From 53bd3a1c30da076d254fc2570c1b5dd46591037a Mon Sep 17 00:00:00 2001 From: Michael Manis Date: Mon, 18 Jun 2018 19:49:12 -0400 Subject: [PATCH 0001/5608] Add some default LengthLimit to OsuTextBox --- osu.Game/Graphics/UserInterface/OsuTextBox.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index 6021af2028..17a1be8879 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -32,6 +32,7 @@ namespace osu.Game.Graphics.UserInterface Height = 40; TextContainer.Height = 0.5f; CornerRadius = 5; + LengthLimit = 1000; Current.DisabledChanged += disabled => { From ffe82aad25659c6f113ac9db685bcca581b815ab Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 10 Jul 2018 21:57:09 +0200 Subject: [PATCH 0002/5608] Add basic quick exit functionality --- .../Input/Bindings/GlobalActionContainer.cs | 3 ++ osu.Game/Screens/Play/Player.cs | 13 +++++++++ osu.Game/Screens/Play/QuickExit.cs | 28 +++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 osu.Game/Screens/Play/QuickExit.cs diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index b21deff509..f4419cc6d0 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -49,6 +49,7 @@ namespace osu.Game.Input.Bindings { new KeyBinding(InputKey.Space, GlobalAction.SkipCutscene), new KeyBinding(InputKey.Tilde, GlobalAction.QuickRetry), + new KeyBinding(new[] { InputKey.Alt, InputKey.Tilde }, GlobalAction.QuickExit), new KeyBinding(new[] { InputKey.Control, InputKey.Plus }, GlobalAction.IncreaseScrollSpeed), new KeyBinding(new[] { InputKey.Control, InputKey.Minus }, GlobalAction.DecreaseScrollSpeed), }; @@ -83,6 +84,8 @@ namespace osu.Game.Input.Bindings SkipCutscene, [Description("Quick Retry (Hold)")] QuickRetry, + [Description("Quick Exit (Hold)")] + QuickExit, [Description("Take screenshot")] TakeScreenshot, diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index b406bda411..84fcede6b5 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -71,6 +71,7 @@ namespace osu.Game.Screens.Play private APIAccess api; private SampleChannel sampleRestart; + private SampleChannel sampleExit; protected ScoreProcessor ScoreProcessor; protected RulesetContainer RulesetContainer; @@ -93,6 +94,7 @@ namespace osu.Game.Screens.Play return; sampleRestart = audio.Sample.Get(@"Gameplay/restart"); + sampleExit = audio.Sample.Get(@"UI/screen-back"); mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); @@ -224,6 +226,17 @@ namespace osu.Game.Screens.Play RulesetContainer?.Hide(); Restart(); }, + }, + new QuickExit + { + Action = () => + { + if (!IsCurrentScreen) return; + + sampleExit?.Play(); + ValidForResume = false; + Exit(); + } } }; diff --git a/osu.Game/Screens/Play/QuickExit.cs b/osu.Game/Screens/Play/QuickExit.cs new file mode 100644 index 0000000000..611b02c543 --- /dev/null +++ b/osu.Game/Screens/Play/QuickExit.cs @@ -0,0 +1,28 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCEusing System; + +using osu.Framework.Input.Bindings; +using osu.Game.Input.Bindings; +using osu.Game.Overlays; + +namespace osu.Game.Screens.Play +{ + public class QuickExit : HoldToConfirmOverlay, IKeyBindingHandler + { + public bool OnPressed(GlobalAction action) + { + if (action != GlobalAction.QuickExit) return false; + + BeginConfirm(); + return true; + } + + public bool OnReleased(GlobalAction action) + { + if (action != GlobalAction.QuickExit) return false; + + AbortConfirm(); + return true; + } + } +} From 4c6286a3ca1929cbe5c96410ea8121da00f65a40 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 10 Jul 2018 22:16:08 +0200 Subject: [PATCH 0003/5608] Fix license header --- osu.Game/Screens/Play/QuickExit.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/QuickExit.cs b/osu.Game/Screens/Play/QuickExit.cs index 611b02c543..0c3908a44f 100644 --- a/osu.Game/Screens/Play/QuickExit.cs +++ b/osu.Game/Screens/Play/QuickExit.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCEusing System; +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Input.Bindings; using osu.Game.Input.Bindings; From 4cc22387d4a3481972ae35688952a392a1fb79fb Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 11 Jul 2018 12:03:05 +0200 Subject: [PATCH 0004/5608] Avoid interversion key configuration conflicts --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index f4419cc6d0..56d8db72fe 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -84,8 +84,6 @@ namespace osu.Game.Input.Bindings SkipCutscene, [Description("Quick Retry (Hold)")] QuickRetry, - [Description("Quick Exit (Hold)")] - QuickExit, [Description("Take screenshot")] TakeScreenshot, @@ -103,5 +101,8 @@ namespace osu.Game.Input.Bindings [Description("Select")] Select, + + [Description("Quick Exit (Hold)")] + QuickExit, } } From fde9df39389e88368360ce46ad2e651ac459a778 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 11 Jul 2018 14:47:34 +0200 Subject: [PATCH 0005/5608] Same as #3006 + hide gameplay instantly --- osu.Game/Screens/Play/Player.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 84fcede6b5..e0d5fed212 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -235,6 +235,8 @@ namespace osu.Game.Screens.Play sampleExit?.Play(); ValidForResume = false; + RulesetContainer?.Hide(); + pauseContainer?.Hide(); Exit(); } } From 07183c0069691ee0c39af25e3535b6362af121bd Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 15 Jul 2018 00:52:15 +0200 Subject: [PATCH 0006/5608] Hide Content instead of particular overlays --- osu.Game/Screens/Play/Player.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index e0d5fed212..c575824c1c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -235,8 +235,7 @@ namespace osu.Game.Screens.Play sampleExit?.Play(); ValidForResume = false; - RulesetContainer?.Hide(); - pauseContainer?.Hide(); + Content.Hide(); Exit(); } } From be977e25414cbd443f51f079347528d64b83de2d Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Mon, 16 Jul 2018 23:50:22 +0200 Subject: [PATCH 0007/5608] Header1 --- osu.Game.Tests/Visual/TestCaseChangelog.cs | 34 ++++ .../Visual/TestCaseTextBadgePair.cs | 76 +++++++ .../Overlays/Changelog/ChangelogHeader.cs | 190 ++++++++++++++++++ .../Overlays/Changelog/Header/LineBadge.cs | 35 ++++ .../Changelog/Header/TextBadgePair.cs | 113 +++++++++++ .../Changelog/Header/TextBadgePairListing.cs | 58 ++++++ .../Changelog/Header/TextBadgePairRelease.cs | 42 ++++ osu.Game/Overlays/ChangelogOverlay.cs | 87 ++++++++ 8 files changed, 635 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseChangelog.cs create mode 100644 osu.Game.Tests/Visual/TestCaseTextBadgePair.cs create mode 100644 osu.Game/Overlays/Changelog/ChangelogHeader.cs create mode 100644 osu.Game/Overlays/Changelog/Header/LineBadge.cs create mode 100644 osu.Game/Overlays/Changelog/Header/TextBadgePair.cs create mode 100644 osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs create mode 100644 osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs create mode 100644 osu.Game/Overlays/ChangelogOverlay.cs diff --git a/osu.Game.Tests/Visual/TestCaseChangelog.cs b/osu.Game.Tests/Visual/TestCaseChangelog.cs new file mode 100644 index 0000000000..688cf2b075 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseChangelog.cs @@ -0,0 +1,34 @@ +// Copyright(c) 2007-2018 ppy Pty Ltd. +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + + +using NUnit.Framework; +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public class TestCaseChangelog : OsuTestCase + { + private ChangelogOverlay changelog; + + protected override void LoadComplete() + { + base.LoadComplete(); + + Add(changelog = new ChangelogOverlay()); + changelog.ToggleVisibility(); + + //AddStep(@"toggle", changelog.ToggleVisibility); + AddStep(@"toggle text 1", () => changelog.header.ActivateRelease("Release 20180626.1")); + AddStep(@"toggle text 2", () => changelog.header.ActivateRelease("Lazer 2018.713.1")); + AddStep(@"toggle text 3", () => changelog.header.ActivateRelease("Beta 20180626")); + AddStep(@"go to listing", changelog.header.ActivateListing); + } + + public TestCaseChangelog() + { + + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs new file mode 100644 index 0000000000..effce3d471 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs @@ -0,0 +1,76 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Overlays.Changelog.Header; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public class TestCaseTextBadgePair : OsuTestCase + { + private readonly Container container; + private readonly Box bottomLine; + private readonly TextBadgePair textBadgePair; + + public TestCaseTextBadgePair() + { + + Add(container = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new OpenTK.Vector2(300, 40), + Children = new Drawable[] + { + new Box + { + Colour = Color4.Gray, + RelativeSizeAxes = Axes.Both, + }, + bottomLine = new Box // purple line + { + Colour = Color4.Purple, + RelativeSizeAxes = Axes.X, + Height = 3, + Anchor = Anchor.BottomLeft, + Origin = Anchor.CentreLeft, + }, + textBadgePair = new TextBadgePair(Color4.White, "testing") + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + } + }, + }); + + AddStep(@"deactivate", () => textBadgePair.Deactivate()); + AddStep(@"activate", () => textBadgePair.Activate()); + AddStep(@"purple text", () => textBadgePair.SetTextColor(Color4.Purple, 100)); + AddStep(@"white text", () => textBadgePair.SetTextColor(Color4.White, 100)); + AddStep(@"purple badge", () => textBadgePair.SetBadgeColor(Color4.Purple, 100)); + AddStep(@"white badge", () => textBadgePair.SetBadgeColor(Color4.White, 100)); + AddStep(@"hide text", () => textBadgePair.HideText(250)); + AddStep(@"show text", () => textBadgePair.ShowText(250)); + } + + //[BackgroundDependencyLoader] + //private void load(OsuColour colours) + //{ + + //} + + //private enum BreadcrumbTab + //{ + // Click, + // The, + // Circles, + //} + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs new file mode 100644 index 0000000000..c8fff5bd6b --- /dev/null +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -0,0 +1,190 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics.Backgrounds; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.Changelog.Header; +using System; +using System.Collections.Generic; +using System.Text; + +namespace osu.Game.Overlays.Changelog +{ + public class ChangelogHeader : Container + { + private readonly Container coverContainer; + + private Color4 purple = new Color4(191, 4, 255, 255); + private readonly Sprite coverImage; + private readonly Sprite headerBadge; //50x50, margin-right: 20 + private readonly FillFlowContainer headerTextContainer; + private readonly OsuSpriteText title, titleStream; + private readonly TextBadgePairListing listing; + private readonly TextBadgePairRelease releaseStream; + private readonly FillFlowContainer breadcrumbContainer; + + private const float cover_height = 310; + private const float title_height = 50; + private const float icon_size = 50; + private const float icon_margin = 20; + private const float version_height = 40; + + public ChangelogHeader() + { + RelativeSizeAxes = Axes.X; + Height = cover_height + 5; // 5 is for the "badge" that sticks a bit out of the bottom + Masking = true; // is masking necessary? since I see it nearly everywhere + Children = new Drawable[] + { + coverContainer = new Container + { + RelativeSizeAxes = Axes.X, + Height = cover_height, + Children = new Drawable[] + { + coverImage = new Sprite + { + RelativeSizeAxes = Axes.Both, + Size = new OpenTK.Vector2(1), + }, + new Container // cover + { + RelativeSizeAxes = Axes.X, + Height = cover_height, + Children = new Drawable[] + { + new Container // this is the line badge-Changelog-Stream + { + Height = title_height, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Y = -version_height, + Children = new Drawable[] + { + new CircularContainer // a purple circle + { + X = icon_margin, + Masking = true, + BorderColour = purple, + BorderThickness = 3, + MaskingSmoothness = 1, + Size = new OpenTK.Vector2(50), + Children = new Drawable[] + { + headerBadge = new Sprite + { + Size = new OpenTK.Vector2(0.8f), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + }, + new Box // this ensures the purple circle doesn't disappear..? + { + RelativeSizeAxes = Axes.Both, + Size = new OpenTK.Vector2(1), + AlwaysPresent = true, + Colour = Color4.Transparent, + } + } + }, + headerTextContainer = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + X = icon_size + icon_margin * 2, + Children = new Drawable[] + { + title = new OsuSpriteText + { + Text = "Changelog ", + TextSize = 30, + }, + titleStream = new OsuSpriteText + { + Text = "Listing", + TextSize = 30, + Colour = purple, + }, + } + } + } + }, + breadcrumbContainer = new FillFlowContainer // Listing > Lazer 2018.713.1 + { + X = 2 * icon_margin + icon_size - 10, + Height = version_height, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + listing = new TextBadgePairListing(purple), + releaseStream = new TextBadgePairRelease(purple, "Lazer") + }, + }, + new Box // purple line + { + Colour = purple, + RelativeSizeAxes = Axes.X, + Height = 3, + Anchor = Anchor.BottomLeft, + Origin = Anchor.CentreLeft, + }, + } + } + } + } + }; + breadcrumbContainer.OnLoadComplete = d => + { + releaseStream.OnActivation = listing.Deactivate; + listing.OnActivation = releaseStream.Deactivate; + }; + listing.text.OnUpdate = d => + { + listing.lineBadge.ResizeWidthTo(listing.text.DrawWidth); + }; + } + + public void ListingActivation() + { + releaseStream.Deactivate(); + } + + public void ReleaseActivation() + { + listing.Deactivate(); + } + + public void ActivateRelease(string displayText) + { + releaseStream.Activate(displayText); + titleStream.Text = displayText; + } + + public void ActivateListing() + { + listing.Activate(); + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + // should be added to osu-resources? + // headerBadge.Texture = textures.Get(@"https://osu.ppy.sh/images/icons/changelog.svg"); // this is not working + headerBadge.Texture = textures.Get(@"https://i.imgur.com/HQM3Vhp.png"); + coverImage.Texture = textures.Get(@"https://osu.ppy.sh/images/headers/changelog.jpg"); + } + } +} diff --git a/osu.Game/Overlays/Changelog/Header/LineBadge.cs b/osu.Game/Overlays/Changelog/Header/LineBadge.cs new file mode 100644 index 0000000000..c3b4ecc187 --- /dev/null +++ b/osu.Game/Overlays/Changelog/Header/LineBadge.cs @@ -0,0 +1,35 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Overlays.Changelog.Header +{ + public class LineBadge : Circle + { + private const float transition_duration = 100; + private const float uncollapsed_height = 10; + public float UncollapsedHeight => uncollapsed_height; + public float TransitionDuration => transition_duration; + private bool isCollapsed; + public bool IsCollapsed + { + get { return isCollapsed; } + set + { + isCollapsed = value; + this.ResizeHeightTo(value ? 1 : 10, transition_duration); + } + } + + public LineBadge(bool startCollapsed = false) + { + IsCollapsed = startCollapsed; + Anchor = Anchor.BottomCentre; + Origin = Anchor.Centre; + } + } +} diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs new file mode 100644 index 0000000000..01326938eb --- /dev/null +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -0,0 +1,113 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input; +using osu.Game.Overlays.Changelog; +using System; + +namespace osu.Game.Overlays.Changelog.Header +{ + + public class TextBadgePair : ClickableContainer + { + // When in listing, "Listing" is white and doesn't change on mouseover + // when release stream is chosen, "Listing" turns purple, and lighter font + // on mouseover, the badge scales up + // Version name steals "Listing"'s styling + + public SpriteText text; + public LineBadge lineBadge; + + public Action OnActivation; + public Action OnDeactivation; + + public void SetTextColor(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) + { + text.FadeColour(newColour, duration, easing); + } + + public void SetBadgeColor(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) + { + lineBadge.FadeColour(newColour, duration, easing); + } + + public void HideText(double duration = 0, Easing easing = Easing.InOutCubic) + { + lineBadge.IsCollapsed = true; + text.MoveToY(20, duration, easing) + .FadeOut(duration, easing); + } + + public void ShowText(double duration = 0, Easing easing = Easing.InOutCubic) + { + lineBadge.IsCollapsed = false; + text.MoveToY(0, duration, easing) + .FadeIn(duration, easing) + .Finally(d => lineBadge.ResizeWidthTo(text.DrawWidth, 250)); + } + + public void ChangeText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) + { + lineBadge.IsCollapsed = true; + text.MoveToY(20, duration, easing) + .FadeOut(duration, easing) + .Finally(d => + { + lineBadge.ResizeWidthTo(0); + if (!string.IsNullOrEmpty(displayText)) text.Text = displayText; + text.MoveToY(0, duration, easing) + .FadeIn(duration, easing) + .OnComplete(dd => { + lineBadge.ResizeWidthTo(text.DrawWidth); + lineBadge.IsCollapsed = false; + }); + }); + } + + public TextBadgePair(ColourInfo badgeColour, string displayText = "Listing") + { + AutoSizeAxes = Axes.X; + RelativeSizeAxes = Axes.Y; + Children = new Drawable[] + { + text = new SpriteText + { + TextSize = 20, + Text = displayText, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AlwaysPresent = true, + Margin = new MarginPadding() + { + Top = 5, + Bottom = 15, + Left = 10, + Right = 10, + } + }, + lineBadge = new LineBadge + { + Colour = badgeColour, + } + }; + } + + public virtual void Deactivate() + { + lineBadge.IsCollapsed = true; + text.Font = "Exo2.0-Regular"; + } + + public virtual void Activate() + { + lineBadge.IsCollapsed = false; + text.Font = "Exo2.0-Bold"; + } + } +} diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs new file mode 100644 index 0000000000..569f5ff2f5 --- /dev/null +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -0,0 +1,58 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Input; +using System; + +namespace osu.Game.Overlays.Changelog.Header +{ + public class TextBadgePairListing : TextBadgePair + { + private TextBadgePairRelease releaseBadge; + private ColourInfo badgeColour; + + public TextBadgePairListing(ColourInfo badgeColour) : base(badgeColour, "Listing") + { + this.releaseBadge = releaseBadge; + this.badgeColour = badgeColour; + text.Font = "Exo2.0-Bold"; + } + + public override void Activate() + { + lineBadge.IsCollapsed = false; + text.Font = "Exo2.0-Bold"; + SetTextColor(Color4.White, 100); + OnActivation?.Invoke(); + } + + public override void Deactivate() + { + lineBadge.IsCollapsed = true; + //text.Font = "Exo2.0-Regular"; // commented out since it makes bad resize-jumping + SetTextColor(badgeColour, 100); + OnDeactivation?.Invoke(); + } + + protected override bool OnClick(InputState state) + { + Activate(); + return base.OnClick(state); + } + + protected override bool OnHover(InputState state) + { + lineBadge.ResizeHeightTo(lineBadge.UncollapsedHeight, lineBadge.TransitionDuration); + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + if (lineBadge.IsCollapsed) lineBadge.ResizeHeightTo(1, lineBadge.TransitionDuration); + base.OnHoverLost(state); + } + } +} diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs new file mode 100644 index 0000000000..318e8a4c73 --- /dev/null +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs @@ -0,0 +1,42 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Input; + +namespace osu.Game.Overlays.Changelog.Header +{ + public class TextBadgePairRelease : TextBadgePair + { + private TextBadgePairListing listingBadge; + + public TextBadgePairRelease(ColourInfo badgeColour, string displayText) : base(badgeColour, displayText) + { + this.listingBadge = listingBadge; + text.Font = "Exo2.0-Bold"; + text.Y = 20; + text.Alpha = 0; + } + + public void SetText(string displayText) + { + text.Text = displayText; + } + + public void Activate(string displayText = null) + { + ClearTransforms(); + if (text.IsPresent) ChangeText(250, displayText); + else ShowText(); + OnActivation?.Invoke(); + } + + public override void Deactivate() + { + FinishTransforms(true); + HideText(250); + OnDeactivation?.Invoke(); + } + } +} diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs new file mode 100644 index 0000000000..f6a138e603 --- /dev/null +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -0,0 +1,87 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.Changelog; +using System; +using System.Collections.Generic; +using System.Text; + +namespace osu.Game.Overlays +{ + public class ChangelogOverlay : WaveOverlayContainer + { + private readonly ScrollContainer scroll; + + public ChangelogHeader header; + + public ChangelogOverlay() + { + Waves.FirstWaveColour = OsuColour.Gray(0.4f); + Waves.SecondWaveColour = OsuColour.Gray(0.3f); + Waves.ThirdWaveColour = OsuColour.Gray(0.2f); + Waves.FourthWaveColour = OsuColour.Gray(0.1f); + + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; + RelativeSizeAxes = Axes.Both; + Width = 0.85f; + + Masking = true; + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0), + Type = EdgeEffectType.Shadow, + Radius = 3, + Offset = new Vector2(0f, 1f), + }; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new Color4(20, 18, 23, 255) + }, + scroll = new ScrollContainer + { + RelativeSizeAxes = Axes.Both, + ScrollbarVisible = false, + Child = new ReverseChildIDFillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + header = new ChangelogHeader(), + }, + }, + }, + }; + } + + // receive input outside our bounds so we can trigger a close event on ourselves. + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; + + protected override void PopIn() + { + base.PopIn(); + FadeEdgeEffectTo(0.25f, WaveContainer.APPEAR_DURATION, Easing.In); + } + + protected override void PopOut() + { + base.PopOut(); + FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); + } + } +} From b4bb97fba89a577af78f38302e9d7f5925f6e820 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 17 Jul 2018 15:01:53 +0200 Subject: [PATCH 0008/5608] Header2 --- osu.Game.Tests/Visual/TestCaseChangelog.cs | 12 ++- .../Visual/TestCaseTextBadgePair.cs | 8 +- .../Input/Bindings/GlobalActionContainer.cs | 2 + osu.Game/OsuGame.cs | 11 ++- .../Overlays/Changelog/ChangelogHeader.cs | 81 +++++++++++-------- .../Overlays/Changelog/Header/LineBadge.cs | 5 ++ .../Changelog/Header/TextBadgePair.cs | 61 ++++++++------ .../Changelog/Header/TextBadgePairListing.cs | 14 ++-- .../Changelog/Header/TextBadgePairRelease.cs | 7 +- .../Toolbar/ToolbarChangelogButton.cs | 22 +++++ 10 files changed, 146 insertions(+), 77 deletions(-) create mode 100644 osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs diff --git a/osu.Game.Tests/Visual/TestCaseChangelog.cs b/osu.Game.Tests/Visual/TestCaseChangelog.cs index 688cf2b075..28c43b5153 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelog.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelog.cs @@ -17,13 +17,11 @@ namespace osu.Game.Tests.Visual base.LoadComplete(); Add(changelog = new ChangelogOverlay()); - changelog.ToggleVisibility(); - - //AddStep(@"toggle", changelog.ToggleVisibility); - AddStep(@"toggle text 1", () => changelog.header.ActivateRelease("Release 20180626.1")); - AddStep(@"toggle text 2", () => changelog.header.ActivateRelease("Lazer 2018.713.1")); - AddStep(@"toggle text 3", () => changelog.header.ActivateRelease("Beta 20180626")); - AddStep(@"go to listing", changelog.header.ActivateListing); + + AddStep(@"Show", changelog.Show); + AddStep(@"Stable Release Stream", () => changelog.header.ShowReleaseStream("Stable", "Stable 20180626.1")); + AddStep(@"Lazer Release Stream", () => changelog.header.ShowReleaseStream("Lazer", "Lazer 2018.713.1")); + AddStep(@"Listing", changelog.header.ActivateListing); } public TestCaseChangelog() diff --git a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs index effce3d471..659bcb26ef 100644 --- a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs +++ b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs @@ -52,10 +52,10 @@ namespace osu.Game.Tests.Visual AddStep(@"deactivate", () => textBadgePair.Deactivate()); AddStep(@"activate", () => textBadgePair.Activate()); - AddStep(@"purple text", () => textBadgePair.SetTextColor(Color4.Purple, 100)); - AddStep(@"white text", () => textBadgePair.SetTextColor(Color4.White, 100)); - AddStep(@"purple badge", () => textBadgePair.SetBadgeColor(Color4.Purple, 100)); - AddStep(@"white badge", () => textBadgePair.SetBadgeColor(Color4.White, 100)); + AddStep(@"purple text", () => textBadgePair.SetTextColour(Color4.Purple, 100)); + AddStep(@"white text", () => textBadgePair.SetTextColour(Color4.White, 100)); + AddStep(@"purple badge", () => textBadgePair.SetBadgeColour(Color4.Purple, 100)); + AddStep(@"white badge", () => textBadgePair.SetBadgeColour(Color4.White, 100)); AddStep(@"hide text", () => textBadgePair.HideText(250)); AddStep(@"show text", () => textBadgePair.ShowText(250)); } diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index b21deff509..00857b9c9b 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -63,6 +63,8 @@ namespace osu.Game.Input.Bindings ToggleChat, [Description("Toggle social overlay")] ToggleSocial, + [Description("Toggle changelog")] + ToggleChangelog, [Description("Reset input settings")] ResetInputSettings, [Description("Toggle toolbar")] diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 557b6e4469..3eb4faf6aa 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -53,6 +53,8 @@ namespace osu.Game private DialogOverlay dialogOverlay; + private ChangelogOverlay changelog; + private DirectOverlay direct; private SocialOverlay social; @@ -110,6 +112,8 @@ namespace osu.Game public void ToggleDirect() => direct.ToggleVisibility(); + public void ToggleChangelog() => changelog.ToggleVisibility(); + /// /// Close all game-wide overlays. /// @@ -281,6 +285,7 @@ namespace osu.Game loadComponentSingleFile(screenshotManager, Add); //overlay elements + loadComponentSingleFile(changelog = new ChangelogOverlay { Depth = -1 }, mainContent.Add); loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, mainContent.Add); loadComponentSingleFile(social = new SocialOverlay { Depth = -1 }, mainContent.Add); loadComponentSingleFile(chat = new ChatOverlay { Depth = -1 }, mainContent.Add); @@ -315,6 +320,7 @@ namespace osu.Game dependencies.Cache(settings); dependencies.Cache(onscreenDisplay); dependencies.Cache(social); + dependencies.Cache(changelog); dependencies.Cache(direct); dependencies.Cache(chat); dependencies.Cache(userProfile); @@ -349,7 +355,7 @@ namespace osu.Game } // ensure only one of these overlays are open at once. - var singleDisplayOverlays = new OverlayContainer[] { chat, social, direct }; + var singleDisplayOverlays = new OverlayContainer[] { chat, social, direct, changelog }; overlays.AddRange(singleDisplayOverlays); foreach (var overlay in singleDisplayOverlays) @@ -459,6 +465,9 @@ namespace osu.Game case GlobalAction.ToggleSocial: social.ToggleVisibility(); return true; + case GlobalAction.ToggleChangelog: + changelog.ToggleVisibility(); + return true; case GlobalAction.ResetInputSettings: var sensitivity = frameworkConfig.GetBindable(FrameworkSetting.CursorSensitivity); diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index c8fff5bd6b..09812f784b 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -10,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Changelog.Header; @@ -55,13 +57,16 @@ namespace osu.Game.Overlays.Changelog { RelativeSizeAxes = Axes.Both, Size = new OpenTK.Vector2(1), + FillMode = FillMode.Fill, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, }, - new Container // cover - { - RelativeSizeAxes = Axes.X, - Height = cover_height, - Children = new Drawable[] - { + //new Container + //{ + // RelativeSizeAxes = Axes.X, + // Height = cover_height, + // Children = new Drawable[] + // { new Container // this is the line badge-Changelog-Stream { Height = title_height, @@ -108,12 +113,14 @@ namespace osu.Game.Overlays.Changelog title = new OsuSpriteText { Text = "Changelog ", - TextSize = 30, + Font = @"Exo2.0-Light", + TextSize = 38, // web: 30 }, titleStream = new OsuSpriteText { Text = "Listing", - TextSize = 30, + TextSize = 38, // web: 30 + Font = @"Exo2.0-Light", Colour = purple, }, } @@ -122,7 +129,7 @@ namespace osu.Game.Overlays.Changelog }, breadcrumbContainer = new FillFlowContainer // Listing > Lazer 2018.713.1 { - X = 2 * icon_margin + icon_size - 10, + X = 2 * icon_margin + icon_size - 8, // for some reason off by 3px Height = version_height, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -130,6 +137,21 @@ namespace osu.Game.Overlays.Changelog Children = new Drawable[] { listing = new TextBadgePairListing(purple), + new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(7), + Colour = OsuColour.FromHex(@"bf04ff"), + Icon = FontAwesome.fa_chevron_right, + Margin = new MarginPadding() + { + Top = 8, + Left = 5, + Right = 5, + Bottom = 15, + }, + }, releaseStream = new TextBadgePairRelease(purple, "Lazer") }, }, @@ -141,42 +163,37 @@ namespace osu.Game.Overlays.Changelog Anchor = Anchor.BottomLeft, Origin = Anchor.CentreLeft, }, - } - } + // } + //} } } }; - breadcrumbContainer.OnLoadComplete = d => + + // is this a bad way to do this? + OnLoadComplete = d => { releaseStream.OnActivation = listing.Deactivate; - listing.OnActivation = releaseStream.Deactivate; - }; - listing.text.OnUpdate = d => - { - listing.lineBadge.ResizeWidthTo(listing.text.DrawWidth); + listing.OnActivation = () => + { + releaseStream.Deactivate(); + ChangeHeaderText("Listing"); + }; }; } - - public void ListingActivation() + + public void ShowReleaseStream(string headerText, string breadcrumbText) { - releaseStream.Deactivate(); + releaseStream.Activate(breadcrumbText); + ChangeHeaderText(headerText); } - public void ReleaseActivation() + private void ChangeHeaderText(string headerText) { - listing.Deactivate(); + titleStream.Text = headerText; + titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); } - public void ActivateRelease(string displayText) - { - releaseStream.Activate(displayText); - titleStream.Text = displayText; - } - - public void ActivateListing() - { - listing.Activate(); - } + public void ActivateListing() => listing.Activate(); [BackgroundDependencyLoader] private void load(TextureStore textures) diff --git a/osu.Game/Overlays/Changelog/Header/LineBadge.cs b/osu.Game/Overlays/Changelog/Header/LineBadge.cs index c3b4ecc187..f321939a96 100644 --- a/osu.Game/Overlays/Changelog/Header/LineBadge.cs +++ b/osu.Game/Overlays/Changelog/Header/LineBadge.cs @@ -30,6 +30,11 @@ namespace osu.Game.Overlays.Changelog.Header IsCollapsed = startCollapsed; Anchor = Anchor.BottomCentre; Origin = Anchor.Centre; + Margin = new MarginPadding() + { + Left = 10, + Right = 10, + }; } } } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index 01326938eb..5d1018e504 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -8,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; +using osu.Game.Graphics; using osu.Game.Overlays.Changelog; using System; @@ -16,23 +18,18 @@ namespace osu.Game.Overlays.Changelog.Header public class TextBadgePair : ClickableContainer { - // When in listing, "Listing" is white and doesn't change on mouseover - // when release stream is chosen, "Listing" turns purple, and lighter font - // on mouseover, the badge scales up - // Version name steals "Listing"'s styling - - public SpriteText text; - public LineBadge lineBadge; + protected SpriteText text; + protected LineBadge lineBadge; public Action OnActivation; public Action OnDeactivation; - public void SetTextColor(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) + public void SetTextColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) { text.FadeColour(newColour, duration, easing); } - public void SetBadgeColor(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) + public void SetBadgeColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) { lineBadge.FadeColour(newColour, duration, easing); } @@ -44,30 +41,42 @@ namespace osu.Game.Overlays.Changelog.Header .FadeOut(duration, easing); } - public void ShowText(double duration = 0, Easing easing = Easing.InOutCubic) + public void ShowText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) { - lineBadge.IsCollapsed = false; + if (!string.IsNullOrEmpty(displayText)) text.Text = displayText; text.MoveToY(0, duration, easing) .FadeIn(duration, easing) - .Finally(d => lineBadge.ResizeWidthTo(text.DrawWidth, 250)); + .Finally(d => { + // waiting until text is drawn to use its DrawWidth + UpdateBadgeWidth(); + lineBadge.IsCollapsed = false; + }); } + /// + /// The duration of popping in and popping out not combined. + /// Full change takes double this time. public void ChangeText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) { lineBadge.IsCollapsed = true; text.MoveToY(20, duration, easing) .FadeOut(duration, easing) - .Finally(d => - { - lineBadge.ResizeWidthTo(0); - if (!string.IsNullOrEmpty(displayText)) text.Text = displayText; - text.MoveToY(0, duration, easing) - .FadeIn(duration, easing) - .OnComplete(dd => { - lineBadge.ResizeWidthTo(text.DrawWidth); - lineBadge.IsCollapsed = false; - }); + .Then() + .MoveToY(0, duration, easing) + .FadeIn(duration, easing) + .OnComplete(dd => { + UpdateBadgeWidth(); + lineBadge.IsCollapsed = false; }); + + // since using .finally/.oncomplete after first fadeout made the badge + // not hide sometimes in visual tests(because FinishTransforms()/CancelTransforms() + // didn't apply to transforms that come after the .finally), I'm using a scheduler here + Scheduler.AddDelayed(() => + { + lineBadge.ResizeWidthTo(0); // resizes when not visible + if (!string.IsNullOrEmpty(displayText)) text.Text = displayText; + }, duration); } public TextBadgePair(ColourInfo badgeColour, string displayText = "Listing") @@ -78,10 +87,10 @@ namespace osu.Game.Overlays.Changelog.Header { text = new SpriteText { - TextSize = 20, + TextSize = 21, // web is 16, but here it looks too small? Text = displayText, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, AlwaysPresent = true, Margin = new MarginPadding() { @@ -109,5 +118,7 @@ namespace osu.Game.Overlays.Changelog.Header lineBadge.IsCollapsed = false; text.Font = "Exo2.0-Bold"; } + + public void UpdateBadgeWidth() => lineBadge.ResizeWidthTo(text.DrawWidth); } } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs index 569f5ff2f5..f89ed8362e 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -11,29 +11,33 @@ namespace osu.Game.Overlays.Changelog.Header { public class TextBadgePairListing : TextBadgePair { - private TextBadgePairRelease releaseBadge; private ColourInfo badgeColour; public TextBadgePairListing(ColourInfo badgeColour) : base(badgeColour, "Listing") { - this.releaseBadge = releaseBadge; this.badgeColour = badgeColour; text.Font = "Exo2.0-Bold"; + text.Anchor = Anchor.TopCentre; + text.Origin = Anchor.TopCentre; + + // this doesn't work without the scheduler + // (because the text isn't yet fully drawn when it's loaded?) + text.OnLoadComplete = d => Scheduler.Add(UpdateBadgeWidth); } public override void Activate() { lineBadge.IsCollapsed = false; text.Font = "Exo2.0-Bold"; - SetTextColor(Color4.White, 100); + SetTextColour(Color4.White, 100); OnActivation?.Invoke(); } public override void Deactivate() { lineBadge.IsCollapsed = true; - //text.Font = "Exo2.0-Regular"; // commented out since it makes bad resize-jumping - SetTextColor(badgeColour, 100); + text.Font = "Exo2.0-Regular"; // commented out since it makes bad resize-jumping + SetTextColour(badgeColour, 100); OnDeactivation?.Invoke(); } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs index 318e8a4c73..71e3b251c2 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs @@ -10,6 +10,7 @@ namespace osu.Game.Overlays.Changelog.Header public class TextBadgePairRelease : TextBadgePair { private TextBadgePairListing listingBadge; + private const float transition_duration = 125; public TextBadgePairRelease(ColourInfo badgeColour, string displayText) : base(badgeColour, displayText) { @@ -27,15 +28,15 @@ namespace osu.Game.Overlays.Changelog.Header public void Activate(string displayText = null) { ClearTransforms(); - if (text.IsPresent) ChangeText(250, displayText); - else ShowText(); + if (!lineBadge.IsCollapsed) ChangeText(transition_duration, displayText); + else ShowText(transition_duration, displayText); OnActivation?.Invoke(); } public override void Deactivate() { FinishTransforms(true); - HideText(250); + HideText(transition_duration); OnDeactivation?.Invoke(); } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs new file mode 100644 index 0000000000..db4fd4ba07 --- /dev/null +++ b/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs @@ -0,0 +1,22 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Game.Graphics; + +namespace osu.Game.Overlays.Toolbar +{ + public class ToolbarChangelogButton : ToolbarOverlayToggleButton + { + public ToolbarChangelogButton() + { + SetIcon(FontAwesome.fa_list); + } + + [BackgroundDependencyLoader(true)] + private void load(ChangelogOverlay changelog) + { + StateContainer = changelog; + } + } +} From 3c1e445fdfddd13e64a71dc60739e0af5f3ea1b8 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 17 Jul 2018 18:32:11 +0200 Subject: [PATCH 0009/5608] Header3 --- .../Visual/TestCaseTextBadgePair.cs | 16 +- .../Overlays/Changelog/ChangelogHeader.cs | 197 +++++++++--------- .../Overlays/Changelog/Header/LineBadge.cs | 14 +- .../Changelog/Header/TextBadgePair.cs | 15 +- .../Changelog/Header/TextBadgePairListing.cs | 1 - .../Changelog/Header/TextBadgePairRelease.cs | 10 +- osu.Game/Overlays/ChangelogOverlay.cs | 17 +- 7 files changed, 129 insertions(+), 141 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs index 659bcb26ef..9a4e481ff8 100644 --- a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs +++ b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs @@ -3,11 +3,9 @@ using NUnit.Framework; using OpenTK.Graphics; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; using osu.Game.Overlays.Changelog.Header; namespace osu.Game.Tests.Visual @@ -58,19 +56,7 @@ namespace osu.Game.Tests.Visual AddStep(@"white badge", () => textBadgePair.SetBadgeColour(Color4.White, 100)); AddStep(@"hide text", () => textBadgePair.HideText(250)); AddStep(@"show text", () => textBadgePair.ShowText(250)); + AddStep(@"change text", () => textBadgePair.ChangeText(250)); } - - //[BackgroundDependencyLoader] - //private void load(OsuColour colours) - //{ - - //} - - //private enum BreadcrumbTab - //{ - // Click, - // The, - // Circles, - //} } } diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 09812f784b..cc07ffeb18 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -4,20 +4,14 @@ using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; -using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Changelog.Header; -using System; -using System.Collections.Generic; -using System.Text; namespace osu.Game.Overlays.Changelog { @@ -25,11 +19,12 @@ namespace osu.Game.Overlays.Changelog { private readonly Container coverContainer; - private Color4 purple = new Color4(191, 4, 255, 255); + protected Color4 purple = new Color4(191, 4, 255, 255); private readonly Sprite coverImage; private readonly Sprite headerBadge; //50x50, margin-right: 20 private readonly FillFlowContainer headerTextContainer; private readonly OsuSpriteText title, titleStream; + private readonly SpriteIcon chevron; private readonly TextBadgePairListing listing; private readonly TextBadgePairRelease releaseStream; private readonly FillFlowContainer breadcrumbContainer; @@ -61,110 +56,117 @@ namespace osu.Game.Overlays.Changelog Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - //new Container - //{ - // RelativeSizeAxes = Axes.X, - // Height = cover_height, - // Children = new Drawable[] - // { - new Container // this is the line badge-Changelog-Stream + new Container // this is the line badge-Changelog-Stream + { + Height = title_height, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Y = -version_height, + Children = new Drawable[] + { + new CircularContainer // a purple circle { - Height = title_height, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Y = -version_height, + X = icon_margin, + Masking = true, + BorderColour = purple, + BorderThickness = 3, + MaskingSmoothness = 1, + Size = new OpenTK.Vector2(50), Children = new Drawable[] { - new CircularContainer // a purple circle + headerBadge = new Sprite { - X = icon_margin, - Masking = true, - BorderColour = purple, - BorderThickness = 3, - MaskingSmoothness = 1, - Size = new OpenTK.Vector2(50), - Children = new Drawable[] - { - headerBadge = new Sprite - { - Size = new OpenTK.Vector2(0.8f), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - }, - new Box // this ensures the purple circle doesn't disappear..? - { - RelativeSizeAxes = Axes.Both, - Size = new OpenTK.Vector2(1), - AlwaysPresent = true, - Colour = Color4.Transparent, - } - } + RelativeSizeAxes = Axes.Both, + Size = new OpenTK.Vector2(0.8f), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, }, - headerTextContainer = new FillFlowContainer + + // this box has 2 functions: + // - ensures the circle doesn't disappear on the X and Y edges + // - lessens the white "contamination" on the circle (due to smoothing) + new Box { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - X = icon_size + icon_margin * 2, - Children = new Drawable[] - { - title = new OsuSpriteText - { - Text = "Changelog ", - Font = @"Exo2.0-Light", - TextSize = 38, // web: 30 - }, - titleStream = new OsuSpriteText - { - Text = "Listing", - TextSize = 38, // web: 30 - Font = @"Exo2.0-Light", - Colour = purple, - }, - } + RelativeSizeAxes = Axes.Both, + Size = new OpenTK.Vector2(1), + Alpha = 0, + AlwaysPresent = true, + Colour = purple, } } }, - breadcrumbContainer = new FillFlowContainer // Listing > Lazer 2018.713.1 + headerTextContainer = new FillFlowContainer { - X = 2 * icon_margin + icon_size - 8, // for some reason off by 3px - Height = version_height, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + X = icon_size + icon_margin * 2, Children = new Drawable[] { - listing = new TextBadgePairListing(purple), - new SpriteIcon + title = new OsuSpriteText { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(7), - Colour = OsuColour.FromHex(@"bf04ff"), - Icon = FontAwesome.fa_chevron_right, - Margin = new MarginPadding() - { - Top = 8, - Left = 5, - Right = 5, - Bottom = 15, - }, + Text = "Changelog ", + Font = @"Exo2.0-Light", + TextSize = 38, // web: 30 + }, + titleStream = new OsuSpriteText + { + Text = "Listing", + TextSize = 38, // web: 30 + Font = @"Exo2.0-Light", + Colour = purple, + }, + } + } + } + }, + breadcrumbContainer = new FillFlowContainer // Listing > Lazer 2018.713.1 + { + X = 2 * icon_margin + icon_size - 8, + Height = version_height, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + listing = new TextBadgePairListing(purple), + new Container() // without a container, moving the chevron wont work + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding() + { + Top = 10, + Left = 7, + Right = 9, + Bottom = 15, + }, + Children = new Drawable[] + { + chevron = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(7), + Colour = purple, + Icon = FontAwesome.fa_chevron_right, + Alpha = 0, + X = -200, }, - releaseStream = new TextBadgePairRelease(purple, "Lazer") }, }, - new Box // purple line - { - Colour = purple, - RelativeSizeAxes = Axes.X, - Height = 3, - Anchor = Anchor.BottomLeft, - Origin = Anchor.CentreLeft, - }, - // } - //} + releaseStream = new TextBadgePairRelease(purple, "Lazer") + }, + }, + new Box // purple line + { + Colour = purple, + RelativeSizeAxes = Axes.X, + Height = 3, + Anchor = Anchor.BottomLeft, + Origin = Anchor.CentreLeft, + }, } } }; @@ -172,10 +174,15 @@ namespace osu.Game.Overlays.Changelog // is this a bad way to do this? OnLoadComplete = d => { - releaseStream.OnActivation = listing.Deactivate; + releaseStream.OnActivation = () => + { + listing.Deactivate(); + chevron.MoveToX(0, 100).FadeIn(100); + }; listing.OnActivation = () => { releaseStream.Deactivate(); + chevron.MoveToX(-20, 100).FadeOut(100); ChangeHeaderText("Listing"); }; }; diff --git a/osu.Game/Overlays/Changelog/Header/LineBadge.cs b/osu.Game/Overlays/Changelog/Header/LineBadge.cs index f321939a96..0846821c5c 100644 --- a/osu.Game/Overlays/Changelog/Header/LineBadge.cs +++ b/osu.Game/Overlays/Changelog/Header/LineBadge.cs @@ -3,8 +3,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; -using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Changelog.Header { @@ -12,24 +10,26 @@ namespace osu.Game.Overlays.Changelog.Header { private const float transition_duration = 100; private const float uncollapsed_height = 10; - public float UncollapsedHeight => uncollapsed_height; + public float TransitionDuration => transition_duration; - private bool isCollapsed; + public float UncollapsedHeight => uncollapsed_height; + protected bool isCollapsed; public bool IsCollapsed { get { return isCollapsed; } set { isCollapsed = value; - this.ResizeHeightTo(value ? 1 : 10, transition_duration); + this.ResizeHeightTo(value ? 1 : uncollapsed_height, transition_duration); } } - public LineBadge(bool startCollapsed = false) + public LineBadge() { - IsCollapsed = startCollapsed; Anchor = Anchor.BottomCentre; Origin = Anchor.Centre; + + // this margin prevents jumps when changing text's font weight Margin = new MarginPadding() { Left = 10, diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index 5d1018e504..24ce873a95 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -1,16 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input; -using osu.Game.Graphics; -using osu.Game.Overlays.Changelog; using System; namespace osu.Game.Overlays.Changelog.Header @@ -43,7 +37,11 @@ namespace osu.Game.Overlays.Changelog.Header public void ShowText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) { - if (!string.IsNullOrEmpty(displayText)) text.Text = displayText; + if (!string.IsNullOrEmpty(displayText)) + { + text.Text = displayText; + } + text.MoveToY(0, duration, easing) .FadeIn(duration, easing) .Finally(d => { @@ -74,7 +72,7 @@ namespace osu.Game.Overlays.Changelog.Header // didn't apply to transforms that come after the .finally), I'm using a scheduler here Scheduler.AddDelayed(() => { - lineBadge.ResizeWidthTo(0); // resizes when not visible + //lineBadge.ResizeWidthTo(0); // resizes when not visible if (!string.IsNullOrEmpty(displayText)) text.Text = displayText; }, duration); } @@ -91,7 +89,6 @@ namespace osu.Game.Overlays.Changelog.Header Text = displayText, Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, - AlwaysPresent = true, Margin = new MarginPadding() { Top = 5, diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs index f89ed8362e..4897aeedd1 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -5,7 +5,6 @@ using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Input; -using System; namespace osu.Game.Overlays.Changelog.Header { diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs index 71e3b251c2..f69c7dd6a7 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs @@ -1,9 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; -using osu.Framework.Input; namespace osu.Game.Overlays.Changelog.Header { @@ -27,15 +25,17 @@ namespace osu.Game.Overlays.Changelog.Header public void Activate(string displayText = null) { - ClearTransforms(); - if (!lineBadge.IsCollapsed) ChangeText(transition_duration, displayText); + //ClearTransforms(); + // not using if (!lineBadge.IsCollapsed) because the text sometimes gets reset + // when quickly switching release streams + if (text.IsPresent) ChangeText(transition_duration, displayText); else ShowText(transition_duration, displayText); OnActivation?.Invoke(); } public override void Deactivate() { - FinishTransforms(true); + //FinishTransforms(true); HideText(transition_duration); OnDeactivation?.Invoke(); } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index f6a138e603..915d747f00 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -9,11 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Changelog; -using System; -using System.Collections.Generic; -using System.Text; namespace osu.Game.Overlays { @@ -23,19 +19,22 @@ namespace osu.Game.Overlays public ChangelogHeader header; + protected Color4 purple = new Color4(191, 4, 255, 255); + public ChangelogOverlay() { - Waves.FirstWaveColour = OsuColour.Gray(0.4f); - Waves.SecondWaveColour = OsuColour.Gray(0.3f); - Waves.ThirdWaveColour = OsuColour.Gray(0.2f); - Waves.FourthWaveColour = OsuColour.Gray(0.1f); + // these possibly need adjusting? + Waves.FirstWaveColour = OsuColour.FromHex(@"bf04ff"); + Waves.SecondWaveColour = OsuColour.FromHex(@"8F03BF"); + Waves.ThirdWaveColour = OsuColour.FromHex(@"600280"); + Waves.FourthWaveColour = OsuColour.FromHex(@"300140"); Anchor = Anchor.TopCentre; Origin = Anchor.TopCentre; RelativeSizeAxes = Axes.Both; Width = 0.85f; - Masking = true; + EdgeEffect = new EdgeEffectParameters { Colour = Color4.Black.Opacity(0), From 523d47e8154e573cf7873ec0650dd7bcde0db379 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 18 Jul 2018 01:35:06 +0200 Subject: [PATCH 0010/5608] Streams1 --- osu.Game.Tests/Visual/TestCaseChangelog.cs | 12 +- osu.Game/Graphics/StreamColour.cs | 17 ++ .../Overlays/Changelog/ChangelogHeader.cs | 217 +++++++++--------- .../Overlays/Changelog/ChangelogStreams.cs | 81 +++++++ .../Overlays/Changelog/Header/LineBadge.cs | 14 +- .../Changelog/Header/TextBadgePair.cs | 7 +- .../Changelog/Header/TextBadgePairListing.cs | 2 +- .../Overlays/Changelog/ReleaseStreamInfo.cs | 25 ++ .../Overlays/Changelog/Streams/StreamBadge.cs | 128 +++++++++++ osu.Game/Overlays/ChangelogOverlay.cs | 20 +- 10 files changed, 397 insertions(+), 126 deletions(-) create mode 100644 osu.Game/Graphics/StreamColour.cs create mode 100644 osu.Game/Overlays/Changelog/ChangelogStreams.cs create mode 100644 osu.Game/Overlays/Changelog/ReleaseStreamInfo.cs create mode 100644 osu.Game/Overlays/Changelog/Streams/StreamBadge.cs diff --git a/osu.Game.Tests/Visual/TestCaseChangelog.cs b/osu.Game.Tests/Visual/TestCaseChangelog.cs index 28c43b5153..c9b8a4d652 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelog.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelog.cs @@ -11,16 +11,22 @@ namespace osu.Game.Tests.Visual public class TestCaseChangelog : OsuTestCase { private ChangelogOverlay changelog; + private int releaseStreamCount; + private int index; protected override void LoadComplete() { base.LoadComplete(); Add(changelog = new ChangelogOverlay()); - + + releaseStreamCount = changelog.streams.badgesContainer.Children.Count; + AddStep(@"Show", changelog.Show); - AddStep(@"Stable Release Stream", () => changelog.header.ShowReleaseStream("Stable", "Stable 20180626.1")); - AddStep(@"Lazer Release Stream", () => changelog.header.ShowReleaseStream("Lazer", "Lazer 2018.713.1")); + AddRepeatStep(@"Toggle Release Stream", () => { + changelog.streams.badgesContainer.Children[index].Activate(); + index = (index == releaseStreamCount - 1) ? 0 : index + 1; + }, releaseStreamCount); AddStep(@"Listing", changelog.header.ActivateListing); } diff --git a/osu.Game/Graphics/StreamColour.cs b/osu.Game/Graphics/StreamColour.cs new file mode 100644 index 0000000000..fbb272c526 --- /dev/null +++ b/osu.Game/Graphics/StreamColour.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; + +namespace osu.Game.Graphics +{ + public class StreamColour + { + public readonly Color4 Stable = new Color4(102, 204, 255, 255); + public readonly Color4 StableFallback = new Color4(34, 153, 187, 255); + public readonly Color4 Beta = new Color4(255, 221, 85, 255); + public readonly Color4 CuttingEdge = new Color4(238, 170, 0, 255); + public readonly Color4 Lazer = new Color4(237, 18, 33, 255); + public readonly Color4 Web = new Color4(136, 102, 238, 255); + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index cc07ffeb18..183a63575b 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -12,13 +12,12 @@ using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Changelog.Header; +using System; namespace osu.Game.Overlays.Changelog { public class ChangelogHeader : Container { - private readonly Container coverContainer; - protected Color4 purple = new Color4(191, 4, 255, 255); private readonly Sprite coverImage; private readonly Sprite headerBadge; //50x50, margin-right: 20 @@ -29,6 +28,8 @@ namespace osu.Game.Overlays.Changelog private readonly TextBadgePairRelease releaseStream; private readonly FillFlowContainer breadcrumbContainer; + public Action OnListingActivated; + private const float cover_height = 310; private const float title_height = 50; private const float icon_size = 50; @@ -38,137 +39,128 @@ namespace osu.Game.Overlays.Changelog public ChangelogHeader() { RelativeSizeAxes = Axes.X; - Height = cover_height + 5; // 5 is for the "badge" that sticks a bit out of the bottom - Masking = true; // is masking necessary? since I see it nearly everywhere + Height = cover_height; Children = new Drawable[] { - coverContainer = new Container + coverImage = new Sprite { - RelativeSizeAxes = Axes.X, - Height = cover_height, + RelativeSizeAxes = Axes.Both, + Size = new OpenTK.Vector2(1), + FillMode = FillMode.Fill, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new Container // this is the line badge-Changelog-Stream + { + Height = title_height, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Y = -version_height, Children = new Drawable[] { - coverImage = new Sprite + new CircularContainer // a purple circle { - RelativeSizeAxes = Axes.Both, - Size = new OpenTK.Vector2(1), - FillMode = FillMode.Fill, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - new Container // this is the line badge-Changelog-Stream - { - Height = title_height, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Y = -version_height, + X = icon_margin, + Masking = true, + BorderColour = purple, + BorderThickness = 3, + MaskingSmoothness = 1, + Size = new OpenTK.Vector2(50), Children = new Drawable[] { - new CircularContainer // a purple circle + headerBadge = new Sprite { - X = icon_margin, - Masking = true, - BorderColour = purple, - BorderThickness = 3, - MaskingSmoothness = 1, - Size = new OpenTK.Vector2(50), - Children = new Drawable[] - { - headerBadge = new Sprite - { - RelativeSizeAxes = Axes.Both, - Size = new OpenTK.Vector2(0.8f), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - - // this box has 2 functions: - // - ensures the circle doesn't disappear on the X and Y edges - // - lessens the white "contamination" on the circle (due to smoothing) - new Box - { - RelativeSizeAxes = Axes.Both, - Size = new OpenTK.Vector2(1), - Alpha = 0, - AlwaysPresent = true, - Colour = purple, - } - } + RelativeSizeAxes = Axes.Both, + Size = new OpenTK.Vector2(0.8f), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, }, - headerTextContainer = new FillFlowContainer + + // this box has 2 functions: + // - ensures the circle doesn't disappear on the X and Y edges + // - lessens the white "contamination" on the circle (due to smoothing) + new Box { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - X = icon_size + icon_margin * 2, - Children = new Drawable[] - { - title = new OsuSpriteText - { - Text = "Changelog ", - Font = @"Exo2.0-Light", - TextSize = 38, // web: 30 - }, - titleStream = new OsuSpriteText - { - Text = "Listing", - TextSize = 38, // web: 30 - Font = @"Exo2.0-Light", - Colour = purple, - }, - } + RelativeSizeAxes = Axes.Both, + Size = new OpenTK.Vector2(1), + Alpha = 0, + AlwaysPresent = true, + Colour = purple, } } }, - breadcrumbContainer = new FillFlowContainer // Listing > Lazer 2018.713.1 + headerTextContainer = new FillFlowContainer { - X = 2 * icon_margin + icon_size - 8, - Height = version_height, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + X = icon_size + icon_margin * 2, Children = new Drawable[] { - listing = new TextBadgePairListing(purple), - new Container() // without a container, moving the chevron wont work + title = new OsuSpriteText { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Margin = new MarginPadding() - { - Top = 10, - Left = 7, - Right = 9, - Bottom = 15, - }, - Children = new Drawable[] - { - chevron = new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(7), - Colour = purple, - Icon = FontAwesome.fa_chevron_right, - Alpha = 0, - X = -200, - }, - }, + Text = "Changelog ", + Font = @"Exo2.0-Light", + TextSize = 38, // web: 30 + }, + titleStream = new OsuSpriteText + { + Text = "Listing", + TextSize = 38, // web: 30 + Font = @"Exo2.0-Light", + Colour = purple, + }, + } + } + } + }, + breadcrumbContainer = new FillFlowContainer // Listing > Lazer 2018.713.1 + { + X = 2 * icon_margin + icon_size - 8, + Height = version_height, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + listing = new TextBadgePairListing(purple), + new Container() // without a container, moving the chevron wont work + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding() + { + Top = 10, + Left = 7, + Right = 9, + Bottom = 15, + }, + Children = new Drawable[] + { + chevron = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(7), + Colour = purple, + Icon = FontAwesome.fa_chevron_right, + Alpha = 0, + X = -200, }, - releaseStream = new TextBadgePairRelease(purple, "Lazer") }, }, - new Box // purple line - { - Colour = purple, - RelativeSizeAxes = Axes.X, - Height = 3, - Anchor = Anchor.BottomLeft, - Origin = Anchor.CentreLeft, - }, - } - } + releaseStream = new TextBadgePairRelease(purple, "Lazer") + }, + }, + new Box // purple line + { + Colour = purple, + RelativeSizeAxes = Axes.X, + Height = 3, + Anchor = Anchor.BottomLeft, + Origin = Anchor.CentreLeft, + }, }; // is this a bad way to do this? @@ -184,6 +176,7 @@ namespace osu.Game.Overlays.Changelog releaseStream.Deactivate(); chevron.MoveToX(-20, 100).FadeOut(100); ChangeHeaderText("Listing"); + OnListingActivated?.Invoke(); }; }; } @@ -201,7 +194,7 @@ namespace osu.Game.Overlays.Changelog } public void ActivateListing() => listing.Activate(); - + [BackgroundDependencyLoader] private void load(TextureStore textures) { diff --git a/osu.Game/Overlays/Changelog/ChangelogStreams.cs b/osu.Game/Overlays/Changelog/ChangelogStreams.cs new file mode 100644 index 0000000000..e7f7d44c80 --- /dev/null +++ b/osu.Game/Overlays/Changelog/ChangelogStreams.cs @@ -0,0 +1,81 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Configuration; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Overlays.Changelog.Streams; +using System; + +namespace osu.Game.Overlays.Changelog +{ + public class ChangelogStreams : Container + { + private const float containerHeight = 106.5f; + private const float containerTopBottomMargin = 20; + private const float containerSideMargin = 85; + + public Bindable SelectedRelease = new Bindable(); + + private readonly StreamColour streamColour; + public readonly FillFlowContainer badgesContainer; + + public ChangelogStreams() + { + streamColour = new StreamColour(); + Height = containerHeight; + RelativeSizeAxes = Axes.X; + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Size = new OpenTK.Vector2(1), + Colour = new Color4(32, 24, 35, 255), + }, + badgesContainer = new FillFlowContainer + { + Direction = FillDirection.Horizontal, + RelativeSizeAxes = Axes.Both, + Margin = new MarginPadding() + { + Top = containerTopBottomMargin, + Bottom = containerTopBottomMargin, + Left = containerSideMargin, + Right = containerSideMargin, + }, + Children = new[] + { + new StreamBadge(streamColour.Stable, "Stable", "20180626.1", 16370, true), + new StreamBadge(streamColour.Beta, "Beta", "20180626", 186), + new StreamBadge(streamColour.Lazer, "Lazer", "2018.713.1"), + }, + }, + }; + badgesContainer.OnLoadComplete = d => + { + foreach (StreamBadge streamBadge in badgesContainer.Children) + { + streamBadge.OnActivation = () => + { + SelectedRelease.Value = new ReleaseStreamInfo() + { + DisplayVersion = streamBadge.DisplayVersion, + IsFeatured = streamBadge.IsFeatured, + Name = streamBadge.Name, + Users = streamBadge.Users, + }; + foreach (StreamBadge item in badgesContainer.Children) + { + if (item.Name != streamBadge.Name) item.Deactivate(); + } + }; + } + }; + } + } +} diff --git a/osu.Game/Overlays/Changelog/Header/LineBadge.cs b/osu.Game/Overlays/Changelog/Header/LineBadge.cs index 0846821c5c..c33244d50b 100644 --- a/osu.Game/Overlays/Changelog/Header/LineBadge.cs +++ b/osu.Game/Overlays/Changelog/Header/LineBadge.cs @@ -8,11 +8,10 @@ namespace osu.Game.Overlays.Changelog.Header { public class LineBadge : Circle { - private const float transition_duration = 100; - private const float uncollapsed_height = 10; + public float TransitionDuration = 100; + public float UncollapsedHeight; + public float CollapsedHeight; - public float TransitionDuration => transition_duration; - public float UncollapsedHeight => uncollapsed_height; protected bool isCollapsed; public bool IsCollapsed { @@ -20,14 +19,17 @@ namespace osu.Game.Overlays.Changelog.Header set { isCollapsed = value; - this.ResizeHeightTo(value ? 1 : uncollapsed_height, transition_duration); + this.ResizeHeightTo(value ? CollapsedHeight : UncollapsedHeight, TransitionDuration); } } - public LineBadge() + public LineBadge(bool startCollapsed = true, float collapsedHeight = 1, float uncollapsedHeight = 10) { Anchor = Anchor.BottomCentre; Origin = Anchor.Centre; + CollapsedHeight = collapsedHeight; + UncollapsedHeight = uncollapsedHeight; + Height = startCollapsed ? CollapsedHeight : UncollapsedHeight; // this margin prevents jumps when changing text's font weight Margin = new MarginPadding() diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index 24ce873a95..32910e26c6 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -14,10 +14,11 @@ namespace osu.Game.Overlays.Changelog.Header { protected SpriteText text; protected LineBadge lineBadge; + protected bool startCollapsed; public Action OnActivation; public Action OnDeactivation; - + public void SetTextColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) { text.FadeColour(newColour, duration, easing); @@ -77,7 +78,7 @@ namespace osu.Game.Overlays.Changelog.Header }, duration); } - public TextBadgePair(ColourInfo badgeColour, string displayText = "Listing") + public TextBadgePair(ColourInfo badgeColour, string displayText = "Listing", bool startBadgeCollapsed = true) { AutoSizeAxes = Axes.X; RelativeSizeAxes = Axes.Y; @@ -97,7 +98,7 @@ namespace osu.Game.Overlays.Changelog.Header Right = 10, } }, - lineBadge = new LineBadge + lineBadge = new LineBadge(startCollapsed) { Colour = badgeColour, } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs index 4897aeedd1..41d9a2a8ef 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -12,7 +12,7 @@ namespace osu.Game.Overlays.Changelog.Header { private ColourInfo badgeColour; - public TextBadgePairListing(ColourInfo badgeColour) : base(badgeColour, "Listing") + public TextBadgePairListing(ColourInfo badgeColour) : base(badgeColour, "Listing", false) { this.badgeColour = badgeColour; text.Font = "Exo2.0-Bold"; diff --git a/osu.Game/Overlays/Changelog/ReleaseStreamInfo.cs b/osu.Game/Overlays/Changelog/ReleaseStreamInfo.cs new file mode 100644 index 0000000000..90b2ab6cfb --- /dev/null +++ b/osu.Game/Overlays/Changelog/ReleaseStreamInfo.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using Newtonsoft.Json; +using osu.Game.Database; +using osu.Game.IO.Serialization; +using osu.Game.Rulesets; + +namespace osu.Game.Overlays.Changelog +{ + [Serializable] + public class ReleaseStreamInfo : IJsonSerializable + { + public string Name; + public string DisplayVersion; + + public float Users; + + public bool IsFeatured; + } +} diff --git a/osu.Game/Overlays/Changelog/Streams/StreamBadge.cs b/osu.Game/Overlays/Changelog/Streams/StreamBadge.cs new file mode 100644 index 0000000000..e61fa22007 --- /dev/null +++ b/osu.Game/Overlays/Changelog/Streams/StreamBadge.cs @@ -0,0 +1,128 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input; +using System; + +namespace osu.Game.Overlays.Changelog.Streams +{ + public class StreamBadge : Container + { + private const float badgeHeight = 56.5f; + private const float badgeWidth = 100; + private const float badgeTopBottomMargin = 5; + private const float transition_duration = 100; + + public Action OnActivation; + + private bool isActive; + + private Header.LineBadge lineBadge; + + public string Name { get; private set; } + public string DisplayVersion { get; private set; } + public bool IsFeatured { get; private set; } + public float Users { get; private set; } + + public StreamBadge(ColourInfo colour, string streamName, string streamBuild, float onlineUsers = 0, bool isFeatured = false) + { + Name = streamName; + DisplayVersion = streamBuild; + IsFeatured = isFeatured; + Users = onlineUsers; + Height = badgeHeight; + Width = isFeatured ? badgeWidth * 2 : badgeWidth; + Margin = new MarginPadding(5); + isActive = true; + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new[] + { + new SpriteText + { + Text = streamName, + Font = @"Exo2.0-Bold", + TextSize = 16, + Margin = new MarginPadding + { + Top = 5, + } + }, + new SpriteText + { + Text = streamBuild, + Font = @"Exo2.0-Light", + TextSize = 21, + }, + new SpriteText + { + Text = onlineUsers > 0 ? + string.Join(" ", onlineUsers.ToString("N0"), "users online"): + null, + TextSize = 12, + Font = @"Exo2.0-Regular", + Colour = new Color4(203, 164, 218, 255), + }, + } + }, + lineBadge = new Header.LineBadge(false, 2, 4) + { + Anchor = Anchor.TopCentre, + Width = 1, + Colour = colour, + RelativeSizeAxes = Axes.X, + }, + }; + } + + public void Activate(bool withoutHeaderUpdate = false) + { + isActive = true; + this.FadeIn(transition_duration); + lineBadge.IsCollapsed = false; + if (!withoutHeaderUpdate) OnActivation?.Invoke(); + } + + public void Deactivate() + { + isActive = false; + this.FadeTo(0.5f, transition_duration); + lineBadge.IsCollapsed = true; + } + + protected override bool OnClick(InputState state) + { + Activate(); + return base.OnClick(state); + } + + protected override bool OnHover(InputState state) + { + this.FadeIn(transition_duration); + lineBadge.IsCollapsed = false; + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + if (!isActive) + { + this.FadeTo(0.5f, transition_duration); + lineBadge.IsCollapsed = true; + } + base.OnHoverLost(state); + } + } +} diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 915d747f00..e47e290075 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Overlays.Changelog; +using osu.Game.Overlays.Changelog.Streams; namespace osu.Game.Overlays { @@ -17,7 +18,8 @@ namespace osu.Game.Overlays { private readonly ScrollContainer scroll; - public ChangelogHeader header; + public readonly ChangelogHeader header; + public readonly ChangelogStreams streams; protected Color4 purple = new Color4(191, 4, 255, 255); @@ -62,10 +64,26 @@ namespace osu.Game.Overlays Children = new Drawable[] { header = new ChangelogHeader(), + streams = new ChangelogStreams(), }, }, }, }; + streams.SelectedRelease.ValueChanged += r => + { + if (streams.SelectedRelease != null) + header.ShowReleaseStream(r.Name, string.Join(" ", r.Name, r.DisplayVersion)); + }; + streams.badgesContainer.OnLoadComplete += d => + { + header.OnListingActivated += () => + { + foreach (StreamBadge item in streams.badgesContainer.Children) + { + item.Activate(true); + } + }; + }; } // receive input outside our bounds so we can trigger a close event on ourselves. From 6baa761b9ce852fa5f313b57a7f77dcd49e66aae Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 18 Jul 2018 03:26:08 +0200 Subject: [PATCH 0011/5608] Streams2 --- osu.Game.Tests/Visual/TestCaseChangelog.cs | 3 +- .../Visual/TestCaseTextBadgePair.cs | 62 ------------------- .../Overlays/Changelog/ChangelogStreams.cs | 29 ++++++++- .../Changelog/Header/TextBadgePair.cs | 3 +- .../Overlays/Changelog/Streams/StreamBadge.cs | 5 +- osu.Game/Overlays/ChangelogOverlay.cs | 3 +- 6 files changed, 35 insertions(+), 70 deletions(-) delete mode 100644 osu.Game.Tests/Visual/TestCaseTextBadgePair.cs diff --git a/osu.Game.Tests/Visual/TestCaseChangelog.cs b/osu.Game.Tests/Visual/TestCaseChangelog.cs index c9b8a4d652..afd06d8415 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelog.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelog.cs @@ -1,7 +1,6 @@ -// Copyright(c) 2007-2018 ppy Pty Ltd. +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - using NUnit.Framework; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs deleted file mode 100644 index 9a4e481ff8..0000000000 --- a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using NUnit.Framework; -using OpenTK.Graphics; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Overlays.Changelog.Header; - -namespace osu.Game.Tests.Visual -{ - [TestFixture] - public class TestCaseTextBadgePair : OsuTestCase - { - private readonly Container container; - private readonly Box bottomLine; - private readonly TextBadgePair textBadgePair; - - public TestCaseTextBadgePair() - { - - Add(container = new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new OpenTK.Vector2(300, 40), - Children = new Drawable[] - { - new Box - { - Colour = Color4.Gray, - RelativeSizeAxes = Axes.Both, - }, - bottomLine = new Box // purple line - { - Colour = Color4.Purple, - RelativeSizeAxes = Axes.X, - Height = 3, - Anchor = Anchor.BottomLeft, - Origin = Anchor.CentreLeft, - }, - textBadgePair = new TextBadgePair(Color4.White, "testing") - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - } - }, - }); - - AddStep(@"deactivate", () => textBadgePair.Deactivate()); - AddStep(@"activate", () => textBadgePair.Activate()); - AddStep(@"purple text", () => textBadgePair.SetTextColour(Color4.Purple, 100)); - AddStep(@"white text", () => textBadgePair.SetTextColour(Color4.White, 100)); - AddStep(@"purple badge", () => textBadgePair.SetBadgeColour(Color4.Purple, 100)); - AddStep(@"white badge", () => textBadgePair.SetBadgeColour(Color4.White, 100)); - AddStep(@"hide text", () => textBadgePair.HideText(250)); - AddStep(@"show text", () => textBadgePair.ShowText(250)); - AddStep(@"change text", () => textBadgePair.ChangeText(250)); - } - } -} diff --git a/osu.Game/Overlays/Changelog/ChangelogStreams.cs b/osu.Game/Overlays/Changelog/ChangelogStreams.cs index e7f7d44c80..99c9c0accd 100644 --- a/osu.Game/Overlays/Changelog/ChangelogStreams.cs +++ b/osu.Game/Overlays/Changelog/ChangelogStreams.cs @@ -7,6 +7,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; using osu.Game.Graphics; using osu.Game.Overlays.Changelog.Streams; using System; @@ -23,7 +24,7 @@ namespace osu.Game.Overlays.Changelog private readonly StreamColour streamColour; public readonly FillFlowContainer badgesContainer; - + public ChangelogStreams() { streamColour = new StreamColour(); @@ -77,5 +78,31 @@ namespace osu.Game.Overlays.Changelog } }; } + + protected override bool OnHover(InputState state) + { + // is this nullreference-safe for badgesContainer? + foreach (StreamBadge streamBadge in badgesContainer.Children) + { + if (SelectedRelease.Value != null) + { + if (SelectedRelease.Value.Name != streamBadge.Name) + { + streamBadge.Deactivate(); + } + } + else streamBadge.Deactivate(); + } + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + if (SelectedRelease.Value == null) + { + foreach (StreamBadge streamBadge in badgesContainer.Children) streamBadge.Activate(true); + } + base.OnHoverLost(state); + } } } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index 32910e26c6..42f7bd601a 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -9,7 +9,6 @@ using System; namespace osu.Game.Overlays.Changelog.Header { - public class TextBadgePair : ClickableContainer { protected SpriteText text; @@ -18,7 +17,7 @@ namespace osu.Game.Overlays.Changelog.Header public Action OnActivation; public Action OnDeactivation; - + public void SetTextColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) { text.FadeColour(newColour, duration, easing); diff --git a/osu.Game/Overlays/Changelog/Streams/StreamBadge.cs b/osu.Game/Overlays/Changelog/Streams/StreamBadge.cs index e61fa22007..9b70c9ce7f 100644 --- a/osu.Game/Overlays/Changelog/Streams/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/Streams/StreamBadge.cs @@ -13,7 +13,7 @@ using System; namespace osu.Game.Overlays.Changelog.Streams { - public class StreamBadge : Container + public class StreamBadge : ClickableContainer { private const float badgeHeight = 56.5f; private const float badgeWidth = 100; @@ -57,7 +57,7 @@ namespace osu.Game.Overlays.Changelog.Streams TextSize = 16, Margin = new MarginPadding { - Top = 5, + Top = 7, } }, new SpriteText @@ -80,6 +80,7 @@ namespace osu.Game.Overlays.Changelog.Streams lineBadge = new Header.LineBadge(false, 2, 4) { Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Width = 1, Colour = colour, RelativeSizeAxes = Axes.X, diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index e47e290075..9d4ec2b806 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -71,13 +71,14 @@ namespace osu.Game.Overlays }; streams.SelectedRelease.ValueChanged += r => { - if (streams.SelectedRelease != null) + if (streams.SelectedRelease.Value != null) header.ShowReleaseStream(r.Name, string.Join(" ", r.Name, r.DisplayVersion)); }; streams.badgesContainer.OnLoadComplete += d => { header.OnListingActivated += () => { + streams.SelectedRelease.Value = null; foreach (StreamBadge item in streams.badgesContainer.Children) { item.Activate(true); From 837747e35f53a152b8f01e192fee6d06a30db688 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 18 Jul 2018 15:17:20 +0200 Subject: [PATCH 0012/5608] Streams3 --- osu.Game.Tests/Visual/TestCaseChangelog.cs | 40 +++++++++++++++++-- .../Overlays/Changelog/ChangelogHeader.cs | 4 +- .../Changelog/Header/TextBadgePair.cs | 28 ++++--------- .../Changelog/Header/TextBadgePairListing.cs | 7 ++++ .../Changelog/Header/TextBadgePairRelease.cs | 1 - osu.Game/Overlays/ChangelogOverlay.cs | 4 +- 6 files changed, 56 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseChangelog.cs b/osu.Game.Tests/Visual/TestCaseChangelog.cs index afd06d8415..c7b9f3dd9e 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelog.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelog.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; +using osu.Framework.Graphics.Containers; using osu.Game.Overlays; namespace osu.Game.Tests.Visual @@ -12,6 +13,7 @@ namespace osu.Game.Tests.Visual private ChangelogOverlay changelog; private int releaseStreamCount; private int index; + private void indexIncrement() => index = (index == releaseStreamCount - 1) ? 0 : index + 1; protected override void LoadComplete() { @@ -22,16 +24,46 @@ namespace osu.Game.Tests.Visual releaseStreamCount = changelog.streams.badgesContainer.Children.Count; AddStep(@"Show", changelog.Show); - AddRepeatStep(@"Toggle Release Stream", () => { + AddRepeatStep(@"Toggle Release Stream", () => + { changelog.streams.badgesContainer.Children[index].Activate(); - index = (index == releaseStreamCount - 1) ? 0 : index + 1; + indexIncrement(); }, releaseStreamCount); - AddStep(@"Listing", changelog.header.ActivateListing); + AddStep(@"Listing", changelog.ActivateListing); + AddStep(@"Hide", changelog.Hide); + AddWaitStep(4); + AddStep(@"Show with Release Stream", () => + { + changelog.streams.badgesContainer.Children[index].Activate(); + changelog.Show(); + indexIncrement(); + }); + AddWaitStep(4); + AddStep(@"Hide", changelog.Hide); + AddWaitStep(4); + AddStep(@"Show with listing", () => + { + // .maybe changelog should have a function that does header.ActivateListing() + changelog.ActivateListing(); + changelog.Show(); + }); + AddWaitStep(4); + AddStep(@"Hide", changelog.Hide); + AddWaitStep(4); + AddStep(@"Activate release", () => + { + changelog.streams.badgesContainer.Children[index].Activate(); + indexIncrement(); + }); + AddStep(@"Show with listing", () => + { + changelog.ActivateListing(); + changelog.Show(); + }); } public TestCaseChangelog() { - } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 183a63575b..43349fb668 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -133,7 +133,9 @@ namespace osu.Game.Overlays.Changelog { Top = 10, Left = 7, - Right = 9, + // + chevron size, and account for gained space on left by + // listing's font draw width being smaller + Right = 18, Bottom = 15, }, Children = new Drawable[] diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index 42f7bd601a..6482a69bb9 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -37,18 +37,10 @@ namespace osu.Game.Overlays.Changelog.Header public void ShowText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) { - if (!string.IsNullOrEmpty(displayText)) - { - text.Text = displayText; - } - + lineBadge.IsCollapsed = false; + if (!string.IsNullOrEmpty(displayText)) text.Text = displayText; text.MoveToY(0, duration, easing) - .FadeIn(duration, easing) - .Finally(d => { - // waiting until text is drawn to use its DrawWidth - UpdateBadgeWidth(); - lineBadge.IsCollapsed = false; - }); + .FadeIn(duration, easing); } /// @@ -61,19 +53,15 @@ namespace osu.Game.Overlays.Changelog.Header .FadeOut(duration, easing) .Then() .MoveToY(0, duration, easing) - .FadeIn(duration, easing) - .OnComplete(dd => { - UpdateBadgeWidth(); - lineBadge.IsCollapsed = false; - }); + .FadeIn(duration, easing); // since using .finally/.oncomplete after first fadeout made the badge // not hide sometimes in visual tests(because FinishTransforms()/CancelTransforms() // didn't apply to transforms that come after the .finally), I'm using a scheduler here Scheduler.AddDelayed(() => { - //lineBadge.ResizeWidthTo(0); // resizes when not visible if (!string.IsNullOrEmpty(displayText)) text.Text = displayText; + lineBadge.IsCollapsed = false; }, duration); } @@ -93,13 +81,13 @@ namespace osu.Game.Overlays.Changelog.Header { Top = 5, Bottom = 15, - Left = 10, - Right = 10, } }, lineBadge = new LineBadge(startCollapsed) { + Width = 1, Colour = badgeColour, + RelativeSizeAxes = Axes.X, } }; } @@ -115,7 +103,5 @@ namespace osu.Game.Overlays.Changelog.Header lineBadge.IsCollapsed = false; text.Font = "Exo2.0-Bold"; } - - public void UpdateBadgeWidth() => lineBadge.ResizeWidthTo(text.DrawWidth); } } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs index 41d9a2a8ef..0e12e1a2c5 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -19,6 +19,11 @@ namespace osu.Game.Overlays.Changelog.Header text.Anchor = Anchor.TopCentre; text.Origin = Anchor.TopCentre; + // I'm using this for constant badge width here, so that the whole + // thing doesn't jump left/right when listing's size changes + // due to different font weight (and thus width) + lineBadge.RelativeSizeAxes = Axes.None; + // this doesn't work without the scheduler // (because the text isn't yet fully drawn when it's loaded?) text.OnLoadComplete = d => Scheduler.Add(UpdateBadgeWidth); @@ -57,5 +62,7 @@ namespace osu.Game.Overlays.Changelog.Header if (lineBadge.IsCollapsed) lineBadge.ResizeHeightTo(1, lineBadge.TransitionDuration); base.OnHoverLost(state); } + + public void UpdateBadgeWidth() => lineBadge.ResizeWidthTo(text.DrawWidth); } } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs index f69c7dd6a7..d2fed56214 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs @@ -12,7 +12,6 @@ namespace osu.Game.Overlays.Changelog.Header public TextBadgePairRelease(ColourInfo badgeColour, string displayText) : base(badgeColour, displayText) { - this.listingBadge = listingBadge; text.Font = "Exo2.0-Bold"; text.Y = 20; text.Alpha = 0; diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 9d4ec2b806..20061317d2 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays { private readonly ScrollContainer scroll; - public readonly ChangelogHeader header; + private ChangelogHeader header; public readonly ChangelogStreams streams; protected Color4 purple = new Color4(191, 4, 255, 255); @@ -87,6 +87,8 @@ namespace osu.Game.Overlays }; } + public void ActivateListing() => header.ActivateListing(); + // receive input outside our bounds so we can trigger a close event on ourselves. public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; From 11e0732a2733401f511a5aefbc88c45fa0a03fc8 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 18 Jul 2018 19:32:15 +0200 Subject: [PATCH 0013/5608] Refactor1, UX1 --- osu.Game.Tests/Visual/TestCaseChangelog.cs | 24 +++---- osu.Game/Graphics/StreamColour.cs | 12 ++-- .../Overlays/Changelog/ChangelogHeader.cs | 48 ++++++------- .../Overlays/Changelog/ChangelogStreams.cs | 44 ++++++------ .../Overlays/Changelog/Header/LineBadge.cs | 10 +-- .../Changelog/Header/TextBadgePair.cs | 68 ++++++++++++------- .../Changelog/Header/TextBadgePairListing.cs | 30 ++++---- .../Changelog/Header/TextBadgePairRelease.cs | 25 ++++--- .../Overlays/Changelog/ReleaseStreamInfo.cs | 6 -- .../Overlays/Changelog/Streams/StreamBadge.cs | 51 ++++++++------ osu.Game/Overlays/ChangelogOverlay.cs | 47 +++++++++---- 11 files changed, 205 insertions(+), 160 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseChangelog.cs b/osu.Game.Tests/Visual/TestCaseChangelog.cs index c7b9f3dd9e..da568e0eb3 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelog.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelog.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; -using osu.Framework.Graphics.Containers; using osu.Game.Overlays; namespace osu.Game.Tests.Visual @@ -13,7 +12,7 @@ namespace osu.Game.Tests.Visual private ChangelogOverlay changelog; private int releaseStreamCount; private int index; - private void indexIncrement() => index = (index == releaseStreamCount - 1) ? 0 : index + 1; + private void indexIncrement() => index = index == releaseStreamCount - 1 ? 0 : index + 1; protected override void LoadComplete() { @@ -21,38 +20,37 @@ namespace osu.Game.Tests.Visual Add(changelog = new ChangelogOverlay()); - releaseStreamCount = changelog.streams.badgesContainer.Children.Count; + releaseStreamCount = changelog.Streams.BadgesContainer.Children.Count; AddStep(@"Show", changelog.Show); AddRepeatStep(@"Toggle Release Stream", () => { - changelog.streams.badgesContainer.Children[index].Activate(); + changelog.Streams.BadgesContainer.Children[index].Activate(); indexIncrement(); }, releaseStreamCount); AddStep(@"Listing", changelog.ActivateListing); AddStep(@"Hide", changelog.Hide); - AddWaitStep(4); + AddWaitStep(3); AddStep(@"Show with Release Stream", () => { - changelog.streams.badgesContainer.Children[index].Activate(); + changelog.Streams.BadgesContainer.Children[index].Activate(); changelog.Show(); indexIncrement(); }); - AddWaitStep(4); + AddWaitStep(3); AddStep(@"Hide", changelog.Hide); - AddWaitStep(4); + AddWaitStep(3); AddStep(@"Show with listing", () => { - // .maybe changelog should have a function that does header.ActivateListing() changelog.ActivateListing(); changelog.Show(); }); AddWaitStep(4); AddStep(@"Hide", changelog.Hide); - AddWaitStep(4); + AddWaitStep(3); AddStep(@"Activate release", () => { - changelog.streams.badgesContainer.Children[index].Activate(); + changelog.Streams.BadgesContainer.Children[index].Activate(); indexIncrement(); }); AddStep(@"Show with listing", () => @@ -61,9 +59,5 @@ namespace osu.Game.Tests.Visual changelog.Show(); }); } - - public TestCaseChangelog() - { - } } } diff --git a/osu.Game/Graphics/StreamColour.cs b/osu.Game/Graphics/StreamColour.cs index fbb272c526..0da0201c06 100644 --- a/osu.Game/Graphics/StreamColour.cs +++ b/osu.Game/Graphics/StreamColour.cs @@ -7,11 +7,11 @@ namespace osu.Game.Graphics { public class StreamColour { - public readonly Color4 Stable = new Color4(102, 204, 255, 255); - public readonly Color4 StableFallback = new Color4(34, 153, 187, 255); - public readonly Color4 Beta = new Color4(255, 221, 85, 255); - public readonly Color4 CuttingEdge = new Color4(238, 170, 0, 255); - public readonly Color4 Lazer = new Color4(237, 18, 33, 255); - public readonly Color4 Web = new Color4(136, 102, 238, 255); + public static readonly Color4 STABLE = new Color4(102, 204, 255, 255); + public static readonly Color4 STABLEFALLBACK = new Color4(34, 153, 187, 255); + public static readonly Color4 BETA = new Color4(255, 221, 85, 255); + public static readonly Color4 CUTTINGEDGE = new Color4(238, 170, 0, 255); + public static readonly Color4 LAZER = new Color4(237, 18, 33, 255); + public static readonly Color4 WEB = new Color4(136, 102, 238, 255); } } diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 43349fb668..ebf666b1d8 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -18,15 +18,12 @@ namespace osu.Game.Overlays.Changelog { public class ChangelogHeader : Container { - protected Color4 purple = new Color4(191, 4, 255, 255); + protected Color4 Purple = new Color4(191, 4, 255, 255); private readonly Sprite coverImage; private readonly Sprite headerBadge; //50x50, margin-right: 20 - private readonly FillFlowContainer headerTextContainer; - private readonly OsuSpriteText title, titleStream; - private readonly SpriteIcon chevron; + private readonly OsuSpriteText titleStream; private readonly TextBadgePairListing listing; private readonly TextBadgePairRelease releaseStream; - private readonly FillFlowContainer breadcrumbContainer; public Action OnListingActivated; @@ -38,6 +35,7 @@ namespace osu.Game.Overlays.Changelog public ChangelogHeader() { + SpriteIcon chevron; // AppVeyor told me this should be a local variable..? RelativeSizeAxes = Axes.X; Height = cover_height; Children = new Drawable[] @@ -45,7 +43,7 @@ namespace osu.Game.Overlays.Changelog coverImage = new Sprite { RelativeSizeAxes = Axes.Both, - Size = new OpenTK.Vector2(1), + Size = new Vector2(1), FillMode = FillMode.Fill, Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -62,16 +60,16 @@ namespace osu.Game.Overlays.Changelog { X = icon_margin, Masking = true, - BorderColour = purple, + BorderColour = Purple, BorderThickness = 3, MaskingSmoothness = 1, - Size = new OpenTK.Vector2(50), + Size = new Vector2(50), Children = new Drawable[] { headerBadge = new Sprite { RelativeSizeAxes = Axes.Both, - Size = new OpenTK.Vector2(0.8f), + Size = new Vector2(0.8f), Anchor = Anchor.Centre, Origin = Anchor.Centre, }, @@ -82,14 +80,14 @@ namespace osu.Game.Overlays.Changelog new Box { RelativeSizeAxes = Axes.Both, - Size = new OpenTK.Vector2(1), + Size = new Vector2(1), Alpha = 0, AlwaysPresent = true, - Colour = purple, + Colour = Purple, } } }, - headerTextContainer = new FillFlowContainer + new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, @@ -98,7 +96,7 @@ namespace osu.Game.Overlays.Changelog X = icon_size + icon_margin * 2, Children = new Drawable[] { - title = new OsuSpriteText + new OsuSpriteText { Text = "Changelog ", Font = @"Exo2.0-Light", @@ -109,13 +107,13 @@ namespace osu.Game.Overlays.Changelog Text = "Listing", TextSize = 38, // web: 30 Font = @"Exo2.0-Light", - Colour = purple, + Colour = Purple, }, } } } }, - breadcrumbContainer = new FillFlowContainer // Listing > Lazer 2018.713.1 + new FillFlowContainer // Listing > Lazer 2018.713.1 { X = 2 * icon_margin + icon_size - 8, Height = version_height, @@ -124,12 +122,12 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Horizontal, Children = new Drawable[] { - listing = new TextBadgePairListing(purple), - new Container() // without a container, moving the chevron wont work + listing = new TextBadgePairListing(Purple), + new Container // without a container, moving the chevron wont work { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Margin = new MarginPadding() + Margin = new MarginPadding { Top = 10, Left = 7, @@ -145,19 +143,19 @@ namespace osu.Game.Overlays.Changelog Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(7), - Colour = purple, + Colour = Purple, Icon = FontAwesome.fa_chevron_right, Alpha = 0, X = -200, }, }, }, - releaseStream = new TextBadgePairRelease(purple, "Lazer") + releaseStream = new TextBadgePairRelease(Purple, "Lazer") }, }, new Box // purple line { - Colour = purple, + Colour = Purple, RelativeSizeAxes = Axes.X, Height = 3, Anchor = Anchor.BottomLeft, @@ -177,7 +175,7 @@ namespace osu.Game.Overlays.Changelog { releaseStream.Deactivate(); chevron.MoveToX(-20, 100).FadeOut(100); - ChangeHeaderText("Listing"); + changeHeaderText("Listing"); OnListingActivated?.Invoke(); }; }; @@ -186,10 +184,10 @@ namespace osu.Game.Overlays.Changelog public void ShowReleaseStream(string headerText, string breadcrumbText) { releaseStream.Activate(breadcrumbText); - ChangeHeaderText(headerText); + changeHeaderText(headerText); } - private void ChangeHeaderText(string headerText) + private void changeHeaderText(string headerText) { titleStream.Text = headerText; titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); @@ -197,6 +195,8 @@ namespace osu.Game.Overlays.Changelog public void ActivateListing() => listing.Activate(); + public bool IsListingActivated() => listing.IsActivated; + [BackgroundDependencyLoader] private void load(TextureStore textures) { diff --git a/osu.Game/Overlays/Changelog/ChangelogStreams.cs b/osu.Game/Overlays/Changelog/ChangelogStreams.cs index 99c9c0accd..f0848188c8 100644 --- a/osu.Game/Overlays/Changelog/ChangelogStreams.cs +++ b/osu.Game/Overlays/Changelog/ChangelogStreams.cs @@ -3,32 +3,28 @@ using OpenTK.Graphics; using osu.Framework.Configuration; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Game.Graphics; using osu.Game.Overlays.Changelog.Streams; -using System; namespace osu.Game.Overlays.Changelog { public class ChangelogStreams : Container { - private const float containerHeight = 106.5f; - private const float containerTopBottomMargin = 20; - private const float containerSideMargin = 85; + private const float container_height = 106.5f; + private const float container_margin_y = 20; + private const float container_margin_x = 85; public Bindable SelectedRelease = new Bindable(); - private readonly StreamColour streamColour; - public readonly FillFlowContainer badgesContainer; + public readonly FillFlowContainer BadgesContainer; public ChangelogStreams() { - streamColour = new StreamColour(); - Height = containerHeight; + Height = container_height; RelativeSizeAxes = Axes.X; Children = new Drawable[] { @@ -38,39 +34,39 @@ namespace osu.Game.Overlays.Changelog Size = new OpenTK.Vector2(1), Colour = new Color4(32, 24, 35, 255), }, - badgesContainer = new FillFlowContainer + BadgesContainer = new FillFlowContainer { Direction = FillDirection.Horizontal, RelativeSizeAxes = Axes.Both, - Margin = new MarginPadding() + Margin = new MarginPadding { - Top = containerTopBottomMargin, - Bottom = containerTopBottomMargin, - Left = containerSideMargin, - Right = containerSideMargin, + Top = container_margin_y, + Bottom = container_margin_y, + Left = container_margin_x, + Right = container_margin_x, }, Children = new[] { - new StreamBadge(streamColour.Stable, "Stable", "20180626.1", 16370, true), - new StreamBadge(streamColour.Beta, "Beta", "20180626", 186), - new StreamBadge(streamColour.Lazer, "Lazer", "2018.713.1"), + new StreamBadge(StreamColour.STABLE, "Stable", "20180626.1", 16370, true), + new StreamBadge(StreamColour.BETA, "Beta", "20180626", 186), + new StreamBadge(StreamColour.LAZER, "Lazer", "2018.713.1"), }, }, }; - badgesContainer.OnLoadComplete = d => + BadgesContainer.OnLoadComplete = d => { - foreach (StreamBadge streamBadge in badgesContainer.Children) + foreach (StreamBadge streamBadge in BadgesContainer.Children) { streamBadge.OnActivation = () => { - SelectedRelease.Value = new ReleaseStreamInfo() + SelectedRelease.Value = new ReleaseStreamInfo { DisplayVersion = streamBadge.DisplayVersion, IsFeatured = streamBadge.IsFeatured, Name = streamBadge.Name, Users = streamBadge.Users, }; - foreach (StreamBadge item in badgesContainer.Children) + foreach (StreamBadge item in BadgesContainer.Children) { if (item.Name != streamBadge.Name) item.Deactivate(); } @@ -82,7 +78,7 @@ namespace osu.Game.Overlays.Changelog protected override bool OnHover(InputState state) { // is this nullreference-safe for badgesContainer? - foreach (StreamBadge streamBadge in badgesContainer.Children) + foreach (StreamBadge streamBadge in BadgesContainer.Children) { if (SelectedRelease.Value != null) { @@ -100,7 +96,7 @@ namespace osu.Game.Overlays.Changelog { if (SelectedRelease.Value == null) { - foreach (StreamBadge streamBadge in badgesContainer.Children) streamBadge.Activate(true); + foreach (StreamBadge streamBadge in BadgesContainer.Children) streamBadge.Activate(true); } base.OnHoverLost(state); } diff --git a/osu.Game/Overlays/Changelog/Header/LineBadge.cs b/osu.Game/Overlays/Changelog/Header/LineBadge.cs index c33244d50b..93eca528c5 100644 --- a/osu.Game/Overlays/Changelog/Header/LineBadge.cs +++ b/osu.Game/Overlays/Changelog/Header/LineBadge.cs @@ -8,18 +8,20 @@ namespace osu.Game.Overlays.Changelog.Header { public class LineBadge : Circle { - public float TransitionDuration = 100; + public float TransitionDuration = 400; public float UncollapsedHeight; public float CollapsedHeight; - protected bool isCollapsed; + private bool isCollapsed; public bool IsCollapsed { get { return isCollapsed; } set { isCollapsed = value; - this.ResizeHeightTo(value ? CollapsedHeight : UncollapsedHeight, TransitionDuration); + this.ResizeHeightTo(value ? CollapsedHeight : UncollapsedHeight, + value ? TransitionDuration / 2f : TransitionDuration, + value ? Easing.Out : Easing.OutElastic); } } @@ -32,7 +34,7 @@ namespace osu.Game.Overlays.Changelog.Header Height = startCollapsed ? CollapsedHeight : UncollapsedHeight; // this margin prevents jumps when changing text's font weight - Margin = new MarginPadding() + Margin = new MarginPadding { Left = 10, Right = 10, diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index 6482a69bb9..a888c436cf 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -1,45 +1,51 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input; using System; namespace osu.Game.Overlays.Changelog.Header { - public class TextBadgePair : ClickableContainer + public class TextBadgePair : Container { - protected SpriteText text; - protected LineBadge lineBadge; - protected bool startCollapsed; + protected SpriteText Text; + protected LineBadge LineBadge; + public bool IsActivated { get; protected set; } public Action OnActivation; public Action OnDeactivation; + private SampleChannel sampleHover; + protected SampleChannel SampleActivate; public void SetTextColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) { - text.FadeColour(newColour, duration, easing); + Text.FadeColour(newColour, duration, easing); } public void SetBadgeColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) { - lineBadge.FadeColour(newColour, duration, easing); + LineBadge.FadeColour(newColour, duration, easing); } public void HideText(double duration = 0, Easing easing = Easing.InOutCubic) { - lineBadge.IsCollapsed = true; - text.MoveToY(20, duration, easing) + LineBadge.IsCollapsed = true; + Text.MoveToY(20, duration, easing) .FadeOut(duration, easing); } public void ShowText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) { - lineBadge.IsCollapsed = false; - if (!string.IsNullOrEmpty(displayText)) text.Text = displayText; - text.MoveToY(0, duration, easing) + LineBadge.IsCollapsed = false; + if (!string.IsNullOrEmpty(displayText)) Text.Text = displayText; + Text.MoveToY(0, duration, easing) .FadeIn(duration, easing); } @@ -48,8 +54,8 @@ namespace osu.Game.Overlays.Changelog.Header /// Full change takes double this time. public void ChangeText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) { - lineBadge.IsCollapsed = true; - text.MoveToY(20, duration, easing) + LineBadge.IsCollapsed = true; + Text.MoveToY(20, duration, easing) .FadeOut(duration, easing) .Then() .MoveToY(0, duration, easing) @@ -60,30 +66,30 @@ namespace osu.Game.Overlays.Changelog.Header // didn't apply to transforms that come after the .finally), I'm using a scheduler here Scheduler.AddDelayed(() => { - if (!string.IsNullOrEmpty(displayText)) text.Text = displayText; - lineBadge.IsCollapsed = false; + if (!string.IsNullOrEmpty(displayText)) Text.Text = displayText; + LineBadge.IsCollapsed = false; }, duration); } - public TextBadgePair(ColourInfo badgeColour, string displayText = "Listing", bool startBadgeCollapsed = true) + public TextBadgePair(ColourInfo badgeColour, string displayText = "Listing", bool startCollapsed = true) { AutoSizeAxes = Axes.X; RelativeSizeAxes = Axes.Y; Children = new Drawable[] { - text = new SpriteText + Text = new SpriteText { TextSize = 21, // web is 16, but here it looks too small? Text = displayText, Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, - Margin = new MarginPadding() + Margin = new MarginPadding { Top = 5, Bottom = 15, } }, - lineBadge = new LineBadge(startCollapsed) + LineBadge = new LineBadge(startCollapsed) { Width = 1, Colour = badgeColour, @@ -94,14 +100,30 @@ namespace osu.Game.Overlays.Changelog.Header public virtual void Deactivate() { - lineBadge.IsCollapsed = true; - text.Font = "Exo2.0-Regular"; + IsActivated = false; + LineBadge.IsCollapsed = true; + Text.Font = "Exo2.0-Regular"; } public virtual void Activate() { - lineBadge.IsCollapsed = false; - text.Font = "Exo2.0-Bold"; + IsActivated = true; + LineBadge.IsCollapsed = false; + Text.Font = "Exo2.0-Bold"; + SampleActivate?.Play(); + } + + protected override bool OnHover(InputState state) + { + if (!IsActivated) sampleHover?.Play(); + return base.OnHover(state); + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); + SampleActivate = audio.Sample.Get(@"UI/generic-select-soft"); } } } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs index 0e12e1a2c5..eaf7e1289b 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -10,37 +10,41 @@ namespace osu.Game.Overlays.Changelog.Header { public class TextBadgePairListing : TextBadgePair { - private ColourInfo badgeColour; + private readonly ColourInfo badgeColour; public TextBadgePairListing(ColourInfo badgeColour) : base(badgeColour, "Listing", false) { + IsActivated = true; this.badgeColour = badgeColour; - text.Font = "Exo2.0-Bold"; - text.Anchor = Anchor.TopCentre; - text.Origin = Anchor.TopCentre; + Text.Font = "Exo2.0-Bold"; + Text.Anchor = Anchor.TopCentre; + Text.Origin = Anchor.TopCentre; // I'm using this for constant badge width here, so that the whole // thing doesn't jump left/right when listing's size changes // due to different font weight (and thus width) - lineBadge.RelativeSizeAxes = Axes.None; + LineBadge.RelativeSizeAxes = Axes.None; // this doesn't work without the scheduler // (because the text isn't yet fully drawn when it's loaded?) - text.OnLoadComplete = d => Scheduler.Add(UpdateBadgeWidth); + Text.OnLoadComplete = d => Scheduler.Add(UpdateBadgeWidth); } public override void Activate() { - lineBadge.IsCollapsed = false; - text.Font = "Exo2.0-Bold"; + IsActivated = true; + LineBadge.IsCollapsed = false; + Text.Font = "Exo2.0-Bold"; SetTextColour(Color4.White, 100); + SampleActivate?.Play(); OnActivation?.Invoke(); } public override void Deactivate() { - lineBadge.IsCollapsed = true; - text.Font = "Exo2.0-Regular"; // commented out since it makes bad resize-jumping + IsActivated = false; + LineBadge.IsCollapsed = true; + Text.Font = "Exo2.0-Regular"; // commented out since it makes bad resize-jumping SetTextColour(badgeColour, 100); OnDeactivation?.Invoke(); } @@ -53,16 +57,16 @@ namespace osu.Game.Overlays.Changelog.Header protected override bool OnHover(InputState state) { - lineBadge.ResizeHeightTo(lineBadge.UncollapsedHeight, lineBadge.TransitionDuration); + LineBadge.ResizeHeightTo(LineBadge.UncollapsedHeight, LineBadge.TransitionDuration, Easing.OutElastic); return base.OnHover(state); } protected override void OnHoverLost(InputState state) { - if (lineBadge.IsCollapsed) lineBadge.ResizeHeightTo(1, lineBadge.TransitionDuration); + if (IsActivated == false) LineBadge.ResizeHeightTo(1, LineBadge.TransitionDuration, Easing.Out); base.OnHoverLost(state); } - public void UpdateBadgeWidth() => lineBadge.ResizeWidthTo(text.DrawWidth); + public void UpdateBadgeWidth() => LineBadge.ResizeWidthTo(Text.DrawWidth); } } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs index d2fed56214..2186043035 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs @@ -12,29 +12,34 @@ namespace osu.Game.Overlays.Changelog.Header public TextBadgePairRelease(ColourInfo badgeColour, string displayText) : base(badgeColour, displayText) { - text.Font = "Exo2.0-Bold"; - text.Y = 20; - text.Alpha = 0; + Text.Font = "Exo2.0-Bold"; + Text.Y = 20; + Text.Alpha = 0; } public void SetText(string displayText) { - text.Text = displayText; + Text.Text = displayText; } public void Activate(string displayText = null) { - //ClearTransforms(); - // not using if (!lineBadge.IsCollapsed) because the text sometimes gets reset - // when quickly switching release streams - if (text.IsPresent) ChangeText(transition_duration, displayText); - else ShowText(transition_duration, displayText); + if (IsActivated) + { + if (displayText != Text.Text) ChangeText(transition_duration, displayText); + } + else + { + ShowText(transition_duration, displayText); + IsActivated = true; + } + SampleActivate?.Play(); OnActivation?.Invoke(); } public override void Deactivate() { - //FinishTransforms(true); + IsActivated = false; HideText(transition_duration); OnDeactivation?.Invoke(); } diff --git a/osu.Game/Overlays/Changelog/ReleaseStreamInfo.cs b/osu.Game/Overlays/Changelog/ReleaseStreamInfo.cs index 90b2ab6cfb..2934ae8f94 100644 --- a/osu.Game/Overlays/Changelog/ReleaseStreamInfo.cs +++ b/osu.Game/Overlays/Changelog/ReleaseStreamInfo.cs @@ -2,13 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using Newtonsoft.Json; -using osu.Game.Database; using osu.Game.IO.Serialization; -using osu.Game.Rulesets; namespace osu.Game.Overlays.Changelog { diff --git a/osu.Game/Overlays/Changelog/Streams/StreamBadge.cs b/osu.Game/Overlays/Changelog/Streams/StreamBadge.cs index 9b70c9ce7f..8bd10dcbb8 100644 --- a/osu.Game/Overlays/Changelog/Streams/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/Streams/StreamBadge.cs @@ -1,12 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; using System; @@ -15,21 +16,20 @@ namespace osu.Game.Overlays.Changelog.Streams { public class StreamBadge : ClickableContainer { - private const float badgeHeight = 56.5f; - private const float badgeWidth = 100; - private const float badgeTopBottomMargin = 5; + private const float badge_height = 56.5f; + private const float badge_width = 100; private const float transition_duration = 100; public Action OnActivation; - private bool isActive; + private bool isActivated; - private Header.LineBadge lineBadge; - - public string Name { get; private set; } - public string DisplayVersion { get; private set; } - public bool IsFeatured { get; private set; } - public float Users { get; private set; } + private readonly Header.LineBadge lineBadge; + private SampleChannel sampleHover; + public readonly string Name; + public readonly string DisplayVersion; + public readonly bool IsFeatured; + public readonly float Users; public StreamBadge(ColourInfo colour, string streamName, string streamBuild, float onlineUsers = 0, bool isFeatured = false) { @@ -37,10 +37,10 @@ namespace osu.Game.Overlays.Changelog.Streams DisplayVersion = streamBuild; IsFeatured = isFeatured; Users = onlineUsers; - Height = badgeHeight; - Width = isFeatured ? badgeWidth * 2 : badgeWidth; + Height = badge_height; + Width = isFeatured ? badge_width * 2 : badge_width; Margin = new MarginPadding(5); - isActive = true; + isActivated = true; Children = new Drawable[] { new FillFlowContainer @@ -84,13 +84,14 @@ namespace osu.Game.Overlays.Changelog.Streams Width = 1, Colour = colour, RelativeSizeAxes = Axes.X, + TransitionDuration = 600, }, }; } public void Activate(bool withoutHeaderUpdate = false) { - isActive = true; + isActivated = true; this.FadeIn(transition_duration); lineBadge.IsCollapsed = false; if (!withoutHeaderUpdate) OnActivation?.Invoke(); @@ -98,9 +99,12 @@ namespace osu.Game.Overlays.Changelog.Streams public void Deactivate() { - isActive = false; - this.FadeTo(0.5f, transition_duration); - lineBadge.IsCollapsed = true; + isActivated = false; + if (!IsHovered) + { + this.FadeTo(0.5f, transition_duration); + lineBadge.IsCollapsed = true; + } } protected override bool OnClick(InputState state) @@ -111,6 +115,7 @@ namespace osu.Game.Overlays.Changelog.Streams protected override bool OnHover(InputState state) { + if (!isActivated) sampleHover?.Play(); this.FadeIn(transition_duration); lineBadge.IsCollapsed = false; return base.OnHover(state); @@ -118,12 +123,18 @@ namespace osu.Game.Overlays.Changelog.Streams protected override void OnHoverLost(InputState state) { - if (!isActive) + if (!isActivated) { this.FadeTo(0.5f, transition_duration); lineBadge.IsCollapsed = true; } base.OnHoverLost(state); } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); + } } } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 20061317d2..f928f9ee58 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Input.Bindings; using osu.Game.Overlays.Changelog; using osu.Game.Overlays.Changelog.Streams; @@ -16,12 +17,10 @@ namespace osu.Game.Overlays { public class ChangelogOverlay : WaveOverlayContainer { - private readonly ScrollContainer scroll; + private readonly ChangelogHeader header; + public readonly ChangelogStreams Streams; - private ChangelogHeader header; - public readonly ChangelogStreams streams; - - protected Color4 purple = new Color4(191, 4, 255, 255); + protected readonly Color4 Purple = new Color4(191, 4, 255, 255); public ChangelogOverlay() { @@ -52,7 +51,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Colour = new Color4(20, 18, 23, 255) }, - scroll = new ScrollContainer + new ScrollContainer { RelativeSizeAxes = Axes.Both, ScrollbarVisible = false, @@ -64,25 +63,25 @@ namespace osu.Game.Overlays Children = new Drawable[] { header = new ChangelogHeader(), - streams = new ChangelogStreams(), + Streams = new ChangelogStreams(), }, }, }, }; - streams.SelectedRelease.ValueChanged += r => + Streams.SelectedRelease.ValueChanged += r => { - if (streams.SelectedRelease.Value != null) + if (Streams.SelectedRelease.Value != null) header.ShowReleaseStream(r.Name, string.Join(" ", r.Name, r.DisplayVersion)); }; - streams.badgesContainer.OnLoadComplete += d => + Streams.BadgesContainer.OnLoadComplete += d => { header.OnListingActivated += () => { - streams.SelectedRelease.Value = null; - foreach (StreamBadge item in streams.badgesContainer.Children) - { - item.Activate(true); - } + Streams.SelectedRelease.Value = null; + if (!Streams.IsHovered) + foreach (StreamBadge item in Streams.BadgesContainer.Children) item.Activate(true); + else + foreach (StreamBadge item in Streams.BadgesContainer.Children) item.Deactivate(); }; }; } @@ -92,6 +91,24 @@ namespace osu.Game.Overlays // receive input outside our bounds so we can trigger a close event on ourselves. public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; + public override bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.Back: + if (header.IsListingActivated()) State = Visibility.Hidden; + + // the problem here is that when hovering over the builds' container + // and pressing back, they don't lower their opacity they're rehovered on + else header.ActivateListing(); + return true; + case GlobalAction.Select: + return true; + } + + return false; + } + protected override void PopIn() { base.PopIn(); From bcd132e87f99bacbe1d91f7e7e69abfe83371ddc Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Thu, 19 Jul 2018 19:07:24 +0200 Subject: [PATCH 0014/5608] API1 --- osu.Game.Tests/Visual/TestCaseChangelog.cs | 16 ++- osu.Game/Graphics/StreamColour.cs | 19 +++ .../UserInterface/TooltipIconButton.cs | 43 +++++++ .../GetChangelogLatestBuildsRequest.cs | 17 +++ .../API/Requests/GetChangelogRequest.cs | 13 +++ .../API/Requests/Responses/APIChangelog.cs | 54 +++++++++ osu.Game/Overlays/Changelog/ChangelogChart.cs | 36 ++++++ .../Overlays/Changelog/ChangelogContent.cs | 18 +++ .../Changelog/ChangelogContentGroup.cs | 109 ++++++++++++++++++ .../Overlays/Changelog/ChangelogHeader.cs | 10 +- .../Overlays/Changelog/ChangelogStreams.cs | 36 +++--- .../Overlays/Changelog/ReleaseStreamInfo.cs | 19 --- .../Changelog/{Streams => }/StreamBadge.cs | 29 ++--- osu.Game/Overlays/ChangelogOverlay.cs | 62 ++++++++-- 14 files changed, 399 insertions(+), 82 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/TooltipIconButton.cs create mode 100644 osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs create mode 100644 osu.Game/Online/API/Requests/GetChangelogRequest.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APIChangelog.cs create mode 100644 osu.Game/Overlays/Changelog/ChangelogChart.cs create mode 100644 osu.Game/Overlays/Changelog/ChangelogContent.cs create mode 100644 osu.Game/Overlays/Changelog/ChangelogContentGroup.cs delete mode 100644 osu.Game/Overlays/Changelog/ReleaseStreamInfo.cs rename osu.Game/Overlays/Changelog/{Streams => }/StreamBadge.cs (81%) diff --git a/osu.Game.Tests/Visual/TestCaseChangelog.cs b/osu.Game.Tests/Visual/TestCaseChangelog.cs index da568e0eb3..894b117118 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelog.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelog.cs @@ -10,9 +10,9 @@ namespace osu.Game.Tests.Visual public class TestCaseChangelog : OsuTestCase { private ChangelogOverlay changelog; - private int releaseStreamCount; private int index; - private void indexIncrement() => index = index == releaseStreamCount - 1 ? 0 : index + 1; + private void indexIncrement() => index = index >= changelog.Streams.BadgesContainer.Children.Count - 1 ? 0 : index + 1; + private bool isLoaded => changelog.Streams.BadgesContainer.Children.Count > 0; protected override void LoadComplete() { @@ -20,20 +20,18 @@ namespace osu.Game.Tests.Visual Add(changelog = new ChangelogOverlay()); - releaseStreamCount = changelog.Streams.BadgesContainer.Children.Count; - AddStep(@"Show", changelog.Show); AddRepeatStep(@"Toggle Release Stream", () => { - changelog.Streams.BadgesContainer.Children[index].Activate(); + if (isLoaded) changelog.Streams.BadgesContainer.Children[index].Activate(); indexIncrement(); - }, releaseStreamCount); + }, 6); AddStep(@"Listing", changelog.ActivateListing); AddStep(@"Hide", changelog.Hide); AddWaitStep(3); AddStep(@"Show with Release Stream", () => { - changelog.Streams.BadgesContainer.Children[index].Activate(); + if (isLoaded) changelog.Streams.BadgesContainer.Children[index].Activate(); changelog.Show(); indexIncrement(); }); @@ -45,12 +43,12 @@ namespace osu.Game.Tests.Visual changelog.ActivateListing(); changelog.Show(); }); - AddWaitStep(4); + AddWaitStep(3); AddStep(@"Hide", changelog.Hide); AddWaitStep(3); AddStep(@"Activate release", () => { - changelog.Streams.BadgesContainer.Children[index].Activate(); + if (isLoaded) changelog.Streams.BadgesContainer.Children[index].Activate(); indexIncrement(); }); AddStep(@"Show with listing", () => diff --git a/osu.Game/Graphics/StreamColour.cs b/osu.Game/Graphics/StreamColour.cs index 0da0201c06..2a0d7fceab 100644 --- a/osu.Game/Graphics/StreamColour.cs +++ b/osu.Game/Graphics/StreamColour.cs @@ -2,6 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; +using osu.Framework.Graphics.Colour; +using System.Collections.Generic; namespace osu.Game.Graphics { @@ -13,5 +15,22 @@ namespace osu.Game.Graphics public static readonly Color4 CUTTINGEDGE = new Color4(238, 170, 0, 255); public static readonly Color4 LAZER = new Color4(237, 18, 33, 255); public static readonly Color4 WEB = new Color4(136, 102, 238, 255); + + private static readonly Dictionary colours = new Dictionary + { + { "stable40", STABLE }, + { "stable", STABLEFALLBACK }, + { "beta40", BETA }, + { "cuttingedge", CUTTINGEDGE }, + { "lazer", LAZER }, + { "web", WEB }, + }; + + public static ColourInfo FromStreamName(string name) + { + if (colours.TryGetValue(name, out ColourInfo colour)) + return colour; + else return new Color4(255, 255, 255, 255); + } } } diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs new file mode 100644 index 0000000000..918e203bf4 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -0,0 +1,43 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Graphics.UserInterface +{ + public class TooltipIconButton : OsuClickableContainer, IHasTooltip + { + private readonly SpriteIcon icon; + + public FontAwesome Icon + { + get { return icon.Icon; } + set { icon.Icon = value; } + } + + public TooltipIconButton() + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + }, + icon = new SpriteIcon + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(18), + } + }; + } + + + public string TooltipText { get; set; } + } +} diff --git a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs new file mode 100644 index 0000000000..845760f2e4 --- /dev/null +++ b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Online.API.Requests.Responses; +using System.Collections.Generic; + +namespace osu.Game.Online.API.Requests +{ + /// + /// Obviously a placeholder + /// + public class GetChangelogLatestBuildsRequest : APIRequest> + { + protected override string Uri => Target; + protected override string Target => @"https://api.myjson.com/bins/16waui"; + } +} diff --git a/osu.Game/Online/API/Requests/GetChangelogRequest.cs b/osu.Game/Online/API/Requests/GetChangelogRequest.cs new file mode 100644 index 0000000000..652e638ab8 --- /dev/null +++ b/osu.Game/Online/API/Requests/GetChangelogRequest.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Online.API.Requests +{ + public class GetChangelogRequest : APIRequest + { + protected override string Uri => Target; + protected override string Target => "https://api.myjson.com/bins/6zv2i"; + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs new file mode 100644 index 0000000000..f0dcafdc04 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs @@ -0,0 +1,54 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using Newtonsoft.Json; +using System; +using System.Collections.Generic; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIChangelog + { + [JsonProperty("id")] + public long Id { get; set; } + + [JsonProperty("version")] + public string Version { get; set; } + + [JsonProperty("display_version")] + public string DisplayVersion { get; set; } + + [JsonProperty("users")] + public long Users { get; set; } + + [JsonProperty("is_featured")] + public bool IsFeatured { get; set; } + + [JsonProperty("created_at")] + public DateTimeOffset CreatedAt { get; set; } + + [JsonProperty("disqus_id")] + public string DisqusId { get; set; } + + [JsonProperty("disqus_title")] + public string DisqusTitle { get; set; } + + [JsonProperty("update_stream")] + public UpdateStream UpdateStream { get; set; } + + [JsonProperty("changelog_entries")] + public List ChangelogEntries { get; set; } + } + + public class UpdateStream + { + [JsonProperty("id")] + public long Id { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("display_name")] + public string DisplayName { get; set; } + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs new file mode 100644 index 0000000000..e885867c74 --- /dev/null +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -0,0 +1,36 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; + +namespace osu.Game.Overlays.Changelog +{ + // maybe look to osu.Game.Screens.Play.SquareGraph for reference later + public class ChangelogChart : BufferedContainer + { + public ChangelogChart() + { + RelativeSizeAxes = Axes.X; + Height = 100; + Children = new Drawable[] + { + new Box + { + Colour = StreamColour.STABLE, + RelativeSizeAxes = Axes.Both, + }, + new SpriteText + { + Text = "Graph Placeholder", + TextSize = 28, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + }; + } + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs new file mode 100644 index 0000000000..d10fe19942 --- /dev/null +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Overlays.Changelog +{ + public class ChangelogContent : FillFlowContainer + { + public ChangelogContent() + { + RelativeSizeAxes = Axes.X; + //AutoSizeAxes = Axes.Y; + Direction = FillDirection.Vertical; + } + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs new file mode 100644 index 0000000000..951cebb941 --- /dev/null +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -0,0 +1,109 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Overlays.Changelog +{ + public class ChangelogContentGroup : FillFlowContainer + { + // will porobably depend in some way on #1692 (https://github.com/ppy/osu-framework/pull/1692) + // need to keep in mind it looks different on Listing (one contains all builds from a date) + // and when a stream is selected (looks like now) + public ChangelogContentGroup(APIChangelog build) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Direction = FillDirection.Vertical; + Padding = new MarginPadding + { + Left = 70, + Right = 70, + }; + Children = new Drawable[] + { + // build version, arrows + new FillFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding + { + Top = 20, + }, + Children = new Drawable[] + { + new TooltipIconButton + { + Icon = FontAwesome.fa_chevron_left, + Size = new Vector2(24), + // how do we link to previous/next builds? + // I'm thinking some linked list, but how do we make that + // from the available API data + TooltipText = "Previous", + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding + { + Left = 40, + Right = 40, + }, + Children = new[] + { + new SpriteText + { + Text = build.UpdateStream.DisplayName, + TextSize = 28, // web: 24, + Font = @"Exo2.0-Medium", + }, + new SpriteText // a space... + { + Text = " ", + TextSize = 28, + }, + new SpriteText + { + Text = build.DisplayVersion, + TextSize = 28, // web: 24, + Colour = StreamColour.STABLE, + }, + } + }, + new TooltipIconButton + { + Icon = FontAwesome.fa_chevron_right, + Size = new Vector2(24), + TooltipText = "Next", + }, + } + }, + new SpriteText + { + // do we need .ToUniversalTime() here? + // also, this is a temporary solution to weekdays in >localized< date strings + Text = build.CreatedAt.Date.ToLongDateString().Replace(build.CreatedAt.ToString("dddd") + ", ", ""), + TextSize = 17, // web: 14, + Colour = OsuColour.FromHex(@"FD5"), + Font = @"Exo2.0-Medium", + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Margin = new MarginPadding + { + Top = 5, + }, + }, + }; + } + //public ChangelogContentGroup(DateTimeOffset date) { } + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index ebf666b1d8..8332aeeaa4 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Changelog.Header; using System; @@ -27,6 +28,8 @@ namespace osu.Game.Overlays.Changelog public Action OnListingActivated; + public APIChangelog ChangelogEntry; + private const float cover_height = 310; private const float title_height = 50; private const float icon_size = 50; @@ -181,10 +184,11 @@ namespace osu.Game.Overlays.Changelog }; } - public void ShowReleaseStream(string headerText, string breadcrumbText) + public void ShowReleaseStream() { - releaseStream.Activate(breadcrumbText); - changeHeaderText(headerText); + releaseStream.Activate(String.Join(" ", + ChangelogEntry.UpdateStream.DisplayName, ChangelogEntry.DisplayVersion)); + changeHeaderText(ChangelogEntry.UpdateStream.DisplayName); } private void changeHeaderText(string headerText) diff --git a/osu.Game/Overlays/Changelog/ChangelogStreams.cs b/osu.Game/Overlays/Changelog/ChangelogStreams.cs index f0848188c8..b857a23653 100644 --- a/osu.Game/Overlays/Changelog/ChangelogStreams.cs +++ b/osu.Game/Overlays/Changelog/ChangelogStreams.cs @@ -2,13 +2,12 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; -using osu.Game.Graphics; -using osu.Game.Overlays.Changelog.Streams; +using osu.Game.Online.API.Requests.Responses; +using System; namespace osu.Game.Overlays.Changelog { @@ -17,8 +16,9 @@ namespace osu.Game.Overlays.Changelog private const float container_height = 106.5f; private const float container_margin_y = 20; private const float container_margin_x = 85; + public Action OnSelection; - public Bindable SelectedRelease = new Bindable(); + public APIChangelog SelectedRelease; public readonly FillFlowContainer BadgesContainer; @@ -45,31 +45,23 @@ namespace osu.Game.Overlays.Changelog Left = container_margin_x, Right = container_margin_x, }, - Children = new[] - { - new StreamBadge(StreamColour.STABLE, "Stable", "20180626.1", 16370, true), - new StreamBadge(StreamColour.BETA, "Beta", "20180626", 186), - new StreamBadge(StreamColour.LAZER, "Lazer", "2018.713.1"), - }, }, }; - BadgesContainer.OnLoadComplete = d => + // ok, so this is probably not the best. + // will need to reflect on this. + // do we need the changelog to be updateable? + BadgesContainer.OnUpdate = d => { foreach (StreamBadge streamBadge in BadgesContainer.Children) { streamBadge.OnActivation = () => { - SelectedRelease.Value = new ReleaseStreamInfo - { - DisplayVersion = streamBadge.DisplayVersion, - IsFeatured = streamBadge.IsFeatured, - Name = streamBadge.Name, - Users = streamBadge.Users, - }; + SelectedRelease = streamBadge.ChangelogEntry; foreach (StreamBadge item in BadgesContainer.Children) { - if (item.Name != streamBadge.Name) item.Deactivate(); + if (item.ChangelogEntry.Id != streamBadge.ChangelogEntry.Id) item.Deactivate(); } + OnSelection?.Invoke(); }; } }; @@ -80,9 +72,9 @@ namespace osu.Game.Overlays.Changelog // is this nullreference-safe for badgesContainer? foreach (StreamBadge streamBadge in BadgesContainer.Children) { - if (SelectedRelease.Value != null) + if (SelectedRelease != null) { - if (SelectedRelease.Value.Name != streamBadge.Name) + if (SelectedRelease.UpdateStream.Id != streamBadge.ChangelogEntry.Id) { streamBadge.Deactivate(); } @@ -94,7 +86,7 @@ namespace osu.Game.Overlays.Changelog protected override void OnHoverLost(InputState state) { - if (SelectedRelease.Value == null) + if (SelectedRelease == null) { foreach (StreamBadge streamBadge in BadgesContainer.Children) streamBadge.Activate(true); } diff --git a/osu.Game/Overlays/Changelog/ReleaseStreamInfo.cs b/osu.Game/Overlays/Changelog/ReleaseStreamInfo.cs deleted file mode 100644 index 2934ae8f94..0000000000 --- a/osu.Game/Overlays/Changelog/ReleaseStreamInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using osu.Game.IO.Serialization; - -namespace osu.Game.Overlays.Changelog -{ - [Serializable] - public class ReleaseStreamInfo : IJsonSerializable - { - public string Name; - public string DisplayVersion; - - public float Users; - - public bool IsFeatured; - } -} diff --git a/osu.Game/Overlays/Changelog/Streams/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs similarity index 81% rename from osu.Game/Overlays/Changelog/Streams/StreamBadge.cs rename to osu.Game/Overlays/Changelog/StreamBadge.cs index 8bd10dcbb8..578a95f583 100644 --- a/osu.Game/Overlays/Changelog/Streams/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -6,13 +6,14 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; +using osu.Game.Graphics; +using osu.Game.Online.API.Requests.Responses; using System; -namespace osu.Game.Overlays.Changelog.Streams +namespace osu.Game.Overlays.Changelog { public class StreamBadge : ClickableContainer { @@ -26,19 +27,13 @@ namespace osu.Game.Overlays.Changelog.Streams private readonly Header.LineBadge lineBadge; private SampleChannel sampleHover; - public readonly string Name; - public readonly string DisplayVersion; - public readonly bool IsFeatured; - public readonly float Users; + public readonly APIChangelog ChangelogEntry; - public StreamBadge(ColourInfo colour, string streamName, string streamBuild, float onlineUsers = 0, bool isFeatured = false) + public StreamBadge(APIChangelog changelogEntry) { - Name = streamName; - DisplayVersion = streamBuild; - IsFeatured = isFeatured; - Users = onlineUsers; + ChangelogEntry = changelogEntry; Height = badge_height; - Width = isFeatured ? badge_width * 2 : badge_width; + Width = ChangelogEntry.IsFeatured ? badge_width * 2 : badge_width; Margin = new MarginPadding(5); isActivated = true; Children = new Drawable[] @@ -52,7 +47,7 @@ namespace osu.Game.Overlays.Changelog.Streams { new SpriteText { - Text = streamName, + Text = ChangelogEntry.UpdateStream.DisplayName, Font = @"Exo2.0-Bold", TextSize = 16, Margin = new MarginPadding @@ -62,14 +57,14 @@ namespace osu.Game.Overlays.Changelog.Streams }, new SpriteText { - Text = streamBuild, + Text = ChangelogEntry.DisplayVersion, Font = @"Exo2.0-Light", TextSize = 21, }, new SpriteText { - Text = onlineUsers > 0 ? - string.Join(" ", onlineUsers.ToString("N0"), "users online"): + Text = ChangelogEntry.Users > 0 ? + string.Join(" ", ChangelogEntry.Users.ToString("N0"), "users online"): null, TextSize = 12, Font = @"Exo2.0-Regular", @@ -82,7 +77,7 @@ namespace osu.Game.Overlays.Changelog.Streams Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Width = 1, - Colour = colour, + Colour = StreamColour.FromStreamName(ChangelogEntry.UpdateStream.Name), RelativeSizeAxes = Axes.X, TransitionDuration = 600, }, diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index f928f9ee58..259036537b 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -3,6 +3,7 @@ using OpenTK; using OpenTK.Graphics; +using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -10,8 +11,10 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Input.Bindings; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Changelog; -using osu.Game.Overlays.Changelog.Streams; namespace osu.Game.Overlays { @@ -19,6 +22,9 @@ namespace osu.Game.Overlays { private readonly ChangelogHeader header; public readonly ChangelogStreams Streams; + private APIChangelog changelogEntry; + + private APIAccess api; protected readonly Color4 Purple = new Color4(191, 4, 255, 255); @@ -36,6 +42,8 @@ namespace osu.Game.Overlays Width = 0.85f; Masking = true; + ChangelogContent content; // told by appveyor to conver to local variable.. + EdgeEffect = new EdgeEffectParameters { Colour = Color4.Black.Opacity(0), @@ -64,25 +72,36 @@ namespace osu.Game.Overlays { header = new ChangelogHeader(), Streams = new ChangelogStreams(), + new ChangelogChart(), + // will need to default to day-sorted content + content = new ChangelogContent(), }, }, }, }; - Streams.SelectedRelease.ValueChanged += r => + Streams.OnSelection = () => { - if (Streams.SelectedRelease.Value != null) - header.ShowReleaseStream(r.Name, string.Join(" ", r.Name, r.DisplayVersion)); + if (Streams.SelectedRelease != null) + { + header.ChangelogEntry = Streams.SelectedRelease; + } + header.ShowReleaseStream(); + content.Clear(); + content.Add(new ChangelogContentGroup(Streams.SelectedRelease)); }; Streams.BadgesContainer.OnLoadComplete += d => { - header.OnListingActivated += () => - { - Streams.SelectedRelease.Value = null; - if (!Streams.IsHovered) - foreach (StreamBadge item in Streams.BadgesContainer.Children) item.Activate(true); - else - foreach (StreamBadge item in Streams.BadgesContainer.Children) item.Deactivate(); - }; + FetchChangelog(); + }; + header.OnListingActivated += () => + { + Streams.SelectedRelease = null; + content.Clear(); + // should add listing to content here + if (!Streams.IsHovered) + foreach (StreamBadge item in Streams.BadgesContainer.Children) item.Activate(true); + else + foreach (StreamBadge item in Streams.BadgesContainer.Children) item.Deactivate(); }; } @@ -120,5 +139,24 @@ namespace osu.Game.Overlays base.PopOut(); FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); } + + [BackgroundDependencyLoader] + private void load(APIAccess api) + { + this.api = api; + } + + public void FetchChangelog() + { + var req = new GetChangelogLatestBuildsRequest(); + req.Success += res => + { + foreach (APIChangelog item in res) + { + Streams.BadgesContainer.Add(new StreamBadge(item)); + } + }; + api.Queue(req); + } } } From a9299423cd79a08c36b8e2a0054e8e1f8cca3482 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Thu, 19 Jul 2018 21:49:13 +0200 Subject: [PATCH 0015/5608] Refactor2 --- .../Input/Bindings/GlobalActionContainer.cs | 2 -- osu.Game/OsuGame.cs | 11 +------- osu.Game/Overlays/Changelog/ChangelogChart.cs | 1 + .../Overlays/Changelog/ChangelogContent.cs | 7 ++++- .../Changelog/ChangelogContentGroup.cs | 5 ++-- .../Overlays/Changelog/ChangelogHeader.cs | 9 ++---- .../Overlays/Changelog/ChangelogStreams.cs | 28 ++++++++++--------- .../Changelog/Header/TextBadgePair.cs | 10 ++----- .../Changelog/Header/TextBadgePairRelease.cs | 5 +--- osu.Game/Overlays/Changelog/StreamBadge.cs | 2 -- osu.Game/Overlays/ChangelogOverlay.cs | 8 ++---- .../Toolbar/ToolbarChangelogButton.cs | 22 --------------- 12 files changed, 36 insertions(+), 74 deletions(-) delete mode 100644 osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 00857b9c9b..b21deff509 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -63,8 +63,6 @@ namespace osu.Game.Input.Bindings ToggleChat, [Description("Toggle social overlay")] ToggleSocial, - [Description("Toggle changelog")] - ToggleChangelog, [Description("Reset input settings")] ResetInputSettings, [Description("Toggle toolbar")] diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 3eb4faf6aa..557b6e4469 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -53,8 +53,6 @@ namespace osu.Game private DialogOverlay dialogOverlay; - private ChangelogOverlay changelog; - private DirectOverlay direct; private SocialOverlay social; @@ -112,8 +110,6 @@ namespace osu.Game public void ToggleDirect() => direct.ToggleVisibility(); - public void ToggleChangelog() => changelog.ToggleVisibility(); - /// /// Close all game-wide overlays. /// @@ -285,7 +281,6 @@ namespace osu.Game loadComponentSingleFile(screenshotManager, Add); //overlay elements - loadComponentSingleFile(changelog = new ChangelogOverlay { Depth = -1 }, mainContent.Add); loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, mainContent.Add); loadComponentSingleFile(social = new SocialOverlay { Depth = -1 }, mainContent.Add); loadComponentSingleFile(chat = new ChatOverlay { Depth = -1 }, mainContent.Add); @@ -320,7 +315,6 @@ namespace osu.Game dependencies.Cache(settings); dependencies.Cache(onscreenDisplay); dependencies.Cache(social); - dependencies.Cache(changelog); dependencies.Cache(direct); dependencies.Cache(chat); dependencies.Cache(userProfile); @@ -355,7 +349,7 @@ namespace osu.Game } // ensure only one of these overlays are open at once. - var singleDisplayOverlays = new OverlayContainer[] { chat, social, direct, changelog }; + var singleDisplayOverlays = new OverlayContainer[] { chat, social, direct }; overlays.AddRange(singleDisplayOverlays); foreach (var overlay in singleDisplayOverlays) @@ -465,9 +459,6 @@ namespace osu.Game case GlobalAction.ToggleSocial: social.ToggleVisibility(); return true; - case GlobalAction.ToggleChangelog: - changelog.ToggleVisibility(); - return true; case GlobalAction.ResetInputSettings: var sensitivity = frameworkConfig.GetBindable(FrameworkSetting.CursorSensitivity); diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index e885867c74..b113a509ec 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -10,6 +10,7 @@ using osu.Game.Graphics; namespace osu.Game.Overlays.Changelog { // maybe look to osu.Game.Screens.Play.SquareGraph for reference later + // placeholder json file: https://api.myjson.com/bins/10ye8a public class ChangelogChart : BufferedContainer { public ChangelogChart() diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index d10fe19942..325ec802d4 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -11,8 +11,13 @@ namespace osu.Game.Overlays.Changelog public ChangelogContent() { RelativeSizeAxes = Axes.X; - //AutoSizeAxes = Axes.Y; + AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; + Padding = new MarginPadding + { + Left = 70, + Right = 70, + }; } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 951cebb941..9675cf91f5 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -75,7 +75,8 @@ namespace osu.Game.Overlays.Changelog { Text = build.DisplayVersion, TextSize = 28, // web: 24, - Colour = StreamColour.STABLE, + Font = @"Exo2.0-Light", + Colour = StreamColour.FromStreamName(build.UpdateStream.Name), }, } }, @@ -90,7 +91,7 @@ namespace osu.Game.Overlays.Changelog new SpriteText { // do we need .ToUniversalTime() here? - // also, this is a temporary solution to weekdays in >localized< date strings + // also, this should be a temporary solution to weekdays in >localized< date strings Text = build.CreatedAt.Date.ToLongDateString().Replace(build.CreatedAt.ToString("dddd") + ", ", ""), TextSize = 17, // web: 14, Colour = OsuColour.FromHex(@"FD5"), diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 8332aeeaa4..a95d66158b 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Changelog { protected Color4 Purple = new Color4(191, 4, 255, 255); private readonly Sprite coverImage; - private readonly Sprite headerBadge; //50x50, margin-right: 20 + private readonly Sprite headerBadge; private readonly OsuSpriteText titleStream; private readonly TextBadgePairListing listing; private readonly TextBadgePairRelease releaseStream; @@ -46,10 +46,7 @@ namespace osu.Game.Overlays.Changelog coverImage = new Sprite { RelativeSizeAxes = Axes.Both, - Size = new Vector2(1), FillMode = FillMode.Fill, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, }, new Container // this is the line badge-Changelog-Stream { @@ -79,11 +76,11 @@ namespace osu.Game.Overlays.Changelog // this box has 2 functions: // - ensures the circle doesn't disappear on the X and Y edges - // - lessens the white "contamination" on the circle (due to smoothing) + // - gets rid of the white "contamination" on the circle (due to smoothing) + // (https://i.imgur.com/SMuvWBZ.png) new Box { RelativeSizeAxes = Axes.Both, - Size = new Vector2(1), Alpha = 0, AlwaysPresent = true, Colour = Purple, diff --git a/osu.Game/Overlays/Changelog/ChangelogStreams.cs b/osu.Game/Overlays/Changelog/ChangelogStreams.cs index b857a23653..aded31cb47 100644 --- a/osu.Game/Overlays/Changelog/ChangelogStreams.cs +++ b/osu.Game/Overlays/Changelog/ChangelogStreams.cs @@ -14,42 +14,44 @@ namespace osu.Game.Overlays.Changelog public class ChangelogStreams : Container { private const float container_height = 106.5f; - private const float container_margin_y = 20; - private const float container_margin_x = 85; + private const float padding_y = 20; + private const float padding_x = 85; public Action OnSelection; public APIChangelog SelectedRelease; + // not using SelectedRelease as a Bindable and then using .OnValueChange instead of OnSelection + // because it doesn't "refresh" the selection if the same stream is chosen public readonly FillFlowContainer BadgesContainer; public ChangelogStreams() { - Height = container_height; + // this should actually be resizeable (https://streamable.com/yw2ug) + // if not, with small width:height ratio it cuts off right-most content RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; Children = new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, - Size = new OpenTK.Vector2(1), Colour = new Color4(32, 24, 35, 255), }, BadgesContainer = new FillFlowContainer { - Direction = FillDirection.Horizontal, - RelativeSizeAxes = Axes.Both, - Margin = new MarginPadding + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { - Top = container_margin_y, - Bottom = container_margin_y, - Left = container_margin_x, - Right = container_margin_x, + Top = padding_y, + Bottom = padding_y, + Left = padding_x, + Right = padding_x, }, }, }; // ok, so this is probably not the best. - // will need to reflect on this. - // do we need the changelog to be updateable? + // how else can this be done? BadgesContainer.OnUpdate = d => { foreach (StreamBadge streamBadge in BadgesContainer.Children) diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index a888c436cf..c14414c6c4 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -61,9 +61,8 @@ namespace osu.Game.Overlays.Changelog.Header .MoveToY(0, duration, easing) .FadeIn(duration, easing); - // since using .finally/.oncomplete after first fadeout made the badge - // not hide sometimes in visual tests(because FinishTransforms()/CancelTransforms() - // didn't apply to transforms that come after the .finally), I'm using a scheduler here + // since using .finally/.oncomplete after first fadeout made the badge not hide + // sometimes in visual tests (https://streamable.com/0qssq), I'm using a scheduler here Scheduler.AddDelayed(() => { if (!string.IsNullOrEmpty(displayText)) Text.Text = displayText; @@ -79,10 +78,8 @@ namespace osu.Game.Overlays.Changelog.Header { Text = new SpriteText { - TextSize = 21, // web is 16, but here it looks too small? + TextSize = 21, // web: 16, Text = displayText, - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, Margin = new MarginPadding { Top = 5, @@ -91,7 +88,6 @@ namespace osu.Game.Overlays.Changelog.Header }, LineBadge = new LineBadge(startCollapsed) { - Width = 1, Colour = badgeColour, RelativeSizeAxes = Axes.X, } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs index 2186043035..339f9f26d6 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs @@ -17,10 +17,7 @@ namespace osu.Game.Overlays.Changelog.Header Text.Alpha = 0; } - public void SetText(string displayText) - { - Text.Text = displayText; - } + public void SetText(string displayText) => Text.Text = displayText; public void Activate(string displayText = null) { diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 578a95f583..4fa9b2de88 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -76,10 +76,8 @@ namespace osu.Game.Overlays.Changelog { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Width = 1, Colour = StreamColour.FromStreamName(ChangelogEntry.UpdateStream.Name), RelativeSizeAxes = Axes.X, - TransitionDuration = 600, }, }; } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 259036537b..7723ab7659 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -79,6 +79,7 @@ namespace osu.Game.Overlays }, }, }; + OnLoadComplete += d => FetchChangelog(); // is i Streams.OnSelection = () => { if (Streams.SelectedRelease != null) @@ -86,13 +87,9 @@ namespace osu.Game.Overlays header.ChangelogEntry = Streams.SelectedRelease; } header.ShowReleaseStream(); - content.Clear(); + content.Clear(); // this should probably happen with some transition content.Add(new ChangelogContentGroup(Streams.SelectedRelease)); }; - Streams.BadgesContainer.OnLoadComplete += d => - { - FetchChangelog(); - }; header.OnListingActivated += () => { Streams.SelectedRelease = null; @@ -151,6 +148,7 @@ namespace osu.Game.Overlays var req = new GetChangelogLatestBuildsRequest(); req.Success += res => { + Streams.BadgesContainer.Clear(); foreach (APIChangelog item in res) { Streams.BadgesContainer.Add(new StreamBadge(item)); diff --git a/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs deleted file mode 100644 index db4fd4ba07..0000000000 --- a/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Allocation; -using osu.Game.Graphics; - -namespace osu.Game.Overlays.Toolbar -{ - public class ToolbarChangelogButton : ToolbarOverlayToggleButton - { - public ToolbarChangelogButton() - { - SetIcon(FontAwesome.fa_list); - } - - [BackgroundDependencyLoader(true)] - private void load(ChangelogOverlay changelog) - { - StateContainer = changelog; - } - } -} From a857999950aa380f1d0d15557dfc89c9d00b6a69 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 00:52:50 +0200 Subject: [PATCH 0016/5608] Refactor3 --- osu.Game.Tests/Visual/TestCaseChangelog.cs | 21 +++++++++++++--- .../UserInterface/TooltipIconButton.cs | 25 +++++++++---------- .../API/Requests/Responses/APIChangelog.cs | 6 ----- .../Overlays/Changelog/ChangelogStreams.cs | 15 +++++------ .../Changelog/Header/TextBadgePair.cs | 6 +++-- .../Changelog/Header/TextBadgePairListing.cs | 3 ++- .../Changelog/Header/TextBadgePairRelease.cs | 7 +++--- osu.Game/Overlays/Changelog/StreamBadge.cs | 5 ++-- osu.Game/Overlays/ChangelogOverlay.cs | 19 ++++++-------- 9 files changed, 56 insertions(+), 51 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseChangelog.cs b/osu.Game.Tests/Visual/TestCaseChangelog.cs index 894b117118..ea6aa8086f 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelog.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelog.cs @@ -23,7 +23,8 @@ namespace osu.Game.Tests.Visual AddStep(@"Show", changelog.Show); AddRepeatStep(@"Toggle Release Stream", () => { - if (isLoaded) changelog.Streams.BadgesContainer.Children[index].Activate(); + if (isLoaded) + changelog.Streams.BadgesContainer.Children[index].Activate(); indexIncrement(); }, 6); AddStep(@"Listing", changelog.ActivateListing); @@ -31,7 +32,8 @@ namespace osu.Game.Tests.Visual AddWaitStep(3); AddStep(@"Show with Release Stream", () => { - if (isLoaded) changelog.Streams.BadgesContainer.Children[index].Activate(); + if (isLoaded) + changelog.Streams.BadgesContainer.Children[index].Activate(); changelog.Show(); indexIncrement(); }); @@ -48,7 +50,8 @@ namespace osu.Game.Tests.Visual AddWaitStep(3); AddStep(@"Activate release", () => { - if (isLoaded) changelog.Streams.BadgesContainer.Children[index].Activate(); + if (isLoaded) + changelog.Streams.BadgesContainer.Children[index].Activate(); indexIncrement(); }); AddStep(@"Show with listing", () => @@ -56,6 +59,18 @@ namespace osu.Game.Tests.Visual changelog.ActivateListing(); changelog.Show(); }); + AddStep(@"Activate Release", () => + { + if (isLoaded) + changelog.Streams.BadgesContainer.Children[index].Activate(); + }); + AddStep(@"Activate Listing", changelog.ActivateListing); + AddStep(@"Activate Release", () => + { + if (isLoaded) + changelog.Streams.BadgesContainer.Children[index].Activate(); + indexIncrement(); + }); } } } diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index 918e203bf4..7614c4510a 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -22,22 +22,21 @@ namespace osu.Game.Graphics.UserInterface public TooltipIconButton() { Children = new Drawable[] + { + new Box { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - }, - icon = new SpriteIcon - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Size = new Vector2(18), - } - }; + RelativeSizeAxes = Axes.Both, + Alpha = 0, + }, + icon = new SpriteIcon + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(18), + } + }; } - public string TooltipText { get; set; } } } diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs index f0dcafdc04..b133888056 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs @@ -27,12 +27,6 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("created_at")] public DateTimeOffset CreatedAt { get; set; } - [JsonProperty("disqus_id")] - public string DisqusId { get; set; } - - [JsonProperty("disqus_title")] - public string DisqusTitle { get; set; } - [JsonProperty("update_stream")] public UpdateStream UpdateStream { get; set; } diff --git a/osu.Game/Overlays/Changelog/ChangelogStreams.cs b/osu.Game/Overlays/Changelog/ChangelogStreams.cs index aded31cb47..01c57b8214 100644 --- a/osu.Game/Overlays/Changelog/ChangelogStreams.cs +++ b/osu.Game/Overlays/Changelog/ChangelogStreams.cs @@ -60,9 +60,8 @@ namespace osu.Game.Overlays.Changelog { SelectedRelease = streamBadge.ChangelogEntry; foreach (StreamBadge item in BadgesContainer.Children) - { - if (item.ChangelogEntry.Id != streamBadge.ChangelogEntry.Id) item.Deactivate(); - } + if (item.ChangelogEntry.Id != streamBadge.ChangelogEntry.Id) + item.Deactivate(); OnSelection?.Invoke(); }; } @@ -77,11 +76,10 @@ namespace osu.Game.Overlays.Changelog if (SelectedRelease != null) { if (SelectedRelease.UpdateStream.Id != streamBadge.ChangelogEntry.Id) - { streamBadge.Deactivate(); - } } - else streamBadge.Deactivate(); + else + streamBadge.Deactivate(); } return base.OnHover(state); } @@ -89,9 +87,8 @@ namespace osu.Game.Overlays.Changelog protected override void OnHoverLost(InputState state) { if (SelectedRelease == null) - { - foreach (StreamBadge streamBadge in BadgesContainer.Children) streamBadge.Activate(true); - } + foreach (StreamBadge streamBadge in BadgesContainer.Children) + streamBadge.Activate(true); base.OnHoverLost(state); } } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index c14414c6c4..6256c52be2 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -44,7 +44,8 @@ namespace osu.Game.Overlays.Changelog.Header public void ShowText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) { LineBadge.IsCollapsed = false; - if (!string.IsNullOrEmpty(displayText)) Text.Text = displayText; + if (!string.IsNullOrEmpty(displayText)) + Text.Text = displayText; Text.MoveToY(0, duration, easing) .FadeIn(duration, easing); } @@ -111,7 +112,8 @@ namespace osu.Game.Overlays.Changelog.Header protected override bool OnHover(InputState state) { - if (!IsActivated) sampleHover?.Play(); + if (!IsActivated) + sampleHover?.Play(); return base.OnHover(state); } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs index eaf7e1289b..425b4b111a 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -63,7 +63,8 @@ namespace osu.Game.Overlays.Changelog.Header protected override void OnHoverLost(InputState state) { - if (IsActivated == false) LineBadge.ResizeHeightTo(1, LineBadge.TransitionDuration, Easing.Out); + if (!IsActivated) + LineBadge.ResizeHeightTo(1, LineBadge.TransitionDuration, Easing.Out); base.OnHoverLost(state); } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs index 339f9f26d6..32a76670f0 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs @@ -23,13 +23,12 @@ namespace osu.Game.Overlays.Changelog.Header { if (IsActivated) { - if (displayText != Text.Text) ChangeText(transition_duration, displayText); + if (displayText != Text.Text) + ChangeText(transition_duration, displayText); } else - { ShowText(transition_duration, displayText); - IsActivated = true; - } + IsActivated = true; SampleActivate?.Play(); OnActivation?.Invoke(); } diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 4fa9b2de88..7e367a63fa 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -64,7 +64,7 @@ namespace osu.Game.Overlays.Changelog new SpriteText { Text = ChangelogEntry.Users > 0 ? - string.Join(" ", ChangelogEntry.Users.ToString("N0"), "users online"): + string.Format($"{ChangelogEntry.Users:N0} users online") : null, TextSize = 12, Font = @"Exo2.0-Regular", @@ -87,7 +87,8 @@ namespace osu.Game.Overlays.Changelog isActivated = true; this.FadeIn(transition_duration); lineBadge.IsCollapsed = false; - if (!withoutHeaderUpdate) OnActivation?.Invoke(); + if (!withoutHeaderUpdate) + OnActivation?.Invoke(); } public void Deactivate() diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 7723ab7659..081b501cad 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -96,9 +96,11 @@ namespace osu.Game.Overlays content.Clear(); // should add listing to content here if (!Streams.IsHovered) - foreach (StreamBadge item in Streams.BadgesContainer.Children) item.Activate(true); + foreach (StreamBadge item in Streams.BadgesContainer.Children) + item.Activate(true); else - foreach (StreamBadge item in Streams.BadgesContainer.Children) item.Deactivate(); + foreach (StreamBadge item in Streams.BadgesContainer.Children) + item.Deactivate(); }; } @@ -112,13 +114,10 @@ namespace osu.Game.Overlays switch (action) { case GlobalAction.Back: - if (header.IsListingActivated()) State = Visibility.Hidden; - - // the problem here is that when hovering over the builds' container - // and pressing back, they don't lower their opacity they're rehovered on - else header.ActivateListing(); - return true; - case GlobalAction.Select: + if (header.IsListingActivated()) + State = Visibility.Hidden; + else + header.ActivateListing(); return true; } @@ -150,9 +149,7 @@ namespace osu.Game.Overlays { Streams.BadgesContainer.Clear(); foreach (APIChangelog item in res) - { Streams.BadgesContainer.Add(new StreamBadge(item)); - } }; api.Queue(req); } From 1857c91647caa6acf62b35b07b207b1b7f20b0f4 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 11:20:01 +0200 Subject: [PATCH 0017/5608] Expand APIChangelog; Normalize its line endings --- .../API/Requests/Responses/APIChangelog.cs | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs index b133888056..f4e4760012 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs @@ -32,6 +32,78 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("changelog_entries")] public List ChangelogEntries { get; set; } + + [JsonProperty("versions")] + public Versions Versions { get; set; } + } + + public class Versions + { + [JsonProperty("next")] + public APIChangelog Next { get; set; } + + [JsonProperty("previous")] + public APIChangelog Previous { get; set; } + } + + public class ChangelogEntry + { + [JsonProperty("id")] + public long Id { get; set; } + + [JsonProperty("repository")] + public string Repository { get; set; } + + [JsonProperty("github_pull_request_id")] + public long GithubPullRequestId { get; set; } + + [JsonProperty("github_url")] + public string GithubUrl { get; set; } + + [JsonProperty("url")] + public object Url { get; set; } + + [JsonProperty("type")] + public string Type { get; set; } + + [JsonProperty("category")] + public string Category { get; set; } + + [JsonProperty("title")] + public string Title { get; set; } + + [JsonProperty("message_html")] + public string MessageHtml { get; set; } + + [JsonProperty("major")] + public bool Major { get; set; } + + [JsonProperty("created_at")] + public DateTimeOffset CreatedAt { get; set; } + + [JsonProperty("github_user")] + public GithubUser GithubUser { get; set; } + } + + public partial class GithubUser + { + [JsonProperty("id")] + public long Id { get; set; } + + [JsonProperty("display_name")] + public string DisplayName { get; set; } + + [JsonProperty("github_url")] + public string GithubUrl { get; set; } + + [JsonProperty("osu_username")] + public string OsuUsername { get; set; } + + [JsonProperty("user_id")] + public long? UserId { get; set; } + + [JsonProperty("user_url")] + public string UserUrl { get; set; } } public class UpdateStream From c7669b21282e7eecdb486f43a5fc3131633657af Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 12:22:31 +0200 Subject: [PATCH 0018/5608] Add build-scoped requests; Add OnClick to TooltipIconButton; Actions on pressing previous/next in builds --- .../UserInterface/TooltipIconButton.cs | 9 +++++++++ .../API/Requests/GetChangelogBuildRequest.cs | 20 +++++++++++++++++++ .../Changelog/ChangelogContentGroup.cs | 8 ++++---- 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index 7614c4510a..5617dc5b44 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -5,13 +5,16 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; using osu.Game.Graphics.Containers; +using System; namespace osu.Game.Graphics.UserInterface { public class TooltipIconButton : OsuClickableContainer, IHasTooltip { private readonly SpriteIcon icon; + public Action OnPressed; public FontAwesome Icon { @@ -37,6 +40,12 @@ namespace osu.Game.Graphics.UserInterface }; } + protected override bool OnClick(InputState state) + { + OnPressed?.Invoke(); + return base.OnClick(state); + } + public string TooltipText { get; set; } } } diff --git a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs new file mode 100644 index 0000000000..64bc6b4b59 --- /dev/null +++ b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Online.API.Requests +{ + public class GetChangelogBuildRequest : APIRequest + { + private string url; + /// This will need to be changed to "long Id" + /// Placeholder for testing + GetChangelogBuildRequest(string url) + { + this.url = url; + } + protected override string Uri => @""; + protected override string Target => url; + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 9675cf91f5..07577e18c1 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -8,12 +8,13 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; +using System; namespace osu.Game.Overlays.Changelog { public class ChangelogContentGroup : FillFlowContainer { - // will porobably depend in some way on #1692 (https://github.com/ppy/osu-framework/pull/1692) + public Action NextRequested, PreviousRequested; // need to keep in mind it looks different on Listing (one contains all builds from a date) // and when a stream is selected (looks like now) public ChangelogContentGroup(APIChangelog build) @@ -45,10 +46,8 @@ namespace osu.Game.Overlays.Changelog { Icon = FontAwesome.fa_chevron_left, Size = new Vector2(24), - // how do we link to previous/next builds? - // I'm thinking some linked list, but how do we make that - // from the available API data TooltipText = "Previous", + OnPressed = PreviousRequested, }, new FillFlowContainer { @@ -85,6 +84,7 @@ namespace osu.Game.Overlays.Changelog Icon = FontAwesome.fa_chevron_right, Size = new Vector2(24), TooltipText = "Next", + OnPressed = NextRequested, }, } }, From 1b3010a1b534a9675582343f82c991cf9a2e704f Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 12:33:44 +0200 Subject: [PATCH 0019/5608] Remove accidental partial modifier in APIChangelog --- osu.Game/Online/API/Requests/Responses/APIChangelog.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs index f4e4760012..02f9bd763d 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs @@ -85,7 +85,7 @@ namespace osu.Game.Online.API.Requests.Responses public GithubUser GithubUser { get; set; } } - public partial class GithubUser + public class GithubUser { [JsonProperty("id")] public long Id { get; set; } From 227394925a0603905989ba47f4e8a112d313ac3e Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 13:51:31 +0200 Subject: [PATCH 0020/5608] Add neighboring builds handling; + provoke angry AppVeyor --- .../API/Requests/GetChangelogBuildRequest.cs | 16 +++--- .../Overlays/Changelog/ChangelogContent.cs | 54 +++++++++++++++++++ .../Changelog/ChangelogContentGroup.cs | 4 +- osu.Game/Overlays/Changelog/StreamBadge.cs | 2 +- osu.Game/Overlays/ChangelogOverlay.cs | 3 +- 5 files changed, 67 insertions(+), 12 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs index 64bc6b4b59..c4ddb9a0cc 100644 --- a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs @@ -7,14 +7,16 @@ namespace osu.Game.Online.API.Requests { public class GetChangelogBuildRequest : APIRequest { - private string url; - /// This will need to be changed to "long Id" - /// Placeholder for testing - GetChangelogBuildRequest(string url) + private readonly string name; + private readonly string version; + + public GetChangelogBuildRequest(string streamName, string buildVersion) { - this.url = url; + name = streamName; + version = buildVersion; } - protected override string Uri => @""; - protected override string Target => url; + + //protected override string Target => $@"changelog/{name}/{version}"; + protected override string Uri => @"https://api.myjson.com/bins/ya5q2"; // for testing } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 325ec802d4..9b35f51721 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -1,13 +1,20 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Changelog { public class ChangelogContent : FillFlowContainer { + private APIChangelog currentBuild; + private APIAccess api; + public ChangelogContent() { RelativeSizeAxes = Axes.X; @@ -19,5 +26,52 @@ namespace osu.Game.Overlays.Changelog Right = 70, }; } + + public override void Add(ChangelogContentGroup changelogContentGroup) + { + changelogContentGroup.PreviousRequested = ShowPrevious; + changelogContentGroup.NextRequested = ShowNext; + base.Add(changelogContentGroup); + } + + public void ShowBuild(APIChangelog changelog) + { + Clear(); + Add(new ChangelogContentGroup(changelog)); + FetchChangelogBuild(changelog); + } + + private void ShowNext() + { + if (currentBuild.Versions.Next != null) + { + Clear(); + Add(new ChangelogContentGroup(currentBuild.Versions.Next)); + FetchChangelogBuild(currentBuild.Versions.Next); + } + } + + private void ShowPrevious() + { + if (currentBuild.Versions.Previous != null) + { + Clear(); + Add(new ChangelogContentGroup(currentBuild.Versions.Previous)); + FetchChangelogBuild(currentBuild.Versions.Previous); + } + } + + [BackgroundDependencyLoader] + private void load(APIAccess api) + { + this.api = api; + } + + private void FetchChangelogBuild(APIChangelog build) + { + var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); + req.Success += res => currentBuild = res; + api.Queue(req); + } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 07577e18c1..4826379682 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays.Changelog Icon = FontAwesome.fa_chevron_left, Size = new Vector2(24), TooltipText = "Previous", - OnPressed = PreviousRequested, + OnPressed = () => PreviousRequested(), }, new FillFlowContainer { @@ -84,7 +84,7 @@ namespace osu.Game.Overlays.Changelog Icon = FontAwesome.fa_chevron_right, Size = new Vector2(24), TooltipText = "Next", - OnPressed = NextRequested, + OnPressed = () => NextRequested(), }, } }, diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 7e367a63fa..ba98e0a4f7 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -64,7 +64,7 @@ namespace osu.Game.Overlays.Changelog new SpriteText { Text = ChangelogEntry.Users > 0 ? - string.Format($"{ChangelogEntry.Users:N0} users online") : + $"{ChangelogEntry.Users:N0} users online" : null, TextSize = 12, Font = @"Exo2.0-Regular", diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 081b501cad..417b4f7a30 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -87,8 +87,7 @@ namespace osu.Game.Overlays header.ChangelogEntry = Streams.SelectedRelease; } header.ShowReleaseStream(); - content.Clear(); // this should probably happen with some transition - content.Add(new ChangelogContentGroup(Streams.SelectedRelease)); + content.ShowBuild(Streams.SelectedRelease); }; header.OnListingActivated += () => { From 02a8fb2154e62a8566a0c3b8c3c1c710335a39a5 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 15:48:20 +0200 Subject: [PATCH 0021/5608] Update comments; Improve neighboring builds handling; Apply fixes to things pointed out by AppVeyor --- .../UserInterface/TooltipIconButton.cs | 9 ------- .../API/Requests/GetChangelogBuildRequest.cs | 14 +++++----- .../GetChangelogLatestBuildsRequest.cs | 7 ++--- .../API/Requests/GetChangelogRequest.cs | 4 +-- .../Overlays/Changelog/ChangelogContent.cs | 26 ++++++++++++------- .../Changelog/ChangelogContentGroup.cs | 10 +++---- .../Overlays/Changelog/ChangelogHeader.cs | 8 +++--- .../Overlays/Changelog/ChangelogStreams.cs | 3 --- osu.Game/Overlays/ChangelogOverlay.cs | 5 ++-- 9 files changed, 37 insertions(+), 49 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index 5617dc5b44..7614c4510a 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -5,16 +5,13 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; using osu.Game.Graphics.Containers; -using System; namespace osu.Game.Graphics.UserInterface { public class TooltipIconButton : OsuClickableContainer, IHasTooltip { private readonly SpriteIcon icon; - public Action OnPressed; public FontAwesome Icon { @@ -40,12 +37,6 @@ namespace osu.Game.Graphics.UserInterface }; } - protected override bool OnClick(InputState state) - { - OnPressed?.Invoke(); - return base.OnClick(state); - } - public string TooltipText { get; set; } } } diff --git a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs index c4ddb9a0cc..5d4d3b860c 100644 --- a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs @@ -7,14 +7,14 @@ namespace osu.Game.Online.API.Requests { public class GetChangelogBuildRequest : APIRequest { - private readonly string name; - private readonly string version; + //private readonly string name; + //private readonly string version; - public GetChangelogBuildRequest(string streamName, string buildVersion) - { - name = streamName; - version = buildVersion; - } + //public GetChangelogBuildRequest(string streamName, string buildVersion) + //{ + // name = streamName; + // version = buildVersion; + //} //protected override string Target => $@"changelog/{name}/{version}"; protected override string Uri => @"https://api.myjson.com/bins/ya5q2"; // for testing diff --git a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs index 845760f2e4..962c8eab15 100644 --- a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs @@ -6,12 +6,9 @@ using System.Collections.Generic; namespace osu.Game.Online.API.Requests { - /// - /// Obviously a placeholder - /// public class GetChangelogLatestBuildsRequest : APIRequest> { - protected override string Uri => Target; - protected override string Target => @"https://api.myjson.com/bins/16waui"; + //protected override string Target => @"changelog"; + protected override string Uri => @"https://api.myjson.com/bins/16waui"; // for testing } } diff --git a/osu.Game/Online/API/Requests/GetChangelogRequest.cs b/osu.Game/Online/API/Requests/GetChangelogRequest.cs index 652e638ab8..6ddff7052e 100644 --- a/osu.Game/Online/API/Requests/GetChangelogRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogRequest.cs @@ -7,7 +7,7 @@ namespace osu.Game.Online.API.Requests { public class GetChangelogRequest : APIRequest { - protected override string Uri => Target; - protected override string Target => "https://api.myjson.com/bins/6zv2i"; + //protected override string Target => @"changelog"; + protected override string Uri => @"https://api.myjson.com/bins/6zv2i"; // for testing } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 9b35f51721..23a1c54b51 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -29,8 +29,11 @@ namespace osu.Game.Overlays.Changelog public override void Add(ChangelogContentGroup changelogContentGroup) { - changelogContentGroup.PreviousRequested = ShowPrevious; - changelogContentGroup.NextRequested = ShowNext; + if (changelogContentGroup != null) + { + changelogContentGroup.PreviousRequested = showPrevious; + changelogContentGroup.NextRequested = showNext; + } base.Add(changelogContentGroup); } @@ -38,26 +41,29 @@ namespace osu.Game.Overlays.Changelog { Clear(); Add(new ChangelogContentGroup(changelog)); - FetchChangelogBuild(changelog); + //fetchChangelogBuild(changelog); + fetchChangelogBuild(); } - private void ShowNext() + private void showNext() { if (currentBuild.Versions.Next != null) { Clear(); Add(new ChangelogContentGroup(currentBuild.Versions.Next)); - FetchChangelogBuild(currentBuild.Versions.Next); + //fetchChangelogBuild(currentBuild.Versions.Next); + fetchChangelogBuild(); } } - private void ShowPrevious() + private void showPrevious() { if (currentBuild.Versions.Previous != null) { Clear(); Add(new ChangelogContentGroup(currentBuild.Versions.Previous)); - FetchChangelogBuild(currentBuild.Versions.Previous); + //fetchChangelogBuild(currentBuild.Versions.Previous); + fetchChangelogBuild(); } } @@ -67,9 +73,11 @@ namespace osu.Game.Overlays.Changelog this.api = api; } - private void FetchChangelogBuild(APIChangelog build) + //private void fetchChangelogBuild(APIChangelog build) + private void fetchChangelogBuild() { - var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); + //var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); + var req = new GetChangelogBuildRequest(); req.Success += res => currentBuild = res; api.Queue(req); } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 4826379682..91b6ba0134 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -15,8 +15,6 @@ namespace osu.Game.Overlays.Changelog public class ChangelogContentGroup : FillFlowContainer { public Action NextRequested, PreviousRequested; - // need to keep in mind it looks different on Listing (one contains all builds from a date) - // and when a stream is selected (looks like now) public ChangelogContentGroup(APIChangelog build) { RelativeSizeAxes = Axes.X; @@ -47,7 +45,7 @@ namespace osu.Game.Overlays.Changelog Icon = FontAwesome.fa_chevron_left, Size = new Vector2(24), TooltipText = "Previous", - OnPressed = () => PreviousRequested(), + Action = () => PreviousRequested(), }, new FillFlowContainer { @@ -65,7 +63,7 @@ namespace osu.Game.Overlays.Changelog TextSize = 28, // web: 24, Font = @"Exo2.0-Medium", }, - new SpriteText // a space... + new SpriteText { Text = " ", TextSize = 28, @@ -84,7 +82,7 @@ namespace osu.Game.Overlays.Changelog Icon = FontAwesome.fa_chevron_right, Size = new Vector2(24), TooltipText = "Next", - OnPressed = () => NextRequested(), + Action = () => NextRequested(), }, } }, @@ -105,6 +103,6 @@ namespace osu.Game.Overlays.Changelog }, }; } - //public ChangelogContentGroup(DateTimeOffset date) { } + //public ChangelogContentGroup() { } // for listing } } diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index a95d66158b..1c3f6f0853 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Changelog RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fill, }, - new Container // this is the line badge-Changelog-Stream + new Container { Height = title_height, Anchor = Anchor.BottomLeft, @@ -56,7 +56,7 @@ namespace osu.Game.Overlays.Changelog Y = -version_height, Children = new Drawable[] { - new CircularContainer // a purple circle + new CircularContainer { X = icon_margin, Masking = true, @@ -131,8 +131,6 @@ namespace osu.Game.Overlays.Changelog { Top = 10, Left = 7, - // + chevron size, and account for gained space on left by - // listing's font draw width being smaller Right = 18, Bottom = 15, }, @@ -153,7 +151,7 @@ namespace osu.Game.Overlays.Changelog releaseStream = new TextBadgePairRelease(Purple, "Lazer") }, }, - new Box // purple line + new Box { Colour = Purple, RelativeSizeAxes = Axes.X, diff --git a/osu.Game/Overlays/Changelog/ChangelogStreams.cs b/osu.Game/Overlays/Changelog/ChangelogStreams.cs index 01c57b8214..cc2e1f3f31 100644 --- a/osu.Game/Overlays/Changelog/ChangelogStreams.cs +++ b/osu.Game/Overlays/Changelog/ChangelogStreams.cs @@ -26,8 +26,6 @@ namespace osu.Game.Overlays.Changelog public ChangelogStreams() { - // this should actually be resizeable (https://streamable.com/yw2ug) - // if not, with small width:height ratio it cuts off right-most content RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Children = new Drawable[] @@ -70,7 +68,6 @@ namespace osu.Game.Overlays.Changelog protected override bool OnHover(InputState state) { - // is this nullreference-safe for badgesContainer? foreach (StreamBadge streamBadge in BadgesContainer.Children) { if (SelectedRelease != null) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 417b4f7a30..d98db9de94 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -42,7 +42,7 @@ namespace osu.Game.Overlays Width = 0.85f; Masking = true; - ChangelogContent content; // told by appveyor to conver to local variable.. + ChangelogContent content; // told by appveyor to convert to local variable.. EdgeEffect = new EdgeEffectParameters { @@ -73,13 +73,12 @@ namespace osu.Game.Overlays header = new ChangelogHeader(), Streams = new ChangelogStreams(), new ChangelogChart(), - // will need to default to day-sorted content content = new ChangelogContent(), }, }, }, }; - OnLoadComplete += d => FetchChangelog(); // is i + OnLoadComplete += d => FetchChangelog(); Streams.OnSelection = () => { if (Streams.SelectedRelease != null) From c50c946b352d130b10d378850cf1c2f2cdf8a03e Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 17:24:21 +0200 Subject: [PATCH 0022/5608] Make chevrons updateable --- .../Overlays/Changelog/ChangelogContent.cs | 42 +++++++++---------- .../Changelog/ChangelogContentGroup.cs | 24 ++++++++++- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 23a1c54b51..16e9d1a074 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -14,6 +14,7 @@ namespace osu.Game.Overlays.Changelog { private APIChangelog currentBuild; private APIAccess api; + private ChangelogContentGroup changelogContentGroup; public ChangelogContent() { @@ -27,20 +28,19 @@ namespace osu.Game.Overlays.Changelog }; } - public override void Add(ChangelogContentGroup changelogContentGroup) + private void add(APIChangelog changelogBuild) { - if (changelogContentGroup != null) - { - changelogContentGroup.PreviousRequested = showPrevious; - changelogContentGroup.NextRequested = showNext; - } - base.Add(changelogContentGroup); + Add(changelogContentGroup = new ChangelogContentGroup(changelogBuild) + { + PreviousRequested = showPrevious, + NextRequested = showNext, + }); } public void ShowBuild(APIChangelog changelog) { Clear(); - Add(new ChangelogContentGroup(changelog)); + add(changelog); //fetchChangelogBuild(changelog); fetchChangelogBuild(); } @@ -48,23 +48,19 @@ namespace osu.Game.Overlays.Changelog private void showNext() { if (currentBuild.Versions.Next != null) - { - Clear(); - Add(new ChangelogContentGroup(currentBuild.Versions.Next)); - //fetchChangelogBuild(currentBuild.Versions.Next); - fetchChangelogBuild(); - } + ShowBuild(currentBuild.Versions.Next); } private void showPrevious() { if (currentBuild.Versions.Previous != null) - { - Clear(); - Add(new ChangelogContentGroup(currentBuild.Versions.Previous)); - //fetchChangelogBuild(currentBuild.Versions.Previous); - fetchChangelogBuild(); - } + ShowBuild(currentBuild.Versions.Previous); + } + + private void updateChevronTooltips() + { + changelogContentGroup.UpdateChevronTooltips(currentBuild.Versions.Previous?.DisplayVersion, + currentBuild.Versions.Next?.DisplayVersion); } [BackgroundDependencyLoader] @@ -78,7 +74,11 @@ namespace osu.Game.Overlays.Changelog { //var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); var req = new GetChangelogBuildRequest(); - req.Success += res => currentBuild = res; + req.Success += res => + { + currentBuild = res; + updateChevronTooltips(); + }; api.Queue(req); } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 91b6ba0134..5b22b360e5 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -14,6 +14,8 @@ namespace osu.Game.Overlays.Changelog { public class ChangelogContentGroup : FillFlowContainer { + private readonly TooltipIconButton chevronPrevious, chevronNext; + public Action NextRequested, PreviousRequested; public ChangelogContentGroup(APIChangelog build) { @@ -40,7 +42,7 @@ namespace osu.Game.Overlays.Changelog }, Children = new Drawable[] { - new TooltipIconButton + chevronPrevious = new TooltipIconButton { Icon = FontAwesome.fa_chevron_left, Size = new Vector2(24), @@ -77,7 +79,7 @@ namespace osu.Game.Overlays.Changelog }, } }, - new TooltipIconButton + chevronNext = new TooltipIconButton { Icon = FontAwesome.fa_chevron_right, Size = new Vector2(24), @@ -103,6 +105,24 @@ namespace osu.Game.Overlays.Changelog }, }; } + + public void UpdateChevronTooltips(string previousVersion, string nextVersion) + { + if (string.IsNullOrEmpty(previousVersion)) + chevronPrevious.IsEnabled = false; + else + { + chevronPrevious.TooltipText = previousVersion; + chevronPrevious.IsEnabled = true; + } + if (string.IsNullOrEmpty(nextVersion)) + chevronNext.IsEnabled = false; + else + { + chevronNext.TooltipText = nextVersion; + chevronNext.IsEnabled = true; + } + } //public ChangelogContentGroup() { } // for listing } } From b049ffa11d0c1b879ab36d18b1cb31de72cdb447 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 18:23:25 +0200 Subject: [PATCH 0023/5608] Improve fake-api --- .../API/Requests/GetChangelogBuildRequest.cs | 18 +++++++++--------- .../GetChangelogLatestBuildsRequest.cs | 4 ++-- .../Online/API/Requests/GetChangelogRequest.cs | 4 ++-- .../Overlays/Changelog/ChangelogContent.cs | 9 +++------ .../Changelog/ChangelogContentGroup.cs | 14 ++------------ 5 files changed, 18 insertions(+), 31 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs index 5d4d3b860c..2338b90865 100644 --- a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs @@ -7,16 +7,16 @@ namespace osu.Game.Online.API.Requests { public class GetChangelogBuildRequest : APIRequest { - //private readonly string name; - //private readonly string version; + private readonly string name; + private readonly string version; - //public GetChangelogBuildRequest(string streamName, string buildVersion) - //{ - // name = streamName; - // version = buildVersion; - //} + public GetChangelogBuildRequest(string streamName, string buildVersion) + { + name = streamName; + version = buildVersion; + } - //protected override string Target => $@"changelog/{name}/{version}"; - protected override string Uri => @"https://api.myjson.com/bins/ya5q2"; // for testing + protected override string Target => $@"changelog/{name}/{version}"; + protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}"; // for testing } } diff --git a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs index 962c8eab15..7940fd8ff5 100644 --- a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs @@ -8,7 +8,7 @@ namespace osu.Game.Online.API.Requests { public class GetChangelogLatestBuildsRequest : APIRequest> { - //protected override string Target => @"changelog"; - protected override string Uri => @"https://api.myjson.com/bins/16waui"; // for testing + protected override string Target => @"changelog/latest-builds"; + protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}"; // for testing } } diff --git a/osu.Game/Online/API/Requests/GetChangelogRequest.cs b/osu.Game/Online/API/Requests/GetChangelogRequest.cs index 6ddff7052e..2f2e0ffe67 100644 --- a/osu.Game/Online/API/Requests/GetChangelogRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogRequest.cs @@ -7,7 +7,7 @@ namespace osu.Game.Online.API.Requests { public class GetChangelogRequest : APIRequest { - //protected override string Target => @"changelog"; - protected override string Uri => @"https://api.myjson.com/bins/6zv2i"; // for testing + protected override string Target => @"changelog"; + protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}"; // for testing } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 16e9d1a074..1f89fba9e1 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -41,8 +41,7 @@ namespace osu.Game.Overlays.Changelog { Clear(); add(changelog); - //fetchChangelogBuild(changelog); - fetchChangelogBuild(); + fetchChangelogBuild(changelog); } private void showNext() @@ -69,11 +68,9 @@ namespace osu.Game.Overlays.Changelog this.api = api; } - //private void fetchChangelogBuild(APIChangelog build) - private void fetchChangelogBuild() + private void fetchChangelogBuild(APIChangelog build) { - //var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); - var req = new GetChangelogBuildRequest(); + var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); req.Success += res => { currentBuild = res; diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 5b22b360e5..3b67aa36ec 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -108,20 +108,10 @@ namespace osu.Game.Overlays.Changelog public void UpdateChevronTooltips(string previousVersion, string nextVersion) { - if (string.IsNullOrEmpty(previousVersion)) - chevronPrevious.IsEnabled = false; - else - { + if (!string.IsNullOrEmpty(previousVersion)) chevronPrevious.TooltipText = previousVersion; - chevronPrevious.IsEnabled = true; - } - if (string.IsNullOrEmpty(nextVersion)) - chevronNext.IsEnabled = false; - else - { + if (!string.IsNullOrEmpty(nextVersion)) chevronNext.TooltipText = nextVersion; - chevronNext.IsEnabled = true; - } } //public ChangelogContentGroup() { } // for listing } From 835a8137151e27ddaeb2ab87466ec447ae615d40 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 19:35:38 +0200 Subject: [PATCH 0024/5608] Improvements to TooltipIconButton Disable sounds when disabled; Remove default tooltip texts --- .../UserInterface/TooltipIconButton.cs | 52 ++++++++++++++++++- .../Changelog/ChangelogContentGroup.cs | 10 +++- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index 7614c4510a..68413e7460 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -2,16 +2,38 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics.Containers; +using osu.Framework.Input; +using System; namespace osu.Game.Graphics.UserInterface { - public class TooltipIconButton : OsuClickableContainer, IHasTooltip + // not inheriting osuclickablecontainer/osuhovercontainer + // because click/hover sounds cannot be disabled, and they make + // double sounds when reappearing under the cursor + public class TooltipIconButton : ClickableContainer, IHasTooltip { private readonly SpriteIcon icon; + private SampleChannel sampleClick; + private SampleChannel sampleHover; + public Action Action; + + private bool isEnabled; + public bool IsEnabled + { + get { return isEnabled; } + set + { + isEnabled = value; + icon.Alpha = value ? 1 : 0.5f; + } + } public FontAwesome Icon { @@ -21,6 +43,7 @@ namespace osu.Game.Graphics.UserInterface public TooltipIconButton() { + isEnabled = true; Children = new Drawable[] { new Box @@ -33,10 +56,35 @@ namespace osu.Game.Graphics.UserInterface Origin = Anchor.Centre, Anchor = Anchor.Centre, Size = new Vector2(18), + Alpha = 0.5f, } }; } + protected override bool OnClick(InputState state) + { + if (isEnabled) + { + Action?.Invoke(); + sampleClick?.Play(); + } + return base.OnClick(state); + } + + protected override bool OnHover(InputState state) + { + if (isEnabled) + sampleHover?.Play(); + return base.OnHover(state); + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleClick = audio.Sample.Get(@"UI/generic-select-soft"); + sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); + } + public string TooltipText { get; set; } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 3b67aa36ec..3ec11beb35 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -44,9 +44,9 @@ namespace osu.Game.Overlays.Changelog { chevronPrevious = new TooltipIconButton { + IsEnabled = false, Icon = FontAwesome.fa_chevron_left, Size = new Vector2(24), - TooltipText = "Previous", Action = () => PreviousRequested(), }, new FillFlowContainer @@ -81,9 +81,9 @@ namespace osu.Game.Overlays.Changelog }, chevronNext = new TooltipIconButton { + IsEnabled = false, Icon = FontAwesome.fa_chevron_right, Size = new Vector2(24), - TooltipText = "Next", Action = () => NextRequested(), }, } @@ -109,9 +109,15 @@ namespace osu.Game.Overlays.Changelog public void UpdateChevronTooltips(string previousVersion, string nextVersion) { if (!string.IsNullOrEmpty(previousVersion)) + { chevronPrevious.TooltipText = previousVersion; + chevronPrevious.IsEnabled = true; + } if (!string.IsNullOrEmpty(nextVersion)) + { chevronNext.TooltipText = nextVersion; + chevronNext.IsEnabled = true; + } } //public ChangelogContentGroup() { } // for listing } From 709872d688fa0fe04ada59dea451fb99de54751f Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 22:11:51 +0200 Subject: [PATCH 0025/5608] Improve showing up builds --- .../UserInterface/TooltipIconButton.cs | 9 ++--- .../Overlays/Changelog/ChangelogContent.cs | 33 ++++++++++++------- osu.Game/Overlays/ChangelogOverlay.cs | 5 +++ 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index 68413e7460..8b85c8c0ec 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -20,7 +20,6 @@ namespace osu.Game.Graphics.UserInterface public class TooltipIconButton : ClickableContainer, IHasTooltip { private readonly SpriteIcon icon; - private SampleChannel sampleClick; private SampleChannel sampleHover; public Action Action; @@ -55,8 +54,8 @@ namespace osu.Game.Graphics.UserInterface { Origin = Anchor.Centre, Anchor = Anchor.Centre, - Size = new Vector2(18), - Alpha = 0.5f, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.8f), } }; } @@ -64,10 +63,7 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnClick(InputState state) { if (isEnabled) - { Action?.Invoke(); - sampleClick?.Play(); - } return base.OnClick(state); } @@ -81,7 +77,6 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(AudioManager audio) { - sampleClick = audio.Sample.Get(@"UI/generic-select-soft"); sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); } diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 1f89fba9e1..8795c040ef 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -7,12 +7,14 @@ using osu.Framework.Graphics.Containers; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; +using System; namespace osu.Game.Overlays.Changelog { public class ChangelogContent : FillFlowContainer { - private APIChangelog currentBuild; + public APIChangelog CurrentBuild { get; private set; } + public Action OnBuildChanged; private APIAccess api; private ChangelogContentGroup changelogContentGroup; @@ -31,35 +33,42 @@ namespace osu.Game.Overlays.Changelog private void add(APIChangelog changelogBuild) { Add(changelogContentGroup = new ChangelogContentGroup(changelogBuild) - { - PreviousRequested = showPrevious, - NextRequested = showNext, - }); + { + PreviousRequested = showPrevious, + NextRequested = showNext, + }); } public void ShowBuild(APIChangelog changelog) { Clear(); add(changelog); + CurrentBuild = changelog; fetchChangelogBuild(changelog); } + private void showBuild(APIChangelog changelog) + { + ShowBuild(changelog); + OnBuildChanged(); + } + private void showNext() { - if (currentBuild.Versions.Next != null) - ShowBuild(currentBuild.Versions.Next); + if (CurrentBuild.Versions.Next != null) + showBuild(CurrentBuild.Versions.Next); } private void showPrevious() { - if (currentBuild.Versions.Previous != null) - ShowBuild(currentBuild.Versions.Previous); + if (CurrentBuild.Versions.Previous != null) + showBuild(CurrentBuild.Versions.Previous); } private void updateChevronTooltips() { - changelogContentGroup.UpdateChevronTooltips(currentBuild.Versions.Previous?.DisplayVersion, - currentBuild.Versions.Next?.DisplayVersion); + changelogContentGroup.UpdateChevronTooltips(CurrentBuild.Versions.Previous?.DisplayVersion, + CurrentBuild.Versions.Next?.DisplayVersion); } [BackgroundDependencyLoader] @@ -73,7 +82,7 @@ namespace osu.Game.Overlays.Changelog var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); req.Success += res => { - currentBuild = res; + CurrentBuild = res; updateChevronTooltips(); }; api.Queue(req); diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index d98db9de94..5932bbb9c8 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -100,6 +100,11 @@ namespace osu.Game.Overlays foreach (StreamBadge item in Streams.BadgesContainer.Children) item.Deactivate(); }; + content.OnBuildChanged = () => + { + header.ChangelogEntry = content.CurrentBuild; + header.ShowReleaseStream(); + }; } public void ActivateListing() => header.ActivateListing(); From c9f3e72b7a868082fc0d7ac2b97e1ec413a29bfe Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 22:13:10 +0200 Subject: [PATCH 0026/5608] Unify build div's dimming mechanics with osu-web --- osu.Game/Overlays/Changelog/ChangelogStreams.cs | 12 +++++++++--- osu.Game/Overlays/Changelog/StreamBadge.cs | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogStreams.cs b/osu.Game/Overlays/Changelog/ChangelogStreams.cs index cc2e1f3f31..1e6e9e1e51 100644 --- a/osu.Game/Overlays/Changelog/ChangelogStreams.cs +++ b/osu.Game/Overlays/Changelog/ChangelogStreams.cs @@ -72,8 +72,10 @@ namespace osu.Game.Overlays.Changelog { if (SelectedRelease != null) { - if (SelectedRelease.UpdateStream.Id != streamBadge.ChangelogEntry.Id) + if (SelectedRelease.UpdateStream.Id != streamBadge.ChangelogEntry.UpdateStream.Id) streamBadge.Deactivate(); + else + streamBadge.EnableDim(); } else streamBadge.Deactivate(); @@ -83,9 +85,13 @@ namespace osu.Game.Overlays.Changelog protected override void OnHoverLost(InputState state) { - if (SelectedRelease == null) - foreach (StreamBadge streamBadge in BadgesContainer.Children) + foreach (StreamBadge streamBadge in BadgesContainer.Children) + { + if (SelectedRelease == null) streamBadge.Activate(true); + else if (streamBadge.ChangelogEntry.UpdateStream.Id == SelectedRelease.UpdateStream.Id) + streamBadge.DisableDim(); + } base.OnHoverLost(state); } } diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index ba98e0a4f7..388245db1a 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -28,6 +28,7 @@ namespace osu.Game.Overlays.Changelog private readonly Header.LineBadge lineBadge; private SampleChannel sampleHover; public readonly APIChangelog ChangelogEntry; + private readonly FillFlowContainer Text; public StreamBadge(APIChangelog changelogEntry) { @@ -38,7 +39,7 @@ namespace osu.Game.Overlays.Changelog isActivated = true; Children = new Drawable[] { - new FillFlowContainer + Text = new FillFlowContainer { AutoSizeAxes = Axes.X, RelativeSizeAxes = Axes.Y, @@ -86,6 +87,7 @@ namespace osu.Game.Overlays.Changelog { isActivated = true; this.FadeIn(transition_duration); + Text.FadeIn(transition_duration); lineBadge.IsCollapsed = false; if (!withoutHeaderUpdate) OnActivation?.Invoke(); @@ -94,6 +96,7 @@ namespace osu.Game.Overlays.Changelog public void Deactivate() { isActivated = false; + DisableDim(); if (!IsHovered) { this.FadeTo(0.5f, transition_duration); @@ -109,7 +112,8 @@ namespace osu.Game.Overlays.Changelog protected override bool OnHover(InputState state) { - if (!isActivated) sampleHover?.Play(); + sampleHover?.Play(); + DisableDim(); this.FadeIn(transition_duration); lineBadge.IsCollapsed = false; return base.OnHover(state); @@ -122,9 +126,15 @@ namespace osu.Game.Overlays.Changelog this.FadeTo(0.5f, transition_duration); lineBadge.IsCollapsed = true; } + else + EnableDim(); base.OnHoverLost(state); } + public void EnableDim() => Text.FadeTo(0.5f, transition_duration); + + public void DisableDim() => Text.FadeIn(transition_duration); + [BackgroundDependencyLoader] private void load(AudioManager audio) { From 311546423863a2442f658ce2f959735168f4076d Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 22:16:16 +0200 Subject: [PATCH 0027/5608] Remove unnecessary statement; Uncapitalize private member; --- osu.Game/Overlays/Changelog/StreamBadge.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 388245db1a..80b2fb2a03 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.Changelog private readonly Header.LineBadge lineBadge; private SampleChannel sampleHover; public readonly APIChangelog ChangelogEntry; - private readonly FillFlowContainer Text; + private readonly FillFlowContainer text; public StreamBadge(APIChangelog changelogEntry) { @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Changelog isActivated = true; Children = new Drawable[] { - Text = new FillFlowContainer + text = new FillFlowContainer { AutoSizeAxes = Axes.X, RelativeSizeAxes = Axes.Y, @@ -87,7 +87,6 @@ namespace osu.Game.Overlays.Changelog { isActivated = true; this.FadeIn(transition_duration); - Text.FadeIn(transition_duration); lineBadge.IsCollapsed = false; if (!withoutHeaderUpdate) OnActivation?.Invoke(); @@ -131,9 +130,9 @@ namespace osu.Game.Overlays.Changelog base.OnHoverLost(state); } - public void EnableDim() => Text.FadeTo(0.5f, transition_duration); + public void EnableDim() => text.FadeTo(0.5f, transition_duration); - public void DisableDim() => Text.FadeIn(transition_duration); + public void DisableDim() => text.FadeIn(transition_duration); [BackgroundDependencyLoader] private void load(AudioManager audio) From c36a303b363bc6f6eba0fd07a118a2483c38a2cd Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 23:14:05 +0200 Subject: [PATCH 0028/5608] Fix ChangelogEntries being a list of objects --- osu.Game/Online/API/Requests/Responses/APIChangelog.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs index 02f9bd763d..4ba7077863 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs @@ -31,7 +31,7 @@ namespace osu.Game.Online.API.Requests.Responses public UpdateStream UpdateStream { get; set; } [JsonProperty("changelog_entries")] - public List ChangelogEntries { get; set; } + public List ChangelogEntries { get; set; } [JsonProperty("versions")] public Versions Versions { get; set; } From 8d4de68c39e246ed01586a6e5a112d02a55048f6 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 20 Jul 2018 23:57:46 +0200 Subject: [PATCH 0029/5608] Nullables in APIChangelog; Primitive changelog entries display --- .../API/Requests/Responses/APIChangelog.cs | 14 ++++++------ .../Overlays/Changelog/ChangelogContent.cs | 1 + .../Changelog/ChangelogContentGroup.cs | 22 ++++++++++++++++++- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs index 4ba7077863..9d3357b071 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs @@ -25,7 +25,7 @@ namespace osu.Game.Online.API.Requests.Responses public bool IsFeatured { get; set; } [JsonProperty("created_at")] - public DateTimeOffset CreatedAt { get; set; } + public DateTimeOffset? CreatedAt { get; set; } [JsonProperty("update_stream")] public UpdateStream UpdateStream { get; set; } @@ -49,19 +49,19 @@ namespace osu.Game.Online.API.Requests.Responses public class ChangelogEntry { [JsonProperty("id")] - public long Id { get; set; } + public long? Id { get; set; } [JsonProperty("repository")] public string Repository { get; set; } [JsonProperty("github_pull_request_id")] - public long GithubPullRequestId { get; set; } + public long? GithubPullRequestId { get; set; } [JsonProperty("github_url")] public string GithubUrl { get; set; } [JsonProperty("url")] - public object Url { get; set; } + public string Url { get; set; } [JsonProperty("type")] public string Type { get; set; } @@ -76,10 +76,10 @@ namespace osu.Game.Online.API.Requests.Responses public string MessageHtml { get; set; } [JsonProperty("major")] - public bool Major { get; set; } + public bool? Major { get; set; } [JsonProperty("created_at")] - public DateTimeOffset CreatedAt { get; set; } + public DateTimeOffset? CreatedAt { get; set; } [JsonProperty("github_user")] public GithubUser GithubUser { get; set; } @@ -88,7 +88,7 @@ namespace osu.Game.Online.API.Requests.Responses public class GithubUser { [JsonProperty("id")] - public long Id { get; set; } + public long? Id { get; set; } [JsonProperty("display_name")] public string DisplayName { get; set; } diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 8795c040ef..1bae32b4ef 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -83,6 +83,7 @@ namespace osu.Game.Overlays.Changelog req.Success += res => { CurrentBuild = res; + changelogContentGroup.GenerateText(CurrentBuild.ChangelogEntries); updateChevronTooltips(); }; api.Queue(req); diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 3ec11beb35..bc6428450e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -9,6 +9,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; using System; +using System.Collections.Generic; namespace osu.Game.Overlays.Changelog { @@ -17,6 +18,8 @@ namespace osu.Game.Overlays.Changelog private readonly TooltipIconButton chevronPrevious, chevronNext; public Action NextRequested, PreviousRequested; + public readonly TextFlowContainer ChangelogEntries; + public ChangelogContentGroup(APIChangelog build) { RelativeSizeAxes = Axes.X; @@ -92,7 +95,8 @@ namespace osu.Game.Overlays.Changelog { // do we need .ToUniversalTime() here? // also, this should be a temporary solution to weekdays in >localized< date strings - Text = build.CreatedAt.Date.ToLongDateString().Replace(build.CreatedAt.ToString("dddd") + ", ", ""), + Text = build.CreatedAt.HasValue ? build.CreatedAt.Value.Date.ToLongDateString() + .Replace(build.CreatedAt.Value.ToString("dddd") + ", ", "") : null, TextSize = 17, // web: 14, Colour = OsuColour.FromHex(@"FD5"), Font = @"Exo2.0-Medium", @@ -103,6 +107,11 @@ namespace osu.Game.Overlays.Changelog Top = 5, }, }, + ChangelogEntries = new TextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, }; } @@ -119,6 +128,17 @@ namespace osu.Game.Overlays.Changelog chevronNext.IsEnabled = true; } } + + public void GenerateText(List changelogEntries) + { + foreach (ChangelogEntry entry in changelogEntries) + { + ChangelogEntries.AddParagraph(entry.Type); + ChangelogEntries.AddParagraph(entry.Title); + ChangelogEntries.AddText($"({entry.Repository}#{entry.GithubPullRequestId})"); + ChangelogEntries.AddText($"by {entry.GithubUser.DisplayName}"); + } + } //public ChangelogContentGroup() { } // for listing } } From 1492d5cb29d26876c3d3d7d6a25cbcfc5920c66f Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sat, 21 Jul 2018 02:58:53 +0200 Subject: [PATCH 0030/5608] Improve primitive changelog entry formatting --- .../Changelog/ChangelogContentGroup.cs | 65 +++++++++++++++---- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index bc6428450e..9393849d93 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; +using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -18,18 +19,13 @@ namespace osu.Game.Overlays.Changelog private readonly TooltipIconButton chevronPrevious, chevronNext; public Action NextRequested, PreviousRequested; - public readonly TextFlowContainer ChangelogEntries; + public readonly FillFlowContainer ChangelogEntries; public ChangelogContentGroup(APIChangelog build) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; - Padding = new MarginPadding - { - Left = 70, - Right = 70, - }; Children = new Drawable[] { // build version, arrows @@ -95,8 +91,7 @@ namespace osu.Game.Overlays.Changelog { // do we need .ToUniversalTime() here? // also, this should be a temporary solution to weekdays in >localized< date strings - Text = build.CreatedAt.HasValue ? build.CreatedAt.Value.Date.ToLongDateString() - .Replace(build.CreatedAt.Value.ToString("dddd") + ", ", "") : null, + Text = build.CreatedAt.Value.Date.ToLongDateString().Replace(build.CreatedAt.Value.ToString("dddd") + ", ", ""), TextSize = 17, // web: 14, Colour = OsuColour.FromHex(@"FD5"), Font = @"Exo2.0-Medium", @@ -107,10 +102,11 @@ namespace osu.Game.Overlays.Changelog Top = 5, }, }, - ChangelogEntries = new TextFlowContainer + ChangelogEntries = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, }, }; } @@ -133,10 +129,53 @@ namespace osu.Game.Overlays.Changelog { foreach (ChangelogEntry entry in changelogEntries) { - ChangelogEntries.AddParagraph(entry.Type); - ChangelogEntries.AddParagraph(entry.Title); - ChangelogEntries.AddText($"({entry.Repository}#{entry.GithubPullRequestId})"); - ChangelogEntries.AddText($"by {entry.GithubUser.DisplayName}"); + // textflowcontainer is unusable for formatting text + // this has to be a placeholder before we get a + // proper markdown/html formatting.. + // it can't handle overflowing properly + ChangelogEntries.Add(new SpriteText + { + Text = entry.Category, + TextSize = 24, // web: 18, + Font = @"Exo2.0-Bold", + Margin = new MarginPadding { Top = 35, Bottom = 15, }, + }); + ChangelogEntries.Add(new FillFlowContainer + { + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopRight, + Icon = FontAwesome.fa_check, + Size = new Vector2(14), + Margin = new MarginPadding { Top = 2, Right = 4 }, + }, + new TextFlowContainer(t => t.TextSize = 18) + { + Text = entry.Title, + AutoSizeAxes = Axes.Both, + }, + new SpriteText + { + Text = !string.IsNullOrEmpty(entry.Repository) ? + $" ({entry.Repository.Substring(4)}#{entry.GithubPullRequestId})" : + null, + TextSize = 18, + Colour = new Color4(153, 238, 255, 255), + }, + new SpriteText + { + Text = $" by {entry.GithubUser.DisplayName}", + TextSize = 14, // web: 12; + Margin = new MarginPadding { Top = 4, Left = 10, }, + }, + } + }); } } //public ChangelogContentGroup() { } // for listing From ce0029eabf68455d5a24ad6fdb5546512553abf1 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sat, 21 Jul 2018 03:19:30 +0200 Subject: [PATCH 0031/5608] Make build's creation date not nullable --- osu.Game/Online/API/Requests/Responses/APIChangelog.cs | 2 +- osu.Game/Overlays/Changelog/ChangelogContentGroup.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs index 9d3357b071..da5437515c 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelog.cs @@ -25,7 +25,7 @@ namespace osu.Game.Online.API.Requests.Responses public bool IsFeatured { get; set; } [JsonProperty("created_at")] - public DateTimeOffset? CreatedAt { get; set; } + public DateTimeOffset CreatedAt { get; set; } [JsonProperty("update_stream")] public UpdateStream UpdateStream { get; set; } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 9393849d93..7c770dd153 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -91,7 +91,7 @@ namespace osu.Game.Overlays.Changelog { // do we need .ToUniversalTime() here? // also, this should be a temporary solution to weekdays in >localized< date strings - Text = build.CreatedAt.Value.Date.ToLongDateString().Replace(build.CreatedAt.Value.ToString("dddd") + ", ", ""), + Text = build.CreatedAt.Date.ToLongDateString().Replace(build.CreatedAt.ToString("dddd") + ", ", ""), TextSize = 17, // web: 14, Colour = OsuColour.FromHex(@"FD5"), Font = @"Exo2.0-Medium", From 50c4f6ff9521efeddeadd1db9ef59cef95a3e774 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sat, 21 Jul 2018 06:37:42 +0200 Subject: [PATCH 0032/5608] Prevent scrolling to top on build change; Add bottom margin --- osu.Game/Overlays/Changelog/ChangelogContent.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 1bae32b4ef..363b251383 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -25,24 +25,22 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Vertical; Padding = new MarginPadding { - Left = 70, - Right = 70, + Horizontal = 70, + Bottom = 100, }; } private void add(APIChangelog changelogBuild) { - Add(changelogContentGroup = new ChangelogContentGroup(changelogBuild) + Child = changelogContentGroup = new ChangelogContentGroup(changelogBuild) { PreviousRequested = showPrevious, NextRequested = showNext, - }); + }; } public void ShowBuild(APIChangelog changelog) { - Clear(); - add(changelog); CurrentBuild = changelog; fetchChangelogBuild(changelog); } @@ -83,6 +81,7 @@ namespace osu.Game.Overlays.Changelog req.Success += res => { CurrentBuild = res; + add(CurrentBuild); changelogContentGroup.GenerateText(CurrentBuild.ChangelogEntries); updateChevronTooltips(); }; From eca5fb6f052f4906233e1e10f7960133703e0035 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sat, 21 Jul 2018 06:38:02 +0200 Subject: [PATCH 0033/5608] Introduce better formatting to changelog entries; Sort by category --- .../Changelog/ChangelogContentGroup.cs | 79 ++++++++++--------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 7c770dd153..4a6eb27cc7 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; using System; @@ -17,6 +18,8 @@ namespace osu.Game.Overlays.Changelog public class ChangelogContentGroup : FillFlowContainer { private readonly TooltipIconButton chevronPrevious, chevronNext; + private readonly SortedDictionary> categories = + new SortedDictionary>(); public Action NextRequested, PreviousRequested; public readonly FillFlowContainer ChangelogEntries; @@ -97,10 +100,7 @@ namespace osu.Game.Overlays.Changelog Font = @"Exo2.0-Medium", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Margin = new MarginPadding - { - Top = 5, - }, + Margin = new MarginPadding{ Top = 5, } }, ChangelogEntries = new FillFlowContainer { @@ -127,7 +127,16 @@ namespace osu.Game.Overlays.Changelog public void GenerateText(List changelogEntries) { + // sort entries by category foreach (ChangelogEntry entry in changelogEntries) + { + if (!categories.ContainsKey(entry.Category)) + categories.Add(entry.Category, new List { entry }); + else + categories[entry.Category].Add(entry); + } + + foreach (KeyValuePair> category in categories) { // textflowcontainer is unusable for formatting text // this has to be a placeholder before we get a @@ -135,47 +144,43 @@ namespace osu.Game.Overlays.Changelog // it can't handle overflowing properly ChangelogEntries.Add(new SpriteText { - Text = entry.Category, + Text = category.Key, TextSize = 24, // web: 18, Font = @"Exo2.0-Bold", Margin = new MarginPadding { Top = 35, Bottom = 15, }, }); - ChangelogEntries.Add(new FillFlowContainer + foreach (ChangelogEntry entry in category.Value) { - Direction = FillDirection.Full, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] + OsuTextFlowContainer title; + + ChangelogEntries.Add(title = new OsuTextFlowContainer { - new SpriteIcon + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + LineSpacing = 0.25f, + }); + title.AddIcon(FontAwesome.fa_check, t => { t.TextSize = 12; t.Padding = new MarginPadding { Left = -17, Right = 5 }; }); + title.AddText(entry.Title, t => { t.TextSize = 18; }); //t.Padding = new MarginPadding(10); }); + if (!string.IsNullOrEmpty(entry.Repository)) + { + title.AddText($" ({entry.Repository.Substring(4)}#{entry.GithubPullRequestId})", t => { - Anchor = Anchor.TopLeft, - Origin = Anchor.TopRight, - Icon = FontAwesome.fa_check, - Size = new Vector2(14), - Margin = new MarginPadding { Top = 2, Right = 4 }, - }, - new TextFlowContainer(t => t.TextSize = 18) - { - Text = entry.Title, - AutoSizeAxes = Axes.Both, - }, - new SpriteText - { - Text = !string.IsNullOrEmpty(entry.Repository) ? - $" ({entry.Repository.Substring(4)}#{entry.GithubPullRequestId})" : - null, - TextSize = 18, - Colour = new Color4(153, 238, 255, 255), - }, - new SpriteText - { - Text = $" by {entry.GithubUser.DisplayName}", - TextSize = 14, // web: 12; - Margin = new MarginPadding { Top = 4, Left = 10, }, - }, + t.TextSize = 18; + t.Colour = Color4.SkyBlue; + }); } - }); + title.AddText($" by {entry.GithubUser.DisplayName}", t => t.TextSize = 14); //web: 12; + ChangelogEntries.Add(new SpriteText + { + TextSize = 14, // web: 12, + Colour = new Color4(235, 184, 254, 255), + Text = $"{entry.MessageHtml?.Replace("

", "").Replace("

", "")}\n", + Margin = new MarginPadding { Bottom = 10, }, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + }); + } } } //public ChangelogContentGroup() { } // for listing From 78f0f37ee65c7c4666b668c25064daf14b63d6a9 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sat, 21 Jul 2018 07:16:22 +0200 Subject: [PATCH 0034/5608] Change graph's colour on stream selection --- osu.Game/Overlays/Changelog/ChangelogChart.cs | 10 +++++++++- osu.Game/Overlays/ChangelogOverlay.cs | 4 +++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index b113a509ec..18c74f4b51 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Changelog { @@ -13,13 +14,15 @@ namespace osu.Game.Overlays.Changelog // placeholder json file: https://api.myjson.com/bins/10ye8a public class ChangelogChart : BufferedContainer { + private Box background; + public ChangelogChart() { RelativeSizeAxes = Axes.X; Height = 100; Children = new Drawable[] { - new Box + background = new Box { Colour = StreamColour.STABLE, RelativeSizeAxes = Axes.Both, @@ -33,5 +36,10 @@ namespace osu.Game.Overlays.Changelog }, }; } + + public void ShowChart(APIChangelog releaseStream) + { + background.Colour = StreamColour.FromStreamName(releaseStream.UpdateStream.Name); + } } } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 5932bbb9c8..f2df54ac99 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -22,6 +22,7 @@ namespace osu.Game.Overlays { private readonly ChangelogHeader header; public readonly ChangelogStreams Streams; + private readonly ChangelogChart chart; private APIChangelog changelogEntry; private APIAccess api; @@ -72,7 +73,7 @@ namespace osu.Game.Overlays { header = new ChangelogHeader(), Streams = new ChangelogStreams(), - new ChangelogChart(), + chart = new ChangelogChart(), content = new ChangelogContent(), }, }, @@ -87,6 +88,7 @@ namespace osu.Game.Overlays } header.ShowReleaseStream(); content.ShowBuild(Streams.SelectedRelease); + chart.ShowChart(Streams.SelectedRelease); }; header.OnListingActivated += () => { From 22af3cd923a9e16e5a4643a511086b9d0b925fa5 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sat, 21 Jul 2018 09:37:58 +0200 Subject: [PATCH 0035/5608] Handle possible null reference; --- osu.Game/Graphics/StreamColour.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/StreamColour.cs b/osu.Game/Graphics/StreamColour.cs index 2a0d7fceab..3ee31c90e6 100644 --- a/osu.Game/Graphics/StreamColour.cs +++ b/osu.Game/Graphics/StreamColour.cs @@ -28,9 +28,10 @@ namespace osu.Game.Graphics public static ColourInfo FromStreamName(string name) { - if (colours.TryGetValue(name, out ColourInfo colour)) - return colour; - else return new Color4(255, 255, 255, 255); + if (!string.IsNullOrEmpty(name)) + if (colours.TryGetValue(name, out ColourInfo colour)) + return colour; + return new Color4(255, 255, 255, 255); } } } From e2af2b0409fe91d7239f69e2fb1e7e77df8ecc32 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sat, 21 Jul 2018 09:39:54 +0200 Subject: [PATCH 0036/5608] Change chart's colour depending on release stream; Show whether it's populated Fix chart requests --- .../API/Requests/GetChangelogChartRequest.cs | 21 +++++++++ .../Requests/Responses/APIChangelogChart.cs | 34 ++++++++++++++ osu.Game/Overlays/Changelog/ChangelogChart.cs | 44 +++++++++++++++++-- 3 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Online/API/Requests/GetChangelogChartRequest.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs diff --git a/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs b/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs new file mode 100644 index 0000000000..4a9568af0b --- /dev/null +++ b/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Online.API.Requests.Responses; +using System.Collections.Generic; + +namespace osu.Game.Online.API.Requests +{ + public class GetChangelogChartRequest : APIRequest + { + private readonly string updateStream; + + public GetChangelogChartRequest() => updateStream = null; + + public GetChangelogChartRequest(string updateStreamName) => updateStream = updateStreamName; + + protected override string Target => $@"changelog/{(!string.IsNullOrEmpty(updateStream) ? + updateStream + "/" : "")}chart-config"; + protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}"; // for testing + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs new file mode 100644 index 0000000000..aa8c462018 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using Newtonsoft.Json; +using osu.Framework.Lists; +using System; +using System.Collections.Generic; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIChangelogChart + { + [JsonProperty("build_history")] + public List BuildHistory { get; set; } + + [JsonProperty("order")] + public List Order { get; set; } + + [JsonProperty("stream_name")] + public string StreamName { get; set; } + } + + public class BuildHistory + { + [JsonProperty("created_at")] + public DateTimeOffset CreatedAt { get; set; } + + [JsonProperty("user_count")] + public long UserCount { get; set; } + + [JsonProperty("label")] + public string Label { get; set; } + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index 18c74f4b51..cb2d60c649 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -1,11 +1,15 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using OpenTK.Graphics; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Changelog @@ -15,6 +19,8 @@ namespace osu.Game.Overlays.Changelog public class ChangelogChart : BufferedContainer { private Box background; + private SpriteText text; + private APIAccess api; public ChangelogChart() { @@ -27,7 +33,7 @@ namespace osu.Game.Overlays.Changelog Colour = StreamColour.STABLE, RelativeSizeAxes = Axes.Both, }, - new SpriteText + text = new SpriteText { Text = "Graph Placeholder", TextSize = 28, @@ -37,9 +43,41 @@ namespace osu.Game.Overlays.Changelog }; } - public void ShowChart(APIChangelog releaseStream) + public void ShowChart(APIChangelog releaseStream) => fetchAndShowChangelogChart(releaseStream); + + private bool isEmpty(APIChangelogChart changelogChart) { - background.Colour = StreamColour.FromStreamName(releaseStream.UpdateStream.Name); + if (changelogChart != null) + foreach (BuildHistory buildHistory in changelogChart.BuildHistory) + if (buildHistory.UserCount > 0) return false; + return true; + } + + private void showChart(APIChangelogChart chartInfo, string updateStreamName) + { + if (!isEmpty(chartInfo)) + { + background.Colour = StreamColour.FromStreamName(updateStreamName); + text.Text = "Graph placeholder\n(chart is not empty)"; + } + else + { + background.Colour = Color4.Black; + text.Text = "Graph placeholder\n(chart is empty)"; + } + } + + [BackgroundDependencyLoader] + private void load(APIAccess api) + { + this.api = api; + } + + private void fetchAndShowChangelogChart(APIChangelog build) + { + var req = new GetChangelogChartRequest(build.UpdateStream.Name); + req.Success += res => showChart(res, build.UpdateStream.Name); + api.Queue(req); } } } From ba0430752caafec4abfabea92a9b6fe5822ac45a Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sat, 21 Jul 2018 09:45:14 +0200 Subject: [PATCH 0037/5608] Check wether a chart is populated; Fixes to graph's colour setting --- .../API/Requests/GetChangelogChartRequest.cs | 21 +++++++++ .../Requests/Responses/APIChangelogChart.cs | 34 ++++++++++++++ osu.Game/Overlays/Changelog/ChangelogChart.cs | 44 +++++++++++++++++-- 3 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Online/API/Requests/GetChangelogChartRequest.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs diff --git a/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs b/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs new file mode 100644 index 0000000000..4a9568af0b --- /dev/null +++ b/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Online.API.Requests.Responses; +using System.Collections.Generic; + +namespace osu.Game.Online.API.Requests +{ + public class GetChangelogChartRequest : APIRequest + { + private readonly string updateStream; + + public GetChangelogChartRequest() => updateStream = null; + + public GetChangelogChartRequest(string updateStreamName) => updateStream = updateStreamName; + + protected override string Target => $@"changelog/{(!string.IsNullOrEmpty(updateStream) ? + updateStream + "/" : "")}chart-config"; + protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}"; // for testing + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs new file mode 100644 index 0000000000..aa8c462018 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using Newtonsoft.Json; +using osu.Framework.Lists; +using System; +using System.Collections.Generic; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIChangelogChart + { + [JsonProperty("build_history")] + public List BuildHistory { get; set; } + + [JsonProperty("order")] + public List Order { get; set; } + + [JsonProperty("stream_name")] + public string StreamName { get; set; } + } + + public class BuildHistory + { + [JsonProperty("created_at")] + public DateTimeOffset CreatedAt { get; set; } + + [JsonProperty("user_count")] + public long UserCount { get; set; } + + [JsonProperty("label")] + public string Label { get; set; } + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index 18c74f4b51..cb2d60c649 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -1,11 +1,15 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using OpenTK.Graphics; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Changelog @@ -15,6 +19,8 @@ namespace osu.Game.Overlays.Changelog public class ChangelogChart : BufferedContainer { private Box background; + private SpriteText text; + private APIAccess api; public ChangelogChart() { @@ -27,7 +33,7 @@ namespace osu.Game.Overlays.Changelog Colour = StreamColour.STABLE, RelativeSizeAxes = Axes.Both, }, - new SpriteText + text = new SpriteText { Text = "Graph Placeholder", TextSize = 28, @@ -37,9 +43,41 @@ namespace osu.Game.Overlays.Changelog }; } - public void ShowChart(APIChangelog releaseStream) + public void ShowChart(APIChangelog releaseStream) => fetchAndShowChangelogChart(releaseStream); + + private bool isEmpty(APIChangelogChart changelogChart) { - background.Colour = StreamColour.FromStreamName(releaseStream.UpdateStream.Name); + if (changelogChart != null) + foreach (BuildHistory buildHistory in changelogChart.BuildHistory) + if (buildHistory.UserCount > 0) return false; + return true; + } + + private void showChart(APIChangelogChart chartInfo, string updateStreamName) + { + if (!isEmpty(chartInfo)) + { + background.Colour = StreamColour.FromStreamName(updateStreamName); + text.Text = "Graph placeholder\n(chart is not empty)"; + } + else + { + background.Colour = Color4.Black; + text.Text = "Graph placeholder\n(chart is empty)"; + } + } + + [BackgroundDependencyLoader] + private void load(APIAccess api) + { + this.api = api; + } + + private void fetchAndShowChangelogChart(APIChangelog build) + { + var req = new GetChangelogChartRequest(build.UpdateStream.Name); + req.Success += res => showChart(res, build.UpdateStream.Name); + api.Queue(req); } } } From b5207d65f7ab6fceb76c9ac423f63d4e999818f7 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sat, 21 Jul 2018 10:05:12 +0200 Subject: [PATCH 0038/5608] Show listing graph; Slight refactor --- osu.Game/Graphics/StreamColour.cs | 2 +- .../API/Requests/GetChangelogChartRequest.cs | 1 - .../Requests/Responses/APIChangelogChart.cs | 1 - osu.Game/Overlays/Changelog/ChangelogChart.cs | 21 ++++++++++++++++--- osu.Game/Overlays/ChangelogOverlay.cs | 2 ++ 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/StreamColour.cs b/osu.Game/Graphics/StreamColour.cs index 3ee31c90e6..71626a0e3a 100644 --- a/osu.Game/Graphics/StreamColour.cs +++ b/osu.Game/Graphics/StreamColour.cs @@ -31,7 +31,7 @@ namespace osu.Game.Graphics if (!string.IsNullOrEmpty(name)) if (colours.TryGetValue(name, out ColourInfo colour)) return colour; - return new Color4(255, 255, 255, 255); + return new Color4(0, 0, 0, 255); } } } diff --git a/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs b/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs index 4a9568af0b..1e131fb91f 100644 --- a/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Online.API.Requests.Responses; -using System.Collections.Generic; namespace osu.Game.Online.API.Requests { diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs index aa8c462018..3509ff7de1 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using Newtonsoft.Json; -using osu.Framework.Lists; using System; using System.Collections.Generic; diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index cb2d60c649..b8df166a19 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -18,8 +18,8 @@ namespace osu.Game.Overlays.Changelog // placeholder json file: https://api.myjson.com/bins/10ye8a public class ChangelogChart : BufferedContainer { - private Box background; - private SpriteText text; + private readonly Box background; + private readonly SpriteText text; private APIAccess api; public ChangelogChart() @@ -43,6 +43,14 @@ namespace osu.Game.Overlays.Changelog }; } + /// + /// Draw the graph with all builds + /// + public void ShowChart() => fetchAndShowChangelogChart(); + + /// + /// Draw the graph for a specific build + /// public void ShowChart(APIChangelog releaseStream) => fetchAndShowChangelogChart(releaseStream); private bool isEmpty(APIChangelogChart changelogChart) @@ -53,7 +61,7 @@ namespace osu.Game.Overlays.Changelog return true; } - private void showChart(APIChangelogChart chartInfo, string updateStreamName) + private void showChart(APIChangelogChart chartInfo, string updateStreamName = null) { if (!isEmpty(chartInfo)) { @@ -79,5 +87,12 @@ namespace osu.Game.Overlays.Changelog req.Success += res => showChart(res, build.UpdateStream.Name); api.Queue(req); } + + private void fetchAndShowChangelogChart() + { + var req = new GetChangelogChartRequest(); + req.Success += res => showChart(res); + api.Queue(req); + } } } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index f2df54ac99..ce2878858f 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -101,6 +101,7 @@ namespace osu.Game.Overlays else foreach (StreamBadge item in Streams.BadgesContainer.Children) item.Deactivate(); + chart.ShowChart(); }; content.OnBuildChanged = () => { @@ -155,6 +156,7 @@ namespace osu.Game.Overlays Streams.BadgesContainer.Clear(); foreach (APIChangelog item in res) Streams.BadgesContainer.Add(new StreamBadge(item)); + chart.ShowChart(); }; api.Queue(req); } From 8f43b883b1509fa46b74ae8c094e022cbfa29893 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sat, 21 Jul 2018 23:00:05 +0200 Subject: [PATCH 0039/5608] Set the right colour for background --- osu.Game/Overlays/ChangelogOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index ce2878858f..cfa669534d 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -58,7 +58,7 @@ namespace osu.Game.Overlays new Box { RelativeSizeAxes = Axes.Both, - Colour = new Color4(20, 18, 23, 255) + Colour = new Color4(49, 36, 54, 255), }, new ScrollContainer { From 8e7efafba31193350088a0f0374060dd8eebad53 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sat, 21 Jul 2018 23:10:42 +0200 Subject: [PATCH 0040/5608] Lower height of the cover image, Adjust height of the purple line --- osu.Game/Overlays/Changelog/ChangelogHeader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 1c3f6f0853..a744fc3c97 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Changelog public APIChangelog ChangelogEntry; - private const float cover_height = 310; + private const float cover_height = 280; private const float title_height = 50; private const float icon_size = 50; private const float icon_margin = 20; @@ -155,7 +155,7 @@ namespace osu.Game.Overlays.Changelog { Colour = Purple, RelativeSizeAxes = Axes.X, - Height = 3, + Height = 2, Anchor = Anchor.BottomLeft, Origin = Anchor.CentreLeft, }, From 80808bddbf049e66e5b38c7e1c899a935d5b857c Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 05:28:43 +0200 Subject: [PATCH 0041/5608] Add changelog listing --- .../API/Requests/GetChangelogRequest.cs | 2 +- .../Overlays/Changelog/ChangelogContent.cs | 66 ++++++++++++++++-- .../Changelog/ChangelogContentGroup.cs | 69 +++++++++++++++++-- osu.Game/Overlays/ChangelogOverlay.cs | 3 +- 4 files changed, 124 insertions(+), 16 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetChangelogRequest.cs b/osu.Game/Online/API/Requests/GetChangelogRequest.cs index 2f2e0ffe67..ec8536c607 100644 --- a/osu.Game/Online/API/Requests/GetChangelogRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogRequest.cs @@ -8,6 +8,6 @@ namespace osu.Game.Online.API.Requests public class GetChangelogRequest : APIRequest { protected override string Target => @"changelog"; - protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}"; // for testing + protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}/index"; // for testing } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 363b251383..a4797d6f7c 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -1,9 +1,11 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -11,7 +13,7 @@ using System; namespace osu.Game.Overlays.Changelog { - public class ChangelogContent : FillFlowContainer + public class ChangelogContent : FillFlowContainer { public APIChangelog CurrentBuild { get; private set; } public Action OnBuildChanged; @@ -23,11 +25,52 @@ namespace osu.Game.Overlays.Changelog RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; - Padding = new MarginPadding + Padding = new MarginPadding{ Bottom = 100, }; + } + + private void add(APIChangelog[] changelog) + { + DateTime currentDate = new DateTime(); + + Clear(); + + foreach (APIChangelog build in changelog) { - Horizontal = 70, - Bottom = 100, - }; + if (build.CreatedAt.Date != currentDate) + { + if (Children.Count != 0) + { + Add(new Box + { + RelativeSizeAxes = Axes.X, + Height = 2, + Colour = new Color4(17, 17, 17, 255), + Margin = new MarginPadding { Top = 30, }, + }); + } + Add(changelogContentGroup = new ChangelogContentGroup(build, true) + { + BuildRequested = () => showBuild(build), + }); + changelogContentGroup.GenerateText(build.ChangelogEntries); + currentDate = build.CreatedAt.Date; + } + else + { + changelogContentGroup.Add(new Box + { + RelativeSizeAxes = Axes.X, + Height = 1, + Colour = new Color4(32, 24, 35, 255), + Margin = new MarginPadding { Top = 30, }, + }); + Add(changelogContentGroup = new ChangelogContentGroup(build, false) + { + BuildRequested = () => ShowBuild(build), + }); + changelogContentGroup.GenerateText(build.ChangelogEntries); + } + } } private void add(APIChangelog changelogBuild) @@ -41,10 +84,12 @@ namespace osu.Game.Overlays.Changelog public void ShowBuild(APIChangelog changelog) { + fetchAndShowChangelogBuild(changelog); CurrentBuild = changelog; - fetchChangelogBuild(changelog); } + public void ShowListing() => fetchAndShowChangelog(); + private void showBuild(APIChangelog changelog) { ShowBuild(changelog); @@ -75,7 +120,14 @@ namespace osu.Game.Overlays.Changelog this.api = api; } - private void fetchChangelogBuild(APIChangelog build) + private void fetchAndShowChangelog() + { + var req = new GetChangelogRequest(); + req.Success += res => add(res); + api.Queue(req); + } + + private void fetchAndShowChangelogBuild(APIChangelog build) { var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); req.Success += res => diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 4a6eb27cc7..0fc4c31bbe 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Changelog private readonly SortedDictionary> categories = new SortedDictionary>(); - public Action NextRequested, PreviousRequested; + public Action NextRequested, PreviousRequested, BuildRequested; public readonly FillFlowContainer ChangelogEntries; public ChangelogContentGroup(APIChangelog build) @@ -29,6 +29,7 @@ namespace osu.Game.Overlays.Changelog RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; + Padding = new MarginPadding { Horizontal = 70 }; Children = new Drawable[] { // build version, arrows @@ -111,6 +112,67 @@ namespace osu.Game.Overlays.Changelog }; } + public ChangelogContentGroup(APIChangelog build, bool newDate = false) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Direction = FillDirection.Vertical; + Padding = new MarginPadding { Horizontal = 70 }; + Children = new Drawable[] + { + new SpriteText + { + // do we need .ToUniversalTime() here? + // also, this should be a temporary solution to weekdays in >localized< date strings + Text = build.CreatedAt.Date.ToLongDateString().Replace(build.CreatedAt.ToString("dddd") + ", ", ""), + TextSize = 28, // web: 24, + Colour = OsuColour.FromHex(@"FD5"), + Font = @"Exo2.0-Light", + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Margin = new MarginPadding{ Top = 20, }, + Alpha = newDate ? 1 : 0, + }, + new FillFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding{ Top = 20, }, + Spacing = new Vector2(5), + Children = new Drawable[] + { + new SpriteText + { + Text = build.UpdateStream.DisplayName, + TextSize = 20, // web: 18, + Font = @"Exo2.0-Medium", + }, + new SpriteText + { + Text = build.DisplayVersion, + TextSize = 20, // web: 18, + Font = @"Exo2.0-Light", + Colour = StreamColour.FromStreamName(build.UpdateStream.Name), + }, + new ClickableText + { + Text = " ok ", + TextSize = 20, + Action = BuildRequested, + }, + } + }, + ChangelogEntries = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + }, + }; + } + public void UpdateChevronTooltips(string previousVersion, string nextVersion) { if (!string.IsNullOrEmpty(previousVersion)) @@ -138,10 +200,6 @@ namespace osu.Game.Overlays.Changelog foreach (KeyValuePair> category in categories) { - // textflowcontainer is unusable for formatting text - // this has to be a placeholder before we get a - // proper markdown/html formatting.. - // it can't handle overflowing properly ChangelogEntries.Add(new SpriteText { Text = category.Key, @@ -183,6 +241,5 @@ namespace osu.Game.Overlays.Changelog } } } - //public ChangelogContentGroup() { } // for listing } } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index cfa669534d..0a2c5e9b6f 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -93,8 +93,7 @@ namespace osu.Game.Overlays header.OnListingActivated += () => { Streams.SelectedRelease = null; - content.Clear(); - // should add listing to content here + content.ShowListing(); if (!Streams.IsHovered) foreach (StreamBadge item in Streams.BadgesContainer.Children) item.Activate(true); From c5bdfb885787cb6350bfa8f87d79c0ec5b7a1c8a Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 05:34:55 +0200 Subject: [PATCH 0042/5608] Use ClickableText for navigating to builds; Fix typo --- osu.Game/Overlays/Changelog/ChangelogContent.cs | 12 +++++++++--- osu.Game/Overlays/Changelog/ChangelogContentGroup.cs | 9 ++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index a4797d6f7c..36f9d3fec6 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -66,7 +66,7 @@ namespace osu.Game.Overlays.Changelog }); Add(changelogContentGroup = new ChangelogContentGroup(build, false) { - BuildRequested = () => ShowBuild(build), + BuildRequested = () => showBuild(build), }); changelogContentGroup.GenerateText(build.ChangelogEntries); } @@ -82,20 +82,26 @@ namespace osu.Game.Overlays.Changelog }; } + /// + /// Doesn't send back that the build has changed + /// public void ShowBuild(APIChangelog changelog) { fetchAndShowChangelogBuild(changelog); CurrentBuild = changelog; } - public void ShowListing() => fetchAndShowChangelog(); - + /// + /// Sends back that the build has changed + /// private void showBuild(APIChangelog changelog) { ShowBuild(changelog); OnBuildChanged(); } + public void ShowListing() => fetchAndShowChangelog(); + private void showNext() { if (CurrentBuild.Versions.Next != null) diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 0fc4c31bbe..36127d585e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -149,18 +149,13 @@ namespace osu.Game.Overlays.Changelog TextSize = 20, // web: 18, Font = @"Exo2.0-Medium", }, - new SpriteText + new ClickableText { Text = build.DisplayVersion, TextSize = 20, // web: 18, Font = @"Exo2.0-Light", Colour = StreamColour.FromStreamName(build.UpdateStream.Name), - }, - new ClickableText - { - Text = " ok ", - TextSize = 20, - Action = BuildRequested, + Action = () => BuildRequested(), }, } }, From 2d36062159d8b3e5e77740eed2ec3c1305c2b60f Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 06:01:04 +0200 Subject: [PATCH 0043/5608] Add ClickableText --- .../Graphics/UserInterface/ClickableText.cs | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 osu.Game/Graphics/UserInterface/ClickableText.cs diff --git a/osu.Game/Graphics/UserInterface/ClickableText.cs b/osu.Game/Graphics/UserInterface/ClickableText.cs new file mode 100644 index 0000000000..8d0e98d687 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ClickableText.cs @@ -0,0 +1,64 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input; +using System; + +namespace osu.Game.Graphics.UserInterface +{ + public class ClickableText : SpriteText, IHasTooltip + { + private bool isEnabled; + private SampleChannel sampleHover; + private SampleChannel sampleClick; + + public Action Action; + + public bool IsEnabled + { + get { return isEnabled; } + set + { + isEnabled = value; + Alpha = value ? 1 : 0.5f; + } + } + + public ClickableText() => isEnabled = true; + + public override bool HandleMouseInput => true; + + protected override bool OnHover(InputState state) + { + if (isEnabled) + sampleHover?.Play(); + return base.OnHover(state); + } + + protected override bool OnClick(InputState state) + { + if (isEnabled) + { + sampleClick?.Play(); + Action?.Invoke(); + } + return base.OnClick(state); + } + + public string TooltipText { get; set; } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); + } + } +} From 9586ef7b0a28d160d13fb6c7989b8c79f010d103 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 08:28:12 +0200 Subject: [PATCH 0044/5608] ClickableText changes --- .../Visual/TestCaseClickableText.cs | 70 +++++++++++++++++++ .../Graphics/UserInterface/ClickableText.cs | 55 ++++++++++++--- 2 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseClickableText.cs diff --git a/osu.Game.Tests/Visual/TestCaseClickableText.cs b/osu.Game.Tests/Visual/TestCaseClickableText.cs new file mode 100644 index 0000000000..8bf58d8bf4 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseClickableText.cs @@ -0,0 +1,70 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using System; +using System.Collections.Generic; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseClickableText : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] { + typeof(ClickableText), + typeof(FillFlowContainer) + }; + + public TestCaseClickableText() + { + ClickableText text; + + Add(new FillFlowContainer + { + Spacing = new Vector2(10), + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new[] + { + new ClickableText + { + Text = "Default", + }, + new ClickableText + { + IsEnabled = false, + Text = "Disabled", + }, + new ClickableText + { + Text = "Without sounds", + IsMuted = true, + }, + new ClickableText + { + Text = "Without click sounds", + IsClickMuted = true, + }, + new ClickableText + { + Text = "Without hover sounds", + IsHoverMuted = true, + }, + text = new ClickableText + { + Text = "Disables after click (Action)", + }, + new ClickableText + { + Text = "Has tooltip", + TooltipText = "Yep", + }, + }, + }); + text.Action = () => text.IsEnabled = false; + } + } +} diff --git a/osu.Game/Graphics/UserInterface/ClickableText.cs b/osu.Game/Graphics/UserInterface/ClickableText.cs index 8d0e98d687..a97569c4c1 100644 --- a/osu.Game/Graphics/UserInterface/ClickableText.cs +++ b/osu.Game/Graphics/UserInterface/ClickableText.cs @@ -1,44 +1,81 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Input; +using osu.Game.Graphics.Sprites; using System; namespace osu.Game.Graphics.UserInterface -{ - public class ClickableText : SpriteText, IHasTooltip +{/// +/// +/// + public class ClickableText : OsuSpriteText, IHasTooltip { private bool isEnabled; + private bool isMuted; private SampleChannel sampleHover; private SampleChannel sampleClick; + /// + /// An action that can be set to execute after click. + /// public Action Action; + /// + /// If set to true, a sound will be played on click. + /// + public bool IsClickMuted; + + /// + /// If set to true, a sound will be played on hover. + /// + public bool IsHoverMuted; + + /// + /// If disabled, no sounds will be played and wont execute. + /// True by default. + /// public bool IsEnabled { get { return isEnabled; } set { isEnabled = value; - Alpha = value ? 1 : 0.5f; + this.FadeTo(value ? 1 : 0.5f, 250); } } + /// + /// Whether to play sounds on hover and click. Automatically sets + /// and to the same value.> + /// + public bool IsMuted { + get { return isMuted; } + set + { + IsHoverMuted = value; + IsClickMuted = value; + isMuted = value; + } + } + + /// + /// A text with sounds on hover and click, + /// an action that can be set to execute on click, + /// and a tooltip. + /// public ClickableText() => isEnabled = true; public override bool HandleMouseInput => true; protected override bool OnHover(InputState state) { - if (isEnabled) + if (isEnabled && !IsHoverMuted) sampleHover?.Play(); return base.OnHover(state); } @@ -47,7 +84,8 @@ namespace osu.Game.Graphics.UserInterface { if (isEnabled) { - sampleClick?.Play(); + if (!IsClickMuted) + sampleClick?.Play(); Action?.Invoke(); } return base.OnClick(state); @@ -58,6 +96,7 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(AudioManager audio) { + sampleClick = audio.Sample.Get(@"UI/generic-select-soft"); sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); } } From 2982fe35870d275d0fdbd93cd11c99fc92ad1130 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 09:19:26 +0200 Subject: [PATCH 0045/5608] Compress Test Case; Remove empty summary --- .../Visual/TestCaseClickableText.cs | 57 +++---------------- .../Graphics/UserInterface/ClickableText.cs | 4 +- 2 files changed, 10 insertions(+), 51 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseClickableText.cs b/osu.Game.Tests/Visual/TestCaseClickableText.cs index 8bf58d8bf4..fb0edf2989 100644 --- a/osu.Game.Tests/Visual/TestCaseClickableText.cs +++ b/osu.Game.Tests/Visual/TestCaseClickableText.cs @@ -1,8 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; -using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.UserInterface; using System; @@ -12,57 +10,20 @@ namespace osu.Game.Tests.Visual { public class TestCaseClickableText : OsuTestCase { - public override IReadOnlyList RequiredTypes => new[] { - typeof(ClickableText), - typeof(FillFlowContainer) - }; + public override IReadOnlyList RequiredTypes => new[] { typeof(ClickableText) }; public TestCaseClickableText() { ClickableText text; - Add(new FillFlowContainer - { - Spacing = new Vector2(10), - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Children = new[] - { - new ClickableText - { - Text = "Default", - }, - new ClickableText - { - IsEnabled = false, - Text = "Disabled", - }, - new ClickableText - { - Text = "Without sounds", - IsMuted = true, - }, - new ClickableText - { - Text = "Without click sounds", - IsClickMuted = true, - }, - new ClickableText - { - Text = "Without hover sounds", - IsHoverMuted = true, - }, - text = new ClickableText - { - Text = "Disables after click (Action)", - }, - new ClickableText - { - Text = "Has tooltip", - TooltipText = "Yep", - }, - }, + AddRange(new[] { + new ClickableText{ Text = "Default", }, + new ClickableText{ IsEnabled = false, Text = "Disabled", }, + new ClickableText{ Text = "Without sounds", IsMuted = true, }, + new ClickableText{ Text = "Without click sounds", IsClickMuted = true, }, + new ClickableText{ Text = "Without hover sounds", IsHoverMuted = true, }, + text = new ClickableText{ Text = "Disables after click (Action)", }, + new ClickableText{ Text = "Has tooltip", TooltipText = "Yep", } }); text.Action = () => text.IsEnabled = false; } diff --git a/osu.Game/Graphics/UserInterface/ClickableText.cs b/osu.Game/Graphics/UserInterface/ClickableText.cs index a97569c4c1..f2f9f12228 100644 --- a/osu.Game/Graphics/UserInterface/ClickableText.cs +++ b/osu.Game/Graphics/UserInterface/ClickableText.cs @@ -11,9 +11,7 @@ using osu.Game.Graphics.Sprites; using System; namespace osu.Game.Graphics.UserInterface -{/// -/// -/// +{ public class ClickableText : OsuSpriteText, IHasTooltip { private bool isEnabled; From 2ea5a97784b7c46f4a34e28572ea5662e7829b58 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 09:31:51 +0200 Subject: [PATCH 0046/5608] Fix ClickableText test case --- .../Visual/TestCaseClickableText.cs | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseClickableText.cs b/osu.Game.Tests/Visual/TestCaseClickableText.cs index fb0edf2989..32167bc00a 100644 --- a/osu.Game.Tests/Visual/TestCaseClickableText.cs +++ b/osu.Game.Tests/Visual/TestCaseClickableText.cs @@ -10,20 +10,25 @@ namespace osu.Game.Tests.Visual { public class TestCaseClickableText : OsuTestCase { - public override IReadOnlyList RequiredTypes => new[] { typeof(ClickableText) }; + public override IReadOnlyList RequiredTypes => new[] { typeof(ClickableText), typeof(FillFlowContainer) }; public TestCaseClickableText() { ClickableText text; - AddRange(new[] { - new ClickableText{ Text = "Default", }, - new ClickableText{ IsEnabled = false, Text = "Disabled", }, - new ClickableText{ Text = "Without sounds", IsMuted = true, }, - new ClickableText{ Text = "Without click sounds", IsClickMuted = true, }, - new ClickableText{ Text = "Without hover sounds", IsHoverMuted = true, }, - text = new ClickableText{ Text = "Disables after click (Action)", }, - new ClickableText{ Text = "Has tooltip", TooltipText = "Yep", } + Add(new FillFlowContainer + { + Direction = FillDirection.Vertical, + Children = new[] + { + new ClickableText{ Text = "Default", }, + new ClickableText{ IsEnabled = false, Text = "Disabled", }, + new ClickableText{ Text = "Without sounds", IsMuted = true, }, + new ClickableText{ Text = "Without click sounds", IsClickMuted = true, }, + new ClickableText{ Text = "Without hover sounds", IsHoverMuted = true, }, + text = new ClickableText{ Text = "Disables after click (Action)", }, + new ClickableText{ Text = "Has tooltip", TooltipText = "Yep", } + } }); text.Action = () => text.IsEnabled = false; } From 8de65066dd0f70717ce1bb63ebac7fedd28a439f Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 10:28:53 +0200 Subject: [PATCH 0047/5608] Use shorter expression --- osu.Game/Overlays/Changelog/ChangelogContent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 36f9d3fec6..f2f2c1b73d 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -129,7 +129,7 @@ namespace osu.Game.Overlays.Changelog private void fetchAndShowChangelog() { var req = new GetChangelogRequest(); - req.Success += res => add(res); + req.Success += add; api.Queue(req); } From 7e327fd084ddc6e2b0df9c4349e27d7a69d3cb59 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 12:02:45 +0200 Subject: [PATCH 0048/5608] Use using --- osu.Game.Tests/Visual/TestCaseClickableText.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseClickableText.cs b/osu.Game.Tests/Visual/TestCaseClickableText.cs index 32167bc00a..10b5e1b112 100644 --- a/osu.Game.Tests/Visual/TestCaseClickableText.cs +++ b/osu.Game.Tests/Visual/TestCaseClickableText.cs @@ -12,11 +12,11 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { typeof(ClickableText), typeof(FillFlowContainer) }; - public TestCaseClickableText() - { - ClickableText text; + ClickableText text; - Add(new FillFlowContainer + protected override void LoadComplete() + { + using (var fillFlowContainer = new FillFlowContainer { Direction = FillDirection.Vertical, Children = new[] @@ -29,8 +29,12 @@ namespace osu.Game.Tests.Visual text = new ClickableText{ Text = "Disables after click (Action)", }, new ClickableText{ Text = "Has tooltip", TooltipText = "Yep", } } - }); + }) + { + Add(fillFlowContainer); + } text.Action = () => text.IsEnabled = false; + base.LoadComplete(); } } } From 59cbc58edd93a04d9ed559e10f88e0a6dff7a09b Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 13:04:39 +0200 Subject: [PATCH 0049/5608] Show changelog by default --- osu.Game/Overlays/ChangelogOverlay.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 0a2c5e9b6f..0af9f57c03 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -74,12 +74,16 @@ namespace osu.Game.Overlays header = new ChangelogHeader(), Streams = new ChangelogStreams(), chart = new ChangelogChart(), - content = new ChangelogContent(), + content = new ChangelogContent() }, }, }, }; - OnLoadComplete += d => FetchChangelog(); + OnLoadComplete += d => + { + FetchChangelog(); + content.ShowListing(); + }; Streams.OnSelection = () => { if (Streams.SelectedRelease != null) From 2b7f657f2c579df5788d1d5789f9952855a8a822 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 14:44:11 +0200 Subject: [PATCH 0050/5608] Place HTML messages in a TextFlowContainer Add missing accessibility modifier in ClickableText test case and fix disposal --- .../Visual/TestCaseClickableText.cs | 31 ++++++------------- .../Changelog/ChangelogContentGroup.cs | 15 +++++---- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseClickableText.cs b/osu.Game.Tests/Visual/TestCaseClickableText.cs index 10b5e1b112..15401724d1 100644 --- a/osu.Game.Tests/Visual/TestCaseClickableText.cs +++ b/osu.Game.Tests/Visual/TestCaseClickableText.cs @@ -12,29 +12,18 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { typeof(ClickableText), typeof(FillFlowContainer) }; - ClickableText text; - - protected override void LoadComplete() + public TestCaseClickableText() => Child = new FillFlowContainer { - using (var fillFlowContainer = new FillFlowContainer + Children = new[] { - Direction = FillDirection.Vertical, - Children = new[] - { - new ClickableText{ Text = "Default", }, - new ClickableText{ IsEnabled = false, Text = "Disabled", }, - new ClickableText{ Text = "Without sounds", IsMuted = true, }, - new ClickableText{ Text = "Without click sounds", IsClickMuted = true, }, - new ClickableText{ Text = "Without hover sounds", IsHoverMuted = true, }, - text = new ClickableText{ Text = "Disables after click (Action)", }, - new ClickableText{ Text = "Has tooltip", TooltipText = "Yep", } - } - }) - { - Add(fillFlowContainer); + new ClickableText { Text = "Default", }, + new ClickableText { IsEnabled = false, Text = "Disabled", }, + new ClickableText { Text = "Without sounds", IsMuted = true, }, + new ClickableText { Text = "Without click sounds", IsClickMuted = true, }, + new ClickableText { Text = "Without hover sounds", IsHoverMuted = true, }, + new ClickableText { Text = "Disables after click (Action)", }, + new ClickableText { Text = "Has tooltip", TooltipText = "Yep", }, } - text.Action = () => text.IsEnabled = false; - base.LoadComplete(); - } + }; } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 36127d585e..504b3f78eb 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -156,6 +156,7 @@ namespace osu.Game.Overlays.Changelog Font = @"Exo2.0-Light", Colour = StreamColour.FromStreamName(build.UpdateStream.Name), Action = () => BuildRequested(), + IsClickMuted = true, }, } }, @@ -211,7 +212,7 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Full, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - LineSpacing = 0.25f, + Margin = new MarginPadding{ Vertical = 5, }, }); title.AddIcon(FontAwesome.fa_check, t => { t.TextSize = 12; t.Padding = new MarginPadding { Left = -17, Right = 5 }; }); title.AddText(entry.Title, t => { t.TextSize = 18; }); //t.Padding = new MarginPadding(10); }); @@ -224,15 +225,17 @@ namespace osu.Game.Overlays.Changelog }); } title.AddText($" by {entry.GithubUser.DisplayName}", t => t.TextSize = 14); //web: 12; - ChangelogEntries.Add(new SpriteText + TextFlowContainer messageContainer; + ChangelogEntries.Add(messageContainer = new OsuTextFlowContainer { - TextSize = 14, // web: 12, - Colour = new Color4(235, 184, 254, 255), - Text = $"{entry.MessageHtml?.Replace("

", "").Replace("

", "")}\n", - Margin = new MarginPadding { Bottom = 10, }, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, }); + messageContainer.AddText($"{entry.MessageHtml?.Replace("

", "").Replace("

", "")}\n", t => + { + t.TextSize = 14; // web: 12, + t.Colour = new Color4(235, 184, 254, 255); + }); } } } From 421c95156b420c5eda20807419c19393646cc9ab Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 15:16:42 +0200 Subject: [PATCH 0051/5608] Fix ClickableText test case --- osu.Game.Tests/Visual/TestCaseClickableText.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseClickableText.cs b/osu.Game.Tests/Visual/TestCaseClickableText.cs index 15401724d1..60ee764cfc 100644 --- a/osu.Game.Tests/Visual/TestCaseClickableText.cs +++ b/osu.Game.Tests/Visual/TestCaseClickableText.cs @@ -12,6 +12,7 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { typeof(ClickableText), typeof(FillFlowContainer) }; + private readonly ClickableText text; public TestCaseClickableText() => Child = new FillFlowContainer { Children = new[] @@ -21,7 +22,7 @@ namespace osu.Game.Tests.Visual new ClickableText { Text = "Without sounds", IsMuted = true, }, new ClickableText { Text = "Without click sounds", IsClickMuted = true, }, new ClickableText { Text = "Without hover sounds", IsHoverMuted = true, }, - new ClickableText { Text = "Disables after click (Action)", }, + text = new ClickableText { Text = "Disables after click (Action)", Action = () => text.IsEnabled = false }, new ClickableText { Text = "Has tooltip", TooltipText = "Yep", }, } }; From b3f789e19a0953e4f6a8596a9acfa2d283f11638 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 18:35:29 +0200 Subject: [PATCH 0052/5608] Rewrite ChangelogOverlay.cs --- osu.Game/Overlays/ChangelogOverlay.cs | 88 +++++++++++---------------- 1 file changed, 37 insertions(+), 51 deletions(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 0af9f57c03..4359741354 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -13,7 +13,6 @@ using osu.Game.Graphics.Containers; using osu.Game.Input.Bindings; using osu.Game.Online.API; using osu.Game.Online.API.Requests; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Changelog; namespace osu.Game.Overlays @@ -21,13 +20,15 @@ namespace osu.Game.Overlays public class ChangelogOverlay : WaveOverlayContainer { private readonly ChangelogHeader header; - public readonly ChangelogStreams Streams; + private readonly ChangelogBadges badges; private readonly ChangelogChart chart; - private APIChangelog changelogEntry; + private readonly ChangelogContent content; + + private readonly Color4 purple = new Color4(191, 4, 255, 255); private APIAccess api; - protected readonly Color4 Purple = new Color4(191, 4, 255, 255); + private bool isAtListing; public ChangelogOverlay() { @@ -43,8 +44,6 @@ namespace osu.Game.Overlays Width = 0.85f; Masking = true; - ChangelogContent content; // told by appveyor to convert to local variable.. - EdgeEffect = new EdgeEffectParameters { Colour = Color4.Black.Opacity(0), @@ -72,49 +71,22 @@ namespace osu.Game.Overlays Children = new Drawable[] { header = new ChangelogHeader(), - Streams = new ChangelogStreams(), + badges = new ChangelogBadges(), chart = new ChangelogChart(), content = new ChangelogContent() }, }, }, }; - OnLoadComplete += d => - { - FetchChangelog(); - content.ShowListing(); - }; - Streams.OnSelection = () => - { - if (Streams.SelectedRelease != null) - { - header.ChangelogEntry = Streams.SelectedRelease; - } - header.ShowReleaseStream(); - content.ShowBuild(Streams.SelectedRelease); - chart.ShowChart(Streams.SelectedRelease); - }; - header.OnListingActivated += () => - { - Streams.SelectedRelease = null; - content.ShowListing(); - if (!Streams.IsHovered) - foreach (StreamBadge item in Streams.BadgesContainer.Children) - item.Activate(true); - else - foreach (StreamBadge item in Streams.BadgesContainer.Children) - item.Deactivate(); - chart.ShowChart(); - }; - content.OnBuildChanged = () => - { - header.ChangelogEntry = content.CurrentBuild; - header.ShowReleaseStream(); - }; + // content.ShowListing(); + // if (!Streams.IsHovered) + // foreach (StreamBadge item in Streams.BadgesContainer.Children) + // item.Activate(true); + // else + // foreach (StreamBadge item in Streams.BadgesContainer.Children) + // item.Deactivate(); } - public void ActivateListing() => header.ActivateListing(); - // receive input outside our bounds so we can trigger a close event on ourselves. public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; @@ -123,10 +95,10 @@ namespace osu.Game.Overlays switch (action) { case GlobalAction.Back: - if (header.IsListingActivated()) + if (isAtListing) State = Visibility.Hidden; else - header.ActivateListing(); + FetchAndShowListing(); return true; } @@ -151,16 +123,30 @@ namespace osu.Game.Overlays this.api = api; } - public void FetchChangelog() + /// + /// Fetches and shows changelog listing. + /// + public void FetchAndShowListing() { var req = new GetChangelogLatestBuildsRequest(); - req.Success += res => - { - Streams.BadgesContainer.Clear(); - foreach (APIChangelog item in res) - Streams.BadgesContainer.Add(new StreamBadge(item)); - chart.ShowChart(); - }; + header.ShowListing(); + badges.SelectNone(); + chart.ShowAllUpdateStreams(); + req.Success += content.ShowListing; + api.Queue(req); + } + + /// + /// Fetches and shows a specific build from a specific update stream. + /// + /// If true, will select fetched build's update stream badge. + public void FetchAndShowBuild(string updateStream, string version) + { + var req = new GetChangelogBuildRequest(updateStream, version); + header.ShowBuild(updateStream, version); + badges.SelectBadge(updateStream); + chart.ShowUpdateStream(updateStream); + req.Success += content.ShowBuild; api.Queue(req); } } From 797abd558f38647e042d283138c234addf1a6c87 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 18:44:45 +0200 Subject: [PATCH 0053/5608] Rewrite ChangelogHeader.cs --- .../Overlays/Changelog/ChangelogHeader.cs | 42 +++++-------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index a744fc3c97..6a7ccacdc3 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -26,9 +26,7 @@ namespace osu.Game.Overlays.Changelog private readonly TextBadgePairListing listing; private readonly TextBadgePairRelease releaseStream; - public Action OnListingActivated; - - public APIChangelog ChangelogEntry; + public Action ListingActivated; private const float cover_height = 280; private const float title_height = 50; @@ -160,41 +158,21 @@ namespace osu.Game.Overlays.Changelog Origin = Anchor.CentreLeft, }, }; - - // is this a bad way to do this? - OnLoadComplete = d => - { - releaseStream.OnActivation = () => - { - listing.Deactivate(); - chevron.MoveToX(0, 100).FadeIn(100); - }; - listing.OnActivation = () => - { - releaseStream.Deactivate(); - chevron.MoveToX(-20, 100).FadeOut(100); - changeHeaderText("Listing"); - OnListingActivated?.Invoke(); - }; - }; } - public void ShowReleaseStream() + public void ShowBuild(string updateStream, string version) { - releaseStream.Activate(String.Join(" ", - ChangelogEntry.UpdateStream.DisplayName, ChangelogEntry.DisplayVersion)); - changeHeaderText(ChangelogEntry.UpdateStream.DisplayName); - } - - private void changeHeaderText(string headerText) - { - titleStream.Text = headerText; + listing.Deactivate(); + releaseStream.Activate($"{updateStream} {version}"); + titleStream.Text = updateStream; titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); } - public void ActivateListing() => listing.Activate(); - - public bool IsListingActivated() => listing.IsActivated; + public void ShowListing() + { + releaseStream.Deactivate(); + listing.Activate(); + } [BackgroundDependencyLoader] private void load(TextureStore textures) From a8bbcca0e06de761ddce0eac18024e00001df466 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 19:51:31 +0200 Subject: [PATCH 0054/5608] Rewrite ChangelogBadges --- .../Overlays/Changelog/ChangelogBadges.cs | 130 ++++++++++++++++++ osu.Game/Overlays/Changelog/StreamBadge.cs | 8 +- 2 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Overlays/Changelog/ChangelogBadges.cs diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs new file mode 100644 index 0000000000..8bd52e76bc --- /dev/null +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -0,0 +1,130 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Game.Online.API.Requests.Responses; +using System; +using System.Collections.Generic; + +namespace osu.Game.Overlays.Changelog +{ + public class ChangelogBadges : Container + { + private const float container_height = 106.5f; + private const float padding_y = 20; + private const float padding_x = 85; + + public delegate void SelectionHandler(string updateStream, string version, EventArgs args); + + public event SelectionHandler Selected; + + private readonly FillFlowContainer badgesContainer; + + public ChangelogBadges() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new Color4(32, 24, 35, 255), + }, + badgesContainer = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding + { + Top = padding_y, + Bottom = padding_y, + Left = padding_x, + Right = padding_x, + }, + }, + }; + //foreach (StreamBadge streamBadge in BadgesContainer.Children) + //{ + // streamBadge.OnActivation = () => + // { + // SelectedRelease = streamBadge.ChangelogEntry; + // foreach (StreamBadge item in BadgesContainer.Children) + // if (item.ChangelogEntry.Id != streamBadge.ChangelogEntry.Id) + // item.Deactivate(); + // OnSelection?.Invoke(); + // }; + //} + } + + public void Populate(List latestBuilds) + { + foreach (APIChangelog updateStream in latestBuilds) + { + var streamBadge = new StreamBadge(updateStream); + streamBadge.Selected += OnBadgeSelected; + badgesContainer.Add(streamBadge); + } + } + + public void SelectNone() + { + foreach (StreamBadge streamBadge in badgesContainer) + streamBadge.Deactivate(); + } + + public void SelectUpdateStream(string updateStream) + { + foreach (StreamBadge streamBadge in badgesContainer) + if (streamBadge.ChangelogEntry.UpdateStream.Name == updateStream) + { + streamBadge.Activate(); + return; + } + } + + private void OnBadgeSelected(StreamBadge source, EventArgs args) + { + OnSelected(source); + } + + protected virtual void OnSelected(StreamBadge source) + { + if (Selected != null) + Selected(source.ChangelogEntry.UpdateStream.Name, source.ChangelogEntry.Version, EventArgs.Empty); + } + + //protected override bool OnHover(InputState state) + //{ + // foreach (StreamBadge streamBadge in BadgesContainer.Children) + // { + // if (SelectedRelease != null) + // { + // if (SelectedRelease.UpdateStream.Id != streamBadge.ChangelogEntry.UpdateStream.Id) + // streamBadge.Deactivate(); + // else + // streamBadge.EnableDim(); + // } + // else + // streamBadge.Deactivate(); + // } + // return base.OnHover(state); + //} + + //protected override void OnHoverLost(InputState state) + //{ + // foreach (StreamBadge streamBadge in BadgesContainer.Children) + // { + // if (SelectedRelease == null) + // streamBadge.Activate(true); + // else if (streamBadge.ChangelogEntry.UpdateStream.Id == SelectedRelease.UpdateStream.Id) + // streamBadge.DisableDim(); + // } + // base.OnHoverLost(state); + //} + } +} diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 80b2fb2a03..8294e6c403 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -21,7 +21,9 @@ namespace osu.Game.Overlays.Changelog private const float badge_width = 100; private const float transition_duration = 100; - public Action OnActivation; + public delegate void SelectedHandler(StreamBadge source, EventArgs args); + + public event SelectedHandler Selected; private bool isActivated; @@ -88,8 +90,8 @@ namespace osu.Game.Overlays.Changelog isActivated = true; this.FadeIn(transition_duration); lineBadge.IsCollapsed = false; - if (!withoutHeaderUpdate) - OnActivation?.Invoke(); + if (!withoutHeaderUpdate && Selected != null) + Selected(this, EventArgs.Empty); } public void Deactivate() From eca6265186d7da9e14eafe9dab47b32a6ff5c6ff Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 20:14:28 +0200 Subject: [PATCH 0055/5608] Rewrite ChangelogContent.cs --- .../Overlays/Changelog/ChangelogContent.cs | 94 +++---------------- 1 file changed, 15 insertions(+), 79 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index f2f2c1b73d..d06ef32420 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -15,11 +15,13 @@ namespace osu.Game.Overlays.Changelog { public class ChangelogContent : FillFlowContainer { - public APIChangelog CurrentBuild { get; private set; } - public Action OnBuildChanged; private APIAccess api; private ChangelogContentGroup changelogContentGroup; + public delegate void BuildSelectedEventHandler(string updateStream, string version, EventArgs args); + + public event BuildSelectedEventHandler BuildSelected; + public ChangelogContent() { RelativeSizeAxes = Axes.X; @@ -48,10 +50,9 @@ namespace osu.Game.Overlays.Changelog Margin = new MarginPadding { Top = 30, }, }); } - Add(changelogContentGroup = new ChangelogContentGroup(build, true) - { - BuildRequested = () => showBuild(build), - }); + // watch out for this? + Add(changelogContentGroup = new ChangelogContentGroup(build, true)); + changelogContentGroup.BuildSelected += OnBuildSelected; changelogContentGroup.GenerateText(build.ChangelogEntries); currentDate = build.CreatedAt.Date; } @@ -64,86 +65,21 @@ namespace osu.Game.Overlays.Changelog Colour = new Color4(32, 24, 35, 255), Margin = new MarginPadding { Top = 30, }, }); - Add(changelogContentGroup = new ChangelogContentGroup(build, false) - { - BuildRequested = () => showBuild(build), - }); + Add(changelogContentGroup = new ChangelogContentGroup(build, false)); + changelogContentGroup.BuildSelected += OnBuildSelected; changelogContentGroup.GenerateText(build.ChangelogEntries); } } } + private void OnBuildSelected(string updateStream, string version, EventArgs args) + { + throw new NotImplementedException(); + } + private void add(APIChangelog changelogBuild) { - Child = changelogContentGroup = new ChangelogContentGroup(changelogBuild) - { - PreviousRequested = showPrevious, - NextRequested = showNext, - }; - } - - /// - /// Doesn't send back that the build has changed - /// - public void ShowBuild(APIChangelog changelog) - { - fetchAndShowChangelogBuild(changelog); - CurrentBuild = changelog; - } - - /// - /// Sends back that the build has changed - /// - private void showBuild(APIChangelog changelog) - { - ShowBuild(changelog); - OnBuildChanged(); - } - - public void ShowListing() => fetchAndShowChangelog(); - - private void showNext() - { - if (CurrentBuild.Versions.Next != null) - showBuild(CurrentBuild.Versions.Next); - } - - private void showPrevious() - { - if (CurrentBuild.Versions.Previous != null) - showBuild(CurrentBuild.Versions.Previous); - } - - private void updateChevronTooltips() - { - changelogContentGroup.UpdateChevronTooltips(CurrentBuild.Versions.Previous?.DisplayVersion, - CurrentBuild.Versions.Next?.DisplayVersion); - } - - [BackgroundDependencyLoader] - private void load(APIAccess api) - { - this.api = api; - } - - private void fetchAndShowChangelog() - { - var req = new GetChangelogRequest(); - req.Success += add; - api.Queue(req); - } - - private void fetchAndShowChangelogBuild(APIChangelog build) - { - var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); - req.Success += res => - { - CurrentBuild = res; - add(CurrentBuild); - changelogContentGroup.GenerateText(CurrentBuild.ChangelogEntries); - updateChevronTooltips(); - }; - api.Queue(req); + Child = changelogContentGroup = new ChangelogContentGroup(changelogBuild); } } } From 6683d4cabeac6446c1b402129716f2ece6bafe8c Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 20:14:58 +0200 Subject: [PATCH 0056/5608] Add event handling in content groups --- .../Changelog/ChangelogContentGroup.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 504b3f78eb..0efa8b70c6 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -21,7 +21,10 @@ namespace osu.Game.Overlays.Changelog private readonly SortedDictionary> categories = new SortedDictionary>(); - public Action NextRequested, PreviousRequested, BuildRequested; + public delegate void BuildSelectedEventHandler(string updateStream, string version, EventArgs args); + + public event BuildSelectedEventHandler BuildSelected; + public readonly FillFlowContainer ChangelogEntries; public ChangelogContentGroup(APIChangelog build) @@ -50,7 +53,8 @@ namespace osu.Game.Overlays.Changelog IsEnabled = false, Icon = FontAwesome.fa_chevron_left, Size = new Vector2(24), - Action = () => PreviousRequested(), + Action = () => OnBuildSelected(build.Versions.Previous.UpdateStream.Name, + build.Versions.Previous.Version), }, new FillFlowContainer { @@ -87,7 +91,8 @@ namespace osu.Game.Overlays.Changelog IsEnabled = false, Icon = FontAwesome.fa_chevron_right, Size = new Vector2(24), - Action = () => NextRequested(), + Action = () => OnBuildSelected(build.Versions.Next.UpdateStream.Name, + build.Versions.Next.Version), }, } }, @@ -155,7 +160,7 @@ namespace osu.Game.Overlays.Changelog TextSize = 20, // web: 18, Font = @"Exo2.0-Light", Colour = StreamColour.FromStreamName(build.UpdateStream.Name), - Action = () => BuildRequested(), + Action = () => OnBuildSelected(build.UpdateStream.Name, build.Version), IsClickMuted = true, }, } @@ -183,6 +188,12 @@ namespace osu.Game.Overlays.Changelog } } + protected virtual void OnBuildSelected(string updateStream, string version) + { + if (BuildSelected != null) + BuildSelected(updateStream, version, EventArgs.Empty); + } + public void GenerateText(List changelogEntries) { // sort entries by category From 23309b3b0045abe3fef10c93869761b97a57f48c Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 20:27:20 +0200 Subject: [PATCH 0057/5608] Strip test case --- osu.Game.Tests/Visual/TestCaseChangelog.cs | 55 ---------------------- 1 file changed, 55 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseChangelog.cs b/osu.Game.Tests/Visual/TestCaseChangelog.cs index ea6aa8086f..0710f7a254 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelog.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelog.cs @@ -10,67 +10,12 @@ namespace osu.Game.Tests.Visual public class TestCaseChangelog : OsuTestCase { private ChangelogOverlay changelog; - private int index; - private void indexIncrement() => index = index >= changelog.Streams.BadgesContainer.Children.Count - 1 ? 0 : index + 1; - private bool isLoaded => changelog.Streams.BadgesContainer.Children.Count > 0; protected override void LoadComplete() { base.LoadComplete(); Add(changelog = new ChangelogOverlay()); - - AddStep(@"Show", changelog.Show); - AddRepeatStep(@"Toggle Release Stream", () => - { - if (isLoaded) - changelog.Streams.BadgesContainer.Children[index].Activate(); - indexIncrement(); - }, 6); - AddStep(@"Listing", changelog.ActivateListing); - AddStep(@"Hide", changelog.Hide); - AddWaitStep(3); - AddStep(@"Show with Release Stream", () => - { - if (isLoaded) - changelog.Streams.BadgesContainer.Children[index].Activate(); - changelog.Show(); - indexIncrement(); - }); - AddWaitStep(3); - AddStep(@"Hide", changelog.Hide); - AddWaitStep(3); - AddStep(@"Show with listing", () => - { - changelog.ActivateListing(); - changelog.Show(); - }); - AddWaitStep(3); - AddStep(@"Hide", changelog.Hide); - AddWaitStep(3); - AddStep(@"Activate release", () => - { - if (isLoaded) - changelog.Streams.BadgesContainer.Children[index].Activate(); - indexIncrement(); - }); - AddStep(@"Show with listing", () => - { - changelog.ActivateListing(); - changelog.Show(); - }); - AddStep(@"Activate Release", () => - { - if (isLoaded) - changelog.Streams.BadgesContainer.Children[index].Activate(); - }); - AddStep(@"Activate Listing", changelog.ActivateListing); - AddStep(@"Activate Release", () => - { - if (isLoaded) - changelog.Streams.BadgesContainer.Children[index].Activate(); - indexIncrement(); - }); } } } From 61a8b98d32fe7a3295354ac6c1fc2787b14feec6 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 20:27:50 +0200 Subject: [PATCH 0058/5608] Rewrite improvements --- osu.Game/Overlays/Changelog/ChangelogChart.cs | 14 +-- .../Overlays/Changelog/ChangelogContent.cs | 20 ++-- .../Overlays/Changelog/ChangelogStreams.cs | 98 ------------------- osu.Game/Overlays/ChangelogOverlay.cs | 10 +- 4 files changed, 24 insertions(+), 118 deletions(-) delete mode 100644 osu.Game/Overlays/Changelog/ChangelogStreams.cs diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index b8df166a19..91e2aa5e49 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -43,15 +43,9 @@ namespace osu.Game.Overlays.Changelog }; } - /// - /// Draw the graph with all builds - /// - public void ShowChart() => fetchAndShowChangelogChart(); - /// /// Draw the graph for a specific build /// - public void ShowChart(APIChangelog releaseStream) => fetchAndShowChangelogChart(releaseStream); private bool isEmpty(APIChangelogChart changelogChart) { @@ -81,14 +75,14 @@ namespace osu.Game.Overlays.Changelog this.api = api; } - private void fetchAndShowChangelogChart(APIChangelog build) + public void ShowUpdateStream(string updateStream) { - var req = new GetChangelogChartRequest(build.UpdateStream.Name); - req.Success += res => showChart(res, build.UpdateStream.Name); + var req = new GetChangelogChartRequest(updateStream); + req.Success += res => showChart(res, updateStream); api.Queue(req); } - private void fetchAndShowChangelogChart() + public void ShowAllUpdateStreams() { var req = new GetChangelogChartRequest(); req.Success += res => showChart(res); diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index d06ef32420..5eb19119ec 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -10,6 +10,7 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using System; +using System.Collections.Generic; namespace osu.Game.Overlays.Changelog { @@ -30,7 +31,7 @@ namespace osu.Game.Overlays.Changelog Padding = new MarginPadding{ Bottom = 100, }; } - private void add(APIChangelog[] changelog) + public void ShowListing(List changelog) { DateTime currentDate = new DateTime(); @@ -52,7 +53,7 @@ namespace osu.Game.Overlays.Changelog } // watch out for this? Add(changelogContentGroup = new ChangelogContentGroup(build, true)); - changelogContentGroup.BuildSelected += OnBuildSelected; + changelogContentGroup.BuildSelected += onBuildSelected; changelogContentGroup.GenerateText(build.ChangelogEntries); currentDate = build.CreatedAt.Date; } @@ -66,20 +67,21 @@ namespace osu.Game.Overlays.Changelog Margin = new MarginPadding { Top = 30, }, }); Add(changelogContentGroup = new ChangelogContentGroup(build, false)); - changelogContentGroup.BuildSelected += OnBuildSelected; + changelogContentGroup.BuildSelected += onBuildSelected; changelogContentGroup.GenerateText(build.ChangelogEntries); } } } - private void OnBuildSelected(string updateStream, string version, EventArgs args) - { - throw new NotImplementedException(); - } - - private void add(APIChangelog changelogBuild) + public void ShowBuild(APIChangelog changelogBuild) { Child = changelogContentGroup = new ChangelogContentGroup(changelogBuild); } + + protected virtual void onBuildSelected(string updateStream, string version, EventArgs args) + { + if (BuildSelected != null) + BuildSelected(updateStream, version, EventArgs.Empty); + } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogStreams.cs b/osu.Game/Overlays/Changelog/ChangelogStreams.cs deleted file mode 100644 index 1e6e9e1e51..0000000000 --- a/osu.Game/Overlays/Changelog/ChangelogStreams.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using OpenTK.Graphics; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; -using osu.Game.Online.API.Requests.Responses; -using System; - -namespace osu.Game.Overlays.Changelog -{ - public class ChangelogStreams : Container - { - private const float container_height = 106.5f; - private const float padding_y = 20; - private const float padding_x = 85; - public Action OnSelection; - - public APIChangelog SelectedRelease; - // not using SelectedRelease as a Bindable and then using .OnValueChange instead of OnSelection - // because it doesn't "refresh" the selection if the same stream is chosen - - public readonly FillFlowContainer BadgesContainer; - - public ChangelogStreams() - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = new Color4(32, 24, 35, 255), - }, - BadgesContainer = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding - { - Top = padding_y, - Bottom = padding_y, - Left = padding_x, - Right = padding_x, - }, - }, - }; - // ok, so this is probably not the best. - // how else can this be done? - BadgesContainer.OnUpdate = d => - { - foreach (StreamBadge streamBadge in BadgesContainer.Children) - { - streamBadge.OnActivation = () => - { - SelectedRelease = streamBadge.ChangelogEntry; - foreach (StreamBadge item in BadgesContainer.Children) - if (item.ChangelogEntry.Id != streamBadge.ChangelogEntry.Id) - item.Deactivate(); - OnSelection?.Invoke(); - }; - } - }; - } - - protected override bool OnHover(InputState state) - { - foreach (StreamBadge streamBadge in BadgesContainer.Children) - { - if (SelectedRelease != null) - { - if (SelectedRelease.UpdateStream.Id != streamBadge.ChangelogEntry.UpdateStream.Id) - streamBadge.Deactivate(); - else - streamBadge.EnableDim(); - } - else - streamBadge.Deactivate(); - } - return base.OnHover(state); - } - - protected override void OnHoverLost(InputState state) - { - foreach (StreamBadge streamBadge in BadgesContainer.Children) - { - if (SelectedRelease == null) - streamBadge.Activate(true); - else if (streamBadge.ChangelogEntry.UpdateStream.Id == SelectedRelease.UpdateStream.Id) - streamBadge.DisableDim(); - } - base.OnHoverLost(state); - } - } -} diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 4359741354..2ae5bbdd78 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -14,6 +14,7 @@ using osu.Game.Input.Bindings; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Changelog; +using System; namespace osu.Game.Overlays { @@ -78,6 +79,8 @@ namespace osu.Game.Overlays }, }, }; + + badges.Selected += onBuildSelected; // content.ShowListing(); // if (!Streams.IsHovered) // foreach (StreamBadge item in Streams.BadgesContainer.Children) @@ -117,6 +120,11 @@ namespace osu.Game.Overlays FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); } + private void onBuildSelected(string updateStream, string version, EventArgs e) + { + FetchAndShowBuild(updateStream, version); + } + [BackgroundDependencyLoader] private void load(APIAccess api) { @@ -144,7 +152,7 @@ namespace osu.Game.Overlays { var req = new GetChangelogBuildRequest(updateStream, version); header.ShowBuild(updateStream, version); - badges.SelectBadge(updateStream); + badges.SelectUpdateStream(updateStream); chart.ShowUpdateStream(updateStream); req.Success += content.ShowBuild; api.Queue(req); From 24abec43c1ff780fd017321434b9504649e34f6b Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 21:00:29 +0200 Subject: [PATCH 0059/5608] Show on test case --- osu.Game.Tests/Visual/TestCaseChangelog.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/TestCaseChangelog.cs b/osu.Game.Tests/Visual/TestCaseChangelog.cs index 0710f7a254..da260c239b 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelog.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelog.cs @@ -16,6 +16,7 @@ namespace osu.Game.Tests.Visual base.LoadComplete(); Add(changelog = new ChangelogOverlay()); + AddStep(@"Show", changelog.Show); } } } From 51eec0dca44e11e7a9c1ae29c4d1ce451c5db325 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 22:13:14 +0200 Subject: [PATCH 0060/5608] Further rewrite --- .../Overlays/Changelog/ChangelogBadges.cs | 79 +++++++++++-------- .../Overlays/Changelog/ChangelogContent.cs | 3 +- .../Overlays/Changelog/ChangelogHeader.cs | 6 +- osu.Game/Overlays/Changelog/StreamBadge.cs | 6 +- osu.Game/Overlays/ChangelogOverlay.cs | 30 ++++--- 5 files changed, 71 insertions(+), 53 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index 8bd52e76bc..53f6a75bbc 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -23,6 +23,7 @@ namespace osu.Game.Overlays.Changelog public event SelectionHandler Selected; private readonly FillFlowContainer badgesContainer; + private long selectedStreamId = -1; public ChangelogBadges() { @@ -66,29 +67,43 @@ namespace osu.Game.Overlays.Changelog foreach (APIChangelog updateStream in latestBuilds) { var streamBadge = new StreamBadge(updateStream); - streamBadge.Selected += OnBadgeSelected; + streamBadge.Selected += onBadgeSelected; badgesContainer.Add(streamBadge); } } public void SelectNone() { - foreach (StreamBadge streamBadge in badgesContainer) - streamBadge.Deactivate(); + selectedStreamId = -1; + if (badgesContainer != null) + { + foreach (StreamBadge streamBadge in badgesContainer) + { + if (!IsHovered) + streamBadge.Activate(); + else + streamBadge.Deactivate(); + } + } } public void SelectUpdateStream(string updateStream) { foreach (StreamBadge streamBadge in badgesContainer) + { if (streamBadge.ChangelogEntry.UpdateStream.Name == updateStream) { + selectedStreamId = streamBadge.ChangelogEntry.UpdateStream.Id; streamBadge.Activate(); - return; } + else + streamBadge.Deactivate(); + } } - private void OnBadgeSelected(StreamBadge source, EventArgs args) + private void onBadgeSelected(StreamBadge source, EventArgs args) { + selectedStreamId = source.ChangelogEntry.UpdateStream.Id; OnSelected(source); } @@ -98,33 +113,33 @@ namespace osu.Game.Overlays.Changelog Selected(source.ChangelogEntry.UpdateStream.Name, source.ChangelogEntry.Version, EventArgs.Empty); } - //protected override bool OnHover(InputState state) - //{ - // foreach (StreamBadge streamBadge in BadgesContainer.Children) - // { - // if (SelectedRelease != null) - // { - // if (SelectedRelease.UpdateStream.Id != streamBadge.ChangelogEntry.UpdateStream.Id) - // streamBadge.Deactivate(); - // else - // streamBadge.EnableDim(); - // } - // else - // streamBadge.Deactivate(); - // } - // return base.OnHover(state); - //} + protected override bool OnHover(InputState state) + { + foreach (StreamBadge streamBadge in badgesContainer.Children) + { + if (selectedStreamId < 0) + { + if (selectedStreamId != streamBadge.ChangelogEntry.UpdateStream.Id) + streamBadge.Deactivate(); + else + streamBadge.EnableDim(); + } + else + streamBadge.Deactivate(); + } + return base.OnHover(state); + } - //protected override void OnHoverLost(InputState state) - //{ - // foreach (StreamBadge streamBadge in BadgesContainer.Children) - // { - // if (SelectedRelease == null) - // streamBadge.Activate(true); - // else if (streamBadge.ChangelogEntry.UpdateStream.Id == SelectedRelease.UpdateStream.Id) - // streamBadge.DisableDim(); - // } - // base.OnHoverLost(state); - //} + protected override void OnHoverLost(InputState state) + { + foreach (StreamBadge streamBadge in badgesContainer.Children) + { + if (selectedStreamId < 0) + streamBadge.Activate(true); + else if (streamBadge.ChangelogEntry.UpdateStream.Id == selectedStreamId) + streamBadge.DisableDim(); + } + base.OnHoverLost(state); + } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 5eb19119ec..3b45e4af87 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -10,7 +10,6 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using System; -using System.Collections.Generic; namespace osu.Game.Overlays.Changelog { @@ -31,7 +30,7 @@ namespace osu.Game.Overlays.Changelog Padding = new MarginPadding{ Bottom = 100, }; } - public void ShowListing(List changelog) + public void ShowListing(APIChangelog[] changelog) { DateTime currentDate = new DateTime(); diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 6a7ccacdc3..68875ef126 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -160,11 +160,11 @@ namespace osu.Game.Overlays.Changelog }; } - public void ShowBuild(string updateStream, string version) + public void ShowBuild(string displayName, string displayVersion) { listing.Deactivate(); - releaseStream.Activate($"{updateStream} {version}"); - titleStream.Text = updateStream; + releaseStream.Activate($"{displayName} {displayVersion}"); + titleStream.Text = displayName; titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); } diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 8294e6c403..f4ae2a0cb2 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -85,12 +85,12 @@ namespace osu.Game.Overlays.Changelog }; } - public void Activate(bool withoutHeaderUpdate = false) + public void Activate(bool withoutFiringUpdates = true) { isActivated = true; this.FadeIn(transition_duration); lineBadge.IsCollapsed = false; - if (!withoutHeaderUpdate && Selected != null) + if (!withoutFiringUpdates && Selected != null) Selected(this, EventArgs.Empty); } @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.Changelog protected override bool OnClick(InputState state) { - Activate(); + Activate(false); return base.OnClick(state); } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 2ae5bbdd78..d9a139c6ee 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -79,15 +79,8 @@ namespace osu.Game.Overlays }, }, }; - badges.Selected += onBuildSelected; - // content.ShowListing(); - // if (!Streams.IsHovered) - // foreach (StreamBadge item in Streams.BadgesContainer.Children) - // item.Activate(true); - // else - // foreach (StreamBadge item in Streams.BadgesContainer.Children) - // item.Deactivate(); + header.ListingActivated += FetchAndShowListing; } // receive input outside our bounds so we can trigger a close event on ourselves. @@ -131,12 +124,22 @@ namespace osu.Game.Overlays this.api = api; } + protected override void LoadComplete() + { + var req = new GetChangelogLatestBuildsRequest(); + req.Success += badges.Populate; + api.Queue(req); + FetchAndShowListing(); + base.LoadComplete(); + } + /// /// Fetches and shows changelog listing. /// public void FetchAndShowListing() { - var req = new GetChangelogLatestBuildsRequest(); + isAtListing = true; + var req = new GetChangelogRequest(); header.ShowListing(); badges.SelectNone(); chart.ShowAllUpdateStreams(); @@ -147,14 +150,15 @@ namespace osu.Game.Overlays /// /// Fetches and shows a specific build from a specific update stream. /// - /// If true, will select fetched build's update stream badge. - public void FetchAndShowBuild(string updateStream, string version) + public void FetchAndShowBuild(string updateStream, string version, bool sentByBadges = false) { + isAtListing = false; var req = new GetChangelogBuildRequest(updateStream, version); - header.ShowBuild(updateStream, version); - badges.SelectUpdateStream(updateStream); + if (!sentByBadges) + badges.SelectUpdateStream(updateStream); chart.ShowUpdateStream(updateStream); req.Success += content.ShowBuild; + req.Success += res => header.ShowBuild(res.UpdateStream.DisplayName, res.DisplayVersion); api.Queue(req); } } From 391da478813c0020166009fcc91451ba43a2fef3 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 22 Jul 2018 22:31:24 +0200 Subject: [PATCH 0061/5608] Refactor the rewrite --- osu.Game/Overlays/Changelog/ChangelogBadges.cs | 5 ++--- osu.Game/Overlays/Changelog/ChangelogContent.cs | 11 ++++------- osu.Game/Overlays/Changelog/ChangelogContentGroup.cs | 3 +-- osu.Game/Overlays/Changelog/ChangelogHeader.cs | 5 +++-- osu.Game/Overlays/Changelog/StreamBadge.cs | 4 ++-- 5 files changed, 12 insertions(+), 16 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index 53f6a75bbc..757f0e0727 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -109,8 +109,7 @@ namespace osu.Game.Overlays.Changelog protected virtual void OnSelected(StreamBadge source) { - if (Selected != null) - Selected(source.ChangelogEntry.UpdateStream.Name, source.ChangelogEntry.Version, EventArgs.Empty); + Selected?.Invoke(source.ChangelogEntry.UpdateStream.Name, source.ChangelogEntry.Version, EventArgs.Empty); } protected override bool OnHover(InputState state) @@ -135,7 +134,7 @@ namespace osu.Game.Overlays.Changelog foreach (StreamBadge streamBadge in badgesContainer.Children) { if (selectedStreamId < 0) - streamBadge.Activate(true); + streamBadge.Activate(); else if (streamBadge.ChangelogEntry.UpdateStream.Id == selectedStreamId) streamBadge.DisableDim(); } diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 3b45e4af87..f6e90b83a3 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -2,12 +2,10 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using System; @@ -52,7 +50,7 @@ namespace osu.Game.Overlays.Changelog } // watch out for this? Add(changelogContentGroup = new ChangelogContentGroup(build, true)); - changelogContentGroup.BuildSelected += onBuildSelected; + changelogContentGroup.BuildSelected += OnBuildSelected; changelogContentGroup.GenerateText(build.ChangelogEntries); currentDate = build.CreatedAt.Date; } @@ -66,7 +64,7 @@ namespace osu.Game.Overlays.Changelog Margin = new MarginPadding { Top = 30, }, }); Add(changelogContentGroup = new ChangelogContentGroup(build, false)); - changelogContentGroup.BuildSelected += onBuildSelected; + changelogContentGroup.BuildSelected += OnBuildSelected; changelogContentGroup.GenerateText(build.ChangelogEntries); } } @@ -77,10 +75,9 @@ namespace osu.Game.Overlays.Changelog Child = changelogContentGroup = new ChangelogContentGroup(changelogBuild); } - protected virtual void onBuildSelected(string updateStream, string version, EventArgs args) + protected virtual void OnBuildSelected(string updateStream, string version, EventArgs args) { - if (BuildSelected != null) - BuildSelected(updateStream, version, EventArgs.Empty); + BuildSelected?.Invoke(updateStream, version, EventArgs.Empty); } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 0efa8b70c6..aabc390d49 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -190,8 +190,7 @@ namespace osu.Game.Overlays.Changelog protected virtual void OnBuildSelected(string updateStream, string version) { - if (BuildSelected != null) - BuildSelected(updateStream, version, EventArgs.Empty); + BuildSelected?.Invoke(updateStream, version, EventArgs.Empty); } public void GenerateText(List changelogEntries) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 68875ef126..a4be3bdf7f 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Changelog.Header; using System; @@ -24,6 +23,7 @@ namespace osu.Game.Overlays.Changelog private readonly Sprite headerBadge; private readonly OsuSpriteText titleStream; private readonly TextBadgePairListing listing; + private readonly SpriteIcon chevron; private readonly TextBadgePairRelease releaseStream; public Action ListingActivated; @@ -36,7 +36,6 @@ namespace osu.Game.Overlays.Changelog public ChangelogHeader() { - SpriteIcon chevron; // AppVeyor told me this should be a local variable..? RelativeSizeAxes = Axes.X; Height = cover_height; Children = new Drawable[] @@ -166,12 +165,14 @@ namespace osu.Game.Overlays.Changelog releaseStream.Activate($"{displayName} {displayVersion}"); titleStream.Text = displayName; titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); + chevron.MoveToX(0, 100).FadeIn(100); } public void ShowListing() { releaseStream.Deactivate(); listing.Activate(); + chevron.MoveToX(-20, 100).FadeOut(100); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index f4ae2a0cb2..2a55b9a4b9 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -90,8 +90,8 @@ namespace osu.Game.Overlays.Changelog isActivated = true; this.FadeIn(transition_duration); lineBadge.IsCollapsed = false; - if (!withoutFiringUpdates && Selected != null) - Selected(this, EventArgs.Empty); + if (!withoutFiringUpdates) + Selected?.Invoke(this, EventArgs.Empty); } public void Deactivate() From 4cc5a657f3343ad226c4fe749f066bc8110886f3 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Mon, 23 Jul 2018 10:05:19 +0200 Subject: [PATCH 0062/5608] Follow up framework changes --- osu.Game/Graphics/UserInterface/ClickableText.cs | 2 +- osu.Game/Graphics/UserInterface/TooltipIconButton.cs | 2 +- osu.Game/Overlays/Changelog/ChangelogBadges.cs | 2 +- osu.Game/Overlays/Changelog/Header/TextBadgePair.cs | 2 +- osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs | 2 +- osu.Game/Overlays/Changelog/StreamBadge.cs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ClickableText.cs b/osu.Game/Graphics/UserInterface/ClickableText.cs index f2f9f12228..c27bc56238 100644 --- a/osu.Game/Graphics/UserInterface/ClickableText.cs +++ b/osu.Game/Graphics/UserInterface/ClickableText.cs @@ -6,7 +6,7 @@ using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; -using osu.Framework.Input; +using osu.Framework.Input.States; using osu.Game.Graphics.Sprites; using System; diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index 8b85c8c0ec..7f6641817a 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; +using osu.Framework.Input.States; using System; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index 757f0e0727..0cfd220601 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -5,7 +5,7 @@ using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; +using osu.Framework.Input.States; using osu.Game.Online.API.Requests.Responses; using System; using System.Collections.Generic; diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index 6256c52be2..c01501c308 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input; +using osu.Framework.Input.States; using System; namespace osu.Game.Overlays.Changelog.Header diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs index 425b4b111a..36db135675 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -4,7 +4,7 @@ using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; -using osu.Framework.Input; +using osu.Framework.Input.States; namespace osu.Game.Overlays.Changelog.Header { diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 2a55b9a4b9..44fdeb80a7 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -8,7 +8,7 @@ using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input; +using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; using System; From e27292fef8bd11c6ab7b672278eb513db05fb684 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Mon, 23 Jul 2018 17:49:42 +0200 Subject: [PATCH 0063/5608] Rewrite LineBadge.cs + update all its references --- osu.Game.Tests/Visual/TestCaseLineBadge.cs | 51 +++++++++++ osu.Game/Graphics/UserInterface/LineBadge.cs | 84 +++++++++++++++++++ .../Overlays/Changelog/Header/LineBadge.cs | 44 ---------- .../Changelog/Header/TextBadgePair.cs | 17 ++-- .../Changelog/Header/TextBadgePairListing.cs | 8 +- osu.Game/Overlays/Changelog/StreamBadge.cs | 19 +++-- 6 files changed, 160 insertions(+), 63 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseLineBadge.cs create mode 100644 osu.Game/Graphics/UserInterface/LineBadge.cs delete mode 100644 osu.Game/Overlays/Changelog/Header/LineBadge.cs diff --git a/osu.Game.Tests/Visual/TestCaseLineBadge.cs b/osu.Game.Tests/Visual/TestCaseLineBadge.cs new file mode 100644 index 0000000000..304b0f9518 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseLineBadge.cs @@ -0,0 +1,51 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseLineBadge : OsuTestCase + { + public TestCaseLineBadge() + { + Container containerHorizontal; + LineBadge lineBadge; + + Add(containerHorizontal = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Box + { + Colour = Color4.Gray, + Alpha = 0.5f, + RelativeSizeAxes = Axes.Both, + }, + lineBadge = new LineBadge + { + Anchor = Anchor.Centre, + UncollapsedSize = 10, + CollapsedSize = 2, + Colour = Color4.DeepSkyBlue, + } + } + }); + + AddStep(@"", () => { }); + AddStep(@"Collapse", () => lineBadge.Collapse()); + AddStep(@"Uncollapse", () => lineBadge.Uncollapse()); + AddSliderStep(@"Resize container", 1, 300, 150, value => containerHorizontal.ResizeTo(value)); + AddStep(@"Horizontal", () => lineBadge.IsHorizontal = true); + AddStep(@"Anchor top", () => lineBadge.Anchor = Anchor.TopCentre); + AddStep(@"Vertical", () => lineBadge.IsHorizontal = false); + AddStep(@"Anchor left", () => lineBadge.Anchor = Anchor.CentreLeft); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/LineBadge.cs b/osu.Game/Graphics/UserInterface/LineBadge.cs new file mode 100644 index 0000000000..91dd2add1f --- /dev/null +++ b/osu.Game/Graphics/UserInterface/LineBadge.cs @@ -0,0 +1,84 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; + +namespace osu.Game.Graphics.UserInterface +{ + public class LineBadge : Circle + { + public float UncollapsedSize; + public float CollapsedSize; + + public bool IsCollapsed { get; private set; } + private bool isHorizontal; + + /// + /// Automatically sets the RelativeSizeAxes and switches X and Y components when changed. + /// + public bool IsHorizontal + { + get { return isHorizontal; } + set + { + if (value == isHorizontal) + return; + if (IsLoaded) + { + FinishTransforms(); + var height = Height; + var width = Width; + RelativeSizeAxes = value ? Axes.X : Axes.Y; + Width = height; + Height = width; + } + else + RelativeSizeAxes = value ? Axes.X : Axes.Y; + isHorizontal = value; + } + } + + /// + /// A simple rounded expandable line. Set its + /// property to the center of the edge it's meant stick with. By default, + /// takes up the full parent's axis defined by . + /// + /// Whether to initialize with the + /// or the + public LineBadge(bool startCollapsed = true) + { + IsCollapsed = startCollapsed; + RelativeSizeAxes = Axes.X; + isHorizontal = true; + Origin = Anchor.Centre; + } + + protected override void LoadComplete() + { + if (isHorizontal) + Height = IsCollapsed ? CollapsedSize : UncollapsedSize; + else + Width = IsCollapsed ? CollapsedSize : UncollapsedSize; + base.LoadComplete(); + } + + public void Collapse(float transitionDuration = 400, Easing easing = Easing.Out) + { + IsCollapsed = true; + if (IsHorizontal) + this.ResizeHeightTo(CollapsedSize, transitionDuration, easing); + else + this.ResizeWidthTo(CollapsedSize, transitionDuration, easing); + } + + public void Uncollapse(float transitionDuration = 400, Easing easing = Easing.OutElastic) + { + IsCollapsed = false; + if (IsHorizontal) + this.ResizeHeightTo(UncollapsedSize, transitionDuration, easing); + else + this.ResizeWidthTo(UncollapsedSize, transitionDuration, easing); + } + } +} diff --git a/osu.Game/Overlays/Changelog/Header/LineBadge.cs b/osu.Game/Overlays/Changelog/Header/LineBadge.cs deleted file mode 100644 index 93eca528c5..0000000000 --- a/osu.Game/Overlays/Changelog/Header/LineBadge.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; - -namespace osu.Game.Overlays.Changelog.Header -{ - public class LineBadge : Circle - { - public float TransitionDuration = 400; - public float UncollapsedHeight; - public float CollapsedHeight; - - private bool isCollapsed; - public bool IsCollapsed - { - get { return isCollapsed; } - set - { - isCollapsed = value; - this.ResizeHeightTo(value ? CollapsedHeight : UncollapsedHeight, - value ? TransitionDuration / 2f : TransitionDuration, - value ? Easing.Out : Easing.OutElastic); - } - } - - public LineBadge(bool startCollapsed = true, float collapsedHeight = 1, float uncollapsedHeight = 10) - { - Anchor = Anchor.BottomCentre; - Origin = Anchor.Centre; - CollapsedHeight = collapsedHeight; - UncollapsedHeight = uncollapsedHeight; - Height = startCollapsed ? CollapsedHeight : UncollapsedHeight; - - // this margin prevents jumps when changing text's font weight - Margin = new MarginPadding - { - Left = 10, - Right = 10, - }; - } - } -} diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index c01501c308..6ff945469c 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.States; +using osu.Game.Graphics.UserInterface; using System; namespace osu.Game.Overlays.Changelog.Header @@ -36,14 +37,14 @@ namespace osu.Game.Overlays.Changelog.Header public void HideText(double duration = 0, Easing easing = Easing.InOutCubic) { - LineBadge.IsCollapsed = true; + LineBadge.Collapse(); Text.MoveToY(20, duration, easing) .FadeOut(duration, easing); } public void ShowText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) { - LineBadge.IsCollapsed = false; + LineBadge.Uncollapse(); if (!string.IsNullOrEmpty(displayText)) Text.Text = displayText; Text.MoveToY(0, duration, easing) @@ -55,7 +56,7 @@ namespace osu.Game.Overlays.Changelog.Header /// Full change takes double this time. public void ChangeText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) { - LineBadge.IsCollapsed = true; + LineBadge.Collapse(); Text.MoveToY(20, duration, easing) .FadeOut(duration, easing) .Then() @@ -67,7 +68,7 @@ namespace osu.Game.Overlays.Changelog.Header Scheduler.AddDelayed(() => { if (!string.IsNullOrEmpty(displayText)) Text.Text = displayText; - LineBadge.IsCollapsed = false; + LineBadge.Uncollapse(); }, duration); } @@ -89,8 +90,10 @@ namespace osu.Game.Overlays.Changelog.Header }, LineBadge = new LineBadge(startCollapsed) { + CollapsedSize = 2, + UncollapsedSize = 10, Colour = badgeColour, - RelativeSizeAxes = Axes.X, + Anchor = Anchor.BottomCentre, } }; } @@ -98,14 +101,14 @@ namespace osu.Game.Overlays.Changelog.Header public virtual void Deactivate() { IsActivated = false; - LineBadge.IsCollapsed = true; + LineBadge.Collapse(); Text.Font = "Exo2.0-Regular"; } public virtual void Activate() { IsActivated = true; - LineBadge.IsCollapsed = false; + LineBadge.Uncollapse(); Text.Font = "Exo2.0-Bold"; SampleActivate?.Play(); } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs index 36db135675..2e9152b256 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -33,7 +33,7 @@ namespace osu.Game.Overlays.Changelog.Header public override void Activate() { IsActivated = true; - LineBadge.IsCollapsed = false; + LineBadge.Uncollapse(); Text.Font = "Exo2.0-Bold"; SetTextColour(Color4.White, 100); SampleActivate?.Play(); @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.Changelog.Header public override void Deactivate() { IsActivated = false; - LineBadge.IsCollapsed = true; + LineBadge.Collapse(); Text.Font = "Exo2.0-Regular"; // commented out since it makes bad resize-jumping SetTextColour(badgeColour, 100); OnDeactivation?.Invoke(); @@ -57,14 +57,14 @@ namespace osu.Game.Overlays.Changelog.Header protected override bool OnHover(InputState state) { - LineBadge.ResizeHeightTo(LineBadge.UncollapsedHeight, LineBadge.TransitionDuration, Easing.OutElastic); + LineBadge.Uncollapse(); return base.OnHover(state); } protected override void OnHoverLost(InputState state) { if (!IsActivated) - LineBadge.ResizeHeightTo(1, LineBadge.TransitionDuration, Easing.Out); + LineBadge.Collapse(); base.OnHoverLost(state); } diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 44fdeb80a7..59ce97bcc7 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.States; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; using System; @@ -27,7 +28,7 @@ namespace osu.Game.Overlays.Changelog private bool isActivated; - private readonly Header.LineBadge lineBadge; + private readonly LineBadge lineBadge; private SampleChannel sampleHover; public readonly APIChangelog ChangelogEntry; private readonly FillFlowContainer text; @@ -75,21 +76,23 @@ namespace osu.Game.Overlays.Changelog }, } }, - lineBadge = new Header.LineBadge(false, 2, 4) + lineBadge = new LineBadge(false) { Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, Colour = StreamColour.FromStreamName(ChangelogEntry.UpdateStream.Name), - RelativeSizeAxes = Axes.X, + UncollapsedSize = 4, + CollapsedSize = 2, }, }; } + /// In case we don't want to + /// fire the event. public void Activate(bool withoutFiringUpdates = true) { isActivated = true; this.FadeIn(transition_duration); - lineBadge.IsCollapsed = false; + lineBadge.Uncollapse(); if (!withoutFiringUpdates) Selected?.Invoke(this, EventArgs.Empty); } @@ -101,7 +104,7 @@ namespace osu.Game.Overlays.Changelog if (!IsHovered) { this.FadeTo(0.5f, transition_duration); - lineBadge.IsCollapsed = true; + lineBadge.Collapse(200); } } @@ -116,7 +119,7 @@ namespace osu.Game.Overlays.Changelog sampleHover?.Play(); DisableDim(); this.FadeIn(transition_duration); - lineBadge.IsCollapsed = false; + lineBadge.Uncollapse(); return base.OnHover(state); } @@ -125,7 +128,7 @@ namespace osu.Game.Overlays.Changelog if (!isActivated) { this.FadeTo(0.5f, transition_duration); - lineBadge.IsCollapsed = true; + lineBadge.Collapse(200); } else EnableDim(); From 554c56d51f8dd1eb7786581ce8079e88c2161c07 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Mon, 23 Jul 2018 18:17:50 +0200 Subject: [PATCH 0064/5608] Change order in TextBadgePair.cs --- .../Changelog/Header/TextBadgePair.cs | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index 6ff945469c..ec99604df5 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -25,53 +25,6 @@ namespace osu.Game.Overlays.Changelog.Header private SampleChannel sampleHover; protected SampleChannel SampleActivate; - public void SetTextColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) - { - Text.FadeColour(newColour, duration, easing); - } - - public void SetBadgeColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) - { - LineBadge.FadeColour(newColour, duration, easing); - } - - public void HideText(double duration = 0, Easing easing = Easing.InOutCubic) - { - LineBadge.Collapse(); - Text.MoveToY(20, duration, easing) - .FadeOut(duration, easing); - } - - public void ShowText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) - { - LineBadge.Uncollapse(); - if (!string.IsNullOrEmpty(displayText)) - Text.Text = displayText; - Text.MoveToY(0, duration, easing) - .FadeIn(duration, easing); - } - - /// - /// The duration of popping in and popping out not combined. - /// Full change takes double this time. - public void ChangeText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) - { - LineBadge.Collapse(); - Text.MoveToY(20, duration, easing) - .FadeOut(duration, easing) - .Then() - .MoveToY(0, duration, easing) - .FadeIn(duration, easing); - - // since using .finally/.oncomplete after first fadeout made the badge not hide - // sometimes in visual tests (https://streamable.com/0qssq), I'm using a scheduler here - Scheduler.AddDelayed(() => - { - if (!string.IsNullOrEmpty(displayText)) Text.Text = displayText; - LineBadge.Uncollapse(); - }, duration); - } - public TextBadgePair(ColourInfo badgeColour, string displayText = "Listing", bool startCollapsed = true) { AutoSizeAxes = Axes.X; @@ -98,6 +51,27 @@ namespace osu.Game.Overlays.Changelog.Header }; } + /// + /// The duration of popping in and popping out not combined. + /// Full change takes double this time. + public void ChangeText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) + { + LineBadge.Collapse(); + Text.MoveToY(20, duration, easing) + .FadeOut(duration, easing) + .Then() + .MoveToY(0, duration, easing) + .FadeIn(duration, easing); + + // since using .finally/.oncomplete after first fadeout made the badge not hide + // sometimes in visual tests (https://streamable.com/0qssq), I'm using a scheduler here + Scheduler.AddDelayed(() => + { + if (!string.IsNullOrEmpty(displayText)) Text.Text = displayText; + LineBadge.Uncollapse(); + }, duration); + } + public virtual void Deactivate() { IsActivated = false; @@ -113,6 +87,32 @@ namespace osu.Game.Overlays.Changelog.Header SampleActivate?.Play(); } + public void SetTextColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) + { + Text.FadeColour(newColour, duration, easing); + } + + public void SetBadgeColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) + { + LineBadge.FadeColour(newColour, duration, easing); + } + + public void HideText(double duration = 0, Easing easing = Easing.InOutCubic) + { + LineBadge.Collapse(); + Text.MoveToY(20, duration, easing) + .FadeOut(duration, easing); + } + + public void ShowText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) + { + LineBadge.Uncollapse(); + if (!string.IsNullOrEmpty(displayText)) + Text.Text = displayText; + Text.MoveToY(0, duration, easing) + .FadeIn(duration, easing); + } + protected override bool OnHover(InputState state) { if (!IsActivated) From f685c5ba5852355b3b2419051b3b61dd7ab8c000 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Mon, 23 Jul 2018 18:38:20 +0200 Subject: [PATCH 0065/5608] Fix typos; remove outdated comments; minor order changes --- osu.Game.Tests/Visual/TestCaseLineBadge.cs | 6 +++--- osu.Game/Graphics/UserInterface/LineBadge.cs | 2 +- osu.Game/Graphics/UserInterface/TooltipIconButton.cs | 3 ++- osu.Game/Overlays/Changelog/ChangelogChart.cs | 5 ----- osu.Game/Overlays/Changelog/ChangelogContent.cs | 9 +++++---- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLineBadge.cs b/osu.Game.Tests/Visual/TestCaseLineBadge.cs index 304b0f9518..d80ef0131b 100644 --- a/osu.Game.Tests/Visual/TestCaseLineBadge.cs +++ b/osu.Game.Tests/Visual/TestCaseLineBadge.cs @@ -13,10 +13,10 @@ namespace osu.Game.Tests.Visual { public TestCaseLineBadge() { - Container containerHorizontal; + Container container; LineBadge lineBadge; - Add(containerHorizontal = new Container + Add(container = new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual AddStep(@"", () => { }); AddStep(@"Collapse", () => lineBadge.Collapse()); AddStep(@"Uncollapse", () => lineBadge.Uncollapse()); - AddSliderStep(@"Resize container", 1, 300, 150, value => containerHorizontal.ResizeTo(value)); + AddSliderStep(@"Resize container", 1, 300, 150, value => container.ResizeTo(value)); AddStep(@"Horizontal", () => lineBadge.IsHorizontal = true); AddStep(@"Anchor top", () => lineBadge.Anchor = Anchor.TopCentre); AddStep(@"Vertical", () => lineBadge.IsHorizontal = false); diff --git a/osu.Game/Graphics/UserInterface/LineBadge.cs b/osu.Game/Graphics/UserInterface/LineBadge.cs index 91dd2add1f..0283559aee 100644 --- a/osu.Game/Graphics/UserInterface/LineBadge.cs +++ b/osu.Game/Graphics/UserInterface/LineBadge.cs @@ -45,7 +45,7 @@ namespace osu.Game.Graphics.UserInterface /// takes up the full parent's axis defined by . /// /// Whether to initialize with the - /// or the + /// or the . public LineBadge(bool startCollapsed = true) { IsCollapsed = startCollapsed; diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index 7f6641817a..1dfec5cb80 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -21,6 +21,7 @@ namespace osu.Game.Graphics.UserInterface { private readonly SpriteIcon icon; private SampleChannel sampleHover; + public Action Action; private bool isEnabled; @@ -30,7 +31,7 @@ namespace osu.Game.Graphics.UserInterface set { isEnabled = value; - icon.Alpha = value ? 1 : 0.5f; + icon.FadeTo(value ? 1 : 0.5f, 250); } } diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index 91e2aa5e49..667f206250 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -15,7 +15,6 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Changelog { // maybe look to osu.Game.Screens.Play.SquareGraph for reference later - // placeholder json file: https://api.myjson.com/bins/10ye8a public class ChangelogChart : BufferedContainer { private readonly Box background; @@ -43,10 +42,6 @@ namespace osu.Game.Overlays.Changelog }; } - /// - /// Draw the graph for a specific build - /// - private bool isEmpty(APIChangelogChart changelogChart) { if (changelogChart != null) diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index f6e90b83a3..9d81fcb30f 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -31,7 +31,6 @@ namespace osu.Game.Overlays.Changelog public void ShowListing(APIChangelog[] changelog) { DateTime currentDate = new DateTime(); - Clear(); foreach (APIChangelog build in changelog) @@ -48,10 +47,10 @@ namespace osu.Game.Overlays.Changelog Margin = new MarginPadding { Top = 30, }, }); } - // watch out for this? - Add(changelogContentGroup = new ChangelogContentGroup(build, true)); + changelogContentGroup = new ChangelogContentGroup(build, true); changelogContentGroup.BuildSelected += OnBuildSelected; changelogContentGroup.GenerateText(build.ChangelogEntries); + Add(changelogContentGroup); currentDate = build.CreatedAt.Date; } else @@ -63,9 +62,11 @@ namespace osu.Game.Overlays.Changelog Colour = new Color4(32, 24, 35, 255), Margin = new MarginPadding { Top = 30, }, }); - Add(changelogContentGroup = new ChangelogContentGroup(build, false)); + + changelogContentGroup = new ChangelogContentGroup(build, false); changelogContentGroup.BuildSelected += OnBuildSelected; changelogContentGroup.GenerateText(build.ChangelogEntries); + Add(changelogContentGroup); } } } From f526d6696970fa3fa7c430982ed597d0d8a69bd1 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Mon, 23 Jul 2018 19:40:58 +0200 Subject: [PATCH 0066/5608] Fix showing builds --- osu.Game/Overlays/Changelog/ChangelogContent.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 9d81fcb30f..4f336dc48b 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -74,6 +74,9 @@ namespace osu.Game.Overlays.Changelog public void ShowBuild(APIChangelog changelogBuild) { Child = changelogContentGroup = new ChangelogContentGroup(changelogBuild); + changelogContentGroup.GenerateText(changelogBuild.ChangelogEntries); + changelogContentGroup.UpdateChevronTooltips(changelogBuild.Versions.Previous?.DisplayVersion, + changelogBuild.Versions.Next?.DisplayVersion); } protected virtual void OnBuildSelected(string updateStream, string version, EventArgs args) From 6cd6ca432c0d43cca651ea5ffe26da3a05eb3806 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Mon, 23 Jul 2018 20:36:24 +0200 Subject: [PATCH 0067/5608] Fix links not working due to rewrite regression --- osu.Game/Overlays/Changelog/ChangelogContent.cs | 1 + osu.Game/Overlays/Changelog/ChangelogHeader.cs | 12 ++++++++++-- .../Overlays/Changelog/Header/TextBadgePair.cs | 17 +++++++++++++++-- .../Changelog/Header/TextBadgePairListing.cs | 6 +++--- .../Changelog/Header/TextBadgePairRelease.cs | 2 -- osu.Game/Overlays/ChangelogOverlay.cs | 6 +++++- 6 files changed, 34 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 4f336dc48b..3b64003104 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -77,6 +77,7 @@ namespace osu.Game.Overlays.Changelog changelogContentGroup.GenerateText(changelogBuild.ChangelogEntries); changelogContentGroup.UpdateChevronTooltips(changelogBuild.Versions.Previous?.DisplayVersion, changelogBuild.Versions.Next?.DisplayVersion); + changelogContentGroup.BuildSelected += OnBuildSelected; } protected virtual void OnBuildSelected(string updateStream, string version, EventArgs args) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index a4be3bdf7f..8617aff6a0 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -26,7 +26,9 @@ namespace osu.Game.Overlays.Changelog private readonly SpriteIcon chevron; private readonly TextBadgePairRelease releaseStream; - public Action ListingActivated; + public delegate void ListingSelectedEventHandler(); + + public event ListingSelectedEventHandler ListingSelected; private const float cover_height = 280; private const float title_height = 50; @@ -127,7 +129,7 @@ namespace osu.Game.Overlays.Changelog Margin = new MarginPadding { Top = 10, - Left = 7, + Left = 15, Right = 18, Bottom = 15, }, @@ -157,6 +159,7 @@ namespace osu.Game.Overlays.Changelog Origin = Anchor.CentreLeft, }, }; + listing.Activated += OnListingSelected; } public void ShowBuild(string displayName, string displayVersion) @@ -175,6 +178,11 @@ namespace osu.Game.Overlays.Changelog chevron.MoveToX(-20, 100).FadeOut(100); } + protected virtual void OnListingSelected(object source, EventArgs e) + { + ListingSelected?.Invoke(); + } + [BackgroundDependencyLoader] private void load(TextureStore textures) { diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index ec99604df5..732edc2a58 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -20,8 +20,10 @@ namespace osu.Game.Overlays.Changelog.Header protected LineBadge LineBadge; public bool IsActivated { get; protected set; } - public Action OnActivation; - public Action OnDeactivation; + public delegate void ActivatedEventHandler(object source, EventArgs args); + + public event ActivatedEventHandler Activated; + private SampleChannel sampleHover; protected SampleChannel SampleActivate; @@ -120,6 +122,17 @@ namespace osu.Game.Overlays.Changelog.Header return base.OnHover(state); } + protected override bool OnClick(InputState state) + { + OnActivated(); + return base.OnClick(state); + } + + protected virtual void OnActivated() + { + Activated?.Invoke(this, EventArgs.Empty); + } + [BackgroundDependencyLoader] private void load(AudioManager audio) { diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs index 2e9152b256..3876e8a226 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -32,21 +32,21 @@ namespace osu.Game.Overlays.Changelog.Header public override void Activate() { + if (IsActivated) + return; IsActivated = true; LineBadge.Uncollapse(); Text.Font = "Exo2.0-Bold"; SetTextColour(Color4.White, 100); SampleActivate?.Play(); - OnActivation?.Invoke(); } public override void Deactivate() { IsActivated = false; LineBadge.Collapse(); - Text.Font = "Exo2.0-Regular"; // commented out since it makes bad resize-jumping + Text.Font = "Exo2.0-Regular"; SetTextColour(badgeColour, 100); - OnDeactivation?.Invoke(); } protected override bool OnClick(InputState state) diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs index 32a76670f0..7f60dbabbd 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs @@ -30,14 +30,12 @@ namespace osu.Game.Overlays.Changelog.Header ShowText(transition_duration, displayText); IsActivated = true; SampleActivate?.Play(); - OnActivation?.Invoke(); } public override void Deactivate() { IsActivated = false; HideText(transition_duration); - OnDeactivation?.Invoke(); } } } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index d9a139c6ee..a4e3e8a91c 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -79,8 +79,9 @@ namespace osu.Game.Overlays }, }, }; + header.ListingSelected += FetchAndShowListing; badges.Selected += onBuildSelected; - header.ListingActivated += FetchAndShowListing; + content.BuildSelected += onBuildSelected; } // receive input outside our bounds so we can trigger a close event on ourselves. @@ -152,6 +153,9 @@ namespace osu.Game.Overlays /// public void FetchAndShowBuild(string updateStream, string version, bool sentByBadges = false) { + //// I should probably change this to take APIChangelog as an argument, + //// instantly update the header and badge, and if it doesn't contain the + //// needed info, just subscribe to when the info will be available isAtListing = false; var req = new GetChangelogBuildRequest(updateStream, version); if (!sentByBadges) From 7c6be4a07538077759630b6e2e2069f400423ebf Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Mon, 23 Jul 2018 21:38:14 +0200 Subject: [PATCH 0068/5608] Handle around an APIChangelog instead of just Name and Version: Makes showing up the header immediately possible --- .../Overlays/Changelog/ChangelogBadges.cs | 15 ++---------- .../Overlays/Changelog/ChangelogContent.cs | 6 ++--- .../Changelog/ChangelogContentGroup.cs | 14 +++++------ osu.Game/Overlays/ChangelogOverlay.cs | 24 +++++++++++-------- 4 files changed, 25 insertions(+), 34 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index 0cfd220601..6f088677d9 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Changelog private const float padding_y = 20; private const float padding_x = 85; - public delegate void SelectionHandler(string updateStream, string version, EventArgs args); + public delegate void SelectionHandler(APIChangelog releaseStream, EventArgs args); public event SelectionHandler Selected; @@ -49,17 +49,6 @@ namespace osu.Game.Overlays.Changelog }, }, }; - //foreach (StreamBadge streamBadge in BadgesContainer.Children) - //{ - // streamBadge.OnActivation = () => - // { - // SelectedRelease = streamBadge.ChangelogEntry; - // foreach (StreamBadge item in BadgesContainer.Children) - // if (item.ChangelogEntry.Id != streamBadge.ChangelogEntry.Id) - // item.Deactivate(); - // OnSelection?.Invoke(); - // }; - //} } public void Populate(List latestBuilds) @@ -109,7 +98,7 @@ namespace osu.Game.Overlays.Changelog protected virtual void OnSelected(StreamBadge source) { - Selected?.Invoke(source.ChangelogEntry.UpdateStream.Name, source.ChangelogEntry.Version, EventArgs.Empty); + Selected?.Invoke(source.ChangelogEntry, EventArgs.Empty); } protected override bool OnHover(InputState state) diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 3b64003104..7e92ab4c26 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Changelog private APIAccess api; private ChangelogContentGroup changelogContentGroup; - public delegate void BuildSelectedEventHandler(string updateStream, string version, EventArgs args); + public delegate void BuildSelectedEventHandler(APIChangelog build, EventArgs args); public event BuildSelectedEventHandler BuildSelected; @@ -80,9 +80,9 @@ namespace osu.Game.Overlays.Changelog changelogContentGroup.BuildSelected += OnBuildSelected; } - protected virtual void OnBuildSelected(string updateStream, string version, EventArgs args) + protected virtual void OnBuildSelected(APIChangelog build, EventArgs args) { - BuildSelected?.Invoke(updateStream, version, EventArgs.Empty); + BuildSelected?.Invoke(build, EventArgs.Empty); } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index aabc390d49..444e81a75d 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Changelog private readonly SortedDictionary> categories = new SortedDictionary>(); - public delegate void BuildSelectedEventHandler(string updateStream, string version, EventArgs args); + public delegate void BuildSelectedEventHandler(APIChangelog build, EventArgs args); public event BuildSelectedEventHandler BuildSelected; @@ -53,8 +53,7 @@ namespace osu.Game.Overlays.Changelog IsEnabled = false, Icon = FontAwesome.fa_chevron_left, Size = new Vector2(24), - Action = () => OnBuildSelected(build.Versions.Previous.UpdateStream.Name, - build.Versions.Previous.Version), + Action = () => OnBuildSelected(build.Versions.Previous), }, new FillFlowContainer { @@ -91,8 +90,7 @@ namespace osu.Game.Overlays.Changelog IsEnabled = false, Icon = FontAwesome.fa_chevron_right, Size = new Vector2(24), - Action = () => OnBuildSelected(build.Versions.Next.UpdateStream.Name, - build.Versions.Next.Version), + Action = () => OnBuildSelected(build.Versions.Next), }, } }, @@ -160,7 +158,7 @@ namespace osu.Game.Overlays.Changelog TextSize = 20, // web: 18, Font = @"Exo2.0-Light", Colour = StreamColour.FromStreamName(build.UpdateStream.Name), - Action = () => OnBuildSelected(build.UpdateStream.Name, build.Version), + Action = () => OnBuildSelected(build), IsClickMuted = true, }, } @@ -188,9 +186,9 @@ namespace osu.Game.Overlays.Changelog } } - protected virtual void OnBuildSelected(string updateStream, string version) + protected virtual void OnBuildSelected(APIChangelog build) { - BuildSelected?.Invoke(updateStream, version, EventArgs.Empty); + BuildSelected?.Invoke(build, EventArgs.Empty); } public void GenerateText(List changelogEntries) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index a4e3e8a91c..fd0515a0b3 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -13,6 +13,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Input.Bindings; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Changelog; using System; @@ -114,9 +115,9 @@ namespace osu.Game.Overlays FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); } - private void onBuildSelected(string updateStream, string version, EventArgs e) + private void onBuildSelected(APIChangelog build, EventArgs e) { - FetchAndShowBuild(updateStream, version); + FetchAndShowBuild(build); } [BackgroundDependencyLoader] @@ -151,18 +152,21 @@ namespace osu.Game.Overlays /// /// Fetches and shows a specific build from a specific update stream. /// - public void FetchAndShowBuild(string updateStream, string version, bool sentByBadges = false) + public void FetchAndShowBuild(APIChangelog build, bool sentByBadges = false) { - //// I should probably change this to take APIChangelog as an argument, - //// instantly update the header and badge, and if it doesn't contain the - //// needed info, just subscribe to when the info will be available isAtListing = false; - var req = new GetChangelogBuildRequest(updateStream, version); + var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); + + if (build.UpdateStream.DisplayName != null && build.DisplayVersion != null) + header.ShowBuild(build.UpdateStream.DisplayName, build.DisplayVersion); + else + req.Success += res => header.ShowBuild(res.UpdateStream.DisplayName, res.DisplayVersion); + if (!sentByBadges) - badges.SelectUpdateStream(updateStream); - chart.ShowUpdateStream(updateStream); + badges.SelectUpdateStream(build.UpdateStream.Name); + + chart.ShowUpdateStream(build.UpdateStream.Name); req.Success += content.ShowBuild; - req.Success += res => header.ShowBuild(res.UpdateStream.DisplayName, res.DisplayVersion); api.Queue(req); } } From 054f578bc8c3cf76055fca4d9e1a976609e677c6 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Mon, 23 Jul 2018 23:15:14 +0200 Subject: [PATCH 0069/5608] Update few links not working; Reasses sample playing; Slight renames --- .../UserInterface/TooltipIconButton.cs | 5 +++++ .../Overlays/Changelog/ChangelogBadges.cs | 12 +++++----- .../Changelog/ChangelogContentGroup.cs | 1 - .../Overlays/Changelog/ChangelogHeader.cs | 8 +++++++ .../Changelog/Header/TextBadgePair.cs | 6 ++--- .../Changelog/Header/TextBadgePairListing.cs | 1 - .../Changelog/Header/TextBadgePairRelease.cs | 1 - osu.Game/Overlays/Changelog/StreamBadge.cs | 22 +++++++++++-------- osu.Game/Overlays/ChangelogOverlay.cs | 10 ++++++++- 9 files changed, 44 insertions(+), 22 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index 1dfec5cb80..ecae010889 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -21,6 +21,7 @@ namespace osu.Game.Graphics.UserInterface { private readonly SpriteIcon icon; private SampleChannel sampleHover; + private SampleChannel sampleClick; public Action Action; @@ -64,7 +65,10 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnClick(InputState state) { if (isEnabled) + { + sampleClick?.Play(); Action?.Invoke(); + } return base.OnClick(state); } @@ -79,6 +83,7 @@ namespace osu.Game.Graphics.UserInterface private void load(AudioManager audio) { sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); + sampleClick = audio.Sample.Get(@"UI/generic-select-soft"); } public string TooltipText { get; set; } diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index 6f088677d9..3d1762e9f6 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -80,9 +80,9 @@ namespace osu.Game.Overlays.Changelog { foreach (StreamBadge streamBadge in badgesContainer) { - if (streamBadge.ChangelogEntry.UpdateStream.Name == updateStream) + if (streamBadge.LatestBuild.UpdateStream.Name == updateStream) { - selectedStreamId = streamBadge.ChangelogEntry.UpdateStream.Id; + selectedStreamId = streamBadge.LatestBuild.UpdateStream.Id; streamBadge.Activate(); } else @@ -92,13 +92,13 @@ namespace osu.Game.Overlays.Changelog private void onBadgeSelected(StreamBadge source, EventArgs args) { - selectedStreamId = source.ChangelogEntry.UpdateStream.Id; + selectedStreamId = source.LatestBuild.UpdateStream.Id; OnSelected(source); } protected virtual void OnSelected(StreamBadge source) { - Selected?.Invoke(source.ChangelogEntry, EventArgs.Empty); + Selected?.Invoke(source.LatestBuild, EventArgs.Empty); } protected override bool OnHover(InputState state) @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.Changelog { if (selectedStreamId < 0) { - if (selectedStreamId != streamBadge.ChangelogEntry.UpdateStream.Id) + if (selectedStreamId != streamBadge.LatestBuild.UpdateStream.Id) streamBadge.Deactivate(); else streamBadge.EnableDim(); @@ -124,7 +124,7 @@ namespace osu.Game.Overlays.Changelog { if (selectedStreamId < 0) streamBadge.Activate(); - else if (streamBadge.ChangelogEntry.UpdateStream.Id == selectedStreamId) + else if (streamBadge.LatestBuild.UpdateStream.Id == selectedStreamId) streamBadge.DisableDim(); } base.OnHoverLost(state); diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 444e81a75d..763be79a43 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -159,7 +159,6 @@ namespace osu.Game.Overlays.Changelog Font = @"Exo2.0-Light", Colour = StreamColour.FromStreamName(build.UpdateStream.Name), Action = () => OnBuildSelected(build), - IsClickMuted = true, }, } }, diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 8617aff6a0..37b9c0a047 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -160,6 +160,7 @@ namespace osu.Game.Overlays.Changelog }, }; listing.Activated += OnListingSelected; + releaseStream.Activated += OnReleaseSelected; } public void ShowBuild(string displayName, string displayVersion) @@ -175,6 +176,8 @@ namespace osu.Game.Overlays.Changelog { releaseStream.Deactivate(); listing.Activate(); + titleStream.Text = "Listing"; + titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); chevron.MoveToX(-20, 100).FadeOut(100); } @@ -183,6 +186,11 @@ namespace osu.Game.Overlays.Changelog ListingSelected?.Invoke(); } + protected virtual void OnReleaseSelected(object source, EventArgs e) + { + titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); + } + [BackgroundDependencyLoader] private void load(TextureStore textures) { diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index 732edc2a58..c8801771d3 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Changelog.Header public event ActivatedEventHandler Activated; private SampleChannel sampleHover; - protected SampleChannel SampleActivate; + private SampleChannel sampleActivate; public TextBadgePair(ColourInfo badgeColour, string displayText = "Listing", bool startCollapsed = true) { @@ -86,7 +86,6 @@ namespace osu.Game.Overlays.Changelog.Header IsActivated = true; LineBadge.Uncollapse(); Text.Font = "Exo2.0-Bold"; - SampleActivate?.Play(); } public void SetTextColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) @@ -125,6 +124,7 @@ namespace osu.Game.Overlays.Changelog.Header protected override bool OnClick(InputState state) { OnActivated(); + sampleActivate?.Play(); return base.OnClick(state); } @@ -137,7 +137,7 @@ namespace osu.Game.Overlays.Changelog.Header private void load(AudioManager audio) { sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); - SampleActivate = audio.Sample.Get(@"UI/generic-select-soft"); + sampleActivate = audio.Sample.Get(@"UI/generic-select-soft"); } } } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs index 3876e8a226..31a06ce67d 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -38,7 +38,6 @@ namespace osu.Game.Overlays.Changelog.Header LineBadge.Uncollapse(); Text.Font = "Exo2.0-Bold"; SetTextColour(Color4.White, 100); - SampleActivate?.Play(); } public override void Deactivate() diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs index 7f60dbabbd..97ce799509 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs @@ -29,7 +29,6 @@ namespace osu.Game.Overlays.Changelog.Header else ShowText(transition_duration, displayText); IsActivated = true; - SampleActivate?.Play(); } public override void Deactivate() diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 59ce97bcc7..2a82620995 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -29,15 +29,17 @@ namespace osu.Game.Overlays.Changelog private bool isActivated; private readonly LineBadge lineBadge; + private SampleChannel sampleClick; private SampleChannel sampleHover; - public readonly APIChangelog ChangelogEntry; + + public readonly APIChangelog LatestBuild; private readonly FillFlowContainer text; - public StreamBadge(APIChangelog changelogEntry) + public StreamBadge(APIChangelog latestBuild) { - ChangelogEntry = changelogEntry; + this.LatestBuild = latestBuild; Height = badge_height; - Width = ChangelogEntry.IsFeatured ? badge_width * 2 : badge_width; + base.Width = this.LatestBuild.IsFeatured ? badge_width * 2 : badge_width; Margin = new MarginPadding(5); isActivated = true; Children = new Drawable[] @@ -51,7 +53,7 @@ namespace osu.Game.Overlays.Changelog { new SpriteText { - Text = ChangelogEntry.UpdateStream.DisplayName, + Text = this.LatestBuild.UpdateStream.DisplayName, Font = @"Exo2.0-Bold", TextSize = 16, Margin = new MarginPadding @@ -61,14 +63,14 @@ namespace osu.Game.Overlays.Changelog }, new SpriteText { - Text = ChangelogEntry.DisplayVersion, + Text = this.LatestBuild.DisplayVersion, Font = @"Exo2.0-Light", TextSize = 21, }, new SpriteText { - Text = ChangelogEntry.Users > 0 ? - $"{ChangelogEntry.Users:N0} users online" : + Text = this.LatestBuild.Users > 0 ? + $"{this.LatestBuild.Users:N0} users online" : null, TextSize = 12, Font = @"Exo2.0-Regular", @@ -79,7 +81,7 @@ namespace osu.Game.Overlays.Changelog lineBadge = new LineBadge(false) { Anchor = Anchor.TopCentre, - Colour = StreamColour.FromStreamName(ChangelogEntry.UpdateStream.Name), + Colour = StreamColour.FromStreamName(this.LatestBuild.UpdateStream.Name), UncollapsedSize = 4, CollapsedSize = 2, }, @@ -111,6 +113,7 @@ namespace osu.Game.Overlays.Changelog protected override bool OnClick(InputState state) { Activate(false); + sampleClick?.Play(); return base.OnClick(state); } @@ -142,6 +145,7 @@ namespace osu.Game.Overlays.Changelog [BackgroundDependencyLoader] private void load(AudioManager audio) { + sampleClick = audio.Sample.Get(@"UI/generic-select-soft"); sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); } } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index fd0515a0b3..4a133870f7 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -4,6 +4,8 @@ using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -26,6 +28,8 @@ namespace osu.Game.Overlays private readonly ChangelogChart chart; private readonly ChangelogContent content; + private SampleChannel sampleBack; + private readonly Color4 purple = new Color4(191, 4, 255, 255); private APIAccess api; @@ -96,7 +100,10 @@ namespace osu.Game.Overlays if (isAtListing) State = Visibility.Hidden; else + { FetchAndShowListing(); + sampleBack?.Play(); + } return true; } @@ -121,9 +128,10 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(APIAccess api) + private void load(APIAccess api, AudioManager audio) { this.api = api; + sampleBack = audio.Sample.Get(@"UI/generic-select-soft"); // @"UI/screen-back" feels non-fitting here } protected override void LoadComplete() From 9a84747fe678cfe9dff3f1751992458acfa42391 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Mon, 23 Jul 2018 23:24:34 +0200 Subject: [PATCH 0070/5608] Fix reversed if/else statement causing inproper behavior for badges --- osu.Game/Overlays/Changelog/ChangelogBadges.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index 3d1762e9f6..1a5e4f7d18 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -105,7 +105,7 @@ namespace osu.Game.Overlays.Changelog { foreach (StreamBadge streamBadge in badgesContainer.Children) { - if (selectedStreamId < 0) + if (selectedStreamId >= 0) { if (selectedStreamId != streamBadge.LatestBuild.UpdateStream.Id) streamBadge.Deactivate(); From 9e9d7a855d5c9b266f294635f5ce5d317d96a046 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 04:03:56 +0200 Subject: [PATCH 0071/5608] Remove reduntant .base and .this --- osu.Game/Overlays/Changelog/StreamBadge.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 2a82620995..8c881348c7 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -37,9 +37,9 @@ namespace osu.Game.Overlays.Changelog public StreamBadge(APIChangelog latestBuild) { - this.LatestBuild = latestBuild; + LatestBuild = latestBuild; Height = badge_height; - base.Width = this.LatestBuild.IsFeatured ? badge_width * 2 : badge_width; + Width = LatestBuild.IsFeatured ? badge_width * 2 : badge_width; Margin = new MarginPadding(5); isActivated = true; Children = new Drawable[] @@ -53,7 +53,7 @@ namespace osu.Game.Overlays.Changelog { new SpriteText { - Text = this.LatestBuild.UpdateStream.DisplayName, + Text = LatestBuild.UpdateStream.DisplayName, Font = @"Exo2.0-Bold", TextSize = 16, Margin = new MarginPadding @@ -63,14 +63,14 @@ namespace osu.Game.Overlays.Changelog }, new SpriteText { - Text = this.LatestBuild.DisplayVersion, + Text = LatestBuild.DisplayVersion, Font = @"Exo2.0-Light", TextSize = 21, }, new SpriteText { - Text = this.LatestBuild.Users > 0 ? - $"{this.LatestBuild.Users:N0} users online" : + Text = LatestBuild.Users > 0 ? + $"{LatestBuild.Users:N0} users online" : null, TextSize = 12, Font = @"Exo2.0-Regular", @@ -81,7 +81,7 @@ namespace osu.Game.Overlays.Changelog lineBadge = new LineBadge(false) { Anchor = Anchor.TopCentre, - Colour = StreamColour.FromStreamName(this.LatestBuild.UpdateStream.Name), + Colour = StreamColour.FromStreamName(LatestBuild.UpdateStream.Name), UncollapsedSize = 4, CollapsedSize = 2, }, From 24bb44a152d42fb67eb6acf03d86dfcb011a597a Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 04:04:18 +0200 Subject: [PATCH 0072/5608] Add TextBadgePair test case --- .../Visual/TestCaseTextBadgePair.cs | 50 +++++++++++++++++++ .../Changelog/Header/TextBadgePair.cs | 6 ++- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Visual/TestCaseTextBadgePair.cs diff --git a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs new file mode 100644 index 0000000000..c61213ce3c --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs @@ -0,0 +1,50 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Overlays.Changelog.Header; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseTextBadgePair : OsuTestCase + { + public TestCaseTextBadgePair() + { + Container container; + TextBadgePair textBadgePair; + + Add(container = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 250, + Height = 50, + Children = new Drawable[] + { + new Box + { + Colour = Color4.Gray, + Alpha = 0.5f, + RelativeSizeAxes = Axes.Both, + }, + textBadgePair = new TextBadgePair(Color4.DeepSkyBlue, "Test") + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + } + }); + + AddStep(@"Deactivate", textBadgePair.Deactivate); + AddStep(@"Activate", textBadgePair.Activate); + AddStep(@"Hide text", () => textBadgePair.HideText(200)); + AddStep(@"Show text", () => textBadgePair.ShowText(200)); + AddStep(@"Different text", () => textBadgePair.ChangeText(200, "This one's a little bit wider")); + AddWaitStep(1); + AddStep(@"Different text", () => textBadgePair.ChangeText(200, "Ok?..")); + } + } +} diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index c8801771d3..201524cc2f 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -37,6 +37,8 @@ namespace osu.Game.Overlays.Changelog.Header { TextSize = 21, // web: 16, Text = displayText, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Margin = new MarginPadding { Top = 5, @@ -49,6 +51,7 @@ namespace osu.Game.Overlays.Changelog.Header UncollapsedSize = 10, Colour = badgeColour, Anchor = Anchor.BottomCentre, + Origin = Anchor.Centre, } }; } @@ -69,7 +72,8 @@ namespace osu.Game.Overlays.Changelog.Header // sometimes in visual tests (https://streamable.com/0qssq), I'm using a scheduler here Scheduler.AddDelayed(() => { - if (!string.IsNullOrEmpty(displayText)) Text.Text = displayText; + if (!string.IsNullOrEmpty(displayText)) + Text.Text = displayText; LineBadge.Uncollapse(); }, duration); } From fa6074925e8bf58d010b9d3a5459277643560dc1 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 17:02:24 +0200 Subject: [PATCH 0073/5608] Remove unused variable --- osu.Game.Tests/Visual/TestCaseTextBadgePair.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs index c61213ce3c..6d2fe20f2b 100644 --- a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs +++ b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs @@ -13,10 +13,9 @@ namespace osu.Game.Tests.Visual { public TestCaseTextBadgePair() { - Container container; TextBadgePair textBadgePair; - Add(container = new Container + Add(new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 175c20a1043b101cb69667c66d050bcc3fbb2f21 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 18:41:47 +0200 Subject: [PATCH 0074/5608] Slight reorder --- osu.Game/Overlays/ChangelogOverlay.cs | 69 +++++++++++++-------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 4a133870f7..08bcaff58b 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -28,14 +28,17 @@ namespace osu.Game.Overlays private readonly ChangelogChart chart; private readonly ChangelogContent content; - private SampleChannel sampleBack; - private readonly Color4 purple = new Color4(191, 4, 255, 255); + private SampleChannel sampleBack; + private APIAccess api; private bool isAtListing; + // receive input outside our bounds so we can trigger a close event on ourselves. + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; + public ChangelogOverlay() { // these possibly need adjusting? @@ -89,8 +92,33 @@ namespace osu.Game.Overlays content.BuildSelected += onBuildSelected; } - // receive input outside our bounds so we can trigger a close event on ourselves. - public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; + [BackgroundDependencyLoader] + private void load(APIAccess api, AudioManager audio) + { + this.api = api; + sampleBack = audio.Sample.Get(@"UI/generic-select-soft"); // @"UI/screen-back" feels non-fitting here + } + + protected override void LoadComplete() + { + var req = new GetChangelogLatestBuildsRequest(); + req.Success += badges.Populate; + api.Queue(req); + FetchAndShowListing(); + base.LoadComplete(); + } + + protected override void PopIn() + { + base.PopIn(); + FadeEdgeEffectTo(0.25f, WaveContainer.APPEAR_DURATION, Easing.In); + } + + protected override void PopOut() + { + base.PopOut(); + FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); + } public override bool OnPressed(GlobalAction action) { @@ -110,38 +138,7 @@ namespace osu.Game.Overlays return false; } - protected override void PopIn() - { - base.PopIn(); - FadeEdgeEffectTo(0.25f, WaveContainer.APPEAR_DURATION, Easing.In); - } - - protected override void PopOut() - { - base.PopOut(); - FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); - } - - private void onBuildSelected(APIChangelog build, EventArgs e) - { - FetchAndShowBuild(build); - } - - [BackgroundDependencyLoader] - private void load(APIAccess api, AudioManager audio) - { - this.api = api; - sampleBack = audio.Sample.Get(@"UI/generic-select-soft"); // @"UI/screen-back" feels non-fitting here - } - - protected override void LoadComplete() - { - var req = new GetChangelogLatestBuildsRequest(); - req.Success += badges.Populate; - api.Queue(req); - FetchAndShowListing(); - base.LoadComplete(); - } + private void onBuildSelected(APIChangelog build, EventArgs e) => FetchAndShowBuild(build); /// /// Fetches and shows changelog listing. From 255c252f6aa3be47b6fdd8331e930fe5f46d65cb Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 18:47:05 +0200 Subject: [PATCH 0075/5608] Shorten MarginPaddings in ChangelogContentGroup --- .../Changelog/ChangelogContentGroup.cs | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 763be79a43..f768b06da7 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -42,10 +42,7 @@ namespace osu.Game.Overlays.Changelog Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - Margin = new MarginPadding - { - Top = 20, - }, + Margin = new MarginPadding { Top = 20 }, Children = new Drawable[] { chevronPrevious = new TooltipIconButton @@ -58,11 +55,7 @@ namespace osu.Game.Overlays.Changelog new FillFlowContainer { AutoSizeAxes = Axes.Both, - Margin = new MarginPadding - { - Left = 40, - Right = 40, - }, + Margin = new MarginPadding { Horizontal = 40 }, Children = new[] { new SpriteText @@ -104,7 +97,7 @@ namespace osu.Game.Overlays.Changelog Font = @"Exo2.0-Medium", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Margin = new MarginPadding{ Top = 5, } + Margin = new MarginPadding { Top = 5 } }, ChangelogEntries = new FillFlowContainer { @@ -133,7 +126,7 @@ namespace osu.Game.Overlays.Changelog Font = @"Exo2.0-Light", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Margin = new MarginPadding{ Top = 20, }, + Margin = new MarginPadding { Top = 20 }, Alpha = newDate ? 1 : 0, }, new FillFlowContainer @@ -142,7 +135,7 @@ namespace osu.Game.Overlays.Changelog Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - Margin = new MarginPadding{ Top = 20, }, + Margin = new MarginPadding { Top = 20 }, Spacing = new Vector2(5), Children = new Drawable[] { @@ -208,7 +201,7 @@ namespace osu.Game.Overlays.Changelog Text = category.Key, TextSize = 24, // web: 18, Font = @"Exo2.0-Bold", - Margin = new MarginPadding { Top = 35, Bottom = 15, }, + Margin = new MarginPadding { Top = 35, Bottom = 15 }, }); foreach (ChangelogEntry entry in category.Value) { @@ -219,10 +212,14 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Full, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Margin = new MarginPadding{ Vertical = 5, }, + Margin = new MarginPadding { Vertical = 5 }, }); - title.AddIcon(FontAwesome.fa_check, t => { t.TextSize = 12; t.Padding = new MarginPadding { Left = -17, Right = 5 }; }); - title.AddText(entry.Title, t => { t.TextSize = 18; }); //t.Padding = new MarginPadding(10); }); + title.AddIcon(FontAwesome.fa_check, t => + { + t.TextSize = 12; + t.Padding = new MarginPadding { Left = -17, Right = 5 }; + }); + title.AddText(entry.Title, t => { t.TextSize = 18; }); if (!string.IsNullOrEmpty(entry.Repository)) { title.AddText($" ({entry.Repository.Substring(4)}#{entry.GithubPullRequestId})", t => From 225ff35907432cd9787c77cc8ff5ee9b69c7fe71 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 18:55:50 +0200 Subject: [PATCH 0076/5608] XML for TooltipIconButton.cs --- osu.Game/Graphics/UserInterface/TooltipIconButton.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index ecae010889..65ab5de036 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -23,9 +23,16 @@ namespace osu.Game.Graphics.UserInterface private SampleChannel sampleHover; private SampleChannel sampleClick; + /// + /// The action to fire upon click, if is set to true. + /// public Action Action; private bool isEnabled; + + /// + /// If set to true, upon click the will execute. It wont otherwise. + /// public bool IsEnabled { get { return isEnabled; } @@ -42,6 +49,9 @@ namespace osu.Game.Graphics.UserInterface set { icon.Icon = value; } } + /// + /// A simple icon that has an action upon click and can be disabled. + /// public TooltipIconButton() { isEnabled = true; From 16d3ca20731ea986382f4583c454b0f3cf2674b4 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 19:01:24 +0200 Subject: [PATCH 0077/5608] Move breadcrumb to the right position --- osu.Game/Overlays/Changelog/ChangelogHeader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 37b9c0a047..035574bd1c 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -114,7 +114,7 @@ namespace osu.Game.Overlays.Changelog }, new FillFlowContainer // Listing > Lazer 2018.713.1 { - X = 2 * icon_margin + icon_size - 8, + X = 2 * icon_margin + icon_size, Height = version_height, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, From dfe4153c95b0cbfc56603741bb231b569d776a54 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 19:34:40 +0200 Subject: [PATCH 0078/5608] Prevent duplicated fetching for listing and builds: - listing when already at it; - builds by immediately disabling links to them (chevrons and links in listing) --- .../Overlays/Changelog/ChangelogContentGroup.cs | 16 +++++++++++++--- osu.Game/Overlays/ChangelogOverlay.cs | 6 ++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index f768b06da7..44d5e33c56 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -50,7 +50,11 @@ namespace osu.Game.Overlays.Changelog IsEnabled = false, Icon = FontAwesome.fa_chevron_left, Size = new Vector2(24), - Action = () => OnBuildSelected(build.Versions.Previous), + Action = () => + { + OnBuildSelected(build.Versions.Previous); + chevronPrevious.IsEnabled = false; + }, }, new FillFlowContainer { @@ -83,7 +87,11 @@ namespace osu.Game.Overlays.Changelog IsEnabled = false, Icon = FontAwesome.fa_chevron_right, Size = new Vector2(24), - Action = () => OnBuildSelected(build.Versions.Next), + Action = () => + { + OnBuildSelected(build.Versions.Next); + chevronNext.IsEnabled = false; + }, }, } }, @@ -110,6 +118,7 @@ namespace osu.Game.Overlays.Changelog public ChangelogContentGroup(APIChangelog build, bool newDate = false) { + ClickableText clickableText; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; @@ -145,7 +154,7 @@ namespace osu.Game.Overlays.Changelog TextSize = 20, // web: 18, Font = @"Exo2.0-Medium", }, - new ClickableText + clickableText = new ClickableText { Text = build.DisplayVersion, TextSize = 20, // web: 18, @@ -162,6 +171,7 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Vertical, }, }; + clickableText.Action += () => clickableText.IsEnabled = false; } public void UpdateChevronTooltips(string previousVersion, string nextVersion) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 08bcaff58b..ad8d60d6ca 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -141,13 +141,15 @@ namespace osu.Game.Overlays private void onBuildSelected(APIChangelog build, EventArgs e) => FetchAndShowBuild(build); /// - /// Fetches and shows changelog listing. + /// If we're not already at it, fetches and shows changelog listing. /// public void FetchAndShowListing() { + header.ShowListing(); + if (isAtListing) + return; isAtListing = true; var req = new GetChangelogRequest(); - header.ShowListing(); badges.SelectNone(); chart.ShowAllUpdateStreams(); req.Success += content.ShowListing; From 3b362881853195936282bc8ade46b5b9fd94ae0c Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 20:13:53 +0200 Subject: [PATCH 0079/5608] Rename TestCaseChangelog to TestCaseChangelogOverlay --- .../{TestCaseChangelog.cs => TestCaseChangelogOverlay.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Tests/Visual/{TestCaseChangelog.cs => TestCaseChangelogOverlay.cs} (90%) diff --git a/osu.Game.Tests/Visual/TestCaseChangelog.cs b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs similarity index 90% rename from osu.Game.Tests/Visual/TestCaseChangelog.cs rename to osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs index da260c239b..53143bd924 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelog.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs @@ -7,7 +7,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual { [TestFixture] - public class TestCaseChangelog : OsuTestCase + public class TestCaseChangelogOverlay : OsuTestCase { private ChangelogOverlay changelog; From 8e412fe4037f78d5db5f4bea73a233a1646bb80f Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 20:57:09 +0200 Subject: [PATCH 0080/5608] Add scrolling to the previous position when on "Back" --- osu.Game/Overlays/ChangelogOverlay.cs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index ad8d60d6ca..965d6fcf49 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -28,6 +28,8 @@ namespace osu.Game.Overlays private readonly ChangelogChart chart; private readonly ChangelogContent content; + private readonly ScrollContainer scroll; + private readonly Color4 purple = new Color4(191, 4, 255, 255); private SampleChannel sampleBack; @@ -35,6 +37,7 @@ namespace osu.Game.Overlays private APIAccess api; private bool isAtListing; + private float savedScrollPosition; // receive input outside our bounds so we can trigger a close event on ourselves. public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; @@ -68,7 +71,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Colour = new Color4(49, 36, 54, 255), }, - new ScrollContainer + scroll = new ScrollContainer { RelativeSizeAxes = Axes.Both, ScrollbarVisible = false, @@ -152,7 +155,11 @@ namespace osu.Game.Overlays var req = new GetChangelogRequest(); badges.SelectNone(); chart.ShowAllUpdateStreams(); - req.Success += content.ShowListing; + req.Success += listing => + { + content.ShowListing(listing); + scroll.ScrollTo(savedScrollPosition); + }; api.Queue(req); } @@ -173,7 +180,13 @@ namespace osu.Game.Overlays badges.SelectUpdateStream(build.UpdateStream.Name); chart.ShowUpdateStream(build.UpdateStream.Name); - req.Success += content.ShowBuild; + req.Success += APIChangelog => + { + savedScrollPosition = scroll.Current; + content.ShowBuild(APIChangelog); + if (scroll.Current > scroll.GetChildPosInContent(content)) + scroll.ScrollTo(content); + }; api.Queue(req); } } From 08a291f0d45e6dd507986dc2f97e0e4deec685c4 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 21:19:29 +0200 Subject: [PATCH 0081/5608] Improve scroll handling --- osu.Game/Overlays/ChangelogOverlay.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 965d6fcf49..3e52e66e35 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -168,7 +168,6 @@ namespace osu.Game.Overlays /// public void FetchAndShowBuild(APIChangelog build, bool sentByBadges = false) { - isAtListing = false; var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); if (build.UpdateStream.DisplayName != null && build.DisplayVersion != null) @@ -182,10 +181,12 @@ namespace osu.Game.Overlays chart.ShowUpdateStream(build.UpdateStream.Name); req.Success += APIChangelog => { - savedScrollPosition = scroll.Current; content.ShowBuild(APIChangelog); if (scroll.Current > scroll.GetChildPosInContent(content)) scroll.ScrollTo(content); + if (isAtListing) + savedScrollPosition = scroll.Current; + isAtListing = false; }; api.Queue(req); } From 43a7b3a82510a073fe4aab2da4cce8b5fd001dfa Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 21:42:25 +0200 Subject: [PATCH 0082/5608] Fetch listing only once; Reenable disabled links as they wont be regenerated --- .../Changelog/ChangelogContentGroup.cs | 8 ++++- osu.Game/Overlays/ChangelogOverlay.cs | 36 ++++++++++++------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 44d5e33c56..88be51bb47 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -171,7 +171,13 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Vertical, }, }; - clickableText.Action += () => clickableText.IsEnabled = false; + + // we may not want double clicks to make it double the work + clickableText.Action += () => + { + clickableText.IsEnabled = false; + Scheduler.AddDelayed(() => clickableText.IsEnabled = true, 2000); + }; } public void UpdateChevronTooltips(string previousVersion, string nextVersion) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 3e52e66e35..ccf2884422 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -26,6 +26,7 @@ namespace osu.Game.Overlays private readonly ChangelogHeader header; private readonly ChangelogBadges badges; private readonly ChangelogChart chart; + private readonly ChangelogContent listing; private readonly ChangelogContent content; private readonly ScrollContainer scroll; @@ -85,13 +86,15 @@ namespace osu.Game.Overlays header = new ChangelogHeader(), badges = new ChangelogBadges(), chart = new ChangelogChart(), + listing = new ChangelogContent(), content = new ChangelogContent() }, }, }, }; - header.ListingSelected += FetchAndShowListing; + header.ListingSelected += ShowListing; badges.Selected += onBuildSelected; + listing.BuildSelected += onBuildSelected; content.BuildSelected += onBuildSelected; } @@ -107,7 +110,7 @@ namespace osu.Game.Overlays var req = new GetChangelogLatestBuildsRequest(); req.Success += badges.Populate; api.Queue(req); - FetchAndShowListing(); + fetchListing(); base.LoadComplete(); } @@ -132,7 +135,7 @@ namespace osu.Game.Overlays State = Visibility.Hidden; else { - FetchAndShowListing(); + ShowListing(); sampleBack?.Play(); } return true; @@ -143,10 +146,7 @@ namespace osu.Game.Overlays private void onBuildSelected(APIChangelog build, EventArgs e) => FetchAndShowBuild(build); - /// - /// If we're not already at it, fetches and shows changelog listing. - /// - public void FetchAndShowListing() + private void fetchListing() { header.ShowListing(); if (isAtListing) @@ -155,14 +155,24 @@ namespace osu.Game.Overlays var req = new GetChangelogRequest(); badges.SelectNone(); chart.ShowAllUpdateStreams(); - req.Success += listing => - { - content.ShowListing(listing); - scroll.ScrollTo(savedScrollPosition); - }; + req.Success += listing.ShowListing; api.Queue(req); } + public void ShowListing() + { + header.ShowListing(); + if (isAtListing) + return; + isAtListing = true; + content.Hide(); + listing.Show(); + badges.SelectNone(); + chart.ShowAllUpdateStreams(); + listing.Show(); + scroll.ScrollTo(savedScrollPosition); + } + /// /// Fetches and shows a specific build from a specific update stream. /// @@ -181,6 +191,8 @@ namespace osu.Game.Overlays chart.ShowUpdateStream(build.UpdateStream.Name); req.Success += APIChangelog => { + listing.Hide(); + content.Show(); content.ShowBuild(APIChangelog); if (scroll.Current > scroll.GetChildPosInContent(content)) scroll.ScrollTo(content); From 74540bba83dd62594a6c1447ac36adfe18baef64 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 21:59:09 +0200 Subject: [PATCH 0083/5608] Non-breaking space for "by ..." Doesn't work for now(?) --- osu.Game/Overlays/Changelog/ChangelogContentGroup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 88be51bb47..23e05d8065 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -244,7 +244,7 @@ namespace osu.Game.Overlays.Changelog t.Colour = Color4.SkyBlue; }); } - title.AddText($" by {entry.GithubUser.DisplayName}", t => t.TextSize = 14); //web: 12; + title.AddText($" by\u00A0{entry.GithubUser.DisplayName}", t => t.TextSize = 14); //web: 12; TextFlowContainer messageContainer; ChangelogEntries.Add(messageContainer = new OsuTextFlowContainer { From d2b2c4c19b3ef6778d73f8867b99c0be9966bc97 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Tue, 24 Jul 2018 23:25:57 +0200 Subject: [PATCH 0084/5608] Make PR-link surrounding parenthesis white --- .../Overlays/Changelog/ChangelogContentGroup.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 23e05d8065..821f6aadc4 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -221,15 +221,13 @@ namespace osu.Game.Overlays.Changelog }); foreach (ChangelogEntry entry in category.Value) { - OsuTextFlowContainer title; - - ChangelogEntries.Add(title = new OsuTextFlowContainer + OsuTextFlowContainer title = new OsuTextFlowContainer { Direction = FillDirection.Full, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Margin = new MarginPadding { Vertical = 5 }, - }); + }; title.AddIcon(FontAwesome.fa_check, t => { t.TextSize = 12; @@ -238,24 +236,27 @@ namespace osu.Game.Overlays.Changelog title.AddText(entry.Title, t => { t.TextSize = 18; }); if (!string.IsNullOrEmpty(entry.Repository)) { - title.AddText($" ({entry.Repository.Substring(4)}#{entry.GithubPullRequestId})", t => + title.AddText(" (", t => t.TextSize = 18); + title.AddText($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", t => { t.TextSize = 18; t.Colour = Color4.SkyBlue; }); + title.AddText(")", t => t.TextSize = 18); } title.AddText($" by\u00A0{entry.GithubUser.DisplayName}", t => t.TextSize = 14); //web: 12; - TextFlowContainer messageContainer; - ChangelogEntries.Add(messageContainer = new OsuTextFlowContainer + ChangelogEntries.Add(title); + TextFlowContainer messageContainer = new TextFlowContainer { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, - }); + }; messageContainer.AddText($"{entry.MessageHtml?.Replace("

", "").Replace("

", "")}\n", t => { t.TextSize = 14; // web: 12, t.Colour = new Color4(235, 184, 254, 255); }); + ChangelogEntries.Add(messageContainer); } } } From a00f4e81788fe1dd49f139d509e13a12ff848458 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 25 Jul 2018 00:12:05 +0200 Subject: [PATCH 0085/5608] Make Back action go to the top of listing before exiting the changelog screen --- osu.Game/Overlays/ChangelogOverlay.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index ccf2884422..fc21ac64ac 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -132,7 +132,15 @@ namespace osu.Game.Overlays { case GlobalAction.Back: if (isAtListing) - State = Visibility.Hidden; + { + if (scroll.Current > scroll.GetChildPosInContent(listing)) + { + scroll.ScrollTo(0); + sampleBack?.Play(); + } + else + State = Visibility.Hidden; + } else { ShowListing(); From cd79c2cc45c70cc59a07e42b5257a7799075086e Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 25 Jul 2018 00:59:21 +0200 Subject: [PATCH 0086/5608] Hide graph when it's unavailable; Scroll change --- osu.Game/Overlays/Changelog/ChangelogChart.cs | 40 +++++++++++-------- osu.Game/Overlays/ChangelogOverlay.cs | 6 +-- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index 667f206250..3313e4adcc 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -17,6 +17,10 @@ namespace osu.Game.Overlays.Changelog // maybe look to osu.Game.Screens.Play.SquareGraph for reference later public class ChangelogChart : BufferedContainer { + private const float height = 100; + private const float transition_duration = 300; + + private readonly Container container; private readonly Box background; private readonly SpriteText text; private APIAccess api; @@ -24,20 +28,25 @@ namespace osu.Game.Overlays.Changelog public ChangelogChart() { RelativeSizeAxes = Axes.X; - Height = 100; - Children = new Drawable[] + AutoSizeAxes = Axes.Y; + Child = container = new Container { - background = new Box + RelativeSizeAxes = Axes.X, + Height = height, + Children = new Drawable[] { - Colour = StreamColour.STABLE, - RelativeSizeAxes = Axes.Both, - }, - text = new SpriteText - { - Text = "Graph Placeholder", - TextSize = 28, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + background = new Box + { + Colour = StreamColour.STABLE, + RelativeSizeAxes = Axes.Both, + }, + text = new SpriteText + { + Text = "Graph Placeholder", + TextSize = 28, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, }, }; } @@ -55,13 +64,10 @@ namespace osu.Game.Overlays.Changelog if (!isEmpty(chartInfo)) { background.Colour = StreamColour.FromStreamName(updateStreamName); - text.Text = "Graph placeholder\n(chart is not empty)"; + container.MoveToY(0, transition_duration, Easing.InOutQuad).FadeIn(transition_duration); } else - { - background.Colour = Color4.Black; - text.Text = "Graph placeholder\n(chart is empty)"; - } + container.MoveToY(-height, transition_duration, Easing.InOutQuad).FadeOut(transition_duration); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index fc21ac64ac..a0d0726c01 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -197,13 +197,13 @@ namespace osu.Game.Overlays badges.SelectUpdateStream(build.UpdateStream.Name); chart.ShowUpdateStream(build.UpdateStream.Name); - req.Success += APIChangelog => + req.Success += apiChangelog => { listing.Hide(); content.Show(); - content.ShowBuild(APIChangelog); + content.ShowBuild(apiChangelog); if (scroll.Current > scroll.GetChildPosInContent(content)) - scroll.ScrollTo(content); + scroll.ScrollTo(chart); if (isAtListing) savedScrollPosition = scroll.Current; isAtListing = false; From 05a59f352547a716c149e70b198f111d4a1923da Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 25 Jul 2018 03:54:16 +0200 Subject: [PATCH 0087/5608] Add links to GitHub --- .../Changelog/ChangelogContentGroup.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 821f6aadc4..07e695b439 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -221,7 +221,7 @@ namespace osu.Game.Overlays.Changelog }); foreach (ChangelogEntry entry in category.Value) { - OsuTextFlowContainer title = new OsuTextFlowContainer + LinkFlowContainer title = new LinkFlowContainer { Direction = FillDirection.Full, RelativeSizeAxes = Axes.X, @@ -237,14 +237,18 @@ namespace osu.Game.Overlays.Changelog if (!string.IsNullOrEmpty(entry.Repository)) { title.AddText(" (", t => t.TextSize = 18); - title.AddText($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", t => - { - t.TextSize = 18; - t.Colour = Color4.SkyBlue; - }); + title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", + entry.GithubUrl, Online.Chat.LinkAction.External, null, + null, t => { t.TextSize = 18; }); title.AddText(")", t => t.TextSize = 18); } - title.AddText($" by\u00A0{entry.GithubUser.DisplayName}", t => t.TextSize = 14); //web: 12; + title.AddText(" by ", t => t.TextSize = 14); + if (entry.GithubUser.GithubUrl != null) + title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, + Online.Chat.LinkAction.External, null, null, + t => t.TextSize = 14); + else + title.AddText(entry.GithubUser.DisplayName, t => t.TextSize = 14); //web: 12; ChangelogEntries.Add(title); TextFlowContainer messageContainer = new TextFlowContainer { @@ -255,6 +259,7 @@ namespace osu.Game.Overlays.Changelog { t.TextSize = 14; // web: 12, t.Colour = new Color4(235, 184, 254, 255); + t = new ClickableText(); }); ChangelogEntries.Add(messageContainer); } From c8f36a0c66626103df5611b143b1bfd19448f8c4 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 25 Jul 2018 03:58:08 +0200 Subject: [PATCH 0088/5608] Add links to GitHub; Remove reduntant using directive and variable --- osu.Game/Overlays/Changelog/ChangelogChart.cs | 4 +--- osu.Game/Overlays/Changelog/ChangelogContentGroup.cs | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index 3313e4adcc..c88eae98a4 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -22,7 +21,6 @@ namespace osu.Game.Overlays.Changelog private readonly Container container; private readonly Box background; - private readonly SpriteText text; private APIAccess api; public ChangelogChart() @@ -40,7 +38,7 @@ namespace osu.Game.Overlays.Changelog Colour = StreamColour.STABLE, RelativeSizeAxes = Axes.Both, }, - text = new SpriteText + new SpriteText { Text = "Graph Placeholder", TextSize = 28, diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 07e695b439..1346689cb7 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -259,7 +259,6 @@ namespace osu.Game.Overlays.Changelog { t.TextSize = 14; // web: 12, t.Colour = new Color4(235, 184, 254, 255); - t = new ClickableText(); }); ChangelogEntries.Add(messageContainer); } From 2906f4b401fcbc69828cf02ef1d06f00c4d4d21c Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 25 Jul 2018 14:31:41 +0200 Subject: [PATCH 0089/5608] Change initial chart colour --- .../Visual/TestCaseChangelogOverlay.cs | 20 +++++++++++++++++++ osu.Game/Overlays/Changelog/ChangelogChart.cs | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs index 53143bd924..d64f1c00f7 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; namespace osu.Game.Tests.Visual @@ -17,6 +18,25 @@ namespace osu.Game.Tests.Visual Add(changelog = new ChangelogOverlay()); AddStep(@"Show", changelog.Show); + AddStep(@"Hide", changelog.Hide); + AddWaitStep(3); + AddStep(@"Show with Lazer 2018.712.0", () => + { + changelog.FetchAndShowBuild(new APIChangelog + { + Version = "2018.712.0", + UpdateStream = new UpdateStream { Name = "lazer" }, + }); + changelog.Show(); + }); + AddWaitStep(3); + AddStep(@"Hide", changelog.Hide); + AddWaitStep(3); + AddStep(@"Show with listing", () => + { + changelog.ShowListing(); + changelog.Show(); + }); } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index c88eae98a4..369982a2ac 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.Changelog { background = new Box { - Colour = StreamColour.STABLE, + Colour = OsuColour.Gray(0), RelativeSizeAxes = Axes.Both, }, new SpriteText @@ -44,6 +44,7 @@ namespace osu.Game.Overlays.Changelog TextSize = 28, Anchor = Anchor.Centre, Origin = Anchor.Centre, + Colour = OsuColour.Gray(1), }, }, }; From a7a6e52c16a1f2e9dde1c397e090e0cd4b765a83 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 25 Jul 2018 14:58:18 +0200 Subject: [PATCH 0090/5608] Bring StreamBadge visual proportions closer to the upstream design --- osu.Game/Overlays/Changelog/StreamBadge.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 8c881348c7..fc12d58f7a 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Changelog { public class StreamBadge : ClickableContainer { - private const float badge_height = 56.5f; + private const float badge_height = 66.5f; private const float badge_width = 100; private const float transition_duration = 100; @@ -40,7 +40,7 @@ namespace osu.Game.Overlays.Changelog LatestBuild = latestBuild; Height = badge_height; Width = LatestBuild.IsFeatured ? badge_width * 2 : badge_width; - Margin = new MarginPadding(5); + Padding = new MarginPadding(5); isActivated = true; Children = new Drawable[] { @@ -55,24 +55,21 @@ namespace osu.Game.Overlays.Changelog { Text = LatestBuild.UpdateStream.DisplayName, Font = @"Exo2.0-Bold", - TextSize = 16, - Margin = new MarginPadding - { - Top = 7, - } + TextSize = 14, // web: 12, + Margin = new MarginPadding { Top = 6, }, }, new SpriteText { Text = LatestBuild.DisplayVersion, Font = @"Exo2.0-Light", - TextSize = 21, + TextSize = 20, // web: 16, }, new SpriteText { Text = LatestBuild.Users > 0 ? $"{LatestBuild.Users:N0} users online" : null, - TextSize = 12, + TextSize = 12, // web: 10, Font = @"Exo2.0-Regular", Colour = new Color4(203, 164, 218, 255), }, From 3e6968b57ebf6baf488f0e7bf893f57370bf1030 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 25 Jul 2018 17:04:36 +0200 Subject: [PATCH 0091/5608] Unify MarginPadding --- osu.Game/Overlays/Changelog/ChangelogBadges.cs | 12 +++--------- osu.Game/Overlays/Changelog/ChangelogContent.cs | 6 +++--- osu.Game/Overlays/Changelog/ChangelogContentGroup.cs | 2 +- osu.Game/Overlays/Changelog/Header/TextBadgePair.cs | 6 +----- osu.Game/Overlays/Changelog/StreamBadge.cs | 2 +- 5 files changed, 9 insertions(+), 19 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index 1a5e4f7d18..365d808108 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -15,8 +15,8 @@ namespace osu.Game.Overlays.Changelog public class ChangelogBadges : Container { private const float container_height = 106.5f; - private const float padding_y = 20; - private const float padding_x = 85; + private const float vertical_padding = 20; + private const float horizontal_padding = 85; public delegate void SelectionHandler(APIChangelog releaseStream, EventArgs args); @@ -40,13 +40,7 @@ namespace osu.Game.Overlays.Changelog { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding - { - Top = padding_y, - Bottom = padding_y, - Left = padding_x, - Right = padding_x, - }, + Padding = new MarginPadding { Vertical = vertical_padding, Horizontal = horizontal_padding }, }, }; } diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 7e92ab4c26..588a61f678 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Changelog RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; - Padding = new MarginPadding{ Bottom = 100, }; + Padding = new MarginPadding{ Bottom = 100 }; } public void ShowListing(APIChangelog[] changelog) @@ -44,7 +44,7 @@ namespace osu.Game.Overlays.Changelog RelativeSizeAxes = Axes.X, Height = 2, Colour = new Color4(17, 17, 17, 255), - Margin = new MarginPadding { Top = 30, }, + Margin = new MarginPadding { Top = 30 }, }); } changelogContentGroup = new ChangelogContentGroup(build, true); @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.Changelog RelativeSizeAxes = Axes.X, Height = 1, Colour = new Color4(32, 24, 35, 255), - Margin = new MarginPadding { Top = 30, }, + Margin = new MarginPadding { Top = 30 }, }); changelogContentGroup = new ChangelogContentGroup(build, false); diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 1346689cb7..8768f3623b 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -105,7 +105,7 @@ namespace osu.Game.Overlays.Changelog Font = @"Exo2.0-Medium", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Margin = new MarginPadding { Top = 5 } + Margin = new MarginPadding { Top = 5 }, }, ChangelogEntries = new FillFlowContainer { diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index 201524cc2f..dd4ca1ce0b 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -39,11 +39,7 @@ namespace osu.Game.Overlays.Changelog.Header Text = displayText, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding - { - Top = 5, - Bottom = 15, - } + Margin = new MarginPadding { Top = 5, Bottom = 15 }, }, LineBadge = new LineBadge(startCollapsed) { diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index fc12d58f7a..ad5a858545 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -56,7 +56,7 @@ namespace osu.Game.Overlays.Changelog Text = LatestBuild.UpdateStream.DisplayName, Font = @"Exo2.0-Bold", TextSize = 14, // web: 12, - Margin = new MarginPadding { Top = 6, }, + Margin = new MarginPadding { Top = 6 }, }, new SpriteText { From dcb5eb1767c3772a033172524f81f0bbb45ab153 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 25 Jul 2018 17:05:29 +0200 Subject: [PATCH 0092/5608] Remove reduntant comment --- osu.Game/Overlays/Changelog/ChangelogChart.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index 369982a2ac..7880ad8021 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -13,7 +13,6 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Changelog { - // maybe look to osu.Game.Screens.Play.SquareGraph for reference later public class ChangelogChart : BufferedContainer { private const float height = 100; From fb8ea770aef05d199d49cfdaed7c5692dd73dd97 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 25 Jul 2018 18:55:02 +0200 Subject: [PATCH 0093/5608] Make ChangelogChart's child buffered --- osu.Game/Overlays/Changelog/ChangelogChart.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index 7880ad8021..ee41b8085b 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -13,12 +13,13 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Changelog { - public class ChangelogChart : BufferedContainer + public class ChangelogChart : Container { private const float height = 100; private const float transition_duration = 300; - private readonly Container container; + // why make the child buffered? https://streamable.com/swbdj + private readonly BufferedContainer container; private readonly Box background; private APIAccess api; @@ -26,7 +27,7 @@ namespace osu.Game.Overlays.Changelog { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Child = container = new Container + Child = container = new BufferedContainer { RelativeSizeAxes = Axes.X, Height = height, From 81786c4763a3ccf68f66ac80f380b60243fad7cf Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 25 Jul 2018 20:01:24 +0200 Subject: [PATCH 0094/5608] Move statement to a new line --- osu.Game/Overlays/Changelog/ChangelogChart.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index ee41b8085b..d965651e27 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -54,7 +54,8 @@ namespace osu.Game.Overlays.Changelog { if (changelogChart != null) foreach (BuildHistory buildHistory in changelogChart.BuildHistory) - if (buildHistory.UserCount > 0) return false; + if (buildHistory.UserCount > 0) + return false; return true; } From e1a24f55cfc84cb0aef8be7784dae73c36f753ff Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 25 Jul 2018 20:31:26 +0200 Subject: [PATCH 0095/5608] Update comments --- osu.Game/Graphics/UserInterface/ClickableText.cs | 4 ++++ osu.Game/Graphics/UserInterface/TooltipIconButton.cs | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ClickableText.cs b/osu.Game/Graphics/UserInterface/ClickableText.cs index c27bc56238..159a2c3377 100644 --- a/osu.Game/Graphics/UserInterface/ClickableText.cs +++ b/osu.Game/Graphics/UserInterface/ClickableText.cs @@ -12,6 +12,10 @@ using System; namespace osu.Game.Graphics.UserInterface { + // created a new class instead of using a Link in + // some kind of textflowcontainer because they aren't + // capable of having delegates/actions on click + // and (probably) can't be disabled public class ClickableText : OsuSpriteText, IHasTooltip { private bool isEnabled; diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index 65ab5de036..19c5421f6a 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -15,8 +15,7 @@ using System; namespace osu.Game.Graphics.UserInterface { // not inheriting osuclickablecontainer/osuhovercontainer - // because click/hover sounds cannot be disabled, and they make - // double sounds when reappearing under the cursor + // because click/hover sounds cannot be disabled public class TooltipIconButton : ClickableContainer, IHasTooltip { private readonly SpriteIcon icon; From 6e6e43e8dffade2c4c1a551448c3a8827b17b3ae Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 25 Jul 2018 21:38:32 +0200 Subject: [PATCH 0096/5608] ClickableText changes colour on hover --- .../Graphics/UserInterface/ClickableText.cs | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/ClickableText.cs b/osu.Game/Graphics/UserInterface/ClickableText.cs index 159a2c3377..739c5067d2 100644 --- a/osu.Game/Graphics/UserInterface/ClickableText.cs +++ b/osu.Game/Graphics/UserInterface/ClickableText.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -20,9 +21,13 @@ namespace osu.Game.Graphics.UserInterface { private bool isEnabled; private bool isMuted; + private SampleChannel sampleHover; private SampleChannel sampleClick; + protected Color4 HoverColour; + protected Color4 IdleColour; + /// /// An action that can be set to execute after click. /// @@ -78,10 +83,19 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(InputState state) { if (isEnabled && !IsHoverMuted) + { + this.FadeColour(HoverColour, 500, Easing.OutQuint); sampleHover?.Play(); + } return base.OnHover(state); } + protected override void OnHoverLost(InputState state) + { + this.FadeColour(IdleColour, 500, Easing.OutQuint); + base.OnHoverLost(state); + } + protected override bool OnClick(InputState state) { if (isEnabled) @@ -93,13 +107,20 @@ namespace osu.Game.Graphics.UserInterface return base.OnClick(state); } + protected override void LoadComplete() + { + IdleColour = Colour; + base.LoadComplete(); + } + public string TooltipText { get; set; } [BackgroundDependencyLoader] - private void load(AudioManager audio) + private void load(AudioManager audio, OsuColour colours) { sampleClick = audio.Sample.Get(@"UI/generic-select-soft"); sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); + HoverColour = colours.Yellow; } } } From 93dbc55738957e7561a2cf1f128dd804e30b825e Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Thu, 26 Jul 2018 10:47:43 +0200 Subject: [PATCH 0097/5608] Fix wrong conditional expression --- osu.Game/Graphics/UserInterface/ClickableText.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ClickableText.cs b/osu.Game/Graphics/UserInterface/ClickableText.cs index 739c5067d2..e0121ae28c 100644 --- a/osu.Game/Graphics/UserInterface/ClickableText.cs +++ b/osu.Game/Graphics/UserInterface/ClickableText.cs @@ -82,10 +82,11 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(InputState state) { - if (isEnabled && !IsHoverMuted) + if (isEnabled) { this.FadeColour(HoverColour, 500, Easing.OutQuint); - sampleHover?.Play(); + if (!IsHoverMuted) + sampleHover?.Play(); } return base.OnHover(state); } From a2959e9171114496ec61b56f982caefae22d7e26 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Thu, 26 Jul 2018 13:43:47 +0200 Subject: [PATCH 0098/5608] Remove default value without use --- osu.Game/Overlays/Changelog/ChangelogContentGroup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 8768f3623b..3e0023ea9a 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -116,7 +116,7 @@ namespace osu.Game.Overlays.Changelog }; } - public ChangelogContentGroup(APIChangelog build, bool newDate = false) + public ChangelogContentGroup(APIChangelog build, bool newDate) { ClickableText clickableText; RelativeSizeAxes = Axes.X; From 0f263e2ccabfd9bb751148527c860baf0261d62f Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Thu, 26 Jul 2018 14:19:58 +0200 Subject: [PATCH 0099/5608] Delete ClickableText class, use OsuHoverContainer instead --- .../Visual/TestCaseClickableText.cs | 30 ----- .../Graphics/UserInterface/ClickableText.cs | 127 ------------------ .../Changelog/ChangelogContentGroup.cs | 49 ++++--- 3 files changed, 29 insertions(+), 177 deletions(-) delete mode 100644 osu.Game.Tests/Visual/TestCaseClickableText.cs delete mode 100644 osu.Game/Graphics/UserInterface/ClickableText.cs diff --git a/osu.Game.Tests/Visual/TestCaseClickableText.cs b/osu.Game.Tests/Visual/TestCaseClickableText.cs deleted file mode 100644 index 60ee764cfc..0000000000 --- a/osu.Game.Tests/Visual/TestCaseClickableText.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics.UserInterface; -using System; -using System.Collections.Generic; - -namespace osu.Game.Tests.Visual -{ - public class TestCaseClickableText : OsuTestCase - { - public override IReadOnlyList RequiredTypes => new[] { typeof(ClickableText), typeof(FillFlowContainer) }; - - private readonly ClickableText text; - public TestCaseClickableText() => Child = new FillFlowContainer - { - Children = new[] - { - new ClickableText { Text = "Default", }, - new ClickableText { IsEnabled = false, Text = "Disabled", }, - new ClickableText { Text = "Without sounds", IsMuted = true, }, - new ClickableText { Text = "Without click sounds", IsClickMuted = true, }, - new ClickableText { Text = "Without hover sounds", IsHoverMuted = true, }, - text = new ClickableText { Text = "Disables after click (Action)", Action = () => text.IsEnabled = false }, - new ClickableText { Text = "Has tooltip", TooltipText = "Yep", }, - } - }; - } -} diff --git a/osu.Game/Graphics/UserInterface/ClickableText.cs b/osu.Game/Graphics/UserInterface/ClickableText.cs deleted file mode 100644 index e0121ae28c..0000000000 --- a/osu.Game/Graphics/UserInterface/ClickableText.cs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using OpenTK.Graphics; -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Input.States; -using osu.Game.Graphics.Sprites; -using System; - -namespace osu.Game.Graphics.UserInterface -{ - // created a new class instead of using a Link in - // some kind of textflowcontainer because they aren't - // capable of having delegates/actions on click - // and (probably) can't be disabled - public class ClickableText : OsuSpriteText, IHasTooltip - { - private bool isEnabled; - private bool isMuted; - - private SampleChannel sampleHover; - private SampleChannel sampleClick; - - protected Color4 HoverColour; - protected Color4 IdleColour; - - /// - /// An action that can be set to execute after click. - /// - public Action Action; - - /// - /// If set to true, a sound will be played on click. - /// - public bool IsClickMuted; - - /// - /// If set to true, a sound will be played on hover. - /// - public bool IsHoverMuted; - - /// - /// If disabled, no sounds will be played and wont execute. - /// True by default. - /// - public bool IsEnabled - { - get { return isEnabled; } - set - { - isEnabled = value; - this.FadeTo(value ? 1 : 0.5f, 250); - } - } - - /// - /// Whether to play sounds on hover and click. Automatically sets - /// and to the same value.> - /// - public bool IsMuted { - get { return isMuted; } - set - { - IsHoverMuted = value; - IsClickMuted = value; - isMuted = value; - } - } - - /// - /// A text with sounds on hover and click, - /// an action that can be set to execute on click, - /// and a tooltip. - /// - public ClickableText() => isEnabled = true; - - public override bool HandleMouseInput => true; - - protected override bool OnHover(InputState state) - { - if (isEnabled) - { - this.FadeColour(HoverColour, 500, Easing.OutQuint); - if (!IsHoverMuted) - sampleHover?.Play(); - } - return base.OnHover(state); - } - - protected override void OnHoverLost(InputState state) - { - this.FadeColour(IdleColour, 500, Easing.OutQuint); - base.OnHoverLost(state); - } - - protected override bool OnClick(InputState state) - { - if (isEnabled) - { - if (!IsClickMuted) - sampleClick?.Play(); - Action?.Invoke(); - } - return base.OnClick(state); - } - - protected override void LoadComplete() - { - IdleColour = Colour; - base.LoadComplete(); - } - - public string TooltipText { get; set; } - - [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuColour colours) - { - sampleClick = audio.Sample.Get(@"UI/generic-select-soft"); - sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); - HoverColour = colours.Yellow; - } - } -} diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 3e0023ea9a..3208f424ce 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -118,7 +118,7 @@ namespace osu.Game.Overlays.Changelog public ChangelogContentGroup(APIChangelog build, bool newDate) { - ClickableText clickableText; + OsuHoverContainer clickableBuildText; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; @@ -138,29 +138,33 @@ namespace osu.Game.Overlays.Changelog Margin = new MarginPadding { Top = 20 }, Alpha = newDate ? 1 : 0, }, - new FillFlowContainer + clickableBuildText = new OsuHoverContainer { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, Margin = new MarginPadding { Top = 20 }, - Spacing = new Vector2(5), - Children = new Drawable[] + Action = () => OnBuildSelected(build), + Child = new FillFlowContainer { - new SpriteText + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), + AutoSizeAxes = Axes.Both, + Children = new Drawable[] { - Text = build.UpdateStream.DisplayName, - TextSize = 20, // web: 18, - Font = @"Exo2.0-Medium", - }, - clickableText = new ClickableText - { - Text = build.DisplayVersion, - TextSize = 20, // web: 18, - Font = @"Exo2.0-Light", - Colour = StreamColour.FromStreamName(build.UpdateStream.Name), - Action = () => OnBuildSelected(build), + new SpriteText + { + Text = build.UpdateStream.DisplayName, + TextSize = 20, // web: 18, + Font = @"Exo2.0-Medium", + }, + new SpriteText + { + Text = build.DisplayVersion, + TextSize = 20, // web: 18, + Font = @"Exo2.0-Light", + Colour = StreamColour.FromStreamName(build.UpdateStream.Name), + }, }, } }, @@ -173,10 +177,15 @@ namespace osu.Game.Overlays.Changelog }; // we may not want double clicks to make it double the work - clickableText.Action += () => + // can be clicked again only after a delay + clickableBuildText.Action += () => { - clickableText.IsEnabled = false; - Scheduler.AddDelayed(() => clickableText.IsEnabled = true, 2000); + clickableBuildText.Action = null; + clickableBuildText.FadeTo(0.5f, 500); + Scheduler.AddDelayed(() => { + clickableBuildText.Action = () => OnBuildSelected(build); + clickableBuildText.FadeIn(500); + }, 2000); }; } From 2d8277f4137868e91d620e24d881fc4c63c092f5 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Thu, 26 Jul 2018 17:02:51 +0200 Subject: [PATCH 0100/5608] Plotting the chart 1 --- osu.Game/Overlays/Changelog/ChangelogChart.cs | 54 ++++++++++++++++--- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index d965651e27..0141a3b3e1 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -3,13 +3,16 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Logging; using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; +using System; namespace osu.Game.Overlays.Changelog { @@ -19,7 +22,7 @@ namespace osu.Game.Overlays.Changelog private const float transition_duration = 300; // why make the child buffered? https://streamable.com/swbdj - private readonly BufferedContainer container; + private readonly Container container; private readonly Box background; private APIAccess api; @@ -27,17 +30,17 @@ namespace osu.Game.Overlays.Changelog { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Child = container = new BufferedContainer + Child = container = new Container { RelativeSizeAxes = Axes.X, Height = height, Children = new Drawable[] { - background = new Box - { - Colour = OsuColour.Gray(0), - RelativeSizeAxes = Axes.Both, - }, + //background = new Box + //{ + // Colour = OsuColour.Gray(0), + // RelativeSizeAxes = Axes.Both, + //}, new SpriteText { Text = "Graph Placeholder", @@ -63,8 +66,8 @@ namespace osu.Game.Overlays.Changelog { if (!isEmpty(chartInfo)) { - background.Colour = StreamColour.FromStreamName(updateStreamName); container.MoveToY(0, transition_duration, Easing.InOutQuad).FadeIn(transition_duration); + plotChart(chartInfo, StreamColour.FromStreamName(updateStreamName)); } else container.MoveToY(-height, transition_duration, Easing.InOutQuad).FadeOut(transition_duration); @@ -89,5 +92,40 @@ namespace osu.Game.Overlays.Changelog req.Success += res => showChart(res); api.Queue(req); } + + // this could probably be combined with isEmpty, todo + private float getMaxUserCount(APIChangelogChart changelogChartInfo) + { + var maxUserCount = 0l; + foreach (BuildHistory build in changelogChartInfo.BuildHistory) + { + if (build.UserCount > maxUserCount) + maxUserCount = build.UserCount; + } + return maxUserCount; + } + + private void plotChart(APIChangelogChart changelogChartInfo, ColourInfo colour) + { + var maxUserCount = getMaxUserCount(changelogChartInfo); + var currentPos = 0f; + + container.Clear(); + + foreach (BuildHistory build in changelogChartInfo.BuildHistory) + { + container.Add(new Box + { + RelativeSizeAxes = Axes.Y, + Width = Math.Max(container.DrawWidth / changelogChartInfo.BuildHistory.Count, 2), + Height = build.UserCount / maxUserCount, + X = currentPos, + Colour = colour, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + }); + currentPos += container.DrawWidth / changelogChartInfo.BuildHistory.Count; + } + } } } From 516ba10dadbe321a19ae285392fa9719d468ccb5 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Thu, 26 Jul 2018 17:26:42 +0200 Subject: [PATCH 0101/5608] Plotting the chart 2 --- osu.Game/Overlays/Changelog/ChangelogChart.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index 0141a3b3e1..730c0e2ad7 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.Logging; using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Online.API.Requests; @@ -30,6 +29,7 @@ namespace osu.Game.Overlays.Changelog { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + Masking = true; Child = container = new Container { RelativeSizeAxes = Axes.X, @@ -117,12 +117,13 @@ namespace osu.Game.Overlays.Changelog container.Add(new Box { RelativeSizeAxes = Axes.Y, - Width = Math.Max(container.DrawWidth / changelogChartInfo.BuildHistory.Count, 2), + Width = Math.Max(container.DrawWidth / changelogChartInfo.BuildHistory.Count, 1), Height = build.UserCount / maxUserCount, X = currentPos, Colour = colour, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, + Blending = BlendingMode.None, }); currentPos += container.DrawWidth / changelogChartInfo.BuildHistory.Count; } From 46134ed63d7bc012b67701a15dcc3b5155de14fd Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Thu, 26 Jul 2018 23:53:12 +0200 Subject: [PATCH 0102/5608] Add "ok" chart plotting; Add more keys to StreamColour .FromStreamName function --- osu.Game/Graphics/StreamColour.cs | 5 ++ osu.Game/Overlays/Changelog/ChangelogChart.cs | 86 ++++++++++++------- 2 files changed, 60 insertions(+), 31 deletions(-) diff --git a/osu.Game/Graphics/StreamColour.cs b/osu.Game/Graphics/StreamColour.cs index 71626a0e3a..9149c29b0a 100644 --- a/osu.Game/Graphics/StreamColour.cs +++ b/osu.Game/Graphics/StreamColour.cs @@ -19,10 +19,15 @@ namespace osu.Game.Graphics private static readonly Dictionary colours = new Dictionary { { "stable40", STABLE }, + { "Stable", STABLE }, { "stable", STABLEFALLBACK }, + { "Stable Fallback", STABLEFALLBACK }, { "beta40", BETA }, + { "Beta", BETA }, { "cuttingedge", CUTTINGEDGE }, + { "Cutting Edge", CUTTINGEDGE }, { "lazer", LAZER }, + { "Lazer", LAZER }, { "web", WEB }, }; diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs index 730c0e2ad7..57b3022724 100644 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ b/osu.Game/Overlays/Changelog/ChangelogChart.cs @@ -8,10 +8,12 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using System; +using System.Collections.Generic; namespace osu.Game.Overlays.Changelog { @@ -29,27 +31,10 @@ namespace osu.Game.Overlays.Changelog { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Masking = true; Child = container = new Container { RelativeSizeAxes = Axes.X, Height = height, - Children = new Drawable[] - { - //background = new Box - //{ - // Colour = OsuColour.Gray(0), - // RelativeSizeAxes = Axes.Both, - //}, - new SpriteText - { - Text = "Graph Placeholder", - TextSize = 28, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Colour = OsuColour.Gray(1), - }, - }, }; } @@ -67,7 +52,10 @@ namespace osu.Game.Overlays.Changelog if (!isEmpty(chartInfo)) { container.MoveToY(0, transition_duration, Easing.InOutQuad).FadeIn(transition_duration); - plotChart(chartInfo, StreamColour.FromStreamName(updateStreamName)); + if (string.IsNullOrEmpty(updateStreamName)) + plotCharts(chartInfo); + else + plotChart(chartInfo, StreamColour.FromStreamName(updateStreamName)); } else container.MoveToY(-height, transition_duration, Easing.InOutQuad).FadeOut(transition_duration); @@ -105,27 +93,63 @@ namespace osu.Game.Overlays.Changelog return maxUserCount; } + private List clearUpDips(List buildHistories, float maxUserCount) + { + var buildHistory = new List(); + foreach (BuildHistory build in buildHistories) + { + if (build.UserCount / maxUserCount > 0.2f) + buildHistory.Add(build.UserCount); + } + return buildHistory; + } + private void plotChart(APIChangelogChart changelogChartInfo, ColourInfo colour) { var maxUserCount = getMaxUserCount(changelogChartInfo); - var currentPos = 0f; - container.Clear(); + container.Child = new BarGraph + { + Colour = colour, + Values = clearUpDips(changelogChartInfo.BuildHistory, maxUserCount), + RelativeSizeAxes = Axes.Both, + Direction = BarDirection.BottomToTop, + }; + } + + private void plotCharts(APIChangelogChart changelogChartInfo) + { + var maxUserCount = getMaxUserCount(changelogChartInfo); + + var releaseStreams = new Dictionary>(changelogChartInfo.Order.Count); + var highestUserCounts = new Dictionary(changelogChartInfo.Order.Count); + + foreach (string updateStream in changelogChartInfo.Order) + { + releaseStreams.Add(updateStream, new List()); + highestUserCounts.Add(updateStream, 0); + } foreach (BuildHistory build in changelogChartInfo.BuildHistory) { - container.Add(new Box + releaseStreams[build.Label].Add(build.UserCount); + if (highestUserCounts[build.Label] < build.UserCount) + highestUserCounts[build.Label] = build.UserCount; + } + + container.Clear(); + + foreach (KeyValuePair> releaseStream in releaseStreams) + { + var barGraph = new BarGraph { - RelativeSizeAxes = Axes.Y, - Width = Math.Max(container.DrawWidth / changelogChartInfo.BuildHistory.Count, 1), - Height = build.UserCount / maxUserCount, - X = currentPos, - Colour = colour, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Blending = BlendingMode.None, - }); - currentPos += container.DrawWidth / changelogChartInfo.BuildHistory.Count; + Colour = StreamColour.FromStreamName(releaseStream.Key), + Values = releaseStream.Value, + RelativeSizeAxes = Axes.Both, + Direction = BarDirection.BottomToTop, + //Height = highestUserCounts[releaseStream.Key] / maxUserCount, + }; + container.Add(barGraph); } } } From fba817b4e110f7c44f30dd79139c3ede7c8f39df Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Fri, 27 Jul 2018 00:34:44 +0200 Subject: [PATCH 0103/5608] Resign ChangelogChart and disable its references --- osu.Game/Overlays/Changelog/ChangelogChart.cs | 156 ------------------ osu.Game/Overlays/ChangelogOverlay.cs | 20 ++- 2 files changed, 12 insertions(+), 164 deletions(-) delete mode 100644 osu.Game/Overlays/Changelog/ChangelogChart.cs diff --git a/osu.Game/Overlays/Changelog/ChangelogChart.cs b/osu.Game/Overlays/Changelog/ChangelogChart.cs deleted file mode 100644 index 57b3022724..0000000000 --- a/osu.Game/Overlays/Changelog/ChangelogChart.cs +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; -using osu.Game.Online.API.Requests.Responses; -using System; -using System.Collections.Generic; - -namespace osu.Game.Overlays.Changelog -{ - public class ChangelogChart : Container - { - private const float height = 100; - private const float transition_duration = 300; - - // why make the child buffered? https://streamable.com/swbdj - private readonly Container container; - private readonly Box background; - private APIAccess api; - - public ChangelogChart() - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Child = container = new Container - { - RelativeSizeAxes = Axes.X, - Height = height, - }; - } - - private bool isEmpty(APIChangelogChart changelogChart) - { - if (changelogChart != null) - foreach (BuildHistory buildHistory in changelogChart.BuildHistory) - if (buildHistory.UserCount > 0) - return false; - return true; - } - - private void showChart(APIChangelogChart chartInfo, string updateStreamName = null) - { - if (!isEmpty(chartInfo)) - { - container.MoveToY(0, transition_duration, Easing.InOutQuad).FadeIn(transition_duration); - if (string.IsNullOrEmpty(updateStreamName)) - plotCharts(chartInfo); - else - plotChart(chartInfo, StreamColour.FromStreamName(updateStreamName)); - } - else - container.MoveToY(-height, transition_duration, Easing.InOutQuad).FadeOut(transition_duration); - } - - [BackgroundDependencyLoader] - private void load(APIAccess api) - { - this.api = api; - } - - public void ShowUpdateStream(string updateStream) - { - var req = new GetChangelogChartRequest(updateStream); - req.Success += res => showChart(res, updateStream); - api.Queue(req); - } - - public void ShowAllUpdateStreams() - { - var req = new GetChangelogChartRequest(); - req.Success += res => showChart(res); - api.Queue(req); - } - - // this could probably be combined with isEmpty, todo - private float getMaxUserCount(APIChangelogChart changelogChartInfo) - { - var maxUserCount = 0l; - foreach (BuildHistory build in changelogChartInfo.BuildHistory) - { - if (build.UserCount > maxUserCount) - maxUserCount = build.UserCount; - } - return maxUserCount; - } - - private List clearUpDips(List buildHistories, float maxUserCount) - { - var buildHistory = new List(); - foreach (BuildHistory build in buildHistories) - { - if (build.UserCount / maxUserCount > 0.2f) - buildHistory.Add(build.UserCount); - } - return buildHistory; - } - - private void plotChart(APIChangelogChart changelogChartInfo, ColourInfo colour) - { - var maxUserCount = getMaxUserCount(changelogChartInfo); - - container.Child = new BarGraph - { - Colour = colour, - Values = clearUpDips(changelogChartInfo.BuildHistory, maxUserCount), - RelativeSizeAxes = Axes.Both, - Direction = BarDirection.BottomToTop, - }; - } - - private void plotCharts(APIChangelogChart changelogChartInfo) - { - var maxUserCount = getMaxUserCount(changelogChartInfo); - - var releaseStreams = new Dictionary>(changelogChartInfo.Order.Count); - var highestUserCounts = new Dictionary(changelogChartInfo.Order.Count); - - foreach (string updateStream in changelogChartInfo.Order) - { - releaseStreams.Add(updateStream, new List()); - highestUserCounts.Add(updateStream, 0); - } - - foreach (BuildHistory build in changelogChartInfo.BuildHistory) - { - releaseStreams[build.Label].Add(build.UserCount); - if (highestUserCounts[build.Label] < build.UserCount) - highestUserCounts[build.Label] = build.UserCount; - } - - container.Clear(); - - foreach (KeyValuePair> releaseStream in releaseStreams) - { - var barGraph = new BarGraph - { - Colour = StreamColour.FromStreamName(releaseStream.Key), - Values = releaseStream.Value, - RelativeSizeAxes = Axes.Both, - Direction = BarDirection.BottomToTop, - //Height = highestUserCounts[releaseStream.Key] / maxUserCount, - }; - container.Add(barGraph); - } - } - } -} diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index a0d0726c01..a14fa77da3 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -25,7 +25,7 @@ namespace osu.Game.Overlays { private readonly ChangelogHeader header; private readonly ChangelogBadges badges; - private readonly ChangelogChart chart; + //private readonly ChangelogChart chart; private readonly ChangelogContent listing; private readonly ChangelogContent content; @@ -85,7 +85,7 @@ namespace osu.Game.Overlays { header = new ChangelogHeader(), badges = new ChangelogBadges(), - chart = new ChangelogChart(), + //chart = new ChangelogChart(), listing = new ChangelogContent(), content = new ChangelogContent() }, @@ -162,7 +162,6 @@ namespace osu.Game.Overlays isAtListing = true; var req = new GetChangelogRequest(); badges.SelectNone(); - chart.ShowAllUpdateStreams(); req.Success += listing.ShowListing; api.Queue(req); } @@ -176,7 +175,7 @@ namespace osu.Game.Overlays content.Hide(); listing.Show(); badges.SelectNone(); - chart.ShowAllUpdateStreams(); + //chart.ShowAllUpdateStreams(); listing.Show(); scroll.ScrollTo(savedScrollPosition); } @@ -184,7 +183,12 @@ namespace osu.Game.Overlays /// /// Fetches and shows a specific build from a specific update stream. /// - public void FetchAndShowBuild(APIChangelog build, bool sentByBadges = false) + /// Must contain at least and + /// . If and + /// are specified, the header will instantly display them. + /// Whether to update badges. Should be set to false in case + /// the function is called by selecting a badge, to avoid an infinite loop. + public void FetchAndShowBuild(APIChangelog build, bool updateBadges = true) { var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); @@ -193,17 +197,17 @@ namespace osu.Game.Overlays else req.Success += res => header.ShowBuild(res.UpdateStream.DisplayName, res.DisplayVersion); - if (!sentByBadges) + if (updateBadges) badges.SelectUpdateStream(build.UpdateStream.Name); - chart.ShowUpdateStream(build.UpdateStream.Name); + //chart.ShowUpdateStream(build.UpdateStream.Name); req.Success += apiChangelog => { listing.Hide(); content.Show(); content.ShowBuild(apiChangelog); if (scroll.Current > scroll.GetChildPosInContent(content)) - scroll.ScrollTo(chart); + scroll.ScrollTo(content); if (isAtListing) savedScrollPosition = scroll.Current; isAtListing = false; From 6a5908801403a25db3864730b2fc615c1d44b1bf Mon Sep 17 00:00:00 2001 From: Houtarou Oreki Date: Wed, 22 Aug 2018 13:43:39 +0200 Subject: [PATCH 0104/5608] Move xml docs from ctors onto classes --- osu.Game/Graphics/UserInterface/LineBadge.cs | 10 +++++----- osu.Game/Graphics/UserInterface/TooltipIconButton.cs | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/LineBadge.cs b/osu.Game/Graphics/UserInterface/LineBadge.cs index 0283559aee..aaf225eb4c 100644 --- a/osu.Game/Graphics/UserInterface/LineBadge.cs +++ b/osu.Game/Graphics/UserInterface/LineBadge.cs @@ -6,6 +6,11 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Graphics.UserInterface { + /// + /// A simple rounded expandable line. Set its + /// property to the center of the edge it's meant stick with. By default, + /// takes up the full parent's axis defined by . + /// public class LineBadge : Circle { public float UncollapsedSize; @@ -39,11 +44,6 @@ namespace osu.Game.Graphics.UserInterface } } - /// - /// A simple rounded expandable line. Set its - /// property to the center of the edge it's meant stick with. By default, - /// takes up the full parent's axis defined by . - /// /// Whether to initialize with the /// or the . public LineBadge(bool startCollapsed = true) diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index 19c5421f6a..86fdd32bd2 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -16,6 +16,9 @@ namespace osu.Game.Graphics.UserInterface { // not inheriting osuclickablecontainer/osuhovercontainer // because click/hover sounds cannot be disabled + /// + /// An icon with an action upon click that can be disabled. + /// public class TooltipIconButton : ClickableContainer, IHasTooltip { private readonly SpriteIcon icon; @@ -48,9 +51,6 @@ namespace osu.Game.Graphics.UserInterface set { icon.Icon = value; } } - /// - /// A simple icon that has an action upon click and can be disabled. - /// public TooltipIconButton() { isEnabled = true; From 164a1a8e6e25797493c7ff44154ce90e6e776774 Mon Sep 17 00:00:00 2001 From: Houtarou Oreki Date: Wed, 22 Aug 2018 13:47:09 +0200 Subject: [PATCH 0105/5608] Remove unnecessary inheritance --- osu.Game/Graphics/UserInterface/TooltipIconButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index 86fdd32bd2..ffd7153570 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -19,7 +19,7 @@ namespace osu.Game.Graphics.UserInterface /// /// An icon with an action upon click that can be disabled. /// - public class TooltipIconButton : ClickableContainer, IHasTooltip + public class TooltipIconButton : Container, IHasTooltip { private readonly SpriteIcon icon; private SampleChannel sampleHover; From a817164cb2cf339261f4b86cf339b4b7f159a3af Mon Sep 17 00:00:00 2001 From: Houtarou Oreki Date: Wed, 22 Aug 2018 13:49:08 +0200 Subject: [PATCH 0106/5608] Update comments --- osu.Game/Graphics/UserInterface/LineBadge.cs | 2 +- osu.Game/Graphics/UserInterface/TooltipIconButton.cs | 6 ++---- osu.Game/Overlays/Changelog/ChangelogContentGroup.cs | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/LineBadge.cs b/osu.Game/Graphics/UserInterface/LineBadge.cs index aaf225eb4c..53f057f4b3 100644 --- a/osu.Game/Graphics/UserInterface/LineBadge.cs +++ b/osu.Game/Graphics/UserInterface/LineBadge.cs @@ -20,7 +20,7 @@ namespace osu.Game.Graphics.UserInterface private bool isHorizontal; /// - /// Automatically sets the RelativeSizeAxes and switches X and Y components when changed. + /// Automatically sets the RelativeSizeAxes and switches X and Y size components when changed. /// public bool IsHorizontal { diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index ffd7153570..f26df3f8c1 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -14,8 +14,6 @@ using System; namespace osu.Game.Graphics.UserInterface { - // not inheriting osuclickablecontainer/osuhovercontainer - // because click/hover sounds cannot be disabled /// /// An icon with an action upon click that can be disabled. /// @@ -26,14 +24,14 @@ namespace osu.Game.Graphics.UserInterface private SampleChannel sampleClick; /// - /// The action to fire upon click, if is set to true. + /// The action to fire upon click if is set to true. /// public Action Action; private bool isEnabled; /// - /// If set to true, upon click the will execute. It wont otherwise. + /// If set to true, upon click the will execute. /// public bool IsEnabled { diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 3208f424ce..c349f44d37 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -35,7 +35,6 @@ namespace osu.Game.Overlays.Changelog Padding = new MarginPadding { Horizontal = 70 }; Children = new Drawable[] { - // build version, arrows new FillFlowContainer { Anchor = Anchor.TopCentre, @@ -176,7 +175,7 @@ namespace osu.Game.Overlays.Changelog }, }; - // we may not want double clicks to make it double the work + // we may not want double clicks, // can be clicked again only after a delay clickableBuildText.Action += () => { From b72d44b1e805c5b142bac0543126ffae6df94119 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Wed, 5 Sep 2018 22:54:07 +0200 Subject: [PATCH 0107/5608] Added OsuModDeflate class and adjusted OsuRuleset.cs --- osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs | 44 +++++++++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 5 +++ 2 files changed, 49 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs new file mode 100644 index 0000000000..ec80537a52 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -0,0 +1,44 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using System.Collections.Generic; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModDeflate : Mod, IApplicableToDrawableHitObjects + { + public override string Name => "Deflate"; + public override string ShortenedName => "DF"; + public override FontAwesome Icon => FontAwesome.fa_compress; + public override ModType Type => ModType.Fun; + public override string Description => "Become one with the approach circle..."; + public override double ScoreMultiplier => 1; + + public void ApplyToDrawableHitObjects(IEnumerable drawables) + { + foreach (var drawable in drawables) + drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState; + } + + protected void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state) + { + if (!(drawable is DrawableHitCircle d)) + return; + + d.ApproachCircle.Hide(); + var h = d.HitObject; + + using (d.BeginAbsoluteSequence(h.StartTime - h.TimePreempt)) + { + var origScale = d.Scale; + d.ScaleTo(1.1f); + d.ScaleTo(origScale, h.TimePreempt); + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index fa6e9a018a..461f7188c9 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -117,6 +117,11 @@ namespace osu.Game.Rulesets.Osu new OsuModRelax(), new OsuModAutopilot(), }; + case ModType.Fun: + return new Mod[] + { + new OsuModDeflate(), + }; default: return new Mod[] { }; } From dbc2eb4771f985b9e6e87b0925bf62f897555272 Mon Sep 17 00:00:00 2001 From: Kyle Chang Date: Tue, 18 Sep 2018 23:15:36 -0400 Subject: [PATCH 0108/5608] Create ZoomIn Mod --- osu.Game.Rulesets.Osu/Mods/OsuModZoomIn.cs | 55 ++++++++++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 1 + 2 files changed, 56 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModZoomIn.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModZoomIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModZoomIn.cs new file mode 100644 index 0000000000..b531b9b3d0 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModZoomIn.cs @@ -0,0 +1,55 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using OpenTK; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModZoomIn : Mod, IApplicableToDrawableHitObjects + { + public override string Name => "Zoom In"; + public override string ShortenedName => "ZI"; + public override FontAwesome Icon => FontAwesome.fa_dot_circle_o; + public override ModType Type => ModType.Fun; + public override string Description => "Circles zoom in. No approach circles."; + public override double ScoreMultiplier => 1; + + public void ApplyToDrawableHitObjects(IEnumerable drawables) + { + foreach (var drawable in drawables) + { + drawable.ApplyCustomUpdateState += ApplyBounceState; + } + } + + protected void ApplyBounceState(DrawableHitObject drawable, ArmedState state) + { + if (!(drawable is DrawableOsuHitObject d)) + return; + + var h = (OsuHitObject)drawable.HitObject; + + double appearTime = h.StartTime - h.TimePreempt; + double moveDuration = h.TimePreempt; + + using (drawable.BeginAbsoluteSequence(appearTime, true)) + { + var origScale = drawable.Scale; + + drawable + .ScaleTo(0.0f) + .ScaleTo(origScale, moveDuration, Easing.InOutSine); + } + + // Hide approach circle + (drawable as DrawableHitCircle)?.ApproachCircle.Hide(); + } + } +} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 6736d10dab..029ca7d43e 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -121,6 +121,7 @@ namespace osu.Game.Rulesets.Osu return new Mod[] { new OsuModTransform(), new OsuModWiggle(), + new OsuModZoomIn(), }; default: return new Mod[] { }; From 1e3599bddef4004561454f049b18439c607f93c8 Mon Sep 17 00:00:00 2001 From: Kyle Chang Date: Wed, 19 Sep 2018 23:56:25 -0400 Subject: [PATCH 0109/5608] Disable fade in --- osu.Game.Rulesets.Osu/Mods/OsuModZoomIn.cs | 51 ++++++++++++++++------ 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModZoomIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModZoomIn.cs index b531b9b3d0..8e73ece12c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModZoomIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModZoomIn.cs @@ -2,13 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using OpenTK; namespace osu.Game.Rulesets.Osu.Mods { @@ -31,25 +31,48 @@ namespace osu.Game.Rulesets.Osu.Mods protected void ApplyBounceState(DrawableHitObject drawable, ArmedState state) { - if (!(drawable is DrawableOsuHitObject d)) - return; + if (!(drawable is DrawableOsuHitObject)) return; + if (state != ArmedState.Idle) return; var h = (OsuHitObject)drawable.HitObject; + var appearTime = h.StartTime - h.TimePreempt; + var moveDuration = h.TimePreempt; - double appearTime = h.StartTime - h.TimePreempt; - double moveDuration = h.TimePreempt; - - using (drawable.BeginAbsoluteSequence(appearTime, true)) + switch (drawable) { - var origScale = drawable.Scale; + case DrawableHitCircle circle: + foreach (var t in circle.Transforms.Where(t => t.TargetMember == "Alpha")) + circle.RemoveTransform(t); + using (circle.BeginAbsoluteSequence(appearTime, true)) + { + var origScale = drawable.Scale; - drawable - .ScaleTo(0.0f) - .ScaleTo(origScale, moveDuration, Easing.InOutSine); + circle + .ScaleTo(0) + .ScaleTo(origScale, moveDuration, Easing.OutSine) + .FadeTo(1); + } + + circle.ApproachCircle.Hide(); + + break; + + case DrawableSlider slider: + foreach (var t in slider.Transforms.Where(t => t.TargetMember == "Alpha")) + slider.RemoveTransform(t); + + using (slider.BeginAbsoluteSequence(appearTime, true)) + { + var origScale = slider.Scale; + + slider + .ScaleTo(0) + .ScaleTo(origScale, moveDuration, Easing.OutSine) + .FadeTo(1); + } + + break; } - - // Hide approach circle - (drawable as DrawableHitCircle)?.ApproachCircle.Hide(); } } } From 51d26fb648727a7db020cdd1367dbd86e13209ee Mon Sep 17 00:00:00 2001 From: Kyle Chang Date: Thu, 20 Sep 2018 19:06:37 -0400 Subject: [PATCH 0110/5608] Now spin in mod; circles spin in --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 1 + .../Mods/{OsuModZoomIn.cs => OsuModSpinIn.cs} | 44 +++++++++++++------ osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- 3 files changed, 32 insertions(+), 15 deletions(-) rename osu.Game.Rulesets.Osu/Mods/{OsuModZoomIn.cs => OsuModSpinIn.cs} (54%) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 4eff2a55c8..b3fb1b57a6 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; + public override Type[] IncompatibleMods => new[] { typeof(OsuModSpinIn) }; private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModZoomIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs similarity index 54% rename from osu.Game.Rulesets.Osu/Mods/OsuModZoomIn.cs rename to osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index 8e73ece12c..3bb7d5933c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModZoomIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -1,35 +1,43 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; +using OpenTK; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModZoomIn : Mod, IApplicableToDrawableHitObjects + public class OsuModSpinIn : Mod, IApplicableToDrawableHitObjects { - public override string Name => "Zoom In"; - public override string ShortenedName => "ZI"; - public override FontAwesome Icon => FontAwesome.fa_dot_circle_o; + public override string Name => "Spin In"; + public override string ShortenedName => "SI"; + public override FontAwesome Icon => FontAwesome.fa_rotate_right; public override ModType Type => ModType.Fun; - public override string Description => "Circles zoom in. No approach circles."; + public override string Description => "Circle spin in. No approach circles."; public override double ScoreMultiplier => 1; + public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden) }; + + private const int rotate_offset = 360; + private const float rotate_starting_width = 2.5f; + public void ApplyToDrawableHitObjects(IEnumerable drawables) { foreach (var drawable in drawables) { - drawable.ApplyCustomUpdateState += ApplyBounceState; + drawable.ApplyCustomUpdateState += ApplyZoomState; } } - protected void ApplyBounceState(DrawableHitObject drawable, ArmedState state) + protected void ApplyZoomState(DrawableHitObject drawable, ArmedState state) { if (!(drawable is DrawableOsuHitObject)) return; if (state != ArmedState.Idle) return; @@ -41,15 +49,21 @@ namespace osu.Game.Rulesets.Osu.Mods switch (drawable) { case DrawableHitCircle circle: - foreach (var t in circle.Transforms.Where(t => t.TargetMember == "Alpha")) - circle.RemoveTransform(t); + // Disable Fade + circle.Transforms + .Where(t => t.TargetMember == "Alpha") + .ForEach(t => circle.RemoveTransform(t)); + using (circle.BeginAbsoluteSequence(appearTime, true)) { var origScale = drawable.Scale; + var origRotate = circle.Rotation; circle - .ScaleTo(0) - .ScaleTo(origScale, moveDuration, Easing.OutSine) + .RotateTo(origRotate+rotate_offset) + .RotateTo(origRotate, moveDuration) + .ScaleTo(origScale * new Vector2(rotate_starting_width, 0)) + .ScaleTo(origScale, moveDuration) .FadeTo(1); } @@ -58,8 +72,10 @@ namespace osu.Game.Rulesets.Osu.Mods break; case DrawableSlider slider: - foreach (var t in slider.Transforms.Where(t => t.TargetMember == "Alpha")) - slider.RemoveTransform(t); + // Disable fade + slider.Transforms + .Where(t => t.TargetMember == "Alpha") + .ForEach(t => slider.RemoveTransform(t)); using (slider.BeginAbsoluteSequence(appearTime, true)) { @@ -67,7 +83,7 @@ namespace osu.Game.Rulesets.Osu.Mods slider .ScaleTo(0) - .ScaleTo(origScale, moveDuration, Easing.OutSine) + .ScaleTo(origScale, moveDuration) .FadeTo(1); } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 029ca7d43e..cebd9f1321 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -121,7 +121,7 @@ namespace osu.Game.Rulesets.Osu return new Mod[] { new OsuModTransform(), new OsuModWiggle(), - new OsuModZoomIn(), + new OsuModSpinIn(), }; default: return new Mod[] { }; From 58e989fb9d925b7b1d160f05be813ffbe90c27b1 Mon Sep 17 00:00:00 2001 From: Kyle Chang Date: Thu, 20 Sep 2018 21:08:31 -0400 Subject: [PATCH 0111/5608] Fix judgement backgrounds not appearing properly --- .../Objects/Drawables/DrawableOsuHitObject.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 10cd246172..5503a61b3b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -37,8 +37,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { double transformTime = HitObject.StartTime - HitObject.TimePreempt; - base.ApplyTransformsAt(transformTime, true); - base.ClearTransformsAfter(transformTime, true); + if (state == ArmedState.Idle) + { + base.ApplyTransformsAt(transformTime, true); + base.ClearTransformsAfter(transformTime, true); + } using (BeginAbsoluteSequence(transformTime, true)) { From ece4da0435e988c968bd4d917c7115fc39a2e032 Mon Sep 17 00:00:00 2001 From: Kyle Chang Date: Thu, 20 Sep 2018 23:49:15 -0400 Subject: [PATCH 0112/5608] Revert "Fix judgement backgrounds not appearing properly" This reverts commit 58e989f --- .../Objects/Drawables/DrawableOsuHitObject.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 5503a61b3b..10cd246172 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -37,11 +37,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { double transformTime = HitObject.StartTime - HitObject.TimePreempt; - if (state == ArmedState.Idle) - { - base.ApplyTransformsAt(transformTime, true); - base.ClearTransformsAfter(transformTime, true); - } + base.ApplyTransformsAt(transformTime, true); + base.ClearTransformsAfter(transformTime, true); using (BeginAbsoluteSequence(transformTime, true)) { From bfa430ad8ca04f683bc7ee7363a58660dd16d210 Mon Sep 17 00:00:00 2001 From: Kyle Chang Date: Thu, 20 Sep 2018 23:51:43 -0400 Subject: [PATCH 0113/5608] Fix judgement backgrounds without breaking other things --- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index 3bb7d5933c..e597567336 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override string ShortenedName => "SI"; public override FontAwesome Icon => FontAwesome.fa_rotate_right; public override ModType Type => ModType.Fun; - public override string Description => "Circle spin in. No approach circles."; + public override string Description => "Circles spin in. No approach circles."; public override double ScoreMultiplier => 1; public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden) }; @@ -33,6 +33,7 @@ namespace osu.Game.Rulesets.Osu.Mods { foreach (var drawable in drawables) { + // Need to add custom update in order to disable fade drawable.ApplyCustomUpdateState += ApplyZoomState; } } @@ -43,8 +44,9 @@ namespace osu.Game.Rulesets.Osu.Mods if (state != ArmedState.Idle) return; var h = (OsuHitObject)drawable.HitObject; - var appearTime = h.StartTime - h.TimePreempt; - var moveDuration = h.TimePreempt; + + var appearTime = h.StartTime - h.TimePreempt + 1; + var moveDuration = h.TimePreempt - 1; switch (drawable) { @@ -63,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.Mods .RotateTo(origRotate+rotate_offset) .RotateTo(origRotate, moveDuration) .ScaleTo(origScale * new Vector2(rotate_starting_width, 0)) - .ScaleTo(origScale, moveDuration) + .ScaleTo(origScale, moveDuration, Easing.InQuad) .FadeTo(1); } From 3cb33e53cc7df760a7295a20c74dfddb863cceb3 Mon Sep 17 00:00:00 2001 From: Kyle Chang Date: Fri, 21 Sep 2018 00:07:09 -0400 Subject: [PATCH 0114/5608] Hid approach circles after rewinding replays --- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index e597567336..348093ec9b 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -69,7 +69,10 @@ namespace osu.Game.Rulesets.Osu.Mods .FadeTo(1); } - circle.ApproachCircle.Hide(); + using (circle.ApproachCircle.BeginAbsoluteSequence(appearTime, true)) + { + circle.ApproachCircle.Hide(); + } break; From 51dcfeee9249ad68500fa97940e3d5edbb46aa71 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 25 Aug 2018 21:40:40 +0900 Subject: [PATCH 0115/5608] Move existing tournament resources to new project --- osu.Game.Tournament.Tests/.vscode/launch.json | 31 ++++++++++++ osu.Game.Tournament.Tests/.vscode/tasks.json | 47 +++++++++++++++++++ .../TestCaseDrawings.cs | 31 ++++++------ .../osu.Game.Tournament.Tests.csproj | 16 +++++++ .../Properties/AssemblyInfo.cs | 11 +++++ .../Components/DrawingsConfigManager.cs | 2 +- .../Drawings/Components}/DrawingsTeam.cs | 20 +++++--- .../Screens/Drawings/Components}/Group.cs | 13 +++-- .../Drawings/Components}/GroupContainer.cs | 5 +- .../Screens/Drawings/Components}/ITeamList.cs | 4 +- .../Components}/ScrollingTeamContainer.cs | 23 ++++----- .../Components}/StorageBackedTeamList.cs | 20 +++----- .../Components/VisualiserContainer.cs | 6 +-- .../Screens/Drawings/DrawingsScreen.cs | 20 ++++---- .../osu.Game.Tournament.csproj | 13 +++++ osu.Game/Screens/Menu/MainMenu.cs | 15 ------ osu.Game/Tests/Visual/OsuTestCase.cs | 2 +- osu.sln | 12 +++++ 18 files changed, 202 insertions(+), 89 deletions(-) create mode 100644 osu.Game.Tournament.Tests/.vscode/launch.json create mode 100644 osu.Game.Tournament.Tests/.vscode/tasks.json rename {osu.Game.Tests/Visual => osu.Game.Tournament.Tests}/TestCaseDrawings.cs (76%) create mode 100644 osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj create mode 100644 osu.Game.Tournament/Properties/AssemblyInfo.cs rename {osu.Game/Screens/Tournament => osu.Game.Tournament/Screens/Drawings}/Components/DrawingsConfigManager.cs (92%) rename {osu.Game/Screens/Tournament/Teams => osu.Game.Tournament/Screens/Drawings/Components}/DrawingsTeam.cs (65%) rename {osu.Game/Screens/Tournament => osu.Game.Tournament/Screens/Drawings/Components}/Group.cs (95%) rename {osu.Game/Screens/Tournament => osu.Game.Tournament/Screens/Drawings/Components}/GroupContainer.cs (95%) rename {osu.Game/Screens/Tournament/Teams => osu.Game.Tournament/Screens/Drawings/Components}/ITeamList.cs (68%) rename {osu.Game/Screens/Tournament => osu.Game.Tournament/Screens/Drawings/Components}/ScrollingTeamContainer.cs (94%) rename {osu.Game/Screens/Tournament/Teams => osu.Game.Tournament/Screens/Drawings/Components}/StorageBackedTeamList.cs (73%) rename {osu.Game/Screens/Tournament => osu.Game.Tournament/Screens/Drawings}/Components/VisualiserContainer.cs (98%) rename osu.Game/Screens/Tournament/Drawings.cs => osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs (96%) create mode 100644 osu.Game.Tournament/osu.Game.Tournament.csproj diff --git a/osu.Game.Tournament.Tests/.vscode/launch.json b/osu.Game.Tournament.Tests/.vscode/launch.json new file mode 100644 index 0000000000..0204158347 --- /dev/null +++ b/osu.Game.Tournament.Tests/.vscode/launch.json @@ -0,0 +1,31 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "VisualTests (Debug)", + "type": "coreclr", + "request": "launch", + "program": "dotnet", + "args": [ + "${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Tournament.Tests.dll" + ], + "cwd": "${workspaceRoot}", + "preLaunchTask": "Build (Debug)", + "env": {}, + "console": "internalConsole" + }, + { + "name": "VisualTests (Release)", + "type": "coreclr", + "request": "launch", + "program": "dotnet", + "args": [ + "${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Tournament.Tests.dll" + ], + "cwd": "${workspaceRoot}", + "preLaunchTask": "Build (Release)", + "env": {}, + "console": "internalConsole" + } + ] +} \ No newline at end of file diff --git a/osu.Game.Tournament.Tests/.vscode/tasks.json b/osu.Game.Tournament.Tests/.vscode/tasks.json new file mode 100644 index 0000000000..37f2f32874 --- /dev/null +++ b/osu.Game.Tournament.Tests/.vscode/tasks.json @@ -0,0 +1,47 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Build (Debug)", + "type": "shell", + "command": "dotnet", + "args": [ + "build", + "--no-restore", + "osu.Game.Tournament.Tests.csproj", + "/p:GenerateFullPaths=true", + "/m", + "/verbosity:m" + ], + "group": "build", + "problemMatcher": "$msCompile" + }, + { + "label": "Build (Release)", + "type": "shell", + "command": "dotnet", + "args": [ + "build", + "--no-restore", + "osu.Game.Tournament.Tests.csproj", + "/p:Configuration=Release", + "/p:GenerateFullPaths=true", + "/m", + "/verbosity:m" + ], + "group": "build", + "problemMatcher": "$msCompile" + }, + { + "label": "Restore", + "type": "shell", + "command": "dotnet", + "args": [ + "restore" + ], + "problemMatcher": [] + } + ] +} \ No newline at end of file diff --git a/osu.Game.Tests/Visual/TestCaseDrawings.cs b/osu.Game.Tournament.Tests/TestCaseDrawings.cs similarity index 76% rename from osu.Game.Tests/Visual/TestCaseDrawings.cs rename to osu.Game.Tournament.Tests/TestCaseDrawings.cs index a6a3ef6747..029668df73 100644 --- a/osu.Game.Tests/Visual/TestCaseDrawings.cs +++ b/osu.Game.Tournament.Tests/TestCaseDrawings.cs @@ -2,18 +2,17 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using System.ComponentModel; -using osu.Game.Screens.Tournament; -using osu.Game.Screens.Tournament.Teams; +using osu.Game.Tests.Visual; +using osu.Game.Tournament.Screens.Drawings; +using osu.Game.Tournament.Screens.Drawings.Components; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tournament.Tests { - [Description("for tournament use")] public class TestCaseDrawings : OsuTestCase { public TestCaseDrawings() { - Add(new Drawings + Add(new DrawingsScreen { TeamList = new TestTeamList(), }); @@ -21,57 +20,57 @@ namespace osu.Game.Tests.Visual private class TestTeamList : ITeamList { - public IEnumerable Teams { get; } = new[] + public IEnumerable Teams { get; } = new[] { - new DrawingsTeam + new TournamentTeam { FlagName = "GB", FullName = "United Kingdom", Acronym = "UK" }, - new DrawingsTeam + new TournamentTeam { FlagName = "FR", FullName = "France", Acronym = "FRA" }, - new DrawingsTeam + new TournamentTeam { FlagName = "CN", FullName = "China", Acronym = "CHN" }, - new DrawingsTeam + new TournamentTeam { FlagName = "AU", FullName = "Australia", Acronym = "AUS" }, - new DrawingsTeam + new TournamentTeam { FlagName = "JP", FullName = "Japan", Acronym = "JPN" }, - new DrawingsTeam + new TournamentTeam { FlagName = "RO", FullName = "Romania", Acronym = "ROM" }, - new DrawingsTeam + new TournamentTeam { FlagName = "IT", FullName = "Italy", Acronym = "PIZZA" }, - new DrawingsTeam + new TournamentTeam { FlagName = "VE", FullName = "Venezuela", Acronym = "VNZ" }, - new DrawingsTeam + new TournamentTeam { FlagName = "US", FullName = "United States of America", diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj new file mode 100644 index 0000000000..2b67016f7a --- /dev/null +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -0,0 +1,16 @@ + + + + + + + + + + WinExe + netcoreapp2.1 + + + + + \ No newline at end of file diff --git a/osu.Game.Tournament/Properties/AssemblyInfo.cs b/osu.Game.Tournament/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..4955391097 --- /dev/null +++ b/osu.Game.Tournament/Properties/AssemblyInfo.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Runtime.CompilerServices; + +// We publish our internal attributes to other sub-projects of the framework. +// Note, that we omit visual tests as they are meant to test the framework +// behavior "in the wild". + +[assembly: InternalsVisibleTo("osu.Game.Tournament.Tests")] +[assembly: InternalsVisibleTo("osu.Game.Tournament.Tests.Dynamic")] diff --git a/osu.Game/Screens/Tournament/Components/DrawingsConfigManager.cs b/osu.Game.Tournament/Screens/Drawings/Components/DrawingsConfigManager.cs similarity index 92% rename from osu.Game/Screens/Tournament/Components/DrawingsConfigManager.cs rename to osu.Game.Tournament/Screens/Drawings/Components/DrawingsConfigManager.cs index 49fb39c6da..ac3dbf8a11 100644 --- a/osu.Game/Screens/Tournament/Components/DrawingsConfigManager.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/DrawingsConfigManager.cs @@ -4,7 +4,7 @@ using osu.Framework.Configuration; using osu.Framework.Platform; -namespace osu.Game.Screens.Tournament.Components +namespace osu.Game.Tournament.Screens.Drawings.Components { public class DrawingsConfigManager : IniConfigManager { diff --git a/osu.Game/Screens/Tournament/Teams/DrawingsTeam.cs b/osu.Game.Tournament/Screens/Drawings/Components/DrawingsTeam.cs similarity index 65% rename from osu.Game/Screens/Tournament/Teams/DrawingsTeam.cs rename to osu.Game.Tournament/Screens/Drawings/Components/DrawingsTeam.cs index 0926ed2748..7e182d1b62 100644 --- a/osu.Game/Screens/Tournament/Teams/DrawingsTeam.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/DrawingsTeam.cs @@ -1,23 +1,29 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Screens.Tournament.Teams +namespace osu.Game.Tournament.Screens.Drawings.Components { - public class DrawingsTeam + public class TournamentTeam { /// /// The name of this team. /// public string FullName; - /// - /// Short acronym which appears in the group boxes post-selection. - /// - public string Acronym; - /// /// Name of the file containing the flag. /// public string FlagName; + + private string acronym; + + /// + /// Short acronym which appears in the group boxes post-selection. + /// + public string Acronym + { + get { return acronym ?? FullName.Substring(0, 3); } + set { acronym = value; } + } } } diff --git a/osu.Game/Screens/Tournament/Group.cs b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs similarity index 95% rename from osu.Game/Screens/Tournament/Group.cs rename to osu.Game.Tournament/Screens/Drawings/Components/Group.cs index 6845d8fc48..01f13857fc 100644 --- a/osu.Game/Screens/Tournament/Group.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs @@ -7,15 +7,14 @@ using System.Text; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics.Sprites; using OpenTK; using OpenTK.Graphics; -using osu.Game.Screens.Tournament.Teams; -using osu.Framework.Graphics.Shapes; -namespace osu.Game.Screens.Tournament +namespace osu.Game.Tournament.Screens.Drawings.Components { public class Group : Container { @@ -73,7 +72,7 @@ namespace osu.Game.Screens.Tournament }; } - public void AddTeam(DrawingsTeam team) + public void AddTeam(TournamentTeam team) { GroupTeam gt = new GroupTeam(team); @@ -91,7 +90,7 @@ namespace osu.Game.Screens.Tournament return allTeams.Any(t => t.Team.FullName == fullName); } - public bool RemoveTeam(DrawingsTeam team) + public bool RemoveTeam(TournamentTeam team) { allTeams.RemoveAll(gt => gt.Team == team); @@ -122,12 +121,12 @@ namespace osu.Game.Screens.Tournament private class GroupTeam : Container { - public readonly DrawingsTeam Team; + public readonly TournamentTeam Team; private readonly FillFlowContainer innerContainer; private readonly Sprite flagSprite; - public GroupTeam(DrawingsTeam team) + public GroupTeam(TournamentTeam team) { Team = team; diff --git a/osu.Game/Screens/Tournament/GroupContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs similarity index 95% rename from osu.Game/Screens/Tournament/GroupContainer.cs rename to osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs index c717a7401f..2914d28a00 100644 --- a/osu.Game/Screens/Tournament/GroupContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs @@ -8,9 +8,8 @@ using System.Text; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using OpenTK; -using osu.Game.Screens.Tournament.Teams; -namespace osu.Game.Screens.Tournament +namespace osu.Game.Tournament.Screens.Drawings.Components { public class GroupContainer : Container { @@ -64,7 +63,7 @@ namespace osu.Game.Screens.Tournament } } - public void AddTeam(DrawingsTeam team) + public void AddTeam(TournamentTeam team) { if (groups[currentGroup].TeamsCount == maxTeams) return; diff --git a/osu.Game/Screens/Tournament/Teams/ITeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs similarity index 68% rename from osu.Game/Screens/Tournament/Teams/ITeamList.cs rename to osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs index 728c702173..37b321c85b 100644 --- a/osu.Game/Screens/Tournament/Teams/ITeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs @@ -3,10 +3,10 @@ using System.Collections.Generic; -namespace osu.Game.Screens.Tournament.Teams +namespace osu.Game.Tournament.Screens.Drawings.Components { public interface ITeamList { - IEnumerable Teams { get; } + IEnumerable Teams { get; } } } diff --git a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs similarity index 94% rename from osu.Game/Screens/Tournament/ScrollingTeamContainer.cs rename to osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index d1c7e0fced..ec2e8afcb6 100644 --- a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -13,18 +13,17 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Threading; -using osu.Game.Screens.Tournament.Teams; using OpenTK; using OpenTK.Graphics; -namespace osu.Game.Screens.Tournament +namespace osu.Game.Tournament.Screens.Drawings.Components { public class ScrollingTeamContainer : Container { public event Action OnScrollStarted; - public event Action OnSelected; + public event Action OnSelected; - private readonly List availableTeams = new List(); + private readonly List availableTeams = new List(); private readonly Container tracker; @@ -84,6 +83,7 @@ namespace osu.Game.Screens.Tournament } private ScrollState _scrollState; + private ScrollState scrollState { get { return _scrollState; } @@ -166,7 +166,7 @@ namespace osu.Game.Screens.Tournament } } - public void AddTeam(DrawingsTeam team) + public void AddTeam(TournamentTeam team) { if (availableTeams.Contains(team)) return; @@ -177,12 +177,12 @@ namespace osu.Game.Screens.Tournament scrollState = ScrollState.Idle; } - public void AddTeams(IEnumerable teams) + public void AddTeams(IEnumerable teams) { if (teams == null) return; - foreach (DrawingsTeam t in teams) + foreach (TournamentTeam t in teams) AddTeam(t); } @@ -193,7 +193,7 @@ namespace osu.Game.Screens.Tournament scrollState = ScrollState.Idle; } - public void RemoveTeam(DrawingsTeam team) + public void RemoveTeam(TournamentTeam team) { availableTeams.Remove(team); @@ -278,7 +278,7 @@ namespace osu.Game.Screens.Tournament private void addFlags() { - foreach (DrawingsTeam t in availableTeams) + foreach (TournamentTeam t in availableTeams) { Add(new ScrollingTeam(t) { @@ -320,12 +320,13 @@ namespace osu.Game.Screens.Tournament public const float WIDTH = 58; public const float HEIGHT = 41; - public DrawingsTeam Team; + public TournamentTeam Team; private readonly Sprite flagSprite; private readonly Box outline; private bool selected; + public bool Selected { get { return selected; } @@ -341,7 +342,7 @@ namespace osu.Game.Screens.Tournament } } - public ScrollingTeam(DrawingsTeam team) + public ScrollingTeam(TournamentTeam team) { Team = team; diff --git a/osu.Game/Screens/Tournament/Teams/StorageBackedTeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs similarity index 73% rename from osu.Game/Screens/Tournament/Teams/StorageBackedTeamList.cs rename to osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs index bb112c7e2d..296a23339e 100644 --- a/osu.Game/Screens/Tournament/Teams/StorageBackedTeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs @@ -7,7 +7,7 @@ using System.IO; using osu.Framework.Logging; using osu.Framework.Platform; -namespace osu.Game.Screens.Tournament.Teams +namespace osu.Game.Tournament.Screens.Drawings.Components { public class StorageBackedTeamList : ITeamList { @@ -20,11 +20,11 @@ namespace osu.Game.Screens.Tournament.Teams this.storage = storage; } - public IEnumerable Teams + public IEnumerable Teams { get { - var teams = new List(); + var teams = new List(); try { @@ -47,17 +47,11 @@ namespace osu.Game.Screens.Tournament.Teams continue; } - string flagName = split[0].Trim(); - string teamName = split[1].Trim(); - - string acronym = split.Length >= 3 ? split[2].Trim() : teamName; - acronym = acronym.Substring(0, Math.Min(3, acronym.Length)); - - teams.Add(new DrawingsTeam + teams.Add(new TournamentTeam { - FlagName = flagName, - FullName = teamName, - Acronym = acronym + FlagName = split[0].Trim(), + FullName = split[1].Trim(), + Acronym = split.Length >= 3 ? split[2].Trim() : null }); } } diff --git a/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs similarity index 98% rename from osu.Game/Screens/Tournament/Components/VisualiserContainer.cs rename to osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs index 1453d4e78f..6581dbd328 100644 --- a/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs @@ -1,16 +1,16 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.MathUtils; -using System.Collections.Generic; -using System.Linq; -namespace osu.Game.Screens.Tournament.Components +namespace osu.Game.Tournament.Screens.Drawings.Components { public class VisualiserContainer : Container { diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs similarity index 96% rename from osu.Game/Screens/Tournament/Drawings.cs rename to osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 4e2109afd0..e3853dca6f 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -9,23 +9,23 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Screens; using osu.Game.Screens.Backgrounds; -using osu.Game.Screens.Tournament.Components; -using osu.Game.Screens.Tournament.Teams; +using osu.Game.Tournament.Screens.Drawings.Components; using OpenTK; using OpenTK.Graphics; -using osu.Framework.IO.Stores; -using osu.Framework.Graphics.Shapes; -namespace osu.Game.Screens.Tournament +namespace osu.Game.Tournament.Screens.Drawings { - public class Drawings : OsuScreen + public class DrawingsScreen : OsuScreen { private const string results_filename = "drawings_results.txt"; @@ -37,7 +37,7 @@ namespace osu.Game.Screens.Tournament private GroupContainer groupsContainer; private OsuSpriteText fullTeamNameText; - private readonly List allTeams = new List(); + private readonly List allTeams = new List(); private DrawingsConfigManager drawingsConfig; @@ -253,7 +253,7 @@ namespace osu.Game.Screens.Tournament reset(true); } - private void onTeamSelected(DrawingsTeam team) + private void onTeamSelected(TournamentTeam team) { groupsContainer.AddTeam(team); @@ -290,7 +290,7 @@ namespace osu.Game.Screens.Tournament teamsContainer.ClearTeams(); allTeams.Clear(); - foreach (DrawingsTeam t in TeamList.Teams) + foreach (TournamentTeam t in TeamList.Teams) { if (groupsContainer.ContainsTeam(t.FullName)) continue; @@ -327,7 +327,7 @@ namespace osu.Game.Screens.Tournament continue; // ReSharper disable once AccessToModifiedClosure - DrawingsTeam teamToAdd = allTeams.FirstOrDefault(t => t.FullName == line); + TournamentTeam teamToAdd = allTeams.FirstOrDefault(t => t.FullName == line); if (teamToAdd == null) continue; diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj new file mode 100644 index 0000000000..8adff80820 --- /dev/null +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -0,0 +1,13 @@ + + + + netstandard2.0 + Library + AnyCPU + true + tools for tournaments. + + + + + \ No newline at end of file diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 2dd6e1d7e1..042fa4a07b 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -3,11 +3,8 @@ using OpenTK; using OpenTK.Graphics; -using OpenTK.Input; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Input.EventArgs; -using osu.Framework.Input.States; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -18,7 +15,6 @@ using osu.Game.Screens.Direct; using osu.Game.Screens.Edit; using osu.Game.Screens.Multi; using osu.Game.Screens.Select; -using osu.Game.Screens.Tournament; namespace osu.Game.Screens.Menu { @@ -199,16 +195,5 @@ namespace osu.Game.Screens.Menu Content.FadeOut(3000); return base.OnExiting(next); } - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - if (!args.Repeat && state.Keyboard.ControlPressed && state.Keyboard.ShiftPressed && args.Key == Key.D) - { - Push(new Drawings()); - return true; - } - - return base.OnKeyDown(state, args); - } } } diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index 67a13bd850..dccf852000 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual { beatmap.SetAudioManager(audioManager); - Ruleset.Value = rulesets.AvailableRulesets.First(); + Ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(); } protected override void Dispose(bool isDisposing) diff --git a/osu.sln b/osu.sln index bf1b6d60e1..f6ed7a5c42 100644 --- a/osu.sln +++ b/osu.sln @@ -27,6 +27,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Taiko.Tes EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Osu.Tests", "osu.Game.Rulesets.Osu.Tests\osu.Game.Rulesets.Osu.Tests.csproj", "{6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament", "osu.Game.Tournament\osu.Game.Tournament.csproj", "{5672CA4D-1B37-425B-A118-A8DA26E78938}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament.Tests", "osu.Game.Tournament.Tests\osu.Game.Tournament.Tests.csproj", "{5789E78D-38F9-4072-AB7B-978F34B2C17F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -81,6 +85,14 @@ Global {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|Any CPU.Build.0 = Debug|Any CPU {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|Any CPU.ActiveCfg = Release|Any CPU {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|Any CPU.Build.0 = Release|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|Any CPU.Build.0 = Release|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 40b01ec35a4337bae9c9f662759ab69287179ff4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 Aug 2018 01:14:18 +0900 Subject: [PATCH 0116/5608] Add basic match pairing component for ladder display --- .../TestCaseMatchPairings.cs | 61 +++++++++ .../Ladder/Components/DrawableMatchPairing.cs | 45 ++++++ .../Ladder/Components/DrawableMatchTeam.cs | 129 ++++++++++++++++++ .../Components/DrawableTournamentTeam.cs | 45 ++++++ .../Screens/Ladder/Components/MatchPairing.cs | 31 +++++ 5 files changed, 311 insertions(+) create mode 100644 osu.Game.Tournament.Tests/TestCaseMatchPairings.cs create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentTeam.cs create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs diff --git a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs new file mode 100644 index 0000000000..77cf3c97f1 --- /dev/null +++ b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs @@ -0,0 +1,61 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Tests.Visual; +using osu.Game.Tournament.Screens.Drawings.Components; +using osu.Game.Tournament.Screens.Ladder.Components; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseMatchPairings : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(MatchPairing), + typeof(DrawableMatchPairing), + typeof(DrawableMatchTeam), + typeof(DrawableTournamentTeam), + }; + + public TestCaseMatchPairings() + { + var pairing1 = new MatchPairing( + new TournamentTeam { FlagName = "AU", FullName = "Australia", }, + new TournamentTeam { FlagName = "JP", FullName = "Japan", Acronym = "JPN" }) + { + Team1Score = { Value = 8 }, + Team2Score = { Value = 6 }, + }; + + var pairing2 = new MatchPairing( + new TournamentTeam + { + FlagName = "RO", + FullName = "Romania", + } + ); + + Child = new FillFlowContainer + { + Children = new Drawable[] + { + new DrawableMatchPairing(pairing1), + new DrawableMatchPairing(pairing2), + new DrawableMatchPairing(new MatchPairing()) + } + }; + + AddStep("mark complete", () => pairing1.Completed.Value = true); + AddRepeatStep("change scores", () => pairing1.Team2Score.Value++, 5); + AddStep("mark complete", () => pairing1.Completed.Value = true); + + AddStep("add new team", () => pairing2.Team2.Value = + new TournamentTeam { FlagName = "PT", FullName = "Portugal" } + ); + } + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs new file mode 100644 index 0000000000..281208cdcf --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -0,0 +1,45 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + public class DrawableMatchPairing : CompositeDrawable + { + private readonly MatchPairing pairing; + private readonly FillFlowContainer flow; + + public DrawableMatchPairing(MatchPairing pairing) + { + this.pairing = pairing; + + AutoSizeAxes = Axes.Both; + + Margin = new MarginPadding(5); + + InternalChild = flow = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + }; + + pairing.Team1.BindValueChanged(_ => updateTeams()); + pairing.Team2.BindValueChanged(_ => updateTeams()); + + updateTeams(); + } + + private void updateTeams() + { + // todo: teams may need to be bindable for transitions at a later point. + + flow.Children = new[] + { + new DrawableMatchTeam(pairing.Team1, pairing), + new DrawableMatchTeam(pairing.Team2, pairing) + }; + } + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs new file mode 100644 index 0000000000..9d8ea00e31 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -0,0 +1,129 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Tournament.Screens.Drawings.Components; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + public class DrawableMatchTeam : DrawableTournamentTeam + { + private OsuSpriteText scoreText; + private Box background; + + private readonly Bindable score = new Bindable(); + private readonly BindableBool completed = new BindableBool(); + + private Color4 colourWinner; + private Color4 colourNormal; + + private readonly Func isWinner; + + public DrawableMatchTeam(TournamentTeam team, MatchPairing pairing) + : base(team) + { + Size = new Vector2(150, 40); + + Masking = true; + CornerRadius = 5; + + Flag.Scale = new Vector2(0.9f); + Flag.Anchor = Flag.Origin = Anchor.CentreLeft; + + AcronymText.Anchor = AcronymText.Origin = Anchor.CentreLeft; + AcronymText.Padding = new MarginPadding { Left = 50 }; + AcronymText.TextSize = 24; + + if (pairing != null) + { + completed.BindTo(pairing.Completed); + + if (team == pairing.Team1.Value) + { + score.BindTo(pairing.Team1Score); + isWinner = () => pairing.Team1Score.Value > pairing.Team2Score.Value; + } + else + { + score.BindTo(pairing.Team2Score); + isWinner = () => pairing.Team2Score.Value > pairing.Team1Score.Value; + } + } + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + colourWinner = colours.BlueDarker; + colourNormal = OsuColour.Gray(0.2f); + + InternalChildren = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new Container + { + Padding = new MarginPadding(5), + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + AcronymText, + Flag, + new Container + { + Masking = true, + CornerRadius = 5, + Width = 0.3f, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + Colour = OsuColour.Gray(0.1f), + Alpha = 0.8f, + RelativeSizeAxes = Axes.Both, + }, + scoreText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + TextSize = 20, + } + } + } + } + } + }; + + completed.BindValueChanged(_ => updateWinStyle()); + + score.BindValueChanged(val => + { + scoreText.Text = val?.ToString() ?? string.Empty; + updateWinStyle(); + }, true); + } + + private void updateWinStyle() + { + bool winner = completed && isWinner?.Invoke() == true; + + background.FadeColour(winner ? colourWinner : colourNormal, winner ? 500 : 0, Easing.OutQuint); + + scoreText.Font = AcronymText.Font = winner ? "Exo2.0-Bold" : "Exo2.0-Regular"; + } + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentTeam.cs new file mode 100644 index 0000000000..dc5e2c9007 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentTeam.cs @@ -0,0 +1,45 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics.Sprites; +using osu.Game.Tournament.Screens.Drawings.Components; + +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + public abstract class DrawableTournamentTeam : CompositeDrawable + { + public readonly TournamentTeam Team; + + protected readonly Sprite Flag; + protected readonly OsuSpriteText AcronymText; + + protected DrawableTournamentTeam(TournamentTeam team) + { + Team = team; + + Flag = new Sprite + { + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit + }; + + AcronymText = new OsuSpriteText + { + Text = team?.Acronym.ToUpperInvariant() ?? string.Empty, + Font = @"Exo2.0-Regular" + }; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + if (Team != null) + Flag.Texture = textures.Get($@"Flags/{Team.FlagName}"); + } + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs new file mode 100644 index 0000000000..b8d8b77d74 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -0,0 +1,31 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Configuration; +using osu.Game.Tournament.Screens.Drawings.Components; + +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + /// + /// A collection of two teams competing in a head-to-head match. + /// + public class MatchPairing + { + public Bindable Team1 = new Bindable(); + public Bindable Team1Score = new Bindable(); + + public Bindable Team2 = new Bindable(); + public Bindable Team2Score = new Bindable(); + + public Bindable Completed = new Bindable(); + + public MatchPairing(TournamentTeam team1 = null, TournamentTeam team2 = null) + { + Team1.Value = team1; + Team2.Value = team2; + + Team1Score.ValueChanged += _ => Completed.Value = false; + Team2Score.ValueChanged += _ => Completed.Value = false; + } + } +} From 3d3a7f714dc338b2d5ccf0a2eb55b563d5bb8fed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 Aug 2018 01:24:19 +0900 Subject: [PATCH 0117/5608] Move and use shared components --- osu.Game.Tournament.Tests/TestCaseDrawings.cs | 1 + .../TestCaseMatchPairings.cs | 2 +- .../Components/DrawableTournamentTeam.cs | 3 +- .../TournamentTeam.cs} | 2 +- .../Screens/Drawings/Components/Group.cs | 49 ++++++------------- .../Drawings/Components/GroupContainer.cs | 1 + .../Screens/Drawings/Components/ITeamList.cs | 1 + .../Components/ScrollingTeamContainer.cs | 32 ++++-------- .../Components/StorageBackedTeamList.cs | 1 + .../Screens/Drawings/DrawingsScreen.cs | 1 + .../Ladder/Components/DrawableMatchTeam.cs | 2 +- .../Screens/Ladder/Components/MatchPairing.cs | 2 +- 12 files changed, 35 insertions(+), 62 deletions(-) rename osu.Game.Tournament/{Screens/Ladder => }/Components/DrawableTournamentTeam.cs (91%) rename osu.Game.Tournament/{Screens/Drawings/Components/DrawingsTeam.cs => Components/TournamentTeam.cs} (92%) diff --git a/osu.Game.Tournament.Tests/TestCaseDrawings.cs b/osu.Game.Tournament.Tests/TestCaseDrawings.cs index 029668df73..511724e51a 100644 --- a/osu.Game.Tournament.Tests/TestCaseDrawings.cs +++ b/osu.Game.Tournament.Tests/TestCaseDrawings.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using osu.Game.Tests.Visual; +using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Drawings; using osu.Game.Tournament.Screens.Drawings.Components; diff --git a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs index 77cf3c97f1..d5835896a4 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Tests.Visual; -using osu.Game.Tournament.Screens.Drawings.Components; +using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Tests diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentTeam.cs b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs similarity index 91% rename from osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentTeam.cs rename to osu.Game.Tournament/Components/DrawableTournamentTeam.cs index dc5e2c9007..ec60d24c2c 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentTeam.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs @@ -7,9 +7,8 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics.Sprites; -using osu.Game.Tournament.Screens.Drawings.Components; -namespace osu.Game.Tournament.Screens.Ladder.Components +namespace osu.Game.Tournament.Components { public abstract class DrawableTournamentTeam : CompositeDrawable { diff --git a/osu.Game.Tournament/Screens/Drawings/Components/DrawingsTeam.cs b/osu.Game.Tournament/Components/TournamentTeam.cs similarity index 92% rename from osu.Game.Tournament/Screens/Drawings/Components/DrawingsTeam.cs rename to osu.Game.Tournament/Components/TournamentTeam.cs index 7e182d1b62..03d787af76 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/DrawingsTeam.cs +++ b/osu.Game.Tournament/Components/TournamentTeam.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Tournament.Screens.Drawings.Components +namespace osu.Game.Tournament.Components { public class TournamentTeam { diff --git a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs index 01f13857fc..1600a19be8 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs @@ -4,13 +4,11 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; using osu.Game.Graphics.Sprites; +using osu.Game.Tournament.Components; using OpenTK; using OpenTK.Graphics; @@ -119,21 +117,26 @@ namespace osu.Game.Tournament.Screens.Drawings.Components return sb.ToString(); } - private class GroupTeam : Container + private class GroupTeam : DrawableTournamentTeam { - public readonly TournamentTeam Team; - private readonly FillFlowContainer innerContainer; - private readonly Sprite flagSprite; - public GroupTeam(TournamentTeam team) + public GroupTeam(TournamentTeam team) : base(team) { - Team = team; - Width = 36; AutoSizeAxes = Axes.Y; - Children = new Drawable[] + + Flag.Anchor = Anchor.TopCentre; + Flag.Origin = Anchor.TopCentre; + + AcronymText.Anchor = Anchor.TopCentre; + AcronymText.Origin = Anchor.TopCentre; + AcronymText.Text = team.Acronym.ToUpperInvariant(); + AcronymText.TextSize = 10f; + AcronymText.Font = @"Exo2.0-Bold"; + + InternalChildren = new Drawable[] { innerContainer = new FillFlowContainer { @@ -148,22 +151,8 @@ namespace osu.Game.Tournament.Screens.Drawings.Components Children = new Drawable[] { - flagSprite = new Sprite - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - FillMode = FillMode.Fit - }, - new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - - Text = team.Acronym.ToUpperInvariant(), - TextSize = 10f, - Font = @"Exo2.0-Bold" - } + Flag, + AcronymText } } }; @@ -175,12 +164,6 @@ namespace osu.Game.Tournament.Screens.Drawings.Components innerContainer.ScaleTo(1.5f); innerContainer.ScaleTo(1f, 200); } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - flagSprite.Texture = textures.Get($@"Flags/{Team.FlagName}"); - } } } } diff --git a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs index 2914d28a00..236d19a3ad 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Text; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Tournament.Components; using OpenTK; namespace osu.Game.Tournament.Screens.Drawings.Components diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs index 37b321c85b..614507dc80 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Game.Tournament.Components; namespace osu.Game.Tournament.Screens.Drawings.Components { diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index ec2e8afcb6..816a3ef958 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -5,14 +5,12 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; using osu.Framework.Threading; +using osu.Game.Tournament.Components; using OpenTK; using OpenTK.Graphics; @@ -315,14 +313,11 @@ namespace osu.Game.Tournament.Screens.Drawings.Components Scrolling } - public class ScrollingTeam : Container + public class ScrollingTeam : DrawableTournamentTeam { public const float WIDTH = 58; public const float HEIGHT = 41; - public TournamentTeam Team; - - private readonly Sprite flagSprite; private readonly Box outline; private bool selected; @@ -343,9 +338,8 @@ namespace osu.Game.Tournament.Screens.Drawings.Components } public ScrollingTeam(TournamentTeam team) + : base(team) { - Team = team; - Anchor = Anchor.CentreLeft; Origin = Anchor.CentreLeft; @@ -355,28 +349,20 @@ namespace osu.Game.Tournament.Screens.Drawings.Components Alpha = 0; - Children = new Drawable[] + Flag.Anchor = Anchor.Centre; + Flag.Origin = Anchor.Centre; + Flag.Scale = new Vector2(0.9f); + + InternalChildren = new Drawable[] { outline = new Box { RelativeSizeAxes = Axes.Both, Alpha = 0 }, - flagSprite = new Sprite - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - - Size = new Vector2(WIDTH, HEIGHT) - new Vector2(8) - } + Flag }; } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - flagSprite.Texture = textures.Get($@"Flags/{Team.FlagName}"); - } } } } diff --git a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs index 296a23339e..44ee9d64ca 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using osu.Framework.Logging; using osu.Framework.Platform; +using osu.Game.Tournament.Components; namespace osu.Game.Tournament.Screens.Drawings.Components { diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index e3853dca6f..8e6738d8d6 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -19,6 +19,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Screens; using osu.Game.Screens.Backgrounds; +using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Drawings.Components; using OpenTK; using OpenTK.Graphics; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 9d8ea00e31..1a190b4cc7 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Tournament.Screens.Drawings.Components; +using osu.Game.Tournament.Components; using OpenTK; using OpenTK.Graphics; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index b8d8b77d74..26beb5c598 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; -using osu.Game.Tournament.Screens.Drawings.Components; +using osu.Game.Tournament.Components; namespace osu.Game.Tournament.Screens.Ladder.Components { From 9fbbede027f76880e4649631f189a5c08eb03d8c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 Aug 2018 01:30:33 +0900 Subject: [PATCH 0118/5608] Fix spacing --- .../Screens/Ladder/Components/DrawableMatchPairing.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 281208cdcf..dd98e92ca3 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using OpenTK; namespace osu.Game.Tournament.Screens.Ladder.Components { @@ -23,6 +24,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, + Spacing = new Vector2(2) }; pairing.Team1.BindValueChanged(_ => updateTeams()); From bfc5ccd6d0a39cd3c0ea4898b7c23fa9962fd24c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 Aug 2018 18:37:46 +0900 Subject: [PATCH 0119/5608] Add winners and progressions --- .../TestCaseMatchPairings.cs | 47 ++++++- .../Ladder/Components/DrawableMatchPairing.cs | 117 ++++++++++++++++-- .../Screens/Ladder/Components/MatchPairing.cs | 8 ++ 3 files changed, 158 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs index d5835896a4..a1ab2c7a48 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs @@ -23,6 +23,9 @@ namespace osu.Game.Tournament.Tests public TestCaseMatchPairings() { + FillFlowContainer level1; + FillFlowContainer level2; + var pairing1 = new MatchPairing( new TournamentTeam { FlagName = "AU", FullName = "Australia", }, new TournamentTeam { FlagName = "JP", FullName = "Japan", Acronym = "JPN" }) @@ -41,21 +44,53 @@ namespace osu.Game.Tournament.Tests Child = new FillFlowContainer { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, Children = new Drawable[] { - new DrawableMatchPairing(pairing1), - new DrawableMatchPairing(pairing2), - new DrawableMatchPairing(new MatchPairing()) + level1 = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new[] + { + new DrawableMatchPairing(pairing1), + new DrawableMatchPairing(pairing2), + new DrawableMatchPairing(new MatchPairing()), + } + }, + level2 = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Margin = new MarginPadding(20), + Children = new[] + { + new DrawableMatchPairing(new MatchPairing()), + new DrawableMatchPairing(new MatchPairing()) + } + } } }; + level1.Children[0].Progression = level2.Children[0]; + level1.Children[1].Progression = level2.Children[0]; + AddStep("mark complete", () => pairing1.Completed.Value = true); AddRepeatStep("change scores", () => pairing1.Team2Score.Value++, 5); AddStep("mark complete", () => pairing1.Completed.Value = true); + AddStep("add new team", () => pairing2.Team2.Value = new TournamentTeam { FlagName = "PT", FullName = "Portugal" }); + AddStep("Add progression", () => level1.Children[2].Progression = level2.Children[1]); - AddStep("add new team", () => pairing2.Team2.Value = - new TournamentTeam { FlagName = "PT", FullName = "Portugal" } - ); + AddStep("start match", () => pairing2.ResetScores()); + + AddRepeatStep("change scores", () => pairing2.Team1Score.Value++, 5); + AddStep("mark complete", () => pairing2.Completed.Value = true); + + AddStep("start submatch", () => level2.Children[0].Pairing.ResetScores()); + + AddRepeatStep("change scores", () => level2.Children[0].Pairing.Team1Score.Value++, 5); + AddStep("mark complete", () => level2.Children[0].Pairing.Completed.Value = true); } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index dd98e92ca3..461199327e 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -1,47 +1,148 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Lines; +using osu.Framework.MathUtils; using OpenTK; namespace osu.Game.Tournament.Screens.Ladder.Components { public class DrawableMatchPairing : CompositeDrawable { - private readonly MatchPairing pairing; + public readonly MatchPairing Pairing; private readonly FillFlowContainer flow; + private DrawableMatchPairing progression; + + private readonly Path path; + + public DrawableMatchPairing Progression + { + get => progression; + set + { + if (progression == value) return; + progression = value; + + if (LoadState == LoadState.Loaded) + updateProgression(); + + path.FadeInFromZero(200); + } + } + + private Vector2 progressionStart; + private Vector2 progressionEnd; + + private const float line_width = 2; + + private void updateProgression() + { + if (progression == null) + { + path.Positions = new List(); + return; + } + + Vector2 getCenteredVector(Vector2 top, Vector2 bottom) => new Vector2(top.X, top.Y + (bottom.Y - top.Y) / 2); + + const float padding = 5; + + var start = getCenteredVector(ScreenSpaceDrawQuad.TopRight, ScreenSpaceDrawQuad.BottomRight); + var end = getCenteredVector(progression.ScreenSpaceDrawQuad.TopLeft, progression.ScreenSpaceDrawQuad.BottomLeft); + + bool progressionAbove = progression.ScreenSpaceDrawQuad.TopLeft.Y < ScreenSpaceDrawQuad.TopLeft.Y; + + if (!Precision.AlmostEquals(progressionStart, start) || !Precision.AlmostEquals(progressionEnd, end)) + { + progressionStart = start; + progressionEnd = end; + + path.Origin = progressionAbove ? Anchor.BottomLeft : Anchor.TopLeft; + path.Y = progressionAbove ? line_width : -line_width; + + Vector2 startPosition = path.ToLocalSpace(start) + new Vector2(padding, 0); + Vector2 endPosition = path.ToLocalSpace(end) + new Vector2(-padding, 0); + Vector2 intermediate1 = startPosition + new Vector2(padding, 0); + Vector2 intermediate2 = new Vector2(intermediate1.X, endPosition.Y); + + path.Positions = new List + { + startPosition, + intermediate1, + intermediate2, + endPosition + }; + } + + var destinationForWinner = progressionAbove ? progression.Pairing.Team2 : progression.Pairing.Team1; + + destinationForWinner.Value = Pairing.Winner; + } + public DrawableMatchPairing(MatchPairing pairing) { - this.pairing = pairing; + Pairing = pairing; AutoSizeAxes = Axes.Both; Margin = new MarginPadding(5); - InternalChild = flow = new FillFlowContainer + InternalChildren = new Drawable[] { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(2) + flow = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(2) + }, + path = new Path + { + Alpha = 0, + BypassAutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreRight, + PathWidth = line_width, + }, }; pairing.Team1.BindValueChanged(_ => updateTeams()); pairing.Team2.BindValueChanged(_ => updateTeams()); + pairing.Completed.BindValueChanged(_ => updateProgression()); + updateTeams(); } + protected override void LoadComplete() + { + base.LoadComplete(); + updateTeams(); + } + + protected override void UpdateAfterAutoSize() + { + // required because the lines rely on flow being completed by other elements. + base.UpdateAfterAutoSize(); + updateProgression(); + } + private void updateTeams() { + if (LoadState != LoadState.Loaded) + return; + // todo: teams may need to be bindable for transitions at a later point. flow.Children = new[] { - new DrawableMatchTeam(pairing.Team1, pairing), - new DrawableMatchTeam(pairing.Team2, pairing) + new DrawableMatchTeam(Pairing.Team1, Pairing), + new DrawableMatchTeam(Pairing.Team2, Pairing) }; + + updateProgression(); } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index 26beb5c598..b19b551a04 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -27,5 +27,13 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Team1Score.ValueChanged += _ => Completed.Value = false; Team2Score.ValueChanged += _ => Completed.Value = false; } + + public TournamentTeam Winner => !Completed.Value ? null : (Team1Score.Value > Team2Score.Value ? Team1.Value : Team2.Value); + + public void ResetScores() + { + Team1Score.Value = 0; + Team2Score.Value = 0; + } } } From 041d8263961e746fedf1058227aa1a22c52e348b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 Aug 2018 18:41:21 +0900 Subject: [PATCH 0120/5608] Simplify winner lookup --- .../Screens/Ladder/Components/DrawableMatchTeam.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 1a190b4cc7..1f2447ef06 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -45,18 +45,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components if (pairing != null) { - completed.BindTo(pairing.Completed); + isWinner = () => pairing.Winner == Team; - if (team == pairing.Team1.Value) - { - score.BindTo(pairing.Team1Score); - isWinner = () => pairing.Team1Score.Value > pairing.Team2Score.Value; - } - else - { - score.BindTo(pairing.Team2Score); - isWinner = () => pairing.Team2Score.Value > pairing.Team1Score.Value; - } + completed.BindTo(pairing.Completed); + score.BindTo(team == pairing.Team1.Value ? pairing.Team1Score : pairing.Team2Score); } } From e4ea802c7bf00a5265a821689a9859f9861bc1d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 Aug 2018 19:11:46 +0900 Subject: [PATCH 0121/5608] Add user interaction and stricter change validation rules --- .../TestCaseMatchPairings.cs | 23 ++--- .../Ladder/Components/DrawableMatchPairing.cs | 86 ++++++++++++------- .../Ladder/Components/DrawableMatchTeam.cs | 32 ++++++- .../Screens/Ladder/Components/MatchPairing.cs | 20 ++++- .../Ladder/Components/TournamentConditions.cs | 13 +++ 5 files changed, 129 insertions(+), 45 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/TournamentConditions.cs diff --git a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs index a1ab2c7a48..553e48a822 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs @@ -3,6 +3,8 @@ using System; using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Tests.Visual; @@ -21,6 +23,9 @@ namespace osu.Game.Tournament.Tests typeof(DrawableTournamentTeam), }; + [Cached] + private Bindable conditions = new Bindable(new TournamentConditions { BestOf = 9 }); + public TestCaseMatchPairings() { FillFlowContainer level1; @@ -30,8 +35,8 @@ namespace osu.Game.Tournament.Tests new TournamentTeam { FlagName = "AU", FullName = "Australia", }, new TournamentTeam { FlagName = "JP", FullName = "Japan", Acronym = "JPN" }) { - Team1Score = { Value = 8 }, - Team2Score = { Value = 6 }, + Team1Score = { Value = 4 }, + Team2Score = { Value = 1 }, }; var pairing2 = new MatchPairing( @@ -76,21 +81,19 @@ namespace osu.Game.Tournament.Tests level1.Children[0].Progression = level2.Children[0]; level1.Children[1].Progression = level2.Children[0]; - AddStep("mark complete", () => pairing1.Completed.Value = true); - AddRepeatStep("change scores", () => pairing1.Team2Score.Value++, 5); - AddStep("mark complete", () => pairing1.Completed.Value = true); + AddRepeatStep("change scores", () => pairing1.Team2Score.Value++, 4); AddStep("add new team", () => pairing2.Team2.Value = new TournamentTeam { FlagName = "PT", FullName = "Portugal" }); AddStep("Add progression", () => level1.Children[2].Progression = level2.Children[1]); - AddStep("start match", () => pairing2.ResetScores()); + AddStep("start match", () => pairing2.StartMatch()); - AddRepeatStep("change scores", () => pairing2.Team1Score.Value++, 5); - AddStep("mark complete", () => pairing2.Completed.Value = true); + AddRepeatStep("change scores", () => pairing2.Team1Score.Value++, 10); - AddStep("start submatch", () => level2.Children[0].Pairing.ResetScores()); + AddStep("start submatch", () => level2.Children[0].Pairing.StartMatch()); AddRepeatStep("change scores", () => level2.Children[0].Pairing.Team1Score.Value++, 5); - AddStep("mark complete", () => level2.Children[0].Pairing.Completed.Value = true); + + AddRepeatStep("change scores", () => level2.Children[0].Pairing.Team2Score.Value++, 4); } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 461199327e..7be302be73 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -2,6 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Lines; @@ -14,9 +16,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public readonly MatchPairing Pairing; private readonly FillFlowContainer flow; - private DrawableMatchPairing progression; + private readonly Bindable conditions = new Bindable(); + private readonly Path path; public DrawableMatchPairing Progression @@ -39,6 +42,51 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private const float line_width = 2; + public DrawableMatchPairing(MatchPairing pairing) + { + Pairing = pairing; + + AutoSizeAxes = Axes.Both; + + Margin = new MarginPadding(5); + + InternalChildren = new Drawable[] + { + flow = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(2) + }, + path = new Path + { + Alpha = 0, + BypassAutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreRight, + PathWidth = line_width, + }, + }; + + pairing.Team1.BindValueChanged(_ => updateTeams()); + pairing.Team2.BindValueChanged(_ => updateTeams()); + + pairing.Team1Score.BindValueChanged(_ => updateWinConditions()); + pairing.Team2Score.BindValueChanged(_ => updateWinConditions()); + + pairing.Completed.BindValueChanged(_ => updateProgression()); + + updateTeams(); + } + + [BackgroundDependencyLoader(true)] + private void load(Bindable conditions) + { + this.conditions.BindValueChanged(_ => updateWinConditions()); + + if (conditions != null) + this.conditions.BindTo(conditions); + } + private void updateProgression() { if (progression == null) @@ -83,37 +131,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components destinationForWinner.Value = Pairing.Winner; } - public DrawableMatchPairing(MatchPairing pairing) + private void updateWinConditions() { - Pairing = pairing; + if (conditions.Value == null) return; - AutoSizeAxes = Axes.Both; - - Margin = new MarginPadding(5); - - InternalChildren = new Drawable[] - { - flow = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(2) - }, - path = new Path - { - Alpha = 0, - BypassAutoSizeAxes = Axes.Both, - Anchor = Anchor.CentreRight, - PathWidth = line_width, - }, - }; - - pairing.Team1.BindValueChanged(_ => updateTeams()); - pairing.Team2.BindValueChanged(_ => updateTeams()); - - pairing.Completed.BindValueChanged(_ => updateProgression()); - - updateTeams(); + Pairing.Completed.Value = Pairing.Team1Score.Value + Pairing.Team2Score.Value >= conditions.Value.BestOf; } protected override void LoadComplete() @@ -136,6 +158,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components // todo: teams may need to be bindable for transitions at a later point. + if (Pairing.Team1.Value == null || Pairing.Team2.Value == null) + Pairing.CancelMatchStart(); + flow.Children = new[] { new DrawableMatchTeam(Pairing.Team1, Pairing), @@ -143,6 +168,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components }; updateProgression(); + updateWinConditions(); } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 1f2447ef06..06b400976c 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -7,16 +7,20 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.EventArgs; +using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Tournament.Components; using OpenTK; using OpenTK.Graphics; +using OpenTK.Input; namespace osu.Game.Tournament.Screens.Ladder.Components { public class DrawableMatchTeam : DrawableTournamentTeam { + private readonly MatchPairing pairing; private OsuSpriteText scoreText; private Box background; @@ -31,6 +35,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public DrawableMatchTeam(TournamentTeam team, MatchPairing pairing) : base(team) { + this.pairing = pairing; Size = new Vector2(150, 40); Masking = true; @@ -48,7 +53,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components isWinner = () => pairing.Winner == Team; completed.BindTo(pairing.Completed); - score.BindTo(team == pairing.Team1.Value ? pairing.Team1Score : pairing.Team2Score); + if (team != null) + score.BindTo(team == pairing.Team1.Value ? pairing.Team1Score : pairing.Team2Score); } } @@ -109,6 +115,30 @@ namespace osu.Game.Tournament.Screens.Ladder.Components }, true); } + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + if (Team == null) return true; + + if (args.Button == MouseButton.Left) + { + if (score.Value == null) + { + pairing.StartMatch(); + } + else if (!pairing.Completed) + score.Value++; + } + else + { + if (score.Value > 0) + score.Value--; + else + pairing.CancelMatchStart(); + } + + return true; + } + private void updateWinStyle() { bool winner = completed && isWinner?.Invoke() == true; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index b19b551a04..b615330cc2 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -23,15 +23,27 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { Team1.Value = team1; Team2.Value = team2; - - Team1Score.ValueChanged += _ => Completed.Value = false; - Team2Score.ValueChanged += _ => Completed.Value = false; } public TournamentTeam Winner => !Completed.Value ? null : (Team1Score.Value > Team2Score.Value ? Team1.Value : Team2.Value); - public void ResetScores() + /// + /// Remove scores from the match, in case of a false click or false start. + /// + public void CancelMatchStart() { + Team1Score.Value = null; + Team2Score.Value = null; + } + + /// + /// Initialise this match with zeroed scores. Will be a noop if either team is not present. + /// + public void StartMatch() + { + if (Team1.Value == null || Team2.Value == null) + return; + Team1Score.Value = 0; Team2Score.Value = 0; } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentConditions.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentConditions.cs new file mode 100644 index 0000000000..fd0e8cea87 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentConditions.cs @@ -0,0 +1,13 @@ +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + /// + /// Conditions governing a tournament. + /// + public class TournamentConditions + { + /// + /// How many matches before a winner is decided. + /// + public int BestOf; + } +} From 6e6b6b285ae8fce66c9da2154337f53a410515d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 27 Aug 2018 17:08:00 +0900 Subject: [PATCH 0122/5608] Don't require every-frame update --- .../Screens/Ladder/Components/DrawableMatchPairing.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 7be302be73..8191df6680 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -144,13 +144,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components updateTeams(); } - protected override void UpdateAfterAutoSize() - { - // required because the lines rely on flow being completed by other elements. - base.UpdateAfterAutoSize(); - updateProgression(); - } - private void updateTeams() { if (LoadState != LoadState.Loaded) @@ -167,7 +160,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components new DrawableMatchTeam(Pairing.Team2, Pairing) }; - updateProgression(); + SchedulerAfterChildren.Add(() => Scheduler.Add(updateProgression)); updateWinConditions(); } } From e6baf418fba4bd216ef1801383066f66d2c4cf34 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Sep 2018 01:34:17 +0900 Subject: [PATCH 0123/5608] Add tournament tests rider configuration --- .../runConfigurations/TournamentTests.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .idea/.idea.osu/.idea/runConfigurations/TournamentTests.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/TournamentTests.xml b/.idea/.idea.osu/.idea/runConfigurations/TournamentTests.xml new file mode 100644 index 0000000000..5b425e8582 --- /dev/null +++ b/.idea/.idea.osu/.idea/runConfigurations/TournamentTests.xml @@ -0,0 +1,18 @@ + + + + \ No newline at end of file From 234b04dfc567629da9056ee6925882afd066126d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Sep 2018 04:51:38 +0900 Subject: [PATCH 0124/5608] Add basic ladder manager and state retention --- .../TestCaseLadderManager.cs | 34 +++++++++++++ .../TestCaseMatchPairings.cs | 13 ++--- osu.Game.Tournament.Tests/teams.json | 1 + .../Components/TournamentTeam.cs | 13 ++++- .../Components/StorageBackedTeamList.cs | 1 - .../Ladder/Components/DrawableMatchPairing.cs | 33 +++++++++++- .../Ladder/Components/DrawableMatchTeam.cs | 47 ++++++++++++++--- .../Screens/Ladder/Components/LadderInfo.cs | 9 ++++ .../Ladder/Components/LadderManager.cs | 51 +++++++++++++++++++ .../Screens/Ladder/Components/MatchPairing.cs | 21 ++++++-- 10 files changed, 199 insertions(+), 24 deletions(-) create mode 100644 osu.Game.Tournament.Tests/TestCaseLadderManager.cs create mode 100644 osu.Game.Tournament.Tests/teams.json create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs new file mode 100644 index 0000000000..dc4633aa17 --- /dev/null +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.IO; +using Newtonsoft.Json; +using osu.Framework.Allocation; +using osu.Game.Tests.Visual; +using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Ladder.Components; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseLadderManager : OsuTestCase + { + [Cached] + private readonly LadderManager manager; + + public TestCaseLadderManager() + { + var teams = JsonConvert.DeserializeObject>(File.ReadAllText(@"teams.json")); + var ladder = JsonConvert.DeserializeObject(File.ReadAllText(@"bracket.json")) ?? new LadderInfo(); + + Child = manager = new LadderManager(ladder, teams); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + File.WriteAllText(@"bracket.json", JsonConvert.SerializeObject(manager.Info)); + } + } +} diff --git a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs index 553e48a822..bd6b085b0f 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs @@ -28,8 +28,8 @@ namespace osu.Game.Tournament.Tests public TestCaseMatchPairings() { - FillFlowContainer level1; - FillFlowContainer level2; + Container level1; + Container level2; var pairing1 = new MatchPairing( new TournamentTeam { FlagName = "AU", FullName = "Australia", }, @@ -47,16 +47,14 @@ namespace osu.Game.Tournament.Tests } ); - Child = new FillFlowContainer + Child = new Container { AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, Children = new Drawable[] { - level1 = new FillFlowContainer + level1 = new Container { AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, Children = new[] { new DrawableMatchPairing(pairing1), @@ -64,10 +62,9 @@ namespace osu.Game.Tournament.Tests new DrawableMatchPairing(new MatchPairing()), } }, - level2 = new FillFlowContainer + level2 = new Container { AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, Margin = new MarginPadding(20), Children = new[] { diff --git a/osu.Game.Tournament.Tests/teams.json b/osu.Game.Tournament.Tests/teams.json new file mode 100644 index 0000000000..7df0040469 --- /dev/null +++ b/osu.Game.Tournament.Tests/teams.json @@ -0,0 +1 @@ +[{"Players":[{"id":3632846,"username":"lxLucasxl"},{"id":7110363,"username":"BubShish"},{"id":5748843,"username":"Fisk-"},{"id":4585260,"username":"A b y s s"},{"id":9513273,"username":"VorticalEx"},{"id":7341471,"username":"Bossplays_02"}],"Name":"Argentina","Acronym":"ARG"},{"Players":[{"id":2956184,"username":"Lusty Platypus"},{"id":2145124,"username":"Spartan-"},{"id":4018184,"username":"Rek"},{"id":4247722,"username":"PotassiumF"},{"id":9527845,"username":"AngeLItchysick"},{"id":8832989,"username":"[Crz]Yukikaze-"}],"Name":"Australia","Acronym":"AUS"},{"Players":[{"id":9530019,"username":"Lothus"},{"id":2288363,"username":"SillyFangirl"},{"id":4917435,"username":"FelipeLink"},{"id":5691061,"username":"andreymc"},{"id":4794096,"username":"Shedin"},{"id":3224958,"username":"Lazarento"}],"Name":"Brazil","Acronym":"BRA"},{"Players":[{"id":2747704,"username":"Dawt"},{"id":7025841,"username":"CommandoBlack"},{"id":5390121,"username":"Piggy"},{"id":2198070,"username":"beary605"},{"id":2777647,"username":"Freeflow"},{"id":9675053,"username":"Kiyora"}],"Name":"Canada","Acronym":"CAN"},{"Players":[{"id":5281416,"username":"WalterToro"},{"id":2225008,"username":"Skalim"},{"id":469808,"username":"Sophti"},{"id":4686036,"username":"sebaex"},{"id":4116072,"username":"Arkener"},{"id":4531184,"username":"Raizenn"}],"Name":"Chile","Acronym":"CHL"},{"Players":[{"id":89545,"username":"ZhangFan"},{"id":7215250,"username":"[Crz]Mix0130"},{"id":7961511,"username":"[Crz]Hina"},{"id":7082178,"username":"[Crz]Satori"},{"id":6659363,"username":"Wilben_Chan"},{"id":5270332,"username":"[Crz]Lucifer"}],"Name":"China","Acronym":"CHN"},{"Players":[{"id":2883132,"username":"Jole"},{"id":5001658,"username":"FreakyHands"},{"id":4402263,"username":"mart732c"},{"id":6751666,"username":"tailsdk"},{"id":5352616,"username":"Kainura"},{"id":8969233,"username":"zyglrox"}],"Name":"Denmark","Acronym":"DNK"},{"Players":[{"id":8132964,"username":"Camopoltergeist"},{"id":4789005,"username":"princesswell"},{"id":9663200,"username":"--Vanilla--"},{"id":1982941,"username":"matti644"},{"id":8370443,"username":"Your Daughter"},{"id":8105584,"username":"Twist-X"}],"Name":"Finland","Acronym":"FIN"},{"Players":[{"id":1594604,"username":"Azubeur"},{"id":2284328,"username":"Elementaires"},{"id":3897919,"username":"AntoAa"},{"id":4056690,"username":"Todestrieb"},{"id":7190228,"username":"Cunu"},{"id":3909293,"username":"DemonWaves"}],"Name":"France","Acronym":"FRA"},{"Players":[{"id":4516252,"username":"Malox"},{"id":3357640,"username":"ElectroYan"},{"id":5587671,"username":"-Dom-"},{"id":9764403,"username":"tyro901"},{"id":7009106,"username":"Nediz"},{"id":6232245,"username":"LastExceed"}],"Name":"Germany","Acronym":"GER"},{"Players":[{"id":5417362,"username":"Mooncha"},{"id":2121137,"username":"ng051106"},{"id":4544555,"username":"Opean"},{"id":643394,"username":"Snow Note"}],"Name":"['Hong Kong']","Acronym":"HKG"},{"Players":[{"id":5767941,"username":"RemFangirl"},{"id":4557440,"username":"reyss"},{"id":5492871,"username":"LovelySerenade"},{"id":6045757,"username":"Nixeria-sama"},{"id":5114499,"username":"lombit"},{"id":3497139,"username":"LordBoker-"}],"Name":"Indonesia","Acronym":"IDN"},{"Players":[{"id":3461860,"username":"Yomiel"},{"id":5245132,"username":"BadIsTheNewGod"},{"id":3244389,"username":"Mura7797"},{"id":8889323,"username":"extramen"},{"id":8485394,"username":"Cribob"},{"id":6380163,"username":"CribobFanBoy"}],"Name":"Italy","Acronym":"ITA"},{"Players":[{"id":1824775,"username":"inteliser"},{"id":7540718,"username":"tinpura"},{"id":1847698,"username":"PiraTom"},{"id":10011429,"username":"[ misa ]"},{"id":8679066,"username":"mach_jp"},{"id":10242062,"username":"AMDuskia1996"}],"Name":"Japan","Acronym":"JPN"},{"Players":[{"id":3946113,"username":"idqoos123"},{"id":10543278,"username":"hh27v5Fangirl"},{"id":8566617,"username":"capchon"},{"id":5315736,"username":"my2tic"}],"Name":"Macau","Acronym":"MAC"},{"Players":[{"id":7727987,"username":"Neokje"},{"id":8287005,"username":"[MY]xRay"},{"id":9627666,"username":"Minisora"},{"id":6237337,"username":"watarakisah"},{"id":6363947,"username":"Kiritolow"},{"id":4477497,"username":"cheewee10"}],"Name":"Malaysia","Acronym":"MYS"},{"Players":[{"id":1098581,"username":"mrdawn2"},{"id":9369363,"username":"TheSnooperPS"},{"id":6964358,"username":"Redenor"},{"id":9630674,"username":"Freek"},{"id":2827823,"username":"Boots"},{"id":5183940,"username":"2fast4you98"}],"Name":"Netherlands","Acronym":"NLD"},{"Players":[{"id":86188,"username":"Staiain"},{"id":7676585,"username":"Bizarrely_F4st"},{"id":3494742,"username":"KarlF"},{"id":3750387,"username":"Falniir"},{"id":9000473,"username":"Jesen"},{"id":2764122,"username":"Hjeg"}],"Name":"Norway","Acronym":"NOR"},{"Players":[{"id":914472,"username":"akuma123"},{"id":6114633,"username":"DaZeRo5"},{"id":11885200,"username":"DaKub"},{"id":10218427,"username":"Ovento17"}],"Name":"Peru","Acronym":"PER"},{"Players":[{"id":2039089,"username":"arcwinolivirus"},{"id":4469895,"username":"SurfChu85"},{"id":2471512,"username":"JztCallMeRon"},{"id":9770359,"username":"Toyohime-"},{"id":2722489,"username":"Cielo Day"},{"id":3770641,"username":"Ainyan"}],"Name":"Philippines","Acronym":"PHL"},{"Players":[{"id":743282,"username":"Tidek"},{"id":1654221,"username":"Hudonom"},{"id":6382502,"username":"Kroly-"},{"id":6905790,"username":"Arkitev"},{"id":2235750,"username":"_underjoy"},{"id":3353343,"username":"[-Agonys-]"}],"Name":"Poland","Acronym":"POL"},{"Players":[{"id":9074986,"username":"AngeloLagusa"},{"id":5145890,"username":"Jormungand"},{"id":9847747,"username":"MAZAFUKER1337"},{"id":8035172,"username":"fegasaren"},{"id":7767168,"username":"claer"}],"Name":"['Russian Federation']","Acronym":"RUS"},{"Players":[{"id":7199159,"username":"ByeForNow"},{"id":876528,"username":"Tamaneko"},{"id":8612061,"username":"Polytetral"},{"id":7462804,"username":"Lindyes"},{"id":4574597,"username":"OrienST8"},{"id":9362562,"username":"LuigiClaren"}],"Name":"Singapore","Acronym":"SGP"},{"Players":[{"id":6699923,"username":"SuddenDeath"},{"id":7014697,"username":"Estonians"},{"id":8474029,"username":"wonder5193"},{"id":8283444,"username":"[ Special ]"},{"id":903155,"username":"Nausicaa"},{"id":7945868,"username":"SnowScent"}],"Name":"['South Korea']","Acronym":"KOR"},{"Players":[{"id":3154852,"username":"aitor98"},{"id":8141215,"username":"David5_"},{"id":7935867,"username":"miguel-580"},{"id":6809566,"username":"itsdarious555"},{"id":8497100,"username":"GreenSoul"}],"Name":"Spain","Acronym":"ESP"},{"Players":[{"id":1612580,"username":"Vent"},{"id":6872025,"username":"Couil"},{"id":2229274,"username":"Xytox"},{"id":4899311,"username":"Stug"},{"id":5045509,"username":"YoShiZoRi"},{"id":3918056,"username":"Craty"}],"Name":"Sweden","Acronym":"SWE"},{"Players":[{"id":4952941,"username":"Gamer97"},{"id":8642966,"username":"Adyrem"},{"id":8372292,"username":"doere_"},{"id":9593126,"username":"Monogai"},{"id":3974114,"username":"Haprapra"},{"id":2573716,"username":"Akayro"}],"Name":"Switzerland","Acronym":"CHE"},{"Players":[{"id":766374,"username":"LostCool"},{"id":2838908,"username":"4ksrub"},{"id":6535376,"username":"SharpKunG1412"},{"id":2772110,"username":"BossMadWolf"},{"id":8521723,"username":"MyZterioN-"},{"id":6456531,"username":"-[DaNieL_TH]-"}],"Name":"Thailand","Acronym":"THA"},{"Players":[{"id":2656856,"username":"Sakaki"},{"id":6193819,"username":"SaKuRaLaN"},{"id":1990582,"username":"mspstommy"},{"id":8819232,"username":"Tamamo Desu"},{"id":11531528,"username":"Red MewFew"},{"id":1967808,"username":"luckygino"}],"Name":"Taiwan","Acronym":"TWN"},{"Players":[{"id":3359035,"username":"Amascite"},{"id":4168230,"username":"PikachuNick"},{"id":3617889,"username":"itsjakey"},{"id":3799946,"username":"xSnaggles"},{"id":6814203,"username":"Civilization"},{"id":6701945,"username":"Domblade"}],"Name":"['United Kingdom']","Acronym":"GBR"},{"Players":[{"id":7616811,"username":"TheToaphster"},{"id":2141612,"username":"stupud man"},{"id":7687954,"username":"Neuro-"},{"id":3251373,"username":"-Electro-"},{"id":5610085,"username":"EtienneXC"},{"id":2594280,"username":"Chrubble"}],"Name":"['United States']","Acronym":"USA"},{"Players":[{"id":2243452,"username":"Nakatoru"},{"id":8065567,"username":"Aezlack"},{"id":8301758,"username":"Edvo"},{"id":2140739,"username":"[_Chichinya_]"},{"id":8198818,"username":"[_Gearfrik_]"},{"id":1489811,"username":"_Yisus_"}],"Name":"Venezuela","Acronym":"VEN"}] \ No newline at end of file diff --git a/osu.Game.Tournament/Components/TournamentTeam.cs b/osu.Game.Tournament/Components/TournamentTeam.cs index 03d787af76..14e874e9ef 100644 --- a/osu.Game.Tournament/Components/TournamentTeam.cs +++ b/osu.Game.Tournament/Components/TournamentTeam.cs @@ -1,6 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using osu.Game.Users; + namespace osu.Game.Tournament.Components { public class TournamentTeam @@ -10,10 +13,16 @@ namespace osu.Game.Tournament.Components /// public string FullName; + private string flagName; + /// /// Name of the file containing the flag. /// - public string FlagName; + public string FlagName + { + get { return flagName ?? Acronym.Substring(0, 2); } + set { flagName = value; } + } private string acronym; @@ -25,5 +34,7 @@ namespace osu.Game.Tournament.Components get { return acronym ?? FullName.Substring(0, 3); } set { acronym = value; } } + + public List Players { get; set; } } } diff --git a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs index 44ee9d64ca..625f05edac 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs @@ -50,7 +50,6 @@ namespace osu.Game.Tournament.Screens.Drawings.Components teams.Add(new TournamentTeam { - FlagName = split[0].Trim(), FullName = split[1].Trim(), Acronym = split.Length >= 3 ? split[2].Trim() : null }); diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 8191df6680..62d38a2ee6 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -7,8 +7,12 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Lines; +using osu.Framework.Input.EventArgs; +using osu.Framework.Input.States; using osu.Framework.MathUtils; using OpenTK; +using OpenTK.Input; +using SixLabors.Primitives; namespace osu.Game.Tournament.Screens.Ladder.Components { @@ -46,6 +50,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { Pairing = pairing; + Position = new Vector2(pairing.Position.X, pairing.Position.Y); + AutoSizeAxes = Axes.Both; Margin = new MarginPadding(5); @@ -103,15 +109,19 @@ namespace osu.Game.Tournament.Screens.Ladder.Components var end = getCenteredVector(progression.ScreenSpaceDrawQuad.TopLeft, progression.ScreenSpaceDrawQuad.BottomLeft); bool progressionAbove = progression.ScreenSpaceDrawQuad.TopLeft.Y < ScreenSpaceDrawQuad.TopLeft.Y; + bool progressionToRight = progression.ScreenSpaceDrawQuad.TopLeft.X > ScreenSpaceDrawQuad.TopLeft.X; if (!Precision.AlmostEquals(progressionStart, start) || !Precision.AlmostEquals(progressionEnd, end)) { progressionStart = start; progressionEnd = end; - path.Origin = progressionAbove ? Anchor.BottomLeft : Anchor.TopLeft; + path.Origin = progressionAbove ? Anchor.y2 : Anchor.y0; path.Y = progressionAbove ? line_width : -line_width; + path.Origin |= progressionToRight ? Anchor.x0 : Anchor.x2; + //path.X = progressionToRight ? line_width : -line_width; + Vector2 startPosition = path.ToLocalSpace(start) + new Vector2(padding, 0); Vector2 endPosition = path.ToLocalSpace(end) + new Vector2(-padding, 0); Vector2 intermediate1 = startPosition + new Vector2(padding, 0); @@ -131,6 +141,12 @@ namespace osu.Game.Tournament.Screens.Ladder.Components destinationForWinner.Value = Pairing.Winner; } + protected override void UpdateAfterAutoSize() + { + base.UpdateAfterAutoSize(); + updateProgression(); + } + private void updateWinConditions() { if (conditions.Value == null) return; @@ -163,5 +179,20 @@ namespace osu.Game.Tournament.Screens.Ladder.Components SchedulerAfterChildren.Add(() => Scheduler.Add(updateProgression)); updateWinConditions(); } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => args.Button == MouseButton.Left; + + protected override bool OnDragStart(InputState state) => true; + + protected override bool OnDrag(InputState state) + { + if (base.OnDrag(state)) return true; + + this.MoveToOffset(state.Mouse.Delta); + + var pos = Position; + Pairing.Position = new Point((int)pos.X, (int)pos.Y); + return true; + } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 06b400976c..1077438693 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -2,11 +2,15 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.EventArgs; using osu.Framework.Input.States; using osu.Game.Graphics; @@ -18,8 +22,9 @@ using OpenTK.Input; namespace osu.Game.Tournament.Screens.Ladder.Components { - public class DrawableMatchTeam : DrawableTournamentTeam + public class DrawableMatchTeam : DrawableTournamentTeam, IHasContextMenu { + private readonly Bindable team; private readonly MatchPairing pairing; private OsuSpriteText scoreText; private Box background; @@ -31,10 +36,12 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private Color4 colourNormal; private readonly Func isWinner; + private LadderManager manager; - public DrawableMatchTeam(TournamentTeam team, MatchPairing pairing) + public DrawableMatchTeam(Bindable team, MatchPairing pairing) : base(team) { + this.team = team.GetBoundCopy(); this.pairing = pairing; Size = new Vector2(150, 40); @@ -53,14 +60,16 @@ namespace osu.Game.Tournament.Screens.Ladder.Components isWinner = () => pairing.Winner == Team; completed.BindTo(pairing.Completed); - if (team != null) - score.BindTo(team == pairing.Team1.Value ? pairing.Team1Score : pairing.Team2Score); + if (team.Value != null) + score.BindTo(team.Value == pairing.Team1.Value ? pairing.Team1Score : pairing.Team2Score); } } - [BackgroundDependencyLoader] - private void load(OsuColour colours) + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours, LadderManager manager) { + this.manager = manager; + colourWinner = colours.BlueDarker; colourNormal = OsuColour.Gray(0.2f); @@ -117,7 +126,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - if (Team == null) return true; + if (Team == null) return false; if (args.Button == MouseButton.Left) { @@ -136,7 +145,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components pairing.CancelMatchStart(); } - return true; + return false; } private void updateWinStyle() @@ -147,5 +156,27 @@ namespace osu.Game.Tournament.Screens.Ladder.Components scoreText.Font = AcronymText.Font = winner ? "Exo2.0-Bold" : "Exo2.0-Regular"; } + + public MenuItem[] ContextMenuItems => new[] + { + new MenuItem("Populate team", () => team.Value = manager.Teams.Random()), + }; + } + + internal static class Extensions + { + public static T Random(this IEnumerable enumerable) + { + if (enumerable == null) + { + throw new ArgumentNullException(nameof(enumerable)); + } + + // note: creating a Random instance each call may not be correct for you, + // consider a thread-safe static instance + var r = new Random(); + var list = enumerable as IList ?? enumerable.ToList(); + return list.Count == 0 ? default(T) : list[r.Next(0, list.Count)]; + } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs new file mode 100644 index 0000000000..e65cc7a512 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + public class LadderInfo + { + public List Pairings = new List(); + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs new file mode 100644 index 0000000000..b7764f946f --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.States; +using osu.Game.Graphics.Cursor; +using osu.Game.Tournament.Components; +using SixLabors.Primitives; + +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + public class LadderManager : CompositeDrawable + { + public readonly LadderInfo Info; + public readonly List Teams; + private readonly OsuContextMenuContainer content; + + public LadderManager(LadderInfo info, List teams) + { + Info = info; + Teams = teams; + + RelativeSizeAxes = Axes.Both; + + InternalChild = content = new OsuContextMenuContainer + { + RelativeSizeAxes = Axes.Both + }; + + foreach (var pairing in info.Pairings) + addPairing(pairing); + } + + protected void AddPairing(MatchPairing pairing) + { + Info.Pairings.Add(pairing); + addPairing(pairing); + } + + private void addPairing(MatchPairing pairing) => content.Add(new DrawableMatchPairing(pairing)); + + protected override bool OnClick(InputState state) + { + AddPairing(new MatchPairing + { + Position = new Point((int)state.Mouse.Position.X, (int)state.Mouse.Position.Y) + }); + + return true; + } + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index b615330cc2..d2a8f66cfd 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -1,8 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using Newtonsoft.Json; using osu.Framework.Configuration; using osu.Game.Tournament.Components; +using SixLabors.Primitives; namespace osu.Game.Tournament.Screens.Ladder.Components { @@ -11,13 +13,22 @@ namespace osu.Game.Tournament.Screens.Ladder.Components /// public class MatchPairing { - public Bindable Team1 = new Bindable(); - public Bindable Team1Score = new Bindable(); + public readonly Bindable Team1 = new Bindable(); - public Bindable Team2 = new Bindable(); - public Bindable Team2Score = new Bindable(); + public readonly Bindable Team1Score = new Bindable(); - public Bindable Completed = new Bindable(); + public readonly Bindable Team2 = new Bindable(); + + public readonly Bindable Team2Score = new Bindable(); + + public readonly Bindable Completed = new Bindable(); + + [JsonProperty] + public Point Position; + + public MatchPairing() + { + } public MatchPairing(TournamentTeam team1 = null, TournamentTeam team2 = null) { From ff125f4c71a4f6ee0d8cd746469b3fbb9530bc6d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 15 Sep 2018 22:13:32 +0900 Subject: [PATCH 0125/5608] Reduce noise in json output and handle the case the file doesn't exist --- osu.Game.Tournament.Tests/TestCaseLadderManager.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index dc4633aa17..b61619de12 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tournament.Tests public TestCaseLadderManager() { var teams = JsonConvert.DeserializeObject>(File.ReadAllText(@"teams.json")); - var ladder = JsonConvert.DeserializeObject(File.ReadAllText(@"bracket.json")) ?? new LadderInfo(); + var ladder = File.Exists(@"bracket.json") ? JsonConvert.DeserializeObject(File.ReadAllText(@"bracket.json")) : new LadderInfo(); Child = manager = new LadderManager(ladder, teams); } @@ -28,7 +28,12 @@ namespace osu.Game.Tournament.Tests { base.Dispose(isDisposing); - File.WriteAllText(@"bracket.json", JsonConvert.SerializeObject(manager.Info)); + File.WriteAllText(@"bracket.json", JsonConvert.SerializeObject(manager.Info, + new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore + })); } } } From 74014bec408cd14cb863086469c27f501e14ac2b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 16 Sep 2018 05:35:51 +0900 Subject: [PATCH 0126/5608] wip --- .../TestCaseLadderManager.cs | 6 +- .../TestCaseMatchPairings.cs | 6 +- .../Ladder/Components/DrawableMatchPairing.cs | 87 +---------- .../Ladder/Components/DrawableMatchTeam.cs | 1 + .../Screens/Ladder/Components/LadderInfo.cs | 1 + .../Ladder/Components/LadderManager.cs | 135 ++++++++++++++++-- .../Screens/Ladder/Components/MatchPairing.cs | 8 +- 7 files changed, 148 insertions(+), 96 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index b61619de12..00a5df411f 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using Newtonsoft.Json; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; @@ -16,6 +17,9 @@ namespace osu.Game.Tournament.Tests [Cached] private readonly LadderManager manager; + [Cached] + private Bindable conditions = new Bindable(new TournamentConditions { BestOf = 9 }); + public TestCaseLadderManager() { var teams = JsonConvert.DeserializeObject>(File.ReadAllText(@"teams.json")); @@ -28,7 +32,7 @@ namespace osu.Game.Tournament.Tests { base.Dispose(isDisposing); - File.WriteAllText(@"bracket.json", JsonConvert.SerializeObject(manager.Info, + File.WriteAllText(@"bracket.json", JsonConvert.SerializeObject(manager.CreateInfo(), new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, diff --git a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs index bd6b085b0f..ca2523c898 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs @@ -75,12 +75,12 @@ namespace osu.Game.Tournament.Tests } }; - level1.Children[0].Progression = level2.Children[0]; - level1.Children[1].Progression = level2.Children[0]; + level1.Children[0].Pairing.Progression.Value = level2.Children[0].Pairing; + level1.Children[1].Pairing.Progression.Value = level2.Children[0].Pairing; AddRepeatStep("change scores", () => pairing1.Team2Score.Value++, 4); AddStep("add new team", () => pairing2.Team2.Value = new TournamentTeam { FlagName = "PT", FullName = "Portugal" }); - AddStep("Add progression", () => level1.Children[2].Progression = level2.Children[1]); + AddStep("Add progression", () => level1.Children[2].Pairing.Progression.Value = level2.Children[1].Pairing); AddStep("start match", () => pairing2.StartMatch()); diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 62d38a2ee6..8f33cdcbbc 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -1,15 +1,12 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Lines; using osu.Framework.Input.EventArgs; using osu.Framework.Input.States; -using osu.Framework.MathUtils; using OpenTK; using OpenTK.Input; using SixLabors.Primitives; @@ -20,32 +17,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public readonly MatchPairing Pairing; private readonly FillFlowContainer flow; - private DrawableMatchPairing progression; - private readonly Bindable conditions = new Bindable(); - private readonly Path path; - - public DrawableMatchPairing Progression - { - get => progression; - set - { - if (progression == value) return; - progression = value; - - if (LoadState == LoadState.Loaded) - updateProgression(); - - path.FadeInFromZero(200); - } - } - - private Vector2 progressionStart; - private Vector2 progressionEnd; - - private const float line_width = 2; - public DrawableMatchPairing(MatchPairing pairing) { Pairing = pairing; @@ -63,14 +36,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, Spacing = new Vector2(2) - }, - path = new Path - { - Alpha = 0, - BypassAutoSizeAxes = Axes.Both, - Anchor = Anchor.CentreRight, - PathWidth = line_width, - }, + } }; pairing.Team1.BindValueChanged(_ => updateTeams()); @@ -80,6 +46,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components pairing.Team2Score.BindValueChanged(_ => updateWinConditions()); pairing.Completed.BindValueChanged(_ => updateProgression()); + pairing.Progression.BindValueChanged(_ => updateProgression()); updateTeams(); } @@ -95,58 +62,16 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private void updateProgression() { - if (progression == null) - { - path.Positions = new List(); - return; - } + var progression = Pairing.Progression?.Value; - Vector2 getCenteredVector(Vector2 top, Vector2 bottom) => new Vector2(top.X, top.Y + (bottom.Y - top.Y) / 2); + if (progression == null) return; - const float padding = 5; - - var start = getCenteredVector(ScreenSpaceDrawQuad.TopRight, ScreenSpaceDrawQuad.BottomRight); - var end = getCenteredVector(progression.ScreenSpaceDrawQuad.TopLeft, progression.ScreenSpaceDrawQuad.BottomLeft); - - bool progressionAbove = progression.ScreenSpaceDrawQuad.TopLeft.Y < ScreenSpaceDrawQuad.TopLeft.Y; - bool progressionToRight = progression.ScreenSpaceDrawQuad.TopLeft.X > ScreenSpaceDrawQuad.TopLeft.X; - - if (!Precision.AlmostEquals(progressionStart, start) || !Precision.AlmostEquals(progressionEnd, end)) - { - progressionStart = start; - progressionEnd = end; - - path.Origin = progressionAbove ? Anchor.y2 : Anchor.y0; - path.Y = progressionAbove ? line_width : -line_width; - - path.Origin |= progressionToRight ? Anchor.x0 : Anchor.x2; - //path.X = progressionToRight ? line_width : -line_width; - - Vector2 startPosition = path.ToLocalSpace(start) + new Vector2(padding, 0); - Vector2 endPosition = path.ToLocalSpace(end) + new Vector2(-padding, 0); - Vector2 intermediate1 = startPosition + new Vector2(padding, 0); - Vector2 intermediate2 = new Vector2(intermediate1.X, endPosition.Y); - - path.Positions = new List - { - startPosition, - intermediate1, - intermediate2, - endPosition - }; - } - - var destinationForWinner = progressionAbove ? progression.Pairing.Team2 : progression.Pairing.Team1; + bool progressionAbove = progression.ID < Pairing.ID; + var destinationForWinner = progressionAbove ? progression.Team2 : progression.Team1; destinationForWinner.Value = Pairing.Winner; } - protected override void UpdateAfterAutoSize() - { - base.UpdateAfterAutoSize(); - updateProgression(); - } - private void updateWinConditions() { if (conditions.Value == null) return; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 1077438693..fcfc87e5c3 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -160,6 +160,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public MenuItem[] ContextMenuItems => new[] { new MenuItem("Populate team", () => team.Value = manager.Teams.Random()), + new MenuItem("Join with", () => manager.JoinRequest(pairing)), }; } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs index e65cc7a512..0860966502 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs @@ -5,5 +5,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public class LadderInfo { public List Pairings = new List(); + public List<(int, int)> Progressions = new List<(int, int)>(); } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs index b7764f946f..834df747d0 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs @@ -1,51 +1,166 @@ +using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Lines; using osu.Framework.Input.States; using osu.Game.Graphics.Cursor; using osu.Game.Tournament.Components; +using OpenTK; using SixLabors.Primitives; namespace osu.Game.Tournament.Screens.Ladder.Components { public class LadderManager : CompositeDrawable { - public readonly LadderInfo Info; public readonly List Teams; - private readonly OsuContextMenuContainer content; + private readonly Container pairingsContainer; + private readonly Container paths; public LadderManager(LadderInfo info, List teams) { - Info = info; Teams = teams; RelativeSizeAxes = Axes.Both; - InternalChild = content = new OsuContextMenuContainer + InternalChild = new OsuContextMenuContainer { - RelativeSizeAxes = Axes.Both + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + pairingsContainer = new Container { RelativeSizeAxes = Axes.Both }, + paths = new Container { RelativeSizeAxes = Axes.Both }, + } }; + foreach (var pair in info.Progressions) + info.Pairings.Single(p => p.ID == pair.Item1).Progression.Value = info.Pairings.Single(p => p.ID == pair.Item2); + foreach (var pairing in info.Pairings) addPairing(pairing); } - protected void AddPairing(MatchPairing pairing) + public LadderInfo CreateInfo() { - Info.Pairings.Add(pairing); - addPairing(pairing); + var pairings = pairingsContainer.Select(p => p.Pairing).ToList(); + + return new LadderInfo + { + Pairings = pairings, + Progressions = pairings + .Where(p => p.Progression.Value != null) + .Select(p => (p.ID, p.Progression.Value.ID)) + .ToList() + }; } - private void addPairing(MatchPairing pairing) => content.Add(new DrawableMatchPairing(pairing)); + private void addPairing(MatchPairing pairing) => pairingsContainer.Add(new DrawableMatchPairing(pairing)); protected override bool OnClick(InputState state) { - AddPairing(new MatchPairing + addPairing(new MatchPairing { Position = new Point((int)state.Mouse.Position.X, (int)state.Mouse.Position.Y) }); return true; } + + protected override void Update() + { + base.Update(); + + paths.Clear(); + + int id = 0; + foreach (var pairing in pairingsContainer.OrderBy(d => d.Y).ThenBy(d => d.X)) + { + pairing.Pairing.ID = id++; + + if (pairing.Pairing.Progression.Value != null) + { + var progression = pairingsContainer.Single(p => p.Pairing == pairing.Pairing.Progression.Value); + + const float line_width = 2; + + var path = new Path + { + BypassAutoSizeAxes = Axes.Both, + PathWidth = line_width, + }; + + paths.Add(path); + + Vector2 getCenteredVector(Vector2 top, Vector2 bottom) => new Vector2(top.X, top.Y + (bottom.Y - top.Y) / 2); + + const float padding = 5; + + var start = getCenteredVector(pairing.ScreenSpaceDrawQuad.TopRight, pairing.ScreenSpaceDrawQuad.BottomRight); + var end = getCenteredVector(progression.ScreenSpaceDrawQuad.TopLeft, progression.ScreenSpaceDrawQuad.BottomLeft); + + bool progressionAbove = progression.ScreenSpaceDrawQuad.TopLeft.Y < pairing.ScreenSpaceDrawQuad.TopLeft.Y; + bool progressionToRight = progression.ScreenSpaceDrawQuad.TopLeft.X > pairing.ScreenSpaceDrawQuad.TopLeft.X; + + //if (!Precision.AlmostEquals(progressionStart, start) || !Precision.AlmostEquals(progressionEnd, end)) + { + // var progressionStart = start; + // var progressionEnd = end; + + Vector2 startPosition = path.ToLocalSpace(start) + new Vector2(padding, 0); + Vector2 endPosition = path.ToLocalSpace(end) + new Vector2(-padding, 0); + Vector2 intermediate1 = startPosition + new Vector2(padding, 0); + Vector2 intermediate2 = new Vector2(intermediate1.X, endPosition.Y); + + path.Positions = new List + { + startPosition, + intermediate1, + intermediate2, + endPosition + }; + } + } + } + } + + public void JoinRequest(MatchPairing pairing) + { + AddInternal(new JoinRequestHandler(pairing, handleProgression)); + } + + private bool handleProgression(JoinRequestHandler handler, InputState state) + { + var found = pairingsContainer.FirstOrDefault(d => d.ReceiveMouseInputAt(state.Mouse.NativeState.Position)); + + if (found != null) + { + handler.Source.Progression.Value = found.Pairing; + return true; + } + + return false; + } + + private class JoinRequestHandler : CompositeDrawable + { + public readonly MatchPairing Source; + private readonly Func onClick; + + public JoinRequestHandler(MatchPairing source, Func onClick) + { + Source = source; + this.onClick = onClick; + RelativeSizeAxes = Axes.Both; + } + + protected override bool OnClick(InputState state) + { + if (onClick(this, state)) + Expire(); + + return true; + } + } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index d2a8f66cfd..47a94b854e 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -13,6 +13,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components /// public class MatchPairing { + public int ID; + public readonly Bindable Team1 = new Bindable(); public readonly Bindable Team1Score = new Bindable(); @@ -23,6 +25,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly Bindable Completed = new Bindable(); + [JsonIgnore] + public readonly Bindable Progression = new Bindable(); + [JsonProperty] public Point Position; @@ -36,7 +41,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Team2.Value = team2; } - public TournamentTeam Winner => !Completed.Value ? null : (Team1Score.Value > Team2Score.Value ? Team1.Value : Team2.Value); + [JsonIgnore] + public TournamentTeam Winner => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team1.Value : Team2.Value; /// /// Remove scores from the match, in case of a false click or false start. From c6071f6e4d221351c87afd844a2509977919a20f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Sep 2018 23:47:01 +0900 Subject: [PATCH 0127/5608] Better line drawing --- .../Ladder/Components/LadderManager.cs | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs index 834df747d0..37d2461304 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs @@ -94,32 +94,36 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Vector2 getCenteredVector(Vector2 top, Vector2 bottom) => new Vector2(top.X, top.Y + (bottom.Y - top.Y) / 2); - const float padding = 5; + const float padding = 10; - var start = getCenteredVector(pairing.ScreenSpaceDrawQuad.TopRight, pairing.ScreenSpaceDrawQuad.BottomRight); - var end = getCenteredVector(progression.ScreenSpaceDrawQuad.TopLeft, progression.ScreenSpaceDrawQuad.BottomLeft); + var q1 = pairing.ScreenSpaceDrawQuad; + var q2 = progression.ScreenSpaceDrawQuad; - bool progressionAbove = progression.ScreenSpaceDrawQuad.TopLeft.Y < pairing.ScreenSpaceDrawQuad.TopLeft.Y; - bool progressionToRight = progression.ScreenSpaceDrawQuad.TopLeft.X > pairing.ScreenSpaceDrawQuad.TopLeft.X; + bool progressionToRight = q2.TopLeft.X > q1.TopLeft.X; - //if (!Precision.AlmostEquals(progressionStart, start) || !Precision.AlmostEquals(progressionEnd, end)) + if (!progressionToRight) { - // var progressionStart = start; - // var progressionEnd = end; - - Vector2 startPosition = path.ToLocalSpace(start) + new Vector2(padding, 0); - Vector2 endPosition = path.ToLocalSpace(end) + new Vector2(-padding, 0); - Vector2 intermediate1 = startPosition + new Vector2(padding, 0); - Vector2 intermediate2 = new Vector2(intermediate1.X, endPosition.Y); - - path.Positions = new List - { - startPosition, - intermediate1, - intermediate2, - endPosition - }; + var temp = q2; + q2 = q1; + q1 = temp; } + + var c1 = getCenteredVector(q1.TopRight, q1.BottomRight) + new Vector2(padding, 0); + var c2 = getCenteredVector(q2.TopLeft, q2.BottomLeft) - new Vector2(padding, 0); + + var p1 = c1; + var p2 = p1 + new Vector2(padding, 0); + + if (p2.X > c2.X) + { + c2 = getCenteredVector(q2.TopRight, q2.BottomRight) + new Vector2(padding, 0); + p2.X = c2.X + padding; + } + + var p3 = new Vector2(p2.X, c2.Y); + var p4 = new Vector2(c2.X, p3.Y); + + path.Positions = new[] { p1, p2, p3, p4 }.Select(p => path.ToLocalSpace(p)).ToList(); } } } From 1de82afd169c7a30048727d5a65a05bad2e9e1dc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Sep 2018 02:00:16 +0900 Subject: [PATCH 0128/5608] Betterify pairing request logic --- .../Ladder/Components/LadderManager.cs | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs index 37d2461304..3e8d2649eb 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; @@ -130,40 +129,33 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public void JoinRequest(MatchPairing pairing) { - AddInternal(new JoinRequestHandler(pairing, handleProgression)); - } - - private bool handleProgression(JoinRequestHandler handler, InputState state) - { - var found = pairingsContainer.FirstOrDefault(d => d.ReceiveMouseInputAt(state.Mouse.NativeState.Position)); - - if (found != null) - { - handler.Source.Progression.Value = found.Pairing; - return true; - } - - return false; + AddInternal(new JoinRequestHandler(pairingsContainer, pairing)); } private class JoinRequestHandler : CompositeDrawable { + private readonly Container pairingsContainer; public readonly MatchPairing Source; - private readonly Func onClick; - public JoinRequestHandler(MatchPairing source, Func onClick) + public JoinRequestHandler(Container pairingsContainer, MatchPairing source) { + this.pairingsContainer = pairingsContainer; Source = source; - this.onClick = onClick; RelativeSizeAxes = Axes.Both; } protected override bool OnClick(InputState state) { - if (onClick(this, state)) - Expire(); + var found = pairingsContainer.FirstOrDefault(d => d.ReceiveMouseInputAt(state.Mouse.NativeState.Position)); - return true; + if (found != null) + { + Source.Progression.Value = found.Pairing; + Expire(); + return true; + } + + return false; } } } From ffadd5dfd0c0635ab60727a249dcf17a41f395fd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Sep 2018 18:51:37 +0900 Subject: [PATCH 0129/5608] Improve join request visual guide --- .../TestCaseLadderManager.cs | 1 + .../Ladder/Components/ProgressionPath.cs | 59 +++++++++++++ .../Ladder/{Components => }/LadderManager.cs | 84 +++++++------------ 3 files changed, 90 insertions(+), 54 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs rename osu.Game.Tournament/Screens/Ladder/{Components => }/LadderManager.cs (62%) diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index 00a5df411f..9544a5c17e 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Tests diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs new file mode 100644 index 0000000000..c44f67a171 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs @@ -0,0 +1,59 @@ +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Lines; +using OpenTK; + +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + public class ProgressionPath : Path + { + public DrawableMatchPairing Source { get; private set; } + public DrawableMatchPairing Destination { get; private set; } + + public ProgressionPath(DrawableMatchPairing source, DrawableMatchPairing destination) + { + Source = source; + Destination = destination; + + PathWidth = 2; + BypassAutoSizeAxes = Axes.Both; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Vector2 getCenteredVector(Vector2 top, Vector2 bottom) => new Vector2(top.X, top.Y + (bottom.Y - top.Y) / 2); + + const float padding = 10; + + var q1 = Source.ScreenSpaceDrawQuad; + var q2 = Destination.ScreenSpaceDrawQuad; + + bool progressionToRight = q2.TopLeft.X > q1.TopLeft.X; + + if (!progressionToRight) + { + var temp = q2; + q2 = q1; + q1 = temp; + } + + var c1 = getCenteredVector(q1.TopRight, q1.BottomRight) + new Vector2(padding, 0); + var c2 = getCenteredVector(q2.TopLeft, q2.BottomLeft) - new Vector2(padding, 0); + + var p1 = c1; + var p2 = p1 + new Vector2(padding, 0); + + if (p2.X > c2.X) + { + c2 = getCenteredVector(q2.TopRight, q2.BottomRight) + new Vector2(padding, 0); + p2.X = c2.X + padding; + } + + var p3 = new Vector2(p2.X, c2.Y); + var p4 = new Vector2(c2.X, p3.Y); + + Positions = new[] { p1, p2, p3, p4 }.Select(ToLocalSpace).ToList(); + } + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs similarity index 62% rename from osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs rename to osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 3e8d2649eb..bf66447224 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -6,10 +6,10 @@ using osu.Framework.Graphics.Lines; using osu.Framework.Input.States; using osu.Game.Graphics.Cursor; using osu.Game.Tournament.Components; -using OpenTK; +using osu.Game.Tournament.Screens.Ladder.Components; using SixLabors.Primitives; -namespace osu.Game.Tournament.Screens.Ladder.Components +namespace osu.Game.Tournament.Screens.Ladder { public class LadderManager : CompositeDrawable { @@ -78,75 +78,51 @@ namespace osu.Game.Tournament.Screens.Ladder.Components pairing.Pairing.ID = id++; if (pairing.Pairing.Progression.Value != null) - { - var progression = pairingsContainer.Single(p => p.Pairing == pairing.Pairing.Progression.Value); - - const float line_width = 2; - - var path = new Path - { - BypassAutoSizeAxes = Axes.Both, - PathWidth = line_width, - }; - - paths.Add(path); - - Vector2 getCenteredVector(Vector2 top, Vector2 bottom) => new Vector2(top.X, top.Y + (bottom.Y - top.Y) / 2); - - const float padding = 10; - - var q1 = pairing.ScreenSpaceDrawQuad; - var q2 = progression.ScreenSpaceDrawQuad; - - bool progressionToRight = q2.TopLeft.X > q1.TopLeft.X; - - if (!progressionToRight) - { - var temp = q2; - q2 = q1; - q1 = temp; - } - - var c1 = getCenteredVector(q1.TopRight, q1.BottomRight) + new Vector2(padding, 0); - var c2 = getCenteredVector(q2.TopLeft, q2.BottomLeft) - new Vector2(padding, 0); - - var p1 = c1; - var p2 = p1 + new Vector2(padding, 0); - - if (p2.X > c2.X) - { - c2 = getCenteredVector(q2.TopRight, q2.BottomRight) + new Vector2(padding, 0); - p2.X = c2.X + padding; - } - - var p3 = new Vector2(p2.X, c2.Y); - var p4 = new Vector2(c2.X, p3.Y); - - path.Positions = new[] { p1, p2, p3, p4 }.Select(p => path.ToLocalSpace(p)).ToList(); - } + paths.Add(new ProgressionPath(pairing, pairingsContainer.Single(p => p.Pairing == pairing.Pairing.Progression.Value))); } } - public void JoinRequest(MatchPairing pairing) - { - AddInternal(new JoinRequestHandler(pairingsContainer, pairing)); - } + public void JoinRequest(MatchPairing pairing) => AddInternal(new JoinRequestHandler(pairingsContainer, pairing)); private class JoinRequestHandler : CompositeDrawable { private readonly Container pairingsContainer; public readonly MatchPairing Source; + private ProgressionPath path; + public JoinRequestHandler(Container pairingsContainer, MatchPairing source) { this.pairingsContainer = pairingsContainer; - Source = source; RelativeSizeAxes = Axes.Both; + + Source = source; + Source.Progression.Value = null; + } + + private DrawableMatchPairing findTarget(InputState state) => pairingsContainer.FirstOrDefault(d => d.ReceiveMouseInputAt(state.Mouse.NativeState.Position)); + + protected override bool OnMouseMove(InputState state) + { + var found = findTarget(state); + + if (found == path?.Destination) + return false; + + path?.Expire(); + path = null; + + if (found == null) + return false; + + AddInternal(path = new ProgressionPath(pairingsContainer.First(c => c.Pairing == Source), found) { Alpha = 0.4f }); + + return base.OnMouseMove(state); } protected override bool OnClick(InputState state) { - var found = pairingsContainer.FirstOrDefault(d => d.ReceiveMouseInputAt(state.Mouse.NativeState.Position)); + var found = findTarget(state); if (found != null) { From 0076ef34476e2099f96e6365254a4211c3f8eb80 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Sep 2018 18:52:00 +0900 Subject: [PATCH 0130/5608] Fix layout in MatchPairing test case --- .../TestCaseMatchPairings.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs index ca2523c898..f1116b2db7 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs @@ -47,14 +47,16 @@ namespace osu.Game.Tournament.Tests } ); - Child = new Container + Child = new FillFlowContainer { - AutoSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, Children = new Drawable[] { - level1 = new Container + level1 = new FillFlowContainer { - AutoSizeAxes = Axes.Both, + AutoSizeAxes = Axes.X, + Direction = FillDirection.Vertical, Children = new[] { new DrawableMatchPairing(pairing1), @@ -62,9 +64,10 @@ namespace osu.Game.Tournament.Tests new DrawableMatchPairing(new MatchPairing()), } }, - level2 = new Container + level2 = new FillFlowContainer { - AutoSizeAxes = Axes.Both, + AutoSizeAxes = Axes.X, + Direction = FillDirection.Vertical, Margin = new MarginPadding(20), Children = new[] { From f2f4e964c569cb7d3ca02f49896f3b0a1bb6fa30 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Sep 2018 19:58:47 +0900 Subject: [PATCH 0131/5608] Add deletion support --- .../TestCaseLadderManager.cs | 8 +++++- .../Ladder/Components/DrawableMatchPairing.cs | 9 ++++++ .../Ladder/Components/DrawableMatchTeam.cs | 8 ++++-- .../Screens/Ladder/Components/MatchPairing.cs | 15 ++++++++++ .../Screens/Ladder/LadderManager.cs | 28 +++++++++++-------- 5 files changed, 52 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index 9544a5c17e..b53660c703 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -6,6 +6,8 @@ using System.IO; using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Game.Graphics.Cursor; using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder; @@ -26,7 +28,11 @@ namespace osu.Game.Tournament.Tests var teams = JsonConvert.DeserializeObject>(File.ReadAllText(@"teams.json")); var ladder = File.Exists(@"bracket.json") ? JsonConvert.DeserializeObject(File.ReadAllText(@"bracket.json")) : new LadderInfo(); - Child = manager = new LadderManager(ladder, teams); + Child = new OsuContextMenuContainer + { + RelativeSizeAxes = Axes.Both, + Child = manager = new LadderManager(ladder, teams) + }; } protected override void Dispose(bool isDisposing) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 8f33cdcbbc..131959892c 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -119,5 +119,14 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Pairing.Position = new Point((int)pos.X, (int)pos.Y); return true; } + + public void Remove() + { + if (Pairing.ProgressionSource.Value != null) + Pairing.ProgressionSource.Value.Progression.Value = null; + + Pairing.Progression.Value = null; + Expire(); + } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index fcfc87e5c3..e74545f073 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -15,6 +15,7 @@ using osu.Framework.Input.EventArgs; using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using OpenTK; using OpenTK.Graphics; @@ -157,10 +158,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components scoreText.Font = AcronymText.Font = winner ? "Exo2.0-Bold" : "Exo2.0-Regular"; } - public MenuItem[] ContextMenuItems => new[] + public MenuItem[] ContextMenuItems => new MenuItem[] { - new MenuItem("Populate team", () => team.Value = manager.Teams.Random()), - new MenuItem("Join with", () => manager.JoinRequest(pairing)), + new OsuMenuItem("Populate team", MenuItemType.Standard, () => team.Value = manager.Teams.Random()), + new OsuMenuItem("Join with", MenuItemType.Standard, () => manager.RequestJoin(pairing)), + new OsuMenuItem("Remove", MenuItemType.Destructive, () => manager.Remove(pairing)), }; } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index 47a94b854e..c0ca25e220 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -28,11 +28,26 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [JsonIgnore] public readonly Bindable Progression = new Bindable(); + [JsonIgnore] + public readonly Bindable ProgressionSource = new Bindable(); + [JsonProperty] public Point Position; + private MatchPairing lastProgression; // todo: fix if we ever get LastValue inside Bindable<>. + public MatchPairing() { + Progression.ValueChanged += progression => + { + if (lastProgression != null) + lastProgression.ProgressionSource.Value = null; + + if (progression != null) + progression.ProgressionSource.Value = this; + + lastProgression = progression; + }; } public MatchPairing(TournamentTeam team1 = null, TournamentTeam team2 = null) diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index bf66447224..807b5f05a9 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -2,16 +2,18 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Lines; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.States; -using osu.Game.Graphics.Cursor; +using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; using SixLabors.Primitives; namespace osu.Game.Tournament.Screens.Ladder { - public class LadderManager : CompositeDrawable + public class LadderManager : CompositeDrawable, IHasContextMenu { public readonly List Teams; private readonly Container pairingsContainer; @@ -23,7 +25,7 @@ namespace osu.Game.Tournament.Screens.Ladder RelativeSizeAxes = Axes.Both; - InternalChild = new OsuContextMenuContainer + InternalChild = new Container { RelativeSizeAxes = Axes.Both, Children = new Drawable[] @@ -56,15 +58,14 @@ namespace osu.Game.Tournament.Screens.Ladder private void addPairing(MatchPairing pairing) => pairingsContainer.Add(new DrawableMatchPairing(pairing)); - protected override bool OnClick(InputState state) + public MenuItem[] ContextMenuItems => new MenuItem[] { - addPairing(new MatchPairing + new OsuMenuItem("Create new match", MenuItemType.Highlighted, () => { - Position = new Point((int)state.Mouse.Position.X, (int)state.Mouse.Position.Y) - }); - - return true; - } + var pos = ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position); + addPairing(new MatchPairing { Position = new Point((int)pos.X, (int)pos.Y) }); + }), + }; protected override void Update() { @@ -82,7 +83,7 @@ namespace osu.Game.Tournament.Screens.Ladder } } - public void JoinRequest(MatchPairing pairing) => AddInternal(new JoinRequestHandler(pairingsContainer, pairing)); + public void RequestJoin(MatchPairing pairing) => AddInternal(new JoinRequestHandler(pairingsContainer, pairing)); private class JoinRequestHandler : CompositeDrawable { @@ -126,7 +127,8 @@ namespace osu.Game.Tournament.Screens.Ladder if (found != null) { - Source.Progression.Value = found.Pairing; + if (found.Pairing != Source) + Source.Progression.Value = found.Pairing; Expire(); return true; } @@ -134,5 +136,7 @@ namespace osu.Game.Tournament.Screens.Ladder return false; } } + + public void Remove(MatchPairing pairing) => pairingsContainer.FirstOrDefault(p => p.Pairing == pairing)?.Remove(); } } From cddc7f74d4b41920c172df124fb9d2e5c0f3f218 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Sep 2018 22:07:03 +0900 Subject: [PATCH 0132/5608] Fix the possibility of a double-direction progression bind --- .../Screens/Ladder/Components/MatchPairing.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index c0ca25e220..994486ffdd 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -41,13 +41,22 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Progression.ValueChanged += progression => { if (lastProgression != null) + // clear the source from the previous progression. lastProgression.ProgressionSource.Value = null; if (progression != null) + // set the source on the new progression. progression.ProgressionSource.Value = this; lastProgression = progression; }; + + ProgressionSource.ValueChanged += source => + { + if (source != null) + // ennsure no two-way progressions. + Progression.Value = null; + }; } public MatchPairing(TournamentTeam team1 = null, TournamentTeam team2 = null) From 36e151719744f33efba1f22ab355884a20e9fe23 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Sep 2018 22:24:21 +0900 Subject: [PATCH 0133/5608] Display paths underneath matches --- osu.Game.Tournament/Screens/Ladder/LadderManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 807b5f05a9..e57f9b739b 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -30,8 +30,8 @@ namespace osu.Game.Tournament.Screens.Ladder RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - pairingsContainer = new Container { RelativeSizeAxes = Axes.Both }, paths = new Container { RelativeSizeAxes = Axes.Both }, + pairingsContainer = new Container { RelativeSizeAxes = Axes.Both }, } }; From 2f2dcec8c765d4c359e804fc0687ddb9671347b0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Sep 2018 05:52:25 +0900 Subject: [PATCH 0134/5608] Complete editing support --- .../TestCaseLadderManager.cs | 2 +- .../TestCaseMatchPairings.cs | 2 +- .../Components/DrawableTournamentTeam.cs | 2 +- .../Components/TournamentTeam.cs | 6 +- .../Ladder/Components/DrawableMatchPairing.cs | 86 +++++++++- .../Ladder/Components/DrawableMatchTeam.cs | 25 ++- .../Ladder/Components/LadderSettings.cs | 147 ++++++++++++++++++ .../Screens/Ladder/Components/MatchPairing.cs | 26 +--- .../Ladder/Components/TournamentConditions.cs | 4 - .../Screens/Ladder/LadderManager.cs | 62 ++++++-- osu.Game/Overlays/Settings/SettingsItem.cs | 2 + 11 files changed, 306 insertions(+), 58 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index b53660c703..ac56803c90 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tournament.Tests private readonly LadderManager manager; [Cached] - private Bindable conditions = new Bindable(new TournamentConditions { BestOf = 9 }); + private Bindable conditions = new Bindable(new TournamentConditions()); public TestCaseLadderManager() { diff --git a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs index f1116b2db7..dc67807c64 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tournament.Tests }; [Cached] - private Bindable conditions = new Bindable(new TournamentConditions { BestOf = 9 }); + private Bindable conditions = new Bindable(new TournamentConditions()); public TestCaseMatchPairings() { diff --git a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs index ec60d24c2c..016db57773 100644 --- a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tournament.Components AcronymText = new OsuSpriteText { - Text = team?.Acronym.ToUpperInvariant() ?? string.Empty, + Text = team?.Acronym?.ToUpperInvariant() ?? string.Empty, Font = @"Exo2.0-Regular" }; } diff --git a/osu.Game.Tournament/Components/TournamentTeam.cs b/osu.Game.Tournament/Components/TournamentTeam.cs index 14e874e9ef..cb6fc9fb92 100644 --- a/osu.Game.Tournament/Components/TournamentTeam.cs +++ b/osu.Game.Tournament/Components/TournamentTeam.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tournament.Components /// public string FlagName { - get { return flagName ?? Acronym.Substring(0, 2); } + get { return flagName ?? Acronym?.Substring(0, 2); } set { flagName = value; } } @@ -31,10 +31,12 @@ namespace osu.Game.Tournament.Components /// public string Acronym { - get { return acronym ?? FullName.Substring(0, 3); } + get { return acronym ?? FullName?.Substring(0, 3); } set { acronym = value; } } public List Players { get; set; } + + public override string ToString() => FullName ?? Acronym; } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 131959892c..f6771d70b4 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -5,9 +5,11 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Input.EventArgs; using osu.Framework.Input.States; using OpenTK; +using OpenTK.Graphics; using OpenTK.Input; using SixLabors.Primitives; @@ -18,6 +20,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly MatchPairing Pairing; private readonly FillFlowContainer flow; private readonly Bindable conditions = new Bindable(); + private readonly Drawable selectionBox; + private Bindable globalSelection; + + [Resolved(CanBeNull = true)] + private LadderEditorInfo editorInfo { get; set; } = null; public DrawableMatchPairing(MatchPairing pairing) { @@ -29,8 +36,20 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Margin = new MarginPadding(5); - InternalChildren = new Drawable[] + InternalChildren = new[] { + selectionBox = new Container + { + CornerRadius = 5, + Masking = true, + Scale = new Vector2(1.05f), + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Alpha = 0, + Colour = Color4.YellowGreen, + Child = new Box { RelativeSizeAxes = Axes.Both } + }, flow = new FillFlowContainer { AutoSizeAxes = Axes.Both, @@ -38,13 +57,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Spacing = new Vector2(2) } }; - pairing.Team1.BindValueChanged(_ => updateTeams()); pairing.Team2.BindValueChanged(_ => updateTeams()); - pairing.Team1Score.BindValueChanged(_ => updateWinConditions()); pairing.Team2Score.BindValueChanged(_ => updateWinConditions()); - + pairing.BestOf.BindValueChanged(_ => updateWinConditions()); pairing.Completed.BindValueChanged(_ => updateProgression()); pairing.Progression.BindValueChanged(_ => updateProgression()); @@ -60,6 +77,27 @@ namespace osu.Game.Tournament.Screens.Ladder.Components this.conditions.BindTo(conditions); } + private bool selected; + + public bool Selected + { + get => selected; + + set + { + if (value == selected) return; + selected = value; + + if (selected) + { + selectionBox.Show(); + editorInfo.Selected.Value = Pairing; + } + else + selectionBox.Hide(); + } + } + private void updateProgression() { var progression = Pairing.Progression?.Value; @@ -76,13 +114,22 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { if (conditions.Value == null) return; - Pairing.Completed.Value = Pairing.Team1Score.Value + Pairing.Team2Score.Value >= conditions.Value.BestOf; + Pairing.Completed.Value = Pairing.Team1Score.Value + Pairing.Team2Score.Value >= Pairing.BestOf.Value; } protected override void LoadComplete() { base.LoadComplete(); updateTeams(); + + if (editorInfo != null) + { + globalSelection = editorInfo.Selected.GetBoundCopy(); + globalSelection.BindValueChanged(s => + { + if (s != Pairing) Selected = false; + }); + } } private void updateTeams() @@ -109,10 +156,34 @@ namespace osu.Game.Tournament.Screens.Ladder.Components protected override bool OnDragStart(InputState state) => true; + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (Selected && editorInfo.EditingEnabled && args.Key == Key.Delete) + { + Remove(); + return true; + } + + return base.OnKeyDown(state, args); + } + + protected override bool OnClick(InputState state) + { + if (!editorInfo.EditingEnabled) + return false; + + Selected = true; + return true; + } + protected override bool OnDrag(InputState state) { if (base.OnDrag(state)) return true; + if (!editorInfo.EditingEnabled) + return false; + + Selected = true; this.MoveToOffset(state.Mouse.Delta); var pos = Position; @@ -122,10 +193,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public void Remove() { - if (Pairing.ProgressionSource.Value != null) - Pairing.ProgressionSource.Value.Progression.Value = null; - + Selected = false; Pairing.Progression.Value = null; + Expire(); } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index e74545f073..a517c5f475 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -25,7 +25,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public class DrawableMatchTeam : DrawableTournamentTeam, IHasContextMenu { - private readonly Bindable team; private readonly MatchPairing pairing; private OsuSpriteText scoreText; private Box background; @@ -39,10 +38,12 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private readonly Func isWinner; private LadderManager manager; + [Resolved(CanBeNull = true)] + private LadderEditorInfo editorInfo { get; set; } = null; + public DrawableMatchTeam(Bindable team, MatchPairing pairing) : base(team) { - this.team = team.GetBoundCopy(); this.pairing = pairing; Size = new Vector2(150, 40); @@ -127,7 +128,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - if (Team == null) return false; + if (Team == null || editorInfo.EditingEnabled) return false; if (args.Button == MouseButton.Left) { @@ -158,12 +159,20 @@ namespace osu.Game.Tournament.Screens.Ladder.Components scoreText.Font = AcronymText.Font = winner ? "Exo2.0-Bold" : "Exo2.0-Regular"; } - public MenuItem[] ContextMenuItems => new MenuItem[] + public MenuItem[] ContextMenuItems { - new OsuMenuItem("Populate team", MenuItemType.Standard, () => team.Value = manager.Teams.Random()), - new OsuMenuItem("Join with", MenuItemType.Standard, () => manager.RequestJoin(pairing)), - new OsuMenuItem("Remove", MenuItemType.Destructive, () => manager.Remove(pairing)), - }; + get + { + if (!editorInfo.EditingEnabled) + return new MenuItem[0]; + + return new MenuItem[] + { + new OsuMenuItem("Join with", MenuItemType.Standard, () => manager.RequestJoin(pairing)), + new OsuMenuItem("Remove", MenuItemType.Destructive, () => manager.Remove(pairing)), + }; + } + } } internal static class Extensions diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs new file mode 100644 index 0000000000..9ef2ccfa0b --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs @@ -0,0 +1,147 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.Settings; +using osu.Game.Screens.Play.PlayerSettings; +using osu.Game.Tournament.Components; + +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + public class LadderEditorSettings : PlayerSettingsGroup + { + private const int padding = 10; + + protected override string Title => @"ladder"; + + private PlayerSliderBar sliderBestOf; + + private SettingsDropdown dropdownTeam1; + private SettingsDropdown dropdownTeam2; + + [Resolved] + private LadderEditorInfo editorInfo { get; set; } = null; + + [BackgroundDependencyLoader] + private void load() + { + var teamEntries = editorInfo.Teams.Select(t => new KeyValuePair(t.ToString(), t)).Prepend(new KeyValuePair("Empty", new TournamentTeam())); + + Children = new Drawable[] + { + new PlayerCheckbox + { + Bindable = editorInfo.EditingEnabled, + LabelText = "Enable editing" + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = padding }, + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = "Team1", + }, + }, + }, + dropdownTeam1 = new SettingsDropdown + { + Items = teamEntries, + Bindable = new Bindable + { + Value = teamEntries.First().Value, + Default = teamEntries.First().Value + } + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = padding }, + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = "Team2", + }, + }, + }, + dropdownTeam2 = new SettingsDropdown + { + Items = teamEntries, + Bindable = new Bindable + { + Value = teamEntries.First().Value, + Default = teamEntries.First().Value + } + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = padding }, + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = "Best of", + }, + }, + }, + sliderBestOf = new PlayerSliderBar + { + Bindable = new BindableDouble + { + Default = 5, + Value = 5, + MinValue = 1, + MaxValue = 20, + Precision = 1, + }, + } + }; + + editorInfo.Selected.ValueChanged += selection => + { + dropdownTeam1.Bindable.Value = dropdownTeam1.Items.FirstOrDefault(i => i.Value.Acronym == selection?.Team1.Value?.Acronym).Value; + dropdownTeam2.Bindable.Value = dropdownTeam1.Items.FirstOrDefault(i => i.Value.Acronym == selection?.Team2.Value?.Acronym).Value; + sliderBestOf.Bindable.Value = selection?.BestOf ?? sliderBestOf.Bindable.Default; + }; + + dropdownTeam1.Bindable.ValueChanged += val => + { + if (editorInfo.Selected.Value != null) editorInfo.Selected.Value.Team1.Value = val.Acronym == null ? null : val; + }; + + dropdownTeam2.Bindable.ValueChanged += val => + { + if (editorInfo.Selected.Value != null) editorInfo.Selected.Value.Team2.Value = val.Acronym == null ? null : val; + }; + + sliderBestOf.Bindable.ValueChanged += val => + { + if (editorInfo.Selected.Value != null) editorInfo.Selected.Value.BestOf.Value = (int)val; + }; + + editorInfo.EditingEnabled.ValueChanged += enabled => + { + if (!enabled) editorInfo.Selected.Value = null; + }; + } + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index 994486ffdd..772a196f37 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -25,38 +25,16 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly Bindable Completed = new Bindable(); - [JsonIgnore] - public readonly Bindable Progression = new Bindable(); + public readonly BindableInt BestOf = new BindableInt(5); [JsonIgnore] - public readonly Bindable ProgressionSource = new Bindable(); + public readonly Bindable Progression = new Bindable(); [JsonProperty] public Point Position; - private MatchPairing lastProgression; // todo: fix if we ever get LastValue inside Bindable<>. - public MatchPairing() { - Progression.ValueChanged += progression => - { - if (lastProgression != null) - // clear the source from the previous progression. - lastProgression.ProgressionSource.Value = null; - - if (progression != null) - // set the source on the new progression. - progression.ProgressionSource.Value = this; - - lastProgression = progression; - }; - - ProgressionSource.ValueChanged += source => - { - if (source != null) - // ennsure no two-way progressions. - Progression.Value = null; - }; } public MatchPairing(TournamentTeam team1 = null, TournamentTeam team2 = null) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentConditions.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentConditions.cs index fd0e8cea87..045149945c 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentConditions.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentConditions.cs @@ -5,9 +5,5 @@ namespace osu.Game.Tournament.Screens.Ladder.Components /// public class TournamentConditions { - /// - /// How many matches before a winner is decided. - /// - public int BestOf; } } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index e57f9b739b..6c14a4225f 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -1,5 +1,8 @@ +using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -13,15 +16,25 @@ using SixLabors.Primitives; namespace osu.Game.Tournament.Screens.Ladder { + public class LadderEditorInfo + { + public readonly BindableBool EditingEnabled = new BindableBool(); + public List Teams = new List(); + public readonly Bindable Selected = new Bindable(); + } + public class LadderManager : CompositeDrawable, IHasContextMenu { public readonly List Teams; private readonly Container pairingsContainer; private readonly Container paths; + [Cached] + private readonly LadderEditorInfo editorInfo = new LadderEditorInfo(); + public LadderManager(LadderInfo info, List teams) { - Teams = teams; + editorInfo.Teams = Teams = teams; RelativeSizeAxes = Axes.Both; @@ -32,11 +45,25 @@ namespace osu.Game.Tournament.Screens.Ladder { paths = new Container { RelativeSizeAxes = Axes.Both }, pairingsContainer = new Container { RelativeSizeAxes = Axes.Both }, + new LadderEditorSettings + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Margin = new MarginPadding(5) + } } }; foreach (var pair in info.Progressions) - info.Pairings.Single(p => p.ID == pair.Item1).Progression.Value = info.Pairings.Single(p => p.ID == pair.Item2); + { + var src = info.Pairings.FirstOrDefault(p => p.ID == pair.Item1); + var dest = info.Pairings.FirstOrDefault(p => p.ID == pair.Item2); + + if (src == null) throw new InvalidOperationException(); + + if (dest != null) + src.Progression.Value = dest; + } foreach (var pairing in info.Pairings) addPairing(pairing); @@ -58,14 +85,23 @@ namespace osu.Game.Tournament.Screens.Ladder private void addPairing(MatchPairing pairing) => pairingsContainer.Add(new DrawableMatchPairing(pairing)); - public MenuItem[] ContextMenuItems => new MenuItem[] + public MenuItem[] ContextMenuItems { - new OsuMenuItem("Create new match", MenuItemType.Highlighted, () => + get { - var pos = ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position); - addPairing(new MatchPairing { Position = new Point((int)pos.X, (int)pos.Y) }); - }), - }; + if (!editorInfo.EditingEnabled) + return new MenuItem[0]; + + return new MenuItem[] + { + new OsuMenuItem("Create new match", MenuItemType.Highlighted, () => + { + var pos = ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position); + addPairing(new MatchPairing { Position = new Point((int)pos.X, (int)pos.Y) }); + }), + }; + } + } protected override void Update() { @@ -79,7 +115,15 @@ namespace osu.Game.Tournament.Screens.Ladder pairing.Pairing.ID = id++; if (pairing.Pairing.Progression.Value != null) - paths.Add(new ProgressionPath(pairing, pairingsContainer.Single(p => p.Pairing == pairing.Pairing.Progression.Value))); + { + var dest = pairingsContainer.FirstOrDefault(p => p.Pairing == pairing.Pairing.Progression.Value); + + if (dest == null) + // clean up outdated progressions. + pairing.Pairing.Progression.Value = null; + else + paths.Add(new ProgressionPath(pairing, dest)); + } } } diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 0f8d3aa2ac..88c3971ab2 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -63,8 +63,10 @@ namespace osu.Game.Overlays.Settings set { + controlWithCurrent?.Current.UnbindBindings(); bindable = value; controlWithCurrent?.Current.BindTo(bindable); + if (ShowsDefaultIndicator) { restoreDefaultButton.Bindable = bindable.GetBoundCopy(); From a113cf41183d2bead8c5a95a5f685d7ac8ffce4c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Sep 2018 06:36:45 +0900 Subject: [PATCH 0135/5608] Start IDs at 1 --- osu.Game.Tournament/Screens/Ladder/LadderManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 6c14a4225f..235ac4a86a 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -109,7 +109,7 @@ namespace osu.Game.Tournament.Screens.Ladder paths.Clear(); - int id = 0; + int id = 1; foreach (var pairing in pairingsContainer.OrderBy(d => d.Y).ThenBy(d => d.X)) { pairing.Pairing.ID = id++; From 3cc75bac3443ac43cab7b62868c5397a2081784d Mon Sep 17 00:00:00 2001 From: Kyle Chang Date: Fri, 21 Sep 2018 20:26:01 -0400 Subject: [PATCH 0136/5608] Adjust easings --- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index 348093ec9b..102275043c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden) }; private const int rotate_offset = 360; - private const float rotate_starting_width = 2.5f; + private const float rotate_starting_width = 2.0f; public void ApplyToDrawableHitObjects(IEnumerable drawables) @@ -63,9 +63,9 @@ namespace osu.Game.Rulesets.Osu.Mods circle .RotateTo(origRotate+rotate_offset) - .RotateTo(origRotate, moveDuration) + .RotateTo(origRotate, moveDuration, Easing.InOutSine) .ScaleTo(origScale * new Vector2(rotate_starting_width, 0)) - .ScaleTo(origScale, moveDuration, Easing.InQuad) + .ScaleTo(origScale, moveDuration, Easing.InOutSine) .FadeTo(1); } @@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Osu.Mods slider .ScaleTo(0) - .ScaleTo(origScale, moveDuration) + .ScaleTo(origScale, moveDuration, Easing.InOutSine) .FadeTo(1); } From 8d773fec97e681cf2895d7324f13a5f4ce0cb447 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 24 Sep 2018 02:16:59 +0900 Subject: [PATCH 0137/5608] Fix incorrect best-of- scoring method --- .../Screens/Ladder/Components/DrawableMatchPairing.cs | 4 +++- osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index f6771d70b4..7f8956c24d 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -114,7 +114,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { if (conditions.Value == null) return; - Pairing.Completed.Value = Pairing.Team1Score.Value + Pairing.Team2Score.Value >= Pairing.BestOf.Value; + var instaWinAmount = Pairing.BestOf.Value / 2; + + Pairing.Completed.Value = Pairing.Team1Score + Pairing.Team2Score >= Pairing.BestOf || Pairing.Team1Score > instaWinAmount || Pairing.Team2Score > instaWinAmount; } protected override void LoadComplete() diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index 772a196f37..c47e3ea440 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly Bindable Completed = new Bindable(); - public readonly BindableInt BestOf = new BindableInt(5); + public readonly BindableInt BestOf = new BindableInt(11); [JsonIgnore] public readonly Bindable Progression = new Bindable(); From a3a2a149ca87464d1163f5396c570df69051d193 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 24 Sep 2018 02:17:07 +0900 Subject: [PATCH 0138/5608] Use textbox rather than dropdowns --- .../Ladder/Components/LadderSettings.cs | 50 +++++++------------ 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs index 9ef2ccfa0b..a2275784a0 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs @@ -1,16 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Overlays.Settings; +using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play.PlayerSettings; -using osu.Game.Tournament.Components; namespace osu.Game.Tournament.Screens.Ladder.Components { @@ -22,8 +20,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private PlayerSliderBar sliderBestOf; - private SettingsDropdown dropdownTeam1; - private SettingsDropdown dropdownTeam2; + private OsuTextBox textboxTeam1; + private OsuTextBox textboxTeam2; [Resolved] private LadderEditorInfo editorInfo { get; set; } = null; @@ -31,7 +29,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [BackgroundDependencyLoader] private void load() { - var teamEntries = editorInfo.Teams.Select(t => new KeyValuePair(t.ToString(), t)).Prepend(new KeyValuePair("Empty", new TournamentTeam())); + var teamEntries = editorInfo.Teams; Children = new Drawable[] { @@ -55,15 +53,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components }, }, }, - dropdownTeam1 = new SettingsDropdown - { - Items = teamEntries, - Bindable = new Bindable - { - Value = teamEntries.First().Value, - Default = teamEntries.First().Value - } - }, + textboxTeam1 = new OsuTextBox { RelativeSizeAxes = Axes.X, Height = 20 }, new Container { RelativeSizeAxes = Axes.X, @@ -79,15 +69,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components }, }, }, - dropdownTeam2 = new SettingsDropdown - { - Items = teamEntries, - Bindable = new Bindable - { - Value = teamEntries.First().Value, - Default = teamEntries.First().Value - } - }, + textboxTeam2 = new OsuTextBox { RelativeSizeAxes = Axes.X, Height = 20 }, new Container { RelativeSizeAxes = Axes.X, @@ -107,10 +89,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { Bindable = new BindableDouble { - Default = 5, - Value = 5, + Default = 11, + Value = 11, MinValue = 1, - MaxValue = 20, + MaxValue = 21, Precision = 1, }, } @@ -118,19 +100,21 @@ namespace osu.Game.Tournament.Screens.Ladder.Components editorInfo.Selected.ValueChanged += selection => { - dropdownTeam1.Bindable.Value = dropdownTeam1.Items.FirstOrDefault(i => i.Value.Acronym == selection?.Team1.Value?.Acronym).Value; - dropdownTeam2.Bindable.Value = dropdownTeam1.Items.FirstOrDefault(i => i.Value.Acronym == selection?.Team2.Value?.Acronym).Value; + textboxTeam1.Text = selection?.Team1.Value?.Acronym; + textboxTeam2.Text = selection?.Team2.Value?.Acronym; sliderBestOf.Bindable.Value = selection?.BestOf ?? sliderBestOf.Bindable.Default; }; - dropdownTeam1.Bindable.ValueChanged += val => + textboxTeam1.OnCommit = (val, newText) => { - if (editorInfo.Selected.Value != null) editorInfo.Selected.Value.Team1.Value = val.Acronym == null ? null : val; + if (newText && editorInfo.Selected.Value != null) + editorInfo.Selected.Value.Team1.Value = teamEntries.FirstOrDefault(t => t.Acronym == val.Text); }; - dropdownTeam2.Bindable.ValueChanged += val => + textboxTeam2.OnCommit = (val, newText) => { - if (editorInfo.Selected.Value != null) editorInfo.Selected.Value.Team2.Value = val.Acronym == null ? null : val; + if (newText && editorInfo.Selected.Value != null) + editorInfo.Selected.Value.Team2.Value = teamEntries.FirstOrDefault(t => t.Acronym == val.Text); }; sliderBestOf.Bindable.ValueChanged += val => From 68cef7646848fb9e3bacae79bf72e7fd1ff11a8c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 24 Sep 2018 05:19:03 +0900 Subject: [PATCH 0139/5608] Add grouping and move BestOf out of pairing --- .../Ladder/Components/DrawableMatchPairing.cs | 8 +-- .../Screens/Ladder/Components/LadderInfo.cs | 4 ++ .../Ladder/Components/LadderSettings.cs | 64 +++++++++---------- .../Screens/Ladder/Components/MatchPairing.cs | 2 +- .../Ladder/Components/TournamentGrouping.cs | 15 +++++ 5 files changed, 54 insertions(+), 39 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 7f8956c24d..a7ebbfa8b3 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -61,7 +61,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components pairing.Team2.BindValueChanged(_ => updateTeams()); pairing.Team1Score.BindValueChanged(_ => updateWinConditions()); pairing.Team2Score.BindValueChanged(_ => updateWinConditions()); - pairing.BestOf.BindValueChanged(_ => updateWinConditions()); + pairing.Grouping.BindValueChanged(_ => updateWinConditions()); pairing.Completed.BindValueChanged(_ => updateProgression()); pairing.Progression.BindValueChanged(_ => updateProgression()); @@ -112,11 +112,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private void updateWinConditions() { - if (conditions.Value == null) return; + if (conditions.Value == null || Pairing.Grouping.Value == null) return; - var instaWinAmount = Pairing.BestOf.Value / 2; + var instaWinAmount = Pairing.Grouping.Value.BestOf / 2; - Pairing.Completed.Value = Pairing.Team1Score + Pairing.Team2Score >= Pairing.BestOf || Pairing.Team1Score > instaWinAmount || Pairing.Team2Score > instaWinAmount; + Pairing.Completed.Value = Pairing.Grouping.Value.BestOf > 0 && (Pairing.Team1Score + Pairing.Team2Score >= Pairing.Grouping.Value.BestOf || Pairing.Team1Score > instaWinAmount || Pairing.Team2Score > instaWinAmount); } protected override void LoadComplete() diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs index 0860966502..e1da676f22 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using System.Collections.Generic; namespace osu.Game.Tournament.Screens.Ladder.Components @@ -6,5 +9,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public List Pairings = new List(); public List<(int, int)> Progressions = new List<(int, int)>(); + public List Groupings = new List(); } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs index a2275784a0..7532cee0f0 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs @@ -3,7 +3,6 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -18,8 +17,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components protected override string Title => @"ladder"; - private PlayerSliderBar sliderBestOf; - private OsuTextBox textboxTeam1; private OsuTextBox textboxTeam2; @@ -70,39 +67,38 @@ namespace osu.Game.Tournament.Screens.Ladder.Components }, }, textboxTeam2 = new OsuTextBox { RelativeSizeAxes = Axes.X, Height = 20 }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = padding }, - Children = new Drawable[] - { - new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = "Best of", - }, - }, - }, - sliderBestOf = new PlayerSliderBar - { - Bindable = new BindableDouble - { - Default = 11, - Value = 11, - MinValue = 1, - MaxValue = 21, - Precision = 1, - }, - } + // new Container + // { + // RelativeSizeAxes = Axes.X, + // AutoSizeAxes = Axes.Y, + // Padding = new MarginPadding { Horizontal = padding }, + // Children = new Drawable[] + // { + // new OsuSpriteText + // { + // Anchor = Anchor.CentreLeft, + // Origin = Anchor.CentreLeft, + // Text = "Best of", + // }, + // }, + // }, + // sliderBestOf = new PlayerSliderBar + // { + // Bindable = new BindableDouble + // { + // Default = 11, + // Value = 11, + // MinValue = 1, + // MaxValue = 21, + // Precision = 1, + // }, + // } }; editorInfo.Selected.ValueChanged += selection => { textboxTeam1.Text = selection?.Team1.Value?.Acronym; textboxTeam2.Text = selection?.Team2.Value?.Acronym; - sliderBestOf.Bindable.Value = selection?.BestOf ?? sliderBestOf.Bindable.Default; }; textboxTeam1.OnCommit = (val, newText) => @@ -117,10 +113,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components editorInfo.Selected.Value.Team2.Value = teamEntries.FirstOrDefault(t => t.Acronym == val.Text); }; - sliderBestOf.Bindable.ValueChanged += val => - { - if (editorInfo.Selected.Value != null) editorInfo.Selected.Value.BestOf.Value = (int)val; - }; + // sliderBestOf.Bindable.ValueChanged += val => + // { + // if (editorInfo.Selected.Value != null) editorInfo.Selected.Value.BestOf.Value = (int)val; + // }; editorInfo.EditingEnabled.ValueChanged += enabled => { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index c47e3ea440..0bdfb5c300 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly Bindable Completed = new Bindable(); - public readonly BindableInt BestOf = new BindableInt(11); + public readonly Bindable Grouping = new Bindable(); [JsonIgnore] public readonly Bindable Progression = new Bindable(); diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs new file mode 100644 index 0000000000..0178885307 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + public class TournamentGrouping + { + public int ID; + + public string Name; + public string Description; + + public int BestOf; + } +} From ad63ff2d069ff544061ac59aba240c0ad273ee16 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 24 Sep 2018 16:34:46 +0900 Subject: [PATCH 0140/5608] Add scrollability --- .../Screens/Ladder/LadderManager.cs | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 235ac4a86a..2cf7e00314 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -12,6 +12,7 @@ using osu.Framework.Input.States; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK; using SixLabors.Primitives; namespace osu.Game.Tournament.Screens.Ladder @@ -43,8 +44,15 @@ namespace osu.Game.Tournament.Screens.Ladder RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - paths = new Container { RelativeSizeAxes = Axes.Both }, - pairingsContainer = new Container { RelativeSizeAxes = Axes.Both }, + new ScrollableContainer + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + paths = new Container { RelativeSizeAxes = Axes.Both }, + pairingsContainer = new Container { RelativeSizeAxes = Axes.Both }, + } + }, new LadderEditorSettings { Anchor = Anchor.TopRight, @@ -183,4 +191,17 @@ namespace osu.Game.Tournament.Screens.Ladder public void Remove(MatchPairing pairing) => pairingsContainer.FirstOrDefault(p => p.Pairing == pairing)?.Remove(); } + + public class ScrollableContainer : Container + { + protected override bool OnDragStart(InputState state) => true; + + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; + + protected override bool OnDrag(InputState state) + { + Position += state.Mouse.Delta; + return base.OnDrag(state); + } + } } From 1644775f7be43dc12301be7cf28a68045a152950 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 24 Sep 2018 23:30:37 +0900 Subject: [PATCH 0141/5608] Add grouping configuration --- .../Ladder/Components/LadderSettings.cs | 18 ++++++++++++++++++ .../Screens/Ladder/Components/MatchPairing.cs | 1 + .../Ladder/Components/TournamentGrouping.cs | 6 ++++-- .../Screens/Ladder/LadderManager.cs | 12 +++++++++++- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs index 7532cee0f0..379bb36c09 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs @@ -1,12 +1,15 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Settings; using osu.Game.Screens.Play.PlayerSettings; namespace osu.Game.Tournament.Screens.Ladder.Components @@ -19,6 +22,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private OsuTextBox textboxTeam1; private OsuTextBox textboxTeam2; + private SettingsDropdown groupingDropdown; [Resolved] private LadderEditorInfo editorInfo { get; set; } = null; @@ -28,6 +32,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { var teamEntries = editorInfo.Teams; + var groupingOptions = editorInfo.Groupings.Select(g => new KeyValuePair(g.Name, g)).Prepend(new KeyValuePair("None", new TournamentGrouping())); + Children = new Drawable[] { new PlayerCheckbox @@ -67,6 +73,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components }, }, textboxTeam2 = new OsuTextBox { RelativeSizeAxes = Axes.X, Height = 20 }, + groupingDropdown = new SettingsDropdown + { + Bindable = new Bindable(), + Items = groupingOptions + }, // new Container // { // RelativeSizeAxes = Axes.X, @@ -99,6 +110,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { textboxTeam1.Text = selection?.Team1.Value?.Acronym; textboxTeam2.Text = selection?.Team2.Value?.Acronym; + groupingDropdown.Bindable.Value = selection?.Grouping.Value ?? groupingOptions.First().Value; }; textboxTeam1.OnCommit = (val, newText) => @@ -113,6 +125,12 @@ namespace osu.Game.Tournament.Screens.Ladder.Components editorInfo.Selected.Value.Team2.Value = teamEntries.FirstOrDefault(t => t.Acronym == val.Text); }; + groupingDropdown.Bindable.ValueChanged += grouping => + { + if (editorInfo.Selected.Value != null) + editorInfo.Selected.Value.Grouping.Value = grouping; + }; + // sliderBestOf.Bindable.ValueChanged += val => // { // if (editorInfo.Selected.Value != null) editorInfo.Selected.Value.BestOf.Value = (int)val; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index 0bdfb5c300..a97354a1c4 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -25,6 +25,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly Bindable Completed = new Bindable(); + [JsonIgnore] public readonly Bindable Grouping = new Bindable(); [JsonIgnore] diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs index 0178885307..675bf5fc4f 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs @@ -1,15 +1,17 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; + namespace osu.Game.Tournament.Screens.Ladder.Components { public class TournamentGrouping { - public int ID; - public string Name; public string Description; public int BestOf; + + public List Pairings = new List(); } } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 2cf7e00314..8939e72be2 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -21,6 +21,7 @@ namespace osu.Game.Tournament.Screens.Ladder { public readonly BindableBool EditingEnabled = new BindableBool(); public List Teams = new List(); + public List Groupings = new List(); public readonly Bindable Selected = new Bindable(); } @@ -36,6 +37,7 @@ namespace osu.Game.Tournament.Screens.Ladder public LadderManager(LadderInfo info, List teams) { editorInfo.Teams = Teams = teams; + editorInfo.Groupings = info.Groupings; RelativeSizeAxes = Axes.Both; @@ -75,19 +77,27 @@ namespace osu.Game.Tournament.Screens.Ladder foreach (var pairing in info.Pairings) addPairing(pairing); + + foreach (var group in info.Groupings) + foreach (var id in group.Pairings) + info.Pairings.Single(p => p.ID == id).Grouping.Value = group; } public LadderInfo CreateInfo() { var pairings = pairingsContainer.Select(p => p.Pairing).ToList(); + foreach (var g in editorInfo.Groupings) + g.Pairings = pairings.Where(p => p.Grouping.Value == g).Select(p => p.ID).ToList(); + return new LadderInfo { Pairings = pairings, Progressions = pairings .Where(p => p.Progression.Value != null) .Select(p => (p.ID, p.Progression.Value.ID)) - .ToList() + .ToList(), + Groupings = editorInfo.Groupings }; } From c7c55f21392d029cb2f5ff851e1b08e495940af1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 00:57:44 +0900 Subject: [PATCH 0142/5608] Add headings --- .../Ladder/DrawableTournamentGrouping.cs | 39 ++++++++++++++++ .../Screens/Ladder/LadderManager.cs | 46 +++++++++++++------ .../Screens/Ladder/ScrollableContainer.cs | 22 +++++++++ 3 files changed, 93 insertions(+), 14 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Ladder/DrawableTournamentGrouping.cs create mode 100644 osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs diff --git a/osu.Game.Tournament/Screens/Ladder/DrawableTournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/DrawableTournamentGrouping.cs new file mode 100644 index 0000000000..28e1183b27 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/DrawableTournamentGrouping.cs @@ -0,0 +1,39 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Tournament.Screens.Ladder.Components; + +namespace osu.Game.Tournament.Screens.Ladder +{ + public class DrawableTournamentGrouping : CompositeDrawable + { + public DrawableTournamentGrouping(TournamentGrouping grouping) + { + AutoSizeAxes = Axes.Both; + InternalChild = new FillFlowContainer + { + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = grouping.Description.ToUpper(), + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre + }, + new OsuSpriteText + { + Text = grouping.Name.ToUpper(), + Font = "Exo2.0-Bold", + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre + }, + } + }; + } + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 8939e72be2..95b2a0a8d1 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; using osu.Framework.Allocation; +using osu.Framework.Caching; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -12,7 +14,6 @@ using osu.Framework.Input.States; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; -using OpenTK; using SixLabors.Primitives; namespace osu.Game.Tournament.Screens.Ladder @@ -30,6 +31,7 @@ namespace osu.Game.Tournament.Screens.Ladder public readonly List Teams; private readonly Container pairingsContainer; private readonly Container paths; + private readonly Container headings; [Cached] private readonly LadderEditorInfo editorInfo = new LadderEditorInfo(); @@ -52,6 +54,7 @@ namespace osu.Game.Tournament.Screens.Ladder Children = new Drawable[] { paths = new Container { RelativeSizeAxes = Axes.Both }, + headings = new Container() { RelativeSizeAxes = Axes.Both }, pairingsContainer = new Container { RelativeSizeAxes = Axes.Both }, } }, @@ -81,6 +84,9 @@ namespace osu.Game.Tournament.Screens.Ladder foreach (var group in info.Groupings) foreach (var id in group.Pairings) info.Pairings.Single(p => p.ID == id).Grouping.Value = group; + + // todo: fix this + Scheduler.AddDelayed(() => layout.Invalidate(), 100, true); } public LadderInfo CreateInfo() @@ -121,11 +127,20 @@ namespace osu.Game.Tournament.Screens.Ladder } } + private Cached layout = new Cached(); + protected override void Update() { base.Update(); + if (!layout.IsValid) + updateLayout(); + } + + private void updateLayout() + { paths.Clear(); + headings.Clear(); int id = 1; foreach (var pairing in pairingsContainer.OrderBy(d => d.Y).ThenBy(d => d.X)) @@ -143,6 +158,22 @@ namespace osu.Game.Tournament.Screens.Ladder paths.Add(new ProgressionPath(pairing, dest)); } } + + foreach (var group in editorInfo.Groupings) + { + var topPairing = pairingsContainer.Where(p => p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); + + if (topPairing == null) continue; + + headings.Add(new DrawableTournamentGrouping(group) + { + Position = headings.ToLocalSpace((topPairing.ScreenSpaceDrawQuad.TopLeft + topPairing.ScreenSpaceDrawQuad.TopRight) / 2), + Margin = new MarginPadding { Bottom = 10 }, + Origin = Anchor.BottomCentre, + }); + } + + layout.Validate(); } public void RequestJoin(MatchPairing pairing) => AddInternal(new JoinRequestHandler(pairingsContainer, pairing)); @@ -201,17 +232,4 @@ namespace osu.Game.Tournament.Screens.Ladder public void Remove(MatchPairing pairing) => pairingsContainer.FirstOrDefault(p => p.Pairing == pairing)?.Remove(); } - - public class ScrollableContainer : Container - { - protected override bool OnDragStart(InputState state) => true; - - public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; - - protected override bool OnDrag(InputState state) - { - Position += state.Mouse.Delta; - return base.OnDrag(state); - } - } } diff --git a/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs b/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs new file mode 100644 index 0000000000..bb4f2e58a9 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs @@ -0,0 +1,22 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.States; +using OpenTK; + +namespace osu.Game.Tournament.Screens.Ladder +{ + public class ScrollableContainer : Container + { + protected override bool OnDragStart(InputState state) => true; + + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; + + protected override bool OnDrag(InputState state) + { + Position += state.Mouse.Delta; + return base.OnDrag(state); + } + } +} From d2ce974ba8ade2586ee8ae343e2dab2cfd09a77d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 02:31:48 +0900 Subject: [PATCH 0143/5608] Add loser progressions --- .../Ladder/Components/DrawableMatchPairing.cs | 19 +++++-- .../Ladder/Components/DrawableMatchTeam.cs | 7 ++- .../Screens/Ladder/Components/LadderInfo.cs | 2 +- .../Ladder/Components/LadderSettings.cs | 16 +++++- .../Screens/Ladder/Components/MatchPairing.cs | 8 +++ .../Components/TournamentProgression.cs | 20 +++++++ .../Ladder/DrawableTournamentGrouping.cs | 4 +- .../Screens/Ladder/LadderManager.cs | 54 ++++++++++++++----- 8 files changed, 108 insertions(+), 22 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index a7ebbfa8b3..285baad872 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -64,6 +64,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components pairing.Grouping.BindValueChanged(_ => updateWinConditions()); pairing.Completed.BindValueChanged(_ => updateProgression()); pairing.Progression.BindValueChanged(_ => updateProgression()); + pairing.LosersProgression.BindValueChanged(_ => updateProgression()); updateTeams(); } @@ -102,12 +103,21 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { var progression = Pairing.Progression?.Value; - if (progression == null) return; + if (progression != null) + { + bool progressionAbove = progression.ID < Pairing.ID; - bool progressionAbove = progression.ID < Pairing.ID; + var destinationForWinner = progressionAbove || progression.Team1.Value != null && progression.Team1.Value != Pairing.Winner ? progression.Team2 : progression.Team1; + destinationForWinner.Value = Pairing.Winner; + } - var destinationForWinner = progressionAbove ? progression.Team2 : progression.Team1; - destinationForWinner.Value = Pairing.Winner; + if ((progression = Pairing.LosersProgression?.Value) != null) + { + bool progressionAbove = progression.ID < Pairing.ID; + + var destinationForLoser = progressionAbove || progression.Team1.Value != null && progression.Team1.Value != Pairing.Winner ? progression.Team2 : progression.Team1; + destinationForLoser.Value = Pairing.Loser; + } } private void updateWinConditions() @@ -197,6 +207,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { Selected = false; Pairing.Progression.Value = null; + Pairing.LosersProgression.Value = null; Expire(); } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index a517c5f475..c66d3fff55 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -141,6 +141,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } else { + if (pairing.Progression.Value.Completed) + // don't allow changing scores if the match has a progression. can cause large data loss + return false; + if (score.Value > 0) score.Value--; else @@ -168,7 +172,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components return new MenuItem[] { - new OsuMenuItem("Join with", MenuItemType.Standard, () => manager.RequestJoin(pairing)), + new OsuMenuItem("Join with", MenuItemType.Standard, () => manager.RequestJoin(pairing, false)), + new OsuMenuItem("Join with (loser)", MenuItemType.Standard, () => manager.RequestJoin(pairing, true)), new OsuMenuItem("Remove", MenuItemType.Destructive, () => manager.Remove(pairing)), }; } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs index e1da676f22..ba64b974d9 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs @@ -8,7 +8,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public class LadderInfo { public List Pairings = new List(); - public List<(int, int)> Progressions = new List<(int, int)>(); + public List Progressions = new List(); public List Groupings = new List(); } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs index 379bb36c09..d8e37a5c80 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs @@ -23,6 +23,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private OsuTextBox textboxTeam1; private OsuTextBox textboxTeam2; private SettingsDropdown groupingDropdown; + private PlayerCheckbox losersCheckbox; [Resolved] private LadderEditorInfo editorInfo { get; set; } = null; @@ -32,7 +33,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { var teamEntries = editorInfo.Teams; - var groupingOptions = editorInfo.Groupings.Select(g => new KeyValuePair(g.Name, g)).Prepend(new KeyValuePair("None", new TournamentGrouping())); + var groupingOptions = editorInfo.Groupings.Select(g => new KeyValuePair(g.Name, g)) + .Prepend(new KeyValuePair("None", new TournamentGrouping())); Children = new Drawable[] { @@ -78,6 +80,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Bindable = new Bindable(), Items = groupingOptions }, + losersCheckbox = new PlayerCheckbox + { + LabelText = "Losers Bracket", + Bindable = new Bindable() + } // new Container // { // RelativeSizeAxes = Axes.X, @@ -111,6 +118,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components textboxTeam1.Text = selection?.Team1.Value?.Acronym; textboxTeam2.Text = selection?.Team2.Value?.Acronym; groupingDropdown.Bindable.Value = selection?.Grouping.Value ?? groupingOptions.First().Value; + losersCheckbox.Current.Value = selection?.Losers.Value ?? false; }; textboxTeam1.OnCommit = (val, newText) => @@ -131,6 +139,12 @@ namespace osu.Game.Tournament.Screens.Ladder.Components editorInfo.Selected.Value.Grouping.Value = grouping; }; + losersCheckbox.Current.ValueChanged += losers => + { + if (editorInfo.Selected.Value != null) + editorInfo.Selected.Value.Losers.Value = losers; + }; + // sliderBestOf.Bindable.ValueChanged += val => // { // if (editorInfo.Selected.Value != null) editorInfo.Selected.Value.BestOf.Value = (int)val; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index a97354a1c4..49a477701f 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -25,12 +25,17 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly Bindable Completed = new Bindable(); + public readonly Bindable Losers = new Bindable(); + [JsonIgnore] public readonly Bindable Grouping = new Bindable(); [JsonIgnore] public readonly Bindable Progression = new Bindable(); + [JsonIgnore] + public readonly Bindable LosersProgression = new Bindable(); + [JsonProperty] public Point Position; @@ -47,6 +52,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [JsonIgnore] public TournamentTeam Winner => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team1.Value : Team2.Value; + [JsonIgnore] + public TournamentTeam Loser => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team2.Value : Team1.Value; + /// /// Remove scores from the match, in case of a false click or false start. /// diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs new file mode 100644 index 0000000000..9f2d2c4045 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + public class TournamentProgression + { + public int Item1; + public int Item2; + + public bool Losers; + + public TournamentProgression(int item1, int item2, bool losers = false) + { + Item1 = item1; + Item2 = item2; + Losers = losers; + } + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/DrawableTournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/DrawableTournamentGrouping.cs index 28e1183b27..df7f621c24 100644 --- a/osu.Game.Tournament/Screens/Ladder/DrawableTournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/DrawableTournamentGrouping.cs @@ -10,7 +10,7 @@ namespace osu.Game.Tournament.Screens.Ladder { public class DrawableTournamentGrouping : CompositeDrawable { - public DrawableTournamentGrouping(TournamentGrouping grouping) + public DrawableTournamentGrouping(TournamentGrouping grouping, bool losers = false) { AutoSizeAxes = Axes.Both; InternalChild = new FillFlowContainer @@ -27,7 +27,7 @@ namespace osu.Game.Tournament.Screens.Ladder }, new OsuSpriteText { - Text = grouping.Name.ToUpper(), + Text = ((losers ? "Losers " : "") + grouping.Name).ToUpper(), Font = "Exo2.0-Bold", Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 95b2a0a8d1..d5ff651ef3 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.InteropServices; using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Configuration; @@ -54,7 +53,7 @@ namespace osu.Game.Tournament.Screens.Ladder Children = new Drawable[] { paths = new Container { RelativeSizeAxes = Axes.Both }, - headings = new Container() { RelativeSizeAxes = Axes.Both }, + headings = new Container { RelativeSizeAxes = Axes.Both }, pairingsContainer = new Container { RelativeSizeAxes = Axes.Both }, } }, @@ -75,7 +74,12 @@ namespace osu.Game.Tournament.Screens.Ladder if (src == null) throw new InvalidOperationException(); if (dest != null) - src.Progression.Value = dest; + { + if (pair.Losers) + src.LosersProgression.Value = dest; + else + src.Progression.Value = dest; + } } foreach (var pairing in info.Pairings) @@ -99,10 +103,9 @@ namespace osu.Game.Tournament.Screens.Ladder return new LadderInfo { Pairings = pairings, - Progressions = pairings - .Where(p => p.Progression.Value != null) - .Select(p => (p.ID, p.Progression.Value.ID)) - .ToList(), + Progressions = pairings.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( + pairings.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) + .ToList(), Groupings = editorInfo.Groupings }; } @@ -120,7 +123,7 @@ namespace osu.Game.Tournament.Screens.Ladder { new OsuMenuItem("Create new match", MenuItemType.Highlighted, () => { - var pos = ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position); + var pos = pairingsContainer.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position); addPairing(new MatchPairing { Position = new Point((int)pos.X, (int)pos.Y) }); }), }; @@ -161,7 +164,7 @@ namespace osu.Game.Tournament.Screens.Ladder foreach (var group in editorInfo.Groupings) { - var topPairing = pairingsContainer.Where(p => p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); + var topPairing = pairingsContainer.Where(p => !p.Pairing.Losers && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); if (topPairing == null) continue; @@ -173,25 +176,44 @@ namespace osu.Game.Tournament.Screens.Ladder }); } + foreach (var group in editorInfo.Groupings) + { + var topPairing = pairingsContainer.Where(p => p.Pairing.Losers && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); + + if (topPairing == null) continue; + + headings.Add(new DrawableTournamentGrouping(group, true) + { + Position = headings.ToLocalSpace((topPairing.ScreenSpaceDrawQuad.TopLeft + topPairing.ScreenSpaceDrawQuad.TopRight) / 2), + Margin = new MarginPadding { Bottom = 10 }, + Origin = Anchor.BottomCentre, + }); + } + layout.Validate(); } - public void RequestJoin(MatchPairing pairing) => AddInternal(new JoinRequestHandler(pairingsContainer, pairing)); + public void RequestJoin(MatchPairing pairing, bool losers) => AddInternal(new JoinRequestHandler(pairingsContainer, pairing, losers)); private class JoinRequestHandler : CompositeDrawable { private readonly Container pairingsContainer; public readonly MatchPairing Source; + private readonly bool losers; private ProgressionPath path; - public JoinRequestHandler(Container pairingsContainer, MatchPairing source) + public JoinRequestHandler(Container pairingsContainer, MatchPairing source, bool losers) { this.pairingsContainer = pairingsContainer; RelativeSizeAxes = Axes.Both; Source = source; - Source.Progression.Value = null; + this.losers = losers; + if (losers) + Source.LosersProgression.Value = null; + else + Source.Progression.Value = null; } private DrawableMatchPairing findTarget(InputState state) => pairingsContainer.FirstOrDefault(d => d.ReceiveMouseInputAt(state.Mouse.NativeState.Position)); @@ -221,7 +243,13 @@ namespace osu.Game.Tournament.Screens.Ladder if (found != null) { if (found.Pairing != Source) - Source.Progression.Value = found.Pairing; + { + if (losers) + Source.LosersProgression.Value = found.Pairing; + else + Source.Progression.Value = found.Pairing; + } + Expire(); return true; } From baefcb9deb52a6c3336e173af6cf1fd6217934bc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 03:14:30 +0900 Subject: [PATCH 0144/5608] Simplify team storage --- .../TestCaseLadderManager.cs | 5 +---- .../Ladder/Components/DrawableMatchPairing.cs | 4 ++-- .../Ladder/Components/DrawableMatchTeam.cs | 21 ++++--------------- .../Screens/Ladder/Components/LadderInfo.cs | 2 ++ .../Screens/Ladder/Components/MatchPairing.cs | 11 ++++++++-- .../Screens/Ladder/LadderManager.cs | 13 ++++++++++-- 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index ac56803c90..767681849b 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using System.IO; using Newtonsoft.Json; using osu.Framework.Allocation; @@ -9,7 +8,6 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Tests.Visual; -using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.Ladder.Components; @@ -25,13 +23,12 @@ namespace osu.Game.Tournament.Tests public TestCaseLadderManager() { - var teams = JsonConvert.DeserializeObject>(File.ReadAllText(@"teams.json")); var ladder = File.Exists(@"bracket.json") ? JsonConvert.DeserializeObject(File.ReadAllText(@"bracket.json")) : new LadderInfo(); Child = new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - Child = manager = new LadderManager(ladder, teams) + Child = manager = new LadderManager(ladder) }; } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 285baad872..42670b7bc0 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -107,7 +107,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { bool progressionAbove = progression.ID < Pairing.ID; - var destinationForWinner = progressionAbove || progression.Team1.Value != null && progression.Team1.Value != Pairing.Winner ? progression.Team2 : progression.Team1; + var destinationForWinner = progressionAbove || progression.Team1.Value != null && progression.Team1.Value != Pairing.Team1.Value && progression.Team1.Value != Pairing.Team2.Value ? progression.Team2 : progression.Team1; destinationForWinner.Value = Pairing.Winner; } @@ -115,7 +115,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { bool progressionAbove = progression.ID < Pairing.ID; - var destinationForLoser = progressionAbove || progression.Team1.Value != null && progression.Team1.Value != Pairing.Winner ? progression.Team2 : progression.Team1; + var destinationForLoser = progressionAbove || progression.Team1.Value != null && progression.Team1.Value != Pairing.Team1.Value && progression.Team1.Value != Pairing.Team2.Value ? progression.Team2 : progression.Team1; destinationForLoser.Value = Pairing.Loser; } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index c66d3fff55..f346e3c242 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -145,6 +145,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components // don't allow changing scores if the match has a progression. can cause large data loss return false; + if (pairing.Completed && pairing.Winner != Team) + // don't allow changing scores from the non-winner + return false; + if (score.Value > 0) score.Value--; else @@ -179,21 +183,4 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } } } - - internal static class Extensions - { - public static T Random(this IEnumerable enumerable) - { - if (enumerable == null) - { - throw new ArgumentNullException(nameof(enumerable)); - } - - // note: creating a Random instance each call may not be correct for you, - // consider a thread-safe static instance - var r = new Random(); - var list = enumerable as IList ?? enumerable.ToList(); - return list.Count == 0 ? default(T) : list[r.Next(0, list.Count)]; - } - } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs index ba64b974d9..567cdb0daa 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Game.Tournament.Components; namespace osu.Game.Tournament.Screens.Ladder.Components { @@ -10,5 +11,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public List Pairings = new List(); public List Progressions = new List(); public List Groupings = new List(); + public List Teams = new List(); } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index 49a477701f..93d1b7085c 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -15,12 +15,18 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public int ID; + [JsonIgnore] public readonly Bindable Team1 = new Bindable(); + public string Team1Acronym; + public readonly Bindable Team1Score = new Bindable(); + [JsonIgnore] public readonly Bindable Team2 = new Bindable(); + public string Team2Acronym; + public readonly Bindable Team2Score = new Bindable(); public readonly Bindable Completed = new Bindable(); @@ -36,14 +42,15 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [JsonIgnore] public readonly Bindable LosersProgression = new Bindable(); - [JsonProperty] public Point Position; public MatchPairing() { + Team1.BindValueChanged(t => Team1Acronym = t?.Acronym, true); + Team2.BindValueChanged(t => Team2Acronym = t?.Acronym, true); } - public MatchPairing(TournamentTeam team1 = null, TournamentTeam team2 = null) + public MatchPairing(TournamentTeam team1 = null, TournamentTeam team2 = null) : this() { Team1.Value = team1; Team2.Value = team2; diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index d5ff651ef3..665230eff7 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -35,9 +35,9 @@ namespace osu.Game.Tournament.Screens.Ladder [Cached] private readonly LadderEditorInfo editorInfo = new LadderEditorInfo(); - public LadderManager(LadderInfo info, List teams) + public LadderManager(LadderInfo info) { - editorInfo.Teams = Teams = teams; + editorInfo.Teams = Teams = info.Teams; editorInfo.Groupings = info.Groupings; RelativeSizeAxes = Axes.Both; @@ -66,6 +66,14 @@ namespace osu.Game.Tournament.Screens.Ladder } }; + // assign teams + foreach (var pairing in info.Pairings) + { + pairing.Team1.Value = info.Teams.FirstOrDefault(t => t.Acronym == pairing.Team1Acronym); + pairing.Team2.Value = info.Teams.FirstOrDefault(t => t.Acronym == pairing.Team2Acronym); + } + + // assign progressions foreach (var pair in info.Progressions) { var src = info.Pairings.FirstOrDefault(p => p.ID == pair.Item1); @@ -106,6 +114,7 @@ namespace osu.Game.Tournament.Screens.Ladder Progressions = pairings.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( pairings.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) .ToList(), + Teams = editorInfo.Teams, Groupings = editorInfo.Groupings }; } From fdccec06b3c8809a4a2bf30a40a6327834cb6e6e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 03:55:24 +0900 Subject: [PATCH 0145/5608] Change colour for losers pairings --- .../Screens/Ladder/Components/DrawableMatchPairing.cs | 5 +++-- .../Screens/Ladder/Components/DrawableMatchTeam.cs | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 42670b7bc0..ee69f5c079 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -65,6 +65,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components pairing.Completed.BindValueChanged(_ => updateProgression()); pairing.Progression.BindValueChanged(_ => updateProgression()); pairing.LosersProgression.BindValueChanged(_ => updateProgression()); + pairing.Losers.BindValueChanged(_ => updateTeams()); updateTeams(); } @@ -156,8 +157,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components flow.Children = new[] { - new DrawableMatchTeam(Pairing.Team1, Pairing), - new DrawableMatchTeam(Pairing.Team2, Pairing) + new DrawableMatchTeam(Pairing.Team1, Pairing, Pairing.Losers), + new DrawableMatchTeam(Pairing.Team2, Pairing, Pairing.Losers) }; SchedulerAfterChildren.Add(() => Scheduler.Add(updateProgression)); diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index f346e3c242..7e3d5f4f2b 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -2,8 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -26,6 +24,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public class DrawableMatchTeam : DrawableTournamentTeam, IHasContextMenu { private readonly MatchPairing pairing; + private readonly bool losers; private OsuSpriteText scoreText; private Box background; @@ -41,10 +40,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [Resolved(CanBeNull = true)] private LadderEditorInfo editorInfo { get; set; } = null; - public DrawableMatchTeam(Bindable team, MatchPairing pairing) + public DrawableMatchTeam(Bindable team, MatchPairing pairing, bool losers) : base(team) { this.pairing = pairing; + this.losers = losers; Size = new Vector2(150, 40); Masking = true; @@ -72,7 +72,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { this.manager = manager; - colourWinner = colours.BlueDarker; + colourWinner = losers ? colours.YellowDarker : colours.BlueDarker; colourNormal = OsuColour.Gray(0.2f); InternalChildren = new Drawable[] From 2bba426622371a6a1e073efc3b8e7c4cd936dceb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 03:55:35 +0900 Subject: [PATCH 0146/5608] Fix pairing line being incorrectly offset when scrolled --- .../Screens/Ladder/LadderEditorInfo.cs | 18 ++++++++++++++ .../Screens/Ladder/LadderManager.cs | 24 +++++++++---------- 2 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Ladder/LadderEditorInfo.cs diff --git a/osu.Game.Tournament/Screens/Ladder/LadderEditorInfo.cs b/osu.Game.Tournament/Screens/Ladder/LadderEditorInfo.cs new file mode 100644 index 0000000000..00272b9378 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/LadderEditorInfo.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Configuration; +using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Ladder.Components; + +namespace osu.Game.Tournament.Screens.Ladder +{ + public class LadderEditorInfo + { + public readonly BindableBool EditingEnabled = new BindableBool(); + public List Teams = new List(); + public List Groupings = new List(); + public readonly Bindable Selected = new Bindable(); + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 665230eff7..8e206a7194 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Caching; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -13,18 +12,12 @@ using osu.Framework.Input.States; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK; +using OpenTK.Graphics; using SixLabors.Primitives; namespace osu.Game.Tournament.Screens.Ladder { - public class LadderEditorInfo - { - public readonly BindableBool EditingEnabled = new BindableBool(); - public List Teams = new List(); - public List Groupings = new List(); - public readonly Bindable Selected = new Bindable(); - } - public class LadderManager : CompositeDrawable, IHasContextMenu { public readonly List Teams; @@ -32,6 +25,8 @@ namespace osu.Game.Tournament.Screens.Ladder private readonly Container paths; private readonly Container headings; + private readonly ScrollableContainer scrollContent; + [Cached] private readonly LadderEditorInfo editorInfo = new LadderEditorInfo(); @@ -47,7 +42,7 @@ namespace osu.Game.Tournament.Screens.Ladder RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new ScrollableContainer + scrollContent = new ScrollableContainer { RelativeSizeAxes = Axes.Both, Children = new Drawable[] @@ -202,7 +197,7 @@ namespace osu.Game.Tournament.Screens.Ladder layout.Validate(); } - public void RequestJoin(MatchPairing pairing, bool losers) => AddInternal(new JoinRequestHandler(pairingsContainer, pairing, losers)); + public void RequestJoin(MatchPairing pairing, bool losers) => scrollContent.Add(new JoinRequestHandler(pairingsContainer, pairing, losers)); private class JoinRequestHandler : CompositeDrawable { @@ -227,6 +222,8 @@ namespace osu.Game.Tournament.Screens.Ladder private DrawableMatchPairing findTarget(InputState state) => pairingsContainer.FirstOrDefault(d => d.ReceiveMouseInputAt(state.Mouse.NativeState.Position)); + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; + protected override bool OnMouseMove(InputState state) { var found = findTarget(state); @@ -240,7 +237,10 @@ namespace osu.Game.Tournament.Screens.Ladder if (found == null) return false; - AddInternal(path = new ProgressionPath(pairingsContainer.First(c => c.Pairing == Source), found) { Alpha = 0.4f }); + AddInternal(path = new ProgressionPath(pairingsContainer.First(c => c.Pairing == Source), found) + { + Colour = Color4.Yellow, + }); return base.OnMouseMove(state); } From 492cdb6a05e788772bc0c79262b6a59d7654647f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 04:21:48 +0900 Subject: [PATCH 0147/5608] Fix namespacing --- .../Ladder/{ => Components}/DrawableTournamentGrouping.cs | 3 +-- .../Screens/Ladder/{ => Components}/LadderEditorInfo.cs | 6 +----- 2 files changed, 2 insertions(+), 7 deletions(-) rename osu.Game.Tournament/Screens/Ladder/{ => Components}/DrawableTournamentGrouping.cs (92%) rename osu.Game.Tournament/Screens/Ladder/{ => Components}/LadderEditorInfo.cs (65%) diff --git a/osu.Game.Tournament/Screens/Ladder/DrawableTournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs similarity index 92% rename from osu.Game.Tournament/Screens/Ladder/DrawableTournamentGrouping.cs rename to osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs index df7f621c24..475e735522 100644 --- a/osu.Game.Tournament/Screens/Ladder/DrawableTournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs @@ -4,9 +4,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Tournament.Screens.Ladder.Components; -namespace osu.Game.Tournament.Screens.Ladder +namespace osu.Game.Tournament.Screens.Ladder.Components { public class DrawableTournamentGrouping : CompositeDrawable { diff --git a/osu.Game.Tournament/Screens/Ladder/LadderEditorInfo.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs similarity index 65% rename from osu.Game.Tournament/Screens/Ladder/LadderEditorInfo.cs rename to osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs index 00272b9378..b02c6eea84 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderEditorInfo.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs @@ -1,12 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - using System.Collections.Generic; using osu.Framework.Configuration; using osu.Game.Tournament.Components; -using osu.Game.Tournament.Screens.Ladder.Components; -namespace osu.Game.Tournament.Screens.Ladder +namespace osu.Game.Tournament.Screens.Ladder.Components { public class LadderEditorInfo { From 756141d9ed6b2ca3d2941ce73002bb3c5dbceea7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 04:51:40 +0900 Subject: [PATCH 0148/5608] Add basic scaling support --- .../Screens/Ladder/Components/ProgressionPath.cs | 4 ++-- .../Screens/Ladder/ScrollableContainer.cs | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs index c44f67a171..841148ce90 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs @@ -24,11 +24,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components base.LoadComplete(); Vector2 getCenteredVector(Vector2 top, Vector2 bottom) => new Vector2(top.X, top.Y + (bottom.Y - top.Y) / 2); - const float padding = 10; - var q1 = Source.ScreenSpaceDrawQuad; var q2 = Destination.ScreenSpaceDrawQuad; + float padding = q1.Width / 20; + bool progressionToRight = q2.TopLeft.X > q1.TopLeft.X; if (!progressionToRight) diff --git a/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs b/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs index bb4f2e58a9..f818a55296 100644 --- a/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.States; using OpenTK; @@ -13,10 +14,22 @@ namespace osu.Game.Tournament.Screens.Ladder public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; + private Vector2 target; + + private float scale = 1; + protected override bool OnDrag(InputState state) { - Position += state.Mouse.Delta; + this.MoveTo(target += state.Mouse.Delta, 1000, Easing.OutQuint); + return base.OnDrag(state); } + + protected override bool OnScroll(InputState state) + { + this.ScaleTo(scale += state.Mouse.ScrollDelta.Y / 15, 1000, Easing.OutQuint); + + return base.OnScroll(state); + } } } From 40ec24c721aed28fdeb82eaa8a35e18ece3c6cd9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 04:52:05 +0900 Subject: [PATCH 0149/5608] Increase line thickness to match design --- .../Screens/Ladder/Components/ProgressionPath.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs index 841148ce90..56add9dc3d 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Source = source; Destination = destination; - PathWidth = 2; + PathWidth = 3; BypassAutoSizeAxes = Axes.Both; } From fbda872a53efc74e62134f92c52ad42dd6cf8461 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 04:58:34 +0900 Subject: [PATCH 0150/5608] Update line colours to match bracket type --- .../Screens/Ladder/LadderManager.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 8e206a7194..5e0b5a8449 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -3,12 +3,14 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Caching; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Lines; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.States; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; @@ -144,6 +146,16 @@ namespace osu.Game.Tournament.Screens.Ladder updateLayout(); } + private Color4 normalPathColour; + private Color4 losersPathColour; + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + normalPathColour = colours.BlueDarker.Darken(2); + losersPathColour = colours.YellowDarker.Darken(2); + } + private void updateLayout() { paths.Clear(); @@ -162,7 +174,7 @@ namespace osu.Game.Tournament.Screens.Ladder // clean up outdated progressions. pairing.Pairing.Progression.Value = null; else - paths.Add(new ProgressionPath(pairing, dest)); + paths.Add(new ProgressionPath(pairing, dest) { Colour = pairing.Pairing.Losers ? losersPathColour : normalPathColour }); } } From 56981acc9256390b08b80fba2e69ab5f72e44f6d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 05:54:42 +0900 Subject: [PATCH 0151/5608] Fix default value of dropdown --- osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs index d8e37a5c80..1cf155ffde 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs @@ -77,7 +77,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components textboxTeam2 = new OsuTextBox { RelativeSizeAxes = Axes.X, Height = 20 }, groupingDropdown = new SettingsDropdown { - Bindable = new Bindable(), + Bindable = new Bindable { Default = groupingOptions.First().Value }, Items = groupingOptions }, losersCheckbox = new PlayerCheckbox From a5888feca4dab0e82f9097cfa98571e18f907a08 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 10:21:50 +0900 Subject: [PATCH 0152/5608] Wip zoomable container logic --- .../Screens/Ladder/ScrollableContainer.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs b/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs index f818a55296..f9263760fb 100644 --- a/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs @@ -20,16 +20,24 @@ namespace osu.Game.Tournament.Screens.Ladder protected override bool OnDrag(InputState state) { - this.MoveTo(target += state.Mouse.Delta, 1000, Easing.OutQuint); - + this.TransformTo(nameof(OriginPosition), target -= state.Mouse.Delta / scale, 1000, Easing.OutQuint); return base.OnDrag(state); } + protected override bool OnScroll(InputState state) { - this.ScaleTo(scale += state.Mouse.ScrollDelta.Y / 15, 1000, Easing.OutQuint); + this.ScaleTo(scale += state.Mouse.ScrollDelta.Y / 15 * scale, 1000, Easing.OutQuint); + target = ToLocalSpace(state.Mouse.NativeState.Position) / 2; + this.TransformTo(nameof(OriginPosition), target, 1000, Easing.OutQuint); return base.OnScroll(state); } + + protected override void Update() + { + base.Update(); + Invalidate(); + } } } From 991d85a9f34d9fd36a810b4d131e03a61feeb746 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 10:27:54 +0900 Subject: [PATCH 0153/5608] Cleanups --- .../TestCaseLadderManager.cs | 4 --- .../TestCaseMatchPairings.cs | 5 ---- .../Ladder/Components/DrawableMatchPairing.cs | 12 +-------- .../Ladder/Components/LadderEditorInfo.cs | 3 +++ ...derSettings.cs => LadderEditorSettings.cs} | 26 ------------------- .../Ladder/Components/ProgressionPath.cs | 3 +++ .../Ladder/Components/TournamentConditions.cs | 9 ------- .../Screens/Ladder/LadderManager.cs | 3 +++ 8 files changed, 10 insertions(+), 55 deletions(-) rename osu.Game.Tournament/Screens/Ladder/Components/{LadderSettings.cs => LadderEditorSettings.cs} (83%) delete mode 100644 osu.Game.Tournament/Screens/Ladder/Components/TournamentConditions.cs diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index 767681849b..2dfb1b8a63 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -4,7 +4,6 @@ using System.IO; using Newtonsoft.Json; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Tests.Visual; @@ -18,9 +17,6 @@ namespace osu.Game.Tournament.Tests [Cached] private readonly LadderManager manager; - [Cached] - private Bindable conditions = new Bindable(new TournamentConditions()); - public TestCaseLadderManager() { var ladder = File.Exists(@"bracket.json") ? JsonConvert.DeserializeObject(File.ReadAllText(@"bracket.json")) : new LadderInfo(); diff --git a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs index dc67807c64..b4a754e439 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs @@ -3,8 +3,6 @@ using System; using System.Collections.Generic; -using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Tests.Visual; @@ -23,9 +21,6 @@ namespace osu.Game.Tournament.Tests typeof(DrawableTournamentTeam), }; - [Cached] - private Bindable conditions = new Bindable(new TournamentConditions()); - public TestCaseMatchPairings() { Container level1; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index ee69f5c079..9b50322098 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -19,7 +19,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public readonly MatchPairing Pairing; private readonly FillFlowContainer flow; - private readonly Bindable conditions = new Bindable(); private readonly Drawable selectionBox; private Bindable globalSelection; @@ -70,15 +69,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components updateTeams(); } - [BackgroundDependencyLoader(true)] - private void load(Bindable conditions) - { - this.conditions.BindValueChanged(_ => updateWinConditions()); - - if (conditions != null) - this.conditions.BindTo(conditions); - } - private bool selected; public bool Selected @@ -123,7 +113,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private void updateWinConditions() { - if (conditions.Value == null || Pairing.Grouping.Value == null) return; + if (Pairing.Grouping.Value == null) return; var instaWinAmount = Pairing.Grouping.Value.BestOf / 2; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs index b02c6eea84..cc91c98188 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using System.Collections.Generic; using osu.Framework.Configuration; using osu.Game.Tournament.Components; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs similarity index 83% rename from osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs rename to osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index 1cf155ffde..95067e8803 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -85,32 +85,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components LabelText = "Losers Bracket", Bindable = new Bindable() } - // new Container - // { - // RelativeSizeAxes = Axes.X, - // AutoSizeAxes = Axes.Y, - // Padding = new MarginPadding { Horizontal = padding }, - // Children = new Drawable[] - // { - // new OsuSpriteText - // { - // Anchor = Anchor.CentreLeft, - // Origin = Anchor.CentreLeft, - // Text = "Best of", - // }, - // }, - // }, - // sliderBestOf = new PlayerSliderBar - // { - // Bindable = new BindableDouble - // { - // Default = 11, - // Value = 11, - // MinValue = 1, - // MaxValue = 21, - // Precision = 1, - // }, - // } }; editorInfo.Selected.ValueChanged += selection => diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs index 56add9dc3d..4496430e79 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Lines; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentConditions.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentConditions.cs deleted file mode 100644 index 045149945c..0000000000 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentConditions.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace osu.Game.Tournament.Screens.Ladder.Components -{ - /// - /// Conditions governing a tournament. - /// - public class TournamentConditions - { - } -} diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 5e0b5a8449..3c3d8243a3 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using System; using System.Collections.Generic; using System.Linq; From e74fd042aa4e8244efc8c38c97d4f08575a1b236 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 10:35:00 +0900 Subject: [PATCH 0154/5608] Use MouseUp instead of MouseDown for now --- .../Screens/Ladder/Components/DrawableMatchPairing.cs | 7 ++----- .../Screens/Ladder/Components/DrawableMatchTeam.cs | 3 ++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 9b50322098..5f58ca0ba5 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -155,9 +155,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components updateWinConditions(); } - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => args.Button == MouseButton.Left; + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => editorInfo.EditingEnabled; - protected override bool OnDragStart(InputState state) => true; + protected override bool OnDragStart(InputState state) => editorInfo.EditingEnabled; protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { @@ -183,9 +183,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { if (base.OnDrag(state)) return true; - if (!editorInfo.EditingEnabled) - return false; - Selected = true; this.MoveToOffset(state.Mouse.Delta); diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 7e3d5f4f2b..b0570a24dc 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -126,7 +126,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components }, true); } - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + //TODO: use OnClick instead once we have per-button clicks. + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { if (Team == null || editorInfo.EditingEnabled) return false; From c210ea7c39d0b1e6180348132f4eb36dd7406501 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 10:46:09 +0900 Subject: [PATCH 0155/5608] Improve zoom logic --- .../Screens/Ladder/ScrollableContainer.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs b/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs index f9263760fb..9d4ad2eccf 100644 --- a/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs @@ -20,18 +20,18 @@ namespace osu.Game.Tournament.Screens.Ladder protected override bool OnDrag(InputState state) { - this.TransformTo(nameof(OriginPosition), target -= state.Mouse.Delta / scale, 1000, Easing.OutQuint); - return base.OnDrag(state); + this.MoveTo(target += state.Mouse.Delta, 1000, Easing.OutQuint); + return true; } - protected override bool OnScroll(InputState state) { - this.ScaleTo(scale += state.Mouse.ScrollDelta.Y / 15 * scale, 1000, Easing.OutQuint); - target = ToLocalSpace(state.Mouse.NativeState.Position) / 2; - this.TransformTo(nameof(OriginPosition), target, 1000, Easing.OutQuint); + var newScale = scale + state.Mouse.ScrollDelta.Y / 15 * scale; + this.MoveTo(target = target - state.Mouse.Position * (newScale - scale), 1000, Easing.OutQuint); - return base.OnScroll(state); + this.ScaleTo(scale = newScale, 1000, Easing.OutQuint); + + return true; } protected override void Update() From 2abe96fb9c18f0bf9f4d9f88943b945b55579b29 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 13:39:27 +0900 Subject: [PATCH 0156/5608] Fix crash --- .../Screens/Ladder/Components/DrawableMatchTeam.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index b0570a24dc..12638609b6 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -142,7 +142,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } else { - if (pairing.Progression.Value.Completed) + if (pairing.Progression.Value?.Completed.Value != false) // don't allow changing scores if the match has a progression. can cause large data loss return false; From 73f451f27af420ec923da06c6e4d404de84db9aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Sep 2018 13:39:33 +0900 Subject: [PATCH 0157/5608] Fix right click regression --- .../Screens/Ladder/Components/DrawableMatchPairing.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 5f58ca0ba5..6e4674b3bf 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -155,7 +155,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components updateWinConditions(); } - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => editorInfo.EditingEnabled; + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => args.Button == MouseButton.Left && editorInfo.EditingEnabled; protected override bool OnDragStart(InputState state) => editorInfo.EditingEnabled; From 9a5127d506e255ab70ae00d2a4ad83bbe27d2c73 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Sun, 30 Sep 2018 14:29:55 +0200 Subject: [PATCH 0158/5608] fixed object scale upon hit --- osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs index ec80537a52..8c6f82dee4 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -29,15 +29,14 @@ namespace osu.Game.Rulesets.Osu.Mods { if (!(drawable is DrawableHitCircle d)) return; - d.ApproachCircle.Hide(); var h = d.HitObject; - using (d.BeginAbsoluteSequence(h.StartTime - h.TimePreempt)) { var origScale = d.Scale; - d.ScaleTo(1.1f); - d.ScaleTo(origScale, h.TimePreempt); + d.ScaleTo(1.1f, 1) // if duration = 0 then components (i.e. flash) scale with it -> we don't want that + .Then() + .ScaleTo(origScale, h.TimePreempt); } } } From 98042eb7d4aaec3e53530b6ffbc2bff2b014ea71 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Sun, 30 Sep 2018 14:46:36 +0200 Subject: [PATCH 0159/5608] add the default fadeout-while-scaling-up to clicked objects --- osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs index 8c6f82dee4..a4f841f188 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -36,7 +36,9 @@ namespace osu.Game.Rulesets.Osu.Mods var origScale = d.Scale; d.ScaleTo(1.1f, 1) // if duration = 0 then components (i.e. flash) scale with it -> we don't want that .Then() - .ScaleTo(origScale, h.TimePreempt); + .ScaleTo(origScale, h.TimePreempt) + .Then() + .ScaleTo(d.Scale * 1.5f, 400, Easing.OutQuad); // reapply overwritten ScaleTo } } } From 8b09935c378b38f72f8c7429d1ed84a3fdf5e198 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Sun, 30 Sep 2018 14:49:52 +0200 Subject: [PATCH 0160/5608] previous commit only added scaling-up (oops), this one includes fading --- osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs index a4f841f188..db46d3992a 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -38,6 +38,7 @@ namespace osu.Game.Rulesets.Osu.Mods .Then() .ScaleTo(origScale, h.TimePreempt) .Then() + .FadeOut(800) .ScaleTo(d.Scale * 1.5f, 400, Easing.OutQuad); // reapply overwritten ScaleTo } } From 01a4c8d92b5556d1757adb7a828a8ffbe7bc5d7c Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Mon, 1 Oct 2018 12:11:19 +0200 Subject: [PATCH 0161/5608] Add deflate mod to OsuRuleset.cs --- osu.Game.Rulesets.Osu/OsuRuleset.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 6736d10dab..30dd9c73d6 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -121,6 +121,7 @@ namespace osu.Game.Rulesets.Osu return new Mod[] { new OsuModTransform(), new OsuModWiggle(), + new OsuModDeflate(), }; default: return new Mod[] { }; From 0ae9c78c38ce3cd33b3b3cfce14234050ad6b05f Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Mon, 1 Oct 2018 12:29:21 +0200 Subject: [PATCH 0162/5608] set drawableOnApplyCustomUpdateState private to make AppVeyor happy :) --- osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs index db46d3992a..d61d552ce2 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Mods drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState; } - protected void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state) + private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state) { if (!(drawable is DrawableHitCircle d)) return; From 1366b53a7150c56165a534dacea2eae9933e0a3b Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Tue, 9 Oct 2018 13:16:27 +0200 Subject: [PATCH 0163/5608] Added traceable mod + HideButApproachCircle function for DrawableHitCircle --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 32 +++++++++++++++++++ .../Objects/Drawables/DrawableHitCircle.cs | 9 ++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 1 + 3 files changed, 42 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs new file mode 100644 index 0000000000..43eac55ffd --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables; + +namespace osu.Game.Rulesets.Osu.Mods +{ + internal class OsuModTraceable : Mod, IApplicableToDrawableHitObjects + { + public override string Name => "Traceable"; + public override string ShortenedName => "TC"; + public override FontAwesome Icon => FontAwesome.fa_snapchat_ghost; + public override ModType Type => ModType.Fun; + public override string Description => "Put your faith in the approach circles..."; + public override double ScoreMultiplier => 1; + + public void ApplyToDrawableHitObjects(IEnumerable drawables) + { + foreach (var drawable in drawables) + { + if (drawable is DrawableHitCircle c) + c.HideButApproachCircle(); + if (drawable is DrawableSlider s) + s.HeadCircle.HideButApproachCircle(); + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 4bdddcef11..79cc88e474 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -76,6 +76,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } + public void HideButApproachCircle() + { + circle.Hide(); + circle.AlwaysPresent = true; + ring.Hide(); + number.Hide(); + glow.Hide(); + } + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!userTriggered) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 6736d10dab..0b6aee7881 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -121,6 +121,7 @@ namespace osu.Game.Rulesets.Osu return new Mod[] { new OsuModTransform(), new OsuModWiggle(), + new OsuModTraceable(), }; default: return new Mod[] { }; From 954bcd8c123dcad1112ed94bc07bf3a824adfc9d Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Tue, 9 Oct 2018 18:36:12 +0200 Subject: [PATCH 0164/5608] Treat non-DrawableHitCircle's similar to OsuModHidden --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 61 +++++++++++++++++-- .../Objects/Drawables/DrawableHitCircle.cs | 2 + 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 43eac55ffd..dfd398e7e4 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -1,11 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Osu.Mods { @@ -21,11 +24,61 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToDrawableHitObjects(IEnumerable drawables) { foreach (var drawable in drawables) + drawable.ApplyCustomUpdateState += ApplyTraceableState; + } + + /* Similar to ApplyHiddenState, only different if drawable is DrawableHitCircle. + * If we'd use ApplyHiddenState instead but only on non-DrawableHitCircle's, then + * the nested object HeadCircle of DrawableSlider would still use ApplyHiddenState, + * thus treating the DrawableHitCircle with the hidden mod instead of the traceable mod. + */ + protected void ApplyTraceableState(DrawableHitObject drawable, ArmedState state) + { + if (!(drawable is DrawableOsuHitObject d)) + return; + + var h = d.HitObject; + + var fadeOutStartTime = h.StartTime - h.TimePreempt + h.TimeFadeIn; + + // new duration from completed fade in to end (before fading out) + var longFadeDuration = ((h as IHasEndTime)?.EndTime ?? h.StartTime) - fadeOutStartTime; + + switch (drawable) { - if (drawable is DrawableHitCircle c) - c.HideButApproachCircle(); - if (drawable is DrawableSlider s) - s.HeadCircle.HideButApproachCircle(); + case DrawableHitCircle circle: + // we only want to see the approach circle + using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + circle.HideButApproachCircle(); + + // approach circle fades out quickly at StartTime + using (drawable.BeginAbsoluteSequence(h.StartTime, true)) + circle.ApproachCircle.FadeOut(50); + + break; + case DrawableSlider slider: + using (slider.BeginAbsoluteSequence(fadeOutStartTime, true)) + slider.Body.FadeOut(longFadeDuration, Easing.Out); + + break; + case DrawableSliderTick sliderTick: + // slider ticks fade out over up to one second + var tickFadeOutDuration = Math.Min(sliderTick.HitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000); + + using (sliderTick.BeginAbsoluteSequence(sliderTick.HitObject.StartTime - tickFadeOutDuration, true)) + sliderTick.FadeOut(tickFadeOutDuration); + + break; + case DrawableSpinner spinner: + // hide elements we don't care about. + spinner.Disc.Hide(); + spinner.Ticks.Hide(); + spinner.Background.Hide(); + + using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true)) + spinner.FadeOut(h.TimePreempt); + + break; } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 79cc88e474..1644480aa4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -81,6 +81,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circle.Hide(); circle.AlwaysPresent = true; ring.Hide(); + flash.Hide(); + explode.Hide(); number.Hide(); glow.Hide(); } From edb69463fd4318145ff97e2bb3a0219fc8f646dc Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Tue, 9 Oct 2018 18:52:34 +0200 Subject: [PATCH 0165/5608] Trimming whitespace from comment...... --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index dfd398e7e4..a6d8d35125 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Mods } /* Similar to ApplyHiddenState, only different if drawable is DrawableHitCircle. - * If we'd use ApplyHiddenState instead but only on non-DrawableHitCircle's, then + * If we'd use ApplyHiddenState instead but only on non-DrawableHitCircle's, then * the nested object HeadCircle of DrawableSlider would still use ApplyHiddenState, * thus treating the DrawableHitCircle with the hidden mod instead of the traceable mod. */ From 951ac30de8a6db2af540b7aef26f5fb352b41330 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Wed, 10 Oct 2018 01:36:37 +0200 Subject: [PATCH 0166/5608] ArmedState now considered, SliderBody now deflates (TODO: handle slider's nested objects) --- osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs | 55 +++++++++++++++++---- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs index d61d552ce2..f5be85158f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -7,6 +7,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; using System.Collections.Generic; +using OpenTK; namespace osu.Game.Rulesets.Osu.Mods { @@ -27,19 +28,53 @@ namespace osu.Game.Rulesets.Osu.Mods private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state) { - if (!(drawable is DrawableHitCircle d)) + if (!(drawable is DrawableOsuHitObject d)) return; - d.ApproachCircle.Hide(); + var h = d.HitObject; - using (d.BeginAbsoluteSequence(h.StartTime - h.TimePreempt)) + + switch (drawable) { - var origScale = d.Scale; - d.ScaleTo(1.1f, 1) // if duration = 0 then components (i.e. flash) scale with it -> we don't want that - .Then() - .ScaleTo(origScale, h.TimePreempt) - .Then() - .FadeOut(800) - .ScaleTo(d.Scale * 1.5f, 400, Easing.OutQuad); // reapply overwritten ScaleTo + case DrawableHitCircle c: + c.ApproachCircle.Hide(); + using (d.BeginAbsoluteSequence(h.StartTime - h.TimePreempt)) + { + var origScale = d.Scale; + d.ScaleTo(1.1f, 1) + .Then() + .ScaleTo(origScale, h.TimePreempt); + } + switch (state) + { + case ArmedState.Miss: + d.FadeOut(100); + break; + case ArmedState.Hit: + d.FadeOut(800) + .ScaleTo(d.Scale * 1.5f, 400, Easing.OutQuad); + break; + } + break; + case DrawableSlider s: + using (d.BeginAbsoluteSequence(h.StartTime - h.TimePreempt + 1, true)) + { + float origPathWidth = s.Body.PathWidth; + var origBodySize = s.Body.Size; + var origBodyDrawPos = s.Body.DrawPosition; + + s.Body.MoveTo(origBodyDrawPos - new Vector2(origPathWidth), 1) + .Then() + .MoveTo(origBodyDrawPos, h.TimePreempt); + + s.Body.ResizeTo(origBodySize * 2, 1) + .Then() + .ResizeTo(origBodySize, h.TimePreempt); + + s.Body.TransformTo("PathWidth", origPathWidth * 2, 1) + .Then() + .TransformTo("PathWidth", origPathWidth, h.TimePreempt); + } + break; } } } From 11dad7bf746820b56fa426f63f8582062de52a6d Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 10 Oct 2018 16:46:02 +0200 Subject: [PATCH 0167/5608] filter beatmaps by star range --- .../Visual/TestCaseBeatmapCarousel.cs | 49 +++++++++++++++++++ .../Select/Carousel/CarouselBeatmap.cs | 6 +++ osu.Game/Screens/Select/FilterControl.cs | 40 +++++++++------ osu.Game/Screens/Select/FilterCriteria.cs | 2 + 4 files changed, 81 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs index db66c01814..df42ba9d16 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs @@ -77,6 +77,7 @@ namespace osu.Game.Tests.Visual testEmptyTraversal(); testHiding(); testSelectingFilteredRuleset(); + testFilterByStarRange(); testCarouselRootIsRandom(); } @@ -245,6 +246,54 @@ namespace osu.Game.Tests.Visual AddAssert("Selection is non-null", () => currentSelection != null); } + /// + /// Test filtering by restricting the desired star range + /// + private void testFilterByStarRange() + { + var manyStarDiffs = createTestBeatmapSet(set_count + 1); + manyStarDiffs.Beatmaps.Clear(); + + for (int i = 0; i < 12; i++) + { + manyStarDiffs.Beatmaps.Add(new BeatmapInfo + { + OnlineBeatmapID = manyStarDiffs.ID * 10 + i, + Path = $"randomDiff{i}.osu", + Version = $"Totally Normal {i}", + StarDifficulty = i, + BaseDifficulty = new BeatmapDifficulty + { + OverallDifficulty = 5, + } + }); + } + + AddStep("add set with many stars", () => carousel.UpdateBeatmapSet(manyStarDiffs)); + + AddStep("select added set", () => carousel.SelectBeatmap(manyStarDiffs.Beatmaps[0], false)); + + AddStep("Filter to 1-3 stars", () => carousel.Filter(new FilterCriteria { DisplayStarsMinimum = 1, DisplayStarsMaximum = 3 }, false)); + checkVisibleItemCount(diff: false, count: 1); + checkVisibleItemCount(diff: true, count: 3); + + AddStep("Filter to 3-3 stars", () => carousel.Filter(new FilterCriteria { DisplayStarsMinimum = 3, DisplayStarsMaximum = 3 }, false)); + checkVisibleItemCount(diff: false, count: 1); + checkVisibleItemCount(diff: true, count: 1); + + AddStep("Filter to 4-2 stars", () => carousel.Filter(new FilterCriteria { DisplayStarsMinimum = 4, DisplayStarsMaximum = 2 }, false)); + checkVisibleItemCount(diff: false, count: 0); + checkVisibleItemCount(diff: true, count: 0); + + AddStep("remove added set", () => + { + carousel.RemoveBeatmapSet(manyStarDiffs); + manyStarDiffs = null; + }); + + AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); + } + /// /// Test random non-repeating algorithm /// diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 272332f1ce..c9ed2f3573 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -26,6 +26,12 @@ namespace osu.Game.Screens.Select.Carousel bool match = criteria.Ruleset == null || Beatmap.RulesetID == criteria.Ruleset.ID || Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps; + if(criteria.DisplayStarsMinimum.HasValue) + match &= Beatmap.StarDifficulty >= criteria.DisplayStarsMinimum; + + if (criteria.DisplayStarsMaximum.HasValue) + match &= Beatmap.StarDifficulty <= criteria.DisplayStarsMaximum; + if (!string.IsNullOrEmpty(criteria.SearchText)) match &= Beatmap.Metadata.SearchableTerms.Any(term => term.IndexOf(criteria.SearchText, StringComparison.InvariantCultureIgnoreCase) >= 0) || diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index fce7af1400..78b452b6f5 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -32,14 +32,13 @@ namespace osu.Game.Screens.Select public SortMode Sort { - get { return sort; } + get => sort; set { - if (sort != value) - { - sort = value; - FilterChanged?.Invoke(CreateCriteria()); - } + if (sort == value) return; + + sort = value; + FilterChanged?.Invoke(CreateCriteria()); } } @@ -47,14 +46,13 @@ namespace osu.Game.Screens.Select public GroupMode Group { - get { return group; } + get => group; set { - if (group != value) - { - group = value; - FilterChanged?.Invoke(CreateCriteria()); - } + if (group == value) return; + + group = value; + FilterChanged?.Invoke(CreateCriteria()); } } @@ -64,7 +62,9 @@ namespace osu.Game.Screens.Select Sort = sort, SearchText = searchTextBox.Text, AllowConvertedBeatmaps = showConverted, - Ruleset = ruleset.Value + Ruleset = ruleset.Value, + DisplayStarsMinimum = minimumStars, + DisplayStarsMaximum = maximumStars, }; public Action Exit; @@ -168,7 +168,9 @@ namespace osu.Game.Screens.Select private readonly IBindable ruleset = new Bindable(); - private Bindable showConverted; + private readonly Bindable showConverted = new Bindable(); + private readonly Bindable minimumStars = new Bindable(); + private readonly Bindable maximumStars = new Bindable(); public readonly Box Background; @@ -177,8 +179,14 @@ namespace osu.Game.Screens.Select { sortTabs.AccentColour = colours.GreenLight; - showConverted = config.GetBindable(OsuSetting.ShowConvertedBeatmaps); - showConverted.ValueChanged += val => updateCriteria(); + config.BindWith(OsuSetting.ShowConvertedBeatmaps, showConverted); + showConverted.ValueChanged += _ => updateCriteria(); + + config.BindWith(OsuSetting.DisplayStarsMinimum, minimumStars); + minimumStars.ValueChanged += _ => updateCriteria(); + + config.BindWith(OsuSetting.DisplayStarsMaximum, maximumStars); + maximumStars.ValueChanged += _ => updateCriteria(); ruleset.BindTo(parentRuleset); ruleset.BindValueChanged(_ => updateCriteria(), true); diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index bea806f00f..f97eb1bea1 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -13,5 +13,7 @@ namespace osu.Game.Screens.Select public string SearchText; public RulesetInfo Ruleset; public bool AllowConvertedBeatmaps; + public double? DisplayStarsMinimum; + public double? DisplayStarsMaximum; } } From 19efa1cafb33859e7444d981790a5c90c42e3f70 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Fri, 12 Oct 2018 20:55:42 +0200 Subject: [PATCH 0168/5608] Added TestCase, first RepeatPoint now deflates aswell --- osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs | 27 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 + osu.Game.Tests/Visual/TestCaseDeflate.cs | 637 ++++++++++++++++++ 3 files changed, 655 insertions(+), 11 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseDeflate.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs index f5be85158f..a049248021 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -33,6 +33,8 @@ namespace osu.Game.Rulesets.Osu.Mods var h = d.HitObject; + float rescale = 2; + switch (drawable) { case DrawableHitCircle c: @@ -55,6 +57,7 @@ namespace osu.Game.Rulesets.Osu.Mods break; } break; + case DrawableSlider s: using (d.BeginAbsoluteSequence(h.StartTime - h.TimePreempt + 1, true)) { @@ -62,19 +65,21 @@ namespace osu.Game.Rulesets.Osu.Mods var origBodySize = s.Body.Size; var origBodyDrawPos = s.Body.DrawPosition; - s.Body.MoveTo(origBodyDrawPos - new Vector2(origPathWidth), 1) - .Then() - .MoveTo(origBodyDrawPos, h.TimePreempt); - - s.Body.ResizeTo(origBodySize * 2, 1) - .Then() - .ResizeTo(origBodySize, h.TimePreempt); - - s.Body.TransformTo("PathWidth", origPathWidth * 2, 1) - .Then() - .TransformTo("PathWidth", origPathWidth, h.TimePreempt); + // Fits nicely for CS=4, too big on lower CS, too small on higher CS + s.Body.Animate( + b => b.MoveTo(origBodyDrawPos - new Vector2(origPathWidth)).MoveTo(origBodyDrawPos, h.TimePreempt), + b => b.ResizeTo(origBodySize * rescale).ResizeTo(origBodySize, h.TimePreempt), + b => b.TransformTo("PathWidth", origPathWidth * rescale).TransformTo("PathWidth", origPathWidth, h.TimePreempt) + ); } break; + case DrawableRepeatPoint rp: + if (!rp.IsFirstRepeat) + break; + var origSizeRP = rp.Size; + using (d.BeginAbsoluteSequence(h.StartTime - h.TimePreempt + 1, true)) + rp.ResizeTo(origSizeRP * rescale).ResizeTo(origSizeRP, h.TimePreempt); + break; } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index dfe7937e81..65b6b5b004 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -41,6 +41,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }; } + public bool IsFirstRepeat => repeatPoint.RepeatIndex == 0; + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (repeatPoint.StartTime <= Time.Current) diff --git a/osu.Game.Tests/Visual/TestCaseDeflate.cs b/osu.Game.Tests/Visual/TestCaseDeflate.cs new file mode 100644 index 0000000000..8a24e2414c --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseDeflate.cs @@ -0,0 +1,637 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.ComponentModel; +using System.IO; +using System.Text; +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using Decoder = osu.Game.Beatmaps.Formats.Decoder; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Screens.Play; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Tests.Visual +{ + [Description("Player instantiated with an deflate mod.")] + public class TestCaseDeflate : TestCasePlayer + { + protected override IBeatmap CreateBeatmap(Ruleset ruleset) + { + Beatmap beatmap; + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(test_beatmap_data))) + using (var reader = new StreamReader(stream)) + beatmap = Decoder.GetDecoder(reader).Decode(reader); + beatmap.BeatmapInfo.Ruleset = ruleset.RulesetInfo; + beatmap.BeatmapInfo.BaseDifficulty.CircleSize = 4; + return beatmap; + } + + protected override Player CreatePlayer(Ruleset ruleset) + { + Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod(), ruleset.GetAllMods().First(mod => mod is OsuModDeflate) }); + return new ScoreAccessiblePlayer + { + AllowPause = false, + AllowLeadIn = false, + AllowResults = false, + }; + } + + protected override bool ContinueCondition(Player player) => base.ContinueCondition(player) && ((ScoreAccessiblePlayer)player).ScoreProcessor.TotalScore > 0; + + private class ScoreAccessiblePlayer : Player + { + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + } + + private const string test_beatmap_data = + @"osu file format v14 + +[General] +AudioFilename: R4V3 B0Y - S3RL Feat Krystal.mp3 +AudioLeadIn: 0 +PreviewTime: 56176 +Countdown: 0 +SampleSet: Soft +StackLeniency: 0.7 +Mode: 0 +LetterboxInBreaks: 0 +WidescreenStoryboard: 1 + +[Editor] +Bookmarks: 12382,23354,34325,45297,56268,67240,78211,89182,100154,111125,122097,128605,133068,144040,155011,165982,175582 +DistanceSpacing: 1.5 +BeatDivisor: 4 +GridSize: 4 +TimelineZoom: 3.799998 + +[Metadata] +Title:R4V3 B0Y +TitleUnicode:R4V3 B0Y +Artist:S3RL feat Krystal +ArtistUnicode:S3RL feat Krystal +Creator:DeRandom Otaku +Version:FCL's H4RD +Source: +Tags:happy hardcore EMFA music rave boy Shmiklak FCL ByBy ByBy13 ByBy_Chan Marvollo M_a_r_v_o_l_l_o +BeatmapID:1056070 +BeatmapSetID:481451 + +[Difficulty] +HPDrainRate:5 +CircleSize:4 +OverallDifficulty:6 +ApproachRate:7.5 +SliderMultiplier:1.4 +SliderTickRate:1 + +[Events] +//Background and Video events +0,0,'BG.jpg',0,0 +//Break Periods +2,89376,99323 +//Storyboard Layer 0 (Background) +//Storyboard Layer 1 (Fail) +//Storyboard Layer 2 (Pass) +//Storyboard Layer 3 (Foreground) +//Storyboard Sound Samples + +[TimingPoints] +34,342.857142857143,4,1,1,100,1,0 +34,-133.333333333333,4,1,1,100,0,0 +1405,-133.333333333333,4,2,1,70,0,0 +12376,-125,4,2,2,70,0,0 +21976,-100,4,2,2,45,0,0 +23348,-100,4,2,2,85,0,0 +26091,-100,4,2,2,85,0,0 +31576,-100,4,2,2,85,0,0 +34319,-100,4,2,2,85,0,0 +37062,-100,4,2,2,85,0,0 +42462,-100,4,2,2,5,0,0 +42548,-100,4,2,2,85,0,0 +43919,-100,4,2,2,65,0,0 +45291,-100,4,2,2,50,0,0 +50691,-100,4,2,2,5,0,0 +50776,-100,4,2,2,50,0,0 +56262,-100,4,2,2,90,0,1 +65862,-125,4,2,2,90,0,0 +67234,-100,4,2,2,90,0,1 +72719,-100,4,2,2,90,0,1 +76834,-125,4,2,2,45,0,0 +78205,-125,4,2,0,50,0,0 +100148,-125,4,2,2,50,0,0 +100491,-125,4,2,0,50,0,0 +111119,-100,4,2,2,50,0,0 +116091,-100,4,2,2,10,0,0 +116262,-100,4,2,2,50,0,0 +116434,-100,4,2,2,10,0,0 +116605,-100,4,2,2,50,0,0 +121748,-133.333333333333,4,2,2,50,0,0 +122091,-100,4,2,2,50,0,0 +127576,-100,4,2,2,50,0,0 +130319,-90.9090909090909,4,2,2,50,0,0 +131005,-83.3333333333333,4,2,2,50,0,0 +131691,-76.9230769230769,4,2,2,50,0,0 +132376,-133.333333333333,4,2,2,50,0,0 +133062,-100,4,2,2,90,0,1 +135719,-100,4,2,2,5,0,1 +135805,-100,4,2,2,90,0,1 +141205,-100,4,2,2,5,0,1 +141291,-100,4,2,2,90,0,1 +142662,-100,4,2,2,70,0,0 +143691,-100,4,2,2,40,0,0 +144034,-100,4,2,2,90,0,1 +146691,-100,4,2,2,5,0,1 +146776,-100,4,2,2,90,0,1 +152176,-100,4,2,2,5,0,1 +152262,-100,4,2,2,90,0,1 +154662,-100,4,2,2,60,0,1 +155005,-100,4,2,2,75,0,0 +165976,-100,4,2,2,75,0,0 +171462,-133.333333333333,4,2,2,60,0,0 +174205,-153.846153846153,4,2,2,50,0,0 +174891,-153.846153846154,4,2,2,40,0,0 +175576,-100,4,2,2,25,0,0 +176262,-125,4,2,2,25,0,0 +176605,-125,4,2,2,15,0,0 + + +[Colours] + Combo1 : 0,255,255 +Combo2 : 17,255,17 +Combo3 : 0,128,192 +Combo4 : 124,0,249 + +[HitObjects] +138,122,34,6,0,L|133:229,3,105.000004005432,0|0|0|0,2:0|2:0|2:0|2:0,2:2:0:0: +133,226,1405,6,0,L|248:220,1,105.000004005432,2|2,1:2|0:0,0:0:0:0: +339,341,2091,2,0,L|222:338,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: +133,226,2776,2,0,P|128:187|129:158,1,52.5000020027162,2|0,0:0|0:0,0:0:0:0: +188,123,3119,2,0,P|193:84|190:55,1,52.5000020027162,2|0,0:0|0:0,0:0:0:0: +262,34,3462,2,0,P|290:62|366:69,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: +431,74,3976,1,0,0:0:0:0: +496,117,4148,6,0,L|503:229,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: +456,286,4662,1,0,0:0:0:0: +408,349,4834,2,0,L|296:356,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: +172,266,5519,2,0,P|155:216|165:148,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: +206,101,6034,1,0,0:0:0:0: +239,172,6205,2,0,L|361:162,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: +494,260,6891,6,0,B|443:252|443:252|386:267,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: +324,308,7405,1,0,0:0:0:0: +248,287,7576,2,0,L|241:227,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: +169,202,7919,2,0,L|176:142,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: +239,104,8262,2,0,P|282:119|345:101,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: +416,92,8776,1,0,0:0:0:0: +484,132,8948,2,0,L|491:195,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: +445,249,9291,2,0,L|452:312,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: +388,349,9634,6,0,P|354:328|289:335,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: +216,360,10148,1,0,0:0:0:0: +143,328,10319,2,0,L|72:315,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: +102,240,10662,2,0,L|173:227,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: +224,195,11005,5,2,0:0:0:0: +160,148,11176,1,0,0:0:0:0: +233,120,11348,1,2,0:0:0:0: +172,69,11519,1,0,0:0:0:0: +247,45,11691,2,0,P|285:39|314:43,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: +355,95,12034,2,0,P|378:105|399:121,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: +482,162,12376,6,0,P|450:190|445:261,1,112,2|2,0:0|0:0,0:0:0:0: +298,342,13062,2,0,P|296:287|259:247,1,112,2|2,0:0|0:0,0:0:0:0: +132,135,13748,2,0,L|127:62,1,56,2|0,0:0|0:0,0:0:0:0: +209,57,14091,2,0,L|235:-11,1,56,2|0,0:0|0:0,0:0:0:0: +304,41,14434,2,0,P|348:52|380:44,2,56,2|0|2,0:0|0:0|0:0,0:0:0:0: +272,119,14948,1,0,0:0:0:0: +335,173,15119,6,0,L|340:298,1,112,2|2,0:0|0:0,0:0:0:0: +274,339,15634,1,0,0:0:0:0: +216,278,15805,2,0,B|165:262|165:262|86:278,1,112,2|2,0:0|0:0,0:0:0:0: +5,139,16491,2,0,B|56:123|56:123|135:139,1,112,2|2,0:0|0:0,0:0:0:0: +189,171,17005,1,0,0:0:0:0: +257,123,17176,2,0,L|379:117,1,112,2|2,0:0|0:0,0:0:0:0: +434,171,17691,1,0,0:0:0:0: +434,171,17776,1,0,0:0:0:0: +434,171,17862,6,0,P|450:218|426:288,1,112,2|2,0:0|0:0,0:0:0:0: +356,308,18376,1,0,0:0:0:0: +288,261,18548,2,0,L|207:258,1,56,2|0,0:0|0:0,0:0:0:0: +170,316,18891,2,0,L|89:319,1,56,2|0,0:0|0:0,0:0:0:0: +38,234,19234,2,0,P|110:237|160:210,1,112,2|2,0:0|0:0,0:0:0:0: +179,144,19748,1,0,0:0:0:0: +104,105,19919,2,0,L|100:31,1,56,2|0,0:0|0:0,0:0:0:0: +179,18,20262,2,0,L|210:8,3,28,2|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: +247,8,20605,6,0,P|236:48|268:122,1,112,2|2,0:0|0:0,0:0:0:0: +311,178,21119,1,0,0:0:0:0: +288,259,21291,2,0,L|286:330,1,56,2|0,0:0|0:0,0:0:0:0: +363,349,21634,2,0,L|361:293,1,56,2|0,0:0|0:0,0:0:0:0: +408,231,21976,5,0,0:0:0:0: +462,125,23005,2,0,L|469:80,3,35 +499,48,23348,6,0,L|348:53,1,140,4|0,1:2|1:0,0:0:0:0: +178,161,24034,1,0,1:0:0:0: +244,241,24205,1,0,0:0:0:0: +244,241,24291,2,0,L|365:231,1,105,0|0,0:0|0:0,0:0:0:0: +434,292,24719,2,0,P|423:335|439:379,1,70,0|0,1:0|0:0,0:0:0:0: +325,333,25062,2,0,P|329:298|319:265,1,70,0|0,1:0|0:0,0:0:0:0: +250,185,25405,1,0,1:0:0:0: +308,135,25576,1,0,0:0:0:0: +213,111,25748,2,0,L|203:64,2,35,0|0|0,1:0|0:0|0:0,0:0:0:0: +146,183,26091,6,0,L|44:180,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: +202,370,26776,1,0,1:0:0:0: +253,288,26948,1,0,0:0:0:0: +253,288,27034,2,0,B|236:237|236:237|246:176,1,105,0|0,0:0|0:0,0:0:0:0: +318,112,27462,2,0,L|466:102,2,140,0|0|0,1:0|1:0|1:0,0:0:0:0: +139,224,28491,2,0,P|110:228|77:229,3,35,0|0|0|0,1:0|0:0|0:0|0:0,0:0:0:0: +69,267,28834,6,0,P|131:258|212:289,1,140,0|0,1:0|1:0,0:0:0:0: +402,217,29519,1,0,1:0:0:0: +303,180,29691,1,0,0:0:0:0: +303,180,29776,2,0,P|288:123|299:60,1,105,0|0,0:0|0:0,0:0:0:0: +200,26,30205,2,0,P|155:51|54:21,2,140,0|0|0,1:0|1:0|1:0,0:0:0:0: +166,125,31062,1,0,0:0:0:0: +242,197,31234,2,0,L|246:257,3,35,0|0|0|0,1:0|0:0|0:0|0:0,0:0:0:0: +293,248,31576,6,0,L|139:246,1,140,0|0,1:0|1:0,0:0:0:0: +66,307,32091,1,0,0:0:0:0: +71,202,32262,2,0,L|84:35,1,140,0|0,1:0|1:0,0:0:0:0: +289,23,32948,5,0,0:0:0:0: +218,53,33119,1,0,0:0:0:0: +176,118,33291,2,0,P|174:157|190:205,2,70,0|0|0,0:0|0:0|0:0,0:0:0:0: +176,118,34148,1,8,0:0:0:0: +265,172,34319,6,0,L|418:174,1,140,4|0,1:2|1:0,0:0:0:0: +440,273,34834,1,0,0:0:0:0: +337,253,35005,2,0,P|281:253|235:345,1,140,0|0,1:0|1:0,0:0:0:0: +232,315,35519,1,0,0:0:0:0: +130,341,35691,2,0,L|36:328,1,70,0|0,1:0|0:0,0:0:0:0: +95,231,36034,2,0,L|15:179,1,70,0|0,1:0|0:0,0:0:0:0: +110,119,36376,2,0,L|59:38,1,70,0|0,1:0|0:0,0:0:0:0: +185,0,36719,1,0,1:0:0:0: +185,0,36805,2,0,L|193:69,1,70,0|0,0:0|0:0,0:0:0:0: +224,85,37062,6,0,L|307:102,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: +262,183,37576,1,0,0:0:0:0: +185,253,37748,2,0,P|117:286|52:236,1,140,0|0,1:0|1:0,0:0:0:0: +116,166,38262,1,0,0:0:0:0: +185,253,38434,2,0,P|222:247|281:246,1,70,0|0,1:0|0:0,0:0:0:0: +344,299,38776,2,0,P|380:310|433:333,1,70,0|0,1:0|0:0,0:0:0:0: +500,267,39119,1,0,1:0:0:0: +379,96,39462,2,0,L|374:53,3,35,0|0|0|0,1:0|0:0|0:0|0:0,0:0:0:0: +395,12,39805,6,0,L|224:2,1,140,0|0,1:0|1:0,0:0:0:0: +172,69,40319,1,0,0:0:0:0: +267,112,40491,2,0,P|250:151|275:259,1,140,0|0,1:0|1:0,0:0:0:0: +264,244,41005,1,0,0:0:0:0: +182,309,41176,2,0,P|155:264|127:236,1,70,0|0,1:0|0:0,0:0:0:0: +69,176,41519,2,0,P|96:131|124:103,1,70,0|0,1:0|0:0,0:0:0:0: +202,71,41862,1,0,1:0:0:0: +179,173,42034,1,0,0:0:0:0: +137,37,42205,1,0,1:0:0:0: +137,37,42291,2,0,L|35:33,1,70,0|0,0:0|0:0,0:0:0:0: +23,63,42548,6,0,B|6:161|6:161|23:218,1,140,0|0,1:0|1:0,0:0:0:0: +62,295,43062,1,0,0:0:0:0: +141,226,43234,1,0,1:0:0:0: +168,348,43405,1,0,0:0:0:0: +168,348,43491,2,0,L|295:355,1,105,0|0,0:0|0:0,0:0:0:0: +367,309,43919,1,0,0:0:0:0: +201,89,45291,6,0,L|279:83,1,70,2|0,0:0|0:0,0:0:0:0: +201,162,45634,2,0,L|279:156,1,70,2|0,0:0|0:0,0:0:0:0: +202,235,45976,2,0,L|280:229,1,70,2|0,0:0|0:0,0:0:0:0: +202,308,46319,2,0,L|280:302,1,70,2|0,0:0|0:0,0:0:0:0: +411,345,46662,6,0,P|368:344|311:362,1,70,2|0,0:0|0:0,0:0:0:0: +399,261,47005,2,0,P|360:241|301:234,1,70,2|0,0:0|0:0,0:0:0:0: +427,187,47348,2,0,P|400:153|349:121,1,70,2|0,0:0|0:0,0:0:0:0: +484,134,47691,2,0,P|473:91|441:41,1,70,2|0,0:0|0:0,0:0:0:0: +348,30,48034,6,0,B|308:39|308:39|264:31,1,70,2|0,0:0|0:0,0:0:0:0: +205,108,48376,2,0,B|245:117|245:117|289:109,1,70,2|0,0:0|0:0,0:0:0:0: +345,188,48719,2,0,B|305:197|305:197|261:189,1,70,2|0,0:0|0:0,0:0:0:0: +199,263,49062,2,0,B|239:272|239:272|283:264,1,70,2|0,0:0|0:0,0:0:0:0: +345,188,49405,6,0,L|354:101,1,70,2|0,0:0|0:0,0:0:0:0: +252,150,49748,2,0,L|243:63,1,70,2|0,0:0|0:0,0:0:0:0: +146,118,50091,2,0,P|123:75|90:43,1,70,2|0,0:0|0:0,0:0:0:0: +8,28,50434,2,0,L|6:177,1,140,10|2,0:0|0:0,0:0:0:0: +93,242,50948,5,0,0:0:0:0: +93,242,51119,2,0,L|190:238,1,70,2|0,0:0|0:0,0:0:0:0: +239,311,51462,2,0,L|308:313,1,70,2|0,0:0|0:0,0:0:0:0: +393,250,51805,1,2,0:0:0:0: +429,348,51976,1,0,0:0:0:0: +429,348,52319,5,0,0:0:0:0: +486,259,52491,2,0,P|487:222|486:172,1,70,2|0,0:0|0:0,0:0:0:0: +382,170,52834,2,0,P|367:136|345:91,1,70,2|0,0:0|0:0,0:0:0:0: +261,55,53176,1,2,0:0:0:0: +242,158,53348,1,0,0:0:0:0: +242,158,53519,6,0,L|70:148,1,140,8|8,0:0|0:0,0:0:0:0: +196,338,54205,2,0,L|205:214,2,105,8|8|8,0:0|0:0|0:0,0:0:0:0: +296,304,54891,5,8,0:0:0:0: +296,304,55062,1,8,0:0:0:0: +327,203,55234,1,8,0:0:0:0: +327,203,55405,1,8,0:0:0:0: +355,102,55576,2,0,L|342:44,3,35,8|8|8|8,0:0|0:0|0:0|0:0,0:0:0:0: +365,18,55919,2,0,P|305:35|246:17,1,105,0|0,0:0|0:0,0:0:0:0: +230,40,56262,5,0,1:0:0:0: +285,129,56434,1,0,0:0:0:0: +223,213,56605,2,0,L|134:207,1,70,0|0,1:0|0:0,0:0:0:0: +66,267,56948,2,0,P|55:317|63:357,1,70,0|0,1:0|0:0,0:0:0:0: +156,369,57291,1,0,1:0:0:0: +156,369,57462,1,0,0:0:0:0: +318,236,57805,5,0,0:0:0:0: +250,155,57976,2,0,L|254:68,1,70,0|0,1:0|0:0,0:0:0:0: +349,42,58319,2,0,P|397:52|447:48,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: +253,85,58834,1,0,0:0:0:0: +169,21,59005,6,0,L|22:18,1,140,0|0,1:0|1:0,0:0:0:0: +9,121,59519,1,0,0:0:0:0: +53,216,59691,1,0,1:0:0:0: +53,216,59862,2,0,L|130:212,1,70,0|0,0:0|1:0,0:0:0:0: +220,252,60205,1,0,0:0:0:0: +173,158,60376,5,0,1:0:0:0: +173,158,60462,1,0,0:0:0:0: +173,158,60548,2,0,P|169:112|176:70,1,70,0|0,0:0|1:0,0:0:0:0: +253,22,60891,1,0,0:0:0:0: +302,114,61062,2,0,L|450:111,1,140,2|2,0:0|0:0,0:0:0:0: +503,196,61576,1,8,0:0:0:0: +503,196,61748,5,0,1:0:0:0: +411,247,61919,2,0,L|406:328,1,70,0|0,0:0|1:0,0:0:0:0: +317,372,62262,1,0,0:0:0:0: +216,340,62434,2,0,L|208:247,1,70,0|0,1:0|0:0,0:0:0:0: +250,173,62776,2,0,P|263:124|255:77,1,70,0|0,1:0|0:0,0:0:0:0: +58,51,63291,5,0,0:0:0:0: +18,148,63462,2,0,P|28:185|22:232,1,70,0|0,1:0|0:0,0:0:0:0: +17,321,63805,2,0,P|51:322|85:312,1,70,0|0,1:0|0:0,0:0:0:0: +172,254,64148,1,0,1:0:0:0: +172,254,64319,1,0,0:0:0:0: +240,334,64491,6,0,B|300:320|300:320|393:333,1,140,0|0,1:0|1:0,0:0:0:0: +466,274,65005,1,0,0:0:0:0: +408,186,65176,2,0,P|401:138|406:98,1,70,0|0,1:0|0:0,0:0:0:0: +298,101,65519,2,0,P|305:53|300:13,1,70,0|0,1:0|0:0,0:0:0:0: +303,31,65862,6,0,L|177:28,1,112,2|0,0:0|0:0,0:0:0:0: +124,79,66376,1,0,0:0:0:0: +200,113,66548,2,0,L|261:111,1,56 +134,161,66891,2,0,L|126:196,3,28,0|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: +89,224,67234,6,0,L|203:220,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: +239,260,67576,2,0,P|292:270|365:248,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: +390,227,67919,2,0,L|400:133,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: +372,69,68262,1,0,1:0:0:0: +251,140,68491,1,0,0:0:0:0: +251,140,68605,6,0,P|194:130|131:146,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: +105,180,68948,2,0,B|97:228|97:228|115:297,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: +166,310,69291,1,0,1:0:0:0: +275,223,69519,1,0,0:0:0:0: +332,263,69634,2,0,L|436:258,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: +499,298,69976,6,0,P|507:243|449:180,1,140,0|0,1:0|1:0,0:0:0:0: +328,131,70548,1,0,0:0:0:0: +278,180,70662,2,0,P|230:192|182:178,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: +122,155,71005,2,0,L|28:151,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: +11,219,71348,6,0,P|2:248|0:281,2,46.6666666666667,0|0|0,1:0|0:0|0:0,0:0:0:0: +28,151,71691,2,0,B|44:105|44:105|26:42,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: +88,20,72034,2,0,L|243:16,1,140,2|2,0:0|0:0,0:0:0:0: +227,16,72719,6,0,P|215:75|218:109,1,70,0|0,1:0|0:0,0:0:0:0: +299,148,73062,2,0,P|311:207|308:241,1,70,0|0,1:0|0:0,0:0:0:0: +260,308,73405,1,0,1:0:0:0: +260,308,73576,1,0,0:0:0:0: +361,278,73748,2,0,L|463:273,1,70,0|0,1:0|0:0,0:0:0:0: +494,74,74262,5,0,0:0:0:0: +430,157,74434,2,0,P|394:163|338:153,1,70,0|0,1:0|0:0,0:0:0:0: +280,93,74776,2,0,P|245:90|210:96,1,70,0|0,1:0|0:0,0:0:0:0: +121,152,75119,2,0,L|111:235,1,70,0|0,1:0|0:0,0:0:0:0: +61,328,75462,6,0,P|117:309|214:344,1,140,0|0,1:0|1:0,0:0:0:0: +296,303,75976,1,0,0:0:0:0: +213,237,76148,2,0,L|208:148,1,70,0|0,1:0|0:0,0:0:0:0: +307,204,76491,2,0,L|312:115,1,70,0|0,1:0|0:0,0:0:0:0: +270,59,76834,6,0,P|241:55|195:64,1,56,0|0,0:0|0:0,0:0:0:0: +172,130,77176,2,0,P|144:138|106:166,1,56 +65,215,77519,2,0,B|61:260|61:260|76:287|76:287|71:331,1,112 +71,322,78205,6,0,P|130:294|193:287,1,112 +288,161,78891,2,0,P|229:133|166:126,1,112 +22,84,79576,6,0,L|18:20,1,56 +100,46,79919,2,0,P|136:51|173:39,1,56,0|0,0:0|0:0,0:0:0:0: +234,19,80262,2,0,B|280:36|280:36|365:20,1,112,0|0,0:0|0:0,0:0:0:0: +341,24,80948,6,0,L|332:160,1,112 +333,135,81462,1,0,0:0:0:0: +277,198,81634,2,0,P|228:183|152:187,1,112,0|0,0:0|0:0,0:0:0:0: +64,315,82319,6,0,L|61:191,1,112 +61,203,82834,1,0,0:0:0:0: +107,133,83005,2,0,P|119:105|82:13,1,112,0|0,0:0|0:0,0:0:0:0: +100,28,83691,6,0,L|180:24,1,56,2|0,0:0|0:0,0:0:0:0: +224,74,84034,1,0,0:0:0:0: +224,74,84205,1,0,0:0:0:0: +289,21,84376,2,0,P|325:17|367:28,1,56,2|0,0:0|0:0,0:0:0:0: +369,100,84719,2,0,P|403:111|436:139,1,56,2|0,0:0|0:0,0:0:0:0: +481,208,85062,6,0,L|414:204,1,56,2|0,0:0|0:0,0:0:0:0: +367,266,85405,1,0,0:0:0:0: +367,266,85576,1,0,0:0:0:0: +307,206,85748,2,0,P|298:175|299:138,1,56,2|0,0:0|0:0,0:0:0:0: +213,154,86091,2,0,P|217:122|234:88,1,56,2|0,0:0|0:0,0:0:0:0: +168,18,86434,6,0,B|87:16|87:16|123:49,1,112,2|0,0:0|0:0,0:0:0:0: +81,116,86948,1,0,0:0:0:0: +117,191,87119,2,0,P|155:198|188:192,1,56,2|0,0:0|0:0,0:0:0:0: +230,256,87462,2,0,P|257:249|285:250,1,56,2|0,0:0|0:0,0:0:0:0: +359,290,87805,5,2,0:0:0:0: +359,290,87976,1,0,0:0:0:0: +389,211,88148,1,0,0:0:0:0: +389,211,88319,1,0,0:0:0:0: +466,177,88491,2,0,B|483:139|483:139|472:54,2,112,2|2|4,0:0|0:0|0:3,0:0:0:0: +185,144,100148,6,0,P|137:124|63:139,1,112,4|2,1:2|0:0,0:0:0:0: +35,189,100662,1,2,0:0:0:0: +35,189,100834,2,0,L|27:318,1,112,2|2,0:0|0:0,0:0:0:0: +164,352,101519,1,2,0:3:0:0: +297,294,101862,2,0,L|428:300,2,112,2|2|2,0:0|0:0|0:0,0:0:0:0: +281,222,102719,1,2,0:0:0:0: +305,153,102891,5,2,0:3:0:0: +225,274,103234,2,0,P|183:292|107:272,2,112,2|2|2,0:0|0:0|0:0,0:0:0:0: +305,153,104262,1,2,0:3:0:0: +186,67,104605,2,0,B|148:52|148:52|54:66,2,112,2|2|2,0:0|0:0|0:0,0:0:0:0: +256,48,105462,1,2,0:0:0:0: +326,30,105634,5,2,0:3:0:0: +428,132,105976,2,0,L|434:266,2,112,2|2|2,0:0|0:0|0:0,0:0:0:0: +308,216,107005,1,2,0:3:0:0: +189,131,107348,2,0,P|147:120|77:142,2,112,2|2|2,0:0|0:0|0:0,0:0:0:0: +230,190,108205,1,2,0:0:0:0: +233,262,108376,6,0,L|239:322,1,56,2|0,0:3|0:0,0:0:0:0: +311,325,108719,2,0,L|316:269,1,56,2|2,0:0|0:0,0:0:0:0: +369,219,109062,2,0,L|361:107,2,112,2|2|0,0:0|0:0|0:0,0:0:0:0: +81,124,110776,2,0,L|92:77,3,28,0|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: +77,52,111119,6,0,L|238:47,1,140,2|2,0:0|0:0,0:0:0:0: +290,102,111634,1,0,0:0:0:0: +349,33,111805,2,0,L|435:29,1,70,2|0,0:0|0:0,0:0:0:0: +439,118,112148,2,0,L|518:150,1,70,2|0,0:0|0:0,0:0:0:0: +426,309,112662,5,0,0:0:0:0: +379,230,112834,2,0,P|338:227|295:238,1,70,2|0,0:0|0:0,0:0:0:0: +237,286,113176,1,2,0:0:0:0: +237,286,113348,1,0,0:0:0:0: +172,221,113519,2,0,L|165:128,1,70,2|0,0:0|0:0,0:0:0:0: +166,151,114034,5,0,0:0:0:0: +237,94,114205,2,0,P|278:84|334:88,1,70,2|0,0:0|0:0,0:0:0:0: +375,142,114548,2,0,P|409:143|443:152,1,70,2|0,0:0|0:0,0:0:0:0: +496,226,114891,2,0,L|502:313,1,70,2|0,0:0|0:0,0:0:0:0: +434,358,115234,5,2,0:0:0:0: +434,358,115319,1,0,0:0:0:0: +434,358,115405,2,0,L|333:347,2,70,0|2|0,0:0|0:0|0:0,0:0:0:0: +398,273,115919,2,0,L|411:117,1,140,2|2,0:0|0:0,0:0:0:0: +255,34,116605,6,0,P|211:59|119:19,1,140,2|2,0:0|0:0,0:0:0:0: +45,68,117119,1,0,0:0:0:0: +108,133,117291,2,0,L|115:214,1,70,2|0,0:0|0:0,0:0:0:0: +197,240,117634,2,0,L|190:321,1,70,2|0,0:0|0:0,0:0:0:0: +363,369,118148,5,0,0:0:0:0: +332,283,118319,2,0,P|329:226|345:193,1,70,2|0,0:0|0:0,0:0:0:0: +386,140,118662,1,2,0:0:0:0: +386,140,118834,1,0,0:0:0:0: +331,67,119005,2,0,L|239:63,1,70,2|0,0:0|0:0,0:0:0:0: +261,63,119519,5,0,0:0:0:0: +198,129,119691,2,0,P|159:137|111:126,1,70,2|0,0:0|0:0,0:0:0:0: +68,201,120034,2,0,P|60:240|71:288,1,70,2|0,0:0|0:0,0:0:0:0: +128,333,120376,2,0,L|221:325,1,70,2|0,0:0|0:0,0:0:0:0: +282,293,120719,5,2,0:0:0:0: +282,293,121062,1,2,0:0:0:0: +282,293,121405,1,2,0:0:0:0: +282,293,121748,2,0,L|383:298,1,78.7500030040742,2|0,0:0|0:0,0:0:0:0: +403,281,122091,6,0,L|395:114,1,140,0|0,1:0|0:0,0:0:0:0: +221,91,122776,2,0,L|214:230,1,140,0|0,0:0|0:0,0:0:0:0: +354,347,123462,2,0,P|389:364|474:287,1,140,0|0,0:0|0:0,0:0:0:0: +329,202,124148,2,0,P|294:185|209:262,1,140,0|0,0:0|0:0,0:0:0:0: +68,341,124834,6,0,L|59:269,1,70,0|0,0:0|0:0,0:0:0:0: +139,313,125176,2,0,L|130:241,1,70,0|0,0:0|0:0,0:0:0:0: +211,286,125519,2,0,L|202:214,1,70,0|0,0:0|0:0,0:0:0:0: +282,260,125862,2,0,L|273:188,1,70,0|0,0:0|0:0,0:0:0:0: +192,108,126205,6,0,P|162:100|107:103,1,70 +172,192,126548,2,0,P|142:181|87:179,1,70 +146,274,126891,2,0,P|117:260|63:254,1,70 +110,354,127234,2,0,P|83:338|29:327,1,70 +150,279,127576,5,0,0:0:0:0: +150,279,127748,1,0,0:0:0:0: +242,327,127919,1,0,0:0:0:0: +242,327,128091,1,0,0:0:0:0: +285,232,128262,2,0,L|379:227,1,70,0|0,0:0|0:0,0:0:0:0: +422,166,128605,2,0,L|491:169,1,70,0|0,0:0|0:0,0:0:0:0: +441,76,128948,5,0,0:0:0:0: +441,76,129119,1,0,0:0:0:0: +388,150,129291,1,0,0:0:0:0: +388,150,129462,1,0,0:0:0:0: +338,73,129634,2,0,P|286:69|238:75,1,70,0|0,0:0|0:0,0:0:0:0: +210,140,129976,2,0,P|175:141|140:137,1,70,0|0,0:0|0:0,0:0:0:0: +79,205,130319,6,0,L|68:260,3,38.5000011749268,0|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: +108,267,130662,2,0,L|115:319,3,38.5000011749268,0|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: +145,334,131005,6,0,P|169:324|197:323,3,41.9999987182618,0|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: +220,339,131348,2,0,P|237:335|263:321,3,41.9999987182618,0|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: +289,300,131691,6,0,L|294:258,14,22.7499989585877,0|0|0|0|0|0|0|0|0|0|0|0|0|0|0,0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0,0:0:0:0: +314,240,132376,6,0,B|356:235|356:235|374:221|374:221|433:213,1,105.000004005432,0|0,0:0|0:0,0:0:0:0: +444,142,132891,1,0,0:0:0:0: +444,142,132976,1,0,0:0:0:0: +444,142,133062,6,0,B|461:90|461:90|446:-12,1,140,4|0,1:2|1:0,0:0:0:0: +238,15,133748,1,0,1:0:0:0: +181,103,133919,1,0,0:0:0:0: +181,103,134005,2,0,L|310:99,1,105,0|0,0:0|0:0,0:0:0:0: +366,167,134434,6,0,P|378:224|363:254,1,70,0|0,1:0|0:0,0:0:0:0: +276,270,134776,2,0,P|262:326|236:347,1,70,0|0,1:0|0:0,0:0:0:0: +151,356,135119,1,0,1:0:0:0: +61,300,135291,1,0,0:0:0:0: +164,254,135462,1,0,1:0:0:0: +164,254,135548,2,0,L|174:156,1,70 +195,162,135805,6,0,P|243:178|290:168,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: +148,67,136319,1,0,0:0:0:0: +148,67,136491,1,0,1:0:0:0: +247,98,136662,1,0,0:0:0:0: +247,98,136748,2,0,B|286:80|286:80|372:100,1,105,0|0,0:0|0:0,0:0:0:0: +432,154,137176,6,0,L|437:294,2,140,0|0|0,1:0|1:0|1:0,0:0:0:0: +307,324,138205,2,0,P|282:331|245:328,3,35,0|0|0|0,1:0|0:0|0:0|0:0,0:0:0:0: +246,309,138548,6,0,P|201:298|114:358,1,140,0|0,1:0|1:0,0:0:0:0: +19,157,139234,1,0,1:0:0:0: +113,112,139405,1,0,0:0:0:0: +113,112,139491,2,0,P|153:134|236:108,1,105,0|0,0:0|0:0,0:0:0:0: +310,159,139919,6,0,P|276:209|172:226,1,140,0|0,1:0|1:0,0:0:0:0: +387,334,140605,2,0,L|381:238,1,70,0|0,1:0|0:0,0:0:0:0: +450,183,140948,1,0,1:0:0:0: +450,183,141034,2,0,L|456:87,1,70,0|0,0:0|0:0,0:0:0:0: +434,85,141291,6,0,P|399:71|337:77,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: +468,292,141976,1,0,1:0:0:0: +377,238,142148,1,0,0:0:0:0: +377,238,142234,2,0,P|327:245|261:229,1,105 +178,185,142662,5,2,0:0:0:0: +178,185,143005,1,2,0:0:0:0: +178,185,143348,1,0,0:0:0:0: +178,185,143691,2,0,L|171:266,1,70,0|0,0:0|0:0,0:0:0:0: +171,254,144034,6,0,P|224:241|320:257,1,140,4|0,1:2|1:0,0:0:0:0: +408,282,144548,1,0,0:0:0:0: +480,205,144719,1,0,1:0:0:0: +433,116,144891,1,0,0:0:0:0: +433,116,144976,2,0,L|443:2,1,105,0|0,0:0|0:0,0:0:0:0: +337,69,145405,6,0,P|303:79|242:60,1,70,0|0,1:0|0:0,0:0:0:0: +172,116,145748,2,0,L|86:103,1,70,0|0,1:0|0:0,0:0:0:0: +38,188,146091,1,0,1:0:0:0: +38,188,146262,1,0,0:0:0:0: +110,264,146434,1,0,1:0:0:0: +110,264,146519,2,0,L|196:251,1,70,0|0,0:0|0:0,0:0:0:0: +208,269,146776,6,0,P|246:279|300:266,1,70,0|0,1:0|0:0,0:0:0:0: +369,227,147119,1,0,1:0:0:0: +369,227,147462,1,0,1:0:0:0: +312,138,147634,1,0,0:0:0:0: +312,138,147719,2,0,P|302:86|316:15,1,105,0|0,0:0|0:0,0:0:0:0: +210,71,148148,6,0,B|159:84|159:84|45:57,2,140,0|0|0,1:0|1:0|1:0,0:0:0:0: +410,132,149176,2,0,P|421:151|426:191,3,35,0|0|0|0,1:0|0:0|0:0|0:0,0:0:0:0: +458,203,149519,6,0,P|408:195|334:253,1,140,0|0,1:0|1:0,0:0:0:0: +232,232,150034,1,0,0:0:0:0: +309,162,150205,1,0,1:0:0:0: +192,144,150376,1,0,0:0:0:0: +192,144,150462,2,0,L|188:19,1,105,0|0,0:0|0:0,0:0:0:0: +112,155,150891,6,0,P|139:204|239:212,1,140,0|0,1:0|1:0,0:0:0:0: +216,221,151405,1,0,0:0:0:0: +296,288,151576,2,0,L|398:280,1,70,0|0,1:0|0:0,0:0:0:0: +445,213,151919,1,0,1:0:0:0: +445,213,152005,2,0,L|452:111,1,70,0|0,0:0|0:0,0:0:0:0: +434,113,152262,6,0,P|428:66|434:17,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: +352,180,152776,1,0,0:0:0:0: +352,180,152948,2,0,B|287:163|287:163|183:186,1,140,0|0,1:0|1:0,0:0:0:0: +215,178,153634,6,0,P|163:175|121:181,1,70,0|0,1:0|0:0,0:0:0:0: +106,274,153976,2,0,L|200:277,1,70,0|0,1:0|0:0,0:0:0:0: +264,329,154319,1,0,1:0:0:0: +264,329,154662,1,0,0:0:0:0: +360,286,154834,2,0,L|365:255,2,17.5,0|0|0,0:0|0:0|0:0,0:0:0:0: +376,312,155005,6,0,L|542:302,1,140,4|0,1:2|1:0,0:0:0:0: +460,213,155519,1,0,0:0:0:0: +460,213,155691,2,0,L|466:132,1,70,0|0,1:0|0:0,0:0:0:0: +363,113,156034,2,0,L|357:32,1,70,0|0,1:0|0:0,0:0:0:0: +253,34,156376,6,0,P|224:40|168:26,1,70,0|0,1:0|0:0,0:0:0:0: +101,98,156719,1,0,1:0:0:0: +101,98,156891,1,0,0:0:0:0: +190,152,157062,2,0,L|195:247,1,70,0|0,1:0|0:0,0:0:0:0: +290,274,157405,2,0,P|303:225|295:182,1,70,0|0,1:0|0:0,0:0:0:0: +271,105,157748,6,0,B|354:84|354:84|425:103,1,140,0|0,1:0|1:0,0:0:0:0: +484,169,158262,1,0,0:0:0:0: +484,169,158434,2,0,P|492:218|484:257,1,70,0|0,1:0|0:0,0:0:0:0: +396,286,158776,2,0,P|388:335|396:374,1,70,0|0,1:0|0:0,0:0:0:0: +285,341,159119,5,0,1:0:0:0: +285,341,159291,1,0,0:0:0:0: +210,267,159462,2,0,L|214:175,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: +129,334,159976,1,0,0:0:0:0: +51,262,160148,2,0,P|40:217|43:169,1,70,0|0,1:0|0:0,0:0:0:0: +125,104,160491,6,0,L|298:97,1,140,0|0,1:0|1:0,0:0:0:0: +341,170,161005,1,0,0:0:0:0: +373,70,161176,2,0,L|377:-8,1,70,0|0,1:0|0:0,0:0:0:0: +468,51,161519,1,0,1:0:0:0: +468,51,161691,1,0,0:0:0:0: +424,146,161862,6,0,P|419:203|429:235,1,70,0|0,1:0|0:0,0:0:0:0: +467,309,162205,2,0,L|388:311,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: +421,214,162719,1,0,0:0:0:0: +332,271,162891,2,0,P|321:309|343:361,1,70,0|0,1:0|0:0,0:0:0:0: +225,359,163234,6,0,P|162:331|86:357,1,140,0|0,1:0|1:0,0:0:0:0: +26,270,163748,1,0,0:0:0:0: +26,270,163919,2,0,L|30:169,1,70,0|0,1:0|0:0,0:0:0:0: +112,136,164262,2,0,L|108:35,1,70,0|0,1:0|0:0,0:0:0:0: +207,103,164605,6,0,P|272:122|351:76,2,140,0|0|0,1:0|1:0|1:0,0:0:0:0: +291,296,165634,1,0,1:0:0:0: +364,221,165805,1,8,0:0:0:0: +364,221,165891,1,0,0:0:0:0: +364,221,165976,6,0,P|373:159|328:87,1,140,4|0,1:2|1:0,0:0:0:0: +175,93,166662,2,0,P|140:152|148:221,1,140,0|0,1:0|1:0,0:0:0:0: +256,356,167348,2,0,L|256:212,1,140,0|0,1:0|1:0,0:0:0:0: +152,88,168034,1,0,1:0:0:0: +360,88,168376,1,0,1:0:0:0: +284,300,168719,6,0,P|216:308|157:273,1,140,0|0,1:0|1:0,0:0:0:0: +157,111,169405,2,0,P|216:76|285:84,1,140,0|0,1:0|1:0,0:0:0:0: +420,192,170091,2,0,L|276:192,1,140,0|0,1:0|1:0,0:0:0:0: +152,296,170777,1,0,1:0:0:0: +152,88,171119,1,0,1:0:0:0: +152,88,171291,1,0,0:0:0:0: +152,88,171462,6,0,L|264:88,1,105.000004005432,6|2,0:0|0:0,0:0:0:0: +392,176,172148,2,0,L|280:176,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: +160,272,172834,2,0,L|272:272,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: +400,352,173519,2,0,L|288:352,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: +105,324,174205,6,0,P|85:285|89:219,1,90.9999958343508,2|2,0:0|0:0,0:0:0:0: +95,219,174719,1,0,0:0:0:0: +103,197,174891,2,0,L|99:88,1,90.9999958343508,2|2,0:0|0:0,0:0:0:0: +240,73,175576,5,0,0:0:0:0: +265,106,175919,1,0,0:0:0:0: +279,136,176262,2,0,B|314:129|351:139|351:139|329:100,1,112"; + } +} From a876beeadaa5123a0ae148eb9e16a8a29765d96a Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Fri, 12 Oct 2018 21:34:24 +0200 Subject: [PATCH 0169/5608] Variable adjustments --- osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs index a049248021..2638d5bf78 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Mods var h = d.HitObject; - float rescale = 2; + const float rescale = 2; switch (drawable) { @@ -76,9 +76,9 @@ namespace osu.Game.Rulesets.Osu.Mods case DrawableRepeatPoint rp: if (!rp.IsFirstRepeat) break; - var origSizeRP = rp.Size; + var origSizeRp = rp.Size; using (d.BeginAbsoluteSequence(h.StartTime - h.TimePreempt + 1, true)) - rp.ResizeTo(origSizeRP * rescale).ResizeTo(origSizeRP, h.TimePreempt); + rp.ResizeTo(origSizeRp * rescale).ResizeTo(origSizeRp, h.TimePreempt); break; } } From f087c43b49c10fd99a0d3822a97c9a4dc6ae7025 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Fri, 12 Oct 2018 22:31:35 +0200 Subject: [PATCH 0170/5608] Nvm about the new TestCase :^) --- osu.Game.Tests/Visual/TestCaseDeflate.cs | 637 ----------------------- 1 file changed, 637 deletions(-) delete mode 100644 osu.Game.Tests/Visual/TestCaseDeflate.cs diff --git a/osu.Game.Tests/Visual/TestCaseDeflate.cs b/osu.Game.Tests/Visual/TestCaseDeflate.cs deleted file mode 100644 index 8a24e2414c..0000000000 --- a/osu.Game.Tests/Visual/TestCaseDeflate.cs +++ /dev/null @@ -1,637 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.ComponentModel; -using System.IO; -using System.Text; -using System.Linq; -using osu.Game.Beatmaps; -using osu.Game.Rulesets; -using Decoder = osu.Game.Beatmaps.Formats.Decoder; -using osu.Game.Rulesets.Osu.Mods; -using osu.Game.Screens.Play; -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Tests.Visual -{ - [Description("Player instantiated with an deflate mod.")] - public class TestCaseDeflate : TestCasePlayer - { - protected override IBeatmap CreateBeatmap(Ruleset ruleset) - { - Beatmap beatmap; - using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(test_beatmap_data))) - using (var reader = new StreamReader(stream)) - beatmap = Decoder.GetDecoder(reader).Decode(reader); - beatmap.BeatmapInfo.Ruleset = ruleset.RulesetInfo; - beatmap.BeatmapInfo.BaseDifficulty.CircleSize = 4; - return beatmap; - } - - protected override Player CreatePlayer(Ruleset ruleset) - { - Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod(), ruleset.GetAllMods().First(mod => mod is OsuModDeflate) }); - return new ScoreAccessiblePlayer - { - AllowPause = false, - AllowLeadIn = false, - AllowResults = false, - }; - } - - protected override bool ContinueCondition(Player player) => base.ContinueCondition(player) && ((ScoreAccessiblePlayer)player).ScoreProcessor.TotalScore > 0; - - private class ScoreAccessiblePlayer : Player - { - public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; - } - - private const string test_beatmap_data = - @"osu file format v14 - -[General] -AudioFilename: R4V3 B0Y - S3RL Feat Krystal.mp3 -AudioLeadIn: 0 -PreviewTime: 56176 -Countdown: 0 -SampleSet: Soft -StackLeniency: 0.7 -Mode: 0 -LetterboxInBreaks: 0 -WidescreenStoryboard: 1 - -[Editor] -Bookmarks: 12382,23354,34325,45297,56268,67240,78211,89182,100154,111125,122097,128605,133068,144040,155011,165982,175582 -DistanceSpacing: 1.5 -BeatDivisor: 4 -GridSize: 4 -TimelineZoom: 3.799998 - -[Metadata] -Title:R4V3 B0Y -TitleUnicode:R4V3 B0Y -Artist:S3RL feat Krystal -ArtistUnicode:S3RL feat Krystal -Creator:DeRandom Otaku -Version:FCL's H4RD -Source: -Tags:happy hardcore EMFA music rave boy Shmiklak FCL ByBy ByBy13 ByBy_Chan Marvollo M_a_r_v_o_l_l_o -BeatmapID:1056070 -BeatmapSetID:481451 - -[Difficulty] -HPDrainRate:5 -CircleSize:4 -OverallDifficulty:6 -ApproachRate:7.5 -SliderMultiplier:1.4 -SliderTickRate:1 - -[Events] -//Background and Video events -0,0,'BG.jpg',0,0 -//Break Periods -2,89376,99323 -//Storyboard Layer 0 (Background) -//Storyboard Layer 1 (Fail) -//Storyboard Layer 2 (Pass) -//Storyboard Layer 3 (Foreground) -//Storyboard Sound Samples - -[TimingPoints] -34,342.857142857143,4,1,1,100,1,0 -34,-133.333333333333,4,1,1,100,0,0 -1405,-133.333333333333,4,2,1,70,0,0 -12376,-125,4,2,2,70,0,0 -21976,-100,4,2,2,45,0,0 -23348,-100,4,2,2,85,0,0 -26091,-100,4,2,2,85,0,0 -31576,-100,4,2,2,85,0,0 -34319,-100,4,2,2,85,0,0 -37062,-100,4,2,2,85,0,0 -42462,-100,4,2,2,5,0,0 -42548,-100,4,2,2,85,0,0 -43919,-100,4,2,2,65,0,0 -45291,-100,4,2,2,50,0,0 -50691,-100,4,2,2,5,0,0 -50776,-100,4,2,2,50,0,0 -56262,-100,4,2,2,90,0,1 -65862,-125,4,2,2,90,0,0 -67234,-100,4,2,2,90,0,1 -72719,-100,4,2,2,90,0,1 -76834,-125,4,2,2,45,0,0 -78205,-125,4,2,0,50,0,0 -100148,-125,4,2,2,50,0,0 -100491,-125,4,2,0,50,0,0 -111119,-100,4,2,2,50,0,0 -116091,-100,4,2,2,10,0,0 -116262,-100,4,2,2,50,0,0 -116434,-100,4,2,2,10,0,0 -116605,-100,4,2,2,50,0,0 -121748,-133.333333333333,4,2,2,50,0,0 -122091,-100,4,2,2,50,0,0 -127576,-100,4,2,2,50,0,0 -130319,-90.9090909090909,4,2,2,50,0,0 -131005,-83.3333333333333,4,2,2,50,0,0 -131691,-76.9230769230769,4,2,2,50,0,0 -132376,-133.333333333333,4,2,2,50,0,0 -133062,-100,4,2,2,90,0,1 -135719,-100,4,2,2,5,0,1 -135805,-100,4,2,2,90,0,1 -141205,-100,4,2,2,5,0,1 -141291,-100,4,2,2,90,0,1 -142662,-100,4,2,2,70,0,0 -143691,-100,4,2,2,40,0,0 -144034,-100,4,2,2,90,0,1 -146691,-100,4,2,2,5,0,1 -146776,-100,4,2,2,90,0,1 -152176,-100,4,2,2,5,0,1 -152262,-100,4,2,2,90,0,1 -154662,-100,4,2,2,60,0,1 -155005,-100,4,2,2,75,0,0 -165976,-100,4,2,2,75,0,0 -171462,-133.333333333333,4,2,2,60,0,0 -174205,-153.846153846153,4,2,2,50,0,0 -174891,-153.846153846154,4,2,2,40,0,0 -175576,-100,4,2,2,25,0,0 -176262,-125,4,2,2,25,0,0 -176605,-125,4,2,2,15,0,0 - - -[Colours] - Combo1 : 0,255,255 -Combo2 : 17,255,17 -Combo3 : 0,128,192 -Combo4 : 124,0,249 - -[HitObjects] -138,122,34,6,0,L|133:229,3,105.000004005432,0|0|0|0,2:0|2:0|2:0|2:0,2:2:0:0: -133,226,1405,6,0,L|248:220,1,105.000004005432,2|2,1:2|0:0,0:0:0:0: -339,341,2091,2,0,L|222:338,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: -133,226,2776,2,0,P|128:187|129:158,1,52.5000020027162,2|0,0:0|0:0,0:0:0:0: -188,123,3119,2,0,P|193:84|190:55,1,52.5000020027162,2|0,0:0|0:0,0:0:0:0: -262,34,3462,2,0,P|290:62|366:69,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: -431,74,3976,1,0,0:0:0:0: -496,117,4148,6,0,L|503:229,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: -456,286,4662,1,0,0:0:0:0: -408,349,4834,2,0,L|296:356,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: -172,266,5519,2,0,P|155:216|165:148,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: -206,101,6034,1,0,0:0:0:0: -239,172,6205,2,0,L|361:162,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: -494,260,6891,6,0,B|443:252|443:252|386:267,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: -324,308,7405,1,0,0:0:0:0: -248,287,7576,2,0,L|241:227,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: -169,202,7919,2,0,L|176:142,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: -239,104,8262,2,0,P|282:119|345:101,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: -416,92,8776,1,0,0:0:0:0: -484,132,8948,2,0,L|491:195,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: -445,249,9291,2,0,L|452:312,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: -388,349,9634,6,0,P|354:328|289:335,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: -216,360,10148,1,0,0:0:0:0: -143,328,10319,2,0,L|72:315,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: -102,240,10662,2,0,L|173:227,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: -224,195,11005,5,2,0:0:0:0: -160,148,11176,1,0,0:0:0:0: -233,120,11348,1,2,0:0:0:0: -172,69,11519,1,0,0:0:0:0: -247,45,11691,2,0,P|285:39|314:43,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: -355,95,12034,2,0,P|378:105|399:121,1,52.5000020027161,2|0,0:0|0:0,0:0:0:0: -482,162,12376,6,0,P|450:190|445:261,1,112,2|2,0:0|0:0,0:0:0:0: -298,342,13062,2,0,P|296:287|259:247,1,112,2|2,0:0|0:0,0:0:0:0: -132,135,13748,2,0,L|127:62,1,56,2|0,0:0|0:0,0:0:0:0: -209,57,14091,2,0,L|235:-11,1,56,2|0,0:0|0:0,0:0:0:0: -304,41,14434,2,0,P|348:52|380:44,2,56,2|0|2,0:0|0:0|0:0,0:0:0:0: -272,119,14948,1,0,0:0:0:0: -335,173,15119,6,0,L|340:298,1,112,2|2,0:0|0:0,0:0:0:0: -274,339,15634,1,0,0:0:0:0: -216,278,15805,2,0,B|165:262|165:262|86:278,1,112,2|2,0:0|0:0,0:0:0:0: -5,139,16491,2,0,B|56:123|56:123|135:139,1,112,2|2,0:0|0:0,0:0:0:0: -189,171,17005,1,0,0:0:0:0: -257,123,17176,2,0,L|379:117,1,112,2|2,0:0|0:0,0:0:0:0: -434,171,17691,1,0,0:0:0:0: -434,171,17776,1,0,0:0:0:0: -434,171,17862,6,0,P|450:218|426:288,1,112,2|2,0:0|0:0,0:0:0:0: -356,308,18376,1,0,0:0:0:0: -288,261,18548,2,0,L|207:258,1,56,2|0,0:0|0:0,0:0:0:0: -170,316,18891,2,0,L|89:319,1,56,2|0,0:0|0:0,0:0:0:0: -38,234,19234,2,0,P|110:237|160:210,1,112,2|2,0:0|0:0,0:0:0:0: -179,144,19748,1,0,0:0:0:0: -104,105,19919,2,0,L|100:31,1,56,2|0,0:0|0:0,0:0:0:0: -179,18,20262,2,0,L|210:8,3,28,2|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: -247,8,20605,6,0,P|236:48|268:122,1,112,2|2,0:0|0:0,0:0:0:0: -311,178,21119,1,0,0:0:0:0: -288,259,21291,2,0,L|286:330,1,56,2|0,0:0|0:0,0:0:0:0: -363,349,21634,2,0,L|361:293,1,56,2|0,0:0|0:0,0:0:0:0: -408,231,21976,5,0,0:0:0:0: -462,125,23005,2,0,L|469:80,3,35 -499,48,23348,6,0,L|348:53,1,140,4|0,1:2|1:0,0:0:0:0: -178,161,24034,1,0,1:0:0:0: -244,241,24205,1,0,0:0:0:0: -244,241,24291,2,0,L|365:231,1,105,0|0,0:0|0:0,0:0:0:0: -434,292,24719,2,0,P|423:335|439:379,1,70,0|0,1:0|0:0,0:0:0:0: -325,333,25062,2,0,P|329:298|319:265,1,70,0|0,1:0|0:0,0:0:0:0: -250,185,25405,1,0,1:0:0:0: -308,135,25576,1,0,0:0:0:0: -213,111,25748,2,0,L|203:64,2,35,0|0|0,1:0|0:0|0:0,0:0:0:0: -146,183,26091,6,0,L|44:180,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: -202,370,26776,1,0,1:0:0:0: -253,288,26948,1,0,0:0:0:0: -253,288,27034,2,0,B|236:237|236:237|246:176,1,105,0|0,0:0|0:0,0:0:0:0: -318,112,27462,2,0,L|466:102,2,140,0|0|0,1:0|1:0|1:0,0:0:0:0: -139,224,28491,2,0,P|110:228|77:229,3,35,0|0|0|0,1:0|0:0|0:0|0:0,0:0:0:0: -69,267,28834,6,0,P|131:258|212:289,1,140,0|0,1:0|1:0,0:0:0:0: -402,217,29519,1,0,1:0:0:0: -303,180,29691,1,0,0:0:0:0: -303,180,29776,2,0,P|288:123|299:60,1,105,0|0,0:0|0:0,0:0:0:0: -200,26,30205,2,0,P|155:51|54:21,2,140,0|0|0,1:0|1:0|1:0,0:0:0:0: -166,125,31062,1,0,0:0:0:0: -242,197,31234,2,0,L|246:257,3,35,0|0|0|0,1:0|0:0|0:0|0:0,0:0:0:0: -293,248,31576,6,0,L|139:246,1,140,0|0,1:0|1:0,0:0:0:0: -66,307,32091,1,0,0:0:0:0: -71,202,32262,2,0,L|84:35,1,140,0|0,1:0|1:0,0:0:0:0: -289,23,32948,5,0,0:0:0:0: -218,53,33119,1,0,0:0:0:0: -176,118,33291,2,0,P|174:157|190:205,2,70,0|0|0,0:0|0:0|0:0,0:0:0:0: -176,118,34148,1,8,0:0:0:0: -265,172,34319,6,0,L|418:174,1,140,4|0,1:2|1:0,0:0:0:0: -440,273,34834,1,0,0:0:0:0: -337,253,35005,2,0,P|281:253|235:345,1,140,0|0,1:0|1:0,0:0:0:0: -232,315,35519,1,0,0:0:0:0: -130,341,35691,2,0,L|36:328,1,70,0|0,1:0|0:0,0:0:0:0: -95,231,36034,2,0,L|15:179,1,70,0|0,1:0|0:0,0:0:0:0: -110,119,36376,2,0,L|59:38,1,70,0|0,1:0|0:0,0:0:0:0: -185,0,36719,1,0,1:0:0:0: -185,0,36805,2,0,L|193:69,1,70,0|0,0:0|0:0,0:0:0:0: -224,85,37062,6,0,L|307:102,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: -262,183,37576,1,0,0:0:0:0: -185,253,37748,2,0,P|117:286|52:236,1,140,0|0,1:0|1:0,0:0:0:0: -116,166,38262,1,0,0:0:0:0: -185,253,38434,2,0,P|222:247|281:246,1,70,0|0,1:0|0:0,0:0:0:0: -344,299,38776,2,0,P|380:310|433:333,1,70,0|0,1:0|0:0,0:0:0:0: -500,267,39119,1,0,1:0:0:0: -379,96,39462,2,0,L|374:53,3,35,0|0|0|0,1:0|0:0|0:0|0:0,0:0:0:0: -395,12,39805,6,0,L|224:2,1,140,0|0,1:0|1:0,0:0:0:0: -172,69,40319,1,0,0:0:0:0: -267,112,40491,2,0,P|250:151|275:259,1,140,0|0,1:0|1:0,0:0:0:0: -264,244,41005,1,0,0:0:0:0: -182,309,41176,2,0,P|155:264|127:236,1,70,0|0,1:0|0:0,0:0:0:0: -69,176,41519,2,0,P|96:131|124:103,1,70,0|0,1:0|0:0,0:0:0:0: -202,71,41862,1,0,1:0:0:0: -179,173,42034,1,0,0:0:0:0: -137,37,42205,1,0,1:0:0:0: -137,37,42291,2,0,L|35:33,1,70,0|0,0:0|0:0,0:0:0:0: -23,63,42548,6,0,B|6:161|6:161|23:218,1,140,0|0,1:0|1:0,0:0:0:0: -62,295,43062,1,0,0:0:0:0: -141,226,43234,1,0,1:0:0:0: -168,348,43405,1,0,0:0:0:0: -168,348,43491,2,0,L|295:355,1,105,0|0,0:0|0:0,0:0:0:0: -367,309,43919,1,0,0:0:0:0: -201,89,45291,6,0,L|279:83,1,70,2|0,0:0|0:0,0:0:0:0: -201,162,45634,2,0,L|279:156,1,70,2|0,0:0|0:0,0:0:0:0: -202,235,45976,2,0,L|280:229,1,70,2|0,0:0|0:0,0:0:0:0: -202,308,46319,2,0,L|280:302,1,70,2|0,0:0|0:0,0:0:0:0: -411,345,46662,6,0,P|368:344|311:362,1,70,2|0,0:0|0:0,0:0:0:0: -399,261,47005,2,0,P|360:241|301:234,1,70,2|0,0:0|0:0,0:0:0:0: -427,187,47348,2,0,P|400:153|349:121,1,70,2|0,0:0|0:0,0:0:0:0: -484,134,47691,2,0,P|473:91|441:41,1,70,2|0,0:0|0:0,0:0:0:0: -348,30,48034,6,0,B|308:39|308:39|264:31,1,70,2|0,0:0|0:0,0:0:0:0: -205,108,48376,2,0,B|245:117|245:117|289:109,1,70,2|0,0:0|0:0,0:0:0:0: -345,188,48719,2,0,B|305:197|305:197|261:189,1,70,2|0,0:0|0:0,0:0:0:0: -199,263,49062,2,0,B|239:272|239:272|283:264,1,70,2|0,0:0|0:0,0:0:0:0: -345,188,49405,6,0,L|354:101,1,70,2|0,0:0|0:0,0:0:0:0: -252,150,49748,2,0,L|243:63,1,70,2|0,0:0|0:0,0:0:0:0: -146,118,50091,2,0,P|123:75|90:43,1,70,2|0,0:0|0:0,0:0:0:0: -8,28,50434,2,0,L|6:177,1,140,10|2,0:0|0:0,0:0:0:0: -93,242,50948,5,0,0:0:0:0: -93,242,51119,2,0,L|190:238,1,70,2|0,0:0|0:0,0:0:0:0: -239,311,51462,2,0,L|308:313,1,70,2|0,0:0|0:0,0:0:0:0: -393,250,51805,1,2,0:0:0:0: -429,348,51976,1,0,0:0:0:0: -429,348,52319,5,0,0:0:0:0: -486,259,52491,2,0,P|487:222|486:172,1,70,2|0,0:0|0:0,0:0:0:0: -382,170,52834,2,0,P|367:136|345:91,1,70,2|0,0:0|0:0,0:0:0:0: -261,55,53176,1,2,0:0:0:0: -242,158,53348,1,0,0:0:0:0: -242,158,53519,6,0,L|70:148,1,140,8|8,0:0|0:0,0:0:0:0: -196,338,54205,2,0,L|205:214,2,105,8|8|8,0:0|0:0|0:0,0:0:0:0: -296,304,54891,5,8,0:0:0:0: -296,304,55062,1,8,0:0:0:0: -327,203,55234,1,8,0:0:0:0: -327,203,55405,1,8,0:0:0:0: -355,102,55576,2,0,L|342:44,3,35,8|8|8|8,0:0|0:0|0:0|0:0,0:0:0:0: -365,18,55919,2,0,P|305:35|246:17,1,105,0|0,0:0|0:0,0:0:0:0: -230,40,56262,5,0,1:0:0:0: -285,129,56434,1,0,0:0:0:0: -223,213,56605,2,0,L|134:207,1,70,0|0,1:0|0:0,0:0:0:0: -66,267,56948,2,0,P|55:317|63:357,1,70,0|0,1:0|0:0,0:0:0:0: -156,369,57291,1,0,1:0:0:0: -156,369,57462,1,0,0:0:0:0: -318,236,57805,5,0,0:0:0:0: -250,155,57976,2,0,L|254:68,1,70,0|0,1:0|0:0,0:0:0:0: -349,42,58319,2,0,P|397:52|447:48,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: -253,85,58834,1,0,0:0:0:0: -169,21,59005,6,0,L|22:18,1,140,0|0,1:0|1:0,0:0:0:0: -9,121,59519,1,0,0:0:0:0: -53,216,59691,1,0,1:0:0:0: -53,216,59862,2,0,L|130:212,1,70,0|0,0:0|1:0,0:0:0:0: -220,252,60205,1,0,0:0:0:0: -173,158,60376,5,0,1:0:0:0: -173,158,60462,1,0,0:0:0:0: -173,158,60548,2,0,P|169:112|176:70,1,70,0|0,0:0|1:0,0:0:0:0: -253,22,60891,1,0,0:0:0:0: -302,114,61062,2,0,L|450:111,1,140,2|2,0:0|0:0,0:0:0:0: -503,196,61576,1,8,0:0:0:0: -503,196,61748,5,0,1:0:0:0: -411,247,61919,2,0,L|406:328,1,70,0|0,0:0|1:0,0:0:0:0: -317,372,62262,1,0,0:0:0:0: -216,340,62434,2,0,L|208:247,1,70,0|0,1:0|0:0,0:0:0:0: -250,173,62776,2,0,P|263:124|255:77,1,70,0|0,1:0|0:0,0:0:0:0: -58,51,63291,5,0,0:0:0:0: -18,148,63462,2,0,P|28:185|22:232,1,70,0|0,1:0|0:0,0:0:0:0: -17,321,63805,2,0,P|51:322|85:312,1,70,0|0,1:0|0:0,0:0:0:0: -172,254,64148,1,0,1:0:0:0: -172,254,64319,1,0,0:0:0:0: -240,334,64491,6,0,B|300:320|300:320|393:333,1,140,0|0,1:0|1:0,0:0:0:0: -466,274,65005,1,0,0:0:0:0: -408,186,65176,2,0,P|401:138|406:98,1,70,0|0,1:0|0:0,0:0:0:0: -298,101,65519,2,0,P|305:53|300:13,1,70,0|0,1:0|0:0,0:0:0:0: -303,31,65862,6,0,L|177:28,1,112,2|0,0:0|0:0,0:0:0:0: -124,79,66376,1,0,0:0:0:0: -200,113,66548,2,0,L|261:111,1,56 -134,161,66891,2,0,L|126:196,3,28,0|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: -89,224,67234,6,0,L|203:220,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: -239,260,67576,2,0,P|292:270|365:248,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: -390,227,67919,2,0,L|400:133,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: -372,69,68262,1,0,1:0:0:0: -251,140,68491,1,0,0:0:0:0: -251,140,68605,6,0,P|194:130|131:146,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: -105,180,68948,2,0,B|97:228|97:228|115:297,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: -166,310,69291,1,0,1:0:0:0: -275,223,69519,1,0,0:0:0:0: -332,263,69634,2,0,L|436:258,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: -499,298,69976,6,0,P|507:243|449:180,1,140,0|0,1:0|1:0,0:0:0:0: -328,131,70548,1,0,0:0:0:0: -278,180,70662,2,0,P|230:192|182:178,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: -122,155,71005,2,0,L|28:151,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: -11,219,71348,6,0,P|2:248|0:281,2,46.6666666666667,0|0|0,1:0|0:0|0:0,0:0:0:0: -28,151,71691,2,0,B|44:105|44:105|26:42,1,93.3333333333333,0|0,1:0|0:0,0:0:0:0: -88,20,72034,2,0,L|243:16,1,140,2|2,0:0|0:0,0:0:0:0: -227,16,72719,6,0,P|215:75|218:109,1,70,0|0,1:0|0:0,0:0:0:0: -299,148,73062,2,0,P|311:207|308:241,1,70,0|0,1:0|0:0,0:0:0:0: -260,308,73405,1,0,1:0:0:0: -260,308,73576,1,0,0:0:0:0: -361,278,73748,2,0,L|463:273,1,70,0|0,1:0|0:0,0:0:0:0: -494,74,74262,5,0,0:0:0:0: -430,157,74434,2,0,P|394:163|338:153,1,70,0|0,1:0|0:0,0:0:0:0: -280,93,74776,2,0,P|245:90|210:96,1,70,0|0,1:0|0:0,0:0:0:0: -121,152,75119,2,0,L|111:235,1,70,0|0,1:0|0:0,0:0:0:0: -61,328,75462,6,0,P|117:309|214:344,1,140,0|0,1:0|1:0,0:0:0:0: -296,303,75976,1,0,0:0:0:0: -213,237,76148,2,0,L|208:148,1,70,0|0,1:0|0:0,0:0:0:0: -307,204,76491,2,0,L|312:115,1,70,0|0,1:0|0:0,0:0:0:0: -270,59,76834,6,0,P|241:55|195:64,1,56,0|0,0:0|0:0,0:0:0:0: -172,130,77176,2,0,P|144:138|106:166,1,56 -65,215,77519,2,0,B|61:260|61:260|76:287|76:287|71:331,1,112 -71,322,78205,6,0,P|130:294|193:287,1,112 -288,161,78891,2,0,P|229:133|166:126,1,112 -22,84,79576,6,0,L|18:20,1,56 -100,46,79919,2,0,P|136:51|173:39,1,56,0|0,0:0|0:0,0:0:0:0: -234,19,80262,2,0,B|280:36|280:36|365:20,1,112,0|0,0:0|0:0,0:0:0:0: -341,24,80948,6,0,L|332:160,1,112 -333,135,81462,1,0,0:0:0:0: -277,198,81634,2,0,P|228:183|152:187,1,112,0|0,0:0|0:0,0:0:0:0: -64,315,82319,6,0,L|61:191,1,112 -61,203,82834,1,0,0:0:0:0: -107,133,83005,2,0,P|119:105|82:13,1,112,0|0,0:0|0:0,0:0:0:0: -100,28,83691,6,0,L|180:24,1,56,2|0,0:0|0:0,0:0:0:0: -224,74,84034,1,0,0:0:0:0: -224,74,84205,1,0,0:0:0:0: -289,21,84376,2,0,P|325:17|367:28,1,56,2|0,0:0|0:0,0:0:0:0: -369,100,84719,2,0,P|403:111|436:139,1,56,2|0,0:0|0:0,0:0:0:0: -481,208,85062,6,0,L|414:204,1,56,2|0,0:0|0:0,0:0:0:0: -367,266,85405,1,0,0:0:0:0: -367,266,85576,1,0,0:0:0:0: -307,206,85748,2,0,P|298:175|299:138,1,56,2|0,0:0|0:0,0:0:0:0: -213,154,86091,2,0,P|217:122|234:88,1,56,2|0,0:0|0:0,0:0:0:0: -168,18,86434,6,0,B|87:16|87:16|123:49,1,112,2|0,0:0|0:0,0:0:0:0: -81,116,86948,1,0,0:0:0:0: -117,191,87119,2,0,P|155:198|188:192,1,56,2|0,0:0|0:0,0:0:0:0: -230,256,87462,2,0,P|257:249|285:250,1,56,2|0,0:0|0:0,0:0:0:0: -359,290,87805,5,2,0:0:0:0: -359,290,87976,1,0,0:0:0:0: -389,211,88148,1,0,0:0:0:0: -389,211,88319,1,0,0:0:0:0: -466,177,88491,2,0,B|483:139|483:139|472:54,2,112,2|2|4,0:0|0:0|0:3,0:0:0:0: -185,144,100148,6,0,P|137:124|63:139,1,112,4|2,1:2|0:0,0:0:0:0: -35,189,100662,1,2,0:0:0:0: -35,189,100834,2,0,L|27:318,1,112,2|2,0:0|0:0,0:0:0:0: -164,352,101519,1,2,0:3:0:0: -297,294,101862,2,0,L|428:300,2,112,2|2|2,0:0|0:0|0:0,0:0:0:0: -281,222,102719,1,2,0:0:0:0: -305,153,102891,5,2,0:3:0:0: -225,274,103234,2,0,P|183:292|107:272,2,112,2|2|2,0:0|0:0|0:0,0:0:0:0: -305,153,104262,1,2,0:3:0:0: -186,67,104605,2,0,B|148:52|148:52|54:66,2,112,2|2|2,0:0|0:0|0:0,0:0:0:0: -256,48,105462,1,2,0:0:0:0: -326,30,105634,5,2,0:3:0:0: -428,132,105976,2,0,L|434:266,2,112,2|2|2,0:0|0:0|0:0,0:0:0:0: -308,216,107005,1,2,0:3:0:0: -189,131,107348,2,0,P|147:120|77:142,2,112,2|2|2,0:0|0:0|0:0,0:0:0:0: -230,190,108205,1,2,0:0:0:0: -233,262,108376,6,0,L|239:322,1,56,2|0,0:3|0:0,0:0:0:0: -311,325,108719,2,0,L|316:269,1,56,2|2,0:0|0:0,0:0:0:0: -369,219,109062,2,0,L|361:107,2,112,2|2|0,0:0|0:0|0:0,0:0:0:0: -81,124,110776,2,0,L|92:77,3,28,0|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: -77,52,111119,6,0,L|238:47,1,140,2|2,0:0|0:0,0:0:0:0: -290,102,111634,1,0,0:0:0:0: -349,33,111805,2,0,L|435:29,1,70,2|0,0:0|0:0,0:0:0:0: -439,118,112148,2,0,L|518:150,1,70,2|0,0:0|0:0,0:0:0:0: -426,309,112662,5,0,0:0:0:0: -379,230,112834,2,0,P|338:227|295:238,1,70,2|0,0:0|0:0,0:0:0:0: -237,286,113176,1,2,0:0:0:0: -237,286,113348,1,0,0:0:0:0: -172,221,113519,2,0,L|165:128,1,70,2|0,0:0|0:0,0:0:0:0: -166,151,114034,5,0,0:0:0:0: -237,94,114205,2,0,P|278:84|334:88,1,70,2|0,0:0|0:0,0:0:0:0: -375,142,114548,2,0,P|409:143|443:152,1,70,2|0,0:0|0:0,0:0:0:0: -496,226,114891,2,0,L|502:313,1,70,2|0,0:0|0:0,0:0:0:0: -434,358,115234,5,2,0:0:0:0: -434,358,115319,1,0,0:0:0:0: -434,358,115405,2,0,L|333:347,2,70,0|2|0,0:0|0:0|0:0,0:0:0:0: -398,273,115919,2,0,L|411:117,1,140,2|2,0:0|0:0,0:0:0:0: -255,34,116605,6,0,P|211:59|119:19,1,140,2|2,0:0|0:0,0:0:0:0: -45,68,117119,1,0,0:0:0:0: -108,133,117291,2,0,L|115:214,1,70,2|0,0:0|0:0,0:0:0:0: -197,240,117634,2,0,L|190:321,1,70,2|0,0:0|0:0,0:0:0:0: -363,369,118148,5,0,0:0:0:0: -332,283,118319,2,0,P|329:226|345:193,1,70,2|0,0:0|0:0,0:0:0:0: -386,140,118662,1,2,0:0:0:0: -386,140,118834,1,0,0:0:0:0: -331,67,119005,2,0,L|239:63,1,70,2|0,0:0|0:0,0:0:0:0: -261,63,119519,5,0,0:0:0:0: -198,129,119691,2,0,P|159:137|111:126,1,70,2|0,0:0|0:0,0:0:0:0: -68,201,120034,2,0,P|60:240|71:288,1,70,2|0,0:0|0:0,0:0:0:0: -128,333,120376,2,0,L|221:325,1,70,2|0,0:0|0:0,0:0:0:0: -282,293,120719,5,2,0:0:0:0: -282,293,121062,1,2,0:0:0:0: -282,293,121405,1,2,0:0:0:0: -282,293,121748,2,0,L|383:298,1,78.7500030040742,2|0,0:0|0:0,0:0:0:0: -403,281,122091,6,0,L|395:114,1,140,0|0,1:0|0:0,0:0:0:0: -221,91,122776,2,0,L|214:230,1,140,0|0,0:0|0:0,0:0:0:0: -354,347,123462,2,0,P|389:364|474:287,1,140,0|0,0:0|0:0,0:0:0:0: -329,202,124148,2,0,P|294:185|209:262,1,140,0|0,0:0|0:0,0:0:0:0: -68,341,124834,6,0,L|59:269,1,70,0|0,0:0|0:0,0:0:0:0: -139,313,125176,2,0,L|130:241,1,70,0|0,0:0|0:0,0:0:0:0: -211,286,125519,2,0,L|202:214,1,70,0|0,0:0|0:0,0:0:0:0: -282,260,125862,2,0,L|273:188,1,70,0|0,0:0|0:0,0:0:0:0: -192,108,126205,6,0,P|162:100|107:103,1,70 -172,192,126548,2,0,P|142:181|87:179,1,70 -146,274,126891,2,0,P|117:260|63:254,1,70 -110,354,127234,2,0,P|83:338|29:327,1,70 -150,279,127576,5,0,0:0:0:0: -150,279,127748,1,0,0:0:0:0: -242,327,127919,1,0,0:0:0:0: -242,327,128091,1,0,0:0:0:0: -285,232,128262,2,0,L|379:227,1,70,0|0,0:0|0:0,0:0:0:0: -422,166,128605,2,0,L|491:169,1,70,0|0,0:0|0:0,0:0:0:0: -441,76,128948,5,0,0:0:0:0: -441,76,129119,1,0,0:0:0:0: -388,150,129291,1,0,0:0:0:0: -388,150,129462,1,0,0:0:0:0: -338,73,129634,2,0,P|286:69|238:75,1,70,0|0,0:0|0:0,0:0:0:0: -210,140,129976,2,0,P|175:141|140:137,1,70,0|0,0:0|0:0,0:0:0:0: -79,205,130319,6,0,L|68:260,3,38.5000011749268,0|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: -108,267,130662,2,0,L|115:319,3,38.5000011749268,0|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: -145,334,131005,6,0,P|169:324|197:323,3,41.9999987182618,0|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: -220,339,131348,2,0,P|237:335|263:321,3,41.9999987182618,0|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: -289,300,131691,6,0,L|294:258,14,22.7499989585877,0|0|0|0|0|0|0|0|0|0|0|0|0|0|0,0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0,0:0:0:0: -314,240,132376,6,0,B|356:235|356:235|374:221|374:221|433:213,1,105.000004005432,0|0,0:0|0:0,0:0:0:0: -444,142,132891,1,0,0:0:0:0: -444,142,132976,1,0,0:0:0:0: -444,142,133062,6,0,B|461:90|461:90|446:-12,1,140,4|0,1:2|1:0,0:0:0:0: -238,15,133748,1,0,1:0:0:0: -181,103,133919,1,0,0:0:0:0: -181,103,134005,2,0,L|310:99,1,105,0|0,0:0|0:0,0:0:0:0: -366,167,134434,6,0,P|378:224|363:254,1,70,0|0,1:0|0:0,0:0:0:0: -276,270,134776,2,0,P|262:326|236:347,1,70,0|0,1:0|0:0,0:0:0:0: -151,356,135119,1,0,1:0:0:0: -61,300,135291,1,0,0:0:0:0: -164,254,135462,1,0,1:0:0:0: -164,254,135548,2,0,L|174:156,1,70 -195,162,135805,6,0,P|243:178|290:168,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: -148,67,136319,1,0,0:0:0:0: -148,67,136491,1,0,1:0:0:0: -247,98,136662,1,0,0:0:0:0: -247,98,136748,2,0,B|286:80|286:80|372:100,1,105,0|0,0:0|0:0,0:0:0:0: -432,154,137176,6,0,L|437:294,2,140,0|0|0,1:0|1:0|1:0,0:0:0:0: -307,324,138205,2,0,P|282:331|245:328,3,35,0|0|0|0,1:0|0:0|0:0|0:0,0:0:0:0: -246,309,138548,6,0,P|201:298|114:358,1,140,0|0,1:0|1:0,0:0:0:0: -19,157,139234,1,0,1:0:0:0: -113,112,139405,1,0,0:0:0:0: -113,112,139491,2,0,P|153:134|236:108,1,105,0|0,0:0|0:0,0:0:0:0: -310,159,139919,6,0,P|276:209|172:226,1,140,0|0,1:0|1:0,0:0:0:0: -387,334,140605,2,0,L|381:238,1,70,0|0,1:0|0:0,0:0:0:0: -450,183,140948,1,0,1:0:0:0: -450,183,141034,2,0,L|456:87,1,70,0|0,0:0|0:0,0:0:0:0: -434,85,141291,6,0,P|399:71|337:77,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: -468,292,141976,1,0,1:0:0:0: -377,238,142148,1,0,0:0:0:0: -377,238,142234,2,0,P|327:245|261:229,1,105 -178,185,142662,5,2,0:0:0:0: -178,185,143005,1,2,0:0:0:0: -178,185,143348,1,0,0:0:0:0: -178,185,143691,2,0,L|171:266,1,70,0|0,0:0|0:0,0:0:0:0: -171,254,144034,6,0,P|224:241|320:257,1,140,4|0,1:2|1:0,0:0:0:0: -408,282,144548,1,0,0:0:0:0: -480,205,144719,1,0,1:0:0:0: -433,116,144891,1,0,0:0:0:0: -433,116,144976,2,0,L|443:2,1,105,0|0,0:0|0:0,0:0:0:0: -337,69,145405,6,0,P|303:79|242:60,1,70,0|0,1:0|0:0,0:0:0:0: -172,116,145748,2,0,L|86:103,1,70,0|0,1:0|0:0,0:0:0:0: -38,188,146091,1,0,1:0:0:0: -38,188,146262,1,0,0:0:0:0: -110,264,146434,1,0,1:0:0:0: -110,264,146519,2,0,L|196:251,1,70,0|0,0:0|0:0,0:0:0:0: -208,269,146776,6,0,P|246:279|300:266,1,70,0|0,1:0|0:0,0:0:0:0: -369,227,147119,1,0,1:0:0:0: -369,227,147462,1,0,1:0:0:0: -312,138,147634,1,0,0:0:0:0: -312,138,147719,2,0,P|302:86|316:15,1,105,0|0,0:0|0:0,0:0:0:0: -210,71,148148,6,0,B|159:84|159:84|45:57,2,140,0|0|0,1:0|1:0|1:0,0:0:0:0: -410,132,149176,2,0,P|421:151|426:191,3,35,0|0|0|0,1:0|0:0|0:0|0:0,0:0:0:0: -458,203,149519,6,0,P|408:195|334:253,1,140,0|0,1:0|1:0,0:0:0:0: -232,232,150034,1,0,0:0:0:0: -309,162,150205,1,0,1:0:0:0: -192,144,150376,1,0,0:0:0:0: -192,144,150462,2,0,L|188:19,1,105,0|0,0:0|0:0,0:0:0:0: -112,155,150891,6,0,P|139:204|239:212,1,140,0|0,1:0|1:0,0:0:0:0: -216,221,151405,1,0,0:0:0:0: -296,288,151576,2,0,L|398:280,1,70,0|0,1:0|0:0,0:0:0:0: -445,213,151919,1,0,1:0:0:0: -445,213,152005,2,0,L|452:111,1,70,0|0,0:0|0:0,0:0:0:0: -434,113,152262,6,0,P|428:66|434:17,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: -352,180,152776,1,0,0:0:0:0: -352,180,152948,2,0,B|287:163|287:163|183:186,1,140,0|0,1:0|1:0,0:0:0:0: -215,178,153634,6,0,P|163:175|121:181,1,70,0|0,1:0|0:0,0:0:0:0: -106,274,153976,2,0,L|200:277,1,70,0|0,1:0|0:0,0:0:0:0: -264,329,154319,1,0,1:0:0:0: -264,329,154662,1,0,0:0:0:0: -360,286,154834,2,0,L|365:255,2,17.5,0|0|0,0:0|0:0|0:0,0:0:0:0: -376,312,155005,6,0,L|542:302,1,140,4|0,1:2|1:0,0:0:0:0: -460,213,155519,1,0,0:0:0:0: -460,213,155691,2,0,L|466:132,1,70,0|0,1:0|0:0,0:0:0:0: -363,113,156034,2,0,L|357:32,1,70,0|0,1:0|0:0,0:0:0:0: -253,34,156376,6,0,P|224:40|168:26,1,70,0|0,1:0|0:0,0:0:0:0: -101,98,156719,1,0,1:0:0:0: -101,98,156891,1,0,0:0:0:0: -190,152,157062,2,0,L|195:247,1,70,0|0,1:0|0:0,0:0:0:0: -290,274,157405,2,0,P|303:225|295:182,1,70,0|0,1:0|0:0,0:0:0:0: -271,105,157748,6,0,B|354:84|354:84|425:103,1,140,0|0,1:0|1:0,0:0:0:0: -484,169,158262,1,0,0:0:0:0: -484,169,158434,2,0,P|492:218|484:257,1,70,0|0,1:0|0:0,0:0:0:0: -396,286,158776,2,0,P|388:335|396:374,1,70,0|0,1:0|0:0,0:0:0:0: -285,341,159119,5,0,1:0:0:0: -285,341,159291,1,0,0:0:0:0: -210,267,159462,2,0,L|214:175,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: -129,334,159976,1,0,0:0:0:0: -51,262,160148,2,0,P|40:217|43:169,1,70,0|0,1:0|0:0,0:0:0:0: -125,104,160491,6,0,L|298:97,1,140,0|0,1:0|1:0,0:0:0:0: -341,170,161005,1,0,0:0:0:0: -373,70,161176,2,0,L|377:-8,1,70,0|0,1:0|0:0,0:0:0:0: -468,51,161519,1,0,1:0:0:0: -468,51,161691,1,0,0:0:0:0: -424,146,161862,6,0,P|419:203|429:235,1,70,0|0,1:0|0:0,0:0:0:0: -467,309,162205,2,0,L|388:311,2,70,0|0|0,1:0|0:0|1:0,0:0:0:0: -421,214,162719,1,0,0:0:0:0: -332,271,162891,2,0,P|321:309|343:361,1,70,0|0,1:0|0:0,0:0:0:0: -225,359,163234,6,0,P|162:331|86:357,1,140,0|0,1:0|1:0,0:0:0:0: -26,270,163748,1,0,0:0:0:0: -26,270,163919,2,0,L|30:169,1,70,0|0,1:0|0:0,0:0:0:0: -112,136,164262,2,0,L|108:35,1,70,0|0,1:0|0:0,0:0:0:0: -207,103,164605,6,0,P|272:122|351:76,2,140,0|0|0,1:0|1:0|1:0,0:0:0:0: -291,296,165634,1,0,1:0:0:0: -364,221,165805,1,8,0:0:0:0: -364,221,165891,1,0,0:0:0:0: -364,221,165976,6,0,P|373:159|328:87,1,140,4|0,1:2|1:0,0:0:0:0: -175,93,166662,2,0,P|140:152|148:221,1,140,0|0,1:0|1:0,0:0:0:0: -256,356,167348,2,0,L|256:212,1,140,0|0,1:0|1:0,0:0:0:0: -152,88,168034,1,0,1:0:0:0: -360,88,168376,1,0,1:0:0:0: -284,300,168719,6,0,P|216:308|157:273,1,140,0|0,1:0|1:0,0:0:0:0: -157,111,169405,2,0,P|216:76|285:84,1,140,0|0,1:0|1:0,0:0:0:0: -420,192,170091,2,0,L|276:192,1,140,0|0,1:0|1:0,0:0:0:0: -152,296,170777,1,0,1:0:0:0: -152,88,171119,1,0,1:0:0:0: -152,88,171291,1,0,0:0:0:0: -152,88,171462,6,0,L|264:88,1,105.000004005432,6|2,0:0|0:0,0:0:0:0: -392,176,172148,2,0,L|280:176,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: -160,272,172834,2,0,L|272:272,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: -400,352,173519,2,0,L|288:352,1,105.000004005432,2|2,0:0|0:0,0:0:0:0: -105,324,174205,6,0,P|85:285|89:219,1,90.9999958343508,2|2,0:0|0:0,0:0:0:0: -95,219,174719,1,0,0:0:0:0: -103,197,174891,2,0,L|99:88,1,90.9999958343508,2|2,0:0|0:0,0:0:0:0: -240,73,175576,5,0,0:0:0:0: -265,106,175919,1,0,0:0:0:0: -279,136,176262,2,0,B|314:129|351:139|351:139|329:100,1,112"; - } -} From c26d226a75fa4e7e4e975b32fa6b5035c21b78dc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 13 Oct 2018 07:09:33 +0900 Subject: [PATCH 0171/5608] Make saving the ladder to disk a button-based operation rather than on dispose --- osu.Game.Tournament.Tests/LadderTestCase.cs | 43 +++++++++++++++++++ .../TestCaseLadderManager.cs | 26 +++-------- 2 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 osu.Game.Tournament.Tests/LadderTestCase.cs diff --git a/osu.Game.Tournament.Tests/LadderTestCase.cs b/osu.Game.Tournament.Tests/LadderTestCase.cs new file mode 100644 index 0000000000..3044451a9e --- /dev/null +++ b/osu.Game.Tournament.Tests/LadderTestCase.cs @@ -0,0 +1,43 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.IO; +using Newtonsoft.Json; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Tests.Visual; +using osu.Game.Tournament.Screens.Ladder.Components; + +namespace osu.Game.Tournament.Tests +{ + public abstract class LadderTestCase : OsuTestCase + { + protected LadderInfo Ladder; + + protected LadderTestCase() + { + Ladder = File.Exists(@"bracket.json") ? JsonConvert.DeserializeObject(File.ReadAllText(@"bracket.json")) : new LadderInfo(); + + Add(new OsuButton + { + Text = "Save Changes", + Width = 140, + Height = 50, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Padding = new MarginPadding(10), + Action = SaveChanges, + }); + } + + protected virtual void SaveChanges() + { + File.WriteAllText(@"bracket.json", JsonConvert.SerializeObject(Ladder, + new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore + })); + } + } +} diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index 2dfb1b8a63..a7b93c8055 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -1,43 +1,31 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.IO; -using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.Cursor; -using osu.Game.Tests.Visual; using osu.Game.Tournament.Screens.Ladder; -using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Tests { - public class TestCaseLadderManager : OsuTestCase + public class TestCaseLadderManager : LadderTestCase { [Cached] private readonly LadderManager manager; public TestCaseLadderManager() { - var ladder = File.Exists(@"bracket.json") ? JsonConvert.DeserializeObject(File.ReadAllText(@"bracket.json")) : new LadderInfo(); - - Child = new OsuContextMenuContainer + Add(new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - Child = manager = new LadderManager(ladder) - }; + Child = manager = new LadderManager(Ladder) + }); } - protected override void Dispose(bool isDisposing) + protected override void SaveChanges() { - base.Dispose(isDisposing); - - File.WriteAllText(@"bracket.json", JsonConvert.SerializeObject(manager.CreateInfo(), - new JsonSerializerSettings - { - NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore - })); + Ladder = manager.CreateInfo(); + base.SaveChanges(); } } } From a4bb4255b167cf051dd9fe60a1942641790529e5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 13 Oct 2018 07:10:13 +0900 Subject: [PATCH 0172/5608] Add grouping manager --- .../TestCaseGroupingManager.cs | 50 +++++++++++++++++++ .../Components/DrawableTournamentGrouping.cs | 2 +- .../Ladder/Components/TournamentGrouping.cs | 5 +- osu.Game/Overlays/Settings/SettingsTextBox.cs | 2 +- 4 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Tournament.Tests/TestCaseGroupingManager.cs diff --git a/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs b/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs new file mode 100644 index 0000000000..0d39ef1c73 --- /dev/null +++ b/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs @@ -0,0 +1,50 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Overlays.Settings; +using osu.Game.Tournament.Screens.Ladder.Components; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseGroupingManager : LadderTestCase + { + public TestCaseGroupingManager() + { + FillFlowContainer items; + + Add(items = new FillFlowContainer + { + Direction = FillDirection.Vertical, + RelativeSizeAxes = Axes.Both + }); + + foreach (var g in Ladder.Groupings) + items.Add(new GroupingRow(g)); + } + + public class GroupingRow : CompositeDrawable + { + public readonly TournamentGrouping Grouping; + + public GroupingRow(TournamentGrouping grouping) + { + Grouping = grouping; + InternalChildren = new Drawable[] + { + new FillFlowContainer + { + Direction = FillDirection.Horizontal, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new SettingsTextBox { Width = 0.4f, Bindable = Grouping.Name }, + new SettingsTextBox { Width = 0.4f, Bindable = Grouping.Description }, + } + } + }; + + RelativeSizeAxes = Axes.X; + Height = 40; + } + } + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs index 475e735522..8a38f402aa 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { new OsuSpriteText { - Text = grouping.Description.ToUpper(), + Text = grouping.Description.Value.ToUpper(), Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre }, diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs index 675bf5fc4f..2e72e1fe06 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs @@ -2,13 +2,14 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Framework.Configuration; namespace osu.Game.Tournament.Screens.Ladder.Components { public class TournamentGrouping { - public string Name; - public string Description; + public readonly Bindable Name = new Bindable(); + public readonly Bindable Description = new Bindable(); public int BestOf; diff --git a/osu.Game/Overlays/Settings/SettingsTextBox.cs b/osu.Game/Overlays/Settings/SettingsTextBox.cs index ce9218bbe7..106b2372e0 100644 --- a/osu.Game/Overlays/Settings/SettingsTextBox.cs +++ b/osu.Game/Overlays/Settings/SettingsTextBox.cs @@ -8,6 +8,6 @@ namespace osu.Game.Overlays.Settings { public class SettingsTextBox : SettingsItem { - protected override Drawable CreateControl() => new OsuTextBox(); + protected override Drawable CreateControl() => new OsuTextBox { RelativeSizeAxes = Axes.X }; } } From 2173f46a4678eb2c708be15ea2362030e845528e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 13 Oct 2018 19:45:59 +0900 Subject: [PATCH 0173/5608] Add missing licence header --- osu.Game.Tournament.Tests/TestCaseGroupingManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs b/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs index 0d39ef1c73..e9df1eb62e 100644 --- a/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Settings; From bac7d644370bdb210b1a1aa6af71d7c53754a58f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 13 Oct 2018 23:45:52 +0900 Subject: [PATCH 0174/5608] Improve the completeness of APIBeatmap's transform methods --- osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index 193ccf1f6b..c9ea66d05f 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -61,17 +61,13 @@ namespace osu.Game.Online.API.Requests.Responses { return new BeatmapInfo { - Metadata = this, + Metadata = !string.IsNullOrEmpty(Artist) ? this : (BeatmapMetadata)BeatmapSet, Ruleset = rulesets.GetRuleset(ruleset), StarDifficulty = starDifficulty, OnlineBeatmapID = OnlineBeatmapID, Version = version, Status = Status, - BeatmapSet = new BeatmapSetInfo - { - OnlineBeatmapSetID = OnlineBeatmapSetID, - Status = BeatmapSet?.Status ?? BeatmapSetOnlineStatus.None - }, + BeatmapSet = BeatmapSet.ToBeatmapSet(rulesets), BaseDifficulty = new BeatmapDifficulty { DrainRate = drainRate, From 522f106f746f34a3a80f64ff236704c506103b30 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 14 Oct 2018 00:40:33 +0900 Subject: [PATCH 0175/5608] Add initial version of beatmap card --- .../TestCaseBeatmapPanel.cs | 42 +++++++ .../Components/TournamentBeatmapPanel.cs | 110 ++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs create mode 100644 osu.Game.Tournament/Components/TournamentBeatmapPanel.cs diff --git a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs new file mode 100644 index 0000000000..8298cbd8ea --- /dev/null +++ b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs @@ -0,0 +1,42 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; +using osu.Game.Tests.Visual; +using osu.Game.Tournament.Components; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseBeatmapPanel : OsuTestCase + { + [Resolved] + protected APIAccess API { get; set; } + + [Resolved] + protected RulesetStore Rulesets { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = 1091460 }); + req.Success += success; + API.Queue(req); + } + + private void success(APIBeatmap apiBeatmap) + { + var beatmap = apiBeatmap.ToBeatmap(Rulesets); + Add(new TournamentBeatmapPanel(beatmap) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }); + } + } +} diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs new file mode 100644 index 0000000000..5eb597a3c6 --- /dev/null +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -0,0 +1,110 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using OpenTK.Graphics; + +namespace osu.Game.Tournament.Components +{ + public class TournamentBeatmapPanel : CompositeDrawable + { + private readonly BeatmapInfo beatmap; + private const float horizontal_padding = 10; + private const float vertical_padding = 5; + + public TournamentBeatmapPanel(BeatmapInfo beatmap) + { + this.beatmap = beatmap; + Width = 400; + Height = 50; + } + + [BackgroundDependencyLoader] + private void load() + { + CornerRadius = 25; + Masking = true; + + AddRangeInternal(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + new UpdateableBeatmapSetCover + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.5f), + BeatmapSet = beatmap.BeatmapSet, + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Padding = new MarginPadding(vertical_padding), + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = new LocalisedString(( + $"{beatmap.Metadata.ArtistUnicode} - {beatmap.Metadata.TitleUnicode}", + $"{beatmap.Metadata.Artist} - {beatmap.Metadata.Title}")), + Font = @"Exo2.0-BoldItalic", + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Padding = new MarginPadding(vertical_padding), + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = "mapper", + Font = @"Exo2.0-RegularItalic", + Padding = new MarginPadding { Right = 5 }, + TextSize = 14 + }, + new OsuSpriteText + { + Text = beatmap.Metadata.AuthorString, + Font = @"Exo2.0-BoldItalic", + Padding = new MarginPadding { Right = 20 }, + TextSize = 14 + }, + new OsuSpriteText + { + Text = "difficulty", + Font = @"Exo2.0-RegularItalic", + Padding = new MarginPadding { Right = 5 }, + TextSize = 14 + }, + new OsuSpriteText + { + Text = beatmap.Version, + Font = @"Exo2.0-BoldItalic", + TextSize = 14 + }, + } + } + }, + }, + }); + } + } +} From f5716c3d213c3d6e4ed597aa18116a9372cb5cee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 14 Oct 2018 01:03:04 +0900 Subject: [PATCH 0176/5608] Add ability to change best of, add and delete groupings --- .../TestCaseGroupingManager.cs | 44 ++++++++++++++++--- .../Ladder/Components/TournamentGrouping.cs | 2 +- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs b/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs index e9df1eb62e..a0a4dfdc8b 100644 --- a/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs @@ -1,8 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Screens.Ladder.Components; @@ -10,20 +12,43 @@ namespace osu.Game.Tournament.Tests { public class TestCaseGroupingManager : LadderTestCase { + private readonly FillFlowContainer items; + public TestCaseGroupingManager() { - FillFlowContainer items; - - Add(items = new FillFlowContainer + Add(new FillFlowContainer { Direction = FillDirection.Vertical, - RelativeSizeAxes = Axes.Both + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + items = new FillFlowContainer + { + Direction = FillDirection.Vertical, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + new TriangleButton + { + Width = 100, + Text = "Add", + Action = addNew + }, + } }); foreach (var g in Ladder.Groupings) items.Add(new GroupingRow(g)); } + protected override void SaveChanges() + { + Ladder.Groupings = items.Children.Select(c => c.Grouping).ToList(); + base.SaveChanges(); + } + + private void addNew() => items.Add(new GroupingRow(new TournamentGrouping())); + public class GroupingRow : CompositeDrawable { public readonly TournamentGrouping Grouping; @@ -39,8 +64,15 @@ namespace osu.Game.Tournament.Tests RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new SettingsTextBox { Width = 0.4f, Bindable = Grouping.Name }, - new SettingsTextBox { Width = 0.4f, Bindable = Grouping.Description }, + new SettingsTextBox { Width = 0.3f, Bindable = Grouping.Name }, + new SettingsTextBox { Width = 0.3f, Bindable = Grouping.Description }, + new SettingsSlider { LabelText = "Best of", Width = 0.3f, Bindable = Grouping.BestOf }, + new DangerousSettingsButton + { + Width = 0.1f, + Text = "Delete", + Action = () => Expire() + }, } } }; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs index 2e72e1fe06..d7c89cb006 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs @@ -11,7 +11,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly Bindable Name = new Bindable(); public readonly Bindable Description = new Bindable(); - public int BestOf; + public readonly BindableInt BestOf = new BindableInt(9) { Default = 9, MinValue = 3, MaxValue = 23 }; public List Pairings = new List(); } From e136f72c8ec8cae0e3e43ec057eeabc38e33b249 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 14 Oct 2018 03:03:17 +0900 Subject: [PATCH 0177/5608] Fix incorrect access definitions --- osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs index 8298cbd8ea..e5cb2f155c 100644 --- a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs +++ b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs @@ -16,22 +16,22 @@ namespace osu.Game.Tournament.Tests public class TestCaseBeatmapPanel : OsuTestCase { [Resolved] - protected APIAccess API { get; set; } + private APIAccess api { get; set; } [Resolved] - protected RulesetStore Rulesets { get; set; } + private RulesetStore rulesets { get; set; } [BackgroundDependencyLoader] private void load() { var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = 1091460 }); req.Success += success; - API.Queue(req); + api.Queue(req); } private void success(APIBeatmap apiBeatmap) { - var beatmap = apiBeatmap.ToBeatmap(Rulesets); + var beatmap = apiBeatmap.ToBeatmap(rulesets); Add(new TournamentBeatmapPanel(beatmap) { Anchor = Anchor.Centre, From b1862a863bd3f7d8c881c3eb50606cbc15191c6b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 14 Oct 2018 03:03:40 +0900 Subject: [PATCH 0178/5608] Fix not being able to decrement scores of matches with no defined progression --- .../Screens/Ladder/Components/DrawableMatchTeam.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 3edc28b4e5..dca8d0f0a8 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -141,7 +141,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } else { - if (pairing.Progression.Value?.Completed.Value != false) + if (pairing.Progression.Value?.Completed.Value == true) // don't allow changing scores if the match has a progression. can cause large data loss return false; From c4b486f1d4cf3d38219fea14d68589b16a0db29b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 14 Oct 2018 03:04:06 +0900 Subject: [PATCH 0179/5608] Fix transfer of teams in the case loser and winner progression are equal --- .../Ladder/Components/DrawableMatchPairing.cs | 54 ++++++++++++++----- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index da56f83d68..1f58bc86ea 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; +using osu.Game.Tournament.Components; using OpenTK; using OpenTK.Graphics; using OpenTK.Input; @@ -91,23 +92,50 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private void updateProgression() { - var progression = Pairing.Progression?.Value; - - if (progression != null) + if (!Pairing.Completed) { - bool progressionAbove = progression.ID < Pairing.ID; + // ensure we clear any of our teams from our progression. + // this is not pretty logic but should suffice for now. + if (Pairing.Progression.Value != null && Pairing.Progression.Value.Team1.Value == Pairing.Team1.Value) + Pairing.Progression.Value.Team1.Value = null; - var destinationForWinner = progressionAbove || progression.Team1.Value != null && progression.Team1.Value != Pairing.Team1.Value && progression.Team1.Value != Pairing.Team2.Value ? progression.Team2 : progression.Team1; - destinationForWinner.Value = Pairing.Winner; + if (Pairing.Progression.Value != null && Pairing.Progression.Value.Team2.Value == Pairing.Team2.Value) + Pairing.Progression.Value.Team2.Value = null; + + if (Pairing.LosersProgression.Value != null && Pairing.LosersProgression.Value.Team1.Value == Pairing.Team1.Value) + Pairing.LosersProgression.Value.Team1.Value = null; + + if (Pairing.LosersProgression.Value != null && Pairing.LosersProgression.Value.Team2.Value == Pairing.Team2.Value) + Pairing.LosersProgression.Value.Team2.Value = null; + } + else + { + transferProgression(Pairing.Progression?.Value, Pairing.Winner); + transferProgression(Pairing.LosersProgression?.Value, Pairing.Loser); + } + } + + private void transferProgression(MatchPairing destination, TournamentTeam team) + { + if (destination == null) return; + + bool progressionAbove = destination.ID < Pairing.ID; + + Bindable destinationTeam; + + // check for the case where we have already transferred out value + if (destination.Team1.Value == team) + destinationTeam = destination.Team1; + else if (destination.Team2.Value == team) + destinationTeam = destination.Team2; + else + { + destinationTeam = progressionAbove ? destination.Team2 : destination.Team1; + if (destinationTeam.Value != null) + destinationTeam = progressionAbove ? destination.Team1 : destination.Team2; } - if ((progression = Pairing.LosersProgression?.Value) != null) - { - bool progressionAbove = progression.ID < Pairing.ID; - - var destinationForLoser = progressionAbove || progression.Team1.Value != null && progression.Team1.Value != Pairing.Team1.Value && progression.Team1.Value != Pairing.Team2.Value ? progression.Team2 : progression.Team1; - destinationForLoser.Value = Pairing.Loser; - } + destinationTeam.Value = team; } private void updateWinConditions() From b17ead22a362082c4ac8d19983fe32cced8411c2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 14 Oct 2018 03:05:34 +0900 Subject: [PATCH 0180/5608] fixup! Fix incorrect access definitions --- osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs index e5cb2f155c..d6c9e0c901 100644 --- a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs +++ b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs @@ -16,10 +16,10 @@ namespace osu.Game.Tournament.Tests public class TestCaseBeatmapPanel : OsuTestCase { [Resolved] - private APIAccess api { get; set; } + private APIAccess api { get; set; } = null; [Resolved] - private RulesetStore rulesets { get; set; } + private RulesetStore rulesets { get; set; } = null; [BackgroundDependencyLoader] private void load() From a02caeef64d5fb12de8271be48e119193c01a532 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 14 Oct 2018 05:19:50 +0900 Subject: [PATCH 0181/5608] Add team intro screen Also adds dates to groups and matches (must be manually populated via json) --- .../TestCaseTeamOverview.cs | 18 ++ .../Screens/Ladder/Components/MatchPairing.cs | 3 + .../Ladder/Components/TournamentGrouping.cs | 3 + .../Screens/TeamIntro/TeamIntro.cs | 192 ++++++++++++++++++ 4 files changed, 216 insertions(+) create mode 100644 osu.Game.Tournament.Tests/TestCaseTeamOverview.cs create mode 100644 osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs diff --git a/osu.Game.Tournament.Tests/TestCaseTeamOverview.cs b/osu.Game.Tournament.Tests/TestCaseTeamOverview.cs new file mode 100644 index 0000000000..b853abb27c --- /dev/null +++ b/osu.Game.Tournament.Tests/TestCaseTeamOverview.cs @@ -0,0 +1,18 @@ +using System.Linq; +using osu.Game.Tournament.Screens.TeamIntro; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseTeamIntro : LadderTestCase + { + public TestCaseTeamIntro() + { + var team1 = Ladder.Teams.First(t => t.Acronym == "USA"); + var team2 = Ladder.Teams.First(t => t.Acronym == "JPN"); + + var round = Ladder.Groupings.First(g => g.Name == "Quarter Finals"); + + Add(new TeamIntroScreen(team1, team2, round)); + } + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index 93d1b7085c..5dc2009c4d 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using Newtonsoft.Json; using osu.Framework.Configuration; using osu.Game.Tournament.Components; @@ -42,6 +43,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [JsonIgnore] public readonly Bindable LosersProgression = new Bindable(); + public readonly Bindable Date = new Bindable(); + public Point Position; public MatchPairing() diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs index d7c89cb006..d8680b7210 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using osu.Framework.Configuration; @@ -13,6 +14,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly BindableInt BestOf = new BindableInt(9) { Default = 9, MinValue = 3, MaxValue = 23 }; + public readonly Bindable StartDate = new Bindable(); + public List Pairings = new List(); } } diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs new file mode 100644 index 0000000000..fce29a2c89 --- /dev/null +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs @@ -0,0 +1,192 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Screens; +using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Tournament.Screens.TeamIntro +{ + public class TeamIntroScreen : OsuScreen + { + public TeamIntroScreen(TournamentTeam team1, TournamentTeam team2, TournamentGrouping round) + { + RelativeSizeAxes = Axes.Both; + + InternalChildren = new Drawable[] + { + new Box + { + Colour = Color4.White, + RelativeSizeAxes = Axes.Both + }, + new TeamWithPlayers(team1, true) + { + RelativeSizeAxes = Axes.Both, + Margin = new MarginPadding(40), + Width = 0.5f, + Height = 0.6f, + Anchor = Anchor.Centre, + Origin = Anchor.CentreRight + }, + new TeamWithPlayers(team2) + { + RelativeSizeAxes = Axes.Both, + Margin = new MarginPadding(40), + Width = 0.5f, + Height = 0.6f, + Anchor = Anchor.Centre, + Origin = Anchor.CentreLeft + }, + new RoundDisplay(round) + { + RelativeSizeAxes = Axes.Both, + Height = 0.3f, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + } + }; + } + + private class RoundDisplay : CompositeDrawable + { + public RoundDisplay(TournamentGrouping group) + { + var col = OsuColour.Gray(0.33f); + + InternalChildren = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Colour = col, + Text = "COMING UP NEXT", + Font = "Exo2.0-SemiBold", + TextSize = 15, + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Colour = col, + Text = group.Name.Value, + Font = "Exo2.0-Light", + Spacing = new Vector2(10, 0), + TextSize = 50, + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Colour = col, + Text = group.StartDate.Value.ToString("dd MMMM HH:mm UTC"), + TextSize = 20, + }, + } + } + }; + } + } + + private class TeamWithPlayers : CompositeDrawable + { + private readonly Color4 red = new Color4(129, 68, 65, 255); + private readonly Color4 blue = new Color4(41, 91, 97, 255); + + public TeamWithPlayers(TournamentTeam team, bool left = false) + { + FillFlowContainer players; + var colour = left ? red : blue; + InternalChildren = new Drawable[] + { + new TeamDisplay(team, left ? "Team Red" : "Team Blue", colour) + { + Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = left ? Anchor.CentreRight : Anchor.CentreLeft, + }, + players = new FillFlowContainer + { + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(0, 5), + Padding = new MarginPadding(20), + Anchor = !left ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = !left ? Anchor.CentreRight : Anchor.CentreLeft, + RelativePositionAxes = Axes.Both, + X = left ? 0.1f : -0.1f, + }, + }; + + foreach (var p in team.Players) + players.Add(new OsuSpriteText + { + Text = p.Username, + TextSize = 24, + Colour = colour, + Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = left ? Anchor.CentreRight : Anchor.CentreLeft, + }); + } + + private class TeamDisplay : DrawableTournamentTeam + { + public TeamDisplay(TournamentTeam team, string teamName, Color4 colour) + : base(team) + { + AutoSizeAxes = Axes.Both; + + Flag.Anchor = Flag.Origin = Anchor.TopCentre; + Flag.RelativeSizeAxes = Axes.None; + Flag.Size = new Vector2(300, 200); + Flag.Scale = new Vector2(0.4f); + Flag.Margin = new MarginPadding { Bottom = 20 }; + + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + Children = new Drawable[] + { + Flag, + new OsuSpriteText + { + Text = team.FullName.ToUpper(), + TextSize = 40, + Colour = Color4.Black, + Font = "Exo2.0-Light", + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + }, + new OsuSpriteText + { + Text = teamName.ToUpper(), + TextSize = 20, + Colour = colour, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + } + } + }; + } + } + } + } +} From 0c4ea4beb102d0df710c94472a2fc92ed8e36e20 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 14 Oct 2018 05:20:10 +0900 Subject: [PATCH 0182/5608] Allow dynamic recompilation of beatmap panel testcase --- osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs index d6c9e0c901..93068f6224 100644 --- a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs +++ b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; @@ -21,6 +23,11 @@ namespace osu.Game.Tournament.Tests [Resolved] private RulesetStore rulesets { get; set; } = null; + public override IReadOnlyList RequiredTypes => new[] + { + typeof(TournamentBeatmapPanel), + }; + [BackgroundDependencyLoader] private void load() { From 63fbe4e946fc3bfcda0397646303207e66062a4c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 14 Oct 2018 18:00:28 +0900 Subject: [PATCH 0183/5608] Add map pool beatmaps to groupings --- osu.Game.Tournament.Tests/TestCaseTeamOverview.cs | 5 ++++- .../Screens/Ladder/Components/GroupingBeatmap.cs | 11 +++++++++++ .../Screens/Ladder/Components/TournamentGrouping.cs | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs diff --git a/osu.Game.Tournament.Tests/TestCaseTeamOverview.cs b/osu.Game.Tournament.Tests/TestCaseTeamOverview.cs index b853abb27c..006c8805c1 100644 --- a/osu.Game.Tournament.Tests/TestCaseTeamOverview.cs +++ b/osu.Game.Tournament.Tests/TestCaseTeamOverview.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using System.Linq; using osu.Game.Tournament.Screens.TeamIntro; @@ -10,7 +13,7 @@ namespace osu.Game.Tournament.Tests var team1 = Ladder.Teams.First(t => t.Acronym == "USA"); var team2 = Ladder.Teams.First(t => t.Acronym == "JPN"); - var round = Ladder.Groupings.First(g => g.Name == "Quarter Finals"); + var round = Ladder.Groupings.First(g => g.Name == "Finals"); Add(new TeamIntroScreen(team1, team2, round)); } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs b/osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs new file mode 100644 index 0000000000..7395a2ae5f --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + public class GroupingBeatmap + { + public int ID; + public string Mods; + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs index d8680b7210..7530910bc1 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs @@ -14,6 +14,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly BindableInt BestOf = new BindableInt(9) { Default = 9, MinValue = 3, MaxValue = 23 }; + public readonly List Beatmaps = new List(); + public readonly Bindable StartDate = new Bindable(); public List Pairings = new List(); From 61083190d08472cb709fa69382d4159db2fd6c6c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 14 Oct 2018 18:09:22 +0900 Subject: [PATCH 0184/5608] Add WIP map pool testcase --- osu.Game.Tournament.Tests/TestCaseMapPool.cs | 42 ++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 osu.Game.Tournament.Tests/TestCaseMapPool.cs diff --git a/osu.Game.Tournament.Tests/TestCaseMapPool.cs b/osu.Game.Tournament.Tests/TestCaseMapPool.cs new file mode 100644 index 0000000000..11d9a7806b --- /dev/null +++ b/osu.Game.Tournament.Tests/TestCaseMapPool.cs @@ -0,0 +1,42 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Ladder.Components; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseMapPool : LadderTestCase + { + public TestCaseMapPool() + { + var round = Ladder.Groupings.First(g => g.Name == "Finals"); + + Add(new MapPoolScreen(round)); + } + } + + public class MapPoolScreen : CompositeDrawable + { + private readonly FillFlowContainer maps; + + public MapPoolScreen(TournamentGrouping round) + { + InternalChildren = new Drawable[] + { + maps = new FillFlowContainer + { + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.Both, + }, + }; + + //foreach (var b in round.Beatmaps) + // maps.Add(new TournamentBeatmapPanel(new BeatmapInfo() { OnlineBeatmapID = b.ID })); + } + } +} From dea2acaea3f24b6fb33cf7f1746002e7151941f7 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sun, 14 Oct 2018 11:18:10 -0400 Subject: [PATCH 0185/5608] Add new interface that allows restarts --- .../Rulesets/Mods/IApplicableForceRestart.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 osu.Game/Rulesets/Mods/IApplicableForceRestart.cs diff --git a/osu.Game/Rulesets/Mods/IApplicableForceRestart.cs b/osu.Game/Rulesets/Mods/IApplicableForceRestart.cs new file mode 100644 index 0000000000..2c9a6b6cb9 --- /dev/null +++ b/osu.Game/Rulesets/Mods/IApplicableForceRestart.cs @@ -0,0 +1,16 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mods +{ + /// + /// Represents a mod which can override (and block) a fail. + /// + public interface IApplicableRestartOnFail : IApplicableMod + { + /// + /// Whether we allow restarting + /// + bool AllowRestart { get; } + } +} From fd774c6a09edf2abd7954e7fd4fc8703bd3d015e Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sun, 14 Oct 2018 11:18:52 -0400 Subject: [PATCH 0186/5608] Allow restarts in ModPerfect --- osu.Game/Rulesets/Mods/ModPerfect.cs | 4 +++- osu.Game/Screens/Play/Player.cs | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 802890866f..5d6065b4a2 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -6,13 +6,15 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModPerfect : ModSuddenDeath + public abstract class ModPerfect : ModSuddenDeath, IApplicableRestartOnFail { public override string Name => "Perfect"; public override string ShortenedName => "PF"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_perfect; public override string Description => "SS or quit."; + public bool AllowRestart => true; + protected override bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Accuracy.Value != 1; } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index b3cbeb3850..0577369b05 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -289,6 +289,12 @@ namespace osu.Game.Screens.Play if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) return false; + if (Beatmap.Value.Mods.Value.OfType().Any(m => m.AllowRestart)) + { + Restart(); + return false; + } + adjustableClock.Stop(); HasFailed = true; From 39c767af2d349e3219b20690208694a4eb7d778a Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sun, 14 Oct 2018 11:25:05 -0400 Subject: [PATCH 0187/5608] Update file name and update summary --- .../{IApplicableForceRestart.cs => IApplicableRestartOnFail.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game/Rulesets/Mods/{IApplicableForceRestart.cs => IApplicableRestartOnFail.cs} (86%) diff --git a/osu.Game/Rulesets/Mods/IApplicableForceRestart.cs b/osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs similarity index 86% rename from osu.Game/Rulesets/Mods/IApplicableForceRestart.cs rename to osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs index 2c9a6b6cb9..43b3f36624 100644 --- a/osu.Game/Rulesets/Mods/IApplicableForceRestart.cs +++ b/osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs @@ -4,7 +4,7 @@ namespace osu.Game.Rulesets.Mods { /// - /// Represents a mod which can override (and block) a fail. + /// Represents a mod which can request to restart on fail. /// public interface IApplicableRestartOnFail : IApplicableMod { From 3a5af47ee8c1149d53c8a3a315d1dc49017ce2a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 Oct 2018 15:20:12 +0900 Subject: [PATCH 0188/5608] Populate beatmaps with api information when not present --- osu.Game.Tournament.Tests/LadderTestCase.cs | 32 ++++++++++++++++++- .../TestCaseGroupingManager.cs | 6 ++++ .../TestCaseLadderManager.cs | 5 +-- osu.Game.Tournament.Tests/TestCaseMapPool.cs | 13 ++++---- .../TestCaseTeamOverview.cs | 4 ++- .../Ladder/Components/GroupingBeatmap.cs | 4 +++ osu.sln.DotSettings | 1 + 7 files changed, 55 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tournament.Tests/LadderTestCase.cs b/osu.Game.Tournament.Tests/LadderTestCase.cs index 3044451a9e..ee8cfb8f8a 100644 --- a/osu.Game.Tournament.Tests/LadderTestCase.cs +++ b/osu.Game.Tournament.Tests/LadderTestCase.cs @@ -3,8 +3,13 @@ using System.IO; using Newtonsoft.Json; +using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Rulesets; using osu.Game.Tests.Visual; using osu.Game.Tournament.Screens.Ladder.Components; @@ -14,10 +19,35 @@ namespace osu.Game.Tournament.Tests { protected LadderInfo Ladder; - protected LadderTestCase() + [Resolved] + private APIAccess api { get; set; } = null; + + [Resolved] + private RulesetStore rulesets { get; set; } = null; + + [BackgroundDependencyLoader] + private void load() { Ladder = File.Exists(@"bracket.json") ? JsonConvert.DeserializeObject(File.ReadAllText(@"bracket.json")) : new LadderInfo(); + bool addedInfo = false; + + foreach (var g in Ladder.Groupings) + foreach (var b in g.Beatmaps) + { + if (b.BeatmapInfo == null) + { + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); + req.Success += i => b.BeatmapInfo = i.ToBeatmap(rulesets); + req.Perform(api); + + addedInfo = true; + } + } + + if (addedInfo) + SaveChanges(); + Add(new OsuButton { Text = "Save Changes", diff --git a/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs b/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs index a0a4dfdc8b..2b79ba0225 100644 --- a/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -37,6 +38,11 @@ namespace osu.Game.Tournament.Tests } }); + } + + [BackgroundDependencyLoader] + private void load() + { foreach (var g in Ladder.Groupings) items.Add(new GroupingRow(g)); } diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index a7b93c8055..35a86e83b8 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -11,9 +11,10 @@ namespace osu.Game.Tournament.Tests public class TestCaseLadderManager : LadderTestCase { [Cached] - private readonly LadderManager manager; + private LadderManager manager; - public TestCaseLadderManager() + [BackgroundDependencyLoader] + private void load() { Add(new OsuContextMenuContainer { diff --git a/osu.Game.Tournament.Tests/TestCaseMapPool.cs b/osu.Game.Tournament.Tests/TestCaseMapPool.cs index 11d9a7806b..2c6999d6ae 100644 --- a/osu.Game.Tournament.Tests/TestCaseMapPool.cs +++ b/osu.Game.Tournament.Tests/TestCaseMapPool.cs @@ -2,9 +2,9 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; @@ -12,7 +12,8 @@ namespace osu.Game.Tournament.Tests { public class TestCaseMapPool : LadderTestCase { - public TestCaseMapPool() + [BackgroundDependencyLoader] + private void load() { var round = Ladder.Groupings.First(g => g.Name == "Finals"); @@ -22,10 +23,10 @@ namespace osu.Game.Tournament.Tests public class MapPoolScreen : CompositeDrawable { - private readonly FillFlowContainer maps; - public MapPoolScreen(TournamentGrouping round) { + FillFlowContainer maps; + InternalChildren = new Drawable[] { maps = new FillFlowContainer @@ -35,8 +36,8 @@ namespace osu.Game.Tournament.Tests }, }; - //foreach (var b in round.Beatmaps) - // maps.Add(new TournamentBeatmapPanel(new BeatmapInfo() { OnlineBeatmapID = b.ID })); + foreach (var b in round.Beatmaps) + maps.Add(new TournamentBeatmapPanel(b.BeatmapInfo)); } } } diff --git a/osu.Game.Tournament.Tests/TestCaseTeamOverview.cs b/osu.Game.Tournament.Tests/TestCaseTeamOverview.cs index 006c8805c1..52a5a7204c 100644 --- a/osu.Game.Tournament.Tests/TestCaseTeamOverview.cs +++ b/osu.Game.Tournament.Tests/TestCaseTeamOverview.cs @@ -2,13 +2,15 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; +using osu.Framework.Allocation; using osu.Game.Tournament.Screens.TeamIntro; namespace osu.Game.Tournament.Tests { public class TestCaseTeamIntro : LadderTestCase { - public TestCaseTeamIntro() + [BackgroundDependencyLoader] + private void load() { var team1 = Ladder.Teams.First(t => t.Acronym == "USA"); var team2 = Ladder.Teams.First(t => t.Acronym == "JPN"); diff --git a/osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs b/osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs index 7395a2ae5f..416f960404 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs @@ -1,11 +1,15 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Beatmaps; + namespace osu.Game.Tournament.Screens.Ladder.Components { public class GroupingBeatmap { public int ID; public string Mods; + + public BeatmapInfo BeatmapInfo; } } diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 404b19deda..345400305c 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -666,6 +666,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste True True True + True True True True From f324072d44d70ec439fe8ef17e95f7dff2d426a2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 Oct 2018 15:25:56 +0900 Subject: [PATCH 0189/5608] Make map pool layout more correct --- osu.Game.Tournament.Tests/TestCaseMapPool.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseMapPool.cs b/osu.Game.Tournament.Tests/TestCaseMapPool.cs index 2c6999d6ae..10ebd4e63c 100644 --- a/osu.Game.Tournament.Tests/TestCaseMapPool.cs +++ b/osu.Game.Tournament.Tests/TestCaseMapPool.cs @@ -5,8 +5,10 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Screens; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK; namespace osu.Game.Tournament.Tests { @@ -21,7 +23,7 @@ namespace osu.Game.Tournament.Tests } } - public class MapPoolScreen : CompositeDrawable + public class MapPoolScreen : OsuScreen { public MapPoolScreen(TournamentGrouping round) { @@ -31,13 +33,19 @@ namespace osu.Game.Tournament.Tests { maps = new FillFlowContainer { + Spacing = new Vector2(20), + Padding = new MarginPadding(50), Direction = FillDirection.Full, RelativeSizeAxes = Axes.Both, }, }; foreach (var b in round.Beatmaps) - maps.Add(new TournamentBeatmapPanel(b.BeatmapInfo)); + maps.Add(new TournamentBeatmapPanel(b.BeatmapInfo) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }); } } } From dfaff3aaed193ade60771e9e1b3b5a6e84158e72 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 Oct 2018 15:45:41 +0900 Subject: [PATCH 0190/5608] Fix filename mismatch --- .../{TestCaseTeamOverview.cs => TestCaseTeamIntro.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Tournament.Tests/{TestCaseTeamOverview.cs => TestCaseTeamIntro.cs} (100%) diff --git a/osu.Game.Tournament.Tests/TestCaseTeamOverview.cs b/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs similarity index 100% rename from osu.Game.Tournament.Tests/TestCaseTeamOverview.cs rename to osu.Game.Tournament.Tests/TestCaseTeamIntro.cs From 830eda2a9f15f274cd830b62005a62f0119d0346 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 Oct 2018 16:07:59 +0900 Subject: [PATCH 0191/5608] Fix unused properties --- osu.Game.Tournament/Components/TournamentTeam.cs | 4 ++++ .../Screens/Ladder/Components/TournamentGrouping.cs | 3 +++ 2 files changed, 7 insertions(+) diff --git a/osu.Game.Tournament/Components/TournamentTeam.cs b/osu.Game.Tournament/Components/TournamentTeam.cs index cb6fc9fb92..78e1386706 100644 --- a/osu.Game.Tournament/Components/TournamentTeam.cs +++ b/osu.Game.Tournament/Components/TournamentTeam.cs @@ -1,11 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; +using Newtonsoft.Json; using osu.Game.Users; namespace osu.Game.Tournament.Components { + [Serializable] public class TournamentTeam { /// @@ -35,6 +38,7 @@ namespace osu.Game.Tournament.Components set { acronym = value; } } + [JsonProperty] public List Players { get; set; } public override string ToString() => FullName ?? Acronym; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs index 7530910bc1..17f76a0143 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs @@ -3,10 +3,12 @@ using System; using System.Collections.Generic; +using Newtonsoft.Json; using osu.Framework.Configuration; namespace osu.Game.Tournament.Screens.Ladder.Components { + [Serializable] public class TournamentGrouping { public readonly Bindable Name = new Bindable(); @@ -14,6 +16,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly BindableInt BestOf = new BindableInt(9) { Default = 9, MinValue = 3, MaxValue = 23 }; + [JsonProperty] public readonly List Beatmaps = new List(); public readonly Bindable StartDate = new Bindable(); From 216de3c53d80882e4c3ef49f0d02167890790aa5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 Oct 2018 17:34:58 +0900 Subject: [PATCH 0192/5608] Don't cache manager --- osu.Game.Tournament.Tests/TestCaseLadderManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index 35a86e83b8..a7af038ca8 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -10,7 +10,6 @@ namespace osu.Game.Tournament.Tests { public class TestCaseLadderManager : LadderTestCase { - [Cached] private LadderManager manager; [BackgroundDependencyLoader] From 143d9d54f9ae5f8e3141ecf3158f8c66b039a905 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 Oct 2018 18:02:47 +0900 Subject: [PATCH 0193/5608] Add basic scene manager --- .../TestCaseSceneManager.cs | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 osu.Game.Tournament.Tests/TestCaseSceneManager.cs diff --git a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs new file mode 100644 index 0000000000..8a56ec883e --- /dev/null +++ b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs @@ -0,0 +1,93 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.UserInterface; +using osu.Game.Tournament.Screens.Ladder; +using osu.Game.Tournament.Screens.TeamIntro; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseSceneManager : LadderTestCase + { + private LadderManager bracket; + private MapPoolScreen mapPool; + private TeamIntroScreen teamIntro; + private Container screens; + + [BackgroundDependencyLoader] + private void load() + { + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Width = 0.2f, + Children = new Drawable[] + { + new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => setScreen(teamIntro) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => setScreen(mapPool) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => setScreen(bracket) }, + } + }, + }, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Size = new Vector2(0.8f), + Masking = true, + Children = new Drawable[] + { + new Box + { + Colour = Color4.White, + RelativeSizeAxes = Axes.Both, + }, + screens = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + bracket = new LadderManager(Ladder), + mapPool = new MapPoolScreen(Ladder.Groupings.First(g => g.Name == "Finals")), + teamIntro = new TeamIntroScreen(Ladder.Teams.First(t => t.Acronym == "USA"), Ladder.Teams.First(t => t.Acronym == "JPN"), Ladder.Groupings.First(g => g.Name == "Finals")) + } + }, + } + }, + }; + } + + private void setScreen(Drawable screen) + { + foreach (var s in screens.Children) + { + if (s == screen) + s.FadeIn(100); + else + s.FadeOut(100); + } + } + } +} From 7a753ad9e2750dcc6ee0f22b7748250edabf9e1f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Oct 2018 02:17:54 +0900 Subject: [PATCH 0194/5608] Change grouping title colours to match white background --- .../Screens/Ladder/Components/DrawableTournamentGrouping.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs index 8a38f402aa..bb984dd61b 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs @@ -4,6 +4,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; +using OpenTK.Graphics; namespace osu.Game.Tournament.Screens.Ladder.Components { @@ -21,6 +22,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components new OsuSpriteText { Text = grouping.Description.Value.ToUpper(), + Colour = Color4.Black, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre }, @@ -28,6 +30,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { Text = ((losers ? "Losers " : "") + grouping.Name).ToUpper(), Font = "Exo2.0-Bold", + Colour = Color4.Black, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre }, From 12c0b2c37d208b17e3787af4936da18178e6fe17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Oct 2018 02:18:09 +0900 Subject: [PATCH 0195/5608] Add test videos and adjust alignment to match --- .../TestCaseSceneManager.cs | 14 ++++++++++---- osu.Game.Tournament.Tests/TestCaseTeamIntro.cs | 7 ++++++- .../Screens/TeamIntro/TeamIntro.cs | 16 ++++++++-------- osu.Game/osu.Game.csproj | 2 +- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs index 8a56ec883e..a1434b3a31 100644 --- a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Video; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.TeamIntro; @@ -53,16 +54,18 @@ namespace osu.Game.Tournament.Tests new Container { RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + FillAspectRatio = 16/9f, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - Size = new Vector2(0.8f), + Size = new Vector2(0.8f, 1), Masking = true, Children = new Drawable[] { - new Box + new VideoSprite(@"C:\Users\Dean\BG Side Logo - OWC.m4v") { - Colour = Color4.White, RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, }, screens = new Container { @@ -71,12 +74,15 @@ namespace osu.Game.Tournament.Tests { bracket = new LadderManager(Ladder), mapPool = new MapPoolScreen(Ladder.Groupings.First(g => g.Name == "Finals")), - teamIntro = new TeamIntroScreen(Ladder.Teams.First(t => t.Acronym == "USA"), Ladder.Teams.First(t => t.Acronym == "JPN"), Ladder.Groupings.First(g => g.Name == "Finals")) + teamIntro = new TeamIntroScreen(Ladder.Teams.First(t => t.Acronym == "USA"), Ladder.Teams.First(t => t.Acronym == "JPN"), + Ladder.Groupings.First(g => g.Name == "Finals")) } }, } }, }; + + setScreen(teamIntro); } private void setScreen(Drawable screen) diff --git a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs b/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs index 52a5a7204c..fff28ba900 100644 --- a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs +++ b/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs @@ -3,6 +3,7 @@ using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Game.Tournament.Screens.TeamIntro; namespace osu.Game.Tournament.Tests @@ -17,7 +18,11 @@ namespace osu.Game.Tournament.Tests var round = Ladder.Groupings.First(g => g.Name == "Finals"); - Add(new TeamIntroScreen(team1, team2, round)); + Add(new TeamIntroScreen(team1, team2, round) + { + FillMode = FillMode.Fit, + FillAspectRatio = 16 / 9f + }); } } } diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs index fce29a2c89..f8820d570a 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs @@ -3,7 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Video; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Screens; @@ -22,15 +22,14 @@ namespace osu.Game.Tournament.Screens.TeamIntro InternalChildren = new Drawable[] { - new Box + new VideoSprite(@"C:\Users\Dean\BG Team - Both OWC.m4v") { - Colour = Color4.White, - RelativeSizeAxes = Axes.Both + RelativeSizeAxes = Axes.Both, + Loop = true, }, new TeamWithPlayers(team1, true) { RelativeSizeAxes = Axes.Both, - Margin = new MarginPadding(40), Width = 0.5f, Height = 0.6f, Anchor = Anchor.Centre, @@ -39,7 +38,6 @@ namespace osu.Game.Tournament.Screens.TeamIntro new TeamWithPlayers(team2) { RelativeSizeAxes = Axes.Both, - Margin = new MarginPadding(40), Width = 0.5f, Height = 0.6f, Anchor = Anchor.Centre, @@ -48,7 +46,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro new RoundDisplay(round) { RelativeSizeAxes = Axes.Both, - Height = 0.3f, + Height = 0.25f, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, } @@ -119,7 +117,9 @@ namespace osu.Game.Tournament.Screens.TeamIntro new TeamDisplay(team, left ? "Team Red" : "Team Blue", colour) { Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = left ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.Both, + X = (left ? -1 : 1) * 0.36f, }, players = new FillFlowContainer { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index cc21f4f6a4..cf1863a58c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 510b52a50379c8a8fab72d529c3dc74e9f89822d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C5=8Dtar=C5=8D=20Oreki?= Date: Thu, 18 Oct 2018 20:56:43 +0200 Subject: [PATCH 0196/5608] Update overrided functions to match their bases --- .../Graphics/UserInterface/TooltipIconButton.cs | 9 +++++---- osu.Game/Overlays/Changelog/ChangelogBadges.cs | 9 +++++---- osu.Game/Overlays/Changelog/Header/TextBadgePair.cs | 9 +++++---- .../Changelog/Header/TextBadgePairListing.cs | 13 +++++++------ osu.Game/Overlays/Changelog/StreamBadge.cs | 13 +++++++------ osu.Game/Overlays/ChangelogOverlay.cs | 2 +- 6 files changed, 30 insertions(+), 25 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index f26df3f8c1..8e26b2d47c 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Framework.Input.States; using System; @@ -69,21 +70,21 @@ namespace osu.Game.Graphics.UserInterface }; } - protected override bool OnClick(InputState state) + protected override bool OnClick(ClickEvent e) { if (isEnabled) { sampleClick?.Play(); Action?.Invoke(); } - return base.OnClick(state); + return base.OnClick(e); } - protected override bool OnHover(InputState state) + protected override bool OnHover(HoverEvent e) { if (isEnabled) sampleHover?.Play(); - return base.OnHover(state); + return base.OnHover(e); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index 365d808108..f5d263bec0 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -5,6 +5,7 @@ using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Online.API.Requests.Responses; using System; @@ -95,7 +96,7 @@ namespace osu.Game.Overlays.Changelog Selected?.Invoke(source.LatestBuild, EventArgs.Empty); } - protected override bool OnHover(InputState state) + protected override bool OnHover(HoverEvent e) { foreach (StreamBadge streamBadge in badgesContainer.Children) { @@ -109,10 +110,10 @@ namespace osu.Game.Overlays.Changelog else streamBadge.Deactivate(); } - return base.OnHover(state); + return base.OnHover(e); } - protected override void OnHoverLost(InputState state) + protected override void OnHoverLost(HoverLostEvent e) { foreach (StreamBadge streamBadge in badgesContainer.Children) { @@ -121,7 +122,7 @@ namespace osu.Game.Overlays.Changelog else if (streamBadge.LatestBuild.UpdateStream.Id == selectedStreamId) streamBadge.DisableDim(); } - base.OnHoverLost(state); + base.OnHoverLost(e); } } } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index dd4ca1ce0b..76db9e4444 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Graphics.UserInterface; using System; @@ -114,18 +115,18 @@ namespace osu.Game.Overlays.Changelog.Header .FadeIn(duration, easing); } - protected override bool OnHover(InputState state) + protected override bool OnHover(HoverEvent e) { if (!IsActivated) sampleHover?.Play(); - return base.OnHover(state); + return base.OnHover(e); } - protected override bool OnClick(InputState state) + protected override bool OnClick(ClickEvent e) { OnActivated(); sampleActivate?.Play(); - return base.OnClick(state); + return base.OnClick(e); } protected virtual void OnActivated() diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs index 31a06ce67d..19f1674551 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -4,6 +4,7 @@ using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; +using osu.Framework.Input.Events; using osu.Framework.Input.States; namespace osu.Game.Overlays.Changelog.Header @@ -48,23 +49,23 @@ namespace osu.Game.Overlays.Changelog.Header SetTextColour(badgeColour, 100); } - protected override bool OnClick(InputState state) + protected override bool OnClick(ClickEvent e) { Activate(); - return base.OnClick(state); + return base.OnClick(e); } - protected override bool OnHover(InputState state) + protected override bool OnHover(HoverEvent e) { LineBadge.Uncollapse(); - return base.OnHover(state); + return base.OnHover(e); } - protected override void OnHoverLost(InputState state) + protected override void OnHoverLost(HoverLostEvent e) { if (!IsActivated) LineBadge.Collapse(); - base.OnHoverLost(state); + base.OnHoverLost(e); } public void UpdateBadgeWidth() => LineBadge.ResizeWidthTo(Text.DrawWidth); diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index ad5a858545..552af17eb6 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -8,6 +8,7 @@ using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; @@ -107,23 +108,23 @@ namespace osu.Game.Overlays.Changelog } } - protected override bool OnClick(InputState state) + protected override bool OnClick(ClickEvent e) { Activate(false); sampleClick?.Play(); - return base.OnClick(state); + return base.OnClick(e); } - protected override bool OnHover(InputState state) + protected override bool OnHover(HoverEvent e) { sampleHover?.Play(); DisableDim(); this.FadeIn(transition_duration); lineBadge.Uncollapse(); - return base.OnHover(state); + return base.OnHover(e); } - protected override void OnHoverLost(InputState state) + protected override void OnHoverLost(HoverLostEvent e) { if (!isActivated) { @@ -132,7 +133,7 @@ namespace osu.Game.Overlays.Changelog } else EnableDim(); - base.OnHoverLost(state); + base.OnHoverLost(e); } public void EnableDim() => text.FadeTo(0.5f, transition_duration); diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index a14fa77da3..30b24d40bb 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -41,7 +41,7 @@ namespace osu.Game.Overlays private float savedScrollPosition; // receive input outside our bounds so we can trigger a close event on ourselves. - public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; public ChangelogOverlay() { From b8ac328ae9a02c639efd5670ca176c80d72feff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C5=8Dtar=C5=8D=20Oreki?= Date: Thu, 18 Oct 2018 21:04:21 +0200 Subject: [PATCH 0197/5608] Rename APIChangelog to APIChangelogBuild --- osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs | 2 +- .../Online/API/Requests/GetChangelogBuildRequest.cs | 2 +- .../API/Requests/GetChangelogLatestBuildsRequest.cs | 2 +- osu.Game/Online/API/Requests/GetChangelogRequest.cs | 2 +- .../{APIChangelog.cs => APIChangelogBuild.cs} | 6 +++--- osu.Game/Overlays/Changelog/ChangelogBadges.cs | 6 +++--- osu.Game/Overlays/Changelog/ChangelogContent.cs | 10 +++++----- osu.Game/Overlays/Changelog/ChangelogContentGroup.cs | 8 ++++---- osu.Game/Overlays/Changelog/StreamBadge.cs | 4 ++-- osu.Game/Overlays/ChangelogOverlay.cs | 10 +++++----- 10 files changed, 26 insertions(+), 26 deletions(-) rename osu.Game/Online/API/Requests/Responses/{APIChangelog.cs => APIChangelogBuild.cs} (95%) diff --git a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs index d64f1c00f7..2bd8cc2016 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual AddWaitStep(3); AddStep(@"Show with Lazer 2018.712.0", () => { - changelog.FetchAndShowBuild(new APIChangelog + changelog.FetchAndShowBuild(new APIChangelogBuild { Version = "2018.712.0", UpdateStream = new UpdateStream { Name = "lazer" }, diff --git a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs index 2338b90865..73d0ec6d20 100644 --- a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs @@ -5,7 +5,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { - public class GetChangelogBuildRequest : APIRequest + public class GetChangelogBuildRequest : APIRequest { private readonly string name; private readonly string version; diff --git a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs index 7940fd8ff5..314a03e7f6 100644 --- a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; namespace osu.Game.Online.API.Requests { - public class GetChangelogLatestBuildsRequest : APIRequest> + public class GetChangelogLatestBuildsRequest : APIRequest> { protected override string Target => @"changelog/latest-builds"; protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}"; // for testing diff --git a/osu.Game/Online/API/Requests/GetChangelogRequest.cs b/osu.Game/Online/API/Requests/GetChangelogRequest.cs index ec8536c607..b43f8d8ee1 100644 --- a/osu.Game/Online/API/Requests/GetChangelogRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogRequest.cs @@ -5,7 +5,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { - public class GetChangelogRequest : APIRequest + public class GetChangelogRequest : APIRequest { protected override string Target => @"changelog"; protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}/index"; // for testing diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs similarity index 95% rename from osu.Game/Online/API/Requests/Responses/APIChangelog.cs rename to osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs index da5437515c..86ee8b49dd 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelog.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; namespace osu.Game.Online.API.Requests.Responses { - public class APIChangelog + public class APIChangelogBuild { [JsonProperty("id")] public long Id { get; set; } @@ -40,10 +40,10 @@ namespace osu.Game.Online.API.Requests.Responses public class Versions { [JsonProperty("next")] - public APIChangelog Next { get; set; } + public APIChangelogBuild Next { get; set; } [JsonProperty("previous")] - public APIChangelog Previous { get; set; } + public APIChangelogBuild Previous { get; set; } } public class ChangelogEntry diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index f5d263bec0..875aa9cd58 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Changelog private const float vertical_padding = 20; private const float horizontal_padding = 85; - public delegate void SelectionHandler(APIChangelog releaseStream, EventArgs args); + public delegate void SelectionHandler(APIChangelogBuild releaseStream, EventArgs args); public event SelectionHandler Selected; @@ -46,9 +46,9 @@ namespace osu.Game.Overlays.Changelog }; } - public void Populate(List latestBuilds) + public void Populate(List latestBuilds) { - foreach (APIChangelog updateStream in latestBuilds) + foreach (APIChangelogBuild updateStream in latestBuilds) { var streamBadge = new StreamBadge(updateStream); streamBadge.Selected += onBadgeSelected; diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 588a61f678..fadfb9048f 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Changelog private APIAccess api; private ChangelogContentGroup changelogContentGroup; - public delegate void BuildSelectedEventHandler(APIChangelog build, EventArgs args); + public delegate void BuildSelectedEventHandler(APIChangelogBuild build, EventArgs args); public event BuildSelectedEventHandler BuildSelected; @@ -28,12 +28,12 @@ namespace osu.Game.Overlays.Changelog Padding = new MarginPadding{ Bottom = 100 }; } - public void ShowListing(APIChangelog[] changelog) + public void ShowListing(APIChangelogBuild[] changelog) { DateTime currentDate = new DateTime(); Clear(); - foreach (APIChangelog build in changelog) + foreach (APIChangelogBuild build in changelog) { if (build.CreatedAt.Date != currentDate) { @@ -71,7 +71,7 @@ namespace osu.Game.Overlays.Changelog } } - public void ShowBuild(APIChangelog changelogBuild) + public void ShowBuild(APIChangelogBuild changelogBuild) { Child = changelogContentGroup = new ChangelogContentGroup(changelogBuild); changelogContentGroup.GenerateText(changelogBuild.ChangelogEntries); @@ -80,7 +80,7 @@ namespace osu.Game.Overlays.Changelog changelogContentGroup.BuildSelected += OnBuildSelected; } - protected virtual void OnBuildSelected(APIChangelog build, EventArgs args) + protected virtual void OnBuildSelected(APIChangelogBuild build, EventArgs args) { BuildSelected?.Invoke(build, EventArgs.Empty); } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index c349f44d37..2dc8fd2bf7 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -21,13 +21,13 @@ namespace osu.Game.Overlays.Changelog private readonly SortedDictionary> categories = new SortedDictionary>(); - public delegate void BuildSelectedEventHandler(APIChangelog build, EventArgs args); + public delegate void BuildSelectedEventHandler(APIChangelogBuild build, EventArgs args); public event BuildSelectedEventHandler BuildSelected; public readonly FillFlowContainer ChangelogEntries; - public ChangelogContentGroup(APIChangelog build) + public ChangelogContentGroup(APIChangelogBuild build) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -115,7 +115,7 @@ namespace osu.Game.Overlays.Changelog }; } - public ChangelogContentGroup(APIChangelog build, bool newDate) + public ChangelogContentGroup(APIChangelogBuild build, bool newDate) { OsuHoverContainer clickableBuildText; RelativeSizeAxes = Axes.X; @@ -202,7 +202,7 @@ namespace osu.Game.Overlays.Changelog } } - protected virtual void OnBuildSelected(APIChangelog build) + protected virtual void OnBuildSelected(APIChangelogBuild build) { BuildSelected?.Invoke(build, EventArgs.Empty); } diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 552af17eb6..5fb466769e 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -33,10 +33,10 @@ namespace osu.Game.Overlays.Changelog private SampleChannel sampleClick; private SampleChannel sampleHover; - public readonly APIChangelog LatestBuild; + public readonly APIChangelogBuild LatestBuild; private readonly FillFlowContainer text; - public StreamBadge(APIChangelog latestBuild) + public StreamBadge(APIChangelogBuild latestBuild) { LatestBuild = latestBuild; Height = badge_height; diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 30b24d40bb..302a9b351f 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -152,7 +152,7 @@ namespace osu.Game.Overlays return false; } - private void onBuildSelected(APIChangelog build, EventArgs e) => FetchAndShowBuild(build); + private void onBuildSelected(APIChangelogBuild build, EventArgs e) => FetchAndShowBuild(build); private void fetchListing() { @@ -183,12 +183,12 @@ namespace osu.Game.Overlays /// /// Fetches and shows a specific build from a specific update stream. /// - /// Must contain at least and - /// . If and - /// are specified, the header will instantly display them. + /// Must contain at least and + /// . If and + /// are specified, the header will instantly display them. /// Whether to update badges. Should be set to false in case /// the function is called by selecting a badge, to avoid an infinite loop. - public void FetchAndShowBuild(APIChangelog build, bool updateBadges = true) + public void FetchAndShowBuild(APIChangelogBuild build, bool updateBadges = true) { var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); From 390d8d230fb41bd01de3d9d0af1f24eadcef30a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C5=8Dtar=C5=8D=20Oreki?= Date: Thu, 18 Oct 2018 21:30:09 +0200 Subject: [PATCH 0198/5608] Remove redundant usings --- osu.Game/Graphics/UserInterface/TooltipIconButton.cs | 1 - osu.Game/Overlays/Changelog/ChangelogBadges.cs | 1 - osu.Game/Overlays/Changelog/Header/TextBadgePair.cs | 1 - osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs | 1 - osu.Game/Overlays/Changelog/StreamBadge.cs | 1 - 5 files changed, 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index 8e26b2d47c..1233483054 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; -using osu.Framework.Input.States; using System; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index 875aa9cd58..eabe5fe258 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; -using osu.Framework.Input.States; using osu.Game.Online.API.Requests.Responses; using System; using System.Collections.Generic; diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index 76db9e4444..387b7d4405 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; -using osu.Framework.Input.States; using osu.Game.Graphics.UserInterface; using System; diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs index 19f1674551..ab4165b30b 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -5,7 +5,6 @@ using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Input.Events; -using osu.Framework.Input.States; namespace osu.Game.Overlays.Changelog.Header { diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 5fb466769e..dcae8dc04f 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; -using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; From d83ce7e4bb35b352f112d1353c4766b4006281be Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 19 Oct 2018 12:22:05 +0200 Subject: [PATCH 0199/5608] don't allow null values in FilterCriteria, ensure values in test instead --- .../Visual/TestCaseBeatmapCarousel.cs | 51 +++++++++++-------- .../Select/Carousel/CarouselBeatmap.cs | 7 +-- osu.Game/Screens/Select/FilterCriteria.cs | 4 +- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs index df42ba9d16..a57ef21dd9 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs @@ -65,6 +65,10 @@ namespace osu.Game.Tests.Visual carousel.SelectionChanged = s => currentSelection = s; + // not being hooked up to the config leads to the SR filter only showing 0 to 0 SR maps + // thus "filter" once to assume a 0 to 10 range + carousel.Filter(new TestCriteria()); + loadBeatmaps(beatmapSets); testTraversal(); @@ -150,9 +154,7 @@ namespace osu.Game.Tests.Visual private bool selectedBeatmapVisible() { var currentlySelected = carousel.Items.FirstOrDefault(s => s.Item is CarouselBeatmap && s.Item.State == CarouselItemState.Selected); - if (currentlySelected == null) - return true; - return currentlySelected.Item.Visible; + return currentlySelected?.Item.Visible ?? true; } private void checkInvisibleDifficultiesUnselectable() @@ -165,8 +167,8 @@ namespace osu.Game.Tests.Visual { AddStep("Toggle non-matching filter", () => { - carousel.Filter(new FilterCriteria { SearchText = "Dingo" }, false); - carousel.Filter(new FilterCriteria(), false); + carousel.Filter(new TestCriteria { SearchText = "Dingo" }, false); + carousel.Filter(new TestCriteria(), false); eagerSelectedIDs.Add(carousel.SelectedBeatmapSet.ID); } ); @@ -207,7 +209,7 @@ namespace osu.Game.Tests.Visual setSelected(1, 1); - AddStep("Filter", () => carousel.Filter(new FilterCriteria { SearchText = "set #3!" }, false)); + AddStep("Filter", () => carousel.Filter(new TestCriteria { SearchText = "set #3!" }, false)); checkVisibleItemCount(diff: false, count: 1); checkVisibleItemCount(diff: true, count: 3); checkSelected(3, 1); @@ -215,7 +217,7 @@ namespace osu.Game.Tests.Visual advanceSelection(diff: true, count: 4); checkSelected(3, 2); - AddStep("Un-filter (debounce)", () => carousel.Filter(new FilterCriteria())); + AddStep("Un-filter (debounce)", () => carousel.Filter(new TestCriteria())); AddUntilStep(() => !carousel.PendingFilterTask, "Wait for debounce"); checkVisibleItemCount(diff: false, count: set_count); checkVisibleItemCount(diff: true, count: 3); @@ -223,13 +225,13 @@ namespace osu.Game.Tests.Visual // test filtering some difficulties (and keeping current beatmap set selected). setSelected(1, 2); - AddStep("Filter some difficulties", () => carousel.Filter(new FilterCriteria { SearchText = "Normal" }, false)); + AddStep("Filter some difficulties", () => carousel.Filter(new TestCriteria { SearchText = "Normal" }, false)); checkSelected(1, 1); - AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); + AddStep("Un-filter", () => carousel.Filter(new TestCriteria(), false)); checkSelected(1, 1); - AddStep("Filter all", () => carousel.Filter(new FilterCriteria { SearchText = "Dingo" }, false)); + AddStep("Filter all", () => carousel.Filter(new TestCriteria { SearchText = "Dingo" }, false)); checkVisibleItemCount(false, 0); checkVisibleItemCount(true, 0); @@ -241,7 +243,7 @@ namespace osu.Game.Tests.Visual advanceSelection(false); AddAssert("Selection is null", () => currentSelection == null); - AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); + AddStep("Un-filter", () => carousel.Filter(new TestCriteria(), false)); AddAssert("Selection is non-null", () => currentSelection != null); } @@ -273,15 +275,15 @@ namespace osu.Game.Tests.Visual AddStep("select added set", () => carousel.SelectBeatmap(manyStarDiffs.Beatmaps[0], false)); - AddStep("Filter to 1-3 stars", () => carousel.Filter(new FilterCriteria { DisplayStarsMinimum = 1, DisplayStarsMaximum = 3 }, false)); + AddStep("Filter to 1-3 stars", () => carousel.Filter(new TestCriteria { DisplayStarsMinimum = 1, DisplayStarsMaximum = 3 }, false)); checkVisibleItemCount(diff: false, count: 1); checkVisibleItemCount(diff: true, count: 3); - AddStep("Filter to 3-3 stars", () => carousel.Filter(new FilterCriteria { DisplayStarsMinimum = 3, DisplayStarsMaximum = 3 }, false)); + AddStep("Filter to 3-3 stars", () => carousel.Filter(new TestCriteria { DisplayStarsMinimum = 3, DisplayStarsMaximum = 3 }, false)); checkVisibleItemCount(diff: false, count: 1); checkVisibleItemCount(diff: true, count: 1); - AddStep("Filter to 4-2 stars", () => carousel.Filter(new FilterCriteria { DisplayStarsMinimum = 4, DisplayStarsMaximum = 2 }, false)); + AddStep("Filter to 4-2 stars", () => carousel.Filter(new TestCriteria { DisplayStarsMinimum = 4, DisplayStarsMaximum = 2 }, false)); checkVisibleItemCount(diff: false, count: 0); checkVisibleItemCount(diff: true, count: 0); @@ -291,7 +293,7 @@ namespace osu.Game.Tests.Visual manyStarDiffs = null; }); - AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); + AddStep("Un-filter", () => carousel.Filter(new TestCriteria(), false)); } /// @@ -322,13 +324,13 @@ namespace osu.Game.Tests.Visual AddAssert("ensure repeat", () => selectedSets.Contains(carousel.SelectedBeatmapSet)); AddStep("Add set with 100 difficulties", () => carousel.UpdateBeatmapSet(createTestBeatmapSetWithManyDifficulties(set_count + 1))); - AddStep("Filter Extra", () => carousel.Filter(new FilterCriteria { SearchText = "Extra 10" }, false)); + AddStep("Filter Extra", () => carousel.Filter(new TestCriteria { SearchText = "Extra 10" }, false)); checkInvisibleDifficultiesUnselectable(); checkInvisibleDifficultiesUnselectable(); checkInvisibleDifficultiesUnselectable(); checkInvisibleDifficultiesUnselectable(); checkInvisibleDifficultiesUnselectable(); - AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); + AddStep("Un-filter", () => carousel.Filter(new TestCriteria(), false)); } /// @@ -359,9 +361,9 @@ namespace osu.Game.Tests.Visual /// private void testSorting() { - AddStep("Sort by author", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Author }, false)); + AddStep("Sort by author", () => carousel.Filter(new TestCriteria { Sort = SortMode.Author }, false)); AddAssert("Check zzzzz is at bottom", () => carousel.BeatmapSets.Last().Metadata.AuthorString == "zzzzz"); - AddStep("Sort by artist", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Artist }, false)); + AddStep("Sort by artist", () => carousel.Filter(new TestCriteria { Sort = SortMode.Artist }, false)); AddAssert($"Check #{set_count} is at bottom", () => carousel.BeatmapSets.Last().Metadata.Title.EndsWith($"#{set_count}!")); } @@ -451,7 +453,7 @@ namespace osu.Game.Tests.Visual carousel.UpdateBeatmapSet(testMixed); }); AddStep("filter to ruleset 0", () => - carousel.Filter(new FilterCriteria { Ruleset = rulesets.AvailableRulesets.ElementAt(0) }, false)); + carousel.Filter(new TestCriteria { Ruleset = rulesets.AvailableRulesets.ElementAt(0) }, false)); AddStep("select filtered map skipping filtered", () => carousel.SelectBeatmap(testMixed.Beatmaps[1], false)); AddAssert("unfiltered beatmap selected", () => carousel.SelectedBeatmap.Equals(testMixed.Beatmaps[0])); @@ -581,5 +583,14 @@ namespace osu.Game.Tests.Visual public bool PendingFilterTask => PendingFilter != null; } + + private class TestCriteria : FilterCriteria + { + public TestCriteria() + { + DisplayStarsMinimum = 0; + DisplayStarsMaximum = 10; + } + } } } diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index c9ed2f3573..2e1adaf66f 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -25,12 +25,7 @@ namespace osu.Game.Screens.Select.Carousel base.Filter(criteria); bool match = criteria.Ruleset == null || Beatmap.RulesetID == criteria.Ruleset.ID || Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps; - - if(criteria.DisplayStarsMinimum.HasValue) - match &= Beatmap.StarDifficulty >= criteria.DisplayStarsMinimum; - - if (criteria.DisplayStarsMaximum.HasValue) - match &= Beatmap.StarDifficulty <= criteria.DisplayStarsMaximum; + match &= Beatmap.StarDifficulty >= criteria.DisplayStarsMinimum && Beatmap.StarDifficulty <= criteria.DisplayStarsMaximum; if (!string.IsNullOrEmpty(criteria.SearchText)) match &= diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index f97eb1bea1..bd8bb22e1c 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.Select public string SearchText; public RulesetInfo Ruleset; public bool AllowConvertedBeatmaps; - public double? DisplayStarsMinimum; - public double? DisplayStarsMaximum; + public double DisplayStarsMinimum; + public double DisplayStarsMaximum; } } From 5568e9ff8a6b9993dae33e41388e768a67366f74 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Oct 2018 01:29:08 +0900 Subject: [PATCH 0200/5608] Reduce test case crashes when missing data is present --- osu.Game.Tournament.Tests/TestCaseMapPool.cs | 7 +++-- .../TestCaseTeamIntro.cs | 6 ++-- .../Screens/TeamIntro/TeamIntro.cs | 28 +++++++++++-------- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseMapPool.cs b/osu.Game.Tournament.Tests/TestCaseMapPool.cs index 10ebd4e63c..e4637b8fc3 100644 --- a/osu.Game.Tournament.Tests/TestCaseMapPool.cs +++ b/osu.Game.Tournament.Tests/TestCaseMapPool.cs @@ -17,9 +17,10 @@ namespace osu.Game.Tournament.Tests [BackgroundDependencyLoader] private void load() { - var round = Ladder.Groupings.First(g => g.Name == "Finals"); + var round = Ladder.Groupings.FirstOrDefault(g => g.Name == "Finals"); - Add(new MapPoolScreen(round)); + if (round != null) + Add(new MapPoolScreen(round)); } } @@ -37,7 +38,7 @@ namespace osu.Game.Tournament.Tests Padding = new MarginPadding(50), Direction = FillDirection.Full, RelativeSizeAxes = Axes.Both, - }, + } }; foreach (var b in round.Beatmaps) diff --git a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs b/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs index fff28ba900..845f5638a0 100644 --- a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs +++ b/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs @@ -13,10 +13,10 @@ namespace osu.Game.Tournament.Tests [BackgroundDependencyLoader] private void load() { - var team1 = Ladder.Teams.First(t => t.Acronym == "USA"); - var team2 = Ladder.Teams.First(t => t.Acronym == "JPN"); + var team1 = Ladder.Teams.FirstOrDefault(t => t.Acronym == "USA"); + var team2 = Ladder.Teams.FirstOrDefault(t => t.Acronym == "JPN"); - var round = Ladder.Groupings.First(g => g.Name == "Finals"); + var round = Ladder.Groupings.FirstOrDefault(g => g.Name == "Finals"); Add(new TeamIntroScreen(team1, team2, round) { diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs index f8820d570a..766feaa806 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Video; @@ -84,7 +85,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Colour = col, - Text = group.Name.Value, + Text = group?.Name.Value ?? "Unknown Grouping", Font = "Exo2.0-Light", Spacing = new Vector2(10, 0), TextSize = 50, @@ -94,7 +95,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Colour = col, - Text = group.StartDate.Value.ToString("dd MMMM HH:mm UTC"), + Text = (group?.StartDate.Value ?? DateTimeOffset.Now).ToString("dd MMMM HH:mm UTC"), TextSize = 20, }, } @@ -134,15 +135,18 @@ namespace osu.Game.Tournament.Screens.TeamIntro }, }; - foreach (var p in team.Players) - players.Add(new OsuSpriteText - { - Text = p.Username, - TextSize = 24, - Colour = colour, - Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = left ? Anchor.CentreRight : Anchor.CentreLeft, - }); + if (team != null) + { + foreach (var p in team.Players) + players.Add(new OsuSpriteText + { + Text = p.Username, + TextSize = 24, + Colour = colour, + Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = left ? Anchor.CentreRight : Anchor.CentreLeft, + }); + } } private class TeamDisplay : DrawableTournamentTeam @@ -168,7 +172,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Flag, new OsuSpriteText { - Text = team.FullName.ToUpper(), + Text = team?.FullName.ToUpper() ?? "???", TextSize = 40, Colour = Color4.Black, Font = "Exo2.0-Light", From eacc0fe7964ca94fcdaf9ad170e4804ae3d14ab3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 2 Sep 2018 02:12:09 +0900 Subject: [PATCH 0201/5608] Use local framework --- osu.Game/osu.Game.csproj | 2 +- osu.sln | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index cf1863a58c..3022b66762 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -11,6 +11,7 @@ + @@ -18,7 +19,6 @@ - diff --git a/osu.sln b/osu.sln index f6ed7a5c42..c62fc02dba 100644 --- a/osu.sln +++ b/osu.sln @@ -31,6 +31,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament", "osu. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament.Tests", "osu.Game.Tournament.Tests\osu.Game.Tournament.Tests.csproj", "{5789E78D-38F9-4072-AB7B-978F34B2C17F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework", "..\osu-framework\osu.Framework\osu.Framework.csproj", "{7A69A230-45A1-4444-8C43-A582E4F48C1E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -93,6 +95,10 @@ Global {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|Any CPU.Build.0 = Debug|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.ActiveCfg = Release|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.Build.0 = Release|Any CPU + {7A69A230-45A1-4444-8C43-A582E4F48C1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A69A230-45A1-4444-8C43-A582E4F48C1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A69A230-45A1-4444-8C43-A582E4F48C1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A69A230-45A1-4444-8C43-A582E4F48C1E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From d7d83a27d40289d73e819984721a9b18a0fa94e6 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Wed, 24 Oct 2018 13:36:35 -0400 Subject: [PATCH 0202/5608] Add restart as mods settings --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 9ac2cabe9f..bcdd3acd10 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -84,6 +84,7 @@ namespace osu.Game.Configuration Set(OsuSetting.ScoreDisplayMode, ScoringMode.Standardised); Set(OsuSetting.IncreaseFirstObjectVisibility, true); + Set(OsuSetting.RestartOnFail, false); // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -148,6 +149,7 @@ namespace osu.Game.Configuration BeatmapSkins, BeatmapHitsounds, IncreaseFirstObjectVisibility, + RestartOnFail, ScoreDisplayMode } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index a9cefa81da..a3a0bf118b 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -20,6 +20,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay LabelText = "Increase visibility of first object with \"Hidden\" mod", Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility) }, + new SettingsCheckbox + { + LabelText = "Restart on fail with \"Perfect\" and \"Sudden Death\" mod", + Bindable = config.GetBindable(OsuSetting.RestartOnFail) + }, }; } } From 794afa988fe6e599ca9e13a1de130d7a765bf4c0 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Wed, 24 Oct 2018 13:37:27 -0400 Subject: [PATCH 0203/5608] Make both SD and PF auto-restart based on settings --- osu.Game/Rulesets/Mods/ModPerfect.cs | 4 +--- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 12 +++++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 5d6065b4a2..802890866f 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -6,15 +6,13 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModPerfect : ModSuddenDeath, IApplicableRestartOnFail + public abstract class ModPerfect : ModSuddenDeath { public override string Name => "Perfect"; public override string ShortenedName => "PF"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_perfect; public override string Description => "SS or quit."; - public bool AllowRestart => true; - protected override bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Accuracy.Value != 1; } } diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 48f7d496a5..af7d9be785 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -3,11 +3,13 @@ using System; using osu.Game.Graphics; +using osu.Game.Configuration; using osu.Game.Rulesets.Scoring; +using osu.Framework.Configuration; namespace osu.Game.Rulesets.Mods { - public abstract class ModSuddenDeath : Mod, IApplicableToScoreProcessor + public abstract class ModSuddenDeath : Mod, IReadFromConfig, IApplicableToScoreProcessor, IApplicableRestartOnFail { public override string Name => "Sudden Death"; public override string ShortenedName => "SD"; @@ -18,11 +20,19 @@ namespace osu.Game.Rulesets.Mods public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; + protected Bindable RestartOnFail = new Bindable(); + public bool AllowRestart => RestartOnFail.Value; + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { scoreProcessor.FailConditions += FailCondition; } + public void ReadFromConfig(OsuConfigManager config) + { + RestartOnFail = config.GetBindable(OsuSetting.RestartOnFail); + } + protected virtual bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Combo.Value == 0; } } From cb9ec94dc2af3c511554b9a8a6ce0439164938c9 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Mon, 29 Oct 2018 08:19:38 -0400 Subject: [PATCH 0204/5608] Remove option from settings --- osu.Game/Configuration/OsuConfigManager.cs | 2 -- .../Settings/Sections/Gameplay/ModsSettings.cs | 5 ----- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 10 ++-------- 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index bcdd3acd10..9ac2cabe9f 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -84,7 +84,6 @@ namespace osu.Game.Configuration Set(OsuSetting.ScoreDisplayMode, ScoringMode.Standardised); Set(OsuSetting.IncreaseFirstObjectVisibility, true); - Set(OsuSetting.RestartOnFail, false); // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -149,7 +148,6 @@ namespace osu.Game.Configuration BeatmapSkins, BeatmapHitsounds, IncreaseFirstObjectVisibility, - RestartOnFail, ScoreDisplayMode } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index a3a0bf118b..a9cefa81da 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -20,11 +20,6 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay LabelText = "Increase visibility of first object with \"Hidden\" mod", Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility) }, - new SettingsCheckbox - { - LabelText = "Restart on fail with \"Perfect\" and \"Sudden Death\" mod", - Bindable = config.GetBindable(OsuSetting.RestartOnFail) - }, }; } } diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index af7d9be785..77e08dff86 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -9,7 +9,7 @@ using osu.Framework.Configuration; namespace osu.Game.Rulesets.Mods { - public abstract class ModSuddenDeath : Mod, IReadFromConfig, IApplicableToScoreProcessor, IApplicableRestartOnFail + public abstract class ModSuddenDeath : Mod, IApplicableToScoreProcessor, IApplicableRestartOnFail { public override string Name => "Sudden Death"; public override string ShortenedName => "SD"; @@ -20,19 +20,13 @@ namespace osu.Game.Rulesets.Mods public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; - protected Bindable RestartOnFail = new Bindable(); - public bool AllowRestart => RestartOnFail.Value; + public bool AllowRestart => true; public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { scoreProcessor.FailConditions += FailCondition; } - public void ReadFromConfig(OsuConfigManager config) - { - RestartOnFail = config.GetBindable(OsuSetting.RestartOnFail); - } - protected virtual bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Combo.Value == 0; } } From 52b9a3f5e9a0096ff5529a223a317b8b489977ec Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Mon, 29 Oct 2018 17:51:49 -0400 Subject: [PATCH 0205/5608] Remove unused using --- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 77e08dff86..733fd6345a 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -3,9 +3,7 @@ using System; using osu.Game.Graphics; -using osu.Game.Configuration; using osu.Game.Rulesets.Scoring; -using osu.Framework.Configuration; namespace osu.Game.Rulesets.Mods { From 007dfedbb751fa0e4767740e39fcc621e73cdf54 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Tue, 30 Oct 2018 07:12:06 -0400 Subject: [PATCH 0206/5608] Combine RestartOnFail into FailOverride --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 1 + .../Rulesets/Mods/IApplicableFailOverride.cs | 5 +++++ .../Rulesets/Mods/IApplicableRestartOnFail.cs | 16 ---------------- osu.Game/Rulesets/Mods/ModAutoplay.cs | 1 + osu.Game/Rulesets/Mods/ModNoFail.cs | 1 + osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 5 +++-- osu.Game/Screens/Play/Player.cs | 2 +- 7 files changed, 12 insertions(+), 19 deletions(-) delete mode 100644 osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 8d27502b3c..2240425654 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -19,6 +19,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray(); public bool AllowFail => false; + public bool RestartOnFail => false; public void Update(Playfield playfield) { diff --git a/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs b/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs index 6a4042a906..f650259373 100644 --- a/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs +++ b/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs @@ -12,5 +12,10 @@ namespace osu.Game.Rulesets.Mods /// Whether we should allow failing at the current point in time. /// bool AllowFail { get; } + + /// + /// Whether we want to restart on fail. Only used if AllowFail is true. + /// + bool RestartOnFail { get; } } } diff --git a/osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs b/osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs deleted file mode 100644 index 43b3f36624..0000000000 --- a/osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Rulesets.Mods -{ - /// - /// Represents a mod which can request to restart on fail. - /// - public interface IApplicableRestartOnFail : IApplicableMod - { - /// - /// Whether we allow restarting - /// - bool AllowRestart { get; } - } -} diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 5c03cb9736..849eaeeb5a 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -30,6 +30,7 @@ namespace osu.Game.Rulesets.Mods public override string Description => "Watch a perfect automated play through the song."; public override double ScoreMultiplier => 1; public bool AllowFail => false; + public bool RestartOnFail => false; public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) }; } } diff --git a/osu.Game/Rulesets/Mods/ModNoFail.cs b/osu.Game/Rulesets/Mods/ModNoFail.cs index 7510f62432..c30c6d712d 100644 --- a/osu.Game/Rulesets/Mods/ModNoFail.cs +++ b/osu.Game/Rulesets/Mods/ModNoFail.cs @@ -21,5 +21,6 @@ namespace osu.Game.Rulesets.Mods /// We never fail, 'yo. /// public bool AllowFail => false; + public bool RestartOnFail => false; } } diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 733fd6345a..252df98f32 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModSuddenDeath : Mod, IApplicableToScoreProcessor, IApplicableRestartOnFail + public abstract class ModSuddenDeath : Mod, IApplicableToScoreProcessor, IApplicableFailOverride { public override string Name => "Sudden Death"; public override string ShortenedName => "SD"; @@ -18,7 +18,8 @@ namespace osu.Game.Rulesets.Mods public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; - public bool AllowRestart => true; + public bool AllowFail => true; + public bool RestartOnFail => true; public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0577369b05..863cfeda07 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -289,7 +289,7 @@ namespace osu.Game.Screens.Play if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) return false; - if (Beatmap.Value.Mods.Value.OfType().Any(m => m.AllowRestart)) + if (Beatmap.Value.Mods.Value.OfType().Any(m => m.RestartOnFail)) { Restart(); return false; From d8f97a32c779f40005c6328c925ec9c327a5b54a Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Wed, 31 Oct 2018 07:03:37 -0400 Subject: [PATCH 0207/5608] Make sure restart on fail actually fails --- osu.Game/Screens/Play/Player.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 863cfeda07..b388387866 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -289,15 +289,16 @@ namespace osu.Game.Screens.Play if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) return false; - if (Beatmap.Value.Mods.Value.OfType().Any(m => m.RestartOnFail)) - { - Restart(); - return false; - } - adjustableClock.Stop(); HasFailed = true; + + if (Beatmap.Value.Mods.Value.OfType().Any(m => m.RestartOnFail)) + { + Restart(); + return true; + } + failOverlay.Retries = RestartCount; failOverlay.Show(); return true; From 9f5546fd62f92a863ce7e0b930271a7ab936ed44 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Nov 2018 21:13:46 +0900 Subject: [PATCH 0208/5608] Fix API regression in direct --- osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 4 ++-- osu.Game/osu.Game.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index c9ea66d05f..55eee11664 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -61,13 +61,13 @@ namespace osu.Game.Online.API.Requests.Responses { return new BeatmapInfo { - Metadata = !string.IsNullOrEmpty(Artist) ? this : (BeatmapMetadata)BeatmapSet, + Metadata = !string.IsNullOrEmpty(Artist) ? this : BeatmapSet as BeatmapMetadata, Ruleset = rulesets.GetRuleset(ruleset), StarDifficulty = starDifficulty, OnlineBeatmapID = OnlineBeatmapID, Version = version, Status = Status, - BeatmapSet = BeatmapSet.ToBeatmapSet(rulesets), + BeatmapSet = BeatmapSet?.ToBeatmapSet(rulesets), BaseDifficulty = new BeatmapDifficulty { DrainRate = drainRate, diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 921da942f0..e641c93ad3 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -19,7 +19,7 @@ - + From b610095ff598e29e0020dcd68ca75705feac1c7c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 4 Nov 2018 04:58:35 +0900 Subject: [PATCH 0209/5608] Update drawings design --- .../Components/ScrollingTeamContainer.cs | 3 + .../Screens/Drawings/DrawingsScreen.cs | 260 +++++++++--------- 2 files changed, 131 insertions(+), 132 deletions(-) diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index 816a3ef958..6e050fd0bb 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Threading; +using osu.Game.Graphics; using osu.Game.Tournament.Components; using OpenTK; using OpenTK.Graphics; @@ -52,6 +53,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.33f), Masking = true, CornerRadius = 10f, @@ -358,6 +360,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components outline = new Box { RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.33f), Alpha = 0 }, Flag diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 8e6738d8d6..38f0be0d5a 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -12,13 +12,14 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Framework.Platform; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Screens; -using osu.Game.Screens.Backgrounds; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Drawings.Components; using OpenTK; @@ -32,7 +33,7 @@ namespace osu.Game.Tournament.Screens.Drawings protected override bool HideOverlaysOnEnter => true; - protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault(); + protected override BackgroundScreen CreateBackground() => null; private ScrollingTeamContainer teamsContainer; private GroupContainer groupsContainer; @@ -56,6 +57,8 @@ namespace osu.Game.Tournament.Screens.Drawings [BackgroundDependencyLoader] private void load(TextureStore textures, Storage storage) { + RelativeSizeAxes = Axes.Both; + this.storage = storage; TextureStore flagStore = new TextureStore(); @@ -79,168 +82,161 @@ namespace osu.Game.Tournament.Screens.Drawings Children = new Drawable[] { - new Box + // Main container + new Container { RelativeSizeAxes = Axes.Both, - Colour = new Color4(77, 77, 77, 255) + Children = new Drawable[] + { + new VideoSprite(@"C:\Users\Dean\BG Logoless - OWC.m4v") + { + RelativeSizeAxes = Axes.Both, + Loop = true, + }, + new Sprite + { + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fill, + Texture = textures.Get(@"Backgrounds/Drawings/background.png") + }, + // Visualiser + new VisualiserContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + + RelativeSizeAxes = Axes.X, + Size = new Vector2(1, 10), + + Colour = new Color4(255, 204, 34, 255), + + Lines = 6 + }, + // Groups + groupsContainer = new GroupContainer(drawingsConfig.Get(DrawingsConfig.Groups), drawingsConfig.Get(DrawingsConfig.TeamsPerGroup)) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + + Padding = new MarginPadding + { + Top = 35f, + Bottom = 35f + } + }, + // Scrolling teams + teamsContainer = new ScrollingTeamContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + + RelativeSizeAxes = Axes.X, + }, + // Scrolling team name + fullTeamNameText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.TopCentre, + + Position = new Vector2(0, 45f), + + Colour = OsuColour.Gray(0.33f), + + Alpha = 0, + + Font = "Exo2.0-Light", + TextSize = 42f + } + } }, - new Sprite + // Control panel container + new Container { RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fill, - Texture = textures.Get(@"Backgrounds/Drawings/background.png") - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, + AlwaysPresent = true, + Width = 0.15f, + Anchor = Anchor.TopRight, Children = new Drawable[] { - // Main container - new Container + new Box { RelativeSizeAxes = Axes.Both, - Width = 0.85f, + Colour = new Color4(54, 54, 54, 255) + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + + Text = "Control Panel", + TextSize = 22f, + Font = "Exo2.0-Bold" + }, + new FillFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Width = 0.75f, + + Position = new Vector2(0, 35f), + + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5f), Children = new Drawable[] { - // Visualiser - new VisualiserContainer + new TriangleButton { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, - Size = new Vector2(1, 10), - Colour = new Color4(255, 204, 34, 255), - - Lines = 6 + Text = "Begin random", + Action = teamsContainer.StartScrolling, }, - // Groups - groupsContainer = new GroupContainer(drawingsConfig.Get(DrawingsConfig.Groups), drawingsConfig.Get(DrawingsConfig.TeamsPerGroup)) + new TriangleButton { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - - Padding = new MarginPadding - { - Top = 35f, - Bottom = 35f - } - }, - // Scrolling teams - teamsContainer = new ScrollingTeamContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, + + Text = "Stop random", + Action = teamsContainer.StopScrolling, }, - // Scrolling team name - fullTeamNameText = new OsuSpriteText + new TriangleButton { - Anchor = Anchor.Centre, - Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, - Position = new Vector2(0, 45f), - - Alpha = 0, - - Font = "Exo2.0-Light", - TextSize = 42f + Text = "Reload", + Action = reloadTeams } } }, - // Control panel container - new Container + new FillFlowContainer { - RelativeSizeAxes = Axes.Both, - Width = 0.15f, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Width = 0.75f, + + Position = new Vector2(0, -5f), + + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5f), Children = new Drawable[] { - new Box + new TriangleButton { - RelativeSizeAxes = Axes.Both, - Colour = new Color4(54, 54, 54, 255) - }, - new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - - Text = "Control Panel", - TextSize = 22f, - Font = "Exo2.0-Bold" - }, - new FillFlowContainer - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Width = 0.75f, - Position = new Vector2(0, 35f), - - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5f), - - Children = new Drawable[] - { - new TriangleButton - { - RelativeSizeAxes = Axes.X, - - Text = "Begin random", - Action = teamsContainer.StartScrolling, - }, - new TriangleButton - { - RelativeSizeAxes = Axes.X, - - Text = "Stop random", - Action = teamsContainer.StopScrolling, - }, - new TriangleButton - { - RelativeSizeAxes = Axes.X, - - Text = "Reload", - Action = reloadTeams - } - } - }, - new FillFlowContainer - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Width = 0.75f, - - Position = new Vector2(0, -5f), - - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5f), - - Children = new Drawable[] - { - new TriangleButton - { - RelativeSizeAxes = Axes.X, - - Text = "Reset", - Action = () => reset() - } - } + Text = "Reset", + Action = () => reset() } } } From a918e83b1e4b1523c48b4d54cdb1a81eb88b6982 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 4 Nov 2018 04:58:59 +0900 Subject: [PATCH 0210/5608] Add drawings screen --- osu.Game.Tournament.Tests/TestCaseSceneManager.cs | 15 +++++++++++---- .../Screens/Ladder/Components/ProgressionPath.cs | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs index a1434b3a31..9454a5674c 100644 --- a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Video; using osu.Game.Graphics.UserInterface; +using osu.Game.Tournament.Screens.Drawings; using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.TeamIntro; using OpenTK; @@ -20,6 +21,7 @@ namespace osu.Game.Tournament.Tests private LadderManager bracket; private MapPoolScreen mapPool; private TeamIntroScreen teamIntro; + private DrawingsScreen drawings; private Container screens; [BackgroundDependencyLoader] @@ -44,6 +46,7 @@ namespace osu.Game.Tournament.Tests Direction = FillDirection.Vertical, Children = new Drawable[] { + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => setScreen(drawings) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => setScreen(teamIntro) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => setScreen(mapPool) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => setScreen(bracket) }, @@ -54,16 +57,19 @@ namespace osu.Game.Tournament.Tests new Container { RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + X = 0.2f, FillMode = FillMode.Fit, FillAspectRatio = 16/9f, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, Size = new Vector2(0.8f, 1), - Masking = true, + //Masking = true, Children = new Drawable[] { new VideoSprite(@"C:\Users\Dean\BG Side Logo - OWC.m4v") { + Loop = true, RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, }, @@ -75,7 +81,8 @@ namespace osu.Game.Tournament.Tests bracket = new LadderManager(Ladder), mapPool = new MapPoolScreen(Ladder.Groupings.First(g => g.Name == "Finals")), teamIntro = new TeamIntroScreen(Ladder.Teams.First(t => t.Acronym == "USA"), Ladder.Teams.First(t => t.Acronym == "JPN"), - Ladder.Groupings.First(g => g.Name == "Finals")) + Ladder.Groupings.First(g => g.Name == "Finals")), + drawings = new DrawingsScreen() } }, } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs index 4496430e79..880b2fefa4 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs @@ -56,7 +56,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components var p3 = new Vector2(p2.X, c2.Y); var p4 = new Vector2(c2.X, p3.Y); - Positions = new[] { p1, p2, p3, p4 }.Select(ToLocalSpace).ToList(); + Vertices = new[] { p1, p2, p3, p4 }.Select(ToLocalSpace).ToList(); } } } From 97b32a72f52ccb255e505710c8cde83d5b1ba69c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 4 Nov 2018 04:59:11 +0900 Subject: [PATCH 0211/5608] Read and write bracket from storage instead of arbitrary location --- osu.Game.Tournament.Tests/LadderTestCase.cs | 34 ++++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tournament.Tests/LadderTestCase.cs b/osu.Game.Tournament.Tests/LadderTestCase.cs index ee8cfb8f8a..ebc78e14be 100644 --- a/osu.Game.Tournament.Tests/LadderTestCase.cs +++ b/osu.Game.Tournament.Tests/LadderTestCase.cs @@ -5,6 +5,7 @@ using System.IO; using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; @@ -17,7 +18,10 @@ namespace osu.Game.Tournament.Tests { public abstract class LadderTestCase : OsuTestCase { + private const string bracket_filename = "bracket.json"; + protected LadderInfo Ladder; + private Storage storage; [Resolved] private APIAccess api { get; set; } = null; @@ -26,9 +30,19 @@ namespace osu.Game.Tournament.Tests private RulesetStore rulesets { get; set; } = null; [BackgroundDependencyLoader] - private void load() + private void load(Storage storage) { - Ladder = File.Exists(@"bracket.json") ? JsonConvert.DeserializeObject(File.ReadAllText(@"bracket.json")) : new LadderInfo(); + this.storage = storage; + + string content = null; + if (storage.Exists(bracket_filename)) + { + using (Stream stream = storage.GetStream(bracket_filename, FileAccess.Read, FileMode.Open)) + using (var sr = new StreamReader(stream)) + content = sr.ReadToEnd(); + } + + Ladder = content != null ? JsonConvert.DeserializeObject(content) : new LadderInfo(); bool addedInfo = false; @@ -62,12 +76,16 @@ namespace osu.Game.Tournament.Tests protected virtual void SaveChanges() { - File.WriteAllText(@"bracket.json", JsonConvert.SerializeObject(Ladder, - new JsonSerializerSettings - { - NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore - })); + using (var stream = storage.GetStream(bracket_filename, FileAccess.Write, FileMode.Create)) + using (var sw = new StreamWriter(stream)) + { + sw.Write(JsonConvert.SerializeObject(Ladder, + new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore + })); + } } } } From 2e348edd8dadbc6f88e45390bae49a0ffdcae66c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 4 Nov 2018 05:29:06 +0900 Subject: [PATCH 0212/5608] Fix filename --- .../Screens/TeamIntro/{TeamIntro.cs => TeamIntroScreen.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Tournament/Screens/TeamIntro/{TeamIntro.cs => TeamIntroScreen.cs} (100%) diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs similarity index 100% rename from osu.Game.Tournament/Screens/TeamIntro/TeamIntro.cs rename to osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs From 54a02ee2d7f7bd50455955d6d85d524f53742e02 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 4 Nov 2018 07:12:07 +0900 Subject: [PATCH 0213/5608] Add showcase screen --- .../TestCaseSceneManager.cs | 4 + osu.Game.Tournament.Tests/TestCaseShowcase.cs | 18 +++ .../Components/TournamentBeatmapPanel.cs | 4 +- .../Screens/Showcase/ShowcaseScreen.cs | 143 ++++++++++++++++++ 4 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tournament.Tests/TestCaseShowcase.cs create mode 100644 osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs diff --git a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs index 9454a5674c..aec9038356 100644 --- a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Video; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Screens.Drawings; using osu.Game.Tournament.Screens.Ladder; +using osu.Game.Tournament.Screens.Showcase; using osu.Game.Tournament.Screens.TeamIntro; using OpenTK; using OpenTK.Graphics; @@ -23,6 +24,7 @@ namespace osu.Game.Tournament.Tests private TeamIntroScreen teamIntro; private DrawingsScreen drawings; private Container screens; + private ShowcaseScreen showcase; [BackgroundDependencyLoader] private void load() @@ -47,6 +49,7 @@ namespace osu.Game.Tournament.Tests Children = new Drawable[] { new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => setScreen(drawings) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => setScreen(showcase) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => setScreen(teamIntro) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => setScreen(mapPool) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => setScreen(bracket) }, @@ -79,6 +82,7 @@ namespace osu.Game.Tournament.Tests Children = new Drawable[] { bracket = new LadderManager(Ladder), + showcase = new ShowcaseScreen(), mapPool = new MapPoolScreen(Ladder.Groupings.First(g => g.Name == "Finals")), teamIntro = new TeamIntroScreen(Ladder.Teams.First(t => t.Acronym == "USA"), Ladder.Teams.First(t => t.Acronym == "JPN"), Ladder.Groupings.First(g => g.Name == "Finals")), diff --git a/osu.Game.Tournament.Tests/TestCaseShowcase.cs b/osu.Game.Tournament.Tests/TestCaseShowcase.cs new file mode 100644 index 0000000000..66183683d1 --- /dev/null +++ b/osu.Game.Tournament.Tests/TestCaseShowcase.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Game.Tests.Visual; +using osu.Game.Tournament.Screens.Showcase; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseShowcase : OsuTestCase + { + [BackgroundDependencyLoader] + private void load() + { + Add(new ShowcaseScreen()); + } + } +} diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 5eb597a3c6..9542c26faf 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -20,11 +20,13 @@ namespace osu.Game.Tournament.Components private const float horizontal_padding = 10; private const float vertical_padding = 5; + public const float HEIGHT = 50; + public TournamentBeatmapPanel(BeatmapInfo beatmap) { this.beatmap = beatmap; Width = 400; - Height = 50; + Height = HEIGHT; } [BackgroundDependencyLoader] diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs new file mode 100644 index 0000000000..7585ad4078 --- /dev/null +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -0,0 +1,143 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; +using osu.Game.Screens; +using osu.Game.Screens.Menu; +using osu.Game.Tournament.Components; +using OpenTK; + +namespace osu.Game.Tournament.Screens.Showcase +{ + public class ShowcaseScreen : OsuScreen + { + private readonly Container panelContainer; + + [Resolved] + private APIAccess api { get; set; } = null; + + [Resolved] + private RulesetStore rulesets { get; set; } = null; + + [BackgroundDependencyLoader] + private void load() + { + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = 1091460 }); + req.Success += success; + api.Queue(req); + } + + private void success(APIBeatmap apiBeatmap) + { + var beatmap = apiBeatmap.ToBeatmap(rulesets); + panelContainer.Children = new Drawable[] + { + new OsuSpriteText + { + Text = $"Length {beatmap.OnlineInfo.Length}s", + Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, + Colour = OsuColour.Gray(0.33f), + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }, + new OsuSpriteText + { + Text = $"BPM {beatmap.BeatmapSet.OnlineInfo.BPM:0.#}", + Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, + Colour = OsuColour.Gray(0.33f), + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft + }, + new OsuSpriteText + { + Text = $"AR {beatmap.BaseDifficulty.ApproachRate:0.#}", + Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, + Colour = OsuColour.Gray(0.33f), + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight + }, + new OsuSpriteText + { + Text = $"Star Rating {beatmap.StarDifficulty:0.#}", + Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, + Colour = OsuColour.Gray(0.33f), + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight + }, + new TournamentBeatmapPanel(beatmap) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + } + }; + } + + public ShowcaseScreen() + { + RelativeSizeAxes = Axes.Both; + + Children = new Drawable[] + { + new Container + { + Masking = true, + RelativeSizeAxes = Axes.X, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Y = -10, + Width = 0.9f, + Height = TournamentBeatmapPanel.HEIGHT, + CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.93f), + }, + new Container + { + Masking = true, + CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Width = 0.7f, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.86f), + }, + panelContainer = new Container + { + RelativeSizeAxes = Axes.Both, + } + } + }, + new OsuLogo() + { + Triangles = false, + Colour = OsuColour.Gray(0.33f), + Scale = new Vector2(0.08f), + Margin = new MarginPadding(50), + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + } + } + } + }; + } + } +} From 89a1414c635d39261a6c65090086b63bb65bdbe3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 4 Nov 2018 21:14:16 +0900 Subject: [PATCH 0214/5608] Read flag name from file --- .../Screens/Drawings/Components/StorageBackedTeamList.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs index 625f05edac..fa7ce5edfa 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs @@ -51,7 +51,8 @@ namespace osu.Game.Tournament.Screens.Drawings.Components teams.Add(new TournamentTeam { FullName = split[1].Trim(), - Acronym = split.Length >= 3 ? split[2].Trim() : null + Acronym = split.Length >= 3 ? split[2].Trim() : null, + FlagName = split[0].Trim() }); } } From 7e092c608400fab60c139b1dab4d24c01ab07bf5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 4 Nov 2018 21:15:02 +0900 Subject: [PATCH 0215/5608] Read videos from storage --- .../TestCaseSceneManager.cs | 5 +++-- .../Screens/Drawings/DrawingsScreen.cs | 2 +- .../Screens/Showcase/ShowcaseScreen.cs | 2 +- .../Screens/TeamIntro/TeamIntroScreen.cs | 16 +++++++++++++++- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs index aec9038356..32a47e2c19 100644 --- a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Video; +using osu.Framework.Platform; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Screens.Drawings; using osu.Game.Tournament.Screens.Ladder; @@ -27,7 +28,7 @@ namespace osu.Game.Tournament.Tests private ShowcaseScreen showcase; [BackgroundDependencyLoader] - private void load() + private void load(Storage storage) { Children = new Drawable[] { @@ -70,7 +71,7 @@ namespace osu.Game.Tournament.Tests //Masking = true, Children = new Drawable[] { - new VideoSprite(@"C:\Users\Dean\BG Side Logo - OWC.m4v") + new VideoSprite(storage.GetStream(@"BG Side Logo - OWC.m4v")) { Loop = true, RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 38f0be0d5a..625d881bdb 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -88,7 +88,7 @@ namespace osu.Game.Tournament.Screens.Drawings RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new VideoSprite(@"C:\Users\Dean\BG Logoless - OWC.m4v") + new VideoSprite(storage.GetStream("BG Logoless - OWC.m4v")) { RelativeSizeAxes = Axes.Both, Loop = true, diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs index 7585ad4078..81ecd45746 100644 --- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -126,7 +126,7 @@ namespace osu.Game.Tournament.Screens.Showcase } } }, - new OsuLogo() + new OsuLogo { Triangles = false, Colour = OsuColour.Gray(0.33f), diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 766feaa806..2c50970624 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -2,9 +2,11 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Video; +using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Screens; @@ -17,13 +19,25 @@ namespace osu.Game.Tournament.Screens.TeamIntro { public class TeamIntroScreen : OsuScreen { + private readonly TournamentTeam team1; + private readonly TournamentTeam team2; + private readonly TournamentGrouping round; + public TeamIntroScreen(TournamentTeam team1, TournamentTeam team2, TournamentGrouping round) + { + this.team1 = team1; + this.team2 = team2; + this.round = round; + } + + [BackgroundDependencyLoader] + private void load(Storage storage) { RelativeSizeAxes = Axes.Both; InternalChildren = new Drawable[] { - new VideoSprite(@"C:\Users\Dean\BG Team - Both OWC.m4v") + new VideoSprite(storage.GetStream(@"BG Team - Both OWC.m4v")) { RelativeSizeAxes = Axes.Both, Loop = true, From c7e5ae0573820149efc327a94f63d79e7fcc03e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 4 Nov 2018 21:25:45 +0900 Subject: [PATCH 0216/5608] Read from stable --- .../Screens/Showcase/ShowcaseScreen.cs | 124 ++++++++++++++++-- 1 file changed, 112 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs index 81ecd45746..95d11e2143 100644 --- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -1,11 +1,15 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.IO; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Platform.Windows; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Legacy; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.API; @@ -21,7 +25,8 @@ namespace osu.Game.Tournament.Screens.Showcase { public class ShowcaseScreen : OsuScreen { - private readonly Container panelContainer; + private Container panel; + private readonly Container panelContents; [Resolved] private APIAccess api { get; set; } = null; @@ -29,22 +34,78 @@ namespace osu.Game.Tournament.Screens.Showcase [Resolved] private RulesetStore rulesets { get; set; } = null; + private int lastBeatmapId; + private int lastMods; + [BackgroundDependencyLoader] private void load() { - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = 1091460 }); - req.Success += success; - api.Queue(req); + var stable = new StableStorage(); + + const string file_ipc_filename = "ipc.txt"; + + if (stable.Exists(file_ipc_filename)) + { + Scheduler.AddDelayed(delegate + { + try + { + using (var stream = stable.GetStream(file_ipc_filename)) + using (var sr = new StreamReader(stream)) + { + var beatmapId = int.Parse(sr.ReadLine()); + var mods = int.Parse(sr.ReadLine()); + + if (lastBeatmapId == beatmapId) + return; + + lastMods = mods; + lastBeatmapId = beatmapId; + + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); + req.Success += success; + api.Queue(req); + } + } + catch + { + // file might be in use. + } + }, 250, true); + } } private void success(APIBeatmap apiBeatmap) { + panel.FadeInFromZero(300, Easing.OutQuint); + var beatmap = apiBeatmap.ToBeatmap(rulesets); - panelContainer.Children = new Drawable[] + + var legacyMods = (LegacyMods)lastMods; + var bpm = beatmap.BeatmapSet.OnlineInfo.BPM; + var length = beatmap.OnlineInfo.Length; + string extra = ""; + + var ar = beatmap.BaseDifficulty.ApproachRate; + if ((legacyMods & LegacyMods.HardRock) > 0) + { + //ar *= 1.4f; + extra = "*"; + } + + if ((legacyMods & LegacyMods.DoubleTime) > 0) + { + //ar *= 1.5f; + bpm *= 1.5f; + length /= 1.5f; + extra = "*"; + } + + panelContents.Children = new Drawable[] { new OsuSpriteText { - Text = $"Length {beatmap.OnlineInfo.Length}s", + Text = $"Length {length}s", Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, Colour = OsuColour.Gray(0.33f), Anchor = Anchor.TopLeft, @@ -52,7 +113,7 @@ namespace osu.Game.Tournament.Screens.Showcase }, new OsuSpriteText { - Text = $"BPM {beatmap.BeatmapSet.OnlineInfo.BPM:0.#}", + Text = $"BPM {bpm:0.#}", Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, Colour = OsuColour.Gray(0.33f), Anchor = Anchor.BottomLeft, @@ -60,7 +121,7 @@ namespace osu.Game.Tournament.Screens.Showcase }, new OsuSpriteText { - Text = $"AR {beatmap.BaseDifficulty.ApproachRate:0.#}", + Text = $"AR {ar:0.#}{extra}", Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, Colour = OsuColour.Gray(0.33f), Anchor = Anchor.TopRight, @@ -68,7 +129,7 @@ namespace osu.Game.Tournament.Screens.Showcase }, new OsuSpriteText { - Text = $"Star Rating {beatmap.StarDifficulty:0.#}", + Text = $"Star Rating {beatmap.StarDifficulty:0.#}{extra}", Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, Colour = OsuColour.Gray(0.33f), Anchor = Anchor.BottomRight, @@ -95,7 +156,7 @@ namespace osu.Game.Tournament.Screens.Showcase Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, Y = -10, - Width = 0.9f, + Width = 0.95f, Height = TournamentBeatmapPanel.HEIGHT, CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, Children = new Drawable[] @@ -105,7 +166,7 @@ namespace osu.Game.Tournament.Screens.Showcase RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.93f), }, - new Container + panel = new Container { Masking = true, CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, @@ -120,7 +181,7 @@ namespace osu.Game.Tournament.Screens.Showcase RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.86f), }, - panelContainer = new Container + panelContents = new Container { RelativeSizeAxes = Axes.Both, } @@ -139,5 +200,44 @@ namespace osu.Game.Tournament.Screens.Showcase } }; } + + /// + /// A method of accessing an osu-stable install in a controlled fashion. + /// + private class StableStorage : WindowsStorage + { + protected override string LocateBasePath() + { + bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")); + + string stableInstallPath; + + try + { + stableInstallPath = "E:\\osu!mappool"; + + if (checkExists(stableInstallPath)) + return stableInstallPath; + } + catch + { + } + + stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); + if (checkExists(stableInstallPath)) + return stableInstallPath; + + stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu"); + if (checkExists(stableInstallPath)) + return stableInstallPath; + + return null; + } + + public StableStorage() + : base(string.Empty, null) + { + } + } } } From fb93aea909383075518ddf2393dc17454443356a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 5 Nov 2018 23:15:30 +0900 Subject: [PATCH 0217/5608] Use logo-less video by default --- osu.Game.Tournament.Tests/TestCaseSceneManager.cs | 3 ++- osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs | 6 ------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs index 32a47e2c19..13c00f081a 100644 --- a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs @@ -71,9 +71,10 @@ namespace osu.Game.Tournament.Tests //Masking = true, Children = new Drawable[] { - new VideoSprite(storage.GetStream(@"BG Side Logo - OWC.m4v")) + new VideoSprite(storage.GetStream("BG Logoless - OWC.m4v")) { Loop = true, + ShowLastFrameDuringHideCutoff = true, RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, }, diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 625d881bdb..9e8074d7dc 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Graphics.Video; using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Framework.Platform; @@ -88,11 +87,6 @@ namespace osu.Game.Tournament.Screens.Drawings RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new VideoSprite(storage.GetStream("BG Logoless - OWC.m4v")) - { - RelativeSizeAxes = Axes.Both, - Loop = true, - }, new Sprite { RelativeSizeAxes = Axes.Both, From 9c5eddea549cfcac278714a1b24296bcfae46646 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Nov 2018 14:49:09 +0900 Subject: [PATCH 0218/5608] Allow running tournament tools from main executable --- osu.Desktop/Program.cs | 4 + osu.Desktop/osu.Desktop.csproj | 1 + osu.Game.Tournament.Tests/TestCaseMapPool.cs | 33 +---- .../TestCaseSceneManager.cs | 97 +-------------- .../Screens/MapPool/MapPoolScreen.cs | 35 ++++++ .../Screens/TournamentSceneManager.cs | 113 ++++++++++++++++++ osu.Game.Tournament/TournamentGame.cs | 99 +++++++++++++++ osu.Game/OsuGameBase.cs | 12 +- 8 files changed, 262 insertions(+), 132 deletions(-) create mode 100644 osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs create mode 100644 osu.Game.Tournament/Screens/TournamentSceneManager.cs create mode 100644 osu.Game.Tournament/TournamentGame.cs diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 257155478f..b864cf3c64 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -11,6 +11,7 @@ using osu.Framework.Development; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.IPC; +using osu.Game.Tournament; namespace osu.Desktop { @@ -45,6 +46,9 @@ namespace osu.Desktop default: host.Run(new OsuGameDesktop(args)); break; + case "--tournament": + host.Run(new TournamentGame()); + break; } } diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index e1e59804e5..a3e7625c44 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -17,6 +17,7 @@ osu.Desktop.Program + diff --git a/osu.Game.Tournament.Tests/TestCaseMapPool.cs b/osu.Game.Tournament.Tests/TestCaseMapPool.cs index e4637b8fc3..1101d2828a 100644 --- a/osu.Game.Tournament.Tests/TestCaseMapPool.cs +++ b/osu.Game.Tournament.Tests/TestCaseMapPool.cs @@ -3,12 +3,7 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Screens; -using osu.Game.Tournament.Components; -using osu.Game.Tournament.Screens.Ladder.Components; -using OpenTK; +using osu.Game.Tournament.Screens.MapPool; namespace osu.Game.Tournament.Tests { @@ -23,30 +18,4 @@ namespace osu.Game.Tournament.Tests Add(new MapPoolScreen(round)); } } - - public class MapPoolScreen : OsuScreen - { - public MapPoolScreen(TournamentGrouping round) - { - FillFlowContainer maps; - - InternalChildren = new Drawable[] - { - maps = new FillFlowContainer - { - Spacing = new Vector2(20), - Padding = new MarginPadding(50), - Direction = FillDirection.Full, - RelativeSizeAxes = Axes.Both, - } - }; - - foreach (var b in round.Beatmaps) - maps.Add(new TournamentBeatmapPanel(b.BeatmapInfo) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - }); - } - } } diff --git a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs index 62e5f77802..9853e31ee3 100644 --- a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs @@ -1,111 +1,18 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Video; using osu.Framework.Platform; -using osu.Game.Graphics.UserInterface; -using osu.Game.Tournament.Screens.Drawings; -using osu.Game.Tournament.Screens.Ladder; -using osu.Game.Tournament.Screens.Showcase; -using osu.Game.Tournament.Screens.TeamIntro; -using OpenTK; -using OpenTK.Graphics; +using osu.Game.Tournament.Screens; namespace osu.Game.Tournament.Tests { public class TestCaseSceneManager : LadderTestCase { - private LadderManager bracket; - private MapPoolScreen mapPool; - private TeamIntroScreen teamIntro; - private DrawingsScreen drawings; - private Container screens; - private ShowcaseScreen showcase; - [BackgroundDependencyLoader] private void load(Storage storage) { - Children = new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Width = 0.2f, - Children = new Drawable[] - { - new Box - { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => setScreen(drawings) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => setScreen(showcase) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => setScreen(teamIntro) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => setScreen(mapPool) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => setScreen(bracket) }, - } - }, - }, - }, - new Container - { - RelativeSizeAxes = Axes.Both, - RelativePositionAxes = Axes.Both, - X = 0.2f, - FillMode = FillMode.Fit, - FillAspectRatio = 16/9f, - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - Size = new Vector2(0.8f, 1), - //Masking = true, - Children = new Drawable[] - { - new VideoSprite(storage.GetStream("BG Logoless - OWC.m4v")) - { - Loop = true, - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, - }, - screens = new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - bracket = new LadderManager(Ladder), - showcase = new ShowcaseScreen(), - mapPool = new MapPoolScreen(Ladder.Groupings.First(g => g.Name == "Finals")), - teamIntro = new TeamIntroScreen(Ladder.Teams.First(t => t.Acronym == "USA"), Ladder.Teams.First(t => t.Acronym == "JPN"), - Ladder.Groupings.First(g => g.Name == "Finals")), - drawings = new DrawingsScreen() - } - }, - } - }, - }; - - setScreen(teamIntro); - } - - private void setScreen(Drawable screen) - { - foreach (var s in screens.Children) - { - if (s == screen) - s.FadeIn(100); - else - s.FadeOut(100); - } + Add(new TournamentSceneManager()); } } } diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs new file mode 100644 index 0000000000..be7b3a0b3b --- /dev/null +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -0,0 +1,35 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Screens; +using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK; + +namespace osu.Game.Tournament.Screens.MapPool +{ + public class MapPoolScreen : OsuScreen + { + public MapPoolScreen(TournamentGrouping round) + { + FillFlowContainer maps; + + InternalChildren = new Drawable[] + { + maps = new FillFlowContainer + { + Spacing = new Vector2(20), + Padding = new MarginPadding(50), + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.Both, + } + }; + + foreach (var b in round.Beatmaps) + maps.Add(new TournamentBeatmapPanel(b.BeatmapInfo) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }); + } + } +} diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs new file mode 100644 index 0000000000..82f17a85c4 --- /dev/null +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -0,0 +1,113 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Video; +using osu.Framework.Platform; +using osu.Game.Graphics.UserInterface; +using osu.Game.Screens; +using osu.Game.Tournament.Screens.Drawings; +using osu.Game.Tournament.Screens.Ladder; +using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Screens.MapPool; +using osu.Game.Tournament.Screens.Showcase; +using osu.Game.Tournament.Screens.TeamIntro; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Tournament.Screens +{ + public class TournamentSceneManager : OsuScreen + { + private LadderManager bracket; + private MapPoolScreen mapPool; + private TeamIntroScreen teamIntro; + private DrawingsScreen drawings; + private Container screens; + private ShowcaseScreen showcase; + + [BackgroundDependencyLoader] + private void load(LadderInfo ladder, Storage storage) + { + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Y, + Width = 200, + Children = new Drawable[] + { + new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => setScreen(drawings) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => setScreen(showcase) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => setScreen(teamIntro) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => setScreen(mapPool) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => setScreen(bracket) }, + } + }, + }, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + X = 200, + FillMode = FillMode.Fit, + FillAspectRatio = 16/9f, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + Size = new Vector2(0.8f, 1), + //Masking = true, + Children = new Drawable[] + { + new VideoSprite(storage.GetStream("BG Logoless - OWC.m4v")) + { + Loop = true, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + }, + screens = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + bracket = new LadderManager(ladder), + showcase = new ShowcaseScreen(), + mapPool = new MapPoolScreen(ladder.Groupings.First(g => g.Name == "Finals")), + teamIntro = new TeamIntroScreen(ladder.Teams.First(t => t.Acronym == "USA"), ladder.Teams.First(t => t.Acronym == "JPN"), + ladder.Groupings.First(g => g.Name == "Finals")), + drawings = new DrawingsScreen() + } + }, + } + }, + }; + + setScreen(teamIntro); + } + + private void setScreen(Drawable screen) + { + foreach (var s in screens.Children) + { + if (s == screen) + s.FadeIn(100); + else + s.FadeOut(100); + } + } + } +} diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs new file mode 100644 index 0000000000..1bbbfdc37a --- /dev/null +++ b/osu.Game.Tournament/TournamentGame.cs @@ -0,0 +1,99 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.IO; +using Newtonsoft.Json; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Platform; +using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API.Requests; +using osu.Game.Rulesets; +using osu.Game.Tournament.Screens; +using osu.Game.Tournament.Screens.Ladder.Components; + +namespace osu.Game.Tournament +{ + public class TournamentGame : OsuGameBase + { + private const string bracket_filename = "bracket.json"; + + protected LadderInfo Ladder; + private Storage storage; + + private DependencyContainer dependencies; + + [Cached] + private readonly Bindable ruleset = new Bindable(); + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + + [BackgroundDependencyLoader] + private void load(Storage storage) + { + this.storage = storage; + + string content = null; + if (storage.Exists(bracket_filename)) + { + using (Stream stream = storage.GetStream(bracket_filename, FileAccess.Read, FileMode.Open)) + using (var sr = new StreamReader(stream)) + content = sr.ReadToEnd(); + } + + Ladder = content != null ? JsonConvert.DeserializeObject(content) : new LadderInfo(); + dependencies.Cache(Ladder); + + bool addedInfo = false; + + foreach (var g in Ladder.Groupings) + foreach (var b in g.Beatmaps) + { + if (b.BeatmapInfo == null) + { + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); + req.Success += i => b.BeatmapInfo = i.ToBeatmap(RulesetStore); + req.Perform(API); + + addedInfo = true; + } + } + + if (addedInfo) + SaveChanges(); + + Add(new OsuButton + { + Text = "Save Changes", + Width = 140, + Height = 50, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Padding = new MarginPadding(10), + Action = SaveChanges, + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Add(new TournamentSceneManager()); + } + + protected virtual void SaveChanges() + { + using (var stream = storage.GetStream(bracket_filename, FileAccess.Write, FileMode.Create)) + using (var sw = new StreamWriter(stream)) + { + sw.Write(JsonConvert.SerializeObject(Ladder, + new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore + })); + } + } + } +} diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 73c970ce5d..ea1dbfa369 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -62,6 +62,8 @@ namespace osu.Game protected MenuCursorContainer MenuCursorContainer; + protected APIAccess API; + private Container content; protected override Container Content => content; @@ -146,14 +148,14 @@ namespace osu.Game dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio)); dependencies.CacheAs(SkinManager); - var api = new APIAccess(LocalConfig); + API = new APIAccess(LocalConfig); - dependencies.Cache(api); - dependencies.CacheAs(api); + dependencies.Cache(API); + dependencies.CacheAs(API); dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); - dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, api, Audio, Host)); + dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, API, Audio, Host)); dependencies.Cache(ScoreStore = new ScoreStore(contextFactory, Host, BeatmapManager, RulesetStore)); dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); @@ -177,7 +179,7 @@ namespace osu.Game FileStore.Cleanup(); - AddInternal(api); + AddInternal(API); GlobalActionContainer globalBinding; From 6f2554873714d10c8c09057cdccff0a7690f0e87 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Nov 2018 14:49:20 +0900 Subject: [PATCH 0219/5608] Remove now unnecessary null setters --- osu.Game.Tournament.Tests/LadderTestCase.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs | 4 ++-- .../Screens/Ladder/Components/DrawableMatchPairing.cs | 2 +- .../Screens/Ladder/Components/DrawableMatchTeam.cs | 2 +- .../Screens/Ladder/Components/LadderEditorSettings.cs | 2 +- osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs | 6 +++--- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tournament.Tests/LadderTestCase.cs b/osu.Game.Tournament.Tests/LadderTestCase.cs index ebc78e14be..7c8d8856e6 100644 --- a/osu.Game.Tournament.Tests/LadderTestCase.cs +++ b/osu.Game.Tournament.Tests/LadderTestCase.cs @@ -24,10 +24,10 @@ namespace osu.Game.Tournament.Tests private Storage storage; [Resolved] - private APIAccess api { get; set; } = null; + private APIAccess api { get; set; } [Resolved] - private RulesetStore rulesets { get; set; } = null; + private RulesetStore rulesets { get; set; } [BackgroundDependencyLoader] private void load(Storage storage) diff --git a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs index 93068f6224..de80d36067 100644 --- a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs +++ b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs @@ -18,10 +18,10 @@ namespace osu.Game.Tournament.Tests public class TestCaseBeatmapPanel : OsuTestCase { [Resolved] - private APIAccess api { get; set; } = null; + private APIAccess api { get; set; } [Resolved] - private RulesetStore rulesets { get; set; } = null; + private RulesetStore rulesets { get; set; } public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 1f58bc86ea..81b3223ea7 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private Bindable globalSelection; [Resolved(CanBeNull = true)] - private LadderEditorInfo editorInfo { get; set; } = null; + private LadderEditorInfo editorInfo { get; set; } public DrawableMatchPairing(MatchPairing pairing) { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index dca8d0f0a8..70ddb6b664 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -37,7 +37,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private LadderManager manager; [Resolved(CanBeNull = true)] - private LadderEditorInfo editorInfo { get; set; } = null; + private LadderEditorInfo editorInfo { get; set; } public DrawableMatchTeam(Bindable team, MatchPairing pairing, bool losers) : base(team) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index 95067e8803..d7b827237a 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -26,7 +26,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private PlayerCheckbox losersCheckbox; [Resolved] - private LadderEditorInfo editorInfo { get; set; } = null; + private LadderEditorInfo editorInfo { get; set; } [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs index 95d11e2143..dcbaad8ab5 100644 --- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -25,14 +25,14 @@ namespace osu.Game.Tournament.Screens.Showcase { public class ShowcaseScreen : OsuScreen { - private Container panel; + private readonly Container panel; private readonly Container panelContents; [Resolved] - private APIAccess api { get; set; } = null; + private APIAccess api { get; set; } [Resolved] - private RulesetStore rulesets { get; set; } = null; + private RulesetStore rulesets { get; set; } private int lastBeatmapId; private int lastMods; From 85fe4db2ec86674fa60afe936fd2fe21daa551f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Nov 2018 15:08:14 +0900 Subject: [PATCH 0220/5608] Hide game cursor so it is not included in stream --- osu.Game.Tournament/TournamentGame.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index 1bbbfdc37a..d4e6ee2a44 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -80,6 +80,8 @@ namespace osu.Game.Tournament { base.LoadComplete(); Add(new TournamentSceneManager()); + + MenuCursorContainer.Cursor.Alpha = 0; } protected virtual void SaveChanges() From a2b28e0bf4326b94b46e77945626940268526056 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Nov 2018 16:15:03 +0900 Subject: [PATCH 0221/5608] Add missing header --- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index be7b3a0b3b..6d7dca0aad 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Screens; From 49d3beac1930db116fb5c7a8a45cfb9752ebda70 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Nov 2018 16:31:43 +0900 Subject: [PATCH 0222/5608] Add rider config for tournament run --- .../runConfigurations/osu___Tournament_.xml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .idea/.idea.osu/.idea/runConfigurations/osu___Tournament_.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/osu___Tournament_.xml b/.idea/.idea.osu/.idea/runConfigurations/osu___Tournament_.xml new file mode 100644 index 0000000000..a5f93489e8 --- /dev/null +++ b/.idea/.idea.osu/.idea/runConfigurations/osu___Tournament_.xml @@ -0,0 +1,20 @@ + + + + \ No newline at end of file From 5a4292717fbe707f93e3e1ad3e74c030dcfbd545 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Nov 2018 17:59:01 +0900 Subject: [PATCH 0223/5608] Allow tests to run custom game --- osu.Game.Tournament.Tests/LadderTestCase.cs | 79 +------------------ .../TestCaseGroupingManager.cs | 4 +- .../TestCaseLadderManager.cs | 4 +- .../TestCaseSceneManager.cs | 3 +- .../TournamentTestBrowser.cs | 27 +++++++ .../TournamentTestRunner.cs | 22 ++++++ .../osu.Game.Tournament.Tests.csproj | 3 + 7 files changed, 60 insertions(+), 82 deletions(-) create mode 100644 osu.Game.Tournament.Tests/TournamentTestBrowser.cs create mode 100644 osu.Game.Tournament.Tests/TournamentTestRunner.cs diff --git a/osu.Game.Tournament.Tests/LadderTestCase.cs b/osu.Game.Tournament.Tests/LadderTestCase.cs index 7c8d8856e6..fcc4d7dc1b 100644 --- a/osu.Game.Tournament.Tests/LadderTestCase.cs +++ b/osu.Game.Tournament.Tests/LadderTestCase.cs @@ -1,91 +1,16 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.IO; -using Newtonsoft.Json; using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Platform; -using osu.Game.Beatmaps; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; -using osu.Game.Rulesets; using osu.Game.Tests.Visual; using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Tests { - public abstract class LadderTestCase : OsuTestCase + public class LadderTestCase : OsuTestCase { - private const string bracket_filename = "bracket.json"; - - protected LadderInfo Ladder; - private Storage storage; [Resolved] - private APIAccess api { get; set; } - - [Resolved] - private RulesetStore rulesets { get; set; } - - [BackgroundDependencyLoader] - private void load(Storage storage) - { - this.storage = storage; - - string content = null; - if (storage.Exists(bracket_filename)) - { - using (Stream stream = storage.GetStream(bracket_filename, FileAccess.Read, FileMode.Open)) - using (var sr = new StreamReader(stream)) - content = sr.ReadToEnd(); - } - - Ladder = content != null ? JsonConvert.DeserializeObject(content) : new LadderInfo(); - - bool addedInfo = false; - - foreach (var g in Ladder.Groupings) - foreach (var b in g.Beatmaps) - { - if (b.BeatmapInfo == null) - { - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); - req.Success += i => b.BeatmapInfo = i.ToBeatmap(rulesets); - req.Perform(api); - - addedInfo = true; - } - } - - if (addedInfo) - SaveChanges(); - - Add(new OsuButton - { - Text = "Save Changes", - Width = 140, - Height = 50, - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Padding = new MarginPadding(10), - Action = SaveChanges, - }); - } - - protected virtual void SaveChanges() - { - using (var stream = storage.GetStream(bracket_filename, FileAccess.Write, FileMode.Create)) - using (var sw = new StreamWriter(stream)) - { - sw.Write(JsonConvert.SerializeObject(Ladder, - new JsonSerializerSettings - { - NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore - })); - } - } + protected LadderInfo Ladder { get; set; } } } diff --git a/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs b/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs index 2b79ba0225..531019c28c 100644 --- a/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs @@ -47,10 +47,10 @@ namespace osu.Game.Tournament.Tests items.Add(new GroupingRow(g)); } - protected override void SaveChanges() + protected override void Dispose(bool isDisposing) { Ladder.Groupings = items.Children.Select(c => c.Grouping).ToList(); - base.SaveChanges(); + base.Dispose(isDisposing); } private void addNew() => items.Add(new GroupingRow(new TournamentGrouping())); diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index a7af038ca8..7a7f7e0771 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -22,10 +22,10 @@ namespace osu.Game.Tournament.Tests }); } - protected override void SaveChanges() + protected override void Dispose(bool isDisposing) { + base.Dispose(isDisposing); Ladder = manager.CreateInfo(); - base.SaveChanges(); } } } diff --git a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs index 9853e31ee3..a19c933d8b 100644 --- a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs @@ -3,11 +3,12 @@ using osu.Framework.Allocation; using osu.Framework.Platform; +using osu.Game.Tests.Visual; using osu.Game.Tournament.Screens; namespace osu.Game.Tournament.Tests { - public class TestCaseSceneManager : LadderTestCase + public class TestCaseSceneManager : OsuTestCase { [BackgroundDependencyLoader] private void load(Storage storage) diff --git a/osu.Game.Tournament.Tests/TournamentTestBrowser.cs b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs new file mode 100644 index 0000000000..8549be0879 --- /dev/null +++ b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs @@ -0,0 +1,27 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Testing; +using osu.Game.Graphics; +using osu.Game.Screens.Backgrounds; + +namespace osu.Game.Tournament.Tests +{ + public class TournamentTestBrowser : TournamentGame + { + protected override void LoadComplete() + { + base.LoadComplete(); + + LoadComponentAsync(new BackgroundScreenDefault + { + Colour = OsuColour.Gray(0.5f), + Depth = 10 + }, AddInternal); + + // Have to construct this here, rather than in the constructor, because + // we depend on some dependencies to be loaded within OsuGameBase.load(). + Add(new TestBrowser()); + } + } +} diff --git a/osu.Game.Tournament.Tests/TournamentTestRunner.cs b/osu.Game.Tournament.Tests/TournamentTestRunner.cs new file mode 100644 index 0000000000..51c2c65cb4 --- /dev/null +++ b/osu.Game.Tournament.Tests/TournamentTestRunner.cs @@ -0,0 +1,22 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework; +using osu.Framework.Platform; + +namespace osu.Game.Tournament.Tests +{ + public static class TournamentTestRunner + { + [STAThread] + public static int Main(string[] args) + { + using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true)) + { + host.Run(new TournamentTestBrowser()); + return 0; + } + } + } +} diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index b3090d5b78..4a65846d68 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -1,5 +1,8 @@  + + osu.Game.Tournament.Tests.TournamentTestRunner + From afb3b38098d275d40117cc69140fda47e485add0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Nov 2018 18:32:59 +0900 Subject: [PATCH 0224/5608] Fix regression in testing logic --- osu.Game.Tournament.Tests/LadderTestCase.cs | 3 +- .../TestCaseLadderManager.cs | 8 +- .../TournamentTestBrowser.cs | 2 +- .../Screens/Showcase/ShowcaseScreen.cs | 229 +++++++++++------- osu.Game.Tournament/TournamentGame.cs | 85 +------ osu.Game.Tournament/TournamentGameBase.cs | 98 ++++++++ 6 files changed, 247 insertions(+), 178 deletions(-) create mode 100644 osu.Game.Tournament/TournamentGameBase.cs diff --git a/osu.Game.Tournament.Tests/LadderTestCase.cs b/osu.Game.Tournament.Tests/LadderTestCase.cs index fcc4d7dc1b..b296956d42 100644 --- a/osu.Game.Tournament.Tests/LadderTestCase.cs +++ b/osu.Game.Tournament.Tests/LadderTestCase.cs @@ -9,8 +9,7 @@ namespace osu.Game.Tournament.Tests { public class LadderTestCase : OsuTestCase { - [Resolved] - protected LadderInfo Ladder { get; set; } + protected LadderInfo Ladder { get; private set; } } } diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index 7a7f7e0771..5fa378a854 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -25,7 +25,13 @@ namespace osu.Game.Tournament.Tests protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - Ladder = manager.CreateInfo(); + + var newInfo = manager.CreateInfo(); + + Ladder.Teams = newInfo.Teams; + Ladder.Groupings = newInfo.Groupings; + Ladder.Pairings = newInfo.Pairings; + Ladder.Progressions = newInfo.Progressions; } } } diff --git a/osu.Game.Tournament.Tests/TournamentTestBrowser.cs b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs index 8549be0879..429adb2c0d 100644 --- a/osu.Game.Tournament.Tests/TournamentTestBrowser.cs +++ b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs @@ -7,7 +7,7 @@ using osu.Game.Screens.Backgrounds; namespace osu.Game.Tournament.Tests { - public class TournamentTestBrowser : TournamentGame + public class TournamentTestBrowser : TournamentGameBase { protected override void LoadComplete() { diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs index dcbaad8ab5..6c0eac1c23 100644 --- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -23,77 +23,116 @@ using OpenTK; namespace osu.Game.Tournament.Screens.Showcase { - public class ShowcaseScreen : OsuScreen + public class SongBar : CompositeDrawable { - private readonly Container panel; - private readonly Container panelContents; + private BeatmapInfo beatmap; - [Resolved] - private APIAccess api { get; set; } + public BeatmapInfo Beatmap + { + get { return beatmap; } + set + { + if (beatmap == value) + return; - [Resolved] - private RulesetStore rulesets { get; set; } + beatmap = value; + update(); + } + } - private int lastBeatmapId; - private int lastMods; + private LegacyMods mods; + + public LegacyMods Mods + { + get { return mods; } + set + { + mods = value; + update(); + } + } + + private Container panelContents; [BackgroundDependencyLoader] private void load() { - var stable = new StableStorage(); + RelativeSizeAxes = Axes.Both; - const string file_ipc_filename = "ipc.txt"; - - if (stable.Exists(file_ipc_filename)) + InternalChildren = new Drawable[] { - Scheduler.AddDelayed(delegate + new Container { - try + Masking = true, + RelativeSizeAxes = Axes.X, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Y = -10, + Width = 0.95f, + Height = TournamentBeatmapPanel.HEIGHT, + CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, + Children = new Drawable[] { - using (var stream = stable.GetStream(file_ipc_filename)) - using (var sr = new StreamReader(stream)) + new Box { - var beatmapId = int.Parse(sr.ReadLine()); - var mods = int.Parse(sr.ReadLine()); - - if (lastBeatmapId == beatmapId) - return; - - lastMods = mods; - lastBeatmapId = beatmapId; - - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); - req.Success += success; - api.Queue(req); + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.93f), + }, + new Container + { + Masking = true, + CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Width = 0.7f, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.86f), + }, + panelContents = new Container + { + RelativeSizeAxes = Axes.Both, + } + } + }, + new OsuLogo + { + Triangles = false, + Colour = OsuColour.Gray(0.33f), + Scale = new Vector2(0.08f), + Margin = new MarginPadding(50), + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, } } - catch - { - // file might be in use. - } - }, 250, true); - } + } + }; } - private void success(APIBeatmap apiBeatmap) + private void update() { - panel.FadeInFromZero(300, Easing.OutQuint); + if (beatmap == null) + { + panelContents.Clear(); + return; + } - var beatmap = apiBeatmap.ToBeatmap(rulesets); - - var legacyMods = (LegacyMods)lastMods; var bpm = beatmap.BeatmapSet.OnlineInfo.BPM; var length = beatmap.OnlineInfo.Length; string extra = ""; var ar = beatmap.BaseDifficulty.ApproachRate; - if ((legacyMods & LegacyMods.HardRock) > 0) + if ((mods & LegacyMods.HardRock) > 0) { //ar *= 1.4f; extra = "*"; } - if ((legacyMods & LegacyMods.DoubleTime) > 0) + if ((mods & LegacyMods.DoubleTime) > 0) { //ar *= 1.5f; bpm *= 1.5f; @@ -142,63 +181,73 @@ namespace osu.Game.Tournament.Screens.Showcase } }; } + } + + public class ShowcaseScreen : OsuScreen + { + [Resolved] + private APIAccess api { get; set; } + + [Resolved] + private RulesetStore rulesets { get; set; } + + private int lastBeatmapId; + private int lastMods; + + private readonly SongBar songBar; public ShowcaseScreen() { - RelativeSizeAxes = Axes.Both; - - Children = new Drawable[] + Add(songBar = new SongBar { - new Container + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre + }); + } + + [BackgroundDependencyLoader] + private void load() + { + var stable = new StableStorage(); + + const string file_ipc_filename = "ipc.txt"; + + if (stable.Exists(file_ipc_filename)) + { + Scheduler.AddDelayed(delegate { - Masking = true, - RelativeSizeAxes = Axes.X, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Y = -10, - Width = 0.95f, - Height = TournamentBeatmapPanel.HEIGHT, - CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, - Children = new Drawable[] + try { - new Box + using (var stream = stable.GetStream(file_ipc_filename)) + using (var sr = new StreamReader(stream)) { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.Gray(0.93f), - }, - panel = new Container - { - Masking = true, - CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Width = 0.7f, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.Gray(0.86f), - }, - panelContents = new Container - { - RelativeSizeAxes = Axes.Both, - } - } - }, - new OsuLogo - { - Triangles = false, - Colour = OsuColour.Gray(0.33f), - Scale = new Vector2(0.08f), - Margin = new MarginPadding(50), - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, + var beatmapId = int.Parse(sr.ReadLine()); + var mods = int.Parse(sr.ReadLine()); + + if (lastBeatmapId == beatmapId) + return; + + lastMods = mods; + lastBeatmapId = beatmapId; + + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); + req.Success += success; + api.Queue(req); } } - } - }; + catch + { + // file might be in use. + } + }, 250, true); + } + } + + private void success(APIBeatmap apiBeatmap) + { + songBar.FadeInFromZero(300, Easing.OutQuint); + songBar.Mods = (LegacyMods)lastMods; + songBar.Beatmap = apiBeatmap.ToBeatmap(rulesets); } /// diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index d4e6ee2a44..b4bdf250b6 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -1,81 +1,12 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.IO; -using Newtonsoft.Json; -using osu.Framework.Allocation; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Platform; -using osu.Game.Beatmaps; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API.Requests; -using osu.Game.Rulesets; using osu.Game.Tournament.Screens; -using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament { - public class TournamentGame : OsuGameBase + public class TournamentGame : TournamentGameBase { - private const string bracket_filename = "bracket.json"; - - protected LadderInfo Ladder; - private Storage storage; - - private DependencyContainer dependencies; - - [Cached] - private readonly Bindable ruleset = new Bindable(); - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - - [BackgroundDependencyLoader] - private void load(Storage storage) - { - this.storage = storage; - - string content = null; - if (storage.Exists(bracket_filename)) - { - using (Stream stream = storage.GetStream(bracket_filename, FileAccess.Read, FileMode.Open)) - using (var sr = new StreamReader(stream)) - content = sr.ReadToEnd(); - } - - Ladder = content != null ? JsonConvert.DeserializeObject(content) : new LadderInfo(); - dependencies.Cache(Ladder); - - bool addedInfo = false; - - foreach (var g in Ladder.Groupings) - foreach (var b in g.Beatmaps) - { - if (b.BeatmapInfo == null) - { - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); - req.Success += i => b.BeatmapInfo = i.ToBeatmap(RulesetStore); - req.Perform(API); - - addedInfo = true; - } - } - - if (addedInfo) - SaveChanges(); - - Add(new OsuButton - { - Text = "Save Changes", - Width = 140, - Height = 50, - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Padding = new MarginPadding(10), - Action = SaveChanges, - }); - } - protected override void LoadComplete() { base.LoadComplete(); @@ -83,19 +14,5 @@ namespace osu.Game.Tournament MenuCursorContainer.Cursor.Alpha = 0; } - - protected virtual void SaveChanges() - { - using (var stream = storage.GetStream(bracket_filename, FileAccess.Write, FileMode.Create)) - using (var sw = new StreamWriter(stream)) - { - sw.Write(JsonConvert.SerializeObject(Ladder, - new JsonSerializerSettings - { - NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore - })); - } - } } } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs new file mode 100644 index 0000000000..e76038d818 --- /dev/null +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -0,0 +1,98 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.IO; +using Newtonsoft.Json; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Platform; +using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API.Requests; +using osu.Game.Rulesets; +using osu.Game.Tournament.Screens.Ladder.Components; + +namespace osu.Game.Tournament +{ + public abstract class TournamentGameBase : OsuGameBase + { + private const string bracket_filename = "bracket.json"; + + protected LadderInfo Ladder; + private Storage storage; + + private DependencyContainer dependencies; + + [Cached] + private readonly Bindable ruleset = new Bindable(); + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + return dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + } + + [BackgroundDependencyLoader] + private void load(Storage storage) + { + this.storage = storage; + + string content = null; + if (storage.Exists(bracket_filename)) + using (Stream stream = storage.GetStream(bracket_filename, FileAccess.Read, FileMode.Open)) + using (var sr = new StreamReader(stream)) + { + content = sr.ReadToEnd(); + } + + Ladder = content != null ? JsonConvert.DeserializeObject(content) : new LadderInfo(); + dependencies.Cache(Ladder); + + bool addedInfo = false; + + foreach (var g in Ladder.Groupings) + foreach (var b in g.Beatmaps) + if (b.BeatmapInfo == null) + { + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); + req.Success += i => b.BeatmapInfo = i.ToBeatmap(RulesetStore); + req.Perform(API); + + addedInfo = true; + } + + if (addedInfo) + SaveChanges(); + + Add(new OsuButton + { + Text = "Save Changes", + Width = 140, + Height = 50, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Padding = new MarginPadding(10), + Action = SaveChanges, + }); + } + + protected override void LoadComplete() + { + MenuCursorContainer.Cursor.Alpha = 0; + } + + protected virtual void SaveChanges() + { + using (var stream = storage.GetStream(bracket_filename, FileAccess.Write, FileMode.Create)) + using (var sw = new StreamWriter(stream)) + { + sw.Write(JsonConvert.SerializeObject(Ladder, + new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore + })); + } + } + } +} From ca9df94ea282a0c8932dfde261fd6618c003ea69 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Nov 2018 19:23:03 +0900 Subject: [PATCH 0225/5608] Add skeleton for gameplay screen --- osu.Game.Tournament.Tests/TestCaseGameplay.cs | 25 ++ osu.Game.Tournament.Tests/TestCaseShowcase.cs | 7 + osu.Game.Tournament/Components/SongBar.cs | 172 +++++++++++ .../Screens/BeatmapInfoScreen.cs | 127 ++++++++ .../Screens/Gameplay/GameplayScreen.cs | 10 + .../Screens/Showcase/ShowcaseScreen.cs | 285 +----------------- .../Screens/TournamentSceneManager.cs | 10 +- 7 files changed, 350 insertions(+), 286 deletions(-) create mode 100644 osu.Game.Tournament.Tests/TestCaseGameplay.cs create mode 100644 osu.Game.Tournament/Components/SongBar.cs create mode 100644 osu.Game.Tournament/Screens/BeatmapInfoScreen.cs create mode 100644 osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs diff --git a/osu.Game.Tournament.Tests/TestCaseGameplay.cs b/osu.Game.Tournament.Tests/TestCaseGameplay.cs new file mode 100644 index 0000000000..eefcd79661 --- /dev/null +++ b/osu.Game.Tournament.Tests/TestCaseGameplay.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Game.Tests.Visual; +using osu.Game.Tournament.Screens.Gameplay; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseGameplay : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(GameplayScreen) + }; + + [BackgroundDependencyLoader] + private void load() + { + Add(new GameplayScreen()); + } + } +} diff --git a/osu.Game.Tournament.Tests/TestCaseShowcase.cs b/osu.Game.Tournament.Tests/TestCaseShowcase.cs index 66183683d1..dcd4b6aec7 100644 --- a/osu.Game.Tournament.Tests/TestCaseShowcase.cs +++ b/osu.Game.Tournament.Tests/TestCaseShowcase.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Tests.Visual; using osu.Game.Tournament.Screens.Showcase; @@ -9,6 +11,11 @@ namespace osu.Game.Tournament.Tests { public class TestCaseShowcase : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ShowcaseScreen) + }; + [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs new file mode 100644 index 0000000000..880b80edf8 --- /dev/null +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -0,0 +1,172 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Screens.Menu; +using OpenTK; + +namespace osu.Game.Tournament.Components +{ + public class SongBar : CompositeDrawable + { + private BeatmapInfo beatmap; + + public BeatmapInfo Beatmap + { + get => beatmap; + set + { + if (beatmap == value) + return; + + beatmap = value; + update(); + } + } + + private LegacyMods mods; + + public LegacyMods Mods + { + get => mods; + set + { + mods = value; + update(); + } + } + + private Container panelContents; + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.Both; + + InternalChildren = new Drawable[] + { + new Container + { + Masking = true, + RelativeSizeAxes = Axes.X, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Y = -10, + Width = 0.95f, + Height = TournamentBeatmapPanel.HEIGHT, + CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.93f), + }, + new Container + { + Masking = true, + CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Width = 0.7f, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.86f), + }, + panelContents = new Container + { + RelativeSizeAxes = Axes.Both, + } + } + }, + new OsuLogo + { + Triangles = false, + Colour = OsuColour.Gray(0.33f), + Scale = new Vector2(0.08f), + Margin = new MarginPadding(50), + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + } + } + } + }; + } + + private void update() + { + if (beatmap == null) + { + panelContents.Clear(); + return; + } + + var bpm = beatmap.BeatmapSet.OnlineInfo.BPM; + var length = beatmap.OnlineInfo.Length; + string extra = ""; + + var ar = beatmap.BaseDifficulty.ApproachRate; + if ((mods & LegacyMods.HardRock) > 0) extra = "*"; + + if ((mods & LegacyMods.DoubleTime) > 0) + { + //ar *= 1.5f; + bpm *= 1.5f; + length /= 1.5f; + extra = "*"; + } + + panelContents.Children = new Drawable[] + { + new OsuSpriteText + { + Text = $"Length {length}s", + Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, + Colour = OsuColour.Gray(0.33f), + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }, + new OsuSpriteText + { + Text = $"BPM {bpm:0.#}", + Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, + Colour = OsuColour.Gray(0.33f), + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft + }, + new OsuSpriteText + { + Text = $"AR {ar:0.#}{extra}", + Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, + Colour = OsuColour.Gray(0.33f), + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight + }, + new OsuSpriteText + { + Text = $"Star Rating {beatmap.StarDifficulty:0.#}{extra}", + Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, + Colour = OsuColour.Gray(0.33f), + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight + }, + new TournamentBeatmapPanel(beatmap) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + } + }; + } + } +} diff --git a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs new file mode 100644 index 0000000000..18ba947582 --- /dev/null +++ b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs @@ -0,0 +1,127 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.IO; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Platform.Windows; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; +using osu.Game.Screens; +using osu.Game.Tournament.Components; + +namespace osu.Game.Tournament.Screens +{ + public abstract class BeatmapInfoScreen : OsuScreen + { + [Resolved] + protected APIAccess API { get; private set; } + + [Resolved] + protected RulesetStore Rulesets { get; private set; } + + private int lastBeatmapId; + private int lastMods; + + protected readonly SongBar SongBar; + + protected BeatmapInfoScreen() + { + Add(SongBar = new SongBar + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre + }); + } + + [BackgroundDependencyLoader] + private void load() + { + var stable = new StableStorage(); + + const string file_ipc_filename = "ipc.txt"; + + if (stable.Exists(file_ipc_filename)) + Scheduler.AddDelayed(delegate + { + try + { + using (var stream = stable.GetStream(file_ipc_filename)) + using (var sr = new StreamReader(stream)) + { + var beatmapId = int.Parse(sr.ReadLine()); + var mods = int.Parse(sr.ReadLine()); + + if (lastBeatmapId == beatmapId) + return; + + lastMods = mods; + lastBeatmapId = beatmapId; + + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); + req.Success += success; + API.Queue(req); + } + } + catch + { + // file might be in use. + } + }, 250, true); + } + + private void success(APIBeatmap apiBeatmap) + { + SongBar.FadeInFromZero(300, Easing.OutQuint); + SongBar.Mods = (LegacyMods)lastMods; + SongBar.Beatmap = apiBeatmap.ToBeatmap(Rulesets); + } + + /// + /// A method of accessing an osu-stable install in a controlled fashion. + /// + private class StableStorage : WindowsStorage + { + protected override string LocateBasePath() + { + bool checkExists(string p) + { + return Directory.Exists(Path.Combine(p, "Songs")); + } + + string stableInstallPath; + + try + { + stableInstallPath = "E:\\osu!mappool"; + + if (checkExists(stableInstallPath)) + return stableInstallPath; + } + catch + { + } + + stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); + if (checkExists(stableInstallPath)) + return stableInstallPath; + + stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu"); + if (checkExists(stableInstallPath)) + return stableInstallPath; + + return null; + } + + public StableStorage() + : base(string.Empty, null) + { + } + } + } +} diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs new file mode 100644 index 0000000000..2a9754b066 --- /dev/null +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Tournament.Screens.Gameplay +{ + public class GameplayScreen : BeatmapInfoScreen + { + + } +} diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs index 6c0eac1c23..ce458413a5 100644 --- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -1,292 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using System.IO; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Platform.Windows; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Legacy; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; -using osu.Game.Online.API.Requests.Responses; -using osu.Game.Rulesets; -using osu.Game.Screens; -using osu.Game.Screens.Menu; -using osu.Game.Tournament.Components; -using OpenTK; - namespace osu.Game.Tournament.Screens.Showcase { - public class SongBar : CompositeDrawable + public class ShowcaseScreen : BeatmapInfoScreen { - private BeatmapInfo beatmap; - - public BeatmapInfo Beatmap - { - get { return beatmap; } - set - { - if (beatmap == value) - return; - - beatmap = value; - update(); - } - } - - private LegacyMods mods; - - public LegacyMods Mods - { - get { return mods; } - set - { - mods = value; - update(); - } - } - - private Container panelContents; - - [BackgroundDependencyLoader] - private void load() - { - RelativeSizeAxes = Axes.Both; - - InternalChildren = new Drawable[] - { - new Container - { - Masking = true, - RelativeSizeAxes = Axes.X, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Y = -10, - Width = 0.95f, - Height = TournamentBeatmapPanel.HEIGHT, - CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.Gray(0.93f), - }, - new Container - { - Masking = true, - CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Width = 0.7f, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.Gray(0.86f), - }, - panelContents = new Container - { - RelativeSizeAxes = Axes.Both, - } - } - }, - new OsuLogo - { - Triangles = false, - Colour = OsuColour.Gray(0.33f), - Scale = new Vector2(0.08f), - Margin = new MarginPadding(50), - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - } - } - } - }; - } - - private void update() - { - if (beatmap == null) - { - panelContents.Clear(); - return; - } - - var bpm = beatmap.BeatmapSet.OnlineInfo.BPM; - var length = beatmap.OnlineInfo.Length; - string extra = ""; - - var ar = beatmap.BaseDifficulty.ApproachRate; - if ((mods & LegacyMods.HardRock) > 0) - { - //ar *= 1.4f; - extra = "*"; - } - - if ((mods & LegacyMods.DoubleTime) > 0) - { - //ar *= 1.5f; - bpm *= 1.5f; - length /= 1.5f; - extra = "*"; - } - - panelContents.Children = new Drawable[] - { - new OsuSpriteText - { - Text = $"Length {length}s", - Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, - Colour = OsuColour.Gray(0.33f), - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - }, - new OsuSpriteText - { - Text = $"BPM {bpm:0.#}", - Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, - Colour = OsuColour.Gray(0.33f), - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft - }, - new OsuSpriteText - { - Text = $"AR {ar:0.#}{extra}", - Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, - Colour = OsuColour.Gray(0.33f), - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight - }, - new OsuSpriteText - { - Text = $"Star Rating {beatmap.StarDifficulty:0.#}{extra}", - Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, - Colour = OsuColour.Gray(0.33f), - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight - }, - new TournamentBeatmapPanel(beatmap) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre - } - }; - } - } - - public class ShowcaseScreen : OsuScreen - { - [Resolved] - private APIAccess api { get; set; } - - [Resolved] - private RulesetStore rulesets { get; set; } - - private int lastBeatmapId; - private int lastMods; - - private readonly SongBar songBar; - - public ShowcaseScreen() - { - Add(songBar = new SongBar - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre - }); - } - - [BackgroundDependencyLoader] - private void load() - { - var stable = new StableStorage(); - - const string file_ipc_filename = "ipc.txt"; - - if (stable.Exists(file_ipc_filename)) - { - Scheduler.AddDelayed(delegate - { - try - { - using (var stream = stable.GetStream(file_ipc_filename)) - using (var sr = new StreamReader(stream)) - { - var beatmapId = int.Parse(sr.ReadLine()); - var mods = int.Parse(sr.ReadLine()); - - if (lastBeatmapId == beatmapId) - return; - - lastMods = mods; - lastBeatmapId = beatmapId; - - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); - req.Success += success; - api.Queue(req); - } - } - catch - { - // file might be in use. - } - }, 250, true); - } - } - - private void success(APIBeatmap apiBeatmap) - { - songBar.FadeInFromZero(300, Easing.OutQuint); - songBar.Mods = (LegacyMods)lastMods; - songBar.Beatmap = apiBeatmap.ToBeatmap(rulesets); - } - - /// - /// A method of accessing an osu-stable install in a controlled fashion. - /// - private class StableStorage : WindowsStorage - { - protected override string LocateBasePath() - { - bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")); - - string stableInstallPath; - - try - { - stableInstallPath = "E:\\osu!mappool"; - - if (checkExists(stableInstallPath)) - return stableInstallPath; - } - catch - { - } - - stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); - if (checkExists(stableInstallPath)) - return stableInstallPath; - - stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu"); - if (checkExists(stableInstallPath)) - return stableInstallPath; - - return null; - } - - public StableStorage() - : base(string.Empty, null) - { - } - } } } diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index 82f17a85c4..87223c04a6 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -11,6 +11,7 @@ using osu.Framework.Platform; using osu.Game.Graphics.UserInterface; using osu.Game.Screens; using osu.Game.Tournament.Screens.Drawings; +using osu.Game.Tournament.Screens.Gameplay; using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.Ladder.Components; using osu.Game.Tournament.Screens.MapPool; @@ -25,6 +26,7 @@ namespace osu.Game.Tournament.Screens { private LadderManager bracket; private MapPoolScreen mapPool; + private GameplayScreen gameplay; private TeamIntroScreen teamIntro; private DrawingsScreen drawings; private Container screens; @@ -54,9 +56,12 @@ namespace osu.Game.Tournament.Screens { new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => setScreen(drawings) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => setScreen(showcase) }, + new Container { RelativeSizeAxes = Axes.X, Height = 50 }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => setScreen(bracket) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => setScreen(teamIntro) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => setScreen(mapPool) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => setScreen(bracket) }, + new Container { RelativeSizeAxes = Axes.X, Height = 50 }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => setScreen(gameplay) }, } }, }, @@ -89,7 +94,8 @@ namespace osu.Game.Tournament.Screens mapPool = new MapPoolScreen(ladder.Groupings.First(g => g.Name == "Finals")), teamIntro = new TeamIntroScreen(ladder.Teams.First(t => t.Acronym == "USA"), ladder.Teams.First(t => t.Acronym == "JPN"), ladder.Groupings.First(g => g.Name == "Finals")), - drawings = new DrawingsScreen() + drawings = new DrawingsScreen(), + gameplay = new GameplayScreen() } }, } From 3427127589afb95b16de9ce6963122ceffc06748 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Nov 2018 19:23:16 +0900 Subject: [PATCH 0226/5608] Automatically keep window wide enough to display correctly --- osu.Game.Tournament/TournamentGameBase.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index e76038d818..cbb7a9fd35 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Drawing; using System.IO; using Newtonsoft.Json; using osu.Framework.Allocation; @@ -27,16 +28,20 @@ namespace osu.Game.Tournament [Cached] private readonly Bindable ruleset = new Bindable(); + private Bindable windowSize; + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { return dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); } [BackgroundDependencyLoader] - private void load(Storage storage) + private void load(Storage storage, FrameworkConfigManager frameworkConfig) { this.storage = storage; + windowSize = frameworkConfig.GetBindable(FrameworkSetting.WindowedSize); + string content = null; if (storage.Exists(bracket_filename)) using (Stream stream = storage.GetStream(bracket_filename, FileAccess.Read, FileMode.Open)) @@ -81,6 +86,18 @@ namespace osu.Game.Tournament MenuCursorContainer.Cursor.Alpha = 0; } + protected override void Update() + { + + base.Update(); + var minWidth = (int)(windowSize.Value.Height / 9f * 16 + 400); + if (windowSize.Value.Width < minWidth) + { + // todo: can be removed after ppy/osu-framework#1975 + windowSize.Value = Host.Window.ClientSize = new Size(minWidth, windowSize.Value.Height); + } + } + protected virtual void SaveChanges() { using (var stream = storage.GetStream(bracket_filename, FileAccess.Write, FileMode.Create)) From 4e872880493fc64a051dea9b889ac1be18feb43c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Nov 2018 20:13:04 +0900 Subject: [PATCH 0227/5608] Add the concept of "current match" --- .../TestCaseTeamIntro.cs | 16 +++++--- .../Screens/TeamIntro/TeamIntroScreen.cs | 39 +++++++++++-------- osu.Game.Tournament/TournamentGameBase.cs | 8 ++++ 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs b/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs index 845f5638a0..6fab1fd875 100644 --- a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs +++ b/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs @@ -3,22 +3,28 @@ using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Game.Tournament.Screens.Ladder.Components; using osu.Game.Tournament.Screens.TeamIntro; namespace osu.Game.Tournament.Tests { public class TestCaseTeamIntro : LadderTestCase { + [Cached] + private readonly Bindable currentMatch = new Bindable(); + [BackgroundDependencyLoader] private void load() { - var team1 = Ladder.Teams.FirstOrDefault(t => t.Acronym == "USA"); - var team2 = Ladder.Teams.FirstOrDefault(t => t.Acronym == "JPN"); + var pairing = new MatchPairing(); + pairing.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == "USA"); + pairing.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == "JPN"); + pairing.Grouping.Value = Ladder.Groupings.FirstOrDefault(g => g.Name == "Finals"); + currentMatch.Value = pairing; - var round = Ladder.Groupings.FirstOrDefault(g => g.Name == "Finals"); - - Add(new TeamIntroScreen(team1, team2, round) + Add(new TeamIntroScreen() { FillMode = FillMode.Fit, FillAspectRatio = 16 / 9f diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 2c50970624..4b5e9aaf09 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Video; @@ -19,30 +20,34 @@ namespace osu.Game.Tournament.Screens.TeamIntro { public class TeamIntroScreen : OsuScreen { - private readonly TournamentTeam team1; - private readonly TournamentTeam team2; - private readonly TournamentGrouping round; + private VideoSprite background; - public TeamIntroScreen(TournamentTeam team1, TournamentTeam team2, TournamentGrouping round) - { - this.team1 = team1; - this.team2 = team2; - this.round = round; - } + [Resolved] + private Bindable currentMatch { get; set; } [BackgroundDependencyLoader] private void load(Storage storage) { RelativeSizeAxes = Axes.Both; + background = new VideoSprite(storage.GetStream(@"BG Team - Both OWC.m4v")) + { + RelativeSizeAxes = Axes.Both, + Loop = true, + }; + + currentMatch.BindValueChanged(matchChanged, true); + } + + private void matchChanged(MatchPairing pairing) + { + if (pairing == null) + return; + InternalChildren = new Drawable[] { - new VideoSprite(storage.GetStream(@"BG Team - Both OWC.m4v")) - { - RelativeSizeAxes = Axes.Both, - Loop = true, - }, - new TeamWithPlayers(team1, true) + background, + new TeamWithPlayers(pairing.Team1, true) { RelativeSizeAxes = Axes.Both, Width = 0.5f, @@ -50,7 +55,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.Centre, Origin = Anchor.CentreRight }, - new TeamWithPlayers(team2) + new TeamWithPlayers(pairing.Team2) { RelativeSizeAxes = Axes.Both, Width = 0.5f, @@ -58,7 +63,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.Centre, Origin = Anchor.CentreLeft }, - new RoundDisplay(round) + new RoundDisplay(pairing.Grouping) { RelativeSizeAxes = Axes.Both, Height = 0.25f, diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index cbb7a9fd35..9e9ed58297 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -3,6 +3,7 @@ using System.Drawing; using System.IO; +using System.Linq; using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -28,6 +29,9 @@ namespace osu.Game.Tournament [Cached] private readonly Bindable ruleset = new Bindable(); + [Cached] + private readonly Bindable currentMatch = new Bindable(); + private Bindable windowSize; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -51,6 +55,10 @@ namespace osu.Game.Tournament } Ladder = content != null ? JsonConvert.DeserializeObject(content) : new LadderInfo(); + + //todo: temp + currentMatch.Value = Ladder.Pairings.FirstOrDefault(); + dependencies.Cache(Ladder); bool addedInfo = false; From 968d39c0e6858ad0d4ba423931ab43ad37a83fb0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Nov 2018 20:13:09 +0900 Subject: [PATCH 0228/5608] Rearrange scenes --- osu.Game.Tournament/Screens/TournamentSceneManager.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index 87223c04a6..303e15aa8d 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -58,9 +58,9 @@ namespace osu.Game.Tournament.Screens new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => setScreen(showcase) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => setScreen(bracket) }, + new Container { RelativeSizeAxes = Axes.X, Height = 50 }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => setScreen(teamIntro) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => setScreen(mapPool) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => setScreen(gameplay) }, } }, @@ -92,8 +92,7 @@ namespace osu.Game.Tournament.Screens bracket = new LadderManager(ladder), showcase = new ShowcaseScreen(), mapPool = new MapPoolScreen(ladder.Groupings.First(g => g.Name == "Finals")), - teamIntro = new TeamIntroScreen(ladder.Teams.First(t => t.Acronym == "USA"), ladder.Teams.First(t => t.Acronym == "JPN"), - ladder.Groupings.First(g => g.Name == "Finals")), + teamIntro = new TeamIntroScreen(), drawings = new DrawingsScreen(), gameplay = new GameplayScreen() } From 53ec01d51f972c7117f56d8c9b0577f86ad89beb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Nov 2018 20:18:11 +0900 Subject: [PATCH 0229/5608] Perform mappings earlier in execution --- .../TestCaseTeamIntro.cs | 2 +- .../Screens/Ladder/LadderManager.cs | 29 --------------- osu.Game.Tournament/TournamentGameBase.cs | 35 +++++++++++++++++-- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs b/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs index 6fab1fd875..004009f269 100644 --- a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs +++ b/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tournament.Tests pairing.Grouping.Value = Ladder.Groupings.FirstOrDefault(g => g.Name == "Finals"); currentMatch.Value = pairing; - Add(new TeamIntroScreen() + Add(new TeamIntroScreen { FillMode = FillMode.Fit, FillAspectRatio = 16 / 9f diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index ebac91c4f7..2ad296dd77 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -67,37 +66,9 @@ namespace osu.Game.Tournament.Screens.Ladder } }; - // assign teams - foreach (var pairing in info.Pairings) - { - pairing.Team1.Value = info.Teams.FirstOrDefault(t => t.Acronym == pairing.Team1Acronym); - pairing.Team2.Value = info.Teams.FirstOrDefault(t => t.Acronym == pairing.Team2Acronym); - } - - // assign progressions - foreach (var pair in info.Progressions) - { - var src = info.Pairings.FirstOrDefault(p => p.ID == pair.Item1); - var dest = info.Pairings.FirstOrDefault(p => p.ID == pair.Item2); - - if (src == null) throw new InvalidOperationException(); - - if (dest != null) - { - if (pair.Losers) - src.LosersProgression.Value = dest; - else - src.Progression.Value = dest; - } - } - foreach (var pairing in info.Pairings) addPairing(pairing); - foreach (var group in info.Groupings) - foreach (var id in group.Pairings) - info.Pairings.Single(p => p.ID == id).Grouping.Value = group; - // todo: fix this Scheduler.AddDelayed(() => layout.Invalidate(), 100, true); } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 9e9ed58297..f7b829b4c7 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Drawing; using System.IO; using System.Linq; @@ -56,13 +57,38 @@ namespace osu.Game.Tournament Ladder = content != null ? JsonConvert.DeserializeObject(content) : new LadderInfo(); - //todo: temp - currentMatch.Value = Ladder.Pairings.FirstOrDefault(); - dependencies.Cache(Ladder); bool addedInfo = false; + // assign teams + foreach (var pairing in Ladder.Pairings) + { + pairing.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == pairing.Team1Acronym); + pairing.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == pairing.Team2Acronym); + } + + // assign progressions + foreach (var pair in Ladder.Progressions) + { + var src = Ladder.Pairings.FirstOrDefault(p => p.ID == pair.Item1); + var dest = Ladder.Pairings.FirstOrDefault(p => p.ID == pair.Item2); + + if (src == null) throw new InvalidOperationException(); + + if (dest != null) + { + if (pair.Losers) + src.LosersProgression.Value = dest; + else + src.Progression.Value = dest; + } + } + + foreach (var group in Ladder.Groupings) + foreach (var id in group.Pairings) + Ladder.Pairings.Single(p => p.ID == id).Grouping.Value = group; + foreach (var g in Ladder.Groupings) foreach (var b in g.Beatmaps) if (b.BeatmapInfo == null) @@ -74,6 +100,9 @@ namespace osu.Game.Tournament addedInfo = true; } + //todo: temp + currentMatch.Value = Ladder.Pairings.FirstOrDefault(); + if (addedInfo) SaveChanges(); From 555d63165b04f716a42434f0702c766bd1b1a367 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Nov 2018 00:27:12 +0900 Subject: [PATCH 0230/5608] Add custom font --- .../Resources/Fonts/Aquatico-Light.bin | Bin 0 -> 4998 bytes .../Resources/Fonts/Aquatico-Light_0.png | Bin 0 -> 68407 bytes .../Resources/Fonts/Aquatico-Regular.bin | Bin 0 -> 4994 bytes .../Resources/Fonts/Aquatico-Regular_0.png | Bin 0 -> 69000 bytes .../Screens/TeamIntro/TeamIntroScreen.cs | 9 +++++---- osu.Game.Tournament/TournamentGameBase.cs | 6 ++++++ 6 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Tournament/Resources/Fonts/Aquatico-Light.bin create mode 100644 osu.Game.Tournament/Resources/Fonts/Aquatico-Light_0.png create mode 100644 osu.Game.Tournament/Resources/Fonts/Aquatico-Regular.bin create mode 100644 osu.Game.Tournament/Resources/Fonts/Aquatico-Regular_0.png diff --git a/osu.Game.Tournament/Resources/Fonts/Aquatico-Light.bin b/osu.Game.Tournament/Resources/Fonts/Aquatico-Light.bin new file mode 100644 index 0000000000000000000000000000000000000000..42cfdf08de4977e66acd9063ef31741f88715f0f GIT binary patch literal 4998 zcmZ9O$&XZ36vof1YC$6UOoK#>Od^8_O?Lw-Gzv7>Ey|#X4HzR~kimgL8AMGq{sB0| zg_`Kb7$YVoy3mDjr7K z#f*s9A3y8r5Jg8vtUG>k&xynPj?Uh6_~4-vQ7Q9^$8;|`ioB$wI$eMNzivrh*R}WX zk=@;0$BrC~j*Al_W^2WY7>YvwN9>C^5v8uERR>~H^hY(Ogmx}(llEmXznB^~WlcMm zbETb+598j(x_)W5OZ!pR(%7bTH)!uD=jr$2%Es6j>+`c)rOlUipx72GV}rELxKG*w zY3CJVVoa4bHLjPoP};*vZANU#&njklhqUjrwmGjuTO{orJ$p;sEbXS4E$vQebBaYp zPb`r(GwzbMSlSQG7#nkpCDLxJ%qwn<30k)-RBPEKty-C1Op1xpwqy^MO5?wt*ePvt z-mhD~zo|s5j{Bu`#yUOQBki|p#Po(QGo|%PJ0lNzvIm`Ux3p!_K9{z%;R{|Zm-cq$ zP5EN)*GQ8d9~F;i9bQezo~o8Orx?o`aaU@c_KfeU=cBvvEc@LftxxNgx2)6Jc%kjt zRnms!)udRU7TTX{khY_Ef80#oFYTYoh3IWOi}wT4&dRHv7Hv@4CwdpwG-gtJm5Lp&SKk;HccZjp zs^i+mvo~nngVHXjM+@{UIcv_!hoqI2U*(>2mdE8LX}x;3tD&jip7%7g16sFJ z+6Bd3(a`W8fcn7dVbawao1Hst{k!(Wa(&-qd|@aIU3VIz4Zi9 zuW6`BthKhINyM?{taz3fqj?wNn)obS$r>;GmBhr6-&iJcHc^L(+Due#!VMESo2X+f zF}JQ4vImfTf$SB;e)aqW`wsJvWRJZzLtr8)Do+SR?ox=(@>Lm z-kN*P6Ye?Won$lY7ox_nh;Ab;Ai_-EhtYx|E5#Cc8mKM|F+lyLJuDPC|AU zBF;$S_jX1hLlSZlSq@ z5ViU4@g_NY?mByjtVR<5OyO?I#9b4aj%AHZ#}aGEY9td`nd}gE$;z6YM6rpLSZON_R^srgHccA%;GON{0(G2|~X@~J+?1$`T}Co-x1R75t)4a3nVd6ExDLp*L9Q3F2atV%>=pg- zevqR<)LTyw^_r;HM7<_w#X2e)%}-FJ$!8dMeTFduxG|O>GBA;qiA+soZ=xa-Rhp=L zEHO#!SI^{%&|D?t$|1V}v7et{KNI_zsAD+qM;*h7)o3XbT1reNaYr%{*F;e(XUNeYX8<`X$eHrSvTis*tQ*dmItE!eF63Mw=l369{|p2G literal 0 HcmV?d00001 diff --git a/osu.Game.Tournament/Resources/Fonts/Aquatico-Light_0.png b/osu.Game.Tournament/Resources/Fonts/Aquatico-Light_0.png new file mode 100644 index 0000000000000000000000000000000000000000..332d9ca0564224402f3b28d295b9ec05d3736822 GIT binary patch literal 68407 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 Rd(f$N8tR(DYOlLK{x5_sc-8;_ literal 0 HcmV?d00001 diff --git a/osu.Game.Tournament/Resources/Fonts/Aquatico-Regular.bin b/osu.Game.Tournament/Resources/Fonts/Aquatico-Regular.bin new file mode 100644 index 0000000000000000000000000000000000000000..3047c2eb3ef7354d250cf4c88b919269a696a06c GIT binary patch literal 4994 zcmZ9OOKeqD6o%Kit%`~{S|k_|M0qG6rId;Sf>54Sd8&YDROBUyAdjLlFp-f%;s9}= zaUuzcP8m6IVB)}mF>0KsL~({OUL6+fhu4 zh&}PGKAocI?2MI12X~z~u=_~V%6#ovsnJ>Fi=7>l_5c4X=55`(fAG+*W8JSDIQ&vi z_Zx@zN9Uy*Bc^H1m0}UOQT3S~;F6{wn zOBLf*#USn-(jJudwNjfFPi0Mem9wR7&Dw^hHb>fD#q?rIOqMn=ly5m#+VNs$(Hrxn zO^rvSJtXa+W{mYY#yn|X*6u0pjhnTuH&jE}E$xW3QZ;nM`s~4cY5erY4r#aK{d)BM zy^e^-VvV#eIT7UoX+Ox9$(1kiv+R|&JU)(v*@G_C9_2!5zsEp_rk1 zyH&@`T<=n8|HK?=i>1xV+GEm|6|*W&XJ!wUN&7T(rRFWxw|T!> z+S%F}dF^#tQ?8MAQS-d8((r1nw83USCggssllE0DG>h(~?kg2LcGi9z6L&z`_c6B^ zU+veWbx%n9wqqb>D{Ib&=BIp8+SJ<5WA1%Q+9$fVr@B|YEjLKpq@1ajx!3-s&Pd#; z{aWW>le8=HYMt_{Y1Xt?xmnsfs;#fOm;P>%#(b=ct=g|Ew12r(-=Eh^F0R(8KjqWX zF2%Dt9X^BfP5#HJ_@kLK>-1F7&!@4ZWhS>t`JrV_)w6QDw0`yXaWuBRr zH>I5~HjkN?x1^0%ey#KJwzRV?XOI}Dq%CX9?}9X5V;eQ`%)REjykYfty#%HA>yr}1 zBf_KuUJ;K2YaDo!j$uU{WNRE>69?495j1hgOpKq20W&dHCWgtxxR@9c6Juba`6k+H zqJbt_WLhO^^KCS-W|uzoOmxEJxLkEEkn@9_Gu>n7M!we-an)5qt{k!(Wa(&-qd|@a zIU3VIy^RD>uW4J8SZi&2lZa!@S#d8hM)EGiHSt>bH)|aDe-jf&exsSl*+d;CYBN!} z2{%mSY@&|Q#N4`G$R0rU1+rHV`!(_%>}RqET(vI{bqwWo)G?IU6)j~#ONnzp+~G{D zFcH^8ToZ9k#5EDuL|hYH_&e`M7fhZeI^dik*8#aU$n`?x(nt{bH4=N_eLWNXs3%qv zt&xcprfp5)erxVIcev+}dk*2tNZtisOzt^X-E*D~tQ$%Y>xObJ(A7*_HQ5a^I-<{T zzG~Od>?CA&A>s@tzCWW+BNMvG6>-%SL9PgLMUX3k$Ymt&LVhM!#8p?sbI$HUb{ry? zMuJ#ta<|ajL5SLX^=OlvJy)GQL{`IzKU27xGI7;JrlVOS)6v8lvKr1rRwg^dRkE^X zC(-OKL{`2^RwiOx&HE9xrH@ z2ILr!V?d4pIR@kykYhlO0XYWb7`W{ikYhlO0XYWb7?5K?jsZCaM2u?*BF44EZ@-Bl zo|-9ZeiNhd1hVEgF`D1Rkl)0R-^7sL#E{>_5Yyvb{3b@*)71PXM%&la{3b^8n;7z& z81kDK@|zg)n;1H#kE7W?H2VkHKgj+;_7Aduko|+~AH-Z<%?_Pt67x~d+Q}x-MQd+1 z3D>XXCkVOtSweopi9h7neKga`CJ`fLjkqaM7rP8+;%Xz|Ct4$GtTQ=h?rqT=g@I8NiLv1d)M>tW0ET zB6|}RnW)l4<)ev7V!uWvSA^y&Ay*FB4T$}G2m6`W&qN(Vc|YnHN~}gpnb1;VGKo8! ziMS@>nuu#6u8EyY#5EDuL>K08{yK8|^C>DxKakmN(yaj?oad&A86e(`ODJ@#uNh$8ZgQhqXch8sW zxxe@Pll;hWdf;?m?b!i@C~W_nN+|D}{b|6n7L^wmPv&av0l`l3=X50eKR~J2GHE#2YyT_ER=caw?8c?h?3YfL zK;U8+Idm9`v4RZ2^ds>5Zc8zy%Tp^=D|RAj6;&()?=GPQm z_bscI5*ia4Q-4LD!;$-QU>y;%vIRz)o|HjwT4CJz$b|QQLh`=dKiGA8JSMHgsf@f^ z{GEFqmbKdz%6ub!;+%}JJ&HDiY}7~6D$KWuBXPJfYYP02Zz{2NjXW@+9}z)_f8^a` z7`o^Qd~Z2m_|7=a_|9Q+cjw}=#gaH3*zxGD*sg^#n9zo|ZI0to(EQ1`Zt;}x;xJFb zG=Mw}Mi+r|#8G56dHFS(WP%>-6M_rjY9)I2sv(<1)L%LY{#CNzdiE<+a8fP6^@D>I zr1T!UV;5f#|Y48wAPrJ~W4}fvBH$hjIVX z$Rv0mG#`LLG3^mj&H8)KbJ3ydB^6&`9MA~-{XIoY1W))y3N;ug{UNH?43=179RT0MZc^Nu5@(b-hf0fTWED2T+7TzKLXOK*Fi*d zghXF>n|VHJJgsl`kReRVNu9n0g)I{)Vdgu96DGavpf zC%kPV_)bX|z52xz_#IcDhVHDW1*0=`U}sX5=4~4pX4uN)c|H5Bto+MWg^5X(!Q#5v zi@qn{0^e<6`$lO#$GGR+=tmQ^tCb+81=fX6yVOsj9ca1OX4(<0dRfG1YUtl_QgaCS zl|qghA7Op>=q8Q)+09|+VQU=XHzIHLh6mtK1@tX$46SW`tvTmtLuobP?|jw}x)Zt+ zHN@*!Qx#ME&UhuBo;S&-XY&mcnwGdC+e}e1MrYX<;vb~y{PGEx4L&Yu&_}JR-6O8O zKsQQ^aANz_{^j0B|c&?5Ze6uNk7bwz`5v1vsKjJQ{<0_ zY5gx{bjyj%hS8%CQ7URc8XRTVg(m0!Ux0Q3^$Usu5nvv zhgGuJpziZ7QW8ZRWTpB<7g3X}heq-^hb{t`q?kxGP1=@R5NlO0*DPEe@%y0n z7RgVN8zmzVD>|-n%5djuHupi2!2p%2D&hGU_sPgG@r3qpR#@AiVVZz4?wuG!z0QRM zG>vWcMdl>-Gy5FM8Yz=_Q^5hTfa&NCW|HDdNW^{NaX$iMDfdhNDo->7VV(?##l+8l zh^#aP)sZYF`m$_gPDbEx*cCqhVr(!@4|s0QWtUm(T!BmO9{=k4_gJd+8EG5qghEC6 z+GuN4N%~BqzEuV@FqKP7Oo1o1Pi<(8$PXC#0pLnQ2yN*TQsFY%2-GZ2Lc8*X+?K_ z&@YpYw^ns6A|nlm@;P{r1zo|6U%!h9v>Y-h>GLO?1ANX%7cK6!8W7YMozIKWtA}=H&l=cx`=`Ke27d_9E&^?CEJ$PlYJhe|rRo z;G`v&PIe70O|D+bv=D==QiRA_7$n%G-Cx(!neeuxJb0yJTPhtR-)OM-2|4LvJ}I^Z zcNrzSgcYYvK0^=%)RClq(Mb{?g;mi+X&SN2y*hqcGk|F5e)UgYxF3|CQS>M?ve z8C~>wi#xqB+KucP(-ps1%%su1JYGv#`>MP_3z$ib$ zd&oOjJ*-a>cQ6r*)l25F`y=cMCqnzgas5Mooc$43x+2aFK(V1?-+22TAy2*)Q;>Ep zSWNx5CP|KZ@U7^tF=;l#(h8xF&qeLDjSNEMRdV@iPcdP-2t9jN5Y5c%o39EAB$moC z1zEeCwPYT}rZg_XHx%$r`+S@x&cK?azP&F`*>C6G=+B%M(M1(u*===+QSSK?iR{ba zKhRb=lA_7QnOzzx%=;=e1bmxSLpB5Md<-74HwECw#eicF&Wl6kB~4XZ{dw(8sUX%x z*HgDmms5l5<9ythBHzo5$)@;1`UYwAl|u>lU>{O zP-(-Kn!LluyZA(Rqvk8CS9raH*3jrDE2_GbzJ9 zs3nE}H|OYWi$cPU%Syd^Y&{^~2yAV1wf19K7W^CU((>3SSZXnTofs&+I-0Hn_(KMi zUKoYw@D5M`m!t|&C|xIslLH^)wblAF0&Y@>G6OM3jvkB?ZRR?FeKX;!;HHK*F%wzv zCh!$4@Lm)XWFcNpohK5-QjrCh#oyW&seknN#<$-ZAXJ!psV!WuHRg;v?R_@o{|OU2e!|TcDaG$o+Z8a21>7tuIlm* z1cIA1Bd++&ZA1C(!KB|)VWZBuT#UG0*{d%yvid_cjMw1c(zqLIXxLzx`?dEB16*6!!29qlVmx~%cc3(UR8AMRDu}Uo$~2O*+N!ZD zQlB&GoC9sb$%MOuufEjhC6Dcoy{30a#LQ!Em#__#2DK?{O8}Q%mJ)R)R*fF~q7n&q z1X~UnmuVWkABf!sT5a`d1MjnJLrMR8(bCjIYoPSdg~)_rSva_-ol<$B4Ehp;NNOl%vkA@tZ%q(hlfsz@#Nf6(cq>t0J8K=|c26WfC@- z;2|Q>Gyw+I9I2(lu}E+e2*+cFRV#ZNx1PzPBe}M!YZ>{5;?j8S;*ZX;v|CPGHaxn_ zZg7Nux`UmN**6=Wf^Q=PWOM@O@HqRb00V)wc|+i)kM(zT9eYzutFuUYaFa*uRo90h z*2ToJ1GW)g{nqv@9c{qcQkg=qVI7L<%cnPAREUE-n{2;t=mHs26w~#_4(vyKA{Oo! zW=H$KC%G4G0Y6qVGiDPJTdX!57=3mch~VZ6dd;2LL3I|?MJrZM$-lz(uP)cdwD%kR zqeZjVS`B!h5r6Z?X>C?ja*EmG*unQQ1r3V+Eck2sk+*x#4|W^8AeMUBtD*k8jv6WC z+)71U+D*5~`6AGofWBIIMNMTH7gO7CujI&YL;L8& zf2cV(+SKh|s{k$tm3P7THo__BS42QlHr!SQ<`JKN?7Vi{Y||?En|`pmmy>g>16)Z1 z+LU9go6p`HTeomo%69T8Nj^7^W)0N_{CNwM?u~`V)K_G6&b~^>Dhu~5jXUuA6~=YV z)IN6xbi9_68aue2TZn8N8GUkm`Ztwv-~E}()T{k>T~@|S!WMs4^UNjh(hBsUKXEU; z>bD)psl(f)4x7Pim<+2H6I%|C*h-ji%QRTveV}hKRGI~hK7h%?;|wGoC>UH`MfiSC zmec!KTHz;v?W5=Cx=L3|Pr#p=I;}yI973V_!y6Ralp=zGeaQepEaU3yf3J-AbqQ9X zqMKmk_47^j5axR#3F7?i?^dXOeQgVf`y}eH7!n_03;xXwn6Kp_IIn=Js(%92V}Arb z`L2xs0Q(E0T#nj2!(Q&MB0Lkh9-B+2-bu6Ig3lp>1x z`wDPUkU@eVr-}!r?(JG=Oj$5h6i~Y=BKvf||B6{>LT{i+#=|KQ=Sxj4r@-ZZ)y zz`#(>USq9xUgJ0})Qa}5Etcm;wOF%FV6vma$x{ZxOb}VS*|yyOt<_)F`WAbRP?ko> zpY_?_nOs}bzK7~a$`|eLFx@)R7<|D1rEF^zt!;1M%7=(`ESATy?z5!%RcCDrJ`F>g zBcQ)f=)>{EURetvszcJKsMvY|Dwq|XGcn(Cf7`Yz*}>8dW?(#eivh2A`Yt{9 zGE}BE)VK>GIFh|qe@0A5D7SEbg7a`FQZMVd@4H{Tg^}sT_HvpEB&{L+XRQ0X!13T6 zgmb9(%0a7Xtz_!m!fAOuF;J(-@K|n*QXKJ2i{|1aSgY($VY>4~Kn3n_XCjdDf_=nF z_-jHH6tl3MZ_3t$!|f`?)M zaT%xzvc(GtnUw9YE6Jg#MQ7i zie>5k78l5jZi-K{bB9s8j3+~CO@_SElT8)g*L zI&m+^AVEj<+J=y4hn3bLM%($cC78#jrgrk&nQoUwQ}2vdRsjVD;l45~XqVSdbu=tt z+c%$mHWJ(Tk>!$F z+nJK*vek(pGRHfil`b&vWidcK9^%*SlvW)yk?Nb%J7Op>QB#Qumh6DzwlDJO9sXwZ zUH+JRO8qfz^Q->$JQ0@l@}={~OozQDOKOh>5j;dSAW0Q4&l%@P;i|xwQn;L8m@%yW zjg3mJ019G9ajEH9KdUULR6a&md_?%nxmc}@6|)mNpWWBL_GyLiTRn8fg0P@MB4q_h z+4S*@@JrZFXA{F$=<(bCp04>3m?aerW-&4V#jGzK0+8{7L)FSj^U!jx0Pb1}0>I9D ze6Ktl$?;a&g>N=A5AW^!yoqN9!i7E!!1*^{oH3pF`353&Cg)xQ0EGiN2Ouk#?I7+P zVLbmCemdh2skYEF0)}SJk5$DF&t`UL&&heH3E3t96E9`xBzS6_QN4jVa{>lw%xkcD zX(_68TZQ@-!xkpb6J7v=TahCeH9|Y$9prjN!cMTt*a(JkR^zAEBhU2(Jo5>C0gkL| z?_Uj*cP9;hvZri^jF3hz*J7{Q({&(&GKr0&%>$2@&;V5bzUNqbd-Xw#AU<;jv%rT) z{LtaCceHGlnKkpOiwD#xHH6|-A5q{+6Z)9= zSu8X7@*L#s+$6s#tEX)Es{_h-W_iRmeHpa;4SOK>Jwd`P@i{KB$&%M`pu{9RWzE-O6|;JyGZO0QNJ+_ak6hyP8L1=?n*bNpK*<&i`Q? zUUP`CU+KlQ?$rn>t|qNKh4NLQv;DJX2i`BRr-16h&*sXkK3n*<1%R{6x;uY+8;S(H9bLn_5r}W1&p>6GD zeRSSgU_w=HaIl0Ls7|Is;m(JoynZST4>o(9=e-Jx2%+`HZk?G$C+-Q@^c8)c80Mzd5AVE9E8SEBQ9JAbFVNhp3WMm$8hP>*Tcn6+=5 z;Tg54_*T4Sv51Iej=54v zSO2^pKeH%95aLOoEeshv**7qAr^bba;-s51w!$7MLMI2oL`vv{YQ={F><K{`)-y+Fzs;7ImNRieCSrfnRM?%7w-wZT5zFhm5DAN5!%wmQc5sk zmx8%$&PMx3d94Lqz8li6p?PkoqE1MS*Q`=*wG2*}h;kxHA*ChNtb;uo!!T@D^695q z`Kvih7PcUa0J+#ivf;U#RglIFVV4AMVdPl!39$_llZnyz>Z45%XxyMX*eHv9$!JF;k$$1`*9+KZO(WUfJx9r)EEfT^ ze#zlxN>m;$U>GkOJb5kJ!8oJ3R*^55ZP&0}hqcIXX{Cn+;y>8F?3qUHge@^`nQEf! zlJ`#6116neeGjC>W^m>iSK*^!_nMSR(hKTaM%_QsThRDbvs)Le(A79XUga+;q64^ncbj^#Ww{VIl-GTWN!!f?W>PC@Tj zd-Hc%A(QVolSaVp!X&M4Kh?RUtUWg$(*>FbAC%jfQ=xYr1Wg$DP}F%0z|hS;37&;8 z$VfU4u+@a?`wWODtM~NT3(@z;M1jh#JsVi1{3OZ!y{LvBpj=QNbX&cF9c(h+&;(@= zmEvtmu``7X$fO_RdWTD0wKXp-jWMg2AS6IUQUZ_&OIzW`lyr&@=@6ADoaAQc}7H7C(DPdWmh3~vh zd55va>m|=uFYN3G`F;E5ca&xNO`H#0YuLHe`bW4>xi4IrF?K4fRJ%w1YW@=z>m_D; zfTdA&?6&Gc)#Sb28Z%O*-(Ndo(iwmTWc~Aap(KGow3b*uw|GxxZ-In$b0vq5)(%z{w&h|Eg$CwY@e0XB#>hK)j2EvuqGY&~BIyQxk)6$SlKSHwWH$A15TmUY zxFa*_I>DH2t1{o}stnHzWW1n z^q^>KTav&(RO==ru3OK1wa^r`>c_pz$Wy*Hq7xO`fHSq=K`b}lmlICDM5A`b{S zm*aEEueCa`^M2a?*aTPZ&v>bDcTL#a!D9WG@BKf`Im_#4yG3i~3jOYDJLh_Te6`hW93pVVL(ab6QO z%j0gl%S9kuAeI*O(vbT;rXAK;4C)=p)8ny>B=WPCXFRmFXcGOPCtCW3J^aNP0f$hA zzgaUOV(V^c)kR;X-hFkC+R?;qU9gN4%rhqE*Yis-;#@s{&)kF2ID1YLkbJ0j5qlCi znC9r-z#v_BWK2!(Xz{TLWX+TvA5-Vv<0BLAp6WtXV5if=Q(Yex_+gkSZsHQjY?FJV zq>Y;8EFQ%QdQY(-3Nl4lI6XK80g3Jx^k;had!Sj8p(z8f%vyH&@BbM{{mq~x#!i0) zwes10ub~Ft@klB1zPNn)RAw0CakW;TN%0bXZFBnEW8HG%VbJ=?kV={@^VWmh&S$Q# znc|WP-eREI>M6S3Nwnz11xbBlAlQJ4VQ=Syo`S-WB9AIFG#^${#qW+Tb2L^%***MZ z9Yooekz8?Sif;QI5!XpJY~SMv5B>5`Z&hMGhPgJ}XH1pWL>{+sZjlw+fi1(wF<u{Z!q)1xu#ou%8iO;2K zzi9?B-KpMh>?snV@gQ=@ax)Fu3t2;pAFGg%#LyX=?x}a8?lH;t23S^lwe2BL^1*kz zz=ZQNjuBZ`!oMSaCvqYMSe=y~n{quhg=&@>r!7-ei-=>8#r)xEFki^%0qmpFEuRQY zC{OK!$lyqU!OUY~lDoCCRj`)uj`Ads9`J!;@7KvdpBF%S1C?75O{o5vThj>g!W5$5 z&3DUJiwoPB2yPEW>h`+*XN`=K#(HaN9;&44s(})DYz_SS(+wtqSAXQ!gT1N5ot~j* zwVkbE)CzQoTIr>j$4cr^&Htcpgg=+5STqRuf%4U73lhv#ZMK1L5-Z*wJ(MQ^*9aiN z8sRzC@O%BUmTLctwA39uQmhs<*tG-apI1~HA41lq4CbAn{t0KDxAdAEq7J zUkr2%^XQAn&ZDdu)&F*ElcKeSF++x)>Q=2voKJ>(MV}@m6{i}iZNKk_(%A;n$att+ zzI4KTMSDVOMcY8_WRA!I^iN&GB5r%^O%IMWT;IYo!*0DGIAP>B%i;M-hH;g6ohQsU z{9U%a_4C4x1*n~K_N2mW3iK%9OyfkE^Ro6^@xe{znk?^|r&z&VQ;0VE@@pB=TRV&} zKWi;ngX@N!5Qpuj4*hHLh{8lu6W5QaUpAc6xsf%q~O!2{NXFhm85r(on6Q2& z9n-e#W6+f<4C%~O(Wa4!oGiZpf)33umRV5;Hs=)mFJ?{47d>aTT&W^2n#ItGSG>fK zcP@Ga-$mB(p>&OkuTcSLXd}49b2LJ^{-nCtnVu)iVej7~a>k%3{#ZXz8+CpcGwo`M zMQ1a>!X=HX%R~jq zJ~!=;u7Gn6@giZU(#@3f6?esB0wDzi*PCGP>dQ{JU5zpMk*mY?GrLA#*g4CD2%f%S zV4Z9ra5{)IZc*t7K7}|P-TzncMG}L48#FQh@PhsEQ-jZ*Q4~eT`=;hG z-XkN5oh_E$P9u_ef7Uqk|Dc>)kg0f8m=c~B)}FV+Jh%Hvh6t^Kon6VF*z#ycUxt@g zrgd`U^S~XeH_#9TYvSV#~$f&niDng_!Az5IP&)Gt0X-fchUl*e>$n?5&Oc z=Uwgn`bCxt$(~M)^*dBWrF&;o{=U3CaFKFmG6laVzVa`CvGEc$p%XP|JF}@f?fvSY zhVrg{6Op9K^!)uXzH_^W>+5F&z|}+%IvyPt3Fd`Z=O$&8_+{*cj7JrbGu5RM3r^Su zz9l|ZtLP3n(SfiU+{a?pf-aw0%26LRR%e(%6N&9E)_^J4AUVpvvx<63NRrlIuLw6$*k+?6%AOrns33N~t)uv3TiAYI zDj!aej`h#vykVHhz)lGZKJ^zrqQ4xdBu3-Il$ILq#(&_org!w?b{o+j&k>I@h^ny& z(QeRsQ(7VEP{JoT9p)MS7tlAbwV5I4jrZ~8$A}H42^*jA%rzc~{kzy=XL7%YZR+IX zIm!wS$8Y=axoQ5S)upIF-_bb8uLi$(W4(cgqoF(U%U{=K{|Xc8H2jAReCRJ$9n=i5 zY4G`-lu6(6nU863n){mtcWd9{>Nu;Sh|`g8DzmCEy+>?G&GlN!SNp@|67~MqQG%lM zu#MnEJEyPBN$6~PN2-hVA8h>Ce^uxgIsL*_}vxjgui3e_SsmGxJ=bE3ST2YK84D?I*FTKzzhg4kR z0G;uMNG#}C+n|9DfPABa9~GXB`>?L)8cdB7tPl4Ba?ML3wSX=^!m-yi@7l8SWTt0y zuw8p--_MRHKpoJxWDKS@uB7EQ%bjq8?(5HN{Cn1-S%SGrBR@te)4~h`65sQ<&aPXi zng9EnlXS7I9t2C>AVPywF&ki_=>-fHT_p!r4>WtGa9DQj0i@f8P_z?l=M~wlr{Dlq zf)5xpt(1ESOBXZSUJq-1rV&{*@NxZzG!9}3gQzrhz^4qZzTkvjJBMTWQ%EW$oDqiAsNpSu|gt?4_-IqbNO2KOuzL;Zx*}loO(y<-sVV~@GRuzto7fo zaUOx6imPu2*L0p!P4td!80MzF!%Hka5BdgBYs*P6q@{uM3@F?#0|XhPr&Y|Btp|#uaD4G zj_mDd#a?6C*+5NqaB&LXt?IMzEcP|3{@;XSmf#!K@WCfYJs6HIqu{!Z!6F+W=-JZ* z{gQCz{}+GrZPb1D0Nbf^WOpFOWTl$t#=^*rVK0qZB)49{z{~K86Mve%t+|z?6FRi7 zGQ2X^^*ny>8LInsvJhYJU*m*mw*1?EhRFVZbBzo#*WDaa39(vd>DQ?2syIE2mJ<+E zFi}SJ83WROjKjZ(5sXox_r(62s;6#2ydmcV5A&Z}=+rMqh5JW_(LVBbg)jY}s#p6U zavIqiFjo@1+?oL0d4B&XbB)jZlI(khVJ-8wksP-NAaqYBB(&FHUVk0aHgBVx^y1eA zQ5&sNxa##kxh~?$4d;4sM(JUizvu{1w6l#%Najg!WnOO}dM*=xvN5I$KK|aw5ft-= z^9spbHkzDpXMrmhd(+ONG>nr_=a8v={>99#sVsP^xjMlO`;Z~quA}__hF})`&FhVV zCa1ZK|J4vGn_OaBmmqhuVO><)s1wEbM+z_?_8F7eb^zx0eg`w?G*t$kQ3st~WwIy* z(V?X)3wG~sZioWjOU$3&p8gfk>&H6Fld@41cIdH;H4>Xnxf5~Luwo$ML+!PmgksyfFZheYT6L7l?Mn*`2 zV7)GUZ{#tQcun&>85)*rgZ~~Fq`K^69dhj_Pm@P(6QTx}JX+%?LQ~tgH-;oka0$N9 z`^(r8!a^)CGJ1Q%y-G{5?T(_NW=2)(at$W`vKl6EnHD#%1DU-0K)yW5qgA1HRPL8% zshZXD0X3D8IEE9PO4h{^oE60(qFN5LeR5IllU?C%dVUl!h^1-ivLUx(=F0=cp!j%J zvZHtU)-0O|*JO*X9?TxRL8ONhM=o@DrCCgY>!dt|S7q@pM z)CVNa>j31l_kjJ_W(`7=8bNB@avtrY|?KY)gjXIM+dX8E9Sk8Eohe z%LYw^W8~T7w07l?mRE34eM9j9lXY1GPFUY*X>b53@k!h^R?uAgvBByq7I`!=-_(3% zW6>LiwCdpri5bB}_9{?`eImNmi}m7uBs%@`jtg9pR~5ff^s{?I(LYf()i~2XU|yRu z+p0q{Rg6}1)cZg$Dldg zi>)Wi7guiQ<=|7A_ylR6Ni4In)ITf#mVA)S_W zt!XC!ckJ^Y^howN7SJT7{l`H!W_5h#jktn{dM^Q`jW73Kqj2dDaG7ZIUG=8+JS=+Z z#b!1@2CFPUr{Sxt)2P7ZD zb4NtefFE5%zm1bEK<#z965m0_E=v0TXB6T+vt$c) zLd^oM{Lhz36D9Y%h7D@6;Cjs7$9CY9+{=t`UhvgR!s8v^yvyT*a_PfgwR@fawj6+r zCIz{j$JZkigAZS_i1lEur4=XE-qW7zTZTZ!)S?wpweMLgyGhkUKf3+a91=}{Ipwt199Y0<#Q@(4+>@^~VI5_ygPa$CxRYk$|imRd4ihWGyiH(4bF zclE&6j#Xw;W-t+IH?PfdwImIVz83FT zVRUm5!vELs{ybTr#-|CUSyo`b0zqULt&g>Aa*N(~njwiPz5qriJ{T+XH=db-C5U+CJWD|h&7(t5TS6cs7zbjIN zFZv9B3YPn_c5~N(?lI_^fWtYHU+`bw3{Q`89rPk*9EmdL`+=%(G=KWJzt`74hk0ef} z+dGfCJrn=MmLd4gcmC0wqGng5v)pm*YKJ43ClfA}?wrPz;GVv$wD-Zzw4KM9XV1Oi zO&0@j^gv=-({oki$Oe4OoqFCwv{mj!9pYz{;~3=JCyOaqZU?^k@*3L2JL1B^Np3ncc>ByP4C<#FV_pa=VDE$H_WYEFvLdferz&OQxh>+Nj}eq5;?^d=J}H zI>Zh9PilX#2d%cEIDrw<<}RyP4yaR>qFp{GQeQvzJ(7Vn3$6lg>Z%_L2aC@ z@(h1pe0m)U;k}=C0PmR8-9NZ%UAqPW6mpug;TXJ&mCW+O-M=@iojgMQu}`X>^n^Q8 z>pEKNWyakvxMJr=5A?NI*Q`G8seH2$c{?HadKg7fo_2-m>$CqugKok~K0-_=JV8p4 z+iP{!9$59W?Dlh&BRDYU3S#+z;bAWR`F!R@aBkM2HMpYGen-l#8*Kb^%5NyN#&Va1 zQrh)2jeB3MY2&QP+_QQRiLdM+b=Z(t)90CBL9fTZ@Hb9ipAgl<7#3!*Pu!dSfVR;C z-H~yiBWSuYCtIn+woZRri8hd4Af>B4fHf|gThAdrk~C{=17e5{l(;iHoh+#}aQHZp?wNG<(G4h3mH{8bG0ywnH5x zt0MJo&zwC$z;;fB95DFP%ZeqwL4)yrB_72pnJHc8vCVJy;?s`KiXGIp_I}Z0gZ{!R3oeHJ&mn2Zlk0`` z*a2M%-;eK);bp#qRolKs2V*1YZYQ0ZMt=uTK^yfh`%$wdgp8{HL#2H9eEOLbF{!DP zl16D9Jh36g3g~Yn`{9g^*gMg3oa*xxiI$jf#g1jTi{ax$*&0xrg^#hf0pz%QDh4w_Wb~HCzeIprC!KB_9rWEIofpiz2Wq|L;5L;v#9d5vFUJ+v!uQ;(^4(;ezU}1tbZ=qv7U_7`U*~yO6#@kv=}&?hmk9oUp9u^j~I6M4@0B zIy9LCy{vfV&0(*ky|=Ss1vdUBwH0P;{)5um+-&>!Sq?|Vw(W{YiLF!WR3Gpbx1|^K zWS*Kmp0ntJiBM?hnbo9Go?nu_#g+IP#Dg3uq*j~QL{ipiv3l{hsalXI1kk4^GaU|} zLwUzN#Z)1*EF14>m`Dy1y7z-Oev^~h-hla)#yxI{XWBR<%GHYE#ZP{jSh;^?a1k^?7V<9*Ran#AcqGILRne?ZTOH=r}5pa;`gXu(1Nk&~N`Lf>5UZp9ak zGUl(MZDEfs@#h`wg9CjRgoA)IFV?@DgF@5{Mju?QpS3|&0}m&l=v3XzXf~trpTbue}l{lFMhxFoKWQq%GP zX<}bk`R?e{7cDSpB|?KKQlBZxjb_GzO0SSkXhVi4+7InO?`D&Ab8+z~C3I4$PO6sm z1RQ58Ol4#3GAw@ksjIYtbW+m-gk$NxjGvoVmvCI9VNcPdhRzbI;)CuKFpYi?$9+QoOj1}pu3{YjcJyPt)qXdDhbBLh7%E& z=Wy*5A{4*F?tC)~-3Bs}*niBPU6i3N&7>s#3U+B=m2)!k6O1v-o>$nIFKSjpZGHbz zH&C=o4mIW34sot{I4cRKgzn}%hGM+Hfhhh`J;JwVYLV>Ic~Y2|akWpb9Q09GV$xOq zO<|rA`uQ4dH<3d>rrKv*nesPnM?`Aw(_rJekZ6*dN>TxC(mz8uN9A={&F;R_;6mDb zi5MY7wIUU?`=0D0=N?DCF2>X6CfgQELvsEIi#E07an6kwRNj}RL^iSOR-#{ay&&R* z!If@fW<_ui>!GmVmQTP6xJk`Ye4+OVoo7|h&TczOTTf3%p zta_m{k~;x8&QKFDdofIqH}T$v303+*#8pB^@%@-8!i2JMJnVmL=>O~Aa|#a=r8kf) z-0vAqd~HUZF0q*IERdgy13&Vd#f6@;n1suJnVU$Y!3l}z5AwHI6Sy#!NZ3W&Q0S#c zBT+_QQ*6aJ^oHbs@Iir1N`cttpT`$JOT%8(69qaeW-fVOVvF*UXb>8UP87%%x!D-o z@hrYcv#EQNSa>0pQBdH);&d@(AJJmn%;X^d{3T&9iz!vtXN<{b-biVJQtIas)CSHN zHJ=oz>h+0YV9?;fg>&u5I;Vn6Vy8m1jFFcBacUKNd3ns+IxyMP${qgrOB;0=s?ac4 zCWWeyft5jrw3nM&@OVyexyQqfj+(qxu!DVXAy_K5iVa?MQ;0&!muqfFM6`% zqxi)tQ|9}XH?WrV=c01=Y=7G7i)t=I@f)ZwOaZ}Q6QZxY0?NXT+;;kQ>HIM=u2)<+ zPji_OO=M5W{nkINvgy$}DvE{yc-<&&bS5B zjj%`ocW1Yr8crAoeZ*0ojz@VQciZ@JVdCZ4?(Oxaw%BI4huij4sU0ts-h1PobDqM^ zqVGj`f2xWoZO;}kh_#JyY1H*6v@iJA5{VRwv!t7F=H8&X>c6}2M+T7=0mV9ObR`xA z>&a(3G-v0_!zevZ{d9PT%DhqxqHtGQ{_}Q#a0B(WKV>j+<(pqZU9JN zT;2lFcf1PS7pHeax?`^V)m%Tz$cZVlC_rBPjEN7ho{UAluxY6(%0frr+83}6zq1!I zN6%NITm{f3W!c+)6m0mmmp3}9OsdmfLjT3u6*kKNpg0ku`nRV)(d$b8WchGWz>W`BR(^pz@mbdYyYxH zSB;z!EGmFLW(AW?N8{wCz@&G*MfLy1p`d)j6G|{xE*&L#`PLdo_AY?pg=X4&6`5AfT3{vy3tJSDlX zw30u%iM1-VDB;@R`Iw;#e)<2N%s7XJ*RA4RU*_b?xse(z)GC+Ehca$2Qj@3u*8D#$ zz*(UnOrR}*p=y;x!By9ebN;G2e(9F%kaPuI2dY zkxXen*%j@=Y%?DsA@z+0Nm(L?HGC=j1|88N9Lrfn3BLgdGnN1U*%m!R^P^tdM@lv5 zMJxtbUaiW-aRYUIW)!Z zAyySr{&nvx^oJ(5TTra3v2a$!;;;@-Kz{+MmC2Lia@^U^YI&uZp+f*h&2KLhkje_= ze9!;)h;R*~)$+w^G7Vn>IDA#4VhX6==}FZa007FC|E1It^jo;?e35LtvuQCj&Q=Jk zcTCel&{PEK)(Qdr3mRX@wUL+Q z+yDQu(M&}x33{%B8BT16)9f1Z;7l!J22Uc0CCQ=JKHE6v{~t})z+OiiZR0cz8{0T- z)Y#4m8>g{t+qP}1jh)7}ZQDL^?)mP0?)-t7J@f9hwf35cXgEK7&3vpq1xx}!4Pr4a zFKSEDZov+JFm-AEFSrj>Jiu!72VnUiXLx%r+#)mRyBYesZ?~_54J|5MAwBsk+9k5Q zSfDZCd;Izud385d+TF^PaD4etfney;Y%6FLA}Pg!&!Ye&C${-Jb*}RSw5x{XE^6%u zg&mMndoMGBz_Djn=CLwRM{gdIsi$8R*6aJMmO+zoX z_d{lv@`G-?(hzMdo`>lSn4t5+JpA#BkL3lg_4%{6QwiVogXvFY76LV>bXsjHo=ulw zfdZIYYA$T1`m4;94HNc(8C_JCiE{)N9`G()b6GA=rn;(Mg|>-HayqhQe3rY`R`&Qg z-G3`+^-xY|L#!;G>*JHG^$I47>H$6`_7#>Us4(}Rz39WI;10`5?6{SI;8uZK|9I06 zwZnXqM`4U~ezy7t#FRf_hOjK2^^#o^_v^+pi>~A6dvMlXRwivpf+W!~vMjH`=@Vw8 zpVlRwfYWvGs-14&oyFVQI9zgGuELOo$)iowo3ELJkMjlr3x_VqaKg$X@XjP{(6sW> zaGq&;yvky{RL+wzg{ z*cCHTR^0FcrJ+r@_}=_6{wLM^*y96!Alse5I2TX)-yLqLG0V2+F&FOgdvm%O>?8X2 z+hSO981l^DS`Hp*OkeRe>D$d+CbWYw9k!Bn&kf_%nKQ}=va&6*B@0?iH;(U_`MLa0ZZw~e++Xf>%qyxqc^&th zQ8&0dd2V!IfQ~3qmK#wcW;VPGzV-&{kQ;%}2BX=r%sOmEn-De74hjedHrr=0w^%z- zR6cf!d*u5T8>;4}+8t5U-DFXDZw$(k>IlUyXOyeiUepd0nIQqBDeewW?n%xC{J%FS z?|Zz8snCBb@Aom7Wy*+a3BfZKTxkE7Q`k;YctQBUT(1!te~<9*CK{&a2@-(bl9|~Q z8D1tB!fe3W3CFZHp4bKWjCyH(r};+}8LwK@ecMS-snVZBl3s9* zHMMEK%#R#0gdW2hK+}WLUwQ*|lRZaZ^#89cgGs(M6f*MiLpFcUcTt{8ZEKtl*{7mK zj4!q}McK{|U-jYq81D5mG~H_#pp1ssy3;GM3kt|hV}Rwx6DltWHR!j;D@YeS6B!%V z#__oEfk>6xUwdgjf4+VkPzL!Vf`dv~{J!P=O%1m`2GlgU+Ew_rf&bBDtje)05}hs# zJeaVKcGG;?I>f@E1Hyuy((aj&{YEGL#KstTo*x-1C?aL@9wCd-wxWMLrU<1!TtP~dkz68bcE9t;EZ;1pXW(nN=%8eJJ^7%S|Rk61a zWo!m(O4_WAN=yXYx%sO86%Vkhr4eZWmOV%sXXKgOO10uMo2|jkKny}RZUI9DuH%|B zDzZ%`C6!H%+y3{+^Bh-4rF2VykNNL{!~Cfc`|V%XG3BceTR2VCM`d}=PK9?1ojZ}= z@*vdzL-1WSOzUDP9-$~h_w5R#vopckul#$QrHETi!^{pac5datU$$wFU&fK&CKMj; z0EJR`%emK43?WV7Ma8X`m8Doq9R)Dsfr=z<4lbXOPCfcRdY{N9pk;Aao9yM7c9Sx| zwzEro(D=v7ug1s5>+gB(r{8&u6_uBn(Zd(aD}d&SJ}LRl$3u(C7LwI?+dS{o}= z>*i{puTf1>?@+c)gDU&8MOw-&H9A9m4_d#`6z~lZe}p|YHPM0z>P;G7;M>Tj5?qdK zpAp?68lbv<_Dsfcmeq|59%N%S$Qa;NCBIt_U`A`V?%W@SzCFn>;bJ z%?Nn(!<7z`HSev=S~~mNvyT5O3@bV;nnuJit4H3*uDF@q2c{IBD@lf4QE`TyiChN4 zQ7vmH_Ji|V*dqVk>)eyZyc)EOk#AZTC-O@0)0e?9it55_{5K!UPJ{zW)|(FzP#2C6 z^za6ub46fIN0Cmbh`a?bc0JMGmb_1wr;ac~!hN47w6Ns1&zopY@;qY5QAwFdX(6|V*4Y^;^%7@>=p79o_ zm6R&T_18Cmmq!N(9b%|}pIhWcomJV-vSUS+gJ6o8&+s8o@XVLUkssLXJp$Z}^9PpNtox+?exiTg7jVpHG2aZXEWyCz z3LV6vW0KpJwg+jyZ8E9X^4@H9dN7cY?5R0#L>AM5&pB`$dL2vc@%#1*q4A%xva~jJ zoZ=661mwE8k_;%kpG(4nBTIf;@mANGGMx2P7eROR{ztwj1GVO`1Q26zDHn3gpl3QY zNInX(acQU4d70}C(9ksJ;b{D@BTbSFk?|Q9raP)zO90oLXCq>EcVo~2IU^64Fh8gw z6I0i{$MBBlmBXa&@N?(eq-j1Usk?$UXcsW&Tx|w<2QdUaXE-{M*LWF;g@qNZ4)cV* zs?>y0qYJ8qzy7Vqw;f5JD4SSB>lZo`#8~b9C);dV0Oeszgl%U$hK@QbXMNg}d(;HH z8GXRllTx?;8szyRBd%%bv6mhcOT!=V84uvJ{E|D6+DEJh^8w*joiMqUx9|qLT(cl- zH0;sf+J8gq_X%G6F^J;xvrBdMYXgr|O`JFGN~6H`mP~ zEo0N)nAv<5U3Fv}=_3G-*S-cHMjMS3ptm-12d4+f9c~rp9etJNp0IL*hNzd^tk_5p z^tq%$MpHO4P;7gXAm5djB^E#zw~G$*{KrA2{}EnU{?f>!9f znoy`|kMnc0MeB5EqN$WbO)=_q*C!6>j~fWO!{0vc<`&C8;<)nsm-ErxoPAUgcv)+L zCw;q35L4HTMwDicB~F9`o8*q<24}5`ps&5%(_I(nSAKo4k`r^UoU)y+BRk-ly%wwy z^t1==AVHNt_>!+%TFPJ|9{I0RW+ZN07Z1`|V70VfJ}WMs=_ruiIe&ueS${q=*Tcu8 zhmbp_cr&ZQSmr@K*gR=jBFiugl2VLW_j_tJWMIkH)GL^6AGj;{Awf;$Ur=%6hntj} zmr6Qf22S@|=z0a-cyP}QnaJpo>@PZ_uF`n2bz-vHBZ(zmi$M-V=$Y;-w!mIX{#vo< zO(#smHL-d|PeINUl=^XDp(tGRO382hVLpl`nQY*Oo_I#`>Cv zAM;v`Uv6@uejD##?ei0j+K3K`js!l;sHDqBu+|8Jk9Wa2_;`~FS1NfY=TfK+C_L3s zu^LKl4|R`qL*gx@r@Y7W`ijwhs6R9g&H^l6&$?~>f?2A%I4(HNV+=&LVfTe|`_cCF znfArFQJ#b%JXA!*a?376D-9@iRkh0zOxcatc3}7n^D6=i@Ns(d5{CS7V|e2t@-Y6* zhB)9wBY)&y-fMS<`Wy2_B9d)I9i;P}34X!&zA2G{WeJ%&w>QGYF&C~9Ac8DpysIU? z@_~s%+dntyq=7+L-+H++hXQ_jh#$~`tcc_sgBZhCd##)vLhGv=I<#uYc$^;+PNY>8 zConOBYtXl=)ypx7hX9`ly5W4GtvUlH)-WGTnL|D#VB%*3$(iKwGY>2fLjWF#ESDH? zXy??$QJ7&@LNSIwW9Gm@QB&oE$>Fz(u=R1f>1N19X-wdC)jgK^hTY2HLyXBt4Kw9> zHIcUUTDYxAJk_dhcDohBrT3_sb!u2K*mWnAPF(M)ul z99NyCHnWy8f?W9px8{cWQv z7?Vy$Tstr_)~$4VxreC27hDTaHQI$ljs&HxY$ZY|vu^c>AaBG>0JF-OrTl zm?@cNx_N9sySXx7{K(ko7b8w9nvy-l!B)D})p#1u9Rklr?k`%-8}<1cRi3~YBXbB` zlyg6=YB?d)vqpehKk~+>uR6$9yueA%*zpW6h?)#|G@}g-3qS6_ydK382NH^pU-6tn zEw*S2yv8aNYq%@=$AOdB!6Bpw2bqeVBWw8zV?7Sz6T1n!B`UOoU-?xIXwTXtVvd^Y z-1P7}qq<1-|Lm%;uPvO^?;ZqG|J8`yeT#PLht(2jMC6fDb?J@6n4V>$Vub9Tc z>!c_z@n!sbZ&ghSV}by#@X|?4~Z+F9p={roaV0=+QmNj z7lwR6PgtFsyfH`&u3S@*uifC!W@N;-Q(=$MnJg`b6hL_{$m=jWM$|!4Ll5e?_PU+ti zl6<4N66SgXR3riV9>TEl|#1=6o@s)1=`CLkM<|wP5 z*wfB>bL?Hi_YjLZd)Pe#UgDK)uJcFrW4CDTLJ>wOos zmn^zRhp}GuSkW@$3O*kEShA1CkrNN`yC_y3gJ1o%<7TXEovt=Qc6r{AIf*ZFbqSwr z!0hc?ZKFKP{!g+oAHvc+-Ujo4mxZ*TDqTP}tL~pF>a3Ark6v{-tqMO6Y|1Y0B!YyE z(_iqNdcTNO1asK(gGAkZ(B0M)j;e;|syPq~ta*tkKEYeA9~epT1AVZ7k6&%I9H-Ur zB3COW>FlGuTxPUsp)QeVzKr~a4>?9xSUgC%9Lu_2P$4pcPFtrWbz3g6jJwB$W3*VzR(|Qxa-^Z@D+DGk73s(bW?-U{ z3-bvzLjAZ^p`VMz&<4U9o}mf21@oEqg2P;YmA2A{u=dAZ>KBhDWtn3^x;Jgfrr1!3 ziHq&-W}5X}(WUl(ZImOh2vR6j64xc}S={Fkle6`4+1R+%Qr63UGDQr@A?49mlf{EL zL$KOK`)S!{F4x1IRwxn~Z%SfTm&@?aiE%ji#n(a@@AkRzMV1ar(9e2s>NEAT-k8D& z&)j4#+c}!8-v66(^84}+A>9cllKG|j&b{?D#Zg}Rnrw6DBPX@G+CB^uc0h6a!;nu* zldavNcTK&mr^zzoRa^epxQgSVt~Thj6+9JeP2B<9W~VLKXNnv?WG-MGK~DRtP*)eR z**uFV#I^83`yxR++UGc;Xq?14QnY`ojPqQlA$x7_hu>>XnG`J_p(T3{Et1NJ3E=ZV zuC#IIgF1xtAy9KceDfsR5@JXqAV+l2B0fcpCz$sD_-W1h0R&3^Jva-PdZR*??`q;z znj+nPT_$*+x4u}eeZ6uY_;<}~XkT7vc?$% z_ZnoYlon$!;C54FwvL&r>GtJa5@($yqH)^7d(mr7;nAcw&|W*})BDExzVn6TR^rwK z;a>t*?f|TOR`N5^!!Mz&g^|fe&52P7_?*sJZ(01Q~1l2&|eAtBS!1~%07o9pawAOI9BBT4HJSTNp+?Zgo-{q zo!Le1EpWlh$S|=K3Md(Rb{={#qHv_hu}jhhFLxKXjJHYIKZ!FwQ z!v#otsy+mJ4fEldYgF#7baS!w3UzYpv&8aMw{zQ7-soe9#q1TjXp1N7Xh5Czs6_IP zI_T>CN;t6+%{EGY5R&2s&my6}c{uYXrj87*%c2)=aB!bvr^1x5lQdCX&Tn;KtPg`_ zmjeH)+P41$GZp_-@GuIimgM6;b19Ft_M)HENc6#E$Q_HG)99OS@$dGq%~CKl5y?Dm zCc4}4?`)-LwC>Yg7ma3x88~Bt3s=u$X)qW9MZrUdcphsN1@_X!jUh9oeg2GveOx^( z@s&tP{^!IqG*(-u5f`LPU1 zv)*Sty=Pj-I5K)-x#VK#QDuzDpSL-7i;nq)=NZG$-x1rtqwsA4q!YD&jK~@RP!E`Q zn}r@sxLcR_(wP(NU>&Q{D#Lu8Ph}cl|70Hv5-VA9PI;nQM@#SOE3w=3bOq;=e7)sl z1|$7}`L=@ibBBMhQqw;;jo&B-)lXZ<>R^l~ewqERnpA-E6M#G`ExY5|reh5!h|>Cm zbNc*5F+;t6!hEn5YhnnpW{WigksbszKsqhh7hkz(%Dp$Ar$;_^Lk_R+C|!XL z6QK#oS!<+M9r6h_q4=@bUwG9ad9^09;2LG`QHYMqOyO3=5|0)Oc{$;`KnKctrd}&- zqmy_~n>~52`xclF?c=P{i7T1@MY=nivDdcybgUt^SPRZL-WRQ^n7?eHyNM|sjoDbg zt>RzQ^JD%yTk>@i5M;0pEmW4`LF0EnozORG<|A_|*Z{t0wdO#Gs{b;>CgXibjlb&q zl-q_Ce>NcoIL;NVu$Ye9B=n$WYrJ6Q+|_rGf>U!i8MT5zhR03Md9|8;hGqGlvUnfH_2>7S&R0YArmU&) z^g7R}Gxx`tP*0P?@$t*?=LV1|)NHvLmRiesJ-Z$MKqY;n5&gf9rhp#xTsq`Q^d-DO zhA4W?GJNTo7E4jC;^AbVr~}G9icA2TWj}M5MwIB%q2jr7TXK|GvBm<7Wphs_nhz8w z-%eJYiRyMg?pk($6N*Os_wL7KXH%7u<*zqNH7EIW@K)G&YHfO&Z5oAF=4h8~$2K6o zII;s2zdid{>{K@>_k+ZFXC3$o|BWXtn9LR+eJ4j0QPMW2=`Qht0NRpCmVT@J@3OdDj%cn}AYVPKDXHZPKFT;elN-&2t+o@Hd;j`rs#Ytw+G zqWz%m-sTU6-p7urA<_9d3#y_?fz6ipp<&5Z%!RQcZ1IPVl&BUa0BuS7GN!hG<>A&q zxA{k@5rvM{9FGZ3Cqq}sB>8l+Z!SLaw3P6iLB?cO%Zy*Rk7a- zopC-#X^+g|!tO(e00TE$Yt!IIlp0C$L90Wp{iiv`r6;KU${z{91@YMPcvi~yL8 zAN+FIeJQPr{u48}NRy}g=5`u6vEI{s;e9X5qQyUyc&Y~$rI>AK!i(dXE~GO4n^CxOg#wqo`84YW0 zbx=&N4vFXGskfkN@))O8p>@T4p1AegYGxsOejoP_sZG2|{d16Lx7Bv!jau|;1kl)! zl@Ty|M(vgxt?1p<|EMUvN_!{Sx9nW=(EdRb5ulbuyBD@a+m-;b>yoS2w>&X6hG2iV z@rdkGVb0KHiITCi@|Sr3;;@pffTzFUP@XimiOL9LD9JIRib$Cezgaue*8B z`c&WC-xc%37&0roDi<+(-W8%DVdgDJ|2&|3#9XE*JdFr=rPEV2_N{ad_>}I+&kpwy^WCE%AB9bT#fF18Jb+CpJkS$zY@GRu93y5C(e=a~ByGERERE`KXlSG`o zmN{!1I@06`X3uszO6J~T#zhU*&s2S{%B#@gWXk2Ee~?XI>KN%mSpN|g4{AO^v%pjP z1Z)n7$DL=h(|BC+VjJo-a-uHxw#dM1sH$bfR}LFBOuqEDY)C2NWQ=Fh*6>ki&9<${ z&o3vdhHs_t(Dr)U{-WIk2}<4fANmu=nP#wfB=N?v2 z5uV?$+`c3a@uF41WS1T#$SE#oPEf+H3 z;q@5TTK&_<^cRJYm=hGbw zFy2sfRg#6*$a^t+R~<=RzFL#tRy!wT1|Q4Myp&!`E>IRdUshQj3o zhGmp1ra{h|}@iWXqQC(oT8zPi=-aSG|(UI6h~2vtcYX+G{$$1$@znU_Vzm7*L@PxPzt$5P-mQv9{v&N}{=iC=vYc-gf%fN}Leag6 zRc`{74m^W1;hKfm-AMnd_k;N8f^PnqzIme>jBJm#{G?Qn&r(VX=ff8`(^{m-s~TgD zi=fOIlMx3yb9+u$O`7lve-fUkdZ(*rTzdA%QQ&gjHz6wFa`c2l+EW)fC|_ z_{czL<;zFSJ@$?0`gkV8e4GKLu+MV+bFKNwO>Q(-8YP;EOgQ4p*C^IL?`Cd+xe~Lx zk))g!U5KSe#m+PfLU2v8=N;H_A&Fs8Q2sciv~pK+)L{Z#&_FkxDMQl71EWz~R;1`%ge>7VZX9Z`I+nQGy6I2O zjgisqhN7PgVWZ8bwU|w=;pLs-#YW~X_^F8#u`=Dw!`?ZrgDOza77MB?Glq_OJd7+3 zhPb0}W}*T`h6ePKPhXOe`n_qKXdX*l)RpNYO3-{Uq{du|Gh+JBmkGt>;%ro_8^9UI zzW0{)MWgynDdQouwE3R}YI@%Kf`NiD zZ3J{U6=eCBZC*$yZ#s~i^1N~mSU@g{aT6~O#q9`?2YYV?d3yVfY`2$Arm-T+E_rk( z^tj7pGXdE+NyNBmst zhIyJ_kj`fpe^Fx=szd9ZN&!S{#;&hWMvybVoZFMf>qKrLKDxin} z6AuCS*ua@tt}NBYDc0B{4)TbCN~IiIO-x`Rvg3b_A5kC_;!gdpWtO&91c>m_GSw|add0WNItmZ*mWwVh3+I0ISg5JSiM|^@ode&Y zKIATpTssx{@44jzAc8yk_1Qc5SxYZ#sz|~zMB~V<+1__T*c21EB;IPWFzFew=TkDj z%ztUR0*DwK;>^7peXNbuZ)@Y7@_inDlx;6D@Emj8sV{qck9e5WUgwm# zd&qa4c@TG05e1=0jymO=ogM~f-w9L?_)(%2*=W-V1pZL1CDOfUM7tE(v?JZT#=RO) z)-VhlzdvI|{GeVC#Elt+_bQf}3?%>6oX5o-F3;4ltR6KZ#X73>fw#SqnSeZfiqwuTzt`FEPdPwVxSh>+ELzBwWVd!Sj5y+5U;?QKK`*Odm6K!A~{* zi*`Z`)PYk0YoW1!Awc%)2=49~5Rxb_3Yf18ZmvZ0ECY40j9d4 zLO4n6>`S${vt43~0gijDTaa;yS*^4qcN$tW?~$HpxAsi)NicF(3%T}oI{@h|@G~3P^N1@Qmt>4^3mj>;n!DQe+y$ zLhnH?G^!a#W^7KCh#5)a!FI2`f=s_%ZzZiE`;*f$F}271+lpprx@DcG;Vb=+wY`}+ z)j!^aMwJS63gGNJMEH(&EdAUi0p_3b$M!T-wV9ggIs7+o@>AknDSCLn@=XyIu+}_V z@a%T%a*(`GPo?I_r`Kf~UQ0#9+=V998-*%o z^@CBt(w z*?o;G18L126Jz`ziL~UN`Z)L65S7)pMMRllrx5${^)M3|jSsnqJDp3^m9HOv_0M-H z#}*$4Oj_XCI}0CQOU+NhJDpPIXJHj0Ya3d=YFdUk&>^-69ZPGDdFCbs#|b+VKIo=h zCVSy=5ogk<_C9HLwjoHu*Q0(ik&Xb>+zQ;LJgH zx>N&jOP+h`7Ugvn!E@A@k6R&QUv%9vieLuXyY%s)p$omzj8#rJWYMGy&Id4C zg?sSKNt<`p9B}lWVmLDZP=piw$yrW9D;GGo>xJ9z1ld}lNvMI;2kWQn^!|CiTqkBj zs{C7(QmM+rC zne~YjZMkAeeDrQ^e+9w3l(3@WsEDPfSMjDTiryCOL%4lw<9=uAPR}`&1q&Z ze~ZlD>_VjCO`(m1Mum*TZBoZ+4tD*ACPBX_gt$jJ_<3CAO&I3GS)WH@yH)k6`|r$l z$vHY&8g(C1MkKBnoV_?ulZ#J70@jSoi>zK@dPoWZH8%KssF= zB13rGkz!Pqwp7?;II_0-x=ocLCL8J#v&Y!~KKAcdcGrYI_NVz%2L~X~8_$Omh2G+J2tyom~@L{pCNf*~`pM>lsC_wT$Ti;;7 zfZq6=p;ok>-K4}O+>xkNWSsUiPkxGoA)8kNrxm;nd(_s~G#t&UpnW%TMJJh1i+d8@A%g;=YwXBNIR?46@)TYg(2c$Mf|6t_T zA52hBTpB;uXSQ({4jsjpngqlfg;cPqwX?&eGA7Ji4m9^4Hqedp2vMS<{#9ee8IE!g zh18~K+|z;2gj0lpokkteq1cqOGzdpJ_Q^xb5O)m`C{5?V28_79fO{KknV@fJF1JV` zlb_6JNk*p+Z(F`$)u;g~BRYJYC>`6bH`WvdNqkoCWA=Ja?RLubJnEbU5@M(~ebdI& z)>OR_@EZeTxh$qyPFR)m2@5QE1PY6)+TXFJ4UbGHnXGWg61Jpa$zP-_@O9zFHgdLt zHXZ&6%Z}+cKHRY z|H3>3EdbmNlyt}Yevs?ON1$hGmBXOR8aP83T01;ai{!xUjc!QdnZKCAUuy(`S-Hgu zuE0bUkS5`4!Uf*HX@VPwhj_nDVXjN`-z34lAK@U7Qgj3LH$kq(+{i1ejiMIyFS1S0 z!4o#woM7i0wlk3hc2(cu_TM4t{UvS=Td?sVjy158i$dfZ>R*0Nh7*pZIGi^tG}+M~ z3axZ@=^rN4vSa>ohw@$N#@^`-QKw8s@f#U-i(OkRW|S%?j?vg|_eYu!ZTtANOk#iK zsnZ?L4e1DZVk}bu1^)2mL0X8@RL3}>SC%&A$J6xeQW#EGjNYqRc$X7<=rr9{rK~10 z4z-GviT1*FLUC7AF62VEC>ylmQXVq@6MGh36)MNi9`)XHSL=<2G--gBr8nkML&xg{ zuBGqGo5t_dt-8t^j-#=)Qf9MJlD@NS)=Yr9yO8$e3O-&8eXLOY3Y;~*%$qR(7^wTv ze>BkiL|fU~Kj)JXZ?{#yBW=|KH|_l|+sV3jK>la5M&_PJ*829SLTj&y#1~WGEY8heELb(@1#dM@j1%;EmJn3Z9O~{D zGbZ&*CJhwM<(6ELG8<)(P&#&%6ZzgJ%H9qAdibHy2+R|f6mT-L0B?dnE$o!jwZ}zn zQLM{Ymv@iThPkm``<5CvYv3oRv|8J0%kJ8UJ@So{B7VFw>nu*G{+J6SeamiA0-pa$Lp~Q$Uw+u89^D`|YX<7)yK~Fa=Gk+Upw}GaA$?SG+hFF9xi2Xf z(~Va>gBLjk_Tfj2_-`Hkihx8?8-ho6WfQ%X&K-|`Dbwp~-5#v5%@v~b@ZCGh7W`Gc zd@t=J%r=!3TaDTyXU^D7KoG^eO36C9=2(M(;T6=k(AV09M^G=lHVbWp0qg5N_5G_| zF?4GB8l{5WlxNBVkGO_p6rsU=>k5pW1>xjMPi-A&f4_GA8M z1Fv%TGnQ;P-3xK_v~C)OaR29ILTv|=Myi#0mbAcqOl^B=XZKErvYh#cwowbK(#EgG zh93U1gG^eI{1lg}hC&sfJ<{>Sbbz5|QOkuC{6lop1M=(3*M(!#fsr!b8d`!9ws@F* zYu498#xmJ)tg*o1;4QNJ91A|rF8D|Bnf?NBe{S~%b?Wt%=7g@ui$^Y`@P39@9f@m( zo*vXG9JA2!2JiWAyiyjdeY#J)HZ$^!^rjO*qnn;A-p7e*hAETN~2i|5>(NqU1^D<3Z0S_MF8h36MH5K zrPFdvQkys?87u)olgy_daisbp1NW;$93d=gfV1$p|y)18oI{2vD<#qlR5c zkUAKfw#_ENIvb2U{mO93Q;Lzi(G{+-$q=FZ;VbJ*=8e-SIvE%eW1cE0Csx2kKpsd# zODxj(ip`Yw`TLn868;!@7wUbTkuIl)N+}cQ5W^Iu zo%1AcOy`CU8js3(vbI(G zaRdPIniJ~%AeOz}B)(EmT1dM4bN^lkQef~Cx@>$YnMUEex|T;lg&+8be(|KcXbCG{ zX|`Ji>)q&cfL|ll3P@z|*{ZX<_axNxF^XO~()OB&Bu-ir4v>cAexxWkK=CHq2|RG7 z56Z@mx?n!k6zzd4<4a*WchB&%8_H*b3I1B#U;Gvg8sU0&*s_r@SPsYTM=6* z4EANI=_=7j{uq43pKi)Wne5Hee4c-s$rI)Aj*i=DX8ojVEL)<41ct;}3>A^hN6yNbAJ1RH`;f(i5l~&;UrSmd zK?|n?mVZcYYW;HkM2TmoW!+GkfuWY*|0BJT<5r=vM!Fdi|JSh0*SE@@H<@YwuQ|CM zC^eiA2aN24zu60mR&qQ^bhme14kTP@+f&ul|0;DRqtyKbw6cbR9yn4;VzAbJGaVTM z2%3;x0qkZFKz!bV`Lo9jb@++Q$l*0tqU{gkm_<7&t{iElKU1Qq|0H`NyYr_Any-42 zhj#M;MD$qye*4HjyVG9k>hL=?ofKyL^w(Y^iJtWxv$w8=XrwSnS(PIB^MjP88~ceq z{kWTtZQwzF5nA(~ALC)qhF`_PN@H1NiYr!8y8M1!xD>d= zrlY2y0iu7%u+yU?rYN=tZdST86Kmp)^AA5?WyZ>HoWOrSe?`D7s!5{8hLy%-GH*s( z0=dL*UR9F@yGgs8aeSXB#>Q4?`EF$UCFC^+1=t1NuZe01aOvM9|0&Zc=zpkBiD(if z?!QG@5H0D}e)dEyp2Aq06&rVYyEB~m=%}Y}bo^d+#v-@WRT(_HADSP0IgI~mCBiY7 zEOpa`-eLLXNu?Bj+r&7S|J=1>?rXYRB8AXY5tTcXCauUm_}+GukU#xZ?2dn!;2qCF zG?{-dUcNB)r9`Yk5BKb@xeg{G=hH7pN9W=tN|4@Ir;v->re~XuSTg&&I(<F|o+s?MmQk@T(6CQSK z;;Oh}-eIo>_GhTR*MB8Eji<_bHf&Xth)y~POG!59qASKXct-UL$&|Wc*w1jrO@U<=~-j$#zR3H?#q>v9|@~sPgQIO8If?s_dFMz$YX8lQVK4 zv4t_~$4K44&g<|DR;cVQBJlZ;6u)$<%da15&V&w~ay`|E3evU!b4vTW%U?SRYA9bP zTn_wXBkCOq{8X1;C-|zYvfVN?2Sm3c0jsftXREb<;S{!=&QkICtF~ZU`OJ=i8AodA z(9=(OoJL3qM(XHaRb3QVAN6*wErUD2qA^z_rh1%+a|q7|B}H>P#r5y1MYS+aBwta2uXhG4Tr3 z?YT7KE`rF-8HPTvfp5OyQt`Vk@IUZPDQE;MG0&T4c(_kMA2R#vl@B>jd1qHu>e1@; zi0HcIzh`g1{Iz`iqq{RIa;&XZ9(9J*z%cUTtGX;WgevU65{ELC-M5jPV%yPwXi5h{ z)pC%+Uj_`bOYn#oKsof&MKD7V56PvLAslx!;4y!EW*eFE6#$T#KKqfxB9&AjTRb|> zbBFjQylwY8Ze(=zI9tJ!0LaD;J7fDKvGddI@86wc>SV^o4UQ4lrtH0fux*l^3+@U+ z^Q2$i`O2In@C}S#3sZv;vju(cr)f=ztiJvM<#GSWjW1hC-wd1&ZkESaRjlgm*s=)! zBSAwN$@<)q6|G~X5>kkxuR<85cvHa}{IbQ4D4l=R{9E2hlhPv->s?-E*J|+Mu{RgO z*i|2>XJg_cE-M1c1E3@~;D$kA6w{5F1LAHuKk5lp3NHDs+}SzZ50%JsCuvTvT)es*~5~g zXkTE!!=$1xDhO%vMhR7&(xw~Kruh!Gs3DtvlDH%4@EcTS%E{i8zqT_-5Xl0(GPnO! z45^H2G^2dW=tm9MDx~PSQ-0d0MzZhE+p~QL{V`l{!|`*9V6haV^Yr#7w*gubW`u=js!&6e0p zw@Y0*U6(p_22JSZ8Yec`J{G0K?$nBm^@??u_;n#e2A4mU0JQqFdoCb-OYddv|8i>F zn2Ypy)yO_i1(PUR$u_S4y))Xe3FZW34J~`15t5xuAk!z%z^>|EXlA#*#+eKP?}LL` zJF1VPo;3N!nrP^gxGjG@BxrF{>|uqWm}1720j0bk z>|DHCa=v;(7vg(JXE;(8Z1m8n;OHNIH`MU@{+-`)juMIBR3XwfPH8@vLjmD8@h>s! zEG^vViw*4mK9nG-JOJ5`N};uV;Fur3*@ewA&%?p;^hvac)SD5#^QB}o&0k{S$yIx( zmY4#CNMgB4C8#~CPf~@E59N=NK-4P7?>0D6Do|s5?-?=Wm>1_)1fIo0WW2>pO3ull zrvekm!)p7A{&GHorjI5yaD2JSxYyX2$VL3n)958Q)>P>1oJXebqbM;^rY z@lM$Al4cj7%s-f8qT73g?(&xRI$saf9fO+4Ew+%q-tz@#mGU#6EQ(S!OXnG=IlKHn z7eLTFsOl(?(zUfJ;H62k(KP{`Eb|ar59TD&N3{;(M{N%6-rh?QM&(l7w8bh!W36`G z`BtZ>B?jX`0ni>|JQUjm8hOntm?6p%b;Q%3KKkwljW8eO*2&8i-7(mV-f^&UfxUfK z-*OklPF0apfy5pBud7@xcnw^nUOBN5ff<9oU=^_9z9`5s8)is4vNSH>&s1R%Vmf6qOHmd_fQ+V#y(9`UeF{lruw|bInUh?pU4`=;7D$r>T#7D zJ41e%_{(HJmH*gVnKAPwv8qdzr%S&K=4a(%V{}@?C~U4URk|FDBTf$8m!%$(HFAos z#YQjU4!J!OoPhiKn0%L?SJh>KvV@buc)5~`Nu5tf#skRW_}b>&;UNVs6;(vt5tH@Z zE>F&vk3wgO)_#?Lwo+dGtM+Kn*{csAj**ds;9N%f*uMe&%O9BK0>-2p@Vkaoy12iD z!yX#fEbaO1U(}YY#X_r;*t0euyPxe9b(oH157%3|qcvvCtmCv`xrase4wV&(;zx$a z$gf0=UEQke6Izs*iGicKIDv;vO7k~safNug*SWSDd=_pK?rDRMHLns3z#i1Le5n0Y z-jNmyUvoE~ogD>BB+XSc_8ZXP2eV(b_)4O>S$fdfb}UwWj8Y+8#F|2g6`|JEl2G@+ zp!ZdTlw0I*Y1!EFZ-8e%O`yCUy)2h~ygP2?Rl+o?F`RWQ;Xn#fz5w}n2uQs_FKQsNy%KX$G8AD+H4tPLjEI#{8lIK{2F zI}|G(+}+*XT}yGdQrz8(TM6#&?!|+<u%_5bgZtVrYMKQ_KoJ{ynpt(Z93&Z)LTT$=|RN@;y;UspX@ch+myC912*+i#CS&48dFBhZvtx!OGMbl z2MpZ)Y0y&R13VWF7!(r3z9>D5V8-8j(6V!PJ9k{s-U-%VK4E}X_AlTc0p1g1YoYd` zv(Ai7BJmV(6RCYlQK~F`+}7-0@B;L3cdCB%_l1bUvW~blPR+&M-_jA>2ksZ z=C&-oUWLifos2($tvBYT`FF~1OZH-e%ewvmhf3M?eK3!gI$rXK@j<0YaT;Q+sPA4M z9^|I(l*>axx%bhXwS_!PTE1o+bO1g{yyFPjb|cogPuNg%gU-|6In;g#Vw-C}&qm2M z=8k5Z`#WP%@Edb3LHXP7bl=deXq9dL z&o2!U<1B!HD1%Gy8=UK)C)Rh7yB)%>wY~=HuvKxn5l+myrJ=`!yFfo08nj!mJZsuG0vESTMT?cWGEkS`#9~7@WY< zGjiaJMl!Gx*x-jN%stzn#-iVtlvbUJaL0MHDAK%XDJA>{p8}H>`dCegh z{t9(~DWj9Sg2fwgIoJz#XX?>9%^i1?ymhSauU>lCtc`}qF?1lR9T?zoN&pR_T*KcI z{`CgWYhKDnvz6Hyb6I%&pe%+)8IS!&ZP?=O*xS|%nL#qk@mZ-Dw*Ml0fEK)aHXVCu z0sAy~(9f#=orjz4M5C~5$yj-PVUJ&#tY_3Eto~wfIk2G~(*;&bmYAOInS+IyqTIgw z6(5Qp3*Wgsiz;cuI#E=-{b5Hfmlg~Yh}fHscVDQPq6V2nT2!pQ*<*qW3A%+VvIrC6 z!X4P7KIKZDYq%~f!$lG;%5wOS06UW#zo!!ydy|HdIvReL_-cADv)=KI@@up!VaVj6 z+aF#UC7(6$(E}?KP?d+v5rcL5wrvQYMn_V!#7c=(H@M~^=?a%TWG_7Vso}XmeDDi1 z$YmEP!n{X9DuH*BuZ%qp>tPi;*tu+PM4sgSOHBwVH?Y8#IYxx(u!<;r(V2PuM@~3S z#$CtdM|#OOMkwV)7v&rBTmtA}PyPK@@ug*f-47W=kVn~lp_P}l_jC|d;>>sW;zODl zBrD0mrzWWt!J5$%2`lF&0*(^uHz*8fdS&ZY6HQ{HyTj}-AE7v1uUq5mom3v1x3!l;$1!f`L5;o-5H+*frR?c z#)2@ab;VZH03O%}W=^y`_s&#)r;8MK#&%|$Kab36vsjU4H1hl{HnHlaxG8Lc5wBd! zGUGpL;!};KI=cui@)=hdFHZmfFC=g7s9s`PhOc8dd^ZJr;4jMJM#ha+mG{Nx;&G9r z)8wzf`3g#TOCSzoqzVio+*qD%9gohiW)!xEo4=q4eZfV+K>rQpoUK%}5hrd4w~^$n zDD5YVQImG2i%2zN{%r!ArNhlogFo8l1@ndJG3!;lXiQe8Gav0D^oK{kzJ%<^t{{z$BEZ84Z`{ADA{ee#pQAiKv?3m{s zRt?r>V7A_vFeTOQ>)3@T?+saXb!_7EYXRGXEA2`DG<{?K;bz$2xkKT7`-eXhx0hhR zQFIJZng*UVI|>i}LrRt~*|Y#-aF(yPkfqJlXP;r*ftdzumx_r^qxAzRS}wLsG zp*_zVgWUl(CQKzOLv2v0Ye9cDbThR~oXIh6kYu8YQV~&@>p9;Fyh-~z*(^V+=u{o5 z7%x;$`zRswsd@qY2j4nI58|NCZe%y&K-y8p<_`t|!ofWj%n$U3MBB7`+@xg0Ej}W@ z9D_-RvQsc>^#Q^(%_KU2!vS0n%g4b$vgryvS?Ab5CEoF^>l|_X@ag48L?FjYu|S#x z<4@hKt(+sO^=uwg&q8N;wU-Q z3HnT$6nd#%mR})BQ5GC74JIP%vlC;yRH5EQKu=ru!;rBNMf)z66S?`AUNann56wWj zD`$7yfM{P7A7$&sQ&xZ{qTV_x;FqUG0|DefPPD*J1MyX`6@ffz+(_-&JTk|#;Cd8| zXfWsJp9g{~1SdKd`tf*iD@UroA(L`lt9c`|ssB8-S!fTanD~^xPe?DPT*C!xSRmXw z9c4d=+e`=Je2K?vVQ|^+PI?Eucq_uLjnPj9^f|}soqCqx^WwZXdNb`aj&V>-iIy*H z{PI>TLIv8mf1`1cu#>tkU-0H5z23&(cM|we%~joW6<+wTF_Cka$~ECZ%&72K4|-sW zGp=`xsw24^h%DnYqZqmp66J$kD&{V9OUJ^C>o;V|isaj9V?{mQ`78!4&@8yqrMbkp zgdOeo-sC~NXnnmT1tQ;XeGLc6kioC3&>;JYeXJuc+k=U#k8TYam`tTloLMJ3? zLLsg5(8dm+d&d1byVHwphSa&k+MGIta(nqm!GX+-lh~pBfTX!IHmb8qo;+~Tn0kaN z;Xw3^(Y^VCmvOrK83whewHh4tYp@;1MTRJIht1R6Lb(qt%uny_^{J_)A*JBw7rfUY7&@?U zvlKT9^NyxPSd3vG)oFnPXO1cJ{TcU!^p$a7xo#Es!CXaM;(2Z$!7nY+w;&-MXa46+QP)b(e*U209 zV4GK_+u%gv(~VobuyMDa`BgQVLK(4yhMi|I31p5>R5~mWn-zy<%7OGxxT#%8-c*G* z;lUm6=bx|>$})ALes?t?W4NS8w+`kag>tRa*gv=AcyiY&y=g16uzeUE+CE zr@coIA+^zVinJ*KhGP=qDRJ%BY553#KXE-vkXV zjRB_bU=p>zJH7Dxlw(oSpuI8#>%>_oIT>JOLGjIAL9#bO`bfMfL%TFLOv7_ddJP8f zob9;doqLcKt^c+fYT*tD`oTN3y$QxtJM6%YUF#1!Rm$eKp0NCWq}>G_$(W*gd(ms# znkGv0NiStr&+pG?7Y(gNY7851Z%cZP3PlUlAo7ylFR{RB*{2V)Pz*v;m?B|O6mu5a zZak`OI=VRNKWVqjxG>_~$g`1g8H)+U5-#O5auJm6?Gj@k7TZWkw)}RXK4;CC{>mwg zbl($=G#fBMDmQ3XA#hK2D8Cj!snDCO3=>Jx--;1InfV`vb1AolkjaHYm<4SGE$BsV1C+7?=8~fsO~R z49;R2SXaZ*Wfq$VvboP>y_$aQ9f`W}Z}qnQ^Cq@xE=zXM7{fi;6ZmTlmX?sB>Z#&J za8#|ns2?nQgC|;J=1i;u6v`*Tkq<7oOf*t#!9k0#~SdpZ@FL|4bcWGX8mM5j-A492CK>5 zhFhi@e9hV$J$+Jx_3GaO){l_WC}$2ilK!HL5u+St!gO=s4o$e*~q?}5I- z08D~!jAv_Kn1)!I&+UgJ0n_oAE5k;&1f6)R(m!fAdtQbhnwa8O$p)_#i%(1-lqXfu z#Qjk%@Qwcc=X=s6Yz0k*(K2=HYCmH-(re5~K_c{s9NdbsENtb?CO3w<_+YYx`m)O$ z`YzW^z^@yUA%AtQ0xKwU0W2hUMUcJL533u)uEF__iU`?Zqm+Lz=kK06zh|E5Zamp( zrWQ@UDK3wpJAkH4-0+;joHJ#EHX;n8b#8qQb;i*;V>>=fEtOgP)hN+vMdfI~toY`5 z0N6K`s%y_G2*eEtJ43&nGSHB1wmg0|D`H3i&>=-Q~l{*F%(u zGLeFyCQz--t3M;=Lc^lVXUS^RWTk7sv)Ay(4|%SQKUNGX4Docdr#rMZr4&uqZ3jS> zZNd53*rP84QAhBzO(CXJr1^Q&a+C73#FOym|bMaf}fy`R@>azKEmF#SN20eS=ZA*eQ) zh?Z)y7zzqjaJ|zs6C{L0IKFm=*l2wdXM%glL+lYe>cLwg+rU`Rek!@mqZ_qkzQw#U zCTqEFd-`W{HW>KRU|VA^5Mw>tBsum4)l8OUx8<#Jh|!FYP9dbL4j=L>Wro-~hhW^r zLgd0U`hygaPd=wb?qE0Cy|{fZqh44RzVmOmR+P*uAq)h<_M3(W6}yLWD93Lv>7P3f zdXpH5WrlKnq>}gHl$8R8v20y&**O%jGWylz_6!?k{Awu^Pa7qXmy#vXdCbGi@C;Mv z{4)Fgg=g70m!f`Yvny8TRAAXi4^rcdXcAxH2gew{2G@3!Gf3G8)l3fpZItbS+xAbq zHI%`wBCF2XbE&+nDNTlj}x z!lzFh_yh~qb@M&aehp7B9DTF@BHo4XOE)11`l1iXrNmq~yEqo2fLjQ?qTNpMIf#eek-Khe*l->@C%2;C^|f%lR-MoKj#j^*$VMMy zD&{>XE3=1jOaQc2o$U-vyqfTSb_|WWgC&i>y|V~E!^Oq~Dly$)K-)bN4(^RhUK`8? z3-i)oO+7-8uVMo0B8OsPykmr)8;zr9TPR8s85)ulJVbELg5`z&eR8uG$hmEWjd*&WVA-Az;(*jDVdjwPB4 zQ}8BrNYN(iuYnLZu$y++}ij(Wc8tW@a;Qc z{+$uVQS^`cnsa(ty`Ox;?zTVRgvX=BJ@ne}BCnse;p~*_Mfx=nP~9AVAvlOClOvOU zEu50vNIO^tUb7>X%<0FjOV~yK)X~R}JCPZCBD_pBCVer9_9-2)Ue3r9-W@mVcZflda0qD{AgMx5=r%#Vt05rTo-PvET!9b;=p$wTflqjAjwLQaS zR&FZ*_Wzg}gI)QOr)o#Z{A!>tDW!=nydc7T?;?#4D)z_tx#ts^Gvy&MIt7mzuf~XT zRyz(t`bs*M()O^yX8@F-&Yh%TDeu|m;?LNQJRz~TWNf{jt(}WLmFIdM^kKl;;IRnB z{Oj9b-Go|-VD7hW&?bH{@poG$(S9a*Cje6PsI`bk}iofAa_Y7KV@N zPvAZWjJK2KlPUx%ytbx#9trXj76WQPAlF$f%YaQf9yEjULg>i51nj>8n#`IiYIEb6 zj;8hN@sJm1+bzgXPwT>r?Xr#nHHK*E8Q`XjaldpEn}_}zA=|%fjCv=A6}a%{mXA?K zs#0$wUI20WILV76M{s)0ur{ZQ*TX)|5Vj)wI&Pwxy$XT-C7Njs%g^$JMooU>YQZj4 z-I+)r{-fM)^g`ynHIU_-0m&5^@4t^Y2U1bAM5F^UO?Blq6-{TFWM|sinpky?v>H|tb(G$aaF7I!*IZu6%&8-I=K%kMBb#+(^FJ+7(^DUKm? z@Cm>fq9w?L;((}Ti-1eYeY^2w!Lt3aq;q(e=l5L5G3U4HSI{3;g5sWaxpSRfx-tXs zY05vNV{Z~701U2!aI_3EMpRXC>ahu3OIwj`r!A8a@3~axk#v#&C3-%X;bYHmb?g8e ztV4nA7CB<1En)v(5C-UKu&oG47jne4uKGi^8vH?3h`&f(cjG+jGfMPkXcOU#mz&{_ zzfpw0YPf*YDN@l@wPHBOPaFC0d8BnDGU;1*2uiyy^q2YJyi_~%XZi{T08|BIW_d-Z zuQ^0DBHkuz1f;i|ZqWc(U~m&0Dv4xKjIwk_gdcWADVHq{%;r_OnEu%d>_Zw%e(W`V zbze@M?t}2V85|}Be$wTDI_Hxr?(?gPh_rJf`l06;xTD{PlDltG7Z}7Pl^%p82mArwuQ4}%gOR#!E;udmo z|APpD@mr!+ZKZ1$M!fOdxpW9c;>~QYCTOzp-jRb_1kOmp0MZ&K@O&U- z03VAyJ=iDf$7e)_!@Zm&;aU%6f;d@_L#bB z9qSinry{#h^j81Nz)6I=BRN|!%|j8^>v^i?Mp2nywGG0jVe$lT@`DZtY0I2RY?^%O zRiKr>ss7LG?_1}qmN_0n79jjVdp@P~`O^2&IRbb@VP~y=*2UR0uIa92MBhf7M%M8H z7LUyp27B75R}zn%DzFTzOJxHeYd`C|`L@U&+vEV4j4s2Kp|QQe8TNgkLXa{?wUwU( z@8Ld42mq0HX7*0Hb4MZuoZKiHSxF2L1dl@W)`UxX0NXlt)dn!AebhCZ=SZkQyLC0j zc1n_HYNmu{a@sh%!Doxll-5*sQGZh z_8Mc`czZK1cewi(oSpE#xRp!8f&SCj(0yiGM%7wm-JE4-oqlFS`%Gg1*{BEQEO)*- z)7j+ihXh4Kku#W&5)SrpL-+4;1=UwyF2D6XLVG*!G;G_YxSJYF&i_3&+w-WNJ^@RV z@C)x=lVPrYUOozCx;Z{>q)y`S*85NU+`l|xG*%OPx;UM*qlTOh04Y7@JGR)<8T)~J z)sjwteMJ_vi=$DqqG5cbpnh)>$^bWiS|>IgRz-k=Bx*UQ&0X}Xk{}*%6m||OjJt+- zH-_e>1Zq2FRtS^qp;c5G0-$0DGTJ)vcUjy;7YaIk?T@br2o{fp^Js?o=RrgW6JN@c zCIF2(MH?_iU)K2nev0*cfc0RA-Gri2^E_Z%cw2VrCBCn{>?R|$oc1@@?2DZa^jQSQ~xZz_x-uHTlI4rxPJ z8UFS=mX=5=MGsNXDfsRWB)mtf-(Gl~J&SD+L~DNE&Xsq%2u9K2)b295I|{DuN>ijx za?m$n$kpY=xspP5{dx!9NT}P^e#FQXK;p$Cz*jPad4PM!Z|v1UUb#^Ed1eS&(1$c5 z$ly0G#!ZCHTWFH;tXy-tpg9p4vb!+p!zcY=l#%r`r*vv4HO&nUNUoWwG*$lOJwv`z ztl?>Gw%%w`*|9VOyOA^+NN}mfH)rk54OB4Kbda?r=iR&EV+@kftTu4~S{fI9ZDd?o z$j%L0GTV*4{ZU((alT1tY3tFF z7MYTP;sMhRxl1UIz{5~4l<7|(V1$U$x*BaYi01ON=nY*9KhtRelF%?0D#JEjwWRPs zVO%325b^_AIxv31&ED@?033F~NlE*yVsNX^9ertb^?)|piWpkSz-H}-`wKQ8{nNIXN*^m9o{SVn1lcFrm_63(Z6kV|Y+LycM&4LP z)g%*x$naAlD3i*x7$-hI^tltH*e)1d5WY$Bs0#jzf{(XIuxczUr08lTfeI~Qv5?=W z9kQA~TuucBcL@-8U?3aoX88?@7@jo!9~a=Z3fnL%S{~^{D(aXOr5bz&ZI!WPG=4Zd zJqm4fRrN}uJO9FFL)bMDb8%WHU$6qLmNr|;sm($QGM(-?#!Q+d>7rT`Ui46v8rs8K48sAZ+&s zzRzoCiq2~|CDQ+eA~J5%JK61vkMV6pb<}kvbpb1f2zvoxRM1&!|M_NWvii!@U{W}t zlV`@zTXkqJsHTzMyg;y-=t}Vk7cnr{)76I_RI_f-GS!PT8g5y);Ckmx~OKYRQQQZ?i)YNgse{hY# z*peZf_TwOYvAYbcBROPdwhDC{t}I8u&?$>oP%%`jJjOaFB0xDGbB9@DVG{{crv zxCjgGH_#-?M`){DHg1@WDn_CDBhaG4*M%Gs%%uFLrkDL=E~q17tCY`n5}5e*H*T*b z&zBeQBT+XypiFQkl?}9Y^6KxbhSh-|1)jnWw3*D3b0!8rT@Iv|`X`Rg27;dx5xWx8 zdZP{)!2@_ z-@|%FY&ck0m8wA=ed+{vGTcPBu-0iG^8=IlHPh={@Ii#wR(AsC|FrAr3f|3d zR3dHRp0ORihHOETO2&%1FWd`33x4=t3X$6>xE`1U=C#6bH6oZ4S?N+mm&8YSZv_bS zy+$Q3eeyiLW=g>d#$iNl1rz9g+SE;lxwHocXyN@PjI?j!gGxLpu$(2lr&KAdB)_Kt zeLci@iV}y(5{7PT-o-rny6%Q{=qPNk%Vgghw1vS{?x4prDscmzS*+G(J2l7#1{?D0hZl^vnJ zUWTzt=y9%KOLSAu)O}i?-L*&wdqKiXb;(EcDF^2)775(&T@qtX+lZqXkyYy#z(Qpm zf?589E3*)Zq(N9vF;Oki z4ZV38_DGA^F8w5iMl+z;IOh}m!e6224%RVL+SIWo5&=g8;Bgo;qv$FB|JdhWP;l54 zF{rbQ)B}eK&6y|IgdYG6@o{1+z-SJA8k5f|uMjMeb3yd@w;$9j|JFY$KtQlAVlLi)LesC=P_O?{a7#tL#vgT}A5 zR(gAoTDRPcJz?i3yv$x_N2Bu;Xn%%Z&-FG2c?0^W#2$TpwN@ETG>}`{$Suh&;`x? zV7*JraU=gjemshzr=zlx9-y?m&yQ?TYVpGMeHxK%x%D9GR?lTRf(a*L#$(7Ycj-ka zbfN&W$r|Gb2L_Qe)tY@f+fBz(iri`aIfSbAH3jgP&tijXai06h#@vmkT2&LrikJkX z&*nM6NwbSDOT0Z)K0zL+voYKy)N}u0bRqwryBEGSZQOp3Ii@RroAGQV9qrVH+mO{< z1aKpgTyw1m=aGFDhej|Zx`d|5)+9EmHA;mE?;OrG_d4<4dr=_mxGRluQ%<<^GPeuh zx;-ekY;QCU#K0EUM(@PSZM==di=wlFpUeO?m@J^ue&7V&S~FaC{_^N}FnCN%YJ3(- zk>^$XC(#sC)94a^1>KHP+$**EWLEqIUctCVS;pup?sipUMG3LWx ziHih8Lc4FIqhxh_`GT;&&Y!VEQ7Kd2-f!IY$Qw}}@&u&y}Pk@!!j{;`#Mvo7|ksQhZmjvU?oN=wbK-x>z zI+TSiLwgX@@*ied#*bMfrX7sX-on9WttC`efPPEuq7;&$N64qQh#yy^wCumy8D!nK z74N^r`13YtFV`dCwXL@>#;)52+bc7jG)tY$XGmx{?6<2xv(QEuN&J@j>kqS0+VD)| z;C{u-Vj+Sd(vzLv!NLq|UsBQRWjqE0F-D&GK6A&!&cPUY7a8vLKDfpE3Vp1GE1_DS zvH+!Wy*CS8$rMIUdVql5isW=XFzE3piI$vku=g}ltkny;(Fhs2+;w#)^Fn;WTvy_nO zNGld6D-Cpw9<7fyj-rluN_4t(hJSIG}hP5&+2#c;xP5in15 zaXemHhtutt5`G}JHmlQqgn0vN76Wa3O_QMTYuVV)m!D(1coU=6WlUz679vzLsja{C zIVrvmQ%AFN`Rr=2e5z1BN!`_}daQ|bH>NSG>sMCuC%}i~`ew-HxodwaZy?pY=S?~5 ziWTCBA=cj8!Ug2Od01M6_Y#3>6HLcvqc>#;D^~t=#^mIARP3;U6bbFNNZpl>Y^yIr=DNqFUIrBI9Zsp%T&dwk}=O3@TK-z zc69=hmTS%<&&U2T6db@sv+eI8x(hf_fZfFp*2C4*#8}3JDHJ4>*KZO5GRLkkmn2SZ zVXiBKtj!u4V=Ke?%JC~RV~5VKEm&uouEWm$-2+TA%O-f5}C;tSY4ko4-i3 zlmBNUAFoO{unb|l5jALXBMOS;3J@`6KQFg|ob?(OquO%}n{Wm_pRyt($<4$`!c?Zh z6CJudTTx@Z5%G3-?*IKBYK3dTY>bq$;zrTyM)vlzTn!Eh_D_7QPxV#8&6Uw<>su); zQXTb=-)jv|CMly?aMWQ6$hr+8sUN4Zo`17Tp*B4>*4|a2#M>!+=bBzUizEUxshwB? zbDs6te~+Dj+QY6OHCGp6C@;(C_$jzB$OO%m11ca>TB@yHtogu?y8oKlbgbGc8q$u! zNiH+-o1cCRvV{KU@oAd{XBLj&YlIc5bPA-jok*LdRu(~{(8{3HCx%#*q%|uj=OGpp zI;>SSum{3de}A*0^w5JZDR>yoP2e7*KkD4Y-ryJHuSHr!}+PjqnkW`q6`>{Rjs?eLfG{U_F1(LeRI< zm^Lh35An#f8S;M$Hj=u(VBY~}vDM=r&Gz5RC%3{2q@*zU5}o-!KSFtXR0mw^C`$@% zhPH1O?;Cdytuf-r;|25Rj?tqAdTn2p>qom=u5WNs-UZV3mUUo)?1S~wuO9eF^ye~n z6{}h8KAwFZH@tVmN=&}Z;9Fw?=)t~XX6D%umE>DKP+}{;V|OWTiEd>4ReXB9gVLL0 zgK6hH;7V-m+{sD@szF=diA>>A?k+h>(yjx-Yi8Px2#TevFGTsF02{zB`tUXeP0aKp{jDip^|{r z$X!Ii5$yW+kDB?-7{G0@by>_X6U9opVpKFX2SgtvQuzRXeO>RF#nD3xwqHVG*5?){Wazc%Ke09v za+YJl2d>t(_?RB~s$BUurDPy}v>}P=$50fetB{U`EG6zuruGHXV3Ew>YN~8KA{NsQ8Gm+( zI+OhGLDL#$T=dSRM&6X@0e{}04w@U%o>psk#@R4tE{cDW^R#xy{jZh+1SzGdFm!7TFA+XCt%?rIQ0ll#`qreLvA8Jr-a+@J_N0A3;EQ*%Tuo&aQ zMk|%e7HZI1<~4dRHLGafFuFWy_a~I(J-14#rYG_%?ktM3;k6ZHB-*xJU|_nh!7nV~ zqKYN=LM}-$=#Txc10#nAD9bRS)Q1UjC5UeV(~j}$5bL2*NP1YL23}^t|FA9 z+=}dDq4DVhs^rvJK|KK`wQlR#7N1h{awsSGri*!WnZC(BE(k)#^`O}~IZwKl=V^BA zjsG>VbuB2KxS4diDc*%RL;5Id4ja|gT<{ib7;&85crFEvG<^Z>ecq@N2d>u9-!w4u zV>-~LJss6#hCUu@GV%o>CV*2JP7BW#uEA=C`Dbg0Cl2^P3}tMTSUaMbCVi6Jwa+(a z5d~H-;rbBdO#+;8PVDx*e}OUzEIA*_m9evlfy$Z2 z0f)R`Um0v*2jRW$PsLj3r+hhEER}X!EKvn$gmw>NMGxYehXjWW(BDob$lBUEwF^`Y zv3Fzw@lrqOp)UmDe8&MQU;G@hiY_?%`(f$o@9=%5!i%d^5tka1Aaos9d}~X-|Ky;b z&ckMzK9zc61JM@KU45Yq%ea?^5|z)nWGt7sMsA3{#S~b{WxM)uy1dkQhTjPARzTjS zk`$qx%qXJ@VkrWrB9aT80)S>vK`em|hhExhFB=Q^z!|Q)W)^e6?a4J>>*9=pcvqZ$ zXTBi*4|0#1I|v$#E+-xb_5$mJ18WU|Y7j@Fm#)SuZteN(46(rr|>}kSw*Iu;@D3^~aQHE(3z;(Hz(sa>6`NrXmqRnQ{Px3%*(X{;c zsXL@vlldevNu!L3a(n`jSb*^O-&{)i_tFjdlbos z+SrH)DZgT5<^=#4&jBLt4Vjoi?u(-ZWsqI+FnfX~$Qr)>cI)w?_e>nL#F~j#XGO~4 zz_oH8ep@Z7SnxYRq|@JX=Um%-PH?vLMGnwP*$I_iUnwbOCq~7cVT@8+L_4Yj7yEoJ>77M#@MY>B7 zXv)z?>9n4JTS+uy+3Nn-G6bzv_X1Z~G}VqJFRsm!0RNjX{TI1*o~dO2^1o&F<`iwI zQ`H0=WP1a%B&!={Cw_*w-89 zLsx_&o5wkS=gRjko?`EUx)RxY_aOlF6}wmuRs8t0s~p^z8AkF5-pT^se1kNZC;zK{}B29wE3ev85y!1{#4%t(&sY;)DEaP7vcYW^!JLxL{x!(j%vMTKf=OUX zqGE-ikTGIq8u{-vhwai9A{;+?=t-cZz~O&s!SYzuWKXqfsG|qS;#KV2wPT_+S6;a^ zl~eokf{Jd;u3}kj{G9$|LpojrJ3{3OT(xjzt|6Do#V6Ht7(hi|7u(?9l6;>R4ynye zb0jB$tC(Al{TQ!?o>s+avBDK??8naCEwE^lW^5~Ale0Co&eOWy5yBY)k(kfc))i=B zIAT)ghy(p-vg(IU@FcW@940&d!uwx!OF2i%xE2nM=B+nOp!pOzWHwD*DSG(scg+{< ze3ydmLaRFD4JJ4v=f)2WDK+N$pN!<+5R0R0HTN9-mE6{gnOns9>Fwpm(EZ`pxMHWD zPd52Xp)rHo7T%ll`ForVD|41%y*FZ{*^=#5)?>EH1PtI>;C0Y=Xdxm2ZrkA2g=nXB z;~B(~c-3t;ZW`iCzhXF2>e-@ba0sdQJlt_nTj(9!0)&b8pOyxV0%4T1zNmF>eWAhb zjG`^TMa)v}(N?lRNKcg(7eSyQQc?!NASgQtPgmxV8%Ua|eZ?fgl0u?9d@(KV&T{i9 z)7M{6-*|cZu1Hd^sQysH;kIPpd)~DBp?EDM;^HOmjY2kJVYYyd%bsmw>DP&N|HKV) z#HZWBM}8-gnfPacjP9#nc~63W$0ET<-_Qr(D;Wb;&bvT@at6w)0bl?s^&hYHja03f z6&ui#5RJqAsKyVH1>^|dd=aec!U&VRN>b+(e)S1td;l%LZ>@rXoSoTIqg^$!U?uh-0)AWe|4G(P^~dke|G$8tr{D zX!$r6fwmcN4kD3sC&8~)|ZUSDd@LC&A2ncqew9^7Ud zNxOFusU9oB;BFI7gMm=Sm)dI?;SsZCb~|3#ekND-Zr6SdnL-!oY{1JhzIHHiStt>$ zj*jR~tHtQ~6Z+-*#aPgk+O3{FyOxm*lf+nqYae0hAk!?V|oelKFzhm?88~d{uB|p!EDY9l>kvzf-%D zi#vnQ14FB^7km6B1OVA=A#?r%Wo7InO+dbi26GG9ea`vt zzFLf)!n$2&u!;Hv=|DzTW^I+Rp8W5BwsTIr#pr$8(sQ3oxULgi`l<#5cAtIJ$HS05 zbVqFZ+R)_3U#RSc-P7)RI$(F3IW1*K-}@JYjo5v|B4!W6*FY*qeZkPhkG3%BjNj>r zk?#0fO%G7AU=Z%6e^FnFz*8N)Sjd})82puf=IZ=;nGaue;}qH6yPK(S5di4Vy#E%VUdsLQ$(h2shlLKUtr)#K zeYu%)oJZ9v{7C>K3x6MVH>}Fn@rd&7O8*m)g4-yqEx{_z-JC7v)*@k}Cx*~i3g-ex z#OFAXRiCamwJ(4m7hRa=CZ3w!m3|XtW%Fii2XT1s3;r{Z_B#+hMzXr&hOIzBDe8|t zUdbKb+U_CS0}ByFcoxMOybb zt6KgAz4Csk1W{>vM_kAHgk&Lif%TWQ3qgHF?yi@HJ$}WktW>TQk+{$I{LILQrY|24 z*Ry{k#r`3_A1G3cn#%V>9@ML8kdBTV_$fkn(bbt@qOBpHd4FnKZ43j5Scu(-Skx(J zf<3*pEa(~z=6OnUxrzEQ)KxJla$8S2aE~S?#~me?60Hz%AyE~>X$`jx_i^ZhsrwMjL$@qN zJ2dGlaq?}YK@03L%*=B|@#Xr1YqMI@P#sw7NfAIA-CWc8`>1a5f7NZeZ!1?_ z_n+R@2b57>9d8sdWm&VrfVOdZ&m{eBqFM%O> zvV8F#@ZrL8s@%qhkXWHjy`P+}->}3h94n%i?~tR@&|$%Y%KjRyD;l8irxbmF4o#8g zP-D02X+xZqviRE*nJXPhm7xsRiW`Txa{m-Yclbs!r1`gOXDN=g@1i~1jO1%aYMfPj zwnWi$i5mh>4w6L7>X$sZ6Uckarp%+q?%U<3s4a$Cd9#G?VXcSECV{gZ9>hSdk!%3>gywCI z8}D6uj;tJ`2a(gecmITkZgWCsZ0pYPw_pfdea7Oc1#L^kv3>Lk}CDVR;>W(d|R-t6r^&$64+dYm6 zyFJ$YKQ4gh*4{{w{Cir0!EpH+F{oSp@xq}${2;9Vq&HYRfxLM5OTX_N=Ubd&vV!j@ zdolz8(WwW-l_dEBWeKftNs-adqjvy%B_SP32oK4#t z*jgyZb-q_tn&Huco0#)#Skivqx(@pqF`VJUjYX$g{OzRZ(0;+cyDxz;}^2;k}dzN&|8mIZI6AI z4s~Op(p8OBE+osh0Gr!7lK3~@_#q!UAH9vJI8)RvU$DaN)-|pAT;`(mSLTL5udj&) zIu;No!U}88wTQ+F2&<0!IrVFbl*pS!FYl?6L#pW&b^~$1a>`RfZw|6~(utrOF)NhoOIG44` z2O$ST7@ffv5gO)88hqp;T~P8hMU-l38N*%o+DwsUU{}sE`v(k02yCS%H-QB{MrSA2 zmAhmj^k2UgQ?G{o|7H44Ijf%USVRn;s)JbY0@o^h;W{u75NQ@Z6^x#1ejvJG-aX`x z^)HFH_d&-hs#c%d0=n5-wc9+CWn=HMS4J#h0iP<`d)7l5ZC10fSCyffVMsRNw=Rct zWrFn)80z;3ww}zf)gitxeXy8F-8Vjwd%HML2OVJN zc8-6YU2XZg>R5^+$p6~{Igscq%`nOlmvrJV)ArJ1tS4&nTh-6`>L&gLMuzF?{gn}f zi}acp{B(_P?V`7{()raD)WXc=kd1c*yB#mlp1qcSfG`#}jRx76+22=y7q`Ousm9RD za(U6l920fBX6zhFzweGF-QQwIirvk}oygidrVL%mkpsRVCUe50q*V#!-2d0!cYih2 zHQ}BR0R}O`r-p8Y>)7&!dpdqG>19sf@s`)`AU2Uv!g9y6* z$RiWv3#BI;sA^HJky&>AK%csJo$K>3hK}D#=)Qby+^;T?qLz!{5}iFuaTmTH6$O_8 zySADxz9Y)#?Ohcc+VWP{$jL4}mwvfpjs&6k-o8QtURz>(afnap`l-Ok);JR&Y8d{q zZ24jCQi`$c@$>&9QczP&o60clwvf}qyYHIBa!Yv>0P6dpG<|dRrpPW1e;Dk$&b~8u zs@S{xwq@{ElKRTlAi63&S!q}5a;-xeC)%hk+Lg$-FOFFUNCL#jS8C~DiZguZFa7%N*%PPwBvSP8fq6MN0D z5mD9{WAS_vh<195)T`{YPZh^I7bn}_u380ggoC7!pF%QWO?sMjpl?}zy`Jttg7KK^ z#Za)+-YKW?V6W&VCqRB-K@ZgNC_WjQ*5X1dow}Rc5?;Dg=8($v$+~CWwW_Z@K}l*y zYWmg5d_TJe*({t#dC0!LZOZf3q*Y8H=1#xn`PJt7qS~>0vy;J0ICq{Ll`>|h{^|Am zxL`Rx;I1oiy8)dyEm+Ck>Z7X>nXmjYU;`1pd&mvimTUFz>7GOW@ir9RRFSciqN^wb zcwJhyIs@B`?Hgl0Rvg}K9&CKqoulQQtedIIW>_I>ukx!|T(EI8}G8#k2v&((?G2?(WGvO7M^wdVTw*Lmo5keN1#C2XZ7Cc)#FmH zvh+{)1GCj#>KqJQnyA~T%T0BG*K34@L*8jmrCgm)q9)B-9vV`_WUcGH%)-QmPqqaQ zPl7Njxti9$^jV76Y2$qgJWuKiX(nqydKS3p0cI6KBtChq%&KifnC;u^)OR3r&xQbP zk{DBEZZp39h>8-w(JD}^d1yS(f}`+wL$D!RcVP%U?4Mg}#v_r3W&^^}Lq@)TqW}ZKOx3{Y)a^L5=}e;n%aO&` zU3h78Am}k=mFS^F8UDOr!P@=zn?>g*vATlcmYBwW086dHJ;kKG`n)#iskw528yNOc zcW7ekYX5dkSAwHLFxSCWI`e#($0T7PUZ{;ErLrmlxhR+HD2xjqf#*7uc-)kmp+4eW zjsCc-;kY){r(Gxyb`h%!$LAa;n-S%n2%j>j2Ry8*0*rPlHZk;v`6LN?iotT5^K+7$ zlj)utHs5Dxfj^daDm30js^Zm5sq&D{IPSgbO`1`uzXpzLUKaP1AJm=jjL56sgp^JHWhLAa{zq82b1Pj?Tc@RGZw={3+%hTpk=czqN4bQQLvS-X&F@as>2_IPU z@TLc}py-o;aI`3I<3wa@5^S6&eLZJ$xM$^Sc)`f|bk8{UePDm=^v3iP9x=!^;qG#%{+evtv4mlQd7a&|FgMB|x;O3#zX6dTQr`X7oN zYmjl5lq$fm!1lkG=W2ly>3ON$MU@cvhsfM~?XByV^URW!0#7#WmQ86r%%^BSQ-z%A z3eK{(GMlwMv39IrwBl%NOjP;!r*elgc7#B4q)s|y7GqmQ=S28x#0|(@i{gIF)AVw6 zA2hPh3t9y{KbMyx7aGX`fRR>&E7tr<1d9>k{a0yQ*Y=nX49#IJSz;D(DO%r)%2x6A z$JP22JN+0DXmX*x1qxgO{vNWad#;k@*5p1w!|`Xrwe)kjpvFyn`2?K>Bcew3kIA#QKJjxO6*95JzCgeoLjFqk5%q|J~+V$YiO zDK<^$9Nr>Ji8CapGK$X+Z_5b}CgUpk23r_HZf*aJ?JaNvEk8SDj3|PrZV(@E#>h+g z=%x-X%PX)WUEm4b)M#wqN3jle{oegbM{$y;4fkzeSYMe}jVwn`Tgi-{#L(C<8b^{z z^a%a(^I}dktprv+EO;1tz7QL^a<0ojBZd(=5=+nE+(nNPCH6tP5p~!*L|PTB#q;Wu1obnP@CqeOpMQlD}&Ct+EUZ6#Pc>#-emiBg*@)X~3rs zkkl@^XQe%IUa-~A7PRG0v#!a&*-qO)4wAcsC{IXs5-FIPBa>2!ioIw#YW!%nA8lTe zz$ZSKHFcu6IVrOb=K}l#{~IZc%hOG9@8tLmZ#6pi&4fFB450NFsa;eS-H}@>%Tm^* z*x}ve0E>z4*u2xkt_wvD8l4-CLM=Vi3)K4qvf01T%ep@eXyT-J)*z;7`6x_!`*}}5 z6`#0T+;qlo;pLTwxj%0eo;U@@q3BTGP(Py`%+AgPLBpJ``ZKRRzXS@h9rx6kpX(=H z2WN#@vDMzYowoK~*k8<_a`<`mWS0#lrNW-bNLT*B@11Rby?l95_8qpeIg0O}>1Ps* zeLpo{+eM3rRH-KXzC5x8ZT-gger1rS1D#_U^AasxFL;QH!)z3cDfJI=Q|w4{rLS+e zLf(?IyQ2}?80;tp`&Su@04PD1c9(a+{pL?cLmr4^!`W<*uK<0+GA zfcsuy38vHqw!>YM!+A1w9`%fyp23p7a;8X?n7@f@1{6CVu(hc#OXOU^Fv2S=aI+tM zG5=4&` zsW~aWcI14$wNd)Dfdgh~up@_ikxJ~i6vDji?D+HX$`H?%3ekD__#z0qw)-xX_#2i_ zN<+H2HnlbN6qLE~-C&DE+O6J$N|bY6>U(lpI~QzQ34{e%qHiCO7n z2~pWzkL^v#7Di{E%0TdZ9j|Wntn8$t)Jy$l636-{dRB~Ly(}d{jwl@+$SSt>w{;ft z{_bO{9Y9i>=_FWtqEvZd3V*KlNO%9V?6^!IDR4Z)vX~?1kC+mTb#A)0VPzwtzW_Qr zb~jIoPnPdWbtK;j7fMVrH|GcO2^rleIK%L|vXr>wFY>^ojWn_0efai5xmCZHzy2h_MOx*B;7|eXebDnZNU#1RW&>KFxax05g9ZqF$_;atb6d{CRaL0w+y1Ckr}WU%moM`LR79a6L@~a|c zM^szPkzMgRT#>9szpC%QTljIn?Hg`?#|1AS+K)1%6|B%yeDk^X*Os|c_NO8Az>Bfd zYy%pcT=TiXc!u8W=(}0UL7L=6R@yX(&WJJUtgre*lh8nIzM21FByGD$Q_ocP{^p8CVJt^;?D1PucFx)z3=MhPbn~;R#_=;Hk!cCeRygV zuBQ)bdTXD`=PKB{hOY>Rl;!5sS4n=YO!l1WBo2-4M~4B#l0c0UGNbKX?h%FD4K44N zKbqFm1ceQ`l@E>2NJ7HCPM)6k1*jzX5B}D`MWvuDE>w^zJpp9s(Zgp%7IG9YX6;2v zaeJK~K`helQ#STU($^i|1EC6%;>9#|g`}`vW#pF)*_qVB(aSX!wE3@7%@TaWYV>c^x!E z0@y&(Nve^GcyF*+cl;h@!Qy?-;jSi#N=3M&@##g|&ggoAxE%?o^}c>T+IW$y*0Nzc zO2y2Fq>l}GNiG|gB|s1L6jyGTn%oaG9AQdP)^FMLYq2dJg9l&+ru#8+zeX`6-MLYQ zzjRb5B6}_i%-(Hrmq|6N?~aU2B$P$yGR*xxc^;#|JXF zX7IJr^jfamGP!QD{8Lr`S5!{OoE=I+%vs&z00=@VuCO^hw0_n_EBsUNM^G?N?9n@y zYLG-5&#>uT8hI`vTdjGP8(B8blwHHMP2!YKZ0I4Ztfa6FEnqpySgi%~IV*((u?gtQ zFH@2Y#`g-cDzbbjYQabZ*HYMMRFeNpLvLX$wf7~4#L3{gY0ncKzpJO(PEu{UOwbEc zy;R^73A=b(X+!Rats`#k@<6FTdPq2Ljg;6|hjjGaS%#3?Mpw=jdOF_-*=mG3d@tKn z4-YW83E02*^f9FvjF0CKTm4lsK3~3Agsw_NxeQeJryTouD z9t9aB_1)UtpES7@x9x+qa8tSK3OGW!-$lF>P)9~mZrrI$-OX1klq_z3B5;yEa%!3d zPd5J#e&5>WxUv#xjBY9-X1BoS)98t+1oG`emfnI7Rir`O=GP|mWbp!v_^wrN^@hpB zp0J2DIi|_mjOef>3mUaQ1)H}g$&}S?wY$EC-kL03ZIWJP=3T0JmGLKkbji!L?b*5e zArzcbk$tj*Bt)sz``SnrO|H8JIEfD1(GJb99;xkjC&EATnj>YNS)N~HJsc*aDH!%8 zxS{y?rvbm|DA|lf4Y@ihfASTIa=vSQo}p7XbxHQ!(B#7wgHi-5Nj{JGT3hP3*A8!K z9L>N&O=bt`UB9aE4!Fhl6_`p+7#MZRcP{AM&NLfU5bTlR%bP@SP5cw8`LR|7%oXeI z1UjAC#}v*O^N~!$`9E*ofy@ zpWpn$0Stm3Wa-UQB&DRhbEJeeTYvE5$gE2Q2^nYYbN1U#$%&Z7i$qz7|(P+NnY0u#X9_8@%^OWkF1i^byT=HCOLVvY>ZAL@Kl;&LaPLE@0kK(+gVS z;Q95=KSxZV_~E=upc3(pf0^u}R4Wb+-*eQeD&ORBC-oOfTy1QUW<&6qv%mo!?!`ldB3^&-xxW|gPxA+2TkZ?mj9 z3kgBDZv>v%Pp*>029HdoNsUgxS3|4cg)G$5t>zZY6sN*o!#y!$tp1p=7O64ZH6}Us z1R+WVN49xXXGJO*g}BiNU^=k7+8psL(oi;o4K*KQ-GiU95)%a5od;%CWE%tbH~XjU zn>3PAT7=>N#vS&8_Y0ZyqFJOyVrNhd*gJ=@+f}~nB<{c=$Pd;f(0_M*w)!zp@bO3lW8(B_e?i2-~|?g0Kc za)mx7emXLT1@neRQU^#FwLh>O|AyD9uVt1j^@wwTm7jCCZ3{Uk9{_Wjmx|@xP^{+4 zbEcoa>R}MO8)gTeG|C4gSeT8X49W6T$2O)MCzj$czU=v~XV0P>E{DgPiJXvSay6Q; zgWo4Ih#)#7LjV*KEdt5r%aKqIw~VM> ztX0)t6uq}USJYj>>Fa1*jxwYK_u0D*(72%uAl($jH&kos7onKEPsk97Wspr&xywf6 zLN=sv>%wTvw7_XWe>2lg-FhCU^gYtrk5R(gUQVv(lUPkGo`o&_Z-d;9LdL_c_c?!- z2)k9iQSblmcmzv%-I6~~Y-YOAMDA33A92;gi4yA_#clrj7IZ>5WDsP7+d6$sOdGE1 zIN`#Gj61Wq75U@zGV^-RR>7X}M}kJp-W*ONKWiUb{+y#cGJr0f2qz})x02c0c(!#Q zx*V)nr_!aMkqIR(8k>{Ctlr(V3EbXKApqEtJOFI7;#@T-T!;7S$Z1bou2tWs3Wyd> zWG5xS6O{!$Bqe&3f87g9RY-#j6`c$AP@?N+&OO{I9`uHJ+%mai+?uPKceufx@KcTb zr*`PLSW9$>A$u`H4@m~ERKZm+<(GQstmBorH<-F&XZ2y7L;WPOq8xMXV$Ax>TI!r? zT5MQ!aWR$1>tVWLv&{0pY5`n@_YZ~s9-6IHR*o?;?S*V;;MASjdzsLcFc#uip|73hhusT$w&@KH;NMKK} zlCtX?CDT~=^3qM|Ah=+3aR16s9mDorb0iHDE#!dPqtA~li2vYSu=p_}jIIi5wR`TP zoVZy>S#IdUM3cWBGu(yy^*UgPbIy<~;+D@<#kldA4iTP4DzkC75DDC+Mdf=zK4}W* zfe#UAdD^!EZJu2Pz0Rk!Qujaqh<2G}gw15OMqCe(tVIgHGxM=h0p{eNPbL<2X5Av0 z+7!bkASm^1)hl|4^}p8bbf=YDnF|aL)AictB&U<6_-zY^_PUuJik~h;2h%J1&S&)+ z_tZrPFh@ckG7o!oW}A(sKCwet&_pi|O2;y2u;BTyrSwA-r@`j=l1*Q^anz*oVM;sf z6Xnkb#c?`LUf(!vXi|TLbyQbyu32sv5P_{0Dg$i?Rr*^UZp%c6groMzZB#&{I{mx# z$Zy;$gz)9{eG1O@^o;PsvaBfnopX6_YyeX&Y2s?#4$7I4WCn(R<{FWHpFe#qeb4^> zj}*(R^O*4`Jjq+vxM>=go;Fz9Ort%*W6rZ8l=USs3k0s!jLo`q2TwP-O>Pv%NH=)3A2ptqkom{c7eQM~>>kS(k?#i>Ew@ zK2ugGu#34e$Oz8%HKB4>b17ugFVlF-EPB;{lj}i#SR}J=14{!|V4I8fAG1me^7-NY zW%)EBXbhs^lkS@h^Oy_9?=(nT8`vHmhK6r)7x4MQI^aFj{GHW@BC_%1 zB$I(kk;>ZxBrDaN@Ln0%3?$Zj$ofkbGt1kYQ@vQTHhj|^<$=(i!(A1+!Q<|}B|pKP z&;ZPQG(VWiVo2PYOMBhKTMF@^0#rBF!Kz4)P(fwwS^eOdI7>u^Rz6@qy2r`OXO(`` zri2=Qa{p%N(@GLMIR_mcs~j=%dg%4d!2jTGbJqEXwdFX?PjDNV%|n2y@YFf?;iQV zwmNs+JN=hANOadrZnc`;m){6reMj8Q@9D=eSN1rLt5U9^TKSlotaR|a^h-ptg9T=JD79ZfvmfGOT+R3qV_>>k=`P7HWQRs=+?nYaFCx#j|TOu0%@7lioeCV`3-iF@v zHz4pKDz5^n^h?Lv=%HF^qtxb^A}}YN{q5cn?;YbhH^VbSUWyThKouvc1_Qxy?0OX& zp*d;AXLPC7sID(-q+DQTQcrQ{1J+O{|4fuL(tL6Mp+D7j87zM(GsRCcSYa5sEY^en znqx(r;384hhBUpD)k2J z72e7;Ro1i2lGyo8odTS@?)K%rh=UtyEfH&@TQ{(g3`&z;=xI`N^S$sS-u?P(wZ-^U z()i7}Q<-c1=*UtcWqZP0WjvW2(~)yR?+`rJ8~K(sV<0t4n=W~LEAQ(HUFpl@-<=xg zm>*qr{TS)=dG_w(Y99FIC(}80dKI>Iinxpxjd%ESs}ASSR69+9;>7q(39Xg)c`X}WdyZaC6 z$!WUq93@AO_z)+=-va{!-WnBT*VZChQ5moIt&tq*r?jV2LB*C_`Rka}Jo}Cm{8d{6 z`tO2i?`8h4ZJ7K`d8N+AoIe2(stMH%<9g8v-@6#*S1{*a&&}txm57c`)qb#G znxEo>_}zUvR1@{1_-ssmVl+zXXR_swa;L@l9apF2CIhCs;az8qJ$<2ebA~OgA|0_4 zY8#mZ`ptQvhK$RWInuwHV`u{dj7Lx6u8-ZJ;Z}HafBVfUH_D7rF_LV%fuuLJHb)@* zc$p>7CW-grO;q*KhLF7OHI7&PXtO<;;k*N9R@$X-A*1W7(G@2&TZLy1suh+uuWu`Y z{d;vwe^+T#JCOeYlyD8#_q;c0jZdTL`8|6BiONeRO0iDDFJgwn2 z3@?xgJ^Xc!=;% zows(H{@$LpU~+t}b4+B|K772ABC;X#rB>tj5T_g&z;58(Rl3`GPw+v0z`d8%Tp*D0 z1DsOJx&`ycw_U>|5@y`dSEg_4p%IHC&j;}b@;GO^gc}AfbcKC#G0e~UW!9vS}$%Y;w;(kMXNkkbH2^)mX7zY;Q0ol;>SDnjF&ljV|;%(5kSUc8K zz<|U$yA2SarY<{bE@HUirfM3EAD{Lb+a;Fcj(>(C4+xdN0(>+o*zMIf91JRdieaRA ztB&PyoMqW(4wT^HMM4xhoH9J}<^A*nbtm!h{!I<|%+goCzto9hH8+fOz?Emj``@sA-cV9Ia&Qh++9)HKya4Cf7j_2Mh)C;&b*&`vzVtSRnin6aHO@}=zQP!(ykN0E|C)rZ}r*JCS>2x^mgu!TPM~^|d_^+|q zRa7vYlvezWM;fC`ftcQ*3dNOmyM(Cp%Op9P)8}7=qdVw&IT6N&x!kBH(=`oNiHr~M zd~i0O@;${b`6zeVLuwml^U;v-Z(;g`-A?;HnjOa z-R9$dmx9O!ks({6iQ1g6C3d>Nn(T3(mnVYdaDqeWAGy?Oc{uTg=3_vHS8;w*m>B%% z!&2A{nZA~{vJJQgD^Netkc|cGDJA>q&f{K0lH{1RzCl=n+KHXI=cl>G9~HgMqZ87G z`ym{O6U5NP-#cEy#0b(O&TR@uJsc}vev~y7Le1CdU}ktG%2O7ta*dx*_8D5@_jg__ z=8HgRWPUZ12<=HQZc>R#5XP<-Ku74uUsMe)G+4&A7Z4QG^XR ztdoGbv-q zDwYR>Q5&Zta?sKd?SC??{Ud|BgzK^(1Y51&ZGZLaMo-WC7hqil>PcohCt{R9T9NM` zUR*Qpsv&)M4X@p$Iz$(32+ck`nigNgzYbgMVBNlFp05);duMFs$Tt5$d)gQOwZKiv z=#G;d1*RkMVWr~yx<4KJ21$jbVpk!kd0^&yn3KN+&e*ZMHok-4bxr(U1SinYwF<8)!Mxg-3notllr{qDo-PU>|1>*q;!(Q1ZHhaM z=#)Zs_uBoz7pxRyngMku~S3DL4zn< zTxgK_VHGcePLvP04ZT_RNKufHX85cd&H5(tH|%u99=j$(xl}LhaSEnc)#B#&j;8-B zAr(+j^)ecTL~&G}%?l0Clu!27xb^*&jQ~RQo>Z%p@oD@_W9{9xUZ;&x@wpl)%J1oQ z7J(H@he`20U!5HBQ&>D~)SMLO_m$O5{$ z?XgZif!dLOTI`rSV}1`10#_U56U8*X7j1%!6aR@EQxMP*eswCDkohPMl|CBvmwKlo zglu@fAf2J-7g4I4Oc;>_f5Hsx>mmCiIG#{48O#iMO;`0&p`5Y?E;pwR!?RTQ;Tk@t zb404C)>X9^e;#2iyut}_Xo{WWUvRQ6{#j@U#V{j{(@5kEBhskvjE{f(uJfdh;(v<^ z!rj3gdUU7qB7EF{*Y>P*!or$|nRB|cC=oXQf%^0IqRmh$pzsGn2>)(y!;Q8X#F@f!3CcnIU|qG!8G@`WKmgvZ--7kP2@%BE;6D*Z)jU5 zmL^|UJWenAmX3a$-Ue8h?&YvTiie}}iHRwGHj}lCwbl`GMlb5G3gg}BPCNYkLOJ^o?LYVUMoBBj%3G8r%!b${%<9izAaP5(naf?hHoZfKWG?kH)x0F z#xwM|G>YUx`dU#_boM=sSZXgez0@s37gq17JynX<eg3{(0* zy5TH+<7SrTSWn~q(__A2n4_1I@EwNL1us}RUWKglnzzY^fHHX*fOsW5W;m*8?I5hc z@lA3RBFQwfV0Be@*LTF6eja+W)Z^v|?~g12T$9Ax>ON7Pk>Z%uOC)6jmowBakp%Ht zS0Y2Tu#zn-A@cqX1xPQ}^VGjHLcEBi6LH{fhYxB6&K3nVs?qNQ_gvxXnKv-YMDWu# zNX3fNyh_hDCnWPC`kvbWWry}7)BZQUx|naKmDOBL6pE6o#dpOX7B2UsWvT1tIrL7T z3^=iskhe4RA+*~mR>VB4OXDGUH;XWscbkr$sZWGwwA4`L!6-ICB;+}5Q* zUig-u+g{n$D&S2M9GsV-*3=4 ziZl8t7yYFq@HqnDbL!|kWOgh7_X~-9f;i#+^W4*)&6IYc1jUT1lcP~?-j~AD76l2^ zB+7R4{-D0#=@8T!TVlxBhlUq-JkxJP=hM&;`9TxzM=KGs#q%&xGEm4;gJ_M~qTCE* zsO;WNuqnE4fU1V~06SwONVvOE`!A4qNcJB+S9!VX0Tl=}W{r9T2TGmnBLXzo_OKRw1%g z;SSmm%a1!ukohW)o5m)2hWck+`qt6|oO+nDt!${@+XyI zUa;*N#U(}ZBd(fzq(h*)NdMlwkYYmqO79@oiIXe_2D202U^_lxy zqhPIPIG){Mh9-o3*m(0wk8W6O3pNgQ9vzc#`?GHo2?t3$l+paC9SIt4JTJ*JQQl3Z zrgS9g393UoJP+}ZZ2MPFK-xWi0921u;p~gKXKogzZlHloLM)_Yq;AZLSl(+$ZXOy5CiU;N8 z$^4QRF>)!pPy`4-6$9yX<=MzEsQ>)ar6IDa3Q(m@xfJY&izK}jdS{(PM%kBZaAF+l zZS*(PdB)&ZqPLmPRm-mTu>Hf-$Gzu?CFggGU3>7m!IW%mY$2jBZ_w+F(-9QFKeM@( zg5D#c8Yclp!N%dKW-Q~38lMed-H$C3_}~PNf;6Z(99xUwsJHG4tXE#QF7E3k@grCmqhb z$MymJW6=KC5PTw^z7rW>D)T|m8Hy9R(kuF@gP5fsbNAaXq8s-oBBW=|o1a)NoCWiz zt95<5m2w*Yt_P1*LcNS8uRfE>|3bxl_{#x&3{Tb=6)IoyX!-n5Xl9g0B|(ompD)T zCe<;BR3yL)lzuW|PapghMI`Yy=<1STbFtZLEMI8)F?&<_uv6pg8nI!D$`Z{Up%Tf` zYy4$ZLmUrhIWQAm`8|j((8$NE1tBN~4eD*%8*0{Sl5x2nBj=E*=%cnM%Y8?Z&#YM3)gEo;=XiNpr2MBn~ zmpj+4wG_oAM}UHPd_-Equy93+5VemxQJ0jBM=ilic@aXN0IYuu#EYLTO7a_n5I6{e zVJ1Hmc;W+9lvz0PiZ&dRWW2aANml~6J@uwABH@5MZCrxBv_|tv@2zSd`ipbcp8(Y; z1waALM%2UUNxjt6eL(l=2@q8hzblT?X$k~& zn?v^Y!jZy*eU)IZVFjSZsb}TJe)xreYhMA?DY_}%g(Hb*he^q_S^dAtC-%wv^Sn7- zHP3hXE|dWFNe#Qd>c^da)VU{%UVP{D9-wP|`K+RMX-87745{ zYUto-x)qy%swB_pqMBlCZvUT+7pDNKHX^)bwfQECvtcBYkaZ?Sg0v&0qZ($itgrAK z{3_T;dC8!B{q-t6xZZ9;W-A)(#iQ{$tHw;0RtxB>v-&vp6@c7k#2qzQH)%WCG^kt&le zRjFp^ImDk7k#k=tPcEy78wJ*55n%Kn+hQ}^O(r5Hs(tdnhwyq(O^`6kD4}C->M2G- zYE?SW+0k^gAm6))K`)w-B=dr}OMw@J^Xweipz;|N5ANf@0@3PzFzEo23^4KWAty64 zvkhWFk}ac@0XqYx^7d|`Dx-HXLVM@oyVrEnutbA6~?sz_VQ54G`eMqCU z(m$0_vPGnFBvkbJktmb1f$MW7U8kpiU%Wt)=fo92=i*19pfu7BxM&q&%t7|wAAKlr zBJSd(xFewYpNpuj0~c1yD+vAfl7IE`uQ7m5@voEo|Ah=T^u7H6K!pdl^D+Gw0{(@7 z|6d^BtSe|k6#)NKUv=$sGHHR+R{%f;mb-w?aQWhRo#x_roAcu6sCse4qArdo2;|}) z^xqpU)bOvCR4>%(FrameworkSetting.WindowedSize); From a0d64c1b13f779488dbfb4a7d952b0e07bbfbfa8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Nov 2018 01:20:32 +0900 Subject: [PATCH 0231/5608] Add ability to select current match --- osu.Game.Tournament.Tests/LadderTestCase.cs | 1 - .../Ladder/Components => }/LadderInfo.cs | 8 ++++- .../Ladder/Components/DrawableMatchPairing.cs | 25 ++++++++++++++- .../Ladder/Components/DrawableMatchTeam.cs | 9 +++++- .../Screens/Ladder/Components/MatchPairing.cs | 5 +++ .../Screens/Ladder/LadderManager.cs | 13 ++++++++ .../Screens/TeamIntro/TeamIntroScreen.cs | 32 ++++++++++++------- .../Screens/TournamentSceneManager.cs | 1 - osu.Game.Tournament/TournamentGame.cs | 9 +++++- osu.Game.Tournament/TournamentGameBase.cs | 9 ++---- 10 files changed, 88 insertions(+), 24 deletions(-) rename osu.Game.Tournament/{Screens/Ladder/Components => }/LadderInfo.cs (70%) diff --git a/osu.Game.Tournament.Tests/LadderTestCase.cs b/osu.Game.Tournament.Tests/LadderTestCase.cs index b296956d42..acc96930ee 100644 --- a/osu.Game.Tournament.Tests/LadderTestCase.cs +++ b/osu.Game.Tournament.Tests/LadderTestCase.cs @@ -3,7 +3,6 @@ using osu.Framework.Allocation; using osu.Game.Tests.Visual; -using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Tests { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs b/osu.Game.Tournament/LadderInfo.cs similarity index 70% rename from osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs rename to osu.Game.Tournament/LadderInfo.cs index 567cdb0daa..c433987491 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderInfo.cs +++ b/osu.Game.Tournament/LadderInfo.cs @@ -2,9 +2,12 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using Newtonsoft.Json; +using osu.Framework.Configuration; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Ladder.Components; -namespace osu.Game.Tournament.Screens.Ladder.Components +namespace osu.Game.Tournament { public class LadderInfo { @@ -12,5 +15,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public List Progressions = new List(); public List Groupings = new List(); public List Teams = new List(); + + [JsonIgnore] + public Bindable CurrentMatch = new Bindable(); } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 81b3223ea7..5d0837c542 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -20,6 +20,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly MatchPairing Pairing; private readonly FillFlowContainer flow; private readonly Drawable selectionBox; + private readonly Drawable currentMatchSelectionBox; private Bindable globalSelection; [Resolved(CanBeNull = true)] @@ -49,6 +50,18 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Colour = Color4.YellowGreen, Child = new Box { RelativeSizeAxes = Axes.Both } }, + currentMatchSelectionBox = new Container + { + CornerRadius = 5, + Masking = true, + Scale = new Vector2(1.05f), + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Alpha = 0, + Colour = Color4.OrangeRed, + Child = new Box { RelativeSizeAxes = Axes.Both } + }, flow = new FillFlowContainer { AutoSizeAxes = Axes.Both, @@ -65,10 +78,19 @@ namespace osu.Game.Tournament.Screens.Ladder.Components pairing.Progression.BindValueChanged(_ => updateProgression()); pairing.LosersProgression.BindValueChanged(_ => updateProgression()); pairing.Losers.BindValueChanged(_ => updateTeams()); + pairing.Current.BindValueChanged(_ => updateCurrentMatch(), true); updateTeams(); } + private void updateCurrentMatch() + { + if (Pairing.Current.Value) + currentMatchSelectionBox.Show(); + else + currentMatchSelectionBox.Hide(); + } + private bool selected; public bool Selected @@ -144,7 +166,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components var instaWinAmount = Pairing.Grouping.Value.BestOf / 2; - Pairing.Completed.Value = Pairing.Grouping.Value.BestOf > 0 && (Pairing.Team1Score + Pairing.Team2Score >= Pairing.Grouping.Value.BestOf || Pairing.Team1Score > instaWinAmount || Pairing.Team2Score > instaWinAmount); + Pairing.Completed.Value = Pairing.Grouping.Value.BestOf > 0 + && (Pairing.Team1Score + Pairing.Team2Score >= Pairing.Grouping.Value.BestOf || Pairing.Team1Score > instaWinAmount || Pairing.Team2Score > instaWinAmount); } protected override void LoadComplete() diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 70ddb6b664..804680ba28 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -126,10 +126,16 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } //TODO: use OnClick instead once we have per-button clicks. - protected override bool OnMouseUp(MouseUpEvent e) + protected override bool OnClick(ClickEvent e) { if (Team == null || editorInfo.EditingEnabled) return false; + if (!pairing.Current.Value) + { + manager.SetCurrent(pairing); + return true; + } + if (e.Button == MouseButton.Left) { if (score.Value == null) @@ -176,6 +182,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components return new MenuItem[] { + new OsuMenuItem("Set as current", MenuItemType.Standard, () => manager.SetCurrent(pairing)), new OsuMenuItem("Join with", MenuItemType.Standard, () => manager.RequestJoin(pairing, false)), new OsuMenuItem("Join with (loser)", MenuItemType.Standard, () => manager.RequestJoin(pairing, true)), new OsuMenuItem("Remove", MenuItemType.Destructive, () => manager.Remove(pairing)), diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index 5dc2009c4d..aa0c3229c9 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -43,6 +43,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [JsonIgnore] public readonly Bindable LosersProgression = new Bindable(); + /// + /// Should not be set directly. Use LadderInfo.CurrentMatch.Value = this instead. + /// + public readonly Bindable Current = new Bindable(); + public readonly Bindable Date = new Bindable(); public Point Position; diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 2ad296dd77..f348eff571 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -23,6 +23,7 @@ using SixLabors.Primitives; namespace osu.Game.Tournament.Screens.Ladder { + [Cached] public class LadderManager : CompositeDrawable, IHasContextMenu { public readonly List Teams; @@ -30,6 +31,8 @@ namespace osu.Game.Tournament.Screens.Ladder private readonly Container paths; private readonly Container headings; + private readonly LadderInfo info; + private readonly ScrollableContainer scrollContent; [Cached] @@ -37,6 +40,7 @@ namespace osu.Game.Tournament.Screens.Ladder public LadderManager(LadderInfo info) { + this.info = info; editorInfo.Teams = Teams = info.Teams; editorInfo.Groupings = info.Groupings; @@ -255,5 +259,14 @@ namespace osu.Game.Tournament.Screens.Ladder } public void Remove(MatchPairing pairing) => pairingsContainer.FirstOrDefault(p => p.Pairing == pairing)?.Remove(); + + public void SetCurrent(MatchPairing pairing) + { + if (info.CurrentMatch.Value != null) + info.CurrentMatch.Value.Current.Value = false; + + info.CurrentMatch.Value = pairing; + info.CurrentMatch.Value.Current.Value = true; + } } } diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 522af5f6c9..d515312dd0 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Video; @@ -20,33 +19,42 @@ namespace osu.Game.Tournament.Screens.TeamIntro { public class TeamIntroScreen : OsuScreen { - private VideoSprite background; + private Container mainContainer; [Resolved] - private Bindable currentMatch { get; set; } + private LadderInfo ladderInfo { get; set; } [BackgroundDependencyLoader] private void load(Storage storage) { RelativeSizeAxes = Axes.Both; - background = new VideoSprite(storage.GetStream(@"BG Team - Both OWC.m4v")) + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Loop = true, + new VideoSprite(storage.GetStream(@"BG Team - Both OWC.m4v")) + { + RelativeSizeAxes = Axes.Both, + Loop = true, + }, + mainContainer = new Container + { + RelativeSizeAxes = Axes.Both, + } }; - currentMatch.BindValueChanged(matchChanged, true); + ladderInfo.CurrentMatch.BindValueChanged(matchChanged, true); } private void matchChanged(MatchPairing pairing) { if (pairing == null) - return; - - InternalChildren = new Drawable[] { - background, + mainContainer.Clear(); + return; + } + + mainContainer.Children = new Drawable[] + { new TeamWithPlayers(pairing.Team1, true) { RelativeSizeAxes = Axes.Both, @@ -148,6 +156,8 @@ namespace osu.Game.Tournament.Screens.TeamIntro AutoSizeAxes = Axes.Both, Spacing = new Vector2(0, 5), Padding = new MarginPadding(20), + + Anchor = !left ? Anchor.CentreRight : Anchor.CentreLeft, Origin = !left ? Anchor.CentreRight : Anchor.CentreLeft, RelativePositionAxes = Axes.Both, diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index 303e15aa8d..91d389b63d 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -13,7 +13,6 @@ using osu.Game.Screens; using osu.Game.Tournament.Screens.Drawings; using osu.Game.Tournament.Screens.Gameplay; using osu.Game.Tournament.Screens.Ladder; -using osu.Game.Tournament.Screens.Ladder.Components; using osu.Game.Tournament.Screens.MapPool; using osu.Game.Tournament.Screens.Showcase; using osu.Game.Tournament.Screens.TeamIntro; diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index b4bdf250b6..f970700fc5 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Graphics; +using osu.Game.Graphics.Cursor; using osu.Game.Tournament.Screens; namespace osu.Game.Tournament @@ -10,7 +12,12 @@ namespace osu.Game.Tournament protected override void LoadComplete() { base.LoadComplete(); - Add(new TournamentSceneManager()); + + Add(new OsuContextMenuContainer + { + RelativeSizeAxes = Axes.Both, + Child = new TournamentSceneManager() + }); MenuCursorContainer.Cursor.Alpha = 0; } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 6eb1feaf6d..2ae6c60067 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -15,7 +15,6 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests; using osu.Game.Rulesets; -using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament { @@ -31,9 +30,6 @@ namespace osu.Game.Tournament [Cached] private readonly Bindable ruleset = new Bindable(); - [Cached] - private readonly Bindable currentMatch = new Bindable(); - private Bindable windowSize; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -95,6 +91,8 @@ namespace osu.Game.Tournament foreach (var id in group.Pairings) Ladder.Pairings.Single(p => p.ID == id).Grouping.Value = group; + Ladder.CurrentMatch.Value = Ladder.Pairings.FirstOrDefault(p => p.Current.Value); + foreach (var g in Ladder.Groupings) foreach (var b in g.Beatmaps) if (b.BeatmapInfo == null) @@ -106,9 +104,6 @@ namespace osu.Game.Tournament addedInfo = true; } - //todo: temp - currentMatch.Value = Ladder.Pairings.FirstOrDefault(); - if (addedInfo) SaveChanges(); From 878b16c596a30e0cd9272cd44a68f75815142750 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Nov 2018 02:50:44 +0900 Subject: [PATCH 0232/5608] Add automatic country/user information lookups --- .../Components/TournamentTeam.cs | 2 +- osu.Game.Tournament/Resources/countries.json | 1252 +++++++++++++++++ osu.Game.Tournament/TournamentGameBase.cs | 35 +- 3 files changed, 1287 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tournament/Resources/countries.json diff --git a/osu.Game.Tournament/Components/TournamentTeam.cs b/osu.Game.Tournament/Components/TournamentTeam.cs index 78e1386706..62dc703fee 100644 --- a/osu.Game.Tournament/Components/TournamentTeam.cs +++ b/osu.Game.Tournament/Components/TournamentTeam.cs @@ -39,7 +39,7 @@ namespace osu.Game.Tournament.Components } [JsonProperty] - public List Players { get; set; } + public List Players { get; set; } = new List(); public override string ToString() => FullName ?? Acronym; } diff --git a/osu.Game.Tournament/Resources/countries.json b/osu.Game.Tournament/Resources/countries.json new file mode 100644 index 0000000000..ec2ca2bf37 --- /dev/null +++ b/osu.Game.Tournament/Resources/countries.json @@ -0,0 +1,1252 @@ +[ + { + "FlagName": "BD", + "FullName": "Bangladesh", + "Acronym": "BGD" + }, + { + "FlagName": "BE", + "FullName": "Belgium", + "Acronym": "BEL" + }, + { + "FlagName": "BF", + "FullName": "Burkina Faso", + "Acronym": "BFA" + }, + { + "FlagName": "BG", + "FullName": "Bulgaria", + "Acronym": "BGR" + }, + { + "FlagName": "BA", + "FullName": "Bosnia and Herzegovina", + "Acronym": "BIH" + }, + { + "FlagName": "BB", + "FullName": "Barbados", + "Acronym": "BRB" + }, + { + "FlagName": "WF", + "FullName": "Wallis and Futuna", + "Acronym": "WLF" + }, + { + "FlagName": "BL", + "FullName": "Saint Barthelemy", + "Acronym": "BLM" + }, + { + "FlagName": "BM", + "FullName": "Bermuda", + "Acronym": "BMU" + }, + { + "FlagName": "BN", + "FullName": "Brunei", + "Acronym": "BRN" + }, + { + "FlagName": "BO", + "FullName": "Bolivia", + "Acronym": "BOL" + }, + { + "FlagName": "BH", + "FullName": "Bahrain", + "Acronym": "BHR" + }, + { + "FlagName": "BI", + "FullName": "Burundi", + "Acronym": "BDI" + }, + { + "FlagName": "BJ", + "FullName": "Benin", + "Acronym": "BEN" + }, + { + "FlagName": "BT", + "FullName": "Bhutan", + "Acronym": "BTN" + }, + { + "FlagName": "JM", + "FullName": "Jamaica", + "Acronym": "JAM" + }, + { + "FlagName": "BV", + "FullName": "Bouvet Island", + "Acronym": "BVT" + }, + { + "FlagName": "BW", + "FullName": "Botswana", + "Acronym": "BWA" + }, + { + "FlagName": "WS", + "FullName": "Samoa", + "Acronym": "WSM" + }, + { + "FlagName": "BQ", + "FullName": "Bonaire, Saint Eustatius and Saba", + "Acronym": "BES" + }, + { + "FlagName": "BR", + "FullName": "Brazil", + "Acronym": "BRA" + }, + { + "FlagName": "BS", + "FullName": "Bahamas", + "Acronym": "BHS" + }, + { + "FlagName": "JE", + "FullName": "Jersey", + "Acronym": "JEY" + }, + { + "FlagName": "BY", + "FullName": "Belarus", + "Acronym": "BLR" + }, + { + "FlagName": "BZ", + "FullName": "Belize", + "Acronym": "BLZ" + }, + { + "FlagName": "RU", + "FullName": "Russia", + "Acronym": "RUS" + }, + { + "FlagName": "RW", + "FullName": "Rwanda", + "Acronym": "RWA" + }, + { + "FlagName": "RS", + "FullName": "Serbia", + "Acronym": "SRB" + }, + { + "FlagName": "TL", + "FullName": "East Timor", + "Acronym": "TLS" + }, + { + "FlagName": "RE", + "FullName": "Reunion", + "Acronym": "REU" + }, + { + "FlagName": "TM", + "FullName": "Turkmenistan", + "Acronym": "TKM" + }, + { + "FlagName": "TJ", + "FullName": "Tajikistan", + "Acronym": "TJK" + }, + { + "FlagName": "RO", + "FullName": "Romania", + "Acronym": "ROU" + }, + { + "FlagName": "TK", + "FullName": "Tokelau", + "Acronym": "TKL" + }, + { + "FlagName": "GW", + "FullName": "Guinea-Bissau", + "Acronym": "GNB" + }, + { + "FlagName": "GU", + "FullName": "Guam", + "Acronym": "GUM" + }, + { + "FlagName": "GT", + "FullName": "Guatemala", + "Acronym": "GTM" + }, + { + "FlagName": "GS", + "FullName": "South Georgia and the South Sandwich Islands", + "Acronym": "SGS" + }, + { + "FlagName": "GR", + "FullName": "Greece", + "Acronym": "GRC" + }, + { + "FlagName": "GQ", + "FullName": "Equatorial Guinea", + "Acronym": "GNQ" + }, + { + "FlagName": "GP", + "FullName": "Guadeloupe", + "Acronym": "GLP" + }, + { + "FlagName": "JP", + "FullName": "Japan", + "Acronym": "JPN" + }, + { + "FlagName": "GY", + "FullName": "Guyana", + "Acronym": "GUY" + }, + { + "FlagName": "GG", + "FullName": "Guernsey", + "Acronym": "GGY" + }, + { + "FlagName": "GF", + "FullName": "French Guiana", + "Acronym": "GUF" + }, + { + "FlagName": "GE", + "FullName": "Georgia", + "Acronym": "GEO" + }, + { + "FlagName": "GD", + "FullName": "Grenada", + "Acronym": "GRD" + }, + { + "FlagName": "GB", + "FullName": "United Kingdom", + "Acronym": "GBR" + }, + { + "FlagName": "GA", + "FullName": "Gabon", + "Acronym": "GAB" + }, + { + "FlagName": "SV", + "FullName": "El Salvador", + "Acronym": "SLV" + }, + { + "FlagName": "GN", + "FullName": "Guinea", + "Acronym": "GIN" + }, + { + "FlagName": "GM", + "FullName": "Gambia", + "Acronym": "GMB" + }, + { + "FlagName": "GL", + "FullName": "Greenland", + "Acronym": "GRL" + }, + { + "FlagName": "GI", + "FullName": "Gibraltar", + "Acronym": "GIB" + }, + { + "FlagName": "GH", + "FullName": "Ghana", + "Acronym": "GHA" + }, + { + "FlagName": "OM", + "FullName": "Oman", + "Acronym": "OMN" + }, + { + "FlagName": "TN", + "FullName": "Tunisia", + "Acronym": "TUN" + }, + { + "FlagName": "JO", + "FullName": "Jordan", + "Acronym": "JOR" + }, + { + "FlagName": "HR", + "FullName": "Croatia", + "Acronym": "HRV" + }, + { + "FlagName": "HT", + "FullName": "Haiti", + "Acronym": "HTI" + }, + { + "FlagName": "HU", + "FullName": "Hungary", + "Acronym": "HUN" + }, + { + "FlagName": "HK", + "FullName": "Hong Kong", + "Acronym": "HKG" + }, + { + "FlagName": "HN", + "FullName": "Honduras", + "Acronym": "HND" + }, + { + "FlagName": "HM", + "FullName": "Heard Island and McDonald Islands", + "Acronym": "HMD" + }, + { + "FlagName": "VE", + "FullName": "Venezuela", + "Acronym": "VEN" + }, + { + "FlagName": "PR", + "FullName": "Puerto Rico", + "Acronym": "PRI" + }, + { + "FlagName": "PS", + "FullName": "Palestinian Territory", + "Acronym": "PSE" + }, + { + "FlagName": "PW", + "FullName": "Palau", + "Acronym": "PLW" + }, + { + "FlagName": "PT", + "FullName": "Portugal", + "Acronym": "PRT" + }, + { + "FlagName": "SJ", + "FullName": "Svalbard and Jan Mayen", + "Acronym": "SJM" + }, + { + "FlagName": "PY", + "FullName": "Paraguay", + "Acronym": "PRY" + }, + { + "FlagName": "IQ", + "FullName": "Iraq", + "Acronym": "IRQ" + }, + { + "FlagName": "PA", + "FullName": "Panama", + "Acronym": "PAN" + }, + { + "FlagName": "PF", + "FullName": "French Polynesia", + "Acronym": "PYF" + }, + { + "FlagName": "PG", + "FullName": "Papua New Guinea", + "Acronym": "PNG" + }, + { + "FlagName": "PE", + "FullName": "Peru", + "Acronym": "PER" + }, + { + "FlagName": "PK", + "FullName": "Pakistan", + "Acronym": "PAK" + }, + { + "FlagName": "PH", + "FullName": "Philippines", + "Acronym": "PHL" + }, + { + "FlagName": "PN", + "FullName": "Pitcairn", + "Acronym": "PCN" + }, + { + "FlagName": "PL", + "FullName": "Poland", + "Acronym": "POL" + }, + { + "FlagName": "PM", + "FullName": "Saint Pierre and Miquelon", + "Acronym": "SPM" + }, + { + "FlagName": "ZM", + "FullName": "Zambia", + "Acronym": "ZMB" + }, + { + "FlagName": "EH", + "FullName": "Western Sahara", + "Acronym": "ESH" + }, + { + "FlagName": "EE", + "FullName": "Estonia", + "Acronym": "EST" + }, + { + "FlagName": "EG", + "FullName": "Egypt", + "Acronym": "EGY" + }, + { + "FlagName": "ZA", + "FullName": "South Africa", + "Acronym": "ZAF" + }, + { + "FlagName": "EC", + "FullName": "Ecuador", + "Acronym": "ECU" + }, + { + "FlagName": "IT", + "FullName": "Italy", + "Acronym": "ITA" + }, + { + "FlagName": "VN", + "FullName": "Vietnam", + "Acronym": "VNM" + }, + { + "FlagName": "SB", + "FullName": "Solomon Islands", + "Acronym": "SLB" + }, + { + "FlagName": "ET", + "FullName": "Ethiopia", + "Acronym": "ETH" + }, + { + "FlagName": "SO", + "FullName": "Somalia", + "Acronym": "SOM" + }, + { + "FlagName": "ZW", + "FullName": "Zimbabwe", + "Acronym": "ZWE" + }, + { + "FlagName": "SA", + "FullName": "Saudi Arabia", + "Acronym": "SAU" + }, + { + "FlagName": "ES", + "FullName": "Spain", + "Acronym": "ESP" + }, + { + "FlagName": "ER", + "FullName": "Eritrea", + "Acronym": "ERI" + }, + { + "FlagName": "ME", + "FullName": "Montenegro", + "Acronym": "MNE" + }, + { + "FlagName": "MD", + "FullName": "Moldova", + "Acronym": "MDA" + }, + { + "FlagName": "MG", + "FullName": "Madagascar", + "Acronym": "MDG" + }, + { + "FlagName": "MF", + "FullName": "Saint Martin", + "Acronym": "MAF" + }, + { + "FlagName": "MA", + "FullName": "Morocco", + "Acronym": "MAR" + }, + { + "FlagName": "MC", + "FullName": "Monaco", + "Acronym": "MCO" + }, + { + "FlagName": "UZ", + "FullName": "Uzbekistan", + "Acronym": "UZB" + }, + { + "FlagName": "MM", + "FullName": "Myanmar", + "Acronym": "MMR" + }, + { + "FlagName": "ML", + "FullName": "Mali", + "Acronym": "MLI" + }, + { + "FlagName": "MO", + "FullName": "Macao", + "Acronym": "MAC" + }, + { + "FlagName": "MN", + "FullName": "Mongolia", + "Acronym": "MNG" + }, + { + "FlagName": "MH", + "FullName": "Marshall Islands", + "Acronym": "MHL" + }, + { + "FlagName": "MK", + "FullName": "Macedonia", + "Acronym": "MKD" + }, + { + "FlagName": "MU", + "FullName": "Mauritius", + "Acronym": "MUS" + }, + { + "FlagName": "MT", + "FullName": "Malta", + "Acronym": "MLT" + }, + { + "FlagName": "MW", + "FullName": "Malawi", + "Acronym": "MWI" + }, + { + "FlagName": "MV", + "FullName": "Maldives", + "Acronym": "MDV" + }, + { + "FlagName": "MQ", + "FullName": "Martinique", + "Acronym": "MTQ" + }, + { + "FlagName": "MP", + "FullName": "Northern Mariana Islands", + "Acronym": "MNP" + }, + { + "FlagName": "MS", + "FullName": "Montserrat", + "Acronym": "MSR" + }, + { + "FlagName": "MR", + "FullName": "Mauritania", + "Acronym": "MRT" + }, + { + "FlagName": "IM", + "FullName": "Isle of Man", + "Acronym": "IMN" + }, + { + "FlagName": "UG", + "FullName": "Uganda", + "Acronym": "UGA" + }, + { + "FlagName": "TZ", + "FullName": "Tanzania", + "Acronym": "TZA" + }, + { + "FlagName": "MY", + "FullName": "Malaysia", + "Acronym": "MYS" + }, + { + "FlagName": "MX", + "FullName": "Mexico", + "Acronym": "MEX" + }, + { + "FlagName": "IL", + "FullName": "Israel", + "Acronym": "ISR" + }, + { + "FlagName": "FR", + "FullName": "France", + "Acronym": "FRA" + }, + { + "FlagName": "IO", + "FullName": "British Indian Ocean Territory", + "Acronym": "IOT" + }, + { + "FlagName": "SH", + "FullName": "Saint Helena", + "Acronym": "SHN" + }, + { + "FlagName": "FI", + "FullName": "Finland", + "Acronym": "FIN" + }, + { + "FlagName": "FJ", + "FullName": "Fiji", + "Acronym": "FJI" + }, + { + "FlagName": "FK", + "FullName": "Falkland Islands", + "Acronym": "FLK" + }, + { + "FlagName": "FM", + "FullName": "Micronesia", + "Acronym": "FSM" + }, + { + "FlagName": "FO", + "FullName": "Faroe Islands", + "Acronym": "FRO" + }, + { + "FlagName": "NI", + "FullName": "Nicaragua", + "Acronym": "NIC" + }, + { + "FlagName": "NL", + "FullName": "Netherlands", + "Acronym": "NLD" + }, + { + "FlagName": "NO", + "FullName": "Norway", + "Acronym": "NOR" + }, + { + "FlagName": "NA", + "FullName": "Namibia", + "Acronym": "NAM" + }, + { + "FlagName": "VU", + "FullName": "Vanuatu", + "Acronym": "VUT" + }, + { + "FlagName": "NC", + "FullName": "New Caledonia", + "Acronym": "NCL" + }, + { + "FlagName": "NE", + "FullName": "Niger", + "Acronym": "NER" + }, + { + "FlagName": "NF", + "FullName": "Norfolk Island", + "Acronym": "NFK" + }, + { + "FlagName": "NG", + "FullName": "Nigeria", + "Acronym": "NGA" + }, + { + "FlagName": "NZ", + "FullName": "New Zealand", + "Acronym": "NZL" + }, + { + "FlagName": "NP", + "FullName": "Nepal", + "Acronym": "NPL" + }, + { + "FlagName": "NR", + "FullName": "Nauru", + "Acronym": "NRU" + }, + { + "FlagName": "NU", + "FullName": "Niue", + "Acronym": "NIU" + }, + { + "FlagName": "CK", + "FullName": "Cook Islands", + "Acronym": "COK" + }, + { + "FlagName": "XK", + "FullName": "Kosovo", + "Acronym": "XKX" + }, + { + "FlagName": "CI", + "FullName": "Ivory Coast", + "Acronym": "CIV" + }, + { + "FlagName": "CH", + "FullName": "Switzerland", + "Acronym": "CHE" + }, + { + "FlagName": "CO", + "FullName": "Colombia", + "Acronym": "COL" + }, + { + "FlagName": "CN", + "FullName": "China", + "Acronym": "CHN" + }, + { + "FlagName": "CM", + "FullName": "Cameroon", + "Acronym": "CMR" + }, + { + "FlagName": "CL", + "FullName": "Chile", + "Acronym": "CHL" + }, + { + "FlagName": "CC", + "FullName": "Cocos Islands", + "Acronym": "CCK" + }, + { + "FlagName": "CA", + "FullName": "Canada", + "Acronym": "CAN" + }, + { + "FlagName": "CG", + "FullName": "Republic of the Congo", + "Acronym": "COG" + }, + { + "FlagName": "CF", + "FullName": "Central African Republic", + "Acronym": "CAF" + }, + { + "FlagName": "CD", + "FullName": "Democratic Republic of the Congo", + "Acronym": "COD" + }, + { + "FlagName": "CZ", + "FullName": "Czech Republic", + "Acronym": "CZE" + }, + { + "FlagName": "CY", + "FullName": "Cyprus", + "Acronym": "CYP" + }, + { + "FlagName": "CX", + "FullName": "Christmas Island", + "Acronym": "CXR" + }, + { + "FlagName": "CR", + "FullName": "Costa Rica", + "Acronym": "CRI" + }, + { + "FlagName": "CW", + "FullName": "Curacao", + "Acronym": "CUW" + }, + { + "FlagName": "CV", + "FullName": "Cape Verde", + "Acronym": "CPV" + }, + { + "FlagName": "CU", + "FullName": "Cuba", + "Acronym": "CUB" + }, + { + "FlagName": "SZ", + "FullName": "Swaziland", + "Acronym": "SWZ" + }, + { + "FlagName": "SY", + "FullName": "Syria", + "Acronym": "SYR" + }, + { + "FlagName": "SX", + "FullName": "Sint Maarten", + "Acronym": "SXM" + }, + { + "FlagName": "KG", + "FullName": "Kyrgyzstan", + "Acronym": "KGZ" + }, + { + "FlagName": "KE", + "FullName": "Kenya", + "Acronym": "KEN" + }, + { + "FlagName": "SS", + "FullName": "South Sudan", + "Acronym": "SSD" + }, + { + "FlagName": "SR", + "FullName": "Suriname", + "Acronym": "SUR" + }, + { + "FlagName": "KI", + "FullName": "Kiribati", + "Acronym": "KIR" + }, + { + "FlagName": "KH", + "FullName": "Cambodia", + "Acronym": "KHM" + }, + { + "FlagName": "KN", + "FullName": "Saint Kitts and Nevis", + "Acronym": "KNA" + }, + { + "FlagName": "KM", + "FullName": "Comoros", + "Acronym": "COM" + }, + { + "FlagName": "ST", + "FullName": "Sao Tome and Principe", + "Acronym": "STP" + }, + { + "FlagName": "SK", + "FullName": "Slovakia", + "Acronym": "SVK" + }, + { + "FlagName": "KR", + "FullName": "South Korea", + "Acronym": "KOR" + }, + { + "FlagName": "SI", + "FullName": "Slovenia", + "Acronym": "SVN" + }, + { + "FlagName": "KP", + "FullName": "North Korea", + "Acronym": "PRK" + }, + { + "FlagName": "KW", + "FullName": "Kuwait", + "Acronym": "KWT" + }, + { + "FlagName": "SN", + "FullName": "Senegal", + "Acronym": "SEN" + }, + { + "FlagName": "SM", + "FullName": "San Marino", + "Acronym": "SMR" + }, + { + "FlagName": "SL", + "FullName": "Sierra Leone", + "Acronym": "SLE" + }, + { + "FlagName": "SC", + "FullName": "Seychelles", + "Acronym": "SYC" + }, + { + "FlagName": "KZ", + "FullName": "Kazakhstan", + "Acronym": "KAZ" + }, + { + "FlagName": "KY", + "FullName": "Cayman Islands", + "Acronym": "CYM" + }, + { + "FlagName": "SG", + "FullName": "Singapore", + "Acronym": "SGP" + }, + { + "FlagName": "SE", + "FullName": "Sweden", + "Acronym": "SWE" + }, + { + "FlagName": "SD", + "FullName": "Sudan", + "Acronym": "SDN" + }, + { + "FlagName": "DO", + "FullName": "Dominican Republic", + "Acronym": "DOM" + }, + { + "FlagName": "DM", + "FullName": "Dominica", + "Acronym": "DMA" + }, + { + "FlagName": "DJ", + "FullName": "Djibouti", + "Acronym": "DJI" + }, + { + "FlagName": "DK", + "FullName": "Denmark", + "Acronym": "DNK" + }, + { + "FlagName": "VG", + "FullName": "British Virgin Islands", + "Acronym": "VGB" + }, + { + "FlagName": "DE", + "FullName": "Germany", + "Acronym": "DEU" + }, + { + "FlagName": "YE", + "FullName": "Yemen", + "Acronym": "YEM" + }, + { + "FlagName": "DZ", + "FullName": "Algeria", + "Acronym": "DZA" + }, + { + "FlagName": "US", + "FullName": "United States", + "Acronym": "USA" + }, + { + "FlagName": "UY", + "FullName": "Uruguay", + "Acronym": "URY" + }, + { + "FlagName": "YT", + "FullName": "Mayotte", + "Acronym": "MYT" + }, + { + "FlagName": "UM", + "FullName": "United States Minor Outlying Islands", + "Acronym": "UMI" + }, + { + "FlagName": "LB", + "FullName": "Lebanon", + "Acronym": "LBN" + }, + { + "FlagName": "LC", + "FullName": "Saint Lucia", + "Acronym": "LCA" + }, + { + "FlagName": "LA", + "FullName": "Laos", + "Acronym": "LAO" + }, + { + "FlagName": "TV", + "FullName": "Tuvalu", + "Acronym": "TUV" + }, + { + "FlagName": "TW", + "FullName": "Taiwan", + "Acronym": "TWN" + }, + { + "FlagName": "TT", + "FullName": "Trinidad and Tobago", + "Acronym": "TTO" + }, + { + "FlagName": "TR", + "FullName": "Turkey", + "Acronym": "TUR" + }, + { + "FlagName": "LK", + "FullName": "Sri Lanka", + "Acronym": "LKA" + }, + { + "FlagName": "LI", + "FullName": "Liechtenstein", + "Acronym": "LIE" + }, + { + "FlagName": "LV", + "FullName": "Latvia", + "Acronym": "LVA" + }, + { + "FlagName": "TO", + "FullName": "Tonga", + "Acronym": "TON" + }, + { + "FlagName": "LT", + "FullName": "Lithuania", + "Acronym": "LTU" + }, + { + "FlagName": "LU", + "FullName": "Luxembourg", + "Acronym": "LUX" + }, + { + "FlagName": "LR", + "FullName": "Liberia", + "Acronym": "LBR" + }, + { + "FlagName": "LS", + "FullName": "Lesotho", + "Acronym": "LSO" + }, + { + "FlagName": "TH", + "FullName": "Thailand", + "Acronym": "THA" + }, + { + "FlagName": "TF", + "FullName": "French Southern Territories", + "Acronym": "ATF" + }, + { + "FlagName": "TG", + "FullName": "Togo", + "Acronym": "TGO" + }, + { + "FlagName": "TD", + "FullName": "Chad", + "Acronym": "TCD" + }, + { + "FlagName": "TC", + "FullName": "Turks and Caicos Islands", + "Acronym": "TCA" + }, + { + "FlagName": "LY", + "FullName": "Libya", + "Acronym": "LBY" + }, + { + "FlagName": "VA", + "FullName": "Vatican", + "Acronym": "VAT" + }, + { + "FlagName": "VC", + "FullName": "Saint Vincent and the Grenadines", + "Acronym": "VCT" + }, + { + "FlagName": "AE", + "FullName": "United Arab Emirates", + "Acronym": "ARE" + }, + { + "FlagName": "AD", + "FullName": "Andorra", + "Acronym": "AND" + }, + { + "FlagName": "AG", + "FullName": "Antigua and Barbuda", + "Acronym": "ATG" + }, + { + "FlagName": "AF", + "FullName": "Afghanistan", + "Acronym": "AFG" + }, + { + "FlagName": "AI", + "FullName": "Anguilla", + "Acronym": "AIA" + }, + { + "FlagName": "VI", + "FullName": "U.S. Virgin Islands", + "Acronym": "VIR" + }, + { + "FlagName": "IS", + "FullName": "Iceland", + "Acronym": "ISL" + }, + { + "FlagName": "IR", + "FullName": "Iran", + "Acronym": "IRN" + }, + { + "FlagName": "AM", + "FullName": "Armenia", + "Acronym": "ARM" + }, + { + "FlagName": "AL", + "FullName": "Albania", + "Acronym": "ALB" + }, + { + "FlagName": "AO", + "FullName": "Angola", + "Acronym": "AGO" + }, + { + "FlagName": "AQ", + "FullName": "Antarctica", + "Acronym": "ATA" + }, + { + "FlagName": "AS", + "FullName": "American Samoa", + "Acronym": "ASM" + }, + { + "FlagName": "AR", + "FullName": "Argentina", + "Acronym": "ARG" + }, + { + "FlagName": "AU", + "FullName": "Australia", + "Acronym": "AUS" + }, + { + "FlagName": "AT", + "FullName": "Austria", + "Acronym": "AUT" + }, + { + "FlagName": "AW", + "FullName": "Aruba", + "Acronym": "ABW" + }, + { + "FlagName": "IN", + "FullName": "India", + "Acronym": "IND" + }, + { + "FlagName": "AX", + "FullName": "Aland Islands", + "Acronym": "ALA" + }, + { + "FlagName": "AZ", + "FullName": "Azerbaijan", + "Acronym": "AZE" + }, + { + "FlagName": "IE", + "FullName": "Ireland", + "Acronym": "IRL" + }, + { + "FlagName": "ID", + "FullName": "Indonesia", + "Acronym": "IDN" + }, + { + "FlagName": "UA", + "FullName": "Ukraine", + "Acronym": "UKR" + }, + { + "FlagName": "QA", + "FullName": "Qatar", + "Acronym": "QAT" + }, + { + "FlagName": "MZ", + "FullName": "Mozambique", + "Acronym": "MOZ" + } +] \ No newline at end of file diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 2ae6c60067..f398dd0a3d 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; @@ -15,6 +16,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests; using osu.Game.Rulesets; +using osu.Game.Tournament.Components; namespace osu.Game.Tournament { @@ -87,12 +89,26 @@ namespace osu.Game.Tournament } } + // link pairings to groupings foreach (var group in Ladder.Groupings) foreach (var id in group.Pairings) Ladder.Pairings.Single(p => p.ID == id).Grouping.Value = group; Ladder.CurrentMatch.Value = Ladder.Pairings.FirstOrDefault(p => p.Current.Value); + // add full player info based on user IDs + foreach (var t in Ladder.Teams) + foreach (var p in t.Players) + if (p.Id == 1) + { + var req = new GetUserRequest(p.Id); + req.Success += i => p.Username = i.Username; + req.Perform(API); + + addedInfo = true; + } + + // add full beatmap info based on beatmap IDs foreach (var g in Ladder.Groupings) foreach (var b in g.Beatmaps) if (b.BeatmapInfo == null) @@ -104,6 +120,24 @@ namespace osu.Game.Tournament addedInfo = true; } + + List countries; + using (Stream stream = Resources.GetStream("Resources/countries.json")) + using (var sr = new StreamReader(stream)) + countries = JsonConvert.DeserializeObject>(sr.ReadToEnd()); + + foreach (var t in Ladder.Teams) + if (string.IsNullOrEmpty(t.FullName)) + { + var result = countries.FirstOrDefault(c => c.Acronym == t.Acronym); + if (result != null) + { + t.Acronym = result.Acronym; + t.FlagName = result.FlagName; + t.FullName = result.FullName; + } + } + if (addedInfo) SaveChanges(); @@ -126,7 +160,6 @@ namespace osu.Game.Tournament protected override void Update() { - base.Update(); var minWidth = (int)(windowSize.Value.Height / 9f * 16 + 400); if (windowSize.Value.Width < minWidth) From 3eabac0e3de1cbc04db391ca80421f91c9b5cd7c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Nov 2018 01:23:00 +0900 Subject: [PATCH 0233/5608] Move all IPC handling to its own class --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 107 ++++++++++++++++++ .../Screens/BeatmapInfoScreen.cs | 104 ++--------------- osu.Game.Tournament/TournamentGameBase.cs | 5 + 3 files changed, 123 insertions(+), 93 deletions(-) create mode 100644 osu.Game.Tournament/IPC/FileBasedIPC.cs diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs new file mode 100644 index 0000000000..c42ccc11c2 --- /dev/null +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -0,0 +1,107 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.IO; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Platform.Windows; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Rulesets; + +namespace osu.Game.Tournament.IPC +{ + public class FileBasedIPC : Component + { + [Resolved] + protected APIAccess API { get; private set; } + + [Resolved] + protected RulesetStore Rulesets { get; private set; } + + public readonly Bindable Beatmap = new Bindable(); + + public readonly Bindable Mods = new Bindable(); + + [BackgroundDependencyLoader] + private void load() + { + var stable = new StableStorage(); + + const string file_ipc_filename = "ipc.txt"; + + if (stable.Exists(file_ipc_filename)) + Scheduler.AddDelayed(delegate + { + try + { + using (var stream = stable.GetStream(file_ipc_filename)) + using (var sr = new StreamReader(stream)) + { + var beatmapId = int.Parse(sr.ReadLine()); + var mods = int.Parse(sr.ReadLine()); + + if (Beatmap.Value?.OnlineBeatmapID != beatmapId) + { + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); + req.Success += b => Beatmap.Value = b.ToBeatmap(Rulesets); + API.Queue(req); + } + + Mods.Value = (LegacyMods)mods; + } + } + catch + { + // file might be in use. + } + }, 250, true); + } + + /// + /// A method of accessing an osu-stable install in a controlled fashion. + /// + private class StableStorage : WindowsStorage + { + protected override string LocateBasePath() + { + bool checkExists(string p) + { + return Directory.Exists(Path.Combine(p, "Songs")); + } + + string stableInstallPath; + + try + { + stableInstallPath = "E:\\osu!mappool"; + + if (checkExists(stableInstallPath)) + return stableInstallPath; + } + catch + { + } + + stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); + if (checkExists(stableInstallPath)) + return stableInstallPath; + + stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu"); + if (checkExists(stableInstallPath)) + return stableInstallPath; + + return null; + } + + public StableStorage() + : base(string.Empty, null) + { + } + } + } +} diff --git a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs index 18ba947582..11cbb56b49 100644 --- a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs +++ b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs @@ -1,33 +1,18 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using System.IO; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Platform.Windows; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; -using osu.Game.Online.API.Requests.Responses; -using osu.Game.Rulesets; using osu.Game.Screens; using osu.Game.Tournament.Components; +using osu.Game.Tournament.IPC; namespace osu.Game.Tournament.Screens { public abstract class BeatmapInfoScreen : OsuScreen { - [Resolved] - protected APIAccess API { get; private set; } - - [Resolved] - protected RulesetStore Rulesets { get; private set; } - - private int lastBeatmapId; - private int lastMods; - protected readonly SongBar SongBar; protected BeatmapInfoScreen() @@ -40,88 +25,21 @@ namespace osu.Game.Tournament.Screens } [BackgroundDependencyLoader] - private void load() + private void load(FileBasedIPC ipc) { - var stable = new StableStorage(); - - const string file_ipc_filename = "ipc.txt"; - - if (stable.Exists(file_ipc_filename)) - Scheduler.AddDelayed(delegate - { - try - { - using (var stream = stable.GetStream(file_ipc_filename)) - using (var sr = new StreamReader(stream)) - { - var beatmapId = int.Parse(sr.ReadLine()); - var mods = int.Parse(sr.ReadLine()); - - if (lastBeatmapId == beatmapId) - return; - - lastMods = mods; - lastBeatmapId = beatmapId; - - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); - req.Success += success; - API.Queue(req); - } - } - catch - { - // file might be in use. - } - }, 250, true); + ipc.Beatmap.BindValueChanged(beatmapChanged, true); + ipc.Mods.BindValueChanged(modsChanged, true); } - private void success(APIBeatmap apiBeatmap) + private void modsChanged(LegacyMods mods) + { + SongBar.Mods = mods; + } + + private void beatmapChanged(BeatmapInfo beatmap) { SongBar.FadeInFromZero(300, Easing.OutQuint); - SongBar.Mods = (LegacyMods)lastMods; - SongBar.Beatmap = apiBeatmap.ToBeatmap(Rulesets); - } - - /// - /// A method of accessing an osu-stable install in a controlled fashion. - /// - private class StableStorage : WindowsStorage - { - protected override string LocateBasePath() - { - bool checkExists(string p) - { - return Directory.Exists(Path.Combine(p, "Songs")); - } - - string stableInstallPath; - - try - { - stableInstallPath = "E:\\osu!mappool"; - - if (checkExists(stableInstallPath)) - return stableInstallPath; - } - catch - { - } - - stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); - if (checkExists(stableInstallPath)) - return stableInstallPath; - - stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu"); - if (checkExists(stableInstallPath)) - return stableInstallPath; - - return null; - } - - public StableStorage() - : base(string.Empty, null) - { - } + SongBar.Beatmap = beatmap; } } } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index f398dd0a3d..562b141095 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -17,6 +17,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests; using osu.Game.Rulesets; using osu.Game.Tournament.Components; +using osu.Game.Tournament.IPC; namespace osu.Game.Tournament { @@ -33,6 +34,7 @@ namespace osu.Game.Tournament private readonly Bindable ruleset = new Bindable(); private Bindable windowSize; + private FileBasedIPC ipc; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { @@ -63,6 +65,9 @@ namespace osu.Game.Tournament dependencies.Cache(Ladder); + dependencies.Cache(ipc = new FileBasedIPC()); + Add(ipc); + bool addedInfo = false; // assign teams From e4a767d656c9add79f0d4fc1863f363396fcb0c9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Nov 2018 03:51:39 +0900 Subject: [PATCH 0234/5608] Move control panel logic to its own class --- .../Components/ControlPanel.cs | 73 ++++++++++++ .../Screens/Drawings/DrawingsScreen.cs | 106 ++++-------------- 2 files changed, 97 insertions(+), 82 deletions(-) create mode 100644 osu.Game.Tournament/Components/ControlPanel.cs diff --git a/osu.Game.Tournament/Components/ControlPanel.cs b/osu.Game.Tournament/Components/ControlPanel.cs new file mode 100644 index 0000000000..f016eb30a4 --- /dev/null +++ b/osu.Game.Tournament/Components/ControlPanel.cs @@ -0,0 +1,73 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Sprites; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Tournament.Components +{ + /// + /// An element anchored to the right-hand area of a screen that provides streamer level controls. + /// Should be off-screen. + /// + public class ControlPanel : Container + { + private readonly FillFlowContainer buttons; + + protected override Container Content => buttons; + + public ControlPanel() + { + RelativeSizeAxes = Axes.Both; + AlwaysPresent = true; + Width = 0.15f; + Anchor = Anchor.TopRight; + + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new Color4(54, 54, 54, 255) + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + + Text = "Control Panel", + TextSize = 22f, + Font = "Exo2.0-Bold" + }, + buttons = new FillFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Width = 0.75f, + + Position = new Vector2(0, 35f), + + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5f), + }, + }; + } + + public class Spacer : CompositeDrawable + { + public Spacer(float height = 20) + { + RelativeSizeAxes = Axes.X; + Height = height; + AlwaysPresent = true; + } + } + } +} diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 9e8074d7dc..f94c882c85 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -9,7 +9,6 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; @@ -147,93 +146,36 @@ namespace osu.Game.Tournament.Screens.Drawings } }, // Control panel container - new Container + new ControlPanel { - RelativeSizeAxes = Axes.Both, - AlwaysPresent = true, - Width = 0.15f, - Anchor = Anchor.TopRight, - - Children = new Drawable[] + new TriangleButton { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = new Color4(54, 54, 54, 255) - }, - new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, - Text = "Control Panel", - TextSize = 22f, - Font = "Exo2.0-Bold" - }, - new FillFlowContainer - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, + Text = "Begin random", + Action = teamsContainer.StartScrolling, + }, + new TriangleButton + { + RelativeSizeAxes = Axes.X, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Width = 0.75f, + Text = "Stop random", + Action = teamsContainer.StopScrolling, + }, + new TriangleButton + { + RelativeSizeAxes = Axes.X, - Position = new Vector2(0, 35f), + Text = "Reload", + Action = reloadTeams + }, + new ControlPanel.Spacer(), + new TriangleButton + { + RelativeSizeAxes = Axes.X, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5f), - - Children = new Drawable[] - { - new TriangleButton - { - RelativeSizeAxes = Axes.X, - - Text = "Begin random", - Action = teamsContainer.StartScrolling, - }, - new TriangleButton - { - RelativeSizeAxes = Axes.X, - - Text = "Stop random", - Action = teamsContainer.StopScrolling, - }, - new TriangleButton - { - RelativeSizeAxes = Axes.X, - - Text = "Reload", - Action = reloadTeams - } - } - }, - new FillFlowContainer - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Width = 0.75f, - - Position = new Vector2(0, -5f), - - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5f), - - Children = new Drawable[] - { - new TriangleButton - { - RelativeSizeAxes = Axes.X, - - Text = "Reset", - Action = () => reset() - } - } - } + Text = "Reset", + Action = () => reset() } } }; From 5c84c3c0a8157b65a64ddcffaa871d9446297de2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Nov 2018 06:29:04 +0900 Subject: [PATCH 0235/5608] Add support for picks and bans --- .../TestCaseLadderManager.cs | 2 +- osu.Game.Tournament.Tests/TestCaseMapPool.cs | 13 +- .../Components/TournamentBeatmapPanel.cs | 68 ++++++++-- .../Ladder/Components/BeatmapChoice.cs | 24 ++++ .../Screens/Ladder/Components/MatchPairing.cs | 6 +- .../Screens/Ladder/LadderManager.cs | 27 ++-- .../Screens/MapPool/MapPoolScreen.cs | 125 +++++++++++++++++- .../Screens/TournamentSceneManager.cs | 5 +- 8 files changed, 232 insertions(+), 38 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index 5fa378a854..3ddd52eeac 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tournament.Tests Add(new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - Child = manager = new LadderManager(Ladder) + Child = manager = new LadderManager() }); } diff --git a/osu.Game.Tournament.Tests/TestCaseMapPool.cs b/osu.Game.Tournament.Tests/TestCaseMapPool.cs index 1101d2828a..d953dbc5d3 100644 --- a/osu.Game.Tournament.Tests/TestCaseMapPool.cs +++ b/osu.Game.Tournament.Tests/TestCaseMapPool.cs @@ -1,7 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; +using System; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Tournament.Screens.MapPool; @@ -9,13 +10,15 @@ namespace osu.Game.Tournament.Tests { public class TestCaseMapPool : LadderTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(MapPoolScreen) + }; + [BackgroundDependencyLoader] private void load() { - var round = Ladder.Groupings.FirstOrDefault(g => g.Name == "Finals"); - - if (round != null) - Add(new MapPoolScreen(round)); + Add(new MapPoolScreen { Width = 0.7f }); } } } diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 9542c26faf..7f9494e3c9 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -1,7 +1,11 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -10,28 +14,35 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Tournament.Screens.Ladder.Components; using OpenTK.Graphics; namespace osu.Game.Tournament.Components { public class TournamentBeatmapPanel : CompositeDrawable { - private readonly BeatmapInfo beatmap; + public readonly BeatmapInfo Beatmap; + private const float horizontal_padding = 10; private const float vertical_padding = 5; public const float HEIGHT = 50; + private readonly Bindable currentMatch = new Bindable(); + public TournamentBeatmapPanel(BeatmapInfo beatmap) { - this.beatmap = beatmap; + Beatmap = beatmap; Width = 400; Height = HEIGHT; } [BackgroundDependencyLoader] - private void load() + private void load(LadderInfo ladder) { + currentMatch.BindValueChanged(matchChanged); + currentMatch.BindTo(ladder.CurrentMatch); + CornerRadius = 25; Masking = true; @@ -46,7 +57,7 @@ namespace osu.Game.Tournament.Components { RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.5f), - BeatmapSet = beatmap.BeatmapSet, + BeatmapSet = Beatmap.BeatmapSet, }, new FillFlowContainer { @@ -62,8 +73,8 @@ namespace osu.Game.Tournament.Components Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = new LocalisedString(( - $"{beatmap.Metadata.ArtistUnicode} - {beatmap.Metadata.TitleUnicode}", - $"{beatmap.Metadata.Artist} - {beatmap.Metadata.Title}")), + $"{Beatmap.Metadata.ArtistUnicode} - {Beatmap.Metadata.TitleUnicode}", + $"{Beatmap.Metadata.Artist} - {Beatmap.Metadata.Title}")), Font = @"Exo2.0-BoldItalic", }, new FillFlowContainer @@ -84,7 +95,7 @@ namespace osu.Game.Tournament.Components }, new OsuSpriteText { - Text = beatmap.Metadata.AuthorString, + Text = Beatmap.Metadata.AuthorString, Font = @"Exo2.0-BoldItalic", Padding = new MarginPadding { Right = 20 }, TextSize = 14 @@ -98,7 +109,7 @@ namespace osu.Game.Tournament.Components }, new OsuSpriteText { - Text = beatmap.Version, + Text = Beatmap.Version, Font = @"Exo2.0-BoldItalic", TextSize = 14 }, @@ -108,5 +119,46 @@ namespace osu.Game.Tournament.Components }, }); } + + private void matchChanged(MatchPairing match) + { + match.PicksBans.CollectionChanged += picksBansOnCollectionChanged; + updateState(); + } + + private void updateState() + { + var found = currentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == Beatmap.OnlineBeatmapID); + + if (found != null) + { + switch (found.Team) + { + case TeamColour.Red: + Colour = Color4.Red; + break; + case TeamColour.Blue: + Colour = Color4.Blue; + break; + } + } + else + { + Colour = Color4.White; + } + } + + private void picksBansOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + var list = (ObservableCollection)sender; + if (sender != currentMatch.Value.PicksBans) + { + // todo: we need a last attribute in bindable valuechanged events badly. + list.CollectionChanged -= picksBansOnCollectionChanged; + return; + } + + updateState(); + } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs b/osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs new file mode 100644 index 0000000000..d0b2556603 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + public class BeatmapChoice + { + public TeamColour Team; + public ChoiceType Type; + public int BeatmapID; + } + + public enum TeamColour + { + Red, + Blue + } + + public enum ChoiceType + { + Pick, + Ban, + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index aa0c3229c9..63c96d350d 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.ObjectModel; using Newtonsoft.Json; using osu.Framework.Configuration; using osu.Game.Tournament.Components; @@ -34,6 +35,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly Bindable Losers = new Bindable(); + public readonly ObservableCollection PicksBans = new ObservableCollection(); + [JsonIgnore] public readonly Bindable Grouping = new Bindable(); @@ -58,7 +61,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Team2.BindValueChanged(t => Team2Acronym = t?.Acronym, true); } - public MatchPairing(TournamentTeam team1 = null, TournamentTeam team2 = null) : this() + public MatchPairing(TournamentTeam team1 = null, TournamentTeam team2 = null) + : this() { Team1.Value = team1; Team2.Value = team2; diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index f348eff571..805358e231 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -26,20 +26,24 @@ namespace osu.Game.Tournament.Screens.Ladder [Cached] public class LadderManager : CompositeDrawable, IHasContextMenu { - public readonly List Teams; - private readonly Container pairingsContainer; - private readonly Container paths; - private readonly Container headings; + public List Teams; + private Container pairingsContainer; + private Container paths; + private Container headings; - private readonly LadderInfo info; + private LadderInfo info; - private readonly ScrollableContainer scrollContent; + private ScrollableContainer scrollContent; [Cached] - private readonly LadderEditorInfo editorInfo = new LadderEditorInfo(); + private LadderEditorInfo editorInfo = new LadderEditorInfo(); - public LadderManager(LadderInfo info) + [BackgroundDependencyLoader] + private void load(LadderInfo info, OsuColour colours) { + normalPathColour = colours.BlueDarker.Darken(2); + losersPathColour = colours.YellowDarker.Darken(2); + this.info = info; editorInfo.Teams = Teams = info.Teams; editorInfo.Groupings = info.Groupings; @@ -128,13 +132,6 @@ namespace osu.Game.Tournament.Screens.Ladder private Color4 normalPathColour; private Color4 losersPathColour; - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - normalPathColour = colours.BlueDarker.Darken(2); - losersPathColour = colours.YellowDarker.Darken(2); - } - private void updateLayout() { paths.Clear(); diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 6d7dca0aad..94f52267de 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -1,33 +1,148 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Screens; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; using OpenTK; +using OpenTK.Input; namespace osu.Game.Tournament.Screens.MapPool { public class MapPoolScreen : OsuScreen { - public MapPoolScreen(TournamentGrouping round) - { - FillFlowContainer maps; + private readonly FillFlowContainer maps; + private readonly Bindable currentMatch = new Bindable(); + + public MapPoolScreen() + { InternalChildren = new Drawable[] { - maps = new FillFlowContainer + maps = new FillFlowContainer { Spacing = new Vector2(20), Padding = new MarginPadding(50), Direction = FillDirection.Full, RelativeSizeAxes = Axes.Both, + }, + new ControlPanel + { + Children = new Drawable[] + { + new OsuSpriteText + { + Text = "Current Mode" + }, + buttonRedBan = new TriangleButton + { + RelativeSizeAxes = Axes.X, + Text = "Red Ban", + Action = () => setMode(TeamColour.Red, ChoiceType.Ban) + }, + buttonBlueBan = new TriangleButton + { + RelativeSizeAxes = Axes.X, + Text = "Blue Ban", + Action = () => setMode(TeamColour.Blue, ChoiceType.Ban) + }, + buttonRedPick = new TriangleButton + { + RelativeSizeAxes = Axes.X, + Text = "Red Pick", + Action = () => setMode(TeamColour.Red, ChoiceType.Pick) + }, + buttonBluePick = new TriangleButton + { + RelativeSizeAxes = Axes.X, + Text = "Blue Pick", + Action = () => setMode(TeamColour.Blue, ChoiceType.Pick) + } + } } }; + } - foreach (var b in round.Beatmaps) + private TeamColour pickColour; + private ChoiceType pickType; + + private readonly TriangleButton buttonRedBan; + private readonly TriangleButton buttonBlueBan; + private readonly TriangleButton buttonRedPick; + private readonly TriangleButton buttonBluePick; + + private void setMode(TeamColour colour, ChoiceType choiceType) + { + pickColour = colour; + pickType = choiceType; + + var enabled = currentMatch.Value.PicksBans.Count == 0; + + buttonRedBan.Enabled.Value = enabled || pickColour == TeamColour.Red && pickType == ChoiceType.Ban; + buttonBlueBan.Enabled.Value = enabled || pickColour == TeamColour.Blue && pickType == ChoiceType.Ban; + buttonRedPick.Enabled.Value = enabled || pickColour == TeamColour.Red && pickType == ChoiceType.Pick; + buttonBluePick.Enabled.Value = enabled || pickColour == TeamColour.Blue && pickType == ChoiceType.Pick; + } + + private void setNextMode() + { + const TeamColour roll_winner = TeamColour.Red; //todo: draw from match + + var nextColour = (currentMatch.Value.PicksBans.LastOrDefault()?.Team ?? roll_winner) == TeamColour.Red ? TeamColour.Blue : TeamColour.Red; + + setMode(nextColour, currentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) >= 2 ? ChoiceType.Pick : ChoiceType.Ban); + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + var map = maps.FirstOrDefault(m => m.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)); + if (map != null) + { + if (e.Button == MouseButton.Left) + { + currentMatch.Value.PicksBans.Add(new BeatmapChoice + { + Team = pickColour, + Type = pickType, + BeatmapID = map.Beatmap.OnlineBeatmapID ?? -1 + }); + + setNextMode(); + } + else + { + var existing = currentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == map.Beatmap.OnlineBeatmapID); + if (existing != null) + { + currentMatch.Value.PicksBans.Remove(existing); + setNextMode(); + } + } + + return true; + } + + return base.OnMouseDown(e); + } + + [BackgroundDependencyLoader] + private void load(LadderInfo ladder) + { + currentMatch.BindValueChanged(matchChanged); + currentMatch.BindTo(ladder.CurrentMatch); + } + + private void matchChanged(MatchPairing match) + { + foreach (var b in match.Grouping.Value.Beatmaps) maps.Add(new TournamentBeatmapPanel(b.BeatmapInfo) { Anchor = Anchor.TopCentre, diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index 91d389b63d..4cd6c681fa 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -88,9 +87,9 @@ namespace osu.Game.Tournament.Screens RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - bracket = new LadderManager(ladder), + bracket = new LadderManager(), showcase = new ShowcaseScreen(), - mapPool = new MapPoolScreen(ladder.Groupings.First(g => g.Name == "Finals")), + mapPool = new MapPoolScreen(), teamIntro = new TeamIntroScreen(), drawings = new DrawingsScreen(), gameplay = new GameplayScreen() From 5da6f11a141b76c5d98c0cd52a2baef7aea16405 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Nov 2018 06:36:36 +0900 Subject: [PATCH 0236/5608] Automate picks and bans from IPC --- .../Screens/MapPool/MapPoolScreen.cs | 63 ++++++++++++------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 94f52267de..fb9bd7b9a5 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -7,10 +7,12 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; +using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Screens; using osu.Game.Tournament.Components; +using osu.Game.Tournament.IPC; using osu.Game.Tournament.Screens.Ladder.Components; using OpenTK; using OpenTK.Input; @@ -23,6 +25,14 @@ namespace osu.Game.Tournament.Screens.MapPool private readonly Bindable currentMatch = new Bindable(); + private TeamColour pickColour; + private ChoiceType pickType; + + private readonly TriangleButton buttonRedBan; + private readonly TriangleButton buttonBlueBan; + private readonly TriangleButton buttonRedPick; + private readonly TriangleButton buttonBluePick; + public MapPoolScreen() { InternalChildren = new Drawable[] @@ -71,13 +81,20 @@ namespace osu.Game.Tournament.Screens.MapPool }; } - private TeamColour pickColour; - private ChoiceType pickType; + [BackgroundDependencyLoader] + private void load(LadderInfo ladder, FileBasedIPC ipc) + { + currentMatch.BindValueChanged(matchChanged); + currentMatch.BindTo(ladder.CurrentMatch); - private readonly TriangleButton buttonRedBan; - private readonly TriangleButton buttonBlueBan; - private readonly TriangleButton buttonRedPick; - private readonly TriangleButton buttonBluePick; + ipc.Beatmap.BindValueChanged(beatmapChanged); + } + + private void beatmapChanged(BeatmapInfo beatmap) + { + if (beatmap.OnlineBeatmapID != null) + addForBeatmap(beatmap.OnlineBeatmapID.Value); + } private void setMode(TeamColour colour, ChoiceType choiceType) { @@ -106,17 +123,8 @@ namespace osu.Game.Tournament.Screens.MapPool var map = maps.FirstOrDefault(m => m.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)); if (map != null) { - if (e.Button == MouseButton.Left) - { - currentMatch.Value.PicksBans.Add(new BeatmapChoice - { - Team = pickColour, - Type = pickType, - BeatmapID = map.Beatmap.OnlineBeatmapID ?? -1 - }); - - setNextMode(); - } + if (e.Button == MouseButton.Left && map.Beatmap.OnlineBeatmapID != null) + addForBeatmap(map.Beatmap.OnlineBeatmapID.Value); else { var existing = currentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == map.Beatmap.OnlineBeatmapID); @@ -133,11 +141,24 @@ namespace osu.Game.Tournament.Screens.MapPool return base.OnMouseDown(e); } - [BackgroundDependencyLoader] - private void load(LadderInfo ladder) + private void addForBeatmap(int beatmapId) { - currentMatch.BindValueChanged(matchChanged); - currentMatch.BindTo(ladder.CurrentMatch); + if (currentMatch.Value.Grouping.Value.Beatmaps.All(b => b.BeatmapInfo.OnlineBeatmapID != beatmapId)) + // don't attempt to add if the beatmap isn't in our pool + return; + + if (currentMatch.Value.PicksBans.Any(p => p.BeatmapID == beatmapId)) + // don't attempt to add if already exists. + return; + + currentMatch.Value.PicksBans.Add(new BeatmapChoice + { + Team = pickColour, + Type = pickType, + BeatmapID = beatmapId + }); + + setNextMode(); } private void matchChanged(MatchPairing match) From bd6d3f147316df900655ddc9a0d816ab11ef1f9e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Nov 2018 06:47:42 +0900 Subject: [PATCH 0237/5608] Improve appearance --- .../Components/TournamentBeatmapPanel.cs | 20 ++++++++++++-- .../Screens/MapPool/MapPoolScreen.cs | 26 ++++++++++++++----- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 7f9494e3c9..b804fc44a7 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -132,19 +132,35 @@ namespace osu.Game.Tournament.Components if (found != null) { + BorderThickness = 6; + switch (found.Team) { case TeamColour.Red: - Colour = Color4.Red; + BorderColour = Color4.Red; break; case TeamColour.Blue: - Colour = Color4.Blue; + BorderColour = Color4.Blue; + break; + } + + switch (found.Type) + { + case ChoiceType.Pick: + Colour = Color4.White; + Alpha = 1; + break; + case ChoiceType.Ban: + Colour = Color4.Gray; + Alpha = 0.5f; break; } } else { Colour = Color4.White; + BorderThickness = 0; + Alpha = 1; } } diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index fb9bd7b9a5..be56869115 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -15,6 +15,7 @@ using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Screens.Ladder.Components; using OpenTK; +using OpenTK.Graphics; using OpenTK.Input; namespace osu.Game.Tournament.Screens.MapPool @@ -75,7 +76,14 @@ namespace osu.Game.Tournament.Screens.MapPool RelativeSizeAxes = Axes.X, Text = "Blue Pick", Action = () => setMode(TeamColour.Blue, ChoiceType.Pick) - } + }, + new ControlPanel.Spacer(), + new TriangleButton + { + RelativeSizeAxes = Axes.X, + Text = "Reset", + Action = reset + }, } } }; @@ -101,12 +109,12 @@ namespace osu.Game.Tournament.Screens.MapPool pickColour = colour; pickType = choiceType; - var enabled = currentMatch.Value.PicksBans.Count == 0; + Color4 setColour(bool active) => active ? Color4.White : Color4.Gray; - buttonRedBan.Enabled.Value = enabled || pickColour == TeamColour.Red && pickType == ChoiceType.Ban; - buttonBlueBan.Enabled.Value = enabled || pickColour == TeamColour.Blue && pickType == ChoiceType.Ban; - buttonRedPick.Enabled.Value = enabled || pickColour == TeamColour.Red && pickType == ChoiceType.Pick; - buttonBluePick.Enabled.Value = enabled || pickColour == TeamColour.Blue && pickType == ChoiceType.Pick; + buttonRedBan.Colour = setColour(pickColour == TeamColour.Red && pickType == ChoiceType.Ban); + buttonBlueBan.Colour = setColour(pickColour == TeamColour.Blue && pickType == ChoiceType.Ban); + buttonRedPick.Colour = setColour(pickColour == TeamColour.Red && pickType == ChoiceType.Pick); + buttonBluePick.Colour = setColour(pickColour == TeamColour.Blue && pickType == ChoiceType.Pick); } private void setNextMode() @@ -141,6 +149,12 @@ namespace osu.Game.Tournament.Screens.MapPool return base.OnMouseDown(e); } + private void reset() + { + currentMatch.Value.PicksBans.Clear(); + setNextMode(); + } + private void addForBeatmap(int beatmapId) { if (currentMatch.Value.Grouping.Value.Beatmaps.All(b => b.BeatmapInfo.OnlineBeatmapID != beatmapId)) From a31507ff0e87443888faeb393d2c5a3266a96856 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Nov 2018 13:08:59 +0900 Subject: [PATCH 0238/5608] Safety check --- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index be56869115..c7bdf8feee 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -157,6 +157,9 @@ namespace osu.Game.Tournament.Screens.MapPool private void addForBeatmap(int beatmapId) { + if (currentMatch.Value == null) + return; + if (currentMatch.Value.Grouping.Value.Beatmaps.All(b => b.BeatmapInfo.OnlineBeatmapID != beatmapId)) // don't attempt to add if the beatmap isn't in our pool return; From 6ff29c1ea4fbed864489d00be08aa6c03e7a31ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Nov 2018 16:55:55 +0900 Subject: [PATCH 0239/5608] Fix non-unbinding bindable bind --- osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index d515312dd0..7c4f139de7 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Video; @@ -21,11 +22,10 @@ namespace osu.Game.Tournament.Screens.TeamIntro { private Container mainContainer; - [Resolved] - private LadderInfo ladderInfo { get; set; } + private readonly Bindable currentMatch = new Bindable(); [BackgroundDependencyLoader] - private void load(Storage storage) + private void load(LadderInfo ladder, Storage storage) { RelativeSizeAxes = Axes.Both; @@ -42,7 +42,8 @@ namespace osu.Game.Tournament.Screens.TeamIntro } }; - ladderInfo.CurrentMatch.BindValueChanged(matchChanged, true); + currentMatch.BindValueChanged(matchChanged); + currentMatch.BindTo(ladder.CurrentMatch); } private void matchChanged(MatchPairing pairing) From ee6263f3956ab5b96c48b0801d32911502338fc2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Nov 2018 20:14:50 +0900 Subject: [PATCH 0240/5608] Fix old maps not getting cleared when switching matches --- .../Screens/MapPool/MapPoolScreen.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index c7bdf8feee..e8d6f18fd7 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -180,12 +180,17 @@ namespace osu.Game.Tournament.Screens.MapPool private void matchChanged(MatchPairing match) { - foreach (var b in match.Grouping.Value.Beatmaps) - maps.Add(new TournamentBeatmapPanel(b.BeatmapInfo) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - }); + maps.Clear(); + + if (match.Grouping.Value != null) + { + foreach (var b in match.Grouping.Value.Beatmaps) + maps.Add(new TournamentBeatmapPanel(b.BeatmapInfo) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }); + } } } } From 0003a9310f809ad3a1fa2d3fcdfc2bcf48d50d20 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Nov 2018 20:15:08 +0900 Subject: [PATCH 0241/5608] Expose LargeTextureStore --- osu.Game/OsuGameBase.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index ea1dbfa369..c7f787cff1 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -110,9 +110,9 @@ namespace osu.Game dependencies.Cache(contextFactory = new DatabaseContextFactory(Host.Storage)); - var largeStore = new LargeTextureStore(new TextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures"))); - largeStore.AddStore(new TextureLoaderStore(new OnlineStore())); - dependencies.Cache(largeStore); + LargeTextureStore = new LargeTextureStore(new TextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures"))); + LargeTextureStore.AddStore(new TextureLoaderStore(new OnlineStore())); + dependencies.Cache(LargeTextureStore); dependencies.CacheAs(this); dependencies.Cache(LocalConfig); @@ -243,6 +243,8 @@ namespace osu.Game private readonly List fileImporters = new List(); + protected LargeTextureStore LargeTextureStore; + public void Import(params string[] paths) { var extension = Path.GetExtension(paths.First())?.ToLowerInvariant(); From 160984719d31ac5ab87829f4921f6f4ab5933432 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Nov 2018 20:15:22 +0900 Subject: [PATCH 0242/5608] Add team and star displays --- .../Screens/Drawings/DrawingsScreen.cs | 14 -- .../Screens/Gameplay/GameplayScreen.cs | 208 ++++++++++++++++++ osu.Game.Tournament/TournamentGameBase.cs | 4 +- 3 files changed, 211 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index f94c882c85..0e146cb15a 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Graphics; @@ -47,11 +46,6 @@ namespace osu.Game.Tournament.Screens.Drawings public ITeamList TeamList; - private DependencyContainer dependencies; - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => - dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - [BackgroundDependencyLoader] private void load(TextureStore textures, Storage storage) { @@ -59,14 +53,6 @@ namespace osu.Game.Tournament.Screens.Drawings this.storage = storage; - TextureStore flagStore = new TextureStore(); - // Local flag store - flagStore.AddStore(new TextureLoaderStore(new NamespacedResourceStore(new StorageBackedResourceStore(storage), "Drawings"))); - // Default texture store - flagStore.AddStore(textures); - - dependencies.Cache(flagStore); - if (TeamList == null) TeamList = new StorageBackedTeamList(storage); diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 2a9754b066..9f46776a6d 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -1,10 +1,218 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Logging; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK; +using OpenTK.Graphics; + namespace osu.Game.Tournament.Screens.Gameplay { public class GameplayScreen : BeatmapInfoScreen { + [BackgroundDependencyLoader] + private void load(LadderInfo ladder, TextureStore textures) + { + Add(new Container + { + RelativeSizeAxes = Axes.X, + Height = 100, + Children = new Drawable[] + { + new Sprite + { + Y = 5, + Texture = textures.Get("game-screen-logo"), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + FillMode = FillMode.Fit, + RelativeSizeAxes = Axes.Both, + Size = Vector2.One + }, + new RoundDisplay + { + Y = 10, + Anchor = Anchor.BottomCentre, + Origin = Anchor.TopCentre, + }, + new TeamScoreDisplay(TeamColour.Red) + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }, + new TeamScoreDisplay(TeamColour.Blue) + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + } + }, + }); + } + private class TeamScoreDisplay : CompositeDrawable + { + private readonly TeamColour teamColour; + + private readonly Color4 red = new Color4(129, 68, 65, 255); + private readonly Color4 blue = new Color4(41, 91, 97, 255); + + private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentTeam = new Bindable(); + private readonly Bindable currentTeamScore = new Bindable(); + + public TeamScoreDisplay(TeamColour teamColour) + { + this.teamColour = teamColour; + + RelativeSizeAxes = Axes.Y; + Width = 300; + } + + [BackgroundDependencyLoader] + private void load(LadderInfo ladder) + { + currentMatch.BindValueChanged(matchChanged); + currentMatch.BindTo(ladder.CurrentMatch); + } + + private void matchChanged(MatchPairing match) + { + currentTeamScore.UnbindBindings(); + currentTeamScore.BindTo(teamColour == TeamColour.Red ? match.Team1Score : match.Team2Score); + + currentTeam.UnbindBindings(); + currentTeam.BindTo(teamColour == TeamColour.Red ? match.Team1 : match.Team2); + + // team may change to same team, which means score is not in a good state. + // thus we handle this manually. + teamChanged(currentTeam.Value); + } + + private void teamChanged(TournamentTeam team) + { + InternalChildren = new Drawable[] + { + new TeamDisplay(team, teamColour == TeamColour.Red ? red : blue, teamColour != TeamColour.Red), + new ScoreDisplay(currentTeamScore, teamColour != TeamColour.Red, currentMatch.Value.Grouping.Value.BestOf / 2 + 1) + }; + } + } + + private class ScoreDisplay : CompositeDrawable + { + private readonly Bindable currentTeamScore = new Bindable(); + private readonly StarCounter counter; + + public ScoreDisplay(Bindable score, bool flip, int count) + { + var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft; + + Anchor = anchor; + Origin = anchor; + + InternalChild = counter = new StarCounter(count) + { + Anchor = anchor, + X = (flip ? -1 : 1) * 90, + Y = 5, + Scale = flip ? new Vector2(-1, 1) : Vector2.One, + Colour = new Color4(95, 41, 60, 255), + }; + + currentTeamScore.BindValueChanged(scoreChanged); + currentTeamScore.BindTo(score); + } + + private void scoreChanged(int? score) => counter.CountStars = score ?? 0; + } + + private class TeamDisplay : DrawableTournamentTeam + { + public TeamDisplay(TournamentTeam team, Color4 colour, bool flip) + : base(team) + { + RelativeSizeAxes = Axes.Both; + + var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft; + + Anchor = Origin = anchor; + + Flag.Anchor = Flag.Origin = anchor; + Flag.RelativeSizeAxes = Axes.None; + Flag.Size = new Vector2(60, 40); + Flag.Margin = new MarginPadding(20); + + InternalChild = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + Flag, + new OsuSpriteText + { + Text = team?.FullName.ToUpper() ?? "???", + X = (flip ? -1 : 1) * 90, + Y = -10, + TextSize = 20, + Colour = colour, + Font = "Aquatico-Regular", + Origin = anchor, + Anchor = anchor, + }, + } + }; + } + } + + private class RoundDisplay : CompositeDrawable + { + private readonly Bindable currentMatch = new Bindable(); + + public RoundDisplay() + { + CornerRadius = 10; + Masking = true; + Width = 200; + Height = 20; + } + + [BackgroundDependencyLoader] + private void load(LadderInfo ladder) + { + currentMatch.BindValueChanged(matchChanged); + currentMatch.BindTo(ladder.CurrentMatch); + } + + private void matchChanged(MatchPairing match) + { + InternalChildren = new Drawable[] + { + new Box + { + Colour = new Color4(95, 41, 60, 255), + RelativeSizeAxes = Axes.Both, + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = Color4.White, + Text = match.Grouping.Value?.Name.Value ?? "Unknown Grouping", + Font = "Aquatico-Regular", + TextSize = 18, + }, + }; + } + }; } } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 562b141095..df93c42d98 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -10,6 +10,7 @@ using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Game.Beatmaps; @@ -49,6 +50,8 @@ namespace osu.Game.Tournament Fonts.AddStore(new GlyphStore(Resources, @"Resources/Fonts/Aquatico-Regular")); Fonts.AddStore(new GlyphStore(Resources, @"Resources/Fonts/Aquatico-Light")); + Textures.AddStore(new TextureLoaderStore(new ResourceStore(new StorageBackedResourceStore(storage)))); + this.storage = storage; windowSize = frameworkConfig.GetBindable(FrameworkSetting.WindowedSize); @@ -125,7 +128,6 @@ namespace osu.Game.Tournament addedInfo = true; } - List countries; using (Stream stream = Resources.GetStream("Resources/countries.json")) using (var sr = new StreamReader(stream)) From 0be2f5ac94722fd03eb6e2e63298b1000f03b74e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Nov 2018 16:10:58 +0900 Subject: [PATCH 0243/5608] Add non-working warmup toggle button --- .../Screens/Gameplay/GameplayScreen.cs | 79 ++++++++++++------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 9f46776a6d..107b8f2736 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Logging; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; @@ -20,45 +19,67 @@ namespace osu.Game.Tournament.Screens.Gameplay { public class GameplayScreen : BeatmapInfoScreen { + private BindableBool warmup = new BindableBool(); + [BackgroundDependencyLoader] private void load(LadderInfo ladder, TextureStore textures) { - Add(new Container + AddRange(new Drawable[] { - RelativeSizeAxes = Axes.X, - Height = 100, - Children = new Drawable[] + new Container { - new Sprite + RelativeSizeAxes = Axes.X, + Height = 100, + Children = new Drawable[] { - Y = 5, - Texture = textures.Get("game-screen-logo"), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - FillMode = FillMode.Fit, - RelativeSizeAxes = Axes.Both, - Size = Vector2.One + new Sprite + { + Y = 5, + Texture = textures.Get("game-screen-logo"), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + FillMode = FillMode.Fit, + RelativeSizeAxes = Axes.Both, + Size = Vector2.One + }, + new RoundDisplay + { + Y = 10, + Anchor = Anchor.BottomCentre, + Origin = Anchor.TopCentre, + }, + new TeamScoreDisplay(TeamColour.Red) + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }, + new TeamScoreDisplay(TeamColour.Blue) + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }, }, - new RoundDisplay - { - Y = 10, - Anchor = Anchor.BottomCentre, - Origin = Anchor.TopCentre, - }, - new TeamScoreDisplay(TeamColour.Red) - { - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - }, - new TeamScoreDisplay(TeamColour.Blue) - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - } }, + new ControlPanel + { + Children = new Drawable[] + { + new TriangleButton + { + RelativeSizeAxes = Axes.X, + Text = "Toggle warmup", + Action = toggleWarmup + } + } + } }); } + private void toggleWarmup() + { + warmup.Toggle(); + } + private class TeamScoreDisplay : CompositeDrawable { private readonly TeamColour teamColour; From 1c6c59864486c863649b11126ce83ea0fa5c6bdc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Nov 2018 16:11:12 +0900 Subject: [PATCH 0244/5608] Fill out username from user ids, rather than user ids from user ids --- osu.Game.Tournament/TournamentGameBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index df93c42d98..416be35456 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -107,7 +107,7 @@ namespace osu.Game.Tournament // add full player info based on user IDs foreach (var t in Ladder.Teams) foreach (var p in t.Players) - if (p.Id == 1) + if (string.IsNullOrEmpty(p.Username)) { var req = new GetUserRequest(p.Id); req.Success += i => p.Username = i.Username; From 66dc7d6b0285b90184eab24c3bd2eb4ea7ed4901 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Nov 2018 16:26:09 +0900 Subject: [PATCH 0245/5608] Fix debug tools not working --- osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs | 2 +- osu.Game.Tournament/TournamentGameBase.cs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 107b8f2736..2d3ed89b97 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tournament.Screens.Gameplay { public class GameplayScreen : BeatmapInfoScreen { - private BindableBool warmup = new BindableBool(); + private readonly BindableBool warmup = new BindableBool(); [BackgroundDependencyLoader] private void load(LadderInfo ladder, TextureStore textures) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 416be35456..28136a6394 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -163,6 +163,7 @@ namespace osu.Game.Tournament protected override void LoadComplete() { MenuCursorContainer.Cursor.Alpha = 0; + base.LoadComplete(); } protected override void Update() From 8a917e4cc7f137cf883b316e16c389507969c7c9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Nov 2018 16:57:45 +0900 Subject: [PATCH 0246/5608] Fix context menus (temporarily) --- osu.Game.Tournament/Screens/Ladder/LadderManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 805358e231..9e43cffc72 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -255,6 +255,9 @@ namespace osu.Game.Tournament.Screens.Ladder } } + // todo: remove after ppy/osu-framework#1980 is merged. + public override bool HandlePositionalInput => true; + public void Remove(MatchPairing pairing) => pairingsContainer.FirstOrDefault(p => p.Pairing == pairing)?.Remove(); public void SetCurrent(MatchPairing pairing) From 9064f3fe0f0477affaba7bc378ada4116c6b6dd1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Nov 2018 17:39:46 +0900 Subject: [PATCH 0247/5608] Fix ladder manager not saving changes out correctly --- .../TestCaseLadderManager.cs | 16 +--- .../Ladder/Components/LadderEditorInfo.cs | 4 - .../Ladder/Components/LadderEditorSettings.cs | 7 +- .../Screens/Ladder/LadderManager.cs | 84 +++++++++---------- 4 files changed, 46 insertions(+), 65 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index 3ddd52eeac..63c8f5e391 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -10,28 +10,14 @@ namespace osu.Game.Tournament.Tests { public class TestCaseLadderManager : LadderTestCase { - private LadderManager manager; - [BackgroundDependencyLoader] private void load() { Add(new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - Child = manager = new LadderManager() + Child = new LadderManager() }); } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - var newInfo = manager.CreateInfo(); - - Ladder.Teams = newInfo.Teams; - Ladder.Groupings = newInfo.Groupings; - Ladder.Pairings = newInfo.Pairings; - Ladder.Progressions = newInfo.Progressions; - } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs index cc91c98188..0ecf387f7c 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs @@ -1,17 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Framework.Configuration; -using osu.Game.Tournament.Components; namespace osu.Game.Tournament.Screens.Ladder.Components { public class LadderEditorInfo { public readonly BindableBool EditingEnabled = new BindableBool(); - public List Teams = new List(); - public List Groupings = new List(); public readonly Bindable Selected = new Bindable(); } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index d7b827237a..3fa7fdf7e8 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -28,12 +28,15 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [Resolved] private LadderEditorInfo editorInfo { get; set; } + [Resolved] + private LadderInfo ladderInfo { get; set; } + [BackgroundDependencyLoader] private void load() { - var teamEntries = editorInfo.Teams; + var teamEntries = ladderInfo.Teams; - var groupingOptions = editorInfo.Groupings.Select(g => new KeyValuePair(g.Name, g)) + var groupingOptions = ladderInfo.Groupings.Select(g => new KeyValuePair(g.Name, g)) .Prepend(new KeyValuePair("None", new TournamentGrouping())); Children = new Drawable[] diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 9e43cffc72..5ef7d047e2 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Caching; @@ -15,7 +15,6 @@ using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; -using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; using OpenTK; using OpenTK.Graphics; @@ -26,28 +25,24 @@ namespace osu.Game.Tournament.Screens.Ladder [Cached] public class LadderManager : CompositeDrawable, IHasContextMenu { - public List Teams; private Container pairingsContainer; private Container paths; private Container headings; - private LadderInfo info; - private ScrollableContainer scrollContent; [Cached] private LadderEditorInfo editorInfo = new LadderEditorInfo(); + [Resolved] + private LadderInfo ladderInfo { get; set; } + [BackgroundDependencyLoader] - private void load(LadderInfo info, OsuColour colours) + private void load(OsuColour colours) { normalPathColour = colours.BlueDarker.Darken(2); losersPathColour = colours.YellowDarker.Darken(2); - this.info = info; - editorInfo.Teams = Teams = info.Teams; - editorInfo.Groupings = info.Groupings; - RelativeSizeAxes = Axes.Both; InternalChild = new Container @@ -74,32 +69,29 @@ namespace osu.Game.Tournament.Screens.Ladder } }; - foreach (var pairing in info.Pairings) + foreach (var pairing in ladderInfo.Pairings) addPairing(pairing); // todo: fix this Scheduler.AddDelayed(() => layout.Invalidate(), 100, true); } - public LadderInfo CreateInfo() + private void updateInfo() { - var pairings = pairingsContainer.Select(p => p.Pairing).ToList(); + ladderInfo.Pairings = pairingsContainer.Select(p => p.Pairing).ToList(); + foreach (var g in ladderInfo.Groupings) + g.Pairings = ladderInfo.Pairings.Where(p => p.Grouping.Value == g).Select(p => p.ID).ToList(); - foreach (var g in editorInfo.Groupings) - g.Pairings = pairings.Where(p => p.Grouping.Value == g).Select(p => p.ID).ToList(); - - return new LadderInfo - { - Pairings = pairings, - Progressions = pairings.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( - pairings.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) - .ToList(), - Teams = editorInfo.Teams, - Groupings = editorInfo.Groupings - }; + ladderInfo.Progressions = ladderInfo.Pairings.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( + ladderInfo.Pairings.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) + .ToList(); } - private void addPairing(MatchPairing pairing) => pairingsContainer.Add(new DrawableMatchPairing(pairing)); + private void addPairing(MatchPairing pairing) + { + pairingsContainer.Add(new DrawableMatchPairing(pairing)); + updateInfo(); + } public MenuItem[] ContextMenuItems { @@ -154,7 +146,7 @@ namespace osu.Game.Tournament.Screens.Ladder } } - foreach (var group in editorInfo.Groupings) + foreach (var group in ladderInfo.Groupings) { var topPairing = pairingsContainer.Where(p => !p.Pairing.Losers && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); @@ -168,7 +160,7 @@ namespace osu.Game.Tournament.Screens.Ladder }); } - foreach (var group in editorInfo.Groupings) + foreach (var group in ladderInfo.Groupings) { var topPairing = pairingsContainer.Where(p => p.Pairing.Losers && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); @@ -183,25 +175,42 @@ namespace osu.Game.Tournament.Screens.Ladder } layout.Validate(); + updateInfo(); } - public void RequestJoin(MatchPairing pairing, bool losers) => scrollContent.Add(new JoinRequestHandler(pairingsContainer, pairing, losers)); + public void RequestJoin(MatchPairing pairing, bool losers) => scrollContent.Add(new JoinRequestHandler(pairingsContainer, pairing, losers, updateInfo)); + + // todo: remove after ppy/osu-framework#1980 is merged. + public override bool HandlePositionalInput => true; + + public void Remove(MatchPairing pairing) => pairingsContainer.FirstOrDefault(p => p.Pairing == pairing)?.Remove(); + + public void SetCurrent(MatchPairing pairing) + { + if (ladderInfo.CurrentMatch.Value != null) + ladderInfo.CurrentMatch.Value.Current.Value = false; + + ladderInfo.CurrentMatch.Value = pairing; + ladderInfo.CurrentMatch.Value.Current.Value = true; + } private class JoinRequestHandler : CompositeDrawable { private readonly Container pairingsContainer; public readonly MatchPairing Source; private readonly bool losers; + private readonly Action complete; private ProgressionPath path; - public JoinRequestHandler(Container pairingsContainer, MatchPairing source, bool losers) + public JoinRequestHandler(Container pairingsContainer, MatchPairing source, bool losers, Action complete) { this.pairingsContainer = pairingsContainer; RelativeSizeAxes = Axes.Both; Source = source; this.losers = losers; + this.complete = complete; if (losers) Source.LosersProgression.Value = null; else @@ -247,6 +256,7 @@ namespace osu.Game.Tournament.Screens.Ladder Source.Progression.Value = found.Pairing; } + complete?.Invoke(); Expire(); return true; } @@ -254,19 +264,5 @@ namespace osu.Game.Tournament.Screens.Ladder return false; } } - - // todo: remove after ppy/osu-framework#1980 is merged. - public override bool HandlePositionalInput => true; - - public void Remove(MatchPairing pairing) => pairingsContainer.FirstOrDefault(p => p.Pairing == pairing)?.Remove(); - - public void SetCurrent(MatchPairing pairing) - { - if (info.CurrentMatch.Value != null) - info.CurrentMatch.Value.Current.Value = false; - - info.CurrentMatch.Value = pairing; - info.CurrentMatch.Value.Current.Value = true; - } } } From e170372932a14153ab2b41973af592038982d638 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Nov 2018 17:54:05 +0900 Subject: [PATCH 0248/5608] Populate json with enums better --- .../Screens/Ladder/Components/BeatmapChoice.cs | 9 +++++++++ osu.Game.Tournament/TournamentGameBase.cs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs b/osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs index d0b2556603..5b38e539c6 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs @@ -1,21 +1,30 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + namespace osu.Game.Tournament.Screens.Ladder.Components { public class BeatmapChoice { + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] public TeamColour Team; + + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] public ChoiceType Type; + public int BeatmapID; } + [JsonConverter(typeof(StringEnumConverter))] public enum TeamColour { Red, Blue } + [JsonConverter(typeof(StringEnumConverter))] public enum ChoiceType { Pick, diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 28136a6394..70868d398e 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -186,7 +186,7 @@ namespace osu.Game.Tournament new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore + DefaultValueHandling = DefaultValueHandling.Ignore, })); } } From 1756ef95cbb520557b90991a4ee93684dd53232a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 10 Nov 2018 07:31:06 +0900 Subject: [PATCH 0249/5608] Add ability to adjust scores from gameplay screen --- .../Screens/Gameplay/GameplayScreen.cs | 22 ++++++++++++++++++- .../Screens/Ladder/Components/MatchPairing.cs | 2 ++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 2d3ed89b97..5593824e55 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -8,12 +8,14 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Input.Events; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; using OpenTK; using OpenTK.Graphics; +using OpenTK.Input; namespace osu.Game.Tournament.Screens.Gameplay { @@ -119,12 +121,30 @@ namespace osu.Game.Tournament.Screens.Gameplay teamChanged(currentTeam.Value); } + + protected override bool OnMouseDown(MouseDownEvent e) + { + switch (e.Button) + { + case MouseButton.Left: + if (currentTeamScore.Value < currentMatch.Value.PointsToWin) + currentTeamScore.Value++; + return true; + case MouseButton.Right: + if (currentTeamScore.Value > 0) + currentTeamScore.Value--; + return true; + } + + return base.OnMouseDown(e); + } + private void teamChanged(TournamentTeam team) { InternalChildren = new Drawable[] { new TeamDisplay(team, teamColour == TeamColour.Red ? red : blue, teamColour != TeamColour.Red), - new ScoreDisplay(currentTeamScore, teamColour != TeamColour.Red, currentMatch.Value.Grouping.Value.BestOf / 2 + 1) + new ScoreDisplay(currentTeamScore, teamColour != TeamColour.Red, currentMatch.Value.PointsToWin) }; } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index 63c96d350d..729249c3d7 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -74,6 +74,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [JsonIgnore] public TournamentTeam Loser => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team2.Value : Team1.Value; + public int PointsToWin => Grouping.Value.BestOf / 2 + 1; + /// /// Remove scores from the match, in case of a false click or false start. /// From 82d53e6f17e7675c5a54a4371a0d338d27b586d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 10 Nov 2018 08:37:21 +0900 Subject: [PATCH 0250/5608] Fix many unnecessary requests being fired --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index c42ccc11c2..a6e171b699 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -27,6 +27,8 @@ namespace osu.Game.Tournament.IPC public readonly Bindable Mods = new Bindable(); + private int lastBeatmapId; + [BackgroundDependencyLoader] private void load() { @@ -45,8 +47,9 @@ namespace osu.Game.Tournament.IPC var beatmapId = int.Parse(sr.ReadLine()); var mods = int.Parse(sr.ReadLine()); - if (Beatmap.Value?.OnlineBeatmapID != beatmapId) + if (lastBeatmapId != beatmapId) { + lastBeatmapId = beatmapId; var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); req.Success += b => Beatmap.Value = b.ToBeatmap(Rulesets); API.Queue(req); From 86aab9c31b480e656c06305639c30ed73a7c59ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 10 Nov 2018 08:54:56 +0900 Subject: [PATCH 0251/5608] Fix chat making needless requests --- osu.Game/Overlays/ChatOverlay.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index ff2ff9af14..65d5371130 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -393,10 +393,10 @@ namespace osu.Game.Overlays api.Queue(req); return; } - } - // let's fetch a small number of messages to bring us up-to-date with the backlog. - fetchInitialMessages(channel); + // let's fetch a small number of messages to bring us up-to-date with the backlog. + fetchInitialMessages(channel); + } if (CurrentChannel == null) CurrentChannel = channel; From 713038bff88c9a24e6c5d13cab6a4d87c2516568 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 10 Nov 2018 17:26:21 +0900 Subject: [PATCH 0252/5608] Share header area between screens --- .../Screens/Gameplay/GameplayScreen.cs | 224 +---------------- .../Screens/Gameplay/MatchHeader.cs | 234 ++++++++++++++++++ .../Screens/MapPool/MapPoolScreen.cs | 5 +- 3 files changed, 245 insertions(+), 218 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 5593824e55..8b87d6d581 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -4,18 +4,9 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Input.Events; -using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; -using osu.Game.Tournament.Screens.Ladder.Components; -using OpenTK; -using OpenTK.Graphics; -using OpenTK.Input; namespace osu.Game.Tournament.Screens.Gameplay { @@ -28,40 +19,13 @@ namespace osu.Game.Tournament.Screens.Gameplay { AddRange(new Drawable[] { - new Container - { - RelativeSizeAxes = Axes.X, - Height = 100, - Children = new Drawable[] - { - new Sprite - { - Y = 5, - Texture = textures.Get("game-screen-logo"), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - FillMode = FillMode.Fit, - RelativeSizeAxes = Axes.Both, - Size = Vector2.One - }, - new RoundDisplay - { - Y = 10, - Anchor = Anchor.BottomCentre, - Origin = Anchor.TopCentre, - }, - new TeamScoreDisplay(TeamColour.Red) - { - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - }, - new TeamScoreDisplay(TeamColour.Blue) - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - }, - }, - }, + new MatchHeader(), + // new CustomChatOverlay + // { + // Anchor = Anchor.BottomCentre, + // Origin = Anchor.BottomCentre, + // Size = new Vector2(0.4f, 1) + // }, new ControlPanel { Children = new Drawable[] @@ -81,179 +45,5 @@ namespace osu.Game.Tournament.Screens.Gameplay { warmup.Toggle(); } - - private class TeamScoreDisplay : CompositeDrawable - { - private readonly TeamColour teamColour; - - private readonly Color4 red = new Color4(129, 68, 65, 255); - private readonly Color4 blue = new Color4(41, 91, 97, 255); - - private readonly Bindable currentMatch = new Bindable(); - private readonly Bindable currentTeam = new Bindable(); - private readonly Bindable currentTeamScore = new Bindable(); - - public TeamScoreDisplay(TeamColour teamColour) - { - this.teamColour = teamColour; - - RelativeSizeAxes = Axes.Y; - Width = 300; - } - - [BackgroundDependencyLoader] - private void load(LadderInfo ladder) - { - currentMatch.BindValueChanged(matchChanged); - currentMatch.BindTo(ladder.CurrentMatch); - } - - private void matchChanged(MatchPairing match) - { - currentTeamScore.UnbindBindings(); - currentTeamScore.BindTo(teamColour == TeamColour.Red ? match.Team1Score : match.Team2Score); - - currentTeam.UnbindBindings(); - currentTeam.BindTo(teamColour == TeamColour.Red ? match.Team1 : match.Team2); - - // team may change to same team, which means score is not in a good state. - // thus we handle this manually. - teamChanged(currentTeam.Value); - } - - - protected override bool OnMouseDown(MouseDownEvent e) - { - switch (e.Button) - { - case MouseButton.Left: - if (currentTeamScore.Value < currentMatch.Value.PointsToWin) - currentTeamScore.Value++; - return true; - case MouseButton.Right: - if (currentTeamScore.Value > 0) - currentTeamScore.Value--; - return true; - } - - return base.OnMouseDown(e); - } - - private void teamChanged(TournamentTeam team) - { - InternalChildren = new Drawable[] - { - new TeamDisplay(team, teamColour == TeamColour.Red ? red : blue, teamColour != TeamColour.Red), - new ScoreDisplay(currentTeamScore, teamColour != TeamColour.Red, currentMatch.Value.PointsToWin) - }; - } - } - - private class ScoreDisplay : CompositeDrawable - { - private readonly Bindable currentTeamScore = new Bindable(); - private readonly StarCounter counter; - - public ScoreDisplay(Bindable score, bool flip, int count) - { - var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft; - - Anchor = anchor; - Origin = anchor; - - InternalChild = counter = new StarCounter(count) - { - Anchor = anchor, - X = (flip ? -1 : 1) * 90, - Y = 5, - Scale = flip ? new Vector2(-1, 1) : Vector2.One, - Colour = new Color4(95, 41, 60, 255), - }; - - currentTeamScore.BindValueChanged(scoreChanged); - currentTeamScore.BindTo(score); - } - - private void scoreChanged(int? score) => counter.CountStars = score ?? 0; - } - - private class TeamDisplay : DrawableTournamentTeam - { - public TeamDisplay(TournamentTeam team, Color4 colour, bool flip) - : base(team) - { - RelativeSizeAxes = Axes.Both; - - var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft; - - Anchor = Origin = anchor; - - Flag.Anchor = Flag.Origin = anchor; - Flag.RelativeSizeAxes = Axes.None; - Flag.Size = new Vector2(60, 40); - Flag.Margin = new MarginPadding(20); - - InternalChild = new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - Flag, - new OsuSpriteText - { - Text = team?.FullName.ToUpper() ?? "???", - X = (flip ? -1 : 1) * 90, - Y = -10, - TextSize = 20, - Colour = colour, - Font = "Aquatico-Regular", - Origin = anchor, - Anchor = anchor, - }, - } - }; - } - } - - private class RoundDisplay : CompositeDrawable - { - private readonly Bindable currentMatch = new Bindable(); - - public RoundDisplay() - { - CornerRadius = 10; - Masking = true; - Width = 200; - Height = 20; - } - - [BackgroundDependencyLoader] - private void load(LadderInfo ladder) - { - currentMatch.BindValueChanged(matchChanged); - currentMatch.BindTo(ladder.CurrentMatch); - } - - private void matchChanged(MatchPairing match) - { - InternalChildren = new Drawable[] - { - new Box - { - Colour = new Color4(95, 41, 60, 255), - RelativeSizeAxes = Axes.Both, - }, - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Colour = Color4.White, - Text = match.Grouping.Value?.Name.Value ?? "Unknown Grouping", - Font = "Aquatico-Regular", - TextSize = 18, - }, - }; - } - }; } } diff --git a/osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs new file mode 100644 index 0000000000..2ff5ee7bf6 --- /dev/null +++ b/osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs @@ -0,0 +1,234 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Input; + +namespace osu.Game.Tournament.Screens.Gameplay +{ + public class MatchHeader : Container + { + [BackgroundDependencyLoader] + private void load(LadderInfo ladder, TextureStore textures) + { + RelativeSizeAxes = Axes.X; + Height = 100; + Children = new Drawable[] + { + new Sprite + { + Y = 5, + Texture = textures.Get("game-screen-logo"), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + FillMode = FillMode.Fit, + RelativeSizeAxes = Axes.Both, + Size = Vector2.One + }, + new RoundDisplay + { + Y = 10, + Anchor = Anchor.BottomCentre, + Origin = Anchor.TopCentre, + }, + new TeamScoreDisplay(TeamColour.Red) + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }, + new TeamScoreDisplay(TeamColour.Blue) + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }, + }; + } + + private class TeamScoreDisplay : CompositeDrawable + { + private readonly TeamColour teamColour; + + private readonly Color4 red = new Color4(129, 68, 65, 255); + private readonly Color4 blue = new Color4(41, 91, 97, 255); + + private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentTeam = new Bindable(); + private readonly Bindable currentTeamScore = new Bindable(); + + public TeamScoreDisplay(TeamColour teamColour) + { + this.teamColour = teamColour; + + RelativeSizeAxes = Axes.Y; + Width = 300; + } + + [BackgroundDependencyLoader] + private void load(LadderInfo ladder) + { + currentMatch.BindValueChanged(matchChanged); + currentMatch.BindTo(ladder.CurrentMatch); + } + + private void matchChanged(MatchPairing match) + { + currentTeamScore.UnbindBindings(); + currentTeamScore.BindTo(teamColour == TeamColour.Red ? match.Team1Score : match.Team2Score); + + currentTeam.UnbindBindings(); + currentTeam.BindTo(teamColour == TeamColour.Red ? match.Team1 : match.Team2); + + // team may change to same team, which means score is not in a good state. + // thus we handle this manually. + teamChanged(currentTeam.Value); + } + + + protected override bool OnMouseDown(MouseDownEvent e) + { + switch (e.Button) + { + case MouseButton.Left: + if (currentTeamScore.Value < currentMatch.Value.PointsToWin) + currentTeamScore.Value++; + return true; + case MouseButton.Right: + if (currentTeamScore.Value > 0) + currentTeamScore.Value--; + return true; + } + + return base.OnMouseDown(e); + } + + private void teamChanged(TournamentTeam team) + { + InternalChildren = new Drawable[] + { + new TeamDisplay(team, teamColour == TeamColour.Red ? red : blue, teamColour != TeamColour.Red), + new ScoreDisplay(currentTeamScore, teamColour != TeamColour.Red, currentMatch.Value.PointsToWin) + }; + } + } + + private class ScoreDisplay : CompositeDrawable + { + private readonly Bindable currentTeamScore = new Bindable(); + private readonly StarCounter counter; + + public ScoreDisplay(Bindable score, bool flip, int count) + { + var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft; + + Anchor = anchor; + Origin = anchor; + + InternalChild = counter = new StarCounter(count) + { + Anchor = anchor, + X = (flip ? -1 : 1) * 90, + Y = 5, + Scale = flip ? new Vector2(-1, 1) : Vector2.One, + Colour = new Color4(95, 41, 60, 255), + }; + + currentTeamScore.BindValueChanged(scoreChanged); + currentTeamScore.BindTo(score); + } + + private void scoreChanged(int? score) => counter.CountStars = score ?? 0; + } + + private class TeamDisplay : DrawableTournamentTeam + { + public TeamDisplay(TournamentTeam team, Color4 colour, bool flip) + : base(team) + { + RelativeSizeAxes = Axes.Both; + + var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft; + + Anchor = Origin = anchor; + + Flag.Anchor = Flag.Origin = anchor; + Flag.RelativeSizeAxes = Axes.None; + Flag.Size = new Vector2(60, 40); + Flag.Margin = new MarginPadding(20); + + InternalChild = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + Flag, + new OsuSpriteText + { + Text = team?.FullName.ToUpper() ?? "???", + X = (flip ? -1 : 1) * 90, + Y = -10, + TextSize = 20, + Colour = colour, + Font = "Aquatico-Regular", + Origin = anchor, + Anchor = anchor, + }, + } + }; + } + } + + private class RoundDisplay : CompositeDrawable + { + private readonly Bindable currentMatch = new Bindable(); + + public RoundDisplay() + { + CornerRadius = 10; + Masking = true; + Width = 200; + Height = 20; + } + + [BackgroundDependencyLoader] + private void load(LadderInfo ladder) + { + currentMatch.BindValueChanged(matchChanged); + currentMatch.BindTo(ladder.CurrentMatch); + } + + private void matchChanged(MatchPairing match) + { + InternalChildren = new Drawable[] + { + new Box + { + Colour = new Color4(95, 41, 60, 255), + RelativeSizeAxes = Axes.Both, + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = Color4.White, + Text = match.Grouping.Value?.Name.Value ?? "Unknown Grouping", + Font = "Aquatico-Regular", + TextSize = 18, + }, + }; + } + } + } +} diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index e8d6f18fd7..84c9e250c3 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -13,6 +13,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Screens; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Screens.Gameplay; using osu.Game.Tournament.Screens.Ladder.Components; using OpenTK; using OpenTK.Graphics; @@ -38,9 +39,11 @@ namespace osu.Game.Tournament.Screens.MapPool { InternalChildren = new Drawable[] { + new MatchHeader(), maps = new FillFlowContainer { - Spacing = new Vector2(20), + Y = 100, + Spacing = new Vector2(10), Padding = new MarginPadding(50), Direction = FillDirection.Full, RelativeSizeAxes = Axes.Both, From 629657044d4234db4781de304e8d2954d6327f17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Nov 2018 00:45:48 +0900 Subject: [PATCH 0253/5608] Add automatic scoring --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 86 ++++++++++++++++--- .../Screens/Gameplay/GameplayScreen.cs | 46 +++++++++- 2 files changed, 116 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index a6e171b699..168ff80eb7 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -6,6 +6,7 @@ using System.IO; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Framework.Logging; using osu.Framework.Platform.Windows; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; @@ -15,6 +16,15 @@ using osu.Game.Rulesets; namespace osu.Game.Tournament.IPC { + public enum TourneyState + { + Initialising, + Idle, + WaitingForClients, + Playing, + Ranking + } + public class FileBasedIPC : Component { [Resolved] @@ -27,7 +37,11 @@ namespace osu.Game.Tournament.IPC public readonly Bindable Mods = new Bindable(); + public readonly Bindable State = new Bindable(); + private int lastBeatmapId; + public int Score1; + public int Score2; [BackgroundDependencyLoader] private void load() @@ -35,6 +49,8 @@ namespace osu.Game.Tournament.IPC var stable = new StableStorage(); const string file_ipc_filename = "ipc.txt"; + const string file_ipc_state_filename = "ipc-state.txt"; + const string file_ipc_scores_filename = "ipc-scores.txt"; if (stable.Exists(file_ipc_filename)) Scheduler.AddDelayed(delegate @@ -62,6 +78,35 @@ namespace osu.Game.Tournament.IPC { // file might be in use. } + + try + { + using (var stream = stable.GetStream(file_ipc_state_filename)) + using (var sr = new StreamReader(stream)) + { + State.Value = (TourneyState)Enum.Parse(typeof(TourneyState), sr.ReadLine()); + } + } + catch (Exception e) + { + Logger.Log(e.ToString(), LoggingTarget.Runtime); + // file might be in use. + } + + try + { + using (var stream = stable.GetStream(file_ipc_scores_filename)) + using (var sr = new StreamReader(stream)) + { + Score1 = int.Parse(sr.ReadLine()); + Score2 = int.Parse(sr.ReadLine()); + } + } + catch (Exception e) + { + Logger.Log(e.ToString(), LoggingTarget.Runtime); + // file might be in use. + } }, 250, true); } @@ -72,33 +117,46 @@ namespace osu.Game.Tournament.IPC { protected override string LocateBasePath() { + bool checkExists(string p) { - return Directory.Exists(Path.Combine(p, "Songs")); + return File.Exists(Path.Combine(p, "ipc.txt")); } - string stableInstallPath; + string stableInstallPath = string.Empty; try { - stableInstallPath = "E:\\osu!mappool"; + try + { + stableInstallPath = "E:\\osu!tourney"; + if (checkExists(stableInstallPath)) + return stableInstallPath; + + stableInstallPath = "E:\\osu!mappool"; + + if (checkExists(stableInstallPath)) + return stableInstallPath; + } + catch + { + } + + stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); if (checkExists(stableInstallPath)) return stableInstallPath; + + stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu"); + if (checkExists(stableInstallPath)) + return stableInstallPath; + + return null; } - catch + finally { + Logger.Log($"Stable path for tourney usage: {stableInstallPath}"); } - - stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); - if (checkExists(stableInstallPath)) - return stableInstallPath; - - stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu"); - if (checkExists(stableInstallPath)) - return stableInstallPath; - - return null; } public StableStorage() diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 8b87d6d581..31c5e9f426 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -4,9 +4,13 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; +using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK.Graphics; namespace osu.Game.Tournament.Screens.Gameplay { @@ -14,9 +18,16 @@ namespace osu.Game.Tournament.Screens.Gameplay { private readonly BindableBool warmup = new BindableBool(); + private readonly Bindable currentMatch = new Bindable(); + + public readonly Bindable State = new Bindable(); + private TriangleButton warmupButton; + private FileBasedIPC ipc; + [BackgroundDependencyLoader] - private void load(LadderInfo ladder, TextureStore textures) + private void load(LadderInfo ladder, TextureStore textures, FileBasedIPC ipc) { + this.ipc = ipc; AddRange(new Drawable[] { new MatchHeader(), @@ -26,12 +37,21 @@ namespace osu.Game.Tournament.Screens.Gameplay // Origin = Anchor.BottomCentre, // Size = new Vector2(0.4f, 1) // }, + new Box + { + RelativeSizeAxes = Axes.Both, + Height = 720 / 1080f, + Colour = new Color4(0, 255, 0, 255), + Anchor = Anchor.Centre, + Origin= Anchor.Centre, + }, new ControlPanel { Children = new Drawable[] { - new TriangleButton + warmupButton = new TriangleButton { + Colour = Color4.Gray, RelativeSizeAxes = Axes.X, Text = "Toggle warmup", Action = toggleWarmup @@ -39,11 +59,33 @@ namespace osu.Game.Tournament.Screens.Gameplay } } }); + + State.BindValueChanged(stateChanged); + State.BindTo(ipc.State); + + currentMatch.BindTo(ladder.CurrentMatch); + } + + private void stateChanged(TourneyState state) + { + if (state == TourneyState.Ranking) + { + if (warmup.Value) return; + + if (ipc.Score1 > ipc.Score2) + currentMatch.Value.Team1Score.Value++; + else + currentMatch.Value.Team2Score.Value++; + } } private void toggleWarmup() { warmup.Toggle(); + if (warmup.Value) + warmupButton.Colour = Color4.White; + else + warmupButton.Colour = Color4.Gray; } } } From 976180ecc2e5ee6fcba20c01a543130fdd08e8b8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Nov 2018 00:48:22 +0900 Subject: [PATCH 0254/5608] Fix incorrect order after bans --- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 84c9e250c3..5a04640ed7 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -103,6 +103,9 @@ namespace osu.Game.Tournament.Screens.MapPool private void beatmapChanged(BeatmapInfo beatmap) { + if (currentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) < 2) + return; + if (beatmap.OnlineBeatmapID != null) addForBeatmap(beatmap.OnlineBeatmapID.Value); } @@ -126,7 +129,10 @@ namespace osu.Game.Tournament.Screens.MapPool var nextColour = (currentMatch.Value.PicksBans.LastOrDefault()?.Team ?? roll_winner) == TeamColour.Red ? TeamColour.Blue : TeamColour.Red; - setMode(nextColour, currentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) >= 2 ? ChoiceType.Pick : ChoiceType.Ban); + if (pickType == ChoiceType.Ban && currentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) >= 2) + setMode(pickColour, ChoiceType.Pick); + else + setMode(nextColour, currentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) >= 2 ? ChoiceType.Pick : ChoiceType.Ban); } protected override bool OnMouseDown(MouseDownEvent e) From 86423dce5fbaffc8a4f1c4555ea2ea889675f291 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Nov 2018 01:29:42 +0900 Subject: [PATCH 0255/5608] Animate song bar based on game mode --- osu.Game.Tournament/Components/SongBar.cs | 40 +++++++++++++++++-- osu.Game.Tournament/IPC/FileBasedIPC.cs | 6 +-- .../Screens/BeatmapInfoScreen.cs | 4 +- .../Screens/Gameplay/GameplayScreen.cs | 21 ++++++---- 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 880b80edf8..6d9dc6025f 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -11,6 +12,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Screens.Menu; using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Tournament.Components { @@ -44,6 +46,28 @@ namespace osu.Game.Tournament.Components } private Container panelContents; + private Container innerPanel; + private Container outerPanel; + + private const float main_width = 0.97f; + + public bool Expanded + { + set + { + if (value) + { + innerPanel.ResizeWidthTo(0.7f, 800, Easing.OutQuint); + outerPanel.ResizeWidthTo(main_width, 800, Easing.OutQuint); + } + else + { + innerPanel.ResizeWidthTo(1, 800, Easing.OutQuint); + outerPanel.ResizeWidthTo(0.3f, 800, Easing.OutQuint); + } + } + } + [BackgroundDependencyLoader] private void load() @@ -52,12 +76,20 @@ namespace osu.Game.Tournament.Components InternalChildren = new Drawable[] { - new Container + outerPanel = new Container { Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0.2f), + Type = EdgeEffectType.Shadow, + Radius = 5, + }, RelativeSizeAxes = Axes.X, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + RelativePositionAxes = Axes.X, + X = -(1 - main_width) / 2, Y = -10, Width = 0.95f, Height = TournamentBeatmapPanel.HEIGHT, @@ -69,7 +101,7 @@ namespace osu.Game.Tournament.Components RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.93f), }, - new Container + innerPanel = new Container { Masking = true, CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 168ff80eb7..2ad30db748 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -87,9 +87,8 @@ namespace osu.Game.Tournament.IPC State.Value = (TourneyState)Enum.Parse(typeof(TourneyState), sr.ReadLine()); } } - catch (Exception e) + catch (Exception) { - Logger.Log(e.ToString(), LoggingTarget.Runtime); // file might be in use. } @@ -102,9 +101,8 @@ namespace osu.Game.Tournament.IPC Score2 = int.Parse(sr.ReadLine()); } } - catch (Exception e) + catch (Exception) { - Logger.Log(e.ToString(), LoggingTarget.Runtime); // file might be in use. } }, 250, true); diff --git a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs index 11cbb56b49..4ddd475b6e 100644 --- a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs +++ b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs @@ -19,8 +19,8 @@ namespace osu.Game.Tournament.Screens { Add(SongBar = new SongBar { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, }); } diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 31c5e9f426..a89200f3a5 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -54,7 +54,7 @@ namespace osu.Game.Tournament.Screens.Gameplay Colour = Color4.Gray, RelativeSizeAxes = Axes.X, Text = "Toggle warmup", - Action = toggleWarmup + Action = () => warmup.Toggle() } } } @@ -64,6 +64,8 @@ namespace osu.Game.Tournament.Screens.Gameplay State.BindTo(ipc.State); currentMatch.BindTo(ladder.CurrentMatch); + + warmup.BindValueChanged(w => warmupButton.Colour = !w ? Color4.White : Color4.Gray, true); } private void stateChanged(TourneyState state) @@ -77,15 +79,18 @@ namespace osu.Game.Tournament.Screens.Gameplay else currentMatch.Value.Team2Score.Value++; } - } - private void toggleWarmup() - { - warmup.Toggle(); - if (warmup.Value) - warmupButton.Colour = Color4.White; + if (state == TourneyState.Idle) + { + // show chat + SongBar.Expanded = false; + } else - warmupButton.Colour = Color4.Gray; + { + SongBar.Expanded = true; + } + + } } } From b5c2d94cc4ee8b5b4e3e5ee858098a974dc4d424 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Nov 2018 01:39:02 +0900 Subject: [PATCH 0256/5608] Avoid rendering more than one video at once --- .../Screens/BeatmapInfoScreen.cs | 3 +-- osu.Game.Tournament/Screens/IProvideVideo.cs | 9 ++++++++ .../Screens/Ladder/LadderManager.cs | 2 +- .../Screens/MapPool/MapPoolScreen.cs | 3 +-- .../Screens/TeamIntro/TeamIntroScreen.cs | 3 +-- .../Screens/TournamentSceneManager.cs | 13 +++++++++--- .../Screens/TournamentScreen.cs | 21 +++++++++++++++++++ 7 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 osu.Game.Tournament/Screens/IProvideVideo.cs create mode 100644 osu.Game.Tournament/Screens/TournamentScreen.cs diff --git a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs index 4ddd475b6e..def9f228cf 100644 --- a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs +++ b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs @@ -5,13 +5,12 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; -using osu.Game.Screens; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; namespace osu.Game.Tournament.Screens { - public abstract class BeatmapInfoScreen : OsuScreen + public abstract class BeatmapInfoScreen : TournamentScreen { protected readonly SongBar SongBar; diff --git a/osu.Game.Tournament/Screens/IProvideVideo.cs b/osu.Game.Tournament/Screens/IProvideVideo.cs new file mode 100644 index 0000000000..b5a4e1ad8e --- /dev/null +++ b/osu.Game.Tournament/Screens/IProvideVideo.cs @@ -0,0 +1,9 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Tournament.Screens +{ + public interface IProvideVideo + { + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 5ef7d047e2..4c9700462f 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -23,7 +23,7 @@ using SixLabors.Primitives; namespace osu.Game.Tournament.Screens.Ladder { [Cached] - public class LadderManager : CompositeDrawable, IHasContextMenu + public class LadderManager : TournamentScreen, IHasContextMenu { private Container pairingsContainer; private Container paths; diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 5a04640ed7..5a463c6d5e 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -10,7 +10,6 @@ using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osu.Game.Screens; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Screens.Gameplay; @@ -21,7 +20,7 @@ using OpenTK.Input; namespace osu.Game.Tournament.Screens.MapPool { - public class MapPoolScreen : OsuScreen + public class MapPoolScreen : TournamentScreen { private readonly FillFlowContainer maps; diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 7c4f139de7..bb17598c70 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Video; using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Screens; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; using OpenTK; @@ -18,7 +17,7 @@ using OpenTK.Graphics; namespace osu.Game.Tournament.Screens.TeamIntro { - public class TeamIntroScreen : OsuScreen + public class TeamIntroScreen : TournamentScreen, IProvideVideo { private Container mainContainer; diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index 4cd6c681fa..20af4c29be 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -29,6 +29,7 @@ namespace osu.Game.Tournament.Screens private DrawingsScreen drawings; private Container screens; private ShowcaseScreen showcase; + private VideoSprite video; [BackgroundDependencyLoader] private void load(LadderInfo ladder, Storage storage) @@ -76,7 +77,7 @@ namespace osu.Game.Tournament.Screens //Masking = true, Children = new Drawable[] { - new VideoSprite(storage.GetStream("BG Logoless - OWC.m4v")) + video = new VideoSprite(storage.GetStream("BG Logoless - OWC.m4v")) { Loop = true, RelativeSizeAxes = Axes.Both, @@ -107,9 +108,15 @@ namespace osu.Game.Tournament.Screens foreach (var s in screens.Children) { if (s == screen) - s.FadeIn(100); + { + s.Show(); + if (s is IProvideVideo) + video.FadeOut(200); + else + video.Show(); + } else - s.FadeOut(100); + s.Hide(); } } } diff --git a/osu.Game.Tournament/Screens/TournamentScreen.cs b/osu.Game.Tournament/Screens/TournamentScreen.cs new file mode 100644 index 0000000000..dcdd7f8ce5 --- /dev/null +++ b/osu.Game.Tournament/Screens/TournamentScreen.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Game.Screens; + +namespace osu.Game.Tournament.Screens +{ + public class TournamentScreen : OsuScreen + { + public override void Hide() + { + this.FadeOut(200); + } + + public override void Show() + { + this.FadeIn(200); + } + } +} From 21bbb6863631ee64d7dd9fad91bbb4015d9a2711 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Nov 2018 01:50:09 +0900 Subject: [PATCH 0257/5608] Handle delayed contract --- .../Screens/Gameplay/GameplayScreen.cs | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index a89200f3a5..f164d2d7b0 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -1,11 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using Microsoft.Diagnostics.Runtime.Interop; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; +using osu.Framework.Threading; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; @@ -68,6 +70,8 @@ namespace osu.Game.Tournament.Screens.Gameplay warmup.BindValueChanged(w => warmupButton.Colour = !w ? Color4.White : Color4.Gray, true); } + private ScheduledDelegate scheduledBarContract; + private void stateChanged(TourneyState state) { if (state == TourneyState.Ranking) @@ -80,17 +84,21 @@ namespace osu.Game.Tournament.Screens.Gameplay currentMatch.Value.Team2Score.Value++; } - if (state == TourneyState.Idle) - { - // show chat - SongBar.Expanded = false; - } - else - { - SongBar.Expanded = true; - } - + scheduledBarContract?.Cancel(); + switch (state) + { + case TourneyState.Idle: + // show chat + SongBar.Expanded = false; + break; + case TourneyState.Ranking: + scheduledBarContract = Scheduler.AddDelayed(() => SongBar.Expanded = false, 15000); + break; + default: + SongBar.Expanded = true; + break; + } } } } From 9c18f7a25afd2ce3ee28ba98bc12b0d22f203e7c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Nov 2018 09:05:36 +0900 Subject: [PATCH 0258/5608] Fix date display --- osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index bb17598c70..63ca968aef 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -71,7 +71,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.Centre, Origin = Anchor.CentreLeft }, - new RoundDisplay(pairing.Grouping) + new RoundDisplay(pairing) { RelativeSizeAxes = Axes.Both, Height = 0.25f, @@ -83,7 +83,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro private class RoundDisplay : CompositeDrawable { - public RoundDisplay(TournamentGrouping group) + public RoundDisplay(MatchPairing pairing) { var col = OsuColour.Gray(0.33f); @@ -112,7 +112,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Colour = col, - Text = group?.Name.Value ?? "Unknown Grouping", + Text = pairing.Grouping.Value?.Name.Value ?? "Unknown Grouping", Font = "Aquatico-Light", Spacing = new Vector2(10, 0), TextSize = 50, @@ -123,7 +123,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Origin = Anchor.TopCentre, Font = "Aquatico-Light", Colour = col, - Text = (group?.StartDate.Value ?? DateTimeOffset.Now).ToString("dd MMMM HH:mm UTC"), + Text = pairing.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"), TextSize = 20, }, } From 2683b161d58df6a7eca79af413a5fb0490fa926a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Nov 2018 09:16:46 +0900 Subject: [PATCH 0259/5608] Fix missing logo --- .../Screens/Gameplay/MatchHeader.cs | 13 ++------ .../Screens/Showcase/ShowcaseScreen.cs | 8 +++++ .../Screens/Showcase/TournamentLogo.cs | 33 +++++++++++++++++++ .../Screens/TeamIntro/TeamIntroScreen.cs | 6 ++-- 4 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs diff --git a/osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs index 2ff5ee7bf6..5765c9cd12 100644 --- a/osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs @@ -6,13 +6,13 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Events; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Screens.Showcase; using OpenTK; using OpenTK.Graphics; using OpenTK.Input; @@ -28,16 +28,7 @@ namespace osu.Game.Tournament.Screens.Gameplay Height = 100; Children = new Drawable[] { - new Sprite - { - Y = 5, - Texture = textures.Get("game-screen-logo"), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - FillMode = FillMode.Fit, - RelativeSizeAxes = Axes.Both, - Size = Vector2.One - }, + new TournamentLogo(), new RoundDisplay { Y = 10, diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs index ce458413a5..6950b940fe 100644 --- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -1,9 +1,17 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; +using osu.Framework.Graphics.Textures; + namespace osu.Game.Tournament.Screens.Showcase { public class ShowcaseScreen : BeatmapInfoScreen { + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Add(new TournamentLogo()); + } } } diff --git a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs new file mode 100644 index 0000000000..135081a641 --- /dev/null +++ b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs @@ -0,0 +1,33 @@ +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using OpenTK; + +namespace osu.Game.Tournament.Screens.Showcase +{ + public class TournamentLogo : CompositeDrawable + { + public TournamentLogo() + { + RelativeSizeAxes = Axes.X; + Height = 100; + Margin = new MarginPadding { Vertical = 5 }; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + InternalChild = new Sprite + { + Texture = textures.Get("game-screen-logo"), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + FillMode = FillMode.Fit, + RelativeSizeAxes = Axes.Both, + Size = Vector2.One + }; + } + } +} diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 63ca968aef..05746c07d0 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -1,17 +1,18 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Video; using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Screens.Showcase; using OpenTK; using OpenTK.Graphics; @@ -24,7 +25,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro private readonly Bindable currentMatch = new Bindable(); [BackgroundDependencyLoader] - private void load(LadderInfo ladder, Storage storage) + private void load(TextureStore textures, LadderInfo ladder, Storage storage) { RelativeSizeAxes = Axes.Both; @@ -35,6 +36,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro RelativeSizeAxes = Axes.Both, Loop = true, }, + new TournamentLogo(), mainContainer = new Container { RelativeSizeAxes = Axes.Both, From e3576572a38f24ab1a18e4207cd9be9196fbad0b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Nov 2018 09:22:57 +0900 Subject: [PATCH 0260/5608] Fix warmup state, automate more --- .../Screens/Gameplay/GameplayScreen.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index f164d2d7b0..c1a4014554 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using Microsoft.Diagnostics.Runtime.Interop; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -33,17 +32,12 @@ namespace osu.Game.Tournament.Screens.Gameplay AddRange(new Drawable[] { new MatchHeader(), - // new CustomChatOverlay - // { - // Anchor = Anchor.BottomCentre, - // Origin = Anchor.BottomCentre, - // Size = new Vector2(0.4f, 1) - // }, new Box { RelativeSizeAxes = Axes.Both, Height = 720 / 1080f, Colour = new Color4(0, 255, 0, 255), + Y = 16, Anchor = Anchor.Centre, Origin= Anchor.Centre, }, @@ -53,7 +47,6 @@ namespace osu.Game.Tournament.Screens.Gameplay { warmupButton = new TriangleButton { - Colour = Color4.Gray, RelativeSizeAxes = Axes.X, Text = "Toggle warmup", Action = () => warmup.Toggle() @@ -65,9 +58,10 @@ namespace osu.Game.Tournament.Screens.Gameplay State.BindValueChanged(stateChanged); State.BindTo(ipc.State); + currentMatch.BindValueChanged(m => warmup.Value = m.Team1Score + m.Team2Score == 0); currentMatch.BindTo(ladder.CurrentMatch); - warmup.BindValueChanged(w => warmupButton.Colour = !w ? Color4.White : Color4.Gray, true); + warmup.BindValueChanged(w => warmupButton.Alpha = !w ? 0.5f : 1, true); } private ScheduledDelegate scheduledBarContract; From 949cf98d1a5316d87c0c51f98b0795e802e325fd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Nov 2018 09:23:54 +0900 Subject: [PATCH 0261/5608] Adjust gameplay position ever so slightly --- osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index c1a4014554..99d996d138 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -35,9 +35,9 @@ namespace osu.Game.Tournament.Screens.Gameplay new Box { RelativeSizeAxes = Axes.Both, - Height = 720 / 1080f, + Height = 718 / 1080f, Colour = new Color4(0, 255, 0, 255), - Y = 16, + Y = 14, Anchor = Anchor.Centre, Origin= Anchor.Centre, }, From eabcef3e12723631810c0b6c12b42d261fc5f200 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Nov 2018 10:13:17 +0900 Subject: [PATCH 0262/5608] Add schedule screen --- osu.Game.Tournament.Tests/TestCaseSchedule.cs | 25 +++ .../Ladder/Components/DrawableMatchPairing.cs | 6 +- .../Ladder/Components/DrawableMatchTeam.cs | 17 +- .../Screens/Ladder/LadderManager.cs | 13 +- .../Screens/Schedule/ScheduleScreen.cs | 167 ++++++++++++++++++ .../Screens/TournamentSceneManager.cs | 4 + osu.Game.Tournament/TournamentGameBase.cs | 4 + osu.Game/OsuGameBase.cs | 2 +- 8 files changed, 221 insertions(+), 17 deletions(-) create mode 100644 osu.Game.Tournament.Tests/TestCaseSchedule.cs create mode 100644 osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs diff --git a/osu.Game.Tournament.Tests/TestCaseSchedule.cs b/osu.Game.Tournament.Tests/TestCaseSchedule.cs new file mode 100644 index 0000000000..a12586cb27 --- /dev/null +++ b/osu.Game.Tournament.Tests/TestCaseSchedule.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Game.Tests.Visual; +using osu.Game.Tournament.Screens.Schedule; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseSchedule : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ScheduleScreen) + }; + + [BackgroundDependencyLoader] + private void load() + { + Add(new ScheduleScreen()); + } + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 5d0837c542..def53ce510 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public class DrawableMatchPairing : CompositeDrawable { public readonly MatchPairing Pairing; - private readonly FillFlowContainer flow; + protected readonly FillFlowContainer Flow; private readonly Drawable selectionBox; private readonly Drawable currentMatchSelectionBox; private Bindable globalSelection; @@ -62,7 +62,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Colour = Color4.OrangeRed, Child = new Box { RelativeSizeAxes = Axes.Both } }, - flow = new FillFlowContainer + Flow = new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, @@ -195,7 +195,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components if (Pairing.Team1.Value == null || Pairing.Team2.Value == null) Pairing.CancelMatchStart(); - flow.Children = new[] + Flow.Children = new[] { new DrawableMatchTeam(Pairing.Team1, Pairing, Pairing.Losers), new DrawableMatchTeam(Pairing.Team2, Pairing, Pairing.Losers) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 804680ba28..7ff15ef434 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -36,6 +36,19 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private readonly Func isWinner; private LadderManager manager; + [Resolved] + private LadderInfo ladderInfo { get; set; } + + private void setCurrent() + { + //todo: tournamentgamebase? + if (ladderInfo.CurrentMatch.Value != null) + ladderInfo.CurrentMatch.Value.Current.Value = false; + + ladderInfo.CurrentMatch.Value = pairing; + ladderInfo.CurrentMatch.Value.Current.Value = true; + } + [Resolved(CanBeNull = true)] private LadderEditorInfo editorInfo { get; set; } @@ -132,7 +145,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components if (!pairing.Current.Value) { - manager.SetCurrent(pairing); + setCurrent(); return true; } @@ -182,7 +195,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components return new MenuItem[] { - new OsuMenuItem("Set as current", MenuItemType.Standard, () => manager.SetCurrent(pairing)), + new OsuMenuItem("Set as current", MenuItemType.Standard, setCurrent), new OsuMenuItem("Join with", MenuItemType.Standard, () => manager.RequestJoin(pairing, false)), new OsuMenuItem("Join with (loser)", MenuItemType.Standard, () => manager.RequestJoin(pairing, true)), new OsuMenuItem("Remove", MenuItemType.Destructive, () => manager.Remove(pairing)), diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs index 4c9700462f..2b1a1bad85 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs @@ -31,8 +31,8 @@ namespace osu.Game.Tournament.Screens.Ladder private ScrollableContainer scrollContent; - [Cached] - private LadderEditorInfo editorInfo = new LadderEditorInfo(); + [Resolved] + private LadderEditorInfo editorInfo { get; set;} [Resolved] private LadderInfo ladderInfo { get; set; } @@ -185,15 +185,6 @@ namespace osu.Game.Tournament.Screens.Ladder public void Remove(MatchPairing pairing) => pairingsContainer.FirstOrDefault(p => p.Pairing == pairing)?.Remove(); - public void SetCurrent(MatchPairing pairing) - { - if (ladderInfo.CurrentMatch.Value != null) - ladderInfo.CurrentMatch.Value.Current.Value = false; - - ladderInfo.CurrentMatch.Value = pairing; - ladderInfo.CurrentMatch.Value.Current.Value = true; - } - private class JoinRequestHandler : CompositeDrawable { private readonly Container pairingsContainer; diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs new file mode 100644 index 0000000000..a0c36cd6c0 --- /dev/null +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -0,0 +1,167 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Video; +using osu.Framework.Platform; +using osu.Game.Graphics.Sprites; +using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Tournament.Screens.Schedule +{ + public class ScheduleScreen : TournamentScreen, IProvideVideo + { + private readonly Bindable currentMatch = new Bindable(); + private Container mainContainer; + private LadderInfo ladder; + + [BackgroundDependencyLoader] + private void load(LadderInfo ladder, Storage storage) + { + this.ladder = ladder; + + RelativeSizeAxes = Axes.Both; + + InternalChildren = new Drawable[] + { + new VideoSprite(storage.GetStream(@"BG Side Logo - OWC.m4v")) + { + RelativeSizeAxes = Axes.Both, + Loop = true, + }, + mainContainer = new Container + { + RelativeSizeAxes = Axes.Both, + } + }; + + currentMatch.BindValueChanged(matchChanged); + currentMatch.BindTo(ladder.CurrentMatch); + } + + private void matchChanged(MatchPairing pairing) + { + if (pairing == null) + { + mainContainer.Clear(); + return; + } + + mainContainer.Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Height = 0.65f, + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new ScheduleContainer("recent matches") + { + RelativeSizeAxes = Axes.Both, + Width = 0.4f, + ChildrenEnumerable = ladder.Pairings + .Where(p => p.Completed.Value) + .OrderByDescending(p => p.Date.Value) + .Take(8) + .Select(p => new SchedulePairing(p)) + }, + new ScheduleContainer("match overview") + { + RelativeSizeAxes = Axes.Both, + Width = 0.6f, + ChildrenEnumerable = ladder.Pairings + .Where(p => !p.Completed.Value) + .OrderBy(p => p.Date.Value) + .Take(8) + .Select(p => new SchedulePairing(p)) + }, + } + } + }, + new ScheduleContainer("current match") + { + RelativeSizeAxes = Axes.Both, + Height = 0.25f, + Children = new Drawable[] + { + new OsuSpriteText + { + Margin = new MarginPadding { Left = -10, Bottom = 10, Top = -5 }, + Spacing = new Vector2(10, 0), + Text = currentMatch.Value.Grouping.Value.Name.Value, + Colour = Color4.Black, + TextSize = 20 + }, + new SchedulePairing(currentMatch), + new OsuSpriteText + { + Text = "Start Time " + pairing.Date.Value.ToUniversalTime().ToString("HH:mm UTC"), + Colour = Color4.Black, + TextSize = 20 + }, + } + } + } + }; + } + + public class SchedulePairing : DrawableMatchPairing + { + public SchedulePairing(MatchPairing pairing) + : base(pairing) + { + Flow.Direction = FillDirection.Horizontal; + } + } + + public class ScheduleContainer : Container + { + protected override Container Content => content; + + private readonly FillFlowContainer content; + + public ScheduleContainer(string title) + { + Padding = new MarginPadding { Left = 30, Top = 30 }; + InternalChildren = new Drawable[] + { + new OsuSpriteText + { + X = 30, + Text = title, + Colour = Color4.Black, + Spacing = new Vector2(10, 0), + TextSize = 30 + }, + content = new FillFlowContainer + { + Direction = FillDirection.Vertical, + RelativeSizeAxes = Axes.Both, + Margin = new MarginPadding(40) + }, + new Circle + { + Colour = new Color4(233, 187, 79, 255), + Width = 5, + RelativeSizeAxes = Axes.Y, + } + }; + } + } + } +} diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index 20af4c29be..c349e48fa2 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -13,6 +13,7 @@ using osu.Game.Tournament.Screens.Drawings; using osu.Game.Tournament.Screens.Gameplay; using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.MapPool; +using osu.Game.Tournament.Screens.Schedule; using osu.Game.Tournament.Screens.Showcase; using osu.Game.Tournament.Screens.TeamIntro; using OpenTK; @@ -22,6 +23,7 @@ namespace osu.Game.Tournament.Screens { public class TournamentSceneManager : OsuScreen { + private ScheduleScreen schedule; private LadderManager bracket; private MapPoolScreen mapPool; private GameplayScreen gameplay; @@ -56,6 +58,7 @@ namespace osu.Game.Tournament.Screens new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => setScreen(drawings) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => setScreen(showcase) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Schedule", Action = () => setScreen(schedule) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => setScreen(bracket) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => setScreen(teamIntro) }, @@ -88,6 +91,7 @@ namespace osu.Game.Tournament.Screens RelativeSizeAxes = Axes.Both, Children = new Drawable[] { + schedule = new ScheduleScreen(), bracket = new LadderManager(), showcase = new ShowcaseScreen(), mapPool = new MapPoolScreen(), diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 70868d398e..938d79929d 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -19,6 +19,7 @@ using osu.Game.Online.API.Requests; using osu.Game.Rulesets; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament { @@ -34,6 +35,9 @@ namespace osu.Game.Tournament [Cached] private readonly Bindable ruleset = new Bindable(); + [Cached] + private LadderEditorInfo editorInfo = new LadderEditorInfo(); + private Bindable windowSize; private FileBasedIPC ipc; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index c7f787cff1..971bc10ecd 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -297,7 +297,7 @@ namespace osu.Game } public override bool EnableDrag => true; // allow right-mouse dragging for absolute scroll in scroll containers. - public override bool EnableClick => false; + public override bool EnableClick => true; public override bool ChangeFocusOnClick => false; } } From be3904b647977331ea8a96dcb1321035a0b875be Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Nov 2018 10:39:04 +0900 Subject: [PATCH 0263/5608] Add win screen --- osu.Game.Tournament.Tests/TeamWinTestCase.cs | 34 +++ .../Screens/TeamWin/TeamWinScreen.cs | 232 ++++++++++++++++++ .../Screens/TournamentSceneManager.cs | 7 +- 3 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tournament.Tests/TeamWinTestCase.cs create mode 100644 osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs diff --git a/osu.Game.Tournament.Tests/TeamWinTestCase.cs b/osu.Game.Tournament.Tests/TeamWinTestCase.cs new file mode 100644 index 0000000000..48ae9acb91 --- /dev/null +++ b/osu.Game.Tournament.Tests/TeamWinTestCase.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Screens.TeamWin; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseTeamWin : LadderTestCase + { + [Cached] + private readonly Bindable currentMatch = new Bindable(); + + [BackgroundDependencyLoader] + private void load() + { + var pairing = new MatchPairing(); + pairing.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == "USA"); + pairing.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == "JPN"); + pairing.Grouping.Value = Ladder.Groupings.FirstOrDefault(g => g.Name == "Finals"); + currentMatch.Value = pairing; + + Add(new TeamWinScreen + { + FillMode = FillMode.Fit, + FillAspectRatio = 16 / 9f + }); + } + } +} diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs new file mode 100644 index 0000000000..3c1bcdd1ae --- /dev/null +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -0,0 +1,232 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; +using osu.Framework.Platform; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Screens.Showcase; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Tournament.Screens.TeamWin +{ + public class TeamWinScreen : TournamentScreen, IProvideVideo + { + private Container mainContainer; + + private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentCompleted = new Bindable(); + + private VideoSprite blueWinVideo; + private VideoSprite redWinVideo; + + [BackgroundDependencyLoader] + private void load(TextureStore textures, LadderInfo ladder, Storage storage) + { + RelativeSizeAxes = Axes.Both; + + InternalChildren = new Drawable[] + { + blueWinVideo = new VideoSprite(storage.GetStream(@"BG Team - Win Blue.m4v")) + { + Alpha = 1, + RelativeSizeAxes = Axes.Both, + Loop = true, + }, + redWinVideo = new VideoSprite(storage.GetStream(@"BG Team - Win Red.m4v")) + { + Alpha = 0, + RelativeSizeAxes = Axes.Both, + Loop = true, + }, + new TournamentLogo() + { + Y = 40, + }, + mainContainer = new Container + { + RelativeSizeAxes = Axes.Both, + } + }; + + currentMatch.BindValueChanged(matchChanged); + currentMatch.BindTo(ladder.CurrentMatch); + + currentCompleted.BindValueChanged(_ => update()); + } + + private void matchChanged(MatchPairing pairing) + { + currentCompleted.UnbindBindings(); + currentCompleted.BindTo(pairing.Completed); + + update(); + } + + private void update() + { + var pairing = currentMatch.Value; + + if (pairing.Winner == null) + { + mainContainer.Clear(); + return; + } + + bool redWin = pairing.Winner == pairing.Team1.Value; + redWinVideo.Alpha = redWin ? 1 : 0; + blueWinVideo.Alpha = redWin ? 0 : 1; + + mainContainer.Children = new Drawable[] + { + new TeamWithPlayers(pairing.Winner, redWin) + { + RelativeSizeAxes = Axes.Both, + Width = 0.5f, + Height = 0.6f, + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }, + new RoundDisplay(pairing) + { + RelativeSizeAxes = Axes.Both, + Height = 0.25f, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + } + }; + } + + private class RoundDisplay : CompositeDrawable + { + public RoundDisplay(MatchPairing pairing) + { + var col = OsuColour.Gray(0.33f); + + InternalChildren = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Colour = col, + Text = "WINNER", + Font = "Aquatico-Regular", + TextSize = 15, + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Colour = col, + Text = pairing.Grouping.Value?.Name.Value ?? "Unknown Grouping", + Font = "Aquatico-Light", + Spacing = new Vector2(10, 0), + TextSize = 50, + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Font = "Aquatico-Light", + Colour = col, + Text = pairing.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"), + TextSize = 20, + }, + } + } + }; + } + } + + private class TeamWithPlayers : CompositeDrawable + { + private readonly Color4 red = new Color4(129, 68, 65, 255); + private readonly Color4 blue = new Color4(41, 91, 97, 255); + + public TeamWithPlayers(TournamentTeam team, bool left = false) + { + FillFlowContainer players; + var colour = left ? red : blue; + InternalChildren = new Drawable[] + { + new TeamDisplay(team, left ? "Team Red" : "Team Blue", colour) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + players = new FillFlowContainer + { + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(0, 5), + Padding = new MarginPadding(20), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.Both, + }, + }; + } + + private class TeamDisplay : DrawableTournamentTeam + { + public TeamDisplay(TournamentTeam team, string teamName, Color4 colour) + : base(team) + { + AutoSizeAxes = Axes.Both; + + Flag.Anchor = Flag.Origin = Anchor.TopCentre; + Flag.RelativeSizeAxes = Axes.None; + Flag.Size = new Vector2(300, 200); + Flag.Scale = new Vector2(0.4f); + Flag.Margin = new MarginPadding { Bottom = 20 }; + + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + Children = new Drawable[] + { + Flag, + new OsuSpriteText + { + Text = team?.FullName.ToUpper() ?? "???", + TextSize = 40, + Colour = Color4.Black, + Font = "Aquatico-Light", + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + }, + new OsuSpriteText + { + Text = teamName.ToUpper(), + TextSize = 20, + Colour = colour, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + } + } + }; + } + } + } + } +} diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index c349e48fa2..02492953f2 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -16,6 +16,7 @@ using osu.Game.Tournament.Screens.MapPool; using osu.Game.Tournament.Screens.Schedule; using osu.Game.Tournament.Screens.Showcase; using osu.Game.Tournament.Screens.TeamIntro; +using osu.Game.Tournament.Screens.TeamWin; using OpenTK; using OpenTK.Graphics; @@ -27,6 +28,7 @@ namespace osu.Game.Tournament.Screens private LadderManager bracket; private MapPoolScreen mapPool; private GameplayScreen gameplay; + private TeamWinScreen winner; private TeamIntroScreen teamIntro; private DrawingsScreen drawings; private Container screens; @@ -64,6 +66,8 @@ namespace osu.Game.Tournament.Screens new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => setScreen(teamIntro) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => setScreen(mapPool) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => setScreen(gameplay) }, + new Container { RelativeSizeAxes = Axes.X, Height = 50 }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Win", Action = () => setScreen(winner) }, } }, }, @@ -97,7 +101,8 @@ namespace osu.Game.Tournament.Screens mapPool = new MapPoolScreen(), teamIntro = new TeamIntroScreen(), drawings = new DrawingsScreen(), - gameplay = new GameplayScreen() + gameplay = new GameplayScreen(), + winner = new TeamWinScreen() } }, } From 123629ba9e94f06e1ff5823ed9507b6f49f04ab0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Nov 2018 10:48:57 +0900 Subject: [PATCH 0264/5608] Flash panels on select --- .../Components/TournamentBeatmapPanel.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index b804fc44a7..8df01b636b 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -29,6 +29,7 @@ namespace osu.Game.Tournament.Components public const float HEIGHT = 50; private readonly Bindable currentMatch = new Bindable(); + private Box flash; public TournamentBeatmapPanel(BeatmapInfo beatmap) { @@ -117,6 +118,13 @@ namespace osu.Game.Tournament.Components } }, }, + flash = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray, + Blending = BlendingMode.Additive, + Alpha = 0, + }, }); } @@ -126,12 +134,20 @@ namespace osu.Game.Tournament.Components updateState(); } + private BeatmapChoice choice; + private void updateState() { var found = currentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == Beatmap.OnlineBeatmapID); + bool doFlash = found != choice; + choice = found; + if (found != null) { + if (doFlash) + flash.FadeOutFromOne(500).Loop(0, 10); + BorderThickness = 6; switch (found.Team) From 00731560cb1ced2f569c5ba27e0d79d285c12767 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Nov 2018 01:25:22 +0900 Subject: [PATCH 0265/5608] Add CS display --- osu.Game.Tournament/Components/SongBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 6d9dc6025f..c0ae2116c4 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -179,7 +179,7 @@ namespace osu.Game.Tournament.Components }, new OsuSpriteText { - Text = $"AR {ar:0.#}{extra}", + Text = $"CS{beatmap.BaseDifficulty.CircleSize:0.#} / AR {ar:0.#}{extra}", Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, Colour = OsuColour.Gray(0.33f), Anchor = Anchor.TopRight, From d7a086be83cbb9054655b4fe25f9a1754627e7f7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Nov 2018 01:25:31 +0900 Subject: [PATCH 0266/5608] Fix regression in song bar display logic --- osu.Game.Tournament/Components/TournamentBeatmapPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 8df01b636b..d2bc790b16 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -146,7 +146,7 @@ namespace osu.Game.Tournament.Components if (found != null) { if (doFlash) - flash.FadeOutFromOne(500).Loop(0, 10); + flash?.FadeOutFromOne(500).Loop(0, 10); BorderThickness = 6; From 01f814aacee8a79e6d917fb4d49e7eef85f9a4cf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Nov 2018 14:11:58 +0900 Subject: [PATCH 0267/5608] Fix song length not being rounded correctly when DT is applied --- osu.Game.Tournament/Components/SongBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index c0ae2116c4..d145544b76 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -163,7 +163,7 @@ namespace osu.Game.Tournament.Components { new OsuSpriteText { - Text = $"Length {length}s", + Text = $"Length {length:0}s", Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, Colour = OsuColour.Gray(0.33f), Anchor = Anchor.TopLeft, From 8eff21d128d1aac39e2826cc093ef48da582270d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Nov 2018 14:12:14 +0900 Subject: [PATCH 0268/5608] Fix star colours being incorrect --- osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs index 5765c9cd12..c750694b87 100644 --- a/osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs @@ -107,10 +107,16 @@ namespace osu.Game.Tournament.Screens.Gameplay private void teamChanged(TournamentTeam team) { + var colour = teamColour == TeamColour.Red ? red : blue; + var flip = teamColour != TeamColour.Red; + InternalChildren = new Drawable[] { - new TeamDisplay(team, teamColour == TeamColour.Red ? red : blue, teamColour != TeamColour.Red), - new ScoreDisplay(currentTeamScore, teamColour != TeamColour.Red, currentMatch.Value.PointsToWin) + new TeamDisplay(team, colour, flip), + new ScoreDisplay(currentTeamScore, flip, currentMatch.Value.PointsToWin) + { + Colour = colour + } }; } } @@ -133,7 +139,6 @@ namespace osu.Game.Tournament.Screens.Gameplay X = (flip ? -1 : 1) * 90, Y = 5, Scale = flip ? new Vector2(-1, 1) : Vector2.One, - Colour = new Color4(95, 41, 60, 255), }; currentTeamScore.BindValueChanged(scoreChanged); From 604cb4cb9ee4060d3512cc58391c780f372947a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Nov 2018 14:12:41 +0900 Subject: [PATCH 0269/5608] Update to support new dropdown logic --- .../Screens/Ladder/Components/LadderEditorSettings.cs | 8 +++----- .../Screens/Ladder/Components/TournamentGrouping.cs | 2 ++ osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs | 5 ++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index 3fa7fdf7e8..afb20a68f0 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -36,8 +35,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { var teamEntries = ladderInfo.Teams; - var groupingOptions = ladderInfo.Groupings.Select(g => new KeyValuePair(g.Name, g)) - .Prepend(new KeyValuePair("None", new TournamentGrouping())); + var groupingOptions = ladderInfo.Groupings.Prepend(new TournamentGrouping()); Children = new Drawable[] { @@ -80,7 +78,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components textboxTeam2 = new OsuTextBox { RelativeSizeAxes = Axes.X, Height = 20 }, groupingDropdown = new SettingsDropdown { - Bindable = new Bindable { Default = groupingOptions.First().Value }, + Bindable = new Bindable { Default = groupingOptions.First() }, Items = groupingOptions }, losersCheckbox = new PlayerCheckbox @@ -94,7 +92,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { textboxTeam1.Text = selection?.Team1.Value?.Acronym; textboxTeam2.Text = selection?.Team2.Value?.Acronym; - groupingDropdown.Bindable.Value = selection?.Grouping.Value ?? groupingOptions.First().Value; + groupingDropdown.Bindable.Value = selection?.Grouping.Value ?? groupingOptions.First(); losersCheckbox.Current.Value = selection?.Losers.Value ?? false; }; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs index 17f76a0143..370f0ea643 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs @@ -22,5 +22,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly Bindable StartDate = new Bindable(); public List Pairings = new List(); + + public override string ToString() => Name.Value ?? "None"; } } diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs index 3c1bcdd1ae..a6f6e7038a 100644 --- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -47,7 +47,7 @@ namespace osu.Game.Tournament.Screens.TeamWin RelativeSizeAxes = Axes.Both, Loop = true, }, - new TournamentLogo() + new TournamentLogo { Y = 40, }, @@ -163,7 +163,6 @@ namespace osu.Game.Tournament.Screens.TeamWin public TeamWithPlayers(TournamentTeam team, bool left = false) { - FillFlowContainer players; var colour = left ? red : blue; InternalChildren = new Drawable[] { @@ -172,7 +171,7 @@ namespace osu.Game.Tournament.Screens.TeamWin Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - players = new FillFlowContainer + new FillFlowContainer { Direction = FillDirection.Vertical, AutoSizeAxes = Axes.Both, From 54b87e9c9344942410f37ebcd94a3c79be593216 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Nov 2018 14:12:51 +0900 Subject: [PATCH 0270/5608] Don't crash on unexpected pairing links --- osu.Game.Tournament/TournamentGameBase.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 938d79929d..8a2e6471c1 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -104,7 +104,10 @@ namespace osu.Game.Tournament // link pairings to groupings foreach (var group in Ladder.Groupings) foreach (var id in group.Pairings) - Ladder.Pairings.Single(p => p.ID == id).Grouping.Value = group; + { + var found = Ladder.Pairings.FirstOrDefault(p => p.ID == id); + if (found != null) found.Grouping.Value = group; + } Ladder.CurrentMatch.Value = Ladder.Pairings.FirstOrDefault(p => p.Current.Value); From 46e163ec5e81c85c1f58a0129cdf144c327560ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Nov 2018 21:28:42 +0900 Subject: [PATCH 0271/5608] Add score display --- .../TestCaseMatchScoreDisplay.cs | 40 +++++ osu.Game.Tournament/IPC/FileBasedIPC.cs | 25 +-- osu.Game.Tournament/IPC/MatchIPCInfo.cs | 19 +++ osu.Game.Tournament/IPC/TourneyState.cs | 14 ++ .../Screens/BeatmapInfoScreen.cs | 2 +- .../Gameplay/{ => Components}/MatchHeader.cs | 8 +- .../Gameplay/Components/MatchScoreDisplay.cs | 144 ++++++++++++++++++ .../Screens/Gameplay/GameplayScreen.cs | 57 ++++++- .../Screens/MapPool/MapPoolScreen.cs | 4 +- osu.Game.Tournament/TournamentGameBase.cs | 2 +- 10 files changed, 277 insertions(+), 38 deletions(-) create mode 100644 osu.Game.Tournament.Tests/TestCaseMatchScoreDisplay.cs create mode 100644 osu.Game.Tournament/IPC/MatchIPCInfo.cs create mode 100644 osu.Game.Tournament/IPC/TourneyState.cs rename osu.Game.Tournament/Screens/Gameplay/{ => Components}/MatchHeader.cs (96%) create mode 100644 osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs diff --git a/osu.Game.Tournament.Tests/TestCaseMatchScoreDisplay.cs b/osu.Game.Tournament.Tests/TestCaseMatchScoreDisplay.cs new file mode 100644 index 0000000000..62c5ca786b --- /dev/null +++ b/osu.Game.Tournament.Tests/TestCaseMatchScoreDisplay.cs @@ -0,0 +1,40 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.MathUtils; +using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Screens.Gameplay.Components; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseMatchScoreDisplay : LadderTestCase + { + [Cached(Type = typeof(MatchIPCInfo))] + private MatchIPCInfo matchInfo = new MatchIPCInfo(); + + public TestCaseMatchScoreDisplay() + { + Add(new MatchScoreDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Scheduler.AddDelayed(() => + { + int amount = (int)((RNG.NextDouble() - 0.5) * 10000); + if (amount < 0) + matchInfo.Score1.Value -= amount; + else + matchInfo.Score2.Value += amount; + }, 100, true); + } + } +} diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 2ad30db748..6759122c16 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -4,8 +4,6 @@ using System; using System.IO; using osu.Framework.Allocation; -using osu.Framework.Configuration; -using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Framework.Platform.Windows; using osu.Game.Beatmaps; @@ -16,16 +14,7 @@ using osu.Game.Rulesets; namespace osu.Game.Tournament.IPC { - public enum TourneyState - { - Initialising, - Idle, - WaitingForClients, - Playing, - Ranking - } - - public class FileBasedIPC : Component + public class FileBasedIPC : MatchIPCInfo { [Resolved] protected APIAccess API { get; private set; } @@ -33,15 +22,7 @@ namespace osu.Game.Tournament.IPC [Resolved] protected RulesetStore Rulesets { get; private set; } - public readonly Bindable Beatmap = new Bindable(); - - public readonly Bindable Mods = new Bindable(); - - public readonly Bindable State = new Bindable(); - private int lastBeatmapId; - public int Score1; - public int Score2; [BackgroundDependencyLoader] private void load() @@ -97,8 +78,8 @@ namespace osu.Game.Tournament.IPC using (var stream = stable.GetStream(file_ipc_scores_filename)) using (var sr = new StreamReader(stream)) { - Score1 = int.Parse(sr.ReadLine()); - Score2 = int.Parse(sr.ReadLine()); + Score1.Value = int.Parse(sr.ReadLine()); + Score2.Value = int.Parse(sr.ReadLine()); } } catch (Exception) diff --git a/osu.Game.Tournament/IPC/MatchIPCInfo.cs b/osu.Game.Tournament/IPC/MatchIPCInfo.cs new file mode 100644 index 0000000000..d40ec35808 --- /dev/null +++ b/osu.Game.Tournament/IPC/MatchIPCInfo.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Legacy; + +namespace osu.Game.Tournament.IPC +{ + public class MatchIPCInfo : Component + { + public Bindable Beatmap { get; } = new Bindable(); + public Bindable Mods { get; } = new Bindable(); + public Bindable State { get; } = new Bindable(); + public BindableInt Score1 { get; } = new BindableInt(); + public BindableInt Score2 { get; } = new BindableInt(); + } +} diff --git a/osu.Game.Tournament/IPC/TourneyState.cs b/osu.Game.Tournament/IPC/TourneyState.cs new file mode 100644 index 0000000000..afa5b400ba --- /dev/null +++ b/osu.Game.Tournament/IPC/TourneyState.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Tournament.IPC +{ + public enum TourneyState + { + Initialising, + Idle, + WaitingForClients, + Playing, + Ranking + } +} diff --git a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs index def9f228cf..b75456c1e9 100644 --- a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs +++ b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tournament.Screens } [BackgroundDependencyLoader] - private void load(FileBasedIPC ipc) + private void load(MatchIPCInfo ipc) { ipc.Beatmap.BindValueChanged(beatmapChanged, true); ipc.Mods.BindValueChanged(modsChanged, true); diff --git a/osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs similarity index 96% rename from osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs rename to osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index c750694b87..9925f5ef74 100644 --- a/osu.Game.Tournament/Screens/Gameplay/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -17,7 +17,7 @@ using OpenTK; using OpenTK.Graphics; using OpenTK.Input; -namespace osu.Game.Tournament.Screens.Gameplay +namespace osu.Game.Tournament.Screens.Gameplay.Components { public class MatchHeader : Container { @@ -113,7 +113,7 @@ namespace osu.Game.Tournament.Screens.Gameplay InternalChildren = new Drawable[] { new TeamDisplay(team, colour, flip), - new ScoreDisplay(currentTeamScore, flip, currentMatch.Value.PointsToWin) + new TeamScore(currentTeamScore, flip, currentMatch.Value.PointsToWin) { Colour = colour } @@ -121,12 +121,12 @@ namespace osu.Game.Tournament.Screens.Gameplay } } - private class ScoreDisplay : CompositeDrawable + private class TeamScore : CompositeDrawable { private readonly Bindable currentTeamScore = new Bindable(); private readonly StarCounter counter; - public ScoreDisplay(Bindable score, bool flip, int count) + public TeamScore(Bindable score, bool flip, int count) { var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs new file mode 100644 index 0000000000..2c00c23d42 --- /dev/null +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs @@ -0,0 +1,144 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.UserInterface; +using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK.Graphics; + +namespace osu.Game.Tournament.Screens.Gameplay.Components +{ + public class MatchScoreDisplay : CompositeDrawable + { + private readonly Color4 red = new Color4(186, 0, 18, 255); + private readonly Color4 blue = new Color4(17, 136, 170, 255); + + private const float bar_height = 20; + + private readonly Bindable currentMatch = new Bindable(); + + private readonly BindableInt score1 = new BindableInt(); + private readonly BindableInt score2 = new BindableInt(); + + private readonly MatchScoreCounter score1Text; + private readonly MatchScoreCounter score2Text; + + private readonly Circle score1Bar; + private readonly Circle score2Bar; + + public MatchScoreDisplay() + { + RelativeSizeAxes = Axes.X; + + InternalChildren = new Drawable[] + { + score1Bar = new Circle + { + Name = "top bar red", + RelativeSizeAxes = Axes.X, + Height = bar_height, + Width = 0, + Colour = red, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopRight + }, + score1Text = new MatchScoreCounter + { + Colour = red, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }, + score2Bar = new Circle + { + Name = "top bar blue", + RelativeSizeAxes = Axes.X, + Height = bar_height, + Width = 0, + Colour = blue, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopLeft + }, + score2Text = new MatchScoreCounter + { + Colour = blue, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }, + }; + } + + [BackgroundDependencyLoader] + private void load(LadderInfo ladder, MatchIPCInfo ipc) + { + currentMatch.BindTo(ladder.CurrentMatch); + + score1.BindValueChanged(_ => updateScores()); + score1.BindTo(ipc.Score1); + + score2.BindValueChanged(_ => updateScores()); + score2.BindTo(ipc.Score2); + } + + private void updateScores() + { + score1Text.Current.Value = score1.Value; + score2Text.Current.Value = score2.Value; + + var winningText = score1.Value > score2.Value ? score1Text : score2Text; + var losingText = score1.Value <= score2.Value ? score1Text : score2Text; + + winningText.Winning = true; + losingText.Winning = false; + + var winningBar = score1.Value > score2.Value ? score1Bar : score2Bar; + var losingBar = score1.Value <= score2.Value ? score1Bar : score2Bar; + + var diff = Math.Max(score1.Value, score2.Value) - Math.Min(score1.Value, score2.Value); + + losingBar.ResizeWidthTo(0, 400, Easing.OutQuint); + winningBar.ResizeWidthTo((float)Math.Pow(diff / 1000000f, 0.5), 400, Easing.OutQuint); + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + score1Text.X = -Math.Max(score1Text.DrawWidth / 2, score1Bar.DrawWidth); + score2Text.X = Math.Max(score2Text.DrawWidth / 2, score2Bar.DrawWidth); + } + + private class MatchScoreCounter : ScoreCounter + { + public MatchScoreCounter() + { + Margin = new MarginPadding { Top = bar_height + 5, Horizontal = 10 }; + Winning = false; + + DisplayedCountSpriteText.FixedWidth = false; + } + + public bool Winning + { + set + { + if (value) + { + DisplayedCountSpriteText.Font = "Aquatico-Regular"; + DisplayedCountSpriteText.TextSize = 60; + } + else + { + DisplayedCountSpriteText.Font = "Aquatico-Light"; + DisplayedCountSpriteText.TextSize = 40; + } + } + } + } + } +} diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 99d996d138..a86c47839b 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -4,12 +4,14 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; using osu.Framework.Threading; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Screens.Gameplay.Components; using osu.Game.Tournament.Screens.Ladder.Components; using OpenTK.Graphics; @@ -23,23 +25,62 @@ namespace osu.Game.Tournament.Screens.Gameplay public readonly Bindable State = new Bindable(); private TriangleButton warmupButton; - private FileBasedIPC ipc; + private MatchIPCInfo ipc; + + private readonly Color4 red = new Color4(186, 0, 18, 255); + private readonly Color4 blue = new Color4(17, 136, 170, 255); [BackgroundDependencyLoader] - private void load(LadderInfo ladder, TextureStore textures, FileBasedIPC ipc) + private void load(LadderInfo ladder, TextureStore textures, MatchIPCInfo ipc) { this.ipc = ipc; AddRange(new Drawable[] { new MatchHeader(), - new Box + new FillFlowContainer { - RelativeSizeAxes = Axes.Both, - Height = 718 / 1080f, - Colour = new Color4(0, 255, 0, 255), - Y = 14, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, Anchor = Anchor.Centre, - Origin= Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Circle + { + Name = "top bar red", + RelativeSizeAxes = Axes.X, + Height = 10, + Width = 0.5f, + Colour = red, + }, + new Circle + { + Name = "top bar blue", + RelativeSizeAxes = Axes.X, + Height = 10, + Width = 0.5f, + Colour = blue, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }, + } + }, + new Box + { + // chroma key area for stable gameplay + Name = "chroma", + RelativeSizeAxes = Axes.X, + Height = 480, + Colour = new Color4(0, 255, 0, 255), + }, + } }, new ControlPanel { diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 5a463c6d5e..c2cefd8c41 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; -using osu.Game.Tournament.Screens.Gameplay; +using osu.Game.Tournament.Screens.Gameplay.Components; using osu.Game.Tournament.Screens.Ladder.Components; using OpenTK; using OpenTK.Graphics; @@ -92,7 +92,7 @@ namespace osu.Game.Tournament.Screens.MapPool } [BackgroundDependencyLoader] - private void load(LadderInfo ladder, FileBasedIPC ipc) + private void load(LadderInfo ladder, MatchIPCInfo ipc) { currentMatch.BindValueChanged(matchChanged); currentMatch.BindTo(ladder.CurrentMatch); diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 8a2e6471c1..31a3c162f5 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -72,7 +72,7 @@ namespace osu.Game.Tournament dependencies.Cache(Ladder); - dependencies.Cache(ipc = new FileBasedIPC()); + dependencies.CacheAs(ipc = new FileBasedIPC()); Add(ipc); bool addedInfo = false; From e6637532bc8ae9eeca7e672e985488b727f09816 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Nov 2018 12:20:21 +0900 Subject: [PATCH 0272/5608] Add back padding --- .../Screens/Gameplay/Components/MatchScoreDisplay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs index 2c00c23d42..fe865a1728 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs @@ -109,8 +109,8 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components { base.UpdateAfterChildren(); - score1Text.X = -Math.Max(score1Text.DrawWidth / 2, score1Bar.DrawWidth); - score2Text.X = Math.Max(score2Text.DrawWidth / 2, score2Bar.DrawWidth); + score1Text.X = -Math.Max(5 + score1Text.DrawWidth / 2, score1Bar.DrawWidth); + score2Text.X = Math.Max(5 + score2Text.DrawWidth / 2, score2Bar.DrawWidth); } private class MatchScoreCounter : ScoreCounter From 1ab4713ef63a6764c78cb3063abe9476df3407ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Nov 2018 14:22:42 +0900 Subject: [PATCH 0273/5608] Add tournament chat display --- .../TestCaseMatchChatDisplay.cs | 103 +++++++++++ .../Components/MatchChatDisplay.cs | 167 ++++++++++++++++++ osu.Game/Online/Chat/Message.cs | 4 - 3 files changed, 270 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs create mode 100644 osu.Game.Tournament/Components/MatchChatDisplay.cs diff --git a/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs b/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs new file mode 100644 index 0000000000..aab56d1714 --- /dev/null +++ b/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs @@ -0,0 +1,103 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Online.Chat; +using osu.Game.Tests.Visual; +using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Users; +using OpenTK; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseMatchChatDisplay : OsuTestCase + { + private readonly Channel testChannel = new Channel(); + + private readonly User admin = new User + { + Username = "HappyStick", + Id = 2, + Colour = "f2ca34" + }; + + private readonly User redUser = new User + { + Username = "BanchoBot", + Id = 3, + }; + + private readonly User blueUser = new User + { + Username = "Zallius", + Id = 4, + }; + + [Cached] + private LadderInfo ladderInfo = new LadderInfo(); + + public TestCaseMatchChatDisplay() + { + MatchChatDisplay chatDisplay; + + Add(chatDisplay = new MatchChatDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(400, 80) + }); + + ladderInfo.CurrentMatch.Value = new MatchPairing + { + Team1 = + { + Value = new TournamentTeam { Players = new List { redUser } } + }, + Team2 = + { + Value = new TournamentTeam { Players = new List { blueUser } } + } + }; + + chatDisplay.Channel.Value = testChannel; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + AddStep("message from admin", () => testChannel.AddLocalEcho(new LocalEchoMessage + { + Sender = admin, + Content = "I am a wang!" + })); + + AddStep("message from team red", () => testChannel.AddLocalEcho(new LocalEchoMessage + { + Sender = redUser, + Content = "I am team red." + })); + + AddStep("message from team red", () => testChannel.AddLocalEcho(new LocalEchoMessage + { + Sender = redUser, + Content = "I plan to win!" + })); + + AddStep("message from team blue", () => testChannel.AddLocalEcho(new LocalEchoMessage + { + Sender = blueUser, + Content = "Not on my watch. Prepare to eat saaaaaaaaaand. Lots and lots of saaaaaaand." + })); + + AddStep("message from admin", () => testChannel.AddLocalEcho(new LocalEchoMessage + { + Sender = admin, + Content = "Okay okay, calm down guys. Let's do this!" + })); + } + } +} diff --git a/osu.Game.Tournament/Components/MatchChatDisplay.cs b/osu.Game.Tournament/Components/MatchChatDisplay.cs new file mode 100644 index 0000000000..a68507044d --- /dev/null +++ b/osu.Game.Tournament/Components/MatchChatDisplay.cs @@ -0,0 +1,167 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.Chat; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Tournament.Components +{ + public class MatchChatDisplay : CompositeDrawable + { + private Channel lastChannel; + public readonly Bindable Channel = new Bindable(); + private readonly FillFlowContainer messagesFlow; + + public MatchChatDisplay() + { + CornerRadius = 5; + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + Colour = Color4.Black, + Alpha = 0.8f, + RelativeSizeAxes = Axes.Both, + }, + messagesFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + LayoutEasing = Easing.Out, + LayoutDuration = 500, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Direction = FillDirection.Vertical, + }, + }; + + Channel.BindValueChanged(channelChanged); + } + + private void channelChanged(Channel channel) + { + if (lastChannel != null) + lastChannel.NewMessagesArrived -= newMessages; + + lastChannel = channel; + + channel.NewMessagesArrived += newMessages; + } + + private void newMessages(IEnumerable messages) + { + var excessChildren = messagesFlow.Children.Count - 10; + if (excessChildren > 0) + { + foreach (var c in messagesFlow.Children.Take(excessChildren)) + c.Expire(); + } + + foreach (var message in messages) + { + var formatted = MessageFormatter.FormatMessage(message); + messagesFlow.Add(new MatchMessage(formatted) { Y = messagesFlow.Height }); + } + } + + private class MatchMessage : CompositeDrawable + { + private readonly Message message; + + public MatchMessage(Message message) + { + this.message = message; + } + + private readonly Color4 red = new Color4(186, 0, 18, 255); + private readonly Color4 blue = new Color4(17, 136, 170, 255); + + [BackgroundDependencyLoader] + private void load(LadderInfo info) + { + Circle colourBox; + + Margin = new MarginPadding(3); + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + OsuSpriteText senderText; + InternalChildren = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + Width = 0.2f, + Children = new Drawable[] + { + senderText = new OsuSpriteText + { + Font = @"Exo2.0-Bold", + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Text = message.Sender.ToString() + } + } + }, + new Container + { + Size = new Vector2(8, OsuSpriteText.FONT_SIZE), + Margin = new MarginPadding { Horizontal = 3 }, + Children = new Drawable[] + { + colourBox = new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(8), + }, + } + }, + new OsuTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Width = 0.5f, + Text = message.DisplayContent + } + } + }, + }; + + if (message.Sender.Colour != null) + { + senderText.Colour = colourBox.Colour = OsuColour.FromHex(message.Sender.Colour); + } + else if (info.CurrentMatch.Value.Team1.Value.Players.Any(u => u.Id == message.Sender.Id)) + { + colourBox.Colour = red; + } + else if (info.CurrentMatch.Value.Team2.Value.Players.Any(u => u.Id == message.Sender.Id)) + { + colourBox.Colour = blue; + } + } + } + } +} diff --git a/osu.Game/Online/Chat/Message.cs b/osu.Game/Online/Chat/Message.cs index 3f0f352ac7..2eb3ca70c2 100644 --- a/osu.Game/Online/Chat/Message.cs +++ b/osu.Game/Online/Chat/Message.cs @@ -13,10 +13,6 @@ namespace osu.Game.Online.Chat [JsonProperty(@"message_id")] public readonly long? Id; - //todo: this should be inside sender. - [JsonProperty(@"sender_id")] - public long UserId; - [JsonProperty(@"channel_id")] public long ChannelId; From c9e2ee8f5623c229248b4618022d7024b05b0448 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Nov 2018 18:14:42 +0900 Subject: [PATCH 0274/5608] Fix masking of song bar --- osu.Game.Tournament/Components/SongBar.cs | 39 ++++++++++++------- .../Components/TournamentBeatmapPanel.cs | 2 +- .../Screens/Gameplay/GameplayScreen.cs | 6 +++ 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index d145544b76..94848b9130 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -48,14 +48,23 @@ namespace osu.Game.Tournament.Components private Container panelContents; private Container innerPanel; private Container outerPanel; + private TournamentBeatmapPanel panel; + + private float panelWidth => expanded ? 0.6f : 1; private const float main_width = 0.97f; + private bool expanded; + public bool Expanded { + get => expanded; set { - if (value) + expanded = value; + panel.ResizeWidthTo(panelWidth, 800, Easing.OutQuint); + + if (expanded) { innerPanel.ResizeWidthTo(0.7f, 800, Easing.OutQuint); outerPanel.ResizeWidthTo(main_width, 800, Easing.OutQuint); @@ -63,7 +72,7 @@ namespace osu.Game.Tournament.Components else { innerPanel.ResizeWidthTo(1, 800, Easing.OutQuint); - outerPanel.ResizeWidthTo(0.3f, 800, Easing.OutQuint); + outerPanel.ResizeWidthTo(0.2f, 800, Easing.OutQuint); } } } @@ -91,7 +100,7 @@ namespace osu.Game.Tournament.Components RelativePositionAxes = Axes.X, X = -(1 - main_width) / 2, Y = -10, - Width = 0.95f, + Width = main_width, Height = TournamentBeatmapPanel.HEIGHT, CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, Children = new Drawable[] @@ -101,6 +110,15 @@ namespace osu.Game.Tournament.Components RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.93f), }, + new OsuLogo + { + Triangles = false, + Colour = OsuColour.Gray(0.33f), + Scale = new Vector2(0.08f), + Margin = new MarginPadding(50), + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + }, innerPanel = new Container { Masking = true, @@ -121,15 +139,6 @@ namespace osu.Game.Tournament.Components RelativeSizeAxes = Axes.Both, } } - }, - new OsuLogo - { - Triangles = false, - Colour = OsuColour.Gray(0.33f), - Scale = new Vector2(0.08f), - Margin = new MarginPadding(50), - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, } } } @@ -193,10 +202,12 @@ namespace osu.Game.Tournament.Components Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight }, - new TournamentBeatmapPanel(beatmap) + panel = new TournamentBeatmapPanel(beatmap) { Anchor = Anchor.Centre, - Origin = Anchor.Centre + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(panelWidth, 1) } }; } diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index d2bc790b16..4456abb48e 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -44,7 +44,7 @@ namespace osu.Game.Tournament.Components currentMatch.BindValueChanged(matchChanged); currentMatch.BindTo(ladder.CurrentMatch); - CornerRadius = 25; + CornerRadius = HEIGHT / 2; Masking = true; AddRangeInternal(new Drawable[] diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index a86c47839b..d3fd08bb8b 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -91,6 +91,12 @@ namespace osu.Game.Tournament.Screens.Gameplay RelativeSizeAxes = Axes.X, Text = "Toggle warmup", Action = () => warmup.Toggle() + }, + new TriangleButton + { + RelativeSizeAxes = Axes.X, + Text = "Toggle chat", + Action = () => { State.Value = State.Value == TourneyState.Idle ? TourneyState.Playing : TourneyState.Idle; } } } } From e3e92f430221b2e477632a7eceb1a11684d53383 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Nov 2018 19:43:54 +0900 Subject: [PATCH 0275/5608] Add chat IPC and gameplay screen integration --- .../Components/MatchChatDisplay.cs | 38 ++++++++++++++++++- osu.Game.Tournament/Components/SongBar.cs | 4 +- osu.Game.Tournament/IPC/FileBasedIPC.cs | 1 + osu.Game.Tournament/IPC/MatchIPCInfo.cs | 1 + .../Screens/Gameplay/GameplayScreen.cs | 23 ++++++++++- osu.Game/Online/Chat/ChannelType.cs | 3 +- 6 files changed, 63 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tournament/Components/MatchChatDisplay.cs b/osu.Game.Tournament/Components/MatchChatDisplay.cs index a68507044d..c44eb88ef8 100644 --- a/osu.Game.Tournament/Components/MatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/MatchChatDisplay.cs @@ -12,6 +12,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; +using osu.Game.Tournament.IPC; using OpenTK; using OpenTK.Graphics; @@ -25,7 +26,7 @@ namespace osu.Game.Tournament.Components public MatchChatDisplay() { - CornerRadius = 5; + CornerRadius = 10; Masking = true; InternalChildren = new Drawable[] @@ -51,13 +52,46 @@ namespace osu.Game.Tournament.Components Channel.BindValueChanged(channelChanged); } + private readonly Bindable chatChannel = new Bindable(); + + private ChannelManager manager; + + [BackgroundDependencyLoader(true)] + private void load(MatchIPCInfo ipc) + { + if (ipc != null) + { + AddInternal(manager = new ChannelManager()); + + Channel.BindTo(manager.CurrentChannel); + + chatChannel.BindTo(ipc.ChatChannel); + chatChannel.BindValueChanged(channelString => + { + if (string.IsNullOrWhiteSpace(channelString)) + return; + + int id = int.Parse(channelString); + + var channel = manager.JoinedChannels.FirstOrDefault(ch => ch.Id == id) ?? new Channel + { + Id = id, + Type = ChannelType.Public + }; + + manager.JoinChannel(channel); + manager.CurrentChannel.Value = channel; + + }, true); + } + } + private void channelChanged(Channel channel) { if (lastChannel != null) lastChannel.NewMessagesArrived -= newMessages; lastChannel = channel; - channel.NewMessagesArrived += newMessages; } diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 94848b9130..53dec8e0a4 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -62,7 +62,7 @@ namespace osu.Game.Tournament.Components set { expanded = value; - panel.ResizeWidthTo(panelWidth, 800, Easing.OutQuint); + panel?.ResizeWidthTo(panelWidth, 800, Easing.OutQuint); if (expanded) { @@ -72,7 +72,7 @@ namespace osu.Game.Tournament.Components else { innerPanel.ResizeWidthTo(1, 800, Easing.OutQuint); - outerPanel.ResizeWidthTo(0.2f, 800, Easing.OutQuint); + outerPanel.ResizeWidthTo(0.25f, 800, Easing.OutQuint); } } } diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 6759122c16..87c6fb4c83 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -53,6 +53,7 @@ namespace osu.Game.Tournament.IPC } Mods.Value = (LegacyMods)mods; + ChatChannel.Value = sr.ReadLine(); } } catch diff --git a/osu.Game.Tournament/IPC/MatchIPCInfo.cs b/osu.Game.Tournament/IPC/MatchIPCInfo.cs index d40ec35808..be31df8009 100644 --- a/osu.Game.Tournament/IPC/MatchIPCInfo.cs +++ b/osu.Game.Tournament/IPC/MatchIPCInfo.cs @@ -13,6 +13,7 @@ namespace osu.Game.Tournament.IPC public Bindable Beatmap { get; } = new Bindable(); public Bindable Mods { get; } = new Bindable(); public Bindable State { get; } = new Bindable(); + public Bindable ChatChannel { get; } = new Bindable(); public BindableInt Score1 { get; } = new BindableInt(); public BindableInt Score2 { get; } = new BindableInt(); } diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index d3fd08bb8b..3c6ea39ae7 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -13,6 +13,7 @@ using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Screens.Gameplay.Components; using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK; using OpenTK.Graphics; namespace osu.Game.Tournament.Screens.Gameplay @@ -82,6 +83,14 @@ namespace osu.Game.Tournament.Screens.Gameplay }, } }, + chat = new MatchChatDisplay + { + RelativeSizeAxes = Axes.X, + Size = new Vector2(0.45f, 120), + Margin = new MarginPadding(10), + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + }, new ControlPanel { Children = new Drawable[] @@ -102,8 +111,8 @@ namespace osu.Game.Tournament.Screens.Gameplay } }); - State.BindValueChanged(stateChanged); State.BindTo(ipc.State); + State.BindValueChanged(stateChanged, true); currentMatch.BindValueChanged(m => warmup.Value = m.Team1Score + m.Team2Score == 0); currentMatch.BindTo(ladder.CurrentMatch); @@ -112,6 +121,7 @@ namespace osu.Game.Tournament.Screens.Gameplay } private ScheduledDelegate scheduledBarContract; + private MatchChatDisplay chat; private void stateChanged(TourneyState state) { @@ -132,12 +142,21 @@ namespace osu.Game.Tournament.Screens.Gameplay case TourneyState.Idle: // show chat SongBar.Expanded = false; + using (chat.BeginDelayedSequence(500)) + { + chat.FadeIn(300); + chat.MoveToY(100).MoveToY(0, 500, Easing.OutQuint); + } + break; case TourneyState.Ranking: scheduledBarContract = Scheduler.AddDelayed(() => SongBar.Expanded = false, 15000); break; default: - SongBar.Expanded = true; + chat.FadeOut(200); + chat.MoveToY(100, 500, Easing.In); + using (SongBar.BeginDelayedSequence(300, true)) + SongBar.Expanded = true; break; } } diff --git a/osu.Game/Online/Chat/ChannelType.cs b/osu.Game/Online/Chat/ChannelType.cs index 4ac0a99fc6..2fbc48fb92 100644 --- a/osu.Game/Online/Chat/ChannelType.cs +++ b/osu.Game/Online/Chat/ChannelType.cs @@ -6,6 +6,7 @@ namespace osu.Game.Online.Chat public enum ChannelType { PM, - Public + Public, + Temporary } } From 5801ed7b1ae88d0c2bf8bd0477f893a730121c87 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Nov 2018 19:49:17 +0900 Subject: [PATCH 0276/5608] Adjust spacing on map pool screen --- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index c2cefd8c41..65f4bfb149 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tournament.Screens.MapPool maps = new FillFlowContainer { Y = 100, - Spacing = new Vector2(10), + Spacing = new Vector2(10, 20), Padding = new MarginPadding(50), Direction = FillDirection.Full, RelativeSizeAxes = Axes.Both, From 67bb428aefdaf9625b9334d651a18ab076ea5831 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Nov 2018 20:14:34 +0900 Subject: [PATCH 0277/5608] Move editing functionality to its own screen --- .../TestCaseLadderManager.cs | 2 +- .../Ladder/Components/DrawableMatchPairing.cs | 18 +- .../Ladder/Components/DrawableMatchTeam.cs | 16 +- .../Ladder/Components/LadderEditorInfo.cs | 1 - .../Ladder/Components/LadderEditorSettings.cs | 15 - .../Screens/Ladder/Components/MatchPairing.cs | 2 +- .../Screens/Ladder/LadderEditorScreen.cs | 166 +++++++++++ .../Screens/Ladder/LadderManager.cs | 259 ------------------ .../Screens/Ladder/LadderScreen.cs | 135 +++++++++ .../Screens/TournamentSceneManager.cs | 8 +- osu.Game.Tournament/TournamentGameBase.cs | 4 - 11 files changed, 328 insertions(+), 298 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs delete mode 100644 osu.Game.Tournament/Screens/Ladder/LadderManager.cs create mode 100644 osu.Game.Tournament/Screens/Ladder/LadderScreen.cs diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index 63c8f5e391..3001f46ed2 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tournament.Tests Add(new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - Child = new LadderManager() + Child = new LadderScreen() }); } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index def53ce510..0e9baf33d2 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -30,8 +30,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { Pairing = pairing; - Position = new Vector2(pairing.Position.X, pairing.Position.Y); - AutoSizeAxes = Axes.Both; Margin = new MarginPadding(5); @@ -69,6 +67,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Spacing = new Vector2(2) } }; + pairing.Team1.BindValueChanged(_ => updateTeams()); pairing.Team2.BindValueChanged(_ => updateTeams()); pairing.Team1Score.BindValueChanged(_ => updateWinConditions()); @@ -79,6 +78,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components pairing.LosersProgression.BindValueChanged(_ => updateProgression()); pairing.Losers.BindValueChanged(_ => updateTeams()); pairing.Current.BindValueChanged(_ => updateCurrentMatch(), true); + pairing.Position.BindValueChanged(pos => + { + if (IsDragged) return; + Position = new Vector2(pos.X, pos.Y); + }, true); updateTeams(); } @@ -205,13 +209,13 @@ namespace osu.Game.Tournament.Screens.Ladder.Components updateWinConditions(); } - protected override bool OnMouseDown(MouseDownEvent e) => e.Button == MouseButton.Left && editorInfo.EditingEnabled; + protected override bool OnMouseDown(MouseDownEvent e) => e.Button == MouseButton.Left && editorInfo != null; - protected override bool OnDragStart(DragStartEvent e) => editorInfo.EditingEnabled; + protected override bool OnDragStart(DragStartEvent e) => editorInfo != null; protected override bool OnKeyDown(KeyDownEvent e) { - if (Selected && editorInfo.EditingEnabled && e.Key == Key.Delete) + if (Selected && editorInfo != null && e.Key == Key.Delete) { Remove(); return true; @@ -222,7 +226,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components protected override bool OnClick(ClickEvent e) { - if (!editorInfo.EditingEnabled) + if (editorInfo == null) return false; Selected = true; @@ -237,7 +241,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components this.MoveToOffset(e.Delta); var pos = Position; - Pairing.Position = new Point((int)pos.X, (int)pos.Y); + Pairing.Position.Value = new Point((int)pos.X, (int)pos.Y); return true; } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 7ff15ef434..be09443684 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -34,7 +34,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private Color4 colourNormal; private readonly Func isWinner; - private LadderManager manager; + private LadderEditorScreen ladderEditor; [Resolved] private LadderInfo ladderInfo { get; set; } @@ -80,9 +80,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, LadderManager manager) + private void load(OsuColour colours, LadderEditorScreen ladderEditor) { - this.manager = manager; + this.ladderEditor = ladderEditor; colourWinner = losers ? colours.YellowDarker : colours.BlueDarker; colourNormal = OsuColour.Gray(0.2f); @@ -141,7 +141,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components //TODO: use OnClick instead once we have per-button clicks. protected override bool OnClick(ClickEvent e) { - if (Team == null || editorInfo.EditingEnabled) return false; + if (Team == null || editorInfo != null) return false; if (!pairing.Current.Value) { @@ -190,15 +190,15 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { get { - if (!editorInfo.EditingEnabled) + if (editorInfo == null) return new MenuItem[0]; return new MenuItem[] { new OsuMenuItem("Set as current", MenuItemType.Standard, setCurrent), - new OsuMenuItem("Join with", MenuItemType.Standard, () => manager.RequestJoin(pairing, false)), - new OsuMenuItem("Join with (loser)", MenuItemType.Standard, () => manager.RequestJoin(pairing, true)), - new OsuMenuItem("Remove", MenuItemType.Destructive, () => manager.Remove(pairing)), + new OsuMenuItem("Join with", MenuItemType.Standard, () => ladderEditor.RequestJoin(pairing, false)), + new OsuMenuItem("Join with (loser)", MenuItemType.Standard, () => ladderEditor.RequestJoin(pairing, true)), + new OsuMenuItem("Remove", MenuItemType.Destructive, () => ladderEditor.Remove(pairing)), }; } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs index 0ecf387f7c..1fd9455195 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs @@ -7,7 +7,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public class LadderEditorInfo { - public readonly BindableBool EditingEnabled = new BindableBool(); public readonly Bindable Selected = new Bindable(); } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index afb20a68f0..90f20a3494 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -39,11 +39,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Children = new Drawable[] { - new PlayerCheckbox - { - Bindable = editorInfo.EditingEnabled, - LabelText = "Enable editing" - }, new Container { RelativeSizeAxes = Axes.X, @@ -119,16 +114,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components if (editorInfo.Selected.Value != null) editorInfo.Selected.Value.Losers.Value = losers; }; - - // sliderBestOf.Bindable.ValueChanged += val => - // { - // if (editorInfo.Selected.Value != null) editorInfo.Selected.Value.BestOf.Value = (int)val; - // }; - - editorInfo.EditingEnabled.ValueChanged += enabled => - { - if (!enabled) editorInfo.Selected.Value = null; - }; } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index 729249c3d7..003f41cfa9 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -53,7 +53,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly Bindable Date = new Bindable(); - public Point Position; + public readonly Bindable Position = new Bindable(); public MatchPairing() { diff --git a/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs new file mode 100644 index 0000000000..cebf7bb682 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs @@ -0,0 +1,166 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Framework.Input.States; +using osu.Game.Graphics.UserInterface; +using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK; +using OpenTK.Graphics; +using SixLabors.Primitives; + +namespace osu.Game.Tournament.Screens.Ladder +{ + [Cached] + public class LadderEditorScreen : LadderScreen, IHasContextMenu + { + [Cached] + private LadderEditorInfo editorInfo = new LadderEditorInfo(); + + [BackgroundDependencyLoader] + private void load() + { + ((Container)InternalChild).Add(new LadderEditorSettings + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Margin = new MarginPadding(5) + }); + } + + private void updateInfo() + { + LadderInfo.Pairings = PairingsContainer.Select(p => p.Pairing).ToList(); + foreach (var g in LadderInfo.Groupings) + g.Pairings = LadderInfo.Pairings.Where(p => p.Grouping.Value == g).Select(p => p.ID).ToList(); + + LadderInfo.Progressions = LadderInfo.Pairings.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( + LadderInfo.Pairings.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) + .ToList(); + } + + protected override void AddPairing(MatchPairing pairing) + { + base.AddPairing(pairing); + updateInfo(); + } + + protected override void UpdateLayout() + { + base.UpdateLayout(); + updateInfo(); + } + + public void RequestJoin(MatchPairing pairing, bool losers) + { + ScrollContent.Add(new JoinRequestHandler(PairingsContainer, pairing, losers, updateInfo)); + } + + public MenuItem[] ContextMenuItems + { + get + { + if (editorInfo == null) + return new MenuItem[0]; + + return new MenuItem[] + { + new OsuMenuItem("Create new match", MenuItemType.Highlighted, () => + { + var pos = PairingsContainer.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position); + AddPairing(new MatchPairing { Position = { Value = new Point((int)pos.X, (int)pos.Y) } }); + }), + }; + } + } + + public void Remove(MatchPairing pairing) + { + PairingsContainer.FirstOrDefault(p => p.Pairing == pairing)?.Remove(); + } + + private class JoinRequestHandler : CompositeDrawable + { + private readonly Container pairingsContainer; + public readonly MatchPairing Source; + private readonly bool losers; + private readonly Action complete; + + private ProgressionPath path; + + public JoinRequestHandler(Container pairingsContainer, MatchPairing source, bool losers, Action complete) + { + this.pairingsContainer = pairingsContainer; + RelativeSizeAxes = Axes.Both; + + Source = source; + this.losers = losers; + this.complete = complete; + if (losers) + Source.LosersProgression.Value = null; + else + Source.Progression.Value = null; + } + + private DrawableMatchPairing findTarget(InputState state) + { + return pairingsContainer.FirstOrDefault(d => d.ReceivePositionalInputAt(state.Mouse.Position)); + } + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) + { + return true; + } + + protected override bool OnMouseMove(MouseMoveEvent e) + { + var found = findTarget(e.CurrentState); + + if (found == path?.Destination) + return false; + + path?.Expire(); + path = null; + + if (found == null) + return false; + + AddInternal(path = new ProgressionPath(pairingsContainer.First(c => c.Pairing == Source), found) + { + Colour = Color4.Yellow, + }); + + return base.OnMouseMove(e); + } + + protected override bool OnClick(ClickEvent e) + { + var found = findTarget(e.CurrentState); + + if (found != null) + { + if (found.Pairing != Source) + { + if (losers) + Source.LosersProgression.Value = found.Pairing; + else + Source.Progression.Value = found.Pairing; + } + + complete?.Invoke(); + Expire(); + return true; + } + + return false; + } + } + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs b/osu.Game.Tournament/Screens/Ladder/LadderManager.cs deleted file mode 100644 index 2b1a1bad85..0000000000 --- a/osu.Game.Tournament/Screens/Ladder/LadderManager.cs +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Caching; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Lines; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Events; -using osu.Framework.Input.States; -using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; -using osu.Game.Tournament.Screens.Ladder.Components; -using OpenTK; -using OpenTK.Graphics; -using SixLabors.Primitives; - -namespace osu.Game.Tournament.Screens.Ladder -{ - [Cached] - public class LadderManager : TournamentScreen, IHasContextMenu - { - private Container pairingsContainer; - private Container paths; - private Container headings; - - private ScrollableContainer scrollContent; - - [Resolved] - private LadderEditorInfo editorInfo { get; set;} - - [Resolved] - private LadderInfo ladderInfo { get; set; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - normalPathColour = colours.BlueDarker.Darken(2); - losersPathColour = colours.YellowDarker.Darken(2); - - RelativeSizeAxes = Axes.Both; - - InternalChild = new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - scrollContent = new ScrollableContainer - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - paths = new Container { RelativeSizeAxes = Axes.Both }, - headings = new Container { RelativeSizeAxes = Axes.Both }, - pairingsContainer = new Container { RelativeSizeAxes = Axes.Both }, - } - }, - new LadderEditorSettings - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Margin = new MarginPadding(5) - } - } - }; - - foreach (var pairing in ladderInfo.Pairings) - addPairing(pairing); - - // todo: fix this - Scheduler.AddDelayed(() => layout.Invalidate(), 100, true); - } - - private void updateInfo() - { - ladderInfo.Pairings = pairingsContainer.Select(p => p.Pairing).ToList(); - foreach (var g in ladderInfo.Groupings) - g.Pairings = ladderInfo.Pairings.Where(p => p.Grouping.Value == g).Select(p => p.ID).ToList(); - - ladderInfo.Progressions = ladderInfo.Pairings.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( - ladderInfo.Pairings.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) - .ToList(); - } - - private void addPairing(MatchPairing pairing) - { - pairingsContainer.Add(new DrawableMatchPairing(pairing)); - updateInfo(); - } - - public MenuItem[] ContextMenuItems - { - get - { - if (!editorInfo.EditingEnabled) - return new MenuItem[0]; - - return new MenuItem[] - { - new OsuMenuItem("Create new match", MenuItemType.Highlighted, () => - { - var pos = pairingsContainer.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position); - addPairing(new MatchPairing { Position = new Point((int)pos.X, (int)pos.Y) }); - }), - }; - } - } - - private Cached layout = new Cached(); - - protected override void Update() - { - base.Update(); - - if (!layout.IsValid) - updateLayout(); - } - - private Color4 normalPathColour; - private Color4 losersPathColour; - - private void updateLayout() - { - paths.Clear(); - headings.Clear(); - - int id = 1; - foreach (var pairing in pairingsContainer.OrderBy(d => d.Y).ThenBy(d => d.X)) - { - pairing.Pairing.ID = id++; - - if (pairing.Pairing.Progression.Value != null) - { - var dest = pairingsContainer.FirstOrDefault(p => p.Pairing == pairing.Pairing.Progression.Value); - - if (dest == null) - // clean up outdated progressions. - pairing.Pairing.Progression.Value = null; - else - paths.Add(new ProgressionPath(pairing, dest) { Colour = pairing.Pairing.Losers ? losersPathColour : normalPathColour }); - } - } - - foreach (var group in ladderInfo.Groupings) - { - var topPairing = pairingsContainer.Where(p => !p.Pairing.Losers && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); - - if (topPairing == null) continue; - - headings.Add(new DrawableTournamentGrouping(group) - { - Position = headings.ToLocalSpace((topPairing.ScreenSpaceDrawQuad.TopLeft + topPairing.ScreenSpaceDrawQuad.TopRight) / 2), - Margin = new MarginPadding { Bottom = 10 }, - Origin = Anchor.BottomCentre, - }); - } - - foreach (var group in ladderInfo.Groupings) - { - var topPairing = pairingsContainer.Where(p => p.Pairing.Losers && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); - - if (topPairing == null) continue; - - headings.Add(new DrawableTournamentGrouping(group, true) - { - Position = headings.ToLocalSpace((topPairing.ScreenSpaceDrawQuad.TopLeft + topPairing.ScreenSpaceDrawQuad.TopRight) / 2), - Margin = new MarginPadding { Bottom = 10 }, - Origin = Anchor.BottomCentre, - }); - } - - layout.Validate(); - updateInfo(); - } - - public void RequestJoin(MatchPairing pairing, bool losers) => scrollContent.Add(new JoinRequestHandler(pairingsContainer, pairing, losers, updateInfo)); - - // todo: remove after ppy/osu-framework#1980 is merged. - public override bool HandlePositionalInput => true; - - public void Remove(MatchPairing pairing) => pairingsContainer.FirstOrDefault(p => p.Pairing == pairing)?.Remove(); - - private class JoinRequestHandler : CompositeDrawable - { - private readonly Container pairingsContainer; - public readonly MatchPairing Source; - private readonly bool losers; - private readonly Action complete; - - private ProgressionPath path; - - public JoinRequestHandler(Container pairingsContainer, MatchPairing source, bool losers, Action complete) - { - this.pairingsContainer = pairingsContainer; - RelativeSizeAxes = Axes.Both; - - Source = source; - this.losers = losers; - this.complete = complete; - if (losers) - Source.LosersProgression.Value = null; - else - Source.Progression.Value = null; - } - - private DrawableMatchPairing findTarget(InputState state) => pairingsContainer.FirstOrDefault(d => d.ReceivePositionalInputAt(state.Mouse.Position)); - - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; - - protected override bool OnMouseMove(MouseMoveEvent e) - { - var found = findTarget(e.CurrentState); - - if (found == path?.Destination) - return false; - - path?.Expire(); - path = null; - - if (found == null) - return false; - - AddInternal(path = new ProgressionPath(pairingsContainer.First(c => c.Pairing == Source), found) - { - Colour = Color4.Yellow, - }); - - return base.OnMouseMove(e); - } - - protected override bool OnClick(ClickEvent e) - { - var found = findTarget(e.CurrentState); - - if (found != null) - { - if (found.Pairing != Source) - { - if (losers) - Source.LosersProgression.Value = found.Pairing; - else - Source.Progression.Value = found.Pairing; - } - - complete?.Invoke(); - Expire(); - return true; - } - - return false; - } - } - } -} diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs new file mode 100644 index 0000000000..69035c21db --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -0,0 +1,135 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Caching; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Lines; +using osu.Game.Graphics; +using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK.Graphics; + +namespace osu.Game.Tournament.Screens.Ladder +{ + public class LadderScreen : TournamentScreen + { + protected Container PairingsContainer; + private Container paths; + private Container headings; + + protected ScrollableContainer ScrollContent; + + [Resolved] + protected LadderInfo LadderInfo { get; private set; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + normalPathColour = colours.BlueDarker.Darken(2); + losersPathColour = colours.YellowDarker.Darken(2); + + RelativeSizeAxes = Axes.Both; + + InternalChild = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + ScrollContent = new ScrollableContainer + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + paths = new Container { RelativeSizeAxes = Axes.Both }, + headings = new Container { RelativeSizeAxes = Axes.Both }, + PairingsContainer = new Container { RelativeSizeAxes = Axes.Both }, + } + }, + } + }; + + foreach (var pairing in LadderInfo.Pairings) + AddPairing(pairing); + + // todo: fix this + Scheduler.AddDelayed(() => layout.Invalidate(), 100, true); + } + + protected virtual void AddPairing(MatchPairing pairing) + { + PairingsContainer.Add(new DrawableMatchPairing(pairing)); + } + + private Cached layout = new Cached(); + + protected override void Update() + { + base.Update(); + + if (!layout.IsValid) + UpdateLayout(); + } + + private Color4 normalPathColour; + private Color4 losersPathColour; + + protected virtual void UpdateLayout() + { + paths.Clear(); + headings.Clear(); + + int id = 1; + foreach (var pairing in PairingsContainer.OrderBy(d => d.Y).ThenBy(d => d.X)) + { + pairing.Pairing.ID = id++; + + if (pairing.Pairing.Progression.Value != null) + { + var dest = PairingsContainer.FirstOrDefault(p => p.Pairing == pairing.Pairing.Progression.Value); + + if (dest == null) + // clean up outdated progressions. + pairing.Pairing.Progression.Value = null; + else + paths.Add(new ProgressionPath(pairing, dest) { Colour = pairing.Pairing.Losers ? losersPathColour : normalPathColour }); + } + } + + foreach (var group in LadderInfo.Groupings) + { + var topPairing = PairingsContainer.Where(p => !p.Pairing.Losers && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); + + if (topPairing == null) continue; + + headings.Add(new DrawableTournamentGrouping(group) + { + Position = headings.ToLocalSpace((topPairing.ScreenSpaceDrawQuad.TopLeft + topPairing.ScreenSpaceDrawQuad.TopRight) / 2), + Margin = new MarginPadding { Bottom = 10 }, + Origin = Anchor.BottomCentre, + }); + } + + foreach (var group in LadderInfo.Groupings) + { + var topPairing = PairingsContainer.Where(p => p.Pairing.Losers && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); + + if (topPairing == null) continue; + + headings.Add(new DrawableTournamentGrouping(group, true) + { + Position = headings.ToLocalSpace((topPairing.ScreenSpaceDrawQuad.TopLeft + topPairing.ScreenSpaceDrawQuad.TopRight) / 2), + Margin = new MarginPadding { Bottom = 10 }, + Origin = Anchor.BottomCentre, + }); + } + + layout.Validate(); + } + + // todo: remove after ppy/osu-framework#1980 is merged. + public override bool HandlePositionalInput => true; + } +} diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index 02492953f2..de9e6ee19d 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -25,7 +25,8 @@ namespace osu.Game.Tournament.Screens public class TournamentSceneManager : OsuScreen { private ScheduleScreen schedule; - private LadderManager bracket; + private LadderScreen bracket; + private LadderEditorScreen bracketEditor; private MapPoolScreen mapPool; private GameplayScreen gameplay; private TeamWinScreen winner; @@ -57,6 +58,8 @@ namespace osu.Game.Tournament.Screens Direction = FillDirection.Vertical, Children = new Drawable[] { + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => setScreen(bracketEditor) }, + new Container { RelativeSizeAxes = Axes.X, Height = 50 }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => setScreen(drawings) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => setScreen(showcase) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, @@ -96,7 +99,8 @@ namespace osu.Game.Tournament.Screens Children = new Drawable[] { schedule = new ScheduleScreen(), - bracket = new LadderManager(), + bracket = new LadderScreen(), + bracketEditor = new LadderEditorScreen(), showcase = new ShowcaseScreen(), mapPool = new MapPoolScreen(), teamIntro = new TeamIntroScreen(), diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 31a3c162f5..8734b2e64b 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -19,7 +19,6 @@ using osu.Game.Online.API.Requests; using osu.Game.Rulesets; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; -using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament { @@ -35,9 +34,6 @@ namespace osu.Game.Tournament [Cached] private readonly Bindable ruleset = new Bindable(); - [Cached] - private LadderEditorInfo editorInfo = new LadderEditorInfo(); - private Bindable windowSize; private FileBasedIPC ipc; From cf0976955bb36edf5be7ed9797cb2c8e2a19f1a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Nov 2018 20:30:12 +0900 Subject: [PATCH 0278/5608] Expose groupings editor --- .../TestCaseGroupingsEditorScreen.cs | 15 ++++++++ .../Groupings/GroupingsEditorScreen.cs | 37 +++++++++++++------ .../Ladder/Components/LadderEditorSettings.cs | 11 ++++++ .../Screens/Ladder/LadderScreen.cs | 3 -- .../Screens/TournamentSceneManager.cs | 4 ++ .../Screens/TournamentScreen.cs | 4 ++ 6 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 osu.Game.Tournament.Tests/TestCaseGroupingsEditorScreen.cs rename osu.Game.Tournament.Tests/TestCaseGroupingManager.cs => osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs (69%) diff --git a/osu.Game.Tournament.Tests/TestCaseGroupingsEditorScreen.cs b/osu.Game.Tournament.Tests/TestCaseGroupingsEditorScreen.cs new file mode 100644 index 0000000000..4e82e27fd9 --- /dev/null +++ b/osu.Game.Tournament.Tests/TestCaseGroupingsEditorScreen.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Tournament.Screens.Groupings; + +namespace osu.Game.Tournament.Tests +{ + public class TestCaseGroupingsEditorScreen : LadderTestCase + { + public TestCaseGroupingsEditorScreen() + { + Add(new GroupingsEditorScreen()); + } + } +} diff --git a/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs similarity index 69% rename from osu.Game.Tournament.Tests/TestCaseGroupingManager.cs rename to osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs index 531019c28c..1b7e9e6bd1 100644 --- a/osu.Game.Tournament.Tests/TestCaseGroupingManager.cs +++ b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -9,13 +10,13 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Screens.Ladder.Components; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Screens.Groupings { - public class TestCaseGroupingManager : LadderTestCase + public class GroupingsEditorScreen : TournamentScreen, IProvideVideo { private readonly FillFlowContainer items; - public TestCaseGroupingManager() + public GroupingsEditorScreen() { Add(new FillFlowContainer { @@ -37,29 +38,37 @@ namespace osu.Game.Tournament.Tests }, } }); - } [BackgroundDependencyLoader] private void load() { - foreach (var g in Ladder.Groupings) - items.Add(new GroupingRow(g)); + foreach (var g in LadderInfo.Groupings) + items.Add(new GroupingRow(g, updateGroupings)); } - protected override void Dispose(bool isDisposing) + protected override void LoadComplete() { - Ladder.Groupings = items.Children.Select(c => c.Grouping).ToList(); - base.Dispose(isDisposing); + base.LoadComplete(); + Scheduler.AddDelayed(() => LadderInfo.Groupings = items.Children.Select(c => c.Grouping).ToList(), 500, true); } - private void addNew() => items.Add(new GroupingRow(new TournamentGrouping())); + private void addNew() + { + items.Add(new GroupingRow(new TournamentGrouping(), updateGroupings)); + updateGroupings(); + } + + private void updateGroupings() + { + LadderInfo.Groupings = items.Children.Select(c => c.Grouping).ToList(); + } public class GroupingRow : CompositeDrawable { public readonly TournamentGrouping Grouping; - public GroupingRow(TournamentGrouping grouping) + public GroupingRow(TournamentGrouping grouping, Action onDelete) { Grouping = grouping; InternalChildren = new Drawable[] @@ -77,7 +86,11 @@ namespace osu.Game.Tournament.Tests { Width = 0.1f, Text = "Delete", - Action = () => Expire() + Action = () => + { + Expire(); + onDelete(); + } }, } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index 90f20a3494..4334f75728 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; @@ -115,5 +116,15 @@ namespace osu.Game.Tournament.Screens.Ladder.Components editorInfo.Selected.Value.Losers.Value = losers; }; } + + protected override bool OnHover(HoverEvent e) + { + return false; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + } + } } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 69035c21db..5e0cb13375 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -22,9 +22,6 @@ namespace osu.Game.Tournament.Screens.Ladder protected ScrollableContainer ScrollContent; - [Resolved] - protected LadderInfo LadderInfo { get; private set; } - [BackgroundDependencyLoader] private void load(OsuColour colours) { diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index de9e6ee19d..0205838fc2 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -11,6 +11,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Screens; using osu.Game.Tournament.Screens.Drawings; using osu.Game.Tournament.Screens.Gameplay; +using osu.Game.Tournament.Screens.Groupings; using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.MapPool; using osu.Game.Tournament.Screens.Schedule; @@ -27,6 +28,7 @@ namespace osu.Game.Tournament.Screens private ScheduleScreen schedule; private LadderScreen bracket; private LadderEditorScreen bracketEditor; + private GroupingsEditorScreen groupingsEditor; private MapPoolScreen mapPool; private GameplayScreen gameplay; private TeamWinScreen winner; @@ -59,6 +61,7 @@ namespace osu.Game.Tournament.Screens Children = new Drawable[] { new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => setScreen(bracketEditor) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Groupings Editor", Action = () => setScreen(groupingsEditor) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => setScreen(drawings) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => setScreen(showcase) }, @@ -101,6 +104,7 @@ namespace osu.Game.Tournament.Screens schedule = new ScheduleScreen(), bracket = new LadderScreen(), bracketEditor = new LadderEditorScreen(), + groupingsEditor = new GroupingsEditorScreen(), showcase = new ShowcaseScreen(), mapPool = new MapPoolScreen(), teamIntro = new TeamIntroScreen(), diff --git a/osu.Game.Tournament/Screens/TournamentScreen.cs b/osu.Game.Tournament/Screens/TournamentScreen.cs index dcdd7f8ce5..b440b8e796 100644 --- a/osu.Game.Tournament/Screens/TournamentScreen.cs +++ b/osu.Game.Tournament/Screens/TournamentScreen.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Screens; @@ -8,6 +9,9 @@ namespace osu.Game.Tournament.Screens { public class TournamentScreen : OsuScreen { + [Resolved] + protected LadderInfo LadderInfo { get; private set; } + public override void Hide() { this.FadeOut(200); From 4b74105ad9a9e7fb001b3fcbbf40875975441dd1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Nov 2018 20:34:51 +0900 Subject: [PATCH 0279/5608] Fix code sanity issues --- .../{TeamWinTestCase.cs => TestCaseTeamWin.cs} | 0 osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs | 3 +++ 2 files changed, 3 insertions(+) rename osu.Game.Tournament.Tests/{TeamWinTestCase.cs => TestCaseTeamWin.cs} (100%) diff --git a/osu.Game.Tournament.Tests/TeamWinTestCase.cs b/osu.Game.Tournament.Tests/TestCaseTeamWin.cs similarity index 100% rename from osu.Game.Tournament.Tests/TeamWinTestCase.cs rename to osu.Game.Tournament.Tests/TestCaseTeamWin.cs diff --git a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs index 135081a641..4225518d53 100644 --- a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs +++ b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; From c1e3c4d4359555ddf32f4c96ac4037277dca37c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 10:40:44 +0900 Subject: [PATCH 0280/5608] Make chat tests work again, clear old messages --- .../TestCaseMatchChatDisplay.cs | 4 ++++ .../Components/MatchChatDisplay.cs | 22 ++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs b/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs index aab56d1714..cc053f8a7e 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Game.Online.Chat; using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; +using osu.Game.Tournament.IPC; using osu.Game.Tournament.Screens.Ladder.Components; using osu.Game.Users; using OpenTK; @@ -39,6 +40,9 @@ namespace osu.Game.Tournament.Tests [Cached] private LadderInfo ladderInfo = new LadderInfo(); + [Cached] + private MatchIPCInfo matchInfo = new MatchIPCInfo(); // hide parent + public TestCaseMatchChatDisplay() { MatchChatDisplay chatDisplay; diff --git a/osu.Game.Tournament/Components/MatchChatDisplay.cs b/osu.Game.Tournament/Components/MatchChatDisplay.cs index c44eb88ef8..dc8f28d9bd 100644 --- a/osu.Game.Tournament/Components/MatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/MatchChatDisplay.cs @@ -61,10 +61,6 @@ namespace osu.Game.Tournament.Components { if (ipc != null) { - AddInternal(manager = new ChannelManager()); - - Channel.BindTo(manager.CurrentChannel); - chatChannel.BindTo(ipc.ChatChannel); chatChannel.BindValueChanged(channelString => { @@ -73,7 +69,18 @@ namespace osu.Game.Tournament.Components int id = int.Parse(channelString); - var channel = manager.JoinedChannels.FirstOrDefault(ch => ch.Id == id) ?? new Channel + if (id <= 0) return; + + if (manager == null) + { + AddInternal(manager = new ChannelManager()); + Channel.BindTo(manager.CurrentChannel); + } + + foreach (var ch in manager.JoinedChannels.ToList()) + manager.LeaveChannel(ch); + + var channel = new Channel { Id = id, Type = ChannelType.Public @@ -81,7 +88,6 @@ namespace osu.Game.Tournament.Components manager.JoinChannel(channel); manager.CurrentChannel.Value = channel; - }, true); } } @@ -92,6 +98,10 @@ namespace osu.Game.Tournament.Components lastChannel.NewMessagesArrived -= newMessages; lastChannel = channel; + messagesFlow.Clear(); + + if (channel == null) return; + channel.NewMessagesArrived += newMessages; } From 2ee77670ee7682da1ef522bc666eabd32bd6f757 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 12:04:19 +0900 Subject: [PATCH 0281/5608] Add date entry for groupings --- .../Groupings/GroupingsEditorScreen.cs | 89 ++++++++++++++----- 1 file changed, 69 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs index 1b7e9e6bd1..b0bd17fe83 100644 --- a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs @@ -4,8 +4,11 @@ using System; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Screens.Ladder.Components; @@ -18,24 +21,36 @@ namespace osu.Game.Tournament.Screens.Groupings public GroupingsEditorScreen() { - Add(new FillFlowContainer + AddRange(new Drawable[] { - Direction = FillDirection.Vertical, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + new Box { - items = new FillFlowContainer + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.2f), + }, + new FillFlowContainer + { + Direction = FillDirection.Vertical, + RelativeSizeAxes = Axes.Both, + Width = 0.9f, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Children = new Drawable[] { - Direction = FillDirection.Vertical, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, - new TriangleButton - { - Width = 100, - Text = "Add", - Action = addNew - }, + items = new FillFlowContainer + { + Direction = FillDirection.Vertical, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + new TriangleButton + { + Margin = new MarginPadding(20), + Width = 100, + Text = "Add", + Action = addNew + }, + } } }); } @@ -55,11 +70,11 @@ namespace osu.Game.Tournament.Screens.Groupings private void addNew() { - items.Add(new GroupingRow(new TournamentGrouping(), updateGroupings)); + items.Add(new GroupingRow(new TournamentGrouping { StartDate = { Value = DateTimeOffset.UtcNow } }, updateGroupings)); updateGroupings(); } - private void updateGroupings() + private void updateGroupings() { LadderInfo.Groupings = items.Children.Select(c => c.Grouping).ToList(); } @@ -75,8 +90,9 @@ namespace osu.Game.Tournament.Screens.Groupings { new FillFlowContainer { - Direction = FillDirection.Horizontal, - RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Children = new Drawable[] { new SettingsTextBox { Width = 0.3f, Bindable = Grouping.Name }, @@ -92,12 +108,45 @@ namespace osu.Game.Tournament.Screens.Groupings onDelete(); } }, + new DateTextBox { Width = 0.3f, Bindable = Grouping.StartDate }, } } }; RelativeSizeAxes = Axes.X; - Height = 40; + AutoSizeAxes = Axes.Y; + } + } + } + + public class DateTextBox : SettingsTextBox + { + public DateTextBox() + { + base.Bindable = new Bindable(); + ((OsuTextBox)Control).OnCommit = (sender, newText) => { + try + { + bindable.Value = DateTimeOffset.Parse(sender.Text); + } + catch + { + bindable.TriggerChange(); + } + }; + } + + // hold a reference to the provided bindable so we don't have to in every settings section. + private Bindable bindable; + + public new Bindable Bindable + { + get { return bindable; } + + set + { + bindable = value; + bindable.BindValueChanged(dto => base.Bindable.Value = dto.ToUniversalTime().ToString(), true); } } } From 87243a72d30f1d0b06368f0e63ac4df2cff1ce1b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 12:14:15 +0900 Subject: [PATCH 0282/5608] Add date entry for pairings --- .../Ladder/Components/LadderEditorSettings.cs | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index 4334f75728..34b16ccab3 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -11,6 +12,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; using osu.Game.Screens.Play.PlayerSettings; +using osu.Game.Tournament.Screens.Groupings; namespace osu.Game.Tournament.Screens.Ladder.Components { @@ -24,6 +26,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private OsuTextBox textboxTeam2; private SettingsDropdown groupingDropdown; private PlayerCheckbox losersCheckbox; + private DateTextBox dateTimeBox; [Resolved] private LadderEditorInfo editorInfo { get; set; } @@ -81,6 +84,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { LabelText = "Losers Bracket", Bindable = new Bindable() + }, + dateTimeBox = new DateTextBox + { + Bindable = new Bindable() } }; @@ -90,6 +97,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components textboxTeam2.Text = selection?.Team2.Value?.Acronym; groupingDropdown.Bindable.Value = selection?.Grouping.Value ?? groupingOptions.First(); losersCheckbox.Current.Value = selection?.Losers.Value ?? false; + dateTimeBox.Bindable.Value = selection?.Date.Value ?? DateTimeOffset.UtcNow; }; textboxTeam1.OnCommit = (val, newText) => @@ -107,7 +115,14 @@ namespace osu.Game.Tournament.Screens.Ladder.Components groupingDropdown.Bindable.ValueChanged += grouping => { if (editorInfo.Selected.Value != null) + { editorInfo.Selected.Value.Grouping.Value = grouping; + if (editorInfo.Selected.Value.Date.Value < grouping.StartDate.Value) + { + editorInfo.Selected.Value.Date.Value = grouping.StartDate.Value; + editorInfo.Selected.TriggerChange(); + } + } }; losersCheckbox.Current.ValueChanged += losers => @@ -115,6 +130,18 @@ namespace osu.Game.Tournament.Screens.Ladder.Components if (editorInfo.Selected.Value != null) editorInfo.Selected.Value.Losers.Value = losers; }; + + dateTimeBox.Bindable.ValueChanged += date => + { + if (editorInfo.Selected.Value != null) + editorInfo.Selected.Value.Date.Value = date; + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + this.FadeIn(); } protected override bool OnHover(HoverEvent e) @@ -125,6 +152,5 @@ namespace osu.Game.Tournament.Screens.Ladder.Components protected override void OnHoverLost(HoverLostEvent e) { } - } } From 7f7d4ef442daab22e6b2c20440b405bf5b4adb83 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 13:36:36 +0900 Subject: [PATCH 0283/5608] =?UTF-8?q?Don=E2=80=99t=20hard=20fail=20if=20st?= =?UTF-8?q?able=20install=20is=20missing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 87c6fb4c83..9cc275e9e0 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -27,7 +27,18 @@ namespace osu.Game.Tournament.IPC [BackgroundDependencyLoader] private void load() { - var stable = new StableStorage(); + + StableStorage stable; + + try + { + stable = new StableStorage(); + } + catch + { + Logger.Log("Stable installation could not be found; disabling file based IPC"); + return; + } const string file_ipc_filename = "ipc.txt"; const string file_ipc_state_filename = "ipc-state.txt"; From c1e1306c976fe0cf99529945647f01ac4737e7ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 13:39:55 +0900 Subject: [PATCH 0284/5608] Show controls above screens --- .../Screens/TournamentSceneManager.cs | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index 0205838fc2..f3bc12a6cf 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -43,41 +43,6 @@ namespace osu.Game.Tournament.Screens { Children = new Drawable[] { - new Container - { - RelativeSizeAxes = Axes.Y, - Width = 200, - Children = new Drawable[] - { - new Box - { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => setScreen(bracketEditor) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Groupings Editor", Action = () => setScreen(groupingsEditor) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => setScreen(drawings) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => setScreen(showcase) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Schedule", Action = () => setScreen(schedule) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => setScreen(bracket) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => setScreen(teamIntro) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => setScreen(mapPool) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => setScreen(gameplay) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Win", Action = () => setScreen(winner) }, - } - }, - }, - }, new Container { RelativeSizeAxes = Axes.Both, @@ -115,6 +80,41 @@ namespace osu.Game.Tournament.Screens }, } }, + new Container + { + RelativeSizeAxes = Axes.Y, + Width = 200, + Children = new Drawable[] + { + new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => setScreen(bracketEditor) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Groupings Editor", Action = () => setScreen(groupingsEditor) }, + new Container { RelativeSizeAxes = Axes.X, Height = 50 }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => setScreen(drawings) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => setScreen(showcase) }, + new Container { RelativeSizeAxes = Axes.X, Height = 50 }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Schedule", Action = () => setScreen(schedule) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => setScreen(bracket) }, + new Container { RelativeSizeAxes = Axes.X, Height = 50 }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => setScreen(teamIntro) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => setScreen(mapPool) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => setScreen(gameplay) }, + new Container { RelativeSizeAxes = Axes.X, Height = 50 }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Win", Action = () => setScreen(winner) }, + } + }, + }, + }, }; setScreen(teamIntro); From bed967b456ceeb38b1d46102983e8fc0e05356ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 14:05:22 +0900 Subject: [PATCH 0285/5608] Add better date string formatting --- osu.Game.Tournament/Components/DateTextBox.cs | 44 +++++++++++++++++++ .../Groupings/GroupingsEditorScreen.cs | 36 +-------------- .../Ladder/Components/LadderEditorSettings.cs | 2 +- 3 files changed, 47 insertions(+), 35 deletions(-) create mode 100644 osu.Game.Tournament/Components/DateTextBox.cs diff --git a/osu.Game.Tournament/Components/DateTextBox.cs b/osu.Game.Tournament/Components/DateTextBox.cs new file mode 100644 index 0000000000..171196f348 --- /dev/null +++ b/osu.Game.Tournament/Components/DateTextBox.cs @@ -0,0 +1,44 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Configuration; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Settings; + +namespace osu.Game.Tournament.Components +{ + public class DateTextBox : SettingsTextBox + { + public new Bindable Bindable + { + get { return bindable; } + + set + { + bindable = value; + bindable.BindValueChanged(dto => + base.Bindable.Value = dto.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"), true); + } + } + + // hold a reference to the provided bindable so we don't have to in every settings section. + private Bindable bindable; + + public DateTextBox() + { + base.Bindable = new Bindable(); + ((OsuTextBox)Control).OnCommit = (sender, newText) => + { + try + { + bindable.Value = DateTimeOffset.Parse(sender.Text); + } + catch + { + bindable.TriggerChange(); + } + }; + } + } +} diff --git a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs index b0bd17fe83..d5d3d1dbda 100644 --- a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs @@ -4,13 +4,13 @@ using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; +using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Screens.Groupings @@ -74,7 +74,7 @@ namespace osu.Game.Tournament.Screens.Groupings updateGroupings(); } - private void updateGroupings() + private void updateGroupings() { LadderInfo.Groupings = items.Children.Select(c => c.Grouping).ToList(); } @@ -118,36 +118,4 @@ namespace osu.Game.Tournament.Screens.Groupings } } } - - public class DateTextBox : SettingsTextBox - { - public DateTextBox() - { - base.Bindable = new Bindable(); - ((OsuTextBox)Control).OnCommit = (sender, newText) => { - try - { - bindable.Value = DateTimeOffset.Parse(sender.Text); - } - catch - { - bindable.TriggerChange(); - } - }; - } - - // hold a reference to the provided bindable so we don't have to in every settings section. - private Bindable bindable; - - public new Bindable Bindable - { - get { return bindable; } - - set - { - bindable = value; - bindable.BindValueChanged(dto => base.Bindable.Value = dto.ToUniversalTime().ToString(), true); - } - } - } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index 34b16ccab3..bb80a845e3 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; using osu.Game.Screens.Play.PlayerSettings; -using osu.Game.Tournament.Screens.Groupings; +using osu.Game.Tournament.Components; namespace osu.Game.Tournament.Screens.Ladder.Components { From 81f39c2f399f7a4e527cda0b70205b4453e62059 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 14:35:40 +0900 Subject: [PATCH 0286/5608] Don't show matches on schedule which don't have teams set --- osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index a0c36cd6c0..325a6105cf 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -75,7 +75,7 @@ namespace osu.Game.Tournament.Screens.Schedule RelativeSizeAxes = Axes.Both, Width = 0.4f, ChildrenEnumerable = ladder.Pairings - .Where(p => p.Completed.Value) + .Where(p => p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null) .OrderByDescending(p => p.Date.Value) .Take(8) .Select(p => new SchedulePairing(p)) @@ -85,7 +85,7 @@ namespace osu.Game.Tournament.Screens.Schedule RelativeSizeAxes = Axes.Both, Width = 0.6f, ChildrenEnumerable = ladder.Pairings - .Where(p => !p.Completed.Value) + .Where(p => !p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null) .OrderBy(p => p.Date.Value) .Take(8) .Select(p => new SchedulePairing(p)) From 71184c602f1d9c1bf3023ce955c004d830328428 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 14:55:27 +0900 Subject: [PATCH 0287/5608] Show times on schedule --- .../Screens/Schedule/ScheduleScreen.cs | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index 325a6105cf..4be24a65f7 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Video; using osu.Framework.Platform; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Tournament.Screens.Ladder.Components; using OpenTK; @@ -107,7 +108,7 @@ namespace osu.Game.Tournament.Screens.Schedule Colour = Color4.Black, TextSize = 20 }, - new SchedulePairing(currentMatch), + new SchedulePairing(currentMatch, false), new OsuSpriteText { Text = "Start Time " + pairing.Date.Value.ToUniversalTime().ToString("HH:mm UTC"), @@ -122,10 +123,29 @@ namespace osu.Game.Tournament.Screens.Schedule public class SchedulePairing : DrawableMatchPairing { - public SchedulePairing(MatchPairing pairing) + public SchedulePairing(MatchPairing pairing, bool showTimestamp = true) : base(pairing) { Flow.Direction = FillDirection.Horizontal; + + if (showTimestamp) + { + AddInternal(new DrawableDate(Pairing.Date.Value) + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopLeft, + Colour = Color4.Black, + Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, + }); + AddInternal(new OsuSpriteText + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomLeft, + Colour = Color4.Black, + Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, + Text = pairing.Date.Value.ToUniversalTime().ToString("HH:mm UTC") + }); + } } } From 5659ba6ef8d8dba5aef6cb3689394a3cadc59316 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 14:59:37 +0900 Subject: [PATCH 0288/5608] Add logo to ladder screen --- osu.Game.Tournament/Screens/Ladder/LadderScreen.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 5e0cb13375..76f65fd87f 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -8,13 +8,15 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Lines; +using osu.Framework.Graphics.Video; +using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Tournament.Screens.Ladder.Components; using OpenTK.Graphics; namespace osu.Game.Tournament.Screens.Ladder { - public class LadderScreen : TournamentScreen + public class LadderScreen : TournamentScreen, IProvideVideo { protected Container PairingsContainer; private Container paths; @@ -23,7 +25,7 @@ namespace osu.Game.Tournament.Screens.Ladder protected ScrollableContainer ScrollContent; [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, Storage storage) { normalPathColour = colours.BlueDarker.Darken(2); losersPathColour = colours.YellowDarker.Darken(2); @@ -35,6 +37,11 @@ namespace osu.Game.Tournament.Screens.Ladder RelativeSizeAxes = Axes.Both, Children = new Drawable[] { + new VideoSprite(storage.GetStream(@"BG Side Logo - OWC.m4v")) + { + RelativeSizeAxes = Axes.Both, + Loop = true, + }, ScrollContent = new ScrollableContainer { RelativeSizeAxes = Axes.Both, From aebece3d89c533a9973b1552ac357f6744fab26a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 15:18:22 +0900 Subject: [PATCH 0289/5608] Use already populated beatmap values if available --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 9cc275e9e0..4bf2cfee38 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -3,6 +3,7 @@ using System; using System.IO; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Logging; using osu.Framework.Platform.Windows; @@ -25,9 +26,8 @@ namespace osu.Game.Tournament.IPC private int lastBeatmapId; [BackgroundDependencyLoader] - private void load() + private void load(LadderInfo ladder) { - StableStorage stable; try @@ -58,9 +58,17 @@ namespace osu.Game.Tournament.IPC if (lastBeatmapId != beatmapId) { lastBeatmapId = beatmapId; - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); - req.Success += b => Beatmap.Value = b.ToBeatmap(Rulesets); - API.Queue(req); + + var existing = ladder.CurrentMatch.Value?.Grouping.Value?.Beatmaps.FirstOrDefault(b => b.ID == beatmapId && b.BeatmapInfo != null); + + if (existing != null) + Beatmap.Value = existing.BeatmapInfo; + else + { + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); + req.Success += b => Beatmap.Value = b.ToBeatmap(Rulesets); + API.Queue(req); + } } Mods.Value = (LegacyMods)mods; From 49e155c2c0ecb6dea2eec2bd2443969e192c9e7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 15:31:03 +0900 Subject: [PATCH 0290/5608] Fix chat not appearing at ranking --- .../Screens/Gameplay/GameplayScreen.cs | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 3c6ea39ae7..696abddded 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -86,6 +86,7 @@ namespace osu.Game.Tournament.Screens.Gameplay chat = new MatchChatDisplay { RelativeSizeAxes = Axes.X, + Y = 100, Size = new Vector2(0.45f, 120), Margin = new MarginPadding(10), Anchor = Anchor.BottomCentre, @@ -137,26 +138,34 @@ namespace osu.Game.Tournament.Screens.Gameplay scheduledBarContract?.Cancel(); + void expand() + { + chat.FadeOut(200); + chat.MoveToY(100, 500, Easing.In); + using (SongBar.BeginDelayedSequence(300, true)) + SongBar.Expanded = true; + } + + void contract() + { + SongBar.Expanded = false; + using (chat.BeginDelayedSequence(500)) + { + chat.FadeIn(300); + chat.MoveToY(0, 500, Easing.OutQuint); + } + } + switch (state) { case TourneyState.Idle: - // show chat - SongBar.Expanded = false; - using (chat.BeginDelayedSequence(500)) - { - chat.FadeIn(300); - chat.MoveToY(100).MoveToY(0, 500, Easing.OutQuint); - } - + contract(); break; case TourneyState.Ranking: - scheduledBarContract = Scheduler.AddDelayed(() => SongBar.Expanded = false, 15000); + scheduledBarContract = Scheduler.AddDelayed(contract, 10000); break; default: - chat.FadeOut(200); - chat.MoveToY(100, 500, Easing.In); - using (SongBar.BeginDelayedSequence(300, true)) - SongBar.Expanded = true; + expand(); break; } } From 26286177d3ba6aa4c34e27b1fa0b13f20ec80700 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 15:35:14 +0900 Subject: [PATCH 0291/5608] Colour chat names --- osu.Game.Tournament/Components/MatchChatDisplay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Components/MatchChatDisplay.cs b/osu.Game.Tournament/Components/MatchChatDisplay.cs index dc8f28d9bd..70f04593fa 100644 --- a/osu.Game.Tournament/Components/MatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/MatchChatDisplay.cs @@ -199,11 +199,11 @@ namespace osu.Game.Tournament.Components } else if (info.CurrentMatch.Value.Team1.Value.Players.Any(u => u.Id == message.Sender.Id)) { - colourBox.Colour = red; + senderText.Colour = colourBox.Colour = red; } else if (info.CurrentMatch.Value.Team2.Value.Players.Any(u => u.Id == message.Sender.Id)) { - colourBox.Colour = blue; + senderText.Colour = colourBox.Colour = blue; } } } From 9f519d7002b589aa91fb272eb0c2499daa1784b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 15:44:56 +0900 Subject: [PATCH 0292/5608] Actually add match score display to gameplay screen --- .../Gameplay/Components/MatchScoreDisplay.cs | 7 ++++--- .../Screens/Gameplay/GameplayScreen.cs | 13 ++++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs index fe865a1728..f84fca5e04 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs @@ -35,6 +35,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components public MatchScoreDisplay() { RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; InternalChildren = new Drawable[] { @@ -102,12 +103,12 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components var diff = Math.Max(score1.Value, score2.Value) - Math.Min(score1.Value, score2.Value); losingBar.ResizeWidthTo(0, 400, Easing.OutQuint); - winningBar.ResizeWidthTo((float)Math.Pow(diff / 1000000f, 0.5), 400, Easing.OutQuint); + winningBar.ResizeWidthTo((float)Math.Pow(diff / 1000000f, 0.5) / 2, 400, Easing.OutQuint); } - protected override void UpdateAfterChildren() + protected override void Update() { - base.UpdateAfterChildren(); + base.Update(); score1Text.X = -Math.Max(5 + score1Text.DrawWidth / 2, score1Bar.DrawWidth); score2Text.X = Math.Max(5 + score2Text.DrawWidth / 2, score2Bar.DrawWidth); diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 696abddded..470b7ed479 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -92,6 +92,12 @@ namespace osu.Game.Tournament.Screens.Gameplay Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, }, + scoreDisplay = new MatchScoreDisplay + { + Y = -65, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + }, new ControlPanel { Children = new Drawable[] @@ -123,6 +129,7 @@ namespace osu.Game.Tournament.Screens.Gameplay private ScheduledDelegate scheduledBarContract; private MatchChatDisplay chat; + private MatchScoreDisplay scoreDisplay; private void stateChanged(TourneyState state) { @@ -142,13 +149,17 @@ namespace osu.Game.Tournament.Screens.Gameplay { chat.FadeOut(200); chat.MoveToY(100, 500, Easing.In); - using (SongBar.BeginDelayedSequence(300, true)) + using (BeginDelayedSequence(300, true)) + { + scoreDisplay.FadeIn(100); SongBar.Expanded = true; + } } void contract() { SongBar.Expanded = false; + scoreDisplay.FadeOut(100); using (chat.BeginDelayedSequence(500)) { chat.FadeIn(300); From 4ae9413ee66b3ce1a026af2ff0d63bb2c6bb418f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 16:00:12 +0900 Subject: [PATCH 0293/5608] Add mod icons --- .../Components/TournamentBeatmapPanel.cs | 21 +++++++++++++++++-- .../Screens/MapPool/MapPoolScreen.cs | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 4456abb48e..aeb9eefd35 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -9,12 +9,17 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.IO.Stores; using osu.Framework.Localisation; +using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Tournament.Screens.Ladder.Components; +using OpenTK; using OpenTK.Graphics; namespace osu.Game.Tournament.Components @@ -22,6 +27,7 @@ namespace osu.Game.Tournament.Components public class TournamentBeatmapPanel : CompositeDrawable { public readonly BeatmapInfo Beatmap; + private readonly string mods; private const float horizontal_padding = 10; private const float vertical_padding = 5; @@ -31,15 +37,16 @@ namespace osu.Game.Tournament.Components private readonly Bindable currentMatch = new Bindable(); private Box flash; - public TournamentBeatmapPanel(BeatmapInfo beatmap) + public TournamentBeatmapPanel(BeatmapInfo beatmap, string mods = null) { Beatmap = beatmap; + this.mods = mods; Width = 400; Height = HEIGHT; } [BackgroundDependencyLoader] - private void load(LadderInfo ladder) + private void load(LadderInfo ladder, Storage storage) { currentMatch.BindValueChanged(matchChanged); currentMatch.BindTo(ladder.CurrentMatch); @@ -126,6 +133,16 @@ namespace osu.Game.Tournament.Components Alpha = 0, }, }); + + if (!string.IsNullOrEmpty(mods)) + AddInternal(new Sprite + { + Texture = new TextureStore(new TextureLoaderStore(new StorageBackedResourceStore(storage))).Get($"mods/{mods}"), + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Margin = new MarginPadding(20), + Scale = new Vector2(0.5f) + }); } private void matchChanged(MatchPairing match) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 65f4bfb149..81a140d5c2 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -193,7 +193,7 @@ namespace osu.Game.Tournament.Screens.MapPool if (match.Grouping.Value != null) { foreach (var b in match.Grouping.Value.Beatmaps) - maps.Add(new TournamentBeatmapPanel(b.BeatmapInfo) + maps.Add(new TournamentBeatmapPanel(b.BeatmapInfo, b.Mods) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, From 852f0337dd070512e22e6e5a10ee734255a41f86 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 16:06:43 +0900 Subject: [PATCH 0294/5608] Group map pool by mod type --- .../Screens/MapPool/MapPoolScreen.cs | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 81a140d5c2..14dd990ec0 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tournament.Screens.MapPool { public class MapPoolScreen : TournamentScreen { - private readonly FillFlowContainer maps; + private readonly FillFlowContainer> mapFlows; private readonly Bindable currentMatch = new Bindable(); @@ -39,12 +39,12 @@ namespace osu.Game.Tournament.Screens.MapPool InternalChildren = new Drawable[] { new MatchHeader(), - maps = new FillFlowContainer + mapFlows = new FillFlowContainer> { Y = 100, Spacing = new Vector2(10, 20), Padding = new MarginPadding(50), - Direction = FillDirection.Full, + Direction = FillDirection.Vertical, RelativeSizeAxes = Axes.Both, }, new ControlPanel @@ -136,7 +136,9 @@ namespace osu.Game.Tournament.Screens.MapPool protected override bool OnMouseDown(MouseDownEvent e) { - var map = maps.FirstOrDefault(m => m.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)); + var maps = mapFlows.Select(f => f.FirstOrDefault(m => m.ReceivePositionalInputAt(e.ScreenSpaceMousePosition))); + var map = maps.FirstOrDefault(m => m != null); + if (map != null) { if (e.Button == MouseButton.Left && map.Beatmap.OnlineBeatmapID != null) @@ -188,16 +190,34 @@ namespace osu.Game.Tournament.Screens.MapPool private void matchChanged(MatchPairing match) { - maps.Clear(); + mapFlows.Clear(); if (match.Grouping.Value != null) { + FillFlowContainer currentFlow = null; + string currentMod = null; + foreach (var b in match.Grouping.Value.Beatmaps) - maps.Add(new TournamentBeatmapPanel(b.BeatmapInfo, b.Mods) + { + if (currentFlow == null || currentMod != b.Mods) + { + mapFlows.Add(currentFlow = new FillFlowContainer + { + Spacing = new Vector2(10, 20), + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }); + + currentMod = b.Mods; + } + + currentFlow.Add(new TournamentBeatmapPanel(b.BeatmapInfo, b.Mods) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }); + } } } } From 8b820f7346f851cc95cecd4db61391493c48d056 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 21:26:56 +0900 Subject: [PATCH 0295/5608] Move channel reading to new ipc file --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 4bf2cfee38..83dbe11ffa 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -43,6 +43,7 @@ namespace osu.Game.Tournament.IPC const string file_ipc_filename = "ipc.txt"; const string file_ipc_state_filename = "ipc-state.txt"; const string file_ipc_scores_filename = "ipc-scores.txt"; + const string file_ipc_channel_filename = "ipc-channel.txt"; if (stable.Exists(file_ipc_filename)) Scheduler.AddDelayed(delegate @@ -72,7 +73,6 @@ namespace osu.Game.Tournament.IPC } Mods.Value = (LegacyMods)mods; - ChatChannel.Value = sr.ReadLine(); } } catch @@ -80,6 +80,19 @@ namespace osu.Game.Tournament.IPC // file might be in use. } + try + { + using (var stream = stable.GetStream(file_ipc_channel_filename)) + using (var sr = new StreamReader(stream)) + { + ChatChannel.Value = sr.ReadLine(); + } + } + catch (Exception) + { + // file might be in use. + } + try { using (var stream = stable.GetStream(file_ipc_state_filename)) From 4b047ad9ccc9048454e871867ad6e05c4bda525f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 21:27:02 +0900 Subject: [PATCH 0296/5608] Centralise chat display --- .../Components/MatchChatDisplay.cs | 12 +++++++ .../Screens/Gameplay/GameplayScreen.cs | 24 ++++---------- .../Screens/TournamentSceneManager.cs | 33 ++++++++++++++++++- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tournament/Components/MatchChatDisplay.cs b/osu.Game.Tournament/Components/MatchChatDisplay.cs index 70f04593fa..2c94e06fc3 100644 --- a/osu.Game.Tournament/Components/MatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/MatchChatDisplay.cs @@ -207,5 +207,17 @@ namespace osu.Game.Tournament.Components } } } + + public void Contract() + { + this.FadeIn(300); + this.MoveToY(0, 500, Easing.OutQuint); + } + + public void Expand() + { + this.FadeOut(200); + this.MoveToY(100, 500, Easing.In); + } } } diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 470b7ed479..372087cfcf 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -13,7 +13,6 @@ using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Screens.Gameplay.Components; using osu.Game.Tournament.Screens.Ladder.Components; -using OpenTK; using OpenTK.Graphics; namespace osu.Game.Tournament.Screens.Gameplay @@ -32,9 +31,11 @@ namespace osu.Game.Tournament.Screens.Gameplay private readonly Color4 blue = new Color4(17, 136, 170, 255); [BackgroundDependencyLoader] - private void load(LadderInfo ladder, TextureStore textures, MatchIPCInfo ipc) + private void load(LadderInfo ladder, TextureStore textures, MatchIPCInfo ipc, MatchChatDisplay chat) { + this.chat = chat; this.ipc = ipc; + AddRange(new Drawable[] { new MatchHeader(), @@ -83,15 +84,6 @@ namespace osu.Game.Tournament.Screens.Gameplay }, } }, - chat = new MatchChatDisplay - { - RelativeSizeAxes = Axes.X, - Y = 100, - Size = new Vector2(0.45f, 120), - Margin = new MarginPadding(10), - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - }, scoreDisplay = new MatchScoreDisplay { Y = -65, @@ -147,8 +139,8 @@ namespace osu.Game.Tournament.Screens.Gameplay void expand() { - chat.FadeOut(200); - chat.MoveToY(100, 500, Easing.In); + chat.Expand(); + using (BeginDelayedSequence(300, true)) { scoreDisplay.FadeIn(100); @@ -161,10 +153,7 @@ namespace osu.Game.Tournament.Screens.Gameplay SongBar.Expanded = false; scoreDisplay.FadeOut(100); using (chat.BeginDelayedSequence(500)) - { - chat.FadeIn(300); - chat.MoveToY(0, 500, Easing.OutQuint); - } + chat.Contract(); } switch (state) @@ -176,6 +165,7 @@ namespace osu.Game.Tournament.Screens.Gameplay scheduledBarContract = Scheduler.AddDelayed(contract, 10000); break; default: + chat.Expand(); expand(); break; } diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index f3bc12a6cf..7947f94cf9 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Video; using osu.Framework.Platform; using osu.Game.Graphics.UserInterface; using osu.Game.Screens; +using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Drawings; using osu.Game.Tournament.Screens.Gameplay; using osu.Game.Tournament.Screens.Groupings; @@ -38,6 +39,20 @@ namespace osu.Game.Tournament.Screens private ShowcaseScreen showcase; private VideoSprite video; + //todo: make less temporary + [Cached] + private MatchChatDisplay chat = new MatchChatDisplay + { + RelativeSizeAxes = Axes.X, + Y = 100, + Size = new Vector2(0.45f, 120), + Margin = new MarginPadding(10), + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + }; + + private Container chatContainer; + [BackgroundDependencyLoader] private void load(LadderInfo ladder, Storage storage) { @@ -48,7 +63,7 @@ namespace osu.Game.Tournament.Screens RelativeSizeAxes = Axes.Both, X = 200, FillMode = FillMode.Fit, - FillAspectRatio = 16/9f, + FillAspectRatio = 16 / 9f, Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, Size = new Vector2(0.8f, 1), @@ -78,6 +93,11 @@ namespace osu.Game.Tournament.Screens winner = new TeamWinScreen() } }, + chatContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Child = chat + }, } }, new Container @@ -135,6 +155,17 @@ namespace osu.Game.Tournament.Screens else s.Hide(); } + + switch (screen) + { + case GameplayScreen _: + case MapPoolScreen _: + chatContainer.FadeIn(100); + break; + default: + chatContainer.FadeOut(100); + break; + } } } } From 92bb92e9c0c11502ef9ba2ce017a3919122888c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Nov 2018 21:28:33 +0900 Subject: [PATCH 0297/5608] Use local framework --- osu.Game/osu.Game.csproj | 2 +- osu.sln | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8c47df654a..3022b66762 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -11,6 +11,7 @@ + @@ -18,7 +19,6 @@ - diff --git a/osu.sln b/osu.sln index f6ed7a5c42..c62fc02dba 100644 --- a/osu.sln +++ b/osu.sln @@ -31,6 +31,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament", "osu. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament.Tests", "osu.Game.Tournament.Tests\osu.Game.Tournament.Tests.csproj", "{5789E78D-38F9-4072-AB7B-978F34B2C17F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework", "..\osu-framework\osu.Framework\osu.Framework.csproj", "{7A69A230-45A1-4444-8C43-A582E4F48C1E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -93,6 +95,10 @@ Global {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|Any CPU.Build.0 = Debug|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.ActiveCfg = Release|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.Build.0 = Release|Any CPU + {7A69A230-45A1-4444-8C43-A582E4F48C1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A69A230-45A1-4444-8C43-A582E4F48C1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A69A230-45A1-4444-8C43-A582E4F48C1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A69A230-45A1-4444-8C43-A582E4F48C1E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 584adaf77db9dff6579312ae1209ba049a9ad5c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Nov 2018 07:54:53 +0900 Subject: [PATCH 0298/5608] Limit horizontal bounds of score display --- .../Screens/Gameplay/Components/MatchScoreDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs index f84fca5e04..5ec9eef6ca 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs @@ -103,7 +103,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components var diff = Math.Max(score1.Value, score2.Value) - Math.Min(score1.Value, score2.Value); losingBar.ResizeWidthTo(0, 400, Easing.OutQuint); - winningBar.ResizeWidthTo((float)Math.Pow(diff / 1000000f, 0.5) / 2, 400, Easing.OutQuint); + winningBar.ResizeWidthTo(Math.Min(0.4f, (float)Math.Pow(diff / 1000000f, 0.5) / 2), 400, Easing.OutQuint); } protected override void Update() From 70739ae5a0dbfc5675e734daa4f0cd8f8f58aeef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Nov 2018 08:25:23 +0900 Subject: [PATCH 0299/5608] Reduce rate of scale of score display --- .../Screens/Gameplay/Components/MatchScoreDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs index 5ec9eef6ca..7bc430e587 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs @@ -103,7 +103,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components var diff = Math.Max(score1.Value, score2.Value) - Math.Min(score1.Value, score2.Value); losingBar.ResizeWidthTo(0, 400, Easing.OutQuint); - winningBar.ResizeWidthTo(Math.Min(0.4f, (float)Math.Pow(diff / 1000000f, 0.5) / 2), 400, Easing.OutQuint); + winningBar.ResizeWidthTo(Math.Min(0.4f, (float)Math.Pow(diff / 1500000f, 0.5) / 2), 400, Easing.OutQuint); } protected override void Update() From e6529eac3e1ae04b1fc61214b205c51bc9ef4f31 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Nov 2018 08:30:17 +0900 Subject: [PATCH 0300/5608] Add automation of map pool and win screen workflows --- .../Screens/Gameplay/GameplayScreen.cs | 24 +++++++- .../Screens/TournamentSceneManager.cs | 60 +++++++++---------- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 372087cfcf..7517e83160 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -13,6 +13,8 @@ using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Screens.Gameplay.Components; using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Screens.MapPool; +using osu.Game.Tournament.Screens.TeamWin; using OpenTK.Graphics; namespace osu.Game.Tournament.Screens.Gameplay @@ -30,6 +32,9 @@ namespace osu.Game.Tournament.Screens.Gameplay private readonly Color4 red = new Color4(186, 0, 18, 255); private readonly Color4 blue = new Color4(17, 136, 170, 255); + [Resolved] + private TournamentSceneManager sceneManager { get; set; } + [BackgroundDependencyLoader] private void load(LadderInfo ladder, TextureStore textures, MatchIPCInfo ipc, MatchChatDisplay chat) { @@ -119,10 +124,12 @@ namespace osu.Game.Tournament.Screens.Gameplay warmup.BindValueChanged(w => warmupButton.Alpha = !w ? 0.5f : 1, true); } - private ScheduledDelegate scheduledBarContract; + private ScheduledDelegate scheduledOperation; private MatchChatDisplay chat; private MatchScoreDisplay scoreDisplay; + private TourneyState lastState; + private void stateChanged(TourneyState state) { if (state == TourneyState.Ranking) @@ -135,7 +142,7 @@ namespace osu.Game.Tournament.Screens.Gameplay currentMatch.Value.Team2Score.Value++; } - scheduledBarContract?.Cancel(); + scheduledOperation?.Cancel(); void expand() { @@ -160,15 +167,26 @@ namespace osu.Game.Tournament.Screens.Gameplay { case TourneyState.Idle: contract(); + + if (lastState == TourneyState.Ranking) + { + if (currentMatch.Value?.Completed == true) + scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(TeamWinScreen)); }, 4000); + else if (currentMatch.Value?.Completed == false) + scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(MapPoolScreen)); }, 4000); + } + break; case TourneyState.Ranking: - scheduledBarContract = Scheduler.AddDelayed(contract, 10000); + scheduledOperation = Scheduler.AddDelayed(contract, 10000); break; default: chat.Expand(); expand(); break; } + + lastState = state; } } } diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index 7947f94cf9..ca3df2627a 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -24,19 +26,10 @@ using OpenTK.Graphics; namespace osu.Game.Tournament.Screens { + [Cached] public class TournamentSceneManager : OsuScreen { - private ScheduleScreen schedule; - private LadderScreen bracket; - private LadderEditorScreen bracketEditor; - private GroupingsEditorScreen groupingsEditor; - private MapPoolScreen mapPool; - private GameplayScreen gameplay; - private TeamWinScreen winner; - private TeamIntroScreen teamIntro; - private DrawingsScreen drawings; private Container screens; - private ShowcaseScreen showcase; private VideoSprite video; //todo: make less temporary @@ -81,16 +74,16 @@ namespace osu.Game.Tournament.Screens RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - schedule = new ScheduleScreen(), - bracket = new LadderScreen(), - bracketEditor = new LadderEditorScreen(), - groupingsEditor = new GroupingsEditorScreen(), - showcase = new ShowcaseScreen(), - mapPool = new MapPoolScreen(), - teamIntro = new TeamIntroScreen(), - drawings = new DrawingsScreen(), - gameplay = new GameplayScreen(), - winner = new TeamWinScreen() + new ScheduleScreen(), + new LadderScreen(), + new LadderEditorScreen(), + new GroupingsEditorScreen(), + new ShowcaseScreen(), + new MapPoolScreen(), + new TeamIntroScreen(), + new DrawingsScreen(), + new GameplayScreen(), + new TeamWinScreen() } }, chatContainer = new Container @@ -117,31 +110,34 @@ namespace osu.Game.Tournament.Screens Direction = FillDirection.Vertical, Children = new Drawable[] { - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => setScreen(bracketEditor) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Groupings Editor", Action = () => setScreen(groupingsEditor) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Groupings Editor", Action = () => SetScreen(typeof(GroupingsEditorScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => setScreen(drawings) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => setScreen(showcase) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => SetScreen(typeof(DrawingsScreen)) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => SetScreen(typeof(ShowcaseScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Schedule", Action = () => setScreen(schedule) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => setScreen(bracket) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Schedule", Action = () => SetScreen(typeof(ScheduleScreen)) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => SetScreen(typeof(LadderScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => setScreen(teamIntro) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => setScreen(mapPool) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => setScreen(gameplay) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => SetScreen(typeof(TeamIntroScreen)) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => SetScreen(typeof(MapPoolScreen)) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => SetScreen(typeof(GameplayScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Win", Action = () => setScreen(winner) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Win", Action = () => SetScreen(typeof(TeamWinScreen)) }, } }, }, }, }; - setScreen(teamIntro); + SetScreen(typeof(ScheduleScreen)); } - private void setScreen(Drawable screen) + public void SetScreen(Type screenType) { + var screen = screens.FirstOrDefault(s => s.GetType() == screenType); + if (screen == null) return; + foreach (var s in screens.Children) { if (s == screen) From 06b08cd82dafee45a767b6fe03b884ecbe4ec558 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Nov 2018 09:29:18 +0900 Subject: [PATCH 0301/5608] Automate return to gameplay after map pool selection --- .../Screens/MapPool/MapPoolScreen.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 14dd990ec0..a0670fcb87 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -7,11 +7,13 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; +using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Screens.Gameplay; using osu.Game.Tournament.Screens.Gameplay.Components; using osu.Game.Tournament.Screens.Ladder.Components; using OpenTK; @@ -165,6 +167,11 @@ namespace osu.Game.Tournament.Screens.MapPool setNextMode(); } + [Resolved] + private TournamentSceneManager sceneManager { get; set; } + + private ScheduledDelegate scheduledChange; + private void addForBeatmap(int beatmapId) { if (currentMatch.Value == null) @@ -186,6 +193,12 @@ namespace osu.Game.Tournament.Screens.MapPool }); setNextMode(); + + if (pickType == ChoiceType.Pick) + { + scheduledChange?.Cancel(); + scheduledChange = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(GameplayScreen)); }, 10000); + } } private void matchChanged(MatchPairing match) From 256d11620fd4be3f700d86616ec59ecfe0fd4693 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Nov 2018 12:38:48 +0900 Subject: [PATCH 0302/5608] Add missing space after "CS" --- osu.Game.Tournament/Components/SongBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 53dec8e0a4..8e266aec28 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -188,7 +188,7 @@ namespace osu.Game.Tournament.Components }, new OsuSpriteText { - Text = $"CS{beatmap.BaseDifficulty.CircleSize:0.#} / AR {ar:0.#}{extra}", + Text = $"CS {beatmap.BaseDifficulty.CircleSize:0.#} / AR {ar:0.#}{extra}", Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, Colour = OsuColour.Gray(0.33f), Anchor = Anchor.TopRight, From 925532508cdac1f94066cf18e2d3c54a80550f1f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Nov 2018 12:39:17 +0900 Subject: [PATCH 0303/5608] Change precedence of chat colouring --- osu.Game.Tournament/Components/MatchChatDisplay.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tournament/Components/MatchChatDisplay.cs b/osu.Game.Tournament/Components/MatchChatDisplay.cs index 2c94e06fc3..f80b73c4f6 100644 --- a/osu.Game.Tournament/Components/MatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/MatchChatDisplay.cs @@ -193,17 +193,17 @@ namespace osu.Game.Tournament.Components }, }; - if (message.Sender.Colour != null) + if (info.CurrentMatch.Value.Team1.Value.Players.Any(u => u.Id == message.Sender.Id)) { - senderText.Colour = colourBox.Colour = OsuColour.FromHex(message.Sender.Colour); - } - else if (info.CurrentMatch.Value.Team1.Value.Players.Any(u => u.Id == message.Sender.Id)) - { - senderText.Colour = colourBox.Colour = red; + colourBox.Colour = red; } else if (info.CurrentMatch.Value.Team2.Value.Players.Any(u => u.Id == message.Sender.Id)) { - senderText.Colour = colourBox.Colour = blue; + colourBox.Colour = blue; + } + else if (message.Sender.Colour != null) + { + senderText.Colour = colourBox.Colour = OsuColour.FromHex(message.Sender.Colour); } } } From 5621101d40208d0a1cd8b426b464117609a83902 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Nov 2018 12:39:25 +0900 Subject: [PATCH 0304/5608] Adjust gameplay screen size --- .../Screens/Gameplay/GameplayScreen.cs | 13 ++++++++----- .../Screens/TournamentSceneManager.cs | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 7517e83160..77dd2fc8d3 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -15,6 +15,7 @@ using osu.Game.Tournament.Screens.Gameplay.Components; using osu.Game.Tournament.Screens.Ladder.Components; using osu.Game.Tournament.Screens.MapPool; using osu.Game.Tournament.Screens.TeamWin; +using OpenTK; using OpenTK.Graphics; namespace osu.Game.Tournament.Screens.Gameplay @@ -48,6 +49,7 @@ namespace osu.Game.Tournament.Screens.Gameplay { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Y = 5, Direction = FillDirection.Vertical, Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -63,7 +65,7 @@ namespace osu.Game.Tournament.Screens.Gameplay { Name = "top bar red", RelativeSizeAxes = Axes.X, - Height = 10, + Height = 8, Width = 0.5f, Colour = red, }, @@ -71,7 +73,7 @@ namespace osu.Game.Tournament.Screens.Gameplay { Name = "top bar blue", RelativeSizeAxes = Axes.X, - Height = 10, + Height = 9, Width = 0.5f, Colour = blue, Anchor = Anchor.TopRight, @@ -84,14 +86,15 @@ namespace osu.Game.Tournament.Screens.Gameplay // chroma key area for stable gameplay Name = "chroma", RelativeSizeAxes = Axes.X, - Height = 480, + Height = 500, Colour = new Color4(0, 255, 0, 255), }, } }, scoreDisplay = new MatchScoreDisplay { - Y = -65, + Y = -60, + Scale = new Vector2(0.86f), Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, }, @@ -168,7 +171,7 @@ namespace osu.Game.Tournament.Screens.Gameplay case TourneyState.Idle: contract(); - if (lastState == TourneyState.Ranking) + if (lastState == TourneyState.Ranking && !warmup.Value) { if (currentMatch.Value?.Completed == true) scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(TeamWinScreen)); }, 4000); diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index ca3df2627a..28066608d1 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tournament.Screens { RelativeSizeAxes = Axes.X, Y = 100, - Size = new Vector2(0.45f, 120), + Size = new Vector2(0.45f, 112), Margin = new MarginPadding(10), Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, From 8fab241ce3afe8e5aeab24d7c22ce39a74cf3d54 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Nov 2018 21:15:29 +0900 Subject: [PATCH 0305/5608] Don't show matches on showcase which are more than four days away --- osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index 4be24a65f7..6781bd78e1 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -76,7 +77,7 @@ namespace osu.Game.Tournament.Screens.Schedule RelativeSizeAxes = Axes.Both, Width = 0.4f, ChildrenEnumerable = ladder.Pairings - .Where(p => p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null) + .Where(p => p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4) .OrderByDescending(p => p.Date.Value) .Take(8) .Select(p => new SchedulePairing(p)) @@ -86,7 +87,7 @@ namespace osu.Game.Tournament.Screens.Schedule RelativeSizeAxes = Axes.Both, Width = 0.6f, ChildrenEnumerable = ladder.Pairings - .Where(p => !p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null) + .Where(p => !p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4) .OrderBy(p => p.Date.Value) .Take(8) .Select(p => new SchedulePairing(p)) From 7d3bcdfc1795d46b5758cf0bdc800fa97f1ce8a4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Nov 2018 13:17:51 +0900 Subject: [PATCH 0306/5608] Fix stats not displaying on showcase screen --- osu.Game.Tournament/Components/SongBar.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index aee16c72c4..04c4927fc1 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -53,6 +53,7 @@ namespace osu.Game.Tournament.Components private float panelWidth => expanded ? 0.6f : 1; private const float main_width = 0.97f; + private const float inner_panel_width = 0.7f; private bool expanded; @@ -66,7 +67,7 @@ namespace osu.Game.Tournament.Components if (expanded) { - innerPanel.ResizeWidthTo(0.7f, 800, Easing.OutQuint); + innerPanel.ResizeWidthTo(inner_panel_width, 800, Easing.OutQuint); outerPanel.ResizeWidthTo(main_width, 800, Easing.OutQuint); } else @@ -126,7 +127,7 @@ namespace osu.Game.Tournament.Components Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Width = 0.7f, + Width = inner_panel_width, Children = new Drawable[] { new Box @@ -143,6 +144,8 @@ namespace osu.Game.Tournament.Components } } }; + + Expanded = true; } private void update() From cbf82f892d697be8a11ad77acf7f4a60f8010f2d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Nov 2018 14:10:33 +0900 Subject: [PATCH 0307/5608] Add OD display and fix "*" difficuty modifier display --- osu.Game.Tournament/Components/SongBar.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 04c4927fc1..3d9fe2f5ee 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -158,17 +158,22 @@ namespace osu.Game.Tournament.Components var bpm = beatmap.BeatmapSet.OnlineInfo.BPM; var length = beatmap.OnlineInfo.Length; - string extra = ""; + string hardRockExtra = ""; + string srExtra = ""; var ar = beatmap.BaseDifficulty.ApproachRate; - if ((mods & LegacyMods.HardRock) > 0) extra = "*"; + if ((mods & LegacyMods.HardRock) > 0) + { + hardRockExtra = "*"; + srExtra = "*"; + } if ((mods & LegacyMods.DoubleTime) > 0) { //ar *= 1.5f; bpm *= 1.5f; length /= 1.5f; - extra = "*"; + srExtra = "*"; } panelContents.Children = new Drawable[] @@ -191,7 +196,7 @@ namespace osu.Game.Tournament.Components }, new OsuSpriteText { - Text = $"CS {beatmap.BaseDifficulty.CircleSize:0.#} / AR {ar:0.#}{extra}", + Text = $"CS {beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra} / AR {ar:0.#}{srExtra} / OD {beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}", Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, Colour = OsuColour.Gray(0.33f), Anchor = Anchor.TopRight, @@ -199,7 +204,7 @@ namespace osu.Game.Tournament.Components }, new OsuSpriteText { - Text = $"Star Rating {beatmap.StarDifficulty:0.#}{extra}", + Text = $"Star Rating {beatmap.StarDifficulty:0.#}{srExtra}", Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, Colour = OsuColour.Gray(0.33f), Anchor = Anchor.BottomRight, From 4e8c7a4dc0fa8530700dff7907e9095d15dc49a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Nov 2018 15:42:10 +0900 Subject: [PATCH 0308/5608] Adjust gameplay area to match better Also reduces size of score display to avoid hiding combos. --- .../Gameplay/Components/MatchHeader.cs | 2 +- .../Screens/Gameplay/GameplayScreen.cs | 24 +++++++++---------- .../Screens/Showcase/TournamentLogo.cs | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index 1085e7a8c3..210b42a4c8 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components private void load(LadderInfo ladder, TextureStore textures) { RelativeSizeAxes = Axes.X; - Height = 100; + Height = 95; Children = new Drawable[] { new TournamentLogo(), diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 29b1b85e02..8897a98a7e 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -45,20 +45,28 @@ namespace osu.Game.Tournament.Screens.Gameplay AddRange(new Drawable[] { new MatchHeader(), - new FillFlowContainer + new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Y = 5, - Direction = FillDirection.Vertical, Anchor = Anchor.Centre, Origin = Anchor.Centre, Children = new Drawable[] { + new Box + { + // chroma key area for stable gameplay + Name = "chroma", + RelativeSizeAxes = Axes.X, + Height = 512, + Colour = new Color4(0, 255, 0, 255), + }, new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Y = -4, Children = new Drawable[] { new Circle @@ -73,7 +81,7 @@ namespace osu.Game.Tournament.Screens.Gameplay { Name = "top bar blue", RelativeSizeAxes = Axes.X, - Height = 9, + Height = 8, Width = 0.5f, Colour = blue, Anchor = Anchor.TopRight, @@ -81,20 +89,12 @@ namespace osu.Game.Tournament.Screens.Gameplay }, } }, - new Box - { - // chroma key area for stable gameplay - Name = "chroma", - RelativeSizeAxes = Axes.X, - Height = 500, - Colour = new Color4(0, 255, 0, 255), - }, } }, scoreDisplay = new MatchScoreDisplay { Y = -60, - Scale = new Vector2(0.86f), + Scale = new Vector2(0.8f), Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, }, diff --git a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs index 5b0b4b62e2..cd4f646fe7 100644 --- a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs +++ b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tournament.Screens.Showcase public TournamentLogo() { RelativeSizeAxes = Axes.X; - Height = 100; + Height = 95; Margin = new MarginPadding { Vertical = 5 }; } From fb05ea3de34e18cba986422e948b6e705eff126c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Nov 2018 16:23:44 +0900 Subject: [PATCH 0309/5608] Fix alignment and fonts of tem intro screen --- .../Screens/TeamIntro/TeamIntroScreen.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 7567325bfe..55af305045 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -105,8 +105,9 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Colour = col, + Font = "Exo2.0-Black", Text = "COMING UP NEXT", - Font = "Aquatico-Regular", + Spacing = new Vector2(2, 0), TextSize = 15, }, new OsuSpriteText @@ -115,7 +116,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Origin = Anchor.TopCentre, Colour = col, Text = pairing.Grouping.Value?.Name.Value ?? "Unknown Grouping", - Font = "Aquatico-Light", + Font = "Exo2.0-Light", Spacing = new Vector2(10, 0), TextSize = 50, }, @@ -123,7 +124,6 @@ namespace osu.Game.Tournament.Screens.TeamIntro { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Font = "Aquatico-Light", Colour = col, Text = pairing.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"), TextSize = 20, @@ -158,11 +158,10 @@ namespace osu.Game.Tournament.Screens.TeamIntro AutoSizeAxes = Axes.Both, Spacing = new Vector2(0, 5), Padding = new MarginPadding(20), - - - Anchor = !left ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = !left ? Anchor.CentreRight : Anchor.CentreLeft, + Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = left ? Anchor.CentreRight : Anchor.CentreLeft, RelativePositionAxes = Axes.Both, + X = (left ? -1 : 1) * 0.66f, }, }; @@ -172,7 +171,6 @@ namespace osu.Game.Tournament.Screens.TeamIntro players.Add(new OsuSpriteText { Text = p.Username, - Font = "Aquatico-Regular", TextSize = 24, Colour = colour, Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft, @@ -215,6 +213,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro { Text = teamName.ToUpper(), TextSize = 20, + Font = "Aquatico-Regular", Colour = colour, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, From 17a81259d4eae8d261caaf0b139a2a85bd8ae1ec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Nov 2018 17:25:46 +0900 Subject: [PATCH 0310/5608] Fix spacing and colouring of song bar eleemnts Also uses MM:ss instead of ssss. --- osu.Game.Tournament/Components/SongBar.cs | 73 +++++++++++++++-------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 3d9fe2f5ee..14a01aebdf 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -1,11 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; using osu.Game.Graphics; @@ -178,38 +180,26 @@ namespace osu.Game.Tournament.Components panelContents.Children = new Drawable[] { - new OsuSpriteText + new DiffPiece(("Length", TimeSpan.FromSeconds(length).ToString(@"mm\:ss"))) { - Text = $"Length {length:0}s", - Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, - Colour = OsuColour.Gray(0.33f), - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, + Anchor = Anchor.CentreLeft, + Origin = Anchor.BottomLeft, }, - new OsuSpriteText + new DiffPiece(("BPM", $"{bpm:0.#}")) { - Text = $"BPM {bpm:0.#}", - Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, - Colour = OsuColour.Gray(0.33f), - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft + Anchor = Anchor.CentreLeft, + Origin = Anchor.TopLeft }, - new OsuSpriteText + new DiffPiece(("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), ("AR", $"{ar:0.#}{srExtra}"), ("OD", $"{beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}")) { - Text = $"CS {beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra} / AR {ar:0.#}{srExtra} / OD {beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}", - Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, - Colour = OsuColour.Gray(0.33f), - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight - }, - new OsuSpriteText - { - Text = $"Star Rating {beatmap.StarDifficulty:0.#}{srExtra}", - Margin = new MarginPadding { Horizontal = 15, Vertical = 5 }, - Colour = OsuColour.Gray(0.33f), - Anchor = Anchor.BottomRight, + Anchor = Anchor.CentreRight, Origin = Anchor.BottomRight }, + new DiffPiece(("Star Rating", $"{beatmap.StarDifficulty:0.#}{srExtra}")) + { + Anchor = Anchor.CentreRight, + Origin = Anchor.TopRight + }, panel = new TournamentBeatmapPanel(beatmap) { Anchor = Anchor.Centre, @@ -219,5 +209,38 @@ namespace osu.Game.Tournament.Components } }; } + + public class DiffPiece : TextFlowContainer + { + public DiffPiece(params (string heading, string content)[] tuples) + { + Margin = new MarginPadding { Horizontal = 15, Vertical = 1 }; + AutoSizeAxes = Axes.Both; + + void cp(SpriteText s, Color4 colour) + { + s.Colour = colour; + s.TextSize = 15; + s.Font = @"Exo2.0-Bold"; + } + + bool first = true; + foreach (var t in tuples) + { + if (!first) + AddText(" / ", s => + { + cp(s, OsuColour.Gray(0.33f)); + s.Spacing = new Vector2(-2, 0); + }); + + AddText(new OsuSpriteText { Text = t.heading }, s => cp(s, OsuColour.Gray(0.33f))); + AddText(" ", s => cp(s, OsuColour.Gray(0.33f))); + AddText(new OsuSpriteText { Text = t.content }, s => cp(s, OsuColour.Gray(0.5f))); + first = false; + } + } + } } } + From fdba2bffb9dee193def8d9cf4cb929849c9d11df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Nov 2018 17:33:48 +0900 Subject: [PATCH 0311/5608] Ensure last state is set correctly --- .../Screens/Gameplay/GameplayScreen.cs | 103 +++++++++--------- 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 8897a98a7e..05cf4751f4 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -135,61 +135,66 @@ namespace osu.Game.Tournament.Screens.Gameplay private void stateChanged(TourneyState state) { - if (state == TourneyState.Ranking) + try { - if (warmup.Value) return; - - if (ipc.Score1 > ipc.Score2) - currentMatch.Value.Team1Score.Value++; - else - currentMatch.Value.Team2Score.Value++; - } - - scheduledOperation?.Cancel(); - - void expand() - { - chat.Expand(); - - using (BeginDelayedSequence(300, true)) + if (state == TourneyState.Ranking) { - scoreDisplay.FadeIn(100); - SongBar.Expanded = true; + if (warmup.Value) return; + + if (ipc.Score1 > ipc.Score2) + currentMatch.Value.Team1Score.Value++; + else + currentMatch.Value.Team2Score.Value++; + } + + scheduledOperation?.Cancel(); + + void expand() + { + chat.Expand(); + + using (BeginDelayedSequence(300, true)) + { + scoreDisplay.FadeIn(100); + SongBar.Expanded = true; + } + } + + void contract() + { + SongBar.Expanded = false; + scoreDisplay.FadeOut(100); + using (chat.BeginDelayedSequence(500)) + chat.Contract(); + } + + switch (state) + { + case TourneyState.Idle: + contract(); + + if (lastState == TourneyState.Ranking && !warmup.Value) + { + if (currentMatch.Value?.Completed == true) + scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(TeamWinScreen)); }, 4000); + else if (currentMatch.Value?.Completed == false) + scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(MapPoolScreen)); }, 4000); + } + + break; + case TourneyState.Ranking: + scheduledOperation = Scheduler.AddDelayed(contract, 10000); + break; + default: + chat.Expand(); + expand(); + break; } } - - void contract() + finally { - SongBar.Expanded = false; - scoreDisplay.FadeOut(100); - using (chat.BeginDelayedSequence(500)) - chat.Contract(); + lastState = state; } - - switch (state) - { - case TourneyState.Idle: - contract(); - - if (lastState == TourneyState.Ranking && !warmup.Value) - { - if (currentMatch.Value?.Completed == true) - scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(TeamWinScreen)); }, 4000); - else if (currentMatch.Value?.Completed == false) - scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(MapPoolScreen)); }, 4000); - } - - break; - case TourneyState.Ranking: - scheduledOperation = Scheduler.AddDelayed(contract, 10000); - break; - default: - chat.Expand(); - expand(); - break; - } - - lastState = state; } } } From 056025c5c2ddc5bca93d5f104372f8b224fe4891 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 1 Dec 2018 09:50:11 +0900 Subject: [PATCH 0312/5608] Fix handling of API responses --- osu.Game.Tournament/Components/TournamentBeatmapPanel.cs | 3 +++ osu.Game.Tournament/TournamentGameBase.cs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 3165e5a2c4..ae2e2b5160 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; @@ -39,6 +40,8 @@ namespace osu.Game.Tournament.Components public TournamentBeatmapPanel(BeatmapInfo beatmap, string mods = null) { + if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); + Beatmap = beatmap; this.mods = mods; Width = 400; diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 8734b2e64b..e37b7cf8d6 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -113,8 +113,8 @@ namespace osu.Game.Tournament if (string.IsNullOrEmpty(p.Username)) { var req = new GetUserRequest(p.Id); - req.Success += i => p.Username = i.Username; req.Perform(API); + p.Username = req.Result.Username; addedInfo = true; } @@ -125,8 +125,8 @@ namespace osu.Game.Tournament if (b.BeatmapInfo == null) { var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); - req.Success += i => b.BeatmapInfo = i.ToBeatmap(RulesetStore); req.Perform(API); + b.BeatmapInfo = req.Result?.ToBeatmap(RulesetStore); addedInfo = true; } From 61ca79a8b2294eba4cd83be2a7b725912ae00dc6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 1 Dec 2018 15:32:11 +0900 Subject: [PATCH 0313/5608] Add conditional match support --- .../Components/ConditionalMatchPairing.cs | 12 +++++++++ .../Ladder/Components/DrawableMatchPairing.cs | 14 ++++++++++- .../Screens/Ladder/Components/MatchPairing.cs | 16 +++++++++++- .../Screens/Schedule/ScheduleScreen.cs | 25 +++++++++++++------ osu.Game.Tournament/TournamentGameBase.cs | 7 ++++++ 5 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs new file mode 100644 index 0000000000..bff661bcf4 --- /dev/null +++ b/osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Tournament.Screens.Ladder.Components +{ + /// + /// A pairing that may not necessarily occur. + /// + public class ConditionalMatchPairing : MatchPairing + { + } +} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index e727e740f9..db942c6e4c 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -199,6 +199,18 @@ namespace osu.Game.Tournament.Screens.Ladder.Components if (Pairing.Team1.Value == null || Pairing.Team2.Value == null) Pairing.CancelMatchStart(); + if (Pairing.ConditionalPairings.Count > 0) + { + foreach (var conditional in Pairing.ConditionalPairings) + { + var team1Match = conditional.Acronyms.Contains(Pairing.Team1Acronym); + var team2Match = conditional.Acronyms.Contains(Pairing.Team2Acronym); + + if (team1Match && team2Match) + Pairing.Date.Value = conditional.Date; + } + } + Flow.Children = new[] { new DrawableMatchTeam(Pairing.Team1, Pairing, Pairing.Losers), @@ -226,7 +238,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components protected override bool OnClick(ClickEvent e) { - if (editorInfo == null) + if (editorInfo == null || Pairing is ConditionalMatchPairing) return false; Selected = true; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index 003f41cfa9..8461cf4ae1 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using Newtonsoft.Json; using osu.Framework.Configuration; @@ -17,6 +18,17 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public int ID; + public List Acronyms + { + get + { + List acronyms = new List(); + if (Team1Acronym != null) acronyms.Add(Team1Acronym); + if (Team2Acronym != null) acronyms.Add(Team2Acronym); + return acronyms; + } + } + [JsonIgnore] public readonly Bindable Team1 = new Bindable(); @@ -53,6 +65,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly Bindable Date = new Bindable(); + public readonly BindableCollection ConditionalPairings = new BindableCollection(); + public readonly Bindable Position = new Bindable(); public MatchPairing() @@ -74,7 +88,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [JsonIgnore] public TournamentTeam Loser => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team2.Value : Team1.Value; - public int PointsToWin => Grouping.Value.BestOf / 2 + 1; + public int PointsToWin => Grouping.Value == null ? 0 : Grouping.Value.BestOf / 2 + 1; /// /// Remove scores from the match, in case of a false click or false start. diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index 37577ec3b0..f3f3667db1 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -56,6 +56,13 @@ namespace osu.Game.Tournament.Screens.Schedule return; } + var upcoming = ladder.Pairings.Where(p => !p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4); + var conditionals = ladder.Pairings.Where(p => !p.Completed.Value && (p.Team1.Value == null || p.Team2.Value == null) && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4) + .SelectMany(m => m.ConditionalPairings.Where(cp => m.Acronyms.TrueForAll(a => cp.Acronyms.Contains(a)))); + + upcoming = upcoming.Concat(conditionals); + upcoming = upcoming.OrderBy(p => p.Date.Value).Take(12); + mainContainer.Child = new FillFlowContainer { RelativeSizeAxes = Axes.Both, @@ -77,7 +84,8 @@ namespace osu.Game.Tournament.Screens.Schedule RelativeSizeAxes = Axes.Both, Width = 0.4f, ChildrenEnumerable = ladder.Pairings - .Where(p => p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4) + .Where(p => p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null + && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4) .OrderByDescending(p => p.Date.Value) .Take(8) .Select(p => new SchedulePairing(p)) @@ -86,11 +94,7 @@ namespace osu.Game.Tournament.Screens.Schedule { RelativeSizeAxes = Axes.Both, Width = 0.6f, - ChildrenEnumerable = ladder.Pairings - .Where(p => !p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4) - .OrderBy(p => p.Date.Value) - .Take(8) - .Select(p => new SchedulePairing(p)) + ChildrenEnumerable = upcoming.Select(p => new SchedulePairing(p)) }, } } @@ -129,6 +133,11 @@ namespace osu.Game.Tournament.Screens.Schedule { Flow.Direction = FillDirection.Horizontal; + bool conditional = pairing is ConditionalMatchPairing; + + if (conditional) + Colour = OsuColour.Gray(0.5f); + if (showTimestamp) { AddInternal(new DrawableDate(Pairing.Date.Value) @@ -136,6 +145,7 @@ namespace osu.Game.Tournament.Screens.Schedule Anchor = Anchor.TopRight, Origin = Anchor.TopLeft, Colour = Color4.Black, + Alpha = conditional ? 0.6f : 1, Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, }); AddInternal(new OsuSpriteText @@ -143,8 +153,9 @@ namespace osu.Game.Tournament.Screens.Schedule Anchor = Anchor.BottomRight, Origin = Anchor.BottomLeft, Colour = Color4.Black, + Alpha = conditional ? 0.6f : 1, Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, - Text = pairing.Date.Value.ToUniversalTime().ToString("HH:mm UTC") + Text = pairing.Date.Value.ToUniversalTime().ToString("HH:mm UTC") + (conditional ? " (conditional)" : "") }); } } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index e37b7cf8d6..4938533a9e 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -78,6 +78,13 @@ namespace osu.Game.Tournament { pairing.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == pairing.Team1Acronym); pairing.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == pairing.Team2Acronym); + + foreach (var conditional in pairing.ConditionalPairings) + { + conditional.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == conditional.Team1Acronym); + conditional.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == conditional.Team2Acronym); + conditional.Grouping.Value = pairing.Grouping.Value; + } } // assign progressions From d16f6576ca70b62ea6d4ac30ea78d36a5d4d8359 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Thu, 13 Dec 2018 00:10:15 -0600 Subject: [PATCH 0314/5608] Add Android project --- osu.Android/Assets/AboutAssets.txt | 19 + osu.Android/GameView.cs | 26 + osu.Android/MainActivity.cs | 26 + osu.Android/Properties/AndroidManifest.xml | 9 + osu.Android/Properties/AssemblyInfo.cs | 33 + osu.Android/Resources/AboutResources.txt | 44 + osu.Android/Resources/Resource.designer.cs | 6488 +++++++++++++++++ .../Resources/layout/activity_main.axml | 13 + .../mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../Resources/mipmap-hdpi/ic_launcher.png | Bin 0 -> 8828 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 1441 bytes .../mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 8828 bytes .../Resources/mipmap-mdpi/ic_launcher.png | Bin 0 -> 5045 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 958 bytes .../mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 5045 bytes .../Resources/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 12931 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 2056 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 12931 bytes .../Resources/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 21256 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 3403 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 21256 bytes .../Resources/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 30047 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 4889 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 30047 bytes osu.Android/Resources/values/Strings.xml | 4 + osu.Android/Resources/values/colors.xml | 6 + .../values/ic_launcher_background.xml | 4 + osu.Android/Resources/values/styles.xml | 11 + osu.Android/bass.dll | Bin 0 -> 210944 bytes osu.Android/lib/arm64-v8a/libbass.so | Bin 0 -> 308904 bytes osu.Android/lib/arm64-v8a/libbass_fx.so | Bin 0 -> 154408 bytes osu.Android/lib/armeabi-v7a/libbass.so | Bin 0 -> 222620 bytes osu.Android/lib/armeabi-v7a/libbass_fx.so | Bin 0 -> 92176 bytes osu.Android/osu.Android.csproj | 175 + 35 files changed, 6868 insertions(+) create mode 100644 osu.Android/Assets/AboutAssets.txt create mode 100644 osu.Android/GameView.cs create mode 100644 osu.Android/MainActivity.cs create mode 100644 osu.Android/Properties/AndroidManifest.xml create mode 100644 osu.Android/Properties/AssemblyInfo.cs create mode 100644 osu.Android/Resources/AboutResources.txt create mode 100644 osu.Android/Resources/Resource.designer.cs create mode 100644 osu.Android/Resources/layout/activity_main.axml create mode 100644 osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 osu.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 osu.Android/Resources/mipmap-hdpi/ic_launcher.png create mode 100644 osu.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 osu.Android/Resources/mipmap-hdpi/ic_launcher_round.png create mode 100644 osu.Android/Resources/mipmap-mdpi/ic_launcher.png create mode 100644 osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 osu.Android/Resources/mipmap-mdpi/ic_launcher_round.png create mode 100644 osu.Android/Resources/mipmap-xhdpi/ic_launcher.png create mode 100644 osu.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 osu.Android/Resources/mipmap-xhdpi/ic_launcher_round.png create mode 100644 osu.Android/Resources/mipmap-xxhdpi/ic_launcher.png create mode 100644 osu.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 osu.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 osu.Android/Resources/mipmap-xxxhdpi/ic_launcher.png create mode 100644 osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 osu.Android/Resources/values/Strings.xml create mode 100644 osu.Android/Resources/values/colors.xml create mode 100644 osu.Android/Resources/values/ic_launcher_background.xml create mode 100644 osu.Android/Resources/values/styles.xml create mode 100644 osu.Android/bass.dll create mode 100644 osu.Android/lib/arm64-v8a/libbass.so create mode 100644 osu.Android/lib/arm64-v8a/libbass_fx.so create mode 100644 osu.Android/lib/armeabi-v7a/libbass.so create mode 100644 osu.Android/lib/armeabi-v7a/libbass_fx.so create mode 100644 osu.Android/osu.Android.csproj diff --git a/osu.Android/Assets/AboutAssets.txt b/osu.Android/Assets/AboutAssets.txt new file mode 100644 index 0000000000..b0633374bd --- /dev/null +++ b/osu.Android/Assets/AboutAssets.txt @@ -0,0 +1,19 @@ +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories) and given a Build Action of "AndroidAsset". + +These files will be deployed with you package and will be accessible using Android's +AssetManager, like this: + +public class ReadAsset : Activity +{ + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + InputStream input = Assets.Open ("my_asset.txt"); + } +} + +Additionally, some Android functions will automatically load asset files: + +Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); \ No newline at end of file diff --git a/osu.Android/GameView.cs b/osu.Android/GameView.cs new file mode 100644 index 0000000000..649ee0134b --- /dev/null +++ b/osu.Android/GameView.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using Android.Content; +using Android.Util; +using osu.Framework; +using osu.Framework.Android; +using osu.Game; + +namespace osu.Android +{ + public class GameView : AndroidGameView + { + public GameView(Context context, IAttributeSet attrs) : + base(context, attrs) + { + CreateGame(); + } + + public GameView(Context context) : base(context) + { + CreateGame(); + } + public override Framework.Game CreateGame() => new OsuGame(); + } +} diff --git a/osu.Android/MainActivity.cs b/osu.Android/MainActivity.cs new file mode 100644 index 0000000000..3a8a5026bc --- /dev/null +++ b/osu.Android/MainActivity.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using Android.App; +using Android.OS; +using Android.Runtime; +using Android.Widget; +using Android.Content.PM; + +namespace osu.Android +{ + [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true, ScreenOrientation = ScreenOrientation.Landscape, SupportsPictureInPicture = false)] + public class MainActivity : Activity + { + protected override void OnCreate(Bundle savedInstanceState) + { + base.OnCreate(savedInstanceState); + // Set our view from the "main" layout resource + SetContentView(Resource.Layout.activity_main); + } + public override void OnBackPressed() + { + + } + } +} diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml new file mode 100644 index 0000000000..12d1f326b9 --- /dev/null +++ b/osu.Android/Properties/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/osu.Android/Properties/AssemblyInfo.cs b/osu.Android/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..d222a06ee0 --- /dev/null +++ b/osu.Android/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Android.App; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("osu.Android")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("osu.Android")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/osu.Android/Resources/AboutResources.txt b/osu.Android/Resources/AboutResources.txt new file mode 100644 index 0000000000..c2bca974c4 --- /dev/null +++ b/osu.Android/Resources/AboutResources.txt @@ -0,0 +1,44 @@ +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.axml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable/ + icon.png + + layout/ + main.axml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called "R" +(this is an Android convention) that contains the tokens for each one of the resources +included. For example, for the above Resources layout, this is what the R class would expose: + +public class R { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main +to reference the layout/main.axml file, or R.strings.first_string to reference the first +string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/osu.Android/Resources/Resource.designer.cs b/osu.Android/Resources/Resource.designer.cs new file mode 100644 index 0000000000..ed8407c130 --- /dev/null +++ b/osu.Android/Resources/Resource.designer.cs @@ -0,0 +1,6488 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +[assembly: global::Android.Runtime.ResourceDesignerAttribute("osu.Android.Resource", IsApplication=true)] + +namespace osu.Android +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public static void UpdateIdValues() + { + } + + public partial class Animation + { + + // aapt resource value: 0x7f050000 + public const int abc_fade_in = 2131034112; + + // aapt resource value: 0x7f050001 + public const int abc_fade_out = 2131034113; + + // aapt resource value: 0x7f050002 + public const int abc_grow_fade_in_from_bottom = 2131034114; + + // aapt resource value: 0x7f050003 + public const int abc_popup_enter = 2131034115; + + // aapt resource value: 0x7f050004 + public const int abc_popup_exit = 2131034116; + + // aapt resource value: 0x7f050005 + public const int abc_shrink_fade_out_from_bottom = 2131034117; + + // aapt resource value: 0x7f050006 + public const int abc_slide_in_bottom = 2131034118; + + // aapt resource value: 0x7f050007 + public const int abc_slide_in_top = 2131034119; + + // aapt resource value: 0x7f050008 + public const int abc_slide_out_bottom = 2131034120; + + // aapt resource value: 0x7f050009 + public const int abc_slide_out_top = 2131034121; + + // aapt resource value: 0x7f05000a + public const int design_bottom_sheet_slide_in = 2131034122; + + // aapt resource value: 0x7f05000b + public const int design_bottom_sheet_slide_out = 2131034123; + + // aapt resource value: 0x7f05000c + public const int design_snackbar_in = 2131034124; + + // aapt resource value: 0x7f05000d + public const int design_snackbar_out = 2131034125; + + // aapt resource value: 0x7f05000e + public const int tooltip_enter = 2131034126; + + // aapt resource value: 0x7f05000f + public const int tooltip_exit = 2131034127; + + static Animation() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Animation() + { + } + } + + public partial class Animator + { + + // aapt resource value: 0x7f060000 + public const int design_appbar_state_list_animator = 2131099648; + + static Animator() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Animator() + { + } + } + + public partial class Attribute + { + + // aapt resource value: 0x7f010052 + public const int actionBarDivider = 2130772050; + + // aapt resource value: 0x7f010053 + public const int actionBarItemBackground = 2130772051; + + // aapt resource value: 0x7f01004c + public const int actionBarPopupTheme = 2130772044; + + // aapt resource value: 0x7f010051 + public const int actionBarSize = 2130772049; + + // aapt resource value: 0x7f01004e + public const int actionBarSplitStyle = 2130772046; + + // aapt resource value: 0x7f01004d + public const int actionBarStyle = 2130772045; + + // aapt resource value: 0x7f010048 + public const int actionBarTabBarStyle = 2130772040; + + // aapt resource value: 0x7f010047 + public const int actionBarTabStyle = 2130772039; + + // aapt resource value: 0x7f010049 + public const int actionBarTabTextStyle = 2130772041; + + // aapt resource value: 0x7f01004f + public const int actionBarTheme = 2130772047; + + // aapt resource value: 0x7f010050 + public const int actionBarWidgetTheme = 2130772048; + + // aapt resource value: 0x7f01006d + public const int actionButtonStyle = 2130772077; + + // aapt resource value: 0x7f010069 + public const int actionDropDownStyle = 2130772073; + + // aapt resource value: 0x7f0100c4 + public const int actionLayout = 2130772164; + + // aapt resource value: 0x7f010054 + public const int actionMenuTextAppearance = 2130772052; + + // aapt resource value: 0x7f010055 + public const int actionMenuTextColor = 2130772053; + + // aapt resource value: 0x7f010058 + public const int actionModeBackground = 2130772056; + + // aapt resource value: 0x7f010057 + public const int actionModeCloseButtonStyle = 2130772055; + + // aapt resource value: 0x7f01005a + public const int actionModeCloseDrawable = 2130772058; + + // aapt resource value: 0x7f01005c + public const int actionModeCopyDrawable = 2130772060; + + // aapt resource value: 0x7f01005b + public const int actionModeCutDrawable = 2130772059; + + // aapt resource value: 0x7f010060 + public const int actionModeFindDrawable = 2130772064; + + // aapt resource value: 0x7f01005d + public const int actionModePasteDrawable = 2130772061; + + // aapt resource value: 0x7f010062 + public const int actionModePopupWindowStyle = 2130772066; + + // aapt resource value: 0x7f01005e + public const int actionModeSelectAllDrawable = 2130772062; + + // aapt resource value: 0x7f01005f + public const int actionModeShareDrawable = 2130772063; + + // aapt resource value: 0x7f010059 + public const int actionModeSplitBackground = 2130772057; + + // aapt resource value: 0x7f010056 + public const int actionModeStyle = 2130772054; + + // aapt resource value: 0x7f010061 + public const int actionModeWebSearchDrawable = 2130772065; + + // aapt resource value: 0x7f01004a + public const int actionOverflowButtonStyle = 2130772042; + + // aapt resource value: 0x7f01004b + public const int actionOverflowMenuStyle = 2130772043; + + // aapt resource value: 0x7f0100c6 + public const int actionProviderClass = 2130772166; + + // aapt resource value: 0x7f0100c5 + public const int actionViewClass = 2130772165; + + // aapt resource value: 0x7f010075 + public const int activityChooserViewStyle = 2130772085; + + // aapt resource value: 0x7f01009a + public const int alertDialogButtonGroupStyle = 2130772122; + + // aapt resource value: 0x7f01009b + public const int alertDialogCenterButtons = 2130772123; + + // aapt resource value: 0x7f010099 + public const int alertDialogStyle = 2130772121; + + // aapt resource value: 0x7f01009c + public const int alertDialogTheme = 2130772124; + + // aapt resource value: 0x7f0100b2 + public const int allowStacking = 2130772146; + + // aapt resource value: 0x7f0100b3 + public const int alpha = 2130772147; + + // aapt resource value: 0x7f0100c1 + public const int alphabeticModifiers = 2130772161; + + // aapt resource value: 0x7f0100ba + public const int arrowHeadLength = 2130772154; + + // aapt resource value: 0x7f0100bb + public const int arrowShaftLength = 2130772155; + + // aapt resource value: 0x7f0100a1 + public const int autoCompleteTextViewStyle = 2130772129; + + // aapt resource value: 0x7f01003b + public const int autoSizeMaxTextSize = 2130772027; + + // aapt resource value: 0x7f01003a + public const int autoSizeMinTextSize = 2130772026; + + // aapt resource value: 0x7f010039 + public const int autoSizePresetSizes = 2130772025; + + // aapt resource value: 0x7f010038 + public const int autoSizeStepGranularity = 2130772024; + + // aapt resource value: 0x7f010037 + public const int autoSizeTextType = 2130772023; + + // aapt resource value: 0x7f010015 + public const int background = 2130771989; + + // aapt resource value: 0x7f010017 + public const int backgroundSplit = 2130771991; + + // aapt resource value: 0x7f010016 + public const int backgroundStacked = 2130771990; + + // aapt resource value: 0x7f0100fd + public const int backgroundTint = 2130772221; + + // aapt resource value: 0x7f0100fe + public const int backgroundTintMode = 2130772222; + + // aapt resource value: 0x7f0100bc + public const int barLength = 2130772156; + + // aapt resource value: 0x7f010128 + public const int behavior_autoHide = 2130772264; + + // aapt resource value: 0x7f010105 + public const int behavior_hideable = 2130772229; + + // aapt resource value: 0x7f010131 + public const int behavior_overlapTop = 2130772273; + + // aapt resource value: 0x7f010104 + public const int behavior_peekHeight = 2130772228; + + // aapt resource value: 0x7f010106 + public const int behavior_skipCollapsed = 2130772230; + + // aapt resource value: 0x7f010126 + public const int borderWidth = 2130772262; + + // aapt resource value: 0x7f010072 + public const int borderlessButtonStyle = 2130772082; + + // aapt resource value: 0x7f010120 + public const int bottomSheetDialogTheme = 2130772256; + + // aapt resource value: 0x7f010121 + public const int bottomSheetStyle = 2130772257; + + // aapt resource value: 0x7f01006f + public const int buttonBarButtonStyle = 2130772079; + + // aapt resource value: 0x7f01009f + public const int buttonBarNegativeButtonStyle = 2130772127; + + // aapt resource value: 0x7f0100a0 + public const int buttonBarNeutralButtonStyle = 2130772128; + + // aapt resource value: 0x7f01009e + public const int buttonBarPositiveButtonStyle = 2130772126; + + // aapt resource value: 0x7f01006e + public const int buttonBarStyle = 2130772078; + + // aapt resource value: 0x7f0100f2 + public const int buttonGravity = 2130772210; + + // aapt resource value: 0x7f01002a + public const int buttonPanelSideLayout = 2130772010; + + // aapt resource value: 0x7f0100a2 + public const int buttonStyle = 2130772130; + + // aapt resource value: 0x7f0100a3 + public const int buttonStyleSmall = 2130772131; + + // aapt resource value: 0x7f0100b4 + public const int buttonTint = 2130772148; + + // aapt resource value: 0x7f0100b5 + public const int buttonTintMode = 2130772149; + + // aapt resource value: 0x7f0100a4 + public const int checkboxStyle = 2130772132; + + // aapt resource value: 0x7f0100a5 + public const int checkedTextViewStyle = 2130772133; + + // aapt resource value: 0x7f0100d5 + public const int closeIcon = 2130772181; + + // aapt resource value: 0x7f010027 + public const int closeItemLayout = 2130772007; + + // aapt resource value: 0x7f0100f4 + public const int collapseContentDescription = 2130772212; + + // aapt resource value: 0x7f0100f3 + public const int collapseIcon = 2130772211; + + // aapt resource value: 0x7f010113 + public const int collapsedTitleGravity = 2130772243; + + // aapt resource value: 0x7f01010d + public const int collapsedTitleTextAppearance = 2130772237; + + // aapt resource value: 0x7f0100b6 + public const int color = 2130772150; + + // aapt resource value: 0x7f010091 + public const int colorAccent = 2130772113; + + // aapt resource value: 0x7f010098 + public const int colorBackgroundFloating = 2130772120; + + // aapt resource value: 0x7f010095 + public const int colorButtonNormal = 2130772117; + + // aapt resource value: 0x7f010093 + public const int colorControlActivated = 2130772115; + + // aapt resource value: 0x7f010094 + public const int colorControlHighlight = 2130772116; + + // aapt resource value: 0x7f010092 + public const int colorControlNormal = 2130772114; + + // aapt resource value: 0x7f0100b1 + public const int colorError = 2130772145; + + // aapt resource value: 0x7f01008f + public const int colorPrimary = 2130772111; + + // aapt resource value: 0x7f010090 + public const int colorPrimaryDark = 2130772112; + + // aapt resource value: 0x7f010096 + public const int colorSwitchThumbNormal = 2130772118; + + // aapt resource value: 0x7f0100da + public const int commitIcon = 2130772186; + + // aapt resource value: 0x7f0100c7 + public const int contentDescription = 2130772167; + + // aapt resource value: 0x7f010020 + public const int contentInsetEnd = 2130772000; + + // aapt resource value: 0x7f010024 + public const int contentInsetEndWithActions = 2130772004; + + // aapt resource value: 0x7f010021 + public const int contentInsetLeft = 2130772001; + + // aapt resource value: 0x7f010022 + public const int contentInsetRight = 2130772002; + + // aapt resource value: 0x7f01001f + public const int contentInsetStart = 2130771999; + + // aapt resource value: 0x7f010023 + public const int contentInsetStartWithNavigation = 2130772003; + + // aapt resource value: 0x7f01010e + public const int contentScrim = 2130772238; + + // aapt resource value: 0x7f010097 + public const int controlBackground = 2130772119; + + // aapt resource value: 0x7f010147 + public const int counterEnabled = 2130772295; + + // aapt resource value: 0x7f010148 + public const int counterMaxLength = 2130772296; + + // aapt resource value: 0x7f01014a + public const int counterOverflowTextAppearance = 2130772298; + + // aapt resource value: 0x7f010149 + public const int counterTextAppearance = 2130772297; + + // aapt resource value: 0x7f010018 + public const int customNavigationLayout = 2130771992; + + // aapt resource value: 0x7f0100d4 + public const int defaultQueryHint = 2130772180; + + // aapt resource value: 0x7f010067 + public const int dialogPreferredPadding = 2130772071; + + // aapt resource value: 0x7f010066 + public const int dialogTheme = 2130772070; + + // aapt resource value: 0x7f01000e + public const int displayOptions = 2130771982; + + // aapt resource value: 0x7f010014 + public const int divider = 2130771988; + + // aapt resource value: 0x7f010074 + public const int dividerHorizontal = 2130772084; + + // aapt resource value: 0x7f0100c0 + public const int dividerPadding = 2130772160; + + // aapt resource value: 0x7f010073 + public const int dividerVertical = 2130772083; + + // aapt resource value: 0x7f0100b8 + public const int drawableSize = 2130772152; + + // aapt resource value: 0x7f010009 + public const int drawerArrowStyle = 2130771977; + + // aapt resource value: 0x7f010086 + public const int dropDownListViewStyle = 2130772102; + + // aapt resource value: 0x7f01006a + public const int dropdownListPreferredItemHeight = 2130772074; + + // aapt resource value: 0x7f01007b + public const int editTextBackground = 2130772091; + + // aapt resource value: 0x7f01007a + public const int editTextColor = 2130772090; + + // aapt resource value: 0x7f0100a6 + public const int editTextStyle = 2130772134; + + // aapt resource value: 0x7f010025 + public const int elevation = 2130772005; + + // aapt resource value: 0x7f010145 + public const int errorEnabled = 2130772293; + + // aapt resource value: 0x7f010146 + public const int errorTextAppearance = 2130772294; + + // aapt resource value: 0x7f010029 + public const int expandActivityOverflowButtonDrawable = 2130772009; + + // aapt resource value: 0x7f0100ff + public const int expanded = 2130772223; + + // aapt resource value: 0x7f010114 + public const int expandedTitleGravity = 2130772244; + + // aapt resource value: 0x7f010107 + public const int expandedTitleMargin = 2130772231; + + // aapt resource value: 0x7f01010b + public const int expandedTitleMarginBottom = 2130772235; + + // aapt resource value: 0x7f01010a + public const int expandedTitleMarginEnd = 2130772234; + + // aapt resource value: 0x7f010108 + public const int expandedTitleMarginStart = 2130772232; + + // aapt resource value: 0x7f010109 + public const int expandedTitleMarginTop = 2130772233; + + // aapt resource value: 0x7f01010c + public const int expandedTitleTextAppearance = 2130772236; + + // aapt resource value: 0x7f010124 + public const int fabSize = 2130772260; + + // aapt resource value: 0x7f010004 + public const int fastScrollEnabled = 2130771972; + + // aapt resource value: 0x7f010007 + public const int fastScrollHorizontalThumbDrawable = 2130771975; + + // aapt resource value: 0x7f010008 + public const int fastScrollHorizontalTrackDrawable = 2130771976; + + // aapt resource value: 0x7f010005 + public const int fastScrollVerticalThumbDrawable = 2130771973; + + // aapt resource value: 0x7f010006 + public const int fastScrollVerticalTrackDrawable = 2130771974; + + // aapt resource value: 0x7f010158 + public const int font = 2130772312; + + // aapt resource value: 0x7f01003c + public const int fontFamily = 2130772028; + + // aapt resource value: 0x7f010151 + public const int fontProviderAuthority = 2130772305; + + // aapt resource value: 0x7f010154 + public const int fontProviderCerts = 2130772308; + + // aapt resource value: 0x7f010155 + public const int fontProviderFetchStrategy = 2130772309; + + // aapt resource value: 0x7f010156 + public const int fontProviderFetchTimeout = 2130772310; + + // aapt resource value: 0x7f010152 + public const int fontProviderPackage = 2130772306; + + // aapt resource value: 0x7f010153 + public const int fontProviderQuery = 2130772307; + + // aapt resource value: 0x7f010157 + public const int fontStyle = 2130772311; + + // aapt resource value: 0x7f010159 + public const int fontWeight = 2130772313; + + // aapt resource value: 0x7f010129 + public const int foregroundInsidePadding = 2130772265; + + // aapt resource value: 0x7f0100b9 + public const int gapBetweenBars = 2130772153; + + // aapt resource value: 0x7f0100d6 + public const int goIcon = 2130772182; + + // aapt resource value: 0x7f01012f + public const int headerLayout = 2130772271; + + // aapt resource value: 0x7f01000a + public const int height = 2130771978; + + // aapt resource value: 0x7f01001e + public const int hideOnContentScroll = 2130771998; + + // aapt resource value: 0x7f01014b + public const int hintAnimationEnabled = 2130772299; + + // aapt resource value: 0x7f010144 + public const int hintEnabled = 2130772292; + + // aapt resource value: 0x7f010143 + public const int hintTextAppearance = 2130772291; + + // aapt resource value: 0x7f01006c + public const int homeAsUpIndicator = 2130772076; + + // aapt resource value: 0x7f010019 + public const int homeLayout = 2130771993; + + // aapt resource value: 0x7f010012 + public const int icon = 2130771986; + + // aapt resource value: 0x7f0100c9 + public const int iconTint = 2130772169; + + // aapt resource value: 0x7f0100ca + public const int iconTintMode = 2130772170; + + // aapt resource value: 0x7f0100d2 + public const int iconifiedByDefault = 2130772178; + + // aapt resource value: 0x7f01007c + public const int imageButtonStyle = 2130772092; + + // aapt resource value: 0x7f01001b + public const int indeterminateProgressStyle = 2130771995; + + // aapt resource value: 0x7f010028 + public const int initialActivityCount = 2130772008; + + // aapt resource value: 0x7f010130 + public const int insetForeground = 2130772272; + + // aapt resource value: 0x7f01000b + public const int isLightTheme = 2130771979; + + // aapt resource value: 0x7f01012d + public const int itemBackground = 2130772269; + + // aapt resource value: 0x7f01012b + public const int itemIconTint = 2130772267; + + // aapt resource value: 0x7f01001d + public const int itemPadding = 2130771997; + + // aapt resource value: 0x7f01012e + public const int itemTextAppearance = 2130772270; + + // aapt resource value: 0x7f01012c + public const int itemTextColor = 2130772268; + + // aapt resource value: 0x7f010118 + public const int keylines = 2130772248; + + // aapt resource value: 0x7f0100d1 + public const int layout = 2130772177; + + // aapt resource value: 0x7f010000 + public const int layoutManager = 2130771968; + + // aapt resource value: 0x7f01011b + public const int layout_anchor = 2130772251; + + // aapt resource value: 0x7f01011d + public const int layout_anchorGravity = 2130772253; + + // aapt resource value: 0x7f01011a + public const int layout_behavior = 2130772250; + + // aapt resource value: 0x7f010116 + public const int layout_collapseMode = 2130772246; + + // aapt resource value: 0x7f010117 + public const int layout_collapseParallaxMultiplier = 2130772247; + + // aapt resource value: 0x7f01011f + public const int layout_dodgeInsetEdges = 2130772255; + + // aapt resource value: 0x7f01011e + public const int layout_insetEdge = 2130772254; + + // aapt resource value: 0x7f01011c + public const int layout_keyline = 2130772252; + + // aapt resource value: 0x7f010102 + public const int layout_scrollFlags = 2130772226; + + // aapt resource value: 0x7f010103 + public const int layout_scrollInterpolator = 2130772227; + + // aapt resource value: 0x7f01008e + public const int listChoiceBackgroundIndicator = 2130772110; + + // aapt resource value: 0x7f010068 + public const int listDividerAlertDialog = 2130772072; + + // aapt resource value: 0x7f01002e + public const int listItemLayout = 2130772014; + + // aapt resource value: 0x7f01002b + public const int listLayout = 2130772011; + + // aapt resource value: 0x7f0100ae + public const int listMenuViewStyle = 2130772142; + + // aapt resource value: 0x7f010087 + public const int listPopupWindowStyle = 2130772103; + + // aapt resource value: 0x7f010081 + public const int listPreferredItemHeight = 2130772097; + + // aapt resource value: 0x7f010083 + public const int listPreferredItemHeightLarge = 2130772099; + + // aapt resource value: 0x7f010082 + public const int listPreferredItemHeightSmall = 2130772098; + + // aapt resource value: 0x7f010084 + public const int listPreferredItemPaddingLeft = 2130772100; + + // aapt resource value: 0x7f010085 + public const int listPreferredItemPaddingRight = 2130772101; + + // aapt resource value: 0x7f010013 + public const int logo = 2130771987; + + // aapt resource value: 0x7f0100f7 + public const int logoDescription = 2130772215; + + // aapt resource value: 0x7f010132 + public const int maxActionInlineWidth = 2130772274; + + // aapt resource value: 0x7f0100f1 + public const int maxButtonHeight = 2130772209; + + // aapt resource value: 0x7f0100be + public const int measureWithLargestChild = 2130772158; + + // aapt resource value: 0x7f01012a + public const int menu = 2130772266; + + // aapt resource value: 0x7f01002c + public const int multiChoiceItemLayout = 2130772012; + + // aapt resource value: 0x7f0100f6 + public const int navigationContentDescription = 2130772214; + + // aapt resource value: 0x7f0100f5 + public const int navigationIcon = 2130772213; + + // aapt resource value: 0x7f01000d + public const int navigationMode = 2130771981; + + // aapt resource value: 0x7f0100c2 + public const int numericModifiers = 2130772162; + + // aapt resource value: 0x7f0100cd + public const int overlapAnchor = 2130772173; + + // aapt resource value: 0x7f0100cf + public const int paddingBottomNoButtons = 2130772175; + + // aapt resource value: 0x7f0100fb + public const int paddingEnd = 2130772219; + + // aapt resource value: 0x7f0100fa + public const int paddingStart = 2130772218; + + // aapt resource value: 0x7f0100d0 + public const int paddingTopNoTitle = 2130772176; + + // aapt resource value: 0x7f01008b + public const int panelBackground = 2130772107; + + // aapt resource value: 0x7f01008d + public const int panelMenuListTheme = 2130772109; + + // aapt resource value: 0x7f01008c + public const int panelMenuListWidth = 2130772108; + + // aapt resource value: 0x7f01014e + public const int passwordToggleContentDescription = 2130772302; + + // aapt resource value: 0x7f01014d + public const int passwordToggleDrawable = 2130772301; + + // aapt resource value: 0x7f01014c + public const int passwordToggleEnabled = 2130772300; + + // aapt resource value: 0x7f01014f + public const int passwordToggleTint = 2130772303; + + // aapt resource value: 0x7f010150 + public const int passwordToggleTintMode = 2130772304; + + // aapt resource value: 0x7f010078 + public const int popupMenuStyle = 2130772088; + + // aapt resource value: 0x7f010026 + public const int popupTheme = 2130772006; + + // aapt resource value: 0x7f010079 + public const int popupWindowStyle = 2130772089; + + // aapt resource value: 0x7f0100cb + public const int preserveIconSpacing = 2130772171; + + // aapt resource value: 0x7f010125 + public const int pressedTranslationZ = 2130772261; + + // aapt resource value: 0x7f01001c + public const int progressBarPadding = 2130771996; + + // aapt resource value: 0x7f01001a + public const int progressBarStyle = 2130771994; + + // aapt resource value: 0x7f0100dc + public const int queryBackground = 2130772188; + + // aapt resource value: 0x7f0100d3 + public const int queryHint = 2130772179; + + // aapt resource value: 0x7f0100a7 + public const int radioButtonStyle = 2130772135; + + // aapt resource value: 0x7f0100a8 + public const int ratingBarStyle = 2130772136; + + // aapt resource value: 0x7f0100a9 + public const int ratingBarStyleIndicator = 2130772137; + + // aapt resource value: 0x7f0100aa + public const int ratingBarStyleSmall = 2130772138; + + // aapt resource value: 0x7f010002 + public const int reverseLayout = 2130771970; + + // aapt resource value: 0x7f010123 + public const int rippleColor = 2130772259; + + // aapt resource value: 0x7f010112 + public const int scrimAnimationDuration = 2130772242; + + // aapt resource value: 0x7f010111 + public const int scrimVisibleHeightTrigger = 2130772241; + + // aapt resource value: 0x7f0100d8 + public const int searchHintIcon = 2130772184; + + // aapt resource value: 0x7f0100d7 + public const int searchIcon = 2130772183; + + // aapt resource value: 0x7f010080 + public const int searchViewStyle = 2130772096; + + // aapt resource value: 0x7f0100ab + public const int seekBarStyle = 2130772139; + + // aapt resource value: 0x7f010070 + public const int selectableItemBackground = 2130772080; + + // aapt resource value: 0x7f010071 + public const int selectableItemBackgroundBorderless = 2130772081; + + // aapt resource value: 0x7f0100c3 + public const int showAsAction = 2130772163; + + // aapt resource value: 0x7f0100bf + public const int showDividers = 2130772159; + + // aapt resource value: 0x7f0100e8 + public const int showText = 2130772200; + + // aapt resource value: 0x7f01002f + public const int showTitle = 2130772015; + + // aapt resource value: 0x7f01002d + public const int singleChoiceItemLayout = 2130772013; + + // aapt resource value: 0x7f010001 + public const int spanCount = 2130771969; + + // aapt resource value: 0x7f0100b7 + public const int spinBars = 2130772151; + + // aapt resource value: 0x7f01006b + public const int spinnerDropDownItemStyle = 2130772075; + + // aapt resource value: 0x7f0100ac + public const int spinnerStyle = 2130772140; + + // aapt resource value: 0x7f0100e7 + public const int splitTrack = 2130772199; + + // aapt resource value: 0x7f010030 + public const int srcCompat = 2130772016; + + // aapt resource value: 0x7f010003 + public const int stackFromEnd = 2130771971; + + // aapt resource value: 0x7f0100ce + public const int state_above_anchor = 2130772174; + + // aapt resource value: 0x7f010100 + public const int state_collapsed = 2130772224; + + // aapt resource value: 0x7f010101 + public const int state_collapsible = 2130772225; + + // aapt resource value: 0x7f010119 + public const int statusBarBackground = 2130772249; + + // aapt resource value: 0x7f01010f + public const int statusBarScrim = 2130772239; + + // aapt resource value: 0x7f0100cc + public const int subMenuArrow = 2130772172; + + // aapt resource value: 0x7f0100dd + public const int submitBackground = 2130772189; + + // aapt resource value: 0x7f01000f + public const int subtitle = 2130771983; + + // aapt resource value: 0x7f0100ea + public const int subtitleTextAppearance = 2130772202; + + // aapt resource value: 0x7f0100f9 + public const int subtitleTextColor = 2130772217; + + // aapt resource value: 0x7f010011 + public const int subtitleTextStyle = 2130771985; + + // aapt resource value: 0x7f0100db + public const int suggestionRowLayout = 2130772187; + + // aapt resource value: 0x7f0100e5 + public const int switchMinWidth = 2130772197; + + // aapt resource value: 0x7f0100e6 + public const int switchPadding = 2130772198; + + // aapt resource value: 0x7f0100ad + public const int switchStyle = 2130772141; + + // aapt resource value: 0x7f0100e4 + public const int switchTextAppearance = 2130772196; + + // aapt resource value: 0x7f010136 + public const int tabBackground = 2130772278; + + // aapt resource value: 0x7f010135 + public const int tabContentStart = 2130772277; + + // aapt resource value: 0x7f010138 + public const int tabGravity = 2130772280; + + // aapt resource value: 0x7f010133 + public const int tabIndicatorColor = 2130772275; + + // aapt resource value: 0x7f010134 + public const int tabIndicatorHeight = 2130772276; + + // aapt resource value: 0x7f01013a + public const int tabMaxWidth = 2130772282; + + // aapt resource value: 0x7f010139 + public const int tabMinWidth = 2130772281; + + // aapt resource value: 0x7f010137 + public const int tabMode = 2130772279; + + // aapt resource value: 0x7f010142 + public const int tabPadding = 2130772290; + + // aapt resource value: 0x7f010141 + public const int tabPaddingBottom = 2130772289; + + // aapt resource value: 0x7f010140 + public const int tabPaddingEnd = 2130772288; + + // aapt resource value: 0x7f01013e + public const int tabPaddingStart = 2130772286; + + // aapt resource value: 0x7f01013f + public const int tabPaddingTop = 2130772287; + + // aapt resource value: 0x7f01013d + public const int tabSelectedTextColor = 2130772285; + + // aapt resource value: 0x7f01013b + public const int tabTextAppearance = 2130772283; + + // aapt resource value: 0x7f01013c + public const int tabTextColor = 2130772284; + + // aapt resource value: 0x7f010036 + public const int textAllCaps = 2130772022; + + // aapt resource value: 0x7f010063 + public const int textAppearanceLargePopupMenu = 2130772067; + + // aapt resource value: 0x7f010088 + public const int textAppearanceListItem = 2130772104; + + // aapt resource value: 0x7f010089 + public const int textAppearanceListItemSecondary = 2130772105; + + // aapt resource value: 0x7f01008a + public const int textAppearanceListItemSmall = 2130772106; + + // aapt resource value: 0x7f010065 + public const int textAppearancePopupMenuHeader = 2130772069; + + // aapt resource value: 0x7f01007e + public const int textAppearanceSearchResultSubtitle = 2130772094; + + // aapt resource value: 0x7f01007d + public const int textAppearanceSearchResultTitle = 2130772093; + + // aapt resource value: 0x7f010064 + public const int textAppearanceSmallPopupMenu = 2130772068; + + // aapt resource value: 0x7f01009d + public const int textColorAlertDialogListItem = 2130772125; + + // aapt resource value: 0x7f010122 + public const int textColorError = 2130772258; + + // aapt resource value: 0x7f01007f + public const int textColorSearchUrl = 2130772095; + + // aapt resource value: 0x7f0100fc + public const int theme = 2130772220; + + // aapt resource value: 0x7f0100bd + public const int thickness = 2130772157; + + // aapt resource value: 0x7f0100e3 + public const int thumbTextPadding = 2130772195; + + // aapt resource value: 0x7f0100de + public const int thumbTint = 2130772190; + + // aapt resource value: 0x7f0100df + public const int thumbTintMode = 2130772191; + + // aapt resource value: 0x7f010033 + public const int tickMark = 2130772019; + + // aapt resource value: 0x7f010034 + public const int tickMarkTint = 2130772020; + + // aapt resource value: 0x7f010035 + public const int tickMarkTintMode = 2130772021; + + // aapt resource value: 0x7f010031 + public const int tint = 2130772017; + + // aapt resource value: 0x7f010032 + public const int tintMode = 2130772018; + + // aapt resource value: 0x7f01000c + public const int title = 2130771980; + + // aapt resource value: 0x7f010115 + public const int titleEnabled = 2130772245; + + // aapt resource value: 0x7f0100eb + public const int titleMargin = 2130772203; + + // aapt resource value: 0x7f0100ef + public const int titleMarginBottom = 2130772207; + + // aapt resource value: 0x7f0100ed + public const int titleMarginEnd = 2130772205; + + // aapt resource value: 0x7f0100ec + public const int titleMarginStart = 2130772204; + + // aapt resource value: 0x7f0100ee + public const int titleMarginTop = 2130772206; + + // aapt resource value: 0x7f0100f0 + public const int titleMargins = 2130772208; + + // aapt resource value: 0x7f0100e9 + public const int titleTextAppearance = 2130772201; + + // aapt resource value: 0x7f0100f8 + public const int titleTextColor = 2130772216; + + // aapt resource value: 0x7f010010 + public const int titleTextStyle = 2130771984; + + // aapt resource value: 0x7f010110 + public const int toolbarId = 2130772240; + + // aapt resource value: 0x7f010077 + public const int toolbarNavigationButtonStyle = 2130772087; + + // aapt resource value: 0x7f010076 + public const int toolbarStyle = 2130772086; + + // aapt resource value: 0x7f0100b0 + public const int tooltipForegroundColor = 2130772144; + + // aapt resource value: 0x7f0100af + public const int tooltipFrameBackground = 2130772143; + + // aapt resource value: 0x7f0100c8 + public const int tooltipText = 2130772168; + + // aapt resource value: 0x7f0100e0 + public const int track = 2130772192; + + // aapt resource value: 0x7f0100e1 + public const int trackTint = 2130772193; + + // aapt resource value: 0x7f0100e2 + public const int trackTintMode = 2130772194; + + // aapt resource value: 0x7f010127 + public const int useCompatPadding = 2130772263; + + // aapt resource value: 0x7f0100d9 + public const int voiceIcon = 2130772185; + + // aapt resource value: 0x7f01003d + public const int windowActionBar = 2130772029; + + // aapt resource value: 0x7f01003f + public const int windowActionBarOverlay = 2130772031; + + // aapt resource value: 0x7f010040 + public const int windowActionModeOverlay = 2130772032; + + // aapt resource value: 0x7f010044 + public const int windowFixedHeightMajor = 2130772036; + + // aapt resource value: 0x7f010042 + public const int windowFixedHeightMinor = 2130772034; + + // aapt resource value: 0x7f010041 + public const int windowFixedWidthMajor = 2130772033; + + // aapt resource value: 0x7f010043 + public const int windowFixedWidthMinor = 2130772035; + + // aapt resource value: 0x7f010045 + public const int windowMinWidthMajor = 2130772037; + + // aapt resource value: 0x7f010046 + public const int windowMinWidthMinor = 2130772038; + + // aapt resource value: 0x7f01003e + public const int windowNoTitle = 2130772030; + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class Boolean + { + + // aapt resource value: 0x7f0b0000 + public const int abc_action_bar_embed_tabs = 2131427328; + + // aapt resource value: 0x7f0b0001 + public const int abc_allow_stacked_button_bar = 2131427329; + + // aapt resource value: 0x7f0b0002 + public const int abc_config_actionMenuItemAllCaps = 2131427330; + + // aapt resource value: 0x7f0b0003 + public const int abc_config_closeDialogWhenTouchOutside = 2131427331; + + // aapt resource value: 0x7f0b0004 + public const int abc_config_showMenuShortcutsWhenKeyboardPresent = 2131427332; + + static Boolean() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Boolean() + { + } + } + + public partial class Color + { + + // aapt resource value: 0x7f0c004b + public const int abc_background_cache_hint_selector_material_dark = 2131492939; + + // aapt resource value: 0x7f0c004c + public const int abc_background_cache_hint_selector_material_light = 2131492940; + + // aapt resource value: 0x7f0c004d + public const int abc_btn_colored_borderless_text_material = 2131492941; + + // aapt resource value: 0x7f0c004e + public const int abc_btn_colored_text_material = 2131492942; + + // aapt resource value: 0x7f0c004f + public const int abc_color_highlight_material = 2131492943; + + // aapt resource value: 0x7f0c0050 + public const int abc_hint_foreground_material_dark = 2131492944; + + // aapt resource value: 0x7f0c0051 + public const int abc_hint_foreground_material_light = 2131492945; + + // aapt resource value: 0x7f0c0000 + public const int abc_input_method_navigation_guard = 2131492864; + + // aapt resource value: 0x7f0c0052 + public const int abc_primary_text_disable_only_material_dark = 2131492946; + + // aapt resource value: 0x7f0c0053 + public const int abc_primary_text_disable_only_material_light = 2131492947; + + // aapt resource value: 0x7f0c0054 + public const int abc_primary_text_material_dark = 2131492948; + + // aapt resource value: 0x7f0c0055 + public const int abc_primary_text_material_light = 2131492949; + + // aapt resource value: 0x7f0c0056 + public const int abc_search_url_text = 2131492950; + + // aapt resource value: 0x7f0c0001 + public const int abc_search_url_text_normal = 2131492865; + + // aapt resource value: 0x7f0c0002 + public const int abc_search_url_text_pressed = 2131492866; + + // aapt resource value: 0x7f0c0003 + public const int abc_search_url_text_selected = 2131492867; + + // aapt resource value: 0x7f0c0057 + public const int abc_secondary_text_material_dark = 2131492951; + + // aapt resource value: 0x7f0c0058 + public const int abc_secondary_text_material_light = 2131492952; + + // aapt resource value: 0x7f0c0059 + public const int abc_tint_btn_checkable = 2131492953; + + // aapt resource value: 0x7f0c005a + public const int abc_tint_default = 2131492954; + + // aapt resource value: 0x7f0c005b + public const int abc_tint_edittext = 2131492955; + + // aapt resource value: 0x7f0c005c + public const int abc_tint_seek_thumb = 2131492956; + + // aapt resource value: 0x7f0c005d + public const int abc_tint_spinner = 2131492957; + + // aapt resource value: 0x7f0c005e + public const int abc_tint_switch_track = 2131492958; + + // aapt resource value: 0x7f0c0004 + public const int accent_material_dark = 2131492868; + + // aapt resource value: 0x7f0c0005 + public const int accent_material_light = 2131492869; + + // aapt resource value: 0x7f0c0006 + public const int background_floating_material_dark = 2131492870; + + // aapt resource value: 0x7f0c0007 + public const int background_floating_material_light = 2131492871; + + // aapt resource value: 0x7f0c0008 + public const int background_material_dark = 2131492872; + + // aapt resource value: 0x7f0c0009 + public const int background_material_light = 2131492873; + + // aapt resource value: 0x7f0c000a + public const int bright_foreground_disabled_material_dark = 2131492874; + + // aapt resource value: 0x7f0c000b + public const int bright_foreground_disabled_material_light = 2131492875; + + // aapt resource value: 0x7f0c000c + public const int bright_foreground_inverse_material_dark = 2131492876; + + // aapt resource value: 0x7f0c000d + public const int bright_foreground_inverse_material_light = 2131492877; + + // aapt resource value: 0x7f0c000e + public const int bright_foreground_material_dark = 2131492878; + + // aapt resource value: 0x7f0c000f + public const int bright_foreground_material_light = 2131492879; + + // aapt resource value: 0x7f0c0010 + public const int button_material_dark = 2131492880; + + // aapt resource value: 0x7f0c0011 + public const int button_material_light = 2131492881; + + // aapt resource value: 0x7f0c0049 + public const int colorAccent = 2131492937; + + // aapt resource value: 0x7f0c0047 + public const int colorPrimary = 2131492935; + + // aapt resource value: 0x7f0c0048 + public const int colorPrimaryDark = 2131492936; + + // aapt resource value: 0x7f0c003c + public const int design_bottom_navigation_shadow_color = 2131492924; + + // aapt resource value: 0x7f0c005f + public const int design_error = 2131492959; + + // aapt resource value: 0x7f0c003d + public const int design_fab_shadow_end_color = 2131492925; + + // aapt resource value: 0x7f0c003e + public const int design_fab_shadow_mid_color = 2131492926; + + // aapt resource value: 0x7f0c003f + public const int design_fab_shadow_start_color = 2131492927; + + // aapt resource value: 0x7f0c0040 + public const int design_fab_stroke_end_inner_color = 2131492928; + + // aapt resource value: 0x7f0c0041 + public const int design_fab_stroke_end_outer_color = 2131492929; + + // aapt resource value: 0x7f0c0042 + public const int design_fab_stroke_top_inner_color = 2131492930; + + // aapt resource value: 0x7f0c0043 + public const int design_fab_stroke_top_outer_color = 2131492931; + + // aapt resource value: 0x7f0c0044 + public const int design_snackbar_background_color = 2131492932; + + // aapt resource value: 0x7f0c0060 + public const int design_tint_password_toggle = 2131492960; + + // aapt resource value: 0x7f0c0012 + public const int dim_foreground_disabled_material_dark = 2131492882; + + // aapt resource value: 0x7f0c0013 + public const int dim_foreground_disabled_material_light = 2131492883; + + // aapt resource value: 0x7f0c0014 + public const int dim_foreground_material_dark = 2131492884; + + // aapt resource value: 0x7f0c0015 + public const int dim_foreground_material_light = 2131492885; + + // aapt resource value: 0x7f0c0016 + public const int error_color_material = 2131492886; + + // aapt resource value: 0x7f0c0017 + public const int foreground_material_dark = 2131492887; + + // aapt resource value: 0x7f0c0018 + public const int foreground_material_light = 2131492888; + + // aapt resource value: 0x7f0c0019 + public const int highlighted_text_material_dark = 2131492889; + + // aapt resource value: 0x7f0c001a + public const int highlighted_text_material_light = 2131492890; + + // aapt resource value: 0x7f0c004a + public const int ic_launcher_background = 2131492938; + + // aapt resource value: 0x7f0c001b + public const int material_blue_grey_800 = 2131492891; + + // aapt resource value: 0x7f0c001c + public const int material_blue_grey_900 = 2131492892; + + // aapt resource value: 0x7f0c001d + public const int material_blue_grey_950 = 2131492893; + + // aapt resource value: 0x7f0c001e + public const int material_deep_teal_200 = 2131492894; + + // aapt resource value: 0x7f0c001f + public const int material_deep_teal_500 = 2131492895; + + // aapt resource value: 0x7f0c0020 + public const int material_grey_100 = 2131492896; + + // aapt resource value: 0x7f0c0021 + public const int material_grey_300 = 2131492897; + + // aapt resource value: 0x7f0c0022 + public const int material_grey_50 = 2131492898; + + // aapt resource value: 0x7f0c0023 + public const int material_grey_600 = 2131492899; + + // aapt resource value: 0x7f0c0024 + public const int material_grey_800 = 2131492900; + + // aapt resource value: 0x7f0c0025 + public const int material_grey_850 = 2131492901; + + // aapt resource value: 0x7f0c0026 + public const int material_grey_900 = 2131492902; + + // aapt resource value: 0x7f0c0045 + public const int notification_action_color_filter = 2131492933; + + // aapt resource value: 0x7f0c0046 + public const int notification_icon_bg_color = 2131492934; + + // aapt resource value: 0x7f0c003b + public const int notification_material_background_media_default_color = 2131492923; + + // aapt resource value: 0x7f0c0027 + public const int primary_dark_material_dark = 2131492903; + + // aapt resource value: 0x7f0c0028 + public const int primary_dark_material_light = 2131492904; + + // aapt resource value: 0x7f0c0029 + public const int primary_material_dark = 2131492905; + + // aapt resource value: 0x7f0c002a + public const int primary_material_light = 2131492906; + + // aapt resource value: 0x7f0c002b + public const int primary_text_default_material_dark = 2131492907; + + // aapt resource value: 0x7f0c002c + public const int primary_text_default_material_light = 2131492908; + + // aapt resource value: 0x7f0c002d + public const int primary_text_disabled_material_dark = 2131492909; + + // aapt resource value: 0x7f0c002e + public const int primary_text_disabled_material_light = 2131492910; + + // aapt resource value: 0x7f0c002f + public const int ripple_material_dark = 2131492911; + + // aapt resource value: 0x7f0c0030 + public const int ripple_material_light = 2131492912; + + // aapt resource value: 0x7f0c0031 + public const int secondary_text_default_material_dark = 2131492913; + + // aapt resource value: 0x7f0c0032 + public const int secondary_text_default_material_light = 2131492914; + + // aapt resource value: 0x7f0c0033 + public const int secondary_text_disabled_material_dark = 2131492915; + + // aapt resource value: 0x7f0c0034 + public const int secondary_text_disabled_material_light = 2131492916; + + // aapt resource value: 0x7f0c0035 + public const int switch_thumb_disabled_material_dark = 2131492917; + + // aapt resource value: 0x7f0c0036 + public const int switch_thumb_disabled_material_light = 2131492918; + + // aapt resource value: 0x7f0c0061 + public const int switch_thumb_material_dark = 2131492961; + + // aapt resource value: 0x7f0c0062 + public const int switch_thumb_material_light = 2131492962; + + // aapt resource value: 0x7f0c0037 + public const int switch_thumb_normal_material_dark = 2131492919; + + // aapt resource value: 0x7f0c0038 + public const int switch_thumb_normal_material_light = 2131492920; + + // aapt resource value: 0x7f0c0039 + public const int tooltip_background_dark = 2131492921; + + // aapt resource value: 0x7f0c003a + public const int tooltip_background_light = 2131492922; + + static Color() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Color() + { + } + } + + public partial class Dimension + { + + // aapt resource value: 0x7f070012 + public const int abc_action_bar_content_inset_material = 2131165202; + + // aapt resource value: 0x7f070013 + public const int abc_action_bar_content_inset_with_nav = 2131165203; + + // aapt resource value: 0x7f070007 + public const int abc_action_bar_default_height_material = 2131165191; + + // aapt resource value: 0x7f070014 + public const int abc_action_bar_default_padding_end_material = 2131165204; + + // aapt resource value: 0x7f070015 + public const int abc_action_bar_default_padding_start_material = 2131165205; + + // aapt resource value: 0x7f070017 + public const int abc_action_bar_elevation_material = 2131165207; + + // aapt resource value: 0x7f070018 + public const int abc_action_bar_icon_vertical_padding_material = 2131165208; + + // aapt resource value: 0x7f070019 + public const int abc_action_bar_overflow_padding_end_material = 2131165209; + + // aapt resource value: 0x7f07001a + public const int abc_action_bar_overflow_padding_start_material = 2131165210; + + // aapt resource value: 0x7f070008 + public const int abc_action_bar_progress_bar_size = 2131165192; + + // aapt resource value: 0x7f07001b + public const int abc_action_bar_stacked_max_height = 2131165211; + + // aapt resource value: 0x7f07001c + public const int abc_action_bar_stacked_tab_max_width = 2131165212; + + // aapt resource value: 0x7f07001d + public const int abc_action_bar_subtitle_bottom_margin_material = 2131165213; + + // aapt resource value: 0x7f07001e + public const int abc_action_bar_subtitle_top_margin_material = 2131165214; + + // aapt resource value: 0x7f07001f + public const int abc_action_button_min_height_material = 2131165215; + + // aapt resource value: 0x7f070020 + public const int abc_action_button_min_width_material = 2131165216; + + // aapt resource value: 0x7f070021 + public const int abc_action_button_min_width_overflow_material = 2131165217; + + // aapt resource value: 0x7f070006 + public const int abc_alert_dialog_button_bar_height = 2131165190; + + // aapt resource value: 0x7f070022 + public const int abc_button_inset_horizontal_material = 2131165218; + + // aapt resource value: 0x7f070023 + public const int abc_button_inset_vertical_material = 2131165219; + + // aapt resource value: 0x7f070024 + public const int abc_button_padding_horizontal_material = 2131165220; + + // aapt resource value: 0x7f070025 + public const int abc_button_padding_vertical_material = 2131165221; + + // aapt resource value: 0x7f070026 + public const int abc_cascading_menus_min_smallest_width = 2131165222; + + // aapt resource value: 0x7f07000b + public const int abc_config_prefDialogWidth = 2131165195; + + // aapt resource value: 0x7f070027 + public const int abc_control_corner_material = 2131165223; + + // aapt resource value: 0x7f070028 + public const int abc_control_inset_material = 2131165224; + + // aapt resource value: 0x7f070029 + public const int abc_control_padding_material = 2131165225; + + // aapt resource value: 0x7f07000c + public const int abc_dialog_fixed_height_major = 2131165196; + + // aapt resource value: 0x7f07000d + public const int abc_dialog_fixed_height_minor = 2131165197; + + // aapt resource value: 0x7f07000e + public const int abc_dialog_fixed_width_major = 2131165198; + + // aapt resource value: 0x7f07000f + public const int abc_dialog_fixed_width_minor = 2131165199; + + // aapt resource value: 0x7f07002a + public const int abc_dialog_list_padding_bottom_no_buttons = 2131165226; + + // aapt resource value: 0x7f07002b + public const int abc_dialog_list_padding_top_no_title = 2131165227; + + // aapt resource value: 0x7f070010 + public const int abc_dialog_min_width_major = 2131165200; + + // aapt resource value: 0x7f070011 + public const int abc_dialog_min_width_minor = 2131165201; + + // aapt resource value: 0x7f07002c + public const int abc_dialog_padding_material = 2131165228; + + // aapt resource value: 0x7f07002d + public const int abc_dialog_padding_top_material = 2131165229; + + // aapt resource value: 0x7f07002e + public const int abc_dialog_title_divider_material = 2131165230; + + // aapt resource value: 0x7f07002f + public const int abc_disabled_alpha_material_dark = 2131165231; + + // aapt resource value: 0x7f070030 + public const int abc_disabled_alpha_material_light = 2131165232; + + // aapt resource value: 0x7f070031 + public const int abc_dropdownitem_icon_width = 2131165233; + + // aapt resource value: 0x7f070032 + public const int abc_dropdownitem_text_padding_left = 2131165234; + + // aapt resource value: 0x7f070033 + public const int abc_dropdownitem_text_padding_right = 2131165235; + + // aapt resource value: 0x7f070034 + public const int abc_edit_text_inset_bottom_material = 2131165236; + + // aapt resource value: 0x7f070035 + public const int abc_edit_text_inset_horizontal_material = 2131165237; + + // aapt resource value: 0x7f070036 + public const int abc_edit_text_inset_top_material = 2131165238; + + // aapt resource value: 0x7f070037 + public const int abc_floating_window_z = 2131165239; + + // aapt resource value: 0x7f070038 + public const int abc_list_item_padding_horizontal_material = 2131165240; + + // aapt resource value: 0x7f070039 + public const int abc_panel_menu_list_width = 2131165241; + + // aapt resource value: 0x7f07003a + public const int abc_progress_bar_height_material = 2131165242; + + // aapt resource value: 0x7f07003b + public const int abc_search_view_preferred_height = 2131165243; + + // aapt resource value: 0x7f07003c + public const int abc_search_view_preferred_width = 2131165244; + + // aapt resource value: 0x7f07003d + public const int abc_seekbar_track_background_height_material = 2131165245; + + // aapt resource value: 0x7f07003e + public const int abc_seekbar_track_progress_height_material = 2131165246; + + // aapt resource value: 0x7f07003f + public const int abc_select_dialog_padding_start_material = 2131165247; + + // aapt resource value: 0x7f070016 + public const int abc_switch_padding = 2131165206; + + // aapt resource value: 0x7f070040 + public const int abc_text_size_body_1_material = 2131165248; + + // aapt resource value: 0x7f070041 + public const int abc_text_size_body_2_material = 2131165249; + + // aapt resource value: 0x7f070042 + public const int abc_text_size_button_material = 2131165250; + + // aapt resource value: 0x7f070043 + public const int abc_text_size_caption_material = 2131165251; + + // aapt resource value: 0x7f070044 + public const int abc_text_size_display_1_material = 2131165252; + + // aapt resource value: 0x7f070045 + public const int abc_text_size_display_2_material = 2131165253; + + // aapt resource value: 0x7f070046 + public const int abc_text_size_display_3_material = 2131165254; + + // aapt resource value: 0x7f070047 + public const int abc_text_size_display_4_material = 2131165255; + + // aapt resource value: 0x7f070048 + public const int abc_text_size_headline_material = 2131165256; + + // aapt resource value: 0x7f070049 + public const int abc_text_size_large_material = 2131165257; + + // aapt resource value: 0x7f07004a + public const int abc_text_size_medium_material = 2131165258; + + // aapt resource value: 0x7f07004b + public const int abc_text_size_menu_header_material = 2131165259; + + // aapt resource value: 0x7f07004c + public const int abc_text_size_menu_material = 2131165260; + + // aapt resource value: 0x7f07004d + public const int abc_text_size_small_material = 2131165261; + + // aapt resource value: 0x7f07004e + public const int abc_text_size_subhead_material = 2131165262; + + // aapt resource value: 0x7f070009 + public const int abc_text_size_subtitle_material_toolbar = 2131165193; + + // aapt resource value: 0x7f07004f + public const int abc_text_size_title_material = 2131165263; + + // aapt resource value: 0x7f07000a + public const int abc_text_size_title_material_toolbar = 2131165194; + + // aapt resource value: 0x7f07008b + public const int compat_button_inset_horizontal_material = 2131165323; + + // aapt resource value: 0x7f07008c + public const int compat_button_inset_vertical_material = 2131165324; + + // aapt resource value: 0x7f07008d + public const int compat_button_padding_horizontal_material = 2131165325; + + // aapt resource value: 0x7f07008e + public const int compat_button_padding_vertical_material = 2131165326; + + // aapt resource value: 0x7f07008f + public const int compat_control_corner_material = 2131165327; + + // aapt resource value: 0x7f070069 + public const int design_appbar_elevation = 2131165289; + + // aapt resource value: 0x7f07006a + public const int design_bottom_navigation_active_item_max_width = 2131165290; + + // aapt resource value: 0x7f07006b + public const int design_bottom_navigation_active_text_size = 2131165291; + + // aapt resource value: 0x7f07006c + public const int design_bottom_navigation_elevation = 2131165292; + + // aapt resource value: 0x7f07006d + public const int design_bottom_navigation_height = 2131165293; + + // aapt resource value: 0x7f07006e + public const int design_bottom_navigation_item_max_width = 2131165294; + + // aapt resource value: 0x7f07006f + public const int design_bottom_navigation_item_min_width = 2131165295; + + // aapt resource value: 0x7f070070 + public const int design_bottom_navigation_margin = 2131165296; + + // aapt resource value: 0x7f070071 + public const int design_bottom_navigation_shadow_height = 2131165297; + + // aapt resource value: 0x7f070072 + public const int design_bottom_navigation_text_size = 2131165298; + + // aapt resource value: 0x7f070073 + public const int design_bottom_sheet_modal_elevation = 2131165299; + + // aapt resource value: 0x7f070074 + public const int design_bottom_sheet_peek_height_min = 2131165300; + + // aapt resource value: 0x7f070075 + public const int design_fab_border_width = 2131165301; + + // aapt resource value: 0x7f070076 + public const int design_fab_elevation = 2131165302; + + // aapt resource value: 0x7f070077 + public const int design_fab_image_size = 2131165303; + + // aapt resource value: 0x7f070078 + public const int design_fab_size_mini = 2131165304; + + // aapt resource value: 0x7f070079 + public const int design_fab_size_normal = 2131165305; + + // aapt resource value: 0x7f07007a + public const int design_fab_translation_z_pressed = 2131165306; + + // aapt resource value: 0x7f07007b + public const int design_navigation_elevation = 2131165307; + + // aapt resource value: 0x7f07007c + public const int design_navigation_icon_padding = 2131165308; + + // aapt resource value: 0x7f07007d + public const int design_navigation_icon_size = 2131165309; + + // aapt resource value: 0x7f070061 + public const int design_navigation_max_width = 2131165281; + + // aapt resource value: 0x7f07007e + public const int design_navigation_padding_bottom = 2131165310; + + // aapt resource value: 0x7f07007f + public const int design_navigation_separator_vertical_padding = 2131165311; + + // aapt resource value: 0x7f070062 + public const int design_snackbar_action_inline_max_width = 2131165282; + + // aapt resource value: 0x7f070063 + public const int design_snackbar_background_corner_radius = 2131165283; + + // aapt resource value: 0x7f070080 + public const int design_snackbar_elevation = 2131165312; + + // aapt resource value: 0x7f070064 + public const int design_snackbar_extra_spacing_horizontal = 2131165284; + + // aapt resource value: 0x7f070065 + public const int design_snackbar_max_width = 2131165285; + + // aapt resource value: 0x7f070066 + public const int design_snackbar_min_width = 2131165286; + + // aapt resource value: 0x7f070081 + public const int design_snackbar_padding_horizontal = 2131165313; + + // aapt resource value: 0x7f070082 + public const int design_snackbar_padding_vertical = 2131165314; + + // aapt resource value: 0x7f070067 + public const int design_snackbar_padding_vertical_2lines = 2131165287; + + // aapt resource value: 0x7f070083 + public const int design_snackbar_text_size = 2131165315; + + // aapt resource value: 0x7f070084 + public const int design_tab_max_width = 2131165316; + + // aapt resource value: 0x7f070068 + public const int design_tab_scrollable_min_width = 2131165288; + + // aapt resource value: 0x7f070085 + public const int design_tab_text_size = 2131165317; + + // aapt resource value: 0x7f070086 + public const int design_tab_text_size_2line = 2131165318; + + // aapt resource value: 0x7f070050 + public const int disabled_alpha_material_dark = 2131165264; + + // aapt resource value: 0x7f070051 + public const int disabled_alpha_material_light = 2131165265; + + // aapt resource value: 0x7f070000 + public const int fastscroll_default_thickness = 2131165184; + + // aapt resource value: 0x7f070001 + public const int fastscroll_margin = 2131165185; + + // aapt resource value: 0x7f070002 + public const int fastscroll_minimum_range = 2131165186; + + // aapt resource value: 0x7f070052 + public const int highlight_alpha_material_colored = 2131165266; + + // aapt resource value: 0x7f070053 + public const int highlight_alpha_material_dark = 2131165267; + + // aapt resource value: 0x7f070054 + public const int highlight_alpha_material_light = 2131165268; + + // aapt resource value: 0x7f070055 + public const int hint_alpha_material_dark = 2131165269; + + // aapt resource value: 0x7f070056 + public const int hint_alpha_material_light = 2131165270; + + // aapt resource value: 0x7f070057 + public const int hint_pressed_alpha_material_dark = 2131165271; + + // aapt resource value: 0x7f070058 + public const int hint_pressed_alpha_material_light = 2131165272; + + // aapt resource value: 0x7f070003 + public const int item_touch_helper_max_drag_scroll_per_frame = 2131165187; + + // aapt resource value: 0x7f070004 + public const int item_touch_helper_swipe_escape_max_velocity = 2131165188; + + // aapt resource value: 0x7f070005 + public const int item_touch_helper_swipe_escape_velocity = 2131165189; + + // aapt resource value: 0x7f070090 + public const int notification_action_icon_size = 2131165328; + + // aapt resource value: 0x7f070091 + public const int notification_action_text_size = 2131165329; + + // aapt resource value: 0x7f070092 + public const int notification_big_circle_margin = 2131165330; + + // aapt resource value: 0x7f070088 + public const int notification_content_margin_start = 2131165320; + + // aapt resource value: 0x7f070093 + public const int notification_large_icon_height = 2131165331; + + // aapt resource value: 0x7f070094 + public const int notification_large_icon_width = 2131165332; + + // aapt resource value: 0x7f070089 + public const int notification_main_column_padding_top = 2131165321; + + // aapt resource value: 0x7f07008a + public const int notification_media_narrow_margin = 2131165322; + + // aapt resource value: 0x7f070095 + public const int notification_right_icon_size = 2131165333; + + // aapt resource value: 0x7f070087 + public const int notification_right_side_padding_top = 2131165319; + + // aapt resource value: 0x7f070096 + public const int notification_small_icon_background_padding = 2131165334; + + // aapt resource value: 0x7f070097 + public const int notification_small_icon_size_as_large = 2131165335; + + // aapt resource value: 0x7f070098 + public const int notification_subtext_size = 2131165336; + + // aapt resource value: 0x7f070099 + public const int notification_top_pad = 2131165337; + + // aapt resource value: 0x7f07009a + public const int notification_top_pad_large_text = 2131165338; + + // aapt resource value: 0x7f070059 + public const int tooltip_corner_radius = 2131165273; + + // aapt resource value: 0x7f07005a + public const int tooltip_horizontal_padding = 2131165274; + + // aapt resource value: 0x7f07005b + public const int tooltip_margin = 2131165275; + + // aapt resource value: 0x7f07005c + public const int tooltip_precise_anchor_extra_offset = 2131165276; + + // aapt resource value: 0x7f07005d + public const int tooltip_precise_anchor_threshold = 2131165277; + + // aapt resource value: 0x7f07005e + public const int tooltip_vertical_padding = 2131165278; + + // aapt resource value: 0x7f07005f + public const int tooltip_y_offset_non_touch = 2131165279; + + // aapt resource value: 0x7f070060 + public const int tooltip_y_offset_touch = 2131165280; + + static Dimension() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Dimension() + { + } + } + + public partial class Drawable + { + + // aapt resource value: 0x7f020000 + public const int abc_ab_share_pack_mtrl_alpha = 2130837504; + + // aapt resource value: 0x7f020001 + public const int abc_action_bar_item_background_material = 2130837505; + + // aapt resource value: 0x7f020002 + public const int abc_btn_borderless_material = 2130837506; + + // aapt resource value: 0x7f020003 + public const int abc_btn_check_material = 2130837507; + + // aapt resource value: 0x7f020004 + public const int abc_btn_check_to_on_mtrl_000 = 2130837508; + + // aapt resource value: 0x7f020005 + public const int abc_btn_check_to_on_mtrl_015 = 2130837509; + + // aapt resource value: 0x7f020006 + public const int abc_btn_colored_material = 2130837510; + + // aapt resource value: 0x7f020007 + public const int abc_btn_default_mtrl_shape = 2130837511; + + // aapt resource value: 0x7f020008 + public const int abc_btn_radio_material = 2130837512; + + // aapt resource value: 0x7f020009 + public const int abc_btn_radio_to_on_mtrl_000 = 2130837513; + + // aapt resource value: 0x7f02000a + public const int abc_btn_radio_to_on_mtrl_015 = 2130837514; + + // aapt resource value: 0x7f02000b + public const int abc_btn_switch_to_on_mtrl_00001 = 2130837515; + + // aapt resource value: 0x7f02000c + public const int abc_btn_switch_to_on_mtrl_00012 = 2130837516; + + // aapt resource value: 0x7f02000d + public const int abc_cab_background_internal_bg = 2130837517; + + // aapt resource value: 0x7f02000e + public const int abc_cab_background_top_material = 2130837518; + + // aapt resource value: 0x7f02000f + public const int abc_cab_background_top_mtrl_alpha = 2130837519; + + // aapt resource value: 0x7f020010 + public const int abc_control_background_material = 2130837520; + + // aapt resource value: 0x7f020011 + public const int abc_dialog_material_background = 2130837521; + + // aapt resource value: 0x7f020012 + public const int abc_edit_text_material = 2130837522; + + // aapt resource value: 0x7f020013 + public const int abc_ic_ab_back_material = 2130837523; + + // aapt resource value: 0x7f020014 + public const int abc_ic_arrow_drop_right_black_24dp = 2130837524; + + // aapt resource value: 0x7f020015 + public const int abc_ic_clear_material = 2130837525; + + // aapt resource value: 0x7f020016 + public const int abc_ic_commit_search_api_mtrl_alpha = 2130837526; + + // aapt resource value: 0x7f020017 + public const int abc_ic_go_search_api_material = 2130837527; + + // aapt resource value: 0x7f020018 + public const int abc_ic_menu_copy_mtrl_am_alpha = 2130837528; + + // aapt resource value: 0x7f020019 + public const int abc_ic_menu_cut_mtrl_alpha = 2130837529; + + // aapt resource value: 0x7f02001a + public const int abc_ic_menu_overflow_material = 2130837530; + + // aapt resource value: 0x7f02001b + public const int abc_ic_menu_paste_mtrl_am_alpha = 2130837531; + + // aapt resource value: 0x7f02001c + public const int abc_ic_menu_selectall_mtrl_alpha = 2130837532; + + // aapt resource value: 0x7f02001d + public const int abc_ic_menu_share_mtrl_alpha = 2130837533; + + // aapt resource value: 0x7f02001e + public const int abc_ic_search_api_material = 2130837534; + + // aapt resource value: 0x7f02001f + public const int abc_ic_star_black_16dp = 2130837535; + + // aapt resource value: 0x7f020020 + public const int abc_ic_star_black_36dp = 2130837536; + + // aapt resource value: 0x7f020021 + public const int abc_ic_star_black_48dp = 2130837537; + + // aapt resource value: 0x7f020022 + public const int abc_ic_star_half_black_16dp = 2130837538; + + // aapt resource value: 0x7f020023 + public const int abc_ic_star_half_black_36dp = 2130837539; + + // aapt resource value: 0x7f020024 + public const int abc_ic_star_half_black_48dp = 2130837540; + + // aapt resource value: 0x7f020025 + public const int abc_ic_voice_search_api_material = 2130837541; + + // aapt resource value: 0x7f020026 + public const int abc_item_background_holo_dark = 2130837542; + + // aapt resource value: 0x7f020027 + public const int abc_item_background_holo_light = 2130837543; + + // aapt resource value: 0x7f020028 + public const int abc_list_divider_mtrl_alpha = 2130837544; + + // aapt resource value: 0x7f020029 + public const int abc_list_focused_holo = 2130837545; + + // aapt resource value: 0x7f02002a + public const int abc_list_longpressed_holo = 2130837546; + + // aapt resource value: 0x7f02002b + public const int abc_list_pressed_holo_dark = 2130837547; + + // aapt resource value: 0x7f02002c + public const int abc_list_pressed_holo_light = 2130837548; + + // aapt resource value: 0x7f02002d + public const int abc_list_selector_background_transition_holo_dark = 2130837549; + + // aapt resource value: 0x7f02002e + public const int abc_list_selector_background_transition_holo_light = 2130837550; + + // aapt resource value: 0x7f02002f + public const int abc_list_selector_disabled_holo_dark = 2130837551; + + // aapt resource value: 0x7f020030 + public const int abc_list_selector_disabled_holo_light = 2130837552; + + // aapt resource value: 0x7f020031 + public const int abc_list_selector_holo_dark = 2130837553; + + // aapt resource value: 0x7f020032 + public const int abc_list_selector_holo_light = 2130837554; + + // aapt resource value: 0x7f020033 + public const int abc_menu_hardkey_panel_mtrl_mult = 2130837555; + + // aapt resource value: 0x7f020034 + public const int abc_popup_background_mtrl_mult = 2130837556; + + // aapt resource value: 0x7f020035 + public const int abc_ratingbar_indicator_material = 2130837557; + + // aapt resource value: 0x7f020036 + public const int abc_ratingbar_material = 2130837558; + + // aapt resource value: 0x7f020037 + public const int abc_ratingbar_small_material = 2130837559; + + // aapt resource value: 0x7f020038 + public const int abc_scrubber_control_off_mtrl_alpha = 2130837560; + + // aapt resource value: 0x7f020039 + public const int abc_scrubber_control_to_pressed_mtrl_000 = 2130837561; + + // aapt resource value: 0x7f02003a + public const int abc_scrubber_control_to_pressed_mtrl_005 = 2130837562; + + // aapt resource value: 0x7f02003b + public const int abc_scrubber_primary_mtrl_alpha = 2130837563; + + // aapt resource value: 0x7f02003c + public const int abc_scrubber_track_mtrl_alpha = 2130837564; + + // aapt resource value: 0x7f02003d + public const int abc_seekbar_thumb_material = 2130837565; + + // aapt resource value: 0x7f02003e + public const int abc_seekbar_tick_mark_material = 2130837566; + + // aapt resource value: 0x7f02003f + public const int abc_seekbar_track_material = 2130837567; + + // aapt resource value: 0x7f020040 + public const int abc_spinner_mtrl_am_alpha = 2130837568; + + // aapt resource value: 0x7f020041 + public const int abc_spinner_textfield_background_material = 2130837569; + + // aapt resource value: 0x7f020042 + public const int abc_switch_thumb_material = 2130837570; + + // aapt resource value: 0x7f020043 + public const int abc_switch_track_mtrl_alpha = 2130837571; + + // aapt resource value: 0x7f020044 + public const int abc_tab_indicator_material = 2130837572; + + // aapt resource value: 0x7f020045 + public const int abc_tab_indicator_mtrl_alpha = 2130837573; + + // aapt resource value: 0x7f020046 + public const int abc_text_cursor_material = 2130837574; + + // aapt resource value: 0x7f020047 + public const int abc_text_select_handle_left_mtrl_dark = 2130837575; + + // aapt resource value: 0x7f020048 + public const int abc_text_select_handle_left_mtrl_light = 2130837576; + + // aapt resource value: 0x7f020049 + public const int abc_text_select_handle_middle_mtrl_dark = 2130837577; + + // aapt resource value: 0x7f02004a + public const int abc_text_select_handle_middle_mtrl_light = 2130837578; + + // aapt resource value: 0x7f02004b + public const int abc_text_select_handle_right_mtrl_dark = 2130837579; + + // aapt resource value: 0x7f02004c + public const int abc_text_select_handle_right_mtrl_light = 2130837580; + + // aapt resource value: 0x7f02004d + public const int abc_textfield_activated_mtrl_alpha = 2130837581; + + // aapt resource value: 0x7f02004e + public const int abc_textfield_default_mtrl_alpha = 2130837582; + + // aapt resource value: 0x7f02004f + public const int abc_textfield_search_activated_mtrl_alpha = 2130837583; + + // aapt resource value: 0x7f020050 + public const int abc_textfield_search_default_mtrl_alpha = 2130837584; + + // aapt resource value: 0x7f020051 + public const int abc_textfield_search_material = 2130837585; + + // aapt resource value: 0x7f020052 + public const int abc_vector_test = 2130837586; + + // aapt resource value: 0x7f020053 + public const int avd_hide_password = 2130837587; + + // aapt resource value: 0x7f02006a + public const int avd_hide_password_1 = 2130837610; + + // aapt resource value: 0x7f02006b + public const int avd_hide_password_2 = 2130837611; + + // aapt resource value: 0x7f02006c + public const int avd_hide_password_3 = 2130837612; + + // aapt resource value: 0x7f020054 + public const int avd_show_password = 2130837588; + + // aapt resource value: 0x7f02006d + public const int avd_show_password_1 = 2130837613; + + // aapt resource value: 0x7f02006e + public const int avd_show_password_2 = 2130837614; + + // aapt resource value: 0x7f02006f + public const int avd_show_password_3 = 2130837615; + + // aapt resource value: 0x7f020055 + public const int design_bottom_navigation_item_background = 2130837589; + + // aapt resource value: 0x7f020056 + public const int design_fab_background = 2130837590; + + // aapt resource value: 0x7f020057 + public const int design_ic_visibility = 2130837591; + + // aapt resource value: 0x7f020058 + public const int design_ic_visibility_off = 2130837592; + + // aapt resource value: 0x7f020059 + public const int design_password_eye = 2130837593; + + // aapt resource value: 0x7f02005a + public const int design_snackbar_background = 2130837594; + + // aapt resource value: 0x7f02005b + public const int navigation_empty_icon = 2130837595; + + // aapt resource value: 0x7f02005c + public const int notification_action_background = 2130837596; + + // aapt resource value: 0x7f02005d + public const int notification_bg = 2130837597; + + // aapt resource value: 0x7f02005e + public const int notification_bg_low = 2130837598; + + // aapt resource value: 0x7f02005f + public const int notification_bg_low_normal = 2130837599; + + // aapt resource value: 0x7f020060 + public const int notification_bg_low_pressed = 2130837600; + + // aapt resource value: 0x7f020061 + public const int notification_bg_normal = 2130837601; + + // aapt resource value: 0x7f020062 + public const int notification_bg_normal_pressed = 2130837602; + + // aapt resource value: 0x7f020063 + public const int notification_icon_background = 2130837603; + + // aapt resource value: 0x7f020068 + public const int notification_template_icon_bg = 2130837608; + + // aapt resource value: 0x7f020069 + public const int notification_template_icon_low_bg = 2130837609; + + // aapt resource value: 0x7f020064 + public const int notification_tile_bg = 2130837604; + + // aapt resource value: 0x7f020065 + public const int notify_panel_notification_icon_bg = 2130837605; + + // aapt resource value: 0x7f020066 + public const int tooltip_frame_dark = 2130837606; + + // aapt resource value: 0x7f020067 + public const int tooltip_frame_light = 2130837607; + + static Drawable() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Drawable() + { + } + } + + public partial class Id + { + + // aapt resource value: 0x7f080032 + public const int ALT = 2131230770; + + // aapt resource value: 0x7f080033 + public const int CTRL = 2131230771; + + // aapt resource value: 0x7f080034 + public const int FUNCTION = 2131230772; + + // aapt resource value: 0x7f080035 + public const int META = 2131230773; + + // aapt resource value: 0x7f080036 + public const int SHIFT = 2131230774; + + // aapt resource value: 0x7f080037 + public const int SYM = 2131230775; + + // aapt resource value: 0x7f08009d + public const int action0 = 2131230877; + + // aapt resource value: 0x7f08007c + public const int action_bar = 2131230844; + + // aapt resource value: 0x7f080001 + public const int action_bar_activity_content = 2131230721; + + // aapt resource value: 0x7f08007b + public const int action_bar_container = 2131230843; + + // aapt resource value: 0x7f080077 + public const int action_bar_root = 2131230839; + + // aapt resource value: 0x7f080002 + public const int action_bar_spinner = 2131230722; + + // aapt resource value: 0x7f08005b + public const int action_bar_subtitle = 2131230811; + + // aapt resource value: 0x7f08005a + public const int action_bar_title = 2131230810; + + // aapt resource value: 0x7f08009a + public const int action_container = 2131230874; + + // aapt resource value: 0x7f08007d + public const int action_context_bar = 2131230845; + + // aapt resource value: 0x7f0800a1 + public const int action_divider = 2131230881; + + // aapt resource value: 0x7f08009b + public const int action_image = 2131230875; + + // aapt resource value: 0x7f080003 + public const int action_menu_divider = 2131230723; + + // aapt resource value: 0x7f080004 + public const int action_menu_presenter = 2131230724; + + // aapt resource value: 0x7f080079 + public const int action_mode_bar = 2131230841; + + // aapt resource value: 0x7f080078 + public const int action_mode_bar_stub = 2131230840; + + // aapt resource value: 0x7f08005c + public const int action_mode_close_button = 2131230812; + + // aapt resource value: 0x7f08009c + public const int action_text = 2131230876; + + // aapt resource value: 0x7f0800aa + public const int actions = 2131230890; + + // aapt resource value: 0x7f08005d + public const int activity_chooser_view_content = 2131230813; + + // aapt resource value: 0x7f080027 + public const int add = 2131230759; + + // aapt resource value: 0x7f080070 + public const int alertTitle = 2131230832; + + // aapt resource value: 0x7f080052 + public const int all = 2131230802; + + // aapt resource value: 0x7f080038 + public const int always = 2131230776; + + // aapt resource value: 0x7f080056 + public const int async = 2131230806; + + // aapt resource value: 0x7f080044 + public const int auto = 2131230788; + + // aapt resource value: 0x7f08002f + public const int beginning = 2131230767; + + // aapt resource value: 0x7f080057 + public const int blocking = 2131230807; + + // aapt resource value: 0x7f08003d + public const int bottom = 2131230781; + + // aapt resource value: 0x7f080063 + public const int buttonPanel = 2131230819; + + // aapt resource value: 0x7f08009e + public const int cancel_action = 2131230878; + + // aapt resource value: 0x7f080045 + public const int center = 2131230789; + + // aapt resource value: 0x7f080046 + public const int center_horizontal = 2131230790; + + // aapt resource value: 0x7f080047 + public const int center_vertical = 2131230791; + + // aapt resource value: 0x7f080073 + public const int checkbox = 2131230835; + + // aapt resource value: 0x7f0800a6 + public const int chronometer = 2131230886; + + // aapt resource value: 0x7f08004e + public const int clip_horizontal = 2131230798; + + // aapt resource value: 0x7f08004f + public const int clip_vertical = 2131230799; + + // aapt resource value: 0x7f080039 + public const int collapseActionView = 2131230777; + + // aapt resource value: 0x7f08008e + public const int container = 2131230862; + + // aapt resource value: 0x7f080066 + public const int contentPanel = 2131230822; + + // aapt resource value: 0x7f08008f + public const int coordinator = 2131230863; + + // aapt resource value: 0x7f08006d + public const int custom = 2131230829; + + // aapt resource value: 0x7f08006c + public const int customPanel = 2131230828; + + // aapt resource value: 0x7f08007a + public const int decor_content_parent = 2131230842; + + // aapt resource value: 0x7f080060 + public const int default_activity_button = 2131230816; + + // aapt resource value: 0x7f080091 + public const int design_bottom_sheet = 2131230865; + + // aapt resource value: 0x7f080098 + public const int design_menu_item_action_area = 2131230872; + + // aapt resource value: 0x7f080097 + public const int design_menu_item_action_area_stub = 2131230871; + + // aapt resource value: 0x7f080096 + public const int design_menu_item_text = 2131230870; + + // aapt resource value: 0x7f080095 + public const int design_navigation_view = 2131230869; + + // aapt resource value: 0x7f080020 + public const int disableHome = 2131230752; + + // aapt resource value: 0x7f08007e + public const int edit_query = 2131230846; + + // aapt resource value: 0x7f080030 + public const int end = 2131230768; + + // aapt resource value: 0x7f0800ac + public const int end_padder = 2131230892; + + // aapt resource value: 0x7f08003f + public const int enterAlways = 2131230783; + + // aapt resource value: 0x7f080040 + public const int enterAlwaysCollapsed = 2131230784; + + // aapt resource value: 0x7f080041 + public const int exitUntilCollapsed = 2131230785; + + // aapt resource value: 0x7f08005e + public const int expand_activities_button = 2131230814; + + // aapt resource value: 0x7f080072 + public const int expanded_menu = 2131230834; + + // aapt resource value: 0x7f080050 + public const int fill = 2131230800; + + // aapt resource value: 0x7f080051 + public const int fill_horizontal = 2131230801; + + // aapt resource value: 0x7f080048 + public const int fill_vertical = 2131230792; + + // aapt resource value: 0x7f080054 + public const int @fixed = 2131230804; + + // aapt resource value: 0x7f080058 + public const int forever = 2131230808; + + // aapt resource value: 0x7f08008b + public const int gameView1 = 2131230859; + + // aapt resource value: 0x7f08000a + public const int ghost_view = 2131230730; + + // aapt resource value: 0x7f080005 + public const int home = 2131230725; + + // aapt resource value: 0x7f080021 + public const int homeAsUp = 2131230753; + + // aapt resource value: 0x7f080062 + public const int icon = 2131230818; + + // aapt resource value: 0x7f0800ab + public const int icon_group = 2131230891; + + // aapt resource value: 0x7f08003a + public const int ifRoom = 2131230778; + + // aapt resource value: 0x7f08005f + public const int image = 2131230815; + + // aapt resource value: 0x7f0800a7 + public const int info = 2131230887; + + // aapt resource value: 0x7f080059 + public const int italic = 2131230809; + + // aapt resource value: 0x7f080000 + public const int item_touch_helper_previous_elevation = 2131230720; + + // aapt resource value: 0x7f08008d + public const int largeLabel = 2131230861; + + // aapt resource value: 0x7f080049 + public const int left = 2131230793; + + // aapt resource value: 0x7f080017 + public const int line1 = 2131230743; + + // aapt resource value: 0x7f080018 + public const int line3 = 2131230744; + + // aapt resource value: 0x7f08001d + public const int listMode = 2131230749; + + // aapt resource value: 0x7f080061 + public const int list_item = 2131230817; + + // aapt resource value: 0x7f0800af + public const int masked = 2131230895; + + // aapt resource value: 0x7f0800a0 + public const int media_actions = 2131230880; + + // aapt resource value: 0x7f0800ad + public const int message = 2131230893; + + // aapt resource value: 0x7f080031 + public const int middle = 2131230769; + + // aapt resource value: 0x7f080053 + public const int mini = 2131230803; + + // aapt resource value: 0x7f080028 + public const int multiply = 2131230760; + + // aapt resource value: 0x7f080094 + public const int navigation_header_container = 2131230868; + + // aapt resource value: 0x7f08003b + public const int never = 2131230779; + + // aapt resource value: 0x7f080022 + public const int none = 2131230754; + + // aapt resource value: 0x7f08001e + public const int normal = 2131230750; + + // aapt resource value: 0x7f0800a9 + public const int notification_background = 2131230889; + + // aapt resource value: 0x7f0800a3 + public const int notification_main_column = 2131230883; + + // aapt resource value: 0x7f0800a2 + public const int notification_main_column_container = 2131230882; + + // aapt resource value: 0x7f08004c + public const int parallax = 2131230796; + + // aapt resource value: 0x7f080065 + public const int parentPanel = 2131230821; + + // aapt resource value: 0x7f08000b + public const int parent_matrix = 2131230731; + + // aapt resource value: 0x7f08004d + public const int pin = 2131230797; + + // aapt resource value: 0x7f080006 + public const int progress_circular = 2131230726; + + // aapt resource value: 0x7f080007 + public const int progress_horizontal = 2131230727; + + // aapt resource value: 0x7f080075 + public const int radio = 2131230837; + + // aapt resource value: 0x7f08004a + public const int right = 2131230794; + + // aapt resource value: 0x7f0800a8 + public const int right_icon = 2131230888; + + // aapt resource value: 0x7f0800a4 + public const int right_side = 2131230884; + + // aapt resource value: 0x7f08000c + public const int save_image_matrix = 2131230732; + + // aapt resource value: 0x7f08000d + public const int save_non_transition_alpha = 2131230733; + + // aapt resource value: 0x7f08000e + public const int save_scale_type = 2131230734; + + // aapt resource value: 0x7f080029 + public const int screen = 2131230761; + + // aapt resource value: 0x7f080042 + public const int scroll = 2131230786; + + // aapt resource value: 0x7f08006b + public const int scrollIndicatorDown = 2131230827; + + // aapt resource value: 0x7f080067 + public const int scrollIndicatorUp = 2131230823; + + // aapt resource value: 0x7f080068 + public const int scrollView = 2131230824; + + // aapt resource value: 0x7f080055 + public const int scrollable = 2131230805; + + // aapt resource value: 0x7f080080 + public const int search_badge = 2131230848; + + // aapt resource value: 0x7f08007f + public const int search_bar = 2131230847; + + // aapt resource value: 0x7f080081 + public const int search_button = 2131230849; + + // aapt resource value: 0x7f080086 + public const int search_close_btn = 2131230854; + + // aapt resource value: 0x7f080082 + public const int search_edit_frame = 2131230850; + + // aapt resource value: 0x7f080088 + public const int search_go_btn = 2131230856; + + // aapt resource value: 0x7f080083 + public const int search_mag_icon = 2131230851; + + // aapt resource value: 0x7f080084 + public const int search_plate = 2131230852; + + // aapt resource value: 0x7f080085 + public const int search_src_text = 2131230853; + + // aapt resource value: 0x7f080089 + public const int search_voice_btn = 2131230857; + + // aapt resource value: 0x7f08008a + public const int select_dialog_listview = 2131230858; + + // aapt resource value: 0x7f080074 + public const int shortcut = 2131230836; + + // aapt resource value: 0x7f080023 + public const int showCustom = 2131230755; + + // aapt resource value: 0x7f080024 + public const int showHome = 2131230756; + + // aapt resource value: 0x7f080025 + public const int showTitle = 2131230757; + + // aapt resource value: 0x7f08008c + public const int smallLabel = 2131230860; + + // aapt resource value: 0x7f080093 + public const int snackbar_action = 2131230867; + + // aapt resource value: 0x7f080092 + public const int snackbar_text = 2131230866; + + // aapt resource value: 0x7f080043 + public const int snap = 2131230787; + + // aapt resource value: 0x7f080064 + public const int spacer = 2131230820; + + // aapt resource value: 0x7f080008 + public const int split_action_bar = 2131230728; + + // aapt resource value: 0x7f08002a + public const int src_atop = 2131230762; + + // aapt resource value: 0x7f08002b + public const int src_in = 2131230763; + + // aapt resource value: 0x7f08002c + public const int src_over = 2131230764; + + // aapt resource value: 0x7f08004b + public const int start = 2131230795; + + // aapt resource value: 0x7f08009f + public const int status_bar_latest_event_content = 2131230879; + + // aapt resource value: 0x7f080076 + public const int submenuarrow = 2131230838; + + // aapt resource value: 0x7f080087 + public const int submit_area = 2131230855; + + // aapt resource value: 0x7f08001f + public const int tabMode = 2131230751; + + // aapt resource value: 0x7f080019 + public const int tag_transition_group = 2131230745; + + // aapt resource value: 0x7f08001a + public const int text = 2131230746; + + // aapt resource value: 0x7f08001b + public const int text2 = 2131230747; + + // aapt resource value: 0x7f08006a + public const int textSpacerNoButtons = 2131230826; + + // aapt resource value: 0x7f080069 + public const int textSpacerNoTitle = 2131230825; + + // aapt resource value: 0x7f080099 + public const int text_input_password_toggle = 2131230873; + + // aapt resource value: 0x7f080014 + public const int textinput_counter = 2131230740; + + // aapt resource value: 0x7f080015 + public const int textinput_error = 2131230741; + + // aapt resource value: 0x7f0800a5 + public const int time = 2131230885; + + // aapt resource value: 0x7f08001c + public const int title = 2131230748; + + // aapt resource value: 0x7f080071 + public const int titleDividerNoCustom = 2131230833; + + // aapt resource value: 0x7f08006f + public const int title_template = 2131230831; + + // aapt resource value: 0x7f08003e + public const int top = 2131230782; + + // aapt resource value: 0x7f08006e + public const int topPanel = 2131230830; + + // aapt resource value: 0x7f080090 + public const int touch_outside = 2131230864; + + // aapt resource value: 0x7f08000f + public const int transition_current_scene = 2131230735; + + // aapt resource value: 0x7f080010 + public const int transition_layout_save = 2131230736; + + // aapt resource value: 0x7f080011 + public const int transition_position = 2131230737; + + // aapt resource value: 0x7f080012 + public const int transition_scene_layoutid_cache = 2131230738; + + // aapt resource value: 0x7f080013 + public const int transition_transform = 2131230739; + + // aapt resource value: 0x7f08002d + public const int uniform = 2131230765; + + // aapt resource value: 0x7f080009 + public const int up = 2131230729; + + // aapt resource value: 0x7f080026 + public const int useLogo = 2131230758; + + // aapt resource value: 0x7f080016 + public const int view_offset_helper = 2131230742; + + // aapt resource value: 0x7f0800ae + public const int visible = 2131230894; + + // aapt resource value: 0x7f08003c + public const int withText = 2131230780; + + // aapt resource value: 0x7f08002e + public const int wrap_content = 2131230766; + + static Id() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Id() + { + } + } + + public partial class Integer + { + + // aapt resource value: 0x7f0d0000 + public const int abc_config_activityDefaultDur = 2131558400; + + // aapt resource value: 0x7f0d0001 + public const int abc_config_activityShortDur = 2131558401; + + // aapt resource value: 0x7f0d0005 + public const int app_bar_elevation_anim_duration = 2131558405; + + // aapt resource value: 0x7f0d0006 + public const int bottom_sheet_slide_duration = 2131558406; + + // aapt resource value: 0x7f0d0002 + public const int cancel_button_image_alpha = 2131558402; + + // aapt resource value: 0x7f0d0003 + public const int config_tooltipAnimTime = 2131558403; + + // aapt resource value: 0x7f0d0004 + public const int design_snackbar_text_max_lines = 2131558404; + + // aapt resource value: 0x7f0d0007 + public const int hide_password_duration = 2131558407; + + // aapt resource value: 0x7f0d0008 + public const int show_password_duration = 2131558408; + + // aapt resource value: 0x7f0d0009 + public const int status_bar_notification_info_maxnum = 2131558409; + + static Integer() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Integer() + { + } + } + + public partial class Layout + { + + // aapt resource value: 0x7f040000 + public const int abc_action_bar_title_item = 2130968576; + + // aapt resource value: 0x7f040001 + public const int abc_action_bar_up_container = 2130968577; + + // aapt resource value: 0x7f040002 + public const int abc_action_menu_item_layout = 2130968578; + + // aapt resource value: 0x7f040003 + public const int abc_action_menu_layout = 2130968579; + + // aapt resource value: 0x7f040004 + public const int abc_action_mode_bar = 2130968580; + + // aapt resource value: 0x7f040005 + public const int abc_action_mode_close_item_material = 2130968581; + + // aapt resource value: 0x7f040006 + public const int abc_activity_chooser_view = 2130968582; + + // aapt resource value: 0x7f040007 + public const int abc_activity_chooser_view_list_item = 2130968583; + + // aapt resource value: 0x7f040008 + public const int abc_alert_dialog_button_bar_material = 2130968584; + + // aapt resource value: 0x7f040009 + public const int abc_alert_dialog_material = 2130968585; + + // aapt resource value: 0x7f04000a + public const int abc_alert_dialog_title_material = 2130968586; + + // aapt resource value: 0x7f04000b + public const int abc_dialog_title_material = 2130968587; + + // aapt resource value: 0x7f04000c + public const int abc_expanded_menu_layout = 2130968588; + + // aapt resource value: 0x7f04000d + public const int abc_list_menu_item_checkbox = 2130968589; + + // aapt resource value: 0x7f04000e + public const int abc_list_menu_item_icon = 2130968590; + + // aapt resource value: 0x7f04000f + public const int abc_list_menu_item_layout = 2130968591; + + // aapt resource value: 0x7f040010 + public const int abc_list_menu_item_radio = 2130968592; + + // aapt resource value: 0x7f040011 + public const int abc_popup_menu_header_item_layout = 2130968593; + + // aapt resource value: 0x7f040012 + public const int abc_popup_menu_item_layout = 2130968594; + + // aapt resource value: 0x7f040013 + public const int abc_screen_content_include = 2130968595; + + // aapt resource value: 0x7f040014 + public const int abc_screen_simple = 2130968596; + + // aapt resource value: 0x7f040015 + public const int abc_screen_simple_overlay_action_mode = 2130968597; + + // aapt resource value: 0x7f040016 + public const int abc_screen_toolbar = 2130968598; + + // aapt resource value: 0x7f040017 + public const int abc_search_dropdown_item_icons_2line = 2130968599; + + // aapt resource value: 0x7f040018 + public const int abc_search_view = 2130968600; + + // aapt resource value: 0x7f040019 + public const int abc_select_dialog_material = 2130968601; + + // aapt resource value: 0x7f04001a + public const int activity_main = 2130968602; + + // aapt resource value: 0x7f04001b + public const int design_bottom_navigation_item = 2130968603; + + // aapt resource value: 0x7f04001c + public const int design_bottom_sheet_dialog = 2130968604; + + // aapt resource value: 0x7f04001d + public const int design_layout_snackbar = 2130968605; + + // aapt resource value: 0x7f04001e + public const int design_layout_snackbar_include = 2130968606; + + // aapt resource value: 0x7f04001f + public const int design_layout_tab_icon = 2130968607; + + // aapt resource value: 0x7f040020 + public const int design_layout_tab_text = 2130968608; + + // aapt resource value: 0x7f040021 + public const int design_menu_item_action_area = 2130968609; + + // aapt resource value: 0x7f040022 + public const int design_navigation_item = 2130968610; + + // aapt resource value: 0x7f040023 + public const int design_navigation_item_header = 2130968611; + + // aapt resource value: 0x7f040024 + public const int design_navigation_item_separator = 2130968612; + + // aapt resource value: 0x7f040025 + public const int design_navigation_item_subheader = 2130968613; + + // aapt resource value: 0x7f040026 + public const int design_navigation_menu = 2130968614; + + // aapt resource value: 0x7f040027 + public const int design_navigation_menu_item = 2130968615; + + // aapt resource value: 0x7f040028 + public const int design_text_input_password_icon = 2130968616; + + // aapt resource value: 0x7f040029 + public const int notification_action = 2130968617; + + // aapt resource value: 0x7f04002a + public const int notification_action_tombstone = 2130968618; + + // aapt resource value: 0x7f04002b + public const int notification_media_action = 2130968619; + + // aapt resource value: 0x7f04002c + public const int notification_media_cancel_action = 2130968620; + + // aapt resource value: 0x7f04002d + public const int notification_template_big_media = 2130968621; + + // aapt resource value: 0x7f04002e + public const int notification_template_big_media_custom = 2130968622; + + // aapt resource value: 0x7f04002f + public const int notification_template_big_media_narrow = 2130968623; + + // aapt resource value: 0x7f040030 + public const int notification_template_big_media_narrow_custom = 2130968624; + + // aapt resource value: 0x7f040031 + public const int notification_template_custom_big = 2130968625; + + // aapt resource value: 0x7f040032 + public const int notification_template_icon_group = 2130968626; + + // aapt resource value: 0x7f040033 + public const int notification_template_lines_media = 2130968627; + + // aapt resource value: 0x7f040034 + public const int notification_template_media = 2130968628; + + // aapt resource value: 0x7f040035 + public const int notification_template_media_custom = 2130968629; + + // aapt resource value: 0x7f040036 + public const int notification_template_part_chronometer = 2130968630; + + // aapt resource value: 0x7f040037 + public const int notification_template_part_time = 2130968631; + + // aapt resource value: 0x7f040038 + public const int select_dialog_item_material = 2130968632; + + // aapt resource value: 0x7f040039 + public const int select_dialog_multichoice_material = 2130968633; + + // aapt resource value: 0x7f04003a + public const int select_dialog_singlechoice_material = 2130968634; + + // aapt resource value: 0x7f04003b + public const int support_simple_spinner_dropdown_item = 2130968635; + + // aapt resource value: 0x7f04003c + public const int tooltip = 2130968636; + + static Layout() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Layout() + { + } + } + + public partial class Mipmap + { + + // aapt resource value: 0x7f030000 + public const int ic_launcher = 2130903040; + + // aapt resource value: 0x7f030001 + public const int ic_launcher_foreground = 2130903041; + + // aapt resource value: 0x7f030002 + public const int ic_launcher_round = 2130903042; + + static Mipmap() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Mipmap() + { + } + } + + public partial class String + { + + // aapt resource value: 0x7f090000 + public const int abc_action_bar_home_description = 2131296256; + + // aapt resource value: 0x7f090001 + public const int abc_action_bar_up_description = 2131296257; + + // aapt resource value: 0x7f090002 + public const int abc_action_menu_overflow_description = 2131296258; + + // aapt resource value: 0x7f090003 + public const int abc_action_mode_done = 2131296259; + + // aapt resource value: 0x7f090004 + public const int abc_activity_chooser_view_see_all = 2131296260; + + // aapt resource value: 0x7f090005 + public const int abc_activitychooserview_choose_application = 2131296261; + + // aapt resource value: 0x7f090006 + public const int abc_capital_off = 2131296262; + + // aapt resource value: 0x7f090007 + public const int abc_capital_on = 2131296263; + + // aapt resource value: 0x7f090012 + public const int abc_font_family_body_1_material = 2131296274; + + // aapt resource value: 0x7f090013 + public const int abc_font_family_body_2_material = 2131296275; + + // aapt resource value: 0x7f090014 + public const int abc_font_family_button_material = 2131296276; + + // aapt resource value: 0x7f090015 + public const int abc_font_family_caption_material = 2131296277; + + // aapt resource value: 0x7f090016 + public const int abc_font_family_display_1_material = 2131296278; + + // aapt resource value: 0x7f090017 + public const int abc_font_family_display_2_material = 2131296279; + + // aapt resource value: 0x7f090018 + public const int abc_font_family_display_3_material = 2131296280; + + // aapt resource value: 0x7f090019 + public const int abc_font_family_display_4_material = 2131296281; + + // aapt resource value: 0x7f09001a + public const int abc_font_family_headline_material = 2131296282; + + // aapt resource value: 0x7f09001b + public const int abc_font_family_menu_material = 2131296283; + + // aapt resource value: 0x7f09001c + public const int abc_font_family_subhead_material = 2131296284; + + // aapt resource value: 0x7f09001d + public const int abc_font_family_title_material = 2131296285; + + // aapt resource value: 0x7f090008 + public const int abc_search_hint = 2131296264; + + // aapt resource value: 0x7f090009 + public const int abc_searchview_description_clear = 2131296265; + + // aapt resource value: 0x7f09000a + public const int abc_searchview_description_query = 2131296266; + + // aapt resource value: 0x7f09000b + public const int abc_searchview_description_search = 2131296267; + + // aapt resource value: 0x7f09000c + public const int abc_searchview_description_submit = 2131296268; + + // aapt resource value: 0x7f09000d + public const int abc_searchview_description_voice = 2131296269; + + // aapt resource value: 0x7f09000e + public const int abc_shareactionprovider_share_with = 2131296270; + + // aapt resource value: 0x7f09000f + public const int abc_shareactionprovider_share_with_application = 2131296271; + + // aapt resource value: 0x7f090010 + public const int abc_toolbar_collapse_description = 2131296272; + + // aapt resource value: 0x7f090028 + public const int action_settings = 2131296296; + + // aapt resource value: 0x7f090027 + public const int app_name = 2131296295; + + // aapt resource value: 0x7f09001e + public const int appbar_scrolling_view_behavior = 2131296286; + + // aapt resource value: 0x7f09001f + public const int bottom_sheet_behavior = 2131296287; + + // aapt resource value: 0x7f090020 + public const int character_counter_pattern = 2131296288; + + // aapt resource value: 0x7f090021 + public const int password_toggle_content_description = 2131296289; + + // aapt resource value: 0x7f090022 + public const int path_password_eye = 2131296290; + + // aapt resource value: 0x7f090023 + public const int path_password_eye_mask_strike_through = 2131296291; + + // aapt resource value: 0x7f090024 + public const int path_password_eye_mask_visible = 2131296292; + + // aapt resource value: 0x7f090025 + public const int path_password_strike_through = 2131296293; + + // aapt resource value: 0x7f090011 + public const int search_menu_title = 2131296273; + + // aapt resource value: 0x7f090026 + public const int status_bar_notification_info_overflow = 2131296294; + + static String() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private String() + { + } + } + + public partial class Style + { + + // aapt resource value: 0x7f0a0095 + public const int AlertDialog_AppCompat = 2131361941; + + // aapt resource value: 0x7f0a0096 + public const int AlertDialog_AppCompat_Light = 2131361942; + + // aapt resource value: 0x7f0a0097 + public const int Animation_AppCompat_Dialog = 2131361943; + + // aapt resource value: 0x7f0a0098 + public const int Animation_AppCompat_DropDownUp = 2131361944; + + // aapt resource value: 0x7f0a0099 + public const int Animation_AppCompat_Tooltip = 2131361945; + + // aapt resource value: 0x7f0a015f + public const int Animation_Design_BottomSheetDialog = 2131362143; + + // aapt resource value: 0x7f0a0180 + public const int AppTheme = 2131362176; + + // aapt resource value: 0x7f0a009a + public const int Base_AlertDialog_AppCompat = 2131361946; + + // aapt resource value: 0x7f0a009b + public const int Base_AlertDialog_AppCompat_Light = 2131361947; + + // aapt resource value: 0x7f0a009c + public const int Base_Animation_AppCompat_Dialog = 2131361948; + + // aapt resource value: 0x7f0a009d + public const int Base_Animation_AppCompat_DropDownUp = 2131361949; + + // aapt resource value: 0x7f0a009e + public const int Base_Animation_AppCompat_Tooltip = 2131361950; + + // aapt resource value: 0x7f0a009f + public const int Base_DialogWindowTitle_AppCompat = 2131361951; + + // aapt resource value: 0x7f0a00a0 + public const int Base_DialogWindowTitleBackground_AppCompat = 2131361952; + + // aapt resource value: 0x7f0a0039 + public const int Base_TextAppearance_AppCompat = 2131361849; + + // aapt resource value: 0x7f0a003a + public const int Base_TextAppearance_AppCompat_Body1 = 2131361850; + + // aapt resource value: 0x7f0a003b + public const int Base_TextAppearance_AppCompat_Body2 = 2131361851; + + // aapt resource value: 0x7f0a0027 + public const int Base_TextAppearance_AppCompat_Button = 2131361831; + + // aapt resource value: 0x7f0a003c + public const int Base_TextAppearance_AppCompat_Caption = 2131361852; + + // aapt resource value: 0x7f0a003d + public const int Base_TextAppearance_AppCompat_Display1 = 2131361853; + + // aapt resource value: 0x7f0a003e + public const int Base_TextAppearance_AppCompat_Display2 = 2131361854; + + // aapt resource value: 0x7f0a003f + public const int Base_TextAppearance_AppCompat_Display3 = 2131361855; + + // aapt resource value: 0x7f0a0040 + public const int Base_TextAppearance_AppCompat_Display4 = 2131361856; + + // aapt resource value: 0x7f0a0041 + public const int Base_TextAppearance_AppCompat_Headline = 2131361857; + + // aapt resource value: 0x7f0a000b + public const int Base_TextAppearance_AppCompat_Inverse = 2131361803; + + // aapt resource value: 0x7f0a0042 + public const int Base_TextAppearance_AppCompat_Large = 2131361858; + + // aapt resource value: 0x7f0a000c + public const int Base_TextAppearance_AppCompat_Large_Inverse = 2131361804; + + // aapt resource value: 0x7f0a0043 + public const int Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = 2131361859; + + // aapt resource value: 0x7f0a0044 + public const int Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = 2131361860; + + // aapt resource value: 0x7f0a0045 + public const int Base_TextAppearance_AppCompat_Medium = 2131361861; + + // aapt resource value: 0x7f0a000d + public const int Base_TextAppearance_AppCompat_Medium_Inverse = 2131361805; + + // aapt resource value: 0x7f0a0046 + public const int Base_TextAppearance_AppCompat_Menu = 2131361862; + + // aapt resource value: 0x7f0a00a1 + public const int Base_TextAppearance_AppCompat_SearchResult = 2131361953; + + // aapt resource value: 0x7f0a0047 + public const int Base_TextAppearance_AppCompat_SearchResult_Subtitle = 2131361863; + + // aapt resource value: 0x7f0a0048 + public const int Base_TextAppearance_AppCompat_SearchResult_Title = 2131361864; + + // aapt resource value: 0x7f0a0049 + public const int Base_TextAppearance_AppCompat_Small = 2131361865; + + // aapt resource value: 0x7f0a000e + public const int Base_TextAppearance_AppCompat_Small_Inverse = 2131361806; + + // aapt resource value: 0x7f0a004a + public const int Base_TextAppearance_AppCompat_Subhead = 2131361866; + + // aapt resource value: 0x7f0a000f + public const int Base_TextAppearance_AppCompat_Subhead_Inverse = 2131361807; + + // aapt resource value: 0x7f0a004b + public const int Base_TextAppearance_AppCompat_Title = 2131361867; + + // aapt resource value: 0x7f0a0010 + public const int Base_TextAppearance_AppCompat_Title_Inverse = 2131361808; + + // aapt resource value: 0x7f0a00a2 + public const int Base_TextAppearance_AppCompat_Tooltip = 2131361954; + + // aapt resource value: 0x7f0a0086 + public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Menu = 2131361926; + + // aapt resource value: 0x7f0a004c + public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle = 2131361868; + + // aapt resource value: 0x7f0a004d + public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = 2131361869; + + // aapt resource value: 0x7f0a004e + public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Title = 2131361870; + + // aapt resource value: 0x7f0a004f + public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = 2131361871; + + // aapt resource value: 0x7f0a0050 + public const int Base_TextAppearance_AppCompat_Widget_ActionMode_Subtitle = 2131361872; + + // aapt resource value: 0x7f0a0051 + public const int Base_TextAppearance_AppCompat_Widget_ActionMode_Title = 2131361873; + + // aapt resource value: 0x7f0a0052 + public const int Base_TextAppearance_AppCompat_Widget_Button = 2131361874; + + // aapt resource value: 0x7f0a008d + public const int Base_TextAppearance_AppCompat_Widget_Button_Borderless_Colored = 2131361933; + + // aapt resource value: 0x7f0a008e + public const int Base_TextAppearance_AppCompat_Widget_Button_Colored = 2131361934; + + // aapt resource value: 0x7f0a0087 + public const int Base_TextAppearance_AppCompat_Widget_Button_Inverse = 2131361927; + + // aapt resource value: 0x7f0a00a3 + public const int Base_TextAppearance_AppCompat_Widget_DropDownItem = 2131361955; + + // aapt resource value: 0x7f0a0053 + public const int Base_TextAppearance_AppCompat_Widget_PopupMenu_Header = 2131361875; + + // aapt resource value: 0x7f0a0054 + public const int Base_TextAppearance_AppCompat_Widget_PopupMenu_Large = 2131361876; + + // aapt resource value: 0x7f0a0055 + public const int Base_TextAppearance_AppCompat_Widget_PopupMenu_Small = 2131361877; + + // aapt resource value: 0x7f0a0056 + public const int Base_TextAppearance_AppCompat_Widget_Switch = 2131361878; + + // aapt resource value: 0x7f0a0057 + public const int Base_TextAppearance_AppCompat_Widget_TextView_SpinnerItem = 2131361879; + + // aapt resource value: 0x7f0a00a4 + public const int Base_TextAppearance_Widget_AppCompat_ExpandedMenu_Item = 2131361956; + + // aapt resource value: 0x7f0a0058 + public const int Base_TextAppearance_Widget_AppCompat_Toolbar_Subtitle = 2131361880; + + // aapt resource value: 0x7f0a0059 + public const int Base_TextAppearance_Widget_AppCompat_Toolbar_Title = 2131361881; + + // aapt resource value: 0x7f0a005a + public const int Base_Theme_AppCompat = 2131361882; + + // aapt resource value: 0x7f0a00a5 + public const int Base_Theme_AppCompat_CompactMenu = 2131361957; + + // aapt resource value: 0x7f0a0011 + public const int Base_Theme_AppCompat_Dialog = 2131361809; + + // aapt resource value: 0x7f0a0012 + public const int Base_Theme_AppCompat_Dialog_Alert = 2131361810; + + // aapt resource value: 0x7f0a00a6 + public const int Base_Theme_AppCompat_Dialog_FixedSize = 2131361958; + + // aapt resource value: 0x7f0a0013 + public const int Base_Theme_AppCompat_Dialog_MinWidth = 2131361811; + + // aapt resource value: 0x7f0a0001 + public const int Base_Theme_AppCompat_DialogWhenLarge = 2131361793; + + // aapt resource value: 0x7f0a005b + public const int Base_Theme_AppCompat_Light = 2131361883; + + // aapt resource value: 0x7f0a00a7 + public const int Base_Theme_AppCompat_Light_DarkActionBar = 2131361959; + + // aapt resource value: 0x7f0a0014 + public const int Base_Theme_AppCompat_Light_Dialog = 2131361812; + + // aapt resource value: 0x7f0a0015 + public const int Base_Theme_AppCompat_Light_Dialog_Alert = 2131361813; + + // aapt resource value: 0x7f0a00a8 + public const int Base_Theme_AppCompat_Light_Dialog_FixedSize = 2131361960; + + // aapt resource value: 0x7f0a0016 + public const int Base_Theme_AppCompat_Light_Dialog_MinWidth = 2131361814; + + // aapt resource value: 0x7f0a0002 + public const int Base_Theme_AppCompat_Light_DialogWhenLarge = 2131361794; + + // aapt resource value: 0x7f0a00a9 + public const int Base_ThemeOverlay_AppCompat = 2131361961; + + // aapt resource value: 0x7f0a00aa + public const int Base_ThemeOverlay_AppCompat_ActionBar = 2131361962; + + // aapt resource value: 0x7f0a00ab + public const int Base_ThemeOverlay_AppCompat_Dark = 2131361963; + + // aapt resource value: 0x7f0a00ac + public const int Base_ThemeOverlay_AppCompat_Dark_ActionBar = 2131361964; + + // aapt resource value: 0x7f0a0017 + public const int Base_ThemeOverlay_AppCompat_Dialog = 2131361815; + + // aapt resource value: 0x7f0a0018 + public const int Base_ThemeOverlay_AppCompat_Dialog_Alert = 2131361816; + + // aapt resource value: 0x7f0a00ad + public const int Base_ThemeOverlay_AppCompat_Light = 2131361965; + + // aapt resource value: 0x7f0a0019 + public const int Base_V11_Theme_AppCompat_Dialog = 2131361817; + + // aapt resource value: 0x7f0a001a + public const int Base_V11_Theme_AppCompat_Light_Dialog = 2131361818; + + // aapt resource value: 0x7f0a001b + public const int Base_V11_ThemeOverlay_AppCompat_Dialog = 2131361819; + + // aapt resource value: 0x7f0a0023 + public const int Base_V12_Widget_AppCompat_AutoCompleteTextView = 2131361827; + + // aapt resource value: 0x7f0a0024 + public const int Base_V12_Widget_AppCompat_EditText = 2131361828; + + // aapt resource value: 0x7f0a0160 + public const int Base_V14_Widget_Design_AppBarLayout = 2131362144; + + // aapt resource value: 0x7f0a005c + public const int Base_V21_Theme_AppCompat = 2131361884; + + // aapt resource value: 0x7f0a005d + public const int Base_V21_Theme_AppCompat_Dialog = 2131361885; + + // aapt resource value: 0x7f0a005e + public const int Base_V21_Theme_AppCompat_Light = 2131361886; + + // aapt resource value: 0x7f0a005f + public const int Base_V21_Theme_AppCompat_Light_Dialog = 2131361887; + + // aapt resource value: 0x7f0a0060 + public const int Base_V21_ThemeOverlay_AppCompat_Dialog = 2131361888; + + // aapt resource value: 0x7f0a015c + public const int Base_V21_Widget_Design_AppBarLayout = 2131362140; + + // aapt resource value: 0x7f0a0084 + public const int Base_V22_Theme_AppCompat = 2131361924; + + // aapt resource value: 0x7f0a0085 + public const int Base_V22_Theme_AppCompat_Light = 2131361925; + + // aapt resource value: 0x7f0a0088 + public const int Base_V23_Theme_AppCompat = 2131361928; + + // aapt resource value: 0x7f0a0089 + public const int Base_V23_Theme_AppCompat_Light = 2131361929; + + // aapt resource value: 0x7f0a0091 + public const int Base_V26_Theme_AppCompat = 2131361937; + + // aapt resource value: 0x7f0a0092 + public const int Base_V26_Theme_AppCompat_Light = 2131361938; + + // aapt resource value: 0x7f0a0093 + public const int Base_V26_Widget_AppCompat_Toolbar = 2131361939; + + // aapt resource value: 0x7f0a015e + public const int Base_V26_Widget_Design_AppBarLayout = 2131362142; + + // aapt resource value: 0x7f0a00ae + public const int Base_V7_Theme_AppCompat = 2131361966; + + // aapt resource value: 0x7f0a00af + public const int Base_V7_Theme_AppCompat_Dialog = 2131361967; + + // aapt resource value: 0x7f0a00b0 + public const int Base_V7_Theme_AppCompat_Light = 2131361968; + + // aapt resource value: 0x7f0a00b1 + public const int Base_V7_Theme_AppCompat_Light_Dialog = 2131361969; + + // aapt resource value: 0x7f0a00b2 + public const int Base_V7_ThemeOverlay_AppCompat_Dialog = 2131361970; + + // aapt resource value: 0x7f0a00b3 + public const int Base_V7_Widget_AppCompat_AutoCompleteTextView = 2131361971; + + // aapt resource value: 0x7f0a00b4 + public const int Base_V7_Widget_AppCompat_EditText = 2131361972; + + // aapt resource value: 0x7f0a00b5 + public const int Base_V7_Widget_AppCompat_Toolbar = 2131361973; + + // aapt resource value: 0x7f0a00b6 + public const int Base_Widget_AppCompat_ActionBar = 2131361974; + + // aapt resource value: 0x7f0a00b7 + public const int Base_Widget_AppCompat_ActionBar_Solid = 2131361975; + + // aapt resource value: 0x7f0a00b8 + public const int Base_Widget_AppCompat_ActionBar_TabBar = 2131361976; + + // aapt resource value: 0x7f0a0061 + public const int Base_Widget_AppCompat_ActionBar_TabText = 2131361889; + + // aapt resource value: 0x7f0a0062 + public const int Base_Widget_AppCompat_ActionBar_TabView = 2131361890; + + // aapt resource value: 0x7f0a0063 + public const int Base_Widget_AppCompat_ActionButton = 2131361891; + + // aapt resource value: 0x7f0a0064 + public const int Base_Widget_AppCompat_ActionButton_CloseMode = 2131361892; + + // aapt resource value: 0x7f0a0065 + public const int Base_Widget_AppCompat_ActionButton_Overflow = 2131361893; + + // aapt resource value: 0x7f0a00b9 + public const int Base_Widget_AppCompat_ActionMode = 2131361977; + + // aapt resource value: 0x7f0a00ba + public const int Base_Widget_AppCompat_ActivityChooserView = 2131361978; + + // aapt resource value: 0x7f0a0025 + public const int Base_Widget_AppCompat_AutoCompleteTextView = 2131361829; + + // aapt resource value: 0x7f0a0066 + public const int Base_Widget_AppCompat_Button = 2131361894; + + // aapt resource value: 0x7f0a0067 + public const int Base_Widget_AppCompat_Button_Borderless = 2131361895; + + // aapt resource value: 0x7f0a0068 + public const int Base_Widget_AppCompat_Button_Borderless_Colored = 2131361896; + + // aapt resource value: 0x7f0a00bb + public const int Base_Widget_AppCompat_Button_ButtonBar_AlertDialog = 2131361979; + + // aapt resource value: 0x7f0a008a + public const int Base_Widget_AppCompat_Button_Colored = 2131361930; + + // aapt resource value: 0x7f0a0069 + public const int Base_Widget_AppCompat_Button_Small = 2131361897; + + // aapt resource value: 0x7f0a006a + public const int Base_Widget_AppCompat_ButtonBar = 2131361898; + + // aapt resource value: 0x7f0a00bc + public const int Base_Widget_AppCompat_ButtonBar_AlertDialog = 2131361980; + + // aapt resource value: 0x7f0a006b + public const int Base_Widget_AppCompat_CompoundButton_CheckBox = 2131361899; + + // aapt resource value: 0x7f0a006c + public const int Base_Widget_AppCompat_CompoundButton_RadioButton = 2131361900; + + // aapt resource value: 0x7f0a00bd + public const int Base_Widget_AppCompat_CompoundButton_Switch = 2131361981; + + // aapt resource value: 0x7f0a0000 + public const int Base_Widget_AppCompat_DrawerArrowToggle = 2131361792; + + // aapt resource value: 0x7f0a00be + public const int Base_Widget_AppCompat_DrawerArrowToggle_Common = 2131361982; + + // aapt resource value: 0x7f0a006d + public const int Base_Widget_AppCompat_DropDownItem_Spinner = 2131361901; + + // aapt resource value: 0x7f0a0026 + public const int Base_Widget_AppCompat_EditText = 2131361830; + + // aapt resource value: 0x7f0a006e + public const int Base_Widget_AppCompat_ImageButton = 2131361902; + + // aapt resource value: 0x7f0a00bf + public const int Base_Widget_AppCompat_Light_ActionBar = 2131361983; + + // aapt resource value: 0x7f0a00c0 + public const int Base_Widget_AppCompat_Light_ActionBar_Solid = 2131361984; + + // aapt resource value: 0x7f0a00c1 + public const int Base_Widget_AppCompat_Light_ActionBar_TabBar = 2131361985; + + // aapt resource value: 0x7f0a006f + public const int Base_Widget_AppCompat_Light_ActionBar_TabText = 2131361903; + + // aapt resource value: 0x7f0a0070 + public const int Base_Widget_AppCompat_Light_ActionBar_TabText_Inverse = 2131361904; + + // aapt resource value: 0x7f0a0071 + public const int Base_Widget_AppCompat_Light_ActionBar_TabView = 2131361905; + + // aapt resource value: 0x7f0a0072 + public const int Base_Widget_AppCompat_Light_PopupMenu = 2131361906; + + // aapt resource value: 0x7f0a0073 + public const int Base_Widget_AppCompat_Light_PopupMenu_Overflow = 2131361907; + + // aapt resource value: 0x7f0a00c2 + public const int Base_Widget_AppCompat_ListMenuView = 2131361986; + + // aapt resource value: 0x7f0a0074 + public const int Base_Widget_AppCompat_ListPopupWindow = 2131361908; + + // aapt resource value: 0x7f0a0075 + public const int Base_Widget_AppCompat_ListView = 2131361909; + + // aapt resource value: 0x7f0a0076 + public const int Base_Widget_AppCompat_ListView_DropDown = 2131361910; + + // aapt resource value: 0x7f0a0077 + public const int Base_Widget_AppCompat_ListView_Menu = 2131361911; + + // aapt resource value: 0x7f0a0078 + public const int Base_Widget_AppCompat_PopupMenu = 2131361912; + + // aapt resource value: 0x7f0a0079 + public const int Base_Widget_AppCompat_PopupMenu_Overflow = 2131361913; + + // aapt resource value: 0x7f0a00c3 + public const int Base_Widget_AppCompat_PopupWindow = 2131361987; + + // aapt resource value: 0x7f0a001c + public const int Base_Widget_AppCompat_ProgressBar = 2131361820; + + // aapt resource value: 0x7f0a001d + public const int Base_Widget_AppCompat_ProgressBar_Horizontal = 2131361821; + + // aapt resource value: 0x7f0a007a + public const int Base_Widget_AppCompat_RatingBar = 2131361914; + + // aapt resource value: 0x7f0a008b + public const int Base_Widget_AppCompat_RatingBar_Indicator = 2131361931; + + // aapt resource value: 0x7f0a008c + public const int Base_Widget_AppCompat_RatingBar_Small = 2131361932; + + // aapt resource value: 0x7f0a00c4 + public const int Base_Widget_AppCompat_SearchView = 2131361988; + + // aapt resource value: 0x7f0a00c5 + public const int Base_Widget_AppCompat_SearchView_ActionBar = 2131361989; + + // aapt resource value: 0x7f0a007b + public const int Base_Widget_AppCompat_SeekBar = 2131361915; + + // aapt resource value: 0x7f0a00c6 + public const int Base_Widget_AppCompat_SeekBar_Discrete = 2131361990; + + // aapt resource value: 0x7f0a007c + public const int Base_Widget_AppCompat_Spinner = 2131361916; + + // aapt resource value: 0x7f0a0003 + public const int Base_Widget_AppCompat_Spinner_Underlined = 2131361795; + + // aapt resource value: 0x7f0a007d + public const int Base_Widget_AppCompat_TextView_SpinnerItem = 2131361917; + + // aapt resource value: 0x7f0a0094 + public const int Base_Widget_AppCompat_Toolbar = 2131361940; + + // aapt resource value: 0x7f0a007e + public const int Base_Widget_AppCompat_Toolbar_Button_Navigation = 2131361918; + + // aapt resource value: 0x7f0a015d + public const int Base_Widget_Design_AppBarLayout = 2131362141; + + // aapt resource value: 0x7f0a0161 + public const int Base_Widget_Design_TabLayout = 2131362145; + + // aapt resource value: 0x7f0a001e + public const int Platform_AppCompat = 2131361822; + + // aapt resource value: 0x7f0a001f + public const int Platform_AppCompat_Light = 2131361823; + + // aapt resource value: 0x7f0a007f + public const int Platform_ThemeOverlay_AppCompat = 2131361919; + + // aapt resource value: 0x7f0a0080 + public const int Platform_ThemeOverlay_AppCompat_Dark = 2131361920; + + // aapt resource value: 0x7f0a0081 + public const int Platform_ThemeOverlay_AppCompat_Light = 2131361921; + + // aapt resource value: 0x7f0a0020 + public const int Platform_V11_AppCompat = 2131361824; + + // aapt resource value: 0x7f0a0021 + public const int Platform_V11_AppCompat_Light = 2131361825; + + // aapt resource value: 0x7f0a0028 + public const int Platform_V14_AppCompat = 2131361832; + + // aapt resource value: 0x7f0a0029 + public const int Platform_V14_AppCompat_Light = 2131361833; + + // aapt resource value: 0x7f0a0082 + public const int Platform_V21_AppCompat = 2131361922; + + // aapt resource value: 0x7f0a0083 + public const int Platform_V21_AppCompat_Light = 2131361923; + + // aapt resource value: 0x7f0a008f + public const int Platform_V25_AppCompat = 2131361935; + + // aapt resource value: 0x7f0a0090 + public const int Platform_V25_AppCompat_Light = 2131361936; + + // aapt resource value: 0x7f0a0022 + public const int Platform_Widget_AppCompat_Spinner = 2131361826; + + // aapt resource value: 0x7f0a002b + public const int RtlOverlay_DialogWindowTitle_AppCompat = 2131361835; + + // aapt resource value: 0x7f0a002c + public const int RtlOverlay_Widget_AppCompat_ActionBar_TitleItem = 2131361836; + + // aapt resource value: 0x7f0a002d + public const int RtlOverlay_Widget_AppCompat_DialogTitle_Icon = 2131361837; + + // aapt resource value: 0x7f0a002e + public const int RtlOverlay_Widget_AppCompat_PopupMenuItem = 2131361838; + + // aapt resource value: 0x7f0a002f + public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_InternalGroup = 2131361839; + + // aapt resource value: 0x7f0a0030 + public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_Text = 2131361840; + + // aapt resource value: 0x7f0a0031 + public const int RtlOverlay_Widget_AppCompat_Search_DropDown = 2131361841; + + // aapt resource value: 0x7f0a0032 + public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Icon1 = 2131361842; + + // aapt resource value: 0x7f0a0033 + public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Icon2 = 2131361843; + + // aapt resource value: 0x7f0a0034 + public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Query = 2131361844; + + // aapt resource value: 0x7f0a0035 + public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Text = 2131361845; + + // aapt resource value: 0x7f0a0036 + public const int RtlOverlay_Widget_AppCompat_SearchView_MagIcon = 2131361846; + + // aapt resource value: 0x7f0a0037 + public const int RtlUnderlay_Widget_AppCompat_ActionButton = 2131361847; + + // aapt resource value: 0x7f0a0038 + public const int RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = 2131361848; + + // aapt resource value: 0x7f0a00c7 + public const int TextAppearance_AppCompat = 2131361991; + + // aapt resource value: 0x7f0a00c8 + public const int TextAppearance_AppCompat_Body1 = 2131361992; + + // aapt resource value: 0x7f0a00c9 + public const int TextAppearance_AppCompat_Body2 = 2131361993; + + // aapt resource value: 0x7f0a00ca + public const int TextAppearance_AppCompat_Button = 2131361994; + + // aapt resource value: 0x7f0a00cb + public const int TextAppearance_AppCompat_Caption = 2131361995; + + // aapt resource value: 0x7f0a00cc + public const int TextAppearance_AppCompat_Display1 = 2131361996; + + // aapt resource value: 0x7f0a00cd + public const int TextAppearance_AppCompat_Display2 = 2131361997; + + // aapt resource value: 0x7f0a00ce + public const int TextAppearance_AppCompat_Display3 = 2131361998; + + // aapt resource value: 0x7f0a00cf + public const int TextAppearance_AppCompat_Display4 = 2131361999; + + // aapt resource value: 0x7f0a00d0 + public const int TextAppearance_AppCompat_Headline = 2131362000; + + // aapt resource value: 0x7f0a00d1 + public const int TextAppearance_AppCompat_Inverse = 2131362001; + + // aapt resource value: 0x7f0a00d2 + public const int TextAppearance_AppCompat_Large = 2131362002; + + // aapt resource value: 0x7f0a00d3 + public const int TextAppearance_AppCompat_Large_Inverse = 2131362003; + + // aapt resource value: 0x7f0a00d4 + public const int TextAppearance_AppCompat_Light_SearchResult_Subtitle = 2131362004; + + // aapt resource value: 0x7f0a00d5 + public const int TextAppearance_AppCompat_Light_SearchResult_Title = 2131362005; + + // aapt resource value: 0x7f0a00d6 + public const int TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = 2131362006; + + // aapt resource value: 0x7f0a00d7 + public const int TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = 2131362007; + + // aapt resource value: 0x7f0a00d8 + public const int TextAppearance_AppCompat_Medium = 2131362008; + + // aapt resource value: 0x7f0a00d9 + public const int TextAppearance_AppCompat_Medium_Inverse = 2131362009; + + // aapt resource value: 0x7f0a00da + public const int TextAppearance_AppCompat_Menu = 2131362010; + + // aapt resource value: 0x7f0a00db + public const int TextAppearance_AppCompat_SearchResult_Subtitle = 2131362011; + + // aapt resource value: 0x7f0a00dc + public const int TextAppearance_AppCompat_SearchResult_Title = 2131362012; + + // aapt resource value: 0x7f0a00dd + public const int TextAppearance_AppCompat_Small = 2131362013; + + // aapt resource value: 0x7f0a00de + public const int TextAppearance_AppCompat_Small_Inverse = 2131362014; + + // aapt resource value: 0x7f0a00df + public const int TextAppearance_AppCompat_Subhead = 2131362015; + + // aapt resource value: 0x7f0a00e0 + public const int TextAppearance_AppCompat_Subhead_Inverse = 2131362016; + + // aapt resource value: 0x7f0a00e1 + public const int TextAppearance_AppCompat_Title = 2131362017; + + // aapt resource value: 0x7f0a00e2 + public const int TextAppearance_AppCompat_Title_Inverse = 2131362018; + + // aapt resource value: 0x7f0a002a + public const int TextAppearance_AppCompat_Tooltip = 2131361834; + + // aapt resource value: 0x7f0a00e3 + public const int TextAppearance_AppCompat_Widget_ActionBar_Menu = 2131362019; + + // aapt resource value: 0x7f0a00e4 + public const int TextAppearance_AppCompat_Widget_ActionBar_Subtitle = 2131362020; + + // aapt resource value: 0x7f0a00e5 + public const int TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = 2131362021; + + // aapt resource value: 0x7f0a00e6 + public const int TextAppearance_AppCompat_Widget_ActionBar_Title = 2131362022; + + // aapt resource value: 0x7f0a00e7 + public const int TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = 2131362023; + + // aapt resource value: 0x7f0a00e8 + public const int TextAppearance_AppCompat_Widget_ActionMode_Subtitle = 2131362024; + + // aapt resource value: 0x7f0a00e9 + public const int TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse = 2131362025; + + // aapt resource value: 0x7f0a00ea + public const int TextAppearance_AppCompat_Widget_ActionMode_Title = 2131362026; + + // aapt resource value: 0x7f0a00eb + public const int TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse = 2131362027; + + // aapt resource value: 0x7f0a00ec + public const int TextAppearance_AppCompat_Widget_Button = 2131362028; + + // aapt resource value: 0x7f0a00ed + public const int TextAppearance_AppCompat_Widget_Button_Borderless_Colored = 2131362029; + + // aapt resource value: 0x7f0a00ee + public const int TextAppearance_AppCompat_Widget_Button_Colored = 2131362030; + + // aapt resource value: 0x7f0a00ef + public const int TextAppearance_AppCompat_Widget_Button_Inverse = 2131362031; + + // aapt resource value: 0x7f0a00f0 + public const int TextAppearance_AppCompat_Widget_DropDownItem = 2131362032; + + // aapt resource value: 0x7f0a00f1 + public const int TextAppearance_AppCompat_Widget_PopupMenu_Header = 2131362033; + + // aapt resource value: 0x7f0a00f2 + public const int TextAppearance_AppCompat_Widget_PopupMenu_Large = 2131362034; + + // aapt resource value: 0x7f0a00f3 + public const int TextAppearance_AppCompat_Widget_PopupMenu_Small = 2131362035; + + // aapt resource value: 0x7f0a00f4 + public const int TextAppearance_AppCompat_Widget_Switch = 2131362036; + + // aapt resource value: 0x7f0a00f5 + public const int TextAppearance_AppCompat_Widget_TextView_SpinnerItem = 2131362037; + + // aapt resource value: 0x7f0a0179 + public const int TextAppearance_Compat_Notification = 2131362169; + + // aapt resource value: 0x7f0a017a + public const int TextAppearance_Compat_Notification_Info = 2131362170; + + // aapt resource value: 0x7f0a0156 + public const int TextAppearance_Compat_Notification_Info_Media = 2131362134; + + // aapt resource value: 0x7f0a017f + public const int TextAppearance_Compat_Notification_Line2 = 2131362175; + + // aapt resource value: 0x7f0a015a + public const int TextAppearance_Compat_Notification_Line2_Media = 2131362138; + + // aapt resource value: 0x7f0a0157 + public const int TextAppearance_Compat_Notification_Media = 2131362135; + + // aapt resource value: 0x7f0a017b + public const int TextAppearance_Compat_Notification_Time = 2131362171; + + // aapt resource value: 0x7f0a0158 + public const int TextAppearance_Compat_Notification_Time_Media = 2131362136; + + // aapt resource value: 0x7f0a017c + public const int TextAppearance_Compat_Notification_Title = 2131362172; + + // aapt resource value: 0x7f0a0159 + public const int TextAppearance_Compat_Notification_Title_Media = 2131362137; + + // aapt resource value: 0x7f0a0162 + public const int TextAppearance_Design_CollapsingToolbar_Expanded = 2131362146; + + // aapt resource value: 0x7f0a0163 + public const int TextAppearance_Design_Counter = 2131362147; + + // aapt resource value: 0x7f0a0164 + public const int TextAppearance_Design_Counter_Overflow = 2131362148; + + // aapt resource value: 0x7f0a0165 + public const int TextAppearance_Design_Error = 2131362149; + + // aapt resource value: 0x7f0a0166 + public const int TextAppearance_Design_Hint = 2131362150; + + // aapt resource value: 0x7f0a0167 + public const int TextAppearance_Design_Snackbar_Message = 2131362151; + + // aapt resource value: 0x7f0a0168 + public const int TextAppearance_Design_Tab = 2131362152; + + // aapt resource value: 0x7f0a00f6 + public const int TextAppearance_Widget_AppCompat_ExpandedMenu_Item = 2131362038; + + // aapt resource value: 0x7f0a00f7 + public const int TextAppearance_Widget_AppCompat_Toolbar_Subtitle = 2131362039; + + // aapt resource value: 0x7f0a00f8 + public const int TextAppearance_Widget_AppCompat_Toolbar_Title = 2131362040; + + // aapt resource value: 0x7f0a00f9 + public const int Theme_AppCompat = 2131362041; + + // aapt resource value: 0x7f0a00fa + public const int Theme_AppCompat_CompactMenu = 2131362042; + + // aapt resource value: 0x7f0a0004 + public const int Theme_AppCompat_DayNight = 2131361796; + + // aapt resource value: 0x7f0a0005 + public const int Theme_AppCompat_DayNight_DarkActionBar = 2131361797; + + // aapt resource value: 0x7f0a0006 + public const int Theme_AppCompat_DayNight_Dialog = 2131361798; + + // aapt resource value: 0x7f0a0007 + public const int Theme_AppCompat_DayNight_Dialog_Alert = 2131361799; + + // aapt resource value: 0x7f0a0008 + public const int Theme_AppCompat_DayNight_Dialog_MinWidth = 2131361800; + + // aapt resource value: 0x7f0a0009 + public const int Theme_AppCompat_DayNight_DialogWhenLarge = 2131361801; + + // aapt resource value: 0x7f0a000a + public const int Theme_AppCompat_DayNight_NoActionBar = 2131361802; + + // aapt resource value: 0x7f0a00fb + public const int Theme_AppCompat_Dialog = 2131362043; + + // aapt resource value: 0x7f0a00fc + public const int Theme_AppCompat_Dialog_Alert = 2131362044; + + // aapt resource value: 0x7f0a00fd + public const int Theme_AppCompat_Dialog_MinWidth = 2131362045; + + // aapt resource value: 0x7f0a00fe + public const int Theme_AppCompat_DialogWhenLarge = 2131362046; + + // aapt resource value: 0x7f0a00ff + public const int Theme_AppCompat_Light = 2131362047; + + // aapt resource value: 0x7f0a0100 + public const int Theme_AppCompat_Light_DarkActionBar = 2131362048; + + // aapt resource value: 0x7f0a0101 + public const int Theme_AppCompat_Light_Dialog = 2131362049; + + // aapt resource value: 0x7f0a0102 + public const int Theme_AppCompat_Light_Dialog_Alert = 2131362050; + + // aapt resource value: 0x7f0a0103 + public const int Theme_AppCompat_Light_Dialog_MinWidth = 2131362051; + + // aapt resource value: 0x7f0a0104 + public const int Theme_AppCompat_Light_DialogWhenLarge = 2131362052; + + // aapt resource value: 0x7f0a0105 + public const int Theme_AppCompat_Light_NoActionBar = 2131362053; + + // aapt resource value: 0x7f0a0106 + public const int Theme_AppCompat_NoActionBar = 2131362054; + + // aapt resource value: 0x7f0a0169 + public const int Theme_Design = 2131362153; + + // aapt resource value: 0x7f0a016a + public const int Theme_Design_BottomSheetDialog = 2131362154; + + // aapt resource value: 0x7f0a016b + public const int Theme_Design_Light = 2131362155; + + // aapt resource value: 0x7f0a016c + public const int Theme_Design_Light_BottomSheetDialog = 2131362156; + + // aapt resource value: 0x7f0a016d + public const int Theme_Design_Light_NoActionBar = 2131362157; + + // aapt resource value: 0x7f0a016e + public const int Theme_Design_NoActionBar = 2131362158; + + // aapt resource value: 0x7f0a0107 + public const int ThemeOverlay_AppCompat = 2131362055; + + // aapt resource value: 0x7f0a0108 + public const int ThemeOverlay_AppCompat_ActionBar = 2131362056; + + // aapt resource value: 0x7f0a0109 + public const int ThemeOverlay_AppCompat_Dark = 2131362057; + + // aapt resource value: 0x7f0a010a + public const int ThemeOverlay_AppCompat_Dark_ActionBar = 2131362058; + + // aapt resource value: 0x7f0a010b + public const int ThemeOverlay_AppCompat_Dialog = 2131362059; + + // aapt resource value: 0x7f0a010c + public const int ThemeOverlay_AppCompat_Dialog_Alert = 2131362060; + + // aapt resource value: 0x7f0a010d + public const int ThemeOverlay_AppCompat_Light = 2131362061; + + // aapt resource value: 0x7f0a010e + public const int Widget_AppCompat_ActionBar = 2131362062; + + // aapt resource value: 0x7f0a010f + public const int Widget_AppCompat_ActionBar_Solid = 2131362063; + + // aapt resource value: 0x7f0a0110 + public const int Widget_AppCompat_ActionBar_TabBar = 2131362064; + + // aapt resource value: 0x7f0a0111 + public const int Widget_AppCompat_ActionBar_TabText = 2131362065; + + // aapt resource value: 0x7f0a0112 + public const int Widget_AppCompat_ActionBar_TabView = 2131362066; + + // aapt resource value: 0x7f0a0113 + public const int Widget_AppCompat_ActionButton = 2131362067; + + // aapt resource value: 0x7f0a0114 + public const int Widget_AppCompat_ActionButton_CloseMode = 2131362068; + + // aapt resource value: 0x7f0a0115 + public const int Widget_AppCompat_ActionButton_Overflow = 2131362069; + + // aapt resource value: 0x7f0a0116 + public const int Widget_AppCompat_ActionMode = 2131362070; + + // aapt resource value: 0x7f0a0117 + public const int Widget_AppCompat_ActivityChooserView = 2131362071; + + // aapt resource value: 0x7f0a0118 + public const int Widget_AppCompat_AutoCompleteTextView = 2131362072; + + // aapt resource value: 0x7f0a0119 + public const int Widget_AppCompat_Button = 2131362073; + + // aapt resource value: 0x7f0a011a + public const int Widget_AppCompat_Button_Borderless = 2131362074; + + // aapt resource value: 0x7f0a011b + public const int Widget_AppCompat_Button_Borderless_Colored = 2131362075; + + // aapt resource value: 0x7f0a011c + public const int Widget_AppCompat_Button_ButtonBar_AlertDialog = 2131362076; + + // aapt resource value: 0x7f0a011d + public const int Widget_AppCompat_Button_Colored = 2131362077; + + // aapt resource value: 0x7f0a011e + public const int Widget_AppCompat_Button_Small = 2131362078; + + // aapt resource value: 0x7f0a011f + public const int Widget_AppCompat_ButtonBar = 2131362079; + + // aapt resource value: 0x7f0a0120 + public const int Widget_AppCompat_ButtonBar_AlertDialog = 2131362080; + + // aapt resource value: 0x7f0a0121 + public const int Widget_AppCompat_CompoundButton_CheckBox = 2131362081; + + // aapt resource value: 0x7f0a0122 + public const int Widget_AppCompat_CompoundButton_RadioButton = 2131362082; + + // aapt resource value: 0x7f0a0123 + public const int Widget_AppCompat_CompoundButton_Switch = 2131362083; + + // aapt resource value: 0x7f0a0124 + public const int Widget_AppCompat_DrawerArrowToggle = 2131362084; + + // aapt resource value: 0x7f0a0125 + public const int Widget_AppCompat_DropDownItem_Spinner = 2131362085; + + // aapt resource value: 0x7f0a0126 + public const int Widget_AppCompat_EditText = 2131362086; + + // aapt resource value: 0x7f0a0127 + public const int Widget_AppCompat_ImageButton = 2131362087; + + // aapt resource value: 0x7f0a0128 + public const int Widget_AppCompat_Light_ActionBar = 2131362088; + + // aapt resource value: 0x7f0a0129 + public const int Widget_AppCompat_Light_ActionBar_Solid = 2131362089; + + // aapt resource value: 0x7f0a012a + public const int Widget_AppCompat_Light_ActionBar_Solid_Inverse = 2131362090; + + // aapt resource value: 0x7f0a012b + public const int Widget_AppCompat_Light_ActionBar_TabBar = 2131362091; + + // aapt resource value: 0x7f0a012c + public const int Widget_AppCompat_Light_ActionBar_TabBar_Inverse = 2131362092; + + // aapt resource value: 0x7f0a012d + public const int Widget_AppCompat_Light_ActionBar_TabText = 2131362093; + + // aapt resource value: 0x7f0a012e + public const int Widget_AppCompat_Light_ActionBar_TabText_Inverse = 2131362094; + + // aapt resource value: 0x7f0a012f + public const int Widget_AppCompat_Light_ActionBar_TabView = 2131362095; + + // aapt resource value: 0x7f0a0130 + public const int Widget_AppCompat_Light_ActionBar_TabView_Inverse = 2131362096; + + // aapt resource value: 0x7f0a0131 + public const int Widget_AppCompat_Light_ActionButton = 2131362097; + + // aapt resource value: 0x7f0a0132 + public const int Widget_AppCompat_Light_ActionButton_CloseMode = 2131362098; + + // aapt resource value: 0x7f0a0133 + public const int Widget_AppCompat_Light_ActionButton_Overflow = 2131362099; + + // aapt resource value: 0x7f0a0134 + public const int Widget_AppCompat_Light_ActionMode_Inverse = 2131362100; + + // aapt resource value: 0x7f0a0135 + public const int Widget_AppCompat_Light_ActivityChooserView = 2131362101; + + // aapt resource value: 0x7f0a0136 + public const int Widget_AppCompat_Light_AutoCompleteTextView = 2131362102; + + // aapt resource value: 0x7f0a0137 + public const int Widget_AppCompat_Light_DropDownItem_Spinner = 2131362103; + + // aapt resource value: 0x7f0a0138 + public const int Widget_AppCompat_Light_ListPopupWindow = 2131362104; + + // aapt resource value: 0x7f0a0139 + public const int Widget_AppCompat_Light_ListView_DropDown = 2131362105; + + // aapt resource value: 0x7f0a013a + public const int Widget_AppCompat_Light_PopupMenu = 2131362106; + + // aapt resource value: 0x7f0a013b + public const int Widget_AppCompat_Light_PopupMenu_Overflow = 2131362107; + + // aapt resource value: 0x7f0a013c + public const int Widget_AppCompat_Light_SearchView = 2131362108; + + // aapt resource value: 0x7f0a013d + public const int Widget_AppCompat_Light_Spinner_DropDown_ActionBar = 2131362109; + + // aapt resource value: 0x7f0a013e + public const int Widget_AppCompat_ListMenuView = 2131362110; + + // aapt resource value: 0x7f0a013f + public const int Widget_AppCompat_ListPopupWindow = 2131362111; + + // aapt resource value: 0x7f0a0140 + public const int Widget_AppCompat_ListView = 2131362112; + + // aapt resource value: 0x7f0a0141 + public const int Widget_AppCompat_ListView_DropDown = 2131362113; + + // aapt resource value: 0x7f0a0142 + public const int Widget_AppCompat_ListView_Menu = 2131362114; + + // aapt resource value: 0x7f0a0143 + public const int Widget_AppCompat_PopupMenu = 2131362115; + + // aapt resource value: 0x7f0a0144 + public const int Widget_AppCompat_PopupMenu_Overflow = 2131362116; + + // aapt resource value: 0x7f0a0145 + public const int Widget_AppCompat_PopupWindow = 2131362117; + + // aapt resource value: 0x7f0a0146 + public const int Widget_AppCompat_ProgressBar = 2131362118; + + // aapt resource value: 0x7f0a0147 + public const int Widget_AppCompat_ProgressBar_Horizontal = 2131362119; + + // aapt resource value: 0x7f0a0148 + public const int Widget_AppCompat_RatingBar = 2131362120; + + // aapt resource value: 0x7f0a0149 + public const int Widget_AppCompat_RatingBar_Indicator = 2131362121; + + // aapt resource value: 0x7f0a014a + public const int Widget_AppCompat_RatingBar_Small = 2131362122; + + // aapt resource value: 0x7f0a014b + public const int Widget_AppCompat_SearchView = 2131362123; + + // aapt resource value: 0x7f0a014c + public const int Widget_AppCompat_SearchView_ActionBar = 2131362124; + + // aapt resource value: 0x7f0a014d + public const int Widget_AppCompat_SeekBar = 2131362125; + + // aapt resource value: 0x7f0a014e + public const int Widget_AppCompat_SeekBar_Discrete = 2131362126; + + // aapt resource value: 0x7f0a014f + public const int Widget_AppCompat_Spinner = 2131362127; + + // aapt resource value: 0x7f0a0150 + public const int Widget_AppCompat_Spinner_DropDown = 2131362128; + + // aapt resource value: 0x7f0a0151 + public const int Widget_AppCompat_Spinner_DropDown_ActionBar = 2131362129; + + // aapt resource value: 0x7f0a0152 + public const int Widget_AppCompat_Spinner_Underlined = 2131362130; + + // aapt resource value: 0x7f0a0153 + public const int Widget_AppCompat_TextView_SpinnerItem = 2131362131; + + // aapt resource value: 0x7f0a0154 + public const int Widget_AppCompat_Toolbar = 2131362132; + + // aapt resource value: 0x7f0a0155 + public const int Widget_AppCompat_Toolbar_Button_Navigation = 2131362133; + + // aapt resource value: 0x7f0a017d + public const int Widget_Compat_NotificationActionContainer = 2131362173; + + // aapt resource value: 0x7f0a017e + public const int Widget_Compat_NotificationActionText = 2131362174; + + // aapt resource value: 0x7f0a016f + public const int Widget_Design_AppBarLayout = 2131362159; + + // aapt resource value: 0x7f0a0170 + public const int Widget_Design_BottomNavigationView = 2131362160; + + // aapt resource value: 0x7f0a0171 + public const int Widget_Design_BottomSheet_Modal = 2131362161; + + // aapt resource value: 0x7f0a0172 + public const int Widget_Design_CollapsingToolbar = 2131362162; + + // aapt resource value: 0x7f0a0173 + public const int Widget_Design_CoordinatorLayout = 2131362163; + + // aapt resource value: 0x7f0a0174 + public const int Widget_Design_FloatingActionButton = 2131362164; + + // aapt resource value: 0x7f0a0175 + public const int Widget_Design_NavigationView = 2131362165; + + // aapt resource value: 0x7f0a0176 + public const int Widget_Design_ScrimInsetsFrameLayout = 2131362166; + + // aapt resource value: 0x7f0a0177 + public const int Widget_Design_Snackbar = 2131362167; + + // aapt resource value: 0x7f0a015b + public const int Widget_Design_TabLayout = 2131362139; + + // aapt resource value: 0x7f0a0178 + public const int Widget_Design_TextInputLayout = 2131362168; + + static Style() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Style() + { + } + } + + public partial class Styleable + { + + public static int[] ActionBar = new int[] { + 2130771978, + 2130771980, + 2130771981, + 2130771982, + 2130771983, + 2130771984, + 2130771985, + 2130771986, + 2130771987, + 2130771988, + 2130771989, + 2130771990, + 2130771991, + 2130771992, + 2130771993, + 2130771994, + 2130771995, + 2130771996, + 2130771997, + 2130771998, + 2130771999, + 2130772000, + 2130772001, + 2130772002, + 2130772003, + 2130772004, + 2130772005, + 2130772006, + 2130772076}; + + // aapt resource value: 10 + public const int ActionBar_background = 10; + + // aapt resource value: 12 + public const int ActionBar_backgroundSplit = 12; + + // aapt resource value: 11 + public const int ActionBar_backgroundStacked = 11; + + // aapt resource value: 21 + public const int ActionBar_contentInsetEnd = 21; + + // aapt resource value: 25 + public const int ActionBar_contentInsetEndWithActions = 25; + + // aapt resource value: 22 + public const int ActionBar_contentInsetLeft = 22; + + // aapt resource value: 23 + public const int ActionBar_contentInsetRight = 23; + + // aapt resource value: 20 + public const int ActionBar_contentInsetStart = 20; + + // aapt resource value: 24 + public const int ActionBar_contentInsetStartWithNavigation = 24; + + // aapt resource value: 13 + public const int ActionBar_customNavigationLayout = 13; + + // aapt resource value: 3 + public const int ActionBar_displayOptions = 3; + + // aapt resource value: 9 + public const int ActionBar_divider = 9; + + // aapt resource value: 26 + public const int ActionBar_elevation = 26; + + // aapt resource value: 0 + public const int ActionBar_height = 0; + + // aapt resource value: 19 + public const int ActionBar_hideOnContentScroll = 19; + + // aapt resource value: 28 + public const int ActionBar_homeAsUpIndicator = 28; + + // aapt resource value: 14 + public const int ActionBar_homeLayout = 14; + + // aapt resource value: 7 + public const int ActionBar_icon = 7; + + // aapt resource value: 16 + public const int ActionBar_indeterminateProgressStyle = 16; + + // aapt resource value: 18 + public const int ActionBar_itemPadding = 18; + + // aapt resource value: 8 + public const int ActionBar_logo = 8; + + // aapt resource value: 2 + public const int ActionBar_navigationMode = 2; + + // aapt resource value: 27 + public const int ActionBar_popupTheme = 27; + + // aapt resource value: 17 + public const int ActionBar_progressBarPadding = 17; + + // aapt resource value: 15 + public const int ActionBar_progressBarStyle = 15; + + // aapt resource value: 4 + public const int ActionBar_subtitle = 4; + + // aapt resource value: 6 + public const int ActionBar_subtitleTextStyle = 6; + + // aapt resource value: 1 + public const int ActionBar_title = 1; + + // aapt resource value: 5 + public const int ActionBar_titleTextStyle = 5; + + public static int[] ActionBarLayout = new int[] { + 16842931}; + + // aapt resource value: 0 + public const int ActionBarLayout_android_layout_gravity = 0; + + public static int[] ActionMenuItemView = new int[] { + 16843071}; + + // aapt resource value: 0 + public const int ActionMenuItemView_android_minWidth = 0; + + public static int[] ActionMenuView; + + public static int[] ActionMode = new int[] { + 2130771978, + 2130771984, + 2130771985, + 2130771989, + 2130771991, + 2130772007}; + + // aapt resource value: 3 + public const int ActionMode_background = 3; + + // aapt resource value: 4 + public const int ActionMode_backgroundSplit = 4; + + // aapt resource value: 5 + public const int ActionMode_closeItemLayout = 5; + + // aapt resource value: 0 + public const int ActionMode_height = 0; + + // aapt resource value: 2 + public const int ActionMode_subtitleTextStyle = 2; + + // aapt resource value: 1 + public const int ActionMode_titleTextStyle = 1; + + public static int[] ActivityChooserView = new int[] { + 2130772008, + 2130772009}; + + // aapt resource value: 1 + public const int ActivityChooserView_expandActivityOverflowButtonDrawable = 1; + + // aapt resource value: 0 + public const int ActivityChooserView_initialActivityCount = 0; + + public static int[] AlertDialog = new int[] { + 16842994, + 2130772010, + 2130772011, + 2130772012, + 2130772013, + 2130772014, + 2130772015}; + + // aapt resource value: 0 + public const int AlertDialog_android_layout = 0; + + // aapt resource value: 1 + public const int AlertDialog_buttonPanelSideLayout = 1; + + // aapt resource value: 5 + public const int AlertDialog_listItemLayout = 5; + + // aapt resource value: 2 + public const int AlertDialog_listLayout = 2; + + // aapt resource value: 3 + public const int AlertDialog_multiChoiceItemLayout = 3; + + // aapt resource value: 6 + public const int AlertDialog_showTitle = 6; + + // aapt resource value: 4 + public const int AlertDialog_singleChoiceItemLayout = 4; + + public static int[] AppBarLayout = new int[] { + 16842964, + 16843919, + 16844096, + 2130772005, + 2130772223}; + + // aapt resource value: 0 + public const int AppBarLayout_android_background = 0; + + // aapt resource value: 2 + public const int AppBarLayout_android_keyboardNavigationCluster = 2; + + // aapt resource value: 1 + public const int AppBarLayout_android_touchscreenBlocksFocus = 1; + + // aapt resource value: 3 + public const int AppBarLayout_elevation = 3; + + // aapt resource value: 4 + public const int AppBarLayout_expanded = 4; + + public static int[] AppBarLayoutStates = new int[] { + 2130772224, + 2130772225}; + + // aapt resource value: 0 + public const int AppBarLayoutStates_state_collapsed = 0; + + // aapt resource value: 1 + public const int AppBarLayoutStates_state_collapsible = 1; + + public static int[] AppBarLayout_Layout = new int[] { + 2130772226, + 2130772227}; + + // aapt resource value: 0 + public const int AppBarLayout_Layout_layout_scrollFlags = 0; + + // aapt resource value: 1 + public const int AppBarLayout_Layout_layout_scrollInterpolator = 1; + + public static int[] AppCompatImageView = new int[] { + 16843033, + 2130772016, + 2130772017, + 2130772018}; + + // aapt resource value: 0 + public const int AppCompatImageView_android_src = 0; + + // aapt resource value: 1 + public const int AppCompatImageView_srcCompat = 1; + + // aapt resource value: 2 + public const int AppCompatImageView_tint = 2; + + // aapt resource value: 3 + public const int AppCompatImageView_tintMode = 3; + + public static int[] AppCompatSeekBar = new int[] { + 16843074, + 2130772019, + 2130772020, + 2130772021}; + + // aapt resource value: 0 + public const int AppCompatSeekBar_android_thumb = 0; + + // aapt resource value: 1 + public const int AppCompatSeekBar_tickMark = 1; + + // aapt resource value: 2 + public const int AppCompatSeekBar_tickMarkTint = 2; + + // aapt resource value: 3 + public const int AppCompatSeekBar_tickMarkTintMode = 3; + + public static int[] AppCompatTextHelper = new int[] { + 16842804, + 16843117, + 16843118, + 16843119, + 16843120, + 16843666, + 16843667}; + + // aapt resource value: 2 + public const int AppCompatTextHelper_android_drawableBottom = 2; + + // aapt resource value: 6 + public const int AppCompatTextHelper_android_drawableEnd = 6; + + // aapt resource value: 3 + public const int AppCompatTextHelper_android_drawableLeft = 3; + + // aapt resource value: 4 + public const int AppCompatTextHelper_android_drawableRight = 4; + + // aapt resource value: 5 + public const int AppCompatTextHelper_android_drawableStart = 5; + + // aapt resource value: 1 + public const int AppCompatTextHelper_android_drawableTop = 1; + + // aapt resource value: 0 + public const int AppCompatTextHelper_android_textAppearance = 0; + + public static int[] AppCompatTextView = new int[] { + 16842804, + 2130772022, + 2130772023, + 2130772024, + 2130772025, + 2130772026, + 2130772027, + 2130772028}; + + // aapt resource value: 0 + public const int AppCompatTextView_android_textAppearance = 0; + + // aapt resource value: 6 + public const int AppCompatTextView_autoSizeMaxTextSize = 6; + + // aapt resource value: 5 + public const int AppCompatTextView_autoSizeMinTextSize = 5; + + // aapt resource value: 4 + public const int AppCompatTextView_autoSizePresetSizes = 4; + + // aapt resource value: 3 + public const int AppCompatTextView_autoSizeStepGranularity = 3; + + // aapt resource value: 2 + public const int AppCompatTextView_autoSizeTextType = 2; + + // aapt resource value: 7 + public const int AppCompatTextView_fontFamily = 7; + + // aapt resource value: 1 + public const int AppCompatTextView_textAllCaps = 1; + + public static int[] AppCompatTheme = new int[] { + 16842839, + 16842926, + 2130772029, + 2130772030, + 2130772031, + 2130772032, + 2130772033, + 2130772034, + 2130772035, + 2130772036, + 2130772037, + 2130772038, + 2130772039, + 2130772040, + 2130772041, + 2130772042, + 2130772043, + 2130772044, + 2130772045, + 2130772046, + 2130772047, + 2130772048, + 2130772049, + 2130772050, + 2130772051, + 2130772052, + 2130772053, + 2130772054, + 2130772055, + 2130772056, + 2130772057, + 2130772058, + 2130772059, + 2130772060, + 2130772061, + 2130772062, + 2130772063, + 2130772064, + 2130772065, + 2130772066, + 2130772067, + 2130772068, + 2130772069, + 2130772070, + 2130772071, + 2130772072, + 2130772073, + 2130772074, + 2130772075, + 2130772076, + 2130772077, + 2130772078, + 2130772079, + 2130772080, + 2130772081, + 2130772082, + 2130772083, + 2130772084, + 2130772085, + 2130772086, + 2130772087, + 2130772088, + 2130772089, + 2130772090, + 2130772091, + 2130772092, + 2130772093, + 2130772094, + 2130772095, + 2130772096, + 2130772097, + 2130772098, + 2130772099, + 2130772100, + 2130772101, + 2130772102, + 2130772103, + 2130772104, + 2130772105, + 2130772106, + 2130772107, + 2130772108, + 2130772109, + 2130772110, + 2130772111, + 2130772112, + 2130772113, + 2130772114, + 2130772115, + 2130772116, + 2130772117, + 2130772118, + 2130772119, + 2130772120, + 2130772121, + 2130772122, + 2130772123, + 2130772124, + 2130772125, + 2130772126, + 2130772127, + 2130772128, + 2130772129, + 2130772130, + 2130772131, + 2130772132, + 2130772133, + 2130772134, + 2130772135, + 2130772136, + 2130772137, + 2130772138, + 2130772139, + 2130772140, + 2130772141, + 2130772142, + 2130772143, + 2130772144, + 2130772145}; + + // aapt resource value: 23 + public const int AppCompatTheme_actionBarDivider = 23; + + // aapt resource value: 24 + public const int AppCompatTheme_actionBarItemBackground = 24; + + // aapt resource value: 17 + public const int AppCompatTheme_actionBarPopupTheme = 17; + + // aapt resource value: 22 + public const int AppCompatTheme_actionBarSize = 22; + + // aapt resource value: 19 + public const int AppCompatTheme_actionBarSplitStyle = 19; + + // aapt resource value: 18 + public const int AppCompatTheme_actionBarStyle = 18; + + // aapt resource value: 13 + public const int AppCompatTheme_actionBarTabBarStyle = 13; + + // aapt resource value: 12 + public const int AppCompatTheme_actionBarTabStyle = 12; + + // aapt resource value: 14 + public const int AppCompatTheme_actionBarTabTextStyle = 14; + + // aapt resource value: 20 + public const int AppCompatTheme_actionBarTheme = 20; + + // aapt resource value: 21 + public const int AppCompatTheme_actionBarWidgetTheme = 21; + + // aapt resource value: 50 + public const int AppCompatTheme_actionButtonStyle = 50; + + // aapt resource value: 46 + public const int AppCompatTheme_actionDropDownStyle = 46; + + // aapt resource value: 25 + public const int AppCompatTheme_actionMenuTextAppearance = 25; + + // aapt resource value: 26 + public const int AppCompatTheme_actionMenuTextColor = 26; + + // aapt resource value: 29 + public const int AppCompatTheme_actionModeBackground = 29; + + // aapt resource value: 28 + public const int AppCompatTheme_actionModeCloseButtonStyle = 28; + + // aapt resource value: 31 + public const int AppCompatTheme_actionModeCloseDrawable = 31; + + // aapt resource value: 33 + public const int AppCompatTheme_actionModeCopyDrawable = 33; + + // aapt resource value: 32 + public const int AppCompatTheme_actionModeCutDrawable = 32; + + // aapt resource value: 37 + public const int AppCompatTheme_actionModeFindDrawable = 37; + + // aapt resource value: 34 + public const int AppCompatTheme_actionModePasteDrawable = 34; + + // aapt resource value: 39 + public const int AppCompatTheme_actionModePopupWindowStyle = 39; + + // aapt resource value: 35 + public const int AppCompatTheme_actionModeSelectAllDrawable = 35; + + // aapt resource value: 36 + public const int AppCompatTheme_actionModeShareDrawable = 36; + + // aapt resource value: 30 + public const int AppCompatTheme_actionModeSplitBackground = 30; + + // aapt resource value: 27 + public const int AppCompatTheme_actionModeStyle = 27; + + // aapt resource value: 38 + public const int AppCompatTheme_actionModeWebSearchDrawable = 38; + + // aapt resource value: 15 + public const int AppCompatTheme_actionOverflowButtonStyle = 15; + + // aapt resource value: 16 + public const int AppCompatTheme_actionOverflowMenuStyle = 16; + + // aapt resource value: 58 + public const int AppCompatTheme_activityChooserViewStyle = 58; + + // aapt resource value: 95 + public const int AppCompatTheme_alertDialogButtonGroupStyle = 95; + + // aapt resource value: 96 + public const int AppCompatTheme_alertDialogCenterButtons = 96; + + // aapt resource value: 94 + public const int AppCompatTheme_alertDialogStyle = 94; + + // aapt resource value: 97 + public const int AppCompatTheme_alertDialogTheme = 97; + + // aapt resource value: 1 + public const int AppCompatTheme_android_windowAnimationStyle = 1; + + // aapt resource value: 0 + public const int AppCompatTheme_android_windowIsFloating = 0; + + // aapt resource value: 102 + public const int AppCompatTheme_autoCompleteTextViewStyle = 102; + + // aapt resource value: 55 + public const int AppCompatTheme_borderlessButtonStyle = 55; + + // aapt resource value: 52 + public const int AppCompatTheme_buttonBarButtonStyle = 52; + + // aapt resource value: 100 + public const int AppCompatTheme_buttonBarNegativeButtonStyle = 100; + + // aapt resource value: 101 + public const int AppCompatTheme_buttonBarNeutralButtonStyle = 101; + + // aapt resource value: 99 + public const int AppCompatTheme_buttonBarPositiveButtonStyle = 99; + + // aapt resource value: 51 + public const int AppCompatTheme_buttonBarStyle = 51; + + // aapt resource value: 103 + public const int AppCompatTheme_buttonStyle = 103; + + // aapt resource value: 104 + public const int AppCompatTheme_buttonStyleSmall = 104; + + // aapt resource value: 105 + public const int AppCompatTheme_checkboxStyle = 105; + + // aapt resource value: 106 + public const int AppCompatTheme_checkedTextViewStyle = 106; + + // aapt resource value: 86 + public const int AppCompatTheme_colorAccent = 86; + + // aapt resource value: 93 + public const int AppCompatTheme_colorBackgroundFloating = 93; + + // aapt resource value: 90 + public const int AppCompatTheme_colorButtonNormal = 90; + + // aapt resource value: 88 + public const int AppCompatTheme_colorControlActivated = 88; + + // aapt resource value: 89 + public const int AppCompatTheme_colorControlHighlight = 89; + + // aapt resource value: 87 + public const int AppCompatTheme_colorControlNormal = 87; + + // aapt resource value: 118 + public const int AppCompatTheme_colorError = 118; + + // aapt resource value: 84 + public const int AppCompatTheme_colorPrimary = 84; + + // aapt resource value: 85 + public const int AppCompatTheme_colorPrimaryDark = 85; + + // aapt resource value: 91 + public const int AppCompatTheme_colorSwitchThumbNormal = 91; + + // aapt resource value: 92 + public const int AppCompatTheme_controlBackground = 92; + + // aapt resource value: 44 + public const int AppCompatTheme_dialogPreferredPadding = 44; + + // aapt resource value: 43 + public const int AppCompatTheme_dialogTheme = 43; + + // aapt resource value: 57 + public const int AppCompatTheme_dividerHorizontal = 57; + + // aapt resource value: 56 + public const int AppCompatTheme_dividerVertical = 56; + + // aapt resource value: 75 + public const int AppCompatTheme_dropDownListViewStyle = 75; + + // aapt resource value: 47 + public const int AppCompatTheme_dropdownListPreferredItemHeight = 47; + + // aapt resource value: 64 + public const int AppCompatTheme_editTextBackground = 64; + + // aapt resource value: 63 + public const int AppCompatTheme_editTextColor = 63; + + // aapt resource value: 107 + public const int AppCompatTheme_editTextStyle = 107; + + // aapt resource value: 49 + public const int AppCompatTheme_homeAsUpIndicator = 49; + + // aapt resource value: 65 + public const int AppCompatTheme_imageButtonStyle = 65; + + // aapt resource value: 83 + public const int AppCompatTheme_listChoiceBackgroundIndicator = 83; + + // aapt resource value: 45 + public const int AppCompatTheme_listDividerAlertDialog = 45; + + // aapt resource value: 115 + public const int AppCompatTheme_listMenuViewStyle = 115; + + // aapt resource value: 76 + public const int AppCompatTheme_listPopupWindowStyle = 76; + + // aapt resource value: 70 + public const int AppCompatTheme_listPreferredItemHeight = 70; + + // aapt resource value: 72 + public const int AppCompatTheme_listPreferredItemHeightLarge = 72; + + // aapt resource value: 71 + public const int AppCompatTheme_listPreferredItemHeightSmall = 71; + + // aapt resource value: 73 + public const int AppCompatTheme_listPreferredItemPaddingLeft = 73; + + // aapt resource value: 74 + public const int AppCompatTheme_listPreferredItemPaddingRight = 74; + + // aapt resource value: 80 + public const int AppCompatTheme_panelBackground = 80; + + // aapt resource value: 82 + public const int AppCompatTheme_panelMenuListTheme = 82; + + // aapt resource value: 81 + public const int AppCompatTheme_panelMenuListWidth = 81; + + // aapt resource value: 61 + public const int AppCompatTheme_popupMenuStyle = 61; + + // aapt resource value: 62 + public const int AppCompatTheme_popupWindowStyle = 62; + + // aapt resource value: 108 + public const int AppCompatTheme_radioButtonStyle = 108; + + // aapt resource value: 109 + public const int AppCompatTheme_ratingBarStyle = 109; + + // aapt resource value: 110 + public const int AppCompatTheme_ratingBarStyleIndicator = 110; + + // aapt resource value: 111 + public const int AppCompatTheme_ratingBarStyleSmall = 111; + + // aapt resource value: 69 + public const int AppCompatTheme_searchViewStyle = 69; + + // aapt resource value: 112 + public const int AppCompatTheme_seekBarStyle = 112; + + // aapt resource value: 53 + public const int AppCompatTheme_selectableItemBackground = 53; + + // aapt resource value: 54 + public const int AppCompatTheme_selectableItemBackgroundBorderless = 54; + + // aapt resource value: 48 + public const int AppCompatTheme_spinnerDropDownItemStyle = 48; + + // aapt resource value: 113 + public const int AppCompatTheme_spinnerStyle = 113; + + // aapt resource value: 114 + public const int AppCompatTheme_switchStyle = 114; + + // aapt resource value: 40 + public const int AppCompatTheme_textAppearanceLargePopupMenu = 40; + + // aapt resource value: 77 + public const int AppCompatTheme_textAppearanceListItem = 77; + + // aapt resource value: 78 + public const int AppCompatTheme_textAppearanceListItemSecondary = 78; + + // aapt resource value: 79 + public const int AppCompatTheme_textAppearanceListItemSmall = 79; + + // aapt resource value: 42 + public const int AppCompatTheme_textAppearancePopupMenuHeader = 42; + + // aapt resource value: 67 + public const int AppCompatTheme_textAppearanceSearchResultSubtitle = 67; + + // aapt resource value: 66 + public const int AppCompatTheme_textAppearanceSearchResultTitle = 66; + + // aapt resource value: 41 + public const int AppCompatTheme_textAppearanceSmallPopupMenu = 41; + + // aapt resource value: 98 + public const int AppCompatTheme_textColorAlertDialogListItem = 98; + + // aapt resource value: 68 + public const int AppCompatTheme_textColorSearchUrl = 68; + + // aapt resource value: 60 + public const int AppCompatTheme_toolbarNavigationButtonStyle = 60; + + // aapt resource value: 59 + public const int AppCompatTheme_toolbarStyle = 59; + + // aapt resource value: 117 + public const int AppCompatTheme_tooltipForegroundColor = 117; + + // aapt resource value: 116 + public const int AppCompatTheme_tooltipFrameBackground = 116; + + // aapt resource value: 2 + public const int AppCompatTheme_windowActionBar = 2; + + // aapt resource value: 4 + public const int AppCompatTheme_windowActionBarOverlay = 4; + + // aapt resource value: 5 + public const int AppCompatTheme_windowActionModeOverlay = 5; + + // aapt resource value: 9 + public const int AppCompatTheme_windowFixedHeightMajor = 9; + + // aapt resource value: 7 + public const int AppCompatTheme_windowFixedHeightMinor = 7; + + // aapt resource value: 6 + public const int AppCompatTheme_windowFixedWidthMajor = 6; + + // aapt resource value: 8 + public const int AppCompatTheme_windowFixedWidthMinor = 8; + + // aapt resource value: 10 + public const int AppCompatTheme_windowMinWidthMajor = 10; + + // aapt resource value: 11 + public const int AppCompatTheme_windowMinWidthMinor = 11; + + // aapt resource value: 3 + public const int AppCompatTheme_windowNoTitle = 3; + + public static int[] BottomNavigationView = new int[] { + 2130772005, + 2130772266, + 2130772267, + 2130772268, + 2130772269}; + + // aapt resource value: 0 + public const int BottomNavigationView_elevation = 0; + + // aapt resource value: 4 + public const int BottomNavigationView_itemBackground = 4; + + // aapt resource value: 2 + public const int BottomNavigationView_itemIconTint = 2; + + // aapt resource value: 3 + public const int BottomNavigationView_itemTextColor = 3; + + // aapt resource value: 1 + public const int BottomNavigationView_menu = 1; + + public static int[] BottomSheetBehavior_Layout = new int[] { + 2130772228, + 2130772229, + 2130772230}; + + // aapt resource value: 1 + public const int BottomSheetBehavior_Layout_behavior_hideable = 1; + + // aapt resource value: 0 + public const int BottomSheetBehavior_Layout_behavior_peekHeight = 0; + + // aapt resource value: 2 + public const int BottomSheetBehavior_Layout_behavior_skipCollapsed = 2; + + public static int[] ButtonBarLayout = new int[] { + 2130772146}; + + // aapt resource value: 0 + public const int ButtonBarLayout_allowStacking = 0; + + public static int[] CollapsingToolbarLayout = new int[] { + 2130771980, + 2130772231, + 2130772232, + 2130772233, + 2130772234, + 2130772235, + 2130772236, + 2130772237, + 2130772238, + 2130772239, + 2130772240, + 2130772241, + 2130772242, + 2130772243, + 2130772244, + 2130772245}; + + // aapt resource value: 13 + public const int CollapsingToolbarLayout_collapsedTitleGravity = 13; + + // aapt resource value: 7 + public const int CollapsingToolbarLayout_collapsedTitleTextAppearance = 7; + + // aapt resource value: 8 + public const int CollapsingToolbarLayout_contentScrim = 8; + + // aapt resource value: 14 + public const int CollapsingToolbarLayout_expandedTitleGravity = 14; + + // aapt resource value: 1 + public const int CollapsingToolbarLayout_expandedTitleMargin = 1; + + // aapt resource value: 5 + public const int CollapsingToolbarLayout_expandedTitleMarginBottom = 5; + + // aapt resource value: 4 + public const int CollapsingToolbarLayout_expandedTitleMarginEnd = 4; + + // aapt resource value: 2 + public const int CollapsingToolbarLayout_expandedTitleMarginStart = 2; + + // aapt resource value: 3 + public const int CollapsingToolbarLayout_expandedTitleMarginTop = 3; + + // aapt resource value: 6 + public const int CollapsingToolbarLayout_expandedTitleTextAppearance = 6; + + // aapt resource value: 12 + public const int CollapsingToolbarLayout_scrimAnimationDuration = 12; + + // aapt resource value: 11 + public const int CollapsingToolbarLayout_scrimVisibleHeightTrigger = 11; + + // aapt resource value: 9 + public const int CollapsingToolbarLayout_statusBarScrim = 9; + + // aapt resource value: 0 + public const int CollapsingToolbarLayout_title = 0; + + // aapt resource value: 15 + public const int CollapsingToolbarLayout_titleEnabled = 15; + + // aapt resource value: 10 + public const int CollapsingToolbarLayout_toolbarId = 10; + + public static int[] CollapsingToolbarLayout_Layout = new int[] { + 2130772246, + 2130772247}; + + // aapt resource value: 0 + public const int CollapsingToolbarLayout_Layout_layout_collapseMode = 0; + + // aapt resource value: 1 + public const int CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier = 1; + + public static int[] ColorStateListItem = new int[] { + 16843173, + 16843551, + 2130772147}; + + // aapt resource value: 2 + public const int ColorStateListItem_alpha = 2; + + // aapt resource value: 1 + public const int ColorStateListItem_android_alpha = 1; + + // aapt resource value: 0 + public const int ColorStateListItem_android_color = 0; + + public static int[] CompoundButton = new int[] { + 16843015, + 2130772148, + 2130772149}; + + // aapt resource value: 0 + public const int CompoundButton_android_button = 0; + + // aapt resource value: 1 + public const int CompoundButton_buttonTint = 1; + + // aapt resource value: 2 + public const int CompoundButton_buttonTintMode = 2; + + public static int[] CoordinatorLayout = new int[] { + 2130772248, + 2130772249}; + + // aapt resource value: 0 + public const int CoordinatorLayout_keylines = 0; + + // aapt resource value: 1 + public const int CoordinatorLayout_statusBarBackground = 1; + + public static int[] CoordinatorLayout_Layout = new int[] { + 16842931, + 2130772250, + 2130772251, + 2130772252, + 2130772253, + 2130772254, + 2130772255}; + + // aapt resource value: 0 + public const int CoordinatorLayout_Layout_android_layout_gravity = 0; + + // aapt resource value: 2 + public const int CoordinatorLayout_Layout_layout_anchor = 2; + + // aapt resource value: 4 + public const int CoordinatorLayout_Layout_layout_anchorGravity = 4; + + // aapt resource value: 1 + public const int CoordinatorLayout_Layout_layout_behavior = 1; + + // aapt resource value: 6 + public const int CoordinatorLayout_Layout_layout_dodgeInsetEdges = 6; + + // aapt resource value: 5 + public const int CoordinatorLayout_Layout_layout_insetEdge = 5; + + // aapt resource value: 3 + public const int CoordinatorLayout_Layout_layout_keyline = 3; + + public static int[] DesignTheme = new int[] { + 2130772256, + 2130772257, + 2130772258}; + + // aapt resource value: 0 + public const int DesignTheme_bottomSheetDialogTheme = 0; + + // aapt resource value: 1 + public const int DesignTheme_bottomSheetStyle = 1; + + // aapt resource value: 2 + public const int DesignTheme_textColorError = 2; + + public static int[] DrawerArrowToggle = new int[] { + 2130772150, + 2130772151, + 2130772152, + 2130772153, + 2130772154, + 2130772155, + 2130772156, + 2130772157}; + + // aapt resource value: 4 + public const int DrawerArrowToggle_arrowHeadLength = 4; + + // aapt resource value: 5 + public const int DrawerArrowToggle_arrowShaftLength = 5; + + // aapt resource value: 6 + public const int DrawerArrowToggle_barLength = 6; + + // aapt resource value: 0 + public const int DrawerArrowToggle_color = 0; + + // aapt resource value: 2 + public const int DrawerArrowToggle_drawableSize = 2; + + // aapt resource value: 3 + public const int DrawerArrowToggle_gapBetweenBars = 3; + + // aapt resource value: 1 + public const int DrawerArrowToggle_spinBars = 1; + + // aapt resource value: 7 + public const int DrawerArrowToggle_thickness = 7; + + public static int[] FloatingActionButton = new int[] { + 2130772005, + 2130772221, + 2130772222, + 2130772259, + 2130772260, + 2130772261, + 2130772262, + 2130772263}; + + // aapt resource value: 1 + public const int FloatingActionButton_backgroundTint = 1; + + // aapt resource value: 2 + public const int FloatingActionButton_backgroundTintMode = 2; + + // aapt resource value: 6 + public const int FloatingActionButton_borderWidth = 6; + + // aapt resource value: 0 + public const int FloatingActionButton_elevation = 0; + + // aapt resource value: 4 + public const int FloatingActionButton_fabSize = 4; + + // aapt resource value: 5 + public const int FloatingActionButton_pressedTranslationZ = 5; + + // aapt resource value: 3 + public const int FloatingActionButton_rippleColor = 3; + + // aapt resource value: 7 + public const int FloatingActionButton_useCompatPadding = 7; + + public static int[] FloatingActionButton_Behavior_Layout = new int[] { + 2130772264}; + + // aapt resource value: 0 + public const int FloatingActionButton_Behavior_Layout_behavior_autoHide = 0; + + public static int[] FontFamily = new int[] { + 2130772305, + 2130772306, + 2130772307, + 2130772308, + 2130772309, + 2130772310}; + + // aapt resource value: 0 + public const int FontFamily_fontProviderAuthority = 0; + + // aapt resource value: 3 + public const int FontFamily_fontProviderCerts = 3; + + // aapt resource value: 4 + public const int FontFamily_fontProviderFetchStrategy = 4; + + // aapt resource value: 5 + public const int FontFamily_fontProviderFetchTimeout = 5; + + // aapt resource value: 1 + public const int FontFamily_fontProviderPackage = 1; + + // aapt resource value: 2 + public const int FontFamily_fontProviderQuery = 2; + + public static int[] FontFamilyFont = new int[] { + 16844082, + 16844083, + 16844095, + 2130772311, + 2130772312, + 2130772313}; + + // aapt resource value: 0 + public const int FontFamilyFont_android_font = 0; + + // aapt resource value: 2 + public const int FontFamilyFont_android_fontStyle = 2; + + // aapt resource value: 1 + public const int FontFamilyFont_android_fontWeight = 1; + + // aapt resource value: 4 + public const int FontFamilyFont_font = 4; + + // aapt resource value: 3 + public const int FontFamilyFont_fontStyle = 3; + + // aapt resource value: 5 + public const int FontFamilyFont_fontWeight = 5; + + public static int[] ForegroundLinearLayout = new int[] { + 16843017, + 16843264, + 2130772265}; + + // aapt resource value: 0 + public const int ForegroundLinearLayout_android_foreground = 0; + + // aapt resource value: 1 + public const int ForegroundLinearLayout_android_foregroundGravity = 1; + + // aapt resource value: 2 + public const int ForegroundLinearLayout_foregroundInsidePadding = 2; + + public static int[] LinearLayoutCompat = new int[] { + 16842927, + 16842948, + 16843046, + 16843047, + 16843048, + 2130771988, + 2130772158, + 2130772159, + 2130772160}; + + // aapt resource value: 2 + public const int LinearLayoutCompat_android_baselineAligned = 2; + + // aapt resource value: 3 + public const int LinearLayoutCompat_android_baselineAlignedChildIndex = 3; + + // aapt resource value: 0 + public const int LinearLayoutCompat_android_gravity = 0; + + // aapt resource value: 1 + public const int LinearLayoutCompat_android_orientation = 1; + + // aapt resource value: 4 + public const int LinearLayoutCompat_android_weightSum = 4; + + // aapt resource value: 5 + public const int LinearLayoutCompat_divider = 5; + + // aapt resource value: 8 + public const int LinearLayoutCompat_dividerPadding = 8; + + // aapt resource value: 6 + public const int LinearLayoutCompat_measureWithLargestChild = 6; + + // aapt resource value: 7 + public const int LinearLayoutCompat_showDividers = 7; + + public static int[] LinearLayoutCompat_Layout = new int[] { + 16842931, + 16842996, + 16842997, + 16843137}; + + // aapt resource value: 0 + public const int LinearLayoutCompat_Layout_android_layout_gravity = 0; + + // aapt resource value: 2 + public const int LinearLayoutCompat_Layout_android_layout_height = 2; + + // aapt resource value: 3 + public const int LinearLayoutCompat_Layout_android_layout_weight = 3; + + // aapt resource value: 1 + public const int LinearLayoutCompat_Layout_android_layout_width = 1; + + public static int[] ListPopupWindow = new int[] { + 16843436, + 16843437}; + + // aapt resource value: 0 + public const int ListPopupWindow_android_dropDownHorizontalOffset = 0; + + // aapt resource value: 1 + public const int ListPopupWindow_android_dropDownVerticalOffset = 1; + + public static int[] MenuGroup = new int[] { + 16842766, + 16842960, + 16843156, + 16843230, + 16843231, + 16843232}; + + // aapt resource value: 5 + public const int MenuGroup_android_checkableBehavior = 5; + + // aapt resource value: 0 + public const int MenuGroup_android_enabled = 0; + + // aapt resource value: 1 + public const int MenuGroup_android_id = 1; + + // aapt resource value: 3 + public const int MenuGroup_android_menuCategory = 3; + + // aapt resource value: 4 + public const int MenuGroup_android_orderInCategory = 4; + + // aapt resource value: 2 + public const int MenuGroup_android_visible = 2; + + public static int[] MenuItem = new int[] { + 16842754, + 16842766, + 16842960, + 16843014, + 16843156, + 16843230, + 16843231, + 16843233, + 16843234, + 16843235, + 16843236, + 16843237, + 16843375, + 2130772161, + 2130772162, + 2130772163, + 2130772164, + 2130772165, + 2130772166, + 2130772167, + 2130772168, + 2130772169, + 2130772170}; + + // aapt resource value: 16 + public const int MenuItem_actionLayout = 16; + + // aapt resource value: 18 + public const int MenuItem_actionProviderClass = 18; + + // aapt resource value: 17 + public const int MenuItem_actionViewClass = 17; + + // aapt resource value: 13 + public const int MenuItem_alphabeticModifiers = 13; + + // aapt resource value: 9 + public const int MenuItem_android_alphabeticShortcut = 9; + + // aapt resource value: 11 + public const int MenuItem_android_checkable = 11; + + // aapt resource value: 3 + public const int MenuItem_android_checked = 3; + + // aapt resource value: 1 + public const int MenuItem_android_enabled = 1; + + // aapt resource value: 0 + public const int MenuItem_android_icon = 0; + + // aapt resource value: 2 + public const int MenuItem_android_id = 2; + + // aapt resource value: 5 + public const int MenuItem_android_menuCategory = 5; + + // aapt resource value: 10 + public const int MenuItem_android_numericShortcut = 10; + + // aapt resource value: 12 + public const int MenuItem_android_onClick = 12; + + // aapt resource value: 6 + public const int MenuItem_android_orderInCategory = 6; + + // aapt resource value: 7 + public const int MenuItem_android_title = 7; + + // aapt resource value: 8 + public const int MenuItem_android_titleCondensed = 8; + + // aapt resource value: 4 + public const int MenuItem_android_visible = 4; + + // aapt resource value: 19 + public const int MenuItem_contentDescription = 19; + + // aapt resource value: 21 + public const int MenuItem_iconTint = 21; + + // aapt resource value: 22 + public const int MenuItem_iconTintMode = 22; + + // aapt resource value: 14 + public const int MenuItem_numericModifiers = 14; + + // aapt resource value: 15 + public const int MenuItem_showAsAction = 15; + + // aapt resource value: 20 + public const int MenuItem_tooltipText = 20; + + public static int[] MenuView = new int[] { + 16842926, + 16843052, + 16843053, + 16843054, + 16843055, + 16843056, + 16843057, + 2130772171, + 2130772172}; + + // aapt resource value: 4 + public const int MenuView_android_headerBackground = 4; + + // aapt resource value: 2 + public const int MenuView_android_horizontalDivider = 2; + + // aapt resource value: 5 + public const int MenuView_android_itemBackground = 5; + + // aapt resource value: 6 + public const int MenuView_android_itemIconDisabledAlpha = 6; + + // aapt resource value: 1 + public const int MenuView_android_itemTextAppearance = 1; + + // aapt resource value: 3 + public const int MenuView_android_verticalDivider = 3; + + // aapt resource value: 0 + public const int MenuView_android_windowAnimationStyle = 0; + + // aapt resource value: 7 + public const int MenuView_preserveIconSpacing = 7; + + // aapt resource value: 8 + public const int MenuView_subMenuArrow = 8; + + public static int[] NavigationView = new int[] { + 16842964, + 16842973, + 16843039, + 2130772005, + 2130772266, + 2130772267, + 2130772268, + 2130772269, + 2130772270, + 2130772271}; + + // aapt resource value: 0 + public const int NavigationView_android_background = 0; + + // aapt resource value: 1 + public const int NavigationView_android_fitsSystemWindows = 1; + + // aapt resource value: 2 + public const int NavigationView_android_maxWidth = 2; + + // aapt resource value: 3 + public const int NavigationView_elevation = 3; + + // aapt resource value: 9 + public const int NavigationView_headerLayout = 9; + + // aapt resource value: 7 + public const int NavigationView_itemBackground = 7; + + // aapt resource value: 5 + public const int NavigationView_itemIconTint = 5; + + // aapt resource value: 8 + public const int NavigationView_itemTextAppearance = 8; + + // aapt resource value: 6 + public const int NavigationView_itemTextColor = 6; + + // aapt resource value: 4 + public const int NavigationView_menu = 4; + + public static int[] PopupWindow = new int[] { + 16843126, + 16843465, + 2130772173}; + + // aapt resource value: 1 + public const int PopupWindow_android_popupAnimationStyle = 1; + + // aapt resource value: 0 + public const int PopupWindow_android_popupBackground = 0; + + // aapt resource value: 2 + public const int PopupWindow_overlapAnchor = 2; + + public static int[] PopupWindowBackgroundState = new int[] { + 2130772174}; + + // aapt resource value: 0 + public const int PopupWindowBackgroundState_state_above_anchor = 0; + + public static int[] RecycleListView = new int[] { + 2130772175, + 2130772176}; + + // aapt resource value: 0 + public const int RecycleListView_paddingBottomNoButtons = 0; + + // aapt resource value: 1 + public const int RecycleListView_paddingTopNoTitle = 1; + + public static int[] RecyclerView = new int[] { + 16842948, + 16842993, + 2130771968, + 2130771969, + 2130771970, + 2130771971, + 2130771972, + 2130771973, + 2130771974, + 2130771975, + 2130771976}; + + // aapt resource value: 1 + public const int RecyclerView_android_descendantFocusability = 1; + + // aapt resource value: 0 + public const int RecyclerView_android_orientation = 0; + + // aapt resource value: 6 + public const int RecyclerView_fastScrollEnabled = 6; + + // aapt resource value: 9 + public const int RecyclerView_fastScrollHorizontalThumbDrawable = 9; + + // aapt resource value: 10 + public const int RecyclerView_fastScrollHorizontalTrackDrawable = 10; + + // aapt resource value: 7 + public const int RecyclerView_fastScrollVerticalThumbDrawable = 7; + + // aapt resource value: 8 + public const int RecyclerView_fastScrollVerticalTrackDrawable = 8; + + // aapt resource value: 2 + public const int RecyclerView_layoutManager = 2; + + // aapt resource value: 4 + public const int RecyclerView_reverseLayout = 4; + + // aapt resource value: 3 + public const int RecyclerView_spanCount = 3; + + // aapt resource value: 5 + public const int RecyclerView_stackFromEnd = 5; + + public static int[] ScrimInsetsFrameLayout = new int[] { + 2130772272}; + + // aapt resource value: 0 + public const int ScrimInsetsFrameLayout_insetForeground = 0; + + public static int[] ScrollingViewBehavior_Layout = new int[] { + 2130772273}; + + // aapt resource value: 0 + public const int ScrollingViewBehavior_Layout_behavior_overlapTop = 0; + + public static int[] SearchView = new int[] { + 16842970, + 16843039, + 16843296, + 16843364, + 2130772177, + 2130772178, + 2130772179, + 2130772180, + 2130772181, + 2130772182, + 2130772183, + 2130772184, + 2130772185, + 2130772186, + 2130772187, + 2130772188, + 2130772189}; + + // aapt resource value: 0 + public const int SearchView_android_focusable = 0; + + // aapt resource value: 3 + public const int SearchView_android_imeOptions = 3; + + // aapt resource value: 2 + public const int SearchView_android_inputType = 2; + + // aapt resource value: 1 + public const int SearchView_android_maxWidth = 1; + + // aapt resource value: 8 + public const int SearchView_closeIcon = 8; + + // aapt resource value: 13 + public const int SearchView_commitIcon = 13; + + // aapt resource value: 7 + public const int SearchView_defaultQueryHint = 7; + + // aapt resource value: 9 + public const int SearchView_goIcon = 9; + + // aapt resource value: 5 + public const int SearchView_iconifiedByDefault = 5; + + // aapt resource value: 4 + public const int SearchView_layout = 4; + + // aapt resource value: 15 + public const int SearchView_queryBackground = 15; + + // aapt resource value: 6 + public const int SearchView_queryHint = 6; + + // aapt resource value: 11 + public const int SearchView_searchHintIcon = 11; + + // aapt resource value: 10 + public const int SearchView_searchIcon = 10; + + // aapt resource value: 16 + public const int SearchView_submitBackground = 16; + + // aapt resource value: 14 + public const int SearchView_suggestionRowLayout = 14; + + // aapt resource value: 12 + public const int SearchView_voiceIcon = 12; + + public static int[] SnackbarLayout = new int[] { + 16843039, + 2130772005, + 2130772274}; + + // aapt resource value: 0 + public const int SnackbarLayout_android_maxWidth = 0; + + // aapt resource value: 1 + public const int SnackbarLayout_elevation = 1; + + // aapt resource value: 2 + public const int SnackbarLayout_maxActionInlineWidth = 2; + + public static int[] Spinner = new int[] { + 16842930, + 16843126, + 16843131, + 16843362, + 2130772006}; + + // aapt resource value: 3 + public const int Spinner_android_dropDownWidth = 3; + + // aapt resource value: 0 + public const int Spinner_android_entries = 0; + + // aapt resource value: 1 + public const int Spinner_android_popupBackground = 1; + + // aapt resource value: 2 + public const int Spinner_android_prompt = 2; + + // aapt resource value: 4 + public const int Spinner_popupTheme = 4; + + public static int[] SwitchCompat = new int[] { + 16843044, + 16843045, + 16843074, + 2130772190, + 2130772191, + 2130772192, + 2130772193, + 2130772194, + 2130772195, + 2130772196, + 2130772197, + 2130772198, + 2130772199, + 2130772200}; + + // aapt resource value: 1 + public const int SwitchCompat_android_textOff = 1; + + // aapt resource value: 0 + public const int SwitchCompat_android_textOn = 0; + + // aapt resource value: 2 + public const int SwitchCompat_android_thumb = 2; + + // aapt resource value: 13 + public const int SwitchCompat_showText = 13; + + // aapt resource value: 12 + public const int SwitchCompat_splitTrack = 12; + + // aapt resource value: 10 + public const int SwitchCompat_switchMinWidth = 10; + + // aapt resource value: 11 + public const int SwitchCompat_switchPadding = 11; + + // aapt resource value: 9 + public const int SwitchCompat_switchTextAppearance = 9; + + // aapt resource value: 8 + public const int SwitchCompat_thumbTextPadding = 8; + + // aapt resource value: 3 + public const int SwitchCompat_thumbTint = 3; + + // aapt resource value: 4 + public const int SwitchCompat_thumbTintMode = 4; + + // aapt resource value: 5 + public const int SwitchCompat_track = 5; + + // aapt resource value: 6 + public const int SwitchCompat_trackTint = 6; + + // aapt resource value: 7 + public const int SwitchCompat_trackTintMode = 7; + + public static int[] TabItem = new int[] { + 16842754, + 16842994, + 16843087}; + + // aapt resource value: 0 + public const int TabItem_android_icon = 0; + + // aapt resource value: 1 + public const int TabItem_android_layout = 1; + + // aapt resource value: 2 + public const int TabItem_android_text = 2; + + public static int[] TabLayout = new int[] { + 2130772275, + 2130772276, + 2130772277, + 2130772278, + 2130772279, + 2130772280, + 2130772281, + 2130772282, + 2130772283, + 2130772284, + 2130772285, + 2130772286, + 2130772287, + 2130772288, + 2130772289, + 2130772290}; + + // aapt resource value: 3 + public const int TabLayout_tabBackground = 3; + + // aapt resource value: 2 + public const int TabLayout_tabContentStart = 2; + + // aapt resource value: 5 + public const int TabLayout_tabGravity = 5; + + // aapt resource value: 0 + public const int TabLayout_tabIndicatorColor = 0; + + // aapt resource value: 1 + public const int TabLayout_tabIndicatorHeight = 1; + + // aapt resource value: 7 + public const int TabLayout_tabMaxWidth = 7; + + // aapt resource value: 6 + public const int TabLayout_tabMinWidth = 6; + + // aapt resource value: 4 + public const int TabLayout_tabMode = 4; + + // aapt resource value: 15 + public const int TabLayout_tabPadding = 15; + + // aapt resource value: 14 + public const int TabLayout_tabPaddingBottom = 14; + + // aapt resource value: 13 + public const int TabLayout_tabPaddingEnd = 13; + + // aapt resource value: 11 + public const int TabLayout_tabPaddingStart = 11; + + // aapt resource value: 12 + public const int TabLayout_tabPaddingTop = 12; + + // aapt resource value: 10 + public const int TabLayout_tabSelectedTextColor = 10; + + // aapt resource value: 8 + public const int TabLayout_tabTextAppearance = 8; + + // aapt resource value: 9 + public const int TabLayout_tabTextColor = 9; + + public static int[] TextAppearance = new int[] { + 16842901, + 16842902, + 16842903, + 16842904, + 16842906, + 16842907, + 16843105, + 16843106, + 16843107, + 16843108, + 16843692, + 2130772022, + 2130772028}; + + // aapt resource value: 10 + public const int TextAppearance_android_fontFamily = 10; + + // aapt resource value: 6 + public const int TextAppearance_android_shadowColor = 6; + + // aapt resource value: 7 + public const int TextAppearance_android_shadowDx = 7; + + // aapt resource value: 8 + public const int TextAppearance_android_shadowDy = 8; + + // aapt resource value: 9 + public const int TextAppearance_android_shadowRadius = 9; + + // aapt resource value: 3 + public const int TextAppearance_android_textColor = 3; + + // aapt resource value: 4 + public const int TextAppearance_android_textColorHint = 4; + + // aapt resource value: 5 + public const int TextAppearance_android_textColorLink = 5; + + // aapt resource value: 0 + public const int TextAppearance_android_textSize = 0; + + // aapt resource value: 2 + public const int TextAppearance_android_textStyle = 2; + + // aapt resource value: 1 + public const int TextAppearance_android_typeface = 1; + + // aapt resource value: 12 + public const int TextAppearance_fontFamily = 12; + + // aapt resource value: 11 + public const int TextAppearance_textAllCaps = 11; + + public static int[] TextInputLayout = new int[] { + 16842906, + 16843088, + 2130772291, + 2130772292, + 2130772293, + 2130772294, + 2130772295, + 2130772296, + 2130772297, + 2130772298, + 2130772299, + 2130772300, + 2130772301, + 2130772302, + 2130772303, + 2130772304}; + + // aapt resource value: 1 + public const int TextInputLayout_android_hint = 1; + + // aapt resource value: 0 + public const int TextInputLayout_android_textColorHint = 0; + + // aapt resource value: 6 + public const int TextInputLayout_counterEnabled = 6; + + // aapt resource value: 7 + public const int TextInputLayout_counterMaxLength = 7; + + // aapt resource value: 9 + public const int TextInputLayout_counterOverflowTextAppearance = 9; + + // aapt resource value: 8 + public const int TextInputLayout_counterTextAppearance = 8; + + // aapt resource value: 4 + public const int TextInputLayout_errorEnabled = 4; + + // aapt resource value: 5 + public const int TextInputLayout_errorTextAppearance = 5; + + // aapt resource value: 10 + public const int TextInputLayout_hintAnimationEnabled = 10; + + // aapt resource value: 3 + public const int TextInputLayout_hintEnabled = 3; + + // aapt resource value: 2 + public const int TextInputLayout_hintTextAppearance = 2; + + // aapt resource value: 13 + public const int TextInputLayout_passwordToggleContentDescription = 13; + + // aapt resource value: 12 + public const int TextInputLayout_passwordToggleDrawable = 12; + + // aapt resource value: 11 + public const int TextInputLayout_passwordToggleEnabled = 11; + + // aapt resource value: 14 + public const int TextInputLayout_passwordToggleTint = 14; + + // aapt resource value: 15 + public const int TextInputLayout_passwordToggleTintMode = 15; + + public static int[] Toolbar = new int[] { + 16842927, + 16843072, + 2130771980, + 2130771983, + 2130771987, + 2130771999, + 2130772000, + 2130772001, + 2130772002, + 2130772003, + 2130772004, + 2130772006, + 2130772201, + 2130772202, + 2130772203, + 2130772204, + 2130772205, + 2130772206, + 2130772207, + 2130772208, + 2130772209, + 2130772210, + 2130772211, + 2130772212, + 2130772213, + 2130772214, + 2130772215, + 2130772216, + 2130772217}; + + // aapt resource value: 0 + public const int Toolbar_android_gravity = 0; + + // aapt resource value: 1 + public const int Toolbar_android_minHeight = 1; + + // aapt resource value: 21 + public const int Toolbar_buttonGravity = 21; + + // aapt resource value: 23 + public const int Toolbar_collapseContentDescription = 23; + + // aapt resource value: 22 + public const int Toolbar_collapseIcon = 22; + + // aapt resource value: 6 + public const int Toolbar_contentInsetEnd = 6; + + // aapt resource value: 10 + public const int Toolbar_contentInsetEndWithActions = 10; + + // aapt resource value: 7 + public const int Toolbar_contentInsetLeft = 7; + + // aapt resource value: 8 + public const int Toolbar_contentInsetRight = 8; + + // aapt resource value: 5 + public const int Toolbar_contentInsetStart = 5; + + // aapt resource value: 9 + public const int Toolbar_contentInsetStartWithNavigation = 9; + + // aapt resource value: 4 + public const int Toolbar_logo = 4; + + // aapt resource value: 26 + public const int Toolbar_logoDescription = 26; + + // aapt resource value: 20 + public const int Toolbar_maxButtonHeight = 20; + + // aapt resource value: 25 + public const int Toolbar_navigationContentDescription = 25; + + // aapt resource value: 24 + public const int Toolbar_navigationIcon = 24; + + // aapt resource value: 11 + public const int Toolbar_popupTheme = 11; + + // aapt resource value: 3 + public const int Toolbar_subtitle = 3; + + // aapt resource value: 13 + public const int Toolbar_subtitleTextAppearance = 13; + + // aapt resource value: 28 + public const int Toolbar_subtitleTextColor = 28; + + // aapt resource value: 2 + public const int Toolbar_title = 2; + + // aapt resource value: 14 + public const int Toolbar_titleMargin = 14; + + // aapt resource value: 18 + public const int Toolbar_titleMarginBottom = 18; + + // aapt resource value: 16 + public const int Toolbar_titleMarginEnd = 16; + + // aapt resource value: 15 + public const int Toolbar_titleMarginStart = 15; + + // aapt resource value: 17 + public const int Toolbar_titleMarginTop = 17; + + // aapt resource value: 19 + public const int Toolbar_titleMargins = 19; + + // aapt resource value: 12 + public const int Toolbar_titleTextAppearance = 12; + + // aapt resource value: 27 + public const int Toolbar_titleTextColor = 27; + + public static int[] View = new int[] { + 16842752, + 16842970, + 2130772218, + 2130772219, + 2130772220}; + + // aapt resource value: 1 + public const int View_android_focusable = 1; + + // aapt resource value: 0 + public const int View_android_theme = 0; + + // aapt resource value: 3 + public const int View_paddingEnd = 3; + + // aapt resource value: 2 + public const int View_paddingStart = 2; + + // aapt resource value: 4 + public const int View_theme = 4; + + public static int[] ViewBackgroundHelper = new int[] { + 16842964, + 2130772221, + 2130772222}; + + // aapt resource value: 0 + public const int ViewBackgroundHelper_android_background = 0; + + // aapt resource value: 1 + public const int ViewBackgroundHelper_backgroundTint = 1; + + // aapt resource value: 2 + public const int ViewBackgroundHelper_backgroundTintMode = 2; + + public static int[] ViewStubCompat = new int[] { + 16842960, + 16842994, + 16842995}; + + // aapt resource value: 0 + public const int ViewStubCompat_android_id = 0; + + // aapt resource value: 2 + public const int ViewStubCompat_android_inflatedId = 2; + + // aapt resource value: 1 + public const int ViewStubCompat_android_layout = 1; + + static Styleable() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Styleable() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/osu.Android/Resources/layout/activity_main.axml b/osu.Android/Resources/layout/activity_main.axml new file mode 100644 index 0000000000..fc0060857f --- /dev/null +++ b/osu.Android/Resources/layout/activity_main.axml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml b/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/osu.Android/Resources/mipmap-hdpi/ic_launcher.png b/osu.Android/Resources/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..2af076dabd0afe60561f41903cc42931db8d33cd GIT binary patch literal 8828 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 N&GnQ!lI8SQ#{X#Iv!eh2 literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-hdpi/ic_launcher_round.png b/osu.Android/Resources/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..2af076dabd0afe60561f41903cc42931db8d33cd GIT binary patch literal 8828 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 LNkvXXu0mjfp$&R0 literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png b/osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..a12b157f00e3022cfe81a1e767525c33f4ed2cf1 GIT binary patch literal 958 zcmeAS@N?(olHy`uVBq!ia0vp^IUvlz1|<8_!p|}=Ft>WTIEGZ*dOIh!!#7am`0)iN z!-Y*JzdqP8rN&2Y&y2(+EtA?m9-5+}#BXAw@$*D;zxcf=lRhYP2`ZYNoGdU|=;=Y1 z!-o@UOzpBVHoTpyopyF#@i)8YcdVaV?2ljDUj6>w?`yyA*Pf5cUSE9b6wq26;8J@~ z){!@7GpTmNE>2kO_POn1zf8`~}P?%{85(;s&nc+C&;t$4D5$+f9? z-8>e~Z&%(_OwrVd==PGc4mhTFjVafjdCqsM|EvEe$2)U;a9s0IGofbtHcpKz;cJR= z`DNzVI-iMtrg<$r*EFejE8l0oMM3e)a|=o;x>Mhk@*n)xx%2Rrt=4TnivwP5zpS-& z@5h3w<{9>vH!6KP74q!po!oh)$BI~jUu}4P|5ofvi@(2i9NyELbZ$qD}PI&+JJ3+^f2=YEuP zjpepXu;`->)%n@lB|b@Iv$k0qhJJp%S?O9t?)zjLwwY?z@=v^12)=lt^ZcwNoye^x z_uu*-x}ntY`mc3S`yMaaHuurqE~e`{G_IsMZdhw*{kDDS9h3WSQa;8d3vwO)d?WE+ z%*LAIs=2#$t=BZmPTP}xMpj0I9ti9_c{r`p zu+;ELV)~|tmk}}-GjAWQO5U<}Lr?bB5UX>pYf5~UOnY%ZTQR${nq6YQOHc15>q%#$ zl8$8k_1fsCw;<~OiJ-OiE?f7RJWt%N`#e!y=2`BhIqju|a?kW5QupmV#wx6HrSs?J z&nJroVy6i|*Og1U`{c;a^^dPvTfNJjdCg1nUS<*OC dK7&Kx57tYsZ49$p7vBM?@pScbS?83{1OVHE%8UR2 literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-mdpi/ic_launcher_round.png b/osu.Android/Resources/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..c51990875e404a36964d727d376637c6e6c81305 GIT binary patch literal 5045 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 LNkvXXu0mjfp$&R0 literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-xhdpi/ic_launcher.png b/osu.Android/Resources/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4e8d9b598cd21e01bbbca29aa077d99a4dabefe3 GIT binary patch literal 12931 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 b;}yxl--Ss53i@>Q4YQuNcebmsMJN0NT!aL! literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-xhdpi/ic_launcher_round.png b/osu.Android/Resources/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..4e8d9b598cd21e01bbbca29aa077d99a4dabefe3 GIT binary patch literal 12931 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 literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png b/osu.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..2d3354eaf2778d4ae52cf3e1368f131be63ccb62 GIT binary patch literal 21256 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 z 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 z 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 F@PB1o0BisN literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png b/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..d8b832e7f7a81d3d69ad5c0b3ea88dfd739e36c0 GIT binary patch literal 30047 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 z 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 + osu.Android + Settings + diff --git a/osu.Android/Resources/values/colors.xml b/osu.Android/Resources/values/colors.xml new file mode 100644 index 0000000000..17bb9a9dd1 --- /dev/null +++ b/osu.Android/Resources/values/colors.xml @@ -0,0 +1,6 @@ + + + #2c3e50 + #1B3147 + #3498db + diff --git a/osu.Android/Resources/values/ic_launcher_background.xml b/osu.Android/Resources/values/ic_launcher_background.xml new file mode 100644 index 0000000000..6ec24e6413 --- /dev/null +++ b/osu.Android/Resources/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #2C3E50 + \ No newline at end of file diff --git a/osu.Android/Resources/values/styles.xml b/osu.Android/Resources/values/styles.xml new file mode 100644 index 0000000000..5885930df6 --- /dev/null +++ b/osu.Android/Resources/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/osu.Android/bass.dll b/osu.Android/bass.dll new file mode 100644 index 0000000000000000000000000000000000000000..3cd403c3acbd9e89ad071c5069392ea208baaa38 GIT binary patch literal 210944 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 S(A~_h>u%w{`TPGJ1^#c6n$Mj8 literal 0 HcmV?d00001 diff --git a/osu.Android/lib/arm64-v8a/libbass.so b/osu.Android/lib/arm64-v8a/libbass.so new file mode 100644 index 0000000000000000000000000000000000000000..d5c24b3e4b2918a33153cf6a0561366996be16f9 GIT binary patch literal 308904 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

^m>m@_QI`Gyr3D`HGSXQzB#7TNkp#fsh! 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%0A0ic&Bx^ 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 T?MJo0F6IAiepbA(NM`E) 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 z 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 EAM_!vo&W#< literal 0 HcmV?d00001 diff --git a/osu.Android/lib/armeabi-v7a/libbass_fx.so b/osu.Android/lib/armeabi-v7a/libbass_fx.so new file mode 100644 index 0000000000000000000000000000000000000000..006e2feb30bb005eec727f829cc3965fb136f16c GIT binary patch literal 92176 zcmb?^3tW^{`u}<7#&A!|8j?2)qa+*P-&v=rY~ zWGODpU5&s2Utk}HA`Z>&`v|`oE;Yed-cXbZFN=xCH~58;{#dkkH1J2zDSvo?vOoD&Zzncf( zQ-EK{W2_lnp!SOc;+GG=i-5mj#`-{6lzs#7uYuFLA^b()sh0lr_66{}fzz6%_z)24 zk^nrF2$z4$4E}@N)2TxjZfV3-D)whjF|e_=~`w z;`nF`%(ykw7GHaEf!_&y5652x{xxua{`0_}ei-?A`+fvI9Q?~a{$W9kJqVok4C-Gj z@VW}dj6D4e;8%YSe!<6YHSnJwV{9W&|2pvBKi*$o8}KKAhwykE81s&R_$9=s`A2=o z1-=IB!3aOqUk3bHFv$pB|C7L9dJgN1$G;5x0&su%UjuIij&8~MhXupKKPo?Z0DdcQ z3;07c;;6oa0rAs-&%3ohUK|jgJ^)`h0Ji`qe)k7nei`sP&_9|F;=k*F6Ms6!$#c>#C~@FxTCRN%V;a1-#DN&WdNfcrn{<2vArkUk22YR?Yf zhsX5G8!rQI0KSsPzYqM@u>yfo}#rh~ra% zKL>mQ$Bn?h4#1ZJzcmi@$m0uv`#&8#j}O2rfv4Oiu-~CV>d&hK;*S8Ii1Ci)@t*>} z5HMcf0>3?Aygb0y1;h`7JosP$J`VV^0eCv_!14SY@OdaN7Hy^WJUjsZ1MpP=@p}j0 zZvuZdApVm9_;;QZ^@Z*U0_g@6=2*B?JE?|B8<8y%D5P+8f z59ALv;KnlFdW>LQ-pvE>9l&h?@hmeldu>)`o~1ae$YRaqXjXadT1z=I%vrJ|Q(Tsr zmRo*b?&>m2NipKHaEM1+@m(sBC?o4rYZtisfhTN=jIk2?c zygD~4Cv(*rl%JWCTUNfhmak@crEAK|*mb$H%F9=0T8h!g zUj~=umX|+LntOfBzf0_IMP_E1`0Kr!%+j+S%F4_xS%qFtEz8X<&Rm&QR+cHZb25gf z&oeoo7n#d*iWWY^$}AYO<;7VAEW4x(zML!suF74NUHV9WZI&F19Js3FA^!}Nu34R% z`H*FG`I@XER$B5f74mQa>kjdC>anmh%LLVJQ3BBZn_3M+vJCELw_kuaDxzAZ}?^e%W>1LfHJ=;{0;6FZAv; zWtQxI0`-;IkM|d3%qq{iuAq5kbF#}Vm>;<@nDwQ(t4d2!(57-8)}MJ^abC%FnZ=^M zcKLInVM|KZtj-=#Ac7a8L^w;y|DNsw+w#9ARyk9DGydaz{q2;81SR=a>~%diJW`%p zHf2d}c1dv#pBY*)U=zd@kY{1m>a10{@T$d3zYV@mY*M|GX?OzL`M;i?U*z@;(0`u4zuW(L-s`9CKhJ+XVf^R$`e{C}DL{@(v*t?eK7 z)YYp?R?93Qhqg4I(2z4_4R#^_1T4;d2&+CfkcDEHc_^}S_V~YU!S&_+r`h@|%=T?i z*tyMpEnh>sENz)ZCHa#R`hxwTpf}vpH+8568MFFM*JCpSUp7_-~{BZA7LqbMmyz@{-KN$-kcFH+SE??BA42Q7J5I zWy$JtwwgC1o7%EE7vhV*;k0_hIRgr(p-f$yom(mkYS(wP1kyx~uh#=|<(92kMKcgE zEa*PMGD}ut#X&4536l?4N(m+iJ91xuF_+MQT6x0z7B3;ypf4Ta#2K%v$ADe2e03J& z9G|AKGB@8+oS9ven^nAqgjmu(NLtTal~tZi3y#{j#y54jYjd-GYll+NxG_oT)A?txue^UdeZMlXeWi-mkq9sQ`oO-l0Tag)280C8QXUC#eX{|ASd1wyDPB^Z z1@iW{7s2zhiXjN)=PtqgS@JB|vWOiJPx#{8B10B23tlC%Ed{6Q3x?`gWPsT@tBE@it@;>Cb`J2|2d~Ei;s-<%Iv_T` zzc7l;=bTSwYGq)4xjCe1WM-~}MhOv;h75d}6f=4|fpG0!OwL`d~I^dbk?6&2VI+o(xB4gpa~i!8O3W4p#}c z6K)Y)7ThCng>bLJ!9*>8tMT_~xHsX*{th!cn-52}6S9Za!qN9KToc?OII;`TSL6fi z4ZsYzJh;E|upGd(a8JN(<6$!aaV)`(!tI5-ACA6taBsmKhC2X9-$Ood-QNYk=zL-m z9NB)}g`@9%xI5wI!O@w)b~yU}1a~*w2XKFb3;bT=NF#?Z>B%2iVg3xa0&cDx;yWKD z+p_}hS-5dLoB*bc{gLAj0Nw)!^Ag(y2eUPM3GN8oGjRLi=&OdKvl04mY$4nIKLo6U zTM6g?U>^Se@~Qq!DWM1_8`ZCUQ9SU*fXGbk{{c@yT+D#@yMRyQVQC!R#Nk2?|0iHTWc+{xi5#C85Plo?X9k3kcRAcF zxG``zGW*5%8-(1;LrVd(x&L>7;c!dgX2Xq!n*f&!_c&YxoDQx4t{jfO5V$+w65uw% zZGl?_mjp-OU>{&6z^!o8;eHE8U%n5>e|O{W^Kfh67Q_7kj=niQApcFq-xuLh;cka} z3eE;+hPw~$FL1?h>2N`COW;PqJqNb|j=p_xPs%>VUf}Q+4&USO6~N!ay$$ycTp1kQ z^Po92ayXwu6Nfn*nmH`uu$04c4%c${D2Fx>ZBVHJmaIIQ9D6%JqH@O2JrIc(za z7>6f0{EWk94o`D44wrHG0EZ?Hb2v0}Sj1sDhif_9!(k1FuW;w!}A>4IsA@8_MmTkR2*tK4C644!wDQFa5$C2g&Z#Ba2baWaJZJkM>(`{xRJvx z96rTiC5JmXtm1GFhcz6&!r?IvPjdJfhs_+G=g`jKcO15H*vX-j!z&!RIqcz(t>)vz zp_aoa4o7mR<8Ty*NgU4NFquOmhYLAe%Hc8&AK!eIi3Q#nlHa2AKj92z-1$l*y2&vJO4Lpz7x`61Oik1;nv2oEaoiyNxY z55OBCkVg>|7#m3t!iJ8Z7V-u`2;gx9AskI02!S_&AcXy?1R-Q45rn`#iy(yIWP-yW zUl4>)I+x%L(1{2_7+y#a1G$tS1lwf@|W@p$`&-FkDM;I`m3{cS4^d2toNMK?uA}1XCD0Mi2ttNrGvNeMWFD?${B$ zpRv;fA@H6hXkzRm+Dp%t;XQc!eMYKsP}MhCKu!c&h9Z zzgOA!em}_mj9u$||NET=Ozua|d=vS}Q{U|T@#yz{|5E|}jRF2g1N`Ly{-OYXPJsV` z0RPee|NH>IF~C17z&|y>KOw+BD!@N7z#kdl4-4?C0{lH){e8R=;O`9Ze;43CAK*V7 z;QuVZe=NX%G{Ao_!2f!H|CIp$o&f*O0RK|~{*3|tM+5xj0sf)@e@=k^fdK!~0RQ{| zzcIi+E5JWBz&|0tKPtdKGQb}h;13J%s{;Hz&Vca`@OK9IzYFl65AdH3@P8KIKSq9h zDz+E!8T;K{@1=vu0@Kz9WmFh!;X`k6{ zVsVj;Q6j=vjVZZq$h;wQA29}-Uz@zv=yjD#H`uey!W-dp6*2yL<3z8kSQ26gmP$Ht z9N=n+uyRRRo6yjN_Gr+a&v4i8$GfmD*}`wN$rIbPwgzp2_qKlmwy}tse}?JyejkRu zDs<1-slS8J-;>C9+UxbQxut1Bm`V{*uW=sf4w|oY7WL>vl~aFBCn}x2y~?=_Z4t?9 zjS)`U``(QAH-Clo?{$6Gh|5y?rgn|KH0_Y2N_W^TNjT$YwBsSw+Nju|xi7o$0 zV(DH ztZHdPLB8~oRg@IgY0{qxf}~Le+Z_sozl?O73PdT$y4|6)rb@5CzuEfFPQhB~P!v)v z)1;t^Yto4oH%OHQhotWdr%Pgm4dIH8ClphShgwIP;zVZy+85Aj^kD{CJ{~O}k5 ztD}z^gf6XcpWO1k7Ne#4%Y!7{;>4t0;9Bkd77k0OO@8K z=*brj!I~?LwHl?D(5ua8vD&JV_90x6POaYV2tp63C(Jq;P%XV;{lcNbD7*@&DVT%& z8flDGK+pg0z558gdxiI|7o$J1-I+Gh{7RQ9gpC?2y3xaT(K8o%_*eA35pZehZ{*(X z6xkR)BUb7M_0cJ%qz6f((H~VonzS!{thBjcEZU_(m?*`f{fYvOq_V0lZyIiC(R8ST zk9G>B1bVEtKIdR4RU^;ah1S5n3DX%-~Q z;cr_fg~C3AFu~dTvnqqd>ck48Hc@Y4`eUHph=yB`hv`$YO0lP6#OCaE=n6-gFS<9{ zR9)U#Y}6PrC-t_LX3X48Qsr{Y)Qm$?>k3eDx-jis=|ha^vGn6tZMO$W5z7yOs`a2g zm87m1D`_fdOkVj8N;S44E5je*GXx(HHrr(QEp5z;4(K~Hg9|;QNJ;DvdklHm(mKsCq@%(5RC*`8VrM4dN51*(i7I(jKb}p<)FXI z>w1j5t{vB}>uG!}uuA&Jq9kPk*7at^r~Om}A_9M^*o*N_>AWFcjgbXMAP#P2&Z5Be zksQbam~$c4d_;o{_gDjYzz>&vJiwne3H*XNXUJ)n4oKU~(^7us{J|TPp%Ynbg)vFy z7ui{g46mzB&dD0FK4;&;^D}3&SIg7(^A=oR&S1`A0qK8C1h47aH<^xj4t>O_Cpsdw zRf&5Y+YXE{*GlO}*y#1O`?|Ct8ZlCQQoIc@Pk8Q4wf)#*`vbVx^A63nI%)2?l+GLD zr%7`^ogjsLx~OwxC?tbRI~{EIyVA$IAKmw5J2)FsjFU9gb2@Jd-7JNDI!+3!J|wYE zXI+H1abu-SK}{o-Gy8VIoD2y^3qso@OA0;I!u_wtWOV0 zC$@D-5#5?I?@Ir5saBd-F-Qul7-F9&g`8W|c{AD^eTiZwNnsrn>#H;T+#o5uLYR*A zQGJIrw|bluT3stKqg~HX;6o+mBH0P zQgBBd=ykd@cUznkx@}Qs6mr%gXONsT`nsIHT-t3xlC}eV?)XcmaOru-EtpTg+){X> zR5|{T^n=VVomc6Fw+=SAC(eaO^`Gw>4Y^*3aSQu$)gGX zfqps+jwx+M7{t{FJO7Kwtm9W=QSmCG2kaM@8#lE%kRhvJzV6T<#`E;)%+d~u} zOrIbP4rq&SW~rpRHSqOav^+ot?V31I_D2=6PQpJKze`6zZ-n{Ge}+HE@>gROCrW*fCs zi(<5(pk&%>K*>G{+(*eDfRa!BKop!Lehg~9 zo{k67ub-~F%-?RQcYpT_I`;E)k^#a0p|?ad*e3<@|6bP*m-}Tv=IrVDH5qU}&%?|S zbqe!POJ$lb5AB2#9fP*1uud|z;n;sH;E}zK`JdKyJyx=_v575kdJ}qGO_w#I&QdGZ zcJ*fNY_##vgO|aJAjOL3_B!T({;|)2)2PKsQc#E9ve%IC#R{!Psp zr%UNrErY7-rQ~Yjnc8OJM7^#pmwl8OTrJp%BMQ^UOW}o!z@2+tPh75*=F41DBZWdH z3a);wQ&F8H1#kPbb+2P|#b!ynEl!*)GClUyLg+m!Vl6uikzdqxDk_A;v68l;UTUhK z+733>LguKI#EhwsVlnF#HQ3)kmT*Naj5AGJuUv}N7||_ zRcU&2wHY%ZR;5iA*NJf`Dg5Wp-OQFQCW?ZXgq%{h-n_y>X(l68yqU(Ox}Yj8K~&bF z^&6=4miH8}0uW7Me{Otlg1|Od43=c`k`&glfg#LNnx?euGAO^q4xbezmZq(UR%UIm zgc>(wX@M~dECFN#p#5Es80Z$1J_-G#ys$e2=q|mkozUzf8kV7+;DB(OSzFiZ`lH13 z`%Kvw1Et(1y$SkEV=2;(f%C~Z-(hTeVHcoMN-=^;^B_@esW$INjW?i|D=phuL5d*K zyge%E&16Sdfzc{$p!`ZpvL!2PSxUI`Sg$TCqJich)x4%|gC)C8iSevT%eKT?mZxlI z0!FmgwUSztm4uqYMbV-Xo6LV@lf`i7tG$~Hw|%YgsJn!pybs1)c|0q|Iav6oX^U2s zaQ(W7lhmTSPH$mdgEeEEgEcGas7+Lp-m;R{L~R`-)yQKo5;f+TUN!B@Ds9k#-b!I_ zdA+d|)S%_#H784(sEbiTr~A;9V%lJ$G55OOlqIj^c+3UbDxj_7U}xFq)mv^hjz$lB zy&sOST?jK-R+^WkC^~G+H;RMAA>s|7yiV^*%Vd#8u-Ekuhc9nwgSLK-rOEsx3wMs| z)shTfp_&YCkx~imosBk{M~+x<$r${ubbR?{NxkCk)MmHJmesP?kyydTK#x@&6d}VD z9!phq=~Ss-q*)>z+K_jprjW2MRoHan3(%ckfSu$8hhoMH4rO`-G|j(73s}984h_I6f$N<5@9(`@Og6JIQK-q+_a_W< zTh6#umC$-r3!JJj;-Rq>3()fjRpJ+CuyP}zWuiUl+Kw>g4)l5lG`+B{h%jG2KPrfo zG=;uC$y#6G4p>jL9h;S^>163a>kE9b9~F=mhTQ3q;JblgC*)p{zV6e<54Or{9URB^ z1qH0TWDBjkZ#rva_z&5FkTA}_)-K6w?I^b^Ol)^A*d>O%s1iT4Y!SDM2Mpm~9M7`J zIX~#Em-mP^z8k#RS(8QMM0*0RXvQ)fi}|o4SgH0XA^Ch%uo=DFZ_qUFvnV@0PzqB% zgiQNW>ub2I0u4Ijcd5x=gmgTCCyLqT-G-50WLusR*;r-AdgYfGt+xyj&9J^K*Grq0 zQ~nbeM<&b8$CppXd~N{N*(w-?DHmIhA>Uhu8=GIY{ERnoAx7x4vL3x2@MVh+r*V26 zoPQtjGzZK0q19%bWIWnxGB@EVa6_B>nLs-Q@$GPNQIJX;e+v8AjAre(rUg#h9Fk#c zOij#WV!9=e40~M*J4r4wSzOXb6~`c_(@0P1G?}mG4^f>fvEOWGrmTjxq~yWQrALYL zYtmVakYzP$rzlJ;_5+i_wBBUMTA%d+xa(HDMNKxBrj^x;X3d^=4B=m@&B6q2W06_W zteBuUHNjkyrn0l0uLCkW(Qk9W1&`ed_@ z7izKc$v*=8)9)u<>i5$w z3vIZ5&#=nj=Mf%JKhdFpgpypG(is&mm_N2`Nh3O|F_VN#nl$a~pEb%-fE2WC2~st5 zDzH~afREmFly*`z-$@6HiZ`hTu)lrtWQiWuxcJqp>Tzqd!wN9pu=y{?m&l4I1U=`lz?ubL{1 zx0t-Hzj{r1IuZL^<5aXS4rSBcJS1b2nJf}Y)5JPD3E0<7yYlKwrs4?f*EFIkjEdLw zwTEi+y3PQG0iN=xV4?8YKCzw}PmdDVH+nx``$Fbx3uXHUIC+{%+$ugRvhk~$mBp+p zOwHn_G_$TaZ8BX8jN?2Cs~^|Qdh7xg;w&yvo_Z2nszC+fW>TQ z))Woe_q$6(li9`K-G!6I86s%2kmz!LW3pV9*yEEc$6SgN7m4X2`Vi!G&Fs+^n~L>^ zmF7Fd@nW?_N3t(${E7+=jgvtm#qcl&J=8!{kt}E2KBBj>gxQ zR&gYvAtYcgu|c1}oM5Hc`+Um2S%_%ZgYkbLmga!P!s3MUlrTNhZ^*V0hXKvoIgF5H z6|d`W*Y*`Ejr+3wc;f*4Z}Kb_wG&0U>osDiSu2KN+^W(N%@@tIX4SHEJRZ_;f_O+? zg+5u(-Jpi9HcTw7uXIE}6UoIW4_%=W2Z@jeRy+Y$=?E*F28qB1$gUn=*km>zrrGe% zg63=uT6<3J>r3V!yB%|)FrP6;i?3l;{%Q8fZ3i2J=0?=hsTwmIixpK7PGN9_7%hf1 zD)a)hi-?9O&?V9NKeNL{TFXCQvtu`)HO`#p-uLa-#Pd|!DjnJivdV%tQEP!mpv5-F zP+(-w*1-BS8dj9l6*ly#Ryw`{ZCwHFM%Jv<=V+976)fqzDSk`ZPRCH$f>SG<+;&j< zShiQG&e_cr%bd6Ns;(Yil7-%Fko&w7<@x&^bk=TOXBg644hl*2erpc3*8mT0CVINl z`%iO?xpK1CmE_%L&Nel4s z8h@EigLJxpbXugtDJi6by_n62`Z1VGmFUxJ)7y@yL%0jeweM6 zBBD`0==69Ya;#VaJF(YwzVTl9tDo&FPlfZ0phA*7V9As1#{T%AdaVB`f_}qFwtW~h z80Or3OZ@4Uvt%7 zwqsqmLD_FWpL(JedfNfTU)T;6G>;~;a=+>Ttk9l6UA0Y)xI;5;#@UN)f>RYbboi}f zCb4lNYs^uN0(O&?J@KG9f^Ue_}BV|E(d{T{2G#VGf)XPeC7@DWrV2!Ve7ut!-{ zWLF+wJCH6WL<|+Lv|^-Jd}!W*6-li*XC?`jk8}u&zxNcVY9>}-#zE=B40#VZ3rVvA zXR<4YVf}ku=R8z1t@3kbN>4Vd6}0lfL5|CNj_T|*vZ_ETQrf|PP>Qw!rEVkG*H(<2 z3f5W$);xF<@hGB5*i{(utQCtoZwM_-lPS)ut7~>wCR8R6ul_T*bP)FLUe_mH4SZqn z9rtRCG{?mr?coG52=gu6<#ky+y{Cf~#F#r_DOJ6+aL7f+ysf)aUu)bgF1REHyAX3<>eQAu4U?K*G8c-m zXzhb3U!bMm6#HBH0dzHC=KsB=7PNF8TKd{`EjJ2+?H(1pV68i zw8qzxi;huS16%XH+?rn>xBtJbk$D#6jX04`7c}zeg4g@F_w&y_yOZQ-%%`;(`Wn*{ z{j?TbbVOo~GzBV)c8YfLI~~Tsx3nyV7Js~W4^t$LHWD3So-h)lafd-suoyZz;m3<7 z7*9I{+$k6>Qx@(w$duJWl!eb<45C9+ZL&3_)g(=fE< zM6uAJ3=^i_YQ)Loa&3oFK7mvv`fL9T=aFr#M8(4GM8oGv=37T~(MR=6bZED&uifj2 zuU48>;s?cBM9|3rHs(S>AtV<8=bh{b*n*Hen3V*1Rd7{AD&T)xO5q+>>As1im?N`$J?M@wqlVc9o+u|o+f&@1U` zY2OUB^y+e-1;%&Bf$TX`B<0MhkOimV-T-ms6Rc{uv?>pg6}h4g+M=J! zk<1flFM95)F>RrfhTK(JKS&ftZ8E=Z2tPj!w1CkmkS!Ne--Shl?(I;yQme|c*Dh7;&|1KEzKk2klVU(3nbGa5P3`sGU<$^zBxYS0?!5tyQY{7X?bdc2(czLGT+ z=UN5aNnx?;!1-C>RzqmZ?MOi*AxxpZlB|o`3nlb1jQR*0R6zd<>oBWW13oVPZ~CXL zU%yIe4ymgyWcC$>q~#~nEB6G~Z7K*ijj#LLs^G(aE5QC5GsF~Mrzj3NtUx*z8*K`! zODWWw639jovjJ48urw8u1@@Zjy$)Dk^CBA7&*}f>vkj z#mbIM-(he|qI|Ea33-CQ{=hPLyypDidD{#-8-*!~DIa8o*)b}8WvI`5Xkqck8kJq% z#1A1oZpcRKo{yTJmzOu2cnH(JbsLNLT_zh-ioK4BSPg2( zloR{(i7lWa5h3w~BoFwdZK5p^yRDkv2?(|7i$mX`eI8atl%to+c?b7d{5gE(ye$p- zAIjN?zPwtn;EMG@dx1G6%=w&0Zy{_2tI4V|=n4-t?#rU^Cp{+EjalP?{q!X_`QY+o z>Jziw=Y!0c>#m-LnzSgo(OuwQeny(EB2boql5 zbk4!d4l9CBhW`8ezEW%jb5p2)VNRVVBJTA@L5zsei80O~!I$n6StC|dv2iCGUs_4B zg(;hjS6ujJC5sj8!YLv4n_L#JxS-EwdKuU2QHR$>cO9|{y{^vzPovMi(rk^x(D(J` zt%jk^FPSQFUiKk0>2mgxx!3i+ha_=4pxv&|(upq>3_~e@^D1g18bSl~XkTxmE~&aI zAqy4BxqDq^PoOUSR3!B1VSamt9WA)#YLhi#8aJx-4iB~Q-d;hUjTJeYST1Tj{OhtJ(hx>qA`vO|)7r91lm z{77m)?v;-A)atIeplu<|yXZwk1KA{Lr&5UssEu&+I=AdI>$zw%5hFUosoS zTH}K_|632>}1v#&o|kMdvJ8O{fVh3M5MxCby4wMNQ!Is|>3xGxV{ z!3xqNa3&t@ud~;6?&l|3`Pgmt(`gfC$w!eQv~9BED9qvFE%SF^t{ydxGJoaXn80FU z%}NiucUXb5q$-WH_yx|WL3?on&inS>EWLS?ltC`8(OqGGV3JwbUdN9T4Zl^?ao$u@w048<8}$yW2Qlx?O3 zSAI_X)TAs9h24F9$&f3XXGb;~u56wX3%5Rhh*LFq{VIewRf<@+^||ti=+$G3KshNy zIW}>NWkYS$Xjq9o!p76>WAcv}w2g1$JbL~ua~p*&uWF+q>{LPq>D?8^5oY>Vl|~rc zAS;vEr6ArL65?t!!Y8&LIL@3`Z;XW>_9IqGoTTNLD?~3p5wR z3y^Y7xU;jd6!vasT?FovkAmjW<7&A)NVXF0Xu|^#{Wi!Z_qp}SQ|rDdp%bFhZkuku zLD4KEcD1rmJ+70u;ZWKDPSU7CeGlE>tCPn12Jxu{WW!sR{9^a1s}igK0( z)bk?n-}IHc?DSs8(mrg_d4C;-U)151>v$?5!LrEyoP%w}{f4b1nU-H@c8o#^bLD=l zYHoH!LetILdeJf4dQytpdPQoL)9FuNbj(6JA2yO|x;GBJ8Fcww=$q7&n{b--Q13=) zY;l%b<(^!VTCKNb>@v_T;owuyGnH%Om0!;^N9snHZ?}(j2B~3FSa#MO!FpVma8^&Y z>0X!0>kIio8e@Of5Z$bmXJ(i@GdG=Tc0ZLclxAmI#9f+6gU|N5W_cl{g^-?n9OD{h zZ^lRp_*92s`O6k9ZREHby!LEJ}y4njY6E ziN!?4rn|>78_JLziRQWD$#zvLZs`%PN<8USB|x9XSwy%q8qJ=|$qplGHZ95G#Vm)quvgLb=(XK|0lS%SX_ zU%I2323OnDZbFadIcw(NG|KdJ+ZGlt5?||a{n4Qk*P6B*z5_cI;Ts)^B}rn6J0!Ws zwbnr;_^4DTs_lgN=rqZ!rm=cP3KLi!Tzs$B3tHj4^MYGvi^R#b%s;OlUj*B>e(>tQ z!A4DdlYC=r?B3Ev{zK@S2`vf7NyiGgj zu=ThmIE3j^D{dX>`u7~7A$fMzJsOJN#zmRo&PfeEIEBM$@;S?>KF;0K8Ou4hM&{hp zT5b{-yHyzn4Y!?Qqwh5JxPI)UeV6)?SaP5)yW~Z~;1)e*a&$sQ-TjcmXv8`@vj${N$r=A(msw6sN> zJb!a-kjP?ahiNLgQM~9rRH-+!(bNv#I*91dhRhWqF@%2Jt~$`;s_InktU&8#wcJti z8e8NZoy;aoZN>|w#L1^FAjN5%2fW=8qR8$DRkHDA$fr2B_>ywah*O8U*x(ya&B2_| z+Ol>kcMmaBYMLc?$tm~9rWmswH|%;`t2-&h%1&6GF`o%&-+Dt?hoCytcq42ejja^B zyc70LnKD@8A4Bk)>2S0@-neSJdsFSr;);?dMP=o7u~O96F`TM~V6HcL!@D9vsU5Ja z+vt`T$+;|U#i=tG-}|wal4G$qb+Wiwa){5L?0muYmsOBpgkSU>#wWwpyoN;fA2zB1kGr>Gh)LVQdAuM58$~t2cYF^vA ze^s1VxN4rrwl5d6ahGXkH{zKoWp=bL#q2BjZ&4{pVyN?m9%`8eZ`*9iq0U2)rtcTm zYvaV{aieSs+K98txUWv#(^^p$YvVt9@j@5YY!h- zwIV3^41NG9mcp1Gv);kt9=|g2Eu)hqGrLX<$9(!Y0Bc-`|Dc5Ccpd2Um37-{%^BgM z+qlfFOc-f4*5zfy>&Wku44Lj-yW-8s7}F}0$eeXHRn>1ZBCfD#q$yRNnrR+`eee=! z3FjG}4PsQ?O!FXw{Ihk=PluTLim9N-71FUtq?7&W-6IdrGz*CRqBZ@BZH8)B$R)K> zOy8F;W{gi(RD~uhcNs1zLuQ)AbhguK6t=%;UMw1M%iy&%d%h03if=6*Y*ke+4+=Un zSG-?T#p<0Zr3(D_o{qu)rRrL!9(?@yw!v%@9Mi+Po1dMp*mcaktmc^8R@v*S>sIcf z`+UFu`9+7q>W0jv+KsnL*yoQy8u(JJ+;t4Qp!)Ps(3J1gl-X7Kj1;_7h+(6TVa~m- z?|+_YwwJ5`&C@wXRMyB0j0H~oYB5T$Uy4S1hnts~pEjsk7P?347S{>4yIX@!6_2dL zY#qEb4Dq*^mYIfTBtsKkVNSu??{PhU$uCjZOG5d2+`~rA&i0;biqiVt5`KpFgipY~ z>YCTv4F5>*pdPH(AK^&1-PWx|*)(q>VAayqFW4v#RaF)Jk5++Zi!^r9owIu;TDNd%RS$gS8@5uYZ@1ar4;mbPrIN{fP|M6!>z zf%eu;wZP~OzguNZetlgjDx1Y;iw* z3G2{!w{!w>&Y!GTrDR!RH8#`za@gwdZt@4nr@m7V#hKF%ja6g6B7H2UQeQZYw+DEy zXWfX@(1ES6xg*zD_*ubyu!Z9_M8Rp;MmIXt@P|UC%CjDGDB)CACuAwVZBTLH7-EC% zryU`%&2F|PNk0?>A^%2%>I+ZfFQraAd`0?1u339Q(5umob{P}SFuguoU&!KTL1&rT zbQC;cI%KccYqPK?dyMDYtQIa|M8W5{C4^f?)fWI)j8Jw5_ttg{Qe<^8CH5jcrAeSY zzUlq~>^%A{X$qVZCSW$+ZYQ1YrJ}65osOtJi=X=3w?)`XcKA;A^@Z8l-xl9&Olf^D zRnfcg|fbLP+M#SyKnk?fXvd4HM>VVOm$1V;K z0&ds%)|L*Zhx-aIf@b1P-xemCcH+E{sOAJ{QYo*msx(38yAxnFR-&F#tW(XlEw#A8 z9<3HFVlZe{3o9}t&^B5d`(gF@?cH8irk6Ac+@d)g-&a?)opr6%V9o5OnKZTGR(+ut z=S&Bs*8QZb0q#EAh!+R@H^NZ}VS{&XgroN*c*%nq_i1P!HSTq!;H5$ksCfvq&5sH% zfYLX@4-H}KMn^;eZn;~>NLs9>&DO2b6Nn4ONkD4>-8ATN-Prc7baE@5IMQh&EYgL? z93d#@6RaW)-Jh3l+V{8=^7|0njyyp3>c>ez)lc#`kL%dwjSj{B!#HilYnKA6G#+n_ z#ugBLCWv(AFa{?;UFaXRt^lLDk)L-^su_rVMLpRJABh!J`^-^!R%tLAP{alndEjVWE0_S6k3|We- z4@|;Jru$~4DO;CKTvpIUG`t2~5O)J%KQP?GMjJ97GhTFS*TL1{Sl{R|CW(hdk89)Q zyHL8Y19H4>`hw>S3!y=&A{JcQG)U+eL{ei-3pA=d2BG<=A^DV0EzB6yr5g00G1|0v z#CGO!&A5CNmW;V5Detln`-yv*uEo7j_oY&OMu)IJ!m{CU?Zn>}XkZ?^vuJTI)y3Aq zc3tXmy?@!&8q&2Er5ux5+;eryQ#GeXrnk7~v$vNGHE+i&j)lmbj2hl*zA58h%SM<7 z*@fHx0!hH*nsj++#!p+-+lv|4zv>1NN?Y(FebFG zeFvV9k3H@yz_Y+<-}CJms%=5yLw7$@`%uOfXwTcl4%9lct_%_j`FuOrf7>;G@wg0^ zRpPS4#TdP+)MV#zTT#YBIWqaK{_?txTw5oa>$2rM>QknG z9Eq|_^WUvDoyT=nQi%%>FPBqIJau0{sxfxl*o^hKs_@cnZ2rEypz3e)7G-oSTXgsD zjZvbo!{gc`jW?S~FWSD~()zH^af34pqqSdB?iRqEwM}ymM*+ugAK>qHDN&Y{cD9;L zCgXUM`i*3_YCgr=@EZjlR|NhFF>gz%ZR8&Zdo#_|P&qDA8aHozdXhLk8jMGCGU9`12XmHcay!jECM!wC=8WpH&J-V6HD#7f89b8W}m z^J`+o5+_Tc93$r?;r9qWs(8eB3_GI7^*UZ2nDUdviHE(eXL}RnIljGB;kA&<{H%jjlS~_abC4;-oqESm^OU;v0WxomJ?gDLcNqnbOD8Qm{3zzR8Wi+`ts)~q^vT85mOt2k zCi$6M+bPkUPbwVrmxGp(9Z&$!x z?sYBbStqvDrL5XkcQ>zP?sc^oG6wb45@TmO7Ro0nSlf=|BXf`g`eS7*N{vUU(;QWY z@8qRSyRMYU89{xekR&<7z7X>H6x1Kn%i?~5Y=HZmXbH`bpw~_L*u6A?=|6TaOBiPU zbJwU)<4?Lg+_`rO!=7|RZTr~0FyR93Y#)HW_p%}6%df$^W*nvxk#42OB|3zJVW%Qt zQ9wD&H!nU4!yKomcRi38Z4Sj?^gGWSU zEV$BL>X*pr{s(A&UD!Q$h??Cx@iF5xbE5f{f_R*|Xy-j*RNzzyGW@lsw<*>0=kPnL za9g|ao2hVXTwbrXp5*6aJxyZ>`S+N2s31Pn;Hd=Ez}Dp8oh`kD}UtB9-j9Lyp%5 z#3vvOZIQzhJel2Fowy|?zvo@wg5T$b^NnM&JdS~~r^oeK$FIwt+Y3qd^te9gxL)@3 z(2W6E_PpfAZ(f0p?t#NzmG-2lg#}i&D~8})71|B<+YUDI9?0rjOf%5BHw|%(lf>!9 zH%8#?p!54)geUxQ1T;|-n{??E^iAj3UVTXr?#J2lX1|8GNe1}N^`szV^(Z`+59x_ zlz3gnZde!y%p%%N1FFK;CqyM;EwpS$9 zJr6$a^N%oZw1?v*#XOArEZK75wW+FyU17IAoq-g|%2RsTa`B_x&zDtw+*o-5D;l!O zcXqmmFZBk2dp5hvD-V;z(2UbR#C=8iWKR6sbM)qecH}7?(4s0ydm^kx)?b@!clV`i z`mxdGPdl=Mz2Hyzl$`Q_?JfIZSS^COW(|51a2MP~_fyaQZ2SX!Ss4x4Xm<_qdFv%u z))T&lWTos9LKj@xrk#V(CoYwOKYCoHmy$paFL{#Szwwe@mLZ5AKW+aQIg*Wd7hDTT z;!#Sw95)$8?5@a9$rzUG$sJSo_Sq`6)E~)9 z5=U0EG0I(v-AD3ouI|m7na7+tJv0*Z?u2%?la2Ii0<;g|9qBdDN(f@*Qy&fV)rx$* zna&zVn5WrCR96SZov8p_`|c*5Al*bxdGi?-n8)_Bw`cB{_3#KJ5i$p%@BTGf0*@!{&zBt02F9&<@LhSs9N*hj7~9YOg_uxadAx=`qHM`%#yvoivE&4XLC*B-Alw zhcIY~d(6Vu3O7P`n4dcRlrZB{q}V<}HMvwAZlukaF1 z@5AF-+kVFVRK$=v^1s|(Sfb~8!^`b%oJk2gm@^aS_#W5kw)v?-wWj%|^eFK?XbwZo zm1#rm!nFEUqQL0(u#7#1h>V^9UEyfk|6NyDioVlayavAeGF-oopxEZ)5!&rf*RIdd zh(8+#ix=Fcn)_uQky7^uxj5rb*^BR{7W#FI;lS8Nw^-RmJIi+bo|DI=ZKL**J=V%~48MkPPaD&JoA)00ox1tf?yW!ixx!-H=Z#L; zZBVvQ=t`M0WP>y8%S*tiZ4`8g+BQw~IW_F0ObIKV$F;T1d?dOWXHmOUyY+d#ea2Qw zD`I%H5~pJNeCAB)j+sZdcOEg4X5n#dX;X`^#dh$;pN;oane2KN**&-rA!syq{1oYFCddG zhDdKM2Zr2x*B1QwN*IxJNEd0)aiRr)3&&~fn_tk9S4f@T4Kdp=tyYY*Eq(67#Wk2c8 zm8=`T`bXgpLHqXI9HSdU$pzZFZr4_+rojK!%$IhCq|JZ~CG+LoSl{XlU9nG|CJTel z*4`wcPjDm;vN5}GKJYf~RUI37NieBCc)9K}l4Zg0{ z370y{g3NU9REe8ML8iTi$a7&HWslJDgi@H+z4DG-zH(SAA%xyLHN4!h0;`i7p^z#B=`q)HQ!F~YdbTG3z#Yw3#mD_RY`dO5Y6emmDrb;}`OM@mtn6?CE?&knO>~eb+wQuV>*LauwaNxj|$TZ@N&A z*IEY~Z=+v@%(p78|8BvC(vglSVZHTp-vv zqc`Q2ge*OPu`l*)8ln0BmQj(BjTyGtG2`kC3?{#LC7DRz|iX2Q| zwlbk0@D+Bq>psU6`Tb_;%5Im4Ww1;g zi3{{>2KRpk-2cy(F&3}uGp||9D)`2tFJR8f?!As1GHAw+wTB6K(IekI)WBMiEc=9J zy=B;8+82h|Rd|(!-x*s02;Jhl!cDk$j~8Yu=r;{;D_y3+jgApkd$AH)qyKl3d~2THxxr}&GN)gW3pFO9hU9j7wajkT0|r|xz=)v2*3K$l)wBsgE_ zQHyP@J|0D5x+nvhVYL747;z!h_{Z^@P2p5dOU=aPp_1r2SZA?=K8&-b5q;-fw>Hzg zXnJ*b+A(;!5F49M_ISKb#p#u5Ic{xNxTWt4o{+}K+==FOuj95tO5?MfkFfgA1*_8R z#q;SlC}`oM0xEB>V=QRl37iYiuL*us5P4m_kN^kO) zzwIWJI0ARel4YG>MB@`Ub)+@1*D-8soHTZ8kQ{%}5rLD5u?QK%PbqzJzsf#B*5Rts zg6Goy2OSo3MBhEhL*(yS@Egn-K03dod5gY;|Cfh;A2QZpQeaO>s26;{0D<$Fm%Bpn zCL%<=$8e}|q?lqBIyMR~8V)wbiBY0n+<+Grb@)XG=pypj+-Z7`WQ`VuMBnOs*`R7( zZ-~VCC(}VAhI7_0xU?ZG$PB(V3bhEdW^Xn&7;ZTyn(GZCT7-@;%_;EAuMqw)&IPYZ zO$D^xL(i(}gjs%FUU7!%AzHGx3RBe+x-UeCPP}!*zA#?3=l`(x=J8QfSsQRwZ|N*R zfB*?=HXtOZfv|){2uY^`9oZd);5eNGw9*X>iVJqs2_S3K3B*xMR5nKuMhK!KtAHRV zj7}23C4jUr8bau%1BB|%LcZtR>aOktbl!QtcfP+q{avb3x3;dTd+s^UdCoanaa(HW z*;KI@vZH$huA+M#XY<}8f4Z~as756J0kX&-Be)CpZj^r&-qIy}Now#pidn9Ml;;OO z3oj|ywa9L{9P$L7oh*!Y@(9kNd(xa<0gns4L&769jN3{6-`3-vp0xaYoeWDL2Gr8B z5O~Ze()QUFJ|+qhJpi^dvhlWPFvlTsWc3PUDA3dva2jMkB=0TaknlYE<12_DPc4?= z*75L6;l5YX8KdBt#5;kfED7hava@o<^55QbbN8u*;Imv@AUMcTh?ZA)rHF%l0eOYE zD0zz$-%QDy5o3~)lGxlN%dOBttq^Yt5z`9Qo52E;rTG&UFYazb{obP-!GPVq@U2h+DcD;T0NsP#C$WPcvEL-x7 zjk_8Voa_k7haPD0L_V(8)UMRy4buqPm*5E6w-R}&hGQS%KvPbzk5Y%TU)CbMb6X`W z*d<@h&_dbz5*#`fZ_Fb&kzihu?s6jik}r&kf!Y3xEb!9Vd*6buJOjD1g6{jYg7RpA%_Zl~gFK{hw7d7R+Nrx8W8YmsiK?7q z<+!RJ#>#p~*NH2Ia@UlFTol>S;r;mG31Wb=PrxDC#^UpJjRD~6fH}nx^XGUCDEwer zn}AA9SqPpldXLw1uzHSQ4{1x?`+x<~c0vOf4u!=uy!->BYHi3o)qz@^^< zt2zs;YIR*7)e^9($NmbddakWASk)cpUvSyVxB;?fep=Pi)KqYcaZYC+HO`9ca9vla ziq&gVgbC0en%NgX+&Yph7X6>)`8BcO;xU*kz9;U=zuG9ZThJD<6xn8u@M76_RUq*z~vVA1egJx zs%RW^u;FSkoqFWfYSn8a(rN?L*q7_{Cbwpsxe92~$_zsJyuO^0f1!>VT8bF#oViEF z>N}ury+!ioj2AkIoz17A>k*To zQ#e?iTv{!!=86V^C$=GjA9}9ZcZK~`^3`{r+h@)SNU2L(ya-X!n5}D$<2mR{l7$ns zDh-X)_ipbI>9}d#b8COX7t0uV9QKOg*6e4wx)+HJ(w57#&z`(RBHb<9N4;0ve^66e z8QvgWh0mTBT&9#89Tp>w0=8iO?MAUA{o{ibz{&T`*ApT?D3;iR{I}rA#)3=FYahI#iCe8)s0}b zkGN zbgCe{HB;DqFtARoelwI9(m!I)-FX`9xnxErSRr&}{eVMk&j;9^0h$^3#{Lz$G4)IA z%MaR@r^nu%4V0_Zc3Bm3y?PP2fYb1+WAQ#TRSi&5Mh zM7MPL8eMDA_8=RL2);tUu7gcqg6}TK294=`}mTK zdyx<0^3Dz(maJPcUu)-K$wIxsQww784Fh*ZBWInqJO}?$bi;K-H@KxNPjo}94K)!l zb}3(xURdYhk5{&YM??N4Aw~ww@sfGO8xKqW-lb2Jx!`oOG4Ix(duxcYOz=OpeLVLHg5k)DLi zRxL>jO~JMRu%EFtRJN(PHxfme&&~J(i2r!tf^1j!f(_C0_v12Gg3H~mzSmURpX;v^ zDj*Zu)%Tp*UFF3GVPj6{N#mm@8BnIa7*VL#82k>6DL_RUC-lU0-ejCck&Is|yKCy&h`q-~A6eA5I@~ za3sDnd4GokWB=^f?$@jT)niT_rwy=?ryv@=2{_x!jz!?sCJOWfp!+l-*3A#^Wjtvc z>1aHDVbAG3;n}3;RRZMJE!}ot+wZ|yfro1#p2>qhQcP1XL01|kgiY$~YzcVLpe^s5 z**B6H8u;H<%C$Qqzq7#eDZqH#$XfUc#{5gE`csU51pBym^9R_nA+^3*1Fx=pB>50r z2gcz1gtbx*nS!~9MNJK>%9;B%MJ+^{cTPhTVo-$%Ph+GbckYatZYdE z*M>L6*!D8l-VOgb@$3u0v!}NU&i`DQW$%`bwPD%&=Feo&%V*J?=eTBY7*fO_=aB>S z@0X0rPE{=^3dt?KZtv|Gr81ZOK84F3$GGhHF6?D_Zs}EAdGpTAkUZ_Ha@pLM1|~Z_ z2?G)+eN(pk7;OT$O*y};grw+V$4nEMI zP=B+2C3LYH<8(qQjpEK+LUMT}^jX*%%!>Kj!O2cuk1sEIWxBeeH?Zj*Vj`kpW~kj# zvON)VrCWLw=*BVEgG(u^3Rr_;G{%Knina#`rad%b0?UbKqdQC7WE=qr7KXlW**SXJ zlaX%+Hg|Wjw?D^~b?h2mtCEj|MhSiH5d6)LpvgKJ#kfI}T2ol|Y$o|4-G*X;aB$)- zKh*}?FK66ke2u^dIOhp)mo3Cy?t=aOxXUTf#@$koooAYlx@wfz7q;?`)feou6rYs( zj2vrp3LaAU!<)4V)A>a8*LMU3c3pz)f5?l%km5Qjw_-U@ zPfKAe=S$gig`=bkB5t`w>fbO*jAXgb`hZU~Lyf1$*v@Wg$kiUWuU}(3yQR@r!_ZG` z=gxj?XSdWFPe9fob84yk{K>qYY>xo93=fzFr zk!O+(49M`E#CbM}KE`w053mKW2l0}FoL%>m9k2;w(~BveVa(*JgL>owP?--|rtxlR zcP+9Q`$=FvQh%WGd%B(m*^4m#Yvl;iAg5y=*|gFpUE%HLi*wCDuz>ftrS^z@;GCNZ z_)^4x0@;C`hrFdc%QHVEpD%eMwZQpu!REY#ac2W2f?wRx{Iuh-EZFq!z^3d9JG(eFy6Ut&4ENa4JO{^}ws+3D39R5K z{wC{E2flO{{EB|q5@yx|3F^f9sZV_-XI}Ii?1{WM-&f-a4c83%V|5uYuR%gCFv$lR zwKD33^`4EhstHZxJb9?PKb}yU_Z)mU31XCR3cLu)ZEQpwM%*5f?8M>eAs)6}aFuOZ zUAE0Q0jz^K_;M}_(-Dj8c1HoLBg|rd%U_MtVY^ukh*0Aw|5UBgx4mV((x+j4=as$< zEpIA)de-+(rEhIZvC1HO|(PMGe;EYGN^ik<8G~<@Qe2 z<%|veivBSs~!Ee;yi`KeqIhFQ$F@d zcC3VBkJ-Cek0DElPp9A`pA#DxmyPs2-IcK62Lw+RA^7m<`}fuc@J6yS^!!dww*&ehW0fY9gjS_$Rc^cHDpaYcpBt*H7?%D#>RNh*oc9z zlg35>d@ds~HVTB4J;XwhN5{Gh;tjc$UU0bzMhN#C!F4xS4QUtyd9DFMl1OMattT5t z2x(Zi8k(g?(6i9f^N4G(U(aOp?DF(XcHQIGlZu`jo}N@!f4`ogbR9%y(RGHpqWyZ} z=sKRBI9E?&uT0{M(a30)y1V4x_3;zC*dDtx+S$}%uqjQ_sIHy9ETr+j5RZ&)3L`>mpgo|tLv%haP%+m_`ie}8AW_*%r7UJgRek6=Jh@woQwGaNS)Is@i|al{blI4M9_ zDYO&G#~xh1g>wO$ND||Pcjoi(sRNS%6EnmnV*4-G%z8-i$RzRY`S3)szAfJ zlyQ(R>52@0iwiCw!(Yh5k96#s{aBC4zLxj}_dRVLGGa{H_=(dvvi#J}%gyuQaiXTC?035XoCI7qz}cha9?#lHcN|;OIy2lcp0&L#z1f=1Ij1?ovzFry z^YpH0?BH1|Y7Sy+8fO$`_$7_iX>LJQj7WNCJjLSJ?PWNe$Z;5kGUiPD9hw>uQrAp9ANH} z7B;4GQ(pIRl>vj#^qtq8KMk3U2p4k~kLUV*>ltLZBF{`Zi|XoZJ_8*o9djk}k6>Nx zS?^%}0yuE{|>{mt~#B_#en+=ZXt1ZsQ1HEaY+ncwtQiR>O2i=q9P8 z*(3iB%QD)Q;gir!;39h^G_5BoGPOy15k0bmrgfi$Zjzork1U~SJIUJl%QQe>xA|N+Ag&9Xhmqx zp#`B)ycJa=DTijGL-h8pKB|N+-+QA211czfqVMcWxpQX!b@tD*pZaON{UGx0Ew^%! zpG_d2STMBZ1Mqn+H}9RmMZ%NAe4mI+nnf8@UGP%BX6IM0w{OSxFX6EaDD-Fy+YnI* z-|1saW1vhavWD>GYKq5j!FnYupVpyK)VicGIFA~-QVP>{#v#w8+)#wPaJ`B&>NGyrLL06(IbhrwBvo2r4z4eC2Xcx{p_GaD={k`1ve?q?L zoZ9v=gVP_JW8KU_ORU0kIq`zy%H9OW%O?VD-Yr(ghipro!?G7zY1IhFJ$vIFuT;I@ z_^Qh3c;LhbY)@}bonyiYZ!ciIV`x!z`f6-w+wqOV!hNudyIB`b>cak2iHcgh4$F{xGm2SbYhhwXsh3O z;CZxEjdr|$Vx*)0-e(wW3OX^@vHHXqJePYM0ag9k`=B#f@fV$e z&WN*|pnIV+(9vc`!d~x@sCBcIu4crQo^`xp#?`7Uj`y(dhkNhG@h>iV z?nTt!iGMf>PaL&}?)}Ay+`exs$Q~p-b>YI798-#zg-(ad4j*C+;i}o z$EL{nO=P=kS=nmE=2|(afLUBL-^%tD=Ui4m7T3}?7S|G3P}87QMj~sHtWmCny><2Q z>N2Zws?fyjt>cJL&4n~Px3fta(@3^VqoKynnt9SV3%Sjq0Tso8`*lyF*DiCq=6ZUF z|4e;-l)j6u$CN&@y_%$sO5bUhN$Dfot4UHTeaBo`N*~!?O;UY>_jd@?(5LZI#H(rgfDUj2q|;dLU&wuCC2=AYG7sb zTrO(!ytT-N(w9R90O{o`*YD6_k`Gvq$@v;n=5l?#$LcCK&+{Htbfvy}1N57huaJI2 zdgaG^y*TKyvaUktTWa7=a?HF-s$`J_FBPauhXZ#~7ju1g3m+h|MqRQdeF1cxc<4Ig z&g8&nxGV^mk~IpMEQ5m2f@dK*-d_zA$7-{{^S^r2JieA|&ljuKdUF2+9YVZmfOBhu zssxyTbsF*-sF1CVbfXNgZ%*QvoVkd9w@xzQYp8Ff(UTXNf~^vN=6r_%S-?WdGJSw?ME`X0MI-}uK?_z?0Hx$cxun2G*B zz=zh`$N2Ceyyd&%L+403`Qt-_m2W|J-X9+_{u(}nYh-xvp>J^w(tBNA>CVv!MG}srIsr2!)~2^m6of zA#}%lcNE7ZMb{{juwWnZgjo#~Q|>y-aaCxi-{ZL5f91G7ShhoRV?7_sJhUBHe-G_L zwErG%(B%f-Dedb`WQV683se^KHR2JT8JLmDxh_rReY<&gA_(1n{>cCS%@tB>H~rvF=*id54Sch6o2P_BpUV zK5t$m7I2dE@wKu!qr{}yi$r){E0aY{)F+Vh(U;R*u^d0-Mzto&C3U|XWDEwX(@A{J z&{+&LS`7Ac(Hmr=9@$y88K#5FS@O> zA)?@eXsjQ*trKR0q3gkE89$igOsSjN$+~iEiadvF;GAw(CW-(mQF?yg_`Ijb$$DN7y`JYG=gva zDgWaI`+dOSHHj9}S?IgR9V@NdOt>%fsaKcUH6_c?&O-0Cpz@rY>qL?^z{-}to-goa zi;g&)rO)awF+apP0^vdM?)S3&OYoU}`;xcdGQN1kTSzb3>7L}Tp1#8`@C}pi!`~Ai zNt{FW1bEnY$TcbRm|+3QxhGRGuN*-;`qXC}_Ym4E8#r#rdX6i^@_95f+CKa}7E1xk ziD=$AC9D?6QDatqaKl25A4`0Ag#TU>h<$~9qEIxp{97h zo(bsj&M6a``ug>ZMvr$+8Qs*!ujf9xj%Vh$uc^DSyMp*PN>NSTnM0mic4q|tD&kLX z!E475+W!r_y@Bs=+?KaE?oV&SK0&KS+mE&tZ7;STMw91@2QXiB!EA8oYL`i50S5r* zmos|EIDb#f7Y{^BQo+>@UkB8M`=R_?bPzIY&|Gm9mXzK&-VfOy3IB;#?l0d9xxXK{ z71~6|eaQT1)odbHOE&JQr76Ko2Zte0?Tld<)~})A?o?^ATS8)Yw5$z zQ$MbeMO*JHSJhTNIr&OXNY31x^uQ{T=KYY_2bHt3o@Sn9HKJ@&ke_7qp$OQxD#-Q# zD{ZOHeH@Z|1#~i+VaP8{=NpfiXb$EWwV9%6`s3aSxz*Y(TFCZ5j0NuVA|yRONHbK% zYG3qVwIu2JCK;JM{=I|1!(+{TwjL#G(Nv``OZ82&I{Ohn*TqrD_(|7U$=2( z*_>8(MWb}UgE!ok3S57H6!!U@8>Jme-;=JHN*~!3jnYP?Z?;6G z^pRcBC@oX^#=A0%;}zS1EQ?0znLE%8Z4p_6-r2eD4}@}f(S+X6<$0yAn}RZQ!giIi zJy_YUBbz{BCF#!iYy0uG+`Mm@%zlitbu$;aFgr#}GUbZ0Zy4XEa^#kS$M6?25?f>P zlCtS6^liL`b5kS%S-Qs{v+tC&5BT908{k7-f)-SY`TR|?WI66y3CC^2`X#hYST|$& z1loU7mL72XWa$C7zbq|7k5`tKx&3A7X7qSv>1MaTEPWk4URnCO+h3NhqU(5M=_+?? zS(@+u-^ zFv*p9c9Z38E}rVjLdG3eMoXvj&4?1Zh^&EpmfRcQ_^TDw(@tn=Uk*73uhwu#xlXpu zXa4A7;BEGvVRzHgcrD19U=8>HqI8P`EAiDt9XN3ya( zx~BAf)I8fbr?+Mb>@qB_0mbf(Jk@ zk|ryE8PN(qrICEVA;wK?tdCs4?@l@lmZcA1(Vy5t_xg5g1fmx-d9L#?)oifSLG3|;xMf}|XLeV3fasn6>& zM|sF=92buD#aPZmn~ApbFB~@p%XGB=o_ubQ?6pL}kRPN7GZ z&$RB7&ke9Az4DpXee$_M+C$f2@|o8C<#U6y?e_m(K3^=uoK_6ob`9nGL z*#(wchyakKb%0X?T;xVZH$*@XA|f+7Z%O?aBJw8mKz{|2ZYBv#{ZlXo2^+a+c{6;IMU_PR5v$;AHRAMBJ5`cCt+H;k zbT<&nj!1Z(j;7gzj^dN(JT=vqEEn@S8=~i4$}I-I4sCfuZXR(^dz`ss!T2_Bvebmf zT-9uPLHq|Hb;}wL(A$Uq_Y%MYiA9ihmh* z4tx_uzDFtYy(g3Js2i@x_s*^4d&s%JV0QM(ckK@edDC~Eb@fa<8_*i<7-xgu#%d8u zvG+;f9NWZ`z&R4~PQs&S!M|aN;J7GKKDM0BaS~h3y22yr3TIu(Tvi&z8oS_&AsxC2 zIyA+~pM<1dg>Qbe{j4h`lIm2S#J;z{vFBn=x<(^+mCv&FN%LEXiSSDEMIUlp7TT;L z_{UxaR|D-8w0yJ@_-|^_>d*}MI}^<-%X_xMEo3_@waxeQ?>LM$;1SM$ zOt)q9F!uE8|J>XE#D9)na0k1>ui698%2|lH@MX+_Xh~?(Ug5aSXdj?8p-+u%vfgcA zdiO2q(ci!@4AHm1=l^xRJLos{?$19!KEc0%MS!+Z#xNp@ukVx7`U4MPAJVNk5pxG3 zABg7_;7kOL;hemxjN8#g$j=^|xqmJlwa?UDY{K*Jro`9_MGp9C*Q=o0q+>}$hSzKq>2Q;}ILz6Fw&C)*`18i}qP8-Hw z#9!~ACj7?g-C{$Y8aXZb@>`PXYAo@9Jvmg7Uk}fS#sFg6QCTL8)t2Gn$1?dDt9<{1 zT4BeFg=A!m_A+?K<7}>_G2%EO0^j~A*P_E<6XQ+TGGb6`{FLi?k6c4;uIN*)tAllr za)Th}_KG7!`W3g4YmW8{S;)n_guWbPVBs0I=F4*?b7sS~0I$M#wsIB6jlxnMyYUk{ zDEFPh?z^9I-y{A<_uWIe@9v)arsLY)H_aa7aNi%{u7SxR0`3-a^-*nsabPy%{!w+W zEJJHsA_k(0I{mV>S6csqN8abSzpO_7v6URR6ia!m#4`WTE$PcE3*-ZqM-aEHF_|n9}pz?dhJLGS(BI z^qjao(bMB(Jq;cUu}L~`n^->?xFf3}S4hmJGuEPah$lManU)2>rMQH!v$?<(JDw#! z1liDDTTXwv1UA_|$2H%Uvk9=oyuX<&v5~e5_83B0F(=Es9MyT$D>dmE;_2OX3EOf_ zRW5yG3}i*{Ij~rq_cm~G^%dRlO?uDwZFO$m6yXGB{aleN-YoLPQQ}20CXaI(8`{Bk z^X}K$>u^g#bw)+*5Eo`U{Lqv;_Zy4_iVL+bhYuC&L$Fjs&%24`VYD4+)6noOq!kEL z@jXzi0rB5E?IK3lL}jeYz6FvlR0|~%+;~|+h1=4NgM@U%Op;frK^hHSKWSR1E^(Vj z79EV%0qV09oBU>~_N*MOM^Ei>8#i!jIU)v&G}}~Lx#AR5f#-|W+c;;P+igg~IWut< zE6&)N&d4&y()zuAJv#KrIc1R@z!j(TxFt8d)EagSt;hKFTt$!8({r_@m$7%|Aal3B3@1SFEiIQE5@%jK^B2n(_kDJ{EA3yuJuluLrRQ^Wmqi z#4|mGCcOka4ebot5wsm>8_C8b;rLj^3(dBsIpdx4n?XvXdfp4CHN zm~^Hz(=wA@2#vah41xW!=Vbpi`{(S)oCOEy8zK!d8QfbvDxRlU&)Y-xYJ@{}e(!mE zyON70it#*TSCydp!N@2R*;bgrwd8-+R=i}_Y?aUTB)GRJOb6v6#}FGAUg9qiUDGw8 z9<>9IVP#gFLkmXiSLT%t9eB6hz@?=q9GPP)q2@rnw48aGWuEP^(t2t2HQdi$x}v=Q z@qInOv5mES>Zpa!z{|1yO5xZ-*I*S4{5ZCZ4XdfxTK$~kgOXK_0VM=QXT3E08ZiuL&2%je8GxMd9L4sh zYRDz2U8@2bRX4eq^t^4U?JIR+FL3eu8HSnfHS9DEGU-HGA8M#E<(cf&{NSIfod=RX ziS4@>(U%`titBtea^?k#x%0kW}^Y0vevCd~z+O=87ftJxeD{vOJuS-*O z+!azp>%)*=Cms7z)WC5_ddkQ2RW;>tGmt-Om}bys7CZ0>WzJj5VV+NnRwI+#AxjpX zd=^lS)=?6~_Xvm2QpTq1CDDU(=$u8L`QjvGl%rny2zd%P=X;755Tnd2$E{9wCWgpy zt3{r;)!BqiXOSQ663}23=B19-kVb7%u{{{Spg&?zdE+zqnvu`YN}4aS2U(BcNj!rJ z=%?@m!tituw`zRW5o=tEU%C|MD8|?DAV$O~yB5d3ix^ckVpKKwo8nYy{{YYaTI{dG z{(8^;fu8*Xu)iMr2eJK8$vSJPJrMf_S$~InI${q7mdX)ti_N2ijS!wKN4WO!uo30D zEUzKg7|qV$LNm0L#j#?%_Q#emE6ur`l)2h)Fn3k5GER+pN)4^!Q{7Uj()VaX>-bc+^or6qrJ;3vs$2S#(wExM zIzH7cJ)!gsX=ojv>W2T{doTSO+Qz54kr}luF8=?=r^55{e-xiuFQr^1EdA5}MSN<# z6wQt$F3NAmr`CfxXs^+J84b)h$H;jghe(TKDlB-BO5x?a;ap^>Irr4PI=A)_puj6&`|});$)UlE;O}A>|9>8zIubtCubxMpEi1>pfR=~$Fj@v$ z5?Ul$2wG<}8OxXBQ=uc&{&sw7y%by9mgktraQu4dvs!=b{@=x?egi-6>=O8V(N-Wn z6}IagcI!0kqjL`1w-C7&WGhwnqt;6^kllZb&yO0V?$wS^`P6$VFN(x>?~MEk%!g|2 zj9G@fl{6EjVV%5cRAG&_VP>-C65wHnz_a z*aH*|1ASeIhoK1T`)%>Ym&)QZDas`hwF56BYIcvu2fxmX&KP4^KgIpy?P8BDY!83j znJ*&N3whbr+dEo*0I!*gBz+c{KP@Y;BwyPq%*Gb+D@1rCvARlpq*Wxw1ffs$(&tw~ zJXWA@d`G0b24CAVX!qhHMn$#<7eAgogQ3bZXp2!% zbhHnnGNKx^2A;#mDK-=L-`5fcn>)^9752xQq~Arq2FpUXGyuPz&ba?DazKtGOUsr) zwiwkFAv@A7g?sk+_;4*lWo;RqZRMV8P$b}bj)<8ipG_v`FmWxV-|4Lz zwgA4y_~$t8_%py}(6*rMK$FMWgW@Wo_v9`@n3LDjlTeqB5_QON5MWD;te4)aX&V>b z$2Lw#jD`jWjzeqvEL8|bC7zH83r)`%l1weqk=vud6`sNnqr1g}-_Q&l`xyM6z2D%t zu4pHbr|52D?nn6fbk67ZD9Df~BSZDlJ2i2;_)^q;MQ#(yCm6v-Tv#QtM5<0hC#yvL zH{!&T&zM+Lky7Mqb@dkH_!uB;Mt$onumc!^g!Op$cb@ShkDalT#$xom z2xdS5zLy&_BE%Ab#?1)!&5TgK85uL6?CV(=H;H?OFuX|4TQ%4=2%~0DCgoqJQB#94 z(c2UE@AcIr7!z23KBC8H%(Q3yG-kZxieks$jZwVxs?!PL%$@;N5x{7C`LQBwJ$Axc zN3ObH+n0C_LAH32;)~U1L=lW=)s!4QsWA0sMF_NX?@=_es+5t{wZ=QLxP#B*`4hI% z2jhpZmEBJvjuq|N(}-N>oWdVhIJgYJ4|fa{E|P9MY#99Z5TNB38b{zFTY7*M-fUE$jQ!~kIy8+E%gB8`!Z zDM9bZB~A1qBv0@$yHe;HyE8)Z)Vz03xD+g)6*x~ozGyM=G3o~0t$R&Zs{{OMW)c2F zdvOOJg8w=YV~?KW20Xj>(N5x7Ry_&*1IxFt48yhv_FReYKSdPH^FL-jEv8=$ z%S>_@W|8mf$jzdAlnYlP?*M#B7WLt#(0EZ4* z<)L8b0eRLVoAl24do6r*%my{zgfCsjowd$M6oUXi@G3m%^RDCqH7Xs(C32`8v$lYc zyzjMK-O7T%$eXBN$i<~NmlPx;q6-B1)2r zMa{F8p~wrZE_p4rcjfo4$Vid`+B4+qecVyN_)?G)z(k5ugDckA+au~OG=CU)E-AuF zyz>@`Z$XxVA)2A*t3OK(hF53=eycvQ5wcxlQQ9Sj z=dH^)QeB4kr(rdE+n>jqG`)T~griXehBM0%t*!_ehHQK7BW(9Te)+0drr2J`bwY+c z@~{-aV@BQdQlM zSDr)P8?GGsWZF$B4jBwJiS9gPO^GZ-50@B>e?t;8bLcA$h6n6$P5YPxkLEWb&uXSx zdVKj!=SmJ>GmEWgK!ziFgxq z{KtnA*xY2x$TFs3{8;ggx)}do?%n3;ebD$IJnYm<^G-+4(eEDq3uKF|FHW3*?*(l9 ziMX>5%%@yspK~!X2gR0=0Z(HDactIucBUNM$~L1FQmiCL5;CV)wWuBfzFM2b-2+Mn7UMG^LqOn!2>X6}>rVt$5#K z3K0h}7x|{pGVymZTL1YRhtdPw0<`- z@Vmx!N5g+QCHkgx8CK^I!8hZ63rrEYGxF)nP0AUCN~3|sAoxn3GXTA0)hLjQE5EJ3 z^dVe#^vmEqz}}=7?$0e6VHsk$IqF+{CoR$TORO zq;lr|7Q&ZNAy%Jb$pDhfSyPGc3(ghQ77sQPZv4I_$D*oTp?VzK1Xw)8?;<2K8YpqK zg&!vC*_$kyLHyuNxqBJgEBVlIkKUb|hiZh#tw(xy4%X*4{vCQZ=90zoeEe8udxe)( zv{(b5QG_RhsvMJ+$@K3>J(^~MXS{l|IK=HCi6Yx<4`P(gIJ~^F$?1m_37}ST+#z=`ZJ6fnKTFFV-Mozx};HTkNG$U%{6omRS_~| zAP&G6{}psc8OU%b*PEvivUZrZ8jx|F(x`k0I&h7#ZDeqI?l^? zO+Y0SAOY5kV6*-;_jRmA0)4+54~n7~SK)iwedQ<1DlRgYzLSrx(6_agLp5mpwFG~e z*xxs$=daM6c)ff+Uerw~NQpqO!KeB;+6x$K8$@vA^T7Qu!_SKKMl>%E>S%#%6X1*m zT)dIJuYqkW1Fw8tj9hNMH?}TAW`aPv7L5?1AYI*cJZJE7^j2K#s`XQrT@eqRcf z8ECT1Nb$&w_P-GqkOG-OCZ2k)*?%QkxE~4Gm?ZU@_{(|E-As))}x?q z#kB9+N;dQco8D*Ncl%+zJynq#p~SRTZ2v&?jaK?p=PunLMIN->Fp*rKNF+L|S90_! zCoVm*Q)ZD&+3iTTaFOxwRv$++8&%hdVe{2aR0|=`HLM=^lUa5r;O_14hE+J0Sf7ux zH{1hfQ$aG(*;F{&9GtDI-`PUxY%KTGO(_*;lH*b-#>s!I`OBGa6*fKLSj?VF`Ev^4 z_Hs;VY|3f)9RH5?2FBuRv%$lh!*R$=&xvTK@%LFYuMGOWl?2EA(Lk30FTLqE`#;aXj}33PBd9Ijb^gxhIHs!x4Y^yeW1^bj=muk zFgAQ^zQv2v2|rIlc1O}XN8Kjog?|+2V819(z0q5syu-alQnbTuST0`0vC8qiCfY(tEJKeUgle zSqIIf82R&l5!Z94QOoZ02pu%cjpBafR3{w<`m7rabkq`B6&QhUojk3f6`J9E?Xi#m z!yD)UU(%c{EJhzPjAaRqzM0LK3q@#AcdSr{?78 z!CVh1=xjKkNU{cLc#8)`%mYWaWjj2r&}Q&FWE|0;VDJ}Q`o%if9E8HlQjGA#WcF>2 zZu4z=?OuOE(|1??m1ATAai1gkpZstkR0{g2|ITw4=WD%dpD?@anMO?+r#G761ScrFB z%9WYSVix|M;qd=neW?8n>9WIzEr#OVJ6{Ceh4I=I?VCR!Up>C%sV49E?K|1a(DFW? zs5Z~X%flxgsXsoE!WHWMh~TKz+kf~en+nvi$?&Is&8jKD*7 zVlVrTK%aJS;WxDd?qC@1$AIxS2JI5`1H=u+er|~pUdl~@^>9N1BLq*u-+Bl=upIt4 z8h0s{8^{+RTMZi22av$Pq&(u6Jo>{8)F9yE#wz-QtUJgy!#$PJEEYTB4A}~(!(@J+ zSQutz6$FsYfUFl}DZrD(vn+))D#@EgR>G#=v=YAYjH^o+ONC%Ckd<%|>$92^o@dtMS?%zm`XOKVmTMWylVpI+B#G`03d?=6yMjv?L`fetKGu@#{%Ik9Xcr zXzcCR(;GeVd@o788^eteei}ij5@R99VC>EaRAiBVPH6ua7TI1|3t!)L$fUVh@Oh#g zM%#h*%`A>vhvj-Sf4k*|^il1v$1|ruGCc{b12F)1wOdC2rercNf}MzW_9fb3=maE} zmOw5UatYzMAqhY=+R7yd{7fX5ILM_3J!po;`TRbwT-vP2rFY^Nv9-tKgnD^lqL_P+LE3Ygf>*Rd}vB+VFMUDrt7;@;e-yEOrK`b^w7IkSn z;wOtlKUuWSGr!+yqnO&rqPxxSX2>EFY?OzYjY2+R8LyBe4R{(Pjoi}lmZ@NY(+p2o z1<8+Fh?1B4_OxUweHzwxS?Sx>l5R{_Gy^^B{efA<{+faM4$0HAmE`HtO7gTWA7ptdc}#m8c+BlAt{-G|~QETcT(A;5@P>7Um^d?k-2jZXh`_?aD_Mis(wr zy&*+k;bImdUh{6K#SN)U&Q;H1R1)!RbwYa`a>DsAI4Cn?Pu@3sW{q2Tu^vGI=1TKKT-4Ki(ulxvhx3(LamCW(79NC@m@9l~G47ym%JpXn@DRLZ8 z&Q~>ynpIOBl+|+NEUsv|U{5Wf%#?F0H;WX7ItEOg;ME5lmrG(S=zoGQMwa5B-Kfcs zj23QCIjh{jn6yEie7>M}!JZ%G?H z_O91fNyHw6y2@;!Thf{~{R52gO8x?pXSa~^kE|VkiKQy?w`JO$Ce6qjeX2ulE??G8 z?Rj4&+Ys9cJaY@88Yl{7n|K2LO)uBThe_O!URE%Pt5bL1KO27f@o2X&ZsMn7zQwW% z?M19FL-Wdz|9kxNmZbJP8=n>9lNPt6o1SR<{fZ6akAL1myph7?^B@iX7XO65>@&!P z%Tqb-BP>hMQlrg z>{%K?>+O9MtD(nfPt_bIVZvD6I^rLBt%~5&sJ|LHO%IJfemATT?{@zY7Hm5KALbNc zfM^yu=az=MWo5pO%m?0xF3MjOhxZkNcH=>gb4&)lhvm0usZ%&^0vgRx1;XG-q~ViX z;^HSU{r=uI&(*8nFK)$QL^Vu2-Pejzggk-YinugHU=bHq_95JorYSf9$0DaF{@K@? zru6cj-Y$L~hFemSr~l(8h!;Zo*zOFSO*1GSkxp(GZQBOlj@Q59$(;#bbSdP<%ab_n zRV?SA{fPCS(d02kF;g_g-n0LjUou_L^z!EbErOq2lQ<*oy7aj{(S*F8PNORbqf18f zwlXyD*Q&LA2EUFOV@pJnFs>GmKHhgxzs=&?sR5NSz{Ipk{Lt_}UYC~GZ&pW&*O4tS z(i6e6s4v%_B6!+YYFPviFRJUpb>QFCF6T7~QHBnt`U-xq9T7Vm`_DUXFD*k|_d*@U z{kfLJiNv9p>|7Mc#bPZ8EqJ|sK5 z)UoYL5zi%W5Ay66;#s!$>=)`;cJk~WRx0n`mHo{ZUzbYkd};XONn#&E@*l%lb;!Nd zJmPwMHHQhO?!r&HcJYPFV?#%OcED29JQf<}SlYf6KI|jr&Zy*$UpkJ9?T>tRi}Y`# zjxA3!$3WjmI-?Z{J<&I6ey6Pyb#sSO-Hu%02AGP(_zbCw4MDC8>qEd*x}YIiB`Y*Z zKTJPV2NZznB6Nn8F0iG_nwy>uwmx}a1h7YSh~c69qCZv;R}?W#L#Xb@Tf}~hJwUNL zz>q2CO;v~r=9ahZ6iuefe;dy%47GVypz=3mKfNvuv?Kl;wHzipQ__h0K~*CtLhZUV z<0{aJd_wiIGVZC&W!{Q&4Q>PBkGOMLSzss)Ty&5_RU+FTUEHG z>}`7_zFKf23eVR>r>_QsY(WvCwbqvkU)QKmNp*5dqA)?|RWge0BX3J@`5u*kd%c;6 zeYlvjXxJX}16yihD%esN^Br4;q<>wbkBKb}D(+j_zPJk8TBP5%bX4jULYvLUmz7D+ zm7)}bP*Y=FS-ZNpV8mATugm!;hvEzAjiB1sR$z1(Me9?iSJLRhC~6FVHcMWh$M?Nr z?^+u2A&tCDLytf9>@`SCjKRGd)Q$R%YwY@by!CuyBgyv{g!@$CzC*CoVA&o^UCb-? zPWfNggkn7i>zZwWuf1Z|?VBlt4*9w!EGBdtq+oF;M81Y?Qx$jJrY~;4tpypEcLT3K zUh%fQYd*YC`N&T>obCW`z`CV69KTdgaU9@x-04%e4*q{z8zK3?R`_OVzAu1e8tlOk z)Xpq0BHH>Cu1n7YMR>puMWC8I#i^q!e-hteJ_XX%d3Y5ziCnEt|2_U9uL9~_hp6CH zmGGAk(U4r{`gK6KZ%-Qn?yQVXCObms`fB4pvgIFas<-!DRa)nRvv|F z)QCQ)U=41mgMu}&4|IVLqOB&;OLOxC0-=A}vQntl^-Jft> zI$d*jf5LTX-EUat|IVLq6uy|1@TD$6tH%6K&yK5`qFc;zvHsv1lBi0EJE)3Tm)@&# zxG)r4Q!_FX#^tSr4*y7vdSJl0?_B=^%KM$m#?iKEHT;mCL-hj#>Oul)sIIbJSHJR^ zsyixC5Q6E1|3`jTh|%po+1WF2p+&yh`qZwKqz{DX0~O{&WlBRb4eh;0Kbn~t($M|N;1(stRqn}{|N0nGpRPX^i zq6FNC93#nr0_To`YztSrG?X^`O0HzGQy++V(fA4Gb5)&*pK4bbr((vYxZKrZ2eBh0NY6n5wM$60 zFm_c(u&bPobmKV0i)J{M8zEPWQ(a-tQ|`n7JiDo`@aM<5!d~8;zU3g6f7?T>x{CAQ z*i3e60=1AT-@B5Z(AS0Np>1~LYgZ8VfQZ)&GwB1Q34lM`adJ!%$sPw`O1DDB-L1lA!bjHm`tJ$D5^*`jVBt z#wN;cF82|-S}(;befFk&Pai75ZfpSF5yJL}Q1&?2^c3!BI>SOjSzj>heflk4Ci6T` zKe00Fr6yQ|g9I=8j52=difBG3lt`}16NzkIdc`t}IQKf9z84qiL>apjZ&EOLX=+T*-R-D4FN-P|Zp+!3XR*}e3n4XUChgbu)NX!jOYK1yw9;CmZ>gmZ9$p@J^^^*#&zKL=3E88I&(q^CQz- z`njY(P%UD0T~9S^jzqqG@ZqPstgWturS8{FY+aEI@xn2Ps!aKhTzDYxJ!OG}4u4A$E4 z6po8QQ{nG(25`sGDzJScmg}%28B|=h6xG#xFVL>(BGgG;9f;r9GcmJmJkG1YyRg@j z_hBDYm-wfqE>U;E74}oRy70ga0yOiW+lCIu-asYQXNBeXH)wl@f69ONXMeY^i&S&{ zI-FdEzN4-Mn~u7kTAStSmuS3Y7#Amg#A(*5i)W;9&L5jKQD3@db9Iu@@ukbenMHLe zAK(6mcv#%sINEy(_BzS-dWx@;hGDM-y!zglbD9$QTr*uNAOxt;VfhE-I2dy^UsMfaOgOjZp5~%{a?RfEHmP<8#`^!`=Is+lzhQjeI_{S6N} z`lH%;KeHBDArKFoHPkUD3wCQ(G4>kj5U|c;okMo{zF9#Acn-3V&jLNmVTtnQV8fZ} zevTDp)lmH~jDoCgjzY|@g;`X=gfe0rt~R8SxT?;-n3>ZI%7h;z>9CEC&qMEGcnwQq9$)Nib}A33XfeZBqYHq9FRyKlYyi<7Dn z&6}%J3$Ck|nLV*HpIrFsj zTnh1)>!hHouq9)5|Fjy_fi>!`Rb|kx)b)`gez13EGC*C=jo}CX=n`#{uS{yMseLu% z7vUfFZq{#HrVan9*3>y$(_4J&mKNgkl`%IQl|{IWl0;9<%)I zDv#)Ze<3?+r&&5jI#8B&vzi@WWQIY??!*_yC2Xb0FjWj9!%D+(mXSgA8M7<8Rm2V_uma(ua&9Y&S`23 zI92_I(OkW4%v<(w>yP&Ch}TFO0t z?J5=FAM`e;au02%XSM`)Tql*YenPbRd&c+@JV&nduhkooUvPDL?AUU2U2-m00}UT|oDaYbg=g^vY!U6O07vMF-Hzk*jPh{?NTXxOy)H-9lU_t$sU}IExVJh1 zqbqx!CJB~JmAbwNks9Mgb$!dYFCV{Ay-DQji^i!2EfBQuVA6N=;FYvrqUIH*9=sK^ zJ$qh+fls2IKrz*&>2bX}BfT9e-;EQrC71GCQW>)HABfd*XzpJKgaLFO{~NJ27Fpdr8S;YJ{T-$#v%J&}U_9=>D0^?n=* z+CyL*iWD%xDqG(4^r_%QsFy}4JzumGdm>2GtY;v4=E0(%qdslXz|WGuGpl#^)R2l@ z_1qr<&((_R1l@Um&t>~F&$o)^c8k_LihJXn-xt(Lj!F|g~Tf*KkL65>UV;@hKaqi0qt+Fh2VcYWygZMI<${fmLA-v0`noZlui}&3)t@=I z(rAV+zm6=Llp{;Z=JN>oH-U7%uS1?VWrGkiIM9_{mr1x4(4`b5bH95t_k=AN#8M zWO`&dW$`=I*c0DT(FW)Md2grQs0?b)DoOP}iGM zG>LVR?efpnl(WzmQ6E*^lcE$oS!jO8{`Au2tDAnBREgYJ-+Y)E`Bx}FQfjS_P#wnit390&dly+ zlPt;d((n*AiO3=l!pnl7>?4^33~pXfR1^Y9OeBz%1VyXOAgHL=hKCi9S`;4v0wgGw zsOh4j1x33H*apOQZI$3I+6g4?vWeN>_sr}{q@~i|=kxpP*MXDoeVlXdx#!+HcjnIQ zoy*)sT<-TZ2k~xu`Va56w+D{>@O)W)AH|zRyThx`#@Yi1k^8scmRcH#Z@+_`3zetH z_=R5&p1nW3=^hTeggpl@O23R8^-Yy<;Ms6ekDQIjQQve62c8VadhK}oUBKQJJ>PYs zaU6YaroQX88_%FKCu6N@Jl=f=nn4{1Cjz@C;Twer)AKV)9FqN{xE9yrQ_uYSo#BV$ zn!W#wnW7x%Ql3%weA`WjagaFuyf%0K5m9Zr0d-1J{JYp zk5Ks~8-DZeWccMQ+V7Wme!glJV~>Ge{Vp7yF+}fjX5DmbwJrTbZ`(L`V`#Uv0bAWf?fo-r&zmyw`^Lt4Jx0-)WpHsOW^!hslymR44dqQCUUp{b8*vSk&gAkpnTw4GxJQ32 zSi*t5;pQ_s3*X7kzu*@*XBOqnc1u3aknNgon=xdPTVUBPyX`64Bv^hkS$^)d&`SA5 zKYmS#s~9fC+V~JV2g})0u>6jJM*C}u<=gyug2k85UQ;aJ=3k50I>gBGZGI18NAV&x zS>C4)S^hSD6P@j{*qm8gu*0z$n&iUQ1YHi_S*Jzj*u@$VZz^h~axwEESEbA>`|*o- zW?^!$iH&HF)Nk{@)Nh5%th|@GR?5ttz7KZ;8i&uW-Qd$E>Rq)yK5?k4(8mn3e7vE? zS3I}IS2CB$f0rD-!ouVJS+n-L7TXM;kIImIJio#x2#@%%Bd?F+qVXF>uXd$3_m-K% z;p4_S+NHrczTRVbx5ZZEw{m@zbYXmsukU!?oo`#{w+mD7>gb5fGEjd4OK0U>)xd;T_Sg7@V%lNR@k3EcHa?=rh`WZpn|2a@vq|G1ZvS!T?q z@Iu0=HfH!G+GvTN;~G1pp@WV!cCev_W7GBXeCf>Ln`+RYJclnMzfXshD9M{8_|&0C zYvdYo+ZeO@HF;K_mP>D*=gToztXAmh-7XC!E5G)vm06<3g*{MB)RXlt)A(&|@xp6u zCf;z;Fi!tD-`3CYE_M~=LIyb*ecRwg3g6;-x6NdrzHSN`x=y*QJ_A>4`EuZkE)J!Q zu%|ay`ZSuMQwN_kOh`DT!CR;Yq0to5$dEa2@d?;&L32LSC%~$Mc(X*!#mXd7DR+dJ z-V6?za04t{*)H|fxmL7Gz40vcrdwO7J(FD2q9fcF+gt0V_SU!th(^e*^$CeXTr8QH zsOE)pwH^zbZZ*5C=r!rh{W>JgR2SDF^-galUuVkQR%^SHgU4BVGwC0w=%F$OyW(*z zkn7_n=v?_eVIpa^wzK4P+_%;${$t6`EcC#3saVrCP6HiU5SQEf@AHi)kNP|D+zcKY zTJi6g-^PM?=TKK4xyHU;u5ql8=jS=I)}e%cE{dyV%&#VUlTiy3WMLIgXC#!4QscZA zTKlQp4q4#m`A!*F{Y>p>c=R`qO@vj35Wv*PHlSuT_320ssKynKVMVpUl=p6_=_rD2b4PuWl(tziQB;U!MXPq%Wd!>`5PRV$2V2NK4bXyMMX>PE& zC+F^O#vw-cb29XV$rSv)(rYSA@bHd5QBVf;yNG4|R4$9>qL#9QpG zNG%btuXXIn_s$F0d#WyMDq?1XD;9GeaV?~{iS`6%u1T=X6d|FER*70-VvqNg`9w`y zHsjq)=DRpAIu72zzb!^Mu4!|lIT?PNF_2;%bx!mV#6Ht$5j*3gcgdJM^=)G_ezDh> zG{>2hg!wiW-oQWXGi$(a!jmh)f&1~En7&aCymU6Tf-{W}Q^Z9@BWbS`^SAC8^Epqt z!u3_ybPbbtb<*8YuWQ`+g;|W~4kp#E!~QiOM?2kAYZ=(|1-?plR)LYDfR zIDS69I*yWT;WsfC_QT8Z?)+YInRsYhplh5#U$!H z*pD6MJrx$}m|V~aZ+lH*FIb7E^}n`MII})lgnC$eT@zm%BPNK!hQyD#`ZL%yp{M<1 zJ;w5Qwtf9vbuE zz-YXmLG5E!JTHgjz)}CZWpPd6z*g6Xi{hYhQY)^M_Hp7$v@d6(-EGqMX+{`Z{&t3w zwL+pGFb*?=y(#f}T?@l1SCW`lCT#9KKfRep`p|uG*b_+D$=1iCw7-XijoOAggPP9E z>ku}nT4Kxce$b)WiElY3+k=|XShGgsZj&^4)`MNr z*9z-D#eEI!i^JqI5p<;}QqEg=6&Q$vpR;y*R7rY1A0q z4`Ox*2WEVK5IaF>ah8{{N<{0S?@Q@oV)FH(&6_FiZ6)5}9{RS$qO$ADHVt<8jxJ^L zYZAW+>tAc*-R5i9x-g!?u+5sCoTBA*AD-j9mM->64hK5Asa(xw(*nVhD%yji#?0_8 zSTG%}(JT3Q&?JTNp01SH+q3PS-(n|7vWNdZF_{;s4K8%!UB2WLgxb4fOb>eX6Bo6P zEW><|O*UN*n?&~@S)a(e$#WJDW>>?(%zkd=S?+TmD595o>EG24Pu@Cd? z0cQT%JzTLO9N5;adCs(8;ewYJ=uBDO)O*M_4pPr{V;-^fQ*7()(WJ8E)P??}gF&rH4MJOA9Rq9k(F9`FQGB@I*L}!tX9&yU;e- zCb)Z-X~ty+Q;q0rBilVME+n4L;B{W(7_KET?b;K(>2WXbUoE`aXiOXBdL1L*Xs~Tx z&M*@EM-25H2OlcH_hWKE+_*<RV;QWT6a1jfsDE)0_0_)OE1#QoI(*rB!T*6^9BLJx8`!%o zJa*Hu+@R)9cC4`nTBGvmK{jSL<^?8?5AJ9+jd>LH)||*vcF__%e{MC7dEta{ns#(e z`vZFt(;8czYqcr!1@2|rCU9%dOk!KaSHzs4=FZwP;l!^*)?9lwIi9XDr3luZHAUho zx+C!e5tPsJ9H=)a88jAT1?7Q?K=*=HfYyRu05yW%0eL`QfZC`mFLZ!VA}kfk2J-y;qy%SH1Fp7);#;Z0PD6@1JEnC-=h<_usBxAS z*B@+nFT4}uXs;=!bBib3fNP6B9yZ1z4_G18PsSAw+h7(GaJ`V&MWM-JV#*Y7Uf-qv z!X(#lz2z|1-{bH}aq-vzi%FOZQ|5)9421)MPT@Iv^3qSX;JWKWT-z692(n4`jhjbW3$p@TU%d=bj))o^%Y3ilB&?!~$GduDF;^lN91Bo{Y)PiyVS{vIax z5_*mN+Rc*HvNUocPgfA{bYiqCX}wY?{#oamSX% zl-yu9Sw5|O{vOya)U?mtgZsGT3D6uA4vdU}#}YL{M6)SnUF#uptRi=+o2)=CGmf(l zj`JQi*R$A|8F zuR@Qzo7>C!@Z37wUGe-n0arH$(`OGn9qg4J4!FA2D?a_caA1G8RH4V0iNb-`y5Flf z`2fzmOrK6E{|x-*Tl%}l${fa7=P5I1S1oh+bXPfi z?+JEaewD-bF4m_84?f_bmCAUJ)yI^TIe0kdjaEv-nx&nYF81ze-|gAG&o5y05B3^* zu6;V2QQuo{#oBGZ%l7Ts)0wd4>C@E0)Lwd}m8Z2&*+a27YP|_H?GyG;`_;4$+e588 zs+D3oYR!q$+P~jTX(_E2`$bLr`@0d-)U@~7gPx$RY4`8$gKOyUR2|l=afNN5wQIte zLCwcly~Zka#ayglV^xkqgWOyLSv29gz>Pp`~ zoa)+oRF~50rp93Ivn#s)Otwxv=Ei-ja*ebK>!b_BHL!ajzJbMD9L{gQ4>NPNi}Z8N zGlTkXaK92(pF-Rj)ORwMn&t~nP@YWmO!I~}{7c#=|0eC=k7Q@C-bed%us*$y_WHE4 zeRAv;t%$yT%ht{0GqwzhgQOAUY z&@jx#hLG@`%@-G^4G9+}8t^+f+)q3f>{h zki&OXwh=1~BOx*AHa+|S}XeaAhiMFQwKf42`!9CDUdw!DLMT*_= zZQ+T!qeZZLXB)32yYCc__&LFfw`}>?ctLhzuXC$5tPR4rR!i|W72Yx*PnXN9+@R+bQ1 z@x%paz?%u=!I}`anS7Yn!-unb_>dPL_U_MI*0Mje`U2gj>O5JQTuVvjl4Dpay{^)G z7%SfTP;77%o@pCGv7I)bUOyaRqc{vZJUe_zGh#xqfjn`joyupZ!|Lz2&3U2@J{90o ze!c3|DWMw;E%bj{I1v|j_pKssidSc~C{ z6pVr1;Iv-Qh_8oMogdV6(65Wgp5**-y!Yp3sU29f!YmaLkgv*%&Wt2^*?5G8l!k=MHDEnsfl1Ox6BaPByS zCpGKhInALro*wU4h?`exsYeH>$hq)HU2Jn@aa(AcR#@9z$53v$olx>NBb^>94R zKo7qSBW0_i#e}vOEOhSN+8LXAN2aDl?}-U%(Z@9>xJj5fhv9w-fAMWarB^S{Iv}zG zzxygtUgI_Xvpd`~UVBM=%_VX7C2{$Z_@PVU2KmSO^_Rpom&7+*BA;|g{J^)}VSOXk z0~**WhT||t;oXl@xM%wRi*QWOas?{4PNH%nHav1MT)&dSJ#9G56aOxW(pT-J@SdR* zmJV|(*eZP^g%9hMbVW~3S%JzmG}b9RF~qY&Eh|CcUqR^`p>xlQ!`D%`r|jjzhczU- zT_XM;h2t*jJZw!fktll%^8j)HYkF_84Eilnn{wR{th($gYwi-J3(+kw}@-uXb%KSxR5B^eof z4!bQtG__>m!ixMBAk}j}aEH(+ol@d;c)dwYKMf>3-bnlm&>afboCO{S%D@(2JMa`R z2=oHGfL{U`ujt5_#ZK)g;mEL8x>KW8KPGLY(L5>)v@1?!{@3ht2304aZh zhVtvAn-$zGU8`03O$x$)K(c>sBz_9G6LK0I@$Ha`6|9paAnDr(tXpwdniHe)bpgpg zxq7vnXNjsE`xV?F)f&S!2a&!RNayGS3f4(S6>LzD>eU{JFYm3^ zbABIH&z!!fFWP+-ko+hEsUMW}Q{(q3*dQ%cuwMEWxEt*yUZv*e1F2p)K&s~vCA~pn zSBGmR!LD{7jWc5sA^J729`dyVRsJu5yHOq+jQl+siCu$yvIj_h-vA`NqlQqvP6`6g z2GRFS6pxd(q!3@7bO7i@x-nIiO9zr&X5ew8rw^m_9nwQUH{!npQu+o;->H!fDEW1g z8%X6PU57D`{D$EqS0|kT?m_=Fj0o4fj&$S5aLs<;>d};6F9m^=-bL}9I!Q_cBEAN= zI}!bO4C;mWwLr3KFp%siQ*gI*T{^|u)0;FsTp zYaRlUUzP*Ch@UNuq?fC5`|nZZ%!^bx6VMI5sX&sO1SCJMsZh(SU82ezsZ`~rI#sy| zK&sb6K&sd3dsTi`t@2M@rq<^Oko0*?$N~a>1>tocw|+SN5VRHy=pltpZYcwLm(L6mC=N zExn}5je1#4uLn|jF9C_a1xW3({1vsF)paWWOWRfcemhit1CaPFK;l0RB)c}&tNgXQ zRDQNwzyEbr zZo)oQZWNIEZ;paHrRBi=(3ATHr8h|V3f4U>A-Z@k^TYZC1Bl$=#N16$7=p@An6Z&qSk-)pCWpW<9ZH!Ujj*=;Zx$r zJO`wCZ-WwVke&z9yxSd#oByo(_aKn!8TS{$2C1KdJ0uafXX##vwW#S`h}Td1nKWC8 z*GUT$+#zj=->Nf!Er*V?` zuWG%H{7p@lfux6d)p!VTx-QB6yPCcfI05BW11AB037iUi2xtL52vo*-E0u?K@vDB= z`mLI7vlbN06X)D$n!aRV<X^n2Mq$caL!_xCio6M$BgS6;&)NVIuK@FDpN@pdi98 z{#$;P&mLuqMA^d1#bcH&nNU?yvSiGHqN=Jf5o@ni&?e5AXPs5(__;Nkm1Zn`U}pJp zR{HajY6ZoTlHvtL_{#}T2g#}d2w|aE6ro21y`WVp6$q=RlrJTmMAdDY*|Lwc<*Ul$|Xfh7NYLOl% zOqI1Xzp`?1LHUCyDWhmHPAorHPD~Xu(T%P^Pww$ND#0pU?tRnptjw&hu$6O7rqd?z-afJX6*HDU6Z1^R*n z{&)P(1OM~D|2*(N5B%32u#CYu6-37a5maO9--pw&-y-Oyv5XBGhjTKhKYll!DdM}2 znfPuAsOOP4k+C~K?}G~P+k6hc)gJ)59RGCa$^(53dSL?InIPT>{|U%ns(&By4udA& z$e0Vr;n#!%K$p{h+ceA-pesFSPb<#CSUK=ED`R~T{sqGKgPsL#1MLKjKwi(|3B;eU z;d>Ew?7Fh`*KrSAd=dZHlD59KnlH7ekH6`v!EmdbVXDFI&~0 zIUU~|1#eXU!-!7@k$x@Ot>^I!(&O=aKeB5k(2sa0C~DW?h}`>*o>Gi`j&FhVzfG0< z6ZVtpSsvBrCgf3hCHe4YA=(jSEkGa3MLW-e9MXp&>;cjtfb^9d!_>}NIL599uDKq2 zUjchZXjKZnPlB*sk9Hvhg~H*=e*$q?z_KA14>W?bpw+z?iv#{8kuh9Ku=&@(7T`w2 z3AaVCA%goOcmPNbq7MTH0xgR;HW+9C4FKgJJ_tzVQ(1Hj0a01_j1Ow@e}7~?k9t&b zECZAS$_3HU>wdNal#iQ`u!~ai+{6HR{{`2TU>?H_V23kxs z7k%(fTq7=EY&*gyiZG_(Xh9pcE(!Pk4Rkzdy2D`Q(NBwJpGF}5A$*JGR@tRBvHP=rP0%eE8W=errZvjO{h?1jw; z4}EkI>6{w(mu*v3oopKMefm0M6W_oX#P7Eo5vJqgBU2B2d?cs&Y~G|lfcIwN8~Y|> zMQ@>g&8T-1&U=5TnMS1Y=O{>gU%5~&tl9M*%0>9;_c5mb2;CpR{|KKrgmcbe`0XR) zBOKA=+PrCi3uWF6pIPwbE5%PAyU{L3alZT%K0=uCsf@LMfxRtgn-e&1Aguii?F)M0 z6#RJ->3>68cwxss&~^wL=M0!uTKdW~l1)AhpMdtAf&af^thBUrn(DWZ; zmHdwHP>%q@PVb8LDn$9f^G9wbNohDZrB(%%t>-xl`b*vE++dlcbl9-XZ4U*VbDmt!ZApmQ+C z+WLSe%Wl8XWX`&E)(F#tv`LK4m9Zc~B(l4)9Ap}sHg+uH)}P@|QAyE)a>k8DP;1Sf zX}a%cOcxhp)nkL)IKja6(e&f`b5{#V+(3SiFoaLxMsX~ys;sJdX?4*8mR3%ST~3x( z{J@f`2NtVXy_BVu6;+k7w525#l%ocm71b=Qx@0;2qM$ScNP!wGFJ2C&%HpExB9>N) z)rNUROP6Ae3Hr;cqhZQbR4%Pl3MyJ$zL2HeT?vJ%;DV|umWDg$#aM!4X-g`rOVaLM zvJ4y*#iJvOm1==S)zwSO7c8sBJ?npQ#DkYwfd@@MfQaU<=s|gOP#WAgp;~fEs0*KdSG@5{@0Yi&Od*l9eM`?mEPxe9Vc^d|X>Zl_4+6w-I5ofwJh@ zBV!@QFoFDVMEQP;6w;R-$ss=Km(hdrh+Y9vzla`%;2Ru`0HgYv5k{HLXqFRvlcEtI V>7s+MhuN$Sd><=0>Ypgz{{j9{WcmOA literal 0 HcmV?d00001 diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj new file mode 100644 index 0000000000..494ff6044b --- /dev/null +++ b/osu.Android/osu.Android.csproj @@ -0,0 +1,175 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {122416d6-6b49-4ee2-a1e8-b825f31c79fe} + Library + Properties + osu.Android + osu.Android + 512 + True + Resources\Resource.designer.cs + Resource + Off + false + v8.1 + Properties\AndroidManifest.xml + Resources + Assets + Xamarin.Android.Net.AndroidClientHandler + + + True + portable + False + bin\Debug\ + DEBUG;TRACE + prompt + 4 + True + None + False + false + false + false + CJK;Mideast;Rare;West;Other + + + + True + pdbonly + True + bin\Release\ + TRACE + prompt + 4 + true + False + SdkOnly + True + + + + + + + + + + + + + + + + osu.licenseheader + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + 0.22.0 + + + 1.1.0 + + + 1.0.0-beta0006 + + + 1.0.0-beta0005 + + + + + + {0fd409e8-a359-42bd-bc52-6a4745a122e5} + osu.Framework.Android + + + {0a8ba083-9d08-45ad-8653-796db1653388} + osu.Framework + + + {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} + osu.Game.Resources + + + {58f6c80c-1253-4a0e-a465-b8c85ebeadf3} + osu.Game.Rulesets.Catch + + + {48f4582b-7687-4621-9cbe-5c24197cb536} + osu.Game.Rulesets.Mania + + + {c92a607b-1fdd-4954-9f92-03ff547d9080} + osu.Game.Rulesets.Osu + + + {f167e17a-7de6-4af5-b920-a5112296c695} + osu.Game.Rulesets.Taiko + + + {2a66dd92-adb1-4994-89e2-c94e04acda0d} + osu.Game + + + + + + + + \ No newline at end of file From f083b186638c2859eded8173903cfa30424536a0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Dec 2018 17:59:42 +0900 Subject: [PATCH 0315/5608] Update in line with framework changes --- osu.Game/Online/Chat/DrawableLinkCompiler.cs | 11 +++++------ osu.Game/OsuGame.cs | 4 ++-- osu.Game/Overlays/Music/PlaylistItem.cs | 5 ++--- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/osu.Game/Online/Chat/DrawableLinkCompiler.cs b/osu.Game/Online/Chat/DrawableLinkCompiler.cs index de017baf35..2b0a49cb6c 100644 --- a/osu.Game/Online/Chat/DrawableLinkCompiler.cs +++ b/osu.Game/Online/Chat/DrawableLinkCompiler.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -15,20 +14,20 @@ using osuTK; namespace osu.Game.Online.Chat { ///

- /// An invisible drawable that brings multiple pieces together to form a consumable clickable link. + /// An invisible drawable that brings multiple pieces together to form a consumable clickable link. /// public class DrawableLinkCompiler : OsuHoverContainer, IHasTooltip { /// /// Each word part of a chat link (split for word-wrap support). /// - public List Parts; + public List Parts; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Parts.Any(d => d.ReceivePositionalInputAt(screenSpacePos)); protected override HoverClickSounds CreateHoverClickSounds(HoverSampleSet sampleSet) => new LinkHoverSounds(sampleSet, Parts); - public DrawableLinkCompiler(IEnumerable parts) + public DrawableLinkCompiler(IEnumerable parts) { Parts = parts.ToList(); } @@ -45,9 +44,9 @@ namespace osu.Game.Online.Chat private class LinkHoverSounds : HoverClickSounds { - private readonly List parts; + private readonly List parts; - public LinkHoverSounds(HoverSampleSet sampleSet, List parts) + public LinkHoverSounds(HoverSampleSet sampleSet, List parts) : base(sampleSet) { this.parts = parts; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index cd40d4793a..73ecbafb9e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -553,9 +553,9 @@ namespace osu.Game try { - Logger.Log($"Loading {d}...", LoggingTarget.Debug); + Logger.Log($"Loading {d}...", level: LogLevel.Debug); await LoadComponentAsync(d, add); - Logger.Log($"Loaded {d}!", LoggingTarget.Debug); + Logger.Log($"Loaded {d}!", level: LogLevel.Debug); } catch (OperationCanceledException) { diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 5d89e53081..40a395535d 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -7,7 +7,6 @@ using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Beatmaps; @@ -26,7 +25,7 @@ namespace osu.Game.Overlays.Music private SpriteIcon handle; private TextFlowContainer text; - private IEnumerable titleSprites; + private IEnumerable titleSprites; private ILocalisedBindableString titleBind; private ILocalisedBindableString artistBind; @@ -58,7 +57,7 @@ namespace osu.Game.Overlays.Music selected = value; FinishTransforms(true); - foreach (SpriteText s in titleSprites) + foreach (Drawable s in titleSprites) s.FadeColour(Selected ? hoverColour : Color4.White, fade_duration); } } From 8907ce3f6300d558ad5490eadf7ee53e0e0df719 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Dec 2018 18:11:04 +0900 Subject: [PATCH 0316/5608] Automatically fix invalid pairing dates on load (based on contained groupings) --- osu.Game.Tournament/TournamentGameBase.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 4938533a9e..5c9bee560e 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -109,7 +109,12 @@ namespace osu.Game.Tournament foreach (var id in group.Pairings) { var found = Ladder.Pairings.FirstOrDefault(p => p.ID == id); - if (found != null) found.Grouping.Value = group; + if (found != null) + { + found.Grouping.Value = group; + if (group.StartDate.Value > found.Date.Value) + found.Date.Value = group.StartDate.Value; + } } Ladder.CurrentMatch.Value = Ladder.Pairings.FirstOrDefault(p => p.Current.Value); From 5d7043156be563cd434e94913f383e2269fa17b2 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Fri, 14 Dec 2018 09:07:17 -0600 Subject: [PATCH 0317/5608] Attempt to get the icon right. --- osu.Android/Properties/AndroidManifest.xml | 3 +-- osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml | 2 +- osu.Android/Resources/values/Strings.xml | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index 12d1f326b9..4ae7d35c2e 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -4,6 +4,5 @@ - - + \ No newline at end of file diff --git a/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml index 036d09bc5f..9412204815 100644 --- a/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml +++ b/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/osu.Android/Resources/values/Strings.xml b/osu.Android/Resources/values/Strings.xml index fa7ba67465..21f749f876 100644 --- a/osu.Android/Resources/values/Strings.xml +++ b/osu.Android/Resources/values/Strings.xml @@ -1,4 +1,4 @@ - osu.Android + osu!lazer Settings From 214908aaa024c816032de5df11ed8ff35cbd6407 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Fri, 14 Dec 2018 09:27:02 -0600 Subject: [PATCH 0318/5608] Add opsu migration, fix font not rendering --- osu.Android/GameView.cs | 3 +-- osu.Android/MainActivity.cs | 2 ++ osu.Android/OsuGameAndroid.cs | 44 ++++++++++++++++++++++++++++++++++ osu.Android/osu.Android.csproj | 5 ++-- 4 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 osu.Android/OsuGameAndroid.cs diff --git a/osu.Android/GameView.cs b/osu.Android/GameView.cs index 649ee0134b..dfae65a2e9 100644 --- a/osu.Android/GameView.cs +++ b/osu.Android/GameView.cs @@ -3,7 +3,6 @@ using Android.Content; using Android.Util; -using osu.Framework; using osu.Framework.Android; using osu.Game; @@ -21,6 +20,6 @@ namespace osu.Android { CreateGame(); } - public override Framework.Game CreateGame() => new OsuGame(); + public override Framework.Game CreateGame() => new OsuGameAndroid(); } } diff --git a/osu.Android/MainActivity.cs b/osu.Android/MainActivity.cs index 3a8a5026bc..ff1fd9eba1 100644 --- a/osu.Android/MainActivity.cs +++ b/osu.Android/MainActivity.cs @@ -5,6 +5,7 @@ using Android.App; using Android.OS; using Android.Runtime; using Android.Widget; +using Android.Views; using Android.Content.PM; namespace osu.Android @@ -17,6 +18,7 @@ namespace osu.Android base.OnCreate(savedInstanceState); // Set our view from the "main" layout resource SetContentView(Resource.Layout.activity_main); + Window.AddFlags(WindowManagerFlags.KeepScreenOn); } public override void OnBackPressed() { diff --git a/osu.Android/OsuGameAndroid.cs b/osu.Android/OsuGameAndroid.cs new file mode 100644 index 0000000000..e2f016887d --- /dev/null +++ b/osu.Android/OsuGameAndroid.cs @@ -0,0 +1,44 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Android; +using osu.Framework.Platform; +using osu.Game; +using System; +using System.IO; + +namespace osu.Android +{ + internal class OsuGameAndroid : OsuGame + { + public OsuGameAndroid() : base() + { + + } + public override Storage GetStorageForStableInstall() + { + return new OpsuStorage(); + } + + // For better migration from opsu! to osu!lazer (WIP) + private class OpsuStorage : AndroidStorage + { + bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")); + + protected override string LocateBasePath() + { + BasePath = base.LocateBasePath(); + string opsuInstallPath = Path.Combine(BasePath, "opsu"); + Console.WriteLine(opsuInstallPath); + if (checkExists(opsuInstallPath)) + return opsuInstallPath; + return null; + } + + public OpsuStorage() : base(string.Empty, null) + { + BasePath = LocateBasePath(); + } + } + } +} diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 494ff6044b..42e472bc83 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -63,6 +63,7 @@ + @@ -120,10 +121,10 @@ 1.1.0 - 1.0.0-beta0006 + 1.0.0-dev000094 - 1.0.0-beta0005 + 1.0.0-dev002278 From a7c82c97416a5f8777299e57715e4a8b7bdcb207 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Dec 2018 16:50:38 +0900 Subject: [PATCH 0319/5608] Split out chat component into reusable piece --- .../Components/MatchChatDisplay.cs | 168 ++---------------- 1 file changed, 13 insertions(+), 155 deletions(-) diff --git a/osu.Game.Tournament/Components/MatchChatDisplay.cs b/osu.Game.Tournament/Components/MatchChatDisplay.cs index 41efd0833b..8eedded0f1 100644 --- a/osu.Game.Tournament/Components/MatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/MatchChatDisplay.cs @@ -1,59 +1,23 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; using osu.Game.Tournament.IPC; -using osuTK; using osuTK.Graphics; namespace osu.Game.Tournament.Components { - public class MatchChatDisplay : CompositeDrawable + public class MatchChatDisplay : StandAloneChatDisplay { - private Channel lastChannel; - public readonly Bindable Channel = new Bindable(); - private readonly FillFlowContainer messagesFlow; - - public MatchChatDisplay() - { - CornerRadius = 10; - Masking = true; - - InternalChildren = new Drawable[] - { - new Box - { - Colour = Color4.Black, - Alpha = 0.8f, - RelativeSizeAxes = Axes.Both, - }, - messagesFlow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - LayoutEasing = Easing.Out, - LayoutDuration = 500, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Direction = FillDirection.Vertical, - }, - }; - - Channel.BindValueChanged(channelChanged); - } - private readonly Bindable chatChannel = new Bindable(); + protected override Drawable CreateMessage(Message message) => new MatchMessage(message); + private ChannelManager manager; [BackgroundDependencyLoader(true)] @@ -92,132 +56,26 @@ namespace osu.Game.Tournament.Components } } - private void channelChanged(Channel channel) + protected class MatchMessage : StandAloneMessage { - if (lastChannel != null) - lastChannel.NewMessagesArrived -= newMessages; - - lastChannel = channel; - messagesFlow.Clear(); - - if (channel == null) return; - - channel.NewMessagesArrived += newMessages; - } - - private void newMessages(IEnumerable messages) - { - var excessChildren = messagesFlow.Children.Count - 10; - if (excessChildren > 0) - { - foreach (var c in messagesFlow.Children.Take(excessChildren)) - c.Expire(); - } - - foreach (var message in messages) - { - var formatted = MessageFormatter.FormatMessage(message); - messagesFlow.Add(new MatchMessage(formatted) { Y = messagesFlow.Height }); - } - } - - private class MatchMessage : CompositeDrawable - { - private readonly Message message; - public MatchMessage(Message message) + : base(message) { - this.message = message; } - private readonly Color4 red = new Color4(186, 0, 18, 255); - private readonly Color4 blue = new Color4(17, 136, 170, 255); - [BackgroundDependencyLoader] private void load(LadderInfo info) { - Circle colourBox; - - Margin = new MarginPadding(3); - - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - OsuSpriteText senderText; - InternalChildren = new Drawable[] - { - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Children = new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.X, - Width = 0.2f, - Children = new Drawable[] - { - senderText = new OsuSpriteText - { - Font = @"Exo2.0-Bold", - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Text = message.Sender.ToString() - } - } - }, - new Container - { - Size = new Vector2(8, OsuSpriteText.FONT_SIZE), - Margin = new MarginPadding { Horizontal = 3 }, - Children = new Drawable[] - { - colourBox = new Circle - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(8), - }, - } - }, - new OsuTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Width = 0.5f, - Text = message.DisplayContent - } - } - }, - }; - - if (info.CurrentMatch.Value.Team1.Value.Players.Any(u => u.Id == message.Sender.Id)) - { - colourBox.Colour = red; - } - else if (info.CurrentMatch.Value.Team2.Value.Players.Any(u => u.Id == message.Sender.Id)) - { - colourBox.Colour = blue; - } - else if (message.Sender.Colour != null) - { - senderText.Colour = colourBox.Colour = OsuColour.FromHex(message.Sender.Colour); - } + if (info.CurrentMatch.Value.Team1.Value.Players.Any(u => u.Id == Message.Sender.Id)) + ColourBox.Colour = red; + else if (info.CurrentMatch.Value.Team2.Value.Players.Any(u => u.Id == Message.Sender.Id)) + ColourBox.Colour = blue; + else if (Message.Sender.Colour != null) + SenderText.Colour = ColourBox.Colour = OsuColour.FromHex(Message.Sender.Colour); } - } - public void Contract() - { - this.FadeIn(300); - this.MoveToY(0, 500, Easing.OutQuint); - } - - public void Expand() - { - this.FadeOut(200); - this.MoveToY(100, 500, Easing.In); + private readonly Color4 red = new Color4(186, 0, 18, 255); + private readonly Color4 blue = new Color4(17, 136, 170, 255); } } } From 660be6a2a454d950bba18c524ba83b7ca9bef8f8 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Thu, 20 Dec 2018 09:11:20 -0600 Subject: [PATCH 0320/5608] Remove ability to import from opsu! This has been struck down by @ppy --- osu.Android/GameView.cs | 2 +- osu.Android/OsuGameAndroid.cs | 44 ---------------------- osu.Android/Properties/AndroidManifest.xml | 1 + osu.Android/osu.Android.csproj | 2 +- 4 files changed, 3 insertions(+), 46 deletions(-) delete mode 100644 osu.Android/OsuGameAndroid.cs diff --git a/osu.Android/GameView.cs b/osu.Android/GameView.cs index dfae65a2e9..fc9cdeda53 100644 --- a/osu.Android/GameView.cs +++ b/osu.Android/GameView.cs @@ -20,6 +20,6 @@ namespace osu.Android { CreateGame(); } - public override Framework.Game CreateGame() => new OsuGameAndroid(); + public override Framework.Game CreateGame() => new OsuGame(); } } diff --git a/osu.Android/OsuGameAndroid.cs b/osu.Android/OsuGameAndroid.cs deleted file mode 100644 index e2f016887d..0000000000 --- a/osu.Android/OsuGameAndroid.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Android; -using osu.Framework.Platform; -using osu.Game; -using System; -using System.IO; - -namespace osu.Android -{ - internal class OsuGameAndroid : OsuGame - { - public OsuGameAndroid() : base() - { - - } - public override Storage GetStorageForStableInstall() - { - return new OpsuStorage(); - } - - // For better migration from opsu! to osu!lazer (WIP) - private class OpsuStorage : AndroidStorage - { - bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")); - - protected override string LocateBasePath() - { - BasePath = base.LocateBasePath(); - string opsuInstallPath = Path.Combine(BasePath, "opsu"); - Console.WriteLine(opsuInstallPath); - if (checkExists(opsuInstallPath)) - return opsuInstallPath; - return null; - } - - public OpsuStorage() : base(string.Empty, null) - { - BasePath = LocateBasePath(); - } - } - } -} diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index 4ae7d35c2e..76cb58969f 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -4,5 +4,6 @@ + \ No newline at end of file diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 42e472bc83..8a481b5239 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -40,6 +40,7 @@ false CJK;Mideast;Rare;West;Other + false True @@ -63,7 +64,6 @@ - From b4fa2d90491066ac834d18be5517de473da0ac05 Mon Sep 17 00:00:00 2001 From: jorolf Date: Sat, 22 Dec 2018 16:51:24 +0100 Subject: [PATCH 0321/5608] WIP --- osu.Game.Tests/Visual/TestCaseUserPanel.cs | 1 + osu.Game.Tests/Visual/TestCaseUserProfile.cs | 15 +- .../Graphics/Containers/OsuHoverContainer.cs | 3 +- osu.Game/Graphics/OsuColour.cs | 10 + .../Overlays/Profile/Header/SupporterIcon.cs | 82 +- osu.Game/Overlays/Profile/ProfileHeader.cs | 1089 +++++++++++++---- osu.Game/Overlays/UserProfileOverlay.cs | 6 +- osu.Game/Users/User.cs | 21 + osu.Game/Users/UserPanel.cs | 4 +- osu.Game/Users/UserStatistics.cs | 18 + osu.sln.DotSettings | 1 + 11 files changed, 981 insertions(+), 269 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseUserPanel.cs b/osu.Game.Tests/Visual/TestCaseUserPanel.cs index a53af247f3..81b7465d47 100644 --- a/osu.Game.Tests/Visual/TestCaseUserPanel.cs +++ b/osu.Game.Tests/Visual/TestCaseUserPanel.cs @@ -38,6 +38,7 @@ namespace osu.Game.Tests.Visual Country = new Country { FlagName = @"AU" }, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", IsSupporter = true, + SupportLevel = 3, }) { Width = 300 }, }, }); diff --git a/osu.Game.Tests/Visual/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/TestCaseUserProfile.cs index cb281d045b..ce41bc22ff 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/TestCaseUserProfile.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Overlays; @@ -27,7 +28,9 @@ namespace osu.Game.Tests.Visual typeof(UserProfileOverlay), typeof(RankGraph), typeof(LineGraph), - typeof(BadgeContainer) + typeof(BadgeContainer), + typeof(SectionsContainer<>), + typeof(SupporterIcon) }; public TestCaseUserProfile() @@ -58,6 +61,11 @@ namespace osu.Game.Tests.Visual { Ranks = new UserStatistics.UserRanks { Global = 2148, Country = 1 }, PP = 4567.89m, + Level = new UserStatistics.LevelInfo + { + Current = 727, + Progress = 69, + } }, RankHistory = new User.RankHistoryData { @@ -72,7 +80,10 @@ namespace osu.Game.Tests.Visual Description = "Outstanding help by being a voluntary test subject.", ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg" } - } + }, + Title = "osu!volunteer", + Colour = "ff0000", + Achievements = new User.UserAchievement[0], }, false)); checkSupporterTag(false); diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index af804735a8..418ccac290 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -33,7 +33,8 @@ namespace osu.Game.Graphics.Containers [BackgroundDependencyLoader] private void load(OsuColour colours) { - HoverColour = colours.Yellow; + if(HoverColour == default) + HoverColour = colours.Yellow; } protected override void LoadComplete() diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index fc627fa501..b069f2bf0e 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -92,5 +92,15 @@ namespace osu.Game.Graphics public readonly Color4 ChatBlue = FromHex(@"17292e"); public readonly Color4 ContextMenuGray = FromHex(@"223034"); + + public readonly Color4 CommunityUserGreenLight = FromHex(@"deff87"); + public readonly Color4 CommunityUserGreen = FromHex(@"05ffa2"); + public readonly Color4 CommunityUserGreenDark = FromHex(@"a6cc00"); + public readonly Color4 CommunityUserGrayGreenLighter = FromHex(@"9ebab1"); + public readonly Color4 CommunityUserGrayGreenLight = FromHex(@"77998e"); + public readonly Color4 CommunityUserGrayGreen = FromHex(@"4e7466"); + public readonly Color4 CommunityUserGrayGreenDark = FromHex(@"33413c"); + public readonly Color4 CommunityUserGrayGreenDarker = FromHex(@"2c3532"); + public readonly Color4 CommunityUserGrayGreenDarkest = FromHex(@"1e2422"); } } diff --git a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs index 1325ea4e9a..8b33a60d37 100644 --- a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; -using osu.Game.Graphics.Backgrounds; using osuTK; namespace osu.Game.Overlays.Profile.Header @@ -15,50 +14,73 @@ namespace osu.Game.Overlays.Profile.Header public class SupporterIcon : CircularContainer, IHasTooltip { private readonly Box background; + private readonly FillFlowContainer iconContainer; public string TooltipText => "osu!supporter"; + public int SupporterLevel + { + set + { + if (value == 0) + { + Hide(); + } + else + { + Show(); + iconContainer.Clear(); + for (int i = 0; i < value; i++) + { + iconContainer.Add(new SpriteIcon + { + Width = 12, + RelativeSizeAxes = Axes.Y, + Icon = FontAwesome.fa_heart, + }); + } + } + } + } + public SupporterIcon() { Masking = true; + AutoSizeAxes = Axes.X; + Hide(); + Children = new Drawable[] { - new Box { RelativeSizeAxes = Axes.Both }, - new CircularContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.8f), - Masking = true, - Children = new Drawable[] - { - background = new Box { RelativeSizeAxes = Axes.Both }, - new Triangles - { - TriangleScale = 0.2f, - ColourLight = OsuColour.FromHex(@"ff7db7"), - ColourDark = OsuColour.FromHex(@"de5b95"), - RelativeSizeAxes = Axes.Both, - Velocity = 0.3f, - }, - } - }, - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.fa_heart, - Scale = new Vector2(0.45f), - } + background = new Box { RelativeSizeAxes = Axes.Both }, + iconContainer = new FillFlowContainer + { + Direction = FillDirection.Horizontal, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Height = 0.6f, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } }; } + public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) + { + bool invalid = base.Invalidate(invalidation, source, shallPropagate); + + if ((invalidation & Invalidation.DrawSize) != 0) + { + iconContainer.Padding = new MarginPadding { Horizontal = DrawHeight / 2 }; + } + + return invalid; + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { background.Colour = colours.Pink; + iconContainer.Colour = colours.CommunityUserGrayGreenDark; } } } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index a8075ec295..78f35b3da8 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -2,52 +2,91 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using osuTK; -using osuTK.Graphics; +using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Extensions; +using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osu.Game.Overlays.Profile.Components; +using osu.Game.Online.Chat; using osu.Game.Overlays.Profile.Header; +using osu.Game.Scoring; using osu.Game.Users; +using osuTK; namespace osu.Game.Overlays.Profile { public class ProfileHeader : Container { - private readonly LinkFlowContainer infoTextLeft; - private readonly LinkFlowContainer infoTextRight; - private readonly FillFlowContainer scoreText, scoreNumberText; private readonly RankGraph rankGraph; public readonly SupporterIcon SupporterTag; private readonly Container coverContainer; - private readonly Sprite levelBadge; - private readonly SpriteText levelText; - private readonly GradeBadge gradeSSPlus, gradeSS, gradeSPlus, gradeS, gradeA; - private readonly Box colourBar; - private readonly DrawableFlag countryFlag; - private readonly BadgeContainer badgeContainer; + private readonly OsuSpriteText coverInfoText; + private readonly CoverInfoTabControl infoTabControl; - private const float cover_height = 350; - private const float info_height = 150; - private const float info_width = 220; + private readonly Box headerTopBox; + private readonly UpdateableAvatar avatar; + private readonly OsuSpriteText usernameText; + private readonly OsuSpriteText titleText; + private readonly DrawableFlag userFlag; + private readonly OsuSpriteText userCountryText; + private readonly Box userIconSeperatorBox; + private readonly FillFlowContainer userStats; + + private readonly Box headerCenterBox; + private readonly OsuSpriteText followerText; + private readonly ProfileHeaderButton messageButton; + private readonly ProfileHeaderButton expandButton; + private readonly Sprite levelBadgeSprite; + private readonly OsuSpriteText levelBadgeText; + + private readonly Bar levelProgressBar; + private readonly OsuSpriteText levelProgressText; + + private readonly OverlinedInfoContainer hiddenDetailGlobal, hiddenDetailCountry; + + public readonly BindableBool DetailsVisible = new BindableBool(); + + private readonly Box headerDetailBox; + private readonly HasTooltipContainer totalPlayTimeTooltip; + private readonly OverlinedInfoContainer totalPlayTimeInfo, medalInfo, ppInfo; + private readonly Dictionary scoreRankInfos = new Dictionary(); + private readonly OverlinedInfoContainer detailGlobalRank, detailCountryRank; + + private const float cover_height = 150; + private const float cover_info_height = 75; + private const float info_height = 500; private const float avatar_size = 110; - private const float level_position = 30; - private const float level_height = 60; - private const float stats_width = 280; - public ProfileHeader(User user) + [Resolved(CanBeNull = true)] + private ChannelManager channelManager { get; set; } + + [Resolved(CanBeNull = true)] + private UserProfileOverlay userOverlay { get; set; } + + [Resolved(CanBeNull = true)] + private ChatOverlay chatOverlay { get; set; } + + public ProfileHeader() { + Container headerDetailContainer, expandedDetailContainer; + FillFlowContainer hiddenDetailContainer; + SpriteIcon expandButtonIcon; + RelativeSizeAxes = Axes.X; Height = cover_height + info_height; @@ -65,262 +104,491 @@ namespace osu.Game.Overlays.Profile RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.1f), Color4.Black.Opacity(0.75f)) }, - new Container - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN, Bottom = 20, Right = stats_width + UserProfileOverlay.CONTENT_X_MARGIN }, - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Children = new Drawable[] - { - new UpdateableAvatar - { - User = user, - Size = new Vector2(avatar_size), - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Masking = true, - CornerRadius = 5, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(0.25f), - Radius = 4, - }, - }, - new Container - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - X = avatar_size + 10, - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - SupporterTag = new SupporterIcon - { - Alpha = 0, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Y = -75, - Size = new Vector2(25, 25) - }, - new FillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Y = -48, - Children = new Drawable[] - { - new OsuSpriteText - { - Text = user.Username, - Font = @"Exo2.0-RegularItalic", - TextSize = 30, - }, - new ExternalLinkButton($@"https://osu.ppy.sh/users/{user.Id}") - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Margin = new MarginPadding { Left = 3, Bottom = 3 }, //To better lineup with the font - }, - } - }, - countryFlag = new DrawableFlag(user.Country) - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Width = 30, - Height = 20 - } - } - }, - badgeContainer = new BadgeContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Origin = Anchor.BottomLeft, - Margin = new MarginPadding { Bottom = 5 }, - Alpha = 0, - }, - } - }, - colourBar = new Box - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - X = UserProfileOverlay.CONTENT_X_MARGIN, - Height = 5, - Width = info_width, - Alpha = 0 - } } }, - new Box // this is a temporary workaround for incorrect masking behaviour of FillMode.Fill used in UserCoverBackground (see https://github.com/ppy/osu-framework/issues/1675) - { - RelativeSizeAxes = Axes.X, - Height = 1, - Y = cover_height, - Colour = OsuColour.Gray(34), - }, - infoTextLeft = new LinkFlowContainer(t => t.TextSize = 14) - { - X = UserProfileOverlay.CONTENT_X_MARGIN, - Y = cover_height + 20, - Width = info_width, - AutoSizeAxes = Axes.Y, - ParagraphSpacing = 0.8f, - LineSpacing = 0.2f - }, - infoTextRight = new LinkFlowContainer(t => - { - t.TextSize = 14; - t.Font = @"Exo2.0-RegularItalic"; - }) - { - X = UserProfileOverlay.CONTENT_X_MARGIN + info_width + 20, - Y = cover_height + 20, - Width = info_width, - AutoSizeAxes = Axes.Y, - ParagraphSpacing = 0.8f, - LineSpacing = 0.2f - }, new Container { - X = -UserProfileOverlay.CONTENT_X_MARGIN, - RelativeSizeAxes = Axes.Y, - Width = stats_width, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, + Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, + Y = cover_height, + Height = cover_info_height, + RelativeSizeAxes = Axes.X, + Anchor = Anchor.TopLeft, + Origin = Anchor.BottomLeft, + Depth = -float.MaxValue, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new[] + { + new OsuSpriteText + { + Text = "Player ", + Font = "Exo2.0-Regular", + TextSize = 30 + }, + coverInfoText = new OsuSpriteText + { + Text = "Info", + Font = "Exo2.0-Regular", + TextSize = 30 + } + } + }, + infoTabControl = new CoverInfoTabControl + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = cover_info_height - 30, + Margin = new MarginPadding { Left = -UserProfileOverlay.CONTENT_X_MARGIN }, + Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN } + } + } + }, + new FillFlowContainer + { + Margin = new MarginPadding { Top = cover_height }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, Children = new Drawable[] { new Container { RelativeSizeAxes = Axes.X, - Y = level_position, - Height = level_height, + Height = 150, Children = new Drawable[] { - new Box + headerTopBox = new Box { - Colour = Color4.Black.Opacity(0.5f), - RelativeSizeAxes = Axes.Both + RelativeSizeAxes = Axes.Both, }, - levelBadge = new Sprite + new FillFlowContainer { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Height = 50, - Width = 50, - Alpha = 0 + Direction = FillDirection.Horizontal, + Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, + Height = avatar_size, + AutoSizeAxes = Axes.X, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Children = new[] + { + avatar = new UpdateableAvatar + { + Size = new Vector2(avatar_size), + Masking = true, + CornerRadius = avatar_size * 0.25f, + }, + new Container + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Padding = new MarginPadding { Left = 10 }, + Children = new Drawable[] + { + usernameText = new OsuSpriteText + { + Font = "Exo2.0-Regular", + TextSize = 24 + }, + new FillFlowContainer + { + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + titleText = new OsuSpriteText + { + TextSize = 18, + Font = "Exo2.0-Regular" + }, + SupporterTag = new SupporterIcon + { + Height = 20, + Margin = new MarginPadding { Top = 5 } + }, + userIconSeperatorBox = new Box + { + RelativeSizeAxes = Axes.X, + Height = 1.5f, + Margin = new MarginPadding { Top = 10 } + }, + new Container + { + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Top = 5 }, + Children = new Drawable[] + { + userFlag = new DrawableFlag + { + Size = new Vector2(30, 20) + }, + userCountryText = new OsuSpriteText + { + Font = "Exo2.0-Regular", + TextSize = 17.5f, + Margin = new MarginPadding { Left = 40 }, + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + } + } + }, + } + } + } + } + } }, - levelText = new OsuSpriteText + userStats = new FillFlowContainer { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Y = 11, - TextSize = 20 + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Y, + Width = 300, + Margin = new MarginPadding { Right = UserProfileOverlay.CONTENT_X_MARGIN }, + Padding = new MarginPadding { Vertical = 15 }, + Spacing = new Vector2(0, 2) } } }, new Container { RelativeSizeAxes = Axes.X, - Y = cover_height, - Anchor = Anchor.TopCentre, - Origin = Anchor.BottomCentre, - Height = cover_height - level_height - level_position - 5, + Height = 60, Children = new Drawable[] { - new Box + headerCenterBox = new Box { - Colour = Color4.Black.Opacity(0.5f), - RelativeSizeAxes = Axes.Both + RelativeSizeAxes = Axes.Both, }, - scoreText = new FillFlowContainer + new FillFlowContainer { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Padding = new MarginPadding { Horizontal = 20, Vertical = 18 }, - Spacing = new Vector2(0, 2) - }, - scoreNumberText = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Padding = new MarginPadding { Horizontal = 20, Vertical = 18 }, - Spacing = new Vector2(0, 2) - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, Direction = FillDirection.Horizontal, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Y = -64, - Spacing = new Vector2(20, 0), - Children = new[] + Padding = new MarginPadding { Vertical = 10 }, + Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, + Spacing = new Vector2(10, 0), + Children = new Drawable[] { - gradeSSPlus = new GradeBadge("SSPlus") { Alpha = 0 }, - gradeSS = new GradeBadge("SS") { Alpha = 0 }, + new ProfileHeaderButton + { + RelativeSizeAxes = Axes.Y, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Horizontal, + Padding = new MarginPadding { Right = 10 }, + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.fa_user, + FillMode = FillMode.Fit, + Size = new Vector2(50, 14) + }, + followerText = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + TextSize = 16, + Font = "Exo2.0-Bold" + } + } + } + } + }, + messageButton = new ProfileHeaderButton + { + RelativeSizeAxes = Axes.Y, + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.fa_envelope, + FillMode = FillMode.Fit, + Size = new Vector2(50, 14) + }, + } + }, + } }, - new FillFlowContainer + new Container { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Y = -18, - Spacing = new Vector2(20, 0), - Children = new[] + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.Y, + Padding = new MarginPadding { Vertical = 10 }, + Width = UserProfileOverlay.CONTENT_X_MARGIN, + Child = expandButton = new ProfileHeaderButton { - gradeSPlus = new GradeBadge("SPlus") { Alpha = 0 }, - gradeS = new GradeBadge("S") { Alpha = 0 }, - gradeA = new GradeBadge("A") { Alpha = 0 }, + RelativeSizeAxes = Axes.Y, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + expandButtonIcon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(20), + Icon = FontAwesome.fa_chevron_up, + }, + } + }, + }, + new Container + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Right = UserProfileOverlay.CONTENT_X_MARGIN }, + Children = new Drawable[] + { + new HasTooltipContainer + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Size = new Vector2(40), + TooltipText = "Level", + Children = new Drawable[] + { + levelBadgeSprite = new Sprite + { + RelativeSizeAxes = Axes.Both, + }, + levelBadgeText = new OsuSpriteText + { + TextSize = 20, + Font = "Exo2.0-Medium", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + } + }, + expandedDetailContainer = new HasTooltipContainer + { + TooltipText = "Progress to next level", + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Width = 200, + Height = 6, + Margin = new MarginPadding { Right = 50 }, + Children = new Drawable[] + { + new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = levelProgressBar = new Bar + { + RelativeSizeAxes = Axes.Both, + BackgroundColour = Color4.Black, + Direction = BarDirection.LeftToRight, + } + }, + levelProgressText = new OsuSpriteText + { + Anchor = Anchor.BottomRight, + Origin = Anchor.TopRight, + Font = "Exo2.0-Bold", + TextSize = 12, + } + } + }, + hiddenDetailContainer = new FillFlowContainer + { + Direction = FillDirection.Horizontal, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Width = 200, + AutoSizeAxes = Axes.Y, + Alpha = 0, + Spacing = new Vector2(10, 0), + Margin = new MarginPadding { Right = 50 }, + Children = new[] + { + hiddenDetailGlobal = new OverlinedInfoContainer + { + Title = "Global Ranking" + }, + hiddenDetailCountry = new OverlinedInfoContainer + { + Title = "Country Ranking" + }, + } + } } } } }, - new Container + headerDetailContainer = new Container { RelativeSizeAxes = Axes.X, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Height = info_height - 15, + AutoSizeAxes = Axes.Y, Children = new Drawable[] { - new Box + headerDetailBox = new Box { - Colour = Color4.Black.Opacity(0.25f), - RelativeSizeAxes = Axes.Both + RelativeSizeAxes = Axes.Both, }, - rankGraph = new RankGraph + new FillFlowContainer { - RelativeSizeAxes = Axes.Both - } + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + totalPlayTimeTooltip = new HasTooltipContainer + { + AutoSizeAxes = Axes.Both, + TooltipText = "0 hours", + Child = totalPlayTimeInfo = new OverlinedInfoContainer + { + Title = "Total Play Time", + }, + }, + medalInfo = new OverlinedInfoContainer + { + Title = "Medals" + }, + ppInfo = new OverlinedInfoContainer + { + Title = "pp" + }, + } + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Direction = FillDirection.Horizontal, + Children = new[] + { + scoreRankInfos[ScoreRank.XH] = new ScoreRankInfo(ScoreRank.XH), + scoreRankInfos[ScoreRank.X] = new ScoreRankInfo(ScoreRank.X), + scoreRankInfos[ScoreRank.SH] = new ScoreRankInfo(ScoreRank.SH), + scoreRankInfos[ScoreRank.S] = new ScoreRankInfo(ScoreRank.S), + scoreRankInfos[ScoreRank.A] = new ScoreRankInfo(ScoreRank.A), + } + } + } + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Right = 130 }, + Children = new Drawable[] + { + rankGraph = new RankGraph + { + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + Width = 130, + Anchor = Anchor.TopRight, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Horizontal = 10 }, + Spacing = new Vector2(0, 20), + Children = new Drawable[] + { + detailGlobalRank = new OverlinedInfoContainer(true, 110) + { + Title = "Global Ranking" + }, + detailCountryRank = new OverlinedInfoContainer(false, 110) + { + Title = "Country Ranking" + }, + } + } + } + } + } + }, } } } } }; + + infoTabControl.AddItem("Info"); + infoTabControl.AddItem("Modding"); + + DetailsVisible.ValueChanged += newValue => expandButtonIcon.Icon = newValue ? FontAwesome.fa_chevron_down : FontAwesome.fa_chevron_up; + DetailsVisible.ValueChanged += newValue => hiddenDetailContainer.Alpha = newValue ? 1 : 0; + DetailsVisible.ValueChanged += newValue => expandedDetailContainer.Alpha = newValue ? 0 : 1; + DetailsVisible.ValueChanged += newValue => headerDetailContainer.Alpha = newValue ? 0 : 1; } - [BackgroundDependencyLoader] - private void load(TextureStore textures) + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours, TextureStore textures) { - levelBadge.Texture = textures.Get(@"Profile/levelbadge"); + coverInfoText.Colour = colours.CommunityUserGreen; + + infoTabControl.AccentColour = colours.CommunityUserGreen; + + headerTopBox.Colour = colours.CommunityUserGrayGreenDarker; + userCountryText.Colour = colours.CommunityUserGrayGreenLighter; + userIconSeperatorBox.Colour = colours.CommunityUserGrayGreenLighter; + + headerCenterBox.Colour = colours.CommunityUserGrayGreenDark; + levelBadgeSprite.Texture = textures.Get("Profile/levelbadge"); + levelBadgeSprite.Colour = colours.Yellow; + levelProgressBar.AccentColour = colours.Yellow; + + hiddenDetailGlobal.LineColour = colours.Yellow; + hiddenDetailCountry.LineColour = colours.Yellow; + + headerDetailBox.Colour = colours.CommunityUserGrayGreenDarkest; + totalPlayTimeInfo.LineColour = colours.Yellow; + medalInfo.LineColour = colours.GreenLight; + ppInfo.LineColour = colours.Red; + + detailGlobalRank.LineColour = colours.Yellow; + detailCountryRank.LineColour = colours.Yellow; } private User user; public User User { - get { return user; } + get => user; set { user = value; @@ -340,9 +608,79 @@ namespace osu.Game.Overlays.Profile Depth = float.MaxValue, }, coverContainer.Add); - if (user.IsSupporter) - SupporterTag.Show(); + avatar.User = User; + usernameText.Text = user.Username; + userFlag.Country = user.Country; + userCountryText.Text = user.Country?.FullName; + SupporterTag.SupporterLevel = user.SupportLevel; + if(user.Title != null) + titleText.Text = user.Title; + titleText.Colour = OsuColour.FromHex(user.Colour ?? "fff"); + userStats.Add(new UserStatsLine("Ranked Score", user.Statistics.RankedScore.ToString("#,##0"))); + userStats.Add(new UserStatsLine("Hit Accuracy", Math.Round(user.Statistics.Accuracy, 2).ToString("#0.00'%'"))); + userStats.Add(new UserStatsLine("Play Count", user.Statistics.PlayCount.ToString("#,##0"))); + userStats.Add(new UserStatsLine("Total Score", user.Statistics.TotalScore.ToString("#,##0"))); + userStats.Add(new UserStatsLine("Total Hits", user.Statistics.TotalHits.ToString("#,##0"))); + userStats.Add(new UserStatsLine("Maximum Combo", user.Statistics.MaxCombo.ToString("#,##0"))); + userStats.Add(new UserStatsLine("Replays Watched by Others", user.Statistics.ReplaysWatched.ToString("#,##0"))); + + followerText.Text = user.FollowerCount?.Length > 0 ? user.FollowerCount[0].ToString("#,##0") : "0"; + + if (!user.PMFriendsOnly) + messageButton.Action = () => + { + channelManager?.OpenPrivateChannel(user); + userOverlay?.Hide(); + chatOverlay?.Show(); + }; + + expandButton.Action = DetailsVisible.Toggle; + + levelBadgeText.Text = user.Statistics.Level.Current.ToString(); + levelProgressBar.Length = user.Statistics.Level.Progress / 100f; + levelProgressText.Text = user.Statistics.Level.Progress.ToString("0'%'"); + + hiddenDetailGlobal.Content = user.Statistics.Ranks.Global?.ToString("#,##0") ?? "-"; + hiddenDetailCountry.Content = user.Statistics.Ranks.Country?.ToString("#,##0") ?? "-"; + + medalInfo.Content = user.Achievements.Length.ToString(); + ppInfo.Content = user.Statistics.PP?.ToString("#,##0") ?? "0"; + + string formatTime(int? secondsNull) + { + if (secondsNull == null) return "0h 0m"; + + int seconds = secondsNull.Value; + string time = ""; + + int days = seconds / 86400; + seconds -= days * 86400; + if (days > 0) + time += days + "d "; + + int hours = seconds / 3600; + seconds -= hours * 3600; + time += hours + "h "; + + int minutes = seconds / 60; + time += minutes + "m"; + + return time; + } + + totalPlayTimeInfo.Content = formatTime(user.Statistics.PlayTime); + totalPlayTimeTooltip.TooltipText = (user.Statistics.PlayTime ?? 0) / 3600 + " hours"; + + foreach (var scoreRankInfo in scoreRankInfos) + scoreRankInfo.Value.RankCount = user.Statistics.GradesCount.GetForScoreRank(scoreRankInfo.Key); + + detailGlobalRank.Content = user.Statistics.Ranks.Global?.ToString("#,##0") ?? "-"; + detailCountryRank.Content = user.Statistics.Ranks.Country?.ToString("#,##0") ?? "-"; + + rankGraph.User.Value = user; + + /* if (!string.IsNullOrEmpty(user.Colour)) { colourBar.Colour = OsuColour.FromHex(user.Colour); @@ -457,24 +795,315 @@ namespace osu.Game.Overlays.Profile rankGraph.User.Value = user; } - badgeContainer.ShowBadges(user.Badges); + badgeContainer.ShowBadges(user.Badges);*/ } - private void tryAddInfoRightLine(FontAwesome icon, string str, string url = null) + private class CoverInfoTabControl : TabControl { - if (string.IsNullOrEmpty(str)) return; + private readonly Box bar; - infoTextRight.AddIcon(icon); - if (url != null) + private Color4 accentColour; + public Color4 AccentColour { - infoTextRight.AddLink(" " + str, url); - } - else - { - infoTextRight.AddText(" " + str); + get => accentColour; + set + { + if (accentColour == value) return; + + accentColour = value; + + bar.Colour = value; + + foreach (TabItem tabItem in TabContainer) + { + ((CoverInfoTabItem)tabItem).AccentColour = value; + } + } } - infoTextRight.NewLine(); + public MarginPadding Padding + { + set => TabContainer.Padding = value; + get => TabContainer.Padding; + } + + public CoverInfoTabControl() + { + TabContainer.Masking = false; + TabContainer.Spacing = new Vector2(20, 0); + + AddInternal(bar = new Box + { + RelativeSizeAxes = Axes.X, + Height = 2, + Anchor = Anchor.BottomLeft, + Origin = Anchor.CentreLeft + }); + } + + protected override Dropdown CreateDropdown() => null; + + protected override TabItem CreateTabItem(string value) => new CoverInfoTabItem(value) + { + AccentColour = AccentColour + }; + + private class CoverInfoTabItem : TabItem + { + private readonly OsuSpriteText text; + private readonly Drawable bar; + + private Color4 accentColour; + public Color4 AccentColour + { + get => accentColour; + set + { + accentColour = value; + + bar.Colour = value; + if (!Active) text.Colour = value; + } + } + + public CoverInfoTabItem(string value) + : base(value) + { + AutoSizeAxes = Axes.X; + RelativeSizeAxes = Axes.Y; + + Children = new[] + { + text = new OsuSpriteText + { + Margin = new MarginPadding { Bottom = 15 }, + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + Text = value, + TextSize = 14, + Font = "Exo2.0-Bold", + }, + bar = new Circle + { + RelativeSizeAxes = Axes.X, + Height = 0, + Origin = Anchor.CentreLeft, + Anchor = Anchor.BottomLeft, + }, + new HoverClickSounds() + }; + } + + protected override bool OnHover(HoverEvent e) + { + if (!Active) + onActivated(true); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + if (!Active) + OnDeactivated(); + } + + protected override void OnActivated() + { + onActivated(); + } + + protected override void OnDeactivated() + { + text.FadeColour(AccentColour, 120, Easing.InQuad); + bar.ResizeHeightTo(0, 120, Easing.InQuad); + text.Font = "Exo2.0-Medium"; + } + + private void onActivated(bool fake = false) + { + text.FadeColour(Color4.White, 120, Easing.InQuad); + bar.ResizeHeightTo(7.5f, 120, Easing.InQuad); + if (!fake) + text.Font = "Exo2.0-Bold"; + } + } + } + + private class UserStatsLine : Container + { + private readonly OsuSpriteText rightText; + + public UserStatsLine(string left, string right) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Children = new Drawable[] + { + new OsuSpriteText + { + TextSize = 15, + Text = left, + Font = "Exo2.0-Medium" + }, + rightText = new OsuSpriteText + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + TextSize = 15, + Text = right, + Font = "Exo2.0-Medium" + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + rightText.Colour = colours.BlueLight; + } + } + + private class ProfileHeaderButton : OsuHoverContainer + { + private readonly Box background; + private readonly Container content; + + protected override Container Content => content; + + protected override IEnumerable EffectTargets => new[] { background }; + + public ProfileHeaderButton() + { + HoverColour = Color4.Black.Opacity(0.75f); + IdleColour = Color4.Black.Opacity(0.7f); + AutoSizeAxes = Axes.X; + + base.Content.Add(new CircularContainer + { + Masking = true, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + content = new Container + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = 10 }, + } + } + }); + } + } + + private class HasTooltipContainer : Container, IHasTooltip + { + public string TooltipText { get; set; } + } + + private class OverlinedInfoContainer : CompositeDrawable + { + private readonly Circle line; + private readonly OsuSpriteText title, content; + + public string Title + { + set => title.Text = value; + } + + public string Content + { + set => content.Text = value; + } + + public Color4 LineColour + { + set => line.Colour = value; + } + + public OverlinedInfoContainer(bool big = false, int minimumWidth = 60) + { + AutoSizeAxes = Axes.Both; + InternalChild = new FillFlowContainer + { + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + line = new Circle + { + RelativeSizeAxes = Axes.X, + Height = 4, + }, + title = new OsuSpriteText + { + Font = "Exo2.0-Bold", + TextSize = big ? 14 : 12, + }, + content = new OsuSpriteText + { + Font = "Exo2.0-Light", + TextSize = big ? 40 : 18, + }, + new Container //Add a minimum size to the FillFlowContainer + { + Width = minimumWidth, + } + } + }; + } + } + + public class ScoreRankInfo : CompositeDrawable + { + private readonly ScoreRank rank; + private readonly Sprite rankSprite; + private readonly OsuSpriteText rankCount; + + public int RankCount + { + set => rankCount.Text = value.ToString("#,##0"); + } + + public ScoreRankInfo(ScoreRank rank) + { + this.rank = rank; + + AutoSizeAxes = Axes.Both; + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + Width = 56, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + rankSprite = new Sprite + { + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit + }, + rankCount = new OsuSpriteText + { + Font = "Exo2.0-Bold", + TextSize = 12, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + rankSprite.Texture = textures.Get($"Grades/{rank.GetDescription()}"); + } } } } diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index c15f464c7c..ca99f07d9b 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays private SectionsContainer sectionsContainer; private ProfileTabControl tabs; - public const float CONTENT_X_MARGIN = 50; + public const float CONTENT_X_MARGIN = 70; public UserProfileOverlay() { @@ -113,12 +113,10 @@ namespace osu.Game.Overlays Colour = OsuColour.Gray(0.2f) }); - Header = new ProfileHeader(user); - Add(sectionsContainer = new SectionsContainer { RelativeSizeAxes = Axes.Both, - ExpandableHeader = Header, + ExpandableHeader = Header = new ProfileHeader(), FixedHeader = tabs, HeaderBackground = new Box { diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index a5d8c03a67..485c953b75 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -59,6 +59,9 @@ namespace osu.Game.Users [JsonProperty(@"is_supporter")] public bool IsSupporter; + [JsonProperty(@"support_level")] + public int SupportLevel; + [JsonProperty(@"is_gmt")] public bool IsGMT; @@ -71,6 +74,9 @@ namespace osu.Game.Users [JsonProperty(@"is_active")] public bool Active; + [JsonProperty(@"pm_friends_only")] + public bool PMFriendsOnly; + [JsonProperty(@"interests")] public string Interests; @@ -104,6 +110,9 @@ namespace osu.Game.Users [JsonProperty(@"post_count")] public int PostCount; + [JsonProperty(@"follower_count")] + public int[] FollowerCount; + [JsonProperty(@"playstyle")] public string[] PlayStyle; @@ -143,6 +152,18 @@ namespace osu.Game.Users [JsonProperty("badges")] public Badge[] Badges; + [JsonProperty("user_achievements")] + public UserAchievement[] Achievements; + + public class UserAchievement + { + [JsonProperty("achieved_at")] + public DateTimeOffset AchievedAt; + + [JsonProperty("achievement_id")] + public int ID; + } + public override string ToString() => Username; /// public Container Overlays { get; private set; } + public override GameplayClock FrameStableClock => frameStabilityContainer.GameplayClock; + /// /// Invoked when a has been applied by a . /// @@ -334,6 +336,11 @@ namespace osu.Game.Rulesets.UI /// diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index d86f608bd1..3d0127bba4 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -185,8 +185,8 @@ namespace osu.Game.Users { infoContainer.Add(new SupporterIcon { - RelativeSizeAxes = Axes.Y, - Width = 20f, + Height = 20f, + SupporterLevel = user.SupportLevel }); } diff --git a/osu.Game/Users/UserStatistics.cs b/osu.Game/Users/UserStatistics.cs index f04bfb62bb..c400a3f15b 100644 --- a/osu.Game/Users/UserStatistics.cs +++ b/osu.Game/Users/UserStatistics.cs @@ -1,7 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using Newtonsoft.Json; +using osu.Game.Scoring; namespace osu.Game.Users { @@ -37,6 +39,9 @@ namespace osu.Game.Users [JsonProperty(@"play_count")] public int PlayCount; + [JsonProperty(@"play_time")] + public int? PlayTime; + [JsonProperty(@"total_score")] public long TotalScore; @@ -68,6 +73,19 @@ namespace osu.Game.Users [JsonProperty(@"a")] public int A; + + public int GetForScoreRank(ScoreRank rank) + { + switch (rank) + { + case ScoreRank.XH: return SSPlus; + case ScoreRank.X: return SS; + case ScoreRank.SH: return SPlus; + case ScoreRank.S: return S; + case ScoreRank.A: return A; + default: throw new ArgumentException($"API does not return {rank.ToString()}"); + } + } } public struct UserRanks diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index d6882282e6..170a7bd8c9 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -208,6 +208,7 @@ MD5 NS OS + PM RGB RNG SHA From 2fe80d556844d82c8029d8999a08c8b5166e5094 Mon Sep 17 00:00:00 2001 From: jorolf Date: Sat, 22 Dec 2018 21:50:25 +0100 Subject: [PATCH 0322/5608] Update ProfileHeader to the new design --- .../Visual/TestCaseBadgeContainer.cs | 62 --- osu.Game.Tests/Visual/TestCaseUserProfile.cs | 1 - .../Graphics/Containers/SectionsContainer.cs | 11 + osu.Game/Graphics/UserInterface/LineGraph.cs | 11 +- .../Profile/Components/DrawableJoinDate.cs | 20 - .../Overlays/Profile/Components/GradeBadge.cs | 50 --- .../Overlays/Profile/Header/BadgeContainer.cs | 198 --------- .../Profile/Header/ProfileHeaderTabControl.cs | 149 +++++++ osu.Game/Overlays/Profile/Header/RankGraph.cs | 194 +++++--- osu.Game/Overlays/Profile/ProfileHeader.cs | 419 ++++++++---------- 10 files changed, 480 insertions(+), 635 deletions(-) delete mode 100644 osu.Game.Tests/Visual/TestCaseBadgeContainer.cs delete mode 100644 osu.Game/Overlays/Profile/Components/DrawableJoinDate.cs delete mode 100644 osu.Game/Overlays/Profile/Components/GradeBadge.cs delete mode 100644 osu.Game/Overlays/Profile/Header/BadgeContainer.cs create mode 100644 osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs diff --git a/osu.Game.Tests/Visual/TestCaseBadgeContainer.cs b/osu.Game.Tests/Visual/TestCaseBadgeContainer.cs deleted file mode 100644 index 8177e2e272..0000000000 --- a/osu.Game.Tests/Visual/TestCaseBadgeContainer.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using osu.Framework.Graphics; -using osu.Game.Overlays.Profile.Header; -using osu.Game.Users; - -namespace osu.Game.Tests.Visual -{ - [TestFixture] - public class TestCaseBadgeContainer : OsuTestCase - { - public override IReadOnlyList RequiredTypes => new[] { typeof(BadgeContainer) }; - - public TestCaseBadgeContainer() - { - BadgeContainer badgeContainer; - - Child = badgeContainer = new BadgeContainer - { - RelativeSizeAxes = Axes.Both - }; - - AddStep("Show 1 badge", () => badgeContainer.ShowBadges(new[] - { - new Badge - { - AwardedAt = DateTimeOffset.Now, - Description = "Appreciates compasses", - ImageUrl = "https://assets.ppy.sh/profile-badges/mg2018-1star.png", - } - })); - - AddStep("Show 2 badges", () => badgeContainer.ShowBadges(new[] - { - new Badge - { - AwardedAt = DateTimeOffset.Now, - Description = "Contributed to osu!lazer testing", - ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.png", - }, - new Badge - { - AwardedAt = DateTimeOffset.Now, - Description = "Appreciates compasses", - ImageUrl = "https://assets.ppy.sh/profile-badges/mg2018-1star.png", - } - })); - - AddStep("Show many badges", () => badgeContainer.ShowBadges(Enumerable.Range(1, 20).Select(i => new Badge - { - AwardedAt = DateTimeOffset.Now, - Description = $"Contributed to osu!lazer testing {i} times", - ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg", - }).ToArray())); - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/TestCaseUserProfile.cs index ce41bc22ff..cff55c2506 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/TestCaseUserProfile.cs @@ -28,7 +28,6 @@ namespace osu.Game.Tests.Visual typeof(UserProfileOverlay), typeof(RankGraph), typeof(LineGraph), - typeof(BadgeContainer), typeof(SectionsContainer<>), typeof(SupporterIcon) }; diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 36fdbe6e94..f16b5773ea 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -141,6 +141,17 @@ namespace osu.Game.Graphics.Containers public void ScrollToTop() => scrollContainer.ScrollTo(0); + public override void InvalidateFromChild(Invalidation invalidation, Drawable source = null) + { + base.InvalidateFromChild(invalidation, source); + + if ((invalidation & Invalidation.DrawSize) != 0) + { + if (source == ExpandableHeader) //We need to recalculate the positions if the ExpandableHeader changed its size + lastKnownScroll = -1; + } + } + private float lastKnownScroll; protected override void UpdateAfterChildren() { diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs index c84c500201..c750f7a89d 100644 --- a/osu.Game/Graphics/UserInterface/LineGraph.cs +++ b/osu.Game/Graphics/UserInterface/LineGraph.cs @@ -9,6 +9,7 @@ using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Lines; +using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { @@ -63,13 +64,19 @@ namespace osu.Game.Graphics.UserInterface } } + public Color4 LineColour + { + get => maskingContainer.Colour; + set => maskingContainer.Colour = value; + } + public LineGraph() { Add(maskingContainer = new Container { Masking = true, RelativeSizeAxes = Axes.Both, - Child = path = new SmoothPath { RelativeSizeAxes = Axes.Both, PathWidth = 1 } + Child = path = new SmoothPath { RelativeSizeAxes = Axes.Both, PathWidth = 1.5f } }); } @@ -103,7 +110,7 @@ namespace osu.Game.Graphics.UserInterface for (int i = 0; i < values.Length; i++) { float x = (i + count - values.Length) / (float)(count - 1) * DrawWidth - 1; - float y = GetYPosition(values[i]) * DrawHeight - 1; + float y = GetYPosition(values[i]) * DrawHeight - path.PathWidth; // the -1 is for inner offset in path (actually -PathWidth) path.AddVertex(new Vector2(x, y)); } diff --git a/osu.Game/Overlays/Profile/Components/DrawableJoinDate.cs b/osu.Game/Overlays/Profile/Components/DrawableJoinDate.cs deleted file mode 100644 index 11ee329f33..0000000000 --- a/osu.Game/Overlays/Profile/Components/DrawableJoinDate.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using osu.Game.Graphics; - -namespace osu.Game.Overlays.Profile.Components -{ - public class DrawableJoinDate : DrawableDate - { - public DrawableJoinDate(DateTimeOffset date) - : base(date) - { - } - - protected override string Format() => Text = Date.ToUniversalTime().Year < 2008 ? "Here since the beginning" : $"{Date:MMMM yyyy}"; - - public override string TooltipText => $"{Date:MMMM d, yyyy}"; - } -} diff --git a/osu.Game/Overlays/Profile/Components/GradeBadge.cs b/osu.Game/Overlays/Profile/Components/GradeBadge.cs deleted file mode 100644 index 14a47e8d03..0000000000 --- a/osu.Game/Overlays/Profile/Components/GradeBadge.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; -using osu.Game.Graphics.Sprites; - -namespace osu.Game.Overlays.Profile.Components -{ - public class GradeBadge : Container - { - private const float width = 50; - private readonly string grade; - private readonly Sprite badge; - private readonly SpriteText numberText; - - public int DisplayCount - { - set => numberText.Text = value.ToString(@"#,0"); - } - - public GradeBadge(string grade) - { - this.grade = grade; - Width = width; - Height = 41; - Add(badge = new Sprite - { - Width = width, - Height = 26 - }); - Add(numberText = new OsuSpriteText - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - TextSize = 14, - Font = @"Exo2.0-Bold" - }); - } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - badge.Texture = textures.Get($"Grades/{grade}"); - } - } -} diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs deleted file mode 100644 index 06fef22309..0000000000 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; -using osu.Framework.Input.Events; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Users; -using osuTK; - -namespace osu.Game.Overlays.Profile.Header -{ - public class BadgeContainer : Container - { - private static readonly Vector2 badge_size = new Vector2(86, 40); - private static readonly MarginPadding outer_padding = new MarginPadding(3); - - private OsuSpriteText badgeCountText; - private FillFlowContainer badgeFlowContainer; - private FillFlowContainer outerBadgeContainer; - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Child = new Container - { - Masking = true, - CornerRadius = 4, - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Gray3 - }, - outerBadgeContainer = new OuterBadgeContainer(onOuterHover, onOuterHoverLost) - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Direction = FillDirection.Vertical, - Padding = outer_padding, - Width = DrawableBadge.DRAWABLE_BADGE_SIZE.X + outer_padding.TotalHorizontal, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - badgeCountText = new OsuSpriteText - { - Alpha = 0, - TextSize = 12, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Font = "Exo2.0-Regular" - }, - new Container - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - AutoSizeAxes = Axes.Both, - Child = badgeFlowContainer = new FillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - } - } - } - }, - } - }; - - Scheduler.AddDelayed(rotateBadges, 3000, true); - } - - private void rotateBadges() - { - if (outerBadgeContainer.IsHovered) return; - - visibleBadge = (visibleBadge + 1) % badgeCount; - - badgeFlowContainer.MoveToX(-DrawableBadge.DRAWABLE_BADGE_SIZE.X * visibleBadge, 500, Easing.InOutQuad); - } - - private int visibleBadge; - private int badgeCount; - - public void ShowBadges(Badge[] badges) - { - if (badges == null || badges.Length == 0) - { - Hide(); - return; - } - - badgeCount = badges.Length; - - badgeCountText.FadeTo(badgeCount > 1 ? 1 : 0); - badgeCountText.Text = $"{badges.Length} badges"; - - Show(); - visibleBadge = 0; - - badgeFlowContainer.Clear(); - for (var index = 0; index < badges.Length; index++) - { - int displayIndex = index; - LoadComponentAsync(new DrawableBadge(badges[index]) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - }, asyncBadge => - { - badgeFlowContainer.Add(asyncBadge); - - // load in stable order regardless of async load order. - badgeFlowContainer.SetLayoutPosition(asyncBadge, displayIndex); - }); - } - } - - private void onOuterHover() - { - badgeFlowContainer.ClearTransforms(); - badgeFlowContainer.X = 0; - badgeFlowContainer.Direction = FillDirection.Full; - outerBadgeContainer.AutoSizeAxes = Axes.Both; - - badgeFlowContainer.MaximumSize = new Vector2(ChildSize.X, float.MaxValue); - } - - private void onOuterHoverLost() - { - badgeFlowContainer.X = -DrawableBadge.DRAWABLE_BADGE_SIZE.X * visibleBadge; - badgeFlowContainer.Direction = FillDirection.Horizontal; - outerBadgeContainer.AutoSizeAxes = Axes.Y; - outerBadgeContainer.Width = DrawableBadge.DRAWABLE_BADGE_SIZE.X + outer_padding.TotalHorizontal; - } - - private class OuterBadgeContainer : FillFlowContainer - { - private readonly Action hoverAction; - private readonly Action hoverLostAction; - - public OuterBadgeContainer(Action hoverAction, Action hoverLostAction) - { - this.hoverAction = hoverAction; - this.hoverLostAction = hoverLostAction; - } - - protected override bool OnHover(HoverEvent e) - { - hoverAction(); - return true; - } - - protected override void OnHoverLost(HoverLostEvent e) => hoverLostAction(); - } - - private class DrawableBadge : Container, IHasTooltip - { - public static readonly Vector2 DRAWABLE_BADGE_SIZE = badge_size + outer_padding.Total; - - private readonly Badge badge; - - public DrawableBadge(Badge badge) - { - this.badge = badge; - Padding = outer_padding; - Size = DRAWABLE_BADGE_SIZE; - } - - [BackgroundDependencyLoader] - private void load(LargeTextureStore textures) - { - Child = new Sprite - { - FillMode = FillMode.Fit, - RelativeSizeAxes = Axes.Both, - Texture = textures.Get(badge.ImageUrl), - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - Child.FadeInFromZero(200); - } - - public string TooltipText => badge.Description; - } - } -} diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs new file mode 100644 index 0000000000..b067273b04 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs @@ -0,0 +1,149 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Profile +{ + public class ProfileHeaderTabControl : TabControl + { + private readonly Box bar; + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) return; + + accentColour = value; + + bar.Colour = value; + + foreach (TabItem tabItem in TabContainer) + { + ((ProfileHeaderTabItem)tabItem).AccentColour = value; + } + } + } + + public MarginPadding Padding + { + set => TabContainer.Padding = value; + get => TabContainer.Padding; + } + + public ProfileHeaderTabControl() + { + TabContainer.Masking = false; + TabContainer.Spacing = new Vector2(20, 0); + + AddInternal(bar = new Box + { + RelativeSizeAxes = Axes.X, + Height = 2, + Anchor = Anchor.BottomLeft, + Origin = Anchor.CentreLeft + }); + } + + protected override Dropdown CreateDropdown() => null; + + protected override TabItem CreateTabItem(string value) => new ProfileHeaderTabItem(value) + { + AccentColour = AccentColour + }; + + private class ProfileHeaderTabItem : TabItem + { + private readonly OsuSpriteText text; + private readonly Drawable bar; + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + accentColour = value; + + bar.Colour = value; + if (!Active) text.Colour = value; + } + } + + public ProfileHeaderTabItem(string value) + : base(value) + { + AutoSizeAxes = Axes.X; + RelativeSizeAxes = Axes.Y; + + Children = new[] + { + text = new OsuSpriteText + { + Margin = new MarginPadding { Bottom = 15 }, + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + Text = value, + TextSize = 14, + Font = "Exo2.0-Bold", + }, + bar = new Circle + { + RelativeSizeAxes = Axes.X, + Height = 0, + Origin = Anchor.CentreLeft, + Anchor = Anchor.BottomLeft, + }, + new HoverClickSounds() + }; + } + + protected override bool OnHover(HoverEvent e) + { + if (!Active) + onActivated(true); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + if (!Active) + OnDeactivated(); + } + + protected override void OnActivated() + { + onActivated(); + } + + protected override void OnDeactivated() + { + text.FadeColour(AccentColour, 120, Easing.InQuad); + bar.ResizeHeightTo(0, 120, Easing.InQuad); + text.Font = "Exo2.0-Medium"; + } + + private void onActivated(bool fake = false) + { + text.FadeColour(Color4.White, 120, Easing.InQuad); + bar.ResizeHeightTo(7.5f, 120, Easing.InQuad); + if (!fake) + text.Font = "Exo2.0-Bold"; + } + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/RankGraph.cs b/osu.Game/Overlays/Profile/Header/RankGraph.cs index f74c8b5069..f67a8e47d4 100644 --- a/osu.Game/Overlays/Profile/Header/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/RankGraph.cs @@ -8,8 +8,8 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -19,19 +19,18 @@ using osuTK; namespace osu.Game.Overlays.Profile.Header { - public class RankGraph : Container + public class RankGraph : Container, IHasCustomTooltip { - private const float primary_textsize = 25; private const float secondary_textsize = 13; private const float padding = 10; private const float fade_duration = 150; private const int ranked_days = 88; - private readonly SpriteText rankText, performanceText, relativeText; private readonly RankChartLineGraph graph; private readonly OsuSpriteText placeholder; private KeyValuePair[] ranks; + private int dayIndex; public Bindable User = new Bindable(); public RankGraph() @@ -44,43 +43,20 @@ namespace osu.Game.Overlays.Profile.Header Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = "No recent plays", - TextSize = 14, - Font = @"Exo2.0-RegularItalic", - }, - rankText = new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Font = @"Exo2.0-RegularItalic", - TextSize = primary_textsize - }, - relativeText = new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Font = @"Exo2.0-RegularItalic", - Y = 25, - TextSize = secondary_textsize - }, - performanceText = new OsuSpriteText - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Font = @"Exo2.0-RegularItalic", - TextSize = secondary_textsize + TextSize = 12, + Font = @"Exo2.0-Regular", }, graph = new RankChartLineGraph { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.X, - Height = 60, + RelativeSizeAxes = Axes.Both, Y = -secondary_textsize, Alpha = 0, } }; - graph.OnBallMove += showHistoryRankTexts; + graph.OnBallMove += i => dayIndex = i; User.ValueChanged += userChanged; } @@ -88,7 +64,7 @@ namespace osu.Game.Overlays.Profile.Header [BackgroundDependencyLoader] private void load(OsuColour colours) { - graph.Colour = colours.Yellow; + graph.LineColour = colours.Yellow; } private void userChanged(User user) @@ -97,9 +73,6 @@ namespace osu.Game.Overlays.Profile.Header if (user?.Statistics?.Ranks.Global == null) { - rankText.Text = string.Empty; - performanceText.Text = string.Empty; - relativeText.Text = string.Empty; graph.FadeOut(fade_duration, Easing.Out); ranks = null; return; @@ -114,27 +87,9 @@ namespace osu.Game.Overlays.Profile.Header graph.DefaultValueCount = ranks.Length; graph.Values = ranks.Select(x => -(float)Math.Log(x.Value)); - graph.SetStaticBallPosition(); } graph.FadeTo(ranks.Length > 1 ? 1 : 0, fade_duration, Easing.Out); - - updateRankTexts(); - } - - private void updateRankTexts() - { - var user = User.Value; - - performanceText.Text = user.Statistics.PP != null ? $"{user.Statistics.PP:#,0}pp" : string.Empty; - rankText.Text = user.Statistics.Ranks.Global > 0 ? $"#{user.Statistics.Ranks.Global:#,0}" : "no rank"; - relativeText.Text = user.Country != null && user.Statistics.Ranks.Country > 0 ? $"{user.Country.FullName} #{user.Statistics.Ranks.Country:#,0}" : "no rank"; - } - - private void showHistoryRankTexts(int dayIndex) - { - rankText.Text = $"#{ranks[dayIndex].Value:#,0}"; - relativeText.Text = dayIndex + 1 == ranks.Length ? "Now" : $"{ranked_days - ranks[dayIndex].Key} days ago"; } protected override bool OnHover(HoverEvent e) @@ -160,7 +115,6 @@ namespace osu.Game.Overlays.Profile.Header if (ranks?.Length > 1) { graph.HideBall(); - updateRankTexts(); } base.OnHoverLost(e); @@ -168,44 +122,62 @@ namespace osu.Game.Overlays.Profile.Header private class RankChartLineGraph : LineGraph { - private readonly CircularContainer staticBall; private readonly CircularContainer movingBall; + private readonly Box ballBg; + private readonly Box movingBar; public Action OnBallMove; public RankChartLineGraph() { - Add(staticBall = new CircularContainer + Add(movingBar = new Box { - Origin = Anchor.Centre, - Size = new Vector2(8), - Masking = true, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Y, + Width = 1.5f, + Alpha = 0, RelativePositionAxes = Axes.Both, - Child = new Box { RelativeSizeAxes = Axes.Both } }); + Add(movingBall = new CircularContainer { Origin = Anchor.Centre, - Size = new Vector2(8), + Size = new Vector2(18), Alpha = 0, Masking = true, + BorderThickness = 4, RelativePositionAxes = Axes.Both, - Child = new Box { RelativeSizeAxes = Axes.Both } + Child = ballBg = new Box { RelativeSizeAxes = Axes.Both } }); } - public void SetStaticBallPosition() => staticBall.Position = new Vector2(1, GetYPosition(Values.Last())); + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + ballBg.Colour = colours.CommunityUserGrayGreenDarkest; + movingBall.BorderColour = colours.Yellow; + movingBar.Colour = colours.Yellow; + } public void UpdateBallPosition(float mouseXPosition) { int index = calculateIndex(mouseXPosition); movingBall.Position = calculateBallPosition(index); + movingBar.X = movingBall.X; OnBallMove.Invoke(index); } - public void ShowBall() => movingBall.FadeIn(fade_duration); + public void ShowBall() + { + movingBall.FadeIn(fade_duration); + movingBar.FadeIn(fade_duration); + } - public void HideBall() => movingBall.FadeOut(fade_duration); + public void HideBall() + { + movingBall.FadeOut(fade_duration); + movingBar.FadeOut(fade_duration); + } private int calculateIndex(float mouseXPosition) => (int)Math.Round(mouseXPosition / DrawWidth * (DefaultValueCount - 1)); @@ -215,5 +187,97 @@ namespace osu.Game.Overlays.Profile.Header return new Vector2(index / (float)(DefaultValueCount - 1), y); } } + + public string TooltipText => User.Value?.Statistics?.Ranks.Global == null ? "" : $"{ranks[dayIndex].Value:#,##0}|{ranked_days - ranks[dayIndex].Key + 1}"; + + public ITooltip GetCustomTooltip() => new RankGraphTooltip(this); + + public class RankGraphTooltip : VisibilityContainer, ITooltip + { + private readonly RankGraph graph; + private readonly OsuSpriteText globalRankingText, timeText; + private readonly Box background; + + public string TooltipText { get; set; } + + public RankGraphTooltip(RankGraph graph) + { + this.graph = graph; + AutoSizeAxes = Axes.Both; + Masking = true; + CornerRadius = 10; + + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Padding = new MarginPadding(10), + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new OsuSpriteText + { + Font = "Exo2.0-Bold", + TextSize = 12, + Text = "Global Ranking " + }, + globalRankingText = new OsuSpriteText + { + Font = "Exo2.0-Regular", + TextSize = 12, + } + } + }, + timeText = new OsuSpriteText + { + TextSize = 12, + Font = "Exo2.0-Regular" + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.CommunityUserGrayGreenDarker; + } + + public void Refresh() + { + var info = TooltipText.Split('|'); + globalRankingText.Text = info[0]; + timeText.Text = info[1] == "0" ? "now" : $"{info[1]} days ago"; + } + + private bool instantMove = true; + + public void Move(Vector2 pos) + { + if (instantMove) + { + Position = pos; + instantMove = false; + } + else + this.MoveTo(pos, 200, Easing.OutQuint); + } + + protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); + + protected override void PopOut() => this.FadeOut(200, Easing.OutQuint); + } } } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index b35ae50c5e..6ab178cfe1 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -15,8 +15,6 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -36,7 +34,7 @@ namespace osu.Game.Overlays.Profile public readonly SupporterIcon SupporterTag; private readonly Container coverContainer; private readonly OsuSpriteText coverInfoText; - private readonly CoverInfoTabControl infoTabControl; + private readonly ProfileHeaderTabControl infoTabControl; private readonly Box headerTopBox; private readonly UpdateableAvatar avatar; @@ -67,9 +65,16 @@ namespace osu.Game.Overlays.Profile private readonly Dictionary scoreRankInfos = new Dictionary(); private readonly OverlinedInfoContainer detailGlobalRank, detailCountryRank; + private readonly Box headerBadgeBox; + private readonly FillFlowContainer badgeFlowContainer; + private readonly Container badgeContainer; + + private readonly Box headerBottomBox; + private readonly LinkFlowContainer bottomTopLinkContainer; + private readonly LinkFlowContainer bottomLinkContainer; + private const float cover_height = 150; private const float cover_info_height = 75; - private const float info_height = 500; private const float avatar_size = 110; [Resolved(CanBeNull = true)] @@ -83,12 +88,12 @@ namespace osu.Game.Overlays.Profile public ProfileHeader() { - Container headerDetailContainer, expandedDetailContainer; - FillFlowContainer hiddenDetailContainer; + Container expandedDetailContainer; + FillFlowContainer hiddenDetailContainer, headerDetailContainer; SpriteIcon expandButtonIcon; RelativeSizeAxes = Axes.X; - Height = cover_height + info_height; + AutoSizeAxes = Axes.Y; Children = new Drawable[] { @@ -137,7 +142,7 @@ namespace osu.Game.Overlays.Profile } } }, - infoTabControl = new CoverInfoTabControl + infoTabControl = new ProfileHeaderTabControl { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -181,7 +186,7 @@ namespace osu.Game.Overlays.Profile Size = new Vector2(avatar_size), Masking = true, CornerRadius = avatar_size * 0.25f, - OpenOnClick = { Value = false }, + OpenOnClick = { Value = false }, }, new Container { @@ -437,7 +442,7 @@ namespace osu.Game.Overlays.Profile } } }, - headerDetailContainer = new Container + new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -447,7 +452,7 @@ namespace osu.Game.Overlays.Profile { RelativeSizeAxes = Axes.Both, }, - new FillFlowContainer + headerDetailContainer = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -539,11 +544,82 @@ namespace osu.Game.Overlays.Profile } } } - } + }, } }, } - } + }, + badgeContainer = new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Alpha = 0, + Children = new Drawable[] + { + headerBadgeBox = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new Container //artificial shadow + { + RelativeSizeAxes = Axes.X, + Height = 3, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new ColourInfo + { + TopLeft = Color4.Black.Opacity(0.2f), + TopRight = Color4.Black.Opacity(0.2f), + BottomLeft = Color4.Black.Opacity(0), + BottomRight = Color4.Black.Opacity(0) + } + }, + }, + badgeFlowContainer = new FillFlowContainer + { + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Top = 5 }, + Spacing = new Vector2(10, 10), + Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, + } + } + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + headerBottomBox = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, + Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + bottomTopLinkContainer = new LinkFlowContainer(text => text.TextSize = 12) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + bottomLinkContainer = new LinkFlowContainer(text => text.TextSize = 12) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } + } + } + } + }, } } }; @@ -557,6 +633,8 @@ namespace osu.Game.Overlays.Profile DetailsVisible.ValueChanged += newValue => headerDetailContainer.Alpha = newValue ? 0 : 1; } + private Color4 communityUserGrayGreenLighter; + [BackgroundDependencyLoader(true)] private void load(OsuColour colours, TextureStore textures) { @@ -583,9 +661,12 @@ namespace osu.Game.Overlays.Profile detailGlobalRank.LineColour = colours.Yellow; detailCountryRank.LineColour = colours.Yellow; - } - private readonly OsuSpriteText usernameText; + headerBadgeBox.Colour = colours.CommunityUserGrayGreenDarkest; + headerBottomBox.Colour = colours.CommunityUserGrayGreenDarker; + + communityUserGrayGreenLighter = colours.CommunityUserGrayGreenLighter; + } private User user; @@ -683,67 +764,68 @@ namespace osu.Game.Overlays.Profile rankGraph.User.Value = user; - /* - if (!string.IsNullOrEmpty(user.Colour)) + var badges = User.Badges; + if (badges.Length > 0) { - colourBar.Colour = OsuColour.FromHex(user.Colour); - colourBar.Show(); + badgeContainer.Show(); + for (var index = 0; index < badges.Length; index++) + { + int displayIndex = index; + LoadComponentAsync(new DrawableBadge(badges[index]), asyncBadge => + { + badgeFlowContainer.Add(asyncBadge); + + // load in stable order regardless of async load order. + badgeFlowContainer.SetLayoutPosition(asyncBadge, displayIndex); + }); + } } - void boldItalic(SpriteText t) => t.Font = @"Exo2.0-BoldItalic"; - void lightText(SpriteText t) => t.Alpha = 0.8f; - - OsuSpriteText createScoreText(string text) => new OsuSpriteText - { - TextSize = 14, - Text = text - }; - - OsuSpriteText createScoreNumberText(string text) => new OsuSpriteText - { - TextSize = 14, - Font = @"Exo2.0-Bold", - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Text = text - }; - - if (user.Country != null) - { - infoTextLeft.AddText("From ", lightText); - infoTextLeft.AddText(user.Country.FullName, boldItalic); - countryFlag.Country = user.Country; - } - - infoTextLeft.NewParagraph(); + void bold(SpriteText t) => t.Font = @"Exo2.0-Bold"; + void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); if (user.JoinDate.ToUniversalTime().Year < 2008) { - infoTextLeft.AddText(new DrawableJoinDate(user.JoinDate), lightText); + bottomTopLinkContainer.AddText("Here since the beginning"); } else { - infoTextLeft.AddText("Joined ", lightText); - infoTextLeft.AddText(new DrawableJoinDate(user.JoinDate), boldItalic); + bottomTopLinkContainer.AddText("Joined "); + bottomTopLinkContainer.AddText(new DrawableDate(user.JoinDate), bold); } + addSpacer(bottomTopLinkContainer); + if (user.LastVisit.HasValue) { - infoTextLeft.NewLine(); - infoTextLeft.AddText("Last seen ", lightText); - infoTextLeft.AddText(new DrawableDate(user.LastVisit.Value), boldItalic); - infoTextLeft.NewParagraph(); + bottomTopLinkContainer.AddText("Last seen "); + bottomTopLinkContainer.AddText(new DrawableDate(user.LastVisit.Value), bold); } - if (user.PlayStyle?.Length > 0) + addSpacer(bottomTopLinkContainer); + + bottomTopLinkContainer.AddText("Contributed "); + bottomTopLinkContainer.AddLink($@"{user.PostCount} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: bold); + + void tryAddInfo(FontAwesome icon, string content, string link = null) { - infoTextLeft.AddText("Plays with ", lightText); - infoTextLeft.AddText(string.Join(", ", user.PlayStyle), boldItalic); - } + if (string.IsNullOrEmpty(content)) return; - infoTextLeft.NewLine(); - infoTextLeft.AddText("Contributed ", lightText); - infoTextLeft.AddLink($@"{user.PostCount} forum posts", url: $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: boldItalic); + bottomLinkContainer.AddIcon(icon, text => + { + text.TextSize = 10; + text.Colour = communityUserGrayGreenLighter; + }); + if (link != null) + { + bottomLinkContainer.AddLink(" " + content, link, creationParameters: bold); + } + else + { + bottomLinkContainer.AddText(" " + content, bold); + } + addSpacer(bottomLinkContainer); + } string websiteWithoutProtcol = user.Website; if (!string.IsNullOrEmpty(websiteWithoutProtcol)) @@ -753,185 +835,16 @@ namespace osu.Game.Overlays.Profile websiteWithoutProtcol = websiteWithoutProtcol.Substring(protocolIndex + 2); } - tryAddInfoRightLine(FontAwesome.fa_map_marker, user.Location); - tryAddInfoRightLine(FontAwesome.fa_heart_o, user.Interests); - tryAddInfoRightLine(FontAwesome.fa_suitcase, user.Occupation); - infoTextRight.NewParagraph(); + tryAddInfo(FontAwesome.fa_map_marker, user.Location); + tryAddInfo(FontAwesome.fa_heart_o, user.Interests); + tryAddInfo(FontAwesome.fa_suitcase, user.Occupation); + bottomLinkContainer.NewLine(); if (!string.IsNullOrEmpty(user.Twitter)) - tryAddInfoRightLine(FontAwesome.fa_twitter, "@" + user.Twitter, $@"https://twitter.com/{user.Twitter}"); - tryAddInfoRightLine(FontAwesome.fa_gamepad, user.Discord); - tryAddInfoRightLine(FontAwesome.fa_skype, user.Skype, @"skype:" + user.Skype + @"?chat"); - tryAddInfoRightLine(FontAwesome.fa_lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); - tryAddInfoRightLine(FontAwesome.fa_globe, websiteWithoutProtcol, user.Website); - - if (user.Statistics != null) - { - levelBadge.Show(); - levelText.Text = user.Statistics.Level.Current.ToString(); - - scoreText.Add(createScoreText("Ranked Score")); - scoreNumberText.Add(createScoreNumberText(user.Statistics.RankedScore.ToString(@"#,0"))); - scoreText.Add(createScoreText("Accuracy")); - scoreNumberText.Add(createScoreNumberText($"{user.Statistics.Accuracy:0.##}%")); - scoreText.Add(createScoreText("Play Count")); - scoreNumberText.Add(createScoreNumberText(user.Statistics.PlayCount.ToString(@"#,0"))); - scoreText.Add(createScoreText("Total Score")); - scoreNumberText.Add(createScoreNumberText(user.Statistics.TotalScore.ToString(@"#,0"))); - scoreText.Add(createScoreText("Total Hits")); - scoreNumberText.Add(createScoreNumberText(user.Statistics.TotalHits.ToString(@"#,0"))); - scoreText.Add(createScoreText("Max Combo")); - scoreNumberText.Add(createScoreNumberText(user.Statistics.MaxCombo.ToString(@"#,0"))); - scoreText.Add(createScoreText("Replays Watched by Others")); - scoreNumberText.Add(createScoreNumberText(user.Statistics.ReplaysWatched.ToString(@"#,0"))); - - gradeSSPlus.DisplayCount = user.Statistics.GradesCount.SSPlus; - gradeSSPlus.Show(); - gradeSS.DisplayCount = user.Statistics.GradesCount.SS; - gradeSS.Show(); - gradeSPlus.DisplayCount = user.Statistics.GradesCount.SPlus; - gradeSPlus.Show(); - gradeS.DisplayCount = user.Statistics.GradesCount.S; - gradeS.Show(); - gradeA.DisplayCount = user.Statistics.GradesCount.A; - gradeA.Show(); - - rankGraph.User.Value = user; - } - - badgeContainer.ShowBadges(user.Badges);*/ - } - - private class CoverInfoTabControl : TabControl - { - private readonly Box bar; - - private Color4 accentColour; - public Color4 AccentColour - { - get => accentColour; - set - { - if (accentColour == value) return; - - accentColour = value; - - bar.Colour = value; - - foreach (TabItem tabItem in TabContainer) - { - ((CoverInfoTabItem)tabItem).AccentColour = value; - } - } - } - - public MarginPadding Padding - { - set => TabContainer.Padding = value; - get => TabContainer.Padding; - } - - public CoverInfoTabControl() - { - TabContainer.Masking = false; - TabContainer.Spacing = new Vector2(20, 0); - - AddInternal(bar = new Box - { - RelativeSizeAxes = Axes.X, - Height = 2, - Anchor = Anchor.BottomLeft, - Origin = Anchor.CentreLeft - }); - } - - protected override Dropdown CreateDropdown() => null; - - protected override TabItem CreateTabItem(string value) => new CoverInfoTabItem(value) - { - AccentColour = AccentColour - }; - - private class CoverInfoTabItem : TabItem - { - private readonly OsuSpriteText text; - private readonly Drawable bar; - - private Color4 accentColour; - public Color4 AccentColour - { - get => accentColour; - set - { - accentColour = value; - - bar.Colour = value; - if (!Active) text.Colour = value; - } - } - - public CoverInfoTabItem(string value) - : base(value) - { - AutoSizeAxes = Axes.X; - RelativeSizeAxes = Axes.Y; - - Children = new[] - { - text = new OsuSpriteText - { - Margin = new MarginPadding { Bottom = 15 }, - Origin = Anchor.BottomLeft, - Anchor = Anchor.BottomLeft, - Text = value, - TextSize = 14, - Font = "Exo2.0-Bold", - }, - bar = new Circle - { - RelativeSizeAxes = Axes.X, - Height = 0, - Origin = Anchor.CentreLeft, - Anchor = Anchor.BottomLeft, - }, - new HoverClickSounds() - }; - } - - protected override bool OnHover(HoverEvent e) - { - if (!Active) - onActivated(true); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - - if (!Active) - OnDeactivated(); - } - - protected override void OnActivated() - { - onActivated(); - } - - protected override void OnDeactivated() - { - text.FadeColour(AccentColour, 120, Easing.InQuad); - bar.ResizeHeightTo(0, 120, Easing.InQuad); - text.Font = "Exo2.0-Medium"; - } - - private void onActivated(bool fake = false) - { - text.FadeColour(Color4.White, 120, Easing.InQuad); - bar.ResizeHeightTo(7.5f, 120, Easing.InQuad); - if (!fake) - text.Font = "Exo2.0-Bold"; - } - } + tryAddInfo(FontAwesome.fa_twitter, "@" + user.Twitter, $@"https://twitter.com/{user.Twitter}"); + tryAddInfo(FontAwesome.fa_gamepad, user.Discord); //todo: update fontawesome to include discord logo + tryAddInfo(FontAwesome.fa_skype, user.Skype, @"skype:" + user.Skype + @"?chat"); + tryAddInfo(FontAwesome.fa_lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); + tryAddInfo(FontAwesome.fa_link, websiteWithoutProtcol, user.Website); } private class UserStatsLine : Container @@ -1108,5 +1021,37 @@ namespace osu.Game.Overlays.Profile rankSprite.Texture = textures.Get($"Grades/{rank.GetDescription()}"); } } + + private class DrawableBadge : CompositeDrawable, IHasTooltip + { + public static readonly Vector2 DRAWABLE_BADGE_SIZE = new Vector2(86, 40); + + private readonly Badge badge; + + public DrawableBadge(Badge badge) + { + this.badge = badge; + Size = DRAWABLE_BADGE_SIZE; + } + + [BackgroundDependencyLoader] + private void load(LargeTextureStore textures) + { + InternalChild = new Sprite + { + FillMode = FillMode.Fit, + RelativeSizeAxes = Axes.Both, + Texture = textures.Get(badge.ImageUrl), + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + InternalChild.FadeInFromZero(200); + } + + public string TooltipText => badge.Description; + } } } From da99161736610b1dba44962f8e03bd87a7efd462 Mon Sep 17 00:00:00 2001 From: jorolf Date: Sat, 22 Dec 2018 22:31:11 +0100 Subject: [PATCH 0323/5608] add some missing stuff --- osu.Game/Graphics/UserInterface/LineGraph.cs | 1 - .../Overlays/Profile/Header/SupporterIcon.cs | 1 - osu.Game/Overlays/Profile/ProfileHeader.cs | 44 ++++++++++++++++--- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs index c750f7a89d..4948c0d7f4 100644 --- a/osu.Game/Graphics/UserInterface/LineGraph.cs +++ b/osu.Game/Graphics/UserInterface/LineGraph.cs @@ -111,7 +111,6 @@ namespace osu.Game.Graphics.UserInterface { float x = (i + count - values.Length) / (float)(count - 1) * DrawWidth - 1; float y = GetYPosition(values[i]) * DrawHeight - path.PathWidth; - // the -1 is for inner offset in path (actually -PathWidth) path.AddVertex(new Vector2(x, y)); } } diff --git a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs index 8b33a60d37..03135824de 100644 --- a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; -using osuTK; namespace osu.Game.Overlays.Profile.Header { diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 6ab178cfe1..1a51ab4cb6 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions; @@ -39,6 +40,7 @@ namespace osu.Game.Overlays.Profile private readonly Box headerTopBox; private readonly UpdateableAvatar avatar; private readonly OsuSpriteText usernameText; + private readonly ExternalLinkButton openUserExternally; private readonly OsuSpriteText titleText; private readonly DrawableFlag userFlag; private readonly OsuSpriteText userCountryText; @@ -76,6 +78,13 @@ namespace osu.Game.Overlays.Profile private const float cover_height = 150; private const float cover_info_height = 75; private const float avatar_size = 110; + private static readonly Dictionary play_styles = new Dictionary + { + {"keyboard", "Keyboard"}, + {"mouse", "Mouse"}, + {"tablet", "Tablet"}, + {"touch", "Touch Screen"}, + }; [Resolved(CanBeNull = true)] private ChannelManager channelManager { get; set; } @@ -195,10 +204,24 @@ namespace osu.Game.Overlays.Profile Padding = new MarginPadding { Left = 10 }, Children = new Drawable[] { - usernameText = new OsuSpriteText + new FillFlowContainer { - Font = "Exo2.0-Regular", - TextSize = 24 + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + usernameText = new OsuSpriteText + { + Font = "Exo2.0-Regular", + TextSize = 24 + }, + openUserExternally = new ExternalLinkButton + { + Margin = new MarginPadding { Left = 5 }, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + } }, new FillFlowContainer { @@ -694,6 +717,7 @@ namespace osu.Game.Overlays.Profile avatar.User = User; usernameText.Text = user.Username; + openUserExternally.Link = $@"https://osu.ppy.sh/users/{user.Id}"; userFlag.Country = user.Country; userCountryText.Text = user.Country?.FullName; SupporterTag.SupporterLevel = user.SupportLevel; @@ -796,16 +820,24 @@ namespace osu.Game.Overlays.Profile addSpacer(bottomTopLinkContainer); + if (user.PlayStyle?.Length > 0) + { + bottomTopLinkContainer.AddText("Plays with "); + bottomTopLinkContainer.AddText(string.Join(", ", user.PlayStyle.Select(style => play_styles[style])), bold); + + addSpacer(bottomTopLinkContainer); + } + if (user.LastVisit.HasValue) { bottomTopLinkContainer.AddText("Last seen "); bottomTopLinkContainer.AddText(new DrawableDate(user.LastVisit.Value), bold); + + addSpacer(bottomTopLinkContainer); } - addSpacer(bottomTopLinkContainer); - bottomTopLinkContainer.AddText("Contributed "); - bottomTopLinkContainer.AddLink($@"{user.PostCount} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: bold); + bottomTopLinkContainer.AddLink($@"{user.PostCount:#,##0} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: bold); void tryAddInfo(FontAwesome icon, string content, string link = null) { From 360c17e2c76b43525f67b159ff5c3652248543e6 Mon Sep 17 00:00:00 2001 From: jorolf Date: Sat, 22 Dec 2018 22:50:19 +0100 Subject: [PATCH 0324/5608] appease CodeFactor and AppVeyor --- osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs | 2 +- osu.Game/Overlays/Profile/Header/RankGraph.cs | 6 ++---- osu.Game/Overlays/Profile/ProfileHeader.cs | 1 - 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs index b067273b04..2576d627ea 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs +++ b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics.UserInterface; using osuTK; using osuTK.Graphics; -namespace osu.Game.Overlays.Profile +namespace osu.Game.Overlays.Profile.Header { public class ProfileHeaderTabControl : TabControl { diff --git a/osu.Game/Overlays/Profile/Header/RankGraph.cs b/osu.Game/Overlays/Profile/Header/RankGraph.cs index f67a8e47d4..76a72fe420 100644 --- a/osu.Game/Overlays/Profile/Header/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/RankGraph.cs @@ -190,19 +190,17 @@ namespace osu.Game.Overlays.Profile.Header public string TooltipText => User.Value?.Statistics?.Ranks.Global == null ? "" : $"{ranks[dayIndex].Value:#,##0}|{ranked_days - ranks[dayIndex].Key + 1}"; - public ITooltip GetCustomTooltip() => new RankGraphTooltip(this); + public ITooltip GetCustomTooltip() => new RankGraphTooltip(); public class RankGraphTooltip : VisibilityContainer, ITooltip { - private readonly RankGraph graph; private readonly OsuSpriteText globalRankingText, timeText; private readonly Box background; public string TooltipText { get; set; } - public RankGraphTooltip(RankGraph graph) + public RankGraphTooltip() { - this.graph = graph; AutoSizeAxes = Axes.Both; Masking = true; CornerRadius = 10; diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 1a51ab4cb6..77074abd09 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -353,7 +353,6 @@ namespace osu.Game.Overlays.Profile }, } }, - } }, new Container From e05fbd4136e338537e4ec6f9d64f958413b0f705 Mon Sep 17 00:00:00 2001 From: jorolf Date: Tue, 25 Dec 2018 01:09:49 +0100 Subject: [PATCH 0325/5608] address some comments and improve ui --- .../Overlays/Profile/Header/ProfileHeaderTabControl.cs | 2 +- osu.Game/Overlays/Profile/Header/RankGraph.cs | 2 ++ osu.Game/Overlays/Profile/ProfileHeader.cs | 10 +++++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs index 2576d627ea..db8a0b594c 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs +++ b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs @@ -38,8 +38,8 @@ namespace osu.Game.Overlays.Profile.Header public MarginPadding Padding { - set => TabContainer.Padding = value; get => TabContainer.Padding; + set => TabContainer.Padding = value; } public ProfileHeaderTabControl() diff --git a/osu.Game/Overlays/Profile/Header/RankGraph.cs b/osu.Game/Overlays/Profile/Header/RankGraph.cs index 76a72fe420..e681d2701a 100644 --- a/osu.Game/Overlays/Profile/Header/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/RankGraph.cs @@ -234,6 +234,8 @@ namespace osu.Game.Overlays.Profile.Header { Font = "Exo2.0-Regular", TextSize = 12, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, } } }, diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 77074abd09..7429a65210 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -20,6 +20,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; using osu.Game.Online.Chat; using osu.Game.Overlays.Profile.Header; using osu.Game.Scoring; @@ -95,6 +96,9 @@ namespace osu.Game.Overlays.Profile [Resolved(CanBeNull = true)] private ChatOverlay chatOverlay { get; set; } + [Resolved] + private APIAccess apiAccess { get; set; } + public ProfileHeader() { Container expandedDetailContainer; @@ -340,6 +344,7 @@ namespace osu.Game.Overlays.Profile }, messageButton = new ProfileHeaderButton { + Alpha = 0, RelativeSizeAxes = Axes.Y, Children = new Drawable[] { @@ -734,13 +739,16 @@ namespace osu.Game.Overlays.Profile followerText.Text = user.FollowerCount?.Length > 0 ? user.FollowerCount[0].ToString("#,##0") : "0"; - if (!user.PMFriendsOnly) + if (!user.PMFriendsOnly && apiAccess.LocalUser.Value.Id != user.Id) + { + messageButton.Show(); messageButton.Action = () => { channelManager?.OpenPrivateChannel(user); userOverlay?.Hide(); chatOverlay?.Show(); }; + } expandButton.Action = DetailsVisible.Toggle; From a33a1458a58bc7f65eb281d06c9691316b0e308f Mon Sep 17 00:00:00 2001 From: jorolf Date: Fri, 4 Jan 2019 22:52:00 +0100 Subject: [PATCH 0326/5608] update design and make play styles an enum --- osu.Game/Overlays/Profile/ProfileHeader.cs | 24 ++++++++++----------- osu.Game/Users/User.cs | 25 ++++++++++++++++++++-- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 7429a65210..e6d892f0b7 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -75,6 +75,7 @@ namespace osu.Game.Overlays.Profile private readonly Box headerBottomBox; private readonly LinkFlowContainer bottomTopLinkContainer; private readonly LinkFlowContainer bottomLinkContainer; + private Color4 linkBlue; private const float cover_height = 150; private const float cover_info_height = 75; @@ -693,6 +694,7 @@ namespace osu.Game.Overlays.Profile headerBottomBox.Colour = colours.CommunityUserGrayGreenDarker; communityUserGrayGreenLighter = colours.CommunityUserGrayGreenLighter; + linkBlue = colours.BlueLight; } private User user; @@ -827,10 +829,10 @@ namespace osu.Game.Overlays.Profile addSpacer(bottomTopLinkContainer); - if (user.PlayStyle?.Length > 0) + if (user.PlayStyles?.Length > 0) { bottomTopLinkContainer.AddText("Plays with "); - bottomTopLinkContainer.AddText(string.Join(", ", user.PlayStyle.Select(style => play_styles[style])), bold); + bottomTopLinkContainer.AddText(string.Join(", ", user.PlayStyles.Select(style => style.GetDescription())), bold); addSpacer(bottomTopLinkContainer); } @@ -857,7 +859,11 @@ namespace osu.Game.Overlays.Profile }); if (link != null) { - bottomLinkContainer.AddLink(" " + content, link, creationParameters: bold); + bottomLinkContainer.AddLink(" " + content, link, creationParameters: text => + { + bold(text); + text.Colour = linkBlue; + }); } else { @@ -888,8 +894,6 @@ namespace osu.Game.Overlays.Profile private class UserStatsLine : Container { - private readonly OsuSpriteText rightText; - public UserStatsLine(string left, string right) { RelativeSizeAxes = Axes.X; @@ -902,22 +906,16 @@ namespace osu.Game.Overlays.Profile Text = left, Font = "Exo2.0-Medium" }, - rightText = new OsuSpriteText + new OsuSpriteText { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, TextSize = 15, Text = right, - Font = "Exo2.0-Medium" + Font = "Exo2.0-Bold" }, }; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - rightText.Colour = colours.BlueLight; - } } private class ProfileHeaderButton : OsuHoverContainer diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 485c953b75..1005b094aa 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -2,7 +2,11 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.ComponentModel; +using System.Linq; +using System.Security.Cryptography; using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using osu.Framework.Configuration; namespace osu.Game.Users @@ -113,8 +117,13 @@ namespace osu.Game.Users [JsonProperty(@"follower_count")] public int[] FollowerCount; - [JsonProperty(@"playstyle")] - public string[] PlayStyle; + [JsonProperty] + private string[] playstyle + { + set { PlayStyles = value?.Select(str => Enum.Parse(typeof(PlayStyle), str, true)).Cast().ToArray(); } + } + + public PlayStyle[] PlayStyles; [JsonProperty(@"playmode")] public string PlayMode; @@ -174,5 +183,17 @@ namespace osu.Game.Users Username = "system", Id = 0 }; + + public enum PlayStyle + { + [Description("Keyboard")] + Keyboard, + [Description("Mouse")] + Mouse, + [Description("Tablet")] + Tablet, + [Description("Touch Screen")] + Touch, + } } } From 8bab87c072e96ef0ca2784d5ad6716ef7709994e Mon Sep 17 00:00:00 2001 From: jorolf Date: Fri, 4 Jan 2019 23:09:21 +0100 Subject: [PATCH 0327/5608] update resources and remove unused usings --- osu-resources | 2 +- osu.Game/Users/User.cs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/osu-resources b/osu-resources index 9880089b4e..677897728f 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit 9880089b4e8fcd78d68f30c8a40d43bf8dccca86 +Subproject commit 677897728f4332fa1200e0280ca02c4b987c6c47 diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 1005b094aa..f90781df77 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -4,9 +4,7 @@ using System; using System.ComponentModel; using System.Linq; -using System.Security.Cryptography; using Newtonsoft.Json; -using Newtonsoft.Json.Converters; using osu.Framework.Configuration; namespace osu.Game.Users From ddce608f97977d5dd6b5dd7ebf8eaff4ac9cda6e Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Sat, 5 Jan 2019 22:15:09 -0600 Subject: [PATCH 0328/5608] Setup osu.Android solution and its ruleset tests --- osu.Android.sln | 124 ++++++++++++++++++ osu.Android/GameView.cs | 25 ---- osu.Android/OsuGameActivity.cs | 17 +++ osu.Android/osu.Android.csproj | 23 +--- .../Assets/AboutAssets.txt | 19 +++ .../MainActivity.cs | 14 +- .../Properties/AndroidManifest.xml | 9 ++ .../Properties/AssemblyInfo.cs | 30 +++++ .../Resources/AboutResources.txt | 0 .../Resources/Resource.designer.cs | 112 ++++++++++++++++ .../Resources/layout/activity_main.axml | 6 - .../mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../Resources/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1634 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 1441 bytes .../mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 3552 bytes .../Resources/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1362 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 958 bytes .../mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2413 bytes .../Resources/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 2307 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 2056 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 4858 bytes .../Resources/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 3871 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 3403 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 8001 bytes .../Resources/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 5016 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 4889 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 10893 bytes .../Resources/values/Strings.xml | 4 + .../Resources/values/colors.xml | 6 + .../values/ic_launcher_background.xml | 4 + .../Resources/values/styles.xml | 0 ...u.Game.Rulesets.Catch.Tests.Android.csproj | 108 +++++++++++++++ .../Assets/AboutAssets.txt | 19 +++ .../MainActivity.cs | 19 +++ .../Properties/AndroidManifest.xml | 9 ++ .../Properties/AssemblyInfo.cs | 30 +++++ .../Resources/AboutResources.txt | 44 +++++++ .../Resources/Resource.designer.cs | 112 ++++++++++++++++ .../Resources/layout/activity_main.axml | 7 + .../mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../Resources/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1634 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 1441 bytes .../mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 3552 bytes .../Resources/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1362 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 958 bytes .../mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2413 bytes .../Resources/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 2307 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 2056 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 4858 bytes .../Resources/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 3871 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 3403 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 8001 bytes .../Resources/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 5016 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 4889 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 10893 bytes .../Resources/values/Strings.xml | 4 + .../Resources/values/colors.xml | 6 + .../values/ic_launcher_background.xml | 4 + .../Resources/values/styles.xml | 11 ++ ...u.Game.Rulesets.Mania.Tests.Android.csproj | 105 +++++++++++++++ .../Assets/AboutAssets.txt | 19 +++ .../MainActivity.cs | 19 +++ .../Properties/AndroidManifest.xml | 9 ++ .../Properties/AssemblyInfo.cs | 30 +++++ .../Resources/AboutResources.txt | 44 +++++++ .../Resources/Resource.designer.cs | 112 ++++++++++++++++ .../Resources/layout/activity_main.axml | 7 + .../mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../Resources/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1634 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 1441 bytes .../mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 3552 bytes .../Resources/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1362 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 958 bytes .../mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2413 bytes .../Resources/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 2307 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 2056 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 4858 bytes .../Resources/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 3871 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 3403 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 8001 bytes .../Resources/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 5016 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 4889 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 10893 bytes .../Resources/values/Strings.xml | 2 +- .../Resources/values/colors.xml | 6 + .../values/ic_launcher_background.xml | 4 + .../Resources/values/styles.xml | 11 ++ ...osu.Game.Rulesets.Osu.Tests.Android.csproj | 105 +++++++++++++++ .../Assets/AboutAssets.txt | 19 +++ .../MainActivity.cs | 19 +++ .../Properties/AndroidManifest.xml | 9 ++ .../Properties/AssemblyInfo.cs | 30 +++++ .../Resources/AboutResources.txt | 44 +++++++ .../Resources/Resource.designer.cs | 112 ++++++++++++++++ .../Resources/layout/activity_main.axml | 7 + .../mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../Resources/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1634 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 1441 bytes .../mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 3552 bytes .../Resources/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1362 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 958 bytes .../mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2413 bytes .../Resources/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 2307 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 2056 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 4858 bytes .../Resources/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 3871 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 3403 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 8001 bytes .../Resources/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 5016 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 4889 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 10893 bytes .../Resources/values/Strings.xml | 4 + .../Resources/values/colors.xml | 6 + .../values/ic_launcher_background.xml | 4 + .../Resources/values/styles.xml | 11 ++ ...u.Game.Rulesets.Taiko.Tests.Android.csproj | 105 +++++++++++++++ 120 files changed, 1591 insertions(+), 58 deletions(-) create mode 100644 osu.Android.sln delete mode 100644 osu.Android/GameView.cs create mode 100644 osu.Android/OsuGameActivity.cs create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Assets/AboutAssets.txt rename {osu.Android => osu.Game.Rulesets.Catch.Tests.Android}/MainActivity.cs (61%) create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Properties/AssemblyInfo.cs rename {osu.Android => osu.Game.Rulesets.Catch.Tests.Android}/Resources/AboutResources.txt (100%) create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/Resource.designer.cs rename {osu.Android => osu.Game.Rulesets.Catch.Tests.Android}/Resources/layout/activity_main.axml (63%) create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-mdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xhdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/values/Strings.xml create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/values/colors.xml create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/values/ic_launcher_background.xml rename {osu.Android => osu.Game.Rulesets.Catch.Tests.Android}/Resources/values/styles.xml (100%) create mode 100644 osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Assets/AboutAssets.txt create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Properties/AssemblyInfo.cs create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/AboutResources.txt create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/Resource.designer.cs create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/layout/activity_main.axml create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-mdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xhdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/values/Strings.xml create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/values/colors.xml create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/values/ic_launcher_background.xml create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/values/styles.xml create mode 100644 osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Assets/AboutAssets.txt create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Properties/AssemblyInfo.cs create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/AboutResources.txt create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/Resource.designer.cs create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/layout/activity_main.axml create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-mdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xhdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png rename {osu.Android => osu.Game.Rulesets.Osu.Tests.Android}/Resources/values/Strings.xml (51%) create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/values/colors.xml create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/values/ic_launcher_background.xml create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/values/styles.xml create mode 100644 osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Assets/AboutAssets.txt create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Properties/AssemblyInfo.cs create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/AboutResources.txt create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/Resource.designer.cs create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/layout/activity_main.axml create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-mdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xhdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/Strings.xml create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/colors.xml create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/ic_launcher_background.xml create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/styles.xml create mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj diff --git a/osu.Android.sln b/osu.Android.sln new file mode 100644 index 0000000000..11c0f3cb27 --- /dev/null +++ b/osu.Android.sln @@ -0,0 +1,124 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2006 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game", "osu.Game\osu.Game.csproj", "{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Resources", "osu-resources\osu.Game.Resources\osu.Game.Resources.csproj", "{D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Osu", "osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj", "{C92A607B-1FDD-4954-9F92-03FF547D9080}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Catch", "osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj", "{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Taiko", "osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj", "{F167E17A-7DE6-4AF5-B920-A5112296C695}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Mania", "osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj", "{48F4582B-7687-4621-9CBE-5C24197CB536}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Android", "osu.Android\osu.Android.csproj", "{D1D5F9A8-B40B-40E6-B02F-482D03346D3D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch.Tests.Android", "osu.Game.Rulesets.Catch.Tests.Android\osu.Game.Rulesets.Catch.Tests.Android.csproj", "{C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania.Tests.Android", "osu.Game.Rulesets.Mania.Tests.Android\osu.Game.Rulesets.Mania.Tests.Android.csproj", "{531F1092-DB27-445D-AA33-2A77C7187C99}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests.Android", "osu.Game.Rulesets.Osu.Tests.Android\osu.Game.Rulesets.Osu.Tests.Android.csproj", "{90CAB706-39CB-4B93-9629-3218A6FF8E9B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tests.Android", "osu.Game.Rulesets.Taiko.Tests.Android\osu.Game.Rulesets.Taiko.Tests.Android.csproj", "{3701A0A1-8476-42C6-B5C4-D24129B4A484}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.Build.0 = Release|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.Build.0 = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.Build.0 = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.Build.0 = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.Build.0 = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.ActiveCfg = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.Build.0 = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.Build.0 = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.Deploy.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.Build.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.Deploy.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.Build.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.ActiveCfg = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.Build.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.Deploy.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.Build.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.Deploy.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.Build.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.Deploy.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {671B0BEC-2403-45B0-9357-2C97CC517668} + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + Policies = $0 + $0.TextStylePolicy = $1 + $1.EolMarker = Windows + $1.inheritsSet = VisualStudio + $1.inheritsScope = text/plain + $1.scope = text/x-csharp + $0.CSharpFormattingPolicy = $2 + $2.IndentSwitchSection = True + $2.NewLinesForBracesInProperties = True + $2.NewLinesForBracesInAccessors = True + $2.NewLinesForBracesInAnonymousMethods = True + $2.NewLinesForBracesInControlBlocks = True + $2.NewLinesForBracesInAnonymousTypes = True + $2.NewLinesForBracesInObjectCollectionArrayInitializers = True + $2.NewLinesForBracesInLambdaExpressionBody = True + $2.NewLineForElse = True + $2.NewLineForCatch = True + $2.NewLineForFinally = True + $2.NewLineForMembersInObjectInit = True + $2.NewLineForMembersInAnonymousTypes = True + $2.NewLineForClausesInQuery = True + $2.SpacingAfterMethodDeclarationName = False + $2.SpaceAfterMethodCallName = False + $2.SpaceBeforeOpenSquareBracket = False + $2.inheritsSet = Mono + $2.inheritsScope = text/x-csharp + $2.scope = text/x-csharp + EndGlobalSection +EndGlobal diff --git a/osu.Android/GameView.cs b/osu.Android/GameView.cs deleted file mode 100644 index fc9cdeda53..0000000000 --- a/osu.Android/GameView.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using Android.Content; -using Android.Util; -using osu.Framework.Android; -using osu.Game; - -namespace osu.Android -{ - public class GameView : AndroidGameView - { - public GameView(Context context, IAttributeSet attrs) : - base(context, attrs) - { - CreateGame(); - } - - public GameView(Context context) : base(context) - { - CreateGame(); - } - public override Framework.Game CreateGame() => new OsuGame(); - } -} diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs new file mode 100644 index 0000000000..08f2707044 --- /dev/null +++ b/osu.Android/OsuGameActivity.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using Android.App; +using Android.Content.PM; +using osu.Framework.Android; +using osu.Game; + +namespace osu.Android +{ + [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] + public class OsuGameActivity : AndroidGameActivity + { + protected override Framework.Game CreateGame() + => new OsuGame(); + } +} diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 8a481b5239..daff6da961 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -62,8 +62,7 @@ - - + @@ -83,18 +82,12 @@ PreserveNewest - - - Designer - - - @@ -114,6 +107,12 @@ + + 0.0.7879 + + + 0.0.7879 + 0.22.0 @@ -129,14 +128,6 @@ - - {0fd409e8-a359-42bd-bc52-6a4745a122e5} - osu.Framework.Android - - - {0a8ba083-9d08-45ad-8653-796db1653388} - osu.Framework - {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} osu.Game.Resources diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Assets/AboutAssets.txt b/osu.Game.Rulesets.Catch.Tests.Android/Assets/AboutAssets.txt new file mode 100644 index 0000000000..b0633374bd --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.Android/Assets/AboutAssets.txt @@ -0,0 +1,19 @@ +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories) and given a Build Action of "AndroidAsset". + +These files will be deployed with you package and will be accessible using Android's +AssetManager, like this: + +public class ReadAsset : Activity +{ + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + InputStream input = Assets.Open ("my_asset.txt"); + } +} + +Additionally, some Android functions will automatically load asset files: + +Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); \ No newline at end of file diff --git a/osu.Android/MainActivity.cs b/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs similarity index 61% rename from osu.Android/MainActivity.cs rename to osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs index ff1fd9eba1..34f10dd16b 100644 --- a/osu.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs @@ -3,26 +3,20 @@ using Android.App; using Android.OS; +using Android.Support.V7.App; using Android.Runtime; using Android.Widget; -using Android.Views; -using Android.Content.PM; -namespace osu.Android +namespace osu.Game.Rulesets.Catch.Tests.Android { - [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true, ScreenOrientation = ScreenOrientation.Landscape, SupportsPictureInPicture = false)] - public class MainActivity : Activity + [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] + public class MainActivity : AppCompatActivity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // Set our view from the "main" layout resource SetContentView(Resource.Layout.activity_main); - Window.AddFlags(WindowManagerFlags.KeepScreenOn); - } - public override void OnBackPressed() - { - } } } diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml new file mode 100644 index 0000000000..6c8c0935b2 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..1b1fd64fb5 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AssemblyInfo.cs @@ -0,0 +1,30 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Android.App; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("osu.Game.Rulesets.Catch.Tests.Android")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("osu.Game.Rulesets.Catch.Tests.Android")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/osu.Android/Resources/AboutResources.txt b/osu.Game.Rulesets.Catch.Tests.Android/Resources/AboutResources.txt similarity index 100% rename from osu.Android/Resources/AboutResources.txt rename to osu.Game.Rulesets.Catch.Tests.Android/Resources/AboutResources.txt diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/Resource.designer.cs b/osu.Game.Rulesets.Catch.Tests.Android/Resources/Resource.designer.cs new file mode 100644 index 0000000000..a19fe391a8 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.Android/Resources/Resource.designer.cs @@ -0,0 +1,112 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +[assembly: global::Android.Runtime.ResourceDesignerAttribute("osu.Game.Rulesets.Catch.Tests.Android.Resource", IsApplication=true)] + +namespace osu.Game.Rulesets.Catch.Tests.Android +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public static void UpdateIdValues() + { + } + + public partial class Attribute + { + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class Id + { + + // aapt resource value: 0x7f050000 + public const int myButton = 2131034112; + + static Id() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Id() + { + } + } + + public partial class Layout + { + + // aapt resource value: 0x7f030000 + public const int Main = 2130903040; + + static Layout() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Layout() + { + } + } + + public partial class Mipmap + { + + // aapt resource value: 0x7f020000 + public const int Icon = 2130837504; + + static Mipmap() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Mipmap() + { + } + } + + public partial class String + { + + // aapt resource value: 0x7f040001 + public const int app_name = 2130968577; + + // aapt resource value: 0x7f040000 + public const int hello = 2130968576; + + static String() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private String() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/osu.Android/Resources/layout/activity_main.axml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/layout/activity_main.axml similarity index 63% rename from osu.Android/Resources/layout/activity_main.axml rename to osu.Game.Rulesets.Catch.Tests.Android/Resources/layout/activity_main.axml index fc0060857f..ff7a60eb50 100644 --- a/osu.Android/Resources/layout/activity_main.axml +++ b/osu.Game.Rulesets.Catch.Tests.Android/Resources/layout/activity_main.axml @@ -4,10 +4,4 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> - \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..2531cb31efc3a0a3de6113ab9c7845dc1d9654e4 GIT binary patch literal 1634 zcmV-o2A%ndP)B+Z3$1(8#|f~9B42Y^N-3=o2YCq0YUY$Zu=pM;#hG{lHi%n~Vh z1d1vN#EDO19X?u$`cV z!a}AKG@Bb*#1cdYg8af_;jP69b`k%G1n?0=F^8bI^o>wg-vEliK^U}y^!D|^p|ax; zC|pK=f+FHp!RUAhtlpGGUxJb|wm^5! z<1r%$<$TR02wajxKZ4MiR#aAxDLE(##UNyD|ABr4WoGRF*?@e^2|~Hq(gurSSJH*;Q~5lw{J5A_(PCXBWhzZE${qgzv0{dk-F( z1<}>r181tLiEla&f1j&?p2xjbfp2cTt-c1Ox~?9EhK9`cJ9Vatf)loIoQ@#h&}cIGD>Z#QLE}&(bMo@7Ff|7f#Nm^$PJpVcbj+v~K7wfVwF}=) zRQsc+`=A-+C)vrRvaIC-5u>|;3h z*G4-u#RI<_vuSN~vZ6{|I~q5FFk3%de#+*>UFG>&bq6~ zUEMZ~FIOmFO=kA^5rkp-Msw?^63xvdXVZ-rv@{6{iVO}M!}^Je%2BPbi+(L<5<%~h z2v^D+f<|j%7~cJjOzg*!GPQ{%uE{i%YgcZhuZh{yNlQ}RhaU1jd=K+AopVKP+D}&} zZ3y$llqZiln=Z_A$!qzkGbX0D{?l(v5@1|`QyCvCnQ`eKI>|zj_zo%y#fKf85VhQ} zP)y&j4P*nR3q{-o35iV6nx7QDqq<;WDVIt}|N%`!dgv*y3va8eLNj zU9x(?ieweHfQ*yXk8|=ssZ~qJEz^QoKJ|iGa>ge_Vm_8l}S+UvJ{8g4jr+o#aTSFsz1W;PDP zW765JXGU#3JL>SlIl3NRV2{7B2dLO1cIP)a4ZRYL|MBD36O1#oSgAf}APz5@;x=_U-<=y)Py7*}O5(uu7BL_eLe6Ek7pH|G zMq)FrF1EFq&yruS5b=F=w)fVVoPd(oeRyTFym_Uwyn~L=OL(O?cf^2L5R(SmjORx6 z%nmZf^W=3pkvT*>@osUNi>DULH1hL;y`JGQX$onRCr_U0=H~Viodq!<7Q{3rPk~{G gu#IhOV;e2n|1(WJB~7~kivR!s07*qoM6N<$g7lUVaR2}S literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..7a859c25556af7a2e46e22a2220eaded55628e9f GIT binary patch literal 1441 zcma)+`#%#30L6FjMQg%tuA0%p#0??L`*E=rD#U2F4L5n@F+O9Sp;(QwEQy7+?sX?r zCWN(!Hg`+j5k8*H@|yQEtnAi*(D{7M`Tlf1=eKjq)BUsp2nqrK01B=yNUv`!`EH=x zx8$xJQUd^Fuec%|(TT&0V}4orr_==mmCnEuzD+ff8Pg>pJRqsWsD{#?eGPaCu0(sEH_2RG@<6-Nt<8 ztPMUmmAz9Ga$23Y9~p9dqJSgJJ#Jk_r@o13^%d-Xf46i+Lrmz3 zy9(DUDVXj;Zny7nO+yn&W2flEX=C!8&D0zI`G# z8;XmlonoghgRFUY*$+7pPLa}Uy)onw>TT9t(FTV6#BV8&lXWDPRvQW_n~xZ|yLcZjX>m$Eaf1)dwXS`&E^ zkNjO;%;fWywchc=+w4utQ0Vbn%B>b~yy4I#D{?1!P`$P>Wdo+ljCo(tYia04JTc=$$u+IbzDVPFYpm8+AQj+ zGKH zfS{{hN%W)kF+(26oZpkURD5Q_G_z97F6{Jval+TOj-;5y)*Rdo3a$^^k~q5gpTzmp1q@+2X9O z;_VUF>;s~C1~gpFrFoh?{aQ|LlBIYz!z^P~lndX5-ES)p#+9GW*|-WBTzQ*&gKOE` zM##bUaWl`6rZBXw0!~_oUhf+H$tNc@lLZCj0bZT^KSo@C|P?7YR8dP0se1jj z9aA0|7MONf(ZYaLZs$s}r*05fx25-iN6mZe_*Rq%uyz(+^-k;t`!R`?uf~rn#1ZC7 zuv3}UrmMzcBbo4jym@fS5%I+G`GJIC1s$)MQs3Vhld?a2U;w}$@V%dC@%qpO7+3#$ N&GnQ!lI8SQ#{X#Iv!eh2 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..b8d35b3a1cfe5308bb099a5a1429555c41417e36 GIT binary patch literal 3552 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..8f56909cddfa86f1387074bf43003f36d6e67be1 GIT binary patch literal 2413 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 b;}yxl--Ss53i@>Q4YQuNcebmsMJN0NT!aL! literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..9737d79c0492b2c8a811621660eba33e79fab959 GIT binary patch literal 4858 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..9133e31b43252d00767a6a3806df9ba68de2d265 GIT binary patch literal 3871 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..c3ae5f5ccdecc01a9b17a2a0c2b1bb20602f0151 GIT binary patch literal 8001 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 z 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 F@PB1o0BisN literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..ef89bd5215ffcc38c68b119a7495a77a7084543b GIT binary patch literal 10893 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/Strings.xml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/Strings.xml new file mode 100644 index 0000000000..f800d6eb45 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/Strings.xml @@ -0,0 +1,4 @@ + + osu.Game.Rulesets.Catch.Tests.Android + Settings + diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/colors.xml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/colors.xml new file mode 100644 index 0000000000..17bb9a9dd1 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/colors.xml @@ -0,0 +1,6 @@ + + + #2c3e50 + #1B3147 + #3498db + diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/ic_launcher_background.xml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/ic_launcher_background.xml new file mode 100644 index 0000000000..6ec24e6413 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #2C3E50 + \ No newline at end of file diff --git a/osu.Android/Resources/values/styles.xml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/styles.xml similarity index 100% rename from osu.Android/Resources/values/styles.xml rename to osu.Game.Rulesets.Catch.Tests.Android/Resources/values/styles.xml diff --git a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj new file mode 100644 index 0000000000..d1e62c46a1 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj @@ -0,0 +1,108 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {122416d6-6b49-4ee2-a1e8-b825f31c79fe} + Library + Properties + osu.Game.Rulesets.Catch.Tests.Android + osu.Game.Rulesets.Catch.Tests.Android + 512 + True + Resources\Resource.designer.cs + Resource + Off + false + v8.1 + Properties\AndroidManifest.xml + Resources + Assets + Xamarin.Android.Net.AndroidClientHandler + + + True + portable + False + bin\Debug\ + DEBUG;TRACE + prompt + 4 + True + None + False + + + True + pdbonly + True + bin\Release\ + TRACE + prompt + 4 + true + False + SdkOnly + True + + + + + + + + + + + + + + + osu.licenseheader + + + + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Assets/AboutAssets.txt b/osu.Game.Rulesets.Mania.Tests.Android/Assets/AboutAssets.txt new file mode 100644 index 0000000000..b0633374bd --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/Assets/AboutAssets.txt @@ -0,0 +1,19 @@ +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories) and given a Build Action of "AndroidAsset". + +These files will be deployed with you package and will be accessible using Android's +AssetManager, like this: + +public class ReadAsset : Activity +{ + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + InputStream input = Assets.Open ("my_asset.txt"); + } +} + +Additionally, some Android functions will automatically load asset files: + +Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs new file mode 100644 index 0000000000..09fc7ce770 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs @@ -0,0 +1,19 @@ +using Android.App; +using Android.OS; +using Android.Support.V7.App; +using Android.Runtime; +using Android.Widget; + +namespace osu.Game.Rulesets.Mania.Tests.Android +{ + [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] + public class MainActivity : AppCompatActivity + { + protected override void OnCreate(Bundle savedInstanceState) + { + base.OnCreate(savedInstanceState); + // Set our view from the "main" layout resource + SetContentView(Resource.Layout.activity_main); + } + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml new file mode 100644 index 0000000000..6ffcfe16f7 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..468676e282 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AssemblyInfo.cs @@ -0,0 +1,30 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Android.App; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("osu.Game.Rulesets.Mania.Tests.Android")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("osu.Game.Rulesets.Mania.Tests.Android")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/AboutResources.txt b/osu.Game.Rulesets.Mania.Tests.Android/Resources/AboutResources.txt new file mode 100644 index 0000000000..c2bca974c4 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/Resources/AboutResources.txt @@ -0,0 +1,44 @@ +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.axml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable/ + icon.png + + layout/ + main.axml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called "R" +(this is an Android convention) that contains the tokens for each one of the resources +included. For example, for the above Resources layout, this is what the R class would expose: + +public class R { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main +to reference the layout/main.axml file, or R.strings.first_string to reference the first +string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/Resource.designer.cs b/osu.Game.Rulesets.Mania.Tests.Android/Resources/Resource.designer.cs new file mode 100644 index 0000000000..c27ae8a832 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/Resources/Resource.designer.cs @@ -0,0 +1,112 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +[assembly: global::Android.Runtime.ResourceDesignerAttribute("osu.Game.Rulesets.Mania.Tests.Android.Resource", IsApplication=true)] + +namespace osu.Game.Rulesets.Mania.Tests.Android +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public static void UpdateIdValues() + { + } + + public partial class Attribute + { + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class Id + { + + // aapt resource value: 0x7f050000 + public const int myButton = 2131034112; + + static Id() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Id() + { + } + } + + public partial class Layout + { + + // aapt resource value: 0x7f030000 + public const int Main = 2130903040; + + static Layout() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Layout() + { + } + } + + public partial class Mipmap + { + + // aapt resource value: 0x7f020000 + public const int Icon = 2130837504; + + static Mipmap() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Mipmap() + { + } + } + + public partial class String + { + + // aapt resource value: 0x7f040001 + public const int app_name = 2130968577; + + // aapt resource value: 0x7f040000 + public const int hello = 2130968576; + + static String() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private String() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/layout/activity_main.axml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/layout/activity_main.axml new file mode 100644 index 0000000000..ff7a60eb50 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/Resources/layout/activity_main.axml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..2531cb31efc3a0a3de6113ab9c7845dc1d9654e4 GIT binary patch literal 1634 zcmV-o2A%ndP)B+Z3$1(8#|f~9B42Y^N-3=o2YCq0YUY$Zu=pM;#hG{lHi%n~Vh z1d1vN#EDO19X?u$`cV z!a}AKG@Bb*#1cdYg8af_;jP69b`k%G1n?0=F^8bI^o>wg-vEliK^U}y^!D|^p|ax; zC|pK=f+FHp!RUAhtlpGGUxJb|wm^5! z<1r%$<$TR02wajxKZ4MiR#aAxDLE(##UNyD|ABr4WoGRF*?@e^2|~Hq(gurSSJH*;Q~5lw{J5A_(PCXBWhzZE${qgzv0{dk-F( z1<}>r181tLiEla&f1j&?p2xjbfp2cTt-c1Ox~?9EhK9`cJ9Vatf)loIoQ@#h&}cIGD>Z#QLE}&(bMo@7Ff|7f#Nm^$PJpVcbj+v~K7wfVwF}=) zRQsc+`=A-+C)vrRvaIC-5u>|;3h z*G4-u#RI<_vuSN~vZ6{|I~q5FFk3%de#+*>UFG>&bq6~ zUEMZ~FIOmFO=kA^5rkp-Msw?^63xvdXVZ-rv@{6{iVO}M!}^Je%2BPbi+(L<5<%~h z2v^D+f<|j%7~cJjOzg*!GPQ{%uE{i%YgcZhuZh{yNlQ}RhaU1jd=K+AopVKP+D}&} zZ3y$llqZiln=Z_A$!qzkGbX0D{?l(v5@1|`QyCvCnQ`eKI>|zj_zo%y#fKf85VhQ} zP)y&j4P*nR3q{-o35iV6nx7QDqq<;WDVIt}|N%`!dgv*y3va8eLNj zU9x(?ieweHfQ*yXk8|=ssZ~qJEz^QoKJ|iGa>ge_Vm_8l}S+UvJ{8g4jr+o#aTSFsz1W;PDP zW765JXGU#3JL>SlIl3NRV2{7B2dLO1cIP)a4ZRYL|MBD36O1#oSgAf}APz5@;x=_U-<=y)Py7*}O5(uu7BL_eLe6Ek7pH|G zMq)FrF1EFq&yruS5b=F=w)fVVoPd(oeRyTFym_Uwyn~L=OL(O?cf^2L5R(SmjORx6 z%nmZf^W=3pkvT*>@osUNi>DULH1hL;y`JGQX$onRCr_U0=H~Viodq!<7Q{3rPk~{G gu#IhOV;e2n|1(WJB~7~kivR!s07*qoM6N<$g7lUVaR2}S literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..7a859c25556af7a2e46e22a2220eaded55628e9f GIT binary patch literal 1441 zcma)+`#%#30L6FjMQg%tuA0%p#0??L`*E=rD#U2F4L5n@F+O9Sp;(QwEQy7+?sX?r zCWN(!Hg`+j5k8*H@|yQEtnAi*(D{7M`Tlf1=eKjq)BUsp2nqrK01B=yNUv`!`EH=x zx8$xJQUd^Fuec%|(TT&0V}4orr_==mmCnEuzD+ff8Pg>pJRqsWsD{#?eGPaCu0(sEH_2RG@<6-Nt<8 ztPMUmmAz9Ga$23Y9~p9dqJSgJJ#Jk_r@o13^%d-Xf46i+Lrmz3 zy9(DUDVXj;Zny7nO+yn&W2flEX=C!8&D0zI`G# z8;XmlonoghgRFUY*$+7pPLa}Uy)onw>TT9t(FTV6#BV8&lXWDPRvQW_n~xZ|yLcZjX>m$Eaf1)dwXS`&E^ zkNjO;%;fWywchc=+w4utQ0Vbn%B>b~yy4I#D{?1!P`$P>Wdo+ljCo(tYia04JTc=$$u+IbzDVPFYpm8+AQj+ zGKH zfS{{hN%W)kF+(26oZpkURD5Q_G_z97F6{Jval+TOj-;5y)*Rdo3a$^^k~q5gpTzmp1q@+2X9O z;_VUF>;s~C1~gpFrFoh?{aQ|LlBIYz!z^P~lndX5-ES)p#+9GW*|-WBTzQ*&gKOE` zM##bUaWl`6rZBXw0!~_oUhf+H$tNc@lLZCj0bZT^KSo@C|P?7YR8dP0se1jj z9aA0|7MONf(ZYaLZs$s}r*05fx25-iN6mZe_*Rq%uyz(+^-k;t`!R`?uf~rn#1ZC7 zuv3}UrmMzcBbo4jym@fS5%I+G`GJIC1s$)MQs3Vhld?a2U;w}$@V%dC@%qpO7+3#$ N&GnQ!lI8SQ#{X#Iv!eh2 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..b8d35b3a1cfe5308bb099a5a1429555c41417e36 GIT binary patch literal 3552 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..8f56909cddfa86f1387074bf43003f36d6e67be1 GIT binary patch literal 2413 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 b;}yxl--Ss53i@>Q4YQuNcebmsMJN0NT!aL! literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..9737d79c0492b2c8a811621660eba33e79fab959 GIT binary patch literal 4858 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..9133e31b43252d00767a6a3806df9ba68de2d265 GIT binary patch literal 3871 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..c3ae5f5ccdecc01a9b17a2a0c2b1bb20602f0151 GIT binary patch literal 8001 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 z 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 F@PB1o0BisN literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..ef89bd5215ffcc38c68b119a7495a77a7084543b GIT binary patch literal 10893 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/Strings.xml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/Strings.xml new file mode 100644 index 0000000000..6ab86b7262 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/Strings.xml @@ -0,0 +1,4 @@ + + osu.Game.Rulesets.Mania.Tests.Android + Settings + diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/colors.xml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/colors.xml new file mode 100644 index 0000000000..17bb9a9dd1 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/colors.xml @@ -0,0 +1,6 @@ + + + #2c3e50 + #1B3147 + #3498db + diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/ic_launcher_background.xml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/ic_launcher_background.xml new file mode 100644 index 0000000000..6ec24e6413 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #2C3E50 + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/styles.xml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/styles.xml new file mode 100644 index 0000000000..5885930df6 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj new file mode 100644 index 0000000000..5fbee695b4 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj @@ -0,0 +1,105 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {531F1092-DB27-445D-AA33-2A77C7187C99} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {122416d6-6b49-4ee2-a1e8-b825f31c79fe} + Library + Properties + osu.Game.Rulesets.Mania.Tests.Android + osu.Game.Rulesets.Mania.Tests.Android + 512 + True + Resources\Resource.designer.cs + Resource + Off + false + v8.1 + Properties\AndroidManifest.xml + Resources + Assets + Xamarin.Android.Net.AndroidClientHandler + + + True + portable + False + bin\Debug\ + DEBUG;TRACE + prompt + 4 + True + None + False + + + True + pdbonly + True + bin\Release\ + TRACE + prompt + 4 + true + False + SdkOnly + True + + + + + + + + + + + + + + + + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Assets/AboutAssets.txt b/osu.Game.Rulesets.Osu.Tests.Android/Assets/AboutAssets.txt new file mode 100644 index 0000000000..b0633374bd --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.Android/Assets/AboutAssets.txt @@ -0,0 +1,19 @@ +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories) and given a Build Action of "AndroidAsset". + +These files will be deployed with you package and will be accessible using Android's +AssetManager, like this: + +public class ReadAsset : Activity +{ + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + InputStream input = Assets.Open ("my_asset.txt"); + } +} + +Additionally, some Android functions will automatically load asset files: + +Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs new file mode 100644 index 0000000000..77a75f0d67 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs @@ -0,0 +1,19 @@ +using Android.App; +using Android.OS; +using Android.Support.V7.App; +using Android.Runtime; +using Android.Widget; + +namespace osu.Game.Rulesets.Osu.Tests.Android +{ + [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] + public class MainActivity : AppCompatActivity + { + protected override void OnCreate(Bundle savedInstanceState) + { + base.OnCreate(savedInstanceState); + // Set our view from the "main" layout resource + SetContentView(Resource.Layout.activity_main); + } + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml new file mode 100644 index 0000000000..05da9d02f7 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..0e43fb25cf --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AssemblyInfo.cs @@ -0,0 +1,30 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Android.App; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("osu.Game.Rulesets.Osu.Tests.Android")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("osu.Game.Rulesets.Osu.Tests.Android")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/AboutResources.txt b/osu.Game.Rulesets.Osu.Tests.Android/Resources/AboutResources.txt new file mode 100644 index 0000000000..c2bca974c4 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.Android/Resources/AboutResources.txt @@ -0,0 +1,44 @@ +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.axml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable/ + icon.png + + layout/ + main.axml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called "R" +(this is an Android convention) that contains the tokens for each one of the resources +included. For example, for the above Resources layout, this is what the R class would expose: + +public class R { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main +to reference the layout/main.axml file, or R.strings.first_string to reference the first +string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/Resource.designer.cs b/osu.Game.Rulesets.Osu.Tests.Android/Resources/Resource.designer.cs new file mode 100644 index 0000000000..f229c3f960 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.Android/Resources/Resource.designer.cs @@ -0,0 +1,112 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +[assembly: global::Android.Runtime.ResourceDesignerAttribute("osu.Game.Rulesets.Osu.Tests.Android.Resource", IsApplication=true)] + +namespace osu.Game.Rulesets.Osu.Tests.Android +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public static void UpdateIdValues() + { + } + + public partial class Attribute + { + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class Id + { + + // aapt resource value: 0x7f050000 + public const int myButton = 2131034112; + + static Id() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Id() + { + } + } + + public partial class Layout + { + + // aapt resource value: 0x7f030000 + public const int Main = 2130903040; + + static Layout() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Layout() + { + } + } + + public partial class Mipmap + { + + // aapt resource value: 0x7f020000 + public const int Icon = 2130837504; + + static Mipmap() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Mipmap() + { + } + } + + public partial class String + { + + // aapt resource value: 0x7f040001 + public const int app_name = 2130968577; + + // aapt resource value: 0x7f040000 + public const int hello = 2130968576; + + static String() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private String() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/layout/activity_main.axml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/layout/activity_main.axml new file mode 100644 index 0000000000..ff7a60eb50 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.Android/Resources/layout/activity_main.axml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..2531cb31efc3a0a3de6113ab9c7845dc1d9654e4 GIT binary patch literal 1634 zcmV-o2A%ndP)B+Z3$1(8#|f~9B42Y^N-3=o2YCq0YUY$Zu=pM;#hG{lHi%n~Vh z1d1vN#EDO19X?u$`cV z!a}AKG@Bb*#1cdYg8af_;jP69b`k%G1n?0=F^8bI^o>wg-vEliK^U}y^!D|^p|ax; zC|pK=f+FHp!RUAhtlpGGUxJb|wm^5! z<1r%$<$TR02wajxKZ4MiR#aAxDLE(##UNyD|ABr4WoGRF*?@e^2|~Hq(gurSSJH*;Q~5lw{J5A_(PCXBWhzZE${qgzv0{dk-F( z1<}>r181tLiEla&f1j&?p2xjbfp2cTt-c1Ox~?9EhK9`cJ9Vatf)loIoQ@#h&}cIGD>Z#QLE}&(bMo@7Ff|7f#Nm^$PJpVcbj+v~K7wfVwF}=) zRQsc+`=A-+C)vrRvaIC-5u>|;3h z*G4-u#RI<_vuSN~vZ6{|I~q5FFk3%de#+*>UFG>&bq6~ zUEMZ~FIOmFO=kA^5rkp-Msw?^63xvdXVZ-rv@{6{iVO}M!}^Je%2BPbi+(L<5<%~h z2v^D+f<|j%7~cJjOzg*!GPQ{%uE{i%YgcZhuZh{yNlQ}RhaU1jd=K+AopVKP+D}&} zZ3y$llqZiln=Z_A$!qzkGbX0D{?l(v5@1|`QyCvCnQ`eKI>|zj_zo%y#fKf85VhQ} zP)y&j4P*nR3q{-o35iV6nx7QDqq<;WDVIt}|N%`!dgv*y3va8eLNj zU9x(?ieweHfQ*yXk8|=ssZ~qJEz^QoKJ|iGa>ge_Vm_8l}S+UvJ{8g4jr+o#aTSFsz1W;PDP zW765JXGU#3JL>SlIl3NRV2{7B2dLO1cIP)a4ZRYL|MBD36O1#oSgAf}APz5@;x=_U-<=y)Py7*}O5(uu7BL_eLe6Ek7pH|G zMq)FrF1EFq&yruS5b=F=w)fVVoPd(oeRyTFym_Uwyn~L=OL(O?cf^2L5R(SmjORx6 z%nmZf^W=3pkvT*>@osUNi>DULH1hL;y`JGQX$onRCr_U0=H~Viodq!<7Q{3rPk~{G gu#IhOV;e2n|1(WJB~7~kivR!s07*qoM6N<$g7lUVaR2}S literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..7a859c25556af7a2e46e22a2220eaded55628e9f GIT binary patch literal 1441 zcma)+`#%#30L6FjMQg%tuA0%p#0??L`*E=rD#U2F4L5n@F+O9Sp;(QwEQy7+?sX?r zCWN(!Hg`+j5k8*H@|yQEtnAi*(D{7M`Tlf1=eKjq)BUsp2nqrK01B=yNUv`!`EH=x zx8$xJQUd^Fuec%|(TT&0V}4orr_==mmCnEuzD+ff8Pg>pJRqsWsD{#?eGPaCu0(sEH_2RG@<6-Nt<8 ztPMUmmAz9Ga$23Y9~p9dqJSgJJ#Jk_r@o13^%d-Xf46i+Lrmz3 zy9(DUDVXj;Zny7nO+yn&W2flEX=C!8&D0zI`G# z8;XmlonoghgRFUY*$+7pPLa}Uy)onw>TT9t(FTV6#BV8&lXWDPRvQW_n~xZ|yLcZjX>m$Eaf1)dwXS`&E^ zkNjO;%;fWywchc=+w4utQ0Vbn%B>b~yy4I#D{?1!P`$P>Wdo+ljCo(tYia04JTc=$$u+IbzDVPFYpm8+AQj+ zGKH zfS{{hN%W)kF+(26oZpkURD5Q_G_z97F6{Jval+TOj-;5y)*Rdo3a$^^k~q5gpTzmp1q@+2X9O z;_VUF>;s~C1~gpFrFoh?{aQ|LlBIYz!z^P~lndX5-ES)p#+9GW*|-WBTzQ*&gKOE` zM##bUaWl`6rZBXw0!~_oUhf+H$tNc@lLZCj0bZT^KSo@C|P?7YR8dP0se1jj z9aA0|7MONf(ZYaLZs$s}r*05fx25-iN6mZe_*Rq%uyz(+^-k;t`!R`?uf~rn#1ZC7 zuv3}UrmMzcBbo4jym@fS5%I+G`GJIC1s$)MQs3Vhld?a2U;w}$@V%dC@%qpO7+3#$ N&GnQ!lI8SQ#{X#Iv!eh2 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..b8d35b3a1cfe5308bb099a5a1429555c41417e36 GIT binary patch literal 3552 zcmV<64IlD}P)o8zx62qSGZVDjFcw zmxU;G#z^HzQ!GXJ-*69pbEeNn;$q%9`<^_ve6S+hkfX>pEmUTks+2m@VN4e=-BfB# zcQM@~beFnE|8|&qR$IOR+Cm@fKKV*xuU`Zdvl=LK4a4vxD=}@uREG)CWaLRqJ5ybP zu6!%iC+?fAzSb|q<0OVH@(J1H8ThTgk0;W=21TJYwd22S48?0q?Ql<_H9oW?Q#<^| zeirUq0oDLxz*ubc^EioOzd5Deq{k}q4=YI_6Qm}Lx&A|+|0D}zEJqe60pgP7hwE|CF z@#G3rLLN!=hY3#Mncm#=bNubjDVN#!%R!#+yMuUTdtd@=nOZsg2kv6qi*x zzDFd9=@0{x|A>LZ;?=}}RP0ia7?F(2EK$;G^~ix^1(KmvlA1T%Me0V!5Mp(azrt*g z`GKR#Hle}^)6nEOi&5p=B`&3>XD&k7hNpOg6rWXgIVwRD#GYff08(lhSI*BM130r6 ztwLvix`bL=@1gtm@4J-l-fc!-e{&2~Oqs{qaK~p9f7wxs>V|45HOAS_daGw5xEuU;CIJ+92}tg z4<4ZP8$L$Eb4K%sldwI?Dr*+0^Cav!^8yGXz0q0enY&~)R;yOG00dN1dkvL6IfJJZ zVXu}^_&HPQzwpQx>^t=9m8u@|rU zGZkWRl_Ic3Qgwcn12rQ-p|)rUPVR0xZ|g z#6I?<=DMiep91ftqa7MkB{^?D-ZoQ_q4o#Zz5>gjTpeUp0 z3G@w~C|7{qc>5!&4by(n%Jp`iuf291jemANFJmoJ=kLN8bXoMLmT3fvj9{#fSNW<} zPWfc?!`YwgG7Mhr!;M=hJH@mEk5k`p+aWlYYie<%{DirkwsaCDMRv!-QbfD`F`U&* zo>5d65*-)D#>B#V$@hY}ZNj;cW4C_i&aXIcn%mJeYW9gE&#PbekM-NS=wn4l1Pv@ zMzD%cy$ABGjazr~@-TOPy^E&IU2N`Sc+MEK;iFAm2A0h&E$DX(ms?2dx_7F01)(i1 zt(1M_?Cw+ZHd@;uW{XK*Y{?Ju0ch5um8c1;jWfXy;v{GISLTsgmo00A* z8#H~vA1NDj?m{&xWtC4M{&ANL0wWz5DipHQ4JPOCWyT?wRHhZzZ zeZJFjg#>%C8}$u6=EclzKE2=~#v<4nARyoPtdc`q14SwhI__K?1o_n~Yb@iSRqNli zs3kSrZnRJbh=V@m8MSxBLHE(SRrcc`CQy{7<{rUV_*?AJCSmpCIGg>1Pb59_r4>#^ z(nn96vdGRMk_L&gj-oWj!lL9s60`o2)KQE1 zB&*KmVz3NtmJIw>|N6;iRC%JSJZi=ZuUXilH+U`xaL>hXvZ^UVLRHpEz@n>UwO_O{ zvxM&!UB21;HmhtN?84Q$8@99YqbIS1J!uhfSMyjD;F8UQWTYp=gUt@U%M2UX5p%4Kzf zcJbV2CClLAM^#U{Xz6L zJdsKRtEu5+&Ybs{fi3b28WN?!`q@NF5kI%@$vey#&m~jmHwA`7A1U07i4e+zpQNm|hsmsx_shxjsk(;ai>lwhlEheA0qLHoISKxd?ut+1!iOjA0S8%WxDr|ybBIOiWdU3lm z`-eQ?oQ5>5uzjd7ej1)jB$<=TK2p#pFi;o>wmV#sI7_BxK%(~=dnzy;Aqovnm`E`X z<`57N71R@7aPSTY2!M`7!(!s5%GHI9gb|Mfi808OJ5S4R8Y+~7+uvURZz0;p z$0s#rxNa}R6fBi{*o(kCWK;@xicx9yVII?fSHiQ~j)?aO3JQYL#1XJ5KSG|e0(*zs zOa;K*K(T=V9)Oo{S<-6w00i(zcy;?%WAK3C1Mvl$9;N=lVFfV>njP|tB6AU(uC?@> z>XDSeeB2Vo7A9ow#Js=(UMbBR<;r{YlREwU{QN+-qoC#%8Y!79O45D}o{p&oU}|T; z>W*ZQ?|P6=Q;;J~SYlu-7;}g~TnRh?FN7zL`Pd01O}@Uq@HG|@9IGE37W1SqA>&g? zTHZBSPGLzE$?Ht!kDJ76DBvsz?sa_Jgn8b?lwYVN8t5Cwz+*wV0=BG(XdZfBYHVG7 zgM)+piP`~Bia~<{b0Q>(OJWkWdn9S2YM^=t1#;S6S%7Af;8{qR!SG`HQiJ>24Sho2 zL}ElRCX5X{JPMx?>I+FAk*G-6f(-`qF+V?Th(J13AWvQ!t;+aJJVO7iBze?19H-RE z(+le5=|zn+71YB$_zj+cXCrYNXbXK1X@NeYU<{IQJ~|&+Vuu8n20(yGz=FMhv2fZG zydQSKNf0W)qyvJ7=KBu`Edqjn!#(_43OobPk~Yv*0DY05b$~lvw>!Y<4{sZy*+GK_ z4fXQ!4TV}T0S=6OG@&SRFASc6XQ2&|l>WaZP#hR`YNGwS5C*yUv?lc$Zn7uu(=Jd zBQr(wEwogv4g_{iFq~uA3k~Z|L@DvE#_JQ>CKxj(Q|L@;_pg7{hnT!9|ZQb+#ochnl1kg9D@G4hNk|1@c1c) z{PkOR|2qXG{Wo$7`M-9{ZVdTtdk+0Kb_u1e2S8@7a?0x`-IJ*AtKYskrENiB%2SAk%zG8F7zQf=Uw)BkpfBE_?MDjX& z@xO&fB(T^G|G)3ZNu2smpTF|o#wUh09?%1ZEU4JTml;2Q`T9S*q6Mrzuc{3gQ-A*d z{Q2vDYEeB{thm1G|F`eoaq0)fT1(#ya4b^Y1D+8X|DV5nO|V2c3(TM(uHGc5|Nf&V|J{K3i0U2yrD0-<#2-I@{x5Ip1M7*&D*x{joegF;bWbC? z(kra(q`n6-N}I4|UUdBS-G~1{3Hjh;&W{YUBz~nhg z|9eJe{4Z(f##+{cVkED+{l6Db&737`v6TNa;pIQg8*`u<_1?qB7^TPOFJHjLD9$4G z$4`iwAE;_BU%Le^B3KtGndh}^?w7N zp&3LI9GX_%Z^hMgm2i3hX^M$M&D3?3wyocP$TZWyV~|^v4II`1-Ns4G92qkYkC3*q zq5Vcp3$J%tR^A_hzW)HC>4{->YFc`|Q_{EF#LX=TNWTIEGZ*dOIh!!#7am`0)iN z!-Y*JzdqP8rN&2Y&y2(+EtA?m9-5+}#BXAw@$*D;zxcf=lRhYP2`ZYNoGdU|=;=Y1 z!-o@UOzpBVHoTpyopyF#@i)8YcdVaV?2ljDUj6>w?`yyA*Pf5cUSE9b6wq26;8J@~ z){!@7GpTmNE>2kO_POn1zf8`~}P?%{85(;s&nc+C&;t$4D5$+f9? z-8>e~Z&%(_OwrVd==PGc4mhTFjVafjdCqsM|EvEe$2)U;a9s0IGofbtHcpKz;cJR= z`DNzVI-iMtrg<$r*EFejE8l0oMM3e)a|=o;x>Mhk@*n)xx%2Rrt=4TnivwP5zpS-& z@5h3w<{9>vH!6KP74q!po!oh)$BI~jUu}4P|5ofvi@(2i9NyELbZ$qD}PI&+JJ3+^f2=YEuP zjpepXu;`->)%n@lB|b@Iv$k0qhJJp%S?O9t?)zjLwwY?z@=v^12)=lt^ZcwNoye^x z_uu*-x}ntY`mc3S`yMaaHuurqE~e`{G_IsMZdhw*{kDDS9h3WSQa;8d3vwO)d?WE+ z%*LAIs=2#$t=BZmPTP}xMpj0I9ti9_c{r`p zu+;ELV)~|tmk}}-GjAWQO5U<}Lr?bB5UX>pYf5~UOnY%ZTQR${nq6YQOHc15>q%#$ zl8$8k_1fsCw;<~OiJ-OiE?f7RJWt%N`#e!y=2`BhIqju|a?kW5QupmV#wx6HrSs?J z&nJroVy6i|*Og1U`{c;a^^dPvTfNJjdCg1nUS<*OC dK7&Kx57tYsZ49$p7vBM?@pScbS?83{1OVHE%8UR2 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..8f56909cddfa86f1387074bf43003f36d6e67be1 GIT binary patch literal 2413 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 b;}yxl--Ss53i@>Q4YQuNcebmsMJN0NT!aL! literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..9737d79c0492b2c8a811621660eba33e79fab959 GIT binary patch literal 4858 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..9133e31b43252d00767a6a3806df9ba68de2d265 GIT binary patch literal 3871 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..c3ae5f5ccdecc01a9b17a2a0c2b1bb20602f0151 GIT binary patch literal 8001 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 z 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 F@PB1o0BisN literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..ef89bd5215ffcc38c68b119a7495a77a7084543b GIT binary patch literal 10893 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 literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/values/Strings.xml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/Strings.xml similarity index 51% rename from osu.Android/Resources/values/Strings.xml rename to osu.Game.Rulesets.Osu.Tests.Android/Resources/values/Strings.xml index 21f749f876..8c47838dfb 100644 --- a/osu.Android/Resources/values/Strings.xml +++ b/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/Strings.xml @@ -1,4 +1,4 @@ - osu!lazer + osu.Game.Rulesets.Osu.Tests.Android Settings diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/colors.xml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/colors.xml new file mode 100644 index 0000000000..17bb9a9dd1 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/colors.xml @@ -0,0 +1,6 @@ + + + #2c3e50 + #1B3147 + #3498db + diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/ic_launcher_background.xml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/ic_launcher_background.xml new file mode 100644 index 0000000000..6ec24e6413 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #2C3E50 + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/styles.xml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/styles.xml new file mode 100644 index 0000000000..5885930df6 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj new file mode 100644 index 0000000000..7eeee4fd80 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj @@ -0,0 +1,105 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {90CAB706-39CB-4B93-9629-3218A6FF8E9B} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {122416d6-6b49-4ee2-a1e8-b825f31c79fe} + Library + Properties + osu.Game.Rulesets.Osu.Tests.Android + osu.Game.Rulesets.Osu.Tests.Android + 512 + True + Resources\Resource.designer.cs + Resource + Off + false + v8.1 + Properties\AndroidManifest.xml + Resources + Assets + Xamarin.Android.Net.AndroidClientHandler + + + True + portable + False + bin\Debug\ + DEBUG;TRACE + prompt + 4 + True + None + False + + + True + pdbonly + True + bin\Release\ + TRACE + prompt + 4 + true + False + SdkOnly + True + + + + + + + + + + + + + + + + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Assets/AboutAssets.txt b/osu.Game.Rulesets.Taiko.Tests.Android/Assets/AboutAssets.txt new file mode 100644 index 0000000000..b0633374bd --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Assets/AboutAssets.txt @@ -0,0 +1,19 @@ +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories) and given a Build Action of "AndroidAsset". + +These files will be deployed with you package and will be accessible using Android's +AssetManager, like this: + +public class ReadAsset : Activity +{ + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + InputStream input = Assets.Open ("my_asset.txt"); + } +} + +Additionally, some Android functions will automatically load asset files: + +Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs new file mode 100644 index 0000000000..8ceca4d436 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs @@ -0,0 +1,19 @@ +using Android.App; +using Android.OS; +using Android.Support.V7.App; +using Android.Runtime; +using Android.Widget; + +namespace osu.Game.Rulesets.Taiko.Tests.Android +{ + [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] + public class MainActivity : AppCompatActivity + { + protected override void OnCreate(Bundle savedInstanceState) + { + base.OnCreate(savedInstanceState); + // Set our view from the "main" layout resource + SetContentView(Resource.Layout.activity_main); + } + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml new file mode 100644 index 0000000000..9b5e759012 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..28f5d292ab --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AssemblyInfo.cs @@ -0,0 +1,30 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Android.App; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("osu.Game.Rulesets.Taiko.Tests.Android")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("osu.Game.Rulesets.Taiko.Tests.Android")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/AboutResources.txt b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/AboutResources.txt new file mode 100644 index 0000000000..c2bca974c4 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/AboutResources.txt @@ -0,0 +1,44 @@ +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.axml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable/ + icon.png + + layout/ + main.axml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called "R" +(this is an Android convention) that contains the tokens for each one of the resources +included. For example, for the above Resources layout, this is what the R class would expose: + +public class R { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main +to reference the layout/main.axml file, or R.strings.first_string to reference the first +string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/Resource.designer.cs b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/Resource.designer.cs new file mode 100644 index 0000000000..d3709d3cdb --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/Resource.designer.cs @@ -0,0 +1,112 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +[assembly: global::Android.Runtime.ResourceDesignerAttribute("osu.Game.Rulesets.Taiko.Tests.Android.Resource", IsApplication=true)] + +namespace osu.Game.Rulesets.Taiko.Tests.Android +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public static void UpdateIdValues() + { + } + + public partial class Attribute + { + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class Id + { + + // aapt resource value: 0x7f050000 + public const int myButton = 2131034112; + + static Id() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Id() + { + } + } + + public partial class Layout + { + + // aapt resource value: 0x7f030000 + public const int Main = 2130903040; + + static Layout() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Layout() + { + } + } + + public partial class Mipmap + { + + // aapt resource value: 0x7f020000 + public const int Icon = 2130837504; + + static Mipmap() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Mipmap() + { + } + } + + public partial class String + { + + // aapt resource value: 0x7f040001 + public const int app_name = 2130968577; + + // aapt resource value: 0x7f040000 + public const int hello = 2130968576; + + static String() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private String() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/layout/activity_main.axml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/layout/activity_main.axml new file mode 100644 index 0000000000..ff7a60eb50 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/layout/activity_main.axml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..2531cb31efc3a0a3de6113ab9c7845dc1d9654e4 GIT binary patch literal 1634 zcmV-o2A%ndP)B+Z3$1(8#|f~9B42Y^N-3=o2YCq0YUY$Zu=pM;#hG{lHi%n~Vh z1d1vN#EDO19X?u$`cV z!a}AKG@Bb*#1cdYg8af_;jP69b`k%G1n?0=F^8bI^o>wg-vEliK^U}y^!D|^p|ax; zC|pK=f+FHp!RUAhtlpGGUxJb|wm^5! z<1r%$<$TR02wajxKZ4MiR#aAxDLE(##UNyD|ABr4WoGRF*?@e^2|~Hq(gurSSJH*;Q~5lw{J5A_(PCXBWhzZE${qgzv0{dk-F( z1<}>r181tLiEla&f1j&?p2xjbfp2cTt-c1Ox~?9EhK9`cJ9Vatf)loIoQ@#h&}cIGD>Z#QLE}&(bMo@7Ff|7f#Nm^$PJpVcbj+v~K7wfVwF}=) zRQsc+`=A-+C)vrRvaIC-5u>|;3h z*G4-u#RI<_vuSN~vZ6{|I~q5FFk3%de#+*>UFG>&bq6~ zUEMZ~FIOmFO=kA^5rkp-Msw?^63xvdXVZ-rv@{6{iVO}M!}^Je%2BPbi+(L<5<%~h z2v^D+f<|j%7~cJjOzg*!GPQ{%uE{i%YgcZhuZh{yNlQ}RhaU1jd=K+AopVKP+D}&} zZ3y$llqZiln=Z_A$!qzkGbX0D{?l(v5@1|`QyCvCnQ`eKI>|zj_zo%y#fKf85VhQ} zP)y&j4P*nR3q{-o35iV6nx7QDqq<;WDVIt}|N%`!dgv*y3va8eLNj zU9x(?ieweHfQ*yXk8|=ssZ~qJEz^QoKJ|iGa>ge_Vm_8l}S+UvJ{8g4jr+o#aTSFsz1W;PDP zW765JXGU#3JL>SlIl3NRV2{7B2dLO1cIP)a4ZRYL|MBD36O1#oSgAf}APz5@;x=_U-<=y)Py7*}O5(uu7BL_eLe6Ek7pH|G zMq)FrF1EFq&yruS5b=F=w)fVVoPd(oeRyTFym_Uwyn~L=OL(O?cf^2L5R(SmjORx6 z%nmZf^W=3pkvT*>@osUNi>DULH1hL;y`JGQX$onRCr_U0=H~Viodq!<7Q{3rPk~{G gu#IhOV;e2n|1(WJB~7~kivR!s07*qoM6N<$g7lUVaR2}S literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..7a859c25556af7a2e46e22a2220eaded55628e9f GIT binary patch literal 1441 zcma)+`#%#30L6FjMQg%tuA0%p#0??L`*E=rD#U2F4L5n@F+O9Sp;(QwEQy7+?sX?r zCWN(!Hg`+j5k8*H@|yQEtnAi*(D{7M`Tlf1=eKjq)BUsp2nqrK01B=yNUv`!`EH=x zx8$xJQUd^Fuec%|(TT&0V}4orr_==mmCnEuzD+ff8Pg>pJRqsWsD{#?eGPaCu0(sEH_2RG@<6-Nt<8 ztPMUmmAz9Ga$23Y9~p9dqJSgJJ#Jk_r@o13^%d-Xf46i+Lrmz3 zy9(DUDVXj;Zny7nO+yn&W2flEX=C!8&D0zI`G# z8;XmlonoghgRFUY*$+7pPLa}Uy)onw>TT9t(FTV6#BV8&lXWDPRvQW_n~xZ|yLcZjX>m$Eaf1)dwXS`&E^ zkNjO;%;fWywchc=+w4utQ0Vbn%B>b~yy4I#D{?1!P`$P>Wdo+ljCo(tYia04JTc=$$u+IbzDVPFYpm8+AQj+ zGKH zfS{{hN%W)kF+(26oZpkURD5Q_G_z97F6{Jval+TOj-;5y)*Rdo3a$^^k~q5gpTzmp1q@+2X9O z;_VUF>;s~C1~gpFrFoh?{aQ|LlBIYz!z^P~lndX5-ES)p#+9GW*|-WBTzQ*&gKOE` zM##bUaWl`6rZBXw0!~_oUhf+H$tNc@lLZCj0bZT^KSo@C|P?7YR8dP0se1jj z9aA0|7MONf(ZYaLZs$s}r*05fx25-iN6mZe_*Rq%uyz(+^-k;t`!R`?uf~rn#1ZC7 zuv3}UrmMzcBbo4jym@fS5%I+G`GJIC1s$)MQs3Vhld?a2U;w}$@V%dC@%qpO7+3#$ N&GnQ!lI8SQ#{X#Iv!eh2 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..b8d35b3a1cfe5308bb099a5a1429555c41417e36 GIT binary patch literal 3552 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..8f56909cddfa86f1387074bf43003f36d6e67be1 GIT binary patch literal 2413 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 b;}yxl--Ss53i@>Q4YQuNcebmsMJN0NT!aL! literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..9737d79c0492b2c8a811621660eba33e79fab959 GIT binary patch literal 4858 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..9133e31b43252d00767a6a3806df9ba68de2d265 GIT binary patch literal 3871 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..c3ae5f5ccdecc01a9b17a2a0c2b1bb20602f0151 GIT binary patch literal 8001 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 z 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 F@PB1o0BisN literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..ef89bd5215ffcc38c68b119a7495a77a7084543b GIT binary patch literal 10893 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/Strings.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/Strings.xml new file mode 100644 index 0000000000..12965f132d --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/Strings.xml @@ -0,0 +1,4 @@ + + osu.Game.Rulesets.Taiko.Tests.Android + Settings + diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/colors.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/colors.xml new file mode 100644 index 0000000000..17bb9a9dd1 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/colors.xml @@ -0,0 +1,6 @@ + + + #2c3e50 + #1B3147 + #3498db + diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/ic_launcher_background.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/ic_launcher_background.xml new file mode 100644 index 0000000000..6ec24e6413 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #2C3E50 + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/styles.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/styles.xml new file mode 100644 index 0000000000..5885930df6 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj new file mode 100644 index 0000000000..62c2cefe06 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj @@ -0,0 +1,105 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {3701A0A1-8476-42C6-B5C4-D24129B4A484} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {122416d6-6b49-4ee2-a1e8-b825f31c79fe} + Library + Properties + osu.Game.Rulesets.Taiko.Tests.Android + osu.Game.Rulesets.Taiko.Tests.Android + 512 + True + Resources\Resource.designer.cs + Resource + Off + false + v8.1 + Properties\AndroidManifest.xml + Resources + Assets + Xamarin.Android.Net.AndroidClientHandler + + + True + portable + False + bin\Debug\ + DEBUG;TRACE + prompt + 4 + True + None + False + + + True + pdbonly + True + bin\Release\ + TRACE + prompt + 4 + true + False + SdkOnly + True + + + + + + + + + + + + + + + + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From e5dd95198a283282936bb76aa463869c84cd22a2 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Sat, 5 Jan 2019 23:17:55 -0600 Subject: [PATCH 0329/5608] Cleanup project files with common props --- osu.Android.props | 60 ++++++++++ osu.Android/Assets/AboutAssets.txt | 19 --- osu.Android/osu.Android.csproj | 67 +---------- .../Assets/AboutAssets.txt | 19 --- .../MainActivity.cs | 19 ++- .../Resources/AboutResources.txt | 44 ------- .../Resources/Resource.designer.cs | 112 ------------------ .../Resources/layout/activity_main.axml | 7 -- .../mipmap-anydpi-v26/ic_launcher.xml | 5 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../Resources/mipmap-hdpi/ic_launcher.png | Bin 1634 -> 0 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 1441 -> 0 bytes .../mipmap-hdpi/ic_launcher_round.png | Bin 3552 -> 0 bytes .../Resources/mipmap-mdpi/ic_launcher.png | Bin 1362 -> 0 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 958 -> 0 bytes .../mipmap-mdpi/ic_launcher_round.png | Bin 2413 -> 0 bytes .../Resources/mipmap-xhdpi/ic_launcher.png | Bin 2307 -> 0 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 2056 -> 0 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 4858 -> 0 bytes .../Resources/mipmap-xxhdpi/ic_launcher.png | Bin 3871 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 3403 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 8001 -> 0 bytes .../Resources/mipmap-xxxhdpi/ic_launcher.png | Bin 5016 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 4889 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 10893 -> 0 bytes .../Resources/values/Strings.xml | 4 - .../Resources/values/colors.xml | 6 - .../values/ic_launcher_background.xml | 4 - .../Resources/values/styles.xml | 11 -- ...u.Game.Rulesets.Catch.Tests.Android.csproj | 82 +++---------- .../Assets/AboutAssets.txt | 19 --- .../MainActivity.cs | 26 ++-- .../Resources/AboutResources.txt | 44 ------- .../Resources/Resource.designer.cs | 112 ------------------ .../Resources/layout/activity_main.axml | 7 -- .../mipmap-anydpi-v26/ic_launcher.xml | 5 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../Resources/mipmap-hdpi/ic_launcher.png | Bin 1634 -> 0 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 1441 -> 0 bytes .../mipmap-hdpi/ic_launcher_round.png | Bin 3552 -> 0 bytes .../Resources/mipmap-mdpi/ic_launcher.png | Bin 1362 -> 0 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 958 -> 0 bytes .../mipmap-mdpi/ic_launcher_round.png | Bin 2413 -> 0 bytes .../Resources/mipmap-xhdpi/ic_launcher.png | Bin 2307 -> 0 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 2056 -> 0 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 4858 -> 0 bytes .../Resources/mipmap-xxhdpi/ic_launcher.png | Bin 3871 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 3403 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 8001 -> 0 bytes .../Resources/mipmap-xxxhdpi/ic_launcher.png | Bin 5016 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 4889 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 10893 -> 0 bytes .../Resources/values/Strings.xml | 4 - .../Resources/values/colors.xml | 6 - .../values/ic_launcher_background.xml | 4 - .../Resources/values/styles.xml | 11 -- ...u.Game.Rulesets.Mania.Tests.Android.csproj | 85 +++---------- .../Assets/AboutAssets.txt | 19 --- .../MainActivity.cs | 26 ++-- .../Resources/AboutResources.txt | 44 ------- .../Resources/Resource.designer.cs | 112 ------------------ .../Resources/layout/activity_main.axml | 7 -- .../mipmap-anydpi-v26/ic_launcher.xml | 5 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../Resources/mipmap-hdpi/ic_launcher.png | Bin 1634 -> 0 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 1441 -> 0 bytes .../mipmap-hdpi/ic_launcher_round.png | Bin 3552 -> 0 bytes .../Resources/mipmap-mdpi/ic_launcher.png | Bin 1362 -> 0 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 958 -> 0 bytes .../mipmap-mdpi/ic_launcher_round.png | Bin 2413 -> 0 bytes .../Resources/mipmap-xhdpi/ic_launcher.png | Bin 2307 -> 0 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 2056 -> 0 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 4858 -> 0 bytes .../Resources/mipmap-xxhdpi/ic_launcher.png | Bin 3871 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 3403 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 8001 -> 0 bytes .../Resources/mipmap-xxxhdpi/ic_launcher.png | Bin 5016 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 4889 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 10893 -> 0 bytes .../Resources/values/Strings.xml | 4 - .../Resources/values/colors.xml | 6 - .../values/ic_launcher_background.xml | 4 - .../Resources/values/styles.xml | 11 -- ...osu.Game.Rulesets.Osu.Tests.Android.csproj | 85 +++---------- .../Assets/AboutAssets.txt | 19 --- .../MainActivity.cs | 26 ++-- .../Resources/AboutResources.txt | 44 ------- .../Resources/Resource.designer.cs | 112 ------------------ .../Resources/layout/activity_main.axml | 7 -- .../mipmap-anydpi-v26/ic_launcher.xml | 5 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../Resources/mipmap-hdpi/ic_launcher.png | Bin 1634 -> 0 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 1441 -> 0 bytes .../mipmap-hdpi/ic_launcher_round.png | Bin 3552 -> 0 bytes .../Resources/mipmap-mdpi/ic_launcher.png | Bin 1362 -> 0 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 958 -> 0 bytes .../mipmap-mdpi/ic_launcher_round.png | Bin 2413 -> 0 bytes .../Resources/mipmap-xhdpi/ic_launcher.png | Bin 2307 -> 0 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 2056 -> 0 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 4858 -> 0 bytes .../Resources/mipmap-xxhdpi/ic_launcher.png | Bin 3871 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 3403 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 8001 -> 0 bytes .../Resources/mipmap-xxxhdpi/ic_launcher.png | Bin 5016 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 4889 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 10893 -> 0 bytes .../Resources/values/Strings.xml | 4 - .../Resources/values/colors.xml | 6 - .../values/ic_launcher_background.xml | 4 - .../Resources/values/styles.xml | 11 -- ...u.Game.Rulesets.Taiko.Tests.Android.csproj | 86 ++++---------- 111 files changed, 179 insertions(+), 1270 deletions(-) create mode 100644 osu.Android.props delete mode 100644 osu.Android/Assets/AboutAssets.txt delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Assets/AboutAssets.txt delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/AboutResources.txt delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/Resource.designer.cs delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/layout/activity_main.axml delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-mdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xhdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/values/Strings.xml delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/values/colors.xml delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/values/ic_launcher_background.xml delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Resources/values/styles.xml delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Assets/AboutAssets.txt delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/AboutResources.txt delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/Resource.designer.cs delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/layout/activity_main.axml delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-mdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xhdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/values/Strings.xml delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/values/colors.xml delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/values/ic_launcher_background.xml delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Resources/values/styles.xml delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Assets/AboutAssets.txt delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/AboutResources.txt delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/Resource.designer.cs delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/layout/activity_main.axml delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-mdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xhdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/values/Strings.xml delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/values/colors.xml delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/values/ic_launcher_background.xml delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Resources/values/styles.xml delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Assets/AboutAssets.txt delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/AboutResources.txt delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/Resource.designer.cs delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/layout/activity_main.axml delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-mdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xhdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/Strings.xml delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/colors.xml delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/ic_launcher_background.xml delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/styles.xml diff --git a/osu.Android.props b/osu.Android.props new file mode 100644 index 0000000000..4c89408203 --- /dev/null +++ b/osu.Android.props @@ -0,0 +1,60 @@ + + + True + portable + False + bin\Debug\ + DEBUG;TRACE + prompt + 4 + True + None + False + false + false + false + CJK;Mideast;Rare;West;Other + + false + + + True + pdbonly + True + bin\Release\ + TRACE + prompt + 4 + true + False + SdkOnly + True + CJK;Mideast;Rare;West;Other + + + + + + + + + + 0.0.7879 + + + 0.0.7879 + + + 0.22.0 + + + 1.1.0 + + + 1.0.0-dev000094 + + + 1.0.0-dev002278 + + + \ No newline at end of file diff --git a/osu.Android/Assets/AboutAssets.txt b/osu.Android/Assets/AboutAssets.txt deleted file mode 100644 index b0633374bd..0000000000 --- a/osu.Android/Assets/AboutAssets.txt +++ /dev/null @@ -1,19 +0,0 @@ -Any raw assets you want to be deployed with your application can be placed in -this directory (and child directories) and given a Build Action of "AndroidAsset". - -These files will be deployed with you package and will be accessible using Android's -AssetManager, like this: - -public class ReadAsset : Activity -{ - protected override void OnCreate (Bundle bundle) - { - base.OnCreate (bundle); - - InputStream input = Assets.Open ("my_asset.txt"); - } -} - -Additionally, some Android functions will automatically load asset files: - -Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); \ No newline at end of file diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index daff6da961..646ed71d44 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -24,43 +24,7 @@ Assets Xamarin.Android.Net.AndroidClientHandler - - True - portable - False - bin\Debug\ - DEBUG;TRACE - prompt - 4 - True - None - False - false - false - false - CJK;Mideast;Rare;West;Other - - false - - - True - pdbonly - True - bin\Release\ - TRACE - prompt - 4 - true - False - SdkOnly - True - - - - - - - + @@ -83,7 +47,6 @@ PreserveNewest - @@ -106,27 +69,6 @@ - - - 0.0.7879 - - - 0.0.7879 - - - 0.22.0 - - - 1.1.0 - - - 1.0.0-dev000094 - - - 1.0.0-dev002278 - - - {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} @@ -157,11 +99,4 @@ - \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Assets/AboutAssets.txt b/osu.Game.Rulesets.Catch.Tests.Android/Assets/AboutAssets.txt deleted file mode 100644 index b0633374bd..0000000000 --- a/osu.Game.Rulesets.Catch.Tests.Android/Assets/AboutAssets.txt +++ /dev/null @@ -1,19 +0,0 @@ -Any raw assets you want to be deployed with your application can be placed in -this directory (and child directories) and given a Build Action of "AndroidAsset". - -These files will be deployed with you package and will be accessible using Android's -AssetManager, like this: - -public class ReadAsset : Activity -{ - protected override void OnCreate (Bundle bundle) - { - base.OnCreate (bundle); - - InputStream input = Assets.Open ("my_asset.txt"); - } -} - -Additionally, some Android functions will automatically load asset files: - -Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs index 34f10dd16b..4b13b86ca2 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs @@ -2,21 +2,16 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using Android.App; -using Android.OS; -using Android.Support.V7.App; -using Android.Runtime; -using Android.Widget; +using Android.Content.PM; +using osu.Framework.Android; +using osu.Game.Tests; namespace osu.Game.Rulesets.Catch.Tests.Android { - [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] - public class MainActivity : AppCompatActivity + [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] + public class MainActivity : AndroidGameActivity { - protected override void OnCreate(Bundle savedInstanceState) - { - base.OnCreate(savedInstanceState); - // Set our view from the "main" layout resource - SetContentView(Resource.Layout.activity_main); - } + protected override Framework.Game CreateGame() + => new OsuTestBrowser(); } } diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/AboutResources.txt b/osu.Game.Rulesets.Catch.Tests.Android/Resources/AboutResources.txt deleted file mode 100644 index c2bca974c4..0000000000 --- a/osu.Game.Rulesets.Catch.Tests.Android/Resources/AboutResources.txt +++ /dev/null @@ -1,44 +0,0 @@ -Images, layout descriptions, binary blobs and string dictionaries can be included -in your application as resource files. Various Android APIs are designed to -operate on the resource IDs instead of dealing with images, strings or binary blobs -directly. - -For example, a sample Android app that contains a user interface layout (main.axml), -an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) -would keep its resources in the "Resources" directory of the application: - -Resources/ - drawable/ - icon.png - - layout/ - main.axml - - values/ - strings.xml - -In order to get the build system to recognize Android resources, set the build action to -"AndroidResource". The native Android APIs do not operate directly with filenames, but -instead operate on resource IDs. When you compile an Android application that uses resources, -the build system will package the resources for distribution and generate a class called "R" -(this is an Android convention) that contains the tokens for each one of the resources -included. For example, for the above Resources layout, this is what the R class would expose: - -public class R { - public class drawable { - public const int icon = 0x123; - } - - public class layout { - public const int main = 0x456; - } - - public class strings { - public const int first_string = 0xabc; - public const int second_string = 0xbcd; - } -} - -You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main -to reference the layout/main.axml file, or R.strings.first_string to reference the first -string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/Resource.designer.cs b/osu.Game.Rulesets.Catch.Tests.Android/Resources/Resource.designer.cs deleted file mode 100644 index a19fe391a8..0000000000 --- a/osu.Game.Rulesets.Catch.Tests.Android/Resources/Resource.designer.cs +++ /dev/null @@ -1,112 +0,0 @@ -#pragma warning disable 1591 -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -[assembly: global::Android.Runtime.ResourceDesignerAttribute("osu.Game.Rulesets.Catch.Tests.Android.Resource", IsApplication=true)] - -namespace osu.Game.Rulesets.Catch.Tests.Android -{ - - - [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] - public partial class Resource - { - - static Resource() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - public static void UpdateIdValues() - { - } - - public partial class Attribute - { - - static Attribute() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Attribute() - { - } - } - - public partial class Id - { - - // aapt resource value: 0x7f050000 - public const int myButton = 2131034112; - - static Id() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Id() - { - } - } - - public partial class Layout - { - - // aapt resource value: 0x7f030000 - public const int Main = 2130903040; - - static Layout() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Layout() - { - } - } - - public partial class Mipmap - { - - // aapt resource value: 0x7f020000 - public const int Icon = 2130837504; - - static Mipmap() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Mipmap() - { - } - } - - public partial class String - { - - // aapt resource value: 0x7f040001 - public const int app_name = 2130968577; - - // aapt resource value: 0x7f040000 - public const int hello = 2130968576; - - static String() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private String() - { - } - } - } -} -#pragma warning restore 1591 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/layout/activity_main.axml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/layout/activity_main.axml deleted file mode 100644 index ff7a60eb50..0000000000 --- a/osu.Game.Rulesets.Catch.Tests.Android/Resources/layout/activity_main.axml +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 036d09bc5f..0000000000 --- a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 036d09bc5f..0000000000 --- a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 2531cb31efc3a0a3de6113ab9c7845dc1d9654e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1634 zcmV-o2A%ndP)B+Z3$1(8#|f~9B42Y^N-3=o2YCq0YUY$Zu=pM;#hG{lHi%n~Vh z1d1vN#EDO19X?u$`cV z!a}AKG@Bb*#1cdYg8af_;jP69b`k%G1n?0=F^8bI^o>wg-vEliK^U}y^!D|^p|ax; zC|pK=f+FHp!RUAhtlpGGUxJb|wm^5! z<1r%$<$TR02wajxKZ4MiR#aAxDLE(##UNyD|ABr4WoGRF*?@e^2|~Hq(gurSSJH*;Q~5lw{J5A_(PCXBWhzZE${qgzv0{dk-F( z1<}>r181tLiEla&f1j&?p2xjbfp2cTt-c1Ox~?9EhK9`cJ9Vatf)loIoQ@#h&}cIGD>Z#QLE}&(bMo@7Ff|7f#Nm^$PJpVcbj+v~K7wfVwF}=) zRQsc+`=A-+C)vrRvaIC-5u>|;3h z*G4-u#RI<_vuSN~vZ6{|I~q5FFk3%de#+*>UFG>&bq6~ zUEMZ~FIOmFO=kA^5rkp-Msw?^63xvdXVZ-rv@{6{iVO}M!}^Je%2BPbi+(L<5<%~h z2v^D+f<|j%7~cJjOzg*!GPQ{%uE{i%YgcZhuZh{yNlQ}RhaU1jd=K+AopVKP+D}&} zZ3y$llqZiln=Z_A$!qzkGbX0D{?l(v5@1|`QyCvCnQ`eKI>|zj_zo%y#fKf85VhQ} zP)y&j4P*nR3q{-o35iV6nx7QDqq<;WDVIt}|N%`!dgv*y3va8eLNj zU9x(?ieweHfQ*yXk8|=ssZ~qJEz^QoKJ|iGa>ge_Vm_8l}S+UvJ{8g4jr+o#aTSFsz1W;PDP zW765JXGU#3JL>SlIl3NRV2{7B2dLO1cIP)a4ZRYL|MBD36O1#oSgAf}APz5@;x=_U-<=y)Py7*}O5(uu7BL_eLe6Ek7pH|G zMq)FrF1EFq&yruS5b=F=w)fVVoPd(oeRyTFym_Uwyn~L=OL(O?cf^2L5R(SmjORx6 z%nmZf^W=3pkvT*>@osUNi>DULH1hL;y`JGQX$onRCr_U0=H~Viodq!<7Q{3rPk~{G gu#IhOV;e2n|1(WJB~7~kivR!s07*qoM6N<$g7lUVaR2}S diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index 7a859c25556af7a2e46e22a2220eaded55628e9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1441 zcma)+`#%#30L6FjMQg%tuA0%p#0??L`*E=rD#U2F4L5n@F+O9Sp;(QwEQy7+?sX?r zCWN(!Hg`+j5k8*H@|yQEtnAi*(D{7M`Tlf1=eKjq)BUsp2nqrK01B=yNUv`!`EH=x zx8$xJQUd^Fuec%|(TT&0V}4orr_==mmCnEuzD+ff8Pg>pJRqsWsD{#?eGPaCu0(sEH_2RG@<6-Nt<8 ztPMUmmAz9Ga$23Y9~p9dqJSgJJ#Jk_r@o13^%d-Xf46i+Lrmz3 zy9(DUDVXj;Zny7nO+yn&W2flEX=C!8&D0zI`G# z8;XmlonoghgRFUY*$+7pPLa}Uy)onw>TT9t(FTV6#BV8&lXWDPRvQW_n~xZ|yLcZjX>m$Eaf1)dwXS`&E^ zkNjO;%;fWywchc=+w4utQ0Vbn%B>b~yy4I#D{?1!P`$P>Wdo+ljCo(tYia04JTc=$$u+IbzDVPFYpm8+AQj+ zGKH zfS{{hN%W)kF+(26oZpkURD5Q_G_z97F6{Jval+TOj-;5y)*Rdo3a$^^k~q5gpTzmp1q@+2X9O z;_VUF>;s~C1~gpFrFoh?{aQ|LlBIYz!z^P~lndX5-ES)p#+9GW*|-WBTzQ*&gKOE` zM##bUaWl`6rZBXw0!~_oUhf+H$tNc@lLZCj0bZT^KSo@C|P?7YR8dP0se1jj z9aA0|7MONf(ZYaLZs$s}r*05fx25-iN6mZe_*Rq%uyz(+^-k;t`!R`?uf~rn#1ZC7 zuv3}UrmMzcBbo4jym@fS5%I+G`GJIC1s$)MQs3Vhld?a2U;w}$@V%dC@%qpO7+3#$ N&GnQ!lI8SQ#{X#Iv!eh2 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index b8d35b3a1cfe5308bb099a5a1429555c41417e36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3552 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 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 8f56909cddfa86f1387074bf43003f36d6e67be1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2413 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 b;}yxl--Ss53i@>Q4YQuNcebmsMJN0NT!aL! diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 9737d79c0492b2c8a811621660eba33e79fab959..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4858 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 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 9133e31b43252d00767a6a3806df9ba68de2d265..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3871 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 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index c3ae5f5ccdecc01a9b17a2a0c2b1bb20602f0151..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8001 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 z 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 F@PB1o0BisN diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Catch.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index ef89bd5215ffcc38c68b119a7495a77a7084543b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10893 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 diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/Strings.xml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/Strings.xml deleted file mode 100644 index f800d6eb45..0000000000 --- a/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/Strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - osu.Game.Rulesets.Catch.Tests.Android - Settings - diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/colors.xml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/colors.xml deleted file mode 100644 index 17bb9a9dd1..0000000000 --- a/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #2c3e50 - #1B3147 - #3498db - diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/ic_launcher_background.xml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/ic_launcher_background.xml deleted file mode 100644 index 6ec24e6413..0000000000 --- a/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/ic_launcher_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #2C3E50 - \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/styles.xml b/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/styles.xml deleted file mode 100644 index 5885930df6..0000000000 --- a/osu.Game.Rulesets.Catch.Tests.Android/Resources/values/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj index d1e62c46a1..82c171cb46 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj +++ b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj @@ -24,85 +24,35 @@ Assets Xamarin.Android.Net.AndroidClientHandler - - True - portable - False - bin\Debug\ - DEBUG;TRACE - prompt - 4 - True - None - False - - - True - pdbonly - True - bin\Release\ - TRACE - prompt - 4 - true - False - SdkOnly - True - - - - - - - + - osu.licenseheader - - - - Designer - - - - - - - - - - - - - - - - - - - - - - + + %(RecursiveDir)%(Filename)%(Extension) + - + + {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} + osu.Game.Resources + + + {58f6c80c-1253-4a0e-a465-b8c85ebeadf3} + osu.Game.Rulesets.Catch + + + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} + osu.Game + - \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Assets/AboutAssets.txt b/osu.Game.Rulesets.Mania.Tests.Android/Assets/AboutAssets.txt deleted file mode 100644 index b0633374bd..0000000000 --- a/osu.Game.Rulesets.Mania.Tests.Android/Assets/AboutAssets.txt +++ /dev/null @@ -1,19 +0,0 @@ -Any raw assets you want to be deployed with your application can be placed in -this directory (and child directories) and given a Build Action of "AndroidAsset". - -These files will be deployed with you package and will be accessible using Android's -AssetManager, like this: - -public class ReadAsset : Activity -{ - protected override void OnCreate (Bundle bundle) - { - base.OnCreate (bundle); - - InputStream input = Assets.Open ("my_asset.txt"); - } -} - -Additionally, some Android functions will automatically load asset files: - -Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs index 09fc7ce770..3c0de47654 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs @@ -1,19 +1,17 @@ -using Android.App; -using Android.OS; -using Android.Support.V7.App; -using Android.Runtime; -using Android.Widget; +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using Android.App; +using Android.Content.PM; +using osu.Framework.Android; +using osu.Game.Tests; namespace osu.Game.Rulesets.Mania.Tests.Android { - [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] - public class MainActivity : AppCompatActivity + [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] + public class MainActivity : AndroidGameActivity { - protected override void OnCreate(Bundle savedInstanceState) - { - base.OnCreate(savedInstanceState); - // Set our view from the "main" layout resource - SetContentView(Resource.Layout.activity_main); - } + protected override Framework.Game CreateGame() + => new OsuTestBrowser(); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/AboutResources.txt b/osu.Game.Rulesets.Mania.Tests.Android/Resources/AboutResources.txt deleted file mode 100644 index c2bca974c4..0000000000 --- a/osu.Game.Rulesets.Mania.Tests.Android/Resources/AboutResources.txt +++ /dev/null @@ -1,44 +0,0 @@ -Images, layout descriptions, binary blobs and string dictionaries can be included -in your application as resource files. Various Android APIs are designed to -operate on the resource IDs instead of dealing with images, strings or binary blobs -directly. - -For example, a sample Android app that contains a user interface layout (main.axml), -an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) -would keep its resources in the "Resources" directory of the application: - -Resources/ - drawable/ - icon.png - - layout/ - main.axml - - values/ - strings.xml - -In order to get the build system to recognize Android resources, set the build action to -"AndroidResource". The native Android APIs do not operate directly with filenames, but -instead operate on resource IDs. When you compile an Android application that uses resources, -the build system will package the resources for distribution and generate a class called "R" -(this is an Android convention) that contains the tokens for each one of the resources -included. For example, for the above Resources layout, this is what the R class would expose: - -public class R { - public class drawable { - public const int icon = 0x123; - } - - public class layout { - public const int main = 0x456; - } - - public class strings { - public const int first_string = 0xabc; - public const int second_string = 0xbcd; - } -} - -You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main -to reference the layout/main.axml file, or R.strings.first_string to reference the first -string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/Resource.designer.cs b/osu.Game.Rulesets.Mania.Tests.Android/Resources/Resource.designer.cs deleted file mode 100644 index c27ae8a832..0000000000 --- a/osu.Game.Rulesets.Mania.Tests.Android/Resources/Resource.designer.cs +++ /dev/null @@ -1,112 +0,0 @@ -#pragma warning disable 1591 -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -[assembly: global::Android.Runtime.ResourceDesignerAttribute("osu.Game.Rulesets.Mania.Tests.Android.Resource", IsApplication=true)] - -namespace osu.Game.Rulesets.Mania.Tests.Android -{ - - - [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] - public partial class Resource - { - - static Resource() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - public static void UpdateIdValues() - { - } - - public partial class Attribute - { - - static Attribute() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Attribute() - { - } - } - - public partial class Id - { - - // aapt resource value: 0x7f050000 - public const int myButton = 2131034112; - - static Id() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Id() - { - } - } - - public partial class Layout - { - - // aapt resource value: 0x7f030000 - public const int Main = 2130903040; - - static Layout() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Layout() - { - } - } - - public partial class Mipmap - { - - // aapt resource value: 0x7f020000 - public const int Icon = 2130837504; - - static Mipmap() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Mipmap() - { - } - } - - public partial class String - { - - // aapt resource value: 0x7f040001 - public const int app_name = 2130968577; - - // aapt resource value: 0x7f040000 - public const int hello = 2130968576; - - static String() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private String() - { - } - } - } -} -#pragma warning restore 1591 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/layout/activity_main.axml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/layout/activity_main.axml deleted file mode 100644 index ff7a60eb50..0000000000 --- a/osu.Game.Rulesets.Mania.Tests.Android/Resources/layout/activity_main.axml +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 036d09bc5f..0000000000 --- a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 036d09bc5f..0000000000 --- a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 2531cb31efc3a0a3de6113ab9c7845dc1d9654e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1634 zcmV-o2A%ndP)B+Z3$1(8#|f~9B42Y^N-3=o2YCq0YUY$Zu=pM;#hG{lHi%n~Vh z1d1vN#EDO19X?u$`cV z!a}AKG@Bb*#1cdYg8af_;jP69b`k%G1n?0=F^8bI^o>wg-vEliK^U}y^!D|^p|ax; zC|pK=f+FHp!RUAhtlpGGUxJb|wm^5! z<1r%$<$TR02wajxKZ4MiR#aAxDLE(##UNyD|ABr4WoGRF*?@e^2|~Hq(gurSSJH*;Q~5lw{J5A_(PCXBWhzZE${qgzv0{dk-F( z1<}>r181tLiEla&f1j&?p2xjbfp2cTt-c1Ox~?9EhK9`cJ9Vatf)loIoQ@#h&}cIGD>Z#QLE}&(bMo@7Ff|7f#Nm^$PJpVcbj+v~K7wfVwF}=) zRQsc+`=A-+C)vrRvaIC-5u>|;3h z*G4-u#RI<_vuSN~vZ6{|I~q5FFk3%de#+*>UFG>&bq6~ zUEMZ~FIOmFO=kA^5rkp-Msw?^63xvdXVZ-rv@{6{iVO}M!}^Je%2BPbi+(L<5<%~h z2v^D+f<|j%7~cJjOzg*!GPQ{%uE{i%YgcZhuZh{yNlQ}RhaU1jd=K+AopVKP+D}&} zZ3y$llqZiln=Z_A$!qzkGbX0D{?l(v5@1|`QyCvCnQ`eKI>|zj_zo%y#fKf85VhQ} zP)y&j4P*nR3q{-o35iV6nx7QDqq<;WDVIt}|N%`!dgv*y3va8eLNj zU9x(?ieweHfQ*yXk8|=ssZ~qJEz^QoKJ|iGa>ge_Vm_8l}S+UvJ{8g4jr+o#aTSFsz1W;PDP zW765JXGU#3JL>SlIl3NRV2{7B2dLO1cIP)a4ZRYL|MBD36O1#oSgAf}APz5@;x=_U-<=y)Py7*}O5(uu7BL_eLe6Ek7pH|G zMq)FrF1EFq&yruS5b=F=w)fVVoPd(oeRyTFym_Uwyn~L=OL(O?cf^2L5R(SmjORx6 z%nmZf^W=3pkvT*>@osUNi>DULH1hL;y`JGQX$onRCr_U0=H~Viodq!<7Q{3rPk~{G gu#IhOV;e2n|1(WJB~7~kivR!s07*qoM6N<$g7lUVaR2}S diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index 7a859c25556af7a2e46e22a2220eaded55628e9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1441 zcma)+`#%#30L6FjMQg%tuA0%p#0??L`*E=rD#U2F4L5n@F+O9Sp;(QwEQy7+?sX?r zCWN(!Hg`+j5k8*H@|yQEtnAi*(D{7M`Tlf1=eKjq)BUsp2nqrK01B=yNUv`!`EH=x zx8$xJQUd^Fuec%|(TT&0V}4orr_==mmCnEuzD+ff8Pg>pJRqsWsD{#?eGPaCu0(sEH_2RG@<6-Nt<8 ztPMUmmAz9Ga$23Y9~p9dqJSgJJ#Jk_r@o13^%d-Xf46i+Lrmz3 zy9(DUDVXj;Zny7nO+yn&W2flEX=C!8&D0zI`G# z8;XmlonoghgRFUY*$+7pPLa}Uy)onw>TT9t(FTV6#BV8&lXWDPRvQW_n~xZ|yLcZjX>m$Eaf1)dwXS`&E^ zkNjO;%;fWywchc=+w4utQ0Vbn%B>b~yy4I#D{?1!P`$P>Wdo+ljCo(tYia04JTc=$$u+IbzDVPFYpm8+AQj+ zGKH zfS{{hN%W)kF+(26oZpkURD5Q_G_z97F6{Jval+TOj-;5y)*Rdo3a$^^k~q5gpTzmp1q@+2X9O z;_VUF>;s~C1~gpFrFoh?{aQ|LlBIYz!z^P~lndX5-ES)p#+9GW*|-WBTzQ*&gKOE` zM##bUaWl`6rZBXw0!~_oUhf+H$tNc@lLZCj0bZT^KSo@C|P?7YR8dP0se1jj z9aA0|7MONf(ZYaLZs$s}r*05fx25-iN6mZe_*Rq%uyz(+^-k;t`!R`?uf~rn#1ZC7 zuv3}UrmMzcBbo4jym@fS5%I+G`GJIC1s$)MQs3Vhld?a2U;w}$@V%dC@%qpO7+3#$ N&GnQ!lI8SQ#{X#Iv!eh2 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index b8d35b3a1cfe5308bb099a5a1429555c41417e36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3552 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 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 8f56909cddfa86f1387074bf43003f36d6e67be1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2413 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 b;}yxl--Ss53i@>Q4YQuNcebmsMJN0NT!aL! diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 9737d79c0492b2c8a811621660eba33e79fab959..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4858 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 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 9133e31b43252d00767a6a3806df9ba68de2d265..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3871 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 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index c3ae5f5ccdecc01a9b17a2a0c2b1bb20602f0151..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8001 zcmV-HAHLv;P)_otvA^2tyUR8VoCfH?7Uf~Y8h zGGvL!9~U1e2+EQ@WE5!2`JeaRb4v*AP1@XhlD4_e^FD<(x#OJQec#_Z&U@V4T!-s$ z9j?Q5xDMCRfsbx(Zj;?X1`i(Golm&WvEOkWT@EAwg5u(04-gg*b^)Q=wdZqzt5X5S z3@E&xRqAU4(t6iMrj`y!NG~3kqBiu;%rFkf27!OW@8ECn8ThO4HTO;#7xy{;~-`#PSee#+yl`$7 zsLK|B`URc=p2hMdam~0$z)>3q=>?G-oqR?n&P@dVyd_S<+u&%Xj+V7fH_Q{po6c#f1Tbw|%*|St=SEuXXwPQvs;F+N*+6v& zkIGS=8;n&;W7y>ag7A-w!kVPC!v1S4JS!J)TIEOFIQ3rxW7krsqtmA#u9&R4Ay`gb z(K=n%T(#4z;juGa*V5Q_dcLDB>_6S5b%fDI*u>4?G*GAIMVyzVRuA^V55I_W&0So_ z?m#5#@*8Uw%Vd?_ozm6kh@LvXJd~7GxJ;G^CQWUu{Z64R4)0XtntK~kATU^H+D^c8 z$u;=`ixI{YgUC>`Lsn3k+$l5>_W&w=jT%4PK^J%^fyih&sMJ+tbZ8JYn=PYBg&*pu z3p}(zRC`R3SDx7+%^8RK)Pkyn^uoFWF7P)0TEDbH=%m>4xeM{1Dq*;BhR7 zR0aLE%d(6S9mK_F16jmX-{=C5qlF!NRYBGF5=p+Vvj-cwP3%~$8xBY7p`fb-9)Y#aFnwpwAl)ydj$3Pl0ek#%w z51>+@mReAKLYiq%I18yZ<2|M|G!vun*52{p6m;a+@eT(ZOF41!6dE_>89JuSh)r33 z`35{^-5t({xYA0jBB#*iJ*5L~K|BBWv%`ajlRbO)V^e%54N~2p($^q)UfEL?rNoXQ z%_@UQN1OM6x_^G|JDmnRAPo%-43En$9Ylo>r502nnWnhdQ6S>fo;$vw?`YTbTtDU^ zbm+*jP6Z&4bLY>ak$3%@nkiH2%D3P-^rUXeu9&X6`)Hf4tkQw#tCj0IBx$xqR(|^( z(qlKDjw$Ph6ghn+P}V|h!z8t#EFRy;3A1h&bcpk~Dd?XwXFDZ$K;YRPe(YIFh5Fc( z{rP(^XJ)J^JN;zjs>jaI){f-zdLwI2BW-GSncYwsaxP zspxKfGjY!Em&bMRq8Bi%L(`s{$B@m=4xmey8qf>#7ox0^fm8@}O0TM>#54m9Ld~c+ z_cWtvF>UQrIrI*+W9RNp4<1eq9y)@mhL53^=1}C8eaXg#L^5NX_EGDrOU%})BU;?& zgC)y4Epcv5KKp7F()J!qgHT^i$*)AxOhZ2rwGgL$>OP~rUcLWK_o5T0PIoErfE+!3 z0*$(V5)A+~GFm97Y=tOV$b$P&4I1johoTj$*LOMaaPs4?+mVJE7pg!BYJG{|T8Q(! z)W+Jmw6)KJlb=Cn&zGwnS);jE(y!@=IfB$9)QGN1`8o z{I$!1hZ6{0^c^yqN?b^(>w8L~%9gQlApt-{RGGWVQ2PLF?K6AcLUi%sr7jO3kOl89 z65EV1bDLUFjij35$uQ?yt=3bBoEL}(cHK$e9y&b<%dZ>VDf3>htLBsDDFFu*Z zK*D7DXFTUVX7g_!_fhC73^d8Jrepw`_s&Ny;8+x&ee~IKW^BYK)0Ie~&aZ&Ew~I^@ z71kY-t7mAMuUqeXlqvhPC!e%y&tGWg?rUY=fkWa(kum9oR76YH27!#bJs=wU&|~70 zX?;JGoK^e^%)LEkj8R_^YPCN`<~Ca7Ij`?^*lpin*CakV<3+{<0`atz>fvKW&E~J( zuo?Bcer$`^2APEK?fm)rcAx*-jXxk`%?MG+G-Jkc%YF-#NJ86f#yIn()HO$*#g8~+ zd1&e^yWRFDpP$EDs6Jxs!|3o);rZ3kV<*tf_e|t{MsUe5UcA`uYh1i^2|YG*j@Vj= zi3!E2^|kFbW8_O7Se;FyWxk4PZxkfo_2=FL%xVX|V*EL8yeGI8dh`8HnR=zxu3K^4 z?Tl%)_d2`(+RtcMvCWuNQ}`lapgjQM)RvdpSi6pf_mx@PA3gQr0)c{Wjp+6NF6Irs zL820t0ST#n`V1b$3tBcTaZ!+L{k*q75;0p3-dHV?<@DZ+G2q({GsfnWwM#`kaZCYc%YN);0tcIqxe~S22_Zd4^oi;xE1y)TF?#>ouYjo{^wp6J+R<)CHpf3u?96tF8RUGgV(bi-!3c zdDjGVQiNZ-uoCj zdR)5-_0QpRkGlU+{2ctxXOD)n>egdY{@AQnuoE&sl;o-+x6i@Q*jNe6gKVf1BC4vp zOk0}Gwr3HKK=&SaEBblcZ=$CG{@AmZ_bmmE^2rw~+swfr;K}Fd0YBNiRs3oK2wU)Z zfOe%dbma{aSyqwFQEBoa52dc}AhRtbMKNEmzV!jaA!yXp%z6DiUbnZ;;MQK@8%U zubLa~M8}Swq?pY7GXf1rV4q zDDOy2*FVX`1Z@Ej`H(mM;!9!?XmG7R`QjVuMe^@0{(|={Egv!(ZToGPb?t*S6=*EJ zXME$mPXviEwMEu#`agjy7uhPsq)g*mj8kQsE6;EsU+lsy5eqy%VPk*szNA#H3k8P;B3WV8iMG zAL^kt)NB&Ngu&|4_1|xGSWV69_22V)EKm*b{nlSvJqKtgcm}@jL*0&}mLNe1FtolA zVy-dJ4}}J*4Yk|F0MNAO=Gs*gBLs-XjGM}PkM}t8}FKMRr@^9KDXTW zAKvc(e>&#`OOPOJ@$RCfcK2Ou29U1riIBMDG`5$JbpUzAD6}c~i)VxkB0?pg*yW^c zk)411#duwO3EsJHf7opHKKS%2-U)%AAx*d4mMA&&6A&VpsMM984UbRJ+6*8`iZ&f< zpn4$zG;YdFr|PT$T4??|A2W4Gt@dFYcq=-5^f=?T4;}p=Z>`VMFD`Jpwfm3Fd_|bD zj$VB)^h`*}2W;>Hhy)S66Vyl(v3 zes{u#pHRRiR5~LjS*f=g3*rEjpvuYW3IJl_CfMWRyKh*F1;uWBpMls?ef@<_3m|1) z`6ZhGMAVbFM46p|zj$6q08M%3Wv6Uhz*mX^=56VUHB55{i0`!OUG^J+R<7OTbkAq4 zO0o?csJ>@{3{03eRx_Sf0Td<6QsFQEBcvBL`d^dL1p(@Tg%a?ppcf&ZX}a<538(>U zsk7(Kq4Ai*wN|zP0v+?~FF2PLx^LnPdjZtMm9~b(DRONFP=quUYN3w`2_R^cuvWp1r77NM)G6)s7O_B`3T0Al^c^ zUw2%amEW;*530U?EU!C1_pJ{d{(PIZ{LIVQ+M3FcX-jrtOhglGbhnlZgRTsrDt*mH zF#vSa-H$l*ErsHJSm4J8f*0q%+hSc1@S(TfU&5<}Du&)J=z6oZ%JGw@(3tU$37Slm zW)*M6n1~?QaJN!Wp9micNiC@QM2vC{i10e9VJ4W*d2fGcwHxdq9)LsP7GGf+WcsJi zp6@VI4LQ6#!HVqJ-ib*W1}NtUCD`BxP)tlr5BxJ&*{kwpvFd@~E#3XsKI(%DM3`?$ zFjN@YvVQB!Z@y)AN9614=!llY!0q_fr?scy6fEsYNY_K#yI_J1-g1s^5{U$sa0I~~ z3SyPCLVN{Q63~20;aWh9`OFWj-#TQ2c|CLHEEAUCU2lfnej!()S`!G7%&`(NZ(m7k z6^c{kJ`I>?3xEQpS%zU^uE>D5lxFyU>(ASHOE{pyur0yBH5)hct_m%{f1_DA2V>cH z$Zf(G)%U7Ev9gRYfC-xbB$LU2X$QolXbOZ*s9MS$k zpR6s}?;Q{TF(5y(x0uz{solwkBUAO&E5u&f3|;8O~Zm}gs8jmZc&?sLfy}ZJH^Pb-rBLkukEGEX2zm!X9k1Z~ZXG;?s)mi>UrdO>Yw!B41@A8A?MzlV><+YT z$1cI255`Q49zh&|R_ZEHbaKW$fCYjHcN@ENFhn{iB1V>lPj;L}k08i137M@2jRt#e z@h#!08F3dndCGng58cW5R)qpkr_P)sIDlrp{Dvr7AaFS_Sx)a$A<=P0zyb*(cC)p; z3y`HiEU~EtRcpi~(&pK3AcH~;F1vnfIByu?lP`r?9Si4JzG^+Msf6o6j!Lkw#4p=X zaotU#%mtIeU?b4b;x3+G!PBh`ZSJ~oBJ0)h2fLM#V{x|~T*y<~OO zMN4bH?5VNl%kYC1dT`Ryf~?4eY&&#&6`K286+q0dLXs5iTyUmBLqh{?CD6@0C^9k< zJhAYYl>3$m>pnTQ5Y|;+t{BGCaai!ltmr(bY{MwMUvH_a_CZ+~zKvvYA*2M^>5@Bhzq3R_;9V4J5SzJXynm~-ra z1+>?EU1i4n{h8h{39{^>*SI_h4FCaIT=M10F1KI&wQXhAGX1PY-|mtj&)WB4uJN4r zw8wl|ly@*hDkegrtWXv7yGV1}Z%9<`bAp~ijuKeZC`7Lxn`(cwC6~gY69&LsySaq~ zwb%P+2f}NR?(97eEtgnp$Y&o&QGX>+3sz(6Igj(@UEM_kk_GW0l$9dCBnHN=P}ghmhLG zA~MY&G`>e*V6IYEegJNSMs%8S>w6DE|6TM&rzX^3y1rh$LG-cYmMtf1iVpb(1n7zO z2^Ye3x4L43AT>EQC1(P#cZgup(n7EYg}vE&XU})RuF@2^Pm?0I4~k4mdjjTCZ0%#g zg_sn79F`P$cJa5YDXVRu1tM_kouN&P81m{{A2M}O;)2K2z-*$Dmj6AT!&EYt!D4Wq zRy{I5Kffr58HB`2`zdu5=V|82p#92bp6v)as{FqDPv+TZq%36F#q~iw8R9Gz%k$#X zLQKuHkB?6x{;5n<>z;%#I4uAHxx8=UbWwLYq%GhaOu=q@hRDPj=17rSh9vTg=V0#0 z9C9_!?rszgP7C?4EkAsq1-?p}S@<<{a-ijvL3_HTD^^q4u#SeTT(?P(rck!zyAo8o zwJ>L7?n232Qqexw5NfRXqFE9akT1{ey&vjHXn_dSJ=8yUbgv9nqrd`3vB9H;y}vYu zgFZg~g>1b~j~E)n*&3k^;!IggqUvTvUPTjaKJ?LNUolbYj--viU58Gw&_cLO#45w9 z)_G}5n|j8{#uC$&#IE-epEz4HWsr0W^Y-?Zfm%#Z{T2X3{>u!4xy|m!J z=;P0qcL;%AiZ_gTNc3?b(dNr?%zI*FnJ>T`k+}+M<96O+n=&XsVs0!gF+KkS*sPUi zl$z^r2#fnVf@F$VnrdmflzDwoTuRQTFgIk5dOFf{wPwl!*g6tsDM)%^rePHjHrgO^ ziDjyy0>!I!>+qaplDUZ`bLBA8)shx+zp{?ZCjo3M7L7F1xP^^Wn;J*}%O%vnV`_jG zI5Dl)&#(;&J15NC1e>KRy16;YVa|s_F+r0;l-f5SAU`>)=yw;08~`3>yY7NN@EjOm zF36mOIs@;q#)lxH8BT~=s()~JiA+{ih(L6BLQ5NochXGG(Ac`bGtW^AAry) z6?UnR%hl&|(cveUthm(N)jt0IMKFe5UjAvMmtnY>x7DFFPivaUlf)t*kr#(Sq=Nhm z@S+&G<|$cr@mb>PU*?LwUBGGX8h;taMye@18!1bl1!D$dM_$A@GNwH`BY0X0HbOKs zgw36KEASwsgBlJFi!;Tmd#!`aF}Gx>tC}@4bJYl%8MIEkI&VX8So8p5veIGfNd7T| zjHyRwGF!G(GzJpFmxu=h)Gz=kD@vL+DOppv58Qn-PwjG701^uvHm*aq+(t>6h67Pa zsZ)uUl}^Sgk&IoSBPt4=1wUG$Gcu36~g<6p#jS)g^iQrNL##*8D&T?#xc@giT6C62PtMw;NBF?CSO zBF`?pz(%n-7q*U6K6ZF*!*Lu&;{eZrXN^zI`8>F1bpIB#P81m{-_Fi=+NzDbN$et= zykWqNGQi!3K@5pZ7%oZ8`64;Hh9nrj5m?`E(04)p87N^SnGNfnx4FotD zWDFE!Ov1?+d3RN0&|r>#v;h2b=t;_{D^lE#SWrZD(iW$8p+q! zS0A06_BgDr8GL(MhT&@Us}qG!F2bR05nRG6sHK znd`Jy8+i~_?N17!qFD~$m11VvG+4BOk#WOf<(gNM()B;dv?cWnm>A7ux(ZO-+s}c@ zUJhk`4sy;Wj?Zv_;WQ0^My4&ThkJy34UCiwhkGaS9Ac^%jgv^8HIzKNx0!qH0*?Sd zA{vR|Nce5_WYj&p!H|g#i;f==Bg=RxA+6W?E)yuEDR}T08@#;#3pNuhw;6vgL?{&ioX%xV=lSZOt^QVRTX9$hXam}3pm09 z$%hPX2&r?Cu=yV^m4#M<3Ci{h3hf&aFTW>7p_v<(n!8G>G48^q<1|bxXesb`7+_(u zazzu>Srta(7;2gCLU%6!s3NZq)-WZfr5T1@ajCjha7}#ed;J1K%ZaARvd}gvlDm?S zX9;m>9C|?VB4PVL;+aH~Tu|~AFg0tYW&o0dW%lJSoTj#=tw0jQ^IDY22NdY1oFf%0}#JFNJg9 zb4`bH!nr*>Jo3r4vdFbLO~ZjEncQnMx%VLQEM6|)&;?R=;*oG#DaZ^=kQ;)Pmr97A zz~q@}C`(Xf6Ah6Ilkel>UxKwpMPNvHbwEgX4G8=jeg}Ue0LcS$Y4&|Hu&^422*hrb zj|K`T5 zvEu&kr?~JYsHgmN0NIn2aTn+aRJ9k!PJ8U-hv4^jUYrdmS}_oGTBmMTI8(8 z03a};B0~PpXcIa4tdx8=ft)LroI8SCE0|onhYK_v7fjvBqPuoO{)9hqzzQR# zC4vyzNCF0Pi6noEAfF9014WI zV2uq3g6f^x2G7c=p@RHqN*TgM%4|`s^UtkutYSaPk<{TxQ5pftG4D{HdAqOLZ#1v_ ze9M+5dsmQgQfV0(U&(S!!AFzvis49pCTa?3*#F3|c3c({E49|qiLo*tWAg7N2r?$H zceChvA3_;lB9B|DgITla;p_)_r>v>z1zcg0vl49vG;Ili>b(32*1hN??A7sM@$nr4 z8!M}P<^@Xi%U%oe11bF}T`A`>43CK-Qz^~WSp-#Hv2Q9-9^X94+}vz@Y^)g{BUOYV z_|+d(CAi?WUj6zyz~}lnkBZ=80;M3*LU zHGMlZ?()$(qVAfc|G0}(d&tSfx)|^Mu2H_=kb4o=Ap3@`Lp&B)cL!~H9PI7w*YctI zQdh5sK=8^5AG8P>#9Vyr+q9%EwH3HQk{XQFUw1_hfFE3734S2!^#qIgdS@@Q{Gn}V z&i9cg|N4u1hekL~)kUtMXQYP=0K1b;zvVq4 zRb1r#*7T38ib@M@JD6D*ec@F^uyytIxz!L&dH3FxrvZWb8BV**eALkmeW5?93@}@n z4gNan2F?-Ie_od^USuAI0%QWj1;%?cUgs$RzY?UxLayXoAPU~f29Th25OmAI z06!5@vgYvOQk6;7bal;{!x-3L@ZzNh{0cx{9p0)g1j+z7i}n8i$po2mA$9%`)fE!Czt%i%kp_d^qH20s4XnQst#a^y8a7?M5z z*L>NT7jYu?ICpgEQUYh_OrrtIc)wKx1p6)`I=;61<0)vR1JCOJwvBjC!)Mv`b#ol9Akg)gKB^lewze1bTfSn@{B`u_A zN)PUeMM_x{I^}mc;UI<%**ErSWv7bWZqZOYaL!Vhe~kgeP$S=_d##+rr~Y2Hh1>Lf zY=aYSLIB5kY+Q46%@wn%6eSeDTv`P&y|-w1o@Q>{3O~TqAV%Mfc7n9fmZEe)q(iKx^n9(NLb73Fz+c+s z!>K-8XvAo7Xl~E$nxjkY=8*HY3k8UR*tK@ktoRk(m_t4G*)CvnEHo5Mv^lI*I$~VT zuH0CQ&e0+^wcyj7d5)_2{MUw8@JEb14uhKmP;dz#w@0mHpB@zWPB$AE8802Ak?aBk z1M!fDJDr>(_(|mFqjVXEY-2j@TGY<*rK|h113ZR$)F9b)LOQJZhEwYNf%4CFbZX7r zL16#j)!2N6%HO@+Vja^$%=71~T?~9Gg$KI>#Wwff2WtS32+6IQEv;R6a?Q?f&t~sy z^?UKhaZ#>^yY+4h*)R!0Fyiwv!ursg*ef5>>?IAD*ns7x&BkByqWr2RWnuEC)*Vud z`9a0}20fROX5f7JsQ%t$N;zJM+&`J&In$Q}u+M=I{b7@g!`prSoyZpQ9TV;3(@D1e z%BI66KJyYBWhq#q@AQ!=m9Nvfnq z-SG?FyKF)enqlGZ8yZrUBOey84zNfN!yy;zjn1@HJvxz3-Fp z@Tz6QUll*eYHc^+v(f|F6?U8_{nr~jaIG0W?B=i6B3RcSto*bvBsbTM=A9BU-3Ah8 zNi`l$9?&GMo=FEwRv_xSgyGZtj9#@e-B5nrpw{?~zkgz73X_}cv)*W^Rr8w)YwNHc z*5Nn6f`7FA!KOwX(rWwMR7CG2XjL0w!d?(-NK_z;CDgW!? zm{={qDnSAQe=8Vg-umXT=L(@JFv-`qNgoa*CdglVGRag)CSpU(wYQsW`&k0q_mT*%_hS-?>#U4EO z2MC~jQ3U6aUEVZn`ZAr-q_#O-3f;~=QSZ=x?WSyg+?f9&^TYDzkb6XdslA>n+|$$Y z#wjomIx&A!XAHF_GVmq|e@koN>Yw2r^&$^Gl_#ddWR=6%jFpj99RV`jcPw{gQUrpP z&}y~JthsyUaj=yQDO|`!1pHEh$z()Rxx-4E66v=_sVbSZ*qEz&S3yM0K3<= zl(AIalVLR~ZN4IX$r$zP!ZB`rtk!neSg;~!`TZzT`@!UHZQV6$;7SKpBW2rrUV6x# zmbf#hIQ8SB>u=fyo$!2K@J^E%%R8%^DUW6^Ebq2+fLvKX@){F7?rY$=jVkSNr#m^S zUpAC=E)0=|)VsRj1l+j|KCG0J1K2@28(?-SzJW8yW`-j@8fz?sRj+*;$DojX-q@wYb}{2W8MP`wCr zpMJgOGt1}UL%B`+e1=bS5ru|!T&(Bpqim_)`YyB+;aZ#ewM>398;>NO39z+)EM@9I zzqa%gS5q)4Ws**y4RgHdAlxy?P#N69EqQ~}t7qX#A{`ZoNn=1A+!}QMkw>!0732x3 z`%S`@brK1YzOF-F&+{yjtW_BZrcDAx(tO-GN;yTY1tuOT<*hG12+Xe>ynLs0qchz{ z`%mg>lPr;0bC~$^CnR=xKR;P3OfpfJ$f|c)lUs?S0JW(^)lwEvC4)e}5}SI^v{!1$ zjqz@CVW6_>%7&F`sY3xz9P-J|lBlF}so2Y{lOpC+^`4$YhDLpp3!lSk@7KlW@%84X z*IvEA!*PC8@8D;8o1-I7vgw9B2}E<;Gq@mSZ&q9x(yG-(0CRJ;r zbr$E?ta2}89WD9k`z^Rc!N4GdALcn;R6#TJ15qv>piYcX@`jjXw~iJvrTm)BH$ zb%K;N2--lOR@QBD`&ZF+4es%d!air^&5bM>hfj5->g#UzXEdTl_hyn zIkQLs>{x-PlSZZM!^euTA~#MxCZTd_Kbjkq`Dn%=#g_vd*TXIuYU@v(d_{kZ;gK)u zziBr#l9lQ0LjnAl*orcD2VJ5{3NMwFco~orS-1~*AxKWOzTLAVmkWPoR%xPGNdu_q zz;1sj4r&=@sDnZO$2EB8H~guAjJd#c{W^O({#pLgMS7mAt2DrusXx<^*a&kdXI-_Y z_9j_9_oo7Ni?ojhH{T{3!6L3yVd(f2Q0Zr`E!UF-##p;v7n$b-e;v^A-o+ab? zlVwJ*Qt6gkF!g%V9M;PT-|U= znQZgx^I%KEj2c)s_Obx$c&fXdCv3`UHn5IUlIGXDmDJu$E7UeYpf5^wf`~WfT87s{$hui5G`USZ+r7zlb|e z{ZrEYyI`t?3$8$w!SQh-JJib09-`-O7ZU4W&ZGTrlS_{>=JI+%v?F3Tq4~1)esPKE zOiQEtW@?$T*;OTKv!Sl$WxW~6_9*!_N!^2IYUo+ypU1@6-e{dt%xSFE+(Fb`n{t+) z$HuFNv2x025j(+st&hXUa}gE1f(XrQ=B;Jhk8HVYcyj)MC0D)AaFV7l_3cKkrp89u z(05Bo#PXm6x=Pa_jB9=7rv$M%r5HsdnqMzLuKQArS-14ABcqZOrYyX~mfY?EWt(fm z(L+_F&V`mRF)}iS^LN5w6g}wbzz9&?o&7$8Y%p%*CHR^I$9f1*yUyH}zB4^i`c9)n z^IWRH4CDIwFT)hq3)>yRq6eP@ro(m*m$s4>KJU-QgKcLrPB2?_UE8C%l~~G<7O(TM zW$LTyd`im-CExf(S*NOi-sw_1p>6i4+&79YR+?)afxX5n4mIp$-P0wan9u#)Ul4SvZ5P^5 z*}dWjId8T<(NSMTCXWyZOnb$5cGAW?f`MWbibU$G>fOxR97aMitp0yYMP)?= z1O$K<=BD-n0)n+a_A!yelXun{$^rsE|6^eacZ`@^o{6gUa>5DRGx2`<)%*{W-(fiE zKNZgd&b|Bnp~hRX`A=CwbJ~tFFaEyeo|pUP4EcicV1wv|i;gmvUVb}SdG@R=&h?^h z3PSUksrkt}uuFf~%EQT?&f}||K|(rx9lY30_TJXsozA%7iJ(FQFNgw*A)ZB;o5OXk z2W9E{7_j|*?Y#`4wVAHYryQ%j!apO!ra!3)N5t{n=S%-`Z&9H|1ggSHaeG=c{YVqE z0nrZ>c$u-m#RjYlJ1__6P(^4W9s;ScgAR=zMOIH2>yAx`HB{r5^EgmL@|bsD=u7Gu zgacoB7^h};0J>#HNEt$s)qtqv*4c|ndX;#H76lzv<;Vxk6@#g{Gq4d5%WWY>Gi3f= zIKV2{dnC-DVoc|KC3NFn1|W?&GD3yrhBQpQn1h|7bczqvxu=CR)Jw7gbC+QwvaIEW zC>4WTKfgc&MmiUJlQ7QQ7}Hg!Ap(tTH@Vv9u#mW7!+x8dHoaYZt4=L{l<%ypU!D4= zAS@TennL1&=;?wmIgrc5%GX_FM5SRm$E04c%mXlGjC)%@wcw!V01?0j7n9{7EPdk=@ym z$AP&CIX2?G3azQ~&F_9DKcX+*Yo?D#h zeA!&ib)-h(S91c||CGiw5S6!M8UOe&d_fPoP1qgv7Ba~8Q*sj)a{=i8HuEbZsa{lu zz-=@kWR7|Y?HSQ%0n!>w;F9us#<{QLC86YcoYnBR1owfTyprh81G;RrC}Esl?1HMv zyb`o29Syq=(7zTFAfx&e4fE$uUZg#Gbh>4=KVyZb+cw~u&Y>qu?u{B68uE``QQG9r zmop-I-|3yLz{~j*d`H3pl^lfgr7-YvghZHlBpOn-tQ_R`!kd!$ea{=!*s5=R#cH z-w1Iv^D>#dtn;Vvc&R1_74NQLpe(P71gUjM=#4Y)q2ZEHM?~zI{U!rX9NTM&AWKD& zRIFnXMQePHcG5+0TeG)#;q}O}4)o5u8|2r*dn4MHKJkvE;lc?nL07p4^g0(ti$qOd z7G<#R+0qe+BXeJs7NmU%6*9-tL`>&b9%g`^JST1Uz_w8UNEKy?+`vpqU{b|pHs`^^ zOy72g#If!7q-y?+iQ`q2vKU=#xG*JW@36RQJ+$r7Kl0zN1}?qeOpvO-=|iob7Q=kZ z&;#HH%r!#0!Y3I8jiWidEi*IP7UD6bbASGI7)sp(zbVzYY8zrxL3tuVe`^QbFHLY! zu#-^Bj5!U65BGn8)`lVC>Y&Zf8rlFtB_ z)|g__N9i>0a%zB+Q*h3cNW}I$Tg3Lki5X{!^g@UdZ2)-J_jP}rAEQ0G?Yy7+Nv*sq z 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 F@PB1o0BisN diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Mania.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index ef89bd5215ffcc38c68b119a7495a77a7084543b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10893 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 diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/Strings.xml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/Strings.xml deleted file mode 100644 index 6ab86b7262..0000000000 --- a/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/Strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - osu.Game.Rulesets.Mania.Tests.Android - Settings - diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/colors.xml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/colors.xml deleted file mode 100644 index 17bb9a9dd1..0000000000 --- a/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #2c3e50 - #1B3147 - #3498db - diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/ic_launcher_background.xml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/ic_launcher_background.xml deleted file mode 100644 index 6ec24e6413..0000000000 --- a/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/ic_launcher_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #2C3E50 - \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/styles.xml b/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/styles.xml deleted file mode 100644 index 5885930df6..0000000000 --- a/osu.Game.Rulesets.Mania.Tests.Android/Resources/values/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj index 5fbee695b4..a761f2569a 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj +++ b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj @@ -24,82 +24,35 @@ Assets Xamarin.Android.Net.AndroidClientHandler - - True - portable - False - bin\Debug\ - DEBUG;TRACE - prompt - 4 - True - None - False - - - True - pdbonly - True - bin\Release\ - TRACE - prompt - 4 - true - False - SdkOnly - True - - - - - - - + - - + + osu.licenseheader + - - - Designer - - - - - - - - - - - - - - - - - - - - - - + + %(RecursiveDir)%(Filename)%(Extension) + - + + {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} + osu.Game.Resources + + + {48f4582b-7687-4621-9cbe-5c24197cb536} + osu.Game.Rulesets.Mania + + + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} + osu.Game + - \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Assets/AboutAssets.txt b/osu.Game.Rulesets.Osu.Tests.Android/Assets/AboutAssets.txt deleted file mode 100644 index b0633374bd..0000000000 --- a/osu.Game.Rulesets.Osu.Tests.Android/Assets/AboutAssets.txt +++ /dev/null @@ -1,19 +0,0 @@ -Any raw assets you want to be deployed with your application can be placed in -this directory (and child directories) and given a Build Action of "AndroidAsset". - -These files will be deployed with you package and will be accessible using Android's -AssetManager, like this: - -public class ReadAsset : Activity -{ - protected override void OnCreate (Bundle bundle) - { - base.OnCreate (bundle); - - InputStream input = Assets.Open ("my_asset.txt"); - } -} - -Additionally, some Android functions will automatically load asset files: - -Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs index 77a75f0d67..622eadef70 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs @@ -1,19 +1,17 @@ -using Android.App; -using Android.OS; -using Android.Support.V7.App; -using Android.Runtime; -using Android.Widget; +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using Android.App; +using Android.Content.PM; +using osu.Framework.Android; +using osu.Game.Tests; namespace osu.Game.Rulesets.Osu.Tests.Android { - [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] - public class MainActivity : AppCompatActivity + [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] + public class MainActivity : AndroidGameActivity { - protected override void OnCreate(Bundle savedInstanceState) - { - base.OnCreate(savedInstanceState); - // Set our view from the "main" layout resource - SetContentView(Resource.Layout.activity_main); - } + protected override Framework.Game CreateGame() + => new OsuTestBrowser(); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/AboutResources.txt b/osu.Game.Rulesets.Osu.Tests.Android/Resources/AboutResources.txt deleted file mode 100644 index c2bca974c4..0000000000 --- a/osu.Game.Rulesets.Osu.Tests.Android/Resources/AboutResources.txt +++ /dev/null @@ -1,44 +0,0 @@ -Images, layout descriptions, binary blobs and string dictionaries can be included -in your application as resource files. Various Android APIs are designed to -operate on the resource IDs instead of dealing with images, strings or binary blobs -directly. - -For example, a sample Android app that contains a user interface layout (main.axml), -an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) -would keep its resources in the "Resources" directory of the application: - -Resources/ - drawable/ - icon.png - - layout/ - main.axml - - values/ - strings.xml - -In order to get the build system to recognize Android resources, set the build action to -"AndroidResource". The native Android APIs do not operate directly with filenames, but -instead operate on resource IDs. When you compile an Android application that uses resources, -the build system will package the resources for distribution and generate a class called "R" -(this is an Android convention) that contains the tokens for each one of the resources -included. For example, for the above Resources layout, this is what the R class would expose: - -public class R { - public class drawable { - public const int icon = 0x123; - } - - public class layout { - public const int main = 0x456; - } - - public class strings { - public const int first_string = 0xabc; - public const int second_string = 0xbcd; - } -} - -You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main -to reference the layout/main.axml file, or R.strings.first_string to reference the first -string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/Resource.designer.cs b/osu.Game.Rulesets.Osu.Tests.Android/Resources/Resource.designer.cs deleted file mode 100644 index f229c3f960..0000000000 --- a/osu.Game.Rulesets.Osu.Tests.Android/Resources/Resource.designer.cs +++ /dev/null @@ -1,112 +0,0 @@ -#pragma warning disable 1591 -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -[assembly: global::Android.Runtime.ResourceDesignerAttribute("osu.Game.Rulesets.Osu.Tests.Android.Resource", IsApplication=true)] - -namespace osu.Game.Rulesets.Osu.Tests.Android -{ - - - [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] - public partial class Resource - { - - static Resource() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - public static void UpdateIdValues() - { - } - - public partial class Attribute - { - - static Attribute() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Attribute() - { - } - } - - public partial class Id - { - - // aapt resource value: 0x7f050000 - public const int myButton = 2131034112; - - static Id() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Id() - { - } - } - - public partial class Layout - { - - // aapt resource value: 0x7f030000 - public const int Main = 2130903040; - - static Layout() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Layout() - { - } - } - - public partial class Mipmap - { - - // aapt resource value: 0x7f020000 - public const int Icon = 2130837504; - - static Mipmap() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Mipmap() - { - } - } - - public partial class String - { - - // aapt resource value: 0x7f040001 - public const int app_name = 2130968577; - - // aapt resource value: 0x7f040000 - public const int hello = 2130968576; - - static String() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private String() - { - } - } - } -} -#pragma warning restore 1591 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/layout/activity_main.axml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/layout/activity_main.axml deleted file mode 100644 index ff7a60eb50..0000000000 --- a/osu.Game.Rulesets.Osu.Tests.Android/Resources/layout/activity_main.axml +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 036d09bc5f..0000000000 --- a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 036d09bc5f..0000000000 --- a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 2531cb31efc3a0a3de6113ab9c7845dc1d9654e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1634 zcmV-o2A%ndP)B+Z3$1(8#|f~9B42Y^N-3=o2YCq0YUY$Zu=pM;#hG{lHi%n~Vh z1d1vN#EDO19X?u$`cV z!a}AKG@Bb*#1cdYg8af_;jP69b`k%G1n?0=F^8bI^o>wg-vEliK^U}y^!D|^p|ax; zC|pK=f+FHp!RUAhtlpGGUxJb|wm^5! z<1r%$<$TR02wajxKZ4MiR#aAxDLE(##UNyD|ABr4WoGRF*?@e^2|~Hq(gurSSJH*;Q~5lw{J5A_(PCXBWhzZE${qgzv0{dk-F( z1<}>r181tLiEla&f1j&?p2xjbfp2cTt-c1Ox~?9EhK9`cJ9Vatf)loIoQ@#h&}cIGD>Z#QLE}&(bMo@7Ff|7f#Nm^$PJpVcbj+v~K7wfVwF}=) zRQsc+`=A-+C)vrRvaIC-5u>|;3h z*G4-u#RI<_vuSN~vZ6{|I~q5FFk3%de#+*>UFG>&bq6~ zUEMZ~FIOmFO=kA^5rkp-Msw?^63xvdXVZ-rv@{6{iVO}M!}^Je%2BPbi+(L<5<%~h z2v^D+f<|j%7~cJjOzg*!GPQ{%uE{i%YgcZhuZh{yNlQ}RhaU1jd=K+AopVKP+D}&} zZ3y$llqZiln=Z_A$!qzkGbX0D{?l(v5@1|`QyCvCnQ`eKI>|zj_zo%y#fKf85VhQ} zP)y&j4P*nR3q{-o35iV6nx7QDqq<;WDVIt}|N%`!dgv*y3va8eLNj zU9x(?ieweHfQ*yXk8|=ssZ~qJEz^QoKJ|iGa>ge_Vm_8l}S+UvJ{8g4jr+o#aTSFsz1W;PDP zW765JXGU#3JL>SlIl3NRV2{7B2dLO1cIP)a4ZRYL|MBD36O1#oSgAf}APz5@;x=_U-<=y)Py7*}O5(uu7BL_eLe6Ek7pH|G zMq)FrF1EFq&yruS5b=F=w)fVVoPd(oeRyTFym_Uwyn~L=OL(O?cf^2L5R(SmjORx6 z%nmZf^W=3pkvT*>@osUNi>DULH1hL;y`JGQX$onRCr_U0=H~Viodq!<7Q{3rPk~{G gu#IhOV;e2n|1(WJB~7~kivR!s07*qoM6N<$g7lUVaR2}S diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index 7a859c25556af7a2e46e22a2220eaded55628e9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1441 zcma)+`#%#30L6FjMQg%tuA0%p#0??L`*E=rD#U2F4L5n@F+O9Sp;(QwEQy7+?sX?r zCWN(!Hg`+j5k8*H@|yQEtnAi*(D{7M`Tlf1=eKjq)BUsp2nqrK01B=yNUv`!`EH=x zx8$xJQUd^Fuec%|(TT&0V}4orr_==mmCnEuzD+ff8Pg>pJRqsWsD{#?eGPaCu0(sEH_2RG@<6-Nt<8 ztPMUmmAz9Ga$23Y9~p9dqJSgJJ#Jk_r@o13^%d-Xf46i+Lrmz3 zy9(DUDVXj;Zny7nO+yn&W2flEX=C!8&D0zI`G# z8;XmlonoghgRFUY*$+7pPLa}Uy)onw>TT9t(FTV6#BV8&lXWDPRvQW_n~xZ|yLcZjX>m$Eaf1)dwXS`&E^ zkNjO;%;fWywchc=+w4utQ0Vbn%B>b~yy4I#D{?1!P`$P>Wdo+ljCo(tYia04JTc=$$u+IbzDVPFYpm8+AQj+ zGKH zfS{{hN%W)kF+(26oZpkURD5Q_G_z97F6{Jval+TOj-;5y)*Rdo3a$^^k~q5gpTzmp1q@+2X9O z;_VUF>;s~C1~gpFrFoh?{aQ|LlBIYz!z^P~lndX5-ES)p#+9GW*|-WBTzQ*&gKOE` zM##bUaWl`6rZBXw0!~_oUhf+H$tNc@lLZCj0bZT^KSo@C|P?7YR8dP0se1jj z9aA0|7MONf(ZYaLZs$s}r*05fx25-iN6mZe_*Rq%uyz(+^-k;t`!R`?uf~rn#1ZC7 zuv3}UrmMzcBbo4jym@fS5%I+G`GJIC1s$)MQs3Vhld?a2U;w}$@V%dC@%qpO7+3#$ N&GnQ!lI8SQ#{X#Iv!eh2 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index b8d35b3a1cfe5308bb099a5a1429555c41417e36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3552 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 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 8f56909cddfa86f1387074bf43003f36d6e67be1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2413 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 b;}yxl--Ss53i@>Q4YQuNcebmsMJN0NT!aL! diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 9737d79c0492b2c8a811621660eba33e79fab959..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4858 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 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 9133e31b43252d00767a6a3806df9ba68de2d265..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3871 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 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index c3ae5f5ccdecc01a9b17a2a0c2b1bb20602f0151..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8001 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 z 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 F@PB1o0BisN diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Osu.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index ef89bd5215ffcc38c68b119a7495a77a7084543b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10893 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 diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/Strings.xml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/Strings.xml deleted file mode 100644 index 8c47838dfb..0000000000 --- a/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/Strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - osu.Game.Rulesets.Osu.Tests.Android - Settings - diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/colors.xml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/colors.xml deleted file mode 100644 index 17bb9a9dd1..0000000000 --- a/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #2c3e50 - #1B3147 - #3498db - diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/ic_launcher_background.xml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/ic_launcher_background.xml deleted file mode 100644 index 6ec24e6413..0000000000 --- a/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/ic_launcher_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #2C3E50 - \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/styles.xml b/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/styles.xml deleted file mode 100644 index 5885930df6..0000000000 --- a/osu.Game.Rulesets.Osu.Tests.Android/Resources/values/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj index 7eeee4fd80..9b2ab38309 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj +++ b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj @@ -24,82 +24,35 @@ Assets Xamarin.Android.Net.AndroidClientHandler - - True - portable - False - bin\Debug\ - DEBUG;TRACE - prompt - 4 - True - None - False - - - True - pdbonly - True - bin\Release\ - TRACE - prompt - 4 - true - False - SdkOnly - True - - - - - - - + - - + + osu.licenseheader + - - - Designer - - - - - - - - - - - - - - - - - - - - - - + + %(RecursiveDir)%(Filename)%(Extension) + - + + {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} + osu.Game.Resources + + + {c92a607b-1fdd-4954-9f92-03ff547d9080} + osu.Game.Rulesets.Osu + + + {2a66dd92-adb1-4994-89e2-c94e04acda0d} + osu.Game + - \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Assets/AboutAssets.txt b/osu.Game.Rulesets.Taiko.Tests.Android/Assets/AboutAssets.txt deleted file mode 100644 index b0633374bd..0000000000 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Assets/AboutAssets.txt +++ /dev/null @@ -1,19 +0,0 @@ -Any raw assets you want to be deployed with your application can be placed in -this directory (and child directories) and given a Build Action of "AndroidAsset". - -These files will be deployed with you package and will be accessible using Android's -AssetManager, like this: - -public class ReadAsset : Activity -{ - protected override void OnCreate (Bundle bundle) - { - base.OnCreate (bundle); - - InputStream input = Assets.Open ("my_asset.txt"); - } -} - -Additionally, some Android functions will automatically load asset files: - -Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs index 8ceca4d436..0c64cbfc5d 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs @@ -1,19 +1,17 @@ -using Android.App; -using Android.OS; -using Android.Support.V7.App; -using Android.Runtime; -using Android.Widget; +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using Android.App; +using Android.Content.PM; +using osu.Framework.Android; +using osu.Game.Tests; namespace osu.Game.Rulesets.Taiko.Tests.Android { - [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] - public class MainActivity : AppCompatActivity + [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] + public class MainActivity : AndroidGameActivity { - protected override void OnCreate(Bundle savedInstanceState) - { - base.OnCreate(savedInstanceState); - // Set our view from the "main" layout resource - SetContentView(Resource.Layout.activity_main); - } + protected override Framework.Game CreateGame() + => new OsuTestBrowser(); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/AboutResources.txt b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/AboutResources.txt deleted file mode 100644 index c2bca974c4..0000000000 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/AboutResources.txt +++ /dev/null @@ -1,44 +0,0 @@ -Images, layout descriptions, binary blobs and string dictionaries can be included -in your application as resource files. Various Android APIs are designed to -operate on the resource IDs instead of dealing with images, strings or binary blobs -directly. - -For example, a sample Android app that contains a user interface layout (main.axml), -an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) -would keep its resources in the "Resources" directory of the application: - -Resources/ - drawable/ - icon.png - - layout/ - main.axml - - values/ - strings.xml - -In order to get the build system to recognize Android resources, set the build action to -"AndroidResource". The native Android APIs do not operate directly with filenames, but -instead operate on resource IDs. When you compile an Android application that uses resources, -the build system will package the resources for distribution and generate a class called "R" -(this is an Android convention) that contains the tokens for each one of the resources -included. For example, for the above Resources layout, this is what the R class would expose: - -public class R { - public class drawable { - public const int icon = 0x123; - } - - public class layout { - public const int main = 0x456; - } - - public class strings { - public const int first_string = 0xabc; - public const int second_string = 0xbcd; - } -} - -You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main -to reference the layout/main.axml file, or R.strings.first_string to reference the first -string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/Resource.designer.cs b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/Resource.designer.cs deleted file mode 100644 index d3709d3cdb..0000000000 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/Resource.designer.cs +++ /dev/null @@ -1,112 +0,0 @@ -#pragma warning disable 1591 -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -[assembly: global::Android.Runtime.ResourceDesignerAttribute("osu.Game.Rulesets.Taiko.Tests.Android.Resource", IsApplication=true)] - -namespace osu.Game.Rulesets.Taiko.Tests.Android -{ - - - [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] - public partial class Resource - { - - static Resource() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - public static void UpdateIdValues() - { - } - - public partial class Attribute - { - - static Attribute() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Attribute() - { - } - } - - public partial class Id - { - - // aapt resource value: 0x7f050000 - public const int myButton = 2131034112; - - static Id() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Id() - { - } - } - - public partial class Layout - { - - // aapt resource value: 0x7f030000 - public const int Main = 2130903040; - - static Layout() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Layout() - { - } - } - - public partial class Mipmap - { - - // aapt resource value: 0x7f020000 - public const int Icon = 2130837504; - - static Mipmap() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Mipmap() - { - } - } - - public partial class String - { - - // aapt resource value: 0x7f040001 - public const int app_name = 2130968577; - - // aapt resource value: 0x7f040000 - public const int hello = 2130968576; - - static String() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private String() - { - } - } - } -} -#pragma warning restore 1591 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/layout/activity_main.axml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/layout/activity_main.axml deleted file mode 100644 index ff7a60eb50..0000000000 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/layout/activity_main.axml +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 036d09bc5f..0000000000 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 036d09bc5f..0000000000 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 2531cb31efc3a0a3de6113ab9c7845dc1d9654e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1634 zcmV-o2A%ndP)B+Z3$1(8#|f~9B42Y^N-3=o2YCq0YUY$Zu=pM;#hG{lHi%n~Vh z1d1vN#EDO19X?u$`cV z!a}AKG@Bb*#1cdYg8af_;jP69b`k%G1n?0=F^8bI^o>wg-vEliK^U}y^!D|^p|ax; zC|pK=f+FHp!RUAhtlpGGUxJb|wm^5! z<1r%$<$TR02wajxKZ4MiR#aAxDLE(##UNyD|ABr4WoGRF*?@e^2|~Hq(gurSSJH*;Q~5lw{J5A_(PCXBWhzZE${qgzv0{dk-F( z1<}>r181tLiEla&f1j&?p2xjbfp2cTt-c1Ox~?9EhK9`cJ9Vatf)loIoQ@#h&}cIGD>Z#QLE}&(bMo@7Ff|7f#Nm^$PJpVcbj+v~K7wfVwF}=) zRQsc+`=A-+C)vrRvaIC-5u>|;3h z*G4-u#RI<_vuSN~vZ6{|I~q5FFk3%de#+*>UFG>&bq6~ zUEMZ~FIOmFO=kA^5rkp-Msw?^63xvdXVZ-rv@{6{iVO}M!}^Je%2BPbi+(L<5<%~h z2v^D+f<|j%7~cJjOzg*!GPQ{%uE{i%YgcZhuZh{yNlQ}RhaU1jd=K+AopVKP+D}&} zZ3y$llqZiln=Z_A$!qzkGbX0D{?l(v5@1|`QyCvCnQ`eKI>|zj_zo%y#fKf85VhQ} zP)y&j4P*nR3q{-o35iV6nx7QDqq<;WDVIt}|N%`!dgv*y3va8eLNj zU9x(?ieweHfQ*yXk8|=ssZ~qJEz^QoKJ|iGa>ge_Vm_8l}S+UvJ{8g4jr+o#aTSFsz1W;PDP zW765JXGU#3JL>SlIl3NRV2{7B2dLO1cIP)a4ZRYL|MBD36O1#oSgAf}APz5@;x=_U-<=y)Py7*}O5(uu7BL_eLe6Ek7pH|G zMq)FrF1EFq&yruS5b=F=w)fVVoPd(oeRyTFym_Uwyn~L=OL(O?cf^2L5R(SmjORx6 z%nmZf^W=3pkvT*>@osUNi>DULH1hL;y`JGQX$onRCr_U0=H~Viodq!<7Q{3rPk~{G gu#IhOV;e2n|1(WJB~7~kivR!s07*qoM6N<$g7lUVaR2}S diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index 7a859c25556af7a2e46e22a2220eaded55628e9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1441 zcma)+`#%#30L6FjMQg%tuA0%p#0??L`*E=rD#U2F4L5n@F+O9Sp;(QwEQy7+?sX?r zCWN(!Hg`+j5k8*H@|yQEtnAi*(D{7M`Tlf1=eKjq)BUsp2nqrK01B=yNUv`!`EH=x zx8$xJQUd^Fuec%|(TT&0V}4orr_==mmCnEuzD+ff8Pg>pJRqsWsD{#?eGPaCu0(sEH_2RG@<6-Nt<8 ztPMUmmAz9Ga$23Y9~p9dqJSgJJ#Jk_r@o13^%d-Xf46i+Lrmz3 zy9(DUDVXj;Zny7nO+yn&W2flEX=C!8&D0zI`G# z8;XmlonoghgRFUY*$+7pPLa}Uy)onw>TT9t(FTV6#BV8&lXWDPRvQW_n~xZ|yLcZjX>m$Eaf1)dwXS`&E^ zkNjO;%;fWywchc=+w4utQ0Vbn%B>b~yy4I#D{?1!P`$P>Wdo+ljCo(tYia04JTc=$$u+IbzDVPFYpm8+AQj+ zGKH zfS{{hN%W)kF+(26oZpkURD5Q_G_z97F6{Jval+TOj-;5y)*Rdo3a$^^k~q5gpTzmp1q@+2X9O z;_VUF>;s~C1~gpFrFoh?{aQ|LlBIYz!z^P~lndX5-ES)p#+9GW*|-WBTzQ*&gKOE` zM##bUaWl`6rZBXw0!~_oUhf+H$tNc@lLZCj0bZT^KSo@C|P?7YR8dP0se1jj z9aA0|7MONf(ZYaLZs$s}r*05fx25-iN6mZe_*Rq%uyz(+^-k;t`!R`?uf~rn#1ZC7 zuv3}UrmMzcBbo4jym@fS5%I+G`GJIC1s$)MQs3Vhld?a2U;w}$@V%dC@%qpO7+3#$ N&GnQ!lI8SQ#{X#Iv!eh2 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index b8d35b3a1cfe5308bb099a5a1429555c41417e36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3552 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 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 8f56909cddfa86f1387074bf43003f36d6e67be1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2413 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 b;}yxl--Ss53i@>Q4YQuNcebmsMJN0NT!aL! diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 9737d79c0492b2c8a811621660eba33e79fab959..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4858 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 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 9133e31b43252d00767a6a3806df9ba68de2d265..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3871 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 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index c3ae5f5ccdecc01a9b17a2a0c2b1bb20602f0151..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8001 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 z zJXRatyoD+rrB5}!y+63gWvR|9?|P`Y@uV?e#kPV8dZodMwHfARej+#cj%=P<30GKd zN!W`c;D2#c=bht_b0^ZLB2elt)}h$X=h^{g!~h^Lci~~8Q+K?>pY9)M$;w}Drvk4 znrFVe5dwt(vj(i}13^XRAthw=Gkacf=1NmU?tp>{)!$I76rY=U(MVn^pC&9n(uUU| zrR%7@4$dC==-(WPFy-rA)Q(b0#<%FtE2h-@nt z1VL31-UIymlq28oZg};RkYCuWS9@cja|FYDLH1kfu}9f)BIu^u>7aYX|C1fZ0Fo#?!+qs%`#D zKdt2++&;b=fF%r3G>4zHBB(TpQWN2DXb%z1oZmTC9&_ zY%cKvKh_xJ2!-Dk{0L&b0I!tUd0hg@*@(J7#LhVT?6=5Bf8F+rqI{bF@`R}Ac%sZ3 zunSthYbzyO{q{>o+~?QL_vBBnZI`-Lz+ZVc#xH2sDpXn}?k`5SksDjq4D(|G|IvHx zTP`vuIVz-8tGE-%a8LE}GxQd159MIWXI6IJcfkODa^9AqD`NT$o08DD_E>l-h^RWda`hdd0%(sOj1%;P5gn^Bt$ zSO%{(#RLEVrf#ORr|m1u@+UTr)KI79wKWi)0RCD2KM_w~$Mo_hXq_1ltqtjQ%BN7s^8p0bK7j{vqN-H+!K<)x4lcR-g`!I*v1)) z&O5_r=dj8E9#+}*g9tY%1HehjSpJZdVVkHJ9-p7NgZ_6%qZMi5@Y!vkB}=^$6MYRE zAE{NhjT{pp9yl$_YR%G0@P_%?#`967FO3aDdRu1-m0>ZmtSxpv&9zzmD1H47G#1*m z601xLhR?>;7kg6jz!*p2GM7_rux0mBA70i;tzj1|PHa;+=HL?(Cl=qS<^&|i0#P>! zZA^+$%&!PSGpL&w{OanKKO^+Tf8RDWg$N9owWW=%`V(>!{xct}3p7B+M$C|-Fqv&N z=){^7KS3IQi)p|5&JU+aOM%lgN8fj@ND%v!1(cU^PEngfm$g_qb?W<`({8p3 zmTi2E)>p4U`n!9`VR--Sf|n0XSYf;vPIGFikDR%BaEtOT&EH6?2#?O;q-01puFSEt zd@m0ig7n|U67&B5X%!&0dP!9AVK=!S6zu?dP5wK)}dh@%d^QuGlwOwriLm?_&In82dC|pGjXo1YVyNZyfaLw zIjmr{9fiI`sG{({h&va^rVA08+ueDKhtOT6ez{c-nmoKP5^lE}L--|uyU4oLDX6&6 zQp$@c5Dtn-tV-U{s$Cu5#sJlk5=ZExEzF70Te`%?3B!NWf4KDr{asG!>jRhMoUv_a zBV^I^$Tfu6;{-xnDVPFj!M{SwyH9p^jxY+tJs989)rw-T{N}f1B^r5FCvGSqxrSd4 z_UQLV1Old%v_lpPRxz^#IG_Ldr2N2NUHPdiLB0Te3n`Pf9M=0}$;QVC+<;B3)sV*6 zOSDcnCwsgWdwB|nK9^W914LO9GC}stSjmX>_2oyYpHs-+(gOuDb;|H^N>Ov=zA7kufFw8eR5>Yj$QVjCUMk%YDH>7lk7%Gg|R_n*08mH~EySy{OHocl0gZ09|xhF<}m>USnn{@VD!oJc4Sjw7x} zYwc?)8;wz}eP2<+vZueJfN^>T@C>0vm0(MxGb{LpAjR@h{xeRtZ0Z9fLvPq-eKIAW z_=i+tH7Pd-kH0Ld76)&BB&BXoc3nBRZq@4DV((4$XZ|x^<{~Z&op~*x~EKrrLEJ z702nz$7O6LB<=;6$hzVJS!_W}m}64!{p>10p)Bhf)YElg)Zek@~2kytT1oxZvBry9u_KJw%qjq{a&?RNmyjjK?&vs{Q(+?0P1=MMt=O1W3+Ngj}M57BsvjU8Dqm zndt6(DL#^vgGtSVcbP+K(U|Y0k%I#1&7i>yLzpCq^$g0k&-`3^!XIc`tk`tZt3;t6 z)Jf};A>RNleP!ZCk5>)z0#4ZWD2Au(3`S0$w~ViV)aGIgimj=Hd~u2NUtz=?R&*oD zXj)l6zCx#VIn1Eio0{wr20p7FucuY_3JD3)b#NBI-t`4##<41={GZHaDXYZmY1i#x z*2-q9H)<-?$%G%+EPv@{fZ-JFRIUF zEiZ{oGP>`SZKs75Qe_dA0F~Vfm+dzH-*Q`7p*F$8YuA+W zT~^#k0*5S|Bs#`&JNn#284m!UT)#*{&yHE~bT;Sd>Q*B4wC`S8m4Q-|2VoJTx;gUk z57*JC%nxv=qOOXd2z#*PQ`WD^h9%J5|FORq0fBgpgQHl7R$u3SqScSfS(sUy*8Jw1 F@PB1o0BisN diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index ef89bd5215ffcc38c68b119a7495a77a7084543b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10893 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 diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/Strings.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/Strings.xml deleted file mode 100644 index 12965f132d..0000000000 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/Strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - osu.Game.Rulesets.Taiko.Tests.Android - Settings - diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/colors.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/colors.xml deleted file mode 100644 index 17bb9a9dd1..0000000000 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #2c3e50 - #1B3147 - #3498db - diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/ic_launcher_background.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/ic_launcher_background.xml deleted file mode 100644 index 6ec24e6413..0000000000 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/ic_launcher_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #2C3E50 - \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/styles.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/styles.xml deleted file mode 100644 index 5885930df6..0000000000 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Resources/values/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj index 62c2cefe06..0174be9451 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj @@ -24,82 +24,38 @@ Assets Xamarin.Android.Net.AndroidClientHandler - - True - portable - False - bin\Debug\ - DEBUG;TRACE - prompt - 4 - True - None - False - - - True - pdbonly - True - bin\Release\ - TRACE - prompt - 4 - true - False - SdkOnly - True - - - - - - - + - - + + osu.licenseheader + - - - Designer - - - - - - - - - - - - - - - - - - - - - - + + %(RecursiveDir)%(Filename)%(Extension) + + + + {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} + osu.Game.Resources + + + {f167e17a-7de6-4af5-b920-a5112296c695} + osu.Game.Rulesets.Taiko + + + {2a66dd92-adb1-4994-89e2-c94e04acda0d} + osu.Game + + - \ No newline at end of file From 5fdf4ee67b3c4e3c8c97625cdbf858c3e92faeec Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Sat, 5 Jan 2019 23:18:12 -0600 Subject: [PATCH 0330/5608] Add Android's VisualTests project --- osu.Android.sln | 8 ++ osu.Game.Tests.Android/MainActivity.cs | 16 ++++ .../Properties/AndroidManifest.xml | 9 ++ .../Properties/AssemblyInfo.cs | 30 ++++++ .../osu.Game.Tests.Android.csproj | 91 +++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 osu.Game.Tests.Android/MainActivity.cs create mode 100644 osu.Game.Tests.Android/Properties/AndroidManifest.xml create mode 100644 osu.Game.Tests.Android/Properties/AssemblyInfo.cs create mode 100644 osu.Game.Tests.Android/osu.Game.Tests.Android.csproj diff --git a/osu.Android.sln b/osu.Android.sln index 11c0f3cb27..d9c6ffc939 100644 --- a/osu.Android.sln +++ b/osu.Android.sln @@ -25,6 +25,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tests.Android", "osu.Game.Rulesets.Taiko.Tests.Android\osu.Game.Rulesets.Taiko.Tests.Android.csproj", "{3701A0A1-8476-42C6-B5C4-D24129B4A484}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tests.Android", "osu.Game.Tests.Android\osu.Game.Tests.Android.csproj", "{5CC222DC-5716-4499-B897-DCBDDA4A5CF9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -85,6 +87,12 @@ Global {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.ActiveCfg = Release|Any CPU {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.Build.0 = Release|Any CPU {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.Deploy.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.Build.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/osu.Game.Tests.Android/MainActivity.cs b/osu.Game.Tests.Android/MainActivity.cs new file mode 100644 index 0000000000..58375c699e --- /dev/null +++ b/osu.Game.Tests.Android/MainActivity.cs @@ -0,0 +1,16 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using Android.App; +using Android.Content.PM; +using osu.Framework.Android; + +namespace osu.Game.Tests.Android +{ + [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] + public class MainActivity : AndroidGameActivity + { + protected override Framework.Game CreateGame() + => new OsuTestBrowser(); + } +} diff --git a/osu.Game.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Tests.Android/Properties/AndroidManifest.xml new file mode 100644 index 0000000000..d4d822c7b0 --- /dev/null +++ b/osu.Game.Tests.Android/Properties/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/osu.Game.Tests.Android/Properties/AssemblyInfo.cs b/osu.Game.Tests.Android/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..dfa3e0197b --- /dev/null +++ b/osu.Game.Tests.Android/Properties/AssemblyInfo.cs @@ -0,0 +1,30 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Android.App; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("osu.Game.Tests.Android")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("osu.Game.Tests.Android")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj new file mode 100644 index 0000000000..4f5b0e68d4 --- /dev/null +++ b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj @@ -0,0 +1,91 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {122416d6-6b49-4ee2-a1e8-b825f31c79fe} + Library + Properties + osu.Game.Tests.Android + osu.Game.Tests.Android + 512 + True + Resources\Resource.designer.cs + Resource + Off + false + v8.1 + Properties\AndroidManifest.xml + Resources + Assets + Xamarin.Android.Net.AndroidClientHandler + + + + + + + + + osu.licenseheader + + + + + + %(RecursiveDir)%(Filename)%(Extension) + + + %(RecursiveDir)%(Filename)%(Extension) + + + %(RecursiveDir)%(Filename)%(Extension) + + + %(RecursiveDir)%(Filename)%(Extension) + + + %(RecursiveDir)%(Filename)%(Extension) + + + %(RecursiveDir)%(Filename)%(Extension) + + + %(RecursiveDir)%(Filename)%(Extension) + + + %(RecursiveDir)%(Filename)%(Extension) + + + + + {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} + osu.Game.Resources + + + {58f6c80c-1253-4a0e-a465-b8c85ebeadf3} + osu.Game.Rulesets.Catch + + + {48f4582b-7687-4621-9cbe-5c24197cb536} + osu.Game.Rulesets.Mania + + + {c92a607b-1fdd-4954-9f92-03ff547d9080} + osu.Game.Rulesets.Osu + + + {f167e17a-7de6-4af5-b920-a5112296c695} + osu.Game.Rulesets.Taiko + + + {2a66dd92-adb1-4994-89e2-c94e04acda0d} + osu.Game + + + + \ No newline at end of file From 8159905ca038994432454cb55233a416cc5236bd Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Sat, 5 Jan 2019 23:48:57 -0600 Subject: [PATCH 0331/5608] Code File Sanity --- .gitignore | 1 + osu.Android/Properties/AssemblyInfo.cs | 33 ------------------- osu.Android/osu.Android.csproj | 1 - .../Properties/AssemblyInfo.cs | 30 ----------------- ...u.Game.Rulesets.Catch.Tests.Android.csproj | 1 - .../Properties/AssemblyInfo.cs | 30 ----------------- ...u.Game.Rulesets.Mania.Tests.Android.csproj | 1 - .../Properties/AssemblyInfo.cs | 30 ----------------- ...osu.Game.Rulesets.Osu.Tests.Android.csproj | 1 - .../Properties/AssemblyInfo.cs | 30 ----------------- ...u.Game.Rulesets.Taiko.Tests.Android.csproj | 1 - .../Properties/AndroidManifest.xml | 12 +++---- .../Properties/AssemblyInfo.cs | 30 ----------------- .../osu.Game.Tests.Android.csproj | 8 +++-- osu.Game/Properties/AssemblyInfo.cs | 1 + 15 files changed, 12 insertions(+), 198 deletions(-) delete mode 100644 osu.Android/Properties/AssemblyInfo.cs delete mode 100644 osu.Game.Rulesets.Catch.Tests.Android/Properties/AssemblyInfo.cs delete mode 100644 osu.Game.Rulesets.Mania.Tests.Android/Properties/AssemblyInfo.cs delete mode 100644 osu.Game.Rulesets.Osu.Tests.Android/Properties/AssemblyInfo.cs delete mode 100644 osu.Game.Rulesets.Taiko.Tests.Android/Properties/AssemblyInfo.cs delete mode 100644 osu.Game.Tests.Android/Properties/AssemblyInfo.cs diff --git a/.gitignore b/.gitignore index f95a04e517..21dbf45618 100644 --- a/.gitignore +++ b/.gitignore @@ -196,6 +196,7 @@ ClientBin/ *.publishsettings node_modules/ orleans.codegen.cs +Resource.designer.cs # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) diff --git a/osu.Android/Properties/AssemblyInfo.cs b/osu.Android/Properties/AssemblyInfo.cs deleted file mode 100644 index d222a06ee0..0000000000 --- a/osu.Android/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Android.App; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("osu.Android")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("osu.Android")] -[assembly: AssemblyCopyright("Copyright © 2018")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: ComVisible(false)] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 646ed71d44..4a1dccd758 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -28,7 +28,6 @@ - diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AssemblyInfo.cs deleted file mode 100644 index 1b1fd64fb5..0000000000 --- a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Android.App; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("osu.Game.Rulesets.Catch.Tests.Android")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("osu.Game.Rulesets.Catch.Tests.Android")] -[assembly: AssemblyCopyright("Copyright © 2018")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: ComVisible(false)] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj index 82c171cb46..e4140374cc 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj +++ b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj @@ -27,7 +27,6 @@ - diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AssemblyInfo.cs deleted file mode 100644 index 468676e282..0000000000 --- a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Android.App; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("osu.Game.Rulesets.Mania.Tests.Android")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("osu.Game.Rulesets.Mania.Tests.Android")] -[assembly: AssemblyCopyright("Copyright © 2018")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: ComVisible(false)] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj index a761f2569a..8b2cc5f55b 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj +++ b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj @@ -27,7 +27,6 @@ - diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AssemblyInfo.cs deleted file mode 100644 index 0e43fb25cf..0000000000 --- a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Android.App; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("osu.Game.Rulesets.Osu.Tests.Android")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("osu.Game.Rulesets.Osu.Tests.Android")] -[assembly: AssemblyCopyright("Copyright © 2018")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: ComVisible(false)] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj index 9b2ab38309..a8d6b631cc 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj +++ b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj @@ -27,7 +27,6 @@ - diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AssemblyInfo.cs deleted file mode 100644 index 28f5d292ab..0000000000 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Android.App; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("osu.Game.Rulesets.Taiko.Tests.Android")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("osu.Game.Rulesets.Taiko.Tests.Android")] -[assembly: AssemblyCopyright("Copyright © 2018")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: ComVisible(false)] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj index 0174be9451..2dc5cc37c1 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj @@ -27,7 +27,6 @@ - diff --git a/osu.Game.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Tests.Android/Properties/AndroidManifest.xml index d4d822c7b0..fda3bdafab 100644 --- a/osu.Game.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Tests.Android/Properties/AndroidManifest.xml @@ -1,9 +1,5 @@  - - - - - + + + + \ No newline at end of file diff --git a/osu.Game.Tests.Android/Properties/AssemblyInfo.cs b/osu.Game.Tests.Android/Properties/AssemblyInfo.cs deleted file mode 100644 index dfa3e0197b..0000000000 --- a/osu.Game.Tests.Android/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Android.App; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("osu.Game.Tests.Android")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("osu.Game.Tests.Android")] -[assembly: AssemblyCopyright("Copyright © 2018")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: ComVisible(false)] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj index 4f5b0e68d4..8a8a2b6733 100644 --- a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj +++ b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj @@ -10,7 +10,7 @@ {122416d6-6b49-4ee2-a1e8-b825f31c79fe} Library Properties - osu.Game.Tests.Android + osu.Game.Tests osu.Game.Tests.Android 512 True @@ -27,7 +27,6 @@ - @@ -87,5 +86,10 @@ osu.Game + + + 2.0.0 + + \ No newline at end of file diff --git a/osu.Game/Properties/AssemblyInfo.cs b/osu.Game/Properties/AssemblyInfo.cs index df9045b802..3a283b29d5 100644 --- a/osu.Game/Properties/AssemblyInfo.cs +++ b/osu.Game/Properties/AssemblyInfo.cs @@ -9,3 +9,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("osu.Game.Tests")] [assembly: InternalsVisibleTo("osu.Game.Tests.Dynamic")] +[assembly: InternalsVisibleTo("osu.Game.Tests.Android")] From 47268898bec498d8e165e26c84fd59315a2ac44d Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Sun, 6 Jan 2019 00:04:25 -0600 Subject: [PATCH 0332/5608] Expose internals for Android test projects --- osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs | 1 + osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs | 1 + osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs | 1 + osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs | 1 + 4 files changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs index 045d0824c6..7dfb32cade 100644 --- a/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs @@ -9,3 +9,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("osu.Game.Rulesets.Catch.Tests")] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Catch.Tests.Dynamic")] +[assembly: InternalsVisibleTo("osu.Game.Rulesets.Catch.Tests.Android")] diff --git a/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs index 76ccfe324b..743cec5ee1 100644 --- a/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs @@ -9,3 +9,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("osu.Game.Rulesets.Mania.Tests")] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Mania.Tests.Dynamic")] +[assembly: InternalsVisibleTo("osu.Game.Rulesets.Mania.Tests.Android")] diff --git a/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs index b61c53be6a..5a41b60a03 100644 --- a/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs @@ -9,3 +9,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("osu.Game.Rulesets.Osu.Tests")] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Osu.Tests.Dynamic")] +[assembly: InternalsVisibleTo("osu.Game.Rulesets.Osu.Tests.Android")] diff --git a/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs index 26f70bc927..ae7a113f7e 100644 --- a/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs @@ -9,3 +9,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("osu.Game.Rulesets.Taiko.Tests")] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Taiko.Tests.Dynamic")] +[assembly: InternalsVisibleTo("osu.Game.Rulesets.Taiko.Tests.Android")] From bf78c93346ff6c54c6e96311b824735f953a8a0a Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Sun, 6 Jan 2019 00:06:00 -0600 Subject: [PATCH 0333/5608] Cleanup Android manifest files --- .../Properties/AndroidManifest.xml | 3 +-- .../Properties/AndroidManifest.xml | 3 +-- .../Properties/AndroidManifest.xml | 3 +-- .../Properties/AndroidManifest.xml | 3 +-- osu.Game.Tests.Android/Properties/AndroidManifest.xml | 2 +- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml index 6c8c0935b2..e22c571991 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml @@ -4,6 +4,5 @@ android:versionName="1.0" package="osu.Game.Rulesets.Catch.Tests.Android.osu.Game.Rulesets.Catch.Tests.Android"> - - + diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml index 6ffcfe16f7..a36d279391 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml @@ -4,6 +4,5 @@ android:versionName="1.0" package="osu.Game.Rulesets.Mania.Tests.Android.osu.Game.Rulesets.Mania.Tests.Android"> - - + diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml index 05da9d02f7..a10763a5ed 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml @@ -4,6 +4,5 @@ android:versionName="1.0" package="osu.Game.Rulesets.Osu.Tests.Android.osu.Game.Rulesets.Osu.Tests.Android"> - - + diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml index 9b5e759012..d9df277133 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml @@ -4,6 +4,5 @@ android:versionName="1.0" package="osu.Game.Rulesets.Taiko.Tests.Android.osu.Game.Rulesets.Taiko.Tests.Android"> - - + diff --git a/osu.Game.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Tests.Android/Properties/AndroidManifest.xml index fda3bdafab..20060728da 100644 --- a/osu.Game.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file From c2a52b56e7e0b04cdcffb3e3543a46ee8b40577e Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Sun, 6 Jan 2019 12:01:50 -0600 Subject: [PATCH 0334/5608] Set app name and reset default namespace --- .../Properties/AndroidManifest.xml | 11 ++++------- .../osu.Game.Rulesets.Catch.Tests.Android.csproj | 2 +- .../Properties/AndroidManifest.xml | 11 ++++------- .../osu.Game.Rulesets.Mania.Tests.Android.csproj | 2 +- .../Properties/AndroidManifest.xml | 11 ++++------- .../osu.Game.Rulesets.Osu.Tests.Android.csproj | 2 +- .../Properties/AndroidManifest.xml | 11 ++++------- .../osu.Game.Rulesets.Taiko.Tests.Android.csproj | 2 +- osu.Game.Tests.Android/Properties/AndroidManifest.xml | 2 +- 9 files changed, 21 insertions(+), 33 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml index e22c571991..b04b0718f5 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml @@ -1,8 +1,5 @@  - - - - + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj index e4140374cc..591f4cbc31 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj +++ b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj @@ -10,7 +10,7 @@ {122416d6-6b49-4ee2-a1e8-b825f31c79fe} Library Properties - osu.Game.Rulesets.Catch.Tests.Android + osu.Game.Rulesets.Catch.Tests osu.Game.Rulesets.Catch.Tests.Android 512 True diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml index a36d279391..c315581606 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml @@ -1,8 +1,5 @@  - - - - + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj index 8b2cc5f55b..5faf9f747d 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj +++ b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj @@ -10,7 +10,7 @@ {122416d6-6b49-4ee2-a1e8-b825f31c79fe} Library Properties - osu.Game.Rulesets.Mania.Tests.Android + osu.Game.Rulesets.Mania.Tests osu.Game.Rulesets.Mania.Tests.Android 512 True diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml index a10763a5ed..dac9c19477 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml @@ -1,8 +1,5 @@  - - - - + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj index a8d6b631cc..f99aa61f01 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj +++ b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj @@ -10,7 +10,7 @@ {122416d6-6b49-4ee2-a1e8-b825f31c79fe} Library Properties - osu.Game.Rulesets.Osu.Tests.Android + osu.Game.Rulesets.Osu.Tests osu.Game.Rulesets.Osu.Tests.Android 512 True diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml index d9df277133..f731042a4c 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml @@ -1,8 +1,5 @@  - - - - + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj index 2dc5cc37c1..defeab5a64 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj @@ -10,7 +10,7 @@ {122416d6-6b49-4ee2-a1e8-b825f31c79fe} Library Properties - osu.Game.Rulesets.Taiko.Tests.Android + osu.Game.Rulesets.Taiko.Tests osu.Game.Rulesets.Taiko.Tests.Android 512 True diff --git a/osu.Game.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Tests.Android/Properties/AndroidManifest.xml index 20060728da..146f96c2a3 100644 --- a/osu.Game.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file From 48686bdb301ba2876324393ecfa18ac6383539cd Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Sun, 6 Jan 2019 18:18:11 -0600 Subject: [PATCH 0335/5608] Fix osu.Android Android manifest --- osu.Android/Properties/AndroidManifest.xml | 2 +- osu.Android/Resources/Resource.designer.cs | 6424 +------------------- 2 files changed, 15 insertions(+), 6411 deletions(-) diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index 76cb58969f..bb5f9b751e 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -5,5 +5,5 @@ - + \ No newline at end of file diff --git a/osu.Android/Resources/Resource.designer.cs b/osu.Android/Resources/Resource.designer.cs index ed8407c130..c02df072f1 100644 --- a/osu.Android/Resources/Resource.designer.cs +++ b/osu.Android/Resources/Resource.designer.cs @@ -28,1124 +28,9 @@ namespace osu.Android { } - public partial class Animation - { - - // aapt resource value: 0x7f050000 - public const int abc_fade_in = 2131034112; - - // aapt resource value: 0x7f050001 - public const int abc_fade_out = 2131034113; - - // aapt resource value: 0x7f050002 - public const int abc_grow_fade_in_from_bottom = 2131034114; - - // aapt resource value: 0x7f050003 - public const int abc_popup_enter = 2131034115; - - // aapt resource value: 0x7f050004 - public const int abc_popup_exit = 2131034116; - - // aapt resource value: 0x7f050005 - public const int abc_shrink_fade_out_from_bottom = 2131034117; - - // aapt resource value: 0x7f050006 - public const int abc_slide_in_bottom = 2131034118; - - // aapt resource value: 0x7f050007 - public const int abc_slide_in_top = 2131034119; - - // aapt resource value: 0x7f050008 - public const int abc_slide_out_bottom = 2131034120; - - // aapt resource value: 0x7f050009 - public const int abc_slide_out_top = 2131034121; - - // aapt resource value: 0x7f05000a - public const int design_bottom_sheet_slide_in = 2131034122; - - // aapt resource value: 0x7f05000b - public const int design_bottom_sheet_slide_out = 2131034123; - - // aapt resource value: 0x7f05000c - public const int design_snackbar_in = 2131034124; - - // aapt resource value: 0x7f05000d - public const int design_snackbar_out = 2131034125; - - // aapt resource value: 0x7f05000e - public const int tooltip_enter = 2131034126; - - // aapt resource value: 0x7f05000f - public const int tooltip_exit = 2131034127; - - static Animation() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Animation() - { - } - } - - public partial class Animator - { - - // aapt resource value: 0x7f060000 - public const int design_appbar_state_list_animator = 2131099648; - - static Animator() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Animator() - { - } - } - public partial class Attribute { - // aapt resource value: 0x7f010052 - public const int actionBarDivider = 2130772050; - - // aapt resource value: 0x7f010053 - public const int actionBarItemBackground = 2130772051; - - // aapt resource value: 0x7f01004c - public const int actionBarPopupTheme = 2130772044; - - // aapt resource value: 0x7f010051 - public const int actionBarSize = 2130772049; - - // aapt resource value: 0x7f01004e - public const int actionBarSplitStyle = 2130772046; - - // aapt resource value: 0x7f01004d - public const int actionBarStyle = 2130772045; - - // aapt resource value: 0x7f010048 - public const int actionBarTabBarStyle = 2130772040; - - // aapt resource value: 0x7f010047 - public const int actionBarTabStyle = 2130772039; - - // aapt resource value: 0x7f010049 - public const int actionBarTabTextStyle = 2130772041; - - // aapt resource value: 0x7f01004f - public const int actionBarTheme = 2130772047; - - // aapt resource value: 0x7f010050 - public const int actionBarWidgetTheme = 2130772048; - - // aapt resource value: 0x7f01006d - public const int actionButtonStyle = 2130772077; - - // aapt resource value: 0x7f010069 - public const int actionDropDownStyle = 2130772073; - - // aapt resource value: 0x7f0100c4 - public const int actionLayout = 2130772164; - - // aapt resource value: 0x7f010054 - public const int actionMenuTextAppearance = 2130772052; - - // aapt resource value: 0x7f010055 - public const int actionMenuTextColor = 2130772053; - - // aapt resource value: 0x7f010058 - public const int actionModeBackground = 2130772056; - - // aapt resource value: 0x7f010057 - public const int actionModeCloseButtonStyle = 2130772055; - - // aapt resource value: 0x7f01005a - public const int actionModeCloseDrawable = 2130772058; - - // aapt resource value: 0x7f01005c - public const int actionModeCopyDrawable = 2130772060; - - // aapt resource value: 0x7f01005b - public const int actionModeCutDrawable = 2130772059; - - // aapt resource value: 0x7f010060 - public const int actionModeFindDrawable = 2130772064; - - // aapt resource value: 0x7f01005d - public const int actionModePasteDrawable = 2130772061; - - // aapt resource value: 0x7f010062 - public const int actionModePopupWindowStyle = 2130772066; - - // aapt resource value: 0x7f01005e - public const int actionModeSelectAllDrawable = 2130772062; - - // aapt resource value: 0x7f01005f - public const int actionModeShareDrawable = 2130772063; - - // aapt resource value: 0x7f010059 - public const int actionModeSplitBackground = 2130772057; - - // aapt resource value: 0x7f010056 - public const int actionModeStyle = 2130772054; - - // aapt resource value: 0x7f010061 - public const int actionModeWebSearchDrawable = 2130772065; - - // aapt resource value: 0x7f01004a - public const int actionOverflowButtonStyle = 2130772042; - - // aapt resource value: 0x7f01004b - public const int actionOverflowMenuStyle = 2130772043; - - // aapt resource value: 0x7f0100c6 - public const int actionProviderClass = 2130772166; - - // aapt resource value: 0x7f0100c5 - public const int actionViewClass = 2130772165; - - // aapt resource value: 0x7f010075 - public const int activityChooserViewStyle = 2130772085; - - // aapt resource value: 0x7f01009a - public const int alertDialogButtonGroupStyle = 2130772122; - - // aapt resource value: 0x7f01009b - public const int alertDialogCenterButtons = 2130772123; - - // aapt resource value: 0x7f010099 - public const int alertDialogStyle = 2130772121; - - // aapt resource value: 0x7f01009c - public const int alertDialogTheme = 2130772124; - - // aapt resource value: 0x7f0100b2 - public const int allowStacking = 2130772146; - - // aapt resource value: 0x7f0100b3 - public const int alpha = 2130772147; - - // aapt resource value: 0x7f0100c1 - public const int alphabeticModifiers = 2130772161; - - // aapt resource value: 0x7f0100ba - public const int arrowHeadLength = 2130772154; - - // aapt resource value: 0x7f0100bb - public const int arrowShaftLength = 2130772155; - - // aapt resource value: 0x7f0100a1 - public const int autoCompleteTextViewStyle = 2130772129; - - // aapt resource value: 0x7f01003b - public const int autoSizeMaxTextSize = 2130772027; - - // aapt resource value: 0x7f01003a - public const int autoSizeMinTextSize = 2130772026; - - // aapt resource value: 0x7f010039 - public const int autoSizePresetSizes = 2130772025; - - // aapt resource value: 0x7f010038 - public const int autoSizeStepGranularity = 2130772024; - - // aapt resource value: 0x7f010037 - public const int autoSizeTextType = 2130772023; - - // aapt resource value: 0x7f010015 - public const int background = 2130771989; - - // aapt resource value: 0x7f010017 - public const int backgroundSplit = 2130771991; - - // aapt resource value: 0x7f010016 - public const int backgroundStacked = 2130771990; - - // aapt resource value: 0x7f0100fd - public const int backgroundTint = 2130772221; - - // aapt resource value: 0x7f0100fe - public const int backgroundTintMode = 2130772222; - - // aapt resource value: 0x7f0100bc - public const int barLength = 2130772156; - - // aapt resource value: 0x7f010128 - public const int behavior_autoHide = 2130772264; - - // aapt resource value: 0x7f010105 - public const int behavior_hideable = 2130772229; - - // aapt resource value: 0x7f010131 - public const int behavior_overlapTop = 2130772273; - - // aapt resource value: 0x7f010104 - public const int behavior_peekHeight = 2130772228; - - // aapt resource value: 0x7f010106 - public const int behavior_skipCollapsed = 2130772230; - - // aapt resource value: 0x7f010126 - public const int borderWidth = 2130772262; - - // aapt resource value: 0x7f010072 - public const int borderlessButtonStyle = 2130772082; - - // aapt resource value: 0x7f010120 - public const int bottomSheetDialogTheme = 2130772256; - - // aapt resource value: 0x7f010121 - public const int bottomSheetStyle = 2130772257; - - // aapt resource value: 0x7f01006f - public const int buttonBarButtonStyle = 2130772079; - - // aapt resource value: 0x7f01009f - public const int buttonBarNegativeButtonStyle = 2130772127; - - // aapt resource value: 0x7f0100a0 - public const int buttonBarNeutralButtonStyle = 2130772128; - - // aapt resource value: 0x7f01009e - public const int buttonBarPositiveButtonStyle = 2130772126; - - // aapt resource value: 0x7f01006e - public const int buttonBarStyle = 2130772078; - - // aapt resource value: 0x7f0100f2 - public const int buttonGravity = 2130772210; - - // aapt resource value: 0x7f01002a - public const int buttonPanelSideLayout = 2130772010; - - // aapt resource value: 0x7f0100a2 - public const int buttonStyle = 2130772130; - - // aapt resource value: 0x7f0100a3 - public const int buttonStyleSmall = 2130772131; - - // aapt resource value: 0x7f0100b4 - public const int buttonTint = 2130772148; - - // aapt resource value: 0x7f0100b5 - public const int buttonTintMode = 2130772149; - - // aapt resource value: 0x7f0100a4 - public const int checkboxStyle = 2130772132; - - // aapt resource value: 0x7f0100a5 - public const int checkedTextViewStyle = 2130772133; - - // aapt resource value: 0x7f0100d5 - public const int closeIcon = 2130772181; - - // aapt resource value: 0x7f010027 - public const int closeItemLayout = 2130772007; - - // aapt resource value: 0x7f0100f4 - public const int collapseContentDescription = 2130772212; - - // aapt resource value: 0x7f0100f3 - public const int collapseIcon = 2130772211; - - // aapt resource value: 0x7f010113 - public const int collapsedTitleGravity = 2130772243; - - // aapt resource value: 0x7f01010d - public const int collapsedTitleTextAppearance = 2130772237; - - // aapt resource value: 0x7f0100b6 - public const int color = 2130772150; - - // aapt resource value: 0x7f010091 - public const int colorAccent = 2130772113; - - // aapt resource value: 0x7f010098 - public const int colorBackgroundFloating = 2130772120; - - // aapt resource value: 0x7f010095 - public const int colorButtonNormal = 2130772117; - - // aapt resource value: 0x7f010093 - public const int colorControlActivated = 2130772115; - - // aapt resource value: 0x7f010094 - public const int colorControlHighlight = 2130772116; - - // aapt resource value: 0x7f010092 - public const int colorControlNormal = 2130772114; - - // aapt resource value: 0x7f0100b1 - public const int colorError = 2130772145; - - // aapt resource value: 0x7f01008f - public const int colorPrimary = 2130772111; - - // aapt resource value: 0x7f010090 - public const int colorPrimaryDark = 2130772112; - - // aapt resource value: 0x7f010096 - public const int colorSwitchThumbNormal = 2130772118; - - // aapt resource value: 0x7f0100da - public const int commitIcon = 2130772186; - - // aapt resource value: 0x7f0100c7 - public const int contentDescription = 2130772167; - - // aapt resource value: 0x7f010020 - public const int contentInsetEnd = 2130772000; - - // aapt resource value: 0x7f010024 - public const int contentInsetEndWithActions = 2130772004; - - // aapt resource value: 0x7f010021 - public const int contentInsetLeft = 2130772001; - - // aapt resource value: 0x7f010022 - public const int contentInsetRight = 2130772002; - - // aapt resource value: 0x7f01001f - public const int contentInsetStart = 2130771999; - - // aapt resource value: 0x7f010023 - public const int contentInsetStartWithNavigation = 2130772003; - - // aapt resource value: 0x7f01010e - public const int contentScrim = 2130772238; - - // aapt resource value: 0x7f010097 - public const int controlBackground = 2130772119; - - // aapt resource value: 0x7f010147 - public const int counterEnabled = 2130772295; - - // aapt resource value: 0x7f010148 - public const int counterMaxLength = 2130772296; - - // aapt resource value: 0x7f01014a - public const int counterOverflowTextAppearance = 2130772298; - - // aapt resource value: 0x7f010149 - public const int counterTextAppearance = 2130772297; - - // aapt resource value: 0x7f010018 - public const int customNavigationLayout = 2130771992; - - // aapt resource value: 0x7f0100d4 - public const int defaultQueryHint = 2130772180; - - // aapt resource value: 0x7f010067 - public const int dialogPreferredPadding = 2130772071; - - // aapt resource value: 0x7f010066 - public const int dialogTheme = 2130772070; - - // aapt resource value: 0x7f01000e - public const int displayOptions = 2130771982; - - // aapt resource value: 0x7f010014 - public const int divider = 2130771988; - - // aapt resource value: 0x7f010074 - public const int dividerHorizontal = 2130772084; - - // aapt resource value: 0x7f0100c0 - public const int dividerPadding = 2130772160; - - // aapt resource value: 0x7f010073 - public const int dividerVertical = 2130772083; - - // aapt resource value: 0x7f0100b8 - public const int drawableSize = 2130772152; - - // aapt resource value: 0x7f010009 - public const int drawerArrowStyle = 2130771977; - - // aapt resource value: 0x7f010086 - public const int dropDownListViewStyle = 2130772102; - - // aapt resource value: 0x7f01006a - public const int dropdownListPreferredItemHeight = 2130772074; - - // aapt resource value: 0x7f01007b - public const int editTextBackground = 2130772091; - - // aapt resource value: 0x7f01007a - public const int editTextColor = 2130772090; - - // aapt resource value: 0x7f0100a6 - public const int editTextStyle = 2130772134; - - // aapt resource value: 0x7f010025 - public const int elevation = 2130772005; - - // aapt resource value: 0x7f010145 - public const int errorEnabled = 2130772293; - - // aapt resource value: 0x7f010146 - public const int errorTextAppearance = 2130772294; - - // aapt resource value: 0x7f010029 - public const int expandActivityOverflowButtonDrawable = 2130772009; - - // aapt resource value: 0x7f0100ff - public const int expanded = 2130772223; - - // aapt resource value: 0x7f010114 - public const int expandedTitleGravity = 2130772244; - - // aapt resource value: 0x7f010107 - public const int expandedTitleMargin = 2130772231; - - // aapt resource value: 0x7f01010b - public const int expandedTitleMarginBottom = 2130772235; - - // aapt resource value: 0x7f01010a - public const int expandedTitleMarginEnd = 2130772234; - - // aapt resource value: 0x7f010108 - public const int expandedTitleMarginStart = 2130772232; - - // aapt resource value: 0x7f010109 - public const int expandedTitleMarginTop = 2130772233; - - // aapt resource value: 0x7f01010c - public const int expandedTitleTextAppearance = 2130772236; - - // aapt resource value: 0x7f010124 - public const int fabSize = 2130772260; - - // aapt resource value: 0x7f010004 - public const int fastScrollEnabled = 2130771972; - - // aapt resource value: 0x7f010007 - public const int fastScrollHorizontalThumbDrawable = 2130771975; - - // aapt resource value: 0x7f010008 - public const int fastScrollHorizontalTrackDrawable = 2130771976; - - // aapt resource value: 0x7f010005 - public const int fastScrollVerticalThumbDrawable = 2130771973; - - // aapt resource value: 0x7f010006 - public const int fastScrollVerticalTrackDrawable = 2130771974; - - // aapt resource value: 0x7f010158 - public const int font = 2130772312; - - // aapt resource value: 0x7f01003c - public const int fontFamily = 2130772028; - - // aapt resource value: 0x7f010151 - public const int fontProviderAuthority = 2130772305; - - // aapt resource value: 0x7f010154 - public const int fontProviderCerts = 2130772308; - - // aapt resource value: 0x7f010155 - public const int fontProviderFetchStrategy = 2130772309; - - // aapt resource value: 0x7f010156 - public const int fontProviderFetchTimeout = 2130772310; - - // aapt resource value: 0x7f010152 - public const int fontProviderPackage = 2130772306; - - // aapt resource value: 0x7f010153 - public const int fontProviderQuery = 2130772307; - - // aapt resource value: 0x7f010157 - public const int fontStyle = 2130772311; - - // aapt resource value: 0x7f010159 - public const int fontWeight = 2130772313; - - // aapt resource value: 0x7f010129 - public const int foregroundInsidePadding = 2130772265; - - // aapt resource value: 0x7f0100b9 - public const int gapBetweenBars = 2130772153; - - // aapt resource value: 0x7f0100d6 - public const int goIcon = 2130772182; - - // aapt resource value: 0x7f01012f - public const int headerLayout = 2130772271; - - // aapt resource value: 0x7f01000a - public const int height = 2130771978; - - // aapt resource value: 0x7f01001e - public const int hideOnContentScroll = 2130771998; - - // aapt resource value: 0x7f01014b - public const int hintAnimationEnabled = 2130772299; - - // aapt resource value: 0x7f010144 - public const int hintEnabled = 2130772292; - - // aapt resource value: 0x7f010143 - public const int hintTextAppearance = 2130772291; - - // aapt resource value: 0x7f01006c - public const int homeAsUpIndicator = 2130772076; - - // aapt resource value: 0x7f010019 - public const int homeLayout = 2130771993; - - // aapt resource value: 0x7f010012 - public const int icon = 2130771986; - - // aapt resource value: 0x7f0100c9 - public const int iconTint = 2130772169; - - // aapt resource value: 0x7f0100ca - public const int iconTintMode = 2130772170; - - // aapt resource value: 0x7f0100d2 - public const int iconifiedByDefault = 2130772178; - - // aapt resource value: 0x7f01007c - public const int imageButtonStyle = 2130772092; - - // aapt resource value: 0x7f01001b - public const int indeterminateProgressStyle = 2130771995; - - // aapt resource value: 0x7f010028 - public const int initialActivityCount = 2130772008; - - // aapt resource value: 0x7f010130 - public const int insetForeground = 2130772272; - - // aapt resource value: 0x7f01000b - public const int isLightTheme = 2130771979; - - // aapt resource value: 0x7f01012d - public const int itemBackground = 2130772269; - - // aapt resource value: 0x7f01012b - public const int itemIconTint = 2130772267; - - // aapt resource value: 0x7f01001d - public const int itemPadding = 2130771997; - - // aapt resource value: 0x7f01012e - public const int itemTextAppearance = 2130772270; - - // aapt resource value: 0x7f01012c - public const int itemTextColor = 2130772268; - - // aapt resource value: 0x7f010118 - public const int keylines = 2130772248; - - // aapt resource value: 0x7f0100d1 - public const int layout = 2130772177; - - // aapt resource value: 0x7f010000 - public const int layoutManager = 2130771968; - - // aapt resource value: 0x7f01011b - public const int layout_anchor = 2130772251; - - // aapt resource value: 0x7f01011d - public const int layout_anchorGravity = 2130772253; - - // aapt resource value: 0x7f01011a - public const int layout_behavior = 2130772250; - - // aapt resource value: 0x7f010116 - public const int layout_collapseMode = 2130772246; - - // aapt resource value: 0x7f010117 - public const int layout_collapseParallaxMultiplier = 2130772247; - - // aapt resource value: 0x7f01011f - public const int layout_dodgeInsetEdges = 2130772255; - - // aapt resource value: 0x7f01011e - public const int layout_insetEdge = 2130772254; - - // aapt resource value: 0x7f01011c - public const int layout_keyline = 2130772252; - - // aapt resource value: 0x7f010102 - public const int layout_scrollFlags = 2130772226; - - // aapt resource value: 0x7f010103 - public const int layout_scrollInterpolator = 2130772227; - - // aapt resource value: 0x7f01008e - public const int listChoiceBackgroundIndicator = 2130772110; - - // aapt resource value: 0x7f010068 - public const int listDividerAlertDialog = 2130772072; - - // aapt resource value: 0x7f01002e - public const int listItemLayout = 2130772014; - - // aapt resource value: 0x7f01002b - public const int listLayout = 2130772011; - - // aapt resource value: 0x7f0100ae - public const int listMenuViewStyle = 2130772142; - - // aapt resource value: 0x7f010087 - public const int listPopupWindowStyle = 2130772103; - - // aapt resource value: 0x7f010081 - public const int listPreferredItemHeight = 2130772097; - - // aapt resource value: 0x7f010083 - public const int listPreferredItemHeightLarge = 2130772099; - - // aapt resource value: 0x7f010082 - public const int listPreferredItemHeightSmall = 2130772098; - - // aapt resource value: 0x7f010084 - public const int listPreferredItemPaddingLeft = 2130772100; - - // aapt resource value: 0x7f010085 - public const int listPreferredItemPaddingRight = 2130772101; - - // aapt resource value: 0x7f010013 - public const int logo = 2130771987; - - // aapt resource value: 0x7f0100f7 - public const int logoDescription = 2130772215; - - // aapt resource value: 0x7f010132 - public const int maxActionInlineWidth = 2130772274; - - // aapt resource value: 0x7f0100f1 - public const int maxButtonHeight = 2130772209; - - // aapt resource value: 0x7f0100be - public const int measureWithLargestChild = 2130772158; - - // aapt resource value: 0x7f01012a - public const int menu = 2130772266; - - // aapt resource value: 0x7f01002c - public const int multiChoiceItemLayout = 2130772012; - - // aapt resource value: 0x7f0100f6 - public const int navigationContentDescription = 2130772214; - - // aapt resource value: 0x7f0100f5 - public const int navigationIcon = 2130772213; - - // aapt resource value: 0x7f01000d - public const int navigationMode = 2130771981; - - // aapt resource value: 0x7f0100c2 - public const int numericModifiers = 2130772162; - - // aapt resource value: 0x7f0100cd - public const int overlapAnchor = 2130772173; - - // aapt resource value: 0x7f0100cf - public const int paddingBottomNoButtons = 2130772175; - - // aapt resource value: 0x7f0100fb - public const int paddingEnd = 2130772219; - - // aapt resource value: 0x7f0100fa - public const int paddingStart = 2130772218; - - // aapt resource value: 0x7f0100d0 - public const int paddingTopNoTitle = 2130772176; - - // aapt resource value: 0x7f01008b - public const int panelBackground = 2130772107; - - // aapt resource value: 0x7f01008d - public const int panelMenuListTheme = 2130772109; - - // aapt resource value: 0x7f01008c - public const int panelMenuListWidth = 2130772108; - - // aapt resource value: 0x7f01014e - public const int passwordToggleContentDescription = 2130772302; - - // aapt resource value: 0x7f01014d - public const int passwordToggleDrawable = 2130772301; - - // aapt resource value: 0x7f01014c - public const int passwordToggleEnabled = 2130772300; - - // aapt resource value: 0x7f01014f - public const int passwordToggleTint = 2130772303; - - // aapt resource value: 0x7f010150 - public const int passwordToggleTintMode = 2130772304; - - // aapt resource value: 0x7f010078 - public const int popupMenuStyle = 2130772088; - - // aapt resource value: 0x7f010026 - public const int popupTheme = 2130772006; - - // aapt resource value: 0x7f010079 - public const int popupWindowStyle = 2130772089; - - // aapt resource value: 0x7f0100cb - public const int preserveIconSpacing = 2130772171; - - // aapt resource value: 0x7f010125 - public const int pressedTranslationZ = 2130772261; - - // aapt resource value: 0x7f01001c - public const int progressBarPadding = 2130771996; - - // aapt resource value: 0x7f01001a - public const int progressBarStyle = 2130771994; - - // aapt resource value: 0x7f0100dc - public const int queryBackground = 2130772188; - - // aapt resource value: 0x7f0100d3 - public const int queryHint = 2130772179; - - // aapt resource value: 0x7f0100a7 - public const int radioButtonStyle = 2130772135; - - // aapt resource value: 0x7f0100a8 - public const int ratingBarStyle = 2130772136; - - // aapt resource value: 0x7f0100a9 - public const int ratingBarStyleIndicator = 2130772137; - - // aapt resource value: 0x7f0100aa - public const int ratingBarStyleSmall = 2130772138; - - // aapt resource value: 0x7f010002 - public const int reverseLayout = 2130771970; - - // aapt resource value: 0x7f010123 - public const int rippleColor = 2130772259; - - // aapt resource value: 0x7f010112 - public const int scrimAnimationDuration = 2130772242; - - // aapt resource value: 0x7f010111 - public const int scrimVisibleHeightTrigger = 2130772241; - - // aapt resource value: 0x7f0100d8 - public const int searchHintIcon = 2130772184; - - // aapt resource value: 0x7f0100d7 - public const int searchIcon = 2130772183; - - // aapt resource value: 0x7f010080 - public const int searchViewStyle = 2130772096; - - // aapt resource value: 0x7f0100ab - public const int seekBarStyle = 2130772139; - - // aapt resource value: 0x7f010070 - public const int selectableItemBackground = 2130772080; - - // aapt resource value: 0x7f010071 - public const int selectableItemBackgroundBorderless = 2130772081; - - // aapt resource value: 0x7f0100c3 - public const int showAsAction = 2130772163; - - // aapt resource value: 0x7f0100bf - public const int showDividers = 2130772159; - - // aapt resource value: 0x7f0100e8 - public const int showText = 2130772200; - - // aapt resource value: 0x7f01002f - public const int showTitle = 2130772015; - - // aapt resource value: 0x7f01002d - public const int singleChoiceItemLayout = 2130772013; - - // aapt resource value: 0x7f010001 - public const int spanCount = 2130771969; - - // aapt resource value: 0x7f0100b7 - public const int spinBars = 2130772151; - - // aapt resource value: 0x7f01006b - public const int spinnerDropDownItemStyle = 2130772075; - - // aapt resource value: 0x7f0100ac - public const int spinnerStyle = 2130772140; - - // aapt resource value: 0x7f0100e7 - public const int splitTrack = 2130772199; - - // aapt resource value: 0x7f010030 - public const int srcCompat = 2130772016; - - // aapt resource value: 0x7f010003 - public const int stackFromEnd = 2130771971; - - // aapt resource value: 0x7f0100ce - public const int state_above_anchor = 2130772174; - - // aapt resource value: 0x7f010100 - public const int state_collapsed = 2130772224; - - // aapt resource value: 0x7f010101 - public const int state_collapsible = 2130772225; - - // aapt resource value: 0x7f010119 - public const int statusBarBackground = 2130772249; - - // aapt resource value: 0x7f01010f - public const int statusBarScrim = 2130772239; - - // aapt resource value: 0x7f0100cc - public const int subMenuArrow = 2130772172; - - // aapt resource value: 0x7f0100dd - public const int submitBackground = 2130772189; - - // aapt resource value: 0x7f01000f - public const int subtitle = 2130771983; - - // aapt resource value: 0x7f0100ea - public const int subtitleTextAppearance = 2130772202; - - // aapt resource value: 0x7f0100f9 - public const int subtitleTextColor = 2130772217; - - // aapt resource value: 0x7f010011 - public const int subtitleTextStyle = 2130771985; - - // aapt resource value: 0x7f0100db - public const int suggestionRowLayout = 2130772187; - - // aapt resource value: 0x7f0100e5 - public const int switchMinWidth = 2130772197; - - // aapt resource value: 0x7f0100e6 - public const int switchPadding = 2130772198; - - // aapt resource value: 0x7f0100ad - public const int switchStyle = 2130772141; - - // aapt resource value: 0x7f0100e4 - public const int switchTextAppearance = 2130772196; - - // aapt resource value: 0x7f010136 - public const int tabBackground = 2130772278; - - // aapt resource value: 0x7f010135 - public const int tabContentStart = 2130772277; - - // aapt resource value: 0x7f010138 - public const int tabGravity = 2130772280; - - // aapt resource value: 0x7f010133 - public const int tabIndicatorColor = 2130772275; - - // aapt resource value: 0x7f010134 - public const int tabIndicatorHeight = 2130772276; - - // aapt resource value: 0x7f01013a - public const int tabMaxWidth = 2130772282; - - // aapt resource value: 0x7f010139 - public const int tabMinWidth = 2130772281; - - // aapt resource value: 0x7f010137 - public const int tabMode = 2130772279; - - // aapt resource value: 0x7f010142 - public const int tabPadding = 2130772290; - - // aapt resource value: 0x7f010141 - public const int tabPaddingBottom = 2130772289; - - // aapt resource value: 0x7f010140 - public const int tabPaddingEnd = 2130772288; - - // aapt resource value: 0x7f01013e - public const int tabPaddingStart = 2130772286; - - // aapt resource value: 0x7f01013f - public const int tabPaddingTop = 2130772287; - - // aapt resource value: 0x7f01013d - public const int tabSelectedTextColor = 2130772285; - - // aapt resource value: 0x7f01013b - public const int tabTextAppearance = 2130772283; - - // aapt resource value: 0x7f01013c - public const int tabTextColor = 2130772284; - - // aapt resource value: 0x7f010036 - public const int textAllCaps = 2130772022; - - // aapt resource value: 0x7f010063 - public const int textAppearanceLargePopupMenu = 2130772067; - - // aapt resource value: 0x7f010088 - public const int textAppearanceListItem = 2130772104; - - // aapt resource value: 0x7f010089 - public const int textAppearanceListItemSecondary = 2130772105; - - // aapt resource value: 0x7f01008a - public const int textAppearanceListItemSmall = 2130772106; - - // aapt resource value: 0x7f010065 - public const int textAppearancePopupMenuHeader = 2130772069; - - // aapt resource value: 0x7f01007e - public const int textAppearanceSearchResultSubtitle = 2130772094; - - // aapt resource value: 0x7f01007d - public const int textAppearanceSearchResultTitle = 2130772093; - - // aapt resource value: 0x7f010064 - public const int textAppearanceSmallPopupMenu = 2130772068; - - // aapt resource value: 0x7f01009d - public const int textColorAlertDialogListItem = 2130772125; - - // aapt resource value: 0x7f010122 - public const int textColorError = 2130772258; - - // aapt resource value: 0x7f01007f - public const int textColorSearchUrl = 2130772095; - - // aapt resource value: 0x7f0100fc - public const int theme = 2130772220; - - // aapt resource value: 0x7f0100bd - public const int thickness = 2130772157; - - // aapt resource value: 0x7f0100e3 - public const int thumbTextPadding = 2130772195; - - // aapt resource value: 0x7f0100de - public const int thumbTint = 2130772190; - - // aapt resource value: 0x7f0100df - public const int thumbTintMode = 2130772191; - - // aapt resource value: 0x7f010033 - public const int tickMark = 2130772019; - - // aapt resource value: 0x7f010034 - public const int tickMarkTint = 2130772020; - - // aapt resource value: 0x7f010035 - public const int tickMarkTintMode = 2130772021; - - // aapt resource value: 0x7f010031 - public const int tint = 2130772017; - - // aapt resource value: 0x7f010032 - public const int tintMode = 2130772018; - - // aapt resource value: 0x7f01000c - public const int title = 2130771980; - - // aapt resource value: 0x7f010115 - public const int titleEnabled = 2130772245; - - // aapt resource value: 0x7f0100eb - public const int titleMargin = 2130772203; - - // aapt resource value: 0x7f0100ef - public const int titleMarginBottom = 2130772207; - - // aapt resource value: 0x7f0100ed - public const int titleMarginEnd = 2130772205; - - // aapt resource value: 0x7f0100ec - public const int titleMarginStart = 2130772204; - - // aapt resource value: 0x7f0100ee - public const int titleMarginTop = 2130772206; - - // aapt resource value: 0x7f0100f0 - public const int titleMargins = 2130772208; - - // aapt resource value: 0x7f0100e9 - public const int titleTextAppearance = 2130772201; - - // aapt resource value: 0x7f0100f8 - public const int titleTextColor = 2130772216; - - // aapt resource value: 0x7f010010 - public const int titleTextStyle = 2130771984; - - // aapt resource value: 0x7f010110 - public const int toolbarId = 2130772240; - - // aapt resource value: 0x7f010077 - public const int toolbarNavigationButtonStyle = 2130772087; - - // aapt resource value: 0x7f010076 - public const int toolbarStyle = 2130772086; - - // aapt resource value: 0x7f0100b0 - public const int tooltipForegroundColor = 2130772144; - - // aapt resource value: 0x7f0100af - public const int tooltipFrameBackground = 2130772143; - - // aapt resource value: 0x7f0100c8 - public const int tooltipText = 2130772168; - - // aapt resource value: 0x7f0100e0 - public const int track = 2130772192; - - // aapt resource value: 0x7f0100e1 - public const int trackTint = 2130772193; - - // aapt resource value: 0x7f0100e2 - public const int trackTintMode = 2130772194; - - // aapt resource value: 0x7f010127 - public const int useCompatPadding = 2130772263; - - // aapt resource value: 0x7f0100d9 - public const int voiceIcon = 2130772185; - - // aapt resource value: 0x7f01003d - public const int windowActionBar = 2130772029; - - // aapt resource value: 0x7f01003f - public const int windowActionBarOverlay = 2130772031; - - // aapt resource value: 0x7f010040 - public const int windowActionModeOverlay = 2130772032; - - // aapt resource value: 0x7f010044 - public const int windowFixedHeightMajor = 2130772036; - - // aapt resource value: 0x7f010042 - public const int windowFixedHeightMinor = 2130772034; - - // aapt resource value: 0x7f010041 - public const int windowFixedWidthMajor = 2130772033; - - // aapt resource value: 0x7f010043 - public const int windowFixedWidthMinor = 2130772035; - - // aapt resource value: 0x7f010045 - public const int windowMinWidthMajor = 2130772037; - - // aapt resource value: 0x7f010046 - public const int windowMinWidthMinor = 2130772038; - - // aapt resource value: 0x7f01003e - public const int windowNoTitle = 2130772030; - static Attribute() { global::Android.Runtime.ResourceIdManager.UpdateIdValues(); @@ -1156,333 +41,20 @@ namespace osu.Android } } - public partial class Boolean - { - - // aapt resource value: 0x7f0b0000 - public const int abc_action_bar_embed_tabs = 2131427328; - - // aapt resource value: 0x7f0b0001 - public const int abc_allow_stacked_button_bar = 2131427329; - - // aapt resource value: 0x7f0b0002 - public const int abc_config_actionMenuItemAllCaps = 2131427330; - - // aapt resource value: 0x7f0b0003 - public const int abc_config_closeDialogWhenTouchOutside = 2131427331; - - // aapt resource value: 0x7f0b0004 - public const int abc_config_showMenuShortcutsWhenKeyboardPresent = 2131427332; - - static Boolean() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Boolean() - { - } - } - public partial class Color { - // aapt resource value: 0x7f0c004b - public const int abc_background_cache_hint_selector_material_dark = 2131492939; + // aapt resource value: 0x7f030002 + public const int colorAccent = 2130903042; - // aapt resource value: 0x7f0c004c - public const int abc_background_cache_hint_selector_material_light = 2131492940; + // aapt resource value: 0x7f030000 + public const int colorPrimary = 2130903040; - // aapt resource value: 0x7f0c004d - public const int abc_btn_colored_borderless_text_material = 2131492941; + // aapt resource value: 0x7f030001 + public const int colorPrimaryDark = 2130903041; - // aapt resource value: 0x7f0c004e - public const int abc_btn_colored_text_material = 2131492942; - - // aapt resource value: 0x7f0c004f - public const int abc_color_highlight_material = 2131492943; - - // aapt resource value: 0x7f0c0050 - public const int abc_hint_foreground_material_dark = 2131492944; - - // aapt resource value: 0x7f0c0051 - public const int abc_hint_foreground_material_light = 2131492945; - - // aapt resource value: 0x7f0c0000 - public const int abc_input_method_navigation_guard = 2131492864; - - // aapt resource value: 0x7f0c0052 - public const int abc_primary_text_disable_only_material_dark = 2131492946; - - // aapt resource value: 0x7f0c0053 - public const int abc_primary_text_disable_only_material_light = 2131492947; - - // aapt resource value: 0x7f0c0054 - public const int abc_primary_text_material_dark = 2131492948; - - // aapt resource value: 0x7f0c0055 - public const int abc_primary_text_material_light = 2131492949; - - // aapt resource value: 0x7f0c0056 - public const int abc_search_url_text = 2131492950; - - // aapt resource value: 0x7f0c0001 - public const int abc_search_url_text_normal = 2131492865; - - // aapt resource value: 0x7f0c0002 - public const int abc_search_url_text_pressed = 2131492866; - - // aapt resource value: 0x7f0c0003 - public const int abc_search_url_text_selected = 2131492867; - - // aapt resource value: 0x7f0c0057 - public const int abc_secondary_text_material_dark = 2131492951; - - // aapt resource value: 0x7f0c0058 - public const int abc_secondary_text_material_light = 2131492952; - - // aapt resource value: 0x7f0c0059 - public const int abc_tint_btn_checkable = 2131492953; - - // aapt resource value: 0x7f0c005a - public const int abc_tint_default = 2131492954; - - // aapt resource value: 0x7f0c005b - public const int abc_tint_edittext = 2131492955; - - // aapt resource value: 0x7f0c005c - public const int abc_tint_seek_thumb = 2131492956; - - // aapt resource value: 0x7f0c005d - public const int abc_tint_spinner = 2131492957; - - // aapt resource value: 0x7f0c005e - public const int abc_tint_switch_track = 2131492958; - - // aapt resource value: 0x7f0c0004 - public const int accent_material_dark = 2131492868; - - // aapt resource value: 0x7f0c0005 - public const int accent_material_light = 2131492869; - - // aapt resource value: 0x7f0c0006 - public const int background_floating_material_dark = 2131492870; - - // aapt resource value: 0x7f0c0007 - public const int background_floating_material_light = 2131492871; - - // aapt resource value: 0x7f0c0008 - public const int background_material_dark = 2131492872; - - // aapt resource value: 0x7f0c0009 - public const int background_material_light = 2131492873; - - // aapt resource value: 0x7f0c000a - public const int bright_foreground_disabled_material_dark = 2131492874; - - // aapt resource value: 0x7f0c000b - public const int bright_foreground_disabled_material_light = 2131492875; - - // aapt resource value: 0x7f0c000c - public const int bright_foreground_inverse_material_dark = 2131492876; - - // aapt resource value: 0x7f0c000d - public const int bright_foreground_inverse_material_light = 2131492877; - - // aapt resource value: 0x7f0c000e - public const int bright_foreground_material_dark = 2131492878; - - // aapt resource value: 0x7f0c000f - public const int bright_foreground_material_light = 2131492879; - - // aapt resource value: 0x7f0c0010 - public const int button_material_dark = 2131492880; - - // aapt resource value: 0x7f0c0011 - public const int button_material_light = 2131492881; - - // aapt resource value: 0x7f0c0049 - public const int colorAccent = 2131492937; - - // aapt resource value: 0x7f0c0047 - public const int colorPrimary = 2131492935; - - // aapt resource value: 0x7f0c0048 - public const int colorPrimaryDark = 2131492936; - - // aapt resource value: 0x7f0c003c - public const int design_bottom_navigation_shadow_color = 2131492924; - - // aapt resource value: 0x7f0c005f - public const int design_error = 2131492959; - - // aapt resource value: 0x7f0c003d - public const int design_fab_shadow_end_color = 2131492925; - - // aapt resource value: 0x7f0c003e - public const int design_fab_shadow_mid_color = 2131492926; - - // aapt resource value: 0x7f0c003f - public const int design_fab_shadow_start_color = 2131492927; - - // aapt resource value: 0x7f0c0040 - public const int design_fab_stroke_end_inner_color = 2131492928; - - // aapt resource value: 0x7f0c0041 - public const int design_fab_stroke_end_outer_color = 2131492929; - - // aapt resource value: 0x7f0c0042 - public const int design_fab_stroke_top_inner_color = 2131492930; - - // aapt resource value: 0x7f0c0043 - public const int design_fab_stroke_top_outer_color = 2131492931; - - // aapt resource value: 0x7f0c0044 - public const int design_snackbar_background_color = 2131492932; - - // aapt resource value: 0x7f0c0060 - public const int design_tint_password_toggle = 2131492960; - - // aapt resource value: 0x7f0c0012 - public const int dim_foreground_disabled_material_dark = 2131492882; - - // aapt resource value: 0x7f0c0013 - public const int dim_foreground_disabled_material_light = 2131492883; - - // aapt resource value: 0x7f0c0014 - public const int dim_foreground_material_dark = 2131492884; - - // aapt resource value: 0x7f0c0015 - public const int dim_foreground_material_light = 2131492885; - - // aapt resource value: 0x7f0c0016 - public const int error_color_material = 2131492886; - - // aapt resource value: 0x7f0c0017 - public const int foreground_material_dark = 2131492887; - - // aapt resource value: 0x7f0c0018 - public const int foreground_material_light = 2131492888; - - // aapt resource value: 0x7f0c0019 - public const int highlighted_text_material_dark = 2131492889; - - // aapt resource value: 0x7f0c001a - public const int highlighted_text_material_light = 2131492890; - - // aapt resource value: 0x7f0c004a - public const int ic_launcher_background = 2131492938; - - // aapt resource value: 0x7f0c001b - public const int material_blue_grey_800 = 2131492891; - - // aapt resource value: 0x7f0c001c - public const int material_blue_grey_900 = 2131492892; - - // aapt resource value: 0x7f0c001d - public const int material_blue_grey_950 = 2131492893; - - // aapt resource value: 0x7f0c001e - public const int material_deep_teal_200 = 2131492894; - - // aapt resource value: 0x7f0c001f - public const int material_deep_teal_500 = 2131492895; - - // aapt resource value: 0x7f0c0020 - public const int material_grey_100 = 2131492896; - - // aapt resource value: 0x7f0c0021 - public const int material_grey_300 = 2131492897; - - // aapt resource value: 0x7f0c0022 - public const int material_grey_50 = 2131492898; - - // aapt resource value: 0x7f0c0023 - public const int material_grey_600 = 2131492899; - - // aapt resource value: 0x7f0c0024 - public const int material_grey_800 = 2131492900; - - // aapt resource value: 0x7f0c0025 - public const int material_grey_850 = 2131492901; - - // aapt resource value: 0x7f0c0026 - public const int material_grey_900 = 2131492902; - - // aapt resource value: 0x7f0c0045 - public const int notification_action_color_filter = 2131492933; - - // aapt resource value: 0x7f0c0046 - public const int notification_icon_bg_color = 2131492934; - - // aapt resource value: 0x7f0c003b - public const int notification_material_background_media_default_color = 2131492923; - - // aapt resource value: 0x7f0c0027 - public const int primary_dark_material_dark = 2131492903; - - // aapt resource value: 0x7f0c0028 - public const int primary_dark_material_light = 2131492904; - - // aapt resource value: 0x7f0c0029 - public const int primary_material_dark = 2131492905; - - // aapt resource value: 0x7f0c002a - public const int primary_material_light = 2131492906; - - // aapt resource value: 0x7f0c002b - public const int primary_text_default_material_dark = 2131492907; - - // aapt resource value: 0x7f0c002c - public const int primary_text_default_material_light = 2131492908; - - // aapt resource value: 0x7f0c002d - public const int primary_text_disabled_material_dark = 2131492909; - - // aapt resource value: 0x7f0c002e - public const int primary_text_disabled_material_light = 2131492910; - - // aapt resource value: 0x7f0c002f - public const int ripple_material_dark = 2131492911; - - // aapt resource value: 0x7f0c0030 - public const int ripple_material_light = 2131492912; - - // aapt resource value: 0x7f0c0031 - public const int secondary_text_default_material_dark = 2131492913; - - // aapt resource value: 0x7f0c0032 - public const int secondary_text_default_material_light = 2131492914; - - // aapt resource value: 0x7f0c0033 - public const int secondary_text_disabled_material_dark = 2131492915; - - // aapt resource value: 0x7f0c0034 - public const int secondary_text_disabled_material_light = 2131492916; - - // aapt resource value: 0x7f0c0035 - public const int switch_thumb_disabled_material_dark = 2131492917; - - // aapt resource value: 0x7f0c0036 - public const int switch_thumb_disabled_material_light = 2131492918; - - // aapt resource value: 0x7f0c0061 - public const int switch_thumb_material_dark = 2131492961; - - // aapt resource value: 0x7f0c0062 - public const int switch_thumb_material_light = 2131492962; - - // aapt resource value: 0x7f0c0037 - public const int switch_thumb_normal_material_dark = 2131492919; - - // aapt resource value: 0x7f0c0038 - public const int switch_thumb_normal_material_light = 2131492920; - - // aapt resource value: 0x7f0c0039 - public const int tooltip_background_dark = 2131492921; - - // aapt resource value: 0x7f0c003a - public const int tooltip_background_light = 2131492922; + // aapt resource value: 0x7f030003 + public const int ic_launcher_background = 2130903043; static Color() { @@ -1494,1624 +66,17 @@ namespace osu.Android } } - public partial class Dimension - { - - // aapt resource value: 0x7f070012 - public const int abc_action_bar_content_inset_material = 2131165202; - - // aapt resource value: 0x7f070013 - public const int abc_action_bar_content_inset_with_nav = 2131165203; - - // aapt resource value: 0x7f070007 - public const int abc_action_bar_default_height_material = 2131165191; - - // aapt resource value: 0x7f070014 - public const int abc_action_bar_default_padding_end_material = 2131165204; - - // aapt resource value: 0x7f070015 - public const int abc_action_bar_default_padding_start_material = 2131165205; - - // aapt resource value: 0x7f070017 - public const int abc_action_bar_elevation_material = 2131165207; - - // aapt resource value: 0x7f070018 - public const int abc_action_bar_icon_vertical_padding_material = 2131165208; - - // aapt resource value: 0x7f070019 - public const int abc_action_bar_overflow_padding_end_material = 2131165209; - - // aapt resource value: 0x7f07001a - public const int abc_action_bar_overflow_padding_start_material = 2131165210; - - // aapt resource value: 0x7f070008 - public const int abc_action_bar_progress_bar_size = 2131165192; - - // aapt resource value: 0x7f07001b - public const int abc_action_bar_stacked_max_height = 2131165211; - - // aapt resource value: 0x7f07001c - public const int abc_action_bar_stacked_tab_max_width = 2131165212; - - // aapt resource value: 0x7f07001d - public const int abc_action_bar_subtitle_bottom_margin_material = 2131165213; - - // aapt resource value: 0x7f07001e - public const int abc_action_bar_subtitle_top_margin_material = 2131165214; - - // aapt resource value: 0x7f07001f - public const int abc_action_button_min_height_material = 2131165215; - - // aapt resource value: 0x7f070020 - public const int abc_action_button_min_width_material = 2131165216; - - // aapt resource value: 0x7f070021 - public const int abc_action_button_min_width_overflow_material = 2131165217; - - // aapt resource value: 0x7f070006 - public const int abc_alert_dialog_button_bar_height = 2131165190; - - // aapt resource value: 0x7f070022 - public const int abc_button_inset_horizontal_material = 2131165218; - - // aapt resource value: 0x7f070023 - public const int abc_button_inset_vertical_material = 2131165219; - - // aapt resource value: 0x7f070024 - public const int abc_button_padding_horizontal_material = 2131165220; - - // aapt resource value: 0x7f070025 - public const int abc_button_padding_vertical_material = 2131165221; - - // aapt resource value: 0x7f070026 - public const int abc_cascading_menus_min_smallest_width = 2131165222; - - // aapt resource value: 0x7f07000b - public const int abc_config_prefDialogWidth = 2131165195; - - // aapt resource value: 0x7f070027 - public const int abc_control_corner_material = 2131165223; - - // aapt resource value: 0x7f070028 - public const int abc_control_inset_material = 2131165224; - - // aapt resource value: 0x7f070029 - public const int abc_control_padding_material = 2131165225; - - // aapt resource value: 0x7f07000c - public const int abc_dialog_fixed_height_major = 2131165196; - - // aapt resource value: 0x7f07000d - public const int abc_dialog_fixed_height_minor = 2131165197; - - // aapt resource value: 0x7f07000e - public const int abc_dialog_fixed_width_major = 2131165198; - - // aapt resource value: 0x7f07000f - public const int abc_dialog_fixed_width_minor = 2131165199; - - // aapt resource value: 0x7f07002a - public const int abc_dialog_list_padding_bottom_no_buttons = 2131165226; - - // aapt resource value: 0x7f07002b - public const int abc_dialog_list_padding_top_no_title = 2131165227; - - // aapt resource value: 0x7f070010 - public const int abc_dialog_min_width_major = 2131165200; - - // aapt resource value: 0x7f070011 - public const int abc_dialog_min_width_minor = 2131165201; - - // aapt resource value: 0x7f07002c - public const int abc_dialog_padding_material = 2131165228; - - // aapt resource value: 0x7f07002d - public const int abc_dialog_padding_top_material = 2131165229; - - // aapt resource value: 0x7f07002e - public const int abc_dialog_title_divider_material = 2131165230; - - // aapt resource value: 0x7f07002f - public const int abc_disabled_alpha_material_dark = 2131165231; - - // aapt resource value: 0x7f070030 - public const int abc_disabled_alpha_material_light = 2131165232; - - // aapt resource value: 0x7f070031 - public const int abc_dropdownitem_icon_width = 2131165233; - - // aapt resource value: 0x7f070032 - public const int abc_dropdownitem_text_padding_left = 2131165234; - - // aapt resource value: 0x7f070033 - public const int abc_dropdownitem_text_padding_right = 2131165235; - - // aapt resource value: 0x7f070034 - public const int abc_edit_text_inset_bottom_material = 2131165236; - - // aapt resource value: 0x7f070035 - public const int abc_edit_text_inset_horizontal_material = 2131165237; - - // aapt resource value: 0x7f070036 - public const int abc_edit_text_inset_top_material = 2131165238; - - // aapt resource value: 0x7f070037 - public const int abc_floating_window_z = 2131165239; - - // aapt resource value: 0x7f070038 - public const int abc_list_item_padding_horizontal_material = 2131165240; - - // aapt resource value: 0x7f070039 - public const int abc_panel_menu_list_width = 2131165241; - - // aapt resource value: 0x7f07003a - public const int abc_progress_bar_height_material = 2131165242; - - // aapt resource value: 0x7f07003b - public const int abc_search_view_preferred_height = 2131165243; - - // aapt resource value: 0x7f07003c - public const int abc_search_view_preferred_width = 2131165244; - - // aapt resource value: 0x7f07003d - public const int abc_seekbar_track_background_height_material = 2131165245; - - // aapt resource value: 0x7f07003e - public const int abc_seekbar_track_progress_height_material = 2131165246; - - // aapt resource value: 0x7f07003f - public const int abc_select_dialog_padding_start_material = 2131165247; - - // aapt resource value: 0x7f070016 - public const int abc_switch_padding = 2131165206; - - // aapt resource value: 0x7f070040 - public const int abc_text_size_body_1_material = 2131165248; - - // aapt resource value: 0x7f070041 - public const int abc_text_size_body_2_material = 2131165249; - - // aapt resource value: 0x7f070042 - public const int abc_text_size_button_material = 2131165250; - - // aapt resource value: 0x7f070043 - public const int abc_text_size_caption_material = 2131165251; - - // aapt resource value: 0x7f070044 - public const int abc_text_size_display_1_material = 2131165252; - - // aapt resource value: 0x7f070045 - public const int abc_text_size_display_2_material = 2131165253; - - // aapt resource value: 0x7f070046 - public const int abc_text_size_display_3_material = 2131165254; - - // aapt resource value: 0x7f070047 - public const int abc_text_size_display_4_material = 2131165255; - - // aapt resource value: 0x7f070048 - public const int abc_text_size_headline_material = 2131165256; - - // aapt resource value: 0x7f070049 - public const int abc_text_size_large_material = 2131165257; - - // aapt resource value: 0x7f07004a - public const int abc_text_size_medium_material = 2131165258; - - // aapt resource value: 0x7f07004b - public const int abc_text_size_menu_header_material = 2131165259; - - // aapt resource value: 0x7f07004c - public const int abc_text_size_menu_material = 2131165260; - - // aapt resource value: 0x7f07004d - public const int abc_text_size_small_material = 2131165261; - - // aapt resource value: 0x7f07004e - public const int abc_text_size_subhead_material = 2131165262; - - // aapt resource value: 0x7f070009 - public const int abc_text_size_subtitle_material_toolbar = 2131165193; - - // aapt resource value: 0x7f07004f - public const int abc_text_size_title_material = 2131165263; - - // aapt resource value: 0x7f07000a - public const int abc_text_size_title_material_toolbar = 2131165194; - - // aapt resource value: 0x7f07008b - public const int compat_button_inset_horizontal_material = 2131165323; - - // aapt resource value: 0x7f07008c - public const int compat_button_inset_vertical_material = 2131165324; - - // aapt resource value: 0x7f07008d - public const int compat_button_padding_horizontal_material = 2131165325; - - // aapt resource value: 0x7f07008e - public const int compat_button_padding_vertical_material = 2131165326; - - // aapt resource value: 0x7f07008f - public const int compat_control_corner_material = 2131165327; - - // aapt resource value: 0x7f070069 - public const int design_appbar_elevation = 2131165289; - - // aapt resource value: 0x7f07006a - public const int design_bottom_navigation_active_item_max_width = 2131165290; - - // aapt resource value: 0x7f07006b - public const int design_bottom_navigation_active_text_size = 2131165291; - - // aapt resource value: 0x7f07006c - public const int design_bottom_navigation_elevation = 2131165292; - - // aapt resource value: 0x7f07006d - public const int design_bottom_navigation_height = 2131165293; - - // aapt resource value: 0x7f07006e - public const int design_bottom_navigation_item_max_width = 2131165294; - - // aapt resource value: 0x7f07006f - public const int design_bottom_navigation_item_min_width = 2131165295; - - // aapt resource value: 0x7f070070 - public const int design_bottom_navigation_margin = 2131165296; - - // aapt resource value: 0x7f070071 - public const int design_bottom_navigation_shadow_height = 2131165297; - - // aapt resource value: 0x7f070072 - public const int design_bottom_navigation_text_size = 2131165298; - - // aapt resource value: 0x7f070073 - public const int design_bottom_sheet_modal_elevation = 2131165299; - - // aapt resource value: 0x7f070074 - public const int design_bottom_sheet_peek_height_min = 2131165300; - - // aapt resource value: 0x7f070075 - public const int design_fab_border_width = 2131165301; - - // aapt resource value: 0x7f070076 - public const int design_fab_elevation = 2131165302; - - // aapt resource value: 0x7f070077 - public const int design_fab_image_size = 2131165303; - - // aapt resource value: 0x7f070078 - public const int design_fab_size_mini = 2131165304; - - // aapt resource value: 0x7f070079 - public const int design_fab_size_normal = 2131165305; - - // aapt resource value: 0x7f07007a - public const int design_fab_translation_z_pressed = 2131165306; - - // aapt resource value: 0x7f07007b - public const int design_navigation_elevation = 2131165307; - - // aapt resource value: 0x7f07007c - public const int design_navigation_icon_padding = 2131165308; - - // aapt resource value: 0x7f07007d - public const int design_navigation_icon_size = 2131165309; - - // aapt resource value: 0x7f070061 - public const int design_navigation_max_width = 2131165281; - - // aapt resource value: 0x7f07007e - public const int design_navigation_padding_bottom = 2131165310; - - // aapt resource value: 0x7f07007f - public const int design_navigation_separator_vertical_padding = 2131165311; - - // aapt resource value: 0x7f070062 - public const int design_snackbar_action_inline_max_width = 2131165282; - - // aapt resource value: 0x7f070063 - public const int design_snackbar_background_corner_radius = 2131165283; - - // aapt resource value: 0x7f070080 - public const int design_snackbar_elevation = 2131165312; - - // aapt resource value: 0x7f070064 - public const int design_snackbar_extra_spacing_horizontal = 2131165284; - - // aapt resource value: 0x7f070065 - public const int design_snackbar_max_width = 2131165285; - - // aapt resource value: 0x7f070066 - public const int design_snackbar_min_width = 2131165286; - - // aapt resource value: 0x7f070081 - public const int design_snackbar_padding_horizontal = 2131165313; - - // aapt resource value: 0x7f070082 - public const int design_snackbar_padding_vertical = 2131165314; - - // aapt resource value: 0x7f070067 - public const int design_snackbar_padding_vertical_2lines = 2131165287; - - // aapt resource value: 0x7f070083 - public const int design_snackbar_text_size = 2131165315; - - // aapt resource value: 0x7f070084 - public const int design_tab_max_width = 2131165316; - - // aapt resource value: 0x7f070068 - public const int design_tab_scrollable_min_width = 2131165288; - - // aapt resource value: 0x7f070085 - public const int design_tab_text_size = 2131165317; - - // aapt resource value: 0x7f070086 - public const int design_tab_text_size_2line = 2131165318; - - // aapt resource value: 0x7f070050 - public const int disabled_alpha_material_dark = 2131165264; - - // aapt resource value: 0x7f070051 - public const int disabled_alpha_material_light = 2131165265; - - // aapt resource value: 0x7f070000 - public const int fastscroll_default_thickness = 2131165184; - - // aapt resource value: 0x7f070001 - public const int fastscroll_margin = 2131165185; - - // aapt resource value: 0x7f070002 - public const int fastscroll_minimum_range = 2131165186; - - // aapt resource value: 0x7f070052 - public const int highlight_alpha_material_colored = 2131165266; - - // aapt resource value: 0x7f070053 - public const int highlight_alpha_material_dark = 2131165267; - - // aapt resource value: 0x7f070054 - public const int highlight_alpha_material_light = 2131165268; - - // aapt resource value: 0x7f070055 - public const int hint_alpha_material_dark = 2131165269; - - // aapt resource value: 0x7f070056 - public const int hint_alpha_material_light = 2131165270; - - // aapt resource value: 0x7f070057 - public const int hint_pressed_alpha_material_dark = 2131165271; - - // aapt resource value: 0x7f070058 - public const int hint_pressed_alpha_material_light = 2131165272; - - // aapt resource value: 0x7f070003 - public const int item_touch_helper_max_drag_scroll_per_frame = 2131165187; - - // aapt resource value: 0x7f070004 - public const int item_touch_helper_swipe_escape_max_velocity = 2131165188; - - // aapt resource value: 0x7f070005 - public const int item_touch_helper_swipe_escape_velocity = 2131165189; - - // aapt resource value: 0x7f070090 - public const int notification_action_icon_size = 2131165328; - - // aapt resource value: 0x7f070091 - public const int notification_action_text_size = 2131165329; - - // aapt resource value: 0x7f070092 - public const int notification_big_circle_margin = 2131165330; - - // aapt resource value: 0x7f070088 - public const int notification_content_margin_start = 2131165320; - - // aapt resource value: 0x7f070093 - public const int notification_large_icon_height = 2131165331; - - // aapt resource value: 0x7f070094 - public const int notification_large_icon_width = 2131165332; - - // aapt resource value: 0x7f070089 - public const int notification_main_column_padding_top = 2131165321; - - // aapt resource value: 0x7f07008a - public const int notification_media_narrow_margin = 2131165322; - - // aapt resource value: 0x7f070095 - public const int notification_right_icon_size = 2131165333; - - // aapt resource value: 0x7f070087 - public const int notification_right_side_padding_top = 2131165319; - - // aapt resource value: 0x7f070096 - public const int notification_small_icon_background_padding = 2131165334; - - // aapt resource value: 0x7f070097 - public const int notification_small_icon_size_as_large = 2131165335; - - // aapt resource value: 0x7f070098 - public const int notification_subtext_size = 2131165336; - - // aapt resource value: 0x7f070099 - public const int notification_top_pad = 2131165337; - - // aapt resource value: 0x7f07009a - public const int notification_top_pad_large_text = 2131165338; - - // aapt resource value: 0x7f070059 - public const int tooltip_corner_radius = 2131165273; - - // aapt resource value: 0x7f07005a - public const int tooltip_horizontal_padding = 2131165274; - - // aapt resource value: 0x7f07005b - public const int tooltip_margin = 2131165275; - - // aapt resource value: 0x7f07005c - public const int tooltip_precise_anchor_extra_offset = 2131165276; - - // aapt resource value: 0x7f07005d - public const int tooltip_precise_anchor_threshold = 2131165277; - - // aapt resource value: 0x7f07005e - public const int tooltip_vertical_padding = 2131165278; - - // aapt resource value: 0x7f07005f - public const int tooltip_y_offset_non_touch = 2131165279; - - // aapt resource value: 0x7f070060 - public const int tooltip_y_offset_touch = 2131165280; - - static Dimension() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Dimension() - { - } - } - - public partial class Drawable - { - - // aapt resource value: 0x7f020000 - public const int abc_ab_share_pack_mtrl_alpha = 2130837504; - - // aapt resource value: 0x7f020001 - public const int abc_action_bar_item_background_material = 2130837505; - - // aapt resource value: 0x7f020002 - public const int abc_btn_borderless_material = 2130837506; - - // aapt resource value: 0x7f020003 - public const int abc_btn_check_material = 2130837507; - - // aapt resource value: 0x7f020004 - public const int abc_btn_check_to_on_mtrl_000 = 2130837508; - - // aapt resource value: 0x7f020005 - public const int abc_btn_check_to_on_mtrl_015 = 2130837509; - - // aapt resource value: 0x7f020006 - public const int abc_btn_colored_material = 2130837510; - - // aapt resource value: 0x7f020007 - public const int abc_btn_default_mtrl_shape = 2130837511; - - // aapt resource value: 0x7f020008 - public const int abc_btn_radio_material = 2130837512; - - // aapt resource value: 0x7f020009 - public const int abc_btn_radio_to_on_mtrl_000 = 2130837513; - - // aapt resource value: 0x7f02000a - public const int abc_btn_radio_to_on_mtrl_015 = 2130837514; - - // aapt resource value: 0x7f02000b - public const int abc_btn_switch_to_on_mtrl_00001 = 2130837515; - - // aapt resource value: 0x7f02000c - public const int abc_btn_switch_to_on_mtrl_00012 = 2130837516; - - // aapt resource value: 0x7f02000d - public const int abc_cab_background_internal_bg = 2130837517; - - // aapt resource value: 0x7f02000e - public const int abc_cab_background_top_material = 2130837518; - - // aapt resource value: 0x7f02000f - public const int abc_cab_background_top_mtrl_alpha = 2130837519; - - // aapt resource value: 0x7f020010 - public const int abc_control_background_material = 2130837520; - - // aapt resource value: 0x7f020011 - public const int abc_dialog_material_background = 2130837521; - - // aapt resource value: 0x7f020012 - public const int abc_edit_text_material = 2130837522; - - // aapt resource value: 0x7f020013 - public const int abc_ic_ab_back_material = 2130837523; - - // aapt resource value: 0x7f020014 - public const int abc_ic_arrow_drop_right_black_24dp = 2130837524; - - // aapt resource value: 0x7f020015 - public const int abc_ic_clear_material = 2130837525; - - // aapt resource value: 0x7f020016 - public const int abc_ic_commit_search_api_mtrl_alpha = 2130837526; - - // aapt resource value: 0x7f020017 - public const int abc_ic_go_search_api_material = 2130837527; - - // aapt resource value: 0x7f020018 - public const int abc_ic_menu_copy_mtrl_am_alpha = 2130837528; - - // aapt resource value: 0x7f020019 - public const int abc_ic_menu_cut_mtrl_alpha = 2130837529; - - // aapt resource value: 0x7f02001a - public const int abc_ic_menu_overflow_material = 2130837530; - - // aapt resource value: 0x7f02001b - public const int abc_ic_menu_paste_mtrl_am_alpha = 2130837531; - - // aapt resource value: 0x7f02001c - public const int abc_ic_menu_selectall_mtrl_alpha = 2130837532; - - // aapt resource value: 0x7f02001d - public const int abc_ic_menu_share_mtrl_alpha = 2130837533; - - // aapt resource value: 0x7f02001e - public const int abc_ic_search_api_material = 2130837534; - - // aapt resource value: 0x7f02001f - public const int abc_ic_star_black_16dp = 2130837535; - - // aapt resource value: 0x7f020020 - public const int abc_ic_star_black_36dp = 2130837536; - - // aapt resource value: 0x7f020021 - public const int abc_ic_star_black_48dp = 2130837537; - - // aapt resource value: 0x7f020022 - public const int abc_ic_star_half_black_16dp = 2130837538; - - // aapt resource value: 0x7f020023 - public const int abc_ic_star_half_black_36dp = 2130837539; - - // aapt resource value: 0x7f020024 - public const int abc_ic_star_half_black_48dp = 2130837540; - - // aapt resource value: 0x7f020025 - public const int abc_ic_voice_search_api_material = 2130837541; - - // aapt resource value: 0x7f020026 - public const int abc_item_background_holo_dark = 2130837542; - - // aapt resource value: 0x7f020027 - public const int abc_item_background_holo_light = 2130837543; - - // aapt resource value: 0x7f020028 - public const int abc_list_divider_mtrl_alpha = 2130837544; - - // aapt resource value: 0x7f020029 - public const int abc_list_focused_holo = 2130837545; - - // aapt resource value: 0x7f02002a - public const int abc_list_longpressed_holo = 2130837546; - - // aapt resource value: 0x7f02002b - public const int abc_list_pressed_holo_dark = 2130837547; - - // aapt resource value: 0x7f02002c - public const int abc_list_pressed_holo_light = 2130837548; - - // aapt resource value: 0x7f02002d - public const int abc_list_selector_background_transition_holo_dark = 2130837549; - - // aapt resource value: 0x7f02002e - public const int abc_list_selector_background_transition_holo_light = 2130837550; - - // aapt resource value: 0x7f02002f - public const int abc_list_selector_disabled_holo_dark = 2130837551; - - // aapt resource value: 0x7f020030 - public const int abc_list_selector_disabled_holo_light = 2130837552; - - // aapt resource value: 0x7f020031 - public const int abc_list_selector_holo_dark = 2130837553; - - // aapt resource value: 0x7f020032 - public const int abc_list_selector_holo_light = 2130837554; - - // aapt resource value: 0x7f020033 - public const int abc_menu_hardkey_panel_mtrl_mult = 2130837555; - - // aapt resource value: 0x7f020034 - public const int abc_popup_background_mtrl_mult = 2130837556; - - // aapt resource value: 0x7f020035 - public const int abc_ratingbar_indicator_material = 2130837557; - - // aapt resource value: 0x7f020036 - public const int abc_ratingbar_material = 2130837558; - - // aapt resource value: 0x7f020037 - public const int abc_ratingbar_small_material = 2130837559; - - // aapt resource value: 0x7f020038 - public const int abc_scrubber_control_off_mtrl_alpha = 2130837560; - - // aapt resource value: 0x7f020039 - public const int abc_scrubber_control_to_pressed_mtrl_000 = 2130837561; - - // aapt resource value: 0x7f02003a - public const int abc_scrubber_control_to_pressed_mtrl_005 = 2130837562; - - // aapt resource value: 0x7f02003b - public const int abc_scrubber_primary_mtrl_alpha = 2130837563; - - // aapt resource value: 0x7f02003c - public const int abc_scrubber_track_mtrl_alpha = 2130837564; - - // aapt resource value: 0x7f02003d - public const int abc_seekbar_thumb_material = 2130837565; - - // aapt resource value: 0x7f02003e - public const int abc_seekbar_tick_mark_material = 2130837566; - - // aapt resource value: 0x7f02003f - public const int abc_seekbar_track_material = 2130837567; - - // aapt resource value: 0x7f020040 - public const int abc_spinner_mtrl_am_alpha = 2130837568; - - // aapt resource value: 0x7f020041 - public const int abc_spinner_textfield_background_material = 2130837569; - - // aapt resource value: 0x7f020042 - public const int abc_switch_thumb_material = 2130837570; - - // aapt resource value: 0x7f020043 - public const int abc_switch_track_mtrl_alpha = 2130837571; - - // aapt resource value: 0x7f020044 - public const int abc_tab_indicator_material = 2130837572; - - // aapt resource value: 0x7f020045 - public const int abc_tab_indicator_mtrl_alpha = 2130837573; - - // aapt resource value: 0x7f020046 - public const int abc_text_cursor_material = 2130837574; - - // aapt resource value: 0x7f020047 - public const int abc_text_select_handle_left_mtrl_dark = 2130837575; - - // aapt resource value: 0x7f020048 - public const int abc_text_select_handle_left_mtrl_light = 2130837576; - - // aapt resource value: 0x7f020049 - public const int abc_text_select_handle_middle_mtrl_dark = 2130837577; - - // aapt resource value: 0x7f02004a - public const int abc_text_select_handle_middle_mtrl_light = 2130837578; - - // aapt resource value: 0x7f02004b - public const int abc_text_select_handle_right_mtrl_dark = 2130837579; - - // aapt resource value: 0x7f02004c - public const int abc_text_select_handle_right_mtrl_light = 2130837580; - - // aapt resource value: 0x7f02004d - public const int abc_textfield_activated_mtrl_alpha = 2130837581; - - // aapt resource value: 0x7f02004e - public const int abc_textfield_default_mtrl_alpha = 2130837582; - - // aapt resource value: 0x7f02004f - public const int abc_textfield_search_activated_mtrl_alpha = 2130837583; - - // aapt resource value: 0x7f020050 - public const int abc_textfield_search_default_mtrl_alpha = 2130837584; - - // aapt resource value: 0x7f020051 - public const int abc_textfield_search_material = 2130837585; - - // aapt resource value: 0x7f020052 - public const int abc_vector_test = 2130837586; - - // aapt resource value: 0x7f020053 - public const int avd_hide_password = 2130837587; - - // aapt resource value: 0x7f02006a - public const int avd_hide_password_1 = 2130837610; - - // aapt resource value: 0x7f02006b - public const int avd_hide_password_2 = 2130837611; - - // aapt resource value: 0x7f02006c - public const int avd_hide_password_3 = 2130837612; - - // aapt resource value: 0x7f020054 - public const int avd_show_password = 2130837588; - - // aapt resource value: 0x7f02006d - public const int avd_show_password_1 = 2130837613; - - // aapt resource value: 0x7f02006e - public const int avd_show_password_2 = 2130837614; - - // aapt resource value: 0x7f02006f - public const int avd_show_password_3 = 2130837615; - - // aapt resource value: 0x7f020055 - public const int design_bottom_navigation_item_background = 2130837589; - - // aapt resource value: 0x7f020056 - public const int design_fab_background = 2130837590; - - // aapt resource value: 0x7f020057 - public const int design_ic_visibility = 2130837591; - - // aapt resource value: 0x7f020058 - public const int design_ic_visibility_off = 2130837592; - - // aapt resource value: 0x7f020059 - public const int design_password_eye = 2130837593; - - // aapt resource value: 0x7f02005a - public const int design_snackbar_background = 2130837594; - - // aapt resource value: 0x7f02005b - public const int navigation_empty_icon = 2130837595; - - // aapt resource value: 0x7f02005c - public const int notification_action_background = 2130837596; - - // aapt resource value: 0x7f02005d - public const int notification_bg = 2130837597; - - // aapt resource value: 0x7f02005e - public const int notification_bg_low = 2130837598; - - // aapt resource value: 0x7f02005f - public const int notification_bg_low_normal = 2130837599; - - // aapt resource value: 0x7f020060 - public const int notification_bg_low_pressed = 2130837600; - - // aapt resource value: 0x7f020061 - public const int notification_bg_normal = 2130837601; - - // aapt resource value: 0x7f020062 - public const int notification_bg_normal_pressed = 2130837602; - - // aapt resource value: 0x7f020063 - public const int notification_icon_background = 2130837603; - - // aapt resource value: 0x7f020068 - public const int notification_template_icon_bg = 2130837608; - - // aapt resource value: 0x7f020069 - public const int notification_template_icon_low_bg = 2130837609; - - // aapt resource value: 0x7f020064 - public const int notification_tile_bg = 2130837604; - - // aapt resource value: 0x7f020065 - public const int notify_panel_notification_icon_bg = 2130837605; - - // aapt resource value: 0x7f020066 - public const int tooltip_frame_dark = 2130837606; - - // aapt resource value: 0x7f020067 - public const int tooltip_frame_light = 2130837607; - - static Drawable() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Drawable() - { - } - } - - public partial class Id - { - - // aapt resource value: 0x7f080032 - public const int ALT = 2131230770; - - // aapt resource value: 0x7f080033 - public const int CTRL = 2131230771; - - // aapt resource value: 0x7f080034 - public const int FUNCTION = 2131230772; - - // aapt resource value: 0x7f080035 - public const int META = 2131230773; - - // aapt resource value: 0x7f080036 - public const int SHIFT = 2131230774; - - // aapt resource value: 0x7f080037 - public const int SYM = 2131230775; - - // aapt resource value: 0x7f08009d - public const int action0 = 2131230877; - - // aapt resource value: 0x7f08007c - public const int action_bar = 2131230844; - - // aapt resource value: 0x7f080001 - public const int action_bar_activity_content = 2131230721; - - // aapt resource value: 0x7f08007b - public const int action_bar_container = 2131230843; - - // aapt resource value: 0x7f080077 - public const int action_bar_root = 2131230839; - - // aapt resource value: 0x7f080002 - public const int action_bar_spinner = 2131230722; - - // aapt resource value: 0x7f08005b - public const int action_bar_subtitle = 2131230811; - - // aapt resource value: 0x7f08005a - public const int action_bar_title = 2131230810; - - // aapt resource value: 0x7f08009a - public const int action_container = 2131230874; - - // aapt resource value: 0x7f08007d - public const int action_context_bar = 2131230845; - - // aapt resource value: 0x7f0800a1 - public const int action_divider = 2131230881; - - // aapt resource value: 0x7f08009b - public const int action_image = 2131230875; - - // aapt resource value: 0x7f080003 - public const int action_menu_divider = 2131230723; - - // aapt resource value: 0x7f080004 - public const int action_menu_presenter = 2131230724; - - // aapt resource value: 0x7f080079 - public const int action_mode_bar = 2131230841; - - // aapt resource value: 0x7f080078 - public const int action_mode_bar_stub = 2131230840; - - // aapt resource value: 0x7f08005c - public const int action_mode_close_button = 2131230812; - - // aapt resource value: 0x7f08009c - public const int action_text = 2131230876; - - // aapt resource value: 0x7f0800aa - public const int actions = 2131230890; - - // aapt resource value: 0x7f08005d - public const int activity_chooser_view_content = 2131230813; - - // aapt resource value: 0x7f080027 - public const int add = 2131230759; - - // aapt resource value: 0x7f080070 - public const int alertTitle = 2131230832; - - // aapt resource value: 0x7f080052 - public const int all = 2131230802; - - // aapt resource value: 0x7f080038 - public const int always = 2131230776; - - // aapt resource value: 0x7f080056 - public const int async = 2131230806; - - // aapt resource value: 0x7f080044 - public const int auto = 2131230788; - - // aapt resource value: 0x7f08002f - public const int beginning = 2131230767; - - // aapt resource value: 0x7f080057 - public const int blocking = 2131230807; - - // aapt resource value: 0x7f08003d - public const int bottom = 2131230781; - - // aapt resource value: 0x7f080063 - public const int buttonPanel = 2131230819; - - // aapt resource value: 0x7f08009e - public const int cancel_action = 2131230878; - - // aapt resource value: 0x7f080045 - public const int center = 2131230789; - - // aapt resource value: 0x7f080046 - public const int center_horizontal = 2131230790; - - // aapt resource value: 0x7f080047 - public const int center_vertical = 2131230791; - - // aapt resource value: 0x7f080073 - public const int checkbox = 2131230835; - - // aapt resource value: 0x7f0800a6 - public const int chronometer = 2131230886; - - // aapt resource value: 0x7f08004e - public const int clip_horizontal = 2131230798; - - // aapt resource value: 0x7f08004f - public const int clip_vertical = 2131230799; - - // aapt resource value: 0x7f080039 - public const int collapseActionView = 2131230777; - - // aapt resource value: 0x7f08008e - public const int container = 2131230862; - - // aapt resource value: 0x7f080066 - public const int contentPanel = 2131230822; - - // aapt resource value: 0x7f08008f - public const int coordinator = 2131230863; - - // aapt resource value: 0x7f08006d - public const int custom = 2131230829; - - // aapt resource value: 0x7f08006c - public const int customPanel = 2131230828; - - // aapt resource value: 0x7f08007a - public const int decor_content_parent = 2131230842; - - // aapt resource value: 0x7f080060 - public const int default_activity_button = 2131230816; - - // aapt resource value: 0x7f080091 - public const int design_bottom_sheet = 2131230865; - - // aapt resource value: 0x7f080098 - public const int design_menu_item_action_area = 2131230872; - - // aapt resource value: 0x7f080097 - public const int design_menu_item_action_area_stub = 2131230871; - - // aapt resource value: 0x7f080096 - public const int design_menu_item_text = 2131230870; - - // aapt resource value: 0x7f080095 - public const int design_navigation_view = 2131230869; - - // aapt resource value: 0x7f080020 - public const int disableHome = 2131230752; - - // aapt resource value: 0x7f08007e - public const int edit_query = 2131230846; - - // aapt resource value: 0x7f080030 - public const int end = 2131230768; - - // aapt resource value: 0x7f0800ac - public const int end_padder = 2131230892; - - // aapt resource value: 0x7f08003f - public const int enterAlways = 2131230783; - - // aapt resource value: 0x7f080040 - public const int enterAlwaysCollapsed = 2131230784; - - // aapt resource value: 0x7f080041 - public const int exitUntilCollapsed = 2131230785; - - // aapt resource value: 0x7f08005e - public const int expand_activities_button = 2131230814; - - // aapt resource value: 0x7f080072 - public const int expanded_menu = 2131230834; - - // aapt resource value: 0x7f080050 - public const int fill = 2131230800; - - // aapt resource value: 0x7f080051 - public const int fill_horizontal = 2131230801; - - // aapt resource value: 0x7f080048 - public const int fill_vertical = 2131230792; - - // aapt resource value: 0x7f080054 - public const int @fixed = 2131230804; - - // aapt resource value: 0x7f080058 - public const int forever = 2131230808; - - // aapt resource value: 0x7f08008b - public const int gameView1 = 2131230859; - - // aapt resource value: 0x7f08000a - public const int ghost_view = 2131230730; - - // aapt resource value: 0x7f080005 - public const int home = 2131230725; - - // aapt resource value: 0x7f080021 - public const int homeAsUp = 2131230753; - - // aapt resource value: 0x7f080062 - public const int icon = 2131230818; - - // aapt resource value: 0x7f0800ab - public const int icon_group = 2131230891; - - // aapt resource value: 0x7f08003a - public const int ifRoom = 2131230778; - - // aapt resource value: 0x7f08005f - public const int image = 2131230815; - - // aapt resource value: 0x7f0800a7 - public const int info = 2131230887; - - // aapt resource value: 0x7f080059 - public const int italic = 2131230809; - - // aapt resource value: 0x7f080000 - public const int item_touch_helper_previous_elevation = 2131230720; - - // aapt resource value: 0x7f08008d - public const int largeLabel = 2131230861; - - // aapt resource value: 0x7f080049 - public const int left = 2131230793; - - // aapt resource value: 0x7f080017 - public const int line1 = 2131230743; - - // aapt resource value: 0x7f080018 - public const int line3 = 2131230744; - - // aapt resource value: 0x7f08001d - public const int listMode = 2131230749; - - // aapt resource value: 0x7f080061 - public const int list_item = 2131230817; - - // aapt resource value: 0x7f0800af - public const int masked = 2131230895; - - // aapt resource value: 0x7f0800a0 - public const int media_actions = 2131230880; - - // aapt resource value: 0x7f0800ad - public const int message = 2131230893; - - // aapt resource value: 0x7f080031 - public const int middle = 2131230769; - - // aapt resource value: 0x7f080053 - public const int mini = 2131230803; - - // aapt resource value: 0x7f080028 - public const int multiply = 2131230760; - - // aapt resource value: 0x7f080094 - public const int navigation_header_container = 2131230868; - - // aapt resource value: 0x7f08003b - public const int never = 2131230779; - - // aapt resource value: 0x7f080022 - public const int none = 2131230754; - - // aapt resource value: 0x7f08001e - public const int normal = 2131230750; - - // aapt resource value: 0x7f0800a9 - public const int notification_background = 2131230889; - - // aapt resource value: 0x7f0800a3 - public const int notification_main_column = 2131230883; - - // aapt resource value: 0x7f0800a2 - public const int notification_main_column_container = 2131230882; - - // aapt resource value: 0x7f08004c - public const int parallax = 2131230796; - - // aapt resource value: 0x7f080065 - public const int parentPanel = 2131230821; - - // aapt resource value: 0x7f08000b - public const int parent_matrix = 2131230731; - - // aapt resource value: 0x7f08004d - public const int pin = 2131230797; - - // aapt resource value: 0x7f080006 - public const int progress_circular = 2131230726; - - // aapt resource value: 0x7f080007 - public const int progress_horizontal = 2131230727; - - // aapt resource value: 0x7f080075 - public const int radio = 2131230837; - - // aapt resource value: 0x7f08004a - public const int right = 2131230794; - - // aapt resource value: 0x7f0800a8 - public const int right_icon = 2131230888; - - // aapt resource value: 0x7f0800a4 - public const int right_side = 2131230884; - - // aapt resource value: 0x7f08000c - public const int save_image_matrix = 2131230732; - - // aapt resource value: 0x7f08000d - public const int save_non_transition_alpha = 2131230733; - - // aapt resource value: 0x7f08000e - public const int save_scale_type = 2131230734; - - // aapt resource value: 0x7f080029 - public const int screen = 2131230761; - - // aapt resource value: 0x7f080042 - public const int scroll = 2131230786; - - // aapt resource value: 0x7f08006b - public const int scrollIndicatorDown = 2131230827; - - // aapt resource value: 0x7f080067 - public const int scrollIndicatorUp = 2131230823; - - // aapt resource value: 0x7f080068 - public const int scrollView = 2131230824; - - // aapt resource value: 0x7f080055 - public const int scrollable = 2131230805; - - // aapt resource value: 0x7f080080 - public const int search_badge = 2131230848; - - // aapt resource value: 0x7f08007f - public const int search_bar = 2131230847; - - // aapt resource value: 0x7f080081 - public const int search_button = 2131230849; - - // aapt resource value: 0x7f080086 - public const int search_close_btn = 2131230854; - - // aapt resource value: 0x7f080082 - public const int search_edit_frame = 2131230850; - - // aapt resource value: 0x7f080088 - public const int search_go_btn = 2131230856; - - // aapt resource value: 0x7f080083 - public const int search_mag_icon = 2131230851; - - // aapt resource value: 0x7f080084 - public const int search_plate = 2131230852; - - // aapt resource value: 0x7f080085 - public const int search_src_text = 2131230853; - - // aapt resource value: 0x7f080089 - public const int search_voice_btn = 2131230857; - - // aapt resource value: 0x7f08008a - public const int select_dialog_listview = 2131230858; - - // aapt resource value: 0x7f080074 - public const int shortcut = 2131230836; - - // aapt resource value: 0x7f080023 - public const int showCustom = 2131230755; - - // aapt resource value: 0x7f080024 - public const int showHome = 2131230756; - - // aapt resource value: 0x7f080025 - public const int showTitle = 2131230757; - - // aapt resource value: 0x7f08008c - public const int smallLabel = 2131230860; - - // aapt resource value: 0x7f080093 - public const int snackbar_action = 2131230867; - - // aapt resource value: 0x7f080092 - public const int snackbar_text = 2131230866; - - // aapt resource value: 0x7f080043 - public const int snap = 2131230787; - - // aapt resource value: 0x7f080064 - public const int spacer = 2131230820; - - // aapt resource value: 0x7f080008 - public const int split_action_bar = 2131230728; - - // aapt resource value: 0x7f08002a - public const int src_atop = 2131230762; - - // aapt resource value: 0x7f08002b - public const int src_in = 2131230763; - - // aapt resource value: 0x7f08002c - public const int src_over = 2131230764; - - // aapt resource value: 0x7f08004b - public const int start = 2131230795; - - // aapt resource value: 0x7f08009f - public const int status_bar_latest_event_content = 2131230879; - - // aapt resource value: 0x7f080076 - public const int submenuarrow = 2131230838; - - // aapt resource value: 0x7f080087 - public const int submit_area = 2131230855; - - // aapt resource value: 0x7f08001f - public const int tabMode = 2131230751; - - // aapt resource value: 0x7f080019 - public const int tag_transition_group = 2131230745; - - // aapt resource value: 0x7f08001a - public const int text = 2131230746; - - // aapt resource value: 0x7f08001b - public const int text2 = 2131230747; - - // aapt resource value: 0x7f08006a - public const int textSpacerNoButtons = 2131230826; - - // aapt resource value: 0x7f080069 - public const int textSpacerNoTitle = 2131230825; - - // aapt resource value: 0x7f080099 - public const int text_input_password_toggle = 2131230873; - - // aapt resource value: 0x7f080014 - public const int textinput_counter = 2131230740; - - // aapt resource value: 0x7f080015 - public const int textinput_error = 2131230741; - - // aapt resource value: 0x7f0800a5 - public const int time = 2131230885; - - // aapt resource value: 0x7f08001c - public const int title = 2131230748; - - // aapt resource value: 0x7f080071 - public const int titleDividerNoCustom = 2131230833; - - // aapt resource value: 0x7f08006f - public const int title_template = 2131230831; - - // aapt resource value: 0x7f08003e - public const int top = 2131230782; - - // aapt resource value: 0x7f08006e - public const int topPanel = 2131230830; - - // aapt resource value: 0x7f080090 - public const int touch_outside = 2131230864; - - // aapt resource value: 0x7f08000f - public const int transition_current_scene = 2131230735; - - // aapt resource value: 0x7f080010 - public const int transition_layout_save = 2131230736; - - // aapt resource value: 0x7f080011 - public const int transition_position = 2131230737; - - // aapt resource value: 0x7f080012 - public const int transition_scene_layoutid_cache = 2131230738; - - // aapt resource value: 0x7f080013 - public const int transition_transform = 2131230739; - - // aapt resource value: 0x7f08002d - public const int uniform = 2131230765; - - // aapt resource value: 0x7f080009 - public const int up = 2131230729; - - // aapt resource value: 0x7f080026 - public const int useLogo = 2131230758; - - // aapt resource value: 0x7f080016 - public const int view_offset_helper = 2131230742; - - // aapt resource value: 0x7f0800ae - public const int visible = 2131230894; - - // aapt resource value: 0x7f08003c - public const int withText = 2131230780; - - // aapt resource value: 0x7f08002e - public const int wrap_content = 2131230766; - - static Id() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Id() - { - } - } - - public partial class Integer - { - - // aapt resource value: 0x7f0d0000 - public const int abc_config_activityDefaultDur = 2131558400; - - // aapt resource value: 0x7f0d0001 - public const int abc_config_activityShortDur = 2131558401; - - // aapt resource value: 0x7f0d0005 - public const int app_bar_elevation_anim_duration = 2131558405; - - // aapt resource value: 0x7f0d0006 - public const int bottom_sheet_slide_duration = 2131558406; - - // aapt resource value: 0x7f0d0002 - public const int cancel_button_image_alpha = 2131558402; - - // aapt resource value: 0x7f0d0003 - public const int config_tooltipAnimTime = 2131558403; - - // aapt resource value: 0x7f0d0004 - public const int design_snackbar_text_max_lines = 2131558404; - - // aapt resource value: 0x7f0d0007 - public const int hide_password_duration = 2131558407; - - // aapt resource value: 0x7f0d0008 - public const int show_password_duration = 2131558408; - - // aapt resource value: 0x7f0d0009 - public const int status_bar_notification_info_maxnum = 2131558409; - - static Integer() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Integer() - { - } - } - - public partial class Layout - { - - // aapt resource value: 0x7f040000 - public const int abc_action_bar_title_item = 2130968576; - - // aapt resource value: 0x7f040001 - public const int abc_action_bar_up_container = 2130968577; - - // aapt resource value: 0x7f040002 - public const int abc_action_menu_item_layout = 2130968578; - - // aapt resource value: 0x7f040003 - public const int abc_action_menu_layout = 2130968579; - - // aapt resource value: 0x7f040004 - public const int abc_action_mode_bar = 2130968580; - - // aapt resource value: 0x7f040005 - public const int abc_action_mode_close_item_material = 2130968581; - - // aapt resource value: 0x7f040006 - public const int abc_activity_chooser_view = 2130968582; - - // aapt resource value: 0x7f040007 - public const int abc_activity_chooser_view_list_item = 2130968583; - - // aapt resource value: 0x7f040008 - public const int abc_alert_dialog_button_bar_material = 2130968584; - - // aapt resource value: 0x7f040009 - public const int abc_alert_dialog_material = 2130968585; - - // aapt resource value: 0x7f04000a - public const int abc_alert_dialog_title_material = 2130968586; - - // aapt resource value: 0x7f04000b - public const int abc_dialog_title_material = 2130968587; - - // aapt resource value: 0x7f04000c - public const int abc_expanded_menu_layout = 2130968588; - - // aapt resource value: 0x7f04000d - public const int abc_list_menu_item_checkbox = 2130968589; - - // aapt resource value: 0x7f04000e - public const int abc_list_menu_item_icon = 2130968590; - - // aapt resource value: 0x7f04000f - public const int abc_list_menu_item_layout = 2130968591; - - // aapt resource value: 0x7f040010 - public const int abc_list_menu_item_radio = 2130968592; - - // aapt resource value: 0x7f040011 - public const int abc_popup_menu_header_item_layout = 2130968593; - - // aapt resource value: 0x7f040012 - public const int abc_popup_menu_item_layout = 2130968594; - - // aapt resource value: 0x7f040013 - public const int abc_screen_content_include = 2130968595; - - // aapt resource value: 0x7f040014 - public const int abc_screen_simple = 2130968596; - - // aapt resource value: 0x7f040015 - public const int abc_screen_simple_overlay_action_mode = 2130968597; - - // aapt resource value: 0x7f040016 - public const int abc_screen_toolbar = 2130968598; - - // aapt resource value: 0x7f040017 - public const int abc_search_dropdown_item_icons_2line = 2130968599; - - // aapt resource value: 0x7f040018 - public const int abc_search_view = 2130968600; - - // aapt resource value: 0x7f040019 - public const int abc_select_dialog_material = 2130968601; - - // aapt resource value: 0x7f04001a - public const int activity_main = 2130968602; - - // aapt resource value: 0x7f04001b - public const int design_bottom_navigation_item = 2130968603; - - // aapt resource value: 0x7f04001c - public const int design_bottom_sheet_dialog = 2130968604; - - // aapt resource value: 0x7f04001d - public const int design_layout_snackbar = 2130968605; - - // aapt resource value: 0x7f04001e - public const int design_layout_snackbar_include = 2130968606; - - // aapt resource value: 0x7f04001f - public const int design_layout_tab_icon = 2130968607; - - // aapt resource value: 0x7f040020 - public const int design_layout_tab_text = 2130968608; - - // aapt resource value: 0x7f040021 - public const int design_menu_item_action_area = 2130968609; - - // aapt resource value: 0x7f040022 - public const int design_navigation_item = 2130968610; - - // aapt resource value: 0x7f040023 - public const int design_navigation_item_header = 2130968611; - - // aapt resource value: 0x7f040024 - public const int design_navigation_item_separator = 2130968612; - - // aapt resource value: 0x7f040025 - public const int design_navigation_item_subheader = 2130968613; - - // aapt resource value: 0x7f040026 - public const int design_navigation_menu = 2130968614; - - // aapt resource value: 0x7f040027 - public const int design_navigation_menu_item = 2130968615; - - // aapt resource value: 0x7f040028 - public const int design_text_input_password_icon = 2130968616; - - // aapt resource value: 0x7f040029 - public const int notification_action = 2130968617; - - // aapt resource value: 0x7f04002a - public const int notification_action_tombstone = 2130968618; - - // aapt resource value: 0x7f04002b - public const int notification_media_action = 2130968619; - - // aapt resource value: 0x7f04002c - public const int notification_media_cancel_action = 2130968620; - - // aapt resource value: 0x7f04002d - public const int notification_template_big_media = 2130968621; - - // aapt resource value: 0x7f04002e - public const int notification_template_big_media_custom = 2130968622; - - // aapt resource value: 0x7f04002f - public const int notification_template_big_media_narrow = 2130968623; - - // aapt resource value: 0x7f040030 - public const int notification_template_big_media_narrow_custom = 2130968624; - - // aapt resource value: 0x7f040031 - public const int notification_template_custom_big = 2130968625; - - // aapt resource value: 0x7f040032 - public const int notification_template_icon_group = 2130968626; - - // aapt resource value: 0x7f040033 - public const int notification_template_lines_media = 2130968627; - - // aapt resource value: 0x7f040034 - public const int notification_template_media = 2130968628; - - // aapt resource value: 0x7f040035 - public const int notification_template_media_custom = 2130968629; - - // aapt resource value: 0x7f040036 - public const int notification_template_part_chronometer = 2130968630; - - // aapt resource value: 0x7f040037 - public const int notification_template_part_time = 2130968631; - - // aapt resource value: 0x7f040038 - public const int select_dialog_item_material = 2130968632; - - // aapt resource value: 0x7f040039 - public const int select_dialog_multichoice_material = 2130968633; - - // aapt resource value: 0x7f04003a - public const int select_dialog_singlechoice_material = 2130968634; - - // aapt resource value: 0x7f04003b - public const int support_simple_spinner_dropdown_item = 2130968635; - - // aapt resource value: 0x7f04003c - public const int tooltip = 2130968636; - - static Layout() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Layout() - { - } - } - public partial class Mipmap { - // aapt resource value: 0x7f030000 - public const int ic_launcher = 2130903040; + // aapt resource value: 0x7f020000 + public const int ic_launcher = 2130837504; - // aapt resource value: 0x7f030001 - public const int ic_launcher_foreground = 2130903041; + // aapt resource value: 0x7f020001 + public const int ic_launcher_foreground = 2130837505; - // aapt resource value: 0x7f030002 - public const int ic_launcher_round = 2130903042; + // aapt resource value: 0x7f020002 + public const int ic_launcher_round = 2130837506; static Mipmap() { @@ -3122,3367 +87,6 @@ namespace osu.Android { } } - - public partial class String - { - - // aapt resource value: 0x7f090000 - public const int abc_action_bar_home_description = 2131296256; - - // aapt resource value: 0x7f090001 - public const int abc_action_bar_up_description = 2131296257; - - // aapt resource value: 0x7f090002 - public const int abc_action_menu_overflow_description = 2131296258; - - // aapt resource value: 0x7f090003 - public const int abc_action_mode_done = 2131296259; - - // aapt resource value: 0x7f090004 - public const int abc_activity_chooser_view_see_all = 2131296260; - - // aapt resource value: 0x7f090005 - public const int abc_activitychooserview_choose_application = 2131296261; - - // aapt resource value: 0x7f090006 - public const int abc_capital_off = 2131296262; - - // aapt resource value: 0x7f090007 - public const int abc_capital_on = 2131296263; - - // aapt resource value: 0x7f090012 - public const int abc_font_family_body_1_material = 2131296274; - - // aapt resource value: 0x7f090013 - public const int abc_font_family_body_2_material = 2131296275; - - // aapt resource value: 0x7f090014 - public const int abc_font_family_button_material = 2131296276; - - // aapt resource value: 0x7f090015 - public const int abc_font_family_caption_material = 2131296277; - - // aapt resource value: 0x7f090016 - public const int abc_font_family_display_1_material = 2131296278; - - // aapt resource value: 0x7f090017 - public const int abc_font_family_display_2_material = 2131296279; - - // aapt resource value: 0x7f090018 - public const int abc_font_family_display_3_material = 2131296280; - - // aapt resource value: 0x7f090019 - public const int abc_font_family_display_4_material = 2131296281; - - // aapt resource value: 0x7f09001a - public const int abc_font_family_headline_material = 2131296282; - - // aapt resource value: 0x7f09001b - public const int abc_font_family_menu_material = 2131296283; - - // aapt resource value: 0x7f09001c - public const int abc_font_family_subhead_material = 2131296284; - - // aapt resource value: 0x7f09001d - public const int abc_font_family_title_material = 2131296285; - - // aapt resource value: 0x7f090008 - public const int abc_search_hint = 2131296264; - - // aapt resource value: 0x7f090009 - public const int abc_searchview_description_clear = 2131296265; - - // aapt resource value: 0x7f09000a - public const int abc_searchview_description_query = 2131296266; - - // aapt resource value: 0x7f09000b - public const int abc_searchview_description_search = 2131296267; - - // aapt resource value: 0x7f09000c - public const int abc_searchview_description_submit = 2131296268; - - // aapt resource value: 0x7f09000d - public const int abc_searchview_description_voice = 2131296269; - - // aapt resource value: 0x7f09000e - public const int abc_shareactionprovider_share_with = 2131296270; - - // aapt resource value: 0x7f09000f - public const int abc_shareactionprovider_share_with_application = 2131296271; - - // aapt resource value: 0x7f090010 - public const int abc_toolbar_collapse_description = 2131296272; - - // aapt resource value: 0x7f090028 - public const int action_settings = 2131296296; - - // aapt resource value: 0x7f090027 - public const int app_name = 2131296295; - - // aapt resource value: 0x7f09001e - public const int appbar_scrolling_view_behavior = 2131296286; - - // aapt resource value: 0x7f09001f - public const int bottom_sheet_behavior = 2131296287; - - // aapt resource value: 0x7f090020 - public const int character_counter_pattern = 2131296288; - - // aapt resource value: 0x7f090021 - public const int password_toggle_content_description = 2131296289; - - // aapt resource value: 0x7f090022 - public const int path_password_eye = 2131296290; - - // aapt resource value: 0x7f090023 - public const int path_password_eye_mask_strike_through = 2131296291; - - // aapt resource value: 0x7f090024 - public const int path_password_eye_mask_visible = 2131296292; - - // aapt resource value: 0x7f090025 - public const int path_password_strike_through = 2131296293; - - // aapt resource value: 0x7f090011 - public const int search_menu_title = 2131296273; - - // aapt resource value: 0x7f090026 - public const int status_bar_notification_info_overflow = 2131296294; - - static String() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private String() - { - } - } - - public partial class Style - { - - // aapt resource value: 0x7f0a0095 - public const int AlertDialog_AppCompat = 2131361941; - - // aapt resource value: 0x7f0a0096 - public const int AlertDialog_AppCompat_Light = 2131361942; - - // aapt resource value: 0x7f0a0097 - public const int Animation_AppCompat_Dialog = 2131361943; - - // aapt resource value: 0x7f0a0098 - public const int Animation_AppCompat_DropDownUp = 2131361944; - - // aapt resource value: 0x7f0a0099 - public const int Animation_AppCompat_Tooltip = 2131361945; - - // aapt resource value: 0x7f0a015f - public const int Animation_Design_BottomSheetDialog = 2131362143; - - // aapt resource value: 0x7f0a0180 - public const int AppTheme = 2131362176; - - // aapt resource value: 0x7f0a009a - public const int Base_AlertDialog_AppCompat = 2131361946; - - // aapt resource value: 0x7f0a009b - public const int Base_AlertDialog_AppCompat_Light = 2131361947; - - // aapt resource value: 0x7f0a009c - public const int Base_Animation_AppCompat_Dialog = 2131361948; - - // aapt resource value: 0x7f0a009d - public const int Base_Animation_AppCompat_DropDownUp = 2131361949; - - // aapt resource value: 0x7f0a009e - public const int Base_Animation_AppCompat_Tooltip = 2131361950; - - // aapt resource value: 0x7f0a009f - public const int Base_DialogWindowTitle_AppCompat = 2131361951; - - // aapt resource value: 0x7f0a00a0 - public const int Base_DialogWindowTitleBackground_AppCompat = 2131361952; - - // aapt resource value: 0x7f0a0039 - public const int Base_TextAppearance_AppCompat = 2131361849; - - // aapt resource value: 0x7f0a003a - public const int Base_TextAppearance_AppCompat_Body1 = 2131361850; - - // aapt resource value: 0x7f0a003b - public const int Base_TextAppearance_AppCompat_Body2 = 2131361851; - - // aapt resource value: 0x7f0a0027 - public const int Base_TextAppearance_AppCompat_Button = 2131361831; - - // aapt resource value: 0x7f0a003c - public const int Base_TextAppearance_AppCompat_Caption = 2131361852; - - // aapt resource value: 0x7f0a003d - public const int Base_TextAppearance_AppCompat_Display1 = 2131361853; - - // aapt resource value: 0x7f0a003e - public const int Base_TextAppearance_AppCompat_Display2 = 2131361854; - - // aapt resource value: 0x7f0a003f - public const int Base_TextAppearance_AppCompat_Display3 = 2131361855; - - // aapt resource value: 0x7f0a0040 - public const int Base_TextAppearance_AppCompat_Display4 = 2131361856; - - // aapt resource value: 0x7f0a0041 - public const int Base_TextAppearance_AppCompat_Headline = 2131361857; - - // aapt resource value: 0x7f0a000b - public const int Base_TextAppearance_AppCompat_Inverse = 2131361803; - - // aapt resource value: 0x7f0a0042 - public const int Base_TextAppearance_AppCompat_Large = 2131361858; - - // aapt resource value: 0x7f0a000c - public const int Base_TextAppearance_AppCompat_Large_Inverse = 2131361804; - - // aapt resource value: 0x7f0a0043 - public const int Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = 2131361859; - - // aapt resource value: 0x7f0a0044 - public const int Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = 2131361860; - - // aapt resource value: 0x7f0a0045 - public const int Base_TextAppearance_AppCompat_Medium = 2131361861; - - // aapt resource value: 0x7f0a000d - public const int Base_TextAppearance_AppCompat_Medium_Inverse = 2131361805; - - // aapt resource value: 0x7f0a0046 - public const int Base_TextAppearance_AppCompat_Menu = 2131361862; - - // aapt resource value: 0x7f0a00a1 - public const int Base_TextAppearance_AppCompat_SearchResult = 2131361953; - - // aapt resource value: 0x7f0a0047 - public const int Base_TextAppearance_AppCompat_SearchResult_Subtitle = 2131361863; - - // aapt resource value: 0x7f0a0048 - public const int Base_TextAppearance_AppCompat_SearchResult_Title = 2131361864; - - // aapt resource value: 0x7f0a0049 - public const int Base_TextAppearance_AppCompat_Small = 2131361865; - - // aapt resource value: 0x7f0a000e - public const int Base_TextAppearance_AppCompat_Small_Inverse = 2131361806; - - // aapt resource value: 0x7f0a004a - public const int Base_TextAppearance_AppCompat_Subhead = 2131361866; - - // aapt resource value: 0x7f0a000f - public const int Base_TextAppearance_AppCompat_Subhead_Inverse = 2131361807; - - // aapt resource value: 0x7f0a004b - public const int Base_TextAppearance_AppCompat_Title = 2131361867; - - // aapt resource value: 0x7f0a0010 - public const int Base_TextAppearance_AppCompat_Title_Inverse = 2131361808; - - // aapt resource value: 0x7f0a00a2 - public const int Base_TextAppearance_AppCompat_Tooltip = 2131361954; - - // aapt resource value: 0x7f0a0086 - public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Menu = 2131361926; - - // aapt resource value: 0x7f0a004c - public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle = 2131361868; - - // aapt resource value: 0x7f0a004d - public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = 2131361869; - - // aapt resource value: 0x7f0a004e - public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Title = 2131361870; - - // aapt resource value: 0x7f0a004f - public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = 2131361871; - - // aapt resource value: 0x7f0a0050 - public const int Base_TextAppearance_AppCompat_Widget_ActionMode_Subtitle = 2131361872; - - // aapt resource value: 0x7f0a0051 - public const int Base_TextAppearance_AppCompat_Widget_ActionMode_Title = 2131361873; - - // aapt resource value: 0x7f0a0052 - public const int Base_TextAppearance_AppCompat_Widget_Button = 2131361874; - - // aapt resource value: 0x7f0a008d - public const int Base_TextAppearance_AppCompat_Widget_Button_Borderless_Colored = 2131361933; - - // aapt resource value: 0x7f0a008e - public const int Base_TextAppearance_AppCompat_Widget_Button_Colored = 2131361934; - - // aapt resource value: 0x7f0a0087 - public const int Base_TextAppearance_AppCompat_Widget_Button_Inverse = 2131361927; - - // aapt resource value: 0x7f0a00a3 - public const int Base_TextAppearance_AppCompat_Widget_DropDownItem = 2131361955; - - // aapt resource value: 0x7f0a0053 - public const int Base_TextAppearance_AppCompat_Widget_PopupMenu_Header = 2131361875; - - // aapt resource value: 0x7f0a0054 - public const int Base_TextAppearance_AppCompat_Widget_PopupMenu_Large = 2131361876; - - // aapt resource value: 0x7f0a0055 - public const int Base_TextAppearance_AppCompat_Widget_PopupMenu_Small = 2131361877; - - // aapt resource value: 0x7f0a0056 - public const int Base_TextAppearance_AppCompat_Widget_Switch = 2131361878; - - // aapt resource value: 0x7f0a0057 - public const int Base_TextAppearance_AppCompat_Widget_TextView_SpinnerItem = 2131361879; - - // aapt resource value: 0x7f0a00a4 - public const int Base_TextAppearance_Widget_AppCompat_ExpandedMenu_Item = 2131361956; - - // aapt resource value: 0x7f0a0058 - public const int Base_TextAppearance_Widget_AppCompat_Toolbar_Subtitle = 2131361880; - - // aapt resource value: 0x7f0a0059 - public const int Base_TextAppearance_Widget_AppCompat_Toolbar_Title = 2131361881; - - // aapt resource value: 0x7f0a005a - public const int Base_Theme_AppCompat = 2131361882; - - // aapt resource value: 0x7f0a00a5 - public const int Base_Theme_AppCompat_CompactMenu = 2131361957; - - // aapt resource value: 0x7f0a0011 - public const int Base_Theme_AppCompat_Dialog = 2131361809; - - // aapt resource value: 0x7f0a0012 - public const int Base_Theme_AppCompat_Dialog_Alert = 2131361810; - - // aapt resource value: 0x7f0a00a6 - public const int Base_Theme_AppCompat_Dialog_FixedSize = 2131361958; - - // aapt resource value: 0x7f0a0013 - public const int Base_Theme_AppCompat_Dialog_MinWidth = 2131361811; - - // aapt resource value: 0x7f0a0001 - public const int Base_Theme_AppCompat_DialogWhenLarge = 2131361793; - - // aapt resource value: 0x7f0a005b - public const int Base_Theme_AppCompat_Light = 2131361883; - - // aapt resource value: 0x7f0a00a7 - public const int Base_Theme_AppCompat_Light_DarkActionBar = 2131361959; - - // aapt resource value: 0x7f0a0014 - public const int Base_Theme_AppCompat_Light_Dialog = 2131361812; - - // aapt resource value: 0x7f0a0015 - public const int Base_Theme_AppCompat_Light_Dialog_Alert = 2131361813; - - // aapt resource value: 0x7f0a00a8 - public const int Base_Theme_AppCompat_Light_Dialog_FixedSize = 2131361960; - - // aapt resource value: 0x7f0a0016 - public const int Base_Theme_AppCompat_Light_Dialog_MinWidth = 2131361814; - - // aapt resource value: 0x7f0a0002 - public const int Base_Theme_AppCompat_Light_DialogWhenLarge = 2131361794; - - // aapt resource value: 0x7f0a00a9 - public const int Base_ThemeOverlay_AppCompat = 2131361961; - - // aapt resource value: 0x7f0a00aa - public const int Base_ThemeOverlay_AppCompat_ActionBar = 2131361962; - - // aapt resource value: 0x7f0a00ab - public const int Base_ThemeOverlay_AppCompat_Dark = 2131361963; - - // aapt resource value: 0x7f0a00ac - public const int Base_ThemeOverlay_AppCompat_Dark_ActionBar = 2131361964; - - // aapt resource value: 0x7f0a0017 - public const int Base_ThemeOverlay_AppCompat_Dialog = 2131361815; - - // aapt resource value: 0x7f0a0018 - public const int Base_ThemeOverlay_AppCompat_Dialog_Alert = 2131361816; - - // aapt resource value: 0x7f0a00ad - public const int Base_ThemeOverlay_AppCompat_Light = 2131361965; - - // aapt resource value: 0x7f0a0019 - public const int Base_V11_Theme_AppCompat_Dialog = 2131361817; - - // aapt resource value: 0x7f0a001a - public const int Base_V11_Theme_AppCompat_Light_Dialog = 2131361818; - - // aapt resource value: 0x7f0a001b - public const int Base_V11_ThemeOverlay_AppCompat_Dialog = 2131361819; - - // aapt resource value: 0x7f0a0023 - public const int Base_V12_Widget_AppCompat_AutoCompleteTextView = 2131361827; - - // aapt resource value: 0x7f0a0024 - public const int Base_V12_Widget_AppCompat_EditText = 2131361828; - - // aapt resource value: 0x7f0a0160 - public const int Base_V14_Widget_Design_AppBarLayout = 2131362144; - - // aapt resource value: 0x7f0a005c - public const int Base_V21_Theme_AppCompat = 2131361884; - - // aapt resource value: 0x7f0a005d - public const int Base_V21_Theme_AppCompat_Dialog = 2131361885; - - // aapt resource value: 0x7f0a005e - public const int Base_V21_Theme_AppCompat_Light = 2131361886; - - // aapt resource value: 0x7f0a005f - public const int Base_V21_Theme_AppCompat_Light_Dialog = 2131361887; - - // aapt resource value: 0x7f0a0060 - public const int Base_V21_ThemeOverlay_AppCompat_Dialog = 2131361888; - - // aapt resource value: 0x7f0a015c - public const int Base_V21_Widget_Design_AppBarLayout = 2131362140; - - // aapt resource value: 0x7f0a0084 - public const int Base_V22_Theme_AppCompat = 2131361924; - - // aapt resource value: 0x7f0a0085 - public const int Base_V22_Theme_AppCompat_Light = 2131361925; - - // aapt resource value: 0x7f0a0088 - public const int Base_V23_Theme_AppCompat = 2131361928; - - // aapt resource value: 0x7f0a0089 - public const int Base_V23_Theme_AppCompat_Light = 2131361929; - - // aapt resource value: 0x7f0a0091 - public const int Base_V26_Theme_AppCompat = 2131361937; - - // aapt resource value: 0x7f0a0092 - public const int Base_V26_Theme_AppCompat_Light = 2131361938; - - // aapt resource value: 0x7f0a0093 - public const int Base_V26_Widget_AppCompat_Toolbar = 2131361939; - - // aapt resource value: 0x7f0a015e - public const int Base_V26_Widget_Design_AppBarLayout = 2131362142; - - // aapt resource value: 0x7f0a00ae - public const int Base_V7_Theme_AppCompat = 2131361966; - - // aapt resource value: 0x7f0a00af - public const int Base_V7_Theme_AppCompat_Dialog = 2131361967; - - // aapt resource value: 0x7f0a00b0 - public const int Base_V7_Theme_AppCompat_Light = 2131361968; - - // aapt resource value: 0x7f0a00b1 - public const int Base_V7_Theme_AppCompat_Light_Dialog = 2131361969; - - // aapt resource value: 0x7f0a00b2 - public const int Base_V7_ThemeOverlay_AppCompat_Dialog = 2131361970; - - // aapt resource value: 0x7f0a00b3 - public const int Base_V7_Widget_AppCompat_AutoCompleteTextView = 2131361971; - - // aapt resource value: 0x7f0a00b4 - public const int Base_V7_Widget_AppCompat_EditText = 2131361972; - - // aapt resource value: 0x7f0a00b5 - public const int Base_V7_Widget_AppCompat_Toolbar = 2131361973; - - // aapt resource value: 0x7f0a00b6 - public const int Base_Widget_AppCompat_ActionBar = 2131361974; - - // aapt resource value: 0x7f0a00b7 - public const int Base_Widget_AppCompat_ActionBar_Solid = 2131361975; - - // aapt resource value: 0x7f0a00b8 - public const int Base_Widget_AppCompat_ActionBar_TabBar = 2131361976; - - // aapt resource value: 0x7f0a0061 - public const int Base_Widget_AppCompat_ActionBar_TabText = 2131361889; - - // aapt resource value: 0x7f0a0062 - public const int Base_Widget_AppCompat_ActionBar_TabView = 2131361890; - - // aapt resource value: 0x7f0a0063 - public const int Base_Widget_AppCompat_ActionButton = 2131361891; - - // aapt resource value: 0x7f0a0064 - public const int Base_Widget_AppCompat_ActionButton_CloseMode = 2131361892; - - // aapt resource value: 0x7f0a0065 - public const int Base_Widget_AppCompat_ActionButton_Overflow = 2131361893; - - // aapt resource value: 0x7f0a00b9 - public const int Base_Widget_AppCompat_ActionMode = 2131361977; - - // aapt resource value: 0x7f0a00ba - public const int Base_Widget_AppCompat_ActivityChooserView = 2131361978; - - // aapt resource value: 0x7f0a0025 - public const int Base_Widget_AppCompat_AutoCompleteTextView = 2131361829; - - // aapt resource value: 0x7f0a0066 - public const int Base_Widget_AppCompat_Button = 2131361894; - - // aapt resource value: 0x7f0a0067 - public const int Base_Widget_AppCompat_Button_Borderless = 2131361895; - - // aapt resource value: 0x7f0a0068 - public const int Base_Widget_AppCompat_Button_Borderless_Colored = 2131361896; - - // aapt resource value: 0x7f0a00bb - public const int Base_Widget_AppCompat_Button_ButtonBar_AlertDialog = 2131361979; - - // aapt resource value: 0x7f0a008a - public const int Base_Widget_AppCompat_Button_Colored = 2131361930; - - // aapt resource value: 0x7f0a0069 - public const int Base_Widget_AppCompat_Button_Small = 2131361897; - - // aapt resource value: 0x7f0a006a - public const int Base_Widget_AppCompat_ButtonBar = 2131361898; - - // aapt resource value: 0x7f0a00bc - public const int Base_Widget_AppCompat_ButtonBar_AlertDialog = 2131361980; - - // aapt resource value: 0x7f0a006b - public const int Base_Widget_AppCompat_CompoundButton_CheckBox = 2131361899; - - // aapt resource value: 0x7f0a006c - public const int Base_Widget_AppCompat_CompoundButton_RadioButton = 2131361900; - - // aapt resource value: 0x7f0a00bd - public const int Base_Widget_AppCompat_CompoundButton_Switch = 2131361981; - - // aapt resource value: 0x7f0a0000 - public const int Base_Widget_AppCompat_DrawerArrowToggle = 2131361792; - - // aapt resource value: 0x7f0a00be - public const int Base_Widget_AppCompat_DrawerArrowToggle_Common = 2131361982; - - // aapt resource value: 0x7f0a006d - public const int Base_Widget_AppCompat_DropDownItem_Spinner = 2131361901; - - // aapt resource value: 0x7f0a0026 - public const int Base_Widget_AppCompat_EditText = 2131361830; - - // aapt resource value: 0x7f0a006e - public const int Base_Widget_AppCompat_ImageButton = 2131361902; - - // aapt resource value: 0x7f0a00bf - public const int Base_Widget_AppCompat_Light_ActionBar = 2131361983; - - // aapt resource value: 0x7f0a00c0 - public const int Base_Widget_AppCompat_Light_ActionBar_Solid = 2131361984; - - // aapt resource value: 0x7f0a00c1 - public const int Base_Widget_AppCompat_Light_ActionBar_TabBar = 2131361985; - - // aapt resource value: 0x7f0a006f - public const int Base_Widget_AppCompat_Light_ActionBar_TabText = 2131361903; - - // aapt resource value: 0x7f0a0070 - public const int Base_Widget_AppCompat_Light_ActionBar_TabText_Inverse = 2131361904; - - // aapt resource value: 0x7f0a0071 - public const int Base_Widget_AppCompat_Light_ActionBar_TabView = 2131361905; - - // aapt resource value: 0x7f0a0072 - public const int Base_Widget_AppCompat_Light_PopupMenu = 2131361906; - - // aapt resource value: 0x7f0a0073 - public const int Base_Widget_AppCompat_Light_PopupMenu_Overflow = 2131361907; - - // aapt resource value: 0x7f0a00c2 - public const int Base_Widget_AppCompat_ListMenuView = 2131361986; - - // aapt resource value: 0x7f0a0074 - public const int Base_Widget_AppCompat_ListPopupWindow = 2131361908; - - // aapt resource value: 0x7f0a0075 - public const int Base_Widget_AppCompat_ListView = 2131361909; - - // aapt resource value: 0x7f0a0076 - public const int Base_Widget_AppCompat_ListView_DropDown = 2131361910; - - // aapt resource value: 0x7f0a0077 - public const int Base_Widget_AppCompat_ListView_Menu = 2131361911; - - // aapt resource value: 0x7f0a0078 - public const int Base_Widget_AppCompat_PopupMenu = 2131361912; - - // aapt resource value: 0x7f0a0079 - public const int Base_Widget_AppCompat_PopupMenu_Overflow = 2131361913; - - // aapt resource value: 0x7f0a00c3 - public const int Base_Widget_AppCompat_PopupWindow = 2131361987; - - // aapt resource value: 0x7f0a001c - public const int Base_Widget_AppCompat_ProgressBar = 2131361820; - - // aapt resource value: 0x7f0a001d - public const int Base_Widget_AppCompat_ProgressBar_Horizontal = 2131361821; - - // aapt resource value: 0x7f0a007a - public const int Base_Widget_AppCompat_RatingBar = 2131361914; - - // aapt resource value: 0x7f0a008b - public const int Base_Widget_AppCompat_RatingBar_Indicator = 2131361931; - - // aapt resource value: 0x7f0a008c - public const int Base_Widget_AppCompat_RatingBar_Small = 2131361932; - - // aapt resource value: 0x7f0a00c4 - public const int Base_Widget_AppCompat_SearchView = 2131361988; - - // aapt resource value: 0x7f0a00c5 - public const int Base_Widget_AppCompat_SearchView_ActionBar = 2131361989; - - // aapt resource value: 0x7f0a007b - public const int Base_Widget_AppCompat_SeekBar = 2131361915; - - // aapt resource value: 0x7f0a00c6 - public const int Base_Widget_AppCompat_SeekBar_Discrete = 2131361990; - - // aapt resource value: 0x7f0a007c - public const int Base_Widget_AppCompat_Spinner = 2131361916; - - // aapt resource value: 0x7f0a0003 - public const int Base_Widget_AppCompat_Spinner_Underlined = 2131361795; - - // aapt resource value: 0x7f0a007d - public const int Base_Widget_AppCompat_TextView_SpinnerItem = 2131361917; - - // aapt resource value: 0x7f0a0094 - public const int Base_Widget_AppCompat_Toolbar = 2131361940; - - // aapt resource value: 0x7f0a007e - public const int Base_Widget_AppCompat_Toolbar_Button_Navigation = 2131361918; - - // aapt resource value: 0x7f0a015d - public const int Base_Widget_Design_AppBarLayout = 2131362141; - - // aapt resource value: 0x7f0a0161 - public const int Base_Widget_Design_TabLayout = 2131362145; - - // aapt resource value: 0x7f0a001e - public const int Platform_AppCompat = 2131361822; - - // aapt resource value: 0x7f0a001f - public const int Platform_AppCompat_Light = 2131361823; - - // aapt resource value: 0x7f0a007f - public const int Platform_ThemeOverlay_AppCompat = 2131361919; - - // aapt resource value: 0x7f0a0080 - public const int Platform_ThemeOverlay_AppCompat_Dark = 2131361920; - - // aapt resource value: 0x7f0a0081 - public const int Platform_ThemeOverlay_AppCompat_Light = 2131361921; - - // aapt resource value: 0x7f0a0020 - public const int Platform_V11_AppCompat = 2131361824; - - // aapt resource value: 0x7f0a0021 - public const int Platform_V11_AppCompat_Light = 2131361825; - - // aapt resource value: 0x7f0a0028 - public const int Platform_V14_AppCompat = 2131361832; - - // aapt resource value: 0x7f0a0029 - public const int Platform_V14_AppCompat_Light = 2131361833; - - // aapt resource value: 0x7f0a0082 - public const int Platform_V21_AppCompat = 2131361922; - - // aapt resource value: 0x7f0a0083 - public const int Platform_V21_AppCompat_Light = 2131361923; - - // aapt resource value: 0x7f0a008f - public const int Platform_V25_AppCompat = 2131361935; - - // aapt resource value: 0x7f0a0090 - public const int Platform_V25_AppCompat_Light = 2131361936; - - // aapt resource value: 0x7f0a0022 - public const int Platform_Widget_AppCompat_Spinner = 2131361826; - - // aapt resource value: 0x7f0a002b - public const int RtlOverlay_DialogWindowTitle_AppCompat = 2131361835; - - // aapt resource value: 0x7f0a002c - public const int RtlOverlay_Widget_AppCompat_ActionBar_TitleItem = 2131361836; - - // aapt resource value: 0x7f0a002d - public const int RtlOverlay_Widget_AppCompat_DialogTitle_Icon = 2131361837; - - // aapt resource value: 0x7f0a002e - public const int RtlOverlay_Widget_AppCompat_PopupMenuItem = 2131361838; - - // aapt resource value: 0x7f0a002f - public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_InternalGroup = 2131361839; - - // aapt resource value: 0x7f0a0030 - public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_Text = 2131361840; - - // aapt resource value: 0x7f0a0031 - public const int RtlOverlay_Widget_AppCompat_Search_DropDown = 2131361841; - - // aapt resource value: 0x7f0a0032 - public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Icon1 = 2131361842; - - // aapt resource value: 0x7f0a0033 - public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Icon2 = 2131361843; - - // aapt resource value: 0x7f0a0034 - public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Query = 2131361844; - - // aapt resource value: 0x7f0a0035 - public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Text = 2131361845; - - // aapt resource value: 0x7f0a0036 - public const int RtlOverlay_Widget_AppCompat_SearchView_MagIcon = 2131361846; - - // aapt resource value: 0x7f0a0037 - public const int RtlUnderlay_Widget_AppCompat_ActionButton = 2131361847; - - // aapt resource value: 0x7f0a0038 - public const int RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = 2131361848; - - // aapt resource value: 0x7f0a00c7 - public const int TextAppearance_AppCompat = 2131361991; - - // aapt resource value: 0x7f0a00c8 - public const int TextAppearance_AppCompat_Body1 = 2131361992; - - // aapt resource value: 0x7f0a00c9 - public const int TextAppearance_AppCompat_Body2 = 2131361993; - - // aapt resource value: 0x7f0a00ca - public const int TextAppearance_AppCompat_Button = 2131361994; - - // aapt resource value: 0x7f0a00cb - public const int TextAppearance_AppCompat_Caption = 2131361995; - - // aapt resource value: 0x7f0a00cc - public const int TextAppearance_AppCompat_Display1 = 2131361996; - - // aapt resource value: 0x7f0a00cd - public const int TextAppearance_AppCompat_Display2 = 2131361997; - - // aapt resource value: 0x7f0a00ce - public const int TextAppearance_AppCompat_Display3 = 2131361998; - - // aapt resource value: 0x7f0a00cf - public const int TextAppearance_AppCompat_Display4 = 2131361999; - - // aapt resource value: 0x7f0a00d0 - public const int TextAppearance_AppCompat_Headline = 2131362000; - - // aapt resource value: 0x7f0a00d1 - public const int TextAppearance_AppCompat_Inverse = 2131362001; - - // aapt resource value: 0x7f0a00d2 - public const int TextAppearance_AppCompat_Large = 2131362002; - - // aapt resource value: 0x7f0a00d3 - public const int TextAppearance_AppCompat_Large_Inverse = 2131362003; - - // aapt resource value: 0x7f0a00d4 - public const int TextAppearance_AppCompat_Light_SearchResult_Subtitle = 2131362004; - - // aapt resource value: 0x7f0a00d5 - public const int TextAppearance_AppCompat_Light_SearchResult_Title = 2131362005; - - // aapt resource value: 0x7f0a00d6 - public const int TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = 2131362006; - - // aapt resource value: 0x7f0a00d7 - public const int TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = 2131362007; - - // aapt resource value: 0x7f0a00d8 - public const int TextAppearance_AppCompat_Medium = 2131362008; - - // aapt resource value: 0x7f0a00d9 - public const int TextAppearance_AppCompat_Medium_Inverse = 2131362009; - - // aapt resource value: 0x7f0a00da - public const int TextAppearance_AppCompat_Menu = 2131362010; - - // aapt resource value: 0x7f0a00db - public const int TextAppearance_AppCompat_SearchResult_Subtitle = 2131362011; - - // aapt resource value: 0x7f0a00dc - public const int TextAppearance_AppCompat_SearchResult_Title = 2131362012; - - // aapt resource value: 0x7f0a00dd - public const int TextAppearance_AppCompat_Small = 2131362013; - - // aapt resource value: 0x7f0a00de - public const int TextAppearance_AppCompat_Small_Inverse = 2131362014; - - // aapt resource value: 0x7f0a00df - public const int TextAppearance_AppCompat_Subhead = 2131362015; - - // aapt resource value: 0x7f0a00e0 - public const int TextAppearance_AppCompat_Subhead_Inverse = 2131362016; - - // aapt resource value: 0x7f0a00e1 - public const int TextAppearance_AppCompat_Title = 2131362017; - - // aapt resource value: 0x7f0a00e2 - public const int TextAppearance_AppCompat_Title_Inverse = 2131362018; - - // aapt resource value: 0x7f0a002a - public const int TextAppearance_AppCompat_Tooltip = 2131361834; - - // aapt resource value: 0x7f0a00e3 - public const int TextAppearance_AppCompat_Widget_ActionBar_Menu = 2131362019; - - // aapt resource value: 0x7f0a00e4 - public const int TextAppearance_AppCompat_Widget_ActionBar_Subtitle = 2131362020; - - // aapt resource value: 0x7f0a00e5 - public const int TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = 2131362021; - - // aapt resource value: 0x7f0a00e6 - public const int TextAppearance_AppCompat_Widget_ActionBar_Title = 2131362022; - - // aapt resource value: 0x7f0a00e7 - public const int TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = 2131362023; - - // aapt resource value: 0x7f0a00e8 - public const int TextAppearance_AppCompat_Widget_ActionMode_Subtitle = 2131362024; - - // aapt resource value: 0x7f0a00e9 - public const int TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse = 2131362025; - - // aapt resource value: 0x7f0a00ea - public const int TextAppearance_AppCompat_Widget_ActionMode_Title = 2131362026; - - // aapt resource value: 0x7f0a00eb - public const int TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse = 2131362027; - - // aapt resource value: 0x7f0a00ec - public const int TextAppearance_AppCompat_Widget_Button = 2131362028; - - // aapt resource value: 0x7f0a00ed - public const int TextAppearance_AppCompat_Widget_Button_Borderless_Colored = 2131362029; - - // aapt resource value: 0x7f0a00ee - public const int TextAppearance_AppCompat_Widget_Button_Colored = 2131362030; - - // aapt resource value: 0x7f0a00ef - public const int TextAppearance_AppCompat_Widget_Button_Inverse = 2131362031; - - // aapt resource value: 0x7f0a00f0 - public const int TextAppearance_AppCompat_Widget_DropDownItem = 2131362032; - - // aapt resource value: 0x7f0a00f1 - public const int TextAppearance_AppCompat_Widget_PopupMenu_Header = 2131362033; - - // aapt resource value: 0x7f0a00f2 - public const int TextAppearance_AppCompat_Widget_PopupMenu_Large = 2131362034; - - // aapt resource value: 0x7f0a00f3 - public const int TextAppearance_AppCompat_Widget_PopupMenu_Small = 2131362035; - - // aapt resource value: 0x7f0a00f4 - public const int TextAppearance_AppCompat_Widget_Switch = 2131362036; - - // aapt resource value: 0x7f0a00f5 - public const int TextAppearance_AppCompat_Widget_TextView_SpinnerItem = 2131362037; - - // aapt resource value: 0x7f0a0179 - public const int TextAppearance_Compat_Notification = 2131362169; - - // aapt resource value: 0x7f0a017a - public const int TextAppearance_Compat_Notification_Info = 2131362170; - - // aapt resource value: 0x7f0a0156 - public const int TextAppearance_Compat_Notification_Info_Media = 2131362134; - - // aapt resource value: 0x7f0a017f - public const int TextAppearance_Compat_Notification_Line2 = 2131362175; - - // aapt resource value: 0x7f0a015a - public const int TextAppearance_Compat_Notification_Line2_Media = 2131362138; - - // aapt resource value: 0x7f0a0157 - public const int TextAppearance_Compat_Notification_Media = 2131362135; - - // aapt resource value: 0x7f0a017b - public const int TextAppearance_Compat_Notification_Time = 2131362171; - - // aapt resource value: 0x7f0a0158 - public const int TextAppearance_Compat_Notification_Time_Media = 2131362136; - - // aapt resource value: 0x7f0a017c - public const int TextAppearance_Compat_Notification_Title = 2131362172; - - // aapt resource value: 0x7f0a0159 - public const int TextAppearance_Compat_Notification_Title_Media = 2131362137; - - // aapt resource value: 0x7f0a0162 - public const int TextAppearance_Design_CollapsingToolbar_Expanded = 2131362146; - - // aapt resource value: 0x7f0a0163 - public const int TextAppearance_Design_Counter = 2131362147; - - // aapt resource value: 0x7f0a0164 - public const int TextAppearance_Design_Counter_Overflow = 2131362148; - - // aapt resource value: 0x7f0a0165 - public const int TextAppearance_Design_Error = 2131362149; - - // aapt resource value: 0x7f0a0166 - public const int TextAppearance_Design_Hint = 2131362150; - - // aapt resource value: 0x7f0a0167 - public const int TextAppearance_Design_Snackbar_Message = 2131362151; - - // aapt resource value: 0x7f0a0168 - public const int TextAppearance_Design_Tab = 2131362152; - - // aapt resource value: 0x7f0a00f6 - public const int TextAppearance_Widget_AppCompat_ExpandedMenu_Item = 2131362038; - - // aapt resource value: 0x7f0a00f7 - public const int TextAppearance_Widget_AppCompat_Toolbar_Subtitle = 2131362039; - - // aapt resource value: 0x7f0a00f8 - public const int TextAppearance_Widget_AppCompat_Toolbar_Title = 2131362040; - - // aapt resource value: 0x7f0a00f9 - public const int Theme_AppCompat = 2131362041; - - // aapt resource value: 0x7f0a00fa - public const int Theme_AppCompat_CompactMenu = 2131362042; - - // aapt resource value: 0x7f0a0004 - public const int Theme_AppCompat_DayNight = 2131361796; - - // aapt resource value: 0x7f0a0005 - public const int Theme_AppCompat_DayNight_DarkActionBar = 2131361797; - - // aapt resource value: 0x7f0a0006 - public const int Theme_AppCompat_DayNight_Dialog = 2131361798; - - // aapt resource value: 0x7f0a0007 - public const int Theme_AppCompat_DayNight_Dialog_Alert = 2131361799; - - // aapt resource value: 0x7f0a0008 - public const int Theme_AppCompat_DayNight_Dialog_MinWidth = 2131361800; - - // aapt resource value: 0x7f0a0009 - public const int Theme_AppCompat_DayNight_DialogWhenLarge = 2131361801; - - // aapt resource value: 0x7f0a000a - public const int Theme_AppCompat_DayNight_NoActionBar = 2131361802; - - // aapt resource value: 0x7f0a00fb - public const int Theme_AppCompat_Dialog = 2131362043; - - // aapt resource value: 0x7f0a00fc - public const int Theme_AppCompat_Dialog_Alert = 2131362044; - - // aapt resource value: 0x7f0a00fd - public const int Theme_AppCompat_Dialog_MinWidth = 2131362045; - - // aapt resource value: 0x7f0a00fe - public const int Theme_AppCompat_DialogWhenLarge = 2131362046; - - // aapt resource value: 0x7f0a00ff - public const int Theme_AppCompat_Light = 2131362047; - - // aapt resource value: 0x7f0a0100 - public const int Theme_AppCompat_Light_DarkActionBar = 2131362048; - - // aapt resource value: 0x7f0a0101 - public const int Theme_AppCompat_Light_Dialog = 2131362049; - - // aapt resource value: 0x7f0a0102 - public const int Theme_AppCompat_Light_Dialog_Alert = 2131362050; - - // aapt resource value: 0x7f0a0103 - public const int Theme_AppCompat_Light_Dialog_MinWidth = 2131362051; - - // aapt resource value: 0x7f0a0104 - public const int Theme_AppCompat_Light_DialogWhenLarge = 2131362052; - - // aapt resource value: 0x7f0a0105 - public const int Theme_AppCompat_Light_NoActionBar = 2131362053; - - // aapt resource value: 0x7f0a0106 - public const int Theme_AppCompat_NoActionBar = 2131362054; - - // aapt resource value: 0x7f0a0169 - public const int Theme_Design = 2131362153; - - // aapt resource value: 0x7f0a016a - public const int Theme_Design_BottomSheetDialog = 2131362154; - - // aapt resource value: 0x7f0a016b - public const int Theme_Design_Light = 2131362155; - - // aapt resource value: 0x7f0a016c - public const int Theme_Design_Light_BottomSheetDialog = 2131362156; - - // aapt resource value: 0x7f0a016d - public const int Theme_Design_Light_NoActionBar = 2131362157; - - // aapt resource value: 0x7f0a016e - public const int Theme_Design_NoActionBar = 2131362158; - - // aapt resource value: 0x7f0a0107 - public const int ThemeOverlay_AppCompat = 2131362055; - - // aapt resource value: 0x7f0a0108 - public const int ThemeOverlay_AppCompat_ActionBar = 2131362056; - - // aapt resource value: 0x7f0a0109 - public const int ThemeOverlay_AppCompat_Dark = 2131362057; - - // aapt resource value: 0x7f0a010a - public const int ThemeOverlay_AppCompat_Dark_ActionBar = 2131362058; - - // aapt resource value: 0x7f0a010b - public const int ThemeOverlay_AppCompat_Dialog = 2131362059; - - // aapt resource value: 0x7f0a010c - public const int ThemeOverlay_AppCompat_Dialog_Alert = 2131362060; - - // aapt resource value: 0x7f0a010d - public const int ThemeOverlay_AppCompat_Light = 2131362061; - - // aapt resource value: 0x7f0a010e - public const int Widget_AppCompat_ActionBar = 2131362062; - - // aapt resource value: 0x7f0a010f - public const int Widget_AppCompat_ActionBar_Solid = 2131362063; - - // aapt resource value: 0x7f0a0110 - public const int Widget_AppCompat_ActionBar_TabBar = 2131362064; - - // aapt resource value: 0x7f0a0111 - public const int Widget_AppCompat_ActionBar_TabText = 2131362065; - - // aapt resource value: 0x7f0a0112 - public const int Widget_AppCompat_ActionBar_TabView = 2131362066; - - // aapt resource value: 0x7f0a0113 - public const int Widget_AppCompat_ActionButton = 2131362067; - - // aapt resource value: 0x7f0a0114 - public const int Widget_AppCompat_ActionButton_CloseMode = 2131362068; - - // aapt resource value: 0x7f0a0115 - public const int Widget_AppCompat_ActionButton_Overflow = 2131362069; - - // aapt resource value: 0x7f0a0116 - public const int Widget_AppCompat_ActionMode = 2131362070; - - // aapt resource value: 0x7f0a0117 - public const int Widget_AppCompat_ActivityChooserView = 2131362071; - - // aapt resource value: 0x7f0a0118 - public const int Widget_AppCompat_AutoCompleteTextView = 2131362072; - - // aapt resource value: 0x7f0a0119 - public const int Widget_AppCompat_Button = 2131362073; - - // aapt resource value: 0x7f0a011a - public const int Widget_AppCompat_Button_Borderless = 2131362074; - - // aapt resource value: 0x7f0a011b - public const int Widget_AppCompat_Button_Borderless_Colored = 2131362075; - - // aapt resource value: 0x7f0a011c - public const int Widget_AppCompat_Button_ButtonBar_AlertDialog = 2131362076; - - // aapt resource value: 0x7f0a011d - public const int Widget_AppCompat_Button_Colored = 2131362077; - - // aapt resource value: 0x7f0a011e - public const int Widget_AppCompat_Button_Small = 2131362078; - - // aapt resource value: 0x7f0a011f - public const int Widget_AppCompat_ButtonBar = 2131362079; - - // aapt resource value: 0x7f0a0120 - public const int Widget_AppCompat_ButtonBar_AlertDialog = 2131362080; - - // aapt resource value: 0x7f0a0121 - public const int Widget_AppCompat_CompoundButton_CheckBox = 2131362081; - - // aapt resource value: 0x7f0a0122 - public const int Widget_AppCompat_CompoundButton_RadioButton = 2131362082; - - // aapt resource value: 0x7f0a0123 - public const int Widget_AppCompat_CompoundButton_Switch = 2131362083; - - // aapt resource value: 0x7f0a0124 - public const int Widget_AppCompat_DrawerArrowToggle = 2131362084; - - // aapt resource value: 0x7f0a0125 - public const int Widget_AppCompat_DropDownItem_Spinner = 2131362085; - - // aapt resource value: 0x7f0a0126 - public const int Widget_AppCompat_EditText = 2131362086; - - // aapt resource value: 0x7f0a0127 - public const int Widget_AppCompat_ImageButton = 2131362087; - - // aapt resource value: 0x7f0a0128 - public const int Widget_AppCompat_Light_ActionBar = 2131362088; - - // aapt resource value: 0x7f0a0129 - public const int Widget_AppCompat_Light_ActionBar_Solid = 2131362089; - - // aapt resource value: 0x7f0a012a - public const int Widget_AppCompat_Light_ActionBar_Solid_Inverse = 2131362090; - - // aapt resource value: 0x7f0a012b - public const int Widget_AppCompat_Light_ActionBar_TabBar = 2131362091; - - // aapt resource value: 0x7f0a012c - public const int Widget_AppCompat_Light_ActionBar_TabBar_Inverse = 2131362092; - - // aapt resource value: 0x7f0a012d - public const int Widget_AppCompat_Light_ActionBar_TabText = 2131362093; - - // aapt resource value: 0x7f0a012e - public const int Widget_AppCompat_Light_ActionBar_TabText_Inverse = 2131362094; - - // aapt resource value: 0x7f0a012f - public const int Widget_AppCompat_Light_ActionBar_TabView = 2131362095; - - // aapt resource value: 0x7f0a0130 - public const int Widget_AppCompat_Light_ActionBar_TabView_Inverse = 2131362096; - - // aapt resource value: 0x7f0a0131 - public const int Widget_AppCompat_Light_ActionButton = 2131362097; - - // aapt resource value: 0x7f0a0132 - public const int Widget_AppCompat_Light_ActionButton_CloseMode = 2131362098; - - // aapt resource value: 0x7f0a0133 - public const int Widget_AppCompat_Light_ActionButton_Overflow = 2131362099; - - // aapt resource value: 0x7f0a0134 - public const int Widget_AppCompat_Light_ActionMode_Inverse = 2131362100; - - // aapt resource value: 0x7f0a0135 - public const int Widget_AppCompat_Light_ActivityChooserView = 2131362101; - - // aapt resource value: 0x7f0a0136 - public const int Widget_AppCompat_Light_AutoCompleteTextView = 2131362102; - - // aapt resource value: 0x7f0a0137 - public const int Widget_AppCompat_Light_DropDownItem_Spinner = 2131362103; - - // aapt resource value: 0x7f0a0138 - public const int Widget_AppCompat_Light_ListPopupWindow = 2131362104; - - // aapt resource value: 0x7f0a0139 - public const int Widget_AppCompat_Light_ListView_DropDown = 2131362105; - - // aapt resource value: 0x7f0a013a - public const int Widget_AppCompat_Light_PopupMenu = 2131362106; - - // aapt resource value: 0x7f0a013b - public const int Widget_AppCompat_Light_PopupMenu_Overflow = 2131362107; - - // aapt resource value: 0x7f0a013c - public const int Widget_AppCompat_Light_SearchView = 2131362108; - - // aapt resource value: 0x7f0a013d - public const int Widget_AppCompat_Light_Spinner_DropDown_ActionBar = 2131362109; - - // aapt resource value: 0x7f0a013e - public const int Widget_AppCompat_ListMenuView = 2131362110; - - // aapt resource value: 0x7f0a013f - public const int Widget_AppCompat_ListPopupWindow = 2131362111; - - // aapt resource value: 0x7f0a0140 - public const int Widget_AppCompat_ListView = 2131362112; - - // aapt resource value: 0x7f0a0141 - public const int Widget_AppCompat_ListView_DropDown = 2131362113; - - // aapt resource value: 0x7f0a0142 - public const int Widget_AppCompat_ListView_Menu = 2131362114; - - // aapt resource value: 0x7f0a0143 - public const int Widget_AppCompat_PopupMenu = 2131362115; - - // aapt resource value: 0x7f0a0144 - public const int Widget_AppCompat_PopupMenu_Overflow = 2131362116; - - // aapt resource value: 0x7f0a0145 - public const int Widget_AppCompat_PopupWindow = 2131362117; - - // aapt resource value: 0x7f0a0146 - public const int Widget_AppCompat_ProgressBar = 2131362118; - - // aapt resource value: 0x7f0a0147 - public const int Widget_AppCompat_ProgressBar_Horizontal = 2131362119; - - // aapt resource value: 0x7f0a0148 - public const int Widget_AppCompat_RatingBar = 2131362120; - - // aapt resource value: 0x7f0a0149 - public const int Widget_AppCompat_RatingBar_Indicator = 2131362121; - - // aapt resource value: 0x7f0a014a - public const int Widget_AppCompat_RatingBar_Small = 2131362122; - - // aapt resource value: 0x7f0a014b - public const int Widget_AppCompat_SearchView = 2131362123; - - // aapt resource value: 0x7f0a014c - public const int Widget_AppCompat_SearchView_ActionBar = 2131362124; - - // aapt resource value: 0x7f0a014d - public const int Widget_AppCompat_SeekBar = 2131362125; - - // aapt resource value: 0x7f0a014e - public const int Widget_AppCompat_SeekBar_Discrete = 2131362126; - - // aapt resource value: 0x7f0a014f - public const int Widget_AppCompat_Spinner = 2131362127; - - // aapt resource value: 0x7f0a0150 - public const int Widget_AppCompat_Spinner_DropDown = 2131362128; - - // aapt resource value: 0x7f0a0151 - public const int Widget_AppCompat_Spinner_DropDown_ActionBar = 2131362129; - - // aapt resource value: 0x7f0a0152 - public const int Widget_AppCompat_Spinner_Underlined = 2131362130; - - // aapt resource value: 0x7f0a0153 - public const int Widget_AppCompat_TextView_SpinnerItem = 2131362131; - - // aapt resource value: 0x7f0a0154 - public const int Widget_AppCompat_Toolbar = 2131362132; - - // aapt resource value: 0x7f0a0155 - public const int Widget_AppCompat_Toolbar_Button_Navigation = 2131362133; - - // aapt resource value: 0x7f0a017d - public const int Widget_Compat_NotificationActionContainer = 2131362173; - - // aapt resource value: 0x7f0a017e - public const int Widget_Compat_NotificationActionText = 2131362174; - - // aapt resource value: 0x7f0a016f - public const int Widget_Design_AppBarLayout = 2131362159; - - // aapt resource value: 0x7f0a0170 - public const int Widget_Design_BottomNavigationView = 2131362160; - - // aapt resource value: 0x7f0a0171 - public const int Widget_Design_BottomSheet_Modal = 2131362161; - - // aapt resource value: 0x7f0a0172 - public const int Widget_Design_CollapsingToolbar = 2131362162; - - // aapt resource value: 0x7f0a0173 - public const int Widget_Design_CoordinatorLayout = 2131362163; - - // aapt resource value: 0x7f0a0174 - public const int Widget_Design_FloatingActionButton = 2131362164; - - // aapt resource value: 0x7f0a0175 - public const int Widget_Design_NavigationView = 2131362165; - - // aapt resource value: 0x7f0a0176 - public const int Widget_Design_ScrimInsetsFrameLayout = 2131362166; - - // aapt resource value: 0x7f0a0177 - public const int Widget_Design_Snackbar = 2131362167; - - // aapt resource value: 0x7f0a015b - public const int Widget_Design_TabLayout = 2131362139; - - // aapt resource value: 0x7f0a0178 - public const int Widget_Design_TextInputLayout = 2131362168; - - static Style() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Style() - { - } - } - - public partial class Styleable - { - - public static int[] ActionBar = new int[] { - 2130771978, - 2130771980, - 2130771981, - 2130771982, - 2130771983, - 2130771984, - 2130771985, - 2130771986, - 2130771987, - 2130771988, - 2130771989, - 2130771990, - 2130771991, - 2130771992, - 2130771993, - 2130771994, - 2130771995, - 2130771996, - 2130771997, - 2130771998, - 2130771999, - 2130772000, - 2130772001, - 2130772002, - 2130772003, - 2130772004, - 2130772005, - 2130772006, - 2130772076}; - - // aapt resource value: 10 - public const int ActionBar_background = 10; - - // aapt resource value: 12 - public const int ActionBar_backgroundSplit = 12; - - // aapt resource value: 11 - public const int ActionBar_backgroundStacked = 11; - - // aapt resource value: 21 - public const int ActionBar_contentInsetEnd = 21; - - // aapt resource value: 25 - public const int ActionBar_contentInsetEndWithActions = 25; - - // aapt resource value: 22 - public const int ActionBar_contentInsetLeft = 22; - - // aapt resource value: 23 - public const int ActionBar_contentInsetRight = 23; - - // aapt resource value: 20 - public const int ActionBar_contentInsetStart = 20; - - // aapt resource value: 24 - public const int ActionBar_contentInsetStartWithNavigation = 24; - - // aapt resource value: 13 - public const int ActionBar_customNavigationLayout = 13; - - // aapt resource value: 3 - public const int ActionBar_displayOptions = 3; - - // aapt resource value: 9 - public const int ActionBar_divider = 9; - - // aapt resource value: 26 - public const int ActionBar_elevation = 26; - - // aapt resource value: 0 - public const int ActionBar_height = 0; - - // aapt resource value: 19 - public const int ActionBar_hideOnContentScroll = 19; - - // aapt resource value: 28 - public const int ActionBar_homeAsUpIndicator = 28; - - // aapt resource value: 14 - public const int ActionBar_homeLayout = 14; - - // aapt resource value: 7 - public const int ActionBar_icon = 7; - - // aapt resource value: 16 - public const int ActionBar_indeterminateProgressStyle = 16; - - // aapt resource value: 18 - public const int ActionBar_itemPadding = 18; - - // aapt resource value: 8 - public const int ActionBar_logo = 8; - - // aapt resource value: 2 - public const int ActionBar_navigationMode = 2; - - // aapt resource value: 27 - public const int ActionBar_popupTheme = 27; - - // aapt resource value: 17 - public const int ActionBar_progressBarPadding = 17; - - // aapt resource value: 15 - public const int ActionBar_progressBarStyle = 15; - - // aapt resource value: 4 - public const int ActionBar_subtitle = 4; - - // aapt resource value: 6 - public const int ActionBar_subtitleTextStyle = 6; - - // aapt resource value: 1 - public const int ActionBar_title = 1; - - // aapt resource value: 5 - public const int ActionBar_titleTextStyle = 5; - - public static int[] ActionBarLayout = new int[] { - 16842931}; - - // aapt resource value: 0 - public const int ActionBarLayout_android_layout_gravity = 0; - - public static int[] ActionMenuItemView = new int[] { - 16843071}; - - // aapt resource value: 0 - public const int ActionMenuItemView_android_minWidth = 0; - - public static int[] ActionMenuView; - - public static int[] ActionMode = new int[] { - 2130771978, - 2130771984, - 2130771985, - 2130771989, - 2130771991, - 2130772007}; - - // aapt resource value: 3 - public const int ActionMode_background = 3; - - // aapt resource value: 4 - public const int ActionMode_backgroundSplit = 4; - - // aapt resource value: 5 - public const int ActionMode_closeItemLayout = 5; - - // aapt resource value: 0 - public const int ActionMode_height = 0; - - // aapt resource value: 2 - public const int ActionMode_subtitleTextStyle = 2; - - // aapt resource value: 1 - public const int ActionMode_titleTextStyle = 1; - - public static int[] ActivityChooserView = new int[] { - 2130772008, - 2130772009}; - - // aapt resource value: 1 - public const int ActivityChooserView_expandActivityOverflowButtonDrawable = 1; - - // aapt resource value: 0 - public const int ActivityChooserView_initialActivityCount = 0; - - public static int[] AlertDialog = new int[] { - 16842994, - 2130772010, - 2130772011, - 2130772012, - 2130772013, - 2130772014, - 2130772015}; - - // aapt resource value: 0 - public const int AlertDialog_android_layout = 0; - - // aapt resource value: 1 - public const int AlertDialog_buttonPanelSideLayout = 1; - - // aapt resource value: 5 - public const int AlertDialog_listItemLayout = 5; - - // aapt resource value: 2 - public const int AlertDialog_listLayout = 2; - - // aapt resource value: 3 - public const int AlertDialog_multiChoiceItemLayout = 3; - - // aapt resource value: 6 - public const int AlertDialog_showTitle = 6; - - // aapt resource value: 4 - public const int AlertDialog_singleChoiceItemLayout = 4; - - public static int[] AppBarLayout = new int[] { - 16842964, - 16843919, - 16844096, - 2130772005, - 2130772223}; - - // aapt resource value: 0 - public const int AppBarLayout_android_background = 0; - - // aapt resource value: 2 - public const int AppBarLayout_android_keyboardNavigationCluster = 2; - - // aapt resource value: 1 - public const int AppBarLayout_android_touchscreenBlocksFocus = 1; - - // aapt resource value: 3 - public const int AppBarLayout_elevation = 3; - - // aapt resource value: 4 - public const int AppBarLayout_expanded = 4; - - public static int[] AppBarLayoutStates = new int[] { - 2130772224, - 2130772225}; - - // aapt resource value: 0 - public const int AppBarLayoutStates_state_collapsed = 0; - - // aapt resource value: 1 - public const int AppBarLayoutStates_state_collapsible = 1; - - public static int[] AppBarLayout_Layout = new int[] { - 2130772226, - 2130772227}; - - // aapt resource value: 0 - public const int AppBarLayout_Layout_layout_scrollFlags = 0; - - // aapt resource value: 1 - public const int AppBarLayout_Layout_layout_scrollInterpolator = 1; - - public static int[] AppCompatImageView = new int[] { - 16843033, - 2130772016, - 2130772017, - 2130772018}; - - // aapt resource value: 0 - public const int AppCompatImageView_android_src = 0; - - // aapt resource value: 1 - public const int AppCompatImageView_srcCompat = 1; - - // aapt resource value: 2 - public const int AppCompatImageView_tint = 2; - - // aapt resource value: 3 - public const int AppCompatImageView_tintMode = 3; - - public static int[] AppCompatSeekBar = new int[] { - 16843074, - 2130772019, - 2130772020, - 2130772021}; - - // aapt resource value: 0 - public const int AppCompatSeekBar_android_thumb = 0; - - // aapt resource value: 1 - public const int AppCompatSeekBar_tickMark = 1; - - // aapt resource value: 2 - public const int AppCompatSeekBar_tickMarkTint = 2; - - // aapt resource value: 3 - public const int AppCompatSeekBar_tickMarkTintMode = 3; - - public static int[] AppCompatTextHelper = new int[] { - 16842804, - 16843117, - 16843118, - 16843119, - 16843120, - 16843666, - 16843667}; - - // aapt resource value: 2 - public const int AppCompatTextHelper_android_drawableBottom = 2; - - // aapt resource value: 6 - public const int AppCompatTextHelper_android_drawableEnd = 6; - - // aapt resource value: 3 - public const int AppCompatTextHelper_android_drawableLeft = 3; - - // aapt resource value: 4 - public const int AppCompatTextHelper_android_drawableRight = 4; - - // aapt resource value: 5 - public const int AppCompatTextHelper_android_drawableStart = 5; - - // aapt resource value: 1 - public const int AppCompatTextHelper_android_drawableTop = 1; - - // aapt resource value: 0 - public const int AppCompatTextHelper_android_textAppearance = 0; - - public static int[] AppCompatTextView = new int[] { - 16842804, - 2130772022, - 2130772023, - 2130772024, - 2130772025, - 2130772026, - 2130772027, - 2130772028}; - - // aapt resource value: 0 - public const int AppCompatTextView_android_textAppearance = 0; - - // aapt resource value: 6 - public const int AppCompatTextView_autoSizeMaxTextSize = 6; - - // aapt resource value: 5 - public const int AppCompatTextView_autoSizeMinTextSize = 5; - - // aapt resource value: 4 - public const int AppCompatTextView_autoSizePresetSizes = 4; - - // aapt resource value: 3 - public const int AppCompatTextView_autoSizeStepGranularity = 3; - - // aapt resource value: 2 - public const int AppCompatTextView_autoSizeTextType = 2; - - // aapt resource value: 7 - public const int AppCompatTextView_fontFamily = 7; - - // aapt resource value: 1 - public const int AppCompatTextView_textAllCaps = 1; - - public static int[] AppCompatTheme = new int[] { - 16842839, - 16842926, - 2130772029, - 2130772030, - 2130772031, - 2130772032, - 2130772033, - 2130772034, - 2130772035, - 2130772036, - 2130772037, - 2130772038, - 2130772039, - 2130772040, - 2130772041, - 2130772042, - 2130772043, - 2130772044, - 2130772045, - 2130772046, - 2130772047, - 2130772048, - 2130772049, - 2130772050, - 2130772051, - 2130772052, - 2130772053, - 2130772054, - 2130772055, - 2130772056, - 2130772057, - 2130772058, - 2130772059, - 2130772060, - 2130772061, - 2130772062, - 2130772063, - 2130772064, - 2130772065, - 2130772066, - 2130772067, - 2130772068, - 2130772069, - 2130772070, - 2130772071, - 2130772072, - 2130772073, - 2130772074, - 2130772075, - 2130772076, - 2130772077, - 2130772078, - 2130772079, - 2130772080, - 2130772081, - 2130772082, - 2130772083, - 2130772084, - 2130772085, - 2130772086, - 2130772087, - 2130772088, - 2130772089, - 2130772090, - 2130772091, - 2130772092, - 2130772093, - 2130772094, - 2130772095, - 2130772096, - 2130772097, - 2130772098, - 2130772099, - 2130772100, - 2130772101, - 2130772102, - 2130772103, - 2130772104, - 2130772105, - 2130772106, - 2130772107, - 2130772108, - 2130772109, - 2130772110, - 2130772111, - 2130772112, - 2130772113, - 2130772114, - 2130772115, - 2130772116, - 2130772117, - 2130772118, - 2130772119, - 2130772120, - 2130772121, - 2130772122, - 2130772123, - 2130772124, - 2130772125, - 2130772126, - 2130772127, - 2130772128, - 2130772129, - 2130772130, - 2130772131, - 2130772132, - 2130772133, - 2130772134, - 2130772135, - 2130772136, - 2130772137, - 2130772138, - 2130772139, - 2130772140, - 2130772141, - 2130772142, - 2130772143, - 2130772144, - 2130772145}; - - // aapt resource value: 23 - public const int AppCompatTheme_actionBarDivider = 23; - - // aapt resource value: 24 - public const int AppCompatTheme_actionBarItemBackground = 24; - - // aapt resource value: 17 - public const int AppCompatTheme_actionBarPopupTheme = 17; - - // aapt resource value: 22 - public const int AppCompatTheme_actionBarSize = 22; - - // aapt resource value: 19 - public const int AppCompatTheme_actionBarSplitStyle = 19; - - // aapt resource value: 18 - public const int AppCompatTheme_actionBarStyle = 18; - - // aapt resource value: 13 - public const int AppCompatTheme_actionBarTabBarStyle = 13; - - // aapt resource value: 12 - public const int AppCompatTheme_actionBarTabStyle = 12; - - // aapt resource value: 14 - public const int AppCompatTheme_actionBarTabTextStyle = 14; - - // aapt resource value: 20 - public const int AppCompatTheme_actionBarTheme = 20; - - // aapt resource value: 21 - public const int AppCompatTheme_actionBarWidgetTheme = 21; - - // aapt resource value: 50 - public const int AppCompatTheme_actionButtonStyle = 50; - - // aapt resource value: 46 - public const int AppCompatTheme_actionDropDownStyle = 46; - - // aapt resource value: 25 - public const int AppCompatTheme_actionMenuTextAppearance = 25; - - // aapt resource value: 26 - public const int AppCompatTheme_actionMenuTextColor = 26; - - // aapt resource value: 29 - public const int AppCompatTheme_actionModeBackground = 29; - - // aapt resource value: 28 - public const int AppCompatTheme_actionModeCloseButtonStyle = 28; - - // aapt resource value: 31 - public const int AppCompatTheme_actionModeCloseDrawable = 31; - - // aapt resource value: 33 - public const int AppCompatTheme_actionModeCopyDrawable = 33; - - // aapt resource value: 32 - public const int AppCompatTheme_actionModeCutDrawable = 32; - - // aapt resource value: 37 - public const int AppCompatTheme_actionModeFindDrawable = 37; - - // aapt resource value: 34 - public const int AppCompatTheme_actionModePasteDrawable = 34; - - // aapt resource value: 39 - public const int AppCompatTheme_actionModePopupWindowStyle = 39; - - // aapt resource value: 35 - public const int AppCompatTheme_actionModeSelectAllDrawable = 35; - - // aapt resource value: 36 - public const int AppCompatTheme_actionModeShareDrawable = 36; - - // aapt resource value: 30 - public const int AppCompatTheme_actionModeSplitBackground = 30; - - // aapt resource value: 27 - public const int AppCompatTheme_actionModeStyle = 27; - - // aapt resource value: 38 - public const int AppCompatTheme_actionModeWebSearchDrawable = 38; - - // aapt resource value: 15 - public const int AppCompatTheme_actionOverflowButtonStyle = 15; - - // aapt resource value: 16 - public const int AppCompatTheme_actionOverflowMenuStyle = 16; - - // aapt resource value: 58 - public const int AppCompatTheme_activityChooserViewStyle = 58; - - // aapt resource value: 95 - public const int AppCompatTheme_alertDialogButtonGroupStyle = 95; - - // aapt resource value: 96 - public const int AppCompatTheme_alertDialogCenterButtons = 96; - - // aapt resource value: 94 - public const int AppCompatTheme_alertDialogStyle = 94; - - // aapt resource value: 97 - public const int AppCompatTheme_alertDialogTheme = 97; - - // aapt resource value: 1 - public const int AppCompatTheme_android_windowAnimationStyle = 1; - - // aapt resource value: 0 - public const int AppCompatTheme_android_windowIsFloating = 0; - - // aapt resource value: 102 - public const int AppCompatTheme_autoCompleteTextViewStyle = 102; - - // aapt resource value: 55 - public const int AppCompatTheme_borderlessButtonStyle = 55; - - // aapt resource value: 52 - public const int AppCompatTheme_buttonBarButtonStyle = 52; - - // aapt resource value: 100 - public const int AppCompatTheme_buttonBarNegativeButtonStyle = 100; - - // aapt resource value: 101 - public const int AppCompatTheme_buttonBarNeutralButtonStyle = 101; - - // aapt resource value: 99 - public const int AppCompatTheme_buttonBarPositiveButtonStyle = 99; - - // aapt resource value: 51 - public const int AppCompatTheme_buttonBarStyle = 51; - - // aapt resource value: 103 - public const int AppCompatTheme_buttonStyle = 103; - - // aapt resource value: 104 - public const int AppCompatTheme_buttonStyleSmall = 104; - - // aapt resource value: 105 - public const int AppCompatTheme_checkboxStyle = 105; - - // aapt resource value: 106 - public const int AppCompatTheme_checkedTextViewStyle = 106; - - // aapt resource value: 86 - public const int AppCompatTheme_colorAccent = 86; - - // aapt resource value: 93 - public const int AppCompatTheme_colorBackgroundFloating = 93; - - // aapt resource value: 90 - public const int AppCompatTheme_colorButtonNormal = 90; - - // aapt resource value: 88 - public const int AppCompatTheme_colorControlActivated = 88; - - // aapt resource value: 89 - public const int AppCompatTheme_colorControlHighlight = 89; - - // aapt resource value: 87 - public const int AppCompatTheme_colorControlNormal = 87; - - // aapt resource value: 118 - public const int AppCompatTheme_colorError = 118; - - // aapt resource value: 84 - public const int AppCompatTheme_colorPrimary = 84; - - // aapt resource value: 85 - public const int AppCompatTheme_colorPrimaryDark = 85; - - // aapt resource value: 91 - public const int AppCompatTheme_colorSwitchThumbNormal = 91; - - // aapt resource value: 92 - public const int AppCompatTheme_controlBackground = 92; - - // aapt resource value: 44 - public const int AppCompatTheme_dialogPreferredPadding = 44; - - // aapt resource value: 43 - public const int AppCompatTheme_dialogTheme = 43; - - // aapt resource value: 57 - public const int AppCompatTheme_dividerHorizontal = 57; - - // aapt resource value: 56 - public const int AppCompatTheme_dividerVertical = 56; - - // aapt resource value: 75 - public const int AppCompatTheme_dropDownListViewStyle = 75; - - // aapt resource value: 47 - public const int AppCompatTheme_dropdownListPreferredItemHeight = 47; - - // aapt resource value: 64 - public const int AppCompatTheme_editTextBackground = 64; - - // aapt resource value: 63 - public const int AppCompatTheme_editTextColor = 63; - - // aapt resource value: 107 - public const int AppCompatTheme_editTextStyle = 107; - - // aapt resource value: 49 - public const int AppCompatTheme_homeAsUpIndicator = 49; - - // aapt resource value: 65 - public const int AppCompatTheme_imageButtonStyle = 65; - - // aapt resource value: 83 - public const int AppCompatTheme_listChoiceBackgroundIndicator = 83; - - // aapt resource value: 45 - public const int AppCompatTheme_listDividerAlertDialog = 45; - - // aapt resource value: 115 - public const int AppCompatTheme_listMenuViewStyle = 115; - - // aapt resource value: 76 - public const int AppCompatTheme_listPopupWindowStyle = 76; - - // aapt resource value: 70 - public const int AppCompatTheme_listPreferredItemHeight = 70; - - // aapt resource value: 72 - public const int AppCompatTheme_listPreferredItemHeightLarge = 72; - - // aapt resource value: 71 - public const int AppCompatTheme_listPreferredItemHeightSmall = 71; - - // aapt resource value: 73 - public const int AppCompatTheme_listPreferredItemPaddingLeft = 73; - - // aapt resource value: 74 - public const int AppCompatTheme_listPreferredItemPaddingRight = 74; - - // aapt resource value: 80 - public const int AppCompatTheme_panelBackground = 80; - - // aapt resource value: 82 - public const int AppCompatTheme_panelMenuListTheme = 82; - - // aapt resource value: 81 - public const int AppCompatTheme_panelMenuListWidth = 81; - - // aapt resource value: 61 - public const int AppCompatTheme_popupMenuStyle = 61; - - // aapt resource value: 62 - public const int AppCompatTheme_popupWindowStyle = 62; - - // aapt resource value: 108 - public const int AppCompatTheme_radioButtonStyle = 108; - - // aapt resource value: 109 - public const int AppCompatTheme_ratingBarStyle = 109; - - // aapt resource value: 110 - public const int AppCompatTheme_ratingBarStyleIndicator = 110; - - // aapt resource value: 111 - public const int AppCompatTheme_ratingBarStyleSmall = 111; - - // aapt resource value: 69 - public const int AppCompatTheme_searchViewStyle = 69; - - // aapt resource value: 112 - public const int AppCompatTheme_seekBarStyle = 112; - - // aapt resource value: 53 - public const int AppCompatTheme_selectableItemBackground = 53; - - // aapt resource value: 54 - public const int AppCompatTheme_selectableItemBackgroundBorderless = 54; - - // aapt resource value: 48 - public const int AppCompatTheme_spinnerDropDownItemStyle = 48; - - // aapt resource value: 113 - public const int AppCompatTheme_spinnerStyle = 113; - - // aapt resource value: 114 - public const int AppCompatTheme_switchStyle = 114; - - // aapt resource value: 40 - public const int AppCompatTheme_textAppearanceLargePopupMenu = 40; - - // aapt resource value: 77 - public const int AppCompatTheme_textAppearanceListItem = 77; - - // aapt resource value: 78 - public const int AppCompatTheme_textAppearanceListItemSecondary = 78; - - // aapt resource value: 79 - public const int AppCompatTheme_textAppearanceListItemSmall = 79; - - // aapt resource value: 42 - public const int AppCompatTheme_textAppearancePopupMenuHeader = 42; - - // aapt resource value: 67 - public const int AppCompatTheme_textAppearanceSearchResultSubtitle = 67; - - // aapt resource value: 66 - public const int AppCompatTheme_textAppearanceSearchResultTitle = 66; - - // aapt resource value: 41 - public const int AppCompatTheme_textAppearanceSmallPopupMenu = 41; - - // aapt resource value: 98 - public const int AppCompatTheme_textColorAlertDialogListItem = 98; - - // aapt resource value: 68 - public const int AppCompatTheme_textColorSearchUrl = 68; - - // aapt resource value: 60 - public const int AppCompatTheme_toolbarNavigationButtonStyle = 60; - - // aapt resource value: 59 - public const int AppCompatTheme_toolbarStyle = 59; - - // aapt resource value: 117 - public const int AppCompatTheme_tooltipForegroundColor = 117; - - // aapt resource value: 116 - public const int AppCompatTheme_tooltipFrameBackground = 116; - - // aapt resource value: 2 - public const int AppCompatTheme_windowActionBar = 2; - - // aapt resource value: 4 - public const int AppCompatTheme_windowActionBarOverlay = 4; - - // aapt resource value: 5 - public const int AppCompatTheme_windowActionModeOverlay = 5; - - // aapt resource value: 9 - public const int AppCompatTheme_windowFixedHeightMajor = 9; - - // aapt resource value: 7 - public const int AppCompatTheme_windowFixedHeightMinor = 7; - - // aapt resource value: 6 - public const int AppCompatTheme_windowFixedWidthMajor = 6; - - // aapt resource value: 8 - public const int AppCompatTheme_windowFixedWidthMinor = 8; - - // aapt resource value: 10 - public const int AppCompatTheme_windowMinWidthMajor = 10; - - // aapt resource value: 11 - public const int AppCompatTheme_windowMinWidthMinor = 11; - - // aapt resource value: 3 - public const int AppCompatTheme_windowNoTitle = 3; - - public static int[] BottomNavigationView = new int[] { - 2130772005, - 2130772266, - 2130772267, - 2130772268, - 2130772269}; - - // aapt resource value: 0 - public const int BottomNavigationView_elevation = 0; - - // aapt resource value: 4 - public const int BottomNavigationView_itemBackground = 4; - - // aapt resource value: 2 - public const int BottomNavigationView_itemIconTint = 2; - - // aapt resource value: 3 - public const int BottomNavigationView_itemTextColor = 3; - - // aapt resource value: 1 - public const int BottomNavigationView_menu = 1; - - public static int[] BottomSheetBehavior_Layout = new int[] { - 2130772228, - 2130772229, - 2130772230}; - - // aapt resource value: 1 - public const int BottomSheetBehavior_Layout_behavior_hideable = 1; - - // aapt resource value: 0 - public const int BottomSheetBehavior_Layout_behavior_peekHeight = 0; - - // aapt resource value: 2 - public const int BottomSheetBehavior_Layout_behavior_skipCollapsed = 2; - - public static int[] ButtonBarLayout = new int[] { - 2130772146}; - - // aapt resource value: 0 - public const int ButtonBarLayout_allowStacking = 0; - - public static int[] CollapsingToolbarLayout = new int[] { - 2130771980, - 2130772231, - 2130772232, - 2130772233, - 2130772234, - 2130772235, - 2130772236, - 2130772237, - 2130772238, - 2130772239, - 2130772240, - 2130772241, - 2130772242, - 2130772243, - 2130772244, - 2130772245}; - - // aapt resource value: 13 - public const int CollapsingToolbarLayout_collapsedTitleGravity = 13; - - // aapt resource value: 7 - public const int CollapsingToolbarLayout_collapsedTitleTextAppearance = 7; - - // aapt resource value: 8 - public const int CollapsingToolbarLayout_contentScrim = 8; - - // aapt resource value: 14 - public const int CollapsingToolbarLayout_expandedTitleGravity = 14; - - // aapt resource value: 1 - public const int CollapsingToolbarLayout_expandedTitleMargin = 1; - - // aapt resource value: 5 - public const int CollapsingToolbarLayout_expandedTitleMarginBottom = 5; - - // aapt resource value: 4 - public const int CollapsingToolbarLayout_expandedTitleMarginEnd = 4; - - // aapt resource value: 2 - public const int CollapsingToolbarLayout_expandedTitleMarginStart = 2; - - // aapt resource value: 3 - public const int CollapsingToolbarLayout_expandedTitleMarginTop = 3; - - // aapt resource value: 6 - public const int CollapsingToolbarLayout_expandedTitleTextAppearance = 6; - - // aapt resource value: 12 - public const int CollapsingToolbarLayout_scrimAnimationDuration = 12; - - // aapt resource value: 11 - public const int CollapsingToolbarLayout_scrimVisibleHeightTrigger = 11; - - // aapt resource value: 9 - public const int CollapsingToolbarLayout_statusBarScrim = 9; - - // aapt resource value: 0 - public const int CollapsingToolbarLayout_title = 0; - - // aapt resource value: 15 - public const int CollapsingToolbarLayout_titleEnabled = 15; - - // aapt resource value: 10 - public const int CollapsingToolbarLayout_toolbarId = 10; - - public static int[] CollapsingToolbarLayout_Layout = new int[] { - 2130772246, - 2130772247}; - - // aapt resource value: 0 - public const int CollapsingToolbarLayout_Layout_layout_collapseMode = 0; - - // aapt resource value: 1 - public const int CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier = 1; - - public static int[] ColorStateListItem = new int[] { - 16843173, - 16843551, - 2130772147}; - - // aapt resource value: 2 - public const int ColorStateListItem_alpha = 2; - - // aapt resource value: 1 - public const int ColorStateListItem_android_alpha = 1; - - // aapt resource value: 0 - public const int ColorStateListItem_android_color = 0; - - public static int[] CompoundButton = new int[] { - 16843015, - 2130772148, - 2130772149}; - - // aapt resource value: 0 - public const int CompoundButton_android_button = 0; - - // aapt resource value: 1 - public const int CompoundButton_buttonTint = 1; - - // aapt resource value: 2 - public const int CompoundButton_buttonTintMode = 2; - - public static int[] CoordinatorLayout = new int[] { - 2130772248, - 2130772249}; - - // aapt resource value: 0 - public const int CoordinatorLayout_keylines = 0; - - // aapt resource value: 1 - public const int CoordinatorLayout_statusBarBackground = 1; - - public static int[] CoordinatorLayout_Layout = new int[] { - 16842931, - 2130772250, - 2130772251, - 2130772252, - 2130772253, - 2130772254, - 2130772255}; - - // aapt resource value: 0 - public const int CoordinatorLayout_Layout_android_layout_gravity = 0; - - // aapt resource value: 2 - public const int CoordinatorLayout_Layout_layout_anchor = 2; - - // aapt resource value: 4 - public const int CoordinatorLayout_Layout_layout_anchorGravity = 4; - - // aapt resource value: 1 - public const int CoordinatorLayout_Layout_layout_behavior = 1; - - // aapt resource value: 6 - public const int CoordinatorLayout_Layout_layout_dodgeInsetEdges = 6; - - // aapt resource value: 5 - public const int CoordinatorLayout_Layout_layout_insetEdge = 5; - - // aapt resource value: 3 - public const int CoordinatorLayout_Layout_layout_keyline = 3; - - public static int[] DesignTheme = new int[] { - 2130772256, - 2130772257, - 2130772258}; - - // aapt resource value: 0 - public const int DesignTheme_bottomSheetDialogTheme = 0; - - // aapt resource value: 1 - public const int DesignTheme_bottomSheetStyle = 1; - - // aapt resource value: 2 - public const int DesignTheme_textColorError = 2; - - public static int[] DrawerArrowToggle = new int[] { - 2130772150, - 2130772151, - 2130772152, - 2130772153, - 2130772154, - 2130772155, - 2130772156, - 2130772157}; - - // aapt resource value: 4 - public const int DrawerArrowToggle_arrowHeadLength = 4; - - // aapt resource value: 5 - public const int DrawerArrowToggle_arrowShaftLength = 5; - - // aapt resource value: 6 - public const int DrawerArrowToggle_barLength = 6; - - // aapt resource value: 0 - public const int DrawerArrowToggle_color = 0; - - // aapt resource value: 2 - public const int DrawerArrowToggle_drawableSize = 2; - - // aapt resource value: 3 - public const int DrawerArrowToggle_gapBetweenBars = 3; - - // aapt resource value: 1 - public const int DrawerArrowToggle_spinBars = 1; - - // aapt resource value: 7 - public const int DrawerArrowToggle_thickness = 7; - - public static int[] FloatingActionButton = new int[] { - 2130772005, - 2130772221, - 2130772222, - 2130772259, - 2130772260, - 2130772261, - 2130772262, - 2130772263}; - - // aapt resource value: 1 - public const int FloatingActionButton_backgroundTint = 1; - - // aapt resource value: 2 - public const int FloatingActionButton_backgroundTintMode = 2; - - // aapt resource value: 6 - public const int FloatingActionButton_borderWidth = 6; - - // aapt resource value: 0 - public const int FloatingActionButton_elevation = 0; - - // aapt resource value: 4 - public const int FloatingActionButton_fabSize = 4; - - // aapt resource value: 5 - public const int FloatingActionButton_pressedTranslationZ = 5; - - // aapt resource value: 3 - public const int FloatingActionButton_rippleColor = 3; - - // aapt resource value: 7 - public const int FloatingActionButton_useCompatPadding = 7; - - public static int[] FloatingActionButton_Behavior_Layout = new int[] { - 2130772264}; - - // aapt resource value: 0 - public const int FloatingActionButton_Behavior_Layout_behavior_autoHide = 0; - - public static int[] FontFamily = new int[] { - 2130772305, - 2130772306, - 2130772307, - 2130772308, - 2130772309, - 2130772310}; - - // aapt resource value: 0 - public const int FontFamily_fontProviderAuthority = 0; - - // aapt resource value: 3 - public const int FontFamily_fontProviderCerts = 3; - - // aapt resource value: 4 - public const int FontFamily_fontProviderFetchStrategy = 4; - - // aapt resource value: 5 - public const int FontFamily_fontProviderFetchTimeout = 5; - - // aapt resource value: 1 - public const int FontFamily_fontProviderPackage = 1; - - // aapt resource value: 2 - public const int FontFamily_fontProviderQuery = 2; - - public static int[] FontFamilyFont = new int[] { - 16844082, - 16844083, - 16844095, - 2130772311, - 2130772312, - 2130772313}; - - // aapt resource value: 0 - public const int FontFamilyFont_android_font = 0; - - // aapt resource value: 2 - public const int FontFamilyFont_android_fontStyle = 2; - - // aapt resource value: 1 - public const int FontFamilyFont_android_fontWeight = 1; - - // aapt resource value: 4 - public const int FontFamilyFont_font = 4; - - // aapt resource value: 3 - public const int FontFamilyFont_fontStyle = 3; - - // aapt resource value: 5 - public const int FontFamilyFont_fontWeight = 5; - - public static int[] ForegroundLinearLayout = new int[] { - 16843017, - 16843264, - 2130772265}; - - // aapt resource value: 0 - public const int ForegroundLinearLayout_android_foreground = 0; - - // aapt resource value: 1 - public const int ForegroundLinearLayout_android_foregroundGravity = 1; - - // aapt resource value: 2 - public const int ForegroundLinearLayout_foregroundInsidePadding = 2; - - public static int[] LinearLayoutCompat = new int[] { - 16842927, - 16842948, - 16843046, - 16843047, - 16843048, - 2130771988, - 2130772158, - 2130772159, - 2130772160}; - - // aapt resource value: 2 - public const int LinearLayoutCompat_android_baselineAligned = 2; - - // aapt resource value: 3 - public const int LinearLayoutCompat_android_baselineAlignedChildIndex = 3; - - // aapt resource value: 0 - public const int LinearLayoutCompat_android_gravity = 0; - - // aapt resource value: 1 - public const int LinearLayoutCompat_android_orientation = 1; - - // aapt resource value: 4 - public const int LinearLayoutCompat_android_weightSum = 4; - - // aapt resource value: 5 - public const int LinearLayoutCompat_divider = 5; - - // aapt resource value: 8 - public const int LinearLayoutCompat_dividerPadding = 8; - - // aapt resource value: 6 - public const int LinearLayoutCompat_measureWithLargestChild = 6; - - // aapt resource value: 7 - public const int LinearLayoutCompat_showDividers = 7; - - public static int[] LinearLayoutCompat_Layout = new int[] { - 16842931, - 16842996, - 16842997, - 16843137}; - - // aapt resource value: 0 - public const int LinearLayoutCompat_Layout_android_layout_gravity = 0; - - // aapt resource value: 2 - public const int LinearLayoutCompat_Layout_android_layout_height = 2; - - // aapt resource value: 3 - public const int LinearLayoutCompat_Layout_android_layout_weight = 3; - - // aapt resource value: 1 - public const int LinearLayoutCompat_Layout_android_layout_width = 1; - - public static int[] ListPopupWindow = new int[] { - 16843436, - 16843437}; - - // aapt resource value: 0 - public const int ListPopupWindow_android_dropDownHorizontalOffset = 0; - - // aapt resource value: 1 - public const int ListPopupWindow_android_dropDownVerticalOffset = 1; - - public static int[] MenuGroup = new int[] { - 16842766, - 16842960, - 16843156, - 16843230, - 16843231, - 16843232}; - - // aapt resource value: 5 - public const int MenuGroup_android_checkableBehavior = 5; - - // aapt resource value: 0 - public const int MenuGroup_android_enabled = 0; - - // aapt resource value: 1 - public const int MenuGroup_android_id = 1; - - // aapt resource value: 3 - public const int MenuGroup_android_menuCategory = 3; - - // aapt resource value: 4 - public const int MenuGroup_android_orderInCategory = 4; - - // aapt resource value: 2 - public const int MenuGroup_android_visible = 2; - - public static int[] MenuItem = new int[] { - 16842754, - 16842766, - 16842960, - 16843014, - 16843156, - 16843230, - 16843231, - 16843233, - 16843234, - 16843235, - 16843236, - 16843237, - 16843375, - 2130772161, - 2130772162, - 2130772163, - 2130772164, - 2130772165, - 2130772166, - 2130772167, - 2130772168, - 2130772169, - 2130772170}; - - // aapt resource value: 16 - public const int MenuItem_actionLayout = 16; - - // aapt resource value: 18 - public const int MenuItem_actionProviderClass = 18; - - // aapt resource value: 17 - public const int MenuItem_actionViewClass = 17; - - // aapt resource value: 13 - public const int MenuItem_alphabeticModifiers = 13; - - // aapt resource value: 9 - public const int MenuItem_android_alphabeticShortcut = 9; - - // aapt resource value: 11 - public const int MenuItem_android_checkable = 11; - - // aapt resource value: 3 - public const int MenuItem_android_checked = 3; - - // aapt resource value: 1 - public const int MenuItem_android_enabled = 1; - - // aapt resource value: 0 - public const int MenuItem_android_icon = 0; - - // aapt resource value: 2 - public const int MenuItem_android_id = 2; - - // aapt resource value: 5 - public const int MenuItem_android_menuCategory = 5; - - // aapt resource value: 10 - public const int MenuItem_android_numericShortcut = 10; - - // aapt resource value: 12 - public const int MenuItem_android_onClick = 12; - - // aapt resource value: 6 - public const int MenuItem_android_orderInCategory = 6; - - // aapt resource value: 7 - public const int MenuItem_android_title = 7; - - // aapt resource value: 8 - public const int MenuItem_android_titleCondensed = 8; - - // aapt resource value: 4 - public const int MenuItem_android_visible = 4; - - // aapt resource value: 19 - public const int MenuItem_contentDescription = 19; - - // aapt resource value: 21 - public const int MenuItem_iconTint = 21; - - // aapt resource value: 22 - public const int MenuItem_iconTintMode = 22; - - // aapt resource value: 14 - public const int MenuItem_numericModifiers = 14; - - // aapt resource value: 15 - public const int MenuItem_showAsAction = 15; - - // aapt resource value: 20 - public const int MenuItem_tooltipText = 20; - - public static int[] MenuView = new int[] { - 16842926, - 16843052, - 16843053, - 16843054, - 16843055, - 16843056, - 16843057, - 2130772171, - 2130772172}; - - // aapt resource value: 4 - public const int MenuView_android_headerBackground = 4; - - // aapt resource value: 2 - public const int MenuView_android_horizontalDivider = 2; - - // aapt resource value: 5 - public const int MenuView_android_itemBackground = 5; - - // aapt resource value: 6 - public const int MenuView_android_itemIconDisabledAlpha = 6; - - // aapt resource value: 1 - public const int MenuView_android_itemTextAppearance = 1; - - // aapt resource value: 3 - public const int MenuView_android_verticalDivider = 3; - - // aapt resource value: 0 - public const int MenuView_android_windowAnimationStyle = 0; - - // aapt resource value: 7 - public const int MenuView_preserveIconSpacing = 7; - - // aapt resource value: 8 - public const int MenuView_subMenuArrow = 8; - - public static int[] NavigationView = new int[] { - 16842964, - 16842973, - 16843039, - 2130772005, - 2130772266, - 2130772267, - 2130772268, - 2130772269, - 2130772270, - 2130772271}; - - // aapt resource value: 0 - public const int NavigationView_android_background = 0; - - // aapt resource value: 1 - public const int NavigationView_android_fitsSystemWindows = 1; - - // aapt resource value: 2 - public const int NavigationView_android_maxWidth = 2; - - // aapt resource value: 3 - public const int NavigationView_elevation = 3; - - // aapt resource value: 9 - public const int NavigationView_headerLayout = 9; - - // aapt resource value: 7 - public const int NavigationView_itemBackground = 7; - - // aapt resource value: 5 - public const int NavigationView_itemIconTint = 5; - - // aapt resource value: 8 - public const int NavigationView_itemTextAppearance = 8; - - // aapt resource value: 6 - public const int NavigationView_itemTextColor = 6; - - // aapt resource value: 4 - public const int NavigationView_menu = 4; - - public static int[] PopupWindow = new int[] { - 16843126, - 16843465, - 2130772173}; - - // aapt resource value: 1 - public const int PopupWindow_android_popupAnimationStyle = 1; - - // aapt resource value: 0 - public const int PopupWindow_android_popupBackground = 0; - - // aapt resource value: 2 - public const int PopupWindow_overlapAnchor = 2; - - public static int[] PopupWindowBackgroundState = new int[] { - 2130772174}; - - // aapt resource value: 0 - public const int PopupWindowBackgroundState_state_above_anchor = 0; - - public static int[] RecycleListView = new int[] { - 2130772175, - 2130772176}; - - // aapt resource value: 0 - public const int RecycleListView_paddingBottomNoButtons = 0; - - // aapt resource value: 1 - public const int RecycleListView_paddingTopNoTitle = 1; - - public static int[] RecyclerView = new int[] { - 16842948, - 16842993, - 2130771968, - 2130771969, - 2130771970, - 2130771971, - 2130771972, - 2130771973, - 2130771974, - 2130771975, - 2130771976}; - - // aapt resource value: 1 - public const int RecyclerView_android_descendantFocusability = 1; - - // aapt resource value: 0 - public const int RecyclerView_android_orientation = 0; - - // aapt resource value: 6 - public const int RecyclerView_fastScrollEnabled = 6; - - // aapt resource value: 9 - public const int RecyclerView_fastScrollHorizontalThumbDrawable = 9; - - // aapt resource value: 10 - public const int RecyclerView_fastScrollHorizontalTrackDrawable = 10; - - // aapt resource value: 7 - public const int RecyclerView_fastScrollVerticalThumbDrawable = 7; - - // aapt resource value: 8 - public const int RecyclerView_fastScrollVerticalTrackDrawable = 8; - - // aapt resource value: 2 - public const int RecyclerView_layoutManager = 2; - - // aapt resource value: 4 - public const int RecyclerView_reverseLayout = 4; - - // aapt resource value: 3 - public const int RecyclerView_spanCount = 3; - - // aapt resource value: 5 - public const int RecyclerView_stackFromEnd = 5; - - public static int[] ScrimInsetsFrameLayout = new int[] { - 2130772272}; - - // aapt resource value: 0 - public const int ScrimInsetsFrameLayout_insetForeground = 0; - - public static int[] ScrollingViewBehavior_Layout = new int[] { - 2130772273}; - - // aapt resource value: 0 - public const int ScrollingViewBehavior_Layout_behavior_overlapTop = 0; - - public static int[] SearchView = new int[] { - 16842970, - 16843039, - 16843296, - 16843364, - 2130772177, - 2130772178, - 2130772179, - 2130772180, - 2130772181, - 2130772182, - 2130772183, - 2130772184, - 2130772185, - 2130772186, - 2130772187, - 2130772188, - 2130772189}; - - // aapt resource value: 0 - public const int SearchView_android_focusable = 0; - - // aapt resource value: 3 - public const int SearchView_android_imeOptions = 3; - - // aapt resource value: 2 - public const int SearchView_android_inputType = 2; - - // aapt resource value: 1 - public const int SearchView_android_maxWidth = 1; - - // aapt resource value: 8 - public const int SearchView_closeIcon = 8; - - // aapt resource value: 13 - public const int SearchView_commitIcon = 13; - - // aapt resource value: 7 - public const int SearchView_defaultQueryHint = 7; - - // aapt resource value: 9 - public const int SearchView_goIcon = 9; - - // aapt resource value: 5 - public const int SearchView_iconifiedByDefault = 5; - - // aapt resource value: 4 - public const int SearchView_layout = 4; - - // aapt resource value: 15 - public const int SearchView_queryBackground = 15; - - // aapt resource value: 6 - public const int SearchView_queryHint = 6; - - // aapt resource value: 11 - public const int SearchView_searchHintIcon = 11; - - // aapt resource value: 10 - public const int SearchView_searchIcon = 10; - - // aapt resource value: 16 - public const int SearchView_submitBackground = 16; - - // aapt resource value: 14 - public const int SearchView_suggestionRowLayout = 14; - - // aapt resource value: 12 - public const int SearchView_voiceIcon = 12; - - public static int[] SnackbarLayout = new int[] { - 16843039, - 2130772005, - 2130772274}; - - // aapt resource value: 0 - public const int SnackbarLayout_android_maxWidth = 0; - - // aapt resource value: 1 - public const int SnackbarLayout_elevation = 1; - - // aapt resource value: 2 - public const int SnackbarLayout_maxActionInlineWidth = 2; - - public static int[] Spinner = new int[] { - 16842930, - 16843126, - 16843131, - 16843362, - 2130772006}; - - // aapt resource value: 3 - public const int Spinner_android_dropDownWidth = 3; - - // aapt resource value: 0 - public const int Spinner_android_entries = 0; - - // aapt resource value: 1 - public const int Spinner_android_popupBackground = 1; - - // aapt resource value: 2 - public const int Spinner_android_prompt = 2; - - // aapt resource value: 4 - public const int Spinner_popupTheme = 4; - - public static int[] SwitchCompat = new int[] { - 16843044, - 16843045, - 16843074, - 2130772190, - 2130772191, - 2130772192, - 2130772193, - 2130772194, - 2130772195, - 2130772196, - 2130772197, - 2130772198, - 2130772199, - 2130772200}; - - // aapt resource value: 1 - public const int SwitchCompat_android_textOff = 1; - - // aapt resource value: 0 - public const int SwitchCompat_android_textOn = 0; - - // aapt resource value: 2 - public const int SwitchCompat_android_thumb = 2; - - // aapt resource value: 13 - public const int SwitchCompat_showText = 13; - - // aapt resource value: 12 - public const int SwitchCompat_splitTrack = 12; - - // aapt resource value: 10 - public const int SwitchCompat_switchMinWidth = 10; - - // aapt resource value: 11 - public const int SwitchCompat_switchPadding = 11; - - // aapt resource value: 9 - public const int SwitchCompat_switchTextAppearance = 9; - - // aapt resource value: 8 - public const int SwitchCompat_thumbTextPadding = 8; - - // aapt resource value: 3 - public const int SwitchCompat_thumbTint = 3; - - // aapt resource value: 4 - public const int SwitchCompat_thumbTintMode = 4; - - // aapt resource value: 5 - public const int SwitchCompat_track = 5; - - // aapt resource value: 6 - public const int SwitchCompat_trackTint = 6; - - // aapt resource value: 7 - public const int SwitchCompat_trackTintMode = 7; - - public static int[] TabItem = new int[] { - 16842754, - 16842994, - 16843087}; - - // aapt resource value: 0 - public const int TabItem_android_icon = 0; - - // aapt resource value: 1 - public const int TabItem_android_layout = 1; - - // aapt resource value: 2 - public const int TabItem_android_text = 2; - - public static int[] TabLayout = new int[] { - 2130772275, - 2130772276, - 2130772277, - 2130772278, - 2130772279, - 2130772280, - 2130772281, - 2130772282, - 2130772283, - 2130772284, - 2130772285, - 2130772286, - 2130772287, - 2130772288, - 2130772289, - 2130772290}; - - // aapt resource value: 3 - public const int TabLayout_tabBackground = 3; - - // aapt resource value: 2 - public const int TabLayout_tabContentStart = 2; - - // aapt resource value: 5 - public const int TabLayout_tabGravity = 5; - - // aapt resource value: 0 - public const int TabLayout_tabIndicatorColor = 0; - - // aapt resource value: 1 - public const int TabLayout_tabIndicatorHeight = 1; - - // aapt resource value: 7 - public const int TabLayout_tabMaxWidth = 7; - - // aapt resource value: 6 - public const int TabLayout_tabMinWidth = 6; - - // aapt resource value: 4 - public const int TabLayout_tabMode = 4; - - // aapt resource value: 15 - public const int TabLayout_tabPadding = 15; - - // aapt resource value: 14 - public const int TabLayout_tabPaddingBottom = 14; - - // aapt resource value: 13 - public const int TabLayout_tabPaddingEnd = 13; - - // aapt resource value: 11 - public const int TabLayout_tabPaddingStart = 11; - - // aapt resource value: 12 - public const int TabLayout_tabPaddingTop = 12; - - // aapt resource value: 10 - public const int TabLayout_tabSelectedTextColor = 10; - - // aapt resource value: 8 - public const int TabLayout_tabTextAppearance = 8; - - // aapt resource value: 9 - public const int TabLayout_tabTextColor = 9; - - public static int[] TextAppearance = new int[] { - 16842901, - 16842902, - 16842903, - 16842904, - 16842906, - 16842907, - 16843105, - 16843106, - 16843107, - 16843108, - 16843692, - 2130772022, - 2130772028}; - - // aapt resource value: 10 - public const int TextAppearance_android_fontFamily = 10; - - // aapt resource value: 6 - public const int TextAppearance_android_shadowColor = 6; - - // aapt resource value: 7 - public const int TextAppearance_android_shadowDx = 7; - - // aapt resource value: 8 - public const int TextAppearance_android_shadowDy = 8; - - // aapt resource value: 9 - public const int TextAppearance_android_shadowRadius = 9; - - // aapt resource value: 3 - public const int TextAppearance_android_textColor = 3; - - // aapt resource value: 4 - public const int TextAppearance_android_textColorHint = 4; - - // aapt resource value: 5 - public const int TextAppearance_android_textColorLink = 5; - - // aapt resource value: 0 - public const int TextAppearance_android_textSize = 0; - - // aapt resource value: 2 - public const int TextAppearance_android_textStyle = 2; - - // aapt resource value: 1 - public const int TextAppearance_android_typeface = 1; - - // aapt resource value: 12 - public const int TextAppearance_fontFamily = 12; - - // aapt resource value: 11 - public const int TextAppearance_textAllCaps = 11; - - public static int[] TextInputLayout = new int[] { - 16842906, - 16843088, - 2130772291, - 2130772292, - 2130772293, - 2130772294, - 2130772295, - 2130772296, - 2130772297, - 2130772298, - 2130772299, - 2130772300, - 2130772301, - 2130772302, - 2130772303, - 2130772304}; - - // aapt resource value: 1 - public const int TextInputLayout_android_hint = 1; - - // aapt resource value: 0 - public const int TextInputLayout_android_textColorHint = 0; - - // aapt resource value: 6 - public const int TextInputLayout_counterEnabled = 6; - - // aapt resource value: 7 - public const int TextInputLayout_counterMaxLength = 7; - - // aapt resource value: 9 - public const int TextInputLayout_counterOverflowTextAppearance = 9; - - // aapt resource value: 8 - public const int TextInputLayout_counterTextAppearance = 8; - - // aapt resource value: 4 - public const int TextInputLayout_errorEnabled = 4; - - // aapt resource value: 5 - public const int TextInputLayout_errorTextAppearance = 5; - - // aapt resource value: 10 - public const int TextInputLayout_hintAnimationEnabled = 10; - - // aapt resource value: 3 - public const int TextInputLayout_hintEnabled = 3; - - // aapt resource value: 2 - public const int TextInputLayout_hintTextAppearance = 2; - - // aapt resource value: 13 - public const int TextInputLayout_passwordToggleContentDescription = 13; - - // aapt resource value: 12 - public const int TextInputLayout_passwordToggleDrawable = 12; - - // aapt resource value: 11 - public const int TextInputLayout_passwordToggleEnabled = 11; - - // aapt resource value: 14 - public const int TextInputLayout_passwordToggleTint = 14; - - // aapt resource value: 15 - public const int TextInputLayout_passwordToggleTintMode = 15; - - public static int[] Toolbar = new int[] { - 16842927, - 16843072, - 2130771980, - 2130771983, - 2130771987, - 2130771999, - 2130772000, - 2130772001, - 2130772002, - 2130772003, - 2130772004, - 2130772006, - 2130772201, - 2130772202, - 2130772203, - 2130772204, - 2130772205, - 2130772206, - 2130772207, - 2130772208, - 2130772209, - 2130772210, - 2130772211, - 2130772212, - 2130772213, - 2130772214, - 2130772215, - 2130772216, - 2130772217}; - - // aapt resource value: 0 - public const int Toolbar_android_gravity = 0; - - // aapt resource value: 1 - public const int Toolbar_android_minHeight = 1; - - // aapt resource value: 21 - public const int Toolbar_buttonGravity = 21; - - // aapt resource value: 23 - public const int Toolbar_collapseContentDescription = 23; - - // aapt resource value: 22 - public const int Toolbar_collapseIcon = 22; - - // aapt resource value: 6 - public const int Toolbar_contentInsetEnd = 6; - - // aapt resource value: 10 - public const int Toolbar_contentInsetEndWithActions = 10; - - // aapt resource value: 7 - public const int Toolbar_contentInsetLeft = 7; - - // aapt resource value: 8 - public const int Toolbar_contentInsetRight = 8; - - // aapt resource value: 5 - public const int Toolbar_contentInsetStart = 5; - - // aapt resource value: 9 - public const int Toolbar_contentInsetStartWithNavigation = 9; - - // aapt resource value: 4 - public const int Toolbar_logo = 4; - - // aapt resource value: 26 - public const int Toolbar_logoDescription = 26; - - // aapt resource value: 20 - public const int Toolbar_maxButtonHeight = 20; - - // aapt resource value: 25 - public const int Toolbar_navigationContentDescription = 25; - - // aapt resource value: 24 - public const int Toolbar_navigationIcon = 24; - - // aapt resource value: 11 - public const int Toolbar_popupTheme = 11; - - // aapt resource value: 3 - public const int Toolbar_subtitle = 3; - - // aapt resource value: 13 - public const int Toolbar_subtitleTextAppearance = 13; - - // aapt resource value: 28 - public const int Toolbar_subtitleTextColor = 28; - - // aapt resource value: 2 - public const int Toolbar_title = 2; - - // aapt resource value: 14 - public const int Toolbar_titleMargin = 14; - - // aapt resource value: 18 - public const int Toolbar_titleMarginBottom = 18; - - // aapt resource value: 16 - public const int Toolbar_titleMarginEnd = 16; - - // aapt resource value: 15 - public const int Toolbar_titleMarginStart = 15; - - // aapt resource value: 17 - public const int Toolbar_titleMarginTop = 17; - - // aapt resource value: 19 - public const int Toolbar_titleMargins = 19; - - // aapt resource value: 12 - public const int Toolbar_titleTextAppearance = 12; - - // aapt resource value: 27 - public const int Toolbar_titleTextColor = 27; - - public static int[] View = new int[] { - 16842752, - 16842970, - 2130772218, - 2130772219, - 2130772220}; - - // aapt resource value: 1 - public const int View_android_focusable = 1; - - // aapt resource value: 0 - public const int View_android_theme = 0; - - // aapt resource value: 3 - public const int View_paddingEnd = 3; - - // aapt resource value: 2 - public const int View_paddingStart = 2; - - // aapt resource value: 4 - public const int View_theme = 4; - - public static int[] ViewBackgroundHelper = new int[] { - 16842964, - 2130772221, - 2130772222}; - - // aapt resource value: 0 - public const int ViewBackgroundHelper_android_background = 0; - - // aapt resource value: 1 - public const int ViewBackgroundHelper_backgroundTint = 1; - - // aapt resource value: 2 - public const int ViewBackgroundHelper_backgroundTintMode = 2; - - public static int[] ViewStubCompat = new int[] { - 16842960, - 16842994, - 16842995}; - - // aapt resource value: 0 - public const int ViewStubCompat_android_id = 0; - - // aapt resource value: 2 - public const int ViewStubCompat_android_inflatedId = 2; - - // aapt resource value: 1 - public const int ViewStubCompat_android_layout = 1; - - static Styleable() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Styleable() - { - } - } } } #pragma warning restore 1591 From fc6f484244d97c44bcc5003ce37a2e94e32c1635 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Sun, 6 Jan 2019 21:53:54 -0600 Subject: [PATCH 0336/5608] Use dev build of framework, make some fixes --- osu.Game.Tests/Visual/TestCaseChatLink.cs | 2 +- .../Visual/TestCaseLoungeRoomsContainer.cs | 4 ++-- .../Visual/TestCaseMatchSettingsOverlay.cs | 2 +- osu.Game/Online/Chat/ChannelManager.cs | 8 ++++---- osu.Game/Online/Multiplayer/PlaylistItem.cs | 4 ++-- osu.Game/Online/Multiplayer/Room.cs | 2 +- .../Settings/Sections/Graphics/LayoutSettings.cs | 14 +++++++------- osu.Game/Screens/Multi/IRoomManager.cs | 2 +- .../Multi/Lounge/Components/RoomsContainer.cs | 2 +- osu.Game/Screens/Multi/RoomBindings.cs | 2 +- osu.Game/Screens/Multi/RoomManager.cs | 4 ++-- osu.Game/osu.Game.csproj | 2 +- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseChatLink.cs b/osu.Game.Tests/Visual/TestCaseChatLink.cs index 61c2f47e7d..8aa3283af7 100644 --- a/osu.Game.Tests/Visual/TestCaseChatLink.cs +++ b/osu.Game.Tests/Visual/TestCaseChatLink.cs @@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual linkColour = colours.Blue; var chatManager = new ChannelManager(); - BindableCollection availableChannels = (BindableCollection)chatManager.AvailableChannels; + BindableList availableChannels = (BindableList)chatManager.AvailableChannels; availableChannels.Add(new Channel { Name = "#english"}); availableChannels.Add(new Channel { Name = "#japanese" }); Dependencies.Cache(chatManager); diff --git a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs index 3e9f2fb3a4..6b5bc875f1 100644 --- a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs @@ -73,8 +73,8 @@ namespace osu.Game.Tests.Visual { public event Action RoomsUpdated; - public readonly BindableCollection Rooms = new BindableCollection(); - IBindableCollection IRoomManager.Rooms => Rooms; + public readonly BindableList Rooms = new BindableList(); + IBindableList IRoomManager.Rooms => Rooms; public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) => Rooms.Add(room); diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs index 7fb9d4dded..6f084def48 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs @@ -138,7 +138,7 @@ namespace osu.Game.Tests.Visual public event Action RoomsUpdated; - public IBindableCollection Rooms { get; } = null; + public IBindableList Rooms { get; } = null; public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 4241b47cd3..d5deda960c 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -29,8 +29,8 @@ namespace osu.Game.Online.Chat @"#lobby" }; - private readonly BindableCollection availableChannels = new BindableCollection(); - private readonly BindableCollection joinedChannels = new BindableCollection(); + private readonly BindableList availableChannels = new BindableList(); + private readonly BindableList joinedChannels = new BindableList(); /// public class FrameStabilityContainer : Container, IHasReplayHandler { - public FrameStabilityContainer() + private readonly double gameplayStartTime; + + public FrameStabilityContainer(double gameplayStartTime = double.MinValue) { RelativeSizeAxes = Axes.Both; gameplayClock = new GameplayClock(framedClock = new FramedClock(manualClock = new ManualClock())); + + this.gameplayStartTime = gameplayStartTime; } private readonly ManualClock manualClock; @@ -116,6 +120,8 @@ namespace osu.Game.Rulesets.UI firstConsumption = false; } + else if (manualClock.CurrentTime < gameplayStartTime) + manualClock.CurrentTime = newProposedTime = Math.Min(gameplayStartTime, newProposedTime); else if (Math.Abs(manualClock.CurrentTime - newProposedTime) > sixty_frame_time * 1.2f) { newProposedTime = newProposedTime > manualClock.CurrentTime From 3bcfc86b9c92c0640d29fda24537bf47c0b26076 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 May 2019 16:37:34 +0900 Subject: [PATCH 0742/5608] Allow custom MaxCatchUpFrames to be specified Also adjusts the default to allow for smoother seeking. --- .../Visual/Gameplay/TestCaseFrameStabilityContainer.cs | 6 +++++- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 9 ++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs index 584fbe5729..7d6430a2cc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs @@ -103,7 +103,11 @@ namespace osu.Game.Tests.Visual.Gameplay checkFrameCount(0); } - private void createStabilityContainer() => AddStep("create container", () => mainContainer.Child = new FrameStabilityContainer().WithChild(consumer = new ClockConsumingChild())); + private const int max_frames_catchup = 50; + + private void createStabilityContainer(double gameplayStartTime = double.MinValue) => AddStep("create container", () => + mainContainer.Child = new FrameStabilityContainer(gameplayStartTime) { MaxCatchUpFrames = max_frames_catchup } + .WithChild(consumer = new ClockConsumingChild())); private void seekManualTo(double time) => AddStep($"seek manual clock to {time}", () => manualClock.CurrentTime = time); diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 16a5ca4387..9f2bf33628 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -19,6 +19,11 @@ namespace osu.Game.Rulesets.UI { private readonly double gameplayStartTime; + /// + /// The number of frames (per parent frame) which can be run in an attempt to catch-up to real-time. + /// + public int MaxCatchUpFrames { get; set; } = 5; + public FrameStabilityContainer(double gameplayStartTime = double.MinValue) { RelativeSizeAxes = Axes.Both; @@ -68,8 +73,6 @@ namespace osu.Game.Rulesets.UI private bool isAttached => ReplayInputHandler != null; - private const int max_catch_up_updates_per_frame = 50; - private const double sixty_frame_time = 1000.0 / 60; private bool firstConsumption = true; @@ -81,7 +84,7 @@ namespace osu.Game.Rulesets.UI int loops = 0; - while (validState && requireMoreUpdateLoops && loops++ < max_catch_up_updates_per_frame) + while (validState && requireMoreUpdateLoops && loops++ < MaxCatchUpFrames) { updateClock(); From 59420721285e2e9b52398be20f786ed87165bd2e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 May 2019 18:05:28 +0900 Subject: [PATCH 0743/5608] Add a tween when clicking to seek --- osu.Game/Screens/Play/SongProgressBar.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index 2e7d452fe7..8ee2c0aa74 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; +using osu.Framework.MathUtils; namespace osu.Game.Screens.Play { @@ -107,9 +108,17 @@ namespace osu.Game.Screens.Play protected override void UpdateValue(float value) { - var xFill = value * UsableWidth; - fill.Width = xFill; - handleBase.X = xFill; + // handled in update + } + + protected override void Update() + { + base.Update(); + + float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Time.Elapsed / 40); + + fill.Width = newX; + handleBase.X = newX; } protected override void OnUserChange(double value) => OnSeek?.Invoke(value); From 9248e6290cbe4a2276b7b4678799a73b67e2c235 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 May 2019 18:06:11 +0900 Subject: [PATCH 0744/5608] Use FrameStabilityClock to denote current position on song progress --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 7 +++++++ osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 11 ++++++----- osu.Game/Screens/Play/HUDOverlay.cs | 17 +++++++++++++---- osu.Game/Screens/Play/SongProgress.cs | 13 +++++++++---- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 77d1e60b87..76790e2b46 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -59,6 +59,8 @@ namespace osu.Game.Rulesets.UI /// /// The currently opened channel @@ -40,12 +40,12 @@ namespace osu.Game.Online.Chat /// /// The Channels the player has joined /// - public IBindableCollection JoinedChannels => joinedChannels; + public IBindableList JoinedChannels => joinedChannels; /// /// The channels available for the player to join /// - public IBindableCollection AvailableChannels => availableChannels; + public IBindableList AvailableChannels => availableChannels; private IAPIProvider api; diff --git a/osu.Game/Online/Multiplayer/PlaylistItem.cs b/osu.Game/Online/Multiplayer/PlaylistItem.cs index 4155121bdf..63b5b95b9c 100644 --- a/osu.Game/Online/Multiplayer/PlaylistItem.cs +++ b/osu.Game/Online/Multiplayer/PlaylistItem.cs @@ -37,10 +37,10 @@ namespace osu.Game.Online.Multiplayer public RulesetInfo Ruleset { get; set; } [JsonIgnore] - public readonly BindableCollection AllowedMods = new BindableCollection(); + public readonly BindableList AllowedMods = new BindableList(); [JsonIgnore] - public readonly BindableCollection RequiredMods = new BindableCollection(); + public readonly BindableList RequiredMods = new BindableList(); [JsonProperty("beatmap")] private APIBeatmap apiBeatmap { get; set; } diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 448f5ced91..5273c7acfb 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -24,7 +24,7 @@ namespace osu.Game.Online.Multiplayer public Bindable Host { get; private set; } = new Bindable(); [JsonProperty("playlist")] - public BindableCollection Playlist { get; set; } = new BindableCollection(); + public BindableList Playlist { get; set; } = new BindableList(); [JsonProperty("channel_id")] public Bindable ChannelId { get; private set; } = new Bindable(); diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 685244e06b..c1fefb7290 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private FillFlowContainer letterboxSettings; - private Bindable letterboxing; + //private Bindable letterboxing; private Bindable sizeFullscreen; private OsuGameBase game; @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { this.game = game; - letterboxing = config.GetBindable(FrameworkSetting.Letterboxing); + //letterboxing = config.GetBindable(FrameworkSetting.Letterboxing); sizeFullscreen = config.GetBindable(FrameworkSetting.SizeFullscreen); Container resolutionSettingsContainer; @@ -52,7 +52,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics new SettingsCheckbox { LabelText = "Letterboxing", - Bindable = letterboxing, + //Bindable = letterboxing, }, letterboxSettings = new FillFlowContainer { @@ -68,13 +68,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics new SettingsSlider { LabelText = "Horizontal position", - Bindable = config.GetBindable(FrameworkSetting.LetterboxPositionX), + //Bindable = config.GetBindable(FrameworkSetting.LetterboxPositionX), KeyboardStep = 0.01f }, new SettingsSlider { LabelText = "Vertical position", - Bindable = config.GetBindable(FrameworkSetting.LetterboxPositionY), + //Bindable = config.GetBindable(FrameworkSetting.LetterboxPositionY), KeyboardStep = 0.01f }, } @@ -105,14 +105,14 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, true); } - letterboxing.BindValueChanged(isVisible => + /*letterboxing.BindValueChanged(isVisible => { letterboxSettings.ClearTransforms(); letterboxSettings.AutoSizeAxes = isVisible ? Axes.Y : Axes.None; if (!isVisible) letterboxSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); - }, true); + }, true);*/ } private IReadOnlyList getResolutions() diff --git a/osu.Game/Screens/Multi/IRoomManager.cs b/osu.Game/Screens/Multi/IRoomManager.cs index f0dbcb0e71..6af8a35208 100644 --- a/osu.Game/Screens/Multi/IRoomManager.cs +++ b/osu.Game/Screens/Multi/IRoomManager.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Multi /// /// All the active s. /// - IBindableCollection Rooms { get; } + IBindableList Rooms { get; } /// /// Creates a new . diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 5133e96a52..4ad8154090 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly Bindable selectedRoom = new Bindable(); public IBindable SelectedRoom => selectedRoom; - private readonly IBindableCollection rooms = new BindableCollection(); + private readonly IBindableList rooms = new BindableList(); private readonly FillFlowContainer roomFlow; public IReadOnlyList Rooms => roomFlow; diff --git a/osu.Game/Screens/Multi/RoomBindings.cs b/osu.Game/Screens/Multi/RoomBindings.cs index dc2547268d..cdbb6dbea6 100644 --- a/osu.Game/Screens/Multi/RoomBindings.cs +++ b/osu.Game/Screens/Multi/RoomBindings.cs @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Multi public readonly Bindable Host = new Bindable(); public readonly Bindable Status = new Bindable(); public readonly Bindable Type = new Bindable(); - public readonly BindableCollection Playlist = new BindableCollection(); + public readonly BindableList Playlist = new BindableList(); public readonly Bindable> Participants = new Bindable>(); public readonly Bindable ParticipantCount = new Bindable(); public readonly Bindable MaxParticipants = new Bindable(); diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index fab19c3fd7..1f95401905 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -21,8 +21,8 @@ namespace osu.Game.Screens.Multi { public event Action RoomsUpdated; - private readonly BindableCollection rooms = new BindableCollection(); - public IBindableCollection Rooms => rooms; + private readonly BindableList rooms = new BindableList(); + public IBindableList Rooms => rooms; private Room currentRoom; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 103c7c20d6..4069ac01d0 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 8c94ea3c35337a145855b8e3db3d885bed31b215 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Tue, 8 Jan 2019 18:14:34 -0600 Subject: [PATCH 0337/5608] Update NuGet packages --- osu.Android.props | 8 ++++---- osu.Game/osu.Game.csproj | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 4c89408203..a662855fc1 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -39,10 +39,10 @@ - 0.0.7879 + 0.0.7939 - 0.0.7879 + 0.0.7939 0.22.0 @@ -51,10 +51,10 @@ 1.1.0 - 1.0.0-dev000094 + 1.0.0-dev000096 - 1.0.0-dev002278 + 1.0.0-dev002315 \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 4069ac01d0..ce6e035b1c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 6624a91697ccb26f9e5b9053d8f3aca631f30765 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Tue, 8 Jan 2019 21:36:22 -0600 Subject: [PATCH 0338/5608] Remove Resource.designer.cs --- osu.Android/Resources/Resource.designer.cs | 92 ---------------------- 1 file changed, 92 deletions(-) delete mode 100644 osu.Android/Resources/Resource.designer.cs diff --git a/osu.Android/Resources/Resource.designer.cs b/osu.Android/Resources/Resource.designer.cs deleted file mode 100644 index c02df072f1..0000000000 --- a/osu.Android/Resources/Resource.designer.cs +++ /dev/null @@ -1,92 +0,0 @@ -#pragma warning disable 1591 -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -[assembly: global::Android.Runtime.ResourceDesignerAttribute("osu.Android.Resource", IsApplication=true)] - -namespace osu.Android -{ - - - [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] - public partial class Resource - { - - static Resource() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - public static void UpdateIdValues() - { - } - - public partial class Attribute - { - - static Attribute() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Attribute() - { - } - } - - public partial class Color - { - - // aapt resource value: 0x7f030002 - public const int colorAccent = 2130903042; - - // aapt resource value: 0x7f030000 - public const int colorPrimary = 2130903040; - - // aapt resource value: 0x7f030001 - public const int colorPrimaryDark = 2130903041; - - // aapt resource value: 0x7f030003 - public const int ic_launcher_background = 2130903043; - - static Color() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Color() - { - } - } - - public partial class Mipmap - { - - // aapt resource value: 0x7f020000 - public const int ic_launcher = 2130837504; - - // aapt resource value: 0x7f020001 - public const int ic_launcher_foreground = 2130837505; - - // aapt resource value: 0x7f020002 - public const int ic_launcher_round = 2130837506; - - static Mipmap() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Mipmap() - { - } - } - } -} -#pragma warning restore 1591 From b18eebfd70757c3fbab997f0d487de00e7ec4489 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Wed, 9 Jan 2019 19:31:42 -0600 Subject: [PATCH 0339/5608] Get icon working for osu.Android --- osu.Android/Properties/AndroidManifest.xml | 2 +- osu.Android/Resources/drawable/lazer.png | Bin 0 -> 39498 bytes .../mipmap-anydpi-v26/ic_launcher.xml | 5 ---- .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 ---- .../Resources/mipmap-hdpi/ic_launcher.png | Bin 8828 -> 0 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 1441 -> 0 bytes .../mipmap-hdpi/ic_launcher_round.png | Bin 8828 -> 0 bytes .../Resources/mipmap-mdpi/ic_launcher.png | Bin 5045 -> 0 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 958 -> 0 bytes .../mipmap-mdpi/ic_launcher_round.png | Bin 5045 -> 0 bytes .../Resources/mipmap-xhdpi/ic_launcher.png | Bin 12931 -> 0 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 2056 -> 0 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 12931 -> 0 bytes .../Resources/mipmap-xxhdpi/ic_launcher.png | Bin 21256 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 3403 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 21256 -> 0 bytes .../Resources/mipmap-xxxhdpi/ic_launcher.png | Bin 30047 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 4889 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 30047 -> 0 bytes osu.Android/Resources/values/colors.xml | 6 ----- .../values/ic_launcher_background.xml | 4 --- osu.Android/osu.Android.csproj | 23 +----------------- 22 files changed, 2 insertions(+), 43 deletions(-) create mode 100644 osu.Android/Resources/drawable/lazer.png delete mode 100644 osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 osu.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 osu.Android/Resources/mipmap-hdpi/ic_launcher.png delete mode 100644 osu.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png delete mode 100644 osu.Android/Resources/mipmap-hdpi/ic_launcher_round.png delete mode 100644 osu.Android/Resources/mipmap-mdpi/ic_launcher.png delete mode 100644 osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png delete mode 100644 osu.Android/Resources/mipmap-mdpi/ic_launcher_round.png delete mode 100644 osu.Android/Resources/mipmap-xhdpi/ic_launcher.png delete mode 100644 osu.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png delete mode 100644 osu.Android/Resources/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 osu.Android/Resources/mipmap-xxhdpi/ic_launcher.png delete mode 100644 osu.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png delete mode 100644 osu.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 osu.Android/Resources/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png delete mode 100644 osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 osu.Android/Resources/values/colors.xml delete mode 100644 osu.Android/Resources/values/ic_launcher_background.xml diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index bb5f9b751e..9b337eec6c 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -5,5 +5,5 @@ - + \ No newline at end of file diff --git a/osu.Android/Resources/drawable/lazer.png b/osu.Android/Resources/drawable/lazer.png new file mode 100644 index 0000000000000000000000000000000000000000..075a8e7184ad508cedd8fe9ae549d8cea696b51a GIT binary patch literal 39498 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 X{r?ZpP_kcw2Ot$CjR&O)ra}J$c_$^Y literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 9412204815..0000000000 --- a/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml b/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 036d09bc5f..0000000000 --- a/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/osu.Android/Resources/mipmap-hdpi/ic_launcher.png b/osu.Android/Resources/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 2af076dabd0afe60561f41903cc42931db8d33cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8828 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 N&GnQ!lI8SQ#{X#Iv!eh2 diff --git a/osu.Android/Resources/mipmap-hdpi/ic_launcher_round.png b/osu.Android/Resources/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 2af076dabd0afe60561f41903cc42931db8d33cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8828 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 LNkvXXu0mjfp$&R0 diff --git a/osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png b/osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png deleted file mode 100644 index a12b157f00e3022cfe81a1e767525c33f4ed2cf1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 958 zcmeAS@N?(olHy`uVBq!ia0vp^IUvlz1|<8_!p|}=Ft>WTIEGZ*dOIh!!#7am`0)iN z!-Y*JzdqP8rN&2Y&y2(+EtA?m9-5+}#BXAw@$*D;zxcf=lRhYP2`ZYNoGdU|=;=Y1 z!-o@UOzpBVHoTpyopyF#@i)8YcdVaV?2ljDUj6>w?`yyA*Pf5cUSE9b6wq26;8J@~ z){!@7GpTmNE>2kO_POn1zf8`~}P?%{85(;s&nc+C&;t$4D5$+f9? z-8>e~Z&%(_OwrVd==PGc4mhTFjVafjdCqsM|EvEe$2)U;a9s0IGofbtHcpKz;cJR= z`DNzVI-iMtrg<$r*EFejE8l0oMM3e)a|=o;x>Mhk@*n)xx%2Rrt=4TnivwP5zpS-& z@5h3w<{9>vH!6KP74q!po!oh)$BI~jUu}4P|5ofvi@(2i9NyELbZ$qD}PI&+JJ3+^f2=YEuP zjpepXu;`->)%n@lB|b@Iv$k0qhJJp%S?O9t?)zjLwwY?z@=v^12)=lt^ZcwNoye^x z_uu*-x}ntY`mc3S`yMaaHuurqE~e`{G_IsMZdhw*{kDDS9h3WSQa;8d3vwO)d?WE+ z%*LAIs=2#$t=BZmPTP}xMpj0I9ti9_c{r`p zu+;ELV)~|tmk}}-GjAWQO5U<}Lr?bB5UX>pYf5~UOnY%ZTQR${nq6YQOHc15>q%#$ zl8$8k_1fsCw;<~OiJ-OiE?f7RJWt%N`#e!y=2`BhIqju|a?kW5QupmV#wx6HrSs?J z&nJroVy6i|*Og1U`{c;a^^dPvTfNJjdCg1nUS<*OC dK7&Kx57tYsZ49$p7vBM?@pScbS?83{1OVHE%8UR2 diff --git a/osu.Android/Resources/mipmap-mdpi/ic_launcher_round.png b/osu.Android/Resources/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index c51990875e404a36964d727d376637c6e6c81305..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5045 zcmV;m6H4rfP)4|Rc@(q%9P1y)Ffj;B{MN5GddGf zGdM88WgM6EBrZW{Sp=~`HnG{4ZfJUcue;y=?tZ4udGB?a&1I7LV-9uuy?f7n=YGHC ze81&_|L=pl82(M0HsSi~uSYBvLnsu2VHgMm0_;-|1a^-oir~1y5`>V;2q80gp05Hh z3P2^taXJ8-5HiSdT#x5@F^=Po0{Daw;?Uogem^)k2%hKJGwAv!Po6|sSs5ac2&PY; zj?X^(?1DJOuWJB82s?@ozJlYp`vJ`5IBx32ep3QT0TxF;$8lQ;Ax!{Yr!$^U? z>iAj$lz{U*f14ype-B{t@EicsG~f83Uf>fENXbeihIp@L?TFC;$Pd1h959h%!{m zfpZ`Zv!w%BT}1x!T8P(;MR?v6NZ@!u5T56G{yP8`d!BcSTKvypfeKL+H;bak+$B4h zg!8-4A+&UWkEal+2m+UeK|o-;E{wbjA{4}|s;opRl|nX?0WVA7G!dK{fL0lVL^znA z_rcoL0c(3FvP&i)Fl`J3j-%FX*EH=f1VMP~%fMaK*>brY{g^yz)TomsU+>@Cip~dC zL;CO})Sw@vCInX%;Ce3GAC_emtmZiI`Fs$ALHGgzx{KKy^=(lUz;hftfrD4!gWgaH z{&*bLigie=`3RP6vo&gJYTgWmLfs!9=9724!1&komiJ zkc%ZtFn+;t+>^!qcfrAZ_~D1c*XhEhY0{%&;lhQjx~^9_6#P${AZ$DVeQY%>&V?*W zh*nm@HVkAk8TLCG9~dalLs?Z7G%A2;0+Iw`+vxA=V%qil{g5OH*=&|QlY&zeg>gQ3 z9;7>ol0m@rb91q&8{yNG$V0hr@4@c#{d(+OzftKq_f z=Xz|z%CcN=7wY$h!Ca(Bu`KX$q5!*lh~1;qMv+b=nXq(D*L5V5$zh9>MWbvz&vn5G z0=WJRQi2WfsRht$%1fAL0oXYbB>k<})YQaIsOB|I!=gotR;a2vhhFRb_l>~Dp+=!Q6 zdI`~Jbk=RR-9~vH$!$mAtl0sjHo`U>$k~#!V8a2n>%i$t0j9%(74Zl-0=S7B${)WO z+N2t!n)X1@75IZeM#)Yr1>STa26gy?LGYCK>AE~$IOwxN8l>(F%$^~LGsn>RibIDE z`5t}r(dON|cVqkZ?da|81xGDF-5{M#(?br&3w z-tL_hxTuw>Ae4>sZT%n*%tYDE)7jjH4I3tRb#)!0R#>`pDR}C8)E%Zyow|U6r#I!^ z+zn;W1c_*ngbPPS#wJuRh7DU2;Q!Xu&>Jcs$3`LRv8i@&kuBgy89bCo&AN4`F z{c>2k0FpD|xDMOUl(y+n`fiyfa;6EQOR(N)g_Sedb0pUOpkM^jGj}?2|g8x=bMo?4d~yx8g4odLUW4QkYdp7J<+rj%)xP&lPqFSeiSfplV32OC-j!>Ean~t+6A2k_Us3HdU^^1Q1`j%rkn1e->qC8?tvc2(EwwLk^odI zbRni0+l5qD23RggJi~lk9vz19>P{s0x5M}CnebE*!sKcYY6ZgvKXDXn+eYN>YmqyA z2C4tphO9!6HF8kW4*0wS<%)Xnio{rmy612LNeFVpK&JIHtX-!Wrnz(H&L2+E>7QxS zrp;iSexL{FOn~^6VWufJ4f_5Bd5LNIo<1EWJ2{p_7c{c01ux)69( zf@4?^D+BOE9!Ad)qg?)qT6RzQilxX`>o9h|LiZ>PNRje|9NyqKEFE{~m5%3cOz#CW(?21YUp`@xeLR4JXgs2xG^NWwa!Y88hZ8 zDio8rZGa_d`Jx6&epoUWr8Y@bKsKI0PxE2ue>n>kcVCBw>n}ss({IAQ;|j<%WiY!3 z;9oceo?%0Z`k-Ik$kK1ADhLBE%zxX4`d7aLGom5!+Q%TjZ-vk0;Fjy~Xm}xiWIBq0 zZE#Hi$yy+>3{bCN%9JUMOo00O`Z@+aZ-MlsAcg(lojgl}86TfRp;RELp&Sv@g|T)Q z&iw8(=yzR%iWN(d`?L)vaS<3dy0A}*Ln`xwKcXPl8HeO?@ISs7@lCC8-fe|u5Xe>K zAexALHV2nR^>bnlbt9K0LP!>{s6ywH?o5Wm5*Yzm7D`!EZ(OlqI3QRYxQw;A# zb+8Rg@)i@;PUj(CUW=M%z6p(&kof2@_}U13R$fejm} z_yE(mpcWFfv!XAphZPZ=B!W0DctvF9?ESBgAy2J^?$eQL>qEtDGtL8F8ftA6_L%`l z6RVLp{1OPxPB0mnM0GfnMx6pX%CgK7B#{n=&-GXYq&IV} zJfh+j^AH%?TgDN&aJ)$U^EX%C!6H}=aD}gwHXN3q|h%5GehEr{twuW>h zcO1h|e+)>OEc0}RvMg!yO{!&SFaH&4SmR8b@xI+XfW%unSeD8~bl77e;<1}RlfU%d zHiTx6|3dH-7MC`W|EvS@gi#pv&;q2_Y)7u?b8s|D%Mv6SFue;Xf;vLyAe1?UPEJ0b zXEm=lFfb6KUxc6rPM3fIdszD;8HoD581k`$qjLIXIGTj`ANGP|41{l)j(j`?cl!}U zzA@o^000u79D$q6A#lxD3^naSzO@rP9B@?uh&~w}&7BnGEGrD-aB06N0=cnJrSo{3t^h6l|#gz7ZB@jU5;p8kBodY192~>=$$0a|#3uYn<=Xf8iz69d$ z?_u}T;+_I@S)j?(0TyQXQPI0{3Vi{279ZAK#AHn=O!a zmAN8JyO7UV4)n|Gk$m+N1RtIU&EjEybPR5}5B`a@P>v5F{@1U-?HB}tDg#a_-L@=P zwgn_|AdOLAN;MN;!-fsb!(L7QoH%hJwsGUeb|5VK&EE^nQWG2ql^`31!mbG z90#?!3}SfzHr=GI$2!tw-(3h>=3s0%i0t7mBsP2wX;c_;RS4;I`;k3xhGn2e_W){E zE@KguSPru;U#7!fQ_d`mVka(>PP2CtrePu^>(H(nUt*=ys#U92pCtet&p!L?Ke7u! z4Z?L}S>k0{g;bg@NDFur0}3g!E6tTC>-gtf2LCP7F!0i52&MqAEzN{TRxX4G1ln4mX||rb@54CRaRXO=Vev)isECkbs*vmd(HM#v8AkI(2IB zJOP@Un_HTjn^`k8eD^G~jW<^nycRW^)klm{yv!R<2z6 zvype6mA5|e#1l`_nkMrt3WEKwH0btb{5 zOo&lGblnG4QCOjFPbh~un1-{n9fD6QG=g;nQrZFf(hveF{Qkf&=hF(%aSH*>IMxGw z_Bd4jU1IJviX!?&&- zX~9C=NJ0{%v+iegt01tJI(-{cYEnsr2QTn&c*1&2G*K&AkOHQ@Um^#}|FpB+z2gwX z$X*4(zWz^pCR$a4p^t+j3VjV6E;f z6k@^V&70qwIdkUhBS((3eHk`<6$^|U4Gj&WSFc{ZYX1EBw~V~*o{Yh5i^Dk?gV!<0 z`Zu%yVebm)+gAEY$;`uzsL-a=KxwRmI<>CQ_$rQpfq|}v9(w4ZrlzJpd>u^xt8wL( zS58^CZe0_(&~QCMhH}L1NfNhnh`8Me;>9zBn9c=nZ*Olua{vAJfBXL&^o2$=8jU>l z)Kiar@WBV~r&6id1reSE^j^00000 LNkvXXu0mjfp$&R0 diff --git a/osu.Android/Resources/mipmap-xhdpi/ic_launcher.png b/osu.Android/Resources/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 4e8d9b598cd21e01bbbca29aa077d99a4dabefe3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12931 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 b;}yxl--Ss53i@>Q4YQuNcebmsMJN0NT!aL! diff --git a/osu.Android/Resources/mipmap-xhdpi/ic_launcher_round.png b/osu.Android/Resources/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 4e8d9b598cd21e01bbbca29aa077d99a4dabefe3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12931 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 diff --git a/osu.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png b/osu.Android/Resources/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 2d3354eaf2778d4ae52cf3e1368f131be63ccb62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21256 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 z 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 z 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 F@PB1o0BisN diff --git a/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png b/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index d8b832e7f7a81d3d69ad5c0b3ea88dfd739e36c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30047 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 z 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 - - #2c3e50 - #1B3147 - #3498db - diff --git a/osu.Android/Resources/values/ic_launcher_background.xml b/osu.Android/Resources/values/ic_launcher_background.xml deleted file mode 100644 index 6ec24e6413..0000000000 --- a/osu.Android/Resources/values/ic_launcher_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #2C3E50 - \ No newline at end of file diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 4a1dccd758..bfde981207 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -27,7 +27,6 @@ - @@ -47,27 +46,6 @@ - - - - - - - - - - - - - - - - - - - - - {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} @@ -96,6 +74,7 @@ + \ No newline at end of file From 6ba7e2b670da39a224b1ee9428553683485651a3 Mon Sep 17 00:00:00 2001 From: jorolf Date: Fri, 11 Jan 2019 01:12:19 +0100 Subject: [PATCH 0340/5608] split the profile header into several components --- osu.Game.Tests/Visual/TestCaseUserProfile.cs | 76 +- .../Visual/TestCaseUserProfileHeader.cs | 76 ++ .../Profile/Header/BottomHeaderContainer.cs | 160 ++++ .../Profile/Header/CenterHeaderContainer.cs | 321 +++++++ .../Profile/Header/DetailHeaderContainer.cs | 238 +++++ .../Profile/Header/MedalHeaderContainer.cs | 132 +++ .../Profile/Header/TopHeaderContainer.cs | 210 +++++ osu.Game/Overlays/Profile/ProfileHeader.cs | 892 +----------------- 8 files changed, 1197 insertions(+), 908 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs create mode 100644 osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs create mode 100644 osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs create mode 100644 osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs create mode 100644 osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs create mode 100644 osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs diff --git a/osu.Game.Tests/Visual/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/TestCaseUserProfile.cs index cff55c2506..3753328427 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/TestCaseUserProfile.cs @@ -32,6 +32,44 @@ namespace osu.Game.Tests.Visual typeof(SupporterIcon) }; + public static readonly User TEST_USER = new User + { + Username = @"Somebody", + Id = 1, + Country = new Country { FullName = @"Alien" }, + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg", + JoinDate = DateTimeOffset.Now.AddDays(-1), + LastVisit = DateTimeOffset.Now, + ProfileOrder = new[] { "me" }, + Statistics = new UserStatistics + { + Ranks = new UserStatistics.UserRanks { Global = 2148, Country = 1 }, + PP = 4567.89m, + Level = new UserStatistics.LevelInfo + { + Current = 727, + Progress = 69, + } + }, + RankHistory = new User.RankHistoryData + { + Mode = @"osu", + Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray() + }, + Badges = new[] + { + new Badge + { + AwardedAt = DateTimeOffset.FromUnixTimeSeconds(1505741569), + Description = "Outstanding help by being a voluntary test subject.", + ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg" + } + }, + Title = "osu!volunteer", + Colour = "ff0000", + Achievements = new User.UserAchievement[0], + }; + public TestCaseUserProfile() { Add(profile = new TestUserProfileOverlay()); @@ -47,43 +85,7 @@ namespace osu.Game.Tests.Visual { base.LoadComplete(); - AddStep("Show offline dummy", () => profile.ShowUser(new User - { - Username = @"Somebody", - Id = 1, - Country = new Country { FullName = @"Alien" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg", - JoinDate = DateTimeOffset.Now.AddDays(-1), - LastVisit = DateTimeOffset.Now, - ProfileOrder = new[] { "me" }, - Statistics = new UserStatistics - { - Ranks = new UserStatistics.UserRanks { Global = 2148, Country = 1 }, - PP = 4567.89m, - Level = new UserStatistics.LevelInfo - { - Current = 727, - Progress = 69, - } - }, - RankHistory = new User.RankHistoryData - { - Mode = @"osu", - Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray() - }, - Badges = new[] - { - new Badge - { - AwardedAt = DateTimeOffset.FromUnixTimeSeconds(1505741569), - Description = "Outstanding help by being a voluntary test subject.", - ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg" - } - }, - Title = "osu!volunteer", - Colour = "ff0000", - Achievements = new User.UserAchievement[0], - }, false)); + AddStep("Show offline dummy", () => profile.ShowUser(TEST_USER, false)); checkSupporterTag(false); diff --git a/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs b/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs new file mode 100644 index 0000000000..c80227f149 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs @@ -0,0 +1,76 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Overlays.Profile; +using osu.Game.Overlays.Profile.Header; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseUserProfileHeader : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ProfileHeader), + typeof(RankGraph), + typeof(LineGraph), + typeof(SupporterIcon) + }; + + [Resolved] + private APIAccess api { get; set; } + + private readonly ProfileHeader header; + + public TestCaseUserProfileHeader() + { + header = new ProfileHeader(); + Add(header); + + AddStep("Show offline dummy", () => header.User = TestCaseUserProfile.TEST_USER); + + AddStep("Show null dummy", () => header.User = new User + { + Username = "Null" + }); + + addOnlineStep("Show ppy", new User + { + Username = @"peppy", + Id = 2, + IsSupporter = true, + Country = new Country { FullName = @"Australia", FlagName = @"AU" }, + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg" + }); + + addOnlineStep("Show flyte", new User + { + Username = @"flyte", + Id = 3103765, + Country = new Country { FullName = @"Japan", FlagName = @"JP" }, + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg" + }); + } + + private void addOnlineStep(string name, User fallback) + { + AddStep(name, () => + { + if (api.IsLoggedIn) + { + var request = new GetUserRequest(fallback.Id); + request.Success += user => header.User = user; + api.Queue(request); + } + else + header.User = fallback; + }); + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs new file mode 100644 index 0000000000..a3a6447a9f --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -0,0 +1,160 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Users; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Profile.Header +{ + public class BottomHeaderContainer : Container + { + private LinkFlowContainer bottomTopLinkContainer; + private LinkFlowContainer bottomLinkContainer; + private Color4 linkBlue, communityUserGrayGreenLighter; + + private User user; + public User User + { + get => user; + set + { + if (user == value) return; + user = value; + updateDisplay(); + } + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.CommunityUserGrayGreenDarker, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, + Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + bottomTopLinkContainer = new LinkFlowContainer(text => text.TextSize = 12) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + bottomLinkContainer = new LinkFlowContainer(text => text.TextSize = 12) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } + } + } + }; + + linkBlue = colours.BlueLight; + communityUserGrayGreenLighter = colours.CommunityUserGrayGreenLighter; + } + + private void updateDisplay() + { + void bold(SpriteText t) => t.Font = @"Exo2.0-Bold"; + void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); + + bottomTopLinkContainer.Clear(); + bottomLinkContainer.Clear(); + + if (user == null) return; + + if (user.JoinDate.ToUniversalTime().Year < 2008) + { + bottomTopLinkContainer.AddText("Here since the beginning"); + } + else + { + bottomTopLinkContainer.AddText("Joined "); + bottomTopLinkContainer.AddText(new DrawableDate(user.JoinDate), bold); + } + + addSpacer(bottomTopLinkContainer); + + if (user.PlayStyles?.Length > 0) + { + bottomTopLinkContainer.AddText("Plays with "); + bottomTopLinkContainer.AddText(string.Join(", ", user.PlayStyles.Select(style => style.GetDescription())), bold); + + addSpacer(bottomTopLinkContainer); + } + + if (user.LastVisit.HasValue) + { + bottomTopLinkContainer.AddText("Last seen "); + bottomTopLinkContainer.AddText(new DrawableDate(user.LastVisit.Value), bold); + + addSpacer(bottomTopLinkContainer); + } + + bottomTopLinkContainer.AddText("Contributed "); + bottomTopLinkContainer.AddLink($@"{user.PostCount:#,##0} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: bold); + + void tryAddInfo(FontAwesome icon, string content, string link = null) + { + if (string.IsNullOrEmpty(content)) return; + + bottomLinkContainer.AddIcon(icon, text => + { + text.TextSize = 10; + text.Colour = communityUserGrayGreenLighter; + }); + if (link != null) + { + bottomLinkContainer.AddLink(" " + content, link, creationParameters: text => + { + bold(text); + text.Colour = linkBlue; + }); + } + else + { + bottomLinkContainer.AddText(" " + content, bold); + } + addSpacer(bottomLinkContainer); + } + + string websiteWithoutProtcol = user.Website; + if (!string.IsNullOrEmpty(websiteWithoutProtcol)) + { + int protocolIndex = websiteWithoutProtcol.IndexOf("//", StringComparison.Ordinal); + if (protocolIndex >= 0) + websiteWithoutProtcol = websiteWithoutProtcol.Substring(protocolIndex + 2); + } + + tryAddInfo(FontAwesome.fa_map_marker, user.Location); + tryAddInfo(FontAwesome.fa_heart_o, user.Interests); + tryAddInfo(FontAwesome.fa_suitcase, user.Occupation); + bottomLinkContainer.NewLine(); + if (!string.IsNullOrEmpty(user.Twitter)) + tryAddInfo(FontAwesome.fa_twitter, "@" + user.Twitter, $@"https://twitter.com/{user.Twitter}"); + tryAddInfo(FontAwesome.fa_gamepad, user.Discord); //todo: update fontawesome to include discord logo + tryAddInfo(FontAwesome.fa_skype, user.Skype, @"skype:" + user.Skype + @"?chat"); + tryAddInfo(FontAwesome.fa_lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); + tryAddInfo(FontAwesome.fa_link, websiteWithoutProtcol, user.Website); + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs new file mode 100644 index 0000000000..9005fd5ab2 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs @@ -0,0 +1,321 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Online.Chat; +using osu.Game.Users; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Profile.Header +{ + public class CenterHeaderContainer : Container + { + public readonly BindableBool DetailsVisible = new BindableBool(); + + private OsuSpriteText followerText; + private ProfileHeaderButton messageButton; + private OsuSpriteText levelBadgeText; + + private Bar levelProgressBar; + private OsuSpriteText levelProgressText; + + private ProfileHeader.OverlinedInfoContainer hiddenDetailGlobal, hiddenDetailCountry; + + [Resolved(CanBeNull = true)] + private ChannelManager channelManager { get; set; } + + [Resolved(CanBeNull = true)] + private UserProfileOverlay userOverlay { get; set; } + + [Resolved(CanBeNull = true)] + private ChatOverlay chatOverlay { get; set; } + + [Resolved] + private APIAccess apiAccess { get; set; } + + private User user; + public User User + { + get => user; + set + { + if (user == value) return; + user = value; + updateDisplay(); + } + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, TextureStore textures) + { + Container hiddenDetailContainer, expandedDetailContainer; + SpriteIcon expandButtonIcon; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.CommunityUserGrayGreenDark + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Padding = new MarginPadding { Vertical = 10 }, + Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + new ProfileHeaderButton + { + RelativeSizeAxes = Axes.Y, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Horizontal, + Padding = new MarginPadding { Right = 10 }, + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.fa_user, + FillMode = FillMode.Fit, + Size = new Vector2(50, 14) + }, + followerText = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + TextSize = 16, + Font = "Exo2.0-Bold" + } + } + } + } + }, + messageButton = new ProfileHeaderButton + { + Alpha = 0, + RelativeSizeAxes = Axes.Y, + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.fa_envelope, + FillMode = FillMode.Fit, + Size = new Vector2(50, 14) + }, + } + }, + } + }, + new Container + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.Y, + Padding = new MarginPadding { Vertical = 10 }, + Width = UserProfileOverlay.CONTENT_X_MARGIN, + Child = new ProfileHeaderButton + { + RelativeSizeAxes = Axes.Y, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Action = DetailsVisible.Toggle, + Children = new Drawable[] + { + expandButtonIcon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(20), + Icon = FontAwesome.fa_chevron_up, + }, + } + }, + }, + new Container + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Right = UserProfileOverlay.CONTENT_X_MARGIN }, + Children = new Drawable[] + { + new ProfileHeader.HasTooltipContainer + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Size = new Vector2(40), + TooltipText = "Level", + Children = new Drawable[] + { + new Sprite + { + RelativeSizeAxes = Axes.Both, + Texture = textures.Get("Profile/levelbadge"), + Colour = colours.Yellow, + }, + levelBadgeText = new OsuSpriteText + { + TextSize = 20, + Font = "Exo2.0-Medium", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + } + }, + expandedDetailContainer = new ProfileHeader.HasTooltipContainer + { + TooltipText = "Progress to next level", + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Width = 200, + Height = 6, + Margin = new MarginPadding { Right = 50 }, + Children = new Drawable[] + { + new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = levelProgressBar = new Bar + { + RelativeSizeAxes = Axes.Both, + BackgroundColour = Color4.Black, + Direction = BarDirection.LeftToRight, + AccentColour = colours.Yellow + } + }, + levelProgressText = new OsuSpriteText + { + Anchor = Anchor.BottomRight, + Origin = Anchor.TopRight, + Font = "Exo2.0-Bold", + TextSize = 12, + } + } + }, + hiddenDetailContainer = new FillFlowContainer + { + Direction = FillDirection.Horizontal, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Width = 200, + AutoSizeAxes = Axes.Y, + Alpha = 0, + Spacing = new Vector2(10, 0), + Margin = new MarginPadding { Right = 50 }, + Children = new[] + { + hiddenDetailGlobal = new ProfileHeader.OverlinedInfoContainer + { + Title = "Global Ranking", + LineColour = colours.Yellow + }, + hiddenDetailCountry = new ProfileHeader.OverlinedInfoContainer + { + Title = "Country Ranking", + LineColour = colours.Yellow + }, + } + } + } + } + }; + + DetailsVisible.ValueChanged += newValue => expandButtonIcon.Icon = newValue ? FontAwesome.fa_chevron_down : FontAwesome.fa_chevron_up; + DetailsVisible.ValueChanged += newValue => hiddenDetailContainer.Alpha = newValue ? 1 : 0; + DetailsVisible.ValueChanged += newValue => expandedDetailContainer.Alpha = newValue ? 0 : 1; + } + + private void updateDisplay() + { + followerText.Text = user.FollowerCount?.Length > 0 ? user.FollowerCount[0].ToString("#,##0") : "0"; + + if (!user.PMFriendsOnly && apiAccess.LocalUser.Value.Id != user.Id) + { + messageButton.Show(); + messageButton.Action = () => + { + channelManager?.OpenPrivateChannel(user); + userOverlay?.Hide(); + chatOverlay?.Show(); + }; + } + else + { + messageButton.Hide(); + } + + levelBadgeText.Text = user.Statistics?.Level.Current.ToString() ?? "0"; + levelProgressBar.Length = user.Statistics?.Level.Progress / 100f ?? 0; + levelProgressText.Text = user.Statistics?.Level.Progress.ToString("0'%'"); + + hiddenDetailGlobal.Content = user?.Statistics?.Ranks.Global?.ToString("#,##0") ?? "-"; + hiddenDetailCountry.Content = user?.Statistics?.Ranks.Country?.ToString("#,##0") ?? "-"; + + } + + private class ProfileHeaderButton : OsuHoverContainer + { + private readonly Box background; + private readonly Container content; + + protected override Container Content => content; + + protected override IEnumerable EffectTargets => new[] { background }; + + public ProfileHeaderButton() + { + HoverColour = Color4.Black.Opacity(0.75f); + IdleColour = Color4.Black.Opacity(0.7f); + AutoSizeAxes = Axes.X; + + base.Content.Add(new CircularContainer + { + Masking = true, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + content = new Container + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = 10 }, + } + } + }); + } + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs new file mode 100644 index 0000000000..678fc2ddb7 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -0,0 +1,238 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Scoring; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Overlays.Profile.Header +{ + public class DetailHeaderContainer : Container + { + private ProfileHeader.HasTooltipContainer totalPlayTimeTooltip; + private ProfileHeader.OverlinedInfoContainer totalPlayTimeInfo, medalInfo, ppInfo; + private readonly Dictionary scoreRankInfos = new Dictionary(); + private ProfileHeader.OverlinedInfoContainer detailGlobalRank, detailCountryRank; + private RankGraph rankGraph; + + private User user; + public User User + { + get => user; + set + { + if (user == value) return; + user = value; + updateDisplay(); + } + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.CommunityUserGrayGreenDarkest, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + totalPlayTimeTooltip = new ProfileHeader.HasTooltipContainer + { + AutoSizeAxes = Axes.Both, + TooltipText = "0 hours", + Child = totalPlayTimeInfo = new ProfileHeader.OverlinedInfoContainer + { + Title = "Total Play Time", + LineColour = colours.Yellow, + }, + }, + medalInfo = new ProfileHeader.OverlinedInfoContainer + { + Title = "Medals", + LineColour = colours.GreenLight, + }, + ppInfo = new ProfileHeader.OverlinedInfoContainer + { + Title = "pp", + LineColour = colours.Red, + }, + } + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Direction = FillDirection.Horizontal, + Children = new[] + { + scoreRankInfos[ScoreRank.XH] = new ScoreRankInfo(ScoreRank.XH), + scoreRankInfos[ScoreRank.X] = new ScoreRankInfo(ScoreRank.X), + scoreRankInfos[ScoreRank.SH] = new ScoreRankInfo(ScoreRank.SH), + scoreRankInfos[ScoreRank.S] = new ScoreRankInfo(ScoreRank.S), + scoreRankInfos[ScoreRank.A] = new ScoreRankInfo(ScoreRank.A), + } + } + } + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Right = 130 }, + Children = new Drawable[] + { + rankGraph = new RankGraph + { + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + Width = 130, + Anchor = Anchor.TopRight, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Horizontal = 10 }, + Spacing = new Vector2(0, 20), + Children = new Drawable[] + { + detailGlobalRank = new ProfileHeader.OverlinedInfoContainer(true, 110) + { + Title = "Global Ranking", + LineColour = colours.Yellow, + }, + detailCountryRank = new ProfileHeader.OverlinedInfoContainer(false, 110) + { + Title = "Country Ranking", + LineColour = colours.Yellow, + }, + } + } + } + }, + } + }, + }; + } + + private void updateDisplay() + { + medalInfo.Content = user?.Achievements?.Length.ToString() ?? "0"; + ppInfo.Content = user?.Statistics?.PP?.ToString("#,##0") ?? "0"; + + string formatTime(int? secondsNull) + { + if (secondsNull == null) return "0h 0m"; + + int seconds = secondsNull.Value; + string time = ""; + + int days = seconds / 86400; + seconds -= days * 86400; + if (days > 0) + time += days + "d "; + + int hours = seconds / 3600; + seconds -= hours * 3600; + time += hours + "h "; + + int minutes = seconds / 60; + time += minutes + "m"; + + return time; + } + + totalPlayTimeInfo.Content = formatTime(user?.Statistics?.PlayTime); + totalPlayTimeTooltip.TooltipText = (user?.Statistics?.PlayTime ?? 0) / 3600 + " hours"; + + foreach (var scoreRankInfo in scoreRankInfos) + scoreRankInfo.Value.RankCount = user?.Statistics?.GradesCount.GetForScoreRank(scoreRankInfo.Key) ?? 0; + + detailGlobalRank.Content = user?.Statistics?.Ranks.Global?.ToString("#,##0") ?? "-"; + detailCountryRank.Content = user?.Statistics?.Ranks.Country?.ToString("#,##0") ?? "-"; + + rankGraph.User.Value = user; + } + + private class ScoreRankInfo : CompositeDrawable + { + private readonly ScoreRank rank; + private readonly Sprite rankSprite; + private readonly OsuSpriteText rankCount; + + public int RankCount + { + set => rankCount.Text = value.ToString("#,##0"); + } + + public ScoreRankInfo(ScoreRank rank) + { + this.rank = rank; + + AutoSizeAxes = Axes.Both; + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + Width = 56, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + rankSprite = new Sprite + { + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit + }, + rankCount = new OsuSpriteText + { + Font = "Exo2.0-Bold", + TextSize = 12, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + rankSprite.Texture = textures.Get($"Grades/{rank.GetDescription()}"); + } + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs new file mode 100644 index 0000000000..74f1e2f689 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs @@ -0,0 +1,132 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; +using osu.Game.Users; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Profile.Header +{ + public class MedalHeaderContainer : Container + { + private FillFlowContainer badgeFlowContainer; + + private User user; + public User User + { + get => user; + set + { + if (user == value) return; + user = value; + updateDisplay(); + } + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Alpha = 0; + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.CommunityUserGrayGreenDarkest, + }, + new Container //artificial shadow + { + RelativeSizeAxes = Axes.X, + Height = 3, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new ColourInfo + { + TopLeft = Color4.Black.Opacity(0.2f), + TopRight = Color4.Black.Opacity(0.2f), + BottomLeft = Color4.Black.Opacity(0), + BottomRight = Color4.Black.Opacity(0) + } + }, + }, + badgeFlowContainer = new FillFlowContainer + { + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Top = 5 }, + Spacing = new Vector2(10, 10), + Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, + } + }; + } + + private void updateDisplay() + { + var badges = User.Badges; + badgeFlowContainer.Clear(); + if (badges?.Length > 0) + { + Show(); + for (var index = 0; index < badges.Length; index++) + { + int displayIndex = index; + LoadComponentAsync(new DrawableBadge(badges[index]), asyncBadge => + { + badgeFlowContainer.Add(asyncBadge); + + // load in stable order regardless of async load order. + badgeFlowContainer.SetLayoutPosition(asyncBadge, displayIndex); + }); + } + } + else + { + Hide(); + } + } + + private class DrawableBadge : CompositeDrawable, IHasTooltip + { + public static readonly Vector2 DRAWABLE_BADGE_SIZE = new Vector2(86, 40); + + private readonly Badge badge; + + public DrawableBadge(Badge badge) + { + this.badge = badge; + Size = DRAWABLE_BADGE_SIZE; + } + + [BackgroundDependencyLoader] + private void load(LargeTextureStore textures) + { + InternalChild = new Sprite + { + FillMode = FillMode.Fit, + RelativeSizeAxes = Axes.Both, + Texture = textures.Get(badge.ImageUrl), + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + InternalChild.FadeInFromZero(200); + } + + public string TooltipText => badge.Description; + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs new file mode 100644 index 0000000000..b003f08b95 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -0,0 +1,210 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Overlays.Profile.Header +{ + public class TopHeaderContainer : Container + { + public SupporterIcon SupporterTag; + private UpdateableAvatar avatar; + private OsuSpriteText usernameText; + private ExternalLinkButton openUserExternally; + private OsuSpriteText titleText; + private DrawableFlag userFlag; + private OsuSpriteText userCountryText; + private FillFlowContainer userStats; + + private const float avatar_size = 110; + + private User user; + public User User + { + get => user; + set + { + if (user == value) return; + user = value; + updateDisplay(); + } + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.CommunityUserGrayGreenDarker, + }, + new FillFlowContainer + { + Direction = FillDirection.Horizontal, + Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, + Height = avatar_size, + AutoSizeAxes = Axes.X, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Children = new[] + { + avatar = new UpdateableAvatar + { + Size = new Vector2(avatar_size), + Masking = true, + CornerRadius = avatar_size * 0.25f, + OpenOnClick = { Value = false }, + }, + new Container + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Padding = new MarginPadding { Left = 10 }, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + usernameText = new OsuSpriteText + { + Font = "Exo2.0-Regular", + TextSize = 24 + }, + openUserExternally = new ExternalLinkButton + { + Margin = new MarginPadding { Left = 5 }, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + } + }, + new FillFlowContainer + { + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + titleText = new OsuSpriteText + { + TextSize = 18, + Font = "Exo2.0-Regular" + }, + SupporterTag = new SupporterIcon + { + Height = 20, + Margin = new MarginPadding { Top = 5 } + }, + new Box + { + RelativeSizeAxes = Axes.X, + Height = 1.5f, + Margin = new MarginPadding { Top = 10 }, + Colour = colours.CommunityUserGrayGreenLighter, + }, + new Container + { + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Top = 5 }, + Children = new Drawable[] + { + userFlag = new DrawableFlag + { + Size = new Vector2(30, 20) + }, + userCountryText = new OsuSpriteText + { + Font = "Exo2.0-Regular", + TextSize = 17.5f, + Margin = new MarginPadding { Left = 40 }, + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + Colour = colours.CommunityUserGrayGreenLighter, + } + } + }, + } + } + } + } + } + }, + userStats = new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Y, + Width = 300, + Margin = new MarginPadding { Right = UserProfileOverlay.CONTENT_X_MARGIN }, + Padding = new MarginPadding { Vertical = 15 }, + Spacing = new Vector2(0, 2) + } + }; + } + + private void updateDisplay() + { + avatar.User = User; + usernameText.Text = user.Username; + openUserExternally.Link = $@"https://osu.ppy.sh/users/{user.Id}"; + userFlag.Country = user.Country; + userCountryText.Text = user.Country?.FullName ?? "Alien"; + SupporterTag.SupporterLevel = user.SupportLevel; + titleText.Text = user.Title; + titleText.Colour = OsuColour.FromHex(user.Colour ?? "fff"); + + userStats.Clear(); + if (user.Statistics != null) + { + userStats.Add(new UserStatsLine("Ranked Score", user.Statistics.RankedScore.ToString("#,##0"))); + userStats.Add(new UserStatsLine("Hit Accuracy", Math.Round(user.Statistics.Accuracy, 2).ToString("#0.00'%'"))); + userStats.Add(new UserStatsLine("Play Count", user.Statistics.PlayCount.ToString("#,##0"))); + userStats.Add(new UserStatsLine("Total Score", user.Statistics.TotalScore.ToString("#,##0"))); + userStats.Add(new UserStatsLine("Total Hits", user.Statistics.TotalHits.ToString("#,##0"))); + userStats.Add(new UserStatsLine("Maximum Combo", user.Statistics.MaxCombo.ToString("#,##0"))); + userStats.Add(new UserStatsLine("Replays Watched by Others", user.Statistics.ReplaysWatched.ToString("#,##0"))); + } + } + + private class UserStatsLine : Container + { + public UserStatsLine(string left, string right) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Children = new Drawable[] + { + new OsuSpriteText + { + TextSize = 15, + Text = left, + Font = "Exo2.0-Medium" + }, + new OsuSpriteText + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + TextSize = 15, + Text = right, + Font = "Exo2.0-Bold" + }, + }; + } + } + } +} diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index e6d892f0b7..8709640b48 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -1,12 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; -using osu.Framework.Extensions; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -14,91 +10,32 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; -using osu.Game.Online.Chat; using osu.Game.Overlays.Profile.Header; -using osu.Game.Scoring; using osu.Game.Users; -using osuTK; namespace osu.Game.Overlays.Profile { public class ProfileHeader : Container { - private readonly RankGraph rankGraph; - - public readonly SupporterIcon SupporterTag; private readonly Container coverContainer; private readonly OsuSpriteText coverInfoText; private readonly ProfileHeaderTabControl infoTabControl; - private readonly Box headerTopBox; - private readonly UpdateableAvatar avatar; - private readonly OsuSpriteText usernameText; - private readonly ExternalLinkButton openUserExternally; - private readonly OsuSpriteText titleText; - private readonly DrawableFlag userFlag; - private readonly OsuSpriteText userCountryText; - private readonly Box userIconSeperatorBox; - private readonly FillFlowContainer userStats; - - private readonly Box headerCenterBox; - private readonly OsuSpriteText followerText; - private readonly ProfileHeaderButton messageButton; - private readonly ProfileHeaderButton expandButton; - private readonly Sprite levelBadgeSprite; - private readonly OsuSpriteText levelBadgeText; - - private readonly Bar levelProgressBar; - private readonly OsuSpriteText levelProgressText; - - private readonly OverlinedInfoContainer hiddenDetailGlobal, hiddenDetailCountry; + private readonly TopHeaderContainer topHeaderContainer; + public SupporterIcon SupporterTag => topHeaderContainer.SupporterTag; + private readonly CenterHeaderContainer centerHeaderContainer; public readonly BindableBool DetailsVisible = new BindableBool(); - private readonly Box headerDetailBox; - private readonly HasTooltipContainer totalPlayTimeTooltip; - private readonly OverlinedInfoContainer totalPlayTimeInfo, medalInfo, ppInfo; - private readonly Dictionary scoreRankInfos = new Dictionary(); - private readonly OverlinedInfoContainer detailGlobalRank, detailCountryRank; - - private readonly Box headerBadgeBox; - private readonly FillFlowContainer badgeFlowContainer; - private readonly Container badgeContainer; - - private readonly Box headerBottomBox; - private readonly LinkFlowContainer bottomTopLinkContainer; - private readonly LinkFlowContainer bottomLinkContainer; - private Color4 linkBlue; + private readonly DetailHeaderContainer detailHeaderContainer; + private readonly MedalHeaderContainer medalHeaderContainer; + private readonly BottomHeaderContainer bottomHeaderContainer; private const float cover_height = 150; private const float cover_info_height = 75; - private const float avatar_size = 110; - private static readonly Dictionary play_styles = new Dictionary - { - {"keyboard", "Keyboard"}, - {"mouse", "Mouse"}, - {"tablet", "Tablet"}, - {"touch", "Touch Screen"}, - }; - - [Resolved(CanBeNull = true)] - private ChannelManager channelManager { get; set; } - - [Resolved(CanBeNull = true)] - private UserProfileOverlay userOverlay { get; set; } - - [Resolved(CanBeNull = true)] - private ChatOverlay chatOverlay { get; set; } - - [Resolved] - private APIAccess apiAccess { get; set; } public ProfileHeader() { @@ -175,478 +112,30 @@ namespace osu.Game.Overlays.Profile Direction = FillDirection.Vertical, Children = new Drawable[] { - new Container + topHeaderContainer = new TopHeaderContainer { RelativeSizeAxes = Axes.X, Height = 150, - Children = new Drawable[] - { - headerTopBox = new Box - { - RelativeSizeAxes = Axes.Both, - }, - new FillFlowContainer - { - Direction = FillDirection.Horizontal, - Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, - Height = avatar_size, - AutoSizeAxes = Axes.X, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Children = new[] - { - avatar = new UpdateableAvatar - { - Size = new Vector2(avatar_size), - Masking = true, - CornerRadius = avatar_size * 0.25f, - OpenOnClick = { Value = false }, - }, - new Container - { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Padding = new MarginPadding { Left = 10 }, - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new Drawable[] - { - usernameText = new OsuSpriteText - { - Font = "Exo2.0-Regular", - TextSize = 24 - }, - openUserExternally = new ExternalLinkButton - { - Margin = new MarginPadding { Left = 5 }, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - }, - } - }, - new FillFlowContainer - { - Origin = Anchor.BottomLeft, - Anchor = Anchor.BottomLeft, - Direction = FillDirection.Vertical, - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - titleText = new OsuSpriteText - { - TextSize = 18, - Font = "Exo2.0-Regular" - }, - SupporterTag = new SupporterIcon - { - Height = 20, - Margin = new MarginPadding { Top = 5 } - }, - userIconSeperatorBox = new Box - { - RelativeSizeAxes = Axes.X, - Height = 1.5f, - Margin = new MarginPadding { Top = 10 } - }, - new Container - { - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Top = 5 }, - Children = new Drawable[] - { - userFlag = new DrawableFlag - { - Size = new Vector2(30, 20) - }, - userCountryText = new OsuSpriteText - { - Font = "Exo2.0-Regular", - TextSize = 17.5f, - Margin = new MarginPadding { Left = 40 }, - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - } - } - }, - } - } - } - } - } - }, - userStats = new FillFlowContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Y, - Width = 300, - Margin = new MarginPadding { Right = UserProfileOverlay.CONTENT_X_MARGIN }, - Padding = new MarginPadding { Vertical = 15 }, - Spacing = new Vector2(0, 2) - } - } }, - new Container + centerHeaderContainer = new CenterHeaderContainer { RelativeSizeAxes = Axes.X, Height = 60, - Children = new Drawable[] - { - headerCenterBox = new Box - { - RelativeSizeAxes = Axes.Both, - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Padding = new MarginPadding { Vertical = 10 }, - Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - new ProfileHeaderButton - { - RelativeSizeAxes = Axes.Y, - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Direction = FillDirection.Horizontal, - Padding = new MarginPadding { Right = 10 }, - Children = new Drawable[] - { - new SpriteIcon - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Icon = FontAwesome.fa_user, - FillMode = FillMode.Fit, - Size = new Vector2(50, 14) - }, - followerText = new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - TextSize = 16, - Font = "Exo2.0-Bold" - } - } - } - } - }, - messageButton = new ProfileHeaderButton - { - Alpha = 0, - RelativeSizeAxes = Axes.Y, - Children = new Drawable[] - { - new SpriteIcon - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Icon = FontAwesome.fa_envelope, - FillMode = FillMode.Fit, - Size = new Vector2(50, 14) - }, - } - }, - } - }, - new Container - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - RelativeSizeAxes = Axes.Y, - Padding = new MarginPadding { Vertical = 10 }, - Width = UserProfileOverlay.CONTENT_X_MARGIN, - Child = expandButton = new ProfileHeaderButton - { - RelativeSizeAxes = Axes.Y, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Children = new Drawable[] - { - expandButtonIcon = new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(20), - Icon = FontAwesome.fa_chevron_up, - }, - } - }, - }, - new Container - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Right = UserProfileOverlay.CONTENT_X_MARGIN }, - Children = new Drawable[] - { - new HasTooltipContainer - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Size = new Vector2(40), - TooltipText = "Level", - Children = new Drawable[] - { - levelBadgeSprite = new Sprite - { - RelativeSizeAxes = Axes.Both, - }, - levelBadgeText = new OsuSpriteText - { - TextSize = 20, - Font = "Exo2.0-Medium", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } - } - }, - expandedDetailContainer = new HasTooltipContainer - { - TooltipText = "Progress to next level", - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Width = 200, - Height = 6, - Margin = new MarginPadding { Right = 50 }, - Children = new Drawable[] - { - new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Child = levelProgressBar = new Bar - { - RelativeSizeAxes = Axes.Both, - BackgroundColour = Color4.Black, - Direction = BarDirection.LeftToRight, - } - }, - levelProgressText = new OsuSpriteText - { - Anchor = Anchor.BottomRight, - Origin = Anchor.TopRight, - Font = "Exo2.0-Bold", - TextSize = 12, - } - } - }, - hiddenDetailContainer = new FillFlowContainer - { - Direction = FillDirection.Horizontal, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Width = 200, - AutoSizeAxes = Axes.Y, - Alpha = 0, - Spacing = new Vector2(10, 0), - Margin = new MarginPadding { Right = 50 }, - Children = new[] - { - hiddenDetailGlobal = new OverlinedInfoContainer - { - Title = "Global Ranking" - }, - hiddenDetailCountry = new OverlinedInfoContainer - { - Title = "Country Ranking" - }, - } - } - } - } - } }, - new Container + detailHeaderContainer = new DetailHeaderContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - headerDetailBox = new Box - { - RelativeSizeAxes = Axes.Both, - }, - headerDetailContainer = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 20), - Children = new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - totalPlayTimeTooltip = new HasTooltipContainer - { - AutoSizeAxes = Axes.Both, - TooltipText = "0 hours", - Child = totalPlayTimeInfo = new OverlinedInfoContainer - { - Title = "Total Play Time", - }, - }, - medalInfo = new OverlinedInfoContainer - { - Title = "Medals" - }, - ppInfo = new OverlinedInfoContainer - { - Title = "pp" - }, - } - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Direction = FillDirection.Horizontal, - Children = new[] - { - scoreRankInfos[ScoreRank.XH] = new ScoreRankInfo(ScoreRank.XH), - scoreRankInfos[ScoreRank.X] = new ScoreRankInfo(ScoreRank.X), - scoreRankInfos[ScoreRank.SH] = new ScoreRankInfo(ScoreRank.SH), - scoreRankInfos[ScoreRank.S] = new ScoreRankInfo(ScoreRank.S), - scoreRankInfos[ScoreRank.A] = new ScoreRankInfo(ScoreRank.A), - } - } - } - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Right = 130 }, - Children = new Drawable[] - { - rankGraph = new RankGraph - { - RelativeSizeAxes = Axes.Both, - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Y, - Width = 130, - Anchor = Anchor.TopRight, - Direction = FillDirection.Vertical, - Padding = new MarginPadding { Horizontal = 10 }, - Spacing = new Vector2(0, 20), - Children = new Drawable[] - { - detailGlobalRank = new OverlinedInfoContainer(true, 110) - { - Title = "Global Ranking" - }, - detailCountryRank = new OverlinedInfoContainer(false, 110) - { - Title = "Country Ranking" - }, - } - } - } - }, - } - }, - } }, - badgeContainer = new Container + medalHeaderContainer = new MedalHeaderContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Alpha = 0, - Children = new Drawable[] - { - headerBadgeBox = new Box - { - RelativeSizeAxes = Axes.Both, - }, - new Container //artificial shadow - { - RelativeSizeAxes = Axes.X, - Height = 3, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = new ColourInfo - { - TopLeft = Color4.Black.Opacity(0.2f), - TopRight = Color4.Black.Opacity(0.2f), - BottomLeft = Color4.Black.Opacity(0), - BottomRight = Color4.Black.Opacity(0) - } - }, - }, - badgeFlowContainer = new FillFlowContainer - { - Direction = FillDirection.Full, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = 5 }, - Spacing = new Vector2(10, 10), - Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, - } - } }, - new Container + bottomHeaderContainer = new BottomHeaderContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - headerBottomBox = new Box - { - RelativeSizeAxes = Axes.Both, - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, - Spacing = new Vector2(0, 10), - Children = new Drawable[] - { - bottomTopLinkContainer = new LinkFlowContainer(text => text.TextSize = 12) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, - bottomLinkContainer = new LinkFlowContainer(text => text.TextSize = 12) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - } - } - } - } }, } } @@ -655,46 +144,16 @@ namespace osu.Game.Overlays.Profile infoTabControl.AddItem("Info"); infoTabControl.AddItem("Modding"); - DetailsVisible.ValueChanged += newValue => expandButtonIcon.Icon = newValue ? FontAwesome.fa_chevron_down : FontAwesome.fa_chevron_up; - DetailsVisible.ValueChanged += newValue => hiddenDetailContainer.Alpha = newValue ? 1 : 0; - DetailsVisible.ValueChanged += newValue => expandedDetailContainer.Alpha = newValue ? 0 : 1; - DetailsVisible.ValueChanged += newValue => headerDetailContainer.Alpha = newValue ? 0 : 1; + centerHeaderContainer.DetailsVisible.BindTo(DetailsVisible); + DetailsVisible.ValueChanged += newValue => detailHeaderContainer.Alpha = newValue ? 0 : 1; } - private Color4 communityUserGrayGreenLighter; - - [BackgroundDependencyLoader(true)] + [BackgroundDependencyLoader] private void load(OsuColour colours, TextureStore textures) { coverInfoText.Colour = colours.CommunityUserGreen; infoTabControl.AccentColour = colours.CommunityUserGreen; - - headerTopBox.Colour = colours.CommunityUserGrayGreenDarker; - userCountryText.Colour = colours.CommunityUserGrayGreenLighter; - userIconSeperatorBox.Colour = colours.CommunityUserGrayGreenLighter; - - headerCenterBox.Colour = colours.CommunityUserGrayGreenDark; - levelBadgeSprite.Texture = textures.Get("Profile/levelbadge"); - levelBadgeSprite.Colour = colours.Yellow; - levelProgressBar.AccentColour = colours.Yellow; - - hiddenDetailGlobal.LineColour = colours.Yellow; - hiddenDetailCountry.LineColour = colours.Yellow; - - headerDetailBox.Colour = colours.CommunityUserGrayGreenDarkest; - totalPlayTimeInfo.LineColour = colours.Yellow; - medalInfo.LineColour = colours.GreenLight; - ppInfo.LineColour = colours.Red; - - detailGlobalRank.LineColour = colours.Yellow; - detailCountryRank.LineColour = colours.Yellow; - - headerBadgeBox.Colour = colours.CommunityUserGrayGreenDarkest; - headerBottomBox.Colour = colours.CommunityUserGrayGreenDarker; - - communityUserGrayGreenLighter = colours.CommunityUserGrayGreenLighter; - linkBlue = colours.BlueLight; } private User user; @@ -704,13 +163,15 @@ namespace osu.Game.Overlays.Profile get => user; set { - user = value; - loadUser(); + medalHeaderContainer.User = detailHeaderContainer.User = bottomHeaderContainer.User = + centerHeaderContainer.User = topHeaderContainer.User = user = value; + updateDisplay(); } } - private void loadUser() + private void updateDisplay() { + coverContainer.RemoveAll(d => d is UserCoverBackground); LoadComponentAsync(new UserCoverBackground(user) { RelativeSizeAxes = Axes.Both, @@ -720,247 +181,14 @@ namespace osu.Game.Overlays.Profile OnLoadComplete = d => d.FadeInFromZero(200), Depth = float.MaxValue, }, coverContainer.Add); - - avatar.User = User; - usernameText.Text = user.Username; - openUserExternally.Link = $@"https://osu.ppy.sh/users/{user.Id}"; - userFlag.Country = user.Country; - userCountryText.Text = user.Country?.FullName; - SupporterTag.SupporterLevel = user.SupportLevel; - if(user.Title != null) - titleText.Text = user.Title; - titleText.Colour = OsuColour.FromHex(user.Colour ?? "fff"); - - userStats.Add(new UserStatsLine("Ranked Score", user.Statistics.RankedScore.ToString("#,##0"))); - userStats.Add(new UserStatsLine("Hit Accuracy", Math.Round(user.Statistics.Accuracy, 2).ToString("#0.00'%'"))); - userStats.Add(new UserStatsLine("Play Count", user.Statistics.PlayCount.ToString("#,##0"))); - userStats.Add(new UserStatsLine("Total Score", user.Statistics.TotalScore.ToString("#,##0"))); - userStats.Add(new UserStatsLine("Total Hits", user.Statistics.TotalHits.ToString("#,##0"))); - userStats.Add(new UserStatsLine("Maximum Combo", user.Statistics.MaxCombo.ToString("#,##0"))); - userStats.Add(new UserStatsLine("Replays Watched by Others", user.Statistics.ReplaysWatched.ToString("#,##0"))); - - followerText.Text = user.FollowerCount?.Length > 0 ? user.FollowerCount[0].ToString("#,##0") : "0"; - - if (!user.PMFriendsOnly && apiAccess.LocalUser.Value.Id != user.Id) - { - messageButton.Show(); - messageButton.Action = () => - { - channelManager?.OpenPrivateChannel(user); - userOverlay?.Hide(); - chatOverlay?.Show(); - }; - } - - expandButton.Action = DetailsVisible.Toggle; - - levelBadgeText.Text = user.Statistics.Level.Current.ToString(); - levelProgressBar.Length = user.Statistics.Level.Progress / 100f; - levelProgressText.Text = user.Statistics.Level.Progress.ToString("0'%'"); - - hiddenDetailGlobal.Content = user.Statistics.Ranks.Global?.ToString("#,##0") ?? "-"; - hiddenDetailCountry.Content = user.Statistics.Ranks.Country?.ToString("#,##0") ?? "-"; - - medalInfo.Content = user.Achievements.Length.ToString(); - ppInfo.Content = user.Statistics.PP?.ToString("#,##0") ?? "0"; - - string formatTime(int? secondsNull) - { - if (secondsNull == null) return "0h 0m"; - - int seconds = secondsNull.Value; - string time = ""; - - int days = seconds / 86400; - seconds -= days * 86400; - if (days > 0) - time += days + "d "; - - int hours = seconds / 3600; - seconds -= hours * 3600; - time += hours + "h "; - - int minutes = seconds / 60; - time += minutes + "m"; - - return time; - } - - totalPlayTimeInfo.Content = formatTime(user.Statistics.PlayTime); - totalPlayTimeTooltip.TooltipText = (user.Statistics.PlayTime ?? 0) / 3600 + " hours"; - - foreach (var scoreRankInfo in scoreRankInfos) - scoreRankInfo.Value.RankCount = user.Statistics.GradesCount.GetForScoreRank(scoreRankInfo.Key); - - detailGlobalRank.Content = user.Statistics.Ranks.Global?.ToString("#,##0") ?? "-"; - detailCountryRank.Content = user.Statistics.Ranks.Country?.ToString("#,##0") ?? "-"; - - rankGraph.User.Value = user; - - var badges = User.Badges; - if (badges.Length > 0) - { - badgeContainer.Show(); - for (var index = 0; index < badges.Length; index++) - { - int displayIndex = index; - LoadComponentAsync(new DrawableBadge(badges[index]), asyncBadge => - { - badgeFlowContainer.Add(asyncBadge); - - // load in stable order regardless of async load order. - badgeFlowContainer.SetLayoutPosition(asyncBadge, displayIndex); - }); - } - } - - void bold(SpriteText t) => t.Font = @"Exo2.0-Bold"; - void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); - - if (user.JoinDate.ToUniversalTime().Year < 2008) - { - bottomTopLinkContainer.AddText("Here since the beginning"); - } - else - { - bottomTopLinkContainer.AddText("Joined "); - bottomTopLinkContainer.AddText(new DrawableDate(user.JoinDate), bold); - } - - addSpacer(bottomTopLinkContainer); - - if (user.PlayStyles?.Length > 0) - { - bottomTopLinkContainer.AddText("Plays with "); - bottomTopLinkContainer.AddText(string.Join(", ", user.PlayStyles.Select(style => style.GetDescription())), bold); - - addSpacer(bottomTopLinkContainer); - } - - if (user.LastVisit.HasValue) - { - bottomTopLinkContainer.AddText("Last seen "); - bottomTopLinkContainer.AddText(new DrawableDate(user.LastVisit.Value), bold); - - addSpacer(bottomTopLinkContainer); - } - - bottomTopLinkContainer.AddText("Contributed "); - bottomTopLinkContainer.AddLink($@"{user.PostCount:#,##0} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: bold); - - void tryAddInfo(FontAwesome icon, string content, string link = null) - { - if (string.IsNullOrEmpty(content)) return; - - bottomLinkContainer.AddIcon(icon, text => - { - text.TextSize = 10; - text.Colour = communityUserGrayGreenLighter; - }); - if (link != null) - { - bottomLinkContainer.AddLink(" " + content, link, creationParameters: text => - { - bold(text); - text.Colour = linkBlue; - }); - } - else - { - bottomLinkContainer.AddText(" " + content, bold); - } - addSpacer(bottomLinkContainer); - } - - string websiteWithoutProtcol = user.Website; - if (!string.IsNullOrEmpty(websiteWithoutProtcol)) - { - int protocolIndex = websiteWithoutProtcol.IndexOf("//", StringComparison.Ordinal); - if (protocolIndex >= 0) - websiteWithoutProtcol = websiteWithoutProtcol.Substring(protocolIndex + 2); - } - - tryAddInfo(FontAwesome.fa_map_marker, user.Location); - tryAddInfo(FontAwesome.fa_heart_o, user.Interests); - tryAddInfo(FontAwesome.fa_suitcase, user.Occupation); - bottomLinkContainer.NewLine(); - if (!string.IsNullOrEmpty(user.Twitter)) - tryAddInfo(FontAwesome.fa_twitter, "@" + user.Twitter, $@"https://twitter.com/{user.Twitter}"); - tryAddInfo(FontAwesome.fa_gamepad, user.Discord); //todo: update fontawesome to include discord logo - tryAddInfo(FontAwesome.fa_skype, user.Skype, @"skype:" + user.Skype + @"?chat"); - tryAddInfo(FontAwesome.fa_lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); - tryAddInfo(FontAwesome.fa_link, websiteWithoutProtcol, user.Website); } - private class UserStatsLine : Container - { - public UserStatsLine(string left, string right) - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Children = new Drawable[] - { - new OsuSpriteText - { - TextSize = 15, - Text = left, - Font = "Exo2.0-Medium" - }, - new OsuSpriteText - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - TextSize = 15, - Text = right, - Font = "Exo2.0-Bold" - }, - }; - } - } - - private class ProfileHeaderButton : OsuHoverContainer - { - private readonly Box background; - private readonly Container content; - - protected override Container Content => content; - - protected override IEnumerable EffectTargets => new[] { background }; - - public ProfileHeaderButton() - { - HoverColour = Color4.Black.Opacity(0.75f); - IdleColour = Color4.Black.Opacity(0.7f); - AutoSizeAxes = Axes.X; - - base.Content.Add(new CircularContainer - { - Masking = true, - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - content = new Container - { - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = 10 }, - } - } - }); - } - } - - private class HasTooltipContainer : Container, IHasTooltip + public class HasTooltipContainer : Container, IHasTooltip { public string TooltipText { get; set; } } - private class OverlinedInfoContainer : CompositeDrawable + public class OverlinedInfoContainer : CompositeDrawable { private readonly Circle line; private readonly OsuSpriteText title, content; @@ -1012,83 +240,5 @@ namespace osu.Game.Overlays.Profile }; } } - - public class ScoreRankInfo : CompositeDrawable - { - private readonly ScoreRank rank; - private readonly Sprite rankSprite; - private readonly OsuSpriteText rankCount; - - public int RankCount - { - set => rankCount.Text = value.ToString("#,##0"); - } - - public ScoreRankInfo(ScoreRank rank) - { - this.rank = rank; - - AutoSizeAxes = Axes.Both; - InternalChild = new FillFlowContainer - { - AutoSizeAxes = Axes.Y, - Width = 56, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - rankSprite = new Sprite - { - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit - }, - rankCount = new OsuSpriteText - { - Font = "Exo2.0-Bold", - TextSize = 12, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - } - } - }; - } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - rankSprite.Texture = textures.Get($"Grades/{rank.GetDescription()}"); - } - } - - private class DrawableBadge : CompositeDrawable, IHasTooltip - { - public static readonly Vector2 DRAWABLE_BADGE_SIZE = new Vector2(86, 40); - - private readonly Badge badge; - - public DrawableBadge(Badge badge) - { - this.badge = badge; - Size = DRAWABLE_BADGE_SIZE; - } - - [BackgroundDependencyLoader] - private void load(LargeTextureStore textures) - { - InternalChild = new Sprite - { - FillMode = FillMode.Fit, - RelativeSizeAxes = Axes.Both, - Texture = textures.Get(badge.ImageUrl), - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - InternalChild.FadeInFromZero(200); - } - - public string TooltipText => badge.Description; - } } } From 14d2ed7085a82ab9ba5d6c91a2aefd6cec4b9471 Mon Sep 17 00:00:00 2001 From: jorolf Date: Tue, 22 Jan 2019 19:50:42 +0100 Subject: [PATCH 0341/5608] fix codefactor issue that I didn't notice and has been there for 12 days --- osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs index 9005fd5ab2..9be1eb4326 100644 --- a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs @@ -278,7 +278,6 @@ namespace osu.Game.Overlays.Profile.Header hiddenDetailGlobal.Content = user?.Statistics?.Ranks.Global?.ToString("#,##0") ?? "-"; hiddenDetailCountry.Content = user?.Statistics?.Ranks.Country?.ToString("#,##0") ?? "-"; - } private class ProfileHeaderButton : OsuHoverContainer From 481f33d17be543c6cef45f5d9e4875cde2e94432 Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 23 Jan 2019 14:27:34 +0100 Subject: [PATCH 0342/5608] add setting to toggle the gameplay cursor trail --- .../Configuration/OsuConfigManager.cs | 4 +++- osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs | 12 +++++++++++- osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs | 5 +++++ osu.Game/Configuration/GameConfigManager.cs | 5 ----- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Configuration/OsuConfigManager.cs b/osu.Game.Rulesets.Osu/Configuration/OsuConfigManager.cs index 4fa49faf1d..492cc7cc7f 100644 --- a/osu.Game.Rulesets.Osu/Configuration/OsuConfigManager.cs +++ b/osu.Game.Rulesets.Osu/Configuration/OsuConfigManager.cs @@ -19,12 +19,14 @@ namespace osu.Game.Rulesets.Osu.Configuration Set(OsuSetting.SnakingInSliders, true); Set(OsuSetting.SnakingOutSliders, true); + Set(OsuSetting.ShowCursorTrail, true); } } public enum OsuSetting { SnakingInSliders, - SnakingOutSliders + SnakingOutSliders, + ShowCursorTrail } } diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs index 582b99af7c..cf6ae2ad3d 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -23,6 +24,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor protected override Container Content => fadeContainer; + private Bindable showTrail; + private readonly CursorTrail cursorTrail; private readonly Container fadeContainer; public GameplayCursor() @@ -32,11 +35,18 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new CursorTrail { Depth = 1 } + cursorTrail = new CursorTrail { Depth = 1 } } }; } + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + showTrail = config.GetBindable(OsuSetting.ShowCursorTrail); + showTrail.ValueChanged += v => cursorTrail.Alpha = v ? 1 : 0; + } + private int downCount; private void updateExpandedState() diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs index 9aa0f4101d..12ef66fa25 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs @@ -34,6 +34,11 @@ namespace osu.Game.Rulesets.Osu.UI LabelText = "Snaking out sliders", Bindable = config.GetBindable(OsuSetting.SnakingOutSliders) }, + new SettingsCheckbox + { + LabelText = "Show cursor trail", + Bindable = config.GetBindable(OsuSetting.ShowCursorTrail) + }, }; } } diff --git a/osu.Game/Configuration/GameConfigManager.cs b/osu.Game/Configuration/GameConfigManager.cs index 736273dc35..b2f2a8e971 100644 --- a/osu.Game/Configuration/GameConfigManager.cs +++ b/osu.Game/Configuration/GameConfigManager.cs @@ -72,9 +72,6 @@ namespace osu.Game.Configuration Set(GameSetting.MenuParallax, true); - Set(GameSetting.SnakingInSliders, true); - Set(GameSetting.SnakingOutSliders, true); - // Gameplay Set(GameSetting.DimLevel, 0.3, 0, 1, 0.01); Set(GameSetting.BlurLevel, 0, 0, 1, 0.01); @@ -150,8 +147,6 @@ namespace osu.Game.Configuration DisplayStarsMinimum, DisplayStarsMaximum, RandomSelectAlgorithm, - SnakingInSliders, - SnakingOutSliders, ShowFpsDisplay, ChatDisplayHeight, Version, From 3e936d386d6975984942e0862b766b0d161b12ec Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 23 Jan 2019 14:54:03 +0100 Subject: [PATCH 0343/5608] add missing dependency --- osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs index 472da88e1f..b24abc3d0a 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.Cursor; +using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Tests.Visual; @@ -20,6 +21,16 @@ namespace osu.Game.Rulesets.Osu.Tests public override IReadOnlyList RequiredTypes => new [] { typeof(CursorTrail) }; + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + + var configCache = dependencies.Get(); + dependencies.CacheAs((OsuConfigManager)configCache.GetConfigFor(new OsuRuleset())); + + return dependencies; + } + public CursorContainer Cursor => cursor; public bool ProvidingUserCursor => true; From 92edafc44a370ad4bdc4312c70190319a1aca3dc Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 23 Jan 2019 15:01:35 +0100 Subject: [PATCH 0344/5608] yeet whitespace --- osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs index b24abc3d0a..89b62116c5 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Tests return dependencies; } - + public CursorContainer Cursor => cursor; public bool ProvidingUserCursor => true; From 648ed0e4677356a2b07721696ee3eece95fbe8af Mon Sep 17 00:00:00 2001 From: jorolf Date: Sun, 27 Jan 2019 23:45:00 +0100 Subject: [PATCH 0345/5608] update license headers --- osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs | 4 ++-- osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 4 ++-- osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs | 4 ++-- osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs | 4 ++-- osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs | 4 ++-- osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs | 4 ++-- osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs b/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs index c80227f149..6f164890f9 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index a3a6447a9f..df0409272f 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Linq; diff --git a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs index 9be1eb4326..30671487d3 100644 --- a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index 678fc2ddb7..124299b0ba 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs index 74f1e2f689..5a54270b80 100644 --- a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs index db8a0b594c..fd7124f20f 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs +++ b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Shapes; diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index b003f08b95..4186d08729 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using osu.Framework.Allocation; From c62848df5ae98a42add6352833ed5d085b2af2cd Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Wed, 30 Jan 2019 18:07:32 -0600 Subject: [PATCH 0346/5608] Update license header --- osu.Android/OsuGameActivity.cs | 16 +++++++++++++--- .../MainActivity.cs | 4 ++-- .../MainActivity.cs | 4 ++-- .../MainActivity.cs | 4 ++-- .../MainActivity.cs | 4 ++-- osu.Game.Tests.Android/MainActivity.cs | 6 +++--- 6 files changed, 24 insertions(+), 14 deletions(-) diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index 08f2707044..130144d417 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.cs @@ -1,17 +1,27 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Android.App; using Android.Content.PM; +using Android.OS; +using Android.Views; using osu.Framework.Android; using osu.Game; namespace osu.Android { - [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] + [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize, HardwareAccelerated = true)] public class OsuGameActivity : AndroidGameActivity { protected override Framework.Game CreateGame() => new OsuGame(); + + protected override void OnCreate(Bundle savedInstanceState) + { + base.OnCreate(savedInstanceState); + + Window.AddFlags(WindowManagerFlags.Fullscreen); + Window.AddFlags(WindowManagerFlags.KeepScreenOn); + } } } diff --git a/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs index 4b13b86ca2..8430a88f15 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Android.App; using Android.Content.PM; diff --git a/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs index 3c0de47654..0f1d6756bc 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Android.App; using Android.Content.PM; diff --git a/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs index 622eadef70..d6f2ec546d 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Android.App; using Android.Content.PM; diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs index 0c64cbfc5d..cc92ad7080 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Android.App; using Android.Content.PM; diff --git a/osu.Game.Tests.Android/MainActivity.cs b/osu.Game.Tests.Android/MainActivity.cs index 58375c699e..6f68c372ef 100644 --- a/osu.Game.Tests.Android/MainActivity.cs +++ b/osu.Game.Tests.Android/MainActivity.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Android.App; using Android.Content.PM; @@ -7,7 +7,7 @@ using osu.Framework.Android; namespace osu.Game.Tests.Android { - [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] + [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize, HardwareAccelerated = true)] public class MainActivity : AndroidGameActivity { protected override Framework.Game CreateGame() From cb23918512a1c8e7d2d65aa5170336a3567381e1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 3 Feb 2019 11:24:43 +0900 Subject: [PATCH 0347/5608] Changes for mania world cup --- osu.Game.Tournament/Components/SongBar.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 14a01aebdf..fc75bd59a4 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -190,7 +190,12 @@ namespace osu.Game.Tournament.Components Anchor = Anchor.CentreLeft, Origin = Anchor.TopLeft }, - new DiffPiece(("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), ("AR", $"{ar:0.#}{srExtra}"), ("OD", $"{beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}")) + new DiffPiece( + //("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), + //("AR", $"{ar:0.#}{srExtra}"), + ("OD", $"{beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}"), + ("HP", $"{beatmap.BaseDifficulty.DrainRate:0.#}{hardRockExtra}") + ) { Anchor = Anchor.CentreRight, Origin = Anchor.BottomRight From 559960036e61edf1caefb5670fe9c939dad0ef59 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 5 Feb 2019 14:48:35 +0300 Subject: [PATCH 0348/5608] update top score design --- .../Graphics/Containers/OsuHoverContainer.cs | 10 +- .../BeatmapSet/Scores/ClickableUsername.cs | 15 +- .../BeatmapSet/Scores/DrawableScore.cs | 16 +- .../BeatmapSet/Scores/DrawableTopScore.cs | 422 ++++++++++++------ .../BeatmapSet/Scores/ScoresContainer.cs | 7 + 5 files changed, 328 insertions(+), 142 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index 276b0f9dd1..091499b7cd 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Input.Events; +using osuTK.Graphics; +using System.Collections.Generic; namespace osu.Game.Graphics.Containers { @@ -16,17 +16,19 @@ namespace osu.Game.Graphics.Containers protected Color4 IdleColour = Color4.White; + protected const float FADE_DURATION = 500; + protected virtual IEnumerable EffectTargets => new[] { Content }; protected override bool OnHover(HoverEvent e) { - EffectTargets.ForEach(d => d.FadeColour(HoverColour, 500, Easing.OutQuint)); + EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - EffectTargets.ForEach(d => d.FadeColour(IdleColour, 500, Easing.OutQuint)); + EffectTargets.ForEach(d => d.FadeColour(IdleColour, FADE_DURATION, Easing.OutQuint)); base.OnHoverLost(e); } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs index 0eb8b325d3..e2aade986d 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs @@ -3,16 +3,20 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Users; +using System.Collections.Generic; namespace osu.Game.Overlays.BeatmapSet.Scores { public class ClickableUsername : OsuHoverContainer { - private readonly OsuSpriteText text; + private readonly SpriteText text; + protected override IEnumerable EffectTargets => new[] { text }; + private UserProfileOverlay profile; private User user; @@ -24,7 +28,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (user == value) return; user = value; - text.Text = user.Username; + OnUserUpdate(user); } } @@ -41,12 +45,17 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public ClickableUsername() { AutoSizeAxes = Axes.Both; - Child = text = new OsuSpriteText + Child = text = new SpriteText { Font = @"Exo2.0-BoldItalic", }; } + protected virtual void OnUserUpdate(User user) + { + text.Text = user.Username; + } + [BackgroundDependencyLoader(true)] private void load(UserProfileOverlay profile) { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index 1f50385adc..609524f170 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.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 osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -16,6 +15,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Users; +using osuTK; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -56,13 +56,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Size = new Vector2(30, 20), Margin = new MarginPadding { Left = 60 } }, - new ClickableUsername - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - User = score.User, - Margin = new MarginPadding { Left = 100 } - }, + //new ClickableUsername + //{ + // Anchor = Anchor.CentreLeft, + // Origin = Anchor.CentreLeft, + // User = score.User, + // Margin = new MarginPadding { Left = 100 } + //}, modsContainer = new ScoreModsContainer { Anchor = Anchor.CentreLeft, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index c9551cf6f8..2e2bb78634 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -1,13 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; -using osuTK.Graphics; +using Humanizer; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -19,29 +19,38 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Users; +using osuTK; +using osuTK.Graphics; +using System.Collections.Generic; namespace osu.Game.Overlays.BeatmapSet.Scores { public class DrawableTopScore : Container { private const float fade_duration = 100; - private const float height = 200; + private const float height = 100; private const float avatar_size = 80; private const float margin = 10; private readonly Box background; - private readonly Box bottomBackground; - private readonly Box middleLine; private readonly UpdateableAvatar avatar; private readonly DrawableFlag flag; private readonly ClickableUsername username; - private readonly OsuSpriteText rankText; - private readonly OsuSpriteText date; + private readonly SpriteText rankText; + private readonly SpriteText date; private readonly DrawableRank rank; - private readonly InfoColumn totalScore; - private readonly InfoColumn accuracy; - private readonly InfoColumn statistics; - private readonly ScoreModsContainer modsContainer; + + private readonly AutoSizeInfoColumn totalScore; + private readonly MediumInfoColumn accuracy; + private readonly MediumInfoColumn maxCombo; + + private readonly SmallInfoColumn hitGreat; + private readonly SmallInfoColumn hitGood; + private readonly SmallInfoColumn hitMeh; + private readonly SmallInfoColumn hitMiss; + private readonly SmallInfoColumn pp; + + private readonly ModsInfoColumn modsInfo; private APIScoreInfo score; public APIScoreInfo Score @@ -54,153 +63,296 @@ namespace osu.Game.Overlays.BeatmapSet.Scores avatar.User = username.User = score.User; flag.Country = score.User.Country; - date.Text = $@"achieved {score.Date:MMM d, yyyy}"; + date.Text = $@"achieved {score.Date.Humanize()}"; rank.UpdateRank(score.Rank); totalScore.Value = $@"{score.TotalScore:N0}"; accuracy.Value = $@"{score.Accuracy:P2}"; - statistics.Value = $"{score.Statistics[HitResult.Great]}/{score.Statistics[HitResult.Good]}/{score.Statistics[HitResult.Meh]}"; + maxCombo.Value = $@"{score.MaxCombo:N0}x"; - modsContainer.Clear(); - foreach (Mod mod in score.Mods) - modsContainer.Add(new ModIcon(mod) - { - AutoSizeAxes = Axes.Both, - Scale = new Vector2(0.45f), - }); + hitGreat.Value = $"{score.Statistics[HitResult.Great]}"; + hitGood.Value = $"{score.Statistics[HitResult.Good]}"; + hitMeh.Value = $"{score.Statistics[HitResult.Meh]}"; + hitMiss.Value = $"{score.Statistics[HitResult.Miss]}"; + pp.Value = $@"{score.PP:N0}"; + + modsInfo.ClearMods(); + modsInfo.Mods = score.Mods; } } public DrawableTopScore() { RelativeSizeAxes = Axes.X; - Height = height; - CornerRadius = 5; - BorderThickness = 4; + AutoSizeAxes = Axes.Y; + CornerRadius = 3; Masking = true; + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.2f), + Radius = 1, + Offset = new Vector2(0, 1), + }; Children = new Drawable[] { background = new Box { RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true, //used for correct border representation - }, - avatar = new UpdateableAvatar - { - Size = new Vector2(avatar_size), - Masking = true, - CornerRadius = 5, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(0.25f), - Offset = new Vector2(0, 2), - Radius = 1, - }, - Margin = new MarginPadding { Top = margin, Left = margin } - }, - flag = new DrawableFlag - { - Size = new Vector2(30, 20), - Position = new Vector2(margin * 2 + avatar_size, height / 4), - }, - username = new ClickableUsername - { - Origin = Anchor.BottomLeft, - TextSize = 30, - Position = new Vector2(margin * 2 + avatar_size, height / 4), - Margin = new MarginPadding { Bottom = 4 } - }, - rankText = new OsuSpriteText - { - Anchor = Anchor.TopRight, - Origin = Anchor.BottomRight, - Text = "#1", - TextSize = 40, - Font = @"Exo2.0-BoldItalic", - Y = height / 4, - Margin = new MarginPadding { Right = margin } - }, - date = new OsuSpriteText - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Y = height / 4, - Margin = new MarginPadding { Right = margin } + Colour = Color4.White, }, new Container { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.Both, - Height = 0.5f, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding(margin), Children = new Drawable[] { - bottomBackground = new Box { RelativeSizeAxes = Axes.Both }, - middleLine = new Box + new FillFlowContainer { - RelativeSizeAxes = Axes.X, - Height = 1, - }, - rank = new DrawableRank(ScoreRank.F) - { - Origin = Anchor.BottomLeft, - Size = new Vector2(avatar_size, 40), - FillMode = FillMode.Fit, - Y = height / 4, - Margin = new MarginPadding { Left = margin } - }, - new FillFlowContainer - { - Origin = Anchor.BottomLeft, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, - Position = new Vector2(height / 2, height / 4), Direction = FillDirection.Horizontal, - Spacing = new Vector2(15, 0), - Children = new[] + Spacing = new Vector2(margin, 0), + Children = new Drawable[] { - totalScore = new InfoColumn("Score"), - accuracy = new InfoColumn("Accuracy"), - statistics = new InfoColumn("300/100/50"), - }, + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 2), + Children = new Drawable[] + { + rankText = new SpriteText + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Text = "#1", + TextSize = 20, + Font = @"Exo2.0-BoldItalic", + }, + rank = new DrawableRank(ScoreRank.F) + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Size = new Vector2(30), + FillMode = FillMode.Fit, + }, + } + }, + avatar = new UpdateableAvatar + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(avatar_size), + Masking = true, + CornerRadius = 5, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.25f), + Offset = new Vector2(0, 2), + Radius = 1, + }, + }, + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 3), + Children = new Drawable[] + { + username = new ClickableTopScoreUsername + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + TextSize = 20, + }, + date = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + TextSize = 10, + }, + flag = new DrawableFlag + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(20, 13), + }, + } + } + } }, - modsContainer = new ScoreModsContainer + new Container { - AutoSizeAxes = Axes.Y, - Width = 80, - Position = new Vector2(height / 2, height / 4), + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(margin, 0), + Children = new Drawable[] + { + totalScore = new AutoSizeInfoColumn("Total Score"), + accuracy = new MediumInfoColumn("Accuracy"), + maxCombo = new MediumInfoColumn("Max Combo"), + hitGreat = new SmallInfoColumn("300", 20), + hitGood = new SmallInfoColumn("100", 20), + hitMeh = new SmallInfoColumn("50", 20), + hitMiss = new SmallInfoColumn("miss", 20), + pp = new SmallInfoColumn("pp", 20), + modsInfo = new ModsInfoColumn("mods"), + } + } } } - }, + } }; } [BackgroundDependencyLoader] private void load(OsuColour colours) { - background.Colour = bottomBackground.Colour = colours.Gray4; - middleLine.Colour = colours.Gray2; - date.Colour = colours.Gray9; - BorderColour = rankText.Colour = colours.Yellow; + date.Colour = rankText.Colour = colours.ContextMenuGray; } protected override bool OnHover(HoverEvent e) { - background.FadeIn(fade_duration, Easing.OutQuint); + background.FadeColour(Color4.WhiteSmoke, fade_duration, Easing.OutQuint); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - background.FadeOut(fade_duration, Easing.OutQuint); + background.FadeColour(Color4.White, fade_duration, Easing.OutQuint); base.OnHoverLost(e); } - private class InfoColumn : FillFlowContainer + private class ClickableTopScoreUsername : ClickableUsername { - private readonly OsuSpriteText headerText; - private readonly OsuSpriteText valueText; + private Box underscore; + + public ClickableTopScoreUsername() + { + Add(new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Height = 1, + Position = new Vector2(0, TextSize / 2 + 1.5f), + Depth = 1, + Child = underscore = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + } + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + IdleColour = colours.ContextMenuGray; + HoverColour = underscore.Colour = colours.Blue; + } + + protected override bool OnHover(HoverEvent e) + { + underscore.FadeIn(FADE_DURATION, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + underscore.FadeOut(FADE_DURATION, Easing.OutQuint); + base.OnHoverLost(e); + } + } + + private class DrawableInfoColumn : FillFlowContainer + { + private readonly SpriteText headerText; + private const float header_text_size = 12; + + public DrawableInfoColumn(string header) + { + AutoSizeAxes = Axes.Y; + Direction = FillDirection.Vertical; + Spacing = new Vector2(0, 2); + Children = new Drawable[] + { + new Container + { + AutoSizeAxes = Axes.X, + Height = header_text_size, + Child = headerText = new SpriteText + { + TextSize = 12, + Text = header.ToUpper(), + } + }, + new Container + { + RelativeSizeAxes = Axes.X, + Height = 3, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.LightGray, + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + headerText.Colour = colours.ContextMenuGray; + } + } + + private class ModsInfoColumn : DrawableInfoColumn + { + private readonly FillFlowContainer modsContainer; + + public IEnumerable Mods + { + set + { + foreach (Mod mod in value) + modsContainer.Add(new ModIcon(mod) + { + AutoSizeAxes = Axes.Both, + Scale = new Vector2(0.3f), + }); + } + } + + public ModsInfoColumn(string header) : base(header) + { + AutoSizeAxes = Axes.Both; + Add(modsContainer = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + }); + } + + public void ClearMods() => modsContainer.Clear(); + } + + private class TextInfoColumn : DrawableInfoColumn + { + private readonly SpriteText valueText; public string Value { @@ -213,31 +365,47 @@ namespace osu.Game.Overlays.BeatmapSet.Scores get { return valueText.Text; } } - public InfoColumn(string header) + public TextInfoColumn(string header, float valueTextSize = 25) : base(header) { - AutoSizeAxes = Axes.Both; - Direction = FillDirection.Vertical; - Spacing = new Vector2(0, 3); - Children = new Drawable[] + Add(valueText = new SpriteText { - headerText = new OsuSpriteText - { - TextSize = 14, - Text = header, - Font = @"Exo2.0-Bold", - }, - valueText = new OsuSpriteText - { - TextSize = 25, - Font = @"Exo2.0-RegularItalic", - } - }; + TextSize = valueTextSize, + Font = @"Exo2.0-Light", + }); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - headerText.Colour = colours.Gray9; + valueText.Colour = colours.ContextMenuGray; + } + } + + private class AutoSizeInfoColumn : TextInfoColumn + { + public AutoSizeInfoColumn(string header, float valueTextSize = 25) : base(header, valueTextSize) + { + AutoSizeAxes = Axes.Both; + } + } + + private class MediumInfoColumn : TextInfoColumn + { + private const float width = 70; + + public MediumInfoColumn(string header, float valueTextSize = 25) : base(header, valueTextSize) + { + Width = width; + } + } + + private class SmallInfoColumn : TextInfoColumn + { + private const float width = 40; + + public SmallInfoColumn(string header, float valueTextSize = 25) : base(header, valueTextSize) + { + Width = width; } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index ab34d2ba1d..ac3068c2c8 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -12,6 +12,8 @@ using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; +using osu.Framework.Graphics.Shapes; +using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -98,6 +100,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores AutoSizeAxes = Axes.Y; Children = new Drawable[] { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }, new FillFlowContainer { Anchor = Anchor.TopCentre, From f560dde157acd3bb83cf417fd6d10a8d67088576 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 5 Feb 2019 15:26:45 +0300 Subject: [PATCH 0349/5608] Add some flow for info containers --- .../BeatmapSet/Scores/DrawableTopScore.cs | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 2e2bb78634..d061e176e0 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -193,23 +193,49 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Width = 0.7f, Child = new FillFlowContainer { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(margin, 0), + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Spacing = new Vector2(margin), Children = new Drawable[] { - totalScore = new AutoSizeInfoColumn("Total Score"), - accuracy = new MediumInfoColumn("Accuracy"), - maxCombo = new MediumInfoColumn("Max Combo"), - hitGreat = new SmallInfoColumn("300", 20), - hitGood = new SmallInfoColumn("100", 20), - hitMeh = new SmallInfoColumn("50", 20), - hitMiss = new SmallInfoColumn("miss", 20), - pp = new SmallInfoColumn("pp", 20), - modsInfo = new ModsInfoColumn("mods"), + new FillFlowContainer + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(margin, 0), + Children = new Drawable[] + { + hitGreat = new SmallInfoColumn("300", 20), + hitGood = new SmallInfoColumn("100", 20), + hitMeh = new SmallInfoColumn("50", 20), + hitMiss = new SmallInfoColumn("miss", 20), + pp = new SmallInfoColumn("pp", 20), + modsInfo = new ModsInfoColumn("mods"), + } + }, + new FillFlowContainer + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(margin, 0), + Children = new Drawable[] + { + totalScore = new AutoSizeInfoColumn("Total Score"), + accuracy = new MediumInfoColumn("Accuracy"), + maxCombo = new MediumInfoColumn("Max Combo"), + } + }, } } } @@ -248,7 +274,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.Centre, RelativeSizeAxes = Axes.X, Height = 1, - Position = new Vector2(0, TextSize / 2 + 1.5f), + Position = new Vector2(0, TextSize / 2 - 1), Depth = 1, Child = underscore = new Box { From c85dc1a2362434298d57661f4cd87e8f71f4e049 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 5 Feb 2019 19:32:33 +0300 Subject: [PATCH 0350/5608] update another scores design --- .../Visual/TestCaseBeatmapSetOverlay.cs | 8 +- ...eUsername.cs => ClickableUserContainer.cs} | 29 +- .../BeatmapSet/Scores/DrawableScore.cs | 278 ++++++++++++++---- .../BeatmapSet/Scores/DrawableTopScore.cs | 46 ++- .../BeatmapSet/Scores/ScoreTextLine.cs | 118 ++++++++ .../BeatmapSet/Scores/ScoresContainer.cs | 18 +- 6 files changed, 397 insertions(+), 100 deletions(-) rename osu.Game/Overlays/BeatmapSet/Scores/{ClickableUsername.cs => ClickableUserContainer.cs} (60%) create mode 100644 osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs index b98014b866..20609dc595 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs @@ -1,9 +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.Collections.Generic; -using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; @@ -13,6 +10,9 @@ using osu.Game.Overlays.BeatmapSet.Buttons; using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Rulesets; using osu.Game.Users; +using System; +using System.Collections.Generic; +using System.Linq; namespace osu.Game.Tests.Visual { @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual public override IReadOnlyList RequiredTypes => new[] { typeof(Header), - typeof(ClickableUsername), + typeof(ClickableUserContainer), typeof(DrawableScore), typeof(DrawableTopScore), typeof(ScoresContainer), diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs similarity index 60% rename from osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs rename to osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs index e2aade986d..2f402bfa74 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; @@ -12,11 +13,8 @@ using System.Collections.Generic; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class ClickableUsername : OsuHoverContainer + public abstract class ClickableUserContainer : Container { - private readonly SpriteText text; - protected override IEnumerable EffectTargets => new[] { text }; - private UserProfileOverlay profile; private User user; @@ -28,33 +26,16 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (user == value) return; user = value; - OnUserUpdate(user); + OnUserChange(user); } } - public float TextSize - { - set - { - if (text.TextSize == value) return; - text.TextSize = value; - } - get { return text.TextSize; } - } - - public ClickableUsername() + public ClickableUserContainer() { AutoSizeAxes = Axes.Both; - Child = text = new SpriteText - { - Font = @"Exo2.0-BoldItalic", - }; } - protected virtual void OnUserUpdate(User user) - { - text.Text = user.Username; - } + protected abstract void OnUserChange(User user); [BackgroundDependencyLoader(true)] private void load(UserProfileOverlay profile) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index 609524f170..6f6fd22a13 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -16,62 +17,63 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Users; using osuTK; +using osuTK.Graphics; +using System.Collections.Generic; namespace osu.Game.Overlays.BeatmapSet.Scores { public class DrawableScore : Container { private const int fade_duration = 100; - private const float side_margin = 20; + private const float text_size = 14; private readonly Box background; + private readonly Box hoveredBackground; + private readonly SpriteText rank; + private readonly SpriteText scoreText; + private readonly SpriteText accuracy; + private readonly SpriteText maxCombo; + private readonly SpriteText hitGreat; + private readonly SpriteText hitGood; + private readonly SpriteText hitMeh; + private readonly SpriteText hitMiss; + private readonly SpriteText pp; + + private readonly ClickableScoreUsername username; + + private readonly APIScoreInfo score; + private Color4 backgroundColor; public DrawableScore(int index, APIScoreInfo score) { - ScoreModsContainer modsContainer; + FillFlowContainer modsContainer; + + this.score = score; RelativeSizeAxes = Axes.X; - Height = 30; + Height = 25; CornerRadius = 3; Masking = true; Children = new Drawable[] { background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + hoveredBackground = new Box { RelativeSizeAxes = Axes.Both, Alpha = 0, }, - new OsuSpriteText + rank = new SpriteText { Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, + Origin = Anchor.CentreRight, Text = $"#{index + 1}", - Font = @"Exo2.0-RegularItalic", - Margin = new MarginPadding { Left = side_margin } - }, - new DrawableFlag(score.User.Country) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(30, 20), - Margin = new MarginPadding { Left = 60 } - }, - //new ClickableUsername - //{ - // Anchor = Anchor.CentreLeft, - // Origin = Anchor.CentreLeft, - // User = score.User, - // Margin = new MarginPadding { Left = 100 } - //}, - modsContainer = new ScoreModsContainer - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Width = 0.06f, - RelativePositionAxes = Axes.X, - X = 0.42f + TextSize = text_size, + X = ScoreTextLine.RANK_POSITION, + Font = @"Exo2.0-Bold", + Colour = Color4.Black, }, new DrawableRank(score.Rank) { @@ -79,64 +81,232 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.CentreLeft, Size = new Vector2(30, 20), FillMode = FillMode.Fit, - RelativePositionAxes = Axes.X, - X = 0.55f + X = 45 }, - new OsuSpriteText + scoreText = new SpriteText { Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreRight, + Origin = Anchor.CentreLeft, Text = $@"{score.TotalScore:N0}", - Font = @"Venera", - RelativePositionAxes = Axes.X, - X = 0.75f, - FixedWidth = true, + X = ScoreTextLine.SCORE_POSITION, + Colour = Color4.Black, + TextSize = text_size, }, - new OsuSpriteText + accuracy = new SpriteText { Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreRight, + Origin = Anchor.CentreLeft, Text = $@"{score.Accuracy:P2}", - Font = @"Exo2.0-RegularItalic", - RelativePositionAxes = Axes.X, - X = 0.85f + X = ScoreTextLine.ACCURACY_POSITION, + TextSize = text_size, }, - new OsuSpriteText + new DrawableFlag(score.User.Country) { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Text = $"{score.Statistics[HitResult.Great]}/{score.Statistics[HitResult.Good]}/{score.Statistics[HitResult.Meh]}", - Font = @"Exo2.0-RegularItalic", - Margin = new MarginPadding { Right = side_margin } + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(20, 13), + X = 230, + }, + username = new ClickableScoreUsername + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + User = score.User, + X = ScoreTextLine.PLAYER_POSITION, + Colour = Color4.Black, + }, + maxCombo = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = $@"{score.MaxCombo:N0}x", + RelativePositionAxes = Axes.X, + X = ScoreTextLine.MAX_COMBO_POSITION, + TextSize = text_size, + Colour = Color4.Black, + }, + hitGreat = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = $"{score.Statistics[HitResult.Great]}", + RelativePositionAxes = Axes.X, + X = ScoreTextLine.HIT_GREAT_POSITION, + TextSize = text_size, + Colour = Color4.Black, + }, + hitGood = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = $"{score.Statistics[HitResult.Good]}", + RelativePositionAxes = Axes.X, + X = ScoreTextLine.HIT_GOOD_POSITION, + TextSize = text_size, + Colour = Color4.Black, + }, + hitMeh = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = $"{score.Statistics[HitResult.Meh]}", + RelativePositionAxes = Axes.X, + X = ScoreTextLine.HIT_MEH_POSITION, + TextSize = text_size, + Colour = Color4.Black, + }, + hitMiss = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = $"{score.Statistics[HitResult.Miss]}", + RelativePositionAxes = Axes.X, + X = ScoreTextLine.HIT_MISS_POSITION, + TextSize = text_size, + Colour = Color4.Black, + }, + pp = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = $@"{score.PP:N0}", + RelativePositionAxes = Axes.X, + X = ScoreTextLine.PP_POSITION, + TextSize = text_size, + Colour = Color4.Black, + }, + modsContainer = new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.Centre, + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + RelativePositionAxes = Axes.X, + X = ScoreTextLine.MODS_POSITION, }, }; + if (index == 0) + scoreText.Font = @"Exo2.0-Bold"; + + accuracy.Colour = (score.Accuracy == 1) ? Color4.Green : Color4.Black; + + hitGreat.Colour = (score.Statistics[HitResult.Great] == 0) ? Color4.Gray : Color4.Black; + hitGood.Colour = (score.Statistics[HitResult.Good] == 0) ? Color4.Gray : Color4.Black; + hitMeh.Colour = (score.Statistics[HitResult.Meh] == 0) ? Color4.Gray : Color4.Black; + hitMiss.Colour = (score.Statistics[HitResult.Miss] == 0) ? Color4.Gray : Color4.Black; + + background.Colour = backgroundColor = (index % 2 == 0) ? Color4.WhiteSmoke : Color4.White; + + foreach (Mod mod in score.Mods) modsContainer.Add(new ModIcon(mod) { AutoSizeAxes = Axes.Both, - Scale = new Vector2(0.35f), + Scale = new Vector2(0.3f), }); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - background.Colour = colours.Gray4; + hoveredBackground.Colour = colours.Gray4; } protected override bool OnHover(HoverEvent e) { - background.FadeIn(fade_duration, Easing.OutQuint); + hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); + rank.FadeColour(Color4.White, fade_duration, Easing.OutQuint); + scoreText.FadeColour(Color4.White, fade_duration, Easing.OutQuint); + accuracy.FadeColour(Color4.White, fade_duration, Easing.OutQuint); + username.FadeColour(Color4.White, fade_duration, Easing.OutQuint); + maxCombo.FadeColour(Color4.White, fade_duration, Easing.OutQuint); + pp.FadeColour(Color4.White, fade_duration, Easing.OutQuint); + + if (score.Statistics[HitResult.Great] != 0) + hitGreat.FadeColour(Color4.White, fade_duration, Easing.OutQuint); + + if (score.Statistics[HitResult.Good] != 0) + hitGood.FadeColour(Color4.White, fade_duration, Easing.OutQuint); + + if (score.Statistics[HitResult.Meh] != 0) + hitMeh.FadeColour(Color4.White, fade_duration, Easing.OutQuint); + + if (score.Statistics[HitResult.Miss] != 0) + hitMiss.FadeColour(Color4.White, fade_duration, Easing.OutQuint); + return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - background.FadeOut(fade_duration, Easing.OutQuint); + hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); + rank.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); + scoreText.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); + username.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); + accuracy.FadeColour((score.Accuracy == 1) ? Color4.Green : Color4.Black, fade_duration, Easing.OutQuint); + maxCombo.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); + pp.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); + + if (score.Statistics[HitResult.Great] != 0) + hitGreat.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); + + if (score.Statistics[HitResult.Good] != 0) + hitGood.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); + + if (score.Statistics[HitResult.Meh] != 0) + hitMeh.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); + + if (score.Statistics[HitResult.Miss] != 0) + hitMiss.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); + base.OnHoverLost(e); } protected override bool OnClick(ClickEvent e) => true; + + private class ClickableScoreUsername : ClickableUserContainer + { + private readonly SpriteText text; + private readonly SpriteText textBold; + + public ClickableScoreUsername() + { + Add(text = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + TextSize = text_size, + }); + + Add(textBold = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + TextSize = text_size, + Font = @"Exo2.0-Bold", + Alpha = 0, + }); + } + + protected override void OnUserChange(User user) + { + text.Text = textBold.Text = user.Username; + } + + protected override bool OnHover(HoverEvent e) + { + textBold.FadeIn(fade_duration, Easing.OutQuint); + text.FadeOut(fade_duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + textBold.FadeOut(fade_duration, Easing.OutQuint); + text.FadeIn(fade_duration, Easing.OutQuint); + base.OnHoverLost(e); + } + } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index d061e176e0..7d82b05099 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly Box background; private readonly UpdateableAvatar avatar; private readonly DrawableFlag flag; - private readonly ClickableUsername username; + private readonly ClickableTopScoreUsername username; private readonly SpriteText rankText; private readonly SpriteText date; private readonly DrawableRank rank; @@ -262,44 +262,70 @@ namespace osu.Game.Overlays.BeatmapSet.Scores base.OnHoverLost(e); } - private class ClickableTopScoreUsername : ClickableUsername + private class ClickableTopScoreUsername : ClickableUserContainer { - private Box underscore; + private const float fade_duration = 500; + + private readonly Box underscore; + private readonly Container underscoreContainer; + private readonly SpriteText text; + + private Color4 hoverColour; + + public float TextSize + { + set + { + if (text.TextSize == value) return; + text.TextSize = value; + } + get { return text.TextSize; } + } public ClickableTopScoreUsername() { - Add(new Container + Add(underscoreContainer = new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.X, Height = 1, - Position = new Vector2(0, TextSize / 2 - 1), - Depth = 1, Child = underscore = new Box { RelativeSizeAxes = Axes.Both, Alpha = 0, } }); + Add(text = new SpriteText + { + Font = @"Exo2.0-BoldItalic", + Colour = Color4.Black, + }); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - IdleColour = colours.ContextMenuGray; - HoverColour = underscore.Colour = colours.Blue; + hoverColour = underscore.Colour = colours.Blue; + underscoreContainer.Position = new Vector2(0, TextSize / 2 - 1); + } + + protected override void OnUserChange(User user) + { + text.Text = user.Username; } protected override bool OnHover(HoverEvent e) { - underscore.FadeIn(FADE_DURATION, Easing.OutQuint); + text.FadeColour(hoverColour, fade_duration, Easing.OutQuint); + underscore.FadeIn(fade_duration, Easing.OutQuint); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - underscore.FadeOut(FADE_DURATION, Easing.OutQuint); + text.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); + underscore.FadeOut(fade_duration, Easing.OutQuint); base.OnHoverLost(e); } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs new file mode 100644 index 0000000000..d8655b4882 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs @@ -0,0 +1,118 @@ +// 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.Sprites; +using osu.Framework.Localisation; +using osu.Game.Graphics; + +namespace osu.Game.Overlays.BeatmapSet.Scores +{ + public class ScoreTextLine : Container + { + private const float text_size = 12; + + public const float RANK_POSITION = 30; + public const float SCORE_POSITION = 90; + public const float ACCURACY_POSITION = 170; + public const float PLAYER_POSITION = 270; + public const float MAX_COMBO_POSITION = 0.5f; + public const float HIT_GREAT_POSITION = 0.6f; + public const float HIT_GOOD_POSITION = 0.65f; + public const float HIT_MEH_POSITION = 0.7f; + public const float HIT_MISS_POSITION = 0.75f; + public const float PP_POSITION = 0.8f; + public const float MODS_POSITION = 0.9f; + + public ScoreTextLine() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Children = new Drawable[] + { + new ScoreText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreRight, + Text = "rank".ToUpper(), + X = RANK_POSITION, + }, + new ScoreText + { + Text = "score".ToUpper(), + X = SCORE_POSITION, + }, + new ScoreText + { + Text = "accuracy".ToUpper(), + X = ACCURACY_POSITION, + }, + new ScoreText + { + Text = "player".ToUpper(), + X = PLAYER_POSITION, + }, + new ScoreText + { + Text = "max combo".ToUpper(), + X = MAX_COMBO_POSITION, + RelativePositionAxes = Axes.X, + }, + new ScoreText + { + Text = "300", + RelativePositionAxes = Axes.X, + X = HIT_GREAT_POSITION, + }, + new ScoreText + { + Text = "100".ToUpper(), + RelativePositionAxes = Axes.X, + X = HIT_GOOD_POSITION, + }, + new ScoreText + { + Text = "50".ToUpper(), + RelativePositionAxes = Axes.X, + X = HIT_MEH_POSITION, + }, + new ScoreText + { + Text = "miss".ToUpper(), + RelativePositionAxes = Axes.X, + X = HIT_MISS_POSITION, + }, + new ScoreText + { + Text = "pp".ToUpper(), + RelativePositionAxes = Axes.X, + X = PP_POSITION, + }, + new ScoreText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.Centre, + Text = "mods".ToUpper(), + X = MODS_POSITION, + RelativePositionAxes = Axes.X, + }, + }; + } + + private class ScoreText : SpriteText + { + public ScoreText() + { + TextSize = text_size; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.ContextMenuGray; + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index ac3068c2c8..5fd1084a14 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -1,19 +1,19 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; +using osuTK; +using osuTK.Graphics; using System.Collections.Generic; using System.Linq; -using osu.Framework.Allocation; -using osu.Game.Beatmaps; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests.Responses; -using osu.Framework.Graphics.Shapes; -using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -90,7 +90,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (scoreCount < 2) return; - for (int i = 1; i < scoreCount; i++) + flow.Add(new ScoreTextLine()); + + for (int i = 0; i < scoreCount; i++) flow.Add(new DrawableScore(i, scores.ElementAt(i))); } From 9cca11fb0d71c81f930cb48dd95a6ff9962cdd8f Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Wed, 6 Feb 2019 01:48:43 +0300 Subject: [PATCH 0351/5608] Warning fixes --- .../BeatmapSet/Scores/ClickableUserContainer.cs | 6 +----- osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs | 9 ++------- .../Overlays/BeatmapSet/Scores/DrawableTopScore.cs | 12 +++++------- osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs | 1 - 4 files changed, 8 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs index 2f402bfa74..621e1ee1f2 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs @@ -4,12 +4,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; using osu.Game.Users; -using System.Collections.Generic; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -30,7 +26,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } - public ClickableUserContainer() + protected ClickableUserContainer() { AutoSizeAxes = Axes.Both; } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index 6f6fd22a13..c2f198d3ee 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -8,17 +8,14 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; -using osu.Game.Overlays.Profile.Sections.Ranks; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Users; using osuTK; using osuTK.Graphics; -using System.Collections.Generic; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -27,7 +24,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private const int fade_duration = 100; private const float text_size = 14; - private readonly Box background; private readonly Box hoveredBackground; private readonly SpriteText rank; private readonly SpriteText scoreText; @@ -42,11 +38,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly ClickableScoreUsername username; private readonly APIScoreInfo score; - private Color4 backgroundColor; public DrawableScore(int index, APIScoreInfo score) { FillFlowContainer modsContainer; + Box background; this.score = score; @@ -196,8 +192,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores hitMeh.Colour = (score.Statistics[HitResult.Meh] == 0) ? Color4.Gray : Color4.Black; hitMiss.Colour = (score.Statistics[HitResult.Miss] == 0) ? Color4.Gray : Color4.Black; - background.Colour = backgroundColor = (index % 2 == 0) ? Color4.WhiteSmoke : Color4.White; - + background.Colour = (index % 2 == 0) ? Color4.WhiteSmoke : Color4.White; foreach (Mod mod in score.Mods) modsContainer.Add(new ModIcon(mod) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 7d82b05099..48b824390d 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -10,10 +10,8 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; -using osu.Game.Overlays.Profile.Sections.Ranks; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; @@ -264,7 +262,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private class ClickableTopScoreUsername : ClickableUserContainer { - private const float fade_duration = 500; + private const float username_fade_duration = 500; private readonly Box underscore; private readonly Container underscoreContainer; @@ -317,15 +315,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores protected override bool OnHover(HoverEvent e) { - text.FadeColour(hoverColour, fade_duration, Easing.OutQuint); - underscore.FadeIn(fade_duration, Easing.OutQuint); + text.FadeColour(hoverColour, username_fade_duration, Easing.OutQuint); + underscore.FadeIn(username_fade_duration, Easing.OutQuint); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - text.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); - underscore.FadeOut(fade_duration, Easing.OutQuint); + text.FadeColour(Color4.Black, username_fade_duration, Easing.OutQuint); + underscore.FadeOut(username_fade_duration, Easing.OutQuint); base.OnHoverLost(e); } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs index d8655b4882..53a477b908 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Localisation; using osu.Game.Graphics; namespace osu.Game.Overlays.BeatmapSet.Scores From 5048f425d4b5fa37881fea1ae0c648ef441ca8ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Feb 2019 18:36:15 +0900 Subject: [PATCH 0352/5608] Add ability to reset bracket --- .../Screens/Ladder/Components/MatchPairing.cs | 9 +++++++++ osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index b3adc3b49b..7d6acc5bd2 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -110,5 +110,14 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Team1Score.Value = 0; Team2Score.Value = 0; } + + public void Reset() + { + CancelMatchStart(); + Team1.Value = null; + Team2.Value = null; + Completed.Value = false; + PicksBans.Clear(); + } } } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs index adc880e524..e3cb1473be 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs @@ -77,6 +77,11 @@ namespace osu.Game.Tournament.Screens.Ladder var pos = PairingsContainer.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position); AddPairing(new MatchPairing { Position = { Value = new Point((int)pos.X, (int)pos.Y) } }); }), + new OsuMenuItem("Reset teams", MenuItemType.Destructive, () => + { + foreach (var p in PairingsContainer) + p.Pairing.Reset(); + }) }; } } From 2a9da602cb388028dbed0973b35c952093ea8567 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Feb 2019 13:07:57 +0900 Subject: [PATCH 0353/5608] Use nuget packages again --- osu.Game/osu.Game.csproj | 4 +--- osu.sln | 12 ------------ 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3b1b276130..fd79f65989 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,13 +15,11 @@ + - - - diff --git a/osu.sln b/osu.sln index 59b85c8936..688339fab5 100644 --- a/osu.sln +++ b/osu.sln @@ -29,10 +29,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament", "osu. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament.Tests", "osu.Game.Tournament.Tests\osu.Game.Tournament.Tests.csproj", "{5789E78D-38F9-4072-AB7B-978F34B2C17F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework", "..\osu-framework\osu.Framework\osu.Framework.csproj", "{7A69A230-45A1-4444-8C43-A582E4F48C1E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework.NativeLibs", "..\osu-framework\osu.Framework.NativeLibs\osu.Framework.NativeLibs.csproj", "{C3ECD150-D109-453F-9625-518B282CF745}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -91,14 +87,6 @@ Global {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|Any CPU.Build.0 = Debug|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.ActiveCfg = Release|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.Build.0 = Release|Any CPU - {7A69A230-45A1-4444-8C43-A582E4F48C1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7A69A230-45A1-4444-8C43-A582E4F48C1E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7A69A230-45A1-4444-8C43-A582E4F48C1E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7A69A230-45A1-4444-8C43-A582E4F48C1E}.Release|Any CPU.Build.0 = Release|Any CPU - {C3ECD150-D109-453F-9625-518B282CF745}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C3ECD150-D109-453F-9625-518B282CF745}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C3ECD150-D109-453F-9625-518B282CF745}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C3ECD150-D109-453F-9625-518B282CF745}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 61e6285f7a601bbf5d292216ca04d640b8a6bc4f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Feb 2019 15:20:22 +0900 Subject: [PATCH 0354/5608] Update paths --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 83dbe11ffa..7f8ed0cb3d 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -141,12 +141,12 @@ namespace osu.Game.Tournament.IPC { try { - stableInstallPath = "E:\\osu!tourney"; + stableInstallPath = "G:\\My Drive\\Main\\osu!tourney"; if (checkExists(stableInstallPath)) return stableInstallPath; - stableInstallPath = "E:\\osu!mappool"; + stableInstallPath = "G:\\My Drive\\Main\\osu!mappool"; if (checkExists(stableInstallPath)) return stableInstallPath; From f43ee6b6a36f12c54de0a2c941c27a01bcb85626 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Fri, 8 Feb 2019 19:06:46 +0300 Subject: [PATCH 0355/5608] update drawable top score inline with the latest design --- .../BeatmapSet/Scores/DrawableTopScore.cs | 85 ++++++++----------- .../BeatmapSet/Scores/ScoresContainer.cs | 7 -- 2 files changed, 35 insertions(+), 57 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 48b824390d..487194c819 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -30,6 +30,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private const float avatar_size = 80; private const float margin = 10; + private OsuColour colours; + + private Color4 backgroundIdleColour => colours.Gray3; + private Color4 backgroundHoveredColour => colours.Gray4; + private readonly Box background; private readonly UpdateableAvatar avatar; private readonly DrawableFlag flag; @@ -38,8 +43,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly SpriteText date; private readonly DrawableRank rank; - private readonly AutoSizeInfoColumn totalScore; - private readonly MediumInfoColumn accuracy; + private readonly AutoSizedInfoColumn totalScore; + private readonly AutoSizedInfoColumn accuracy; private readonly MediumInfoColumn maxCombo; private readonly SmallInfoColumn hitGreat; @@ -56,7 +61,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores get { return score; } set { - if (score == value) return; + if (score == value) + return; score = value; avatar.User = username.User = score.User; @@ -83,7 +89,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - CornerRadius = 3; + CornerRadius = 10; Masking = true; EdgeEffect = new EdgeEffectParameters { @@ -97,7 +103,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores background = new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4.White, }, new Container { @@ -115,31 +120,20 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(margin, 0), Children = new Drawable[] { - new FillFlowContainer + rankText = new SpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 2), - Children = new Drawable[] - { - rankText = new SpriteText - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Text = "#1", - TextSize = 20, - Font = @"Exo2.0-BoldItalic", - }, - rank = new DrawableRank(ScoreRank.F) - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Size = new Vector2(30), - FillMode = FillMode.Fit, - }, - } + Text = "#1", + TextSize = 30, + Font = @"Exo2.0-BoldItalic", + }, + rank = new DrawableRank(ScoreRank.F) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(40), + FillMode = FillMode.Fit, }, avatar = new UpdateableAvatar { @@ -229,8 +223,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(margin, 0), Children = new Drawable[] { - totalScore = new AutoSizeInfoColumn("Total Score"), - accuracy = new MediumInfoColumn("Accuracy"), + totalScore = new AutoSizedInfoColumn("Total Score"), + accuracy = new AutoSizedInfoColumn("Accuracy"), maxCombo = new MediumInfoColumn("Max Combo"), } }, @@ -245,18 +239,21 @@ namespace osu.Game.Overlays.BeatmapSet.Scores [BackgroundDependencyLoader] private void load(OsuColour colours) { - date.Colour = rankText.Colour = colours.ContextMenuGray; + this.colours = colours; + + rankText.Colour = colours.Yellow; + background.Colour = backgroundIdleColour; } protected override bool OnHover(HoverEvent e) { - background.FadeColour(Color4.WhiteSmoke, fade_duration, Easing.OutQuint); + background.FadeColour(backgroundHoveredColour, fade_duration, Easing.OutQuint); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - background.FadeColour(Color4.White, fade_duration, Easing.OutQuint); + background.FadeColour(backgroundIdleColour, fade_duration, Easing.OutQuint); base.OnHoverLost(e); } @@ -274,7 +271,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { set { - if (text.TextSize == value) return; + if (text.TextSize == value) + return; text.TextSize = value; } get { return text.TextSize; } @@ -297,7 +295,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Add(text = new SpriteText { Font = @"Exo2.0-BoldItalic", - Colour = Color4.Black, }); } @@ -322,7 +319,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores protected override void OnHoverLost(HoverLostEvent e) { - text.FadeColour(Color4.Black, username_fade_duration, Easing.OutQuint); + text.FadeColour(Color4.White, username_fade_duration, Easing.OutQuint); underscore.FadeOut(username_fade_duration, Easing.OutQuint); base.OnHoverLost(e); } @@ -348,6 +345,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { TextSize = 12, Text = header.ToUpper(), + Font = @"Exo2.0-Bold", } }, new Container @@ -362,12 +360,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } }; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - headerText.Colour = colours.ContextMenuGray; - } } private class ModsInfoColumn : DrawableInfoColumn @@ -420,20 +412,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Add(valueText = new SpriteText { TextSize = valueTextSize, - Font = @"Exo2.0-Light", }); } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - valueText.Colour = colours.ContextMenuGray; - } } - private class AutoSizeInfoColumn : TextInfoColumn + private class AutoSizedInfoColumn : TextInfoColumn { - public AutoSizeInfoColumn(string header, float valueTextSize = 25) : base(header, valueTextSize) + public AutoSizedInfoColumn(string header, float valueTextSize = 25) : base(header, valueTextSize) { AutoSizeAxes = Axes.Both; } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 5fd1084a14..5211f1398f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -4,14 +4,12 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osuTK; -using osuTK.Graphics; using System.Collections.Generic; using System.Linq; @@ -102,11 +100,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores AutoSizeAxes = Axes.Y; Children = new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.White, - }, new FillFlowContainer { Anchor = Anchor.TopCentre, From 7a3ae0f479bebb101ad8b00828419ff0eae5291d Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Fri, 8 Feb 2019 19:50:02 +0300 Subject: [PATCH 0356/5608] update drawable score inline with the latest design --- .../BeatmapSet/Scores/DrawableScore.cs | 75 ++++--------------- .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 58 ++++++++++++++ .../BeatmapSet/Scores/ScoreTextLine.cs | 16 +--- .../BeatmapSet/Scores/ScoresContainer.cs | 22 +++--- 4 files changed, 87 insertions(+), 84 deletions(-) create mode 100644 osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index c2f198d3ee..1076fe6449 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -25,6 +25,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private const float text_size = 14; private readonly Box hoveredBackground; + private readonly Box background; + private readonly SpriteText rank; private readonly SpriteText scoreText; private readonly SpriteText accuracy; @@ -39,10 +41,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly APIScoreInfo score; - public DrawableScore(int index, APIScoreInfo score) + public DrawableScore(int index, APIScoreInfo score, int maxModsAmount) { FillFlowContainer modsContainer; - Box background; this.score = score; @@ -69,7 +70,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores TextSize = text_size, X = ScoreTextLine.RANK_POSITION, Font = @"Exo2.0-Bold", - Colour = Color4.Black, }, new DrawableRank(score.Rank) { @@ -85,7 +85,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.CentreLeft, Text = $@"{score.TotalScore:N0}", X = ScoreTextLine.SCORE_POSITION, - Colour = Color4.Black, TextSize = text_size, }, accuracy = new SpriteText @@ -109,7 +108,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.CentreLeft, User = score.User, X = ScoreTextLine.PLAYER_POSITION, - Colour = Color4.Black, }, maxCombo = new SpriteText { @@ -119,7 +117,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativePositionAxes = Axes.X, X = ScoreTextLine.MAX_COMBO_POSITION, TextSize = text_size, - Colour = Color4.Black, }, hitGreat = new SpriteText { @@ -129,7 +126,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativePositionAxes = Axes.X, X = ScoreTextLine.HIT_GREAT_POSITION, TextSize = text_size, - Colour = Color4.Black, }, hitGood = new SpriteText { @@ -139,7 +135,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativePositionAxes = Axes.X, X = ScoreTextLine.HIT_GOOD_POSITION, TextSize = text_size, - Colour = Color4.Black, }, hitMeh = new SpriteText { @@ -149,7 +144,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativePositionAxes = Axes.X, X = ScoreTextLine.HIT_MEH_POSITION, TextSize = text_size, - Colour = Color4.Black, }, hitMiss = new SpriteText { @@ -159,7 +153,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativePositionAxes = Axes.X, X = ScoreTextLine.HIT_MISS_POSITION, TextSize = text_size, - Colour = Color4.Black, }, pp = new SpriteText { @@ -169,34 +162,35 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativePositionAxes = Axes.X, X = ScoreTextLine.PP_POSITION, TextSize = text_size, - Colour = Color4.Black, }, modsContainer = new FillFlowContainer { - Anchor = Anchor.CentreLeft, - Origin = Anchor.Centre, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreLeft, Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, - RelativePositionAxes = Axes.X, - X = ScoreTextLine.MODS_POSITION, + X = -30 * maxModsAmount, }, }; if (index == 0) scoreText.Font = @"Exo2.0-Bold"; - accuracy.Colour = (score.Accuracy == 1) ? Color4.Green : Color4.Black; + accuracy.Colour = (score.Accuracy == 1) ? Color4.LightGreen : Color4.White; - hitGreat.Colour = (score.Statistics[HitResult.Great] == 0) ? Color4.Gray : Color4.Black; - hitGood.Colour = (score.Statistics[HitResult.Good] == 0) ? Color4.Gray : Color4.Black; - hitMeh.Colour = (score.Statistics[HitResult.Meh] == 0) ? Color4.Gray : Color4.Black; - hitMiss.Colour = (score.Statistics[HitResult.Miss] == 0) ? Color4.Gray : Color4.Black; + hitGreat.Colour = (score.Statistics[HitResult.Great] == 0) ? Color4.Gray : Color4.White; + hitGood.Colour = (score.Statistics[HitResult.Good] == 0) ? Color4.Gray : Color4.White; + hitMeh.Colour = (score.Statistics[HitResult.Meh] == 0) ? Color4.Gray : Color4.White; + hitMiss.Colour = (score.Statistics[HitResult.Miss] == 0) ? Color4.Gray : Color4.White; - background.Colour = (index % 2 == 0) ? Color4.WhiteSmoke : Color4.White; + if (index % 2 == 0) + background.Alpha = 0; foreach (Mod mod in score.Mods) modsContainer.Add(new ModIcon(mod) { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Scale = new Vector2(0.3f), }); @@ -206,55 +200,18 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void load(OsuColour colours) { hoveredBackground.Colour = colours.Gray4; + background.Colour = colours.Gray3; } protected override bool OnHover(HoverEvent e) { hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); - rank.FadeColour(Color4.White, fade_duration, Easing.OutQuint); - scoreText.FadeColour(Color4.White, fade_duration, Easing.OutQuint); - accuracy.FadeColour(Color4.White, fade_duration, Easing.OutQuint); - username.FadeColour(Color4.White, fade_duration, Easing.OutQuint); - maxCombo.FadeColour(Color4.White, fade_duration, Easing.OutQuint); - pp.FadeColour(Color4.White, fade_duration, Easing.OutQuint); - - if (score.Statistics[HitResult.Great] != 0) - hitGreat.FadeColour(Color4.White, fade_duration, Easing.OutQuint); - - if (score.Statistics[HitResult.Good] != 0) - hitGood.FadeColour(Color4.White, fade_duration, Easing.OutQuint); - - if (score.Statistics[HitResult.Meh] != 0) - hitMeh.FadeColour(Color4.White, fade_duration, Easing.OutQuint); - - if (score.Statistics[HitResult.Miss] != 0) - hitMiss.FadeColour(Color4.White, fade_duration, Easing.OutQuint); - return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); - rank.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); - scoreText.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); - username.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); - accuracy.FadeColour((score.Accuracy == 1) ? Color4.Green : Color4.Black, fade_duration, Easing.OutQuint); - maxCombo.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); - pp.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); - - if (score.Statistics[HitResult.Great] != 0) - hitGreat.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); - - if (score.Statistics[HitResult.Good] != 0) - hitGood.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); - - if (score.Statistics[HitResult.Meh] != 0) - hitMeh.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); - - if (score.Statistics[HitResult.Miss] != 0) - hitMiss.FadeColour(Color4.Black, fade_duration, Easing.OutQuint); - base.OnHoverLost(e); } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs new file mode 100644 index 0000000000..90947364e4 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.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.Game.Online.API.Requests.Responses; +using System.Collections.Generic; + +namespace osu.Game.Overlays.BeatmapSet.Scores +{ + public class ScoreTable : FillFlowContainer + { + private IEnumerable scores; + public IEnumerable Scores + { + set + { + scores = value; + + int maxModsAmount = 0; + foreach (var s in scores) + { + var scoreModsAmount = s.Mods.Length; + if (scoreModsAmount > maxModsAmount) + maxModsAmount = scoreModsAmount; + } + + Add(new ScoreTextLine(maxModsAmount)); + + + int index = 0; + foreach (var s in scores) + Add(new DrawableScore(index++, s, maxModsAmount)); + } + get + { + return scores; + } + } + + public ScoreTable() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Direction = FillDirection.Vertical; + } + + public void ClearScores() + { + scores = null; + foreach (var s in this) + { + if (s is DrawableScore) + Remove(s); + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs index 53a477b908..43255683c4 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs @@ -23,9 +23,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public const float HIT_MEH_POSITION = 0.7f; public const float HIT_MISS_POSITION = 0.75f; public const float PP_POSITION = 0.8f; - public const float MODS_POSITION = 0.9f; - public ScoreTextLine() + public ScoreTextLine(int maxModsAmount) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -91,11 +90,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }, new ScoreText { - Anchor = Anchor.CentreLeft, - Origin = Anchor.Centre, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreLeft, Text = "mods".ToUpper(), - X = MODS_POSITION, - RelativePositionAxes = Axes.X, + X = -30 * maxModsAmount, }, }; } @@ -106,12 +104,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { TextSize = text_size; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Colour = colours.ContextMenuGray; - } } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 5211f1398f..8f3414c292 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -20,7 +20,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private const int spacing = 15; private const int fade_duration = 200; - private readonly FillFlowContainer flow; + private readonly ScoreTable scoreTable; + private readonly DrawableTopScore topScore; private readonly LoadingAnimation loadingAnimation; @@ -76,22 +77,19 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (scoreCount == 0) { topScore.Hide(); - flow.Clear(); + scoreTable.ClearScores(); return; } topScore.Score = scores.FirstOrDefault(); topScore.Show(); - flow.Clear(); + scoreTable.ClearScores(); if (scoreCount < 2) return; - flow.Add(new ScoreTextLine()); - - for (int i = 0; i < scoreCount; i++) - flow.Add(new DrawableScore(i, scores.ElementAt(i))); + scoreTable.Scores = scores; } public ScoresContainer() @@ -113,13 +111,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Children = new Drawable[] { topScore = new DrawableTopScore(), - flow = new FillFlowContainer + scoreTable = new ScoreTable { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 1), - }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + } } }, loadingAnimation = new LoadingAnimation From 13c154a0b37f2c4c89f66d697dab122ec9a754d4 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Fri, 8 Feb 2019 20:07:21 +0300 Subject: [PATCH 0357/5608] Fix background colour and a bug with removing scores --- osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 7 ++----- .../Overlays/BeatmapSet/Scores/ScoresContainer.cs | 12 +++++++++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 90947364e4..7de13b7204 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; using System.Collections.Generic; +using System.Linq; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -48,11 +49,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public void ClearScores() { scores = null; - foreach (var s in this) - { - if (s is DrawableScore) - Remove(s); - } + Clear(); } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 8f3414c292..2a9e76874e 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -4,12 +4,15 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osuTK; +using osuTK.Graphics; using System.Collections.Generic; using System.Linq; @@ -20,6 +23,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private const int spacing = 15; private const int fade_duration = 200; + private readonly Box background; private readonly ScoreTable scoreTable; private readonly DrawableTopScore topScore; @@ -98,6 +102,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores AutoSizeAxes = Axes.Y; Children = new Drawable[] { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, new FillFlowContainer { Anchor = Anchor.TopCentre, @@ -127,9 +135,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } [BackgroundDependencyLoader] - private void load(APIAccess api) + private void load(APIAccess api, OsuColour colours) { this.api = api; + + background.Colour = colours.Gray2; updateDisplay(); } From bd1f4f954955bf426225e67d9db270c275135483 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Fri, 8 Feb 2019 20:35:07 +0300 Subject: [PATCH 0358/5608] Small design fixes --- .../BeatmapSet/Scores/DrawableScore.cs | 2 +- .../BeatmapSet/Scores/DrawableTopScore.cs | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index 1076fe6449..cb9d89dc2c 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -176,7 +176,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (index == 0) scoreText.Font = @"Exo2.0-Bold"; - accuracy.Colour = (score.Accuracy == 1) ? Color4.LightGreen : Color4.White; + accuracy.Colour = (score.Accuracy == 1) ? Color4.GreenYellow : Color4.White; hitGreat.Colour = (score.Statistics[HitResult.Great] == 0) ? Color4.Gray : Color4.White; hitGood.Colour = (score.Statistics[HitResult.Good] == 0) ? Color4.Gray : Color4.White; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 487194c819..903e86423b 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -169,7 +169,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - TextSize = 10, + TextSize = 15, + Font = @"Exo2.0-Bold", }, flag = new DrawableFlag { @@ -327,9 +328,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private class DrawableInfoColumn : FillFlowContainer { - private readonly SpriteText headerText; private const float header_text_size = 12; + private readonly SpriteText headerText; + private readonly Box line; + public DrawableInfoColumn(string header) { AutoSizeAxes = Axes.Y; @@ -351,15 +354,20 @@ namespace osu.Game.Overlays.BeatmapSet.Scores new Container { RelativeSizeAxes = Axes.X, - Height = 3, - Child = new Box + Height = 2, + Child = line = new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4.LightGray, } } }; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + line.Colour = colours.Gray5; + } } private class ModsInfoColumn : DrawableInfoColumn From 107e0a5239be8e629d4c0a5498fd49ff03e082be Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Fri, 8 Feb 2019 20:43:11 +0300 Subject: [PATCH 0359/5608] Warning fixes --- .../BeatmapSet/Scores/DrawableScore.cs | 31 +++++++------------ .../BeatmapSet/Scores/DrawableTopScore.cs | 7 ++--- .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 2 -- .../BeatmapSet/Scores/ScoreTextLine.cs | 2 -- .../BeatmapSet/Scores/ScoresContainer.cs | 1 - 5 files changed, 14 insertions(+), 29 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index cb9d89dc2c..d37bbe5db0 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -27,25 +27,16 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly Box hoveredBackground; private readonly Box background; - private readonly SpriteText rank; - private readonly SpriteText scoreText; - private readonly SpriteText accuracy; - private readonly SpriteText maxCombo; - private readonly SpriteText hitGreat; - private readonly SpriteText hitGood; - private readonly SpriteText hitMeh; - private readonly SpriteText hitMiss; - private readonly SpriteText pp; - - private readonly ClickableScoreUsername username; - - private readonly APIScoreInfo score; - public DrawableScore(int index, APIScoreInfo score, int maxModsAmount) { - FillFlowContainer modsContainer; + SpriteText accuracy; + SpriteText scoreText; + SpriteText hitGreat; + SpriteText hitGood; + SpriteText hitMeh; + SpriteText hitMiss; - this.score = score; + FillFlowContainer modsContainer; RelativeSizeAxes = Axes.X; Height = 25; @@ -62,7 +53,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativeSizeAxes = Axes.Both, Alpha = 0, }, - rank = new SpriteText + new SpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreRight, @@ -102,14 +93,14 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Size = new Vector2(20, 13), X = 230, }, - username = new ClickableScoreUsername + new ClickableScoreUsername { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, User = score.User, X = ScoreTextLine.PLAYER_POSITION, }, - maxCombo = new SpriteText + new SpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -154,7 +145,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores X = ScoreTextLine.HIT_MISS_POSITION, TextSize = text_size, }, - pp = new SpriteText + new SpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 903e86423b..d2421ec606 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -330,10 +330,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { private const float header_text_size = 12; - private readonly SpriteText headerText; private readonly Box line; - public DrawableInfoColumn(string header) + protected DrawableInfoColumn(string header) { AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; @@ -344,7 +343,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { AutoSizeAxes = Axes.X, Height = header_text_size, - Child = headerText = new SpriteText + Child = new SpriteText { TextSize = 12, Text = header.ToUpper(), @@ -415,7 +414,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores get { return valueText.Text; } } - public TextInfoColumn(string header, float valueTextSize = 25) : base(header) + protected TextInfoColumn(string header, float valueTextSize = 25) : base(header) { Add(valueText = new SpriteText { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 7de13b7204..1b20b2c382 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; using System.Collections.Generic; -using System.Linq; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -28,7 +27,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Add(new ScoreTextLine(maxModsAmount)); - int index = 0; foreach (var s in scores) Add(new DrawableScore(index++, s, maxModsAmount)); diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs index 43255683c4..04934185a1 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; namespace osu.Game.Overlays.BeatmapSet.Scores { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 2a9e76874e..2783b0483b 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -12,7 +12,6 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osuTK; -using osuTK.Graphics; using System.Collections.Generic; using System.Linq; From 105053e91b01bfb86a8af60b82fa25b2a7acb344 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Sat, 9 Feb 2019 00:56:41 +0300 Subject: [PATCH 0360/5608] TestCase fix --- osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs | 8 ++++++-- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 5 ++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs index 321a38d087..bcc1774729 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs @@ -17,10 +17,11 @@ using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Osu; using osu.Game.Scoring; +using NUnit.Framework; namespace osu.Game.Tests.Visual { - [System.ComponentModel.Description("in BeatmapOverlay")] + [Description("in BeatmapOverlay")] public class TestCaseBeatmapScoresContainer : OsuTestCase { private readonly IEnumerable scores; @@ -160,11 +161,12 @@ namespace osu.Game.Tests.Visual Accuracy = 0.6543, }, }; - foreach(var s in scores) + foreach (var s in 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)); } anotherScores = new[] @@ -277,6 +279,7 @@ namespace osu.Game.Tests.Visual 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)); } topScoreInfo = new APIScoreInfo @@ -304,6 +307,7 @@ namespace osu.Game.Tests.Visual topScoreInfo.Statistics.Add(HitResult.Great, RNG.Next(2000)); topScoreInfo.Statistics.Add(HitResult.Good, RNG.Next(2000)); topScoreInfo.Statistics.Add(HitResult.Meh, RNG.Next(2000)); + topScoreInfo.Statistics.Add(HitResult.Miss, RNG.Next(2000)); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 2783b0483b..180f4a949c 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -73,6 +73,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void updateDisplay() { + scoreTable.ClearScores(); + loading = false; var scoreCount = scores?.Count() ?? 0; @@ -80,15 +82,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (scoreCount == 0) { topScore.Hide(); - scoreTable.ClearScores(); return; } topScore.Score = scores.FirstOrDefault(); topScore.Show(); - scoreTable.ClearScores(); - if (scoreCount < 2) return; From 04e57d7d3dcd2dc7423a6ef077437abafcfeb7e9 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Sat, 9 Feb 2019 06:23:58 +0300 Subject: [PATCH 0361/5608] Refactor to make things more flexible --- .../BeatmapSet/Scores/DrawableScore.cs | 242 ++++++++---------- .../BeatmapSet/Scores/DrawableTopScore.cs | 2 +- .../BeatmapSet/Scores/ScoreTableLine.cs | 183 +++++++++++++ .../BeatmapSet/Scores/ScoreTextLine.cs | 146 ++++------- 4 files changed, 341 insertions(+), 232 deletions(-) create mode 100644 osu.Game/Overlays/BeatmapSet/Scores/ScoreTableLine.cs diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index d37bbe5db0..8741fd8dfe 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -22,24 +22,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public class DrawableScore : Container { private const int fade_duration = 100; - private const float text_size = 14; + private const int text_size = 14; private readonly Box hoveredBackground; private readonly Box background; public DrawableScore(int index, APIScoreInfo score, int maxModsAmount) { - SpriteText accuracy; - SpriteText scoreText; - SpriteText hitGreat; - SpriteText hitGood; - SpriteText hitMeh; - SpriteText hitMiss; - - FillFlowContainer modsContainer; - RelativeSizeAxes = Axes.X; - Height = 25; + AutoSizeAxes = Axes.Y; CornerRadius = 3; Masking = true; Children = new Drawable[] @@ -53,138 +44,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativeSizeAxes = Axes.Both, Alpha = 0, }, - new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreRight, - Text = $"#{index + 1}", - TextSize = text_size, - X = ScoreTextLine.RANK_POSITION, - Font = @"Exo2.0-Bold", - }, - new DrawableRank(score.Rank) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(30, 20), - FillMode = FillMode.Fit, - X = 45 - }, - scoreText = new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = $@"{score.TotalScore:N0}", - X = ScoreTextLine.SCORE_POSITION, - TextSize = text_size, - }, - accuracy = new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = $@"{score.Accuracy:P2}", - X = ScoreTextLine.ACCURACY_POSITION, - TextSize = text_size, - }, - new DrawableFlag(score.User.Country) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(20, 13), - X = 230, - }, - new ClickableScoreUsername - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - User = score.User, - X = ScoreTextLine.PLAYER_POSITION, - }, - new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = $@"{score.MaxCombo:N0}x", - RelativePositionAxes = Axes.X, - X = ScoreTextLine.MAX_COMBO_POSITION, - TextSize = text_size, - }, - hitGreat = new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = $"{score.Statistics[HitResult.Great]}", - RelativePositionAxes = Axes.X, - X = ScoreTextLine.HIT_GREAT_POSITION, - TextSize = text_size, - }, - hitGood = new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = $"{score.Statistics[HitResult.Good]}", - RelativePositionAxes = Axes.X, - X = ScoreTextLine.HIT_GOOD_POSITION, - TextSize = text_size, - }, - hitMeh = new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = $"{score.Statistics[HitResult.Meh]}", - RelativePositionAxes = Axes.X, - X = ScoreTextLine.HIT_MEH_POSITION, - TextSize = text_size, - }, - hitMiss = new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = $"{score.Statistics[HitResult.Miss]}", - RelativePositionAxes = Axes.X, - X = ScoreTextLine.HIT_MISS_POSITION, - TextSize = text_size, - }, - new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = $@"{score.PP:N0}", - RelativePositionAxes = Axes.X, - X = ScoreTextLine.PP_POSITION, - TextSize = text_size, - }, - modsContainer = new FillFlowContainer - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreLeft, - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - X = -30 * maxModsAmount, - }, + new DrawableScoreData(index, score, maxModsAmount), }; - if (index == 0) - scoreText.Font = @"Exo2.0-Bold"; - - accuracy.Colour = (score.Accuracy == 1) ? Color4.GreenYellow : Color4.White; - - hitGreat.Colour = (score.Statistics[HitResult.Great] == 0) ? Color4.Gray : Color4.White; - hitGood.Colour = (score.Statistics[HitResult.Good] == 0) ? Color4.Gray : Color4.White; - hitMeh.Colour = (score.Statistics[HitResult.Meh] == 0) ? Color4.Gray : Color4.White; - hitMiss.Colour = (score.Statistics[HitResult.Miss] == 0) ? Color4.Gray : Color4.White; - - if (index % 2 == 0) + if (index % 2 != 0) background.Alpha = 0; - - foreach (Mod mod in score.Mods) - modsContainer.Add(new ModIcon(mod) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Scale = new Vector2(0.3f), - }); } [BackgroundDependencyLoader] @@ -251,5 +115,103 @@ namespace osu.Game.Overlays.BeatmapSet.Scores base.OnHoverLost(e); } } + + private class DrawableScoreData : ScoreTableLine + { + public DrawableScoreData(int index, APIScoreInfo score, int maxModsAmount) : base(maxModsAmount) + { + SpriteText scoreText; + SpriteText accuracy; + SpriteText hitGreat; + SpriteText hitGood; + SpriteText hitMeh; + SpriteText hitMiss; + + FillFlowContainer modsContainer; + + RankContainer.Add(new SpriteText + { + Text = $"#{index + 1}", + Font = @"Exo2.0-Bold", + TextSize = text_size, + }); + DrawableRankContainer.Add(new DrawableRank(score.Rank) + { + Size = new Vector2(30, 20), + FillMode = FillMode.Fit, + }); + ScoreContainer.Add(scoreText = new SpriteText + { + Text = $@"{score.TotalScore:N0}", + TextSize = text_size, + }); + AccuracyContainer.Add(accuracy = new SpriteText + { + Text = $@"{score.Accuracy:P2}", + TextSize = text_size, + }); + FlagContainer.Add(new DrawableFlag(score.User.Country) + { + Size = new Vector2(20, 13), + }); + PlayerContainer.Add(new ClickableScoreUsername + { + User = score.User, + }); + MaxComboContainer.Add(new SpriteText + { + Text = $@"{score.MaxCombo:N0}x", + TextSize = text_size, + }); + HitGreatContainer.Add(hitGreat = new SpriteText + { + Text = $"{score.Statistics[HitResult.Great]}", + TextSize = text_size, + }); + HitGoodContainer.Add(hitGood = new SpriteText + { + Text = $"{score.Statistics[HitResult.Good]}", + TextSize = text_size, + }); + HitMehContainer.Add(hitMeh = new SpriteText + { + Text = $"{score.Statistics[HitResult.Meh]}", + TextSize = text_size, + }); + HitMissContainer.Add(hitMiss = new SpriteText + { + Text = $"{score.Statistics[HitResult.Miss]}", + TextSize = text_size, + }); + PPContainer.Add(new SpriteText + { + Text = $@"{score.PP:N0}", + TextSize = text_size, + }); + ModsContainer.Add(modsContainer = new FillFlowContainer + { + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + }); + + if (index == 0) + scoreText.Font = @"Exo2.0-Bold"; + + accuracy.Colour = (score.Accuracy == 1) ? Color4.GreenYellow : Color4.White; + hitGreat.Colour = (score.Statistics[HitResult.Great] == 0) ? Color4.Gray : Color4.White; + hitGood.Colour = (score.Statistics[HitResult.Good] == 0) ? Color4.Gray : Color4.White; + hitMeh.Colour = (score.Statistics[HitResult.Meh] == 0) ? Color4.Gray : Color4.White; + hitMiss.Colour = (score.Statistics[HitResult.Miss] == 0) ? Color4.Gray : Color4.White; + + foreach (Mod mod in score.Mods) + modsContainer.Add(new ModIcon(mod) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Scale = new Vector2(0.3f), + }); + } + } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index d2421ec606..7623153710 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -188,7 +188,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.CentreRight, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Width = 0.7f, + Width = 0.65f, Child = new FillFlowContainer { AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableLine.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableLine.cs new file mode 100644 index 0000000000..d57225b541 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableLine.cs @@ -0,0 +1,183 @@ +// 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; + +namespace osu.Game.Overlays.BeatmapSet.Scores +{ + public class ScoreTableLine : GridContainer + { + private const float rank_position = 30; + private const float drawable_rank_position = 45; + private const float score_position = 90; + private const float accuracy_position = 170; + private const float flag_position = 220; + private const float player_position = 250; + + private const float max_combo_position = 0.1f; + private const float hit_great_position = 0.3f; + private const float hit_good_position = 0.45f; + private const float hit_meh_position = 0.6f; + private const float hit_miss_position = 0.75f; + private const float pp_position = 0.9f; + + protected readonly Container RankContainer; + protected readonly Container DrawableRankContainer; + protected readonly Container ScoreContainer; + protected readonly Container AccuracyContainer; + protected readonly Container FlagContainer; + protected readonly Container PlayerContainer; + protected readonly Container MaxComboContainer; + protected readonly Container HitGreatContainer; + protected readonly Container HitGoodContainer; + protected readonly Container HitMehContainer; + protected readonly Container HitMissContainer; + protected readonly Container PPContainer; + protected readonly Container ModsContainer; + + public ScoreTableLine(int maxModsAmount) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + RowDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, 25), + }; + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, 300), + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + }; + Content = new[] + { + new Drawable[] + { + new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + RankContainer = new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + X = rank_position, + }, + DrawableRankContainer = new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + X = drawable_rank_position, + }, + ScoreContainer = new Container + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + X = score_position, + }, + AccuracyContainer = new Container + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + X = accuracy_position, + }, + FlagContainer = new Container + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + X = flag_position, + }, + PlayerContainer = new Container + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + X = player_position, + } + } + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + MaxComboContainer = new Container + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + RelativePositionAxes = Axes.X, + X = max_combo_position, + }, + HitGreatContainer = new Container + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + RelativePositionAxes = Axes.X, + X = hit_great_position, + }, + HitGoodContainer = new Container + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + RelativePositionAxes = Axes.X, + X = hit_good_position, + }, + HitMehContainer = new Container + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + RelativePositionAxes = Axes.X, + X = hit_meh_position, + }, + HitMissContainer = new Container + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + RelativePositionAxes = Axes.X, + X = hit_miss_position, + }, + PPContainer = new Container + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + RelativePositionAxes = Axes.X, + X = pp_position, + } + } + }, + new Container + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Child = ModsContainer = new Container + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + X = -30 * maxModsAmount, + } + } + } + }; + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs index 04934185a1..b7c9742764 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs @@ -1,107 +1,71 @@ // 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.Sprites; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class ScoreTextLine : Container + public class ScoreTextLine : ScoreTableLine { private const float text_size = 12; - public const float RANK_POSITION = 30; - public const float SCORE_POSITION = 90; - public const float ACCURACY_POSITION = 170; - public const float PLAYER_POSITION = 270; - public const float MAX_COMBO_POSITION = 0.5f; - public const float HIT_GREAT_POSITION = 0.6f; - public const float HIT_GOOD_POSITION = 0.65f; - public const float HIT_MEH_POSITION = 0.7f; - public const float HIT_MISS_POSITION = 0.75f; - public const float PP_POSITION = 0.8f; - - public ScoreTextLine(int maxModsAmount) + public ScoreTextLine(int maxModsAmount) : base(maxModsAmount) { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Children = new Drawable[] + RankContainer.Add(new SpriteText { - new ScoreText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreRight, - Text = "rank".ToUpper(), - X = RANK_POSITION, - }, - new ScoreText - { - Text = "score".ToUpper(), - X = SCORE_POSITION, - }, - new ScoreText - { - Text = "accuracy".ToUpper(), - X = ACCURACY_POSITION, - }, - new ScoreText - { - Text = "player".ToUpper(), - X = PLAYER_POSITION, - }, - new ScoreText - { - Text = "max combo".ToUpper(), - X = MAX_COMBO_POSITION, - RelativePositionAxes = Axes.X, - }, - new ScoreText - { - Text = "300", - RelativePositionAxes = Axes.X, - X = HIT_GREAT_POSITION, - }, - new ScoreText - { - Text = "100".ToUpper(), - RelativePositionAxes = Axes.X, - X = HIT_GOOD_POSITION, - }, - new ScoreText - { - Text = "50".ToUpper(), - RelativePositionAxes = Axes.X, - X = HIT_MEH_POSITION, - }, - new ScoreText - { - Text = "miss".ToUpper(), - RelativePositionAxes = Axes.X, - X = HIT_MISS_POSITION, - }, - new ScoreText - { - Text = "pp".ToUpper(), - RelativePositionAxes = Axes.X, - X = PP_POSITION, - }, - new ScoreText - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreLeft, - Text = "mods".ToUpper(), - X = -30 * maxModsAmount, - }, - }; - } - - private class ScoreText : SpriteText - { - public ScoreText() + Text = @"rank".ToUpper(), + TextSize = text_size, + }); + ScoreContainer.Add(new SpriteText { - TextSize = text_size; - } + Text = @"score".ToUpper(), + TextSize = text_size, + }); + AccuracyContainer.Add(new SpriteText + { + Text = @"accuracy".ToUpper(), + TextSize = text_size, + }); + PlayerContainer.Add(new SpriteText + { + Text = @"player".ToUpper(), + TextSize = text_size, + }); + MaxComboContainer.Add(new SpriteText + { + Text = @"max combo".ToUpper(), + TextSize = text_size, + }); + HitGreatContainer.Add(new SpriteText + { + Text = "300".ToUpper(), + TextSize = text_size, + }); + HitGoodContainer.Add(new SpriteText + { + Text = "100".ToUpper(), + TextSize = text_size, + }); + HitMehContainer.Add(new SpriteText + { + Text = "50".ToUpper(), + TextSize = text_size, + }); + HitMissContainer.Add(new SpriteText + { + Text = @"miss".ToUpper(), + TextSize = text_size, + }); + PPContainer.Add(new SpriteText + { + Text = @"pp".ToUpper(), + TextSize = text_size, + }); + ModsContainer.Add(new SpriteText + { + Text = @"mods".ToUpper(), + TextSize = text_size, + }); } } } From 4d489da03280c51ca1ff2b88f9d00d4dcdf2e715 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Sun, 10 Feb 2019 04:16:56 +0300 Subject: [PATCH 0362/5608] small visual improvements --- .../BeatmapSet/Scores/DrawableTopScore.cs | 12 ++--- .../BeatmapSet/Scores/ScoreTableLine.cs | 2 +- .../BeatmapSet/Scores/ScoreTextLine.cs | 48 +++++++++---------- 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 7623153710..e4486b1514 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -200,8 +200,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { new FillFlowContainer { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(margin, 0), @@ -210,15 +210,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores hitGreat = new SmallInfoColumn("300", 20), hitGood = new SmallInfoColumn("100", 20), hitMeh = new SmallInfoColumn("50", 20), - hitMiss = new SmallInfoColumn("miss", 20), + hitMiss = new SmallInfoColumn("misses", 20), pp = new SmallInfoColumn("pp", 20), modsInfo = new ModsInfoColumn("mods"), } }, new FillFlowContainer { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(margin, 0), @@ -347,7 +347,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { TextSize = 12, Text = header.ToUpper(), - Font = @"Exo2.0-Bold", + Font = @"Exo2.0-Black", } }, new Container diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableLine.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableLine.cs index d57225b541..5c4723eae1 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableLine.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableLine.cs @@ -173,7 +173,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Anchor = Anchor.CentreRight, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, - X = -30 * maxModsAmount, + X = -30 * ((maxModsAmount == 0) ? 1 : maxModsAmount), } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs index b7c9742764..9fd12df3a8 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs @@ -7,65 +7,63 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { public class ScoreTextLine : ScoreTableLine { - private const float text_size = 12; - public ScoreTextLine(int maxModsAmount) : base(maxModsAmount) { - RankContainer.Add(new SpriteText + RankContainer.Add(new ScoreText { Text = @"rank".ToUpper(), - TextSize = text_size, }); - ScoreContainer.Add(new SpriteText + ScoreContainer.Add(new ScoreText { Text = @"score".ToUpper(), - TextSize = text_size, }); - AccuracyContainer.Add(new SpriteText + AccuracyContainer.Add(new ScoreText { Text = @"accuracy".ToUpper(), - TextSize = text_size, }); - PlayerContainer.Add(new SpriteText + PlayerContainer.Add(new ScoreText { Text = @"player".ToUpper(), - TextSize = text_size, }); - MaxComboContainer.Add(new SpriteText + MaxComboContainer.Add(new ScoreText { Text = @"max combo".ToUpper(), - TextSize = text_size, }); - HitGreatContainer.Add(new SpriteText + HitGreatContainer.Add(new ScoreText { Text = "300".ToUpper(), - TextSize = text_size, }); - HitGoodContainer.Add(new SpriteText + HitGoodContainer.Add(new ScoreText { Text = "100".ToUpper(), - TextSize = text_size, }); - HitMehContainer.Add(new SpriteText + HitMehContainer.Add(new ScoreText { Text = "50".ToUpper(), - TextSize = text_size, }); - HitMissContainer.Add(new SpriteText + HitMissContainer.Add(new ScoreText { - Text = @"miss".ToUpper(), - TextSize = text_size, + Text = @"misses".ToUpper(), }); - PPContainer.Add(new SpriteText + PPContainer.Add(new ScoreText { Text = @"pp".ToUpper(), - TextSize = text_size, }); - ModsContainer.Add(new SpriteText + ModsContainer.Add(new ScoreText { Text = @"mods".ToUpper(), - TextSize = text_size, }); } + + private class ScoreText : SpriteText + { + private const float text_size = 12; + + public ScoreText() + { + TextSize = text_size; + Font = @"Exo2.0-Black"; + } + } } } From fcab21908bd02a73effc030849e9df6f75ad8dbe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 17 Feb 2019 18:20:03 +0900 Subject: [PATCH 0363/5608] Update in line with screen changes --- osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs | 9 +-------- osu.Game.Tournament/Screens/TournamentScreen.cs | 9 +++++++-- osu.Game.Tournament/TournamentGame.cs | 3 ++- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 66e539af25..f68adabb4c 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -13,11 +13,9 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Logging; using osu.Framework.Platform; -using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osu.Game.Screens; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Drawings.Components; using osuTK; @@ -25,14 +23,10 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Drawings { - public class DrawingsScreen : OsuScreen + public class DrawingsScreen : CompositeDrawable { private const string results_filename = "drawings_results.txt"; - public override bool HideOverlaysOnEnter => true; - - protected override BackgroundScreen CreateBackground() => null; - private ScrollingTeamContainer teamsContainer; private GroupContainer groupsContainer; private OsuSpriteText fullTeamNameText; @@ -59,7 +53,6 @@ namespace osu.Game.Tournament.Screens.Drawings if (!TeamList.Teams.Any()) { - this.Exit(); return; } diff --git a/osu.Game.Tournament/Screens/TournamentScreen.cs b/osu.Game.Tournament/Screens/TournamentScreen.cs index b440b8e796..e830509db9 100644 --- a/osu.Game.Tournament/Screens/TournamentScreen.cs +++ b/osu.Game.Tournament/Screens/TournamentScreen.cs @@ -3,15 +3,20 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Game.Screens; +using osu.Framework.Graphics.Containers; namespace osu.Game.Tournament.Screens { - public class TournamentScreen : OsuScreen + public class TournamentScreen : CompositeDrawable { [Resolved] protected LadderInfo LadderInfo { get; private set; } + public TournamentScreen() + { + RelativeSizeAxes = Axes.Both; + } + public override void Hide() { this.FadeOut(200); diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index f970700fc5..711ecc5ae9 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; +using osu.Framework.Screens; using osu.Game.Graphics.Cursor; using osu.Game.Tournament.Screens; @@ -16,7 +17,7 @@ namespace osu.Game.Tournament Add(new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - Child = new TournamentSceneManager() + Child = new ScreenStack(new TournamentSceneManager()) { RelativeSizeAxes = Axes.Both } }); MenuCursorContainer.Cursor.Alpha = 0; From 6ea1ed8d04addf7e04044fa6de531f773dd455bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 17 Feb 2019 19:48:54 +0900 Subject: [PATCH 0364/5608] Fix unnecessary texture atlas generation --- .../Components/TournamentBeatmapPanel.cs | 2 +- .../Screens/Gameplay/Components/MatchHeader.cs | 3 +-- .../Screens/Gameplay/GameplayScreen.cs | 3 +-- .../Ladder/Components/DrawableMatchPairing.cs | 13 +++++++++++-- .../Screens/Showcase/ShowcaseScreen.cs | 3 +-- .../Screens/TeamIntro/TeamIntroScreen.cs | 3 +-- .../Screens/TeamWin/TeamWinScreen.cs | 3 +-- 7 files changed, 17 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index ae2e2b5160..748f9fbdce 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -140,7 +140,7 @@ namespace osu.Game.Tournament.Components if (!string.IsNullOrEmpty(mods)) AddInternal(new Sprite { - Texture = new TextureStore(new TextureLoaderStore(new StorageBackedResourceStore(storage))).Get($"mods/{mods}"), + Texture = new LargeTextureStore(new TextureLoaderStore(new StorageBackedResourceStore(storage))).Get($"mods/{mods}"), Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Margin = new MarginPadding(20), diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index 210b42a4c8..25f7be1739 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -6,7 +6,6 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Textures; using osu.Framework.Input.Events; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -22,7 +21,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components public class MatchHeader : Container { [BackgroundDependencyLoader] - private void load(LadderInfo ladder, TextureStore textures) + private void load(LadderInfo ladder) { RelativeSizeAxes = Axes.X; Height = 95; diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 277d2aad6d..ad0ef0f521 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -6,7 +6,6 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Textures; using osu.Framework.Threading; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; @@ -37,7 +36,7 @@ namespace osu.Game.Tournament.Screens.Gameplay private TournamentSceneManager sceneManager { get; set; } [BackgroundDependencyLoader] - private void load(LadderInfo ladder, TextureStore textures, MatchIPCInfo ipc, MatchChatDisplay chat) + private void load(LadderInfo ladder, MatchIPCInfo ipc, MatchChatDisplay chat) { this.chat = chat; this.ipc = ipc; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index db942c6e4c..58eab5bc0a 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -18,6 +18,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public class DrawableMatchPairing : CompositeDrawable { public readonly MatchPairing Pairing; + private readonly bool editor; protected readonly FillFlowContainer Flow; private readonly Drawable selectionBox; private readonly Drawable currentMatchSelectionBox; @@ -26,9 +27,14 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [Resolved(CanBeNull = true)] private LadderEditorInfo editorInfo { get; set; } - public DrawableMatchPairing(MatchPairing pairing) + [Resolved(CanBeNull = true)] + private LadderInfo ladderInfo { get; set; } + + + public DrawableMatchPairing(MatchPairing pairing, bool editor = false) { Pairing = pairing; + this.editor = editor; AutoSizeAxes = Axes.Both; @@ -109,7 +115,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components if (selected) { selectionBox.Show(); - editorInfo.Selected.Value = Pairing; + if (editor) + editorInfo.Selected.Value = Pairing; + else + ladderInfo.CurrentMatch.Value = Pairing; } else selectionBox.Hide(); diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs index 7690ff4b97..65369fa6da 100644 --- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -2,14 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; -using osu.Framework.Graphics.Textures; namespace osu.Game.Tournament.Screens.Showcase { public class ShowcaseScreen : BeatmapInfoScreen { [BackgroundDependencyLoader] - private void load(TextureStore textures) + private void load() { AddInternal(new TournamentLogo()); } diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 55af305045..dc79d4aab0 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Video; using osu.Framework.Platform; using osu.Game.Graphics; @@ -25,7 +24,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro private readonly Bindable currentMatch = new Bindable(); [BackgroundDependencyLoader] - private void load(TextureStore textures, LadderInfo ladder, Storage storage) + private void load(LadderInfo ladder, Storage storage) { RelativeSizeAxes = Axes.Both; diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs index fbb622e16f..2e2c8e5020 100644 --- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Video; using osu.Framework.Platform; using osu.Game.Graphics; @@ -29,7 +28,7 @@ namespace osu.Game.Tournament.Screens.TeamWin private VideoSprite redWinVideo; [BackgroundDependencyLoader] - private void load(TextureStore textures, LadderInfo ladder, Storage storage) + private void load(LadderInfo ladder, Storage storage) { RelativeSizeAxes = Axes.Both; From ef321b41035e38dbfba2087c830f2b7d9ef97ded Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 17 Feb 2019 19:48:58 +0900 Subject: [PATCH 0365/5608] Fix regressed test --- osu.Game.Tournament.Tests/TestCaseDrawings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament.Tests/TestCaseDrawings.cs b/osu.Game.Tournament.Tests/TestCaseDrawings.cs index d957c792f7..f5f5615bf6 100644 --- a/osu.Game.Tournament.Tests/TestCaseDrawings.cs +++ b/osu.Game.Tournament.Tests/TestCaseDrawings.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tournament.Tests { public TestCaseDrawings() { - LoadScreen(new DrawingsScreen + Add(new DrawingsScreen { TeamList = new TestTeamList(), }); From e7668a749bce0cbcbf8b49c3f8f720f0b1847a5d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 17 Feb 2019 19:49:10 +0900 Subject: [PATCH 0366/5608] Bind to correct target (hacky) --- osu.Game.Tournament/Screens/Ladder/LadderScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 549f12f769..36baaf0b39 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -64,7 +64,7 @@ namespace osu.Game.Tournament.Screens.Ladder protected virtual void AddPairing(MatchPairing pairing) { - PairingsContainer.Add(new DrawableMatchPairing(pairing)); + PairingsContainer.Add(new DrawableMatchPairing(pairing, this is LadderEditorScreen)); } private Cached layout = new Cached(); From 389632d9325dc078605e2dfefcec03b4def93fcd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 2 Mar 2019 13:40:43 +0900 Subject: [PATCH 0367/5608] Fix bindable changes --- osu.Game.Tournament/Components/DateTextBox.cs | 7 +++--- .../Components/MatchChatDisplay.cs | 8 +++---- .../Components/TournamentBeatmapPanel.cs | 6 ++--- osu.Game.Tournament/IPC/MatchIPCInfo.cs | 2 +- osu.Game.Tournament/LadderInfo.cs | 2 +- .../Screens/BeatmapInfoScreen.cs | 9 ++++---- .../Gameplay/Components/MatchHeader.cs | 14 ++++++------ .../Gameplay/Components/MatchScoreDisplay.cs | 2 +- .../Screens/Gameplay/GameplayScreen.cs | 20 ++++++++--------- .../Ladder/Components/DrawableMatchPairing.cs | 21 +++++++++--------- .../Ladder/Components/DrawableMatchTeam.cs | 16 +++++++------- .../Ladder/Components/LadderEditorInfo.cs | 2 +- .../Ladder/Components/LadderEditorSettings.cs | 22 +++++++++---------- .../Screens/Ladder/Components/MatchPairing.cs | 8 +++---- .../Ladder/Components/TournamentGrouping.cs | 2 +- .../Screens/Ladder/LadderScreen.cs | 6 ++--- .../Screens/MapPool/MapPoolScreen.cs | 14 ++++++------ .../Screens/Schedule/ScheduleScreen.cs | 10 ++++----- .../Screens/TeamIntro/TeamIntroScreen.cs | 12 +++++----- .../Screens/TeamWin/TeamWinScreen.cs | 6 ++--- osu.Game.Tournament/TournamentGameBase.cs | 1 + 21 files changed, 96 insertions(+), 94 deletions(-) diff --git a/osu.Game.Tournament/Components/DateTextBox.cs b/osu.Game.Tournament/Components/DateTextBox.cs index 171196f348..0a2485e4f3 100644 --- a/osu.Game.Tournament/Components/DateTextBox.cs +++ b/osu.Game.Tournament/Components/DateTextBox.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; @@ -12,13 +12,12 @@ namespace osu.Game.Tournament.Components { public new Bindable Bindable { - get { return bindable; } - + get => bindable; set { bindable = value; bindable.BindValueChanged(dto => - base.Bindable.Value = dto.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"), true); + base.Bindable.Value = dto.NewValue.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"), true); } } diff --git a/osu.Game.Tournament/Components/MatchChatDisplay.cs b/osu.Game.Tournament/Components/MatchChatDisplay.cs index f96db186ea..33c544f83d 100644 --- a/osu.Game.Tournament/Components/MatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/MatchChatDisplay.cs @@ -3,7 +3,7 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Online.Chat; using osu.Game.Overlays.Chat; using osu.Game.Tournament.IPC; @@ -25,12 +25,12 @@ namespace osu.Game.Tournament.Components if (ipc != null) { chatChannel.BindTo(ipc.ChatChannel); - chatChannel.BindValueChanged(channelString => + chatChannel.BindValueChanged(c => { - if (string.IsNullOrWhiteSpace(channelString)) + if (string.IsNullOrWhiteSpace(c.NewValue)) return; - int id = int.Parse(channelString); + int id = int.Parse(c.NewValue); if (id <= 0) return; diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 748f9fbdce..94aa86d5cb 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -6,7 +6,7 @@ using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -148,9 +148,9 @@ namespace osu.Game.Tournament.Components }); } - private void matchChanged(MatchPairing match) + private void matchChanged(ValueChangedEvent pairing) { - match.PicksBans.CollectionChanged += picksBansOnCollectionChanged; + pairing.NewValue.PicksBans.CollectionChanged += picksBansOnCollectionChanged; updateState(); } diff --git a/osu.Game.Tournament/IPC/MatchIPCInfo.cs b/osu.Game.Tournament/IPC/MatchIPCInfo.cs index be31df8009..cd57756f60 100644 --- a/osu.Game.Tournament/IPC/MatchIPCInfo.cs +++ b/osu.Game.Tournament/IPC/MatchIPCInfo.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; diff --git a/osu.Game.Tournament/LadderInfo.cs b/osu.Game.Tournament/LadderInfo.cs index c433987491..83d0f76020 100644 --- a/osu.Game.Tournament/LadderInfo.cs +++ b/osu.Game.Tournament/LadderInfo.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; diff --git a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs index 0b37e2fab1..b0aadc7e9e 100644 --- a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs +++ b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; @@ -30,15 +31,15 @@ namespace osu.Game.Tournament.Screens ipc.Mods.BindValueChanged(modsChanged, true); } - private void modsChanged(LegacyMods mods) + private void modsChanged(ValueChangedEvent mods) { - SongBar.Mods = mods; + SongBar.Mods = mods.NewValue; } - private void beatmapChanged(BeatmapInfo beatmap) + private void beatmapChanged(ValueChangedEvent beatmap) { SongBar.FadeInFromZero(300, Easing.OutQuint); - SongBar.Beatmap = beatmap; + SongBar.Beatmap = beatmap.NewValue; } } } diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index 25f7be1739..364d437619 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -73,13 +73,13 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components currentMatch.BindTo(ladder.CurrentMatch); } - private void matchChanged(MatchPairing match) + private void matchChanged(ValueChangedEvent match) { currentTeamScore.UnbindBindings(); - currentTeamScore.BindTo(teamColour == TeamColour.Red ? match.Team1Score : match.Team2Score); + currentTeamScore.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1Score : match.NewValue.Team2Score); currentTeam.UnbindBindings(); - currentTeam.BindTo(teamColour == TeamColour.Red ? match.Team1 : match.Team2); + currentTeam.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1 : match.NewValue.Team2); // team may change to same team, which means score is not in a good state. // thus we handle this manually. @@ -144,7 +144,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components currentTeamScore.BindTo(score); } - private void scoreChanged(int? score) => counter.CountStars = score ?? 0; + private void scoreChanged(ValueChangedEvent score) => counter.CountStars = score.NewValue ?? 0; } private class TeamDisplay : DrawableTournamentTeam @@ -204,7 +204,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components currentMatch.BindTo(ladder.CurrentMatch); } - private void matchChanged(MatchPairing match) + private void matchChanged(ValueChangedEvent match) { InternalChildren = new Drawable[] { @@ -218,7 +218,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components Anchor = Anchor.Centre, Origin = Anchor.Centre, Colour = Color4.White, - Text = match.Grouping.Value?.Name.Value ?? "Unknown Grouping", + Text = match.NewValue.Grouping.Value?.Name.Value ?? "Unknown Grouping", Font = "Aquatico-Regular", TextSize = 18, }, diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs index b4eb9ef239..30cd2b2e85 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index ad0ef0f521..eb33c2fbdb 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -120,10 +120,10 @@ namespace osu.Game.Tournament.Screens.Gameplay State.BindTo(ipc.State); State.BindValueChanged(stateChanged, true); - currentMatch.BindValueChanged(m => warmup.Value = m.Team1Score + m.Team2Score == 0); + currentMatch.BindValueChanged(m => warmup.Value = m.NewValue.Team1Score.Value + m.NewValue.Team2Score.Value == 0); currentMatch.BindTo(ladder.CurrentMatch); - warmup.BindValueChanged(w => warmupButton.Alpha = !w ? 0.5f : 1, true); + warmup.BindValueChanged(w => warmupButton.Alpha = !w.NewValue ? 0.5f : 1, true); } private ScheduledDelegate scheduledOperation; @@ -132,15 +132,15 @@ namespace osu.Game.Tournament.Screens.Gameplay private TourneyState lastState; - private void stateChanged(TourneyState state) + private void stateChanged(ValueChangedEvent state) { try { - if (state == TourneyState.Ranking) + if (state.NewValue == TourneyState.Ranking) { if (warmup.Value) return; - if (ipc.Score1 > ipc.Score2) + if (ipc.Score1.Value > ipc.Score2.Value) currentMatch.Value.Team1Score.Value++; else currentMatch.Value.Team2Score.Value++; @@ -167,16 +167,16 @@ namespace osu.Game.Tournament.Screens.Gameplay chat.Contract(); } - switch (state) + switch (state.NewValue) { case TourneyState.Idle: contract(); if (lastState == TourneyState.Ranking && !warmup.Value) { - if (currentMatch.Value?.Completed == true) + if (currentMatch.Value?.Completed.Value == true) scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(TeamWinScreen)); }, 4000); - else if (currentMatch.Value?.Completed == false) + else if (currentMatch.Value?.Completed.Value == false) scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(MapPoolScreen)); }, 4000); } @@ -192,7 +192,7 @@ namespace osu.Game.Tournament.Screens.Gameplay } finally { - lastState = state; + lastState = state.NewValue; } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 58eab5bc0a..d993fbda20 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -87,7 +87,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components pairing.Position.BindValueChanged(pos => { if (IsDragged) return; - Position = new Vector2(pos.X, pos.Y); + + Position = new Vector2(pos.NewValue.X, pos.NewValue.Y); }, true); updateTeams(); @@ -127,7 +128,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private void updateProgression() { - if (!Pairing.Completed) + if (!Pairing.Completed.Value) { // ensure we clear any of our teams from our progression. // this is not pretty logic but should suffice for now. @@ -177,10 +178,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { if (Pairing.Grouping.Value == null) return; - var instaWinAmount = Pairing.Grouping.Value.BestOf / 2; + var instaWinAmount = Pairing.Grouping.Value.BestOf.Value / 2; - Pairing.Completed.Value = Pairing.Grouping.Value.BestOf > 0 - && (Pairing.Team1Score + Pairing.Team2Score >= Pairing.Grouping.Value.BestOf || Pairing.Team1Score > instaWinAmount || Pairing.Team2Score > instaWinAmount); + Pairing.Completed.Value = Pairing.Grouping.Value.BestOf.Value > 0 + && (Pairing.Team1Score.Value + Pairing.Team2Score.Value >= Pairing.Grouping.Value.BestOf.Value || Pairing.Team1Score.Value > instaWinAmount || Pairing.Team2Score.Value > instaWinAmount); } protected override void LoadComplete() @@ -193,7 +194,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components globalSelection = editorInfo.Selected.GetBoundCopy(); globalSelection.BindValueChanged(s => { - if (s != Pairing) Selected = false; + if (s.NewValue != Pairing) Selected = false; }); } } @@ -216,14 +217,14 @@ namespace osu.Game.Tournament.Screens.Ladder.Components var team2Match = conditional.Acronyms.Contains(Pairing.Team2Acronym); if (team1Match && team2Match) - Pairing.Date.Value = conditional.Date; + Pairing.Date.Value = conditional.Date.Value; } } Flow.Children = new[] { - new DrawableMatchTeam(Pairing.Team1, Pairing, Pairing.Losers), - new DrawableMatchTeam(Pairing.Team2, Pairing, Pairing.Losers) + new DrawableMatchTeam(Pairing.Team1.Value, Pairing, Pairing.Losers.Value), + new DrawableMatchTeam(Pairing.Team2.Value, Pairing, Pairing.Losers.Value) }; SchedulerAfterChildren.Add(() => Scheduler.Add(updateProgression)); diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 461283ffed..63d15781ca 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -52,7 +52,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [Resolved(CanBeNull = true)] private LadderEditorInfo editorInfo { get; set; } - public DrawableMatchTeam(Bindable team, MatchPairing pairing, bool losers) + public DrawableMatchTeam(TournamentTeam team, MatchPairing pairing, bool losers) : base(team) { this.pairing = pairing; @@ -74,8 +74,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components isWinner = () => pairing.Winner == Team; completed.BindTo(pairing.Completed); - if (team.Value != null) - score.BindTo(team.Value == pairing.Team1.Value ? pairing.Team1Score : pairing.Team2Score); + if (team != null) + score.BindTo(team == pairing.Team1.Value ? pairing.Team1Score : pairing.Team2Score); } } @@ -133,7 +133,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components score.BindValueChanged(val => { - scoreText.Text = val?.ToString() ?? string.Empty; + scoreText.Text = val.NewValue?.ToString() ?? string.Empty; updateWinStyle(); }, true); } @@ -155,7 +155,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { pairing.StartMatch(); } - else if (!pairing.Completed) + else if (!pairing.Completed.Value) score.Value++; } else @@ -164,7 +164,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components // don't allow changing scores if the match has a progression. can cause large data loss return false; - if (pairing.Completed && pairing.Winner != Team) + if (pairing.Completed.Value && pairing.Winner != Team) // don't allow changing scores from the non-winner return false; @@ -179,7 +179,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private void updateWinStyle() { - bool winner = completed && isWinner?.Invoke() == true; + bool winner = completed.Value && isWinner?.Invoke() == true; background.FadeColour(winner ? colourWinner : colourNormal, winner ? 500 : 0, Easing.OutQuint); diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs index 1fd9455195..6979aae295 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Tournament.Screens.Ladder.Components { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index bb80a845e3..f0559e0266 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -4,7 +4,7 @@ using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -93,11 +93,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components editorInfo.Selected.ValueChanged += selection => { - textboxTeam1.Text = selection?.Team1.Value?.Acronym; - textboxTeam2.Text = selection?.Team2.Value?.Acronym; - groupingDropdown.Bindable.Value = selection?.Grouping.Value ?? groupingOptions.First(); - losersCheckbox.Current.Value = selection?.Losers.Value ?? false; - dateTimeBox.Bindable.Value = selection?.Date.Value ?? DateTimeOffset.UtcNow; + textboxTeam1.Text = selection.NewValue?.Team1.Value?.Acronym; + textboxTeam2.Text = selection.NewValue?.Team2.Value?.Acronym; + groupingDropdown.Bindable.Value = selection.NewValue?.Grouping.Value ?? groupingOptions.First(); + losersCheckbox.Current.Value = selection.NewValue?.Losers.Value ?? false; + dateTimeBox.Bindable.Value = selection.NewValue?.Date.Value ?? DateTimeOffset.UtcNow; }; textboxTeam1.OnCommit = (val, newText) => @@ -116,10 +116,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { if (editorInfo.Selected.Value != null) { - editorInfo.Selected.Value.Grouping.Value = grouping; - if (editorInfo.Selected.Value.Date.Value < grouping.StartDate.Value) + editorInfo.Selected.Value.Grouping.Value = grouping.NewValue; + if (editorInfo.Selected.Value.Date.Value < grouping.NewValue.StartDate.Value) { - editorInfo.Selected.Value.Date.Value = grouping.StartDate.Value; + editorInfo.Selected.Value.Date.Value = grouping.NewValue.StartDate.Value; editorInfo.Selected.TriggerChange(); } } @@ -128,13 +128,13 @@ namespace osu.Game.Tournament.Screens.Ladder.Components losersCheckbox.Current.ValueChanged += losers => { if (editorInfo.Selected.Value != null) - editorInfo.Selected.Value.Losers.Value = losers; + editorInfo.Selected.Value.Losers.Value = losers.NewValue; }; dateTimeBox.Bindable.ValueChanged += date => { if (editorInfo.Selected.Value != null) - editorInfo.Selected.Value.Date.Value = date; + editorInfo.Selected.Value.Date.Value = date.NewValue; }; } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index 7d6acc5bd2..760f6d42f4 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using Newtonsoft.Json; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Tournament.Components; using SixLabors.Primitives; @@ -71,8 +71,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public MatchPairing() { - Team1.BindValueChanged(t => Team1Acronym = t?.Acronym, true); - Team2.BindValueChanged(t => Team2Acronym = t?.Acronym, true); + Team1.BindValueChanged(t => Team1Acronym = t.NewValue?.Acronym, true); + Team2.BindValueChanged(t => Team2Acronym = t.NewValue?.Acronym, true); } public MatchPairing(TournamentTeam team1 = null, TournamentTeam team2 = null) @@ -88,7 +88,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [JsonIgnore] public TournamentTeam Loser => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team2.Value : Team1.Value; - public int PointsToWin => Grouping.Value == null ? 0 : Grouping.Value.BestOf / 2 + 1; + public int PointsToWin => Grouping.Value?.BestOf.Value / 2 + 1 ?? 0; /// /// Remove scores from the match, in case of a false click or false start. diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs index 370f0ea643..3555e4db11 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; -using osu.Framework.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Tournament.Screens.Ladder.Components { diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 36baaf0b39..7c6aabbe53 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -98,13 +98,13 @@ namespace osu.Game.Tournament.Screens.Ladder // clean up outdated progressions. pairing.Pairing.Progression.Value = null; else - paths.Add(new ProgressionPath(pairing, dest) { Colour = pairing.Pairing.Losers ? losersPathColour : normalPathColour }); + paths.Add(new ProgressionPath(pairing, dest) { Colour = pairing.Pairing.Losers.Value ? losersPathColour : normalPathColour }); } } foreach (var group in LadderInfo.Groupings) { - var topPairing = PairingsContainer.Where(p => !p.Pairing.Losers && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); + var topPairing = PairingsContainer.Where(p => !p.Pairing.Losers.Value && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); if (topPairing == null) continue; @@ -118,7 +118,7 @@ namespace osu.Game.Tournament.Screens.Ladder foreach (var group in LadderInfo.Groupings) { - var topPairing = PairingsContainer.Where(p => p.Pairing.Losers && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); + var topPairing = PairingsContainer.Where(p => p.Pairing.Losers.Value && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); if (topPairing == null) continue; diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index bed2c35b76..41368eb96e 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -3,7 +3,7 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -102,13 +102,13 @@ namespace osu.Game.Tournament.Screens.MapPool ipc.Beatmap.BindValueChanged(beatmapChanged); } - private void beatmapChanged(BeatmapInfo beatmap) + private void beatmapChanged(ValueChangedEvent beatmap) { if (currentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) < 2) return; - if (beatmap.OnlineBeatmapID != null) - addForBeatmap(beatmap.OnlineBeatmapID.Value); + if (beatmap.NewValue.OnlineBeatmapID != null) + addForBeatmap(beatmap.NewValue.OnlineBeatmapID.Value); } private void setMode(TeamColour colour, ChoiceType choiceType) @@ -201,16 +201,16 @@ namespace osu.Game.Tournament.Screens.MapPool } } - private void matchChanged(MatchPairing match) + private void matchChanged(ValueChangedEvent match) { mapFlows.Clear(); - if (match.Grouping.Value != null) + if (match.NewValue.Grouping.Value != null) { FillFlowContainer currentFlow = null; string currentMod = null; - foreach (var b in match.Grouping.Value.Beatmaps) + foreach (var b in match.NewValue.Grouping.Value.Beatmaps) { if (currentFlow == null || currentMod != b.Mods) { diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index f3f3667db1..def2161ea0 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -4,7 +4,7 @@ using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -48,9 +48,9 @@ namespace osu.Game.Tournament.Screens.Schedule currentMatch.BindTo(ladder.CurrentMatch); } - private void matchChanged(MatchPairing pairing) + private void matchChanged(ValueChangedEvent pairing) { - if (pairing == null) + if (pairing.NewValue == null) { mainContainer.Clear(); return; @@ -113,10 +113,10 @@ namespace osu.Game.Tournament.Screens.Schedule Colour = Color4.Black, TextSize = 20 }, - new SchedulePairing(currentMatch, false), + new SchedulePairing(currentMatch.Value, false), new OsuSpriteText { - Text = "Start Time " + pairing.Date.Value.ToUniversalTime().ToString("HH:mm UTC"), + Text = "Start Time " + pairing.NewValue.Date.Value.ToUniversalTime().ToString("HH:mm UTC"), Colour = Color4.Black, TextSize = 20 }, diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index dc79d4aab0..a42c7775e6 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Video; @@ -46,9 +46,9 @@ namespace osu.Game.Tournament.Screens.TeamIntro currentMatch.BindTo(ladder.CurrentMatch); } - private void matchChanged(MatchPairing pairing) + private void matchChanged(ValueChangedEvent pairing) { - if (pairing == null) + if (pairing.NewValue == null) { mainContainer.Clear(); return; @@ -56,7 +56,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro mainContainer.Children = new Drawable[] { - new TeamWithPlayers(pairing.Team1, true) + new TeamWithPlayers(pairing.NewValue.Team1.Value, true) { RelativeSizeAxes = Axes.Both, Width = 0.5f, @@ -64,7 +64,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.Centre, Origin = Anchor.CentreRight }, - new TeamWithPlayers(pairing.Team2) + new TeamWithPlayers(pairing.NewValue.Team2.Value) { RelativeSizeAxes = Axes.Both, Width = 0.5f, @@ -72,7 +72,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.Centre, Origin = Anchor.CentreLeft }, - new RoundDisplay(pairing) + new RoundDisplay(pairing.NewValue) { RelativeSizeAxes = Axes.Both, Height = 0.25f, diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs index 2e2c8e5020..f0f46f2dc8 100644 --- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Video; @@ -62,10 +62,10 @@ namespace osu.Game.Tournament.Screens.TeamWin currentCompleted.BindValueChanged(_ => update()); } - private void matchChanged(MatchPairing pairing) + private void matchChanged(ValueChangedEvent pairing) { currentCompleted.UnbindBindings(); - currentCompleted.BindTo(pairing.Completed); + currentCompleted.BindTo(pairing.NewValue.Completed); update(); } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 5c9bee560e..bf6c02d064 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using Newtonsoft.Json; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; From f1832103622d5e7816c570b73f6ebf371aa9ffa2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 2 Mar 2019 13:50:43 +0900 Subject: [PATCH 0368/5608] Fix test bindables --- osu.Game.Tournament.Tests/TestCaseTeamIntro.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseTeamWin.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs b/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs index 004009f269..d8d5007238 100644 --- a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs +++ b/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs @@ -3,7 +3,7 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Tournament.Screens.Ladder.Components; using osu.Game.Tournament.Screens.TeamIntro; @@ -21,7 +21,7 @@ namespace osu.Game.Tournament.Tests var pairing = new MatchPairing(); pairing.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == "USA"); pairing.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == "JPN"); - pairing.Grouping.Value = Ladder.Groupings.FirstOrDefault(g => g.Name == "Finals"); + pairing.Grouping.Value = Ladder.Groupings.FirstOrDefault(g => g.Name.Value == "Finals"); currentMatch.Value = pairing; Add(new TeamIntroScreen diff --git a/osu.Game.Tournament.Tests/TestCaseTeamWin.cs b/osu.Game.Tournament.Tests/TestCaseTeamWin.cs index 48ae9acb91..fb798d3587 100644 --- a/osu.Game.Tournament.Tests/TestCaseTeamWin.cs +++ b/osu.Game.Tournament.Tests/TestCaseTeamWin.cs @@ -3,7 +3,7 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Tournament.Screens.Ladder.Components; using osu.Game.Tournament.Screens.TeamWin; @@ -21,7 +21,7 @@ namespace osu.Game.Tournament.Tests var pairing = new MatchPairing(); pairing.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == "USA"); pairing.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == "JPN"); - pairing.Grouping.Value = Ladder.Groupings.FirstOrDefault(g => g.Name == "Finals"); + pairing.Grouping.Value = Ladder.Groupings.FirstOrDefault(g => g.Name.Value == "Finals"); currentMatch.Value = pairing; Add(new TeamWinScreen From 4c66ebb501187edc9b6a5cc2ebe8927f4a3e600e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 2 Mar 2019 13:52:56 +0900 Subject: [PATCH 0369/5608] Fix formatting issues --- osu.Game.Tournament/Components/TournamentTeam.cs | 8 ++++---- osu.Game.Tournament/IPC/FileBasedIPC.cs | 1 - osu.Game.Tournament/Screens/Drawings/Components/Group.cs | 3 ++- .../Screens/Ladder/Components/DrawableMatchPairing.cs | 1 + osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs | 9 +++++---- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentTeam.cs b/osu.Game.Tournament/Components/TournamentTeam.cs index 62dc703fee..73c24282c4 100644 --- a/osu.Game.Tournament/Components/TournamentTeam.cs +++ b/osu.Game.Tournament/Components/TournamentTeam.cs @@ -23,8 +23,8 @@ namespace osu.Game.Tournament.Components /// public string FlagName { - get { return flagName ?? Acronym?.Substring(0, 2); } - set { flagName = value; } + get => flagName ?? Acronym?.Substring(0, 2); + set => flagName = value; } private string acronym; @@ -34,8 +34,8 @@ namespace osu.Game.Tournament.Components /// public string Acronym { - get { return acronym ?? FullName?.Substring(0, 3); } - set { acronym = value; } + get => acronym ?? FullName?.Substring(0, 3); + set => acronym = value; } [JsonProperty] diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 7f8ed0cb3d..da66460acb 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -129,7 +129,6 @@ namespace osu.Game.Tournament.IPC { protected override string LocateBasePath() { - bool checkExists(string p) { return File.Exists(Path.Combine(p, "ipc.txt")); diff --git a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs index a701731d1e..ca092cdf02 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs @@ -121,7 +121,8 @@ namespace osu.Game.Tournament.Screens.Drawings.Components { private readonly FillFlowContainer innerContainer; - public GroupTeam(TournamentTeam team) : base(team) + public GroupTeam(TournamentTeam team) + : base(team) { Width = 36; AutoSizeAxes = Axes.Y; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index d993fbda20..9d3af60427 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -111,6 +111,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components set { if (value == selected) return; + selected = value; if (selected) diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index def2161ea0..05343117bf 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -57,8 +57,9 @@ namespace osu.Game.Tournament.Screens.Schedule } var upcoming = ladder.Pairings.Where(p => !p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4); - var conditionals = ladder.Pairings.Where(p => !p.Completed.Value && (p.Team1.Value == null || p.Team2.Value == null) && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4) - .SelectMany(m => m.ConditionalPairings.Where(cp => m.Acronyms.TrueForAll(a => cp.Acronyms.Contains(a)))); + var conditionals = ladder + .Pairings.Where(p => !p.Completed.Value && (p.Team1.Value == null || p.Team2.Value == null) && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4) + .SelectMany(m => m.ConditionalPairings.Where(cp => m.Acronyms.TrueForAll(a => cp.Acronyms.Contains(a)))); upcoming = upcoming.Concat(conditionals); upcoming = upcoming.OrderBy(p => p.Date.Value).Take(12); @@ -145,7 +146,7 @@ namespace osu.Game.Tournament.Screens.Schedule Anchor = Anchor.TopRight, Origin = Anchor.TopLeft, Colour = Color4.Black, - Alpha = conditional ? 0.6f : 1, + Alpha = conditional ? 0.6f : 1, Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, }); AddInternal(new OsuSpriteText @@ -153,7 +154,7 @@ namespace osu.Game.Tournament.Screens.Schedule Anchor = Anchor.BottomRight, Origin = Anchor.BottomLeft, Colour = Color4.Black, - Alpha = conditional ? 0.6f : 1, + Alpha = conditional ? 0.6f : 1, Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, Text = pairing.Date.Value.ToUniversalTime().ToString("HH:mm UTC") + (conditional ? " (conditional)" : "") }); From 73d266fe1041f7c56571f241a558de29ade43b53 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 2 Mar 2019 16:32:11 +0900 Subject: [PATCH 0370/5608] Fix win screen being incorrectly displayed after switching matches --- .../Screens/Gameplay/GameplayScreen.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index eb33c2fbdb..2b6d16505a 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -120,7 +120,12 @@ namespace osu.Game.Tournament.Screens.Gameplay State.BindTo(ipc.State); State.BindValueChanged(stateChanged, true); - currentMatch.BindValueChanged(m => warmup.Value = m.NewValue.Team1Score.Value + m.NewValue.Team2Score.Value == 0); + currentMatch.BindValueChanged(m => + { + warmup.Value = m.NewValue.Team1Score.Value + m.NewValue.Team2Score.Value == 0; + scheduledOperation?.Cancel(); + }); + currentMatch.BindTo(ladder.CurrentMatch); warmup.BindValueChanged(w => warmupButton.Alpha = !w.NewValue ? 0.5f : 1, true); @@ -172,12 +177,16 @@ namespace osu.Game.Tournament.Screens.Gameplay case TourneyState.Idle: contract(); + const float delay_before_progression = 4000; + + // if we've returned to idle and the last screen was ranking + // we should automatically proceed after a short delay if (lastState == TourneyState.Ranking && !warmup.Value) { if (currentMatch.Value?.Completed.Value == true) - scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(TeamWinScreen)); }, 4000); + scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(TeamWinScreen)); }, delay_before_progression); else if (currentMatch.Value?.Completed.Value == false) - scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(MapPoolScreen)); }, 4000); + scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(MapPoolScreen)); }, delay_before_progression); } break; From 132ce541f3eca72d9a119aca7b4dbd64f0e895f5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 4 Mar 2019 12:06:41 +0900 Subject: [PATCH 0371/5608] Fix obsolete font usages --- .../Components/ControlPanel.cs | 4 ++-- osu.Game.Tournament/Components/SongBar.cs | 5 ++--- .../Components/TournamentBeatmapPanel.cs | 12 ++++------- .../Screens/Drawings/Components/Group.cs | 7 +++---- .../Screens/Drawings/DrawingsScreen.cs | 3 +-- .../Gameplay/Components/MatchHeader.cs | 7 +++---- .../Gameplay/Components/MatchScoreDisplay.cs | 20 +++++-------------- .../Ladder/Components/DrawableMatchTeam.cs | 4 ++-- .../Screens/Schedule/ScheduleScreen.cs | 6 +++--- .../Screens/TeamIntro/TeamIntroScreen.cs | 16 ++++++--------- .../Screens/TeamWin/TeamWinScreen.cs | 14 +++++-------- osu.Game/Graphics/OsuFont.cs | 3 +++ 12 files changed, 39 insertions(+), 62 deletions(-) diff --git a/osu.Game.Tournament/Components/ControlPanel.cs b/osu.Game.Tournament/Components/ControlPanel.cs index 5f777fbf43..dee6cfbe0e 100644 --- a/osu.Game.Tournament/Components/ControlPanel.cs +++ b/osu.Game.Tournament/Components/ControlPanel.cs @@ -4,6 +4,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; @@ -40,8 +41,7 @@ namespace osu.Game.Tournament.Components Origin = Anchor.TopCentre, Text = "Control Panel", - TextSize = 22f, - Font = "Exo2.0-Bold" + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22) }, buttons = new FillFlowContainer { diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index fc75bd59a4..a138dfaa1e 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -163,7 +163,7 @@ namespace osu.Game.Tournament.Components string hardRockExtra = ""; string srExtra = ""; - var ar = beatmap.BaseDifficulty.ApproachRate; + //var ar = beatmap.BaseDifficulty.ApproachRate; if ((mods & LegacyMods.HardRock) > 0) { hardRockExtra = "*"; @@ -225,8 +225,7 @@ namespace osu.Game.Tournament.Components void cp(SpriteText s, Color4 colour) { s.Colour = colour; - s.TextSize = 15; - s.Font = @"Exo2.0-Bold"; + s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15); } bool first = true; diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 94aa86d5cb..6b80094990 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -100,29 +100,25 @@ namespace osu.Game.Tournament.Components new OsuSpriteText { Text = "mapper", - Font = @"Exo2.0-RegularItalic", Padding = new MarginPadding { Right = 5 }, - TextSize = 14 + Font = OsuFont.GetFont(italics: true, weight: FontWeight.Regular, size: 14) }, new OsuSpriteText { Text = Beatmap.Metadata.AuthorString, - Font = @"Exo2.0-BoldItalic", Padding = new MarginPadding { Right = 20 }, - TextSize = 14 + Font = OsuFont.GetFont(italics: true, weight: FontWeight.Bold, size: 14) }, new OsuSpriteText { Text = "difficulty", - Font = @"Exo2.0-RegularItalic", Padding = new MarginPadding { Right = 5 }, - TextSize = 14 + Font = OsuFont.GetFont(italics: true, weight: FontWeight.Regular, size: 14) }, new OsuSpriteText { Text = Beatmap.Version, - Font = @"Exo2.0-BoldItalic", - TextSize = 14 + Font = OsuFont.GetFont(italics: true, weight: FontWeight.Bold, size: 14) }, } } diff --git a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs index ca092cdf02..36ab7482a0 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs @@ -7,6 +7,7 @@ using System.Text; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Tournament.Components; using osuTK; @@ -49,8 +50,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components Position = new Vector2(0, 7f), Text = $"GROUP {name.ToUpperInvariant()}", - TextSize = 8f, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 8), Colour = new Color4(255, 204, 34, 255), }, teams = new FillFlowContainer @@ -134,8 +134,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components AcronymText.Anchor = Anchor.TopCentre; AcronymText.Origin = Anchor.TopCentre; AcronymText.Text = team.Acronym.ToUpperInvariant(); - AcronymText.TextSize = 10f; - AcronymText.Font = @"Exo2.0-Bold"; + AcronymText.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 10); InternalChildren = new Drawable[] { diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index f68adabb4c..c30caa5a00 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -120,8 +120,7 @@ namespace osu.Game.Tournament.Screens.Drawings Alpha = 0, - Font = "Exo2.0-Light", - TextSize = 42f + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 42), } } }, diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index 364d437619..5bbdbe104f 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; @@ -174,9 +175,8 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components Text = team?.FullName.ToUpper() ?? "???", X = (flip ? -1 : 1) * 90, Y = -10, - TextSize = 20, Colour = colour, - Font = "Aquatico-Regular", + Font = OsuFont.GetFont(typeface: Typeface.Aquatico, weight: FontWeight.Regular, size: 20), Origin = anchor, Anchor = anchor, }, @@ -219,8 +219,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components Origin = Anchor.Centre, Colour = Color4.White, Text = match.NewValue.Grouping.Value?.Name.Value ?? "Unknown Grouping", - Font = "Aquatico-Regular", - TextSize = 18, + Font = OsuFont.GetFont(typeface: Typeface.Aquatico, weight: FontWeight.Regular, size: 18), }, }; } diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs index 30cd2b2e85..a648072d04 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs @@ -7,6 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Screens.Ladder.Components; @@ -119,26 +120,15 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components public MatchScoreCounter() { Margin = new MarginPadding { Top = bar_height + 5, Horizontal = 10 }; - Winning = false; - DisplayedCountSpriteText.FixedWidth = false; + Winning = false; } public bool Winning { - set - { - if (value) - { - DisplayedCountSpriteText.Font = "Aquatico-Regular"; - DisplayedCountSpriteText.TextSize = 60; - } - else - { - DisplayedCountSpriteText.Font = "Aquatico-Light"; - DisplayedCountSpriteText.TextSize = 40; - } - } + set => DisplayedCountSpriteText.Font = value + ? OsuFont.GetFont(typeface: Typeface.Aquatico, weight: FontWeight.Regular, size: 60) + : OsuFont.GetFont(typeface: Typeface.Aquatico, weight: FontWeight.Light, size: 40); } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 63d15781ca..c4097848d7 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -67,7 +67,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components AcronymText.Anchor = AcronymText.Origin = Anchor.CentreLeft; AcronymText.Padding = new MarginPadding { Left = 50 }; - AcronymText.TextSize = 24; + AcronymText.Font = OsuFont.GetFont(size: 24); if (pairing != null) { @@ -121,7 +121,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { Anchor = Anchor.Centre, Origin = Anchor.Centre, - TextSize = 20, + Font = OsuFont.GetFont(size: 20), } } } diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index 05343117bf..384f2f7ab2 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -112,14 +112,14 @@ namespace osu.Game.Tournament.Screens.Schedule Spacing = new Vector2(10, 0), Text = currentMatch.Value.Grouping.Value.Name.Value, Colour = Color4.Black, - TextSize = 20 + Font = OsuFont.GetFont(size: 20) }, new SchedulePairing(currentMatch.Value, false), new OsuSpriteText { Text = "Start Time " + pairing.NewValue.Date.Value.ToUniversalTime().ToString("HH:mm UTC"), Colour = Color4.Black, - TextSize = 20 + Font = OsuFont.GetFont(size: 20) }, } } @@ -179,7 +179,7 @@ namespace osu.Game.Tournament.Screens.Schedule Text = title, Colour = Color4.Black, Spacing = new Vector2(10, 0), - TextSize = 30 + Font = OsuFont.GetFont(size: 30) }, content = new FillFlowContainer { diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index a42c7775e6..94130cb383 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -104,10 +104,9 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Colour = col, - Font = "Exo2.0-Black", Text = "COMING UP NEXT", Spacing = new Vector2(2, 0), - TextSize = 15, + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Black) }, new OsuSpriteText { @@ -115,9 +114,8 @@ namespace osu.Game.Tournament.Screens.TeamIntro Origin = Anchor.TopCentre, Colour = col, Text = pairing.Grouping.Value?.Name.Value ?? "Unknown Grouping", - Font = "Exo2.0-Light", Spacing = new Vector2(10, 0), - TextSize = 50, + Font = OsuFont.GetFont(size: 50, weight: FontWeight.Light) }, new OsuSpriteText { @@ -125,7 +123,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Origin = Anchor.TopCentre, Colour = col, Text = pairing.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"), - TextSize = 20, + Font = OsuFont.GetFont(size: 20) }, } } @@ -170,7 +168,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro players.Add(new OsuSpriteText { Text = p.Username, - TextSize = 24, + Font = OsuFont.GetFont(size: 24), Colour = colour, Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft, Origin = left ? Anchor.CentreRight : Anchor.CentreLeft, @@ -202,17 +200,15 @@ namespace osu.Game.Tournament.Screens.TeamIntro new OsuSpriteText { Text = team?.FullName.ToUpper() ?? "???", - TextSize = 40, + Font = OsuFont.GetFont(Typeface.Aquatico, 40, FontWeight.Light), Colour = Color4.Black, - Font = "Aquatico-Light", Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, }, new OsuSpriteText { Text = teamName.ToUpper(), - TextSize = 20, - Font = "Aquatico-Regular", + Font = OsuFont.GetFont(Typeface.Aquatico, 20, FontWeight.Regular), Colour = colour, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs index f0f46f2dc8..1de9b6ae5c 100644 --- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -127,8 +127,7 @@ namespace osu.Game.Tournament.Screens.TeamWin Origin = Anchor.TopCentre, Colour = col, Text = "WINNER", - Font = "Aquatico-Regular", - TextSize = 15, + Font = OsuFont.GetFont(Typeface.Aquatico, 15, FontWeight.Regular), }, new OsuSpriteText { @@ -136,18 +135,16 @@ namespace osu.Game.Tournament.Screens.TeamWin Origin = Anchor.TopCentre, Colour = col, Text = pairing.Grouping.Value?.Name.Value ?? "Unknown Grouping", - Font = "Aquatico-Light", + Font = OsuFont.GetFont(Typeface.Aquatico, 50, FontWeight.Light), Spacing = new Vector2(10, 0), - TextSize = 50, }, new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Font = "Aquatico-Light", Colour = col, Text = pairing.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"), - TextSize = 20, + Font = OsuFont.GetFont(Typeface.Aquatico, 20, FontWeight.Light), }, } } @@ -207,16 +204,15 @@ namespace osu.Game.Tournament.Screens.TeamWin new OsuSpriteText { Text = team?.FullName.ToUpper() ?? "???", - TextSize = 40, + Font = OsuFont.GetFont(Typeface.Aquatico, 40, FontWeight.Light), Colour = Color4.Black, - Font = "Aquatico-Light", Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, }, new OsuSpriteText { Text = teamName.ToUpper(), - TextSize = 20, + Font = OsuFont.GetFont(size: 20), Colour = colour, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, diff --git a/osu.Game/Graphics/OsuFont.cs b/osu.Game/Graphics/OsuFont.cs index dc660fd159..22937333d7 100644 --- a/osu.Game/Graphics/OsuFont.cs +++ b/osu.Game/Graphics/OsuFont.cs @@ -46,6 +46,8 @@ namespace osu.Game.Graphics return "FontAwesome"; case Typeface.Venera: return "Venera"; + case Typeface.Aquatico: + return "Aquatico"; } return null; @@ -103,6 +105,7 @@ namespace osu.Game.Graphics Exo, FontAwesome, Venera, + Aquatico // tournament use only } public enum FontWeight From 5c8cbd43c8fab1e0d14e0cc85fb939bcd58dbace Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 4 Mar 2019 13:02:43 +0900 Subject: [PATCH 0372/5608] Enforce max consecutive blank lines --- osu.sln.DotSettings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 5363d6dddf..3c6a6dd2a9 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -230,6 +230,8 @@ True NEXT_LINE NEXT_LINE + 1 + 1 True NEVER NEVER From 5b81de7663cb0ebcbce195df7dd2177f147a9f7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 4 Mar 2019 13:04:07 +0900 Subject: [PATCH 0373/5608] Apply codefactor fixes --- osu.Game.Tournament/Components/SongBar.cs | 2 -- osu.Game.Tournament/Screens/Drawings/Components/Group.cs | 1 - osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs | 1 - .../Screens/Ladder/Components/DrawableMatchPairing.cs | 1 - 4 files changed, 5 deletions(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index a138dfaa1e..452565d7d8 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -80,7 +80,6 @@ namespace osu.Game.Tournament.Components } } - [BackgroundDependencyLoader] private void load() { @@ -247,4 +246,3 @@ namespace osu.Game.Tournament.Components } } } - diff --git a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs index 36ab7482a0..50e413afea 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs @@ -127,7 +127,6 @@ namespace osu.Game.Tournament.Screens.Drawings.Components Width = 36; AutoSizeAxes = Axes.Y; - Flag.Anchor = Anchor.TopCentre; Flag.Origin = Anchor.TopCentre; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index 5bbdbe104f..89168aa8bb 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -87,7 +87,6 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components teamChanged(currentTeam.Value); } - protected override bool OnMouseDown(MouseDownEvent e) { switch (e.Button) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 9d3af60427..0244403bff 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -30,7 +30,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [Resolved(CanBeNull = true)] private LadderInfo ladderInfo { get; set; } - public DrawableMatchPairing(MatchPairing pairing, bool editor = false) { Pairing = pairing; From 8bf49830d5e994eb1a6100779947da9da8b97802 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 4 Mar 2019 13:13:31 +0900 Subject: [PATCH 0374/5608] Simplify and extract complex method --- osu.Game.Tournament/TournamentGameBase.cs | 144 ++++++++++++++-------- 1 file changed, 93 insertions(+), 51 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index bf6c02d064..e3996bc572 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -27,7 +27,8 @@ namespace osu.Game.Tournament { private const string bracket_filename = "bracket.json"; - protected LadderInfo Ladder; + private LadderInfo ladder; + private Storage storage; private DependencyContainer dependencies; @@ -57,42 +58,61 @@ namespace osu.Game.Tournament windowSize = frameworkConfig.GetBindable(FrameworkSetting.WindowedSize); - string content = null; - if (storage.Exists(bracket_filename)) - using (Stream stream = storage.GetStream(bracket_filename, FileAccess.Read, FileMode.Open)) - using (var sr = new StreamReader(stream)) - { - content = sr.ReadToEnd(); - } + readBracket(); - Ladder = content != null ? JsonConvert.DeserializeObject(content) : new LadderInfo(); - - dependencies.Cache(Ladder); + ladder.CurrentMatch.Value = ladder.Pairings.FirstOrDefault(p => p.Current.Value); dependencies.CacheAs(ipc = new FileBasedIPC()); Add(ipc); + Add(new OsuButton + { + Text = "Save Changes", + Width = 140, + Height = 50, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Padding = new MarginPadding(10), + Action = SaveChanges, + }); + } + + private void readBracket() + { + if (storage.Exists(bracket_filename)) + { + using (Stream stream = storage.GetStream(bracket_filename, FileAccess.Read, FileMode.Open)) + using (var sr = new StreamReader(stream)) + ladder = JsonConvert.DeserializeObject(sr.ReadToEnd()); + } + else + { + ladder = new LadderInfo(); + } + + dependencies.Cache(ladder); + bool addedInfo = false; // assign teams - foreach (var pairing in Ladder.Pairings) + foreach (var pairing in ladder.Pairings) { - pairing.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == pairing.Team1Acronym); - pairing.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == pairing.Team2Acronym); + pairing.Team1.Value = ladder.Teams.FirstOrDefault(t => t.Acronym == pairing.Team1Acronym); + pairing.Team2.Value = ladder.Teams.FirstOrDefault(t => t.Acronym == pairing.Team2Acronym); foreach (var conditional in pairing.ConditionalPairings) { - conditional.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == conditional.Team1Acronym); - conditional.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym == conditional.Team2Acronym); + conditional.Team1.Value = ladder.Teams.FirstOrDefault(t => t.Acronym == conditional.Team1Acronym); + conditional.Team2.Value = ladder.Teams.FirstOrDefault(t => t.Acronym == conditional.Team2Acronym); conditional.Grouping.Value = pairing.Grouping.Value; } } // assign progressions - foreach (var pair in Ladder.Progressions) + foreach (var pair in ladder.Progressions) { - var src = Ladder.Pairings.FirstOrDefault(p => p.ID == pair.Item1); - var dest = Ladder.Pairings.FirstOrDefault(p => p.ID == pair.Item2); + var src = ladder.Pairings.FirstOrDefault(p => p.ID == pair.Item1); + var dest = ladder.Pairings.FirstOrDefault(p => p.ID == pair.Item2); if (src == null) throw new InvalidOperationException(); @@ -106,10 +126,10 @@ namespace osu.Game.Tournament } // link pairings to groupings - foreach (var group in Ladder.Groupings) + foreach (var group in ladder.Groupings) foreach (var id in group.Pairings) { - var found = Ladder.Pairings.FirstOrDefault(p => p.ID == id); + var found = ladder.Pairings.FirstOrDefault(p => p.ID == id); if (found != null) { found.Grouping.Value = group; @@ -118,10 +138,23 @@ namespace osu.Game.Tournament } } - Ladder.CurrentMatch.Value = Ladder.Pairings.FirstOrDefault(p => p.Current.Value); + addedInfo |= addPlayers(); + addedInfo |= addBeatmaps(); + addedInfo |= addCountries(); - // add full player info based on user IDs - foreach (var t in Ladder.Teams) + if (addedInfo) + SaveChanges(); + } + + /// + /// Add missing player info based on user IDs. + /// + /// + private bool addPlayers() + { + bool addedInfo = false; + + foreach (var t in ladder.Teams) foreach (var p in t.Players) if (string.IsNullOrEmpty(p.Username)) { @@ -132,8 +165,16 @@ namespace osu.Game.Tournament addedInfo = true; } - // add full beatmap info based on beatmap IDs - foreach (var g in Ladder.Groupings) + return addedInfo; + } + + /// + /// Add missing beatmap info based on beatmap IDs + /// + private bool addBeatmaps() + { + bool addedInfo = false; + foreach (var g in ladder.Groupings) foreach (var b in g.Beatmaps) if (b.BeatmapInfo == null) { @@ -144,36 +185,37 @@ namespace osu.Game.Tournament addedInfo = true; } + return addedInfo; + } + + /// + /// Add missing country info based on acronyms. + /// + private bool addCountries() + { + bool addedInfo = false; + List countries; using (Stream stream = Resources.GetStream("Resources/countries.json")) using (var sr = new StreamReader(stream)) countries = JsonConvert.DeserializeObject>(sr.ReadToEnd()); - foreach (var t in Ladder.Teams) - if (string.IsNullOrEmpty(t.FullName)) - { - var result = countries.FirstOrDefault(c => c.Acronym == t.Acronym); - if (result != null) - { - t.Acronym = result.Acronym; - t.FlagName = result.FlagName; - t.FullName = result.FullName; - } - } - - if (addedInfo) - SaveChanges(); - - Add(new OsuButton + foreach (var t in ladder.Teams) { - Text = "Save Changes", - Width = 140, - Height = 50, - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Padding = new MarginPadding(10), - Action = SaveChanges, - }); + if (!string.IsNullOrEmpty(t.FullName)) + continue; + + var result = countries.FirstOrDefault(c => c.Acronym == t.Acronym); + + if (result == null) continue; + + t.Acronym = result.Acronym; + t.FlagName = result.FlagName; + t.FullName = result.FullName; + addedInfo = true; + } + + return addedInfo; } protected override void LoadComplete() @@ -198,7 +240,7 @@ namespace osu.Game.Tournament using (var stream = storage.GetStream(bracket_filename, FileAccess.Write, FileMode.Create)) using (var sw = new StreamWriter(stream)) { - sw.Write(JsonConvert.SerializeObject(Ladder, + sw.Write(JsonConvert.SerializeObject(ladder, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, From cf63ee4948a812edf153274112cbf83100fa18ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 4 Mar 2019 13:24:19 +0900 Subject: [PATCH 0375/5608] Update licence headers --- osu.Game.Tournament.Tests/LadderTestCase.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseGameplay.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseGroupingsEditorScreen.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseLadderManager.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseMapPool.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseMatchPairings.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseMatchScoreDisplay.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseSceneManager.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseSchedule.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseShowcase.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseTeamIntro.cs | 4 ++-- osu.Game.Tournament.Tests/TestCaseTeamWin.cs | 4 ++-- osu.Game.Tournament.Tests/TournamentTestBrowser.cs | 4 ++-- osu.Game.Tournament.Tests/TournamentTestRunner.cs | 4 ++-- osu.Game.Tournament/Components/ControlPanel.cs | 4 ++-- osu.Game.Tournament/Components/DateTextBox.cs | 4 ++-- osu.Game.Tournament/Components/DrawableTournamentTeam.cs | 4 ++-- osu.Game.Tournament/Components/MatchChatDisplay.cs | 4 ++-- osu.Game.Tournament/Components/SongBar.cs | 4 ++-- osu.Game.Tournament/Components/TournamentBeatmapPanel.cs | 4 ++-- osu.Game.Tournament/Components/TournamentTeam.cs | 4 ++-- osu.Game.Tournament/IPC/FileBasedIPC.cs | 4 ++-- osu.Game.Tournament/IPC/MatchIPCInfo.cs | 4 ++-- osu.Game.Tournament/IPC/TourneyState.cs | 4 ++-- osu.Game.Tournament/LadderInfo.cs | 4 ++-- osu.Game.Tournament/Properties/AssemblyInfo.cs | 4 ++-- osu.Game.Tournament/Screens/BeatmapInfoScreen.cs | 4 ++-- osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs | 4 ++-- .../Screens/Gameplay/Components/MatchHeader.cs | 4 ++-- .../Screens/Gameplay/Components/MatchScoreDisplay.cs | 4 ++-- osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs | 4 ++-- .../Screens/Groupings/GroupingsEditorScreen.cs | 4 ++-- osu.Game.Tournament/Screens/IProvideVideo.cs | 4 ++-- .../Screens/Ladder/Components/BeatmapChoice.cs | 4 ++-- .../Screens/Ladder/Components/ConditionalMatchPairing.cs | 4 ++-- .../Screens/Ladder/Components/DrawableMatchPairing.cs | 4 ++-- .../Screens/Ladder/Components/DrawableMatchTeam.cs | 4 ++-- .../Screens/Ladder/Components/DrawableTournamentGrouping.cs | 4 ++-- .../Screens/Ladder/Components/GroupingBeatmap.cs | 4 ++-- .../Screens/Ladder/Components/LadderEditorInfo.cs | 4 ++-- .../Screens/Ladder/Components/LadderEditorSettings.cs | 4 ++-- osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs | 4 ++-- .../Screens/Ladder/Components/ProgressionPath.cs | 4 ++-- .../Screens/Ladder/Components/TournamentGrouping.cs | 4 ++-- .../Screens/Ladder/Components/TournamentProgression.cs | 4 ++-- osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs | 4 ++-- osu.Game.Tournament/Screens/Ladder/LadderScreen.cs | 4 ++-- osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs | 4 ++-- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 4 ++-- osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs | 4 ++-- osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs | 4 ++-- osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs | 4 ++-- osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs | 4 ++-- osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs | 4 ++-- osu.Game.Tournament/Screens/TournamentSceneManager.cs | 4 ++-- osu.Game.Tournament/Screens/TournamentScreen.cs | 4 ++-- osu.Game.Tournament/TournamentGame.cs | 4 ++-- osu.Game.Tournament/TournamentGameBase.cs | 4 ++-- 60 files changed, 120 insertions(+), 120 deletions(-) diff --git a/osu.Game.Tournament.Tests/LadderTestCase.cs b/osu.Game.Tournament.Tests/LadderTestCase.cs index acc96930ee..fc827150bd 100644 --- a/osu.Game.Tournament.Tests/LadderTestCase.cs +++ b/osu.Game.Tournament.Tests/LadderTestCase.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Game.Tests.Visual; diff --git a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs index de80d36067..8bcc34bd7a 100644 --- a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs +++ b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; diff --git a/osu.Game.Tournament.Tests/TestCaseGameplay.cs b/osu.Game.Tournament.Tests/TestCaseGameplay.cs index eefcd79661..8e435de5e6 100644 --- a/osu.Game.Tournament.Tests/TestCaseGameplay.cs +++ b/osu.Game.Tournament.Tests/TestCaseGameplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; diff --git a/osu.Game.Tournament.Tests/TestCaseGroupingsEditorScreen.cs b/osu.Game.Tournament.Tests/TestCaseGroupingsEditorScreen.cs index 4e82e27fd9..d3ef011535 100644 --- a/osu.Game.Tournament.Tests/TestCaseGroupingsEditorScreen.cs +++ b/osu.Game.Tournament.Tests/TestCaseGroupingsEditorScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Tournament.Screens.Groupings; diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs index 3001f46ed2..8704c3aec5 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseLadderManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament.Tests/TestCaseMapPool.cs b/osu.Game.Tournament.Tests/TestCaseMapPool.cs index d953dbc5d3..6d2f64e7a7 100644 --- a/osu.Game.Tournament.Tests/TestCaseMapPool.cs +++ b/osu.Game.Tournament.Tests/TestCaseMapPool.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; diff --git a/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs b/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs index d71e4b8006..0c3c189cf5 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs index b4a754e439..2dce0c6017 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; diff --git a/osu.Game.Tournament.Tests/TestCaseMatchScoreDisplay.cs b/osu.Game.Tournament.Tests/TestCaseMatchScoreDisplay.cs index 62c5ca786b..c7de5cf8ce 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchScoreDisplay.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchScoreDisplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs index a19c933d8b..97d2018e3d 100644 --- a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Platform; diff --git a/osu.Game.Tournament.Tests/TestCaseSchedule.cs b/osu.Game.Tournament.Tests/TestCaseSchedule.cs index a12586cb27..f9dc447077 100644 --- a/osu.Game.Tournament.Tests/TestCaseSchedule.cs +++ b/osu.Game.Tournament.Tests/TestCaseSchedule.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; diff --git a/osu.Game.Tournament.Tests/TestCaseShowcase.cs b/osu.Game.Tournament.Tests/TestCaseShowcase.cs index dcd4b6aec7..51877cdfb6 100644 --- a/osu.Game.Tournament.Tests/TestCaseShowcase.cs +++ b/osu.Game.Tournament.Tests/TestCaseShowcase.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; diff --git a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs b/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs index d8d5007238..78614518ce 100644 --- a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs +++ b/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament.Tests/TestCaseTeamWin.cs b/osu.Game.Tournament.Tests/TestCaseTeamWin.cs index fb798d3587..df24877f09 100644 --- a/osu.Game.Tournament.Tests/TestCaseTeamWin.cs +++ b/osu.Game.Tournament.Tests/TestCaseTeamWin.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament.Tests/TournamentTestBrowser.cs b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs index 429adb2c0d..6d4063ec4f 100644 --- a/osu.Game.Tournament.Tests/TournamentTestBrowser.cs +++ b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Testing; using osu.Game.Graphics; diff --git a/osu.Game.Tournament.Tests/TournamentTestRunner.cs b/osu.Game.Tournament.Tests/TournamentTestRunner.cs index 51c2c65cb4..1f63f7c545 100644 --- a/osu.Game.Tournament.Tests/TournamentTestRunner.cs +++ b/osu.Game.Tournament.Tests/TournamentTestRunner.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using osu.Framework; diff --git a/osu.Game.Tournament/Components/ControlPanel.cs b/osu.Game.Tournament/Components/ControlPanel.cs index dee6cfbe0e..0d228fb3b4 100644 --- a/osu.Game.Tournament/Components/ControlPanel.cs +++ b/osu.Game.Tournament/Components/ControlPanel.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; diff --git a/osu.Game.Tournament/Components/DateTextBox.cs b/osu.Game.Tournament/Components/DateTextBox.cs index 0a2485e4f3..f25c4b6e78 100644 --- a/osu.Game.Tournament/Components/DateTextBox.cs +++ b/osu.Game.Tournament/Components/DateTextBox.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using osu.Framework.Bindables; diff --git a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs index 016db57773..a0c0856e7f 100644 --- a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament/Components/MatchChatDisplay.cs b/osu.Game.Tournament/Components/MatchChatDisplay.cs index 33c544f83d..dd567ed290 100644 --- a/osu.Game.Tournament/Components/MatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/MatchChatDisplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 452565d7d8..4844074372 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 6b80094990..dd3ba1af47 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.ObjectModel; diff --git a/osu.Game.Tournament/Components/TournamentTeam.cs b/osu.Game.Tournament/Components/TournamentTeam.cs index 73c24282c4..167f77c229 100644 --- a/osu.Game.Tournament/Components/TournamentTeam.cs +++ b/osu.Game.Tournament/Components/TournamentTeam.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index da66460acb..8cdd06003f 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.IO; diff --git a/osu.Game.Tournament/IPC/MatchIPCInfo.cs b/osu.Game.Tournament/IPC/MatchIPCInfo.cs index cd57756f60..701258c6c7 100644 --- a/osu.Game.Tournament/IPC/MatchIPCInfo.cs +++ b/osu.Game.Tournament/IPC/MatchIPCInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament/IPC/TourneyState.cs b/osu.Game.Tournament/IPC/TourneyState.cs index afa5b400ba..ef1c612a53 100644 --- a/osu.Game.Tournament/IPC/TourneyState.cs +++ b/osu.Game.Tournament/IPC/TourneyState.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Tournament.IPC { diff --git a/osu.Game.Tournament/LadderInfo.cs b/osu.Game.Tournament/LadderInfo.cs index 83d0f76020..9ddca460e2 100644 --- a/osu.Game.Tournament/LadderInfo.cs +++ b/osu.Game.Tournament/LadderInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game.Tournament/Properties/AssemblyInfo.cs b/osu.Game.Tournament/Properties/AssemblyInfo.cs index 4955391097..70e42bcafb 100644 --- a/osu.Game.Tournament/Properties/AssemblyInfo.cs +++ b/osu.Game.Tournament/Properties/AssemblyInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Runtime.CompilerServices; diff --git a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs index b0aadc7e9e..fccd35ca9e 100644 --- a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs +++ b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index c30caa5a00..d902defe94 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index 89168aa8bb..dd12581046 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs index a648072d04..f8b887b952 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 2b6d16505a..444f080b6c 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs index 238de0d5bc..9c35ff21d4 100644 --- a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Linq; diff --git a/osu.Game.Tournament/Screens/IProvideVideo.cs b/osu.Game.Tournament/Screens/IProvideVideo.cs index b5a4e1ad8e..c11c921412 100644 --- a/osu.Game.Tournament/Screens/IProvideVideo.cs +++ b/osu.Game.Tournament/Screens/IProvideVideo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Tournament.Screens { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs b/osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs index 5b38e539c6..bb9ed39b82 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// 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 Newtonsoft.Json.Converters; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs index bff661bcf4..7831cac84d 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Tournament.Screens.Ladder.Components { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 0244403bff..cf9fe3f2be 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index c4097848d7..3078b58c45 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs index 3abeca3d81..175910d9d6 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs b/osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs index 416f960404..b16ba13f65 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs index 6979aae295..d6b5d172de 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Bindables; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index f0559e0266..d43a410a8f 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Linq; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index 760f6d42f4..f788737add 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs index 578ec79321..4ed46223c8 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs index 3555e4db11..e38b684c28 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs index 9f2d2c4045..241e1d1d0b 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Tournament.Screens.Ladder.Components { diff --git a/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs index e3cb1473be..e605de9a7c 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Linq; diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 7c6aabbe53..351eee0433 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs b/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs index 125d358638..832e218b74 100644 --- a/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 41368eb96e..3116a1361c 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index 384f2f7ab2..093a1ba2d9 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Linq; diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs index 65369fa6da..d809dfc994 100644 --- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; diff --git a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs index cd4f646fe7..0db3348e5d 100644 --- a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs +++ b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 94130cb383..d2ff632da0 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs index 1de9b6ae5c..69c088efbc 100644 --- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index ec103f2444..cb9737d13f 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Linq; diff --git a/osu.Game.Tournament/Screens/TournamentScreen.cs b/osu.Game.Tournament/Screens/TournamentScreen.cs index e830509db9..7f6c5f8e18 100644 --- a/osu.Game.Tournament/Screens/TournamentScreen.cs +++ b/osu.Game.Tournament/Screens/TournamentScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index 711ecc5ae9..bb5682bb42 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Screens; diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index e3996bc572..a90f17ac68 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; From b0971ef0fda240df52b3ff4d729f7705646b6662 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 4 Mar 2019 14:18:04 +0900 Subject: [PATCH 0376/5608] Fix remaining inspections --- osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs | 2 ++ osu.Game/Graphics/UserInterface/RollingCounter.cs | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index f788737add..043ade4285 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -14,6 +14,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components /// /// A collection of two teams competing in a head-to-head match. /// + [Serializable] public class MatchPairing { public int ID; @@ -65,6 +66,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly Bindable Date = new Bindable(); + [JsonProperty] public readonly BindableList ConditionalPairings = new BindableList(); public readonly Bindable Position = new Bindable(); diff --git a/osu.Game/Graphics/UserInterface/RollingCounter.cs b/osu.Game/Graphics/UserInterface/RollingCounter.cs index 47e12f5f15..cd244ed7e6 100644 --- a/osu.Game/Graphics/UserInterface/RollingCounter.cs +++ b/osu.Game/Graphics/UserInterface/RollingCounter.cs @@ -59,7 +59,6 @@ namespace osu.Game.Graphics.UserInterface public abstract void Increment(T amount); - public float TextSize { get => DisplayedCountSpriteText.Font.Size; From 999b947153206c10b5f1295a08d70391758256b1 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Tue, 5 Mar 2019 17:55:18 -0600 Subject: [PATCH 0377/5608] Update Android csproj files --- osu.Android.props | 85 +- osu.Android.sln | 10 +- osu.Android.sln.DotSettings | 815 ++++++++++++++++++ osu.Android/Properties/AndroidManifest.xml | 4 +- osu.Android/monogc.txt | 1 + osu.Android/osu.Android.csproj | 40 +- ...u.Game.Rulesets.Catch.Tests.Android.csproj | 21 +- ...u.Game.Rulesets.Mania.Tests.Android.csproj | 21 +- ...osu.Game.Rulesets.Osu.Tests.Android.csproj | 21 +- ...u.Game.Rulesets.Taiko.Tests.Android.csproj | 24 +- .../osu.Game.Tests.Android.csproj | 21 +- osu.Game/osu.Game.csproj | 2 +- 12 files changed, 880 insertions(+), 185 deletions(-) create mode 100644 osu.Android.sln.DotSettings create mode 100644 osu.Android/monogc.txt diff --git a/osu.Android.props b/osu.Android.props index a662855fc1..bf18d9f022 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -1,60 +1,69 @@ + + bin\$(Configuration) + 4 + 2.0 + false + false + default + Library + 512 + Off + True + Xamarin.Android.Net.AndroidClientHandler + v8.1 + false + True portable False - bin\Debug\ DEBUG;TRACE prompt - 4 - True - None - False - false false - false - CJK;Mideast;Rare;West;Other - - false + false + SdkOnly + true + false + cjk,mideast,other,rare,west + true + armeabi-v7a;x86;arm64-v8a + true - True - pdbonly + false + None True - bin\Release\ - TRACE prompt - 4 - true - False + true + false SdkOnly - True - CJK;Mideast;Rare;West;Other + False + true + cjk,mideast,other,rare,west + true + armeabi-v7a;x86;arm64-v8a + true + + + osu.licenseheader + + + Always + + + + + - - - 0.0.7939 - - - 0.0.7939 - - - 0.22.0 - - - 1.1.0 - - - 1.0.0-dev000096 - - - 1.0.0-dev002315 - + + + \ No newline at end of file diff --git a/osu.Android.sln b/osu.Android.sln index d9c6ffc939..ebf2c55cb4 100644 --- a/osu.Android.sln +++ b/osu.Android.sln @@ -1,12 +1,10 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2006 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28516.95 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game", "osu.Game\osu.Game.csproj", "{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Resources", "osu-resources\osu.Game.Resources\osu.Game.Resources.csproj", "{D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Osu", "osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj", "{C92A607B-1FDD-4954-9F92-03FF547D9080}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Catch", "osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj", "{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}" @@ -37,10 +35,6 @@ Global {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.Build.0 = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.Build.0 = Release|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.Build.0 = Debug|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/osu.Android.sln.DotSettings b/osu.Android.sln.DotSettings new file mode 100644 index 0000000000..3f5bd9d34d --- /dev/null +++ b/osu.Android.sln.DotSettings @@ -0,0 +1,815 @@ + + True + True + True + True + ExplicitlyExcluded + ExplicitlyExcluded + SOLUTION + HINT + WARNING + + True + WARNING + WARNING + HINT + HINT + HINT + HINT + WARNING + WARNING + WARNING + HINT + WARNING + HINT + SUGGESTION + HINT + HINT + HINT + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + WARNING + WARNING + HINT + WARNING + WARNING + DO_NOT_SHOW + HINT + WARNING + DO_NOT_SHOW + WARNING + HINT + HINT + HINT + ERROR + HINT + HINT + HINT + WARNING + WARNING + HINT + DO_NOT_SHOW + HINT + HINT + HINT + HINT + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + HINT + HINT + HINT + HINT + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + WARNING + + WARNING + WARNING + WARNING + ERROR + WARNING + WARNING + HINT + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + WARNING + WARNING + HINT + WARNING + HINT + HINT + HINT + HINT + HINT + HINT + HINT + + HINT + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + WARNING + WARNING + HINT + HINT + WARNING + <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> + Code Cleanup (peppy) + True + True + True + True + True + True + True + True + NEXT_LINE + NEXT_LINE + True + NEVER + NEVER + False + NEVER + False + True + False + False + True + True + False + CHOP_IF_LONG + True + 200 + CHOP_IF_LONG + False + False + AABB + API + BPM + GC + GL + GLSL + HID + HUD + ID + IP + IPC + LTRB + MD5 + NS + OS + RGB + RNG + SHA + SRGB + TK + SS + PP + GMT + QAT + BNG + UI + HINT + <?xml version="1.0" encoding="utf-16"?> +<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> + <TypePattern DisplayName="COM interfaces or structs"> + <TypePattern.Match> + <Or> + <And> + <Kind Is="Interface" /> + <Or> + <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> + <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> + </Or> + </And> + <Kind Is="Struct" /> + </Or> + </TypePattern.Match> + </TypePattern> + <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> + <TypePattern.Match> + <And> + <Kind Is="Class" /> + <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> + </And> + </TypePattern.Match> + <Entry DisplayName="Setup/Teardown Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <Or> + <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="All other members" /> + <Entry Priority="100" DisplayName="Test Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <HasAttribute Name="NUnit.Framework.TestAttribute" /> + </And> + </Entry.Match> + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + </TypePattern> + <TypePattern DisplayName="Default Pattern"> + <Group DisplayName="Fields/Properties"> + <Group DisplayName="Public Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Public Properties"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Internal Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Internal Properties"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Protected Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Protected Properties"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Private Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Private Properties"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Constructor/Destructor"> + <Entry DisplayName="Ctor"> + <Entry.Match> + <Kind Is="Constructor" /> + </Entry.Match> + </Entry> + <Region Name="Disposal"> + <Entry DisplayName="Dtor"> + <Entry.Match> + <Kind Is="Destructor" /> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose()"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose(true)"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Virtual /> + <Override /> + </Or> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + </Region> + </Group> + <Group DisplayName="Methods"> + <Group DisplayName="Public"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Internal"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Protected"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Private"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + </Group> + </TypePattern> +</Patterns> + Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +See the LICENCE file in the repository root for full licence text. + + <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> + <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="_" Suffix="" Style="aaBb" /></Policy> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True + True + True + True + True + True + True + True + True + True + True + True + o!f – Object Initializer: Anchor&Origin + True + constant("Centre") + 0 + True + True + 2.0 + InCSharpFile + ofao + True + Anchor = Anchor.$anchor$, +Origin = Anchor.$anchor$, + True + True + o!f – InternalChildren = [] + True + True + 2.0 + InCSharpFile + ofic + True + InternalChildren = new Drawable[] +{ + $END$ +}; + True + True + o!f – new GridContainer { .. } + True + True + 2.0 + InCSharpFile + ofgc + True + new GridContainer +{ + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { $END$ }, + new Drawable[] { } + } +}; + True + True + o!f – new FillFlowContainer { .. } + True + True + 2.0 + InCSharpFile + offf + True + new FillFlowContainer +{ + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + $END$ + } +}, + True + True + o!f – new Container { .. } + True + True + 2.0 + InCSharpFile + ofcont + True + new Container +{ + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + $END$ + } +}, + True + True + o!f – BackgroundDependencyLoader load() + True + True + 2.0 + InCSharpFile + ofbdl + True + [BackgroundDependencyLoader] +private void load() +{ + $END$ +} + True + True + o!f – new Box { .. } + True + True + 2.0 + InCSharpFile + ofbox + True + new Box +{ + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, +}, + True + True + o!f – Children = [] + True + True + 2.0 + InCSharpFile + ofc + True + Children = new Drawable[] +{ + $END$ +}; + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index 9b337eec6c..c053ced9e2 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -1,9 +1,9 @@  - + - + \ No newline at end of file diff --git a/osu.Android/monogc.txt b/osu.Android/monogc.txt new file mode 100644 index 0000000000..d15a2bd2ae --- /dev/null +++ b/osu.Android/monogc.txt @@ -0,0 +1 @@ +MONO_GC_PARAMS=nursery-size=8m \ No newline at end of file diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index bfde981207..45ff8ba31a 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -1,5 +1,6 @@  + Debug AnyCPU @@ -8,49 +9,20 @@ {D1D5F9A8-B40B-40E6-B02F-482D03346D3D} {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} {122416d6-6b49-4ee2-a1e8-b825f31c79fe} - Library - Properties osu.Android osu.Android - 512 - True - Resources\Resource.designer.cs - Resource - Off - false - v8.1 Properties\AndroidManifest.xml - Resources - Assets - Xamarin.Android.Net.AndroidClientHandler - + + true + - - osu.licenseheader - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} - osu.Game.Resources - {58f6c80c-1253-4a0e-a465-b8c85ebeadf3} osu.Game.Rulesets.Catch @@ -73,8 +45,10 @@ - + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj index 591f4cbc31..ed746921be 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj +++ b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj @@ -1,5 +1,6 @@  + Debug AnyCPU @@ -8,30 +9,14 @@ {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D} {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} {122416d6-6b49-4ee2-a1e8-b825f31c79fe} - Library - Properties osu.Game.Rulesets.Catch.Tests osu.Game.Rulesets.Catch.Tests.Android - 512 - True - Resources\Resource.designer.cs - Resource - Off - false - v8.1 Properties\AndroidManifest.xml - Resources - Assets - Xamarin.Android.Net.AndroidClientHandler - - - osu.licenseheader - @@ -40,10 +25,6 @@ - - {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} - osu.Game.Resources - {58f6c80c-1253-4a0e-a465-b8c85ebeadf3} osu.Game.Rulesets.Catch diff --git a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj index 5faf9f747d..b366958342 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj +++ b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj @@ -1,5 +1,6 @@  + Debug AnyCPU @@ -8,30 +9,14 @@ {531F1092-DB27-445D-AA33-2A77C7187C99} {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} {122416d6-6b49-4ee2-a1e8-b825f31c79fe} - Library - Properties osu.Game.Rulesets.Mania.Tests osu.Game.Rulesets.Mania.Tests.Android - 512 - True - Resources\Resource.designer.cs - Resource - Off - false - v8.1 Properties\AndroidManifest.xml - Resources - Assets - Xamarin.Android.Net.AndroidClientHandler - - - osu.licenseheader - @@ -40,10 +25,6 @@ - - {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} - osu.Game.Resources - {48f4582b-7687-4621-9cbe-5c24197cb536} osu.Game.Rulesets.Mania diff --git a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj index f99aa61f01..a40f7ca588 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj +++ b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj @@ -1,5 +1,6 @@  + Debug AnyCPU @@ -8,30 +9,14 @@ {90CAB706-39CB-4B93-9629-3218A6FF8E9B} {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} {122416d6-6b49-4ee2-a1e8-b825f31c79fe} - Library - Properties osu.Game.Rulesets.Osu.Tests osu.Game.Rulesets.Osu.Tests.Android - 512 - True - Resources\Resource.designer.cs - Resource - Off - false - v8.1 Properties\AndroidManifest.xml - Resources - Assets - Xamarin.Android.Net.AndroidClientHandler - - - osu.licenseheader - @@ -40,10 +25,6 @@ - - {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} - osu.Game.Resources - {c92a607b-1fdd-4954-9f92-03ff547d9080} osu.Game.Rulesets.Osu diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj index defeab5a64..bc7b00ffc8 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj @@ -1,5 +1,6 @@  + Debug AnyCPU @@ -8,30 +9,14 @@ {3701A0A1-8476-42C6-B5C4-D24129B4A484} {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} {122416d6-6b49-4ee2-a1e8-b825f31c79fe} - Library - Properties osu.Game.Rulesets.Taiko.Tests osu.Game.Rulesets.Taiko.Tests.Android - 512 - True - Resources\Resource.designer.cs - Resource - Off - false - v8.1 Properties\AndroidManifest.xml - Resources - Assets - Xamarin.Android.Net.AndroidClientHandler - - - osu.licenseheader - @@ -40,13 +25,6 @@ - - - - - {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} - osu.Game.Resources - {f167e17a-7de6-4af5-b920-a5112296c695} osu.Game.Rulesets.Taiko diff --git a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj index 8a8a2b6733..4e83234e7d 100644 --- a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj +++ b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj @@ -1,5 +1,6 @@  + Debug AnyCPU @@ -8,30 +9,14 @@ {5CC222DC-5716-4499-B897-DCBDDA4A5CF9} {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} {122416d6-6b49-4ee2-a1e8-b825f31c79fe} - Library - Properties osu.Game.Tests osu.Game.Tests.Android - 512 - True - Resources\Resource.designer.cs - Resource - Off - false - v8.1 Properties\AndroidManifest.xml - Resources - Assets - Xamarin.Android.Net.AndroidClientHandler - - - osu.licenseheader - @@ -61,10 +46,6 @@ - - {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} - osu.Game.Resources - {58f6c80c-1253-4a0e-a465-b8c85ebeadf3} osu.Game.Rulesets.Catch diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e87b43ac93..8f9a7cd14b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + From 3c999d64d451db3ab3163cc6100790f967a9a11c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Mar 2019 16:09:21 +0900 Subject: [PATCH 0378/5608] Fix post-merge errors --- .../Profile/Header/CenterHeaderContainer.cs | 20 +++++++++---------- .../Profile/Header/ProfileHeaderTabControl.cs | 16 +++++++-------- osu.Game/Overlays/Profile/ProfileHeader.cs | 10 ++++------ 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs index 30671487d3..fc330a03a9 100644 --- a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -108,8 +108,7 @@ namespace osu.Game.Overlays.Profile.Header { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - TextSize = 16, - Font = "Exo2.0-Bold" + Font = OsuFont.GetFont(weight: FontWeight.Bold) } } } @@ -182,10 +181,9 @@ namespace osu.Game.Overlays.Profile.Header }, levelBadgeText = new OsuSpriteText { - TextSize = 20, - Font = "Exo2.0-Medium", Anchor = Anchor.Centre, Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium) } } }, @@ -215,8 +213,7 @@ namespace osu.Game.Overlays.Profile.Header { Anchor = Anchor.BottomRight, Origin = Anchor.TopRight, - Font = "Exo2.0-Bold", - TextSize = 12, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold) } } }, @@ -248,9 +245,12 @@ namespace osu.Game.Overlays.Profile.Header } }; - DetailsVisible.ValueChanged += newValue => expandButtonIcon.Icon = newValue ? FontAwesome.fa_chevron_down : FontAwesome.fa_chevron_up; - DetailsVisible.ValueChanged += newValue => hiddenDetailContainer.Alpha = newValue ? 1 : 0; - DetailsVisible.ValueChanged += newValue => expandedDetailContainer.Alpha = newValue ? 0 : 1; + DetailsVisible.ValueChanged += visible => + { + expandButtonIcon.Icon = visible.NewValue ? FontAwesome.fa_chevron_down : FontAwesome.fa_chevron_up; + hiddenDetailContainer.Alpha = visible.NewValue ? 1 : 0; + expandedDetailContainer.Alpha = visible.NewValue ? 0 : 1; + }; } private void updateDisplay() diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs index fd7124f20f..a8e50e00fe 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs +++ b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osuTK; @@ -36,7 +37,7 @@ namespace osu.Game.Overlays.Profile.Header } } - public MarginPadding Padding + public new MarginPadding Padding { get => TabContainer.Padding; set => TabContainer.Padding = value; @@ -78,7 +79,7 @@ namespace osu.Game.Overlays.Profile.Header accentColour = value; bar.Colour = value; - if (!Active) text.Colour = value; + if (!Active.Value) text.Colour = value; } } @@ -96,8 +97,7 @@ namespace osu.Game.Overlays.Profile.Header Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, Text = value, - TextSize = 14, - Font = "Exo2.0-Bold", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) }, bar = new Circle { @@ -112,7 +112,7 @@ namespace osu.Game.Overlays.Profile.Header protected override bool OnHover(HoverEvent e) { - if (!Active) + if (!Active.Value) onActivated(true); return base.OnHover(e); } @@ -121,7 +121,7 @@ namespace osu.Game.Overlays.Profile.Header { base.OnHoverLost(e); - if (!Active) + if (!Active.Value) OnDeactivated(); } @@ -134,7 +134,7 @@ namespace osu.Game.Overlays.Profile.Header { text.FadeColour(AccentColour, 120, Easing.InQuad); bar.ResizeHeightTo(0, 120, Easing.InQuad); - text.Font = "Exo2.0-Medium"; + text.Font = text.Font.With(Typeface.Exo, weight: FontWeight.Medium); } private void onActivated(bool fake = false) @@ -142,7 +142,7 @@ namespace osu.Game.Overlays.Profile.Header text.FadeColour(Color4.White, 120, Easing.InQuad); bar.ResizeHeightTo(7.5f, 120, Easing.InQuad); if (!fake) - text.Font = "Exo2.0-Bold"; + text.Font = text.Font.With(Typeface.Exo, weight: FontWeight.Bold); } } } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 21f1989606..fdb515270b 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -15,6 +14,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; +using osu.Framework.Bindables; namespace osu.Game.Overlays.Profile { @@ -145,7 +145,7 @@ namespace osu.Game.Overlays.Profile infoTabControl.AddItem("Modding"); centerHeaderContainer.DetailsVisible.BindTo(DetailsVisible); - DetailsVisible.ValueChanged += newValue => detailHeaderContainer.Alpha = newValue ? 0 : 1; + DetailsVisible.ValueChanged += visible => detailHeaderContainer.Alpha = visible.NewValue ? 0 : 1; } [BackgroundDependencyLoader] @@ -224,13 +224,11 @@ namespace osu.Game.Overlays.Profile }, title = new OsuSpriteText { - Font = "Exo2.0-Bold", - TextSize = big ? 14 : 12, + Font = OsuFont.GetFont(size: big ? 14 : 12, weight: FontWeight.Bold) }, content = new OsuSpriteText { - Font = "Exo2.0-Light", - TextSize = big ? 40 : 18, + Font = OsuFont.GetFont(size: big ? 40 : 18, weight: FontWeight.Light) }, new Container //Add a minimum size to the FillFlowContainer { From e3d463a141269e4909b49ed6bf4c277de84dab44 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Mar 2019 16:30:56 +0900 Subject: [PATCH 0379/5608] Formatting fixes --- .../Graphics/Containers/OsuHoverContainer.cs | 2 +- .../Profile/Header/BottomHeaderContainer.cs | 9 ++++--- .../Profile/Header/CenterHeaderContainer.cs | 8 ++++-- .../Profile/Header/DetailHeaderContainer.cs | 8 ++++-- .../Profile/Header/MedalHeaderContainer.cs | 6 ++++- .../Profile/Header/TopHeaderContainer.cs | 6 ++++- osu.Game/Users/User.cs | 3 +++ osu.Game/Users/UserStatistics.cs | 25 +++++++++++++------ 8 files changed, 49 insertions(+), 18 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index f94fb2540c..1e0b56dae3 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -33,7 +33,7 @@ namespace osu.Game.Graphics.Containers [BackgroundDependencyLoader] private void load(OsuColour colours) { - if(HoverColour == default) + if (HoverColour == default) HoverColour = colours.Yellow; } diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index df0409272f..7bb1b8acc2 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -24,13 +24,17 @@ namespace osu.Game.Overlays.Profile.Header private Color4 linkBlue, communityUserGrayGreenLighter; private User user; + public User User { get => user; set { - if (user == value) return; + if (user == value) + return; + user = value; + updateDisplay(); } } @@ -131,9 +135,8 @@ namespace osu.Game.Overlays.Profile.Header }); } else - { bottomLinkContainer.AddText(" " + content, bold); - } + addSpacer(bottomLinkContainer); } diff --git a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs index fc330a03a9..ca615ccf4b 100644 --- a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs @@ -48,13 +48,17 @@ namespace osu.Game.Overlays.Profile.Header private APIAccess apiAccess { get; set; } private User user; + public User User { get => user; set { - if (user == value) return; + if (user == value) + return; + user = value; + updateDisplay(); } } @@ -183,7 +187,7 @@ namespace osu.Game.Overlays.Profile.Header { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium) + Font = OsuFont.GetFont(size: 20) } } }, diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index 124299b0ba..a7d21bcdf3 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -26,13 +26,17 @@ namespace osu.Game.Overlays.Profile.Header private RankGraph rankGraph; private User user; + public User User { get => user; set { - if (user == value) return; + if (user == value) + return; + user = value; + updateDisplay(); } } @@ -181,7 +185,7 @@ namespace osu.Game.Overlays.Profile.Header totalPlayTimeTooltip.TooltipText = (user?.Statistics?.PlayTime ?? 0) / 3600 + " hours"; foreach (var scoreRankInfo in scoreRankInfos) - scoreRankInfo.Value.RankCount = user?.Statistics?.GradesCount.GetForScoreRank(scoreRankInfo.Key) ?? 0; + scoreRankInfo.Value.RankCount = user?.Statistics?.GradesCount[scoreRankInfo.Key] ?? 0; detailGlobalRank.Content = user?.Statistics?.Ranks.Global?.ToString("#,##0") ?? "-"; detailCountryRank.Content = user?.Statistics?.Ranks.Country?.ToString("#,##0") ?? "-"; diff --git a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs index 5a54270b80..45c1e1e208 100644 --- a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs @@ -22,13 +22,17 @@ namespace osu.Game.Overlays.Profile.Header private FillFlowContainer badgeFlowContainer; private User user; + public User User { get => user; set { - if (user == value) return; + if (user == value) + return; + user = value; + updateDisplay(); } } diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 4186d08729..13a7951170 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -28,13 +28,17 @@ namespace osu.Game.Overlays.Profile.Header private const float avatar_size = 110; private User user; + public User User { get => user; set { - if (user == value) return; + if (user == value) + return; + user = value; + updateDisplay(); } } diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index d8e1ec81b5..314684069a 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -186,10 +186,13 @@ namespace osu.Game.Users { [Description("Keyboard")] Keyboard, + [Description("Mouse")] Mouse, + [Description("Tablet")] Tablet, + [Description("Touch Screen")] Touch, } diff --git a/osu.Game/Users/UserStatistics.cs b/osu.Game/Users/UserStatistics.cs index a69cd794b3..752534a80d 100644 --- a/osu.Game/Users/UserStatistics.cs +++ b/osu.Game/Users/UserStatistics.cs @@ -77,16 +77,25 @@ namespace osu.Game.Users [JsonProperty(@"a")] public int A; - public int GetForScoreRank(ScoreRank rank) + public int this[ScoreRank rank] { - switch (rank) + get { - case ScoreRank.XH: return SSPlus; - case ScoreRank.X: return SS; - case ScoreRank.SH: return SPlus; - case ScoreRank.S: return S; - case ScoreRank.A: return A; - default: throw new ArgumentException($"API does not return {rank.ToString()}"); + switch (rank) + { + case ScoreRank.XH: + return SSPlus; + case ScoreRank.X: + return SS; + case ScoreRank.SH: + return SPlus; + case ScoreRank.S: + return S; + case ScoreRank.A: + return A; + default: + throw new ArgumentException($"API does not return {rank.ToString()}"); + } } } } From 22423f60d42efe96c985289daa01fbc6900bd566 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Mar 2019 19:27:42 +0900 Subject: [PATCH 0380/5608] Fix DI not working --- osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs b/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs index 6f164890f9..49ffa2d63f 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual typeof(ProfileHeader), typeof(RankGraph), typeof(LineGraph), - typeof(SupporterIcon) + typeof(ProfileHeaderTabControl), }; [Resolved] From c93adb220eb5a02afe3c5811af4cbb826b5f83a4 Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Thu, 7 Mar 2019 10:14:19 -0600 Subject: [PATCH 0381/5608] Use official NuGet osu-framework build for Android --- osu.Android.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index bf18d9f022..da3abeb446 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -64,6 +64,6 @@ - + - \ No newline at end of file + From 8c0e325d8bc54ae802668c483ffdf30a6acbdd0f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Mar 2019 16:40:37 +0900 Subject: [PATCH 0382/5608] Reduce + make beatmap scores testcase work --- .../Visual/TestCaseBeatmapScoresContainer.cs | 147 +----------------- 1 file changed, 6 insertions(+), 141 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs index 4ad5b2dc35..072bbff4cf 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs @@ -13,9 +13,7 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Users; using System.Collections.Generic; using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Rulesets.Osu; using osu.Game.Scoring; using NUnit.Framework; @@ -67,6 +65,7 @@ namespace osu.Game.Tests.Visual new OsuModHardRock(), }, Rank = ScoreRank.XH, + MaxCombo = 1234, TotalScore = 1234567890, Accuracy = 1, }, @@ -89,6 +88,7 @@ namespace osu.Game.Tests.Visual new OsuModFlashlight(), }, Rank = ScoreRank.S, + MaxCombo = 1234, TotalScore = 1234789, Accuracy = 0.9997, }, @@ -110,6 +110,7 @@ namespace osu.Game.Tests.Visual new OsuModHidden(), }, Rank = ScoreRank.B, + MaxCombo = 1234, TotalScore = 12345678, Accuracy = 0.9854, }, @@ -130,6 +131,7 @@ namespace osu.Game.Tests.Visual new OsuModDoubleTime(), }, Rank = ScoreRank.C, + MaxCombo = 1234, TotalScore = 1234567, Accuracy = 0.8765, }, @@ -146,6 +148,7 @@ namespace osu.Game.Tests.Visual }, }, Rank = ScoreRank.F, + MaxCombo = 1234, TotalScore = 123456, Accuracy = 0.6543, }, @@ -159,145 +162,7 @@ namespace osu.Game.Tests.Visual s.Statistics.Add(HitResult.Miss, RNG.Next(2000)); } - IEnumerable anotherScores = new[] - { - new APIScoreInfo - { - User = new User - { - Id = 4608074, - Username = @"Skycries", - Country = new Country - { - FullName = @"Brazil", - FlagName = @"BR", - }, - }, - Mods = new Mod[] - { - new OsuModDoubleTime(), - new OsuModHidden(), - new OsuModFlashlight(), - }, - Rank = ScoreRank.S, - TotalScore = 1234789, - Accuracy = 0.9997, - }, - new APIScoreInfo - { - User = new User - { - Id = 6602580, - Username = @"waaiiru", - Country = new Country - { - FullName = @"Spain", - FlagName = @"ES", - }, - }, - Mods = new Mod[] - { - new OsuModDoubleTime(), - new OsuModHidden(), - new OsuModFlashlight(), - new OsuModHardRock(), - }, - Rank = ScoreRank.XH, - TotalScore = 1234567890, - Accuracy = 1, - }, - new APIScoreInfo - { - User = new User - { - Id = 7151382, - Username = @"Mayuri Hana", - Country = new Country - { - FullName = @"Thailand", - FlagName = @"TH", - }, - }, - Rank = ScoreRank.F, - TotalScore = 123456, - Accuracy = 0.6543, - }, - new APIScoreInfo - { - User = new User - { - Id = 1014222, - Username = @"eLy", - Country = new Country - { - FullName = @"Japan", - FlagName = @"JP", - }, - }, - Mods = new Mod[] - { - new OsuModDoubleTime(), - new OsuModHidden(), - }, - Rank = ScoreRank.B, - TotalScore = 12345678, - Accuracy = 0.9854, - }, - new APIScoreInfo - { - User = new User - { - Id = 1541390, - Username = @"Toukai", - Country = new Country - { - FullName = @"Canada", - FlagName = @"CA", - }, - }, - Mods = new Mod[] - { - new OsuModDoubleTime(), - }, - Rank = ScoreRank.C, - TotalScore = 1234567, - Accuracy = 0.8765, - }, - }; - foreach (var s in anotherScores) - { - 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)); - } - - var topScoreInfo = new APIScoreInfo - { - User = new User - { - Id = 2705430, - Username = @"Mooha", - Country = new Country - { - FullName = @"France", - FlagName = @"FR", - }, - }, - Mods = new Mod[] - { - new OsuModDoubleTime(), - new OsuModFlashlight(), - new OsuModHardRock(), - }, - Rank = ScoreRank.B, - TotalScore = 987654321, - Accuracy = 0.8487, - }; - topScoreInfo.Statistics.Add(HitResult.Great, RNG.Next(2000)); - topScoreInfo.Statistics.Add(HitResult.Good, RNG.Next(2000)); - topScoreInfo.Statistics.Add(HitResult.Meh, RNG.Next(2000)); - topScoreInfo.Statistics.Add(HitResult.Miss, RNG.Next(2000)); + scoresContainer.Scores = scores; } [BackgroundDependencyLoader] From a40ffcc6920d5bc25f0782727a1b967e1b1fc951 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Mar 2019 16:44:39 +0900 Subject: [PATCH 0383/5608] Apply formatting adjustments --- .../Visual/TestCaseBeatmapScoresContainer.cs | 8 ++++-- .../Scores/ClickableUserContainer.cs | 1 - .../BeatmapSet/Scores/DrawableScore.cs | 3 ++- .../BeatmapSet/Scores/DrawableTopScore.cs | 25 +++++++++++++------ .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 6 ++--- .../BeatmapSet/Scores/ScoreTextLine.cs | 3 ++- 6 files changed, 29 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs index 072bbff4cf..ead743a283 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs @@ -26,10 +26,9 @@ namespace osu.Game.Tests.Visual public TestCaseBeatmapScoresContainer() { - Container container; ScoresContainer scoresContainer; - Child = container = new Container + Child = new Container { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -65,6 +64,7 @@ namespace osu.Game.Tests.Visual new OsuModHardRock(), }, Rank = ScoreRank.XH, + PP = 200, MaxCombo = 1234, TotalScore = 1234567890, Accuracy = 1, @@ -88,6 +88,7 @@ namespace osu.Game.Tests.Visual new OsuModFlashlight(), }, Rank = ScoreRank.S, + PP = 190, MaxCombo = 1234, TotalScore = 1234789, Accuracy = 0.9997, @@ -110,6 +111,7 @@ namespace osu.Game.Tests.Visual new OsuModHidden(), }, Rank = ScoreRank.B, + PP = 180, MaxCombo = 1234, TotalScore = 12345678, Accuracy = 0.9854, @@ -131,6 +133,7 @@ namespace osu.Game.Tests.Visual new OsuModDoubleTime(), }, Rank = ScoreRank.C, + PP = 170, MaxCombo = 1234, TotalScore = 1234567, Accuracy = 0.8765, @@ -148,6 +151,7 @@ namespace osu.Game.Tests.Visual }, }, Rank = ScoreRank.F, + PP = 160, MaxCombo = 1234, TotalScore = 123456, Accuracy = 0.6543, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs index 3f1c8f56f5..cf1c3d7fcf 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; -using osu.Game.Graphics; using osu.Game.Users; namespace osu.Game.Overlays.BeatmapSet.Scores diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index 8741fd8dfe..19e999547b 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -118,7 +118,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private class DrawableScoreData : ScoreTableLine { - public DrawableScoreData(int index, APIScoreInfo score, int maxModsAmount) : base(maxModsAmount) + public DrawableScoreData(int index, APIScoreInfo score, int maxModsAmount) + : base(maxModsAmount) { SpriteText scoreText; SpriteText accuracy; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index e4486b1514..3712f38d02 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -56,13 +56,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly ModsInfoColumn modsInfo; private APIScoreInfo score; + public APIScoreInfo Score { - get { return score; } + get => score; set { if (score == value) return; + score = value; avatar.User = username.User = score.User; @@ -274,9 +276,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { if (text.TextSize == value) return; + text.TextSize = value; } - get { return text.TextSize; } + get => text.TextSize; } public ClickableTopScoreUsername() @@ -386,7 +389,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } - public ModsInfoColumn(string header) : base(header) + public ModsInfoColumn(string header) + : base(header) { AutoSizeAxes = Axes.Both; Add(modsContainer = new FillFlowContainer @@ -409,12 +413,14 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { if (valueText.Text == value) return; + valueText.Text = value; } - get { return valueText.Text; } + get => valueText.Text; } - protected TextInfoColumn(string header, float valueTextSize = 25) : base(header) + protected TextInfoColumn(string header, float valueTextSize = 25) + : base(header) { Add(valueText = new SpriteText { @@ -425,7 +431,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private class AutoSizedInfoColumn : TextInfoColumn { - public AutoSizedInfoColumn(string header, float valueTextSize = 25) : base(header, valueTextSize) + public AutoSizedInfoColumn(string header, float valueTextSize = 25) + : base(header, valueTextSize) { AutoSizeAxes = Axes.Both; } @@ -435,7 +442,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { private const float width = 70; - public MediumInfoColumn(string header, float valueTextSize = 25) : base(header, valueTextSize) + public MediumInfoColumn(string header, float valueTextSize = 25) + : base(header, valueTextSize) { Width = width; } @@ -445,7 +453,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { private const float width = 40; - public SmallInfoColumn(string header, float valueTextSize = 25) : base(header, valueTextSize) + public SmallInfoColumn(string header, float valueTextSize = 25) + : base(header, valueTextSize) { Width = width; } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 1b20b2c382..d69bc39bc6 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -11,6 +11,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public class ScoreTable : FillFlowContainer { private IEnumerable scores; + public IEnumerable Scores { set @@ -31,10 +32,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores foreach (var s in scores) Add(new DrawableScore(index++, s, maxModsAmount)); } - get - { - return scores; - } + get => scores; } public ScoreTable() diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs index 9fd12df3a8..9e201bd98d 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs @@ -7,7 +7,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { public class ScoreTextLine : ScoreTableLine { - public ScoreTextLine(int maxModsAmount) : base(maxModsAmount) + public ScoreTextLine(int maxModsAmount) + : base(maxModsAmount) { RankContainer.Add(new ScoreText { From 9a05643ec980732837124698e535396c34ab73bf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Mar 2019 17:18:54 +0900 Subject: [PATCH 0384/5608] Minor refactorings --- .../BeatmapSet/Scores/DrawableScore.cs | 2 + .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 45 +++--- .../BeatmapSet/Scores/ScoresContainer.cs | 140 +++++++++--------- 3 files changed, 97 insertions(+), 90 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index 19e999547b..a2a9f9a01b 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -31,8 +31,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + CornerRadius = 3; Masking = true; + Children = new Drawable[] { background = new Box diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index d69bc39bc6..4723fcaf2b 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -5,47 +5,50 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; using System.Collections.Generic; +using System.Linq; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class ScoreTable : FillFlowContainer + public class ScoreTable : CompositeDrawable { - private IEnumerable scores; + private readonly FillFlowContainer scoresFlow; + + public ScoreTable() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + InternalChild = scoresFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical + }; + } public IEnumerable Scores { set { - scores = value; + scoresFlow.Clear(); + + if (value == null || !value.Any()) + return; int maxModsAmount = 0; - foreach (var s in scores) + foreach (var s in value) { var scoreModsAmount = s.Mods.Length; if (scoreModsAmount > maxModsAmount) maxModsAmount = scoreModsAmount; } - Add(new ScoreTextLine(maxModsAmount)); + scoresFlow.Add(new ScoreTextLine(maxModsAmount)); int index = 0; - foreach (var s in scores) - Add(new DrawableScore(index++, s, maxModsAmount)); + foreach (var s in value) + scoresFlow.Add(new DrawableScore(index++, s, maxModsAmount)); } - get => scores; - } - - public ScoreTable() - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Direction = FillDirection.Vertical; - } - - public void ClearScores() - { - scores = null; - Clear(); } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index d99f391d21..6c90e192ac 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -17,7 +17,7 @@ using System.Linq; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class ScoresContainer : Container + public class ScoresContainer : CompositeDrawable { private const int spacing = 15; private const int fade_duration = 200; @@ -28,77 +28,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly DrawableTopScore topScore; private readonly LoadingAnimation loadingAnimation; - private bool loading - { - set => loadingAnimation.FadeTo(value ? 1 : 0, fade_duration); - } - - private IEnumerable scores; - private BeatmapInfo beatmap; - - public IEnumerable Scores - { - get => scores; - set - { - getScoresRequest?.Cancel(); - scores = value; - - updateDisplay(); - } - } - - private GetScoresRequest getScoresRequest; - private APIAccess api; - - public BeatmapInfo Beatmap - { - get => beatmap; - set - { - beatmap = value; - - Scores = null; - - if (beatmap?.OnlineBeatmapID.HasValue != true) - return; - - loading = true; - - getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); - getScoresRequest.Success += r => Schedule(() => Scores = r.Scores); - api.Queue(getScoresRequest); - } - } - - private void updateDisplay() - { - scoreTable.ClearScores(); - - loading = false; - - var scoreCount = scores?.Count() ?? 0; - - if (scoreCount == 0) - { - topScore.Hide(); - return; - } - - topScore.Score = scores.FirstOrDefault(); - topScore.Show(); - - if (scoreCount < 2) - return; - - scoreTable.Scores = scores; - } + [Resolved] + private APIAccess api { get; set; } public ScoresContainer() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Children = new Drawable[] + + InternalChildren = new Drawable[] { background = new Box { @@ -135,12 +73,76 @@ namespace osu.Game.Overlays.BeatmapSet.Scores [BackgroundDependencyLoader] private void load(APIAccess api, OsuColour colours) { - this.api = api; - background.Colour = colours.Gray2; updateDisplay(); } + private bool loading + { + set => loadingAnimation.FadeTo(value ? 1 : 0, fade_duration); + } + + private GetScoresRequest getScoresRequest; + + private IEnumerable scores; + + public IEnumerable Scores + { + get => scores; + set + { + getScoresRequest?.Cancel(); + scores = value; + + updateDisplay(); + } + } + + private BeatmapInfo beatmap; + + public BeatmapInfo Beatmap + { + get => beatmap; + set + { + beatmap = value; + + Scores = null; + + if (beatmap?.OnlineBeatmapID.HasValue != true) + return; + + loading = true; + + getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); + getScoresRequest.Success += r => Schedule(() => Scores = r.Scores); + api.Queue(getScoresRequest); + } + } + + private void updateDisplay() + { + scoreTable.Scores = Enumerable.Empty(); + + loading = false; + + var scoreCount = scores?.Count() ?? 0; + + if (scoreCount == 0) + { + topScore.Hide(); + return; + } + + topScore.Score = scores.FirstOrDefault(); + topScore.Show(); + + if (scoreCount < 2) + return; + + scoreTable.Scores = scores; + } + protected override void Dispose(bool isDisposing) { getScoresRequest?.Cancel(); From 2525f5bcb787955ab3a315c62143e76bd26825b7 Mon Sep 17 00:00:00 2001 From: jorolf Date: Sat, 9 Mar 2019 23:58:14 +0100 Subject: [PATCH 0385/5608] Apply most suggestions --- osu.Game.Tests/Visual/TestCaseUserProfile.cs | 13 -- .../Visual/TestCaseUserProfileHeader.cs | 8 +- .../Profile/Header/BottomHeaderContainer.cs | 26 +-- .../Profile/Header/CenterHeaderContainer.cs | 138 +++------------- .../Profile/Header/DetailHeaderContainer.cs | 40 ++--- .../Overlays/Profile/Header/DrawableBadge.cs | 46 ++++++ .../Profile/Header/MedalHeaderContainer.cs | 63 ++------ .../Profile/Header/OverlinedInfoContainer.cs | 63 ++++++++ .../Profile/Header/ProfileHeaderButton.cs | 50 ++++++ .../Profile/Header/ProfileHeaderTabControl.cs | 8 +- .../Profile/Header/ProfileMessageButton.cs | 57 +++++++ .../Overlays/Profile/Header/SupporterIcon.cs | 48 +++--- .../Profile/Header/TopHeaderContainer.cs | 34 ++-- osu.Game/Overlays/Profile/ProfileHeader.cs | 153 +++--------------- osu.Game/Overlays/UserProfileOverlay.cs | 4 +- osu.Game/Users/UserCoverBackground.cs | 47 ++++-- osu.Game/Users/UserPanel.cs | 4 +- 17 files changed, 375 insertions(+), 427 deletions(-) create mode 100644 osu.Game/Overlays/Profile/Header/DrawableBadge.cs create mode 100644 osu.Game/Overlays/Profile/Header/OverlinedInfoContainer.cs create mode 100644 osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs create mode 100644 osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs diff --git a/osu.Game.Tests/Visual/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/TestCaseUserProfile.cs index d0c4e495b8..3abb2584ce 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/TestCaseUserProfile.cs @@ -87,8 +87,6 @@ namespace osu.Game.Tests.Visual AddStep("Show offline dummy", () => profile.ShowUser(TEST_USER, false)); - checkSupporterTag(false); - AddStep("Show null dummy", () => profile.ShowUser(new User { Username = @"Null", @@ -104,8 +102,6 @@ namespace osu.Game.Tests.Visual CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg" }, api.IsLoggedIn)); - checkSupporterTag(true); - AddStep("Show flyte", () => profile.ShowUser(new User { Username = @"flyte", @@ -118,15 +114,6 @@ namespace osu.Game.Tests.Visual AddStep("Show without reload", profile.Show); } - private void checkSupporterTag(bool isSupporter) - { - AddUntilStep(() => profile.Header.User != null, "wait for load"); - if (isSupporter) - AddAssert("is supporter", () => profile.Header.SupporterTag.Alpha == 1); - else - AddAssert("no supporter", () => profile.Header.SupporterTag.Alpha == 0); - } - private class TestUserProfileOverlay : UserProfileOverlay { public new ProfileHeader Header => base.Header; diff --git a/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs b/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs index 49ffa2d63f..8f36b4dda8 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs @@ -33,9 +33,9 @@ namespace osu.Game.Tests.Visual header = new ProfileHeader(); Add(header); - AddStep("Show offline dummy", () => header.User = TestCaseUserProfile.TEST_USER); + AddStep("Show offline dummy", () => header.User.Value = TestCaseUserProfile.TEST_USER); - AddStep("Show null dummy", () => header.User = new User + AddStep("Show null dummy", () => header.User.Value = new User { Username = "Null" }); @@ -65,11 +65,11 @@ namespace osu.Game.Tests.Visual if (api.IsLoggedIn) { var request = new GetUserRequest(fallback.Id); - request.Success += user => header.User = user; + request.Success += user => header.User.Value = user; api.Queue(request); } else - header.User = fallback; + header.User.Value = fallback; }); } } diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 7bb1b8acc2..1f9d741b8d 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -17,32 +18,21 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header { - public class BottomHeaderContainer : Container + public class BottomHeaderContainer : CompositeDrawable { private LinkFlowContainer bottomTopLinkContainer; private LinkFlowContainer bottomLinkContainer; private Color4 linkBlue, communityUserGrayGreenLighter; - private User user; - - public User User - { - get => user; - set - { - if (user == value) - return; - - user = value; - - updateDisplay(); - } - } + public readonly Bindable User = new Bindable(); [BackgroundDependencyLoader] private void load(OsuColour colours) { - Children = new Drawable[] + AutoSizeAxes = Axes.Y; + User.ValueChanged += e => updateDisplay(e.NewValue); + + InternalChildren = new Drawable[] { new Box { @@ -76,7 +66,7 @@ namespace osu.Game.Overlays.Profile.Header communityUserGrayGreenLighter = colours.CommunityUserGrayGreenLighter; } - private void updateDisplay() + private void updateDisplay(User user) { void bold(SpriteText t) => t.Font = @"Exo2.0-Bold"; void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); diff --git a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs index ca615ccf4b..b5e04bee9e 100644 --- a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs @@ -1,75 +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 System.Collections.Generic; +using System; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; -using osu.Game.Online.Chat; using osu.Game.Users; using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header { - public class CenterHeaderContainer : Container + public class CenterHeaderContainer : CompositeDrawable { - public readonly BindableBool DetailsVisible = new BindableBool(); + public Action DetailsVisibilityAction; + private bool detailsVisible; private OsuSpriteText followerText; - private ProfileHeaderButton messageButton; private OsuSpriteText levelBadgeText; private Bar levelProgressBar; private OsuSpriteText levelProgressText; - private ProfileHeader.OverlinedInfoContainer hiddenDetailGlobal, hiddenDetailCountry; + private OverlinedInfoContainer hiddenDetailGlobal, hiddenDetailCountry; - [Resolved(CanBeNull = true)] - private ChannelManager channelManager { get; set; } - - [Resolved(CanBeNull = true)] - private UserProfileOverlay userOverlay { get; set; } - - [Resolved(CanBeNull = true)] - private ChatOverlay chatOverlay { get; set; } - - [Resolved] - private APIAccess apiAccess { get; set; } - - private User user; - - public User User - { - get => user; - set - { - if (user == value) - return; - - user = value; - - updateDisplay(); - } - } + public readonly Bindable User = new Bindable(); [BackgroundDependencyLoader] private void load(OsuColour colours, TextureStore textures) { Container hiddenDetailContainer, expandedDetailContainer; SpriteIcon expandButtonIcon; + ProfileHeaderButton detailsToggleButton; + Height = 60; + User.ValueChanged += e => updateDisplay(e.NewValue); - Children = new Drawable[] + InternalChildren = new Drawable[] { new Box { @@ -118,21 +91,9 @@ namespace osu.Game.Overlays.Profile.Header } } }, - messageButton = new ProfileHeaderButton + new ProfileMessageButton { - Alpha = 0, - RelativeSizeAxes = Axes.Y, - Children = new Drawable[] - { - new SpriteIcon - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Icon = FontAwesome.fa_envelope, - FillMode = FillMode.Fit, - Size = new Vector2(50, 14) - }, - } + User = { BindTarget = User } }, } }, @@ -143,12 +104,11 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.Y, Padding = new MarginPadding { Vertical = 10 }, Width = UserProfileOverlay.CONTENT_X_MARGIN, - Child = new ProfileHeaderButton + Child = detailsToggleButton = new ProfileHeaderButton { RelativeSizeAxes = Axes.Y, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Action = DetailsVisible.Toggle, Children = new Drawable[] { expandButtonIcon = new SpriteIcon @@ -233,12 +193,12 @@ namespace osu.Game.Overlays.Profile.Header Margin = new MarginPadding { Right = 50 }, Children = new[] { - hiddenDetailGlobal = new ProfileHeader.OverlinedInfoContainer + hiddenDetailGlobal = new OverlinedInfoContainer { Title = "Global Ranking", LineColour = colours.Yellow }, - hiddenDetailCountry = new ProfileHeader.OverlinedInfoContainer + hiddenDetailCountry = new OverlinedInfoContainer { Title = "Country Ranking", LineColour = colours.Yellow @@ -249,76 +209,26 @@ namespace osu.Game.Overlays.Profile.Header } }; - DetailsVisible.ValueChanged += visible => + detailsToggleButton.Action = () => { - expandButtonIcon.Icon = visible.NewValue ? FontAwesome.fa_chevron_down : FontAwesome.fa_chevron_up; - hiddenDetailContainer.Alpha = visible.NewValue ? 1 : 0; - expandedDetailContainer.Alpha = visible.NewValue ? 0 : 1; + detailsVisible = !detailsVisible; + expandButtonIcon.Icon = detailsVisible ? FontAwesome.fa_chevron_down : FontAwesome.fa_chevron_up; + hiddenDetailContainer.Alpha = detailsVisible ? 1 : 0; + expandedDetailContainer.Alpha = detailsVisible ? 0 : 1; + DetailsVisibilityAction(detailsVisible); }; } - private void updateDisplay() + private void updateDisplay(User user) { followerText.Text = user.FollowerCount?.Length > 0 ? user.FollowerCount[0].ToString("#,##0") : "0"; - if (!user.PMFriendsOnly && apiAccess.LocalUser.Value.Id != user.Id) - { - messageButton.Show(); - messageButton.Action = () => - { - channelManager?.OpenPrivateChannel(user); - userOverlay?.Hide(); - chatOverlay?.Show(); - }; - } - else - { - messageButton.Hide(); - } - levelBadgeText.Text = user.Statistics?.Level.Current.ToString() ?? "0"; levelProgressBar.Length = user.Statistics?.Level.Progress / 100f ?? 0; levelProgressText.Text = user.Statistics?.Level.Progress.ToString("0'%'"); - hiddenDetailGlobal.Content = user?.Statistics?.Ranks.Global?.ToString("#,##0") ?? "-"; - hiddenDetailCountry.Content = user?.Statistics?.Ranks.Country?.ToString("#,##0") ?? "-"; - } - - private class ProfileHeaderButton : OsuHoverContainer - { - private readonly Box background; - private readonly Container content; - - protected override Container Content => content; - - protected override IEnumerable EffectTargets => new[] { background }; - - public ProfileHeaderButton() - { - HoverColour = Color4.Black.Opacity(0.75f); - IdleColour = Color4.Black.Opacity(0.7f); - AutoSizeAxes = Axes.X; - - base.Content.Add(new CircularContainer - { - Masking = true, - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - content = new Container - { - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = 10 }, - } - } - }); - } + hiddenDetailGlobal.Content = user.Statistics?.Ranks.Global?.ToString("#,##0") ?? "-"; + hiddenDetailCountry.Content = user.Statistics?.Ranks.Country?.ToString("#,##0") ?? "-"; } } } diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index a7d21bcdf3..19894f0301 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -17,34 +18,23 @@ using osuTK; namespace osu.Game.Overlays.Profile.Header { - public class DetailHeaderContainer : Container + public class DetailHeaderContainer : CompositeDrawable { private ProfileHeader.HasTooltipContainer totalPlayTimeTooltip; - private ProfileHeader.OverlinedInfoContainer totalPlayTimeInfo, medalInfo, ppInfo; + private OverlinedInfoContainer totalPlayTimeInfo, medalInfo, ppInfo; private readonly Dictionary scoreRankInfos = new Dictionary(); - private ProfileHeader.OverlinedInfoContainer detailGlobalRank, detailCountryRank; + private OverlinedInfoContainer detailGlobalRank, detailCountryRank; private RankGraph rankGraph; - private User user; - - public User User - { - get => user; - set - { - if (user == value) - return; - - user = value; - - updateDisplay(); - } - } + public readonly Bindable User = new Bindable(); [BackgroundDependencyLoader] private void load(OsuColour colours) { - Children = new Drawable[] + AutoSizeAxes = Axes.Y; + User.ValueChanged += e => updateDisplay(e.NewValue); + + InternalChildren = new Drawable[] { new Box { @@ -79,18 +69,18 @@ namespace osu.Game.Overlays.Profile.Header { AutoSizeAxes = Axes.Both, TooltipText = "0 hours", - Child = totalPlayTimeInfo = new ProfileHeader.OverlinedInfoContainer + Child = totalPlayTimeInfo = new OverlinedInfoContainer { Title = "Total Play Time", LineColour = colours.Yellow, }, }, - medalInfo = new ProfileHeader.OverlinedInfoContainer + medalInfo = new OverlinedInfoContainer { Title = "Medals", LineColour = colours.GreenLight, }, - ppInfo = new ProfileHeader.OverlinedInfoContainer + ppInfo = new OverlinedInfoContainer { Title = "pp", LineColour = colours.Red, @@ -135,12 +125,12 @@ namespace osu.Game.Overlays.Profile.Header Spacing = new Vector2(0, 20), Children = new Drawable[] { - detailGlobalRank = new ProfileHeader.OverlinedInfoContainer(true, 110) + detailGlobalRank = new OverlinedInfoContainer(true, 110) { Title = "Global Ranking", LineColour = colours.Yellow, }, - detailCountryRank = new ProfileHeader.OverlinedInfoContainer(false, 110) + detailCountryRank = new OverlinedInfoContainer(false, 110) { Title = "Country Ranking", LineColour = colours.Yellow, @@ -154,7 +144,7 @@ namespace osu.Game.Overlays.Profile.Header }; } - private void updateDisplay() + private void updateDisplay(User user) { medalInfo.Content = user?.Achievements?.Length.ToString() ?? "0"; ppInfo.Content = user?.Statistics?.PP?.ToString("#,##0") ?? "0"; diff --git a/osu.Game/Overlays/Profile/Header/DrawableBadge.cs b/osu.Game/Overlays/Profile/Header/DrawableBadge.cs new file mode 100644 index 0000000000..75a8f4e415 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/DrawableBadge.cs @@ -0,0 +1,46 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Overlays.Profile.Header +{ + public class DrawableBadge : CompositeDrawable, IHasTooltip + { + public static readonly Vector2 DRAWABLE_BADGE_SIZE = new Vector2(86, 40); + + private readonly Badge badge; + + public DrawableBadge(Badge badge) + { + this.badge = badge; + Size = DRAWABLE_BADGE_SIZE; + } + + [BackgroundDependencyLoader] + private void load(LargeTextureStore textures) + { + InternalChild = new Sprite + { + FillMode = FillMode.Fit, + RelativeSizeAxes = Axes.Both, + Texture = textures.Get(badge.ImageUrl), + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + InternalChild.FadeInFromZero(200); + } + + public string TooltipText => badge.Description; + } +} diff --git a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs index 45c1e1e208..69b1203b9f 100644 --- a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs @@ -2,14 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Users; using osuTK; @@ -17,31 +15,20 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header { - public class MedalHeaderContainer : Container + public class MedalHeaderContainer : CompositeDrawable { private FillFlowContainer badgeFlowContainer; - private User user; - - public User User - { - get => user; - set - { - if (user == value) - return; - - user = value; - - updateDisplay(); - } - } + public readonly Bindable User = new Bindable(); [BackgroundDependencyLoader] private void load(OsuColour colours) { Alpha = 0; - Children = new Drawable[] + AutoSizeAxes = Axes.Y; + User.ValueChanged += e => updateDisplay(e.NewValue); + + InternalChildren = new Drawable[] { new Box { @@ -76,9 +63,9 @@ namespace osu.Game.Overlays.Profile.Header }; } - private void updateDisplay() + private void updateDisplay(User user) { - var badges = User.Badges; + var badges = user.Badges; badgeFlowContainer.Clear(); if (badges?.Length > 0) { @@ -100,37 +87,5 @@ namespace osu.Game.Overlays.Profile.Header Hide(); } } - - private class DrawableBadge : CompositeDrawable, IHasTooltip - { - public static readonly Vector2 DRAWABLE_BADGE_SIZE = new Vector2(86, 40); - - private readonly Badge badge; - - public DrawableBadge(Badge badge) - { - this.badge = badge; - Size = DRAWABLE_BADGE_SIZE; - } - - [BackgroundDependencyLoader] - private void load(LargeTextureStore textures) - { - InternalChild = new Sprite - { - FillMode = FillMode.Fit, - RelativeSizeAxes = Axes.Both, - Texture = textures.Get(badge.ImageUrl), - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - InternalChild.FadeInFromZero(200); - } - - public string TooltipText => badge.Description; - } } } diff --git a/osu.Game/Overlays/Profile/Header/OverlinedInfoContainer.cs b/osu.Game/Overlays/Profile/Header/OverlinedInfoContainer.cs new file mode 100644 index 0000000000..6d15f96eea --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/OverlinedInfoContainer.cs @@ -0,0 +1,63 @@ +// 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.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Profile.Header +{ + public class OverlinedInfoContainer : CompositeDrawable + { + private readonly Circle line; + private readonly OsuSpriteText title, content; + + public string Title + { + set => title.Text = value; + } + + public string Content + { + set => content.Text = value; + } + + public Color4 LineColour + { + set => line.Colour = value; + } + + public OverlinedInfoContainer(bool big = false, int minimumWidth = 60) + { + AutoSizeAxes = Axes.Both; + InternalChild = new FillFlowContainer + { + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + line = new Circle + { + RelativeSizeAxes = Axes.X, + Height = 4, + }, + title = new OsuSpriteText + { + Font = OsuFont.GetFont(size: big ? 14 : 12, weight: FontWeight.Bold) + }, + content = new OsuSpriteText + { + Font = OsuFont.GetFont(size: big ? 40 : 18, weight: FontWeight.Light) + }, + new Container //Add a minimum size to the FillFlowContainer + { + Width = minimumWidth, + } + } + }; + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs b/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs new file mode 100644 index 0000000000..6d9ab7a4d8 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs @@ -0,0 +1,50 @@ +// 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.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Containers; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Profile.Header +{ + public class ProfileHeaderButton : OsuHoverContainer + { + private readonly Box background; + private readonly Container content; + + protected override Container Content => content; + + protected override IEnumerable EffectTargets => new[] { background }; + + public ProfileHeaderButton() + { + HoverColour = Color4.Black.Opacity(0.75f); + IdleColour = Color4.Black.Opacity(0.7f); + AutoSizeAxes = Axes.X; + + base.Content.Add(new CircularContainer + { + Masking = true, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + content = new Container + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = 10 }, + } + } + }); + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs index a8e50e00fe..e7c9676550 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs +++ b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs @@ -93,11 +93,11 @@ namespace osu.Game.Overlays.Profile.Header { text = new OsuSpriteText { - Margin = new MarginPadding { Bottom = 15 }, + Margin = new MarginPadding { Bottom = 10 }, Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, Text = value, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) + Font = OsuFont.GetFont() }, bar = new Circle { @@ -134,7 +134,7 @@ namespace osu.Game.Overlays.Profile.Header { text.FadeColour(AccentColour, 120, Easing.InQuad); bar.ResizeHeightTo(0, 120, Easing.InQuad); - text.Font = text.Font.With(Typeface.Exo, weight: FontWeight.Medium); + text.Font = text.Font.With(weight: FontWeight.Medium); } private void onActivated(bool fake = false) @@ -142,7 +142,7 @@ namespace osu.Game.Overlays.Profile.Header text.FadeColour(Color4.White, 120, Easing.InQuad); bar.ResizeHeightTo(7.5f, 120, Easing.InQuad); if (!fake) - text.Font = text.Font.With(Typeface.Exo, weight: FontWeight.Bold); + text.Font = text.Font.With(weight: FontWeight.Bold); } } } diff --git a/osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs b/osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs new file mode 100644 index 0000000000..a14c0324d7 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs @@ -0,0 +1,57 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Online.API; +using osu.Game.Online.Chat; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Overlays.Profile.Header +{ + public class ProfileMessageButton : ProfileHeaderButton + { + public readonly Bindable User = new Bindable(); + + [Resolved(CanBeNull = true)] + private ChannelManager channelManager { get; set; } + + [Resolved(CanBeNull = true)] + private UserProfileOverlay userOverlay { get; set; } + + [Resolved(CanBeNull = true)] + private ChatOverlay chatOverlay { get; set; } + + [Resolved] + private APIAccess apiAccess { get; set; } + + public ProfileMessageButton() + { + Content.Alpha = 0; + RelativeSizeAxes = Axes.Y; + + Child = new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.fa_envelope, + FillMode = FillMode.Fit, + Size = new Vector2(50, 14) + }; + + Action = () => + { + if (!Content.IsPresent) return; + + channelManager?.OpenPrivateChannel(User.Value); + userOverlay?.Hide(); + chatOverlay?.Show(); + }; + + User.ValueChanged += e => Content.Alpha = !e.NewValue.PMFriendsOnly && apiAccess.LocalUser.Value.Id != e.NewValue.Id ? 1 : 0; + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs index d7e25e32c2..04d6db8b3c 100644 --- a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs @@ -10,10 +10,11 @@ using osu.Game.Graphics; namespace osu.Game.Overlays.Profile.Header { - public class SupporterIcon : CircularContainer, IHasTooltip + public class SupporterIcon : CompositeDrawable, IHasTooltip { private readonly Box background; private readonly FillFlowContainer iconContainer; + private readonly CircularContainer content; public string TooltipText => "osu!supporter"; @@ -23,11 +24,11 @@ namespace osu.Game.Overlays.Profile.Header { if (value == 0) { - Hide(); + content.Hide(); } else { - Show(); + content.Show(); iconContainer.Clear(); for (int i = 0; i < value; i++) { @@ -38,43 +39,38 @@ namespace osu.Game.Overlays.Profile.Header Icon = FontAwesome.fa_heart, }); } + + iconContainer.Padding = new MarginPadding { Horizontal = DrawHeight / 2 }; } } } public SupporterIcon() { - Masking = true; AutoSizeAxes = Axes.X; - Hide(); - Children = new Drawable[] + InternalChild = content = new CircularContainer { - background = new Box { RelativeSizeAxes = Axes.Both }, - iconContainer = new FillFlowContainer + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Masking = true, + Alpha = 0, + Children = new Drawable[] { - Direction = FillDirection.Horizontal, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Height = 0.6f, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + background = new Box { RelativeSizeAxes = Axes.Both }, + iconContainer = new FillFlowContainer + { + Direction = FillDirection.Horizontal, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Height = 0.6f, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } } }; } - public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) - { - bool invalid = base.Invalidate(invalidation, source, shallPropagate); - - if ((invalidation & Invalidation.DrawSize) != 0) - { - iconContainer.Padding = new MarginPadding { Horizontal = DrawHeight / 2 }; - } - - return invalid; - } - [BackgroundDependencyLoader] private void load(OsuColour colours) { diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 13a7951170..8e4d72c702 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -14,9 +15,9 @@ using osuTK; namespace osu.Game.Overlays.Profile.Header { - public class TopHeaderContainer : Container + public class TopHeaderContainer : CompositeDrawable { - public SupporterIcon SupporterTag; + private SupporterIcon supporterTag; private UpdateableAvatar avatar; private OsuSpriteText usernameText; private ExternalLinkButton openUserExternally; @@ -27,26 +28,15 @@ namespace osu.Game.Overlays.Profile.Header private const float avatar_size = 110; - private User user; - - public User User - { - get => user; - set - { - if (user == value) - return; - - user = value; - - updateDisplay(); - } - } + public readonly Bindable User = new Bindable(); [BackgroundDependencyLoader] private void load(OsuColour colours) { - Children = new Drawable[] + Height = 150; + User.ValueChanged += e => updateDisplay(e.NewValue); + + InternalChildren = new Drawable[] { new Box { @@ -109,7 +99,7 @@ namespace osu.Game.Overlays.Profile.Header TextSize = 18, Font = "Exo2.0-Regular" }, - SupporterTag = new SupporterIcon + supporterTag = new SupporterIcon { Height = 20, Margin = new MarginPadding { Top = 5 } @@ -161,14 +151,14 @@ namespace osu.Game.Overlays.Profile.Header }; } - private void updateDisplay() + private void updateDisplay(User user) { - avatar.User = User; + avatar.User = user; usernameText.Text = user.Username; openUserExternally.Link = $@"https://osu.ppy.sh/users/{user.Id}"; userFlag.Country = user.Country; userCountryText.Text = user.Country?.FullName ?? "Alien"; - SupporterTag.SupporterLevel = user.SupportLevel; + supporterTag.SupporterLevel = user.SupportLevel; titleText.Text = user.Title; titleText.Colour = OsuColour.FromHex(user.Colour ?? "fff"); diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index fdb515270b..988fa3afd9 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -2,43 +2,31 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osuTK.Graphics; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; using osu.Framework.Bindables; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Profile { public class ProfileHeader : Container { - private readonly Container coverContainer; - private readonly OsuSpriteText coverInfoText; + private readonly UserCoverBackground coverContainer; + private readonly ScreenTitle coverTitle; private readonly ProfileHeaderTabControl infoTabControl; - private readonly TopHeaderContainer topHeaderContainer; - public SupporterIcon SupporterTag => topHeaderContainer.SupporterTag; - - private readonly CenterHeaderContainer centerHeaderContainer; - public readonly BindableBool DetailsVisible = new BindableBool(); - - private readonly DetailHeaderContainer detailHeaderContainer; - private readonly MedalHeaderContainer medalHeaderContainer; - private readonly BottomHeaderContainer bottomHeaderContainer; - private const float cover_height = 150; private const float cover_info_height = 75; public ProfileHeader() { + CenterHeaderContainer centerHeaderContainer; + DetailHeaderContainer detailHeaderContainer; Container expandedDetailContainer; FillFlowContainer hiddenDetailContainer, headerDetailContainer; SpriteIcon expandButtonIcon; @@ -48,19 +36,10 @@ namespace osu.Game.Overlays.Profile Children = new Drawable[] { - coverContainer = new Container + coverContainer = new UserCoverBackground { RelativeSizeAxes = Axes.X, Height = cover_height, - Masking = true, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.1f), Color4.Black.Opacity(0.75f)) - }, - } }, new Container { @@ -73,25 +52,10 @@ namespace osu.Game.Overlays.Profile Depth = -float.MaxValue, Children = new Drawable[] { - new FillFlowContainer + coverTitle = new ScreenTitle { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new[] - { - new OsuSpriteText - { - Text = "Player ", - Font = "Exo2.0-Regular", - TextSize = 30 - }, - coverInfoText = new OsuSpriteText - { - Text = "Info", - Font = "Exo2.0-Regular", - TextSize = 30 - } - } + Title = "Player ", + Page = "Info" }, infoTabControl = new ProfileHeaderTabControl { @@ -112,30 +76,30 @@ namespace osu.Game.Overlays.Profile Direction = FillDirection.Vertical, Children = new Drawable[] { - topHeaderContainer = new TopHeaderContainer + new TopHeaderContainer { RelativeSizeAxes = Axes.X, - Height = 150, + User = { BindTarget = User }, }, centerHeaderContainer = new CenterHeaderContainer { RelativeSizeAxes = Axes.X, - Height = 60, + User = { BindTarget = User }, }, detailHeaderContainer = new DetailHeaderContainer { RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, + User = { BindTarget = User }, }, - medalHeaderContainer = new MedalHeaderContainer + new MedalHeaderContainer { RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, + User = { BindTarget = User }, }, - bottomHeaderContainer = new BottomHeaderContainer + new BottomHeaderContainer { RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, + User = { BindTarget = User }, }, } } @@ -144,99 +108,28 @@ namespace osu.Game.Overlays.Profile infoTabControl.AddItem("Info"); infoTabControl.AddItem("Modding"); - centerHeaderContainer.DetailsVisible.BindTo(DetailsVisible); - DetailsVisible.ValueChanged += visible => detailHeaderContainer.Alpha = visible.NewValue ? 0 : 1; + centerHeaderContainer.DetailsVisibilityAction = visible => detailHeaderContainer.Alpha = visible ? 0 : 1; + User.ValueChanged += e => updateDisplay(e.NewValue); } [BackgroundDependencyLoader] private void load(OsuColour colours, TextureStore textures) { - coverInfoText.Colour = colours.CommunityUserGreen; + coverTitle.AccentColour = colours.CommunityUserGreen; infoTabControl.AccentColour = colours.CommunityUserGreen; } - private User user; + public Bindable User = new Bindable(); - public User User + private void updateDisplay(User user) { - get => user; - set - { - medalHeaderContainer.User = detailHeaderContainer.User = bottomHeaderContainer.User = - centerHeaderContainer.User = topHeaderContainer.User = user = value; - updateDisplay(); - } - } - - private void updateDisplay() - { - coverContainer.RemoveAll(d => d is UserCoverBackground); - LoadComponentAsync(new UserCoverBackground(user) - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(200), - Depth = float.MaxValue, - }, coverContainer.Add); + coverContainer.User = user; } public class HasTooltipContainer : Container, IHasTooltip { public string TooltipText { get; set; } } - - public class OverlinedInfoContainer : CompositeDrawable - { - private readonly Circle line; - private readonly OsuSpriteText title, content; - - public string Title - { - set => title.Text = value; - } - - public string Content - { - set => content.Text = value; - } - - public Color4 LineColour - { - set => line.Colour = value; - } - - public OverlinedInfoContainer(bool big = false, int minimumWidth = 60) - { - AutoSizeAxes = Axes.Both; - InternalChild = new FillFlowContainer - { - Direction = FillDirection.Vertical, - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - line = new Circle - { - RelativeSizeAxes = Axes.X, - Height = 4, - }, - title = new OsuSpriteText - { - Font = OsuFont.GetFont(size: big ? 14 : 12, weight: FontWeight.Bold) - }, - content = new OsuSpriteText - { - Font = OsuFont.GetFont(size: big ? 40 : 18, weight: FontWeight.Light) - }, - new Container //Add a minimum size to the FillFlowContainer - { - Width = minimumWidth, - } - } - }; - } - } } } diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 60e2921127..9b6e34d399 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -81,7 +81,7 @@ namespace osu.Game.Overlays Show(); - if (user.Id == Header?.User?.Id) + if (user.Id == Header?.User.Value?.Id) return; userReq?.Cancel(); @@ -167,7 +167,7 @@ namespace osu.Game.Overlays private void userLoadComplete(User user) { - Header.User = user; + Header.User.Value = user; if (user.ProfileOrder != null) { diff --git a/osu.Game/Users/UserCoverBackground.cs b/osu.Game/Users/UserCoverBackground.cs index 4c72762498..d037f809b4 100644 --- a/osu.Game/Users/UserCoverBackground.cs +++ b/osu.Game/Users/UserCoverBackground.cs @@ -1,30 +1,51 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osuTK.Graphics; namespace osu.Game.Users { - public class UserCoverBackground : Sprite + public class UserCoverBackground : ModelBackedDrawable { - private readonly User user; - - public UserCoverBackground(User user) + public User User { - this.user = user; + get => Model; + set => Model = value; } - [BackgroundDependencyLoader] - private void load(LargeTextureStore textures) - { - if (textures == null) - throw new ArgumentNullException(nameof(textures)); + [Resolved] + private LargeTextureStore textures { get; set; } - if (!string.IsNullOrEmpty(user.CoverUrl)) - Texture = textures.Get(user.CoverUrl); + protected override Drawable CreateDrawable(User user) + { + if (user == null) + { + return new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.1f), Color4.Black.Opacity(0.75f)) + }; + } + else + { + return new Sprite + { + RelativeSizeAxes = Axes.Both, + Texture = textures.Get(user.CoverUrl), + FillMode = FillMode.Fill, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + OnLoadComplete = d => d.FadeInFromZero(400), + }; + } } } } diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index cebbc74d50..def967e69b 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -73,12 +73,12 @@ namespace osu.Game.Users Children = new Drawable[] { - new DelayedLoadWrapper(new UserCoverBackground(user) + new DelayedLoadWrapper(new UserCoverBackground { RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, - FillMode = FillMode.Fill, + User = user, OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out) }, 300) { RelativeSizeAxes = Axes.Both }, new Box From 315788c97535344f84988c12a63777fbc5032620 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Mar 2019 15:11:01 +0900 Subject: [PATCH 0386/5608] Rename a few classes --- osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs | 6 +++--- osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 2 +- .../Scores/{ScoreTextLine.cs => ScoreTableHeader.cs} | 4 ++-- .../Scores/{ScoreTableLine.cs => ScoreTableRow.cs} | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) rename osu.Game/Overlays/BeatmapSet/Scores/{ScoreTextLine.cs => ScoreTableHeader.cs} (94%) rename osu.Game/Overlays/BeatmapSet/Scores/{ScoreTableLine.cs => ScoreTableRow.cs} (98%) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index a2a9f9a01b..d7396c8839 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativeSizeAxes = Axes.Both, Alpha = 0, }, - new DrawableScoreData(index, score, maxModsAmount), + new ScoreRow(index, score, maxModsAmount), }; if (index % 2 != 0) @@ -118,9 +118,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } - private class DrawableScoreData : ScoreTableLine + private class ScoreRow : ScoreTableRow { - public DrawableScoreData(int index, APIScoreInfo score, int maxModsAmount) + public ScoreRow(int index, APIScoreInfo score, int maxModsAmount) : base(maxModsAmount) { SpriteText scoreText; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 4723fcaf2b..5d248c5501 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores maxModsAmount = scoreModsAmount; } - scoresFlow.Add(new ScoreTextLine(maxModsAmount)); + scoresFlow.Add(new ScoreTableHeader(maxModsAmount)); int index = 0; foreach (var s in value) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeader.cs similarity index 94% rename from osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs rename to osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeader.cs index 9e201bd98d..544bf34ec5 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTextLine.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeader.cs @@ -5,9 +5,9 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class ScoreTextLine : ScoreTableLine + public class ScoreTableHeader : ScoreTableRow { - public ScoreTextLine(int maxModsAmount) + public ScoreTableHeader(int maxModsAmount) : base(maxModsAmount) { RankContainer.Add(new ScoreText diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableLine.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs similarity index 98% rename from osu.Game/Overlays/BeatmapSet/Scores/ScoreTableLine.cs rename to osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs index 5c4723eae1..3a48a0cca1 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableLine.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class ScoreTableLine : GridContainer + public class ScoreTableRow : GridContainer { private const float rank_position = 30; private const float drawable_rank_position = 45; @@ -36,7 +36,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores protected readonly Container PPContainer; protected readonly Container ModsContainer; - public ScoreTableLine(int maxModsAmount) + public ScoreTableRow(int maxModsAmount) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; From 92595e43f60aeb8f2c2d4308d2c9235d07bbcaa2 Mon Sep 17 00:00:00 2001 From: Santeri Nogelainen Date: Thu, 14 Mar 2019 21:57:39 +0200 Subject: [PATCH 0387/5608] slider border thickness --- .../Objects/Drawables/DrawableSlider.cs | 1 + .../Objects/Drawables/Pieces/SliderBody.cs | 35 +++++++++++++++++-- osu.Game/Skinning/LegacySkinDecoder.cs | 4 +++ osu.Game/Skinning/SkinConfiguration.cs | 2 ++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 57ea0abdd8..1e7155ced9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -160,6 +160,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.SkinChanged(skin, allowFallback); + Body.BorderSize = skin.GetValue(s => s.SliderBorderSize) ?? Body.BorderSize; Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? Body.AccentColour; Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Body.BorderColour; Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Ball.AccentColour; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 2f5c326bda..a4b27b2ee9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -64,6 +64,21 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } + /// + /// Used to size the path border. + /// + public int BorderSize { + get => path.BorderSize; + set { + if (path.BorderSize == value) + return; + + path.BorderSize = value; + + container.ForceRedraw(); + } + } + public Quad PathDrawQuad => container.ScreenSpaceDrawQuad; protected SliderBody() @@ -130,12 +145,28 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } + private int borderSize = 100; + + public int BorderSize { + get => borderSize; + set { + if (borderSize == value) + return; + + borderSize = value; + + InvalidateTexture(); + } + } + + private float calucatedBorderPortion => BorderSize / 100f * border_portion; + protected override Color4 ColourAt(float position) { - if (position <= border_portion) + if (position <= calucatedBorderPortion) return BorderColour; - position -= border_portion; + position -= calucatedBorderPortion; return new Color4(AccentColour.R, AccentColour.G, AccentColour.B, (opacity_at_edge - (opacity_at_edge - opacity_at_centre) * position / gradient_portion) * AccentColour.A); } } diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 96a9116c51..50d7191f08 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -33,6 +33,10 @@ namespace osu.Game.Skinning case @"CursorExpand": skin.CursorExpand = pair.Value != "0"; break; + case @"SliderBorderSize": + if (int.TryParse(pair.Value, out int size)) + skin.SliderBorderSize = size; + break; } break; diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index 82faec4e9d..bd6393db36 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -25,6 +25,8 @@ namespace osu.Game.Skinning public int HitCircleOverlap { get; set; } + public int? SliderBorderSize { get; set; } + public bool? CursorExpand { get; set; } = true; } } From cbb7498a42d6311b94ca07f939fb72dd0c7ac532 Mon Sep 17 00:00:00 2001 From: Santeri Nogelainen Date: Sat, 16 Mar 2019 12:41:03 +0200 Subject: [PATCH 0388/5608] Border size to float, add min and max size, other small changes --- .../Objects/Drawables/DrawableSlider.cs | 2 +- .../Objects/Drawables/Pieces/SliderBody.cs | 20 +++++++++++++------ osu.Game/Skinning/LegacySkinDecoder.cs | 4 +++- osu.Game/Skinning/SkinConfiguration.cs | 2 +- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 1e7155ced9..d76612e26d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -160,7 +160,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.SkinChanged(skin, allowFallback); - Body.BorderSize = skin.GetValue(s => s.SliderBorderSize) ?? Body.BorderSize; + Body.BorderSize = skin.GetValue(s => s.SliderBorderSize) ?? Body.BorderSize; Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? Body.AccentColour; Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Body.BorderColour; Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Ball.AccentColour; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index a4b27b2ee9..9340d32bd9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -67,7 +67,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces /// /// Used to size the path border. /// - public int BorderSize { + public float BorderSize + { get => path.BorderSize; set { if (path.BorderSize == value) @@ -107,6 +108,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private class SliderPath : SmoothPath { + private const float border_max_size = 10f; + private const float border_min_size = 0f; // = no border + private const float border_portion = 0.128f; private const float gradient_portion = 1 - border_portion; @@ -145,28 +149,32 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } - private int borderSize = 100; + private float borderSize = 1f; - public int BorderSize { + public float BorderSize + { get => borderSize; set { if (borderSize == value) return; + if (value < border_min_size || value > border_max_size) + return; + borderSize = value; InvalidateTexture(); } } - private float calucatedBorderPortion => BorderSize / 100f * border_portion; + private float calculatedBorderPortion => BorderSize * border_portion; protected override Color4 ColourAt(float position) { - if (position <= calucatedBorderPortion) + if (calculatedBorderPortion != 0f && position <= calculatedBorderPortion) return BorderColour; - position -= calucatedBorderPortion; + position -= calculatedBorderPortion; return new Color4(AccentColour.R, AccentColour.G, AccentColour.B, (opacity_at_edge - (opacity_at_edge - opacity_at_centre) * position / gradient_portion) * AccentColour.A); } } diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 50d7191f08..1f530de4fb 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps.Formats; +using System; +using System.Globalization; namespace osu.Game.Skinning { @@ -34,7 +36,7 @@ namespace osu.Game.Skinning skin.CursorExpand = pair.Value != "0"; break; case @"SliderBorderSize": - if (int.TryParse(pair.Value, out int size)) + if (Single.TryParse(pair.Value, NumberStyles.Number, CultureInfo.CreateSpecificCulture("en-US"), out float size)) skin.SliderBorderSize = size; break; } diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index bd6393db36..043622f8ce 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -25,7 +25,7 @@ namespace osu.Game.Skinning public int HitCircleOverlap { get; set; } - public int? SliderBorderSize { get; set; } + public float? SliderBorderSize { get; set; } public bool? CursorExpand { get; set; } = true; } From b624ecabde67901b254a67a7037a6f1bb54c1cfe Mon Sep 17 00:00:00 2001 From: Santeri Nogelainen Date: Sat, 16 Mar 2019 12:47:37 +0200 Subject: [PATCH 0389/5608] Max = 8 --- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 9340d32bd9..b99f79afcb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -108,8 +108,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private class SliderPath : SmoothPath { - private const float border_max_size = 10f; - private const float border_min_size = 0f; // = no border + private const float border_max_size = 8f; + private const float border_min_size = 0f; private const float border_portion = 0.128f; private const float gradient_portion = 1 - border_portion; From c0471019ffa0605752d601eb519ad68189307bc8 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Sun, 17 Mar 2019 09:39:07 -0500 Subject: [PATCH 0390/5608] Very minor changes --- osu.Android/OsuGameActivity.cs | 4 +--- osu.Android/OsuGameAndroid.cs | 14 ++++++++++++++ osu.Android/osu.Android.csproj | 4 +--- 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 osu.Android/OsuGameAndroid.cs diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index 130144d417..4623402b1a 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.cs @@ -6,15 +6,13 @@ using Android.Content.PM; using Android.OS; using Android.Views; using osu.Framework.Android; -using osu.Game; namespace osu.Android { [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize, HardwareAccelerated = true)] public class OsuGameActivity : AndroidGameActivity { - protected override Framework.Game CreateGame() - => new OsuGame(); + protected override Framework.Game CreateGame() => new OsuGameAndroid(); protected override void OnCreate(Bundle savedInstanceState) { diff --git a/osu.Android/OsuGameAndroid.cs b/osu.Android/OsuGameAndroid.cs new file mode 100644 index 0000000000..d9bdd9c0c2 --- /dev/null +++ b/osu.Android/OsuGameAndroid.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 System; +using Android.App; +using osu.Game; + +namespace osu.Android +{ + public class OsuGameAndroid : OsuGame + { + public override Version AssemblyVersion => new Version(Application.Context.ApplicationContext.PackageManager.GetPackageInfo(Application.Context.ApplicationContext.PackageName, 0).VersionName); + } +} diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 45ff8ba31a..6a859742ee 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -13,11 +13,9 @@ osu.Android Properties\AndroidManifest.xml - - true - + From c6c98257f2022a0d62b46114b6aa281633729652 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Sun, 17 Mar 2019 09:45:01 -0500 Subject: [PATCH 0391/5608] Add internet permission, update Android framework --- osu.Android.props | 2 +- osu.Android/Properties/AndroidManifest.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index da3abeb446..e320c45ea9 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -64,6 +64,6 @@ - + diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index c053ced9e2..549ba9f46a 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -5,5 +5,6 @@ + \ No newline at end of file From 41d25c7d19d6d7babd2c0194d77fc68bf8dcfc2b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 20 Mar 2019 17:15:21 +0900 Subject: [PATCH 0392/5608] Fix post-merge errors --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 6c90e192ac..79858a9ccb 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly LoadingAnimation loadingAnimation; [Resolved] - private APIAccess api { get; set; } + private IAPIProvider api { get; set; } public ScoresContainer() { @@ -71,7 +71,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } [BackgroundDependencyLoader] - private void load(APIAccess api, OsuColour colours) + private void load(OsuColour colours) { background.Colour = colours.Gray2; updateDisplay(); From f7016e1d2c81b4ab675c3a654ca3695bbf1265b5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 20 Mar 2019 17:15:38 +0900 Subject: [PATCH 0393/5608] Rename DrawableScore --- osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs | 2 +- osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 2 +- .../Scores/{DrawableScore.cs => ScoreTableScore.cs} | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game/Overlays/BeatmapSet/Scores/{DrawableScore.cs => ScoreTableScore.cs} (98%) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs index 20609dc595..58ccaf9dfa 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual { typeof(Header), typeof(ClickableUserContainer), - typeof(DrawableScore), + typeof(ScoreTableScore), typeof(DrawableTopScore), typeof(ScoresContainer), typeof(AuthorInfo), diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 5d248c5501..aacbc12cd8 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores int index = 0; foreach (var s in value) - scoresFlow.Add(new DrawableScore(index++, s, maxModsAmount)); + scoresFlow.Add(new ScoreTableScore(index++, s, maxModsAmount)); } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScore.cs similarity index 98% rename from osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs rename to osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScore.cs index d7396c8839..a54770fb39 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScore.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class DrawableScore : Container + public class ScoreTableScore : Container { private const int fade_duration = 100; private const int text_size = 14; @@ -27,7 +27,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly Box hoveredBackground; private readonly Box background; - public DrawableScore(int index, APIScoreInfo score, int maxModsAmount) + public ScoreTableScore(int index, APIScoreInfo score, int maxModsAmount) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; From edfc0368ac3fdb155847b8e8a1c713a7f6d3cba5 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Wed, 20 Mar 2019 11:34:12 -0500 Subject: [PATCH 0394/5608] Update Android framework --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index e320c45ea9..028b4bda83 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -64,6 +64,6 @@ - + From e93311fdc9e2372e262e5fb9f4cd496ec53f5798 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 22 Mar 2019 19:01:32 +0900 Subject: [PATCH 0395/5608] DI facade --- .../Graphics/Containers/FacadeContainer.cs | 30 +++++++++++++++++++ osu.Game/Screens/Play/PlayerLoader.cs | 14 ++++++--- 2 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Graphics/Containers/FacadeContainer.cs diff --git a/osu.Game/Graphics/Containers/FacadeContainer.cs b/osu.Game/Graphics/Containers/FacadeContainer.cs new file mode 100644 index 0000000000..7d7a4b0680 --- /dev/null +++ b/osu.Game/Graphics/Containers/FacadeContainer.cs @@ -0,0 +1,30 @@ +// 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.Containers; +using osu.Game.Screens.Menu; +using osuTK; + +namespace osu.Game.Graphics.Containers +{ + public class FacadeContainer : Container + { + [Cached] + private Facade facade; + + public FacadeContainer() + { + facade = new Facade(); + } + + public void SetLogo(OsuLogo logo) + { + facade.Size = new Vector2(logo.SizeForFlow); + } + } + + public class Facade : Container + { + } +} diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index e9ee5d3fa8..878c2541e9 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -14,6 +14,7 @@ using osu.Framework.Screens; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Menu; @@ -32,7 +33,7 @@ namespace osu.Game.Screens.Play private Player player; - private Container content; + private FacadeContainer content; private BeatmapMetadataDisplay info; @@ -59,7 +60,7 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load() { - InternalChild = content = new Container + InternalChild = content = new FacadeContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -153,6 +154,8 @@ namespace osu.Game.Screens.Play logo.FadeIn(350); logo.Delay(resuming ? 0 : 500).MoveToOffset(new Vector2(0, -0.24f), 500, Easing.InOutExpo); + + content.SetLogo(logo); } protected override void LoadComplete() @@ -302,6 +305,8 @@ namespace osu.Game.Screens.Play private LoadingAnimation loading; private Sprite backgroundSprite; private ModDisplay modDisplay; + private FillFlowContainer fillFlowContainer; + private FacadeContainer facadeContainer; public bool Loading { @@ -326,14 +331,14 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load() + private void load(Facade facade) { var metadata = beatmap.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); AutoSizeAxes = Axes.Both; Children = new Drawable[] { - new FillFlowContainer + fillFlowContainer = new FillFlowContainer { AutoSizeAxes = Axes.Both, Origin = Anchor.TopCentre, @@ -341,6 +346,7 @@ namespace osu.Game.Screens.Play Direction = FillDirection.Vertical, Children = new Drawable[] { + facade, new OsuSpriteText { Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)), From 6e98a8dd7c15ff372a39ebf9b7785b0c6e16a755 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 22 Mar 2019 20:01:58 +0900 Subject: [PATCH 0396/5608] Initial implementation --- osu.Game.Tests/Visual/TestCasePlayerLoader.cs | 10 +++- .../Graphics/Containers/FacadeContainer.cs | 53 ++++++++++++++++++- osu.Game/Screens/Play/PlayerLoader.cs | 13 +++-- 3 files changed, 67 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/TestCasePlayerLoader.cs index 2bc416f7f4..ad0965b4d6 100644 --- a/osu.Game.Tests/Visual/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/TestCasePlayerLoader.cs @@ -7,7 +7,9 @@ using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Screens; +using osu.Game.Screens.Menu; using osu.Game.Screens.Play; +using osuTK; namespace osu.Game.Tests.Visual { @@ -16,6 +18,9 @@ namespace osu.Game.Tests.Visual private PlayerLoader loader; private readonly ScreenStack stack; + [Cached] + private OsuLogo logo; + [Cached] private BackgroundScreenStack backgroundStack; @@ -23,6 +28,7 @@ namespace osu.Game.Tests.Visual { InputManager.Add(backgroundStack = new BackgroundScreenStack { RelativeSizeAxes = Axes.Both }); InputManager.Add(stack = new ScreenStack { RelativeSizeAxes = Axes.Both }); + InputManager.Add(logo = new OsuLogo()); } [BackgroundDependencyLoader] @@ -30,6 +36,8 @@ namespace osu.Game.Tests.Visual { Beatmap.Value = new DummyWorkingBeatmap(game); + AddStep("Reset logo position", () => logo = new OsuLogo { Position = new Vector2(0, 0) }); + AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => new Player { AllowPause = false, @@ -57,8 +65,6 @@ namespace osu.Game.Tests.Visual AllowLeadIn = false, AllowResults = false, })); - - Scheduler.AddDelayed(() => slow.Ready = true, 5000); }); AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen()); diff --git a/osu.Game/Graphics/Containers/FacadeContainer.cs b/osu.Game/Graphics/Containers/FacadeContainer.cs index 7d7a4b0680..e39fba64ce 100644 --- a/osu.Game/Graphics/Containers/FacadeContainer.cs +++ b/osu.Game/Graphics/Containers/FacadeContainer.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Screens.Menu; using osuTK; @@ -13,14 +14,62 @@ namespace osu.Game.Graphics.Containers [Cached] private Facade facade; + private OsuLogo logo; + + private bool tracking; + private bool smoothTransform; + public FacadeContainer() { facade = new Facade(); } - public void SetLogo(OsuLogo logo) + private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(facade.ScreenSpaceDrawQuad.Centre); + + public void SetLogo(OsuLogo logo, bool resuming, double transformDelay) { - facade.Size = new Vector2(logo.SizeForFlow); + if (logo != null) + { + facade.Size = new Vector2(logo.SizeForFlow * 0.3f); + this.logo = logo; + Scheduler.AddDelayed(() => + { + tracking = true; + smoothTransform = !resuming; + }, transformDelay); + } + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + facade.Size = new Vector2(logo.SizeForFlow * 0.3f); + + if (!tracking) + return; + + logo.RelativePositionAxes = Axes.None; + + bool childrenLoaded = true; + + foreach (var d in Children) + { + if (!d.IsAlive) + childrenLoaded = false; + } + + if (smoothTransform && childrenLoaded) + { + // Our initial movement to the tracking location should be smooth. + Schedule(() => logo.MoveTo(logoTrackingPosition, 500, Easing.InOutExpo)); + smoothTransform = false; + } + else if (logo.Transforms.Count == 0) + { + // If all transforms have finished playing, the logo constantly track the position of the facade. + logo.Position = logoTrackingPosition; + } } } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 878c2541e9..97249ee6cd 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -149,13 +149,13 @@ namespace osu.Game.Screens.Play { base.LogoArriving(logo, resuming); - logo.ScaleTo(new Vector2(0.15f), 300, Easing.In); - logo.MoveTo(new Vector2(0.5f), 300, Easing.In); + const double duration = 300; + + logo.ScaleTo(new Vector2(0.15f), duration, Easing.In); + logo.MoveTo(new Vector2(0.5f), duration, Easing.In); logo.FadeIn(350); - logo.Delay(resuming ? 0 : 500).MoveToOffset(new Vector2(0, -0.24f), 500, Easing.InOutExpo); - - content.SetLogo(logo); + content.SetLogo(logo, resuming, duration); } protected override void LoadComplete() @@ -335,6 +335,9 @@ namespace osu.Game.Screens.Play { var metadata = beatmap.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); + facade.Anchor = Anchor.TopCentre; + facade.Origin = Anchor.TopCentre; + AutoSizeAxes = Axes.Both; Children = new Drawable[] { From d37968d88df2ad6f6f0a6f64596212df28bfabde Mon Sep 17 00:00:00 2001 From: David Zhao Date: Sun, 24 Mar 2019 15:18:38 +0900 Subject: [PATCH 0397/5608] Add better test for facade containers --- .../Visual/TestCaseFacadeContainer.cs | 113 ++++++++++++++++++ .../Graphics/Containers/FacadeContainer.cs | 33 +++-- osu.Game/Screens/Play/PlayerLoader.cs | 46 +++---- 3 files changed, 152 insertions(+), 40 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseFacadeContainer.cs diff --git a/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs new file mode 100644 index 0000000000..3063a4ca3f --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs @@ -0,0 +1,113 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Testing; +using osu.Game.Configuration; +using osu.Game.Graphics.Containers; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Screens; +using osu.Game.Screens.Menu; +using osu.Game.Screens.Play; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseFacadeContainer : ScreenTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(PlayerLoader), + typeof(Player), + typeof(Facade), + }; + + [Cached] + private OsuLogo logo; + + private readonly Bindable uiScale = new Bindable(); + + private OsuScreen baseScreen; + + public TestCaseFacadeContainer() + { + Add(logo = new OsuLogo()); + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + baseScreen = null; + config.BindWith(OsuSetting.UIScale, uiScale); + AddSliderStep("Adjust scale", 1f, 1.5f, 1f, v => uiScale.Value = v); + AddToggleStep("Toggle mods", b => { Beatmap.Value.Mods.Value = b ? Beatmap.Value.Mods.Value.Concat(new[] { new OsuModNoFail() }) : Enumerable.Empty(); }); + } + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("Null screens", () => baseScreen = null); + } + + [Test] + public void PlayerLoaderTest() + { + AddStep("Add new playerloader", () => LoadScreen(baseScreen = new TestPlayerLoader(() => new TestPlayer + { + AllowPause = false, + AllowLeadIn = false, + AllowResults = false, + }))); + } + + [Test] + public void MainMenuTest() + { + AddStep("Add new Main Menu", () => LoadScreen(baseScreen = new MainMenu())); + } + + private class TestFacadeContainer : FacadeContainer + { + protected override Facade CreateFacade() => new Facade + { + Colour = Color4.Tomato, + Alpha = 0.35f, + Child = new Box + { + Colour = Color4.Tomato, + RelativeSizeAxes = Axes.Both, + }, + }; + } + + private class TestPlayerLoader : PlayerLoader + { + public TestPlayerLoader(Func player) + : base(player) + { + } + + protected override FacadeContainer CreateFacadeContainer() => new TestFacadeContainer(); + } + + private class TestPlayer : Player + { + [BackgroundDependencyLoader] + private void load() + { + // Never finish loading + while (true) + Thread.Sleep(1); + } + } + } +} diff --git a/osu.Game/Graphics/Containers/FacadeContainer.cs b/osu.Game/Graphics/Containers/FacadeContainer.cs index e39fba64ce..d7fae8887f 100644 --- a/osu.Game/Graphics/Containers/FacadeContainer.cs +++ b/osu.Game/Graphics/Containers/FacadeContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -19,9 +20,11 @@ namespace osu.Game.Graphics.Containers private bool tracking; private bool smoothTransform; + protected virtual Facade CreateFacade() => new Facade(); + public FacadeContainer() { - facade = new Facade(); + facade = CreateFacade(); } private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(facade.ScreenSpaceDrawQuad.Centre); @@ -44,30 +47,26 @@ namespace osu.Game.Graphics.Containers { base.UpdateAfterChildren(); - facade.Size = new Vector2(logo.SizeForFlow * 0.3f); - - if (!tracking) + if (logo == null) return; - logo.RelativePositionAxes = Axes.None; + facade.Size = new Vector2(logo.SizeForFlow * 0.3f); - bool childrenLoaded = true; - - foreach (var d in Children) - { - if (!d.IsAlive) - childrenLoaded = false; - } - - if (smoothTransform && childrenLoaded) + if (smoothTransform && facade.IsLoaded && logo.Transforms.Count == 0) { // Our initial movement to the tracking location should be smooth. - Schedule(() => logo.MoveTo(logoTrackingPosition, 500, Easing.InOutExpo)); - smoothTransform = false; + Schedule(() => + { + facade.Size = new Vector2(logo.SizeForFlow * 0.3f); + logo.RelativePositionAxes = Axes.None; + logo.MoveTo(logoTrackingPosition, 500, Easing.InOutExpo); + smoothTransform = false; + }); } - else if (logo.Transforms.Count == 0) + else if (facade.IsLoaded && logo.Transforms.Count == 0) { // If all transforms have finished playing, the logo constantly track the position of the facade. + logo.RelativePositionAxes = Axes.None; logo.Position = logoTrackingPosition; } } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 97249ee6cd..5817e11277 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -35,6 +35,8 @@ namespace osu.Game.Screens.Play private FacadeContainer content; + protected virtual FacadeContainer CreateFacadeContainer() => new FacadeContainer(); + private BeatmapMetadataDisplay info; private bool hideOverlays; @@ -60,32 +62,30 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load() { - InternalChild = content = new FacadeContainer + InternalChild = content = CreateFacadeContainer(); + content.Anchor = Anchor.Centre; + content.Origin = Anchor.Centre; + content.RelativeSizeAxes = Axes.Both; + content.Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + info = new BeatmapMetadataDisplay(Beatmap.Value) { - info = new BeatmapMetadataDisplay(Beatmap.Value) + Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), + Margin = new MarginPadding(25), + Children = new PlayerSettingsGroup[] { - Alpha = 0, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - new FillFlowContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 20), - Margin = new MarginPadding(25), - Children = new PlayerSettingsGroup[] - { - VisualSettings = new VisualSettings(), - new InputSettings() - } + VisualSettings = new VisualSettings(), + new InputSettings() } } }; From bc16a82494582f0d6c3f294ae3dc7f89e9cd07fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Mar 2019 17:39:53 +0900 Subject: [PATCH 0398/5608] Move osu! cursor to its own class --- .../UI/Cursor/GameplayCursorContainer.cs | 140 ----------------- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs | 148 ++++++++++++++++++ 2 files changed, 148 insertions(+), 140 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs index 8c6723f5be..b64561e4f7 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs @@ -1,19 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; -using osu.Game.Beatmaps; -using osu.Game.Configuration; -using osu.Game.Skinning; -using osuTK; -using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.UI.Cursor { @@ -88,136 +79,5 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint); ActiveCursor.ScaleTo(0.8f, 450, Easing.OutQuint); } - - public class OsuCursor : SkinReloadableDrawable - { - private bool cursorExpand; - - private Bindable cursorScale; - private Bindable autoCursorScale; - private readonly IBindable beatmap = new Bindable(); - - private Container expandTarget; - private Drawable scaleTarget; - - public OsuCursor() - { - Origin = Anchor.Centre; - Size = new Vector2(28); - } - - protected override void SkinChanged(ISkinSource skin, bool allowFallback) - { - cursorExpand = skin.GetValue(s => s.CursorExpand ?? true); - } - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config, IBindable beatmap) - { - InternalChild = expandTarget = new Container - { - RelativeSizeAxes = Axes.Both, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Child = scaleTarget = new SkinnableDrawable("cursor", _ => new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = Size.X / 6, - BorderColour = Color4.White, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Pink.Opacity(0.5f), - Radius = 5, - }, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true, - }, - new CircularContainer - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = Size.X / 3, - BorderColour = Color4.White.Opacity(0.5f), - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true, - }, - }, - }, - new CircularContainer - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.1f), - Masking = true, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.White, - }, - }, - }, - } - }, restrictSize: false) - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - } - }; - - this.beatmap.BindTo(beatmap); - this.beatmap.ValueChanged += _ => calculateScale(); - - cursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); - cursorScale.ValueChanged += _ => calculateScale(); - - autoCursorScale = config.GetBindable(OsuSetting.AutoCursorSize); - autoCursorScale.ValueChanged += _ => calculateScale(); - - calculateScale(); - } - - private void calculateScale() - { - float scale = (float)cursorScale.Value; - - if (autoCursorScale.Value && beatmap.Value != null) - { - // if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier. - scale *= (float)(1 - 0.7 * (1 + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY); - } - - scaleTarget.Scale = new Vector2(scale); - } - - private const float pressed_scale = 1.2f; - private const float released_scale = 1f; - - public void Expand() - { - if (!cursorExpand) return; - - expandTarget.ScaleTo(released_scale).ScaleTo(pressed_scale, 100, Easing.OutQuad); - } - - public void Contract() => expandTarget.ScaleTo(released_scale, 100, Easing.OutQuad); - } } } diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs new file mode 100644 index 0000000000..ecdafb0fa2 --- /dev/null +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.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 osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.UI.Cursor +{ + public class OsuCursor : SkinReloadableDrawable + { + private bool cursorExpand; + + private Bindable cursorScale; + private Bindable autoCursorScale; + private readonly IBindable beatmap = new Bindable(); + + private Container expandTarget; + private Drawable scaleTarget; + + public OsuCursor() + { + Origin = Anchor.Centre; + Size = new Vector2(28); + } + + protected override void SkinChanged(ISkinSource skin, bool allowFallback) + { + cursorExpand = skin.GetValue(s => s.CursorExpand ?? true); + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config, IBindable beatmap) + { + InternalChild = expandTarget = new Container + { + RelativeSizeAxes = Axes.Both, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Child = scaleTarget = new SkinnableDrawable("cursor", _ => new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = Size.X / 6, + BorderColour = Color4.White, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Pink.Opacity(0.5f), + Radius = 5, + }, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true, + }, + new CircularContainer + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = Size.X / 3, + BorderColour = Color4.White.Opacity(0.5f), + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true, + }, + }, + }, + new CircularContainer + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.1f), + Masking = true, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }, + }, + }, + } + }, restrictSize: false) + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + } + }; + + this.beatmap.BindTo(beatmap); + this.beatmap.ValueChanged += _ => calculateScale(); + + cursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); + cursorScale.ValueChanged += _ => calculateScale(); + + autoCursorScale = config.GetBindable(OsuSetting.AutoCursorSize); + autoCursorScale.ValueChanged += _ => calculateScale(); + + calculateScale(); + } + + private void calculateScale() + { + float scale = (float)cursorScale.Value; + + if (autoCursorScale.Value && beatmap.Value != null) + { + // if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier. + scale *= (float)(1 - 0.7 * (1 + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY); + } + + scaleTarget.Scale = new Vector2(scale); + } + + private const float pressed_scale = 1.2f; + private const float released_scale = 1f; + + public void Expand() + { + if (!cursorExpand) return; + + expandTarget.ScaleTo(released_scale).ScaleTo(pressed_scale, 100, Easing.OutQuad); + } + + public void Contract() => expandTarget.ScaleTo(released_scale, 100, Easing.OutQuad); + } +} From 8ad4009c33d5c0f9984d85cfb26ed69dcf0b6eec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Mar 2019 19:04:07 +0900 Subject: [PATCH 0399/5608] osu! resume overlay --- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 105 +++++++++++++++++++ osu.Game/Screens/Play/ResumeOverlay.cs | 74 +++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs create mode 100644 osu.Game/Screens/Play/ResumeOverlay.cs diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs new file mode 100644 index 0000000000..c2000131db --- /dev/null +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -0,0 +1,105 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Rulesets.Osu.UI.Cursor; +using osu.Game.Screens.Play; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.UI +{ + public class OsuResumeOverlay : ResumeOverlay + { + private OsuClickToResumeCursor clickToResumeCursor; + + private GameplayCursorContainer localCursorContainer; + + public override CursorContainer LocalCursor => State == Visibility.Visible ? localCursorContainer : null; + + protected override string Message => "Click the orange cursor to resume"; + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Add(clickToResumeCursor = new OsuClickToResumeCursor { ResumeRequested = Resume }); + } + + public override void Show() + { + base.Show(); + clickToResumeCursor.ShowAt(GameplayCursor.ActiveCursor.Position); + Add(localCursorContainer = new GameplayCursorContainer()); + } + + public override void Hide() + { + localCursorContainer.Expire(); + base.Hide(); + } + + protected override bool OnHover(HoverEvent e) => true; + + public class OsuClickToResumeCursor : OsuCursor, IKeyBindingHandler + { + public override bool HandlePositionalInput => true; + + public Action ResumeRequested; + + public OsuClickToResumeCursor() + { + RelativePositionAxes = Axes.Both; + } + + protected override bool OnHover(HoverEvent e) + { + updateColour(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateColour(); + base.OnHoverLost(e); + } + + public bool OnPressed(OsuAction action) + { + switch (action) + { + case OsuAction.LeftButton: + case OsuAction.RightButton: + if (!IsHovered) return false; + + this.ScaleTo(new Vector2(2), TRANSITION_TIME, Easing.OutQuint); + + ResumeRequested?.Invoke(); + return true; + } + + return false; + } + + public bool OnReleased(OsuAction action) => false; + + public void ShowAt(Vector2 activeCursorPosition) => Schedule(() => + { + updateColour(); + this.MoveTo(activeCursorPosition); + this.ScaleTo(new Vector2(4)).Then().ScaleTo(Vector2.One, 1000, Easing.OutQuint); + }); + + private void updateColour() + { + this.FadeColour(IsHovered ? Color4.White : Color4.Orange, 400, Easing.OutQuint); + } + } + } +} diff --git a/osu.Game/Screens/Play/ResumeOverlay.cs b/osu.Game/Screens/Play/ResumeOverlay.cs new file mode 100644 index 0000000000..2ef76069c2 --- /dev/null +++ b/osu.Game/Screens/Play/ResumeOverlay.cs @@ -0,0 +1,74 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Play +{ + /// + /// An overlay which can be used to require further user actions before gameplay is resumed. + /// + public abstract class ResumeOverlay : OverlayContainer + { + public CursorContainer GameplayCursor { get; set; } + + /// + /// The action to be performed to complete resuming. + /// + public Action ResumeAction { private get; set; } + + public virtual CursorContainer LocalCursor => null; + + protected const float TRANSITION_TIME = 500; + + protected override bool BlockPositionalInput => false; + + protected abstract string Message { get; } + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + + protected ResumeOverlay() + { + RelativeSizeAxes = Axes.Both; + } + + protected void Resume() + { + ResumeAction?.Invoke(); + Hide(); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AddRange(new Drawable[] + { + new OsuSpriteText + { + RelativePositionAxes = Axes.Both, + Y = 0.4f, + Text = Message, + Font = OsuFont.GetFont(size: 30), + Spacing = new Vector2(5, 0), + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Colour = colours.Yellow, + Shadow = true, + ShadowColour = new Color4(0, 0, 0, 0.25f) + } + }); + } + + protected override void PopIn() => this.FadeIn(TRANSITION_TIME, Easing.OutQuint); + + protected override void PopOut() => this.FadeOut(TRANSITION_TIME, Easing.OutQuint); + } +} From a694626cc66780e6527c3d843b5789d197f8c0b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Mar 2019 16:57:40 +0900 Subject: [PATCH 0400/5608] Add proper resume request logic --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 31c0afd743..ab10c48ce0 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -169,7 +169,20 @@ namespace osu.Game.Rulesets.UI mod.ApplyToDrawableHitObjects(Playfield.HitObjectContainer.Objects); } - public override void RequestResume(Action continueResume) => continueResume(); + public override void RequestResume(Action continueResume) + { + if (ResumeOverlay != null && (Cursor == null || Contains(Cursor.ActiveCursor.ScreenSpaceDrawQuad.Centre))) + { + ResumeOverlay.ResumeAction = continueResume; + ResumeOverlay.Show(); + } + else + continueResume(); + } + + public ResumeOverlay ResumeOverlay { get; private set; } + + protected virtual ResumeOverlay CreateResumeOverlay() => null; /// /// Creates and adds the visual representation of a to this . From 57b3b7b54b8ed092b02f770aaf99f9a2c79c4a8e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Mar 2019 11:55:05 +0900 Subject: [PATCH 0401/5608] Add back resume overlay --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index ab10c48ce0..4c0bc9867b 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -138,7 +138,8 @@ namespace osu.Game.Rulesets.UI { KeyBindingInputManager.AddRange(new Drawable[] { - Playfield + Playfield, + (ResumeOverlay = CreateResumeOverlay()) ?? new Container() }); InternalChildren = new Drawable[] From 650a5c993a176022c410d5f35cd1c60923f9d170 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2019 15:30:51 +0900 Subject: [PATCH 0402/5608] Add test --- .../TestCaseResumeOverlay.cs | 70 +++++++++++++++++++ osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 3 +- 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestCaseResumeOverlay.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseResumeOverlay.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseResumeOverlay.cs new file mode 100644 index 0000000000..5956f12146 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseResumeOverlay.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; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Screens.Play; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestCaseResumeOverlay : ManualInputManagerTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuResumeOverlay), + }; + + public TestCaseResumeOverlay() + { + ManualOsuInputManager osuInputManager; + CursorContainer cursor; + ResumeOverlay resume; + + bool resumeFired = false; + + Child = osuInputManager = new ManualOsuInputManager(new OsuRuleset().RulesetInfo) + { + Children = new Drawable[] + { + cursor = new CursorContainer(), + resume = new OsuResumeOverlay + { + GameplayCursor = cursor + }, + } + }; + + resume.ResumeAction = () => resumeFired = true; + + AddStep("move mouse to center", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.Centre)); + AddStep("show", () => resume.Show()); + + AddStep("move mouse away", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.TopLeft)); + AddStep("click", () => osuInputManager.GameClick()); + AddAssert("not dismissed", () => !resumeFired && resume.State == Visibility.Visible); + + AddStep("move mouse back", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.Centre)); + AddStep("click", () => osuInputManager.GameClick()); + AddAssert("dismissed", () => resumeFired && resume.State == Visibility.Hidden); + } + + private class ManualOsuInputManager : OsuInputManager + { + public ManualOsuInputManager(RulesetInfo ruleset) + : base(ruleset) + { + } + + public void GameClick() + { + KeyBindingContainer.TriggerPressed(OsuAction.LeftButton); + KeyBindingContainer.TriggerReleased(OsuAction.LeftButton); + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index c2000131db..9829839841 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; -using osu.Game.Graphics; using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Screens.Play; using osuTK; @@ -27,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.UI protected override string Message => "Click the orange cursor to resume"; [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { Add(clickToResumeCursor = new OsuClickToResumeCursor { ResumeRequested = Resume }); } From 38e481686f03c50c50c958a5c9b71175f4e44218 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2019 19:21:01 +0900 Subject: [PATCH 0403/5608] Make PlayfieldAdjustmentContainer universal --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 34 +-- ...s => CatchPlayfieldAdjustmentContainer.cs} | 10 +- .../UI/DrawableCatchRuleset.cs | 2 + .../UI/DrawableManiaRuleset.cs | 9 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 - .../UI/ManiaPlayfieldAdjustmentContainer.cs | 20 ++ .../Edit/OsuHitObjectComposer.cs | 2 +- .../UI/DrawableOsuRuleset.cs | 5 +- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 45 ++- ....cs => OsuPlayfieldAdjustmentContainer.cs} | 10 +- .../UI/DrawableTaikoRuleset.cs | 2 + osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 256 +++++++++--------- ...s => TaikoPlayfieldAdjustmentContainer.cs} | 11 +- osu.Game/Rulesets/UI/DrawableRuleset.cs | 15 +- .../UI/PlayfieldAdjustmentContainer.cs | 19 ++ 15 files changed, 236 insertions(+), 206 deletions(-) rename osu.Game.Rulesets.Catch/UI/{PlayfieldAdjustmentContainer.cs => CatchPlayfieldAdjustmentContainer.cs} (78%) create mode 100644 osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs rename osu.Game.Rulesets.Osu/UI/{PlayfieldAdjustmentContainer.cs => OsuPlayfieldAdjustmentContainer.cs} (82%) rename osu.Game.Rulesets.Taiko/UI/{PlayfieldAdjustmentContainer.cs => TaikoPlayfieldAdjustmentContainer.cs} (68%) create mode 100644 osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 4dae95b53c..43d0dc026d 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -10,7 +10,6 @@ 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 { @@ -24,29 +23,20 @@ namespace osu.Game.Rulesets.Catch.UI { Container explodingFruitContainer; - Anchor = Anchor.TopCentre; - Origin = Anchor.TopCentre; - - Size = new Vector2(0.86f); // matches stable's vertical offset for catcher plate - - InternalChild = new PlayfieldAdjustmentContainer + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + explodingFruitContainer = new Container { - explodingFruitContainer = new Container - { - RelativeSizeAxes = Axes.Both, - }, - CatcherArea = new CatcherArea(difficulty) - { - GetVisualRepresentation = getVisualRepresentation, - ExplodingFruitTarget = explodingFruitContainer, - Anchor = Anchor.BottomLeft, - Origin = Anchor.TopLeft, - }, - HitObjectContainer - } + RelativeSizeAxes = Axes.Both, + }, + CatcherArea = new CatcherArea(difficulty) + { + GetVisualRepresentation = getVisualRepresentation, + ExplodingFruitTarget = explodingFruitContainer, + Anchor = Anchor.BottomLeft, + Origin = Anchor.TopLeft, + }, + HitObjectContainer }; } diff --git a/osu.Game.Rulesets.Catch/UI/PlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs similarity index 78% rename from osu.Game.Rulesets.Catch/UI/PlayfieldAdjustmentContainer.cs rename to osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs index 76daee2bbf..b8d3dc9017 100644 --- a/osu.Game.Rulesets.Catch/UI/PlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs @@ -3,17 +3,23 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.UI; using osuTK; namespace osu.Game.Rulesets.Catch.UI { - public class PlayfieldAdjustmentContainer : Container + public class CatchPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer { protected override Container Content => content; private readonly Container content; - public PlayfieldAdjustmentContainer() + public CatchPlayfieldAdjustmentContainer() { + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; + + Size = new Vector2(0.86f); // matches stable's vertical offset for catcher plate + InternalChild = new Container { Anchor = Anchor.Centre, diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index 406dc10eea..6981c98ec7 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -36,6 +36,8 @@ namespace osu.Game.Rulesets.Catch.UI protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty, GetVisualRepresentation); + protected override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new CatchPlayfieldAdjustmentContainer(); + protected override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); public override DrawableHitObject GetVisualRepresentation(CatchHitObject h) diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index a019401d5b..0dc081f3da 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.MathUtils; using osu.Game.Beatmaps; @@ -89,11 +88,9 @@ namespace osu.Game.Rulesets.Mania.UI /// The column which intersects with . public Column GetColumnByPosition(Vector2 screenSpacePosition) => Playfield.GetColumnByPosition(screenSpacePosition); - protected override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }; + protected override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new ManiaPlayfieldAdjustmentContainer(); + + protected override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages); public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 81888d2773..cbabfcc8b4 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -28,8 +28,6 @@ namespace osu.Game.Rulesets.Mania.UI if (stageDefinitions.Count <= 0) throw new ArgumentException("Can't have zero or fewer stages."); - Size = new Vector2(1, 0.8f); - GridContainer playfieldGrid; AddInternal(playfieldGrid = new GridContainer { diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs new file mode 100644 index 0000000000..d893a3fdde --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs @@ -0,0 +1,20 @@ +// 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; +using osuTK; + +namespace osu.Game.Rulesets.Mania.UI +{ + public class ManiaPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer + { + public ManiaPlayfieldAdjustmentContainer() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + Size = new Vector2(1, 0.8f); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index dd3925e04f..952fe0b708 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.Edit public override SelectionHandler CreateSelectionHandler() => new OsuSelectionHandler(); - protected override Container CreateLayerContainer() => new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both }; + protected override Container CreateLayerContainer() => new OsuPlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both }; public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) { diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index b632e0fb05..1c5032a938 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -1,7 +1,8 @@ -// 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; +using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Input.Handlers; @@ -32,6 +33,8 @@ namespace osu.Game.Rulesets.Osu.UI protected override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo); + protected override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new OsuPlayfieldAdjustmentContainer(); + public override DrawableHitObject GetVisualRepresentation(OsuHitObject h) { switch (h) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 51733c3c01..5e532d9b04 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -24,41 +24,28 @@ namespace osu.Game.Rulesets.Osu.UI public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); - private readonly PlayfieldAdjustmentContainer adjustmentContainer; - - protected override Container CursorTargetContainer => adjustmentContainer; - protected override CursorContainer CreateCursor() => new GameplayCursorContainer(); public OsuPlayfield() { - Anchor = Anchor.Centre; - Origin = Anchor.Centre; - - Size = new Vector2(0.75f); - - InternalChild = adjustmentContainer = new PlayfieldAdjustmentContainer + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + connectionLayer = new FollowPointRenderer { - connectionLayer = new FollowPointRenderer - { - RelativeSizeAxes = Axes.Both, - Depth = 2, - }, - judgementLayer = new JudgementContainer - { - RelativeSizeAxes = Axes.Both, - Depth = 1, - }, - HitObjectContainer, - approachCircles = new ApproachCircleProxyContainer - { - RelativeSizeAxes = Axes.Both, - Depth = -1, - }, - } + RelativeSizeAxes = Axes.Both, + Depth = 2, + }, + judgementLayer = new JudgementContainer + { + RelativeSizeAxes = Axes.Both, + Depth = 1, + }, + HitObjectContainer, + approachCircles = new ApproachCircleProxyContainer + { + RelativeSizeAxes = Axes.Both, + Depth = -1, + }, }; } diff --git a/osu.Game.Rulesets.Osu/UI/PlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs similarity index 82% rename from osu.Game.Rulesets.Osu/UI/PlayfieldAdjustmentContainer.cs rename to osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs index c383c47491..e28ff5f460 100644 --- a/osu.Game.Rulesets.Osu/UI/PlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs @@ -3,17 +3,23 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.UI; using osuTK; namespace osu.Game.Rulesets.Osu.UI { - public class PlayfieldAdjustmentContainer : Container + public class OsuPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer { protected override Container Content => content; private readonly Container content; - public PlayfieldAdjustmentContainer() + public OsuPlayfieldAdjustmentContainer() { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + Size = new Vector2(0.75f); + InternalChild = new Container { Anchor = Anchor.Centre, diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index 899b91863e..f595432082 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -81,6 +81,8 @@ namespace osu.Game.Rulesets.Taiko.UI public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); + protected override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new TaikoPlayfieldAdjustmentContainer(); + protected override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo); protected override Playfield CreatePlayfield() => new TaikoPlayfield(Beatmap.ControlPointInfo); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 35b941b52b..dbff5270d2 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -55,143 +55,137 @@ namespace osu.Game.Rulesets.Taiko.UI public TaikoPlayfield(ControlPointInfo controlPoints) { - InternalChild = new PlayfieldAdjustmentContainer + InternalChildren = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + backgroundContainer = new Container { - backgroundContainer = new Container + Name = "Transparent playfield background", + RelativeSizeAxes = Axes.Both, + Masking = true, + EdgeEffect = new EdgeEffectParameters { - Name = "Transparent playfield background", - RelativeSizeAxes = Axes.Both, - Masking = true, - EdgeEffect = new EdgeEffectParameters + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.2f), + Radius = 5, + }, + Children = new Drawable[] + { + background = new Box { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(0.2f), - Radius = 5, + RelativeSizeAxes = Axes.Both, + Alpha = 0.6f }, - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.6f - }, - } - }, - new Container - { - Name = "Right area", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = left_area_size }, - Children = new Drawable[] - { - new Container - { - Name = "Masked elements before hit objects", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = HIT_TARGET_OFFSET }, - Masking = true, - Children = new Drawable[] - { - hitExplosionContainer = new Container - { - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, - Blending = BlendingMode.Additive, - }, - HitTarget = new HitTarget - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit - } - } - }, - barlineContainer = new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = HIT_TARGET_OFFSET } - }, - new Container - { - Name = "Hit objects", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = HIT_TARGET_OFFSET }, - Masking = true, - Child = HitObjectContainer - }, - kiaiExplosionContainer = new Container - { - Name = "Kiai hit explosions", - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, - Margin = new MarginPadding { Left = HIT_TARGET_OFFSET }, - Blending = BlendingMode.Additive - }, - judgementContainer = new JudgementContainer - { - Name = "Judgements", - RelativeSizeAxes = Axes.Y, - Margin = new MarginPadding { Left = HIT_TARGET_OFFSET }, - Blending = BlendingMode.Additive - }, - } - }, - overlayBackgroundContainer = new Container - { - Name = "Left overlay", - RelativeSizeAxes = Axes.Y, - Size = new Vector2(left_area_size, 1), - Children = new Drawable[] - { - overlayBackground = new Box - { - RelativeSizeAxes = Axes.Both, - }, - new InputDrum(controlPoints) - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Scale = new Vector2(0.9f), - Margin = new MarginPadding { Right = 20 } - }, - new Box - { - Anchor = Anchor.TopRight, - RelativeSizeAxes = Axes.Y, - Width = 10, - Colour = Framework.Graphics.Colour.ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.6f), Color4.Black.Opacity(0)), - }, - } - }, - new Container - { - Name = "Border", - RelativeSizeAxes = Axes.Both, - Masking = true, - MaskingSmoothness = 0, - BorderThickness = 2, - AlwaysPresent = true, - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - } - } - }, - topLevelHitContainer = new Container - { - Name = "Top level hit objects", - RelativeSizeAxes = Axes.Both, } + }, + new Container + { + Name = "Right area", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = left_area_size }, + Children = new Drawable[] + { + new Container + { + Name = "Masked elements before hit objects", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = HIT_TARGET_OFFSET }, + Masking = true, + Children = new Drawable[] + { + hitExplosionContainer = new Container + { + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + Blending = BlendingMode.Additive, + }, + HitTarget = new HitTarget + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit + } + } + }, + barlineContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = HIT_TARGET_OFFSET } + }, + new Container + { + Name = "Hit objects", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = HIT_TARGET_OFFSET }, + Masking = true, + Child = HitObjectContainer + }, + kiaiExplosionContainer = new Container + { + Name = "Kiai hit explosions", + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + Margin = new MarginPadding { Left = HIT_TARGET_OFFSET }, + Blending = BlendingMode.Additive + }, + judgementContainer = new JudgementContainer + { + Name = "Judgements", + RelativeSizeAxes = Axes.Y, + Margin = new MarginPadding { Left = HIT_TARGET_OFFSET }, + Blending = BlendingMode.Additive + }, + } + }, + overlayBackgroundContainer = new Container + { + Name = "Left overlay", + RelativeSizeAxes = Axes.Y, + Size = new Vector2(left_area_size, 1), + Children = new Drawable[] + { + overlayBackground = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new InputDrum(controlPoints) + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Scale = new Vector2(0.9f), + Margin = new MarginPadding { Right = 20 } + }, + new Box + { + Anchor = Anchor.TopRight, + RelativeSizeAxes = Axes.Y, + Width = 10, + Colour = Framework.Graphics.Colour.ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.6f), Color4.Black.Opacity(0)), + }, + } + }, + new Container + { + Name = "Border", + RelativeSizeAxes = Axes.Both, + Masking = true, + MaskingSmoothness = 0, + BorderThickness = 2, + AlwaysPresent = true, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + } + } + }, + topLevelHitContainer = new Container + { + Name = "Top level hit objects", + RelativeSizeAxes = Axes.Both, } }; } diff --git a/osu.Game.Rulesets.Taiko/UI/PlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs similarity index 68% rename from osu.Game.Rulesets.Taiko/UI/PlayfieldAdjustmentContainer.cs rename to osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 0f0ad59fd3..84464b199e 100644 --- a/osu.Game.Rulesets.Taiko/UI/PlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -1,16 +1,23 @@ // 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.Containers; +using osu.Framework.Graphics; +using osu.Game.Rulesets.UI; using osuTK; namespace osu.Game.Rulesets.Taiko.UI { - public class PlayfieldAdjustmentContainer : Container + public class TaikoPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer { private const float default_relative_height = TaikoPlayfield.DEFAULT_HEIGHT / 768; private const float default_aspect = 16f / 9f; + public TaikoPlayfieldAdjustmentContainer() + { + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + } + protected override void Update() { base.Update(); diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 4c0bc9867b..0ced3476d0 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.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.Allocation; @@ -133,20 +133,19 @@ namespace osu.Game.Rulesets.UI return dependencies; } + protected virtual PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new PlayfieldAdjustmentContainer(); + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - KeyBindingInputManager.AddRange(new Drawable[] - { - Playfield, - (ResumeOverlay = CreateResumeOverlay()) ?? new Container() - }); - InternalChildren = new Drawable[] { frameStabilityContainer = new FrameStabilityContainer { - Child = KeyBindingInputManager, + Child = KeyBindingInputManager + .WithChild(CreatePlayfieldAdjustmentContainer() + .WithChild(Playfield) + ) }, Overlays = new Container { RelativeSizeAxes = Axes.Both } }; diff --git a/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs b/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs new file mode 100644 index 0000000000..fff4a450e5 --- /dev/null +++ b/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Rulesets.UI +{ + /// + /// A container which handles sizing of the and any other components that need to match their size. + /// + public class PlayfieldAdjustmentContainer : Container + { + public PlayfieldAdjustmentContainer() + { + RelativeSizeAxes = Axes.Both; + } + } +} From c79d187a896176018dd38d06c18cf7400a33f6d3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2019 19:21:25 +0900 Subject: [PATCH 0404/5608] Add final osu! resume screen implementation --- osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs | 6 ++++-- osu.Game/Rulesets/UI/DrawableRuleset.cs | 10 +++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index 1c5032a938..ffb5d3b5d7 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.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 System.Linq; -using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Input.Handlers; @@ -15,6 +14,7 @@ using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Play; namespace osu.Game.Rulesets.Osu.UI { @@ -35,6 +35,8 @@ namespace osu.Game.Rulesets.Osu.UI protected override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new OsuPlayfieldAdjustmentContainer(); + protected override ResumeOverlay CreateResumeOverlay() => new OsuResumeOverlay(); + public override DrawableHitObject GetVisualRepresentation(OsuHitObject h) { switch (h) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 0ced3476d0..0f61b1cb2f 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.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.Allocation; @@ -150,6 +150,13 @@ namespace osu.Game.Rulesets.UI Overlays = new Container { RelativeSizeAxes = Axes.Both } }; + if ((ResumeOverlay = CreateResumeOverlay()) != null) + { + AddInternal(CreateInputManager() + .WithChild(CreatePlayfieldAdjustmentContainer() + .WithChild(ResumeOverlay))); + } + applyRulesetMods(mods, config); loadObjects(); @@ -173,6 +180,7 @@ namespace osu.Game.Rulesets.UI { if (ResumeOverlay != null && (Cursor == null || Contains(Cursor.ActiveCursor.ScreenSpaceDrawQuad.Centre))) { + ResumeOverlay.GameplayCursor = Cursor; ResumeOverlay.ResumeAction = continueResume; ResumeOverlay.Show(); } From 95889440488e9639b855e85d0c33e56aec63b6eb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2019 19:21:34 +0900 Subject: [PATCH 0405/5608] Fix multiple cursors appearing --- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 9829839841..5312711a7d 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -35,12 +35,16 @@ namespace osu.Game.Rulesets.Osu.UI { base.Show(); clickToResumeCursor.ShowAt(GameplayCursor.ActiveCursor.Position); - Add(localCursorContainer = new GameplayCursorContainer()); + + if (localCursorContainer == null) + Add(localCursorContainer = new GameplayCursorContainer()); } public override void Hide() { - localCursorContainer.Expire(); + localCursorContainer?.Expire(); + localCursorContainer = null; + base.Hide(); } From 06d4856e1716a250d26483aa1e67d3799f33f5bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2019 19:21:47 +0900 Subject: [PATCH 0406/5608] Remove unnecessary CursorTargetContainer --- osu.Game/Rulesets/UI/Playfield.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 78d14a27e3..53bfa6af48 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.UI Cursor = CreateCursor(); if (Cursor != null) - CursorTargetContainer.Add(Cursor); + AddInternal(Cursor); } /// @@ -99,11 +99,6 @@ namespace osu.Game.Rulesets.UI /// The cursor, or null if a cursor is not rqeuired. protected virtual CursorContainer CreateCursor() => null; - /// - /// The target container to add the cursor after it is created. - /// - protected virtual Container CursorTargetContainer => null; - /// /// Registers a as a nested . /// This does not add the to the draw hierarchy. From a23dfb58ad11d7b324aa9301ddc1527c862ce56d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2019 20:25:16 +0900 Subject: [PATCH 0407/5608] Add base cursor class to retrieve true visibility state --- .../TestCaseGameplayCursor.cs | 3 ++- .../Edit/DrawableOsuEditRuleset.cs | 3 +-- .../UI/Cursor/GameplayCursorContainer.cs | 6 ++--- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 3 +-- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 3 ++- osu.Game/Rulesets/UI/DrawableRuleset.cs | 8 +++--- .../Rulesets/UI/GameplayCursorContainer.cs | 25 +++++++++++++++++++ osu.Game/Rulesets/UI/Playfield.cs | 5 ++-- 8 files changed, 41 insertions(+), 15 deletions(-) create mode 100644 osu.Game/Rulesets/UI/GameplayCursorContainer.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs index 5c1e775c01..1e2a936002 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.Cursor; using osu.Game.Rulesets.Osu.UI.Cursor; +using osu.Game.Rulesets.UI; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests @@ -27,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Tests [BackgroundDependencyLoader] private void load() { - Add(cursorContainer = new GameplayCursorContainer { RelativeSizeAxes = Axes.Both }); + Add(cursorContainer = new OsuCursorContainer { RelativeSizeAxes = Axes.Both }); } } } diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs index 1a6e78d918..3ae554a5d7 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics.Cursor; using osu.Game.Beatmaps; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.UI; @@ -20,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Edit private class OsuPlayfieldNoCursor : OsuPlayfield { - protected override CursorContainer CreateCursor() => null; + protected override GameplayCursorContainer CreateCursor() => null; } } } diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs index b64561e4f7..f028a5f15c 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs @@ -3,12 +3,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Bindings; +using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu.UI.Cursor { - public class GameplayCursorContainer : CursorContainer, IKeyBindingHandler + public class OsuCursorContainer : GameplayCursorContainer, IKeyBindingHandler { protected override Drawable CreateCursor() => new OsuCursor(); @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly Container fadeContainer; - public GameplayCursorContainer() + public OsuCursorContainer() { InternalChild = fadeContainer = new Container { diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 5e532d9b04..0cbe0cca85 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Connections; using osu.Game.Rulesets.UI; using System.Linq; -using osu.Framework.Graphics.Cursor; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.UI.Cursor; @@ -24,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.UI public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); - protected override CursorContainer CreateCursor() => new GameplayCursorContainer(); + protected override GameplayCursorContainer CreateCursor() => new OsuCursorContainer(); public OsuPlayfield() { diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 5312711a7d..0d4e7edb7b 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.UI.Cursor; +using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using osuTK; using osuTK.Graphics; @@ -37,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.UI clickToResumeCursor.ShowAt(GameplayCursor.ActiveCursor.Position); if (localCursorContainer == null) - Add(localCursorContainer = new GameplayCursorContainer()); + Add(localCursorContainer = new OsuCursorContainer()); } public override void Hide() diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 0f61b1cb2f..2b64aec8ea 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -178,7 +178,7 @@ namespace osu.Game.Rulesets.UI public override void RequestResume(Action continueResume) { - if (ResumeOverlay != null && (Cursor == null || Contains(Cursor.ActiveCursor.ScreenSpaceDrawQuad.Centre))) + if (ResumeOverlay != null && (Cursor == null || ((GameplayCursorContainer)Cursor).LastFrameState == Visibility.Visible && Contains(Cursor.ActiveCursor.ScreenSpaceDrawQuad.Centre))) { ResumeOverlay.GameplayCursor = Cursor; ResumeOverlay.ResumeAction = continueResume; @@ -284,7 +284,9 @@ namespace osu.Game.Rulesets.UI protected override bool OnHover(HoverEvent e) => true; // required for IProvideCursor - public override CursorContainer Cursor => Playfield.Cursor; + CursorContainer IProvideCursor.Cursor => Playfield.Cursor; + + public override GameplayCursorContainer Cursor => Playfield.Cursor; public bool ProvidingUserCursor => Playfield.Cursor != null && !HasReplayLoaded.Value; @@ -354,7 +356,7 @@ namespace osu.Game.Rulesets.UI /// /// The cursor being displayed by the . May be null if no cursor is provided. /// - public abstract CursorContainer Cursor { get; } + public abstract GameplayCursorContainer Cursor { get; } /// /// Sets a replay to be used, overriding local input. diff --git a/osu.Game/Rulesets/UI/GameplayCursorContainer.cs b/osu.Game/Rulesets/UI/GameplayCursorContainer.cs new file mode 100644 index 0000000000..de73c08809 --- /dev/null +++ b/osu.Game/Rulesets/UI/GameplayCursorContainer.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 osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; + +namespace osu.Game.Rulesets.UI +{ + public class GameplayCursorContainer : CursorContainer + { + /// + /// Because Show/Hide are executed by a parent, is updated immediately even if the cursor + /// is in a non-updating state (via limitations). + /// + /// This holds the true visibility value. + /// + public Visibility LastFrameState; + + protected override void Update() + { + base.Update(); + LastFrameState = State; + } + } +} diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 53bfa6af48..48b950c070 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -10,7 +10,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; using osuTK; @@ -90,14 +89,14 @@ namespace osu.Game.Rulesets.UI /// /// The cursor currently being used by this . May be null if no cursor is provided. /// - public CursorContainer Cursor { get; private set; } + public GameplayCursorContainer Cursor { get; private set; } /// /// Provide an optional cursor which is to be used for gameplay. /// If providing a cursor, must also point to a valid target container. /// /// The cursor, or null if a cursor is not rqeuired. - protected virtual CursorContainer CreateCursor() => null; + protected virtual GameplayCursorContainer CreateCursor() => null; /// /// Registers a as a nested . From 245f463e3fd554f522f666a01c4864ccfbbde7cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2019 20:25:47 +0900 Subject: [PATCH 0408/5608] Don't update gameplay loop while paused --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 5 ++++- osu.Game/Screens/Play/GameplayClock.cs | 3 +++ osu.Game/Screens/Play/GameplayClockContainer.cs | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 161e7aecb4..deec2b8eac 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -36,7 +36,10 @@ namespace osu.Game.Rulesets.UI private void load(GameplayClock clock) { if (clock != null) + { parentGameplayClock = clock; + gameplayClock.IsPaused.BindTo(clock.IsPaused); + } } protected override void LoadComplete() @@ -68,7 +71,7 @@ namespace osu.Game.Rulesets.UI public override bool UpdateSubTree() { requireMoreUpdateLoops = true; - validState = true; + validState = !gameplayClock.IsPaused.Value; int loops = 0; diff --git a/osu.Game/Screens/Play/GameplayClock.cs b/osu.Game/Screens/Play/GameplayClock.cs index 0400bfbc27..3efcfa0f65 100644 --- a/osu.Game/Screens/Play/GameplayClock.cs +++ b/osu.Game/Screens/Play/GameplayClock.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Framework.Timing; namespace osu.Game.Screens.Play @@ -17,6 +18,8 @@ namespace osu.Game.Screens.Play { private readonly IFrameBasedClock underlyingClock; + public readonly BindableBool IsPaused = new BindableBool(); + public GameplayClock(IFrameBasedClock underlyingClock) { this.underlyingClock = underlyingClock; diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index deac5e02bf..546364b26d 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -79,6 +79,8 @@ namespace osu.Game.Screens.Play // the clock to be exposed via DI to children. GameplayClock = new GameplayClock(offsetClock); + + GameplayClock.IsPaused.BindTo(IsPaused); } [BackgroundDependencyLoader] From 15aea7f745ac0b9dfa4695eef7da897f84a02418 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2019 21:39:15 +0900 Subject: [PATCH 0409/5608] Update framework --- osu.Game/Screens/Multi/MultiplayerSubScreen.cs | 2 -- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Multi/MultiplayerSubScreen.cs b/osu.Game/Screens/Multi/MultiplayerSubScreen.cs index ad72072981..65e501b114 100644 --- a/osu.Game/Screens/Multi/MultiplayerSubScreen.cs +++ b/osu.Game/Screens/Multi/MultiplayerSubScreen.cs @@ -14,8 +14,6 @@ namespace osu.Game.Screens.Multi { public override bool DisallowExternalBeatmapRulesetChanges => false; - public override bool RemoveWhenNotAlive => false; - public virtual string ShortTitle => Title; [Resolved(CanBeNull = true)] diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 71324ea0f0..eb5d0fd8ee 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 02099a59bb..c3792a48a1 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From a642f1013167c61cd60fe4f76f69c4b391600f02 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2019 21:52:01 +0900 Subject: [PATCH 0410/5608] Remove redundant cast --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 2b64aec8ea..bdb1c9c0cc 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -178,7 +178,7 @@ namespace osu.Game.Rulesets.UI public override void RequestResume(Action continueResume) { - if (ResumeOverlay != null && (Cursor == null || ((GameplayCursorContainer)Cursor).LastFrameState == Visibility.Visible && Contains(Cursor.ActiveCursor.ScreenSpaceDrawQuad.Centre))) + if (ResumeOverlay != null && (Cursor == null || Cursor.LastFrameState == Visibility.Visible && Contains(Cursor.ActiveCursor.ScreenSpaceDrawQuad.Centre))) { ResumeOverlay.GameplayCursor = Cursor; ResumeOverlay.ResumeAction = continueResume; From 82140c38fc39ca7e0124b80ebdd043fd72281584 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2019 22:00:33 +0900 Subject: [PATCH 0411/5608] Apply CI fixes --- .../{GameplayCursorContainer.cs => OsuCursorContainer.cs} | 0 osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Rulesets.Osu/UI/Cursor/{GameplayCursorContainer.cs => OsuCursorContainer.cs} (100%) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs similarity index 100% rename from osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs rename to osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index bdb1c9c0cc..905da3c33b 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -178,7 +178,7 @@ namespace osu.Game.Rulesets.UI public override void RequestResume(Action continueResume) { - if (ResumeOverlay != null && (Cursor == null || Cursor.LastFrameState == Visibility.Visible && Contains(Cursor.ActiveCursor.ScreenSpaceDrawQuad.Centre))) + if (ResumeOverlay != null && (Cursor == null || (Cursor.LastFrameState == Visibility.Visible && Contains(Cursor.ActiveCursor.ScreenSpaceDrawQuad.Centre)))) { ResumeOverlay.GameplayCursor = Cursor; ResumeOverlay.ResumeAction = continueResume; From f4aeb390efb7ee2a8620a73c02e0a43bf25b1f86 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Mar 2019 10:21:34 +0900 Subject: [PATCH 0412/5608] Initial re-layout of score table --- .../TestCaseBeatmapScoresContainer.cs | 12 +- .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 213 +++++++++++++++++- 2 files changed, 222 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs index b626c23f25..2bc0796045 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs @@ -1,18 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; -using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; @@ -24,6 +23,15 @@ namespace osu.Game.Tests.Visual.SongSelect [Description("in BeatmapOverlay")] public class TestCaseBeatmapScoresContainer : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ScoresContainer), + typeof(ScoreTable), + typeof(ScoreTableRow), + typeof(ScoreTableHeader), + typeof(ScoreTableScore) + }; + private readonly Box background; public TestCaseBeatmapScoresContainer() diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index aacbc12cd8..7e838f0aae 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -6,19 +6,52 @@ using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; using System.Collections.Generic; using System.Linq; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Online.Leaderboards; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Users; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Scores { public class ScoreTable : CompositeDrawable { + private const int fade_duration = 100; + private const int text_size = 14; + private readonly FillFlowContainer scoresFlow; + private readonly ScoresGrid scoresGrid; public ScoreTable() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - InternalChild = scoresFlow = new FillFlowContainer + InternalChild = scoresGrid = new ScoresGrid + { + RelativeSizeAxes = Axes.X, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, 40), + new Dimension(GridSizeMode.Absolute, 70), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Distributed, minSize: 180), + new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), + new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), + new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), + new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), + new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), + new Dimension(GridSizeMode.Distributed, minSize: 40, maxSize: 70), + new Dimension(GridSizeMode.AutoSize), + } + }; + + scoresFlow = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -48,6 +81,184 @@ namespace osu.Game.Overlays.BeatmapSet.Scores int index = 0; foreach (var s in value) scoresFlow.Add(new ScoreTableScore(index++, s, maxModsAmount)); + + scoresGrid.Content = value.Select((s, i) => createRowContents(s, i).ToArray()).ToArray(); + } + } + + private IEnumerable createRowContents(APIScoreInfo score, int index) + { + yield return new SpriteText + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Text = $"#{index + 1}", + Font = @"Exo2.0-Bold", + TextSize = text_size, + }; + + yield return new DrawableRank(score.Rank) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(30, 20), + FillMode = FillMode.Fit, + }; + + yield return new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Right = 20 }, + Text = $@"{score.TotalScore:N0}", + TextSize = text_size, + Font = index == 0 ? OsuFont.GetFont(weight: FontWeight.Bold) : OsuFont.Default + }; + + yield return new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Right = 20 }, + Text = $@"{score.Accuracy:P2}", + TextSize = text_size, + Colour = score.Accuracy == 1 ? Color4.GreenYellow : Color4.White + }; + + yield return new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + Children = new Drawable[] + { + new DrawableFlag(score.User.Country) + { + Size = new Vector2(20, 13), + }, + new ClickableScoreUsername + { + User = score.User, + } + } + }; + + yield return new SpriteText + { + Text = $@"{score.MaxCombo:N0}x", + TextSize = text_size, + }; + + yield return new SpriteText + { + Text = $"{score.Statistics[HitResult.Great]}", + TextSize = text_size, + Colour = score.Statistics[HitResult.Great] == 0 ? Color4.Gray : Color4.White + }; + + yield return new SpriteText + { + Text = $"{score.Statistics[HitResult.Good]}", + TextSize = text_size, + Colour = score.Statistics[HitResult.Good] == 0 ? Color4.Gray : Color4.White + }; + + yield return new SpriteText + { + Text = $"{score.Statistics[HitResult.Meh]}", + TextSize = text_size, + Colour = score.Statistics[HitResult.Meh] == 0 ? Color4.Gray : Color4.White + }; + + yield return new SpriteText + { + Text = $"{score.Statistics[HitResult.Miss]}", + TextSize = text_size, + Colour = score.Statistics[HitResult.Miss] == 0 ? Color4.Gray : Color4.White + }; + + yield return new SpriteText + { + Text = $@"{score.PP:N0}", + TextSize = text_size, + }; + + yield return new FillFlowContainer + { + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + ChildrenEnumerable = score.Mods.Select(m => new ModIcon(m) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Scale = new Vector2(0.3f), + }) + }; + } + + private class ScoresGrid : GridContainer + { + public ScoresGrid() + { + AutoSizeAxes = Axes.Y; + } + + public Drawable[][] Content + { + get => base.Content; + set + { + base.Content = value; + + RowDimensions = Enumerable.Repeat(new Dimension(GridSizeMode.Absolute, 25), value.Length).ToArray(); + } + } + } + + private class ClickableScoreUsername : ClickableUserContainer + { + private readonly SpriteText text; + private readonly SpriteText textBold; + + public ClickableScoreUsername() + { + Add(text = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + TextSize = text_size, + }); + + Add(textBold = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + TextSize = text_size, + Font = @"Exo2.0-Bold", + Alpha = 0, + }); + } + + protected override void OnUserChange(User user) + { + text.Text = textBold.Text = user.Username; + } + + protected override bool OnHover(HoverEvent e) + { + textBold.FadeIn(fade_duration, Easing.OutQuint); + text.FadeOut(fade_duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + textBold.FadeOut(fade_duration, Easing.OutQuint); + text.FadeIn(fade_duration, Easing.OutQuint); + base.OnHoverLost(e); } } } From a0f6718145f4cadb74e86161fe635c221d30e2d9 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 26 Mar 2019 10:48:29 +0900 Subject: [PATCH 0413/5608] Better tests and implementation --- .../Visual/TestCaseFacadeContainer.cs | 75 ++++++++++++++++++- .../Graphics/Containers/FacadeContainer.cs | 55 ++++++++------ osu.Game/Screens/Play/PlayerLoader.cs | 5 +- 3 files changed, 109 insertions(+), 26 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs index 3063a4ca3f..d3f854998c 100644 --- a/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs @@ -9,7 +9,9 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Testing; using osu.Game.Configuration; using osu.Game.Graphics.Containers; @@ -18,6 +20,7 @@ using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens; using osu.Game.Screens.Menu; using osu.Game.Screens.Play; +using osuTK; using osuTK.Graphics; namespace osu.Game.Tests.Visual @@ -36,6 +39,7 @@ namespace osu.Game.Tests.Visual private readonly Bindable uiScale = new Bindable(); + private TestScreen screen1; private OsuScreen baseScreen; public TestCaseFacadeContainer() @@ -49,7 +53,6 @@ namespace osu.Game.Tests.Visual baseScreen = null; config.BindWith(OsuSetting.UIScale, uiScale); AddSliderStep("Adjust scale", 1f, 1.5f, 1f, v => uiScale.Value = v); - AddToggleStep("Toggle mods", b => { Beatmap.Value.Mods.Value = b ? Beatmap.Value.Mods.Value.Concat(new[] { new OsuModNoFail() }) : Enumerable.Empty(); }); } [SetUpSteps] @@ -58,9 +61,18 @@ namespace osu.Game.Tests.Visual AddStep("Null screens", () => baseScreen = null); } + [Test] + public void IsolatedTest() + { + bool randomPositions = false; + AddToggleStep("Toggle move continuously", b => randomPositions = b); + AddStep("Move facade to random position", () => LoadScreen(screen1 = new TestScreen(randomPositions))); + } + [Test] public void PlayerLoaderTest() { + AddToggleStep("Toggle mods", b => { Beatmap.Value.Mods.Value = b ? Beatmap.Value.Mods.Value.Concat(new[] { new OsuModNoFail() }) : Enumerable.Empty(); }); AddStep("Add new playerloader", () => LoadScreen(baseScreen = new TestPlayerLoader(() => new TestPlayer { AllowPause = false, @@ -89,6 +101,67 @@ namespace osu.Game.Tests.Visual }; } + private class TestScreen : OsuScreen + { + private TestFacadeContainer facadeContainer; + private FacadeFlowComponent facadeFlowComponent; + private OsuLogo logo; + + private readonly bool randomPositions; + + public TestScreen(bool randomPositions = false) + { + this.randomPositions = randomPositions; + } + + private SpriteText positionText; + private SpriteText sizeAxesText; + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = facadeContainer = new TestFacadeContainer + { + Child = facadeFlowComponent = new FacadeFlowComponent + { + AutoSizeAxes = Axes.Both + } + }; + } + + protected override void LogoArriving(OsuLogo logo, bool resuming) + { + base.LogoArriving(logo, resuming); + logo.FadeIn(350); + logo.ScaleTo(new Vector2(0.15f), 350, Easing.In); + facadeContainer.SetLogo(logo); + moveLogoFacade(); + } + + private void moveLogoFacade() + { + Random random = new Random(); + if (facadeFlowComponent.Transforms.Count == 0) + { + facadeFlowComponent.Delay(500).MoveTo(new Vector2(random.Next(0, 800), random.Next(0, 600)), 300); + } + + if (randomPositions) + Schedule(moveLogoFacade); + } + } + + private class FacadeFlowComponent : FillFlowContainer + { + [BackgroundDependencyLoader] + private void load(Facade facade) + { + facade.Anchor = Anchor.TopCentre; + facade.Origin = Anchor.TopCentre; + Child = facade; + } + } + private class TestPlayerLoader : PlayerLoader { public TestPlayerLoader(Func player) diff --git a/osu.Game/Graphics/Containers/FacadeContainer.cs b/osu.Game/Graphics/Containers/FacadeContainer.cs index d7fae8887f..0511c87166 100644 --- a/osu.Game/Graphics/Containers/FacadeContainer.cs +++ b/osu.Game/Graphics/Containers/FacadeContainer.cs @@ -1,10 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.MathUtils; using osu.Game.Screens.Menu; using osuTK; @@ -18,7 +18,6 @@ namespace osu.Game.Graphics.Containers private OsuLogo logo; private bool tracking; - private bool smoothTransform; protected virtual Facade CreateFacade() => new Facade(); @@ -29,7 +28,7 @@ namespace osu.Game.Graphics.Containers private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(facade.ScreenSpaceDrawQuad.Centre); - public void SetLogo(OsuLogo logo, bool resuming, double transformDelay) + public void SetLogo(OsuLogo logo, double transformDelay = 0) { if (logo != null) { @@ -38,41 +37,53 @@ namespace osu.Game.Graphics.Containers Scheduler.AddDelayed(() => { tracking = true; - smoothTransform = !resuming; }, transformDelay); } } + private double startTime; + private double duration = 1000; + + private Vector2 startPosition; + private Easing easing = Easing.InOutExpo; + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - if (logo == null) + if (logo == null || !tracking) return; facade.Size = new Vector2(logo.SizeForFlow * 0.3f); - if (smoothTransform && facade.IsLoaded && logo.Transforms.Count == 0) + if (facade.IsLoaded && logo.Position != logoTrackingPosition) { - // Our initial movement to the tracking location should be smooth. - Schedule(() => + if (logo.RelativePositionAxes != Axes.None) { - facade.Size = new Vector2(logo.SizeForFlow * 0.3f); + logo.Position = logo.Parent.ToLocalSpace(logo.Position); logo.RelativePositionAxes = Axes.None; - logo.MoveTo(logoTrackingPosition, 500, Easing.InOutExpo); - smoothTransform = false; - }); - } - else if (facade.IsLoaded && logo.Transforms.Count == 0) - { - // If all transforms have finished playing, the logo constantly track the position of the facade. - logo.RelativePositionAxes = Axes.None; - logo.Position = logoTrackingPosition; + } + + if (startTime == 0) + { + startTime = Time.Current; + } + + var endTime = startTime + duration; + var remainingDuration = endTime - Time.Current; + + if (remainingDuration <= 0) + { + remainingDuration = 0; + } + + float currentTime = (float)Interpolation.ApplyEasing(easing, remainingDuration / duration); + logo.Position = Vector2.Lerp(logoTrackingPosition, startPosition, currentTime); } } } - - public class Facade : Container - { - } } + +public class Facade : Container +{ +} \ No newline at end of file diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 5817e11277..b7155f771f 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -155,7 +155,7 @@ namespace osu.Game.Screens.Play logo.MoveTo(new Vector2(0.5f), duration, Easing.In); logo.FadeIn(350); - content.SetLogo(logo, resuming, duration); + content.SetLogo(logo, duration); } protected override void LoadComplete() @@ -167,7 +167,7 @@ namespace osu.Game.Screens.Play private ScheduledDelegate pushDebounce; protected VisualSettings VisualSettings; - // Hhere because IsHovered will not update unless we do so. + // Here because IsHovered will not update unless we do so. public override bool HandlePositionalInput => true; private bool readyForPush => player.LoadState == LoadState.Ready && IsHovered && GetContainingInputManager()?.DraggedDrawable == null; @@ -306,7 +306,6 @@ namespace osu.Game.Screens.Play private Sprite backgroundSprite; private ModDisplay modDisplay; private FillFlowContainer fillFlowContainer; - private FacadeContainer facadeContainer; public bool Loading { From be9ac39f542eb6bea400086c9cf04cb7b4a15e69 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 26 Mar 2019 11:11:27 +0900 Subject: [PATCH 0414/5608] Cleanup --- .../Visual/TestCaseFacadeContainer.cs | 23 ++++--------------- .../Graphics/Containers/FacadeContainer.cs | 2 +- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs index d3f854998c..5591bec0b8 100644 --- a/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs @@ -11,7 +11,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Testing; using osu.Game.Configuration; using osu.Game.Graphics.Containers; @@ -32,6 +31,7 @@ namespace osu.Game.Tests.Visual typeof(PlayerLoader), typeof(Player), typeof(Facade), + typeof(FacadeContainer) }; [Cached] @@ -39,9 +39,6 @@ namespace osu.Game.Tests.Visual private readonly Bindable uiScale = new Bindable(); - private TestScreen screen1; - private OsuScreen baseScreen; - public TestCaseFacadeContainer() { Add(logo = new OsuLogo()); @@ -50,30 +47,23 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - baseScreen = null; config.BindWith(OsuSetting.UIScale, uiScale); AddSliderStep("Adjust scale", 1f, 1.5f, 1f, v => uiScale.Value = v); } - [SetUpSteps] - public void SetUpSteps() - { - AddStep("Null screens", () => baseScreen = null); - } - [Test] public void IsolatedTest() { bool randomPositions = false; AddToggleStep("Toggle move continuously", b => randomPositions = b); - AddStep("Move facade to random position", () => LoadScreen(screen1 = new TestScreen(randomPositions))); + AddStep("Move facade to random position", () => LoadScreen(new TestScreen(randomPositions))); } [Test] public void PlayerLoaderTest() { AddToggleStep("Toggle mods", b => { Beatmap.Value.Mods.Value = b ? Beatmap.Value.Mods.Value.Concat(new[] { new OsuModNoFail() }) : Enumerable.Empty(); }); - AddStep("Add new playerloader", () => LoadScreen(baseScreen = new TestPlayerLoader(() => new TestPlayer + AddStep("Add new playerloader", () => LoadScreen(new TestPlayerLoader(() => new TestPlayer { AllowPause = false, AllowLeadIn = false, @@ -84,7 +74,7 @@ namespace osu.Game.Tests.Visual [Test] public void MainMenuTest() { - AddStep("Add new Main Menu", () => LoadScreen(baseScreen = new MainMenu())); + AddStep("Add new Main Menu", () => LoadScreen(new MainMenu())); } private class TestFacadeContainer : FacadeContainer @@ -105,8 +95,6 @@ namespace osu.Game.Tests.Visual { private TestFacadeContainer facadeContainer; private FacadeFlowComponent facadeFlowComponent; - private OsuLogo logo; - private readonly bool randomPositions; public TestScreen(bool randomPositions = false) @@ -114,9 +102,6 @@ namespace osu.Game.Tests.Visual this.randomPositions = randomPositions; } - private SpriteText positionText; - private SpriteText sizeAxesText; - [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game/Graphics/Containers/FacadeContainer.cs b/osu.Game/Graphics/Containers/FacadeContainer.cs index 0511c87166..611cc94958 100644 --- a/osu.Game/Graphics/Containers/FacadeContainer.cs +++ b/osu.Game/Graphics/Containers/FacadeContainer.cs @@ -60,8 +60,8 @@ namespace osu.Game.Graphics.Containers { if (logo.RelativePositionAxes != Axes.None) { - logo.Position = logo.Parent.ToLocalSpace(logo.Position); logo.RelativePositionAxes = Axes.None; + logo.Position = logo.Parent.ToLocalSpace(logo.Position); } if (startTime == 0) From b75ea295dbf97862711515506e1fad7332ca8120 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 11:28:43 +0900 Subject: [PATCH 0415/5608] Rename KeyCounterCollection -> KeyCounterDisplay Also fix not working --- osu.Game.Tests/Visual/TestCaseKeyCounter.cs | 4 +-- osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 +- osu.Game/Rulesets/UI/RulesetInputManager.cs | 28 +++++++++++++------ osu.Game/Screens/Play/HUDOverlay.cs | 4 +-- ...nterCollection.cs => KeyCounterDisplay.cs} | 8 +++--- 5 files changed, 28 insertions(+), 18 deletions(-) rename osu.Game/Screens/Play/{KeyCounterCollection.cs => KeyCounterDisplay.cs} (95%) diff --git a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs index 52caffc29f..9360cfd911 100644 --- a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs +++ b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs @@ -20,13 +20,13 @@ namespace osu.Game.Tests.Visual { typeof(KeyCounterKeyboard), typeof(KeyCounterMouse), - typeof(KeyCounterCollection) + typeof(KeyCounterDisplay) }; public TestCaseKeyCounter() { KeyCounterKeyboard rewindTestKeyCounterKeyboard; - KeyCounterCollection kc = new KeyCounterCollection + KeyCounterDisplay kc = new KeyCounterDisplay { Origin = Anchor.Centre, Anchor = Anchor.Centre, diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 905da3c33b..88fdb9a135 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -232,7 +232,7 @@ namespace osu.Game.Rulesets.UI /// The DrawableHitObject. public abstract DrawableHitObject GetVisualRepresentation(TObject h); - public void Attach(KeyCounterCollection keyCounter) => + public void Attach(KeyCounterDisplay keyCounter) => (KeyBindingInputManager as ICanAttachKeyCounter)?.Attach(keyCounter); /// diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index e303166774..150c53274f 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; @@ -34,11 +35,19 @@ namespace osu.Game.Rulesets.UI protected readonly KeyBindingContainer KeyBindingContainer; - protected override Container Content => KeyBindingContainer; + protected override Container Content => content; + + private readonly Container content; + + private class Poop : Container + { + } protected RulesetInputManager(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) { - InternalChild = KeyBindingContainer = CreateKeyBindingContainer(ruleset, variant, unique); + InternalChild = KeyBindingContainer = + (KeyBindingContainer)CreateKeyBindingContainer(ruleset, variant, unique) + .WithChild(content = new Container { RelativeSizeAxes = Axes.Both }); } [BackgroundDependencyLoader(true)] @@ -115,18 +124,19 @@ namespace osu.Game.Rulesets.UI #region Key Counter Attachment - public void Attach(KeyCounterCollection keyCounter) + public void Attach(KeyCounterDisplay keyCounter) { var receptor = new ActionReceptor(keyCounter); - Add(receptor); - keyCounter.SetReceptor(receptor); + KeyBindingContainer.Add(receptor); + + keyCounter.SetReceptor(receptor); keyCounter.AddRange(KeyBindingContainer.DefaultKeyBindings.Select(b => b.GetAction()).Distinct().Select(b => new KeyCounterAction(b))); } - public class ActionReceptor : KeyCounterCollection.Receptor, IKeyBindingHandler + public class ActionReceptor : KeyCounterDisplay.Receptor, IKeyBindingHandler { - public ActionReceptor(KeyCounterCollection target) + public ActionReceptor(KeyCounterDisplay target) : base(target) { } @@ -159,12 +169,12 @@ namespace osu.Game.Rulesets.UI } /// - /// Supports attaching a . + /// Supports attaching a . /// Keys will be populated automatically and a receptor will be injected inside. /// public interface ICanAttachKeyCounter { - void Attach(KeyCounterCollection keyCounter); + void Attach(KeyCounterDisplay keyCounter); } public class RulesetInputManagerInputState : InputState diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 285e6eab23..a7b7f96e7a 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Play { private const int duration = 100; - public readonly KeyCounterCollection KeyCounter; + public readonly KeyCounterDisplay KeyCounter; public readonly RollingCounter ComboCounter; public readonly ScoreCounter ScoreCounter; public readonly RollingCounter AccuracyCounter; @@ -201,7 +201,7 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20 } }; - protected virtual KeyCounterCollection CreateKeyCounter() => new KeyCounterCollection + protected virtual KeyCounterDisplay CreateKeyCounter() => new KeyCounterDisplay { FadeTime = 50, Anchor = Anchor.BottomRight, diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs similarity index 95% rename from osu.Game/Screens/Play/KeyCounterCollection.cs rename to osu.Game/Screens/Play/KeyCounterDisplay.cs index 1b43737731..d5967f5899 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -14,14 +14,14 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play { - public class KeyCounterCollection : FillFlowContainer + public class KeyCounterDisplay : FillFlowContainer { private const int duration = 100; public readonly Bindable Visible = new Bindable(true); private readonly Bindable configVisibility = new Bindable(); - public KeyCounterCollection() + public KeyCounterDisplay() { Direction = FillDirection.Horizontal; AutoSizeAxes = Axes.Both; @@ -138,9 +138,9 @@ namespace osu.Game.Screens.Play public class Receptor : Drawable { - protected readonly KeyCounterCollection Target; + protected readonly KeyCounterDisplay Target; - public Receptor(KeyCounterCollection target) + public Receptor(KeyCounterDisplay target) { RelativeSizeAxes = Axes.Both; Depth = float.MinValue; From c403dede20ccddd7186fd315acf4a0e5f1d09f49 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 13:16:46 +0900 Subject: [PATCH 0416/5608] Add ManualInputManager to screen tests Also sanitises content init order (ctor for content; bdl for other) --- .../Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs | 3 ++- osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs | 4 +++- osu.Game/Tests/Visual/ManualInputManagerTestCase.cs | 3 +-- osu.Game/Tests/Visual/PlayerTestCase.cs | 5 +++++ osu.Game/Tests/Visual/ScreenTestCase.cs | 8 +++++--- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs index 34de61cb5b..497da33a05 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs @@ -27,7 +27,8 @@ namespace osu.Game.Tests.Visual.Multiplayer [Cached(Type = typeof(IRoomManager))] private TestRoomManager roomManager = new TestRoomManager(); - public TestCaseLoungeRoomsContainer() + [BackgroundDependencyLoader] + private void load() { RoomsContainer container; diff --git a/osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs b/osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs index 9453d0a5b2..53fb60bcb6 100644 --- a/osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs +++ b/osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel; +using osu.Framework.Allocation; using osu.Game.Screens.Tournament; using osu.Game.Screens.Tournament.Teams; @@ -11,7 +12,8 @@ namespace osu.Game.Tests.Visual.Tournament [Description("for tournament use")] public class TestCaseDrawings : ScreenTestCase { - public TestCaseDrawings() + [BackgroundDependencyLoader] + private void load() { LoadScreen(new Drawings { diff --git a/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs b/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs index 7c7c5938aa..f14ac833e4 100644 --- a/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs +++ b/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs @@ -14,8 +14,7 @@ namespace osu.Game.Tests.Visual protected ManualInputManagerTestCase() { - base.Content.Add(InputManager = new ManualInputManager()); - ReturnUserInput(); + base.Content.Add(InputManager = new ManualInputManager { UseParentInput = true }); } /// diff --git a/osu.Game/Tests/Visual/PlayerTestCase.cs b/osu.Game/Tests/Visual/PlayerTestCase.cs index 50cb839ed9..fb10244b12 100644 --- a/osu.Game/Tests/Visual/PlayerTestCase.cs +++ b/osu.Game/Tests/Visual/PlayerTestCase.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; @@ -23,7 +24,11 @@ namespace osu.Game.Tests.Visual protected PlayerTestCase(Ruleset ruleset) { this.ruleset = ruleset; + } + [BackgroundDependencyLoader] + private void load() + { Add(new Box { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Tests/Visual/ScreenTestCase.cs b/osu.Game/Tests/Visual/ScreenTestCase.cs index eec60d01c5..981f9acb63 100644 --- a/osu.Game/Tests/Visual/ScreenTestCase.cs +++ b/osu.Game/Tests/Visual/ScreenTestCase.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Screens; @@ -9,11 +10,12 @@ namespace osu.Game.Tests.Visual /// /// A test case which can be used to test a screen (that relies on OnEntering being called to execute startup instructions). /// - public abstract class ScreenTestCase : OsuTestCase + public abstract class ScreenTestCase : ManualInputManagerTestCase { - private readonly OsuScreenStack stack; + private OsuScreenStack stack; - protected ScreenTestCase() + [BackgroundDependencyLoader] + private void load() { Child = stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }; } From 256a579de02228bb3e243c6c6b350c4907eabb63 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 13:17:00 +0900 Subject: [PATCH 0417/5608] Allow player to not pause on focus loss --- osu.Game/Screens/Play/Player.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7b1cdd21a6..f2fd7e765f 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -47,6 +47,8 @@ namespace osu.Game.Screens.Play public bool AllowLeadIn { get; set; } = true; public bool AllowResults { get; set; } = true; + public bool PauseOnFocusLost { get; set; } = true; + private Bindable mouseWheelDisabled; private readonly Bindable storyboardReplacesBackground = new Bindable(); @@ -372,7 +374,7 @@ namespace osu.Game.Screens.Play base.Update(); // eagerly pause when we lose window focus (if we are locally playing). - if (!Game.IsActive.Value) + if (PauseOnFocusLost && !Game.IsActive.Value) Pause(); } From 85c63f14f2e630c5eadf1b66646bb658cdabdd43 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 13:18:33 +0900 Subject: [PATCH 0418/5608] Add comprehensive player resume testing --- .../Visual/Gameplay/TestCasePause.cs | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs index 1ed61c9fe1..a52e84ed62 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs @@ -1,13 +1,19 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using NUnit.Framework; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Cursor; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; +using osuTK; +using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { @@ -15,14 +21,52 @@ namespace osu.Game.Tests.Visual.Gameplay { protected new PausePlayer Player => (PausePlayer)base.Player; + private readonly Container content; + + protected override Container Content => content; + public TestCasePause() : base(new OsuRuleset()) { + base.Content.Add(content = new MenuCursorContainer { RelativeSizeAxes = Axes.Both }); } [Test] public void TestPauseResume() { + AddStep("move cursor outside", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft - new Vector2(10))); + pauseAndConfirm(); + resumeAndConfirm(); + } + + [Test] + public void TestResumeWithResumeOverlay() + { + AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre)); + AddUntilStep("wait for hitobjects", () => Player.ScoreProcessor.Health.Value < 1); + + pauseAndConfirm(); + resume(); + + confirmClockRunning(false); + confirmPauseOverlayShown(false); + + AddStep("click to resume", () => + { + InputManager.PressButton(MouseButton.Left); + InputManager.ReleaseButton(MouseButton.Left); + }); + + confirmClockRunning(true); + } + + [Test] + public void TestResumeWithResumeOverlaySkipped() + { + AddStep("move cursor to button", () => + InputManager.MoveMouseTo(Player.HUDOverlay.HoldToQuit.Children.OfType().First().ScreenSpaceDrawQuad.Centre)); + AddUntilStep("wait for hitobjects", () => Player.ScoreProcessor.Health.Value < 1); + pauseAndConfirm(); resumeAndConfirm(); } @@ -30,6 +74,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestPauseTooSoon() { + AddStep("move cursor outside", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft - new Vector2(10))); + pauseAndConfirm(); resumeAndConfirm(); @@ -144,9 +190,16 @@ namespace osu.Game.Tests.Visual.Gameplay public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + public new HUDOverlay HUDOverlay => base.HUDOverlay; + public bool FailOverlayVisible => FailOverlay.State == Visibility.Visible; public bool PauseOverlayVisible => PauseOverlay.State == Visibility.Visible; + + public PausePlayer() + { + PauseOnFocusLost = false; + } } } } From 27cb4ce0d1a761b1e9df48f92cdd74802c46d061 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 13:48:35 +0900 Subject: [PATCH 0419/5608] Remove poop --- osu.Game/Rulesets/UI/RulesetInputManager.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 150c53274f..656170f339 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -39,10 +39,6 @@ namespace osu.Game.Rulesets.UI private readonly Container content; - private class Poop : Container - { - } - protected RulesetInputManager(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) { InternalChild = KeyBindingContainer = From fb302e7ad8e464ac6dd6950c0972819e213147b6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 13:58:07 +0900 Subject: [PATCH 0420/5608] Remove using --- osu.Game/Rulesets/UI/RulesetInputManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 656170f339..3ce8f92458 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -6,7 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; From 3fe52be77febe7ce3e41cc1762717cdd71b02db6 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 26 Mar 2019 17:18:35 +0900 Subject: [PATCH 0421/5608] Better tests, add documentation --- .../Visual/Gameplay/TestCasePlayerLoader.cs | 7 +- .../Visual/TestCaseFacadeContainer.cs | 30 ++++--- .../Graphics/Containers/FacadeContainer.cs | 78 ++++++++++++------- osu.Game/Screens/Menu/ButtonSystem.cs | 63 +++++++-------- osu.Game/Screens/Play/PlayerLoader.cs | 37 +++++---- 5 files changed, 121 insertions(+), 94 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs index 67dba71d45..be2a21d23d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs @@ -7,16 +7,13 @@ using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Screens; -using osu.Game.Screens.Menu; using osu.Game.Screens.Play; -using osuTK; namespace osu.Game.Tests.Visual.Gameplay { public class TestCasePlayerLoader : ManualInputManagerTestCase { private PlayerLoader loader; - private readonly OsuScreenStack stack; public TestCasePlayerLoader() @@ -29,8 +26,6 @@ namespace osu.Game.Tests.Visual.Gameplay { Beatmap.Value = new DummyWorkingBeatmap(game); - AddStep("Reset logo position", () => logo = new OsuLogo { Position = new Vector2(0, 0) }); - AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => new Player { AllowPause = false, @@ -58,6 +53,8 @@ namespace osu.Game.Tests.Visual.Gameplay AllowLeadIn = false, AllowResults = false, })); + + Scheduler.AddDelayed(() => slow.Ready = true, 5000); }); AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen()); diff --git a/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs index 5591bec0b8..0d4caff97e 100644 --- a/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs @@ -11,7 +11,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Testing; +using osu.Framework.Graphics.UserInterface; using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osu.Game.Rulesets.Mods; @@ -31,7 +31,11 @@ namespace osu.Game.Tests.Visual typeof(PlayerLoader), typeof(Player), typeof(Facade), - typeof(FacadeContainer) + typeof(FacadeContainer), + typeof(ButtonSystem), + typeof(ButtonSystemState), + typeof(Menu), + typeof(MainMenu) }; [Cached] @@ -68,15 +72,10 @@ namespace osu.Game.Tests.Visual AllowPause = false, AllowLeadIn = false, AllowResults = false, + Ready = false }))); } - [Test] - public void MainMenuTest() - { - AddStep("Add new Main Menu", () => LoadScreen(new MainMenu())); - } - private class TestFacadeContainer : FacadeContainer { protected override Facade CreateFacade() => new Facade @@ -119,16 +118,23 @@ namespace osu.Game.Tests.Visual base.LogoArriving(logo, resuming); logo.FadeIn(350); logo.ScaleTo(new Vector2(0.15f), 350, Easing.In); - facadeContainer.SetLogo(logo); + facadeContainer.SetLogo(logo, 0.3f, 1000, Easing.InOutQuint); + facadeContainer.Tracking = true; moveLogoFacade(); } + protected override void LogoExiting(OsuLogo logo) + { + base.LogoExiting(logo); + facadeContainer.Tracking = false; + } + private void moveLogoFacade() { Random random = new Random(); if (facadeFlowComponent.Transforms.Count == 0) { - facadeFlowComponent.Delay(500).MoveTo(new Vector2(random.Next(0, 800), random.Next(0, 600)), 300); + facadeFlowComponent.Delay(500).MoveTo(new Vector2(random.Next(0, (int)DrawWidth), random.Next(0, (int)DrawHeight)), 300); } if (randomPositions) @@ -159,11 +165,13 @@ namespace osu.Game.Tests.Visual private class TestPlayer : Player { + public bool Ready; + [BackgroundDependencyLoader] private void load() { // Never finish loading - while (true) + while (!Ready) Thread.Sleep(1); } } diff --git a/osu.Game/Graphics/Containers/FacadeContainer.cs b/osu.Game/Graphics/Containers/FacadeContainer.cs index 611cc94958..47ba738f1c 100644 --- a/osu.Game/Graphics/Containers/FacadeContainer.cs +++ b/osu.Game/Graphics/Containers/FacadeContainer.cs @@ -10,80 +10,98 @@ using osuTK; namespace osu.Game.Graphics.Containers { + /// + /// A container that creates a to be used by its children. + /// This container also updates the position and size of the Facade, and contains logic for tracking an on the Facade's position. + /// public class FacadeContainer : Container { + protected virtual Facade CreateFacade() => new Facade(); + + public Facade Facade => facade; + + /// + /// Whether or not the logo assigned to this FacadeContainer should be tracking the position its facade. + /// + public bool Tracking; + [Cached] private Facade facade; private OsuLogo logo; + private float facadeScale; - private bool tracking; - - protected virtual Facade CreateFacade() => new Facade(); + private Vector2 startPosition; + private Easing easing; + private double startTime; + private double duration; public FacadeContainer() { facade = CreateFacade(); } - private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(facade.ScreenSpaceDrawQuad.Centre); - - public void SetLogo(OsuLogo logo, double transformDelay = 0) + /// + /// Set the logo that should track the Facade's position, as well as how it should transform to its initial position. + /// + /// The instance of the logo to be used for tracking. + /// The scale of the facade. + /// The duration of the initial transform. Default is instant. + /// The easing type of the initial transform. + public void SetLogo(OsuLogo logo, float facadeScale, double duration = 0, Easing easing = Easing.None) { if (logo != null) { - facade.Size = new Vector2(logo.SizeForFlow * 0.3f); this.logo = logo; - Scheduler.AddDelayed(() => - { - tracking = true; - }, transformDelay); } + + this.facadeScale = facadeScale; + this.duration = duration; + this.easing = easing; } - private double startTime; - private double duration = 1000; - - private Vector2 startPosition; - private Easing easing = Easing.InOutExpo; + private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(facade.ScreenSpaceDrawQuad.Centre); protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - if (logo == null || !tracking) + if (logo == null || !Tracking) return; - facade.Size = new Vector2(logo.SizeForFlow * 0.3f); + facade.Size = new Vector2(logo.SizeForFlow * facadeScale); if (facade.IsLoaded && logo.Position != logoTrackingPosition) { - if (logo.RelativePositionAxes != Axes.None) - { - logo.RelativePositionAxes = Axes.None; - logo.Position = logo.Parent.ToLocalSpace(logo.Position); - } + // Required for the correct position of the logo to be set with respect to logoTrackingPosition + logo.RelativePositionAxes = Axes.None; + // If this is our first update since tracking has started, initialize our starting values for interpolation if (startTime == 0) { startTime = Time.Current; + startPosition = logo.Position; } var endTime = startTime + duration; var remainingDuration = endTime - Time.Current; - if (remainingDuration <= 0) - { - remainingDuration = 0; - } + // If our transform should be instant, our position should already be at logoTrackingPosition, thus set the blend to 0. + // If we are already past when the transform should be finished playing, set the blend to 0 so that the logo is always at the position of the facade. + var blend = duration > 0 && remainingDuration > 0 + ? (float)Interpolation.ApplyEasing(easing, remainingDuration / duration) + : 0; - float currentTime = (float)Interpolation.ApplyEasing(easing, remainingDuration / duration); - logo.Position = Vector2.Lerp(logoTrackingPosition, startPosition, currentTime); + // Interpolate the position of the logo, where blend 0 is the position of the Facade, and blend 1 is where the logo was when it first began interpolating. + logo.Position = Vector2.Lerp(logoTrackingPosition, startPosition, blend); } } } } +/// +/// A placeholder container that serves as a dummy object to denote another object's location and size. +/// public class Facade : Container { -} \ No newline at end of file +} diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 3df4ef9059..4c0bcd399a 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; @@ -16,6 +17,7 @@ using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Threading; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.Online.API; @@ -53,15 +55,19 @@ namespace osu.Game.Screens.Menu if (this.logo != null) { this.logo.Action = onOsuLogo; + facadeContainer.SetLogo(logo, 0.5f); // osuLogo.SizeForFlow relies on loading to be complete. buttonArea.Flow.Position = new Vector2(WEDGE_WIDTH * 2 - (BUTTON_WIDTH + this.logo.SizeForFlow / 4), 0); updateLogoState(); } + else + { + facadeContainer.Tracking = false; + } } - private readonly Drawable iconFacade; private readonly ButtonArea buttonArea; private readonly Button backButton; @@ -71,26 +77,29 @@ namespace osu.Game.Screens.Menu private SampleChannel sampleBack; + private readonly FacadeContainer facadeContainer; + public ButtonSystem() { RelativeSizeAxes = Axes.Both; - Child = buttonArea = new ButtonArea(); + Child = facadeContainer = new FacadeContainer + { + RelativeSizeAxes = Axes.Both, + Child = buttonArea = new ButtonArea() + }; - buttonArea.AddRange(new[] + buttonArea.AddRange(new Container[] { new Button(@"settings", string.Empty, FontAwesome.fa_gear, new Color4(85, 85, 85, 255), () => OnSettings?.Invoke(), -WEDGE_WIDTH, Key.O), backButton = new Button(@"back", @"button-back-select", FontAwesome.fa_osu_left_o, new Color4(51, 58, 94, 255), () => State = ButtonSystemState.TopLevel, -WEDGE_WIDTH) { VisibleState = ButtonSystemState.Play, }, - iconFacade = new Container //need a container to make the osu! icon flow properly. - { - Size = new Vector2(0, ButtonArea.BUTTON_AREA_HEIGHT) - } + facadeContainer.Facade }); - buttonArea.Flow.CentreTarget = iconFacade; + buttonArea.Flow.CentreTarget = facadeContainer.Facade; } [Resolved(CanBeNull = true)] @@ -120,6 +129,15 @@ namespace osu.Game.Screens.Menu buttonArea.AddRange(buttonsPlay); buttonArea.AddRange(buttonsTopLevel); + buttonArea.ForEach(b => + { + if (b is Button) + { + b.Origin = Anchor.CentreLeft; + b.Anchor = Anchor.CentreLeft; + } + }); + isIdle.ValueChanged += idle => updateIdleState(idle.NewValue); if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle); @@ -247,7 +265,7 @@ namespace osu.Game.Screens.Menu logoDelayedAction?.Cancel(); logoDelayedAction = Scheduler.AddDelayed(() => { - logoTracking = false; + facadeContainer.Tracking = false; game?.Toolbar.Hide(); @@ -266,19 +284,16 @@ namespace osu.Game.Screens.Menu break; case ButtonSystemState.Initial: logo.ClearTransforms(targetMember: nameof(Position)); - logo.RelativePositionAxes = Axes.None; bool impact = logo.Scale.X > 0.6f; if (lastState == ButtonSystemState.Initial) logo.ScaleTo(0.5f, 200, Easing.In); - logo.MoveTo(logoTrackingPosition, lastState == ButtonSystemState.EnteringMode ? 0 : 200, Easing.In); - logoDelayedAction?.Cancel(); logoDelayedAction = Scheduler.AddDelayed(() => { - logoTracking = true; + facadeContainer.Tracking = true; if (impact) logo.Impact(); @@ -288,35 +303,17 @@ namespace osu.Game.Screens.Menu break; default: logo.ClearTransforms(targetMember: nameof(Position)); - logo.RelativePositionAxes = Axes.None; - logoTracking = true; + facadeContainer.Tracking = true; logo.ScaleTo(0.5f, 200, Easing.OutQuint); break; } break; case ButtonSystemState.EnteringMode: - logoTracking = true; + facadeContainer.Tracking = true; break; } } - - private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(iconFacade.ScreenSpaceDrawQuad.Centre); - - private bool logoTracking; - - protected override void Update() - { - base.Update(); - - if (logo != null) - { - if (logoTracking && logo.RelativePositionAxes == Axes.None && iconFacade.IsLoaded) - logo.Position = logoTrackingPosition; - - iconFacade.Width = logo.SizeForFlow * 0.5f; - } - } } public enum ButtonSystemState diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index b7155f771f..f35eb6979d 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Play private Player player; - private FacadeContainer content; + private FacadeContainer facadeContainer; protected virtual FacadeContainer CreateFacadeContainer() => new FacadeContainer(); @@ -62,11 +62,11 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load() { - InternalChild = content = CreateFacadeContainer(); - content.Anchor = Anchor.Centre; - content.Origin = Anchor.Centre; - content.RelativeSizeAxes = Axes.Both; - content.Children = new Drawable[] + InternalChild = facadeContainer = CreateFacadeContainer(); + facadeContainer.Anchor = Anchor.Centre; + facadeContainer.Origin = Anchor.Centre; + facadeContainer.RelativeSizeAxes = Axes.Both; + facadeContainer.Children = new Drawable[] { info = new BeatmapMetadataDisplay(Beatmap.Value) { @@ -122,21 +122,21 @@ namespace osu.Game.Screens.Play private void contentIn() { - content.ScaleTo(1, 650, Easing.OutQuint); - content.FadeInFromZero(400); + facadeContainer.ScaleTo(1, 650, Easing.OutQuint); + facadeContainer.FadeInFromZero(400); } private void contentOut() { - content.ScaleTo(0.7f, 300, Easing.InQuint); - content.FadeOut(250); + facadeContainer.ScaleTo(0.7f, 300, Easing.InQuint); + facadeContainer.FadeOut(250); } public override void OnEntering(IScreen last) { base.OnEntering(last); - content.ScaleTo(0.7f); + facadeContainer.ScaleTo(0.7f); Background?.FadeColour(Color4.White, 800, Easing.OutQuint); contentIn(); @@ -155,7 +155,15 @@ namespace osu.Game.Screens.Play logo.MoveTo(new Vector2(0.5f), duration, Easing.In); logo.FadeIn(350); - content.SetLogo(logo, duration); + facadeContainer.SetLogo(logo, 0.3f, 500, Easing.InOutQuint); + + Scheduler.AddDelayed(() => facadeContainer.Tracking = true, duration); + } + + protected override void LogoExiting(OsuLogo logo) + { + base.LogoExiting(logo); + facadeContainer.Tracking = false; } protected override void LoadComplete() @@ -230,7 +238,7 @@ namespace osu.Game.Screens.Play public override bool OnExiting(IScreen next) { - content.ScaleTo(0.7f, 150, Easing.InQuint); + facadeContainer.ScaleTo(0.7f, 150, Easing.InQuint); this.FadeOut(150); cancelLoad(); @@ -305,7 +313,6 @@ namespace osu.Game.Screens.Play private LoadingAnimation loading; private Sprite backgroundSprite; private ModDisplay modDisplay; - private FillFlowContainer fillFlowContainer; public bool Loading { @@ -340,7 +347,7 @@ namespace osu.Game.Screens.Play AutoSizeAxes = Axes.Both; Children = new Drawable[] { - fillFlowContainer = new FillFlowContainer + new FillFlowContainer { AutoSizeAxes = Axes.Both, Origin = Anchor.TopCentre, From adab31fd582dfe6509e863f3f221b012271142b1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 26 Mar 2019 17:38:56 +0900 Subject: [PATCH 0422/5608] Cleanup + fix up score table layout --- .../Online/TestCaseBeatmapSetOverlay.cs | 6 +- .../TestCaseBeatmapScoresContainer.cs | 5 +- .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 237 +++-------------- .../BeatmapSet/Scores/ScoreTableHeader.cs | 70 ----- .../BeatmapSet/Scores/ScoreTableHeaderRow.cs | 46 ++++ .../BeatmapSet/Scores/ScoreTableRow.cs | 246 ++++++------------ .../Scores/ScoreTableRowBackground.cs | 64 +++++ .../BeatmapSet/Scores/ScoreTableScore.cs | 220 ---------------- .../BeatmapSet/Scores/ScoreTableScoreRow.cs | 168 ++++++++++++ 9 files changed, 401 insertions(+), 661 deletions(-) delete mode 100644 osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeader.cs create mode 100644 osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs create mode 100644 osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs delete mode 100644 osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScore.cs create mode 100644 osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs diff --git a/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs index df24c42b00..19d295cf12 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs @@ -25,7 +25,11 @@ namespace osu.Game.Tests.Visual.Online { typeof(Header), typeof(ClickableUserContainer), - typeof(ScoreTableScore), + typeof(ScoreTable), + typeof(ScoreTableRow), + typeof(ScoreTableHeaderRow), + typeof(ScoreTableScoreRow), + typeof(ScoreTableRowBackground), typeof(DrawableTopScore), typeof(ScoresContainer), typeof(AuthorInfo), diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs index 2bc0796045..63dacef8fa 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs @@ -28,8 +28,9 @@ namespace osu.Game.Tests.Visual.SongSelect typeof(ScoresContainer), typeof(ScoreTable), typeof(ScoreTableRow), - typeof(ScoreTableHeader), - typeof(ScoreTableScore) + typeof(ScoreTableHeaderRow), + typeof(ScoreTableScoreRow), + typeof(ScoreTableRowBackground), }; private readonly Box background; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 7e838f0aae..e2acf778a3 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -6,203 +6,74 @@ using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; using System.Collections.Generic; using System.Linq; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; -using osu.Game.Graphics; -using osu.Game.Online.Leaderboards; -using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; -using osu.Game.Users; -using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Scores { public class ScoreTable : CompositeDrawable { - private const int fade_duration = 100; - private const int text_size = 14; - - private readonly FillFlowContainer scoresFlow; private readonly ScoresGrid scoresGrid; + private readonly FillFlowContainer backgroundFlow; public ScoreTable() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - InternalChild = scoresGrid = new ScoresGrid + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.X, - ColumnDimensions = new[] + backgroundFlow = new FillFlowContainer { - new Dimension(GridSizeMode.Absolute, 40), - new Dimension(GridSizeMode.Absolute, 70), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Distributed, minSize: 180), - new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), - new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), - new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), - new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), - new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), - new Dimension(GridSizeMode.Distributed, minSize: 40, maxSize: 70), - new Dimension(GridSizeMode.AutoSize), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Top = 25 } + }, + scoresGrid = new ScoresGrid + { + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, 40), + new Dimension(GridSizeMode.Absolute, 70), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Distributed, minSize: 150), + new Dimension(GridSizeMode.Distributed, minSize: 70, maxSize: 90), + new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), + new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), + new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), + new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), + new Dimension(GridSizeMode.Distributed, minSize: 40, maxSize: 70), + new Dimension(GridSizeMode.AutoSize), + } } }; - - scoresFlow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical - }; } public IEnumerable Scores { set { - scoresFlow.Clear(); - if (value == null || !value.Any()) return; - int maxModsAmount = 0; - foreach (var s in value) - { - var scoreModsAmount = s.Mods.Length; - if (scoreModsAmount > maxModsAmount) - maxModsAmount = scoreModsAmount; - } - - scoresFlow.Add(new ScoreTableHeader(maxModsAmount)); + var content = new List { new ScoreTableHeaderRow().CreateDrawables().ToArray() }; int index = 0; foreach (var s in value) - scoresFlow.Add(new ScoreTableScore(index++, s, maxModsAmount)); + content.Add(new ScoreTableScoreRow(index++, s).CreateDrawables().ToArray()); - scoresGrid.Content = value.Select((s, i) => createRowContents(s, i).ToArray()).ToArray(); + scoresGrid.Content = content.ToArray(); + + backgroundFlow.Clear(); + for (int i = 0; i < index; i++) + backgroundFlow.Add(new ScoreTableRowBackground(i)); } } - private IEnumerable createRowContents(APIScoreInfo score, int index) - { - yield return new SpriteText - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Text = $"#{index + 1}", - Font = @"Exo2.0-Bold", - TextSize = text_size, - }; - - yield return new DrawableRank(score.Rank) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(30, 20), - FillMode = FillMode.Fit, - }; - - yield return new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Margin = new MarginPadding { Right = 20 }, - Text = $@"{score.TotalScore:N0}", - TextSize = text_size, - Font = index == 0 ? OsuFont.GetFont(weight: FontWeight.Bold) : OsuFont.Default - }; - - yield return new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Margin = new MarginPadding { Right = 20 }, - Text = $@"{score.Accuracy:P2}", - TextSize = text_size, - Colour = score.Accuracy == 1 ? Color4.GreenYellow : Color4.White - }; - - yield return new FillFlowContainer - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5, 0), - Children = new Drawable[] - { - new DrawableFlag(score.User.Country) - { - Size = new Vector2(20, 13), - }, - new ClickableScoreUsername - { - User = score.User, - } - } - }; - - yield return new SpriteText - { - Text = $@"{score.MaxCombo:N0}x", - TextSize = text_size, - }; - - yield return new SpriteText - { - Text = $"{score.Statistics[HitResult.Great]}", - TextSize = text_size, - Colour = score.Statistics[HitResult.Great] == 0 ? Color4.Gray : Color4.White - }; - - yield return new SpriteText - { - Text = $"{score.Statistics[HitResult.Good]}", - TextSize = text_size, - Colour = score.Statistics[HitResult.Good] == 0 ? Color4.Gray : Color4.White - }; - - yield return new SpriteText - { - Text = $"{score.Statistics[HitResult.Meh]}", - TextSize = text_size, - Colour = score.Statistics[HitResult.Meh] == 0 ? Color4.Gray : Color4.White - }; - - yield return new SpriteText - { - Text = $"{score.Statistics[HitResult.Miss]}", - TextSize = text_size, - Colour = score.Statistics[HitResult.Miss] == 0 ? Color4.Gray : Color4.White - }; - - yield return new SpriteText - { - Text = $@"{score.PP:N0}", - TextSize = text_size, - }; - - yield return new FillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - ChildrenEnumerable = score.Mods.Select(m => new ModIcon(m) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Scale = new Vector2(0.3f), - }) - }; - } - private class ScoresGrid : GridContainer { public ScoresGrid() { + RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; } @@ -217,49 +88,5 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } } - - private class ClickableScoreUsername : ClickableUserContainer - { - private readonly SpriteText text; - private readonly SpriteText textBold; - - public ClickableScoreUsername() - { - Add(text = new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - TextSize = text_size, - }); - - Add(textBold = new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - TextSize = text_size, - Font = @"Exo2.0-Bold", - Alpha = 0, - }); - } - - protected override void OnUserChange(User user) - { - text.Text = textBold.Text = user.Username; - } - - protected override bool OnHover(HoverEvent e) - { - textBold.FadeIn(fade_duration, Easing.OutQuint); - text.FadeOut(fade_duration, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - textBold.FadeOut(fade_duration, Easing.OutQuint); - text.FadeIn(fade_duration, Easing.OutQuint); - base.OnHoverLost(e); - } - } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeader.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeader.cs deleted file mode 100644 index 544bf34ec5..0000000000 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeader.cs +++ /dev/null @@ -1,70 +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.Sprites; - -namespace osu.Game.Overlays.BeatmapSet.Scores -{ - public class ScoreTableHeader : ScoreTableRow - { - public ScoreTableHeader(int maxModsAmount) - : base(maxModsAmount) - { - RankContainer.Add(new ScoreText - { - Text = @"rank".ToUpper(), - }); - ScoreContainer.Add(new ScoreText - { - Text = @"score".ToUpper(), - }); - AccuracyContainer.Add(new ScoreText - { - Text = @"accuracy".ToUpper(), - }); - PlayerContainer.Add(new ScoreText - { - Text = @"player".ToUpper(), - }); - MaxComboContainer.Add(new ScoreText - { - Text = @"max combo".ToUpper(), - }); - HitGreatContainer.Add(new ScoreText - { - Text = "300".ToUpper(), - }); - HitGoodContainer.Add(new ScoreText - { - Text = "100".ToUpper(), - }); - HitMehContainer.Add(new ScoreText - { - Text = "50".ToUpper(), - }); - HitMissContainer.Add(new ScoreText - { - Text = @"misses".ToUpper(), - }); - PPContainer.Add(new ScoreText - { - Text = @"pp".ToUpper(), - }); - ModsContainer.Add(new ScoreText - { - Text = @"mods".ToUpper(), - }); - } - - private class ScoreText : SpriteText - { - private const float text_size = 12; - - public ScoreText() - { - TextSize = text_size; - Font = @"Exo2.0-Black"; - } - } - } -} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs new file mode 100644 index 0000000000..a48716b71a --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs @@ -0,0 +1,46 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Overlays.BeatmapSet.Scores +{ + public class ScoreTableHeaderRow : ScoreTableRow + { + protected override Drawable CreateIndexCell() => new CellText("rank"); + + protected override Drawable CreateRankCell() => new Container(); + + protected override Drawable CreateScoreCell() => new CellText("score"); + + protected override Drawable CreateAccuracyCell() => new CellText("accuracy"); + + protected override Drawable CreatePlayerCell() => new CellText("player"); + + protected override IEnumerable CreateStatisticsCells() => new[] + { + new CellText("max combo"), + new CellText("300"), + new CellText("100"), + new CellText("50"), + new CellText("miss"), + }; + + protected override Drawable CreatePpCell() => new CellText("pp"); + + protected override Drawable CreateModsCell() => new CellText("mods"); + + private class CellText : OsuSpriteText + { + public CellText(string text) + { + Text = text.ToUpper(); + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black); + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs index 3a48a0cca1..4abfb92957 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs @@ -1,183 +1,103 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class ScoreTableRow : GridContainer + public abstract class ScoreTableRow { - private const float rank_position = 30; - private const float drawable_rank_position = 45; - private const float score_position = 90; - private const float accuracy_position = 170; - private const float flag_position = 220; - private const float player_position = 250; + protected const int TEXT_SIZE = 14; - private const float max_combo_position = 0.1f; - private const float hit_great_position = 0.3f; - private const float hit_good_position = 0.45f; - private const float hit_meh_position = 0.6f; - private const float hit_miss_position = 0.75f; - private const float pp_position = 0.9f; - - protected readonly Container RankContainer; - protected readonly Container DrawableRankContainer; - protected readonly Container ScoreContainer; - protected readonly Container AccuracyContainer; - protected readonly Container FlagContainer; - protected readonly Container PlayerContainer; - protected readonly Container MaxComboContainer; - protected readonly Container HitGreatContainer; - protected readonly Container HitGoodContainer; - protected readonly Container HitMehContainer; - protected readonly Container HitMissContainer; - protected readonly Container PPContainer; - protected readonly Container ModsContainer; - - public ScoreTableRow(int maxModsAmount) + public IEnumerable CreateDrawables() { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - RowDimensions = new[] + yield return new Container { - new Dimension(GridSizeMode.Absolute, 25), + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Child = CreateIndexCell() }; - ColumnDimensions = new[] + + yield return new Container { - new Dimension(GridSizeMode.Absolute, 300), - new Dimension(), - new Dimension(GridSizeMode.AutoSize), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Child = CreateRankCell() }; - Content = new[] + + yield return new Container { - new Drawable[] + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Right = 20 }, + Child = CreateScoreCell() + }; + + yield return new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Right = 20 }, + Child = CreateAccuracyCell() + }; + + yield return new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Right = 20 }, + Child = CreatePlayerCell() + }; + + foreach (var cell in CreateStatisticsCells()) + { + yield return new Container { - new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - RankContainer = new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - X = rank_position, - }, - DrawableRankContainer = new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - X = drawable_rank_position, - }, - ScoreContainer = new Container - { - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - X = score_position, - }, - AccuracyContainer = new Container - { - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - X = accuracy_position, - }, - FlagContainer = new Container - { - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - X = flag_position, - }, - PlayerContainer = new Container - { - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - X = player_position, - } - } - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Children = new Drawable[] - { - MaxComboContainer = new Container - { - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - RelativePositionAxes = Axes.X, - X = max_combo_position, - }, - HitGreatContainer = new Container - { - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - RelativePositionAxes = Axes.X, - X = hit_great_position, - }, - HitGoodContainer = new Container - { - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - RelativePositionAxes = Axes.X, - X = hit_good_position, - }, - HitMehContainer = new Container - { - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - RelativePositionAxes = Axes.X, - X = hit_meh_position, - }, - HitMissContainer = new Container - { - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - RelativePositionAxes = Axes.X, - X = hit_miss_position, - }, - PPContainer = new Container - { - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - RelativePositionAxes = Axes.X, - X = pp_position, - } - } - }, - new Container - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Child = ModsContainer = new Container - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - X = -30 * ((maxModsAmount == 0) ? 1 : maxModsAmount), - } - } - } + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Child = cell + }; + } + + yield return new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Child = CreatePpCell() + }; + + yield return new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Child = CreateModsCell() }; } + + protected abstract Drawable CreateIndexCell(); + + protected abstract Drawable CreateRankCell(); + + protected abstract Drawable CreateScoreCell(); + + protected abstract Drawable CreateAccuracyCell(); + + protected abstract Drawable CreatePlayerCell(); + + protected abstract IEnumerable CreateStatisticsCells(); + + protected abstract Drawable CreatePpCell(); + + protected abstract Drawable CreateModsCell(); } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs new file mode 100644 index 0000000000..d820f4d89d --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs @@ -0,0 +1,64 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Graphics; + +namespace osu.Game.Overlays.BeatmapSet.Scores +{ + public class ScoreTableRowBackground : CompositeDrawable + { + private const int fade_duration = 100; + + private readonly Box hoveredBackground; + private readonly Box background; + + public ScoreTableRowBackground(int index) + { + RelativeSizeAxes = Axes.X; + Height = 25; + + CornerRadius = 3; + Masking = true; + + InternalChildren = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + hoveredBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + }, + }; + + if (index % 2 != 0) + background.Alpha = 0; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + hoveredBackground.Colour = colours.Gray4; + background.Colour = colours.Gray3; + } + + protected override bool OnHover(HoverEvent e) + { + hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); + base.OnHoverLost(e); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScore.cs deleted file mode 100644 index a54770fb39..0000000000 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScore.cs +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; -using osu.Game.Graphics; -using osu.Game.Online.API.Requests.Responses; -using osu.Game.Online.Leaderboards; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; -using osu.Game.Users; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Overlays.BeatmapSet.Scores -{ - public class ScoreTableScore : Container - { - private const int fade_duration = 100; - private const int text_size = 14; - - private readonly Box hoveredBackground; - private readonly Box background; - - public ScoreTableScore(int index, APIScoreInfo score, int maxModsAmount) - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - CornerRadius = 3; - Masking = true; - - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - hoveredBackground = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - }, - new ScoreRow(index, score, maxModsAmount), - }; - - if (index % 2 != 0) - background.Alpha = 0; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - hoveredBackground.Colour = colours.Gray4; - background.Colour = colours.Gray3; - } - - protected override bool OnHover(HoverEvent e) - { - hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); - base.OnHoverLost(e); - } - - protected override bool OnClick(ClickEvent e) => true; - - private class ClickableScoreUsername : ClickableUserContainer - { - private readonly SpriteText text; - private readonly SpriteText textBold; - - public ClickableScoreUsername() - { - Add(text = new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - TextSize = text_size, - }); - - Add(textBold = new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - TextSize = text_size, - Font = @"Exo2.0-Bold", - Alpha = 0, - }); - } - - protected override void OnUserChange(User user) - { - text.Text = textBold.Text = user.Username; - } - - protected override bool OnHover(HoverEvent e) - { - textBold.FadeIn(fade_duration, Easing.OutQuint); - text.FadeOut(fade_duration, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - textBold.FadeOut(fade_duration, Easing.OutQuint); - text.FadeIn(fade_duration, Easing.OutQuint); - base.OnHoverLost(e); - } - } - - private class ScoreRow : ScoreTableRow - { - public ScoreRow(int index, APIScoreInfo score, int maxModsAmount) - : base(maxModsAmount) - { - SpriteText scoreText; - SpriteText accuracy; - SpriteText hitGreat; - SpriteText hitGood; - SpriteText hitMeh; - SpriteText hitMiss; - - FillFlowContainer modsContainer; - - RankContainer.Add(new SpriteText - { - Text = $"#{index + 1}", - Font = @"Exo2.0-Bold", - TextSize = text_size, - }); - DrawableRankContainer.Add(new DrawableRank(score.Rank) - { - Size = new Vector2(30, 20), - FillMode = FillMode.Fit, - }); - ScoreContainer.Add(scoreText = new SpriteText - { - Text = $@"{score.TotalScore:N0}", - TextSize = text_size, - }); - AccuracyContainer.Add(accuracy = new SpriteText - { - Text = $@"{score.Accuracy:P2}", - TextSize = text_size, - }); - FlagContainer.Add(new DrawableFlag(score.User.Country) - { - Size = new Vector2(20, 13), - }); - PlayerContainer.Add(new ClickableScoreUsername - { - User = score.User, - }); - MaxComboContainer.Add(new SpriteText - { - Text = $@"{score.MaxCombo:N0}x", - TextSize = text_size, - }); - HitGreatContainer.Add(hitGreat = new SpriteText - { - Text = $"{score.Statistics[HitResult.Great]}", - TextSize = text_size, - }); - HitGoodContainer.Add(hitGood = new SpriteText - { - Text = $"{score.Statistics[HitResult.Good]}", - TextSize = text_size, - }); - HitMehContainer.Add(hitMeh = new SpriteText - { - Text = $"{score.Statistics[HitResult.Meh]}", - TextSize = text_size, - }); - HitMissContainer.Add(hitMiss = new SpriteText - { - Text = $"{score.Statistics[HitResult.Miss]}", - TextSize = text_size, - }); - PPContainer.Add(new SpriteText - { - Text = $@"{score.PP:N0}", - TextSize = text_size, - }); - ModsContainer.Add(modsContainer = new FillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - }); - - if (index == 0) - scoreText.Font = @"Exo2.0-Bold"; - - accuracy.Colour = (score.Accuracy == 1) ? Color4.GreenYellow : Color4.White; - hitGreat.Colour = (score.Statistics[HitResult.Great] == 0) ? Color4.Gray : Color4.White; - hitGood.Colour = (score.Statistics[HitResult.Good] == 0) ? Color4.Gray : Color4.White; - hitMeh.Colour = (score.Statistics[HitResult.Meh] == 0) ? Color4.Gray : Color4.White; - hitMiss.Colour = (score.Statistics[HitResult.Miss] == 0) ? Color4.Gray : Color4.White; - - foreach (Mod mod in score.Mods) - modsContainer.Add(new ModIcon(mod) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Scale = new Vector2(0.3f), - }); - } - } - } -} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs new file mode 100644 index 0000000000..cd1ade934a --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs @@ -0,0 +1,168 @@ +// 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; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.Leaderboards; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Scoring; +using osu.Game.Users; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.BeatmapSet.Scores +{ + public class ScoreTableScoreRow : ScoreTableRow + { + private readonly int index; + private readonly ScoreInfo score; + + public ScoreTableScoreRow(int index, ScoreInfo score) + { + this.index = index; + this.score = score; + } + + protected override Drawable CreateIndexCell() => new OsuSpriteText + { + Text = $"#{index + 1}", + Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold) + }; + + protected override Drawable CreateRankCell() => new DrawableRank(score.Rank) + { + Size = new Vector2(30, 20), + }; + + protected override Drawable CreateScoreCell() => new OsuSpriteText + { + Text = $@"{score.TotalScore:N0}", + Font = OsuFont.GetFont(size: TEXT_SIZE, weight: index == 0 ? FontWeight.Bold : FontWeight.Medium) + }; + + protected override Drawable CreateAccuracyCell() => new OsuSpriteText + { + Text = $@"{score.Accuracy:P2}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + Colour = score.Accuracy == 1 ? Color4.GreenYellow : Color4.White + }; + + protected override Drawable CreatePlayerCell() => new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + Children = new Drawable[] + { + new DrawableFlag(score.User.Country) { Size = new Vector2(20, 13) }, + new ClickableScoreUsername { User = score.User } + } + }; + + protected override IEnumerable CreateStatisticsCells() + { + yield return new OsuSpriteText + { + Text = $@"{score.MaxCombo:N0}x", + Font = OsuFont.GetFont(size: TEXT_SIZE) + }; + + yield return new OsuSpriteText + { + Text = $"{score.Statistics[HitResult.Great]}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + Colour = score.Statistics[HitResult.Great] == 0 ? Color4.Gray : Color4.White + }; + + yield return new OsuSpriteText + { + Text = $"{score.Statistics[HitResult.Good]}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + Colour = score.Statistics[HitResult.Good] == 0 ? Color4.Gray : Color4.White + }; + + yield return new OsuSpriteText + { + Text = $"{score.Statistics[HitResult.Meh]}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + Colour = score.Statistics[HitResult.Meh] == 0 ? Color4.Gray : Color4.White + }; + + yield return new OsuSpriteText + { + Text = $"{score.Statistics[HitResult.Miss]}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + Colour = score.Statistics[HitResult.Miss] == 0 ? Color4.Gray : Color4.White + }; + } + + protected override Drawable CreatePpCell() => new OsuSpriteText + { + Text = $@"{score.PP:N0}", + Font = OsuFont.GetFont(size: TEXT_SIZE) + }; + + protected override Drawable CreateModsCell() => new FillFlowContainer + { + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + ChildrenEnumerable = score.Mods.Select(m => new ModIcon(m) + { + AutoSizeAxes = Axes.Both, + Scale = new Vector2(0.3f) + }) + }; + + private class ClickableScoreUsername : ClickableUserContainer + { + private const int fade_duration = 100; + + private readonly SpriteText text; + private readonly SpriteText textBold; + + public ClickableScoreUsername() + { + Add(text = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: TEXT_SIZE) + }); + + Add(textBold = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold), + Alpha = 0, + }); + } + + protected override void OnUserChange(User user) + { + text.Text = textBold.Text = user.Username; + } + + protected override bool OnHover(HoverEvent e) + { + textBold.FadeIn(fade_duration, Easing.OutQuint); + text.FadeOut(fade_duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + textBold.FadeOut(fade_duration, Easing.OutQuint); + text.FadeIn(fade_duration, Easing.OutQuint); + base.OnHoverLost(e); + } + } + } +} From 384eee33957a30c88ec2b8ff2baffa30ede3bb98 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 27 Mar 2019 11:32:26 +0900 Subject: [PATCH 0423/5608] Remove DI requirement for the Facade in PlayerLoader --- .../Visual/TestCaseFacadeContainer.cs | 11 +++-------- osu.Game/Graphics/Containers/FacadeContainer.cs | 17 ++++++----------- osu.Game/Screens/Play/PlayerLoader.cs | 8 +++++--- 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs index 0d4caff97e..6291b026f3 100644 --- a/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs @@ -93,7 +93,7 @@ namespace osu.Game.Tests.Visual private class TestScreen : OsuScreen { private TestFacadeContainer facadeContainer; - private FacadeFlowComponent facadeFlowComponent; + private Facade facadeFlowComponent; private readonly bool randomPositions; public TestScreen(bool randomPositions = false) @@ -104,13 +104,8 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - InternalChild = facadeContainer = new TestFacadeContainer - { - Child = facadeFlowComponent = new FacadeFlowComponent - { - AutoSizeAxes = Axes.Both - } - }; + InternalChild = facadeContainer = new TestFacadeContainer(); + facadeContainer.Child = facadeFlowComponent = facadeContainer.Facade; } protected override void LogoArriving(OsuLogo logo, bool resuming) diff --git a/osu.Game/Graphics/Containers/FacadeContainer.cs b/osu.Game/Graphics/Containers/FacadeContainer.cs index 47ba738f1c..11c256725d 100644 --- a/osu.Game/Graphics/Containers/FacadeContainer.cs +++ b/osu.Game/Graphics/Containers/FacadeContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; @@ -18,19 +17,15 @@ namespace osu.Game.Graphics.Containers { protected virtual Facade CreateFacade() => new Facade(); - public Facade Facade => facade; + public readonly Facade Facade; /// /// Whether or not the logo assigned to this FacadeContainer should be tracking the position its facade. /// public bool Tracking; - [Cached] - private Facade facade; - private OsuLogo logo; private float facadeScale; - private Vector2 startPosition; private Easing easing; private double startTime; @@ -38,11 +33,11 @@ namespace osu.Game.Graphics.Containers public FacadeContainer() { - facade = CreateFacade(); + Facade = CreateFacade(); } /// - /// Set the logo that should track the Facade's position, as well as how it should transform to its initial position. + /// Assign the logo that should track the Facade's position, as well as how it should transform to its initial position. /// /// The instance of the logo to be used for tracking. /// The scale of the facade. @@ -60,7 +55,7 @@ namespace osu.Game.Graphics.Containers this.easing = easing; } - private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(facade.ScreenSpaceDrawQuad.Centre); + private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(Facade.ScreenSpaceDrawQuad.Centre); protected override void UpdateAfterChildren() { @@ -69,9 +64,9 @@ namespace osu.Game.Graphics.Containers if (logo == null || !Tracking) return; - facade.Size = new Vector2(logo.SizeForFlow * facadeScale); + Facade.Size = new Vector2(logo.SizeForFlow * facadeScale); - if (facade.IsLoaded && logo.Position != logoTrackingPosition) + if (Facade.IsLoaded && logo.Position != logoTrackingPosition) { // Required for the correct position of the logo to be set with respect to logoTrackingPosition logo.RelativePositionAxes = Axes.None; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index f35eb6979d..4601cf71e0 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -68,7 +68,7 @@ namespace osu.Game.Screens.Play facadeContainer.RelativeSizeAxes = Axes.Both; facadeContainer.Children = new Drawable[] { - info = new BeatmapMetadataDisplay(Beatmap.Value) + info = new BeatmapMetadataDisplay(Beatmap.Value, facadeContainer.Facade) { Alpha = 0, Anchor = Anchor.Centre, @@ -310,6 +310,7 @@ namespace osu.Game.Screens.Play } private readonly WorkingBeatmap beatmap; + private readonly Facade facade; private LoadingAnimation loading; private Sprite backgroundSprite; private ModDisplay modDisplay; @@ -331,13 +332,14 @@ namespace osu.Game.Screens.Play } } - public BeatmapMetadataDisplay(WorkingBeatmap beatmap) + public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Facade facade) { this.beatmap = beatmap; + this.facade = facade; } [BackgroundDependencyLoader] - private void load(Facade facade) + private void load() { var metadata = beatmap.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); From efeed715170c5e9e45501cabda7da80d59f947fa Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 27 Mar 2019 11:37:16 +0900 Subject: [PATCH 0424/5608] Add comment --- osu.Game/Screens/Menu/ButtonSystem.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 4c0bcd399a..7b458809b1 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -64,6 +64,8 @@ namespace osu.Game.Screens.Menu } else { + // If logo is null, we are suspending from the screen that uses this ButtonSystem. + // We should stop tracking as the facade is now out of scope. facadeContainer.Tracking = false; } } From 43c6a8d2e59a3fbdba14ce3014abaa289d32bef8 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 27 Mar 2019 11:44:50 +0900 Subject: [PATCH 0425/5608] use a property instead --- osu.Game/Graphics/Containers/FacadeContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/FacadeContainer.cs b/osu.Game/Graphics/Containers/FacadeContainer.cs index 11c256725d..0ec5e77c72 100644 --- a/osu.Game/Graphics/Containers/FacadeContainer.cs +++ b/osu.Game/Graphics/Containers/FacadeContainer.cs @@ -17,7 +17,7 @@ namespace osu.Game.Graphics.Containers { protected virtual Facade CreateFacade() => new Facade(); - public readonly Facade Facade; + public Facade Facade { get; } /// /// Whether or not the logo assigned to this FacadeContainer should be tracking the position its facade. From 7239ebf5deb6b0809e453fa8e9fcd1c1b61056a5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Mar 2019 13:57:26 +0900 Subject: [PATCH 0426/5608] Add margin for mods --- osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs index 4abfb92957..8efda73270 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs @@ -80,6 +80,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Right = 20 }, Child = CreateModsCell() }; } From 4b1e564df2fe8d7882725ad71b744dd6ffc70f42 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 27 Mar 2019 14:31:07 +0900 Subject: [PATCH 0427/5608] Fix test cases potentially getting stuck after 4th run --- osu.Game.Tests/Visual/TestCaseFacadeContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs index 6291b026f3..55842af867 100644 --- a/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs @@ -163,10 +163,10 @@ namespace osu.Game.Tests.Visual public bool Ready; [BackgroundDependencyLoader] - private void load() + private void load(CancellationToken token) { // Never finish loading - while (!Ready) + while (!Ready && !token.IsCancellationRequested) Thread.Sleep(1); } } From ca7a20585dbb58b09b7426949e0ad4b28543efd5 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 27 Mar 2019 17:28:53 +0900 Subject: [PATCH 0428/5608] Apply reviews, delete playerloader test --- ...iner.cs => TestCaseLogoFacadeContainer.cs} | 72 +++---------- .../Graphics/Containers/FacadeContainer.cs | 102 ------------------ .../Containers/LogoFacadeContainer.cs | 100 +++++++++++++++++ osu.Game/Screens/Menu/ButtonSystem.cs | 25 +++-- osu.Game/Screens/Play/PlayerLoader.cs | 70 ++++++------ 5 files changed, 161 insertions(+), 208 deletions(-) rename osu.Game.Tests/Visual/{TestCaseFacadeContainer.cs => TestCaseLogoFacadeContainer.cs} (60%) delete mode 100644 osu.Game/Graphics/Containers/FacadeContainer.cs create mode 100644 osu.Game/Graphics/Containers/LogoFacadeContainer.cs diff --git a/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs similarity index 60% rename from osu.Game.Tests/Visual/TestCaseFacadeContainer.cs rename to osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs index 55842af867..0e7f4d4bc0 100644 --- a/osu.Game.Tests/Visual/TestCaseFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs @@ -9,7 +9,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Game.Configuration; @@ -24,14 +23,14 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual { - public class TestCaseFacadeContainer : ScreenTestCase + public class TestCaseLogoFacadeContainer : ScreenTestCase { public override IReadOnlyList RequiredTypes => new[] { typeof(PlayerLoader), typeof(Player), - typeof(Facade), - typeof(FacadeContainer), + typeof(LogoFacadeContainer.Facade), + typeof(LogoFacadeContainer), typeof(ButtonSystem), typeof(ButtonSystemState), typeof(Menu), @@ -43,7 +42,7 @@ namespace osu.Game.Tests.Visual private readonly Bindable uiScale = new Bindable(); - public TestCaseFacadeContainer() + public TestCaseLogoFacadeContainer() { Add(logo = new OsuLogo()); } @@ -63,20 +62,7 @@ namespace osu.Game.Tests.Visual AddStep("Move facade to random position", () => LoadScreen(new TestScreen(randomPositions))); } - [Test] - public void PlayerLoaderTest() - { - AddToggleStep("Toggle mods", b => { Beatmap.Value.Mods.Value = b ? Beatmap.Value.Mods.Value.Concat(new[] { new OsuModNoFail() }) : Enumerable.Empty(); }); - AddStep("Add new playerloader", () => LoadScreen(new TestPlayerLoader(() => new TestPlayer - { - AllowPause = false, - AllowLeadIn = false, - AllowResults = false, - Ready = false - }))); - } - - private class TestFacadeContainer : FacadeContainer + private class TestLogoFacadeContainer : LogoFacadeContainer { protected override Facade CreateFacade() => new Facade { @@ -92,8 +78,8 @@ namespace osu.Game.Tests.Visual private class TestScreen : OsuScreen { - private TestFacadeContainer facadeContainer; - private Facade facadeFlowComponent; + private TestLogoFacadeContainer logoFacadeContainer; + private LogoFacadeContainer.Facade facadeFlowComponent; private readonly bool randomPositions; public TestScreen(bool randomPositions = false) @@ -104,8 +90,8 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - InternalChild = facadeContainer = new TestFacadeContainer(); - facadeContainer.Child = facadeFlowComponent = facadeContainer.Facade; + InternalChild = logoFacadeContainer = new TestLogoFacadeContainer(); + logoFacadeContainer.Child = facadeFlowComponent = logoFacadeContainer.LogoFacade; } protected override void LogoArriving(OsuLogo logo, bool resuming) @@ -113,15 +99,15 @@ namespace osu.Game.Tests.Visual base.LogoArriving(logo, resuming); logo.FadeIn(350); logo.ScaleTo(new Vector2(0.15f), 350, Easing.In); - facadeContainer.SetLogo(logo, 0.3f, 1000, Easing.InOutQuint); - facadeContainer.Tracking = true; + logoFacadeContainer.SetLogo(logo, 0.3f, 1000, Easing.InOutQuint); + logoFacadeContainer.Tracking = true; moveLogoFacade(); } protected override void LogoExiting(OsuLogo logo) { base.LogoExiting(logo); - facadeContainer.Tracking = false; + logoFacadeContainer.Tracking = false; } private void moveLogoFacade() @@ -136,39 +122,5 @@ namespace osu.Game.Tests.Visual Schedule(moveLogoFacade); } } - - private class FacadeFlowComponent : FillFlowContainer - { - [BackgroundDependencyLoader] - private void load(Facade facade) - { - facade.Anchor = Anchor.TopCentre; - facade.Origin = Anchor.TopCentre; - Child = facade; - } - } - - private class TestPlayerLoader : PlayerLoader - { - public TestPlayerLoader(Func player) - : base(player) - { - } - - protected override FacadeContainer CreateFacadeContainer() => new TestFacadeContainer(); - } - - private class TestPlayer : Player - { - public bool Ready; - - [BackgroundDependencyLoader] - private void load(CancellationToken token) - { - // Never finish loading - while (!Ready && !token.IsCancellationRequested) - Thread.Sleep(1); - } - } } } diff --git a/osu.Game/Graphics/Containers/FacadeContainer.cs b/osu.Game/Graphics/Containers/FacadeContainer.cs deleted file mode 100644 index 0ec5e77c72..0000000000 --- a/osu.Game/Graphics/Containers/FacadeContainer.cs +++ /dev/null @@ -1,102 +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.MathUtils; -using osu.Game.Screens.Menu; -using osuTK; - -namespace osu.Game.Graphics.Containers -{ - /// - /// A container that creates a to be used by its children. - /// This container also updates the position and size of the Facade, and contains logic for tracking an on the Facade's position. - /// - public class FacadeContainer : Container - { - protected virtual Facade CreateFacade() => new Facade(); - - public Facade Facade { get; } - - /// - /// Whether or not the logo assigned to this FacadeContainer should be tracking the position its facade. - /// - public bool Tracking; - - private OsuLogo logo; - private float facadeScale; - private Vector2 startPosition; - private Easing easing; - private double startTime; - private double duration; - - public FacadeContainer() - { - Facade = CreateFacade(); - } - - /// - /// Assign the logo that should track the Facade's position, as well as how it should transform to its initial position. - /// - /// The instance of the logo to be used for tracking. - /// The scale of the facade. - /// The duration of the initial transform. Default is instant. - /// The easing type of the initial transform. - public void SetLogo(OsuLogo logo, float facadeScale, double duration = 0, Easing easing = Easing.None) - { - if (logo != null) - { - this.logo = logo; - } - - this.facadeScale = facadeScale; - this.duration = duration; - this.easing = easing; - } - - private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(Facade.ScreenSpaceDrawQuad.Centre); - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - if (logo == null || !Tracking) - return; - - Facade.Size = new Vector2(logo.SizeForFlow * facadeScale); - - if (Facade.IsLoaded && logo.Position != logoTrackingPosition) - { - // Required for the correct position of the logo to be set with respect to logoTrackingPosition - logo.RelativePositionAxes = Axes.None; - - // If this is our first update since tracking has started, initialize our starting values for interpolation - if (startTime == 0) - { - startTime = Time.Current; - startPosition = logo.Position; - } - - var endTime = startTime + duration; - var remainingDuration = endTime - Time.Current; - - // If our transform should be instant, our position should already be at logoTrackingPosition, thus set the blend to 0. - // If we are already past when the transform should be finished playing, set the blend to 0 so that the logo is always at the position of the facade. - var blend = duration > 0 && remainingDuration > 0 - ? (float)Interpolation.ApplyEasing(easing, remainingDuration / duration) - : 0; - - // Interpolate the position of the logo, where blend 0 is the position of the Facade, and blend 1 is where the logo was when it first began interpolating. - logo.Position = Vector2.Lerp(logoTrackingPosition, startPosition, blend); - } - } - } -} - -/// -/// A placeholder container that serves as a dummy object to denote another object's location and size. -/// -public class Facade : Container -{ -} diff --git a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs new file mode 100644 index 0000000000..a556fa697c --- /dev/null +++ b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs @@ -0,0 +1,100 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.MathUtils; +using osu.Game.Screens.Menu; +using osuTK; + +namespace osu.Game.Graphics.Containers +{ + /// + /// A container that creates a to be used to update and track the position of an . + /// + public class LogoFacadeContainer : Container + { + protected virtual Facade CreateFacade() => new Facade(); + + public Facade LogoFacade { get; } + + /// + /// Whether or not the logo assigned to this FacadeContainer should be tracking the position its facade. + /// + public bool Tracking = false; + + private OsuLogo logo; + private float facadeScale; + private Vector2 startPosition; + private Easing easing; + private double? startTime; + private double duration; + + public LogoFacadeContainer() + { + LogoFacade = CreateFacade(); + } + + /// + /// Assign the logo that should track the Facade's position, as well as how it should transform to its initial position. + /// + /// The instance of the logo to be used for tracking. + /// The scale of the facade. Does not actually affect the logo itself. + /// The duration of the initial transform. Default is instant. + /// The easing type of the initial transform. + public void SetLogo(OsuLogo logo, float facadeScale, double duration = 0, Easing easing = Easing.None) + { + this.logo = logo ?? throw new ArgumentNullException(nameof(logo)); + this.facadeScale = facadeScale; + this.duration = duration; + this.easing = easing; + } + + private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre); + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + if (logo == null || !Tracking) + return; + + LogoFacade.Size = new Vector2(logo.SizeForFlow * facadeScale); + + if (LogoFacade.Parent != null && logo.Position != logoTrackingPosition) + { + // Required for the correct position of the logo to be set with respect to logoTrackingPosition + logo.RelativePositionAxes = Axes.None; + + // If this is our first update since tracking has started, initialize our starting values for interpolation + if (startTime == null) + { + startTime = Time.Current; + startPosition = logo.Position; + } + + if (duration != 0) + { + double elapsedDuration = Time.Current - startTime ?? 0; + + var mount = (float)Interpolation.ApplyEasing(easing, Math.Min(elapsedDuration / duration, 1)); + + // Interpolate the position of the logo, where mount 0 is where the logo was when it first began interpolating, and mount 1 is the target location. + logo.Position = Vector2.Lerp(startPosition, logoTrackingPosition, mount); + } + else + { + logo.Position = logoTrackingPosition; + } + } + } + + /// + /// A placeholder container that serves as a dummy object to denote another object's location and size. + /// + public class Facade : Container + { + } + } +} diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 7b458809b1..3fad36cddb 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -48,6 +48,10 @@ namespace osu.Game.Screens.Menu private OsuLogo logo; + /// + /// Assign the that this ButtonSystem should manage the position of. + /// + /// The instance of the logo to be assigned. If null, we are suspending from the screen that uses this ButtonSystem. public void SetOsuLogo(OsuLogo logo) { this.logo = logo; @@ -55,7 +59,7 @@ namespace osu.Game.Screens.Menu if (this.logo != null) { this.logo.Action = onOsuLogo; - facadeContainer.SetLogo(logo, 0.5f); + logoFacadeContainer.SetLogo(logo, 0.5f); // osuLogo.SizeForFlow relies on loading to be complete. buttonArea.Flow.Position = new Vector2(WEDGE_WIDTH * 2 - (BUTTON_WIDTH + this.logo.SizeForFlow / 4), 0); @@ -64,9 +68,8 @@ namespace osu.Game.Screens.Menu } else { - // If logo is null, we are suspending from the screen that uses this ButtonSystem. // We should stop tracking as the facade is now out of scope. - facadeContainer.Tracking = false; + logoFacadeContainer.Tracking = false; } } @@ -79,13 +82,13 @@ namespace osu.Game.Screens.Menu private SampleChannel sampleBack; - private readonly FacadeContainer facadeContainer; + private readonly LogoFacadeContainer logoFacadeContainer; public ButtonSystem() { RelativeSizeAxes = Axes.Both; - Child = facadeContainer = new FacadeContainer + Child = logoFacadeContainer = new LogoFacadeContainer { RelativeSizeAxes = Axes.Both, Child = buttonArea = new ButtonArea() @@ -98,10 +101,10 @@ namespace osu.Game.Screens.Menu { VisibleState = ButtonSystemState.Play, }, - facadeContainer.Facade + logoFacadeContainer.LogoFacade }); - buttonArea.Flow.CentreTarget = facadeContainer.Facade; + buttonArea.Flow.CentreTarget = logoFacadeContainer.LogoFacade; } [Resolved(CanBeNull = true)] @@ -267,7 +270,7 @@ namespace osu.Game.Screens.Menu logoDelayedAction?.Cancel(); logoDelayedAction = Scheduler.AddDelayed(() => { - facadeContainer.Tracking = false; + logoFacadeContainer.Tracking = false; game?.Toolbar.Hide(); @@ -295,7 +298,7 @@ namespace osu.Game.Screens.Menu logoDelayedAction?.Cancel(); logoDelayedAction = Scheduler.AddDelayed(() => { - facadeContainer.Tracking = true; + logoFacadeContainer.Tracking = true; if (impact) logo.Impact(); @@ -305,14 +308,14 @@ namespace osu.Game.Screens.Menu break; default: logo.ClearTransforms(targetMember: nameof(Position)); - facadeContainer.Tracking = true; + logoFacadeContainer.Tracking = true; logo.ScaleTo(0.5f, 200, Easing.OutQuint); break; } break; case ButtonSystemState.EnteringMode: - facadeContainer.Tracking = true; + logoFacadeContainer.Tracking = true; break; } } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 4601cf71e0..6ac2c8220f 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -33,9 +33,7 @@ namespace osu.Game.Screens.Play private Player player; - private FacadeContainer facadeContainer; - - protected virtual FacadeContainer CreateFacadeContainer() => new FacadeContainer(); + private LogoFacadeContainer content; private BeatmapMetadataDisplay info; @@ -62,30 +60,32 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load() { - InternalChild = facadeContainer = CreateFacadeContainer(); - facadeContainer.Anchor = Anchor.Centre; - facadeContainer.Origin = Anchor.Centre; - facadeContainer.RelativeSizeAxes = Axes.Both; - facadeContainer.Children = new Drawable[] + InternalChild = content = new LogoFacadeContainer { - info = new BeatmapMetadataDisplay(Beatmap.Value, facadeContainer.Facade) + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - Alpha = 0, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - new FillFlowContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 20), - Margin = new MarginPadding(25), - Children = new PlayerSettingsGroup[] + info = new BeatmapMetadataDisplay(Beatmap.Value, content.LogoFacade) { - VisualSettings = new VisualSettings(), - new InputSettings() + Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), + Margin = new MarginPadding(25), + Children = new PlayerSettingsGroup[] + { + VisualSettings = new VisualSettings(), + new InputSettings() + } } } }; @@ -122,21 +122,21 @@ namespace osu.Game.Screens.Play private void contentIn() { - facadeContainer.ScaleTo(1, 650, Easing.OutQuint); - facadeContainer.FadeInFromZero(400); + content.ScaleTo(1, 650, Easing.OutQuint); + content.FadeInFromZero(400); } private void contentOut() { - facadeContainer.ScaleTo(0.7f, 300, Easing.InQuint); - facadeContainer.FadeOut(250); + content.ScaleTo(0.7f, 300, Easing.InQuint); + content.FadeOut(250); } public override void OnEntering(IScreen last) { base.OnEntering(last); - facadeContainer.ScaleTo(0.7f); + content.ScaleTo(0.7f); Background?.FadeColour(Color4.White, 800, Easing.OutQuint); contentIn(); @@ -155,15 +155,15 @@ namespace osu.Game.Screens.Play logo.MoveTo(new Vector2(0.5f), duration, Easing.In); logo.FadeIn(350); - facadeContainer.SetLogo(logo, 0.3f, 500, Easing.InOutQuint); + content.SetLogo(logo, 0.3f, 500, Easing.InOutExpo); - Scheduler.AddDelayed(() => facadeContainer.Tracking = true, duration); + Scheduler.AddDelayed(() => content.Tracking = true, resuming ? 0 : 500); } protected override void LogoExiting(OsuLogo logo) { base.LogoExiting(logo); - facadeContainer.Tracking = false; + content.Tracking = false; } protected override void LoadComplete() @@ -238,7 +238,7 @@ namespace osu.Game.Screens.Play public override bool OnExiting(IScreen next) { - facadeContainer.ScaleTo(0.7f, 150, Easing.InQuint); + content.ScaleTo(0.7f, 150, Easing.InQuint); this.FadeOut(150); cancelLoad(); @@ -310,7 +310,7 @@ namespace osu.Game.Screens.Play } private readonly WorkingBeatmap beatmap; - private readonly Facade facade; + private readonly LogoFacadeContainer.Facade facade; private LoadingAnimation loading; private Sprite backgroundSprite; private ModDisplay modDisplay; @@ -332,7 +332,7 @@ namespace osu.Game.Screens.Play } } - public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Facade facade) + public BeatmapMetadataDisplay(WorkingBeatmap beatmap, LogoFacadeContainer.Facade facade) { this.beatmap = beatmap; this.facade = facade; From 34a33b335d1e5046cd1cc5f9712f5994753d8fc9 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 27 Mar 2019 17:29:38 +0900 Subject: [PATCH 0429/5608] oops --- osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs index 0e7f4d4bc0..152b9b1706 100644 --- a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs @@ -3,8 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Threading; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -13,8 +11,6 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Game.Configuration; using osu.Game.Graphics.Containers; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens; using osu.Game.Screens.Menu; using osu.Game.Screens.Play; From 2e3791be1ca9e67676e4b5b42be184cd7c001060 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 27 Mar 2019 18:11:12 +0900 Subject: [PATCH 0430/5608] Fix incorrect usage of LogoFacade --- osu.Game/Screens/Play/PlayerLoader.cs | 39 ++++++++++++++------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 6ac2c8220f..3f547755c1 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -65,27 +65,28 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + }; + + content.Children = new Drawable[] + { + info = new BeatmapMetadataDisplay(Beatmap.Value, content.LogoFacade) { - info = new BeatmapMetadataDisplay(Beatmap.Value, content.LogoFacade) + Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), + Margin = new MarginPadding(25), + Children = new PlayerSettingsGroup[] { - Alpha = 0, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - new FillFlowContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 20), - Margin = new MarginPadding(25), - Children = new PlayerSettingsGroup[] - { - VisualSettings = new VisualSettings(), - new InputSettings() - } + VisualSettings = new VisualSettings(), + new InputSettings() } } }; From 061527a260241e78b5ce479006f6c91e2b91e271 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 27 Mar 2019 20:04:01 +0900 Subject: [PATCH 0431/5608] Add new automated tests for logofacade, reset interpolation --- .../Visual/TestCaseLogoFacadeContainer.cs | 115 ++++++++++++++---- .../Containers/LogoFacadeContainer.cs | 11 +- osu.Game/Screens/Play/PlayerLoader.cs | 4 +- 3 files changed, 103 insertions(+), 27 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs index 152b9b1706..8be0d25a86 100644 --- a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs @@ -7,8 +7,10 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Screens; using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osu.Game.Screens; @@ -25,7 +27,6 @@ namespace osu.Game.Tests.Visual { typeof(PlayerLoader), typeof(Player), - typeof(LogoFacadeContainer.Facade), typeof(LogoFacadeContainer), typeof(ButtonSystem), typeof(ButtonSystemState), @@ -47,36 +48,65 @@ namespace osu.Game.Tests.Visual private void load(OsuConfigManager config) { config.BindWith(OsuSetting.UIScale, uiScale); - AddSliderStep("Adjust scale", 1f, 1.5f, 1f, v => uiScale.Value = v); + AddSliderStep("Adjust scale", 0.8f, 1.5f, 1f, v => uiScale.Value = v); } + /// + /// Move the facade to 0,0, then move it to a random new location while the logo is still transforming to it. + /// Check if the logo is still tracking the facade. + /// [Test] - public void IsolatedTest() + public void MoveFacadeTest() { + TestScreen screen = null; bool randomPositions = false; AddToggleStep("Toggle move continuously", b => randomPositions = b); - AddStep("Move facade to random position", () => LoadScreen(new TestScreen(randomPositions))); + AddStep("Move facade to random position", () => LoadScreen(screen = new TestScreen(randomPositions))); + AddUntilStep("Screen is current", () => screen.IsCurrentScreen()); + waitForMove(); + AddAssert("Logo is tracking", () => screen.IsLogoTracking); } - private class TestLogoFacadeContainer : LogoFacadeContainer + /// + /// Check if the facade is removed from the container, the logo stops tracking. + /// + [Test] + public void RemoveFacadeTest() { - protected override Facade CreateFacade() => new Facade - { - Colour = Color4.Tomato, - Alpha = 0.35f, - Child = new Box - { - Colour = Color4.Tomato, - RelativeSizeAxes = Axes.Both, - }, - }; + TestScreen screen = null; + AddStep("Move facade to random position", () => LoadScreen(screen = new TestScreen())); + AddUntilStep("Screen is current", () => screen.IsCurrentScreen()); + AddStep("Remove facade from FacadeContainer", () => screen.RemoveFacade()); + waitForMove(); + AddAssert("Logo is not tracking", () => !screen.IsLogoTracking); } + /// + /// Check if the facade gets added to a new container, tracking starts on the new facade. + /// + [Test] + public void TransferFacadeTest() + { + TestScreen screen = null; + AddStep("Move facade to random position", () => LoadScreen(screen = new TestScreen())); + AddUntilStep("Screen is current", () => screen.IsCurrentScreen()); + AddStep("Remove facade from FacadeContainer", () => screen.RemoveFacade()); + AddStep("Transfer facade to a new container", () => screen.TransferFacade()); + waitForMove(); + AddAssert("Logo is tracking", () => screen.IsLogoTracking); + } + + private void waitForMove() => AddWaitStep("Wait for transforms to finish", 5); + private class TestScreen : OsuScreen { - private TestLogoFacadeContainer logoFacadeContainer; - private LogoFacadeContainer.Facade facadeFlowComponent; + private LogoFacadeContainer logoFacadeContainer; + private Container transferContainer; + private Container logoFacade; private readonly bool randomPositions; + private OsuLogo logo; + private Box visualBox; + private Box transferContainerBox; public TestScreen(bool randomPositions = false) { @@ -86,13 +116,55 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - InternalChild = logoFacadeContainer = new TestLogoFacadeContainer(); - logoFacadeContainer.Child = facadeFlowComponent = logoFacadeContainer.LogoFacade; + InternalChildren = new Drawable[] + { + logoFacadeContainer = new LogoFacadeContainer + { + Alpha = 0.35f, + RelativeSizeAxes = Axes.None, + Size = new Vector2(107), + Child = visualBox = new Box + { + Colour = Color4.Tomato, + RelativeSizeAxes = Axes.Both, + } + }, + transferContainer = new Container + { + Alpha = 0.35f, + RelativeSizeAxes = Axes.None, + Size = new Vector2(107), + Child = transferContainerBox = new Box + { + Colour = Color4.White, + RelativeSizeAxes = Axes.Both, + } + }, + }; + + logoFacadeContainer.Add(logoFacade = logoFacadeContainer.LogoFacade); + } + + public bool IsLogoTracking => logo.Position == logo.Parent.ToLocalSpace(logoFacadeContainer.LogoFacade.ScreenSpaceDrawQuad.Centre); + + public void RemoveFacade() + { + logoFacadeContainer.Remove(logoFacade); + visualBox.Colour = Color4.White; + moveLogoFacade(); + } + + public void TransferFacade() + { + transferContainer.Add(logoFacade); + transferContainerBox.Colour = Color4.Tomato; + moveLogoFacade(); } protected override void LogoArriving(OsuLogo logo, bool resuming) { base.LogoArriving(logo, resuming); + this.logo = logo; logo.FadeIn(350); logo.ScaleTo(new Vector2(0.15f), 350, Easing.In); logoFacadeContainer.SetLogo(logo, 0.3f, 1000, Easing.InOutQuint); @@ -109,9 +181,10 @@ namespace osu.Game.Tests.Visual private void moveLogoFacade() { Random random = new Random(); - if (facadeFlowComponent.Transforms.Count == 0) + if (logoFacade.Transforms.Count == 0 && transferContainer.Transforms.Count == 0) { - facadeFlowComponent.Delay(500).MoveTo(new Vector2(random.Next(0, (int)DrawWidth), random.Next(0, (int)DrawHeight)), 300); + logoFacadeContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)DrawWidth), random.Next(0, (int)DrawHeight)), 300); + transferContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)DrawWidth), random.Next(0, (int)DrawHeight)), 300); } if (randomPositions) diff --git a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs index a556fa697c..f4599e0039 100644 --- a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs +++ b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs @@ -26,8 +26,8 @@ namespace osu.Game.Graphics.Containers private OsuLogo logo; private float facadeScale; - private Vector2 startPosition; private Easing easing; + private Vector2? startPosition; private double? startTime; private double duration; @@ -49,6 +49,9 @@ namespace osu.Game.Graphics.Containers this.facadeScale = facadeScale; this.duration = duration; this.easing = easing; + + startTime = null; + startPosition = null; } private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre); @@ -68,7 +71,7 @@ namespace osu.Game.Graphics.Containers logo.RelativePositionAxes = Axes.None; // If this is our first update since tracking has started, initialize our starting values for interpolation - if (startTime == null) + if (startTime == null || startPosition == null) { startTime = Time.Current; startPosition = logo.Position; @@ -76,12 +79,12 @@ namespace osu.Game.Graphics.Containers if (duration != 0) { - double elapsedDuration = Time.Current - startTime ?? 0; + double elapsedDuration = Time.Current - startTime ?? throw new ArgumentNullException(nameof(startTime)); var mount = (float)Interpolation.ApplyEasing(easing, Math.Min(elapsedDuration / duration, 1)); // Interpolate the position of the logo, where mount 0 is where the logo was when it first began interpolating, and mount 1 is the target location. - logo.Position = Vector2.Lerp(startPosition, logoTrackingPosition, mount); + logo.Position = Vector2.Lerp(startPosition ?? throw new ArgumentNullException(nameof(startPosition)), logoTrackingPosition, mount); } else { diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 3f547755c1..72fbb378a4 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -311,7 +311,7 @@ namespace osu.Game.Screens.Play } private readonly WorkingBeatmap beatmap; - private readonly LogoFacadeContainer.Facade facade; + private readonly Container facade; private LoadingAnimation loading; private Sprite backgroundSprite; private ModDisplay modDisplay; @@ -333,7 +333,7 @@ namespace osu.Game.Screens.Play } } - public BeatmapMetadataDisplay(WorkingBeatmap beatmap, LogoFacadeContainer.Facade facade) + public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Container facade) { this.beatmap = beatmap; this.facade = facade; From 9b047d9b90c112013369959d23fb1703775ac52d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 28 Mar 2019 12:00:50 +0900 Subject: [PATCH 0432/5608] Add back menu logo transform --- osu.Game/Screens/Menu/ButtonSystem.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 3fad36cddb..21305c6489 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -295,11 +295,12 @@ namespace osu.Game.Screens.Menu if (lastState == ButtonSystemState.Initial) logo.ScaleTo(0.5f, 200, Easing.In); + logoFacadeContainer.SetLogo(logo, 0.5f, lastState == ButtonSystemState.EnteringMode ? 0 : 200, Easing.In); + logoFacadeContainer.Tracking = true; + logoDelayedAction?.Cancel(); logoDelayedAction = Scheduler.AddDelayed(() => { - logoFacadeContainer.Tracking = true; - if (impact) logo.Impact(); From bfe44eb33d7df500b5031171b928c9320b347473 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 28 Mar 2019 15:40:58 +0900 Subject: [PATCH 0433/5608] Remove SizeForFlow magic number --- osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs | 7 ++++++- osu.Game/Graphics/Containers/LogoFacadeContainer.cs | 3 ++- osu.Game/Screens/Menu/OsuLogo.cs | 2 +- osu.Game/Screens/Play/PlayerLoader.cs | 3 ++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs index 8be0d25a86..f81e70e7b0 100644 --- a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs @@ -145,7 +145,12 @@ namespace osu.Game.Tests.Visual logoFacadeContainer.Add(logoFacade = logoFacadeContainer.LogoFacade); } - public bool IsLogoTracking => logo.Position == logo.Parent.ToLocalSpace(logoFacadeContainer.LogoFacade.ScreenSpaceDrawQuad.Centre); + private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(logoFacade.ScreenSpaceDrawQuad.Centre); + + /// + /// Check that the logo is tracking the position of the facade, with an acceptable precision lenience. + /// + public bool IsLogoTracking => Math.Abs(logo.Position.X - logoTrackingPosition.X) < 0.001f && Math.Abs(logo.Position.Y - logoTrackingPosition.Y) < 0.001f; public void RemoveFacade() { diff --git a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs index f4599e0039..547af87522 100644 --- a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs +++ b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs @@ -63,7 +63,8 @@ namespace osu.Game.Graphics.Containers if (logo == null || !Tracking) return; - LogoFacade.Size = new Vector2(logo.SizeForFlow * facadeScale); + // Account for the scale of the actual logo container, as SizeForFlow only accounts for the sprite scale. + LogoFacade.Size = new Vector2(logo.SizeForFlow * logo.Scale.X * facadeScale); if (LogoFacade.Parent != null && logo.Position != logoTrackingPosition) { diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index af697d37bd..c54ccd21b5 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -54,7 +54,7 @@ namespace osu.Game.Screens.Menu /// public Func Action; - public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * logoHoverContainer.Scale.X * 0.74f; + public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * logoHoverContainer.Scale.X; private readonly Sprite ripple; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 72fbb378a4..5a8c3846fa 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -156,7 +156,7 @@ namespace osu.Game.Screens.Play logo.MoveTo(new Vector2(0.5f), duration, Easing.In); logo.FadeIn(350); - content.SetLogo(logo, 0.3f, 500, Easing.InOutExpo); + content.SetLogo(logo, 1.0f, 500, Easing.InOutExpo); Scheduler.AddDelayed(() => content.Tracking = true, resuming ? 0 : 500); } @@ -365,6 +365,7 @@ namespace osu.Game.Screens.Play Font = OsuFont.GetFont(size: 36, italics: true), Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, + Margin = new MarginPadding { Top = 15 }, }, new OsuSpriteText { From 039e451ab1b4eee334c937a9bcaf3320118e1f48 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 28 Mar 2019 16:09:42 +0900 Subject: [PATCH 0434/5608] ensure logo is where it already needs to be on resume --- osu.Game/Screens/Play/PlayerLoader.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 5a8c3846fa..da5abbae95 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -152,8 +152,12 @@ namespace osu.Game.Screens.Play const double duration = 300; + if (!resuming) + { + logo.MoveTo(new Vector2(0.5f), duration, Easing.In); + } + logo.ScaleTo(new Vector2(0.15f), duration, Easing.In); - logo.MoveTo(new Vector2(0.5f), duration, Easing.In); logo.FadeIn(350); content.SetLogo(logo, 1.0f, 500, Easing.InOutExpo); From 9d66a5e4b20841ed8d6222a71e5767a4fe7c6eaa Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 28 Mar 2019 16:29:35 +0900 Subject: [PATCH 0435/5608] Ensure logo stops tracking before suspend animation --- osu.Game/Screens/Play/PlayerLoader.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index da5abbae95..53a349f595 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -129,6 +129,9 @@ namespace osu.Game.Screens.Play private void contentOut() { + // Ensure the logo is no longer tracking before we scale the content. + content.Tracking = false; + content.ScaleTo(0.7f, 300, Easing.InQuint); content.FadeOut(250); } From f066bd11384b56ea55afb7a0439b9a6fc8de12fd Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 28 Mar 2019 16:35:15 +0900 Subject: [PATCH 0436/5608] Adjust facade scale now that the size is different --- osu.Game/Screens/Menu/ButtonSystem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 21305c6489..19b460250f 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Menu if (this.logo != null) { this.logo.Action = onOsuLogo; - logoFacadeContainer.SetLogo(logo, 0.5f); + logoFacadeContainer.SetLogo(logo, 0.74f); // osuLogo.SizeForFlow relies on loading to be complete. buttonArea.Flow.Position = new Vector2(WEDGE_WIDTH * 2 - (BUTTON_WIDTH + this.logo.SizeForFlow / 4), 0); @@ -295,7 +295,7 @@ namespace osu.Game.Screens.Menu if (lastState == ButtonSystemState.Initial) logo.ScaleTo(0.5f, 200, Easing.In); - logoFacadeContainer.SetLogo(logo, 0.5f, lastState == ButtonSystemState.EnteringMode ? 0 : 200, Easing.In); + logoFacadeContainer.SetLogo(logo, 0.74f, lastState == ButtonSystemState.EnteringMode ? 0 : 200, Easing.In); logoFacadeContainer.Tracking = true; logoDelayedAction?.Cancel(); From eefc55f89bbf9ab64e94291a01c792473955645b Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 29 Mar 2019 00:20:16 -0700 Subject: [PATCH 0437/5608] Fix volume overlay being blocked by other floating overlays - excluding settings --- osu.Game/OsuGame.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e470d554c9..2172f5870d 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -421,7 +421,6 @@ namespace osu.Game }, }, topMostOverlayContent.Add); - loadComponentSingleFile(volume = new VolumeOverlay(), floatingOverlayContent.Add); loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add); loadComponentSingleFile(loginOverlay = new LoginOverlay @@ -438,7 +437,6 @@ namespace osu.Game loadComponentSingleFile(social = new SocialOverlay(), overlayContent.Add); loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal); loadComponentSingleFile(chatOverlay = new ChatOverlay(), overlayContent.Add); - loadComponentSingleFile(settings = new MainSettings { GetToolbarHeight = () => ToolbarOffset }, floatingOverlayContent.Add); loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add); @@ -456,6 +454,9 @@ namespace osu.Game Origin = Anchor.TopRight, }, floatingOverlayContent.Add); + loadComponentSingleFile(volume = new VolumeOverlay(), floatingOverlayContent.Add); + loadComponentSingleFile(settings = new MainSettings { GetToolbarHeight = () => ToolbarOffset }, floatingOverlayContent.Add); + loadComponentSingleFile(accountCreation = new AccountCreationOverlay(), topMostOverlayContent.Add); loadComponentSingleFile(dialogOverlay = new DialogOverlay(), topMostOverlayContent.Add); From 1ba608f01fcc3edb0f854ce4f2d6bc1e9bcd3777 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 29 Mar 2019 00:26:17 -0700 Subject: [PATCH 0438/5608] Remove line spacing on similar code --- osu.Game/OsuGame.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 2172f5870d..9f47d545e2 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -458,9 +458,7 @@ namespace osu.Game loadComponentSingleFile(settings = new MainSettings { GetToolbarHeight = () => ToolbarOffset }, floatingOverlayContent.Add); loadComponentSingleFile(accountCreation = new AccountCreationOverlay(), topMostOverlayContent.Add); - loadComponentSingleFile(dialogOverlay = new DialogOverlay(), topMostOverlayContent.Add); - loadComponentSingleFile(externalLinkOpener = new ExternalLinkOpener(), topMostOverlayContent.Add); dependencies.CacheAs(idleTracker); From 352b4b20d917d34d2d8f9ec4b34e9b9323f41c46 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 29 Mar 2019 16:28:25 +0900 Subject: [PATCH 0439/5608] Correct the sizes of TestCaseLogoFacadeContainer --- osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs index f81e70e7b0..adbf22302b 100644 --- a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs @@ -122,7 +122,7 @@ namespace osu.Game.Tests.Visual { Alpha = 0.35f, RelativeSizeAxes = Axes.None, - Size = new Vector2(107), + Size = new Vector2(72), Child = visualBox = new Box { Colour = Color4.Tomato, @@ -133,7 +133,7 @@ namespace osu.Game.Tests.Visual { Alpha = 0.35f, RelativeSizeAxes = Axes.None, - Size = new Vector2(107), + Size = new Vector2(72), Child = transferContainerBox = new Box { Colour = Color4.White, @@ -172,7 +172,7 @@ namespace osu.Game.Tests.Visual this.logo = logo; logo.FadeIn(350); logo.ScaleTo(new Vector2(0.15f), 350, Easing.In); - logoFacadeContainer.SetLogo(logo, 0.3f, 1000, Easing.InOutQuint); + logoFacadeContainer.SetLogo(logo, 1.0f, 1000, Easing.InOutQuint); logoFacadeContainer.Tracking = true; moveLogoFacade(); } From 952a12bb19b118fa129b8aa73551906e8baa8388 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 29 Mar 2019 16:54:34 +0900 Subject: [PATCH 0440/5608] Return logo relativepositionaxes on content out --- osu.Game/Screens/Play/PlayerLoader.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 53a349f595..9e6f7cf24e 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -37,6 +37,8 @@ namespace osu.Game.Screens.Play private BeatmapMetadataDisplay info; + private OsuLogo logo; + private bool hideOverlays; public override bool HideOverlaysOnEnter => hideOverlays; @@ -129,9 +131,12 @@ namespace osu.Game.Screens.Play private void contentOut() { - // Ensure the logo is no longer tracking before we scale the content. + // Ensure the logo is no longer tracking before we scale the content, and that its RelativePositionAxes have been returned. content.Tracking = false; + if (logo != null) + logo.RelativePositionAxes = Axes.Both; + content.ScaleTo(0.7f, 300, Easing.InQuint); content.FadeOut(250); } @@ -153,6 +158,8 @@ namespace osu.Game.Screens.Play { base.LogoArriving(logo, resuming); + this.logo = logo; + const double duration = 300; if (!resuming) From 7d6a08d6dac94a942174ae52aa4a5f8ab9357809 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Apr 2019 11:39:02 +0900 Subject: [PATCH 0441/5608] Fix a few new inspections in latest Rider EAP --- .../Replays/OsuAutoGenerator.cs | 6 ++---- osu.Game.Tests/Visual/TestCaseCharLookup.cs | 16 ++++++++++++++++ osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 4 ++++ osu.Game/Skinning/LegacySkinDecoder.cs | 11 +++-------- osu.sln.DotSettings | 1 + 5 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseCharLookup.cs diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index c1aaa7767e..690263c6a0 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -199,6 +199,7 @@ namespace osu.Game.Rulesets.Osu.Replays // Wait until Auto could "see and react" to the next note. double waitTime = h.StartTime - Math.Max(0.0, h.TimePreempt - reactionTime); + if (waitTime > lastFrame.Time) { lastFrame = new OsuReplayFrame(waitTime, lastFrame.Position) { Actions = lastFrame.Actions }; @@ -292,7 +293,6 @@ namespace osu.Game.Rulesets.Osu.Replays { // We add intermediate frames for spinning / following a slider here. case Spinner spinner: - { Vector2 difference = startPosition - SPINNER_CENTRE; float radius = difference.Length; @@ -315,9 +315,8 @@ namespace osu.Game.Rulesets.Osu.Replays endFrame.Position = endPosition; break; - } + case Slider slider: - { for (double j = FrameDelay; j < slider.Duration; j += FrameDelay) { Vector2 pos = slider.StackedPositionAt(j / slider.Duration); @@ -326,7 +325,6 @@ namespace osu.Game.Rulesets.Osu.Replays AddFrameToReplay(new OsuReplayFrame(slider.EndTime, new Vector2(slider.StackedEndPosition.X, slider.StackedEndPosition.Y), action)); break; - } } // We only want to let go of our button if we are at the end of the current replay. Otherwise something is still going on after us so we need to keep the button pressed! diff --git a/osu.Game.Tests/Visual/TestCaseCharLookup.cs b/osu.Game.Tests/Visual/TestCaseCharLookup.cs new file mode 100644 index 0000000000..0b9413f332 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseCharLookup.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseCharLookup : OsuTestCase + { + public TestCaseCharLookup() + { + AddStep("null", () => { }); + AddStep("display acharacter", () => Add(new OsuSpriteText { Text = "振込申請" })); + } + } +} diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 51810945db..bc54882f28 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -88,6 +88,7 @@ namespace osu.Game.Scoring.Legacy throw new IOException("input .lzma is too short"); long outSize = 0; + for (int i = 0; i < 8; i++) { int v = replayInStream.ReadByte(); @@ -144,6 +145,7 @@ namespace osu.Game.Scoring.Legacy score.Rank = ScoreRank.D; break; } + case 1: { int totalHits = count50 + count100 + count300 + countMiss; @@ -166,6 +168,7 @@ namespace osu.Game.Scoring.Legacy score.Rank = ScoreRank.D; break; } + case 2: { int totalHits = count50 + count100 + count300 + countMiss + countKatu; @@ -185,6 +188,7 @@ namespace osu.Game.Scoring.Legacy score.Rank = ScoreRank.D; break; } + case 3: { int totalHits = count50 + count100 + count300 + countMiss + countGeki + countKatu; diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 96a9116c51..461dfed589 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -16,12 +16,11 @@ namespace osu.Game.Skinning { line = StripComments(line); + var pair = SplitKeyVal(line); + switch (section) { case Section.General: - { - var pair = SplitKeyVal(line); - switch (pair.Key) { case @"Name": @@ -36,11 +35,8 @@ namespace osu.Game.Skinning } break; - } - case Section.Fonts: - { - var pair = SplitKeyVal(line); + case Section.Fonts: switch (pair.Key) { case "HitCirclePrefix": @@ -52,7 +48,6 @@ namespace osu.Game.Skinning } break; - } } base.ParseLine(skin, section, line); diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 71cbd83e3e..cfffed663c 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -230,6 +230,7 @@ True True NEXT_LINE + 1 NEXT_LINE 1 1 From 612db31c38737e3be893fb65f7a598730c7a1960 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Apr 2019 12:16:05 +0900 Subject: [PATCH 0442/5608] Apply newline additions --- osu.Desktop/OsuGameDesktop.cs | 2 + osu.Desktop/Overlays/VersionManager.cs | 1 + osu.Desktop/Program.cs | 1 + .../Beatmaps/CatchBeatmapProcessor.cs | 3 ++ .../Difficulty/CatchDifficultyCalculator.cs | 1 + .../Objects/Drawable/DrawableFruit.cs | 11 +++++ osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 5 +++ .../TestCaseNotes.cs | 2 + .../Beatmaps/ManiaBeatmapConverter.cs | 1 + .../Legacy/DistanceObjectPatternGenerator.cs | 7 ++++ .../Legacy/HitObjectPatternGenerator.cs | 9 ++++ .../Patterns/Legacy/PatternGenerator.cs | 1 + osu.Game.Rulesets.Mania/ManiaRuleset.cs | 7 ++++ .../Objects/Drawables/Pieces/BodyPiece.cs | 1 + .../Replays/ManiaAutoGenerator.cs | 3 ++ .../Replays/ManiaReplayFrame.cs | 1 + .../UI/DrawableManiaRuleset.cs | 3 ++ osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 + .../Beatmaps/OsuBeatmapProcessor.cs | 4 ++ .../Difficulty/OsuPerformanceCalculator.cs | 1 + .../Preprocessing/OsuDifficultyHitObject.cs | 1 + .../Difficulty/Skills/Speed.cs | 2 + .../Sliders/SliderPlacementBlueprint.cs | 2 + osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs | 2 + .../Connections/FollowPointRenderer.cs | 1 + .../Objects/Drawables/DrawableHitCircle.cs | 3 ++ .../UI/Cursor/CursorTrail.cs | 1 + .../Beatmaps/TaikoBeatmapConverter.cs | 1 + .../Objects/Drawables/DrawableHit.cs | 4 ++ .../Drawables/DrawableTaikoHitObject.cs | 1 + osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 1 + .../Replays/TaikoAutoGenerator.cs | 4 ++ .../SongSelect/TestCaseBeatmapCarousel.cs | 1 + .../TestCaseBeatmapScoresContainer.cs | 1 + osu.Game/Beatmaps/BeatmapManager.cs | 2 + .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 + osu.Game/Beatmaps/Formats/Decoder.cs | 1 + .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 42 +++++++++++++++++++ osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 1 + .../Formats/LegacyStoryboardDecoder.cs | 35 ++++++++++++++-- .../Configuration/DatabasedConfigManager.cs | 1 + osu.Game/Database/ArchiveModelManager.cs | 2 + osu.Game/Database/OsuDbContext.cs | 3 ++ .../Containers/ConstrainedIconContainer.cs | 1 + .../Graphics/Containers/LinkFlowContainer.cs | 7 ++++ .../Graphics/Containers/SectionsContainer.cs | 2 + osu.Game/Graphics/Cursor/MenuCursor.cs | 2 + .../Graphics/Cursor/OsuTooltipContainer.cs | 1 + osu.Game/Graphics/DrawableDate.cs | 2 + osu.Game/Graphics/UserInterface/BarGraph.cs | 2 + osu.Game/Graphics/UserInterface/LineGraph.cs | 1 + .../Graphics/UserInterface/OsuSliderBar.cs | 1 + .../Graphics/UserInterface/StarCounter.cs | 2 + osu.Game/IO/Legacy/SerializationReader.cs | 21 ++++++++++ osu.Game/IO/Legacy/SerializationWriter.cs | 1 + .../Converters/TypedListConverter.cs | 2 + osu.Game/Online/API/APIAccess.cs | 2 + .../Requests/Responses/APILegacyScoreInfo.cs | 7 ++++ osu.Game/Online/Chat/MessageFormatter.cs | 13 ++++++ osu.Game/Online/Leaderboards/Leaderboard.cs | 6 +++ osu.Game/OsuGame.cs | 9 ++++ .../Overlays/AccountCreation/ScreenEntry.cs | 1 + osu.Game/Overlays/Chat/DrawableChannel.cs | 1 + osu.Game/Overlays/ChatOverlay.cs | 2 + osu.Game/Overlays/Dialog/PopupDialog.cs | 2 + osu.Game/Overlays/DirectOverlay.cs | 2 + osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 1 + osu.Game/Overlays/Mods/ModButton.cs | 4 ++ osu.Game/Overlays/Mods/ModSection.cs | 1 + osu.Game/Overlays/Music/PlaylistList.cs | 1 + osu.Game/Overlays/Music/PlaylistOverlay.cs | 1 + osu.Game/Overlays/MusicController.cs | 3 ++ .../Overlays/Profile/Header/BadgeContainer.cs | 1 + osu.Game/Overlays/Profile/ProfileHeader.cs | 6 +-- osu.Game/Overlays/Settings/SettingsItem.cs | 1 + osu.Game/Overlays/Settings/SidebarButton.cs | 1 + osu.Game/Overlays/SocialOverlay.cs | 4 ++ .../Toolbar/ToolbarOverlayToggleButton.cs | 2 + .../Toolbar/ToolbarRulesetSelector.cs | 1 + osu.Game/Overlays/UserProfileOverlay.cs | 1 + osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 2 + .../Objects/Drawables/DrawableHitObject.cs | 3 ++ .../Objects/Legacy/ConvertHitObjectParser.cs | 6 +++ osu.Game/Rulesets/Objects/SliderPath.cs | 3 ++ osu.Game/Rulesets/UI/DrawableRuleset.cs | 1 + .../Backgrounds/BackgroundScreenBeatmap.cs | 1 + .../Screens/Edit/Compose/ComposeScreen.cs | 2 + osu.Game/Screens/Edit/Editor.cs | 5 +++ osu.Game/Screens/Edit/EditorClock.cs | 1 + osu.Game/Screens/Menu/ButtonSystem.cs | 11 +++++ osu.Game/Screens/Menu/LogoVisualisation.cs | 1 + .../Multi/Lounge/Components/RoomInspector.cs | 1 + .../Screens/Multi/Match/MatchSubScreen.cs | 1 + osu.Game/Screens/Multi/Multiplayer.cs | 1 + osu.Game/Screens/OsuScreenDependencies.cs | 2 + osu.Game/Screens/Play/HUD/ModDisplay.cs | 1 + osu.Game/Screens/Play/KeyCounter.cs | 1 + osu.Game/Screens/Play/SquareGraph.cs | 1 + .../Screens/Ranking/Pages/ScoreResultsPage.cs | 2 + osu.Game/Screens/Select/BeatmapCarousel.cs | 8 ++++ osu.Game/Screens/Select/PlaySongSelect.cs | 1 + osu.Game/Screens/Tournament/Drawings.cs | 1 + osu.Game/Skinning/LegacySkin.cs | 6 +++ osu.Game/Skinning/SkinManager.cs | 1 + .../Drawables/DrawableStoryboardAnimation.cs | 1 + osu.Game/Storyboards/StoryboardSprite.cs | 1 + .../Tests/Beatmaps/BeatmapConversionTest.cs | 2 + osu.sln.DotSettings | 1 + 108 files changed, 359 insertions(+), 7 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index e7e0af7eea..00cabbadf7 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -77,6 +77,7 @@ namespace osu.Desktop if (versionManager != null) versionManager.State = Visibility.Visible; break; + default: if (versionManager != null) versionManager.State = Visibility.Hidden; @@ -87,6 +88,7 @@ namespace osu.Desktop public override void SetHost(GameHost host) { base.SetHost(host); + if (host.Window is DesktopGameWindow desktopWindow) { desktopWindow.CursorState |= CursorState.Hidden; diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 2998e08715..2fbbe6f685 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -95,6 +95,7 @@ namespace osu.Desktop.Overlays var version = game.Version; var lastVersion = config.Get(OsuSetting.Version); + if (game.IsDeployedBuild && version != lastVersion) { config.Set(OsuSetting.Version, version); diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index ff9972ac48..29554df64c 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -31,6 +31,7 @@ namespace osu.Desktop var importer = new ArchiveImportIPCChannel(host); // Restore the cwd so relative paths given at the command line work correctly Directory.SetCurrentDirectory(cwd); + foreach (var file in args) { Console.WriteLine(@"Importing {0}", file); diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 78b5a510b2..645cb5701a 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -31,6 +31,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps initialiseHyperDash((List)Beatmap.HitObjects); int index = 0; + foreach (var obj in Beatmap.HitObjects.OfType()) { obj.IndexInBeatmap = index++; @@ -58,6 +59,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps } break; + case JuiceStream juiceStream: foreach (var nested in juiceStream.NestedHitObjects) { @@ -103,6 +105,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps double timeToNext = nextObject.StartTime - currentObject.StartTime - 1000f / 60f / 4; // 1/4th of a frame of grace time, taken from osu-stable double distanceToNext = Math.Abs(nextObject.X - currentObject.X) - (lastDirection == thisDirection ? lastExcess : halfCatcherWidth); float distanceToHyper = (float)(timeToNext * CatcherArea.Catcher.BASE_SPEED - distanceToNext); + if (distanceToHyper < 0) { currentObject.HyperDashTarget = nextObject; diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index b4998347f4..bd647fd667 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -73,6 +73,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty lastObject = hitObject; break; + case JuiceStream _: foreach (var nested in hitObject.NestedHitObjects.OfType().Where(o => !(o is TinyDroplet))) { diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 0dc3f73404..8368e2f276 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -105,6 +105,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { default: return new Container(); + case FruitVisualRepresentation.Raspberry: return new Container { @@ -143,6 +144,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable }, } }; + case FruitVisualRepresentation.Pineapple: return new Container { @@ -181,6 +183,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable }, } }; + case FruitVisualRepresentation.Pear: return new Container { @@ -213,6 +216,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable }, } }; + case FruitVisualRepresentation.Grape: return new Container { @@ -245,6 +249,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable }, } }; + case FruitVisualRepresentation.Banana: return new Container { @@ -282,19 +287,25 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable default: case FruitVisualRepresentation.Pear: return new Color4(17, 136, 170, 255); + case FruitVisualRepresentation.Grape: return new Color4(204, 102, 0, 255); + case FruitVisualRepresentation.Raspberry: return new Color4(121, 9, 13, 255); + case FruitVisualRepresentation.Pineapple: return new Color4(102, 136, 0, 255); + case FruitVisualRepresentation.Banana: switch (RNG.Next(0, 3)) { default: return new Color4(255, 240, 0, 255); + case 1: return new Color4(255, 192, 0, 255); + case 2: return new Color4(214, 221, 28, 255); } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 83f791690a..e7c7fd77df 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -292,6 +292,7 @@ namespace osu.Game.Rulesets.Catch.UI const float hyper_dash_transition_length = 180; bool previouslyHyperDashing = HyperDashing; + if (modifier <= 1 || X == targetPosition) { hyperDashModifier = 1; @@ -325,9 +326,11 @@ namespace osu.Game.Rulesets.Catch.UI case CatchAction.MoveLeft: currentDirection--; return true; + case CatchAction.MoveRight: currentDirection++; return true; + case CatchAction.Dash: Dashing = true; return true; @@ -343,9 +346,11 @@ namespace osu.Game.Rulesets.Catch.UI case CatchAction.MoveLeft: currentDirection++; return true; + case CatchAction.MoveRight: currentDirection--; return true; + case CatchAction.Dash: Dashing = false; return true; diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs index 0bc2c3ea28..2220873d89 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs @@ -168,11 +168,13 @@ namespace osu.Game.Rulesets.Mania.Tests foreach (var nested in obj.NestedHitObjects) { double finalPosition = (nested.HitObject.StartTime - obj.HitObject.StartTime) / endTime.Duration; + switch (direction) { case ScrollingDirection.Up: nested.Y = (float)(finalPosition * content.DrawHeight); break; + case ScrollingDirection.Down: nested.Y = (float)(-finalPosition * content.DrawHeight); break; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 71df68c087..704deba78b 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -48,6 +48,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps if (IsForCurrentRuleset) { TargetColumns = (int)Math.Max(1, roundedCircleSize); + if (TargetColumns >= 10) { TargetColumns = TargetColumns / 2; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index ed52bdd23f..1b6ff16388 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -179,6 +179,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int usableColumns = TotalColumns - RandomStart - PreviousPattern.ColumnWithObjects; int nextColumn = GetRandomColumn(); + for (int i = 0; i < Math.Min(usableColumns, noteCount); i++) { // Find available column @@ -217,6 +218,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy nextColumn = FindAvailableColumn(nextColumn, PreviousPattern); int lastColumn = nextColumn; + for (int i = 0; i < noteCount; i++) { addToPattern(pattern, nextColumn, startTime, startTime); @@ -299,6 +301,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int interval = Random.Next(1, TotalColumns - (legacy ? 1 : 0)); int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); + for (int i = 0; i <= spanCount; i++) { addToPattern(pattern, nextColumn, startTime, startTime); @@ -341,16 +344,19 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy p3 = 0; p4 = 0; break; + case 3: p2 = Math.Min(p2, 0.1); p3 = 0; p4 = 0; break; + case 4: p2 = Math.Min(p2, 0.3); p3 = Math.Min(p3, 0.04); p4 = 0; break; + case 5: p2 = Math.Min(p2, 0.34); p3 = Math.Min(p3, 0.1); @@ -440,6 +446,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy bool ignoreHead = !sampleInfoListAt(startTime).Any(s => s.Name == SampleInfo.HIT_WHISTLE || s.Name == SampleInfo.HIT_FINISH || s.Name == SampleInfo.HIT_CLAP); var rowPattern = new Pattern(); + for (int i = 0; i <= spanCount; i++) { if (!(ignoreHead && startTime == HitObject.StartTime)) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 34f5f5c415..d13b21183b 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -233,6 +233,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy noteCount = Math.Min(noteCount, TotalColumns - RandomStart - PreviousPattern.ColumnWithObjects); int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); + for (int i = 0; i < noteCount; i++) { nextColumn = allowStacking @@ -303,6 +304,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int columnLimit = (TotalColumns % 2 == 0 ? TotalColumns : TotalColumns - 1) / 2; int nextColumn = GetRandomColumn(upperBound: columnLimit); + for (int i = 0; i < noteCount; i++) { nextColumn = FindAvailableColumn(nextColumn, upperBound: columnLimit, patterns: pattern); @@ -340,18 +342,21 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy p4 = 0; p5 = 0; break; + case 3: p2 = Math.Min(p2, 0.1); p3 = 0; p4 = 0; p5 = 0; break; + case 4: p2 = Math.Min(p2, 0.23); p3 = Math.Min(p3, 0.04); p4 = 0; p5 = 0; break; + case 5: p3 = Math.Min(p3, 0.15); p4 = Math.Min(p4, 0.03); @@ -384,20 +389,24 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy p2 = 0; p3 = 0; break; + case 3: centreProbability = Math.Min(centreProbability, 0.03); p2 = 0; p3 = 0; break; + case 4: centreProbability = 0; p2 = Math.Min(p2 * 2, 0.2); p3 = 0; break; + case 5: centreProbability = Math.Min(centreProbability, 0.03); p3 = 0; break; + case 6: centreProbability = 0; p2 = Math.Min(p2 * 2, 0.5); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index b702291c5d..fba52dfc32 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -158,6 +158,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy // Ensure that we have at least one free column, so that an endless loop is avoided bool hasValidColumns = false; + for (int i = lowerBound.Value; i < upperBound.Value; i++) { hasValidColumns = isValid(i); diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 0ff79d2836..0ef53f0f37 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -117,6 +117,7 @@ namespace osu.Game.Rulesets.Mania new ManiaModNoFail(), new MultiMod(new ManiaModHalfTime(), new ManiaModDaycore()), }; + case ModType.DifficultyIncrease: return new Mod[] { @@ -126,6 +127,7 @@ namespace osu.Game.Rulesets.Mania new MultiMod(new ManiaModFadeIn(), new ManiaModHidden()), new ManiaModFlashlight(), }; + case ModType.Conversion: return new Mod[] { @@ -142,16 +144,19 @@ namespace osu.Game.Rulesets.Mania new ManiaModDualStages(), new ManiaModMirror(), }; + case ModType.Automation: return new Mod[] { new MultiMod(new ManiaModAutoplay(), new ModCinema()), }; + case ModType.Fun: return new Mod[] { new MultiMod(new ModWindUp(), new ModWindDown()) }; + default: return new Mod[] { }; } @@ -214,6 +219,7 @@ namespace osu.Game.Rulesets.Mania SpecialAction = ManiaAction.Special1, NormalActionStart = ManiaAction.Key1, }.GenerateKeyBindingsFor(variant, out _); + case PlayfieldType.Dual: int keys = getDualStageKeyCount(variant); @@ -271,6 +277,7 @@ namespace osu.Game.Rulesets.Mania { default: return $"{variant}K"; + case PlayfieldType.Dual: { var keys = getDualStageKeyCount(variant); diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index 2baf1ad520..2bed1d42db 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs @@ -144,6 +144,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces const float animation_length = 50; Foreground.ClearTransforms(false, nameof(Foreground.Colour)); + if (hitting) { // wait for the next sync point diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 65b7d54cd2..e5669816fa 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -28,6 +28,7 @@ namespace osu.Game.Rulesets.Mania.Replays var normalAction = ManiaAction.Key1; var specialAction = ManiaAction.Special1; int totalCounter = 0; + foreach (var stage in Beatmap.Stages) { for (int i = 0; i < stage.Columns; i++) @@ -51,6 +52,7 @@ namespace osu.Game.Rulesets.Mania.Replays var pointGroups = generateActionPoints().GroupBy(a => a.Time).OrderBy(g => g.First().Time); var actions = new List(); + foreach (var group in pointGroups) { foreach (var point in group) @@ -60,6 +62,7 @@ namespace osu.Game.Rulesets.Mania.Replays case HitPoint _: actions.Add(columnActions[point.Column]); break; + case ReleasePoint _: actions.Remove(columnActions[point.Column]); break; diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index 81a76c93e6..f7277d3669 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -39,6 +39,7 @@ namespace osu.Game.Rulesets.Mania.Replays int activeColumns = (int)(legacyFrame.MouseX ?? 0); int counter = 0; + while (activeColumns > 0) { var isSpecial = stage.IsSpecialColumn(counter); diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 1c1ec604f6..989bbdbfde 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -56,6 +56,7 @@ namespace osu.Game.Rulesets.Mania.UI double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - point.BeatLength : lastObjectTime + point.BeatLength * (int)point.TimeSignature; int index = 0; + for (double t = timingPoints[i].Time; Precision.DefinitelyBigger(endTime, t); t += point.BeatLength, index++) { barLines.Add(new BarLine @@ -104,8 +105,10 @@ namespace osu.Game.Rulesets.Mania.UI { case HoldNote holdNote: return new DrawableHoldNote(holdNote); + case Note note: return new DrawableNote(note); + default: return null; } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index cbabfcc8b4..5ab07416a6 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -38,6 +38,7 @@ namespace osu.Game.Rulesets.Mania.UI var normalColumnAction = ManiaAction.Key1; var specialColumnAction = ManiaAction.Special1; int firstColumnIndex = 0; + for (int i = 0; i < stageDefinitions.Count; i++) { var newStage = new ManiaStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction); @@ -92,6 +93,7 @@ namespace osu.Game.Rulesets.Mania.UI private ManiaStage getStageByColumn(int column) { int sum = 0; + foreach (var stage in stages) { sum = sum + stage.Columns.Count; diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index 59a5f90fd0..b2beda18f4 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -44,12 +44,14 @@ namespace osu.Game.Rulesets.Osu.Beatmaps if (endIndex < 0) throw new ArgumentOutOfRangeException(nameof(endIndex), $"{nameof(endIndex)} cannot be less than 0."); int extendedEndIndex = endIndex; + if (endIndex < beatmap.HitObjects.Count - 1) { // Extend the end index to include objects they are stacked on for (int i = endIndex; i >= startIndex; i--) { int stackBaseIndex = i; + for (int n = stackBaseIndex + 1; n < beatmap.HitObjects.Count; n++) { OsuHitObject stackBaseObject = beatmap.HitObjects[stackBaseIndex]; @@ -87,6 +89,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps //Reverse pass for stack calculation. int extendedStartIndex = startIndex; + for (int i = extendedEndIndex; i > startIndex; i--) { int n = i; @@ -138,6 +141,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps if (objectN is Slider && Vector2Extensions.Distance(objectN.EndPosition, objectI.Position) < stack_distance) { int offset = objectI.StackHeight - objectN.StackHeight + 1; + for (int j = n + 1; j <= i; j++) { //For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above). diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 0dce5208dd..093081b6a1 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -109,6 +109,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty aimValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f); double approachRateFactor = 1.0f; + if (Attributes.ApproachRate > 10.33f) approachRateFactor += 0.3f * (Attributes.ApproachRate - 10.33f); else if (Attributes.ApproachRate < 8.0f) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs index 37276a3432..eacac7ae6a 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -56,6 +56,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing { // We will scale distances by this factor, so we can assume a uniform CircleSize among beatmaps. float scalingFactor = normalized_radius / (float)BaseObject.Radius; + if (BaseObject.Radius < 30) { float smallCircleBonus = Math.Min(30 - (float)BaseObject.Radius, 5) / 50; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index 46a81a9480..01f2fb8dc8 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -42,9 +42,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills speedBonus = 1 + Math.Pow((min_speed_bonus - deltaTime) / speed_balancing_factor, 2); double angleBonus = 1.0; + if (osuCurrent.Angle != null && osuCurrent.Angle.Value < angle_bonus_begin) { angleBonus = 1 + Math.Pow(Math.Sin(1.5 * (angle_bonus_begin - osuCurrent.Angle.Value)), 2) / 3.57; + if (osuCurrent.Angle.Value < pi_over_2) { angleBonus = 1.28; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 989a53db1f..55de626d7d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -62,6 +62,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders case PlacementState.Initial: HitObject.Position = e.MousePosition; return true; + case PlacementState.Body: cursor = e.MousePosition - HitObject.Position; return true; @@ -77,6 +78,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders case PlacementState.Initial: beginCurve(); break; + case PlacementState.Body: switch (e.Button) { diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs index 2e93815ef0..3e53cd7087 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs @@ -33,6 +33,7 @@ namespace osu.Game.Rulesets.Osu.Mods { case DrawableSpinner _: continue; + default: drawable.ApplyCustomUpdateState += ApplyCustomState; break; @@ -51,6 +52,7 @@ namespace osu.Game.Rulesets.Osu.Mods case DrawableSliderTail _: // special cases we should *not* be scaling. break; + case DrawableSlider _: case DrawableHitCircle _: { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 8f9d487d49..7569626230 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -67,6 +67,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections return; OsuHitObject prevHitObject = null; + foreach (var currHitObject in hitObjects) { if (prevHitObject != null && !currHitObject.NewCombo && !(prevHitObject is Spinner) && !(currHitObject is Spinner)) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index decd0ce073..fef0bfdc2c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -124,6 +124,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } var result = HitObject.HitWindows.ResultFor(timeOffset); + if (result == HitResult.None) { Shake(Math.Abs(timeOffset) - HitObject.HitWindows.HalfWindowFor(HitResult.Miss)); @@ -158,11 +159,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early. LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.HalfWindowFor(HitResult.Miss); break; + case ArmedState.Miss: ApproachCircle.FadeOut(50); this.FadeOut(100); Expire(); break; + case ArmedState.Hit: ApproachCircle.FadeOut(50); diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 03dbf7ac63..1a3e244fa6 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -191,6 +191,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor Shader.GetUniform("g_FadeClock").UpdateValue(ref Time); int updateStart = -1, updateEnd = 0; + for (int i = 0; i < Parts.Length; ++i) { if (Parts[i].WasUpdated) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 3e0e2624bf..f8672037cd 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -120,6 +120,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps List> allSamples = curveData != null ? curveData.NodeSamples : new List>(new[] { samples }); int i = 0; + for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing) { List currentSamples = allSamples[i]; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index d3837946c9..4c8d5d5204 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -98,6 +98,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables circlePiece?.FlashBox.FinishTransforms(); var offset = !AllJudged ? 0 : Time.Current - HitObject.StartTime; + using (BeginDelayedSequence(HitObject.StartTime - Time.Current + offset, true)) { switch (State.Value) @@ -108,15 +109,18 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables UnproxyContent(); this.Delay(HitObject.HitWindows.HalfWindowFor(HitResult.Miss)).Expire(); break; + case ArmedState.Miss: this.FadeOut(100) .Expire(); break; + case ArmedState.Hit: // If we're far enough away from the left stage, we should bring outselves in front of it ProxyContent(); var flash = circlePiece?.FlashBox; + if (flash != null) { flash.FadeTo(0.9f); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 8dfe89eea7..119940536e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -111,6 +111,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables MainPiece.KiaiMode = HitObject.Kiai; var strongObject = HitObject.NestedHitObjects.OfType().FirstOrDefault(); + if (strongObject != null) { var strongHit = CreateStrongHit(strongObject); diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 6f3bdca6fb..1d25735fe3 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -70,6 +70,7 @@ namespace osu.Game.Rulesets.Taiko.Objects return; bool first = true; + for (double t = StartTime; t < EndTime + tickSpacing / 2; t += tickSpacing) { AddNested(new DrumRollTick diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 01ba53e07b..422ba748e3 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -52,6 +52,7 @@ namespace osu.Game.Rulesets.Taiko.Replays int count = 0; int req = swell.RequiredHits; double hitRate = Math.Min(swell_hit_speed, swell.Duration / req); + for (double j = h.StartTime; j < endTime; j += hitRate) { TaikoAction action; @@ -62,12 +63,15 @@ namespace osu.Game.Rulesets.Taiko.Replays case 0: action = TaikoAction.LeftCentre; break; + case 1: action = TaikoAction.LeftRim; break; + case 2: action = TaikoAction.RightCentre; break; + case 3: action = TaikoAction.RightRim; break; diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapCarousel.cs index 1500605896..1ffc164026 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapCarousel.cs @@ -508,6 +508,7 @@ namespace osu.Game.Tests.Visual.SongSelect }, Beatmaps = new List(), }; + for (int b = 1; b < 101; b++) { toReturn.Beatmaps.Add(new BeatmapInfo diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs index 8de6cc2a88..5bddf4222a 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs @@ -261,6 +261,7 @@ namespace osu.Game.Tests.Visual.SongSelect Accuracy = 0.8765, }, }; + foreach (var s in anotherScores) { s.Statistics.Add(HitResult.Great, RNG.Next(2000)); diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 9caa64ec96..95ec7d55c8 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -117,6 +117,7 @@ namespace osu.Game.Beatmaps if (beatmapSet.OnlineBeatmapSetID != null) { var existingOnlineId = beatmaps.ConsumableItems.FirstOrDefault(b => b.OnlineBeatmapSetID == beatmapSet.OnlineBeatmapSetID); + if (existingOnlineId != null) { Delete(existingOnlineId); @@ -325,6 +326,7 @@ namespace osu.Game.Beatmaps { // let's make sure there are actually .osu files to import. string mapName = reader.Filenames.FirstOrDefault(f => f.EndsWith(".osu")); + if (string.IsNullOrEmpty(mapName)) { Logger.Log($"No beatmap files found in the beatmap archive ({reader.Name}).", LoggingTarget.Database); diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index a2e43e5a97..0bdab22dd2 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -101,6 +101,7 @@ namespace osu.Game.Beatmaps protected override Storyboard GetStoryboard() { Storyboard storyboard; + try { using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path)))) @@ -131,6 +132,7 @@ namespace osu.Game.Beatmaps protected override Skin GetSkin() { Skin skin; + try { skin = new LegacyBeatmapSkin(BeatmapInfo, store, audioManager); diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs index a895ba3d63..953e50eadc 100644 --- a/osu.Game/Beatmaps/Formats/Decoder.cs +++ b/osu.Game/Beatmaps/Formats/Decoder.cs @@ -49,6 +49,7 @@ namespace osu.Game.Beatmaps.Formats throw new IOException(@"Unknown decoder type"); string line; + do { line = stream.ReadLine()?.Trim(); diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index a27126ad9c..b489b5e6d9 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -70,21 +70,27 @@ namespace osu.Game.Beatmaps.Formats case Section.General: handleGeneral(strippedLine); return; + case Section.Editor: handleEditor(strippedLine); return; + case Section.Metadata: handleMetadata(line); return; + case Section.Difficulty: handleDifficulty(strippedLine); return; + case Section.Events: handleEvent(strippedLine); return; + case Section.TimingPoints: handleTimingPoint(strippedLine); return; + case Section.HitObjects: handleHitObject(strippedLine); return; @@ -98,29 +104,37 @@ namespace osu.Game.Beatmaps.Formats var pair = SplitKeyVal(line); var metadata = beatmap.BeatmapInfo.Metadata; + switch (pair.Key) { case @"AudioFilename": metadata.AudioFile = FileSafety.PathStandardise(pair.Value); break; + case @"AudioLeadIn": beatmap.BeatmapInfo.AudioLeadIn = Parsing.ParseInt(pair.Value); break; + case @"PreviewTime": metadata.PreviewTime = getOffsetTime(Parsing.ParseInt(pair.Value)); break; + case @"Countdown": beatmap.BeatmapInfo.Countdown = Parsing.ParseInt(pair.Value) == 1; break; + case @"SampleSet": defaultSampleBank = (LegacySampleBank)Enum.Parse(typeof(LegacySampleBank), pair.Value); break; + case @"SampleVolume": defaultSampleVolume = Parsing.ParseInt(pair.Value); break; + case @"StackLeniency": beatmap.BeatmapInfo.StackLeniency = Parsing.ParseFloat(pair.Value); break; + case @"Mode": beatmap.BeatmapInfo.RulesetID = Parsing.ParseInt(pair.Value); @@ -129,24 +143,30 @@ namespace osu.Game.Beatmaps.Formats case 0: parser = new Rulesets.Objects.Legacy.Osu.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; + case 1: parser = new Rulesets.Objects.Legacy.Taiko.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; + case 2: parser = new Rulesets.Objects.Legacy.Catch.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; + case 3: parser = new Rulesets.Objects.Legacy.Mania.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; } break; + case @"LetterboxInBreaks": beatmap.BeatmapInfo.LetterboxInBreaks = Parsing.ParseInt(pair.Value) == 1; break; + case @"SpecialStyle": beatmap.BeatmapInfo.SpecialStyle = Parsing.ParseInt(pair.Value) == 1; break; + case @"WidescreenStoryboard": beatmap.BeatmapInfo.WidescreenStoryboard = Parsing.ParseInt(pair.Value) == 1; break; @@ -162,15 +182,19 @@ namespace osu.Game.Beatmaps.Formats case @"Bookmarks": beatmap.BeatmapInfo.StoredBookmarks = pair.Value; break; + case @"DistanceSpacing": beatmap.BeatmapInfo.DistanceSpacing = Math.Max(0, Parsing.ParseDouble(pair.Value)); break; + case @"BeatDivisor": beatmap.BeatmapInfo.BeatDivisor = Parsing.ParseInt(pair.Value); break; + case @"GridSize": beatmap.BeatmapInfo.GridSize = Parsing.ParseInt(pair.Value); break; + case @"TimelineZoom": beatmap.BeatmapInfo.TimelineZoom = Math.Max(0, Parsing.ParseDouble(pair.Value)); break; @@ -182,35 +206,45 @@ namespace osu.Game.Beatmaps.Formats var pair = SplitKeyVal(line); var metadata = beatmap.BeatmapInfo.Metadata; + switch (pair.Key) { case @"Title": metadata.Title = pair.Value; break; + case @"TitleUnicode": metadata.TitleUnicode = pair.Value; break; + case @"Artist": metadata.Artist = pair.Value; break; + case @"ArtistUnicode": metadata.ArtistUnicode = pair.Value; break; + case @"Creator": metadata.AuthorString = pair.Value; break; + case @"Version": beatmap.BeatmapInfo.Version = pair.Value; break; + case @"Source": beatmap.BeatmapInfo.Metadata.Source = pair.Value; break; + case @"Tags": beatmap.BeatmapInfo.Metadata.Tags = pair.Value; break; + case @"BeatmapID": beatmap.BeatmapInfo.OnlineBeatmapID = Parsing.ParseInt(pair.Value); break; + case @"BeatmapSetID": beatmap.BeatmapInfo.BeatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = Parsing.ParseInt(pair.Value) }; break; @@ -222,23 +256,29 @@ namespace osu.Game.Beatmaps.Formats var pair = SplitKeyVal(line); var difficulty = beatmap.BeatmapInfo.BaseDifficulty; + switch (pair.Key) { case @"HPDrainRate": difficulty.DrainRate = Parsing.ParseFloat(pair.Value); break; + case @"CircleSize": difficulty.CircleSize = Parsing.ParseFloat(pair.Value); break; + case @"OverallDifficulty": difficulty.OverallDifficulty = Parsing.ParseFloat(pair.Value); break; + case @"ApproachRate": difficulty.ApproachRate = Parsing.ParseFloat(pair.Value); break; + case @"SliderMultiplier": difficulty.SliderMultiplier = Parsing.ParseDouble(pair.Value); break; + case @"SliderTickRate": difficulty.SliderTickRate = Parsing.ParseDouble(pair.Value); break; @@ -259,6 +299,7 @@ namespace osu.Game.Beatmaps.Formats string filename = split[2].Trim('"'); beatmap.BeatmapInfo.Metadata.BackgroundFile = FileSafety.PathStandardise(filename); break; + case EventType.Break: double start = getOffsetTime(Parsing.ParseDouble(split[1])); @@ -308,6 +349,7 @@ namespace osu.Game.Beatmaps.Formats bool kiaiMode = false; bool omitFirstBarSignature = false; + if (split.Length >= 8) { EffectFlags effectFlags = (EffectFlags)Parsing.ParseInt(split[7]); diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 040f582e3b..cd1d8a6218 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -26,6 +26,7 @@ namespace osu.Game.Beatmaps.Formats Section section = Section.None; string line; + while ((line = stream.ReadLine()) != null) { if (ShouldSkipLine(line)) diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 0f83edf034..f6e2bf6966 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -54,6 +54,7 @@ namespace osu.Game.Beatmaps.Formats case Section.Events: handleEvents(line); return; + case Section.Variables: handleVariables(line); return; @@ -65,6 +66,7 @@ namespace osu.Game.Beatmaps.Formats private void handleEvents(string line) { var depth = 0; + while (line.StartsWith(" ", StringComparison.Ordinal) || line.StartsWith("_", StringComparison.Ordinal)) { ++depth; @@ -94,8 +96,9 @@ namespace osu.Game.Beatmaps.Formats var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo); storyboardSprite = new StoryboardSprite(path, origin, new Vector2(x, y)); storyboard.GetLayer(layer).Add(storyboardSprite); - } break; + } + case EventType.Animation: { var layer = parseLayer(split[1]); @@ -108,8 +111,9 @@ namespace osu.Game.Beatmaps.Formats var loopType = split.Length > 8 ? (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]) : AnimationLoopType.LoopForever; storyboardSprite = new StoryboardAnimation(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType); storyboard.GetLayer(layer).Add(storyboardSprite); - } break; + } + case EventType.Sample: { var time = double.Parse(split[1], CultureInfo.InvariantCulture); @@ -117,8 +121,8 @@ namespace osu.Game.Beatmaps.Formats var path = cleanFilename(split[3]); var volume = split.Length > 4 ? float.Parse(split[4], CultureInfo.InvariantCulture) : 100; storyboard.GetLayer(layer).Add(new StoryboardSample(path, time, volume)); - } break; + } } } else @@ -127,6 +131,7 @@ namespace osu.Game.Beatmaps.Formats timelineGroup = storyboardSprite?.TimelineGroup; var commandType = split[0]; + switch (commandType) { case "T": @@ -138,6 +143,7 @@ namespace osu.Game.Beatmaps.Formats timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber); } break; + case "L": { var startTime = double.Parse(split[1], CultureInfo.InvariantCulture); @@ -145,6 +151,7 @@ namespace osu.Game.Beatmaps.Formats timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount); } break; + default: { if (string.IsNullOrEmpty(split[3])) @@ -163,6 +170,7 @@ namespace osu.Game.Beatmaps.Formats timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue); } break; + case "S": { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); @@ -170,6 +178,7 @@ namespace osu.Game.Beatmaps.Formats timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue)); } break; + case "V": { var startX = float.Parse(split[4], CultureInfo.InvariantCulture); @@ -179,6 +188,7 @@ namespace osu.Game.Beatmaps.Formats timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY)); } break; + case "R": { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); @@ -186,6 +196,7 @@ namespace osu.Game.Beatmaps.Formats timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue)); } break; + case "M": { var startX = float.Parse(split[4], CultureInfo.InvariantCulture); @@ -196,6 +207,7 @@ namespace osu.Game.Beatmaps.Formats timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY); } break; + case "MX": { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); @@ -203,6 +215,7 @@ namespace osu.Game.Beatmaps.Formats timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue); } break; + case "MY": { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); @@ -210,6 +223,7 @@ namespace osu.Game.Beatmaps.Formats timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue); } break; + case "C": { var startRed = float.Parse(split[4], CultureInfo.InvariantCulture); @@ -223,23 +237,28 @@ namespace osu.Game.Beatmaps.Formats new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1)); } break; + case "P": { var type = split[4]; + switch (type) { case "A": timelineGroup?.BlendingMode.Add(easing, startTime, endTime, BlendingMode.Additive, startTime == endTime ? BlendingMode.Additive : BlendingMode.Inherit); break; + case "H": timelineGroup?.FlipH.Add(easing, startTime, endTime, true, startTime == endTime); break; + case "V": timelineGroup?.FlipV.Add(easing, startTime, endTime, true, startTime == endTime); break; } } break; + default: throw new InvalidDataException($@"Unknown command type: {commandType}"); } @@ -254,26 +273,36 @@ namespace osu.Game.Beatmaps.Formats private Anchor parseOrigin(string value) { var origin = (LegacyOrigins)Enum.Parse(typeof(LegacyOrigins), value); + switch (origin) { case LegacyOrigins.TopLeft: return Anchor.TopLeft; + case LegacyOrigins.TopCentre: return Anchor.TopCentre; + case LegacyOrigins.TopRight: return Anchor.TopRight; + case LegacyOrigins.CentreLeft: return Anchor.CentreLeft; + case LegacyOrigins.Centre: return Anchor.Centre; + case LegacyOrigins.CentreRight: return Anchor.CentreRight; + case LegacyOrigins.BottomLeft: return Anchor.BottomLeft; + case LegacyOrigins.BottomCentre: return Anchor.BottomCentre; + case LegacyOrigins.BottomRight: return Anchor.BottomRight; + default: return Anchor.TopLeft; } diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs index f547a7d3e1..8f1780cab5 100644 --- a/osu.Game/Configuration/DatabasedConfigManager.cs +++ b/osu.Game/Configuration/DatabasedConfigManager.cs @@ -44,6 +44,7 @@ namespace osu.Game.Configuration base.AddBindable(lookup, bindable); var setting = databasedSettings.Find(s => (int)s.Key == (int)(object)lookup); + if (setting != null) { bindable.Parse(setting.Value); diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 3805921ac2..1eb199327e 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -84,6 +84,7 @@ namespace osu.Game.Database private void flushEvents(bool perform) { Action[] events; + lock (queuedEvents) { events = queuedEvents.ToArray(); @@ -147,6 +148,7 @@ namespace osu.Game.Database List imported = new List(); int current = 0; + foreach (string path in paths) { if (notification.State == ProgressNotificationState.Cancelled) diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 17efe2c839..38f2a53586 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -60,6 +60,7 @@ namespace osu.Game.Database this.connectionString = connectionString; var connection = Database.GetDbConnection(); + try { connection.Open(); @@ -170,9 +171,11 @@ namespace osu.Game.Database default: frameworkLogLevel = Framework.Logging.LogLevel.Debug; break; + case LogLevel.Warning: frameworkLogLevel = Framework.Logging.LogLevel.Important; break; + case LogLevel.Error: case LogLevel.Critical: frameworkLogLevel = Framework.Logging.LogLevel.Error; diff --git a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs index c1811f37d5..3bb9e1f091 100644 --- a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs +++ b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs @@ -34,6 +34,7 @@ namespace osu.Game.Graphics.Containers protected override void Update() { base.Update(); + if (InternalChildren.Count > 0 && InternalChild.DrawSize.X > 0) { // We're modifying scale here for a few reasons diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 204c83aac9..23e2a66107 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -51,6 +51,7 @@ namespace osu.Game.Graphics.Containers } int previousLinkEnd = 0; + foreach (var link in links) { AddText(text.Substring(previousLinkEnd, link.Index - previousLinkEnd)); @@ -90,10 +91,12 @@ namespace osu.Game.Graphics.Containers if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) game?.ShowBeatmap(beatmapId); break; + case LinkAction.OpenBeatmapSet: if (int.TryParse(linkArgument, out int setId)) game?.ShowBeatmapSet(setId); break; + case LinkAction.OpenChannel: try { @@ -105,18 +108,22 @@ namespace osu.Game.Graphics.Containers } break; + case LinkAction.OpenEditorTimestamp: case LinkAction.JoinMultiplayerMatch: case LinkAction.Spectate: showNotImplementedError?.Invoke(); break; + case LinkAction.External: game?.OpenUrlExternally(url); break; + case LinkAction.OpenUserProfile: if (long.TryParse(linkArgument, out long userId)) game?.ShowUser(userId); break; + default: throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); } diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 6bbab4766d..1f2ee53fe9 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -150,6 +150,7 @@ namespace osu.Game.Graphics.Containers float headerH = (ExpandableHeader?.LayoutSize.Y ?? 0) + (FixedHeader?.LayoutSize.Y ?? 0); float footerH = Footer?.LayoutSize.Y ?? 0; + if (headerH != headerHeight || footerH != footerHeight) { headerHeight = headerH; @@ -181,6 +182,7 @@ namespace osu.Game.Graphics.Containers foreach (var section in Children) { float diff = Math.Abs(scrollContainer.GetChildPosInContent(section) - currentScroll - scrollOffset); + if (diff < minDiff) { minDiff = diff; diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 059beeca4d..092a23e787 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -45,10 +45,12 @@ namespace osu.Game.Graphics.Cursor { var position = e.MousePosition; var distance = Vector2Extensions.Distance(position, positionMouseDown); + // don't start rotating until we're moved a minimum distance away from the mouse down location, // else it can have an annoying effect. if (dragRotationState == DragRotationState.DragStarted && distance > 30) dragRotationState = DragRotationState.Rotating; + // don't rotate when distance is zero to avoid NaN if (dragRotationState == DragRotationState.Rotating && distance > 0) { diff --git a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs index 4e0ce4a3e1..fa79331274 100644 --- a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs @@ -37,6 +37,7 @@ namespace osu.Game.Graphics.Cursor if (value == text.Text) return; text.Text = value; + if (IsPresent) { AutoSizeDuration = 250; diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 3ae1033f5d..125c994c92 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -54,9 +54,11 @@ namespace osu.Game.Graphics var diffToNow = DateTimeOffset.Now.Subtract(Date); double timeUntilNextUpdate = 1000; + if (Math.Abs(diffToNow.TotalSeconds) > 120) { timeUntilNextUpdate *= 60; + if (Math.Abs(diffToNow.TotalMinutes) > 120) { timeUntilNextUpdate *= 60; diff --git a/osu.Game/Graphics/UserInterface/BarGraph.cs b/osu.Game/Graphics/UserInterface/BarGraph.cs index 58058c9d4c..953f3985f9 100644 --- a/osu.Game/Graphics/UserInterface/BarGraph.cs +++ b/osu.Game/Graphics/UserInterface/BarGraph.cs @@ -25,6 +25,7 @@ namespace osu.Game.Graphics.UserInterface { direction = value; base.Direction = direction.HasFlag(BarDirection.Horizontal) ? FillDirection.Vertical : FillDirection.Horizontal; + foreach (var bar in Children) { bar.Size = direction.HasFlag(BarDirection.Horizontal) ? new Vector2(1, 1.0f / Children.Count) : new Vector2(1.0f / Children.Count, 1); @@ -41,6 +42,7 @@ namespace osu.Game.Graphics.UserInterface set { List bars = Children.ToList(); + foreach (var bar in value.Select((length, index) => new { Value = length, Bar = bars.Count > index ? bars[index] : null })) { float length = MaxValue ?? value.Max(); diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs index 74025b71ff..3882e7c1e5 100644 --- a/osu.Game/Graphics/UserInterface/LineGraph.cs +++ b/osu.Game/Graphics/UserInterface/LineGraph.cs @@ -86,6 +86,7 @@ namespace osu.Game.Graphics.UserInterface protected override void Update() { base.Update(); + if (!pathCached.IsValid) { applyPath(); diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index c558fd7c7b..c3c447ef83 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -203,6 +203,7 @@ namespace osu.Game.Graphics.UserInterface private int findPrecision(decimal d) { int precision = 0; + while (d != Math.Round(d)) { d *= 10; diff --git a/osu.Game/Graphics/UserInterface/StarCounter.cs b/osu.Game/Graphics/UserInterface/StarCounter.cs index ac6e393435..f7f282c1aa 100644 --- a/osu.Game/Graphics/UserInterface/StarCounter.cs +++ b/osu.Game/Graphics/UserInterface/StarCounter.cs @@ -100,6 +100,7 @@ namespace osu.Game.Graphics.UserInterface public void StopAnimation() { int i = 0; + foreach (var star in stars.Children) { star.ClearTransforms(true); @@ -120,6 +121,7 @@ namespace osu.Game.Graphics.UserInterface private void transformCount(float newValue) { int i = 0; + foreach (var star in stars.Children) { star.ClearTransforms(true); diff --git a/osu.Game/IO/Legacy/SerializationReader.cs b/osu.Game/IO/Legacy/SerializationReader.cs index 95ee5aea6b..7a84c11930 100644 --- a/osu.Game/IO/Legacy/SerializationReader.cs +++ b/osu.Game/IO/Legacy/SerializationReader.cs @@ -85,6 +85,7 @@ namespace osu.Game.IO.Legacy for (int i = 0; i < count; i++) { T obj = new T(); + try { obj.ReadFromStream(sr); @@ -129,44 +130,63 @@ namespace osu.Game.IO.Legacy public object ReadObject() { ObjType t = (ObjType)ReadByte(); + switch (t) { case ObjType.boolType: return ReadBoolean(); + case ObjType.byteType: return ReadByte(); + case ObjType.uint16Type: return ReadUInt16(); + case ObjType.uint32Type: return ReadUInt32(); + case ObjType.uint64Type: return ReadUInt64(); + case ObjType.sbyteType: return ReadSByte(); + case ObjType.int16Type: return ReadInt16(); + case ObjType.int32Type: return ReadInt32(); + case ObjType.int64Type: return ReadInt64(); + case ObjType.charType: return ReadChar(); + case ObjType.stringType: return base.ReadString(); + case ObjType.singleType: return ReadSingle(); + case ObjType.doubleType: return ReadDouble(); + case ObjType.decimalType: return ReadDecimal(); + case ObjType.dateTimeType: return ReadDateTime(); + case ObjType.byteArrayType: return ReadByteArray(); + case ObjType.charArrayType: return ReadCharArray(); + case ObjType.otherType: return DynamicDeserializer.Deserialize(BaseStream); + default: return null; } @@ -241,6 +261,7 @@ namespace osu.Game.IO.Legacy string toAssemblyName = assemblyName.Split(',')[0]; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + foreach (Assembly a in assemblies) { if (a.FullName.Split(',')[0] == toAssemblyName) diff --git a/osu.Game/IO/Legacy/SerializationWriter.cs b/osu.Game/IO/Legacy/SerializationWriter.cs index 695767c822..f30e4492af 100644 --- a/osu.Game/IO/Legacy/SerializationWriter.cs +++ b/osu.Game/IO/Legacy/SerializationWriter.cs @@ -111,6 +111,7 @@ namespace osu.Game.IO.Legacy else { Write(d.Count); + foreach (KeyValuePair kvp in d) { WriteObject(kvp.Key); diff --git a/osu.Game/IO/Serialization/Converters/TypedListConverter.cs b/osu.Game/IO/Serialization/Converters/TypedListConverter.cs index 13be4be0c6..6d244bff60 100644 --- a/osu.Game/IO/Serialization/Converters/TypedListConverter.cs +++ b/osu.Game/IO/Serialization/Converters/TypedListConverter.cs @@ -65,6 +65,7 @@ namespace osu.Game.IO.Serialization.Converters var lookupTable = new List(); var objects = new List(); + foreach (var item in list) { var type = item.GetType(); @@ -75,6 +76,7 @@ namespace osu.Game.IO.Serialization.Converters typeString += $", {assemblyName.Version}"; int typeId = lookupTable.IndexOf(typeString); + if (typeId == -1) { lookupTable.Add(typeString); diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index c5f6ef41c2..6d855765b1 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -113,6 +113,7 @@ namespace osu.Game.Online.API } break; + case APIState.Offline: case APIState.Connecting: //work to restore a connection... @@ -300,6 +301,7 @@ namespace osu.Game.Online.API case HttpStatusCode.Unauthorized: Logout(); return true; + case HttpStatusCode.RequestTimeout: failureCount++; log.Add($@"API failure count is now {failureCount}"); diff --git a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs index 8ee71ce9ac..b2bb48b3de 100644 --- a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs @@ -72,26 +72,33 @@ namespace osu.Game.Online.API.Requests.Responses foreach (var kvp in value) { HitResult newKey; + 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; } diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index d35dc07368..e1fc65da6c 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -51,6 +51,7 @@ namespace osu.Game.Online.Chat private static void handleMatches(Regex regex, string display, string link, MessageFormatterResult result, int startIndex = 0, LinkAction? linkActionOverride = null) { int captureOffset = 0; + foreach (Match m in regex.Matches(result.Text, startIndex)) { var index = m.Index - captureOffset; @@ -114,51 +115,63 @@ namespace osu.Game.Online.Chat case "b": case "beatmaps": return new LinkDetails(LinkAction.OpenBeatmap, args[3]); + case "s": case "beatmapsets": case "d": return new LinkDetails(LinkAction.OpenBeatmapSet, args[3]); + case "u": return new LinkDetails(LinkAction.OpenUserProfile, args[3]); } } return new LinkDetails(LinkAction.External, null); + case "osu": // every internal link also needs some kind of argument if (args.Length < 3) return new LinkDetails(LinkAction.External, null); LinkAction linkType; + switch (args[1]) { case "chan": linkType = LinkAction.OpenChannel; break; + case "edit": linkType = LinkAction.OpenEditorTimestamp; break; + case "b": linkType = LinkAction.OpenBeatmap; break; + case "s": case "dl": linkType = LinkAction.OpenBeatmapSet; break; + case "spectate": linkType = LinkAction.Spectate; break; + case "u": linkType = LinkAction.OpenUserProfile; break; + default: linkType = LinkAction.External; break; } return new LinkDetails(linkType, args[2]); + case "osump": return new LinkDetails(LinkAction.JoinMultiplayerMatch, args[1]); + default: return new LinkDetails(LinkAction.External, null); } diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index ac1666f8ed..3ce71cccba 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -74,6 +74,7 @@ namespace osu.Game.Online.Leaderboards scrollContainer.Add(scrollFlow); int i = 0; + foreach (var s in scrollFlow.Children) { using (s.BeginDelayedSequence(i++ * 50, true)) @@ -138,18 +139,23 @@ namespace osu.Game.Online.Leaderboards OnRetry = UpdateScores, }); break; + case PlaceholderState.Unavailable: replacePlaceholder(new MessagePlaceholder(@"Leaderboards are not available for this beatmap!")); break; + case PlaceholderState.NoScores: replacePlaceholder(new MessagePlaceholder(@"No records yet!")); break; + case PlaceholderState.NotLoggedIn: replacePlaceholder(new MessagePlaceholder(@"Please sign in to view online leaderboards!")); break; + case PlaceholderState.NotSupporter: replacePlaceholder(new MessagePlaceholder(@"Please invest in an osu!supporter tag to view this leaderboard!")); break; + default: replacePlaceholder(null); break; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e470d554c9..5ac5842b22 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -271,6 +271,7 @@ namespace osu.Game { var databasedScore = ScoreManager.GetScore(score); var databasedScoreInfo = databasedScore.ScoreInfo; + if (databasedScore.Replay == null) { Logger.Log("The loaded score has no replay data.", LoggingTarget.Information); @@ -278,6 +279,7 @@ namespace osu.Game } var databasedBeatmap = BeatmapManager.QueryBeatmap(b => b.ID == databasedScoreInfo.Beatmap.ID); + if (databasedBeatmap == null) { Logger.Log("Tried to load a score for a beatmap we don't have!", LoggingTarget.Information); @@ -661,9 +663,11 @@ namespace osu.Game case GlobalAction.ToggleChat: chatOverlay.ToggleVisibility(); return true; + case GlobalAction.ToggleSocial: social.ToggleVisibility(); return true; + case GlobalAction.ResetInputSettings: var sensitivity = frameworkConfig.GetBindable(FrameworkSetting.CursorSensitivity); @@ -674,15 +678,19 @@ namespace osu.Game frameworkConfig.Set(FrameworkSetting.IgnoredInputHandlers, string.Empty); frameworkConfig.GetBindable(FrameworkSetting.ConfineMouseMode).SetDefault(); return true; + case GlobalAction.ToggleToolbar: Toolbar.ToggleVisibility(); return true; + case GlobalAction.ToggleSettings: settings.ToggleVisibility(); return true; + case GlobalAction.ToggleDirect: direct.ToggleVisibility(); return true; + case GlobalAction.ToggleGameplayMouseButtons: LocalConfig.Set(OsuSetting.MouseDisableButtons, !LocalConfig.Get(OsuSetting.MouseDisableButtons)); return true; @@ -758,6 +766,7 @@ namespace osu.Game case Intro intro: introScreen = intro; break; + case MainMenu menu: menuScreen = menu; break; diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 13d8df098f..e136fc1403 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -209,6 +209,7 @@ namespace osu.Game.Overlays.AccountCreation private bool focusNextTextbox() { var nextTextbox = nextUnfilledTextbox(); + if (nextTextbox != null) { Schedule(() => GetContainingInputManager().ChangeFocus(nextTextbox)); diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index e3df81e455..aec78b962f 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -99,6 +99,7 @@ namespace osu.Game.Overlays.Chat private void pendingMessageResolved(Message existing, Message updated) { var found = ChatLineFlow.Children.LastOrDefault(c => c.Message == existing); + if (found != null) { Trace.Assert(updated.Id.HasValue, "An updated message was returned with no ID."); diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 77f88ab4e7..221fd35576 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -205,6 +205,7 @@ namespace osu.Game.Overlays Scheduler.Add(() => channelTabControl.Current.Value = e.NewValue); var loaded = loadedChannels.Find(d => d.Channel == e.NewValue); + if (loaded == null) { currentChannelContainer.FadeOut(500, Easing.OutQuint); @@ -288,6 +289,7 @@ namespace osu.Game.Overlays case Key.Number9: selectTab((int)e.Key - (int)Key.Number1); return true; + case Key.Number0: selectTab(9); return true; diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index ede2f34574..1ab5d76555 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -72,6 +72,7 @@ namespace osu.Game.Overlays.Dialog set { buttonsContainer.ChildrenEnumerable = value; + foreach (PopupDialogButton b in value) { var action = b.Action; @@ -222,6 +223,7 @@ namespace osu.Game.Overlays.Dialog // press button at number if 1-9 on number row or keypad are pressed var k = e.Key; + if (k >= Key.Number1 && k <= Key.Number9) { pressButtonAtIndex(k - Key.Number1); diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 34edbbcc8b..40c4c90fca 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -58,6 +58,7 @@ namespace osu.Game.Overlays var artists = new List(); var songs = new List(); var tags = new List(); + foreach (var s in beatmapSets) { artists.Add(s.Metadata.Artist); @@ -210,6 +211,7 @@ namespace osu.Game.Overlays Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }; + default: return new DirectListPanel(b); } diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 8313dac50a..ee7a65042b 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -117,6 +117,7 @@ namespace osu.Game.Overlays.KeyBinding public void RestoreDefaults() { int i = 0; + foreach (var d in Defaults) { var button = buttons[i++]; diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index 23b75caedc..fa1ee500a8 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -81,6 +81,7 @@ namespace osu.Game.Overlays.Mods backgroundIcon.RotateTo(-rotate_angle * direction, mod_switch_duration, mod_switch_easing); backgroundIcon.Icon = modAfter.Icon; + using (BeginDelayedSequence(mod_switch_duration, true)) { foregroundIcon @@ -139,6 +140,7 @@ namespace osu.Game.Overlays.Mods } createIcons(); + if (Mods.Length > 0) { displayMod(Mods[0]); @@ -168,6 +170,7 @@ namespace osu.Game.Overlays.Mods case MouseButton.Left: SelectNext(1); break; + case MouseButton.Right: SelectNext(-1); break; @@ -219,6 +222,7 @@ namespace osu.Game.Overlays.Mods private void createIcons() { iconsContainer.Clear(); + if (Mods.Length > 1) { iconsContainer.AddRange(new[] diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index a118357f21..50400e254f 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -77,6 +77,7 @@ namespace osu.Game.Overlays.Mods public void DeselectTypes(IEnumerable modTypes, bool immediate = false) { int delay = 0; + foreach (var button in buttons) { Mod selected = button.SelectedMod; diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 310c6c919f..89d166b788 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -190,6 +190,7 @@ namespace osu.Game.Overlays.Music // the item positions as they are being transformed float heightAccumulator = 0; int dstIndex = 0; + for (; dstIndex < items.Count; dstIndex++) { // Using BoundingBox here takes care of scale, paddings, etc... diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 8cbea63fe3..c66d0694ae 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -81,6 +81,7 @@ namespace osu.Game.Overlays.Music filter.Search.OnCommit = (sender, newText) => { BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault(); + if (toSelect != null) { beatmap.Value = beatmaps.GetWorkingBeatmap(toSelect); diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index ce2137346f..75073a14f1 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -296,6 +296,7 @@ namespace osu.Game.Overlays queuedDirection = TransformDirection.Prev; var playable = beatmapSets.TakeWhile(i => i.ID != current.BeatmapSetInfo.ID).LastOrDefault() ?? beatmapSets.LastOrDefault(); + if (playable != null) { beatmap.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); @@ -309,6 +310,7 @@ namespace osu.Game.Overlays queuedDirection = TransformDirection.Next; var playable = beatmapSets.SkipWhile(i => i.ID != current.BeatmapSetInfo.ID).Skip(1).FirstOrDefault() ?? beatmapSets.FirstOrDefault(); + if (playable != null) { beatmap.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); @@ -399,6 +401,7 @@ namespace osu.Game.Overlays newBackground.MoveToX(0, 500, Easing.OutCubic); background.MoveToX(-400, 500, Easing.OutCubic); break; + case TransformDirection.Prev: newBackground.Position = new Vector2(-400, 0); newBackground.MoveToX(0, 500, Easing.OutCubic); diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs index ff4d7a10dc..769eff53c2 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -106,6 +106,7 @@ namespace osu.Game.Overlays.Profile.Header visibleBadge = 0; badgeFlowContainer.Clear(); + for (var index = 0; index < badges.Length; index++) { int displayIndex = index; diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 28877c21f0..b8a07dfad2 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -408,6 +408,7 @@ namespace osu.Game.Overlays.Profile infoTextLeft.AddLink("forum post".ToQuantity(user.PostCount), url: $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: boldItalic); string websiteWithoutProtcol = user.Website; + if (!string.IsNullOrEmpty(websiteWithoutProtcol)) { int protocolIndex = websiteWithoutProtcol.IndexOf("//", StringComparison.Ordinal); @@ -468,14 +469,11 @@ namespace osu.Game.Overlays.Profile if (string.IsNullOrEmpty(str)) return; infoTextRight.AddIcon(icon); + if (url != null) - { infoTextRight.AddLink(" " + str, url); - } else - { infoTextRight.AddText(" " + str); - } infoTextRight.NewLine(); } diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 02e9d48f40..ec35040a42 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -64,6 +64,7 @@ namespace osu.Game.Overlays.Settings { bindable = value; controlWithCurrent?.Current.BindTo(bindable); + if (ShowsDefaultIndicator) { restoreDefaultButton.Bindable = bindable.GetBoundCopy(); diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index c7736d6047..a94f76e7af 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -46,6 +46,7 @@ namespace osu.Game.Overlays.Settings set { selected = value; + if (selected) { selectionIndicator.FadeIn(50); diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index daf3d1c576..e6d0c2fe40 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -111,6 +111,7 @@ namespace osu.Game.Overlays ChildrenEnumerable = Users.Select(u => { SocialPanel panel; + switch (displayStyle) { case PanelDisplayStyle.Grid: @@ -120,6 +121,7 @@ namespace osu.Game.Overlays Origin = Anchor.TopCentre }; break; + default: panel = new SocialListPanel(u); break; @@ -167,6 +169,7 @@ namespace osu.Game.Overlays friendRequest.Success += updateUsers; api.Queue(getUsersRequest = friendRequest); break; + default: var userRequest = new GetUsersRequest(); // TODO filter arguments! userRequest.Success += response => updateUsers(response.Select(r => r.User)); @@ -200,6 +203,7 @@ namespace osu.Game.Overlays case APIState.Online: Scheduler.AddOnce(updateSearch); break; + default: Users = null; clearPanels(); diff --git a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs index ca86ce7aa7..b2ae273e31 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs @@ -21,6 +21,7 @@ namespace osu.Game.Overlays.Toolbar set { stateContainer = value; + if (stateContainer != null) { Action = stateContainer.ToggleVisibility; @@ -55,6 +56,7 @@ namespace osu.Game.Overlays.Toolbar case Visibility.Hidden: stateBackground.FadeOut(200); break; + case Visibility.Visible: stateBackground.FadeIn(200); break; diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index d01eab4dab..bbe1b34a48 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -71,6 +71,7 @@ namespace osu.Game.Overlays.Toolbar private void load(RulesetStore rulesets, Bindable parentRuleset) { this.rulesets = rulesets; + foreach (var r in rulesets.AvailableRulesets) { modeButtons.Add(new ToolbarRulesetButton diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 48ce055975..f856592f2e 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -176,6 +176,7 @@ namespace osu.Game.Overlays foreach (string id in user.ProfileOrder) { var sec = sections.FirstOrDefault(s => s.Identifier == id); + if (sec != null) { sec.User.Value = user; diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 85b6c91a07..8f892f2be1 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -71,12 +71,14 @@ namespace osu.Game.Rulesets.Edit if (state == value) return; state = value; + switch (state) { case SelectionState.Selected: Show(); Selected?.Invoke(this); break; + case SelectionState.NotSelected: Hide(); Deselected?.Invoke(this); diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index a7cfbd3300..edbf9079af 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -97,6 +97,7 @@ namespace osu.Game.Rulesets.Objects.Drawables private void load() { var judgement = HitObject.CreateJudgement(); + if (judgement != null) { Result = CreateResult(judgement); @@ -211,9 +212,11 @@ namespace osu.Game.Rulesets.Objects.Drawables { case HitResult.None: break; + case HitResult.Miss: State.Value = ArmedState.Miss; break; + default: State.Value = ArmedState.Hit; break; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 8d6bb8bd3f..c14f3b6a42 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -84,6 +84,7 @@ namespace osu.Game.Rulesets.Objects.Legacy var points = new Vector2[pointCount]; int pointIndex = 1; + foreach (string t in pointSplit) { if (t.Length == 1) @@ -93,12 +94,15 @@ namespace osu.Game.Rulesets.Objects.Legacy case @"C": pathType = PathType.Catmull; break; + case @"B": pathType = PathType.Bezier; break; + case @"L": pathType = PathType.Linear; break; + case @"P": pathType = PathType.PerfectCurve; break; @@ -143,6 +147,7 @@ namespace osu.Game.Rulesets.Objects.Legacy if (split.Length > 9 && split[9].Length > 0) { string[] sets = split[9].Split('|'); + for (int i = 0; i < nodes; i++) { if (i >= sets.Length) @@ -162,6 +167,7 @@ namespace osu.Game.Rulesets.Objects.Legacy if (split.Length > 8 && split[8].Length > 0) { string[] adds = split[8].Split('|'); + for (int i = 0; i < nodes; i++) { if (i >= adds.Length) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 1e9767a54f..5515d4a41a 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -95,6 +95,7 @@ namespace osu.Game.Rulesets.Objects path.Clear(); int i = 0; + for (; i < calculatedPath.Count && cumulativeLength[i] < d0; ++i) { } @@ -142,6 +143,7 @@ namespace osu.Game.Rulesets.Objects { case PathType.Linear: return PathApproximator.ApproximateLinear(subControlPoints); + case PathType.PerfectCurve: //we can only use CircularArc iff we have exactly three control points and no dissection. if (ControlPoints.Length != 3 || subControlPoints.Length != 3) @@ -155,6 +157,7 @@ namespace osu.Game.Rulesets.Objects break; return subpath; + case PathType.Catmull: return PathApproximator.ApproximateCatmull(subControlPoints); } diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index bbb587cb3f..0e74caf8ba 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -124,6 +124,7 @@ namespace osu.Game.Rulesets.UI onScreenDisplay = dependencies.Get(); Config = dependencies.Get().GetConfigFor(Ruleset); + if (Config != null) { dependencies.Cache(Config); diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 6df418753c..b6c2d016d2 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -76,6 +76,7 @@ namespace osu.Game.Screens.Backgrounds private void switchBackground(BeatmapBackground b) { float newDepth = 0; + if (Background != null) { newDepth = Background.Depth + 1; diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 9ccf974244..5699ef0a84 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -100,6 +100,7 @@ namespace osu.Game.Screens.Edit.Compose }; var ruleset = Beatmap.Value.BeatmapInfo.Ruleset?.CreateInstance(); + if (ruleset == null) { Logger.Log("Beatmap doesn't have a ruleset assigned."); @@ -108,6 +109,7 @@ namespace osu.Game.Screens.Edit.Compose } composer = ruleset.CreateHitObjectComposer(); + if (composer == null) { Logger.Log($"Ruleset {ruleset.Description} doesn't support hitobject composition."); diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 0ba1e74aca..3ae26c4ea4 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -70,6 +70,7 @@ namespace osu.Game.Screens.Edit PlaybackControl playback; var fileMenuItems = new List(); + if (RuntimeInfo.IsDesktop) { fileMenuItems.Add(new EditorMenuItem("Export", MenuItemType.Standard, exportBeatmap)); @@ -173,6 +174,7 @@ namespace osu.Game.Screens.Edit case Key.Left: seek(e, -1); return true; + case Key.Right: seek(e, 1); return true; @@ -218,6 +220,7 @@ namespace osu.Game.Screens.Edit public override bool OnExiting(IScreen next) { Background.FadeColour(Color4.White, 500); + if (Beatmap.Value.Track != null) { Beatmap.Value.Track.Tempo.Value = 1; @@ -238,9 +241,11 @@ namespace osu.Game.Screens.Edit case EditorScreenMode.Compose: currentScreen = new ComposeScreen(); break; + case EditorScreenMode.Design: currentScreen = new DesignScreen(); break; + default: currentScreen = new EditorScreen(); break; diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 8f65366650..24fb561f04 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -83,6 +83,7 @@ namespace osu.Game.Screens.Edit if (amount <= 0) throw new ArgumentException("Value should be greater than zero", nameof(amount)); var timingPoint = ControlPointInfo.TimingPointAt(CurrentTime); + if (direction < 0 && timingPoint.Time == CurrentTime) { // When going backwards and we're at the boundary of two timing points, we compute the seek distance with the timing point which we are seeking into diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index bcd24fd83e..61b93c9486 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -156,9 +156,11 @@ namespace osu.Game.Screens.Menu { case GlobalAction.Back: return goBack(); + case GlobalAction.Select: logo?.Click(); return true; + default: return false; } @@ -174,9 +176,11 @@ namespace osu.Game.Screens.Menu State = ButtonSystemState.Initial; sampleBack?.Play(); return true; + case ButtonSystemState.Play: backButton.Click(); return true; + default: return false; } @@ -188,12 +192,15 @@ namespace osu.Game.Screens.Menu { default: return true; + case ButtonSystemState.Initial: State = ButtonSystemState.TopLevel; return true; + case ButtonSystemState.TopLevel: buttonsTopLevel.First().Click(); return false; + case ButtonSystemState.Play: buttonsPlay.First().Click(); return false; @@ -259,12 +266,14 @@ namespace osu.Game.Screens.Menu logo.ScaleTo(1, 800, Easing.OutExpo); }, buttonArea.Alpha * 150); break; + case ButtonSystemState.TopLevel: case ButtonSystemState.Play: switch (lastState) { case ButtonSystemState.TopLevel: // coming from toplevel to play break; + case ButtonSystemState.Initial: logo.ClearTransforms(targetMember: nameof(Position)); logo.RelativePositionAxes = Axes.None; @@ -287,6 +296,7 @@ namespace osu.Game.Screens.Menu game?.Toolbar.Show(); }, 200); break; + default: logo.ClearTransforms(targetMember: nameof(Position)); logo.RelativePositionAxes = Axes.None; @@ -296,6 +306,7 @@ namespace osu.Game.Screens.Menu } break; + case ButtonSystemState.EnteringMode: logoTracking = true; break; diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index a41a12927b..a6ca483c12 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -118,6 +118,7 @@ namespace osu.Game.Screens.Menu base.Update(); float decayFactor = (float)Time.Elapsed * decay_per_milisecond; + for (int i = 0; i < bars_per_visualiser; i++) { //3% of extra bar length to make it a little faster when bar is almost at it's minimum diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 5798fce457..485de87d31 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -258,6 +258,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components // nice little progressive fade int time = 500; + foreach (var c in fill.Children) { c.Delay(500 - time).FadeOut(time, Easing.Out); diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index a71106872e..eac9871a57 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -149,6 +149,7 @@ namespace osu.Game.Screens.Multi.Match header.Tabs.Current.BindValueChanged(tab => { const float fade_duration = 500; + if (tab.NewValue is SettingsMatchPage) { settings.Show(); diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 5e019a7b3a..a726523ee5 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -248,6 +248,7 @@ namespace osu.Game.Screens.Multi if (screenStack.CurrentScreen is MatchSubScreen) { var track = Beatmap.Value.Track; + if (track != null) { track.Looping = true; diff --git a/osu.Game/Screens/OsuScreenDependencies.cs b/osu.Game/Screens/OsuScreenDependencies.cs index 84e5de76de..8c759ec6f8 100644 --- a/osu.Game/Screens/OsuScreenDependencies.cs +++ b/osu.Game/Screens/OsuScreenDependencies.cs @@ -20,12 +20,14 @@ namespace osu.Game.Screens if (requireLease) { Beatmap = parent.Get>()?.GetBoundCopy(); + if (Beatmap == null) { Cache(Beatmap = parent.Get>().BeginLease(false)); } Ruleset = parent.Get>()?.GetBoundCopy(); + if (Ruleset == null) { Cache(Ruleset = parent.Get>().BeginLease(true)); diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index 2c1293833f..2df5ce101c 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -68,6 +68,7 @@ namespace osu.Game.Screens.Play.HUD Current.ValueChanged += mods => { iconsContainer.Clear(); + foreach (Mod mod in mods.NewValue) { iconsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.6f) }); diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 0626c40334..88a62ac8d4 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -52,6 +52,7 @@ namespace osu.Game.Screens.Play { isLit = value; updateGlowSprite(value); + if (value && IsCounting) { CountPresses++; diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index d10034d552..5b7a9574b6 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -169,6 +169,7 @@ namespace osu.Game.Screens.Play var max = values.Max(); float step = values.Length / (float)ColumnCount; + for (float i = 0; i < values.Length; i += step) { newValues.Add((float)values[(int)i] / max); diff --git a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs index 043bf55d2b..fab227c7f4 100644 --- a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs +++ b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs @@ -180,6 +180,7 @@ namespace osu.Game.Screens.Ranking.Pages scoreCounter.Increment(Score.TotalScore); int delay = 0; + foreach (var s in statisticsContainer.Children) { s.FadeOut() @@ -336,6 +337,7 @@ namespace osu.Game.Screens.Ranking.Pages versionMapper.Colour = colours.Gray8; var creator = beatmap.Metadata.Author?.Username; + if (!string.IsNullOrEmpty(creator)) { versionMapper.Text = $"mapped by {creator}"; diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index d7240a40ad..63ad3b6ab2 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -257,6 +257,7 @@ namespace osu.Game.Screens.Select select(beatmap); return; + case CarouselBeatmapSet set: if (skipDifficulties) select(set); @@ -292,6 +293,7 @@ namespace osu.Game.Screens.Select if (RandomAlgorithm.Value == RandomSelectAlgorithm.RandomPermutation) { var notYetVisitedSets = visibleSets.Except(previouslyVisitedRandomSets).ToList(); + if (!notYetVisitedSets.Any()) { previouslyVisitedRandomSets.RemoveAll(s => visibleSets.Contains(s)); @@ -394,13 +396,16 @@ namespace osu.Game.Screens.Select case Key.Up: direction = -1; break; + case Key.Down: direction = 1; break; + case Key.Left: direction = -1; skipDifficulties = true; break; + case Key.Right: direction = 1; skipDifficulties = true; @@ -465,8 +470,10 @@ namespace osu.Game.Screens.Select case LoadState.NotLoaded: LoadComponentAsync(item); break; + case LoadState.Loading: break; + default: scrollableContent.Add(item); break; @@ -557,6 +564,7 @@ namespace osu.Game.Screens.Select set.MoveToX(set.Item.State.Value == CarouselItemState.Selected ? -100 : 0, 500, Easing.OutExpo); set.MoveToY(currentY, 750, Easing.OutExpo); break; + case DrawableCarouselBeatmap beatmap: if (beatmap.Item.State.Value == CarouselItemState.Selected) scrollTarget = currentY + beatmap.DrawHeight / 2 - DrawHeight / 2; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 6a10e86198..7c7d9e3928 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -53,6 +53,7 @@ namespace osu.Game.Screens.Select var autoType = auto.GetType(); var mods = SelectedMods.Value; + if (mods.All(m => m.GetType() != autoType)) { SelectedMods.Value = mods.Append(auto); diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index f8445a4a7d..8499b56847 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -318,6 +318,7 @@ namespace osu.Game.Screens.Tournament using (StreamReader sr = new StreamReader(stream)) { string line; + while ((line = sr.ReadLine()?.Trim()) != null) { if (string.IsNullOrEmpty(line)) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 358b2b222b..ea4a777b47 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -49,15 +49,19 @@ namespace osu.Game.Skinning case "Play/Miss": componentName = "hit0"; break; + case "Play/Meh": componentName = "hit50"; break; + case "Play/Good": componentName = "hit100"; break; + case "Play/Great": componentName = "hit300"; break; + case "Play/osu/number-text": return !hasFont(Configuration.HitCircleFont) ? null @@ -82,6 +86,7 @@ namespace osu.Game.Skinning float ratio = 2; var texture = Textures.Get($"{componentName}@2x"); + if (texture == null) { ratio = 1; @@ -184,6 +189,7 @@ namespace osu.Game.Skinning float ratio = 36; var texture = textures.Get($"{textureName}@2x"); + if (texture == null) { ratio = 18; diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index f6bbbc8355..3a4d44f608 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -76,6 +76,7 @@ namespace osu.Game.Skinning base.Populate(model, archive); Skin reference = getSkin(model); + if (!string.IsNullOrEmpty(reference.Configuration.SkinInfo.Name)) { model.Name = reference.Configuration.SkinInfo.Name; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index 0b9ebaf3a7..d01fba7d39 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -67,6 +67,7 @@ namespace osu.Game.Storyboards.Drawables private void load(IBindable beatmap, TextureStore textureStore) { var basePath = Animation.Path.ToLowerInvariant(); + for (var frame = 0; frame < Animation.FrameCount; frame++) { var framePath = basePath.Replace(".", frame + "."); diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index b91b05bd04..8f8ec22aae 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -82,6 +82,7 @@ namespace osu.Game.Storyboards where T : struct { var initialized = false; + foreach (var command in commands.OrderBy(l => l)) { if (!initialized) diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 44ac38044d..6a5e17eb38 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -35,6 +35,7 @@ namespace osu.Game.Tests.Beatmaps Assert.Multiple(() => { int mappingCounter = 0; + while (true) { if (mappingCounter >= ourResult.Mappings.Count && mappingCounter >= expectedResult.Mappings.Count) @@ -61,6 +62,7 @@ namespace osu.Game.Tests.Beatmaps Assert.Multiple(() => { int objectCounter = 0; + while (true) { if (objectCounter >= ourMapping.Objects.Count && objectCounter >= expectedMapping.Objects.Count) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index cfffed663c..e6f8044b60 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -231,6 +231,7 @@ True NEXT_LINE 1 + 1 NEXT_LINE 1 1 From c39c37a18dce16f25fbf9a23be5f27c93c485320 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Apr 2019 12:44:46 +0900 Subject: [PATCH 0443/5608] Apply more missed cases --- osu.Desktop/Updater/SimpleUpdateManager.cs | 1 + .../CatchBeatmapConversionTest.cs | 2 ++ osu.Game.Rulesets.Catch/CatchRuleset.cs | 4 ++++ .../Judgements/CatchBananaJudgement.cs | 2 ++ .../Judgements/CatchDropletJudgement.cs | 2 ++ .../Judgements/CatchJudgement.cs | 2 ++ .../Judgements/CatchTinyDropletJudgement.cs | 2 ++ .../Objects/Drawable/DrawableCatchHitObject.cs | 1 + osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 1 + .../UI/DrawableCatchRuleset.cs | 5 +++++ .../Legacy/EndTimeObjectPatternGenerator.cs | 2 ++ .../Edit/ManiaHitObjectComposer.cs | 1 + .../Judgements/ManiaJudgement.cs | 4 ++++ .../Objects/Drawables/DrawableManiaHitObject.cs | 1 + .../Scoring/ManiaScoreProcessor.cs | 5 +++++ .../OsuBeatmapConversionTest.cs | 1 + .../Sliders/Components/SliderCirclePiece.cs | 1 + .../Edit/OsuHitObjectComposer.cs | 2 ++ osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs | 3 +++ osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 3 +++ .../Objects/Drawables/DrawableRepeatPoint.cs | 2 ++ .../Objects/Drawables/DrawableSliderTick.cs | 2 ++ .../Objects/Drawables/DrawableSpinner.cs | 2 ++ osu.Game.Rulesets.Osu/Objects/Slider.cs | 3 +++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 5 +++++ osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs | 2 ++ .../TestCaseTaikoPlayfield.cs | 5 +++++ .../Judgements/TaikoDrumRollJudgement.cs | 1 + .../Judgements/TaikoDrumRollTickJudgement.cs | 2 ++ .../Judgements/TaikoJudgement.cs | 5 +++++ .../Judgements/TaikoSwellJudgement.cs | 1 + .../Objects/Drawables/DrawableSwell.cs | 1 + .../Objects/TaikoHitWindows.cs | 1 + osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 4 ++++ .../UI/DrawableTaikoJudgement.cs | 1 + .../UI/DrawableTaikoRuleset.cs | 5 +++++ osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 ++ .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 15 +++++++++++++++ .../Formats/LegacyStoryboardDecoderTest.cs | 2 ++ .../Beatmaps/Formats/OsuJsonDecoderTest.cs | 1 + .../Beatmaps/IO/OszArchiveReaderTest.cs | 1 + osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 1 + .../Gameplay/TestCaseScrollingHitObjects.cs | 4 ++++ .../Visual/SongSelect/TestCaseBeatmapInfoWedge.cs | 4 ++++ .../UserInterface/TestCaseNotificationOverlay.cs | 3 +++ osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs | 2 ++ .../Drawables/DifficultyColouredContainer.cs | 5 +++++ .../WorkingBeatmap_VirtualBeatmapTrack.cs | 2 ++ .../Containers/OsuFocusedOverlayContainer.cs | 2 ++ osu.Game/Graphics/OsuColour.cs | 2 ++ osu.Game/Graphics/OsuFont.cs | 2 ++ osu.Game/Graphics/ScreenshotManager.cs | 2 ++ osu.Game/Graphics/UserInterface/OsuMenu.cs | 2 ++ osu.Game/Input/IdleTracker.cs | 1 + osu.Game/Online/API/Requests/GetRoomsRequest.cs | 3 +++ osu.Game/Overlays/AccountCreationOverlay.cs | 2 ++ .../Overlays/BeatmapSet/Buttons/DownloadButton.cs | 3 +++ osu.Game/Overlays/BeatmapSet/Header.cs | 2 ++ osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs | 1 + osu.Game/Overlays/Direct/DownloadButton.cs | 4 ++++ osu.Game/Overlays/Direct/DownloadProgressBar.cs | 3 +++ osu.Game/Overlays/MainSettings.cs | 1 + osu.Game/Overlays/MedalSplash/DrawableMedal.cs | 3 +++ .../Notifications/ProgressNotification.cs | 3 +++ osu.Game/Overlays/OnScreenDisplay.cs | 1 + .../Sections/Ranks/PaginatedScoreContainer.cs | 1 + .../Settings/Sections/General/LoginSettings.cs | 5 +++++ osu.Game/Overlays/Settings/Sidebar.cs | 1 + osu.Game/Overlays/Toolbar/ToolbarUserButton.cs | 1 + osu.Game/Overlays/VolumeOverlay.cs | 2 ++ .../Rulesets/Difficulty/DifficultyCalculator.cs | 2 ++ osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 2 ++ osu.Game/Rulesets/Judgements/DrawableJudgement.cs | 6 ++++++ osu.Game/Rulesets/Mods/ModTimeRamp.cs | 2 ++ osu.Game/Rulesets/Objects/HitWindows.cs | 7 +++++++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 3 +++ osu.Game/Rulesets/UI/ModIcon.cs | 4 ++++ osu.Game/Rulesets/UI/RulesetInputManager.cs | 1 + .../UI/Scrolling/DrawableScrollingRuleset.cs | 3 +++ .../UI/Scrolling/ScrollingHitObjectContainer.cs | 5 +++++ osu.Game/Scoring/Legacy/LegacyScoreInfo.cs | 2 ++ .../Edit/Compose/Components/BeatDivisorControl.cs | 9 +++++++++ osu.Game/Screens/Menu/Button.cs | 5 +++++ osu.Game/Screens/Menu/ButtonArea.cs | 3 +++ osu.Game/Screens/Menu/MainMenu.cs | 1 + osu.Game/Screens/Play/GameplayMenuOverlay.cs | 2 ++ osu.Game/Screens/Play/KeyCounterMouse.cs | 2 ++ osu.Game/Screens/Play/SkipOverlay.cs | 1 + .../Screens/Select/Carousel/CarouselBeatmapSet.cs | 3 +++ osu.Game/Screens/Select/Carousel/CarouselGroup.cs | 1 + .../Select/Carousel/CarouselGroupEagerSelect.cs | 1 + .../Select/Carousel/DrawableCarouselItem.cs | 1 + .../Screens/Tournament/ScrollingTeamContainer.cs | 3 +++ osu.Game/Skinning/LegacySkinDecoder.cs | 3 +++ osu.Game/Tests/Visual/ScrollingTestContainer.cs | 2 ++ 95 files changed, 250 insertions(+) diff --git a/osu.Desktop/Updater/SimpleUpdateManager.cs b/osu.Desktop/Updater/SimpleUpdateManager.cs index 1cb47d6b58..e07ecc9433 100644 --- a/osu.Desktop/Updater/SimpleUpdateManager.cs +++ b/osu.Desktop/Updater/SimpleUpdateManager.cs @@ -78,6 +78,7 @@ namespace osu.Desktop.Updater case RuntimeInfo.Platform.Windows: bestAsset = release.Assets?.Find(f => f.Name.EndsWith(".exe")); break; + case RuntimeInfo.Platform.MacOsx: bestAsset = release.Assets?.Find(f => f.Name.EndsWith(".app.zip")); break; diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index 7f85d4ccce..e45ed8c6f4 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -36,11 +36,13 @@ namespace osu.Game.Rulesets.Catch.Tests yield return new ConvertValue((CatchHitObject)nested); break; + case BananaShower shower: foreach (var nested in shower.NestedHitObjects) yield return new ConvertValue((CatchHitObject)nested); break; + default: yield return new ConvertValue((CatchHitObject)hitObject); diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index aa00e182a9..0c46c1f9e5 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -87,6 +87,7 @@ namespace osu.Game.Rulesets.Catch new CatchModNoFail(), new MultiMod(new CatchModHalfTime(), new CatchModDaycore()) }; + case ModType.DifficultyIncrease: return new Mod[] { @@ -96,17 +97,20 @@ namespace osu.Game.Rulesets.Catch new CatchModHidden(), new CatchModFlashlight(), }; + case ModType.Automation: return new Mod[] { new MultiMod(new CatchModAutoplay(), new ModCinema()), new CatchModRelax(), }; + case ModType.Fun: return new Mod[] { new MultiMod(new ModWindUp(), new ModWindDown()) }; + default: return new Mod[] { }; } diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs index 4e64753a65..1da4cf4a5e 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs @@ -16,6 +16,7 @@ namespace osu.Game.Rulesets.Catch.Judgements { default: return 0; + case HitResult.Perfect: return 1100; } @@ -27,6 +28,7 @@ namespace osu.Game.Rulesets.Catch.Judgements { default: return 0; + case HitResult.Perfect: return 8; } diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs index 2598dee156..4272d8471e 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs @@ -13,6 +13,7 @@ namespace osu.Game.Rulesets.Catch.Judgements { default: return 0; + case HitResult.Perfect: return 30; } @@ -24,6 +25,7 @@ namespace osu.Game.Rulesets.Catch.Judgements { default: return 0; + case HitResult.Perfect: return 7; } diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs index 5d7ef04dd2..6acef7190c 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs @@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Catch.Judgements { default: return 0; + case HitResult.Perfect: return 300; } @@ -28,6 +29,7 @@ namespace osu.Game.Rulesets.Catch.Judgements { default: return 0; + case HitResult.Perfect: return 10.2; } diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs index b8c51b7b60..d71ff3f640 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs @@ -15,6 +15,7 @@ namespace osu.Game.Rulesets.Catch.Judgements { default: return 0; + case HitResult.Perfect: return 10; } @@ -26,6 +27,7 @@ namespace osu.Game.Rulesets.Catch.Judgements { default: return 0; + case HitResult.Perfect: return 4; } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 294fd97d59..2f8ccec48b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -84,6 +84,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable case ArmedState.Miss: this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out).Expire(); break; + case ArmedState.Hit: this.FadeOut().Expire(); break; diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 2adc156efd..a9fd34455a 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -95,6 +95,7 @@ namespace osu.Game.Rulesets.Catch.Objects X = X + Path.PositionAt(e.PathProgress).X / CatchPlayfield.BASE_WIDTH, }); break; + case SliderEventType.Head: case SliderEventType.Tail: case SliderEventType.Repeat: diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index ba0f5b90ba..555c1adc4d 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -46,14 +46,19 @@ namespace osu.Game.Rulesets.Catch.UI { case Banana banana: return new DrawableBanana(banana); + case Fruit fruit: return new DrawableFruit(fruit); + case JuiceStream stream: return new DrawableJuiceStream(stream, CreateDrawableRepresentation); + case BananaShower shower: return new DrawableBananaShower(shower, CreateDrawableRepresentation); + case TinyDroplet tiny: return new DrawableTinyDroplet(tiny); + case Droplet droplet: return new DrawableDroplet(droplet); } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index 0bf6c055ac..9e95be35fa 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs @@ -38,9 +38,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy case 8 when HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && endTime - HitObject.StartTime < 1000: addToPattern(pattern, 0, generateHold); break; + case 8: addToPattern(pattern, FindAvailableColumn(GetRandomColumn(), PreviousPattern), generateHold); break; + default: if (TotalColumns > 0) addToPattern(pattern, GetRandomColumn(), generateHold); diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 56c9471462..eec3e1b33d 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -65,6 +65,7 @@ namespace osu.Game.Rulesets.Mania.Edit { case DrawableNote note: return new NoteSelectionBlueprint(note); + case DrawableHoldNote holdNote: return new HoldNoteSelectionBlueprint(holdNote); } diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs index b6fb37f054..c2f8fb8678 100644 --- a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs @@ -14,12 +14,16 @@ namespace osu.Game.Rulesets.Mania.Judgements { default: return 0; + case HitResult.Meh: return 50; + case HitResult.Ok: return 100; + case HitResult.Good: return 200; + case HitResult.Great: case HitResult.Perfect: return 300; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index a78524011f..0873f753be 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -65,6 +65,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables case ArmedState.Miss: this.FadeOut(150, Easing.In).Expire(); break; + case ArmedState.Hit: this.FadeOut(150, Easing.OutQuint).Expire(); break; diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 5c914d8eac..ba38d11225 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -140,18 +140,23 @@ namespace osu.Game.Rulesets.Mania.Scoring case HitResult.Miss: Health.Value += hpMissMultiplier * hp_increase_miss; break; + case HitResult.Meh: Health.Value += hpMultiplier * hp_increase_bad; break; + case HitResult.Ok: Health.Value += hpMultiplier * hp_increase_ok; break; + case HitResult.Good: Health.Value += hpMultiplier * hp_increase_good; break; + case HitResult.Great: Health.Value += hpMultiplier * hp_increase_great; break; + case HitResult.Perfect: Health.Value += hpMultiplier * hp_increase_perfect; break; diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index f7d1ff4db1..f98d63e6c7 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -35,6 +35,7 @@ namespace osu.Game.Rulesets.Osu.Tests yield return createConvertValue(nested); break; + default: yield return createConvertValue(hitObject); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs index 9d164ebe0b..2ecfea2e3e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs @@ -37,6 +37,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components case SliderPosition.Start: Position = slider.StackedPosition + slider.Path.PositionAt(0); break; + case SliderPosition.End: Position = slider.StackedPosition + slider.Path.PositionAt(1); break; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 039ec5585e..8d007ad88e 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -41,8 +41,10 @@ namespace osu.Game.Rulesets.Osu.Edit { case DrawableHitCircle circle: return new HitCircleSelectionBlueprint(circle); + case DrawableSlider slider: return new SliderSelectionBlueprint(slider); + case DrawableSpinner spinner: return new SpinnerSelectionBlueprint(spinner); } diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs index 81fedf9f4a..bf30fbc351 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs @@ -16,10 +16,13 @@ namespace osu.Game.Rulesets.Osu.Judgements { default: return 0; + case HitResult.Meh: return 50; + case HitResult.Good: return 100; + case HitResult.Great: return 300; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 1a30b2c944..ddf708d0f1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -59,11 +59,13 @@ namespace osu.Game.Rulesets.Osu.Mods circle.FadeOut(fadeOutDuration); break; + case DrawableSlider slider: using (slider.BeginAbsoluteSequence(fadeOutStartTime, true)) slider.Body.FadeOut(longFadeDuration, Easing.Out); break; + case DrawableSliderTick sliderTick: // slider ticks fade out over up to one second var tickFadeOutDuration = Math.Min(sliderTick.HitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000); @@ -72,6 +74,7 @@ namespace osu.Game.Rulesets.Osu.Mods sliderTick.FadeOut(tickFadeOutDuration); break; + case DrawableSpinner spinner: // hide elements we don't care about. spinner.Disc.Hide(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index a6714690b1..c278c0c7ec 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -64,9 +64,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables case ArmedState.Idle: this.Delay(HitObject.TimePreempt).FadeOut(); break; + case ArmedState.Miss: this.FadeOut(animDuration); break; + case ArmedState.Hit: this.FadeOut(animDuration, Easing.OutQuint) .ScaleTo(Scale * 1.5f, animDuration, Easing.Out); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index b5ce36f889..72b648bfd0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -67,10 +67,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables case ArmedState.Idle: this.Delay(HitObject.TimePreempt).FadeOut(); break; + case ArmedState.Miss: this.FadeOut(ANIM_DURATION); this.FadeColour(Color4.Red, ANIM_DURATION / 2); break; + case ArmedState.Hit: this.FadeOut(ANIM_DURATION, Easing.OutQuint); this.ScaleTo(Scale * 1.5f, ANIM_DURATION, Easing.Out); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 3a6ff3fcf8..ca219b0094 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -222,9 +222,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables case ArmedState.Idle: Expire(true); break; + case ArmedState.Hit: sequence.ScaleTo(Scale * 1.2f, 320, Easing.Out); break; + case ArmedState.Miss: sequence.ScaleTo(Scale * 0.8f, 320, Easing.In); break; diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 1afbacc01e..a8aec005d1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -183,6 +183,7 @@ namespace osu.Game.Rulesets.Osu.Objects Samples = sampleList }); break; + case SliderEventType.Head: AddNested(HeadCircle = new SliderCircle { @@ -194,6 +195,7 @@ namespace osu.Game.Rulesets.Osu.Objects ComboIndex = ComboIndex, }); break; + case SliderEventType.LegacyLastTick: // we need to use the LegacyLastTick here for compatibility reasons (difficulty). // it is *okay* to use this because the TailCircle is not used for any meaningful purpose in gameplay. @@ -206,6 +208,7 @@ namespace osu.Game.Rulesets.Osu.Objects ComboIndex = ComboIndex, }); break; + case SliderEventType.Repeat: AddNested(new RepeatPoint { diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 44bce5bed8..3481b7751b 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -104,6 +104,7 @@ namespace osu.Game.Rulesets.Osu new MultiMod(new OsuModHalfTime(), new OsuModDaycore()), new OsuModSpunOut(), }; + case ModType.DifficultyIncrease: return new Mod[] { @@ -113,11 +114,13 @@ namespace osu.Game.Rulesets.Osu new OsuModHidden(), new MultiMod(new OsuModFlashlight(), new OsuModBlinds()), }; + case ModType.Conversion: return new Mod[] { new OsuModTarget(), }; + case ModType.Automation: return new Mod[] { @@ -125,6 +128,7 @@ namespace osu.Game.Rulesets.Osu new OsuModRelax(), new OsuModAutopilot(), }; + case ModType.Fun: return new Mod[] { @@ -133,6 +137,7 @@ namespace osu.Game.Rulesets.Osu new OsuModGrow(), new MultiMod(new ModWindUp(), new ModWindDown()), }; + default: return new Mod[] { }; } diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index 828b3720d3..3adf788665 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -40,8 +40,10 @@ namespace osu.Game.Rulesets.Osu.UI { case HitCircle circle: return new DrawableHitCircle(circle); + case Slider slider: return new DrawableSlider(slider); + case Spinner spinner: return new DrawableSpinner(spinner); } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs index 369cdd49d2..69eb48b7ce 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs @@ -100,15 +100,19 @@ namespace osu.Game.Rulesets.Taiko.Tests case 1: addCentreHit(false); break; + case 2: addCentreHit(true); break; + case 3: addDrumRoll(false); break; + case 4: addDrumRoll(true); break; + case 5: addSwell(); delay = scroll_time - 100; @@ -121,6 +125,7 @@ namespace osu.Game.Rulesets.Taiko.Tests default: playfieldContainer.Delay(delay).ResizeTo(new Vector2(1, rng.Next(25, 400)), 500); break; + case 6: playfieldContainer.Delay(delay).ResizeTo(new Vector2(1, TaikoPlayfield.DEFAULT_HEIGHT), 500); break; diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs index e5ebd5c647..604daa929f 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs @@ -16,6 +16,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements { case HitResult.Miss: return 0; + default: return base.HealthIncreaseFor(result); } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index 32d4b77ca4..a617028f1c 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs @@ -15,6 +15,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements { case HitResult.Great: return 200; + default: return 0; } @@ -26,6 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements { case HitResult.Great: return 0.15; + default: return 0; } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index 427d38aaa7..eb5f443365 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -16,8 +16,10 @@ namespace osu.Game.Rulesets.Taiko.Judgements { case HitResult.Good: return 100; + case HitResult.Great: return 300; + default: return 0; } @@ -29,10 +31,13 @@ namespace osu.Game.Rulesets.Taiko.Judgements { case HitResult.Miss: return -1.0; + case HitResult.Good: return 1.1; + case HitResult.Great: return 3.0; + default: return 0; } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs index f0f621d12b..29be5e0eac 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs @@ -15,6 +15,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements { case HitResult.Miss: return -0.65; + default: return 0; } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 9211eccc40..5ec9dc61e2 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -192,6 +192,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables using (BeginAbsoluteSequence(HitObject.StartTime - preempt, true)) targetRing.ScaleTo(target_ring_scale, preempt * 4, Easing.OutQuint); break; + case ArmedState.Miss: case ArmedState.Hit: this.FadeOut(out_transition_time, Easing.Out); diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs index ce841fff80..f232919cbf 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs @@ -25,6 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Objects case HitResult.Good: case HitResult.Miss: return true; + default: return false; } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 448b1b42bb..1fec4ae173 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -86,6 +86,7 @@ namespace osu.Game.Rulesets.Taiko new TaikoModNoFail(), new MultiMod(new TaikoModHalfTime(), new TaikoModDaycore()), }; + case ModType.DifficultyIncrease: return new Mod[] { @@ -95,17 +96,20 @@ namespace osu.Game.Rulesets.Taiko new TaikoModHidden(), new TaikoModFlashlight(), }; + case ModType.Automation: return new Mod[] { new MultiMod(new TaikoModAutoplay(), new ModCinema()), new TaikoModRelax(), }; + case ModType.Fun: return new Mod[] { new MultiMod(new ModWindUp(), new ModWindDown()) }; + default: return new Mod[] { }; } diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs index 943adaed4b..f91bbb14e8 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs @@ -33,6 +33,7 @@ namespace osu.Game.Rulesets.Taiko.UI case HitResult.Good: JudgementBody.Colour = colours.GreenLight; break; + case HitResult.Great: JudgementBody.Colour = colours.BlueLight; break; diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index f4b9c46dfc..d3b2f4e987 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -52,9 +52,11 @@ namespace osu.Game.Rulesets.Taiko.UI int currentIndex = 0; int currentBeat = 0; double time = timingPoints[currentIndex].Time; + while (time <= lastHitTime) { int nextIndex = currentIndex + 1; + if (nextIndex < timingPoints.Count && time > timingPoints[nextIndex].Time) { currentIndex = nextIndex; @@ -93,10 +95,13 @@ namespace osu.Game.Rulesets.Taiko.UI { case CentreHit centreHit: return new DrawableCentreHit(centreHit); + case RimHit rimHit: return new DrawableRimHit(rimHit); + case DrumRoll drumRoll: return new DrawableDrumRoll(drumRoll); + case Swell swell: return new DrawableSwell(swell); } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index dbff5270d2..260c5b0727 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -211,6 +211,7 @@ namespace osu.Game.Rulesets.Taiko.UI case DrawableBarLine barline: barlineContainer.Add(barline.CreateProxy()); break; + case DrawableTaikoHitObject taikoObject: topLevelHitContainer.Add(taikoObject.CreateProxiedContent()); break; @@ -231,6 +232,7 @@ namespace osu.Game.Rulesets.Taiko.UI if (result.IsHit) hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongNestedHit)judgedObject).MainObject)?.VisualiseSecondHit(); break; + default: judgementContainer.Add(new DrawableTaikoJudgement(result, judgedObject) { diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 02dff6993d..6df4e7d6c8 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -47,6 +47,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapGeneral() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { @@ -70,6 +71,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapEditor() { var decoder = new LegacyBeatmapDecoder(); + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { @@ -95,6 +97,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapMetadata() { var decoder = new LegacyBeatmapDecoder(); + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { @@ -119,6 +122,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapDifficulty() { var decoder = new LegacyBeatmapDecoder(); + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { @@ -137,6 +141,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapEvents() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { @@ -155,6 +160,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapTimingPoints() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { @@ -190,6 +196,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapColours() { var decoder = new LegacySkinDecoder(); + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { @@ -215,6 +222,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapComboOffsetsOsu() { var decoder = new LegacyBeatmapDecoder(); + using (var resStream = TestResources.OpenResource("hitobject-combo-offset.osu")) using (var stream = new StreamReader(resStream)) { @@ -237,6 +245,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapComboOffsetsCatch() { var decoder = new LegacyBeatmapDecoder(); + using (var resStream = TestResources.OpenResource("hitobject-combo-offset.osu")) using (var stream = new StreamReader(resStream)) { @@ -259,6 +268,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapHitObjects() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { @@ -286,6 +296,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeControlPointCustomSampleBank() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + using (var resStream = TestResources.OpenResource("controlpoint-custom-samplebank.osu")) using (var stream = new StreamReader(resStream)) { @@ -307,6 +318,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeHitObjectCustomSampleBank() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + using (var resStream = TestResources.OpenResource("hitobject-custom-samplebank.osu")) using (var stream = new StreamReader(resStream)) { @@ -324,6 +336,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeHitObjectFileSamples() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + using (var resStream = TestResources.OpenResource("hitobject-file-samples.osu")) using (var stream = new StreamReader(resStream)) { @@ -343,6 +356,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeSliderSamples() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + using (var resStream = TestResources.OpenResource("slider-samples.osu")) using (var stream = new StreamReader(resStream)) { @@ -386,6 +400,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeHitObjectNullAdditionBank() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + using (var resStream = TestResources.OpenResource("hitobject-no-addition-bank.osu")) using (var stream = new StreamReader(resStream)) { diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index 2288d04493..971518909d 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs @@ -19,6 +19,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeStoryboardEvents() { var decoder = new LegacyStoryboardDecoder(); + using (var resStream = TestResources.OpenResource("Himeringo - Yotsuya-san ni Yoroshiku (RLC) [Winber1's Extreme].osu")) using (var stream = new StreamReader(resStream)) { @@ -91,6 +92,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeVariableWithSuffix() { var decoder = new LegacyStoryboardDecoder(); + using (var resStream = TestResources.OpenResource("variable-with-suffix.osb")) using (var stream = new StreamReader(resStream)) { diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs index a867ddebae..39b7735a55 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs @@ -151,6 +151,7 @@ namespace osu.Game.Tests.Beatmaps.Formats using (var sr = new StreamReader(stream)) { var legacyDecoded = new LegacyBeatmapDecoder { ApplyOffsets = false }.Decode(sr); + using (var ms = new MemoryStream()) using (var sw = new StreamWriter(ms)) using (var sr2 = new StreamReader(ms)) diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs index 17197aff27..37e0565df0 100644 --- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs @@ -75,6 +75,7 @@ namespace osu.Game.Tests.Beatmaps.IO using (var osz = TestResources.GetTestBeatmapStream()) { var reader = new ZipArchiveReader(osz); + using (var stream = new StreamReader( reader.GetStream("Soleily - Renatus (Deif) [Platter].osu"))) { diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 2a97519e21..24ef9e4535 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -18,6 +18,7 @@ namespace osu.Game.Tests.Skins public void TestDecodeSkinColours(bool hasColours) { var decoder = new LegacySkinDecoder(); + using (var resStream = TestResources.OpenResource(hasColours ? "skin.ini" : "skin-empty.ini")) using (var stream = new StreamReader(resStream)) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs index c99a4bb89b..b5a7240839 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs @@ -124,12 +124,15 @@ namespace osu.Game.Tests.Visual.Gameplay case ScrollingDirection.Up: obj.Anchor = Anchor.TopCentre; break; + case ScrollingDirection.Down: obj.Anchor = Anchor.BottomCentre; break; + case ScrollingDirection.Left: obj.Anchor = Anchor.CentreLeft; break; + case ScrollingDirection.Right: obj.Anchor = Anchor.CentreRight; break; @@ -184,6 +187,7 @@ namespace osu.Game.Tests.Visual.Gameplay RelativeSizeAxes = Axes.X; Height = 2; break; + case ScrollingDirection.Left: case ScrollingDirection.Right: RelativeSizeAxes = Axes.Y; diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapInfoWedge.cs index f3e44bd808..36a7eba37f 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapInfoWedge.cs @@ -83,15 +83,19 @@ namespace osu.Game.Tests.Visual.SongSelect case OsuRuleset _: testInfoLabels(5); break; + case TaikoRuleset _: testInfoLabels(5); break; + case CatchRuleset _: testInfoLabels(5); break; + case ManiaRuleset _: testInfoLabels(4); break; + default: testInfoLabels(2); break; diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseNotificationOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseNotificationOverlay.cs index 4819597d22..faf80d22ff 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseNotificationOverlay.cs @@ -86,12 +86,15 @@ namespace osu.Game.Tests.Visual.UserInterface case 0: sendHelloNotification(); break; + case 1: sendAmazingNotification(); break; + case 2: sendUploadProgress(); break; + case 3: sendDownloadProgress(); break; diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs index 3adfcb85ea..d0db7765c2 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs @@ -32,9 +32,11 @@ namespace osu.Game.Beatmaps.Drawables case BeatmapSetCoverType.Cover: resource = set.OnlineInfo.Covers.Cover; break; + case BeatmapSetCoverType.Card: resource = set.OnlineInfo.Covers.Card; break; + case BeatmapSetCoverType.List: resource = set.OnlineInfo.Covers.List; break; diff --git a/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs b/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs index f1607ad749..26ffcca1ec 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs @@ -63,15 +63,20 @@ namespace osu.Game.Beatmaps.Drawables { case DifficultyRating.Easy: return palette.Green; + default: case DifficultyRating.Normal: return palette.Blue; + case DifficultyRating.Hard: return palette.Yellow; + case DifficultyRating.Insane: return palette.Pink; + case DifficultyRating.Expert: return palette.Purple; + case DifficultyRating.ExpertPlus: return palette.Gray0; } diff --git a/osu.Game/Beatmaps/WorkingBeatmap_VirtualBeatmapTrack.cs b/osu.Game/Beatmaps/WorkingBeatmap_VirtualBeatmapTrack.cs index cb1be82c69..1e237a2b53 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap_VirtualBeatmapTrack.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap_VirtualBeatmapTrack.cs @@ -26,9 +26,11 @@ namespace osu.Game.Beatmaps case null: Length = excess_length; break; + case IHasEndTime endTime: Length = endTime.EndTime + excess_length; break; + default: Length = lastObject.StartTime + excess_length; break; diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index c6ee91f961..3f84f77081 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -84,6 +84,7 @@ namespace osu.Game.Graphics.Containers case GlobalAction.Back: State = Visibility.Hidden; return true; + case GlobalAction.Select: return true; } @@ -107,6 +108,7 @@ namespace osu.Game.Graphics.Containers State = Visibility.Hidden; break; + case Visibility.Hidden: if (PlaySamplesOnStateChange) samplePopOut?.Play(); if (BlockScreenWideMouse) osuGame?.RemoveBlockingOverlay(this); diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 712dc4c444..192cb917d5 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -20,12 +20,14 @@ namespace osu.Game.Graphics { default: throw new ArgumentException(@"Invalid hex string length!"); + case 3: return new Color4( (byte)(Convert.ToByte(hex.Substring(0, 1), 16) * 17), (byte)(Convert.ToByte(hex.Substring(1, 1), 16) * 17), (byte)(Convert.ToByte(hex.Substring(2, 1), 16) * 17), 255); + case 6: return new Color4( Convert.ToByte(hex.Substring(0, 2), 16), diff --git a/osu.Game/Graphics/OsuFont.cs b/osu.Game/Graphics/OsuFont.cs index 26112430f6..841e53ffbb 100644 --- a/osu.Game/Graphics/OsuFont.cs +++ b/osu.Game/Graphics/OsuFont.cs @@ -42,8 +42,10 @@ namespace osu.Game.Graphics { case Typeface.Exo: return "Exo2.0"; + case Typeface.FontAwesome: return "FontAwesome"; + case Typeface.Venera: return "Venera"; } diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index a2ac71de93..24a98e6dc9 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -104,9 +104,11 @@ namespace osu.Game.Graphics case ScreenshotFormat.Png: image.SaveAsPng(stream); break; + case ScreenshotFormat.Jpg: image.SaveAsJpeg(stream); break; + default: throw new ArgumentOutOfRangeException(nameof(screenshotFormat)); } diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index 9b5755ea8b..32994be78a 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -88,9 +88,11 @@ namespace osu.Game.Graphics.UserInterface case MenuItemType.Standard: text.Colour = Color4.White; break; + case MenuItemType.Destructive: text.Colour = Color4.Red; break; + case MenuItemType.Highlighted: text.Colour = OsuColour.FromHex(@"ffcc22"); break; diff --git a/osu.Game/Input/IdleTracker.cs b/osu.Game/Input/IdleTracker.cs index 91e2456ef7..cbc446a126 100644 --- a/osu.Game/Input/IdleTracker.cs +++ b/osu.Game/Input/IdleTracker.cs @@ -62,6 +62,7 @@ namespace osu.Game.Input case MouseUpEvent _: case MouseMoveEvent _: return updateLastInteractionTime(); + default: return base.Handle(e); } diff --git a/osu.Game/Online/API/Requests/GetRoomsRequest.cs b/osu.Game/Online/API/Requests/GetRoomsRequest.cs index d7c66707e4..8f1497ef33 100644 --- a/osu.Game/Online/API/Requests/GetRoomsRequest.cs +++ b/osu.Game/Online/API/Requests/GetRoomsRequest.cs @@ -26,12 +26,15 @@ namespace osu.Game.Online.API.Requests { case PrimaryFilter.Open: break; + case PrimaryFilter.Owned: target += "/owned"; break; + case PrimaryFilter.Participated: target += "/participated"; break; + case PrimaryFilter.RecentlyEnded: target += "/ended"; break; diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs index e8e44c206e..0169401d2d 100644 --- a/osu.Game/Overlays/AccountCreationOverlay.cs +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -103,8 +103,10 @@ namespace osu.Game.Overlays case APIState.Offline: case APIState.Failing: break; + case APIState.Connecting: break; + case APIState.Online: State = Visibility.Hidden; break; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 667869e310..e6fca84731 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -123,6 +123,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, }; break; + case DownloadState.Downloaded: textSprites.Children = new Drawable[] { @@ -133,9 +134,11 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, }; break; + case DownloadState.LocallyAvailable: this.FadeOut(200); break; + case DownloadState.NotDownloaded: textSprites.Children = new Drawable[] { diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 95cf9e9d04..7ea0748585 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -225,11 +225,13 @@ namespace osu.Game.Overlays.BeatmapSet RelativeSizeAxes = Axes.Y }; break; + case DownloadState.Downloading: case DownloadState.Downloaded: // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); break; + default: downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); if (BeatmapSet.Value.OnlineInfo.HasVideo) diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index f8a8038878..a47a494a42 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -58,6 +58,7 @@ namespace osu.Game.Overlays.Chat.Tabs { default: return new ChannelTabItem(value) { OnRequestClose = tabCloseRequested }; + case ChannelType.PM: return new PrivateChannelTabItem(value) { OnRequestClose = tabCloseRequested }; } diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 7fc145d635..26e2bb1ae4 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -85,9 +85,11 @@ namespace osu.Game.Overlays.Direct case DownloadState.Downloaded: shakeContainer.Shake(); break; + case DownloadState.LocallyAvailable: game.PresentBeatmap(BeatmapSet.Value); break; + default: beatmaps.Download(BeatmapSet.Value, noVideo); break; @@ -110,9 +112,11 @@ namespace osu.Game.Overlays.Direct icon.MoveToX(0, 500, Easing.InOutExpo); checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo); break; + case DownloadState.Downloaded: background.FadeColour(colours.Yellow, 500, Easing.InOutExpo); break; + case DownloadState.LocallyAvailable: background.FadeColour(colours.Green, 500, Easing.InOutExpo); icon.MoveToX(-8, 500, Easing.InOutExpo); diff --git a/osu.Game/Overlays/Direct/DownloadProgressBar.cs b/osu.Game/Overlays/Direct/DownloadProgressBar.cs index 9c2b1e5b63..57500b3531 100644 --- a/osu.Game/Overlays/Direct/DownloadProgressBar.cs +++ b/osu.Game/Overlays/Direct/DownloadProgressBar.cs @@ -43,10 +43,12 @@ namespace osu.Game.Overlays.Direct progressBar.Current.Value = 0; progressBar.FadeOut(500); break; + case DownloadState.Downloading: progressBar.FadeIn(400, Easing.OutQuint); progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); break; + case DownloadState.Downloaded: progressBar.FadeIn(400, Easing.OutQuint); progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); @@ -54,6 +56,7 @@ namespace osu.Game.Overlays.Direct progressBar.Current.Value = 1; progressBar.FillColour = colours.Yellow; break; + case DownloadState.LocallyAvailable: progressBar.FadeOut(500); break; diff --git a/osu.Game/Overlays/MainSettings.cs b/osu.Game/Overlays/MainSettings.cs index 61dd51d16f..39bfdfd4d6 100644 --- a/osu.Game/Overlays/MainSettings.cs +++ b/osu.Game/Overlays/MainSettings.cs @@ -55,6 +55,7 @@ namespace osu.Game.Overlays SectionsContainer.FadeOut(300, Easing.OutQuint); ContentContainer.MoveToX(-WIDTH, 500, Easing.OutQuint); break; + case Visibility.Hidden: Background.FadeTo(0.6f, 500, Easing.OutQuint); Sidebar?.FadeColour(Color4.White, 300, Easing.OutQuint); diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index 431ae98c2c..f1ae5d64f5 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -156,11 +156,13 @@ namespace osu.Game.Overlays.MedalSplash case DisplayState.None: medalContainer.ScaleTo(0); break; + case DisplayState.Icon: medalContainer .FadeIn(duration) .ScaleTo(1, duration, Easing.OutElastic); break; + case DisplayState.MedalUnlocked: medalContainer .FadeTo(1) @@ -170,6 +172,7 @@ namespace osu.Game.Overlays.MedalSplash this.MoveToY(MedalOverlay.DISC_SIZE / 2 - 30, duration, Easing.OutExpo); unlocked.FadeInFromZero(duration); break; + case DisplayState.Full: medalContainer .FadeTo(1) diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index 75e70b18ea..857a0bda9e 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -54,11 +54,13 @@ namespace osu.Game.Overlays.Notifications Light.Pulsate = false; progressBar.Active = false; break; + case ProgressNotificationState.Active: Light.Colour = colourActive; Light.Pulsate = true; progressBar.Active = true; break; + case ProgressNotificationState.Cancelled: Light.Colour = colourCancelled; Light.Pulsate = false; @@ -145,6 +147,7 @@ namespace osu.Game.Overlays.Notifications case ProgressNotificationState.Cancelled: base.Close(); break; + case ProgressNotificationState.Active: case ProgressNotificationState.Queued: if (CancelRequested?.Invoke() != false) diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 5e45fbf081..5af7d5aea5 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -188,6 +188,7 @@ namespace osu.Game.Overlays optionCount = 1; if (val) selectedOption = 0; break; + case Enum _: var values = Enum.GetValues(description.RawValue.GetType()); optionCount = values.Length; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 95a18ccfa9..470bed2854 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -54,6 +54,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks default: drawableScores = scores.Select(score => new DrawablePerformanceScore(score, includeWeight ? Math.Pow(0.95, ItemsContainer.Count) : (double?)null)); break; + case ScoreType.Recent: drawableScores = scores.Select(score => new DrawableTotalScore(score)); break; diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 078c01ce92..8ac13060b0 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -87,6 +87,7 @@ namespace osu.Game.Overlays.Settings.Sections.General } }; break; + case APIState.Failing: case APIState.Connecting: LinkFlowContainer linkFlow; @@ -112,6 +113,7 @@ namespace osu.Game.Overlays.Settings.Sections.General linkFlow.AddLink("cancel", api.Logout, string.Empty); break; + case APIState.Online: Children = new Drawable[] { @@ -160,14 +162,17 @@ namespace osu.Game.Overlays.Settings.Sections.General api.LocalUser.Value.Status.Value = new UserStatusOnline(); dropdown.StatusColour = colours.Green; break; + case UserAction.DoNotDisturb: api.LocalUser.Value.Status.Value = new UserStatusDoNotDisturb(); dropdown.StatusColour = colours.Red; break; + case UserAction.AppearOffline: api.LocalUser.Value.Status.Value = new UserStatusOffline(); dropdown.StatusColour = colours.Gray7; break; + case UserAction.SignOut: api.Logout(); break; diff --git a/osu.Game/Overlays/Settings/Sidebar.cs b/osu.Game/Overlays/Settings/Sidebar.cs index 969686e36d..3c18627f23 100644 --- a/osu.Game/Overlays/Settings/Sidebar.cs +++ b/osu.Game/Overlays/Settings/Sidebar.cs @@ -102,6 +102,7 @@ namespace osu.Game.Overlays.Settings default: this.ResizeTo(new Vector2(DEFAULT_WIDTH, Height), 500, Easing.OutQuint); break; + case ExpandedState.Expanded: this.ResizeTo(new Vector2(EXPANDED_WIDTH, Height), 500, Easing.OutQuint); break; diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 356ffa5180..77def1adcf 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -58,6 +58,7 @@ namespace osu.Game.Overlays.Toolbar Text = @"Guest"; avatar.User = new User(); break; + case APIState.Online: Text = api.LocalUser.Value.Username; avatar.User = api.LocalUser.Value; diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index e2e480ef53..34b15d958d 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -105,12 +105,14 @@ namespace osu.Game.Overlays else volumeMeterMaster.Decrease(amount, isPrecise); return true; + case GlobalAction.IncreaseVolume: if (State == Visibility.Hidden) Show(); else volumeMeterMaster.Increase(amount, isPrecise); return true; + case GlobalAction.ToggleMute: Show(); muteButton.Current.Value = !muteButton.Current.Value; diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index aad55f8a38..4e71615195 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -117,10 +117,12 @@ namespace osu.Game.Rulesets.Difficulty yield return new ModNoMod(); break; + case 1: yield return currentSet.Single(); break; + default: yield return new MultiMod(currentSet.ToArray()); diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 74aa9ace2d..2dd45660c7 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -122,8 +122,10 @@ namespace osu.Game.Rulesets.Edit { case ScrollEvent _: return false; + case MouseEvent _: return true; + default: return false; } diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 89db954c36..2150726a42 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -89,6 +89,7 @@ namespace osu.Game.Rulesets.Judgements { case HitResult.None: break; + case HitResult.Miss: JudgementBody.ScaleTo(1.6f); JudgementBody.ScaleTo(1, 100, Easing.In); @@ -98,6 +99,7 @@ namespace osu.Game.Rulesets.Judgements this.Delay(600).FadeOut(200); break; + default: ApplyHitAnimations(); break; @@ -113,13 +115,17 @@ namespace osu.Game.Rulesets.Judgements case HitResult.Perfect: case HitResult.Great: return colours.Blue; + case HitResult.Ok: case HitResult.Good: return colours.Green; + case HitResult.Meh: return colours.Yellow; + case HitResult.Miss: return colours.Red; + default: return Color4.White; } diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 62407907c1..a5f96087c0 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -73,10 +73,12 @@ namespace osu.Game.Rulesets.Mods pitch.PitchAdjust /= lastAdjust; pitch.PitchAdjust *= adjust; break; + case IHasTempoAdjust tempo: tempo.TempoAdjust /= lastAdjust; tempo.TempoAdjust *= adjust; break; + default: clock.Rate /= lastAdjust; clock.Rate *= adjust; diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index c5b7686da6..6fb8425a33 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -77,6 +77,7 @@ namespace osu.Game.Rulesets.Objects case HitResult.Perfect: case HitResult.Ok: return false; + default: return true; } @@ -126,16 +127,22 @@ namespace osu.Game.Rulesets.Objects { case HitResult.Perfect: return Perfect / 2; + case HitResult.Great: return Great / 2; + case HitResult.Good: return Good / 2; + case HitResult.Ok: return Ok / 2; + case HitResult.Meh: return Meh / 2; + case HitResult.Miss: return Miss / 2; + default: throw new ArgumentException(nameof(result)); } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 0fddb19a6c..034ebbeb3e 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -313,9 +313,11 @@ namespace osu.Game.Rulesets.Scoring { case HitResult.None: break; + case HitResult.Miss: Combo.Value = 0; break; + default: Combo.Value++; break; @@ -373,6 +375,7 @@ namespace osu.Game.Rulesets.Scoring default: case ScoringMode.Standardised: return max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo.Value / maxHighestCombo) + bonusScore; + case ScoringMode.Classic: // should emulate osu-stable's scoring as closely as we can (https://osu.ppy.sh/help/wiki/Score/ScoreV1) return bonusScore + baseScore * (1 + Math.Max(0, HighestCombo.Value - 1) / 25); diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index f9f6b5cc2f..86feea09a8 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -76,18 +76,22 @@ namespace osu.Game.Rulesets.UI backgroundColour = colours.Yellow; highlightedColour = colours.YellowLight; break; + case ModType.DifficultyReduction: backgroundColour = colours.Green; highlightedColour = colours.GreenLight; break; + case ModType.Automation: backgroundColour = colours.Blue; highlightedColour = colours.BlueLight; break; + case ModType.Conversion: backgroundColour = colours.Purple; highlightedColour = colours.PurpleLight; break; + case ModType.Fun: backgroundColour = colours.Pink; highlightedColour = colours.PinkLight; diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index b4271085f5..e25c3bd0e7 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -105,6 +105,7 @@ namespace osu.Game.Rulesets.UI return false; break; + case MouseUpEvent mouseUp: if (!CurrentState.Mouse.IsPressed(mouseUp.Button)) return false; diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 3b368652f2..a0bfb356bc 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -92,9 +92,11 @@ namespace osu.Game.Rulesets.UI.Scrolling case ScrollVisualisationMethod.Sequential: scrollingInfo.Algorithm = new SequentialScrollAlgorithm(controlPoints); break; + case ScrollVisualisationMethod.Overlapping: scrollingInfo.Algorithm = new OverlappingScrollAlgorithm(controlPoints); break; + case ScrollVisualisationMethod.Constant: scrollingInfo.Algorithm = new ConstantScrollAlgorithm(); break; @@ -159,6 +161,7 @@ namespace osu.Game.Rulesets.UI.Scrolling case GlobalAction.IncreaseScrollSpeed: this.TransformBindableTo(TimeRange, TimeRange.Value - time_span_step, 200, Easing.OutQuint); return true; + case GlobalAction.DecreaseScrollSpeed: this.TransformBindableTo(TimeRange, TimeRange.Value + time_span_step, 200, Easing.OutQuint); return true; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index ed3534fb36..069e2d1a0b 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -72,6 +72,7 @@ namespace osu.Game.Rulesets.UI.Scrolling case ScrollingDirection.Down: scrollLength = DrawSize.Y; break; + default: scrollLength = DrawSize.X; break; @@ -97,6 +98,7 @@ namespace osu.Game.Rulesets.UI.Scrolling case ScrollingDirection.Down: hitObject.Height = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, endTime.EndTime, timeRange.Value, scrollLength); break; + case ScrollingDirection.Left: case ScrollingDirection.Right: hitObject.Width = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, endTime.EndTime, timeRange.Value, scrollLength); @@ -129,12 +131,15 @@ namespace osu.Game.Rulesets.UI.Scrolling case ScrollingDirection.Up: hitObject.Y = scrollingInfo.Algorithm.PositionAt(hitObject.HitObject.StartTime, currentTime, timeRange.Value, scrollLength); break; + case ScrollingDirection.Down: hitObject.Y = -scrollingInfo.Algorithm.PositionAt(hitObject.HitObject.StartTime, currentTime, timeRange.Value, scrollLength); break; + case ScrollingDirection.Left: hitObject.X = scrollingInfo.Algorithm.PositionAt(hitObject.HitObject.StartTime, currentTime, timeRange.Value, scrollLength); break; + case ScrollingDirection.Right: hitObject.X = -scrollingInfo.Algorithm.PositionAt(hitObject.HitObject.StartTime, currentTime, timeRange.Value, scrollLength); break; diff --git a/osu.Game/Scoring/Legacy/LegacyScoreInfo.cs b/osu.Game/Scoring/Legacy/LegacyScoreInfo.cs index df80f848e3..e66f93ec8d 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreInfo.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreInfo.cs @@ -41,6 +41,7 @@ namespace osu.Game.Scoring.Legacy case 3: Statistics[HitResult.Great] = value; break; + case 2: Statistics[HitResult.Perfect] = value; break; @@ -81,6 +82,7 @@ namespace osu.Game.Scoring.Legacy case 1: Statistics[HitResult.Good] = value; break; + case 3: Statistics[HitResult.Ok] = value; break; diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 1f13797497..74b1e3c6cb 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -236,10 +236,12 @@ namespace osu.Game.Screens.Edit.Compose.Components beatDivisor.Next(); OnUserChange(Current.Value); return true; + case Key.Left: beatDivisor.Previous(); OnUserChange(Current.Value); return true; + default: return false; } @@ -307,18 +309,25 @@ namespace osu.Game.Screens.Edit.Compose.Components { case 2: return colours.BlueLight; + case 4: return colours.Blue; + case 8: return colours.BlueDarker; + case 16: return colours.PurpleDark; + case 3: return colours.YellowLight; + case 6: return colours.Yellow; + case 12: return colours.YellowDarker; + default: return Color4.White; } diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index 794fc093d3..cc2a0c6c46 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -260,6 +260,7 @@ namespace osu.Game.Screens.Menu box.ScaleTo(new Vector2(0, 1), 500, Easing.OutExpo); this.FadeOut(500); break; + case 1: box.ScaleTo(new Vector2(0, 1), 400, Easing.InSine); this.FadeOut(800); @@ -267,11 +268,13 @@ namespace osu.Game.Screens.Menu } break; + case ButtonState.Expanded: const int expand_duration = 500; box.ScaleTo(new Vector2(1, 1), expand_duration, Easing.OutExpo); this.FadeIn(expand_duration / 6f); break; + case ButtonState.Exploded: const int explode_duration = 200; box.ScaleTo(new Vector2(2, 1), explode_duration, Easing.OutExpo); @@ -294,10 +297,12 @@ namespace osu.Game.Screens.Menu case ButtonSystemState.Initial: State = ButtonState.Contracted; break; + case ButtonSystemState.EnteringMode: ContractStyle = 1; State = ButtonState.Contracted; break; + default: if (value == VisibleState) State = ButtonState.Expanded; diff --git a/osu.Game/Screens/Menu/ButtonArea.cs b/osu.Game/Screens/Menu/ButtonArea.cs index d6e1aef63c..b25efe53e1 100644 --- a/osu.Game/Screens/Menu/ButtonArea.cs +++ b/osu.Game/Screens/Menu/ButtonArea.cs @@ -57,6 +57,7 @@ namespace osu.Game.Screens.Menu case ButtonSystemState.EnteringMode: State = Visibility.Hidden; break; + case ButtonSystemState.TopLevel: case ButtonSystemState.Play: State = Visibility.Visible; @@ -109,6 +110,7 @@ namespace osu.Game.Screens.Menu case ButtonAreaBackgroundState.Flat: this.ScaleTo(new Vector2(2, 0), 300, Easing.InSine); break; + case ButtonAreaBackgroundState.Normal: this.ScaleTo(Vector2.One, 400, Easing.OutQuint); break; @@ -127,6 +129,7 @@ namespace osu.Game.Screens.Menu default: State = ButtonAreaBackgroundState.Normal; break; + case ButtonSystemState.Initial: case ButtonSystemState.Exit: case ButtonSystemState.EnteringMode: diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 5403f7c702..21fc53be6e 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -79,6 +79,7 @@ namespace osu.Game.Screens.Menu case ButtonSystemState.Exit: Background.FadeColour(Color4.White, 500, Easing.OutSine); break; + default: Background.FadeColour(OsuColour.Gray(0.8f), 500, Easing.OutSine); break; diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 2fac8de799..c4425fd5fe 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -221,6 +221,7 @@ namespace osu.Game.Screens.Play else selectionIndex--; return true; + case Key.Down: if (selectionIndex == -1 || selectionIndex == InternalButtons.Count - 1) selectionIndex = 0; @@ -240,6 +241,7 @@ namespace osu.Game.Screens.Play case GlobalAction.Back: BackAction.Invoke(); return true; + case GlobalAction.Select: SelectAction.Invoke(); return true; diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouse.cs index 13dbe40a8b..95fa58e5c0 100644 --- a/osu.Game/Screens/Play/KeyCounterMouse.cs +++ b/osu.Game/Screens/Play/KeyCounterMouse.cs @@ -25,8 +25,10 @@ namespace osu.Game.Screens.Play { default: return button.ToString(); + case MouseButton.Left: return @"M1"; + case MouseButton.Right: return @"M2"; } diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 78ed742bfa..d2d56f8c40 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -174,6 +174,7 @@ namespace osu.Game.Screens.Play using (BeginDelayedSequence(1000)) scheduledHide = Schedule(() => State = Visibility.Hidden); break; + case Visibility.Hidden: this.FadeOut(1000, Easing.OutExpo); break; diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 8e7ea8f964..5c334b126c 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -38,10 +38,13 @@ namespace osu.Game.Screens.Select.Carousel default: case SortMode.Artist: return string.Compare(BeatmapSet.Metadata.Artist, otherSet.BeatmapSet.Metadata.Artist, StringComparison.InvariantCultureIgnoreCase); + case SortMode.Title: return string.Compare(BeatmapSet.Metadata.Title, otherSet.BeatmapSet.Metadata.Title, StringComparison.InvariantCultureIgnoreCase); + case SortMode.Author: return string.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username, StringComparison.InvariantCultureIgnoreCase); + case SortMode.Difficulty: return BeatmapSet.MaxStarDifficulty.CompareTo(otherSet.BeatmapSet.MaxStarDifficulty); } diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs index 5d8f4f0ec6..6ebd2d41cc 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs @@ -66,6 +66,7 @@ namespace osu.Game.Screens.Select.Carousel case CarouselItemState.NotSelected: InternalChildren.ForEach(c => c.State.Value = CarouselItemState.Collapsed); break; + case CarouselItemState.Selected: InternalChildren.ForEach(c => { diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs b/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs index 67e8282b76..045c682dc3 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs @@ -69,6 +69,7 @@ namespace osu.Game.Screens.Select.Carousel case CarouselItemState.Selected: updateSelected(item); break; + case CarouselItemState.NotSelected: case CarouselItemState.Collapsed: attemptSelection(); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index 3c1b7cc831..9a07852e02 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -106,6 +106,7 @@ namespace osu.Game.Screens.Select.Carousel case CarouselItemState.NotSelected: Deselected(); break; + case CarouselItemState.Selected: Selected(); break; diff --git a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs index 0bcf1b1816..02f7f73399 100644 --- a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs +++ b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs @@ -108,12 +108,14 @@ namespace osu.Game.Screens.Tournament speedTo(1000f, 200); tracker.FadeOut(100); break; + case ScrollState.Stopping: speedTo(0f, 2000); tracker.FadeIn(200); delayedStateChangeDelegate = Scheduler.AddDelayed(() => scrollState = ScrollState.Stopped, 2300); break; + case ScrollState.Stopped: // Find closest to center if (!Children.Any()) @@ -155,6 +157,7 @@ namespace osu.Game.Screens.Tournament delayedStateChangeDelegate = Scheduler.AddDelayed(() => scrollState = ScrollState.Idle, 10000); break; + case ScrollState.Idle: resetSelected(); diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 461dfed589..09f7e09961 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -26,9 +26,11 @@ namespace osu.Game.Skinning case @"Name": skin.SkinInfo.Name = pair.Value; break; + case @"Author": skin.SkinInfo.Creator = pair.Value; break; + case @"CursorExpand": skin.CursorExpand = pair.Value != "0"; break; @@ -42,6 +44,7 @@ namespace osu.Game.Skinning case "HitCirclePrefix": skin.HitCircleFont = pair.Value; break; + case "HitCircleOverlap": skin.HitCircleOverlap = int.Parse(pair.Value); break; diff --git a/osu.Game/Tests/Visual/ScrollingTestContainer.cs b/osu.Game/Tests/Visual/ScrollingTestContainer.cs index f2e03208fd..bdad3d278c 100644 --- a/osu.Game/Tests/Visual/ScrollingTestContainer.cs +++ b/osu.Game/Tests/Visual/ScrollingTestContainer.cs @@ -74,9 +74,11 @@ namespace osu.Game.Tests.Visual case ScrollVisualisationMethod.Constant: implementation = new ConstantScrollAlgorithm(); break; + case ScrollVisualisationMethod.Overlapping: implementation = new OverlappingScrollAlgorithm(ControlPoints); break; + case ScrollVisualisationMethod.Sequential: implementation = new SequentialScrollAlgorithm(ControlPoints); break; From d8af5e1c5a01df26271c5d9fa50f080ac1660514 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Apr 2019 11:56:22 +0900 Subject: [PATCH 0444/5608] Update in-line with drawnode changes --- .../UI/Cursor/CursorTrail.cs | 76 ++++++++++--------- osu.Game/Graphics/Backgrounds/Triangles.cs | 62 ++++++++------- osu.Game/Rulesets/Mods/ModFlashlight.cs | 61 ++++++++------- osu.Game/Screens/Menu/LogoVisualisation.cs | 61 ++++++++------- 4 files changed, 139 insertions(+), 121 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 03dbf7ac63..4aec7c634e 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -43,22 +43,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly InputResampler resampler = new InputResampler(); - protected override DrawNode CreateDrawNode() => new TrailDrawNode(); - - protected override void ApplyDrawNode(DrawNode node) - { - base.ApplyDrawNode(node); - - TrailDrawNode tNode = (TrailDrawNode)node; - tNode.Shader = shader; - tNode.Texture = texture; - tNode.Size = size; - tNode.Time = time; - - for (int i = 0; i < parts.Length; ++i) - if (parts[i].InvalidationID > tNode.Parts[i].InvalidationID) - tNode.Parts[i] = parts[i]; - } + protected override DrawNode CreateDrawNode() => new TrailDrawNode(this); public CursorTrail() { @@ -167,33 +152,52 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private class TrailDrawNode : DrawNode { - public IShader Shader; - public Texture Texture; + protected new CursorTrail Source => (CursorTrail)base.Source; - public float Time; + private IShader shader; + private Texture texture; - public readonly TrailPart[] Parts = new TrailPart[max_sprites]; - public Vector2 Size; + private float time; + + private readonly TrailPart[] parts = new TrailPart[max_sprites]; + private Vector2 size; private readonly VertexBuffer vertexBuffer = new QuadVertexBuffer(max_sprites, BufferUsageHint.DynamicDraw); - public TrailDrawNode() + public TrailDrawNode(CursorTrail source) + : base(source) { for (int i = 0; i < max_sprites; i++) { - Parts[i].InvalidationID = 0; - Parts[i].WasUpdated = false; + parts[i].InvalidationID = 0; + parts[i].WasUpdated = false; + } + } + + public override void ApplyState() + { + base.ApplyState(); + + shader = Source.shader; + texture = Source.texture; + size = Source.size; + time = Source.time; + + for (int i = 0; i < Source.parts.Length; ++i) + { + if (Source.parts[i].InvalidationID > parts[i].InvalidationID) + parts[i] = Source.parts[i]; } } public override void Draw(Action vertexAction) { - Shader.GetUniform("g_FadeClock").UpdateValue(ref Time); + shader.GetUniform("g_FadeClock").UpdateValue(ref time); int updateStart = -1, updateEnd = 0; - for (int i = 0; i < Parts.Length; ++i) + for (int i = 0; i < parts.Length; ++i) { - if (Parts[i].WasUpdated) + if (parts[i].WasUpdated) { if (updateStart == -1) updateStart = i; @@ -202,22 +206,22 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor int start = i * 4; int end = start; - Vector2 pos = Parts[i].Position; - float time = Parts[i].Time; + Vector2 pos = parts[i].Position; + float localTime = parts[i].Time; - Texture.DrawQuad( - new Quad(pos.X - Size.X / 2, pos.Y - Size.Y / 2, Size.X, Size.Y), + texture.DrawQuad( + new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y), DrawColourInfo.Colour, null, v => vertexBuffer.Vertices[end++] = new TexturedTrailVertex { Position = v.Position, TexturePosition = v.TexturePosition, - Time = time + 1, + Time = localTime + 1, Colour = v.Colour, }); - Parts[i].WasUpdated = false; + parts[i].WasUpdated = false; } else if (updateStart != -1) { @@ -232,12 +236,12 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor base.Draw(vertexAction); - Shader.Bind(); + shader.Bind(); - Texture.TextureGL.Bind(); + texture.TextureGL.Bind(); vertexBuffer.Draw(); - Shader.Unbind(); + shader.Unbind(); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index c67d779c37..e2c7693700 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -178,64 +178,68 @@ namespace osu.Game.Graphics.Backgrounds /// The colour. protected virtual Color4 CreateTriangleShade() => Interpolation.ValueAt(RNG.NextSingle(), ColourDark, ColourLight, 0, 1); - protected override DrawNode CreateDrawNode() => new TrianglesDrawNode(); - - protected override void ApplyDrawNode(DrawNode node) - { - base.ApplyDrawNode(node); - - var trianglesNode = (TrianglesDrawNode)node; - - trianglesNode.Shader = shader; - trianglesNode.Texture = texture; - trianglesNode.Size = DrawSize; - - trianglesNode.Parts.Clear(); - trianglesNode.Parts.AddRange(parts); - } + protected override DrawNode CreateDrawNode() => new TrianglesDrawNode(this); private class TrianglesDrawNode : DrawNode { - public IShader Shader; - public Texture Texture; + protected new Triangles Source => (Triangles)base.Source; - public readonly List Parts = new List(); - public Vector2 Size; + private IShader shader; + private Texture texture; + + private readonly List parts = new List(); + private Vector2 size; private readonly LinearBatch vertexBatch = new LinearBatch(100 * 3, 10, PrimitiveType.Triangles); + public TrianglesDrawNode(Triangles source) + : base(source) + { + } + + public override void ApplyState() + { + base.ApplyState(); + + shader = Source.shader; + texture = Source.texture; + size = Source.DrawSize; + + parts.Clear(); + parts.AddRange(Source.parts); + } + public override void Draw(Action vertexAction) { base.Draw(vertexAction); - Shader.Bind(); - Texture.TextureGL.Bind(); + shader.Bind(); + texture.TextureGL.Bind(); Vector2 localInflationAmount = edge_smoothness * DrawInfo.MatrixInverse.ExtractScale().Xy; - foreach (TriangleParticle particle in Parts) + foreach (TriangleParticle particle in parts) { var offset = triangle_size * new Vector2(particle.Scale * 0.5f, particle.Scale * 0.866f); - var size = new Vector2(2 * offset.X, offset.Y); var triangle = new Triangle( - Vector2Extensions.Transform(particle.Position * Size, DrawInfo.Matrix), - Vector2Extensions.Transform(particle.Position * Size + offset, DrawInfo.Matrix), - Vector2Extensions.Transform(particle.Position * Size + new Vector2(-offset.X, offset.Y), DrawInfo.Matrix) + Vector2Extensions.Transform(particle.Position * size, DrawInfo.Matrix), + Vector2Extensions.Transform(particle.Position * size + offset, DrawInfo.Matrix), + Vector2Extensions.Transform(particle.Position * size + new Vector2(-offset.X, offset.Y), DrawInfo.Matrix) ); ColourInfo colourInfo = DrawColourInfo.Colour; colourInfo.ApplyChild(particle.Colour); - Texture.DrawTriangle( + texture.DrawTriangle( triangle, colourInfo, null, vertexBatch.AddAction, - Vector2.Divide(localInflationAmount, size)); + Vector2.Divide(localInflationAmount, new Vector2(2 * offset.X, offset.Y))); } - Shader.Unbind(); + shader.Unbind(); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 0ad99d13ff..31d3720cee 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -64,24 +64,12 @@ namespace osu.Game.Rulesets.Mods internal BindableInt Combo; private IShader shader; - protected override DrawNode CreateDrawNode() => new FlashlightDrawNode(); + protected override DrawNode CreateDrawNode() => new FlashlightDrawNode(this); public override bool RemoveCompletedTransforms => false; public List Breaks; - protected override void ApplyDrawNode(DrawNode node) - { - base.ApplyDrawNode(node); - - var flashNode = (FlashlightDrawNode)node; - - flashNode.Shader = shader; - flashNode.ScreenSpaceDrawQuad = ScreenSpaceDrawQuad; - flashNode.FlashlightPosition = Vector2Extensions.Transform(FlashlightPosition, DrawInfo.Matrix); - flashNode.FlashlightSize = Vector2Extensions.Transform(FlashlightSize, DrawInfo.Matrix); - } - [BackgroundDependencyLoader] private void load(ShaderManager shaderManager) { @@ -136,27 +124,44 @@ namespace osu.Game.Rulesets.Mods Invalidate(Invalidation.DrawNode); } } - } - private class FlashlightDrawNode : DrawNode - { - public IShader Shader; - public Quad ScreenSpaceDrawQuad; - public Vector2 FlashlightPosition; - public Vector2 FlashlightSize; - - public override void Draw(Action vertexAction) + private class FlashlightDrawNode : DrawNode { - base.Draw(vertexAction); + protected new Flashlight Source => (Flashlight)base.Source; - Shader.Bind(); + private IShader shader; + private Quad screenSpaceDrawQuad; + private Vector2 flashlightPosition; + private Vector2 flashlightSize; - Shader.GetUniform("flashlightPos").UpdateValue(ref FlashlightPosition); - Shader.GetUniform("flashlightSize").UpdateValue(ref FlashlightSize); + public FlashlightDrawNode(Flashlight source) + : base(source) + { + } - Texture.WhitePixel.DrawQuad(ScreenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction); + public override void ApplyState() + { + base.ApplyState(); - Shader.Unbind(); + shader = Source.shader; + screenSpaceDrawQuad = Source.ScreenSpaceDrawQuad; + flashlightPosition = Vector2Extensions.Transform(Source.FlashlightPosition, DrawInfo.Matrix); + flashlightSize = Vector2Extensions.Transform(Source.FlashlightSize, DrawInfo.Matrix); + } + + public override void Draw(Action vertexAction) + { + base.Draw(vertexAction); + + shader.Bind(); + + shader.GetUniform("flashlightPos").UpdateValue(ref flashlightPosition); + shader.GetUniform("flashlightSize").UpdateValue(ref flashlightSize); + + Texture.WhitePixel.DrawQuad(screenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction); + + shader.Unbind(); + } } } } diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 8283bf7ea2..9eab588a57 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -150,62 +150,67 @@ namespace osu.Game.Screens.Menu Invalidate(Invalidation.DrawNode, shallPropagate: false); } - protected override DrawNode CreateDrawNode() => new VisualisationDrawNode(); - - protected override void ApplyDrawNode(DrawNode node) - { - base.ApplyDrawNode(node); - - var visNode = (VisualisationDrawNode)node; - - visNode.Shader = shader; - visNode.Texture = texture; - visNode.Size = DrawSize.X; - visNode.Colour = AccentColour; - visNode.AudioData = frequencyAmplitudes; - } + protected override DrawNode CreateDrawNode() => new VisualisationDrawNode(this); private class VisualisationDrawNode : DrawNode { - public IShader Shader; - public Texture Texture; + protected new LogoVisualisation Source => (LogoVisualisation)base.Source; + + private IShader shader; + private Texture texture; //Asuming the logo is a circle, we don't need a second dimension. - public float Size; + private float size; - public Color4 Colour; - public float[] AudioData; + private Color4 colour; + private float[] audioData; private readonly QuadBatch vertexBatch = new QuadBatch(100, 10); + public VisualisationDrawNode(LogoVisualisation source) + : base(source) + { + } + + public override void ApplyState() + { + base.ApplyState(); + + shader = Source.shader; + texture = Source.texture; + size = Source.DrawSize.X; + colour = Source.AccentColour; + audioData = Source.frequencyAmplitudes; + } + public override void Draw(Action vertexAction) { base.Draw(vertexAction); - Shader.Bind(); - Texture.TextureGL.Bind(); + shader.Bind(); + texture.TextureGL.Bind(); Vector2 inflation = DrawInfo.MatrixInverse.ExtractScale().Xy; ColourInfo colourInfo = DrawColourInfo.Colour; - colourInfo.ApplyChild(Colour); + colourInfo.ApplyChild(colour); - if (AudioData != null) + if (audioData != null) { for (int j = 0; j < visualiser_rounds; j++) { for (int i = 0; i < bars_per_visualiser; i++) { - if (AudioData[i] < amplitude_dead_zone) + if (audioData[i] < amplitude_dead_zone) continue; float rotation = MathHelper.DegreesToRadians(i / (float)bars_per_visualiser * 360 + j * 360 / visualiser_rounds); float rotationCos = (float)Math.Cos(rotation); float rotationSin = (float)Math.Sin(rotation); //taking the cos and sin to the 0..1 range - var barPosition = new Vector2(rotationCos / 2 + 0.5f, rotationSin / 2 + 0.5f) * Size; + var barPosition = new Vector2(rotationCos / 2 + 0.5f, rotationSin / 2 + 0.5f) * size; - var barSize = new Vector2(Size * (float)Math.Sqrt(2 * (1 - Math.Cos(MathHelper.DegreesToRadians(360f / bars_per_visualiser)))) / 2f, bar_length * AudioData[i]); + var barSize = new Vector2(size * (float)Math.Sqrt(2 * (1 - Math.Cos(MathHelper.DegreesToRadians(360f / bars_per_visualiser)))) / 2f, bar_length * audioData[i]); //The distance between the position and the sides of the bar. var bottomOffset = new Vector2(-rotationSin * barSize.X / 2, rotationCos * barSize.X / 2); //The distance between the bottom side of the bar and the top side. @@ -218,7 +223,7 @@ namespace osu.Game.Screens.Menu Vector2Extensions.Transform(barPosition + bottomOffset + amplitudeOffset, DrawInfo.Matrix) ); - Texture.DrawQuad( + texture.DrawQuad( rectangle, colourInfo, null, @@ -229,7 +234,7 @@ namespace osu.Game.Screens.Menu } } - Shader.Unbind(); + shader.Unbind(); } protected override void Dispose(bool isDisposing) From a56e29347fdcdad1618c139b6fe47f1bed276f32 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Apr 2019 14:51:28 +0900 Subject: [PATCH 0445/5608] Adjust namespaces --- osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs | 1 + osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs | 2 +- .../Objects/Drawables/DrawableHoldNoteTick.cs | 1 + osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs | 2 +- osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs | 1 + osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs | 1 + osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs | 1 + osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs | 1 + osu.Game.Rulesets.Mania/UI/HitExplosion.cs | 1 + .../Objects/Drawables/Connections/FollowPoint.cs | 1 + osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs | 1 + .../Objects/Drawables/Pieces/SpinnerBackground.cs | 1 + osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs | 1 + osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs | 1 + osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs | 1 + osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs | 1 + osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 1 + osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 1 + osu.Game/Graphics/Containers/ConstrainedIconContainer.cs | 1 + osu.Game/Graphics/Containers/WaveContainer.cs | 1 + osu.Game/Graphics/Cursor/OsuTooltipContainer.cs | 2 +- osu.Game/Graphics/UserInterface/DialogButton.cs | 1 + osu.Game/Graphics/UserInterface/Nub.cs | 1 + osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs | 1 + osu.Game/Graphics/UserInterface/OsuContextMenu.cs | 2 +- osu.Game/Graphics/UserInterface/TwoLayerButton.cs | 1 + osu.Game/Online/Leaderboards/LeaderboardScore.cs | 1 + osu.Game/Overlays/AccountCreationOverlay.cs | 1 + osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 1 + osu.Game/Overlays/BeatmapSet/Header.cs | 1 + osu.Game/Overlays/BeatmapSet/Info.cs | 1 + osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs | 1 + osu.Game/Overlays/BeatmapSetOverlay.cs | 1 + osu.Game/Overlays/Chat/ChatLine.cs | 1 + osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs | 1 + osu.Game/Overlays/Dialog/PopupDialog.cs | 1 + osu.Game/Overlays/Direct/DirectPanel.cs | 1 + osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 1 + osu.Game/Overlays/MedalOverlay.cs | 1 + osu.Game/Overlays/Music/CollectionsDropdown.cs | 2 +- osu.Game/Overlays/Music/PlaylistOverlay.cs | 1 + osu.Game/Overlays/MusicController.cs | 1 + osu.Game/Overlays/Notifications/Notification.cs | 1 + osu.Game/Overlays/OnScreenDisplay.cs | 1 + osu.Game/Overlays/Profile/ProfileHeader.cs | 1 + osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs | 1 + osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs | 1 + osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs | 1 + osu.Game/Overlays/Settings/SettingsItem.cs | 1 + osu.Game/Overlays/Social/SocialPanel.cs | 2 +- osu.Game/Overlays/Toolbar/ToolbarButton.cs | 1 + osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs | 2 +- osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs | 1 + osu.Game/Overlays/Toolbar/ToolbarUserButton.cs | 2 +- osu.Game/Overlays/UserProfileOverlay.cs | 2 +- .../Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs | 1 + osu.Game/Screens/Menu/Button.cs | 1 + osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs | 1 + osu.Game/Screens/Play/GameplayMenuOverlay.cs | 1 + osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs | 1 + osu.Game/Screens/Ranking/ResultModeButton.cs | 1 + osu.Game/Screens/Ranking/Results.cs | 1 + osu.Game/Screens/Ranking/ResultsPage.cs | 1 + osu.Game/Screens/Select/BeatmapInfoWedge.cs | 1 + osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs | 1 + osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs | 1 + osu.Game/Users/UserPanel.cs | 1 + 67 files changed, 67 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 0dc3f73404..625e857156 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs index 2e18c5f2ad..b9b6d5b924 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs @@ -3,7 +3,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index f2be8d614c..9a29273282 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -7,6 +7,7 @@ using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 82a34224f4..afd7777861 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -5,7 +5,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osuTK.Graphics; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index 2baf1ad520..b515abcc86 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs @@ -7,6 +7,7 @@ using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs index b146a33fd3..1d25a0c966 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs @@ -4,6 +4,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index 89e8cd9b5a..a0d713067d 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs index 03b55cbead..85880222d7 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs @@ -7,6 +7,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs index f5a9978f77..0ec1fc38d2 100644 --- a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs @@ -4,6 +4,7 @@ using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; using osu.Game.Rulesets.Mania.Objects.Drawables; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index 3c64fe57d4..aacf3ee08d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -6,6 +6,7 @@ using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Skinning; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs index 93ac8748dd..84034d3ee9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs @@ -4,6 +4,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Game.Graphics.Sprites; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs index c982f53c2b..77228e28af 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs @@ -4,6 +4,7 @@ using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs index f47617bcf6..9219fab830 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index ba6b27f743..0cc7858f5a 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs index 53dbe5d08e..b7db819717 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs @@ -9,6 +9,7 @@ using osu.Game.Graphics.Backgrounds; using osuTK.Graphics; using osu.Game.Beatmaps.ControlPoints; using osu.Framework.Audio.Track; +using osu.Framework.Graphics.Effects; namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces { diff --git a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs index bed2c554ec..e80b463481 100644 --- a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs @@ -5,6 +5,7 @@ using osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index dbff5270d2..88d7f9a751 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index f0f58b9b5d..5bb2767438 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs index c1811f37d5..f5ef291c8f 100644 --- a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs +++ b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osuTK; namespace osu.Game.Graphics.Containers diff --git a/osu.Game/Graphics/Containers/WaveContainer.cs b/osu.Game/Graphics/Containers/WaveContainer.cs index 48131d7e86..464682a0ad 100644 --- a/osu.Game/Graphics/Containers/WaveContainer.cs +++ b/osu.Game/Graphics/Containers/WaveContainer.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osuTK.Graphics; diff --git a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs index 4e0ce4a3e1..7bb6396041 100644 --- a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs @@ -6,8 +6,8 @@ using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index dbbe5b4258..b50bf14bab 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Sprites; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics.Effects; using osu.Game.Graphics.Containers; using osu.Framework.Input.Events; diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index 1f5195eaf1..82b09e0821 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs index d64068f74c..a8041c79fc 100644 --- a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs index c72d11b57e..cea8427296 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs @@ -5,7 +5,7 @@ using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; namespace osu.Game.Graphics.UserInterface { diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs index 9911a7c368..36a9aca412 100644 --- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs +++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs @@ -12,6 +12,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Beatmaps.ControlPoints; using osu.Framework.Audio.Track; using System; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index da5cc76060..e4458181f6 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -8,6 +8,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs index e8e44c206e..0d376257e0 100644 --- a/osu.Game/Overlays/AccountCreationOverlay.cs +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Screens; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index 18de87e7b4..abe954aa80 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -11,6 +11,7 @@ using osuTK; using osuTK.Graphics; using osu.Game.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 95cf9e9d04..3659769752 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -6,6 +6,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 4d974a0b63..44827f0a0c 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index ac4485a410..44b0d9e4f6 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index c49268bc16..82bac71f5e 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -7,6 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Beatmaps; diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 908ec5f026..66a6672ab1 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -8,6 +8,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs index e1f29a40e4..5e506f1e4b 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index ede2f34574..a5f5ea37eb 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -6,6 +6,7 @@ using System.Linq; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 2b509f370e..f413dc3771 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -8,6 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 8313dac50a..58d6cd10d2 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -8,6 +8,7 @@ using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index a5703eba92..6d82db5603 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -19,6 +19,7 @@ using osu.Framework.Graphics.Textures; using osuTK.Input; using osu.Framework.Graphics.Shapes; using System; +using osu.Framework.Graphics.Effects; using osu.Framework.Input.Events; using osu.Framework.MathUtils; diff --git a/osu.Game/Overlays/Music/CollectionsDropdown.cs b/osu.Game/Overlays/Music/CollectionsDropdown.cs index aa93e349e8..4f59b053b6 100644 --- a/osu.Game/Overlays/Music/CollectionsDropdown.cs +++ b/osu.Game/Overlays/Music/CollectionsDropdown.cs @@ -6,7 +6,7 @@ using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 8cbea63fe3..949090e8b8 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -8,6 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index ce2137346f..307fac11df 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -10,6 +10,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; diff --git a/osu.Game/Overlays/Notifications/Notification.cs b/osu.Game/Overlays/Notifications/Notification.cs index 7abff9252f..711b3a1eef 100644 --- a/osu.Game/Overlays/Notifications/Notification.cs +++ b/osu.Game/Overlays/Notifications/Notification.cs @@ -7,6 +7,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Game.Graphics; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 5e45fbf081..9198455bf7 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics; using osuTK; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Transforms; using osu.Framework.Threading; using osu.Game.Configuration; diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 28877c21f0..46b0726123 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -20,6 +20,7 @@ using osu.Game.Overlays.Profile.Components; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; using Humanizer; +using osu.Framework.Graphics.Effects; namespace osu.Game.Overlays.Profile { diff --git a/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs b/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs index a93fefdd75..23fe6e9cd5 100644 --- a/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs +++ b/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs index 3c69082e9d..aeea5118a7 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -7,6 +7,7 @@ using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 078c01ce92..0dbc96998a 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -16,6 +16,7 @@ using System.ComponentModel; using osu.Game.Graphics; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 02e9d48f40..e970ff6211 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -9,6 +9,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Social/SocialPanel.cs b/osu.Game/Overlays/Social/SocialPanel.cs index 738f940484..555527670a 100644 --- a/osu.Game/Overlays/Social/SocialPanel.cs +++ b/osu.Game/Overlays/Social/SocialPanel.cs @@ -5,7 +5,7 @@ using osuTK; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Input.Events; using osu.Game.Users; diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index 71374d5180..2b2b19b73a 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -4,6 +4,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs index f729810fbc..87b18ba9f4 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Game.Rulesets; using osuTK.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index d01eab4dab..ebfa6706d4 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -7,6 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osuTK; using osuTK.Input; using osuTK.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 356ffa5180..c9e49a09f4 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -4,7 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Users; diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 48ce055975..0d33a8b9ef 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -5,7 +5,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs index 1ad69afe91..70c0cf623e 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index 794fc093d3..611dd66ab3 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -16,6 +16,7 @@ using osuTK.Input; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics.Containers; using osu.Framework.Audio.Track; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index dce597b276..6ec8f2bfe5 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -9,6 +9,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 2fac8de799..ae50e0898a 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -19,6 +19,7 @@ using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Input.Bindings; using Humanizer; +using osu.Framework.Graphics.Effects; namespace osu.Game.Screens.Play { diff --git a/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs b/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs index 8f09c2b2bf..315bc27a79 100644 --- a/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; using osuTK; diff --git a/osu.Game/Screens/Ranking/ResultModeButton.cs b/osu.Game/Screens/Ranking/ResultModeButton.cs index 109d0195db..1383511241 100644 --- a/osu.Game/Screens/Ranking/ResultModeButton.cs +++ b/osu.Game/Screens/Ranking/ResultModeButton.cs @@ -6,6 +6,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osuTK; diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index dafb4c0aad..bebeaee00a 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -8,6 +8,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; using osu.Framework.Screens; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Screens/Ranking/ResultsPage.cs b/osu.Game/Screens/Ranking/ResultsPage.cs index 1b17dda563..8776c599dd 100644 --- a/osu.Game/Screens/Ranking/ResultsPage.cs +++ b/osu.Game/Screens/Ranking/ResultsPage.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index b2e08aeefd..670b5ca62c 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -22,6 +22,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Rulesets; diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index 3c1b7cc831..4402b25c9e 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -7,6 +7,7 @@ using osu.Framework.Audio.Sample; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.MathUtils; diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs index 0f1f49bd85..410102b607 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs @@ -4,6 +4,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 1f62111a4e..fc7a544433 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -16,6 +16,7 @@ using osu.Game.Overlays; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Containers; using osu.Game.Overlays.Profile.Header; From f1952c08162ff088194ab0d19a365c57871f6553 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Apr 2019 19:55:24 +0900 Subject: [PATCH 0446/5608] Update font awesome usage --- osu.Desktop/Overlays/VersionManager.cs | 2 +- osu.Desktop/Updater/SimpleUpdateManager.cs | 2 +- osu.Desktop/Updater/SquirrelUpdateManager.cs | 2 +- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs | 6 +++--- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs | 4 ++-- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs | 6 +++--- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs | 2 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- .../Objects/Drawables/DrawableSpinner.cs | 2 +- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs | 6 +++--- .../Objects/Drawables/Pieces/SwellSymbolPiece.cs | 2 +- .../SongSelect/TestCaseBeatmapOptionsOverlay.cs | 8 ++++---- .../UserInterface/TestCaseDialogOverlay.cs | 4 ++-- .../Visual/UserInterface/TestCasePopupDialog.cs | 2 +- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 2 +- .../Graphics/Containers/LinkFlowContainer.cs | 2 +- .../Graphics/UserInterface/BreadcrumbControl.cs | 2 +- .../Graphics/UserInterface/ExternalLinkButton.cs | 2 +- .../Graphics/UserInterface/LoadingAnimation.cs | 4 ++-- osu.Game/Graphics/UserInterface/OsuDropdown.cs | 4 ++-- .../Graphics/UserInterface/OsuPasswordTextBox.cs | 2 +- osu.Game/Graphics/UserInterface/OsuTabControl.cs | 2 +- .../UserInterface/OsuTabControlCheckbox.cs | 6 +++--- osu.Game/Graphics/UserInterface/SearchTextBox.cs | 2 +- osu.Game/Graphics/UserInterface/StarCounter.cs | 2 +- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 6 +++--- .../Online/Leaderboards/MessagePlaceholder.cs | 2 +- .../Leaderboards/RetrievalFailurePlaceholder.cs | 2 +- .../Online/Multiplayer/GameTypes/GameTypeTag.cs | 2 +- .../Multiplayer/GameTypes/GameTypeTagTeam.cs | 4 ++-- .../Multiplayer/GameTypes/GameTypeTimeshift.cs | 2 +- osu.Game/OsuGame.cs | 4 ++-- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 10 +++++----- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 4 ++-- .../BeatmapSet/Buttons/DownloadButton.cs | 2 +- .../BeatmapSet/Buttons/FavouriteButton.cs | 6 +++--- osu.Game/Overlays/Chat/ExternalLinkDialog.cs | 2 +- .../Overlays/Chat/Selection/ChannelListItem.cs | 4 ++-- osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs | 2 +- osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs | 2 +- .../Overlays/Chat/Tabs/PrivateChannelTabItem.cs | 2 +- osu.Game/Overlays/Chat/Tabs/TabCloseButton.cs | 2 +- osu.Game/Overlays/Dialog/PopupDialog.cs | 2 +- osu.Game/Overlays/Direct/DirectGridPanel.cs | 8 ++++---- osu.Game/Overlays/Direct/DirectListPanel.cs | 8 ++++---- osu.Game/Overlays/Direct/DownloadButton.cs | 4 ++-- osu.Game/Overlays/Direct/PlayButton.cs | 4 ++-- .../KeyBinding/GlobalKeyBindingsSection.cs | 2 +- osu.Game/Overlays/KeyBindingOverlay.cs | 2 +- osu.Game/Overlays/Music/PlaylistItem.cs | 2 +- osu.Game/Overlays/MusicController.cs | 12 ++++++------ osu.Game/Overlays/Notifications/Notification.cs | 2 +- .../ProgressCompletionNotification.cs | 2 +- .../Overlays/Notifications/SimpleNotification.cs | 2 +- .../Overlays/Profile/Header/SupporterIcon.cs | 2 +- osu.Game/Overlays/Profile/ProfileHeader.cs | 16 ++++++++-------- .../SearchableList/DisplayStyleControl.cs | 4 ++-- .../Overlays/Settings/Sections/AudioSection.cs | 2 +- .../Overlays/Settings/Sections/DebugSection.cs | 2 +- .../Settings/Sections/GameplaySection.cs | 2 +- .../Settings/Sections/General/LoginSettings.cs | 2 +- .../Overlays/Settings/Sections/GeneralSection.cs | 2 +- .../Settings/Sections/GraphicsSection.cs | 2 +- .../Overlays/Settings/Sections/InputSection.cs | 2 +- .../Maintenance/DeleteAllBeatmapsDialog.cs | 2 +- .../Settings/Sections/MaintenanceSection.cs | 2 +- .../Overlays/Settings/Sections/OnlineSection.cs | 2 +- .../Overlays/Settings/Sections/SkinSection.cs | 2 +- osu.Game/Overlays/Social/Header.cs | 2 +- osu.Game/Overlays/Toolbar/Toolbar.cs | 2 +- osu.Game/Overlays/Toolbar/ToolbarChatButton.cs | 2 +- osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs | 2 +- osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs | 2 +- .../Toolbar/ToolbarNotificationButton.cs | 2 +- .../Overlays/Toolbar/ToolbarSettingsButton.cs | 2 +- osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs | 2 +- osu.Game/Overlays/Volume/MuteButton.cs | 2 +- osu.Game/Rulesets/Mods/Mod.cs | 2 +- osu.Game/Rulesets/Mods/ModDaycore.cs | 2 +- osu.Game/Rulesets/Mods/ModWindDown.cs | 2 +- osu.Game/Rulesets/Mods/ModWindUp.cs | 2 +- osu.Game/Rulesets/Ruleset.cs | 2 +- .../Screens/Edit/Components/PlaybackControl.cs | 4 ++-- .../Compose/Components/BeatDivisorControl.cs | 4 ++-- .../Compose/Components/Timeline/TimelineArea.cs | 4 ++-- osu.Game/Screens/Menu/ButtonSystem.cs | 8 ++++---- osu.Game/Screens/Menu/Disclaimer.cs | 4 ++-- .../Match/Components/MatchLeaderboardScore.cs | 6 +++--- .../Ranking/Types/RoomLeaderboardPageInfo.cs | 2 +- osu.Game/Screens/Play/Break/BreakArrows.cs | 8 ++++---- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 2 +- .../Play/PlayerSettings/PlayerSettingsGroup.cs | 2 +- osu.Game/Screens/Play/SkipOverlay.cs | 6 +++--- .../Ranking/Types/LocalLeaderboardPageInfo.cs | 2 +- .../Ranking/Types/ScoreOverviewPageInfo.cs | 2 +- osu.Game/Screens/ScreenWhiteBox.cs | 2 +- .../Screens/Select/BeatmapClearScoresDialog.cs | 2 +- osu.Game/Screens/Select/BeatmapDeleteDialog.cs | 2 +- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 6 +++--- osu.Game/Screens/Select/ImportFromStablePopup.cs | 2 +- .../Select/Options/BeatmapOptionsButton.cs | 2 +- osu.Game/Screens/Select/PlaySongSelect.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 6 +++--- osu.Game/Users/UserPanel.cs | 2 +- 107 files changed, 173 insertions(+), 173 deletions(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 2998e08715..711ffa7d9e 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -110,7 +110,7 @@ namespace osu.Desktop.Overlays public UpdateCompleteNotification(string version, Action openUrl = null) { Text = $"You are now running osu!lazer {version}.\nClick to see what's new!"; - Icon = FontAwesome.CheckSquare; + Icon = FontAwesome.Solid.CheckSquare; Activated = delegate { openUrl?.Invoke($"https://osu.ppy.sh/home/changelog/lazer/{version}"); diff --git a/osu.Desktop/Updater/SimpleUpdateManager.cs b/osu.Desktop/Updater/SimpleUpdateManager.cs index 1cb47d6b58..0600804339 100644 --- a/osu.Desktop/Updater/SimpleUpdateManager.cs +++ b/osu.Desktop/Updater/SimpleUpdateManager.cs @@ -54,7 +54,7 @@ namespace osu.Desktop.Updater { Text = $"A newer release of osu! has been found ({version} → {latest.TagName}).\n\n" + "Click here to download the new version, which can be installed over the top of your existing installation", - Icon = FontAwesome.Upload, + Icon = FontAwesome.Solid.Upload, Activated = () => { host.OpenUrlExternally(getBestUrl(latest)); diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index 6ebadeb4e9..5fed2a63e1 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -159,7 +159,7 @@ namespace osu.Desktop.Updater { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Icon = FontAwesome.Upload, + Icon = FontAwesome.Solid.Upload, Colour = Color4.White, Size = new Vector2(20), } diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs index d55f3ff159..18cc300ff9 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs @@ -23,19 +23,19 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { Name = @"Fruit Count", Content = fruits.ToString(), - Icon = FontAwesome.CircleOutline + Icon = FontAwesome.Regular.Circle }, new BeatmapStatistic { Name = @"Juice Stream Count", Content = juiceStreams.ToString(), - Icon = FontAwesome.Circle + Icon = FontAwesome.Regular.Circle }, new BeatmapStatistic { Name = @"Banana Shower Count", Content = bananaShowers.ToString(), - Icon = FontAwesome.Circle + Icon = FontAwesome.Regular.Circle } }; } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs index 184cbf339d..dc24a344e9 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs @@ -42,13 +42,13 @@ namespace osu.Game.Rulesets.Mania.Beatmaps { Name = @"Note Count", Content = notes.ToString(), - Icon = FontAwesome.CircleOutline + Icon = FontAwesome.Regular.Circle }, new BeatmapStatistic { Name = @"Hold Note Count", Content = holdnotes.ToString(), - Icon = FontAwesome.Circle + Icon = FontAwesome.Regular.Circle }, }; } diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs index 7099758e3d..491d82b89e 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs @@ -23,19 +23,19 @@ namespace osu.Game.Rulesets.Osu.Beatmaps { Name = @"Circle Count", Content = circles.ToString(), - Icon = FontAwesome.CircleOutline + Icon = FontAwesome.Regular.Circle }, new BeatmapStatistic { Name = @"Slider Count", Content = sliders.ToString(), - Icon = FontAwesome.Circle + Icon = FontAwesome.Regular.Circle }, new BeatmapStatistic { Name = @"Spinner Count", Content = spinners.ToString(), - Icon = FontAwesome.Circle + Icon = FontAwesome.Regular.Circle } }; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 7f94b68cc0..f3c7939a94 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => "Play with blinds on your screen."; public override string Acronym => "BL"; - public override IconUsage Icon => FontAwesome.Adjust; + public override IconUsage Icon => FontAwesome.Solid.Adjust; public override ModType Type => ModType.DifficultyIncrease; public override bool Ranked => false; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs index 2e93815ef0..35a5992e25 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Acronym => "GR"; - public override IconUsage Icon => FontAwesome.ArrowsV; + public override IconUsage Icon => FontAwesome.Solid.ArrowsAltV; public override ModType Type => ModType.Fun; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs index 31195b7878..9b079895fa 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public override string Name => "Transform"; public override string Acronym => "TR"; - public override IconUsage Icon => FontAwesome.Arrows; + public override IconUsage Icon => FontAwesome.Solid.ArrowsAlt; public override ModType Type => ModType.Fun; public override string Description => "Everything rotates. EVERYTHING."; public override double ScoreMultiplier => 1; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs index bdc2873d8d..17fcd03dd5 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public override string Name => "Wiggle"; public override string Acronym => "WG"; - public override IconUsage Icon => FontAwesome.Certificate; + public override IconUsage Icon => FontAwesome.Solid.Certificate; public override ModType Type => ModType.Fun; public override string Description => "They just won't stay still..."; public override double ScoreMultiplier => 1; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index a6714690b1..edf2d90c08 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon { RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.ChevronRight + Icon = FontAwesome.Solid.ChevronRight }, restrictSize: false) }; } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 3a6ff3fcf8..ab4935e350 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(48), - Icon = FontAwesome.Asterisk, + Icon = FontAwesome.Solid.Asterisk, Shadow = false, }, } diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs index 4149da67c7..b595f43fbb 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs @@ -23,19 +23,19 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { Name = @"Hit Count", Content = hits.ToString(), - Icon = FontAwesome.CircleOutline + Icon = FontAwesome.Regular.Circle }, new BeatmapStatistic { Name = @"Drumroll Count", Content = drumrolls.ToString(), - Icon = FontAwesome.Circle + Icon = FontAwesome.Regular.Circle }, new BeatmapStatistic { Name = @"Swell Count", Content = swells.ToString(), - Icon = FontAwesome.Circle + Icon = FontAwesome.Regular.Circle } }; } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs index 569ac96c15..0ed9923924 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces new SpriteIcon { RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.Asterisk, + Icon = FontAwesome.Solid.Asterisk, Shadow = false } }; diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapOptionsOverlay.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapOptionsOverlay.cs index 3cb480bab8..7d09debbd6 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapOptionsOverlay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapOptionsOverlay.cs @@ -16,10 +16,10 @@ namespace osu.Game.Tests.Visual.SongSelect { var overlay = new BeatmapOptionsOverlay(); - overlay.AddButton(@"Remove", @"from unplayed", FontAwesome.TimesCircleOutline, Color4.Purple, null, Key.Number1); - overlay.AddButton(@"Clear", @"local scores", FontAwesome.Eraser, Color4.Purple, null, Key.Number2); - overlay.AddButton(@"Edit", @"Beatmap", FontAwesome.Pencil, Color4.Yellow, null, Key.Number3); - overlay.AddButton(@"Delete", @"Beatmap", FontAwesome.Trash, Color4.Pink, null, Key.Number4, float.MaxValue); + overlay.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, Color4.Purple, null, Key.Number1); + overlay.AddButton(@"Clear", @"local scores", FontAwesome.Solid.Eraser, Color4.Purple, null, Key.Number2); + overlay.AddButton(@"Edit", @"Beatmap", FontAwesome.Solid.PencilAlt, Color4.Yellow, null, Key.Number3); + overlay.AddButton(@"Delete", @"Beatmap", FontAwesome.Solid.Trash, Color4.Pink, null, Key.Number4, float.MaxValue); Add(overlay); diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseDialogOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseDialogOverlay.cs index 98d6f3a149..8964d20564 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseDialogOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseDialogOverlay.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("dialog #1", () => overlay.Push(new PopupDialog { - Icon = FontAwesome.TrashOutline, + Icon = FontAwesome.Regular.TrashAlt, HeaderText = @"Confirm deletion of", BodyText = @"Ayase Rie - Yuima-ru*World TVver.", Buttons = new PopupDialogButton[] @@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("dialog #2", () => overlay.Push(new PopupDialog { - Icon = FontAwesome.Gear, + Icon = FontAwesome.Solid.Cog, HeaderText = @"What do you want to do with", BodyText = "Camellia as \"Bang Riot\" - Blastix Riotz", Buttons = new PopupDialogButton[] diff --git a/osu.Game.Tests/Visual/UserInterface/TestCasePopupDialog.cs b/osu.Game.Tests/Visual/UserInterface/TestCasePopupDialog.cs index bcba7e6811..2f01f593c7 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCasePopupDialog.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCasePopupDialog.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.UserInterface { RelativeSizeAxes = Axes.Both, State = Framework.Graphics.Containers.Visibility.Visible, - Icon = FontAwesome.AssistiveListeningSystems, + Icon = FontAwesome.Solid.AssistiveListeningSystems, HeaderText = @"This is a test popup", BodyText = "I can say lots of stuff and even wrap my words!", Buttons = new PopupDialogButton[] diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index f0f58b9b5d..1be7411bec 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -60,7 +60,7 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, // the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment) - Icon = ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.QuestionCircleOutline } + Icon = ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle } } }; } diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 204c83aac9..dace873b92 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -35,7 +35,7 @@ namespace osu.Game.Graphics.Containers showNotImplementedError = () => notifications?.Post(new SimpleNotification { Text = @"This link type is not yet supported!", - Icon = FontAwesome.LifeSaver, + Icon = FontAwesome.Solid.LifeRing, }); } diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index 8eb9b99f29..f5e57e5f27 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -93,7 +93,7 @@ namespace osu.Game.Graphics.UserInterface Anchor = Anchor.CentreRight, Origin = Anchor.CentreLeft, Size = new Vector2(item_chevron_size), - Icon = FontAwesome.ChevronRight, + Icon = FontAwesome.Solid.ChevronRight, Margin = new MarginPadding { Left = padding }, Alpha = 0f, }); diff --git a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs index 14328930ce..8c00cae08a 100644 --- a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs +++ b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs @@ -26,7 +26,7 @@ namespace osu.Game.Graphics.UserInterface Size = new Vector2(12); InternalChild = new SpriteIcon { - Icon = FontAwesome.ExternalLink, + Icon = FontAwesome.Solid.ExternalLinkAlt, RelativeSizeAxes = Axes.Both }; } diff --git a/osu.Game/Graphics/UserInterface/LoadingAnimation.cs b/osu.Game/Graphics/UserInterface/LoadingAnimation.cs index bb92d8a2a9..5a8a0da135 100644 --- a/osu.Game/Graphics/UserInterface/LoadingAnimation.cs +++ b/osu.Game/Graphics/UserInterface/LoadingAnimation.cs @@ -37,14 +37,14 @@ namespace osu.Game.Graphics.UserInterface Position = new Vector2(1, 1), Colour = Color4.Black, Alpha = 0.4f, - Icon = FontAwesome.CircleONotch + Icon = FontAwesome.Solid.CircleNotch }, spinner = new SpriteIcon { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.CircleONotch + Icon = FontAwesome.Solid.CircleNotch } }; } diff --git a/osu.Game/Graphics/UserInterface/OsuDropdown.cs b/osu.Game/Graphics/UserInterface/OsuDropdown.cs index 902fd310c5..8245de9f70 100644 --- a/osu.Game/Graphics/UserInterface/OsuDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuDropdown.cs @@ -179,7 +179,7 @@ namespace osu.Game.Graphics.UserInterface Chevron = new SpriteIcon { AlwaysPresent = true, - Icon = FontAwesome.ChevronRight, + Icon = FontAwesome.Solid.ChevronRight, Colour = Color4.Black, Alpha = 0.5f, Size = new Vector2(8), @@ -244,7 +244,7 @@ namespace osu.Game.Graphics.UserInterface }, Icon = new SpriteIcon { - Icon = FontAwesome.ChevronDown, + Icon = FontAwesome.Solid.ChevronDown, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Margin = new MarginPadding { Right = 4 }, diff --git a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs index 37a13f5274..418ad038f7 100644 --- a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs @@ -108,7 +108,7 @@ namespace osu.Game.Graphics.UserInterface public CapsWarning() { - Icon = FontAwesome.Warning; + Icon = FontAwesome.Solid.ExclamationTriangle; } [BackgroundDependencyLoader] diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 0ddc88b29e..fadc905541 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -254,7 +254,7 @@ namespace osu.Game.Graphics.UserInterface { new SpriteIcon { - Icon = FontAwesome.EllipsisH, + Icon = FontAwesome.Solid.EllipsisH, Size = new Vector2(14), Origin = Anchor.Centre, Anchor = Anchor.Centre, diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index 557a337941..869005d05c 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -99,7 +99,7 @@ namespace osu.Game.Graphics.UserInterface icon = new SpriteIcon { Size = new Vector2(14), - Icon = FontAwesome.CircleOutline, + Icon = FontAwesome.Regular.Circle, Shadow = true, }, }, @@ -120,12 +120,12 @@ namespace osu.Game.Graphics.UserInterface if (selected.NewValue) { fadeIn(); - icon.Icon = FontAwesome.CheckCircleOutline; + icon.Icon = FontAwesome.Regular.CheckCircle; } else { fadeOut(); - icon.Icon = FontAwesome.CircleOutline; + icon.Icon = FontAwesome.Regular.Circle; } }; } diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index 341f49732e..7023711aaa 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -22,7 +22,7 @@ namespace osu.Game.Graphics.UserInterface { new SpriteIcon { - Icon = FontAwesome.Search, + Icon = FontAwesome.Solid.Search, Origin = Anchor.CentreRight, Anchor = Anchor.CentreRight, Margin = new MarginPadding { Right = 10 }, diff --git a/osu.Game/Graphics/UserInterface/StarCounter.cs b/osu.Game/Graphics/UserInterface/StarCounter.cs index ac6e393435..8ccf3001e3 100644 --- a/osu.Game/Graphics/UserInterface/StarCounter.cs +++ b/osu.Game/Graphics/UserInterface/StarCounter.cs @@ -143,7 +143,7 @@ namespace osu.Game.Graphics.UserInterface Child = Icon = new SpriteIcon { Size = new Vector2(star_size), - Icon = FontAwesome.Star, + Icon = FontAwesome.Solid.Star, Anchor = Anchor.Centre, Origin = Anchor.Centre, }; diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index da5cc76060..70edcc3fc8 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -258,8 +258,8 @@ namespace osu.Game.Online.Leaderboards protected virtual IEnumerable GetStatistics(ScoreInfo model) => new[] { - new LeaderboardScoreStatistic(FontAwesome.Link, "Max Combo", model.MaxCombo.ToString()), - new LeaderboardScoreStatistic(FontAwesome.Crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy)) + new LeaderboardScoreStatistic(FontAwesome.Solid.Link, "Max Combo", model.MaxCombo.ToString()), + new LeaderboardScoreStatistic(FontAwesome.Solid.Crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy)) }; protected override bool OnHover(HoverEvent e) @@ -353,7 +353,7 @@ namespace osu.Game.Online.Leaderboards Size = new Vector2(icon_size), Rotation = 45, Colour = OsuColour.FromHex(@"3087ac"), - Icon = FontAwesome.Square, + Icon = FontAwesome.Solid.Square, Shadow = true, }, new SpriteIcon diff --git a/osu.Game/Online/Leaderboards/MessagePlaceholder.cs b/osu.Game/Online/Leaderboards/MessagePlaceholder.cs index b4980444d1..ef425dacd8 100644 --- a/osu.Game/Online/Leaderboards/MessagePlaceholder.cs +++ b/osu.Game/Online/Leaderboards/MessagePlaceholder.cs @@ -12,7 +12,7 @@ namespace osu.Game.Online.Leaderboards public MessagePlaceholder(string message) { - AddIcon(FontAwesome.ExclamationCircle, cp => + AddIcon(FontAwesome.Solid.ExclamationCircle, cp => { cp.Font = cp.Font.With(size: TEXT_SIZE); cp.Padding = new MarginPadding { Right = 10 }; diff --git a/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs b/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs index 9a35dbc476..801f3f8ff0 100644 --- a/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs +++ b/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs @@ -41,7 +41,7 @@ namespace osu.Game.Online.Leaderboards Action = () => Action?.Invoke(), Child = icon = new SpriteIcon { - Icon = FontAwesome.Refresh, + Icon = FontAwesome.Solid.Sync, Size = new Vector2(TEXT_SIZE), Shadow = true, }, diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs index d51c5eb9bb..5ba5f1a415 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs @@ -18,7 +18,7 @@ namespace osu.Game.Online.Multiplayer.GameTypes { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Icon = FontAwesome.Refresh, + Icon = FontAwesome.Solid.Sync, Size = new Vector2(size), Colour = colours.Blue, Shadow = false, diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs index 266f4a77b2..ef0a00a9f0 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs @@ -26,14 +26,14 @@ namespace osu.Game.Online.Multiplayer.GameTypes { new SpriteIcon { - Icon = FontAwesome.Refresh, + Icon = FontAwesome.Solid.Sync, Size = new Vector2(size * 0.75f), Colour = colours.Blue, Shadow = false, }, new SpriteIcon { - Icon = FontAwesome.Refresh, + Icon = FontAwesome.Solid.Sync, Size = new Vector2(size * 0.75f), Colour = colours.Pink, Shadow = false, diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs index 1271556db4..1a3d2837ce 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs @@ -16,7 +16,7 @@ namespace osu.Game.Online.Multiplayer.GameTypes { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Icon = FontAwesome.ClockOutline, + Icon = FontAwesome.Regular.Clock, Size = new Vector2(size), Colour = colours.Blue, Shadow = false diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e470d554c9..f8ca1bc65f 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -580,7 +580,7 @@ namespace osu.Game { Schedule(() => notifications.Post(new SimpleNotification { - Icon = entry.Level == LogLevel.Important ? FontAwesome.ExclamationCircle : FontAwesome.Bomb, + Icon = entry.Level == LogLevel.Important ? FontAwesome.Solid.ExclamationCircle : FontAwesome.Solid.Bomb, Text = entry.Message + (entry.Exception != null && IsDeployedBuild ? "\n\nThis error has been automatically reported to the devs." : string.Empty), })); } @@ -588,7 +588,7 @@ namespace osu.Game { Schedule(() => notifications.Post(new SimpleNotification { - Icon = FontAwesome.EllipsisH, + Icon = FontAwesome.Solid.EllipsisH, Text = "Subsequent messages have been logged. Click to view log files.", Activated = () => { diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index e817b28589..8ed52dade5 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -75,10 +75,10 @@ namespace osu.Game.Overlays.BeatmapSet Direction = FillDirection.Horizontal, Children = new[] { - length = new Statistic(FontAwesome.ClockOutline, "Length") { Width = 0.25f }, - bpm = new Statistic(FontAwesome.Circle, "BPM") { Width = 0.25f }, - circleCount = new Statistic(FontAwesome.CircleOutline, "Circle Count") { Width = 0.25f }, - sliderCount = new Statistic(FontAwesome.Circle, "Slider Count") { Width = 0.25f }, + length = new Statistic(FontAwesome.Regular.Clock, "Length") { Width = 0.25f }, + bpm = new Statistic(FontAwesome.Regular.Circle, "BPM") { Width = 0.25f }, + circleCount = new Statistic(FontAwesome.Regular.Circle, "Circle Count") { Width = 0.25f }, + sliderCount = new Statistic(FontAwesome.Regular.Circle, "Slider Count") { Width = 0.25f }, }, }; } @@ -121,7 +121,7 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.CentreLeft, Origin = Anchor.Centre, - Icon = FontAwesome.Square, + Icon = FontAwesome.Solid.Square, Size = new Vector2(13), Rotation = 45, Colour = OsuColour.FromHex(@"441288"), diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 1d4f181256..baf702eebc 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -131,8 +131,8 @@ namespace osu.Game.Overlays.BeatmapSet Margin = new MarginPadding { Top = 5 }, Children = new[] { - plays = new Statistic(FontAwesome.PlayCircle), - favourites = new Statistic(FontAwesome.Heart), + plays = new Statistic(FontAwesome.Solid.PlayCircle), + favourites = new Statistic(FontAwesome.Solid.Heart), }, }, }, diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 667869e310..4a60b69a5a 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -78,7 +78,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons Depth = -1, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Icon = FontAwesome.Download, + Icon = FontAwesome.Solid.Download, Size = new Vector2(16), Margin = new MarginPadding { Right = 5 }, }, diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 43c14e2a58..7207739646 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Icon = FontAwesome.HeartOutline, + Icon = FontAwesome.Regular.Heart, Size = new Vector2(18), Shadow = false, }, @@ -59,12 +59,12 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons if (favourited.NewValue) { pink.FadeIn(200); - icon.Icon = FontAwesome.Heart; + icon.Icon = FontAwesome.Solid.Heart; } else { pink.FadeOut(200); - icon.Icon = FontAwesome.HeartOutline; + icon.Icon = FontAwesome.Regular.Heart; } }; diff --git a/osu.Game/Overlays/Chat/ExternalLinkDialog.cs b/osu.Game/Overlays/Chat/ExternalLinkDialog.cs index bcf63672ac..dbae091fb0 100644 --- a/osu.Game/Overlays/Chat/ExternalLinkDialog.cs +++ b/osu.Game/Overlays/Chat/ExternalLinkDialog.cs @@ -14,7 +14,7 @@ namespace osu.Game.Overlays.Chat HeaderText = "Just checking..."; BodyText = $"You are about to leave osu! and open the following link in a web browser:\n\n{url}"; - Icon = FontAwesome.Warning; + Icon = FontAwesome.Solid.ExclamationTriangle; Buttons = new PopupDialogButton[] { diff --git a/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs b/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs index 85a10510ef..4d77e5f93d 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs @@ -74,7 +74,7 @@ namespace osu.Game.Overlays.Chat.Selection { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - Icon = FontAwesome.CheckCircle, + Icon = FontAwesome.Solid.CheckCircle, Size = new Vector2(text_size), Shadow = false, Margin = new MarginPadding { Right = 10f }, @@ -121,7 +121,7 @@ namespace osu.Game.Overlays.Chat.Selection { new SpriteIcon { - Icon = FontAwesome.User, + Icon = FontAwesome.Solid.User, Size = new Vector2(text_size - 2), Shadow = false, Margin = new MarginPadding { Top = 1 }, diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index f8a8038878..2e7f2d5908 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Chat.Tabs AddInternal(new SpriteIcon { - Icon = FontAwesome.Comments, + Icon = FontAwesome.Solid.Comments, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Size = new Vector2(20), diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs index e1f29a40e4..a4aefa4c4f 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs @@ -117,7 +117,7 @@ namespace osu.Game.Overlays.Chat.Tabs }; } - protected virtual IconUsage DisplayIcon => FontAwesome.Hashtag; + protected virtual IconUsage DisplayIcon => FontAwesome.Solid.Hashtag; protected virtual bool ShowCloseOnHover => true; diff --git a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs index f8add20674..8aa6d6fecd 100644 --- a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Chat.Tabs private readonly OsuSpriteText username; private readonly Avatar avatarContainer; - protected override IconUsage DisplayIcon => FontAwesome.At; + protected override IconUsage DisplayIcon => FontAwesome.Solid.At; public PrivateChannelTabItem(Channel value) : base(value) diff --git a/osu.Game/Overlays/Chat/Tabs/TabCloseButton.cs b/osu.Game/Overlays/Chat/Tabs/TabCloseButton.cs index b15f568c94..bde930d4fb 100644 --- a/osu.Game/Overlays/Chat/Tabs/TabCloseButton.cs +++ b/osu.Game/Overlays/Chat/Tabs/TabCloseButton.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Chat.Tabs Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(0.75f), - Icon = FontAwesome.Close, + Icon = FontAwesome.Solid.TimesCircle, RelativeSizeAxes = Axes.Both, }; } diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index ede2f34574..91f42a491a 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -166,7 +166,7 @@ namespace osu.Game.Overlays.Dialog { Origin = Anchor.Centre, Anchor = Anchor.Centre, - Icon = FontAwesome.Close, + Icon = FontAwesome.Solid.TimesCircle, Size = new Vector2(50), }, }, diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index b8168f692a..eb73a50f99 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -186,8 +186,8 @@ namespace osu.Game.Overlays.Direct Margin = new MarginPadding { Top = vertical_padding, Right = vertical_padding }, Children = new[] { - new Statistic(FontAwesome.PlayCircle, SetInfo.OnlineInfo?.PlayCount ?? 0), - new Statistic(FontAwesome.Heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0), + new Statistic(FontAwesome.Solid.PlayCircle, SetInfo.OnlineInfo?.PlayCount ?? 0), + new Statistic(FontAwesome.Solid.Heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0), }, }, statusContainer = new FillFlowContainer @@ -206,12 +206,12 @@ namespace osu.Game.Overlays.Direct if (SetInfo.OnlineInfo?.HasVideo ?? false) { - statusContainer.Add(new IconPill(FontAwesome.Film)); + statusContainer.Add(new IconPill(FontAwesome.Solid.Film)); } if (SetInfo.OnlineInfo?.HasStoryboard ?? false) { - statusContainer.Add(new IconPill(FontAwesome.Image)); + statusContainer.Add(new IconPill(FontAwesome.Solid.Image)); } statusContainer.Add(new BeatmapSetOnlineStatusPill diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index 518f6e498a..d645fd3bda 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -161,8 +161,8 @@ namespace osu.Game.Overlays.Direct Direction = FillDirection.Vertical, Children = new Drawable[] { - new Statistic(FontAwesome.PlayCircle, SetInfo.OnlineInfo?.PlayCount ?? 0), - new Statistic(FontAwesome.Heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0), + new Statistic(FontAwesome.Solid.PlayCircle, SetInfo.OnlineInfo?.PlayCount ?? 0), + new Statistic(FontAwesome.Solid.Heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0), new FillFlowContainer { Anchor = Anchor.TopRight, @@ -211,12 +211,12 @@ namespace osu.Game.Overlays.Direct if (SetInfo.OnlineInfo?.HasVideo ?? false) { - statusContainer.Add(new IconPill(FontAwesome.Film) { IconSize = new Vector2(20) }); + statusContainer.Add(new IconPill(FontAwesome.Solid.Film) { IconSize = new Vector2(20) }); } if (SetInfo.OnlineInfo?.HasStoryboard ?? false) { - statusContainer.Add(new IconPill(FontAwesome.Image) { IconSize = new Vector2(20) }); + statusContainer.Add(new IconPill(FontAwesome.Solid.Image) { IconSize = new Vector2(20) }); } statusContainer.Add(new BeatmapSetOnlineStatusPill diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 7fc145d635..6107dc3af3 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -49,7 +49,7 @@ namespace osu.Game.Overlays.Direct Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(13), - Icon = FontAwesome.Download, + Icon = FontAwesome.Solid.Download, }, checkmark = new SpriteIcon { @@ -57,7 +57,7 @@ namespace osu.Game.Overlays.Direct Origin = Anchor.Centre, X = 8, Size = Vector2.Zero, - Icon = FontAwesome.Check, + Icon = FontAwesome.Solid.Check, } } } diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 05ef5c8496..6daebb3c15 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -74,7 +74,7 @@ namespace osu.Game.Overlays.Direct Origin = Anchor.Centre, FillMode = FillMode.Fit, RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.Play, + Icon = FontAwesome.Solid.Play, }, loadingAnimation = new LoadingAnimation { @@ -116,7 +116,7 @@ namespace osu.Game.Overlays.Direct private void playingStateChanged(ValueChangedEvent e) { - icon.Icon = e.NewValue ? FontAwesome.Stop : FontAwesome.Play; + icon.Icon = e.NewValue ? FontAwesome.Solid.Stop : FontAwesome.Solid.Play; icon.FadeColour(e.NewValue || IsHovered ? hoverColour : Color4.White, 120, Easing.InOutQuint); if (e.NewValue) diff --git a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs index fb524e32c3..7e33d7ba27 100644 --- a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs @@ -9,7 +9,7 @@ namespace osu.Game.Overlays.KeyBinding { public class GlobalKeyBindingsSection : SettingsSection { - public override IconUsage Icon => FontAwesome.Globe; + public override IconUsage Icon => FontAwesome.Solid.Globe; public override string Header => "Global"; public GlobalKeyBindingsSection(GlobalActionContainer manager) diff --git a/osu.Game/Overlays/KeyBindingOverlay.cs b/osu.Game/Overlays/KeyBindingOverlay.cs index 6259f39c66..b223d4701d 100644 --- a/osu.Game/Overlays/KeyBindingOverlay.cs +++ b/osu.Game/Overlays/KeyBindingOverlay.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays Y = -15, Size = new Vector2(15), Shadow = true, - Icon = FontAwesome.ChevronLeft + Icon = FontAwesome.Solid.ChevronLeft }, new OsuSpriteText { diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 96e9cc9ca7..df37a1b2c7 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -164,7 +164,7 @@ namespace osu.Game.Overlays.Music Anchor = Anchor.TopLeft; Origin = Anchor.TopLeft; Size = new Vector2(12); - Icon = FontAwesome.Bars; + Icon = FontAwesome.Solid.Bars; Alpha = 0f; Margin = new MarginPadding { Left = 5, Top = 2 }; } diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index ce2137346f..b24c6c3508 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -148,7 +148,7 @@ namespace osu.Game.Overlays Anchor = Anchor.Centre, Origin = Anchor.Centre, Action = prev, - Icon = FontAwesome.StepBackward, + Icon = FontAwesome.Solid.StepBackward, }, playButton = new MusicIconButton { @@ -157,14 +157,14 @@ namespace osu.Game.Overlays Scale = new Vector2(1.4f), IconScale = new Vector2(1.4f), Action = play, - Icon = FontAwesome.PlayCircleOutline, + Icon = FontAwesome.Regular.PlayCircle, }, nextButton = new MusicIconButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, Action = () => next(), - Icon = FontAwesome.StepForward, + Icon = FontAwesome.Solid.StepForward, }, } }, @@ -173,7 +173,7 @@ namespace osu.Game.Overlays Origin = Anchor.Centre, Anchor = Anchor.CentreRight, Position = new Vector2(-bottom_black_area_height / 2, 0), - Icon = FontAwesome.Bars, + Icon = FontAwesome.Solid.Bars, Action = () => playlist.ToggleVisibility(), }, } @@ -264,13 +264,13 @@ namespace osu.Game.Overlays progressBar.EndTime = track.Length; progressBar.CurrentTime = track.CurrentTime; - playButton.Icon = track.IsRunning ? FontAwesome.PauseCircleOutline : FontAwesome.PlayCircleOutline; + playButton.Icon = track.IsRunning ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle; } else { progressBar.CurrentTime = 0; progressBar.EndTime = 1; - playButton.Icon = FontAwesome.PlayCircleOutline; + playButton.Icon = FontAwesome.Regular.PlayCircle; } } diff --git a/osu.Game/Overlays/Notifications/Notification.cs b/osu.Game/Overlays/Notifications/Notification.cs index 7abff9252f..522e039cdb 100644 --- a/osu.Game/Overlays/Notifications/Notification.cs +++ b/osu.Game/Overlays/Notifications/Notification.cs @@ -175,7 +175,7 @@ namespace osu.Game.Overlays.Notifications { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Icon = FontAwesome.TimesCircle, + Icon = FontAwesome.Solid.TimesCircle, Size = new Vector2(20), } }; diff --git a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs index d5993e1f79..feffb4fa66 100644 --- a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs @@ -12,7 +12,7 @@ namespace osu.Game.Overlays.Notifications { public ProgressCompletionNotification() { - Icon = FontAwesome.Check; + Icon = FontAwesome.Solid.Check; } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Notifications/SimpleNotification.cs b/osu.Game/Overlays/Notifications/SimpleNotification.cs index 26852242d2..3a3136b1ea 100644 --- a/osu.Game/Overlays/Notifications/SimpleNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleNotification.cs @@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Notifications } } - private IconUsage icon = FontAwesome.InfoCircle; + private IconUsage icon = FontAwesome.Solid.InfoCircle; public IconUsage Icon { diff --git a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs index 7b07617e2e..5c9126dbe0 100644 --- a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs @@ -50,7 +50,7 @@ namespace osu.Game.Overlays.Profile.Header Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.Heart, + Icon = FontAwesome.Solid.Heart, Scale = new Vector2(0.45f), } }; diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 28877c21f0..138e522cd7 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -415,16 +415,16 @@ namespace osu.Game.Overlays.Profile websiteWithoutProtcol = websiteWithoutProtcol.Substring(protocolIndex + 2); } - tryAddInfoRightLine(FontAwesome.MapMarker, user.Location); - tryAddInfoRightLine(FontAwesome.HeartOutline, user.Interests); - tryAddInfoRightLine(FontAwesome.Suitcase, user.Occupation); + tryAddInfoRightLine(FontAwesome.Solid.MapMarker, user.Location); + tryAddInfoRightLine(FontAwesome.Regular.Heart, user.Interests); + tryAddInfoRightLine(FontAwesome.Solid.Suitcase, user.Occupation); infoTextRight.NewParagraph(); if (!string.IsNullOrEmpty(user.Twitter)) - tryAddInfoRightLine(FontAwesome.Twitter, "@" + user.Twitter, $@"https://twitter.com/{user.Twitter}"); - tryAddInfoRightLine(FontAwesome.Gamepad, user.Discord); - tryAddInfoRightLine(FontAwesome.Skype, user.Skype, @"skype:" + user.Skype + @"?chat"); - tryAddInfoRightLine(FontAwesome.Lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); - tryAddInfoRightLine(FontAwesome.Globe, websiteWithoutProtcol, user.Website); + tryAddInfoRightLine(FontAwesome.Brands.Twitter, "@" + user.Twitter, $@"https://twitter.com/{user.Twitter}"); + tryAddInfoRightLine(FontAwesome.Solid.Gamepad, user.Discord); + tryAddInfoRightLine(FontAwesome.Brands.Skype, user.Skype, @"skype:" + user.Skype + @"?chat"); + tryAddInfoRightLine(FontAwesome.Brands.Lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); + tryAddInfoRightLine(FontAwesome.Solid.Globe, websiteWithoutProtcol, user.Website); if (user.Statistics != null) { diff --git a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs b/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs index 48be91ea23..0808cc8fcc 100644 --- a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs +++ b/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs @@ -37,8 +37,8 @@ namespace osu.Game.Overlays.SearchableList Direction = FillDirection.Horizontal, Children = new[] { - new DisplayStyleToggleButton(FontAwesome.ThLarge, PanelDisplayStyle.Grid, DisplayStyle), - new DisplayStyleToggleButton(FontAwesome.ListUl, PanelDisplayStyle.List, DisplayStyle), + new DisplayStyleToggleButton(FontAwesome.Solid.ThLarge, PanelDisplayStyle.Grid, DisplayStyle), + new DisplayStyleToggleButton(FontAwesome.Solid.ListUl, PanelDisplayStyle.List, DisplayStyle), }, }, Dropdown = new SlimEnumDropdown diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index ea7011ea01..772f5c2039 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.cs @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Settings.Sections public class AudioSection : SettingsSection { public override string Header => "Audio"; - public override IconUsage Icon => FontAwesome.VolumeUp; + public override IconUsage Icon => FontAwesome.Solid.VolumeUp; public AudioSection() { diff --git a/osu.Game/Overlays/Settings/Sections/DebugSection.cs b/osu.Game/Overlays/Settings/Sections/DebugSection.cs index d90bb9be10..0149cab802 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSection.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSection.cs @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Settings.Sections public class DebugSection : SettingsSection { public override string Header => "Debug"; - public override IconUsage Icon => FontAwesome.Bug; + public override IconUsage Icon => FontAwesome.Solid.Bug; public DebugSection() { diff --git a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs index e69a19b447..97d9d3c697 100644 --- a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs +++ b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Settings.Sections public class GameplaySection : SettingsSection { public override string Header => "Gameplay"; - public override IconUsage Icon => FontAwesome.CircleOutline; + public override IconUsage Icon => FontAwesome.Regular.Circle; public GameplaySection() { diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 078c01ce92..e4ddc53e17 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -363,7 +363,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Icon = FontAwesome.CircleOutline, + Icon = FontAwesome.Regular.Circle, Size = new Vector2(14), }); diff --git a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs index f571d5ff7c..d9947f16cc 100644 --- a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Settings.Sections public class GeneralSection : SettingsSection { public override string Header => "General"; - public override IconUsage Icon => FontAwesome.Gear; + public override IconUsage Icon => FontAwesome.Solid.Cog; public GeneralSection() { diff --git a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs index 92746d5117..3d6086d3ea 100644 --- a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Settings.Sections public class GraphicsSection : SettingsSection { public override string Header => "Graphics"; - public override IconUsage Icon => FontAwesome.Laptop; + public override IconUsage Icon => FontAwesome.Solid.Laptop; public GraphicsSection() { diff --git a/osu.Game/Overlays/Settings/Sections/InputSection.cs b/osu.Game/Overlays/Settings/Sections/InputSection.cs index d193277a6b..6a3f8783b0 100644 --- a/osu.Game/Overlays/Settings/Sections/InputSection.cs +++ b/osu.Game/Overlays/Settings/Sections/InputSection.cs @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Settings.Sections public class InputSection : SettingsSection { public override string Header => "Input"; - public override IconUsage Icon => FontAwesome.KeyboardOutline; + public override IconUsage Icon => FontAwesome.Regular.Keyboard; public InputSection(KeyBindingOverlay keyConfig) { diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs index 7ab3629e12..a124501454 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { BodyText = "Everything?"; - Icon = FontAwesome.TrashOutline; + Icon = FontAwesome.Regular.TrashAlt; HeaderText = @"Confirm deletion of"; Buttons = new PopupDialogButton[] { diff --git a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs index 41530e20ca..0f3acd5b7f 100644 --- a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs +++ b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs @@ -11,7 +11,7 @@ namespace osu.Game.Overlays.Settings.Sections public class MaintenanceSection : SettingsSection { public override string Header => "Maintenance"; - public override IconUsage Icon => FontAwesome.Wrench; + public override IconUsage Icon => FontAwesome.Solid.Wrench; public MaintenanceSection() { diff --git a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs index f9f5d99c84..80295690c0 100644 --- a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs +++ b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Settings.Sections public class OnlineSection : SettingsSection { public override string Header => "Online"; - public override IconUsage Icon => FontAwesome.Globe; + public override IconUsage Icon => FontAwesome.Solid.GlobeAsia; public OnlineSection() { diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 79b9076a52..100022bd13 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Settings.Sections public override string Header => "Skin"; - public override IconUsage Icon => FontAwesome.PaintBrush; + public override IconUsage Icon => FontAwesome.Solid.PaintBrush; private readonly Bindable dropdownBindable = new Bindable { Default = SkinInfo.Default }; private readonly Bindable configBindable = new Bindable(); diff --git a/osu.Game/Overlays/Social/Header.cs b/osu.Game/Overlays/Social/Header.cs index bf07c343e6..22bca9b421 100644 --- a/osu.Game/Overlays/Social/Header.cs +++ b/osu.Game/Overlays/Social/Header.cs @@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Social protected override Color4 BackgroundColour => OsuColour.FromHex(@"38202e"); protected override SocialTab DefaultTab => SocialTab.AllPlayers; - protected override IconUsage Icon => FontAwesome.Users; + protected override IconUsage Icon => FontAwesome.Solid.Users; protected override Drawable CreateHeaderText() { diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 59d7a18a34..a7f2a0e8d0 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays.Toolbar new ToolbarMusicButton(), //new ToolbarButton //{ - // Icon = FontAwesome.search + // Icon = FontAwesome.Solid.search //}, userButton = new ToolbarUserButton(), new ToolbarNotificationButton(), diff --git a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs index 8ea21e88b5..ad0e5be551 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Toolbar { public ToolbarChatButton() { - SetIcon(FontAwesome.Comments); + SetIcon(FontAwesome.Solid.Comments); } [BackgroundDependencyLoader(true)] diff --git a/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs index 18a116127c..6f5e703a66 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs @@ -9,7 +9,7 @@ namespace osu.Game.Overlays.Toolbar { public ToolbarHomeButton() { - Icon = FontAwesome.Home; + Icon = FontAwesome.Solid.Home; TooltipMain = "Home"; TooltipSub = "Return to the main menu"; } diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index 7f4c9d455e..f03df2ed93 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Toolbar { public ToolbarMusicButton() { - Icon = FontAwesome.Music; + Icon = FontAwesome.Solid.Music; } [BackgroundDependencyLoader(true)] diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index b3bd82ae38..dbd6c557d3 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Toolbar public ToolbarNotificationButton() { - Icon = FontAwesome.Bars; + Icon = FontAwesome.Solid.Bars; TooltipMain = "Notifications"; TooltipSub = "Waiting for 'ya"; diff --git a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs index 4e48ffd034..08f8f867fd 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Toolbar { public ToolbarSettingsButton() { - Icon = FontAwesome.Gear; + Icon = FontAwesome.Solid.Cog; TooltipMain = "Settings"; TooltipSub = "Change your settings"; } diff --git a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs index 769fa520cb..5e353d3319 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Toolbar { public ToolbarSocialButton() { - Icon = FontAwesome.Users; + Icon = FontAwesome.Solid.Users; } [BackgroundDependencyLoader(true)] diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index 090e443a0c..2b1f78243b 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.cs @@ -72,7 +72,7 @@ namespace osu.Game.Overlays.Volume Current.ValueChanged += muted => { - icon.Icon = muted.NewValue ? FontAwesome.VolumeOff : FontAwesome.VolumeUp; + icon.Icon = muted.NewValue ? FontAwesome.Solid.VolumeOff : FontAwesome.Solid.VolumeUp; icon.Margin = new MarginPadding { Left = muted.NewValue ? width / 2 - 15 : width / 2 - 10 }; //Magic numbers to line up both icons because they're different widths }; Current.TriggerChange(); diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index be2ff33730..d2d0a5bb26 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Mods /// The icon of this mod. /// [JsonIgnore] - public virtual IconUsage Icon => FontAwesome.Question; + public virtual IconUsage Icon => FontAwesome.Solid.Question; /// /// The type of this mod. diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index 0dd5d7b815..7e6d959119 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mods { public override string Name => "Daycore"; public override string Acronym => "DC"; - public override IconUsage Icon => FontAwesome.Question; + public override IconUsage Icon => FontAwesome.Solid.Question; public override string Description => "Whoaaaaa..."; public override void ApplyToClock(IAdjustableClock clock) diff --git a/osu.Game/Rulesets/Mods/ModWindDown.cs b/osu.Game/Rulesets/Mods/ModWindDown.cs index eccd848c48..5d71c8950b 100644 --- a/osu.Game/Rulesets/Mods/ModWindDown.cs +++ b/osu.Game/Rulesets/Mods/ModWindDown.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mods public override string Name => "Wind Down"; public override string Acronym => "WD"; public override string Description => "Sloooow doooown..."; - public override IconUsage Icon => FontAwesome.ChevronCircleDown; + public override IconUsage Icon => FontAwesome.Solid.ChevronCircleDown; public override double ScoreMultiplier => 1.0; protected override double FinalRateAdjustment => -0.25; diff --git a/osu.Game/Rulesets/Mods/ModWindUp.cs b/osu.Game/Rulesets/Mods/ModWindUp.cs index d430c291cb..aae85cec19 100644 --- a/osu.Game/Rulesets/Mods/ModWindUp.cs +++ b/osu.Game/Rulesets/Mods/ModWindUp.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mods public override string Name => "Wind Up"; public override string Acronym => "WU"; public override string Description => "Can you keep up?"; - public override IconUsage Icon => FontAwesome.ChevronCircleUp; + public override IconUsage Icon => FontAwesome.Solid.ChevronCircleUp; public override double ScoreMultiplier => 1.0; protected override double FinalRateAdjustment => 0.5; diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 013fffb7cb..cdfe02b60b 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets public virtual HitObjectComposer CreateHitObjectComposer() => null; - public virtual Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.QuestionCircle }; + public virtual Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.Solid.QuestionCircle }; public abstract string Description { get; } diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 6d590780b0..f5c9f74f62 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.Edit.Components Origin = Anchor.Centre, Scale = new Vector2(1.4f), IconScale = new Vector2(1.4f), - Icon = FontAwesome.PlayCircleOutline, + Icon = FontAwesome.Regular.PlayCircle, Action = togglePause, Padding = new MarginPadding { Left = 20 } }, @@ -89,7 +89,7 @@ namespace osu.Game.Screens.Edit.Components { base.Update(); - playButton.Icon = adjustableClock.IsRunning ? FontAwesome.PauseCircleOutline : FontAwesome.PlayCircleOutline; + playButton.Icon = adjustableClock.IsRunning ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle; } private class PlaybackTabControl : OsuTabControl diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 1f13797497..9a7ac8dfd0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -94,13 +94,13 @@ namespace osu.Game.Screens.Edit.Compose.Components { new DivisorButton { - Icon = FontAwesome.ChevronLeft, + Icon = FontAwesome.Solid.ChevronLeft, Action = beatDivisor.Previous }, new DivisorText(beatDivisor), new DivisorButton { - Icon = FontAwesome.ChevronRight, + Icon = FontAwesome.Solid.ChevronRight, Action = beatDivisor.Next } }, diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 2bed231da7..863a120fc3 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -91,7 +91,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { RelativeSizeAxes = Axes.Y, Height = 0.5f, - Icon = FontAwesome.SearchPlus, + Icon = FontAwesome.Solid.SearchPlus, Action = () => changeZoom(1) }, new TimelineButton @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.Y, Height = 0.5f, - Icon = FontAwesome.SearchMinus, + Icon = FontAwesome.Solid.SearchMinus, Action = () => changeZoom(-1) }, } diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index bcd24fd83e..d3cf23dab8 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -80,7 +80,7 @@ namespace osu.Game.Screens.Menu buttonArea.AddRange(new[] { - new Button(@"settings", string.Empty, FontAwesome.Gear, new Color4(85, 85, 85, 255), () => OnSettings?.Invoke(), -WEDGE_WIDTH, Key.O), + new Button(@"settings", string.Empty, FontAwesome.Solid.Cog, new Color4(85, 85, 85, 255), () => OnSettings?.Invoke(), -WEDGE_WIDTH, Key.O), backButton = new Button(@"back", @"button-back-select", OsuIcon.LeftCircle, new Color4(51, 58, 94, 255), () => State = ButtonSystemState.TopLevel, -WEDGE_WIDTH) { VisibleState = ButtonSystemState.Play, @@ -106,8 +106,8 @@ namespace osu.Game.Screens.Menu [BackgroundDependencyLoader(true)] private void load(AudioManager audio, IdleTracker idleTracker, GameHost host) { - buttonsPlay.Add(new Button(@"solo", @"button-solo-select", FontAwesome.User, new Color4(102, 68, 204, 255), () => OnSolo?.Invoke(), WEDGE_WIDTH, Key.P)); - buttonsPlay.Add(new Button(@"multi", @"button-generic-select", FontAwesome.Users, new Color4(94, 63, 186, 255), onMulti, 0, Key.M)); + buttonsPlay.Add(new Button(@"solo", @"button-solo-select", FontAwesome.Solid.User, new Color4(102, 68, 204, 255), () => OnSolo?.Invoke(), WEDGE_WIDTH, Key.P)); + buttonsPlay.Add(new Button(@"multi", @"button-generic-select", FontAwesome.Solid.Users, new Color4(94, 63, 186, 255), onMulti, 0, Key.M)); buttonsPlay.Add(new Button(@"chart", @"button-generic-select", OsuIcon.Charts, new Color4(80, 53, 160, 255), () => OnChart?.Invoke())); buttonsPlay.ForEach(b => b.VisibleState = ButtonSystemState.Play); @@ -135,7 +135,7 @@ namespace osu.Game.Screens.Menu notifications?.Post(new SimpleNotification { Text = "You gotta be logged in to multi 'yo!", - Icon = FontAwesome.Globe + Icon = FontAwesome.Solid.Globe }); return; diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index 170209207b..0130a5143b 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -54,7 +54,7 @@ namespace osu.Game.Screens.Menu { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Icon = FontAwesome.Warning, + Icon = FontAwesome.Solid.ExclamationTriangle, Size = new Vector2(icon_size), Y = icon_y, }, @@ -128,7 +128,7 @@ namespace osu.Game.Screens.Menu supportFlow.AddText(" to help support the game", format); } - heart = supportFlow.AddIcon(FontAwesome.Heart, t => + heart = supportFlow.AddIcon(FontAwesome.Solid.Heart, t => { t.Padding = new MarginPadding { Left = 5 }; t.Font = t.Font.With(size: 12); diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs index 2734c55ce7..92074abe4b 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs @@ -25,9 +25,9 @@ namespace osu.Game.Screens.Multi.Match.Components protected override IEnumerable GetStatistics(ScoreInfo model) => new[] { - new LeaderboardScoreStatistic(FontAwesome.Crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy)), - new LeaderboardScoreStatistic(FontAwesome.Refresh, "Total Attempts", ((APIRoomScoreInfo)model).TotalAttempts.ToString()), - new LeaderboardScoreStatistic(FontAwesome.Check, "Completed Beatmaps", ((APIRoomScoreInfo)model).CompletedBeatmaps.ToString()), + 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()), }; } } diff --git a/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs b/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs index b03fafbd13..dcfad8458f 100644 --- a/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs +++ b/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Multi.Ranking.Types this.beatmap = beatmap; } - public IconUsage Icon => FontAwesome.Users; + public IconUsage Icon => FontAwesome.Solid.Users; public string Name => "Room Leaderboard"; diff --git a/osu.Game/Screens/Play/Break/BreakArrows.cs b/osu.Game/Screens/Play/Break/BreakArrows.cs index e0238f6814..4b96fa666a 100644 --- a/osu.Game/Screens/Play/Break/BreakArrows.cs +++ b/osu.Game/Screens/Play/Break/BreakArrows.cs @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Play.Break Anchor = Anchor.Centre, Origin = Anchor.CentreRight, X = -glow_icon_offscreen_offset, - Icon = FontAwesome.ChevronRight, + Icon = FontAwesome.Solid.ChevronRight, BlurSigma = new Vector2(glow_icon_blur_sigma), Size = new Vector2(glow_icon_size), }, @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Play.Break Anchor = Anchor.Centre, Origin = Anchor.CentreLeft, X = glow_icon_offscreen_offset, - Icon = FontAwesome.ChevronLeft, + Icon = FontAwesome.Solid.ChevronLeft, BlurSigma = new Vector2(glow_icon_blur_sigma), Size = new Vector2(glow_icon_size), }, @@ -68,7 +68,7 @@ namespace osu.Game.Screens.Play.Break Origin = Anchor.CentreRight, Alpha = 0.7f, X = -blurred_icon_offscreen_offset, - Icon = FontAwesome.ChevronRight, + Icon = FontAwesome.Solid.ChevronRight, BlurSigma = new Vector2(blurred_icon_blur_sigma), Size = new Vector2(blurred_icon_size), }, @@ -78,7 +78,7 @@ namespace osu.Game.Screens.Play.Break Origin = Anchor.CentreLeft, Alpha = 0.7f, X = blurred_icon_offscreen_offset, - Icon = FontAwesome.ChevronLeft, + Icon = FontAwesome.Solid.ChevronLeft, BlurSigma = new Vector2(blurred_icon_blur_sigma), Size = new Vector2(blurred_icon_size), }, diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 03843eeb90..6883f246e4 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -129,7 +129,7 @@ namespace osu.Game.Screens.Play.HUD Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(15), - Icon = FontAwesome.Close + Icon = FontAwesome.Solid.TimesCircle }, } }; diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs index d243ff24a3..90424ec007 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs @@ -104,7 +104,7 @@ namespace osu.Game.Screens.Play.PlayerSettings Origin = Anchor.Centre, Anchor = Anchor.CentreRight, Position = new Vector2(-15, 0), - Icon = FontAwesome.Bars, + Icon = FontAwesome.Solid.Bars, Scale = new Vector2(0.75f), Action = () => Expanded = !Expanded, }, diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 78ed742bfa..738877232d 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -259,9 +259,9 @@ namespace osu.Game.Screens.Play Direction = FillDirection.Horizontal, Children = new[] { - new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.ChevronRight }, - new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.ChevronRight }, - new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.ChevronRight }, + new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.Solid.ChevronRight }, + new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.Solid.ChevronRight }, + new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.Solid.ChevronRight }, } }, new OsuSpriteText diff --git a/osu.Game/Screens/Ranking/Types/LocalLeaderboardPageInfo.cs b/osu.Game/Screens/Ranking/Types/LocalLeaderboardPageInfo.cs index e563eb8116..fe183c5f89 100644 --- a/osu.Game/Screens/Ranking/Types/LocalLeaderboardPageInfo.cs +++ b/osu.Game/Screens/Ranking/Types/LocalLeaderboardPageInfo.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Ranking.Types this.beatmap = beatmap; } - public IconUsage Icon => FontAwesome.User; + public IconUsage Icon => FontAwesome.Solid.User; public string Name => @"Local Leaderboard"; diff --git a/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs b/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs index 2d9b3b9ef9..424dbff6f6 100644 --- a/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs +++ b/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs @@ -10,7 +10,7 @@ namespace osu.Game.Screens.Ranking.Types { public class ScoreOverviewPageInfo : IResultPageInfo { - public IconUsage Icon => FontAwesome.Asterisk; + public IconUsage Icon => FontAwesome.Solid.Asterisk; public string Name => "Overview"; private readonly ScoreInfo score; diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index f471cab063..d6766c2b49 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -113,7 +113,7 @@ namespace osu.Game.Screens { new SpriteIcon { - Icon = FontAwesome.UniversalAccess, + Icon = FontAwesome.Solid.UniversalAccess, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Size = new Vector2(50), diff --git a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs index aa579ac665..c9b6ca7bb3 100644 --- a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs +++ b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Select public BeatmapClearScoresDialog(BeatmapInfo beatmap, Action onCompletion) { BodyText = $@"{beatmap.Metadata?.Artist} - {beatmap.Metadata?.Title}"; - Icon = FontAwesome.Eraser; + Icon = FontAwesome.Solid.Eraser; HeaderText = @"Clearing all local scores. Are you sure?"; Buttons = new PopupDialogButton[] { diff --git a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs index a1adaff1d8..5fb72e4151 100644 --- a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs +++ b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Select { BodyText = $@"{beatmap.Metadata?.Artist} - {beatmap.Metadata?.Title}"; - Icon = FontAwesome.TrashOutline; + Icon = FontAwesome.Regular.TrashAlt; HeaderText = @"Confirm deletion of"; Buttons = new PopupDialogButton[] { diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index b2e08aeefd..d32387c1d3 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -293,14 +293,14 @@ namespace osu.Game.Screens.Select labels.Add(new InfoLabel(new BeatmapStatistic { Name = "Length", - Icon = FontAwesome.ClockOutline, + Icon = FontAwesome.Regular.Clock, Content = TimeSpan.FromMilliseconds(endTime - b.HitObjects.First().StartTime).ToString(@"m\:ss"), })); labels.Add(new InfoLabel(new BeatmapStatistic { Name = "BPM", - Icon = FontAwesome.Circle, + Icon = FontAwesome.Regular.Circle, Content = getBPMRange(b), })); @@ -378,7 +378,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, Colour = OsuColour.FromHex(@"441288"), - Icon = FontAwesome.Square, + Icon = FontAwesome.Solid.Square, Rotation = 45, }, new SpriteIcon diff --git a/osu.Game/Screens/Select/ImportFromStablePopup.cs b/osu.Game/Screens/Select/ImportFromStablePopup.cs index f1cc3d632c..54e4c096f6 100644 --- a/osu.Game/Screens/Select/ImportFromStablePopup.cs +++ b/osu.Game/Screens/Select/ImportFromStablePopup.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Select HeaderText = @"You have no beatmaps!"; BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps (and skins)?"; - Icon = FontAwesome.Plane; + Icon = FontAwesome.Solid.Plane; Buttons = new PopupDialogButton[] { diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs index 0f1f49bd85..a9616ee535 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs @@ -141,7 +141,7 @@ namespace osu.Game.Screens.Select.Options Anchor = Anchor.TopCentre, Size = new Vector2(30), Shadow = true, - Icon = FontAwesome.Close, + Icon = FontAwesome.Solid.TimesCircle, Margin = new MarginPadding { Bottom = 5, diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 6a10e86198..340ceb6864 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -21,7 +21,7 @@ namespace osu.Game.Screens.Select [BackgroundDependencyLoader] private void load(OsuColour colours) { - BeatmapOptions.AddButton(@"Edit", @"beatmap", FontAwesome.Pencil, colours.Yellow, () => + BeatmapOptions.AddButton(@"Edit", @"beatmap", FontAwesome.Solid.PencilAlt, colours.Yellow, () => { ValidForResume = false; Edit(); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 9ac8e26ec0..b60e693cbf 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -228,9 +228,9 @@ namespace osu.Game.Screens.Select Footer.AddButton(@"random", colours.Green, triggerRandom, Key.F2); Footer.AddButton(@"options", colours.Blue, BeatmapOptions, Key.F3); - BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo), Key.Number4, float.MaxValue); - BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.TimesCircleOutline, colours.Purple, null, Key.Number1); - BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.Eraser, colours.Purple, () => clearScores(Beatmap.Value.BeatmapInfo), Key.Number2); + BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo), Key.Number4, float.MaxValue); + BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, colours.Purple, null, Key.Number1); + BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.Solid.Eraser, colours.Purple, () => clearScores(Beatmap.Value.BeatmapInfo), Key.Number2); } if (this.beatmaps == null) diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 1f62111a4e..e745aa54c8 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -166,7 +166,7 @@ namespace osu.Game.Users { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Icon = FontAwesome.CircleOutline, + Icon = FontAwesome.Regular.Circle, Shadow = true, Size = new Vector2(14), }, From bc1077ed73b2f237e4a52bf6aa2e13af0b310578 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Apr 2019 19:55:34 +0900 Subject: [PATCH 0447/5608] Remove remaining FontAwesome reference --- osu.Game/Graphics/OsuFont.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Graphics/OsuFont.cs b/osu.Game/Graphics/OsuFont.cs index 26112430f6..c8a736f49a 100644 --- a/osu.Game/Graphics/OsuFont.cs +++ b/osu.Game/Graphics/OsuFont.cs @@ -42,8 +42,6 @@ namespace osu.Game.Graphics { case Typeface.Exo: return "Exo2.0"; - case Typeface.FontAwesome: - return "FontAwesome"; case Typeface.Venera: return "Venera"; } @@ -101,7 +99,6 @@ namespace osu.Game.Graphics public enum Typeface { Exo, - FontAwesome, Venera, } From bcd51afea1686f874b120cc043906d3d32ecf021 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Apr 2019 19:55:46 +0900 Subject: [PATCH 0448/5608] Fix osu! icon font name mismatch --- osu.Game/Graphics/OsuIcon.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/OsuIcon.cs b/osu.Game/Graphics/OsuIcon.cs index 52fb31553d..982e9dacab 100644 --- a/osu.Game/Graphics/OsuIcon.cs +++ b/osu.Game/Graphics/OsuIcon.cs @@ -7,7 +7,7 @@ namespace osu.Game.Graphics { public static class OsuIcon { - public static IconUsage Get(int icon) => new IconUsage((char)icon, "OsuFont"); + public static IconUsage Get(int icon) => new IconUsage((char)icon, "osuFont"); // ruleset icons in circles public static IconUsage RulesetOsu => Get(0xe000); From 072954e4c05fd274c276dd43d361b101d510cf95 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Apr 2019 21:00:05 +0900 Subject: [PATCH 0449/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 52c53503ee..f3c648cf02 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 9ecc7d4632..7ce7329246 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From e9269dc83bb5df8db8e9bf470cf9f263ff42ee27 Mon Sep 17 00:00:00 2001 From: Samuel Van Allen Date: Tue, 2 Apr 2019 23:57:31 +0800 Subject: [PATCH 0450/5608] Prevent unnecessary query in OsuGame::PresentBeatmap This resolves issue #4575 --- osu.Game/OsuGame.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index f8ca1bc65f..9ab09d1122 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -254,6 +254,12 @@ namespace osu.Game if (menuScreen.IsCurrentScreen()) menuScreen.LoadToSolo(); + // we might even already be at the song + if (Beatmap.Value.BeatmapSetInfo.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID) + { + return; + } + // Use first beatmap available for current ruleset, else switch ruleset. var first = databasedSet.Beatmaps.Find(b => b.Ruleset == ruleset.Value) ?? databasedSet.Beatmaps.First(); From ab4be3b75f1ae455a18d21fc3609c96e9dbab00c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 3 Apr 2019 15:20:38 +0900 Subject: [PATCH 0451/5608] General refactoring --- .../TestCaseBeatmapScoresContainer.cs | 1 + .../Graphics/Containers/OsuHoverContainer.cs | 4 +- .../Scores/ClickableUserContainer.cs | 29 ++++---- .../BeatmapSet/Scores/DrawableTopScore.cs | 66 ++++++++----------- .../BeatmapSet/Scores/ScoreTableScoreRow.cs | 2 +- 5 files changed, 48 insertions(+), 54 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs index c72d12c09c..4a38f98810 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs @@ -24,6 +24,7 @@ namespace osu.Game.Tests.Visual.SongSelect { public override IReadOnlyList RequiredTypes => new[] { + typeof(DrawableTopScore), typeof(ScoresContainer), typeof(ScoreTable), typeof(ScoreTableRow), diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index 091499b7cd..880807c8b4 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -12,12 +12,12 @@ namespace osu.Game.Graphics.Containers { public class OsuHoverContainer : OsuClickableContainer { + protected const float FADE_DURATION = 500; + protected Color4 HoverColour; protected Color4 IdleColour = Color4.White; - protected const float FADE_DURATION = 500; - protected virtual IEnumerable EffectTargets => new[] { Content }; protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs index cf1c3d7fcf..2448ae17f8 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs @@ -13,6 +13,17 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { private UserProfileOverlay profile; + protected ClickableUserContainer() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader(true)] + private void load(UserProfileOverlay profile) + { + this.profile = profile; + } + private User user; public User User @@ -20,26 +31,16 @@ namespace osu.Game.Overlays.BeatmapSet.Scores get => user; set { - if (user == value) return; + if (user == value) + return; user = value; - OnUserChange(user); + OnUserChanged(user); } } - protected ClickableUserContainer() - { - AutoSizeAxes = Axes.Both; - } - - protected abstract void OnUserChange(User user); - - [BackgroundDependencyLoader(true)] - private void load(UserProfileOverlay profile) - { - this.profile = profile; - } + protected abstract void OnUserChanged(User user); protected override bool OnClick(ClickEvent e) { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 82905d065e..e3141624b5 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -19,6 +19,7 @@ using osu.Game.Users; using osuTK; using osuTK.Graphics; using System.Collections.Generic; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -164,7 +165,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - TextSize = 20, }, date = new SpriteText { @@ -263,67 +263,59 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { private const float username_fade_duration = 500; - private readonly Box underscore; - private readonly Container underscoreContainer; - private readonly SpriteText text; + private readonly FillFlowContainer hoverContainer; - private Color4 hoverColour; - - public float TextSize - { - set - { - if (text.TextSize == value) - return; - - text.TextSize = value; - } - get => text.TextSize; - } + private readonly SpriteText normalText; + private readonly SpriteText hoveredText; public ClickableTopScoreUsername() { - Add(underscoreContainer = new Container + var font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold, italics: true); + + Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, - Height = 1, - Child = underscore = new Box + normalText = new OsuSpriteText { Font = font }, + hoverContainer = new FillFlowContainer { - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Alpha = 0, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 1), + Children = new Drawable[] + { + hoveredText = new OsuSpriteText { Font = font }, + new Box + { + BypassAutoSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + Height = 1 + } + } } - }); - Add(text = new SpriteText - { - Font = @"Exo2.0-BoldItalic", - }); + }; } [BackgroundDependencyLoader] private void load(OsuColour colours) { - hoverColour = underscore.Colour = colours.Blue; - underscoreContainer.Position = new Vector2(0, TextSize / 2 - 1); + hoverContainer.Colour = colours.Blue; } - protected override void OnUserChange(User user) + protected override void OnUserChanged(User user) { - text.Text = user.Username; + normalText.Text = hoveredText.Text = user.Username; } protected override bool OnHover(HoverEvent e) { - text.FadeColour(hoverColour, username_fade_duration, Easing.OutQuint); - underscore.FadeIn(username_fade_duration, Easing.OutQuint); + hoverContainer.FadeIn(username_fade_duration, Easing.OutQuint); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - text.FadeColour(Color4.White, username_fade_duration, Easing.OutQuint); - underscore.FadeOut(username_fade_duration, Easing.OutQuint); + hoverContainer.FadeOut(username_fade_duration, Easing.OutQuint); base.OnHoverLost(e); } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs index cd1ade934a..a0c6db9a56 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs @@ -145,7 +145,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }); } - protected override void OnUserChange(User user) + protected override void OnUserChanged(User user) { text.Text = textBold.Text = user.Username; } From 1dad1523632352769cfab479de52af7609c0e1b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Apr 2019 15:37:22 +0900 Subject: [PATCH 0452/5608] Correctly handle nvika/inspectcode return codes --- build/build.cake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build/build.cake b/build/build.cake index 81deeb3bc7..3269bbf1c0 100644 --- a/build/build.cake +++ b/build/build.cake @@ -46,7 +46,9 @@ Task("InspectCode") OutputFile = "inspectcodereport.xml", }); - StartProcess(nVikaToolPath, @"parsereport ""inspectcodereport.xml"" --treatwarningsaserrors"); + int returnCode = StartProcess(nVikaToolPath, $@"parsereport ""{inspectcodereport}"" --treatwarningsaserrors"); + if (returnCode != 0) + throw new Exception($"inspectcode failed with return code {returnCode}"); }); Task("CodeFileSanity") From 7f425059aecbc83a0f8b12873fd95f789c8c5858 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 3 Apr 2019 15:41:22 +0900 Subject: [PATCH 0453/5608] Adjust transforms --- .../Overlays/BeatmapSet/Scores/DrawableTopScore.cs | 2 +- .../BeatmapSet/Scores/ScoreTableScoreRow.cs | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index e3141624b5..3bcb44ab94 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -261,7 +261,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private class ClickableTopScoreUsername : ClickableUserContainer { - private const float username_fade_duration = 500; + private const float username_fade_duration = 150; private readonly FillFlowContainer hoverContainer; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs index a0c6db9a56..83901cc662 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs @@ -145,22 +145,19 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }); } - protected override void OnUserChanged(User user) - { - text.Text = textBold.Text = user.Username; - } + protected override void OnUserChanged(User user) => text.Text = textBold.Text = user.Username; protected override bool OnHover(HoverEvent e) { - textBold.FadeIn(fade_duration, Easing.OutQuint); - text.FadeOut(fade_duration, Easing.OutQuint); + textBold.Show(); + text.Hide(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - textBold.FadeOut(fade_duration, Easing.OutQuint); - text.FadeIn(fade_duration, Easing.OutQuint); + textBold.Hide(); + text.Show(); base.OnHoverLost(e); } } From dff58ab4edb52c2faec7eb241b6b50602cd1d432 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 3 Apr 2019 15:41:33 +0900 Subject: [PATCH 0454/5608] Initial cleanup pass of DrawableTopScore --- .../BeatmapSet/Scores/DrawableTopScore.cs | 201 +++++++----------- 1 file changed, 72 insertions(+), 129 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 3bcb44ab94..66ef2a30a3 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -43,15 +43,14 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly SpriteText date; private readonly DrawableRank rank; - private readonly AutoSizedInfoColumn totalScore; - private readonly AutoSizedInfoColumn accuracy; - private readonly MediumInfoColumn maxCombo; - - private readonly SmallInfoColumn hitGreat; - private readonly SmallInfoColumn hitGood; - private readonly SmallInfoColumn hitMeh; - private readonly SmallInfoColumn hitMiss; - private readonly SmallInfoColumn pp; + private readonly SpriteText totalScoreText; + private readonly SpriteText accuracyText; + private readonly SpriteText maxComboText; + private readonly SpriteText hitGreatText; + private readonly SpriteText hitGoodText; + private readonly SpriteText hitMehText; + private readonly SpriteText hitMissText; + private readonly SpriteText ppText; private readonly ModsInfoColumn modsInfo; @@ -72,17 +71,16 @@ namespace osu.Game.Overlays.BeatmapSet.Scores date.Text = $@"achieved {score.Date.Humanize()}"; rank.UpdateRank(score.Rank); - totalScore.Value = $@"{score.TotalScore:N0}"; - accuracy.Value = $@"{score.Accuracy:P2}"; - maxCombo.Value = $@"{score.MaxCombo:N0}x"; + totalScoreText.Text = $@"{score.TotalScore:N0}"; + accuracyText.Text = $@"{score.Accuracy:P2}"; + maxComboText.Text = $@"{score.MaxCombo:N0}x"; - hitGreat.Value = $"{score.Statistics[HitResult.Great]}"; - hitGood.Value = $"{score.Statistics[HitResult.Good]}"; - hitMeh.Value = $"{score.Statistics[HitResult.Meh]}"; - hitMiss.Value = $"{score.Statistics[HitResult.Miss]}"; - pp.Value = $@"{score.PP:N0}"; + hitGreatText.Text = $"{score.Statistics[HitResult.Great]}"; + hitGoodText.Text = $"{score.Statistics[HitResult.Good]}"; + hitMehText.Text = $"{score.Statistics[HitResult.Meh]}"; + hitMissText.Text = $"{score.Statistics[HitResult.Miss]}"; + ppText.Text = $@"{score.PP:N0}"; - modsInfo.ClearMods(); modsInfo.Mods = score.Mods; } } @@ -91,8 +89,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - CornerRadius = 10; + Masking = true; + CornerRadius = 10; EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, @@ -100,6 +99,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Radius = 1, Offset = new Vector2(0, 1), }; + + var smallFont = OsuFont.GetFont(size: 20); + var largeFont = OsuFont.GetFont(size: 25); + Children = new Drawable[] { background = new Box @@ -208,12 +211,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(margin, 0), Children = new Drawable[] { - hitGreat = new SmallInfoColumn("300", 20), - hitGood = new SmallInfoColumn("100", 20), - hitMeh = new SmallInfoColumn("50", 20), - hitMiss = new SmallInfoColumn("misses", 20), - pp = new SmallInfoColumn("pp", 20), - modsInfo = new ModsInfoColumn("mods"), + new InfoColumn("300", hitGreatText = new OsuSpriteText { Font = smallFont }), + new InfoColumn("100", hitGoodText = new OsuSpriteText { Font = smallFont }), + new InfoColumn("50", hitMehText = new OsuSpriteText { Font = smallFont }), + new InfoColumn("misses", hitMissText = new OsuSpriteText { Font = smallFont }), + new InfoColumn("pp", ppText = new OsuSpriteText { Font = smallFont }), + modsInfo = new ModsInfoColumn(), } }, new FillFlowContainer @@ -225,9 +228,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(margin, 0), Children = new Drawable[] { - totalScore = new AutoSizedInfoColumn("Total Score"), - accuracy = new AutoSizedInfoColumn("Accuracy"), - maxCombo = new MediumInfoColumn("Max Combo"), + new InfoColumn("total score", totalScoreText = new OsuSpriteText { Font = largeFont }), + new InfoColumn("accuracy", accuracyText = new OsuSpriteText { Font = largeFont }), + new InfoColumn("max combo", maxComboText = new OsuSpriteText { Font = largeFont }) } }, } @@ -302,10 +305,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores hoverContainer.Colour = colours.Blue; } - protected override void OnUserChanged(User user) - { - normalText.Text = hoveredText.Text = user.Username; - } + protected override void OnUserChanged(User user) => normalText.Text = hoveredText.Text = user.Username; protected override bool OnHover(HoverEvent e) { @@ -320,38 +320,32 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } - private class DrawableInfoColumn : FillFlowContainer + private class InfoColumn : CompositeDrawable { - private const float header_text_size = 12; + private readonly Box separator; - private readonly Box line; - - protected DrawableInfoColumn(string header) + public InfoColumn(string title, Drawable content) { - AutoSizeAxes = Axes.Y; - Direction = FillDirection.Vertical; - Spacing = new Vector2(0, 2); - Children = new Drawable[] + AutoSizeAxes = Axes.Both; + + InternalChild = new FillFlowContainer { - new Container + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 2), + Children = new[] { - AutoSizeAxes = Axes.X, - Height = header_text_size, - Child = new SpriteText + new OsuSpriteText { - TextSize = 12, - Text = header.ToUpper(), - Font = @"Exo2.0-Black", - } - }, - new Container - { - RelativeSizeAxes = Axes.X, - Height = 2, - Child = line = new Box + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black), + Text = title.ToUpper() + }, + separator = new Box { - RelativeSizeAxes = Axes.Both, - } + RelativeSizeAxes = Axes.X, + Height = 2 + }, + content } }; } @@ -359,96 +353,45 @@ namespace osu.Game.Overlays.BeatmapSet.Scores [BackgroundDependencyLoader] private void load(OsuColour colours) { - line.Colour = colours.Gray5; + separator.Colour = colours.Gray5; } } - private class ModsInfoColumn : DrawableInfoColumn + private class ModsInfoColumn : InfoColumn { private readonly FillFlowContainer modsContainer; + public ModsInfoColumn() + : this(new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal + }) + { + } + + private ModsInfoColumn(FillFlowContainer modsContainer) + : base("mods", modsContainer) + { + this.modsContainer = modsContainer; + } + public IEnumerable Mods { set { + modsContainer.Clear(); + foreach (Mod mod in value) + { modsContainer.Add(new ModIcon(mod) { AutoSizeAxes = Axes.Both, Scale = new Vector2(0.3f), }); + } } } - - public ModsInfoColumn(string header) - : base(header) - { - AutoSizeAxes = Axes.Both; - Add(modsContainer = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - }); - } - - public void ClearMods() => modsContainer.Clear(); - } - - private class TextInfoColumn : DrawableInfoColumn - { - private readonly SpriteText valueText; - - public string Value - { - set - { - if (valueText.Text == value) - return; - - valueText.Text = value; - } - get => valueText.Text; - } - - protected TextInfoColumn(string header, float valueTextSize = 25) - : base(header) - { - Add(valueText = new SpriteText - { - TextSize = valueTextSize, - }); - } - } - - private class AutoSizedInfoColumn : TextInfoColumn - { - public AutoSizedInfoColumn(string header, float valueTextSize = 25) - : base(header, valueTextSize) - { - AutoSizeAxes = Axes.Both; - } - } - - private class MediumInfoColumn : TextInfoColumn - { - private const float width = 70; - - public MediumInfoColumn(string header, float valueTextSize = 25) - : base(header, valueTextSize) - { - Width = width; - } - } - - private class SmallInfoColumn : TextInfoColumn - { - private const float width = 40; - - public SmallInfoColumn(string header, float valueTextSize = 25) - : base(header, valueTextSize) - { - Width = width; - } } } } From f8d53a1e30b2f3471ac7712983dc8af703a79272 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Apr 2019 15:43:36 +0900 Subject: [PATCH 0455/5608] Fix variable mismatch --- build/build.cake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/build.cake b/build/build.cake index 3269bbf1c0..f1b7fa4036 100644 --- a/build/build.cake +++ b/build/build.cake @@ -46,7 +46,7 @@ Task("InspectCode") OutputFile = "inspectcodereport.xml", }); - int returnCode = StartProcess(nVikaToolPath, $@"parsereport ""{inspectcodereport}"" --treatwarningsaserrors"); + int returnCode = StartProcess(nVikaToolPath, $@"parsereport ""inspectcodereport.xml"" --treatwarningsaserrors"); if (returnCode != 0) throw new Exception($"inspectcode failed with return code {returnCode}"); }); From 542a46b0a7675cc9b4676cdceeb1326257217261 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Apr 2019 15:43:48 +0900 Subject: [PATCH 0456/5608] Update r# version --- build/build.cake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/build.cake b/build/build.cake index f1b7fa4036..de94eb7ab3 100644 --- a/build/build.cake +++ b/build/build.cake @@ -1,5 +1,5 @@ #addin "nuget:?package=CodeFileSanity&version=0.0.21" -#addin "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2018.2.2" +#addin "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2018.3.4" #tool "nuget:?package=NVika.MSBuild&version=1.0.1" var nVikaToolPath = GetFiles("./tools/NVika.MSBuild.*/tools/NVika.exe").First(); From 0cf27e244d4948d9425cdfe18941800a96d5226e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 3 Apr 2019 15:44:14 +0900 Subject: [PATCH 0457/5608] Fix usages of SpriteText and obsolete members --- osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 66ef2a30a3..6e5104b137 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -125,13 +125,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(margin, 0), Children = new Drawable[] { - rankText = new SpriteText + rankText = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = "#1", - TextSize = 30, - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true) }, rank = new DrawableRank(ScoreRank.F) { @@ -173,8 +172,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - TextSize = 15, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold) }, flag = new DrawableFlag { From d6b15f040a7b7cab448905b4b9d562105c8ff3c1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 3 Apr 2019 15:57:36 +0900 Subject: [PATCH 0458/5608] Improve statistics display --- .../BeatmapSet/Scores/DrawableTopScore.cs | 78 ++++++++++++------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 6e5104b137..052eaf60e5 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -12,13 +12,15 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Online.Leaderboards; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Users; using osuTK; using osuTK.Graphics; using System.Collections.Generic; +using System.Linq; +using osu.Framework.Extensions; +using osu.Framework.Localisation; using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet.Scores @@ -26,7 +28,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public class DrawableTopScore : Container { private const float fade_duration = 100; - private const float height = 100; private const float avatar_size = 80; private const float margin = 10; @@ -35,6 +36,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private Color4 backgroundIdleColour => colours.Gray3; private Color4 backgroundHoveredColour => colours.Gray4; + private readonly FontUsage smallStatisticsFont = OsuFont.GetFont(size: 20); + private readonly FontUsage largeStatisticsFont = OsuFont.GetFont(size: 25); + private readonly Box background; private readonly UpdateableAvatar avatar; private readonly DrawableFlag flag; @@ -43,14 +47,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly SpriteText date; private readonly DrawableRank rank; - private readonly SpriteText totalScoreText; - private readonly SpriteText accuracyText; - private readonly SpriteText maxComboText; - private readonly SpriteText hitGreatText; - private readonly SpriteText hitGoodText; - private readonly SpriteText hitMehText; - private readonly SpriteText hitMissText; - private readonly SpriteText ppText; + private readonly FillFlowContainer statisticsContainer; + + private readonly TextColumn totalScoreColumn; + private readonly TextColumn accuracyColumn; + private readonly TextColumn maxComboColumn; + private readonly TextColumn ppColumn; private readonly ModsInfoColumn modsInfo; @@ -71,15 +73,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores date.Text = $@"achieved {score.Date.Humanize()}"; rank.UpdateRank(score.Rank); - totalScoreText.Text = $@"{score.TotalScore:N0}"; - accuracyText.Text = $@"{score.Accuracy:P2}"; - maxComboText.Text = $@"{score.MaxCombo:N0}x"; + totalScoreColumn.Text = $@"{score.TotalScore:N0}"; + accuracyColumn.Text = $@"{score.Accuracy:P2}"; + maxComboColumn.Text = $@"{score.MaxCombo:N0}x"; + ppColumn.Text = $@"{score.PP:N0}"; - hitGreatText.Text = $"{score.Statistics[HitResult.Great]}"; - hitGoodText.Text = $"{score.Statistics[HitResult.Good]}"; - hitMehText.Text = $"{score.Statistics[HitResult.Meh]}"; - hitMissText.Text = $"{score.Statistics[HitResult.Miss]}"; - ppText.Text = $@"{score.PP:N0}"; + statisticsContainer.ChildrenEnumerable = score.Statistics.Select(kvp => new TextColumn(kvp.Key.GetDescription(), smallStatisticsFont) { Text = kvp.Value.ToString() }); modsInfo.Mods = score.Mods; } @@ -100,9 +99,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Offset = new Vector2(0, 1), }; - var smallFont = OsuFont.GetFont(size: 20); - var largeFont = OsuFont.GetFont(size: 25); - Children = new Drawable[] { background = new Box @@ -209,11 +205,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(margin, 0), Children = new Drawable[] { - new InfoColumn("300", hitGreatText = new OsuSpriteText { Font = smallFont }), - new InfoColumn("100", hitGoodText = new OsuSpriteText { Font = smallFont }), - new InfoColumn("50", hitMehText = new OsuSpriteText { Font = smallFont }), - new InfoColumn("misses", hitMissText = new OsuSpriteText { Font = smallFont }), - new InfoColumn("pp", ppText = new OsuSpriteText { Font = smallFont }), + statisticsContainer = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(margin, 0), + }, + ppColumn = new TextColumn("pp", smallStatisticsFont), modsInfo = new ModsInfoColumn(), } }, @@ -226,9 +224,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(margin, 0), Children = new Drawable[] { - new InfoColumn("total score", totalScoreText = new OsuSpriteText { Font = largeFont }), - new InfoColumn("accuracy", accuracyText = new OsuSpriteText { Font = largeFont }), - new InfoColumn("max combo", maxComboText = new OsuSpriteText { Font = largeFont }) + totalScoreColumn = new TextColumn("total score", largeStatisticsFont), + accuracyColumn = new TextColumn("accuracy", largeStatisticsFont), + maxComboColumn = new TextColumn("max combo", largeStatisticsFont) } }, } @@ -355,6 +353,28 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } + private class TextColumn : InfoColumn + { + private readonly SpriteText text; + + public TextColumn(string title, FontUsage font) + : this(title, new OsuSpriteText { Font = font }) + { + } + + private TextColumn(string title, SpriteText text) + : base(title, text) + { + this.text = text; + } + + public LocalisedString Text + { + get => text.Text; + set => text.Text = value; + } + } + private class ModsInfoColumn : InfoColumn { private readonly FillFlowContainer modsContainer; From 2c18b6df1c21e0983bc7536d95923a41a404ea82 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 3 Apr 2019 16:09:19 +0900 Subject: [PATCH 0459/5608] Fix score table using 300/100/50 --- .../TestCaseBeatmapScoresContainer.cs | 2 +- .../API/Requests/Responses/APILegacyScores.cs | 2 +- .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 21 ++++++----- .../BeatmapSet/Scores/ScoreTableHeaderRow.cs | 22 ++++++++---- .../BeatmapSet/Scores/ScoreTableScoreRow.cs | 35 +++++-------------- .../BeatmapSet/Scores/ScoresContainer.cs | 8 ++--- 6 files changed, 41 insertions(+), 49 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs index 4a38f98810..b30d6b1546 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs @@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }; - IEnumerable scores = new[] + var scores = new List { new ScoreInfo { diff --git a/osu.Game/Online/API/Requests/Responses/APILegacyScores.cs b/osu.Game/Online/API/Requests/Responses/APILegacyScores.cs index 15ec5d3b13..c629caaa6f 100644 --- a/osu.Game/Online/API/Requests/Responses/APILegacyScores.cs +++ b/osu.Game/Online/API/Requests/Responses/APILegacyScores.cs @@ -9,6 +9,6 @@ namespace osu.Game.Online.API.Requests.Responses public class APILegacyScores { [JsonProperty(@"scores")] - public IEnumerable Scores; + public List Scores; } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 08e73da841..ada442d50e 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -48,24 +48,27 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }; } - public IEnumerable Scores + public IReadOnlyList Scores { set { if (value == null || !value.Any()) return; - var content = new List { new ScoreTableHeaderRow().CreateDrawables().ToArray() }; - - int index = 0; - foreach (var s in value) - content.Add(new ScoreTableScoreRow(index++, s).CreateDrawables().ToArray()); - - scoresGrid.Content = content.ToArray(); + var content = new List + { + new ScoreTableHeaderRow(value.First()).CreateDrawables().ToArray() + }; backgroundFlow.Clear(); - for (int i = 0; i < index; i++) + + for (int i = 0; i < value.Count; i++) + { + content.Add(new ScoreTableScoreRow(i, value[i]).CreateDrawables().ToArray()); backgroundFlow.Add(new ScoreTableRowBackground(i)); + } + + scoresGrid.Content = content.ToArray(); } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs index a48716b71a..c73543eb10 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs @@ -2,15 +2,24 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Scoring; namespace osu.Game.Overlays.BeatmapSet.Scores { public class ScoreTableHeaderRow : ScoreTableRow { + private readonly ScoreInfo score; + + public ScoreTableHeaderRow(ScoreInfo score) + { + this.score = score; + } + protected override Drawable CreateIndexCell() => new CellText("rank"); protected override Drawable CreateRankCell() => new Container(); @@ -21,14 +30,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores protected override Drawable CreatePlayerCell() => new CellText("player"); - protected override IEnumerable CreateStatisticsCells() => new[] + protected override IEnumerable CreateStatisticsCells() { - new CellText("max combo"), - new CellText("300"), - new CellText("100"), - new CellText("50"), - new CellText("miss"), - }; + yield return new CellText("max combo"); + + foreach (var kvp in score.Statistics) + yield return new CellText(kvp.Key.GetDescription()); + } protected override Drawable CreatePpCell() => new CellText("pp"); diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs index 83901cc662..2cb16a5785 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs @@ -10,7 +10,6 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.Leaderboards; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Users; @@ -74,33 +73,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Font = OsuFont.GetFont(size: TEXT_SIZE) }; - yield return new OsuSpriteText + foreach (var kvp in score.Statistics) { - Text = $"{score.Statistics[HitResult.Great]}", - Font = OsuFont.GetFont(size: TEXT_SIZE), - Colour = score.Statistics[HitResult.Great] == 0 ? Color4.Gray : Color4.White - }; - - yield return new OsuSpriteText - { - Text = $"{score.Statistics[HitResult.Good]}", - Font = OsuFont.GetFont(size: TEXT_SIZE), - Colour = score.Statistics[HitResult.Good] == 0 ? Color4.Gray : Color4.White - }; - - yield return new OsuSpriteText - { - Text = $"{score.Statistics[HitResult.Meh]}", - Font = OsuFont.GetFont(size: TEXT_SIZE), - Colour = score.Statistics[HitResult.Meh] == 0 ? Color4.Gray : Color4.White - }; - - yield return new OsuSpriteText - { - Text = $"{score.Statistics[HitResult.Miss]}", - Font = OsuFont.GetFont(size: TEXT_SIZE), - Colour = score.Statistics[HitResult.Miss] == 0 ? Color4.Gray : Color4.White - }; + yield return new OsuSpriteText + { + Text = $"{kvp.Value}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + Colour = kvp.Value == 0 ? Color4.Gray : Color4.White + }; + } } protected override Drawable CreatePpCell() => new OsuSpriteText diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index a29d812088..de080732f9 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -83,9 +83,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } private GetScoresRequest getScoresRequest; - private IEnumerable scores; + private IReadOnlyList scores; - public IEnumerable Scores + public IReadOnlyList Scores { get => scores; set @@ -121,11 +121,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void updateDisplay() { - scoreTable.Scores = Enumerable.Empty(); + scoreTable.Scores = new List(); loading = false; - var scoreCount = scores?.Count() ?? 0; + var scoreCount = scores?.Count ?? 0; if (scoreCount == 0) { From e246fad301616d1b97ec20a5f21a2ef4186e731f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 3 Apr 2019 16:09:34 +0900 Subject: [PATCH 0460/5608] Clear table if no scores are provided --- osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index ada442d50e..09ab0e3f6a 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -52,6 +52,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { set { + scoresGrid.Content = new Drawable[0][]; + backgroundFlow.Clear(); + if (value == null || !value.Any()) return; @@ -60,8 +63,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores new ScoreTableHeaderRow(value.First()).CreateDrawables().ToArray() }; - backgroundFlow.Clear(); - for (int i = 0; i < value.Count; i++) { content.Add(new ScoreTableScoreRow(i, value[i]).CreateDrawables().ToArray()); From 42c915190a968c340d6185ed10539ec2161b8c70 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 3 Apr 2019 16:12:24 +0900 Subject: [PATCH 0461/5608] Reorder DrawableTopScore --- .../BeatmapSet/Scores/DrawableTopScore.cs | 62 +++++++++---------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 052eaf60e5..f22c6b3529 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -31,10 +31,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private const float avatar_size = 80; private const float margin = 10; - private OsuColour colours; - - private Color4 backgroundIdleColour => colours.Gray3; - private Color4 backgroundHoveredColour => colours.Gray4; + private Color4 backgroundIdleColour; + private Color4 backgroundHoveredColour; private readonly FontUsage smallStatisticsFont = OsuFont.GetFont(size: 20); private readonly FontUsage largeStatisticsFont = OsuFont.GetFont(size: 25); @@ -56,34 +54,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly ModsInfoColumn modsInfo; - private ScoreInfo score; - - public ScoreInfo Score - { - get => score; - set - { - if (score == value) - return; - - score = value; - - avatar.User = username.User = score.User; - flag.Country = score.User.Country; - date.Text = $@"achieved {score.Date.Humanize()}"; - rank.UpdateRank(score.Rank); - - totalScoreColumn.Text = $@"{score.TotalScore:N0}"; - accuracyColumn.Text = $@"{score.Accuracy:P2}"; - maxComboColumn.Text = $@"{score.MaxCombo:N0}x"; - ppColumn.Text = $@"{score.PP:N0}"; - - statisticsContainer.ChildrenEnumerable = score.Statistics.Select(kvp => new TextColumn(kvp.Key.GetDescription(), smallStatisticsFont) { Text = kvp.Value.ToString() }); - - modsInfo.Mods = score.Mods; - } - } - public DrawableTopScore() { RelativeSizeAxes = Axes.X; @@ -240,12 +210,36 @@ namespace osu.Game.Overlays.BeatmapSet.Scores [BackgroundDependencyLoader] private void load(OsuColour colours) { - this.colours = colours; - + backgroundIdleColour = colours.Gray3; + backgroundHoveredColour = colours.Gray4; rankText.Colour = colours.Yellow; + background.Colour = backgroundIdleColour; } + /// + /// Sets the score to be displayed. + /// + public ScoreInfo Score + { + set + { + avatar.User = username.User = value.User; + flag.Country = value.User.Country; + date.Text = $@"achieved {value.Date.Humanize()}"; + rank.UpdateRank(value.Rank); + + totalScoreColumn.Text = $@"{value.TotalScore:N0}"; + accuracyColumn.Text = $@"{value.Accuracy:P2}"; + maxComboColumn.Text = $@"{value.MaxCombo:N0}x"; + ppColumn.Text = $@"{value.PP:N0}"; + + statisticsContainer.ChildrenEnumerable = value.Statistics.Select(kvp => new TextColumn(kvp.Key.GetDescription(), smallStatisticsFont) { Text = kvp.Value.ToString() }); + + modsInfo.Mods = value.Mods; + } + } + protected override bool OnHover(HoverEvent e) { background.FadeColour(backgroundHoveredColour, fade_duration, Easing.OutQuint); From f8596e055ad8a4c0379666a0913add225a15c456 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 3 Apr 2019 16:36:38 +0900 Subject: [PATCH 0462/5608] Separate into multiple files --- .../TestCaseBeatmapScoresContainer.cs | 2 + .../BeatmapSet/Scores/DrawableTopScore.cs | 329 ++---------------- .../Scores/TopScoreStatisticsSection.cs | 204 +++++++++++ .../BeatmapSet/Scores/TopScoreUserSection.cs | 181 ++++++++++ 4 files changed, 409 insertions(+), 307 deletions(-) create mode 100644 osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs create mode 100644 osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs index b30d6b1546..0457e1469a 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs @@ -25,6 +25,8 @@ namespace osu.Game.Tests.Visual.SongSelect public override IReadOnlyList RequiredTypes => new[] { typeof(DrawableTopScore), + typeof(TopScoreUserSection), + typeof(TopScoreStatisticsSection), typeof(ScoresContainer), typeof(ScoreTable), typeof(ScoreTableRow), diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index f22c6b3529..3667fc3f9f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -1,58 +1,29 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using Humanizer; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; -using osu.Game.Online.Leaderboards; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.UI; using osu.Game.Scoring; -using osu.Game.Users; using osuTK; using osuTK.Graphics; -using System.Collections.Generic; -using System.Linq; -using osu.Framework.Extensions; -using osu.Framework.Localisation; -using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet.Scores { public class DrawableTopScore : Container { private const float fade_duration = 100; - private const float avatar_size = 80; - private const float margin = 10; private Color4 backgroundIdleColour; private Color4 backgroundHoveredColour; - private readonly FontUsage smallStatisticsFont = OsuFont.GetFont(size: 20); - private readonly FontUsage largeStatisticsFont = OsuFont.GetFont(size: 25); - private readonly Box background; - private readonly UpdateableAvatar avatar; - private readonly DrawableFlag flag; - private readonly ClickableTopScoreUsername username; - private readonly SpriteText rankText; - private readonly SpriteText date; - private readonly DrawableRank rank; - - private readonly FillFlowContainer statisticsContainer; - - private readonly TextColumn totalScoreColumn; - private readonly TextColumn accuracyColumn; - private readonly TextColumn maxComboColumn; - private readonly TextColumn ppColumn; - - private readonly ModsInfoColumn modsInfo; + private readonly TopScoreUserSection userSection; + private readonly TopScoreStatisticsSection statisticsSection; public DrawableTopScore() { @@ -79,128 +50,30 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding(margin), + Padding = new MarginPadding(10), Children = new Drawable[] { - new FillFlowContainer + new AutoSizingGrid { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(margin, 0), - Children = new Drawable[] - { - rankText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = "#1", - Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true) - }, - rank = new DrawableRank(ScoreRank.F) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(40), - FillMode = FillMode.Fit, - }, - avatar = new UpdateableAvatar - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(avatar_size), - Masking = true, - CornerRadius = 5, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(0.25f), - Offset = new Vector2(0, 2), - Radius = 1, - }, - }, - new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 3), - Children = new Drawable[] - { - username = new ClickableTopScoreUsername - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - }, - date = new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold) - }, - flag = new DrawableFlag - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(20, 13), - }, - } - } - } - }, - new Container - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Width = 0.65f, - Child = new FillFlowContainer + Content = new[] { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Spacing = new Vector2(margin), - Children = new Drawable[] + new Drawable[] { - new FillFlowContainer + userSection = new TopScoreUserSection { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(margin, 0), - Children = new Drawable[] - { - statisticsContainer = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(margin, 0), - }, - ppColumn = new TextColumn("pp", smallStatisticsFont), - modsInfo = new ModsInfoColumn(), - } + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, }, - new FillFlowContainer + statisticsSection = new TopScoreStatisticsSection { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(margin, 0), - Children = new Drawable[] - { - totalScoreColumn = new TextColumn("total score", largeStatisticsFont), - accuracyColumn = new TextColumn("accuracy", largeStatisticsFont), - maxComboColumn = new TextColumn("max combo", largeStatisticsFont) - } - }, - } - } + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + } + }, + }, + ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, } } } @@ -212,7 +85,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { backgroundIdleColour = colours.Gray3; backgroundHoveredColour = colours.Gray4; - rankText.Colour = colours.Yellow; background.Colour = backgroundIdleColour; } @@ -224,19 +96,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { set { - avatar.User = username.User = value.User; - flag.Country = value.User.Country; - date.Text = $@"achieved {value.Date.Humanize()}"; - rank.UpdateRank(value.Rank); - - totalScoreColumn.Text = $@"{value.TotalScore:N0}"; - accuracyColumn.Text = $@"{value.Accuracy:P2}"; - maxComboColumn.Text = $@"{value.MaxCombo:N0}x"; - ppColumn.Text = $@"{value.PP:N0}"; - - statisticsContainer.ChildrenEnumerable = value.Statistics.Select(kvp => new TextColumn(kvp.Key.GetDescription(), smallStatisticsFont) { Text = kvp.Value.ToString() }); - - modsInfo.Mods = value.Mods; + userSection.Score = value; + statisticsSection.Score = value; } } @@ -252,157 +113,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores base.OnHoverLost(e); } - private class ClickableTopScoreUsername : ClickableUserContainer + private class AutoSizingGrid : GridContainer { - private const float username_fade_duration = 150; - - private readonly FillFlowContainer hoverContainer; - - private readonly SpriteText normalText; - private readonly SpriteText hoveredText; - - public ClickableTopScoreUsername() + public AutoSizingGrid() { - var font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold, italics: true); - - Children = new Drawable[] - { - normalText = new OsuSpriteText { Font = font }, - hoverContainer = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Alpha = 0, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 1), - Children = new Drawable[] - { - hoveredText = new OsuSpriteText { Font = font }, - new Box - { - BypassAutoSizeAxes = Axes.Both, - RelativeSizeAxes = Axes.X, - Height = 1 - } - } - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - hoverContainer.Colour = colours.Blue; - } - - protected override void OnUserChanged(User user) => normalText.Text = hoveredText.Text = user.Username; - - protected override bool OnHover(HoverEvent e) - { - hoverContainer.FadeIn(username_fade_duration, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - hoverContainer.FadeOut(username_fade_duration, Easing.OutQuint); - base.OnHoverLost(e); - } - } - - private class InfoColumn : CompositeDrawable - { - private readonly Box separator; - - public InfoColumn(string title, Drawable content) - { - AutoSizeAxes = Axes.Both; - - InternalChild = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 2), - Children = new[] - { - new OsuSpriteText - { - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black), - Text = title.ToUpper() - }, - separator = new Box - { - RelativeSizeAxes = Axes.X, - Height = 2 - }, - content - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - separator.Colour = colours.Gray5; - } - } - - private class TextColumn : InfoColumn - { - private readonly SpriteText text; - - public TextColumn(string title, FontUsage font) - : this(title, new OsuSpriteText { Font = font }) - { - } - - private TextColumn(string title, SpriteText text) - : base(title, text) - { - this.text = text; - } - - public LocalisedString Text - { - get => text.Text; - set => text.Text = value; - } - } - - private class ModsInfoColumn : InfoColumn - { - private readonly FillFlowContainer modsContainer; - - public ModsInfoColumn() - : this(new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal - }) - { - } - - private ModsInfoColumn(FillFlowContainer modsContainer) - : base("mods", modsContainer) - { - this.modsContainer = modsContainer; - } - - public IEnumerable Mods - { - set - { - modsContainer.Clear(); - - foreach (Mod mod in value) - { - modsContainer.Add(new ModIcon(mod) - { - AutoSizeAxes = Axes.Both, - Scale = new Vector2(0.3f), - }); - } - } + AutoSizeAxes = Axes.Y; } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs new file mode 100644 index 0000000000..6761d0f710 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -0,0 +1,204 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Scoring; +using osuTK; + +namespace osu.Game.Overlays.BeatmapSet.Scores +{ + public class TopScoreStatisticsSection : CompositeDrawable + { + private const float margin = 10; + + private readonly FontUsage smallFont = OsuFont.GetFont(size: 20); + private readonly FontUsage largeFont = OsuFont.GetFont(size: 25); + + private readonly TextColumn totalScoreColumn; + private readonly TextColumn accuracyColumn; + private readonly TextColumn maxComboColumn; + private readonly TextColumn ppColumn; + + private readonly FillFlowContainer statisticsColumns; + private readonly ModsInfoColumn modsColumn; + + public TopScoreStatisticsSection() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + InternalChild = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(margin, 0), + Children = new Drawable[] + { + statisticsColumns = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(margin, 0), + }, + ppColumn = new TextColumn("pp", smallFont), + modsColumn = new ModsInfoColumn(), + } + }, + new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(margin, 0), + Children = new Drawable[] + { + totalScoreColumn = new TextColumn("total score", largeFont), + accuracyColumn = new TextColumn("accuracy", largeFont), + maxComboColumn = new TextColumn("max combo", largeFont) + } + }, + } + }; + } + + /// + /// Sets the score to be displayed. + /// + public ScoreInfo Score + { + set + { + totalScoreColumn.Text = $@"{value.TotalScore:N0}"; + accuracyColumn.Text = $@"{value.Accuracy:P2}"; + maxComboColumn.Text = $@"{value.MaxCombo:N0}x"; + ppColumn.Text = $@"{value.PP:N0}"; + + statisticsColumns.ChildrenEnumerable = value.Statistics.Select(kvp => createStatisticsColumn(kvp.Key, kvp.Value)); + modsColumn.Mods = value.Mods; + } + } + + private TextColumn createStatisticsColumn(HitResult hitResult, int count) => new TextColumn(hitResult.GetDescription(), smallFont) + { + Text = count.ToString() + }; + + private class InfoColumn : CompositeDrawable + { + private readonly Box separator; + + public InfoColumn(string title, Drawable content) + { + AutoSizeAxes = Axes.Both; + + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 2), + Children = new[] + { + new OsuSpriteText + { + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black), + Text = title.ToUpper() + }, + separator = new Box + { + RelativeSizeAxes = Axes.X, + Height = 2 + }, + content + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + separator.Colour = colours.Gray5; + } + } + + private class TextColumn : InfoColumn + { + private readonly SpriteText text; + + public TextColumn(string title, FontUsage font) + : this(title, new OsuSpriteText { Font = font }) + { + } + + private TextColumn(string title, SpriteText text) + : base(title, text) + { + this.text = text; + } + + public LocalisedString Text + { + set => text.Text = value; + } + } + + private class ModsInfoColumn : InfoColumn + { + private readonly FillFlowContainer modsContainer; + + public ModsInfoColumn() + : this(new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal + }) + { + } + + private ModsInfoColumn(FillFlowContainer modsContainer) + : base("mods", modsContainer) + { + this.modsContainer = modsContainer; + } + + public IEnumerable Mods + { + set + { + modsContainer.Clear(); + + foreach (Mod mod in value) + { + modsContainer.Add(new ModIcon(mod) + { + AutoSizeAxes = Axes.Both, + Scale = new Vector2(0.3f), + }); + } + } + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs new file mode 100644 index 0000000000..1ec4b7197d --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -0,0 +1,181 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Humanizer; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.Leaderboards; +using osu.Game.Scoring; +using osu.Game.Users; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.BeatmapSet.Scores +{ + public class TopScoreUserSection : CompositeDrawable + { + private readonly SpriteText rankText; + private readonly DrawableRank rank; + private readonly UpdateableAvatar avatar; + private readonly UsernameText usernameText; + private readonly SpriteText date; + private readonly DrawableFlag flag; + + public TopScoreUserSection() + { + AutoSizeAxes = Axes.Both; + + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + rankText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "#1", + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true) + }, + rank = new DrawableRank(ScoreRank.F) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(40), + FillMode = FillMode.Fit, + }, + avatar = new UpdateableAvatar + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(80), + Masking = true, + CornerRadius = 5, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.25f), + Offset = new Vector2(0, 2), + Radius = 1, + }, + }, + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 3), + Children = new Drawable[] + { + usernameText = new UsernameText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + date = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold) + }, + flag = new DrawableFlag + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(20, 13), + }, + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + rankText.Colour = colours.Yellow; + } + + /// + /// Sets the score to be displayed. + /// + public ScoreInfo Score + { + set + { + avatar.User = usernameText.User = value.User; + flag.Country = value.User.Country; + date.Text = $@"achieved {value.Date.Humanize()}"; + rank.UpdateRank(value.Rank); + } + } + + private class UsernameText : ClickableUserContainer + { + private const float username_fade_duration = 150; + + private readonly FillFlowContainer hoverContainer; + + private readonly SpriteText normalText; + private readonly SpriteText hoveredText; + + public UsernameText() + { + var font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold, italics: true); + + Children = new Drawable[] + { + normalText = new OsuSpriteText { Font = font }, + hoverContainer = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Alpha = 0, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 1), + Children = new Drawable[] + { + hoveredText = new OsuSpriteText { Font = font }, + new Box + { + BypassAutoSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + Height = 1 + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + hoverContainer.Colour = colours.Blue; + } + + protected override void OnUserChanged(User user) => normalText.Text = hoveredText.Text = user.Username; + + protected override bool OnHover(HoverEvent e) + { + hoverContainer.FadeIn(username_fade_duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + hoverContainer.FadeOut(username_fade_duration, Easing.OutQuint); + base.OnHoverLost(e); + } + } + } +} From 3da008d29380dac150b4cd1d6fb629cace86700c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 3 Apr 2019 16:43:56 +0900 Subject: [PATCH 0463/5608] Add a bit of padding between the sections --- osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 3667fc3f9f..aace49e120 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -65,6 +65,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, }, + null, statisticsSection = new TopScoreStatisticsSection { Anchor = Anchor.CentreRight, @@ -72,7 +73,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } }, }, - ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize), new Dimension(GridSizeMode.Absolute, 20) }, RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, } } From 50f8ab3dfb07c9cc12b0fb5598ecadfdecf3b43d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Apr 2019 16:58:20 +0900 Subject: [PATCH 0464/5608] Fix gameplay offset handling on seeks --- .../Screens/Play/GameplayClockContainer.cs | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index c13222c6de..fc7a9ddd20 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -36,6 +36,8 @@ namespace osu.Game.Screens.Play /// private readonly DecoupleableInterpolatingFramedClock adjustableClock; + private readonly double gameplayStartTime; + public readonly Bindable UserPlaybackRate = new BindableDouble(1) { Default = 1, @@ -52,11 +54,14 @@ namespace osu.Game.Screens.Play private Bindable userAudioOffset; - private readonly FramedOffsetClock offsetClock; + private readonly FramedOffsetClock userOffsetClock; + + private readonly FramedOffsetClock platformOffsetClock; public GameplayClockContainer(WorkingBeatmap beatmap, double gameplayStartTime) { this.beatmap = beatmap; + this.gameplayStartTime = gameplayStartTime; RelativeSizeAxes = Axes.Both; @@ -64,30 +69,31 @@ namespace osu.Game.Screens.Play adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; - adjustableClock.Seek(Math.Min(0, gameplayStartTime - beatmap.BeatmapInfo.AudioLeadIn)); - - adjustableClock.ProcessFrame(); - // Lazer's audio timings in general doesn't match stable. This is the result of user testing, albeit limited. // This only seems to be required on windows. We need to eventually figure out why, with a bit of luck. - var platformOffsetClock = new FramedOffsetClock(adjustableClock) { Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 22 : 0 }; + platformOffsetClock = new FramedOffsetClock(adjustableClock) { Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 22 : 0 }; // the final usable gameplay clock with user-set offsets applied. - offsetClock = new FramedOffsetClock(platformOffsetClock); + userOffsetClock = new FramedOffsetClock(platformOffsetClock); // the clock to be exposed via DI to children. - GameplayClock = new GameplayClock(offsetClock); + GameplayClock = new GameplayClock(userOffsetClock); GameplayClock.IsPaused.BindTo(IsPaused); } + private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset; + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); - userAudioOffset.BindValueChanged(offset => offsetClock.Offset = offset.NewValue, true); + userAudioOffset.BindValueChanged(offset => userOffsetClock.Offset = offset.NewValue, true); UserPlaybackRate.ValueChanged += _ => updateRate(); + + Seek(Math.Min(0, gameplayStartTime - beatmap.BeatmapInfo.AudioLeadIn)); + adjustableClock.ProcessFrame(); } public void Restart() @@ -104,9 +110,7 @@ namespace osu.Game.Screens.Play this.Delay(750).Schedule(() => { if (!IsPaused.Value) - { - adjustableClock.Start(); - } + Start(); }); }); }); @@ -121,7 +125,12 @@ namespace osu.Game.Screens.Play IsPaused.Value = false; } - public void Seek(double time) => adjustableClock.Seek(time); + public void Seek(double time) + { + // remove the offset component here because most of the time we want the seek to be aligned to gameplay, not the audio track. + // we may want to consider reversing the application of offsets in the future as it may feel more correct. + adjustableClock.Seek(time - totalOffset); + } public void Stop() { @@ -138,7 +147,7 @@ namespace osu.Game.Screens.Play protected override void Update() { if (!IsPaused.Value) - offsetClock.ProcessFrame(); + userOffsetClock.ProcessFrame(); base.Update(); } From efd7bea7712463013746f1a9295402303d819120 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Apr 2019 17:01:11 +0900 Subject: [PATCH 0465/5608] Add further xmldoc --- osu.Game/Screens/Play/GameplayClockContainer.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index fc7a9ddd20..5ded375259 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -125,6 +125,13 @@ namespace osu.Game.Screens.Play IsPaused.Value = false; } + /// + /// Seek to a specific time in gameplay. + /// + /// Adjusts for any offsets which have been applied (so the seek may not be the expected point in time on the underlying audio track). + /// + /// + /// The destination time to seek to. public void Seek(double time) { // remove the offset component here because most of the time we want the seek to be aligned to gameplay, not the audio track. From 3b7d26cca805330a1a98bb1f86059890204999dc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 3 Apr 2019 17:49:01 +0900 Subject: [PATCH 0466/5608] Remove custom styled text --- .../Online/TestCaseBeatmapSetOverlay.cs | 1 - .../Scores/ClickableUserContainer.cs | 51 ------------- .../BeatmapSet/Scores/ScoreTableScoreRow.cs | 74 ++++++------------- .../BeatmapSet/Scores/TopScoreUserSection.cs | 73 +++--------------- 4 files changed, 31 insertions(+), 168 deletions(-) delete mode 100644 osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs diff --git a/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs index 19d295cf12..9cbccbd603 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs @@ -24,7 +24,6 @@ namespace osu.Game.Tests.Visual.Online public override IReadOnlyList RequiredTypes => new[] { typeof(Header), - typeof(ClickableUserContainer), typeof(ScoreTable), typeof(ScoreTableRow), typeof(ScoreTableHeaderRow), diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs deleted file mode 100644 index 2448ae17f8..0000000000 --- a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUserContainer.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Events; -using osu.Game.Users; - -namespace osu.Game.Overlays.BeatmapSet.Scores -{ - public abstract class ClickableUserContainer : Container - { - private UserProfileOverlay profile; - - protected ClickableUserContainer() - { - AutoSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader(true)] - private void load(UserProfileOverlay profile) - { - this.profile = profile; - } - - private User user; - - public User User - { - get => user; - set - { - if (user == value) - return; - - user = value; - - OnUserChanged(user); - } - } - - protected abstract void OnUserChanged(User user); - - protected override bool OnClick(ClickEvent e) - { - profile?.ShowUser(user); - return true; - } - } -} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs index 2cb16a5785..adb79eedfa 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Online.Chat; using osu.Game.Online.Leaderboards; using osu.Game.Rulesets.UI; using osu.Game.Scoring; @@ -53,17 +53,27 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Colour = score.Accuracy == 1 ? Color4.GreenYellow : Color4.White }; - protected override Drawable CreatePlayerCell() => new FillFlowContainer + protected override Drawable CreatePlayerCell() { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5, 0), - Children = new Drawable[] + var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: TEXT_SIZE)) { - new DrawableFlag(score.User.Country) { Size = new Vector2(20, 13) }, - new ClickableScoreUsername { User = score.User } - } - }; + AutoSizeAxes = Axes.Both, + }; + + username.AddLink(score.User.Username, null, LinkAction.OpenUserProfile, score.User.Id.ToString(), "Open profile"); + + return new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + Children = new Drawable[] + { + new DrawableFlag(score.User.Country) { Size = new Vector2(20, 13) }, + username + } + }; + } protected override IEnumerable CreateStatisticsCells() { @@ -100,47 +110,5 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Scale = new Vector2(0.3f) }) }; - - private class ClickableScoreUsername : ClickableUserContainer - { - private const int fade_duration = 100; - - private readonly SpriteText text; - private readonly SpriteText textBold; - - public ClickableScoreUsername() - { - Add(text = new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: TEXT_SIZE) - }); - - Add(textBold = new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold), - Alpha = 0, - }); - } - - protected override void OnUserChanged(User user) => text.Text = textBold.Text = user.Username; - - protected override bool OnHover(HoverEvent e) - { - textBold.Show(); - text.Hide(); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - textBold.Hide(); - text.Show(); - base.OnHoverLost(e); - } - } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 1ec4b7197d..f401dc93a7 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -6,11 +6,11 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Online.Chat; using osu.Game.Online.Leaderboards; using osu.Game.Scoring; using osu.Game.Users; @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly SpriteText rankText; private readonly DrawableRank rank; private readonly UpdateableAvatar avatar; - private readonly UsernameText usernameText; + private readonly LinkFlowContainer usernameText; private readonly SpriteText date; private readonly DrawableFlag flag; @@ -77,10 +77,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(0, 3), Children = new Drawable[] { - usernameText = new UsernameText + usernameText = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold, italics: true)) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, }, date = new SpriteText { @@ -113,69 +114,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { set { - avatar.User = usernameText.User = value.User; + avatar.User = value.User; flag.Country = value.User.Country; date.Text = $@"achieved {value.Date.Humanize()}"; + + usernameText.Clear(); + usernameText.AddLink(value.User.Username, null, LinkAction.OpenUserProfile, value.User.Id.ToString(), "Open profile"); + rank.UpdateRank(value.Rank); } } - - private class UsernameText : ClickableUserContainer - { - private const float username_fade_duration = 150; - - private readonly FillFlowContainer hoverContainer; - - private readonly SpriteText normalText; - private readonly SpriteText hoveredText; - - public UsernameText() - { - var font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold, italics: true); - - Children = new Drawable[] - { - normalText = new OsuSpriteText { Font = font }, - hoverContainer = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Alpha = 0, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 1), - Children = new Drawable[] - { - hoveredText = new OsuSpriteText { Font = font }, - new Box - { - BypassAutoSizeAxes = Axes.Both, - RelativeSizeAxes = Axes.X, - Height = 1 - } - } - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - hoverContainer.Colour = colours.Blue; - } - - protected override void OnUserChanged(User user) => normalText.Text = hoveredText.Text = user.Username; - - protected override bool OnHover(HoverEvent e) - { - hoverContainer.FadeIn(username_fade_duration, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - hoverContainer.FadeOut(username_fade_duration, Easing.OutQuint); - base.OnHoverLost(e); - } - } } } From 5d37851d34b716d361cd67fa8bef60e81e36a399 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Apr 2019 18:14:59 +0900 Subject: [PATCH 0467/5608] Rename and move test to correct location --- .../TestCaseScoresContainer.cs} | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) rename osu.Game.Tests/Visual/{SongSelect/TestCaseBeatmapScoresContainer.cs => Online/TestCaseScoresContainer.cs} (96%) diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestCaseScoresContainer.cs similarity index 96% rename from osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs rename to osu.Game.Tests/Visual/Online/TestCaseScoresContainer.cs index 0457e1469a..3d87e1743c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseScoresContainer.cs @@ -15,19 +15,16 @@ using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Users; -using NUnit.Framework; -namespace osu.Game.Tests.Visual.SongSelect +namespace osu.Game.Tests.Visual.Online { - [Description("in BeatmapOverlay")] - public class TestCaseBeatmapScoresContainer : OsuTestCase + public class TestCaseScoresContainer : OsuTestCase { public override IReadOnlyList RequiredTypes => new[] { typeof(DrawableTopScore), typeof(TopScoreUserSection), typeof(TopScoreStatisticsSection), - typeof(ScoresContainer), typeof(ScoreTable), typeof(ScoreTableRow), typeof(ScoreTableHeaderRow), @@ -37,7 +34,7 @@ namespace osu.Game.Tests.Visual.SongSelect private readonly Box background; - public TestCaseBeatmapScoresContainer() + public TestCaseScoresContainer() { ScoresContainer scoresContainer; From 5c3c08566f4f99e6f414ae618a23739cd5a4df8e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Apr 2019 18:20:03 +0900 Subject: [PATCH 0468/5608] DrawableTopScore can be composite --- osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index aace49e120..d8bd15a4a9 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class DrawableTopScore : Container + public class DrawableTopScore : CompositeDrawable { private const float fade_duration = 100; @@ -40,7 +40,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Offset = new Vector2(0, 1), }; - Children = new Drawable[] + InternalChildren = new Drawable[] { background = new Box { From a15a9bd03aa95502172ac33958c2cb36e7e5c13f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Apr 2019 18:29:46 +0900 Subject: [PATCH 0469/5608] Rewrite updateDisplay logic to not fail on some cases --- .../BeatmapSet/Scores/ScoresContainer.cs | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index de080732f9..ef2b14b8f0 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -121,25 +121,17 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void updateDisplay() { - scoreTable.Scores = new List(); - loading = false; - var scoreCount = scores?.Count ?? 0; + scoreTable.Scores = scores?.Count > 1 ? scores : new List(); - if (scoreCount == 0) + if (scores.Any()) { - topScore.Hide(); - return; + topScore.Score = scores.FirstOrDefault(); + topScore.Show(); } - - topScore.Score = scores.FirstOrDefault(); - topScore.Show(); - - if (scoreCount < 2) - return; - - scoreTable.Scores = scores; + else + topScore.Hide(); } protected override void Dispose(bool isDisposing) From cb417ebd777085599a2d848e631db49b13a4c8d9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Apr 2019 18:44:19 +0900 Subject: [PATCH 0470/5608] Player -> User --- osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs | 2 +- osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs | 4 ++-- osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs index c73543eb10..f6f410a729 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores protected override Drawable CreateAccuracyCell() => new CellText("accuracy"); - protected override Drawable CreatePlayerCell() => new CellText("player"); + protected override Drawable CreateUserCell() => new CellText("player"); protected override IEnumerable CreateStatisticsCells() { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs index 8efda73270..15355512ba 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs @@ -53,7 +53,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Right = 20 }, - Child = CreatePlayerCell() + Child = CreateUserCell() }; foreach (var cell in CreateStatisticsCells()) @@ -93,7 +93,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores protected abstract Drawable CreateAccuracyCell(); - protected abstract Drawable CreatePlayerCell(); + protected abstract Drawable CreateUserCell(); protected abstract IEnumerable CreateStatisticsCells(); diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs index adb79eedfa..75d45d0b23 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs @@ -53,7 +53,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Colour = score.Accuracy == 1 ? Color4.GreenYellow : Color4.White }; - protected override Drawable CreatePlayerCell() + protected override Drawable CreateUserCell() { var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: TEXT_SIZE)) { From 84da708d44f2db71e7a50c93b5f49961787a8c3b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Apr 2019 18:46:08 +0900 Subject: [PATCH 0471/5608] Fix nullref --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index ef2b14b8f0..8ef3f71fe3 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -125,7 +125,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores scoreTable.Scores = scores?.Count > 1 ? scores : new List(); - if (scores.Any()) + if (scores?.Any() == true) { topScore.Score = scores.FirstOrDefault(); topScore.Show(); From 2ed945605ec06da3c2ff57493a83c4bc953904b3 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 3 Apr 2019 19:57:22 +0900 Subject: [PATCH 0472/5608] Fix Axes.None requirement for FacadeContainer --- .../Visual/TestCaseLogoFacadeContainer.cs | 292 +++++++++++------- osu.Game.Tests/Visual/TestCasePositionAxes.cs | 33 ++ .../Containers/LogoFacadeContainer.cs | 21 +- osu.Game/Screens/Menu/ButtonSystem.cs | 2 + osu.Game/Screens/Play/PlayerLoader.cs | 6 +- 5 files changed, 229 insertions(+), 125 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCasePositionAxes.cs diff --git a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs index adbf22302b..b4d7976e4a 100644 --- a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Drawing; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -10,10 +11,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; -using osu.Framework.Screens; +using osu.Framework.Testing; using osu.Game.Configuration; using osu.Game.Graphics.Containers; -using osu.Game.Screens; using osu.Game.Screens.Menu; using osu.Game.Screens.Play; using osuTK; @@ -21,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual { - public class TestCaseLogoFacadeContainer : ScreenTestCase + public class TestCaseLogoFacadeContainer : OsuTestCase { public override IReadOnlyList RequiredTypes => new[] { @@ -34,23 +34,38 @@ namespace osu.Game.Tests.Visual typeof(MainMenu) }; - [Cached] private OsuLogo logo; private readonly Bindable uiScale = new Bindable(); + private LogoFacadeContainer logoFacadeContainer; + private Container transferContainer; + private Box visualBox; + private Box transferContainerBox; + private Container logoFacade; - public TestCaseLogoFacadeContainer() - { - Add(logo = new OsuLogo()); - } + private bool randomPositions = false; [BackgroundDependencyLoader] private void load(OsuConfigManager config) { + Add(logo = new OsuLogo { Scale = new Vector2(0.15f), RelativePositionAxes = Axes.None }); + config.BindWith(OsuSetting.UIScale, uiScale); AddSliderStep("Adjust scale", 0.8f, 1.5f, 1f, v => uiScale.Value = v); } + [SetUpSteps] + public void SetUpSteps() + { + AddStep("Clear facades", () => + { + Clear(); + Add(logo = new OsuLogo { Scale = new Vector2(0.15f), RelativePositionAxes = Axes.None }); + logoFacadeContainer = null; + transferContainer = null; + }); + } + /// /// Move the facade to 0,0, then move it to a random new location while the logo is still transforming to it. /// Check if the logo is still tracking the facade. @@ -58,13 +73,11 @@ namespace osu.Game.Tests.Visual [Test] public void MoveFacadeTest() { - TestScreen screen = null; - bool randomPositions = false; AddToggleStep("Toggle move continuously", b => randomPositions = b); - AddStep("Move facade to random position", () => LoadScreen(screen = new TestScreen(randomPositions))); - AddUntilStep("Screen is current", () => screen.IsCurrentScreen()); + AddStep("Add facade containers", addFacadeContainers); + AddStep("Move facade to random position", StartTrackingRandom); waitForMove(); - AddAssert("Logo is tracking", () => screen.IsLogoTracking); + AddAssert("Logo is tracking", () => IsLogoTracking); } /// @@ -73,12 +86,11 @@ namespace osu.Game.Tests.Visual [Test] public void RemoveFacadeTest() { - TestScreen screen = null; - AddStep("Move facade to random position", () => LoadScreen(screen = new TestScreen())); - AddUntilStep("Screen is current", () => screen.IsCurrentScreen()); - AddStep("Remove facade from FacadeContainer", () => screen.RemoveFacade()); + AddStep("Add facade containers", addFacadeContainers); + AddStep("Move facade to random position", StartTrackingRandom); + AddStep("Remove facade from FacadeContainer", RemoveFacade); waitForMove(); - AddAssert("Logo is not tracking", () => !screen.IsLogoTracking); + AddAssert("Logo is not tracking", () => !IsLogoTracking); } /// @@ -87,114 +99,162 @@ namespace osu.Game.Tests.Visual [Test] public void TransferFacadeTest() { - TestScreen screen = null; - AddStep("Move facade to random position", () => LoadScreen(screen = new TestScreen())); - AddUntilStep("Screen is current", () => screen.IsCurrentScreen()); - AddStep("Remove facade from FacadeContainer", () => screen.RemoveFacade()); - AddStep("Transfer facade to a new container", () => screen.TransferFacade()); + AddStep("Add facade containers", addFacadeContainers); + AddStep("Move facade to random position", StartTrackingRandom); + AddStep("Remove facade from FacadeContainer", RemoveFacade); + AddStep("Transfer facade to a new container", TransferFacade); waitForMove(); - AddAssert("Logo is tracking", () => screen.IsLogoTracking); + AddAssert("Logo is tracking", () => IsLogoTracking); + } + + /// + /// Add a facade to a flow container then move logo to facade. + /// + [Test] + public void FlowContainerTest() + { + FillFlowContainer flowContainer; + + AddStep("Create new Logo Facade Container", () => + { + Add(logoFacadeContainer = new LogoFacadeContainer + { + AutoSizeAxes = Axes.Both, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Child = flowContainer = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Direction = FillDirection.Vertical, + } + }); + flowContainer.Children = new Drawable[] + { + new Box + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Colour = Color4.Azure, + Size = new Vector2(70) + }, + new Container + { + Alpha = 0.35f, + RelativeSizeAxes = Axes.None, + Size = new Vector2(72), + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Children = new Drawable[] + { + visualBox = new Box + { + Colour = Color4.White, + RelativeSizeAxes = Axes.Both, + }, + logoFacadeContainer.LogoFacade, + } + }, + new Box + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Colour = Color4.Azure, + Size = new Vector2(70) + }, + }; + }); + + AddStep("Perform logo movements", () => + { + logoFacadeContainer.Tracking = false; + logo.RelativePositionAxes = Axes.Both; + logo.MoveTo(new Vector2(0.5f), 500, Easing.InOutExpo); + logoFacadeContainer.SetLogo(logo, 1.0f, 1000, Easing.InOutExpo); + visualBox.Colour = Color4.White; + + Scheduler.AddDelayed(() => + { + logoFacadeContainer.Tracking = true; + //logo.RelativePositionAxes = Axes.None; + visualBox.Colour = Color4.Tomato; + }, 700); + }); + } + + private void addFacadeContainers() + { + AddRange(new Drawable[] + { + logoFacadeContainer = new LogoFacadeContainer + { + Alpha = 0.35f, + RelativeSizeAxes = Axes.None, + Size = new Vector2(72), + Child = visualBox = new Box + { + Colour = Color4.Tomato, + RelativeSizeAxes = Axes.Both, + } + }, + transferContainer = new Container + { + Alpha = 0.35f, + RelativeSizeAxes = Axes.None, + Size = new Vector2(72), + Child = transferContainerBox = new Box + { + Colour = Color4.White, + RelativeSizeAxes = Axes.Both, + } + }, + }); + + logoFacadeContainer.Add(logoFacade = logoFacadeContainer.LogoFacade); + logoFacadeContainer.SetLogo(logo, 1.0f, 1000); } private void waitForMove() => AddWaitStep("Wait for transforms to finish", 5); - private class TestScreen : OsuScreen + private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(logoFacade.ScreenSpaceDrawQuad.Centre); + + /// + /// Check that the logo is tracking the position of the facade, with an acceptable precision lenience. + /// + public bool IsLogoTracking => Math.Abs(logo.Position.X - logoTrackingPosition.X) < 0.001f && Math.Abs(logo.Position.Y - logoTrackingPosition.Y) < 0.001f; + + public void RemoveFacade() { - private LogoFacadeContainer logoFacadeContainer; - private Container transferContainer; - private Container logoFacade; - private readonly bool randomPositions; - private OsuLogo logo; - private Box visualBox; - private Box transferContainerBox; + logoFacadeContainer.Remove(logoFacade); + visualBox.Colour = Color4.White; + moveLogoFacade(); + } - public TestScreen(bool randomPositions = false) + public void TransferFacade() + { + transferContainer.Add(logoFacade); + transferContainerBox.Colour = Color4.Tomato; + moveLogoFacade(); + } + + public void StartTrackingRandom() + { + logoFacadeContainer.Tracking = true; + moveLogoFacade(); + } + + private void moveLogoFacade() + { + Random random = new Random(); + if (logoFacade.Transforms.Count == 0 && transferContainer.Transforms.Count == 0) { - this.randomPositions = randomPositions; + logoFacadeContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300); + transferContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300); } - [BackgroundDependencyLoader] - private void load() - { - InternalChildren = new Drawable[] - { - logoFacadeContainer = new LogoFacadeContainer - { - Alpha = 0.35f, - RelativeSizeAxes = Axes.None, - Size = new Vector2(72), - Child = visualBox = new Box - { - Colour = Color4.Tomato, - RelativeSizeAxes = Axes.Both, - } - }, - transferContainer = new Container - { - Alpha = 0.35f, - RelativeSizeAxes = Axes.None, - Size = new Vector2(72), - Child = transferContainerBox = new Box - { - Colour = Color4.White, - RelativeSizeAxes = Axes.Both, - } - }, - }; - - logoFacadeContainer.Add(logoFacade = logoFacadeContainer.LogoFacade); - } - - private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(logoFacade.ScreenSpaceDrawQuad.Centre); - - /// - /// Check that the logo is tracking the position of the facade, with an acceptable precision lenience. - /// - public bool IsLogoTracking => Math.Abs(logo.Position.X - logoTrackingPosition.X) < 0.001f && Math.Abs(logo.Position.Y - logoTrackingPosition.Y) < 0.001f; - - public void RemoveFacade() - { - logoFacadeContainer.Remove(logoFacade); - visualBox.Colour = Color4.White; - moveLogoFacade(); - } - - public void TransferFacade() - { - transferContainer.Add(logoFacade); - transferContainerBox.Colour = Color4.Tomato; - moveLogoFacade(); - } - - protected override void LogoArriving(OsuLogo logo, bool resuming) - { - base.LogoArriving(logo, resuming); - this.logo = logo; - logo.FadeIn(350); - logo.ScaleTo(new Vector2(0.15f), 350, Easing.In); - logoFacadeContainer.SetLogo(logo, 1.0f, 1000, Easing.InOutQuint); - logoFacadeContainer.Tracking = true; - moveLogoFacade(); - } - - protected override void LogoExiting(OsuLogo logo) - { - base.LogoExiting(logo); - logoFacadeContainer.Tracking = false; - } - - private void moveLogoFacade() - { - Random random = new Random(); - if (logoFacade.Transforms.Count == 0 && transferContainer.Transforms.Count == 0) - { - logoFacadeContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)DrawWidth), random.Next(0, (int)DrawHeight)), 300); - transferContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)DrawWidth), random.Next(0, (int)DrawHeight)), 300); - } - - if (randomPositions) - Schedule(moveLogoFacade); - } + if (randomPositions) + Schedule(moveLogoFacade); } } } diff --git a/osu.Game.Tests/Visual/TestCasePositionAxes.cs b/osu.Game.Tests/Visual/TestCasePositionAxes.cs new file mode 100644 index 0000000000..04ff0dcf8c --- /dev/null +++ b/osu.Game.Tests/Visual/TestCasePositionAxes.cs @@ -0,0 +1,33 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Testing; +using osuTK; + +namespace osu.Game.Tests.Visual +{ + public class TestCasePositionAxes : OsuTestCase + { + private Box box; + + public TestCasePositionAxes() + { + Add(new Container() + { + Size = new Vector2(1), + Child = box = new Box + { + Size = new Vector2(25), + RelativePositionAxes = Axes.None, + Position = new Vector2(250) + } + }); + + AddStep("blank", () => { }); + AddStep("change axes", () => box.RelativePositionAxes = Axes.Both); + } + } +} diff --git a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs index 547af87522..c9f41e75e7 100644 --- a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs +++ b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs @@ -43,7 +43,7 @@ namespace osu.Game.Graphics.Containers /// The scale of the facade. Does not actually affect the logo itself. /// The duration of the initial transform. Default is instant. /// The easing type of the initial transform. - public void SetLogo(OsuLogo logo, float facadeScale, double duration = 0, Easing easing = Easing.None) + public void SetLogo(OsuLogo logo, float facadeScale = 1.0f, double duration = 0, Easing easing = Easing.None) { this.logo = logo ?? throw new ArgumentNullException(nameof(logo)); this.facadeScale = facadeScale; @@ -54,11 +54,19 @@ namespace osu.Game.Graphics.Containers startPosition = null; } - private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre); - - protected override void UpdateAfterChildren() + private Vector2 localSpaceConversion() { - base.UpdateAfterChildren(); + Vector2 local; + local.X = logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).X / logo.Parent.RelativeToAbsoluteFactor.X; + local.Y = logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).Y / logo.Parent.RelativeToAbsoluteFactor.Y; + return local; + } + + private Vector2 logoTrackingPosition => logo.RelativePositionAxes == Axes.None ? logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre) : localSpaceConversion(); + + protected override void Update() + { + base.Update(); if (logo == null || !Tracking) return; @@ -68,9 +76,6 @@ namespace osu.Game.Graphics.Containers if (LogoFacade.Parent != null && logo.Position != logoTrackingPosition) { - // Required for the correct position of the logo to be set with respect to logoTrackingPosition - logo.RelativePositionAxes = Axes.None; - // If this is our first update since tracking has started, initialize our starting values for interpolation if (startTime == null || startPosition == null) { diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index f13dadf3dd..607700649d 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -290,6 +290,7 @@ namespace osu.Game.Screens.Menu break; case ButtonSystemState.Initial: logo.ClearTransforms(targetMember: nameof(Position)); + logo.RelativePositionAxes = Axes.None; bool impact = logo.Scale.X > 0.6f; @@ -310,6 +311,7 @@ namespace osu.Game.Screens.Menu break; default: logo.ClearTransforms(targetMember: nameof(Position)); + logo.RelativePositionAxes = Axes.None; logoFacadeContainer.Tracking = true; logo.ScaleTo(0.5f, 200, Easing.OutQuint); break; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 9e6f7cf24e..19607129a0 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -172,7 +172,11 @@ namespace osu.Game.Screens.Play content.SetLogo(logo, 1.0f, 500, Easing.InOutExpo); - Scheduler.AddDelayed(() => content.Tracking = true, resuming ? 0 : 500); + Scheduler.AddDelayed(() => + { + content.Tracking = true; + //logo.RelativePositionAxes = Axes.None; + }, resuming ? 0 : 500); } protected override void LogoExiting(OsuLogo logo) From 8a40b27e8fc3cf9b17069439e8af130a72d7564e Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 3 Apr 2019 20:32:53 +0900 Subject: [PATCH 0473/5608] Remove need for logo relativePositionAxes none --- osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs | 1 - osu.Game/Graphics/Containers/LogoFacadeContainer.cs | 10 ++++------ osu.Game/Screens/Menu/ButtonSystem.cs | 2 -- osu.Game/Screens/Play/PlayerLoader.cs | 1 - 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs index b4d7976e4a..bd1fb932bb 100644 --- a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs @@ -177,7 +177,6 @@ namespace osu.Game.Tests.Visual Scheduler.AddDelayed(() => { logoFacadeContainer.Tracking = true; - //logo.RelativePositionAxes = Axes.None; visualBox.Colour = Color4.Tomato; }, 700); }); diff --git a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs index c9f41e75e7..76903a20b3 100644 --- a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs +++ b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs @@ -54,7 +54,7 @@ namespace osu.Game.Graphics.Containers startPosition = null; } - private Vector2 localSpaceConversion() + private Vector2 logoTrackingPosition() { Vector2 local; local.X = logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).X / logo.Parent.RelativeToAbsoluteFactor.X; @@ -62,8 +62,6 @@ namespace osu.Game.Graphics.Containers return local; } - private Vector2 logoTrackingPosition => logo.RelativePositionAxes == Axes.None ? logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre) : localSpaceConversion(); - protected override void Update() { base.Update(); @@ -74,7 +72,7 @@ namespace osu.Game.Graphics.Containers // Account for the scale of the actual logo container, as SizeForFlow only accounts for the sprite scale. LogoFacade.Size = new Vector2(logo.SizeForFlow * logo.Scale.X * facadeScale); - if (LogoFacade.Parent != null && logo.Position != logoTrackingPosition) + if (LogoFacade.Parent != null && logo.Position != logoTrackingPosition()) { // If this is our first update since tracking has started, initialize our starting values for interpolation if (startTime == null || startPosition == null) @@ -90,11 +88,11 @@ namespace osu.Game.Graphics.Containers var mount = (float)Interpolation.ApplyEasing(easing, Math.Min(elapsedDuration / duration, 1)); // Interpolate the position of the logo, where mount 0 is where the logo was when it first began interpolating, and mount 1 is the target location. - logo.Position = Vector2.Lerp(startPosition ?? throw new ArgumentNullException(nameof(startPosition)), logoTrackingPosition, mount); + logo.Position = Vector2.Lerp(startPosition ?? throw new ArgumentNullException(nameof(startPosition)), logoTrackingPosition(), mount); } else { - logo.Position = logoTrackingPosition; + logo.Position = logoTrackingPosition(); } } } diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 607700649d..f13dadf3dd 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -290,7 +290,6 @@ namespace osu.Game.Screens.Menu break; case ButtonSystemState.Initial: logo.ClearTransforms(targetMember: nameof(Position)); - logo.RelativePositionAxes = Axes.None; bool impact = logo.Scale.X > 0.6f; @@ -311,7 +310,6 @@ namespace osu.Game.Screens.Menu break; default: logo.ClearTransforms(targetMember: nameof(Position)); - logo.RelativePositionAxes = Axes.None; logoFacadeContainer.Tracking = true; logo.ScaleTo(0.5f, 200, Easing.OutQuint); break; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 19607129a0..2ba5bd81d1 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -175,7 +175,6 @@ namespace osu.Game.Screens.Play Scheduler.AddDelayed(() => { content.Tracking = true; - //logo.RelativePositionAxes = Axes.None; }, resuming ? 0 : 500); } From 73c7c6c31613175bcdcfe30d4169bdd160e2b52b Mon Sep 17 00:00:00 2001 From: Samuel Van Allen Date: Wed, 3 Apr 2019 21:44:36 +0800 Subject: [PATCH 0474/5608] Hides "Details" button when OnlineBeatmapID is null --- .../Carousel/DrawableCarouselBeatmap.cs | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 38ca9a9aed..a31e40dd8f 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -167,16 +168,21 @@ namespace osu.Game.Screens.Select.Carousel base.ApplyState(); } - - public MenuItem[] ContextMenuItems => new MenuItem[] + public MenuItem[] ContextMenuItems { - new OsuMenuItem("Play", MenuItemType.Highlighted, () => startRequested?.Invoke(beatmap)), - new OsuMenuItem("Edit", MenuItemType.Standard, () => editRequested?.Invoke(beatmap)), - new OsuMenuItem("Hide", MenuItemType.Destructive, () => hideRequested?.Invoke(beatmap)), - new OsuMenuItem("Details", MenuItemType.Standard, () => + get { - if (beatmap.OnlineBeatmapID.HasValue) beatmapOverlay?.FetchAndShowBeatmap(beatmap.OnlineBeatmapID.Value); - }), - }; + List items = new List(); + + items.Add(new OsuMenuItem("Play", MenuItemType.Highlighted, () => startRequested?.Invoke(beatmap))); + items.Add(new OsuMenuItem("Edit", MenuItemType.Standard, () => editRequested?.Invoke(beatmap))); + items.Add(new OsuMenuItem("Hide", MenuItemType.Destructive, () => hideRequested?.Invoke(beatmap))); + + if (beatmap.OnlineBeatmapID.HasValue) + items.Add(new OsuMenuItem("Details", MenuItemType.Standard, () => beatmapOverlay?.FetchAndShowBeatmap(beatmap.OnlineBeatmapID.Value))); + + return items.ToArray(); + } + } } } From 55a6e43778da2a932f1b7ae41e713107c7fae54e Mon Sep 17 00:00:00 2001 From: Samuel Van Allen Date: Wed, 3 Apr 2019 21:49:33 +0800 Subject: [PATCH 0475/5608] Check against databasedSet instead of function param --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 9ab09d1122..b31b9e5e87 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -255,7 +255,7 @@ namespace osu.Game menuScreen.LoadToSolo(); // we might even already be at the song - if (Beatmap.Value.BeatmapSetInfo.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID) + if (Beatmap.Value.BeatmapSetInfo.Hash == databasedSet.Hash) { return; } From 4d60f6fb6a0cd17fb4e330a4f67177bab083d4e8 Mon Sep 17 00:00:00 2001 From: Samuel Van Allen Date: Wed, 3 Apr 2019 22:37:50 +0800 Subject: [PATCH 0476/5608] Use collection initializer and added missing blank line --- .../Select/Carousel/DrawableCarouselBeatmap.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index a31e40dd8f..0b60ca03a7 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -168,16 +168,18 @@ namespace osu.Game.Screens.Select.Carousel base.ApplyState(); } + public MenuItem[] ContextMenuItems { get { - List items = new List(); - - items.Add(new OsuMenuItem("Play", MenuItemType.Highlighted, () => startRequested?.Invoke(beatmap))); - items.Add(new OsuMenuItem("Edit", MenuItemType.Standard, () => editRequested?.Invoke(beatmap))); - items.Add(new OsuMenuItem("Hide", MenuItemType.Destructive, () => hideRequested?.Invoke(beatmap))); - + List items = new List() + { + new OsuMenuItem("Play", MenuItemType.Highlighted, () => startRequested?.Invoke(beatmap)), + new OsuMenuItem("Edit", MenuItemType.Standard, () => editRequested?.Invoke(beatmap)), + new OsuMenuItem("Hide", MenuItemType.Destructive, () => hideRequested?.Invoke(beatmap)), + }; + if (beatmap.OnlineBeatmapID.HasValue) items.Add(new OsuMenuItem("Details", MenuItemType.Standard, () => beatmapOverlay?.FetchAndShowBeatmap(beatmap.OnlineBeatmapID.Value))); From 36609244410b25aa4f42596d126d3a66651998e3 Mon Sep 17 00:00:00 2001 From: Samuel Van Allen Date: Wed, 3 Apr 2019 22:40:20 +0800 Subject: [PATCH 0477/5608] Trimmed whitespace --- osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 0b60ca03a7..c19fa73ab1 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -179,7 +179,7 @@ namespace osu.Game.Screens.Select.Carousel new OsuMenuItem("Edit", MenuItemType.Standard, () => editRequested?.Invoke(beatmap)), new OsuMenuItem("Hide", MenuItemType.Destructive, () => hideRequested?.Invoke(beatmap)), }; - + if (beatmap.OnlineBeatmapID.HasValue) items.Add(new OsuMenuItem("Details", MenuItemType.Standard, () => beatmapOverlay?.FetchAndShowBeatmap(beatmap.OnlineBeatmapID.Value))); From bb516da5b6903c454c5b9197e57ab4db72b39a23 Mon Sep 17 00:00:00 2001 From: Samuel Van Allen Date: Wed, 3 Apr 2019 22:57:05 +0800 Subject: [PATCH 0478/5608] Removed redundant empty argument list --- osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index c19fa73ab1..0a20f2aa6d 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -173,7 +173,7 @@ namespace osu.Game.Screens.Select.Carousel { get { - List items = new List() + List items = new List { new OsuMenuItem("Play", MenuItemType.Highlighted, () => startRequested?.Invoke(beatmap)), new OsuMenuItem("Edit", MenuItemType.Standard, () => editRequested?.Invoke(beatmap)), From 5825890c31b6c74e604f21b90f1d9b481b1e1091 Mon Sep 17 00:00:00 2001 From: RORIdev Date: Wed, 3 Apr 2019 16:58:44 -0300 Subject: [PATCH 0479/5608] Implemented the 3 lives system into the Easy Mod. --- osu.Game/Screens/Play/Player.cs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0eebefec86..f45c5d1028 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -51,6 +51,8 @@ namespace osu.Game.Screens.Play public int RestartCount; + public int Lives = 2; + [Resolved] private ScoreManager scoreManager { get; set; } @@ -323,8 +325,32 @@ namespace osu.Game.Screens.Play protected FailOverlay FailOverlay { get; private set; } + private bool onFail() { + + //issue #3372 + if (Beatmap.Value.Mods.Value.Any(x => x is ModEasy)) + { + + if (Lives != 0) + { + Lives--; + ScoreProcessor.Health.Value = 100; + return false; + } + else + { + GameplayClockContainer.Stop(); + HasFailed = true; + FailOverlay.Retries = RestartCount; + FailOverlay.Show(); + return true; + + } + + } + if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) return false; @@ -332,6 +358,8 @@ namespace osu.Game.Screens.Play HasFailed = true; + + // There is a chance that we could be in a paused state as the ruleset's internal clock (see FrameStabilityContainer) // could process an extra frame after the GameplayClock is stopped. // In such cases we want the fail state to precede a user triggered pause. From e9f4cdd5119d75e4c57a8cb40abbf0e46c314dcd Mon Sep 17 00:00:00 2001 From: RORIdev Date: Wed, 3 Apr 2019 17:18:42 -0300 Subject: [PATCH 0480/5608] Removed code duplication. --- osu.Game/Screens/Play/Player.cs | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index f45c5d1028..b71bb87bdb 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -325,14 +325,18 @@ namespace osu.Game.Screens.Play protected FailOverlay FailOverlay { get; private set; } - + private void Fail() + { + GameplayClockContainer.Stop(); + HasFailed = true; + FailOverlay.Retries = RestartCount; + FailOverlay.Show(); + } private bool onFail() { - //issue #3372 if (Beatmap.Value.Mods.Value.Any(x => x is ModEasy)) { - if (Lives != 0) { Lives--; @@ -341,33 +345,18 @@ namespace osu.Game.Screens.Play } else { - GameplayClockContainer.Stop(); - HasFailed = true; - FailOverlay.Retries = RestartCount; - FailOverlay.Show(); + Fail(); return true; - } - } - if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) return false; - - GameplayClockContainer.Stop(); - - HasFailed = true; - - - // There is a chance that we could be in a paused state as the ruleset's internal clock (see FrameStabilityContainer) // could process an extra frame after the GameplayClock is stopped. // In such cases we want the fail state to precede a user triggered pause. if (PauseOverlay.State == Visibility.Visible) PauseOverlay.Hide(); - - FailOverlay.Retries = RestartCount; - FailOverlay.Show(); + Fail(); return true; } From 9cfe17cbf1cec2eacdbca515844de530c6bc4ef5 Mon Sep 17 00:00:00 2001 From: RORIdev Date: Wed, 3 Apr 2019 17:28:48 -0300 Subject: [PATCH 0481/5608] Makes AppVeyour happy. --- osu.Game/Screens/Play/Player.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index b71bb87bdb..800adcd928 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -325,7 +325,7 @@ namespace osu.Game.Screens.Play protected FailOverlay FailOverlay { get; private set; } - private void Fail() + private void fail() { GameplayClockContainer.Stop(); HasFailed = true; @@ -345,7 +345,7 @@ namespace osu.Game.Screens.Play } else { - Fail(); + fail(); return true; } } @@ -356,7 +356,7 @@ namespace osu.Game.Screens.Play // In such cases we want the fail state to precede a user triggered pause. if (PauseOverlay.State == Visibility.Visible) PauseOverlay.Hide(); - Fail(); + fail(); return true; } From f6e1cb07a1b9d3418105e2c8399caba3bd9fe1ee Mon Sep 17 00:00:00 2001 From: RORIdev Date: Wed, 3 Apr 2019 17:58:17 -0300 Subject: [PATCH 0482/5608] Changed the logic to ModEasy. --- osu.Game/Rulesets/Mods/ModEasy.cs | 20 +++++++++++++++++++- osu.Game/Screens/Play/Player.cs | 29 ++++++----------------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index 56ec0bec06..ec18496966 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -5,11 +5,13 @@ using System; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModEasy : Mod, IApplicableToDifficulty + public abstract class ModEasy : Mod, IApplicableToDifficulty, IApplicableToScoreProcessor { + public static int Lives = 2; public override string Name => "Easy"; public override string Acronym => "EZ"; public override IconUsage Icon => OsuIcon.ModEasy; @@ -26,5 +28,21 @@ namespace osu.Game.Rulesets.Mods difficulty.DrainRate *= ratio; difficulty.OverallDifficulty *= ratio; } + + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + { + scoreProcessor.Health.ValueChanged += ValueChanged =>{ + if (scoreProcessor.Health.Value == 0) + { + if (Lives != 0) + { + Lives--; + scoreProcessor.Health.Value = 100; + } + } + + } ; + + } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 800adcd928..864cbc8878 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -325,38 +325,21 @@ namespace osu.Game.Screens.Play protected FailOverlay FailOverlay { get; private set; } - private void fail() - { - GameplayClockContainer.Stop(); - HasFailed = true; - FailOverlay.Retries = RestartCount; - FailOverlay.Show(); - } + private bool onFail() { - //issue #3372 - if (Beatmap.Value.Mods.Value.Any(x => x is ModEasy)) - { - if (Lives != 0) - { - Lives--; - ScoreProcessor.Health.Value = 100; - return false; - } - else - { - fail(); - return true; - } - } + if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) return false; + GameplayClockContainer.Stop(); + HasFailed = true; // There is a chance that we could be in a paused state as the ruleset's internal clock (see FrameStabilityContainer) // could process an extra frame after the GameplayClock is stopped. // In such cases we want the fail state to precede a user triggered pause. if (PauseOverlay.State == Visibility.Visible) PauseOverlay.Hide(); - fail(); + FailOverlay.Retries = RestartCount; + FailOverlay.Show(); return true; } From 621f8fd78dbde2604122d67548ed6edf635e35fc Mon Sep 17 00:00:00 2001 From: RORIdev Date: Wed, 3 Apr 2019 18:05:47 -0300 Subject: [PATCH 0483/5608] Trimmed whitespaces. --- osu.Game/Rulesets/Mods/ModEasy.cs | 4 +--- osu.Game/Screens/Play/Player.cs | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index ec18496966..9099235aed 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -40,9 +40,7 @@ namespace osu.Game.Rulesets.Mods scoreProcessor.Health.Value = 100; } } - - } ; - + }; } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 864cbc8878..68f8fd38d3 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -325,10 +325,8 @@ namespace osu.Game.Screens.Play protected FailOverlay FailOverlay { get; private set; } - private bool onFail() { - if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) return false; GameplayClockContainer.Stop(); From ebaaaef4d6ac68b2a5d3007a8d3c1c88373e3275 Mon Sep 17 00:00:00 2001 From: RORIdev Date: Wed, 3 Apr 2019 18:17:21 -0300 Subject: [PATCH 0484/5608] Fixed Inconsistent Naming --- osu.Game/Rulesets/Mods/ModEasy.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index 9099235aed..c0f75b7c83 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Mods public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { - scoreProcessor.Health.ValueChanged += ValueChanged =>{ + scoreProcessor.Health.ValueChanged += valueChanged =>{ if (scoreProcessor.Health.Value == 0) { if (Lives != 0) From 5aa284781eef3baab0c28e54f26c8a1f9ba0f993 Mon Sep 17 00:00:00 2001 From: RORIdev Date: Wed, 3 Apr 2019 19:20:20 -0300 Subject: [PATCH 0485/5608] Reverted back Player.cs changes. --- osu.Game/Rulesets/Mods/ModEasy.cs | 5 +++-- osu.Game/Screens/Play/Player.cs | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index c0f75b7c83..16f54d0743 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mods { public abstract class ModEasy : Mod, IApplicableToDifficulty, IApplicableToScoreProcessor { - public static int Lives = 2; + public int Lives = 2; public override string Name => "Easy"; public override string Acronym => "EZ"; public override IconUsage Icon => OsuIcon.ModEasy; @@ -31,7 +31,8 @@ namespace osu.Game.Rulesets.Mods public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { - scoreProcessor.Health.ValueChanged += valueChanged =>{ + scoreProcessor.Health.ValueChanged += valueChanged => + { if (scoreProcessor.Health.Value == 0) { if (Lives != 0) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 68f8fd38d3..0eebefec86 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -51,8 +51,6 @@ namespace osu.Game.Screens.Play public int RestartCount; - public int Lives = 2; - [Resolved] private ScoreManager scoreManager { get; set; } @@ -329,13 +327,17 @@ namespace osu.Game.Screens.Play { if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) return false; + GameplayClockContainer.Stop(); + HasFailed = true; + // There is a chance that we could be in a paused state as the ruleset's internal clock (see FrameStabilityContainer) // could process an extra frame after the GameplayClock is stopped. // In such cases we want the fail state to precede a user triggered pause. if (PauseOverlay.State == Visibility.Visible) PauseOverlay.Hide(); + FailOverlay.Retries = RestartCount; FailOverlay.Show(); return true; From ccc804a9b2ac61e4f90448fd265dac4ec1db568f Mon Sep 17 00:00:00 2001 From: jorolf Date: Thu, 4 Apr 2019 00:24:42 +0200 Subject: [PATCH 0486/5608] get everything working again --- .../{ => Online}/TestCaseUserProfileHeader.cs | 4 +-- .../Graphics/UserInterface/ScreenTitle.cs | 6 +++-- .../Profile/Header/BottomHeaderContainer.cs | 18 ++++++------- .../Profile/Header/CenterHeaderContainer.cs | 6 ++--- .../Profile/Header/ProfileMessageButton.cs | 8 +++--- .../Overlays/Profile/Header/SupporterIcon.cs | 5 ++-- osu.Game/Overlays/Profile/ProfileHeader.cs | 27 +++++++++++++------ osu.Game/Screens/Multi/Header.cs | 2 +- osu.Game/Users/UserCoverBackground.cs | 7 ++--- osu.Game/Users/UserPanel.cs | 2 +- 10 files changed, 49 insertions(+), 36 deletions(-) rename osu.Game.Tests/Visual/{ => Online}/TestCaseUserProfileHeader.cs (96%) diff --git a/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs similarity index 96% rename from osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs rename to osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs index 8f36b4dda8..98bad9831f 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays.Profile; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { public class TestCaseUserProfileHeader : OsuTestCase { @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual }; [Resolved] - private APIAccess api { get; set; } + private IAPIProvider api { get; set; } private readonly ProfileHeader header; diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index 1574023068..b9d9b5427d 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -14,6 +14,8 @@ namespace osu.Game.Graphics.UserInterface { private readonly SpriteIcon iconSprite; private readonly OsuSpriteText titleText, pageText; + public const float ICON_WIDTH = icon_size + icon_spacing; + private const float icon_size = 25, icon_spacing = 10; protected IconUsage Icon { @@ -48,12 +50,12 @@ namespace osu.Game.Graphics.UserInterface new FillFlowContainer { AutoSizeAxes = Axes.Both, - Spacing = new Vector2(10, 0), + Spacing = new Vector2(icon_spacing, 0), Children = new Drawable[] { iconSprite = new SpriteIcon { - Size = new Vector2(25), + Size = new Vector2(icon_size), }, new FillFlowContainer { diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 1f9d741b8d..04b70ea10f 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.Profile.Header bottomTopLinkContainer.AddText("Contributed "); bottomTopLinkContainer.AddLink($@"{user.PostCount:#,##0} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: bold); - void tryAddInfo(FontAwesome icon, string content, string link = null) + void tryAddInfo(IconUsage icon, string content, string link = null) { if (string.IsNullOrEmpty(content)) return; @@ -138,16 +138,16 @@ namespace osu.Game.Overlays.Profile.Header websiteWithoutProtcol = websiteWithoutProtcol.Substring(protocolIndex + 2); } - tryAddInfo(FontAwesome.fa_map_marker, user.Location); - tryAddInfo(FontAwesome.fa_heart_o, user.Interests); - tryAddInfo(FontAwesome.fa_suitcase, user.Occupation); + tryAddInfo(FontAwesome.Solid.MapMarker, user.Location); + tryAddInfo(OsuIcon.Heart, user.Interests); + tryAddInfo(FontAwesome.Solid.Suitcase, user.Occupation); bottomLinkContainer.NewLine(); if (!string.IsNullOrEmpty(user.Twitter)) - tryAddInfo(FontAwesome.fa_twitter, "@" + user.Twitter, $@"https://twitter.com/{user.Twitter}"); - tryAddInfo(FontAwesome.fa_gamepad, user.Discord); //todo: update fontawesome to include discord logo - tryAddInfo(FontAwesome.fa_skype, user.Skype, @"skype:" + user.Skype + @"?chat"); - tryAddInfo(FontAwesome.fa_lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); - tryAddInfo(FontAwesome.fa_link, websiteWithoutProtcol, user.Website); + tryAddInfo(FontAwesome.Brands.Twitter, "@" + user.Twitter, $@"https://twitter.com/{user.Twitter}"); + tryAddInfo(FontAwesome.Brands.Discord, user.Discord); + tryAddInfo(FontAwesome.Brands.Skype, user.Skype, @"skype:" + user.Skype + @"?chat"); + tryAddInfo(FontAwesome.Brands.Lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); + tryAddInfo(FontAwesome.Solid.Link, websiteWithoutProtcol, user.Website); } } } diff --git a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs index b5e04bee9e..3d0b9b9db4 100644 --- a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs @@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Profile.Header { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Icon = FontAwesome.fa_user, + Icon = FontAwesome.Solid.User, FillMode = FillMode.Fit, Size = new Vector2(50, 14) }, @@ -116,7 +116,7 @@ namespace osu.Game.Overlays.Profile.Header Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(20), - Icon = FontAwesome.fa_chevron_up, + Icon = FontAwesome.Solid.ChevronUp, }, } }, @@ -212,7 +212,7 @@ namespace osu.Game.Overlays.Profile.Header detailsToggleButton.Action = () => { detailsVisible = !detailsVisible; - expandButtonIcon.Icon = detailsVisible ? FontAwesome.fa_chevron_down : FontAwesome.fa_chevron_up; + expandButtonIcon.Icon = detailsVisible ? FontAwesome.Solid.ChevronDown : FontAwesome.Solid.ChevronUp; hiddenDetailContainer.Alpha = detailsVisible ? 1 : 0; expandedDetailContainer.Alpha = detailsVisible ? 0 : 1; DetailsVisibilityAction(detailsVisible); diff --git a/osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs b/osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs index a14c0324d7..3121eae727 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs +++ b/osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs @@ -4,7 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Graphics; +using osu.Framework.Graphics.Sprites; using osu.Game.Online.API; using osu.Game.Online.Chat; using osu.Game.Users; @@ -26,7 +26,7 @@ namespace osu.Game.Overlays.Profile.Header private ChatOverlay chatOverlay { get; set; } [Resolved] - private APIAccess apiAccess { get; set; } + private IAPIProvider apiProvider { get; set; } public ProfileMessageButton() { @@ -37,7 +37,7 @@ namespace osu.Game.Overlays.Profile.Header { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Icon = FontAwesome.fa_envelope, + Icon = FontAwesome.Solid.Envelope, FillMode = FillMode.Fit, Size = new Vector2(50, 14) }; @@ -51,7 +51,7 @@ namespace osu.Game.Overlays.Profile.Header chatOverlay?.Show(); }; - User.ValueChanged += e => Content.Alpha = !e.NewValue.PMFriendsOnly && apiAccess.LocalUser.Value.Id != e.NewValue.Id ? 1 : 0; + User.ValueChanged += e => Content.Alpha = !e.NewValue.PMFriendsOnly && apiProvider.LocalUser.Value.Id != e.NewValue.Id ? 1 : 0; } } } diff --git a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs index 3cb30ab044..569ed252b7 100644 --- a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs @@ -37,7 +37,7 @@ namespace osu.Game.Overlays.Profile.Header { Width = 12, RelativeSizeAxes = Axes.Y, - Icon = FontAwesome.fa_heart, + Icon = FontAwesome.Solid.Heart, }); } @@ -66,8 +66,7 @@ namespace osu.Game.Overlays.Profile.Header AutoSizeAxes = Axes.X, Height = 0.6f, Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Icon = FontAwesome.Solid.Heart, + Origin = Anchor.Centre } } }; diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 988fa3afd9..b75de39c4b 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -5,11 +5,11 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; using osu.Framework.Bindables; +using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Profile @@ -17,7 +17,6 @@ namespace osu.Game.Overlays.Profile public class ProfileHeader : Container { private readonly UserCoverBackground coverContainer; - private readonly ScreenTitle coverTitle; private readonly ProfileHeaderTabControl infoTabControl; private const float cover_height = 150; @@ -52,10 +51,9 @@ namespace osu.Game.Overlays.Profile Depth = -float.MaxValue, Children = new Drawable[] { - coverTitle = new ScreenTitle + new ProfileHeaderTitle { - Title = "Player ", - Page = "Info" + X = -ScreenTitle.ICON_WIDTH, }, infoTabControl = new ProfileHeaderTabControl { @@ -113,10 +111,8 @@ namespace osu.Game.Overlays.Profile } [BackgroundDependencyLoader] - private void load(OsuColour colours, TextureStore textures) + private void load(OsuColour colours) { - coverTitle.AccentColour = colours.CommunityUserGreen; - infoTabControl.AccentColour = colours.CommunityUserGreen; } @@ -131,5 +127,20 @@ namespace osu.Game.Overlays.Profile { public string TooltipText { get; set; } } + + private class ProfileHeaderTitle : ScreenTitle + { + public ProfileHeaderTitle() + { + Title = "Player "; + Section = "Info"; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AccentColour = colours.CommunityUserGreen; + } + } } } diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index 7924086389..35edc5bac8 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Multi { Anchor = Anchor.CentreLeft, Origin = Anchor.BottomLeft, - X = -35, + X = -ScreenTitle.ICON_WIDTH, }, breadcrumbs = new HeaderBreadcrumbControl(stack) { diff --git a/osu.Game/Users/UserCoverBackground.cs b/osu.Game/Users/UserCoverBackground.cs index d037f809b4..dbc132995a 100644 --- a/osu.Game/Users/UserCoverBackground.cs +++ b/osu.Game/Users/UserCoverBackground.cs @@ -36,15 +36,16 @@ namespace osu.Game.Users } else { - return new Sprite + var sprite = new Sprite { RelativeSizeAxes = Axes.Both, Texture = textures.Get(user.CoverUrl), FillMode = FillMode.Fill, Anchor = Anchor.Centre, - Origin = Anchor.Centre, - OnLoadComplete = d => d.FadeInFromZero(400), + Origin = Anchor.Centre }; + sprite.OnLoadComplete += d => d.FadeInFromZero(400); + return sprite; } } } diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 0e928e0aac..eb7f0941fb 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -76,7 +76,7 @@ namespace osu.Game.Users Children = new Drawable[] { - new DelayedLoadWrapper(coverBackground = new UserCoverBackground(user) + new DelayedLoadWrapper(coverBackground = new UserCoverBackground { RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, From 28bf3156badefe95399de0e73c1f288aa4721f8d Mon Sep 17 00:00:00 2001 From: RORIdev Date: Wed, 3 Apr 2019 19:32:29 -0300 Subject: [PATCH 0487/5608] Fixed the mod being not resetting. --- osu.Game/Rulesets/Mods/ModEasy.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index 16f54d0743..03b69b3163 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mods { public abstract class ModEasy : Mod, IApplicableToDifficulty, IApplicableToScoreProcessor { - public int Lives = 2; + public static int Lives = 2; public override string Name => "Easy"; public override string Acronym => "EZ"; public override IconUsage Icon => OsuIcon.ModEasy; @@ -40,6 +40,10 @@ namespace osu.Game.Rulesets.Mods Lives--; scoreProcessor.Health.Value = 100; } + else + { + Lives = 2; + } } }; } From ba871364514ae468bc5e0a47a12c4adda5206dc0 Mon Sep 17 00:00:00 2001 From: jorolf Date: Thu, 4 Apr 2019 00:57:15 +0200 Subject: [PATCH 0488/5608] add gradient and fix remaining error --- .../Visual/Online/TestCaseUserProfile.cs | 10 +++------- osu.Game/Overlays/Profile/ProfileHeader.cs | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs index abb96b8e84..c455c092ed 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs @@ -20,7 +20,9 @@ namespace osu.Game.Tests.Visual.Online public class TestCaseUserProfile : OsuTestCase { private readonly TestUserProfileOverlay profile; - private IAPIProvider api; + + [Resolved] + private IAPIProvider api { get; set; } public override IReadOnlyList RequiredTypes => new[] { @@ -75,12 +77,6 @@ namespace osu.Game.Tests.Visual.Online Add(profile = new TestUserProfileOverlay()); } - [BackgroundDependencyLoader] - private void load(APIAccess api) - { - this.api = api; - } - protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index b75de39c4b..776fcbb8b7 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -9,6 +9,9 @@ using osu.Game.Graphics; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -35,10 +38,23 @@ namespace osu.Game.Overlays.Profile Children = new Drawable[] { - coverContainer = new UserCoverBackground + new Container { RelativeSizeAxes = Axes.X, Height = cover_height, + Masking = true, + Children = new Drawable[] + { + coverContainer = new UserCoverBackground + { + RelativeSizeAxes = Axes.Both, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(OsuColour.FromHex("222").Opacity(0.8f), OsuColour.FromHex("222").Opacity(0.2f)) + }, + } }, new Container { From ff1815e714d66ab76192115907361854e3bf0898 Mon Sep 17 00:00:00 2001 From: RORIdev Date: Wed, 3 Apr 2019 20:22:48 -0300 Subject: [PATCH 0489/5608] Fixed lives being not reseting between maps. E.G. quitting a map with only 1 revive and getting 2 lives on another map. --- osu.Game/Rulesets/Mods/ModEasy.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index 03b69b3163..ae1e6145d1 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mods { public abstract class ModEasy : Mod, IApplicableToDifficulty, IApplicableToScoreProcessor { - public static int Lives = 2; + public static int Lives; public override string Name => "Easy"; public override string Acronym => "EZ"; public override IconUsage Icon => OsuIcon.ModEasy; @@ -31,6 +31,7 @@ namespace osu.Game.Rulesets.Mods public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { + Lives = 2; scoreProcessor.Health.ValueChanged += valueChanged => { if (scoreProcessor.Health.Value == 0) From 27fe6f610a384badc77c53a5021dda84a200e7c2 Mon Sep 17 00:00:00 2001 From: RORIdev Date: Wed, 3 Apr 2019 22:55:09 -0300 Subject: [PATCH 0490/5608] Removed deprecated code. Thanks peppy. --- osu.Game/Rulesets/Mods/ModEasy.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index ae1e6145d1..85cac872b8 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -41,10 +41,6 @@ namespace osu.Game.Rulesets.Mods Lives--; scoreProcessor.Health.Value = 100; } - else - { - Lives = 2; - } } }; } From 6b5458a625840759eb178278a88f423532359081 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 4 Apr 2019 11:22:05 +0900 Subject: [PATCH 0491/5608] Clean up test cases --- .../Visual/TestCaseLogoFacadeContainer.cs | 92 +++++++++---------- osu.Game.Tests/Visual/TestCasePositionAxes.cs | 33 ------- .../Containers/LogoFacadeContainer.cs | 23 ++--- 3 files changed, 57 insertions(+), 91 deletions(-) delete mode 100644 osu.Game.Tests/Visual/TestCasePositionAxes.cs diff --git a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs index bd1fb932bb..d66ac19aed 100644 --- a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Drawing; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -35,21 +34,18 @@ namespace osu.Game.Tests.Visual }; private OsuLogo logo; - private readonly Bindable uiScale = new Bindable(); - private LogoFacadeContainer logoFacadeContainer; + private TestLogoFacadeContainer facadeContainer; private Container transferContainer; private Box visualBox; private Box transferContainerBox; private Container logoFacade; - private bool randomPositions = false; + private bool randomPositions; [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - Add(logo = new OsuLogo { Scale = new Vector2(0.15f), RelativePositionAxes = Axes.None }); - config.BindWith(OsuSetting.UIScale, uiScale); AddSliderStep("Adjust scale", 0.8f, 1.5f, 1f, v => uiScale.Value = v); } @@ -60,8 +56,8 @@ namespace osu.Game.Tests.Visual AddStep("Clear facades", () => { Clear(); - Add(logo = new OsuLogo { Scale = new Vector2(0.15f), RelativePositionAxes = Axes.None }); - logoFacadeContainer = null; + Add(logo = new OsuLogo { Scale = new Vector2(0.15f), RelativePositionAxes = Axes.Both }); + facadeContainer = null; transferContainer = null; }); } @@ -75,9 +71,9 @@ namespace osu.Game.Tests.Visual { AddToggleStep("Toggle move continuously", b => randomPositions = b); AddStep("Add facade containers", addFacadeContainers); - AddStep("Move facade to random position", StartTrackingRandom); + AddStep("Move facade to random position", startTrackingRandom); waitForMove(); - AddAssert("Logo is tracking", () => IsLogoTracking); + AddAssert("Logo is tracking", () => facadeContainer.IsLogoTracking); } /// @@ -87,10 +83,10 @@ namespace osu.Game.Tests.Visual public void RemoveFacadeTest() { AddStep("Add facade containers", addFacadeContainers); - AddStep("Move facade to random position", StartTrackingRandom); - AddStep("Remove facade from FacadeContainer", RemoveFacade); + AddStep("Move facade to random position", startTrackingRandom); + AddStep("Remove facade from FacadeContainer", removeFacade); waitForMove(); - AddAssert("Logo is not tracking", () => !IsLogoTracking); + AddAssert("Logo is not tracking", () => !facadeContainer.IsLogoTracking); } /// @@ -100,11 +96,16 @@ namespace osu.Game.Tests.Visual public void TransferFacadeTest() { AddStep("Add facade containers", addFacadeContainers); - AddStep("Move facade to random position", StartTrackingRandom); - AddStep("Remove facade from FacadeContainer", RemoveFacade); - AddStep("Transfer facade to a new container", TransferFacade); + AddStep("Move facade to random position", startTrackingRandom); + AddStep("Remove facade from FacadeContainer", removeFacade); + AddStep("Transfer facade to a new container", () => + { + transferContainer.Add(logoFacade); + transferContainerBox.Colour = Color4.Tomato; + moveLogoFacade(); + }); waitForMove(); - AddAssert("Logo is tracking", () => IsLogoTracking); + AddAssert("Logo is tracking", () => facadeContainer.IsLogoTracking); } /// @@ -115,9 +116,9 @@ namespace osu.Game.Tests.Visual { FillFlowContainer flowContainer; - AddStep("Create new Logo Facade Container", () => + AddStep("Create new flow container with facade", () => { - Add(logoFacadeContainer = new LogoFacadeContainer + Add(facadeContainer = new TestLogoFacadeContainer { AutoSizeAxes = Axes.Both, Origin = Anchor.TopCentre, @@ -153,7 +154,7 @@ namespace osu.Game.Tests.Visual Colour = Color4.White, RelativeSizeAxes = Axes.Both, }, - logoFacadeContainer.LogoFacade, + facadeContainer.LogoFacade, } }, new Box @@ -168,25 +169,28 @@ namespace osu.Game.Tests.Visual AddStep("Perform logo movements", () => { - logoFacadeContainer.Tracking = false; + facadeContainer.Tracking = false; logo.RelativePositionAxes = Axes.Both; logo.MoveTo(new Vector2(0.5f), 500, Easing.InOutExpo); - logoFacadeContainer.SetLogo(logo, 1.0f, 1000, Easing.InOutExpo); + facadeContainer.SetLogo(logo, 1.0f, 1000, Easing.InOutExpo); visualBox.Colour = Color4.White; Scheduler.AddDelayed(() => { - logoFacadeContainer.Tracking = true; + facadeContainer.Tracking = true; visualBox.Colour = Color4.Tomato; }, 700); }); + + waitForMove(); + AddAssert("Logo is tracking", () => facadeContainer.IsLogoTracking); } private void addFacadeContainers() { AddRange(new Drawable[] { - logoFacadeContainer = new LogoFacadeContainer + facadeContainer = new TestLogoFacadeContainer { Alpha = 0.35f, RelativeSizeAxes = Axes.None, @@ -210,50 +214,44 @@ namespace osu.Game.Tests.Visual }, }); - logoFacadeContainer.Add(logoFacade = logoFacadeContainer.LogoFacade); - logoFacadeContainer.SetLogo(logo, 1.0f, 1000); + facadeContainer.Add(logoFacade = facadeContainer.LogoFacade); + facadeContainer.SetLogo(logo, 1.0f, 1000); } private void waitForMove() => AddWaitStep("Wait for transforms to finish", 5); - private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(logoFacade.ScreenSpaceDrawQuad.Centre); - - /// - /// Check that the logo is tracking the position of the facade, with an acceptable precision lenience. - /// - public bool IsLogoTracking => Math.Abs(logo.Position.X - logoTrackingPosition.X) < 0.001f && Math.Abs(logo.Position.Y - logoTrackingPosition.Y) < 0.001f; - - public void RemoveFacade() + private void removeFacade() { - logoFacadeContainer.Remove(logoFacade); + facadeContainer.Remove(logoFacade); visualBox.Colour = Color4.White; moveLogoFacade(); } - public void TransferFacade() + private void startTrackingRandom() { - transferContainer.Add(logoFacade); - transferContainerBox.Colour = Color4.Tomato; - moveLogoFacade(); - } - - public void StartTrackingRandom() - { - logoFacadeContainer.Tracking = true; + facadeContainer.Tracking = true; moveLogoFacade(); } private void moveLogoFacade() { - Random random = new Random(); - if (logoFacade.Transforms.Count == 0 && transferContainer.Transforms.Count == 0) + if (logoFacade?.Transforms.Count == 0 && transferContainer?.Transforms.Count == 0) { - logoFacadeContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300); + Random random = new Random(); + facadeContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300); transferContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300); } if (randomPositions) Schedule(moveLogoFacade); } + + private class TestLogoFacadeContainer : LogoFacadeContainer + { + /// + /// Check that the logo is tracking the position of the facade, with an acceptable precision lenience. + /// + public bool IsLogoTracking => Math.Abs(Logo.Position.X - LogoTrackingPosition().X) < 0.001f && Math.Abs(Logo.Position.Y - LogoTrackingPosition().Y) < 0.001f; + } } } diff --git a/osu.Game.Tests/Visual/TestCasePositionAxes.cs b/osu.Game.Tests/Visual/TestCasePositionAxes.cs deleted file mode 100644 index 04ff0dcf8c..0000000000 --- a/osu.Game.Tests/Visual/TestCasePositionAxes.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Testing; -using osuTK; - -namespace osu.Game.Tests.Visual -{ - public class TestCasePositionAxes : OsuTestCase - { - private Box box; - - public TestCasePositionAxes() - { - Add(new Container() - { - Size = new Vector2(1), - Child = box = new Box - { - Size = new Vector2(25), - RelativePositionAxes = Axes.None, - Position = new Vector2(250) - } - }); - - AddStep("blank", () => { }); - AddStep("change axes", () => box.RelativePositionAxes = Axes.Both); - } - } -} diff --git a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs index 76903a20b3..a80b687057 100644 --- a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs +++ b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs @@ -24,7 +24,8 @@ namespace osu.Game.Graphics.Containers /// public bool Tracking = false; - private OsuLogo logo; + protected OsuLogo Logo; + private float facadeScale; private Easing easing; private Vector2? startPosition; @@ -45,7 +46,7 @@ namespace osu.Game.Graphics.Containers /// The easing type of the initial transform. public void SetLogo(OsuLogo logo, float facadeScale = 1.0f, double duration = 0, Easing easing = Easing.None) { - this.logo = logo ?? throw new ArgumentNullException(nameof(logo)); + Logo = logo ?? throw new ArgumentNullException(nameof(logo)); this.facadeScale = facadeScale; this.duration = duration; this.easing = easing; @@ -54,11 +55,11 @@ namespace osu.Game.Graphics.Containers startPosition = null; } - private Vector2 logoTrackingPosition() + protected Vector2 LogoTrackingPosition() { Vector2 local; - local.X = logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).X / logo.Parent.RelativeToAbsoluteFactor.X; - local.Y = logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).Y / logo.Parent.RelativeToAbsoluteFactor.Y; + local.X = Logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).X / Logo.Parent.RelativeToAbsoluteFactor.X; + local.Y = Logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).Y / Logo.Parent.RelativeToAbsoluteFactor.Y; return local; } @@ -66,19 +67,19 @@ namespace osu.Game.Graphics.Containers { base.Update(); - if (logo == null || !Tracking) + if (Logo == null || !Tracking) return; // Account for the scale of the actual logo container, as SizeForFlow only accounts for the sprite scale. - LogoFacade.Size = new Vector2(logo.SizeForFlow * logo.Scale.X * facadeScale); + LogoFacade.Size = new Vector2(Logo.SizeForFlow * Logo.Scale.X * facadeScale); - if (LogoFacade.Parent != null && logo.Position != logoTrackingPosition()) + if (LogoFacade.Parent != null && Logo.Position != LogoTrackingPosition()) { // If this is our first update since tracking has started, initialize our starting values for interpolation if (startTime == null || startPosition == null) { startTime = Time.Current; - startPosition = logo.Position; + startPosition = Logo.Position; } if (duration != 0) @@ -88,11 +89,11 @@ namespace osu.Game.Graphics.Containers var mount = (float)Interpolation.ApplyEasing(easing, Math.Min(elapsedDuration / duration, 1)); // Interpolate the position of the logo, where mount 0 is where the logo was when it first began interpolating, and mount 1 is the target location. - logo.Position = Vector2.Lerp(startPosition ?? throw new ArgumentNullException(nameof(startPosition)), logoTrackingPosition(), mount); + Logo.Position = Vector2.Lerp(startPosition ?? throw new ArgumentNullException(nameof(startPosition)), LogoTrackingPosition(), mount); } else { - logo.Position = logoTrackingPosition(); + Logo.Position = LogoTrackingPosition(); } } } From 15b2b6af7d8c8da6c371b14ff4c571b1c284d423 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 4 Apr 2019 11:28:36 +0900 Subject: [PATCH 0492/5608] Clean up remaining assignments of logo relativePositionAxes --- osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs | 1 - osu.Game/Screens/Menu/ButtonSystem.cs | 2 -- osu.Game/Screens/Play/PlayerLoader.cs | 5 +---- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs index d66ac19aed..3e9d52483d 100644 --- a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs @@ -170,7 +170,6 @@ namespace osu.Game.Tests.Visual AddStep("Perform logo movements", () => { facadeContainer.Tracking = false; - logo.RelativePositionAxes = Axes.Both; logo.MoveTo(new Vector2(0.5f), 500, Easing.InOutExpo); facadeContainer.SetLogo(logo, 1.0f, 1000, Easing.InOutExpo); visualBox.Colour = Color4.White; diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index f13dadf3dd..cb95ec1765 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -276,8 +276,6 @@ namespace osu.Game.Screens.Menu game?.Toolbar.Hide(); logo.ClearTransforms(targetMember: nameof(Position)); - logo.RelativePositionAxes = Axes.Both; - logo.MoveTo(new Vector2(0.5f), 800, Easing.OutExpo); logo.ScaleTo(1, 800, Easing.OutExpo); }, buttonArea.Alpha * 150); diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 2ba5bd81d1..ba27f87ee6 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -131,12 +131,9 @@ namespace osu.Game.Screens.Play private void contentOut() { - // Ensure the logo is no longer tracking before we scale the content, and that its RelativePositionAxes have been returned. + // Ensure the logo is no longer tracking before we scale the content content.Tracking = false; - if (logo != null) - logo.RelativePositionAxes = Axes.Both; - content.ScaleTo(0.7f, 300, Easing.InQuint); content.FadeOut(250); } From e89143d76b94610bf88c3a733e64e340f97713e5 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 4 Apr 2019 12:07:11 +0900 Subject: [PATCH 0493/5608] Add xmldoc for LogoTrackingPosition --- osu.Game/Graphics/Containers/LogoFacadeContainer.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs index a80b687057..1664fdde4d 100644 --- a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs +++ b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs @@ -55,6 +55,12 @@ namespace osu.Game.Graphics.Containers startPosition = null; } + /// + /// Gets the position that the logo should move to with respect to the . + /// Manually performs a conversion of the Facade's position to the relative position of the Logo's Parent. + /// + /// Will only be correct if the logo's are set to Axes.Both + /// The position that the logo should move to in its parent's relative space. protected Vector2 LogoTrackingPosition() { Vector2 local; From b2857384b8f3c83be474b17cca9c7cc90342cf4e Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 4 Apr 2019 12:08:05 +0900 Subject: [PATCH 0494/5608] Remove unnecessary logo assignment --- osu.Game/Screens/Play/PlayerLoader.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index ba27f87ee6..ccfd965f53 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -37,8 +37,6 @@ namespace osu.Game.Screens.Play private BeatmapMetadataDisplay info; - private OsuLogo logo; - private bool hideOverlays; public override bool HideOverlaysOnEnter => hideOverlays; @@ -155,8 +153,6 @@ namespace osu.Game.Screens.Play { base.LogoArriving(logo, resuming); - this.logo = logo; - const double duration = 300; if (!resuming) From f2bbde83bf3788957ffb3ad7b7e35b1f2e4c9e6d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 4 Apr 2019 13:05:34 +0900 Subject: [PATCH 0495/5608] Use precision almost equals --- .../{ => UserInterface}/TestCaseLogoFacadeContainer.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) rename osu.Game.Tests/Visual/{ => UserInterface}/TestCaseLogoFacadeContainer.cs (97%) diff --git a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs similarity index 97% rename from osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs index 3e9d52483d..4bc4ae724a 100644 --- a/osu.Game.Tests/Visual/TestCaseLogoFacadeContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; +using osu.Framework.MathUtils; using osu.Framework.Testing; using osu.Game.Configuration; using osu.Game.Graphics.Containers; @@ -18,7 +19,7 @@ using osu.Game.Screens.Play; using osuTK; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { public class TestCaseLogoFacadeContainer : OsuTestCase { @@ -250,7 +251,7 @@ namespace osu.Game.Tests.Visual /// /// Check that the logo is tracking the position of the facade, with an acceptable precision lenience. /// - public bool IsLogoTracking => Math.Abs(Logo.Position.X - LogoTrackingPosition().X) < 0.001f && Math.Abs(Logo.Position.Y - LogoTrackingPosition().Y) < 0.001f; + public bool IsLogoTracking => Precision.AlmostEquals(Logo.Position, LogoTrackingPosition()); } } } From b2e932dc74c5eae1184172758b3a62789d23e719 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 4 Apr 2019 13:13:03 +0900 Subject: [PATCH 0496/5608] Clean up tests, xmldoc --- .../UserInterface/TestCaseLogoFacadeContainer.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs index 4bc4ae724a..5f864eeabb 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs @@ -41,9 +41,10 @@ namespace osu.Game.Tests.Visual.UserInterface private Box visualBox; private Box transferContainerBox; private Container logoFacade; - private bool randomPositions; + private const float visual_box_size = 72; + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { @@ -110,7 +111,7 @@ namespace osu.Game.Tests.Visual.UserInterface } /// - /// Add a facade to a flow container then move logo to facade. + /// Add a facade to a flow container, move the logo to the center of the screen, then start tracking on the facade. /// [Test] public void FlowContainerTest() @@ -139,13 +140,13 @@ namespace osu.Game.Tests.Visual.UserInterface Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Colour = Color4.Azure, - Size = new Vector2(70) + Size = new Vector2(visual_box_size) }, new Container { Alpha = 0.35f, RelativeSizeAxes = Axes.None, - Size = new Vector2(72), + Size = new Vector2(visual_box_size), Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Children = new Drawable[] @@ -163,7 +164,7 @@ namespace osu.Game.Tests.Visual.UserInterface Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Colour = Color4.Azure, - Size = new Vector2(70) + Size = new Vector2(visual_box_size) }, }; }); @@ -194,7 +195,7 @@ namespace osu.Game.Tests.Visual.UserInterface { Alpha = 0.35f, RelativeSizeAxes = Axes.None, - Size = new Vector2(72), + Size = new Vector2(visual_box_size), Child = visualBox = new Box { Colour = Color4.Tomato, @@ -205,7 +206,7 @@ namespace osu.Game.Tests.Visual.UserInterface { Alpha = 0.35f, RelativeSizeAxes = Axes.None, - Size = new Vector2(72), + Size = new Vector2(visual_box_size), Child = transferContainerBox = new Box { Colour = Color4.White, From 456459cafa91f49981dd085e43312d10e9dc1255 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 4 Apr 2019 13:25:24 +0900 Subject: [PATCH 0497/5608] Give flow container test long enough to finish --- .../Visual/UserInterface/TestCaseLogoFacadeContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs index 5f864eeabb..0b664a310a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs @@ -183,7 +183,7 @@ namespace osu.Game.Tests.Visual.UserInterface }, 700); }); - waitForMove(); + waitForMove(8); AddAssert("Logo is tracking", () => facadeContainer.IsLogoTracking); } @@ -219,7 +219,7 @@ namespace osu.Game.Tests.Visual.UserInterface facadeContainer.SetLogo(logo, 1.0f, 1000); } - private void waitForMove() => AddWaitStep("Wait for transforms to finish", 5); + private void waitForMove(int count = 5) => AddWaitStep("Wait for transforms to finish", count); private void removeFacade() { From 6f5e9fe50d3976de9c1d686bce6e14c75ada64f8 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 4 Apr 2019 13:33:13 +0900 Subject: [PATCH 0498/5608] Correct xmldoc --- osu.Game/Graphics/Containers/LogoFacadeContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs index 1664fdde4d..c37588cb55 100644 --- a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs +++ b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs @@ -57,7 +57,7 @@ namespace osu.Game.Graphics.Containers /// /// Gets the position that the logo should move to with respect to the . - /// Manually performs a conversion of the Facade's position to the relative position of the Logo's Parent. + /// Manually performs a conversion of the Facade's position to the Logo's parent's relative space. /// /// Will only be correct if the logo's are set to Axes.Both /// The position that the logo should move to in its parent's relative space. From d54750aa37e5a94a6f1c34c4168c1e4876181b74 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Apr 2019 17:10:29 +0900 Subject: [PATCH 0499/5608] Remove incorrect class --- .../Configuration/OsuConfigManager.cs | 32 ------------------- .../Configuration/OsuRulesetConfigManager.cs | 1 - 2 files changed, 33 deletions(-) delete mode 100644 osu.Game.Rulesets.Osu/Configuration/OsuConfigManager.cs diff --git a/osu.Game.Rulesets.Osu/Configuration/OsuConfigManager.cs b/osu.Game.Rulesets.Osu/Configuration/OsuConfigManager.cs deleted file mode 100644 index 492cc7cc7f..0000000000 --- a/osu.Game.Rulesets.Osu/Configuration/OsuConfigManager.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Configuration; -using osu.Game.Rulesets.Configuration; - -namespace osu.Game.Rulesets.Osu.Configuration -{ - public class OsuConfigManager : RulesetConfigManager - { - public OsuConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) - : base(settings, ruleset, variant) - { - } - - protected override void InitialiseDefaults() - { - base.InitialiseDefaults(); - - Set(OsuSetting.SnakingInSliders, true); - Set(OsuSetting.SnakingOutSliders, true); - Set(OsuSetting.ShowCursorTrail, true); - } - } - - public enum OsuSetting - { - SnakingInSliders, - SnakingOutSliders, - ShowCursorTrail - } -} diff --git a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs index 872e152e0d..f76635a932 100644 --- a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs @@ -16,7 +16,6 @@ namespace osu.Game.Rulesets.Osu.Configuration protected override void InitialiseDefaults() { base.InitialiseDefaults(); - Set(OsuRulesetSetting.SnakingInSliders, true); Set(OsuRulesetSetting.SnakingOutSliders, true); Set(OsuRulesetSetting.ShowCursorTrail, true); From 9802d8ab1133d33e267afcb173efac0da82579e0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Apr 2019 17:18:53 +0900 Subject: [PATCH 0500/5608] Rename setting --- osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs index 48eb74a74d..88adf72551 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.UI }, new SettingsCheckbox { - LabelText = "Show cursor trail", + LabelText = "Cursor trail", Bindable = config.GetBindable(OsuRulesetSetting.ShowCursorTrail) }, }; From e13fffaca3dd5b520a5073234d83a99b44f10cc3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Apr 2019 16:32:04 +0900 Subject: [PATCH 0501/5608] Make ScoreTable use TableContainer --- .../Online/TestCaseBeatmapSetOverlay.cs | 3 - .../Visual/Online/TestCaseScoresContainer.cs | 3 - .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 184 +++++++++++++----- .../BeatmapSet/Scores/ScoreTableHeaderRow.cs | 54 ----- .../BeatmapSet/Scores/ScoreTableRow.cs | 104 ---------- .../BeatmapSet/Scores/ScoreTableScoreRow.cs | 114 ----------- 6 files changed, 136 insertions(+), 326 deletions(-) delete mode 100644 osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs delete mode 100644 osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs delete mode 100644 osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs diff --git a/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs index 9cbccbd603..8363f8be04 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs @@ -25,9 +25,6 @@ namespace osu.Game.Tests.Visual.Online { typeof(Header), typeof(ScoreTable), - typeof(ScoreTableRow), - typeof(ScoreTableHeaderRow), - typeof(ScoreTableScoreRow), typeof(ScoreTableRowBackground), typeof(DrawableTopScore), typeof(ScoresContainer), diff --git a/osu.Game.Tests/Visual/Online/TestCaseScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestCaseScoresContainer.cs index 3d87e1743c..1ef4558691 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseScoresContainer.cs @@ -26,9 +26,6 @@ namespace osu.Game.Tests.Visual.Online typeof(TopScoreUserSection), typeof(TopScoreStatisticsSection), typeof(ScoreTable), - typeof(ScoreTableRow), - typeof(ScoreTableHeaderRow), - typeof(ScoreTableScoreRow), typeof(ScoreTableRowBackground), }; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 09ab0e3f6a..08e8dc7ecc 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -5,13 +5,26 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using System.Collections.Generic; using System.Linq; +using osu.Framework.Extensions; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.Chat; +using osu.Game.Online.Leaderboards; +using osu.Game.Rulesets.UI; using osu.Game.Scoring; +using osu.Game.Users; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Scores { - public class ScoreTable : CompositeDrawable + public class ScoreTable : TableContainer { - private readonly ScoresGrid scoresGrid; + private const float horizontal_inset = 20; + private const float row_height = 25; + private const int text_size = 14; + private readonly FillFlowContainer backgroundFlow; public ScoreTable() @@ -19,77 +32,152 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - InternalChildren = new Drawable[] + Padding = new MarginPadding { Horizontal = horizontal_inset }; + RowSize = new Dimension(GridSizeMode.Absolute, row_height); + + AddInternal(backgroundFlow = new FillFlowContainer { - backgroundFlow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = 25 } - }, - scoresGrid = new ScoresGrid - { - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.Absolute, 40), - new Dimension(GridSizeMode.Absolute, 70), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Distributed, minSize: 150), - new Dimension(GridSizeMode.Distributed, minSize: 70, maxSize: 90), - new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), - new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), - new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), - new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), - new Dimension(GridSizeMode.Distributed, minSize: 40, maxSize: 70), - new Dimension(GridSizeMode.AutoSize), - } - } - }; + RelativeSizeAxes = Axes.Both, + Depth = 1f, + Padding = new MarginPadding { Horizontal = -horizontal_inset }, + Margin = new MarginPadding { Top = row_height } + }); } public IReadOnlyList Scores { set { - scoresGrid.Content = new Drawable[0][]; + Content = null; backgroundFlow.Clear(); if (value == null || !value.Any()) return; - var content = new List - { - new ScoreTableHeaderRow(value.First()).CreateDrawables().ToArray() - }; - for (int i = 0; i < value.Count; i++) - { - content.Add(new ScoreTableScoreRow(i, value[i]).CreateDrawables().ToArray()); backgroundFlow.Add(new ScoreTableRowBackground(i)); - } - scoresGrid.Content = content.ToArray(); + Columns = createHeaders(value[0]); + Content = value.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); } } - private class ScoresGrid : GridContainer + private TableColumn[] createHeaders(ScoreInfo score) { - public ScoresGrid() + var columns = new List { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; + new TableColumn("rank", Anchor.CentreRight, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 70)), // grade + new TableColumn("score", Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("accuracy", Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("player", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 150)), + new TableColumn("max combo", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 70, maxSize: 90)) + }; + + foreach (var statistic in score.Statistics) + columns.Add(new TableColumn(statistic.Key.GetDescription(), Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70))); + + columns.AddRange(new[] + { + new TableColumn("pp", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 40, maxSize: 70)), + new TableColumn("mods", Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize)), + }); + + return columns.ToArray(); + } + + private Drawable[] createContent(int index, ScoreInfo score) + { + var content = new List + { + new OsuSpriteText + { + Text = $"#{index + 1}", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) + }, + new DrawableRank(score.Rank) + { + Size = new Vector2(30, 20) + }, + new OsuSpriteText + { + Margin = new MarginPadding { Right = horizontal_inset }, + Text = $@"{score.TotalScore:N0}", + Font = OsuFont.GetFont(size: text_size, weight: index == 0 ? FontWeight.Bold : FontWeight.Medium) + }, + new OsuSpriteText + { + Margin = new MarginPadding { Right = horizontal_inset }, + Text = $@"{score.Accuracy:P2}", + Font = OsuFont.GetFont(size: text_size), + Colour = score.Accuracy == 1 ? Color4.GreenYellow : Color4.White + }, + }; + + var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: text_size)) { AutoSizeAxes = Axes.Both }; + username.AddLink(score.User.Username, null, LinkAction.OpenUserProfile, score.User.Id.ToString(), "Open profile"); + + content.AddRange(new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding { Right = horizontal_inset }, + Spacing = new Vector2(5, 0), + Children = new Drawable[] + { + new DrawableFlag(score.User.Country) { Size = new Vector2(20, 13) }, + username + } + }, + new OsuSpriteText + { + Text = $@"{score.MaxCombo:N0}x", + Font = OsuFont.GetFont(size: text_size) + } + }); + + foreach (var kvp in score.Statistics) + { + content.Add(new OsuSpriteText + { + Text = $"{kvp.Value}", + Font = OsuFont.GetFont(size: text_size), + Colour = kvp.Value == 0 ? Color4.Gray : Color4.White + }); } - public Drawable[][] Content + content.AddRange(new Drawable[] { - get => base.Content; - set + new OsuSpriteText { - base.Content = value; + Text = $@"{score.PP:N0}", + Font = OsuFont.GetFont(size: text_size) + }, + new FillFlowContainer + { + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + ChildrenEnumerable = score.Mods.Select(m => new ModIcon(m) + { + AutoSizeAxes = Axes.Both, + Scale = new Vector2(0.3f) + }) + }, + }); - RowDimensions = Enumerable.Repeat(new Dimension(GridSizeMode.Absolute, 25), value.Length).ToArray(); - } + return content.ToArray(); + } + + protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty); + + private class HeaderText : OsuSpriteText + { + public HeaderText(string text) + { + Text = text.ToUpper(); + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black); } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs deleted file mode 100644 index f6f410a729..0000000000 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableHeaderRow.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using osu.Framework.Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Scoring; - -namespace osu.Game.Overlays.BeatmapSet.Scores -{ - public class ScoreTableHeaderRow : ScoreTableRow - { - private readonly ScoreInfo score; - - public ScoreTableHeaderRow(ScoreInfo score) - { - this.score = score; - } - - protected override Drawable CreateIndexCell() => new CellText("rank"); - - protected override Drawable CreateRankCell() => new Container(); - - protected override Drawable CreateScoreCell() => new CellText("score"); - - protected override Drawable CreateAccuracyCell() => new CellText("accuracy"); - - protected override Drawable CreateUserCell() => new CellText("player"); - - protected override IEnumerable CreateStatisticsCells() - { - yield return new CellText("max combo"); - - foreach (var kvp in score.Statistics) - yield return new CellText(kvp.Key.GetDescription()); - } - - protected override Drawable CreatePpCell() => new CellText("pp"); - - protected override Drawable CreateModsCell() => new CellText("mods"); - - private class CellText : OsuSpriteText - { - public CellText(string text) - { - Text = text.ToUpper(); - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black); - } - } - } -} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs deleted file mode 100644 index 15355512ba..0000000000 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRow.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; - -namespace osu.Game.Overlays.BeatmapSet.Scores -{ - public abstract class ScoreTableRow - { - protected const int TEXT_SIZE = 14; - - public IEnumerable CreateDrawables() - { - yield return new Container - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - Child = CreateIndexCell() - }; - - yield return new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Child = CreateRankCell() - }; - - yield return new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Right = 20 }, - Child = CreateScoreCell() - }; - - yield return new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Right = 20 }, - Child = CreateAccuracyCell() - }; - - yield return new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Right = 20 }, - Child = CreateUserCell() - }; - - foreach (var cell in CreateStatisticsCells()) - { - yield return new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Child = cell - }; - } - - yield return new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Child = CreatePpCell() - }; - - yield return new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Right = 20 }, - Child = CreateModsCell() - }; - } - - protected abstract Drawable CreateIndexCell(); - - protected abstract Drawable CreateRankCell(); - - protected abstract Drawable CreateScoreCell(); - - protected abstract Drawable CreateAccuracyCell(); - - protected abstract Drawable CreateUserCell(); - - protected abstract IEnumerable CreateStatisticsCells(); - - protected abstract Drawable CreatePpCell(); - - protected abstract Drawable CreateModsCell(); - } -} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs deleted file mode 100644 index 75d45d0b23..0000000000 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableScoreRow.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using System.Linq; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Online.Chat; -using osu.Game.Online.Leaderboards; -using osu.Game.Rulesets.UI; -using osu.Game.Scoring; -using osu.Game.Users; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Overlays.BeatmapSet.Scores -{ - public class ScoreTableScoreRow : ScoreTableRow - { - private readonly int index; - private readonly ScoreInfo score; - - public ScoreTableScoreRow(int index, ScoreInfo score) - { - this.index = index; - this.score = score; - } - - protected override Drawable CreateIndexCell() => new OsuSpriteText - { - Text = $"#{index + 1}", - Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold) - }; - - protected override Drawable CreateRankCell() => new DrawableRank(score.Rank) - { - Size = new Vector2(30, 20), - }; - - protected override Drawable CreateScoreCell() => new OsuSpriteText - { - Text = $@"{score.TotalScore:N0}", - Font = OsuFont.GetFont(size: TEXT_SIZE, weight: index == 0 ? FontWeight.Bold : FontWeight.Medium) - }; - - protected override Drawable CreateAccuracyCell() => new OsuSpriteText - { - Text = $@"{score.Accuracy:P2}", - Font = OsuFont.GetFont(size: TEXT_SIZE), - Colour = score.Accuracy == 1 ? Color4.GreenYellow : Color4.White - }; - - protected override Drawable CreateUserCell() - { - var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: TEXT_SIZE)) - { - AutoSizeAxes = Axes.Both, - }; - - username.AddLink(score.User.Username, null, LinkAction.OpenUserProfile, score.User.Id.ToString(), "Open profile"); - - return new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5, 0), - Children = new Drawable[] - { - new DrawableFlag(score.User.Country) { Size = new Vector2(20, 13) }, - username - } - }; - } - - protected override IEnumerable CreateStatisticsCells() - { - yield return new OsuSpriteText - { - Text = $@"{score.MaxCombo:N0}x", - Font = OsuFont.GetFont(size: TEXT_SIZE) - }; - - foreach (var kvp in score.Statistics) - { - yield return new OsuSpriteText - { - Text = $"{kvp.Value}", - Font = OsuFont.GetFont(size: TEXT_SIZE), - Colour = kvp.Value == 0 ? Color4.Gray : Color4.White - }; - } - } - - protected override Drawable CreatePpCell() => new OsuSpriteText - { - Text = $@"{score.PP:N0}", - Font = OsuFont.GetFont(size: TEXT_SIZE) - }; - - protected override Drawable CreateModsCell() => new FillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - ChildrenEnumerable = score.Mods.Select(m => new ModIcon(m) - { - AutoSizeAxes = Axes.Both, - Scale = new Vector2(0.3f) - }) - }; - } -} From a6bf076dc7fe9c9777bf546285973df963170cae Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Apr 2019 17:58:34 +0900 Subject: [PATCH 0502/5608] Adjust green colour --- osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 08e8dc7ecc..3addef854a 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -5,6 +5,7 @@ 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.Containers; @@ -27,6 +28,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly FillFlowContainer backgroundFlow; + private Color4 highAccuracyColour; + public ScoreTable() { RelativeSizeAxes = Axes.X; @@ -44,6 +47,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }); } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + highAccuracyColour = colours.GreenLight; + } + public IReadOnlyList Scores { set @@ -110,7 +119,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Margin = new MarginPadding { Right = horizontal_inset }, Text = $@"{score.Accuracy:P2}", Font = OsuFont.GetFont(size: text_size), - Colour = score.Accuracy == 1 ? Color4.GreenYellow : Color4.White + Colour = score.Accuracy == 1 ? highAccuracyColour : Color4.White }, }; From 5a3e5036ed81c3a67292fb0eac1bccf8eca82a5f Mon Sep 17 00:00:00 2001 From: RORIdev Date: Thu, 4 Apr 2019 13:21:53 -0300 Subject: [PATCH 0503/5608] All suggestions were applied. --- osu.Game/Rulesets/Mods/ModEasy.cs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index 85cac872b8..bdfa4f9bb5 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -2,7 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; using osu.Framework.Graphics.Sprites; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Scoring; @@ -11,7 +15,7 @@ namespace osu.Game.Rulesets.Mods { public abstract class ModEasy : Mod, IApplicableToDifficulty, IApplicableToScoreProcessor { - public static int Lives; + private int Lives; public override string Name => "Easy"; public override string Acronym => "EZ"; public override IconUsage Icon => OsuIcon.ModEasy; @@ -19,7 +23,7 @@ namespace osu.Game.Rulesets.Mods public override double ScoreMultiplier => 0.5; public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) }; - + public void ApplyToDifficulty(BeatmapDifficulty difficulty) { const float ratio = 0.5f; @@ -31,16 +35,17 @@ namespace osu.Game.Rulesets.Mods public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { + //Note : The lives has to be instaciated here in order to prevent the values from different plays to interfear + //with each other / not reseting after a restart , as this method is called once a play starts (to my knowlegde). + //This will be better implemented with a List once I know how to reliably get the game time and update it. + //If you know any information about that, please contact me because I didn't find a sollution to that. Lives = 2; scoreProcessor.Health.ValueChanged += valueChanged => { - if (scoreProcessor.Health.Value == 0) + if (scoreProcessor.Health.Value == scoreProcessor.Health.MinValue && Lives > 0) { - if (Lives != 0) - { - Lives--; - scoreProcessor.Health.Value = 100; - } + Lives--; + scoreProcessor.Health.Value = scoreProcessor.Health.MaxValue; } }; } From c19548122352bf86461b9bfe5c9abf6f4ca6f33b Mon Sep 17 00:00:00 2001 From: RORIdev Date: Thu, 4 Apr 2019 13:28:43 -0300 Subject: [PATCH 0504/5608] Trimmed Whitespace --- osu.Game/Rulesets/Mods/ModEasy.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index bdfa4f9bb5..96a2f5fd3f 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -23,7 +23,6 @@ namespace osu.Game.Rulesets.Mods public override double ScoreMultiplier => 0.5; public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) }; - public void ApplyToDifficulty(BeatmapDifficulty difficulty) { const float ratio = 0.5f; From ca6a73cb9d5933533416df8a3750d0ae89380931 Mon Sep 17 00:00:00 2001 From: RORIdev Date: Thu, 4 Apr 2019 18:04:49 -0300 Subject: [PATCH 0505/5608] Fixed Code Inspection Fails. --- osu.Game/Rulesets/Mods/ModEasy.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index 96a2f5fd3f..4365ed256f 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -2,11 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; using osu.Framework.Graphics.Sprites; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Scoring; @@ -15,7 +11,7 @@ namespace osu.Game.Rulesets.Mods { public abstract class ModEasy : Mod, IApplicableToDifficulty, IApplicableToScoreProcessor { - private int Lives; + private int lives; public override string Name => "Easy"; public override string Acronym => "EZ"; public override IconUsage Icon => OsuIcon.ModEasy; @@ -23,6 +19,7 @@ namespace osu.Game.Rulesets.Mods public override double ScoreMultiplier => 0.5; public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) }; + public void ApplyToDifficulty(BeatmapDifficulty difficulty) { const float ratio = 0.5f; @@ -38,12 +35,12 @@ namespace osu.Game.Rulesets.Mods //with each other / not reseting after a restart , as this method is called once a play starts (to my knowlegde). //This will be better implemented with a List once I know how to reliably get the game time and update it. //If you know any information about that, please contact me because I didn't find a sollution to that. - Lives = 2; + lives = 2; scoreProcessor.Health.ValueChanged += valueChanged => { - if (scoreProcessor.Health.Value == scoreProcessor.Health.MinValue && Lives > 0) + if (scoreProcessor.Health.Value == scoreProcessor.Health.MinValue && lives > 0) { - Lives--; + lives--; scoreProcessor.Health.Value = scoreProcessor.Health.MaxValue; } }; From 7047f305a1a7af92532d8902e4490f96119d23a9 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 5 Apr 2019 12:02:47 +0900 Subject: [PATCH 0506/5608] Apply reviews, add safety for multiple facades --- ...er.cs => TestCaseLogoTrackingContainer.cs} | 71 ++++---- .../Containers/LogoFacadeContainer.cs | 114 ------------- .../Containers/LogoTrackingContainer.cs | 156 ++++++++++++++++++ osu.Game/Screens/Menu/ButtonSystem.cs | 24 +-- osu.Game/Screens/Menu/OsuLogo.cs | 6 + osu.Game/Screens/Play/PlayerLoader.cs | 23 +-- 6 files changed, 223 insertions(+), 171 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{TestCaseLogoFacadeContainer.cs => TestCaseLogoTrackingContainer.cs} (77%) delete mode 100644 osu.Game/Graphics/Containers/LogoFacadeContainer.cs create mode 100644 osu.Game/Graphics/Containers/LogoTrackingContainer.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs similarity index 77% rename from osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs index 0b664a310a..4d255eb25a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoFacadeContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs @@ -21,13 +21,13 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestCaseLogoFacadeContainer : OsuTestCase + public class TestCaseLogoTrackingContainer : OsuTestCase { public override IReadOnlyList RequiredTypes => new[] { typeof(PlayerLoader), typeof(Player), - typeof(LogoFacadeContainer), + typeof(LogoTrackingContainer), typeof(ButtonSystem), typeof(ButtonSystemState), typeof(Menu), @@ -36,11 +36,11 @@ namespace osu.Game.Tests.Visual.UserInterface private OsuLogo logo; private readonly Bindable uiScale = new Bindable(); - private TestLogoFacadeContainer facadeContainer; + private TestLogoTrackingContainer trackingContainer; private Container transferContainer; private Box visualBox; private Box transferContainerBox; - private Container logoFacade; + private Drawable logoFacade; private bool randomPositions; private const float visual_box_size = 72; @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.UserInterface { Clear(); Add(logo = new OsuLogo { Scale = new Vector2(0.15f), RelativePositionAxes = Axes.Both }); - facadeContainer = null; + trackingContainer = null; transferContainer = null; }); } @@ -72,10 +72,10 @@ namespace osu.Game.Tests.Visual.UserInterface public void MoveFacadeTest() { AddToggleStep("Toggle move continuously", b => randomPositions = b); - AddStep("Add facade containers", addFacadeContainers); + AddStep("Add tracking containers", addFacadeContainers); AddStep("Move facade to random position", startTrackingRandom); waitForMove(); - AddAssert("Logo is tracking", () => facadeContainer.IsLogoTracking); + AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking); } /// @@ -84,11 +84,11 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void RemoveFacadeTest() { - AddStep("Add facade containers", addFacadeContainers); + AddStep("Add tracking containers", addFacadeContainers); AddStep("Move facade to random position", startTrackingRandom); AddStep("Remove facade from FacadeContainer", removeFacade); waitForMove(); - AddAssert("Logo is not tracking", () => !facadeContainer.IsLogoTracking); + AddAssert("Logo is not tracking", () => !trackingContainer.IsLogoTracking); } /// @@ -97,17 +97,12 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TransferFacadeTest() { - AddStep("Add facade containers", addFacadeContainers); + AddStep("Add tracking containers", addFacadeContainers); AddStep("Move facade to random position", startTrackingRandom); AddStep("Remove facade from FacadeContainer", removeFacade); - AddStep("Transfer facade to a new container", () => - { - transferContainer.Add(logoFacade); - transferContainerBox.Colour = Color4.Tomato; - moveLogoFacade(); - }); + AddStep("Transfer facade to a new container", addFacadeToNewContainer); waitForMove(); - AddAssert("Logo is tracking", () => facadeContainer.IsLogoTracking); + AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking); } /// @@ -120,7 +115,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Create new flow container with facade", () => { - Add(facadeContainer = new TestLogoFacadeContainer + Add(trackingContainer = new TestLogoTrackingContainer { AutoSizeAxes = Axes.Both, Origin = Anchor.TopCentre, @@ -156,7 +151,7 @@ namespace osu.Game.Tests.Visual.UserInterface Colour = Color4.White, RelativeSizeAxes = Axes.Both, }, - facadeContainer.LogoFacade, + trackingContainer.LogoFacade, } }, new Box @@ -171,27 +166,34 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Perform logo movements", () => { - facadeContainer.Tracking = false; + trackingContainer.Tracking = false; logo.MoveTo(new Vector2(0.5f), 500, Easing.InOutExpo); - facadeContainer.SetLogo(logo, 1.0f, 1000, Easing.InOutExpo); + trackingContainer.SetLogo(logo, 1.0f, 1000, Easing.InOutExpo); visualBox.Colour = Color4.White; Scheduler.AddDelayed(() => { - facadeContainer.Tracking = true; + trackingContainer.Tracking = true; visualBox.Colour = Color4.Tomato; }, 700); }); waitForMove(8); - AddAssert("Logo is tracking", () => facadeContainer.IsLogoTracking); + AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking); + } + + [Test] + public void SetFacadeSizeTest() + { + AddStep("Add tracking containers", addFacadeContainers); + AddStep("Break shit", () => { logoFacade.Size = new Vector2(0, 0); }); } private void addFacadeContainers() { AddRange(new Drawable[] { - facadeContainer = new TestLogoFacadeContainer + trackingContainer = new TestLogoTrackingContainer { Alpha = 0.35f, RelativeSizeAxes = Axes.None, @@ -215,22 +217,29 @@ namespace osu.Game.Tests.Visual.UserInterface }, }); - facadeContainer.Add(logoFacade = facadeContainer.LogoFacade); - facadeContainer.SetLogo(logo, 1.0f, 1000); + trackingContainer.Add(logoFacade = trackingContainer.LogoFacade); + trackingContainer.SetLogo(logo, 1.0f, 1000); } private void waitForMove(int count = 5) => AddWaitStep("Wait for transforms to finish", count); private void removeFacade() { - facadeContainer.Remove(logoFacade); + trackingContainer.Remove(logoFacade); visualBox.Colour = Color4.White; moveLogoFacade(); } private void startTrackingRandom() { - facadeContainer.Tracking = true; + trackingContainer.Tracking = true; + moveLogoFacade(); + } + + private void addFacadeToNewContainer() + { + transferContainer.Add(logoFacade); + transferContainerBox.Colour = Color4.Tomato; moveLogoFacade(); } @@ -239,7 +248,7 @@ namespace osu.Game.Tests.Visual.UserInterface if (logoFacade?.Transforms.Count == 0 && transferContainer?.Transforms.Count == 0) { Random random = new Random(); - facadeContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300); + trackingContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300); transferContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300); } @@ -247,12 +256,12 @@ namespace osu.Game.Tests.Visual.UserInterface Schedule(moveLogoFacade); } - private class TestLogoFacadeContainer : LogoFacadeContainer + private class TestLogoTrackingContainer : LogoTrackingContainer { /// /// Check that the logo is tracking the position of the facade, with an acceptable precision lenience. /// - public bool IsLogoTracking => Precision.AlmostEquals(Logo.Position, LogoTrackingPosition()); + public bool IsLogoTracking => Precision.AlmostEquals(Logo.Position, LogoTrackingPosition); } } } diff --git a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs b/osu.Game/Graphics/Containers/LogoFacadeContainer.cs deleted file mode 100644 index c37588cb55..0000000000 --- a/osu.Game/Graphics/Containers/LogoFacadeContainer.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.MathUtils; -using osu.Game.Screens.Menu; -using osuTK; - -namespace osu.Game.Graphics.Containers -{ - /// - /// A container that creates a to be used to update and track the position of an . - /// - public class LogoFacadeContainer : Container - { - protected virtual Facade CreateFacade() => new Facade(); - - public Facade LogoFacade { get; } - - /// - /// Whether or not the logo assigned to this FacadeContainer should be tracking the position its facade. - /// - public bool Tracking = false; - - protected OsuLogo Logo; - - private float facadeScale; - private Easing easing; - private Vector2? startPosition; - private double? startTime; - private double duration; - - public LogoFacadeContainer() - { - LogoFacade = CreateFacade(); - } - - /// - /// Assign the logo that should track the Facade's position, as well as how it should transform to its initial position. - /// - /// The instance of the logo to be used for tracking. - /// The scale of the facade. Does not actually affect the logo itself. - /// The duration of the initial transform. Default is instant. - /// The easing type of the initial transform. - public void SetLogo(OsuLogo logo, float facadeScale = 1.0f, double duration = 0, Easing easing = Easing.None) - { - Logo = logo ?? throw new ArgumentNullException(nameof(logo)); - this.facadeScale = facadeScale; - this.duration = duration; - this.easing = easing; - - startTime = null; - startPosition = null; - } - - /// - /// Gets the position that the logo should move to with respect to the . - /// Manually performs a conversion of the Facade's position to the Logo's parent's relative space. - /// - /// Will only be correct if the logo's are set to Axes.Both - /// The position that the logo should move to in its parent's relative space. - protected Vector2 LogoTrackingPosition() - { - Vector2 local; - local.X = Logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).X / Logo.Parent.RelativeToAbsoluteFactor.X; - local.Y = Logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).Y / Logo.Parent.RelativeToAbsoluteFactor.Y; - return local; - } - - protected override void Update() - { - base.Update(); - - if (Logo == null || !Tracking) - return; - - // Account for the scale of the actual logo container, as SizeForFlow only accounts for the sprite scale. - LogoFacade.Size = new Vector2(Logo.SizeForFlow * Logo.Scale.X * facadeScale); - - if (LogoFacade.Parent != null && Logo.Position != LogoTrackingPosition()) - { - // If this is our first update since tracking has started, initialize our starting values for interpolation - if (startTime == null || startPosition == null) - { - startTime = Time.Current; - startPosition = Logo.Position; - } - - if (duration != 0) - { - double elapsedDuration = Time.Current - startTime ?? throw new ArgumentNullException(nameof(startTime)); - - var mount = (float)Interpolation.ApplyEasing(easing, Math.Min(elapsedDuration / duration, 1)); - - // Interpolate the position of the logo, where mount 0 is where the logo was when it first began interpolating, and mount 1 is the target location. - Logo.Position = Vector2.Lerp(startPosition ?? throw new ArgumentNullException(nameof(startPosition)), LogoTrackingPosition(), mount); - } - else - { - Logo.Position = LogoTrackingPosition(); - } - } - } - - /// - /// A placeholder container that serves as a dummy object to denote another object's location and size. - /// - public class Facade : Container - { - } - } -} diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs new file mode 100644 index 0000000000..afb30f981b --- /dev/null +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -0,0 +1,156 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.MathUtils; +using osu.Game.Screens.Menu; +using osuTK; + +namespace osu.Game.Graphics.Containers +{ + /// + /// A container that handles tracking of an through different layout scenarios + /// + public class LogoTrackingContainer : Container + { + public Facade LogoFacade { get; } + + /// + /// Whether or not the logo assigned to this FacadeContainer should be tracking the position of its facade. + /// + public bool Tracking { get; set; } + + protected OsuLogo Logo; + + private float facadeScale; + private Easing easing; + private Vector2? startPosition; + private double? startTime; + private double duration; + + public LogoTrackingContainer() + { + LogoFacade = new ExposedFacade(); + } + + /// + /// Assign the logo that should track the Facade's position, as well as how it should transform to its initial position. + /// + /// The instance of the logo to be used for tracking. + /// The scale of the facade. Does not actually affect the logo itself. + /// The duration of the initial transform. Default is instant. + /// The easing type of the initial transform. + public void SetLogo(OsuLogo logo, float facadeScale = 1.0f, double duration = 0, Easing easing = Easing.None) + { + if (Logo != logo) + { + if (logo?.HasTrackingContainer ?? throw new ArgumentNullException(nameof(logo))) + { + // Prevent the same logo from being added to multiple LogoTrackingContainers. + throw new InvalidOperationException($"Cannot add an instance of {typeof(OsuLogo)} to multiple {typeof(LogoTrackingContainer)}s"); + } + + if (Logo != null) + { + // If we're replacing the logo to be tracked, the old one no longer has a tracking container + Logo.HasTrackingContainer = false; + } + } + + Logo = logo; + Logo.HasTrackingContainer = true; + this.facadeScale = facadeScale; + this.duration = duration; + this.easing = easing; + + startTime = null; + startPosition = null; + } + + /// + /// Gets the position that the logo should move to with respect to the . + /// Manually performs a conversion of the Facade's position to the Logo's parent's relative space. + /// + /// Will only be correct if the logo's are set to Axes.Both + protected Vector2 LogoTrackingPosition => new Vector2(Logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).X / Logo.Parent.RelativeToAbsoluteFactor.X, + Logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).Y / Logo.Parent.RelativeToAbsoluteFactor.Y); + + protected override void Update() + { + base.Update(); + + if (Logo == null || !Tracking) + return; + + // Account for the scale of the actual OsuLogo, as SizeForFlow only accounts for the sprite scale. + ((ExposedFacade)LogoFacade).SetSize(new Vector2(Logo.SizeForFlow * Logo.Scale.X * facadeScale)); + + if (LogoFacade.Parent != null && Logo.Position != LogoTrackingPosition && Logo.RelativePositionAxes == Axes.Both) + { + // If this is our first update since tracking has started, initialize our starting values for interpolation + if (startTime == null || startPosition == null) + { + startTime = Time.Current; + startPosition = Logo.Position; + } + + if (duration != 0) + { + double elapsedDuration = (double)(Time.Current - startTime); + + var amount = (float)Interpolation.ApplyEasing(easing, Math.Min(elapsedDuration / duration, 1)); + + // Interpolate the position of the logo, where amount 0 is where the logo was when it first began interpolating, and amount 1 is the target location. + Logo.Position = Vector2.Lerp((Vector2)startPosition, LogoTrackingPosition, amount); + } + else + { + Logo.Position = LogoTrackingPosition; + } + } + } + + protected override void Dispose(bool isDisposing) + { + if (Logo != null) + Logo.HasTrackingContainer = false; + + base.Dispose(isDisposing); + } + + private Vector2 size; + + private class ExposedFacade : Facade + { + public override Vector2 Size + { + get => base.Size; + set => throw new InvalidOperationException($"Cannot set the Size of a {typeof(Facade)} outside of a {typeof(LogoTrackingContainer)}"); + } + + public void SetSize(Vector2 size) + { + base.SetSize(size); + } + } + + /// + /// A dummy object used to denote another object's location. + /// + public abstract class Facade : Drawable + { + public override Vector2 Size + { + get => base.Size; + set => throw new InvalidOperationException($"Cannot set the Size of a {typeof(Facade)} outside of a {typeof(LogoTrackingContainer)}"); + } + + protected void SetSize(Vector2 size) + { + base.Size = size; + } + } + } +} diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index cb95ec1765..a359893418 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -60,7 +60,7 @@ namespace osu.Game.Screens.Menu if (this.logo != null) { this.logo.Action = onOsuLogo; - logoFacadeContainer.SetLogo(logo, 0.74f); + logoTrackingContainer.SetLogo(logo, 0.74f); // osuLogo.SizeForFlow relies on loading to be complete. buttonArea.Flow.Position = new Vector2(WEDGE_WIDTH * 2 - (BUTTON_WIDTH + this.logo.SizeForFlow / 4), 0); @@ -70,7 +70,7 @@ namespace osu.Game.Screens.Menu else { // We should stop tracking as the facade is now out of scope. - logoFacadeContainer.Tracking = false; + logoTrackingContainer.Tracking = false; } } @@ -83,29 +83,29 @@ namespace osu.Game.Screens.Menu private SampleChannel sampleBack; - private readonly LogoFacadeContainer logoFacadeContainer; + private readonly LogoTrackingContainer logoTrackingContainer; public ButtonSystem() { RelativeSizeAxes = Axes.Both; - Child = logoFacadeContainer = new LogoFacadeContainer + Child = logoTrackingContainer = new LogoTrackingContainer { RelativeSizeAxes = Axes.Both, Child = buttonArea = new ButtonArea() }; - buttonArea.AddRange(new Container[] + buttonArea.AddRange(new Drawable[] { new Button(@"settings", string.Empty, FontAwesome.Gear, new Color4(85, 85, 85, 255), () => OnSettings?.Invoke(), -WEDGE_WIDTH, Key.O), backButton = new Button(@"back", @"button-back-select", OsuIcon.LeftCircle, new Color4(51, 58, 94, 255), () => State = ButtonSystemState.TopLevel, -WEDGE_WIDTH) { VisibleState = ButtonSystemState.Play, }, - logoFacadeContainer.LogoFacade + logoTrackingContainer.LogoFacade }); - buttonArea.Flow.CentreTarget = logoFacadeContainer.LogoFacade; + buttonArea.Flow.CentreTarget = logoTrackingContainer.LogoFacade; } [Resolved(CanBeNull = true)] @@ -271,7 +271,7 @@ namespace osu.Game.Screens.Menu logoDelayedAction?.Cancel(); logoDelayedAction = Scheduler.AddDelayed(() => { - logoFacadeContainer.Tracking = false; + logoTrackingContainer.Tracking = false; game?.Toolbar.Hide(); @@ -294,8 +294,8 @@ namespace osu.Game.Screens.Menu if (lastState == ButtonSystemState.Initial) logo.ScaleTo(0.5f, 200, Easing.In); - logoFacadeContainer.SetLogo(logo, 0.74f, lastState == ButtonSystemState.EnteringMode ? 0 : 200, Easing.In); - logoFacadeContainer.Tracking = true; + logoTrackingContainer.SetLogo(logo, 0.74f, lastState == ButtonSystemState.EnteringMode ? 0 : 200, Easing.In); + logoTrackingContainer.Tracking = true; logoDelayedAction?.Cancel(); logoDelayedAction = Scheduler.AddDelayed(() => @@ -308,14 +308,14 @@ namespace osu.Game.Screens.Menu break; default: logo.ClearTransforms(targetMember: nameof(Position)); - logoFacadeContainer.Tracking = true; + logoTrackingContainer.Tracking = true; logo.ScaleTo(0.5f, 200, Easing.OutQuint); break; } break; case ButtonSystemState.EnteringMode: - logoFacadeContainer.Tracking = true; + logoTrackingContainer.Tracking = true; break; } } diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index c54ccd21b5..ad70d34637 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -54,8 +54,14 @@ namespace osu.Game.Screens.Menu /// public Func Action; + /// + /// The size of the logo Sprite with respect to the scale of its hover and bounce containers. + /// + /// Does not account for the scale of this public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * logoHoverContainer.Scale.X; + public bool HasTrackingContainer { get; set; } + private readonly Sprite ripple; private readonly Container rippleContainer; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index ccfd965f53..f7feb3535d 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Play private Player player; - private LogoFacadeContainer content; + private LogoTrackingContainer content; private BeatmapMetadataDisplay info; @@ -60,14 +60,12 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load() { - InternalChild = content = new LogoFacadeContainer + InternalChild = (content = new LogoTrackingContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - }; - - content.Children = new Drawable[] + }).WithChildren(new Drawable[] { info = new BeatmapMetadataDisplay(Beatmap.Value, content.LogoFacade) { @@ -89,7 +87,7 @@ namespace osu.Game.Screens.Play new InputSettings() } } - }; + }); loadNewPlayer(); } @@ -163,12 +161,9 @@ namespace osu.Game.Screens.Play logo.ScaleTo(new Vector2(0.15f), duration, Easing.In); logo.FadeIn(350); - content.SetLogo(logo, 1.0f, 500, Easing.InOutExpo); + content.SetLogo(logo, 1.0f, resuming ? 0 : 500, Easing.InOutExpo); - Scheduler.AddDelayed(() => - { - content.Tracking = true; - }, resuming ? 0 : 500); + Scheduler.AddDelayed(() => { content.Tracking = true; }, resuming ? 0 : 500); } protected override void LogoExiting(OsuLogo logo) @@ -321,7 +316,7 @@ namespace osu.Game.Screens.Play } private readonly WorkingBeatmap beatmap; - private readonly Container facade; + private readonly Drawable facade; private LoadingAnimation loading; private Sprite backgroundSprite; private ModDisplay modDisplay; @@ -343,7 +338,7 @@ namespace osu.Game.Screens.Play } } - public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Container facade) + public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Drawable facade) { this.beatmap = beatmap; this.facade = facade; @@ -366,7 +361,7 @@ namespace osu.Game.Screens.Play Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Direction = FillDirection.Vertical, - Children = new Drawable[] + Children = new[] { facade, new OsuSpriteText From b1d74e57e58fc175fed9061dabed5f8e6d2e9642 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 5 Apr 2019 13:56:08 +0900 Subject: [PATCH 0507/5608] Add checks guarding against setting tracking on multiple trackingcongtainers and setting facade size --- .../Containers/LogoTrackingContainer.cs | 48 ++++++++++--------- osu.Game/Screens/Menu/OsuLogo.cs | 2 +- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index afb30f981b..ee6d5dec20 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Reflection.Metadata.Ecma335; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; @@ -20,7 +21,24 @@ namespace osu.Game.Graphics.Containers /// /// Whether or not the logo assigned to this FacadeContainer should be tracking the position of its facade. /// - public bool Tracking { get; set; } + public bool Tracking + { + get => tracking; + set + { + if (Logo != null) + { + if (value && !tracking && Logo.IsTracking) + throw new InvalidOperationException($"Cannot track an instance of {typeof(OsuLogo)} to multiple {typeof(LogoTrackingContainer)}s"); + + Logo.IsTracking = value; + } + + tracking = value; + } + } + + private bool tracking; protected OsuLogo Logo; @@ -44,23 +62,15 @@ namespace osu.Game.Graphics.Containers /// The easing type of the initial transform. public void SetLogo(OsuLogo logo, float facadeScale = 1.0f, double duration = 0, Easing easing = Easing.None) { - if (Logo != logo) + if (Logo != logo && Logo != null) { - if (logo?.HasTrackingContainer ?? throw new ArgumentNullException(nameof(logo))) - { - // Prevent the same logo from being added to multiple LogoTrackingContainers. - throw new InvalidOperationException($"Cannot add an instance of {typeof(OsuLogo)} to multiple {typeof(LogoTrackingContainer)}s"); - } - - if (Logo != null) - { - // If we're replacing the logo to be tracked, the old one no longer has a tracking container - Logo.HasTrackingContainer = false; - } + // If we're replacing the logo to be tracked, the old one no longer has a tracking container + Logo.IsTracking = false; } - Logo = logo; - Logo.HasTrackingContainer = true; + Logo = logo ?? throw new ArgumentNullException(nameof(logo)); + Logo.IsTracking = Tracking; + this.facadeScale = facadeScale; this.duration = duration; this.easing = easing; @@ -115,7 +125,7 @@ namespace osu.Game.Graphics.Containers protected override void Dispose(bool isDisposing) { if (Logo != null) - Logo.HasTrackingContainer = false; + Tracking = false; base.Dispose(isDisposing); } @@ -124,12 +134,6 @@ namespace osu.Game.Graphics.Containers private class ExposedFacade : Facade { - public override Vector2 Size - { - get => base.Size; - set => throw new InvalidOperationException($"Cannot set the Size of a {typeof(Facade)} outside of a {typeof(LogoTrackingContainer)}"); - } - public void SetSize(Vector2 size) { base.SetSize(size); diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index ad70d34637..4631f4e222 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -60,7 +60,7 @@ namespace osu.Game.Screens.Menu /// Does not account for the scale of this public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * logoHoverContainer.Scale.X; - public bool HasTrackingContainer { get; set; } + public bool IsTracking { get; set; } private readonly Sprite ripple; From 15fbb6f176395ae2ef5cc76c9cfe12ba2c53f6e4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 5 Apr 2019 14:15:36 +0900 Subject: [PATCH 0508/5608] Use common AddUserLink method --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 4 ++++ osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 3 +-- osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs | 3 +-- osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs | 3 +-- osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs | 5 ++--- osu.Game/Screens/Multi/Match/Components/HostInfo.cs | 4 +--- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index dace873b92..eefbeea24c 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; +using osu.Game.Users; namespace osu.Game.Graphics.Containers { @@ -75,6 +76,9 @@ namespace osu.Game.Graphics.Containers return createLink(text, null, url, linkType, linkArgument, tooltipText); } + public IEnumerable AddUserLink(User user, Action creationParameters = null) + => createLink(AddText(user.Username, creationParameters), user.Username, null, LinkAction.OpenUserProfile, user.Id.ToString(), "View profile"); + private IEnumerable createLink(IEnumerable drawables, string text, string url = null, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action action = null) { AddInternal(new DrawableLinkCompiler(drawables.OfType().ToList()) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 3addef854a..693ce958dd 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -10,7 +10,6 @@ using osu.Framework.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Online.Chat; using osu.Game.Online.Leaderboards; using osu.Game.Rulesets.UI; using osu.Game.Scoring; @@ -124,7 +123,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }; var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: text_size)) { AutoSizeAxes = Axes.Both }; - username.AddLink(score.User.Username, null, LinkAction.OpenUserProfile, score.User.Id.ToString(), "Open profile"); + username.AddUserLink(score.User); content.AddRange(new Drawable[] { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index f401dc93a7..c0d9ecad3a 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Online.Chat; using osu.Game.Online.Leaderboards; using osu.Game.Scoring; using osu.Game.Users; @@ -119,7 +118,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores date.Text = $@"achieved {value.Date.Humanize()}"; usernameText.Clear(); - usernameText.AddLink(value.User.Username, null, LinkAction.OpenUserProfile, value.User.Id.ToString(), "Open profile"); + usernameText.AddUserLink(value.User); rank.UpdateRank(value.Rank); } diff --git a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs index 23771451bd..d63f2fecd2 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Online.Chat; using osuTK; namespace osu.Game.Screens.Multi.Components @@ -60,7 +59,7 @@ namespace osu.Game.Screens.Multi.Components if (beatmap != null) { beatmapAuthor.AddText("mapped by ", s => s.Colour = OsuColour.Gray(0.8f)); - beatmapAuthor.AddLink(beatmap.Metadata.Author.Username, null, LinkAction.OpenUserProfile, beatmap.Metadata.Author.Id.ToString(), "View Profile"); + beatmapAuthor.AddUserLink(beatmap.Metadata.Author); } }, true); } diff --git a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs index 40e59de25d..51d3c93624 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Online.Chat; using osu.Game.Users; using osuTK; @@ -95,8 +94,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components if (host.NewValue != null) { hostText.AddText("hosted by "); - hostText.AddLink(host.NewValue.Username, null, LinkAction.OpenUserProfile, host.NewValue.Id.ToString(), "Open profile", - s => s.Font = s.Font.With(Typeface.Exo, weight: FontWeight.Bold, italics: true)); + hostText.AddUserLink(host.NewValue, s => s.Font = s.Font.With(Typeface.Exo, weight: FontWeight.Bold, italics: true)); + flagContainer.Child = new DrawableFlag(host.NewValue.Country) { RelativeSizeAxes = Axes.Both }; } }, true); diff --git a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs index 02c8929f44..b898cd0466 100644 --- a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs +++ b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Online.Chat; using osu.Game.Users; using osuTK; @@ -54,8 +53,7 @@ namespace osu.Game.Screens.Multi.Match.Components { linkContainer.AddText("hosted by"); linkContainer.NewLine(); - linkContainer.AddLink(host.Username, null, LinkAction.OpenUserProfile, host.Id.ToString(), "View Profile", - s => s.Font = s.Font.With(Typeface.Exo, weight: FontWeight.Bold, italics: true)); + linkContainer.AddUserLink(host, s => s.Font = s.Font.With(Typeface.Exo, weight: FontWeight.Bold, italics: true)); } } } From a34a511f221e5d964772228d5feb1fb331fed543 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Apr 2019 14:55:25 +0900 Subject: [PATCH 0509/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f3c648cf02..74ed9f91dd 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 7ce7329246..9fff64c61c 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 5fa93f4a050263be0a2a546bcbfbd1bbc97e2771 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 5 Apr 2019 15:05:11 +0900 Subject: [PATCH 0510/5608] Add test for checking exception --- .../UserInterface/TestCaseLogoTrackingContainer.cs | 12 +++++++++++- .../Graphics/Containers/LogoTrackingContainer.cs | 11 +++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs index 4d255eb25a..3b57d892ad 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs @@ -186,7 +186,17 @@ namespace osu.Game.Tests.Visual.UserInterface public void SetFacadeSizeTest() { AddStep("Add tracking containers", addFacadeContainers); - AddStep("Break shit", () => { logoFacade.Size = new Vector2(0, 0); }); + AddStep("Break stuff", () => { logoFacade.Size = new Vector2(0, 0); }); + } + + [Test] + public void SetMultipleContainers() + { + LogoTrackingContainer newContainer = new LogoTrackingContainer(); + AddStep("Add tracking containers", addFacadeContainers); + AddStep("Move facade to random position", startTrackingRandom); + AddStep("Add logo to new container", () => newContainer.SetLogo(logo)); + AddStep("Break stuff", () => newContainer.Tracking = true); } private void addFacadeContainers() diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index ee6d5dec20..ab6f7ebc2a 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Graphics.Containers { /// - /// A container that handles tracking of an through different layout scenarios + /// A container that handles tracking of an through different layout scenarios. /// public class LogoTrackingContainer : Container { @@ -38,8 +38,6 @@ namespace osu.Game.Graphics.Containers } } - private bool tracking; - protected OsuLogo Logo; private float facadeScale; @@ -47,6 +45,7 @@ namespace osu.Game.Graphics.Containers private Vector2? startPosition; private double? startTime; private double duration; + private bool tracking; public LogoTrackingContainer() { @@ -69,7 +68,11 @@ namespace osu.Game.Graphics.Containers } Logo = logo ?? throw new ArgumentNullException(nameof(logo)); - Logo.IsTracking = Tracking; + + if (Tracking) + { + Logo.IsTracking = true; + } this.facadeScale = facadeScale; this.duration = duration; From e06fe7950b04bec9df82a6244281b06faaf4892d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 5 Apr 2019 15:06:37 +0900 Subject: [PATCH 0511/5608] Cleanup --- .../TestCaseLogoTrackingContainer.cs | 17 ----------------- .../Containers/LogoTrackingContainer.cs | 3 --- 2 files changed, 20 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs index 3b57d892ad..19e430da3e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs @@ -182,23 +182,6 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking); } - [Test] - public void SetFacadeSizeTest() - { - AddStep("Add tracking containers", addFacadeContainers); - AddStep("Break stuff", () => { logoFacade.Size = new Vector2(0, 0); }); - } - - [Test] - public void SetMultipleContainers() - { - LogoTrackingContainer newContainer = new LogoTrackingContainer(); - AddStep("Add tracking containers", addFacadeContainers); - AddStep("Move facade to random position", startTrackingRandom); - AddStep("Add logo to new container", () => newContainer.SetLogo(logo)); - AddStep("Break stuff", () => newContainer.Tracking = true); - } - private void addFacadeContainers() { AddRange(new Drawable[] diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index ab6f7ebc2a..746710bcda 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Reflection.Metadata.Ecma335; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; @@ -133,8 +132,6 @@ namespace osu.Game.Graphics.Containers base.Dispose(isDisposing); } - private Vector2 size; - private class ExposedFacade : Facade { public void SetSize(Vector2 size) From 37ffe47e4b763140befcea82f29cfe662869b2c4 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 5 Apr 2019 15:30:09 +0900 Subject: [PATCH 0512/5608] Add back exception tests with better descriptions --- .../TestCaseLogoTrackingContainer.cs | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs index 19e430da3e..cf84a34344 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs @@ -182,6 +182,49 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking); } + [Test] + public void SetFacadeSizeTest() + { + bool failed = false; + AddStep("Add tracking containers", addFacadeContainers); + AddStep("Try setting facade size", () => + { + try + { + logoFacade.Size = new Vector2(0, 0); + } + catch (Exception e) + { + if (e is InvalidOperationException) + failed = true; + } + }); + AddAssert("Exception thrown", () => failed); + } + + [Test] + public void SetMultipleContainers() + { + bool failed = false; + LogoTrackingContainer newContainer = new LogoTrackingContainer(); + AddStep("Add tracking containers", addFacadeContainers); + AddStep("Move facade to random position", startTrackingRandom); + AddStep("Add logo to new container", () => newContainer.SetLogo(logo)); + AddStep("Try tracking new container", () => + { + try + { + newContainer.Tracking = true; + } + catch (Exception e) + { + if (e is InvalidOperationException) + failed = true; + } + }); + AddAssert("Exception thrown", () => failed); + } + private void addFacadeContainers() { AddRange(new Drawable[] From c693d1fad89ea3b3d4ab655808668a6350bb9f6c Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 5 Apr 2019 15:48:48 +0900 Subject: [PATCH 0513/5608] Further condense steps --- .../TestCaseLogoTrackingContainer.cs | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs index cf84a34344..01a3113fe1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs @@ -100,7 +100,12 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Add tracking containers", addFacadeContainers); AddStep("Move facade to random position", startTrackingRandom); AddStep("Remove facade from FacadeContainer", removeFacade); - AddStep("Transfer facade to a new container", addFacadeToNewContainer); + AddStep("Transfer facade to a new container", () => + { + transferContainer.Add(logoFacade); + transferContainerBox.Colour = Color4.Tomato; + moveLogoFacade(); + }); waitForMove(); AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking); } @@ -186,7 +191,11 @@ namespace osu.Game.Tests.Visual.UserInterface public void SetFacadeSizeTest() { bool failed = false; - AddStep("Add tracking containers", addFacadeContainers); + AddStep("Set up scenario", () => + { + failed = false; + addFacadeContainers(); + }); AddStep("Try setting facade size", () => { try @@ -203,13 +212,18 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void SetMultipleContainers() + public void SetMultipleContainersTest() { bool failed = false; LogoTrackingContainer newContainer = new LogoTrackingContainer(); - AddStep("Add tracking containers", addFacadeContainers); - AddStep("Move facade to random position", startTrackingRandom); - AddStep("Add logo to new container", () => newContainer.SetLogo(logo)); + AddStep("Set up scenario", () => + { + failed = false; + newContainer = new LogoTrackingContainer(); + addFacadeContainers(); + startTrackingRandom(); + newContainer.SetLogo(logo); + }); AddStep("Try tracking new container", () => { try @@ -272,13 +286,6 @@ namespace osu.Game.Tests.Visual.UserInterface moveLogoFacade(); } - private void addFacadeToNewContainer() - { - transferContainer.Add(logoFacade); - transferContainerBox.Colour = Color4.Tomato; - moveLogoFacade(); - } - private void moveLogoFacade() { if (logoFacade?.Transforms.Count == 0 && transferContainer?.Transforms.Count == 0) From 53906e87ec35fcb657fd4700dd3039bc8d878347 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 5 Apr 2019 00:00:21 -0700 Subject: [PATCH 0514/5608] Split floatingOverlayContent --- osu.Game/OsuGame.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index f19860a884..bb279a0bc2 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -399,7 +399,8 @@ namespace osu.Game } }, overlayContent = new Container { RelativeSizeAxes = Axes.Both }, - floatingOverlayContent = new Container { RelativeSizeAxes = Axes.Both }, + rightFloatingOverlayContent = new Container { RelativeSizeAxes = Axes.Both }, + leftFloatingOverlayContent = new Container { RelativeSizeAxes = Axes.Both }, topMostOverlayContent = new Container { RelativeSizeAxes = Axes.Both }, idleTracker = new GameIdleTracker(6000) }); @@ -427,6 +428,7 @@ namespace osu.Game }, }, topMostOverlayContent.Add); + loadComponentSingleFile(volume = new VolumeOverlay(), rightFloatingOverlayContent.Add); loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add); loadComponentSingleFile(loginOverlay = new LoginOverlay @@ -434,7 +436,7 @@ namespace osu.Game GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - }, floatingOverlayContent.Add); + }, rightFloatingOverlayContent.Add); loadComponentSingleFile(screenshotManager, Add); @@ -443,6 +445,7 @@ namespace osu.Game loadComponentSingleFile(social = new SocialOverlay(), overlayContent.Add); loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal); loadComponentSingleFile(chatOverlay = new ChatOverlay(), overlayContent.Add); + loadComponentSingleFile(settings = new MainSettings { GetToolbarHeight = () => ToolbarOffset }, leftFloatingOverlayContent.Add); loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add); @@ -451,17 +454,14 @@ namespace osu.Game GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - }, floatingOverlayContent.Add); + }, rightFloatingOverlayContent.Add); loadComponentSingleFile(musicController = new MusicController { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - }, floatingOverlayContent.Add); - - loadComponentSingleFile(volume = new VolumeOverlay(), floatingOverlayContent.Add); - loadComponentSingleFile(settings = new MainSettings { GetToolbarHeight = () => ToolbarOffset }, floatingOverlayContent.Add); + }, rightFloatingOverlayContent.Add); loadComponentSingleFile(accountCreation = new AccountCreationOverlay(), topMostOverlayContent.Add); loadComponentSingleFile(dialogOverlay = new DialogOverlay(), topMostOverlayContent.Add); @@ -710,7 +710,9 @@ namespace osu.Game private Container overlayContent; - private Container floatingOverlayContent; + private Container rightFloatingOverlayContent; + + private Container leftFloatingOverlayContent; private Container topMostOverlayContent; From debda7ae7de8c0b4bd57fc48a9dec0c01723dd45 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 5 Apr 2019 00:05:42 -0700 Subject: [PATCH 0515/5608] Fix volume overlay container reference --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index bb279a0bc2..15cd6d73e5 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -428,7 +428,7 @@ namespace osu.Game }, }, topMostOverlayContent.Add); - loadComponentSingleFile(volume = new VolumeOverlay(), rightFloatingOverlayContent.Add); + loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add); loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add); loadComponentSingleFile(loginOverlay = new LoginOverlay From 0208526837180c9e19f7f297b7d5c49d0629398c Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 5 Apr 2019 18:21:54 +0900 Subject: [PATCH 0516/5608] Fix button system visual issue --- osu.Game/Screens/Menu/Button.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index 794fc093d3..383150cbd3 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -63,6 +63,8 @@ namespace osu.Game.Screens.Menu { box = new Container { + // box needs to be always present to ensure the button is always sized correctly for flow + AlwaysPresent = true, Masking = true, MaskingSmoothness = 2, EdgeEffect = new EdgeEffectParameters From cb3532e7d46a7b9614a4161463ac32a7c8aa2105 Mon Sep 17 00:00:00 2001 From: theFerdi265 Date: Sat, 6 Apr 2019 00:53:02 +0200 Subject: [PATCH 0517/5608] BeatmapLeaderboard: fix local scores not being sorted --- osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index ebb1d78ba0..042ef0f5a1 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Select.Leaderboards { if (Scope == BeatmapLeaderboardScope.Local) { - Scores = scoreManager.QueryScores(s => !s.DeletePending && s.Beatmap.ID == Beatmap.ID).ToArray(); + Scores = scoreManager.QueryScores(s => !s.DeletePending && s.Beatmap.ID == Beatmap.ID).OrderBy(s => -s.TotalScore).ToArray(); PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; return null; } From d5b7865ab8c73ae2f3aad743a190ef12d5ef983c Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 6 Apr 2019 17:40:48 +0200 Subject: [PATCH 0518/5608] Invert notification and loginOverlay depth order --- 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 15cd6d73e5..4f92ff831c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -431,7 +431,7 @@ namespace osu.Game loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add); loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add); - loadComponentSingleFile(loginOverlay = new LoginOverlay + loadComponentSingleFile(notifications = new NotificationOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, @@ -449,7 +449,7 @@ namespace osu.Game loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add); - loadComponentSingleFile(notifications = new NotificationOverlay + loadComponentSingleFile(loginOverlay = new LoginOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, From 59410dbe3b739a5708604dddb8dd7e5df48236be Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 6 Apr 2019 18:05:13 +0200 Subject: [PATCH 0519/5608] Open login overlay when notification asking for signing in to play multi is clicked --- osu.Game/Screens/Menu/ButtonSystem.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index d3cf23dab8..77be5d08d9 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -103,6 +103,9 @@ namespace osu.Game.Screens.Menu [Resolved(CanBeNull = true)] private NotificationOverlay notifications { get; set; } + [Resolved] + private LoginOverlay loginOverlay { get; set; } + [BackgroundDependencyLoader(true)] private void load(AudioManager audio, IdleTracker idleTracker, GameHost host) { @@ -134,8 +137,13 @@ namespace osu.Game.Screens.Menu { notifications?.Post(new SimpleNotification { - Text = "You gotta be logged in to multi 'yo!", - Icon = FontAwesome.Solid.Globe + Text = "You gotta be logged in to multi 'yo!", + Icon = FontAwesome.Solid.Globe, + Activated = () => + { + loginOverlay.Show(); + return true; + } }); return; From 394f14965b88c745252a3932af9337c30d17037d Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 6 Apr 2019 18:23:56 +0200 Subject: [PATCH 0520/5608] Make appveyor happy with whitespaces --- osu.Game/Screens/Menu/ButtonSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 77be5d08d9..d311664737 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -137,7 +137,7 @@ namespace osu.Game.Screens.Menu { notifications?.Post(new SimpleNotification { - Text = "You gotta be logged in to multi 'yo!", + Text = "You gotta be logged in to multi 'yo!", Icon = FontAwesome.Solid.Globe, Activated = () => { From 3f2e6a9376e024ada4a91e565f7b66b3eb232439 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 6 Apr 2019 18:52:30 +0200 Subject: [PATCH 0521/5608] Allow loginOverlay to be null if there's no cached instance in DI (for testing cases) --- osu.Game/Screens/Menu/ButtonSystem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index d311664737..80fbce2cf8 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -103,7 +103,7 @@ namespace osu.Game.Screens.Menu [Resolved(CanBeNull = true)] private NotificationOverlay notifications { get; set; } - [Resolved] + [Resolved(CanBeNull = true)] private LoginOverlay loginOverlay { get; set; } [BackgroundDependencyLoader(true)] @@ -141,7 +141,7 @@ namespace osu.Game.Screens.Menu Icon = FontAwesome.Solid.Globe, Activated = () => { - loginOverlay.Show(); + loginOverlay?.Show(); return true; } }); From d431ca4efc2f1cf384d0cf595213130792474445 Mon Sep 17 00:00:00 2001 From: Ferdinand Bachmann Date: Sun, 7 Apr 2019 13:26:35 +0200 Subject: [PATCH 0522/5608] BeatmapLeaderboard: use OrderByDescending instead of negation (suggested by peppy) --- osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 042ef0f5a1..aafa6bb0eb 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Select.Leaderboards { if (Scope == BeatmapLeaderboardScope.Local) { - Scores = scoreManager.QueryScores(s => !s.DeletePending && s.Beatmap.ID == Beatmap.ID).OrderBy(s => -s.TotalScore).ToArray(); + Scores = scoreManager.QueryScores(s => !s.DeletePending && s.Beatmap.ID == Beatmap.ID).OrderByDescending(s => s.TotalScore).ToArray(); PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; return null; } From e76897d6a76091885e3318d7bfccae9fe9268277 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Sun, 7 Apr 2019 16:32:55 -0300 Subject: [PATCH 0523/5608] Fix ResumeContainers appearing when resuming during breaks. --- osu.Game/Screens/Play/BreakOverlay.cs | 4 ++++ osu.Game/Screens/Play/Player.cs | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index d390787090..ab81e613cc 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -23,6 +23,8 @@ namespace osu.Game.Screens.Play private readonly Container fadeContainer; + public bool IsActive { get; private set; } + public List Breaks { get => breaks; @@ -125,6 +127,7 @@ namespace osu.Game.Screens.Play using (BeginAbsoluteSequence(b.StartTime, true)) { + Schedule(() => IsActive = true); fadeContainer.FadeIn(fade_duration); breakArrows.Show(fade_duration); @@ -142,6 +145,7 @@ namespace osu.Game.Screens.Play using (BeginDelayedSequence(b.Duration - fade_duration, true)) { + Schedule(() => IsActive = false); fadeContainer.FadeOut(fade_duration); breakArrows.Hide(fade_duration); } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0eebefec86..60287f7a2e 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -60,6 +60,8 @@ namespace osu.Game.Screens.Play private SampleChannel sampleRestart; + private BreakOverlay breakOverlay; + protected ScoreProcessor ScoreProcessor { get; private set; } protected DrawableRuleset DrawableRuleset { get; private set; } @@ -115,7 +117,7 @@ namespace osu.Game.Screens.Play Child = DrawableRuleset } }, - new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) + breakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -405,8 +407,8 @@ namespace osu.Game.Screens.Play IsResuming = true; PauseOverlay.Hide(); - // time-based conditions may allow instant resume. - if (GameplayClockContainer.GameplayClock.CurrentTime < Beatmap.Value.Beatmap.HitObjects.First().StartTime) + // breaks and time-based conditions may allow instant resume. + if (breakOverlay.IsActive || GameplayClockContainer.GameplayClock.CurrentTime < Beatmap.Value.Beatmap.HitObjects.First().StartTime) completeResume(); else DrawableRuleset.RequestResume(completeResume); From d7655bc579df0a5193caa5cad65b02fd7084c3d8 Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Mon, 8 Apr 2019 11:22:01 +0900 Subject: [PATCH 0524/5608] Use .Value instead of cast Co-Authored-By: nyquillerium --- osu.Game/Graphics/Containers/LogoTrackingContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index 746710bcda..de70231989 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -115,7 +115,7 @@ namespace osu.Game.Graphics.Containers var amount = (float)Interpolation.ApplyEasing(easing, Math.Min(elapsedDuration / duration, 1)); // Interpolate the position of the logo, where amount 0 is where the logo was when it first began interpolating, and amount 1 is the target location. - Logo.Position = Vector2.Lerp((Vector2)startPosition, LogoTrackingPosition, amount); + Logo.Position = Vector2.Lerp(startPosition.Value, LogoTrackingPosition, amount); } else { From a690302d00cefdae17fa150e1d567cb9669fbc9d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 8 Apr 2019 15:24:09 +0900 Subject: [PATCH 0525/5608] Apply reviews --- .../UserInterface/TestCaseButtonSystem.cs | 2 +- .../TestCaseLogoTrackingContainer.cs | 27 +++---- .../Containers/LogoTrackingContainer.cs | 78 +++++++++---------- osu.Game/Screens/Menu/ButtonSystem.cs | 13 ++-- .../Screens/Menu/FlowContainerWithOrigin.cs | 2 +- osu.Game/Screens/Play/PlayerLoader.cs | 8 +- 6 files changed, 59 insertions(+), 71 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs index 261e87ff07..04aa8bce7e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs @@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.UserInterface RelativeSizeAxes = Axes.Both, }, buttons = new ButtonSystem(), - logo = new OsuLogo() + logo = new OsuLogo { RelativePositionAxes = Axes.Both } }; buttons.SetOsuLogo(logo); diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs index 01a3113fe1..8b70a34c85 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs @@ -73,7 +73,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddToggleStep("Toggle move continuously", b => randomPositions = b); AddStep("Add tracking containers", addFacadeContainers); - AddStep("Move facade to random position", startTrackingRandom); + AddStep("Move facade to random position", moveLogoFacade); waitForMove(); AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking); } @@ -85,7 +85,7 @@ namespace osu.Game.Tests.Visual.UserInterface public void RemoveFacadeTest() { AddStep("Add tracking containers", addFacadeContainers); - AddStep("Move facade to random position", startTrackingRandom); + AddStep("Move facade to random position", moveLogoFacade); AddStep("Remove facade from FacadeContainer", removeFacade); waitForMove(); AddAssert("Logo is not tracking", () => !trackingContainer.IsLogoTracking); @@ -98,7 +98,7 @@ namespace osu.Game.Tests.Visual.UserInterface public void TransferFacadeTest() { AddStep("Add tracking containers", addFacadeContainers); - AddStep("Move facade to random position", startTrackingRandom); + AddStep("Move facade to random position", moveLogoFacade); AddStep("Remove facade from FacadeContainer", removeFacade); AddStep("Transfer facade to a new container", () => { @@ -171,14 +171,14 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Perform logo movements", () => { - trackingContainer.Tracking = false; + trackingContainer.StopTracking(); logo.MoveTo(new Vector2(0.5f), 500, Easing.InOutExpo); - trackingContainer.SetLogo(logo, 1.0f, 1000, Easing.InOutExpo); + visualBox.Colour = Color4.White; Scheduler.AddDelayed(() => { - trackingContainer.Tracking = true; + trackingContainer.StartTracking(logo, 1000, Easing.InOutExpo); visualBox.Colour = Color4.Tomato; }, 700); }); @@ -221,14 +221,13 @@ namespace osu.Game.Tests.Visual.UserInterface failed = false; newContainer = new LogoTrackingContainer(); addFacadeContainers(); - startTrackingRandom(); - newContainer.SetLogo(logo); + moveLogoFacade(); }); AddStep("Try tracking new container", () => { try { - newContainer.Tracking = true; + newContainer.StartTracking(logo); } catch (Exception e) { @@ -268,7 +267,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); trackingContainer.Add(logoFacade = trackingContainer.LogoFacade); - trackingContainer.SetLogo(logo, 1.0f, 1000); + trackingContainer.StartTracking(logo, 1000); } private void waitForMove(int count = 5) => AddWaitStep("Wait for transforms to finish", count); @@ -280,12 +279,6 @@ namespace osu.Game.Tests.Visual.UserInterface moveLogoFacade(); } - private void startTrackingRandom() - { - trackingContainer.Tracking = true; - moveLogoFacade(); - } - private void moveLogoFacade() { if (logoFacade?.Transforms.Count == 0 && transferContainer?.Transforms.Count == 0) @@ -304,7 +297,7 @@ namespace osu.Game.Tests.Visual.UserInterface /// /// Check that the logo is tracking the position of the facade, with an acceptable precision lenience. /// - public bool IsLogoTracking => Precision.AlmostEquals(Logo.Position, LogoTrackingPosition); + public bool IsLogoTracking => Precision.AlmostEquals(Logo.Position, ComputeLogoTrackingPosition()); } } } diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index 746710bcda..ae585a2ba7 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -17,29 +17,9 @@ namespace osu.Game.Graphics.Containers { public Facade LogoFacade { get; } - /// - /// Whether or not the logo assigned to this FacadeContainer should be tracking the position of its facade. - /// - public bool Tracking - { - get => tracking; - set - { - if (Logo != null) - { - if (value && !tracking && Logo.IsTracking) - throw new InvalidOperationException($"Cannot track an instance of {typeof(OsuLogo)} to multiple {typeof(LogoTrackingContainer)}s"); + protected OsuLogo Logo => logo; - Logo.IsTracking = value; - } - - tracking = value; - } - } - - protected OsuLogo Logo; - - private float facadeScale; + private OsuLogo logo; private Easing easing; private Vector2? startPosition; private double? startTime; @@ -58,27 +38,38 @@ namespace osu.Game.Graphics.Containers /// The scale of the facade. Does not actually affect the logo itself. /// The duration of the initial transform. Default is instant. /// The easing type of the initial transform. - public void SetLogo(OsuLogo logo, float facadeScale = 1.0f, double duration = 0, Easing easing = Easing.None) + public void StartTracking(OsuLogo logo, double duration = 0, Easing easing = Easing.None) { - if (Logo != logo && Logo != null) + if (logo == null) + throw new ArgumentNullException(nameof(logo)); + + if (logo.IsTracking && tracking == false) + throw new InvalidOperationException($"Cannot track an instance of {typeof(OsuLogo)} to multiple {typeof(LogoTrackingContainer)}s"); + + if (this.logo != logo && this.logo != null) { // If we're replacing the logo to be tracked, the old one no longer has a tracking container - Logo.IsTracking = false; + this.logo.IsTracking = false; } - Logo = logo ?? throw new ArgumentNullException(nameof(logo)); + this.logo = logo; + this.logo.IsTracking = true; - if (Tracking) - { - Logo.IsTracking = true; - } - - this.facadeScale = facadeScale; this.duration = duration; this.easing = easing; startTime = null; startPosition = null; + + tracking = true; + } + + public void StopTracking() + { + if (logo != null) + logo.IsTracking = false; + + tracking = false; } /// @@ -86,20 +77,27 @@ namespace osu.Game.Graphics.Containers /// Manually performs a conversion of the Facade's position to the Logo's parent's relative space. /// /// Will only be correct if the logo's are set to Axes.Both - protected Vector2 LogoTrackingPosition => new Vector2(Logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).X / Logo.Parent.RelativeToAbsoluteFactor.X, - Logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).Y / Logo.Parent.RelativeToAbsoluteFactor.Y); + protected Vector2 ComputeLogoTrackingPosition() + { + var absolutePos = Logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre); + + return new Vector2(absolutePos.X / Logo.Parent.RelativeToAbsoluteFactor.X, + absolutePos.Y / Logo.Parent.RelativeToAbsoluteFactor.Y); + } protected override void Update() { base.Update(); - if (Logo == null || !Tracking) + if (Logo == null || !tracking) return; // Account for the scale of the actual OsuLogo, as SizeForFlow only accounts for the sprite scale. - ((ExposedFacade)LogoFacade).SetSize(new Vector2(Logo.SizeForFlow * Logo.Scale.X * facadeScale)); + ((ExposedFacade)LogoFacade).SetSize(new Vector2(Logo.SizeForFlow * Logo.Scale.X)); - if (LogoFacade.Parent != null && Logo.Position != LogoTrackingPosition && Logo.RelativePositionAxes == Axes.Both) + var localPos = ComputeLogoTrackingPosition(); + + if (LogoFacade.Parent != null && Logo.Position != localPos && Logo.RelativePositionAxes == Axes.Both) { // If this is our first update since tracking has started, initialize our starting values for interpolation if (startTime == null || startPosition == null) @@ -115,11 +113,11 @@ namespace osu.Game.Graphics.Containers var amount = (float)Interpolation.ApplyEasing(easing, Math.Min(elapsedDuration / duration, 1)); // Interpolate the position of the logo, where amount 0 is where the logo was when it first began interpolating, and amount 1 is the target location. - Logo.Position = Vector2.Lerp((Vector2)startPosition, LogoTrackingPosition, amount); + Logo.Position = Vector2.Lerp((Vector2)startPosition, localPos, amount); } else { - Logo.Position = LogoTrackingPosition; + Logo.Position = localPos; } } } @@ -127,7 +125,7 @@ namespace osu.Game.Graphics.Containers protected override void Dispose(bool isDisposing) { if (Logo != null) - Tracking = false; + Logo.IsTracking = false; base.Dispose(isDisposing); } diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index d042e110e9..1d2ee3c284 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -60,17 +60,17 @@ namespace osu.Game.Screens.Menu if (this.logo != null) { this.logo.Action = onOsuLogo; - logoTrackingContainer.SetLogo(logo, 0.74f); // osuLogo.SizeForFlow relies on loading to be complete. buttonArea.Flow.Position = new Vector2(WEDGE_WIDTH * 2 - (BUTTON_WIDTH + this.logo.SizeForFlow / 4), 0); + logoTrackingContainer.LogoFacade.Scale = new Vector2(0.74f); updateLogoState(); } else { // We should stop tracking as the facade is now out of scope. - logoTrackingContainer.Tracking = false; + logoTrackingContainer.StopTracking(); } } @@ -271,7 +271,7 @@ namespace osu.Game.Screens.Menu logoDelayedAction?.Cancel(); logoDelayedAction = Scheduler.AddDelayed(() => { - logoTrackingContainer.Tracking = false; + logoTrackingContainer.StopTracking(); game?.Toolbar.Hide(); @@ -294,8 +294,7 @@ namespace osu.Game.Screens.Menu if (lastState == ButtonSystemState.Initial) logo.ScaleTo(0.5f, 200, Easing.In); - logoTrackingContainer.SetLogo(logo, 0.74f, lastState == ButtonSystemState.EnteringMode ? 0 : 200, Easing.In); - logoTrackingContainer.Tracking = true; + logoTrackingContainer.StartTracking(logo, lastState == ButtonSystemState.EnteringMode ? 0 : 200, Easing.In); logoDelayedAction?.Cancel(); logoDelayedAction = Scheduler.AddDelayed(() => @@ -308,14 +307,14 @@ namespace osu.Game.Screens.Menu break; default: logo.ClearTransforms(targetMember: nameof(Position)); - logoTrackingContainer.Tracking = true; + logoTrackingContainer.StartTracking(logo, 0, Easing.In); logo.ScaleTo(0.5f, 200, Easing.OutQuint); break; } break; case ButtonSystemState.EnteringMode: - logoTrackingContainer.Tracking = true; + logoTrackingContainer.StartTracking(logo, 0, Easing.In); break; } } diff --git a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs index ec7333ec02..8310ab06eb 100644 --- a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs +++ b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Menu if (CentreTarget == null) return base.OriginPosition; - return CentreTarget.DrawPosition + CentreTarget.DrawSize / 2; + return CentreTarget.DrawPosition + CentreTarget.DrawSize / 2 * CentreTarget.Scale; } } } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index f7feb3535d..4c8f9a3539 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -128,7 +128,7 @@ namespace osu.Game.Screens.Play private void contentOut() { // Ensure the logo is no longer tracking before we scale the content - content.Tracking = false; + content.StopTracking(); content.ScaleTo(0.7f, 300, Easing.InQuint); content.FadeOut(250); @@ -161,15 +161,13 @@ namespace osu.Game.Screens.Play logo.ScaleTo(new Vector2(0.15f), duration, Easing.In); logo.FadeIn(350); - content.SetLogo(logo, 1.0f, resuming ? 0 : 500, Easing.InOutExpo); - - Scheduler.AddDelayed(() => { content.Tracking = true; }, resuming ? 0 : 500); + Scheduler.AddDelayed(() => { content.StartTracking(logo, resuming ? 0 : 500, Easing.InOutExpo); }, resuming ? 0 : 500); } protected override void LogoExiting(OsuLogo logo) { base.LogoExiting(logo); - content.Tracking = false; + content.StopTracking(); } protected override void LoadComplete() From 8a01995668734e46e0630ce8b143fb446d868a1b Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 8 Apr 2019 16:14:41 +0900 Subject: [PATCH 0526/5608] Remove need for tracking bool and backing logo --- .../Containers/LogoTrackingContainer.cs | 27 +++++++++---------- osu.Game/Screens/Menu/ButtonSystem.cs | 2 +- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index 0721011345..5ebdb7d45d 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -17,14 +17,12 @@ namespace osu.Game.Graphics.Containers { public Facade LogoFacade { get; } - protected OsuLogo Logo => logo; + protected OsuLogo Logo { get; private set; } - private OsuLogo logo; private Easing easing; private Vector2? startPosition; private double? startTime; private double duration; - private bool tracking; public LogoTrackingContainer() { @@ -43,33 +41,32 @@ namespace osu.Game.Graphics.Containers if (logo == null) throw new ArgumentNullException(nameof(logo)); - if (logo.IsTracking && tracking == false) + if (logo.IsTracking && Logo == null) throw new InvalidOperationException($"Cannot track an instance of {typeof(OsuLogo)} to multiple {typeof(LogoTrackingContainer)}s"); - if (this.logo != logo && this.logo != null) + if (Logo != logo && Logo != null) { // If we're replacing the logo to be tracked, the old one no longer has a tracking container - this.logo.IsTracking = false; + Logo.IsTracking = false; } - this.logo = logo; - this.logo.IsTracking = true; + Logo = logo; + Logo.IsTracking = true; this.duration = duration; this.easing = easing; startTime = null; startPosition = null; - - tracking = true; } public void StopTracking() { - if (logo != null) - logo.IsTracking = false; - - tracking = false; + if (Logo != null) + { + Logo.IsTracking = false; + Logo = null; + } } /// @@ -89,7 +86,7 @@ namespace osu.Game.Graphics.Containers { base.Update(); - if (Logo == null || !tracking) + if (Logo == null) return; // Account for the scale of the actual OsuLogo, as SizeForFlow only accounts for the sprite scale. diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 1d2ee3c284..a6157cdb64 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -63,7 +63,6 @@ namespace osu.Game.Screens.Menu // osuLogo.SizeForFlow relies on loading to be complete. buttonArea.Flow.Position = new Vector2(WEDGE_WIDTH * 2 - (BUTTON_WIDTH + this.logo.SizeForFlow / 4), 0); - logoTrackingContainer.LogoFacade.Scale = new Vector2(0.74f); updateLogoState(); } @@ -106,6 +105,7 @@ namespace osu.Game.Screens.Menu }); buttonArea.Flow.CentreTarget = logoTrackingContainer.LogoFacade; + logoTrackingContainer.LogoFacade.Scale = new Vector2(0.74f); } [Resolved(CanBeNull = true)] From 93b6cc00dfe96e2b4e26564bba09a92a0a7d0481 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 9 Apr 2019 12:53:00 +0900 Subject: [PATCH 0527/5608] Fix OsuScreenDependencies using the incorrect parent --- osu.Game/Screens/OsuScreen.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 5034385969..fdbc1120bc 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -65,12 +65,12 @@ namespace osu.Game.Screens protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - var deps = new OsuScreenDependencies(DisallowExternalBeatmapRulesetChanges, base.CreateChildDependencies(parent)); + OsuScreenDependencies screenDependencies = new OsuScreenDependencies(DisallowExternalBeatmapRulesetChanges, parent); - Beatmap = deps.Beatmap; - Ruleset = deps.Ruleset; + Beatmap = screenDependencies.Beatmap; + Ruleset = screenDependencies.Ruleset; - return deps; + return base.CreateChildDependencies(screenDependencies); } protected BackgroundScreen Background => backgroundStack?.CurrentScreen as BackgroundScreen; From ca9f172a96f15ef9461418f6fc541ab50df3323c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 9 Apr 2019 12:58:10 +0900 Subject: [PATCH 0528/5608] Use var --- osu.Game/Screens/OsuScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index fdbc1120bc..e0a25deecf 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -65,7 +65,7 @@ namespace osu.Game.Screens protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - OsuScreenDependencies screenDependencies = new OsuScreenDependencies(DisallowExternalBeatmapRulesetChanges, parent); + var screenDependencies = new OsuScreenDependencies(DisallowExternalBeatmapRulesetChanges, parent); Beatmap = screenDependencies.Beatmap; Ruleset = screenDependencies.Ruleset; From c584967eb12adb64c26111e43d4f2fa790e7ec8b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 8 Apr 2019 18:32:05 +0900 Subject: [PATCH 0529/5608] Remove mods from workingbeatmap --- .../TestCaseAutoJuiceStream.cs | 2 +- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- .../UI/DrawableCatchRuleset.cs | 6 ++-- .../Edit/DrawableManiaEditRuleset.cs | 6 ++-- .../Edit/ManiaHitObjectComposer.cs | 5 +-- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../UI/DrawableManiaRuleset.cs | 5 +-- osu.Game.Rulesets.Osu.Tests/StackingTest.cs | 3 +- .../Edit/DrawableOsuEditRuleset.cs | 6 ++-- .../Edit/OsuHitObjectComposer.cs | 5 +-- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../UI/DrawableOsuRuleset.cs | 6 ++-- .../TestCaseTaikoPlayfield.cs | 4 ++- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- .../UI/DrawableTaikoRuleset.cs | 6 ++-- .../Formats/LegacyBeatmapDecoderTest.cs | 3 +- .../TestCaseBackgroundScreenBeatmap.cs | 2 +- .../Visual/Gameplay/TestCaseAutoplay.cs | 2 +- .../Visual/Gameplay/TestCaseReplay.cs | 3 +- .../SongSelect/TestCasePlaySongSelect.cs | 4 +-- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 35 ++++++++----------- osu.Game/OsuGame.cs | 3 +- .../Difficulty/DifficultyCalculator.cs | 3 +- .../Difficulty/PerformanceCalculator.cs | 3 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 5 +-- osu.Game/Rulesets/Ruleset.cs | 2 +- osu.Game/Rulesets/UI/DrawableRuleset.cs | 19 +++++----- osu.Game/Rulesets/UI/Playfield.cs | 12 ++++--- .../UI/Scrolling/DrawableScrollingRuleset.cs | 5 +-- .../Screens/Multi/Match/MatchSubScreen.cs | 2 -- osu.Game/Screens/OsuScreen.cs | 5 +++ osu.Game/Screens/OsuScreenDependencies.cs | 13 ++++--- .../Screens/Play/GameplayClockContainer.cs | 9 ++--- osu.Game/Screens/Play/HUDOverlay.cs | 7 ++-- osu.Game/Screens/Play/Player.cs | 14 ++++---- osu.Game/Screens/Play/PlayerLoader.cs | 10 ++++-- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 5 +-- osu.Game/Screens/Select/MatchSongSelect.cs | 6 +--- osu.Game/Screens/Select/SongSelect.cs | 6 ++-- osu.Game/Tests/Visual/AllPlayersTestCase.cs | 2 +- osu.Game/Tests/Visual/OsuTestCase.cs | 17 +++++---- osu.Game/Tests/Visual/PlayerTestCase.cs | 2 +- 43 files changed, 147 insertions(+), 116 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs index fbb2db33b0..a696ba4e7e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.Tests protected override Player CreatePlayer(Ruleset ruleset) { - Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); + SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); return base.CreatePlayer(ruleset); } } diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index aa00e182a9..544694fc8f 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch { public class CatchRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) => new DrawableCatchRuleset(this, beatmap); + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IEnumerable mods) => new DrawableCatchRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index ba0f5b90ba..4b75b54d41 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.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.Input; using osu.Game.Beatmaps; using osu.Game.Configuration; @@ -10,6 +11,7 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Catch.Scoring; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; @@ -23,8 +25,8 @@ namespace osu.Game.Rulesets.Catch.UI protected override bool UserScrollSpeedAdjustment => false; - public DrawableCatchRuleset(Ruleset ruleset, WorkingBeatmap beatmap) - : base(ruleset, beatmap) + public DrawableCatchRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + : base(ruleset, beatmap, mods) { Direction.Value = ScrollingDirection.Down; TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450); diff --git a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs index acafaffee6..0bfbf38832 100644 --- a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs +++ b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs @@ -1,10 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using osu.Framework.Graphics; using osuTK; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; @@ -14,8 +16,8 @@ namespace osu.Game.Rulesets.Mania.Edit { public new IScrollingInfo ScrollingInfo => base.ScrollingInfo; - public DrawableManiaEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap) - : base(ruleset, beatmap) + public DrawableManiaEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 56c9471462..ebc94c86e2 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osu.Game.Screens.Edit.Compose.Components; using osuTK; @@ -41,9 +42,9 @@ namespace osu.Game.Rulesets.Mania.Edit public int TotalColumns => ((ManiaPlayfield)DrawableRuleset.Playfield).TotalColumns; - protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap) + protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) { - DrawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap); + DrawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap, mods); // This is the earliest we can cache the scrolling info to ourselves, before masks are added to the hierarchy and inject it dependencies.CacheAs(DrawableRuleset.ScrollingInfo); diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 0ff79d2836..02a9b5ed30 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Mania { public class ManiaRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) => new DrawableManiaRuleset(this, beatmap); + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IEnumerable mods) => new DrawableManiaRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score); diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 1c1ec604f6..9d10657680 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Scoring; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; @@ -39,8 +40,8 @@ namespace osu.Game.Rulesets.Mania.UI private readonly Bindable configDirection = new Bindable(); - public DrawableManiaRuleset(Ruleset ruleset, WorkingBeatmap beatmap) - : base(ruleset, beatmap) + public DrawableManiaRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + : base(ruleset, beatmap, mods) { // Generate the bar lines double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; diff --git a/osu.Game.Rulesets.Osu.Tests/StackingTest.cs b/osu.Game.Rulesets.Osu.Tests/StackingTest.cs index e2f6b2164c..13c9985f47 100644 --- a/osu.Game.Rulesets.Osu.Tests/StackingTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/StackingTest.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using NUnit.Framework; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Tests.Beatmaps; using Decoder = osu.Game.Beatmaps.Formats.Decoder; @@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Tests using (var reader = new StreamReader(stream)) { var beatmap = Decoder.GetDecoder(reader).Decode(reader); - var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo); + var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Enumerable.Empty()); var objects = converted.HitObjects.ToList(); diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs index d9cb203bdf..0c3050bfb4 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -1,7 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.UI; using osuTK; @@ -10,8 +12,8 @@ namespace osu.Game.Rulesets.Osu.Edit { public class DrawableOsuEditRuleset : DrawableOsuRuleset { - public DrawableOsuEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap) - : base(ruleset, beatmap) + public DrawableOsuEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 039ec5585e..9c4b6ee7aa 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders; @@ -23,8 +24,8 @@ namespace osu.Game.Rulesets.Osu.Edit { } - protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap) - => new DrawableOsuEditRuleset(ruleset, beatmap); + protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + => new DrawableOsuEditRuleset(ruleset, beatmap, mods); protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] { diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 44bce5bed8..115271da85 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu { public class OsuRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) => new DrawableOsuRuleset(this, beatmap); + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IEnumerable mods) => new DrawableOsuRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index f6a3be40b0..c2954e1b3b 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -1,11 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using System.Linq; using osu.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Input.Handlers; using osu.Game.Replays; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Objects; @@ -22,8 +24,8 @@ namespace osu.Game.Rulesets.Osu.UI { protected new OsuRulesetConfigManager Config => (OsuRulesetConfigManager)base.Config; - public DrawableOsuRuleset(Ruleset ruleset, WorkingBeatmap beatmap) - : base(ruleset, beatmap) + public DrawableOsuRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs index 369cdd49d2..c42faea9f9 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -11,6 +12,7 @@ using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Judgements; @@ -86,7 +88,7 @@ namespace osu.Game.Rulesets.Taiko.Tests Origin = Anchor.Centre, RelativeSizeAxes = Axes.X, Height = 768, - Children = new[] { drawableRuleset = new DrawableTaikoRuleset(new TaikoRuleset(), beatmap) } + Children = new[] { drawableRuleset = new DrawableTaikoRuleset(new TaikoRuleset(), beatmap, Enumerable.Empty()) } }); } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 448b1b42bb..cb53ec890b 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Taiko { public class TaikoRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) => new DrawableTaikoRuleset(this, beatmap); + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IEnumerable mods) => new DrawableTaikoRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index f4b9c46dfc..76bdd37ed3 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.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.Allocation; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Drawables; @@ -16,6 +17,7 @@ using osu.Framework.Input; using osu.Game.Configuration; using osu.Game.Input.Handlers; using osu.Game.Replays; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI @@ -26,8 +28,8 @@ namespace osu.Game.Rulesets.Taiko.UI protected override bool UserScrollSpeedAdjustment => false; - public DrawableTaikoRuleset(Ruleset ruleset, WorkingBeatmap beatmap) - : base(ruleset, beatmap) + public DrawableTaikoRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + : base(ruleset, beatmap, mods) { Direction.Value = ScrollingDirection.Left; TimeRange.Value = 7000; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 02dff6993d..e181130774 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -13,6 +13,7 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Catch.Beatmaps; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Rulesets.Osu; @@ -39,7 +40,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(6, working.BeatmapInfo.BeatmapVersion); Assert.AreEqual(6, working.Beatmap.BeatmapInfo.BeatmapVersion); - Assert.AreEqual(6, working.GetPlayableBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapVersion); + Assert.AreEqual(6, working.GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Enumerable.Empty()).BeatmapInfo.BeatmapVersion); } } diff --git a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs index 891b89e72d..e3875421b1 100644 --- a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs @@ -267,7 +267,7 @@ namespace osu.Game.Tests.Visual.Background AddUntilStep("Song select has selection", () => songSelect.Carousel.SelectedBeatmap != null); AddStep("Set default user settings", () => { - Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Concat(new[] { new OsuModNoFail() }); + SelectedMods.Value = SelectedMods.Value.Concat(new[] { new OsuModNoFail() }); songSelect.DimLevel.Value = 0.7f; songSelect.BlurLevel.Value = 0.4f; }); diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs index a2d92b7861..c930e77e9e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Gameplay { protected override Player CreatePlayer(Ruleset ruleset) { - Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); + SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); return new ScoreAccessiblePlayer(); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs index b98ce96fbb..2a72dc8242 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.Linq; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Play; @@ -15,7 +16,7 @@ namespace osu.Game.Tests.Visual.Gameplay { protected override Player CreatePlayer(Ruleset ruleset) { - var beatmap = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo); + var beatmap = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Enumerable.Empty()); return new ScoreAccessibleReplayPlayer(ruleset.GetAutoplayMod().CreateReplayScore(beatmap)); } diff --git a/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs index d5bc452d75..bc644da9d5 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs @@ -175,12 +175,12 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("change ruleset", () => { - songSelect.CurrentBeatmap.Mods.ValueChanged += onModChange; + SelectedMods.ValueChanged += onModChange; songSelect.Ruleset.ValueChanged += onRulesetChange; Ruleset.Value = new TaikoRuleset().RulesetInfo; - songSelect.CurrentBeatmap.Mods.ValueChanged -= onModChange; + SelectedMods.ValueChanged -= onModChange; songSelect.Ruleset.ValueChanged -= onRulesetChange; }); diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 73aa12a3db..3e6033da9c 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -52,7 +52,7 @@ namespace osu.Game.Beatmaps { public override IEnumerable GetModsFor(ModType type) => new Mod[] { }; - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IEnumerable mods) { throw new NotImplementedException(); } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 2e36d87024..bb13a8c0e7 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -11,7 +11,6 @@ using osu.Framework.IO.File; using System.IO; using System.Linq; using System.Threading; -using osu.Framework.Bindables; using osu.Game.IO.Serialization; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; @@ -28,16 +27,12 @@ namespace osu.Game.Beatmaps public readonly BeatmapMetadata Metadata; - public readonly Bindable> Mods = new Bindable>(new Mod[] { }); - protected WorkingBeatmap(BeatmapInfo beatmapInfo) { BeatmapInfo = beatmapInfo; BeatmapSetInfo = beatmapInfo.BeatmapSet; Metadata = beatmapInfo.Metadata ?? BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); - Mods.ValueChanged += _ => applyRateAdjustments(); - beatmap = new RecyclableLazy(() => { var b = GetBeatmap() ?? new Beatmap(); @@ -55,7 +50,7 @@ namespace osu.Game.Beatmaps { // we want to ensure that we always have a track, even if it's a fake one. var t = GetTrack() ?? new VirtualBeatmapTrack(Beatmap); - applyRateAdjustments(t); + // applyRateAdjustments(t); return t; }); @@ -87,7 +82,7 @@ namespace osu.Game.Beatmaps /// The to create a playable for. /// The converted . /// If could not be converted to . - public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset) + public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IEnumerable mods) { var rulesetInstance = ruleset.CreateInstance(); @@ -98,19 +93,19 @@ namespace osu.Game.Beatmaps throw new BeatmapInvalidForRulesetException($"{nameof(Beatmaps.Beatmap)} can not be converted for the ruleset (ruleset: {ruleset.InstantiationInfo}, converter: {converter})."); // Apply conversion mods - foreach (var mod in Mods.Value.OfType()) + foreach (var mod in mods.OfType()) mod.ApplyToBeatmapConverter(converter); // Convert IBeatmap converted = converter.Convert(); // Apply difficulty mods - if (Mods.Value.Any(m => m is IApplicableToDifficulty)) + if (mods.Any(m => m is IApplicableToDifficulty)) { converted.BeatmapInfo = converted.BeatmapInfo.Clone(); converted.BeatmapInfo.BaseDifficulty = converted.BeatmapInfo.BaseDifficulty.Clone(); - foreach (var mod in Mods.Value.OfType()) + foreach (var mod in mods.OfType()) mod.ApplyToDifficulty(converted.BeatmapInfo.BaseDifficulty); } @@ -122,7 +117,7 @@ namespace osu.Game.Beatmaps foreach (var obj in converted.HitObjects) obj.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty); - foreach (var mod in Mods.Value.OfType()) + foreach (var mod in mods.OfType()) foreach (var obj in converted.HitObjects) mod.ApplyToHitObject(obj); @@ -188,15 +183,15 @@ namespace osu.Game.Beatmaps /// public void RecycleTrack() => track.Recycle(); - private void applyRateAdjustments(Track t = null) - { - if (t == null && track.IsResultAvailable) t = Track; - if (t == null) return; - - t.ResetSpeedAdjustments(); - foreach (var mod in Mods.Value.OfType()) - mod.ApplyToClock(t); - } + // private void applyRateAdjustments(Track t = null) + // { + // if (t == null && track.IsResultAvailable) t = Track; + // if (t == null) return; + // + // t.ResetSpeedAdjustments(); + // foreach (var mod in Mods.Value.OfType()) + // mod.ApplyToClock(t); + // } public class RecyclableLazy { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 4f92ff831c..2cef4f66a9 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -293,9 +293,8 @@ namespace osu.Game performFromMainMenu(() => { ruleset.Value = databasedScoreInfo.Ruleset; - Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); - Beatmap.Value.Mods.Value = databasedScoreInfo.Mods; + selectedMods.Value = databasedScoreInfo.Mods; menuScreen.Push(new PlayerLoader(() => new ReplayPlayer(databasedScore))); }, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true); diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index aad55f8a38..e181051737 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -39,8 +39,7 @@ namespace osu.Game.Rulesets.Difficulty { mods = mods.Select(m => m.CreateCopy()).ToArray(); - beatmap.Mods.Value = mods; - IBeatmap playableBeatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo); + IBeatmap playableBeatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo, mods); var clock = new StopwatchClock(); mods.OfType().ForEach(m => m.ApplyToClock(clock)); diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index 2b627ee8e6..9ab81b9580 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -26,8 +26,7 @@ namespace osu.Game.Rulesets.Difficulty Ruleset = ruleset; Score = score; - beatmap.Mods.Value = score.Mods; - Beatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo); + Beatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo, score.Mods); Attributes = ruleset.CreateDifficultyCalculator(beatmap).Calculate(score.Mods); diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 41de0c36fc..5219cb9581 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -14,6 +14,7 @@ using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Edit.Tools; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; @@ -185,8 +186,8 @@ namespace osu.Game.Rulesets.Edit } internal override DrawableEditRuleset CreateDrawableRuleset() - => new DrawableEditRuleset(CreateDrawableRuleset(Ruleset, Beatmap.Value)); + => new DrawableEditRuleset(CreateDrawableRuleset(Ruleset, Beatmap.Value, Enumerable.Empty())); - protected abstract DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap); + protected abstract DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods); } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index cdfe02b60b..90fe25accf 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets /// The beatmap to create the hit renderer for. /// Unable to successfully load the beatmap to be usable with this ruleset. /// - public abstract DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap); + public abstract DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IEnumerable mods); /// /// Creates a to convert a to one that is applicable for this . diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 27137d9f98..0ab07de1ac 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -11,7 +11,6 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics.Cursor; @@ -82,7 +81,9 @@ namespace osu.Game.Rulesets.UI /// /// The mods which are to be applied. /// - private readonly IEnumerable mods; + [Cached] + [Cached(typeof(IBindable>))] + private readonly Bindable> mods = new Bindable>(); private FrameStabilityContainer frameStabilityContainer; @@ -93,16 +94,18 @@ namespace osu.Game.Rulesets.UI /// /// The ruleset being represented. /// The beatmap to create the hit renderer for. - protected DrawableRuleset(Ruleset ruleset, WorkingBeatmap workingBeatmap) + protected DrawableRuleset(Ruleset ruleset, WorkingBeatmap workingBeatmap, IEnumerable mods) : base(ruleset) { - Debug.Assert(workingBeatmap != null, "DrawableRuleset initialized with a null beatmap."); + if (workingBeatmap == null) + throw new ArgumentException("Beatmap cannot be null.", nameof(workingBeatmap)); + + this.mods.Value = mods; RelativeSizeAxes = Axes.Both; - Beatmap = (Beatmap)workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo); + Beatmap = (Beatmap)workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo, mods); - mods = workingBeatmap.Mods.Value; applyBeatmapMods(mods); KeyBindingInputManager = CreateInputManager(); @@ -157,7 +160,7 @@ namespace osu.Game.Rulesets.UI .WithChild(ResumeOverlay))); } - applyRulesetMods(mods, config); + applyRulesetMods(mods.Value, config); loadObjects(); } @@ -172,7 +175,7 @@ namespace osu.Game.Rulesets.UI Playfield.PostProcess(); - foreach (var mod in mods.OfType()) + foreach (var mod in mods.Value.OfType()) mod.ApplyToDrawableHitObjects(Playfield.HitObjectContainer.Objects); } diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 48b950c070..6ea565af44 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -57,13 +57,15 @@ namespace osu.Game.Rulesets.UI hitObjectContainerLazy = new Lazy(CreateHitObjectContainer); } - private WorkingBeatmap beatmap; + [Resolved] + private IBindable beatmap { get; set; } + + [Resolved] + private IBindable> selectedMods { get; set; } [BackgroundDependencyLoader] - private void load(IBindable beatmap) + private void load() { - this.beatmap = beatmap.Value; - Cursor = CreateCursor(); if (Cursor != null) AddInternal(Cursor); @@ -123,7 +125,7 @@ namespace osu.Game.Rulesets.UI base.Update(); if (beatmap != null) - foreach (var mod in beatmap.Mods.Value) + foreach (var mod in selectedMods.Value) if (mod is IUpdatableByPlayfield updatable) updatable.Update(this); } diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 3b368652f2..2bb98dd679 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Configuration; using osu.Game.Input.Bindings; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; @@ -80,8 +81,8 @@ namespace osu.Game.Rulesets.UI.Scrolling [Cached(Type = typeof(IScrollingInfo))] private readonly LocalScrollingInfo scrollingInfo; - protected DrawableScrollingRuleset(Ruleset ruleset, WorkingBeatmap beatmap) - : base(ruleset, beatmap) + protected DrawableScrollingRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + : base(ruleset, beatmap, mods) { scrollingInfo = new LocalScrollingInfo(); scrollingInfo.Direction.BindTo(Direction); diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index a71106872e..b3f9a4ae21 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -222,8 +222,6 @@ namespace osu.Game.Screens.Multi.Match private void onStart() { - Beatmap.Value.Mods.Value = SelectedMods.Value.ToArray(); - switch (type.Value) { default: diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index e0a25deecf..33e725eb41 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.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 Microsoft.EntityFrameworkCore.Internal; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -14,6 +15,7 @@ using osu.Game.Input.Bindings; using osu.Game.Rulesets; using osu.Game.Screens.Menu; using osu.Game.Overlays; +using osu.Game.Rulesets.Mods; namespace osu.Game.Screens { @@ -63,12 +65,15 @@ namespace osu.Game.Screens public Bindable Ruleset { get; set; } + public Bindable> SelectedMods { get; set; } + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { var screenDependencies = new OsuScreenDependencies(DisallowExternalBeatmapRulesetChanges, parent); Beatmap = screenDependencies.Beatmap; Ruleset = screenDependencies.Ruleset; + SelectedMods = screenDependencies.SelectedMods; return base.CreateChildDependencies(screenDependencies); } diff --git a/osu.Game/Screens/OsuScreenDependencies.cs b/osu.Game/Screens/OsuScreenDependencies.cs index 84e5de76de..9cc415f581 100644 --- a/osu.Game/Screens/OsuScreenDependencies.cs +++ b/osu.Game/Screens/OsuScreenDependencies.cs @@ -1,10 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; namespace osu.Game.Screens { @@ -14,6 +16,8 @@ namespace osu.Game.Screens public Bindable Ruleset { get; } + public Bindable> SelectedMods { get; } + public OsuScreenDependencies(bool requireLease, IReadOnlyDependencyContainer parent) : base(parent) { @@ -21,20 +25,21 @@ namespace osu.Game.Screens { Beatmap = parent.Get>()?.GetBoundCopy(); if (Beatmap == null) - { Cache(Beatmap = parent.Get>().BeginLease(false)); - } Ruleset = parent.Get>()?.GetBoundCopy(); if (Ruleset == null) - { Cache(Ruleset = parent.Get>().BeginLease(true)); - } + + SelectedMods = parent.Get>>()?.GetBoundCopy(); + if (SelectedMods == null) + Cache(SelectedMods = parent.Get>>().BeginLease(true)); } else { Beatmap = (parent.Get>() ?? parent.Get>()).GetBoundCopy(); Ruleset = (parent.Get>() ?? parent.Get>()).GetBoundCopy(); + SelectedMods = (parent.Get>>() ?? parent.Get>>()).GetBoundCopy(); } } } diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index c13222c6de..b17286f69e 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.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 System.Threading.Tasks; using osu.Framework; @@ -22,7 +23,7 @@ namespace osu.Game.Screens.Play /// public class GameplayClockContainer : Container { - private readonly WorkingBeatmap beatmap; + private readonly IEnumerable mods; /// /// The original source (usually a 's track). @@ -54,9 +55,9 @@ namespace osu.Game.Screens.Play private readonly FramedOffsetClock offsetClock; - public GameplayClockContainer(WorkingBeatmap beatmap, double gameplayStartTime) + public GameplayClockContainer(WorkingBeatmap beatmap, IEnumerable mods, double gameplayStartTime) { - this.beatmap = beatmap; + this.mods = mods; RelativeSizeAxes = Axes.Both; @@ -154,7 +155,7 @@ namespace osu.Game.Screens.Play else sourceClock.Rate = UserPlaybackRate.Value; - foreach (var mod in beatmap.Mods.Value.OfType()) + foreach (var mod in mods.OfType()) mod.ApplyToClock(sourceClock); } } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index a7b7f96e7a..aa4375f652 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -2,16 +2,17 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; -using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Screens.Play.HUD; @@ -42,7 +43,7 @@ namespace osu.Game.Screens.Play public Action RequestSeek; - public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, WorkingBeatmap working) + public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, IEnumerable mods) { RelativeSizeAxes = Axes.Both; @@ -96,7 +97,7 @@ namespace osu.Game.Screens.Play Progress.AllowSeeking = drawableRuleset.HasReplayLoaded.Value; Progress.RequestSeek = time => RequestSeek(time); - ModDisplay.Current.BindTo(working.Mods); + ModDisplay.Current.Value = mods; } [BackgroundDependencyLoader(true)] diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0eebefec86..bf2bbc58b8 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Play if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); - InternalChild = GameplayClockContainer = new GameplayClockContainer(working, DrawableRuleset.GameplayStartTime); + InternalChild = GameplayClockContainer = new GameplayClockContainer(working, SelectedMods.Value, DrawableRuleset.GameplayStartTime); GameplayClockContainer.Children = new[] { @@ -123,7 +123,7 @@ namespace osu.Game.Screens.Play }, // display the cursor above some HUD elements. DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), - HUDOverlay = new HUDOverlay(ScoreProcessor, DrawableRuleset, working) + HUDOverlay = new HUDOverlay(ScoreProcessor, DrawableRuleset, SelectedMods.Value) { HoldToQuit = { Action = performUserRequestedExit }, PlayerSettingsOverlay = { PlaybackSettings = { UserPlaybackRate = { BindTarget = GameplayClockContainer.UserPlaybackRate } } }, @@ -170,7 +170,7 @@ namespace osu.Game.Screens.Play ScoreProcessor.AllJudged += onCompletion; ScoreProcessor.Failed += onFail; - foreach (var mod in Beatmap.Value.Mods.Value.OfType()) + foreach (var mod in SelectedMods.Value.OfType()) mod.ApplyToScoreProcessor(ScoreProcessor); } @@ -192,7 +192,7 @@ namespace osu.Game.Screens.Play try { - DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(working); + DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(working, SelectedMods.Value); } catch (BeatmapInvalidForRulesetException) { @@ -200,7 +200,7 @@ namespace osu.Game.Screens.Play // let's try again forcing the beatmap's ruleset. ruleset = beatmap.BeatmapInfo.Ruleset; rulesetInstance = ruleset.CreateInstance(); - DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(Beatmap.Value); + DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(Beatmap.Value, SelectedMods.Value); } if (!DrawableRuleset.Objects.Any()) @@ -271,7 +271,7 @@ namespace osu.Game.Screens.Play { Beatmap = Beatmap.Value.BeatmapInfo, Ruleset = ruleset, - Mods = Beatmap.Value.Mods.Value.ToArray(), + Mods = SelectedMods.Value.ToArray(), User = api.LocalUser.Value, }; @@ -325,7 +325,7 @@ namespace osu.Game.Screens.Play private bool onFail() { - if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) + if (SelectedMods.Value.OfType().Any(m => !m.AllowFail)) return false; GameplayClockContainer.Stop(); diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index e9ee5d3fa8..70f5736786 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.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 System.Threading.Tasks; using osu.Framework.Allocation; @@ -16,6 +17,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Menu; using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.PlayerSettings; @@ -66,7 +68,7 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - info = new BeatmapMetadataDisplay(Beatmap.Value) + info = new BeatmapMetadataDisplay(Beatmap.Value, SelectedMods.Value) { Alpha = 0, Anchor = Anchor.Centre, @@ -299,6 +301,7 @@ namespace osu.Game.Screens.Play } private readonly WorkingBeatmap beatmap; + private readonly IEnumerable mods; private LoadingAnimation loading; private Sprite backgroundSprite; private ModDisplay modDisplay; @@ -320,9 +323,10 @@ namespace osu.Game.Screens.Play } } - public BeatmapMetadataDisplay(WorkingBeatmap beatmap) + public BeatmapMetadataDisplay(WorkingBeatmap beatmap, IEnumerable mods) { this.beatmap = beatmap; + this.mods = mods; } [BackgroundDependencyLoader] @@ -403,7 +407,7 @@ namespace osu.Game.Screens.Play Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Top = 20 }, - Current = beatmap.Mods + Current = { Value = mods } } }, } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index d32387c1d3..03cf767062 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -25,6 +25,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; namespace osu.Game.Screens.Select @@ -309,12 +310,12 @@ namespace osu.Game.Screens.Select try { // Try to get the beatmap with the user's ruleset - playableBeatmap = beatmap.GetPlayableBeatmap(ruleset); + playableBeatmap = beatmap.GetPlayableBeatmap(ruleset, Enumerable.Empty()); } catch (BeatmapInvalidForRulesetException) { // Can't be converted to the user's ruleset, so use the beatmap's own ruleset - playableBeatmap = beatmap.GetPlayableBeatmap(beatmap.BeatmapInfo.Ruleset); + playableBeatmap = beatmap.GetPlayableBeatmap(beatmap.BeatmapInfo.Ruleset, Enumerable.Empty()); } labels.AddRange(playableBeatmap.GetStatistics().Select(s => new InfoLabel(s))); diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index fa5dc4c1d1..bc33750d6f 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; using Humanizer; using osu.Framework.Allocation; @@ -26,9 +25,6 @@ namespace osu.Game.Screens.Select [Resolved(typeof(Room))] protected Bindable CurrentItem { get; private set; } - [Resolved] - private Bindable> selectedMods { get; set; } - [Resolved] private BeatmapManager beatmaps { get; set; } @@ -65,7 +61,7 @@ namespace osu.Game.Screens.Select { Ruleset.Value = CurrentItem.Value.Ruleset; Beatmap.Value = beatmaps.GetWorkingBeatmap(CurrentItem.Value.Beatmap); - Beatmap.Value.Mods.Value = selectedMods.Value = CurrentItem.Value.RequiredMods ?? Enumerable.Empty(); + SelectedMods.Value = CurrentItem.Value.RequiredMods ?? Enumerable.Empty(); } Beatmap.Disabled = true; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index b60e693cbf..64e64edce2 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -394,7 +394,7 @@ namespace osu.Game.Screens.Select { Logger.Log($"ruleset changed from \"{decoupledRuleset.Value}\" to \"{ruleset}\""); - Beatmap.Value.Mods.Value = Enumerable.Empty(); + SelectedMods.Value = Enumerable.Empty(); decoupledRuleset.Value = ruleset; // force a filter before attempting to change the beatmap. @@ -530,7 +530,7 @@ namespace osu.Game.Screens.Select Beatmap.Value.Track.Looping = false; SelectedMods.UnbindAll(); - Beatmap.Value.Mods.Value = new Mod[] { }; + base.SelectedMods.Value = Enumerable.Empty(); return false; } @@ -557,8 +557,6 @@ namespace osu.Game.Screens.Select /// The working beatmap. protected virtual void UpdateBeatmap(WorkingBeatmap beatmap) { - beatmap.Mods.BindTo(SelectedMods); - Logger.Log($"working beatmap updated to {beatmap}"); if (Background is BackgroundScreenBeatmap backgroundModeBeatmap) diff --git a/osu.Game/Tests/Visual/AllPlayersTestCase.cs b/osu.Game/Tests/Visual/AllPlayersTestCase.cs index 4ef9b346b0..21955da6e9 100644 --- a/osu.Game/Tests/Visual/AllPlayersTestCase.cs +++ b/osu.Game/Tests/Visual/AllPlayersTestCase.cs @@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual var working = CreateWorkingBeatmap(beatmap, Clock); Beatmap.Value = working; - Beatmap.Value.Mods.Value = new[] { r.GetAllMods().First(m => m is ModNoFail) }; + SelectedMods.Value = new[] { r.GetAllMods().First(m => m is ModNoFail) }; Player?.Exit(); Player = null; diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index 495c5dfbad..9dab981ed5 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.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.Framework.Allocation; using osu.Framework.Audio; @@ -10,16 +11,26 @@ using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; namespace osu.Game.Tests.Visual { public abstract class OsuTestCase : TestCase { + [Cached(typeof(Bindable))] + [Cached(typeof(IBindable))] private readonly OsuTestBeatmap beatmap = new OsuTestBeatmap(new DummyWorkingBeatmap()); + protected BindableBeatmap Beatmap => beatmap; + [Cached] + [Cached(typeof(IBindable))] protected readonly Bindable Ruleset = new Bindable(); + [Cached] + [Cached(Type = typeof(IBindable>))] + protected readonly Bindable> SelectedMods = new Bindable>(); + protected DependencyContainer Dependencies { get; private set; } private readonly Lazy localStorage; @@ -32,12 +43,6 @@ namespace osu.Game.Tests.Visual // This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures beatmap.Default = new DummyWorkingBeatmap(Dependencies.Get()); - Dependencies.CacheAs>(beatmap); - Dependencies.CacheAs>(beatmap); - - Dependencies.CacheAs(Ruleset); - Dependencies.CacheAs>(Ruleset); - return Dependencies; } diff --git a/osu.Game/Tests/Visual/PlayerTestCase.cs b/osu.Game/Tests/Visual/PlayerTestCase.cs index 3bf707fade..409e79b4a5 100644 --- a/osu.Game/Tests/Visual/PlayerTestCase.cs +++ b/osu.Game/Tests/Visual/PlayerTestCase.cs @@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual Beatmap.Value = new TestWorkingBeatmap(beatmap, Clock); if (!AllowFail) - Beatmap.Value.Mods.Value = new[] { ruleset.GetAllMods().First(m => m is ModNoFail) }; + SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModNoFail) }; Player = CreatePlayer(ruleset); LoadScreen(Player); From ad124bfeec6745939b172f310618d2b6c5a99656 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 8 Apr 2019 19:16:34 +0900 Subject: [PATCH 0530/5608] Reimplement select mod track adjustments --- osu.Game/Beatmaps/WorkingBeatmap.cs | 19 +------------------ osu.Game/OsuGame.cs | 2 +- osu.Game/Overlays/MusicController.cs | 22 ++++++++++++++++++++-- osu.Game/Screens/OsuScreen.cs | 6 +++--- osu.Game/Screens/Select/SongSelect.cs | 15 ++++++++------- 5 files changed, 33 insertions(+), 31 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index bb13a8c0e7..ec0a76b52b 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -46,14 +46,7 @@ namespace osu.Game.Beatmaps return b; }); - track = new RecyclableLazy(() => - { - // we want to ensure that we always have a track, even if it's a fake one. - var t = GetTrack() ?? new VirtualBeatmapTrack(Beatmap); - // applyRateAdjustments(t); - return t; - }); - + track = new RecyclableLazy(() => GetTrack() ?? new VirtualBeatmapTrack(Beatmap)); background = new RecyclableLazy(GetBackground, BackgroundStillValid); waveform = new RecyclableLazy(GetWaveform); storyboard = new RecyclableLazy(GetStoryboard); @@ -183,16 +176,6 @@ namespace osu.Game.Beatmaps /// public void RecycleTrack() => track.Recycle(); - // private void applyRateAdjustments(Track t = null) - // { - // if (t == null && track.IsResultAvailable) t = Track; - // if (t == null) return; - // - // t.ResetSpeedAdjustments(); - // foreach (var mod in Mods.Value.OfType()) - // mod.ApplyToClock(t); - // } - public class RecyclableLazy { private Lazy lazy; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 2cef4f66a9..4d889677a5 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -113,7 +113,7 @@ namespace osu.Game // todo: move this to SongSelect once Screen has the ability to unsuspend. [Cached] [Cached(Type = typeof(IBindable>))] - private readonly Bindable> selectedMods = new Bindable>(new Mod[] { }); + private readonly Bindable> selectedMods = new Bindable>(Enumerable.Empty()); public OsuGame(string[] args = null) { diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index b24c6c3508..0ad4da2ce9 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -22,6 +22,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Music; +using osu.Game.Rulesets.Mods; using osuTK; using osuTK.Graphics; @@ -54,7 +55,11 @@ namespace osu.Game.Overlays private Container dragContainer; private Container playerContainer; - private readonly Bindable beatmap = new Bindable(); + [Resolved] + private Bindable beatmap { get; set; } + + [Resolved] + private IBindable> selectedMods { get; set; } /// /// Provide a source for the toolbar height. @@ -73,7 +78,6 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load(Bindable beatmap, BeatmapManager beatmaps, OsuColour colours) { - this.beatmap.BindTo(beatmap); this.beatmaps = beatmaps; Children = new Drawable[] @@ -231,6 +235,7 @@ namespace osu.Game.Overlays { beatmap.BindValueChanged(beatmapChanged, true); beatmap.BindDisabledChanged(beatmapDisabledChanged, true); + selectedMods.BindValueChanged(_ => updateAudioAdjustments(), true); base.LoadComplete(); } @@ -354,10 +359,23 @@ namespace osu.Game.Overlays progressBar.CurrentTime = 0; updateDisplay(current, direction); + updateAudioAdjustments(); queuedDirection = null; } + private void updateAudioAdjustments() + { + var track = current?.Track; + if (track == null) + return; + + track.ResetSpeedAdjustments(); + + foreach (var mod in selectedMods.Value.OfType()) + mod.ApplyToClock(track); + } + private void currentTrackCompleted() => Schedule(() => { if (!current.Track.Looping && !beatmap.Disabled && beatmapSets.Any()) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 33e725eb41..bd7f326b50 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -61,11 +61,11 @@ namespace osu.Game.Screens public virtual float BackgroundParallaxAmount => 1; - public Bindable Beatmap { get; set; } + public Bindable Beatmap { get; private set; } - public Bindable Ruleset { get; set; } + public Bindable Ruleset { get; private set; } - public Bindable> SelectedMods { get; set; } + public Bindable> SelectedMods { get; private set; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 64e64edce2..0b6bb6f570 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -83,9 +83,7 @@ namespace osu.Game.Screens.Select private readonly Bindable decoupledRuleset = new Bindable(); - [Cached] - [Cached(Type = typeof(IBindable>))] - protected readonly Bindable> SelectedMods = new Bindable>(new Mod[] { }); + protected readonly Bindable> SelectedMods = new Bindable>(Enumerable.Empty()); protected SongSelect() { @@ -217,11 +215,8 @@ namespace osu.Game.Screens.Select } [BackgroundDependencyLoader(true)] - private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, Bindable> selectedMods) + private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins) { - if (selectedMods != null) - SelectedMods.BindTo(selectedMods); - if (Footer != null) { Footer.AddButton(@"mods", colours.Yellow, ModSelect, Key.F1); @@ -269,6 +264,12 @@ namespace osu.Game.Screens.Select protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + + SelectedMods.BindTo(base.SelectedMods); + + dependencies.CacheAs(SelectedMods); + dependencies.CacheAs>>(SelectedMods); + dependencies.CacheAs(this); dependencies.CacheAs(decoupledRuleset); dependencies.CacheAs>(decoupledRuleset); From cbb3fdaca8f0fe2bc05f7839c5e9d57c07dac573 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 9 Apr 2019 12:44:03 +0900 Subject: [PATCH 0531/5608] Fix various crashes due to bindable being disabled --- .../Visual/SongSelect/TestCasePlaySongSelect.cs | 8 ++------ osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 4 ---- osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs | 7 +------ osu.Game/Screens/Select/MatchSongSelect.cs | 2 ++ osu.Game/Screens/Select/SongSelect.cs | 17 ++++++++--------- 5 files changed, 13 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs index bc644da9d5..a70529b384 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs @@ -35,10 +35,6 @@ namespace osu.Game.Tests.Visual.SongSelect private WorkingBeatmap defaultBeatmap; private DatabaseContextFactory factory; - [Cached] - [Cached(Type = typeof(IBindable>))] - private readonly Bindable> selectedMods = new Bindable>(new Mod[] { }); - public override IReadOnlyList RequiredTypes => new[] { typeof(Screens.Select.SongSelect), @@ -185,7 +181,7 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddAssert("mods changed before ruleset", () => modChangeIndex < rulesetChangeIndex); - AddAssert("empty mods", () => !selectedMods.Value.Any()); + AddAssert("empty mods", () => !SelectedMods.Value.Any()); void onModChange(ValueChangedEvent> e) => modChangeIndex = actionIndex++; void onRulesetChange(ValueChangedEvent e) => rulesetChangeIndex = actionIndex--; @@ -218,7 +214,7 @@ namespace osu.Game.Tests.Visual.SongSelect private static int importId; private int getImportId() => ++importId; - private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => selectedMods.Value = mods); + private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => SelectedMods.Value = mods); private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id)); diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index b3f9a4ae21..e5ab46ebe2 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.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.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -42,9 +41,6 @@ namespace osu.Game.Screens.Multi.Match [Resolved(typeof(Room))] protected Bindable CurrentItem { get; private set; } - [Resolved] - protected Bindable> SelectedMods { get; private set; } - [Resolved] private BeatmapManager beatmapManager { get; set; } diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index d5b8f1f0c8..8ce68ac593 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; @@ -14,7 +13,6 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Screens.Multi.Ranking; using osu.Game.Screens.Play; @@ -37,9 +35,6 @@ namespace osu.Game.Screens.Multi.Play [Resolved] private IBindable ruleset { get; set; } - [Resolved] - private Bindable> selectedMods { get; set; } - public TimeshiftPlayer(PlaylistItem playlistItem) { this.playlistItem = playlistItem; @@ -61,7 +56,7 @@ namespace osu.Game.Screens.Multi.Play if (ruleset.Value.ID != playlistItem.Ruleset.ID) throw new InvalidOperationException("Current Ruleset does not match PlaylistItem's Ruleset"); - if (!playlistItem.RequiredMods.All(m => selectedMods.Value.Contains(m))) + if (!playlistItem.RequiredMods.All(m => SelectedMods.Value.Contains(m))) throw new InvalidOperationException("Current Mods do not match PlaylistItem's RequiredMods"); var req = new CreateRoomScoreRequest(roomId.Value ?? 0, playlistItem.ID); diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index bc33750d6f..1011f6f32d 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -66,6 +66,7 @@ namespace osu.Game.Screens.Select Beatmap.Disabled = true; Ruleset.Disabled = true; + SelectedMods.Disabled = true; return false; } @@ -76,6 +77,7 @@ namespace osu.Game.Screens.Select Beatmap.Disabled = false; Ruleset.Disabled = false; + SelectedMods.Disabled = false; } } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 0b6bb6f570..2bb646750c 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -83,7 +83,9 @@ namespace osu.Game.Screens.Select private readonly Bindable decoupledRuleset = new Bindable(); - protected readonly Bindable> SelectedMods = new Bindable>(Enumerable.Empty()); + [Cached] + [Cached(Type = typeof(IBindable>))] + private readonly Bindable> selectedMods = new Bindable>(Enumerable.Empty()); // Bound to the game's mods, but is not reset on exiting protected SongSelect() { @@ -217,6 +219,8 @@ namespace osu.Game.Screens.Select [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins) { + selectedMods.BindTo(SelectedMods); + if (Footer != null) { Footer.AddButton(@"mods", colours.Yellow, ModSelect, Key.F1); @@ -265,11 +269,6 @@ namespace osu.Game.Screens.Select { dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - SelectedMods.BindTo(base.SelectedMods); - - dependencies.CacheAs(SelectedMods); - dependencies.CacheAs>>(SelectedMods); - dependencies.CacheAs(this); dependencies.CacheAs(decoupledRuleset); dependencies.CacheAs>(decoupledRuleset); @@ -395,7 +394,7 @@ namespace osu.Game.Screens.Select { Logger.Log($"ruleset changed from \"{decoupledRuleset.Value}\" to \"{ruleset}\""); - SelectedMods.Value = Enumerable.Empty(); + selectedMods.Value = Enumerable.Empty(); decoupledRuleset.Value = ruleset; // force a filter before attempting to change the beatmap. @@ -530,8 +529,8 @@ namespace osu.Game.Screens.Select if (Beatmap.Value.Track != null) Beatmap.Value.Track.Looping = false; - SelectedMods.UnbindAll(); - base.SelectedMods.Value = Enumerable.Empty(); + selectedMods.UnbindAll(); + SelectedMods.Value = Enumerable.Empty(); return false; } From 56496d28ba9575ea75b37dd0e02243433a292bea Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 9 Apr 2019 12:50:54 +0900 Subject: [PATCH 0532/5608] Reset mods when exiting match --- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index e5ab46ebe2..5f29044c76 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -178,6 +178,9 @@ namespace osu.Game.Screens.Multi.Match public override bool OnExiting(IScreen next) { RoomManager?.PartRoom(); + + SelectedMods.Value = Enumerable.Empty(); + return base.OnExiting(next); } From 1c952e58cc45710bf63d0226972d71818b33e778 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 9 Apr 2019 13:15:48 +0900 Subject: [PATCH 0533/5608] Fix testcase failures --- osu.Game/Tests/Visual/OsuTestCase.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index 9dab981ed5..1a8403db40 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual [Cached] [Cached(Type = typeof(IBindable>))] - protected readonly Bindable> SelectedMods = new Bindable>(); + protected readonly Bindable> SelectedMods = new Bindable>(Enumerable.Empty()); protected DependencyContainer Dependencies { get; private set; } @@ -38,12 +38,10 @@ namespace osu.Game.Tests.Visual protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - // This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures - beatmap.Default = new DummyWorkingBeatmap(Dependencies.Get()); + beatmap.Default = new DummyWorkingBeatmap(parent.Get()); - return Dependencies; + return Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); } protected OsuTestCase() From 4c571acd671a293dfbe3a6aee6963475bcbb67cc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 9 Apr 2019 13:33:16 +0900 Subject: [PATCH 0534/5608] Reinstantiate mods for every player --- osu.Game/Screens/Play/Player.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index bf2bbc58b8..d8e31b7ad6 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.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.Framework.Allocation; using osu.Framework.Audio; @@ -69,6 +70,10 @@ namespace osu.Game.Screens.Play protected GameplayClockContainer GameplayClockContainer { get; private set; } + [Cached] + [Cached(Type = typeof(IBindable>))] + protected readonly Bindable> SelectedMods = new Bindable>(Enumerable.Empty()); + private readonly bool allowPause; private readonly bool showResults; @@ -88,6 +93,8 @@ namespace osu.Game.Screens.Play { this.api = api; + SelectedMods.Value = base.SelectedMods.Value.Select(m => m.CreateCopy()).ToArray(); + WorkingBeatmap working = loadBeatmap(); if (working == null) From d8ec1e73a3025c162e10cebbf8606af91c0ac88c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 9 Apr 2019 13:50:54 +0900 Subject: [PATCH 0535/5608] Cleanup TestCasePlayerLoader --- .../Visual/Gameplay/TestCasePlayerLoader.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs index 41d484e21f..aba689b241 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs @@ -2,10 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System.Threading; +using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; -using osu.Game.Beatmaps; using osu.Game.Screens; using osu.Game.Screens.Play; @@ -21,23 +21,15 @@ namespace osu.Game.Tests.Visual.Gameplay InputManager.Add(stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }); } - [BackgroundDependencyLoader] - private void load(OsuGameBase game) + [Test] + public void TestLoadContinuation() { - Beatmap.Value = new DummyWorkingBeatmap(game); - AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => new Player(false, false)))); - AddUntilStep("wait for current", () => loader.IsCurrentScreen()); - AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); - AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen()); - AddStep("exit loader", () => loader.Exit()); - AddUntilStep("wait for no longer alive", () => !loader.IsAlive); - AddStep("load slow dummy beatmap", () => { SlowLoadPlayer slow = null; From aa2c97b859eec9cc6778520a45b13bb5d1c21341 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 9 Apr 2019 15:05:03 +0900 Subject: [PATCH 0536/5608] Add mod reinstantiation testcase --- .../Visual/Gameplay/TestCasePlayerLoader.cs | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs index aba689b241..fba4aca343 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs @@ -1,11 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using System.Threading; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Screens; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; using osu.Game.Screens; using osu.Game.Screens.Play; @@ -42,6 +47,81 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen()); } + [Test] + public void TestModReinstantiation() + { + TestPlayer player = null; + TestMod gameMod = null; + TestMod playerMod1 = null; + TestMod playerMod2 = null; + + AddStep("load player", () => + { + SelectedMods.Value = new[] { gameMod = new TestMod() }; + InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre); + stack.Push(new PlayerLoader(() => player = new TestPlayer())); + }); + + AddUntilStep("wait for player to become current", () => + { + if (player.IsCurrentScreen()) + { + playerMod1 = (TestMod)player.SelectedMods.Value.Single(); + return true; + } + + return false; + }); + + AddAssert("game mods not applied", () => gameMod.Applied == false); + AddAssert("player mods applied", () => playerMod1.Applied); + + AddStep("restart player", () => + { + player = null; + player.Restart(); + }); + + AddUntilStep("wait for player to become current", () => + { + if (player.IsCurrentScreen()) + { + playerMod2 = (TestMod)player.SelectedMods.Value.Single(); + return true; + } + + return false; + }); + + AddAssert("game mods not applied", () => gameMod.Applied == false); + AddAssert("player has different mods", () => playerMod1 != playerMod2); + AddAssert("player mods applied", () => playerMod2.Applied); + } + + private class TestMod : Mod, IApplicableToScoreProcessor + { + public override string Name => string.Empty; + public override string Acronym => string.Empty; + public override double ScoreMultiplier => 1; + + public bool Applied { get; private set; } + + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + { + Applied = true; + } + } + + private class TestPlayer : Player + { + public new Bindable> SelectedMods => base.SelectedMods; + + public TestPlayer() + : base(false, false) + { + } + } + protected class SlowLoadPlayer : Player { public bool Ready; From 0603ed9ab755dc45c0d25822e4de2c5ec84c9721 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 9 Apr 2019 16:27:10 +0900 Subject: [PATCH 0537/5608] Fix post-merge errors --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs | 1 + osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index ecdafb0fa2..27546fa424 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Configuration; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index c0d9ecad3a..e70bf4c572 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Containers; From 4310f07a5cbba63eba921db02ed3e4ff9ce9498d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Apr 2019 12:03:57 +0900 Subject: [PATCH 0538/5608] Rename SelectedMods -> Mods --- .../TestCaseAutoJuiceStream.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs | 3 +-- .../TestCaseHitCircleHidden.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs | 3 +-- .../TestCaseSliderHidden.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs | 3 +-- .../TestCaseSpinnerHidden.cs | 2 +- .../Background/TestCaseBackgroundScreenBeatmap.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs | 2 +- .../Visual/SongSelect/TestCasePlaySongSelect.cs | 8 ++++---- osu.Game/OsuGame.cs | 4 ++-- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 6 +++--- osu.Game/Overlays/MusicController.cs | 6 +++--- osu.Game/Rulesets/UI/Playfield.cs | 4 ++-- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 4 ++-- osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs | 2 +- osu.Game/Screens/OsuScreen.cs | 4 ++-- osu.Game/Screens/OsuScreenDependencies.cs | 10 +++++----- osu.Game/Screens/Play/Player.cs | 14 +++++++------- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- osu.Game/Screens/Select/MatchSongSelect.cs | 8 ++++---- osu.Game/Screens/Select/PlaySongSelect.cs | 4 ++-- osu.Game/Screens/Select/SongSelect.cs | 10 +++++----- osu.Game/Tests/Visual/AllPlayersTestCase.cs | 2 +- osu.Game/Tests/Visual/OsuTestCase.cs | 2 +- osu.Game/Tests/Visual/PlayerTestCase.cs | 2 +- 26 files changed, 55 insertions(+), 58 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs index a696ba4e7e..0b20f34eb1 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.Tests protected override Player CreatePlayer(Ruleset ruleset) { - SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); + Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); return base.CreatePlayer(ruleset); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs index e1e854e8dc..31f3146046 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs @@ -30,7 +30,6 @@ namespace osu.Game.Rulesets.Osu.Tests protected override Container Content => content; private int depthIndex; - protected readonly List Mods = new List(); public TestCaseHitCircle() { @@ -68,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Tests Depth = depthIndex++ }; - foreach (var mod in Mods.OfType()) + foreach (var mod in Mods.Value.OfType()) mod.ApplyToDrawableHitObjects(new[] { drawable }); Add(drawable); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleHidden.cs index 26d9b5ae91..7391c0f11a 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleHidden.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Tests public TestCaseHitCircleHidden() { - Mods.Add(new OsuModHidden()); + Mods.Value = new[] { new OsuModHidden() }; } } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs index 35e8f3e17e..0f02050605 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs @@ -44,7 +44,6 @@ namespace osu.Game.Rulesets.Osu.Tests protected override Container Content => content; private int depthIndex; - protected readonly List Mods = new List(); public TestCaseSlider() { @@ -292,7 +291,7 @@ namespace osu.Game.Rulesets.Osu.Tests Depth = depthIndex++ }; - foreach (var mod in Mods.OfType()) + foreach (var mod in Mods.Value.OfType()) mod.ApplyToDrawableHitObjects(new[] { drawable }); drawable.OnNewResult += onNewResult; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderHidden.cs index ba5bd48c51..65a8005407 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderHidden.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Tests public TestCaseSliderHidden() { - Mods.Add(new OsuModHidden()); + Mods.Value = new[] { new OsuModHidden() }; } } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs index e8b534bba9..ab33d1e518 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs @@ -31,7 +31,6 @@ namespace osu.Game.Rulesets.Osu.Tests protected override Container Content => content; private int depthIndex; - protected readonly List Mods = new List(); public TestCaseSpinner() { @@ -57,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Tests Depth = depthIndex++ }; - foreach (var mod in Mods.OfType()) + foreach (var mod in Mods.Value.OfType()) mod.ApplyToDrawableHitObjects(new[] { drawable }); Add(drawable); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerHidden.cs index 6136ce1639..24e3bcb47b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerHidden.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Tests public TestCaseSpinnerHidden() { - Mods.Add(new OsuModHidden()); + Mods.Value = new[] { new OsuModHidden() }; } } } diff --git a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs index e3875421b1..283fd4c8b9 100644 --- a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs @@ -267,7 +267,7 @@ namespace osu.Game.Tests.Visual.Background AddUntilStep("Song select has selection", () => songSelect.Carousel.SelectedBeatmap != null); AddStep("Set default user settings", () => { - SelectedMods.Value = SelectedMods.Value.Concat(new[] { new OsuModNoFail() }); + Mods.Value = Mods.Value.Concat(new[] { new OsuModNoFail() }); songSelect.DimLevel.Value = 0.7f; songSelect.BlurLevel.Value = 0.4f; }); diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs index c930e77e9e..df48834e1f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Gameplay { protected override Player CreatePlayer(Ruleset ruleset) { - SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); + Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); return new ScoreAccessiblePlayer(); } diff --git a/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs index a70529b384..e89b361104 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs @@ -171,17 +171,17 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("change ruleset", () => { - SelectedMods.ValueChanged += onModChange; + Mods.ValueChanged += onModChange; songSelect.Ruleset.ValueChanged += onRulesetChange; Ruleset.Value = new TaikoRuleset().RulesetInfo; - SelectedMods.ValueChanged -= onModChange; + Mods.ValueChanged -= onModChange; songSelect.Ruleset.ValueChanged -= onRulesetChange; }); AddAssert("mods changed before ruleset", () => modChangeIndex < rulesetChangeIndex); - AddAssert("empty mods", () => !SelectedMods.Value.Any()); + AddAssert("empty mods", () => !Mods.Value.Any()); void onModChange(ValueChangedEvent> e) => modChangeIndex = actionIndex++; void onRulesetChange(ValueChangedEvent e) => rulesetChangeIndex = actionIndex--; @@ -214,7 +214,7 @@ namespace osu.Game.Tests.Visual.SongSelect private static int importId; private int getImportId() => ++importId; - private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => SelectedMods.Value = mods); + private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => Mods.Value = mods); private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id)); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 4d889677a5..0785c588e5 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -113,7 +113,7 @@ namespace osu.Game // todo: move this to SongSelect once Screen has the ability to unsuspend. [Cached] [Cached(Type = typeof(IBindable>))] - private readonly Bindable> selectedMods = new Bindable>(Enumerable.Empty()); + private readonly Bindable> mods = new Bindable>(Enumerable.Empty()); public OsuGame(string[] args = null) { @@ -294,7 +294,7 @@ namespace osu.Game { ruleset.Value = databasedScoreInfo.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); - selectedMods.Value = databasedScoreInfo.Mods; + mods.Value = databasedScoreInfo.Mods; menuScreen.Push(new PlayerLoader(() => new ReplayPlayer(databasedScore))); }, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index aa41723ca6..9e97f4551a 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -42,19 +42,19 @@ namespace osu.Game.Overlays.Mods protected readonly FillFlowContainer ModSectionsContainer; - protected readonly Bindable> SelectedMods = new Bindable>(new Mod[] { }); + protected readonly Bindable> SelectedMods = new Bindable>(Enumerable.Empty()); protected readonly IBindable Ruleset = new Bindable(); [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, IBindable ruleset, AudioManager audio, Bindable> selectedMods) + private void load(OsuColour colours, IBindable ruleset, AudioManager audio, Bindable> mods) { LowMultiplierColour = colours.Red; HighMultiplierColour = colours.Green; UnrankedLabel.Colour = colours.Blue; Ruleset.BindTo(ruleset); - if (selectedMods != null) SelectedMods.BindTo(selectedMods); + if (mods != null) SelectedMods.BindTo(mods); sampleOn = audio.Sample.Get(@"UI/check-on"); sampleOff = audio.Sample.Get(@"UI/check-off"); diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 0ad4da2ce9..d9b669f753 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays private Bindable beatmap { get; set; } [Resolved] - private IBindable> selectedMods { get; set; } + private IBindable> mods { get; set; } /// /// Provide a source for the toolbar height. @@ -235,7 +235,7 @@ namespace osu.Game.Overlays { beatmap.BindValueChanged(beatmapChanged, true); beatmap.BindDisabledChanged(beatmapDisabledChanged, true); - selectedMods.BindValueChanged(_ => updateAudioAdjustments(), true); + mods.BindValueChanged(_ => updateAudioAdjustments(), true); base.LoadComplete(); } @@ -372,7 +372,7 @@ namespace osu.Game.Overlays track.ResetSpeedAdjustments(); - foreach (var mod in selectedMods.Value.OfType()) + foreach (var mod in mods.Value.OfType()) mod.ApplyToClock(track); } diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 6ea565af44..c9a05dae2c 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.UI private IBindable beatmap { get; set; } [Resolved] - private IBindable> selectedMods { get; set; } + private IBindable> mods { get; set; } [BackgroundDependencyLoader] private void load() @@ -125,7 +125,7 @@ namespace osu.Game.Rulesets.UI base.Update(); if (beatmap != null) - foreach (var mod in selectedMods.Value) + foreach (var mod in mods.Value) if (mod is IUpdatableByPlayfield updatable) updatable.Update(this); } diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 5f29044c76..aad571cf87 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -179,7 +179,7 @@ namespace osu.Game.Screens.Multi.Match { RoomManager?.PartRoom(); - SelectedMods.Value = Enumerable.Empty(); + Mods.Value = Enumerable.Empty(); return base.OnExiting(next); } @@ -193,7 +193,7 @@ namespace osu.Game.Screens.Multi.Match var localBeatmap = e.NewValue?.Beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == e.NewValue.Beatmap.OnlineBeatmapID); Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); - SelectedMods.Value = e.NewValue?.RequiredMods ?? Enumerable.Empty(); + Mods.Value = e.NewValue?.RequiredMods ?? Enumerable.Empty(); if (e.NewValue?.Ruleset != null) Ruleset.Value = e.NewValue.Ruleset; } diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index 8ce68ac593..9692dc513d 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Multi.Play if (ruleset.Value.ID != playlistItem.Ruleset.ID) throw new InvalidOperationException("Current Ruleset does not match PlaylistItem's Ruleset"); - if (!playlistItem.RequiredMods.All(m => SelectedMods.Value.Contains(m))) + if (!playlistItem.RequiredMods.All(m => Mods.Value.Contains(m))) throw new InvalidOperationException("Current Mods do not match PlaylistItem's RequiredMods"); var req = new CreateRoomScoreRequest(roomId.Value ?? 0, playlistItem.ID); diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index bd7f326b50..d1e700cf92 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -65,7 +65,7 @@ namespace osu.Game.Screens public Bindable Ruleset { get; private set; } - public Bindable> SelectedMods { get; private set; } + public Bindable> Mods { get; private set; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { @@ -73,7 +73,7 @@ namespace osu.Game.Screens Beatmap = screenDependencies.Beatmap; Ruleset = screenDependencies.Ruleset; - SelectedMods = screenDependencies.SelectedMods; + Mods = screenDependencies.Mods; return base.CreateChildDependencies(screenDependencies); } diff --git a/osu.Game/Screens/OsuScreenDependencies.cs b/osu.Game/Screens/OsuScreenDependencies.cs index 9cc415f581..d7e1862c05 100644 --- a/osu.Game/Screens/OsuScreenDependencies.cs +++ b/osu.Game/Screens/OsuScreenDependencies.cs @@ -16,7 +16,7 @@ namespace osu.Game.Screens public Bindable Ruleset { get; } - public Bindable> SelectedMods { get; } + public Bindable> Mods { get; } public OsuScreenDependencies(bool requireLease, IReadOnlyDependencyContainer parent) : base(parent) @@ -31,15 +31,15 @@ namespace osu.Game.Screens if (Ruleset == null) Cache(Ruleset = parent.Get>().BeginLease(true)); - SelectedMods = parent.Get>>()?.GetBoundCopy(); - if (SelectedMods == null) - Cache(SelectedMods = parent.Get>>().BeginLease(true)); + Mods = parent.Get>>()?.GetBoundCopy(); + if (Mods == null) + Cache(Mods = parent.Get>>().BeginLease(true)); } else { Beatmap = (parent.Get>() ?? parent.Get>()).GetBoundCopy(); Ruleset = (parent.Get>() ?? parent.Get>()).GetBoundCopy(); - SelectedMods = (parent.Get>>() ?? parent.Get>>()).GetBoundCopy(); + Mods = (parent.Get>>() ?? parent.Get>>()).GetBoundCopy(); } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index bf2bbc58b8..5add641404 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Play if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); - InternalChild = GameplayClockContainer = new GameplayClockContainer(working, SelectedMods.Value, DrawableRuleset.GameplayStartTime); + InternalChild = GameplayClockContainer = new GameplayClockContainer(working, Mods.Value, DrawableRuleset.GameplayStartTime); GameplayClockContainer.Children = new[] { @@ -123,7 +123,7 @@ namespace osu.Game.Screens.Play }, // display the cursor above some HUD elements. DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), - HUDOverlay = new HUDOverlay(ScoreProcessor, DrawableRuleset, SelectedMods.Value) + HUDOverlay = new HUDOverlay(ScoreProcessor, DrawableRuleset, Mods.Value) { HoldToQuit = { Action = performUserRequestedExit }, PlayerSettingsOverlay = { PlaybackSettings = { UserPlaybackRate = { BindTarget = GameplayClockContainer.UserPlaybackRate } } }, @@ -170,7 +170,7 @@ namespace osu.Game.Screens.Play ScoreProcessor.AllJudged += onCompletion; ScoreProcessor.Failed += onFail; - foreach (var mod in SelectedMods.Value.OfType()) + foreach (var mod in Mods.Value.OfType()) mod.ApplyToScoreProcessor(ScoreProcessor); } @@ -192,7 +192,7 @@ namespace osu.Game.Screens.Play try { - DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(working, SelectedMods.Value); + DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(working, Mods.Value); } catch (BeatmapInvalidForRulesetException) { @@ -200,7 +200,7 @@ namespace osu.Game.Screens.Play // let's try again forcing the beatmap's ruleset. ruleset = beatmap.BeatmapInfo.Ruleset; rulesetInstance = ruleset.CreateInstance(); - DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(Beatmap.Value, SelectedMods.Value); + DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(Beatmap.Value, Mods.Value); } if (!DrawableRuleset.Objects.Any()) @@ -271,7 +271,7 @@ namespace osu.Game.Screens.Play { Beatmap = Beatmap.Value.BeatmapInfo, Ruleset = ruleset, - Mods = SelectedMods.Value.ToArray(), + Mods = Mods.Value.ToArray(), User = api.LocalUser.Value, }; @@ -325,7 +325,7 @@ namespace osu.Game.Screens.Play private bool onFail() { - if (SelectedMods.Value.OfType().Any(m => !m.AllowFail)) + if (Mods.Value.OfType().Any(m => !m.AllowFail)) return false; GameplayClockContainer.Stop(); diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 70f5736786..2096f3f0f8 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -68,7 +68,7 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - info = new BeatmapMetadataDisplay(Beatmap.Value, SelectedMods.Value) + info = new BeatmapMetadataDisplay(Beatmap.Value, Mods.Value) { Alpha = 0, Anchor = Anchor.Centre, diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 1011f6f32d..4468f5704f 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Select RulesetID = Ruleset.Value.ID ?? 0 }; - item.RequiredMods.AddRange(SelectedMods.Value); + item.RequiredMods.AddRange(Mods.Value); Selected?.Invoke(item); @@ -61,12 +61,12 @@ namespace osu.Game.Screens.Select { Ruleset.Value = CurrentItem.Value.Ruleset; Beatmap.Value = beatmaps.GetWorkingBeatmap(CurrentItem.Value.Beatmap); - SelectedMods.Value = CurrentItem.Value.RequiredMods ?? Enumerable.Empty(); + Mods.Value = CurrentItem.Value.RequiredMods ?? Enumerable.Empty(); } Beatmap.Disabled = true; Ruleset.Disabled = true; - SelectedMods.Disabled = true; + Mods.Disabled = true; return false; } @@ -77,7 +77,7 @@ namespace osu.Game.Screens.Select Beatmap.Disabled = false; Ruleset.Disabled = false; - SelectedMods.Disabled = false; + Mods.Disabled = false; } } } diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 340ceb6864..44e38edda8 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -52,10 +52,10 @@ namespace osu.Game.Screens.Select var auto = Ruleset.Value.CreateInstance().GetAutoplayMod(); var autoType = auto.GetType(); - var mods = SelectedMods.Value; + var mods = Mods.Value; if (mods.All(m => m.GetType() != autoType)) { - SelectedMods.Value = mods.Append(auto); + Mods.Value = mods.Append(auto); removeAutoModOnResume = true; } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 2bb646750c..6ad5b54e65 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -85,7 +85,7 @@ namespace osu.Game.Screens.Select [Cached] [Cached(Type = typeof(IBindable>))] - private readonly Bindable> selectedMods = new Bindable>(Enumerable.Empty()); // Bound to the game's mods, but is not reset on exiting + private readonly Bindable> mods = new Bindable>(Enumerable.Empty()); // Bound to the game's mods, but is not reset on exiting protected SongSelect() { @@ -219,7 +219,7 @@ namespace osu.Game.Screens.Select [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins) { - selectedMods.BindTo(SelectedMods); + mods.BindTo(Mods); if (Footer != null) { @@ -394,7 +394,7 @@ namespace osu.Game.Screens.Select { Logger.Log($"ruleset changed from \"{decoupledRuleset.Value}\" to \"{ruleset}\""); - selectedMods.Value = Enumerable.Empty(); + mods.Value = Enumerable.Empty(); decoupledRuleset.Value = ruleset; // force a filter before attempting to change the beatmap. @@ -529,8 +529,8 @@ namespace osu.Game.Screens.Select if (Beatmap.Value.Track != null) Beatmap.Value.Track.Looping = false; - selectedMods.UnbindAll(); - SelectedMods.Value = Enumerable.Empty(); + mods.UnbindAll(); + Mods.Value = Enumerable.Empty(); return false; } diff --git a/osu.Game/Tests/Visual/AllPlayersTestCase.cs b/osu.Game/Tests/Visual/AllPlayersTestCase.cs index 21955da6e9..af190ec7d5 100644 --- a/osu.Game/Tests/Visual/AllPlayersTestCase.cs +++ b/osu.Game/Tests/Visual/AllPlayersTestCase.cs @@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual var working = CreateWorkingBeatmap(beatmap, Clock); Beatmap.Value = working; - SelectedMods.Value = new[] { r.GetAllMods().First(m => m is ModNoFail) }; + Mods.Value = new[] { r.GetAllMods().First(m => m is ModNoFail) }; Player?.Exit(); Player = null; diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index 1a8403db40..8ec440db8b 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual [Cached] [Cached(Type = typeof(IBindable>))] - protected readonly Bindable> SelectedMods = new Bindable>(Enumerable.Empty()); + protected readonly Bindable> Mods = new Bindable>(Enumerable.Empty()); protected DependencyContainer Dependencies { get; private set; } diff --git a/osu.Game/Tests/Visual/PlayerTestCase.cs b/osu.Game/Tests/Visual/PlayerTestCase.cs index 409e79b4a5..719b1d6892 100644 --- a/osu.Game/Tests/Visual/PlayerTestCase.cs +++ b/osu.Game/Tests/Visual/PlayerTestCase.cs @@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual Beatmap.Value = new TestWorkingBeatmap(beatmap, Clock); if (!AllowFail) - SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModNoFail) }; + Mods.Value = new[] { ruleset.GetAllMods().First(m => m is ModNoFail) }; Player = CreatePlayer(ruleset); LoadScreen(Player); From 7845d542e3b63d86c2c9364c14021bbd9c96a239 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Apr 2019 17:11:17 +0900 Subject: [PATCH 0539/5608] Cache mods as array in DrawableRuleset --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 11 +++++------ osu.Game/Rulesets/UI/Playfield.cs | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 0ab07de1ac..654f330a08 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -81,9 +81,8 @@ namespace osu.Game.Rulesets.UI /// /// The mods which are to be applied. /// - [Cached] - [Cached(typeof(IBindable>))] - private readonly Bindable> mods = new Bindable>(); + [Cached(typeof(IReadOnlyList))] + private readonly IReadOnlyList mods; private FrameStabilityContainer frameStabilityContainer; @@ -100,7 +99,7 @@ namespace osu.Game.Rulesets.UI if (workingBeatmap == null) throw new ArgumentException("Beatmap cannot be null.", nameof(workingBeatmap)); - this.mods.Value = mods; + this.mods = mods.ToArray(); RelativeSizeAxes = Axes.Both; @@ -160,7 +159,7 @@ namespace osu.Game.Rulesets.UI .WithChild(ResumeOverlay))); } - applyRulesetMods(mods.Value, config); + applyRulesetMods(mods, config); loadObjects(); } @@ -175,7 +174,7 @@ namespace osu.Game.Rulesets.UI Playfield.PostProcess(); - foreach (var mod in mods.Value.OfType()) + foreach (var mod in mods.OfType()) mod.ApplyToDrawableHitObjects(Playfield.HitObjectContainer.Objects); } diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index c9a05dae2c..13689153f0 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.UI private IBindable beatmap { get; set; } [Resolved] - private IBindable> mods { get; set; } + private IReadOnlyList mods { get; set; } [BackgroundDependencyLoader] private void load() @@ -125,7 +125,7 @@ namespace osu.Game.Rulesets.UI base.Update(); if (beatmap != null) - foreach (var mod in mods.Value) + foreach (var mod in mods) if (mod is IUpdatableByPlayfield updatable) updatable.Update(this); } From 0222424aef8cf51e5f201633938880d8d756f25f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Apr 2019 17:13:12 +0900 Subject: [PATCH 0540/5608] Make mods IReadOnlyList gamewide Prevents potential multiple evaluations of enumerable. --- osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs | 2 +- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs | 2 +- osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs | 2 +- osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs | 2 +- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 2 +- osu.Game.Rulesets.Osu.Tests/StackingTest.cs | 3 ++- osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs | 2 +- osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs | 2 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs | 2 +- osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs | 3 +-- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs | 2 +- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 3 ++- .../Visual/Background/TestCaseBackgroundScreenBeatmap.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs | 3 ++- .../Visual/SongSelect/TestCasePlaySongSelect.cs | 2 +- osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs | 2 +- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- osu.Game/OsuGame.cs | 4 ++-- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 8 ++++---- osu.Game/Overlays/MusicController.cs | 2 +- osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs | 2 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 4 ++-- osu.Game/Rulesets/Ruleset.cs | 2 +- osu.Game/Rulesets/UI/DrawableRuleset.cs | 6 +++--- .../Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs | 2 +- osu.Game/Screens/Multi/Match/Components/Header.cs | 3 +-- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 6 +++--- osu.Game/Screens/OsuScreen.cs | 2 +- osu.Game/Screens/OsuScreenDependencies.cs | 8 ++++---- osu.Game/Screens/Play/GameplayClockContainer.cs | 4 ++-- osu.Game/Screens/Play/HUD/ModDisplay.cs | 6 +++--- osu.Game/Screens/Play/HUDOverlay.cs | 2 +- osu.Game/Screens/Play/PlayerLoader.cs | 4 ++-- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 4 ++-- osu.Game/Screens/Select/MatchSongSelect.cs | 3 +-- osu.Game/Screens/Select/PlaySongSelect.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 8 ++++---- osu.Game/Tests/Visual/OsuTestCase.cs | 4 ++-- 44 files changed, 68 insertions(+), 68 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs index 0b20f34eb1..102afa9ca6 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.Tests protected override Player CreatePlayer(Ruleset ruleset) { - Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); + Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); return base.CreatePlayer(ruleset); } } diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 544694fc8f..404766051f 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch { public class CatchRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IEnumerable mods) => new DrawableCatchRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableCatchRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index 4b75b54d41..0324ba1d0b 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.UI protected override bool UserScrollSpeedAdjustment => false; - public DrawableCatchRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + public DrawableCatchRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { Direction.Value = ScrollingDirection.Down; diff --git a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs index 0bfbf38832..e5f379f608 100644 --- a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs +++ b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Edit { public new IScrollingInfo ScrollingInfo => base.ScrollingInfo; - public DrawableManiaEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + public DrawableManiaEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index ebc94c86e2..5a8af60aab 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.Edit public int TotalColumns => ((ManiaPlayfield)DrawableRuleset.Playfield).TotalColumns; - protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) { DrawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap, mods); diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 02a9b5ed30..36381294f5 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Mania { public class ManiaRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IEnumerable mods) => new DrawableManiaRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableManiaRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score); diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 9d10657680..f592023300 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly Bindable configDirection = new Bindable(); - public DrawableManiaRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + public DrawableManiaRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { // Generate the bar lines diff --git a/osu.Game.Rulesets.Osu.Tests/StackingTest.cs b/osu.Game.Rulesets.Osu.Tests/StackingTest.cs index 13c9985f47..e8b99e86f9 100644 --- a/osu.Game.Rulesets.Osu.Tests/StackingTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/StackingTest.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.IO; using System.Linq; using System.Text; @@ -23,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Tests using (var reader = new StreamReader(stream)) { var beatmap = Decoder.GetDecoder(reader).Decode(reader); - var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Enumerable.Empty()); + var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Array.Empty()); var objects = converted.HitObjects.ToList(); diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs index 0c3050bfb4..bcb6099cfb 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Edit { public class DrawableOsuEditRuleset : DrawableOsuRuleset { - public DrawableOsuEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + public DrawableOsuEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 9c4b6ee7aa..12e15be9b9 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Edit { } - protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableOsuEditRuleset(ruleset, beatmap, mods); protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 115271da85..40155cf8a9 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu { public class OsuRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IEnumerable mods) => new DrawableOsuRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableOsuRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index c2954e1b3b..ba7241c165 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.UI { protected new OsuRulesetConfigManager Config => (OsuRulesetConfigManager)base.Config; - public DrawableOsuRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + public DrawableOsuRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs index c42faea9f9..9ceb1a9846 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -88,7 +87,7 @@ namespace osu.Game.Rulesets.Taiko.Tests Origin = Anchor.Centre, RelativeSizeAxes = Axes.X, Height = 768, - Children = new[] { drawableRuleset = new DrawableTaikoRuleset(new TaikoRuleset(), beatmap, Enumerable.Empty()) } + Children = new[] { drawableRuleset = new DrawableTaikoRuleset(new TaikoRuleset(), beatmap, Array.Empty()) } }); } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index cb53ec890b..f90894ff5d 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Taiko { public class TaikoRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IEnumerable mods) => new DrawableTaikoRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableTaikoRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index 76bdd37ed3..adff869d26 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Taiko.UI protected override bool UserScrollSpeedAdjustment => false; - public DrawableTaikoRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + public DrawableTaikoRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { Direction.Value = ScrollingDirection.Left; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index e181130774..6738e0e7c2 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.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.IO; using NUnit.Framework; using osuTK; @@ -40,7 +41,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(6, working.BeatmapInfo.BeatmapVersion); Assert.AreEqual(6, working.Beatmap.BeatmapInfo.BeatmapVersion); - Assert.AreEqual(6, working.GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Enumerable.Empty()).BeatmapInfo.BeatmapVersion); + Assert.AreEqual(6, working.GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Array.Empty()).BeatmapInfo.BeatmapVersion); } } diff --git a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs index 283fd4c8b9..81fab5b4b3 100644 --- a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs @@ -267,7 +267,7 @@ namespace osu.Game.Tests.Visual.Background AddUntilStep("Song select has selection", () => songSelect.Carousel.SelectedBeatmap != null); AddStep("Set default user settings", () => { - Mods.Value = Mods.Value.Concat(new[] { new OsuModNoFail() }); + Mods.Value = Mods.Value.Concat(new[] { new OsuModNoFail() }).ToArray(); songSelect.DimLevel.Value = 0.7f; songSelect.BlurLevel.Value = 0.4f; }); diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs index df48834e1f..624e5f08bd 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Gameplay { protected override Player CreatePlayer(Ruleset ruleset) { - Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); + Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); return new ScoreAccessiblePlayer(); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs index 2a72dc8242..263070ab21 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.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 System.Linq; using osu.Game.Rulesets; @@ -16,7 +17,7 @@ namespace osu.Game.Tests.Visual.Gameplay { protected override Player CreatePlayer(Ruleset ruleset) { - var beatmap = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Enumerable.Empty()); + var beatmap = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Array.Empty()); return new ScoreAccessibleReplayPlayer(ruleset.GetAutoplayMod().CreateReplayScore(beatmap)); } diff --git a/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs index e89b361104..7e33f6ce02 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs @@ -183,7 +183,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("mods changed before ruleset", () => modChangeIndex < rulesetChangeIndex); AddAssert("empty mods", () => !Mods.Value.Any()); - void onModChange(ValueChangedEvent> e) => modChangeIndex = actionIndex++; + void onModChange(ValueChangedEvent> e) => modChangeIndex = actionIndex++; void onRulesetChange(ValueChangedEvent e) => rulesetChangeIndex = actionIndex--; } diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs index aab44f7d92..fd003c7ea2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs @@ -253,7 +253,7 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestModSelectOverlay : ModSelectOverlay { - public new Bindable> SelectedMods => base.SelectedMods; + public new Bindable> SelectedMods => base.SelectedMods; public ModButton GetModButton(Mod mod) { diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 3e6033da9c..58463d2219 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -52,7 +52,7 @@ namespace osu.Game.Beatmaps { public override IEnumerable GetModsFor(ModType type) => new Mod[] { }; - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IEnumerable mods) + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods) { throw new NotImplementedException(); } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index ec0a76b52b..8989785dcd 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -75,7 +75,7 @@ namespace osu.Game.Beatmaps /// The to create a playable for. /// The converted . /// If could not be converted to . - public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IEnumerable mods) + public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods) { var rulesetInstance = ruleset.CreateInstance(); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 0785c588e5..30f98aa1ce 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -112,8 +112,8 @@ namespace osu.Game // todo: move this to SongSelect once Screen has the ability to unsuspend. [Cached] - [Cached(Type = typeof(IBindable>))] - private readonly Bindable> mods = new Bindable>(Enumerable.Empty()); + [Cached(typeof(IBindable>))] + private readonly Bindable> mods = new Bindable>(Array.Empty()); public OsuGame(string[] args = null) { diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 9e97f4551a..97769fe5aa 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -42,12 +42,12 @@ namespace osu.Game.Overlays.Mods protected readonly FillFlowContainer ModSectionsContainer; - protected readonly Bindable> SelectedMods = new Bindable>(Enumerable.Empty()); + protected readonly Bindable> SelectedMods = new Bindable>(Array.Empty()); protected readonly IBindable Ruleset = new Bindable(); [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, IBindable ruleset, AudioManager audio, Bindable> mods) + private void load(OsuColour colours, IBindable ruleset, AudioManager audio, Bindable> mods) { LowMultiplierColour = colours.Red; HighMultiplierColour = colours.Green; @@ -87,14 +87,14 @@ namespace osu.Game.Overlays.Mods // attempt to re-select any already selected mods. // this may be the first time we are receiving the ruleset, in which case they will still match. - selectedModsChanged(new ValueChangedEvent>(SelectedMods.Value, SelectedMods.Value)); + selectedModsChanged(new ValueChangedEvent>(SelectedMods.Value, SelectedMods.Value)); // write the mods back to the SelectedMods bindable in the case a change was not applicable. // this generally isn't required as the previous line will perform deselection; just here for safety. refreshSelectedMods(); } - private void selectedModsChanged(ValueChangedEvent> e) + private void selectedModsChanged(ValueChangedEvent> e) { foreach (ModSection section in ModSectionsContainer.Children) section.SelectTypes(e.NewValue.Select(m => m.GetType()).ToList()); diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index d9b669f753..c250d3b62a 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays private Bindable beatmap { get; set; } [Resolved] - private IBindable> mods { get; set; } + private IBindable> mods { get; set; } /// /// Provide a source for the toolbar height. diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index e181051737..14f7665e05 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Difficulty /// public Mod[] CreateDifficultyAdjustmentModCombinations() { - return createDifficultyAdjustmentModCombinations(Enumerable.Empty(), DifficultyAdjustmentMods).ToArray(); + return createDifficultyAdjustmentModCombinations(Array.Empty(), DifficultyAdjustmentMods).ToArray(); IEnumerable createDifficultyAdjustmentModCombinations(IEnumerable currentSet, Mod[] adjustmentSet, int currentSetCount = 0, int adjustmentSetStart = 0) { diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 5219cb9581..38ec09535d 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -186,8 +186,8 @@ namespace osu.Game.Rulesets.Edit } internal override DrawableEditRuleset CreateDrawableRuleset() - => new DrawableEditRuleset(CreateDrawableRuleset(Ruleset, Beatmap.Value, Enumerable.Empty())); + => new DrawableEditRuleset(CreateDrawableRuleset(Ruleset, Beatmap.Value, Array.Empty())); - protected abstract DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods); + protected abstract DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods); } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 90fe25accf..3521c17b23 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets /// The beatmap to create the hit renderer for. /// Unable to successfully load the beatmap to be usable with this ruleset. /// - public abstract DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IEnumerable mods); + public abstract DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods); /// /// Creates a to convert a to one that is applicable for this . diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 654f330a08..2866e81682 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.UI /// /// The ruleset being represented. /// The beatmap to create the hit renderer for. - protected DrawableRuleset(Ruleset ruleset, WorkingBeatmap workingBeatmap, IEnumerable mods) + protected DrawableRuleset(Ruleset ruleset, WorkingBeatmap workingBeatmap, IReadOnlyList mods) : base(ruleset) { if (workingBeatmap == null) @@ -257,7 +257,7 @@ namespace osu.Game.Rulesets.UI /// Applies the active mods to the Beatmap. /// /// - private void applyBeatmapMods(IEnumerable mods) + private void applyBeatmapMods(IReadOnlyList mods) { if (mods == null) return; @@ -270,7 +270,7 @@ namespace osu.Game.Rulesets.UI /// Applies the active mods to this DrawableRuleset. /// /// - private void applyRulesetMods(IEnumerable mods, OsuConfigManager config) + private void applyRulesetMods(IReadOnlyList mods, OsuConfigManager config) { if (mods == null) return; diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 2bb98dd679..dbe8d8c299 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.UI.Scrolling [Cached(Type = typeof(IScrollingInfo))] private readonly LocalScrollingInfo scrollingInfo; - protected DrawableScrollingRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IEnumerable mods) + protected DrawableScrollingRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { scrollingInfo = new LocalScrollingInfo(); diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index e1592532a3..2a6074882d 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -110,7 +109,7 @@ namespace osu.Game.Screens.Multi.Match.Components }, }; - CurrentItem.BindValueChanged(item => modDisplay.Current.Value = item.NewValue?.RequiredMods ?? Enumerable.Empty(), true); + CurrentItem.BindValueChanged(item => modDisplay.Current.Value = item.NewValue?.RequiredMods?.ToArray() ?? Array.Empty(), true); beatmapButton.Action = () => RequestBeatmapSelection?.Invoke(); } diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index aad571cf87..6271693a6a 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; +using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -179,7 +179,7 @@ namespace osu.Game.Screens.Multi.Match { RoomManager?.PartRoom(); - Mods.Value = Enumerable.Empty(); + Mods.Value = Array.Empty(); return base.OnExiting(next); } @@ -193,7 +193,7 @@ namespace osu.Game.Screens.Multi.Match var localBeatmap = e.NewValue?.Beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == e.NewValue.Beatmap.OnlineBeatmapID); Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); - Mods.Value = e.NewValue?.RequiredMods ?? Enumerable.Empty(); + Mods.Value = e.NewValue?.RequiredMods?.ToArray() ?? Array.Empty(); if (e.NewValue?.Ruleset != null) Ruleset.Value = e.NewValue.Ruleset; } diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index d1e700cf92..c1a822c75c 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -65,7 +65,7 @@ namespace osu.Game.Screens public Bindable Ruleset { get; private set; } - public Bindable> Mods { get; private set; } + public Bindable> Mods { get; private set; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { diff --git a/osu.Game/Screens/OsuScreenDependencies.cs b/osu.Game/Screens/OsuScreenDependencies.cs index d7e1862c05..4167faba83 100644 --- a/osu.Game/Screens/OsuScreenDependencies.cs +++ b/osu.Game/Screens/OsuScreenDependencies.cs @@ -16,7 +16,7 @@ namespace osu.Game.Screens public Bindable Ruleset { get; } - public Bindable> Mods { get; } + public Bindable> Mods { get; } public OsuScreenDependencies(bool requireLease, IReadOnlyDependencyContainer parent) : base(parent) @@ -31,15 +31,15 @@ namespace osu.Game.Screens if (Ruleset == null) Cache(Ruleset = parent.Get>().BeginLease(true)); - Mods = parent.Get>>()?.GetBoundCopy(); + Mods = parent.Get>>()?.GetBoundCopy(); if (Mods == null) - Cache(Mods = parent.Get>>().BeginLease(true)); + Cache(Mods = parent.Get>>().BeginLease(true)); } else { Beatmap = (parent.Get>() ?? parent.Get>()).GetBoundCopy(); Ruleset = (parent.Get>() ?? parent.Get>()).GetBoundCopy(); - Mods = (parent.Get>>() ?? parent.Get>>()).GetBoundCopy(); + Mods = (parent.Get>>() ?? parent.Get>>()).GetBoundCopy(); } } } diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 2b18ef5ecd..29974b728e 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Play public class GameplayClockContainer : Container { private readonly WorkingBeatmap beatmap; - private readonly IEnumerable mods; + private readonly IReadOnlyList mods; /// /// The original source (usually a 's track). @@ -60,7 +60,7 @@ namespace osu.Game.Screens.Play private readonly FramedOffsetClock platformOffsetClock; - public GameplayClockContainer(WorkingBeatmap beatmap, IEnumerable mods, double gameplayStartTime) + public GameplayClockContainer(WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime) { this.beatmap = beatmap; this.mods = mods; diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index 2c1293833f..878d2b7c38 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -18,15 +18,15 @@ using osu.Game.Graphics; namespace osu.Game.Screens.Play.HUD { - public class ModDisplay : Container, IHasCurrentValue> + public class ModDisplay : Container, IHasCurrentValue> { private const int fade_duration = 1000; public bool DisplayUnrankedText = true; - private readonly Bindable> current = new Bindable>(); + private readonly Bindable> current = new Bindable>(); - public Bindable> Current + public Bindable> Current { get => current; set diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index aa4375f652..3c1b33297a 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Play public Action RequestSeek; - public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, IEnumerable mods) + public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, IReadOnlyList mods) { RelativeSizeAxes = Axes.Both; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 2096f3f0f8..1c558eae2e 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -301,7 +301,7 @@ namespace osu.Game.Screens.Play } private readonly WorkingBeatmap beatmap; - private readonly IEnumerable mods; + private readonly IReadOnlyList mods; private LoadingAnimation loading; private Sprite backgroundSprite; private ModDisplay modDisplay; @@ -323,7 +323,7 @@ namespace osu.Game.Screens.Play } } - public BeatmapMetadataDisplay(WorkingBeatmap beatmap, IEnumerable mods) + public BeatmapMetadataDisplay(WorkingBeatmap beatmap, IReadOnlyList mods) { this.beatmap = beatmap; this.mods = mods; diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 03cf767062..51f87dcc6d 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -310,12 +310,12 @@ namespace osu.Game.Screens.Select try { // Try to get the beatmap with the user's ruleset - playableBeatmap = beatmap.GetPlayableBeatmap(ruleset, Enumerable.Empty()); + playableBeatmap = beatmap.GetPlayableBeatmap(ruleset, Array.Empty()); } catch (BeatmapInvalidForRulesetException) { // Can't be converted to the user's ruleset, so use the beatmap's own ruleset - playableBeatmap = beatmap.GetPlayableBeatmap(beatmap.BeatmapInfo.Ruleset, Enumerable.Empty()); + playableBeatmap = beatmap.GetPlayableBeatmap(beatmap.BeatmapInfo.Ruleset, Array.Empty()); } labels.AddRange(playableBeatmap.GetStatistics().Select(s => new InfoLabel(s))); diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 4468f5704f..c5fa9e2396 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using Humanizer; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -61,7 +60,7 @@ namespace osu.Game.Screens.Select { Ruleset.Value = CurrentItem.Value.Ruleset; Beatmap.Value = beatmaps.GetWorkingBeatmap(CurrentItem.Value.Beatmap); - Mods.Value = CurrentItem.Value.RequiredMods ?? Enumerable.Empty(); + Mods.Value = CurrentItem.Value.RequiredMods?.ToArray() ?? Array.Empty(); } Beatmap.Disabled = true; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 44e38edda8..bf4f898323 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Select var mods = Mods.Value; if (mods.All(m => m.GetType() != autoType)) { - Mods.Value = mods.Append(auto); + Mods.Value = mods.Append(auto).ToArray(); removeAutoModOnResume = true; } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 6ad5b54e65..a78238c584 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -84,8 +84,8 @@ namespace osu.Game.Screens.Select private readonly Bindable decoupledRuleset = new Bindable(); [Cached] - [Cached(Type = typeof(IBindable>))] - private readonly Bindable> mods = new Bindable>(Enumerable.Empty()); // Bound to the game's mods, but is not reset on exiting + [Cached(Type = typeof(IBindable>))] + private readonly Bindable> mods = new Bindable>(Array.Empty()); // Bound to the game's mods, but is not reset on exiting protected SongSelect() { @@ -394,7 +394,7 @@ namespace osu.Game.Screens.Select { Logger.Log($"ruleset changed from \"{decoupledRuleset.Value}\" to \"{ruleset}\""); - mods.Value = Enumerable.Empty(); + mods.Value = Array.Empty(); decoupledRuleset.Value = ruleset; // force a filter before attempting to change the beatmap. @@ -530,7 +530,7 @@ namespace osu.Game.Screens.Select Beatmap.Value.Track.Looping = false; mods.UnbindAll(); - Mods.Value = Enumerable.Empty(); + Mods.Value = Array.Empty(); return false; } diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index 8ec440db8b..c08a6a4bcb 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -28,8 +28,8 @@ namespace osu.Game.Tests.Visual protected readonly Bindable Ruleset = new Bindable(); [Cached] - [Cached(Type = typeof(IBindable>))] - protected readonly Bindable> Mods = new Bindable>(Enumerable.Empty()); + [Cached(Type = typeof(IBindable>))] + protected readonly Bindable> Mods = new Bindable>(Array.Empty()); protected DependencyContainer Dependencies { get; private set; } From 1db2d49696a8cc33b54968e6ec6ab3dbfe5ece70 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Apr 2019 17:54:57 +0900 Subject: [PATCH 0541/5608] Fix testcases --- .../ManiaPlacementBlueprintTestCase.cs | 6 ++++++ osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs | 4 ++++ osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs | 5 +++++ .../Visual/Gameplay/TestCaseScrollingHitObjects.cs | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs index 13bbe87513..9ad22498a9 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -8,6 +10,7 @@ using osu.Framework.Timing; using osu.Game.Rulesets.Mania.Edit; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Tests.Visual; @@ -21,6 +24,9 @@ namespace osu.Game.Rulesets.Mania.Tests { private readonly Column column; + [Cached(typeof(IReadOnlyList))] + private IReadOnlyList mods { get; set; } = Array.Empty(); + protected ManiaPlacementBlueprintTestCase() { Add(column = new Column(0) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index b14f999f61..d46b661eea 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -13,6 +13,7 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mania.UI.Components; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Tests.Visual; using osuTK; @@ -31,6 +32,9 @@ namespace osu.Game.Rulesets.Mania.Tests typeof(ColumnHitObjectArea) }; + [Cached(typeof(IReadOnlyList))] + private IReadOnlyList mods { get; set; } = Array.Empty(); + private readonly List columns = new List(); public TestCaseColumn() diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs index ac430037e4..9a7a3d1c5c 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; @@ -13,6 +14,7 @@ using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Tests.Visual; using osuTK; @@ -24,6 +26,9 @@ namespace osu.Game.Rulesets.Mania.Tests { private const int columns = 4; + [Cached(typeof(IReadOnlyList))] + private IReadOnlyList mods { get; set; } = Array.Empty(); + private readonly List stages = new List(); private FillFlowContainer fill; diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs index c99a4bb89b..3cfc5ac7c8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs @@ -4,11 +4,13 @@ using System; using System.Collections.Generic; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; @@ -23,6 +25,9 @@ namespace osu.Game.Tests.Visual.Gameplay { public override IReadOnlyList RequiredTypes => new[] { typeof(Playfield) }; + [Cached(typeof(IReadOnlyList))] + private IReadOnlyList mods { get; set; } = Array.Empty(); + private readonly ScrollingTestContainer[] scrollContainers = new ScrollingTestContainer[4]; private readonly TestPlayfield[] playfields = new TestPlayfield[4]; From 22f9339b01ff091b1e538050912c85377fbe38bf Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Wed, 10 Apr 2019 21:53:13 +0800 Subject: [PATCH 0542/5608] let mods button have selected mod icons --- osu.Game/Screens/Select/Footer.cs | 31 ++++++------- osu.Game/Screens/Select/FooterButton.cs | 16 ++++--- osu.Game/Screens/Select/FooterButtonMods.cs | 48 +++++++++++++++++++++ osu.Game/Screens/Select/SongSelect.cs | 6 +-- 4 files changed, 74 insertions(+), 27 deletions(-) create mode 100644 osu.Game/Screens/Select/FooterButtonMods.cs diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index 03b9826e9b..c991e5c350 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -20,9 +20,6 @@ namespace osu.Game.Screens.Select { private readonly Box modeLight; - private const float play_song_select_button_width = 100; - private const float play_song_select_button_height = 50; - public const float HEIGHT = 50; public const int TRANSITION_LENGTH = 300; @@ -33,6 +30,7 @@ namespace osu.Game.Screens.Select private readonly FillFlowContainer buttons; + /// Button to be added. /// Text on the button. /// Colour of the button. /// Hotkey of the button. @@ -41,21 +39,16 @@ namespace osu.Game.Screens.Select /// Higher depth to be put on the left, and lower to be put on the right. /// Notice this is different to ! /// - public void AddButton(string text, Color4 colour, Action action, Key? hotkey = null, float depth = 0) + public void AddButton(FooterButton button, string text, Color4 colour, Action action, Key? hotkey = null, float depth = 0) { - var button = new FooterButton - { - Text = text, - Height = play_song_select_button_height, - Width = play_song_select_button_width, - Depth = depth, - SelectedColour = colour, - DeselectedColour = colour.Opacity(0.5f), - Hotkey = hotkey, - Hovered = updateModeLight, - HoverLost = updateModeLight, - Action = action, - }; + button.Text = text; + button.Depth = depth; + button.SelectedColour = colour; + button.DeselectedColour = colour.Opacity(0.5f); + button.Hotkey = hotkey; + button.Hovered = updateModeLight; + button.HoverLost = updateModeLight; + button.Action = action; buttons.Add(button); buttons.SetLayoutPosition(button, -depth); @@ -71,10 +64,10 @@ namespace osu.Game.Screens.Select /// Higher depth to be put on the left, and lower to be put on the right. /// Notice this is different to ! /// - public void AddButton(string text, Color4 colour, OverlayContainer overlay, Key? hotkey = null, float depth = 0) + public void AddButton(FooterButton button, string text, Color4 colour, OverlayContainer overlay, Key? hotkey = null, float depth = 0) { overlays.Add(overlay); - AddButton(text, colour, () => + AddButton(button, text, colour, () => { foreach (var o in overlays) { diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index 9b98e344ce..0000bb95dd 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -6,6 +6,7 @@ using osuTK; using osuTK.Graphics; using osuTK.Input; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; @@ -61,8 +62,18 @@ namespace osu.Game.Screens.Select public FooterButton() { + AutoSizeAxes = Axes.Both; Children = new Drawable[] { + new Container + { + Size = new Vector2(100, 50), + Child = spriteText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }, box = new Box { RelativeSizeAxes = Axes.Both, @@ -78,11 +89,6 @@ namespace osu.Game.Screens.Select EdgeSmoothness = new Vector2(2, 0), RelativeSizeAxes = Axes.X, }, - spriteText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } }; } diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs new file mode 100644 index 0000000000..a08870ba03 --- /dev/null +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -0,0 +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.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; +using System; +using System.Collections.Generic; +using osuTK; + +namespace osu.Game.Screens.Select +{ + public class FooterButtonMods : FooterButton + { + private readonly Bindable> selectedMods = new Bindable>(); + + private readonly FillFlowContainer modIcons; + + public FooterButtonMods(Bindable> mods) : base() + { + Add(modIcons = new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding {Left = 80, Right = 20} + }); + + if (mods != null) + { + selectedMods.BindTo(mods); + selectedMods.ValueChanged += updateModIcons; + } + } + + private void updateModIcons(ValueChangedEvent> mods) + { + modIcons.Clear(); + foreach (Mod mod in mods.NewValue) + { + modIcons.Add(new ModIcon(mod) { Scale = new Vector2(0.4f) }); + } + } + } +} diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index b60e693cbf..6fc95ea2e1 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -224,9 +224,9 @@ namespace osu.Game.Screens.Select if (Footer != null) { - Footer.AddButton(@"mods", colours.Yellow, ModSelect, Key.F1); - Footer.AddButton(@"random", colours.Green, triggerRandom, Key.F2); - Footer.AddButton(@"options", colours.Blue, BeatmapOptions, Key.F3); + Footer.AddButton(new FooterButtonMods(selectedMods), @"mods", colours.Yellow, ModSelect, Key.F1); + Footer.AddButton(new FooterButton(), @"random", colours.Green, triggerRandom, Key.F2); + Footer.AddButton(new FooterButton(), @"options", colours.Blue, BeatmapOptions, Key.F3); BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo), Key.Number4, float.MaxValue); BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, colours.Purple, null, Key.Number1); From b4d07558186a9d8dc3627ac1af564e375cab2f95 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Wed, 10 Apr 2019 22:10:09 +0800 Subject: [PATCH 0543/5608] please appveyor --- osu.Game/Screens/Select/FooterButtonMods.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index a08870ba03..51973b1e3d 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; -using System; using System.Collections.Generic; using osuTK; @@ -18,7 +17,7 @@ namespace osu.Game.Screens.Select private readonly FillFlowContainer modIcons; - public FooterButtonMods(Bindable> mods) : base() + public FooterButtonMods(Bindable> mods) { Add(modIcons = new FillFlowContainer { @@ -26,7 +25,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.CentreLeft, Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, - Margin = new MarginPadding {Left = 80, Right = 20} + Margin = new MarginPadding { Left = 80, Right = 20 } }); if (mods != null) From 01cc78108c1bd0d2fa3a21d6327e85354ccc6e8b Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Thu, 11 Apr 2019 05:47:32 +0800 Subject: [PATCH 0544/5608] add random button --- osu.Game/Screens/Select/FooterButton.cs | 5 +- osu.Game/Screens/Select/FooterButtonRandom.cs | 56 +++++++++++++++++++ osu.Game/Screens/Select/SongSelect.cs | 2 +- 3 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Screens/Select/FooterButtonRandom.cs diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index 0000bb95dd..aa547c658f 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -54,7 +54,8 @@ namespace osu.Game.Screens.Select } } - private readonly SpriteText spriteText; + protected readonly Container textContainer; + protected readonly SpriteText spriteText; private readonly Box box; private readonly Box light; @@ -65,7 +66,7 @@ namespace osu.Game.Screens.Select AutoSizeAxes = Axes.Both; Children = new Drawable[] { - new Container + textContainer = new Container { Size = new Vector2(100, 50), Child = spriteText = new OsuSpriteText diff --git a/osu.Game/Screens/Select/FooterButtonRandom.cs b/osu.Game/Screens/Select/FooterButtonRandom.cs new file mode 100644 index 0000000000..7466e1f243 --- /dev/null +++ b/osu.Game/Screens/Select/FooterButtonRandom.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.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Sprites; +using System; + +namespace osu.Game.Screens.Select +{ + public class FooterButtonRandom : FooterButton + { + private readonly SpriteText secondaryText; + private bool secondaryActive; + + public FooterButtonRandom() + { + textContainer.Add(secondaryText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = @"rewind", + Alpha = 0 + }); + } + + protected override bool OnKeyDown(KeyDownEvent e) + { + secondaryActive = e.ShiftPressed; + updateText(); + return base.OnKeyDown(e); + } + + protected override bool OnKeyUp(KeyUpEvent e) + { + secondaryActive = e.ShiftPressed; + updateText(); + return base.OnKeyUp(e); + } + + private void updateText() + { + if (secondaryActive) + { + spriteText.FadeOut(120, Easing.InQuad); + secondaryText.FadeIn(120, Easing.InQuad); + } + else + { + spriteText.FadeIn(120, Easing.InQuad); + secondaryText.FadeOut(120, Easing.InQuad); + } + } + } +} diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 6fc95ea2e1..7fb49e6dc6 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -225,7 +225,7 @@ namespace osu.Game.Screens.Select if (Footer != null) { Footer.AddButton(new FooterButtonMods(selectedMods), @"mods", colours.Yellow, ModSelect, Key.F1); - Footer.AddButton(new FooterButton(), @"random", colours.Green, triggerRandom, Key.F2); + Footer.AddButton(new FooterButtonRandom(), @"random", colours.Green, triggerRandom, Key.F2); Footer.AddButton(new FooterButton(), @"options", colours.Blue, BeatmapOptions, Key.F3); BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo), Key.Number4, float.MaxValue); From 664a4ba540677fb6851d7a6c7277bc1eb788928c Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 12 Apr 2019 10:47:22 +0900 Subject: [PATCH 0545/5608] Implement flashlight dimming on slider slide --- .../Mods/OsuModFlashlight.cs | 30 +++++++++++++++++-- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- .../Objects/Drawables/DrawableSlider.cs | 4 +-- osu.Game/Rulesets/Mods/ModFlashlight.cs | 17 +++++++++++ 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 2c40d18f1b..26c0c26f0f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -1,23 +1,49 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; using osuTK; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModFlashlight : ModFlashlight + public class OsuModFlashlight : ModFlashlight, IApplicableToDrawableHitObjects { public override double ScoreMultiplier => 1.12; private const float default_flashlight_size = 180; - public override Flashlight CreateFlashlight() => new OsuFlashlight(); + private int trackingSliders; + + private OsuFlashlight flashlight; + + public override Flashlight CreateFlashlight() => flashlight = new OsuFlashlight(); + + public void ApplyToDrawableHitObjects(IEnumerable drawables) + { + foreach (DrawableSlider drawable in drawables.OfType()) + { + drawable.Tracking.ValueChanged += updateTrackingSliders; + } + } + + private void updateTrackingSliders(ValueChangedEvent value) + { + if (value.NewValue) + trackingSliders++; + else + trackingSliders--; + + flashlight.FlashlightLightness = trackingSliders > 0 ? 0.2f : 1.0f; + } private class OsuFlashlight : Flashlight, IRequireHighFrequencyMousePosition { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index edf2d90c08..bece2a49cd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForResult(bool userTriggered, double timeOffset) { if (repeatPoint.StartTime <= Time.Current) - ApplyResult(r => r.Type = drawableSlider.Tracking ? HitResult.Great : HitResult.Miss); + ApplyResult(r => r.Type = drawableSlider.Tracking.Value ? HitResult.Great : HitResult.Miss); } protected override void UpdatePreemptState() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 57ea0abdd8..c1a4c1981f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -130,13 +130,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - public bool Tracking; + public readonly Bindable Tracking = new Bindable(); protected override void Update() { base.Update(); - Tracking = Ball.Tracking; + Tracking.Value = Ball.Tracking; double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 0ad99d13ff..fa070dc9e8 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -80,6 +80,7 @@ namespace osu.Game.Rulesets.Mods flashNode.ScreenSpaceDrawQuad = ScreenSpaceDrawQuad; flashNode.FlashlightPosition = Vector2Extensions.Transform(FlashlightPosition, DrawInfo.Matrix); flashNode.FlashlightSize = Vector2Extensions.Transform(FlashlightSize, DrawInfo.Matrix); + flashNode.FlashlightLightness = FlashlightLightness; } [BackgroundDependencyLoader] @@ -136,6 +137,20 @@ namespace osu.Game.Rulesets.Mods Invalidate(Invalidation.DrawNode); } } + + private float flashlightLightness = 1.0f; + + public float FlashlightLightness + { + get => flashlightLightness; + set + { + if (flashlightLightness == value) return; + + flashlightLightness = value; + Invalidate(Invalidation.DrawNode); + } + } } private class FlashlightDrawNode : DrawNode @@ -144,6 +159,7 @@ namespace osu.Game.Rulesets.Mods public Quad ScreenSpaceDrawQuad; public Vector2 FlashlightPosition; public Vector2 FlashlightSize; + public float FlashlightLightness; public override void Draw(Action vertexAction) { @@ -153,6 +169,7 @@ namespace osu.Game.Rulesets.Mods Shader.GetUniform("flashlightPos").UpdateValue(ref FlashlightPosition); Shader.GetUniform("flashlightSize").UpdateValue(ref FlashlightSize); + Shader.GetUniform("flashlightLightness").UpdateValue(ref FlashlightLightness); Texture.WhitePixel.DrawQuad(ScreenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction); From 846a4835ca3a5915a31318d8b67472eb0ab636d2 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 12 Apr 2019 11:23:40 +0900 Subject: [PATCH 0546/5608] Invert flashlight dim --- osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs | 2 +- osu.Game/Rulesets/Mods/ModFlashlight.cs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 26c0c26f0f..6a57e39616 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Mods else trackingSliders--; - flashlight.FlashlightLightness = trackingSliders > 0 ? 0.2f : 1.0f; + flashlight.FlashlightDim = trackingSliders > 0 ? 0.8f : 0.0f; } private class OsuFlashlight : Flashlight, IRequireHighFrequencyMousePosition diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index fa070dc9e8..e454c59fab 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Mods flashNode.ScreenSpaceDrawQuad = ScreenSpaceDrawQuad; flashNode.FlashlightPosition = Vector2Extensions.Transform(FlashlightPosition, DrawInfo.Matrix); flashNode.FlashlightSize = Vector2Extensions.Transform(FlashlightSize, DrawInfo.Matrix); - flashNode.FlashlightLightness = FlashlightLightness; + flashNode.FlashlightDim = FlashlightDim; } [BackgroundDependencyLoader] @@ -138,16 +138,16 @@ namespace osu.Game.Rulesets.Mods } } - private float flashlightLightness = 1.0f; + private float flashlightDim; - public float FlashlightLightness + public float FlashlightDim { - get => flashlightLightness; + get => flashlightDim; set { - if (flashlightLightness == value) return; + if (flashlightDim == value) return; - flashlightLightness = value; + flashlightDim = value; Invalidate(Invalidation.DrawNode); } } @@ -159,7 +159,7 @@ namespace osu.Game.Rulesets.Mods public Quad ScreenSpaceDrawQuad; public Vector2 FlashlightPosition; public Vector2 FlashlightSize; - public float FlashlightLightness; + public float FlashlightDim; public override void Draw(Action vertexAction) { @@ -169,7 +169,7 @@ namespace osu.Game.Rulesets.Mods Shader.GetUniform("flashlightPos").UpdateValue(ref FlashlightPosition); Shader.GetUniform("flashlightSize").UpdateValue(ref FlashlightSize); - Shader.GetUniform("flashlightLightness").UpdateValue(ref FlashlightLightness); + Shader.GetUniform("flashlightDim").UpdateValue(ref FlashlightDim); Texture.WhitePixel.DrawQuad(ScreenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction); From dba4ccdf74b401f6f07584df67acd4ead0c49c89 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 12 Apr 2019 14:53:23 +0900 Subject: [PATCH 0547/5608] Add back flashlight testcase --- .../TestCaseFlashlight.cs | 18 ++++++++++++++++++ osu.Game/Tests/Visual/AllPlayersTestCase.cs | 12 +++++------- osu.Game/Tests/Visual/PlayerTestCase.cs | 13 ++++--------- 3 files changed, 27 insertions(+), 16 deletions(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestCaseFlashlight.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseFlashlight.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseFlashlight.cs new file mode 100644 index 0000000000..28a732cc49 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseFlashlight.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.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Screens.Play; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestCaseFlashlight : TestCaseOsuPlayer + { + protected override Player CreatePlayer(Ruleset ruleset) + { + Beatmap.Value.Mods.Value = new Mod[] { new OsuModAutoplay(), new OsuModFlashlight(), }; + return base.CreatePlayer(ruleset); + } + } +} diff --git a/osu.Game/Tests/Visual/AllPlayersTestCase.cs b/osu.Game/Tests/Visual/AllPlayersTestCase.cs index 4ef9b346b0..6747493509 100644 --- a/osu.Game/Tests/Visual/AllPlayersTestCase.cs +++ b/osu.Game/Tests/Visual/AllPlayersTestCase.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Screens; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; @@ -26,13 +27,6 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - Add(new Box - { - RelativeSizeAxes = Framework.Graphics.Axes.Both, - Colour = Color4.Black, - Depth = int.MaxValue - }); - foreach (var r in rulesets.AvailableRulesets) { Player p = null; @@ -50,6 +44,10 @@ namespace osu.Game.Tests.Visual AddCheckSteps(); } + + OsuConfigManager manager; + Dependencies.Cache(manager = new OsuConfigManager(LocalStorage)); + manager.GetBindable(OsuSetting.DimLevel).Value = 1.0; } protected abstract void AddCheckSteps(); diff --git a/osu.Game/Tests/Visual/PlayerTestCase.cs b/osu.Game/Tests/Visual/PlayerTestCase.cs index 3bf707fade..8ec822957f 100644 --- a/osu.Game/Tests/Visual/PlayerTestCase.cs +++ b/osu.Game/Tests/Visual/PlayerTestCase.cs @@ -3,15 +3,13 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps; -using osuTK.Graphics; namespace osu.Game.Tests.Visual { @@ -29,12 +27,9 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - Add(new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Depth = int.MaxValue - }); + OsuConfigManager manager; + Dependencies.Cache(manager = new OsuConfigManager(LocalStorage)); + manager.GetBindable(OsuSetting.DimLevel).Value = 1.0; } [SetUpSteps] From 69748abedcd1e8e018afd8c55da4e6a36297018d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 12 Apr 2019 15:09:43 +0900 Subject: [PATCH 0548/5608] Rename to TestCaseOsuFlashlight --- .../{TestCaseFlashlight.cs => TestCaseOsuFlashlight.cs} | 2 +- osu.Game/Tests/Visual/AllPlayersTestCase.cs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) rename osu.Game.Rulesets.Osu.Tests/{TestCaseFlashlight.cs => TestCaseOsuFlashlight.cs} (89%) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseFlashlight.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseOsuFlashlight.cs similarity index 89% rename from osu.Game.Rulesets.Osu.Tests/TestCaseFlashlight.cs rename to osu.Game.Rulesets.Osu.Tests/TestCaseOsuFlashlight.cs index 28a732cc49..6f198084f5 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseFlashlight.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseOsuFlashlight.cs @@ -7,7 +7,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseFlashlight : TestCaseOsuPlayer + public class TestCaseOsuFlashlight : TestCaseOsuPlayer { protected override Player CreatePlayer(Ruleset ruleset) { diff --git a/osu.Game/Tests/Visual/AllPlayersTestCase.cs b/osu.Game/Tests/Visual/AllPlayersTestCase.cs index 6747493509..882f510b64 100644 --- a/osu.Game/Tests/Visual/AllPlayersTestCase.cs +++ b/osu.Game/Tests/Visual/AllPlayersTestCase.cs @@ -3,7 +3,6 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Graphics.Shapes; using osu.Framework.Screens; using osu.Framework.Timing; using osu.Game.Beatmaps; @@ -12,7 +11,6 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps; -using osuTK.Graphics; namespace osu.Game.Tests.Visual { From d9ed68b18968ce1c1eafd6c3dc466b7119c5e134 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 12 Apr 2019 15:33:31 +0900 Subject: [PATCH 0549/5608] Add short fade to flashlight dimming --- .../Mods/OsuModFlashlight.cs | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 6a57e39616..5d136e4cbe 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -21,8 +21,6 @@ namespace osu.Game.Rulesets.Osu.Mods private const float default_flashlight_size = 180; - private int trackingSliders; - private OsuFlashlight flashlight; public override Flashlight CreateFlashlight() => flashlight = new OsuFlashlight(); @@ -31,27 +29,30 @@ namespace osu.Game.Rulesets.Osu.Mods { foreach (DrawableSlider drawable in drawables.OfType()) { - drawable.Tracking.ValueChanged += updateTrackingSliders; + drawable.Tracking.ValueChanged += flashlight.OnSliderTrackingChange; } } - private void updateTrackingSliders(ValueChangedEvent value) - { - if (value.NewValue) - trackingSliders++; - else - trackingSliders--; - - flashlight.FlashlightDim = trackingSliders > 0 ? 0.8f : 0.0f; - } - private class OsuFlashlight : Flashlight, IRequireHighFrequencyMousePosition { + private int trackingSliders; + public OsuFlashlight() { FlashlightSize = new Vector2(0, getSizeFor(0)); } + public void OnSliderTrackingChange(ValueChangedEvent e) + { + if (e.NewValue) + trackingSliders++; + else + trackingSliders--; + + // If there are any sliders in a tracking state, apply a dim to the entire playfield over a brief duration. + this.TransformTo(nameof(FlashlightDim), trackingSliders > 0 ? 0.8f : 0.0f, 50); + } + protected override bool OnMouseMove(MouseMoveEvent e) { FlashlightPosition = e.MousePosition; From e25c7fdb9b5c8de23ef51c39065fbde9c7af2bf1 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 12 Apr 2019 17:39:25 +0900 Subject: [PATCH 0550/5608] Use absolute sequence for flashlight breaks --- osu.Game/Rulesets/Mods/ModFlashlight.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index e454c59fab..b5a907c0ef 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -95,14 +95,17 @@ namespace osu.Game.Rulesets.Mods Combo.ValueChanged += OnComboChange; - this.FadeInFromZero(FLASHLIGHT_FADE_DURATION); - - foreach (var breakPeriod in Breaks) + using (BeginAbsoluteSequence(0)) { - if (breakPeriod.Duration < FLASHLIGHT_FADE_DURATION * 2) continue; + this.FadeInFromZero(FLASHLIGHT_FADE_DURATION); - this.Delay(breakPeriod.StartTime + FLASHLIGHT_FADE_DURATION).FadeOutFromOne(FLASHLIGHT_FADE_DURATION); - this.Delay(breakPeriod.EndTime - FLASHLIGHT_FADE_DURATION).FadeInFromZero(FLASHLIGHT_FADE_DURATION); + foreach (var breakPeriod in Breaks) + { + if (breakPeriod.Duration < FLASHLIGHT_FADE_DURATION * 2) continue; + + this.Delay(breakPeriod.StartTime + FLASHLIGHT_FADE_DURATION).FadeOutFromOne(FLASHLIGHT_FADE_DURATION); + this.Delay(breakPeriod.EndTime - FLASHLIGHT_FADE_DURATION).FadeInFromZero(FLASHLIGHT_FADE_DURATION); + } } } From 69dda0ffd43caa6b94efd871e887cd3667433a9c Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 12 Apr 2019 22:36:01 +0200 Subject: [PATCH 0551/5608] OsuScreens can now set a per screen user status which defaults to UserStatusOnline --- osu.Game/Screens/OsuScreen.cs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index e0a25deecf..d54936ffda 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -14,6 +14,8 @@ using osu.Game.Input.Bindings; using osu.Game.Rulesets; using osu.Game.Screens.Menu; using osu.Game.Overlays; +using osu.Game.Users; +using osu.Game.Online.API; namespace osu.Game.Screens { @@ -50,6 +52,14 @@ namespace osu.Game.Screens protected new OsuGameBase Game => base.Game as OsuGameBase; + /// + /// The to set the user's status automatically to when this screen is entered / resumed. + /// Note that the user status won't be automatically set if : + /// - is overriden and returns null + /// - The current is or + /// + protected virtual UserStatus ScreenStatus => new UserStatusOnline(); + /// /// Whether to disallow changes to game-wise Beatmap/Ruleset bindables for this screen (and all children). /// @@ -83,6 +93,9 @@ namespace osu.Game.Screens [Resolved(canBeNull: true)] private OsuLogo logo { get; set; } + [Resolved(canBeNull: true)] + private IAPIProvider api { get; set; } + protected OsuScreen() { Anchor = Anchor.Centre; @@ -115,6 +128,8 @@ namespace osu.Game.Screens sampleExit?.Play(); applyArrivingDefaults(true); + setUserStatus(ScreenStatus); + base.OnResuming(last); } @@ -130,6 +145,8 @@ namespace osu.Game.Screens backgroundStack?.Push(localBackground = CreateBackground()); + setUserStatus(ScreenStatus); + base.OnEntering(last); } @@ -147,6 +164,12 @@ namespace osu.Game.Screens return false; } + private void setUserStatus(UserStatus status) + { + if (api != null && status != null && !(api.LocalUser.Value.Status.Value is UserStatusDoNotDisturb) && !(api.LocalUser.Value.Status.Value is UserStatusOffline)) //only sets the user's status to the given one if + api.LocalUser.Value.Status.Value = status; //status is not null and the current status isn't either UserStatusDoNotDisturb or UserStatusOffline + } + /// /// Fired when this screen was entered or resumed and the logo state is required to be adjusted. /// From da5d6cb1d48c7622e8f4e365dbea1a840fd48e22 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 12 Apr 2019 22:54:35 +0200 Subject: [PATCH 0552/5608] Add Beatmap fields to UserStatusSoloGame & UserStatusEditing so they can carry metadata about the played / edited beatmap --- osu.Game/Screens/Edit/Editor.cs | 3 +++ osu.Game/Screens/Play/Player.cs | 3 +++ osu.Game/Screens/Select/PlaySongSelect.cs | 3 +++ osu.Game/Users/UserStatus.cs | 27 +++++++++++++++++++++++ 4 files changed, 36 insertions(+) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 0ba1e74aca..bf00d23903 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -24,6 +24,7 @@ using osu.Game.Screens.Edit.Design; using osuTK.Input; using System.Collections.Generic; using osu.Framework; +using osu.Game.Users; namespace osu.Game.Screens.Edit { @@ -47,6 +48,8 @@ namespace osu.Game.Screens.Edit private DependencyContainer dependencies; private GameHost host; + protected override UserStatus ScreenStatus => new UserStatusEditing(Beatmap.Value.BeatmapInfo); + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0eebefec86..edb6f9f865 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -26,6 +26,7 @@ using osu.Game.Scoring; using osu.Game.Screens.Ranking; using osu.Game.Skinning; using osu.Game.Storyboards.Drawables; +using osu.Game.Users; namespace osu.Game.Screens.Play { @@ -33,6 +34,8 @@ namespace osu.Game.Screens.Play { protected override bool AllowBackButton => false; // handled by HoldForMenuButton + protected override UserStatus ScreenStatus => new UserStatusSoloGame(Beatmap.Value.BeatmapInfo); + public override float BackgroundParallaxAmount => 0.1f; public override bool HideOverlaysOnEnter => true; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 340ceb6864..384064d2a8 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Screens.Play; +using osu.Game.Users; using osuTK.Input; namespace osu.Game.Screens.Select @@ -18,6 +19,8 @@ namespace osu.Game.Screens.Select public override bool AllowExternalScreenChange => true; + protected override UserStatus ScreenStatus => new UserStatusChoosingBeatmap(); + [BackgroundDependencyLoader] private void load(OsuColour colours) { diff --git a/osu.Game/Users/UserStatus.cs b/osu.Game/Users/UserStatus.cs index 14b4538a00..60e637d7e4 100644 --- a/osu.Game/Users/UserStatus.cs +++ b/osu.Game/Users/UserStatus.cs @@ -3,6 +3,7 @@ using osuTK.Graphics; using osu.Game.Graphics; +using osu.Game.Beatmaps; namespace osu.Game.Users { @@ -41,7 +42,33 @@ namespace osu.Game.Users public class UserStatusSoloGame : UserStatusBusy { + public UserStatusSoloGame(BeatmapInfo info) + { + Beatmap = info; + } + public override string Message => @"Solo Game"; + + public BeatmapInfo Beatmap { get; } + } + + public class UserStatusEditing : UserStatusBusy + { + public UserStatusEditing(BeatmapInfo info) + { + Beatmap = info; + } + + public override string Message => @"Editing a beatmap"; + + public override Color4 GetAppropriateColour(OsuColour colours) => colours.GreenDarker; + + public BeatmapInfo Beatmap { get; } + } + + public class UserStatusChoosingBeatmap : UserStatusOnline + { + public override string Message => @"Choosing a beatmap"; } public class UserStatusMultiplayerGame : UserStatusBusy From 5ab278f9eac4a3d72b8da0e37b07bfc037117717 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 12 Apr 2019 23:01:11 +0200 Subject: [PATCH 0553/5608] Add missing user statuses to tests --- osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs b/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs index b2877f7bd7..182ea6da01 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs @@ -43,11 +43,13 @@ namespace osu.Game.Tests.Visual.Online }); flyte.Status.Value = new UserStatusOnline(); - peppy.Status.Value = new UserStatusSoloGame(); + peppy.Status.Value = new UserStatusSoloGame(new Game.Beatmaps.BeatmapInfo()); AddStep(@"spectating", () => { flyte.Status.Value = new UserStatusSpectating(); }); AddStep(@"multiplaying", () => { flyte.Status.Value = new UserStatusMultiplayerGame(); }); AddStep(@"modding", () => { flyte.Status.Value = new UserStatusModding(); }); + AddStep(@"editing", () => { flyte.Status.Value = new UserStatusEditing(null); }); + AddStep(@"choosing", () => { flyte.Status.Value = new UserStatusChoosingBeatmap(); }); AddStep(@"offline", () => { flyte.Status.Value = new UserStatusOffline(); }); AddStep(@"null status", () => { flyte.Status.Value = null; }); } From 361c0ec9f26d9c066cb4830e16343bc3d5b6e02b Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 13 Apr 2019 13:18:44 +0200 Subject: [PATCH 0554/5608] Allow UserStatusSoloGame to provide metadata such as the ruleset the current beatmap is played in --- osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Play/PlayerLoader.cs | 3 +++ osu.Game/Users/UserStatus.cs | 5 ++++- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs b/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs index 182ea6da01..90cdd48a1e 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Online }); flyte.Status.Value = new UserStatusOnline(); - peppy.Status.Value = new UserStatusSoloGame(new Game.Beatmaps.BeatmapInfo()); + peppy.Status.Value = new UserStatusSoloGame(null, null); AddStep(@"spectating", () => { flyte.Status.Value = new UserStatusSpectating(); }); AddStep(@"multiplaying", () => { flyte.Status.Value = new UserStatusMultiplayerGame(); }); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index edb6f9f865..97133773fa 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Play { protected override bool AllowBackButton => false; // handled by HoldForMenuButton - protected override UserStatus ScreenStatus => new UserStatusSoloGame(Beatmap.Value.BeatmapInfo); + protected override UserStatus ScreenStatus => new UserStatusSoloGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); public override float BackgroundParallaxAmount => 0.1f; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index e9ee5d3fa8..4d2e3a8cca 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -19,6 +19,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Menu; using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.PlayerSettings; +using osu.Game.Users; using osuTK; using osuTK.Graphics; @@ -39,6 +40,8 @@ namespace osu.Game.Screens.Play private bool hideOverlays; public override bool HideOverlaysOnEnter => hideOverlays; + protected override UserStatus ScreenStatus => null; //shows the previous screen status + public override bool DisallowExternalBeatmapRulesetChanges => true; private Task loadTask; diff --git a/osu.Game/Users/UserStatus.cs b/osu.Game/Users/UserStatus.cs index 60e637d7e4..39f295f445 100644 --- a/osu.Game/Users/UserStatus.cs +++ b/osu.Game/Users/UserStatus.cs @@ -42,14 +42,17 @@ namespace osu.Game.Users public class UserStatusSoloGame : UserStatusBusy { - public UserStatusSoloGame(BeatmapInfo info) + public UserStatusSoloGame(BeatmapInfo info, Rulesets.RulesetInfo ruleset) { Beatmap = info; + Ruleset = ruleset; } public override string Message => @"Solo Game"; public BeatmapInfo Beatmap { get; } + + public Rulesets.RulesetInfo Ruleset { get; } } public class UserStatusEditing : UserStatusBusy From c766631ad6a163e04c531d20d4ed24db47d0e4d3 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Sat, 13 Apr 2019 11:39:22 -0300 Subject: [PATCH 0555/5608] Check for breaks using GameplayClock time. --- osu.Game/Screens/Play/BreakOverlay.cs | 4 ---- osu.Game/Screens/Play/Player.cs | 8 ++++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index ab81e613cc..d390787090 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -23,8 +23,6 @@ namespace osu.Game.Screens.Play private readonly Container fadeContainer; - public bool IsActive { get; private set; } - public List Breaks { get => breaks; @@ -127,7 +125,6 @@ namespace osu.Game.Screens.Play using (BeginAbsoluteSequence(b.StartTime, true)) { - Schedule(() => IsActive = true); fadeContainer.FadeIn(fade_duration); breakArrows.Show(fade_duration); @@ -145,7 +142,6 @@ namespace osu.Game.Screens.Play using (BeginDelayedSequence(b.Duration - fade_duration, true)) { - Schedule(() => IsActive = false); fadeContainer.FadeOut(fade_duration); breakArrows.Hide(fade_duration); } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 60287f7a2e..1878b19a1c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -60,8 +60,6 @@ namespace osu.Game.Screens.Play private SampleChannel sampleRestart; - private BreakOverlay breakOverlay; - protected ScoreProcessor ScoreProcessor { get; private set; } protected DrawableRuleset DrawableRuleset { get; private set; } @@ -117,7 +115,7 @@ namespace osu.Game.Screens.Play Child = DrawableRuleset } }, - breakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) + new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -408,7 +406,9 @@ namespace osu.Game.Screens.Play PauseOverlay.Hide(); // breaks and time-based conditions may allow instant resume. - if (breakOverlay.IsActive || GameplayClockContainer.GameplayClock.CurrentTime < Beatmap.Value.Beatmap.HitObjects.First().StartTime) + double time = GameplayClockContainer.GameplayClock.CurrentTime; + if (Beatmap.Value.Beatmap.Breaks.Any(b => time >= b.StartTime && time <= b.EndTime) || + time < Beatmap.Value.Beatmap.HitObjects.First().StartTime) completeResume(); else DrawableRuleset.RequestResume(completeResume); From 91c327a90f14b151ff3a62710559ab3f96153aa5 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Sun, 14 Apr 2019 07:22:31 +0800 Subject: [PATCH 0556/5608] use ModDisplay --- osu.Game/Screens/Select/FooterButtonMods.cs | 28 +++++++++------------ 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 51973b1e3d..d4bb7d3f21 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -4,44 +4,40 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Screens.Play.HUD; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using System.Collections.Generic; using osuTK; +using osu.Framework.Input.Events; namespace osu.Game.Screens.Select { public class FooterButtonMods : FooterButton { - private readonly Bindable> selectedMods = new Bindable>(); - - private readonly FillFlowContainer modIcons; + private readonly FooterModDisplay modDisplay; public FooterButtonMods(Bindable> mods) { - Add(modIcons = new FillFlowContainer + Add(new Container { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Direction = FillDirection.Horizontal, + Child = modDisplay = new FooterModDisplay { + DisplayUnrankedText = false, + Scale = new Vector2(0.8f) + }, AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Left = 80, Right = 20 } + Margin = new MarginPadding { Left = 70 } }); if (mods != null) - { - selectedMods.BindTo(mods); - selectedMods.ValueChanged += updateModIcons; - } + modDisplay.Current = mods; } - private void updateModIcons(ValueChangedEvent> mods) + private class FooterModDisplay : ModDisplay { - modIcons.Clear(); - foreach (Mod mod in mods.NewValue) - { - modIcons.Add(new ModIcon(mod) { Scale = new Vector2(0.4f) }); - } + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Parent?.Parent?.ReceivePositionalInputAt(screenSpacePos) ?? false; } } } From 2d227d25ccf45132e813e5293cd165fa30a6606f Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Sun, 14 Apr 2019 07:55:15 +0800 Subject: [PATCH 0557/5608] fix appveyor warnings --- osu.Game/Screens/Select/FooterButton.cs | 14 +++++++------- osu.Game/Screens/Select/FooterButtonMods.cs | 6 ++---- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index aa547c658f..e18a086a10 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -21,11 +21,11 @@ namespace osu.Game.Screens.Select public string Text { - get => spriteText?.Text; + get => SpriteText?.Text; set { - if (spriteText != null) - spriteText.Text = value; + if (SpriteText != null) + SpriteText.Text = value; } } @@ -54,8 +54,8 @@ namespace osu.Game.Screens.Select } } - protected readonly Container textContainer; - protected readonly SpriteText spriteText; + protected readonly Container TextContainer; + protected readonly SpriteText SpriteText; private readonly Box box; private readonly Box light; @@ -66,10 +66,10 @@ namespace osu.Game.Screens.Select AutoSizeAxes = Axes.Both; Children = new Drawable[] { - textContainer = new Container + TextContainer = new Container { Size = new Vector2(100, 50), - Child = spriteText = new OsuSpriteText + Child = SpriteText = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index d4bb7d3f21..0a5b8c0929 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -6,19 +6,17 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Screens.Play.HUD; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.UI; using System.Collections.Generic; using osuTK; -using osu.Framework.Input.Events; namespace osu.Game.Screens.Select { public class FooterButtonMods : FooterButton { - private readonly FooterModDisplay modDisplay; - public FooterButtonMods(Bindable> mods) { + FooterModDisplay modDisplay; + Add(new Container { Anchor = Anchor.CentreLeft, From ac2eabc9bfb8bf7c5d52b5b8a1f97ca37fc1c585 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Apr 2019 17:47:00 +0900 Subject: [PATCH 0558/5608] Fix replay rewinding not respecting 60fps playback --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index deec2b8eac..c307520aca 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.UI { if (Math.Abs(manualClock.CurrentTime - newProposedTime) > sixty_frame_time * 1.2f) { - newProposedTime = manualClock.Rate > 0 + newProposedTime = newProposedTime > manualClock.CurrentTime ? Math.Min(newProposedTime, manualClock.CurrentTime + sixty_frame_time) : Math.Max(newProposedTime, manualClock.CurrentTime - sixty_frame_time); } From b684cd49e6fdd0233f91be155c1bdd182a76ddf7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 Apr 2019 22:51:57 +0800 Subject: [PATCH 0559/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 74ed9f91dd..1fcbe7c4c1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 9fff64c61c..831f33f0b8 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 5a3d6a02585b2d3b97e5846359e28a7b317cf6e3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Apr 2019 16:11:59 +0900 Subject: [PATCH 0560/5608] Fix post-merge errors --- osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs | 8 ++++---- osu.Game/Screens/Play/Player.cs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs index fba4aca343..f58c0d35b3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("load player", () => { - SelectedMods.Value = new[] { gameMod = new TestMod() }; + Mods.Value = new[] { gameMod = new TestMod() }; InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre); stack.Push(new PlayerLoader(() => player = new TestPlayer())); }); @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Visual.Gameplay { if (player.IsCurrentScreen()) { - playerMod1 = (TestMod)player.SelectedMods.Value.Single(); + playerMod1 = (TestMod)player.Mods.Value.Single(); return true; } @@ -86,7 +86,7 @@ namespace osu.Game.Tests.Visual.Gameplay { if (player.IsCurrentScreen()) { - playerMod2 = (TestMod)player.SelectedMods.Value.Single(); + playerMod2 = (TestMod)player.Mods.Value.Single(); return true; } @@ -114,7 +114,7 @@ namespace osu.Game.Tests.Visual.Gameplay private class TestPlayer : Player { - public new Bindable> SelectedMods => base.SelectedMods; + public new Bindable> Mods => base.Mods; public TestPlayer() : base(false, false) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index f8b3efb781..f833aa2bb7 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -71,8 +71,8 @@ namespace osu.Game.Screens.Play protected GameplayClockContainer GameplayClockContainer { get; private set; } [Cached] - [Cached(Type = typeof(IBindable>))] - protected readonly Bindable> SelectedMods = new Bindable>(Enumerable.Empty()); + [Cached(Type = typeof(IBindable>))] + protected readonly Bindable> Mods = new Bindable>(Array.Empty()); private readonly bool allowPause; private readonly bool showResults; @@ -93,7 +93,7 @@ namespace osu.Game.Screens.Play { this.api = api; - SelectedMods.Value = base.SelectedMods.Value.Select(m => m.CreateCopy()).ToArray(); + Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray(); WorkingBeatmap working = loadBeatmap(); From 9f92b3a8ba503940bbd559388149812086a4504f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Apr 2019 16:34:53 +0900 Subject: [PATCH 0561/5608] Add xmldoc --- osu.Game/Graphics/Containers/LogoTrackingContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index 5ebdb7d45d..f139040abd 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -60,6 +60,9 @@ namespace osu.Game.Graphics.Containers startPosition = null; } + /// + /// Stops the logo assigned in from tracking the facade's position. + /// public void StopTracking() { if (Logo != null) From 3a1587fa53b53ce5490032469d8e19fce34d3f47 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Apr 2019 16:40:47 +0900 Subject: [PATCH 0562/5608] Throw exception when not relatively positioned --- osu.Game/Graphics/Containers/LogoTrackingContainer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index f139040abd..ddf257776f 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -92,12 +92,15 @@ namespace osu.Game.Graphics.Containers if (Logo == null) return; + if (Logo.RelativePositionAxes != Axes.Both) + throw new InvalidOperationException($"Tracking logo must have {nameof(RelativePositionAxes)} = Axes.Both"); + // Account for the scale of the actual OsuLogo, as SizeForFlow only accounts for the sprite scale. ((ExposedFacade)LogoFacade).SetSize(new Vector2(Logo.SizeForFlow * Logo.Scale.X)); var localPos = ComputeLogoTrackingPosition(); - if (LogoFacade.Parent != null && Logo.Position != localPos && Logo.RelativePositionAxes == Axes.Both) + if (LogoFacade.Parent != null && Logo.Position != localPos) { // If this is our first update since tracking has started, initialize our starting values for interpolation if (startTime == null || startPosition == null) From 4106da24303cf0289293d0d87ccc16fc4aee0b93 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Apr 2019 16:41:20 +0900 Subject: [PATCH 0563/5608] Rename facade + cleanup usage --- .../Graphics/Containers/LogoTrackingContainer.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index ddf257776f..fb23038dde 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -15,22 +15,19 @@ namespace osu.Game.Graphics.Containers /// public class LogoTrackingContainer : Container { - public Facade LogoFacade { get; } + public Facade LogoFacade => facade; protected OsuLogo Logo { get; private set; } + private readonly InternalFacade facade = new InternalFacade(); + private Easing easing; private Vector2? startPosition; private double? startTime; private double duration; - public LogoTrackingContainer() - { - LogoFacade = new ExposedFacade(); - } - /// - /// Assign the logo that should track the Facade's position, as well as how it should transform to its initial position. + /// Assign the logo that should track the facade's position, as well as how it should transform to its initial position. /// /// The instance of the logo to be used for tracking. /// The scale of the facade. Does not actually affect the logo itself. @@ -96,7 +93,7 @@ namespace osu.Game.Graphics.Containers throw new InvalidOperationException($"Tracking logo must have {nameof(RelativePositionAxes)} = Axes.Both"); // Account for the scale of the actual OsuLogo, as SizeForFlow only accounts for the sprite scale. - ((ExposedFacade)LogoFacade).SetSize(new Vector2(Logo.SizeForFlow * Logo.Scale.X)); + facade.SetSize(new Vector2(Logo.SizeForFlow * Logo.Scale.X)); var localPos = ComputeLogoTrackingPosition(); @@ -133,7 +130,7 @@ namespace osu.Game.Graphics.Containers base.Dispose(isDisposing); } - private class ExposedFacade : Facade + private class InternalFacade : Facade { public void SetSize(Vector2 size) { From 897bfa60db361b01682be36b55640ed3bf4a4d9f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Apr 2019 17:02:47 +0900 Subject: [PATCH 0564/5608] Fix tracking position during 150ms state change delay --- osu.Game/Screens/Menu/ButtonArea.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Menu/ButtonArea.cs b/osu.Game/Screens/Menu/ButtonArea.cs index d6e1aef63c..eada1e0777 100644 --- a/osu.Game/Screens/Menu/ButtonArea.cs +++ b/osu.Game/Screens/Menu/ButtonArea.cs @@ -32,6 +32,7 @@ namespace osu.Game.Screens.Menu RelativeSizeAxes = Axes.X, Size = new Vector2(1, BUTTON_AREA_HEIGHT), Alpha = 0, + AlwaysPresent = true, // Always needs to be present for correct tracking on initial -> toplevel state change Children = new Drawable[] { buttonAreaBackground = new ButtonAreaBackground(), From 106e77c3d7794ab923380cbeb2cbe72c7b289741 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Apr 2019 17:15:23 +0900 Subject: [PATCH 0565/5608] Cleanup testcase --- .../TestCaseLogoTrackingContainer.cs | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs index 8b70a34c85..088a46d5e4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs @@ -35,7 +35,6 @@ namespace osu.Game.Tests.Visual.UserInterface }; private OsuLogo logo; - private readonly Bindable uiScale = new Bindable(); private TestLogoTrackingContainer trackingContainer; private Container transferContainer; private Box visualBox; @@ -45,13 +44,6 @@ namespace osu.Game.Tests.Visual.UserInterface private const float visual_box_size = 72; - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - config.BindWith(OsuSetting.UIScale, uiScale); - AddSliderStep("Adjust scale", 0.8f, 1.5f, 1f, v => uiScale.Value = v); - } - [SetUpSteps] public void SetUpSteps() { @@ -69,7 +61,7 @@ namespace osu.Game.Tests.Visual.UserInterface /// Check if the logo is still tracking the facade. /// [Test] - public void MoveFacadeTest() + public void TestMoveFacade() { AddToggleStep("Toggle move continuously", b => randomPositions = b); AddStep("Add tracking containers", addFacadeContainers); @@ -82,7 +74,7 @@ namespace osu.Game.Tests.Visual.UserInterface /// Check if the facade is removed from the container, the logo stops tracking. /// [Test] - public void RemoveFacadeTest() + public void TestRemoveFacade() { AddStep("Add tracking containers", addFacadeContainers); AddStep("Move facade to random position", moveLogoFacade); @@ -95,7 +87,7 @@ namespace osu.Game.Tests.Visual.UserInterface /// Check if the facade gets added to a new container, tracking starts on the new facade. /// [Test] - public void TransferFacadeTest() + public void TestTransferFacade() { AddStep("Add tracking containers", addFacadeContainers); AddStep("Move facade to random position", moveLogoFacade); @@ -106,6 +98,7 @@ namespace osu.Game.Tests.Visual.UserInterface transferContainerBox.Colour = Color4.Tomato; moveLogoFacade(); }); + waitForMove(); AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking); } @@ -114,7 +107,7 @@ namespace osu.Game.Tests.Visual.UserInterface /// Add a facade to a flow container, move the logo to the center of the screen, then start tracking on the facade. /// [Test] - public void FlowContainerTest() + public void TestFlowContainer() { FillFlowContainer flowContainer; @@ -188,14 +181,16 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void SetFacadeSizeTest() + public void TestSetFacadeSize() { bool failed = false; + AddStep("Set up scenario", () => { failed = false; addFacadeContainers(); }); + AddStep("Try setting facade size", () => { try @@ -208,14 +203,16 @@ namespace osu.Game.Tests.Visual.UserInterface failed = true; } }); + AddAssert("Exception thrown", () => failed); } [Test] - public void SetMultipleContainersTest() + public void TestSetMultipleContainers() { bool failed = false; LogoTrackingContainer newContainer = new LogoTrackingContainer(); + AddStep("Set up scenario", () => { failed = false; @@ -223,6 +220,7 @@ namespace osu.Game.Tests.Visual.UserInterface addFacadeContainers(); moveLogoFacade(); }); + AddStep("Try tracking new container", () => { try @@ -235,6 +233,7 @@ namespace osu.Game.Tests.Visual.UserInterface failed = true; } }); + AddAssert("Exception thrown", () => failed); } From c145ce2d005ac723d1625fab276d23cc4384855d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Apr 2019 17:19:55 +0900 Subject: [PATCH 0566/5608] Remove usings --- .../Visual/UserInterface/TestCaseLogoTrackingContainer.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs index 088a46d5e4..e45e2e24da 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs @@ -4,15 +4,12 @@ using System; using System.Collections.Generic; using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.MathUtils; using osu.Framework.Testing; -using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osu.Game.Screens.Menu; using osu.Game.Screens.Play; From 12b6bc48bd780a20b563f7c45cd9c8e5662e7c19 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Apr 2019 17:24:09 +0900 Subject: [PATCH 0567/5608] Use .With() wherever possible --- osu.Game/Screens/Menu/ButtonSystem.cs | 3 +-- osu.Game/Screens/Play/PlayerLoader.cs | 9 +++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index f6778691bf..519fadb34b 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -101,11 +101,10 @@ namespace osu.Game.Screens.Menu { VisibleState = ButtonSystemState.Play, }, - logoTrackingContainer.LogoFacade + logoTrackingContainer.LogoFacade.With(d => d.Scale = new Vector2(0.74f)) }); buttonArea.Flow.CentreTarget = logoTrackingContainer.LogoFacade; - logoTrackingContainer.LogoFacade.Scale = new Vector2(0.74f); } [Resolved(CanBeNull = true)] diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 7ff214c607..6a55fe278b 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -351,9 +351,6 @@ namespace osu.Game.Screens.Play { var metadata = beatmap.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); - facade.Anchor = Anchor.TopCentre; - facade.Origin = Anchor.TopCentre; - AutoSizeAxes = Axes.Both; Children = new Drawable[] { @@ -365,7 +362,11 @@ namespace osu.Game.Screens.Play Direction = FillDirection.Vertical, Children = new[] { - facade, + facade.With(d => + { + d.Anchor = Anchor.TopCentre; + d.Origin = Anchor.TopCentre; + }), new OsuSpriteText { Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)), From d1799d197ddc5d0beee07edb14f5bac7537d039a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Apr 2019 09:27:30 +0800 Subject: [PATCH 0568/5608] Update resources and mods usage --- osu.Game.Rulesets.Osu.Tests/TestCaseOsuFlashlight.cs | 3 ++- osu.Game/osu.Game.csproj | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseOsuFlashlight.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseOsuFlashlight.cs index 6f198084f5..1e72591b87 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseOsuFlashlight.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseOsuFlashlight.cs @@ -11,7 +11,8 @@ namespace osu.Game.Rulesets.Osu.Tests { protected override Player CreatePlayer(Ruleset ruleset) { - Beatmap.Value.Mods.Value = new Mod[] { new OsuModAutoplay(), new OsuModFlashlight(), }; + Mods.Value = new Mod[] { new OsuModAutoplay(), new OsuModFlashlight(), }; + return base.CreatePlayer(ruleset); } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 1fcbe7c4c1..25a98c9b74 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + From dfa5beea89ef6e2f7398723cf60ae386fd2bf738 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 18 Apr 2019 14:24:19 +0900 Subject: [PATCH 0569/5608] Use the actual scale of Flashlight for FlashlightSize --- osu.Game/Rulesets/Mods/ModFlashlight.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index b5a907c0ef..22c2f6dd51 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.MatrixExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.OpenGL.Vertices; using osu.Framework.Graphics.Primitives; @@ -79,7 +80,7 @@ namespace osu.Game.Rulesets.Mods flashNode.Shader = shader; flashNode.ScreenSpaceDrawQuad = ScreenSpaceDrawQuad; flashNode.FlashlightPosition = Vector2Extensions.Transform(FlashlightPosition, DrawInfo.Matrix); - flashNode.FlashlightSize = Vector2Extensions.Transform(FlashlightSize, DrawInfo.Matrix); + flashNode.FlashlightSize = FlashlightSize * DrawInfo.Matrix.ExtractScale().Xy; flashNode.FlashlightDim = FlashlightDim; } From 037e23247f766ce5d0bc71eeeaac4f4787f99dfe Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 18 Apr 2019 14:31:47 +0900 Subject: [PATCH 0570/5608] Remove unused using --- osu.Game/Rulesets/Mods/ModFlashlight.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 22c2f6dd51..c0816b2457 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.MatrixExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.OpenGL.Vertices; using osu.Framework.Graphics.Primitives; From 9d6912a6920848036a617f241c4c4ff154e04149 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Apr 2019 21:23:40 +0800 Subject: [PATCH 0571/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 1fcbe7c4c1..2b7ded6d8c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 831f33f0b8..958191d708 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From c8d760b555b52265f0cf2dc3f3ec3832ead211e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Apr 2019 21:33:29 +0800 Subject: [PATCH 0572/5608] Attempt using previous appveyor image --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 1f485485da..4dcaa7b45e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ clone_depth: 1 version: '{branch}-{build}' -image: Visual Studio 2017 +image: Previous Visual Studio 2017 test: off install: - cmd: git submodule update --init --recursive --depth=5 From 7a0320d39e29c66824a04ef7b6e06a4aaa35cfe9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 19 Apr 2019 00:01:26 +0800 Subject: [PATCH 0573/5608] Increase diagnostic level --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4dcaa7b45e..51e946219f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,8 +1,8 @@ clone_depth: 1 version: '{branch}-{build}' -image: Previous Visual Studio 2017 +image: Visual Studio 2017 test: off install: - cmd: git submodule update --init --recursive --depth=5 build_script: - - cmd: PowerShell -Version 2.0 .\build.ps1 + - cmd: PowerShell -Version 2.0 .\build.ps1 -Verbosity Diagnostic From 6502e26d09020a3ee564b40e74e0fa937aca70ea Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 19 Apr 2019 16:21:15 +0900 Subject: [PATCH 0574/5608] Add draw size invalidation to ZoomableScrollContainer --- .../Components/Timeline/ZoomableScrollContainer.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index 1e94a20dc7..f41b3cddc0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -92,13 +92,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } - protected override void Update() - { - base.Update(); - - zoomedContent.Width = DrawWidth * currentZoom; - } - protected override bool OnScroll(ScrollEvent e) { if (e.IsPrecise) @@ -169,6 +162,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline float targetOffset = expectedWidth * (focusPoint / contentSize) - focusOffset; d.currentZoom = newZoom; + + d.zoomedContent.Width = d.DrawWidth * d.currentZoom; + // Temporarily here to make sure ScrollTo gets the correct DrawSize for scrollable area. + // TODO: Make sure draw size gets invalidated properly on the framework side, and remove this once it is. + d.Invalidate(Invalidation.DrawSize); d.ScrollTo(targetOffset, false); } From d3920d652d82b1d7603bec9e94ba9f9500d9879e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 19 Apr 2019 12:44:57 +0900 Subject: [PATCH 0575/5608] Fix loader animation test case --- osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs b/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs index df12e14891..eb275cbceb 100644 --- a/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs +++ b/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs @@ -23,7 +23,11 @@ namespace osu.Game.Tests.Visual.Menus public TestCaseLoaderAnimation() { - Child = logo = new OsuLogo { Depth = float.MinValue }; + Child = logo = new OsuLogo + { + Alpha = 0, + Depth = float.MinValue + }; } [Test] @@ -39,7 +43,7 @@ namespace osu.Game.Tests.Visual.Menus LoadScreen(loader); }); - AddAssert("loaded", () => + AddUntilStep("loaded", () => { logoVisible = loader.Logo?.Alpha > 0; return loader.Logo != null && loader.ScreenLoaded; From 489929d25ce7eb0907ee8a848a5aa3094c22bde1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 19 Apr 2019 19:45:17 +0900 Subject: [PATCH 0576/5608] Fix PlayerLoader testcase being completely broken --- .../Visual/Gameplay/TestCasePlayerLoader.cs | 48 +++++++------------ 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs index f58c0d35b3..1f0a97cc58 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs @@ -10,21 +10,25 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; using osu.Game.Screens; using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual.Gameplay { public class TestCasePlayerLoader : ManualInputManagerTestCase { private PlayerLoader loader; - private readonly OsuScreenStack stack; + private OsuScreenStack stack; - public TestCasePlayerLoader() + [SetUp] + public void Setup() => Schedule(() => { - InputManager.Add(stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }); - } + InputManager.Child = stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }; + Beatmap.Value = new TestWorkingBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo), Clock); + }); [Test] public void TestLoadContinuation() @@ -33,8 +37,6 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen()); - AddStep("exit loader", () => loader.Exit()); - AddUntilStep("wait for no longer alive", () => !loader.IsAlive); AddStep("load slow dummy beatmap", () => { SlowLoadPlayer slow = null; @@ -58,41 +60,25 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("load player", () => { Mods.Value = new[] { gameMod = new TestMod() }; - InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre); - stack.Push(new PlayerLoader(() => player = new TestPlayer())); - }); - - AddUntilStep("wait for player to become current", () => - { - if (player.IsCurrentScreen()) - { - playerMod1 = (TestMod)player.Mods.Value.Single(); - return true; - } - - return false; + stack.Push(loader = new PlayerLoader(() => player = new TestPlayer())); }); + AddUntilStep("wait for loader to become current", () => loader.IsCurrentScreen()); + AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); + AddUntilStep("wait for player to be current", () => player.IsCurrentScreen()); + AddStep("retrieve mods", () => playerMod1 = (TestMod)player.Mods.Value.Single()); AddAssert("game mods not applied", () => gameMod.Applied == false); AddAssert("player mods applied", () => playerMod1.Applied); AddStep("restart player", () => { + var lastPlayer = player; player = null; - player.Restart(); - }); - - AddUntilStep("wait for player to become current", () => - { - if (player.IsCurrentScreen()) - { - playerMod2 = (TestMod)player.Mods.Value.Single(); - return true; - } - - return false; + lastPlayer.Restart(); }); + AddUntilStep("wait for player to be current", () => player.IsCurrentScreen()); + AddStep("retrieve mods", () => playerMod2 = (TestMod)player.Mods.Value.Single()); AddAssert("game mods not applied", () => gameMod.Applied == false); AddAssert("player has different mods", () => playerMod1 != playerMod2); AddAssert("player mods applied", () => playerMod2.Applied); From 5989cf284904b5affa224656412a9b687f1f880d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 19 Apr 2019 20:39:25 +0900 Subject: [PATCH 0577/5608] Revert "Increase diagnostic level" This reverts commit 7a0320d39e29c66824a04ef7b6e06a4aaa35cfe9. --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 51e946219f..4dcaa7b45e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,8 +1,8 @@ clone_depth: 1 version: '{branch}-{build}' -image: Visual Studio 2017 +image: Previous Visual Studio 2017 test: off install: - cmd: git submodule update --init --recursive --depth=5 build_script: - - cmd: PowerShell -Version 2.0 .\build.ps1 -Verbosity Diagnostic + - cmd: PowerShell -Version 2.0 .\build.ps1 From 4cf234295c67e05bc598299e70212bf55f7ceb9f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 19 Apr 2019 21:27:24 +0900 Subject: [PATCH 0578/5608] Fix appveyor temporarily --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 1f485485da..4dcaa7b45e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ clone_depth: 1 version: '{branch}-{build}' -image: Visual Studio 2017 +image: Previous Visual Studio 2017 test: off install: - cmd: git submodule update --init --recursive --depth=5 From 65d664425bdfeca60343863d1ef441a7ade7a389 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 12 Apr 2019 23:13:13 +0200 Subject: [PATCH 0579/5608] Added DiscordRichPresence to osu.Desktop packages --- osu.Desktop/osu.Desktop.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 66db439c82..7a19e73be6 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -22,6 +22,7 @@ + From 533afaa770be793be46f9948b7168e469f33431f Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 13 Apr 2019 13:06:53 +0200 Subject: [PATCH 0580/5608] Added DiscordRichPresenceClient --- osu.Desktop/DiscordRichPresenceClient.cs | 106 +++++++++++++++++++++++ osu.Desktop/OsuGameDesktop.cs | 2 + 2 files changed, 108 insertions(+) create mode 100644 osu.Desktop/DiscordRichPresenceClient.cs diff --git a/osu.Desktop/DiscordRichPresenceClient.cs b/osu.Desktop/DiscordRichPresenceClient.cs new file mode 100644 index 0000000000..03b2884ab6 --- /dev/null +++ b/osu.Desktop/DiscordRichPresenceClient.cs @@ -0,0 +1,106 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using DiscordRPC; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Logging; +using osu.Game.Online.API; +using osu.Game.Rulesets; +using osu.Game.Users; +using User = osu.Game.Users.User; + +namespace osu.Desktop +{ + internal class DiscordRichPresenceClient : Component + { + private const string client_id = "559391129716391967"; + + private Bindable user; + + private readonly DiscordRpcClient client = new DiscordRpcClient(client_id); + + [BackgroundDependencyLoader] + private void load(IAPIProvider provider) + { + user = provider.LocalUser.GetBoundCopy(); + + user.ValueChanged += usr => + { + usr.OldValue.Status.ValueChanged -= updateStatus; + usr.NewValue.Status.ValueChanged += updateStatus; + }; + + user.Value.Status.ValueChanged += updateStatus; + + client.OnReady += (_, __) => Logger.Log("Discord RPC Client ready.", LoggingTarget.Network, LogLevel.Debug); + client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client : {e.Message}", LoggingTarget.Network, LogLevel.Debug); + client.OnConnectionFailed += (_, e) => Logger.Log("Discord RPC Client failed to initialize : is discord running ?", LoggingTarget.Network, LogLevel.Debug); + client.OnPresenceUpdate += (_, __) => Logger.Log("Updated Discord Rich Presence", LoggingTarget.Network, LogLevel.Debug); + + client.Initialize(); + } + + private void updateStatus(ValueChangedEvent e) + { + var presence = defaultPresence(e.NewValue.Message); + + switch (e.NewValue) + { + case UserStatusSoloGame game: + presence.State = $"{game.Beatmap.Metadata.Artist} - {game.Beatmap.Metadata.Title} [{game.Beatmap.Version}]"; + setPresenceGamemode(game.Beatmap.Ruleset, presence); + break; + + case UserStatusEditing editing: + presence.State = $"{editing.Beatmap.Metadata.Artist} - {editing.Beatmap.Metadata.Title}" + (editing.Beatmap.Version != null ? $"[{editing.Beatmap.Version}]" : ""); + break; + } + + client.SetPresence(presence); + } + + private void setPresenceGamemode(RulesetInfo ruleset, RichPresence presence) + { + switch (ruleset.ID) + { + case 0: + presence.Assets.SmallImageKey = "osu"; + break; + + case 1: + presence.Assets.SmallImageKey = "taiko"; + break; + + case 2: + presence.Assets.SmallImageKey = "fruits"; + break; + + case 3: + presence.Assets.SmallImageKey = "mania"; + break; + } + + presence.Assets.SmallImageText = ruleset.ShortName; + } + + private RichPresence defaultPresence(string status) => new RichPresence + { + Details = status, + Assets = new Assets + { + LargeImageKey = "lazer", + LargeImageText = "osu!lazer" + } + }; + + protected override void Update() + { + if (client.IsInitialized) + client?.Invoke(); + + base.Update(); + } + } +} diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index e7e0af7eea..41e2efd011 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -64,6 +64,8 @@ namespace osu.Desktop else Add(new SimpleUpdateManager()); } + + Add(new DiscordRichPresenceClient()); } protected override void ScreenChanged(IScreen lastScreen, IScreen newScreen) From 4996ad4b042c73de5919818c2a047f19b701c75b Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 13 Apr 2019 13:25:52 +0200 Subject: [PATCH 0581/5608] Show the current gamemode on the rich presence --- osu.Desktop/DiscordRichPresenceClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/DiscordRichPresenceClient.cs b/osu.Desktop/DiscordRichPresenceClient.cs index 03b2884ab6..1e7c1f051a 100644 --- a/osu.Desktop/DiscordRichPresenceClient.cs +++ b/osu.Desktop/DiscordRichPresenceClient.cs @@ -50,7 +50,7 @@ namespace osu.Desktop { case UserStatusSoloGame game: presence.State = $"{game.Beatmap.Metadata.Artist} - {game.Beatmap.Metadata.Title} [{game.Beatmap.Version}]"; - setPresenceGamemode(game.Beatmap.Ruleset, presence); + setPresenceGamemode(game.Ruleset, presence); break; case UserStatusEditing editing: From 1b1ebb7fd928f0651e7c2777ce0807e47961ea54 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 14 Apr 2019 21:12:10 +0200 Subject: [PATCH 0582/5608] Show current logged-in user on rich presence --- osu.Desktop/DiscordRichPresenceClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/DiscordRichPresenceClient.cs b/osu.Desktop/DiscordRichPresenceClient.cs index 1e7c1f051a..1f4d91dbdb 100644 --- a/osu.Desktop/DiscordRichPresenceClient.cs +++ b/osu.Desktop/DiscordRichPresenceClient.cs @@ -91,7 +91,7 @@ namespace osu.Desktop Assets = new Assets { LargeImageKey = "lazer", - LargeImageText = "osu!lazer" + LargeImageText = user.Value.Username } }; From b38160177af31069b0c5377a7d1c8eaa92fe945e Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 14 Apr 2019 22:18:57 +0200 Subject: [PATCH 0583/5608] Add some more icons to rich presence + prevent rich presence from displaying empty brackets when current beatmap doesn't have a version (trying to edit osu! main menu theme music ?) --- osu.Desktop/DiscordRichPresenceClient.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/DiscordRichPresenceClient.cs b/osu.Desktop/DiscordRichPresenceClient.cs index 1f4d91dbdb..93c2a8bdcf 100644 --- a/osu.Desktop/DiscordRichPresenceClient.cs +++ b/osu.Desktop/DiscordRichPresenceClient.cs @@ -15,7 +15,7 @@ namespace osu.Desktop { internal class DiscordRichPresenceClient : Component { - private const string client_id = "559391129716391967"; + private const string client_id = "563024054391537674"; private Bindable user; @@ -54,7 +54,9 @@ namespace osu.Desktop break; case UserStatusEditing editing: - presence.State = $"{editing.Beatmap.Metadata.Artist} - {editing.Beatmap.Metadata.Title}" + (editing.Beatmap.Version != null ? $"[{editing.Beatmap.Version}]" : ""); + presence.State = $"{editing.Beatmap.Metadata.Artist} - {editing.Beatmap.Metadata.Title} " + (!string.IsNullOrEmpty(editing.Beatmap.Version) ? $"[{editing.Beatmap.Version}]" : ""); + presence.Assets.SmallImageKey = "edit"; + presence.Assets.SmallImageText = "editing"; break; } @@ -80,6 +82,10 @@ namespace osu.Desktop case 3: presence.Assets.SmallImageKey = "mania"; break; + + default: + presence.Assets.SmallImageKey = "unknown"; + break; } presence.Assets.SmallImageText = ruleset.ShortName; From a4166ce1e3991ba23a7bac15bf10ca860dace0f1 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 19 Apr 2019 19:50:13 +0200 Subject: [PATCH 0584/5608] Removed Update() override from DiscordRichPresenceClient because client.Invoke() is unecessary (events callbacks are automatically called) --- osu.Desktop/DiscordRichPresenceClient.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/osu.Desktop/DiscordRichPresenceClient.cs b/osu.Desktop/DiscordRichPresenceClient.cs index 93c2a8bdcf..9288141e5f 100644 --- a/osu.Desktop/DiscordRichPresenceClient.cs +++ b/osu.Desktop/DiscordRichPresenceClient.cs @@ -100,13 +100,5 @@ namespace osu.Desktop LargeImageText = user.Value.Username } }; - - protected override void Update() - { - if (client.IsInitialized) - client?.Invoke(); - - base.Update(); - } } } From 8e485f32835d6d0c72b9e04d52c3ab1b42879b8c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 20 Apr 2019 06:41:09 +0300 Subject: [PATCH 0585/5608] Fix issue --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index f3c7939a94..9e3f28918c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osuTK; using osuTK.Graphics; @@ -40,6 +41,10 @@ namespace osu.Game.Rulesets.Osu.Mods { scoreProcessor.Health.ValueChanged += health => { blinds.AnimateClosedness((float)health.NewValue); }; } + + public ScoreRank AdjustRank(ScoreRank rank) + { + } /// /// Element for the Blinds mod drawing 2 black boxes covering the whole screen which resize inside a restricted area with some leniency. From 59da78b0d4fd31a3df67b77d973fc66fbc0a94f7 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 20 Apr 2019 06:44:59 +0300 Subject: [PATCH 0586/5608] nothing. --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 9e3f28918c..f3c7939a94 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -12,7 +12,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; -using osu.Game.Scoring; using osuTK; using osuTK.Graphics; @@ -41,10 +40,6 @@ namespace osu.Game.Rulesets.Osu.Mods { scoreProcessor.Health.ValueChanged += health => { blinds.AnimateClosedness((float)health.NewValue); }; } - - public ScoreRank AdjustRank(ScoreRank rank) - { - } /// /// Element for the Blinds mod drawing 2 black boxes covering the whole screen which resize inside a restricted area with some leniency. From 6f2bc943eb57c0a0ec97de5053c1d9cbd91249d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 21 Apr 2019 12:04:15 +0800 Subject: [PATCH 0587/5608] Fix rank display on break info display --- osu.Game/Screens/Play/Break/BreakInfoLine.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index 4b07405812..70e7b8f297 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -1,8 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -60,7 +62,13 @@ namespace osu.Game.Screens.Play.Break valueText.Text = newText; } - protected virtual string Format(T count) => count.ToString(); + protected virtual string Format(T count) + { + if (count is Enum countEnum) + return countEnum.GetDescription(); + + return count.ToString(); + } [BackgroundDependencyLoader] private void load(OsuColour colours) From 30d4dd93558f00bb806612040568e3827ec41d3e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 21 Apr 2019 21:38:12 +0900 Subject: [PATCH 0588/5608] Change + rank strings to be cleaner for the end-user --- osu.Game/Scoring/ScoreRank.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreRank.cs b/osu.Game/Scoring/ScoreRank.cs index 82c33748bb..a93d015f1b 100644 --- a/osu.Game/Scoring/ScoreRank.cs +++ b/osu.Game/Scoring/ScoreRank.cs @@ -25,13 +25,13 @@ namespace osu.Game.Scoring [Description(@"S")] S, - [Description(@"SPlus")] + [Description(@"S+")] SH, [Description(@"SS")] X, - [Description(@"SSPlus")] + [Description(@"SS+")] XH, } } From 73da4236391df7209c476ff769faf2a480e8f20b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 21 Apr 2019 15:58:19 +0300 Subject: [PATCH 0589/5608] Adjust rank --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 0fddb19a6c..4a1eba9c5e 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -95,6 +95,11 @@ namespace osu.Game.Rulesets.Scoring /// protected virtual bool DefaultFailCondition => Health.Value == Health.MinValue; + /// + /// Used by specific mods to adjust . + /// + public bool AdjustRank { get; set; } + protected ScoreProcessor() { Combo.ValueChanged += delegate { HighestCombo.Value = Math.Max(HighestCombo.Value, Combo.Value); }; @@ -104,9 +109,9 @@ namespace osu.Game.Rulesets.Scoring private ScoreRank rankFrom(double acc) { if (acc == 1) - return ScoreRank.X; + return (AdjustRank ? ScoreRank.XH : ScoreRank.X); if (acc > 0.95) - return ScoreRank.S; + return (AdjustRank ? ScoreRank.SH : ScoreRank.S); if (acc > 0.9) return ScoreRank.A; if (acc > 0.8) From 4e07975e7ca88c49d4c4fa83206bc27d254e7456 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 21 Apr 2019 15:58:40 +0300 Subject: [PATCH 0590/5608] Ranks must be adjusted in Hidden Mod --- osu.Game/Rulesets/Mods/ModHidden.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index c7e3f0a78f..744da30f0a 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -8,10 +8,11 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModHidden : Mod, IReadFromConfig, IApplicableToDrawableHitObjects + public abstract class ModHidden : Mod, IReadFromConfig, IApplicableToDrawableHitObjects, IApplicableToScoreProcessor { public override string Name => "Hidden"; public override string Acronym => "HD"; @@ -31,6 +32,11 @@ namespace osu.Game.Rulesets.Mods foreach (var d in drawables.Skip(IncreaseFirstObjectVisibility.Value ? 1 : 0)) d.ApplyCustomUpdateState += ApplyHiddenState; } + + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + { + scoreProcessor.AdjustRank = true; + } protected virtual void ApplyHiddenState(DrawableHitObject hitObject, ArmedState state) { From 77614189c978e4bffa18b4dee16dbfa90351944c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 21 Apr 2019 17:48:50 +0300 Subject: [PATCH 0591/5608] Make AdjustRank Bindable --- osu.Game/Rulesets/Mods/ModHidden.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index 744da30f0a..4c4177a779 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Mods public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { - scoreProcessor.AdjustRank = true; + scoreProcessor.AdjustRank.Value = true; } protected virtual void ApplyHiddenState(DrawableHitObject hitObject, ArmedState state) From b200142afb174e4c16a64403cb23575ab3692fd3 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 21 Apr 2019 17:55:01 +0300 Subject: [PATCH 0592/5608] Make AdjustRank Bindable and fix issue --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 4a1eba9c5e..617e643d41 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -98,20 +98,21 @@ namespace osu.Game.Rulesets.Scoring /// /// Used by specific mods to adjust . /// - public bool AdjustRank { get; set; } + public BindableBool AdjustRank = new BindableBool(); protected ScoreProcessor() { Combo.ValueChanged += delegate { HighestCombo.Value = Math.Max(HighestCombo.Value, Combo.Value); }; Accuracy.ValueChanged += delegate { Rank.Value = rankFrom(Accuracy.Value); }; + AdjustRank.ValueChanged += delegate { Rank.Value = rankFrom(Accuracy.Value); }; // Update rank immediately if AdjustRank was changed } private ScoreRank rankFrom(double acc) { if (acc == 1) - return (AdjustRank ? ScoreRank.XH : ScoreRank.X); + return (AdjustRank.Value ? ScoreRank.XH : ScoreRank.X); if (acc > 0.95) - return (AdjustRank ? ScoreRank.SH : ScoreRank.S); + return (AdjustRank.Value ? ScoreRank.SH : ScoreRank.S); if (acc > 0.9) return ScoreRank.A; if (acc > 0.8) @@ -128,6 +129,7 @@ namespace osu.Game.Rulesets.Scoring /// Whether to store the current state of the for future use. protected virtual void Reset(bool storeResults) { + AdjustRank.Value = false; TotalScore.Value = 0; Accuracy.Value = 1; Health.Value = 1; From c5bf01cc5ccaf8a53f57fce21cc1fb16cf6cfc0b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 21 Apr 2019 18:05:52 +0300 Subject: [PATCH 0593/5608] Fix issue --- osu.Game/Rulesets/Mods/ModHidden.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index 4c4177a779..b36b2362ca 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Mods foreach (var d in drawables.Skip(IncreaseFirstObjectVisibility.Value ? 1 : 0)) d.ApplyCustomUpdateState += ApplyHiddenState; } - + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { scoreProcessor.AdjustRank.Value = true; From cff319e0d8cd22d12f7e44a4754cca2a2f8051ec Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 21 Apr 2019 18:12:50 +0300 Subject: [PATCH 0594/5608] Fix issue --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 617e643d41..e60ca70969 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Scoring protected virtual bool DefaultFailCondition => Health.Value == Health.MinValue; /// - /// Used by specific mods to adjust . + /// Used by specific mods to adjust . /// public BindableBool AdjustRank = new BindableBool(); From ae51a9e45122e453dcfc49bb237c55882854b140 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Apr 2019 09:57:33 +0900 Subject: [PATCH 0595/5608] Fix drawable rank texture lookup --- osu.Game/Online/Leaderboards/DrawableRank.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs index 9155df69b4..5224150181 100644 --- a/osu.Game/Online/Leaderboards/DrawableRank.cs +++ b/osu.Game/Online/Leaderboards/DrawableRank.cs @@ -43,7 +43,21 @@ namespace osu.Game.Online.Leaderboards private void updateTexture() { - rankSprite.Texture = textures.Get($@"Grades/{Rank.GetDescription()}"); + string textureName; + switch (Rank) + { + default: + textureName = Rank.GetDescription(); + break; + case ScoreRank.SH: + textureName = "SPlus"; + break; + case ScoreRank.XH: + textureName = "SSPlus"; + break; + } + + rankSprite.Texture = textures.Get($@"Grades/{textureName}"); } public void UpdateRank(ScoreRank newRank) From 732c38fa794a81ab3c2b2e8be8a9abec8f189f89 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Apr 2019 10:45:56 +0900 Subject: [PATCH 0596/5608] Update framework again --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 2b7ded6d8c..a45cac2cb6 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 958191d708..70edc01821 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 8ffb2f4224d5ba340fa6e42dd3518edbd938df2d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Apr 2019 10:55:01 +0900 Subject: [PATCH 0597/5608] Remove black box blocking some visual tests from being visible --- osu.Game/Tests/Visual/AllPlayersTestCase.cs | 9 --------- osu.Game/Tests/Visual/PlayerTestCase.cs | 15 --------------- 2 files changed, 24 deletions(-) diff --git a/osu.Game/Tests/Visual/AllPlayersTestCase.cs b/osu.Game/Tests/Visual/AllPlayersTestCase.cs index af190ec7d5..3e1f408a16 100644 --- a/osu.Game/Tests/Visual/AllPlayersTestCase.cs +++ b/osu.Game/Tests/Visual/AllPlayersTestCase.cs @@ -3,7 +3,6 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Graphics.Shapes; using osu.Framework.Screens; using osu.Framework.Timing; using osu.Game.Beatmaps; @@ -11,7 +10,6 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps; -using osuTK.Graphics; namespace osu.Game.Tests.Visual { @@ -26,13 +24,6 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - Add(new Box - { - RelativeSizeAxes = Framework.Graphics.Axes.Both, - Colour = Color4.Black, - Depth = int.MaxValue - }); - foreach (var r in rulesets.AvailableRulesets) { Player p = null; diff --git a/osu.Game/Tests/Visual/PlayerTestCase.cs b/osu.Game/Tests/Visual/PlayerTestCase.cs index 719b1d6892..d308b86b5a 100644 --- a/osu.Game/Tests/Visual/PlayerTestCase.cs +++ b/osu.Game/Tests/Visual/PlayerTestCase.cs @@ -2,16 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps; -using osuTK.Graphics; namespace osu.Game.Tests.Visual { @@ -26,17 +22,6 @@ namespace osu.Game.Tests.Visual this.ruleset = ruleset; } - [BackgroundDependencyLoader] - private void load() - { - Add(new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Depth = int.MaxValue - }); - } - [SetUpSteps] public void SetUpSteps() { From 26f0b2a4fe65342757a52476367b6ae432b10b40 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 22 Apr 2019 06:12:41 +0300 Subject: [PATCH 0598/5608] Remove bindable Bad usage --- osu.Game/Rulesets/Mods/ModHidden.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index b36b2362ca..389edb5a35 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Mods public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { - scoreProcessor.AdjustRank.Value = true; + scoreProcessor.AdjustRank = true; } protected virtual void ApplyHiddenState(DrawableHitObject hitObject, ArmedState state) From de542ca20251951df7dea4cd449018aa03b2c29d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 22 Apr 2019 06:14:14 +0300 Subject: [PATCH 0599/5608] Remove bindable and use property --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index e60ca70969..c37b5d189f 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -95,24 +95,29 @@ namespace osu.Game.Rulesets.Scoring /// protected virtual bool DefaultFailCondition => Health.Value == Health.MinValue; + private bool adjustRank = false; + /// /// Used by specific mods to adjust . /// - public BindableBool AdjustRank = new BindableBool(); + public bool AdjustRank + { + get { return adjustRank; } + set { adjustRank = value; Rank.Value = rankFrom(Accuracy.Value); } // Update rank immediately if AdjustRank was changed + } protected ScoreProcessor() { Combo.ValueChanged += delegate { HighestCombo.Value = Math.Max(HighestCombo.Value, Combo.Value); }; Accuracy.ValueChanged += delegate { Rank.Value = rankFrom(Accuracy.Value); }; - AdjustRank.ValueChanged += delegate { Rank.Value = rankFrom(Accuracy.Value); }; // Update rank immediately if AdjustRank was changed } private ScoreRank rankFrom(double acc) { if (acc == 1) - return (AdjustRank.Value ? ScoreRank.XH : ScoreRank.X); + return (adjustRank ? ScoreRank.XH : ScoreRank.X); if (acc > 0.95) - return (AdjustRank.Value ? ScoreRank.SH : ScoreRank.S); + return (adjustRank ? ScoreRank.SH : ScoreRank.S); if (acc > 0.9) return ScoreRank.A; if (acc > 0.8) @@ -129,7 +134,6 @@ namespace osu.Game.Rulesets.Scoring /// Whether to store the current state of the for future use. protected virtual void Reset(bool storeResults) { - AdjustRank.Value = false; TotalScore.Value = 0; Accuracy.Value = 1; Health.Value = 1; @@ -137,6 +141,7 @@ namespace osu.Game.Rulesets.Scoring Rank.Value = ScoreRank.X; HighestCombo.Value = 0; + AdjustRank = false; HasFailed = false; } From c784bc4418c9908099a1ecc08fb6194140743224 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 22 Apr 2019 06:15:37 +0300 Subject: [PATCH 0600/5608] Remove whitespaces --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index c37b5d189f..e563d3a848 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Scoring protected virtual bool DefaultFailCondition => Health.Value == Health.MinValue; private bool adjustRank = false; - + /// /// Used by specific mods to adjust . /// From a47f5040af2b157f58aeabc6ac9bbae97d09b0e2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 22 Apr 2019 13:58:05 +0900 Subject: [PATCH 0601/5608] Improve waveform graph testing --- .../Visual/Editor/TestCaseWaveform.cs | 79 +++++++++++++------ 1 file changed, 56 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestCaseWaveform.cs b/osu.Game.Tests/Visual/Editor/TestCaseWaveform.cs index c35e8741c1..ce6ca08a61 100644 --- a/osu.Game.Tests/Visual/Editor/TestCaseWaveform.cs +++ b/osu.Game.Tests/Visual/Editor/TestCaseWaveform.cs @@ -3,12 +3,13 @@ using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio.Track; using osu.Framework.Graphics; using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; -using osuTK; using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editor @@ -16,35 +17,38 @@ namespace osu.Game.Tests.Visual.Editor [TestFixture] public class TestCaseWaveform : OsuTestCase { + private WorkingBeatmap waveformBeatmap; + [BackgroundDependencyLoader] private void load() { - Beatmap.Value = new WaveformTestBeatmap(); + waveformBeatmap = new WaveformTestBeatmap(); + } - FillFlowContainer flow; - Child = flow = new FillFlowContainer + [TestCase(1f)] + [TestCase(1f / 2)] + [TestCase(1f / 4)] + [TestCase(1f / 8)] + [TestCase(1f / 16)] + [TestCase(0f)] + public void TestResolution(float resolution) + { + TestWaveformGraph graph = null; + + AddStep("add graph", () => { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 10), - }; - - for (int i = 1; i <= 16; i *= 2) - { - var newDisplay = new WaveformGraph - { - RelativeSizeAxes = Axes.Both, - Resolution = 1f / i, - Waveform = Beatmap.Value.Waveform, - }; - - flow.Add(new Container + Child = new Container { RelativeSizeAxes = Axes.X, Height = 100, Children = new Drawable[] { - newDisplay, + graph = new TestWaveformGraph + { + RelativeSizeAxes = Axes.Both, + Resolution = resolution, + Waveform = waveformBeatmap.Waveform, + }, new Container { Anchor = Anchor.Centre, @@ -62,13 +66,42 @@ namespace osu.Game.Tests.Visual.Editor { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Text = $"Resolution: {1f / i:0.00}" + Text = $"Resolution: {resolution:0.00}" } } } } - }); - } + }; + }); + + AddUntilStep("wait for load", () => graph.ResampledWaveform != null); + } + + [Test] + public void TestDefaultBeatmap() + { + TestWaveformGraph graph = null; + + AddStep("add graph", () => + { + Child = new Container + { + RelativeSizeAxes = Axes.X, + Height = 100, + Child = graph = new TestWaveformGraph + { + RelativeSizeAxes = Axes.Both, + Waveform = new DummyWorkingBeatmap().Waveform, + }, + }; + }); + + AddUntilStep("wait for load", () => graph.ResampledWaveform != null); + } + + public class TestWaveformGraph : WaveformGraph + { + public new Waveform ResampledWaveform => base.ResampledWaveform; } } } From 7a385e56ecd0089689ce63d145eb5fbd44a8f5da Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 22 Apr 2019 09:58:29 +0300 Subject: [PATCH 0602/5608] Fix AppVeyor Errors --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index e563d3a848..99178409fb 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -95,15 +95,20 @@ namespace osu.Game.Rulesets.Scoring /// protected virtual bool DefaultFailCondition => Health.Value == Health.MinValue; - private bool adjustRank = false; + private bool adjustRank; /// /// Used by specific mods to adjust . /// public bool AdjustRank { - get { return adjustRank; } - set { adjustRank = value; Rank.Value = rankFrom(Accuracy.Value); } // Update rank immediately if AdjustRank was changed + get => return adjustRank; + + set + { + adjustRank = value; + Rank.Value = rankFrom(Accuracy.Value); // Update rank immediately if AdjustRank was changed + } } protected ScoreProcessor() From 3c252d79ead8fc1e7a13e8d12b3210bce989d402 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 22 Apr 2019 15:59:47 +0900 Subject: [PATCH 0603/5608] Use var, rework dim application logic --- .../Mods/OsuModFlashlight.cs | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 5d136e4cbe..b2bc5f4320 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; @@ -27,9 +28,9 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToDrawableHitObjects(IEnumerable drawables) { - foreach (DrawableSlider drawable in drawables.OfType()) + foreach (var s in drawables.OfType()) { - drawable.Tracking.ValueChanged += flashlight.OnSliderTrackingChange; + s.Tracking.ValueChanged += flashlight.OnSliderTrackingChange; } } @@ -44,13 +45,28 @@ namespace osu.Game.Rulesets.Osu.Mods public void OnSliderTrackingChange(ValueChangedEvent e) { + // If any sliders are in a tracking state, apply a dim to the entire playfield over a brief duration. if (e.NewValue) + { trackingSliders++; + // This check being here ensures we're only applying a dim if and only if a slider begins tracking. + if (trackingSliders == 1) + { + this.TransformTo(nameof(FlashlightDim), 0.8f, 50); + } + } else + { trackingSliders--; - // If there are any sliders in a tracking state, apply a dim to the entire playfield over a brief duration. - this.TransformTo(nameof(FlashlightDim), trackingSliders > 0 ? 0.8f : 0.0f, 50); + if (trackingSliders == 0) + { + this.TransformTo(nameof(FlashlightDim), 0.0f, 50); + } + } + + if (trackingSliders < 0) + throw new InvalidOperationException($"The number of {nameof(trackingSliders)} cannot be below 0."); } protected override bool OnMouseMove(MouseMoveEvent e) From 64429aa96877c96ca67f53d6a95b0b98085fe425 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 22 Apr 2019 09:59:51 +0300 Subject: [PATCH 0604/5608] Fix AppVeyor Errors --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 99178409fb..fc7e8746b7 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Scoring public bool AdjustRank { get => return adjustRank; - + set { adjustRank = value; From 903093503041d6fd3f2061615cbc2cda56239b9d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 22 Apr 2019 10:07:45 +0300 Subject: [PATCH 0605/5608] Fix AppVeyor Errors --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index fc7e8746b7..b3e1beed04 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -104,8 +104,8 @@ namespace osu.Game.Rulesets.Scoring { get => return adjustRank; - set - { + set + { adjustRank = value; Rank.Value = rankFrom(Accuracy.Value); // Update rank immediately if AdjustRank was changed } From cfb3c38c3a086dd1d892fe471ca1c80da1e1f710 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 22 Apr 2019 10:14:19 +0300 Subject: [PATCH 0606/5608] Fix. --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index b3e1beed04..b1cd78dde6 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Scoring /// public bool AdjustRank { - get => return adjustRank; + get => adjustRank; set { From 3fbbb7dcf9901fcd5595d5e1a88d22ce667aa94e Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 22 Apr 2019 16:39:28 +0900 Subject: [PATCH 0607/5608] Move intiial fade outside of absolute sequence --- osu.Game/Rulesets/Mods/ModFlashlight.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index c0816b2457..c3ac00f3ad 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -95,10 +95,10 @@ namespace osu.Game.Rulesets.Mods Combo.ValueChanged += OnComboChange; + this.FadeInFromZero(FLASHLIGHT_FADE_DURATION); + using (BeginAbsoluteSequence(0)) { - this.FadeInFromZero(FLASHLIGHT_FADE_DURATION); - foreach (var breakPeriod in Breaks) { if (breakPeriod.Duration < FLASHLIGHT_FADE_DURATION * 2) continue; From fbb4e9df044b2e6d3d911de3846cc6140dd7ef6f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 22 Apr 2019 16:51:38 +0900 Subject: [PATCH 0608/5608] Implement hp at base ScoreProcessor --- osu.Game/Rulesets/Judgements/Judgement.cs | 5 +++++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index e14eedd3dc..f07f76a2b8 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -31,6 +31,11 @@ namespace osu.Game.Rulesets.Judgements /// public int MaxNumericResult => NumericResultFor(MaxResult); + /// + /// The health increase for the maximum achievable result. + /// + public double MaxHealthIncrease => HealthIncreaseFor(MaxResult); + /// /// Retrieves the numeric score representation of a . /// diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 0fddb19a6c..1a682080bf 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -206,6 +206,9 @@ namespace osu.Game.Rulesets.Scoring private double baseScore; private double bonusScore; + private double rollingHp; + private double rollingMaxHp; + protected ScoreProcessor() { } @@ -332,6 +335,9 @@ namespace osu.Game.Rulesets.Scoring baseScore += result.Judgement.NumericResultFor(result); rollingMaxBaseScore += result.Judgement.MaxNumericResult; } + + rollingHp += HpFactorFor(result.Judgement, result.Type) * result.Judgement.HealthIncreaseFor(result); + rollingMaxHp += HpFactorFor(result.Judgement, result.Judgement.MaxResult) * result.Judgement.MaxHealthIncrease; } /// @@ -356,8 +362,13 @@ namespace osu.Game.Rulesets.Scoring baseScore -= result.Judgement.NumericResultFor(result); rollingMaxBaseScore -= result.Judgement.MaxNumericResult; } + + rollingHp -= HpFactorFor(result.Judgement, result.Type) * result.Judgement.HealthIncreaseFor(result); + rollingMaxHp -= HpFactorFor(result.Judgement, result.Judgement.MaxResult) * result.Judgement.MaxHealthIncrease; } + protected virtual double HpFactorFor(Judgement judgement, HitResult result) => 1; + private void updateScore() { if (rollingMaxBaseScore != 0) From d7919544fe8e5e6f78fb04834c44fbb7ff721b89 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 22 Apr 2019 16:59:14 +0900 Subject: [PATCH 0609/5608] Implement approximate hp increase for catch --- .../Judgements/CatchBananaJudgement.cs | 2 +- .../Judgements/CatchDropletJudgement.cs | 4 ++-- .../Judgements/CatchJudgement.cs | 4 ++-- .../Judgements/CatchTinyDropletJudgement.cs | 2 +- .../Scoring/CatchScoreProcessor.cs | 20 ++++++++----------- 5 files changed, 14 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs index 4e64753a65..31f825c3ef 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Judgements default: return 0; case HitResult.Perfect: - return 8; + return 0.08; } } diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs index 2598dee156..f03897d611 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs @@ -23,9 +23,9 @@ namespace osu.Game.Rulesets.Catch.Judgements switch (result) { default: - return 0; + return base.HealthIncreaseFor(result); case HitResult.Perfect: - return 7; + return 0.07; } } } diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs index 5d7ef04dd2..abc38fe258 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs @@ -27,9 +27,9 @@ namespace osu.Game.Rulesets.Catch.Judgements switch (result) { default: - return 0; + return -0.02; case HitResult.Perfect: - return 10.2; + return 0.01; } } diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs index b8c51b7b60..bd1a74bc14 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Catch.Judgements default: return 0; case HitResult.Perfect: - return 4; + return 0.004; } } } diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index af614f95d0..40585f2054 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.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 osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Judgements; @@ -27,20 +26,17 @@ namespace osu.Game.Rulesets.Catch.Scoring hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate; } - private const double harshness = 0.01; - - protected override void ApplyResult(JudgementResult result) + protected override double HpFactorFor(Judgement judgement, HitResult result) { - base.ApplyResult(result); - - if (result.Type == HitResult.Miss) + switch (result) { - if (!result.Judgement.IsBonus) - Health.Value -= hpDrainRate * (harshness * 2); - return; + case HitResult.Miss when judgement.IsBonus: + return 0; + case HitResult.Miss: + return hpDrainRate; + default: + return 10 - hpDrainRate; // Award less HP as drain rate is increased } - - Health.Value += Math.Max(result.Judgement.HealthIncreaseFor(result) - hpDrainRate, 0) * harshness; } public override HitWindows CreateHitWindows() => new CatchHitWindows(); From 4c5f41e40f1646df96c8fe1b87cafbfe5e775749 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 22 Apr 2019 17:04:18 +0900 Subject: [PATCH 0610/5608] Implement hp increase for mania --- .../Judgements/HoldNoteTickJudgement.cs | 11 ++++++ .../Judgements/ManiaJudgement.cs | 21 ++++++++++ .../Scoring/ManiaScoreProcessor.cs | 38 +------------------ 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs index 015eb1310e..48c2eb547b 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs @@ -10,5 +10,16 @@ namespace osu.Game.Rulesets.Mania.Judgements public override bool AffectsCombo => false; protected override int NumericResultFor(HitResult result) => 20; + + protected override double HealthIncreaseFor(HitResult result) + { + switch (result) + { + case HitResult.Miss: + return 0; + default: + return 0.040; + } + } } } diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs index b6fb37f054..0548dc9eed 100644 --- a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs @@ -25,5 +25,26 @@ namespace osu.Game.Rulesets.Mania.Judgements return 300; } } + + protected override double HealthIncreaseFor(HitResult result) + { + switch (result) + { + case HitResult.Miss: + return -0.125; + case HitResult.Meh: + return 0.005; + case HitResult.Ok: + return 0.010; + case HitResult.Good: + return 0.035; + case HitResult.Great: + return 0.055; + case HitResult.Perfect: + return 0.065; + default: + return 0; + } + } } } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 5c914d8eac..75a73614f0 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -122,42 +122,8 @@ namespace osu.Game.Rulesets.Mania.Scoring } } - protected override void ApplyResult(JudgementResult result) - { - base.ApplyResult(result); - - bool isTick = result.Judgement is HoldNoteTickJudgement; - - if (isTick) - { - if (result.IsHit) - Health.Value += hpMultiplier * hp_increase_tick; - } - else - { - switch (result.Type) - { - case HitResult.Miss: - Health.Value += hpMissMultiplier * hp_increase_miss; - break; - case HitResult.Meh: - Health.Value += hpMultiplier * hp_increase_bad; - break; - case HitResult.Ok: - Health.Value += hpMultiplier * hp_increase_ok; - break; - case HitResult.Good: - Health.Value += hpMultiplier * hp_increase_good; - break; - case HitResult.Great: - Health.Value += hpMultiplier * hp_increase_great; - break; - case HitResult.Perfect: - Health.Value += hpMultiplier * hp_increase_perfect; - break; - } - } - } + protected override double HpFactorFor(Judgement judgement, HitResult result) + => result == HitResult.Miss ? hpMissMultiplier : hpMultiplier; public override HitWindows CreateHitWindows() => new ManiaHitWindows(); } From b59f23d0944a5aa512c2bf3096d4ef7390f32e72 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 22 Apr 2019 17:04:46 +0900 Subject: [PATCH 0611/5608] Implement hp increase for taiko --- .../Scoring/TaikoScoreProcessor.cs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 442cca49f8..a0055a93aa 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -46,19 +46,8 @@ namespace osu.Game.Rulesets.Taiko.Scoring hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120); } - protected override void ApplyResult(JudgementResult result) - { - base.ApplyResult(result); - - double hpIncrease = result.Judgement.HealthIncreaseFor(result); - - if (result.Type == HitResult.Miss) - hpIncrease *= hpMissMultiplier; - else - hpIncrease *= hpMultiplier; - - Health.Value += hpIncrease; - } + protected override double HpFactorFor(Judgement judgement, HitResult result) + => result == HitResult.Miss ? hpMissMultiplier : hpMultiplier; protected override void Reset(bool storeResults) { From 034643b8356bf2325d207ec0aab91179f402f3c7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Apr 2019 17:06:01 +0900 Subject: [PATCH 0612/5608] Fix pause tests --- osu.Game/Rulesets/UI/Playfield.cs | 5 +++++ osu.Game/Screens/Play/GameplayClockContainer.cs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 13689153f0..a99c16a610 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -68,7 +68,12 @@ namespace osu.Game.Rulesets.UI { Cursor = CreateCursor(); if (Cursor != null) + { + // initial showing of the cursor will be handed by MenuCursorContainer (via DrawableRuleset's IProvideCursor implementation). + Cursor.Hide(); + AddInternal(Cursor); + } } /// diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 29974b728e..3654dc679c 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -123,7 +123,7 @@ namespace osu.Game.Screens.Play { // Seeking the decoupled clock to its current time ensures that its source clock will be seeked to the same time // This accounts for the audio clock source potentially taking time to enter a completely stopped state - adjustableClock.Seek(adjustableClock.CurrentTime); + adjustableClock.Seek(GameplayClock.CurrentTime); adjustableClock.Start(); IsPaused.Value = false; } From b3c496d72cb6d3a381098f357edcfd940c12a8ce Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Apr 2019 17:06:40 +0900 Subject: [PATCH 0613/5608] Remove delay on entering player --- osu.Game/Screens/Play/GameplayClockContainer.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 3654dc679c..2d1ba3f2ab 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -110,11 +110,8 @@ namespace osu.Game.Screens.Play adjustableClock.ChangeSource(sourceClock); updateRate(); - this.Delay(750).Schedule(() => - { - if (!IsPaused.Value) - Start(); - }); + if (!IsPaused.Value) + Start(); }); }); } From 78c844e25930af377c3c28162c58551d03c374b8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 22 Apr 2019 17:24:22 +0900 Subject: [PATCH 0614/5608] Make catch provide some HP at DrainRate=10 --- osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 40585f2054..13c5028b23 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Catch.Scoring case HitResult.Miss: return hpDrainRate; default: - return 10 - hpDrainRate; // Award less HP as drain rate is increased + return 10.2 - hpDrainRate; // Award less HP as drain rate is increased } } From 144e6012dc333153c7e41ad37df544a23ea4b827 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 22 Apr 2019 17:24:42 +0900 Subject: [PATCH 0615/5608] Implement hp increase for osu! --- .../Judgements/OsuJudgement.cs | 15 +++++++++++ .../Scoring/OsuScoreProcessor.cs | 25 ++++++++++--------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs index 81fedf9f4a..7a98c5003d 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs @@ -24,5 +24,20 @@ namespace osu.Game.Rulesets.Osu.Judgements return 300; } } + + protected override double HealthIncreaseFor(HitResult result) + { + switch (result) + { + case HitResult.Miss: + return -0.02; + case HitResult.Meh: + case HitResult.Good: + case HitResult.Great: + return 0.01; + default: + return 0; + } + } } } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 2c8bf11016..a4975ef3b3 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -47,28 +47,29 @@ namespace osu.Game.Rulesets.Osu.Scoring if (result.Type != HitResult.None) comboResultCounts[osuResult.ComboType] = comboResultCounts.GetOrDefault(osuResult.ComboType) + 1; + } - switch (result.Type) + protected override double HpFactorFor(Judgement judgement, HitResult result) + { + switch (result) { case HitResult.Great: - Health.Value += (10.2 - hpDrainRate) * harshness; - break; + return 10.2 - hpDrainRate; case HitResult.Good: - Health.Value += (8 - hpDrainRate) * harshness; - break; + return 8 - hpDrainRate; case HitResult.Meh: - Health.Value += (4 - hpDrainRate) * harshness; - break; + return 4 - hpDrainRate; - /*case HitResult.SliderTick: - Health.Value += Math.Max(7 - hpDrainRate, 0) * 0.01; - break;*/ + // case HitResult.SliderTick: + // return Math.Max(7 - hpDrainRate, 0) * 0.01; case HitResult.Miss: - Health.Value -= hpDrainRate * (harshness * 2); - break; + return hpDrainRate; + + default: + return 0; } } From 4edb17a88a9ac82ac06fb2c7a172e4ad4bc0dc2c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 22 Apr 2019 17:51:43 +0900 Subject: [PATCH 0616/5608] Make hp work + cleanup --- .../Scoring/CatchScoreProcessor.cs | 6 +-- .../Scoring/ManiaScoreProcessor.cs | 44 +------------------ .../Scoring/OsuScoreProcessor.cs | 6 +-- .../Scoring/TaikoScoreProcessor.cs | 4 +- .../Rulesets/Judgements/JudgementResult.cs | 5 +++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 13 ++---- 6 files changed, 17 insertions(+), 61 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 13c5028b23..778a7426aa 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -26,12 +26,10 @@ namespace osu.Game.Rulesets.Catch.Scoring hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate; } - protected override double HpFactorFor(Judgement judgement, HitResult result) + protected override double HpFactorFor(JudgementResult result) { - switch (result) + switch (result.Type) { - case HitResult.Miss when judgement.IsBonus: - return 0; case HitResult.Miss: return hpDrainRate; default: diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 75a73614f0..ee4618e5c2 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -3,7 +3,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; @@ -28,36 +27,6 @@ namespace osu.Game.Rulesets.Mania.Scoring /// private const double hp_multiplier_max = 1; - /// - /// The default BAD hit HP increase. - /// - private const double hp_increase_bad = 0.005; - - /// - /// The default OK hit HP increase. - /// - private const double hp_increase_ok = 0.010; - - /// - /// The default GOOD hit HP increase. - /// - private const double hp_increase_good = 0.035; - - /// - /// The default tick hit HP increase. - /// - private const double hp_increase_tick = 0.040; - - /// - /// The default GREAT hit HP increase. - /// - private const double hp_increase_great = 0.055; - - /// - /// The default PERFECT hit HP increase. - /// - private const double hp_increase_perfect = 0.065; - /// /// The MISS HP multiplier at OD = 0. /// @@ -73,11 +42,6 @@ namespace osu.Game.Rulesets.Mania.Scoring /// private const double hp_multiplier_miss_max = 1; - /// - /// The default MISS HP increase. - /// - private const double hp_increase_miss = -0.125; - /// /// The MISS HP multiplier. This is multiplied to the miss hp increase. /// @@ -88,10 +52,6 @@ namespace osu.Game.Rulesets.Mania.Scoring /// private double hpMultiplier = 1; - public ManiaScoreProcessor() - { - } - public ManiaScoreProcessor(DrawableRuleset drawableRuleset) : base(drawableRuleset) { @@ -122,8 +82,8 @@ namespace osu.Game.Rulesets.Mania.Scoring } } - protected override double HpFactorFor(Judgement judgement, HitResult result) - => result == HitResult.Miss ? hpMissMultiplier : hpMultiplier; + protected override double HpFactorFor(JudgementResult result) + => result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier; public override HitWindows CreateHitWindows() => new ManiaHitWindows(); } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index a4975ef3b3..2162663539 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -37,8 +37,6 @@ namespace osu.Game.Rulesets.Osu.Scoring comboResultCounts.Clear(); } - private const double harshness = 0.01; - protected override void ApplyResult(JudgementResult result) { base.ApplyResult(result); @@ -49,9 +47,9 @@ namespace osu.Game.Rulesets.Osu.Scoring comboResultCounts[osuResult.ComboType] = comboResultCounts.GetOrDefault(osuResult.ComboType) + 1; } - protected override double HpFactorFor(Judgement judgement, HitResult result) + protected override double HpFactorFor(JudgementResult result) { - switch (result) + switch (result.Type) { case HitResult.Great: return 10.2 - hpDrainRate; diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index a0055a93aa..b2b866db4b 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -46,8 +46,8 @@ namespace osu.Game.Rulesets.Taiko.Scoring hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120); } - protected override double HpFactorFor(Judgement judgement, HitResult result) - => result == HitResult.Miss ? hpMissMultiplier : hpMultiplier; + protected override double HpFactorFor(JudgementResult result) + => result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier; protected override void Reset(bool storeResults) { diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs index d4ef5750b1..195fe316ac 100644 --- a/osu.Game/Rulesets/Judgements/JudgementResult.cs +++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs @@ -37,6 +37,11 @@ namespace osu.Game.Rulesets.Judgements /// public int HighestComboAtJudgement { get; internal set; } + /// + /// The health prior to this occurring. + /// + public double HealthAtJudgement { get; internal set; } + /// /// Whether a miss or hit occurred. /// diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 1a682080bf..429aa620f6 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -206,9 +206,6 @@ namespace osu.Game.Rulesets.Scoring private double baseScore; private double bonusScore; - private double rollingHp; - private double rollingMaxHp; - protected ScoreProcessor() { } @@ -304,6 +301,7 @@ namespace osu.Game.Rulesets.Scoring { result.ComboAtJudgement = Combo.Value; result.HighestComboAtJudgement = HighestCombo.Value; + result.HealthAtJudgement = Health.Value; JudgedHits++; @@ -336,8 +334,7 @@ namespace osu.Game.Rulesets.Scoring rollingMaxBaseScore += result.Judgement.MaxNumericResult; } - rollingHp += HpFactorFor(result.Judgement, result.Type) * result.Judgement.HealthIncreaseFor(result); - rollingMaxHp += HpFactorFor(result.Judgement, result.Judgement.MaxResult) * result.Judgement.MaxHealthIncrease; + Health.Value += HpFactorFor(result) * result.Judgement.HealthIncreaseFor(result); } /// @@ -349,6 +346,7 @@ namespace osu.Game.Rulesets.Scoring { Combo.Value = result.ComboAtJudgement; HighestCombo.Value = result.HighestComboAtJudgement; + Health.Value = result.HealthAtJudgement; JudgedHits--; @@ -362,12 +360,9 @@ namespace osu.Game.Rulesets.Scoring baseScore -= result.Judgement.NumericResultFor(result); rollingMaxBaseScore -= result.Judgement.MaxNumericResult; } - - rollingHp -= HpFactorFor(result.Judgement, result.Type) * result.Judgement.HealthIncreaseFor(result); - rollingMaxHp -= HpFactorFor(result.Judgement, result.Judgement.MaxResult) * result.Judgement.MaxHealthIncrease; } - protected virtual double HpFactorFor(Judgement judgement, HitResult result) => 1; + protected virtual double HpFactorFor(JudgementResult result) => 1; private void updateScore() { From 910b9df2d54b93e28c6e729807337d9a14f161bf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 22 Apr 2019 18:02:57 +0900 Subject: [PATCH 0617/5608] Fix catch awarding too much hp --- osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs | 2 +- osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs index 31f825c3ef..5835e746b9 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Judgements default: return 0; case HitResult.Perfect: - return 0.08; + return 0.008; } } diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs index f03897d611..679691fcd6 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.Judgements default: return base.HealthIncreaseFor(result); case HitResult.Perfect: - return 0.07; + return 0.007; } } } From aeae759fcd5b9949815b2bba02a799e9d6c277e8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 22 Apr 2019 18:08:15 +0900 Subject: [PATCH 0618/5608] Rename method + add xmldoc --- osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs | 2 +- osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs | 2 +- osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs | 2 +- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 2 +- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 9 +++++++-- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 778a7426aa..0d0ca6506c 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Catch.Scoring hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate; } - protected override double HpFactorFor(JudgementResult result) + protected override double HealthAdjustmentFactorFor(JudgementResult result) { switch (result.Type) { diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index ee4618e5c2..5caf08fb1e 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -82,7 +82,7 @@ namespace osu.Game.Rulesets.Mania.Scoring } } - protected override double HpFactorFor(JudgementResult result) + protected override double HealthAdjustmentFactorFor(JudgementResult result) => result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier; public override HitWindows CreateHitWindows() => new ManiaHitWindows(); diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 2162663539..cf0565c6da 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Osu.Scoring comboResultCounts[osuResult.ComboType] = comboResultCounts.GetOrDefault(osuResult.ComboType) + 1; } - protected override double HpFactorFor(JudgementResult result) + protected override double HealthAdjustmentFactorFor(JudgementResult result) { switch (result.Type) { diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index b2b866db4b..68ddf2db19 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120); } - protected override double HpFactorFor(JudgementResult result) + protected override double HealthAdjustmentFactorFor(JudgementResult result) => result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier; protected override void Reset(bool storeResults) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 429aa620f6..ba71e1e9b2 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -334,7 +334,7 @@ namespace osu.Game.Rulesets.Scoring rollingMaxBaseScore += result.Judgement.MaxNumericResult; } - Health.Value += HpFactorFor(result) * result.Judgement.HealthIncreaseFor(result); + Health.Value += HealthAdjustmentFactorFor(result) * result.Judgement.HealthIncreaseFor(result); } /// @@ -362,7 +362,12 @@ namespace osu.Game.Rulesets.Scoring } } - protected virtual double HpFactorFor(JudgementResult result) => 1; + /// + /// An adjustment factor which is multiplied into the health increase provided by a . + /// + /// The for which the adjustment should apply. + /// The adjustment factor. + protected virtual double HealthAdjustmentFactorFor(JudgementResult result) => 1; private void updateScore() { From 908eee9942653eabd72e68a3a60b93f7ec35cccd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Apr 2019 17:06:01 +0900 Subject: [PATCH 0619/5608] Fix pause tests --- osu.Game/Rulesets/UI/Playfield.cs | 5 +++++ osu.Game/Screens/Play/GameplayClockContainer.cs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 13689153f0..a99c16a610 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -68,7 +68,12 @@ namespace osu.Game.Rulesets.UI { Cursor = CreateCursor(); if (Cursor != null) + { + // initial showing of the cursor will be handed by MenuCursorContainer (via DrawableRuleset's IProvideCursor implementation). + Cursor.Hide(); + AddInternal(Cursor); + } } /// diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 29974b728e..3654dc679c 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -123,7 +123,7 @@ namespace osu.Game.Screens.Play { // Seeking the decoupled clock to its current time ensures that its source clock will be seeked to the same time // This accounts for the audio clock source potentially taking time to enter a completely stopped state - adjustableClock.Seek(adjustableClock.CurrentTime); + adjustableClock.Seek(GameplayClock.CurrentTime); adjustableClock.Start(); IsPaused.Value = false; } From 55c5ef898d2cba265b877bf1d4a5195a1b14c6bc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Apr 2019 17:06:40 +0900 Subject: [PATCH 0620/5608] Remove delay on entering player --- osu.Game/Screens/Play/GameplayClockContainer.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 3654dc679c..2d1ba3f2ab 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -110,11 +110,8 @@ namespace osu.Game.Screens.Play adjustableClock.ChangeSource(sourceClock); updateRate(); - this.Delay(750).Schedule(() => - { - if (!IsPaused.Value) - Start(); - }); + if (!IsPaused.Value) + Start(); }); }); } From 6856571f17d06cd8080b19d967846347a54565af Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Apr 2019 18:45:58 +0900 Subject: [PATCH 0621/5608] Fix incorrect seek target --- osu.Game/Screens/Play/GameplayClockContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 2d1ba3f2ab..6b12430552 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -120,7 +120,7 @@ namespace osu.Game.Screens.Play { // Seeking the decoupled clock to its current time ensures that its source clock will be seeked to the same time // This accounts for the audio clock source potentially taking time to enter a completely stopped state - adjustableClock.Seek(GameplayClock.CurrentTime); + Seek(GameplayClock.CurrentTime); adjustableClock.Start(); IsPaused.Value = false; } From 48e82d4b1c742dff5bbe101ebf6ffefcfa044809 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Apr 2019 18:47:28 +0900 Subject: [PATCH 0622/5608] Fix hold for menu button's icon being incorrect --- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 6883f246e4..c0ee5e6142 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -129,7 +129,7 @@ namespace osu.Game.Screens.Play.HUD Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(15), - Icon = FontAwesome.Solid.TimesCircle + Icon = FontAwesome.Solid.Times }, } }; From 1f18c08cfc15a8184306ecce7915afff16c2061b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Apr 2019 19:17:58 +0900 Subject: [PATCH 0623/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a45cac2cb6..303587bf88 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 70edc01821..e45a76dbac 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 414d55548439b4a1e5e16f1da7830bd5aedc3296 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 22 Apr 2019 19:24:57 +0900 Subject: [PATCH 0624/5608] Fix possible exit from non-current screen --- osu.Game/Screens/Multi/Multiplayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 5e019a7b3a..1183396369 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -276,7 +276,7 @@ namespace osu.Game.Screens.Multi updatePollingRate(isIdle.Value); - if (screenStack.CurrentScreen == null) + if (screenStack.CurrentScreen == null && this.IsCurrentScreen()) this.Exit(); } From 52336e9062affa6742ad49c7802f31153364e04a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 Apr 2019 11:52:42 +0900 Subject: [PATCH 0625/5608] Fix pause tests --- osu.Game/Tests/Visual/PlayerTestCase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/PlayerTestCase.cs b/osu.Game/Tests/Visual/PlayerTestCase.cs index d308b86b5a..fca4fccae0 100644 --- a/osu.Game/Tests/Visual/PlayerTestCase.cs +++ b/osu.Game/Tests/Visual/PlayerTestCase.cs @@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual public void SetUpSteps() { AddStep(ruleset.RulesetInfo.Name, loadPlayer); - AddUntilStep(() => Player.IsLoaded, "player loaded"); + AddUntilStep(() => Player.IsLoaded && Player.Alpha == 1, "player loaded"); } protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo); From 6add3952883f7d8b40f7e2cfd3ec0061cffa0f9b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 23 Apr 2019 13:32:44 +0900 Subject: [PATCH 0626/5608] Fix gameplay cursor being hidden in tests/replays --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 3 +++ osu.Game/Tests/Visual/ManualInputManagerTestCase.cs | 11 +++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 2866e81682..302380744a 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -225,6 +225,9 @@ namespace osu.Game.Rulesets.UI if (replayInputManager.ReplayInputHandler != null) replayInputManager.ReplayInputHandler.GamefieldToScreenSpace = Playfield.GamefieldToScreenSpace; + + if (!ProvidingUserCursor) + Playfield.Cursor?.Show(); } /// diff --git a/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs b/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs index f14ac833e4..9b1ccdd6a4 100644 --- a/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs +++ b/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs @@ -4,17 +4,24 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing.Input; +using osu.Game.Graphics.Cursor; namespace osu.Game.Tests.Visual { public abstract class ManualInputManagerTestCase : OsuTestCase { - protected override Container Content => InputManager; + protected override Container Content => content; + private readonly Container content; + protected readonly ManualInputManager InputManager; protected ManualInputManagerTestCase() { - base.Content.Add(InputManager = new ManualInputManager { UseParentInput = true }); + base.Content.Add(InputManager = new ManualInputManager + { + UseParentInput = true, + Child = content = new MenuCursorContainer { RelativeSizeAxes = Axes.Both }, + }); } /// From 6c568d228fe7edb316492c4b4c32aae595c3b333 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 23 Apr 2019 13:45:51 +0900 Subject: [PATCH 0627/5608] Add comment --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 302380744a..01ae637158 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -227,7 +227,10 @@ namespace osu.Game.Rulesets.UI replayInputManager.ReplayInputHandler.GamefieldToScreenSpace = Playfield.GamefieldToScreenSpace; if (!ProvidingUserCursor) + { + // The cursor is hidden by default (see Playfield.load()), but should be shown when there's a replay Playfield.Cursor?.Show(); + } } /// From 9890884726181bcb8605a39c5cf3bb2c9be38c6b Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 23 Apr 2019 14:23:09 +0900 Subject: [PATCH 0628/5608] Remove fade in, update comment --- osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs | 3 ++- osu.Game/Rulesets/Mods/ModFlashlight.cs | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index b2bc5f4320..597c430e16 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -49,7 +49,8 @@ namespace osu.Game.Rulesets.Osu.Mods if (e.NewValue) { trackingSliders++; - // This check being here ensures we're only applying a dim if and only if a slider begins tracking. + // The fade should only be applied if tracking sliders is increasing from 0 to 1, and cannot be a result of a slider losing tracking. + // As a result, this logic must be exclusive to when e.NewValue is true. if (trackingSliders == 1) { this.TransformTo(nameof(FlashlightDim), 0.8f, 50); diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index c3ac00f3ad..54331508a0 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -95,8 +95,6 @@ namespace osu.Game.Rulesets.Mods Combo.ValueChanged += OnComboChange; - this.FadeInFromZero(FLASHLIGHT_FADE_DURATION); - using (BeginAbsoluteSequence(0)) { foreach (var breakPeriod in Breaks) From 0838206ddd3c54d2ec9f2d7cfc015da931a97a0c Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 22 Apr 2019 22:44:43 -0700 Subject: [PATCH 0629/5608] Shorten multiplayer header to multi --- osu.Game/Screens/Multi/Header.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index 7924086389..b9354cac7d 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -79,7 +79,7 @@ namespace osu.Game.Screens.Multi [BackgroundDependencyLoader] private void load(OsuColour colours) { - Title = "multiplayer"; + Title = "multi"; Icon = OsuIcon.Multi; AccentColour = colours.Yellow; } From 80e1568e974f0cfa5efd0e8a4b1c2298c7fffefc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Apr 2019 13:44:21 +0900 Subject: [PATCH 0630/5608] Fix FrameStabilityContainer performing frame-stable seeks --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index c307520aca..2866ce08ed 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -68,6 +68,8 @@ namespace osu.Game.Rulesets.UI private const double sixty_frame_time = 1000.0 / 60; + private bool firstConsumption = true; + public override bool UpdateSubTree() { requireMoreUpdateLoops = true; @@ -103,7 +105,14 @@ namespace osu.Game.Rulesets.UI try { - if (Math.Abs(manualClock.CurrentTime - newProposedTime) > sixty_frame_time * 1.2f) + if (firstConsumption) + { + // On the first update, frame-stability seeking would result in unexpected/unwanted behaviour. + // Instead we perform an initial seek to the proposed time. + manualClock.CurrentTime = newProposedTime; + firstConsumption = false; + } + else if (Math.Abs(manualClock.CurrentTime - newProposedTime) > sixty_frame_time * 1.2f) { newProposedTime = newProposedTime > manualClock.CurrentTime ? Math.Min(newProposedTime, manualClock.CurrentTime + sixty_frame_time) From 60328cf1fb840344d3919ee80638ffe01b5010cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Apr 2019 15:23:00 +0900 Subject: [PATCH 0631/5608] Ensure FrameStabilityContainer's ElapsedTime is zero on initial seek --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 2866ce08ed..ad15bcf057 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -110,6 +110,10 @@ namespace osu.Game.Rulesets.UI // On the first update, frame-stability seeking would result in unexpected/unwanted behaviour. // Instead we perform an initial seek to the proposed time. manualClock.CurrentTime = newProposedTime; + + // do a second process to clear out ElapsedTime + framedClock.ProcessFrame(); + firstConsumption = false; } else if (Math.Abs(manualClock.CurrentTime - newProposedTime) > sixty_frame_time * 1.2f) From a3e7ec0a14b85acec83e68963bb5d44e99a96300 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Apr 2019 15:23:31 +0900 Subject: [PATCH 0632/5608] Add tests for FrameStabilityContainer --- .../TestCaseFrameStabilityContainer.cs | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs new file mode 100644 index 0000000000..ca0607cd6b --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs @@ -0,0 +1,149 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Timing; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestCaseFrameStabilityContainer : OsuTestCase + { + private ManualClock manualClock; + + private Container mainContainer; + + private ClockConsumingChild consumer; + + [SetUp] + public void SetUp() + { + Child = mainContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Clock = new FramedClock(manualClock = new ManualClock()), + }; + } + + [Test] + public void TestLargeJumps() + { + createStabilityContainer(); + seekManualTo(100000); + + confirmSeek(100000); + checkFrameCount(6000); + + seekManualTo(0); + + confirmSeek(0); + checkFrameCount(12000); + } + + [Test] + public void TestSmallJumps() + { + createStabilityContainer(); + seekManualTo(40); + + confirmSeek(40); + checkFrameCount(3); + + seekManualTo(0); + + confirmSeek(0); + checkFrameCount(6); + } + + [Test] + public void TestSingleFrameJump() + { + createStabilityContainer(); + seekManualTo(8); + confirmSeek(8); + checkFrameCount(1); + + seekManualTo(16); + confirmSeek(16); + checkFrameCount(2); + } + + [Test] + public void TestInitialSeek() + { + seekManualTo(100000); + + createStabilityContainer(); + + confirmSeek(100000); + checkFrameCount(0); + } + + private void createStabilityContainer() => AddStep("create container", () => mainContainer.Child = new FrameStabilityContainer().WithChild(consumer = new ClockConsumingChild())); + + private void seekManualTo(double time) => AddStep($"seek manual clock to {time}", () => manualClock.CurrentTime = time); + + private void confirmSeek(double time) => AddUntilStep($"wait for seek to {time}", () => consumer.Clock.CurrentTime == time); + + private void checkFrameCount(int frames) => + AddAssert($"elapsed frames is {frames}", () => consumer.ElapsedFrames == frames); + + public class ClockConsumingChild : CompositeDrawable + { + private readonly OsuSpriteText text; + private readonly OsuSpriteText text2; + private readonly OsuSpriteText text3; + + public ClockConsumingChild() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + InternalChildren = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + text = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + text2 = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + text3 = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + } + }, + }; + } + + public int ElapsedFrames; + + protected override void Update() + { + base.Update(); + + if (Clock.ElapsedFrameTime != 0) + ElapsedFrames++; + + text.Text = $"current time: {Clock.CurrentTime:F0}"; + if (Clock.ElapsedFrameTime != 0) + text2.Text = $"last elapsed frame time: {Clock.ElapsedFrameTime:F0}"; + text3.Text = $"total frames: {ElapsedFrames:F0}"; + } + } + } +} From e69963e60e2627f9682de1835ea1f3c2388b50c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Apr 2019 12:35:34 +0900 Subject: [PATCH 0633/5608] Ensure there is enough time before the first object in osu! (roughly following osu-stable specs) --- osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index ba7241c165..72adb4624d 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Input; @@ -61,7 +62,7 @@ namespace osu.Game.Rulesets.Osu.UI get { var first = (OsuHitObject)Objects.First(); - return first.StartTime - first.TimePreempt; + return first.StartTime - Math.Max(2000, first.TimePreempt); } } } From efaedafc0870bdff673a37034b57a615a6e59d72 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Apr 2019 13:53:05 +0900 Subject: [PATCH 0634/5608] Fix (legacy) AudioLeadIn being used incorrectly. This lead-in is intended to specify a value before zero, not a value before the start time. Also removes an unnecessary ProcessFrame call (it happens within Seek itself). --- osu.Game/Screens/Play/GameplayClockContainer.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 6b12430552..f1eed3f662 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -95,8 +95,7 @@ namespace osu.Game.Screens.Play UserPlaybackRate.ValueChanged += _ => updateRate(); - Seek(Math.Min(0, gameplayStartTime - beatmap.BeatmapInfo.AudioLeadIn)); - adjustableClock.ProcessFrame(); + Seek(Math.Min(-beatmap.BeatmapInfo.AudioLeadIn, gameplayStartTime)); } public void Restart() From bb69330e9f85e1e76140e225e497a2cd45a1311f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Apr 2019 14:01:46 +0900 Subject: [PATCH 0635/5608] Call ProcessFrame on the userOffsetClock after a seek Without doing this, GameplayClock can be left in an incorrect state after a seek (due to the userOffsetClock being its own FramedClock). --- osu.Game/Screens/Play/GameplayClockContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index f1eed3f662..c151e598f7 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -136,6 +136,9 @@ namespace osu.Game.Screens.Play // remove the offset component here because most of the time we want the seek to be aligned to gameplay, not the audio track. // we may want to consider reversing the application of offsets in the future as it may feel more correct. adjustableClock.Seek(time - totalOffset); + + // manually process frame to ensure GameplayClock is correctly updated after a seek. + userOffsetClock.ProcessFrame(); } public void Stop() From 3b36a4982deabef006ccd97909c3f2730abbe51e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Apr 2019 15:46:21 +0900 Subject: [PATCH 0636/5608] Fix tests running under nUnit and running multiple times in concession --- .../Gameplay/TestCaseFrameStabilityContainer.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs index ca0607cd6b..bc30648566 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs @@ -4,6 +4,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.UI; @@ -12,14 +13,13 @@ namespace osu.Game.Tests.Visual.Gameplay { public class TestCaseFrameStabilityContainer : OsuTestCase { - private ManualClock manualClock; + private readonly ManualClock manualClock; - private Container mainContainer; + private readonly Container mainContainer; private ClockConsumingChild consumer; - [SetUp] - public void SetUp() + public TestCaseFrameStabilityContainer() { Child = mainContainer = new Container { @@ -31,6 +31,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestLargeJumps() { + seekManualTo(0); createStabilityContainer(); seekManualTo(100000); @@ -46,6 +47,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestSmallJumps() { + seekManualTo(0); createStabilityContainer(); seekManualTo(40); @@ -61,6 +63,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestSingleFrameJump() { + seekManualTo(0); createStabilityContainer(); seekManualTo(8); confirmSeek(8); @@ -75,7 +78,6 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestInitialSeek() { seekManualTo(100000); - createStabilityContainer(); confirmSeek(100000); From f273f5daae7e6224ead6491e491b391fc261db07 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Apr 2019 15:55:51 +0900 Subject: [PATCH 0637/5608] Remove unnecessary using statement --- .../Visual/Gameplay/TestCaseFrameStabilityContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs index bc30648566..5cd01fe9a8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs @@ -4,7 +4,6 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.UI; From 8222923ab8838cf754874df7edbe62fa37679291 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 24 Apr 2019 16:20:51 +0900 Subject: [PATCH 0638/5608] Only track logo if we're still the current screen --- osu.Game/Screens/Play/PlayerLoader.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 6a55fe278b..4403cae883 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -163,7 +163,11 @@ namespace osu.Game.Screens.Play logo.ScaleTo(new Vector2(0.15f), duration, Easing.In); logo.FadeIn(350); - Scheduler.AddDelayed(() => { content.StartTracking(logo, resuming ? 0 : 500, Easing.InOutExpo); }, resuming ? 0 : 500); + Scheduler.AddDelayed(() => + { + if (this.IsCurrentScreen()) + content.StartTracking(logo, resuming ? 0 : 500, Easing.InOutExpo); + }, resuming ? 0 : 500); } protected override void LogoExiting(OsuLogo logo) From 67382724f633e1f79e4e7f18204de3f49200acf5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Apr 2019 16:58:13 +0900 Subject: [PATCH 0639/5608] Reword and reoganise logic --- .../Mods/OsuModFlashlight.cs | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 597c430e16..c2d6ec7934 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Mods private class OsuFlashlight : Flashlight, IRequireHighFrequencyMousePosition { - private int trackingSliders; + private int slidersCurrentlyTracking; public OsuFlashlight() { @@ -45,29 +45,22 @@ namespace osu.Game.Rulesets.Osu.Mods public void OnSliderTrackingChange(ValueChangedEvent e) { - // If any sliders are in a tracking state, apply a dim to the entire playfield over a brief duration. + // If any sliders are in a tracking state, a further dim should be applied to the (remaining) visible portion of the playfield over a brief duration. if (e.NewValue) { - trackingSliders++; - // The fade should only be applied if tracking sliders is increasing from 0 to 1, and cannot be a result of a slider losing tracking. - // As a result, this logic must be exclusive to when e.NewValue is true. - if (trackingSliders == 1) - { + // The transform should only be applied when the first slider begins tracking. + if (++slidersCurrentlyTracking == 1) this.TransformTo(nameof(FlashlightDim), 0.8f, 50); - } } else { - trackingSliders--; + if (slidersCurrentlyTracking == 0) + throw new InvalidOperationException($"The number of {nameof(slidersCurrentlyTracking)} cannot be below 0."); - if (trackingSliders == 0) - { + // The fade is restored after the last slider exits a tracked state. + if (--slidersCurrentlyTracking == 0) this.TransformTo(nameof(FlashlightDim), 0.0f, 50); - } } - - if (trackingSliders < 0) - throw new InvalidOperationException($"The number of {nameof(trackingSliders)} cannot be below 0."); } protected override bool OnMouseMove(MouseMoveEvent e) From 8f101e4f604bac362799fe8c171b8cdaee4aef28 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 24 Apr 2019 18:25:38 +0900 Subject: [PATCH 0640/5608] Remove unnecessary multi-slider tracking logic --- .../Mods/OsuModFlashlight.cs | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index c2d6ec7934..8e98a02392 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -36,8 +36,6 @@ namespace osu.Game.Rulesets.Osu.Mods private class OsuFlashlight : Flashlight, IRequireHighFrequencyMousePosition { - private int slidersCurrentlyTracking; - public OsuFlashlight() { FlashlightSize = new Vector2(0, getSizeFor(0)); @@ -45,22 +43,8 @@ namespace osu.Game.Rulesets.Osu.Mods public void OnSliderTrackingChange(ValueChangedEvent e) { - // If any sliders are in a tracking state, a further dim should be applied to the (remaining) visible portion of the playfield over a brief duration. - if (e.NewValue) - { - // The transform should only be applied when the first slider begins tracking. - if (++slidersCurrentlyTracking == 1) - this.TransformTo(nameof(FlashlightDim), 0.8f, 50); - } - else - { - if (slidersCurrentlyTracking == 0) - throw new InvalidOperationException($"The number of {nameof(slidersCurrentlyTracking)} cannot be below 0."); - - // The fade is restored after the last slider exits a tracked state. - if (--slidersCurrentlyTracking == 0) - this.TransformTo(nameof(FlashlightDim), 0.0f, 50); - } + // If a slider is in a tracking state, a further dim should be applied to the (remaining) visible portion of the playfield over a brief duration. + this.TransformTo(nameof(FlashlightDim), e.NewValue ? 0.8f : 0.0f, 50); } protected override bool OnMouseMove(MouseMoveEvent e) From 90d5c64cf36df3ab147383b3d8e03ae93e6c44cf Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 24 Apr 2019 18:25:55 +0900 Subject: [PATCH 0641/5608] Remove unused usings --- osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 8e98a02392..c0332fbf60 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.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.Collections.Generic; using System.Linq; using osu.Framework.Bindables; From 8dc7fd8223235fa56c335840b79354c1e1d46be6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Apr 2019 12:16:12 +0900 Subject: [PATCH 0642/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 303587bf88..22afce9c86 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index e45a76dbac..eaebcc3361 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 6fdcd98caadb0415e4bddd198a1e5e5804a56ea7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Apr 2019 14:15:07 +0900 Subject: [PATCH 0643/5608] Don't play screen "back" sample when retrying --- osu.Game/Screens/OsuScreen.cs | 5 ++++- osu.Game/Screens/Play/PlayerLoader.cs | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index c1a822c75c..9d53e43b80 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -59,6 +59,8 @@ namespace osu.Game.Screens private SampleChannel sampleExit; + protected virtual bool PlayResumeSound => true; + public virtual float BackgroundParallaxAmount => 1; public Bindable Beatmap { get; private set; } @@ -117,7 +119,8 @@ namespace osu.Game.Screens public override void OnResuming(IScreen last) { - sampleExit?.Play(); + if (PlayResumeSound) + sampleExit?.Play(); applyArrivingDefaults(true); base.OnResuming(last); diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 6a55fe278b..d49ac0ed16 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -44,6 +44,8 @@ namespace osu.Game.Screens.Play public override bool DisallowExternalBeatmapRulesetChanges => true; + protected override bool PlayResumeSound => false; + private Task loadTask; private InputManager inputManager; From 0bd35ab7bbdb29705813c02474c16d2db35dd36f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 25 Apr 2019 17:36:17 +0900 Subject: [PATCH 0644/5608] Turn on warnings, resolve issues --- .../Visual/Gameplay/TestCaseSkinReloadable.cs | 12 ++-------- osu.Game/Audio/IPreviewTrackOwner.cs | 2 +- osu.Game/Beatmaps/BeatmapConverter.cs | 2 +- osu.Game/Beatmaps/BeatmapManager.cs | 3 +-- osu.Game/Beatmaps/BindableBeatmap.cs | 4 ++-- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 12 +++++++++- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 1 + osu.Game/Database/ArchiveModelManager.cs | 2 +- osu.Game/Database/DatabaseContextFactory.cs | 3 +-- osu.Game/Database/OsuDbContext.cs | 2 +- .../Graphics/Containers/LinkFlowContainer.cs | 2 +- .../Containers/LogoTrackingContainer.cs | 3 +-- osu.Game/Graphics/OsuFont.cs | 5 ++-- .../UserInterface/ScreenBreadcrumbControl.cs | 2 +- osu.Game/Online/API/APIAccess.cs | 2 +- .../Requests/Responses/APILegacyScoreInfo.cs | 2 -- .../Responses/APIUserMostPlayedBeatmap.cs | 8 +++---- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 2 -- osu.Game/OsuGame.cs | 1 - .../Chat/Tabs/ChannelSelectorTabItem.cs | 2 +- .../Chat/Tabs/PrivateChannelTabItem.cs | 4 ---- osu.Game/Overlays/HoldToConfirmOverlay.cs | 2 +- osu.Game/Overlays/MusicController.cs | 1 - .../Settings/RulesetSettingsSubsection.cs | 3 ++- .../Overlays/Settings/SettingsEnumDropdown.cs | 2 +- .../Difficulty/DifficultyCalculator.cs | 2 +- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 4 +++- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 6 ++++- .../Mods/IApplicableToBeatmapConverter.cs | 2 -- .../Rulesets/Mods/IApplicableToHitObject.cs | 2 +- .../Objects/Drawables/DrawableHitObject.cs | 5 ++-- osu.Game/Rulesets/Objects/HitObject.cs | 4 +--- osu.Game/Rulesets/Objects/HitWindows.cs | 2 +- osu.Game/Rulesets/Objects/SliderPath.cs | 7 ------ osu.Game/Rulesets/Ruleset.cs | 1 + osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 3 --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 4 +++- .../Rulesets/UI/GameplayCursorContainer.cs | 2 +- osu.Game/Rulesets/UI/Playfield.cs | 1 - .../Scrolling/Algorithms/IScrollAlgorithm.cs | 2 +- .../UI/Scrolling/DrawableScrollingRuleset.cs | 2 +- osu.Game/Screens/BackgroundScreenStack.cs | 2 +- .../Compose/Components/SelectionHandler.cs | 3 +-- .../Timeline/ZoomableScrollContainer.cs | 2 +- osu.Game/Screens/Edit/Editor.cs | 3 --- .../LabelledComponents/LabelledTextBox.cs | 7 ------ .../Multi/Components/DisableableTabControl.cs | 6 ++--- .../Lounge/Components/ParticipantInfo.cs | 24 ------------------- .../Multi/Lounge/Components/RoomInspector.cs | 2 +- .../Multi/Match/Components/GameTypePicker.cs | 2 +- .../Screens/Multi/Match/Components/Info.cs | 3 +-- .../Match/Components/MatchSettingsOverlay.cs | 4 ++-- .../Components/RoomAvailabilityPicker.cs | 2 +- .../Screens/Multi/MultiplayerComposite.cs | 4 ++-- .../Screens/Multi/MultiplayerSubScreen.cs | 22 +---------------- osu.Game/Screens/Multi/RoomManager.cs | 2 +- osu.Game/Screens/Play/GameplayClock.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Play/PlayerLoader.cs | 1 - .../Screens/Select/Carousel/CarouselItem.cs | 2 -- osu.Game/Screens/Select/SongSelect.cs | 2 -- osu.Game/Skinning/ISkin.cs | 24 +++++++++++++++++++ osu.Game/Skinning/ISkinSource.cs | 13 +--------- .../Skinning/LocalSkinOverrideContainer.cs | 14 +++++------ osu.Game/Skinning/Skin.cs | 4 +--- osu.Game/Tests/Visual/AllPlayersTestCase.cs | 4 ++-- osu.Game/Tests/Visual/EditorClockTestCase.cs | 2 +- osu.Game/Tests/Visual/OsuTestCase.cs | 2 +- osu.Game/Tests/Visual/PlayerTestCase.cs | 2 +- osu.Game/osu.Game.csproj | 1 - 71 files changed, 116 insertions(+), 182 deletions(-) create mode 100644 osu.Game/Skinning/ISkin.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseSkinReloadable.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseSkinReloadable.cs index a9fbf35d37..56ab70b400 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseSkinReloadable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseSkinReloadable.cs @@ -120,12 +120,8 @@ namespace osu.Game.Tests.Visual.Gameplay } } - private class SecondarySource : ISkinSource + private class SecondarySource : ISkin { - public event Action SourceChanged; - - public void TriggerSourceChanged() => SourceChanged?.Invoke(); - public Drawable GetDrawableComponent(string componentName) => new SecondarySourceBox(); public Texture GetTexture(string componentName) => throw new NotImplementedException(); @@ -135,12 +131,8 @@ namespace osu.Game.Tests.Visual.Gameplay public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); } - private class SkinSourceContainer : Container, ISkinSource + private class SkinSourceContainer : Container, ISkin { - public event Action SourceChanged; - - public void TriggerSourceChanged() => SourceChanged?.Invoke(); - public Drawable GetDrawableComponent(string componentName) => new BaseSourceBox(); public Texture GetTexture(string componentName) => throw new NotImplementedException(); diff --git a/osu.Game/Audio/IPreviewTrackOwner.cs b/osu.Game/Audio/IPreviewTrackOwner.cs index fdcae65e3c..8ab93257a5 100644 --- a/osu.Game/Audio/IPreviewTrackOwner.cs +++ b/osu.Game/Audio/IPreviewTrackOwner.cs @@ -4,7 +4,7 @@ namespace osu.Game.Audio { /// - /// Interface for objects that can own s. + /// Interface for objects that can own s. /// /// /// s can cancel the currently playing through the diff --git a/osu.Game/Beatmaps/BeatmapConverter.cs b/osu.Game/Beatmaps/BeatmapConverter.cs index b6fa6674f6..7922843626 100644 --- a/osu.Game/Beatmaps/BeatmapConverter.cs +++ b/osu.Game/Beatmaps/BeatmapConverter.cs @@ -98,7 +98,7 @@ namespace osu.Game.Beatmaps protected abstract IEnumerable ValidConversionTypes { get; } /// - /// Creates the that will be returned by this . + /// Creates the that will be returned by this . /// protected virtual Beatmap CreateBeatmap() => new Beatmap(); diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 9caa64ec96..a36a8ea7dd 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -217,7 +217,7 @@ namespace osu.Game.Beatmaps { request.Perform(api); } - catch (Exception e) + catch { // no need to handle here as exceptions will filter down to request.Failure above. } @@ -382,7 +382,6 @@ namespace osu.Game.Beatmaps /// Query the API to populate missing values like OnlineBeatmapID / OnlineBeatmapSetID or (Rank-)Status. /// /// The beatmap to populate. - /// The other beatmaps contained within this set. /// Whether to re-query if the provided beatmap already has populated values. /// True if population was successful. private bool fetchAndPopulateOnlineValues(BeatmapInfo beatmap, bool force = false) diff --git a/osu.Game/Beatmaps/BindableBeatmap.cs b/osu.Game/Beatmaps/BindableBeatmap.cs index 657dc06297..27bad65062 100644 --- a/osu.Game/Beatmaps/BindableBeatmap.cs +++ b/osu.Game/Beatmaps/BindableBeatmap.cs @@ -12,7 +12,7 @@ namespace osu.Game.Beatmaps { /// /// A for the beatmap. - /// This should be used sparingly in-favour of . + /// This should be used sparingly in-favour of . /// public abstract class BindableBeatmap : NonNullableBindable { @@ -67,6 +67,6 @@ namespace osu.Game.Beatmaps /// If you are further binding to events of the retrieved , ensure a local reference is held. /// [NotNull] - public abstract BindableBeatmap GetBoundCopy(); + public new abstract BindableBeatmap GetBoundCopy(); } } diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 58463d2219..7d25ca3ede 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using osu.Framework.Audio.Track; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Textures; using osu.Game.Rulesets; using osu.Game.Rulesets.Difficulty; @@ -73,9 +74,18 @@ namespace osu.Game.Beatmaps private class DummyBeatmapConverter : IBeatmapConverter { public event Action> ObjectConverted; + public IBeatmap Beatmap { get; set; } + public bool CanConvert => true; - public IBeatmap Convert() => Beatmap; + + public IBeatmap Convert() + { + foreach (var obj in Beatmap.HitObjects) + ObjectConverted?.Invoke(obj, obj.Yield()); + + return Beatmap; + } } } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 040f582e3b..31cfe076cd 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -95,7 +95,7 @@ namespace osu.Game.Beatmaps.Formats { colour = new Color4(byte.Parse(split[0]), byte.Parse(split[1]), byte.Parse(split[2]), split.Length == 4 ? byte.Parse(split[3]) : (byte)255); } - catch (Exception e) + catch { throw new InvalidOperationException(@"Color must be specified with 8-bit integer components"); } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 8989785dcd..4b0720d867 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -73,6 +73,7 @@ namespace osu.Game.Beatmaps /// /// /// The to create a playable for. + /// The s to apply to the . /// The converted . /// If could not be converted to . public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 3805921ac2..41f8c64853 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -563,7 +563,7 @@ namespace osu.Game.Database /// /// Check whether an existing model already exists for a new import item. /// - /// The new model proposed for import. + /// The new model proposed for import. /// An existing model which matches the criteria to skip importing, else null. protected TModel CheckForExisting(TModel model) => model.Hash == null ? null : ModelStore.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash); diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index f6250732d9..554337c477 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.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 System.Threading; using Microsoft.EntityFrameworkCore.Storage; @@ -67,7 +66,7 @@ namespace osu.Game.Database context = threadContexts.Value; } } - catch (Exception e) + catch { // retrieval of a context could trigger a fatal error. Monitor.Exit(writeLock); diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 17efe2c839..f4cd23f5a5 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -70,7 +70,7 @@ namespace osu.Game.Database cmd.ExecuteNonQuery(); } } - catch (Exception e) + catch { connection.Close(); throw; diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index eefbeea24c..222336d663 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -103,7 +103,7 @@ namespace osu.Game.Graphics.Containers { channelManager?.OpenChannel(linkArgument); } - catch (ChannelNotFoundException e) + catch (ChannelNotFoundException) { Logger.Log($"The requested channel \"{linkArgument}\" does not exist"); } diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index fb23038dde..23015e8bf5 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -30,7 +30,6 @@ namespace osu.Game.Graphics.Containers /// Assign the logo that should track the facade's position, as well as how it should transform to its initial position. /// /// The instance of the logo to be used for tracking. - /// The scale of the facade. Does not actually affect the logo itself. /// The duration of the initial transform. Default is instant. /// The easing type of the initial transform. public void StartTracking(OsuLogo logo, double duration = 0, Easing easing = Easing.None) @@ -132,7 +131,7 @@ namespace osu.Game.Graphics.Containers private class InternalFacade : Facade { - public void SetSize(Vector2 size) + public new void SetSize(Vector2 size) { base.SetSize(size); } diff --git a/osu.Game/Graphics/OsuFont.cs b/osu.Game/Graphics/OsuFont.cs index c8a736f49a..5324b269ee 100644 --- a/osu.Game/Graphics/OsuFont.cs +++ b/osu.Game/Graphics/OsuFont.cs @@ -61,9 +61,9 @@ namespace osu.Game.Graphics /// /// Retrieves the string representation of a . /// - /// The . + /// The family string. /// The . - /// The string representation of in the specified . + /// The string representation of in the specified . public static string GetWeightString(string family, FontWeight weight) { string weightString = weight.ToString(); @@ -81,6 +81,7 @@ namespace osu.Game.Graphics /// /// Creates a new by applying adjustments to this . /// + /// The base . /// The font typeface. If null, the value is copied from this . /// The text size. If null, the value is copied from this . /// The font weight. If null, the value is copied from this . diff --git a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs index f564a4b5a8..3e0a6c3265 100644 --- a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs @@ -8,7 +8,7 @@ using osu.Framework.Screens; namespace osu.Game.Graphics.UserInterface { /// - /// A which follows the active screen (and allows navigation) in a stack. + /// A which follows the active screen (and allows navigation) in a stack. /// public class ScreenBreadcrumbControl : BreadcrumbControl { diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index c5f6ef41c2..d5a496dc17 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -253,7 +253,7 @@ namespace osu.Game.Online.API handleWebException(we); return false; } - catch (Exception e) + catch { return false; } diff --git a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs index 8ee71ce9ac..ca3a77a140 100644 --- a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs @@ -7,7 +7,6 @@ using System.Linq; using Newtonsoft.Json; using osu.Game.Beatmaps; using osu.Game.Rulesets; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring.Legacy; using osu.Game.Users; @@ -71,7 +70,6 @@ namespace osu.Game.Online.API.Requests.Responses { foreach (var kvp in value) { - HitResult newKey; switch (kvp.Key) { case @"count_geki": diff --git a/osu.Game/Online/API/Requests/Responses/APIUserMostPlayedBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIUserMostPlayedBeatmap.cs index 8177f99abe..4614fe29b7 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUserMostPlayedBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUserMostPlayedBeatmap.cs @@ -10,16 +10,16 @@ namespace osu.Game.Online.API.Requests.Responses public class APIUserMostPlayedBeatmap { [JsonProperty("beatmap_id")] - public int BeatmapID; + public int BeatmapID { get; set; } [JsonProperty("count")] - public int PlayCount; + public int PlayCount { get; set; } [JsonProperty] - private BeatmapInfo beatmap; + private BeatmapInfo beatmap { get; set; } [JsonProperty] - private APIBeatmapSet beatmapSet; + private APIBeatmapSet beatmapSet { get; set; } public BeatmapInfo GetBeatmapInfo(RulesetStore rulesets) { diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 438bf231c4..ae4a056033 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -27,8 +27,6 @@ namespace osu.Game.Online.Chat protected ChannelManager ChannelManager; - private ScrollContainer scroll; - private DrawableChannel drawableChannel; private readonly bool postingTextbox; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 30f98aa1ce..4ce056195c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -272,7 +272,6 @@ namespace osu.Game /// Present a score's replay immediately. /// The user should have already requested this interactively. /// - /// The beatmap to select. public void PresentScore(ScoreInfo score) { var databasedScore = ScoreManager.GetScore(score); diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs index 52260506fe..c26ecfd86f 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays.Chat.Tabs } [BackgroundDependencyLoader] - private new void load(OsuColour colour) + private void load(OsuColour colour) { BackgroundInactive = colour.Gray2; BackgroundActive = colour.Gray3; diff --git a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs index 8aa6d6fecd..b8165e70cb 100644 --- a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; using osu.Game.Users; using osuTK; @@ -18,9 +17,6 @@ namespace osu.Game.Overlays.Chat.Tabs { public class PrivateChannelTabItem : ChannelTabItem { - private readonly OsuSpriteText username; - private readonly Avatar avatarContainer; - protected override IconUsage DisplayIcon => FontAwesome.Solid.At; public PrivateChannelTabItem(Channel value) diff --git a/osu.Game/Overlays/HoldToConfirmOverlay.cs b/osu.Game/Overlays/HoldToConfirmOverlay.cs index 154aff605a..fb38ddcbd1 100644 --- a/osu.Game/Overlays/HoldToConfirmOverlay.cs +++ b/osu.Game/Overlays/HoldToConfirmOverlay.cs @@ -11,7 +11,7 @@ namespace osu.Game.Overlays { /// /// An overlay which will display a black screen that dims over a period before confirming an exit action. - /// Action is BYO (derived class will need to call and from a user event). + /// Action is BYO (derived class will need to call and from a user event). /// public abstract class HoldToConfirmOverlay : HoldToConfirmContainer { diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index c250d3b62a..9046a196da 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -50,7 +50,6 @@ namespace osu.Game.Overlays private BeatmapManager beatmaps; private List beatmapSets; - private BeatmapSetInfo currentSet; private Container dragContainer; private Container playerContainer; diff --git a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs index a16e852902..93b07fbac7 100644 --- a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Game.Configuration; using osu.Game.Rulesets; using osu.Game.Rulesets.Configuration; @@ -9,7 +10,7 @@ namespace osu.Game.Overlays.Settings { /// /// A which provides subclasses with the - /// from the 's . + /// from the 's . /// public abstract class RulesetSettingsSubsection : SettingsSubsection { diff --git a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs b/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs index 11cdbf6e0a..9f09f251c2 100644 --- a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs +++ b/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Settings { protected override OsuDropdown CreateDropdown() => new DropdownControl(); - protected class DropdownControl : OsuEnumDropdown + protected new class DropdownControl : OsuEnumDropdown { public DropdownControl() { diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 14f7665e05..5eabe1e936 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -165,7 +165,7 @@ namespace osu.Game.Rulesets.Difficulty /// /// Creates the s to calculate the difficulty of an . /// - /// The whose difficulty will be calculated.The whose difficulty will be calculated. /// The s. protected abstract Skill[] CreateSkills(IBeatmap beatmap); } diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 74aa9ace2d..f12591cef4 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit.Compose; using osuTK; @@ -108,7 +109,8 @@ namespace osu.Game.Rulesets.Edit } /// - /// Invokes , refreshing and parameters for the . + /// Invokes , + /// refreshing and parameters for the . /// protected void ApplyDefaultsToHitObject() => HitObject.ApplyDefaults(beatmap.Value.Beatmap.ControlPointInfo, beatmap.Value.Beatmap.BeatmapInfo.BaseDifficulty); diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 85b6c91a07..01992cbbd3 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -68,9 +68,11 @@ namespace osu.Game.Rulesets.Edit get => state; set { - if (state == value) return; + if (state == value) + return; state = value; + switch (state) { case SelectionState.Selected: @@ -82,6 +84,8 @@ namespace osu.Game.Rulesets.Edit Deselected?.Invoke(this); break; } + + StateChanged?.Invoke(state); } } diff --git a/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs b/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs index eb80fa131a..8cefb02904 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs @@ -2,14 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; -using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mods { /// /// Interface for a that applies changes to a . /// - /// The type of converted . public interface IApplicableToBeatmapConverter : IApplicableMod { /// diff --git a/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs b/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs index c13b62812b..f7f81c92c0 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mods public interface IApplicableToHitObject : IApplicableMod { /// - /// Applies this to a . + /// Applies this to a . /// /// The to apply to. void ApplyToHitObject(HitObject hitObject); diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index a7cfbd3300..2e983b8fe1 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; +using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Game.Audio; using osu.Game.Graphics; @@ -58,7 +59,7 @@ namespace osu.Game.Rulesets.Objects.Drawables public bool AllJudged => Judged && NestedHitObjects.All(h => h.AllJudged); /// - /// Whether this has been hit. This occurs if is . + /// Whether this has been hit. This occurs if is hit. /// Note: This does NOT include nested hitobjects. /// public bool IsHit => Result?.IsHit ?? false; @@ -223,7 +224,7 @@ namespace osu.Game.Rulesets.Objects.Drawables } /// - /// Will called at least once after the of this has been passed. + /// Will called at least once after the of this has been passed. /// internal void OnLifetimeEnd() { diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index fd542be67d..cede2e50d0 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -53,8 +53,6 @@ namespace osu.Game.Rulesets.Objects [JsonIgnore] public bool Kiai { get; private set; } - private float overallDifficulty = BeatmapDifficulty.DEFAULT_DIFFICULTY; - /// /// The hit windows for this . /// @@ -115,7 +113,7 @@ namespace osu.Game.Rulesets.Objects /// Creates the for this . /// This can be null to indicate that the has no . /// - /// This will only be invoked if hasn't been set externally (e.g. from a . + /// This will only be invoked if hasn't been set externally (e.g. from a . /// /// protected virtual HitWindows CreateHitWindows() => new HitWindows(); diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index c5b7686da6..589c72957b 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Objects /// /// Given a time offset, whether the can ever be hit in the future with a non- result. - /// This happens if is less than what is required for a result. + /// This happens if is less than what is required for . /// /// The time offset. /// Whether the can be hit at any point in the future from this time offset. diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 1e9767a54f..e312b004ba 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -277,12 +277,5 @@ namespace osu.Game.Rulesets.Objects return ControlPoints.SequenceEqual(other.ControlPoints) && ExpectedDistance.Equals(other.ExpectedDistance) && Type == other.Type; } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - - return obj is SliderPath other && Equals(other); - } } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 3521c17b23..42b1322cae 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -53,6 +53,7 @@ namespace osu.Game.Rulesets /// Attempt to create a hit renderer for a beatmap /// /// The beatmap to create the hit renderer for. + /// The s to apply. /// Unable to successfully load the beatmap to be usable with this ruleset. /// public abstract DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods); diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ba71e1e9b2..a2937ff959 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -154,7 +154,6 @@ namespace osu.Game.Rulesets.Scoring /// /// Notifies subscribers of that a new judgement has occurred. /// - /// The judgement to notify subscribers of. /// The judgement scoring result to notify subscribers of. protected void NotifyNewJudgement(JudgementResult result) { @@ -283,7 +282,6 @@ namespace osu.Game.Rulesets.Scoring /// /// Reverts the score change of a that was applied to this . /// - /// The judgement to remove. /// The judgement scoring result. private void revertResult(JudgementResult result) { @@ -340,7 +338,6 @@ namespace osu.Game.Rulesets.Scoring /// /// Reverts the score change of a that was applied to this . /// - /// The judgement to remove. /// The judgement scoring result. protected virtual void RevertResult(JudgementResult result) { diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 01ae637158..df9effb321 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -93,6 +93,7 @@ namespace osu.Game.Rulesets.UI /// /// The ruleset being represented. /// The beatmap to create the hit renderer for. + /// The s to apply. protected DrawableRuleset(Ruleset ruleset, WorkingBeatmap workingBeatmap, IReadOnlyList mods) : base(ruleset) { @@ -275,7 +276,8 @@ namespace osu.Game.Rulesets.UI /// /// Applies the active mods to this DrawableRuleset. /// - /// + /// The s to apply. + /// The to apply. private void applyRulesetMods(IReadOnlyList mods, OsuConfigManager config) { if (mods == null) diff --git a/osu.Game/Rulesets/UI/GameplayCursorContainer.cs b/osu.Game/Rulesets/UI/GameplayCursorContainer.cs index de73c08809..41edfa0b68 100644 --- a/osu.Game/Rulesets/UI/GameplayCursorContainer.cs +++ b/osu.Game/Rulesets/UI/GameplayCursorContainer.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.UI public class GameplayCursorContainer : CursorContainer { /// - /// Because Show/Hide are executed by a parent, is updated immediately even if the cursor + /// Because Show/Hide are executed by a parent, is updated immediately even if the cursor /// is in a non-updating state (via limitations). /// /// This holds the true visibility value. diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index a99c16a610..a073ad246b 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -100,7 +100,6 @@ namespace osu.Game.Rulesets.UI /// /// Provide an optional cursor which is to be used for gameplay. - /// If providing a cursor, must also point to a valid target container. /// /// The cursor, or null if a cursor is not rqeuired. protected virtual GameplayCursorContainer CreateCursor() => null; diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs index a104b0629f..b7a5eedc22 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms /// The current time. /// The amount of visible time. /// The absolute spatial length through . - /// The time at which == . + /// The time at which == . double TimeAt(float position, double currentTime, double timeRange, float scrollLength); /// diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index dbe8d8c299..f21d0b4a66 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.UI.Scrolling protected virtual ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Sequential; /// - /// Whether the player can change . + /// Whether the player can change . /// protected virtual bool UserScrollSpeedAdjustment => true; diff --git a/osu.Game/Screens/BackgroundScreenStack.cs b/osu.Game/Screens/BackgroundScreenStack.cs index 5f82329496..9c0c5da0fb 100644 --- a/osu.Game/Screens/BackgroundScreenStack.cs +++ b/osu.Game/Screens/BackgroundScreenStack.cs @@ -21,7 +21,7 @@ namespace osu.Game.Screens //public float ParallaxAmount { set => parallax.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * value; } - public new void Push(BackgroundScreen screen) + public void Push(BackgroundScreen screen) { if (screen == null) return; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index bcb2bee601..11e649168f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -121,6 +121,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// Handle a blueprint requesting selection. /// /// The blueprint. + /// The input state at the point of selection. internal void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state) { if (state.Keyboard.ControlPressed) @@ -166,8 +167,6 @@ namespace osu.Game.Screens.Edit.Compose.Components var topLeft = new Vector2(float.MaxValue, float.MaxValue); var bottomRight = new Vector2(float.MinValue, float.MinValue); - bool hasSelection = false; - foreach (var blueprint in selectedBlueprints) { topLeft = Vector2.ComponentMin(topLeft, ToLocalSpace(blueprint.SelectionQuad.TopLeft)); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index f41b3cddc0..9b00a3998d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -131,7 +131,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private readonly float scrollOffset; /// - /// Transforms to a new value. + /// Transforms to a new value. /// /// The focus point in absolute coordinates local to the content. /// The size of the content. diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 0ba1e74aca..09977454f0 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -65,9 +65,6 @@ namespace osu.Game.Screens.Edit dependencies.Cache(beatDivisor); EditorMenuBar menuBar; - TimeInfoContainer timeInfo; - SummaryTimeline timeline; - PlaybackControl playback; var fileMenuItems = new List(); if (RuntimeInfo.IsDesktop) diff --git a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs index 50d524d1f5..1c53fc7088 100644 --- a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs +++ b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs @@ -60,14 +60,7 @@ namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents set => label.Colour = value; } - public Color4 BackgroundColour - { - get => content.Colour; - set => content.Colour = value; - } - private readonly OsuTextBox textBox; - private readonly Container content; private readonly OsuSpriteText label; public LabelledTextBox() diff --git a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs index b6b0332cf3..27b5aec4d3 100644 --- a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs +++ b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs @@ -13,15 +13,13 @@ namespace osu.Game.Screens.Multi.Components protected override void AddTabItem(TabItem tab, bool addToDropdown = true) { - if (tab is DisableableTabItem disableable) + if (tab is DisableableTabItem disableable) disableable.Enabled.BindTo(Enabled); base.AddTabItem(tab, addToDropdown); } - protected abstract class DisableableTabItem : TabItem + protected abstract class DisableableTabItem : TabItem { - public readonly BindableBool Enabled = new BindableBool(); - protected DisableableTabItem(T value) : base(value) { diff --git a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs index 51d3c93624..6570051040 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs @@ -25,8 +25,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components private void load(OsuColour colours) { OsuSpriteText summary; - OsuSpriteText levelRangeHigher; - OsuSpriteText levelRangeLower; Container flagContainer; LinkFlowContainer hostText; @@ -45,21 +43,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components Width = 22f, RelativeSizeAxes = Axes.Y, }, - /*new Container //todo: team banners - { - Width = 38f, - RelativeSizeAxes = Axes.Y, - CornerRadius = 2f, - Masking = true, - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"ad387e"), - }, - }, - },*/ hostText = new LinkFlowContainer { Anchor = Anchor.CentreLeft, @@ -101,13 +84,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components }, true); ParticipantCount.BindValueChanged(count => summary.Text = "participant".ToQuantity(count.NewValue), true); - - /*Participants.BindValueChanged(e => - { - var ranks = v.Select(u => u.Statistics.Ranks.Global); - levelRangeLower.Text = ranks.Min().ToString(); - levelRangeHigher.Text = ranks.Max().ToString(); - });*/ } } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 5798fce457..1297090a32 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -97,7 +97,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Font = OsuFont.GetFont(size: 30), - Current = Name + Current = RoomName }, }, }, diff --git a/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs b/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs index ccb957734f..b69cb9705d 100644 --- a/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs +++ b/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Multi.Match.Components AddItem(new GameTypeTimeshift()); } - private class GameTypePickerItem : DisableableTabItem + private class GameTypePickerItem : DisableableTabItem { private const float transition_duration = 200; diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index a944d965bd..a185c4db50 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -30,7 +30,6 @@ namespace osu.Game.Screens.Multi.Match.Components ReadyButton readyButton; ViewBeatmapButton viewBeatmapButton; HostInfo hostInfo; - RoomStatusInfo statusInfo; InternalChildren = new Drawable[] { @@ -63,7 +62,7 @@ namespace osu.Game.Screens.Multi.Match.Components new OsuSpriteText { Font = OsuFont.GetFont(size: 30), - Current = Name + Current = RoomName }, new RoomStatusInfo(), } diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 586a986111..359b5824c0 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -265,7 +265,7 @@ namespace osu.Game.Screens.Multi.Match.Components }; TypePicker.Current.BindValueChanged(type => typeLabel.Text = type.NewValue?.Name ?? string.Empty, true); - Name.BindValueChanged(name => NameField.Text = name.NewValue, true); + RoomName.BindValueChanged(name => NameField.Text = name.NewValue, true); Availability.BindValueChanged(availability => AvailabilityPicker.Current.Value = availability.NewValue, true); Type.BindValueChanged(type => TypePicker.Current.Value = type.NewValue, true); MaxParticipants.BindValueChanged(count => MaxParticipantsField.Text = count.NewValue?.ToString(), true); @@ -285,7 +285,7 @@ namespace osu.Game.Screens.Multi.Match.Components { hideError(); - Name.Value = NameField.Text; + RoomName.Value = NameField.Text; Availability.Value = AvailabilityPicker.Current.Value; Type.Value = TypePicker.Current.Value; diff --git a/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs b/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs index 8751e27552..9de4a61cde 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Multi.Match.Components AddItem(RoomAvailability.InviteOnly); } - private class RoomAvailabilityPickerItem : DisableableTabItem + private class RoomAvailabilityPickerItem : DisableableTabItem { private const float transition_duration = 200; diff --git a/osu.Game/Screens/Multi/MultiplayerComposite.cs b/osu.Game/Screens/Multi/MultiplayerComposite.cs index da6bba7865..8c09d576ff 100644 --- a/osu.Game/Screens/Multi/MultiplayerComposite.cs +++ b/osu.Game/Screens/Multi/MultiplayerComposite.cs @@ -16,8 +16,8 @@ namespace osu.Game.Screens.Multi [Resolved(typeof(Room))] protected Bindable RoomID { get; private set; } - [Resolved(typeof(Room))] - protected Bindable Name { get; private set; } + [Resolved(typeof(Room), nameof(Room.Name))] + protected Bindable RoomName { get; private set; } [Resolved(typeof(Room))] protected Bindable Host { get; private set; } diff --git a/osu.Game/Screens/Multi/MultiplayerSubScreen.cs b/osu.Game/Screens/Multi/MultiplayerSubScreen.cs index 65e501b114..ff94f63f01 100644 --- a/osu.Game/Screens/Multi/MultiplayerSubScreen.cs +++ b/osu.Game/Screens/Multi/MultiplayerSubScreen.cs @@ -3,22 +3,17 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Input.Bindings; using osu.Framework.Screens; using osu.Game.Graphics.Containers; -using osu.Game.Input.Bindings; namespace osu.Game.Screens.Multi { - public abstract class MultiplayerSubScreen : OsuScreen, IMultiplayerSubScreen, IKeyBindingHandler + public abstract class MultiplayerSubScreen : OsuScreen, IMultiplayerSubScreen { public override bool DisallowExternalBeatmapRulesetChanges => false; public virtual string ShortTitle => Title; - [Resolved(CanBeNull = true)] - protected OsuGame Game { get; private set; } - [Resolved(CanBeNull = true)] protected IRoomManager RoomManager { get; private set; } @@ -56,21 +51,6 @@ namespace osu.Game.Screens.Multi this.MoveToX(-200, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); } - public override bool OnPressed(GlobalAction action) - { - if (!this.IsCurrentScreen()) return false; - - if (action == GlobalAction.Back) - { - this.Exit(); - return true; - } - - return false; - } - - public bool OnReleased(GlobalAction action) => action == GlobalAction.Back; - public override string ToString() => Title; } } diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 385cbe20e5..6f473aaafa 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -171,7 +171,7 @@ namespace osu.Game.Screens.Multi /// /// Adds a to the list of available rooms. /// - /// The to add.< + /// The to add. private void addRoom(Room room) { var existing = rooms.FirstOrDefault(e => e.RoomID.Value == room.RoomID.Value); diff --git a/osu.Game/Screens/Play/GameplayClock.cs b/osu.Game/Screens/Play/GameplayClock.cs index 3efcfa0f65..b1948d02d5 100644 --- a/osu.Game/Screens/Play/GameplayClock.cs +++ b/osu.Game/Screens/Play/GameplayClock.cs @@ -8,7 +8,7 @@ namespace osu.Game.Screens.Play { /// /// A clock which is used for gameplay elements that need to follow audio time 1:1. - /// Exposed via DI by . + /// Exposed via DI by . /// /// The main purpose of this clock is to stop components using it from accidentally processing the main /// , as this should only be done once to ensure accuracy. diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index f833aa2bb7..5bf54877fc 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -72,7 +72,7 @@ namespace osu.Game.Screens.Play [Cached] [Cached(Type = typeof(IBindable>))] - protected readonly Bindable> Mods = new Bindable>(Array.Empty()); + protected new readonly Bindable> Mods = new Bindable>(Array.Empty()); private readonly bool allowPause; private readonly bool showResults; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 6a55fe278b..ebc6459abe 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -320,7 +320,6 @@ namespace osu.Game.Screens.Play private readonly Drawable facade; private LoadingAnimation loading; private Sprite backgroundSprite; - private ModDisplay modDisplay; public bool Loading { diff --git a/osu.Game/Screens/Select/Carousel/CarouselItem.cs b/osu.Game/Screens/Select/Carousel/CarouselItem.cs index a0f5969b3c..79c1a4cb6b 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselItem.cs @@ -31,8 +31,6 @@ namespace osu.Game.Screens.Select.Carousel } } - private int creationOrder; - protected CarouselItem() { DrawableRepresentation = new Lazy(CreateDrawableRepresentation); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index a78238c584..14c362b8ca 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -388,8 +388,6 @@ namespace osu.Game.Screens.Select { Logger.Log($"updating selection with beatmap:{beatmap?.ID.ToString() ?? "null"} ruleset:{ruleset?.ID.ToString() ?? "null"}"); - bool preview = false; - if (ruleset?.Equals(decoupledRuleset.Value) == false) { Logger.Log($"ruleset changed from \"{decoupledRuleset.Value}\" to \"{ruleset}\""); diff --git a/osu.Game/Skinning/ISkin.cs b/osu.Game/Skinning/ISkin.cs new file mode 100644 index 0000000000..0e67a1897c --- /dev/null +++ b/osu.Game/Skinning/ISkin.cs @@ -0,0 +1,24 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Audio.Sample; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Textures; + +namespace osu.Game.Skinning +{ + /// + /// Provides access to skinnable elements. + /// + public interface ISkin + { + Drawable GetDrawableComponent(string componentName); + + Texture GetTexture(string componentName); + + SampleChannel GetSample(string sampleName); + + TValue GetValue(Func query) where TConfiguration : SkinConfiguration; + } +} diff --git a/osu.Game/Skinning/ISkinSource.cs b/osu.Game/Skinning/ISkinSource.cs index 6d2b9e6fe2..337d2a87a4 100644 --- a/osu.Game/Skinning/ISkinSource.cs +++ b/osu.Game/Skinning/ISkinSource.cs @@ -2,25 +2,14 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Audio.Sample; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Textures; namespace osu.Game.Skinning { /// /// Provides access to skinnable elements. /// - public interface ISkinSource + public interface ISkinSource : ISkin { event Action SourceChanged; - - Drawable GetDrawableComponent(string componentName); - - Texture GetTexture(string componentName); - - SampleChannel GetSample(string sampleName); - - TValue GetValue(Func query) where TConfiguration : SkinConfiguration; } } diff --git a/osu.Game/Skinning/LocalSkinOverrideContainer.cs b/osu.Game/Skinning/LocalSkinOverrideContainer.cs index 955ef7b65b..f1ed14595e 100644 --- a/osu.Game/Skinning/LocalSkinOverrideContainer.cs +++ b/osu.Game/Skinning/LocalSkinOverrideContainer.cs @@ -22,18 +22,18 @@ namespace osu.Game.Skinning private readonly Bindable beatmapSkins = new Bindable(); private readonly Bindable beatmapHitsounds = new Bindable(); - private readonly ISkinSource source; + private readonly ISkin skin; private ISkinSource fallbackSource; - public LocalSkinOverrideContainer(ISkinSource source) + public LocalSkinOverrideContainer(ISkin skin) { - this.source = source; + this.skin = skin; } public Drawable GetDrawableComponent(string componentName) { Drawable sourceDrawable; - if (beatmapSkins.Value && (sourceDrawable = source.GetDrawableComponent(componentName)) != null) + if (beatmapSkins.Value && (sourceDrawable = skin.GetDrawableComponent(componentName)) != null) return sourceDrawable; return fallbackSource?.GetDrawableComponent(componentName); @@ -42,7 +42,7 @@ namespace osu.Game.Skinning public Texture GetTexture(string componentName) { Texture sourceTexture; - if (beatmapSkins.Value && (sourceTexture = source.GetTexture(componentName)) != null) + if (beatmapSkins.Value && (sourceTexture = skin.GetTexture(componentName)) != null) return sourceTexture; return fallbackSource.GetTexture(componentName); @@ -51,7 +51,7 @@ namespace osu.Game.Skinning public SampleChannel GetSample(string sampleName) { SampleChannel sourceChannel; - if (beatmapHitsounds.Value && (sourceChannel = source.GetSample(sampleName)) != null) + if (beatmapHitsounds.Value && (sourceChannel = skin.GetSample(sampleName)) != null) return sourceChannel; return fallbackSource?.GetSample(sampleName); @@ -60,7 +60,7 @@ namespace osu.Game.Skinning public TValue GetValue(Func query) where TConfiguration : SkinConfiguration { TValue val; - if ((source as Skin)?.Configuration is TConfiguration conf) + if ((skin as Skin)?.Configuration is TConfiguration conf) if (beatmapSkins.Value && (val = query.Invoke(conf)) != null) return val; diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 1d14f9cd6a..09c0d3d0bc 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -8,14 +8,12 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Skinning { - public abstract class Skin : IDisposable, ISkinSource + public abstract class Skin : IDisposable, ISkin { public readonly SkinInfo SkinInfo; public virtual SkinConfiguration Configuration { get; protected set; } - public event Action SourceChanged; - public abstract Drawable GetDrawableComponent(string componentName); public abstract SampleChannel GetSample(string sampleName); diff --git a/osu.Game/Tests/Visual/AllPlayersTestCase.cs b/osu.Game/Tests/Visual/AllPlayersTestCase.cs index 3e1f408a16..6e78851e31 100644 --- a/osu.Game/Tests/Visual/AllPlayersTestCase.cs +++ b/osu.Game/Tests/Visual/AllPlayersTestCase.cs @@ -28,7 +28,7 @@ namespace osu.Game.Tests.Visual { Player p = null; AddStep(r.Name, () => p = loadPlayerFor(r)); - AddUntilStep(() => + AddUntilStep("player loaded", () => { if (p?.IsLoaded == true) { @@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual } return false; - }, "player loaded"); + }); AddCheckSteps(); } diff --git a/osu.Game/Tests/Visual/EditorClockTestCase.cs b/osu.Game/Tests/Visual/EditorClockTestCase.cs index 7f36a0e142..c71c2ae857 100644 --- a/osu.Game/Tests/Visual/EditorClockTestCase.cs +++ b/osu.Game/Tests/Visual/EditorClockTestCase.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual public abstract class EditorClockTestCase : OsuTestCase { protected readonly BindableBeatDivisor BeatDivisor = new BindableBeatDivisor(); - protected readonly EditorClock Clock; + protected new readonly EditorClock Clock; protected EditorClockTestCase() { diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index c08a6a4bcb..1f475209a4 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual [Cached(Type = typeof(IBindable>))] protected readonly Bindable> Mods = new Bindable>(Array.Empty()); - protected DependencyContainer Dependencies { get; private set; } + protected new DependencyContainer Dependencies { get; private set; } private readonly Lazy localStorage; protected Storage LocalStorage => localStorage.Value; diff --git a/osu.Game/Tests/Visual/PlayerTestCase.cs b/osu.Game/Tests/Visual/PlayerTestCase.cs index fca4fccae0..b9c7933cfb 100644 --- a/osu.Game/Tests/Visual/PlayerTestCase.cs +++ b/osu.Game/Tests/Visual/PlayerTestCase.cs @@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual public void SetUpSteps() { AddStep(ruleset.RulesetInfo.Name, loadPlayer); - AddUntilStep(() => Player.IsLoaded && Player.Alpha == 1, "player loaded"); + AddUntilStep("player loaded", () => Player.IsLoaded && Player.Alpha == 1); } protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 22afce9c86..e25921c486 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -5,7 +5,6 @@ Library AnyCPU true - 0 From 1766ed8f9e2d28de824a20432c79e050d012dc34 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 25 Apr 2019 18:05:46 +0900 Subject: [PATCH 0645/5608] Fix warnings/remove obsolete usages --- .../Profile/Header/BottomHeaderContainer.cs | 8 ++++---- .../Profile/Header/DetailHeaderContainer.cs | 3 +-- osu.Game/Overlays/Profile/Header/RankGraph.cs | 12 ++++-------- .../Overlays/Profile/Header/TopHeaderContainer.cs | 15 +++++---------- osu.Game/Overlays/Profile/ProfileHeader.cs | 4 ---- 5 files changed, 14 insertions(+), 28 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 04b70ea10f..9eb6feec8e 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -48,12 +48,12 @@ namespace osu.Game.Overlays.Profile.Header Spacing = new Vector2(0, 10), Children = new Drawable[] { - bottomTopLinkContainer = new LinkFlowContainer(text => text.TextSize = 12) + bottomTopLinkContainer = new LinkFlowContainer(text => text.Font = text.Font.With(size: 12)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, }, - bottomLinkContainer = new LinkFlowContainer(text => text.TextSize = 12) + bottomLinkContainer = new LinkFlowContainer(text => text.Font = text.Font.With(size: 12)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -68,7 +68,7 @@ namespace osu.Game.Overlays.Profile.Header private void updateDisplay(User user) { - void bold(SpriteText t) => t.Font = @"Exo2.0-Bold"; + void bold(SpriteText t) => t.Font = t.Font.With(weight: FontWeight.Bold); void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); bottomTopLinkContainer.Clear(); @@ -113,7 +113,7 @@ namespace osu.Game.Overlays.Profile.Header bottomLinkContainer.AddIcon(icon, text => { - text.TextSize = 10; + text.Font = text.Font.With(size: 10); text.Colour = communityUserGrayGreenLighter; }); if (link != null) diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index 19894f0301..84611b3bf1 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -213,8 +213,7 @@ namespace osu.Game.Overlays.Profile.Header }, rankCount = new OsuSpriteText { - Font = "Exo2.0-Bold", - TextSize = 12, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre } diff --git a/osu.Game/Overlays/Profile/Header/RankGraph.cs b/osu.Game/Overlays/Profile/Header/RankGraph.cs index 01f16fe942..d66f2306a0 100644 --- a/osu.Game/Overlays/Profile/Header/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/RankGraph.cs @@ -43,8 +43,7 @@ namespace osu.Game.Overlays.Profile.Header Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = "No recent plays", - TextSize = 12, - Font = @"Exo2.0-Regular", + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular) }, graph = new RankChartLineGraph { @@ -227,14 +226,12 @@ namespace osu.Game.Overlays.Profile.Header { new OsuSpriteText { - Font = "Exo2.0-Bold", - TextSize = 12, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), Text = "Global Ranking " }, globalRankingText = new OsuSpriteText { - Font = "Exo2.0-Regular", - TextSize = 12, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular), Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, } @@ -242,8 +239,7 @@ namespace osu.Game.Overlays.Profile.Header }, timeText = new OsuSpriteText { - TextSize = 12, - Font = "Exo2.0-Regular" + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular), } } } diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 8e4d72c702..80721af42f 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -75,8 +75,7 @@ namespace osu.Game.Overlays.Profile.Header { usernameText = new OsuSpriteText { - Font = "Exo2.0-Regular", - TextSize = 24 + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Regular) }, openUserExternally = new ExternalLinkButton { @@ -96,8 +95,7 @@ namespace osu.Game.Overlays.Profile.Header { titleText = new OsuSpriteText { - TextSize = 18, - Font = "Exo2.0-Regular" + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Regular) }, supporterTag = new SupporterIcon { @@ -123,8 +121,7 @@ namespace osu.Game.Overlays.Profile.Header }, userCountryText = new OsuSpriteText { - Font = "Exo2.0-Regular", - TextSize = 17.5f, + Font = OsuFont.GetFont(size: 17.5f, weight: FontWeight.Regular), Margin = new MarginPadding { Left = 40 }, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, @@ -185,17 +182,15 @@ namespace osu.Game.Overlays.Profile.Header { new OsuSpriteText { - TextSize = 15, + Font = OsuFont.GetFont(size: 15), Text = left, - Font = "Exo2.0-Medium" }, new OsuSpriteText { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - TextSize = 15, + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), Text = right, - Font = "Exo2.0-Bold" }, }; } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 776fcbb8b7..6238d1bc53 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -12,7 +12,6 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Profile @@ -29,9 +28,6 @@ namespace osu.Game.Overlays.Profile { CenterHeaderContainer centerHeaderContainer; DetailHeaderContainer detailHeaderContainer; - Container expandedDetailContainer; - FillFlowContainer hiddenDetailContainer, headerDetailContainer; - SpriteIcon expandButtonIcon; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; From b33c0e9a9337763df37951623d29705d132b5f5a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 25 Apr 2019 18:42:19 +0900 Subject: [PATCH 0646/5608] Cleanup bottom header container --- .../Online/TestCaseUserProfileHeader.cs | 1 + .../Profile/Header/BottomHeaderContainer.cs | 108 +++++++++--------- 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs index 98bad9831f..bc2ff708c5 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs @@ -21,6 +21,7 @@ namespace osu.Game.Tests.Visual.Online typeof(RankGraph), typeof(LineGraph), typeof(ProfileHeaderTabControl), + typeof(BottomHeaderContainer) }; [Resolved] diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 9eb6feec8e..39dd1bd028 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -20,18 +20,21 @@ namespace osu.Game.Overlays.Profile.Header { public class BottomHeaderContainer : CompositeDrawable { - private LinkFlowContainer bottomTopLinkContainer; - private LinkFlowContainer bottomLinkContainer; - private Color4 linkBlue, communityUserGrayGreenLighter; - public readonly Bindable User = new Bindable(); + private LinkFlowContainer topLinkContainer; + private LinkFlowContainer bottomLinkContainer; + + private Color4 iconColour; + + public BottomHeaderContainer() + { + AutoSizeAxes = Axes.Y; + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { - AutoSizeAxes = Axes.Y; - User.ValueChanged += e => updateDisplay(e.NewValue); - InternalChildren = new Drawable[] { new Box @@ -48,7 +51,7 @@ namespace osu.Game.Overlays.Profile.Header Spacing = new Vector2(0, 10), Children = new Drawable[] { - bottomTopLinkContainer = new LinkFlowContainer(text => text.Font = text.Font.With(size: 12)) + topLinkContainer = new LinkFlowContainer(text => text.Font = text.Font.With(size: 12)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -62,80 +65,55 @@ namespace osu.Game.Overlays.Profile.Header } }; - linkBlue = colours.BlueLight; - communityUserGrayGreenLighter = colours.CommunityUserGrayGreenLighter; + iconColour = colours.CommunityUserGrayGreenLighter; + + User.BindValueChanged(user => updateDisplay(user.NewValue)); } private void updateDisplay(User user) { - void bold(SpriteText t) => t.Font = t.Font.With(weight: FontWeight.Bold); - void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); - - bottomTopLinkContainer.Clear(); + topLinkContainer.Clear(); bottomLinkContainer.Clear(); if (user == null) return; if (user.JoinDate.ToUniversalTime().Year < 2008) - { - bottomTopLinkContainer.AddText("Here since the beginning"); - } + topLinkContainer.AddText("Here since the beginning"); else { - bottomTopLinkContainer.AddText("Joined "); - bottomTopLinkContainer.AddText(new DrawableDate(user.JoinDate), bold); + topLinkContainer.AddText("Joined "); + topLinkContainer.AddText(new DrawableDate(user.JoinDate), embolden); } - addSpacer(bottomTopLinkContainer); + addSpacer(topLinkContainer); if (user.PlayStyles?.Length > 0) { - bottomTopLinkContainer.AddText("Plays with "); - bottomTopLinkContainer.AddText(string.Join(", ", user.PlayStyles.Select(style => style.GetDescription())), bold); + topLinkContainer.AddText("Plays with "); + topLinkContainer.AddText(string.Join(", ", user.PlayStyles.Select(style => style.GetDescription())), embolden); - addSpacer(bottomTopLinkContainer); + addSpacer(topLinkContainer); } if (user.LastVisit.HasValue) { - bottomTopLinkContainer.AddText("Last seen "); - bottomTopLinkContainer.AddText(new DrawableDate(user.LastVisit.Value), bold); + topLinkContainer.AddText("Last seen "); + topLinkContainer.AddText(new DrawableDate(user.LastVisit.Value), embolden); - addSpacer(bottomTopLinkContainer); + addSpacer(topLinkContainer); } - bottomTopLinkContainer.AddText("Contributed "); - bottomTopLinkContainer.AddLink($@"{user.PostCount:#,##0} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: bold); - - void tryAddInfo(IconUsage icon, string content, string link = null) - { - if (string.IsNullOrEmpty(content)) return; - - bottomLinkContainer.AddIcon(icon, text => - { - text.Font = text.Font.With(size: 10); - text.Colour = communityUserGrayGreenLighter; - }); - if (link != null) - { - bottomLinkContainer.AddLink(" " + content, link, creationParameters: text => - { - bold(text); - text.Colour = linkBlue; - }); - } - else - bottomLinkContainer.AddText(" " + content, bold); - - addSpacer(bottomLinkContainer); - } + topLinkContainer.AddText("Contributed "); + topLinkContainer.AddLink($@"{user.PostCount:#,##0} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: embolden); string websiteWithoutProtcol = user.Website; if (!string.IsNullOrEmpty(websiteWithoutProtcol)) { - int protocolIndex = websiteWithoutProtcol.IndexOf("//", StringComparison.Ordinal); - if (protocolIndex >= 0) - websiteWithoutProtcol = websiteWithoutProtcol.Substring(protocolIndex + 2); + if (Uri.TryCreate(websiteWithoutProtcol, UriKind.Absolute, out var uri)) + { + websiteWithoutProtcol = uri.Host + uri.PathAndQuery + uri.Fragment; + websiteWithoutProtcol = websiteWithoutProtcol.TrimEnd('/'); + } } tryAddInfo(FontAwesome.Solid.MapMarker, user.Location); @@ -149,5 +127,27 @@ namespace osu.Game.Overlays.Profile.Header tryAddInfo(FontAwesome.Brands.Lastfm, user.Lastfm, $@"https://last.fm/users/{user.Lastfm}"); tryAddInfo(FontAwesome.Solid.Link, websiteWithoutProtcol, user.Website); } + + private void addSpacer(OsuTextFlowContainer textFlow) => textFlow.AddArbitraryDrawable(new Container { Width = 15 }); + + private void tryAddInfo(IconUsage icon, string content, string link = null) + { + if (string.IsNullOrEmpty(content)) return; + + bottomLinkContainer.AddIcon(icon, text => + { + text.Font = text.Font.With(size: 10); + text.Colour = iconColour; + }); + + if (link != null) + bottomLinkContainer.AddLink(" " + content, link, creationParameters: embolden); + else + bottomLinkContainer.AddText(" " + content, embolden); + + addSpacer(bottomLinkContainer); + } + + private void embolden(SpriteText text) => text.Font = text.Font.With(weight: FontWeight.Bold); } } From 0eca9b9683e25c81f6d509d9bd8f749967ca56ec Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 25 Apr 2019 18:43:29 +0900 Subject: [PATCH 0647/5608] Center -> centre --- osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs | 1 + .../{CenterHeaderContainer.cs => CentreHeaderContainer.cs} | 2 +- osu.Game/Overlays/Profile/ProfileHeader.cs | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) rename osu.Game/Overlays/Profile/Header/{CenterHeaderContainer.cs => CentreHeaderContainer.cs} (99%) diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs index bc2ff708c5..531f30de83 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs @@ -21,6 +21,7 @@ namespace osu.Game.Tests.Visual.Online typeof(RankGraph), typeof(LineGraph), typeof(ProfileHeaderTabControl), + typeof(CentreHeaderContainer), typeof(BottomHeaderContainer) }; diff --git a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs similarity index 99% rename from osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs rename to osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index 3d0b9b9db4..0ad343bb7e 100644 --- a/osu.Game/Overlays/Profile/Header/CenterHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header { - public class CenterHeaderContainer : CompositeDrawable + public class CentreHeaderContainer : CompositeDrawable { public Action DetailsVisibilityAction; private bool detailsVisible; diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 6238d1bc53..3e257e19bf 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays.Profile public ProfileHeader() { - CenterHeaderContainer centerHeaderContainer; + CentreHeaderContainer centreHeaderContainer; DetailHeaderContainer detailHeaderContainer; RelativeSizeAxes = Axes.X; @@ -91,7 +91,7 @@ namespace osu.Game.Overlays.Profile RelativeSizeAxes = Axes.X, User = { BindTarget = User }, }, - centerHeaderContainer = new CenterHeaderContainer + centreHeaderContainer = new CentreHeaderContainer { RelativeSizeAxes = Axes.X, User = { BindTarget = User }, @@ -118,7 +118,7 @@ namespace osu.Game.Overlays.Profile infoTabControl.AddItem("Info"); infoTabControl.AddItem("Modding"); - centerHeaderContainer.DetailsVisibilityAction = visible => detailHeaderContainer.Alpha = visible ? 0 : 1; + centreHeaderContainer.DetailsVisibilityAction = visible => detailHeaderContainer.Alpha = visible ? 0 : 1; User.ValueChanged += e => updateDisplay(e.NewValue); } From 9d5b81165e4432b8e8299b43f8fd2c63ba8eab2a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 25 Apr 2019 19:51:05 +0900 Subject: [PATCH 0648/5608] Adjust button stylings --- .../Visual/Online/TestCaseUserProfileHeader.cs | 3 ++- .../Profile/Header/CentreHeaderContainer.cs | 15 +++++++++++++-- .../Profile/Header/ProfileHeaderButton.cs | 7 ++++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs index 531f30de83..e425c25787 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs @@ -22,7 +22,8 @@ namespace osu.Game.Tests.Visual.Online typeof(LineGraph), typeof(ProfileHeaderTabControl), typeof(CentreHeaderContainer), - typeof(BottomHeaderContainer) + typeof(BottomHeaderContainer), + typeof(ProfileHeaderButton) }; [Resolved] diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index 0ad343bb7e..658dd79570 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -104,7 +105,7 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.Y, Padding = new MarginPadding { Vertical = 10 }, Width = UserProfileOverlay.CONTENT_X_MARGIN, - Child = detailsToggleButton = new ProfileHeaderButton + Child = detailsToggleButton = new ExpandButton { RelativeSizeAxes = Axes.Y, Anchor = Anchor.Centre, @@ -115,7 +116,7 @@ namespace osu.Game.Overlays.Profile.Header { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(20), + Size = new Vector2(20, 12), Icon = FontAwesome.Solid.ChevronUp, }, } @@ -230,5 +231,15 @@ namespace osu.Game.Overlays.Profile.Header hiddenDetailGlobal.Content = user.Statistics?.Ranks.Global?.ToString("#,##0") ?? "-"; hiddenDetailCountry.Content = user.Statistics?.Ranks.Country?.ToString("#,##0") ?? "-"; } + + private class ExpandButton : ProfileHeaderButton + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + IdleColour = colours.CommunityUserGrayGreen; + HoverColour = colours.CommunityUserGrayGreen.Darken(0.2f); + } + } } } diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs b/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs index 6d9ab7a4d8..e8c8788a10 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs +++ b/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs @@ -2,10 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osuTK.Graphics; @@ -22,8 +22,9 @@ namespace osu.Game.Overlays.Profile.Header public ProfileHeaderButton() { - HoverColour = Color4.Black.Opacity(0.75f); - IdleColour = Color4.Black.Opacity(0.7f); + IdleColour = Color4.Black; + HoverColour = OsuColour.Gray(0.1f); + AutoSizeAxes = Axes.X; base.Content.Add(new CircularContainer From c6b3197dd0081aec6db80a2b1c7f00cb13124866 Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Thu, 25 Apr 2019 13:56:57 +0300 Subject: [PATCH 0649/5608] Add AdjustRank and use it in Hidden Mod --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 3 ++ .../Visual/Gameplay/TestCasePlayerLoader.cs | 3 ++ .../Mods/IApplicableToScoreProcessor.cs | 3 ++ osu.Game/Rulesets/Mods/ModFlashlight.cs | 3 ++ osu.Game/Rulesets/Mods/ModHidden.cs | 18 +++++++++- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 3 ++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 34 ++++++++----------- osu.Game/Screens/Play/Player.cs | 2 ++ 8 files changed, 48 insertions(+), 21 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index f3c7939a94..445f81c6d4 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osuTK; using osuTK.Graphics; @@ -41,6 +42,8 @@ namespace osu.Game.Rulesets.Osu.Mods scoreProcessor.Health.ValueChanged += health => { blinds.AnimateClosedness((float)health.NewValue); }; } + public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; + /// /// Element for the Blinds mod drawing 2 black boxes covering the whole screen which resize inside a restricted area with some leniency. /// diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs index f58c0d35b3..425d8fcda1 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; using osu.Game.Screens; using osu.Game.Screens.Play; @@ -110,6 +111,8 @@ namespace osu.Game.Tests.Visual.Gameplay { Applied = true; } + + public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; } private class TestPlayer : Player diff --git a/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs b/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs index 1d0ed94ef4..34e8d858f6 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Mods { @@ -11,5 +12,7 @@ namespace osu.Game.Rulesets.Mods public interface IApplicableToScoreProcessor : IApplicableMod { void ApplyToScoreProcessor(ScoreProcessor scoreProcessor); + + ScoreRank AdjustRank(ScoreRank rank, double accuracy); } } diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 0ad99d13ff..f47306d16e 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -16,6 +16,7 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osuTK; using osuTK.Graphics; @@ -46,6 +47,8 @@ namespace osu.Game.Rulesets.Mods Combo.BindTo(scoreProcessor.Combo); } + public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; + public virtual void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { var flashlight = CreateFlashlight(); diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index 389edb5a35..c55c45c9fa 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -9,6 +9,7 @@ using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Mods { @@ -35,7 +36,22 @@ namespace osu.Game.Rulesets.Mods public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { - scoreProcessor.AdjustRank = true; + // Default value of ScoreProcessor's Rank in Hidden Mod should bes SS+ + scoreProcessor.Rank.Value = ScoreRank.XH; + } + + // TODO: Other mods that uses AdjustRank might have some issues due to rank changes + public ScoreRank AdjustRank(ScoreRank rank, double accuracy) + { + switch (rank) + { + case ScoreRank.X: + return ScoreRank.XH; + case ScoreRank.S: + return ScoreRank.SH; + default: + return rank; + } } protected virtual void ApplyHiddenState(DrawableHitObject hitObject, ArmedState state) diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 6a82050d26..809661db8e 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Mods { @@ -24,6 +25,8 @@ namespace osu.Game.Rulesets.Mods scoreProcessor.FailConditions += FailCondition; } + public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; + protected virtual bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Combo.Value == 0; } } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index b1cd78dde6..9f31cb8d7c 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -7,9 +7,11 @@ using System.Diagnostics; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Extensions; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.TypeExtensions; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; using osu.Game.Scoring; @@ -60,6 +62,11 @@ namespace osu.Game.Rulesets.Scoring /// public readonly BindableInt Combo = new BindableInt(); + /// + /// The current selected mods + /// + public readonly Bindable> Mods = new Bindable>(Array.Empty()); + /// /// Create a for this processor. /// @@ -95,34 +102,22 @@ namespace osu.Game.Rulesets.Scoring /// protected virtual bool DefaultFailCondition => Health.Value == Health.MinValue; - private bool adjustRank; - - /// - /// Used by specific mods to adjust . - /// - public bool AdjustRank - { - get => adjustRank; - - set - { - adjustRank = value; - Rank.Value = rankFrom(Accuracy.Value); // Update rank immediately if AdjustRank was changed - } - } - protected ScoreProcessor() { Combo.ValueChanged += delegate { HighestCombo.Value = Math.Max(HighestCombo.Value, Combo.Value); }; - Accuracy.ValueChanged += delegate { Rank.Value = rankFrom(Accuracy.Value); }; + Accuracy.ValueChanged += delegate + { + foreach (var mod in Mods.Value.OfType()) + Rank.Value = mod.AdjustRank(rankFrom(Accuracy.Value), Accuracy.Value); + }; } private ScoreRank rankFrom(double acc) { if (acc == 1) - return (adjustRank ? ScoreRank.XH : ScoreRank.X); + return ScoreRank.X; if (acc > 0.95) - return (adjustRank ? ScoreRank.SH : ScoreRank.S); + return ScoreRank.S; if (acc > 0.9) return ScoreRank.A; if (acc > 0.8) @@ -146,7 +141,6 @@ namespace osu.Game.Rulesets.Scoring Rank.Value = ScoreRank.X; HighestCombo.Value = 0; - AdjustRank = false; HasFailed = false; } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index f833aa2bb7..5e2880e24b 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -106,6 +106,8 @@ namespace osu.Game.Screens.Play showStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); ScoreProcessor = DrawableRuleset.CreateScoreProcessor(); + ScoreProcessor.Mods.BindTo(Mods); + if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); From 2caea38f8c4f4e672a12197d03aee73e18e646cc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 25 Apr 2019 20:05:59 +0900 Subject: [PATCH 0650/5608] Cleanup centre header container --- .../Profile/Header/BottomHeaderContainer.cs | 4 +-- .../Profile/Header/CentreHeaderContainer.cs | 36 ++++++++++--------- .../Profile/Header/OverlinedInfoContainer.cs | 3 +- .../Profile/Header/ProfileHeaderButton.cs | 4 +-- osu.Game/Overlays/Profile/ProfileHeader.cs | 2 +- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 39dd1bd028..f97fecb913 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -35,6 +35,8 @@ namespace osu.Game.Overlays.Profile.Header [BackgroundDependencyLoader] private void load(OsuColour colours) { + iconColour = colours.CommunityUserGrayGreenLighter; + InternalChildren = new Drawable[] { new Box @@ -65,8 +67,6 @@ namespace osu.Game.Overlays.Profile.Header } }; - iconColour = colours.CommunityUserGrayGreenLighter; - User.BindValueChanged(user => updateDisplay(user.NewValue)); } diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index 658dd79570..935e25e4b8 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.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 osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -21,8 +20,8 @@ namespace osu.Game.Overlays.Profile.Header { public class CentreHeaderContainer : CompositeDrawable { - public Action DetailsVisibilityAction; - private bool detailsVisible; + public readonly BindableBool DetailsVisible = new BindableBool(true); + public readonly Bindable User = new Bindable(); private OsuSpriteText followerText; private OsuSpriteText levelBadgeText; @@ -30,18 +29,20 @@ namespace osu.Game.Overlays.Profile.Header private Bar levelProgressBar; private OsuSpriteText levelProgressText; - private OverlinedInfoContainer hiddenDetailGlobal, hiddenDetailCountry; + private OverlinedInfoContainer hiddenDetailGlobal; + private OverlinedInfoContainer hiddenDetailCountry; - public readonly Bindable User = new Bindable(); + public CentreHeaderContainer() + { + Height = 60; + } [BackgroundDependencyLoader] private void load(OsuColour colours, TextureStore textures) { - Container hiddenDetailContainer, expandedDetailContainer; + Container hiddenDetailContainer; + Container expandedDetailContainer; SpriteIcon expandButtonIcon; - ProfileHeaderButton detailsToggleButton; - Height = 60; - User.ValueChanged += e => updateDisplay(e.NewValue); InternalChildren = new Drawable[] { @@ -105,11 +106,12 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.Y, Padding = new MarginPadding { Vertical = 10 }, Width = UserProfileOverlay.CONTENT_X_MARGIN, - Child = detailsToggleButton = new ExpandButton + Child = new ExpandButton { RelativeSizeAxes = Axes.Y, Anchor = Anchor.Centre, Origin = Anchor.Centre, + Action = () => DetailsVisible.Toggle(), Children = new Drawable[] { expandButtonIcon = new SpriteIcon @@ -210,14 +212,14 @@ namespace osu.Game.Overlays.Profile.Header } }; - detailsToggleButton.Action = () => + DetailsVisible.BindValueChanged(visible => { - detailsVisible = !detailsVisible; - expandButtonIcon.Icon = detailsVisible ? FontAwesome.Solid.ChevronDown : FontAwesome.Solid.ChevronUp; - hiddenDetailContainer.Alpha = detailsVisible ? 1 : 0; - expandedDetailContainer.Alpha = detailsVisible ? 0 : 1; - DetailsVisibilityAction(detailsVisible); - }; + expandButtonIcon.Icon = visible.NewValue ? FontAwesome.Solid.ChevronUp : FontAwesome.Solid.ChevronDown; + hiddenDetailContainer.Alpha = visible.NewValue ? 1 : 0; + expandedDetailContainer.Alpha = visible.NewValue ? 0 : 1; + }, true); + + User.BindValueChanged(user => updateDisplay(user.NewValue)); } private void updateDisplay(User user) diff --git a/osu.Game/Overlays/Profile/Header/OverlinedInfoContainer.cs b/osu.Game/Overlays/Profile/Header/OverlinedInfoContainer.cs index 6d15f96eea..2eb84c9d71 100644 --- a/osu.Game/Overlays/Profile/Header/OverlinedInfoContainer.cs +++ b/osu.Game/Overlays/Profile/Header/OverlinedInfoContainer.cs @@ -13,7 +13,8 @@ namespace osu.Game.Overlays.Profile.Header public class OverlinedInfoContainer : CompositeDrawable { private readonly Circle line; - private readonly OsuSpriteText title, content; + private readonly OsuSpriteText title; + private readonly OsuSpriteText content; public string Title { diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs b/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs index e8c8788a10..300767cf0d 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs +++ b/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs @@ -22,11 +22,11 @@ namespace osu.Game.Overlays.Profile.Header public ProfileHeaderButton() { + AutoSizeAxes = Axes.X; + IdleColour = Color4.Black; HoverColour = OsuColour.Gray(0.1f); - AutoSizeAxes = Axes.X; - base.Content.Add(new CircularContainer { Masking = true, diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 3e257e19bf..3ccf2af061 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -118,7 +118,7 @@ namespace osu.Game.Overlays.Profile infoTabControl.AddItem("Info"); infoTabControl.AddItem("Modding"); - centreHeaderContainer.DetailsVisibilityAction = visible => detailHeaderContainer.Alpha = visible ? 0 : 1; + centreHeaderContainer.DetailsVisible.BindValueChanged(visible => detailHeaderContainer.Alpha = visible.NewValue ? 1 : 0, true); User.ValueChanged += e => updateDisplay(e.NewValue); } From 8329e53b6ceea408c7c13fb1153ba4b29f1d1a09 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 25 Apr 2019 20:08:14 +0900 Subject: [PATCH 0651/5608] Remove extra space from header title --- osu.Game/Overlays/Profile/ProfileHeader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 3ccf2af061..d9557952df 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -144,7 +144,7 @@ namespace osu.Game.Overlays.Profile { public ProfileHeaderTitle() { - Title = "Player "; + Title = "Player"; Section = "Info"; } From f8c5ee457bcdc3f46215860d74c91fa3394340dd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 25 Apr 2019 20:09:42 +0900 Subject: [PATCH 0652/5608] Reduce tabcontrol spacing --- osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs index e7c9676550..c6b66b48d0 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs +++ b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Profile.Header public ProfileHeaderTabControl() { TabContainer.Masking = false; - TabContainer.Spacing = new Vector2(20, 0); + TabContainer.Spacing = new Vector2(15, 0); AddInternal(bar = new Box { From 619071b7ee1fb4d241e264feeb22b32d43952e11 Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Thu, 25 Apr 2019 14:23:00 +0300 Subject: [PATCH 0653/5608] Unnecessary 'using' directive --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index a4ba541499..aed5631f0f 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -7,7 +7,6 @@ using System.Diagnostics; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Extensions; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.TypeExtensions; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; From 9ce7d0416bc4dfdeb865507b5926565488b92970 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 25 Apr 2019 23:16:08 +0900 Subject: [PATCH 0654/5608] Fix framework version --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 25a98c9b74..2f0266ce07 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + From 838325fed41503c00b909da2067bae8b2bb257c1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 25 Apr 2019 20:30:16 +0900 Subject: [PATCH 0655/5608] Remove HasTooltipContainer, use separate composites --- .../Online/TestCaseUserProfileHeader.cs | 1 + .../Profile/Header/CentreHeaderContainer.cs | 55 ++------------- .../Profile/Header/DetailHeaderContainer.cs | 38 +--------- .../Overlays/Profile/Header/LevelBadge.cs | 57 +++++++++++++++ .../Profile/Header/LevelProgressBar.cs | 65 +++++++++++++++++ .../Profile/Header/OverlinedTotalPlayTime.cs | 69 +++++++++++++++++++ osu.Game/Overlays/Profile/ProfileHeader.cs | 6 -- 7 files changed, 201 insertions(+), 90 deletions(-) create mode 100644 osu.Game/Overlays/Profile/Header/LevelBadge.cs create mode 100644 osu.Game/Overlays/Profile/Header/LevelProgressBar.cs create mode 100644 osu.Game/Overlays/Profile/Header/OverlinedTotalPlayTime.cs diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs index e425c25787..0f1e954224 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs @@ -23,6 +23,7 @@ namespace osu.Game.Tests.Visual.Online typeof(ProfileHeaderTabControl), typeof(CentreHeaderContainer), typeof(BottomHeaderContainer), + typeof(DetailHeaderContainer), typeof(ProfileHeaderButton) }; diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index 935e25e4b8..e10d259ca9 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -11,10 +11,8 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Users; using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header { @@ -24,11 +22,6 @@ namespace osu.Game.Overlays.Profile.Header public readonly Bindable User = new Bindable(); private OsuSpriteText followerText; - private OsuSpriteText levelBadgeText; - - private Bar levelProgressBar; - private OsuSpriteText levelProgressText; - private OverlinedInfoContainer hiddenDetailGlobal; private OverlinedInfoContainer hiddenDetailCountry; @@ -132,56 +125,24 @@ namespace osu.Game.Overlays.Profile.Header Margin = new MarginPadding { Right = UserProfileOverlay.CONTENT_X_MARGIN }, Children = new Drawable[] { - new ProfileHeader.HasTooltipContainer + new LevelBadge { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Size = new Vector2(40), - TooltipText = "Level", - Children = new Drawable[] - { - new Sprite - { - RelativeSizeAxes = Axes.Both, - Texture = textures.Get("Profile/levelbadge"), - Colour = colours.Yellow, - }, - levelBadgeText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 20) - } - } + User = { BindTarget = User } }, - expandedDetailContainer = new ProfileHeader.HasTooltipContainer + expandedDetailContainer = new Container { - TooltipText = "Progress to next level", Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Width = 200, Height = 6, Margin = new MarginPadding { Right = 50 }, - Children = new Drawable[] + Child = new LevelProgressBar { - new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Child = levelProgressBar = new Bar - { - RelativeSizeAxes = Axes.Both, - BackgroundColour = Color4.Black, - Direction = BarDirection.LeftToRight, - AccentColour = colours.Yellow - } - }, - levelProgressText = new OsuSpriteText - { - Anchor = Anchor.BottomRight, - Origin = Anchor.TopRight, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold) - } + RelativeSizeAxes = Axes.Both, + User = { BindTarget = User } } }, hiddenDetailContainer = new FillFlowContainer @@ -226,10 +187,6 @@ namespace osu.Game.Overlays.Profile.Header { followerText.Text = user.FollowerCount?.Length > 0 ? user.FollowerCount[0].ToString("#,##0") : "0"; - levelBadgeText.Text = user.Statistics?.Level.Current.ToString() ?? "0"; - levelProgressBar.Length = user.Statistics?.Level.Progress / 100f ?? 0; - levelProgressText.Text = user.Statistics?.Level.Progress.ToString("0'%'"); - hiddenDetailGlobal.Content = user.Statistics?.Ranks.Global?.ToString("#,##0") ?? "-"; hiddenDetailCountry.Content = user.Statistics?.Ranks.Country?.ToString("#,##0") ?? "-"; } diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index 84611b3bf1..62e57fef79 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -20,8 +20,7 @@ namespace osu.Game.Overlays.Profile.Header { public class DetailHeaderContainer : CompositeDrawable { - private ProfileHeader.HasTooltipContainer totalPlayTimeTooltip; - private OverlinedInfoContainer totalPlayTimeInfo, medalInfo, ppInfo; + private OverlinedInfoContainer medalInfo, ppInfo; private readonly Dictionary scoreRankInfos = new Dictionary(); private OverlinedInfoContainer detailGlobalRank, detailCountryRank; private RankGraph rankGraph; @@ -65,15 +64,9 @@ namespace osu.Game.Overlays.Profile.Header Spacing = new Vector2(10, 0), Children = new Drawable[] { - totalPlayTimeTooltip = new ProfileHeader.HasTooltipContainer + new OverlinedTotalPlayTime { - AutoSizeAxes = Axes.Both, - TooltipText = "0 hours", - Child = totalPlayTimeInfo = new OverlinedInfoContainer - { - Title = "Total Play Time", - LineColour = colours.Yellow, - }, + User = { BindTarget = User } }, medalInfo = new OverlinedInfoContainer { @@ -149,31 +142,6 @@ namespace osu.Game.Overlays.Profile.Header medalInfo.Content = user?.Achievements?.Length.ToString() ?? "0"; ppInfo.Content = user?.Statistics?.PP?.ToString("#,##0") ?? "0"; - string formatTime(int? secondsNull) - { - if (secondsNull == null) return "0h 0m"; - - int seconds = secondsNull.Value; - string time = ""; - - int days = seconds / 86400; - seconds -= days * 86400; - if (days > 0) - time += days + "d "; - - int hours = seconds / 3600; - seconds -= hours * 3600; - time += hours + "h "; - - int minutes = seconds / 60; - time += minutes + "m"; - - return time; - } - - totalPlayTimeInfo.Content = formatTime(user?.Statistics?.PlayTime); - totalPlayTimeTooltip.TooltipText = (user?.Statistics?.PlayTime ?? 0) / 3600 + " hours"; - foreach (var scoreRankInfo in scoreRankInfos) scoreRankInfo.Value.RankCount = user?.Statistics?.GradesCount[scoreRankInfo.Key] ?? 0; diff --git a/osu.Game/Overlays/Profile/Header/LevelBadge.cs b/osu.Game/Overlays/Profile/Header/LevelBadge.cs new file mode 100644 index 0000000000..8990956811 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/LevelBadge.cs @@ -0,0 +1,57 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Users; + +namespace osu.Game.Overlays.Profile.Header +{ + public class LevelBadge : CompositeDrawable, IHasTooltip + { + public readonly Bindable User = new Bindable(); + + public string TooltipText { get; } + + private OsuSpriteText levelText; + + public LevelBadge() + { + TooltipText = "Level"; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, TextureStore textures) + { + InternalChildren = new Drawable[] + { + new Sprite + { + RelativeSizeAxes = Axes.Both, + Texture = textures.Get("Profile/levelbadge"), + Colour = colours.Yellow, + }, + levelText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 20) + } + }; + + User.BindValueChanged(updateLevel); + } + + private void updateLevel(ValueChangedEvent user) + { + levelText.Text = user.NewValue?.Statistics?.Level.Current.ToString() ?? "0"; + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/LevelProgressBar.cs b/osu.Game/Overlays/Profile/Header/LevelProgressBar.cs new file mode 100644 index 0000000000..20d30bd993 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/LevelProgressBar.cs @@ -0,0 +1,65 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Users; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Profile.Header +{ + public class LevelProgressBar : CompositeDrawable, IHasTooltip + { + public readonly Bindable User = new Bindable(); + + public string TooltipText { get; } + + private Bar levelProgressBar; + private OsuSpriteText levelProgressText; + + public LevelProgressBar() + { + TooltipText = "Progress to next level"; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + InternalChildren = new Drawable[] + { + new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = levelProgressBar = new Bar + { + RelativeSizeAxes = Axes.Both, + BackgroundColour = Color4.Black, + Direction = BarDirection.LeftToRight, + AccentColour = colours.Yellow + } + }, + levelProgressText = new OsuSpriteText + { + Anchor = Anchor.BottomRight, + Origin = Anchor.TopRight, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold) + } + }; + + User.BindValueChanged(updateProgress); + } + + private void updateProgress(ValueChangedEvent user) + { + levelProgressBar.Length = user.NewValue?.Statistics?.Level.Progress / 100f ?? 0; + levelProgressText.Text = user.NewValue?.Statistics?.Level.Progress.ToString("0'%'"); + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/OverlinedTotalPlayTime.cs b/osu.Game/Overlays/Profile/Header/OverlinedTotalPlayTime.cs new file mode 100644 index 0000000000..80c25ef4e5 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/OverlinedTotalPlayTime.cs @@ -0,0 +1,69 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Game.Graphics; +using osu.Game.Users; + +namespace osu.Game.Overlays.Profile.Header +{ + public class OverlinedTotalPlayTime : CompositeDrawable, IHasTooltip + { + public readonly Bindable User = new Bindable(); + + public string TooltipText { get; set; } + + private OverlinedInfoContainer info; + + public OverlinedTotalPlayTime() + { + AutoSizeAxes = Axes.Both; + + TooltipText = "0 hours"; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + InternalChild = info = new OverlinedInfoContainer + { + Title = "Total Play Time", + LineColour = colours.Yellow, + }; + + User.BindValueChanged(updateTime, true); + } + + private void updateTime(ValueChangedEvent user) + { + TooltipText = (user.NewValue?.Statistics?.PlayTime ?? 0) / 3600 + " hours"; + info.Content = formatTime(user.NewValue?.Statistics?.PlayTime); + } + + private string formatTime(int? secondsNull) + { + if (secondsNull == null) return "0h 0m"; + + int seconds = secondsNull.Value; + string time = ""; + + int days = seconds / 86400; + seconds -= days * 86400; + if (days > 0) + time += days + "d "; + + int hours = seconds / 3600; + seconds -= hours * 3600; + time += hours + "h "; + + int minutes = seconds / 60; + time += minutes + "m"; + + return time; + } + } +} diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index d9557952df..7969c645ec 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Game.Graphics; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; @@ -135,11 +134,6 @@ namespace osu.Game.Overlays.Profile coverContainer.User = user; } - public class HasTooltipContainer : Container, IHasTooltip - { - public string TooltipText { get; set; } - } - private class ProfileHeaderTitle : ScreenTitle { public ProfileHeaderTitle() From d5b91c6455b1fe9cae8ef37f98a2c4fffa6b3070 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 26 Apr 2019 12:32:15 +0900 Subject: [PATCH 0656/5608] Cleanup top header container + user handling --- .../Profile/Header/CentreHeaderContainer.cs | 6 ++-- .../Overlays/Profile/Header/LevelBadge.cs | 6 ++-- .../Profile/Header/LevelProgressBar.cs | 8 ++--- .../Profile/Header/TopHeaderContainer.cs | 29 ++++++++++--------- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index e10d259ca9..7964d25db6 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -185,10 +185,10 @@ namespace osu.Game.Overlays.Profile.Header private void updateDisplay(User user) { - followerText.Text = user.FollowerCount?.Length > 0 ? user.FollowerCount[0].ToString("#,##0") : "0"; + followerText.Text = user?.FollowerCount?.Length > 0 ? user.FollowerCount[0].ToString("#,##0") : "0"; - hiddenDetailGlobal.Content = user.Statistics?.Ranks.Global?.ToString("#,##0") ?? "-"; - hiddenDetailCountry.Content = user.Statistics?.Ranks.Country?.ToString("#,##0") ?? "-"; + hiddenDetailGlobal.Content = user?.Statistics?.Ranks.Global?.ToString("#,##0") ?? "-"; + hiddenDetailCountry.Content = user?.Statistics?.Ranks.Country?.ToString("#,##0") ?? "-"; } private class ExpandButton : ProfileHeaderButton diff --git a/osu.Game/Overlays/Profile/Header/LevelBadge.cs b/osu.Game/Overlays/Profile/Header/LevelBadge.cs index 8990956811..cc05926be4 100644 --- a/osu.Game/Overlays/Profile/Header/LevelBadge.cs +++ b/osu.Game/Overlays/Profile/Header/LevelBadge.cs @@ -46,12 +46,12 @@ namespace osu.Game.Overlays.Profile.Header } }; - User.BindValueChanged(updateLevel); + User.BindValueChanged(user => updateLevel(user.NewValue)); } - private void updateLevel(ValueChangedEvent user) + private void updateLevel(User user) { - levelText.Text = user.NewValue?.Statistics?.Level.Current.ToString() ?? "0"; + levelText.Text = user?.Statistics?.Level.Current.ToString() ?? "0"; } } } diff --git a/osu.Game/Overlays/Profile/Header/LevelProgressBar.cs b/osu.Game/Overlays/Profile/Header/LevelProgressBar.cs index 20d30bd993..c043efb423 100644 --- a/osu.Game/Overlays/Profile/Header/LevelProgressBar.cs +++ b/osu.Game/Overlays/Profile/Header/LevelProgressBar.cs @@ -53,13 +53,13 @@ namespace osu.Game.Overlays.Profile.Header } }; - User.BindValueChanged(updateProgress); + User.BindValueChanged(user => updateProgress(user.NewValue)); } - private void updateProgress(ValueChangedEvent user) + private void updateProgress(User user) { - levelProgressBar.Length = user.NewValue?.Statistics?.Level.Progress / 100f ?? 0; - levelProgressText.Text = user.NewValue?.Statistics?.Level.Progress.ToString("0'%'"); + levelProgressBar.Length = user?.Statistics?.Level.Progress / 100f ?? 0; + levelProgressText.Text = user?.Statistics?.Level.Progress.ToString("0'%'"); } } } diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 80721af42f..50e19d430b 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -17,6 +17,10 @@ namespace osu.Game.Overlays.Profile.Header { public class TopHeaderContainer : CompositeDrawable { + private const float avatar_size = 110; + + public readonly Bindable User = new Bindable(); + private SupporterIcon supporterTag; private UpdateableAvatar avatar; private OsuSpriteText usernameText; @@ -26,15 +30,10 @@ namespace osu.Game.Overlays.Profile.Header private OsuSpriteText userCountryText; private FillFlowContainer userStats; - private const float avatar_size = 110; - - public readonly Bindable User = new Bindable(); - [BackgroundDependencyLoader] private void load(OsuColour colours) { Height = 150; - User.ValueChanged += e => updateDisplay(e.NewValue); InternalChildren = new Drawable[] { @@ -146,21 +145,23 @@ namespace osu.Game.Overlays.Profile.Header Spacing = new Vector2(0, 2) } }; + + User.BindValueChanged(user => updateUser(user.NewValue)); } - private void updateDisplay(User user) + private void updateUser(User user) { avatar.User = user; - usernameText.Text = user.Username; - openUserExternally.Link = $@"https://osu.ppy.sh/users/{user.Id}"; - userFlag.Country = user.Country; - userCountryText.Text = user.Country?.FullName ?? "Alien"; - supporterTag.SupporterLevel = user.SupportLevel; - titleText.Text = user.Title; - titleText.Colour = OsuColour.FromHex(user.Colour ?? "fff"); + usernameText.Text = user?.Username ?? string.Empty; + openUserExternally.Link = $@"https://osu.ppy.sh/users/{user?.Id ?? 0}"; + userFlag.Country = user?.Country; + userCountryText.Text = user?.Country?.FullName ?? "Alien"; + supporterTag.SupporterLevel = user?.SupportLevel ?? 0; + titleText.Text = user?.Title ?? string.Empty; + titleText.Colour = OsuColour.FromHex(user?.Colour ?? "fff"); userStats.Clear(); - if (user.Statistics != null) + if (user?.Statistics != null) { userStats.Add(new UserStatsLine("Ranked Score", user.Statistics.RankedScore.ToString("#,##0"))); userStats.Add(new UserStatsLine("Hit Accuracy", Math.Round(user.Statistics.Accuracy, 2).ToString("#0.00'%'"))); From 4adf590036e6b9a6674175e0a15870079601373b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 26 Apr 2019 12:41:00 +0900 Subject: [PATCH 0657/5608] Combine hover/active state handling in tab control --- .../Profile/Header/ProfileHeaderTabControl.cs | 54 ++++++++++--------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs index c6b66b48d0..3b16b102d5 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs +++ b/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs @@ -24,10 +24,10 @@ namespace osu.Game.Overlays.Profile.Header get => accentColour; set { - if (accentColour == value) return; + if (accentColour == value) + return; accentColour = value; - bar.Colour = value; foreach (TabItem tabItem in TabContainer) @@ -76,10 +76,13 @@ namespace osu.Game.Overlays.Profile.Header get => accentColour; set { - accentColour = value; + if (accentColour == value) + return; + accentColour = value; bar.Colour = value; - if (!Active.Value) text.Colour = value; + + updateState(); } } @@ -112,37 +115,40 @@ namespace osu.Game.Overlays.Profile.Header protected override bool OnHover(HoverEvent e) { - if (!Active.Value) - onActivated(true); - return base.OnHover(e); + base.OnHover(e); + + updateState(); + + return true; } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - if (!Active.Value) - OnDeactivated(); + updateState(); } - protected override void OnActivated() - { - onActivated(); - } + protected override void OnActivated() => updateState(); - protected override void OnDeactivated() - { - text.FadeColour(AccentColour, 120, Easing.InQuad); - bar.ResizeHeightTo(0, 120, Easing.InQuad); - text.Font = text.Font.With(weight: FontWeight.Medium); - } + protected override void OnDeactivated() => updateState(); - private void onActivated(bool fake = false) + private void updateState() { - text.FadeColour(Color4.White, 120, Easing.InQuad); - bar.ResizeHeightTo(7.5f, 120, Easing.InQuad); - if (!fake) - text.Font = text.Font.With(weight: FontWeight.Bold); + if (Active.Value || IsHovered) + { + text.FadeColour(Color4.White, 120, Easing.InQuad); + bar.ResizeHeightTo(7.5f, 120, Easing.InQuad); + + if (Active.Value) + text.Font = text.Font.With(weight: FontWeight.Bold); + } + else + { + text.FadeColour(AccentColour, 120, Easing.InQuad); + bar.ResizeHeightTo(0, 120, Easing.InQuad); + text.Font = text.Font.With(weight: FontWeight.Medium); + } } } } From 7047303b0fcf68378f6ea315570ab8a279d0061e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 26 Apr 2019 13:29:58 +0900 Subject: [PATCH 0658/5608] Add tooltips to all buttons --- .../Profile/Header/CentreHeaderContainer.cs | 63 ++----------------- .../Profile/Header/ExpandDetailsButton.cs | 45 +++++++++++++ .../Overlays/Profile/Header/FriendButton.cs | 58 +++++++++++++++++ .../Profile/Header/ProfileHeaderButton.cs | 7 ++- .../Profile/Header/ProfileMessageButton.cs | 2 + 5 files changed, 114 insertions(+), 61 deletions(-) create mode 100644 osu.Game/Overlays/Profile/Header/ExpandDetailsButton.cs create mode 100644 osu.Game/Overlays/Profile/Header/FriendButton.cs diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index 7964d25db6..1d947383a1 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -3,14 +3,11 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK; @@ -21,7 +18,6 @@ namespace osu.Game.Overlays.Profile.Header public readonly BindableBool DetailsVisible = new BindableBool(true); public readonly Bindable User = new Bindable(); - private OsuSpriteText followerText; private OverlinedInfoContainer hiddenDetailGlobal; private OverlinedInfoContainer hiddenDetailCountry; @@ -35,7 +31,6 @@ namespace osu.Game.Overlays.Profile.Header { Container hiddenDetailContainer; Container expandedDetailContainer; - SpriteIcon expandButtonIcon; InternalChildren = new Drawable[] { @@ -54,37 +49,10 @@ namespace osu.Game.Overlays.Profile.Header Spacing = new Vector2(10, 0), Children = new Drawable[] { - new ProfileHeaderButton + new FriendButton { RelativeSizeAxes = Axes.Y, - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Direction = FillDirection.Horizontal, - Padding = new MarginPadding { Right = 10 }, - Children = new Drawable[] - { - new SpriteIcon - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Icon = FontAwesome.Solid.User, - FillMode = FillMode.Fit, - Size = new Vector2(50, 14) - }, - followerText = new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(weight: FontWeight.Bold) - } - } - } - } + User = { BindTarget = User } }, new ProfileMessageButton { @@ -99,22 +67,12 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.Y, Padding = new MarginPadding { Vertical = 10 }, Width = UserProfileOverlay.CONTENT_X_MARGIN, - Child = new ExpandButton + Child = new ExpandDetailsButton { RelativeSizeAxes = Axes.Y, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Action = () => DetailsVisible.Toggle(), - Children = new Drawable[] - { - expandButtonIcon = new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(20, 12), - Icon = FontAwesome.Solid.ChevronUp, - }, - } + DetailsVisible = { BindTarget = DetailsVisible } }, }, new Container @@ -175,7 +133,6 @@ namespace osu.Game.Overlays.Profile.Header DetailsVisible.BindValueChanged(visible => { - expandButtonIcon.Icon = visible.NewValue ? FontAwesome.Solid.ChevronUp : FontAwesome.Solid.ChevronDown; hiddenDetailContainer.Alpha = visible.NewValue ? 1 : 0; expandedDetailContainer.Alpha = visible.NewValue ? 0 : 1; }, true); @@ -185,20 +142,8 @@ namespace osu.Game.Overlays.Profile.Header private void updateDisplay(User user) { - followerText.Text = user?.FollowerCount?.Length > 0 ? user.FollowerCount[0].ToString("#,##0") : "0"; - hiddenDetailGlobal.Content = user?.Statistics?.Ranks.Global?.ToString("#,##0") ?? "-"; hiddenDetailCountry.Content = user?.Statistics?.Ranks.Country?.ToString("#,##0") ?? "-"; } - - private class ExpandButton : ProfileHeaderButton - { - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - IdleColour = colours.CommunityUserGrayGreen; - HoverColour = colours.CommunityUserGrayGreen.Darken(0.2f); - } - } } } diff --git a/osu.Game/Overlays/Profile/Header/ExpandDetailsButton.cs b/osu.Game/Overlays/Profile/Header/ExpandDetailsButton.cs new file mode 100644 index 0000000000..dc507be0b1 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/ExpandDetailsButton.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 osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osuTK; + +namespace osu.Game.Overlays.Profile.Header +{ + public class ExpandDetailsButton : ProfileHeaderButton + { + public readonly BindableBool DetailsVisible = new BindableBool(); + + public override string TooltipText => DetailsVisible.Value ? "collapse" : "expand"; + + private SpriteIcon icon; + + public ExpandDetailsButton() + { + Action = () => DetailsVisible.Toggle(); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + IdleColour = colours.CommunityUserGrayGreen; + HoverColour = colours.CommunityUserGrayGreen.Darken(0.2f); + + Child = icon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(20, 12) + }; + + DetailsVisible.BindValueChanged(visible => updateState(visible.NewValue), true); + } + + private void updateState(bool detailsVisible) => icon.Icon = detailsVisible ? FontAwesome.Solid.ChevronUp : FontAwesome.Solid.ChevronDown; + } +} diff --git a/osu.Game/Overlays/Profile/Header/FriendButton.cs b/osu.Game/Overlays/Profile/Header/FriendButton.cs new file mode 100644 index 0000000000..3b2f192fb1 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/FriendButton.cs @@ -0,0 +1,58 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Overlays.Profile.Header +{ + public class FriendButton : ProfileHeaderButton + { + public readonly Bindable User = new Bindable(); + + public override string TooltipText => "friends"; + + private OsuSpriteText followerText; + + [BackgroundDependencyLoader] + private void load() + { + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Horizontal, + Padding = new MarginPadding { Right = 10 }, + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.Solid.User, + FillMode = FillMode.Fit, + Size = new Vector2(50, 14) + }, + followerText = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(weight: FontWeight.Bold) + } + } + }; + + User.BindValueChanged(user => updateFollowers(user.NewValue), true); + } + + private void updateFollowers(User user) => followerText.Text = user?.FollowerCount?.Length > 0 ? user.FollowerCount[0].ToString("#,##0") : "0"; + } +} diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs b/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs index 300767cf0d..ddf2338873 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs +++ b/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -11,8 +12,10 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header { - public class ProfileHeaderButton : OsuHoverContainer + public abstract class ProfileHeaderButton : OsuHoverContainer, IHasTooltip { + public abstract string TooltipText { get; } + private readonly Box background; private readonly Container content; @@ -20,7 +23,7 @@ namespace osu.Game.Overlays.Profile.Header protected override IEnumerable EffectTargets => new[] { background }; - public ProfileHeaderButton() + protected ProfileHeaderButton() { AutoSizeAxes = Axes.X; diff --git a/osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs b/osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs index 3121eae727..162d49cf1b 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs +++ b/osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs @@ -16,6 +16,8 @@ namespace osu.Game.Overlays.Profile.Header { public readonly Bindable User = new Bindable(); + public override string TooltipText => "send message"; + [Resolved(CanBeNull = true)] private ChannelManager channelManager { get; set; } From 2f4bf423a4d4ef4d56a91046ef4d0e70074188ee Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 26 Apr 2019 13:49:44 +0900 Subject: [PATCH 0659/5608] Renamespace --- osu.Game.Tests/Visual/Online/TestCaseRankGraph.cs | 2 +- osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs | 2 +- .../Visual/Online/TestCaseUserProfileHeader.cs | 1 + .../Overlays/Profile/Header/CentreHeaderContainer.cs | 5 +++-- .../{FriendButton.cs => Components/AddFriendButton.cs} | 4 ++-- .../Profile/Header/{ => Components}/DrawableBadge.cs | 2 +- .../Header/{ => Components}/ExpandDetailsButton.cs | 2 +- .../Profile/Header/{ => Components}/LevelBadge.cs | 2 +- .../Header/{ => Components}/LevelProgressBar.cs | 2 +- .../MessageUserButton.cs} | 6 +++--- .../Header/{ => Components}/OverlinedInfoContainer.cs | 2 +- .../Header/{ => Components}/OverlinedTotalPlayTime.cs | 2 +- .../Header/{ => Components}/ProfileHeaderButton.cs | 2 +- .../Profile/Header/{ => Components}/RankGraph.cs | 2 +- .../Profile/Header/{ => Components}/SupporterIcon.cs | 2 +- .../Overlays/Profile/Header/DetailHeaderContainer.cs | 1 + .../Overlays/Profile/Header/MedalHeaderContainer.cs | 1 + osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs | 1 + osu.Game/Overlays/Profile/ProfileHeader.cs | 10 +++++----- osu.Game/Overlays/Profile/ProfileSection.cs | 2 +- osu.Game/Users/UserPanel.cs | 2 +- 21 files changed, 30 insertions(+), 25 deletions(-) rename osu.Game/Overlays/Profile/Header/{FriendButton.cs => Components/AddFriendButton.cs} (94%) rename osu.Game/Overlays/Profile/Header/{ => Components}/DrawableBadge.cs (95%) rename osu.Game/Overlays/Profile/Header/{ => Components}/ExpandDetailsButton.cs (96%) rename osu.Game/Overlays/Profile/Header/{ => Components}/LevelBadge.cs (96%) rename osu.Game/Overlays/Profile/Header/{ => Components}/LevelProgressBar.cs (97%) rename osu.Game/Overlays/Profile/Header/{ProfileMessageButton.cs => Components/MessageUserButton.cs} (91%) rename osu.Game/Overlays/Profile/Header/{ => Components}/OverlinedInfoContainer.cs (97%) rename osu.Game/Overlays/Profile/Header/{ => Components}/OverlinedTotalPlayTime.cs (97%) rename osu.Game/Overlays/Profile/Header/{ => Components}/ProfileHeaderButton.cs (96%) rename osu.Game/Overlays/Profile/Header/{ => Components}/RankGraph.cs (99%) rename osu.Game/Overlays/Profile/Header/{ => Components}/SupporterIcon.cs (97%) diff --git a/osu.Game.Tests/Visual/Online/TestCaseRankGraph.cs b/osu.Game.Tests/Visual/Online/TestCaseRankGraph.cs index dff018bf91..a92b788e83 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseRankGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseRankGraph.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; -using osu.Game.Overlays.Profile.Header; +using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Users; using osuTK; diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs index c455c092ed..0789c14b32 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Overlays.Profile; -using osu.Game.Overlays.Profile.Header; +using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual.Online diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs index 0f1e954224..5f5ba89186 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs @@ -9,6 +9,7 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Profile; using osu.Game.Overlays.Profile.Header; +using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual.Online diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index 1d947383a1..c1ad2011f8 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; +using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Users; using osuTK; @@ -49,12 +50,12 @@ namespace osu.Game.Overlays.Profile.Header Spacing = new Vector2(10, 0), Children = new Drawable[] { - new FriendButton + new AddFriendButton { RelativeSizeAxes = Axes.Y, User = { BindTarget = User } }, - new ProfileMessageButton + new MessageUserButton { User = { BindTarget = User } }, diff --git a/osu.Game/Overlays/Profile/Header/FriendButton.cs b/osu.Game/Overlays/Profile/Header/Components/AddFriendButton.cs similarity index 94% rename from osu.Game/Overlays/Profile/Header/FriendButton.cs rename to osu.Game/Overlays/Profile/Header/Components/AddFriendButton.cs index 3b2f192fb1..2e4fd6fe3d 100644 --- a/osu.Game/Overlays/Profile/Header/FriendButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/AddFriendButton.cs @@ -11,9 +11,9 @@ using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays.Profile.Header.Components { - public class FriendButton : ProfileHeaderButton + public class AddFriendButton : ProfileHeaderButton { public readonly Bindable User = new Bindable(); diff --git a/osu.Game/Overlays/Profile/Header/DrawableBadge.cs b/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs similarity index 95% rename from osu.Game/Overlays/Profile/Header/DrawableBadge.cs rename to osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs index 75a8f4e415..ea259fe49a 100644 --- a/osu.Game/Overlays/Profile/Header/DrawableBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs @@ -10,7 +10,7 @@ using osu.Framework.Graphics.Textures; using osu.Game.Users; using osuTK; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays.Profile.Header.Components { public class DrawableBadge : CompositeDrawable, IHasTooltip { diff --git a/osu.Game/Overlays/Profile/Header/ExpandDetailsButton.cs b/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs similarity index 96% rename from osu.Game/Overlays/Profile/Header/ExpandDetailsButton.cs rename to osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs index dc507be0b1..089228b2cd 100644 --- a/osu.Game/Overlays/Profile/Header/ExpandDetailsButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osuTK; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays.Profile.Header.Components { public class ExpandDetailsButton : ProfileHeaderButton { diff --git a/osu.Game/Overlays/Profile/Header/LevelBadge.cs b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs similarity index 96% rename from osu.Game/Overlays/Profile/Header/LevelBadge.cs rename to osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs index cc05926be4..8069937810 100644 --- a/osu.Game/Overlays/Profile/Header/LevelBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Users; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays.Profile.Header.Components { public class LevelBadge : CompositeDrawable, IHasTooltip { diff --git a/osu.Game/Overlays/Profile/Header/LevelProgressBar.cs b/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs similarity index 97% rename from osu.Game/Overlays/Profile/Header/LevelProgressBar.cs rename to osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs index c043efb423..6a6532764f 100644 --- a/osu.Game/Overlays/Profile/Header/LevelProgressBar.cs +++ b/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Users; using osuTK.Graphics; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays.Profile.Header.Components { public class LevelProgressBar : CompositeDrawable, IHasTooltip { diff --git a/osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs b/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs similarity index 91% rename from osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs rename to osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs index 162d49cf1b..cc6edcdd6a 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileMessageButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs @@ -10,9 +10,9 @@ using osu.Game.Online.Chat; using osu.Game.Users; using osuTK; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays.Profile.Header.Components { - public class ProfileMessageButton : ProfileHeaderButton + public class MessageUserButton : ProfileHeaderButton { public readonly Bindable User = new Bindable(); @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Profile.Header [Resolved] private IAPIProvider apiProvider { get; set; } - public ProfileMessageButton() + public MessageUserButton() { Content.Alpha = 0; RelativeSizeAxes = Axes.Y; diff --git a/osu.Game/Overlays/Profile/Header/OverlinedInfoContainer.cs b/osu.Game/Overlays/Profile/Header/Components/OverlinedInfoContainer.cs similarity index 97% rename from osu.Game/Overlays/Profile/Header/OverlinedInfoContainer.cs rename to osu.Game/Overlays/Profile/Header/Components/OverlinedInfoContainer.cs index 2eb84c9d71..c40ddca688 100644 --- a/osu.Game/Overlays/Profile/Header/OverlinedInfoContainer.cs +++ b/osu.Game/Overlays/Profile/Header/Components/OverlinedInfoContainer.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK.Graphics; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays.Profile.Header.Components { public class OverlinedInfoContainer : CompositeDrawable { diff --git a/osu.Game/Overlays/Profile/Header/OverlinedTotalPlayTime.cs b/osu.Game/Overlays/Profile/Header/Components/OverlinedTotalPlayTime.cs similarity index 97% rename from osu.Game/Overlays/Profile/Header/OverlinedTotalPlayTime.cs rename to osu.Game/Overlays/Profile/Header/Components/OverlinedTotalPlayTime.cs index 80c25ef4e5..2c88a83680 100644 --- a/osu.Game/Overlays/Profile/Header/OverlinedTotalPlayTime.cs +++ b/osu.Game/Overlays/Profile/Header/Components/OverlinedTotalPlayTime.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.Cursor; using osu.Game.Graphics; using osu.Game.Users; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays.Profile.Header.Components { public class OverlinedTotalPlayTime : CompositeDrawable, IHasTooltip { diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs similarity index 96% rename from osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs rename to osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs index ddf2338873..1650f11523 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osuTK.Graphics; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays.Profile.Header.Components { public abstract class ProfileHeaderButton : OsuHoverContainer, IHasTooltip { diff --git a/osu.Game/Overlays/Profile/Header/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs similarity index 99% rename from osu.Game/Overlays/Profile/Header/RankGraph.cs rename to osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index d66f2306a0..bb54d0ac51 100644 --- a/osu.Game/Overlays/Profile/Header/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -17,7 +17,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Users; using osuTK; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays.Profile.Header.Components { public class RankGraph : Container, IHasCustomTooltip { diff --git a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs similarity index 97% rename from osu.Game/Overlays/Profile/Header/SupporterIcon.cs rename to osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index 569ed252b7..99b45aca93 100644 --- a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays.Profile.Header.Components { public class SupporterIcon : CompositeDrawable, IHasTooltip { diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index 62e57fef79..89a9d7ddd1 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Scoring; using osu.Game.Users; using osuTK; diff --git a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs index 69b1203b9f..1e214b2d0c 100644 --- a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Users; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 50e19d430b..ce02e61d82 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Users; using osuTK; diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 7969c645ec..f5233cf70c 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -2,16 +2,16 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Overlays.Profile.Header; -using osu.Game.Users; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Profile.Header; +using osu.Game.Users; namespace osu.Game.Overlays.Profile { diff --git a/osu.Game/Overlays/Profile/ProfileSection.cs b/osu.Game/Overlays/Profile/ProfileSection.cs index 6da736432f..4d891384e8 100644 --- a/osu.Game/Overlays/Profile/ProfileSection.cs +++ b/osu.Game/Overlays/Profile/ProfileSection.cs @@ -2,13 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; -using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Users; +using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.Profile diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index eb7f0941fb..1a10e035cd 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -18,7 +18,7 @@ using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Containers; -using osu.Game.Overlays.Profile.Header; +using osu.Game.Overlays.Profile.Header.Components; namespace osu.Game.Users { From 50a775145cb3eb8de776799c35ae35f1c03715d6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 26 Apr 2019 13:56:26 +0900 Subject: [PATCH 0660/5608] Separate variables --- osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index 89a9d7ddd1..9bb0affe7d 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -21,9 +21,11 @@ namespace osu.Game.Overlays.Profile.Header { public class DetailHeaderContainer : CompositeDrawable { - private OverlinedInfoContainer medalInfo, ppInfo; private readonly Dictionary scoreRankInfos = new Dictionary(); - private OverlinedInfoContainer detailGlobalRank, detailCountryRank; + private OverlinedInfoContainer medalInfo; + private OverlinedInfoContainer ppInfo; + private OverlinedInfoContainer detailGlobalRank; + private OverlinedInfoContainer detailCountryRank; private RankGraph rankGraph; public readonly Bindable User = new Bindable(); From 32e71a6314c485107d24a9de9e2e4598d246fe88 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 26 Apr 2019 16:15:42 +0900 Subject: [PATCH 0661/5608] Fix incorrect seeking behaviour of TrackVirtualManual --- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index 78f9103a74..c558275f62 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets; +using osuTK; namespace osu.Game.Tests.Beatmaps { @@ -67,9 +68,10 @@ namespace osu.Game.Tests.Beatmaps public override bool Seek(double seek) { - offset = Math.Min(seek, Length); + offset = MathHelper.Clamp(seek, 0, Length); lastReferenceTime = null; - return true; + + return offset == seek; } public override void Start() From 41d0b00120c9da14bbbac7fb514e64e779cb6ab0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 27 Apr 2019 16:43:23 +0900 Subject: [PATCH 0662/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 74ed9f91dd..3b47005049 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 9fff64c61c..20810886f3 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 27c1c368ac715470e22b8dccfc5b42eed2745464 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 27 Apr 2019 20:31:00 +0900 Subject: [PATCH 0663/5608] Remove unused using --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index fd65d8f9cc..d72c334ed3 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.UI; From 27ba89444ee7af1a82988fea3b3ecae91e7f1d8e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 28 Apr 2019 01:08:14 +0900 Subject: [PATCH 0664/5608] Remove unnecessary using statements --- osu.Game/Overlays/Profile/ProfileHeader.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 8c220b2cb4..f5233cf70c 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -12,8 +12,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; -using Humanizer; -using osu.Framework.Graphics.Effects; namespace osu.Game.Overlays.Profile { From 8ab514933673967a02ee873cb34d40755ceac527 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 28 Apr 2019 20:11:36 +0900 Subject: [PATCH 0665/5608] SupporterLevel -> SupportLevel --- osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs | 2 +- osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs | 2 +- osu.Game/Users/UserPanel.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index 99b45aca93..d4ccef8b69 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Profile.Header.Components public string TooltipText => "osu!supporter"; - public int SupporterLevel + public int SupportLevel { set { diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index ce02e61d82..c1fe430bdd 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -157,7 +157,7 @@ namespace osu.Game.Overlays.Profile.Header openUserExternally.Link = $@"https://osu.ppy.sh/users/{user?.Id ?? 0}"; userFlag.Country = user?.Country; userCountryText.Text = user?.Country?.FullName ?? "Alien"; - supporterTag.SupporterLevel = user?.SupportLevel ?? 0; + supporterTag.SupportLevel = user?.SupportLevel ?? 0; titleText.Text = user?.Title ?? string.Empty; titleText.Colour = OsuColour.FromHex(user?.Colour ?? "fff"); diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 75069273a5..47571b673d 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -191,7 +191,7 @@ namespace osu.Game.Users infoContainer.Add(new SupporterIcon { Height = 20f, - SupporterLevel = user.SupportLevel + SupportLevel = user.SupportLevel }); } From f9f6e1f04ae8cfbc3d1851a7746814baf5b189e5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 28 Apr 2019 20:13:28 +0900 Subject: [PATCH 0666/5608] Clamp values to avoid potentially weird element --- .../Overlays/Profile/Header/Components/SupporterIcon.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index d4ccef8b69..cb12a62702 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { @@ -23,7 +24,9 @@ namespace osu.Game.Overlays.Profile.Header.Components { set { - if (value == 0) + int count = MathHelper.Clamp(value, 0, 3); + + if (count == 0) { content.Hide(); } @@ -31,7 +34,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { content.Show(); iconContainer.Clear(); - for (int i = 0; i < value; i++) + for (int i = 0; i < count; i++) { iconContainer.Add(new SpriteIcon { From 5d50316ae7565979ecb40604c74c7da0649b632c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 30 Apr 2019 18:12:27 +0300 Subject: [PATCH 0667/5608] Add xmldoc --- osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs b/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs index 34e8d858f6..1b62dbdacf 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs @@ -13,6 +13,9 @@ namespace osu.Game.Rulesets.Mods { void ApplyToScoreProcessor(ScoreProcessor scoreProcessor); + /// + /// Adjusts a rank value passed by and returns it. + /// ScoreRank AdjustRank(ScoreRank rank, double accuracy); } } From 665558c297984e2a05590337440ee81bea864784 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 30 Apr 2019 18:44:06 +0300 Subject: [PATCH 0668/5608] Remove unnecessary comment --- osu.Game/Rulesets/Mods/ModHidden.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index c55c45c9fa..cda919c894 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -36,11 +36,10 @@ namespace osu.Game.Rulesets.Mods public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { - // Default value of ScoreProcessor's Rank in Hidden Mod should bes SS+ + // Default value of public interface IApplicableToScoreProcessor : IApplicableMod { + /// + /// Provide a to a mod. Called once on initialisation of a play instance. + /// void ApplyToScoreProcessor(ScoreProcessor scoreProcessor); /// - /// Adjusts a rank value passed by and returns it. + /// Called every time a rank calculation is requested. Allows mods to adjust the final rank. /// ScoreRank AdjustRank(ScoreRank rank, double accuracy); } From c6992bd6f9d89e2670592d4e9264bd3dfc645ee7 Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 2 May 2019 03:37:15 -0700 Subject: [PATCH 0681/5608] Switch hidden/expanded centre profile header information --- osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index c1ad2011f8..c2f1d5f2ad 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -134,8 +134,8 @@ namespace osu.Game.Overlays.Profile.Header DetailsVisible.BindValueChanged(visible => { - hiddenDetailContainer.Alpha = visible.NewValue ? 1 : 0; - expandedDetailContainer.Alpha = visible.NewValue ? 0 : 1; + hiddenDetailContainer.Alpha = visible.NewValue ? 0 : 1; + expandedDetailContainer.Alpha = visible.NewValue ? 1 : 0; }, true); User.BindValueChanged(user => updateDisplay(user.NewValue)); From ac31a9640a6f3f8df8f14edd2229f2d936b43dd0 Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 2 May 2019 03:47:20 -0700 Subject: [PATCH 0682/5608] Add number sign to centre info rankings --- osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index c2f1d5f2ad..0642ef94df 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -143,8 +143,8 @@ namespace osu.Game.Overlays.Profile.Header private void updateDisplay(User user) { - hiddenDetailGlobal.Content = user?.Statistics?.Ranks.Global?.ToString("#,##0") ?? "-"; - hiddenDetailCountry.Content = user?.Statistics?.Ranks.Country?.ToString("#,##0") ?? "-"; + hiddenDetailGlobal.Content = user?.Statistics?.Ranks.Global?.ToString("\\##,##0") ?? "-"; + hiddenDetailCountry.Content = user?.Statistics?.Ranks.Country?.ToString("\\##,##0") ?? "-"; } } } From 84b41b3886297d939c71fcba5bc21faeb1c0cbdc Mon Sep 17 00:00:00 2001 From: Lucas A Date: Thu, 2 May 2019 19:44:07 +0200 Subject: [PATCH 0683/5608] Split out setUserStatus() logic to multiple lines. + Make UserStatusDoNotDisturb inherit from UserStatus --- osu.Game.Tests/Visual/Gameplay/TestCasePause.cs | 3 +++ osu.Game/Screens/OsuScreen.cs | 13 +++++++++---- osu.Game/Users/UserStatus.cs | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs index a52e84ed62..eb84fe6316 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; +using osu.Game.Users; using osuTK; using osuTK.Input; @@ -192,6 +193,8 @@ namespace osu.Game.Tests.Visual.Gameplay public new HUDOverlay HUDOverlay => base.HUDOverlay; + protected override UserStatus ScreenStatus => null; + public bool FailOverlayVisible => FailOverlay.State == Visibility.Visible; public bool PauseOverlayVisible => PauseOverlay.State == Visibility.Visible; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 11161dd688..f00d18271d 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -143,8 +143,9 @@ namespace osu.Game.Screens private void userStatusChanged(ValueChangedEvent obj) { - if (obj.NewValue?.GetType() != ScreenStatus?.GetType()) //restore the status back to this screen's status when the user status is changed back to online after having being set to DND / offline - setUserStatus(ScreenStatus); + if (obj.NewValue?.GetType() == ScreenStatus?.GetType()) return; //don't update the user's status if the current status is of the same type as the given one + + setUserStatus(ScreenStatus); } public override void OnSuspending(IScreen next) @@ -190,8 +191,12 @@ namespace osu.Game.Screens private void setUserStatus(UserStatus status) { - if (api != null && status != null && !(api.LocalUser.Value.Status.Value is UserStatusDoNotDisturb) && !(api.LocalUser.Value.Status.Value is UserStatusOffline)) //only sets the user's status to the given one if - api.LocalUser.Value.Status.Value = status; //status is not null and the current status isn't either UserStatusDoNotDisturb or UserStatusOffline + if (api == null) return; + if (status == null) return; + + if (!(api.LocalUser.Value.Status.Value is UserStatusOnline)) return; //don't update the user's status if the current status doesn't allow to be modified by screens (eg: DND / Offline) + + api.LocalUser.Value.Status.Value = status; } /// diff --git a/osu.Game/Users/UserStatus.cs b/osu.Game/Users/UserStatus.cs index 39f295f445..0ee12ed63f 100644 --- a/osu.Game/Users/UserStatus.cs +++ b/osu.Game/Users/UserStatus.cs @@ -85,7 +85,7 @@ namespace osu.Game.Users public override Color4 GetAppropriateColour(OsuColour colours) => colours.PurpleDark; } - public class UserStatusDoNotDisturb : UserStatusBusy + public class UserStatusDoNotDisturb : UserStatus { public override string Message => @"Do not disturb"; public override Color4 GetAppropriateColour(OsuColour colours) => colours.RedDark; From 5d4aa5a12e669e77edb03ef14be284cf23741fc2 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Thu, 2 May 2019 20:51:19 +0200 Subject: [PATCH 0684/5608] Add ScreenStatus property to change the OsuScreen's status + Renamed old ScreenStatus property to InitialScreenStatus --- .../TestCaseBackgroundScreenBeatmap.cs | 8 +++-- .../Visual/Gameplay/TestCasePause.cs | 2 +- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/OsuScreen.cs | 33 +++++++++++++++---- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- osu.Game/Screens/Select/PlaySongSelect.cs | 2 +- 7 files changed, 36 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs index d4e563220b..58404d307f 100644 --- a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs @@ -275,6 +275,8 @@ namespace osu.Game.Tests.Visual.Background private class DummySongSelect : PlaySongSelect { + protected override UserStatusOnline InitialScreenStatus => null; + protected override BackgroundScreen CreateBackground() { FadeAccessibleBackground background = new FadeAccessibleBackground(Beatmap.Value); @@ -318,7 +320,7 @@ namespace osu.Game.Tests.Visual.Background private class FadeAccessibleResults : SoloResults { - protected override UserStatus ScreenStatus => null; + protected override UserStatusOnline InitialScreenStatus => null; public FadeAccessibleResults(ScoreInfo score) : base(score) @@ -332,7 +334,7 @@ namespace osu.Game.Tests.Visual.Background private class TestPlayer : Player { - protected override UserStatus ScreenStatus => null; + protected override UserStatusOnline InitialScreenStatus => null; protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); @@ -381,7 +383,7 @@ namespace osu.Game.Tests.Visual.Background public VisualSettings VisualSettingsPos => VisualSettings; public BackgroundScreen ScreenPos => Background; - protected override UserStatus ScreenStatus => null; + protected override UserStatusOnline InitialScreenStatus => null; public TestPlayerLoader(Player player) : base(() => player) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs index eb84fe6316..ae7faf318f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs @@ -193,7 +193,7 @@ namespace osu.Game.Tests.Visual.Gameplay public new HUDOverlay HUDOverlay => base.HUDOverlay; - protected override UserStatus ScreenStatus => null; + protected override UserStatusOnline InitialScreenStatus => null; public bool FailOverlayVisible => FailOverlay.State == Visibility.Visible; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 6cbbc90ada..a04124082c 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -48,7 +48,7 @@ namespace osu.Game.Screens.Edit private DependencyContainer dependencies; private GameHost host; - protected override UserStatus ScreenStatus => new UserStatusEditing(Beatmap.Value.BeatmapInfo); + protected override UserStatusOnline InitialScreenStatus => new UserStatusEditing(Beatmap.Value.BeatmapInfo); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index f00d18271d..17b8ca60dc 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -55,12 +55,29 @@ namespace osu.Game.Screens protected new OsuGameBase Game => base.Game as OsuGameBase; /// - /// The to set the user's status automatically to when this screen is entered / resumed. - /// Note that the user status won't be automatically set if : - /// - is overriden and returns null - /// - The current is or + /// The to set the user's status automatically to when this screen is entered /// - protected virtual UserStatus ScreenStatus => new UserStatusOnline(); + protected virtual UserStatusOnline InitialScreenStatus => new UserStatusOnline(); + + /// + /// The for this screen. + /// Note that the status won't be updated for the user if : + /// - The is set to null + /// - The current of the user is or + /// + protected UserStatusOnline ScreenStatus + { + set + { + if (value == null) return; + + status = value; + setUserStatus(value); + } + get => status; + } + + private UserStatusOnline status; /// /// Whether to disallow changes to game-wise Beatmap/Ruleset bindables for this screen (and all children). @@ -104,6 +121,8 @@ namespace osu.Game.Screens { Anchor = Anchor.Centre; Origin = Anchor.Centre; + + status = null; } [BackgroundDependencyLoader(true)] @@ -136,7 +155,7 @@ namespace osu.Game.Screens if (api != null) api.LocalUser.Value.Status.ValueChanged += userStatusChanged; - setUserStatus(ScreenStatus); + ScreenStatus = ScreenStatus; base.OnResuming(last); } @@ -167,7 +186,7 @@ namespace osu.Game.Screens if (api != null) api.LocalUser.Value.Status.ValueChanged += userStatusChanged; - setUserStatus(ScreenStatus); + ScreenStatus = InitialScreenStatus; base.OnEntering(last); } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 3a3bac8070..883e96b316 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Play { protected override bool AllowBackButton => false; // handled by HoldForMenuButton - protected override UserStatus ScreenStatus => new UserStatusSoloGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); + protected override UserStatusOnline InitialScreenStatus => new UserStatusSoloGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); public override float BackgroundParallaxAmount => 0.1f; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 1099fbdcfd..8c4bf079ea 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Play private bool hideOverlays; public override bool HideOverlaysOnEnter => hideOverlays; - protected override UserStatus ScreenStatus => null; //shows the previous screen status + protected override UserStatusOnline InitialScreenStatus => null; //shows the previous screen status public override bool DisallowExternalBeatmapRulesetChanges => true; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 8c6872846e..58b8ef3d28 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Select public override bool AllowExternalScreenChange => true; - protected override UserStatus ScreenStatus => new UserStatusChoosingBeatmap(); + protected override UserStatusOnline InitialScreenStatus => new UserStatusChoosingBeatmap(); [BackgroundDependencyLoader] private void load(OsuColour colours) From 6bdaca1e3bf0a3ce4411a5d53f9ae64e80c8aec1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 3 May 2019 10:05:45 +0900 Subject: [PATCH 0685/5608] Fix mod equality checks not working as intended --- osu.Game/Online/API/Requests/Responses/APIMod.cs | 2 ++ osu.Game/Rulesets/Mods/IMod.cs | 3 ++- osu.Game/Rulesets/Mods/Mod.cs | 2 ++ osu.Game/Scoring/ScoreInfo.cs | 2 ++ osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs | 2 +- 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIMod.cs b/osu.Game/Online/API/Requests/Responses/APIMod.cs index d7dda07b33..b9da4f49ee 100644 --- a/osu.Game/Online/API/Requests/Responses/APIMod.cs +++ b/osu.Game/Online/API/Requests/Responses/APIMod.cs @@ -8,5 +8,7 @@ namespace osu.Game.Online.API.Requests.Responses public class APIMod : IMod { public string Acronym { get; set; } + + public bool Equals(IMod other) => Acronym == other?.Acronym; } } diff --git a/osu.Game/Rulesets/Mods/IMod.cs b/osu.Game/Rulesets/Mods/IMod.cs index 448ad0eb30..a5e19f293c 100644 --- a/osu.Game/Rulesets/Mods/IMod.cs +++ b/osu.Game/Rulesets/Mods/IMod.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using Newtonsoft.Json; namespace osu.Game.Rulesets.Mods { - public interface IMod + public interface IMod : IEquatable { /// /// The shortened name of this mod. diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index d2d0a5bb26..023d37497a 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -70,5 +70,7 @@ namespace osu.Game.Rulesets.Mods /// Creates a copy of this initialised to a default state. /// public virtual Mod CreateCopy() => (Mod)Activator.CreateInstance(GetType()); + + public bool Equals(IMod other) => GetType() == other?.GetType(); } } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index d36f963016..8bdc30ac94 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -177,6 +177,8 @@ namespace osu.Game.Scoring protected class DeserializedMod : IMod { public string Acronym { get; set; } + + public bool Equals(IMod other) => Acronym == other?.Acronym; } public override string ToString() => $"{User} playing {Beatmap}"; diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index 9692dc513d..88c6fc5e2e 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Multi.Play if (ruleset.Value.ID != playlistItem.Ruleset.ID) throw new InvalidOperationException("Current Ruleset does not match PlaylistItem's Ruleset"); - if (!playlistItem.RequiredMods.All(m => Mods.Value.Contains(m))) + if (!playlistItem.RequiredMods.All(m => Mods.Value.Any(m.Equals))) throw new InvalidOperationException("Current Mods do not match PlaylistItem's RequiredMods"); var req = new CreateRoomScoreRequest(roomId.Value ?? 0, playlistItem.ID); From 009eaa647a6acb5bf2d6b34bc02ce8223df891e3 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Fri, 3 May 2019 16:38:15 +0800 Subject: [PATCH 0686/5608] fixes to FooterButtonRandom --- osu.Game/Screens/Select/FooterButtonRandom.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButtonRandom.cs b/osu.Game/Screens/Select/FooterButtonRandom.cs index 7466e1f243..61e95de7fa 100644 --- a/osu.Game/Screens/Select/FooterButtonRandom.cs +++ b/osu.Game/Screens/Select/FooterButtonRandom.cs @@ -16,7 +16,7 @@ namespace osu.Game.Screens.Select public FooterButtonRandom() { - textContainer.Add(secondaryText = new OsuSpriteText + TextContainer.Add(secondaryText = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -43,12 +43,12 @@ namespace osu.Game.Screens.Select { if (secondaryActive) { - spriteText.FadeOut(120, Easing.InQuad); + SpriteText.FadeOut(120, Easing.InQuad); secondaryText.FadeIn(120, Easing.InQuad); } else { - spriteText.FadeIn(120, Easing.InQuad); + SpriteText.FadeIn(120, Easing.InQuad); secondaryText.FadeOut(120, Easing.InQuad); } } From 31341bfeb181a5f2c3a71db7ae7010ed6115f839 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Fri, 3 May 2019 16:51:33 +0800 Subject: [PATCH 0687/5608] use SongSelect's SelectedMods property to ensure it exists --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 7fb49e6dc6..db77323b3d 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -224,7 +224,7 @@ namespace osu.Game.Screens.Select if (Footer != null) { - Footer.AddButton(new FooterButtonMods(selectedMods), @"mods", colours.Yellow, ModSelect, Key.F1); + Footer.AddButton(new FooterButtonMods(SelectedMods), @"mods", colours.Yellow, ModSelect, Key.F1); Footer.AddButton(new FooterButtonRandom(), @"random", colours.Green, triggerRandom, Key.F2); Footer.AddButton(new FooterButton(), @"options", colours.Blue, BeatmapOptions, Key.F3); From 0fa02718786a0eefa063cce18e9e5351f509ab59 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 4 May 2019 11:01:12 +0900 Subject: [PATCH 0688/5608] Add animation when collapsing or expanding the profile details section --- .../Profile/Header/CentreHeaderContainer.cs | 6 ++-- .../Profile/Header/DetailHeaderContainer.cs | 33 +++++++++++++++++-- osu.Game/Overlays/Profile/ProfileHeader.cs | 2 +- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index 0642ef94df..b441775393 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -134,9 +134,9 @@ namespace osu.Game.Overlays.Profile.Header DetailsVisible.BindValueChanged(visible => { - hiddenDetailContainer.Alpha = visible.NewValue ? 0 : 1; - expandedDetailContainer.Alpha = visible.NewValue ? 1 : 0; - }, true); + hiddenDetailContainer.FadeTo(visible.NewValue ? 0 : 1, 200, Easing.OutQuint); + expandedDetailContainer.FadeTo(visible.NewValue ? 1 : 0, 200, Easing.OutQuint); + }); User.BindValueChanged(user => updateDisplay(user.NewValue)); } diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index 8fcf2711dd..de710c5fcd 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -26,14 +26,40 @@ namespace osu.Game.Overlays.Profile.Header private OverlinedInfoContainer ppInfo; private OverlinedInfoContainer detailGlobalRank; private OverlinedInfoContainer detailCountryRank; + private FillFlowContainer fillFlow; private RankGraph rankGraph; public readonly Bindable User = new Bindable(); + private bool expanded = true; + + public bool Expanded + { + set + { + if (expanded == value) return; + + expanded = value; + + if (fillFlow == null) return; + + fillFlow.ClearTransforms(); + + if (expanded) + fillFlow.AutoSizeAxes = Axes.Y; + else + { + fillFlow.AutoSizeAxes = Axes.None; + fillFlow.ResizeHeightTo(0, 200, Easing.OutQuint); + } + } + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { AutoSizeAxes = Axes.Y; + User.ValueChanged += e => updateDisplay(e.NewValue); InternalChildren = new Drawable[] @@ -43,10 +69,13 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.Both, Colour = colours.CommunityUserGrayGreenDarkest, }, - new FillFlowContainer + fillFlow = new FillFlowContainer { RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, + AutoSizeAxes = expanded ? Axes.Y : Axes.None, + AutoSizeDuration = 200, + AutoSizeEasing = Easing.OutQuint, + Masking = true, Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, Direction = FillDirection.Vertical, Spacing = new Vector2(0, 20), diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index f5233cf70c..2d8c47b11a 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -117,7 +117,7 @@ namespace osu.Game.Overlays.Profile infoTabControl.AddItem("Info"); infoTabControl.AddItem("Modding"); - centreHeaderContainer.DetailsVisible.BindValueChanged(visible => detailHeaderContainer.Alpha = visible.NewValue ? 1 : 0, true); + centreHeaderContainer.DetailsVisible.BindValueChanged(visible => detailHeaderContainer.Expanded = visible.NewValue, true); User.ValueChanged += e => updateDisplay(e.NewValue); } From b9a39fb7880b3dfa818a0e3e59f89343b2241d51 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Apr 2019 21:52:49 +0900 Subject: [PATCH 0689/5608] Fix instant pausing when game becomes inactive Resolves #4685. --- .../Screens/Play/HUD/HoldForMenuButton.cs | 24 +++++++++++++++++++ osu.Game/Screens/Play/Player.cs | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index c0ee5e6142..6f2738e4a1 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -70,6 +70,11 @@ namespace osu.Game.Screens.Play.HUD return base.OnMouseMove(e); } + public bool GameInactive + { + set => button.GameInactive = value; + } + protected override void Update() { base.Update(); @@ -184,6 +189,25 @@ namespace osu.Game.Screens.Play.HUD base.OnHoverLost(e); } + private bool gameInactive; + + public bool GameInactive + { + get => gameInactive; + set + { + if (gameInactive == value) + return; + + gameInactive = value; + + if (gameInactive) + BeginConfirm(); + else + AbortConfirm(); + } + } + public bool OnPressed(GlobalAction action) { switch (action) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 81fa348d72..516caf8744 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -393,8 +393,8 @@ namespace osu.Game.Screens.Play base.Update(); // eagerly pause when we lose window focus (if we are locally playing). - if (PauseOnFocusLost && !Game.IsActive.Value) - Pause(); + if (PauseOnFocusLost) + HUDOverlay.HoldToQuit.GameInactive = !Game.IsActive.Value; } public void Pause() From 3e3f12f27722c1dc2b2473a39be52dd48f64f45a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 4 May 2019 16:50:36 +0900 Subject: [PATCH 0690/5608] Use more local bindables --- .../Visual/Gameplay/TestCasePause.cs | 5 ++- .../Screens/Play/HUD/HoldForMenuButton.cs | 37 ++++++++++++------- osu.Game/Screens/Play/Player.cs | 11 ------ 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs index a52e84ed62..b9c7fd14bd 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs @@ -196,9 +196,10 @@ namespace osu.Game.Tests.Visual.Gameplay public bool PauseOverlayVisible => PauseOverlay.State == Visibility.Visible; - public PausePlayer() + protected override void LoadComplete() { - PauseOnFocusLost = false; + base.LoadComplete(); + HUDOverlay.HoldToQuit.PauseOnFocusLost = false; } } } diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 6f2738e4a1..41591e98c0 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -70,9 +71,9 @@ namespace osu.Game.Screens.Play.HUD return base.OnMouseMove(e); } - public bool GameInactive + public bool PauseOnFocusLost { - set => button.GameInactive = value; + set => button.PauseOnFocusLost = value; } protected override void Update() @@ -98,8 +99,10 @@ namespace osu.Game.Screens.Play.HUD public Action HoverGained; public Action HoverLost; + private readonly IBindable gameActive = new Bindable(true); + [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, Framework.Game game) { Size = new Vector2(60); @@ -140,6 +143,9 @@ namespace osu.Game.Screens.Play.HUD }; bind(); + + gameActive.BindValueChanged(_ => updateActive()); + gameActive.BindTo(game.IsActive); } private void bind() @@ -189,25 +195,30 @@ namespace osu.Game.Screens.Play.HUD base.OnHoverLost(e); } - private bool gameInactive; + private bool pauseOnFocusLost; - public bool GameInactive + public bool PauseOnFocusLost { - get => gameInactive; set { - if (gameInactive == value) + if (pauseOnFocusLost == value) return; - gameInactive = value; - - if (gameInactive) - BeginConfirm(); - else - AbortConfirm(); + pauseOnFocusLost = value; + updateActive(); } } + private void updateActive() + { + if (!pauseOnFocusLost) return; + + if (gameActive.Value) + AbortConfirm(); + else + BeginConfirm(); + } + public bool OnPressed(GlobalAction action) { switch (action) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 516caf8744..fd9ddec314 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -44,8 +44,6 @@ namespace osu.Game.Screens.Play public bool HasFailed { get; private set; } - public bool PauseOnFocusLost { get; set; } = true; - private Bindable mouseWheelDisabled; private readonly Bindable storyboardReplacesBackground = new Bindable(); @@ -388,15 +386,6 @@ namespace osu.Game.Screens.Play // already resuming && !IsResuming; - protected override void Update() - { - base.Update(); - - // eagerly pause when we lose window focus (if we are locally playing). - if (PauseOnFocusLost) - HUDOverlay.HoldToQuit.GameInactive = !Game.IsActive.Value; - } - public void Pause() { if (!canPause) return; From 7fdc79dd68f32d13456aaa64994881215cf21b41 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 5 May 2019 20:20:41 +0900 Subject: [PATCH 0691/5608] Improve skip boundary logic to be closer to expectations Supersedes #4693. Closes #4676. --- osu.Game/Screens/Play/SkipOverlay.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 738877232d..65cf5e51f3 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -38,6 +38,10 @@ namespace osu.Game.Screens.Play public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; protected override bool BlockPositionalInput => false; + /// + /// Displays a skip overlay, giving the user the ability to skip forward. + /// + /// The time at which gameplay begins to appear. public SkipOverlay(double startTime) { this.startTime = startTime; @@ -87,16 +91,21 @@ namespace osu.Game.Screens.Play }; } - private const double skip_required_cutoff = 3000; + /// + /// Duration before gameplay start time required before skip button displays. + /// + private const double skip_buffer = 1000; + private const double fade_time = 300; - private double beginFadeTime => startTime - skip_required_cutoff - fade_time; + private double beginFadeTime => startTime - fade_time; protected override void LoadComplete() { base.LoadComplete(); - if (startTime < skip_required_cutoff) + // skip is not required if there is no extra "empty" time to skip. + if (Clock.CurrentTime > beginFadeTime - skip_buffer) { Alpha = 0; Expire(); @@ -107,7 +116,7 @@ namespace osu.Game.Screens.Play using (BeginAbsoluteSequence(beginFadeTime)) this.FadeOut(fade_time); - button.Action = () => RequestSeek?.Invoke(startTime - skip_required_cutoff - fade_time); + button.Action = () => RequestSeek?.Invoke(beginFadeTime); displayTime = Time.Current; From b216635488b934bc1a6c114750184879d6fdcac8 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 5 May 2019 20:07:55 +0200 Subject: [PATCH 0692/5608] Added UserActivity class holding information about the current activity for the local user --- osu.Game/Users/User.cs | 2 + osu.Game/Users/UserActivity.cs | 70 ++++++++++++++++++++++++++++++++++ osu.Game/Users/UserStatus.cs | 56 --------------------------- 3 files changed, 72 insertions(+), 56 deletions(-) create mode 100644 osu.Game/Users/UserActivity.cs diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 314684069a..cf67af7bb8 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -25,6 +25,8 @@ namespace osu.Game.Users public Bindable Status = new Bindable(); + public Bindable Activity = new Bindable(); + //public Team Team; [JsonProperty(@"profile_colour")] diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs new file mode 100644 index 0000000000..1e69cc3e8e --- /dev/null +++ b/osu.Game/Users/UserActivity.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 osu.Game.Beatmaps; +using osu.Game.Graphics; +using osuTK.Graphics; + +namespace osu.Game.Users +{ + public abstract class UserActivity + { + public abstract string Status { get; } + public virtual Color4 GetAppropriateColour(OsuColour colours) => colours.GreenDarker; + } + + public class UserActivityModding : UserActivity + { + public override string Status => "Modding a map"; + public override Color4 GetAppropriateColour(OsuColour colours) => colours.PurpleDark; + } + + public class UserActivityChoosingBeatmap : UserActivity + { + public override string Status => "Choosing a beatmap"; + } + + public class UserActivityMultiplayerGame : UserActivity + { + public override string Status => "Multiplaying"; + } + + public class UserActivityEditing : UserActivity + { + public UserActivityEditing(BeatmapInfo info) + { + Beatmap = info; + } + + public override string Status => @"Editing a beatmap"; + + public BeatmapInfo Beatmap { get; } + } + + public class UserActivitySoloGame : UserActivity + { + public UserActivitySoloGame(BeatmapInfo info, Rulesets.RulesetInfo ruleset) + { + Beatmap = info; + Ruleset = ruleset; + } + + public override string Status => @"Solo Game"; + + public BeatmapInfo Beatmap { get; } + + public Rulesets.RulesetInfo Ruleset { get; } + } + + public class UserActivitySpectating : UserActivity + { + public override string Status => @"Spectating a game"; + } + + public class UserActivityInLobby : UserActivity + { + public override string Status => @"in Multiplayer Lobby"; + } + + +} diff --git a/osu.Game/Users/UserStatus.cs b/osu.Game/Users/UserStatus.cs index 0ee12ed63f..cf372560af 100644 --- a/osu.Game/Users/UserStatus.cs +++ b/osu.Game/Users/UserStatus.cs @@ -3,7 +3,6 @@ using osuTK.Graphics; using osu.Game.Graphics; -using osu.Game.Beatmaps; namespace osu.Game.Users { @@ -30,61 +29,6 @@ namespace osu.Game.Users public override Color4 GetAppropriateColour(OsuColour colours) => colours.Gray7; } - public class UserStatusSpectating : UserStatusOnline - { - public override string Message => @"Spectating a game"; - } - - public class UserStatusInLobby : UserStatusOnline - { - public override string Message => @"in Multiplayer Lobby"; - } - - public class UserStatusSoloGame : UserStatusBusy - { - public UserStatusSoloGame(BeatmapInfo info, Rulesets.RulesetInfo ruleset) - { - Beatmap = info; - Ruleset = ruleset; - } - - public override string Message => @"Solo Game"; - - public BeatmapInfo Beatmap { get; } - - public Rulesets.RulesetInfo Ruleset { get; } - } - - public class UserStatusEditing : UserStatusBusy - { - public UserStatusEditing(BeatmapInfo info) - { - Beatmap = info; - } - - public override string Message => @"Editing a beatmap"; - - public override Color4 GetAppropriateColour(OsuColour colours) => colours.GreenDarker; - - public BeatmapInfo Beatmap { get; } - } - - public class UserStatusChoosingBeatmap : UserStatusOnline - { - public override string Message => @"Choosing a beatmap"; - } - - public class UserStatusMultiplayerGame : UserStatusBusy - { - public override string Message => @"Multiplaying"; - } - - public class UserStatusModding : UserStatusOnline - { - public override string Message => @"Modding a map"; - public override Color4 GetAppropriateColour(OsuColour colours) => colours.PurpleDark; - } - public class UserStatusDoNotDisturb : UserStatus { public override string Message => @"Do not disturb"; From fa986bb5e94b255a6d9bbf0715fc9735ec1acea9 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 5 May 2019 20:26:56 +0200 Subject: [PATCH 0693/5608] Rework OsuScreen user activity logic --- osu.Game/Screens/OsuScreen.cs | 53 ++++++++--------------------------- 1 file changed, 11 insertions(+), 42 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 17b8ca60dc..d8b38ff20a 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -55,29 +55,27 @@ namespace osu.Game.Screens protected new OsuGameBase Game => base.Game as OsuGameBase; /// - /// The to set the user's status automatically to when this screen is entered + /// The to set the user's activity automatically to when this screen is entered /// - protected virtual UserStatusOnline InitialScreenStatus => new UserStatusOnline(); + protected virtual UserActivity InitialScreenActivity => null; /// - /// The for this screen. - /// Note that the status won't be updated for the user if : - /// - The is set to null - /// - The current of the user is or + /// The for this screen. /// - protected UserStatusOnline ScreenStatus + protected UserActivity ScreenActivity { set { if (value == null) return; + if (api == null) return; - status = value; - setUserStatus(value); + activity = value; + api.LocalUser.Value.Activity.Value = activity; } - get => status; + get => activity; } - private UserStatusOnline status; + private UserActivity activity; /// /// Whether to disallow changes to game-wise Beatmap/Ruleset bindables for this screen (and all children). @@ -122,7 +120,7 @@ namespace osu.Game.Screens Anchor = Anchor.Centre; Origin = Anchor.Centre; - status = null; + activity = null; } [BackgroundDependencyLoader(true)] @@ -152,28 +150,15 @@ namespace osu.Game.Screens sampleExit?.Play(); applyArrivingDefaults(true); - if (api != null) - api.LocalUser.Value.Status.ValueChanged += userStatusChanged; - ScreenStatus = ScreenStatus; base.OnResuming(last); } - private void userStatusChanged(ValueChangedEvent obj) - { - if (obj.NewValue?.GetType() == ScreenStatus?.GetType()) return; //don't update the user's status if the current status is of the same type as the given one - - setUserStatus(ScreenStatus); - } - public override void OnSuspending(IScreen next) { base.OnSuspending(next); - if (api != null) - api.LocalUser.Value.Status.ValueChanged -= userStatusChanged; - onSuspendingLogo(); } @@ -183,10 +168,7 @@ namespace osu.Game.Screens backgroundStack?.Push(localBackground = CreateBackground()); - if (api != null) - api.LocalUser.Value.Status.ValueChanged += userStatusChanged; - - ScreenStatus = InitialScreenStatus; + ScreenStatus = InitialScreenActivity; base.OnEntering(last); } @@ -196,9 +178,6 @@ namespace osu.Game.Screens if (ValidForResume && logo != null) onExitingLogo(); - if (api != null) - api.LocalUser.Value.Status.ValueChanged -= userStatusChanged; - if (base.OnExiting(next)) return true; @@ -208,16 +187,6 @@ namespace osu.Game.Screens return false; } - private void setUserStatus(UserStatus status) - { - if (api == null) return; - if (status == null) return; - - if (!(api.LocalUser.Value.Status.Value is UserStatusOnline)) return; //don't update the user's status if the current status doesn't allow to be modified by screens (eg: DND / Offline) - - api.LocalUser.Value.Status.Value = status; - } - /// /// Fired when this screen was entered or resumed and the logo state is required to be adjusted. /// From 88b8afbb6aa0c8468b3b9e22e760ca9735e4fda2 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 5 May 2019 20:51:55 +0200 Subject: [PATCH 0694/5608] Make UserPanel show current user activity when user status is online. --- .../Sections/General/LoginSettings.cs | 1 + osu.Game/Overlays/SocialOverlay.cs | 1 + osu.Game/Screens/OsuScreen.cs | 4 ++-- osu.Game/Users/UserPanel.cs | 21 +++++++++++++++---- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 98eb4b662f..bf5a3c12f5 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -152,6 +152,7 @@ namespace osu.Game.Overlays.Settings.Sections.General }; panel.Status.BindTo(api.LocalUser.Value.Status); + panel.Activity.BindTo(api.LocalUser.Value.Activity); dropdown.Current.ValueChanged += action => { diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index daf3d1c576..0ad3541071 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -126,6 +126,7 @@ namespace osu.Game.Overlays } panel.Status.BindTo(u.Status); + panel.Activity.BindTo(u.Activity); return panel; }) }; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index d8b38ff20a..170f548676 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -150,7 +150,7 @@ namespace osu.Game.Screens sampleExit?.Play(); applyArrivingDefaults(true); - ScreenStatus = ScreenStatus; + ScreenActivity = ScreenActivity; base.OnResuming(last); } @@ -168,7 +168,7 @@ namespace osu.Game.Screens backgroundStack?.Push(localBackground = CreateBackground()); - ScreenStatus = InitialScreenActivity; + ScreenActivity = InitialScreenActivity; base.OnEntering(last); } diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 47571b673d..d5061ad423 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -30,6 +30,9 @@ namespace osu.Game.Users private const float content_padding = 10; private const float status_height = 30; + [Resolved(canBeNull: true)] + private OsuColour colours { get; set; } + private Container statusBar; private Box statusBg; private OsuSpriteText statusMessage; @@ -39,6 +42,8 @@ namespace osu.Game.Users public readonly Bindable Status = new Bindable(); + public readonly Bindable Activity = new Bindable(); + public new Action Action; protected Action ViewProfile; @@ -54,7 +59,7 @@ namespace osu.Game.Users } [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuColour colours, UserProfileOverlay profile) + private void load(UserProfileOverlay profile) { if (colours == null) throw new ArgumentNullException(nameof(colours)); @@ -195,8 +200,8 @@ namespace osu.Game.Users }); } - Status.ValueChanged += status => displayStatus(status.NewValue); - Status.ValueChanged += status => statusBg.FadeColour(status.NewValue?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint); + Status.ValueChanged += status => displayStatus(status.NewValue, Activity.Value); + Activity.ValueChanged += activity => displayStatus(Status.Value, activity.NewValue); base.Action = ViewProfile = () => { @@ -211,7 +216,7 @@ namespace osu.Game.Users Status.TriggerChange(); } - private void displayStatus(UserStatus status) + private void displayStatus(UserStatus status, UserActivity activity = null) { const float transition_duration = 500; @@ -227,7 +232,15 @@ namespace osu.Game.Users statusBar.FadeIn(transition_duration, Easing.OutQuint); this.ResizeHeightTo(height, transition_duration, Easing.OutQuint); + if (status is UserStatusOnline && activity != null) + { + statusMessage.Text = activity.Status; + statusBg.FadeColour(status.GetAppropriateColour(colours), 500, Easing.OutQuint); + return; + } + statusMessage.Text = status.Message; + statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint); } } From d5d31282e520511de72eb5c4e91fe25507ec250b Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 5 May 2019 20:55:42 +0200 Subject: [PATCH 0695/5608] Rename InitialScreenStatus to InitialScreenActivity in Editor / Player classes --- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- osu.Game/Screens/Select/PlaySongSelect.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index a04124082c..33f86b99bf 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -48,7 +48,7 @@ namespace osu.Game.Screens.Edit private DependencyContainer dependencies; private GameHost host; - protected override UserStatusOnline InitialScreenStatus => new UserStatusEditing(Beatmap.Value.BeatmapInfo); + protected override UserActivity InitialScreenActivity => new UserActivityEditing(Beatmap.Value.BeatmapInfo); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index b75bfa9e04..f59c87d79e 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Play { protected override bool AllowBackButton => false; // handled by HoldForMenuButton - protected override UserStatusOnline InitialScreenStatus => new UserStatusSoloGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); + protected override UserActivity InitialScreenActivity => new UserActivitySoloGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); public override float BackgroundParallaxAmount => 0.1f; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 8c4bf079ea..0385a70206 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Play private bool hideOverlays; public override bool HideOverlaysOnEnter => hideOverlays; - protected override UserStatusOnline InitialScreenStatus => null; //shows the previous screen status + protected override UserActivity InitialScreenActivity => null; //shows the previous screen status public override bool DisallowExternalBeatmapRulesetChanges => true; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 58b8ef3d28..d52b6d44f5 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Select public override bool AllowExternalScreenChange => true; - protected override UserStatusOnline InitialScreenStatus => new UserStatusChoosingBeatmap(); + protected override UserActivity InitialScreenActivity => new UserActivityChoosingBeatmap(); [BackgroundDependencyLoader] private void load(OsuColour colours) From 8beb2f6e90d4e1fbe33f6d823886646b036be8b8 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 5 May 2019 21:01:35 +0200 Subject: [PATCH 0696/5608] Remove hackery from unit tests. --- .../Visual/Background/TestCaseBackgroundScreenBeatmap.cs | 5 ----- osu.Game.Tests/Visual/Gameplay/TestCasePause.cs | 2 -- 2 files changed, 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs index 58404d307f..e9208d8f5b 100644 --- a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs @@ -275,7 +275,6 @@ namespace osu.Game.Tests.Visual.Background private class DummySongSelect : PlaySongSelect { - protected override UserStatusOnline InitialScreenStatus => null; protected override BackgroundScreen CreateBackground() { @@ -320,7 +319,6 @@ namespace osu.Game.Tests.Visual.Background private class FadeAccessibleResults : SoloResults { - protected override UserStatusOnline InitialScreenStatus => null; public FadeAccessibleResults(ScoreInfo score) : base(score) @@ -334,7 +332,6 @@ namespace osu.Game.Tests.Visual.Background private class TestPlayer : Player { - protected override UserStatusOnline InitialScreenStatus => null; protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); @@ -383,8 +380,6 @@ namespace osu.Game.Tests.Visual.Background public VisualSettings VisualSettingsPos => VisualSettings; public BackgroundScreen ScreenPos => Background; - protected override UserStatusOnline InitialScreenStatus => null; - public TestPlayerLoader(Player player) : base(() => player) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs index ae7faf318f..dec4830188 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs @@ -193,8 +193,6 @@ namespace osu.Game.Tests.Visual.Gameplay public new HUDOverlay HUDOverlay => base.HUDOverlay; - protected override UserStatusOnline InitialScreenStatus => null; - public bool FailOverlayVisible => FailOverlay.State == Visibility.Visible; public bool PauseOverlayVisible => PauseOverlay.State == Visibility.Visible; From 3d8b56fe57b6f5d72e25dc06370692f9ded43918 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 5 May 2019 21:11:52 +0200 Subject: [PATCH 0697/5608] Fix user status related unit tests --- .../Visual/Online/TestCaseUserPanel.cs | 33 +++++++++++++------ osu.Game/Users/UserPanel.cs | 2 +- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs b/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs index ef91c843f2..3929fe6c50 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs @@ -12,10 +12,11 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestCaseUserPanel : OsuTestCase { + UserPanel flyte; + UserPanel peppy; + public TestCaseUserPanel() { - UserPanel flyte; - UserPanel peppy; Add(new FillFlowContainer { Anchor = Anchor.Centre, @@ -44,15 +45,27 @@ namespace osu.Game.Tests.Visual.Online }); flyte.Status.Value = new UserStatusOnline(); - peppy.Status.Value = new UserStatusSoloGame(null, null); + peppy.Status.Value = null; + } - AddStep(@"spectating", () => { flyte.Status.Value = new UserStatusSpectating(); }); - AddStep(@"multiplaying", () => { flyte.Status.Value = new UserStatusMultiplayerGame(); }); - AddStep(@"modding", () => { flyte.Status.Value = new UserStatusModding(); }); - AddStep(@"editing", () => { flyte.Status.Value = new UserStatusEditing(null); }); - AddStep(@"choosing", () => { flyte.Status.Value = new UserStatusChoosingBeatmap(); }); - AddStep(@"offline", () => { flyte.Status.Value = new UserStatusOffline(); }); - AddStep(@"null status", () => { flyte.Status.Value = null; }); + [Test] + public void UserStatusesTests() + { + AddStep("online", () => { peppy.Status.Value = new UserStatusOnline(); }); + AddStep(@"do not disturb", () => { peppy.Status.Value = new UserStatusDoNotDisturb(); }); + AddStep(@"offline", () => { peppy.Status.Value = new UserStatusOffline(); }); + AddStep(@"null status", () => { peppy.Status.Value = null; }); + } + + [Test] + public void UserActivitiesTests() + { + AddStep("idle", () => { flyte.Activity.Value = null; }); + AddStep("spectating", () => { flyte.Activity.Value = new UserActivitySpectating(); }); + AddStep("solo", () => { flyte.Activity.Value = new UserActivitySoloGame(null, null); }); + AddStep("choosing", () => { flyte.Activity.Value = new UserActivityChoosingBeatmap(); }); + AddStep("editing", () => { flyte.Activity.Value = new UserActivityEditing(null); }); + AddStep("modding", () => { flyte.Activity.Value = new UserActivityModding(); }); } } } diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index d5061ad423..410ade33fb 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -235,7 +235,7 @@ namespace osu.Game.Users if (status is UserStatusOnline && activity != null) { statusMessage.Text = activity.Status; - statusBg.FadeColour(status.GetAppropriateColour(colours), 500, Easing.OutQuint); + statusBg.FadeColour(activity.GetAppropriateColour(colours), 500, Easing.OutQuint); return; } From a50bbf7f4208bbd5998ffdc2094bd5c58f721c2c Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 5 May 2019 21:32:23 +0200 Subject: [PATCH 0698/5608] Make appveyor happy. --- .../Visual/Background/TestCaseBackgroundScreenBeatmap.cs | 3 --- osu.Game.Tests/Visual/Gameplay/TestCasePause.cs | 1 - osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs | 4 ++-- osu.Game/Screens/OsuScreen.cs | 4 ++-- osu.Game/Users/UserActivity.cs | 2 -- osu.Game/Users/UserPanel.cs | 6 +++--- 6 files changed, 7 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs index e9208d8f5b..81fab5b4b3 100644 --- a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs @@ -275,7 +275,6 @@ namespace osu.Game.Tests.Visual.Background private class DummySongSelect : PlaySongSelect { - protected override BackgroundScreen CreateBackground() { FadeAccessibleBackground background = new FadeAccessibleBackground(Beatmap.Value); @@ -319,7 +318,6 @@ namespace osu.Game.Tests.Visual.Background private class FadeAccessibleResults : SoloResults { - public FadeAccessibleResults(ScoreInfo score) : base(score) { @@ -332,7 +330,6 @@ namespace osu.Game.Tests.Visual.Background private class TestPlayer : Player { - protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); protected override UserDimContainer CreateStoryboardContainer() diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs index dec4830188..a52e84ed62 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs @@ -12,7 +12,6 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; -using osu.Game.Users; using osuTK; using osuTK.Input; diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs b/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs index 3929fe6c50..0e958f45c6 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs @@ -12,8 +12,8 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestCaseUserPanel : OsuTestCase { - UserPanel flyte; - UserPanel peppy; + private readonly UserPanel flyte; + private readonly UserPanel peppy; public TestCaseUserPanel() { diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 170f548676..8a6049b6fd 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -64,15 +64,15 @@ namespace osu.Game.Screens /// protected UserActivity ScreenActivity { + get => activity; set { - if (value == null) return; + if (value == activity) return; if (api == null) return; activity = value; api.LocalUser.Value.Activity.Value = activity; } - get => activity; } private UserActivity activity; diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 1e69cc3e8e..fb896413e5 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -65,6 +65,4 @@ namespace osu.Game.Users { public override string Status => @"in Multiplayer Lobby"; } - - } diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 410ade33fb..1f31ead1e7 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -238,10 +238,10 @@ namespace osu.Game.Users statusBg.FadeColour(activity.GetAppropriateColour(colours), 500, Easing.OutQuint); return; } - - statusMessage.Text = status.Message; - statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint); } + + statusMessage.Text = status?.Message; + statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint); } public MenuItem[] ContextMenuItems => new MenuItem[] From 8ef6a745f74ed7e3abb3eba77097819435c069d3 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 5 May 2019 22:43:03 -0700 Subject: [PATCH 0699/5608] Fix slider border not reverting to default color --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 57ea0abdd8..def034877a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -161,7 +161,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.SkinChanged(skin, allowFallback); Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? Body.AccentColour; - Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Body.BorderColour; + Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Color4.White; Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Ball.AccentColour; } From 59b8da5c77ab5e9d6304daea09621fa6a36bca53 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Mon, 6 May 2019 18:37:21 +0200 Subject: [PATCH 0700/5608] Move OsuScreen activity logic to setUserActivity() --- osu.Game/Screens/OsuScreen.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 8a6049b6fd..ad90e97a09 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -68,10 +68,9 @@ namespace osu.Game.Screens set { if (value == activity) return; - if (api == null) return; activity = value; - api.LocalUser.Value.Activity.Value = activity; + setUserActivity(activity); } } @@ -150,7 +149,7 @@ namespace osu.Game.Screens sampleExit?.Play(); applyArrivingDefaults(true); - ScreenActivity = ScreenActivity; + setUserActivity(activity); base.OnResuming(last); } @@ -159,6 +158,8 @@ namespace osu.Game.Screens { base.OnSuspending(next); + setUserActivity(null); + onSuspendingLogo(); } @@ -175,6 +176,8 @@ namespace osu.Game.Screens public override bool OnExiting(IScreen next) { + setUserActivity(null); + if (ValidForResume && logo != null) onExitingLogo(); @@ -187,6 +190,13 @@ namespace osu.Game.Screens return false; } + private void setUserActivity(UserActivity activity) + { + if (api == null) return; + + api.LocalUser.Value.Activity.Value = activity; + } + /// /// Fired when this screen was entered or resumed and the logo state is required to be adjusted. /// From abc163fa36fac13a90d732267484b3eeffc94668 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 7 May 2019 12:07:45 +0900 Subject: [PATCH 0701/5608] Fix merge --- osu.Game/Rulesets/Mods/ModFlashlight.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index a477868ad0..e174a25df3 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -177,7 +177,7 @@ namespace osu.Game.Rulesets.Mods shader.GetUniform("flashlightPos").UpdateValue(ref flashlightPosition); shader.GetUniform("flashlightSize").UpdateValue(ref flashlightSize); - shader.GetUniform("flashlightDim").UpdateValue(ref FlashlightDim); + shader.GetUniform("flashlightDim").UpdateValue(ref flashlightDim); Texture.WhitePixel.DrawQuad(screenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction); From f26a1cff6cc7b1666e450d190d2c54e57a860531 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 7 May 2019 12:14:57 +0900 Subject: [PATCH 0702/5608] Fix beatmap import crashing during room creation --- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 6271693a6a..a69b3d87ae 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -206,7 +206,7 @@ namespace osu.Game.Screens.Multi.Match if (Beatmap.Value != beatmapManager.DefaultBeatmap) return; - if (Beatmap.Value == null) + if (CurrentItem.Value == null) return; // Try to retrieve the corresponding local beatmap From 3661ddbff61c92dae456656974f5253a02681c59 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 7 May 2019 13:02:19 +0900 Subject: [PATCH 0703/5608] Fix player loader testcase potentially failing --- .../Visual/Gameplay/TestCasePlayerLoader.cs | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs index 15c38e6d18..4ec0299c9a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -34,20 +35,20 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestLoadContinuation() { - AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => new Player(false, false)))); + Player player = null; + SlowLoadPlayer slowPlayer = null; + + AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => player = new Player(false, false)))); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); - AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen()); + AddUntilStep("wait for player to be current", () => player.IsCurrentScreen()); AddStep("load slow dummy beatmap", () => { - SlowLoadPlayer slow = null; - - stack.Push(loader = new PlayerLoader(() => slow = new SlowLoadPlayer(false, false))); - - Scheduler.AddDelayed(() => slow.Ready = true, 5000); + stack.Push(loader = new PlayerLoader(() => slowPlayer = new SlowLoadPlayer(false, false))); + Scheduler.AddDelayed(() => slowPlayer.AllowLoad.Set(), 5000); }); - AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen()); + AddUntilStep("wait for player to be current", () => slowPlayer.IsCurrentScreen()); } [Test] @@ -113,7 +114,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected class SlowLoadPlayer : Player { - public bool Ready; + public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim(false); public SlowLoadPlayer(bool allowPause = true, bool showResults = true) : base(allowPause, showResults) @@ -123,8 +124,8 @@ namespace osu.Game.Tests.Visual.Gameplay [BackgroundDependencyLoader] private void load() { - while (!Ready) - Thread.Sleep(1); + if (!AllowLoad.Wait(TimeSpan.FromSeconds(10))) + throw new TimeoutException(); } } } From 13b9b04bb804c06f62be86de4a2b54f0aec2d930 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 7 May 2019 13:23:09 +0900 Subject: [PATCH 0704/5608] Apply more cases/fix some existing ones --- osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs | 1 + osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs | 1 + osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs | 6 ++++++ osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs | 5 ----- osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs | 2 ++ osu.Game/Graphics/OsuFont.cs | 1 - .../Online/API/Requests/Responses/APILegacyScoreInfo.cs | 1 - osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 1 + .../Overlays/Profile/Header/Components/SupporterIcon.cs | 1 + osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs | 2 ++ osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs | 1 + osu.Game/Overlays/Profile/ProfileHeader.cs | 4 ++-- osu.Game/Rulesets/Mods/ModHidden.cs | 2 ++ osu.Game/Rulesets/UI/Playfield.cs | 1 + osu.Game/Users/UserStatistics.cs | 5 +++++ 15 files changed, 25 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 0d0ca6506c..99b22b2d56 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -32,6 +32,7 @@ namespace osu.Game.Rulesets.Catch.Scoring { case HitResult.Miss: return hpDrainRate; + default: return 10.2 - hpDrainRate; // Award less HP as drain rate is increased } diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs index 48c2eb547b..b9c6e3a7f7 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs @@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Mania.Judgements { case HitResult.Miss: return 0; + default: return 0.040; } diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs index 3727966390..0e4c811945 100644 --- a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs @@ -36,16 +36,22 @@ namespace osu.Game.Rulesets.Mania.Judgements { case HitResult.Miss: return -0.125; + case HitResult.Meh: return 0.005; + case HitResult.Ok: return 0.010; + case HitResult.Good: return 0.035; + case HitResult.Great: return 0.055; + case HitResult.Perfect: return 0.065; + default: return 0; } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 7a39263edf..5caf08fb1e 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -85,11 +85,6 @@ namespace osu.Game.Rulesets.Mania.Scoring protected override double HealthAdjustmentFactorFor(JudgementResult result) => result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier; - - - - - public override HitWindows CreateHitWindows() => new ManiaHitWindows(); } } diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs index 1531b64cc6..7a5b98864c 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs @@ -34,10 +34,12 @@ namespace osu.Game.Rulesets.Osu.Judgements { case HitResult.Miss: return -0.02; + case HitResult.Meh: case HitResult.Good: case HitResult.Great: return 0.01; + default: return 0; } diff --git a/osu.Game/Graphics/OsuFont.cs b/osu.Game/Graphics/OsuFont.cs index 121f5b6f81..22250d4a56 100644 --- a/osu.Game/Graphics/OsuFont.cs +++ b/osu.Game/Graphics/OsuFont.cs @@ -43,7 +43,6 @@ namespace osu.Game.Graphics case Typeface.Exo: return "Exo2.0"; - case Typeface.Venera: return "Venera"; } diff --git a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs index 358c571719..3060300077 100644 --- a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs @@ -70,7 +70,6 @@ namespace osu.Game.Online.API.Requests.Responses { foreach (var kvp in value) { - switch (kvp.Key) { case @"count_geki": diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index f97fecb913..52336dcd30 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -107,6 +107,7 @@ namespace osu.Game.Overlays.Profile.Header topLinkContainer.AddLink($@"{user.PostCount:#,##0} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: embolden); string websiteWithoutProtcol = user.Website; + if (!string.IsNullOrEmpty(websiteWithoutProtcol)) { if (Uri.TryCreate(websiteWithoutProtcol, UriKind.Absolute, out var uri)) diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index cb12a62702..97454d7327 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -34,6 +34,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { content.Show(); iconContainer.Clear(); + for (int i = 0; i < count; i++) { iconContainer.Add(new SpriteIcon diff --git a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs index 1e214b2d0c..25d04195b2 100644 --- a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs @@ -68,9 +68,11 @@ namespace osu.Game.Overlays.Profile.Header { var badges = user.Badges; badgeFlowContainer.Clear(); + if (badges?.Length > 0) { Show(); + for (var index = 0; index < badges.Length; index++) { int displayIndex = index; diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index c1fe430bdd..2ac7f3cc96 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -162,6 +162,7 @@ namespace osu.Game.Overlays.Profile.Header titleText.Colour = OsuColour.FromHex(user?.Colour ?? "fff"); userStats.Clear(); + if (user?.Statistics != null) { userStats.Add(new UserStatsLine("Ranked Score", user.Statistics.RankedScore.ToString("#,##0"))); diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index c742b8f0d7..2d8c47b11a 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -135,7 +135,6 @@ namespace osu.Game.Overlays.Profile } private class ProfileHeaderTitle : ScreenTitle - { public ProfileHeaderTitle() { @@ -145,8 +144,9 @@ namespace osu.Game.Overlays.Profile [BackgroundDependencyLoader] private void load(OsuColour colours) - + { AccentColour = colours.CommunityUserGreen; + } } } } diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index ea1c56623f..0934992f55 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -46,8 +46,10 @@ namespace osu.Game.Rulesets.Mods { case ScoreRank.X: return ScoreRank.XH; + case ScoreRank.S: return ScoreRank.SH; + default: return rank; } diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index a073ad246b..f2e7f51b52 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -67,6 +67,7 @@ namespace osu.Game.Rulesets.UI private void load() { Cursor = CreateCursor(); + if (Cursor != null) { // initial showing of the cursor will be handed by MenuCursorContainer (via DrawableRuleset's IProvideCursor implementation). diff --git a/osu.Game/Users/UserStatistics.cs b/osu.Game/Users/UserStatistics.cs index 752534a80d..7afbef01c5 100644 --- a/osu.Game/Users/UserStatistics.cs +++ b/osu.Game/Users/UserStatistics.cs @@ -85,14 +85,19 @@ namespace osu.Game.Users { case ScoreRank.XH: return SSPlus; + case ScoreRank.X: return SS; + case ScoreRank.SH: return SPlus; + case ScoreRank.S: return S; + case ScoreRank.A: return A; + default: throw new ArgumentException($"API does not return {rank.ToString()}"); } From 652a21b3dcac5a2b6c17f14011df8b31b003d8c7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 7 May 2019 13:31:54 +0900 Subject: [PATCH 0705/5608] Update r# CLT --- build/build.cake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/build.cake b/build/build.cake index de94eb7ab3..1d2588de49 100644 --- a/build/build.cake +++ b/build/build.cake @@ -1,5 +1,5 @@ #addin "nuget:?package=CodeFileSanity&version=0.0.21" -#addin "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2018.3.4" +#addin "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2019.1.1" #tool "nuget:?package=NVika.MSBuild&version=1.0.1" var nVikaToolPath = GetFiles("./tools/NVika.MSBuild.*/tools/NVika.exe").First(); From f7a570d67abab39e854b1dbe5f34f6a6571f6fd5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 May 2019 13:34:06 +0900 Subject: [PATCH 0706/5608] Fix double confirmation --- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 41591e98c0..446df94aca 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -144,10 +144,15 @@ namespace osu.Game.Screens.Play.HUD bind(); - gameActive.BindValueChanged(_ => updateActive()); gameActive.BindTo(game.IsActive); } + protected override void LoadComplete() + { + base.LoadComplete(); + gameActive.BindValueChanged(_ => updateActive(), true); + } + private void bind() { circularProgress.Current.BindTo(Progress); @@ -195,7 +200,7 @@ namespace osu.Game.Screens.Play.HUD base.OnHoverLost(e); } - private bool pauseOnFocusLost; + private bool pauseOnFocusLost = true; public bool PauseOnFocusLost { @@ -205,7 +210,8 @@ namespace osu.Game.Screens.Play.HUD return; pauseOnFocusLost = value; - updateActive(); + if (IsLoaded) + updateActive(); } } From 1cfb7550eee8c295e416d8f5c7749e3ec392e664 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 7 May 2019 13:42:55 +0900 Subject: [PATCH 0707/5608] Fix possible nullref --- osu.Desktop/Updater/SquirrelUpdateManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index 5fed2a63e1..9681350ade 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -175,7 +175,7 @@ namespace osu.Desktop.Updater public SquirrelLogger() { - var file = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "SquirrelSetupUpdater.log"); + var file = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location ?? Directory.GetCurrentDirectory()), "SquirrelSetupUpdater.log"); if (File.Exists(file)) File.Delete(file); path = file; } From 99f2ee0e48244308897b1a7bac23bce0ff08a09d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 7 May 2019 15:09:03 +0900 Subject: [PATCH 0708/5608] Fix CI issues --- osu.Game/Online/Leaderboards/DrawableRank.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Online/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs index 5224150181..ce64395dde 100644 --- a/osu.Game/Online/Leaderboards/DrawableRank.cs +++ b/osu.Game/Online/Leaderboards/DrawableRank.cs @@ -44,14 +44,17 @@ namespace osu.Game.Online.Leaderboards private void updateTexture() { string textureName; + switch (Rank) { default: textureName = Rank.GetDescription(); break; + case ScoreRank.SH: textureName = "SPlus"; break; + case ScoreRank.XH: textureName = "SSPlus"; break; From 1d2db85866906bf17e56f93a488d80df49ed5adf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 7 May 2019 17:23:44 +0900 Subject: [PATCH 0709/5608] Improve background sprite testcase --- ...stCaseUpdateableBeatmapBackgroundSprite.cs | 67 ++++++++++++++----- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs index 74114b2e53..dc0aff420a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs @@ -2,8 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; @@ -11,12 +11,15 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Rulesets; using osu.Game.Tests.Beatmaps.IO; +using osuTK; namespace osu.Game.Tests.Visual.UserInterface { public class TestCaseUpdateableBeatmapBackgroundSprite : OsuTestCase { - private TestUpdateableBeatmapBackgroundSprite backgroundSprite; + private BeatmapSetInfo testBeatmap; + private IAPIProvider api; + private RulesetStore rulesets; [Resolved] private BeatmapManager beatmaps { get; set; } @@ -24,40 +27,68 @@ namespace osu.Game.Tests.Visual.UserInterface [BackgroundDependencyLoader] private void load(OsuGameBase osu, IAPIProvider api, RulesetStore rulesets) { - Bindable beatmapBindable = new Bindable(); + this.api = api; + this.rulesets = rulesets; - var imported = ImportBeatmapTest.LoadOszIntoOsu(osu); + testBeatmap = ImportBeatmapTest.LoadOszIntoOsu(osu); + } - Child = backgroundSprite = new TestUpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }; + [Test] + public void TestNullBeatmap() + { + TestUpdateableBeatmapBackgroundSprite background = null; - backgroundSprite.Beatmap.BindTo(beatmapBindable); + AddStep("load null beatmap", () => Child = background = new TestUpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }); + AddUntilStep("wait for load", () => background.ContentLoaded); + } - var req = new GetBeatmapSetRequest(1); - api.Queue(req); + [Test] + public void TestLocalBeatmap() + { + TestUpdateableBeatmapBackgroundSprite background = null; - AddStep("load null beatmap", () => beatmapBindable.Value = null); - AddUntilStep("wait for cleanup...", () => backgroundSprite.ChildCount == 1); - AddStep("load imported beatmap", () => beatmapBindable.Value = imported.Beatmaps.First()); - AddUntilStep("wait for cleanup...", () => backgroundSprite.ChildCount == 1); + AddStep("load local beatmap", () => + { + Child = background = new TestUpdateableBeatmapBackgroundSprite + { + RelativeSizeAxes = Axes.Both, + Beatmap = { Value = testBeatmap.Beatmaps.First() } + }; + }); + AddUntilStep("wait for load", () => background.ContentLoaded); + } + + [Test] + public void TestOnlineBeatmap() + { if (api.IsLoggedIn) { + var req = new GetBeatmapSetRequest(1); + api.Queue(req); + AddUntilStep("wait for api response", () => req.Result != null); - AddStep("load online beatmap", () => beatmapBindable.Value = new BeatmapInfo + + TestUpdateableBeatmapBackgroundSprite background = null; + + AddStep("load online beatmap", () => { - BeatmapSet = req.Result?.ToBeatmapSet(rulesets) + Child = background = new TestUpdateableBeatmapBackgroundSprite + { + RelativeSizeAxes = Axes.Both, + Beatmap = { Value = new BeatmapInfo { BeatmapSet = req.Result?.ToBeatmapSet(rulesets) } } + }; }); - AddUntilStep("wait for cleanup...", () => backgroundSprite.ChildCount == 1); + + AddUntilStep("wait for load", () => background.ContentLoaded); } else - { AddStep("online (login first)", () => { }); - } } private class TestUpdateableBeatmapBackgroundSprite : UpdateableBeatmapBackgroundSprite { - public int ChildCount => InternalChildren.Count; + public bool ContentLoaded => ((DelayedLoadUnloadWrapper)InternalChildren.LastOrDefault())?.Content?.IsLoaded ?? false; } } } From a00e2b18a9034e5f1736d1b1c99489d8c1c47463 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 7 May 2019 17:24:05 +0900 Subject: [PATCH 0710/5608] Fix background unloading/reloading sometimes crashing --- ...stCaseUpdateableBeatmapBackgroundSprite.cs | 55 +++++++++++++++++++ .../UpdateableBeatmapBackgroundSprite.cs | 9 ++- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs index dc0aff420a..a4dd7b83e2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs @@ -1,10 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Online.API; @@ -86,8 +88,61 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("online (login first)", () => { }); } + [Test] + public void TestUnloadAndReload() + { + var backgrounds = new List(); + ScrollContainer scrollContainer = null; + + AddStep("create backgrounds hierarchy", () => + { + FillFlowContainer backgroundFlow; + + Child = scrollContainer = new ScrollContainer + { + Size = new Vector2(500), + Child = backgroundFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(10), + Padding = new MarginPadding { Bottom = 250 } + } + }; + + for (int i = 0; i < 25; i++) + { + var background = new TestUpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }; + + if (i % 2 == 0) + background.Beatmap.Value = testBeatmap.Beatmaps.First(); + + backgroundFlow.Add(new Container + { + RelativeSizeAxes = Axes.X, + Height = 100, + Masking = true, + Child = background + }); + + backgrounds.Add(background); + } + }); + + var loadedBackgrounds = backgrounds.Where(b => b.ContentLoaded); + + int initialLoadCount = 0; + + AddUntilStep("some loaded", () => (initialLoadCount = loadedBackgrounds.Count()) > 0); + AddStep("scroll to bottom", () => scrollContainer.ScrollToEnd()); + AddUntilStep("some unloaded", () => loadedBackgrounds.Count() < initialLoadCount); + } + private class TestUpdateableBeatmapBackgroundSprite : UpdateableBeatmapBackgroundSprite { + protected override double UnloadDelay => 2000; + public bool ContentLoaded => ((DelayedLoadUnloadWrapper)InternalChildren.LastOrDefault())?.Content?.IsLoaded ?? false; } } diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index ce7811fc0d..bd80919851 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -26,6 +26,11 @@ namespace osu.Game.Beatmaps.Drawables this.beatmapSetCoverType = beatmapSetCoverType; } + /// + /// Delay before the background is unloaded while off-screen. + /// + protected virtual double UnloadDelay => 10000; + private BeatmapInfo lastModel; protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Drawable content, double timeBeforeLoad) @@ -34,13 +39,13 @@ namespace osu.Game.Beatmaps.Drawables { // If DelayedLoadUnloadWrapper is attempting to RELOAD the same content (Beatmap), that means that it was // previously UNLOADED and thus its children have been disposed of, so we need to recreate them here. - if (lastModel == Beatmap.Value && Beatmap.Value != null) + if (lastModel == Beatmap.Value) return CreateDrawable(Beatmap.Value); // If the model has changed since the previous unload (or if there was no load), then we can safely use the given content lastModel = Beatmap.Value; return content; - }, timeBeforeLoad, 10000); + }, timeBeforeLoad, UnloadDelay); } protected override Drawable CreateDrawable(BeatmapInfo model) From 3ecfa9dcdb3dd513ca90b4b580bfaae69551b9ab Mon Sep 17 00:00:00 2001 From: Lucas A Date: Tue, 7 May 2019 18:26:34 +0200 Subject: [PATCH 0711/5608] Invert partialy activity logic introduced in latest commit --- osu.Game/Screens/OsuScreen.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index ad90e97a09..cc9aa285ff 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -158,8 +158,6 @@ namespace osu.Game.Screens { base.OnSuspending(next); - setUserActivity(null); - onSuspendingLogo(); } @@ -176,8 +174,6 @@ namespace osu.Game.Screens public override bool OnExiting(IScreen next) { - setUserActivity(null); - if (ValidForResume && logo != null) onExitingLogo(); From ff3c2265967ef633bdf91ba616d95f5bd9f3a60e Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 8 May 2019 13:37:03 +0900 Subject: [PATCH 0712/5608] Give ZoomableScrollContainer an initial width --- .../Editor/TestCaseZoomableScrollContainer.cs | 60 +++++++++++-------- .../Timeline/ZoomableScrollContainer.cs | 8 +++ 2 files changed, 44 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestCaseZoomableScrollContainer.cs b/osu.Game.Tests/Visual/Editor/TestCaseZoomableScrollContainer.cs index e2cf1ef28a..55c978ae06 100644 --- a/osu.Game.Tests/Visual/Editor/TestCaseZoomableScrollContainer.cs +++ b/osu.Game.Tests/Visual/Editor/TestCaseZoomableScrollContainer.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; +using osu.Framework.Testing; using osu.Game.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Screens.Edit.Compose.Components.Timeline; @@ -18,38 +19,49 @@ namespace osu.Game.Tests.Visual.Editor { public class TestCaseZoomableScrollContainer : ManualInputManagerTestCase { - private readonly ZoomableScrollContainer scrollContainer; - private readonly Drawable innerBox; + private ZoomableScrollContainer scrollContainer; + private Drawable innerBox; - public TestCaseZoomableScrollContainer() + [SetUpSteps] + public void SetUpSteps() { - Children = new Drawable[] + AddStep("Add new scroll container", () => { - new Container + Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, - Height = 250, - Width = 0.75f, - Children = new Drawable[] + new Container { - new Box + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Height = 250, + Width = 0.75f, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.Gray(30) - }, - scrollContainer = new ZoomableScrollContainer { RelativeSizeAxes = Axes.Both } - } - }, - new MenuCursor() - }; + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(30) + }, + scrollContainer = new ZoomableScrollContainer { RelativeSizeAxes = Axes.Both } + } + }, + new MenuCursor() + }; - scrollContainer.Add(innerBox = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(new Color4(0.8f, 0.6f, 0.4f, 1f), new Color4(0.4f, 0.6f, 0.8f, 1f)) + scrollContainer.Add(innerBox = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(new Color4(0.8f, 0.6f, 0.4f, 1f), new Color4(0.4f, 0.6f, 0.8f, 1f)) + }); }); + AddUntilStep("Scroll container is loaded", () => scrollContainer.LoadState >= LoadState.Loaded); + } + + [Test] + public void TestWidthInitialization() + { + AddAssert("Inner container width was initialized", () => innerBox.DrawWidth > 0); } [Test] diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index 9b00a3998d..ee6e29c92e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -102,6 +102,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline return true; } + protected override void LoadComplete() + { + base.LoadComplete(); + + // This width only gets updated on the application of a transform, so this needs to be initialized here. + zoomedContent.Width = DrawWidth * currentZoom; + } + private float zoomTarget = 1; private void setZoomTarget(float newZoom, float focusPoint) From 66ebdbbe4cf0e2aa9614c086ce1efb600dde7035 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 May 2019 18:13:07 +0900 Subject: [PATCH 0713/5608] Fix control points with same timestamp potentially being parsed incorrectly --- osu.Game/Beatmaps/ControlPoints/ControlPoint.cs | 5 +++++ osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 14 +++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 825b60ae5f..5e538126b3 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -12,6 +12,11 @@ namespace osu.Game.Beatmaps.ControlPoints /// public double Time; + /// + /// Whether this timing point was generated internally, as opposed to parsed from the underlying beatmap. + /// + internal bool AutoGenerated; + public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); /// diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index b489b5e6d9..46a6197546 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -374,14 +374,16 @@ namespace osu.Game.Beatmaps.Formats handleDifficultyControlPoint(new DifficultyControlPoint { Time = time, - SpeedMultiplier = speedMultiplier + SpeedMultiplier = speedMultiplier, + AutoGenerated = timingChange }); handleEffectControlPoint(new EffectControlPoint { Time = time, KiaiMode = kiaiMode, - OmitFirstBarLine = omitFirstBarSignature + OmitFirstBarLine = omitFirstBarSignature, + AutoGenerated = timingChange }); handleSampleControlPoint(new LegacySampleControlPoint @@ -389,7 +391,8 @@ namespace osu.Game.Beatmaps.Formats Time = time, SampleBank = stringSampleSet, SampleVolume = sampleVolume, - CustomSampleBank = customSampleBank + CustomSampleBank = customSampleBank, + AutoGenerated = timingChange }); } catch (FormatException) @@ -419,6 +422,11 @@ namespace osu.Game.Beatmaps.Formats if (newPoint.EquivalentTo(existing)) return; + // autogenerated points should not replace non-autogenerated. + // this allows for incorrectly ordered timing points to still be correctly handled. + if (newPoint.AutoGenerated && !existing.AutoGenerated) + return; + if (existing.Time == newPoint.Time) beatmap.ControlPointInfo.DifficultyPoints.Remove(existing); From bace8296297851ed337ab71afeec50f7350a0169 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 May 2019 18:42:26 +0900 Subject: [PATCH 0714/5608] Add ability to avoid expand animation in ModDisplay --- osu.Game/Screens/Play/HUD/ModDisplay.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index 878d2b7c38..eeed74ae94 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -24,6 +24,8 @@ namespace osu.Game.Screens.Play.HUD public bool DisplayUnrankedText = true; + public bool AllowExpand = true; + private readonly Bindable> current = new Bindable>(); public Bindable> Current @@ -87,7 +89,9 @@ namespace osu.Game.Screens.Play.HUD protected override void LoadComplete() { base.LoadComplete(); + appearTransform(); + iconsContainer.FadeInFromZero(fade_duration, Easing.OutQuint); } private void appearTransform() @@ -97,14 +101,17 @@ namespace osu.Game.Screens.Play.HUD else unrankedText.Hide(); - iconsContainer.FinishTransforms(); - iconsContainer.FadeInFromZero(fade_duration, Easing.OutQuint); expand(); + using (iconsContainer.BeginDelayedSequence(1200)) contract(); } - private void expand() => iconsContainer.TransformSpacingTo(new Vector2(5, 0), 500, Easing.OutQuint); + private void expand() + { + if (AllowExpand) + iconsContainer.TransformSpacingTo(new Vector2(5, 0), 500, Easing.OutQuint); + } private void contract() => iconsContainer.TransformSpacingTo(new Vector2(-25, 0), 500, Easing.OutQuint); From 9a9ac05cd915c74b909bd3ad5372fa8a354db953 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 May 2019 18:42:54 +0900 Subject: [PATCH 0715/5608] Fix post-merge issues --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index ae1343099c..d43ca33ee3 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -223,7 +223,7 @@ namespace osu.Game.Screens.Select if (Footer != null) { - Footer.AddButton(new FooterButtonMods(SelectedMods), @"mods", colours.Yellow, ModSelect, Key.F1); + Footer.AddButton(new FooterButtonMods(mods), @"mods", colours.Yellow, ModSelect, Key.F1); Footer.AddButton(new FooterButtonRandom(), @"random", colours.Green, triggerRandom, Key.F2); Footer.AddButton(new FooterButton(), @"options", colours.Blue, BeatmapOptions, Key.F3); From 8906eb874ae7a015a5932b858b6ee586a9bd8267 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 May 2019 18:43:06 +0900 Subject: [PATCH 0716/5608] Fix CI issues --- osu.Game/Screens/Select/Footer.cs | 1 + osu.Game/Screens/Select/FooterButtonMods.cs | 7 ++++--- osu.Game/Screens/Select/FooterButtonRandom.cs | 1 - 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index c991e5c350..4466fb418c 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -56,6 +56,7 @@ namespace osu.Game.Screens.Select private readonly List overlays = new List(); + /// THe button to be added. /// Text on the button. /// Colour of the button. /// Hotkey of the button. diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 0a5b8c0929..639804b3bd 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.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.Bindables; @@ -13,7 +13,7 @@ namespace osu.Game.Screens.Select { public class FooterButtonMods : FooterButton { - public FooterButtonMods(Bindable> mods) + public FooterButtonMods(Bindable> mods) { FooterModDisplay modDisplay; @@ -21,7 +21,8 @@ namespace osu.Game.Screens.Select { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Child = modDisplay = new FooterModDisplay { + Child = modDisplay = new FooterModDisplay + { DisplayUnrankedText = false, Scale = new Vector2(0.8f) }, diff --git a/osu.Game/Screens/Select/FooterButtonRandom.cs b/osu.Game/Screens/Select/FooterButtonRandom.cs index 61e95de7fa..a725bfc103 100644 --- a/osu.Game/Screens/Select/FooterButtonRandom.cs +++ b/osu.Game/Screens/Select/FooterButtonRandom.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics.Sprites; -using System; namespace osu.Game.Screens.Select { From b33372ca629e46f4d399c9d35fe360bb9090843c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 May 2019 18:43:15 +0900 Subject: [PATCH 0717/5608] Don't expand mods in button on hover --- osu.Game/Screens/Select/FooterButtonMods.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 639804b3bd..3de668bbf0 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.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.Bindables; @@ -37,6 +37,11 @@ namespace osu.Game.Screens.Select private class FooterModDisplay : ModDisplay { public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Parent?.Parent?.ReceivePositionalInputAt(screenSpacePos) ?? false; + + public FooterModDisplay() + { + AllowExpand = false; + } } } } From 772eb460fbd477fac46d5948bc133e0bc947b433 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 May 2019 19:03:26 +0900 Subject: [PATCH 0718/5608] Move button definitions to their respective classes --- osu.Game/Screens/Select/Footer.cs | 57 +++++++------------ osu.Game/Screens/Select/FooterButtonMods.cs | 11 ++++ osu.Game/Screens/Select/FooterButtonRandom.cs | 11 ++++ osu.Game/Screens/Select/SongSelect.cs | 6 +- 4 files changed, 46 insertions(+), 39 deletions(-) diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index 4466fb418c..b5afc7b0ff 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -30,54 +30,39 @@ namespace osu.Game.Screens.Select private readonly FillFlowContainer buttons; - /// Button to be added. - /// Text on the button. - /// Colour of the button. + private readonly List overlays = new List(); + + /// THe button to be added. + /// The to be toggled by this button. /// Hotkey of the button. - /// Action the button does. - /// - /// Higher depth to be put on the left, and lower to be put on the right. - /// Notice this is different to ! - /// - public void AddButton(FooterButton button, string text, Color4 colour, Action action, Key? hotkey = null, float depth = 0) + public void AddButton(FooterButton button, OverlayContainer overlay, Key? hotkey = null) + { + overlays.Add(overlay); + AddButton(button, () => showOverlay(overlay), hotkey); + } + + /// Button to be added. + /// Action the button does. + /// Hotkey of the button. + public void AddButton(FooterButton button, Action action, Key? hotkey = null) { - button.Text = text; - button.Depth = depth; - button.SelectedColour = colour; - button.DeselectedColour = colour.Opacity(0.5f); button.Hotkey = hotkey; button.Hovered = updateModeLight; button.HoverLost = updateModeLight; button.Action = action; buttons.Add(button); - buttons.SetLayoutPosition(button, -depth); } - private readonly List overlays = new List(); - - /// THe button to be added. - /// Text on the button. - /// Colour of the button. - /// Hotkey of the button. - /// The to be toggled by this button. - /// - /// Higher depth to be put on the left, and lower to be put on the right. - /// Notice this is different to ! - /// - public void AddButton(FooterButton button, string text, Color4 colour, OverlayContainer overlay, Key? hotkey = null, float depth = 0) + private void showOverlay(OverlayContainer overlay) { - overlays.Add(overlay); - AddButton(button, text, colour, () => + foreach (var o in overlays) { - foreach (var o in overlays) - { - if (o == overlay) - o.ToggleVisibility(); - else - o.Hide(); - } - }, hotkey, depth); + if (o == overlay) + o.ToggleVisibility(); + else + o.Hide(); + } } private void updateModeLight() => modeLight.FadeColour(buttons.FirstOrDefault(b => b.IsHovered)?.SelectedColour ?? Color4.Transparent, TRANSITION_LENGTH, Easing.OutQuint); diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 3de668bbf0..4343ee6cdb 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -7,6 +7,9 @@ using osu.Framework.Graphics.Containers; using osu.Game.Screens.Play.HUD; using osu.Game.Rulesets.Mods; using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Game.Graphics; using osuTK; namespace osu.Game.Screens.Select @@ -34,6 +37,14 @@ namespace osu.Game.Screens.Select modDisplay.Current = mods; } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + SelectedColour = colours.Yellow; + DeselectedColour = SelectedColour.Opacity(0.5f); + Text = @"mods"; + } + private class FooterModDisplay : ModDisplay { public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Parent?.Parent?.ReceivePositionalInputAt(screenSpacePos) ?? false; diff --git a/osu.Game/Screens/Select/FooterButtonRandom.cs b/osu.Game/Screens/Select/FooterButtonRandom.cs index a725bfc103..06f2e1ee43 100644 --- a/osu.Game/Screens/Select/FooterButtonRandom.cs +++ b/osu.Game/Screens/Select/FooterButtonRandom.cs @@ -1,9 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Select @@ -24,6 +27,14 @@ namespace osu.Game.Screens.Select }); } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + SelectedColour = colours.Green; + DeselectedColour = SelectedColour.Opacity(0.5f); + Text = @"random"; + } + protected override bool OnKeyDown(KeyDownEvent e) { secondaryActive = e.ShiftPressed; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index d43ca33ee3..c747fdee60 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -223,9 +223,9 @@ namespace osu.Game.Screens.Select if (Footer != null) { - Footer.AddButton(new FooterButtonMods(mods), @"mods", colours.Yellow, ModSelect, Key.F1); - Footer.AddButton(new FooterButtonRandom(), @"random", colours.Green, triggerRandom, Key.F2); - Footer.AddButton(new FooterButton(), @"options", colours.Blue, BeatmapOptions, Key.F3); + Footer.AddButton(new FooterButtonMods(mods), ModSelect, Key.F1); + Footer.AddButton(new FooterButtonRandom(), triggerRandom, Key.F2); + Footer.AddButton(new FooterButtonOptions(), BeatmapOptions, Key.F3); BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo), Key.Number4, float.MaxValue); BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, colours.Purple, null, Key.Number1); From 39efa2d173de774cf130dded0bf4f5febdbb4666 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 8 May 2019 19:05:00 +0900 Subject: [PATCH 0719/5608] Fix possible cross-thread config cache access --- osu.Game/Rulesets/RulesetConfigCache.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index 4ac866fc90..9a5a4d4acd 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; +using System.Collections.Concurrent; using osu.Framework.Graphics; using osu.Game.Configuration; using osu.Game.Rulesets.Configuration; @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets /// public class RulesetConfigCache : Component { - private readonly Dictionary configCache = new Dictionary(); + private readonly ConcurrentDictionary configCache = new ConcurrentDictionary(); private readonly SettingsStore settingsStore; public RulesetConfigCache(SettingsStore settingsStore) @@ -34,10 +34,7 @@ namespace osu.Game.Rulesets if (ruleset.RulesetInfo.ID == null) throw new InvalidOperationException("The provided ruleset doesn't have a valid id."); - if (configCache.TryGetValue(ruleset.RulesetInfo.ID.Value, out var existing)) - return existing; - - return configCache[ruleset.RulesetInfo.ID.Value] = ruleset.CreateConfig(settingsStore); + return configCache.GetOrAdd(ruleset.RulesetInfo.ID.Value, _ => ruleset.CreateConfig(settingsStore)); } } } From c91b9c60322f2c580c2378e4ad5afbf9c539f967 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 May 2019 19:27:53 +0900 Subject: [PATCH 0720/5608] Add missing button --- osu.Game/Screens/Select/FooterButtonOptions.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 osu.Game/Screens/Select/FooterButtonOptions.cs diff --git a/osu.Game/Screens/Select/FooterButtonOptions.cs b/osu.Game/Screens/Select/FooterButtonOptions.cs new file mode 100644 index 0000000000..1fbe03216d --- /dev/null +++ b/osu.Game/Screens/Select/FooterButtonOptions.cs @@ -0,0 +1,17 @@ +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Game.Graphics; + +namespace osu.Game.Screens.Select +{ + public class FooterButtonOptions : FooterButton + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + SelectedColour = colours.Blue; + DeselectedColour = SelectedColour.Opacity(0.5f); + Text = @"options"; + } + } +} \ No newline at end of file From 6dea16f36543f640901652e2f2e69020d14c321e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 May 2019 19:29:43 +0900 Subject: [PATCH 0721/5608] Move action and hotkey specification local --- osu.Game/Screens/Select/Footer.cs | 14 +++++--------- osu.Game/Screens/Select/FooterButtonMods.cs | 2 ++ osu.Game/Screens/Select/FooterButtonOptions.cs | 4 +++- osu.Game/Screens/Select/FooterButtonRandom.cs | 2 ++ osu.Game/Screens/Select/SongSelect.cs | 6 +++--- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index b5afc7b0ff..6ba29751b0 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using osuTK; using osuTK.Graphics; -using osuTK.Input; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -34,22 +33,19 @@ namespace osu.Game.Screens.Select /// THe button to be added. /// The to be toggled by this button. - /// Hotkey of the button. - public void AddButton(FooterButton button, OverlayContainer overlay, Key? hotkey = null) + public void AddButton(FooterButton button, OverlayContainer overlay) { overlays.Add(overlay); - AddButton(button, () => showOverlay(overlay), hotkey); + button.Action = () => showOverlay(overlay); + + AddButton(button); } /// Button to be added. - /// Action the button does. - /// Hotkey of the button. - public void AddButton(FooterButton button, Action action, Key? hotkey = null) + public void AddButton(FooterButton button) { - button.Hotkey = hotkey; button.Hovered = updateModeLight; button.HoverLost = updateModeLight; - button.Action = action; buttons.Add(button); } diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 4343ee6cdb..c96c5022c0 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -11,6 +11,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics; using osuTK; +using osuTK.Input; namespace osu.Game.Screens.Select { @@ -43,6 +44,7 @@ namespace osu.Game.Screens.Select SelectedColour = colours.Yellow; DeselectedColour = SelectedColour.Opacity(0.5f); Text = @"mods"; + Hotkey = Key.F1; } private class FooterModDisplay : ModDisplay diff --git a/osu.Game/Screens/Select/FooterButtonOptions.cs b/osu.Game/Screens/Select/FooterButtonOptions.cs index 1fbe03216d..0e4a32299d 100644 --- a/osu.Game/Screens/Select/FooterButtonOptions.cs +++ b/osu.Game/Screens/Select/FooterButtonOptions.cs @@ -1,6 +1,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics; +using osuTK.Input; namespace osu.Game.Screens.Select { @@ -12,6 +13,7 @@ namespace osu.Game.Screens.Select SelectedColour = colours.Blue; DeselectedColour = SelectedColour.Opacity(0.5f); Text = @"options"; + Hotkey = Key.F3; } } -} \ No newline at end of file +} diff --git a/osu.Game/Screens/Select/FooterButtonRandom.cs b/osu.Game/Screens/Select/FooterButtonRandom.cs index 06f2e1ee43..14c9eb2035 100644 --- a/osu.Game/Screens/Select/FooterButtonRandom.cs +++ b/osu.Game/Screens/Select/FooterButtonRandom.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osuTK.Input; namespace osu.Game.Screens.Select { @@ -33,6 +34,7 @@ namespace osu.Game.Screens.Select SelectedColour = colours.Green; DeselectedColour = SelectedColour.Opacity(0.5f); Text = @"random"; + Hotkey = Key.F2; } protected override bool OnKeyDown(KeyDownEvent e) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index c747fdee60..d5301116a9 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -223,9 +223,9 @@ namespace osu.Game.Screens.Select if (Footer != null) { - Footer.AddButton(new FooterButtonMods(mods), ModSelect, Key.F1); - Footer.AddButton(new FooterButtonRandom(), triggerRandom, Key.F2); - Footer.AddButton(new FooterButtonOptions(), BeatmapOptions, Key.F3); + Footer.AddButton(new FooterButtonMods(mods), ModSelect); + Footer.AddButton(new FooterButtonRandom { Action = triggerRandom }); + Footer.AddButton(new FooterButtonOptions(), BeatmapOptions); BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo), Key.Number4, float.MaxValue); BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, colours.Purple, null, Key.Number1); From 4f697e2bd58c4e238c03918c0a2c4eedb9152174 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 May 2019 19:35:20 +0900 Subject: [PATCH 0722/5608] Add licence header --- osu.Game/Screens/Select/FooterButtonOptions.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Select/FooterButtonOptions.cs b/osu.Game/Screens/Select/FooterButtonOptions.cs index 0e4a32299d..c000d8a8c8 100644 --- a/osu.Game/Screens/Select/FooterButtonOptions.cs +++ b/osu.Game/Screens/Select/FooterButtonOptions.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics; From 83663467ce4ea861622b9a7ad86be18904f03783 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 May 2019 21:08:46 +0900 Subject: [PATCH 0723/5608] Update dependencies --- osu.Desktop/osu.Desktop.csproj | 6 +++--- osu.Game/osu.Game.csproj | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 66db439c82..aa8848c55f 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -26,9 +26,9 @@ - - - + + + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b6b4896658..8f733a5c55 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -11,11 +11,11 @@ - - - - - + + + + + From 17a9f191cd70dde920ee52ba58ada1e81d38127d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 8 May 2019 23:08:08 +0900 Subject: [PATCH 0724/5608] Fix incorrect texture name usage for some rank icons --- .../Profile/Header/DetailHeaderContainer.cs | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index de710c5fcd..f9ee67002a 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -4,14 +4,12 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Online.Leaderboards; using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Scoring; using osu.Game.Users; @@ -185,8 +183,6 @@ namespace osu.Game.Overlays.Profile.Header private class ScoreRankInfo : CompositeDrawable { - private readonly ScoreRank rank; - private readonly Sprite rankSprite; private readonly OsuSpriteText rankCount; public int RankCount @@ -196,8 +192,6 @@ namespace osu.Game.Overlays.Profile.Header public ScoreRankInfo(ScoreRank rank) { - this.rank = rank; - AutoSizeAxes = Axes.Both; InternalChild = new FillFlowContainer { @@ -206,9 +200,10 @@ namespace osu.Game.Overlays.Profile.Header Direction = FillDirection.Vertical, Children = new Drawable[] { - rankSprite = new Sprite + new DrawableRank(rank) { - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + Height = 30, FillMode = FillMode.Fit }, rankCount = new OsuSpriteText @@ -220,12 +215,6 @@ namespace osu.Game.Overlays.Profile.Header } }; } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - rankSprite.Texture = textures.Get($"Grades/{rank.GetDescription()}"); - } } } } From 5128dc32e440d7c3925d1440ef5961d0782c00a4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 8 May 2019 23:13:09 +0900 Subject: [PATCH 0725/5608] Remove unnecessary fillmode --- osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index f9ee67002a..e41c90be45 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -204,7 +204,6 @@ namespace osu.Game.Overlays.Profile.Header { RelativeSizeAxes = Axes.X, Height = 30, - FillMode = FillMode.Fit }, rankCount = new OsuSpriteText { From 9b279f324f35c367edf0ad12cb1b22dfe0fef797 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 8 May 2019 23:38:57 +0900 Subject: [PATCH 0726/5608] Adjust testcase to avoid random failures --- .../TestCaseUpdateableBeatmapBackgroundSprite.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs index a4dd7b83e2..e9c5bc929d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs @@ -107,7 +107,7 @@ namespace osu.Game.Tests.Visual.UserInterface AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, Spacing = new Vector2(10), - Padding = new MarginPadding { Bottom = 250 } + Padding = new MarginPadding { Bottom = 550 } } }; @@ -136,7 +136,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("some loaded", () => (initialLoadCount = loadedBackgrounds.Count()) > 0); AddStep("scroll to bottom", () => scrollContainer.ScrollToEnd()); - AddUntilStep("some unloaded", () => loadedBackgrounds.Count() < initialLoadCount); + AddUntilStep("all unloaded", () => !loadedBackgrounds.Any()); } private class TestUpdateableBeatmapBackgroundSprite : UpdateableBeatmapBackgroundSprite From 9c01f6793ecb7341d8c3fe42ac20f0ab140e6822 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 8 May 2019 23:52:44 +0900 Subject: [PATCH 0727/5608] Remove unused variable --- .../UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs index e9c5bc929d..f57464e7c3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs @@ -132,8 +132,6 @@ namespace osu.Game.Tests.Visual.UserInterface var loadedBackgrounds = backgrounds.Where(b => b.ContentLoaded); - int initialLoadCount = 0; - AddUntilStep("some loaded", () => (initialLoadCount = loadedBackgrounds.Count()) > 0); AddStep("scroll to bottom", () => scrollContainer.ScrollToEnd()); AddUntilStep("all unloaded", () => !loadedBackgrounds.Any()); From 5dbf57046e894a965ebe86725e634cb4b12ee191 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 May 2019 10:38:22 +0900 Subject: [PATCH 0728/5608] Fix regression from removing unused variable --- .../UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs index f57464e7c3..6185fbd34e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs @@ -132,7 +132,7 @@ namespace osu.Game.Tests.Visual.UserInterface var loadedBackgrounds = backgrounds.Where(b => b.ContentLoaded); - AddUntilStep("some loaded", () => (initialLoadCount = loadedBackgrounds.Count()) > 0); + AddUntilStep("some loaded", () => loadedBackgrounds.Any()); AddStep("scroll to bottom", () => scrollContainer.ScrollToEnd()); AddUntilStep("all unloaded", () => !loadedBackgrounds.Any()); } From 9457a6128eb2a31c4863e52a80a4337b9317020c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 May 2019 10:57:55 +0900 Subject: [PATCH 0729/5608] Fix game pausing when made inactive while watching a replay --- osu.Game/Screens/Play/HUDOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 3c1b33297a..f8e092c8b1 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -129,6 +129,7 @@ namespace osu.Game.Screens.Play private void replayLoadedValueChanged(ValueChangedEvent e) { PlayerSettingsOverlay.ReplayLoaded = e.NewValue; + HoldToQuit.PauseOnFocusLost = !e.NewValue; if (e.NewValue) { From 5b1ae1210ad01387a7ddf7996e17bfad1a455d95 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 May 2019 11:31:40 +0900 Subject: [PATCH 0730/5608] Add more asserts to pause test in an attempt to track down intermittent test failures --- osu.Game.Tests/Visual/Gameplay/TestCasePause.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs index b9c7fd14bd..14be10b65c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs @@ -157,6 +157,8 @@ namespace osu.Game.Tests.Visual.Gameplay private void confirmPaused() { confirmClockRunning(false); + AddAssert("player not exited", () => Player.IsCurrentScreen()); + AddAssert("player not failed", () => !Player.HasFailed); AddAssert("pause overlay shown", () => Player.PauseOverlayVisible); } From d625f3c104df120ffeed7ed8f9a1203fb2504e90 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 9 May 2019 13:16:56 +0900 Subject: [PATCH 0731/5608] Private method --- .../Compose/Components/Timeline/ZoomableScrollContainer.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index ee6e29c92e..eb78e827f0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -92,6 +92,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } + private void updateZoomedContentWidth() => zoomedContent.Width = DrawWidth * currentZoom; + protected override bool OnScroll(ScrollEvent e) { if (e.IsPrecise) @@ -107,7 +109,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline base.LoadComplete(); // This width only gets updated on the application of a transform, so this needs to be initialized here. - zoomedContent.Width = DrawWidth * currentZoom; + updateZoomedContentWidth(); } private float zoomTarget = 1; @@ -171,7 +173,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline d.currentZoom = newZoom; - d.zoomedContent.Width = d.DrawWidth * d.currentZoom; + d.updateZoomedContentWidth(); // Temporarily here to make sure ScrollTo gets the correct DrawSize for scrollable area. // TODO: Make sure draw size gets invalidated properly on the framework side, and remove this once it is. d.Invalidate(Invalidation.DrawSize); From c69d813745ae55b66548d82e291215a1024ebe9f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 9 May 2019 13:32:18 +0900 Subject: [PATCH 0732/5608] Fix bindable potentially being set from background thread --- osu.Game/Online/API/APIAccess.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index d62b53088a..70cd21b2db 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -352,10 +352,12 @@ namespace osu.Game.Online.API public void Logout() { flushQueue(); + password = null; authentication.Clear(); - LocalUser.Value = createGuestUser(); State = APIState.Offline; + + Schedule(() => LocalUser.Value = createGuestUser()); } private static User createGuestUser() => new GuestUser(); From 3fed165b749221af2c019885168030b1b4654f13 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 9 May 2019 13:33:18 +0900 Subject: [PATCH 0733/5608] Cleanup some schedules --- osu.Game/Online/API/APIAccess.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 70cd21b2db..08bb9472c1 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -77,13 +77,13 @@ namespace osu.Game.Online.API /// public void Register(IOnlineComponent component) { - Scheduler.Add(delegate { components.Add(component); }); + Schedule(() => components.Add(component)); component.APIStateChanged(this, state); } public void Unregister(IOnlineComponent component) { - Scheduler.Add(delegate { components.Remove(component); }); + Schedule(() => components.Remove(component)); } public string AccessToken => authentication.RequestAccessToken(); @@ -274,7 +274,7 @@ namespace osu.Game.Online.API state = value; log.Add($@"We just went {state}!"); - Scheduler.Add(delegate + Schedule(() => { components.ForEach(c => c.APIStateChanged(this, state)); OnStateChange?.Invoke(oldState, state); From 35624a5d1cd5969cf12770bda40dab3a5343c9c7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 9 May 2019 13:42:04 +0900 Subject: [PATCH 0734/5608] Invert scheduling order --- osu.Game/Online/API/APIAccess.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 08bb9472c1..594bc1e3ca 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -355,9 +355,11 @@ namespace osu.Game.Online.API password = null; authentication.Clear(); - State = APIState.Offline; + // Scheduled prior to state change such that the state changed event is invoked with the correct user present Schedule(() => LocalUser.Value = createGuestUser()); + + State = APIState.Offline; } private static User createGuestUser() => new GuestUser(); From 5c6b4d923f04d63eaaf7a7c0978ba0bbf95cf977 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 9 May 2019 13:53:53 +0900 Subject: [PATCH 0735/5608] Reorder methods --- .../Timeline/ZoomableScrollContainer.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index eb78e827f0..829437d599 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -92,7 +92,13 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } - private void updateZoomedContentWidth() => zoomedContent.Width = DrawWidth * currentZoom; + protected override void LoadComplete() + { + base.LoadComplete(); + + // This width only gets updated on the application of a transform, so this needs to be initialized here. + updateZoomedContentWidth(); + } protected override bool OnScroll(ScrollEvent e) { @@ -104,13 +110,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline return true; } - protected override void LoadComplete() - { - base.LoadComplete(); - - // This width only gets updated on the application of a transform, so this needs to be initialized here. - updateZoomedContentWidth(); - } + private void updateZoomedContentWidth() => zoomedContent.Width = DrawWidth * currentZoom; private float zoomTarget = 1; From c8f9354327eb25020241c07f456fbfab204d8884 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 May 2019 15:13:35 +0900 Subject: [PATCH 0736/5608] Remove incorrect deletion include This was causing deletions of scores without considering that scores are now managed by a ScoreManager (and have their own data dependencies). --- osu.Game/Beatmaps/BeatmapStore.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapStore.cs b/osu.Game/Beatmaps/BeatmapStore.cs index f4b7b1d74f..a2279fdb14 100644 --- a/osu.Game/Beatmaps/BeatmapStore.cs +++ b/osu.Game/Beatmaps/BeatmapStore.cs @@ -65,7 +65,6 @@ namespace osu.Game.Beatmaps protected override IQueryable AddIncludesForDeletion(IQueryable query) => base.AddIncludesForDeletion(query) .Include(s => s.Metadata) - .Include(s => s.Beatmaps).ThenInclude(b => b.Scores) .Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty) .Include(s => s.Beatmaps).ThenInclude(b => b.Metadata); From 6ebd13c73389660b9a05cc053403021ec1fd03ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 May 2019 15:15:02 +0900 Subject: [PATCH 0737/5608] Allow Delete and Undelete operations to run silently when needed --- osu.Game/Database/ArchiveModelManager.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index ba348c4090..54dbae9ddc 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -385,7 +385,7 @@ namespace osu.Game.Database /// Delete multiple items. /// This will post notifications tracking progress. /// - public void Delete(List items) + public void Delete(List items, bool silent = false) { if (items.Count == 0) return; @@ -396,7 +396,8 @@ namespace osu.Game.Database State = ProgressNotificationState.Active, }; - PostNotification?.Invoke(notification); + if (!silent) + PostNotification?.Invoke(notification); int i = 0; @@ -423,7 +424,7 @@ namespace osu.Game.Database /// Restore multiple items that were previously deleted. /// This will post notifications tracking progress. /// - public void Undelete(List items) + public void Undelete(List items, bool silent = false) { if (!items.Any()) return; @@ -434,7 +435,8 @@ namespace osu.Game.Database State = ProgressNotificationState.Active, }; - PostNotification?.Invoke(notification); + if (!silent) + PostNotification?.Invoke(notification); int i = 0; From 24e64c13335cc5f8ac0fcf6282a7ddd297651a86 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 May 2019 15:15:28 +0900 Subject: [PATCH 0738/5608] Add proper co-dependent beatmap/score deletion via events --- osu.Game/OsuGameBase.cs | 17 ++++++++++++++++- osu.Game/Scoring/ScoreManager.cs | 8 ++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 44776bb2a8..66552c43e0 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -155,8 +155,23 @@ namespace osu.Game dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); + + // ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup() + dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Host.Storage, contextFactory, Host)); dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap)); - dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, BeatmapManager, Host.Storage, contextFactory, Host)); + + // this should likely be moved to ArchiveModelManager when another case appers where it is necessary + // to have inter-dependent model managers. this could be obtained with an IHasForeign interface to + // allow lookups to be done on the child (ScoreManager in this case) to perform the cascading delete. + List getBeatmapScores(BeatmapSetInfo set) + { + var beatmapIds = BeatmapManager.QueryBeatmaps(b => b.BeatmapSetInfoID == set.ID).Select(b => b.ID).ToList(); + return ScoreManager.QueryScores(s => beatmapIds.Contains(s.Beatmap.ID)).ToList(); + } + + BeatmapManager.ItemRemoved += i => ScoreManager.Delete(getBeatmapScores(i), true); + BeatmapManager.ItemAdded += (i, existing) => ScoreManager.Undelete(getBeatmapScores(i), true); + dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); dependencies.Cache(RulesetConfigCache = new RulesetConfigCache(SettingsStore)); diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 7a527bfc69..6b737dc734 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -25,9 +25,9 @@ namespace osu.Game.Scoring protected override string ImportFromStablePath => "Replays"; private readonly RulesetStore rulesets; - private readonly BeatmapManager beatmaps; + private readonly Func beatmaps; - public ScoreManager(RulesetStore rulesets, BeatmapManager beatmaps, Storage storage, IDatabaseContextFactory contextFactory, IIpcHost importHost = null) + public ScoreManager(RulesetStore rulesets, Func beatmaps, Storage storage, IDatabaseContextFactory contextFactory, IIpcHost importHost = null) : base(storage, contextFactory, new ScoreStore(contextFactory, storage), importHost) { this.rulesets = rulesets; @@ -43,7 +43,7 @@ namespace osu.Game.Scoring { try { - return new DatabasedLegacyScoreParser(rulesets, beatmaps).Parse(stream).ScoreInfo; + return new DatabasedLegacyScoreParser(rulesets, beatmaps()).Parse(stream).ScoreInfo; } catch (LegacyScoreParser.BeatmapNotFoundException e) { @@ -53,7 +53,7 @@ namespace osu.Game.Scoring } } - public Score GetScore(ScoreInfo score) => new LegacyDatabasedScore(score, rulesets, beatmaps, Files.Store); + public Score GetScore(ScoreInfo score) => new LegacyDatabasedScore(score, rulesets, beatmaps(), Files.Store); public List GetAllUsableScores() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); From 39fb5712f1a331720014ee5f8a62ca2261ba4741 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 9 May 2019 15:31:37 +0900 Subject: [PATCH 0739/5608] Only combo-incrementing results add to result count --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 0ca92a8861..6beb393367 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -314,11 +314,11 @@ namespace osu.Game.Rulesets.Scoring JudgedHits++; - if (result.Type != HitResult.None) - scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) + 1; - if (result.Judgement.AffectsCombo) { + if (result.Type != HitResult.None) + scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) + 1; + switch (result.Type) { case HitResult.None: From b0e34d86d5016cb069a388dfe187decd0502a890 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 9 May 2019 16:16:20 +0900 Subject: [PATCH 0740/5608] Subtract a result from count if its been reverted --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 6beb393367..2944b784ad 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -360,6 +360,12 @@ namespace osu.Game.Rulesets.Scoring JudgedHits--; + if (result.Judgement.AffectsCombo) + { + if (result.Type != HitResult.None) + scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) - 1; + } + if (result.Judgement.IsBonus) { if (result.IsHit) From 66594b7a1b39ce1ec12049e2458a466030ffb5bc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 May 2019 16:36:47 +0900 Subject: [PATCH 0741/5608] Pass GameplayStartTime to FrameStabilityContainer to allow bypassing prior to start --- .../TestCaseFrameStabilityContainer.cs | 20 +++++++++++++++++++ osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 +- .../Rulesets/UI/FrameStabilityContainer.cs | 8 +++++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs index 5cd01fe9a8..584fbe5729 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs @@ -73,6 +73,26 @@ namespace osu.Game.Tests.Visual.Gameplay checkFrameCount(2); } + [Test] + public void TestInitialSeekWithGameplayStart() + { + seekManualTo(1000); + createStabilityContainer(30000); + + confirmSeek(1000); + checkFrameCount(0); + + seekManualTo(10000); + confirmSeek(10000); + + checkFrameCount(1); + + seekManualTo(130000); + confirmSeek(130000); + + checkFrameCount(6002); + } + [Test] public void TestInitialSeek() { diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 77d1e60b87..75526ae50a 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -144,7 +144,7 @@ namespace osu.Game.Rulesets.UI { InternalChildren = new Drawable[] { - frameStabilityContainer = new FrameStabilityContainer + frameStabilityContainer = new FrameStabilityContainer(GameplayStartTime) { Child = KeyBindingInputManager .WithChild(CreatePlayfieldAdjustmentContainer() diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index ad15bcf057..16a5ca4387 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -17,10 +17,14 @@ namespace osu.Game.Rulesets.UI ///

public readonly BindableBool IsPaused = new BindableBool(); + /// + /// The frame-stable clock which is being used for playfield display. + /// + public abstract GameplayClock FrameStableClock { get; } + /// ~ /// The associated ruleset. /// diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index ad15bcf057..733a495248 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -20,7 +20,8 @@ namespace osu.Game.Rulesets.UI public FrameStabilityContainer() { RelativeSizeAxes = Axes.Both; - gameplayClock = new GameplayClock(framedClock = new FramedClock(manualClock = new ManualClock())); + + GameplayClock = new GameplayClock(framedClock = new FramedClock(manualClock = new ManualClock())); } private readonly ManualClock manualClock; @@ -28,7 +29,7 @@ namespace osu.Game.Rulesets.UI private readonly FramedClock framedClock; [Cached] - private GameplayClock gameplayClock; + public GameplayClock GameplayClock { get; } private IFrameBasedClock parentGameplayClock; @@ -38,7 +39,7 @@ namespace osu.Game.Rulesets.UI if (clock != null) { parentGameplayClock = clock; - gameplayClock.IsPaused.BindTo(clock.IsPaused); + GameplayClock.IsPaused.BindTo(clock.IsPaused); } } @@ -73,7 +74,7 @@ namespace osu.Game.Rulesets.UI public override bool UpdateSubTree() { requireMoreUpdateLoops = true; - validState = !gameplayClock.IsPaused.Value; + validState = !GameplayClock.IsPaused.Value; int loops = 0; @@ -160,7 +161,7 @@ namespace osu.Game.Rulesets.UI if (parentGameplayClock == null) parentGameplayClock = Clock; - Clock = gameplayClock; + Clock = GameplayClock; ProcessCustomClock = false; } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index f8e092c8b1..ee229ab93e 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -35,6 +35,10 @@ namespace osu.Game.Screens.Play public readonly HoldForMenuButton HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; + private readonly ScoreProcessor scoreProcessor; + private readonly DrawableRuleset drawableRuleset; + private readonly IReadOnlyList mods; + private Bindable showHud; private readonly Container visibilityContainer; private readonly BindableBool replayLoaded = new BindableBool(); @@ -45,6 +49,10 @@ namespace osu.Game.Screens.Play public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, IReadOnlyList mods) { + this.scoreProcessor = scoreProcessor; + this.drawableRuleset = drawableRuleset; + this.mods = mods; + RelativeSizeAxes = Axes.Both; Children = new Drawable[] @@ -89,20 +97,21 @@ namespace osu.Game.Screens.Play } } }; + } + [BackgroundDependencyLoader(true)] + private void load(OsuConfigManager config, NotificationOverlay notificationOverlay) + { BindProcessor(scoreProcessor); BindDrawableRuleset(drawableRuleset); Progress.Objects = drawableRuleset.Objects; Progress.AllowSeeking = drawableRuleset.HasReplayLoaded.Value; Progress.RequestSeek = time => RequestSeek(time); + Progress.ReferenceClock = drawableRuleset.FrameStableClock; ModDisplay.Current.Value = mods; - } - [BackgroundDependencyLoader(true)] - private void load(OsuConfigManager config, NotificationOverlay notificationOverlay) - { showHud = config.GetBindable(OsuSetting.ShowInterface); showHud.ValueChanged += visible => visibilityContainer.FadeTo(visible.NewValue ? 1 : 0, duration); showHud.TriggerChange(); diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 94b25e04a3..d478454f00 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -10,6 +10,7 @@ using osu.Game.Graphics; using osu.Framework.Allocation; using System.Linq; using osu.Framework.Bindables; +using osu.Framework.Timing; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; @@ -55,7 +56,9 @@ namespace osu.Game.Screens.Play private readonly BindableBool replayLoaded = new BindableBool(); - private GameplayClock gameplayClock; + public IClock ReferenceClock; + + private IClock gameplayClock; [BackgroundDependencyLoader(true)] private void load(OsuColour colours, GameplayClock clock) @@ -154,10 +157,12 @@ namespace osu.Game.Screens.Play if (objects == null) return; - double position = gameplayClock?.CurrentTime ?? Time.Current; - double progress = Math.Min(1, (position - firstHitTime) / (lastHitTime - firstHitTime)); + double gameplayTime = gameplayClock?.CurrentTime ?? Time.Current; + double frameStableTime = ReferenceClock?.CurrentTime ?? gameplayTime; - bar.CurrentTime = position; + double progress = Math.Min(1, (frameStableTime - firstHitTime) / (lastHitTime - firstHitTime)); + + bar.CurrentTime = gameplayTime; graph.Progress = (int)(graph.ColumnCount * progress); } } From 9e0af723cca8acca9bb4fad33e60da8ed5cadae8 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 9 May 2019 18:56:19 +0900 Subject: [PATCH 0745/5608] Split out affectscombo change --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 2944b784ad..4adc29853d 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -314,11 +314,11 @@ namespace osu.Game.Rulesets.Scoring JudgedHits++; + if (result.Type != HitResult.None) + scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) + 1; + if (result.Judgement.AffectsCombo) { - if (result.Type != HitResult.None) - scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) + 1; - switch (result.Type) { case HitResult.None: From 5c096cbc910172aab8948576912acab0da033593 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 9 May 2019 18:59:00 +0900 Subject: [PATCH 0746/5608] Revert mirroring condition too --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 4adc29853d..cf42a70640 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -360,11 +360,8 @@ namespace osu.Game.Rulesets.Scoring JudgedHits--; - if (result.Judgement.AffectsCombo) - { - if (result.Type != HitResult.None) - scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) - 1; - } + if (result.Type != HitResult.None) + scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) - 1; if (result.Judgement.IsBonus) { From 7c105fd99fea6b415156faf88721872ea16a3fcd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 10 May 2019 15:39:25 +0900 Subject: [PATCH 0747/5608] Fix testcase players pausing on window unfocus --- .../TestCaseSliderInput.cs | 2 ++ .../TestCaseBackgroundScreenBeatmap.cs | 2 +- .../Visual/Gameplay/TestCaseAutoplay.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestCasePause.cs | 8 +------- .../Visual/Gameplay/TestCasePlayerLoader.cs | 16 ++-------------- .../Visual/Gameplay/TestCaseReplay.cs | 2 ++ osu.Game/Screens/Play/HUDOverlay.cs | 4 +--- osu.Game/Screens/Play/Player.cs | 7 +++++++ osu.Game/Tests/Visual/AllPlayersTestCase.cs | 2 +- osu.Game/Tests/Visual/PlayerTestCase.cs | 2 +- osu.Game/Tests/Visual/TestPlayer.cs | 17 +++++++++++++++++ 11 files changed, 36 insertions(+), 28 deletions(-) create mode 100644 osu.Game/Tests/Visual/TestPlayer.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 76bd9ef758..9a32cf42b0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -353,6 +353,8 @@ namespace osu.Game.Rulesets.Osu.Tests { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + protected override bool PauseOnFocusLost => false; + public ScoreAccessibleReplayPlayer(Score score) : base(score, false, false) { diff --git a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs index 81fab5b4b3..55e8a810fd 100644 --- a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs @@ -328,7 +328,7 @@ namespace osu.Game.Tests.Visual.Background public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR); } - private class TestPlayer : Player + private class TestPlayer : Visual.TestPlayer { protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs index 624e5f08bd..e5dc092c73 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 0)); } - private class ScoreAccessiblePlayer : Player + private class ScoreAccessiblePlayer : TestPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new HUDOverlay HUDOverlay => base.HUDOverlay; diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs index 14be10b65c..61790467e2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs @@ -186,7 +186,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Player CreatePlayer(Ruleset ruleset) => new PausePlayer(); - protected class PausePlayer : Player + protected class PausePlayer : TestPlayer { public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; @@ -197,12 +197,6 @@ namespace osu.Game.Tests.Visual.Gameplay public bool FailOverlayVisible => FailOverlay.State == Visibility.Visible; public bool PauseOverlayVisible => PauseOverlay.State == Visibility.Visible; - - protected override void LoadComplete() - { - base.LoadComplete(); - HUDOverlay.HoldToQuit.PauseOnFocusLost = false; - } } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs index 15c38e6d18..b8b8f2e4e2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs @@ -1,12 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using System.Linq; using System.Threading; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Rulesets.Mods; @@ -34,7 +32,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestLoadContinuation() { - AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => new Player(false, false)))); + AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => new TestPlayer(false, false)))); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen()); @@ -101,17 +99,7 @@ namespace osu.Game.Tests.Visual.Gameplay public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; } - private class TestPlayer : Player - { - public new Bindable> Mods => base.Mods; - - public TestPlayer() - : base(false, false) - { - } - } - - protected class SlowLoadPlayer : Player + protected class SlowLoadPlayer : TestPlayer { public bool Ready; diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs index 263070ab21..a302c978d2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs @@ -33,6 +33,8 @@ namespace osu.Game.Tests.Visual.Gameplay public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new HUDOverlay HUDOverlay => base.HUDOverlay; + protected override bool PauseOnFocusLost => false; + public ScoreAccessibleReplayPlayer(Score score) : base(score) { diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index f8e092c8b1..361123d08b 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -122,14 +122,12 @@ namespace osu.Game.Screens.Play { base.LoadComplete(); - replayLoaded.ValueChanged += replayLoadedValueChanged; - replayLoaded.TriggerChange(); + replayLoaded.BindValueChanged(replayLoadedValueChanged, true); } private void replayLoadedValueChanged(ValueChangedEvent e) { PlayerSettingsOverlay.ReplayLoaded = e.NewValue; - HoldToQuit.PauseOnFocusLost = !e.NewValue; if (e.NewValue) { diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fd9ddec314..5cc6f09383 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -40,6 +40,11 @@ namespace osu.Game.Screens.Play public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered; + /// + /// Whether gameplay should pause when the game window focus is lost. + /// + protected virtual bool PauseOnFocusLost => true; + public Action RestartRequested; public bool HasFailed { get; private set; } @@ -167,6 +172,8 @@ namespace osu.Game.Screens.Play } }; + DrawableRuleset.HasReplayLoaded.BindValueChanged(e => HUDOverlay.HoldToQuit.PauseOnFocusLost = !e.NewValue && PauseOnFocusLost, true); + // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); diff --git a/osu.Game/Tests/Visual/AllPlayersTestCase.cs b/osu.Game/Tests/Visual/AllPlayersTestCase.cs index 40aa90f2d1..dc3ef1a85b 100644 --- a/osu.Game/Tests/Visual/AllPlayersTestCase.cs +++ b/osu.Game/Tests/Visual/AllPlayersTestCase.cs @@ -76,6 +76,6 @@ namespace osu.Game.Tests.Visual return Player; } - protected virtual Player CreatePlayer(Ruleset ruleset) => new Player(false, false); + protected virtual Player CreatePlayer(Ruleset ruleset) => new TestPlayer(false, false); } } diff --git a/osu.Game/Tests/Visual/PlayerTestCase.cs b/osu.Game/Tests/Visual/PlayerTestCase.cs index c1960eefeb..67d5696020 100644 --- a/osu.Game/Tests/Visual/PlayerTestCase.cs +++ b/osu.Game/Tests/Visual/PlayerTestCase.cs @@ -56,6 +56,6 @@ namespace osu.Game.Tests.Visual LoadScreen(Player); } - protected virtual Player CreatePlayer(Ruleset ruleset) => new Player(false, false); + protected virtual Player CreatePlayer(Ruleset ruleset) => new TestPlayer(false, false); } } diff --git a/osu.Game/Tests/Visual/TestPlayer.cs b/osu.Game/Tests/Visual/TestPlayer.cs new file mode 100644 index 0000000000..b93a1466e0 --- /dev/null +++ b/osu.Game/Tests/Visual/TestPlayer.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual +{ + public class TestPlayer : Player + { + protected override bool PauseOnFocusLost => false; + + public TestPlayer(bool allowPause = true, bool showResults = true) + : base(allowPause, showResults) + { + } + } +} From 6a957ad27ff7fe280eb145ded18e38e3dcecdc1c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 10 May 2019 15:51:12 +0900 Subject: [PATCH 0748/5608] Fix pause triggered when already paused --- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 9 +++++++-- osu.Game/Screens/Play/HUDOverlay.cs | 2 ++ osu.Game/Screens/Play/Player.cs | 6 +++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 446df94aca..91c14591b1 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -25,6 +25,8 @@ namespace osu.Game.Screens.Play.HUD { public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + public readonly Bindable IsPaused = new Bindable(); + private readonly Button button; public Action Action @@ -51,7 +53,8 @@ namespace osu.Game.Screens.Play.HUD button = new Button { HoverGained = () => text.FadeIn(500, Easing.OutQuint), - HoverLost = () => text.FadeOut(500, Easing.OutQuint) + HoverLost = () => text.FadeOut(500, Easing.OutQuint), + IsPaused = { BindTarget = IsPaused } } }; AutoSizeAxes = Axes.Both; @@ -94,6 +97,8 @@ namespace osu.Game.Screens.Play.HUD private CircularProgress circularProgress; private Circle overlayCircle; + public readonly Bindable IsPaused = new Bindable(); + protected override bool AllowMultipleFires => true; public Action HoverGained; @@ -217,7 +222,7 @@ namespace osu.Game.Screens.Play.HUD private void updateActive() { - if (!pauseOnFocusLost) return; + if (!pauseOnFocusLost || IsPaused.Value) return; if (gameActive.Value) AbortConfirm(); diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 361123d08b..43733ef252 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -35,6 +35,8 @@ namespace osu.Game.Screens.Play public readonly HoldForMenuButton HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; + public readonly IBindable IsPaused = new Bindable(); + private Bindable showHud; private readonly Container visibilityContainer; private readonly BindableBool replayLoaded = new BindableBool(); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 5cc6f09383..92f53d3f9e 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -137,7 +137,11 @@ namespace osu.Game.Screens.Play DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), HUDOverlay = new HUDOverlay(ScoreProcessor, DrawableRuleset, Mods.Value) { - HoldToQuit = { Action = performUserRequestedExit }, + HoldToQuit = + { + Action = performUserRequestedExit, + IsPaused = { BindTarget = GameplayClockContainer.IsPaused } + }, PlayerSettingsOverlay = { PlaybackSettings = { UserPlaybackRate = { BindTarget = GameplayClockContainer.UserPlaybackRate } } }, KeyCounter = { Visible = { BindTarget = DrawableRuleset.HasReplayLoaded } }, RequestSeek = GameplayClockContainer.Seek, From d25d39b3154e8bfea6c0b9aa7af31ae9a16b6df6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 10 May 2019 16:31:09 +0900 Subject: [PATCH 0749/5608] Add cancellation to storyboard/hitobject loading --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 15 ++++++++++++--- .../Storyboards/Drawables/DrawableStoryboard.cs | 8 +++++++- .../Drawables/DrawableStoryboardLayer.cs | 6 +++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 77d1e60b87..7f13c8e469 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Objects.Drawables; using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using osu.Framework.Bindables; using osu.Framework.Graphics.Cursor; using osu.Framework.Input; @@ -140,7 +141,7 @@ namespace osu.Game.Rulesets.UI public virtual PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new PlayfieldAdjustmentContainer(); [BackgroundDependencyLoader] - private void load(OsuConfigManager config) + private void load(OsuConfigManager config, CancellationToken cancellationToken) { InternalChildren = new Drawable[] { @@ -163,16 +164,24 @@ namespace osu.Game.Rulesets.UI applyRulesetMods(mods, config); - loadObjects(); + loadObjects(cancellationToken); } /// /// Creates and adds drawable representations of hit objects to the play field. /// - private void loadObjects() + private void loadObjects(CancellationToken cancellationToken) { foreach (TObject h in Beatmap.HitObjects) + { + if (cancellationToken.IsCancellationRequested) + break; + addHitObject(h); + } + + if (cancellationToken.IsCancellationRequested) + return; Playfield.PostProcess(); diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index 1182cacfc1..6af9d4d7f9 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.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; using osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -57,7 +58,7 @@ namespace osu.Game.Storyboards.Drawables } [BackgroundDependencyLoader(true)] - private void load(FileStore fileStore, GameplayClock clock) + private void load(FileStore fileStore, GameplayClock clock, CancellationToken cancellationToken) { if (clock != null) Clock = clock; @@ -65,7 +66,12 @@ namespace osu.Game.Storyboards.Drawables dependencies.Cache(new TextureStore(new TextureLoaderStore(fileStore.Store), false, scaleAdjust: 1)); foreach (var layer in Storyboard.Layers) + { + if (cancellationToken.IsCancellationRequested) + break; + Add(layer.CreateDrawable()); + } } private void updateLayerVisibility() diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs index 106ebfaf5d..e82b0df4f4 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.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; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -24,10 +25,13 @@ namespace osu.Game.Storyboards.Drawables } [BackgroundDependencyLoader] - private void load() + private void load(CancellationToken cancellationToken) { foreach (var element in Layer.Elements) { + if (cancellationToken.IsCancellationRequested) + break; + if (element.IsDrawable) AddInternal(element.CreateDrawable()); } From f6dfcc4dcf80673156ceecb3a757a9d0026eaeb9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 10 May 2019 16:31:22 +0900 Subject: [PATCH 0750/5608] Remove unnecessary Storyboard disposal --- osu.Game/Storyboards/Storyboard.cs | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 0cc753ff7e..3d988c5fe3 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -5,11 +5,10 @@ using osu.Game.Beatmaps; using osu.Game.Storyboards.Drawables; using System.Collections.Generic; using System.Linq; -using System; namespace osu.Game.Storyboards { - public class Storyboard : IDisposable + public class Storyboard { private readonly Dictionary layers = new Dictionary(); public IEnumerable Layers => layers.Values; @@ -56,30 +55,5 @@ namespace osu.Game.Storyboards drawable.Width = drawable.Height * (BeatmapInfo.WidescreenStoryboard ? 16 / 9f : 4 / 3f); return drawable; } - - #region Disposal - - ~Storyboard() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - private bool isDisposed; - - protected virtual void Dispose(bool isDisposing) - { - if (isDisposed) - return; - - isDisposed = true; - } - - #endregion } } From fdf67aaa11a3cc26d4b1343890a73ec11dfaeed3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 May 2019 17:18:39 +0900 Subject: [PATCH 0751/5608] Clamp values --- osu.Game/Screens/Play/SongProgressBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index 8ee2c0aa74..7e94dadf49 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -115,7 +115,7 @@ namespace osu.Game.Screens.Play { base.Update(); - float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Time.Elapsed / 40); + float newX = (float)MathHelper.Clamp(Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Time.Elapsed / 40), 0, UsableWidth); fill.Width = newX; handleBase.X = newX; From ad4b4f34226beb2d5333814b798de63272a3f582 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 10 May 2019 17:42:45 +0900 Subject: [PATCH 0752/5608] Use nullable cancellation tokens --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 11 ++++------- osu.Game/Storyboards/Drawables/DrawableStoryboard.cs | 5 ++--- .../Storyboards/Drawables/DrawableStoryboardLayer.cs | 5 ++--- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 1215cfb626..37f53d552c 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -141,7 +141,7 @@ namespace osu.Game.Rulesets.UI public virtual PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new PlayfieldAdjustmentContainer(); [BackgroundDependencyLoader] - private void load(OsuConfigManager config, CancellationToken cancellationToken) + private void load(OsuConfigManager config, CancellationToken? cancellationToken) { InternalChildren = new Drawable[] { @@ -170,18 +170,15 @@ namespace osu.Game.Rulesets.UI /// /// Creates and adds drawable representations of hit objects to the play field. /// - private void loadObjects(CancellationToken cancellationToken) + private void loadObjects(CancellationToken? cancellationToken) { foreach (TObject h in Beatmap.HitObjects) { - if (cancellationToken.IsCancellationRequested) - break; - + cancellationToken?.ThrowIfCancellationRequested(); addHitObject(h); } - if (cancellationToken.IsCancellationRequested) - return; + cancellationToken?.ThrowIfCancellationRequested(); Playfield.PostProcess(); diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index 6af9d4d7f9..2b27a56844 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -58,7 +58,7 @@ namespace osu.Game.Storyboards.Drawables } [BackgroundDependencyLoader(true)] - private void load(FileStore fileStore, GameplayClock clock, CancellationToken cancellationToken) + private void load(FileStore fileStore, GameplayClock clock, CancellationToken? cancellationToken) { if (clock != null) Clock = clock; @@ -67,8 +67,7 @@ namespace osu.Game.Storyboards.Drawables foreach (var layer in Storyboard.Layers) { - if (cancellationToken.IsCancellationRequested) - break; + cancellationToken?.ThrowIfCancellationRequested(); Add(layer.CreateDrawable()); } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs index e82b0df4f4..fd2d441f34 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs @@ -25,12 +25,11 @@ namespace osu.Game.Storyboards.Drawables } [BackgroundDependencyLoader] - private void load(CancellationToken cancellationToken) + private void load(CancellationToken? cancellationToken) { foreach (var element in Layer.Elements) { - if (cancellationToken.IsCancellationRequested) - break; + cancellationToken?.ThrowIfCancellationRequested(); if (element.IsDrawable) AddInternal(element.CreateDrawable()); From d2479acbf25f12d9adf3c61dd86d492db6b6aea0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 10 May 2019 18:04:58 +0900 Subject: [PATCH 0753/5608] Fix incorrect value being clamped --- osu.Game/Screens/Play/SongProgressBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index 7e94dadf49..dd7b5826d5 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -115,7 +115,7 @@ namespace osu.Game.Screens.Play { base.Update(); - float newX = (float)MathHelper.Clamp(Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Time.Elapsed / 40), 0, UsableWidth); + float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, MathHelper.Clamp(Time.Elapsed / 40, 0, 1)); fill.Width = newX; handleBase.X = newX; From 97796a85781aa5192d0317c177026ef00cab9c56 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 May 2019 18:10:07 +0900 Subject: [PATCH 0754/5608] Attempt to fix failing tests by delaying starting of the gameplay clock --- osu.Game.Tests/Visual/Gameplay/TestCasePause.cs | 15 +++++++++++++++ osu.Game/Tests/Visual/PlayerTestCase.cs | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs index 14be10b65c..81ef41ceec 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; +using osu.Framework.Testing; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; using osu.Game.Rulesets; @@ -31,6 +32,14 @@ namespace osu.Game.Tests.Visual.Gameplay base.Content.Add(content = new MenuCursorContainer { RelativeSizeAxes = Axes.Both }); } + [SetUpSteps] + public override void SetUpSteps() + { + base.SetUpSteps(); + AddStep("resume player", () => Player.GameplayClockContainer.Start()); + confirmClockRunning(true); + } + [Test] public void TestPauseResume() { @@ -203,6 +212,12 @@ namespace osu.Game.Tests.Visual.Gameplay base.LoadComplete(); HUDOverlay.HoldToQuit.PauseOnFocusLost = false; } + + public override void OnEntering(IScreen last) + { + base.OnEntering(last); + GameplayClockContainer.Stop(); + } } } } diff --git a/osu.Game/Tests/Visual/PlayerTestCase.cs b/osu.Game/Tests/Visual/PlayerTestCase.cs index c1960eefeb..85eacc7e09 100644 --- a/osu.Game/Tests/Visual/PlayerTestCase.cs +++ b/osu.Game/Tests/Visual/PlayerTestCase.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; @@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual } [SetUpSteps] - public void SetUpSteps() + public virtual void SetUpSteps() { AddStep(ruleset.RulesetInfo.Name, loadPlayer); AddUntilStep("player loaded", () => Player.IsLoaded && Player.Alpha == 1); From 3352252e00f82cce8c25ce074c8cb00616bc685a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 10 May 2019 18:21:07 +0900 Subject: [PATCH 0755/5608] Fix testcase regression --- .../Visual/Gameplay/TestCasePlayerLoader.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs index b8b8f2e4e2..511af971dc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs @@ -1,10 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using System.Linq; using System.Threading; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Rulesets.Mods; @@ -99,7 +101,17 @@ namespace osu.Game.Tests.Visual.Gameplay public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; } - protected class SlowLoadPlayer : TestPlayer + private class TestPlayer : Visual.TestPlayer + { + public new Bindable> Mods => base.Mods; + + public TestPlayer(bool allowPause = true, bool showResults = true) + : base(allowPause, showResults) + { + } + } + + protected class SlowLoadPlayer : Visual.TestPlayer { public bool Ready; From 3fe61c4a7ee96dddac374bfa244502c983d05a97 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 10 May 2019 18:48:39 +0900 Subject: [PATCH 0756/5608] Trim whitespace --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 6a2169592d..1cc56fff8b 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.UI /// The number of frames (per parent frame) which can be run in an attempt to catch-up to real-time. ///
public int MaxCatchUpFrames { get; set; } = 5; - + [Cached] public GameplayClock GameplayClock { get; } From 01eb1a34a915fcc871b3b013467b7d12da60a01d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 10 May 2019 22:15:33 +0900 Subject: [PATCH 0757/5608] Remove unused variable --- osu.Game/Screens/Play/HUDOverlay.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 43733ef252..361123d08b 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -35,8 +35,6 @@ namespace osu.Game.Screens.Play public readonly HoldForMenuButton HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; - public readonly IBindable IsPaused = new Bindable(); - private Bindable showHud; private readonly Container visibilityContainer; private readonly BindableBool replayLoaded = new BindableBool(); From 023a5c6e4faef1cd82bde231af6ed481f89d43c8 Mon Sep 17 00:00:00 2001 From: Tav TaOr Date: Fri, 10 May 2019 19:12:32 +0300 Subject: [PATCH 0758/5608] Add the ability to ignore the user's mouse movement. --- osu.Game.Rulesets.Osu/OsuInputManager.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index b9e083d35b..b4cc556ff2 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Osu set => ((OsuKeyBindingContainer)KeyBindingContainer).AllowUserPresses = value; } + public bool AllowUserCursorMovement { get; set; } = true; + protected override RulesetKeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) => new OsuKeyBindingContainer(ruleset, variant, unique); @@ -26,6 +28,16 @@ namespace osu.Game.Rulesets.Osu { } + protected override bool Handle(UIEvent e) + { + if (!AllowUserCursorMovement && e is MouseMoveEvent) + { + return false; + } + + return base.Handle(e); + } + private class OsuKeyBindingContainer : RulesetKeyBindingContainer { public bool AllowUserPresses = true; From bda0b35d849d15e01cf6ba4cd4ddd97d225e06c2 Mon Sep 17 00:00:00 2001 From: Tav TaOr Date: Fri, 10 May 2019 19:46:13 +0300 Subject: [PATCH 0759/5608] Slight formating change. --- osu.Game.Rulesets.Osu/OsuInputManager.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index b4cc556ff2..58e275ba26 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -30,10 +30,7 @@ namespace osu.Game.Rulesets.Osu protected override bool Handle(UIEvent e) { - if (!AllowUserCursorMovement && e is MouseMoveEvent) - { - return false; - } + if (e is MouseMoveEvent && !AllowUserCursorMovement) return false; return base.Handle(e); } From 0ec7c11a90f6ec343752ea786a5adf4078c06f7c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 May 2019 19:44:22 +0200 Subject: [PATCH 0760/5608] 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 0761/5608] 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 0762/5608] 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 0763/5608] 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 6cf1ca288f578874c84adf1c3468851d9d1b6f11 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sat, 11 May 2019 19:13:48 -0400 Subject: [PATCH 0764/5608] Do not try to join the Add-channel button --- osu.Game/Online/Chat/ChannelManager.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 8c6422afe3..1165c77977 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -84,7 +84,11 @@ namespace osu.Game.Online.Chat ?? new Channel(user); } - private void currentChannelChanged(ValueChangedEvent e) => JoinChannel(e.NewValue); + private void currentChannelChanged(ValueChangedEvent e) + { + if (e.NewValue?.Name != "+") + JoinChannel(e.NewValue); + } /// /// Ensure we run post actions in sequence, once at a time. From 3971a495491ac5e0317b7c3b5d462c5271a56a89 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sat, 11 May 2019 19:16:15 -0400 Subject: [PATCH 0765/5608] Ignore Add-channel button --- osu.Game/Overlays/ChatOverlay.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 221fd35576..6d18d3dae8 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -198,6 +198,11 @@ namespace osu.Game.Overlays channelSelectionOverlay.State = Visibility.Visible; return; } + + if (e.NewValue.Name == "+") + { + return; + } textbox.Current.Disabled = e.NewValue.ReadOnly; From c508b8ed6b1a8f3df9a59f904b73c3d1e5abd07a Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sat, 11 May 2019 19:21:12 -0400 Subject: [PATCH 0766/5608] Trim whitespace --- osu.Game/Overlays/ChatOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 6d18d3dae8..fa1c289007 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -198,7 +198,7 @@ namespace osu.Game.Overlays channelSelectionOverlay.State = Visibility.Visible; return; } - + if (e.NewValue.Name == "+") { return; From 29cec54b3ceaace918c38f0e47e2fbb38d0aa0ee Mon Sep 17 00:00:00 2001 From: Joehu Date: Sat, 11 May 2019 20:08:45 -0700 Subject: [PATCH 0767/5608] Fix beatmap carousel overlapping beatmap info wedge --- osu.Game/Screens/Select/SongSelect.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index d5301116a9..edc0474aa3 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -89,8 +89,6 @@ namespace osu.Game.Screens.Select protected SongSelect() { - const float carousel_width = 640; - AddRangeInternal(new Drawable[] { new ParallaxContainer @@ -103,7 +101,8 @@ namespace osu.Game.Screens.Select new WedgeBackground { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = carousel_width * 0.76f }, + Padding = new MarginPadding { Right = -150 }, + Size = new Vector2(wedged_container_size.X, 1), } } }, @@ -144,8 +143,8 @@ namespace osu.Game.Screens.Select Carousel = new BeatmapCarousel { Masking = false, - RelativeSizeAxes = Axes.Y, - Size = new Vector2(carousel_width, 1), + RelativeSizeAxes = Axes.Both, + Size = new Vector2(wedged_container_size.X, 1), Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, SelectionChanged = updateSelectedBeatmap, From 175daac16ae0b9bdd5989f0f23ff115a057a4b2b Mon Sep 17 00:00:00 2001 From: Joehu Date: Sat, 11 May 2019 21:26:42 -0700 Subject: [PATCH 0768/5608] Close beatmap options when suspending --- osu.Game/Screens/Select/SongSelect.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index d5301116a9..e8512748b3 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -505,6 +505,8 @@ namespace osu.Game.Screens.Select { ModSelect.Hide(); + BeatmapOptions.Hide(); + this.ScaleTo(1.1f, 250, Easing.InSine); this.FadeOut(250); From 790700d8bf8a711d956206cf19dfc149e2f5a68b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 12 May 2019 15:40:58 +0900 Subject: [PATCH 0769/5608] Use more correct calculation --- osu.Game/Screens/Select/SongSelect.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index edc0474aa3..b2924da908 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -39,6 +39,7 @@ namespace osu.Game.Screens.Select public abstract class SongSelect : OsuScreen { private static readonly Vector2 wedged_container_size = new Vector2(0.5f, 245); + protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; @@ -144,7 +145,7 @@ namespace osu.Game.Screens.Select { Masking = false, RelativeSizeAxes = Axes.Both, - Size = new Vector2(wedged_container_size.X, 1), + Size = new Vector2(1 - wedged_container_size.X, 1), Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, SelectionChanged = updateSelectedBeatmap, From 038e49701ec34a239a935072749f3bc466fcff65 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 12 May 2019 16:25:25 +0900 Subject: [PATCH 0770/5608] Move conditional to within BreakPeriod --- osu.Game/Beatmaps/Timing/BreakPeriod.cs | 7 +++++++ osu.Game/Screens/Play/Player.cs | 3 +-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Timing/BreakPeriod.cs b/osu.Game/Beatmaps/Timing/BreakPeriod.cs index 7cff54a058..856a5fefd4 100644 --- a/osu.Game/Beatmaps/Timing/BreakPeriod.cs +++ b/osu.Game/Beatmaps/Timing/BreakPeriod.cs @@ -29,5 +29,12 @@ namespace osu.Game.Beatmaps.Timing /// Whether the break has any effect. Breaks that are too short are culled before they are added to the beatmap. /// public bool HasEffect => Duration >= MIN_BREAK_DURATION; + + /// + /// Whether this break contains a specified time. + /// + /// The time to check in milliseconds. + /// Whether the time falls within this . + public bool Contains(double time) => time >= StartTime && time <= EndTime; } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 4d3bec668b..60054f38fa 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -416,8 +416,7 @@ namespace osu.Game.Screens.Play // breaks and time-based conditions may allow instant resume. double time = GameplayClockContainer.GameplayClock.CurrentTime; - if (Beatmap.Value.Beatmap.Breaks.Any(b => time >= b.StartTime && time <= b.EndTime) || - time < Beatmap.Value.Beatmap.HitObjects.First().StartTime) + if (Beatmap.Value.Beatmap.Breaks.Any(b => b.Contains(time)) || time < Beatmap.Value.Beatmap.HitObjects.First().StartTime) completeResume(); else DrawableRuleset.RequestResume(completeResume); From b8446fb67f07a9c8753947c41a1fa2940b322cb0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 12 May 2019 18:51:31 +0900 Subject: [PATCH 0771/5608] Fix fallbacks for SliderTrackOverride and SliderBall too --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 96cacd669d..b4c0aacb4d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -160,9 +160,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.SkinChanged(skin, allowFallback); - Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? Body.AccentColour; + Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? AccentColour; Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Color4.White; - Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Ball.AccentColour; + Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? AccentColour; } protected override void CheckForResult(bool userTriggered, double timeOffset) From 496a9dd41dc74460463ad3341541874f97f938a7 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sun, 12 May 2019 06:02:21 -0400 Subject: [PATCH 0772/5608] Create separate type for Join-Channel button --- .../Chat/Tabs/ChannelSelectorTabChannel.cs | 15 +++++++++++++++ osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabChannel.cs diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabChannel.cs b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabChannel.cs new file mode 100644 index 0000000000..39c570b239 --- /dev/null +++ b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabChannel.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 osu.Game.Online.Chat; + +namespace osu.Game.Overlays.Chat.Tabs +{ + public class ChannelSelectorTabChannel : Channel + { + public ChannelSelectorTabChannel() + { + Name = "+"; + } + } +} diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 67d9356b76..1d0dd3f192 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Chat.Tabs Margin = new MarginPadding(10), }); - AddTabItem(selectorTab = new ChannelSelectorTabItem(new Channel { Name = "+" })); + AddTabItem(selectorTab = new ChannelSelectorTabItem(new ChannelSelectorTabChannel())); ChannelSelectorActive.BindTo(selectorTab.Active); } From d53fb9a5c8b58d54bcedc82c5be5ca3fb62f33b8 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sun, 12 May 2019 06:11:16 -0400 Subject: [PATCH 0773/5608] Check against type instead of channel name --- osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs | 2 +- osu.Game/Online/Chat/ChannelManager.cs | 3 ++- osu.Game/Overlays/ChatOverlay.cs | 6 ++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs b/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs index fdc3d5394f..85488e36e7 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs @@ -93,7 +93,7 @@ namespace osu.Game.Tests.Visual.Online AddUntilStep("remove all channels", () => { var first = channelTabControl.Items.First(); - if (first.Name == "+") + if (first is ChannelSelectorTabChannel) return true; channelTabControl.RemoveChannel(first); diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 1165c77977..bf624ccbe7 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -10,6 +10,7 @@ using osu.Framework.Bindables; using osu.Framework.Logging; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Overlays.Chat.Tabs; using osu.Game.Users; namespace osu.Game.Online.Chat @@ -86,7 +87,7 @@ namespace osu.Game.Online.Chat private void currentChannelChanged(ValueChangedEvent e) { - if (e.NewValue?.Name != "+") + if (!(e.NewValue is ChannelSelectorTabChannel)) JoinChannel(e.NewValue); } diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index fa1c289007..a418fb1e78 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -199,10 +199,8 @@ namespace osu.Game.Overlays return; } - if (e.NewValue.Name == "+") - { + if (e.NewValue is ChannelSelectorTabChannel) return; - } textbox.Current.Disabled = e.NewValue.ReadOnly; @@ -273,7 +271,7 @@ namespace osu.Game.Overlays private void selectTab(int index) { var channel = channelTabControl.Items.Skip(index).FirstOrDefault(); - if (channel != null && channel.Name != "+") + if (channel != null && !(channel is ChannelSelectorTabChannel)) channelTabControl.Current.Value = channel; } From 8957ad5a7e9f0da1342ee194279b6953b3a62919 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sun, 12 May 2019 06:26:03 -0400 Subject: [PATCH 0774/5608] Instantiate channel in tab item --- osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs | 4 ++-- osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs index c26ecfd86f..9f22ab6923 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs @@ -13,8 +13,8 @@ namespace osu.Game.Overlays.Chat.Tabs public override bool IsSwitchable => false; - public ChannelSelectorTabItem(Channel value) - : base(value) + public ChannelSelectorTabItem() + : base(new ChannelSelectorTabChannel()) { Depth = float.MaxValue; Width = 45; diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 1d0dd3f192..fafcb0a72d 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Chat.Tabs Margin = new MarginPadding(10), }); - AddTabItem(selectorTab = new ChannelSelectorTabItem(new ChannelSelectorTabChannel())); + AddTabItem(selectorTab = new ChannelSelectorTabItem()); ChannelSelectorActive.BindTo(selectorTab.Active); } From 7adaa092630f7f41ea268c0a161d326abc5d1564 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sun, 12 May 2019 06:31:11 -0400 Subject: [PATCH 0775/5608] Move tab channel class into tab item class --- .../Visual/Online/TestCaseChannelTabControl.cs | 2 +- osu.Game/Online/Chat/ChannelManager.cs | 2 +- .../Chat/Tabs/ChannelSelectorTabChannel.cs | 15 --------------- .../Overlays/Chat/Tabs/ChannelSelectorTabItem.cs | 8 ++++++++ osu.Game/Overlays/ChatOverlay.cs | 4 ++-- 5 files changed, 12 insertions(+), 19 deletions(-) delete mode 100644 osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabChannel.cs diff --git a/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs b/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs index 85488e36e7..356ede0d57 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs @@ -93,7 +93,7 @@ namespace osu.Game.Tests.Visual.Online AddUntilStep("remove all channels", () => { var first = channelTabControl.Items.First(); - if (first is ChannelSelectorTabChannel) + if (first is ChannelSelectorTabItem.ChannelSelectorTabChannel) return true; channelTabControl.RemoveChannel(first); diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index bf624ccbe7..2efc9f4968 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -87,7 +87,7 @@ namespace osu.Game.Online.Chat private void currentChannelChanged(ValueChangedEvent e) { - if (!(e.NewValue is ChannelSelectorTabChannel)) + if (!(e.NewValue is ChannelSelectorTabItem.ChannelSelectorTabChannel)) JoinChannel(e.NewValue); } diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabChannel.cs b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabChannel.cs deleted file mode 100644 index 39c570b239..0000000000 --- a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabChannel.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Online.Chat; - -namespace osu.Game.Overlays.Chat.Tabs -{ - public class ChannelSelectorTabChannel : Channel - { - public ChannelSelectorTabChannel() - { - Name = "+"; - } - } -} diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs index 9f22ab6923..7386bffb1a 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs @@ -31,5 +31,13 @@ namespace osu.Game.Overlays.Chat.Tabs BackgroundInactive = colour.Gray2; BackgroundActive = colour.Gray3; } + + public class ChannelSelectorTabChannel : Channel + { + public ChannelSelectorTabChannel() + { + Name = "+"; + } + } } } diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index a418fb1e78..eb95fabe02 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -199,7 +199,7 @@ namespace osu.Game.Overlays return; } - if (e.NewValue is ChannelSelectorTabChannel) + if (e.NewValue is ChannelSelectorTabItem.ChannelSelectorTabChannel) return; textbox.Current.Disabled = e.NewValue.ReadOnly; @@ -271,7 +271,7 @@ namespace osu.Game.Overlays private void selectTab(int index) { var channel = channelTabControl.Items.Skip(index).FirstOrDefault(); - if (channel != null && !(channel is ChannelSelectorTabChannel)) + if (channel != null && !(channel is ChannelSelectorTabItem.ChannelSelectorTabChannel)) channelTabControl.Current.Value = channel; } From d229fed1287c3d48878ab7e91981cf123fbd429d Mon Sep 17 00:00:00 2001 From: Tav TaOr Date: Sun, 12 May 2019 14:00:43 +0300 Subject: [PATCH 0776/5608] Implemented Autopilot --- osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs index 401bd28d7c..7c423235fa 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs @@ -2,13 +2,19 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.StateChanges; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Replays; +using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModAutopilot : Mod + public class OsuModAutopilot : Mod, IApplicableFailOverride, IUpdatableByPlayfield, IApplicableToDrawableRuleset { public override string Name => "Autopilot"; public override string Acronym => "AP"; @@ -17,5 +23,41 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => @"Automatic cursor movement - just follow the rhythm."; public override double ScoreMultiplier => 1; public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) }; + + public bool AllowFail => false; + + private OsuInputManager inputManager; + + private List replayFrames; + private int frameIndex = 0; + + public void Update(Playfield playfield) + { + // If we are on the last replay frame, no need to do anything + if (frameIndex == replayFrames.Count - 1) + { + return; + } + + // Check if we are closer to the next replay frame then the current one + if (Math.Abs(replayFrames[frameIndex].Time - playfield.Time.Current) >= Math.Abs(replayFrames[frameIndex + 1].Time - playfield.Time.Current)) + { + // If we are, move to the next frame, and update the mouse position + frameIndex++; + new MousePositionAbsoluteInput() { Position = playfield.ToScreenSpace(replayFrames[frameIndex].Position) }.Apply(inputManager.CurrentState, inputManager); + } + + // TODO: Implement the functionality to automatically spin spinners + } + + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) + { + // Grab the input manager to disable the user's cursor, and for future use + inputManager = (OsuInputManager)drawableRuleset.KeyBindingInputManager; + inputManager.AllowUserCursorMovement = false; + + // Generate the replay frames the cursor should follow + replayFrames = new OsuAutoGenerator(drawableRuleset.Beatmap).Generate().Frames.Cast().ToList(); + } } } From 2051be7453ad5c201f0d6e11ecb737a68df1866e Mon Sep 17 00:00:00 2001 From: Tav TaOr Date: Sun, 12 May 2019 15:00:59 +0300 Subject: [PATCH 0777/5608] Minor changes to pass the AppVeyor test --- osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs index 7c423235fa..a9b99f3afe 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.Mods private OsuInputManager inputManager; private List replayFrames; - private int frameIndex = 0; + private int frameIndex; public void Update(Playfield playfield) { @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Mods { // If we are, move to the next frame, and update the mouse position frameIndex++; - new MousePositionAbsoluteInput() { Position = playfield.ToScreenSpace(replayFrames[frameIndex].Position) }.Apply(inputManager.CurrentState, inputManager); + new MousePositionAbsoluteInput { Position = playfield.ToScreenSpace(replayFrames[frameIndex].Position) }.Apply(inputManager.CurrentState, inputManager); } // TODO: Implement the functionality to automatically spin spinners From 1a6c8e91a5488dc512eeb739847f337296e39a95 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sun, 12 May 2019 08:44:20 -0400 Subject: [PATCH 0778/5608] Compare Health with small value --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index cf42a70640..584a9116fc 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Scoring /// /// The default conditions for failing. /// - protected virtual bool DefaultFailCondition => Health.Value == Health.MinValue; + protected virtual bool DefaultFailCondition => Health.Value < Health.MinValue + 1e-15; protected ScoreProcessor() { From 1c3b7682662f841988aae0be7a676a1970f56f69 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sun, 12 May 2019 09:02:22 -0400 Subject: [PATCH 0779/5608] Use Precision.AlmostBigger --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 584a9116fc..ce94ca9c7d 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -8,6 +8,7 @@ using System.Linq; using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Extensions.TypeExtensions; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; @@ -99,7 +100,7 @@ namespace osu.Game.Rulesets.Scoring /// /// The default conditions for failing. /// - protected virtual bool DefaultFailCondition => Health.Value < Health.MinValue + 1e-15; + protected virtual bool DefaultFailCondition => Precision.AlmostBigger(Health.MinValue, Health.Value); protected ScoreProcessor() { From dfd7b1111492735a7ecd7aead43163edbee439f6 Mon Sep 17 00:00:00 2001 From: Tav TaOr Date: Sun, 12 May 2019 16:04:37 +0300 Subject: [PATCH 0780/5608] Changed the unimplemented mod test to use OsuModSpunOut instead of OsuModAutopilot since Autopilot is implemented now. --- osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs index fd003c7ea2..7d1242083e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs @@ -90,7 +90,7 @@ namespace osu.Game.Tests.Visual.UserInterface var doubleTimeMod = harderMods.OfType().FirstOrDefault(m => m.Mods.Any(a => a is OsuModDoubleTime)); - var autoPilotMod = assistMods.FirstOrDefault(m => m is OsuModAutopilot); + var spunOutMod = easierMods.FirstOrDefault(m => m is OsuModSpunOut); var easy = easierMods.FirstOrDefault(m => m is OsuModEasy); var hardRock = harderMods.FirstOrDefault(m => m is OsuModHardRock); @@ -102,7 +102,7 @@ namespace osu.Game.Tests.Visual.UserInterface testMultiplierTextColour(noFailMod, modSelect.LowMultiplierColour); testMultiplierTextColour(hiddenMod, modSelect.HighMultiplierColour); - testUnimplementedMod(autoPilotMod); + testUnimplementedMod(spunOutMod); } [Test] From fca1b9325d4800edb79f4a24d4c4a82b500046bb Mon Sep 17 00:00:00 2001 From: Tav TaOr Date: Sun, 12 May 2019 16:18:27 +0300 Subject: [PATCH 0781/5608] Deleted the assistMods variable since it is never used --- osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs index 7d1242083e..4fbb12d6df 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs @@ -83,7 +83,6 @@ namespace osu.Game.Tests.Visual.UserInterface var easierMods = instance.GetModsFor(ModType.DifficultyReduction); var harderMods = instance.GetModsFor(ModType.DifficultyIncrease); - var assistMods = instance.GetModsFor(ModType.Automation); var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); var hiddenMod = harderMods.FirstOrDefault(m => m is OsuModHidden); From 65097fddc154808e06546d53595b3f5fe786e01a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 12 May 2019 22:34:36 +0900 Subject: [PATCH 0782/5608] Hide music controller when exiting via Alt-F4 Closes #4764. --- osu.Game/OsuGame.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 7b2a8184d1..a431802a1d 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -147,12 +147,17 @@ namespace osu.Game /// /// Close all game-wide overlays. /// - /// Whether the toolbar should also be hidden. - public void CloseAllOverlays(bool toolbar = true) + /// Whether the toolbar (and accompanying controls) should also be hidden. + public void CloseAllOverlays(bool hideToolbarElements = true) { foreach (var overlay in overlays) overlay.State = Visibility.Hidden; - if (toolbar) Toolbar.State = Visibility.Hidden; + + if (hideToolbarElements) + { + Toolbar.State = Visibility.Hidden; + musicController.State = Visibility.Hidden; + } } private DependencyContainer dependencies; From 41e13aef239b02b3407ab9fd0094e767d84147ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 12 May 2019 22:53:03 +0900 Subject: [PATCH 0783/5608] Use more standard parsing method --- osu.Game/Skinning/LegacySkinDecoder.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index f18b10384e..30280e2ffb 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps.Formats; @@ -37,8 +37,7 @@ namespace osu.Game.Skinning skin.CursorExpand = pair.Value != "0"; break; case @"SliderBorderSize": - if (Single.TryParse(pair.Value, NumberStyles.Number, CultureInfo.CreateSpecificCulture("en-US"), out float size)) - skin.SliderBorderSize = size; + skin.SliderBorderSize = Parsing.ParseFloat(pair.Value); break; } From 487a56549efb9097d0cd3ca4245f939b2957138c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 12 May 2019 22:53:12 +0900 Subject: [PATCH 0784/5608] Fix CI issues --- .../Objects/Drawables/Pieces/SliderBody.cs | 6 ++++-- osu.Game/Skinning/LegacySkinDecoder.cs | 5 ++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index b99f79afcb..83d4e9f453 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -70,7 +70,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public float BorderSize { get => path.BorderSize; - set { + set + { if (path.BorderSize == value) return; @@ -154,7 +155,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public float BorderSize { get => borderSize; - set { + set + { if (borderSize == value) return; diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 30280e2ffb..ecb112955c 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -1,9 +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.Game.Beatmaps.Formats; -using System; -using System.Globalization; namespace osu.Game.Skinning { @@ -36,6 +34,7 @@ namespace osu.Game.Skinning case @"CursorExpand": skin.CursorExpand = pair.Value != "0"; break; + case @"SliderBorderSize": skin.SliderBorderSize = Parsing.ParseFloat(pair.Value); break; From daa2786dbd1a91ea95153c90b20ea39056d1f0d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 12 May 2019 23:08:42 +0900 Subject: [PATCH 0785/5608] Use a constant for the default value --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 61d41bb246..05cb42d853 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -160,7 +160,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.SkinChanged(skin, allowFallback); - Body.BorderSize = skin.GetValue(s => s.SliderBorderSize) ?? 1; + Body.BorderSize = skin.GetValue(s => s.SliderBorderSize) ?? SliderBody.DEFAULT_BORDER_SIZE; Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? AccentColour; Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Color4.White; Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? AccentColour; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 83d4e9f453..25e1aebd18 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -14,6 +14,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public abstract class SliderBody : CompositeDrawable { + public const float DEFAULT_BORDER_SIZE = 1; + private readonly SliderPath path; protected Path Path => path; @@ -150,7 +152,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } - private float borderSize = 1f; + private float borderSize = DEFAULT_BORDER_SIZE; public float BorderSize { From 34f54aa94599f9e07ba7ee7391eea2a65d9d5c40 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 00:36:05 +0900 Subject: [PATCH 0786/5608] Resolve compile-time issues --- .../Visual/TestCaseChangelogOverlay.cs | 5 +++-- osu.Game.Tests/Visual/TestCaseLineBadge.cs | 2 +- osu.Game.Tests/Visual/TestCaseTextBadgePair.cs | 2 +- osu.Game/Graphics/StreamColour.cs | 2 +- osu.Game/Graphics/UserInterface/LineBadge.cs | 5 +++-- .../UserInterface/TooltipIconButton.cs | 9 +++++---- .../API/Requests/GetChangelogBuildRequest.cs | 5 +++-- .../API/Requests/GetChangelogChartRequest.cs | 5 +++-- .../GetChangelogLatestBuildsRequest.cs | 5 +++-- .../Online/API/Requests/GetChangelogRequest.cs | 5 +++-- .../Requests/Responses/APIChangelogBuild.cs | 5 +++-- .../Requests/Responses/APIChangelogChart.cs | 5 +++-- osu.Game/Overlays/Changelog/ChangelogBadges.cs | 5 ++++- .../Overlays/Changelog/ChangelogContent.cs | 5 +++-- .../Changelog/ChangelogContentGroup.cs | 18 ++++++++++++------ osu.Game/Overlays/Changelog/ChangelogHeader.cs | 7 +++---- .../Overlays/Changelog/Header/TextBadgePair.cs | 5 +++-- .../Changelog/Header/TextBadgePairListing.cs | 12 +++++++----- .../Changelog/Header/TextBadgePairRelease.cs | 9 +++++---- osu.Game/Overlays/Changelog/StreamBadge.cs | 8 ++++---- osu.Game/Overlays/ChangelogOverlay.cs | 14 +++++++++----- 21 files changed, 82 insertions(+), 56 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs index 2bd8cc2016..12961aeda7 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs @@ -1,5 +1,6 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// 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.Online.API.Requests.Responses; diff --git a/osu.Game.Tests/Visual/TestCaseLineBadge.cs b/osu.Game.Tests/Visual/TestCaseLineBadge.cs index d80ef0131b..06311ea7f9 100644 --- a/osu.Game.Tests/Visual/TestCaseLineBadge.cs +++ b/osu.Game.Tests/Visual/TestCaseLineBadge.cs @@ -1,11 +1,11 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.UserInterface; +using osuTK.Graphics; namespace osu.Game.Tests.Visual { diff --git a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs index 6d2fe20f2b..df2f796407 100644 --- a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs +++ b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs @@ -1,11 +1,11 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Overlays.Changelog.Header; +using osuTK.Graphics; namespace osu.Game.Tests.Visual { diff --git a/osu.Game/Graphics/StreamColour.cs b/osu.Game/Graphics/StreamColour.cs index 9149c29b0a..b730286608 100644 --- a/osu.Game/Graphics/StreamColour.cs +++ b/osu.Game/Graphics/StreamColour.cs @@ -1,9 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Graphics; using osu.Framework.Graphics.Colour; using System.Collections.Generic; +using osuTK.Graphics; namespace osu.Game.Graphics { diff --git a/osu.Game/Graphics/UserInterface/LineBadge.cs b/osu.Game/Graphics/UserInterface/LineBadge.cs index 53f057f4b3..ef55cb03ef 100644 --- a/osu.Game/Graphics/UserInterface/LineBadge.cs +++ b/osu.Game/Graphics/UserInterface/LineBadge.cs @@ -1,5 +1,6 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Shapes; diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index 1233483054..af203d316a 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -11,6 +10,8 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using System; +using osu.Framework.Graphics.Sprites; +using osuTK; namespace osu.Game.Graphics.UserInterface { @@ -43,10 +44,10 @@ namespace osu.Game.Graphics.UserInterface } } - public FontAwesome Icon + public IconUsage Icon { - get { return icon.Icon; } - set { icon.Icon = value; } + get => icon.Icon; + set => icon.Icon = value; } public TooltipIconButton() diff --git a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs index 73d0ec6d20..52b87eda73 100644 --- a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs @@ -1,5 +1,6 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs b/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs index 1e131fb91f..9d2e20c184 100644 --- a/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs @@ -1,5 +1,6 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs index 314a03e7f6..1d485edb4d 100644 --- a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs @@ -1,5 +1,6 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Game.Online.API.Requests.Responses; using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/GetChangelogRequest.cs b/osu.Game/Online/API/Requests/GetChangelogRequest.cs index b43f8d8ee1..17fb1992f3 100644 --- a/osu.Game/Online/API/Requests/GetChangelogRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogRequest.cs @@ -1,5 +1,6 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs index 86ee8b49dd..ab4bd9e613 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs @@ -1,5 +1,6 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// 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 System; diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs index 3509ff7de1..0d6487e01a 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs @@ -1,5 +1,6 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// 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 System; diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index eabe5fe258..f5a7737896 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -9,6 +8,7 @@ using osu.Framework.Input.Events; using osu.Game.Online.API.Requests.Responses; using System; using System.Collections.Generic; +using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { @@ -58,6 +58,7 @@ namespace osu.Game.Overlays.Changelog public void SelectNone() { selectedStreamId = -1; + if (badgesContainer != null) { foreach (StreamBadge streamBadge in badgesContainer) @@ -109,6 +110,7 @@ namespace osu.Game.Overlays.Changelog else streamBadge.Deactivate(); } + return base.OnHover(e); } @@ -121,6 +123,7 @@ namespace osu.Game.Overlays.Changelog else if (streamBadge.LatestBuild.UpdateStream.Id == selectedStreamId) streamBadge.DisableDim(); } + base.OnHoverLost(e); } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index fadfb9048f..aa95b54d0c 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -1,13 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using System; +using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { @@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Changelog RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; - Padding = new MarginPadding{ Bottom = 100 }; + Padding = new MarginPadding { Bottom = 100 }; } public void ShowListing(APIChangelogBuild[] changelog) @@ -47,6 +47,7 @@ namespace osu.Game.Overlays.Changelog Margin = new MarginPadding { Top = 30 }, }); } + changelogContentGroup = new ChangelogContentGroup(build, true); changelogContentGroup.BuildSelected += OnBuildSelected; changelogContentGroup.GenerateText(build.ChangelogEntries); diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 2dc8fd2bf7..6f12ff973a 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -1,8 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -12,12 +10,15 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; using System; using System.Collections.Generic; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { public class ChangelogContentGroup : FillFlowContainer { private readonly TooltipIconButton chevronPrevious, chevronNext; + private readonly SortedDictionary> categories = new SortedDictionary>(); @@ -47,7 +48,7 @@ namespace osu.Game.Overlays.Changelog chevronPrevious = new TooltipIconButton { IsEnabled = false, - Icon = FontAwesome.fa_chevron_left, + Icon = FontAwesome.Solid.ChevronLeft, Size = new Vector2(24), Action = () => { @@ -84,7 +85,7 @@ namespace osu.Game.Overlays.Changelog chevronNext = new TooltipIconButton { IsEnabled = false, - Icon = FontAwesome.fa_chevron_right, + Icon = FontAwesome.Solid.ChevronRight, Size = new Vector2(24), Action = () => { @@ -181,7 +182,8 @@ namespace osu.Game.Overlays.Changelog { clickableBuildText.Action = null; clickableBuildText.FadeTo(0.5f, 500); - Scheduler.AddDelayed(() => { + Scheduler.AddDelayed(() => + { clickableBuildText.Action = () => OnBuildSelected(build); clickableBuildText.FadeIn(500); }, 2000); @@ -195,6 +197,7 @@ namespace osu.Game.Overlays.Changelog chevronPrevious.TooltipText = previousVersion; chevronPrevious.IsEnabled = true; } + if (!string.IsNullOrEmpty(nextVersion)) { chevronNext.TooltipText = nextVersion; @@ -227,6 +230,7 @@ namespace osu.Game.Overlays.Changelog Font = @"Exo2.0-Bold", Margin = new MarginPadding { Top = 35, Bottom = 15 }, }); + foreach (ChangelogEntry entry in category.Value) { LinkFlowContainer title = new LinkFlowContainer @@ -236,12 +240,13 @@ namespace osu.Game.Overlays.Changelog AutoSizeAxes = Axes.Y, Margin = new MarginPadding { Vertical = 5 }, }; - title.AddIcon(FontAwesome.fa_check, t => + title.AddIcon(FontAwesome.Solid.Check, t => { t.TextSize = 12; t.Padding = new MarginPadding { Left = -17, Right = 5 }; }); title.AddText(entry.Title, t => { t.TextSize = 18; }); + if (!string.IsNullOrEmpty(entry.Repository)) { title.AddText(" (", t => t.TextSize = 18); @@ -250,6 +255,7 @@ namespace osu.Game.Overlays.Changelog null, t => { t.TextSize = 18; }); title.AddText(")", t => t.TextSize = 18); } + title.AddText(" by ", t => t.TextSize = 14); if (entry.GithubUser.GithubUrl != null) title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 035574bd1c..c23951bf23 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -1,18 +1,17 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Changelog.Header; using System; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { @@ -141,7 +140,7 @@ namespace osu.Game.Overlays.Changelog Origin = Anchor.Centre, Size = new Vector2(7), Colour = Purple, - Icon = FontAwesome.fa_chevron_right, + Icon = FontAwesome.Solid.ChevronRight, Alpha = 0, X = -200, }, diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index 387b7d4405..46a46913fd 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -1,5 +1,6 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Audio; diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs index ab4165b30b..b51948e849 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Input.Events; +using osuTK.Graphics; namespace osu.Game.Overlays.Changelog.Header { @@ -12,7 +12,8 @@ namespace osu.Game.Overlays.Changelog.Header { private readonly ColourInfo badgeColour; - public TextBadgePairListing(ColourInfo badgeColour) : base(badgeColour, "Listing", false) + public TextBadgePairListing(ColourInfo badgeColour) + : base(badgeColour, "Listing", false) { IsActivated = true; this.badgeColour = badgeColour; @@ -27,13 +28,14 @@ namespace osu.Game.Overlays.Changelog.Header // this doesn't work without the scheduler // (because the text isn't yet fully drawn when it's loaded?) - Text.OnLoadComplete = d => Scheduler.Add(UpdateBadgeWidth); + Text.OnLoadComplete += d => Scheduler.Add(UpdateBadgeWidth); } public override void Activate() { if (IsActivated) return; + IsActivated = true; LineBadge.Uncollapse(); Text.Font = "Exo2.0-Bold"; diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs index 97ce799509..f677bf62fe 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Colour; @@ -7,10 +7,10 @@ namespace osu.Game.Overlays.Changelog.Header { public class TextBadgePairRelease : TextBadgePair { - private TextBadgePairListing listingBadge; private const float transition_duration = 125; - public TextBadgePairRelease(ColourInfo badgeColour, string displayText) : base(badgeColour, displayText) + public TextBadgePairRelease(ColourInfo badgeColour, string displayText) + : base(badgeColour, displayText) { Text.Font = "Exo2.0-Bold"; Text.Y = 20; @@ -28,6 +28,7 @@ namespace osu.Game.Overlays.Changelog.Header } else ShowText(transition_duration, displayText); + IsActivated = true; } diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index dcae8dc04f..fc143c46d2 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -13,6 +12,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; using System; +using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { @@ -66,9 +66,7 @@ namespace osu.Game.Overlays.Changelog }, new SpriteText { - Text = LatestBuild.Users > 0 ? - $"{LatestBuild.Users:N0} users online" : - null, + Text = LatestBuild.Users > 0 ? $"{LatestBuild.Users:N0} users online" : null, TextSize = 12, // web: 10, Font = @"Exo2.0-Regular", Colour = new Color4(203, 164, 218, 255), @@ -100,6 +98,7 @@ namespace osu.Game.Overlays.Changelog { isActivated = false; DisableDim(); + if (!IsHovered) { this.FadeTo(0.5f, transition_duration); @@ -132,6 +131,7 @@ namespace osu.Game.Overlays.Changelog } else EnableDim(); + base.OnHoverLost(e); } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 302a9b351f..d3db26889f 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -1,12 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -18,13 +15,19 @@ using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Changelog; using System; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics.Effects; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays { public class ChangelogOverlay : WaveOverlayContainer { private readonly ChangelogHeader header; + private readonly ChangelogBadges badges; + //private readonly ChangelogChart chart; private readonly ChangelogContent listing; private readonly ChangelogContent content; @@ -35,7 +38,7 @@ namespace osu.Game.Overlays private SampleChannel sampleBack; - private APIAccess api; + private IAPIProvider api; private bool isAtListing; private float savedScrollPosition; @@ -99,7 +102,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(APIAccess api, AudioManager audio) + private void load(IAPIProvider api, AudioManager audio) { this.api = api; sampleBack = audio.Sample.Get(@"UI/generic-select-soft"); // @"UI/screen-back" feels non-fitting here @@ -146,6 +149,7 @@ namespace osu.Game.Overlays ShowListing(); sampleBack?.Play(); } + return true; } From 55663b3576c7e18c4c5beb030225f21e8b2a2f8c Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 12 May 2019 17:38:02 +0200 Subject: [PATCH 0787/5608] Nest all UserActivities into UserActivity --- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Select/PlaySongSelect.cs | 2 +- osu.Game/Users/UserActivity.cs | 87 ++++++++++++----------- 4 files changed, 47 insertions(+), 46 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 9384587bbb..a4cb659183 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -48,7 +48,7 @@ namespace osu.Game.Screens.Edit private DependencyContainer dependencies; private GameHost host; - protected override UserActivity InitialScreenActivity => new UserActivityEditing(Beatmap.Value.BeatmapInfo); + protected override UserActivity InitialScreenActivity => new UserActivity.UserActivityEditing(Beatmap.Value.BeatmapInfo); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 8f6ed43206..6a548cb6e4 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Play { protected override bool AllowBackButton => false; // handled by HoldForMenuButton - protected override UserActivity InitialScreenActivity => new UserActivitySoloGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); + protected override UserActivity InitialScreenActivity => new UserActivity.UserActivitySoloGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); public override float BackgroundParallaxAmount => 0.1f; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 608cd52bce..aba3343d69 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Select public override bool AllowExternalScreenChange => true; - protected override UserActivity InitialScreenActivity => new UserActivityChoosingBeatmap(); + protected override UserActivity InitialScreenActivity => new UserActivity.UserActivityChoosingBeatmap(); [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index fb896413e5..3e59b2a219 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -11,58 +11,59 @@ namespace osu.Game.Users { public abstract string Status { get; } public virtual Color4 GetAppropriateColour(OsuColour colours) => colours.GreenDarker; - } - public class UserActivityModding : UserActivity - { - public override string Status => "Modding a map"; - public override Color4 GetAppropriateColour(OsuColour colours) => colours.PurpleDark; - } - - public class UserActivityChoosingBeatmap : UserActivity - { - public override string Status => "Choosing a beatmap"; - } - - public class UserActivityMultiplayerGame : UserActivity - { - public override string Status => "Multiplaying"; - } - - public class UserActivityEditing : UserActivity - { - public UserActivityEditing(BeatmapInfo info) + public class UserActivityModding : UserActivity { - Beatmap = info; + public override string Status => "Modding a map"; + public override Color4 GetAppropriateColour(OsuColour colours) => colours.PurpleDark; } - public override string Status => @"Editing a beatmap"; - - public BeatmapInfo Beatmap { get; } - } - - public class UserActivitySoloGame : UserActivity - { - public UserActivitySoloGame(BeatmapInfo info, Rulesets.RulesetInfo ruleset) + public class UserActivityChoosingBeatmap : UserActivity { - Beatmap = info; - Ruleset = ruleset; + public override string Status => "Choosing a beatmap"; } - public override string Status => @"Solo Game"; + public class UserActivityMultiplayerGame : UserActivity + { + public override string Status => "Multiplaying"; + } - public BeatmapInfo Beatmap { get; } + public class UserActivityEditing : UserActivity + { + public UserActivityEditing(BeatmapInfo info) + { + Beatmap = info; + } - public Rulesets.RulesetInfo Ruleset { get; } + public override string Status => @"Editing a beatmap"; + + public BeatmapInfo Beatmap { get; } + } + + public class UserActivitySoloGame : UserActivity + { + public UserActivitySoloGame(BeatmapInfo info, Rulesets.RulesetInfo ruleset) + { + Beatmap = info; + Ruleset = ruleset; + } + + public override string Status => @"Solo Game"; + + public BeatmapInfo Beatmap { get; } + + public Rulesets.RulesetInfo Ruleset { get; } + } + + public class UserActivitySpectating : UserActivity + { + public override string Status => @"Spectating a game"; + } + + public class UserActivityInLobby : UserActivity + { + public override string Status => @"in Multiplayer Lobby"; + } } - public class UserActivitySpectating : UserActivity - { - public override string Status => @"Spectating a game"; - } - - public class UserActivityInLobby : UserActivity - { - public override string Status => @"in Multiplayer Lobby"; - } } From 2f663622ccaaba1945ea424a0fb19d64ae1c4e33 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 12 May 2019 17:40:18 +0200 Subject: [PATCH 0788/5608] Fix CI inspections --- osu.Game/Users/UserActivity.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 3e59b2a219..fe72f116ee 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -65,5 +65,4 @@ namespace osu.Game.Users public override string Status => @"in Multiplayer Lobby"; } } - } From 31b72f168d4851a59b64afb640be3e5e112fc639 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 00:46:22 +0900 Subject: [PATCH 0789/5608] Fix deprecated calls and code styling (partly) --- .../Visual/TestCaseChangelogOverlay.cs | 11 +++-- .../Visual/TestCaseTextBadgePair.cs | 1 - osu.Game/Graphics/StreamColour.cs | 1 + osu.Game/Graphics/UserInterface/LineBadge.cs | 5 +- .../UserInterface/TooltipIconButton.cs | 3 +- .../API/Requests/GetChangelogBuildRequest.cs | 1 - .../API/Requests/GetChangelogChartRequest.cs | 12 +++-- .../GetChangelogLatestBuildsRequest.cs | 1 - .../API/Requests/GetChangelogRequest.cs | 1 - .../Requests/Responses/APIChangelogBuild.cs | 1 - .../Requests/Responses/APIChangelogChart.cs | 1 - .../Overlays/Changelog/ChangelogContent.cs | 2 - .../Changelog/ChangelogContentGroup.cs | 48 +++++++++---------- .../Overlays/Changelog/ChangelogHeader.cs | 7 ++- .../Changelog/Header/TextBadgePair.cs | 6 ++- osu.Game/Overlays/Changelog/StreamBadge.cs | 9 ++-- osu.Game/Overlays/ChangelogOverlay.cs | 8 +++- 17 files changed, 62 insertions(+), 56 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs index 12961aeda7..063555cf76 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.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 NUnit.Framework; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; @@ -20,7 +19,9 @@ namespace osu.Game.Tests.Visual Add(changelog = new ChangelogOverlay()); AddStep(@"Show", changelog.Show); AddStep(@"Hide", changelog.Hide); - AddWaitStep(3); + + AddWaitStep("wait for hide", 3); + AddStep(@"Show with Lazer 2018.712.0", () => { changelog.FetchAndShowBuild(new APIChangelogBuild @@ -30,9 +31,11 @@ namespace osu.Game.Tests.Visual }); changelog.Show(); }); - AddWaitStep(3); + + AddWaitStep("wait for show", 3); AddStep(@"Hide", changelog.Hide); - AddWaitStep(3); + AddWaitStep("wait for hide", 3); + AddStep(@"Show with listing", () => { changelog.ShowListing(); diff --git a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs index df2f796407..bfd77ee3c7 100644 --- a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs +++ b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs @@ -42,7 +42,6 @@ namespace osu.Game.Tests.Visual AddStep(@"Hide text", () => textBadgePair.HideText(200)); AddStep(@"Show text", () => textBadgePair.ShowText(200)); AddStep(@"Different text", () => textBadgePair.ChangeText(200, "This one's a little bit wider")); - AddWaitStep(1); AddStep(@"Different text", () => textBadgePair.ChangeText(200, "Ok?..")); } } diff --git a/osu.Game/Graphics/StreamColour.cs b/osu.Game/Graphics/StreamColour.cs index b730286608..c4df3b64a3 100644 --- a/osu.Game/Graphics/StreamColour.cs +++ b/osu.Game/Graphics/StreamColour.cs @@ -36,6 +36,7 @@ namespace osu.Game.Graphics if (!string.IsNullOrEmpty(name)) if (colours.TryGetValue(name, out ColourInfo colour)) return colour; + return new Color4(0, 0, 0, 255); } } diff --git a/osu.Game/Graphics/UserInterface/LineBadge.cs b/osu.Game/Graphics/UserInterface/LineBadge.cs index ef55cb03ef..fc87acab0a 100644 --- a/osu.Game/Graphics/UserInterface/LineBadge.cs +++ b/osu.Game/Graphics/UserInterface/LineBadge.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. - using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -25,11 +24,12 @@ namespace osu.Game.Graphics.UserInterface /// public bool IsHorizontal { - get { return isHorizontal; } + get => isHorizontal; set { if (value == isHorizontal) return; + if (IsLoaded) { FinishTransforms(); @@ -41,6 +41,7 @@ namespace osu.Game.Graphics.UserInterface } else RelativeSizeAxes = value ? Axes.X : Axes.Y; + isHorizontal = value; } } diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index af203d316a..ce546c5358 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -36,7 +36,7 @@ namespace osu.Game.Graphics.UserInterface /// public bool IsEnabled { - get { return isEnabled; } + get => isEnabled; set { isEnabled = value; @@ -77,6 +77,7 @@ namespace osu.Game.Graphics.UserInterface sampleClick?.Play(); Action?.Invoke(); } + return base.OnClick(e); } diff --git a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs index 52b87eda73..6c32abee42 100644 --- a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. - using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs b/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs index 9d2e20c184..cf5dc5a65a 100644 --- a/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. - using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests @@ -10,12 +9,19 @@ namespace osu.Game.Online.API.Requests { private readonly string updateStream; - public GetChangelogChartRequest() => updateStream = null; + public GetChangelogChartRequest() + { + updateStream = null; + } - public GetChangelogChartRequest(string updateStreamName) => updateStream = updateStreamName; + public GetChangelogChartRequest(string updateStreamName) + { + updateStream = updateStreamName; + } protected override string Target => $@"changelog/{(!string.IsNullOrEmpty(updateStream) ? updateStream + "/" : "")}chart-config"; + protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}"; // for testing } } diff --git a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs index 1d485edb4d..087d4bb49c 100644 --- a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. - using osu.Game.Online.API.Requests.Responses; using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/GetChangelogRequest.cs b/osu.Game/Online/API/Requests/GetChangelogRequest.cs index 17fb1992f3..483182e720 100644 --- a/osu.Game/Online/API/Requests/GetChangelogRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogRequest.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. - using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs index ab4bd9e613..3ae992c22d 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.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 Newtonsoft.Json; using System; using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs index 0d6487e01a..598928d309 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogChart.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 Newtonsoft.Json; using System; using System.Collections.Generic; diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index aa95b54d0c..1f1bfae40a 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -4,7 +4,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using System; using osuTK.Graphics; @@ -13,7 +12,6 @@ namespace osu.Game.Overlays.Changelog { public class ChangelogContent : FillFlowContainer { - private APIAccess api; private ChangelogContentGroup changelogContentGroup; public delegate void BuildSelectedEventHandler(APIChangelogBuild build, EventArgs args); diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 6f12ff973a..837ce24522 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -65,19 +65,17 @@ namespace osu.Game.Overlays.Changelog new SpriteText { Text = build.UpdateStream.DisplayName, - TextSize = 28, // web: 24, - Font = @"Exo2.0-Medium", + Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 28), // web: 24, }, new SpriteText { Text = " ", - TextSize = 28, + Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 28), // web: 24, }, new SpriteText { Text = build.DisplayVersion, - TextSize = 28, // web: 24, - Font = @"Exo2.0-Light", + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 28), // web: 24, Colour = StreamColour.FromStreamName(build.UpdateStream.Name), }, } @@ -100,9 +98,8 @@ namespace osu.Game.Overlays.Changelog // do we need .ToUniversalTime() here? // also, this should be a temporary solution to weekdays in >localized< date strings Text = build.CreatedAt.Date.ToLongDateString().Replace(build.CreatedAt.ToString("dddd") + ", ", ""), - TextSize = 17, // web: 14, + Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 17), // web: 14, Colour = OsuColour.FromHex(@"FD5"), - Font = @"Exo2.0-Medium", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Margin = new MarginPadding { Top = 5 }, @@ -130,9 +127,8 @@ namespace osu.Game.Overlays.Changelog // do we need .ToUniversalTime() here? // also, this should be a temporary solution to weekdays in >localized< date strings Text = build.CreatedAt.Date.ToLongDateString().Replace(build.CreatedAt.ToString("dddd") + ", ", ""), - TextSize = 28, // web: 24, + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 28), // web: 24, Colour = OsuColour.FromHex(@"FD5"), - Font = @"Exo2.0-Light", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Margin = new MarginPadding { Top = 20 }, @@ -155,14 +151,12 @@ namespace osu.Game.Overlays.Changelog new SpriteText { Text = build.UpdateStream.DisplayName, - TextSize = 20, // web: 18, - Font = @"Exo2.0-Medium", + Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 20), // web: 19, }, new SpriteText { Text = build.DisplayVersion, - TextSize = 20, // web: 18, - Font = @"Exo2.0-Light", + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 20), // web: 19, Colour = StreamColour.FromStreamName(build.UpdateStream.Name), }, }, @@ -226,8 +220,7 @@ namespace osu.Game.Overlays.Changelog ChangelogEntries.Add(new SpriteText { Text = category.Key, - TextSize = 24, // web: 18, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 24), // web: 24, Margin = new MarginPadding { Top = 35, Bottom = 15 }, }); @@ -240,40 +233,47 @@ namespace osu.Game.Overlays.Changelog AutoSizeAxes = Axes.Y, Margin = new MarginPadding { Vertical = 5 }, }; + title.AddIcon(FontAwesome.Solid.Check, t => { - t.TextSize = 12; + t.Font = OsuFont.GetFont(size: 12); t.Padding = new MarginPadding { Left = -17, Right = 5 }; }); - title.AddText(entry.Title, t => { t.TextSize = 18; }); + + title.AddText(entry.Title, t => { t.Font = OsuFont.GetFont(size: 18); }); if (!string.IsNullOrEmpty(entry.Repository)) { - title.AddText(" (", t => t.TextSize = 18); + title.AddText(" (", t => t.Font = OsuFont.GetFont(size: 18)); title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, Online.Chat.LinkAction.External, null, - null, t => { t.TextSize = 18; }); - title.AddText(")", t => t.TextSize = 18); + null, t => { t.Font = OsuFont.GetFont(size: 18); }); + title.AddText(")", t => t.Font = OsuFont.GetFont(size: 18)); } - title.AddText(" by ", t => t.TextSize = 14); + title.AddText(" by ", t => t.Font = OsuFont.GetFont(size: 14)); + if (entry.GithubUser.GithubUrl != null) title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, - t => t.TextSize = 14); + t => t.Font = OsuFont.GetFont(size: 14)); else - title.AddText(entry.GithubUser.DisplayName, t => t.TextSize = 14); //web: 12; + title.AddText(entry.GithubUser.DisplayName, t => t.Font = OsuFont.GetFont(size: 14)); //web: 12; + ChangelogEntries.Add(title); + TextFlowContainer messageContainer = new TextFlowContainer { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, }; + messageContainer.AddText($"{entry.MessageHtml?.Replace("

", "").Replace("

", "")}\n", t => { - t.TextSize = 14; // web: 12, + t.Font = OsuFont.GetFont(size: 14); // web: 12, t.Colour = new Color4(235, 184, 254, 255); }); + ChangelogEntries.Add(messageContainer); } } diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index c23951bf23..b14e065b1e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Textures; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Changelog.Header; using System; +using osu.Game.Graphics; using osuTK; using osuTK.Graphics; @@ -97,14 +98,12 @@ namespace osu.Game.Overlays.Changelog new OsuSpriteText { Text = "Changelog ", - Font = @"Exo2.0-Light", - TextSize = 38, // web: 30 + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 38), // web: 30, }, titleStream = new OsuSpriteText { Text = "Listing", - TextSize = 38, // web: 30 - Font = @"Exo2.0-Light", + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 38), // web: 30, Colour = Purple, }, } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs index 46a46913fd..e044d4c342 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. - using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -12,6 +11,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; using System; +using osu.Game.Graphics; namespace osu.Game.Overlays.Changelog.Header { @@ -36,7 +36,7 @@ namespace osu.Game.Overlays.Changelog.Header { Text = new SpriteText { - TextSize = 21, // web: 16, + Font = OsuFont.GetFont(size: 21), // web: 16, Text = displayText, Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -56,6 +56,8 @@ namespace osu.Game.Overlays.Changelog.Header /// /// The duration of popping in and popping out not combined. /// Full change takes double this time. + /// + /// public void ChangeText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) { LineBadge.Collapse(); diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index fc143c46d2..c9ed04168c 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -54,21 +54,18 @@ namespace osu.Game.Overlays.Changelog new SpriteText { Text = LatestBuild.UpdateStream.DisplayName, - Font = @"Exo2.0-Bold", - TextSize = 14, // web: 12, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), // web: 12, Margin = new MarginPadding { Top = 6 }, }, new SpriteText { Text = LatestBuild.DisplayVersion, - Font = @"Exo2.0-Light", - TextSize = 20, // web: 16, + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 20), // web: 16, }, new SpriteText { Text = LatestBuild.Users > 0 ? $"{LatestBuild.Users:N0} users online" : null, - TextSize = 12, // web: 10, - Font = @"Exo2.0-Regular", + Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 12), // web: 10, Colour = new Color4(203, 164, 218, 255), }, } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index d3db26889f..8f77862c99 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -161,8 +161,10 @@ namespace osu.Game.Overlays private void fetchListing() { header.ShowListing(); + if (isAtListing) return; + isAtListing = true; var req = new GetChangelogRequest(); badges.SelectNone(); @@ -173,8 +175,10 @@ namespace osu.Game.Overlays public void ShowListing() { header.ShowListing(); + if (isAtListing) return; + isAtListing = true; content.Hide(); listing.Show(); @@ -187,8 +191,8 @@ namespace osu.Game.Overlays /// /// Fetches and shows a specific build from a specific update stream. /// - /// Must contain at least and - /// . If and + /// Must contain at least and + /// . If and /// are specified, the header will instantly display them. /// Whether to update badges. Should be set to false in case /// the function is called by selecting a badge, to avoid an infinite loop. From 1fe4d20d9ba3794e9894414ee6c62e91753e7aba Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 12 May 2019 17:47:02 +0200 Subject: [PATCH 0790/5608] Fix references to UserActivities in Tests --- osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs b/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs index 0e958f45c6..b800c361cf 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs @@ -61,11 +61,11 @@ namespace osu.Game.Tests.Visual.Online public void UserActivitiesTests() { AddStep("idle", () => { flyte.Activity.Value = null; }); - AddStep("spectating", () => { flyte.Activity.Value = new UserActivitySpectating(); }); - AddStep("solo", () => { flyte.Activity.Value = new UserActivitySoloGame(null, null); }); - AddStep("choosing", () => { flyte.Activity.Value = new UserActivityChoosingBeatmap(); }); - AddStep("editing", () => { flyte.Activity.Value = new UserActivityEditing(null); }); - AddStep("modding", () => { flyte.Activity.Value = new UserActivityModding(); }); + AddStep("spectating", () => { flyte.Activity.Value = new UserActivity.UserActivitySpectating(); }); + AddStep("solo", () => { flyte.Activity.Value = new UserActivity.UserActivitySoloGame(null, null); }); + AddStep("choosing", () => { flyte.Activity.Value = new UserActivity.UserActivityChoosingBeatmap(); }); + AddStep("editing", () => { flyte.Activity.Value = new UserActivity.UserActivityEditing(null); }); + AddStep("modding", () => { flyte.Activity.Value = new UserActivity.UserActivityModding(); }); } } } From f14690e3b888d48a3ec7b58b53009d676f6a4f44 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 12 May 2019 09:04:11 -0700 Subject: [PATCH 0791/5608] Swap profile play styles and last visit positions --- .../Profile/Header/BottomHeaderContainer.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 52336dcd30..633085960b 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -87,14 +87,6 @@ namespace osu.Game.Overlays.Profile.Header addSpacer(topLinkContainer); - if (user.PlayStyles?.Length > 0) - { - topLinkContainer.AddText("Plays with "); - topLinkContainer.AddText(string.Join(", ", user.PlayStyles.Select(style => style.GetDescription())), embolden); - - addSpacer(topLinkContainer); - } - if (user.LastVisit.HasValue) { topLinkContainer.AddText("Last seen "); @@ -103,6 +95,14 @@ namespace osu.Game.Overlays.Profile.Header addSpacer(topLinkContainer); } + if (user.PlayStyles?.Length > 0) + { + topLinkContainer.AddText("Plays with "); + topLinkContainer.AddText(string.Join(", ", user.PlayStyles.Select(style => style.GetDescription())), embolden); + + addSpacer(topLinkContainer); + } + topLinkContainer.AddText("Contributed "); topLinkContainer.AddLink($@"{user.PostCount:#,##0} forum posts", $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: embolden); From c119a6a13587830469b009919e376d8e3c5048d6 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 12 May 2019 09:30:43 -0700 Subject: [PATCH 0792/5608] Use VolumeMute icon for mute button --- osu.Game/Overlays/Volume/MuteButton.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index 2b1f78243b..c87ca65dba 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.cs @@ -64,16 +64,15 @@ namespace osu.Game.Overlays.Volume }, icon = new SpriteIcon { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Size = new Vector2(20), } }); Current.ValueChanged += muted => { - icon.Icon = muted.NewValue ? FontAwesome.Solid.VolumeOff : FontAwesome.Solid.VolumeUp; - icon.Margin = new MarginPadding { Left = muted.NewValue ? width / 2 - 15 : width / 2 - 10 }; //Magic numbers to line up both icons because they're different widths + icon.Icon = muted.NewValue ? FontAwesome.Solid.VolumeMute : FontAwesome.Solid.VolumeUp; }; Current.TriggerChange(); } From b3a95cac84e2f30bcc4acfb5eb8e4b030f9ad7d3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 12 May 2019 20:20:11 +0200 Subject: [PATCH 0793/5608] 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 0794/5608] 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 0795/5608] 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 0796/5608] 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 0797/5608] 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 3981cf55fa8d47a25a94395e774c0d68b3c2b33f Mon Sep 17 00:00:00 2001 From: HoLLy Date: Sun, 12 May 2019 21:31:16 +0200 Subject: [PATCH 0798/5608] Fix order of nested hitobjects on 2B Catch maps --- .../Difficulty/CatchDifficultyCalculator.cs | 33 ++++++------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index bd647fd667..f24e67366a 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -57,33 +57,20 @@ namespace osu.Game.Rulesets.Catch.Difficulty CatchHitObject lastObject = null; - foreach (var hitObject in beatmap.HitObjects.OfType()) + // In 2B beatmaps, it is possible that a normal Fruit is placed in the middle of a JuiceStream. + foreach (var hitObject in beatmap.HitObjects + .SelectMany(obj => obj is JuiceStream stream ? stream.NestedHitObjects : new[] { obj }) + .OfType() + .OrderBy(x => x.StartTime)) { - if (lastObject == null) - { - lastObject = hitObject; + // We want to only consider fruits that contribute to the combo. + if (hitObject is BananaShower || hitObject is TinyDroplet) continue; - } - switch (hitObject) - { - // We want to only consider fruits that contribute to the combo. Droplets are addressed as accuracy and spinners are not relevant for "skill" calculations. - case Fruit fruit: - yield return new CatchDifficultyHitObject(fruit, lastObject, clockRate, halfCatchWidth); + if (lastObject != null) + yield return new CatchDifficultyHitObject(hitObject, lastObject, clockRate, halfCatchWidth); - lastObject = hitObject; - break; - - case JuiceStream _: - foreach (var nested in hitObject.NestedHitObjects.OfType().Where(o => !(o is TinyDroplet))) - { - yield return new CatchDifficultyHitObject(nested, lastObject, clockRate, halfCatchWidth); - - lastObject = nested; - } - - break; - } + lastObject = hitObject; } } From cb664dd183e3c111edd4a10fc2221614ea44c946 Mon Sep 17 00:00:00 2001 From: HoLLy Date: Sun, 12 May 2019 22:08:47 +0200 Subject: [PATCH 0799/5608] Change OfType<> to Cast<> to be more clear --- osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index f24e67366a..d6a1ed632b 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty // In 2B beatmaps, it is possible that a normal Fruit is placed in the middle of a JuiceStream. foreach (var hitObject in beatmap.HitObjects .SelectMany(obj => obj is JuiceStream stream ? stream.NestedHitObjects : new[] { obj }) - .OfType() + .Cast() .OrderBy(x => x.StartTime)) { // We want to only consider fruits that contribute to the combo. From 8110d6768c14ba88d2aae8d8ebd63e177fde35bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 07:24:34 +0900 Subject: [PATCH 0800/5608] Inherit OsuButton --- osu.Game/Overlays/Volume/MuteButton.cs | 36 +++++++++++--------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index c87ca65dba..a4884dc2c1 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.cs @@ -4,21 +4,20 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.Volume { - public class MuteButton : Container, IHasCurrentValue + public class MuteButton : OsuButton, IHasCurrentValue { private readonly Bindable current = new Bindable(); @@ -36,32 +35,32 @@ namespace osu.Game.Overlays.Volume } private Color4 hoveredColour, unhoveredColour; + private const float width = 100; public const float HEIGHT = 35; public MuteButton() { - Masking = true; - BorderThickness = 3; - CornerRadius = HEIGHT / 2; + Content.BorderThickness = 3; + Content.CornerRadius = HEIGHT / 2; + Size = new Vector2(width, HEIGHT); + + Action = () => Current.Value = !Current.Value; } [BackgroundDependencyLoader] private void load(OsuColour colours) { hoveredColour = colours.YellowDark; - BorderColour = unhoveredColour = colours.Gray1.Opacity(0.9f); + + Content.BorderColour = unhoveredColour = colours.Gray1; + BackgroundColour = colours.Gray1; SpriteIcon icon; + AddRange(new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Gray1, - Alpha = 0.9f, - }, icon = new SpriteIcon { Anchor = Anchor.Centre, @@ -74,24 +73,19 @@ namespace osu.Game.Overlays.Volume { icon.Icon = muted.NewValue ? FontAwesome.Solid.VolumeMute : FontAwesome.Solid.VolumeUp; }; + Current.TriggerChange(); } protected override bool OnHover(HoverEvent e) { - this.TransformTo("BorderColour", hoveredColour, 500, Easing.OutQuint); + Content.TransformTo, SRGBColour>("BorderColour", hoveredColour, 500, Easing.OutQuint); return false; } protected override void OnHoverLost(HoverLostEvent e) { - this.TransformTo("BorderColour", unhoveredColour, 500, Easing.OutQuint); - } - - protected override bool OnClick(ClickEvent e) - { - Current.Value = !Current.Value; - return true; + Content.TransformTo, SRGBColour>("BorderColour", unhoveredColour, 500, Easing.OutQuint); } } } From f7806bc20538111cf2fc858d979dcc808a655e3e Mon Sep 17 00:00:00 2001 From: HoLLy Date: Mon, 13 May 2019 01:31:47 +0200 Subject: [PATCH 0801/5608] Add smoothing to flashlight movement --- osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index c0332fbf60..c3c1e86c18 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -7,6 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Events; +using osu.Framework.MathUtils; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; @@ -35,6 +36,9 @@ namespace osu.Game.Rulesets.Osu.Mods private class OsuFlashlight : Flashlight, IRequireHighFrequencyMousePosition { + private const double follow_delay = 120; + private double lastPositionUpdate; + public OsuFlashlight() { FlashlightSize = new Vector2(0, getSizeFor(0)); @@ -48,7 +52,16 @@ namespace osu.Game.Rulesets.Osu.Mods protected override bool OnMouseMove(MouseMoveEvent e) { - FlashlightPosition = e.MousePosition; + var position = FlashlightPosition; + var destination = e.MousePosition; + + double frameTime = Clock.CurrentTime - lastPositionUpdate; + double interp = Interpolation.ApplyEasing(Easing.Out, MathHelper.Clamp(frameTime / follow_delay, 0, 1)); + FlashlightPosition = new Vector2( + (float)Interpolation.Lerp(position.X, destination.X, interp), + (float)Interpolation.Lerp(position.Y, destination.Y, interp) + ); + lastPositionUpdate = Clock.CurrentTime; return base.OnMouseMove(e); } From 219c590b8ab11b1a3fd4c2b81c9aedb8657ff121 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 16:24:32 +0900 Subject: [PATCH 0802/5608] Initial pass to make work with real API --- .../API/Requests/GetChangelogBuildRequest.cs | 1 - .../API/Requests/GetChangelogChartRequest.cs | 2 -- .../GetChangelogLatestBuildsRequest.cs | 7 +------ .../Online/API/Requests/GetChangelogRequest.cs | 3 +-- .../Requests/Responses/APIChangelogBuild.cs | 9 ++++++--- .../Requests/Responses/APIChangelogIndex.cs | 14 ++++++++++++++ osu.Game/Overlays/Changelog/ChangelogBadges.cs | 16 ++++++++-------- .../Overlays/Changelog/ChangelogContent.cs | 3 ++- osu.Game/Overlays/Changelog/StreamBadge.cs | 18 ++++++++++-------- osu.Game/Overlays/ChangelogOverlay.cs | 4 ++-- 10 files changed, 44 insertions(+), 33 deletions(-) create mode 100644 osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs diff --git a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs index 6c32abee42..baa15c70c4 100644 --- a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs @@ -17,6 +17,5 @@ namespace osu.Game.Online.API.Requests } protected override string Target => $@"changelog/{name}/{version}"; - protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}"; // for testing } } diff --git a/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs b/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs index cf5dc5a65a..66e7d198c2 100644 --- a/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs @@ -21,7 +21,5 @@ namespace osu.Game.Online.API.Requests protected override string Target => $@"changelog/{(!string.IsNullOrEmpty(updateStream) ? updateStream + "/" : "")}chart-config"; - - protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}"; // for testing } } diff --git a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs index 087d4bb49c..dd50701e39 100644 --- a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs @@ -1,14 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Online.API.Requests.Responses; -using System.Collections.Generic; - namespace osu.Game.Online.API.Requests { - public class GetChangelogLatestBuildsRequest : APIRequest> + public class GetChangelogLatestBuildsRequest : GetChangelogRequest { - protected override string Target => @"changelog/latest-builds"; - protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}"; // for testing } } diff --git a/osu.Game/Online/API/Requests/GetChangelogRequest.cs b/osu.Game/Online/API/Requests/GetChangelogRequest.cs index 483182e720..97799ff66a 100644 --- a/osu.Game/Online/API/Requests/GetChangelogRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogRequest.cs @@ -5,9 +5,8 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { - public class GetChangelogRequest : APIRequest + public class GetChangelogRequest : APIRequest { protected override string Target => @"changelog"; - protected override string Uri => $@"https://houtarouoreki.github.io/fake-api/{Target}/index"; // for testing } } diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs index 3ae992c22d..64b62e1f73 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs @@ -21,9 +21,6 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("users")] public long Users { get; set; } - [JsonProperty("is_featured")] - public bool IsFeatured { get; set; } - [JsonProperty("created_at")] public DateTimeOffset CreatedAt { get; set; } @@ -114,7 +111,13 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("name")] public string Name { get; set; } + [JsonProperty("is_featured")] + public bool IsFeatured { get; set; } + [JsonProperty("display_name")] public string DisplayName { get; set; } + + [JsonProperty("latest_build")] + public APIChangelogBuild LatestBuild { get; set; } } } diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs new file mode 100644 index 0000000000..957694b887 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.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 System.Collections.Generic; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIChangelogIndex + { + public List Builds; + + public List Streams; + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index f5a7737896..cf14ddbb01 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -45,9 +45,9 @@ namespace osu.Game.Overlays.Changelog }; } - public void Populate(List latestBuilds) + public void Populate(List streams) { - foreach (APIChangelogBuild updateStream in latestBuilds) + foreach (UpdateStream updateStream in streams) { var streamBadge = new StreamBadge(updateStream); streamBadge.Selected += onBadgeSelected; @@ -75,9 +75,9 @@ namespace osu.Game.Overlays.Changelog { foreach (StreamBadge streamBadge in badgesContainer) { - if (streamBadge.LatestBuild.UpdateStream.Name == updateStream) + if (streamBadge.Stream.Name == updateStream) { - selectedStreamId = streamBadge.LatestBuild.UpdateStream.Id; + selectedStreamId = streamBadge.Stream.Id; streamBadge.Activate(); } else @@ -87,13 +87,13 @@ namespace osu.Game.Overlays.Changelog private void onBadgeSelected(StreamBadge source, EventArgs args) { - selectedStreamId = source.LatestBuild.UpdateStream.Id; + selectedStreamId = source.Stream.Id; OnSelected(source); } protected virtual void OnSelected(StreamBadge source) { - Selected?.Invoke(source.LatestBuild, EventArgs.Empty); + Selected?.Invoke(source.Stream.LatestBuild, EventArgs.Empty); } protected override bool OnHover(HoverEvent e) @@ -102,7 +102,7 @@ namespace osu.Game.Overlays.Changelog { if (selectedStreamId >= 0) { - if (selectedStreamId != streamBadge.LatestBuild.UpdateStream.Id) + if (selectedStreamId != streamBadge.Stream.Id) streamBadge.Deactivate(); else streamBadge.EnableDim(); @@ -120,7 +120,7 @@ namespace osu.Game.Overlays.Changelog { if (selectedStreamId < 0) streamBadge.Activate(); - else if (streamBadge.LatestBuild.UpdateStream.Id == selectedStreamId) + else if (streamBadge.Stream.Id == selectedStreamId) streamBadge.DisableDim(); } diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 1f1bfae40a..e71769595f 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Online.API.Requests.Responses; using System; +using System.Collections.Generic; using osuTK.Graphics; namespace osu.Game.Overlays.Changelog @@ -26,7 +27,7 @@ namespace osu.Game.Overlays.Changelog Padding = new MarginPadding { Bottom = 100 }; } - public void ShowListing(APIChangelogBuild[] changelog) + public void ShowListing(List changelog) { DateTime currentDate = new DateTime(); Clear(); diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index c9ed04168c..424c344e91 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -32,14 +32,16 @@ namespace osu.Game.Overlays.Changelog private SampleChannel sampleClick; private SampleChannel sampleHover; - public readonly APIChangelogBuild LatestBuild; + public readonly UpdateStream Stream; + private readonly FillFlowContainer text; - public StreamBadge(APIChangelogBuild latestBuild) + public StreamBadge(UpdateStream stream) { - LatestBuild = latestBuild; + Stream = stream; + Height = badge_height; - Width = LatestBuild.IsFeatured ? badge_width * 2 : badge_width; + Width = stream.IsFeatured ? badge_width * 2 : badge_width; Padding = new MarginPadding(5); isActivated = true; Children = new Drawable[] @@ -53,18 +55,18 @@ namespace osu.Game.Overlays.Changelog { new SpriteText { - Text = LatestBuild.UpdateStream.DisplayName, + Text = stream.DisplayName, Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), // web: 12, Margin = new MarginPadding { Top = 6 }, }, new SpriteText { - Text = LatestBuild.DisplayVersion, + Text = stream.LatestBuild.DisplayVersion, Font = OsuFont.GetFont(weight: FontWeight.Light, size: 20), // web: 16, }, new SpriteText { - Text = LatestBuild.Users > 0 ? $"{LatestBuild.Users:N0} users online" : null, + Text = stream.LatestBuild.Users > 0 ? $"{stream.LatestBuild.Users:N0} users online" : null, Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 12), // web: 10, Colour = new Color4(203, 164, 218, 255), }, @@ -73,7 +75,7 @@ namespace osu.Game.Overlays.Changelog lineBadge = new LineBadge(false) { Anchor = Anchor.TopCentre, - Colour = StreamColour.FromStreamName(LatestBuild.UpdateStream.Name), + Colour = StreamColour.FromStreamName(stream.Name), UncollapsedSize = 4, CollapsedSize = 2, }, diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 8f77862c99..aa32b8dae4 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -111,7 +111,7 @@ namespace osu.Game.Overlays protected override void LoadComplete() { var req = new GetChangelogLatestBuildsRequest(); - req.Success += badges.Populate; + req.Success += res => badges.Populate(res.Streams); api.Queue(req); fetchListing(); base.LoadComplete(); @@ -168,7 +168,7 @@ namespace osu.Game.Overlays isAtListing = true; var req = new GetChangelogRequest(); badges.SelectNone(); - req.Success += listing.ShowListing; + req.Success += res => listing.ShowListing(res.Builds); api.Queue(req); } From 37a8d9eb801bdacacc47ca5e628526b2cdf2da3e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 16:27:54 +0900 Subject: [PATCH 0803/5608] Remove chart references for now --- .../API/Requests/GetChangelogChartRequest.cs | 25 -------------- .../Requests/Responses/APIChangelogChart.cs | 33 ------------------- osu.Game/Overlays/ChangelogOverlay.cs | 4 --- 3 files changed, 62 deletions(-) delete mode 100644 osu.Game/Online/API/Requests/GetChangelogChartRequest.cs delete mode 100644 osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs diff --git a/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs b/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs deleted file mode 100644 index 66e7d198c2..0000000000 --- a/osu.Game/Online/API/Requests/GetChangelogChartRequest.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Online.API.Requests.Responses; - -namespace osu.Game.Online.API.Requests -{ - public class GetChangelogChartRequest : APIRequest - { - private readonly string updateStream; - - public GetChangelogChartRequest() - { - updateStream = null; - } - - public GetChangelogChartRequest(string updateStreamName) - { - updateStream = updateStreamName; - } - - protected override string Target => $@"changelog/{(!string.IsNullOrEmpty(updateStream) ? - updateStream + "/" : "")}chart-config"; - } -} diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs deleted file mode 100644 index 598928d309..0000000000 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogChart.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using Newtonsoft.Json; -using System; -using System.Collections.Generic; - -namespace osu.Game.Online.API.Requests.Responses -{ - public class APIChangelogChart - { - [JsonProperty("build_history")] - public List BuildHistory { get; set; } - - [JsonProperty("order")] - public List Order { get; set; } - - [JsonProperty("stream_name")] - public string StreamName { get; set; } - } - - public class BuildHistory - { - [JsonProperty("created_at")] - public DateTimeOffset CreatedAt { get; set; } - - [JsonProperty("user_count")] - public long UserCount { get; set; } - - [JsonProperty("label")] - public string Label { get; set; } - } -} diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index aa32b8dae4..eb1d4ca69f 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -28,7 +28,6 @@ namespace osu.Game.Overlays private readonly ChangelogBadges badges; - //private readonly ChangelogChart chart; private readonly ChangelogContent listing; private readonly ChangelogContent content; @@ -88,7 +87,6 @@ namespace osu.Game.Overlays { header = new ChangelogHeader(), badges = new ChangelogBadges(), - //chart = new ChangelogChart(), listing = new ChangelogContent(), content = new ChangelogContent() }, @@ -183,7 +181,6 @@ namespace osu.Game.Overlays content.Hide(); listing.Show(); badges.SelectNone(); - //chart.ShowAllUpdateStreams(); listing.Show(); scroll.ScrollTo(savedScrollPosition); } @@ -208,7 +205,6 @@ namespace osu.Game.Overlays if (updateBadges) badges.SelectUpdateStream(build.UpdateStream.Name); - //chart.ShowUpdateStream(build.UpdateStream.Name); req.Success += apiChangelog => { listing.Hide(); From e9c3f5430722912aa88add88731dffc3f33819c7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 16:44:43 +0900 Subject: [PATCH 0804/5608] Share web request between builds and streams --- .../API/Requests/GetChangelogLatestBuildsRequest.cs | 9 --------- osu.Game/Overlays/ChangelogOverlay.cs | 11 ++++++----- 2 files changed, 6 insertions(+), 14 deletions(-) delete mode 100644 osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs diff --git a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs b/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs deleted file mode 100644 index dd50701e39..0000000000 --- a/osu.Game/Online/API/Requests/GetChangelogLatestBuildsRequest.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Online.API.Requests -{ - public class GetChangelogLatestBuildsRequest : GetChangelogRequest - { - } -} diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index eb1d4ca69f..ddbd755696 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -108,11 +108,8 @@ namespace osu.Game.Overlays protected override void LoadComplete() { - var req = new GetChangelogLatestBuildsRequest(); - req.Success += res => badges.Populate(res.Streams); - api.Queue(req); - fetchListing(); base.LoadComplete(); + fetchListing(); } protected override void PopIn() @@ -166,7 +163,11 @@ namespace osu.Game.Overlays isAtListing = true; var req = new GetChangelogRequest(); badges.SelectNone(); - req.Success += res => listing.ShowListing(res.Builds); + req.Success += res => + { + listing.ShowListing(res.Builds); + badges.Populate(res.Streams); + }; api.Queue(req); } From 50c440de8d336130a69730bbcb642685399314ec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 17:01:17 +0900 Subject: [PATCH 0805/5608] Add toolbar button --- osu.Game/OsuGame.cs | 4 ++++ osu.Game/Overlays/Toolbar/Toolbar.cs | 1 + .../Toolbar/ToolbarChangelogButton.cs | 22 +++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 7b2a8184d1..679f067f22 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -76,6 +76,8 @@ namespace osu.Game private BeatmapSetOverlay beatmapSetOverlay; + private ChangelogOverlay changelogOverlay; + [Cached] private readonly ScreenshotManager screenshotManager = new ScreenshotManager(); @@ -448,6 +450,7 @@ namespace osu.Game loadComponentSingleFile(settings = new MainSettings { GetToolbarHeight = () => ToolbarOffset }, leftFloatingOverlayContent.Add); loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add); + loadComponentSingleFile(changelogOverlay = new ChangelogOverlay(), overlayContent.Add); loadComponentSingleFile(loginOverlay = new LoginOverlay { @@ -480,6 +483,7 @@ namespace osu.Game dependencies.Cache(notifications); dependencies.Cache(loginOverlay); dependencies.Cache(dialogOverlay); + dependencies.Cache(changelogOverlay); dependencies.Cache(accountCreation); chatOverlay.StateChanged += state => channelManager.HighPollRate.Value = state == Visibility.Visible; diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index a7f2a0e8d0..3c8b96fe8a 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -69,6 +69,7 @@ namespace osu.Game.Overlays.Toolbar AutoSizeAxes = Axes.X, Children = new Drawable[] { + new ToolbarChangelogButton(), new ToolbarDirectButton(), new ToolbarChatButton(), new ToolbarSocialButton(), diff --git a/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs new file mode 100644 index 0000000000..84210e27a4 --- /dev/null +++ b/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Overlays.Toolbar +{ + public class ToolbarChangelogButton : ToolbarOverlayToggleButton + { + public ToolbarChangelogButton() + { + SetIcon(FontAwesome.Solid.Bullhorn); + } + + [BackgroundDependencyLoader(true)] + private void load(ChangelogOverlay changelog) + { + StateContainer = changelog; + } + } +} From 4b508915f624d63bb6f262d93117fa3af85ab34e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 17:10:25 +0900 Subject: [PATCH 0806/5608] Centralise caching of components at OsuGame level --- osu.Game/OsuGame.cs | 67 ++++++++++--------------------- osu.Game/Screens/Menu/MainMenu.cs | 10 ++--- 2 files changed, 26 insertions(+), 51 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 7b2a8184d1..978e78663f 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -58,16 +58,8 @@ namespace osu.Game private ChannelManager channelManager; - private MusicController musicController; - private NotificationOverlay notifications; - private LoginOverlay loginOverlay; - - private DialogOverlay dialogOverlay; - - private AccountCreationOverlay accountCreation; - private DirectOverlay direct; private SocialOverlay social; @@ -91,7 +83,6 @@ namespace osu.Game private OsuScreenStack screenStack; private VolumeOverlay volume; - private OnScreenDisplay onscreenDisplay; private OsuLogo osuLogo; private MainMenu menuScreen; @@ -124,10 +115,6 @@ namespace osu.Game RavenLogger = new RavenLogger(this); } - public void ToggleSettings() => settings.ToggleVisibility(); - - public void ToggleDirect() => direct.ToggleVisibility(); - private void updateBlockingOverlayFade() => screenContainer.FadeColour(visibleBlockingOverlays.Any() ? OsuColour.Gray(0.5f) : Color4.White, 500, Easing.OutQuint); @@ -381,6 +368,8 @@ namespace osu.Game Container logoContainer; + dependencies.CacheAs(idleTracker = new GameIdleTracker(6000)); + AddRange(new Drawable[] { new VolumeControlReceptor @@ -402,7 +391,7 @@ namespace osu.Game rightFloatingOverlayContent = new Container { RelativeSizeAxes = Axes.Both }, leftFloatingOverlayContent = new Container { RelativeSizeAxes = Axes.Both }, topMostOverlayContent = new Container { RelativeSizeAxes = Axes.Both }, - idleTracker = new GameIdleTracker(6000) + idleTracker }); screenStack.ScreenPushed += screenPushed; @@ -429,59 +418,44 @@ namespace osu.Game }, topMostOverlayContent.Add); loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add); - loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add); + loadComponentSingleFile(new OnScreenDisplay(), Add, true); loadComponentSingleFile(notifications = new NotificationOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - }, rightFloatingOverlayContent.Add); + }, rightFloatingOverlayContent.Add, true); loadComponentSingleFile(screenshotManager, Add); //overlay elements - loadComponentSingleFile(direct = new DirectOverlay(), overlayContent.Add); - loadComponentSingleFile(social = new SocialOverlay(), overlayContent.Add); - loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal); - loadComponentSingleFile(chatOverlay = new ChatOverlay(), overlayContent.Add); - loadComponentSingleFile(settings = new MainSettings { GetToolbarHeight = () => ToolbarOffset }, leftFloatingOverlayContent.Add); - loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add); - loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add); + loadComponentSingleFile(direct = new DirectOverlay(), overlayContent.Add, true); + loadComponentSingleFile(social = new SocialOverlay(), overlayContent.Add, true); + loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal, true); + loadComponentSingleFile(chatOverlay = new ChatOverlay(), overlayContent.Add, true); + loadComponentSingleFile(settings = new MainSettings { GetToolbarHeight = () => ToolbarOffset }, leftFloatingOverlayContent.Add, true); + loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true); + loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true); - loadComponentSingleFile(loginOverlay = new LoginOverlay + loadComponentSingleFile(new LoginOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - }, rightFloatingOverlayContent.Add); + }, rightFloatingOverlayContent.Add, true); - loadComponentSingleFile(musicController = new MusicController + loadComponentSingleFile(new MusicController { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - }, rightFloatingOverlayContent.Add); + }, rightFloatingOverlayContent.Add, true); - loadComponentSingleFile(accountCreation = new AccountCreationOverlay(), topMostOverlayContent.Add); - loadComponentSingleFile(dialogOverlay = new DialogOverlay(), topMostOverlayContent.Add); + loadComponentSingleFile(new AccountCreationOverlay(), topMostOverlayContent.Add, true); + loadComponentSingleFile(new DialogOverlay(), topMostOverlayContent.Add, true); loadComponentSingleFile(externalLinkOpener = new ExternalLinkOpener(), topMostOverlayContent.Add); - dependencies.CacheAs(idleTracker); - dependencies.Cache(settings); - dependencies.Cache(onscreenDisplay); - dependencies.Cache(social); - dependencies.Cache(direct); - dependencies.Cache(chatOverlay); - dependencies.Cache(channelManager); - dependencies.Cache(userProfile); - dependencies.Cache(musicController); - dependencies.Cache(beatmapSetOverlay); - dependencies.Cache(notifications); - dependencies.Cache(loginOverlay); - dependencies.Cache(dialogOverlay); - dependencies.Cache(accountCreation); - chatOverlay.StateChanged += state => channelManager.HighPollRate.Value = state == Visibility.Visible; Add(externalLinkOpener = new ExternalLinkOpener()); @@ -610,9 +584,12 @@ namespace osu.Game private Task asyncLoadStream; - private void loadComponentSingleFile(T d, Action add) + private void loadComponentSingleFile(T d, Action add, bool cache = false) where T : Drawable { + if (cache) + dependencies.Cache(d); + // schedule is here to ensure that all component loads are done after LoadComplete is run (and thus all dependencies are cached). // with some better organisation of LoadComplete to do construction and dependency caching in one step, followed by calls to loadComponentSingleFile, // we could avoid the need for scheduling altogether. diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 21fc53be6e..788cad3bad 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -20,6 +20,7 @@ using osu.Game.Screens.Multi; using osu.Game.Screens.Select; using osu.Game.Screens.Tournament; using osu.Framework.Platform; +using osu.Game.Overlays; namespace osu.Game.Screens.Menu { @@ -45,7 +46,7 @@ namespace osu.Game.Screens.Menu protected override BackgroundScreen CreateBackground() => background; [BackgroundDependencyLoader(true)] - private void load(OsuGame game = null) + private void load(DirectOverlay direct, SettingsOverlay settings) { if (host.CanExit) AddInternal(new ExitConfirmOverlay { Action = this.Exit }); @@ -86,11 +87,8 @@ namespace osu.Game.Screens.Menu } }; - if (game != null) - { - buttons.OnSettings = game.ToggleSettings; - buttons.OnDirect = game.ToggleDirect; - } + buttons.OnSettings = () => settings?.ToggleVisibility(); + buttons.OnDirect = () => direct?.ToggleVisibility(); LoadComponentAsync(background = new BackgroundScreenDefault()); preloadSongSelect(); From 27ca0944212450417faf839fce80ca70e5123b70 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 17:14:52 +0900 Subject: [PATCH 0807/5608] Update outdated licence headers --- osu.Game.Tests/Visual/TestCaseLineBadge.cs | 4 ++-- osu.Game.Tests/Visual/TestCaseTextBadgePair.cs | 4 ++-- osu.Game/Graphics/StreamColour.cs | 4 ++-- osu.Game/Graphics/UserInterface/TooltipIconButton.cs | 4 ++-- osu.Game/Overlays/Changelog/ChangelogBadges.cs | 4 ++-- osu.Game/Overlays/Changelog/ChangelogContent.cs | 4 ++-- osu.Game/Overlays/Changelog/ChangelogContentGroup.cs | 4 ++-- osu.Game/Overlays/Changelog/ChangelogHeader.cs | 4 ++-- osu.Game/Overlays/Changelog/StreamBadge.cs | 4 ++-- osu.Game/Overlays/ChangelogOverlay.cs | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLineBadge.cs b/osu.Game.Tests/Visual/TestCaseLineBadge.cs index 06311ea7f9..ae94767640 100644 --- a/osu.Game.Tests/Visual/TestCaseLineBadge.cs +++ b/osu.Game.Tests/Visual/TestCaseLineBadge.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; diff --git a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs index bfd77ee3c7..3c461a2dd6 100644 --- a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs +++ b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; diff --git a/osu.Game/Graphics/StreamColour.cs b/osu.Game/Graphics/StreamColour.cs index c4df3b64a3..b7740c3be0 100644 --- a/osu.Game/Graphics/StreamColour.cs +++ b/osu.Game/Graphics/StreamColour.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Colour; using System.Collections.Generic; diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs index ce546c5358..7287794f89 100644 --- a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs +++ b/osu.Game/Graphics/UserInterface/TooltipIconButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Audio; diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index cf14ddbb01..372ef76351 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index e71769595f..fdc9fac404 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 837ce24522..0e846ae115 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index b14e065b1e..bae84bd4ac 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 424c344e91..6c3c95a2b3 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Audio; diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index ddbd755696..276ec622c7 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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.Allocation; using osu.Framework.Audio; From 4b8a9bae346b5c40a98cf767b51632c855dcdcd9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 17:17:20 +0900 Subject: [PATCH 0808/5608] Remove unused test case --- osu.Game.Tests/Visual/TestCaseCharLookup.cs | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 osu.Game.Tests/Visual/TestCaseCharLookup.cs diff --git a/osu.Game.Tests/Visual/TestCaseCharLookup.cs b/osu.Game.Tests/Visual/TestCaseCharLookup.cs deleted file mode 100644 index 0b9413f332..0000000000 --- a/osu.Game.Tests/Visual/TestCaseCharLookup.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Graphics.Sprites; - -namespace osu.Game.Tests.Visual -{ - public class TestCaseCharLookup : OsuTestCase - { - public TestCaseCharLookup() - { - AddStep("null", () => { }); - AddStep("display acharacter", () => Add(new OsuSpriteText { Text = "振込申請" })); - } - } -} From 8ecd1912e1da5ffdeb92c677af53aeb8bdea76d6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 17:24:33 +0900 Subject: [PATCH 0809/5608] Split out web response classes into own files --- .../Visual/TestCaseChangelogOverlay.cs | 2 +- .../Requests/Responses/APIChangelogBuild.cs | 98 ++----------------- .../Requests/Responses/APIChangelogEntry.cs | 47 +++++++++ .../Requests/Responses/APIChangelogIndex.cs | 2 +- .../Requests/Responses/APIChangelogUser.cs | 28 ++++++ .../API/Requests/Responses/APIUpdateStream.cs | 25 +++++ .../Overlays/Changelog/ChangelogBadges.cs | 4 +- .../Changelog/ChangelogContentGroup.cs | 14 +-- osu.Game/Overlays/Changelog/StreamBadge.cs | 4 +- osu.Game/Overlays/ChangelogOverlay.cs | 4 +- 10 files changed, 125 insertions(+), 103 deletions(-) create mode 100644 osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APIChangelogUser.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs diff --git a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs index 063555cf76..851cf17cfc 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual changelog.FetchAndShowBuild(new APIChangelogBuild { Version = "2018.712.0", - UpdateStream = new UpdateStream { Name = "lazer" }, + UpdateStream = new APIUpdateStream { Name = "lazer" }, }); changelog.Show(); }); diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs index 64b62e1f73..03c3ed0957 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs @@ -25,99 +25,21 @@ namespace osu.Game.Online.API.Requests.Responses public DateTimeOffset CreatedAt { get; set; } [JsonProperty("update_stream")] - public UpdateStream UpdateStream { get; set; } + public APIUpdateStream UpdateStream { get; set; } [JsonProperty("changelog_entries")] - public List ChangelogEntries { get; set; } + public List ChangelogEntries { get; set; } [JsonProperty("versions")] - public Versions Versions { get; set; } - } + public VersionNativation Versions { get; set; } - public class Versions - { - [JsonProperty("next")] - public APIChangelogBuild Next { get; set; } + public class VersionNativation + { + [JsonProperty("next")] + public APIChangelogBuild Next { get; set; } - [JsonProperty("previous")] - public APIChangelogBuild Previous { get; set; } - } - - public class ChangelogEntry - { - [JsonProperty("id")] - public long? Id { get; set; } - - [JsonProperty("repository")] - public string Repository { get; set; } - - [JsonProperty("github_pull_request_id")] - public long? GithubPullRequestId { get; set; } - - [JsonProperty("github_url")] - public string GithubUrl { get; set; } - - [JsonProperty("url")] - public string Url { get; set; } - - [JsonProperty("type")] - public string Type { get; set; } - - [JsonProperty("category")] - public string Category { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("message_html")] - public string MessageHtml { get; set; } - - [JsonProperty("major")] - public bool? Major { get; set; } - - [JsonProperty("created_at")] - public DateTimeOffset? CreatedAt { get; set; } - - [JsonProperty("github_user")] - public GithubUser GithubUser { get; set; } - } - - public class GithubUser - { - [JsonProperty("id")] - public long? Id { get; set; } - - [JsonProperty("display_name")] - public string DisplayName { get; set; } - - [JsonProperty("github_url")] - public string GithubUrl { get; set; } - - [JsonProperty("osu_username")] - public string OsuUsername { get; set; } - - [JsonProperty("user_id")] - public long? UserId { get; set; } - - [JsonProperty("user_url")] - public string UserUrl { get; set; } - } - - public class UpdateStream - { - [JsonProperty("id")] - public long Id { get; set; } - - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("is_featured")] - public bool IsFeatured { get; set; } - - [JsonProperty("display_name")] - public string DisplayName { get; set; } - - [JsonProperty("latest_build")] - public APIChangelogBuild LatestBuild { get; set; } + [JsonProperty("previous")] + public APIChangelogBuild Previous { get; set; } + } } } diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs new file mode 100644 index 0000000000..abaff9b7ae --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs @@ -0,0 +1,47 @@ +// 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 Newtonsoft.Json; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIChangelogEntry + { + [JsonProperty("id")] + public long? Id { get; set; } + + [JsonProperty("repository")] + public string Repository { get; set; } + + [JsonProperty("github_pull_request_id")] + public long? GithubPullRequestId { get; set; } + + [JsonProperty("github_url")] + public string GithubUrl { get; set; } + + [JsonProperty("url")] + public string Url { get; set; } + + [JsonProperty("type")] + public string Type { get; set; } + + [JsonProperty("category")] + public string Category { get; set; } + + [JsonProperty("title")] + public string Title { get; set; } + + [JsonProperty("message_html")] + public string MessageHtml { get; set; } + + [JsonProperty("major")] + public bool? Major { get; set; } + + [JsonProperty("created_at")] + public DateTimeOffset? CreatedAt { get; set; } + + [JsonProperty("github_user")] + public APIChangelogUser GithubUser { get; set; } + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs index 957694b887..2c31ba6659 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs @@ -9,6 +9,6 @@ namespace osu.Game.Online.API.Requests.Responses { public List Builds; - public List Streams; + public List Streams; } } diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogUser.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogUser.cs new file mode 100644 index 0000000000..5891391e83 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogUser.cs @@ -0,0 +1,28 @@ +// 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.Online.API.Requests.Responses +{ + public class APIChangelogUser + { + [JsonProperty("id")] + public long? Id { get; set; } + + [JsonProperty("display_name")] + public string DisplayName { get; set; } + + [JsonProperty("github_url")] + public string GithubUrl { get; set; } + + [JsonProperty("osu_username")] + public string OsuUsername { get; set; } + + [JsonProperty("user_id")] + public long? UserId { get; set; } + + [JsonProperty("user_url")] + public string UserUrl { get; set; } + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs new file mode 100644 index 0000000000..5cf56333bb --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.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.Online.API.Requests.Responses +{ + public class APIUpdateStream + { + [JsonProperty("id")] + public long Id { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("is_featured")] + public bool IsFeatured { get; set; } + + [JsonProperty("display_name")] + public string DisplayName { get; set; } + + [JsonProperty("latest_build")] + public APIChangelogBuild LatestBuild { get; set; } + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/ChangelogBadges.cs index 372ef76351..e95fa72f2e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBadges.cs @@ -45,9 +45,9 @@ namespace osu.Game.Overlays.Changelog }; } - public void Populate(List streams) + public void Populate(List streams) { - foreach (UpdateStream updateStream in streams) + foreach (APIUpdateStream updateStream in streams) { var streamBadge = new StreamBadge(updateStream); streamBadge.Selected += onBadgeSelected; diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 0e846ae115..e9ca025425 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -19,8 +19,8 @@ namespace osu.Game.Overlays.Changelog { private readonly TooltipIconButton chevronPrevious, chevronNext; - private readonly SortedDictionary> categories = - new SortedDictionary>(); + private readonly SortedDictionary> categories = + new SortedDictionary>(); public delegate void BuildSelectedEventHandler(APIChangelogBuild build, EventArgs args); @@ -204,18 +204,18 @@ namespace osu.Game.Overlays.Changelog BuildSelected?.Invoke(build, EventArgs.Empty); } - public void GenerateText(List changelogEntries) + public void GenerateText(List changelogEntries) { // sort entries by category - foreach (ChangelogEntry entry in changelogEntries) + foreach (APIChangelogEntry entry in changelogEntries) { if (!categories.ContainsKey(entry.Category)) - categories.Add(entry.Category, new List { entry }); + categories.Add(entry.Category, new List { entry }); else categories[entry.Category].Add(entry); } - foreach (KeyValuePair> category in categories) + foreach (KeyValuePair> category in categories) { ChangelogEntries.Add(new SpriteText { @@ -224,7 +224,7 @@ namespace osu.Game.Overlays.Changelog Margin = new MarginPadding { Top = 35, Bottom = 15 }, }); - foreach (ChangelogEntry entry in category.Value) + foreach (APIChangelogEntry entry in category.Value) { LinkFlowContainer title = new LinkFlowContainer { diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 6c3c95a2b3..b617ae8f53 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -32,11 +32,11 @@ namespace osu.Game.Overlays.Changelog private SampleChannel sampleClick; private SampleChannel sampleHover; - public readonly UpdateStream Stream; + public readonly APIUpdateStream Stream; private readonly FillFlowContainer text; - public StreamBadge(UpdateStream stream) + public StreamBadge(APIUpdateStream stream) { Stream = stream; diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 276ec622c7..e9fd5789ed 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -189,8 +189,8 @@ namespace osu.Game.Overlays /// /// Fetches and shows a specific build from a specific update stream. /// - /// Must contain at least and - /// . If and + /// Must contain at least and + /// . If and /// are specified, the header will instantly display them. /// Whether to update badges. Should be set to false in case /// the function is called by selecting a badge, to avoid an infinite loop. From d66a26cd116bc45f9fd240cefbfd0acfc7f727b8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 17:26:50 +0900 Subject: [PATCH 0810/5608] Add JsonProperty hinting --- osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs index 2c31ba6659..778e8754fe 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs @@ -2,13 +2,16 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using Newtonsoft.Json; namespace osu.Game.Online.API.Requests.Responses { public class APIChangelogIndex { + [JsonProperty] public List Builds; + [JsonProperty] public List Streams; } } From 66df784e9a7cc7b858a98dd81f272bde81f3af82 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 17:32:49 +0900 Subject: [PATCH 0811/5608] Adjust header image sizing --- osu.Game/Overlays/Changelog/ChangelogHeader.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index bae84bd4ac..0c92aa3755 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Changelog public event ListingSelectedEventHandler ListingSelected; - private const float cover_height = 280; + private const float cover_height = 150; private const float title_height = 50; private const float icon_size = 50; private const float icon_margin = 20; @@ -40,12 +40,22 @@ namespace osu.Game.Overlays.Changelog { RelativeSizeAxes = Axes.X; Height = cover_height; + Children = new Drawable[] { - coverImage = new Sprite + new Container { - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fill, + RelativeSizeAxes = Axes.X, + Height = cover_height, + Masking = true, + Children = new Drawable[] + { + coverImage = new Sprite + { + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fill, + }, + } }, new Container { From 92f6f4d21a858ad6319c7849e6cab33d5a5a6282 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 19:04:12 +0900 Subject: [PATCH 0812/5608] Apply same fix to other methods which were missed --- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 46a6197546..a5c3d8a4de 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -410,7 +410,14 @@ namespace osu.Game.Beatmaps.Formats var existing = beatmap.ControlPointInfo.TimingPointAt(newPoint.Time); if (existing.Time == newPoint.Time) + { + // autogenerated points should not replace non-autogenerated. + // this allows for incorrectly ordered timing points to still be correctly handled. + if (newPoint.AutoGenerated && !existing.AutoGenerated) + return; + beatmap.ControlPointInfo.TimingPoints.Remove(existing); + } beatmap.ControlPointInfo.TimingPoints.Add(newPoint); } @@ -422,13 +429,15 @@ namespace osu.Game.Beatmaps.Formats if (newPoint.EquivalentTo(existing)) return; - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - if (existing.Time == newPoint.Time) + { + // autogenerated points should not replace non-autogenerated. + // this allows for incorrectly ordered timing points to still be correctly handled. + if (newPoint.AutoGenerated && !existing.AutoGenerated) + return; + beatmap.ControlPointInfo.DifficultyPoints.Remove(existing); + } beatmap.ControlPointInfo.DifficultyPoints.Add(newPoint); } @@ -441,7 +450,14 @@ namespace osu.Game.Beatmaps.Formats return; if (existing.Time == newPoint.Time) + { + // autogenerated points should not replace non-autogenerated. + // this allows for incorrectly ordered timing points to still be correctly handled. + if (newPoint.AutoGenerated && !existing.AutoGenerated) + return; + beatmap.ControlPointInfo.EffectPoints.Remove(existing); + } beatmap.ControlPointInfo.EffectPoints.Add(newPoint); } @@ -454,7 +470,14 @@ namespace osu.Game.Beatmaps.Formats return; if (existing.Time == newPoint.Time) + { + // autogenerated points should not replace non-autogenerated. + // this allows for incorrectly ordered timing points to still be correctly handled. + if (newPoint.AutoGenerated && !existing.AutoGenerated) + return; + beatmap.ControlPointInfo.SamplePoints.Remove(existing); + } beatmap.ControlPointInfo.SamplePoints.Add(newPoint); } From 1809c996bbede491ce99aea838122e589f770c3e Mon Sep 17 00:00:00 2001 From: HoLLy Date: Mon, 13 May 2019 12:09:19 +0200 Subject: [PATCH 0813/5608] Use Interpolation.ValueAt instead of manually interpolating FL position. --- osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index c3c1e86c18..084959f775 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -37,7 +37,6 @@ namespace osu.Game.Rulesets.Osu.Mods private class OsuFlashlight : Flashlight, IRequireHighFrequencyMousePosition { private const double follow_delay = 120; - private double lastPositionUpdate; public OsuFlashlight() { @@ -55,13 +54,8 @@ namespace osu.Game.Rulesets.Osu.Mods var position = FlashlightPosition; var destination = e.MousePosition; - double frameTime = Clock.CurrentTime - lastPositionUpdate; - double interp = Interpolation.ApplyEasing(Easing.Out, MathHelper.Clamp(frameTime / follow_delay, 0, 1)); - FlashlightPosition = new Vector2( - (float)Interpolation.Lerp(position.X, destination.X, interp), - (float)Interpolation.Lerp(position.Y, destination.Y, interp) - ); - lastPositionUpdate = Clock.CurrentTime; + FlashlightPosition = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); + return base.OnMouseMove(e); } From d18504bfe0b82e622f0eb6bcc0d8f013eefb0246 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 19:23:38 +0900 Subject: [PATCH 0814/5608] Attempt to fix pause test failures by reducing steps --- osu.Game.Tests/Visual/Gameplay/TestCasePause.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs index 53ac990183..1a6d58909d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs @@ -86,8 +86,8 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("move cursor outside", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft - new Vector2(10))); pauseAndConfirm(); - resumeAndConfirm(); + resume(); pause(); confirmClockRunning(true); From 647e2c297cb91288df121bf4577a792537ce4012 Mon Sep 17 00:00:00 2001 From: Xie Yi Date: Tue, 14 May 2019 02:45:12 +0800 Subject: [PATCH 0815/5608] Fix iOS app entry for raw keyboard input --- osu.iOS/Application.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS/Application.cs b/osu.iOS/Application.cs index cb75e5c159..30e0e15ad1 100644 --- a/osu.iOS/Application.cs +++ b/osu.iOS/Application.cs @@ -9,7 +9,7 @@ namespace osu.iOS { public static void Main(string[] args) { - UIApplication.Main(args, null, "AppDelegate"); + UIApplication.Main(args, "GameUIApplication", "AppDelegate"); } } } From 7aa10956b582f741f006f4df959041c5b873f93a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 May 2019 09:46:42 +0900 Subject: [PATCH 0816/5608] Add unit test --- .../Formats/LegacyBeatmapDecoderTest.cs | 28 +++++++++++++++++++ .../Resources/overlapping-control-points.osu | 11 ++++++++ 2 files changed, 39 insertions(+) create mode 100644 osu.Game.Tests/Resources/overlapping-control-points.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 3c1f48b7a4..7e7ddb12d2 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -194,6 +194,34 @@ namespace osu.Game.Tests.Beatmaps.Formats } } + [Test] + public void TestDecodeOverlappingTimingPoints() + { + var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + + using (var resStream = TestResources.OpenResource("overlapping-control-points.osu")) + using (var stream = new StreamReader(resStream)) + { + var controlPoints = decoder.Decode(stream).ControlPointInfo; + + Assert.That(controlPoints.DifficultyPoints, Has.Count.EqualTo(2)); + Assert.That(controlPoints.DifficultyPoints[0].SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); + Assert.That(controlPoints.DifficultyPoints[1].SpeedMultiplier, Is.EqualTo(0.75).Within(0.1)); + + Assert.That(controlPoints.EffectPoints, Has.Count.EqualTo(2)); + Assert.That(controlPoints.EffectPoints[0].KiaiMode, Is.True); + Assert.That(controlPoints.EffectPoints[1].KiaiMode, Is.True); + + Assert.That(controlPoints.SamplePoints, Has.Count.EqualTo(2)); + Assert.That(controlPoints.SamplePoints[0].SampleBank, Is.EqualTo("drum")); + Assert.That(controlPoints.SamplePoints[1].SampleBank, Is.EqualTo("normal")); + + Assert.That(controlPoints.TimingPoints, Has.Count.EqualTo(2)); + Assert.That(controlPoints.TimingPoints[0].BeatLength, Is.EqualTo(500)); + Assert.That(controlPoints.TimingPoints[1].BeatLength, Is.EqualTo(250)); + } + } + [Test] public void TestDecodeBeatmapColours() { diff --git a/osu.Game.Tests/Resources/overlapping-control-points.osu b/osu.Game.Tests/Resources/overlapping-control-points.osu new file mode 100644 index 0000000000..d96db72bd7 --- /dev/null +++ b/osu.Game.Tests/Resources/overlapping-control-points.osu @@ -0,0 +1,11 @@ +osu file format v14 + +[TimingPoints] + +// Timing -> Inherited +0,500,4,2,0,100,1,0 +0,-66.6666666666667,4,3,0,100,0,1 + +// Inherited -> Timing +1000,-133.333333333333,4,1,0,100,0,1 +1000,250,4,2,0,100,1,0 From 19bc6b72cc7ef1a9a059322ae0e76ed19b601705 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 May 2019 10:13:42 +0900 Subject: [PATCH 0817/5608] More tests to showcase failures --- .../Formats/LegacyBeatmapDecoderTest.cs | 28 +++++++++++-------- .../Resources/overlapping-control-points.osu | 16 ++++++++--- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 7e7ddb12d2..42e421d1ad 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -204,21 +204,25 @@ namespace osu.Game.Tests.Beatmaps.Formats { var controlPoints = decoder.Decode(stream).ControlPointInfo; - Assert.That(controlPoints.DifficultyPoints, Has.Count.EqualTo(2)); - Assert.That(controlPoints.DifficultyPoints[0].SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); - Assert.That(controlPoints.DifficultyPoints[1].SpeedMultiplier, Is.EqualTo(0.75).Within(0.1)); + Assert.That(controlPoints.DifficultyPointAt(500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); + Assert.That(controlPoints.DifficultyPointAt(1500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); + Assert.That(controlPoints.DifficultyPointAt(2500).SpeedMultiplier, Is.EqualTo(0.75).Within(0.1)); + Assert.That(controlPoints.DifficultyPointAt(3500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); - Assert.That(controlPoints.EffectPoints, Has.Count.EqualTo(2)); - Assert.That(controlPoints.EffectPoints[0].KiaiMode, Is.True); - Assert.That(controlPoints.EffectPoints[1].KiaiMode, Is.True); + Assert.That(controlPoints.EffectPointAt(500).KiaiMode, Is.True); + Assert.That(controlPoints.EffectPointAt(1500).KiaiMode, Is.True); + Assert.That(controlPoints.EffectPointAt(2500).KiaiMode, Is.False); + Assert.That(controlPoints.EffectPointAt(3500).KiaiMode, Is.True); - Assert.That(controlPoints.SamplePoints, Has.Count.EqualTo(2)); - Assert.That(controlPoints.SamplePoints[0].SampleBank, Is.EqualTo("drum")); - Assert.That(controlPoints.SamplePoints[1].SampleBank, Is.EqualTo("normal")); + Assert.That(controlPoints.SamplePointAt(500).SampleBank, Is.EqualTo("drum")); + Assert.That(controlPoints.SamplePointAt(1500).SampleBank, Is.EqualTo("drum")); + Assert.That(controlPoints.SamplePointAt(2500).SampleBank, Is.EqualTo("normal")); + Assert.That(controlPoints.SamplePointAt(3500).SampleBank, Is.EqualTo("drum")); - Assert.That(controlPoints.TimingPoints, Has.Count.EqualTo(2)); - Assert.That(controlPoints.TimingPoints[0].BeatLength, Is.EqualTo(500)); - Assert.That(controlPoints.TimingPoints[1].BeatLength, Is.EqualTo(250)); + Assert.That(controlPoints.TimingPointAt(500).BeatLength, Is.EqualTo(500)); + Assert.That(controlPoints.TimingPointAt(1500).BeatLength, Is.EqualTo(500)); + Assert.That(controlPoints.TimingPointAt(2500).BeatLength, Is.EqualTo(250)); + Assert.That(controlPoints.TimingPointAt(3500).BeatLength, Is.EqualTo(500)); } } diff --git a/osu.Game.Tests/Resources/overlapping-control-points.osu b/osu.Game.Tests/Resources/overlapping-control-points.osu index d96db72bd7..31d38a3d01 100644 --- a/osu.Game.Tests/Resources/overlapping-control-points.osu +++ b/osu.Game.Tests/Resources/overlapping-control-points.osu @@ -2,10 +2,18 @@ osu file format v14 [TimingPoints] -// Timing -> Inherited +// Timing then inherited 0,500,4,2,0,100,1,0 0,-66.6666666666667,4,3,0,100,0,1 -// Inherited -> Timing -1000,-133.333333333333,4,1,0,100,0,1 -1000,250,4,2,0,100,1,0 +// Inherited then timing (equivalent to previous) +1000,-66.6666666666667,4,3,0,100,0,1 +1000,500,4,2,0,100,1,0 + +// Inherited then timing (different to previous) +2000,-133.333333333333,4,1,0,100,0,0 +2000,250,4,2,0,100,1,0 + +// Timing then inherited (different to previous) +3000,500,4,2,0,100,1,0 +3000,-66.6666666666667,4,3,0,100,0,1 From 7553e2da25b5ff1de4eb1633dae7d6bc805e2c7e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 10:45:05 +0900 Subject: [PATCH 0818/5608] Fix incorrect DI reference and update naming of SettingsOverlay classes --- .../Settings/TestCaseKeyConfiguration.cs | 6 +- .../Visual/Settings/TestCaseSettings.cs | 4 +- osu.Game/OsuGame.cs | 6 +- .../KeyBinding/KeyBindingsSubsection.cs | 2 +- ...eyBindingOverlay.cs => KeyBindingPanel.cs} | 4 +- osu.Game/Overlays/MainSettings.cs | 77 ------ .../Sections/Input/KeyboardSettings.cs | 2 +- .../Settings/Sections/InputSection.cs | 2 +- osu.Game/Overlays/Settings/SettingsButton.cs | 2 +- osu.Game/Overlays/Settings/SettingsHeader.cs | 4 +- osu.Game/Overlays/Settings/SettingsItem.cs | 6 +- osu.Game/Overlays/Settings/SettingsSection.cs | 2 +- .../Overlays/Settings/SettingsSubsection.cs | 2 +- osu.Game/Overlays/SettingsOverlay.cs | 257 ++++-------------- osu.Game/Overlays/SettingsPanel.cs | 224 +++++++++++++++ .../Overlays/Toolbar/ToolbarSettingsButton.cs | 2 +- 16 files changed, 301 insertions(+), 301 deletions(-) rename osu.Game/Overlays/{KeyBindingOverlay.cs => KeyBindingPanel.cs} (97%) delete mode 100644 osu.Game/Overlays/MainSettings.cs create mode 100644 osu.Game/Overlays/SettingsPanel.cs diff --git a/osu.Game.Tests/Visual/Settings/TestCaseKeyConfiguration.cs b/osu.Game.Tests/Visual/Settings/TestCaseKeyConfiguration.cs index ce179c21ba..fccd48b85c 100644 --- a/osu.Game.Tests/Visual/Settings/TestCaseKeyConfiguration.cs +++ b/osu.Game.Tests/Visual/Settings/TestCaseKeyConfiguration.cs @@ -9,17 +9,17 @@ namespace osu.Game.Tests.Visual.Settings [TestFixture] public class TestCaseKeyConfiguration : OsuTestCase { - private readonly KeyBindingOverlay overlay; + private readonly KeyBindingPanel panel; public TestCaseKeyConfiguration() { - Child = overlay = new KeyBindingOverlay(); + Child = panel = new KeyBindingPanel(); } protected override void LoadComplete() { base.LoadComplete(); - overlay.Show(); + panel.Show(); } } } diff --git a/osu.Game.Tests/Visual/Settings/TestCaseSettings.cs b/osu.Game.Tests/Visual/Settings/TestCaseSettings.cs index e846d5c020..5b6c033c1d 100644 --- a/osu.Game.Tests/Visual/Settings/TestCaseSettings.cs +++ b/osu.Game.Tests/Visual/Settings/TestCaseSettings.cs @@ -11,12 +11,12 @@ namespace osu.Game.Tests.Visual.Settings [TestFixture] public class TestCaseSettings : OsuTestCase { - private readonly SettingsOverlay settings; + private readonly SettingsPanel settings; private readonly DialogOverlay dialogOverlay; public TestCaseSettings() { - settings = new MainSettings + settings = new SettingsOverlay { State = Visibility.Visible }; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 978e78663f..6fe91181fb 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -95,7 +95,7 @@ namespace osu.Game private readonly string[] args; - private SettingsOverlay settings; + private SettingsPanel settings; private readonly List overlays = new List(); @@ -434,7 +434,7 @@ namespace osu.Game loadComponentSingleFile(social = new SocialOverlay(), overlayContent.Add, true); loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal, true); loadComponentSingleFile(chatOverlay = new ChatOverlay(), overlayContent.Add, true); - loadComponentSingleFile(settings = new MainSettings { GetToolbarHeight = () => ToolbarOffset }, leftFloatingOverlayContent.Add, true); + loadComponentSingleFile(settings = new SettingsOverlay { GetToolbarHeight = () => ToolbarOffset }, leftFloatingOverlayContent.Add, true); loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true); @@ -518,7 +518,7 @@ namespace osu.Game if (notifications.State == Visibility.Visible) offset -= ToolbarButton.WIDTH / 2; - screenContainer.MoveToX(offset, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint); + screenContainer.MoveToX(offset, SettingsPanel.TRANSITION_LENGTH, Easing.OutQuint); } settings.StateChanged += _ => updateScreenOffset(); diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs index 53cb3edeca..08288516e3 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.KeyBinding this.variant = variant; FlowContent.Spacing = new Vector2(0, 1); - FlowContent.Padding = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS }; + FlowContent.Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS, Right = SettingsPanel.CONTENT_MARGINS }; } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/KeyBindingOverlay.cs b/osu.Game/Overlays/KeyBindingPanel.cs similarity index 97% rename from osu.Game/Overlays/KeyBindingOverlay.cs rename to osu.Game/Overlays/KeyBindingPanel.cs index b223d4701d..301c8faca2 100644 --- a/osu.Game/Overlays/KeyBindingOverlay.cs +++ b/osu.Game/Overlays/KeyBindingPanel.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Overlays { - public class KeyBindingOverlay : SettingsOverlay + public class KeyBindingPanel : SettingsPanel { protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); @@ -38,7 +38,7 @@ namespace osu.Game.Overlays }); } - public KeyBindingOverlay() + public KeyBindingPanel() : base(true) { } diff --git a/osu.Game/Overlays/MainSettings.cs b/osu.Game/Overlays/MainSettings.cs deleted file mode 100644 index 39bfdfd4d6..0000000000 --- a/osu.Game/Overlays/MainSettings.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Overlays.Settings; -using osu.Game.Overlays.Settings.Sections; -using osuTK.Graphics; -using System.Collections.Generic; - -namespace osu.Game.Overlays -{ - public class MainSettings : SettingsOverlay - { - private readonly KeyBindingOverlay keyBindingOverlay; - - protected override IEnumerable CreateSections() => new SettingsSection[] - { - new GeneralSection(), - new GraphicsSection(), - new GameplaySection(), - new AudioSection(), - new SkinSection(), - new InputSection(keyBindingOverlay), - new OnlineSection(), - new MaintenanceSection(), - new DebugSection(), - }; - - protected override Drawable CreateHeader() => new SettingsHeader("settings", "Change the way osu! behaves"); - protected override Drawable CreateFooter() => new SettingsFooter(); - - public MainSettings() - : base(true) - { - keyBindingOverlay = new KeyBindingOverlay - { - Depth = 1, - Anchor = Anchor.TopRight, - }; - keyBindingOverlay.StateChanged += keyBindingOverlay_StateChanged; - } - - public override bool AcceptsFocus => keyBindingOverlay.State != Visibility.Visible; - - private void keyBindingOverlay_StateChanged(Visibility visibility) - { - switch (visibility) - { - case Visibility.Visible: - Background.FadeTo(0.9f, 300, Easing.OutQuint); - Sidebar?.FadeColour(Color4.DarkGray, 300, Easing.OutQuint); - - SectionsContainer.FadeOut(300, Easing.OutQuint); - ContentContainer.MoveToX(-WIDTH, 500, Easing.OutQuint); - break; - - case Visibility.Hidden: - Background.FadeTo(0.6f, 500, Easing.OutQuint); - Sidebar?.FadeColour(Color4.White, 300, Easing.OutQuint); - - SectionsContainer.FadeIn(500, Easing.OutQuint); - ContentContainer.MoveToX(0, 500, Easing.OutQuint); - break; - } - } - - protected override float ExpandedPosition => keyBindingOverlay.State == Visibility.Visible ? -WIDTH : base.ExpandedPosition; - - [BackgroundDependencyLoader] - private void load() - { - ContentContainer.Add(keyBindingOverlay); - } - } -} diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs index 3f1e77d482..55c7210d6c 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs @@ -9,7 +9,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input { protected override string Header => "Keyboard"; - public KeyboardSettings(KeyBindingOverlay keyConfig) + public KeyboardSettings(KeyBindingPanel keyConfig) { Children = new Drawable[] { diff --git a/osu.Game/Overlays/Settings/Sections/InputSection.cs b/osu.Game/Overlays/Settings/Sections/InputSection.cs index 6a3f8783b0..2a348b4e03 100644 --- a/osu.Game/Overlays/Settings/Sections/InputSection.cs +++ b/osu.Game/Overlays/Settings/Sections/InputSection.cs @@ -12,7 +12,7 @@ namespace osu.Game.Overlays.Settings.Sections public override string Header => "Input"; public override IconUsage Icon => FontAwesome.Regular.Keyboard; - public InputSection(KeyBindingOverlay keyConfig) + public InputSection(KeyBindingPanel keyConfig) { Children = new Drawable[] { diff --git a/osu.Game/Overlays/Settings/SettingsButton.cs b/osu.Game/Overlays/Settings/SettingsButton.cs index ef98c28285..088d69c031 100644 --- a/osu.Game/Overlays/Settings/SettingsButton.cs +++ b/osu.Game/Overlays/Settings/SettingsButton.cs @@ -14,7 +14,7 @@ namespace osu.Game.Overlays.Settings public SettingsButton() { RelativeSizeAxes = Axes.X; - Padding = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS }; + Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS, Right = SettingsPanel.CONTENT_MARGINS }; } public string TooltipText { get; set; } diff --git a/osu.Game/Overlays/Settings/SettingsHeader.cs b/osu.Game/Overlays/Settings/SettingsHeader.cs index fbf29f7ff5..d8ec00bd99 100644 --- a/osu.Game/Overlays/Settings/SettingsHeader.cs +++ b/osu.Game/Overlays/Settings/SettingsHeader.cs @@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Settings Font = OsuFont.GetFont(size: 40), Margin = new MarginPadding { - Left = SettingsOverlay.CONTENT_MARGINS, + Left = SettingsPanel.CONTENT_MARGINS, Top = Toolbar.Toolbar.TOOLTIP_HEIGHT }, }, @@ -52,7 +52,7 @@ namespace osu.Game.Overlays.Settings Font = OsuFont.GetFont(size: 18), Margin = new MarginPadding { - Left = SettingsOverlay.CONTENT_MARGINS, + Left = SettingsPanel.CONTENT_MARGINS, Bottom = 30 }, }, diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 4b64f942bf..4776cd6442 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -87,7 +87,7 @@ namespace osu.Game.Overlays.Settings { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Padding = new MarginPadding { Right = SettingsOverlay.CONTENT_MARGINS }; + Padding = new MarginPadding { Right = SettingsPanel.CONTENT_MARGINS }; InternalChildren = new Drawable[] { @@ -96,7 +96,7 @@ namespace osu.Game.Overlays.Settings { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS }, + Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS }, Child = Control = CreateControl() }, }; @@ -131,7 +131,7 @@ namespace osu.Game.Overlays.Settings public RestoreDefaultValueButton() { RelativeSizeAxes = Axes.Y; - Width = SettingsOverlay.CONTENT_MARGINS; + Width = SettingsPanel.CONTENT_MARGINS; Alpha = 0f; } diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index e92f28d5d2..c878a9fc65 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -83,7 +83,7 @@ namespace osu.Game.Overlays.Settings Font = OsuFont.GetFont(size: header_size), Text = Header, Colour = colours.Yellow, - Margin = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS } + Margin = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS, Right = SettingsPanel.CONTENT_MARGINS } }, FlowContent } diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index a1b4d8b131..c9c763e8d4 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -53,7 +53,7 @@ namespace osu.Game.Overlays.Settings new OsuSpriteText { Text = Header.ToUpperInvariant(), - Margin = new MarginPadding { Bottom = 10, Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS }, + Margin = new MarginPadding { Bottom = 10, Left = SettingsPanel.CONTENT_MARGINS, Right = SettingsPanel.CONTENT_MARGINS }, Font = OsuFont.GetFont(weight: FontWeight.Black), }, FlowContent diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 174d3a3de1..4f3a71a1b3 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -1,224 +1,77 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using System.Collections.Generic; -using System.Linq; -using osuTK; -using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; +using osu.Game.Overlays.Settings.Sections; +using osuTK.Graphics; +using System.Collections.Generic; namespace osu.Game.Overlays { - public abstract class SettingsOverlay : OsuFocusedOverlayContainer + public class SettingsOverlay : SettingsPanel { - public const float CONTENT_MARGINS = 15; + private readonly KeyBindingPanel keyBindingPanel; - public const float TRANSITION_LENGTH = 600; - - private const float sidebar_width = Sidebar.DEFAULT_WIDTH; - - protected const float WIDTH = 400; - - private const float sidebar_padding = 10; - - protected Container ContentContainer; - - protected override Container Content => ContentContainer; - - protected Sidebar Sidebar; - private SidebarButton selectedSidebarButton; - - protected SettingsSectionsContainer SectionsContainer; - - private SearchTextBox searchTextBox; - - /// - /// Provide a source for the toolbar height. - /// - public Func GetToolbarHeight; - - private readonly bool showSidebar; - - protected Box Background; - - protected SettingsOverlay(bool showSidebar) + protected override IEnumerable CreateSections() => new SettingsSection[] { - this.showSidebar = showSidebar; - RelativeSizeAxes = Axes.Y; - AutoSizeAxes = Axes.X; + new GeneralSection(), + new GraphicsSection(), + new GameplaySection(), + new AudioSection(), + new SkinSection(), + new InputSection(keyBindingPanel), + new OnlineSection(), + new MaintenanceSection(), + new DebugSection(), + }; + + protected override Drawable CreateHeader() => new SettingsHeader("settings", "Change the way osu! behaves"); + protected override Drawable CreateFooter() => new SettingsFooter(); + + public SettingsOverlay() + : base(true) + { + keyBindingPanel = new KeyBindingPanel + { + Depth = 1, + Anchor = Anchor.TopRight, + }; + keyBindingPanel.StateChanged += keyBindingPanelStateChanged; } - protected virtual IEnumerable CreateSections() => null; + public override bool AcceptsFocus => keyBindingPanel.State != Visibility.Visible; + + private void keyBindingPanelStateChanged(Visibility visibility) + { + switch (visibility) + { + case Visibility.Visible: + Background.FadeTo(0.9f, 300, Easing.OutQuint); + Sidebar?.FadeColour(Color4.DarkGray, 300, Easing.OutQuint); + + SectionsContainer.FadeOut(300, Easing.OutQuint); + ContentContainer.MoveToX(-WIDTH, 500, Easing.OutQuint); + break; + + case Visibility.Hidden: + Background.FadeTo(0.6f, 500, Easing.OutQuint); + Sidebar?.FadeColour(Color4.White, 300, Easing.OutQuint); + + SectionsContainer.FadeIn(500, Easing.OutQuint); + ContentContainer.MoveToX(0, 500, Easing.OutQuint); + break; + } + } + + protected override float ExpandedPosition => keyBindingPanel.State == Visibility.Visible ? -WIDTH : base.ExpandedPosition; [BackgroundDependencyLoader] private void load() { - InternalChild = ContentContainer = new Container - { - Width = WIDTH, - RelativeSizeAxes = Axes.Y, - Children = new Drawable[] - { - Background = new Box - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Scale = new Vector2(2, 1), // over-extend to the left for transitions - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.6f, - }, - SectionsContainer = new SettingsSectionsContainer - { - Masking = true, - RelativeSizeAxes = Axes.Both, - ExpandableHeader = CreateHeader(), - FixedHeader = searchTextBox = new SearchTextBox - { - RelativeSizeAxes = Axes.X, - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Width = 0.95f, - Margin = new MarginPadding - { - Top = 20, - Bottom = 20 - }, - Exit = Hide, - }, - Footer = CreateFooter() - }, - } - }; - - if (showSidebar) - { - AddInternal(Sidebar = new Sidebar { Width = sidebar_width }); - - SectionsContainer.SelectedSection.ValueChanged += section => - { - selectedSidebarButton.Selected = false; - selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section.NewValue); - selectedSidebarButton.Selected = true; - }; - } - - searchTextBox.Current.ValueChanged += term => SectionsContainer.SearchContainer.SearchTerm = term.NewValue; - - CreateSections()?.ForEach(AddSection); - } - - protected void AddSection(SettingsSection section) - { - SectionsContainer.Add(section); - - if (Sidebar != null) - { - var button = new SidebarButton - { - Section = section, - Action = s => - { - SectionsContainer.ScrollTo(s); - Sidebar.State = ExpandedState.Contracted; - }, - }; - - Sidebar.Add(button); - - if (selectedSidebarButton == null) - { - selectedSidebarButton = Sidebar.Children.First(); - selectedSidebarButton.Selected = true; - } - } - } - - protected virtual Drawable CreateHeader() => new Container(); - - protected virtual Drawable CreateFooter() => new Container(); - - protected override void PopIn() - { - base.PopIn(); - - ContentContainer.MoveToX(ExpandedPosition, TRANSITION_LENGTH, Easing.OutQuint); - - Sidebar?.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); - this.FadeTo(1, TRANSITION_LENGTH, Easing.OutQuint); - - searchTextBox.HoldFocus = true; - } - - protected virtual float ExpandedPosition => 0; - - protected override void PopOut() - { - base.PopOut(); - - ContentContainer.MoveToX(-WIDTH, TRANSITION_LENGTH, Easing.OutQuint); - - Sidebar?.MoveToX(-sidebar_width, TRANSITION_LENGTH, Easing.OutQuint); - this.FadeTo(0, TRANSITION_LENGTH, Easing.OutQuint); - - searchTextBox.HoldFocus = false; - if (searchTextBox.HasFocus) - GetContainingInputManager().ChangeFocus(null); - } - - public override bool AcceptsFocus => true; - - protected override void OnFocus(FocusEvent e) - { - searchTextBox.TakeFocus(); - base.OnFocus(e); - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - ContentContainer.Margin = new MarginPadding { Left = Sidebar?.DrawWidth ?? 0 }; - ContentContainer.Padding = new MarginPadding { Top = GetToolbarHeight?.Invoke() ?? 0 }; - } - - protected class SettingsSectionsContainer : SectionsContainer - { - public SearchContainer SearchContainer; - - protected override FlowContainer CreateScrollContentContainer() - => SearchContainer = new SearchContainer - { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Direction = FillDirection.Vertical, - }; - - public SettingsSectionsContainer() - { - HeaderBackground = new Box - { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both - }; - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - // no null check because the usage of this class is strict - HeaderBackground.Alpha = -ExpandableHeader.Y / ExpandableHeader.LayoutSize.Y * 0.5f; - } + ContentContainer.Add(keyBindingPanel); } } } diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs new file mode 100644 index 0000000000..85b74c0fad --- /dev/null +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -0,0 +1,224 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using osuTK; +using osuTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Settings; + +namespace osu.Game.Overlays +{ + public abstract class SettingsPanel : OsuFocusedOverlayContainer + { + public const float CONTENT_MARGINS = 15; + + public const float TRANSITION_LENGTH = 600; + + private const float sidebar_width = Sidebar.DEFAULT_WIDTH; + + protected const float WIDTH = 400; + + private const float sidebar_padding = 10; + + protected Container ContentContainer; + + protected override Container Content => ContentContainer; + + protected Sidebar Sidebar; + private SidebarButton selectedSidebarButton; + + protected SettingsSectionsContainer SectionsContainer; + + private SearchTextBox searchTextBox; + + /// + /// Provide a source for the toolbar height. + /// + public Func GetToolbarHeight; + + private readonly bool showSidebar; + + protected Box Background; + + protected SettingsPanel(bool showSidebar) + { + this.showSidebar = showSidebar; + RelativeSizeAxes = Axes.Y; + AutoSizeAxes = Axes.X; + } + + protected virtual IEnumerable CreateSections() => null; + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = ContentContainer = new Container + { + Width = WIDTH, + RelativeSizeAxes = Axes.Y, + Children = new Drawable[] + { + Background = new Box + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Scale = new Vector2(2, 1), // over-extend to the left for transitions + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.6f, + }, + SectionsContainer = new SettingsSectionsContainer + { + Masking = true, + RelativeSizeAxes = Axes.Both, + ExpandableHeader = CreateHeader(), + FixedHeader = searchTextBox = new SearchTextBox + { + RelativeSizeAxes = Axes.X, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Width = 0.95f, + Margin = new MarginPadding + { + Top = 20, + Bottom = 20 + }, + Exit = Hide, + }, + Footer = CreateFooter() + }, + } + }; + + if (showSidebar) + { + AddInternal(Sidebar = new Sidebar { Width = sidebar_width }); + + SectionsContainer.SelectedSection.ValueChanged += section => + { + selectedSidebarButton.Selected = false; + selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section.NewValue); + selectedSidebarButton.Selected = true; + }; + } + + searchTextBox.Current.ValueChanged += term => SectionsContainer.SearchContainer.SearchTerm = term.NewValue; + + CreateSections()?.ForEach(AddSection); + } + + protected void AddSection(SettingsSection section) + { + SectionsContainer.Add(section); + + if (Sidebar != null) + { + var button = new SidebarButton + { + Section = section, + Action = s => + { + SectionsContainer.ScrollTo(s); + Sidebar.State = ExpandedState.Contracted; + }, + }; + + Sidebar.Add(button); + + if (selectedSidebarButton == null) + { + selectedSidebarButton = Sidebar.Children.First(); + selectedSidebarButton.Selected = true; + } + } + } + + protected virtual Drawable CreateHeader() => new Container(); + + protected virtual Drawable CreateFooter() => new Container(); + + protected override void PopIn() + { + base.PopIn(); + + ContentContainer.MoveToX(ExpandedPosition, TRANSITION_LENGTH, Easing.OutQuint); + + Sidebar?.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); + this.FadeTo(1, TRANSITION_LENGTH, Easing.OutQuint); + + searchTextBox.HoldFocus = true; + } + + protected virtual float ExpandedPosition => 0; + + protected override void PopOut() + { + base.PopOut(); + + ContentContainer.MoveToX(-WIDTH, TRANSITION_LENGTH, Easing.OutQuint); + + Sidebar?.MoveToX(-sidebar_width, TRANSITION_LENGTH, Easing.OutQuint); + this.FadeTo(0, TRANSITION_LENGTH, Easing.OutQuint); + + searchTextBox.HoldFocus = false; + if (searchTextBox.HasFocus) + GetContainingInputManager().ChangeFocus(null); + } + + public override bool AcceptsFocus => true; + + protected override void OnFocus(FocusEvent e) + { + searchTextBox.TakeFocus(); + base.OnFocus(e); + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + ContentContainer.Margin = new MarginPadding { Left = Sidebar?.DrawWidth ?? 0 }; + ContentContainer.Padding = new MarginPadding { Top = GetToolbarHeight?.Invoke() ?? 0 }; + } + + protected class SettingsSectionsContainer : SectionsContainer + { + public SearchContainer SearchContainer; + + protected override FlowContainer CreateScrollContentContainer() + => SearchContainer = new SearchContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + }; + + public SettingsSectionsContainer() + { + HeaderBackground = new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both + }; + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + // no null check because the usage of this class is strict + HeaderBackground.Alpha = -ExpandableHeader.Y / ExpandableHeader.LayoutSize.Y * 0.5f; + } + } + } +} diff --git a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs index 08f8f867fd..79942012f9 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Toolbar } [BackgroundDependencyLoader(true)] - private void load(MainSettings settings) + private void load(SettingsOverlay settings) { StateContainer = settings; } From a98accb4d46d67a64c9dbefb455bcf012fcc135d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 11:05:53 +0900 Subject: [PATCH 0819/5608] Add tests for cached types in OsuGame and OsuGameBase --- osu.Game.Tests/Visual/TestCaseOsuGame.cs | 69 ++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/osu.Game.Tests/Visual/TestCaseOsuGame.cs b/osu.Game.Tests/Visual/TestCaseOsuGame.cs index 9e649b92e4..dd98ff088c 100644 --- a/osu.Game.Tests/Visual/TestCaseOsuGame.cs +++ b/osu.Game.Tests/Visual/TestCaseOsuGame.cs @@ -3,12 +3,30 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Textures; using osu.Framework.Platform; +using osu.Game.Audio; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Database; +using osu.Game.Graphics; +using osu.Game.Input; +using osu.Game.Input.Bindings; +using osu.Game.IO; +using osu.Game.Online.API; +using osu.Game.Online.Chat; +using osu.Game.Overlays; +using osu.Game.Rulesets; +using osu.Game.Scoring; using osu.Game.Screens.Menu; +using osu.Game.Skinning; +using osu.Game.Utils; using osuTK.Graphics; namespace osu.Game.Tests.Visual @@ -21,6 +39,52 @@ namespace osu.Game.Tests.Visual typeof(OsuLogo), }; + private IReadOnlyList requiredGameDependencies => new[] + { + typeof(OsuGame), + typeof(RavenLogger), + typeof(Bindable), + typeof(IBindable), + typeof(OsuLogo), + typeof(IdleTracker), + typeof(OnScreenDisplay), + typeof(NotificationOverlay), + typeof(DirectOverlay), + typeof(SocialOverlay), + typeof(ChannelManager), + typeof(ChatOverlay), + typeof(SettingsOverlay), + typeof(UserProfileOverlay), + typeof(BeatmapSetOverlay), + typeof(LoginOverlay), + typeof(MusicController), + typeof(AccountCreationOverlay), + typeof(DialogOverlay), + }; + + private IReadOnlyList requiredGameBaseDependencies => new[] + { + typeof(OsuGameBase), + typeof(DatabaseContextFactory), + typeof(LargeTextureStore), + typeof(OsuConfigManager), + typeof(SkinManager), + typeof(ISkinSource), + typeof(IAPIProvider), + typeof(RulesetStore), + typeof(FileStore), + typeof(ScoreManager), + typeof(BeatmapManager), + typeof(KeyBindingStore), + typeof(SettingsStore), + typeof(RulesetConfigCache), + typeof(OsuColour), + typeof(IBindable), + typeof(Bindable), + typeof(GlobalActionContainer), + typeof(PreviewTrackManager), + }; + [BackgroundDependencyLoader] private void load(GameHost host) { @@ -36,6 +100,11 @@ namespace osu.Game.Tests.Visual }, game }; + + AddUntilStep("wait for load", () => game.IsLoaded); + + AddAssert("check OsuGame DI members", () => requiredGameDependencies.All(d => game.Dependencies.Get(d) != null)); + AddAssert("check OsuGameBase DI members", () => requiredGameBaseDependencies.All(d => Dependencies.Get(d) != null)); } } } From be6da833f822ab60ecbdd9c8f8acb7b54812aa6c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 11:11:57 +0900 Subject: [PATCH 0820/5608] Move constant local (and break line) --- osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 084959f775..7fa3dbe07e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -36,8 +36,6 @@ namespace osu.Game.Rulesets.Osu.Mods private class OsuFlashlight : Flashlight, IRequireHighFrequencyMousePosition { - private const double follow_delay = 120; - public OsuFlashlight() { FlashlightSize = new Vector2(0, getSizeFor(0)); @@ -51,10 +49,13 @@ namespace osu.Game.Rulesets.Osu.Mods protected override bool OnMouseMove(MouseMoveEvent e) { + const double follow_delay = 120; + var position = FlashlightPosition; var destination = e.MousePosition; - FlashlightPosition = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); + FlashlightPosition = Interpolation.ValueAt( + MathHelper.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); return base.OnMouseMove(e); } From ad5ad8ccb5eaf4c05eb17e43d16560a2b82b3b37 Mon Sep 17 00:00:00 2001 From: Alten Date: Mon, 13 May 2019 23:29:24 -0400 Subject: [PATCH 0821/5608] Fix hard crash --- osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index 17fffbd974..b7df4f2f2b 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -63,8 +63,13 @@ namespace osu.Game.Rulesets.Osu.UI { get { - var first = (OsuHitObject)Objects.First(); - return first.StartTime - Math.Max(2000, first.TimePreempt); + if (Objects.Any()) + { + var first = (OsuHitObject)Objects.First(); + return first.StartTime - Math.Max(2000, first.TimePreempt); + } + + return 0; } } } From 93b26cd026786fa3ae75f97128686a77e0150fca Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 May 2019 13:04:49 +0900 Subject: [PATCH 0822/5608] Reduce unnecessary allocations --- .../Storyboards/Drawables/DrawableStoryboardAnimation.cs | 7 +++---- osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index d01fba7d39..de3077c025 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.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 osuTK; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -66,13 +67,11 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader] private void load(IBindable beatmap, TextureStore textureStore) { - var basePath = Animation.Path.ToLowerInvariant(); - for (var frame = 0; frame < Animation.FrameCount; frame++) { - var framePath = basePath.Replace(".", frame + "."); + var framePath = Animation.Path.Replace(".", frame + "."); - var path = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.ToLowerInvariant() == framePath)?.FileInfo.StoragePath; + var path = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.Equals(framePath, StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath; if (path == null) continue; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index 604260a38c..5f1f5ddacb 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.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 osuTK; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -65,8 +66,7 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader] private void load(IBindable beatmap, TextureStore textureStore) { - var spritePath = Sprite.Path.ToLowerInvariant(); - var path = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.ToLowerInvariant() == spritePath)?.FileInfo.StoragePath; + var path = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.Equals(Sprite.Path, StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath; if (path == null) return; From 0d57cf659921006ebd311e4b31375867a0655d5f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 13:13:51 +0900 Subject: [PATCH 0823/5608] Remember FPS display state after changing via Ctrl+F11 hotkey --- osu.Game/OsuGameBase.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 66552c43e0..c068c5b0d4 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -220,8 +220,10 @@ namespace osu.Game // TODO: This is temporary until we reimplement the local FPS display. // It's just to allow end-users to access the framework FPS display without knowing the shortcut key. fpsDisplayVisible = LocalConfig.GetBindable(OsuSetting.ShowFpsDisplay); - fpsDisplayVisible.ValueChanged += visible => { FrameStatisticsMode = visible.NewValue ? FrameStatisticsMode.Minimal : FrameStatisticsMode.None; }; + fpsDisplayVisible.ValueChanged += visible => { FrameStatistics.Value = visible.NewValue ? FrameStatisticsMode.Minimal : FrameStatisticsMode.None; }; fpsDisplayVisible.TriggerChange(); + + FrameStatistics.ValueChanged += e => fpsDisplayVisible.Value = e.NewValue != FrameStatisticsMode.None; } private void runMigrations() From 4abe987e11b834380f8371ce8d35f181b133c485 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 13:27:09 +0900 Subject: [PATCH 0824/5608] Add new colour palette --- osu.Game/Graphics/OsuColour.cs | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index e1e33b4c57..a73a8bcbc1 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -68,6 +68,48 @@ namespace osu.Game.Graphics public readonly Color4 GreenDark = FromHex(@"668800"); public readonly Color4 GreenDarker = FromHex(@"445500"); + public readonly Color4 Sky = FromHex(@"6bb5ff"); + public readonly Color4 GreySkyLighter = FromHex(@"c6e3f4"); + public readonly Color4 GreySkyLight = FromHex(@"8ab3cc"); + public readonly Color4 GreySky = FromHex(@"405461"); + public readonly Color4 GreySkyDark = FromHex(@"303d47"); + public readonly Color4 GreySkyDarker = FromHex(@"21272c"); + + public readonly Color4 Seafoam = FromHex(@"05ffa2"); + public readonly Color4 GreySeafoamLighter = FromHex(@"9ebab1"); + public readonly Color4 GreySeafoamLight = FromHex(@"4d7365"); + public readonly Color4 GreySeafoam = FromHex(@"33413c"); + public readonly Color4 GreySeafoamDark = FromHex(@"2c3532"); + public readonly Color4 GreySeafoamDarker = FromHex(@"1e2422"); + + public readonly Color4 Cyan = FromHex(@"05f4fd"); + public readonly Color4 GreyCyanLighter = FromHex(@"77b1b3"); + public readonly Color4 GreyCyanLight = FromHex(@"436d6f"); + public readonly Color4 GreyCyan = FromHex(@"293d3e"); + public readonly Color4 GreyCyanDark = FromHex(@"243536"); + public readonly Color4 GreyCyanDarker = FromHex(@"1e2929"); + + public readonly Color4 Lime = FromHex(@"82ff05"); + public readonly Color4 GreyLimeLighter = FromHex(@"deff87"); + public readonly Color4 GreyLimeLight = FromHex(@"657259"); + public readonly Color4 GreyLime = FromHex(@"3f443a"); + public readonly Color4 GreyLimeDark = FromHex(@"32352e"); + public readonly Color4 GreyLimeDarker = FromHex(@"2e302b"); + + public readonly Color4 Violet = FromHex(@"bf04ff"); + public readonly Color4 GreyVioletLighter = FromHex(@"ebb8fe"); + public readonly Color4 GreyVioletLight = FromHex(@"685370"); + public readonly Color4 GreyViolet = FromHex(@"46334d"); + public readonly Color4 GreyVioletDark = FromHex(@"2c2230"); + public readonly Color4 GreyVioletDarker = FromHex(@"201823"); + + public readonly Color4 Carmine = FromHex(@"ff0542"); + public readonly Color4 GreyCarmineLighter = FromHex(@"deaab4"); + public readonly Color4 GreyCarmineLight = FromHex(@"644f53"); + public readonly Color4 GreyCarmine = FromHex(@"342b2d"); + public readonly Color4 GreyCarmineDark = FromHex(@"302a2b"); + public readonly Color4 GreyCarmineDarker = FromHex(@"241d1e"); + public readonly Color4 Gray0 = FromHex(@"000"); public readonly Color4 Gray1 = FromHex(@"111"); public readonly Color4 Gray2 = FromHex(@"222"); From cb2b14e501aefd9133af3b5090e11d043316de60 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 14:18:06 +0900 Subject: [PATCH 0825/5608] Centralise fullscreen overlay logic --- osu.Game/Overlays/BeatmapSetOverlay.cs | 23 +------- osu.Game/Overlays/DirectOverlay.cs | 11 +--- osu.Game/Overlays/FullscreenOverlay.cs | 58 +++++++++++++++++++ .../SearchableList/SearchableListOverlay.cs | 4 +- osu.Game/Overlays/SocialOverlay.cs | 19 ++---- osu.Game/Overlays/UserProfileOverlay.cs | 37 +----------- 6 files changed, 70 insertions(+), 82 deletions(-) create mode 100644 osu.Game/Overlays/FullscreenOverlay.cs diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 82bac71f5e..5cfdd4050b 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -4,10 +4,8 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Beatmaps; @@ -19,11 +17,10 @@ using osu.Game.Overlays.BeatmapSet; using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Rulesets; using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays { - public class BeatmapSetOverlay : WaveOverlayContainer + public class BeatmapSetOverlay : FullscreenOverlay { private const int fade_duration = 300; @@ -46,24 +43,6 @@ namespace osu.Game.Overlays { Info info; ScoresContainer scores; - Waves.FirstWaveColour = OsuColour.Gray(0.4f); - Waves.SecondWaveColour = OsuColour.Gray(0.3f); - Waves.ThirdWaveColour = OsuColour.Gray(0.2f); - Waves.FourthWaveColour = OsuColour.Gray(0.1f); - - Anchor = Anchor.TopCentre; - Origin = Anchor.TopCentre; - RelativeSizeAxes = Axes.Both; - Width = 0.85f; - - Masking = true; - EdgeEffect = new EdgeEffectParameters - { - Colour = Color4.Black.Opacity(0), - Type = EdgeEffectType.Shadow, - Radius = 3, - Offset = new Vector2(0f, 1f), - }; Children = new Drawable[] { diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 40c4c90fca..975bf4e3ca 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -14,7 +14,6 @@ using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Direct; using osu.Game.Overlays.SearchableList; @@ -28,7 +27,6 @@ namespace osu.Game.Overlays { private const float panel_padding = 10f; - private IAPIProvider api; private RulesetStore rulesets; private readonly FillFlowContainer resultCountsContainer; @@ -87,8 +85,6 @@ namespace osu.Game.Overlays public DirectOverlay() { - RelativeSizeAxes = Axes.Both; - // osu!direct colours are not part of the standard palette Waves.FirstWaveColour = OsuColour.FromHex(@"19b0e2"); @@ -165,9 +161,8 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(OsuColour colours, IAPIProvider api, RulesetStore rulesets, PreviewTrackManager previewTrackManager) + private void load(OsuColour colours, RulesetStore rulesets, PreviewTrackManager previewTrackManager) { - this.api = api; this.rulesets = rulesets; this.previewTrackManager = previewTrackManager; @@ -260,7 +255,7 @@ namespace osu.Game.Overlays if (State == Visibility.Hidden) return; - if (api == null) + if (API == null) return; previewTrackManager.StopAnyPlaying(this); @@ -286,7 +281,7 @@ namespace osu.Game.Overlays }); }; - api.Queue(getSetsRequest); + API.Queue(getSetsRequest); } private int distinctCount(List list) => list.Distinct().ToArray().Length; diff --git a/osu.Game/Overlays/FullscreenOverlay.cs b/osu.Game/Overlays/FullscreenOverlay.cs new file mode 100644 index 0000000000..36de40be3e --- /dev/null +++ b/osu.Game/Overlays/FullscreenOverlay.cs @@ -0,0 +1,58 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Effects; +using osu.Game.Graphics; +using osu.Game.Online.API; +using osuTK.Graphics; + +namespace osu.Game.Overlays +{ + public abstract class FullscreenOverlay : WaveOverlayContainer, IOnlineComponent + { + [Resolved] + protected IAPIProvider API { get; private set; } + + protected FullscreenOverlay() + { + Waves.FirstWaveColour = OsuColour.Gray(0.4f); + Waves.SecondWaveColour = OsuColour.Gray(0.3f); + Waves.ThirdWaveColour = OsuColour.Gray(0.2f); + Waves.FourthWaveColour = OsuColour.Gray(0.1f); + + RelativeSizeAxes = Axes.Both; + RelativePositionAxes = Axes.Both; + Width = 0.85f; + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; + + Masking = true; + + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0), + Type = EdgeEffectType.Shadow, + Radius = 10 + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + API.Register(this); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + API.Unregister(this); + } + + public virtual void APIStateChanged(IAPIProvider api, APIState state) + { + } + } +} diff --git a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs index 87c369e246..293ee4bcda 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.SearchableList { - public abstract class SearchableListOverlay : WaveOverlayContainer + public abstract class SearchableListOverlay : FullscreenOverlay { public static readonly float WIDTH_PADDING = 80; } @@ -32,8 +32,6 @@ namespace osu.Game.Overlays.SearchableList protected SearchableListOverlay() { - RelativeSizeAxes = Axes.Both; - Children = new Drawable[] { new Box diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index e6d0c2fe40..2baa614365 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Bindables; using osuTK; using osuTK.Graphics; @@ -20,9 +19,8 @@ using osu.Framework.Threading; namespace osu.Game.Overlays { - public class SocialOverlay : SearchableListOverlay, IOnlineComponent + public class SocialOverlay : SearchableListOverlay { - private IAPIProvider api; private readonly LoadingAnimation loading; private FillFlowContainer panels; @@ -88,13 +86,6 @@ namespace osu.Game.Overlays currentQuery.BindTo(Filter.Search.Current); } - [BackgroundDependencyLoader] - private void load(IAPIProvider api) - { - this.api = api; - api.Register(this); - } - private void recreatePanels(PanelDisplayStyle displayStyle) { clearPanels(); @@ -159,7 +150,7 @@ namespace osu.Game.Overlays loading.Hide(); getUsersRequest?.Cancel(); - if (api?.IsLoggedIn != true) + if (API?.IsLoggedIn != true) return; switch (Header.Tabs.Current.Value) @@ -167,13 +158,13 @@ namespace osu.Game.Overlays case SocialTab.Friends: var friendRequest = new GetFriendsRequest(); // TODO filter arguments? friendRequest.Success += updateUsers; - api.Queue(getUsersRequest = friendRequest); + API.Queue(getUsersRequest = friendRequest); break; default: var userRequest = new GetUsersRequest(); // TODO filter arguments! userRequest.Success += response => updateUsers(response.Select(r => r.User)); - api.Queue(getUsersRequest = userRequest); + API.Queue(getUsersRequest = userRequest); break; } @@ -196,7 +187,7 @@ namespace osu.Game.Overlays } } - public void APIStateChanged(IAPIProvider api, APIState state) + public override void APIStateChanged(IAPIProvider api, APIState state) { switch (state) { diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 1c242e3768..2d2840107d 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -3,64 +3,31 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Profile; using osu.Game.Overlays.Profile.Sections; using osu.Game.Users; using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays { - public class UserProfileOverlay : WaveOverlayContainer + public class UserProfileOverlay : FullscreenOverlay { private ProfileSection lastSection; private ProfileSection[] sections; private GetUserRequest userReq; - private IAPIProvider api; protected ProfileHeader Header; private SectionsContainer sectionsContainer; private ProfileTabControl tabs; public const float CONTENT_X_MARGIN = 70; - public UserProfileOverlay() - { - Waves.FirstWaveColour = OsuColour.Gray(0.4f); - Waves.SecondWaveColour = OsuColour.Gray(0.3f); - Waves.ThirdWaveColour = OsuColour.Gray(0.2f); - Waves.FourthWaveColour = OsuColour.Gray(0.1f); - - RelativeSizeAxes = Axes.Both; - RelativePositionAxes = Axes.Both; - Width = 0.85f; - Anchor = Anchor.TopCentre; - Origin = Anchor.TopCentre; - - Masking = true; - EdgeEffect = new EdgeEffectParameters - { - Colour = Color4.Black.Opacity(0), - Type = EdgeEffectType.Shadow, - Radius = 10 - }; - } - - [BackgroundDependencyLoader] - private void load(IAPIProvider api) - { - this.api = api; - } - protected override void PopIn() { base.PopIn(); @@ -154,7 +121,7 @@ namespace osu.Game.Overlays { userReq = new GetUserRequest(user.Id); userReq.Success += userLoadComplete; - api.Queue(userReq); + API.Queue(userReq); } else { From ca2662e941705c6f9b364f69c4e4c9dbedda7c1b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 14:58:36 +0900 Subject: [PATCH 0826/5608] Rename incorrectly named test cases --- .../Online/{TestCaseDirect.cs => TestCaseDirectOverlay.cs} | 2 +- .../Online/{TestCaseSocial.cs => TestCaseSocialOverlay.cs} | 5 ++--- osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs | 2 +- ...{TestCaseUserProfile.cs => TestCaseUserProfileOverlay.cs} | 5 ++--- 4 files changed, 6 insertions(+), 8 deletions(-) rename osu.Game.Tests/Visual/Online/{TestCaseDirect.cs => TestCaseDirectOverlay.cs} (99%) rename osu.Game.Tests/Visual/Online/{TestCaseSocial.cs => TestCaseSocialOverlay.cs} (96%) rename osu.Game.Tests/Visual/Online/{TestCaseUserProfile.cs => TestCaseUserProfileOverlay.cs} (96%) diff --git a/osu.Game.Tests/Visual/Online/TestCaseDirect.cs b/osu.Game.Tests/Visual/Online/TestCaseDirectOverlay.cs similarity index 99% rename from osu.Game.Tests/Visual/Online/TestCaseDirect.cs rename to osu.Game.Tests/Visual/Online/TestCaseDirectOverlay.cs index ff57104d8a..677b49e1af 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseDirect.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseDirectOverlay.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseDirect : OsuTestCase + public class TestCaseDirectOverlay : OsuTestCase { private DirectOverlay direct; private RulesetStore rulesets; diff --git a/osu.Game.Tests/Visual/Online/TestCaseSocial.cs b/osu.Game.Tests/Visual/Online/TestCaseSocialOverlay.cs similarity index 96% rename from osu.Game.Tests/Visual/Online/TestCaseSocial.cs rename to osu.Game.Tests/Visual/Online/TestCaseSocialOverlay.cs index 48325713df..2c524da99d 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseSocial.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseSocialOverlay.cs @@ -11,19 +11,18 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseSocial : OsuTestCase + public class TestCaseSocialOverlay : OsuTestCase { public override IReadOnlyList RequiredTypes => new[] { typeof(UserPanel), typeof(SocialPanel), typeof(FilterControl), - typeof(SocialOverlay), typeof(SocialGridPanel), typeof(SocialListPanel) }; - public TestCaseSocial() + public TestCaseSocialOverlay() { SocialOverlay s = new SocialOverlay { diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs index 5f5ba89186..887228c06e 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Online header = new ProfileHeader(); Add(header); - AddStep("Show offline dummy", () => header.User.Value = TestCaseUserProfile.TEST_USER); + AddStep("Show offline dummy", () => header.User.Value = TestCaseUserProfileOverlay.TEST_USER); AddStep("Show null dummy", () => header.User.Value = new User { diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/Online/TestCaseUserProfileOverlay.cs similarity index 96% rename from osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs rename to osu.Game.Tests/Visual/Online/TestCaseUserProfileOverlay.cs index 0789c14b32..6940392f32 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserProfileOverlay.cs @@ -17,7 +17,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseUserProfile : OsuTestCase + public class TestCaseUserProfileOverlay : OsuTestCase { private readonly TestUserProfileOverlay profile; @@ -27,7 +27,6 @@ namespace osu.Game.Tests.Visual.Online public override IReadOnlyList RequiredTypes => new[] { typeof(ProfileHeader), - typeof(UserProfileOverlay), typeof(RankGraph), typeof(LineGraph), typeof(SectionsContainer<>), @@ -72,7 +71,7 @@ namespace osu.Game.Tests.Visual.Online Achievements = new User.UserAchievement[0], }; - public TestCaseUserProfile() + public TestCaseUserProfileOverlay() { Add(profile = new TestUserProfileOverlay()); } From 29bdc97ab7a669709f4c2fd050e01eecd90e9538 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 15:07:18 +0900 Subject: [PATCH 0827/5608] Remove unnecessary DI --- osu.Game/Overlays/BeatmapSetOverlay.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 5cfdd4050b..2cf400f776 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -11,7 +11,6 @@ using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.BeatmapSet; using osu.Game.Overlays.BeatmapSet.Scores; @@ -29,7 +28,6 @@ namespace osu.Game.Overlays private readonly Header header; - private IAPIProvider api; private RulesetStore rulesets; private readonly ScrollContainer scroll; @@ -81,9 +79,8 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(IAPIProvider api, RulesetStore rulesets) + private void load(RulesetStore rulesets) { - this.api = api; this.rulesets = rulesets; } @@ -114,7 +111,7 @@ namespace osu.Game.Overlays beatmapSet.Value = res.ToBeatmapSet(rulesets); header.Picker.Beatmap.Value = header.BeatmapSet.Value.Beatmaps.First(b => b.OnlineBeatmapID == beatmapId); }; - api.Queue(req); + API.Queue(req); Show(); } @@ -123,7 +120,7 @@ namespace osu.Game.Overlays beatmapSet.Value = null; var req = new GetBeatmapSetRequest(beatmapSetId); req.Success += res => beatmapSet.Value = res.ToBeatmapSet(rulesets); - api.Queue(req); + API.Queue(req); Show(); } From a765f2502daa9760786e9c20baf688ddcb8a4a27 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 15:14:00 +0900 Subject: [PATCH 0828/5608] Add simple test case for FullscreenOverlay --- .../Online/TestCaseFullscreenOverlay.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestCaseFullscreenOverlay.cs diff --git a/osu.Game.Tests/Visual/Online/TestCaseFullscreenOverlay.cs b/osu.Game.Tests/Visual/Online/TestCaseFullscreenOverlay.cs new file mode 100644 index 0000000000..925e6e1349 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestCaseFullscreenOverlay.cs @@ -0,0 +1,40 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Overlays; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Online +{ + [TestFixture] + public class TestCaseFullscreenOverlay : OsuTestCase + { + private FullscreenOverlay overlay; + + protected override void LoadComplete() + { + base.LoadComplete(); + + Add(overlay = new TestFullscreenOverlay()); + AddStep(@"toggle", overlay.ToggleVisibility); + } + + private class TestFullscreenOverlay : FullscreenOverlay + { + public TestFullscreenOverlay() + { + Children = new Drawable[] + { + new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + }, + }; + } + } + } +} From e893925417d9b7bd2a453e6ec2e9d5429d0372b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 15:19:23 +0900 Subject: [PATCH 0829/5608] Move shadow fade logic --- osu.Game/Overlays/BeatmapSetOverlay.cs | 12 +++--------- osu.Game/Overlays/FullscreenOverlay.cs | 17 +++++++++++++++++ osu.Game/Overlays/UserProfileOverlay.cs | 12 ------------ 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 2cf400f776..3ed398d31a 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -84,16 +84,10 @@ namespace osu.Game.Overlays this.rulesets = rulesets; } - protected override void PopIn() + protected override void PopOutComplete() { - base.PopIn(); - FadeEdgeEffectTo(0.25f, WaveContainer.APPEAR_DURATION, Easing.In); - } - - protected override void PopOut() - { - base.PopOut(); - FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out).OnComplete(_ => beatmapSet.Value = null); + base.PopOutComplete(); + beatmapSet.Value = null; } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game/Overlays/FullscreenOverlay.cs b/osu.Game/Overlays/FullscreenOverlay.cs index 36de40be3e..921dcd316d 100644 --- a/osu.Game/Overlays/FullscreenOverlay.cs +++ b/osu.Game/Overlays/FullscreenOverlay.cs @@ -6,6 +6,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Effects; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Online.API; using osuTK.Graphics; @@ -39,6 +40,22 @@ namespace osu.Game.Overlays }; } + protected override void PopIn() + { + base.PopIn(); + FadeEdgeEffectTo(0.4f, WaveContainer.APPEAR_DURATION, Easing.Out); + } + + protected override void PopOut() + { + base.PopOut(); + FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.In).OnComplete(_ => PopOutComplete()); + } + + protected virtual void PopOutComplete() + { + } + protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 2d2840107d..8a133a1d1e 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -28,18 +28,6 @@ namespace osu.Game.Overlays public const float CONTENT_X_MARGIN = 70; - protected override void PopIn() - { - base.PopIn(); - FadeEdgeEffectTo(0.5f, WaveContainer.APPEAR_DURATION, Easing.In); - } - - protected override void PopOut() - { - base.PopOut(); - FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); - } - public void ShowUser(long userId) => ShowUser(new User { Id = userId }); public void ShowUser(User user, bool fetchOnline = true) From f1c9073338e32630eca13774e8b9b0143c6feaa9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 May 2019 16:16:55 +0900 Subject: [PATCH 0830/5608] Fix commented line check not working with whitespace --- .../Beatmaps/Formats/LegacyDecoderTest.cs | 56 +++++++++++++++++++ osu.Game.Tests/Resources/comments.osu | 9 +++ osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs create mode 100644 osu.Game.Tests/Resources/comments.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs new file mode 100644 index 0000000000..b4d219456c --- /dev/null +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.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 System.Collections.Generic; +using System.IO; +using NUnit.Framework; +using osu.Game.Beatmaps.Formats; +using osu.Game.Tests.Resources; + +namespace osu.Game.Tests.Beatmaps.Formats +{ + [TestFixture] + public class LegacyDecoderTest + { + [Test] + public void TestDecodeComments() + { + var decoder = new LineLoggingDecoder(14); + + using (var resStream = TestResources.OpenResource("comments.osu")) + using (var stream = new StreamReader(resStream)) + { + decoder.Decode(stream); + + Assert.That(decoder.ParsedLines, Has.None.EqualTo("// Combo1: 0, 0, 0")); + Assert.That(decoder.ParsedLines, Has.None.EqualTo("//Combo2: 0, 0, 0")); + Assert.That(decoder.ParsedLines, Has.None.EqualTo(" // Combo3: 0, 0, 0")); + Assert.That(decoder.ParsedLines, Has.One.EqualTo("Combo1: 100, 100, 100 // Comment at end of line")); + } + } + + private class LineLoggingDecoder : LegacyDecoder + { + public readonly List ParsedLines = new List(); + + public LineLoggingDecoder(int version) + : base(version) + { + } + + protected override bool ShouldSkipLine(string line) + { + var result = base.ShouldSkipLine(line); + + if (!result) + ParsedLines.Add(line); + + return result; + } + } + + private class TestModel + { + } + } +} diff --git a/osu.Game.Tests/Resources/comments.osu b/osu.Game.Tests/Resources/comments.osu new file mode 100644 index 0000000000..78b48dd804 --- /dev/null +++ b/osu.Game.Tests/Resources/comments.osu @@ -0,0 +1,9 @@ +osu file format v14 + +[Colours] + +// Combo1: 0, 0, 0 +//Combo2: 0, 0, 0 + // Combo3: 0, 0, 0 + +Combo1: 100, 100, 100 // Comment at end of line \ No newline at end of file diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index ad5089958c..eb5bcfe824 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -54,7 +54,7 @@ namespace osu.Game.Beatmaps.Formats } } - protected virtual bool ShouldSkipLine(string line) => string.IsNullOrWhiteSpace(line) || line.StartsWith("//", StringComparison.Ordinal); + protected virtual bool ShouldSkipLine(string line) => string.IsNullOrWhiteSpace(line) || line.AsSpan().TrimStart().StartsWith("//".AsSpan(), StringComparison.Ordinal); protected virtual void ParseLine(T output, Section section, string line) { From fad9e7399940946d90f4314f9344d8871af68df6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 17:08:42 +0900 Subject: [PATCH 0831/5608] Add null check in disposal clause --- osu.Game/Overlays/FullscreenOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/FullscreenOverlay.cs b/osu.Game/Overlays/FullscreenOverlay.cs index 921dcd316d..9706f75087 100644 --- a/osu.Game/Overlays/FullscreenOverlay.cs +++ b/osu.Game/Overlays/FullscreenOverlay.cs @@ -65,7 +65,7 @@ namespace osu.Game.Overlays protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - API.Unregister(this); + API?.Unregister(this); } public virtual void APIStateChanged(IAPIProvider api, APIState state) From 31e7f2fa877a4804d399119bf44f0f52305bcbfc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 14:18:36 +0900 Subject: [PATCH 0832/5608] Update ChangelogOverlay to use FullScreenOverlay --- osu.Game/Overlays/ChangelogOverlay.cs | 49 +++++++-------------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index e9fd5789ed..b13b28afe9 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -10,63 +10,43 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Input.Bindings; -using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Changelog; using System; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics.Effects; using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays { - public class ChangelogOverlay : WaveOverlayContainer + public class ChangelogOverlay : FullscreenOverlay { - private readonly ChangelogHeader header; + private ChangelogHeader header; - private readonly ChangelogBadges badges; + private ChangelogBadges badges; - private readonly ChangelogContent listing; - private readonly ChangelogContent content; + private ChangelogContent listing; + private ChangelogContent content; - private readonly ScrollContainer scroll; - - private readonly Color4 purple = new Color4(191, 4, 255, 255); + private ScrollContainer scroll; private SampleChannel sampleBack; - private IAPIProvider api; - private bool isAtListing; private float savedScrollPosition; // receive input outside our bounds so we can trigger a close event on ourselves. public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; - public ChangelogOverlay() + [BackgroundDependencyLoader] + private void load(AudioManager audio, OsuColour colour) { // these possibly need adjusting? - Waves.FirstWaveColour = OsuColour.FromHex(@"bf04ff"); + Waves.FirstWaveColour = colour.Violet; Waves.SecondWaveColour = OsuColour.FromHex(@"8F03BF"); Waves.ThirdWaveColour = OsuColour.FromHex(@"600280"); Waves.FourthWaveColour = OsuColour.FromHex(@"300140"); - Anchor = Anchor.TopCentre; - Origin = Anchor.TopCentre; - RelativeSizeAxes = Axes.Both; - Width = 0.85f; - Masking = true; - - EdgeEffect = new EdgeEffectParameters - { - Colour = Color4.Black.Opacity(0), - Type = EdgeEffectType.Shadow, - Radius = 3, - Offset = new Vector2(0f, 1f), - }; - Children = new Drawable[] { new Box @@ -97,12 +77,7 @@ namespace osu.Game.Overlays badges.Selected += onBuildSelected; listing.BuildSelected += onBuildSelected; content.BuildSelected += onBuildSelected; - } - [BackgroundDependencyLoader] - private void load(IAPIProvider api, AudioManager audio) - { - this.api = api; sampleBack = audio.Sample.Get(@"UI/generic-select-soft"); // @"UI/screen-back" feels non-fitting here } @@ -168,7 +143,8 @@ namespace osu.Game.Overlays listing.ShowListing(res.Builds); badges.Populate(res.Streams); }; - api.Queue(req); + + API.Queue(req); } public void ShowListing() @@ -217,7 +193,8 @@ namespace osu.Game.Overlays savedScrollPosition = scroll.Current; isAtListing = false; }; - api.Queue(req); + + API.Queue(req); } } } From eece4d878fb31d862e753ada76ab2e4aa278cfc6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 18:03:54 +0900 Subject: [PATCH 0833/5608] Tidy up colour references and texture assignment in ChangelogHeader --- .../Overlays/Changelog/ChangelogHeader.cs | 45 ++++++++----------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 0c92aa3755..1bc30b87d4 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -18,13 +18,10 @@ namespace osu.Game.Overlays.Changelog { public class ChangelogHeader : Container { - protected Color4 Purple = new Color4(191, 4, 255, 255); - private readonly Sprite coverImage; - private readonly Sprite headerBadge; - private readonly OsuSpriteText titleStream; - private readonly TextBadgePairListing listing; - private readonly SpriteIcon chevron; - private readonly TextBadgePairRelease releaseStream; + private OsuSpriteText titleStream; + private TextBadgePairListing listing; + private SpriteIcon chevron; + private TextBadgePairRelease releaseStream; public delegate void ListingSelectedEventHandler(); @@ -36,7 +33,8 @@ namespace osu.Game.Overlays.Changelog private const float icon_margin = 20; private const float version_height = 40; - public ChangelogHeader() + [BackgroundDependencyLoader] + private void load(OsuColour colours, TextureStore textures) { RelativeSizeAxes = Axes.X; Height = cover_height; @@ -50,9 +48,10 @@ namespace osu.Game.Overlays.Changelog Masking = true, Children = new Drawable[] { - coverImage = new Sprite + new Sprite { RelativeSizeAxes = Axes.Both, + Texture = textures.Get(@"https://osu.ppy.sh/images/headers/changelog.jpg"), FillMode = FillMode.Fill, }, } @@ -69,15 +68,17 @@ namespace osu.Game.Overlays.Changelog { X = icon_margin, Masking = true, - BorderColour = Purple, + BorderColour = colours.Violet, BorderThickness = 3, MaskingSmoothness = 1, Size = new Vector2(50), Children = new Drawable[] { - headerBadge = new Sprite + new Sprite { RelativeSizeAxes = Axes.Both, + // todo: https://osu.ppy.sh/images/icons/changelog.svg + Texture = textures.Get(@"https://i.imgur.com/HQM3Vhp.png"), Size = new Vector2(0.8f), Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -92,7 +93,7 @@ namespace osu.Game.Overlays.Changelog RelativeSizeAxes = Axes.Both, Alpha = 0, AlwaysPresent = true, - Colour = Purple, + Colour = colours.Violet, } } }, @@ -114,7 +115,7 @@ namespace osu.Game.Overlays.Changelog { Text = "Listing", Font = OsuFont.GetFont(weight: FontWeight.Light, size: 38), // web: 30, - Colour = Purple, + Colour = colours.Violet, }, } } @@ -129,7 +130,7 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Horizontal, Children = new Drawable[] { - listing = new TextBadgePairListing(Purple), + listing = new TextBadgePairListing(colours.Violet), new Container // without a container, moving the chevron wont work { Anchor = Anchor.CentreLeft, @@ -148,25 +149,26 @@ namespace osu.Game.Overlays.Changelog Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(7), - Colour = Purple, + Colour = colours.Violet, Icon = FontAwesome.Solid.ChevronRight, Alpha = 0, X = -200, }, }, }, - releaseStream = new TextBadgePairRelease(Purple, "Lazer") + releaseStream = new TextBadgePairRelease(colours.Violet, "Lazer") }, }, new Box { - Colour = Purple, + Colour = colours.Violet, RelativeSizeAxes = Axes.X, Height = 2, Anchor = Anchor.BottomLeft, Origin = Anchor.CentreLeft, }, }; + listing.Activated += OnListingSelected; releaseStream.Activated += OnReleaseSelected; } @@ -198,14 +200,5 @@ namespace osu.Game.Overlays.Changelog { titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - // should be added to osu-resources? - // headerBadge.Texture = textures.Get(@"https://osu.ppy.sh/images/icons/changelog.svg"); // this is not working - headerBadge.Texture = textures.Get(@"https://i.imgur.com/HQM3Vhp.png"); - coverImage.Texture = textures.Get(@"https://osu.ppy.sh/images/headers/changelog.jpg"); - } } } From 77263bd56e9cc89cdd4fc53e6b2f6f1419584672 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 May 2019 18:11:32 +0900 Subject: [PATCH 0834/5608] Linkify more user links --- osu.Game/Overlays/Direct/DirectGridPanel.cs | 31 ++++++---------- .../Historical/DrawableMostPlayedRow.cs | 36 +++++-------------- 2 files changed, 18 insertions(+), 49 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index eb73a50f99..5756a4593d 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -15,6 +15,7 @@ using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Direct { @@ -119,28 +120,16 @@ namespace osu.Game.Overlays.Direct }, Children = new Drawable[] { - new FillFlowContainer + new LinkFlowContainer(s => { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new[] - { - new OsuSpriteText - { - Text = "mapped by ", - Font = OsuFont.GetFont(size: 14), - Shadow = false, - Colour = colours.Gray5, - }, - new OsuSpriteText - { - Text = SetInfo.Metadata.Author.Username, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold, italics: true), - Shadow = false, - Colour = colours.BlueDark, - }, - }, - }, + s.Shadow = false; + s.Font = OsuFont.GetFont(size: 14); + }).With(d => + { + d.AutoSizeAxes = Axes.Both; + d.AddText("mapped by ", t => t.Colour = colours.Gray5); + d.AddUserLink(SetInfo.Metadata.Author); + }), new Container { AutoSizeAxes = Axes.X, diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs index b0609e685e..1b286f92d3 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs @@ -17,7 +17,6 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { private readonly BeatmapInfo beatmap; private readonly int playCount; - private OsuHoverContainer mapperContainer; public DrawableMostPlayedRow(BeatmapInfo beatmap, int playCount) { @@ -34,36 +33,20 @@ namespace osu.Game.Overlays.Profile.Sections.Historical CoverType = BeatmapSetCoverType.List, }; - [BackgroundDependencyLoader(true)] - private void load(UserProfileOverlay profileOverlay) + [BackgroundDependencyLoader] + private void load() { LeftFlowContainer.Add(new BeatmapMetadataContainer(beatmap)); - LeftFlowContainer.Add(new FillFlowContainer + LeftFlowContainer.Add(new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: 12)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Horizontal, - Children = new Drawable[] - { - new OsuSpriteText - { - Text = @"mapped by ", - Font = OsuFont.GetFont(size: 12) - }, - mapperContainer = new OsuHoverContainer - { - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - new OsuSpriteText - { - Text = beatmap.Metadata.AuthorString, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Medium, italics: true) - } - } - }, - } - }); + }.With(d => + { + d.AddText("mapped by "); + d.AddUserLink(beatmap.Metadata.Author); + })); RightFlowContainer.Add(new FillFlowContainer { @@ -89,9 +72,6 @@ namespace osu.Game.Overlays.Profile.Sections.Historical }, } }); - - if (profileOverlay != null) - mapperContainer.Action = () => profileOverlay.ShowUser(beatmap.BeatmapSet.Metadata.Author); } } } From ec5b024fa605bce0706d0f608b1dcb2dfade6691 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 18:34:25 +0900 Subject: [PATCH 0835/5608] Define toolbarElements --- osu.Game/OsuGame.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index c1004ce5eb..1f4b78f5fb 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -99,6 +99,8 @@ namespace osu.Game private readonly List overlays = new List(); + private readonly List toolbarElements = new List(); + private readonly List visibleBlockingOverlays = new List(); // todo: move this to SongSelect once Screen has the ability to unsuspend. @@ -142,8 +144,8 @@ namespace osu.Game if (hideToolbarElements) { - Toolbar.State = Visibility.Hidden; - musicController.State = Visibility.Hidden; + foreach (var overlay in toolbarElements) + overlay.State = Visibility.Hidden; } } @@ -420,7 +422,11 @@ namespace osu.Game CloseAllOverlays(false); menuScreen?.MakeCurrent(); }, - }, topMostOverlayContent.Add); + }, d => + { + topMostOverlayContent.Add(d); + toolbarElements.Add(d); + }); loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add); loadComponentSingleFile(new OnScreenDisplay(), Add, true); @@ -455,7 +461,11 @@ namespace osu.Game GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - }, rightFloatingOverlayContent.Add, true); + }, d => + { + rightFloatingOverlayContent.Add(d); + toolbarElements.Add(d); + }, true); loadComponentSingleFile(new AccountCreationOverlay(), topMostOverlayContent.Add, true); loadComponentSingleFile(new DialogOverlay(), topMostOverlayContent.Add, true); From f2e5beec11f86959985d4ed35e1feb53e5bc8606 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 18:35:35 +0900 Subject: [PATCH 0836/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8f733a5c55..66d298f8c1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index e5b4d61615..ccec475d98 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From d5e25c05b3b6ccdea3bce018e835db72b7053f90 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 May 2019 18:39:03 +0900 Subject: [PATCH 0837/5608] Increase loader animation test wait --- osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs b/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs index eb275cbceb..3f0d965c99 100644 --- a/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs +++ b/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual.Menus bool logoVisible = false; AddStep("begin loading", () => LoadScreen(loader = new TestLoader())); - AddWaitStep("wait", 2); + AddWaitStep("wait", 3); AddStep("finish loading", () => { logoVisible = loader.Logo?.Alpha > 0; From 4c221e43a97d412ce237012a3e289432d9aed2da Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 May 2019 18:39:56 +0900 Subject: [PATCH 0838/5608] Apply minimal changes to make framework compile --- .../Visual/UserInterface/TestCaseLoadingAnimation.cs | 2 +- .../Visual/UserInterface/TestCaseOsuIcon.cs | 3 +-- osu.Game/Tests/Visual/OsuTestCase.cs | 12 ++++++------ 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs index 43f6f0e4db..1cfd56e2c8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs @@ -9,7 +9,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestCaseLoadingAnimation : GridTestCase + public class TestCaseLoadingAnimation : GridTestScene //todo: this should be an OsuTestCase { public TestCaseLoadingAnimation() : base(2, 2) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseOsuIcon.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseOsuIcon.cs index a57e11cb0c..cef122ff58 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseOsuIcon.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseOsuIcon.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.Testing; using osu.Game.Graphics; using osuTK; using osuTK.Graphics; @@ -17,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseOsuIcon : TestCase + public class TestCaseOsuIcon : OsuTestCase { public TestCaseOsuIcon() { diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index 1f475209a4..3a40db4571 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -15,7 +15,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Tests.Visual { - public abstract class OsuTestCase : TestCase + public abstract class OsuTestCase : TestScene { [Cached(typeof(Bindable))] [Cached(typeof(IBindable))] @@ -76,21 +76,21 @@ namespace osu.Game.Tests.Visual } } - protected override ITestCaseTestRunner CreateRunner() => new OsuTestCaseTestRunner(); + protected override ITestSceneTestRunner CreateRunner() => new OsuTestCaseTestRunner(); - public class OsuTestCaseTestRunner : OsuGameBase, ITestCaseTestRunner + public class OsuTestCaseTestRunner : OsuGameBase, ITestSceneTestRunner { - private TestCaseTestRunner.TestRunner runner; + private TestSceneTestRunner.TestRunner runner; protected override void LoadAsyncComplete() { // this has to be run here rather than LoadComplete because // TestCase.cs is checking the IsLoaded state (on another thread) and expects // the runner to be loaded at that point. - Add(runner = new TestCaseTestRunner.TestRunner()); + Add(runner = new TestSceneTestRunner.TestRunner()); } - public void RunTestBlocking(TestCase test) => runner.RunTestBlocking(test); + public void RunTestBlocking(TestScene test) => runner.RunTestBlocking(test); } private class OsuTestBeatmap : BindableBeatmap From ee2bbf950f682c82e6cb31ae20f871b1958724af Mon Sep 17 00:00:00 2001 From: Lucas A Date: Tue, 14 May 2019 19:13:21 +0200 Subject: [PATCH 0839/5608] Update DiscordRichPresenceClient presence logic --- osu.Desktop/DiscordRichPresenceClient.cs | 36 ++++++++++++++++-------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/osu.Desktop/DiscordRichPresenceClient.cs b/osu.Desktop/DiscordRichPresenceClient.cs index 9288141e5f..9537252216 100644 --- a/osu.Desktop/DiscordRichPresenceClient.cs +++ b/osu.Desktop/DiscordRichPresenceClient.cs @@ -9,6 +9,7 @@ using osu.Framework.Logging; using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Users; +using static osu.Game.Users.UserActivity; using User = osu.Game.Users.User; namespace osu.Desktop @@ -28,32 +29,43 @@ namespace osu.Desktop user.ValueChanged += usr => { - usr.OldValue.Status.ValueChanged -= updateStatus; - usr.NewValue.Status.ValueChanged += updateStatus; + usr.NewValue.Activity.ValueChanged += activity => updateStatus(user.Value.Status.Value, activity.NewValue); + usr.NewValue.Status.ValueChanged += status => updateStatus(status.NewValue, user.Value.Activity.Value); }; - user.Value.Status.ValueChanged += updateStatus; + user.TriggerChange(); - client.OnReady += (_, __) => Logger.Log("Discord RPC Client ready.", LoggingTarget.Network, LogLevel.Debug); - client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client : {e.Message}", LoggingTarget.Network, LogLevel.Debug); - client.OnConnectionFailed += (_, e) => Logger.Log("Discord RPC Client failed to initialize : is discord running ?", LoggingTarget.Network, LogLevel.Debug); - client.OnPresenceUpdate += (_, __) => Logger.Log("Updated Discord Rich Presence", LoggingTarget.Network, LogLevel.Debug); + enableLogging(); client.Initialize(); } - private void updateStatus(ValueChangedEvent e) + private void enableLogging() { - var presence = defaultPresence(e.NewValue.Message); + client.OnReady += (_, __) => Logger.Log("Discord RPC Client ready.", LoggingTarget.Network, LogLevel.Debug); + client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client : {e.Message}", LoggingTarget.Network, LogLevel.Debug); + client.OnConnectionFailed += (_, e) => Logger.Log("Discord RPC Client failed to initialize : is discord running ?", LoggingTarget.Network, LogLevel.Debug); + client.OnPresenceUpdate += (_, __) => Logger.Log("Updated Discord Rich Presence", LoggingTarget.Network, LogLevel.Debug); + } - switch (e.NewValue) + private void updateStatus(UserStatus st, UserActivity a) + { + var presence = defaultPresence(st is UserStatusOnline ? a?.Status : st.Message); + + if (!(st is UserStatusOnline)) //don't update the presence any further if the current user status is DND / Offline & simply return with the default presence { - case UserStatusSoloGame game: + client.SetPresence(presence); + return; + } + + switch (a) + { + case UserActivitySoloGame game: presence.State = $"{game.Beatmap.Metadata.Artist} - {game.Beatmap.Metadata.Title} [{game.Beatmap.Version}]"; setPresenceGamemode(game.Ruleset, presence); break; - case UserStatusEditing editing: + case UserActivityEditing editing: presence.State = $"{editing.Beatmap.Metadata.Artist} - {editing.Beatmap.Metadata.Title} " + (!string.IsNullOrEmpty(editing.Beatmap.Version) ? $"[{editing.Beatmap.Version}]" : ""); presence.Assets.SmallImageKey = "edit"; presence.Assets.SmallImageText = "editing"; From d4013ae0d894134c2397a84f2bf0427bfa026ec0 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Tue, 14 May 2019 19:37:43 +0200 Subject: [PATCH 0840/5608] Make DiscordRichPresenceClient dispose client on disposal --- osu.Desktop/DiscordRichPresenceClient.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Desktop/DiscordRichPresenceClient.cs b/osu.Desktop/DiscordRichPresenceClient.cs index 9537252216..d49b08823c 100644 --- a/osu.Desktop/DiscordRichPresenceClient.cs +++ b/osu.Desktop/DiscordRichPresenceClient.cs @@ -112,5 +112,11 @@ namespace osu.Desktop LargeImageText = user.Value.Username } }; + + protected override void Dispose(bool isDisposing) + { + client.Dispose(); + base.Dispose(isDisposing); + } } } From 459a285cd860653d1f425ed83bdc7499474ba7d5 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Tue, 14 May 2019 22:37:25 +0300 Subject: [PATCH 0841/5608] Rename test cases to test scenes inline with the framework change --- ...CaseAutoJuiceStream.cs => TestSceneAutoJuiceStream.cs} | 4 ++-- .../{TestCaseBananaShower.cs => TestSceneBananaShower.cs} | 4 ++-- .../{TestCaseCatchPlayer.cs => TestSceneCatchPlayer.cs} | 4 ++-- .../{TestCaseCatchStacker.cs => TestSceneCatchStacker.cs} | 4 ++-- .../{TestCaseCatcherArea.cs => TestSceneCatcherArea.cs} | 4 ++-- .../{TestCaseFruitObjects.cs => TestSceneFruitObjects.cs} | 4 ++-- .../{TestCaseHyperDash.cs => TestSceneHyperDash.cs} | 4 ++-- .../{ManiaInputTestCase.cs => ManiaInputTestScene.cs} | 4 ++-- ...intTestCase.cs => ManiaPlacementBlueprintTestScene.cs} | 4 ++-- ...intTestCase.cs => ManiaSelectionBlueprintTestScene.cs} | 4 ++-- ...stCaseAutoGeneration.cs => TestSceneAutoGeneration.cs} | 2 +- .../{TestCaseColumn.cs => TestSceneColumn.cs} | 4 ++-- .../{TestCaseEditor.cs => TestSceneEditor.cs} | 4 ++-- ...lueprint.cs => TestSceneHoldNotePlacementBlueprint.cs} | 2 +- ...lueprint.cs => TestSceneHoldNoteSelectionBlueprint.cs} | 4 ++-- ...entBlueprint.cs => TestSceneNotePlacementBlueprint.cs} | 2 +- ...ionBlueprint.cs => TestSceneNoteSelectionBlueprint.cs} | 4 ++-- .../{TestCaseNotes.cs => TestSceneNotes.cs} | 2 +- .../{TestCaseStage.cs => TestSceneStage.cs} | 4 ++-- .../{TestCaseEditor.cs => TestSceneEditor.cs} | 4 ++-- ...stCaseGameplayCursor.cs => TestSceneGameplayCursor.cs} | 2 +- .../{TestCaseHitCircle.cs => TestSceneHitCircle.cs} | 4 ++-- ...CaseHitCircleHidden.cs => TestSceneHitCircleHidden.cs} | 4 ++-- ...tCircleLongCombo.cs => TestSceneHitCircleLongCombo.cs} | 4 ++-- ...ueprint.cs => TestSceneHitCirclePlacementBlueprint.cs} | 2 +- ...ueprint.cs => TestSceneHitCircleSelectionBlueprint.cs} | 4 ++-- ...TestCaseOsuFlashlight.cs => TestSceneOsuFlashlight.cs} | 2 +- .../{TestCaseOsuPlayer.cs => TestSceneOsuPlayer.cs} | 4 ++-- ...TestCaseResumeOverlay.cs => TestSceneResumeOverlay.cs} | 4 ++-- .../{TestCaseShaking.cs => TestSceneShaking.cs} | 2 +- .../{TestCaseSlider.cs => TestSceneSlider.cs} | 4 ++-- .../{TestCaseSliderHidden.cs => TestSceneSliderHidden.cs} | 4 ++-- .../{TestCaseSliderInput.cs => TestSceneSliderInput.cs} | 2 +- ...tBlueprint.cs => TestSceneSliderPlacementBlueprint.cs} | 2 +- ...nBlueprint.cs => TestSceneSliderSelectionBlueprint.cs} | 4 ++-- .../{TestCaseSpinner.cs => TestSceneSpinner.cs} | 4 ++-- ...TestCaseSpinnerHidden.cs => TestSceneSpinnerHidden.cs} | 4 ++-- ...Blueprint.cs => TestSceneSpinnerPlacementBlueprint.cs} | 2 +- ...Blueprint.cs => TestSceneSpinnerSelectionBlueprint.cs} | 4 ++-- .../{TestCaseInputDrum.cs => TestSceneInputDrum.cs} | 4 ++-- ...stCaseTaikoPlayfield.cs => TestSceneTaikoPlayfield.cs} | 2 +- ...reenBeatmap.cs => TestSceneBackgroundScreenBeatmap.cs} | 2 +- .../{TestCaseIdleTracker.cs => TestSceneIdleTracker.cs} | 4 ++-- ...sePollingComponent.cs => TestScenePollingComponent.cs} | 2 +- ...iewTrackManager.cs => TestScenePreviewTrackManager.cs} | 2 +- ...atDivisorControl.cs => TestSceneBeatDivisorControl.cs} | 2 +- ...TestCaseEditorCompose.cs => TestSceneEditorCompose.cs} | 2 +- ...ioButtons.cs => TestSceneEditorComposeRadioButtons.cs} | 4 ++-- ...mposeTimeline.cs => TestSceneEditorComposeTimeline.cs} | 2 +- ...TestCaseEditorMenuBar.cs => TestSceneEditorMenuBar.cs} | 4 ++-- ...itorSeekSnapping.cs => TestSceneEditorSeekSnapping.cs} | 4 ++-- ...mmaryTimeline.cs => TestSceneEditorSummaryTimeline.cs} | 2 +- ...HitObjectComposer.cs => TestSceneHitObjectComposer.cs} | 2 +- ...CasePlaybackControl.cs => TestScenePlaybackControl.cs} | 2 +- ...TestCaseWaveContainer.cs => TestSceneWaveContainer.cs} | 2 +- .../Editor/{TestCaseWaveform.cs => TestSceneWaveform.cs} | 2 +- ...llContainer.cs => TestSceneZoomableScrollContainer.cs} | 2 +- .../{TestCaseAutoplay.cs => TestSceneAutoplay.cs} | 2 +- .../{TestCaseBreakOverlay.cs => TestSceneBreakOverlay.cs} | 4 ++-- ...tyContainer.cs => TestSceneFrameStabilityContainer.cs} | 4 ++-- ...playMenuOverlay.cs => TestSceneGameplayMenuOverlay.cs} | 2 +- ...HoldForMenuButton.cs => TestSceneHoldForMenuButton.cs} | 2 +- .../{TestCaseKeyCounter.cs => TestSceneKeyCounter.cs} | 4 ++-- .../{TestCaseMedalOverlay.cs => TestSceneMedalOverlay.cs} | 4 ++-- .../Gameplay/{TestCasePause.cs => TestScenePause.cs} | 4 ++-- .../{TestCasePlayerLoader.cs => TestScenePlayerLoader.cs} | 2 +- ...renceLeaking.cs => TestScenePlayerReferenceLeaking.cs} | 2 +- .../Gameplay/{TestCaseReplay.cs => TestSceneReplay.cs} | 2 +- ...ttingsOverlay.cs => TestSceneReplaySettingsOverlay.cs} | 4 ++-- .../Gameplay/{TestCaseResults.cs => TestSceneResults.cs} | 2 +- .../{TestCaseScoreCounter.cs => TestSceneScoreCounter.cs} | 4 ++-- ...llingHitObjects.cs => TestSceneScrollingHitObjects.cs} | 4 ++-- ...stCaseSkinReloadable.cs => TestSceneSkinReloadable.cs} | 2 +- .../{TestCaseSkipOverlay.cs => TestSceneSkipOverlay.cs} | 2 +- .../{TestCaseSongProgress.cs => TestSceneSongProgress.cs} | 4 ++-- .../{TestCaseStoryboard.cs => TestSceneStoryboard.cs} | 4 ++-- .../{TestCaseDisclaimer.cs => TestSceneDisclaimer.cs} | 2 +- ...TestCaseIntroSequence.cs => TestSceneIntroSequence.cs} | 4 ++-- ...CaseLoaderAnimation.cs => TestSceneLoaderAnimation.cs} | 4 ++-- .../Menus/{TestCaseToolbar.cs => TestSceneToolbar.cs} | 4 ++-- ...RoomsContainer.cs => TestSceneLoungeRoomsContainer.cs} | 2 +- .../{TestCaseMatchHeader.cs => TestSceneMatchHeader.cs} | 4 ++-- ...TestCaseMatchHostInfo.cs => TestSceneMatchHostInfo.cs} | 4 ++-- .../{TestCaseMatchInfo.cs => TestSceneMatchInfo.cs} | 2 +- ...seMatchLeaderboard.cs => TestSceneMatchLeaderboard.cs} | 4 ++-- ...MatchParticipants.cs => TestSceneMatchParticipants.cs} | 4 ++-- .../{TestCaseMatchResults.cs => TestSceneMatchResults.cs} | 2 +- ...ettingsOverlay.cs => TestSceneMatchSettingsOverlay.cs} | 2 +- .../{TestCaseMultiHeader.cs => TestSceneMultiHeader.cs} | 4 ++-- .../{TestCaseMultiScreen.cs => TestSceneMultiScreen.cs} | 4 ++-- .../{TestCaseRoomStatus.cs => TestSceneRoomStatus.cs} | 4 ++-- ...ationOverlay.cs => TestSceneAccountCreationOverlay.cs} | 4 ++-- ...BeatmapSetOverlay.cs => TestSceneBeatmapSetOverlay.cs} | 4 ++-- ...ChannelTabControl.cs => TestSceneChannelTabControl.cs} | 4 ++-- .../{TestCaseChatDisplay.cs => TestSceneChatDisplay.cs} | 2 +- .../Online/{TestCaseChatLink.cs => TestSceneChatLink.cs} | 4 ++-- ...TestCaseDirectOverlay.cs => TestSceneDirectOverlay.cs} | 2 +- .../{TestCaseDirectPanel.cs => TestSceneDirectPanel.cs} | 2 +- ...ternalLinkButton.cs => TestSceneExternalLinkButton.cs} | 4 ++-- ...FullscreenOverlay.cs => TestSceneFullscreenOverlay.cs} | 2 +- .../Visual/Online/{TestCaseGraph.cs => TestSceneGraph.cs} | 4 ++-- ...HistoricalSection.cs => TestSceneHistoricalSection.cs} | 4 ++-- .../{TestCaseRankGraph.cs => TestSceneRankGraph.cs} | 4 ++-- ...CaseScoresContainer.cs => TestSceneScoresContainer.cs} | 4 ++-- ...TestCaseSocialOverlay.cs => TestSceneSocialOverlay.cs} | 4 ++-- ...neChatDisplay.cs => TestSceneStandAloneChatDisplay.cs} | 4 ++-- .../{TestCaseUserPanel.cs => TestSceneUserPanel.cs} | 4 ++-- ...UserProfileHeader.cs => TestSceneUserProfileHeader.cs} | 6 +++--- ...erProfileOverlay.cs => TestSceneUserProfileOverlay.cs} | 4 ++-- ...entSection.cs => TestSceneUserProfileRecentSection.cs} | 4 ++-- .../{TestCaseUserRanks.cs => TestSceneUserRanks.cs} | 4 ++-- ...seKeyConfiguration.cs => TestSceneKeyConfiguration.cs} | 4 ++-- .../{TestCaseSettings.cs => TestSceneSettings.cs} | 4 ++-- ...CaseBeatmapCarousel.cs => TestSceneBeatmapCarousel.cs} | 2 +- ...BeatmapDetailArea.cs => TestSceneBeatmapDetailArea.cs} | 4 ++-- ...stCaseBeatmapDetails.cs => TestSceneBeatmapDetails.cs} | 4 ++-- ...seBeatmapInfoWedge.cs => TestSceneBeatmapInfoWedge.cs} | 2 +- ...ptionsOverlay.cs => TestSceneBeatmapOptionsOverlay.cs} | 4 ++-- .../{TestCaseLeaderboard.cs => TestSceneLeaderboard.cs} | 4 ++-- ...stCasePlaySongSelect.cs => TestScenePlaySongSelect.cs} | 2 +- .../Visual/{TestCaseOsuGame.cs => TestSceneOsuGame.cs} | 2 +- ...stCaseOsuScreenStack.cs => TestSceneOsuScreenStack.cs} | 2 +- .../{TestCaseDrawings.cs => TestSceneDrawings.cs} | 2 +- .../Visual/UserInterface/TestCaseLoadingAnimation.cs | 2 +- ...SyncedContainer.cs => TestSceneBeatSyncedContainer.cs} | 4 ++-- .../{TestCaseBreadcrumbs.cs => TestSceneBreadcrumbs.cs} | 4 ++-- .../{TestCaseButtonSystem.cs => TestSceneButtonSystem.cs} | 4 ++-- .../{TestCaseContextMenu.cs => TestSceneContextMenu.cs} | 4 ++-- .../{TestCaseCursors.cs => TestSceneCursors.cs} | 4 ++-- ...TestCaseDialogOverlay.cs => TestSceneDialogOverlay.cs} | 4 ++-- .../{TestCaseDrawableDate.cs => TestSceneDrawableDate.cs} | 4 ++-- ...ConfirmOverlay.cs => TestSceneHoldToConfirmOverlay.cs} | 4 ++-- .../{TestCaseIconButton.cs => TestSceneIconButton.cs} | 4 ++-- ...CaseLabelledTextBox.cs => TestSceneLabelledTextBox.cs} | 2 +- ...kingContainer.cs => TestSceneLogoTrackingContainer.cs} | 2 +- .../UserInterface/{TestCaseMods.cs => TestSceneMods.cs} | 2 +- ...CaseMusicController.cs => TestSceneMusicController.cs} | 4 ++-- ...ficationOverlay.cs => TestSceneNotificationOverlay.cs} | 4 ++-- ...CaseOnScreenDisplay.cs => TestSceneOnScreenDisplay.cs} | 2 +- .../{TestCaseOsuIcon.cs => TestSceneOsuIcon.cs} | 4 ++-- ...ParallaxContainer.cs => TestSceneParallaxContainer.cs} | 4 ++-- .../{TestCasePopupDialog.cs => TestScenePopupDialog.cs} | 4 ++-- ...rumbControl.cs => TestSceneScreenBreadcrumbControl.cs} | 4 ++-- .../{TestCaseTabControl.cs => TestSceneTabControl.cs} | 4 ++-- ...stCaseTwoLayerButton.cs => TestSceneTwoLayerButton.cs} | 4 ++-- ...e.cs => TestSceneUpdateableBeatmapBackgroundSprite.cs} | 2 +- .../{TestCaseVolumePieces.cs => TestSceneVolumePieces.cs} | 2 +- .../{AllPlayersTestCase.cs => AllPlayersTestScene.cs} | 2 +- .../{EditorClockTestCase.cs => EditorClockTestScene.cs} | 4 ++-- .../Visual/{EditorTestCase.cs => EditorTestScene.cs} | 4 ++-- ...tManagerTestCase.cs => ManualInputManagerTestScene.cs} | 4 ++-- .../{MultiplayerTestCase.cs => MultiplayerTestScene.cs} | 2 +- osu.Game/Tests/Visual/{OsuTestCase.cs => OsuTestScene.cs} | 8 ++++---- ...lueprintTestCase.cs => PlacementBlueprintTestScene.cs} | 4 ++-- .../Visual/{PlayerTestCase.cs => PlayerTestScene.cs} | 4 ++-- ...BeatmapTestCase.cs => RateAdjustedBeatmapTestScene.cs} | 2 +- .../Visual/{ScreenTestCase.cs => ScreenTestScene.cs} | 4 ++-- ...lueprintTestCase.cs => SelectionBlueprintTestScene.cs} | 4 ++-- 158 files changed, 261 insertions(+), 261 deletions(-) rename osu.Game.Rulesets.Catch.Tests/{TestCaseAutoJuiceStream.cs => TestSceneAutoJuiceStream.cs} (94%) rename osu.Game.Rulesets.Catch.Tests/{TestCaseBananaShower.cs => TestSceneBananaShower.cs} (93%) rename osu.Game.Rulesets.Catch.Tests/{TestCaseCatchPlayer.cs => TestSceneCatchPlayer.cs} (78%) rename osu.Game.Rulesets.Catch.Tests/{TestCaseCatchStacker.cs => TestSceneCatchStacker.cs} (91%) rename osu.Game.Rulesets.Catch.Tests/{TestCaseCatcherArea.cs => TestSceneCatcherArea.cs} (95%) rename osu.Game.Rulesets.Catch.Tests/{TestCaseFruitObjects.cs => TestSceneFruitObjects.cs} (96%) rename osu.Game.Rulesets.Catch.Tests/{TestCaseHyperDash.cs => TestSceneHyperDash.cs} (94%) rename osu.Game.Rulesets.Mania.Tests/{ManiaInputTestCase.cs => ManiaInputTestScene.cs} (93%) rename osu.Game.Rulesets.Mania.Tests/{ManiaPlacementBlueprintTestCase.cs => ManiaPlacementBlueprintTestScene.cs} (92%) rename osu.Game.Rulesets.Mania.Tests/{ManiaSelectionBlueprintTestCase.cs => ManiaSelectionBlueprintTestScene.cs} (86%) rename osu.Game.Rulesets.Mania.Tests/{TestCaseAutoGeneration.cs => TestSceneAutoGeneration.cs} (99%) rename osu.Game.Rulesets.Mania.Tests/{TestCaseColumn.cs => TestSceneColumn.cs} (97%) rename osu.Game.Rulesets.Mania.Tests/{TestCaseEditor.cs => TestSceneEditor.cs} (92%) rename osu.Game.Rulesets.Mania.Tests/{TestCaseHoldNotePlacementBlueprint.cs => TestSceneHoldNotePlacementBlueprint.cs} (88%) rename osu.Game.Rulesets.Mania.Tests/{TestCaseHoldNoteSelectionBlueprint.cs => TestSceneHoldNoteSelectionBlueprint.cs} (93%) rename osu.Game.Rulesets.Mania.Tests/{TestCaseNotePlacementBlueprint.cs => TestSceneNotePlacementBlueprint.cs} (88%) rename osu.Game.Rulesets.Mania.Tests/{TestCaseNoteSelectionBlueprint.cs => TestSceneNoteSelectionBlueprint.cs} (90%) rename osu.Game.Rulesets.Mania.Tests/{TestCaseNotes.cs => TestSceneNotes.cs} (99%) rename osu.Game.Rulesets.Mania.Tests/{TestCaseStage.cs => TestSceneStage.cs} (98%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseEditor.cs => TestSceneEditor.cs} (79%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseGameplayCursor.cs => TestSceneGameplayCursor.cs} (93%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseHitCircle.cs => TestSceneHitCircle.cs} (97%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseHitCircleHidden.cs => TestSceneHitCircleHidden.cs} (84%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseHitCircleLongCombo.cs => TestSceneHitCircleLongCombo.cs} (89%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseHitCirclePlacementBlueprint.cs => TestSceneHitCirclePlacementBlueprint.cs} (89%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseHitCircleSelectionBlueprint.cs => TestSceneHitCircleSelectionBlueprint.cs} (87%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseOsuFlashlight.cs => TestSceneOsuFlashlight.cs} (89%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseOsuPlayer.cs => TestSceneOsuPlayer.cs} (78%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseResumeOverlay.cs => TestSceneResumeOverlay.cs} (95%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseShaking.cs => TestSceneShaking.cs} (92%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseSlider.cs => TestSceneSlider.cs} (99%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseSliderHidden.cs => TestSceneSliderHidden.cs} (85%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseSliderInput.cs => TestSceneSliderInput.cs} (99%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseSliderPlacementBlueprint.cs => TestSceneSliderPlacementBlueprint.cs} (89%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseSliderSelectionBlueprint.cs => TestSceneSliderSelectionBlueprint.cs} (92%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseSpinner.cs => TestSceneSpinner.cs} (97%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseSpinnerHidden.cs => TestSceneSpinnerHidden.cs} (84%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseSpinnerPlacementBlueprint.cs => TestSceneSpinnerPlacementBlueprint.cs} (89%) rename osu.Game.Rulesets.Osu.Tests/{TestCaseSpinnerSelectionBlueprint.cs => TestSceneSpinnerSelectionBlueprint.cs} (92%) rename osu.Game.Rulesets.Taiko.Tests/{TestCaseInputDrum.cs => TestSceneInputDrum.cs} (93%) rename osu.Game.Rulesets.Taiko.Tests/{TestCaseTaikoPlayfield.cs => TestSceneTaikoPlayfield.cs} (99%) rename osu.Game.Tests/Visual/Background/{TestCaseBackgroundScreenBeatmap.cs => TestSceneBackgroundScreenBeatmap.cs} (99%) rename osu.Game.Tests/Visual/Components/{TestCaseIdleTracker.cs => TestSceneIdleTracker.cs} (97%) rename osu.Game.Tests/Visual/Components/{TestCasePollingComponent.cs => TestScenePollingComponent.cs} (98%) rename osu.Game.Tests/Visual/Components/{TestCasePreviewTrackManager.cs => TestScenePreviewTrackManager.cs} (98%) rename osu.Game.Tests/Visual/Editor/{TestCaseBeatDivisorControl.cs => TestSceneBeatDivisorControl.cs} (93%) rename osu.Game.Tests/Visual/Editor/{TestCaseEditorCompose.cs => TestSceneEditorCompose.cs} (92%) rename osu.Game.Tests/Visual/Editor/{TestCaseEditorComposeRadioButtons.cs => TestSceneEditorComposeRadioButtons.cs} (92%) rename osu.Game.Tests/Visual/Editor/{TestCaseEditorComposeTimeline.cs => TestSceneEditorComposeTimeline.cs} (98%) rename osu.Game.Tests/Visual/Editor/{TestCaseEditorMenuBar.cs => TestSceneEditorMenuBar.cs} (98%) rename osu.Game.Tests/Visual/Editor/{TestCaseEditorSeekSnapping.cs => TestSceneEditorSeekSnapping.cs} (99%) rename osu.Game.Tests/Visual/Editor/{TestCaseEditorSummaryTimeline.cs => TestSceneEditorSummaryTimeline.cs} (93%) rename osu.Game.Tests/Visual/Editor/{TestCaseHitObjectComposer.cs => TestSceneHitObjectComposer.cs} (97%) rename osu.Game.Tests/Visual/Editor/{TestCasePlaybackControl.cs => TestScenePlaybackControl.cs} (94%) rename osu.Game.Tests/Visual/Editor/{TestCaseWaveContainer.cs => TestSceneWaveContainer.cs} (96%) rename osu.Game.Tests/Visual/Editor/{TestCaseWaveform.cs => TestSceneWaveform.cs} (98%) rename osu.Game.Tests/Visual/Editor/{TestCaseZoomableScrollContainer.cs => TestSceneZoomableScrollContainer.cs} (98%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseAutoplay.cs => TestSceneAutoplay.cs} (95%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseBreakOverlay.cs => TestSceneBreakOverlay.cs} (96%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseFrameStabilityContainer.cs => TestSceneFrameStabilityContainer.cs} (97%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseGameplayMenuOverlay.cs => TestSceneGameplayMenuOverlay.cs} (99%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseHoldForMenuButton.cs => TestSceneHoldForMenuButton.cs} (96%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseKeyCounter.cs => TestSceneKeyCounter.cs} (97%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseMedalOverlay.cs => TestSceneMedalOverlay.cs} (90%) rename osu.Game.Tests/Visual/Gameplay/{TestCasePause.cs => TestScenePause.cs} (98%) rename osu.Game.Tests/Visual/Gameplay/{TestCasePlayerLoader.cs => TestScenePlayerLoader.cs} (98%) rename osu.Game.Tests/Visual/Gameplay/{TestCasePlayerReferenceLeaking.cs => TestScenePlayerReferenceLeaking.cs} (95%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseReplay.cs => TestSceneReplay.cs} (96%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseReplaySettingsOverlay.cs => TestSceneReplaySettingsOverlay.cs} (92%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseResults.cs => TestSceneResults.cs} (97%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseScoreCounter.cs => TestSceneScoreCounter.cs} (97%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseScrollingHitObjects.cs => TestSceneScrollingHitObjects.cs} (98%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseSkinReloadable.cs => TestSceneSkinReloadable.cs} (98%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseSkipOverlay.cs => TestSceneSkipOverlay.cs} (89%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseSongProgress.cs => TestSceneSongProgress.cs} (97%) rename osu.Game.Tests/Visual/Gameplay/{TestCaseStoryboard.cs => TestSceneStoryboard.cs} (96%) rename osu.Game.Tests/Visual/Menus/{TestCaseDisclaimer.cs => TestSceneDisclaimer.cs} (94%) rename osu.Game.Tests/Visual/Menus/{TestCaseIntroSequence.cs => TestSceneIntroSequence.cs} (93%) rename osu.Game.Tests/Visual/Menus/{TestCaseLoaderAnimation.cs => TestSceneLoaderAnimation.cs} (97%) rename osu.Game.Tests/Visual/Menus/{TestCaseToolbar.cs => TestSceneToolbar.cs} (94%) rename osu.Game.Tests/Visual/Multiplayer/{TestCaseLoungeRoomsContainer.cs => TestSceneLoungeRoomsContainer.cs} (98%) rename osu.Game.Tests/Visual/Multiplayer/{TestCaseMatchHeader.cs => TestSceneMatchHeader.cs} (93%) rename osu.Game.Tests/Visual/Multiplayer/{TestCaseMatchHostInfo.cs => TestSceneMatchHostInfo.cs} (90%) rename osu.Game.Tests/Visual/Multiplayer/{TestCaseMatchInfo.cs => TestSceneMatchInfo.cs} (97%) rename osu.Game.Tests/Visual/Multiplayer/{TestCaseMatchLeaderboard.cs => TestSceneMatchLeaderboard.cs} (94%) rename osu.Game.Tests/Visual/Multiplayer/{TestCaseMatchParticipants.cs => TestSceneMatchParticipants.cs} (94%) rename osu.Game.Tests/Visual/Multiplayer/{TestCaseMatchResults.cs => TestSceneMatchResults.cs} (98%) rename osu.Game.Tests/Visual/Multiplayer/{TestCaseMatchSettingsOverlay.cs => TestSceneMatchSettingsOverlay.cs} (98%) rename osu.Game.Tests/Visual/Multiplayer/{TestCaseMultiHeader.cs => TestSceneMultiHeader.cs} (92%) rename osu.Game.Tests/Visual/Multiplayer/{TestCaseMultiScreen.cs => TestSceneMultiScreen.cs} (88%) rename osu.Game.Tests/Visual/Multiplayer/{TestCaseRoomStatus.cs => TestSceneRoomStatus.cs} (94%) rename osu.Game.Tests/Visual/Online/{TestCaseAccountCreationOverlay.cs => TestSceneAccountCreationOverlay.cs} (93%) rename osu.Game.Tests/Visual/Online/{TestCaseBeatmapSetOverlay.cs => TestSceneBeatmapSetOverlay.cs} (99%) rename osu.Game.Tests/Visual/Online/{TestCaseChannelTabControl.cs => TestSceneChannelTabControl.cs} (97%) rename osu.Game.Tests/Visual/Online/{TestCaseChatDisplay.cs => TestSceneChatDisplay.cs} (96%) rename osu.Game.Tests/Visual/Online/{TestCaseChatLink.cs => TestSceneChatLink.cs} (99%) rename osu.Game.Tests/Visual/Online/{TestCaseDirectOverlay.cs => TestSceneDirectOverlay.cs} (99%) rename osu.Game.Tests/Visual/Online/{TestCaseDirectPanel.cs => TestSceneDirectPanel.cs} (96%) rename osu.Game.Tests/Visual/Online/{TestCaseExternalLinkButton.cs => TestSceneExternalLinkButton.cs} (84%) rename osu.Game.Tests/Visual/Online/{TestCaseFullscreenOverlay.cs => TestSceneFullscreenOverlay.cs} (94%) rename osu.Game.Tests/Visual/Online/{TestCaseGraph.cs => TestSceneGraph.cs} (94%) rename osu.Game.Tests/Visual/Online/{TestCaseHistoricalSection.cs => TestSceneHistoricalSection.cs} (93%) rename osu.Game.Tests/Visual/Online/{TestCaseRankGraph.cs => TestSceneRankGraph.cs} (97%) rename osu.Game.Tests/Visual/Online/{TestCaseScoresContainer.cs => TestSceneScoresContainer.cs} (98%) rename osu.Game.Tests/Visual/Online/{TestCaseSocialOverlay.cs => TestSceneSocialOverlay.cs} (97%) rename osu.Game.Tests/Visual/Online/{TestCaseStandAloneChatDisplay.cs => TestSceneStandAloneChatDisplay.cs} (96%) rename osu.Game.Tests/Visual/Online/{TestCaseUserPanel.cs => TestSceneUserPanel.cs} (96%) rename osu.Game.Tests/Visual/Online/{TestCaseUserProfileHeader.cs => TestSceneUserProfileHeader.cs} (94%) rename osu.Game.Tests/Visual/Online/{TestCaseUserProfileOverlay.cs => TestSceneUserProfileOverlay.cs} (97%) rename osu.Game.Tests/Visual/Online/{TestCaseUserProfileRecentSection.cs => TestSceneUserProfileRecentSection.cs} (97%) rename osu.Game.Tests/Visual/Online/{TestCaseUserRanks.cs => TestSceneUserRanks.cs} (94%) rename osu.Game.Tests/Visual/Settings/{TestCaseKeyConfiguration.cs => TestSceneKeyConfiguration.cs} (83%) rename osu.Game.Tests/Visual/Settings/{TestCaseSettings.cs => TestSceneSettings.cs} (90%) rename osu.Game.Tests/Visual/SongSelect/{TestCaseBeatmapCarousel.cs => TestSceneBeatmapCarousel.cs} (99%) rename osu.Game.Tests/Visual/SongSelect/{TestCaseBeatmapDetailArea.cs => TestSceneBeatmapDetailArea.cs} (98%) rename osu.Game.Tests/Visual/SongSelect/{TestCaseBeatmapDetails.cs => TestSceneBeatmapDetails.cs} (98%) rename osu.Game.Tests/Visual/SongSelect/{TestCaseBeatmapInfoWedge.cs => TestSceneBeatmapInfoWedge.cs} (99%) rename osu.Game.Tests/Visual/SongSelect/{TestCaseBeatmapOptionsOverlay.cs => TestSceneBeatmapOptionsOverlay.cs} (90%) rename osu.Game.Tests/Visual/SongSelect/{TestCaseLeaderboard.cs => TestSceneLeaderboard.cs} (99%) rename osu.Game.Tests/Visual/SongSelect/{TestCasePlaySongSelect.cs => TestScenePlaySongSelect.cs} (99%) rename osu.Game.Tests/Visual/{TestCaseOsuGame.cs => TestSceneOsuGame.cs} (98%) rename osu.Game.Tests/Visual/{TestCaseOsuScreenStack.cs => TestSceneOsuScreenStack.cs} (97%) rename osu.Game.Tests/Visual/Tournament/{TestCaseDrawings.cs => TestSceneDrawings.cs} (97%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseBeatSyncedContainer.cs => TestSceneBeatSyncedContainer.cs} (98%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseBreadcrumbs.cs => TestSceneBreadcrumbs.cs} (93%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseButtonSystem.cs => TestSceneButtonSystem.cs} (93%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseContextMenu.cs => TestSceneContextMenu.cs} (97%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseCursors.cs => TestSceneCursors.cs} (99%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseDialogOverlay.cs => TestSceneDialogOverlay.cs} (96%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseDrawableDate.cs => TestSceneDrawableDate.cs} (96%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseHoldToConfirmOverlay.cs => TestSceneHoldToConfirmOverlay.cs} (94%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseIconButton.cs => TestSceneIconButton.cs} (97%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseLabelledTextBox.cs => TestSceneLabelledTextBox.cs} (95%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseLogoTrackingContainer.cs => TestSceneLogoTrackingContainer.cs} (99%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseMods.cs => TestSceneMods.cs} (99%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseMusicController.cs => TestSceneMusicController.cs} (89%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseNotificationOverlay.cs => TestSceneNotificationOverlay.cs} (98%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseOnScreenDisplay.cs => TestSceneOnScreenDisplay.cs} (98%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseOsuIcon.cs => TestSceneOsuIcon.cs} (96%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseParallaxContainer.cs => TestSceneParallaxContainer.cs} (91%) rename osu.Game.Tests/Visual/UserInterface/{TestCasePopupDialog.cs => TestScenePopupDialog.cs} (92%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseScreenBreadcrumbControl.cs => TestSceneScreenBreadcrumbControl.cs} (97%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseTabControl.cs => TestSceneTabControl.cs} (93%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseTwoLayerButton.cs => TestSceneTwoLayerButton.cs} (79%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseUpdateableBeatmapBackgroundSprite.cs => TestSceneUpdateableBeatmapBackgroundSprite.cs} (98%) rename osu.Game.Tests/Visual/UserInterface/{TestCaseVolumePieces.cs => TestSceneVolumePieces.cs} (95%) rename osu.Game/Tests/Visual/{AllPlayersTestCase.cs => AllPlayersTestScene.cs} (96%) rename osu.Game/Tests/Visual/{EditorClockTestCase.cs => EditorClockTestScene.cs} (95%) rename osu.Game/Tests/Visual/{EditorTestCase.cs => EditorTestScene.cs} (87%) rename osu.Game/Tests/Visual/{ManualInputManagerTestCase.cs => ManualInputManagerTestScene.cs} (89%) rename osu.Game/Tests/Visual/{MultiplayerTestCase.cs => MultiplayerTestScene.cs} (93%) rename osu.Game/Tests/Visual/{OsuTestCase.cs => OsuTestScene.cs} (95%) rename osu.Game/Tests/Visual/{PlacementBlueprintTestCase.cs => PlacementBlueprintTestScene.cs} (93%) rename osu.Game/Tests/Visual/{PlayerTestCase.cs => PlayerTestScene.cs} (93%) rename osu.Game/Tests/Visual/{RateAdjustedBeatmapTestCase.cs => RateAdjustedBeatmapTestScene.cs} (88%) rename osu.Game/Tests/Visual/{ScreenTestCase.cs => ScreenTestScene.cs} (90%) rename osu.Game/Tests/Visual/{SelectionBlueprintTestCase.cs => SelectionBlueprintTestScene.cs} (92%) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs similarity index 94% rename from osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs rename to osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 102afa9ca6..9cec0d280d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -13,9 +13,9 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests { - public class TestCaseAutoJuiceStream : PlayerTestCase + public class TestSceneAutoJuiceStream : PlayerTestScene { - public TestCaseAutoJuiceStream() + public TestSceneAutoJuiceStream() : base(new CatchRuleset()) { } diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseBananaShower.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs similarity index 93% rename from osu.Game.Rulesets.Catch.Tests/TestCaseBananaShower.cs rename to osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs index d413b53d17..035bbe4b4e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseBananaShower.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs @@ -13,7 +13,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestCaseBananaShower : PlayerTestCase + public class TestSceneBananaShower : PlayerTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Tests typeof(DrawableCatchRuleset), }; - public TestCaseBananaShower() + public TestSceneBananaShower() : base(new CatchRuleset()) { } diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatchPlayer.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs similarity index 78% rename from osu.Game.Rulesets.Catch.Tests/TestCaseCatchPlayer.cs rename to osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs index 5b242d05d7..9836a7811a 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatchPlayer.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs @@ -7,9 +7,9 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestCaseCatchPlayer : PlayerTestCase + public class TestSceneCatchPlayer : PlayerTestScene { - public TestCaseCatchPlayer() + public TestSceneCatchPlayer() : base(new CatchRuleset()) { } diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatchStacker.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs similarity index 91% rename from osu.Game.Rulesets.Catch.Tests/TestCaseCatchStacker.cs rename to osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs index 5a16a23a4e..7d7528372a 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatchStacker.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs @@ -9,9 +9,9 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestCaseCatchStacker : PlayerTestCase + public class TestSceneCatchStacker : PlayerTestScene { - public TestCaseCatchStacker() + public TestSceneCatchStacker() : base(new CatchRuleset()) { } diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs similarity index 95% rename from osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs rename to osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index 5e3fcd239f..3ae6886c31 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -13,7 +13,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestCaseCatcherArea : OsuTestCase + public class TestSceneCatcherArea : OsuTestScene { private RulesetInfo catchRuleset; private TestCatcherArea catcherArea; @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.Tests typeof(CatcherArea), }; - public TestCaseCatcherArea() + public TestSceneCatcherArea() { AddSliderStep("CircleSize", 0, 8, 5, createCatcher); AddToggleStep("Hyperdash", t => catcherArea.ToggleHyperDash(t)); diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseFruitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs similarity index 96% rename from osu.Game.Rulesets.Catch.Tests/TestCaseFruitObjects.cs rename to osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs index a59f4ce150..44517382f7 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseFruitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestCaseFruitObjects : OsuTestCase + public class TestSceneFruitObjects : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.Tests typeof(Pulp), }; - public TestCaseFruitObjects() + public TestSceneFruitObjects() { Add(new GridContainer { diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseHyperDash.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs similarity index 94% rename from osu.Game.Rulesets.Catch.Tests/TestCaseHyperDash.cs rename to osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs index a7e7f0ab14..7393f75e5a 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseHyperDash.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs @@ -10,9 +10,9 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestCaseHyperDash : PlayerTestCase + public class TestSceneHyperDash : PlayerTestScene { - public TestCaseHyperDash() + public TestSceneHyperDash() : base(new CatchRuleset()) { } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs similarity index 93% rename from osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs rename to osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs index f281883e0c..909d0d45c6 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs @@ -8,12 +8,12 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests { - public abstract class ManiaInputTestCase : OsuTestCase + public abstract class ManiaInputTestScene : OsuTestScene { private readonly Container content; protected override Container Content => content ?? base.Content; - protected ManiaInputTestCase(int keys) + protected ManiaInputTestScene(int keys) { base.Content.Add(content = new LocalInputManager(keys)); } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs similarity index 92% rename from osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs rename to osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs index 9ad22498a9..4b3786c30a 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs @@ -20,14 +20,14 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests { [Cached(Type = typeof(IManiaHitObjectComposer))] - public abstract class ManiaPlacementBlueprintTestCase : PlacementBlueprintTestCase, IManiaHitObjectComposer + public abstract class ManiaPlacementBlueprintTestScene : PlacementBlueprintTestScene, IManiaHitObjectComposer { private readonly Column column; [Cached(typeof(IReadOnlyList))] private IReadOnlyList mods { get; set; } = Array.Empty(); - protected ManiaPlacementBlueprintTestCase() + protected ManiaPlacementBlueprintTestScene() { Add(column = new Column(0) { diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestScene.cs similarity index 86% rename from osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs rename to osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestScene.cs index a22e599681..b598893e8c 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestScene.cs @@ -13,14 +13,14 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests { [Cached(Type = typeof(IManiaHitObjectComposer))] - public abstract class ManiaSelectionBlueprintTestCase : SelectionBlueprintTestCase, IManiaHitObjectComposer + public abstract class ManiaSelectionBlueprintTestScene : SelectionBlueprintTestScene, IManiaHitObjectComposer { [Cached(Type = typeof(IAdjustableClock))] private readonly IAdjustableClock clock = new StopwatchClock(); private readonly Column column; - protected ManiaSelectionBlueprintTestCase() + protected ManiaSelectionBlueprintTestScene() { Add(column = new Column(0) { diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs similarity index 99% rename from osu.Game.Rulesets.Mania.Tests/TestCaseAutoGeneration.cs rename to osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs index e8a056bbff..20ac5eaa39 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs @@ -12,7 +12,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests { [TestFixture] - public class TestCaseAutoGeneration : OsuTestCase + public class TestSceneAutoGeneration : OsuTestScene { [Test] public void TestSingleNote() diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs similarity index 97% rename from osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs rename to osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs index d46b661eea..d94a986dae 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs @@ -22,7 +22,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests { [TestFixture] - public class TestCaseColumn : ManiaInputTestCase + public class TestSceneColumn : ManiaInputTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Mania.Tests private readonly List columns = new List(); - public TestCaseColumn() + public TestSceneColumn() : base(2) { } diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneEditor.cs similarity index 92% rename from osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs rename to osu.Game.Rulesets.Mania.Tests/TestSceneEditor.cs index e721eb6fd9..7ed886be49 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneEditor.cs @@ -11,11 +11,11 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests { [TestFixture] - public class TestCaseEditor : EditorTestCase + public class TestSceneEditor : EditorTestScene { private readonly Bindable direction = new Bindable(); - public TestCaseEditor() + public TestSceneEditor() : base(new ManiaRuleset()) { AddStep("upwards scroll", () => direction.Value = ManiaScrollingDirection.Up); diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNotePlacementBlueprint.cs similarity index 88% rename from osu.Game.Rulesets.Mania.Tests/TestCaseHoldNotePlacementBlueprint.cs rename to osu.Game.Rulesets.Mania.Tests/TestSceneHoldNotePlacementBlueprint.cs index 411412e127..b4332264b9 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNotePlacementBlueprint.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Tests { - public class TestCaseHoldNotePlacementBlueprint : ManiaPlacementBlueprintTestCase + public class TestSceneHoldNotePlacementBlueprint : ManiaPlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableHoldNote((HoldNote)hitObject); protected override PlacementBlueprint CreateBlueprint() => new HoldNotePlacementBlueprint(); diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs similarity index 93% rename from osu.Game.Rulesets.Mania.Tests/TestCaseHoldNoteSelectionBlueprint.cs rename to osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs index ae614ae4b8..04c5724f93 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs @@ -15,14 +15,14 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests { - public class TestCaseHoldNoteSelectionBlueprint : ManiaSelectionBlueprintTestCase + public class TestSceneHoldNoteSelectionBlueprint : ManiaSelectionBlueprintTestScene { private readonly DrawableHoldNote drawableObject; protected override Container Content => content ?? base.Content; private readonly Container content; - public TestCaseHoldNoteSelectionBlueprint() + public TestSceneHoldNoteSelectionBlueprint() { var holdNote = new HoldNote { Column = 0, Duration = 1000 }; holdNote.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotePlacementBlueprint.cs similarity index 88% rename from osu.Game.Rulesets.Mania.Tests/TestCaseNotePlacementBlueprint.cs rename to osu.Game.Rulesets.Mania.Tests/TestSceneNotePlacementBlueprint.cs index 12cbeb81f3..d7b539a2a0 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotePlacementBlueprint.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Tests { - public class TestCaseNotePlacementBlueprint : ManiaPlacementBlueprintTestCase + public class TestSceneNotePlacementBlueprint : ManiaPlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableNote((Note)hitObject); protected override PlacementBlueprint CreateBlueprint() => new NotePlacementBlueprint(); diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNoteSelectionBlueprint.cs similarity index 90% rename from osu.Game.Rulesets.Mania.Tests/TestCaseNoteSelectionBlueprint.cs rename to osu.Game.Rulesets.Mania.Tests/TestSceneNoteSelectionBlueprint.cs index 99fe464cfd..6bb344f977 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNoteSelectionBlueprint.cs @@ -15,14 +15,14 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Tests { - public class TestCaseNoteSelectionBlueprint : ManiaSelectionBlueprintTestCase + public class TestSceneNoteSelectionBlueprint : ManiaSelectionBlueprintTestScene { private readonly DrawableNote drawableObject; protected override Container Content => content ?? base.Content; private readonly Container content; - public TestCaseNoteSelectionBlueprint() + public TestSceneNoteSelectionBlueprint() { var note = new Note { Column = 0 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs similarity index 99% rename from osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs rename to osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index 2220873d89..0d143198dd 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs @@ -27,7 +27,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests { [TestFixture] - public class TestCaseNotes : OsuTestCase + public class TestSceneNotes : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs similarity index 98% rename from osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs rename to osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs index 9a7a3d1c5c..395e6daf0a 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Tests { [TestFixture] - public class TestCaseStage : ManiaInputTestCase + public class TestSceneStage : ManiaInputTestScene { private const int columns = 4; @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Mania.Tests private FillFlowContainer fill; - public TestCaseStage() + public TestSceneStage() : base(columns) { } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseEditor.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneEditor.cs similarity index 79% rename from osu.Game.Rulesets.Osu.Tests/TestCaseEditor.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneEditor.cs index 83626e7043..4aca34bf64 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseEditor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneEditor.cs @@ -7,9 +7,9 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestCaseEditor : EditorTestCase + public class TestSceneEditor : EditorTestScene { - public TestCaseEditor() + public TestSceneEditor() : base(new OsuRuleset()) { } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs similarity index 93% rename from osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs index 1e2a936002..1b1cfa89c0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs @@ -15,7 +15,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestCaseGameplayCursor : OsuTestCase, IProvideCursor + public class TestSceneGameplayCursor : OsuTestScene, IProvideCursor { private GameplayCursorContainer cursorContainer; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs similarity index 97% rename from osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs index 31f3146046..d44a0cd841 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs @@ -19,7 +19,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestCaseHitCircle : OsuTestCase + public class TestSceneHitCircle : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Tests private int depthIndex; - public TestCaseHitCircle() + public TestSceneHitCircle() { base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 })); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs similarity index 84% rename from osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleHidden.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs index 7391c0f11a..55c6b22146 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs @@ -10,11 +10,11 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestCaseHitCircleHidden : TestCaseHitCircle + public class TestSceneHitCircleHidden : TestSceneHitCircle { public override IReadOnlyList RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(OsuModHidden) }).ToList(); - public TestCaseHitCircleHidden() + public TestSceneHitCircleHidden() { Mods.Value = new[] { new OsuModHidden() }; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleLongCombo.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs similarity index 89% rename from osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleLongCombo.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs index 8d097ff1c1..921246751c 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleLongCombo.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs @@ -10,9 +10,9 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestCaseHitCircleLongCombo : PlayerTestCase + public class TestSceneHitCircleLongCombo : PlayerTestScene { - public TestCaseHitCircleLongCombo() + public TestSceneHitCircleLongCombo() : base(new OsuRuleset()) { } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCirclePlacementBlueprint.cs similarity index 89% rename from osu.Game.Rulesets.Osu.Tests/TestCaseHitCirclePlacementBlueprint.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneHitCirclePlacementBlueprint.cs index d536e39eef..4c6abc45f7 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCirclePlacementBlueprint.cs @@ -11,7 +11,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseHitCirclePlacementBlueprint : PlacementBlueprintTestCase + public class TestSceneHitCirclePlacementBlueprint : PlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableHitCircle((HitCircle)hitObject); protected override PlacementBlueprint CreateBlueprint() => new HitCirclePlacementBlueprint(); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs similarity index 87% rename from osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleSelectionBlueprint.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs index e9284e453e..32043bf5d7 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs @@ -12,11 +12,11 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseHitCircleSelectionBlueprint : SelectionBlueprintTestCase + public class TestSceneHitCircleSelectionBlueprint : SelectionBlueprintTestScene { private readonly DrawableHitCircle drawableObject; - public TestCaseHitCircleSelectionBlueprint() + public TestSceneHitCircleSelectionBlueprint() { var hitCircle = new HitCircle { Position = new Vector2(256, 192) }; hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 }); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseOsuFlashlight.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs similarity index 89% rename from osu.Game.Rulesets.Osu.Tests/TestCaseOsuFlashlight.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs index 1e72591b87..64e7632b1b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseOsuFlashlight.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs @@ -7,7 +7,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseOsuFlashlight : TestCaseOsuPlayer + public class TestSceneOsuFlashlight : TestSceneOsuPlayer { protected override Player CreatePlayer(Ruleset ruleset) { diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseOsuPlayer.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs similarity index 78% rename from osu.Game.Rulesets.Osu.Tests/TestCaseOsuPlayer.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs index 720c3c66fe..0a33b09ba8 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseOsuPlayer.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs @@ -7,9 +7,9 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestCaseOsuPlayer : PlayerTestCase + public class TestSceneOsuPlayer : PlayerTestScene { - public TestCaseOsuPlayer() + public TestSceneOsuPlayer() : base(new OsuRuleset()) { } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseResumeOverlay.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs similarity index 95% rename from osu.Game.Rulesets.Osu.Tests/TestCaseResumeOverlay.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs index 5956f12146..12a3a8d27e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs @@ -12,14 +12,14 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseResumeOverlay : ManualInputManagerTestCase + public class TestSceneResumeOverlay : ManualInputManagerTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(OsuResumeOverlay), }; - public TestCaseResumeOverlay() + public TestSceneResumeOverlay() { ManualOsuInputManager osuInputManager; CursorContainer cursor; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseShaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs similarity index 92% rename from osu.Game.Rulesets.Osu.Tests/TestCaseShaking.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs index 5dc0dc1024..3d8afd66f4 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseShaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseShaking : TestCaseHitCircle + public class TestSceneShaking : TestSceneHitCircle { public override void Add(Drawable drawable) { diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs similarity index 99% rename from osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 0f02050605..1ba6d107be 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -27,7 +27,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestCaseSlider : OsuTestCase + public class TestSceneSlider : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Tests private int depthIndex; - public TestCaseSlider() + public TestSceneSlider() { base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 })); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs similarity index 85% rename from osu.Game.Rulesets.Osu.Tests/TestCaseSliderHidden.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs index 65a8005407..2a9c1d167b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs @@ -10,11 +10,11 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestCaseSliderHidden : TestCaseSlider + public class TestSceneSliderHidden : TestSceneSlider { public override IReadOnlyList RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(OsuModHidden) }).ToList(); - public TestCaseSliderHidden() + public TestSceneSliderHidden() { Mods.Value = new[] { new OsuModHidden() }; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs similarity index 99% rename from osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index 9a32cf42b0..193cfe9c94 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -26,7 +26,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseSliderInput : RateAdjustedBeatmapTestCase + public class TestSceneSliderInput : RateAdjustedBeatmapTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderPlacementBlueprint.cs similarity index 89% rename from osu.Game.Rulesets.Osu.Tests/TestCaseSliderPlacementBlueprint.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneSliderPlacementBlueprint.cs index f11d98613a..0522260150 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderPlacementBlueprint.cs @@ -11,7 +11,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseSliderPlacementBlueprint : PlacementBlueprintTestCase + public class TestSceneSliderPlacementBlueprint : PlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableSlider((Slider)hitObject); protected override PlacementBlueprint CreateBlueprint() => new SliderPlacementBlueprint(); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs similarity index 92% rename from osu.Game.Rulesets.Osu.Tests/TestCaseSliderSelectionBlueprint.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs index a7386ba48b..8cf5a2f33e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseSliderSelectionBlueprint : SelectionBlueprintTestCase + public class TestSceneSliderSelectionBlueprint : SelectionBlueprintTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Tests private readonly DrawableSlider drawableObject; - public TestCaseSliderSelectionBlueprint() + public TestSceneSliderSelectionBlueprint() { var slider = new Slider { diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs similarity index 97% rename from osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs index ab33d1e518..3ed3f3e981 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs @@ -18,7 +18,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestCaseSpinner : OsuTestCase + public class TestSceneSpinner : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Tests private int depthIndex; - public TestCaseSpinner() + public TestSceneSpinner() { base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 })); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs similarity index 84% rename from osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerHidden.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs index 24e3bcb47b..a0ab1908d6 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs @@ -10,11 +10,11 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestCaseSpinnerHidden : TestCaseSpinner + public class TestSceneSpinnerHidden : TestSceneSpinner { public override IReadOnlyList RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(OsuModHidden) }).ToList(); - public TestCaseSpinnerHidden() + public TestSceneSpinnerHidden() { Mods.Value = new[] { new OsuModHidden() }; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerPlacementBlueprint.cs similarity index 89% rename from osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerPlacementBlueprint.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerPlacementBlueprint.cs index 9001ad3596..d74d072857 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerPlacementBlueprint.cs @@ -11,7 +11,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseSpinnerPlacementBlueprint : PlacementBlueprintTestCase + public class TestSceneSpinnerPlacementBlueprint : PlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableSpinner((Spinner)hitObject); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerSelectionBlueprint.cs similarity index 92% rename from osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerSelectionBlueprint.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerSelectionBlueprint.cs index 11f5ddf8b5..c5cea76b14 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerSelectionBlueprint.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Tests { - public class TestCaseSpinnerSelectionBlueprint : SelectionBlueprintTestCase + public class TestSceneSpinnerSelectionBlueprint : SelectionBlueprintTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Tests private readonly DrawableSpinner drawableSpinner; - public TestCaseSpinnerSelectionBlueprint() + public TestSceneSpinnerSelectionBlueprint() { var spinner = new Spinner { diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseInputDrum.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneInputDrum.cs similarity index 93% rename from osu.Game.Rulesets.Taiko.Tests/TestCaseInputDrum.cs rename to osu.Game.Rulesets.Taiko.Tests/TestSceneInputDrum.cs index 136d9067d5..02300a5dde 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseInputDrum.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneInputDrum.cs @@ -16,7 +16,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests { [TestFixture] - public class TestCaseInputDrum : OsuTestCase + public class TestSceneInputDrum : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Taiko.Tests typeof(SampleControlPoint) }; - public TestCaseInputDrum() + public TestSceneInputDrum() { Add(new TaikoInputManager(new RulesetInfo { ID = 1 }) { diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs similarity index 99% rename from osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs rename to osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index 8cd5918fc5..3634ec7d4a 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -26,7 +26,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Tests { [TestFixture] - public class TestCaseTaikoPlayfield : OsuTestCase + public class TestSceneTaikoPlayfield : OsuTestScene { private const double default_duration = 1000; private const float scroll_time = 1000; diff --git a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs similarity index 99% rename from osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs rename to osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs index 55e8a810fd..10e3dc10c8 100644 --- a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs @@ -35,7 +35,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Background { [TestFixture] - public class TestCaseBackgroundScreenBeatmap : ManualInputManagerTestCase + public class TestSceneBackgroundScreenBeatmap : ManualInputManagerTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Components/TestCaseIdleTracker.cs b/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs similarity index 97% rename from osu.Game.Tests/Visual/Components/TestCaseIdleTracker.cs rename to osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs index bf59c116bb..e97983dd8b 100644 --- a/osu.Game.Tests/Visual/Components/TestCaseIdleTracker.cs +++ b/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs @@ -12,14 +12,14 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Components { [TestFixture] - public class TestCaseIdleTracker : ManualInputManagerTestCase + public class TestSceneIdleTracker : ManualInputManagerTestScene { private readonly IdleTrackingBox box1; private readonly IdleTrackingBox box2; private readonly IdleTrackingBox box3; private readonly IdleTrackingBox box4; - public TestCaseIdleTracker() + public TestSceneIdleTracker() { Children = new Drawable[] { diff --git a/osu.Game.Tests/Visual/Components/TestCasePollingComponent.cs b/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs similarity index 98% rename from osu.Game.Tests/Visual/Components/TestCasePollingComponent.cs rename to osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs index 6582145f6e..fb10015ef4 100644 --- a/osu.Game.Tests/Visual/Components/TestCasePollingComponent.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Components { - public class TestCasePollingComponent : OsuTestCase + public class TestScenePollingComponent : OsuTestScene { private Container pollBox; private TestPoller poller; diff --git a/osu.Game.Tests/Visual/Components/TestCasePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs similarity index 98% rename from osu.Game.Tests/Visual/Components/TestCasePreviewTrackManager.cs rename to osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 4b6ae696fe..94412455a0 100644 --- a/osu.Game.Tests/Visual/Components/TestCasePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -10,7 +10,7 @@ using osu.Game.Beatmaps; namespace osu.Game.Tests.Visual.Components { - public class TestCasePreviewTrackManager : OsuTestCase, IPreviewTrackOwner + public class TestScenePreviewTrackManager : OsuTestScene, IPreviewTrackOwner { private readonly PreviewTrackManager trackManager = new TestPreviewTrackManager(); diff --git a/osu.Game.Tests/Visual/Editor/TestCaseBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editor/TestSceneBeatDivisorControl.cs similarity index 93% rename from osu.Game.Tests/Visual/Editor/TestCaseBeatDivisorControl.cs rename to osu.Game.Tests/Visual/Editor/TestSceneBeatDivisorControl.cs index e822e01110..7531a7be2c 100644 --- a/osu.Game.Tests/Visual/Editor/TestCaseBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneBeatDivisorControl.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Editor { - public class TestCaseBeatDivisorControl : OsuTestCase + public class TestSceneBeatDivisorControl : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(BindableBeatDivisor) }; diff --git a/osu.Game.Tests/Visual/Editor/TestCaseEditorCompose.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorCompose.cs similarity index 92% rename from osu.Game.Tests/Visual/Editor/TestCaseEditorCompose.cs rename to osu.Game.Tests/Visual/Editor/TestSceneEditorCompose.cs index aa7c7f5cb3..b537cb0beb 100644 --- a/osu.Game.Tests/Visual/Editor/TestCaseEditorCompose.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorCompose.cs @@ -12,7 +12,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual.Editor { [TestFixture] - public class TestCaseEditorCompose : EditorClockTestCase + public class TestSceneEditorCompose : EditorClockTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(ComposeScreen) }; diff --git a/osu.Game.Tests/Visual/Editor/TestCaseEditorComposeRadioButtons.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeRadioButtons.cs similarity index 92% rename from osu.Game.Tests/Visual/Editor/TestCaseEditorComposeRadioButtons.cs rename to osu.Game.Tests/Visual/Editor/TestSceneEditorComposeRadioButtons.cs index 499db1b69f..1709067d5d 100644 --- a/osu.Game.Tests/Visual/Editor/TestCaseEditorComposeRadioButtons.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeRadioButtons.cs @@ -10,11 +10,11 @@ using osu.Game.Screens.Edit.Components.RadioButtons; namespace osu.Game.Tests.Visual.Editor { [TestFixture] - public class TestCaseEditorComposeRadioButtons : OsuTestCase + public class TestSceneEditorComposeRadioButtons : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(DrawableRadioButton) }; - public TestCaseEditorComposeRadioButtons() + public TestSceneEditorComposeRadioButtons() { RadioButtonCollection collection; Add(collection = new RadioButtonCollection diff --git a/osu.Game.Tests/Visual/Editor/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs similarity index 98% rename from osu.Game.Tests/Visual/Editor/TestCaseEditorComposeTimeline.cs rename to osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index d7712293c3..154c58dd99 100644 --- a/osu.Game.Tests/Visual/Editor/TestCaseEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editor { [TestFixture] - public class TestCaseEditorComposeTimeline : EditorClockTestCase + public class TestSceneEditorComposeTimeline : EditorClockTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Editor/TestCaseEditorMenuBar.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorMenuBar.cs similarity index 98% rename from osu.Game.Tests/Visual/Editor/TestCaseEditorMenuBar.cs rename to osu.Game.Tests/Visual/Editor/TestSceneEditorMenuBar.cs index b012d4b52d..53c2d62067 100644 --- a/osu.Game.Tests/Visual/Editor/TestCaseEditorMenuBar.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorMenuBar.cs @@ -13,11 +13,11 @@ using osu.Game.Screens.Edit.Components.Menus; namespace osu.Game.Tests.Visual.Editor { [TestFixture] - public class TestCaseEditorMenuBar : OsuTestCase + public class TestSceneEditorMenuBar : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(EditorMenuBar), typeof(ScreenSelectionTabControl) }; - public TestCaseEditorMenuBar() + public TestSceneEditorMenuBar() { Add(new Container { diff --git a/osu.Game.Tests/Visual/Editor/TestCaseEditorSeekSnapping.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs similarity index 99% rename from osu.Game.Tests/Visual/Editor/TestCaseEditorSeekSnapping.cs rename to osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs index 9daba54b58..590fa59107 100644 --- a/osu.Game.Tests/Visual/Editor/TestCaseEditorSeekSnapping.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs @@ -17,9 +17,9 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editor { [TestFixture] - public class TestCaseEditorSeekSnapping : EditorClockTestCase + public class TestSceneEditorSeekSnapping : EditorClockTestScene { - public TestCaseEditorSeekSnapping() + public TestSceneEditorSeekSnapping() { BeatDivisor.Value = 4; } diff --git a/osu.Game.Tests/Visual/Editor/TestCaseEditorSummaryTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorSummaryTimeline.cs similarity index 93% rename from osu.Game.Tests/Visual/Editor/TestCaseEditorSummaryTimeline.cs rename to osu.Game.Tests/Visual/Editor/TestSceneEditorSummaryTimeline.cs index 99d6385804..f20c921ff2 100644 --- a/osu.Game.Tests/Visual/Editor/TestCaseEditorSummaryTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorSummaryTimeline.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Editor { [TestFixture] - public class TestCaseEditorSummaryTimeline : EditorClockTestCase + public class TestSceneEditorSummaryTimeline : EditorClockTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(SummaryTimeline) }; diff --git a/osu.Game.Tests/Visual/Editor/TestCaseHitObjectComposer.cs b/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs similarity index 97% rename from osu.Game.Tests/Visual/Editor/TestCaseHitObjectComposer.cs rename to osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs index be335fb71f..47aa059b62 100644 --- a/osu.Game.Tests/Visual/Editor/TestCaseHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.Editor { [TestFixture] [Cached(Type = typeof(IPlacementHandler))] - public class TestCaseHitObjectComposer : OsuTestCase, IPlacementHandler + public class TestSceneHitObjectComposer : OsuTestScene, IPlacementHandler { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Editor/TestCasePlaybackControl.cs b/osu.Game.Tests/Visual/Editor/TestScenePlaybackControl.cs similarity index 94% rename from osu.Game.Tests/Visual/Editor/TestCasePlaybackControl.cs rename to osu.Game.Tests/Visual/Editor/TestScenePlaybackControl.cs index 7d9b43251e..126ab98291 100644 --- a/osu.Game.Tests/Visual/Editor/TestCasePlaybackControl.cs +++ b/osu.Game.Tests/Visual/Editor/TestScenePlaybackControl.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Editor { [TestFixture] - public class TestCasePlaybackControl : OsuTestCase + public class TestScenePlaybackControl : OsuTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tests/Visual/Editor/TestCaseWaveContainer.cs b/osu.Game.Tests/Visual/Editor/TestSceneWaveContainer.cs similarity index 96% rename from osu.Game.Tests/Visual/Editor/TestCaseWaveContainer.cs rename to osu.Game.Tests/Visual/Editor/TestSceneWaveContainer.cs index e87304ded6..de19727251 100644 --- a/osu.Game.Tests/Visual/Editor/TestCaseWaveContainer.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneWaveContainer.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editor { [TestFixture] - public class TestCaseWaveContainer : OsuTestCase + public class TestSceneWaveContainer : OsuTestScene { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game.Tests/Visual/Editor/TestCaseWaveform.cs b/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs similarity index 98% rename from osu.Game.Tests/Visual/Editor/TestCaseWaveform.cs rename to osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs index ce6ca08a61..e93789b1d3 100644 --- a/osu.Game.Tests/Visual/Editor/TestCaseWaveform.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editor { [TestFixture] - public class TestCaseWaveform : OsuTestCase + public class TestSceneWaveform : OsuTestScene { private WorkingBeatmap waveformBeatmap; diff --git a/osu.Game.Tests/Visual/Editor/TestCaseZoomableScrollContainer.cs b/osu.Game.Tests/Visual/Editor/TestSceneZoomableScrollContainer.cs similarity index 98% rename from osu.Game.Tests/Visual/Editor/TestCaseZoomableScrollContainer.cs rename to osu.Game.Tests/Visual/Editor/TestSceneZoomableScrollContainer.cs index 55c978ae06..da8702209c 100644 --- a/osu.Game.Tests/Visual/Editor/TestCaseZoomableScrollContainer.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneZoomableScrollContainer.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editor { - public class TestCaseZoomableScrollContainer : ManualInputManagerTestCase + public class TestSceneZoomableScrollContainer : ManualInputManagerTestScene { private ZoomableScrollContainer scrollContainer; private Drawable innerBox; diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs similarity index 95% rename from osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index e5dc092c73..452ac859de 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay { [Description("Player instantiated with an autoplay mod.")] - public class TestCaseAutoplay : AllPlayersTestCase + public class TestSceneAutoplay : AllPlayersTestScene { protected override Player CreatePlayer(Ruleset ruleset) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs similarity index 96% rename from osu.Game.Tests/Visual/Gameplay/TestCaseBreakOverlay.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs index dda8005f70..3cd1b8307a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs @@ -9,11 +9,11 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestCaseBreakOverlay : OsuTestCase + public class TestSceneBreakOverlay : OsuTestScene { private readonly BreakOverlay breakOverlay; - public TestCaseBreakOverlay() + public TestSceneBreakOverlay() { Child = breakOverlay = new BreakOverlay(true); diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs similarity index 97% rename from osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs index 7d6430a2cc..5eb71e92c2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseFrameStabilityContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Tests.Visual.Gameplay { - public class TestCaseFrameStabilityContainer : OsuTestCase + public class TestSceneFrameStabilityContainer : OsuTestScene { private readonly ManualClock manualClock; @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Gameplay private ClockConsumingChild consumer; - public TestCaseFrameStabilityContainer() + public TestSceneFrameStabilityContainer() { Child = mainContainer = new Container { diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs similarity index 99% rename from osu.Game.Tests/Visual/Gameplay/TestCaseGameplayMenuOverlay.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs index 8e43bf6d3a..ba9c583b08 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs @@ -17,7 +17,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { [Description("player pause/fail screens")] - public class TestCaseGameplayMenuOverlay : ManualInputManagerTestCase + public class TestSceneGameplayMenuOverlay : ManualInputManagerTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(FailOverlay), typeof(PauseOverlay) }; diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseHoldForMenuButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs similarity index 96% rename from osu.Game.Tests/Visual/Gameplay/TestCaseHoldForMenuButton.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs index 14e9c7cdb6..d42b61ea55 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseHoldForMenuButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs @@ -13,7 +13,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { [Description("'Hold to Quit' UI element")] - public class TestCaseHoldForMenuButton : ManualInputManagerTestCase + public class TestSceneHoldForMenuButton : ManualInputManagerTestScene { private bool exitAction; diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs similarity index 97% rename from osu.Game.Tests/Visual/Gameplay/TestCaseKeyCounter.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 4b55879224..18088a9a5b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -14,7 +14,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestCaseKeyCounter : ManualInputManagerTestCase + public class TestSceneKeyCounter : ManualInputManagerTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.Gameplay typeof(KeyCounterDisplay) }; - public TestCaseKeyCounter() + public TestSceneKeyCounter() { KeyCounterKeyboard rewindTestKeyCounterKeyboard; KeyCounterDisplay kc = new KeyCounterDisplay diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseMedalOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs similarity index 90% rename from osu.Game.Tests/Visual/Gameplay/TestCaseMedalOverlay.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs index dd686c36e6..41722b430e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseMedalOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs @@ -11,7 +11,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestCaseMedalOverlay : OsuTestCase + public class TestSceneMedalOverlay : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Gameplay typeof(DrawableMedal), }; - public TestCaseMedalOverlay() + public TestSceneMedalOverlay() { AddStep(@"display", () => { diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs similarity index 98% rename from osu.Game.Tests/Visual/Gameplay/TestCasePause.cs rename to osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 1a6d58909d..b6f8638f4a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -18,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestCasePause : PlayerTestCase + public class TestScenePause : PlayerTestScene { protected new PausePlayer Player => (PausePlayer)base.Player; @@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Container Content => content; - public TestCasePause() + public TestScenePause() : base(new OsuRuleset()) { base.Content.Add(content = new MenuCursorContainer { RelativeSizeAxes = Axes.Both }); diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs similarity index 98% rename from osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs rename to osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index b9a0421db7..5c26f733ab 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -20,7 +20,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual.Gameplay { - public class TestCasePlayerLoader : ManualInputManagerTestCase + public class TestScenePlayerLoader : ManualInputManagerTestScene { private PlayerLoader loader; private OsuScreenStack stack; diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerReferenceLeaking.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs similarity index 95% rename from osu.Game.Tests/Visual/Gameplay/TestCasePlayerReferenceLeaking.cs rename to osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs index 5937d489f2..d941ad54c0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerReferenceLeaking.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay { - public class TestCasePlayerReferenceLeaking : AllPlayersTestCase + public class TestScenePlayerReferenceLeaking : AllPlayersTestScene { private readonly WeakList workingWeakReferences = new WeakList(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs similarity index 96% rename from osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs index a302c978d2..3fbce9d43c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay { [Description("Player instantiated with a replay.")] - public class TestCaseReplay : AllPlayersTestCase + public class TestSceneReplay : AllPlayersTestScene { protected override Player CreatePlayer(Ruleset ruleset) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseReplaySettingsOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplaySettingsOverlay.cs similarity index 92% rename from osu.Game.Tests/Visual/Gameplay/TestCaseReplaySettingsOverlay.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneReplaySettingsOverlay.cs index 2fdfda0d80..944480243d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseReplaySettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplaySettingsOverlay.cs @@ -10,9 +10,9 @@ using osu.Game.Screens.Play.PlayerSettings; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestCaseReplaySettingsOverlay : OsuTestCase + public class TestSceneReplaySettingsOverlay : OsuTestScene { - public TestCaseReplaySettingsOverlay() + public TestSceneReplaySettingsOverlay() { ExampleContainer container; diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseResults.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs similarity index 97% rename from osu.Game.Tests/Visual/Gameplay/TestCaseResults.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs index d9da45f39a..f3c8f89db7 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseResults.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs @@ -16,7 +16,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestCaseResults : ScreenTestCase + public class TestSceneResults : ScreenTestScene { private BeatmapManager beatmaps; diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseScoreCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs similarity index 97% rename from osu.Game.Tests/Visual/Gameplay/TestCaseScoreCounter.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs index 3dd5c99e45..0c9e3fcd73 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseScoreCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs @@ -12,9 +12,9 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestCaseScoreCounter : OsuTestCase + public class TestSceneScoreCounter : OsuTestScene { - public TestCaseScoreCounter() + public TestSceneScoreCounter() { int numerator = 0, denominator = 0; diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs similarity index 98% rename from osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs index 6998f238c9..0a9cdc6a8e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestCaseScrollingHitObjects : OsuTestCase + public class TestSceneScrollingHitObjects : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(Playfield) }; @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Gameplay private readonly ScrollingTestContainer[] scrollContainers = new ScrollingTestContainer[4]; private readonly TestPlayfield[] playfields = new TestPlayfield[4]; - public TestCaseScrollingHitObjects() + public TestSceneScrollingHitObjects() { Add(new GridContainer { diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseSkinReloadable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs similarity index 98% rename from osu.Game.Tests/Visual/Gameplay/TestCaseSkinReloadable.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs index 56ab70b400..7d6edd0d12 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseSkinReloadable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { - public class TestCaseSkinReloadable : OsuTestCase + public class TestSceneSkinReloadable : OsuTestScene { [Test] public void TestInitialLoad() diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs similarity index 89% rename from osu.Game.Tests/Visual/Gameplay/TestCaseSkipOverlay.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index b46d79ac04..0519660477 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -7,7 +7,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestCaseSkipOverlay : OsuTestCase + public class TestSceneSkipOverlay : OsuTestScene { protected override void LoadComplete() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs similarity index 97% rename from osu.Game.Tests/Visual/Gameplay/TestCaseSongProgress.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index e17dcef19c..af21007efe 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestCaseSongProgress : OsuTestCase + public class TestSceneSongProgress : OsuTestScene { private readonly SongProgress progress; private readonly TestSongProgressGraph graph; @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.Gameplay private readonly FramedClock framedClock; - public TestCaseSongProgress() + public TestSceneSongProgress() { clock = new StopwatchClock(true); diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs similarity index 96% rename from osu.Game.Tests/Visual/Gameplay/TestCaseStoryboard.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs index 651683a671..213cdf5e48 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs @@ -16,12 +16,12 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestCaseStoryboard : OsuTestCase + public class TestSceneStoryboard : OsuTestScene { private readonly Container storyboardContainer; private DrawableStoryboard storyboard; - public TestCaseStoryboard() + public TestSceneStoryboard() { Clock = new FramedClock(); diff --git a/osu.Game.Tests/Visual/Menus/TestCaseDisclaimer.cs b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs similarity index 94% rename from osu.Game.Tests/Visual/Menus/TestCaseDisclaimer.cs rename to osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs index 68a1ceec16..f2718b8e80 100644 --- a/osu.Game.Tests/Visual/Menus/TestCaseDisclaimer.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs @@ -8,7 +8,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Menus { - public class TestCaseDisclaimer : ScreenTestCase + public class TestSceneDisclaimer : ScreenTestScene { [Cached(typeof(IAPIProvider))] private readonly DummyAPIAccess api = new DummyAPIAccess(); diff --git a/osu.Game.Tests/Visual/Menus/TestCaseIntroSequence.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroSequence.cs similarity index 93% rename from osu.Game.Tests/Visual/Menus/TestCaseIntroSequence.cs rename to osu.Game.Tests/Visual/Menus/TestSceneIntroSequence.cs index 0b924e56f5..b59fb18428 100644 --- a/osu.Game.Tests/Visual/Menus/TestCaseIntroSequence.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroSequence.cs @@ -14,14 +14,14 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Menus { [TestFixture] - public class TestCaseIntroSequence : OsuTestCase + public class TestSceneIntroSequence : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(OsuLogo), }; - public TestCaseIntroSequence() + public TestSceneIntroSequence() { OsuLogo logo; diff --git a/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs similarity index 97% rename from osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs rename to osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs index 3f0d965c99..813d4df708 100644 --- a/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs @@ -14,14 +14,14 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Menus { [TestFixture] - public class TestCaseLoaderAnimation : ScreenTestCase + public class TestSceneLoaderAnimation : ScreenTestScene { private TestLoader loader; [Cached] private OsuLogo logo; - public TestCaseLoaderAnimation() + public TestSceneLoaderAnimation() { Child = logo = new OsuLogo { diff --git a/osu.Game.Tests/Visual/Menus/TestCaseToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs similarity index 94% rename from osu.Game.Tests/Visual/Menus/TestCaseToolbar.cs rename to osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index 4da17f9944..0c789d8cb7 100644 --- a/osu.Game.Tests/Visual/Menus/TestCaseToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays.Toolbar; namespace osu.Game.Tests.Visual.Menus { [TestFixture] - public class TestCaseToolbar : OsuTestCase + public class TestSceneToolbar : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.Menus typeof(ToolbarNotificationButton), }; - public TestCaseToolbar() + public TestSceneToolbar() { var toolbar = new Toolbar { State = Visibility.Visible }; ToolbarNotificationButton notificationButton = null; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs similarity index 98% rename from osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index 497da33a05..eb4dc909df 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestCaseLoungeRoomsContainer : MultiplayerTestCase + public class TestSceneLoungeRoomsContainer : MultiplayerTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs similarity index 93% rename from osu.Game.Tests/Visual/Multiplayer/TestCaseMatchHeader.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs index 81cb90c7cd..e42042f2ea 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchHeader.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs @@ -12,14 +12,14 @@ using osu.Game.Screens.Multi.Match.Components; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestCaseMatchHeader : MultiplayerTestCase + public class TestSceneMatchHeader : MultiplayerTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(Header) }; - public TestCaseMatchHeader() + public TestSceneMatchHeader() { Room.Playlist.Add(new PlaylistItem { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchHostInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHostInfo.cs similarity index 90% rename from osu.Game.Tests/Visual/Multiplayer/TestCaseMatchHostInfo.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHostInfo.cs index d2dc417100..808a45cdf0 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchHostInfo.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHostInfo.cs @@ -10,7 +10,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestCaseMatchHostInfo : OsuTestCase + public class TestSceneMatchHostInfo : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private readonly Bindable host = new Bindable(new User { Username = "SomeHost" }); - public TestCaseMatchHostInfo() + public TestSceneMatchHostInfo() { HostInfo hostInfo; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchInfo.cs similarity index 97% rename from osu.Game.Tests/Visual/Multiplayer/TestCaseMatchInfo.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneMatchInfo.cs index 6b04b71da4..3f0c0b07b7 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchInfo.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchInfo.cs @@ -14,7 +14,7 @@ using osu.Game.Screens.Multi.Match.Components; namespace osu.Game.Tests.Visual.Multiplayer { [TestFixture] - public class TestCaseMatchInfo : MultiplayerTestCase + public class TestSceneMatchInfo : MultiplayerTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs similarity index 94% rename from osu.Game.Tests/Visual/Multiplayer/TestCaseMatchLeaderboard.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs index 8ec323dbc3..fa3c392b2e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs @@ -12,9 +12,9 @@ using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestCaseMatchLeaderboard : MultiplayerTestCase + public class TestSceneMatchLeaderboard : MultiplayerTestScene { - public TestCaseMatchLeaderboard() + public TestSceneMatchLeaderboard() { Room.RoomID.Value = 3; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchParticipants.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchParticipants.cs similarity index 94% rename from osu.Game.Tests/Visual/Multiplayer/TestCaseMatchParticipants.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneMatchParticipants.cs index 5382726516..50df4022dc 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchParticipants.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchParticipants.cs @@ -9,9 +9,9 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { [TestFixture] - public class TestCaseMatchParticipants : MultiplayerTestCase + public class TestSceneMatchParticipants : MultiplayerTestScene { - public TestCaseMatchParticipants() + public TestSceneMatchParticipants() { Add(new Participants { RelativeSizeAxes = Axes.Both }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchResults.cs similarity index 98% rename from osu.Game.Tests/Visual/Multiplayer/TestCaseMatchResults.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneMatchResults.cs index 69606c9ba7..7915a981dd 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchResults.cs @@ -18,7 +18,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestCaseMatchResults : MultiplayerTestCase + public class TestSceneMatchResults : MultiplayerTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs similarity index 98% rename from osu.Game.Tests/Visual/Multiplayer/TestCaseMatchSettingsOverlay.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs index 51854800e3..21b97fe73b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs @@ -17,7 +17,7 @@ using osu.Game.Screens.Multi.Match.Components; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestCaseMatchSettingsOverlay : MultiplayerTestCase + public class TestSceneMatchSettingsOverlay : MultiplayerTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseMultiHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs similarity index 92% rename from osu.Game.Tests/Visual/Multiplayer/TestCaseMultiHeader.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs index b49bb7fd84..3f89f636b1 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestCaseMultiHeader.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs @@ -10,9 +10,9 @@ using osu.Game.Screens.Multi; namespace osu.Game.Tests.Visual.Multiplayer { [TestFixture] - public class TestCaseMultiHeader : OsuTestCase + public class TestSceneMultiHeader : OsuTestScene { - public TestCaseMultiHeader() + public TestSceneMultiHeader() { int index = 0; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseMultiScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs similarity index 88% rename from osu.Game.Tests/Visual/Multiplayer/TestCaseMultiScreen.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs index ef381efd67..069e133c2b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestCaseMultiScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Multi.Lounge.Components; namespace osu.Game.Tests.Visual.Multiplayer { [TestFixture] - public class TestCaseMultiScreen : ScreenTestCase + public class TestSceneMultiScreen : ScreenTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Multiplayer typeof(FilterControl) }; - public TestCaseMultiScreen() + public TestSceneMultiScreen() { Screens.Multi.Multiplayer multi = new Screens.Multi.Multiplayer(); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseRoomStatus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomStatus.cs similarity index 94% rename from osu.Game.Tests/Visual/Multiplayer/TestCaseRoomStatus.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneRoomStatus.cs index a7c7d41ed4..74d1645f6d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestCaseRoomStatus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomStatus.cs @@ -11,7 +11,7 @@ using osu.Game.Screens.Multi.Lounge.Components; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestCaseRoomStatus : OsuTestCase + public class TestSceneRoomStatus : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.Multiplayer typeof(RoomStatusPlaying) }; - public TestCaseRoomStatus() + public TestSceneRoomStatus() { Child = new FillFlowContainer { diff --git a/osu.Game.Tests/Visual/Online/TestCaseAccountCreationOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs similarity index 93% rename from osu.Game.Tests/Visual/Online/TestCaseAccountCreationOverlay.cs rename to osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs index 5cdb90b61f..a7e725ec3f 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseAccountCreationOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs @@ -13,7 +13,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { - public class TestCaseAccountCreationOverlay : OsuTestCase + public class TestSceneAccountCreationOverlay : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -28,7 +28,7 @@ namespace osu.Game.Tests.Visual.Online [Cached(typeof(IAPIProvider))] private DummyAPIAccess api = new DummyAPIAccess(); - public TestCaseAccountCreationOverlay() + public TestSceneAccountCreationOverlay() { Container userPanelArea; AccountCreationOverlay accountCreation; diff --git a/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs similarity index 99% rename from osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs rename to osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 8363f8be04..5910da7b88 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -17,7 +17,7 @@ using System.Linq; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseBeatmapSetOverlay : OsuTestCase + public class TestSceneBeatmapSetOverlay : OsuTestScene { private readonly BeatmapSetOverlay overlay; @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.Online typeof(SuccessRate), }; - public TestCaseBeatmapSetOverlay() + public TestSceneBeatmapSetOverlay() { Add(overlay = new BeatmapSetOverlay()); } diff --git a/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs b/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs similarity index 97% rename from osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs rename to osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs index 356ede0d57..d93daba4d4 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Online { - public class TestCaseChannelTabControl : OsuTestCase + public class TestSceneChannelTabControl : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual.Online private readonly ChannelTabControl channelTabControl; - public TestCaseChannelTabControl() + public TestSceneChannelTabControl() { SpriteText currentText; Add(new Container diff --git a/osu.Game.Tests/Visual/Online/TestCaseChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatDisplay.cs similarity index 96% rename from osu.Game.Tests/Visual/Online/TestCaseChatDisplay.cs rename to osu.Game.Tests/Visual/Online/TestSceneChatDisplay.cs index 6e20165c1b..634176e65f 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatDisplay.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays.Chat.Tabs; namespace osu.Game.Tests.Visual.Online { [Description("Testing chat api and overlay")] - public class TestCaseChatDisplay : OsuTestCase + public class TestSceneChatDisplay : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Online/TestCaseChatLink.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs similarity index 99% rename from osu.Game.Tests/Visual/Online/TestCaseChatLink.cs rename to osu.Game.Tests/Visual/Online/TestSceneChatLink.cs index 8843f136a1..c18e0e3064 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseChatLink.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs @@ -21,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseChatLink : OsuTestCase + public class TestSceneChatLink : OsuTestScene { private readonly TestChatLineContainer textContainer; private readonly DialogOverlay dialogOverlay; @@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual.Online typeof(MessageFormatter) }; - public TestCaseChatLink() + public TestSceneChatLink() { Add(dialogOverlay = new DialogOverlay { Depth = float.MinValue }); Add(textContainer = new TestChatLineContainer diff --git a/osu.Game.Tests/Visual/Online/TestCaseDirectOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs similarity index 99% rename from osu.Game.Tests/Visual/Online/TestCaseDirectOverlay.cs rename to osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs index 677b49e1af..efc12c5fdd 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseDirectOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseDirectOverlay : OsuTestCase + public class TestSceneDirectOverlay : OsuTestScene { private DirectOverlay direct; private RulesetStore rulesets; diff --git a/osu.Game.Tests/Visual/Online/TestCaseDirectPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs similarity index 96% rename from osu.Game.Tests/Visual/Online/TestCaseDirectPanel.cs rename to osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs index fbda531792..a3d932a383 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseDirectPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { - public class TestCaseDirectPanel : OsuTestCase + public class TestSceneDirectPanel : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Online/TestCaseExternalLinkButton.cs b/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs similarity index 84% rename from osu.Game.Tests/Visual/Online/TestCaseExternalLinkButton.cs rename to osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs index a73cbd86d0..637b577021 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseExternalLinkButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs @@ -8,11 +8,11 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { - public class TestCaseExternalLinkButton : OsuTestCase + public class TestSceneExternalLinkButton : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(ExternalLinkButton) }; - public TestCaseExternalLinkButton() + public TestSceneExternalLinkButton() { Child = new ExternalLinkButton("https://osu.ppy.sh/home") { diff --git a/osu.Game.Tests/Visual/Online/TestCaseFullscreenOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs similarity index 94% rename from osu.Game.Tests/Visual/Online/TestCaseFullscreenOverlay.cs rename to osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs index 925e6e1349..6dc3428bff 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseFullscreenOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseFullscreenOverlay : OsuTestCase + public class TestSceneFullscreenOverlay : OsuTestScene { private FullscreenOverlay overlay; diff --git a/osu.Game.Tests/Visual/Online/TestCaseGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneGraph.cs similarity index 94% rename from osu.Game.Tests/Visual/Online/TestCaseGraph.cs rename to osu.Game.Tests/Visual/Online/TestSceneGraph.cs index 77e850fc92..fa433571cf 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneGraph.cs @@ -10,9 +10,9 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseGraph : OsuTestCase + public class TestSceneGraph : OsuTestScene { - public TestCaseGraph() + public TestSceneGraph() { BarGraph graph; diff --git a/osu.Game.Tests/Visual/Online/TestCaseHistoricalSection.cs b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs similarity index 93% rename from osu.Game.Tests/Visual/Online/TestCaseHistoricalSection.cs rename to osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs index 92aa9320c8..455807649a 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseHistoricalSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs @@ -15,7 +15,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseHistoricalSection : OsuTestCase + public class TestSceneHistoricalSection : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] @@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual.Online typeof(DrawableProfileRow) }; - public TestCaseHistoricalSection() + public TestSceneHistoricalSection() { HistoricalSection section; diff --git a/osu.Game.Tests/Visual/Online/TestCaseRankGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs similarity index 97% rename from osu.Game.Tests/Visual/Online/TestCaseRankGraph.cs rename to osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs index a92b788e83..c04a4249cc 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseRankGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseRankGraph : OsuTestCase + public class TestSceneRankGraph : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Online typeof(LineGraph) }; - public TestCaseRankGraph() + public TestSceneRankGraph() { RankGraph graph; diff --git a/osu.Game.Tests/Visual/Online/TestCaseScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs similarity index 98% rename from osu.Game.Tests/Visual/Online/TestCaseScoresContainer.cs rename to osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index 1ef4558691..6815018be6 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -18,7 +18,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { - public class TestCaseScoresContainer : OsuTestCase + public class TestSceneScoresContainer : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Online private readonly Box background; - public TestCaseScoresContainer() + public TestSceneScoresContainer() { ScoresContainer scoresContainer; diff --git a/osu.Game.Tests/Visual/Online/TestCaseSocialOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs similarity index 97% rename from osu.Game.Tests/Visual/Online/TestCaseSocialOverlay.cs rename to osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs index 2c524da99d..5cb96c7ed2 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseSocialOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs @@ -11,7 +11,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseSocialOverlay : OsuTestCase + public class TestSceneSocialOverlay : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.Online typeof(SocialListPanel) }; - public TestCaseSocialOverlay() + public TestSceneSocialOverlay() { SocialOverlay s = new SocialOverlay { diff --git a/osu.Game.Tests/Visual/Online/TestCaseStandAloneChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs similarity index 96% rename from osu.Game.Tests/Visual/Online/TestCaseStandAloneChatDisplay.cs rename to osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs index 4c4b3b2612..91006bc0d9 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseStandAloneChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { - public class TestCaseStandAloneChatDisplay : OsuTestCase + public class TestSceneStandAloneChatDisplay : OsuTestScene { private readonly Channel testChannel = new Channel(); @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Online private readonly StandAloneChatDisplay chatDisplay; private readonly StandAloneChatDisplay chatDisplay2; - public TestCaseStandAloneChatDisplay() + public TestSceneStandAloneChatDisplay() { Add(channelManager); diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs similarity index 96% rename from osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs rename to osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index b015418d78..fca18a9263 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -10,9 +10,9 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseUserPanel : OsuTestCase + public class TestSceneUserPanel : OsuTestScene { - public TestCaseUserPanel() + public TestSceneUserPanel() { UserPanel flyte; UserPanel peppy; diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs similarity index 94% rename from osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs rename to osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index 887228c06e..14c81558c1 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -14,7 +14,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { - public class TestCaseUserProfileHeader : OsuTestCase + public class TestSceneUserProfileHeader : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -33,12 +33,12 @@ namespace osu.Game.Tests.Visual.Online private readonly ProfileHeader header; - public TestCaseUserProfileHeader() + public TestSceneUserProfileHeader() { header = new ProfileHeader(); Add(header); - AddStep("Show offline dummy", () => header.User.Value = TestCaseUserProfileOverlay.TEST_USER); + AddStep("Show offline dummy", () => header.User.Value = TestSceneUserProfileOverlay.TEST_USER); AddStep("Show null dummy", () => header.User.Value = new User { diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs similarity index 97% rename from osu.Game.Tests/Visual/Online/TestCaseUserProfileOverlay.cs rename to osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index 6940392f32..c2376aa153 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -17,7 +17,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseUserProfileOverlay : OsuTestCase + public class TestSceneUserProfileOverlay : OsuTestScene { private readonly TestUserProfileOverlay profile; @@ -71,7 +71,7 @@ namespace osu.Game.Tests.Visual.Online Achievements = new User.UserAchievement[0], }; - public TestCaseUserProfileOverlay() + public TestSceneUserProfileOverlay() { Add(profile = new TestUserProfileOverlay()); } diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserProfileRecentSection.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs similarity index 97% rename from osu.Game.Tests/Visual/Online/TestCaseUserProfileRecentSection.cs rename to osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs index 6b29ed1e85..d60e723102 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserProfileRecentSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs @@ -17,7 +17,7 @@ using osu.Game.Overlays.Profile.Sections.Recent; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseUserProfileRecentSection : OsuTestCase + public class TestSceneUserProfileRecentSection : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.Online typeof(MedalIcon) }; - public TestCaseUserProfileRecentSection() + public TestSceneUserProfileRecentSection() { Children = new Drawable[] { diff --git a/osu.Game.Tests/Visual/Online/TestCaseUserRanks.cs b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs similarity index 94% rename from osu.Game.Tests/Visual/Online/TestCaseUserRanks.cs rename to osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs index 64257f8877..70118b5ebd 100644 --- a/osu.Game.Tests/Visual/Online/TestCaseUserRanks.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs @@ -15,11 +15,11 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseUserRanks : OsuTestCase + public class TestSceneUserRanks : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(DrawableProfileScore), typeof(RanksSection) }; - public TestCaseUserRanks() + public TestSceneUserRanks() { RanksSection ranks; diff --git a/osu.Game.Tests/Visual/Settings/TestCaseKeyConfiguration.cs b/osu.Game.Tests/Visual/Settings/TestSceneKeyConfiguration.cs similarity index 83% rename from osu.Game.Tests/Visual/Settings/TestCaseKeyConfiguration.cs rename to osu.Game.Tests/Visual/Settings/TestSceneKeyConfiguration.cs index fccd48b85c..d06d82ddb5 100644 --- a/osu.Game.Tests/Visual/Settings/TestCaseKeyConfiguration.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneKeyConfiguration.cs @@ -7,11 +7,11 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Settings { [TestFixture] - public class TestCaseKeyConfiguration : OsuTestCase + public class TestSceneKeyConfiguration : OsuTestScene { private readonly KeyBindingPanel panel; - public TestCaseKeyConfiguration() + public TestSceneKeyConfiguration() { Child = panel = new KeyBindingPanel(); } diff --git a/osu.Game.Tests/Visual/Settings/TestCaseSettings.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettings.cs similarity index 90% rename from osu.Game.Tests/Visual/Settings/TestCaseSettings.cs rename to osu.Game.Tests/Visual/Settings/TestSceneSettings.cs index 5b6c033c1d..964754f8d0 100644 --- a/osu.Game.Tests/Visual/Settings/TestCaseSettings.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettings.cs @@ -9,12 +9,12 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Settings { [TestFixture] - public class TestCaseSettings : OsuTestCase + public class TestSceneSettings : OsuTestScene { private readonly SettingsPanel settings; private readonly DialogOverlay dialogOverlay; - public TestCaseSettings() + public TestSceneSettings() { settings = new SettingsOverlay { diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs similarity index 99% rename from osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapCarousel.cs rename to osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 1ffc164026..7c9b7c7815 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -20,7 +20,7 @@ using osu.Game.Screens.Select.Filter; namespace osu.Game.Tests.Visual.SongSelect { [TestFixture] - public class TestCaseBeatmapCarousel : OsuTestCase + public class TestSceneBeatmapCarousel : OsuTestScene { private TestBeatmapCarousel carousel; private RulesetStore rulesets; diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs similarity index 98% rename from osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapDetailArea.cs rename to osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index 722a63f2b0..cf4362ba28 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -14,11 +14,11 @@ namespace osu.Game.Tests.Visual.SongSelect { [TestFixture] [System.ComponentModel.Description("PlaySongSelect leaderboard/details area")] - public class TestCaseBeatmapDetailArea : OsuTestCase + public class TestSceneBeatmapDetailArea : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(BeatmapDetails) }; - public TestCaseBeatmapDetailArea() + public TestSceneBeatmapDetailArea() { BeatmapDetailArea detailsArea; Add(detailsArea = new BeatmapDetailArea diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs similarity index 98% rename from osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapDetails.cs rename to osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index 37987b8884..acbbd4e18b 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -10,9 +10,9 @@ using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.SongSelect { [Description("PlaySongSelect beatmap details")] - public class TestCaseBeatmapDetails : OsuTestCase + public class TestSceneBeatmapDetails : OsuTestScene { - public TestCaseBeatmapDetails() + public TestSceneBeatmapDetails() { BeatmapDetails details; Add(details = new BeatmapDetails diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs similarity index 99% rename from osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapInfoWedge.cs rename to osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index 36a7eba37f..b1ed5c46c2 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -24,7 +24,7 @@ using osuTK; namespace osu.Game.Tests.Visual.SongSelect { [TestFixture] - public class TestCaseBeatmapInfoWedge : OsuTestCase + public class TestSceneBeatmapInfoWedge : OsuTestScene { private RulesetStore rulesets; private TestBeatmapInfoWedge infoWedge; diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapOptionsOverlay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs similarity index 90% rename from osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapOptionsOverlay.cs rename to osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs index 7d09debbd6..ecdc484887 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapOptionsOverlay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs @@ -10,9 +10,9 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.SongSelect { [Description("bottom beatmap details")] - public class TestCaseBeatmapOptionsOverlay : OsuTestCase + public class TestSceneBeatmapOptionsOverlay : OsuTestScene { - public TestCaseBeatmapOptionsOverlay() + public TestSceneBeatmapOptionsOverlay() { var overlay = new BeatmapOptionsOverlay(); diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs similarity index 99% rename from osu.Game.Tests/Visual/SongSelect/TestCaseLeaderboard.cs rename to osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs index 13ae6f228a..3d75470328 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCaseLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Tests.Visual.SongSelect { [Description("PlaySongSelect leaderboard")] - public class TestCaseLeaderboard : OsuTestCase + public class TestSceneLeaderboard : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.SongSelect private readonly FailableLeaderboard leaderboard; - public TestCaseLeaderboard() + public TestSceneLeaderboard() { Add(leaderboard = new FailableLeaderboard { diff --git a/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs similarity index 99% rename from osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs rename to osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 7e33f6ce02..7e962dbc06 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -26,7 +26,7 @@ using osu.Game.Screens.Select.Filter; namespace osu.Game.Tests.Visual.SongSelect { [TestFixture] - public class TestCasePlaySongSelect : ScreenTestCase + public class TestScenePlaySongSelect : ScreenTestScene { private BeatmapManager manager; diff --git a/osu.Game.Tests/Visual/TestCaseOsuGame.cs b/osu.Game.Tests/Visual/TestSceneOsuGame.cs similarity index 98% rename from osu.Game.Tests/Visual/TestCaseOsuGame.cs rename to osu.Game.Tests/Visual/TestSceneOsuGame.cs index dd98ff088c..c44547677e 100644 --- a/osu.Game.Tests/Visual/TestCaseOsuGame.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuGame.cs @@ -32,7 +32,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual { [TestFixture] - public class TestCaseOsuGame : OsuTestCase + public class TestSceneOsuGame : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/TestCaseOsuScreenStack.cs b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs similarity index 97% rename from osu.Game.Tests/Visual/TestCaseOsuScreenStack.cs rename to osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs index 0831228681..53ce25ebb3 100644 --- a/osu.Game.Tests/Visual/TestCaseOsuScreenStack.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual { [TestFixture] - public class TestCaseOsuScreenStack : OsuTestCase + public class TestSceneOsuScreenStack : OsuTestScene { private TestOsuScreenStack stack; diff --git a/osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs b/osu.Game.Tests/Visual/Tournament/TestSceneDrawings.cs similarity index 97% rename from osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs rename to osu.Game.Tests/Visual/Tournament/TestSceneDrawings.cs index 53fb60bcb6..995819f7ae 100644 --- a/osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs +++ b/osu.Game.Tests/Visual/Tournament/TestSceneDrawings.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Tournament.Teams; namespace osu.Game.Tests.Visual.Tournament { [Description("for tournament use")] - public class TestCaseDrawings : ScreenTestCase + public class TestSceneDrawings : ScreenTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs index 1cfd56e2c8..9befac94f2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs @@ -9,7 +9,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestCaseLoadingAnimation : GridTestScene //todo: this should be an OsuTestCase + public class TestCaseLoadingAnimation : GridTestScene //todo: this should be an OsuTestScene { public TestCaseLoadingAnimation() : base(2, 2) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs similarity index 98% rename from osu.Game.Tests/Visual/UserInterface/TestCaseBeatSyncedContainer.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index dcd194e050..28f0cc027e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -20,11 +20,11 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseBeatSyncedContainer : OsuTestCase + public class TestSceneBeatSyncedContainer : OsuTestScene { private readonly MusicController mc; - public TestCaseBeatSyncedContainer() + public TestSceneBeatSyncedContainer() { Clock = new FramedClock(); Clock.ProcessFrame(); diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseBreadcrumbs.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbs.cs similarity index 93% rename from osu.Game.Tests/Visual/UserInterface/TestCaseBreadcrumbs.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbs.cs index 5e09e0a5b9..554696765e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseBreadcrumbs.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbs.cs @@ -10,11 +10,11 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseBreadcrumbs : OsuTestCase + public class TestSceneBreadcrumbs : OsuTestScene { private readonly BreadcrumbControl breadcrumbs; - public TestCaseBreadcrumbs() + public TestSceneBreadcrumbs() { Add(breadcrumbs = new BreadcrumbControl { diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs similarity index 93% rename from osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs index 04aa8bce7e..c8cc864089 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseButtonSystem : OsuTestCase + public class TestSceneButtonSystem : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.UserInterface typeof(Button) }; - public TestCaseButtonSystem() + public TestSceneButtonSystem() { OsuLogo logo; ButtonSystem buttons; diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseContextMenu.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs similarity index 97% rename from osu.Game.Tests/Visual/UserInterface/TestCaseContextMenu.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs index 71cde787f9..53693d1b70 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseContextMenu.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs @@ -15,14 +15,14 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseContextMenu : OsuTestCase + public class TestSceneContextMenu : OsuTestScene { private const int start_time = 0; private const int duration = 1000; private readonly Container container; - public TestCaseContextMenu() + public TestSceneContextMenu() { Add(new OsuContextMenuContainer { diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseCursors.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs similarity index 99% rename from osu.Game.Tests/Visual/UserInterface/TestCaseCursors.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs index 5f45d9ba4d..590ee4e720 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseCursors.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs @@ -17,12 +17,12 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseCursors : ManualInputManagerTestCase + public class TestSceneCursors : ManualInputManagerTestScene { private readonly MenuCursorContainer menuCursorContainer; private readonly CustomCursorBox[] cursorBoxes = new CustomCursorBox[6]; - public TestCaseCursors() + public TestSceneCursors() { Child = menuCursorContainer = new MenuCursorContainer { diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseDialogOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs similarity index 96% rename from osu.Game.Tests/Visual/UserInterface/TestCaseDialogOverlay.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs index 8964d20564..a6ff3462d4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseDialogOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs @@ -9,9 +9,9 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseDialogOverlay : OsuTestCase + public class TestSceneDialogOverlay : OsuTestScene { - public TestCaseDialogOverlay() + public TestSceneDialogOverlay() { DialogOverlay overlay; diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseDrawableDate.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs similarity index 96% rename from osu.Game.Tests/Visual/UserInterface/TestCaseDrawableDate.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs index e8662ce965..19097f33bb 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseDrawableDate.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs @@ -11,9 +11,9 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestCaseDrawableDate : OsuTestCase + public class TestSceneDrawableDate : OsuTestScene { - public TestCaseDrawableDate() + public TestSceneDrawableDate() { Child = new FillFlowContainer { diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs similarity index 94% rename from osu.Game.Tests/Visual/UserInterface/TestCaseHoldToConfirmOverlay.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs index 38dc4a11dc..7e6cf1285e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseHoldToConfirmOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs @@ -10,11 +10,11 @@ using osu.Game.Screens.Menu; namespace osu.Game.Tests.Visual.UserInterface { - public class TestCaseHoldToConfirmOverlay : OsuTestCase + public class TestSceneHoldToConfirmOverlay : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(ExitConfirmOverlay) }; - public TestCaseHoldToConfirmOverlay() + public TestSceneHoldToConfirmOverlay() { bool fired = false; diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseIconButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs similarity index 97% rename from osu.Game.Tests/Visual/UserInterface/TestCaseIconButton.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs index 6bb1347608..0c9ce50288 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseIconButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs @@ -14,9 +14,9 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseIconButton : OsuTestCase + public class TestSceneIconButton : OsuTestScene { - public TestCaseIconButton() + public TestSceneIconButton() { Child = new FillFlowContainer { diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLabelledTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs similarity index 95% rename from osu.Game.Tests/Visual/UserInterface/TestCaseLabelledTextBox.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs index 781dfbdcc1..395905a30d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLabelledTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs @@ -12,7 +12,7 @@ using osu.Game.Screens.Edit.Setup.Components.LabelledComponents; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseLabelledTextBox : OsuTestCase + public class TestSceneLabelledTextBox : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs similarity index 99% rename from osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs index e45e2e24da..54876dbbda 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLogoTrackingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestCaseLogoTrackingContainer : OsuTestCase + public class TestSceneLogoTrackingContainer : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneMods.cs similarity index 99% rename from osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneMods.cs index fd003c7ea2..2e36ba39ed 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneMods.cs @@ -24,7 +24,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [Description("mod select and icon display")] - public class TestCaseMods : OsuTestCase + public class TestSceneMods : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseMusicController.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs similarity index 89% rename from osu.Game.Tests/Visual/UserInterface/TestCaseMusicController.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs index 644c7eb4fc..a62fd6467b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseMusicController.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs @@ -10,9 +10,9 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseMusicController : OsuTestCase + public class TestSceneMusicController : OsuTestScene { - public TestCaseMusicController() + public TestSceneMusicController() { Clock = new FramedClock(); diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseNotificationOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs similarity index 98% rename from osu.Game.Tests/Visual/UserInterface/TestCaseNotificationOverlay.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs index faf80d22ff..0cb7c2484d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays.Notifications; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseNotificationOverlay : OsuTestCase + public class TestSceneNotificationOverlay : OsuTestScene { private readonly NotificationOverlay manager; private readonly List progressingNotifications = new List(); @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Visual.UserInterface typeof(Notification) }; - public TestCaseNotificationOverlay() + public TestSceneNotificationOverlay() { progressingNotifications.Clear(); diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseOnScreenDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs similarity index 98% rename from osu.Game.Tests/Visual/UserInterface/TestCaseOnScreenDisplay.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs index 7ad42cb926..d900526c07 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseOnScreenDisplay : OsuTestCase + public class TestSceneOnScreenDisplay : OsuTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseOsuIcon.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs similarity index 96% rename from osu.Game.Tests/Visual/UserInterface/TestCaseOsuIcon.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs index cef122ff58..2c2a28394c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseOsuIcon.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs @@ -16,9 +16,9 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseOsuIcon : OsuTestCase + public class TestSceneOsuIcon : OsuTestScene { - public TestCaseOsuIcon() + public TestSceneOsuIcon() { FillFlowContainer flow; diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseParallaxContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs similarity index 91% rename from osu.Game.Tests/Visual/UserInterface/TestCaseParallaxContainer.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs index 5de4c3f41f..588b25c02d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseParallaxContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs @@ -8,9 +8,9 @@ using osu.Game.Screens.Backgrounds; namespace osu.Game.Tests.Visual.UserInterface { - public class TestCaseParallaxContainer : OsuTestCase + public class TestSceneParallaxContainer : OsuTestScene { - public TestCaseParallaxContainer() + public TestSceneParallaxContainer() { ParallaxContainer parallax; diff --git a/osu.Game.Tests/Visual/UserInterface/TestCasePopupDialog.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs similarity index 92% rename from osu.Game.Tests/Visual/UserInterface/TestCasePopupDialog.cs rename to osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs index 2f01f593c7..24140125e0 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCasePopupDialog.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs @@ -9,9 +9,9 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCasePopupDialog : OsuTestCase + public class TestScenePopupDialog : OsuTestScene { - public TestCasePopupDialog() + public TestScenePopupDialog() { var popup = new PopupDialog { diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseScreenBreadcrumbControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs similarity index 97% rename from osu.Game.Tests/Visual/UserInterface/TestCaseScreenBreadcrumbControl.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs index c92072eb71..9c83fdf96c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseScreenBreadcrumbControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs @@ -16,12 +16,12 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestCaseScreenBreadcrumbControl : OsuTestCase + public class TestSceneScreenBreadcrumbControl : OsuTestScene { private readonly ScreenBreadcrumbControl breadcrumbs; private readonly OsuScreenStack screenStack; - public TestCaseScreenBreadcrumbControl() + public TestSceneScreenBreadcrumbControl() { OsuSpriteText titleText; diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs similarity index 93% rename from osu.Game.Tests/Visual/UserInterface/TestCaseTabControl.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs index 480dc73dde..a884741ff8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs @@ -11,9 +11,9 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { [Description("SongSelect filter control")] - public class TestCaseTabControl : OsuTestCase + public class TestSceneTabControl : OsuTestScene { - public TestCaseTabControl() + public TestSceneTabControl() { OsuSpriteText text; OsuTabControl filter; diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseTwoLayerButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs similarity index 79% rename from osu.Game.Tests/Visual/UserInterface/TestCaseTwoLayerButton.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs index 8d3cc7a0f2..b9ed1a71cc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseTwoLayerButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs @@ -7,9 +7,9 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Tests.Visual.UserInterface { [Description("mostly back button")] - public class TestCaseTwoLayerButton : OsuTestCase + public class TestSceneTwoLayerButton : OsuTestScene { - public TestCaseTwoLayerButton() + public TestSceneTwoLayerButton() { Add(new BackButton()); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs similarity index 98% rename from osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs index 6185fbd34e..23065629a6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs @@ -17,7 +17,7 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestCaseUpdateableBeatmapBackgroundSprite : OsuTestCase + public class TestSceneUpdateableBeatmapBackgroundSprite : OsuTestScene { private BeatmapSetInfo testBeatmap; private IAPIProvider api; diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseVolumePieces.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs similarity index 95% rename from osu.Game.Tests/Visual/UserInterface/TestCaseVolumePieces.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs index 3ad1c922e4..2fe6240b22 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseVolumePieces.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestCaseVolumePieces : OsuTestCase + public class TestSceneVolumePieces : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(VolumeMeter), typeof(MuteButton) }; diff --git a/osu.Game/Tests/Visual/AllPlayersTestCase.cs b/osu.Game/Tests/Visual/AllPlayersTestScene.cs similarity index 96% rename from osu.Game/Tests/Visual/AllPlayersTestCase.cs rename to osu.Game/Tests/Visual/AllPlayersTestScene.cs index dc3ef1a85b..454fbe1222 100644 --- a/osu.Game/Tests/Visual/AllPlayersTestCase.cs +++ b/osu.Game/Tests/Visual/AllPlayersTestScene.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual /// A base class which runs test for all available rulesets. /// Steps to be run for each ruleset should be added via . /// - public abstract class AllPlayersTestCase : RateAdjustedBeatmapTestCase + public abstract class AllPlayersTestScene : RateAdjustedBeatmapTestScene { protected Player Player; diff --git a/osu.Game/Tests/Visual/EditorClockTestCase.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs similarity index 95% rename from osu.Game/Tests/Visual/EditorClockTestCase.cs rename to osu.Game/Tests/Visual/EditorClockTestScene.cs index c71c2ae857..58a443ed3d 100644 --- a/osu.Game/Tests/Visual/EditorClockTestCase.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -15,12 +15,12 @@ namespace osu.Game.Tests.Visual /// Provides a clock, beat-divisor, and scrolling capability for test cases of editor components that /// are preferrably tested within the presence of a clock and seek controls. /// - public abstract class EditorClockTestCase : OsuTestCase + public abstract class EditorClockTestScene : OsuTestScene { protected readonly BindableBeatDivisor BeatDivisor = new BindableBeatDivisor(); protected new readonly EditorClock Clock; - protected EditorClockTestCase() + protected EditorClockTestScene() { Clock = new EditorClock(new ControlPointInfo(), 5000, BeatDivisor) { IsCoupled = false }; } diff --git a/osu.Game/Tests/Visual/EditorTestCase.cs b/osu.Game/Tests/Visual/EditorTestScene.cs similarity index 87% rename from osu.Game/Tests/Visual/EditorTestCase.cs rename to osu.Game/Tests/Visual/EditorTestScene.cs index 96e70e018e..14c0f0950f 100644 --- a/osu.Game/Tests/Visual/EditorTestCase.cs +++ b/osu.Game/Tests/Visual/EditorTestScene.cs @@ -10,13 +10,13 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual { - public abstract class EditorTestCase : ScreenTestCase + public abstract class EditorTestScene : ScreenTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(Editor), typeof(EditorScreen) }; private readonly Ruleset ruleset; - protected EditorTestCase(Ruleset ruleset) + protected EditorTestScene(Ruleset ruleset) { this.ruleset = ruleset; } diff --git a/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs b/osu.Game/Tests/Visual/ManualInputManagerTestScene.cs similarity index 89% rename from osu.Game/Tests/Visual/ManualInputManagerTestCase.cs rename to osu.Game/Tests/Visual/ManualInputManagerTestScene.cs index 9b1ccdd6a4..a7a7f88ff7 100644 --- a/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs +++ b/osu.Game/Tests/Visual/ManualInputManagerTestScene.cs @@ -8,14 +8,14 @@ using osu.Game.Graphics.Cursor; namespace osu.Game.Tests.Visual { - public abstract class ManualInputManagerTestCase : OsuTestCase + public abstract class ManualInputManagerTestScene : OsuTestScene { protected override Container Content => content; private readonly Container content; protected readonly ManualInputManager InputManager; - protected ManualInputManagerTestCase() + protected ManualInputManagerTestScene() { base.Content.Add(InputManager = new ManualInputManager { diff --git a/osu.Game/Tests/Visual/MultiplayerTestCase.cs b/osu.Game/Tests/Visual/MultiplayerTestScene.cs similarity index 93% rename from osu.Game/Tests/Visual/MultiplayerTestCase.cs rename to osu.Game/Tests/Visual/MultiplayerTestScene.cs index bb866cf750..ffb431b4d3 100644 --- a/osu.Game/Tests/Visual/MultiplayerTestCase.cs +++ b/osu.Game/Tests/Visual/MultiplayerTestScene.cs @@ -7,7 +7,7 @@ using osu.Game.Online.Multiplayer; namespace osu.Game.Tests.Visual { - public abstract class MultiplayerTestCase : ScreenTestCase + public abstract class MultiplayerTestScene : ScreenTestScene { [Cached] private readonly Bindable currentRoom = new Bindable(new Room()); diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestScene.cs similarity index 95% rename from osu.Game/Tests/Visual/OsuTestCase.cs rename to osu.Game/Tests/Visual/OsuTestScene.cs index 3a40db4571..f628f3c29a 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -15,7 +15,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Tests.Visual { - public abstract class OsuTestCase : TestScene + public abstract class OsuTestScene : TestScene { [Cached(typeof(Bindable))] [Cached(typeof(IBindable))] @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual return Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); } - protected OsuTestCase() + protected OsuTestScene() { localStorage = new Lazy(() => new NativeStorage($"{GetType().Name}-{Guid.NewGuid()}")); } @@ -76,9 +76,9 @@ namespace osu.Game.Tests.Visual } } - protected override ITestSceneTestRunner CreateRunner() => new OsuTestCaseTestRunner(); + protected override ITestSceneTestRunner CreateRunner() => new OsuTestSceneTestRunner(); - public class OsuTestCaseTestRunner : OsuGameBase, ITestSceneTestRunner + public class OsuTestSceneTestRunner : OsuGameBase, ITestSceneTestRunner { private TestSceneTestRunner.TestRunner runner; diff --git a/osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs similarity index 93% rename from osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs rename to osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs index ec4b0a1f62..c1561ffea1 100644 --- a/osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs +++ b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs @@ -13,12 +13,12 @@ using osu.Game.Screens.Edit.Compose; namespace osu.Game.Tests.Visual { [Cached(Type = typeof(IPlacementHandler))] - public abstract class PlacementBlueprintTestCase : OsuTestCase, IPlacementHandler + public abstract class PlacementBlueprintTestScene : OsuTestScene, IPlacementHandler { protected readonly Container HitObjectContainer; private PlacementBlueprint currentBlueprint; - protected PlacementBlueprintTestCase() + protected PlacementBlueprintTestScene() { Beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize = 2; diff --git a/osu.Game/Tests/Visual/PlayerTestCase.cs b/osu.Game/Tests/Visual/PlayerTestScene.cs similarity index 93% rename from osu.Game/Tests/Visual/PlayerTestCase.cs rename to osu.Game/Tests/Visual/PlayerTestScene.cs index 5e453f0ac8..0c39194088 100644 --- a/osu.Game/Tests/Visual/PlayerTestCase.cs +++ b/osu.Game/Tests/Visual/PlayerTestScene.cs @@ -13,13 +13,13 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual { - public abstract class PlayerTestCase : RateAdjustedBeatmapTestCase + public abstract class PlayerTestScene : RateAdjustedBeatmapTestScene { private readonly Ruleset ruleset; protected Player Player; - protected PlayerTestCase(Ruleset ruleset) + protected PlayerTestScene(Ruleset ruleset) { this.ruleset = ruleset; } diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs similarity index 88% rename from osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs rename to osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs index 3b3adb4d76..921a1d9789 100644 --- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs @@ -6,7 +6,7 @@ namespace osu.Game.Tests.Visual /// /// Test case which adjusts the beatmap's rate to match any speed adjustments in visual tests. /// - public abstract class RateAdjustedBeatmapTestCase : ScreenTestCase + public abstract class RateAdjustedBeatmapTestScene : ScreenTestScene { protected override void Update() { diff --git a/osu.Game/Tests/Visual/ScreenTestCase.cs b/osu.Game/Tests/Visual/ScreenTestScene.cs similarity index 90% rename from osu.Game/Tests/Visual/ScreenTestCase.cs rename to osu.Game/Tests/Visual/ScreenTestScene.cs index 4fd4c7c207..23f45e0d0f 100644 --- a/osu.Game/Tests/Visual/ScreenTestCase.cs +++ b/osu.Game/Tests/Visual/ScreenTestScene.cs @@ -10,7 +10,7 @@ namespace osu.Game.Tests.Visual /// /// A test case which can be used to test a screen (that relies on OnEntering being called to execute startup instructions). /// - public abstract class ScreenTestCase : ManualInputManagerTestCase + public abstract class ScreenTestScene : ManualInputManagerTestScene { private readonly OsuScreenStack stack; @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual protected override Container Content => content; - protected ScreenTestCase() + protected ScreenTestScene() { base.Content.AddRange(new Drawable[] { diff --git a/osu.Game/Tests/Visual/SelectionBlueprintTestCase.cs b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs similarity index 92% rename from osu.Game/Tests/Visual/SelectionBlueprintTestCase.cs rename to osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs index d17f670a2d..df3af2cc43 100644 --- a/osu.Game/Tests/Visual/SelectionBlueprintTestCase.cs +++ b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs @@ -10,14 +10,14 @@ using osu.Game.Rulesets.Edit; namespace osu.Game.Tests.Visual { - public abstract class SelectionBlueprintTestCase : OsuTestCase + public abstract class SelectionBlueprintTestScene : OsuTestScene { private SelectionBlueprint blueprint; protected override Container Content => content ?? base.Content; private readonly Container content; - protected SelectionBlueprintTestCase() + protected SelectionBlueprintTestScene() { base.Content.Add(content = new Container { From 37ec722a1d075a0910aa460c0a956f165e2805c8 Mon Sep 17 00:00:00 2001 From: Alten Date: Tue, 14 May 2019 16:18:46 -0400 Subject: [PATCH 0842/5608] Shorten code --- osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index b7df4f2f2b..1630370bd1 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -63,13 +63,10 @@ namespace osu.Game.Rulesets.Osu.UI { get { - if (Objects.Any()) - { - var first = (OsuHitObject)Objects.First(); + if (Objects.FirstOrDefault() is OsuHitObject first) return first.StartTime - Math.Max(2000, first.TimePreempt); - } - - return 0; + else + return 0; } } } From cbf662eb566c97703d1e5905fb33256b1ae79292 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 May 2019 10:55:02 +0900 Subject: [PATCH 0843/5608] Remove redundant else statement --- osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index 1630370bd1..d185d7d4c9 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -65,8 +65,8 @@ namespace osu.Game.Rulesets.Osu.UI { if (Objects.FirstOrDefault() is OsuHitObject first) return first.StartTime - Math.Max(2000, first.TimePreempt); - else - return 0; + + return 0; } } } From c01841d7d7c00975c21aa5804627f5700aa707e2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 May 2019 11:28:22 +0900 Subject: [PATCH 0844/5608] Use Logger for squirrel update logs --- osu.Desktop/Updater/SquirrelUpdateManager.cs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index 9681350ade..71cc7f6386 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -2,8 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.IO; -using System.Reflection; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -169,23 +167,14 @@ namespace osu.Desktop.Updater private class SquirrelLogger : Splat.ILogger, IDisposable { - private readonly string path; - private readonly object locker = new object(); public LogLevel Level { get; set; } = LogLevel.Info; - public SquirrelLogger() - { - var file = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location ?? Directory.GetCurrentDirectory()), "SquirrelSetupUpdater.log"); - if (File.Exists(file)) File.Delete(file); - path = file; - } - public void Write(string message, LogLevel logLevel) { if (logLevel < Level) return; - lock (locker) File.AppendAllText(path, message + "\r\n"); + Logger.Log(message); } public void Dispose() From 1fd44d7945c1513844b7704b9e86c7d2da1bd580 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 13:00:11 +0900 Subject: [PATCH 0845/5608] Move OsuScreenDependencies to GameBase --- osu.Game.Tests/Visual/TestCaseOsuGame.cs | 29 +++++++++++++++++++----- osu.Game/OsuGame.cs | 23 +++++-------------- osu.Game/OsuGameBase.cs | 12 +++++++++- 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseOsuGame.cs b/osu.Game.Tests/Visual/TestCaseOsuGame.cs index dd98ff088c..b87ea433fe 100644 --- a/osu.Game.Tests/Visual/TestCaseOsuGame.cs +++ b/osu.Game.Tests/Visual/TestCaseOsuGame.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -23,6 +22,7 @@ using osu.Game.Online.API; using osu.Game.Online.Chat; using osu.Game.Overlays; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Screens.Menu; using osu.Game.Skinning; @@ -43,8 +43,6 @@ namespace osu.Game.Tests.Visual { typeof(OsuGame), typeof(RavenLogger), - typeof(Bindable), - typeof(IBindable), typeof(OsuLogo), typeof(IdleTracker), typeof(OnScreenDisplay), @@ -60,12 +58,17 @@ namespace osu.Game.Tests.Visual typeof(MusicController), typeof(AccountCreationOverlay), typeof(DialogOverlay), + typeof(ScreenshotManager) }; private IReadOnlyList requiredGameBaseDependencies => new[] { typeof(OsuGameBase), typeof(DatabaseContextFactory), + typeof(Bindable), + typeof(IBindable), + typeof(Bindable>), + typeof(IBindable>), typeof(LargeTextureStore), typeof(OsuConfigManager), typeof(SkinManager), @@ -86,7 +89,7 @@ namespace osu.Game.Tests.Visual }; [BackgroundDependencyLoader] - private void load(GameHost host) + private void load(GameHost host, OsuGameBase gameBase) { OsuGame game = new OsuGame(); game.SetHost(host); @@ -103,8 +106,22 @@ namespace osu.Game.Tests.Visual AddUntilStep("wait for load", () => game.IsLoaded); - AddAssert("check OsuGame DI members", () => requiredGameDependencies.All(d => game.Dependencies.Get(d) != null)); - AddAssert("check OsuGameBase DI members", () => requiredGameBaseDependencies.All(d => Dependencies.Get(d) != null)); + AddAssert("check OsuGame DI members", () => + { + foreach (var type in requiredGameDependencies) + if (game.Dependencies.Get(type) == null) + throw new Exception($"{type} has not been cached"); + + return true; + }); + AddAssert("check OsuGameBase DI members", () => + { + foreach (var type in requiredGameBaseDependencies) + if (gameBase.Dependencies.Get(type) == null) + throw new Exception($"{type} has not been cached"); + + return true; + }); } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 1f4b78f5fb..d108bb45f3 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -31,11 +31,9 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Input; using osu.Game.Overlays.Notifications; -using osu.Game.Rulesets; using osu.Game.Screens.Play; using osu.Game.Input.Bindings; using osu.Game.Online.Chat; -using osu.Game.Rulesets.Mods; using osu.Game.Skinning; using osuTK.Graphics; using osu.Game.Overlays.Volume; @@ -89,7 +87,6 @@ namespace osu.Game private Intro introScreen; private Bindable configRuleset; - private readonly Bindable ruleset = new Bindable(); private Bindable configSkin; @@ -103,11 +100,6 @@ namespace osu.Game private readonly List visibleBlockingOverlays = new List(); - // todo: move this to SongSelect once Screen has the ability to unsuspend. - [Cached] - [Cached(typeof(IBindable>))] - private readonly Bindable> mods = new Bindable>(Array.Empty()); - public OsuGame(string[] args = null) { this.args = args; @@ -176,15 +168,12 @@ namespace osu.Game dependencies.Cache(RavenLogger); - dependencies.CacheAs(ruleset); - dependencies.CacheAs>(ruleset); - dependencies.Cache(osuLogo = new OsuLogo { Alpha = 0 }); // bind config int to database RulesetInfo configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset); - ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value) ?? RulesetStore.AvailableRulesets.First(); - ruleset.ValueChanged += r => configRuleset.Value = r.NewValue.ID ?? 0; + Ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value) ?? RulesetStore.AvailableRulesets.First(); + Ruleset.ValueChanged += r => configRuleset.Value = r.NewValue.ID ?? 0; // bind config int to database SkinInfo configSkin = LocalConfig.GetBindable(OsuSetting.Skin); @@ -255,9 +244,9 @@ namespace osu.Game } // Use first beatmap available for current ruleset, else switch ruleset. - var first = databasedSet.Beatmaps.Find(b => b.Ruleset == ruleset.Value) ?? databasedSet.Beatmaps.First(); + var first = databasedSet.Beatmaps.Find(b => b.Ruleset == Ruleset.Value) ?? databasedSet.Beatmaps.First(); - ruleset.Value = first.Ruleset; + Ruleset.Value = first.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first); }, $"load {beatmap}", bypassScreenAllowChecks: true, targetScreen: typeof(PlaySongSelect)); } @@ -287,9 +276,9 @@ namespace osu.Game performFromMainMenu(() => { - ruleset.Value = databasedScoreInfo.Ruleset; + Ruleset.Value = databasedScoreInfo.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); - mods.Value = databasedScoreInfo.Mods; + Mods.Value = databasedScoreInfo.Mods; menuScreen.Push(new PlayerLoader(() => new ReplayPlayer(databasedScore))); }, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true); diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index c068c5b0d4..7b9aed8364 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -29,6 +29,7 @@ using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.IO; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Skinning; using osuTK.Input; @@ -69,7 +70,16 @@ namespace osu.Game protected override Container Content => content; - private Bindable beatmap; + private Bindable beatmap; // cached via load() method + + [Cached] + [Cached(typeof(IBindable))] + protected readonly Bindable Ruleset = new Bindable(); + + // todo: move this to SongSelect once Screen has the ability to unsuspend. + [Cached] + [Cached(Type = typeof(IBindable>))] + protected readonly Bindable> Mods = new Bindable>(Array.Empty()); protected Bindable Beatmap => beatmap; From 530032cafee5b39c18b702e1abc6f7336abffb14 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 13:10:58 +0900 Subject: [PATCH 0846/5608] Update obsoleted font usages --- osu.Game.Tournament/Components/DrawableTournamentTeam.cs | 3 ++- osu.Game.Tournament/Components/TournamentBeatmapPanel.cs | 2 +- .../Screens/Ladder/Components/DrawableMatchTeam.cs | 2 +- .../Screens/Ladder/Components/DrawableTournamentGrouping.cs | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs index a0c0856e7f..8662eeba2d 100644 --- a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Tournament.Components @@ -30,7 +31,7 @@ namespace osu.Game.Tournament.Components AcronymText = new OsuSpriteText { Text = team?.Acronym?.ToUpperInvariant() ?? string.Empty, - Font = @"Exo2.0-Regular" + Font = OsuFont.GetFont(weight: FontWeight.Regular), }; } diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index df4c15a221..8ab0dc2459 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -86,7 +86,7 @@ namespace osu.Game.Tournament.Components Text = new LocalisedString(( $"{Beatmap.Metadata.ArtistUnicode} - {Beatmap.Metadata.TitleUnicode}", $"{Beatmap.Metadata.Artist} - {Beatmap.Metadata.Title}")), - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true), }, new FillFlowContainer { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 3078b58c45..35b6dfb606 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -183,7 +183,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components background.FadeColour(winner ? colourWinner : colourNormal, winner ? 500 : 0, Easing.OutQuint); - scoreText.Font = AcronymText.Font = winner ? "Exo2.0-Bold" : "Exo2.0-Regular"; + scoreText.Font = AcronymText.Font = OsuFont.GetFont(weight: winner ? FontWeight.Bold : FontWeight.Regular); } public MenuItem[] ContextMenuItems diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs index 175910d9d6..40adc24dc4 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK.Graphics; @@ -29,7 +30,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components new OsuSpriteText { Text = ((losers ? "Losers " : "") + grouping.Name).ToUpper(), - Font = "Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Colour = Color4.Black, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre From 501eaa072e62d321f0d3804568cd61b1d998e330 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 14:12:59 +0900 Subject: [PATCH 0847/5608] Use local logger --- osu.Desktop/Updater/SquirrelUpdateManager.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index 71cc7f6386..e2c7a5e892 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -169,12 +169,17 @@ namespace osu.Desktop.Updater { public LogLevel Level { get; set; } = LogLevel.Info; + private Logger logger; + public void Write(string message, LogLevel logLevel) { if (logLevel < Level) return; - Logger.Log(message); + if (logger == null) + logger = Logger.GetLogger("updater"); + + logger.Add(message); } public void Dispose() From 5ddd28bf309f219322cc3e82d7afcf9c540067e2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 16:42:12 +0900 Subject: [PATCH 0848/5608] Fix message display / html stripping --- .../Changelog/ChangelogContentGroup.cs | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index e9ca025425..190720df04 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -10,6 +10,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; using System; using System.Collections.Generic; +using System.Text.RegularExpressions; using osuTK; using osuTK.Graphics; @@ -262,19 +263,23 @@ namespace osu.Game.Overlays.Changelog ChangelogEntries.Add(title); - TextFlowContainer messageContainer = new TextFlowContainer + if (!string.IsNullOrEmpty(entry.MessageHtml)) { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - }; + TextFlowContainer messageContainer = new TextFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + }; - messageContainer.AddText($"{entry.MessageHtml?.Replace("

", "").Replace("

", "")}\n", t => - { - t.Font = OsuFont.GetFont(size: 14); // web: 12, - t.Colour = new Color4(235, 184, 254, 255); - }); + // todo: use markdown parsing once API returns markdown + messageContainer.AddText(Regex.Replace(entry.MessageHtml, @"<(.|\n)*?>", string.Empty), t => + { + t.Font = OsuFont.GetFont(size: 14); // web: 12, + t.Colour = new Color4(235, 184, 254, 255); + }); - ChangelogEntries.Add(messageContainer); + ChangelogEntries.Add(messageContainer); + } } } } From e46a61febfa33ffaacc6e04f95f5db7affaec6c2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 17:36:29 +0900 Subject: [PATCH 0849/5608] Allow chaining of loadComponentSingleFile --- osu.Game/OsuGame.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ab643b1469..b214f48485 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.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; @@ -589,7 +589,7 @@ namespace osu.Game private Task asyncLoadStream; - private void loadComponentSingleFile(T d, Action add, bool cache = false) + private T loadComponentSingleFile(T d, Action add, bool cache = false) where T : Drawable { if (cache) @@ -637,6 +637,8 @@ namespace osu.Game } }); }); + + return d; } public bool OnPressed(GlobalAction action) From d7098e2066186dc0300447a097b4497eb0f7ccd6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 17:38:19 +0900 Subject: [PATCH 0850/5608] Hide other overlays when showing changelog --- osu.Game/OsuGame.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b214f48485..752762ee50 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.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; @@ -437,7 +437,7 @@ namespace osu.Game loadComponentSingleFile(settings = new SettingsOverlay { GetToolbarHeight = () => ToolbarOffset }, leftFloatingOverlayContent.Add, true); loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true); - loadComponentSingleFile(new ChangelogOverlay(), overlayContent.Add, true); + var changelogOverlay = loadComponentSingleFile(new ChangelogOverlay(), overlayContent.Add, true); loadComponentSingleFile(new LoginOverlay { @@ -479,7 +479,7 @@ namespace osu.Game } // eventually informational overlays should be displayed in a stack, but for now let's only allow one to stay open at a time. - var informationalOverlays = new OverlayContainer[] { beatmapSetOverlay, userProfile }; + var informationalOverlays = new OverlayContainer[] { beatmapSetOverlay, userProfile, changelogOverlay }; overlays.AddRange(informationalOverlays); foreach (var overlay in informationalOverlays) From f49b0dc16df3aa6270f82ddb29e3a31cef51c448 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 17:55:26 +0900 Subject: [PATCH 0851/5608] Initial clean-up pass of breadcrumb and header --- .../Visual/TestCaseTextBadgePair.cs | 25 ++++--- .../{ChangelogBadges.cs => BadgeDisplay.cs} | 7 +- .../Overlays/Changelog/ChangelogHeader.cs | 30 +++----- .../{TextBadgePair.cs => Breadcrumb.cs} | 72 +++++++------------ ...dgePairListing.cs => BreadcrumbListing.cs} | 42 +++++------ ...dgePairRelease.cs => BreadcrumbRelease.cs} | 21 ++---- osu.Game/Overlays/ChangelogOverlay.cs | 15 ++-- 7 files changed, 89 insertions(+), 123 deletions(-) rename osu.Game/Overlays/Changelog/{ChangelogBadges.cs => BadgeDisplay.cs} (95%) rename osu.Game/Overlays/Changelog/Header/{TextBadgePair.cs => Breadcrumb.cs} (68%) rename osu.Game/Overlays/Changelog/Header/{TextBadgePairListing.cs => BreadcrumbListing.cs} (54%) rename osu.Game/Overlays/Changelog/Header/{TextBadgePairRelease.cs => BreadcrumbRelease.cs} (53%) diff --git a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs index 3c461a2dd6..2f7ab5deba 100644 --- a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs +++ b/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Overlays.Changelog.Header; @@ -13,7 +14,7 @@ namespace osu.Game.Tests.Visual { public TestCaseTextBadgePair() { - TextBadgePair textBadgePair; + Breadcrumb breadcrumb; Add(new Container { @@ -29,7 +30,7 @@ namespace osu.Game.Tests.Visual Alpha = 0.5f, RelativeSizeAxes = Axes.Both, }, - textBadgePair = new TextBadgePair(Color4.DeepSkyBlue, "Test") + breadcrumb = new TestBadgePair(Color4.DeepSkyBlue, "Test") { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -37,12 +38,20 @@ namespace osu.Game.Tests.Visual } }); - AddStep(@"Deactivate", textBadgePair.Deactivate); - AddStep(@"Activate", textBadgePair.Activate); - AddStep(@"Hide text", () => textBadgePair.HideText(200)); - AddStep(@"Show text", () => textBadgePair.ShowText(200)); - AddStep(@"Different text", () => textBadgePair.ChangeText(200, "This one's a little bit wider")); - AddStep(@"Different text", () => textBadgePair.ChangeText(200, "Ok?..")); + AddStep(@"Deactivate", breadcrumb.Deactivate); + AddStep(@"Activate", breadcrumb.Activate); + AddStep(@"Hide text", () => breadcrumb.HideText(200)); + AddStep(@"Show text", () => breadcrumb.ShowText(200)); + AddStep(@"Different text", () => breadcrumb.ShowText(200, "This one's a little bit wider")); + AddStep(@"Different text", () => breadcrumb.ShowText(200, "Ok?..")); + } + + private class TestBadgePair : Breadcrumb + { + public TestBadgePair(ColourInfo badgeColour, string displayText = "Listing", bool startCollapsed = true) + : base(badgeColour, displayText, startCollapsed) + { + } } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogBadges.cs b/osu.Game/Overlays/Changelog/BadgeDisplay.cs similarity index 95% rename from osu.Game/Overlays/Changelog/ChangelogBadges.cs rename to osu.Game/Overlays/Changelog/BadgeDisplay.cs index e95fa72f2e..441909132a 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBadges.cs +++ b/osu.Game/Overlays/Changelog/BadgeDisplay.cs @@ -12,9 +12,8 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { - public class ChangelogBadges : Container + public class BadgeDisplay : CompositeDrawable { - private const float container_height = 106.5f; private const float vertical_padding = 20; private const float horizontal_padding = 85; @@ -25,11 +24,11 @@ namespace osu.Game.Overlays.Changelog private readonly FillFlowContainer badgesContainer; private long selectedStreamId = -1; - public ChangelogBadges() + public BadgeDisplay() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Children = new Drawable[] + InternalChildren = new Drawable[] { new Box { diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 1bc30b87d4..4186356bd4 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Changelog.Header; -using System; using osu.Game.Graphics; using osuTK; using osuTK.Graphics; @@ -19,9 +18,9 @@ namespace osu.Game.Overlays.Changelog public class ChangelogHeader : Container { private OsuSpriteText titleStream; - private TextBadgePairListing listing; + private BreadcrumbListing listing; private SpriteIcon chevron; - private TextBadgePairRelease releaseStream; + private BreadcrumbRelease releaseStream; public delegate void ListingSelectedEventHandler(); @@ -130,7 +129,10 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Horizontal, Children = new Drawable[] { - listing = new TextBadgePairListing(colours.Violet), + listing = new BreadcrumbListing(colours.Violet) + { + Action = () => ListingSelected?.Invoke() + }, new Container // without a container, moving the chevron wont work { Anchor = Anchor.CentreLeft, @@ -156,7 +158,10 @@ namespace osu.Game.Overlays.Changelog }, }, }, - releaseStream = new TextBadgePairRelease(colours.Violet, "Lazer") + releaseStream = new BreadcrumbRelease(colours.Violet, "Lazer") + { + Action = () => titleStream.FlashColour(Color4.White, 500, Easing.OutQuad) + } }, }, new Box @@ -168,15 +173,12 @@ namespace osu.Game.Overlays.Changelog Origin = Anchor.CentreLeft, }, }; - - listing.Activated += OnListingSelected; - releaseStream.Activated += OnReleaseSelected; } public void ShowBuild(string displayName, string displayVersion) { listing.Deactivate(); - releaseStream.Activate($"{displayName} {displayVersion}"); + releaseStream.ShowBuild($"{displayName} {displayVersion}"); titleStream.Text = displayName; titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); chevron.MoveToX(0, 100).FadeIn(100); @@ -190,15 +192,5 @@ namespace osu.Game.Overlays.Changelog titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); chevron.MoveToX(-20, 100).FadeOut(100); } - - protected virtual void OnListingSelected(object source, EventArgs e) - { - ListingSelected?.Invoke(); - } - - protected virtual void OnReleaseSelected(object source, EventArgs e) - { - titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); - } } } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs b/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs similarity index 68% rename from osu.Game/Overlays/Changelog/Header/TextBadgePair.cs rename to osu.Game/Overlays/Changelog/Header/Breadcrumb.cs index e044d4c342..43dcaf22ca 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePair.cs +++ b/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs @@ -15,20 +15,19 @@ using osu.Game.Graphics; namespace osu.Game.Overlays.Changelog.Header { - public class TextBadgePair : Container + public abstract class Breadcrumb : Container { protected SpriteText Text; protected LineBadge LineBadge; + public bool IsActivated { get; protected set; } - public delegate void ActivatedEventHandler(object source, EventArgs args); - - public event ActivatedEventHandler Activated; + public Action Action; private SampleChannel sampleHover; private SampleChannel sampleActivate; - public TextBadgePair(ColourInfo badgeColour, string displayText = "Listing", bool startCollapsed = true) + protected Breadcrumb(ColourInfo badgeColour, string displayText = "Listing", bool startCollapsed = true) { AutoSizeAxes = Axes.X; RelativeSizeAxes = Axes.Y; @@ -53,42 +52,24 @@ namespace osu.Game.Overlays.Changelog.Header }; } - /// - /// The duration of popping in and popping out not combined. - /// Full change takes double this time. - /// - /// - public void ChangeText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) - { - LineBadge.Collapse(); - Text.MoveToY(20, duration, easing) - .FadeOut(duration, easing) - .Then() - .MoveToY(0, duration, easing) - .FadeIn(duration, easing); - - // since using .finally/.oncomplete after first fadeout made the badge not hide - // sometimes in visual tests (https://streamable.com/0qssq), I'm using a scheduler here - Scheduler.AddDelayed(() => - { - if (!string.IsNullOrEmpty(displayText)) - Text.Text = displayText; - LineBadge.Uncollapse(); - }, duration); - } - public virtual void Deactivate() { + if (!IsActivated) + return; + IsActivated = false; LineBadge.Collapse(); - Text.Font = "Exo2.0-Regular"; + Text.Font = Text.Font.With(weight: FontWeight.Regular); } public virtual void Activate() { + if (IsActivated) + return; + IsActivated = true; LineBadge.Uncollapse(); - Text.Font = "Exo2.0-Bold"; + Text.Font = Text.Font.With(weight: FontWeight.Bold); } public void SetTextColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) @@ -96,11 +77,6 @@ namespace osu.Game.Overlays.Changelog.Header Text.FadeColour(newColour, duration, easing); } - public void SetBadgeColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) - { - LineBadge.FadeColour(newColour, duration, easing); - } - public void HideText(double duration = 0, Easing easing = Easing.InOutCubic) { LineBadge.Collapse(); @@ -110,11 +86,18 @@ namespace osu.Game.Overlays.Changelog.Header public void ShowText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) { - LineBadge.Uncollapse(); - if (!string.IsNullOrEmpty(displayText)) - Text.Text = displayText; - Text.MoveToY(0, duration, easing) + LineBadge.Collapse(); + Text.MoveToY(20, duration, easing) + .FadeOut(duration, easing) + .Then() + .MoveToY(0, duration, easing) .FadeIn(duration, easing); + + Scheduler.AddDelayed(() => + { + Text.Text = displayText; + LineBadge.Uncollapse(); + }, duration); } protected override bool OnHover(HoverEvent e) @@ -126,14 +109,11 @@ namespace osu.Game.Overlays.Changelog.Header protected override bool OnClick(ClickEvent e) { - OnActivated(); + Action?.Invoke(); + Activate(); sampleActivate?.Play(); - return base.OnClick(e); - } - protected virtual void OnActivated() - { - Activated?.Invoke(this, EventArgs.Empty); + return true; } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs b/osu.Game/Overlays/Changelog/Header/BreadcrumbListing.cs similarity index 54% rename from osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs rename to osu.Game/Overlays/Changelog/Header/BreadcrumbListing.cs index b51948e849..50db916e7e 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairListing.cs +++ b/osu.Game/Overlays/Changelog/Header/BreadcrumbListing.cs @@ -4,31 +4,32 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Input.Events; +using osu.Game.Graphics; using osuTK.Graphics; namespace osu.Game.Overlays.Changelog.Header { - public class TextBadgePairListing : TextBadgePair + public class BreadcrumbListing : Breadcrumb { private readonly ColourInfo badgeColour; - public TextBadgePairListing(ColourInfo badgeColour) + public BreadcrumbListing(ColourInfo badgeColour) : base(badgeColour, "Listing", false) { - IsActivated = true; this.badgeColour = badgeColour; - Text.Font = "Exo2.0-Bold"; + Text.Font = Text.Font.With(weight: FontWeight.Bold); Text.Anchor = Anchor.TopCentre; Text.Origin = Anchor.TopCentre; - // I'm using this for constant badge width here, so that the whole - // thing doesn't jump left/right when listing's size changes - // due to different font weight (and thus width) - LineBadge.RelativeSizeAxes = Axes.None; + AutoSizeAxes = Axes.None; + } - // this doesn't work without the scheduler - // (because the text isn't yet fully drawn when it's loaded?) - Text.OnLoadComplete += d => Scheduler.Add(UpdateBadgeWidth); + protected override void LoadComplete() + { + base.LoadComplete(); + + Activate(); + Width = Text.DrawWidth; } public override void Activate() @@ -36,24 +37,17 @@ namespace osu.Game.Overlays.Changelog.Header if (IsActivated) return; - IsActivated = true; - LineBadge.Uncollapse(); - Text.Font = "Exo2.0-Bold"; + base.Activate(); SetTextColour(Color4.White, 100); } public override void Deactivate() { - IsActivated = false; - LineBadge.Collapse(); - Text.Font = "Exo2.0-Regular"; - SetTextColour(badgeColour, 100); - } + if (!IsActivated) + return; - protected override bool OnClick(ClickEvent e) - { - Activate(); - return base.OnClick(e); + base.Deactivate(); + SetTextColour(badgeColour, 100); } protected override bool OnHover(HoverEvent e) @@ -68,7 +62,5 @@ namespace osu.Game.Overlays.Changelog.Header LineBadge.Collapse(); base.OnHoverLost(e); } - - public void UpdateBadgeWidth() => LineBadge.ResizeWidthTo(Text.DrawWidth); } } diff --git a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs b/osu.Game/Overlays/Changelog/Header/BreadcrumbRelease.cs similarity index 53% rename from osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs rename to osu.Game/Overlays/Changelog/Header/BreadcrumbRelease.cs index f677bf62fe..86000ea4d1 100644 --- a/osu.Game/Overlays/Changelog/Header/TextBadgePairRelease.cs +++ b/osu.Game/Overlays/Changelog/Header/BreadcrumbRelease.cs @@ -5,11 +5,11 @@ using osu.Framework.Graphics.Colour; namespace osu.Game.Overlays.Changelog.Header { - public class TextBadgePairRelease : TextBadgePair + public class BreadcrumbRelease : Breadcrumb { private const float transition_duration = 125; - public TextBadgePairRelease(ColourInfo badgeColour, string displayText) + public BreadcrumbRelease(ColourInfo badgeColour, string displayText) : base(badgeColour, displayText) { Text.Font = "Exo2.0-Bold"; @@ -17,24 +17,17 @@ namespace osu.Game.Overlays.Changelog.Header Text.Alpha = 0; } - public void SetText(string displayText) => Text.Text = displayText; - - public void Activate(string displayText = null) + public void ShowBuild(string displayText = null) { - if (IsActivated) - { - if (displayText != Text.Text) - ChangeText(transition_duration, displayText); - } - else - ShowText(transition_duration, displayText); - + ShowText(transition_duration, displayText); IsActivated = true; } public override void Deactivate() { - IsActivated = false; + if (!IsActivated) + return; + HideText(transition_duration); } } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index b13b28afe9..a571879192 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays { private ChangelogHeader header; - private ChangelogBadges badges; + private BadgeDisplay badgeDisplay; private ChangelogContent listing; private ChangelogContent content; @@ -66,15 +66,16 @@ namespace osu.Game.Overlays Children = new Drawable[] { header = new ChangelogHeader(), - badges = new ChangelogBadges(), + badgeDisplay = new BadgeDisplay(), listing = new ChangelogContent(), content = new ChangelogContent() }, }, }, }; + header.ListingSelected += ShowListing; - badges.Selected += onBuildSelected; + badgeDisplay.Selected += onBuildSelected; listing.BuildSelected += onBuildSelected; content.BuildSelected += onBuildSelected; @@ -137,11 +138,11 @@ namespace osu.Game.Overlays isAtListing = true; var req = new GetChangelogRequest(); - badges.SelectNone(); + badgeDisplay.SelectNone(); req.Success += res => { listing.ShowListing(res.Builds); - badges.Populate(res.Streams); + badgeDisplay.Populate(res.Streams); }; API.Queue(req); @@ -157,7 +158,7 @@ namespace osu.Game.Overlays isAtListing = true; content.Hide(); listing.Show(); - badges.SelectNone(); + badgeDisplay.SelectNone(); listing.Show(); scroll.ScrollTo(savedScrollPosition); } @@ -180,7 +181,7 @@ namespace osu.Game.Overlays req.Success += res => header.ShowBuild(res.UpdateStream.DisplayName, res.DisplayVersion); if (updateBadges) - badges.SelectUpdateStream(build.UpdateStream.Name); + badgeDisplay.SelectUpdateStream(build.UpdateStream.Name); req.Success += apiChangelog => { From 60d244d2d60ae4d1fcc1e68997be7874c1f34671 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 18:08:19 +0900 Subject: [PATCH 0852/5608] Clean up events and states --- .../Visual/TestCaseChangelogOverlay.cs | 2 +- osu.Game/Overlays/Changelog/BadgeDisplay.cs | 8 ++-- .../Overlays/Changelog/ChangelogContent.cs | 15 ++----- .../Changelog/ChangelogContentGroup.cs | 17 +++----- osu.Game/Overlays/ChangelogOverlay.cs | 39 +++++++------------ 5 files changed, 27 insertions(+), 54 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs index 851cf17cfc..89b4fd2d18 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual AddStep(@"Show with Lazer 2018.712.0", () => { - changelog.FetchAndShowBuild(new APIChangelogBuild + changelog.ShowBuild(new APIChangelogBuild { Version = "2018.712.0", UpdateStream = new APIUpdateStream { Name = "lazer" }, diff --git a/osu.Game/Overlays/Changelog/BadgeDisplay.cs b/osu.Game/Overlays/Changelog/BadgeDisplay.cs index 441909132a..8c58decf49 100644 --- a/osu.Game/Overlays/Changelog/BadgeDisplay.cs +++ b/osu.Game/Overlays/Changelog/BadgeDisplay.cs @@ -17,9 +17,7 @@ namespace osu.Game.Overlays.Changelog private const float vertical_padding = 20; private const float horizontal_padding = 85; - public delegate void SelectionHandler(APIChangelogBuild releaseStream, EventArgs args); - - public event SelectionHandler Selected; + public event Action Selected; private readonly FillFlowContainer badgesContainer; private long selectedStreamId = -1; @@ -46,6 +44,8 @@ namespace osu.Game.Overlays.Changelog public void Populate(List streams) { + SelectNone(); + foreach (APIUpdateStream updateStream in streams) { var streamBadge = new StreamBadge(updateStream); @@ -92,7 +92,7 @@ namespace osu.Game.Overlays.Changelog protected virtual void OnSelected(StreamBadge source) { - Selected?.Invoke(source.Stream.LatestBuild, EventArgs.Empty); + Selected?.Invoke(source.Stream.LatestBuild); } protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index fdc9fac404..45fb98add0 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -15,9 +15,7 @@ namespace osu.Game.Overlays.Changelog { private ChangelogContentGroup changelogContentGroup; - public delegate void BuildSelectedEventHandler(APIChangelogBuild build, EventArgs args); - - public event BuildSelectedEventHandler BuildSelected; + public event Action BuildSelected; public ChangelogContent() { @@ -48,7 +46,7 @@ namespace osu.Game.Overlays.Changelog } changelogContentGroup = new ChangelogContentGroup(build, true); - changelogContentGroup.BuildSelected += OnBuildSelected; + changelogContentGroup.BuildSelected += b => BuildSelected?.Invoke(b); changelogContentGroup.GenerateText(build.ChangelogEntries); Add(changelogContentGroup); currentDate = build.CreatedAt.Date; @@ -64,7 +62,7 @@ namespace osu.Game.Overlays.Changelog }); changelogContentGroup = new ChangelogContentGroup(build, false); - changelogContentGroup.BuildSelected += OnBuildSelected; + changelogContentGroup.BuildSelected += b => BuildSelected?.Invoke(b); changelogContentGroup.GenerateText(build.ChangelogEntries); Add(changelogContentGroup); } @@ -77,12 +75,7 @@ namespace osu.Game.Overlays.Changelog changelogContentGroup.GenerateText(changelogBuild.ChangelogEntries); changelogContentGroup.UpdateChevronTooltips(changelogBuild.Versions.Previous?.DisplayVersion, changelogBuild.Versions.Next?.DisplayVersion); - changelogContentGroup.BuildSelected += OnBuildSelected; - } - - protected virtual void OnBuildSelected(APIChangelogBuild build, EventArgs args) - { - BuildSelected?.Invoke(build, EventArgs.Empty); + changelogContentGroup.BuildSelected += b => BuildSelected?.Invoke(b); } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 190720df04..1b03ade7e0 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -23,9 +23,7 @@ namespace osu.Game.Overlays.Changelog private readonly SortedDictionary> categories = new SortedDictionary>(); - public delegate void BuildSelectedEventHandler(APIChangelogBuild build, EventArgs args); - - public event BuildSelectedEventHandler BuildSelected; + public event Action BuildSelected; public readonly FillFlowContainer ChangelogEntries; @@ -53,7 +51,7 @@ namespace osu.Game.Overlays.Changelog Size = new Vector2(24), Action = () => { - OnBuildSelected(build.Versions.Previous); + BuildSelected?.Invoke(build.Versions.Previous); chevronPrevious.IsEnabled = false; }, }, @@ -88,7 +86,7 @@ namespace osu.Game.Overlays.Changelog Size = new Vector2(24), Action = () => { - OnBuildSelected(build.Versions.Next); + BuildSelected?.Invoke(build.Versions.Next); chevronNext.IsEnabled = false; }, }, @@ -141,7 +139,7 @@ namespace osu.Game.Overlays.Changelog Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Top = 20 }, - Action = () => OnBuildSelected(build), + Action = () => BuildSelected?.Invoke(build), Child = new FillFlowContainer { Direction = FillDirection.Horizontal, @@ -179,7 +177,7 @@ namespace osu.Game.Overlays.Changelog clickableBuildText.FadeTo(0.5f, 500); Scheduler.AddDelayed(() => { - clickableBuildText.Action = () => OnBuildSelected(build); + clickableBuildText.Action = () => BuildSelected?.Invoke(build); clickableBuildText.FadeIn(500); }, 2000); }; @@ -200,11 +198,6 @@ namespace osu.Game.Overlays.Changelog } } - protected virtual void OnBuildSelected(APIChangelogBuild build) - { - BuildSelected?.Invoke(build, EventArgs.Empty); - } - public void GenerateText(List changelogEntries) { // sort entries by category diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index a571879192..2bf5f0336c 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -13,7 +13,6 @@ using osu.Game.Input.Bindings; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Changelog; -using System; using osuTK; using osuTK.Graphics; @@ -23,7 +22,7 @@ namespace osu.Game.Overlays { private ChangelogHeader header; - private BadgeDisplay badgeDisplay; + private BadgeDisplay badges; private ChangelogContent listing; private ChangelogContent content; @@ -32,7 +31,6 @@ namespace osu.Game.Overlays private SampleChannel sampleBack; - private bool isAtListing; private float savedScrollPosition; // receive input outside our bounds so we can trigger a close event on ourselves. @@ -66,7 +64,7 @@ namespace osu.Game.Overlays Children = new Drawable[] { header = new ChangelogHeader(), - badgeDisplay = new BadgeDisplay(), + badges = new BadgeDisplay(), listing = new ChangelogContent(), content = new ChangelogContent() }, @@ -75,9 +73,10 @@ namespace osu.Game.Overlays }; header.ListingSelected += ShowListing; - badgeDisplay.Selected += onBuildSelected; - listing.BuildSelected += onBuildSelected; - content.BuildSelected += onBuildSelected; + + badges.Selected += ShowBuild; + listing.BuildSelected += ShowBuild; + content.BuildSelected += ShowBuild; sampleBack = audio.Sample.Get(@"UI/generic-select-soft"); // @"UI/screen-back" feels non-fitting here } @@ -127,38 +126,29 @@ namespace osu.Game.Overlays return false; } - private void onBuildSelected(APIChangelogBuild build, EventArgs e) => FetchAndShowBuild(build); - private void fetchListing() { header.ShowListing(); - if (isAtListing) - return; - - isAtListing = true; var req = new GetChangelogRequest(); - badgeDisplay.SelectNone(); req.Success += res => { listing.ShowListing(res.Builds); - badgeDisplay.Populate(res.Streams); + badges.Populate(res.Streams); }; API.Queue(req); } + private bool isAtListing; + public void ShowListing() { + isAtListing = true; header.ShowListing(); - if (isAtListing) - return; - - isAtListing = true; content.Hide(); - listing.Show(); - badgeDisplay.SelectNone(); + badges.SelectNone(); listing.Show(); scroll.ScrollTo(savedScrollPosition); } @@ -169,9 +159,7 @@ namespace osu.Game.Overlays /// Must contain at least and /// . If and /// are specified, the header will instantly display them. - /// Whether to update badges. Should be set to false in case - /// the function is called by selecting a badge, to avoid an infinite loop. - public void FetchAndShowBuild(APIChangelogBuild build, bool updateBadges = true) + public void ShowBuild(APIChangelogBuild build) { var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); @@ -180,8 +168,7 @@ namespace osu.Game.Overlays else req.Success += res => header.ShowBuild(res.UpdateStream.DisplayName, res.DisplayVersion); - if (updateBadges) - badgeDisplay.SelectUpdateStream(build.UpdateStream.Name); + badges.SelectUpdateStream(build.UpdateStream.Name); req.Success += apiChangelog => { From 827ca445b1efa8f9180e7e83ef3ccb9d33442e06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 18:11:22 +0900 Subject: [PATCH 0853/5608] Remove unnecessary ReceivePositionalinputAt modification --- osu.Game/Overlays/ChangelogOverlay.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 2bf5f0336c..2b3fda39a4 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -13,7 +13,6 @@ using osu.Game.Input.Bindings; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Changelog; -using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays @@ -33,9 +32,6 @@ namespace osu.Game.Overlays private float savedScrollPosition; - // receive input outside our bounds so we can trigger a close event on ourselves. - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; - [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colour) { From 1505ca976bc94a30967bba4c5dd66b1da74da59b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 18:21:06 +0900 Subject: [PATCH 0854/5608] API request clean-up --- .../Requests/Responses/APIChangelogBuild.cs | 4 +-- osu.Game/Overlays/ChangelogOverlay.cs | 28 +++++++++++-------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs index 03c3ed0957..3377800c2b 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs @@ -31,9 +31,9 @@ namespace osu.Game.Online.API.Requests.Responses public List ChangelogEntries { get; set; } [JsonProperty("versions")] - public VersionNativation Versions { get; set; } + public VersionNatigation Versions { get; set; } - public class VersionNativation + public class VersionNatigation { [JsonProperty("next")] public APIChangelogBuild Next { get; set; } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 2b3fda39a4..ef049035c3 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -157,28 +157,32 @@ namespace osu.Game.Overlays /// are specified, the header will instantly display them. public void ShowBuild(APIChangelogBuild build) { - var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); - - if (build.UpdateStream.DisplayName != null && build.DisplayVersion != null) - header.ShowBuild(build.UpdateStream.DisplayName, build.DisplayVersion); - else - req.Success += res => header.ShowBuild(res.UpdateStream.DisplayName, res.DisplayVersion); - + header.ShowBuild(build.UpdateStream.DisplayName, build.DisplayVersion); badges.SelectUpdateStream(build.UpdateStream.Name); - req.Success += apiChangelog => + listing.Hide(); + + void displayBuild(APIChangelogBuild populatedBuild) { - listing.Hide(); content.Show(); - content.ShowBuild(apiChangelog); + content.ShowBuild(populatedBuild); + if (scroll.Current > scroll.GetChildPosInContent(content)) scroll.ScrollTo(content); + if (isAtListing) savedScrollPosition = scroll.Current; isAtListing = false; - }; + } - API.Queue(req); + if (build.Versions != null) + displayBuild(build); + else + { + var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); + req.Success += displayBuild; + API.Queue(req); + } } } } From 084ea3efa98734c6cb5deca2ae6b4ca3cdc22bd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 18:27:43 +0900 Subject: [PATCH 0855/5608] Fix another font usage case --- osu.Game/Overlays/Changelog/Header/BreadcrumbRelease.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/Header/BreadcrumbRelease.cs b/osu.Game/Overlays/Changelog/Header/BreadcrumbRelease.cs index 86000ea4d1..43711af61b 100644 --- a/osu.Game/Overlays/Changelog/Header/BreadcrumbRelease.cs +++ b/osu.Game/Overlays/Changelog/Header/BreadcrumbRelease.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Colour; +using osu.Game.Graphics; namespace osu.Game.Overlays.Changelog.Header { @@ -12,7 +13,7 @@ namespace osu.Game.Overlays.Changelog.Header public BreadcrumbRelease(ColourInfo badgeColour, string displayText) : base(badgeColour, displayText) { - Text.Font = "Exo2.0-Bold"; + Text.Font = Text.Font.With(weight: FontWeight.Bold); Text.Y = 20; Text.Alpha = 0; } From 19a179db923aa9aad5f13f37fd24112baada60be Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 18:30:02 +0900 Subject: [PATCH 0856/5608] Bring up-to-date with master --- .../TestSceneChangelogOverlay.cs} | 4 ++-- .../TestSceneLineBadge.cs} | 6 +++--- .../TestSceneTextBadgePair.cs} | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) rename osu.Game.Tests/Visual/{TestCaseChangelogOverlay.cs => Online/TestSceneChangelogOverlay.cs} (92%) rename osu.Game.Tests/Visual/{TestCaseLineBadge.cs => UserInterface/TestSceneLineBadge.cs} (92%) rename osu.Game.Tests/Visual/{TestCaseTextBadgePair.cs => UserInterface/TestSceneTextBadgePair.cs} (92%) diff --git a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs similarity index 92% rename from osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs rename to osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 89b4fd2d18..7ad410ac71 100644 --- a/osu.Game.Tests/Visual/TestCaseChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -5,10 +5,10 @@ using NUnit.Framework; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestCaseChangelogOverlay : OsuTestCase + public class TestSceneChangelogOverlay : OsuTestScene { private ChangelogOverlay changelog; diff --git a/osu.Game.Tests/Visual/TestCaseLineBadge.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLineBadge.cs similarity index 92% rename from osu.Game.Tests/Visual/TestCaseLineBadge.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneLineBadge.cs index ae94767640..9f80cd40cf 100644 --- a/osu.Game.Tests/Visual/TestCaseLineBadge.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLineBadge.cs @@ -7,11 +7,11 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.UserInterface; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { - public class TestCaseLineBadge : OsuTestCase + public class TestSceneLineBadge : OsuTestScene { - public TestCaseLineBadge() + public TestSceneLineBadge() { Container container; LineBadge lineBadge; diff --git a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTextBadgePair.cs similarity index 92% rename from osu.Game.Tests/Visual/TestCaseTextBadgePair.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneTextBadgePair.cs index 2f7ab5deba..67b2b9854d 100644 --- a/osu.Game.Tests/Visual/TestCaseTextBadgePair.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneTextBadgePair.cs @@ -8,11 +8,11 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Overlays.Changelog.Header; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { - public class TestCaseTextBadgePair : OsuTestCase + public class TestSceneTextBadgePair : OsuTestScene { - public TestCaseTextBadgePair() + public TestSceneTextBadgePair() { Breadcrumb breadcrumb; From 1ccef61f7ba21bb02ce1e7b557d28058964bc326 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 18:32:29 +0900 Subject: [PATCH 0857/5608] Fix some missed instances of TestCase --- osu.Game.Tests/Chat/MessageFormatterTests.cs | 2 +- ...stCaseLoadingAnimation.cs => TestSceneLoadingAnimation.cs} | 4 ++-- osu.Game.Tests/WaveformTestBeatmap.cs | 2 +- osu.Game/Tests/Visual/OsuTestScene.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{TestCaseLoadingAnimation.cs => TestSceneLoadingAnimation.cs} (91%) diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs index 720d93cb10..0d6ed67767 100644 --- a/osu.Game.Tests/Chat/MessageFormatterTests.cs +++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs @@ -65,7 +65,7 @@ namespace osu.Game.Tests.Chat } [Test] - public void TestCaseInsensitiveLinks() + public void TestInsensitiveLinks() { Message result = MessageFormatter.FormatMessage(new Message { Content = "look: http://puu.sh/7Ggh8xcC6/asf0asd9876.NEF" }); diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingAnimation.cs similarity index 91% rename from osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneLoadingAnimation.cs index 9befac94f2..b9a6d74f19 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingAnimation.cs @@ -9,9 +9,9 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestCaseLoadingAnimation : GridTestScene //todo: this should be an OsuTestScene + public class TestSceneLoadingAnimation : GridTestScene //todo: this should be an OsuTestScene { - public TestCaseLoadingAnimation() + public TestSceneLoadingAnimation() : base(2, 2) { LoadingAnimation loading; diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index 2028671b0e..f66b374cd7 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -13,7 +13,7 @@ using osu.Game.Tests.Resources; namespace osu.Game.Tests { /// - /// A that is used for testcases that include waveforms. + /// A that is used for test scenes that include waveforms. /// public class WaveformTestBeatmap : WorkingBeatmap { diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index f628f3c29a..9b775fd498 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -85,7 +85,7 @@ namespace osu.Game.Tests.Visual protected override void LoadAsyncComplete() { // this has to be run here rather than LoadComplete because - // TestCase.cs is checking the IsLoaded state (on another thread) and expects + // TestScene.cs is checking the IsLoaded state (on another thread) and expects // the runner to be loaded at that point. Add(runner = new TestSceneTestRunner.TestRunner()); } From 958598d13ba38841a86ac46029d4e363aae88a9c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 19:39:36 +0900 Subject: [PATCH 0858/5608] Fix crash on switching from main menu to gameplay too fast --- osu.Game/Screens/Menu/MainMenu.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 788cad3bad..3afe9b9371 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -155,9 +155,11 @@ namespace osu.Game.Screens.Menu protected override void LogoSuspending(OsuLogo logo) { - logo.FadeOut(300, Easing.InSine) - .ScaleTo(0.2f, 300, Easing.InSine) - .OnComplete(l => buttons.SetOsuLogo(null)); + var seq = logo.FadeOut(300, Easing.InSine) + .ScaleTo(0.2f, 300, Easing.InSine); + + seq.OnComplete(_ => buttons.SetOsuLogo(null)); + seq.OnAbort(_ => buttons.SetOsuLogo(null)); } private void beatmap_ValueChanged(ValueChangedEvent e) From 7c50bdd173ce5c7fbd3cd3d1eaa52725eff372e9 Mon Sep 17 00:00:00 2001 From: Tav TaOr Date: Wed, 15 May 2019 23:48:37 +0300 Subject: [PATCH 0859/5608] Removed redundant parentheses. --- osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs index a9b99f3afe..1853b0228f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs @@ -34,10 +34,7 @@ namespace osu.Game.Rulesets.Osu.Mods public void Update(Playfield playfield) { // If we are on the last replay frame, no need to do anything - if (frameIndex == replayFrames.Count - 1) - { - return; - } + if (frameIndex == replayFrames.Count - 1) return; // Check if we are closer to the next replay frame then the current one if (Math.Abs(replayFrames[frameIndex].Time - playfield.Time.Current) >= Math.Abs(replayFrames[frameIndex + 1].Time - playfield.Time.Current)) From 7f30f61d1b28f2f5249b0e9e87a0fbf66a33aa53 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 May 2019 15:02:13 +0900 Subject: [PATCH 0860/5608] Update DirectListPanel to use same styling --- osu.Game/Overlays/Direct/DirectListPanel.cs | 28 +++++++++------------ 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index d645fd3bda..4c5e4ceae7 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -15,6 +15,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Direct { @@ -163,26 +164,21 @@ namespace osu.Game.Overlays.Direct { new Statistic(FontAwesome.Solid.PlayCircle, SetInfo.OnlineInfo?.PlayCount ?? 0), new Statistic(FontAwesome.Solid.Heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0), - new FillFlowContainer + new LinkFlowContainer(s => + { + s.Shadow = false; + s.Font = OsuFont.GetFont(size: 14); + }) { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new[] - { - new OsuSpriteText - { - Text = "mapped by ", - Font = OsuFont.GetFont(size: 14) - }, - new OsuSpriteText - { - Text = SetInfo.Metadata.Author.Username, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold, italics: true) - }, - }, - }, + }.With(d => + { + d.AutoSizeAxes = Axes.Both; + d.AddText("mapped by "); + d.AddUserLink(SetInfo.Metadata.Author); + }), new OsuSpriteText { Text = SetInfo.Metadata.Source, From 8ee3958b4a8e78e5d6f5259a0e9575f55f336b79 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 May 2019 15:17:44 +0900 Subject: [PATCH 0861/5608] Fix some padding issues with DirectListPanel --- osu.Game/Overlays/Direct/DirectListPanel.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index 4c5e4ceae7..b731e95d54 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -87,8 +87,9 @@ namespace osu.Game.Overlays.Direct { Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, - Size = new Vector2(height / 2), + Size = new Vector2(height / 3), FillMode = FillMode.Fit, + Margin = new MarginPadding { Right = 10 }, }, new FillFlowContainer { @@ -151,7 +152,7 @@ namespace osu.Game.Overlays.Direct Child = new DownloadButton(SetInfo) { Size = new Vector2(height - vertical_padding * 3), - Margin = new MarginPadding { Left = vertical_padding, Right = vertical_padding }, + Margin = new MarginPadding { Left = vertical_padding * 2, Right = vertical_padding }, }, }, new FillFlowContainer From 359e5b71a5cffbb806592d8ccd5cf80a20038676 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 May 2019 17:13:03 +0900 Subject: [PATCH 0862/5608] Fix race condition causing player to never restart --- osu.Game/Screens/Play/Player.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 60054f38fa..30214d1b9c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -249,6 +249,10 @@ namespace osu.Game.Screens.Play if (!this.IsCurrentScreen()) return; sampleRestart?.Play(); + + // if a restart has been requested, cancel any pending completion (user has shown intent to restart). + onCompletionEvent = null; + ValidForResume = false; RestartRequested?.Invoke(); this.Exit(); From 409d89eecf1d6baff6aafaffe7b7d36934ea9ecc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 May 2019 18:53:20 +0900 Subject: [PATCH 0863/5608] Match header titles with web (pt size) --- .../Graphics/UserInterface/ScreenTitle.cs | 4 ++-- .../Changelog/ChangelogContentGroup.cs | 20 +++++++++---------- .../Overlays/Changelog/ChangelogHeader.cs | 4 ++-- .../Overlays/Changelog/Header/Breadcrumb.cs | 2 +- osu.Game/Overlays/Changelog/StreamBadge.cs | 6 +++--- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index b9d9b5427d..34c70f2bed 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -66,11 +66,11 @@ namespace osu.Game.Graphics.UserInterface { titleText = new OsuSpriteText { - Font = OsuFont.GetFont(size: 25), + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light), }, pageText = new OsuSpriteText { - Font = OsuFont.GetFont(size: 25), + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light), } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 1b03ade7e0..9f3da7eade 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -64,17 +64,17 @@ namespace osu.Game.Overlays.Changelog new SpriteText { Text = build.UpdateStream.DisplayName, - Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 28), // web: 24, + Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 24), }, new SpriteText { Text = " ", - Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 28), // web: 24, + Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 24), }, new SpriteText { Text = build.DisplayVersion, - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 28), // web: 24, + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 24), Colour = StreamColour.FromStreamName(build.UpdateStream.Name), }, } @@ -97,7 +97,7 @@ namespace osu.Game.Overlays.Changelog // do we need .ToUniversalTime() here? // also, this should be a temporary solution to weekdays in >localized< date strings Text = build.CreatedAt.Date.ToLongDateString().Replace(build.CreatedAt.ToString("dddd") + ", ", ""), - Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 17), // web: 14, + Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 14), Colour = OsuColour.FromHex(@"FD5"), Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -126,7 +126,7 @@ namespace osu.Game.Overlays.Changelog // do we need .ToUniversalTime() here? // also, this should be a temporary solution to weekdays in >localized< date strings Text = build.CreatedAt.Date.ToLongDateString().Replace(build.CreatedAt.ToString("dddd") + ", ", ""), - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 28), // web: 24, + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 24), Colour = OsuColour.FromHex(@"FD5"), Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -150,12 +150,12 @@ namespace osu.Game.Overlays.Changelog new SpriteText { Text = build.UpdateStream.DisplayName, - Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 20), // web: 19, + Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 19), }, new SpriteText { Text = build.DisplayVersion, - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 20), // web: 19, + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 19), Colour = StreamColour.FromStreamName(build.UpdateStream.Name), }, }, @@ -214,7 +214,7 @@ namespace osu.Game.Overlays.Changelog ChangelogEntries.Add(new SpriteText { Text = category.Key, - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 24), // web: 24, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 24), Margin = new MarginPadding { Top = 35, Bottom = 15 }, }); @@ -252,7 +252,7 @@ namespace osu.Game.Overlays.Changelog Online.Chat.LinkAction.External, null, null, t => t.Font = OsuFont.GetFont(size: 14)); else - title.AddText(entry.GithubUser.DisplayName, t => t.Font = OsuFont.GetFont(size: 14)); //web: 12; + title.AddText(entry.GithubUser.DisplayName, t => t.Font = OsuFont.GetFont(size: 12)); ChangelogEntries.Add(title); @@ -267,7 +267,7 @@ namespace osu.Game.Overlays.Changelog // todo: use markdown parsing once API returns markdown messageContainer.AddText(Regex.Replace(entry.MessageHtml, @"<(.|\n)*?>", string.Empty), t => { - t.Font = OsuFont.GetFont(size: 14); // web: 12, + t.Font = OsuFont.GetFont(size: 12); t.Colour = new Color4(235, 184, 254, 255); }); diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 4186356bd4..c2a341cfe8 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -108,12 +108,12 @@ namespace osu.Game.Overlays.Changelog new OsuSpriteText { Text = "Changelog ", - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 38), // web: 30, + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 30), }, titleStream = new OsuSpriteText { Text = "Listing", - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 38), // web: 30, + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 30), Colour = colours.Violet, }, } diff --git a/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs b/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs index 43dcaf22ca..ae902043e3 100644 --- a/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs +++ b/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.Changelog.Header { Text = new SpriteText { - Font = OsuFont.GetFont(size: 21), // web: 16, + Font = OsuFont.GetFont(size: 16), Text = displayText, Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index b617ae8f53..721689c75d 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -56,18 +56,18 @@ namespace osu.Game.Overlays.Changelog new SpriteText { Text = stream.DisplayName, - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), // web: 12, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12), Margin = new MarginPadding { Top = 6 }, }, new SpriteText { Text = stream.LatestBuild.DisplayVersion, - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 20), // web: 16, + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 16), }, new SpriteText { Text = stream.LatestBuild.Users > 0 ? $"{stream.LatestBuild.Users:N0} users online" : null, - Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 12), // web: 10, + Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 10), Colour = new Color4(203, 164, 218, 255), }, } From 01b75db21a791732b1e2c57951eaae7a8c2523ac Mon Sep 17 00:00:00 2001 From: Lucas A Date: Thu, 16 May 2019 18:36:54 +0200 Subject: [PATCH 0864/5608] Use ruleset.ShortName instead of hardcoded names. --- osu.Desktop/DiscordRichPresenceClient.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Desktop/DiscordRichPresenceClient.cs b/osu.Desktop/DiscordRichPresenceClient.cs index d49b08823c..38e929c1ae 100644 --- a/osu.Desktop/DiscordRichPresenceClient.cs +++ b/osu.Desktop/DiscordRichPresenceClient.cs @@ -80,19 +80,19 @@ namespace osu.Desktop switch (ruleset.ID) { case 0: - presence.Assets.SmallImageKey = "osu"; + presence.Assets.SmallImageKey = ruleset.ShortName; break; case 1: - presence.Assets.SmallImageKey = "taiko"; + presence.Assets.SmallImageKey = ruleset.ShortName; break; case 2: - presence.Assets.SmallImageKey = "fruits"; + presence.Assets.SmallImageKey = ruleset.ShortName; break; case 3: - presence.Assets.SmallImageKey = "mania"; + presence.Assets.SmallImageKey = ruleset.ShortName; break; default: From 880bfe9b6b4037866d17460d5e3afbebded8bb9b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 May 2019 10:29:27 +0900 Subject: [PATCH 0865/5608] Move resources to osu-resources --- osu.Game/Overlays/Changelog/ChangelogHeader.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index c2a341cfe8..7502ef1773 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.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.Allocation; @@ -50,7 +50,7 @@ namespace osu.Game.Overlays.Changelog new Sprite { RelativeSizeAxes = Axes.Both, - Texture = textures.Get(@"https://osu.ppy.sh/images/headers/changelog.jpg"), + Texture = textures.Get(@"Headers/changelog"), FillMode = FillMode.Fill, }, } @@ -76,8 +76,7 @@ namespace osu.Game.Overlays.Changelog new Sprite { RelativeSizeAxes = Axes.Both, - // todo: https://osu.ppy.sh/images/icons/changelog.svg - Texture = textures.Get(@"https://i.imgur.com/HQM3Vhp.png"), + Texture = textures.Get(@"Icons/changelog"), Size = new Vector2(0.8f), Anchor = Anchor.Centre, Origin = Anchor.Centre, From 5bf513eba83e16d1e16231cd776bb9bc5727550a Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 17 May 2019 11:24:34 +0900 Subject: [PATCH 0866/5608] Don't track immediately when entering mode --- .../UserInterface/TestCaseButtonSystem.cs | 21 ++++++++++++++++++- osu.Game/Screens/Menu/ButtonSystem.cs | 2 +- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs index 04aa8bce7e..814558547a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Shapes; using osu.Game.Screens.Menu; +using osuTK; using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface @@ -42,7 +43,25 @@ namespace osu.Game.Tests.Visual.UserInterface buttons.SetOsuLogo(logo); foreach (var s in Enum.GetValues(typeof(ButtonSystemState)).OfType().Skip(1)) - AddStep($"State to {s}", () => buttons.State = s); + AddStep($"State to {s}", () => + { + buttons.State = s; + + if (buttons.State == ButtonSystemState.EnteringMode) + { + buttons.FadeOut(400, Easing.InSine); + buttons.MoveTo(new Vector2(-800, 0), 400, Easing.InSine); + logo.FadeOut(300, Easing.InSine) + .ScaleTo(0.2f, 300, Easing.InSine); + } + else + { + buttons.FadeIn(400, Easing.OutQuint); + buttons.MoveTo(new Vector2(0), 400, Easing.OutQuint); + logo.FadeColour(Color4.White, 100, Easing.OutQuint); + logo.FadeIn(100, Easing.OutQuint); + } + }); } } } diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index a098d42c83..9784e8cfcb 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -332,7 +332,7 @@ namespace osu.Game.Screens.Menu break; case ButtonSystemState.EnteringMode: - logoTrackingContainer.StartTracking(logo, 0, Easing.In); + logoTrackingContainer.StartTracking(logo, 400, Easing.InSine); break; } } From b7aed0a0147e8881a05cac4404ea3a22d8addcf0 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 17 May 2019 12:21:34 +0900 Subject: [PATCH 0867/5608] Interpolate to tracking position on from Initial button state --- osu.Game/Screens/Menu/ButtonSystem.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 9784e8cfcb..900e5ae514 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -332,7 +332,8 @@ namespace osu.Game.Screens.Menu break; case ButtonSystemState.EnteringMode: - logoTrackingContainer.StartTracking(logo, 400, Easing.InSine); + // When coming from the Initial (untracked) state, interpolate to the tracking position over a brief duration instead of tracking immediately. + logoTrackingContainer.StartTracking(logo, lastState == ButtonSystemState.Initial ? 400 : 0, Easing.InSine); break; } } From e94b9feebd04c8f56f6df087e56607c0814bd97a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 May 2019 10:29:43 +0900 Subject: [PATCH 0868/5608] Fix dynamic recompilation in TestSceneChangelogOverlay --- .../Visual/Online/TestSceneChangelogOverlay.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 7ad410ac71..0e4f31c217 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -1,9 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; +using osu.Game.Overlays.Changelog; +using osu.Game.Overlays.Changelog.Header; namespace osu.Game.Tests.Visual.Online { @@ -12,6 +16,18 @@ namespace osu.Game.Tests.Visual.Online { private ChangelogOverlay changelog; + public override IReadOnlyList RequiredTypes => new[] + { + typeof(BadgeDisplay), + typeof(StreamBadge), + typeof(ChangelogHeader), + typeof(ChangelogContent), + typeof(ChangelogContentGroup), + typeof(Breadcrumb), + typeof(BreadcrumbListing), + typeof(BreadcrumbRelease), + }; + protected override void LoadComplete() { base.LoadComplete(); From e606c7332931f3af3a9d58d85c882c6f62603ffe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 May 2019 11:43:36 +0900 Subject: [PATCH 0869/5608] Convert BadgeDisplay to use bindable --- osu.Game/Overlays/Changelog/BadgeDisplay.cs | 66 +++++-------------- .../Overlays/Changelog/ChangelogHeader.cs | 11 +--- osu.Game/Overlays/Changelog/StreamBadge.cs | 6 +- osu.Game/Overlays/ChangelogOverlay.cs | 15 ++++- 4 files changed, 36 insertions(+), 62 deletions(-) diff --git a/osu.Game/Overlays/Changelog/BadgeDisplay.cs b/osu.Game/Overlays/Changelog/BadgeDisplay.cs index 8c58decf49..e04624cfcb 100644 --- a/osu.Game/Overlays/Changelog/BadgeDisplay.cs +++ b/osu.Game/Overlays/Changelog/BadgeDisplay.cs @@ -6,8 +6,8 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Online.API.Requests.Responses; -using System; using System.Collections.Generic; +using osu.Framework.Bindables; using osuTK.Graphics; namespace osu.Game.Overlays.Changelog @@ -17,10 +17,9 @@ namespace osu.Game.Overlays.Changelog private const float vertical_padding = 20; private const float horizontal_padding = 85; - public event Action Selected; + public readonly Bindable Current = new Bindable(); private readonly FillFlowContainer badgesContainer; - private long selectedStreamId = -1; public BadgeDisplay() { @@ -40,23 +39,34 @@ namespace osu.Game.Overlays.Changelog Padding = new MarginPadding { Vertical = vertical_padding, Horizontal = horizontal_padding }, }, }; + + Current.ValueChanged += e => + { + foreach (StreamBadge streamBadge in badgesContainer) + { + if (!IsHovered || e.NewValue.Id == streamBadge.Stream.Id) + streamBadge.Activate(); + else + streamBadge.Deactivate(); + } + }; } public void Populate(List streams) { - SelectNone(); + Current.Value = null; foreach (APIUpdateStream updateStream in streams) { var streamBadge = new StreamBadge(updateStream); - streamBadge.Selected += onBadgeSelected; + streamBadge.Selected += () => Current.Value = updateStream; badgesContainer.Add(streamBadge); } } public void SelectNone() { - selectedStreamId = -1; + Current.Value = null; if (badgesContainer != null) { @@ -70,45 +80,10 @@ namespace osu.Game.Overlays.Changelog } } - public void SelectUpdateStream(string updateStream) - { - foreach (StreamBadge streamBadge in badgesContainer) - { - if (streamBadge.Stream.Name == updateStream) - { - selectedStreamId = streamBadge.Stream.Id; - streamBadge.Activate(); - } - else - streamBadge.Deactivate(); - } - } - - private void onBadgeSelected(StreamBadge source, EventArgs args) - { - selectedStreamId = source.Stream.Id; - OnSelected(source); - } - - protected virtual void OnSelected(StreamBadge source) - { - Selected?.Invoke(source.Stream.LatestBuild); - } - protected override bool OnHover(HoverEvent e) { foreach (StreamBadge streamBadge in badgesContainer.Children) - { - if (selectedStreamId >= 0) - { - if (selectedStreamId != streamBadge.Stream.Id) - streamBadge.Deactivate(); - else - streamBadge.EnableDim(); - } - else - streamBadge.Deactivate(); - } + streamBadge.EnableDim(); return base.OnHover(e); } @@ -116,12 +91,7 @@ namespace osu.Game.Overlays.Changelog protected override void OnHoverLost(HoverLostEvent e) { foreach (StreamBadge streamBadge in badgesContainer.Children) - { - if (selectedStreamId < 0) - streamBadge.Activate(); - else if (streamBadge.Stream.Id == selectedStreamId) - streamBadge.DisableDim(); - } + streamBadge.DisableDim(); base.OnHoverLost(e); } diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 7502ef1773..94046d5762 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.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.Allocation; @@ -81,18 +81,13 @@ namespace osu.Game.Overlays.Changelog Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - - // this box has 2 functions: - // - ensures the circle doesn't disappear on the X and Y edges - // - gets rid of the white "contamination" on the circle (due to smoothing) - // (https://i.imgur.com/SMuvWBZ.png) new Box { RelativeSizeAxes = Axes.Both, + Colour = colours.Violet, Alpha = 0, AlwaysPresent = true, - Colour = colours.Violet, - } + }, } }, new FillFlowContainer diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 721689c75d..2be6aba926 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -22,9 +22,7 @@ namespace osu.Game.Overlays.Changelog private const float badge_width = 100; private const float transition_duration = 100; - public delegate void SelectedHandler(StreamBadge source, EventArgs args); - - public event SelectedHandler Selected; + public event Action Selected; private bool isActivated; @@ -90,7 +88,7 @@ namespace osu.Game.Overlays.Changelog this.FadeIn(transition_duration); lineBadge.Uncollapse(); if (!withoutFiringUpdates) - Selected?.Invoke(this, EventArgs.Empty); + Selected?.Invoke(); } public void Deactivate() diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index ef049035c3..71393141bd 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -70,7 +70,8 @@ namespace osu.Game.Overlays header.ListingSelected += ShowListing; - badges.Selected += ShowBuild; + // todo: better + badges.Current.ValueChanged += e => ShowBuild(e.NewValue.LatestBuild); listing.BuildSelected += ShowBuild; content.BuildSelected += ShowBuild; @@ -129,6 +130,10 @@ namespace osu.Game.Overlays var req = new GetChangelogRequest(); req.Success += res => { + // remap streams to builds to ensure model equality + res.Builds.ForEach(b => b.UpdateStream = res.Streams.Find(s => s.Id == b.UpdateStream.Id)); + res.Streams.ForEach(s => s.LatestBuild.UpdateStream = res.Streams.Find(s2 => s2.Id == s.LatestBuild.UpdateStream.Id)); + listing.ShowListing(res.Builds); badges.Populate(res.Streams); }; @@ -157,8 +162,14 @@ namespace osu.Game.Overlays /// are specified, the header will instantly display them. public void ShowBuild(APIChangelogBuild build) { + if (build == null) + { + ShowListing(); + return; + } + header.ShowBuild(build.UpdateStream.DisplayName, build.DisplayVersion); - badges.SelectUpdateStream(build.UpdateStream.Name); + badges.Current.Value = build.UpdateStream; listing.Hide(); From 37e989fc64351f181bf6d0b8152e213375e05599 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 May 2019 12:40:15 +0900 Subject: [PATCH 0870/5608] fixup! Convert BadgeDisplay to use bindable --- .../API/Requests/Responses/APIUpdateStream.cs | 11 ++++++++++- osu.Game/Overlays/Changelog/BadgeDisplay.cs | 16 ---------------- osu.Game/Overlays/ChangelogOverlay.cs | 9 +++++++-- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs index 5cf56333bb..25f1a413d6 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using Newtonsoft.Json; namespace osu.Game.Online.API.Requests.Responses { - public class APIUpdateStream + public class APIUpdateStream : IEquatable { [JsonProperty("id")] public long Id { get; set; } @@ -21,5 +22,13 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("latest_build")] public APIChangelogBuild LatestBuild { get; set; } + + public bool Equals(APIUpdateStream other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return Id == other.Id; + } } } diff --git a/osu.Game/Overlays/Changelog/BadgeDisplay.cs b/osu.Game/Overlays/Changelog/BadgeDisplay.cs index e04624cfcb..9b0f152eb0 100644 --- a/osu.Game/Overlays/Changelog/BadgeDisplay.cs +++ b/osu.Game/Overlays/Changelog/BadgeDisplay.cs @@ -64,22 +64,6 @@ namespace osu.Game.Overlays.Changelog } } - public void SelectNone() - { - Current.Value = null; - - if (badgesContainer != null) - { - foreach (StreamBadge streamBadge in badgesContainer) - { - if (!IsHovered) - streamBadge.Activate(); - else - streamBadge.Deactivate(); - } - } - } - protected override bool OnHover(HoverEvent e) { foreach (StreamBadge streamBadge in badgesContainer.Children) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 71393141bd..17a2441a9e 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -71,7 +71,12 @@ namespace osu.Game.Overlays header.ListingSelected += ShowListing; // todo: better - badges.Current.ValueChanged += e => ShowBuild(e.NewValue.LatestBuild); + badges.Current.ValueChanged += e => + { + if (e.NewValue?.LatestBuild != null) + ShowBuild(e.NewValue.LatestBuild); + }; + listing.BuildSelected += ShowBuild; content.BuildSelected += ShowBuild; @@ -149,7 +154,7 @@ namespace osu.Game.Overlays header.ShowListing(); content.Hide(); - badges.SelectNone(); + badges.Current.Value = null; listing.Show(); scroll.ScrollTo(savedScrollPosition); } From 876f108e0a035ff9d4b901c5849fc59c30906dc9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 May 2019 12:42:08 +0900 Subject: [PATCH 0871/5608] Remove custom scroll logic --- osu.Game/Overlays/ChangelogOverlay.cs | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 17a2441a9e..afa4f4185e 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -26,12 +26,8 @@ namespace osu.Game.Overlays private ChangelogContent listing; private ChangelogContent content; - private ScrollContainer scroll; - private SampleChannel sampleBack; - private float savedScrollPosition; - [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colour) { @@ -48,7 +44,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Colour = new Color4(49, 36, 54, 255), }, - scroll = new ScrollContainer + new ScrollContainer { RelativeSizeAxes = Axes.Both, ScrollbarVisible = false, @@ -106,15 +102,9 @@ namespace osu.Game.Overlays switch (action) { case GlobalAction.Back: - if (isAtListing) + if (listing.Alpha == 1) { - if (scroll.Current > scroll.GetChildPosInContent(listing)) - { - scroll.ScrollTo(0); - sampleBack?.Play(); - } - else - State = Visibility.Hidden; + State = Visibility.Hidden; } else { @@ -146,17 +136,13 @@ namespace osu.Game.Overlays API.Queue(req); } - private bool isAtListing; - public void ShowListing() { - isAtListing = true; header.ShowListing(); content.Hide(); badges.Current.Value = null; listing.Show(); - scroll.ScrollTo(savedScrollPosition); } ///
@@ -182,13 +168,6 @@ namespace osu.Game.Overlays { content.Show(); content.ShowBuild(populatedBuild); - - if (scroll.Current > scroll.GetChildPosInContent(content)) - scroll.ScrollTo(content); - - if (isAtListing) - savedScrollPosition = scroll.Current; - isAtListing = false; } if (build.Versions != null) From dd2d58d4f7c64726cd4ef1b277954d83ad55912c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 May 2019 17:15:51 +0900 Subject: [PATCH 0872/5608] Split out ChangelogContent into two classes --- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 30 ++++++++ .../Overlays/Changelog/ChangelogContent.cs | 60 +--------------- .../Overlays/Changelog/ChangelogListing.cs | 70 +++++++++++++++++++ osu.Game/Overlays/ChangelogOverlay.cs | 37 +++++----- 4 files changed, 118 insertions(+), 79 deletions(-) create mode 100644 osu.Game/Overlays/Changelog/ChangelogBuild.cs create mode 100644 osu.Game/Overlays/Changelog/ChangelogListing.cs diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs new file mode 100644 index 0000000000..0f3e76021b --- /dev/null +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Overlays.Changelog +{ + public class ChangelogBuild : ChangelogContent + { + private readonly APIChangelogBuild changelogBuild; + + public ChangelogBuild(APIChangelogBuild changelogBuild) + { + this.changelogBuild = changelogBuild; + } + + [BackgroundDependencyLoader] + private void load() + { + var changelogContentGroup = new ChangelogContentGroup(changelogBuild); + changelogContentGroup.GenerateText(changelogBuild.ChangelogEntries); + changelogContentGroup.UpdateChevronTooltips(changelogBuild.Versions.Previous?.DisplayVersion, + changelogBuild.Versions.Next?.DisplayVersion); + changelogContentGroup.BuildSelected += SelectBuild; + + Add(changelogContentGroup); + } + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 45fb98add0..92c33567a8 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -3,20 +3,17 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Game.Online.API.Requests.Responses; using System; -using System.Collections.Generic; -using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { public class ChangelogContent : FillFlowContainer { - private ChangelogContentGroup changelogContentGroup; - public event Action BuildSelected; + public void SelectBuild(APIChangelogBuild build) => BuildSelected?.Invoke(build); + public ChangelogContent() { RelativeSizeAxes = Axes.X; @@ -24,58 +21,5 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Vertical; Padding = new MarginPadding { Bottom = 100 }; } - - public void ShowListing(List changelog) - { - DateTime currentDate = new DateTime(); - Clear(); - - foreach (APIChangelogBuild build in changelog) - { - if (build.CreatedAt.Date != currentDate) - { - if (Children.Count != 0) - { - Add(new Box - { - RelativeSizeAxes = Axes.X, - Height = 2, - Colour = new Color4(17, 17, 17, 255), - Margin = new MarginPadding { Top = 30 }, - }); - } - - changelogContentGroup = new ChangelogContentGroup(build, true); - changelogContentGroup.BuildSelected += b => BuildSelected?.Invoke(b); - changelogContentGroup.GenerateText(build.ChangelogEntries); - Add(changelogContentGroup); - currentDate = build.CreatedAt.Date; - } - else - { - changelogContentGroup.Add(new Box - { - RelativeSizeAxes = Axes.X, - Height = 1, - Colour = new Color4(32, 24, 35, 255), - Margin = new MarginPadding { Top = 30 }, - }); - - changelogContentGroup = new ChangelogContentGroup(build, false); - changelogContentGroup.BuildSelected += b => BuildSelected?.Invoke(b); - changelogContentGroup.GenerateText(build.ChangelogEntries); - Add(changelogContentGroup); - } - } - } - - public void ShowBuild(APIChangelogBuild changelogBuild) - { - Child = changelogContentGroup = new ChangelogContentGroup(changelogBuild); - changelogContentGroup.GenerateText(changelogBuild.ChangelogEntries); - changelogContentGroup.UpdateChevronTooltips(changelogBuild.Versions.Previous?.DisplayVersion, - changelogBuild.Versions.Next?.DisplayVersion); - changelogContentGroup.BuildSelected += b => BuildSelected?.Invoke(b); - } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogListing.cs b/osu.Game/Overlays/Changelog/ChangelogListing.cs new file mode 100644 index 0000000000..8e615d1dc9 --- /dev/null +++ b/osu.Game/Overlays/Changelog/ChangelogListing.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; +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Online.API.Requests.Responses; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Changelog +{ + public class ChangelogListing : ChangelogContent + { + private readonly List entries; + + public ChangelogListing(List entries) + { + this.entries = entries; + } + + [BackgroundDependencyLoader] + private void load() + { + DateTime currentDate = new DateTime(); + Clear(); + + ChangelogContentGroup changelogContentGroup = null; + + foreach (APIChangelogBuild build in entries) + { + if (build.CreatedAt.Date != currentDate) + { + if (Children.Count != 0) + { + Add(new Box + { + RelativeSizeAxes = Axes.X, + Height = 2, + Colour = new Color4(17, 17, 17, 255), + Margin = new MarginPadding { Top = 30 }, + }); + } + + changelogContentGroup = new ChangelogContentGroup(build, true); + changelogContentGroup.BuildSelected += SelectBuild; + changelogContentGroup.GenerateText(build.ChangelogEntries); + Add(changelogContentGroup); + currentDate = build.CreatedAt.Date; + } + else + { + changelogContentGroup?.Add(new Box + { + RelativeSizeAxes = Axes.X, + Height = 1, + Colour = new Color4(32, 24, 35, 255), + Margin = new MarginPadding { Top = 30 }, + }); + + changelogContentGroup = new ChangelogContentGroup(build, false); + changelogContentGroup.BuildSelected += SelectBuild; + changelogContentGroup.GenerateText(build.ChangelogEntries); + Add(changelogContentGroup); + } + } + } + } +} diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index afa4f4185e..6ef239733d 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.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.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -23,15 +24,15 @@ namespace osu.Game.Overlays private BadgeDisplay badges; - private ChangelogContent listing; - private ChangelogContent content; + private Container content; private SampleChannel sampleBack; + private List builds; + [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colour) { - // these possibly need adjusting? Waves.FirstWaveColour = colour.Violet; Waves.SecondWaveColour = OsuColour.FromHex(@"8F03BF"); Waves.ThirdWaveColour = OsuColour.FromHex(@"600280"); @@ -57,8 +58,11 @@ namespace osu.Game.Overlays { header = new ChangelogHeader(), badges = new BadgeDisplay(), - listing = new ChangelogContent(), - content = new ChangelogContent() + content = new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } }, }, }, @@ -73,10 +77,7 @@ namespace osu.Game.Overlays ShowBuild(e.NewValue.LatestBuild); }; - listing.BuildSelected += ShowBuild; - content.BuildSelected += ShowBuild; - - sampleBack = audio.Sample.Get(@"UI/generic-select-soft"); // @"UI/screen-back" feels non-fitting here + sampleBack = audio.Sample.Get(@"UI/generic-select-soft"); } protected override void LoadComplete() @@ -102,7 +103,7 @@ namespace osu.Game.Overlays switch (action) { case GlobalAction.Back: - if (listing.Alpha == 1) + if (content.Child is ChangelogContent) { State = Visibility.Hidden; } @@ -129,7 +130,8 @@ namespace osu.Game.Overlays res.Builds.ForEach(b => b.UpdateStream = res.Streams.Find(s => s.Id == b.UpdateStream.Id)); res.Streams.ForEach(s => s.LatestBuild.UpdateStream = res.Streams.Find(s2 => s2.Id == s.LatestBuild.UpdateStream.Id)); - listing.ShowListing(res.Builds); + builds = res.Builds; + ShowListing(); badges.Populate(res.Streams); }; @@ -139,10 +141,8 @@ namespace osu.Game.Overlays public void ShowListing() { header.ShowListing(); - - content.Hide(); badges.Current.Value = null; - listing.Show(); + content.Child = new ChangelogListing(builds); } /// @@ -162,13 +162,8 @@ namespace osu.Game.Overlays header.ShowBuild(build.UpdateStream.DisplayName, build.DisplayVersion); badges.Current.Value = build.UpdateStream; - listing.Hide(); - - void displayBuild(APIChangelogBuild populatedBuild) - { - content.Show(); - content.ShowBuild(populatedBuild); - } + void displayBuild(APIChangelogBuild populatedBuild) => + content.Child = new ChangelogBuild(populatedBuild); if (build.Versions != null) displayBuild(build); From c5c1896a11e9acebe93e30b57ae7d43e6f374f07 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 May 2019 17:20:50 +0900 Subject: [PATCH 0873/5608] Use new colour palette --- osu.Game/Overlays/ChangelogOverlay.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 6ef239733d..c9a9aee895 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -33,10 +33,10 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colour) { - Waves.FirstWaveColour = colour.Violet; - Waves.SecondWaveColour = OsuColour.FromHex(@"8F03BF"); - Waves.ThirdWaveColour = OsuColour.FromHex(@"600280"); - Waves.FourthWaveColour = OsuColour.FromHex(@"300140"); + Waves.FirstWaveColour = colour.GreyVioletLight; + Waves.SecondWaveColour = colour.GreyViolet; + Waves.ThirdWaveColour = colour.GreyVioletDark; + Waves.FourthWaveColour = colour.GreyVioletDarker; Children = new Drawable[] { From c41ec20236a7c57da0a62dfc53bd162c49e6abad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 May 2019 17:47:28 +0900 Subject: [PATCH 0874/5608] Improve load and switch logic between views --- .../Online/TestSceneChangelogOverlay.cs | 2 + osu.Game/Overlays/Changelog/ChangelogBuild.cs | 24 +++++- .../Overlays/Changelog/ChangelogContent.cs | 2 +- osu.Game/Overlays/ChangelogOverlay.cs | 75 +++++++++++-------- 4 files changed, 68 insertions(+), 35 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 0e4f31c217..e1cb6e6a85 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -22,6 +22,8 @@ namespace osu.Game.Tests.Visual.Online typeof(StreamBadge), typeof(ChangelogHeader), typeof(ChangelogContent), + typeof(ChangelogListing), + typeof(ChangelogBuild), typeof(ChangelogContentGroup), typeof(Breadcrumb), typeof(BreadcrumbListing), diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 0f3e76021b..0af117c11e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -1,14 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Threading; +using System.Threading.Tasks; using osu.Framework.Allocation; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Changelog { public class ChangelogBuild : ChangelogContent { - private readonly APIChangelogBuild changelogBuild; + private APIChangelogBuild changelogBuild; public ChangelogBuild(APIChangelogBuild changelogBuild) { @@ -16,8 +20,24 @@ namespace osu.Game.Overlays.Changelog } [BackgroundDependencyLoader] - private void load() + private void load(CancellationToken? cancellation, IAPIProvider api) { + var req = new GetChangelogBuildRequest(changelogBuild.UpdateStream.Name, changelogBuild.Version); + bool complete = false; + + req.Success += res => + { + changelogBuild = res; + complete = true; + }; + + req.Failure += _ => complete = true; + + api.Queue(req); + + while (!complete && cancellation?.IsCancellationRequested != true) + Task.Delay(1); + var changelogContentGroup = new ChangelogContentGroup(changelogBuild); changelogContentGroup.GenerateText(changelogBuild.ChangelogEntries); changelogContentGroup.UpdateChevronTooltips(changelogBuild.Versions.Previous?.DisplayVersion, diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 92c33567a8..f8d5bbd66c 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Changelog { public class ChangelogContent : FillFlowContainer { - public event Action BuildSelected; + public Action BuildSelected; public void SelectBuild(APIChangelogBuild build) => BuildSelected?.Invoke(build); diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index c9a9aee895..b8449f618d 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; +using System.Threading; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -24,7 +26,7 @@ namespace osu.Game.Overlays private BadgeDisplay badges; - private Container content; + private Container content; private SampleChannel sampleBack; @@ -58,7 +60,7 @@ namespace osu.Game.Overlays { header = new ChangelogHeader(), badges = new BadgeDisplay(), - content = new Container + content = new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -103,7 +105,7 @@ namespace osu.Game.Overlays switch (action) { case GlobalAction.Back: - if (content.Child is ChangelogContent) + if (content.Child is ChangelogListing) { State = Visibility.Hidden; } @@ -119,30 +121,14 @@ namespace osu.Game.Overlays return false; } - private void fetchListing() - { - header.ShowListing(); - - var req = new GetChangelogRequest(); - req.Success += res => - { - // remap streams to builds to ensure model equality - res.Builds.ForEach(b => b.UpdateStream = res.Streams.Find(s => s.Id == b.UpdateStream.Id)); - res.Streams.ForEach(s => s.LatestBuild.UpdateStream = res.Streams.Find(s2 => s2.Id == s.LatestBuild.UpdateStream.Id)); - - builds = res.Builds; - ShowListing(); - badges.Populate(res.Streams); - }; - - API.Queue(req); - } - public void ShowListing() { + if (content.Children.FirstOrDefault() is ChangelogListing) + return; + header.ShowListing(); badges.Current.Value = null; - content.Child = new ChangelogListing(builds); + loadContent(new ChangelogListing(builds)); } /// @@ -162,17 +148,42 @@ namespace osu.Game.Overlays header.ShowBuild(build.UpdateStream.DisplayName, build.DisplayVersion); badges.Current.Value = build.UpdateStream; - void displayBuild(APIChangelogBuild populatedBuild) => - content.Child = new ChangelogBuild(populatedBuild); + loadContent(new ChangelogBuild(build)); + } - if (build.Versions != null) - displayBuild(build); - else + private void fetchListing() + { + var req = new GetChangelogRequest(); + req.Success += res => { - var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); - req.Success += displayBuild; - API.Queue(req); - } + // remap streams to builds to ensure model equality + res.Builds.ForEach(b => b.UpdateStream = res.Streams.Find(s => s.Id == b.UpdateStream.Id)); + res.Streams.ForEach(s => s.LatestBuild.UpdateStream = res.Streams.Find(s2 => s2.Id == s.LatestBuild.UpdateStream.Id)); + + builds = res.Builds; + badges.Populate(res.Streams); + + ShowListing(); + }; + + API.Queue(req); + } + + private CancellationTokenSource loadContentTask; + + private void loadContent(ChangelogContent newContent) + { + content.FadeTo(0.2f, 300, Easing.OutQuint); + + loadContentTask?.Cancel(); + + LoadComponentAsync(newContent, c => + { + content.FadeIn(300, Easing.OutQuint); + + c.BuildSelected = ShowBuild; + content.Child = c; + }, (loadContentTask = new CancellationTokenSource()).Token); } } } From 0b076c9ca0807f2c4e2e38c17c5b85064cee5464 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 May 2019 17:49:05 +0900 Subject: [PATCH 0875/5608] Only fetch after initial pop in --- osu.Game/Overlays/ChangelogOverlay.cs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index b8449f618d..f4c0338436 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -82,22 +82,12 @@ namespace osu.Game.Overlays sampleBack = audio.Sample.Get(@"UI/generic-select-soft"); } - protected override void LoadComplete() - { - base.LoadComplete(); - fetchListing(); - } - protected override void PopIn() { base.PopIn(); - FadeEdgeEffectTo(0.25f, WaveContainer.APPEAR_DURATION, Easing.In); - } - protected override void PopOut() - { - base.PopOut(); - FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); + if (!initialFetchPerformed) + fetchListing(); } public override bool OnPressed(GlobalAction action) @@ -151,8 +141,12 @@ namespace osu.Game.Overlays loadContent(new ChangelogBuild(build)); } + private bool initialFetchPerformed; + private void fetchListing() { + initialFetchPerformed = true; + var req = new GetChangelogRequest(); req.Success += res => { @@ -165,6 +159,7 @@ namespace osu.Game.Overlays ShowListing(); }; + req.Failure += _ => initialFetchPerformed = false; API.Queue(req); } From dbc42fd59e1b1b786a84b8d672b2502d5924ce95 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 May 2019 18:09:11 +0900 Subject: [PATCH 0876/5608] Remove StreamColour class and implement locally --- osu.Game/Graphics/StreamColour.cs | 43 ------------------- .../API/Requests/Responses/APIUpdateStream.cs | 32 ++++++++++++++ .../Changelog/ChangelogContentGroup.cs | 4 +- osu.Game/Overlays/Changelog/StreamBadge.cs | 2 +- 4 files changed, 35 insertions(+), 46 deletions(-) delete mode 100644 osu.Game/Graphics/StreamColour.cs diff --git a/osu.Game/Graphics/StreamColour.cs b/osu.Game/Graphics/StreamColour.cs deleted file mode 100644 index b7740c3be0..0000000000 --- a/osu.Game/Graphics/StreamColour.cs +++ /dev/null @@ -1,43 +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.Colour; -using System.Collections.Generic; -using osuTK.Graphics; - -namespace osu.Game.Graphics -{ - public class StreamColour - { - public static readonly Color4 STABLE = new Color4(102, 204, 255, 255); - public static readonly Color4 STABLEFALLBACK = new Color4(34, 153, 187, 255); - public static readonly Color4 BETA = new Color4(255, 221, 85, 255); - public static readonly Color4 CUTTINGEDGE = new Color4(238, 170, 0, 255); - public static readonly Color4 LAZER = new Color4(237, 18, 33, 255); - public static readonly Color4 WEB = new Color4(136, 102, 238, 255); - - private static readonly Dictionary colours = new Dictionary - { - { "stable40", STABLE }, - { "Stable", STABLE }, - { "stable", STABLEFALLBACK }, - { "Stable Fallback", STABLEFALLBACK }, - { "beta40", BETA }, - { "Beta", BETA }, - { "cuttingedge", CUTTINGEDGE }, - { "Cutting Edge", CUTTINGEDGE }, - { "lazer", LAZER }, - { "Lazer", LAZER }, - { "web", WEB }, - }; - - public static ColourInfo FromStreamName(string name) - { - if (!string.IsNullOrEmpty(name)) - if (colours.TryGetValue(name, out ColourInfo colour)) - return colour; - - return new Color4(0, 0, 0, 255); - } - } -} diff --git a/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs index 25f1a413d6..4c65b562dd 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs @@ -3,6 +3,8 @@ using System; using Newtonsoft.Json; +using osu.Framework.Graphics.Colour; +using osuTK.Graphics; namespace osu.Game.Online.API.Requests.Responses { @@ -30,5 +32,35 @@ namespace osu.Game.Online.API.Requests.Responses return Id == other.Id; } + + public ColourInfo Colour + { + get + { + switch (Name) + { + case "stable40": + return new Color4(102, 204, 255, 255); + + case "stable": + return new Color4(34, 153, 187, 255); + + case "beta40": + return new Color4(255, 221, 85, 255); + + case "cuttingedge": + return new Color4(238, 170, 0, 255); + + case "lazer": + return new Color4(237, 18, 33, 255); + + case "web": + return new Color4(136, 102, 238, 255); + + default: + return new Color4(0, 0, 0, 255); + } + } + } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 9f3da7eade..52186ec37c 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays.Changelog { Text = build.DisplayVersion, Font = OsuFont.GetFont(weight: FontWeight.Light, size: 24), - Colour = StreamColour.FromStreamName(build.UpdateStream.Name), + Colour = build.UpdateStream.Colour, }, } }, @@ -156,7 +156,7 @@ namespace osu.Game.Overlays.Changelog { Text = build.DisplayVersion, Font = OsuFont.GetFont(weight: FontWeight.Light, size: 19), - Colour = StreamColour.FromStreamName(build.UpdateStream.Name), + Colour = build.UpdateStream.Colour, }, }, } diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 2be6aba926..61bdf9f537 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -73,7 +73,7 @@ namespace osu.Game.Overlays.Changelog lineBadge = new LineBadge(false) { Anchor = Anchor.TopCentre, - Colour = StreamColour.FromStreamName(stream.Name), + Colour = stream.Colour, UncollapsedSize = 4, CollapsedSize = 2, }, From 9bc3aa3d467677a7516e41041edb1fbee024a4b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 May 2019 19:15:25 +0900 Subject: [PATCH 0877/5608] Move new classes for now --- .../UserInterface => Overlays/Changelog/Components}/LineBadge.cs | 0 .../Changelog/Components}/TooltipIconButton.cs | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename osu.Game/{Graphics/UserInterface => Overlays/Changelog/Components}/LineBadge.cs (100%) rename osu.Game/{Graphics/UserInterface => Overlays/Changelog/Components}/TooltipIconButton.cs (100%) diff --git a/osu.Game/Graphics/UserInterface/LineBadge.cs b/osu.Game/Overlays/Changelog/Components/LineBadge.cs similarity index 100% rename from osu.Game/Graphics/UserInterface/LineBadge.cs rename to osu.Game/Overlays/Changelog/Components/LineBadge.cs diff --git a/osu.Game/Graphics/UserInterface/TooltipIconButton.cs b/osu.Game/Overlays/Changelog/Components/TooltipIconButton.cs similarity index 100% rename from osu.Game/Graphics/UserInterface/TooltipIconButton.cs rename to osu.Game/Overlays/Changelog/Components/TooltipIconButton.cs From 2d56413e3509401ede5fb916ef57adf220cff84c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 May 2019 19:15:39 +0900 Subject: [PATCH 0878/5608] Update namespaces --- osu.Game.Tests/Visual/UserInterface/TestSceneLineBadge.cs | 2 +- osu.Game/Overlays/Changelog/ChangelogContentGroup.cs | 2 +- osu.Game/Overlays/Changelog/Components/LineBadge.cs | 2 +- osu.Game/Overlays/Changelog/Components/TooltipIconButton.cs | 6 +++--- osu.Game/Overlays/Changelog/Header/Breadcrumb.cs | 2 +- osu.Game/Overlays/Changelog/StreamBadge.cs | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLineBadge.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLineBadge.cs index 9f80cd40cf..14e7b45ee6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLineBadge.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLineBadge.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Changelog.Components; using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs index 52186ec37c..44c2c4cf9c 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs @@ -6,11 +6,11 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; using System; using System.Collections.Generic; using System.Text.RegularExpressions; +using osu.Game.Overlays.Changelog.Components; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Overlays/Changelog/Components/LineBadge.cs b/osu.Game/Overlays/Changelog/Components/LineBadge.cs index fc87acab0a..84cd712eef 100644 --- a/osu.Game/Overlays/Changelog/Components/LineBadge.cs +++ b/osu.Game/Overlays/Changelog/Components/LineBadge.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; -namespace osu.Game.Graphics.UserInterface +namespace osu.Game.Overlays.Changelog.Components { /// /// A simple rounded expandable line. Set its diff --git a/osu.Game/Overlays/Changelog/Components/TooltipIconButton.cs b/osu.Game/Overlays/Changelog/Components/TooltipIconButton.cs index 7287794f89..5721481685 100644 --- a/osu.Game/Overlays/Changelog/Components/TooltipIconButton.cs +++ b/osu.Game/Overlays/Changelog/Components/TooltipIconButton.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -8,12 +9,11 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; -using System; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; using osuTK; -namespace osu.Game.Graphics.UserInterface +namespace osu.Game.Overlays.Changelog.Components { /// /// An icon with an action upon click that can be disabled. diff --git a/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs b/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs index ae902043e3..c9b1430b5d 100644 --- a/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs +++ b/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs @@ -9,9 +9,9 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; -using osu.Game.Graphics.UserInterface; using System; using osu.Game.Graphics; +using osu.Game.Overlays.Changelog.Components; namespace osu.Game.Overlays.Changelog.Header { diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index 61bdf9f537..ce2ae8baf6 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -9,9 +9,9 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; using System; +using osu.Game.Overlays.Changelog.Components; using osuTK.Graphics; namespace osu.Game.Overlays.Changelog From ccbf3ff81209ffcaa637390d4486faf794739411 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 May 2019 22:35:23 +0900 Subject: [PATCH 0879/5608] Update framework --- .../Visual/Gameplay/TestScenePlayerReferenceLeaking.cs | 8 ++++++-- osu.Game/osu.Game.csproj | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs index d941ad54c0..c75fb2567b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs @@ -24,7 +24,9 @@ namespace osu.Game.Tests.Visual.Gameplay GC.WaitForPendingFinalizers(); int count = 0; - workingWeakReferences.ForEachAlive(_ => count++); + foreach (var unused in workingWeakReferences) + count++; + return count == 1; }); @@ -34,7 +36,9 @@ namespace osu.Game.Tests.Visual.Gameplay GC.WaitForPendingFinalizers(); int count = 0; - playerWeakReferences.ForEachAlive(_ => count++); + foreach (var unused in playerWeakReferences) + count++; + return count == 1; }); } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 66d298f8c1..fcfaf71d6a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + From a538c94feddce714e266403df7ab881194551ff8 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 17 May 2019 21:40:46 +0300 Subject: [PATCH 0880/5608] Update NuGet packages --- .../osu.Game.Rulesets.Catch.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Mania.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Osu.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Taiko.Tests.csproj | 4 ++-- osu.Game.Tests/osu.Game.Tests.csproj | 4 ++-- osu.Game/osu.Game.csproj | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 3f8b3bf086..265ecb7688 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -2,8 +2,8 @@ - - + + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index fd17285a38..dbade6ff8d 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -2,8 +2,8 @@ - - + + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 8c31db9a7d..a99a93c3e9 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -2,8 +2,8 @@ - - + + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 72ce6c947b..216cc0222f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -2,8 +2,8 @@ - - + + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 938e1ae0f8..11d70ee7be 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -3,8 +3,8 @@ - - + + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 66d298f8c1..7c005980c6 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -17,7 +17,7 @@ - + From 9106200c65edde6363e0542b2b6f79634936980d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 May 2019 12:08:22 +0900 Subject: [PATCH 0881/5608] Bump framework version --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index fcfaf71d6a..0cff6117d8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index ccec475d98..d947d0dfb9 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 5e499cf55d1f2ea5378b939f1a0c96c221535b54 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 May 2019 12:45:06 +0900 Subject: [PATCH 0882/5608] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index bf76fbcc94..e18f4b8771 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + From d407981ae4f065cda08b1c95eff155ef71c22145 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 May 2019 12:58:13 +0900 Subject: [PATCH 0883/5608] Increase fastlane processing interval This seems to be getting longer as we go. May be related to having many versions released under one testflight build? --- fastlane/Fastfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 3f64bcdf19..48c16caf0f 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -35,7 +35,7 @@ platform :ios do changelog.gsub!('$BUILD_ID', options[:build]) pilot( - wait_processing_interval: 900, + wait_processing_interval: 1800, changelog: changelog, ipa: './osu.iOS/bin/iPhone/Release/osu.iOS.ipa' ) From bc462532993d2abd5e7c071c1d8ba98d50061231 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 May 2019 20:18:07 +0900 Subject: [PATCH 0884/5608] Update test case naming --- osu.Game.Tournament.Tests/LadderTestCase.cs | 2 +- osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs | 2 +- osu.Game.Tournament.Tests/TestCaseGameplay.cs | 2 +- osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs | 2 +- osu.Game.Tournament.Tests/TestCaseMatchPairings.cs | 2 +- osu.Game.Tournament.Tests/TestCaseSceneManager.cs | 2 +- osu.Game.Tournament.Tests/TestCaseSchedule.cs | 2 +- osu.Game.Tournament.Tests/TestCaseShowcase.cs | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tournament.Tests/LadderTestCase.cs b/osu.Game.Tournament.Tests/LadderTestCase.cs index fc827150bd..450626fd43 100644 --- a/osu.Game.Tournament.Tests/LadderTestCase.cs +++ b/osu.Game.Tournament.Tests/LadderTestCase.cs @@ -6,7 +6,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tournament.Tests { - public class LadderTestCase : OsuTestCase + public class LadderTestCase : OsuTestScene { [Resolved] protected LadderInfo Ladder { get; private set; } diff --git a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs index 0a23b1e82f..6ebdcc511b 100644 --- a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs +++ b/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs @@ -15,7 +15,7 @@ using osu.Game.Tournament.Components; namespace osu.Game.Tournament.Tests { - public class TestCaseBeatmapPanel : OsuTestCase + public class TestCaseBeatmapPanel : OsuTestScene { [Resolved] private IAPIProvider api { get; set; } diff --git a/osu.Game.Tournament.Tests/TestCaseGameplay.cs b/osu.Game.Tournament.Tests/TestCaseGameplay.cs index 8e435de5e6..c881f09cb9 100644 --- a/osu.Game.Tournament.Tests/TestCaseGameplay.cs +++ b/osu.Game.Tournament.Tests/TestCaseGameplay.cs @@ -9,7 +9,7 @@ using osu.Game.Tournament.Screens.Gameplay; namespace osu.Game.Tournament.Tests { - public class TestCaseGameplay : OsuTestCase + public class TestCaseGameplay : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs b/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs index 0c3c189cf5..cec6095598 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tournament.Tests { - public class TestCaseMatchChatDisplay : OsuTestCase + public class TestCaseMatchChatDisplay : OsuTestScene { private readonly Channel testChannel = new Channel(); diff --git a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs index 2dce0c6017..e7a329d35f 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs @@ -11,7 +11,7 @@ using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Tests { - public class TestCaseMatchPairings : OsuTestCase + public class TestCaseMatchPairings : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs index 97d2018e3d..7c1b794e16 100644 --- a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestCaseSceneManager.cs @@ -8,7 +8,7 @@ using osu.Game.Tournament.Screens; namespace osu.Game.Tournament.Tests { - public class TestCaseSceneManager : OsuTestCase + public class TestCaseSceneManager : OsuTestScene { [BackgroundDependencyLoader] private void load(Storage storage) diff --git a/osu.Game.Tournament.Tests/TestCaseSchedule.cs b/osu.Game.Tournament.Tests/TestCaseSchedule.cs index f9dc447077..b5a80d7bee 100644 --- a/osu.Game.Tournament.Tests/TestCaseSchedule.cs +++ b/osu.Game.Tournament.Tests/TestCaseSchedule.cs @@ -9,7 +9,7 @@ using osu.Game.Tournament.Screens.Schedule; namespace osu.Game.Tournament.Tests { - public class TestCaseSchedule : OsuTestCase + public class TestCaseSchedule : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tournament.Tests/TestCaseShowcase.cs b/osu.Game.Tournament.Tests/TestCaseShowcase.cs index 51877cdfb6..c0816e3594 100644 --- a/osu.Game.Tournament.Tests/TestCaseShowcase.cs +++ b/osu.Game.Tournament.Tests/TestCaseShowcase.cs @@ -9,7 +9,7 @@ using osu.Game.Tournament.Screens.Showcase; namespace osu.Game.Tournament.Tests { - public class TestCaseShowcase : OsuTestCase + public class TestCaseShowcase : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 4a65846d68..b76fc261f0 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -6,7 +6,7 @@ - + From 30e36627cf37f1e8784764df7857dccce129533d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 May 2019 21:37:46 +0900 Subject: [PATCH 0885/5608] Remove redundant code --- .../Screens/Gameplay/Components/MatchHeader.cs | 2 +- .../Screens/Gameplay/Components/MatchScoreDisplay.cs | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index 51467842eb..10c1c006cf 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components public class MatchHeader : Container { [BackgroundDependencyLoader] - private void load(LadderInfo ladder) + private void load() { RelativeSizeAxes = Axes.X; Height = 95; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs index f8b887b952..62a785398f 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.IPC; -using osu.Game.Tournament.Screens.Ladder.Components; using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Gameplay.Components @@ -22,8 +21,6 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components private const float bar_height = 20; - private readonly Bindable currentMatch = new Bindable(); - private readonly BindableInt score1 = new BindableInt(); private readonly BindableInt score2 = new BindableInt(); @@ -78,8 +75,6 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components [BackgroundDependencyLoader] private void load(LadderInfo ladder, MatchIPCInfo ipc) { - currentMatch.BindTo(ladder.CurrentMatch); - score1.BindValueChanged(_ => updateScores()); score1.BindTo(ipc.Score1); From 069245e7ab31685389cb3e591c4319136aaa2d58 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 May 2019 21:40:02 +0900 Subject: [PATCH 0886/5608] Update header colour to match TWC --- osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index 10c1c006cf..22aa6995cf 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -210,7 +210,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components { new Box { - Colour = new Color4(95, 41, 60, 255), + Colour = new Color4(47, 71, 67, 255), RelativeSizeAxes = Axes.Both, }, new OsuSpriteText From f81c66db63ce5081b545da7e7f6bbbf53beb82b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 May 2019 21:46:03 +0900 Subject: [PATCH 0887/5608] Hotfix to fix chat scrolling to end --- osu.Game/Overlays/Chat/DrawableChannel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index aec78b962f..6c30b8cc36 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -81,7 +81,7 @@ namespace osu.Game.Overlays.Chat ChatLineFlow.AddRange(displayMessages.Select(CreateChatLine)); - if (scroll.IsScrolledToEnd(10) || !ChatLineFlow.Children.Any() || newMessages.Any(m => m is LocalMessage)) + //if (scroll.IsScrolledToEnd(10) || !ChatLineFlow.Children.Any() || newMessages.Any(m => m is LocalMessage)) scrollToEnd(); var staleMessages = ChatLineFlow.Children.Where(c => c.LifetimeEnd == double.MaxValue).ToArray(); From 3fa1545ea445f7fe8aca58153e03a839d2a74091 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 May 2019 02:09:08 +0900 Subject: [PATCH 0888/5608] Huge refactor pass focusing on ChangelogContent --- .../Online/TestSceneChangelogOverlay.cs | 2 +- .../Graphics/Containers/OsuHoverContainer.cs | 3 +- .../BeatmapSet/Scores/TopScoreUserSection.cs | 2 +- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 176 +++++++++-- .../Changelog/ChangelogContentGroup.cs | 280 ------------------ .../Overlays/Changelog/ChangelogListing.cs | 32 +- .../Changelog/ChangelogSingleBuild.cs | 118 ++++++++ .../Overlays/Changelog/Header/Breadcrumb.cs | 3 +- osu.Game/Overlays/Changelog/StreamBadge.cs | 7 +- osu.Game/Overlays/ChangelogOverlay.cs | 2 +- 10 files changed, 294 insertions(+), 331 deletions(-) delete mode 100644 osu.Game/Overlays/Changelog/ChangelogContentGroup.cs create mode 100644 osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index e1cb6e6a85..4ac5514019 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -23,8 +23,8 @@ namespace osu.Game.Tests.Visual.Online typeof(ChangelogHeader), typeof(ChangelogContent), typeof(ChangelogListing), + typeof(ChangelogSingleBuild), typeof(ChangelogBuild), - typeof(ChangelogContentGroup), typeof(Breadcrumb), typeof(BreadcrumbListing), typeof(BreadcrumbRelease), diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index d5ae7cba57..b1fe1e81f1 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -22,7 +22,8 @@ namespace osu.Game.Graphics.Containers protected override bool OnHover(HoverEvent e) { - EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); + if (Action != null) + EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); return base.OnHover(e); } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index e70bf4c572..89da0fc254 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -83,7 +83,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, }, - date = new SpriteText + date = new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 0af117c11e..09706a419e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -1,50 +1,168 @@ -// 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.Threading; -using System.Threading.Tasks; -using osu.Framework.Allocation; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using osu.Game.Graphics.Sprites; +using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { - public class ChangelogBuild : ChangelogContent + public class ChangelogBuild : FillFlowContainer { - private APIChangelogBuild changelogBuild; + public Action SelectBuild; - public ChangelogBuild(APIChangelogBuild changelogBuild) + protected readonly APIChangelogBuild Build; + + public readonly FillFlowContainer ChangelogEntries; + + public ChangelogBuild(APIChangelogBuild build) { - this.changelogBuild = changelogBuild; - } + Build = build; - [BackgroundDependencyLoader] - private void load(CancellationToken? cancellation, IAPIProvider api) - { - var req = new GetChangelogBuildRequest(changelogBuild.UpdateStream.Name, changelogBuild.Version); - bool complete = false; + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Direction = FillDirection.Vertical; + Padding = new MarginPadding { Horizontal = 70 }; - req.Success += res => + Children = new Drawable[] { - changelogBuild = res; - complete = true; + CreateHeader(), + ChangelogEntries = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + }, }; - req.Failure += _ => complete = true; + var categories = new SortedDictionary>(); - api.Queue(req); + // sort entries by category + foreach (APIChangelogEntry entry in build.ChangelogEntries) + { + if (!categories.ContainsKey(entry.Category)) + categories.Add(entry.Category, new List { entry }); + else + categories[entry.Category].Add(entry); + } - while (!complete && cancellation?.IsCancellationRequested != true) - Task.Delay(1); + foreach (KeyValuePair> category in categories) + { + ChangelogEntries.Add(new OsuSpriteText + { + Text = category.Key, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 24), + Margin = new MarginPadding { Top = 35, Bottom = 15 }, + }); - var changelogContentGroup = new ChangelogContentGroup(changelogBuild); - changelogContentGroup.GenerateText(changelogBuild.ChangelogEntries); - changelogContentGroup.UpdateChevronTooltips(changelogBuild.Versions.Previous?.DisplayVersion, - changelogBuild.Versions.Next?.DisplayVersion); - changelogContentGroup.BuildSelected += SelectBuild; + foreach (APIChangelogEntry entry in category.Value) + { + LinkFlowContainer title = new LinkFlowContainer + { + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Vertical = 5 }, + }; - Add(changelogContentGroup); + title.AddIcon(FontAwesome.Solid.Check, t => + { + t.Font = OsuFont.GetFont(size: 12); + t.Padding = new MarginPadding { Left = -17, Right = 5 }; + }); + + title.AddText(entry.Title, t => { t.Font = OsuFont.GetFont(size: 18); }); + + if (!string.IsNullOrEmpty(entry.Repository)) + { + title.AddText(" (", t => t.Font = OsuFont.GetFont(size: 18)); + title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", + entry.GithubUrl, Online.Chat.LinkAction.External, null, + null, t => { t.Font = OsuFont.GetFont(size: 18); }); + title.AddText(")", t => t.Font = OsuFont.GetFont(size: 18)); + } + + title.AddText(" by ", t => t.Font = OsuFont.GetFont(size: 14)); + + if (entry.GithubUser.GithubUrl != null) + title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, + Online.Chat.LinkAction.External, null, null, + t => t.Font = OsuFont.GetFont(size: 14)); + else + title.AddText(entry.GithubUser.DisplayName, t => t.Font = OsuFont.GetFont(size: 12)); + + ChangelogEntries.Add(title); + + if (!string.IsNullOrEmpty(entry.MessageHtml)) + { + TextFlowContainer messageContainer = new TextFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + }; + + // todo: use markdown parsing once API returns markdown + messageContainer.AddText(Regex.Replace(entry.MessageHtml, @"<(.|\n)*?>", string.Empty), t => + { + t.Font = OsuFont.GetFont(size: 12); + t.Colour = new Color4(235, 184, 254, 255); + }); + + ChangelogEntries.Add(messageContainer); + } + } + } } + + protected virtual FillFlowContainer CreateHeader() => new FillFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding { Top = 20 }, + Children = new Drawable[] + { + new OsuHoverContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Action = () => SelectBuild?.Invoke(Build), + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Horizontal = 40 }, + Children = new[] + { + new OsuSpriteText + { + Text = Build.UpdateStream.DisplayName, + Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 19), + }, + new OsuSpriteText + { + Text = " ", + Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 19), + }, + new OsuSpriteText + { + Text = Build.DisplayVersion, + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 19), + Colour = Build.UpdateStream.Colour, + }, + } + } + }, + } + }; } } diff --git a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs b/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs deleted file mode 100644 index 44c2c4cf9c..0000000000 --- a/osu.Game/Overlays/Changelog/ChangelogContentGroup.cs +++ /dev/null @@ -1,280 +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.Sprites; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Online.API.Requests.Responses; -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using osu.Game.Overlays.Changelog.Components; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Overlays.Changelog -{ - public class ChangelogContentGroup : FillFlowContainer - { - private readonly TooltipIconButton chevronPrevious, chevronNext; - - private readonly SortedDictionary> categories = - new SortedDictionary>(); - - public event Action BuildSelected; - - public readonly FillFlowContainer ChangelogEntries; - - public ChangelogContentGroup(APIChangelogBuild build) - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Direction = FillDirection.Vertical; - Padding = new MarginPadding { Horizontal = 70 }; - Children = new Drawable[] - { - new FillFlowContainer - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Margin = new MarginPadding { Top = 20 }, - Children = new Drawable[] - { - chevronPrevious = new TooltipIconButton - { - IsEnabled = false, - Icon = FontAwesome.Solid.ChevronLeft, - Size = new Vector2(24), - Action = () => - { - BuildSelected?.Invoke(build.Versions.Previous); - chevronPrevious.IsEnabled = false; - }, - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Horizontal = 40 }, - Children = new[] - { - new SpriteText - { - Text = build.UpdateStream.DisplayName, - Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 24), - }, - new SpriteText - { - Text = " ", - Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 24), - }, - new SpriteText - { - Text = build.DisplayVersion, - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 24), - Colour = build.UpdateStream.Colour, - }, - } - }, - chevronNext = new TooltipIconButton - { - IsEnabled = false, - Icon = FontAwesome.Solid.ChevronRight, - Size = new Vector2(24), - Action = () => - { - BuildSelected?.Invoke(build.Versions.Next); - chevronNext.IsEnabled = false; - }, - }, - } - }, - new SpriteText - { - // do we need .ToUniversalTime() here? - // also, this should be a temporary solution to weekdays in >localized< date strings - Text = build.CreatedAt.Date.ToLongDateString().Replace(build.CreatedAt.ToString("dddd") + ", ", ""), - Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 14), - Colour = OsuColour.FromHex(@"FD5"), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Margin = new MarginPadding { Top = 5 }, - }, - ChangelogEntries = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - }, - }; - } - - public ChangelogContentGroup(APIChangelogBuild build, bool newDate) - { - OsuHoverContainer clickableBuildText; - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Direction = FillDirection.Vertical; - Padding = new MarginPadding { Horizontal = 70 }; - Children = new Drawable[] - { - new SpriteText - { - // do we need .ToUniversalTime() here? - // also, this should be a temporary solution to weekdays in >localized< date strings - Text = build.CreatedAt.Date.ToLongDateString().Replace(build.CreatedAt.ToString("dddd") + ", ", ""), - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 24), - Colour = OsuColour.FromHex(@"FD5"), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Margin = new MarginPadding { Top = 20 }, - Alpha = newDate ? 1 : 0, - }, - clickableBuildText = new OsuHoverContainer - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Top = 20 }, - Action = () => BuildSelected?.Invoke(build), - Child = new FillFlowContainer - { - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5), - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - new SpriteText - { - Text = build.UpdateStream.DisplayName, - Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 19), - }, - new SpriteText - { - Text = build.DisplayVersion, - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 19), - Colour = build.UpdateStream.Colour, - }, - }, - } - }, - ChangelogEntries = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - }, - }; - - // we may not want double clicks, - // can be clicked again only after a delay - clickableBuildText.Action += () => - { - clickableBuildText.Action = null; - clickableBuildText.FadeTo(0.5f, 500); - Scheduler.AddDelayed(() => - { - clickableBuildText.Action = () => BuildSelected?.Invoke(build); - clickableBuildText.FadeIn(500); - }, 2000); - }; - } - - public void UpdateChevronTooltips(string previousVersion, string nextVersion) - { - if (!string.IsNullOrEmpty(previousVersion)) - { - chevronPrevious.TooltipText = previousVersion; - chevronPrevious.IsEnabled = true; - } - - if (!string.IsNullOrEmpty(nextVersion)) - { - chevronNext.TooltipText = nextVersion; - chevronNext.IsEnabled = true; - } - } - - public void GenerateText(List changelogEntries) - { - // sort entries by category - foreach (APIChangelogEntry entry in changelogEntries) - { - if (!categories.ContainsKey(entry.Category)) - categories.Add(entry.Category, new List { entry }); - else - categories[entry.Category].Add(entry); - } - - foreach (KeyValuePair> category in categories) - { - ChangelogEntries.Add(new SpriteText - { - Text = category.Key, - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 24), - Margin = new MarginPadding { Top = 35, Bottom = 15 }, - }); - - foreach (APIChangelogEntry entry in category.Value) - { - LinkFlowContainer title = new LinkFlowContainer - { - Direction = FillDirection.Full, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Vertical = 5 }, - }; - - title.AddIcon(FontAwesome.Solid.Check, t => - { - t.Font = OsuFont.GetFont(size: 12); - t.Padding = new MarginPadding { Left = -17, Right = 5 }; - }); - - title.AddText(entry.Title, t => { t.Font = OsuFont.GetFont(size: 18); }); - - if (!string.IsNullOrEmpty(entry.Repository)) - { - title.AddText(" (", t => t.Font = OsuFont.GetFont(size: 18)); - title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", - entry.GithubUrl, Online.Chat.LinkAction.External, null, - null, t => { t.Font = OsuFont.GetFont(size: 18); }); - title.AddText(")", t => t.Font = OsuFont.GetFont(size: 18)); - } - - title.AddText(" by ", t => t.Font = OsuFont.GetFont(size: 14)); - - if (entry.GithubUser.GithubUrl != null) - title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, - Online.Chat.LinkAction.External, null, null, - t => t.Font = OsuFont.GetFont(size: 14)); - else - title.AddText(entry.GithubUser.DisplayName, t => t.Font = OsuFont.GetFont(size: 12)); - - ChangelogEntries.Add(title); - - if (!string.IsNullOrEmpty(entry.MessageHtml)) - { - TextFlowContainer messageContainer = new TextFlowContainer - { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - }; - - // todo: use markdown parsing once API returns markdown - messageContainer.AddText(Regex.Replace(entry.MessageHtml, @"<(.|\n)*?>", string.Empty), t => - { - t.Font = OsuFont.GetFont(size: 12); - t.Colour = new Color4(235, 184, 254, 255); - }); - - ChangelogEntries.Add(messageContainer); - } - } - } - } - } -} diff --git a/osu.Game/Overlays/Changelog/ChangelogListing.cs b/osu.Game/Overlays/Changelog/ChangelogListing.cs index 8e615d1dc9..907c122232 100644 --- a/osu.Game/Overlays/Changelog/ChangelogListing.cs +++ b/osu.Game/Overlays/Changelog/ChangelogListing.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osuTK.Graphics; @@ -23,10 +25,7 @@ namespace osu.Game.Overlays.Changelog [BackgroundDependencyLoader] private void load() { - DateTime currentDate = new DateTime(); - Clear(); - - ChangelogContentGroup changelogContentGroup = null; + DateTime currentDate = DateTime.MinValue; foreach (APIChangelogBuild build in entries) { @@ -43,27 +42,32 @@ namespace osu.Game.Overlays.Changelog }); } - changelogContentGroup = new ChangelogContentGroup(build, true); - changelogContentGroup.BuildSelected += SelectBuild; - changelogContentGroup.GenerateText(build.ChangelogEntries); - Add(changelogContentGroup); + Add(new OsuSpriteText + { + // do we need .ToUniversalTime() here? + // also, this should be a temporary solution to weekdays in >localized< date strings + Text = build.CreatedAt.Date.ToLongDateString().Replace(build.CreatedAt.ToString("dddd") + ", ", ""), + Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 24), + Colour = OsuColour.FromHex(@"FD5"), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Margin = new MarginPadding { Top = 15 }, + }); + currentDate = build.CreatedAt.Date; } else { - changelogContentGroup?.Add(new Box + Add(new Box { RelativeSizeAxes = Axes.X, Height = 1, Colour = new Color4(32, 24, 35, 255), Margin = new MarginPadding { Top = 30 }, }); - - changelogContentGroup = new ChangelogContentGroup(build, false); - changelogContentGroup.BuildSelected += SelectBuild; - changelogContentGroup.GenerateText(build.ChangelogEntries); - Add(changelogContentGroup); } + + Add(new ChangelogBuild(build) { SelectBuild = SelectBuild }); } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs new file mode 100644 index 0000000000..af4603fddf --- /dev/null +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -0,0 +1,118 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays.Changelog.Components; +using osuTK; + +namespace osu.Game.Overlays.Changelog +{ + public class ChangelogSingleBuild : ChangelogContent + { + private APIChangelogBuild build; + + public ChangelogSingleBuild(APIChangelogBuild build) + { + this.build = build; + } + + [BackgroundDependencyLoader] + private void load(CancellationToken? cancellation, IAPIProvider api) + { + var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); + bool complete = false; + + req.Success += res => + { + build = res; + complete = true; + }; + + req.Failure += _ => complete = true; + + api.Queue(req); + + while (!complete && cancellation?.IsCancellationRequested != true) + Task.Delay(1); + + Children = new Drawable[] + { + new ChangelogBuildWithNavigation(build) { SelectBuild = SelectBuild }, + }; + } + + public class ChangelogBuildWithNavigation : ChangelogBuild + { + public ChangelogBuildWithNavigation(APIChangelogBuild build) + : base(build) + { + } + + protected override FillFlowContainer CreateHeader() + { + var fill = base.CreateHeader(); + + foreach (var existing in fill.Children.OfType()) + { + existing.Scale = new Vector2(1.25f); + existing.Action = null; + + existing.Add(new OsuSpriteText + { + // do we need .ToUniversalTime() here? + // also, this should be a temporary solution to weekdays in >localized< date strings + Text = Build.CreatedAt.Date.ToLongDateString().Replace(Build.CreatedAt.ToString("dddd") + ", ", ""), + Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 14), + Colour = OsuColour.FromHex(@"FD5"), + Anchor = Anchor.BottomCentre, + Origin = Anchor.TopCentre, + Margin = new MarginPadding { Top = 5 }, + }); + } + + TooltipIconButton left, right; + + fill.AddRange(new[] + { + left = new TooltipIconButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Icon = FontAwesome.Solid.ChevronLeft, + Size = new Vector2(24), + TooltipText = Build.Versions?.Previous?.DisplayVersion, + IsEnabled = Build.Versions?.Previous != null, + Action = () => { SelectBuild?.Invoke(Build.Versions.Previous); }, + }, + right = new TooltipIconButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Icon = FontAwesome.Solid.ChevronRight, + Size = new Vector2(24), + TooltipText = Build.Versions?.Next?.DisplayVersion, + IsEnabled = Build.Versions?.Next != null, + Action = () => { SelectBuild?.Invoke(Build.Versions.Next); }, + }, + }); + + fill.SetLayoutPosition(left, -1); + fill.SetLayoutPosition(right, 1); + + return fill; + } + } + } +} diff --git a/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs b/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs index c9b1430b5d..f960111a53 100644 --- a/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs +++ b/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using System; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Changelog.Components; namespace osu.Game.Overlays.Changelog.Header @@ -33,7 +34,7 @@ namespace osu.Game.Overlays.Changelog.Header RelativeSizeAxes = Axes.Y; Children = new Drawable[] { - Text = new SpriteText + Text = new OsuSpriteText { Font = OsuFont.GetFont(size: 16), Text = displayText, diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index ce2ae8baf6..bdddc1f968 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -11,6 +11,7 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; using System; +using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Changelog.Components; using osuTK.Graphics; @@ -51,18 +52,18 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Vertical, Children = new[] { - new SpriteText + new OsuSpriteText { Text = stream.DisplayName, Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12), Margin = new MarginPadding { Top = 6 }, }, - new SpriteText + new OsuSpriteText { Text = stream.LatestBuild.DisplayVersion, Font = OsuFont.GetFont(weight: FontWeight.Light, size: 16), }, - new SpriteText + new OsuSpriteText { Text = stream.LatestBuild.Users > 0 ? $"{stream.LatestBuild.Users:N0} users online" : null, Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 10), diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index f4c0338436..22c362d49d 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -138,7 +138,7 @@ namespace osu.Game.Overlays header.ShowBuild(build.UpdateStream.DisplayName, build.DisplayVersion); badges.Current.Value = build.UpdateStream; - loadContent(new ChangelogBuild(build)); + loadContent(new ChangelogSingleBuild(build)); } private bool initialFetchPerformed; From dae315ec0a458fd7390f7b97d6439c8445da5709 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 May 2019 11:28:24 +0900 Subject: [PATCH 0889/5608] Move TooltipText to OsuClickableContainer --- osu.Game/Graphics/Containers/OsuClickableContainer.cs | 5 ++++- osu.Game/Online/Chat/DrawableLinkCompiler.cs | 5 +---- osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 7 ------- .../Profile/Header/Components/ProfileHeaderButton.cs | 5 +---- .../Overlays/Profile/Sections/BeatmapMetadataContainer.cs | 5 +---- osu.Game/Users/Avatar.cs | 5 ++--- 6 files changed, 9 insertions(+), 23 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuClickableContainer.cs b/osu.Game/Graphics/Containers/OsuClickableContainer.cs index e4d30cebb7..6dbe340efb 100644 --- a/osu.Game/Graphics/Containers/OsuClickableContainer.cs +++ b/osu.Game/Graphics/Containers/OsuClickableContainer.cs @@ -4,11 +4,12 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.Containers { - public class OsuClickableContainer : ClickableContainer + public class OsuClickableContainer : ClickableContainer, IHasTooltip { private readonly HoverSampleSet sampleSet; @@ -23,6 +24,8 @@ namespace osu.Game.Graphics.Containers this.sampleSet = sampleSet; } + public virtual string TooltipText { get; set; } + [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game/Online/Chat/DrawableLinkCompiler.cs b/osu.Game/Online/Chat/DrawableLinkCompiler.cs index d34ec8091c..d27a3fbffe 100644 --- a/osu.Game/Online/Chat/DrawableLinkCompiler.cs +++ b/osu.Game/Online/Chat/DrawableLinkCompiler.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics.Cursor; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -16,7 +15,7 @@ namespace osu.Game.Online.Chat /// /// An invisible drawable that brings multiple pieces together to form a consumable clickable link. /// - public class DrawableLinkCompiler : OsuHoverContainer, IHasTooltip + public class DrawableLinkCompiler : OsuHoverContainer { /// /// Each word part of a chat link (split for word-wrap support). @@ -40,8 +39,6 @@ namespace osu.Game.Online.Chat protected override IEnumerable EffectTargets => Parts; - public string TooltipText { get; set; } - private class LinkHoverSounds : HoverClickSounds { private readonly List parts; diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index abe954aa80..7331faa618 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -9,8 +9,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK; using osuTK.Graphics; -using osu.Game.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; @@ -129,10 +127,5 @@ namespace osu.Game.Overlays.BeatmapSet }; } } - - private class ClickableArea : OsuClickableContainer, IHasTooltip - { - public string TooltipText => @"View Profile"; - } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs index 1650f11523..ddcf011277 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -12,10 +11,8 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { - public abstract class ProfileHeaderButton : OsuHoverContainer, IHasTooltip + public abstract class ProfileHeaderButton : OsuHoverContainer { - public abstract string TooltipText { get; } - private readonly Box background; private readonly Container content; diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs index bb55816880..16326900f1 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -16,7 +15,7 @@ namespace osu.Game.Overlays.Profile.Sections /// /// Display artist/title/mapper information, commonly used as the left portion of a profile or score display row (see ). /// - public class BeatmapMetadataContainer : OsuHoverContainer, IHasTooltip + public class BeatmapMetadataContainer : OsuHoverContainer { private readonly BeatmapInfo beatmap; @@ -27,8 +26,6 @@ namespace osu.Game.Overlays.Profile.Sections TooltipText = $"{beatmap.Metadata.Artist} - {beatmap.Metadata.Title}"; } - public string TooltipText { get; } - [BackgroundDependencyLoader(true)] private void load(BeatmapSetOverlay beatmapSetOverlay) { diff --git a/osu.Game/Users/Avatar.cs b/osu.Game/Users/Avatar.cs index 3df5957ff9..8937f94768 100644 --- a/osu.Game/Users/Avatar.cs +++ b/osu.Game/Users/Avatar.cs @@ -6,7 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Events; @@ -72,9 +71,9 @@ namespace osu.Game.Users game?.ShowUser(user.Id); } - private class ClickableArea : OsuClickableContainer, IHasTooltip + private class ClickableArea : OsuClickableContainer { - public string TooltipText => Enabled.Value ? @"View Profile" : null; + public override string TooltipText => Enabled.Value ? @"View Profile" : null; protected override bool OnClick(ClickEvent e) { From 1c85fcbc81dca20cf9d72aa72e3dd5e0703a4d50 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 May 2019 11:28:34 +0900 Subject: [PATCH 0890/5608] Remove usage of TooltipIconButton completely --- .../Changelog/ChangelogSingleBuild.cs | 52 ++++++--- .../Changelog/Components/TooltipIconButton.cs | 100 ------------------ 2 files changed, 36 insertions(+), 116 deletions(-) delete mode 100644 osu.Game/Overlays/Changelog/Components/TooltipIconButton.cs diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index af4603fddf..50a7946ee7 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -1,20 +1,22 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Overlays.Changelog.Components; using osuTK; namespace osu.Game.Overlays.Changelog @@ -82,29 +84,19 @@ namespace osu.Game.Overlays.Changelog }); } - TooltipIconButton left, right; + NavigationIconButton left, right; fill.AddRange(new[] { - left = new TooltipIconButton + left = new NavigationIconButton(Build.Versions?.Previous) { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, Icon = FontAwesome.Solid.ChevronLeft, - Size = new Vector2(24), - TooltipText = Build.Versions?.Previous?.DisplayVersion, - IsEnabled = Build.Versions?.Previous != null, - Action = () => { SelectBuild?.Invoke(Build.Versions.Previous); }, + SelectBuild = b => SelectBuild(b) }, - right = new TooltipIconButton + right = new NavigationIconButton(Build.Versions?.Next) { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, Icon = FontAwesome.Solid.ChevronRight, - Size = new Vector2(24), - TooltipText = Build.Versions?.Next?.DisplayVersion, - IsEnabled = Build.Versions?.Next != null, - Action = () => { SelectBuild?.Invoke(Build.Versions.Next); }, + SelectBuild = b => SelectBuild(b) }, }); @@ -114,5 +106,33 @@ namespace osu.Game.Overlays.Changelog return fill; } } + + private class NavigationIconButton : IconButton + { + public Action SelectBuild; + + public NavigationIconButton(APIChangelogBuild build) + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + if (build == null) return; + + TooltipText = build.DisplayVersion; + + Action = () => + { + SelectBuild?.Invoke(build); + Enabled.Value = false; + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + HoverColour = colours.GreyVioletLight.Opacity(0.6f); + FlashColour = colours.GreyVioletLighter; + } + } } } diff --git a/osu.Game/Overlays/Changelog/Components/TooltipIconButton.cs b/osu.Game/Overlays/Changelog/Components/TooltipIconButton.cs deleted file mode 100644 index 5721481685..0000000000 --- a/osu.Game/Overlays/Changelog/Components/TooltipIconButton.cs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; -using osuTK; - -namespace osu.Game.Overlays.Changelog.Components -{ - /// - /// An icon with an action upon click that can be disabled. - /// - public class TooltipIconButton : Container, IHasTooltip - { - private readonly SpriteIcon icon; - private SampleChannel sampleHover; - private SampleChannel sampleClick; - - /// - /// The action to fire upon click if is set to true. - /// - public Action Action; - - private bool isEnabled; - - /// - /// If set to true, upon click the will execute. - /// - public bool IsEnabled - { - get => isEnabled; - set - { - isEnabled = value; - icon.FadeTo(value ? 1 : 0.5f, 250); - } - } - - public IconUsage Icon - { - get => icon.Icon; - set => icon.Icon = value; - } - - public TooltipIconButton() - { - isEnabled = true; - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - }, - icon = new SpriteIcon - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.8f), - } - }; - } - - protected override bool OnClick(ClickEvent e) - { - if (isEnabled) - { - sampleClick?.Play(); - Action?.Invoke(); - } - - return base.OnClick(e); - } - - protected override bool OnHover(HoverEvent e) - { - if (isEnabled) - sampleHover?.Play(); - return base.OnHover(e); - } - - [BackgroundDependencyLoader] - private void load(AudioManager audio) - { - sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); - sampleClick = audio.Sample.Get(@"UI/generic-select-soft"); - } - - public string TooltipText { get; set; } - } -} From 39e03ae7058f3bd18821fb23190bdd2900286ab2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 May 2019 11:58:47 +0900 Subject: [PATCH 0891/5608] Fix tests failing when not logged in --- osu.Game/Overlays/Changelog/ChangelogListing.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/Changelog/ChangelogListing.cs b/osu.Game/Overlays/Changelog/ChangelogListing.cs index 907c122232..ebfcf76738 100644 --- a/osu.Game/Overlays/Changelog/ChangelogListing.cs +++ b/osu.Game/Overlays/Changelog/ChangelogListing.cs @@ -27,6 +27,8 @@ namespace osu.Game.Overlays.Changelog { DateTime currentDate = DateTime.MinValue; + if (entries == null) return; + foreach (APIChangelogBuild build in entries) { if (build.CreatedAt.Date != currentDate) From d8ed402779e20483c2d32efed137f1ae20d68aed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 May 2019 14:47:46 +0900 Subject: [PATCH 0892/5608] Make use of ValueChanged.OldValue --- .../Components/TournamentBeatmapPanel.cs | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 8ab0dc2459..818d25d559 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; using osu.Framework.Allocation; @@ -146,10 +145,15 @@ namespace osu.Game.Tournament.Components private void matchChanged(ValueChangedEvent pairing) { + if (pairing.OldValue != null) + pairing.OldValue.PicksBans.CollectionChanged -= picksBansOnCollectionChanged; pairing.NewValue.PicksBans.CollectionChanged += picksBansOnCollectionChanged; updateState(); } + private void picksBansOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + => updateState(); + private BeatmapChoice choice; private void updateState() @@ -197,19 +201,5 @@ namespace osu.Game.Tournament.Components Alpha = 1; } } - - private void picksBansOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) - { - var list = (ObservableCollection)sender; - - if (sender != currentMatch.Value.PicksBans) - { - // todo: we need a last attribute in bindable valuechanged events badly. - list.CollectionChanged -= picksBansOnCollectionChanged; - return; - } - - updateState(); - } } } From 084c2252cbb34ff9f5793d3717eb066d3ea9376c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 May 2019 14:48:33 +0900 Subject: [PATCH 0893/5608] Use less DI where we already have access to LadderInfo --- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 4 ++-- osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 7e91ded848..0e3a9b0dfd 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -94,10 +94,10 @@ namespace osu.Game.Tournament.Screens.MapPool } [BackgroundDependencyLoader] - private void load(LadderInfo ladder, MatchIPCInfo ipc) + private void load(MatchIPCInfo ipc) { currentMatch.BindValueChanged(matchChanged); - currentMatch.BindTo(ladder.CurrentMatch); + currentMatch.BindTo(LadderInfo.CurrentMatch); ipc.Beatmap.BindValueChanged(beatmapChanged); } diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index d2ff632da0..7000d776f0 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro private readonly Bindable currentMatch = new Bindable(); [BackgroundDependencyLoader] - private void load(LadderInfo ladder, Storage storage) + private void load(Storage storage) { RelativeSizeAxes = Axes.Both; @@ -43,7 +43,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro }; currentMatch.BindValueChanged(matchChanged); - currentMatch.BindTo(ladder.CurrentMatch); + currentMatch.BindTo(LadderInfo.CurrentMatch); } private void matchChanged(ValueChangedEvent pairing) From 455301de2c1501433836411385bd1a82cda6220f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 May 2019 15:58:40 +0900 Subject: [PATCH 0894/5608] Use OsuColour for profile overlay --- osu.Game/Graphics/OsuColour.cs | 12 +----------- .../Overlays/Profile/Header/BottomHeaderContainer.cs | 4 ++-- .../Overlays/Profile/Header/CentreHeaderContainer.cs | 2 +- .../Profile/Header/Components/ExpandDetailsButton.cs | 4 ++-- .../Overlays/Profile/Header/Components/RankGraph.cs | 4 ++-- .../Profile/Header/Components/SupporterIcon.cs | 2 +- .../Overlays/Profile/Header/DetailHeaderContainer.cs | 2 +- .../Overlays/Profile/Header/MedalHeaderContainer.cs | 2 +- .../Overlays/Profile/Header/TopHeaderContainer.cs | 6 +++--- osu.Game/Overlays/Profile/ProfileHeader.cs | 4 ++-- 10 files changed, 16 insertions(+), 26 deletions(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index a73a8bcbc1..d337455176 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -77,7 +77,7 @@ namespace osu.Game.Graphics public readonly Color4 Seafoam = FromHex(@"05ffa2"); public readonly Color4 GreySeafoamLighter = FromHex(@"9ebab1"); - public readonly Color4 GreySeafoamLight = FromHex(@"4d7365"); + public readonly Color4 GreySeafoamLight = FromHex(@"4e7466"); public readonly Color4 GreySeafoam = FromHex(@"33413c"); public readonly Color4 GreySeafoamDark = FromHex(@"2c3532"); public readonly Color4 GreySeafoamDarker = FromHex(@"1e2422"); @@ -136,15 +136,5 @@ namespace osu.Game.Graphics public readonly Color4 ChatBlue = FromHex(@"17292e"); public readonly Color4 ContextMenuGray = FromHex(@"223034"); - - public readonly Color4 CommunityUserGreenLight = FromHex(@"deff87"); - public readonly Color4 CommunityUserGreen = FromHex(@"05ffa2"); - public readonly Color4 CommunityUserGreenDark = FromHex(@"a6cc00"); - public readonly Color4 CommunityUserGrayGreenLighter = FromHex(@"9ebab1"); - public readonly Color4 CommunityUserGrayGreenLight = FromHex(@"77998e"); - public readonly Color4 CommunityUserGrayGreen = FromHex(@"4e7466"); - public readonly Color4 CommunityUserGrayGreenDark = FromHex(@"33413c"); - public readonly Color4 CommunityUserGrayGreenDarker = FromHex(@"2c3532"); - public readonly Color4 CommunityUserGrayGreenDarkest = FromHex(@"1e2422"); } } diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 633085960b..ffbb9ad218 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -35,14 +35,14 @@ namespace osu.Game.Overlays.Profile.Header [BackgroundDependencyLoader] private void load(OsuColour colours) { - iconColour = colours.CommunityUserGrayGreenLighter; + iconColour = colours.GreySeafoamLighter; InternalChildren = new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDarker, + Colour = colours.GreySeafoamDark, }, new FillFlowContainer { diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index b441775393..68fd77dd84 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Profile.Header new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDark + Colour = colours.GreySeafoam }, new FillFlowContainer { diff --git a/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs b/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs index 089228b2cd..46d24608ed 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs @@ -27,8 +27,8 @@ namespace osu.Game.Overlays.Profile.Header.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - IdleColour = colours.CommunityUserGrayGreen; - HoverColour = colours.CommunityUserGrayGreen.Darken(0.2f); + IdleColour = colours.GreySeafoamLight; + HoverColour = colours.GreySeafoamLight.Darken(0.2f); Child = icon = new SpriteIcon { diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 1dabf167e3..85ea2a175a 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -154,7 +154,7 @@ namespace osu.Game.Overlays.Profile.Header.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - ballBg.Colour = colours.CommunityUserGrayGreenDarkest; + ballBg.Colour = colours.GreySeafoamDarker; movingBall.BorderColour = colours.Yellow; movingBar.Colour = colours.Yellow; } @@ -249,7 +249,7 @@ namespace osu.Game.Overlays.Profile.Header.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - background.Colour = colours.CommunityUserGrayGreenDarker; + background.Colour = colours.GreySeafoamDark; } public void Refresh() diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index 97454d7327..c5e61f68f4 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -80,7 +80,7 @@ namespace osu.Game.Overlays.Profile.Header.Components private void load(OsuColour colours) { background.Colour = colours.Pink; - iconContainer.Colour = colours.CommunityUserGrayGreenDark; + iconContainer.Colour = colours.GreySeafoam; } } } diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index e41c90be45..f26cc360a2 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -65,7 +65,7 @@ namespace osu.Game.Overlays.Profile.Header new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDarkest, + Colour = colours.GreySeafoamDarker, }, fillFlow = new FillFlowContainer { diff --git a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs index 25d04195b2..67229a80c0 100644 --- a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Profile.Header new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDarkest, + Colour = colours.GreySeafoamDarker, }, new Container //artificial shadow { diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 2ac7f3cc96..6fe55e2368 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Profile.Header new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDarker, + Colour = colours.GreySeafoamDark, }, new FillFlowContainer { @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.X, Height = 1.5f, Margin = new MarginPadding { Top = 10 }, - Colour = colours.CommunityUserGrayGreenLighter, + Colour = colours.GreySeafoamLighter, }, new Container { @@ -125,7 +125,7 @@ namespace osu.Game.Overlays.Profile.Header Margin = new MarginPadding { Left = 40 }, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, - Colour = colours.CommunityUserGrayGreenLighter, + Colour = colours.GreySeafoamLighter, } } }, diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 2d8c47b11a..f2ac94b7ff 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -124,7 +124,7 @@ namespace osu.Game.Overlays.Profile [BackgroundDependencyLoader] private void load(OsuColour colours) { - infoTabControl.AccentColour = colours.CommunityUserGreen; + infoTabControl.AccentColour = colours.Seafoam; } public Bindable User = new Bindable(); @@ -145,7 +145,7 @@ namespace osu.Game.Overlays.Profile [BackgroundDependencyLoader] private void load(OsuColour colours) { - AccentColour = colours.CommunityUserGreen; + AccentColour = colours.Seafoam; } } } From a5bd3262beabe43ff5a4e39eba5e29398f0e58b3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 May 2019 18:02:13 +0900 Subject: [PATCH 0895/5608] Move UserProfileOverlay's header into an abstract implementation --- .../Online/TestSceneUserProfileHeader.cs | 2 +- osu.Game/Overlays/OverlayHeader.cs | 71 ++++++++ ...eaderTabControl.cs => HeaderTabControl.cs} | 12 +- osu.Game/Overlays/Profile/ProfileHeader.cs | 165 +++++++----------- 4 files changed, 142 insertions(+), 108 deletions(-) create mode 100644 osu.Game/Overlays/OverlayHeader.cs rename osu.Game/Overlays/Profile/Header/{ProfileHeaderTabControl.cs => HeaderTabControl.cs} (92%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index 14c81558c1..730140faed 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.Online typeof(ProfileHeader), typeof(RankGraph), typeof(LineGraph), - typeof(ProfileHeaderTabControl), + typeof(HeaderTabControl), typeof(CentreHeaderContainer), typeof(BottomHeaderContainer), typeof(DetailHeaderContainer), diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs new file mode 100644 index 0000000000..fe50d4a2be --- /dev/null +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -0,0 +1,71 @@ +// 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.UserInterface; +using osu.Game.Overlays.Profile.Header; + +namespace osu.Game.Overlays +{ + public abstract class OverlayHeader : Container + { + protected readonly HeaderTabControl TabControl; + + private const float cover_height = 150; + private const float cover_info_height = 75; + + protected OverlayHeader() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + Height = cover_height, + Masking = true, + Child = CreateBackground() + }, + new Container + { + Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, + Y = cover_height, + Height = cover_info_height, + RelativeSizeAxes = Axes.X, + Anchor = Anchor.TopLeft, + Origin = Anchor.BottomLeft, + Depth = -float.MaxValue, + Children = new Drawable[] + { + CreateTitle().With(t => t.X = -ScreenTitle.ICON_WIDTH), + TabControl = new HeaderTabControl + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = cover_info_height - 30, + Margin = new MarginPadding { Left = -UserProfileOverlay.CONTENT_X_MARGIN }, + Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN } + } + } + }, + new Container + { + Margin = new MarginPadding { Top = cover_height }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = CreateContent() + } + }; + } + + protected abstract Drawable CreateBackground(); + + protected abstract Drawable CreateContent(); + + protected abstract ScreenTitle CreateTitle(); + } +} diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs b/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs similarity index 92% rename from osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs rename to osu.Game/Overlays/Profile/Header/HeaderTabControl.cs index 3b16b102d5..1169ef7013 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs +++ b/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header { - public class ProfileHeaderTabControl : TabControl + public class HeaderTabControl : TabControl { private readonly Box bar; @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Profile.Header foreach (TabItem tabItem in TabContainer) { - ((ProfileHeaderTabItem)tabItem).AccentColour = value; + ((HeaderTabItem)tabItem).AccentColour = value; } } } @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.Profile.Header set => TabContainer.Padding = value; } - public ProfileHeaderTabControl() + public HeaderTabControl() { TabContainer.Masking = false; TabContainer.Spacing = new Vector2(15, 0); @@ -59,12 +59,12 @@ namespace osu.Game.Overlays.Profile.Header protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(string value) => new ProfileHeaderTabItem(value) + protected override TabItem CreateTabItem(string value) => new HeaderTabItem(value) { AccentColour = AccentColour }; - private class ProfileHeaderTabItem : TabItem + private class HeaderTabItem : TabItem { private readonly OsuSpriteText text; private readonly Drawable bar; @@ -86,7 +86,7 @@ namespace osu.Game.Overlays.Profile.Header } } - public ProfileHeaderTabItem(string value) + public HeaderTabItem(string value) : base(value) { AutoSizeAxes = Axes.X; diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index f2ac94b7ff..702bd6c2c4 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -15,124 +15,85 @@ using osu.Game.Users; namespace osu.Game.Overlays.Profile { - public class ProfileHeader : Container + public class ProfileHeader : OverlayHeader { - private readonly UserCoverBackground coverContainer; - private readonly ProfileHeaderTabControl infoTabControl; + private UserCoverBackground coverContainer; - private const float cover_height = 150; - private const float cover_info_height = 75; + public Bindable User = new Bindable(); + + private CentreHeaderContainer centreHeaderContainer; + private DetailHeaderContainer detailHeaderContainer; public ProfileHeader() { - CentreHeaderContainer centreHeaderContainer; - DetailHeaderContainer detailHeaderContainer; + User.ValueChanged += e => updateDisplay(e.NewValue); - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - Children = new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.X, - Height = cover_height, - Masking = true, - Children = new Drawable[] - { - coverContainer = new UserCoverBackground - { - RelativeSizeAxes = Axes.Both, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(OsuColour.FromHex("222").Opacity(0.8f), OsuColour.FromHex("222").Opacity(0.2f)) - }, - } - }, - new Container - { - Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, - Y = cover_height, - Height = cover_info_height, - RelativeSizeAxes = Axes.X, - Anchor = Anchor.TopLeft, - Origin = Anchor.BottomLeft, - Depth = -float.MaxValue, - Children = new Drawable[] - { - new ProfileHeaderTitle - { - X = -ScreenTitle.ICON_WIDTH, - }, - infoTabControl = new ProfileHeaderTabControl - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Height = cover_info_height - 30, - Margin = new MarginPadding { Left = -UserProfileOverlay.CONTENT_X_MARGIN }, - Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN } - } - } - }, - new FillFlowContainer - { - Margin = new MarginPadding { Top = cover_height }, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new TopHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - centreHeaderContainer = new CentreHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - detailHeaderContainer = new DetailHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - new MedalHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - new BottomHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - } - } - }; - - infoTabControl.AddItem("Info"); - infoTabControl.AddItem("Modding"); + TabControl.AddItem("Info"); + TabControl.AddItem("Modding"); centreHeaderContainer.DetailsVisible.BindValueChanged(visible => detailHeaderContainer.Expanded = visible.NewValue, true); - User.ValueChanged += e => updateDisplay(e.NewValue); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - infoTabControl.AccentColour = colours.Seafoam; + TabControl.AccentColour = colours.Seafoam; } - public Bindable User = new Bindable(); + protected override Drawable CreateBackground() => + new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + coverContainer = new UserCoverBackground + { + RelativeSizeAxes = Axes.Both, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(OsuColour.FromHex("222").Opacity(0.8f), OsuColour.FromHex("222").Opacity(0.2f)) + }, + } + }; - private void updateDisplay(User user) + protected override Drawable CreateContent() => new FillFlowContainer { - coverContainer.User = user; - } + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new TopHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + centreHeaderContainer = new CentreHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + detailHeaderContainer = new DetailHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + new MedalHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + new BottomHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + } + }; + + protected override ScreenTitle CreateTitle() => new ProfileHeaderTitle(); private class ProfileHeaderTitle : ScreenTitle { @@ -148,5 +109,7 @@ namespace osu.Game.Overlays.Profile AccentColour = colours.Seafoam; } } + + private void updateDisplay(User user) => coverContainer.User = user; } } From 6a8a743eaa5d5e5f630d05ac23a12051b67c7ddd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 May 2019 18:02:27 +0900 Subject: [PATCH 0896/5608] Begin to consume abstract header implementation --- .../Overlays/Changelog/ChangelogHeader.cs | 104 ++++++++++-------- 1 file changed, 60 insertions(+), 44 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 94046d5762..9ef3316985 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -10,12 +10,13 @@ using osu.Framework.Graphics.Textures; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Changelog.Header; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { - public class ChangelogHeader : Container + public class ChangelogHeader : OverlayHeader { private OsuSpriteText titleStream; private BreadcrumbListing listing; @@ -26,35 +27,36 @@ namespace osu.Game.Overlays.Changelog public event ListingSelectedEventHandler ListingSelected; - private const float cover_height = 150; private const float title_height = 50; private const float icon_size = 50; private const float icon_margin = 20; private const float version_height = 40; - [BackgroundDependencyLoader] - private void load(OsuColour colours, TextureStore textures) + public void ShowBuild(string displayName, string displayVersion) { - RelativeSizeAxes = Axes.X; - Height = cover_height; + listing.Deactivate(); + releaseStream.ShowBuild($"{displayName} {displayVersion}"); + titleStream.Text = displayName; + titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); + chevron.MoveToX(0, 100).FadeIn(100); + } + public void ShowListing() + { + releaseStream.Deactivate(); + listing.Activate(); + titleStream.Text = "Listing"; + titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); + chevron.MoveToX(-20, 100).FadeOut(100); + } + + protected override Drawable CreateBackground() => new HeaderBackground(); + + protected override Drawable CreateContent() => new Container + { + RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Container - { - RelativeSizeAxes = Axes.X, - Height = cover_height, - Masking = true, - Children = new Drawable[] - { - new Sprite - { - RelativeSizeAxes = Axes.Both, - Texture = textures.Get(@"Headers/changelog"), - FillMode = FillMode.Fill, - }, - } - }, new Container { Height = title_height, @@ -67,7 +69,7 @@ namespace osu.Game.Overlays.Changelog { X = icon_margin, Masking = true, - BorderColour = colours.Violet, + //BorderColour = colours.Violet, BorderThickness = 3, MaskingSmoothness = 1, Size = new Vector2(50), @@ -76,7 +78,7 @@ namespace osu.Game.Overlays.Changelog new Sprite { RelativeSizeAxes = Axes.Both, - Texture = textures.Get(@"Icons/changelog"), + //Texture = textures.Get(@"Icons/changelog"), Size = new Vector2(0.8f), Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -84,7 +86,7 @@ namespace osu.Game.Overlays.Changelog new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.Violet, + //Colour = colours.Violet, Alpha = 0, AlwaysPresent = true, }, @@ -108,7 +110,7 @@ namespace osu.Game.Overlays.Changelog { Text = "Listing", Font = OsuFont.GetFont(weight: FontWeight.Light, size: 30), - Colour = colours.Violet, + //Colour = colours.Violet, }, } } @@ -123,7 +125,7 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Horizontal, Children = new Drawable[] { - listing = new BreadcrumbListing(colours.Violet) + listing = new BreadcrumbListing( /*colours.Violet*/ Color4.WhiteSmoke) { Action = () => ListingSelected?.Invoke() }, @@ -145,14 +147,14 @@ namespace osu.Game.Overlays.Changelog Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(7), - Colour = colours.Violet, + // Colour = colours.Violet, Icon = FontAwesome.Solid.ChevronRight, Alpha = 0, X = -200, }, }, }, - releaseStream = new BreadcrumbRelease(colours.Violet, "Lazer") + releaseStream = new BreadcrumbRelease( /*colours.Violet*/ Color4.WhiteSmoke, "Lazer") { Action = () => titleStream.FlashColour(Color4.White, 500, Easing.OutQuad) } @@ -160,31 +162,45 @@ namespace osu.Game.Overlays.Changelog }, new Box { - Colour = colours.Violet, + //Colour = colours.Violet, RelativeSizeAxes = Axes.X, Height = 2, Anchor = Anchor.BottomLeft, Origin = Anchor.CentreLeft, }, - }; + } + }; + + protected override ScreenTitle CreateTitle() => new ChangelogHeaderTitle(); + + public class HeaderBackground : Sprite + { + public HeaderBackground() + { + RelativeSizeAxes = Axes.Both; + FillMode = FillMode.Fill; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Texture = textures.Get(@"Headers/changelog"); + } } - public void ShowBuild(string displayName, string displayVersion) + private class ChangelogHeaderTitle : ScreenTitle { - listing.Deactivate(); - releaseStream.ShowBuild($"{displayName} {displayVersion}"); - titleStream.Text = displayName; - titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); - chevron.MoveToX(0, 100).FadeIn(100); - } + public ChangelogHeaderTitle() + { + Title = "Changelog"; + Section = "Listing"; + } - public void ShowListing() - { - releaseStream.Deactivate(); - listing.Activate(); - titleStream.Text = "Listing"; - titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); - chevron.MoveToX(-20, 100).FadeOut(100); + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AccentColour = colours.Seafoam; + } } } } From 6c26d6fdf908513348548c4c148f73f16b1bb27e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 11:13:36 +0900 Subject: [PATCH 0897/5608] Remove unnecessary getters from ScreenTitle --- osu.Game/Graphics/UserInterface/ScreenTitle.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index 34c70f2bed..3c3aa8fe85 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -19,19 +19,16 @@ namespace osu.Game.Graphics.UserInterface protected IconUsage Icon { - get => iconSprite.Icon; set => iconSprite.Icon = value; } protected string Title { - get => titleText.Text; set => titleText.Text = value; } protected string Section { - get => pageText.Text; set => pageText.Text = value; } From 808b45ac645ce2488dff52de7f55428f386e4044 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 11:50:03 +0900 Subject: [PATCH 0898/5608] Allow custom icon specification in ScreenTitle Not all icons are available in fonts so IconUsage alone is not enough to cover all scenarios. --- .../Graphics/UserInterface/ScreenTitle.cs | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index 3c3aa8fe85..7b39238e5e 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -12,14 +13,24 @@ namespace osu.Game.Graphics.UserInterface { public abstract class ScreenTitle : CompositeDrawable, IHasAccentColour { - private readonly SpriteIcon iconSprite; + public const float ICON_WIDTH = ICON_SIZE + icon_spacing; + + protected const float ICON_SIZE = 25; + + private SpriteIcon iconSprite; private readonly OsuSpriteText titleText, pageText; - public const float ICON_WIDTH = icon_size + icon_spacing; - private const float icon_size = 25, icon_spacing = 10; + + private const float icon_spacing = 10; protected IconUsage Icon { - set => iconSprite.Icon = value; + set + { + if (iconSprite == null) + throw new InvalidOperationException($"Cannot use {nameof(Icon)} with a custom {nameof(CreateIcon)} function."); + + iconSprite.Icon = value; + } } protected string Title @@ -38,6 +49,11 @@ namespace osu.Game.Graphics.UserInterface set => pageText.Colour = value; } + protected virtual Drawable CreateIcon() => iconSprite = new SpriteIcon + { + Size = new Vector2(ICON_SIZE), + }; + protected ScreenTitle() { AutoSizeAxes = Axes.Both; @@ -48,12 +64,9 @@ namespace osu.Game.Graphics.UserInterface { AutoSizeAxes = Axes.Both, Spacing = new Vector2(icon_spacing, 0), - Children = new Drawable[] + Children = new[] { - iconSprite = new SpriteIcon - { - Size = new Vector2(icon_size), - }, + CreateIcon(), new FillFlowContainer { AutoSizeAxes = Axes.Both, From aca0fc80a8e25679226b267a9919375d4afff748 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 12:45:20 +0900 Subject: [PATCH 0899/5608] Set HeaderTabControl's default AccentColour to non-transparent Avoids items disappearing if no accent colour is set. --- osu.Game/Overlays/Profile/Header/HeaderTabControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs b/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs index 1169ef7013..5fd9195945 100644 --- a/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs +++ b/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Profile.Header { private readonly Box bar; - private Color4 accentColour; + private Color4 accentColour = Color4.White; public Color4 AccentColour { From 58a3480b6aa428734449262be6046a12657581cf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 12:52:50 +0900 Subject: [PATCH 0900/5608] Update ChangelogHeader to work again with OverlayHeader --- .../Requests/Responses/APIChangelogBuild.cs | 2 + .../Overlays/Changelog/ChangelogHeader.cs | 237 +++++++----------- osu.Game/Overlays/ChangelogOverlay.cs | 9 +- 3 files changed, 104 insertions(+), 144 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs index 3377800c2b..504c65928d 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs @@ -41,5 +41,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("previous")] public APIChangelogBuild Previous { get; set; } } + + public override string ToString() => $"{UpdateStream.DisplayName} {DisplayVersion}"; } } diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 9ef3316985..4f406daabe 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -1,53 +1,72 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Game.Graphics.Sprites; -using osu.Game.Overlays.Changelog.Header; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API.Requests.Responses; using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { public class ChangelogHeader : OverlayHeader { - private OsuSpriteText titleStream; - private BreadcrumbListing listing; - private SpriteIcon chevron; - private BreadcrumbRelease releaseStream; + public Action ListingSelected; - public delegate void ListingSelectedEventHandler(); + private const string listing_string = "Listing"; - public event ListingSelectedEventHandler ListingSelected; - - private const float title_height = 50; - private const float icon_size = 50; - private const float icon_margin = 20; - private const float version_height = 40; - - public void ShowBuild(string displayName, string displayVersion) + public ChangelogHeader() { - listing.Deactivate(); - releaseStream.ShowBuild($"{displayName} {displayVersion}"); - titleStream.Text = displayName; - titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); - chevron.MoveToX(0, 100).FadeIn(100); + TabControl.AddItem(listing_string); + TabControl.Current.ValueChanged += e => + { + if (e.NewValue == listing_string) + ListingSelected?.Invoke(); + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + TabControl.AccentColour = colours.Violet; + } + + private APIChangelogBuild displayedBuild; + + private ChangelogHeaderTitle title; + + public void ShowBuild(APIChangelogBuild build) + { + hideBuildTab(); + + displayedBuild = build; + + TabControl.AddItem(build.ToString()); + TabControl.Current.Value = build.ToString(); + + title.Version = build.UpdateStream.DisplayName; } public void ShowListing() { - releaseStream.Deactivate(); - listing.Activate(); - titleStream.Text = "Listing"; - titleStream.FlashColour(Color4.White, 500, Easing.OutQuad); - chevron.MoveToX(-20, 100).FadeOut(100); + hideBuildTab(); + + title.Version = null; + } + + private void hideBuildTab() + { + if (displayedBuild != null) + { + TabControl.RemoveItem(displayedBuild.ToString()); + displayedBuild = null; + } } protected override Drawable CreateBackground() => new HeaderBackground(); @@ -57,121 +76,11 @@ namespace osu.Game.Overlays.Changelog RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Container - { - Height = title_height, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Y = -version_height, - Children = new Drawable[] - { - new CircularContainer - { - X = icon_margin, - Masking = true, - //BorderColour = colours.Violet, - BorderThickness = 3, - MaskingSmoothness = 1, - Size = new Vector2(50), - Children = new Drawable[] - { - new Sprite - { - RelativeSizeAxes = Axes.Both, - //Texture = textures.Get(@"Icons/changelog"), - Size = new Vector2(0.8f), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - //Colour = colours.Violet, - Alpha = 0, - AlwaysPresent = true, - }, - } - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - X = icon_size + icon_margin * 2, - Children = new Drawable[] - { - new OsuSpriteText - { - Text = "Changelog ", - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 30), - }, - titleStream = new OsuSpriteText - { - Text = "Listing", - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 30), - //Colour = colours.Violet, - }, - } - } - } - }, - new FillFlowContainer // Listing > Lazer 2018.713.1 - { - X = 2 * icon_margin + icon_size, - Height = version_height, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Direction = FillDirection.Horizontal, - Children = new Drawable[] - { - listing = new BreadcrumbListing( /*colours.Violet*/ Color4.WhiteSmoke) - { - Action = () => ListingSelected?.Invoke() - }, - new Container // without a container, moving the chevron wont work - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Margin = new MarginPadding - { - Top = 10, - Left = 15, - Right = 18, - Bottom = 15, - }, - Children = new Drawable[] - { - chevron = new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(7), - // Colour = colours.Violet, - Icon = FontAwesome.Solid.ChevronRight, - Alpha = 0, - X = -200, - }, - }, - }, - releaseStream = new BreadcrumbRelease( /*colours.Violet*/ Color4.WhiteSmoke, "Lazer") - { - Action = () => titleStream.FlashColour(Color4.White, 500, Easing.OutQuad) - } - }, - }, - new Box - { - //Colour = colours.Violet, - RelativeSizeAxes = Axes.X, - Height = 2, - Anchor = Anchor.BottomLeft, - Origin = Anchor.CentreLeft, - }, + // todo: move badge display here } }; - protected override ScreenTitle CreateTitle() => new ChangelogHeaderTitle(); + protected override ScreenTitle CreateTitle() => title = new ChangelogHeaderTitle(); public class HeaderBackground : Sprite { @@ -190,16 +99,64 @@ namespace osu.Game.Overlays.Changelog private class ChangelogHeaderTitle : ScreenTitle { + public string Version + { + set => Section = value ?? listing_string; + } + public ChangelogHeaderTitle() { Title = "Changelog"; - Section = "Listing"; + Version = null; } [BackgroundDependencyLoader] private void load(OsuColour colours) { - AccentColour = colours.Seafoam; + AccentColour = colours.Violet; + } + + protected override Drawable CreateIcon() => new ChangelogIcon(); + + internal class ChangelogIcon : CompositeDrawable + { + private const float circle_allowance = 0.8f; + + [BackgroundDependencyLoader] + private void load(TextureStore textures, OsuColour colours) + { + Size = new Vector2(ICON_SIZE / circle_allowance); + + InternalChildren = new Drawable[] + { + new CircularContainer + { + Masking = true, + BorderColour = colours.Violet, + BorderThickness = 3, + MaskingSmoothness = 1, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Sprite + { + RelativeSizeAxes = Axes.Both, + Texture = textures.Get(@"Icons/changelog"), + Size = new Vector2(circle_allowance), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Violet, + Alpha = 0, + AlwaysPresent = true, + }, + } + }, + }; + } } } } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 22c362d49d..430fa569f1 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -58,7 +58,10 @@ namespace osu.Game.Overlays Direction = FillDirection.Vertical, Children = new Drawable[] { - header = new ChangelogHeader(), + header = new ChangelogHeader + { + ListingSelected = ShowListing, + }, badges = new BadgeDisplay(), content = new Container { @@ -70,8 +73,6 @@ namespace osu.Game.Overlays }, }; - header.ListingSelected += ShowListing; - // todo: better badges.Current.ValueChanged += e => { @@ -135,7 +136,7 @@ namespace osu.Game.Overlays return; } - header.ShowBuild(build.UpdateStream.DisplayName, build.DisplayVersion); + header.ShowBuild(build); badges.Current.Value = build.UpdateStream; loadContent(new ChangelogSingleBuild(build)); From a131875a7b40346b62f67175a40016fe7c998c0a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 13:34:35 +0900 Subject: [PATCH 0901/5608] Use bindables the whole way --- .../Requests/Responses/APIChangelogBuild.cs | 4 +- .../API/Requests/Responses/APIUpdateStream.cs | 8 +- .../Overlays/Changelog/ChangelogHeader.cs | 42 +++++----- osu.Game/Overlays/ChangelogOverlay.cs | 81 ++++++++++--------- 4 files changed, 65 insertions(+), 70 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs index 504c65928d..36c9cc610f 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; namespace osu.Game.Online.API.Requests.Responses { - public class APIChangelogBuild + public class APIChangelogBuild : IEquatable { [JsonProperty("id")] public long Id { get; set; } @@ -42,6 +42,8 @@ namespace osu.Game.Online.API.Requests.Responses public APIChangelogBuild Previous { get; set; } } + public bool Equals(APIChangelogBuild other) => this.Id == other?.Id; + public override string ToString() => $"{UpdateStream.DisplayName} {DisplayVersion}"; } } diff --git a/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs index 4c65b562dd..0c3fee88c7 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs @@ -25,13 +25,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("latest_build")] public APIChangelogBuild LatestBuild { get; set; } - public bool Equals(APIUpdateStream other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - - return Id == other.Id; - } + public bool Equals(APIUpdateStream other) => this.Id == other?.Id; public ColourInfo Colour { diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 4f406daabe..ccc976c4dc 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -17,6 +18,8 @@ namespace osu.Game.Overlays.Changelog { public class ChangelogHeader : OverlayHeader { + public readonly Bindable Current = new Bindable(); + public Action ListingSelected; private const string listing_string = "Listing"; @@ -29,6 +32,8 @@ namespace osu.Game.Overlays.Changelog if (e.NewValue == listing_string) ListingSelected?.Invoke(); }; + + Current.ValueChanged += showBuild; } [BackgroundDependencyLoader] @@ -37,35 +42,24 @@ namespace osu.Game.Overlays.Changelog TabControl.AccentColour = colours.Violet; } - private APIChangelogBuild displayedBuild; - private ChangelogHeaderTitle title; - public void ShowBuild(APIChangelogBuild build) + private void showBuild(ValueChangedEvent e) { - hideBuildTab(); + if (e.OldValue != null) + TabControl.RemoveItem(e.OldValue.ToString()); - displayedBuild = build; - - TabControl.AddItem(build.ToString()); - TabControl.Current.Value = build.ToString(); - - title.Version = build.UpdateStream.DisplayName; - } - - public void ShowListing() - { - hideBuildTab(); - - title.Version = null; - } - - private void hideBuildTab() - { - if (displayedBuild != null) + if (e.NewValue != null) { - TabControl.RemoveItem(displayedBuild.ToString()); - displayedBuild = null; + TabControl.AddItem(e.NewValue.ToString()); + TabControl.Current.Value = e.NewValue.ToString(); + + title.Version = e.NewValue.UpdateStream.DisplayName; + } + else + { + TabControl.Current.Value = listing_string; + title.Version = null; } } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 430fa569f1..34347d8e0a 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.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.Collections.Generic; -using System.Linq; using System.Threading; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -32,6 +34,23 @@ namespace osu.Game.Overlays private List builds; + public readonly Bindable Current = new Bindable(); + + public void ShowListing() => Current.Value = null; + + /// + /// Fetches and shows a specific build from a specific update stream. + /// + /// Must contain at least and + /// . If and + /// are specified, the header will instantly display them. + public void ShowBuild([NotNull] APIChangelogBuild build) + { + if (build == null) throw new ArgumentNullException(nameof(build)); + + Current.Value = build; + } + [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colour) { @@ -73,22 +92,30 @@ namespace osu.Game.Overlays }, }; - // todo: better badges.Current.ValueChanged += e => { - if (e.NewValue?.LatestBuild != null) + if (e.NewValue != null) ShowBuild(e.NewValue.LatestBuild); }; sampleBack = audio.Sample.Get(@"UI/generic-select-soft"); - } - protected override void PopIn() - { - base.PopIn(); + header.Current.BindTo(Current); - if (!initialFetchPerformed) - fetchListing(); + Current.BindValueChanged(e => + { + if (e.NewValue != null) + { + badges.Current.Value = e.NewValue.UpdateStream; + + loadContent(new ChangelogSingleBuild(e.NewValue)); + } + else + { + badges.Current.Value = null; + loadContent(new ChangelogListing(builds)); + } + }); } public override bool OnPressed(GlobalAction action) @@ -96,13 +123,13 @@ namespace osu.Game.Overlays switch (action) { case GlobalAction.Back: - if (content.Child is ChangelogListing) + if (Current.Value == null) { State = Visibility.Hidden; } else { - ShowListing(); + Current.Value = null; sampleBack?.Play(); } @@ -112,34 +139,12 @@ namespace osu.Game.Overlays return false; } - public void ShowListing() + protected override void PopIn() { - if (content.Children.FirstOrDefault() is ChangelogListing) - return; + base.PopIn(); - header.ShowListing(); - badges.Current.Value = null; - loadContent(new ChangelogListing(builds)); - } - - /// - /// Fetches and shows a specific build from a specific update stream. - /// - /// Must contain at least and - /// . If and - /// are specified, the header will instantly display them. - public void ShowBuild(APIChangelogBuild build) - { - if (build == null) - { - ShowListing(); - return; - } - - header.ShowBuild(build); - badges.Current.Value = build.UpdateStream; - - loadContent(new ChangelogSingleBuild(build)); + if (!initialFetchPerformed) + fetchListing(); } private bool initialFetchPerformed; @@ -158,7 +163,7 @@ namespace osu.Game.Overlays builds = res.Builds; badges.Populate(res.Streams); - ShowListing(); + Current.TriggerChange(); }; req.Failure += _ => initialFetchPerformed = false; From 9a769c9f15801ff781621b160a953e7c5c777c32 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 13:36:21 +0900 Subject: [PATCH 0902/5608] Move OverlayHeaderTabControl to correct namespace --- osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs | 3 ++- osu.Game/Overlays/OverlayHeader.cs | 5 ++--- .../HeaderTabControl.cs => OverlayHeaderTabControl.cs} | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) rename osu.Game/Overlays/{Profile/Header/HeaderTabControl.cs => OverlayHeaderTabControl.cs} (97%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index 730140faed..d9230090fc 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Overlays; using osu.Game.Overlays.Profile; using osu.Game.Overlays.Profile.Header; using osu.Game.Overlays.Profile.Header.Components; @@ -21,7 +22,7 @@ namespace osu.Game.Tests.Visual.Online typeof(ProfileHeader), typeof(RankGraph), typeof(LineGraph), - typeof(HeaderTabControl), + typeof(OverlayHeaderTabControl), typeof(CentreHeaderContainer), typeof(BottomHeaderContainer), typeof(DetailHeaderContainer), diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index fe50d4a2be..2e032db2ba 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -4,13 +4,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.UserInterface; -using osu.Game.Overlays.Profile.Header; namespace osu.Game.Overlays { public abstract class OverlayHeader : Container { - protected readonly HeaderTabControl TabControl; + protected readonly OverlayHeaderTabControl TabControl; private const float cover_height = 150; private const float cover_info_height = 75; @@ -41,7 +40,7 @@ namespace osu.Game.Overlays Children = new Drawable[] { CreateTitle().With(t => t.X = -ScreenTitle.ICON_WIDTH), - TabControl = new HeaderTabControl + TabControl = new OverlayHeaderTabControl { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, diff --git a/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs b/osu.Game/Overlays/OverlayHeaderTabControl.cs similarity index 97% rename from osu.Game/Overlays/Profile/Header/HeaderTabControl.cs rename to osu.Game/Overlays/OverlayHeaderTabControl.cs index 5fd9195945..21b42cfbf4 100644 --- a/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs +++ b/osu.Game/Overlays/OverlayHeaderTabControl.cs @@ -11,9 +11,9 @@ using osu.Game.Graphics.UserInterface; using osuTK; using osuTK.Graphics; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays { - public class HeaderTabControl : TabControl + public class OverlayHeaderTabControl : TabControl { private readonly Box bar; @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.Profile.Header set => TabContainer.Padding = value; } - public HeaderTabControl() + public OverlayHeaderTabControl() { TabContainer.Masking = false; TabContainer.Spacing = new Vector2(15, 0); From 340b207fa0013b9fee8d99bdf4e5f17967bcd160 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 13:37:35 +0900 Subject: [PATCH 0903/5608] Delete breadcrumb implementation --- .../Online/TestSceneChangelogOverlay.cs | 4 - .../UserInterface/TestSceneTextBadgePair.cs | 57 -------- .../Overlays/Changelog/Header/Breadcrumb.cs | 127 ------------------ .../Changelog/Header/BreadcrumbListing.cs | 66 --------- .../Changelog/Header/BreadcrumbRelease.cs | 35 ----- 5 files changed, 289 deletions(-) delete mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneTextBadgePair.cs delete mode 100644 osu.Game/Overlays/Changelog/Header/Breadcrumb.cs delete mode 100644 osu.Game/Overlays/Changelog/Header/BreadcrumbListing.cs delete mode 100644 osu.Game/Overlays/Changelog/Header/BreadcrumbRelease.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 4ac5514019..c97ef384d3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -7,7 +7,6 @@ using NUnit.Framework; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.Changelog; -using osu.Game.Overlays.Changelog.Header; namespace osu.Game.Tests.Visual.Online { @@ -25,9 +24,6 @@ namespace osu.Game.Tests.Visual.Online typeof(ChangelogListing), typeof(ChangelogSingleBuild), typeof(ChangelogBuild), - typeof(Breadcrumb), - typeof(BreadcrumbListing), - typeof(BreadcrumbRelease), }; protected override void LoadComplete() diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneTextBadgePair.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTextBadgePair.cs deleted file mode 100644 index 67b2b9854d..0000000000 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneTextBadgePair.cs +++ /dev/null @@ -1,57 +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.Colour; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Overlays.Changelog.Header; -using osuTK.Graphics; - -namespace osu.Game.Tests.Visual.UserInterface -{ - public class TestSceneTextBadgePair : OsuTestScene - { - public TestSceneTextBadgePair() - { - Breadcrumb breadcrumb; - - Add(new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Width = 250, - Height = 50, - Children = new Drawable[] - { - new Box - { - Colour = Color4.Gray, - Alpha = 0.5f, - RelativeSizeAxes = Axes.Both, - }, - breadcrumb = new TestBadgePair(Color4.DeepSkyBlue, "Test") - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } - } - }); - - AddStep(@"Deactivate", breadcrumb.Deactivate); - AddStep(@"Activate", breadcrumb.Activate); - AddStep(@"Hide text", () => breadcrumb.HideText(200)); - AddStep(@"Show text", () => breadcrumb.ShowText(200)); - AddStep(@"Different text", () => breadcrumb.ShowText(200, "This one's a little bit wider")); - AddStep(@"Different text", () => breadcrumb.ShowText(200, "Ok?..")); - } - - private class TestBadgePair : Breadcrumb - { - public TestBadgePair(ColourInfo badgeColour, string displayText = "Listing", bool startCollapsed = true) - : base(badgeColour, displayText, startCollapsed) - { - } - } - } -} diff --git a/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs b/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs deleted file mode 100644 index f960111a53..0000000000 --- a/osu.Game/Overlays/Changelog/Header/Breadcrumb.cs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; -using System; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Overlays.Changelog.Components; - -namespace osu.Game.Overlays.Changelog.Header -{ - public abstract class Breadcrumb : Container - { - protected SpriteText Text; - protected LineBadge LineBadge; - - public bool IsActivated { get; protected set; } - - public Action Action; - - private SampleChannel sampleHover; - private SampleChannel sampleActivate; - - protected Breadcrumb(ColourInfo badgeColour, string displayText = "Listing", bool startCollapsed = true) - { - AutoSizeAxes = Axes.X; - RelativeSizeAxes = Axes.Y; - Children = new Drawable[] - { - Text = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 16), - Text = displayText, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Margin = new MarginPadding { Top = 5, Bottom = 15 }, - }, - LineBadge = new LineBadge(startCollapsed) - { - CollapsedSize = 2, - UncollapsedSize = 10, - Colour = badgeColour, - Anchor = Anchor.BottomCentre, - Origin = Anchor.Centre, - } - }; - } - - public virtual void Deactivate() - { - if (!IsActivated) - return; - - IsActivated = false; - LineBadge.Collapse(); - Text.Font = Text.Font.With(weight: FontWeight.Regular); - } - - public virtual void Activate() - { - if (IsActivated) - return; - - IsActivated = true; - LineBadge.Uncollapse(); - Text.Font = Text.Font.With(weight: FontWeight.Bold); - } - - public void SetTextColour(ColourInfo newColour, double duration = 0, Easing easing = Easing.None) - { - Text.FadeColour(newColour, duration, easing); - } - - public void HideText(double duration = 0, Easing easing = Easing.InOutCubic) - { - LineBadge.Collapse(); - Text.MoveToY(20, duration, easing) - .FadeOut(duration, easing); - } - - public void ShowText(double duration = 0, string displayText = null, Easing easing = Easing.InOutCubic) - { - LineBadge.Collapse(); - Text.MoveToY(20, duration, easing) - .FadeOut(duration, easing) - .Then() - .MoveToY(0, duration, easing) - .FadeIn(duration, easing); - - Scheduler.AddDelayed(() => - { - Text.Text = displayText; - LineBadge.Uncollapse(); - }, duration); - } - - protected override bool OnHover(HoverEvent e) - { - if (!IsActivated) - sampleHover?.Play(); - return base.OnHover(e); - } - - protected override bool OnClick(ClickEvent e) - { - Action?.Invoke(); - Activate(); - sampleActivate?.Play(); - - return true; - } - - [BackgroundDependencyLoader] - private void load(AudioManager audio) - { - sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); - sampleActivate = audio.Sample.Get(@"UI/generic-select-soft"); - } - } -} diff --git a/osu.Game/Overlays/Changelog/Header/BreadcrumbListing.cs b/osu.Game/Overlays/Changelog/Header/BreadcrumbListing.cs deleted file mode 100644 index 50db916e7e..0000000000 --- a/osu.Game/Overlays/Changelog/Header/BreadcrumbListing.cs +++ /dev/null @@ -1,66 +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.Colour; -using osu.Framework.Input.Events; -using osu.Game.Graphics; -using osuTK.Graphics; - -namespace osu.Game.Overlays.Changelog.Header -{ - public class BreadcrumbListing : Breadcrumb - { - private readonly ColourInfo badgeColour; - - public BreadcrumbListing(ColourInfo badgeColour) - : base(badgeColour, "Listing", false) - { - this.badgeColour = badgeColour; - Text.Font = Text.Font.With(weight: FontWeight.Bold); - Text.Anchor = Anchor.TopCentre; - Text.Origin = Anchor.TopCentre; - - AutoSizeAxes = Axes.None; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - Activate(); - Width = Text.DrawWidth; - } - - public override void Activate() - { - if (IsActivated) - return; - - base.Activate(); - SetTextColour(Color4.White, 100); - } - - public override void Deactivate() - { - if (!IsActivated) - return; - - base.Deactivate(); - SetTextColour(badgeColour, 100); - } - - protected override bool OnHover(HoverEvent e) - { - LineBadge.Uncollapse(); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - if (!IsActivated) - LineBadge.Collapse(); - base.OnHoverLost(e); - } - } -} diff --git a/osu.Game/Overlays/Changelog/Header/BreadcrumbRelease.cs b/osu.Game/Overlays/Changelog/Header/BreadcrumbRelease.cs deleted file mode 100644 index 43711af61b..0000000000 --- a/osu.Game/Overlays/Changelog/Header/BreadcrumbRelease.cs +++ /dev/null @@ -1,35 +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.Colour; -using osu.Game.Graphics; - -namespace osu.Game.Overlays.Changelog.Header -{ - public class BreadcrumbRelease : Breadcrumb - { - private const float transition_duration = 125; - - public BreadcrumbRelease(ColourInfo badgeColour, string displayText) - : base(badgeColour, displayText) - { - Text.Font = Text.Font.With(weight: FontWeight.Bold); - Text.Y = 20; - Text.Alpha = 0; - } - - public void ShowBuild(string displayText = null) - { - ShowText(transition_duration, displayText); - IsActivated = true; - } - - public override void Deactivate() - { - if (!IsActivated) - return; - - HideText(transition_duration); - } - } -} From 85a41cf6c3bf4cad37b8f06b9e84ffc36059051a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 17:36:29 +0900 Subject: [PATCH 0904/5608] Allow chaining of loadComponentSingleFile --- osu.Game/OsuGame.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index d108bb45f3..8cdddd6736 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.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; @@ -588,7 +588,7 @@ namespace osu.Game private Task asyncLoadStream; - private void loadComponentSingleFile(T d, Action add, bool cache = false) + private T loadComponentSingleFile(T d, Action add, bool cache = false) where T : Drawable { if (cache) @@ -636,6 +636,8 @@ namespace osu.Game } }); }); + + return d; } public bool OnPressed(GlobalAction action) From bc962bf8f0bf6db4660217163e7a85a601709606 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 May 2019 11:28:24 +0900 Subject: [PATCH 0905/5608] Move TooltipText to OsuClickableContainer --- osu.Game/Graphics/Containers/OsuClickableContainer.cs | 5 ++++- osu.Game/Online/Chat/DrawableLinkCompiler.cs | 5 +---- osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 7 ------- .../Profile/Header/Components/ProfileHeaderButton.cs | 5 +---- .../Overlays/Profile/Sections/BeatmapMetadataContainer.cs | 5 +---- osu.Game/Users/Avatar.cs | 5 ++--- 6 files changed, 9 insertions(+), 23 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuClickableContainer.cs b/osu.Game/Graphics/Containers/OsuClickableContainer.cs index e4d30cebb7..6dbe340efb 100644 --- a/osu.Game/Graphics/Containers/OsuClickableContainer.cs +++ b/osu.Game/Graphics/Containers/OsuClickableContainer.cs @@ -4,11 +4,12 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.Containers { - public class OsuClickableContainer : ClickableContainer + public class OsuClickableContainer : ClickableContainer, IHasTooltip { private readonly HoverSampleSet sampleSet; @@ -23,6 +24,8 @@ namespace osu.Game.Graphics.Containers this.sampleSet = sampleSet; } + public virtual string TooltipText { get; set; } + [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game/Online/Chat/DrawableLinkCompiler.cs b/osu.Game/Online/Chat/DrawableLinkCompiler.cs index d34ec8091c..d27a3fbffe 100644 --- a/osu.Game/Online/Chat/DrawableLinkCompiler.cs +++ b/osu.Game/Online/Chat/DrawableLinkCompiler.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics.Cursor; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -16,7 +15,7 @@ namespace osu.Game.Online.Chat /// /// An invisible drawable that brings multiple pieces together to form a consumable clickable link. /// - public class DrawableLinkCompiler : OsuHoverContainer, IHasTooltip + public class DrawableLinkCompiler : OsuHoverContainer { /// /// Each word part of a chat link (split for word-wrap support). @@ -40,8 +39,6 @@ namespace osu.Game.Online.Chat protected override IEnumerable EffectTargets => Parts; - public string TooltipText { get; set; } - private class LinkHoverSounds : HoverClickSounds { private readonly List parts; diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index abe954aa80..7331faa618 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -9,8 +9,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK; using osuTK.Graphics; -using osu.Game.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; @@ -129,10 +127,5 @@ namespace osu.Game.Overlays.BeatmapSet }; } } - - private class ClickableArea : OsuClickableContainer, IHasTooltip - { - public string TooltipText => @"View Profile"; - } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs index 1650f11523..ddcf011277 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -12,10 +11,8 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { - public abstract class ProfileHeaderButton : OsuHoverContainer, IHasTooltip + public abstract class ProfileHeaderButton : OsuHoverContainer { - public abstract string TooltipText { get; } - private readonly Box background; private readonly Container content; diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs index bb55816880..16326900f1 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -16,7 +15,7 @@ namespace osu.Game.Overlays.Profile.Sections /// /// Display artist/title/mapper information, commonly used as the left portion of a profile or score display row (see ). /// - public class BeatmapMetadataContainer : OsuHoverContainer, IHasTooltip + public class BeatmapMetadataContainer : OsuHoverContainer { private readonly BeatmapInfo beatmap; @@ -27,8 +26,6 @@ namespace osu.Game.Overlays.Profile.Sections TooltipText = $"{beatmap.Metadata.Artist} - {beatmap.Metadata.Title}"; } - public string TooltipText { get; } - [BackgroundDependencyLoader(true)] private void load(BeatmapSetOverlay beatmapSetOverlay) { diff --git a/osu.Game/Users/Avatar.cs b/osu.Game/Users/Avatar.cs index 3df5957ff9..8937f94768 100644 --- a/osu.Game/Users/Avatar.cs +++ b/osu.Game/Users/Avatar.cs @@ -6,7 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Events; @@ -72,9 +71,9 @@ namespace osu.Game.Users game?.ShowUser(user.Id); } - private class ClickableArea : OsuClickableContainer, IHasTooltip + private class ClickableArea : OsuClickableContainer { - public string TooltipText => Enabled.Value ? @"View Profile" : null; + public override string TooltipText => Enabled.Value ? @"View Profile" : null; protected override bool OnClick(ClickEvent e) { From 247dad7e86515e0872d62882de10fc996430b727 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 May 2019 15:58:40 +0900 Subject: [PATCH 0906/5608] Use OsuColour for profile overlay --- osu.Game/Graphics/OsuColour.cs | 10 ---------- .../Overlays/Profile/Header/BottomHeaderContainer.cs | 4 ++-- .../Overlays/Profile/Header/CentreHeaderContainer.cs | 2 +- .../Profile/Header/Components/ExpandDetailsButton.cs | 4 ++-- .../Overlays/Profile/Header/Components/RankGraph.cs | 4 ++-- .../Profile/Header/Components/SupporterIcon.cs | 2 +- .../Overlays/Profile/Header/DetailHeaderContainer.cs | 2 +- .../Overlays/Profile/Header/MedalHeaderContainer.cs | 2 +- osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs | 6 +++--- osu.Game/Overlays/Profile/ProfileHeader.cs | 4 ++-- 10 files changed, 15 insertions(+), 25 deletions(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index a73a8bcbc1..53693a1e38 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -136,15 +136,5 @@ namespace osu.Game.Graphics public readonly Color4 ChatBlue = FromHex(@"17292e"); public readonly Color4 ContextMenuGray = FromHex(@"223034"); - - public readonly Color4 CommunityUserGreenLight = FromHex(@"deff87"); - public readonly Color4 CommunityUserGreen = FromHex(@"05ffa2"); - public readonly Color4 CommunityUserGreenDark = FromHex(@"a6cc00"); - public readonly Color4 CommunityUserGrayGreenLighter = FromHex(@"9ebab1"); - public readonly Color4 CommunityUserGrayGreenLight = FromHex(@"77998e"); - public readonly Color4 CommunityUserGrayGreen = FromHex(@"4e7466"); - public readonly Color4 CommunityUserGrayGreenDark = FromHex(@"33413c"); - public readonly Color4 CommunityUserGrayGreenDarker = FromHex(@"2c3532"); - public readonly Color4 CommunityUserGrayGreenDarkest = FromHex(@"1e2422"); } } diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 633085960b..ffbb9ad218 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -35,14 +35,14 @@ namespace osu.Game.Overlays.Profile.Header [BackgroundDependencyLoader] private void load(OsuColour colours) { - iconColour = colours.CommunityUserGrayGreenLighter; + iconColour = colours.GreySeafoamLighter; InternalChildren = new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDarker, + Colour = colours.GreySeafoamDark, }, new FillFlowContainer { diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index b441775393..68fd77dd84 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Profile.Header new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDark + Colour = colours.GreySeafoam }, new FillFlowContainer { diff --git a/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs b/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs index 089228b2cd..46d24608ed 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs @@ -27,8 +27,8 @@ namespace osu.Game.Overlays.Profile.Header.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - IdleColour = colours.CommunityUserGrayGreen; - HoverColour = colours.CommunityUserGrayGreen.Darken(0.2f); + IdleColour = colours.GreySeafoamLight; + HoverColour = colours.GreySeafoamLight.Darken(0.2f); Child = icon = new SpriteIcon { diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 1dabf167e3..85ea2a175a 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -154,7 +154,7 @@ namespace osu.Game.Overlays.Profile.Header.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - ballBg.Colour = colours.CommunityUserGrayGreenDarkest; + ballBg.Colour = colours.GreySeafoamDarker; movingBall.BorderColour = colours.Yellow; movingBar.Colour = colours.Yellow; } @@ -249,7 +249,7 @@ namespace osu.Game.Overlays.Profile.Header.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - background.Colour = colours.CommunityUserGrayGreenDarker; + background.Colour = colours.GreySeafoamDark; } public void Refresh() diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index 97454d7327..c5e61f68f4 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -80,7 +80,7 @@ namespace osu.Game.Overlays.Profile.Header.Components private void load(OsuColour colours) { background.Colour = colours.Pink; - iconContainer.Colour = colours.CommunityUserGrayGreenDark; + iconContainer.Colour = colours.GreySeafoam; } } } diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index e41c90be45..f26cc360a2 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -65,7 +65,7 @@ namespace osu.Game.Overlays.Profile.Header new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDarkest, + Colour = colours.GreySeafoamDarker, }, fillFlow = new FillFlowContainer { diff --git a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs index 25d04195b2..67229a80c0 100644 --- a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Profile.Header new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDarkest, + Colour = colours.GreySeafoamDarker, }, new Container //artificial shadow { diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 2ac7f3cc96..6fe55e2368 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Profile.Header new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDarker, + Colour = colours.GreySeafoamDark, }, new FillFlowContainer { @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.X, Height = 1.5f, Margin = new MarginPadding { Top = 10 }, - Colour = colours.CommunityUserGrayGreenLighter, + Colour = colours.GreySeafoamLighter, }, new Container { @@ -125,7 +125,7 @@ namespace osu.Game.Overlays.Profile.Header Margin = new MarginPadding { Left = 40 }, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, - Colour = colours.CommunityUserGrayGreenLighter, + Colour = colours.GreySeafoamLighter, } } }, diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 2d8c47b11a..f2ac94b7ff 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -124,7 +124,7 @@ namespace osu.Game.Overlays.Profile [BackgroundDependencyLoader] private void load(OsuColour colours) { - infoTabControl.AccentColour = colours.CommunityUserGreen; + infoTabControl.AccentColour = colours.Seafoam; } public Bindable User = new Bindable(); @@ -145,7 +145,7 @@ namespace osu.Game.Overlays.Profile [BackgroundDependencyLoader] private void load(OsuColour colours) { - AccentColour = colours.CommunityUserGreen; + AccentColour = colours.Seafoam; } } } From 5a9c3ab9fa203d228a579c850c22e30ffd2af435 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 May 2019 18:02:13 +0900 Subject: [PATCH 0907/5608] Move UserProfileOverlay's header into an abstract implementation --- .../Online/TestSceneUserProfileHeader.cs | 2 +- osu.Game/Overlays/OverlayHeader.cs | 71 ++++++++ ...eaderTabControl.cs => HeaderTabControl.cs} | 12 +- osu.Game/Overlays/Profile/ProfileHeader.cs | 165 +++++++----------- 4 files changed, 142 insertions(+), 108 deletions(-) create mode 100644 osu.Game/Overlays/OverlayHeader.cs rename osu.Game/Overlays/Profile/Header/{ProfileHeaderTabControl.cs => HeaderTabControl.cs} (92%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index 14c81558c1..730140faed 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.Online typeof(ProfileHeader), typeof(RankGraph), typeof(LineGraph), - typeof(ProfileHeaderTabControl), + typeof(HeaderTabControl), typeof(CentreHeaderContainer), typeof(BottomHeaderContainer), typeof(DetailHeaderContainer), diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs new file mode 100644 index 0000000000..fe50d4a2be --- /dev/null +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -0,0 +1,71 @@ +// 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.UserInterface; +using osu.Game.Overlays.Profile.Header; + +namespace osu.Game.Overlays +{ + public abstract class OverlayHeader : Container + { + protected readonly HeaderTabControl TabControl; + + private const float cover_height = 150; + private const float cover_info_height = 75; + + protected OverlayHeader() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + Height = cover_height, + Masking = true, + Child = CreateBackground() + }, + new Container + { + Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, + Y = cover_height, + Height = cover_info_height, + RelativeSizeAxes = Axes.X, + Anchor = Anchor.TopLeft, + Origin = Anchor.BottomLeft, + Depth = -float.MaxValue, + Children = new Drawable[] + { + CreateTitle().With(t => t.X = -ScreenTitle.ICON_WIDTH), + TabControl = new HeaderTabControl + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = cover_info_height - 30, + Margin = new MarginPadding { Left = -UserProfileOverlay.CONTENT_X_MARGIN }, + Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN } + } + } + }, + new Container + { + Margin = new MarginPadding { Top = cover_height }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = CreateContent() + } + }; + } + + protected abstract Drawable CreateBackground(); + + protected abstract Drawable CreateContent(); + + protected abstract ScreenTitle CreateTitle(); + } +} diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs b/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs similarity index 92% rename from osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs rename to osu.Game/Overlays/Profile/Header/HeaderTabControl.cs index 3b16b102d5..1169ef7013 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs +++ b/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header { - public class ProfileHeaderTabControl : TabControl + public class HeaderTabControl : TabControl { private readonly Box bar; @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Profile.Header foreach (TabItem tabItem in TabContainer) { - ((ProfileHeaderTabItem)tabItem).AccentColour = value; + ((HeaderTabItem)tabItem).AccentColour = value; } } } @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.Profile.Header set => TabContainer.Padding = value; } - public ProfileHeaderTabControl() + public HeaderTabControl() { TabContainer.Masking = false; TabContainer.Spacing = new Vector2(15, 0); @@ -59,12 +59,12 @@ namespace osu.Game.Overlays.Profile.Header protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(string value) => new ProfileHeaderTabItem(value) + protected override TabItem CreateTabItem(string value) => new HeaderTabItem(value) { AccentColour = AccentColour }; - private class ProfileHeaderTabItem : TabItem + private class HeaderTabItem : TabItem { private readonly OsuSpriteText text; private readonly Drawable bar; @@ -86,7 +86,7 @@ namespace osu.Game.Overlays.Profile.Header } } - public ProfileHeaderTabItem(string value) + public HeaderTabItem(string value) : base(value) { AutoSizeAxes = Axes.X; diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index f2ac94b7ff..702bd6c2c4 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -15,124 +15,85 @@ using osu.Game.Users; namespace osu.Game.Overlays.Profile { - public class ProfileHeader : Container + public class ProfileHeader : OverlayHeader { - private readonly UserCoverBackground coverContainer; - private readonly ProfileHeaderTabControl infoTabControl; + private UserCoverBackground coverContainer; - private const float cover_height = 150; - private const float cover_info_height = 75; + public Bindable User = new Bindable(); + + private CentreHeaderContainer centreHeaderContainer; + private DetailHeaderContainer detailHeaderContainer; public ProfileHeader() { - CentreHeaderContainer centreHeaderContainer; - DetailHeaderContainer detailHeaderContainer; + User.ValueChanged += e => updateDisplay(e.NewValue); - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - Children = new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.X, - Height = cover_height, - Masking = true, - Children = new Drawable[] - { - coverContainer = new UserCoverBackground - { - RelativeSizeAxes = Axes.Both, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(OsuColour.FromHex("222").Opacity(0.8f), OsuColour.FromHex("222").Opacity(0.2f)) - }, - } - }, - new Container - { - Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, - Y = cover_height, - Height = cover_info_height, - RelativeSizeAxes = Axes.X, - Anchor = Anchor.TopLeft, - Origin = Anchor.BottomLeft, - Depth = -float.MaxValue, - Children = new Drawable[] - { - new ProfileHeaderTitle - { - X = -ScreenTitle.ICON_WIDTH, - }, - infoTabControl = new ProfileHeaderTabControl - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Height = cover_info_height - 30, - Margin = new MarginPadding { Left = -UserProfileOverlay.CONTENT_X_MARGIN }, - Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN } - } - } - }, - new FillFlowContainer - { - Margin = new MarginPadding { Top = cover_height }, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new TopHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - centreHeaderContainer = new CentreHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - detailHeaderContainer = new DetailHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - new MedalHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - new BottomHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - } - } - }; - - infoTabControl.AddItem("Info"); - infoTabControl.AddItem("Modding"); + TabControl.AddItem("Info"); + TabControl.AddItem("Modding"); centreHeaderContainer.DetailsVisible.BindValueChanged(visible => detailHeaderContainer.Expanded = visible.NewValue, true); - User.ValueChanged += e => updateDisplay(e.NewValue); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - infoTabControl.AccentColour = colours.Seafoam; + TabControl.AccentColour = colours.Seafoam; } - public Bindable User = new Bindable(); + protected override Drawable CreateBackground() => + new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + coverContainer = new UserCoverBackground + { + RelativeSizeAxes = Axes.Both, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(OsuColour.FromHex("222").Opacity(0.8f), OsuColour.FromHex("222").Opacity(0.2f)) + }, + } + }; - private void updateDisplay(User user) + protected override Drawable CreateContent() => new FillFlowContainer { - coverContainer.User = user; - } + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new TopHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + centreHeaderContainer = new CentreHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + detailHeaderContainer = new DetailHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + new MedalHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + new BottomHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + } + }; + + protected override ScreenTitle CreateTitle() => new ProfileHeaderTitle(); private class ProfileHeaderTitle : ScreenTitle { @@ -148,5 +109,7 @@ namespace osu.Game.Overlays.Profile AccentColour = colours.Seafoam; } } + + private void updateDisplay(User user) => coverContainer.User = user; } } From aba945934dceb67a30c89b6f07b2887bf497135f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 13:36:21 +0900 Subject: [PATCH 0908/5608] Move OverlayHeaderTabControl to correct namespace --- osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs | 3 ++- osu.Game/Overlays/OverlayHeader.cs | 5 ++--- .../HeaderTabControl.cs => OverlayHeaderTabControl.cs} | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) rename osu.Game/Overlays/{Profile/Header/HeaderTabControl.cs => OverlayHeaderTabControl.cs} (97%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index 730140faed..d9230090fc 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Overlays; using osu.Game.Overlays.Profile; using osu.Game.Overlays.Profile.Header; using osu.Game.Overlays.Profile.Header.Components; @@ -21,7 +22,7 @@ namespace osu.Game.Tests.Visual.Online typeof(ProfileHeader), typeof(RankGraph), typeof(LineGraph), - typeof(HeaderTabControl), + typeof(OverlayHeaderTabControl), typeof(CentreHeaderContainer), typeof(BottomHeaderContainer), typeof(DetailHeaderContainer), diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index fe50d4a2be..2e032db2ba 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -4,13 +4,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.UserInterface; -using osu.Game.Overlays.Profile.Header; namespace osu.Game.Overlays { public abstract class OverlayHeader : Container { - protected readonly HeaderTabControl TabControl; + protected readonly OverlayHeaderTabControl TabControl; private const float cover_height = 150; private const float cover_info_height = 75; @@ -41,7 +40,7 @@ namespace osu.Game.Overlays Children = new Drawable[] { CreateTitle().With(t => t.X = -ScreenTitle.ICON_WIDTH), - TabControl = new HeaderTabControl + TabControl = new OverlayHeaderTabControl { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, diff --git a/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs b/osu.Game/Overlays/OverlayHeaderTabControl.cs similarity index 97% rename from osu.Game/Overlays/Profile/Header/HeaderTabControl.cs rename to osu.Game/Overlays/OverlayHeaderTabControl.cs index 1169ef7013..0587a9bb2b 100644 --- a/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs +++ b/osu.Game/Overlays/OverlayHeaderTabControl.cs @@ -11,9 +11,9 @@ using osu.Game.Graphics.UserInterface; using osuTK; using osuTK.Graphics; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays { - public class HeaderTabControl : TabControl + public class OverlayHeaderTabControl : TabControl { private readonly Box bar; @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.Profile.Header set => TabContainer.Padding = value; } - public HeaderTabControl() + public OverlayHeaderTabControl() { TabContainer.Masking = false; TabContainer.Spacing = new Vector2(15, 0); From db817b3b2510385d11a46828892fa4b6f0cb6635 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 12:45:20 +0900 Subject: [PATCH 0909/5608] Set HeaderTabControl's default AccentColour to non-transparent Avoids items disappearing if no accent colour is set. --- osu.Game/Overlays/OverlayHeaderTabControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/OverlayHeaderTabControl.cs b/osu.Game/Overlays/OverlayHeaderTabControl.cs index 0587a9bb2b..21b42cfbf4 100644 --- a/osu.Game/Overlays/OverlayHeaderTabControl.cs +++ b/osu.Game/Overlays/OverlayHeaderTabControl.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays { private readonly Box bar; - private Color4 accentColour; + private Color4 accentColour = Color4.White; public Color4 AccentColour { From e3ae858c876cc5f7db899d8c78e609be6184e718 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 May 2019 14:01:41 +0900 Subject: [PATCH 0910/5608] Adjust testcase to avoid potential rounding issues --- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 42e421d1ad..d6259a1fdf 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -219,10 +219,10 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.That(controlPoints.SamplePointAt(2500).SampleBank, Is.EqualTo("normal")); Assert.That(controlPoints.SamplePointAt(3500).SampleBank, Is.EqualTo("drum")); - Assert.That(controlPoints.TimingPointAt(500).BeatLength, Is.EqualTo(500)); - Assert.That(controlPoints.TimingPointAt(1500).BeatLength, Is.EqualTo(500)); - Assert.That(controlPoints.TimingPointAt(2500).BeatLength, Is.EqualTo(250)); - Assert.That(controlPoints.TimingPointAt(3500).BeatLength, Is.EqualTo(500)); + Assert.That(controlPoints.TimingPointAt(500).BeatLength, Is.EqualTo(500).Within(0.1)); + Assert.That(controlPoints.TimingPointAt(1500).BeatLength, Is.EqualTo(500).Within(0.1)); + Assert.That(controlPoints.TimingPointAt(2500).BeatLength, Is.EqualTo(250).Within(0.1)); + Assert.That(controlPoints.TimingPointAt(3500).BeatLength, Is.EqualTo(500).Within(0.1)); } } From e7c8c4f787fac5005521a92a05ef5a3f805af4f8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 14:02:17 +0900 Subject: [PATCH 0911/5608] Fix incorrectly changed colour --- osu.Game/Graphics/OsuColour.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index d337455176..53693a1e38 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -77,7 +77,7 @@ namespace osu.Game.Graphics public readonly Color4 Seafoam = FromHex(@"05ffa2"); public readonly Color4 GreySeafoamLighter = FromHex(@"9ebab1"); - public readonly Color4 GreySeafoamLight = FromHex(@"4e7466"); + public readonly Color4 GreySeafoamLight = FromHex(@"4d7365"); public readonly Color4 GreySeafoam = FromHex(@"33413c"); public readonly Color4 GreySeafoamDark = FromHex(@"2c3532"); public readonly Color4 GreySeafoamDarker = FromHex(@"1e2422"); From a9447eaf7b2beee0e7f99589855dc39201303f71 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 14:02:34 +0900 Subject: [PATCH 0912/5608] Remove redundant prefixes --- osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs | 2 +- osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs index 36c9cc610f..40f1b791f9 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs @@ -42,7 +42,7 @@ namespace osu.Game.Online.API.Requests.Responses public APIChangelogBuild Previous { get; set; } } - public bool Equals(APIChangelogBuild other) => this.Id == other?.Id; + public bool Equals(APIChangelogBuild other) => Id == other?.Id; public override string ToString() => $"{UpdateStream.DisplayName} {DisplayVersion}"; } diff --git a/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs index 0c3fee88c7..ef204c7687 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs @@ -25,7 +25,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("latest_build")] public APIChangelogBuild LatestBuild { get; set; } - public bool Equals(APIUpdateStream other) => this.Id == other?.Id; + public bool Equals(APIUpdateStream other) => Id == other?.Id; public ColourInfo Colour { From 89e62c3d3025d743f187c4897e29709903897312 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 14:07:40 +0900 Subject: [PATCH 0913/5608] Only play OsuHoverContainer hover effect if action is present --- osu.Game/Graphics/Containers/OsuHoverContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index d5ae7cba57..b1fe1e81f1 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -22,7 +22,8 @@ namespace osu.Game.Graphics.Containers protected override bool OnHover(HoverEvent e) { - EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); + if (Action != null) + EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); return base.OnHover(e); } From 587e4bb5d54585428d4ba3fadbedf2790f4e85bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 11:13:36 +0900 Subject: [PATCH 0914/5608] Remove unnecessary getters from ScreenTitle --- osu.Game/Graphics/UserInterface/ScreenTitle.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index b9d9b5427d..18b79d9ec2 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -19,19 +19,16 @@ namespace osu.Game.Graphics.UserInterface protected IconUsage Icon { - get => iconSprite.Icon; set => iconSprite.Icon = value; } protected string Title { - get => titleText.Text; set => titleText.Text = value; } protected string Section { - get => pageText.Text; set => pageText.Text = value; } From e0da919fe920ad2688b2b95471dc76f30b8f38fa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 11:50:03 +0900 Subject: [PATCH 0915/5608] Allow custom icon specification in ScreenTitle Not all icons are available in fonts so IconUsage alone is not enough to cover all scenarios. --- .../Graphics/UserInterface/ScreenTitle.cs | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index 18b79d9ec2..fe1936d4e8 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -12,14 +13,24 @@ namespace osu.Game.Graphics.UserInterface { public abstract class ScreenTitle : CompositeDrawable, IHasAccentColour { - private readonly SpriteIcon iconSprite; + public const float ICON_WIDTH = ICON_SIZE + icon_spacing; + + protected const float ICON_SIZE = 25; + + private SpriteIcon iconSprite; private readonly OsuSpriteText titleText, pageText; - public const float ICON_WIDTH = icon_size + icon_spacing; - private const float icon_size = 25, icon_spacing = 10; + + private const float icon_spacing = 10; protected IconUsage Icon { - set => iconSprite.Icon = value; + set + { + if (iconSprite == null) + throw new InvalidOperationException($"Cannot use {nameof(Icon)} with a custom {nameof(CreateIcon)} function."); + + iconSprite.Icon = value; + } } protected string Title @@ -38,6 +49,11 @@ namespace osu.Game.Graphics.UserInterface set => pageText.Colour = value; } + protected virtual Drawable CreateIcon() => iconSprite = new SpriteIcon + { + Size = new Vector2(ICON_SIZE), + }; + protected ScreenTitle() { AutoSizeAxes = Axes.Both; @@ -48,12 +64,9 @@ namespace osu.Game.Graphics.UserInterface { AutoSizeAxes = Axes.Both, Spacing = new Vector2(icon_spacing, 0), - Children = new Drawable[] + Children = new[] { - iconSprite = new SpriteIcon - { - Size = new Vector2(icon_size), - }, + CreateIcon(), new FillFlowContainer { AutoSizeAxes = Axes.Both, From 4ac2acbfc0a969d9693c3bf62d3af7fd5f542956 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 14:13:52 +0900 Subject: [PATCH 0916/5608] Fix usages of SpriteText (instead of OsuSpriteText) --- osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs | 4 ++-- .../Visual/Background/TestSceneBackgroundScreenBeatmap.cs | 4 ++-- osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs | 3 ++- osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs | 4 ++-- osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs | 3 ++- osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs | 4 ++-- .../Visual/UserInterface/TestSceneNotificationOverlay.cs | 3 ++- osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs | 2 +- 8 files changed, 15 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index 0d143198dd..b2613a59d5 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs @@ -11,10 +11,10 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; @@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Mania.Tests content = new Container { RelativeSizeAxes = Axes.Both } } }, - new SpriteText + new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs index 10e3dc10c8..c9bdcf928f 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs @@ -9,7 +9,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Framework.Platform; @@ -19,6 +18,7 @@ using osu.Game.Configuration; using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; @@ -240,7 +240,7 @@ namespace osu.Game.Tests.Visual.Background { player.StoryboardEnabled.Value = false; player.ReplacesBackground.Value = false; - player.CurrentStoryboardContainer.Add(new SpriteText + player.CurrentStoryboardContainer.Add(new OsuSpriteText { Size = new Vector2(250, 50), Alpha = 1, diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs index 0c9e3fcd73..080a287b48 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs @@ -5,6 +5,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; +using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play.HUD; using osuTK; @@ -53,7 +54,7 @@ namespace osu.Game.Tests.Visual.Gameplay }; Add(stars); - SpriteText starsLabel = new SpriteText + SpriteText starsLabel = new OsuSpriteText { Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs index 7d6edd0d12..c7a0df6e9f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs @@ -7,9 +7,9 @@ using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Skinning; using osuTK.Graphics; @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.Gameplay Colour = Color4.Black, RelativeSizeAxes = Axes.Both, }, - new SpriteText + new OsuSpriteText { Font = OsuFont.Default.With(size: 40), Anchor = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs b/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs index d93daba4d4..364c986723 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; +using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; using osu.Game.Overlays.Chat.Tabs; using osu.Game.Users; @@ -61,7 +62,7 @@ namespace osu.Game.Tests.Visual.Online Anchor = Anchor.TopLeft, Children = new Drawable[] { - currentText = new SpriteText + currentText = new OsuSpriteText { Text = "Currently selected channel:" } diff --git a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs index 53ce25ebb3..a68fd0ef40 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs @@ -4,9 +4,9 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; using osu.Framework.Screens; using osu.Framework.Testing; +using osu.Game.Graphics.Sprites; using osu.Game.Screens; using osu.Game.Screens.Play; using osuTK.Graphics; @@ -54,7 +54,7 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - AddInternal(new SpriteText + AddInternal(new OsuSpriteText { Text = screenText, Colour = Color4.White, diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs index 0cb7c2484d..71033fcd2f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; +using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; @@ -40,7 +41,7 @@ namespace osu.Game.Tests.Visual.UserInterface Origin = Anchor.TopRight }); - SpriteText displayedCount = new SpriteText(); + SpriteText displayedCount = new OsuSpriteText(); Content.Add(displayedCount); diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index e70bf4c572..89da0fc254 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -83,7 +83,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, }, - date = new SpriteText + date = new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, From 7e38aabe7518e47ef3dd010c4f77241a424bfc5a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 May 2019 14:27:41 +0900 Subject: [PATCH 0917/5608] Remove equivalence check from controlpoint parsing --- .../Formats/LegacyBeatmapDecoderTest.cs | 57 ++++++++++++++++--- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 9 --- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index d6259a1fdf..5fd5fe342d 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -170,27 +170,66 @@ namespace osu.Game.Tests.Beatmaps.Formats var controlPoints = beatmap.ControlPointInfo; Assert.AreEqual(4, controlPoints.TimingPoints.Count); - var timingPoint = controlPoints.TimingPoints[0]; + Assert.AreEqual(42, controlPoints.DifficultyPoints.Count); + Assert.AreEqual(42, controlPoints.SamplePoints.Count); + Assert.AreEqual(42, controlPoints.EffectPoints.Count); + + var timingPoint = controlPoints.TimingPointAt(0); + Assert.AreEqual(956, timingPoint.Time); + Assert.AreEqual(329.67032967033, timingPoint.BeatLength); + Assert.AreEqual(TimeSignatures.SimpleQuadruple, timingPoint.TimeSignature); + + timingPoint = controlPoints.TimingPointAt(48428); Assert.AreEqual(956, timingPoint.Time); Assert.AreEqual(329.67032967033d, timingPoint.BeatLength); Assert.AreEqual(TimeSignatures.SimpleQuadruple, timingPoint.TimeSignature); - Assert.AreEqual(5, controlPoints.DifficultyPoints.Count); - var difficultyPoint = controlPoints.DifficultyPoints[0]; - Assert.AreEqual(116999, difficultyPoint.Time); - Assert.AreEqual(0.75000000000000189d, difficultyPoint.SpeedMultiplier); + timingPoint = controlPoints.TimingPointAt(119637); + Assert.AreEqual(119637, timingPoint.Time); + Assert.AreEqual(659.340659340659, timingPoint.BeatLength); + Assert.AreEqual(TimeSignatures.SimpleQuadruple, timingPoint.TimeSignature); - Assert.AreEqual(34, controlPoints.SamplePoints.Count); - var soundPoint = controlPoints.SamplePoints[0]; + var difficultyPoint = controlPoints.DifficultyPointAt(0); + Assert.AreEqual(0, difficultyPoint.Time); + Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); + + difficultyPoint = controlPoints.DifficultyPointAt(48428); + Assert.AreEqual(48428, difficultyPoint.Time); + Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); + + difficultyPoint = controlPoints.DifficultyPointAt(116999); + Assert.AreEqual(116999, difficultyPoint.Time); + Assert.AreEqual(0.75, difficultyPoint.SpeedMultiplier, 0.1); + + var soundPoint = controlPoints.SamplePointAt(0); Assert.AreEqual(956, soundPoint.Time); Assert.AreEqual("soft", soundPoint.SampleBank); Assert.AreEqual(60, soundPoint.SampleVolume); - Assert.AreEqual(8, controlPoints.EffectPoints.Count); - var effectPoint = controlPoints.EffectPoints[0]; + soundPoint = controlPoints.SamplePointAt(53373); + Assert.AreEqual(53373, soundPoint.Time); + Assert.AreEqual("soft", soundPoint.SampleBank); + Assert.AreEqual(60, soundPoint.SampleVolume); + + soundPoint = controlPoints.SamplePointAt(119637); + Assert.AreEqual(119637, soundPoint.Time); + Assert.AreEqual("soft", soundPoint.SampleBank); + Assert.AreEqual(80, soundPoint.SampleVolume); + + var effectPoint = controlPoints.EffectPointAt(0); + Assert.AreEqual(0, effectPoint.Time); + Assert.IsFalse(effectPoint.KiaiMode); + Assert.IsFalse(effectPoint.OmitFirstBarLine); + + effectPoint = controlPoints.EffectPointAt(53703); Assert.AreEqual(53703, effectPoint.Time); Assert.IsTrue(effectPoint.KiaiMode); Assert.IsFalse(effectPoint.OmitFirstBarLine); + + effectPoint = controlPoints.EffectPointAt(119637); + Assert.AreEqual(119637, effectPoint.Time); + Assert.IsFalse(effectPoint.KiaiMode); + Assert.IsFalse(effectPoint.OmitFirstBarLine); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index a5c3d8a4de..3cd425ea44 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -426,9 +426,6 @@ namespace osu.Game.Beatmaps.Formats { var existing = beatmap.ControlPointInfo.DifficultyPointAt(newPoint.Time); - if (newPoint.EquivalentTo(existing)) - return; - if (existing.Time == newPoint.Time) { // autogenerated points should not replace non-autogenerated. @@ -446,9 +443,6 @@ namespace osu.Game.Beatmaps.Formats { var existing = beatmap.ControlPointInfo.EffectPointAt(newPoint.Time); - if (newPoint.EquivalentTo(existing)) - return; - if (existing.Time == newPoint.Time) { // autogenerated points should not replace non-autogenerated. @@ -466,9 +460,6 @@ namespace osu.Game.Beatmaps.Formats { var existing = beatmap.ControlPointInfo.SamplePointAt(newPoint.Time); - if (newPoint.EquivalentTo(existing)) - return; - if (existing.Time == newPoint.Time) { // autogenerated points should not replace non-autogenerated. From 7a56fe84f20433063d811290c5afedb381cd7d5f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 May 2019 14:27:57 +0900 Subject: [PATCH 0918/5608] Remove ControlPoint.EquivalentTo --- osu.Game/Beatmaps/ControlPoints/ControlPoint.cs | 10 +--------- .../Beatmaps/ControlPoints/DifficultyControlPoint.cs | 10 +++++----- .../Beatmaps/ControlPoints/EffectControlPoint.cs | 12 ++++++------ .../Beatmaps/ControlPoints/SampleControlPoint.cs | 11 +++++------ .../Beatmaps/ControlPoints/TimingControlPoint.cs | 11 +++++------ osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 9 ++++----- 6 files changed, 26 insertions(+), 37 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 5e538126b3..abe7e5e803 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -19,15 +19,7 @@ namespace osu.Game.Beatmaps.ControlPoints public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); - /// - /// Whether this provides the same parametric changes as another . - /// Basically an equality check without considering the . - /// - /// The to compare to. - /// Whether this is equivalent to . - public virtual bool EquivalentTo(ControlPoint other) => true; - public bool Equals(ControlPoint other) - => EquivalentTo(other) && Time.Equals(other?.Time); + => Time.Equals(other?.Time); } } diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 013271d597..a3e3121575 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; namespace osu.Game.Beatmaps.ControlPoints { - public class DifficultyControlPoint : ControlPoint + public class DifficultyControlPoint : ControlPoint, IEquatable { /// /// The speed multiplier at this control point. @@ -18,9 +19,8 @@ namespace osu.Game.Beatmaps.ControlPoints private double speedMultiplier = 1; - public override bool EquivalentTo(ControlPoint other) - => base.EquivalentTo(other) - && other is DifficultyControlPoint difficulty - && SpeedMultiplier.Equals(difficulty.SpeedMultiplier); + public bool Equals(DifficultyControlPoint other) + => base.Equals(other) + && SpeedMultiplier.Equals(other?.SpeedMultiplier); } } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 3978b7b4b0..354d86dc13 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -1,9 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; + namespace osu.Game.Beatmaps.ControlPoints { - public class EffectControlPoint : ControlPoint + public class EffectControlPoint : ControlPoint, IEquatable { /// /// Whether this control point enables Kiai mode. @@ -15,10 +17,8 @@ namespace osu.Game.Beatmaps.ControlPoints /// public bool OmitFirstBarLine; - public override bool EquivalentTo(ControlPoint other) - => base.EquivalentTo(other) - && other is EffectControlPoint effect - && KiaiMode.Equals(effect.KiaiMode) - && OmitFirstBarLine.Equals(effect.OmitFirstBarLine); + public bool Equals(EffectControlPoint other) + => base.Equals(other) + && KiaiMode == other?.KiaiMode && OmitFirstBarLine == other.OmitFirstBarLine; } } diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 241ce90740..4c45bef862 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Game.Audio; namespace osu.Game.Beatmaps.ControlPoints { - public class SampleControlPoint : ControlPoint + public class SampleControlPoint : ControlPoint, IEquatable { public const string DEFAULT_BANK = "normal"; @@ -44,10 +45,8 @@ namespace osu.Game.Beatmaps.ControlPoints return newSampleInfo; } - public override bool EquivalentTo(ControlPoint other) - => base.EquivalentTo(other) - && other is SampleControlPoint sample - && SampleBank.Equals(sample.SampleBank) - && SampleVolume.Equals(sample.SampleVolume); + public bool Equals(SampleControlPoint other) + => base.Equals(other) + && string.Equals(SampleBank, other?.SampleBank) && SampleVolume == other?.SampleVolume; } } diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index 9ec27bdfdf..e5815a3f3b 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -1,12 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osu.Game.Beatmaps.Timing; namespace osu.Game.Beatmaps.ControlPoints { - public class TimingControlPoint : ControlPoint + public class TimingControlPoint : ControlPoint, IEquatable { /// /// The time signature at this control point. @@ -24,10 +25,8 @@ namespace osu.Game.Beatmaps.ControlPoints private double beatLength = 1000; - public override bool EquivalentTo(ControlPoint other) - => base.EquivalentTo(other) - && other is TimingControlPoint timing - && TimeSignature.Equals(timing.TimeSignature) - && BeatLength.Equals(timing.BeatLength); + public bool Equals(TimingControlPoint other) + => base.Equals(other) + && TimeSignature == other?.TimeSignature && beatLength.Equals(other.beatLength); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index ad5089958c..854d3b41d6 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -189,7 +189,7 @@ namespace osu.Game.Beatmaps.Formats Foreground = 3 } - internal class LegacySampleControlPoint : SampleControlPoint + internal class LegacySampleControlPoint : SampleControlPoint, IEquatable { public int CustomSampleBank; @@ -203,10 +203,9 @@ namespace osu.Game.Beatmaps.Formats return baseInfo; } - public override bool EquivalentTo(ControlPoint other) - => base.EquivalentTo(other) - && other is LegacySampleControlPoint legacy - && CustomSampleBank == legacy.CustomSampleBank; + public bool Equals(LegacySampleControlPoint other) + => base.Equals(other) + && CustomSampleBank == other?.CustomSampleBank; } } } From 24a7e624df1464eedd64b3c56bf999bb76c8f15a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 14:35:11 +0900 Subject: [PATCH 0919/5608] Only propagate badge value changes if not the current UpdateStream --- osu.Game/Overlays/ChangelogOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 34347d8e0a..daee91416c 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -94,7 +94,7 @@ namespace osu.Game.Overlays badges.Current.ValueChanged += e => { - if (e.NewValue != null) + if (e.NewValue?.LatestBuild != null && e.NewValue != Current.Value?.UpdateStream) ShowBuild(e.NewValue.LatestBuild); }; From a18e0b3b2faa0d94601021a688ee88efe09cb15b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 14:46:12 +0900 Subject: [PATCH 0920/5608] Fix test scene --- .../Visual/Online/TestSceneChangelogOverlay.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index c97ef384d3..2c941d4a48 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -41,7 +41,17 @@ namespace osu.Game.Tests.Visual.Online changelog.ShowBuild(new APIChangelogBuild { Version = "2018.712.0", + DisplayVersion = "2018.712.0", UpdateStream = new APIUpdateStream { Name = "lazer" }, + ChangelogEntries = new List() + { + new APIChangelogEntry + { + Category = "Test", + Title = "Title", + MessageHtml = "Message", + } + } }); changelog.Show(); }); From aed4634fe00fd91343bcff6701f84cfc85976814 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 May 2019 14:48:14 +0900 Subject: [PATCH 0921/5608] Consolidate loader animation tests --- .../Visual/Menus/TestSceneLoaderAnimation.cs | 32 ++----------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs index 813d4df708..000832b784 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs @@ -53,38 +53,12 @@ namespace osu.Game.Tests.Visual.Menus } [Test] - public void TestShortLoad() + public void TestDelayedLoad() { - bool logoVisible = false; - AddStep("begin loading", () => LoadScreen(loader = new TestLoader())); - AddWaitStep("wait", 3); - AddStep("finish loading", () => - { - logoVisible = loader.Logo?.Alpha > 0; - loader.AllowLoad.Set(); - }); - + AddUntilStep("wait for logo visible", () => loader.Logo?.Alpha > 0); + AddStep("finish loading", () => loader.AllowLoad.Set()); AddAssert("loaded", () => loader.Logo != null && loader.ScreenLoaded); - AddAssert("logo was visible", () => logoVisible); - AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0); - } - - [Test] - public void TestLongLoad() - { - bool logoVisible = false; - - AddStep("begin loading", () => LoadScreen(loader = new TestLoader())); - AddWaitStep("wait", 10); - AddStep("finish loading", () => - { - logoVisible = loader.Logo?.Alpha > 0; - loader.AllowLoad.Set(); - }); - - AddAssert("loaded", () => loader.Logo != null && loader.ScreenLoaded); - AddAssert("logo was visible", () => logoVisible); AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0); } From 5ed1540a12bac009c075e6cbd77744824d203acd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 15:02:31 +0900 Subject: [PATCH 0922/5608] Handle unhover state change better --- .../Graphics/Containers/OsuHoverContainer.cs | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index b1fe1e81f1..c4f85926ee 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -20,19 +20,41 @@ namespace osu.Game.Graphics.Containers protected virtual IEnumerable EffectTargets => new[] { Content }; + public OsuHoverContainer() + { + Enabled.ValueChanged += e => + { + if (!e.NewValue) unhover(); + }; + } + + private bool isHovered; + protected override bool OnHover(HoverEvent e) { - if (Action != null) - EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); + if (!Enabled.Value) + return false; + + EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); + isHovered = true; + return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - EffectTargets.ForEach(d => d.FadeColour(IdleColour, FADE_DURATION, Easing.OutQuint)); + unhover(); base.OnHoverLost(e); } + private void unhover() + { + if (!isHovered) return; + + isHovered = false; + EffectTargets.ForEach(d => d.FadeColour(IdleColour, FADE_DURATION, Easing.OutQuint)); + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { From 236b8cec279f4e415330e5d736b3e064984e05b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 15:31:36 +0900 Subject: [PATCH 0923/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e18f4b8771..98b158134d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index d947d0dfb9..b7549eeaef 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From e76d785c10542947a6ccf8773035b4ea6ee64319 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 May 2019 16:05:59 +0900 Subject: [PATCH 0924/5608] Move method above nested class --- osu.Game/Overlays/Profile/ProfileHeader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 702bd6c2c4..76613c156d 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -95,6 +95,8 @@ namespace osu.Game.Overlays.Profile protected override ScreenTitle CreateTitle() => new ProfileHeaderTitle(); + private void updateDisplay(User user) => coverContainer.User = user; + private class ProfileHeaderTitle : ScreenTitle { public ProfileHeaderTitle() @@ -109,7 +111,5 @@ namespace osu.Game.Overlays.Profile AccentColour = colours.Seafoam; } } - - private void updateDisplay(User user) => coverContainer.User = user; } } From 9e1f2d4fbcb3ab924f8b2a73c6314eb936688f48 Mon Sep 17 00:00:00 2001 From: Welsar55 Date: Tue, 21 May 2019 21:48:09 -0500 Subject: [PATCH 0925/5608] Added ability to reset all mods by pressing 1 as present on stable. --- osu.Game/Overlays/Mods/ModSection.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 50400e254f..f584eff0f9 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -57,7 +57,11 @@ namespace osu.Game.Overlays.Mods protected override bool OnKeyDown(KeyDownEvent e) { - if (ToggleKeys != null) + if(e.Key == Key.Number1) + { + DeselectAll(); + } + else if (ToggleKeys != null) { var index = Array.IndexOf(ToggleKeys, e.Key); if (index > -1 && index < buttons.Length) From 555822a68da554b9f3e63e4436f6b6e3d8189ab7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 May 2019 13:28:41 +0900 Subject: [PATCH 0926/5608] Remove unnecessary brackets --- osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 2c941d4a48..6db289efd7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Online Version = "2018.712.0", DisplayVersion = "2018.712.0", UpdateStream = new APIUpdateStream { Name = "lazer" }, - ChangelogEntries = new List() + ChangelogEntries = new List { new APIChangelogEntry { From 92c991494d8dab709e8adb9bacba8d7c86093811 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 May 2019 16:33:50 +0900 Subject: [PATCH 0927/5608] Fix (and rename) ExpandingBar --- ...eLineBadge.cs => TestSceneExpandingBar.cs} | 25 +++-- .../Graphics/UserInterface/ExpandingBar.cs | 101 ++++++++++++++++++ .../Changelog/Components/LineBadge.cs | 86 --------------- osu.Game/Overlays/Changelog/StreamBadge.cs | 16 +-- osu.Game/Overlays/OverlayHeaderTabControl.cs | 17 ++- 5 files changed, 129 insertions(+), 116 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{TestSceneLineBadge.cs => TestSceneExpandingBar.cs} (60%) create mode 100644 osu.Game/Graphics/UserInterface/ExpandingBar.cs delete mode 100644 osu.Game/Overlays/Changelog/Components/LineBadge.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLineBadge.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs similarity index 60% rename from osu.Game.Tests/Visual/UserInterface/TestSceneLineBadge.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs index 14e7b45ee6..974dbf0282 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLineBadge.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs @@ -4,17 +4,17 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Overlays.Changelog.Components; +using osu.Game.Graphics.UserInterface; using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLineBadge : OsuTestScene + public class TestSceneExpandingBar : OsuTestScene { - public TestSceneLineBadge() + public TestSceneExpandingBar() { Container container; - LineBadge lineBadge; + ExpandingBar expandingBar; Add(container = new Container { @@ -28,24 +28,23 @@ namespace osu.Game.Tests.Visual.UserInterface Alpha = 0.5f, RelativeSizeAxes = Axes.Both, }, - lineBadge = new LineBadge + expandingBar = new ExpandingBar { Anchor = Anchor.Centre, - UncollapsedSize = 10, + ExpandedSize = 10, CollapsedSize = 2, Colour = Color4.DeepSkyBlue, } } }); - AddStep(@"", () => { }); - AddStep(@"Collapse", () => lineBadge.Collapse()); - AddStep(@"Uncollapse", () => lineBadge.Uncollapse()); + AddStep(@"Collapse", () => expandingBar.Collapse()); + AddStep(@"Uncollapse", () => expandingBar.Expand()); AddSliderStep(@"Resize container", 1, 300, 150, value => container.ResizeTo(value)); - AddStep(@"Horizontal", () => lineBadge.IsHorizontal = true); - AddStep(@"Anchor top", () => lineBadge.Anchor = Anchor.TopCentre); - AddStep(@"Vertical", () => lineBadge.IsHorizontal = false); - AddStep(@"Anchor left", () => lineBadge.Anchor = Anchor.CentreLeft); + AddStep(@"Horizontal", () => expandingBar.RelativeSizeAxes = Axes.X); + AddStep(@"Anchor top", () => expandingBar.Anchor = Anchor.TopCentre); + AddStep(@"Vertical", () => expandingBar.RelativeSizeAxes = Axes.Y); + AddStep(@"Anchor left", () => expandingBar.Anchor = Anchor.CentreLeft); } } } diff --git a/osu.Game/Graphics/UserInterface/ExpandingBar.cs b/osu.Game/Graphics/UserInterface/ExpandingBar.cs new file mode 100644 index 0000000000..439a6002d8 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ExpandingBar.cs @@ -0,0 +1,101 @@ +// 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.Shapes; +using osuTK; + +namespace osu.Game.Graphics.UserInterface +{ + /// + /// A rounded bar which can be expanded or collapsed. + /// Generally used for tabs or breadcrumbs. + /// + public class ExpandingBar : Circle + { + private bool isCollapsed; + + public bool IsCollapsed + { + get => isCollapsed; + set + { + if (value == isCollapsed) + return; + + isCollapsed = value; + updateState(); + } + } + + private float expandedSize = 4; + + public float ExpandedSize + { + get => expandedSize; + set + { + if (value == expandedSize) + return; + + expandedSize = value; + updateState(); + } + } + + private float collapsedSize = 2; + + public float CollapsedSize + { + get => collapsedSize; + set + { + if (value == collapsedSize) + return; + + collapsedSize = value; + updateState(); + } + } + + public override Axes RelativeSizeAxes + { + get => base.RelativeSizeAxes; + set + { + base.RelativeSizeAxes = Axes.None; + Size = Vector2.Zero; + + base.RelativeSizeAxes = value; + updateState(); + } + } + + public ExpandingBar() + { + RelativeSizeAxes = Axes.X; + Origin = Anchor.Centre; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateState(); + } + + public void Collapse() => IsCollapsed = true; + + public void Expand() => IsCollapsed = false; + + private void updateState() + { + float newSize = IsCollapsed ? CollapsedSize : ExpandedSize; + Easing easingType = IsCollapsed ? Easing.Out : Easing.OutElastic; + + if (RelativeSizeAxes == Axes.X) + this.ResizeHeightTo(newSize, 400, easingType); + else + this.ResizeWidthTo(newSize, 400, easingType); + } + } +} diff --git a/osu.Game/Overlays/Changelog/Components/LineBadge.cs b/osu.Game/Overlays/Changelog/Components/LineBadge.cs deleted file mode 100644 index 84cd712eef..0000000000 --- a/osu.Game/Overlays/Changelog/Components/LineBadge.cs +++ /dev/null @@ -1,86 +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.Shapes; - -namespace osu.Game.Overlays.Changelog.Components -{ - /// - /// A simple rounded expandable line. Set its - /// property to the center of the edge it's meant stick with. By default, - /// takes up the full parent's axis defined by . - /// - public class LineBadge : Circle - { - public float UncollapsedSize; - public float CollapsedSize; - - public bool IsCollapsed { get; private set; } - private bool isHorizontal; - - /// - /// Automatically sets the RelativeSizeAxes and switches X and Y size components when changed. - /// - public bool IsHorizontal - { - get => isHorizontal; - set - { - if (value == isHorizontal) - return; - - if (IsLoaded) - { - FinishTransforms(); - var height = Height; - var width = Width; - RelativeSizeAxes = value ? Axes.X : Axes.Y; - Width = height; - Height = width; - } - else - RelativeSizeAxes = value ? Axes.X : Axes.Y; - - isHorizontal = value; - } - } - - /// Whether to initialize with the - /// or the . - public LineBadge(bool startCollapsed = true) - { - IsCollapsed = startCollapsed; - RelativeSizeAxes = Axes.X; - isHorizontal = true; - Origin = Anchor.Centre; - } - - protected override void LoadComplete() - { - if (isHorizontal) - Height = IsCollapsed ? CollapsedSize : UncollapsedSize; - else - Width = IsCollapsed ? CollapsedSize : UncollapsedSize; - base.LoadComplete(); - } - - public void Collapse(float transitionDuration = 400, Easing easing = Easing.Out) - { - IsCollapsed = true; - if (IsHorizontal) - this.ResizeHeightTo(CollapsedSize, transitionDuration, easing); - else - this.ResizeWidthTo(CollapsedSize, transitionDuration, easing); - } - - public void Uncollapse(float transitionDuration = 400, Easing easing = Easing.OutElastic) - { - IsCollapsed = false; - if (IsHorizontal) - this.ResizeHeightTo(UncollapsedSize, transitionDuration, easing); - else - this.ResizeWidthTo(UncollapsedSize, transitionDuration, easing); - } - } -} diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index bdddc1f968..e3c5cba496 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; using System; using osu.Game.Graphics.Sprites; -using osu.Game.Overlays.Changelog.Components; +using osu.Game.Graphics.UserInterface; using osuTK.Graphics; namespace osu.Game.Overlays.Changelog @@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Changelog private bool isActivated; - private readonly LineBadge lineBadge; + private readonly ExpandingBar expandingBar; private SampleChannel sampleClick; private SampleChannel sampleHover; @@ -71,11 +71,11 @@ namespace osu.Game.Overlays.Changelog }, } }, - lineBadge = new LineBadge(false) + expandingBar = new ExpandingBar { Anchor = Anchor.TopCentre, Colour = stream.Colour, - UncollapsedSize = 4, + ExpandedSize = 4, CollapsedSize = 2, }, }; @@ -87,7 +87,7 @@ namespace osu.Game.Overlays.Changelog { isActivated = true; this.FadeIn(transition_duration); - lineBadge.Uncollapse(); + expandingBar.Expand(); if (!withoutFiringUpdates) Selected?.Invoke(); } @@ -100,7 +100,7 @@ namespace osu.Game.Overlays.Changelog if (!IsHovered) { this.FadeTo(0.5f, transition_duration); - lineBadge.Collapse(200); + expandingBar.Collapse(); } } @@ -116,7 +116,7 @@ namespace osu.Game.Overlays.Changelog sampleHover?.Play(); DisableDim(); this.FadeIn(transition_duration); - lineBadge.Uncollapse(); + expandingBar.Expand(); return base.OnHover(e); } @@ -125,7 +125,7 @@ namespace osu.Game.Overlays.Changelog if (!isActivated) { this.FadeTo(0.5f, transition_duration); - lineBadge.Collapse(200); + expandingBar.Collapse(); } else EnableDim(); diff --git a/osu.Game/Overlays/OverlayHeaderTabControl.cs b/osu.Game/Overlays/OverlayHeaderTabControl.cs index 21b42cfbf4..dfe7e52420 100644 --- a/osu.Game/Overlays/OverlayHeaderTabControl.cs +++ b/osu.Game/Overlays/OverlayHeaderTabControl.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays private class HeaderTabItem : TabItem { private readonly OsuSpriteText text; - private readonly Drawable bar; + private readonly ExpandingBar bar; private Color4 accentColour; @@ -92,7 +92,7 @@ namespace osu.Game.Overlays AutoSizeAxes = Axes.X; RelativeSizeAxes = Axes.Y; - Children = new[] + Children = new Drawable[] { text = new OsuSpriteText { @@ -102,12 +102,11 @@ namespace osu.Game.Overlays Text = value, Font = OsuFont.GetFont() }, - bar = new Circle + bar = new ExpandingBar { - RelativeSizeAxes = Axes.X, - Height = 0, - Origin = Anchor.CentreLeft, - Anchor = Anchor.BottomLeft, + Anchor = Anchor.BottomCentre, + ExpandedSize = 7.5f, + CollapsedSize = 0 }, new HoverClickSounds() }; @@ -138,7 +137,7 @@ namespace osu.Game.Overlays if (Active.Value || IsHovered) { text.FadeColour(Color4.White, 120, Easing.InQuad); - bar.ResizeHeightTo(7.5f, 120, Easing.InQuad); + bar.Expand(); if (Active.Value) text.Font = text.Font.With(weight: FontWeight.Bold); @@ -146,7 +145,7 @@ namespace osu.Game.Overlays else { text.FadeColour(AccentColour, 120, Easing.InQuad); - bar.ResizeHeightTo(0, 120, Easing.InQuad); + bar.Collapse(); text.Font = text.Font.With(weight: FontWeight.Medium); } } From 1d5b7cdec0240dab30d65d24b10b490d54a76674 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 May 2019 16:44:47 +0900 Subject: [PATCH 0928/5608] Add ExpandingBar UI element --- .../UserInterface/TestSceneExpandingBar.cs | 50 +++++++++ .../Graphics/UserInterface/ExpandingBar.cs | 101 ++++++++++++++++++ osu.Game/Overlays/OverlayHeaderTabControl.cs | 17 ++- 3 files changed, 159 insertions(+), 9 deletions(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs create mode 100644 osu.Game/Graphics/UserInterface/ExpandingBar.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs new file mode 100644 index 0000000000..974dbf0282 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs @@ -0,0 +1,50 @@ +// 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.Shapes; +using osu.Game.Graphics.UserInterface; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneExpandingBar : OsuTestScene + { + public TestSceneExpandingBar() + { + Container container; + ExpandingBar expandingBar; + + Add(container = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Box + { + Colour = Color4.Gray, + Alpha = 0.5f, + RelativeSizeAxes = Axes.Both, + }, + expandingBar = new ExpandingBar + { + Anchor = Anchor.Centre, + ExpandedSize = 10, + CollapsedSize = 2, + Colour = Color4.DeepSkyBlue, + } + } + }); + + AddStep(@"Collapse", () => expandingBar.Collapse()); + AddStep(@"Uncollapse", () => expandingBar.Expand()); + AddSliderStep(@"Resize container", 1, 300, 150, value => container.ResizeTo(value)); + AddStep(@"Horizontal", () => expandingBar.RelativeSizeAxes = Axes.X); + AddStep(@"Anchor top", () => expandingBar.Anchor = Anchor.TopCentre); + AddStep(@"Vertical", () => expandingBar.RelativeSizeAxes = Axes.Y); + AddStep(@"Anchor left", () => expandingBar.Anchor = Anchor.CentreLeft); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/ExpandingBar.cs b/osu.Game/Graphics/UserInterface/ExpandingBar.cs new file mode 100644 index 0000000000..439a6002d8 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ExpandingBar.cs @@ -0,0 +1,101 @@ +// 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.Shapes; +using osuTK; + +namespace osu.Game.Graphics.UserInterface +{ + /// + /// A rounded bar which can be expanded or collapsed. + /// Generally used for tabs or breadcrumbs. + /// + public class ExpandingBar : Circle + { + private bool isCollapsed; + + public bool IsCollapsed + { + get => isCollapsed; + set + { + if (value == isCollapsed) + return; + + isCollapsed = value; + updateState(); + } + } + + private float expandedSize = 4; + + public float ExpandedSize + { + get => expandedSize; + set + { + if (value == expandedSize) + return; + + expandedSize = value; + updateState(); + } + } + + private float collapsedSize = 2; + + public float CollapsedSize + { + get => collapsedSize; + set + { + if (value == collapsedSize) + return; + + collapsedSize = value; + updateState(); + } + } + + public override Axes RelativeSizeAxes + { + get => base.RelativeSizeAxes; + set + { + base.RelativeSizeAxes = Axes.None; + Size = Vector2.Zero; + + base.RelativeSizeAxes = value; + updateState(); + } + } + + public ExpandingBar() + { + RelativeSizeAxes = Axes.X; + Origin = Anchor.Centre; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateState(); + } + + public void Collapse() => IsCollapsed = true; + + public void Expand() => IsCollapsed = false; + + private void updateState() + { + float newSize = IsCollapsed ? CollapsedSize : ExpandedSize; + Easing easingType = IsCollapsed ? Easing.Out : Easing.OutElastic; + + if (RelativeSizeAxes == Axes.X) + this.ResizeHeightTo(newSize, 400, easingType); + else + this.ResizeWidthTo(newSize, 400, easingType); + } + } +} diff --git a/osu.Game/Overlays/OverlayHeaderTabControl.cs b/osu.Game/Overlays/OverlayHeaderTabControl.cs index 21b42cfbf4..dfe7e52420 100644 --- a/osu.Game/Overlays/OverlayHeaderTabControl.cs +++ b/osu.Game/Overlays/OverlayHeaderTabControl.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays private class HeaderTabItem : TabItem { private readonly OsuSpriteText text; - private readonly Drawable bar; + private readonly ExpandingBar bar; private Color4 accentColour; @@ -92,7 +92,7 @@ namespace osu.Game.Overlays AutoSizeAxes = Axes.X; RelativeSizeAxes = Axes.Y; - Children = new[] + Children = new Drawable[] { text = new OsuSpriteText { @@ -102,12 +102,11 @@ namespace osu.Game.Overlays Text = value, Font = OsuFont.GetFont() }, - bar = new Circle + bar = new ExpandingBar { - RelativeSizeAxes = Axes.X, - Height = 0, - Origin = Anchor.CentreLeft, - Anchor = Anchor.BottomLeft, + Anchor = Anchor.BottomCentre, + ExpandedSize = 7.5f, + CollapsedSize = 0 }, new HoverClickSounds() }; @@ -138,7 +137,7 @@ namespace osu.Game.Overlays if (Active.Value || IsHovered) { text.FadeColour(Color4.White, 120, Easing.InQuad); - bar.ResizeHeightTo(7.5f, 120, Easing.InQuad); + bar.Expand(); if (Active.Value) text.Font = text.Font.With(weight: FontWeight.Bold); @@ -146,7 +145,7 @@ namespace osu.Game.Overlays else { text.FadeColour(AccentColour, 120, Easing.InQuad); - bar.ResizeHeightTo(0, 120, Easing.InQuad); + bar.Collapse(); text.Font = text.Font.With(weight: FontWeight.Medium); } } From 9f9e86f18c92d65773714532180fc0cb566bf67b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 May 2019 17:04:21 +0900 Subject: [PATCH 0929/5608] Rename classes and fix back-to-front state --- .../Visual/Online/TestSceneChangelogOverlay.cs | 2 +- osu.Game/Overlays/Changelog/StreamBadge.cs | 1 + .../{BadgeDisplay.cs => StreamBadgeArea.cs} | 4 ++-- osu.Game/Overlays/ChangelogOverlay.cs | 12 ++++++------ 4 files changed, 10 insertions(+), 9 deletions(-) rename osu.Game/Overlays/Changelog/{BadgeDisplay.cs => StreamBadgeArea.cs} (96%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 6db289efd7..2e8e05fb0f 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.Online public override IReadOnlyList RequiredTypes => new[] { - typeof(BadgeDisplay), + typeof(StreamBadgeArea), typeof(StreamBadge), typeof(ChangelogHeader), typeof(ChangelogContent), diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/StreamBadge.cs index e3c5cba496..ef1dda5b41 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/StreamBadge.cs @@ -77,6 +77,7 @@ namespace osu.Game.Overlays.Changelog Colour = stream.Colour, ExpandedSize = 4, CollapsedSize = 2, + IsCollapsed = true }, }; } diff --git a/osu.Game/Overlays/Changelog/BadgeDisplay.cs b/osu.Game/Overlays/Changelog/StreamBadgeArea.cs similarity index 96% rename from osu.Game/Overlays/Changelog/BadgeDisplay.cs rename to osu.Game/Overlays/Changelog/StreamBadgeArea.cs index 9b0f152eb0..9d8fc6773d 100644 --- a/osu.Game/Overlays/Changelog/BadgeDisplay.cs +++ b/osu.Game/Overlays/Changelog/StreamBadgeArea.cs @@ -12,7 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { - public class BadgeDisplay : CompositeDrawable + public class StreamBadgeArea : CompositeDrawable { private const float vertical_padding = 20; private const float horizontal_padding = 85; @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Changelog private readonly FillFlowContainer badgesContainer; - public BadgeDisplay() + public StreamBadgeArea() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index daee91416c..4fea4bd220 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays { private ChangelogHeader header; - private BadgeDisplay badges; + private StreamBadgeArea streamBadges; private Container content; @@ -81,7 +81,7 @@ namespace osu.Game.Overlays { ListingSelected = ShowListing, }, - badges = new BadgeDisplay(), + streamBadges = new StreamBadgeArea(), content = new Container { RelativeSizeAxes = Axes.X, @@ -92,7 +92,7 @@ namespace osu.Game.Overlays }, }; - badges.Current.ValueChanged += e => + streamBadges.Current.ValueChanged += e => { if (e.NewValue?.LatestBuild != null && e.NewValue != Current.Value?.UpdateStream) ShowBuild(e.NewValue.LatestBuild); @@ -106,13 +106,13 @@ namespace osu.Game.Overlays { if (e.NewValue != null) { - badges.Current.Value = e.NewValue.UpdateStream; + streamBadges.Current.Value = e.NewValue.UpdateStream; loadContent(new ChangelogSingleBuild(e.NewValue)); } else { - badges.Current.Value = null; + streamBadges.Current.Value = null; loadContent(new ChangelogListing(builds)); } }); @@ -161,7 +161,7 @@ namespace osu.Game.Overlays res.Streams.ForEach(s => s.LatestBuild.UpdateStream = res.Streams.Find(s2 => s2.Id == s.LatestBuild.UpdateStream.Id)); builds = res.Builds; - badges.Populate(res.Streams); + streamBadges.Populate(res.Streams); Current.TriggerChange(); }; From b588638740470bdc97668a9a96bea58aa5f1590b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 May 2019 19:51:16 +0900 Subject: [PATCH 0930/5608] Use TabControl instead of custom logic --- .../Online/TestSceneChangelogOverlay.cs | 4 +- .../Overlays/Changelog/StreamBadgeArea.cs | 83 ------------------- .../{StreamBadge.cs => UpdateStreamBadge.cs} | 35 ++------ .../Changelog/UpdateStreamBadgeArea.cs | 80 ++++++++++++++++++ osu.Game/Overlays/ChangelogOverlay.cs | 12 +-- 5 files changed, 97 insertions(+), 117 deletions(-) delete mode 100644 osu.Game/Overlays/Changelog/StreamBadgeArea.cs rename osu.Game/Overlays/Changelog/{StreamBadge.cs => UpdateStreamBadge.cs} (82%) create mode 100644 osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 2e8e05fb0f..d1a7730bee 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -17,8 +17,8 @@ namespace osu.Game.Tests.Visual.Online public override IReadOnlyList RequiredTypes => new[] { - typeof(StreamBadgeArea), - typeof(StreamBadge), + typeof(UpdateStreamBadgeArea), + typeof(UpdateStreamBadge), typeof(ChangelogHeader), typeof(ChangelogContent), typeof(ChangelogListing), diff --git a/osu.Game/Overlays/Changelog/StreamBadgeArea.cs b/osu.Game/Overlays/Changelog/StreamBadgeArea.cs deleted file mode 100644 index 9d8fc6773d..0000000000 --- a/osu.Game/Overlays/Changelog/StreamBadgeArea.cs +++ /dev/null @@ -1,83 +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.Shapes; -using osu.Framework.Input.Events; -using osu.Game.Online.API.Requests.Responses; -using System.Collections.Generic; -using osu.Framework.Bindables; -using osuTK.Graphics; - -namespace osu.Game.Overlays.Changelog -{ - public class StreamBadgeArea : CompositeDrawable - { - private const float vertical_padding = 20; - private const float horizontal_padding = 85; - - public readonly Bindable Current = new Bindable(); - - private readonly FillFlowContainer badgesContainer; - - public StreamBadgeArea() - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - InternalChildren = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = new Color4(32, 24, 35, 255), - }, - badgesContainer = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Vertical = vertical_padding, Horizontal = horizontal_padding }, - }, - }; - - Current.ValueChanged += e => - { - foreach (StreamBadge streamBadge in badgesContainer) - { - if (!IsHovered || e.NewValue.Id == streamBadge.Stream.Id) - streamBadge.Activate(); - else - streamBadge.Deactivate(); - } - }; - } - - public void Populate(List streams) - { - Current.Value = null; - - foreach (APIUpdateStream updateStream in streams) - { - var streamBadge = new StreamBadge(updateStream); - streamBadge.Selected += () => Current.Value = updateStream; - badgesContainer.Add(streamBadge); - } - } - - protected override bool OnHover(HoverEvent e) - { - foreach (StreamBadge streamBadge in badgesContainer.Children) - streamBadge.EnableDim(); - - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - foreach (StreamBadge streamBadge in badgesContainer.Children) - streamBadge.DisableDim(); - - base.OnHoverLost(e); - } - } -} diff --git a/osu.Game/Overlays/Changelog/StreamBadge.cs b/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs similarity index 82% rename from osu.Game/Overlays/Changelog/StreamBadge.cs rename to osu.Game/Overlays/Changelog/UpdateStreamBadge.cs index ef1dda5b41..9500f080e7 100644 --- a/osu.Game/Overlays/Changelog/StreamBadge.cs +++ b/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs @@ -10,35 +10,30 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; -using System; +using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osuTK.Graphics; namespace osu.Game.Overlays.Changelog { - public class StreamBadge : ClickableContainer + public class UpdateStreamBadge : TabItem { private const float badge_height = 66.5f; private const float badge_width = 100; private const float transition_duration = 100; - public event Action Selected; - - private bool isActivated; + private readonly bool isActivated; private readonly ExpandingBar expandingBar; private SampleChannel sampleClick; private SampleChannel sampleHover; - public readonly APIUpdateStream Stream; - private readonly FillFlowContainer text; - public StreamBadge(APIUpdateStream stream) + public UpdateStreamBadge(APIUpdateStream stream) + : base(stream) { - Stream = stream; - Height = badge_height; Width = stream.IsFeatured ? badge_width * 2 : badge_width; Padding = new MarginPadding(5); @@ -82,32 +77,20 @@ namespace osu.Game.Overlays.Changelog }; } - /// In case we don't want to - /// fire the event. - public void Activate(bool withoutFiringUpdates = true) + protected override void OnActivated() { - isActivated = true; this.FadeIn(transition_duration); expandingBar.Expand(); - if (!withoutFiringUpdates) - Selected?.Invoke(); } - public void Deactivate() + protected override void OnDeactivated() { - isActivated = false; - DisableDim(); - - if (!IsHovered) - { - this.FadeTo(0.5f, transition_duration); - expandingBar.Collapse(); - } + this.FadeTo(0.5f, transition_duration); + expandingBar.Collapse(); } protected override bool OnClick(ClickEvent e) { - Activate(false); sampleClick?.Play(); return base.OnClick(e); } diff --git a/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs b/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs new file mode 100644 index 0000000000..4d357ed944 --- /dev/null +++ b/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs @@ -0,0 +1,80 @@ +// 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.Input.Events; +using osu.Game.Online.API.Requests.Responses; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Changelog +{ + public class UpdateStreamBadgeArea : TabControl + { + private const float vertical_padding = 20; + private const float horizontal_padding = 85; + + public UpdateStreamBadgeArea() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + AddInternal(new Box + { + Colour = Color4.Black, + Alpha = 0.12f, + RelativeSizeAxes = Axes.Both, + }); + } + + public void Populate(List streams) + { + Current.Value = null; + + foreach (APIUpdateStream updateStream in streams) + { + AddItem(updateStream); + } + } + + protected override bool OnHover(HoverEvent e) + { + foreach (UpdateStreamBadge streamBadge in TabContainer.Children.OfType()) + streamBadge.EnableDim(); + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + foreach (UpdateStreamBadge streamBadge in TabContainer.Children.OfType()) + streamBadge.DisableDim(); + + base.OnHoverLost(e); + } + + protected override TabFillFlowContainer CreateTabFlow() + { + var flow = base.CreateTabFlow(); + + flow.RelativeSizeAxes = Axes.X; + flow.AutoSizeAxes = Axes.Y; + flow.AllowMultiline = true; + flow.Padding = new MarginPadding + { + Vertical = vertical_padding, + Horizontal = horizontal_padding, + }; + + return flow; + } + + protected override Dropdown CreateDropdown() => null; + + protected override TabItem CreateTabItem(APIUpdateStream value) => + new UpdateStreamBadge(value); + } +} diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 4fea4bd220..6176e93609 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays { private ChangelogHeader header; - private StreamBadgeArea streamBadges; + private UpdateStreamBadgeArea updateStreamBadges; private Container content; @@ -81,7 +81,7 @@ namespace osu.Game.Overlays { ListingSelected = ShowListing, }, - streamBadges = new StreamBadgeArea(), + updateStreamBadges = new UpdateStreamBadgeArea(), content = new Container { RelativeSizeAxes = Axes.X, @@ -92,7 +92,7 @@ namespace osu.Game.Overlays }, }; - streamBadges.Current.ValueChanged += e => + updateStreamBadges.Current.ValueChanged += e => { if (e.NewValue?.LatestBuild != null && e.NewValue != Current.Value?.UpdateStream) ShowBuild(e.NewValue.LatestBuild); @@ -106,13 +106,13 @@ namespace osu.Game.Overlays { if (e.NewValue != null) { - streamBadges.Current.Value = e.NewValue.UpdateStream; + updateStreamBadges.Current.Value = e.NewValue.UpdateStream; loadContent(new ChangelogSingleBuild(e.NewValue)); } else { - streamBadges.Current.Value = null; + updateStreamBadges.Current.Value = null; loadContent(new ChangelogListing(builds)); } }); @@ -161,7 +161,7 @@ namespace osu.Game.Overlays res.Streams.ForEach(s => s.LatestBuild.UpdateStream = res.Streams.Find(s2 => s2.Id == s.LatestBuild.UpdateStream.Id)); builds = res.Builds; - streamBadges.Populate(res.Streams); + updateStreamBadges.Populate(res.Streams); Current.TriggerChange(); }; From 66f5dbaa9f2f4fea5eaa6870aa57f3fb10f983cf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 May 2019 23:44:37 +0900 Subject: [PATCH 0931/5608] Fix badge state regressions from tab control usage --- .../Overlays/Changelog/UpdateStreamBadge.cs | 134 ++++++++++-------- .../Changelog/UpdateStreamBadgeArea.cs | 9 +- 2 files changed, 79 insertions(+), 64 deletions(-) diff --git a/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs b/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs index 9500f080e7..925412f94d 100644 --- a/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs +++ b/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -23,71 +24,70 @@ namespace osu.Game.Overlays.Changelog private const float badge_width = 100; private const float transition_duration = 100; - private readonly bool isActivated; - private readonly ExpandingBar expandingBar; private SampleChannel sampleClick; private SampleChannel sampleHover; private readonly FillFlowContainer text; + public readonly Bindable SelectedTab = new Bindable(); + + private readonly Container fadeContainer; + public UpdateStreamBadge(APIUpdateStream stream) : base(stream) { Height = badge_height; Width = stream.IsFeatured ? badge_width * 2 : badge_width; Padding = new MarginPadding(5); - isActivated = true; - Children = new Drawable[] + Child = fadeContainer = new Container { - text = new FillFlowContainer + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new[] + text = new FillFlowContainer { - new OsuSpriteText + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new[] { - Text = stream.DisplayName, - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12), - Margin = new MarginPadding { Top = 6 }, - }, - new OsuSpriteText - { - Text = stream.LatestBuild.DisplayVersion, - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 16), - }, - new OsuSpriteText - { - Text = stream.LatestBuild.Users > 0 ? $"{stream.LatestBuild.Users:N0} users online" : null, - Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 10), - Colour = new Color4(203, 164, 218, 255), - }, - } - }, - expandingBar = new ExpandingBar - { - Anchor = Anchor.TopCentre, - Colour = stream.Colour, - ExpandedSize = 4, - CollapsedSize = 2, - IsCollapsed = true - }, + new OsuSpriteText + { + Text = stream.DisplayName, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12), + Margin = new MarginPadding { Top = 6 }, + }, + new OsuSpriteText + { + Text = stream.LatestBuild.DisplayVersion, + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 16), + }, + new OsuSpriteText + { + Text = stream.LatestBuild.Users > 0 ? $"{stream.LatestBuild.Users:N0} users online" : null, + Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 10), + Colour = new Color4(203, 164, 218, 255), + }, + } + }, + expandingBar = new ExpandingBar + { + Anchor = Anchor.TopCentre, + Colour = stream.Colour, + ExpandedSize = 4, + CollapsedSize = 2, + IsCollapsed = true + }, + } }; + + SelectedTab.ValueChanged += _ => updateState(); } - protected override void OnActivated() - { - this.FadeIn(transition_duration); - expandingBar.Expand(); - } + protected override void OnActivated() => updateState(); - protected override void OnDeactivated() - { - this.FadeTo(0.5f, transition_duration); - expandingBar.Collapse(); - } + protected override void OnDeactivated() => updateState(); protected override bool OnClick(ClickEvent e) { @@ -98,28 +98,46 @@ namespace osu.Game.Overlays.Changelog protected override bool OnHover(HoverEvent e) { sampleHover?.Play(); - DisableDim(); - this.FadeIn(transition_duration); - expandingBar.Expand(); + updateState(); + return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - if (!isActivated) - { - this.FadeTo(0.5f, transition_duration); - expandingBar.Collapse(); - } - else - EnableDim(); - + updateState(); base.OnHoverLost(e); } - public void EnableDim() => text.FadeTo(0.5f, transition_duration); + private void updateState() + { + if (Active.Value || IsHovered || SelectedTab.Value == null) + { + expandingBar.Expand(); + fadeContainer.FadeTo(1, transition_duration); + } + else + { + expandingBar.Collapse(); + fadeContainer.FadeTo(0.5f, transition_duration); + } - public void DisableDim() => text.FadeIn(transition_duration); + text.FadeTo(externalDimRequested && !IsHovered ? 0.5f : 1, transition_duration); + } + + private bool externalDimRequested; + + public void EnableDim() + { + externalDimRequested = true; + updateState(); + } + + public void DisableDim() + { + externalDimRequested = false; + updateState(); + } [BackgroundDependencyLoader] private void load(AudioManager audio) diff --git a/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs b/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs index 4d357ed944..925be48cd1 100644 --- a/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs +++ b/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs @@ -14,9 +14,6 @@ namespace osu.Game.Overlays.Changelog { public class UpdateStreamBadgeArea : TabControl { - private const float vertical_padding = 20; - private const float horizontal_padding = 85; - public UpdateStreamBadgeArea() { RelativeSizeAxes = Axes.X; @@ -65,8 +62,8 @@ namespace osu.Game.Overlays.Changelog flow.AllowMultiline = true; flow.Padding = new MarginPadding { - Vertical = vertical_padding, - Horizontal = horizontal_padding, + Vertical = 20, + Horizontal = 85, }; return flow; @@ -75,6 +72,6 @@ namespace osu.Game.Overlays.Changelog protected override Dropdown CreateDropdown() => null; protected override TabItem CreateTabItem(APIUpdateStream value) => - new UpdateStreamBadge(value); + new UpdateStreamBadge(value) { SelectedTab = { BindTarget = Current } }; } } From 661fc01e7d88920f8e6cc62f9052d577d3d5234e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 May 2019 23:49:54 +0900 Subject: [PATCH 0932/5608] Fix date string --- osu.Game/Overlays/Changelog/ChangelogListing.cs | 4 +--- osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogListing.cs b/osu.Game/Overlays/Changelog/ChangelogListing.cs index ebfcf76738..20b7a32eba 100644 --- a/osu.Game/Overlays/Changelog/ChangelogListing.cs +++ b/osu.Game/Overlays/Changelog/ChangelogListing.cs @@ -46,9 +46,7 @@ namespace osu.Game.Overlays.Changelog Add(new OsuSpriteText { - // do we need .ToUniversalTime() here? - // also, this should be a temporary solution to weekdays in >localized< date strings - Text = build.CreatedAt.Date.ToLongDateString().Replace(build.CreatedAt.ToString("dddd") + ", ", ""), + Text = build.CreatedAt.Date.ToString("dd MMM yyyy"), Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 24), Colour = OsuColour.FromHex(@"FD5"), Anchor = Anchor.TopCentre, diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index 50a7946ee7..98fe68c015 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -73,9 +73,7 @@ namespace osu.Game.Overlays.Changelog existing.Add(new OsuSpriteText { - // do we need .ToUniversalTime() here? - // also, this should be a temporary solution to weekdays in >localized< date strings - Text = Build.CreatedAt.Date.ToLongDateString().Replace(Build.CreatedAt.ToString("dddd") + ", ", ""), + Text = Build.CreatedAt.Date.ToString("dd MMM yyyy"), Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 14), Colour = OsuColour.FromHex(@"FD5"), Anchor = Anchor.BottomCentre, From 81e42041e6fab9e336a2f5f18601335d613a3a3f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 May 2019 23:56:50 +0900 Subject: [PATCH 0933/5608] Move update streams inside header content --- osu.Game/Overlays/Changelog/ChangelogHeader.cs | 16 ++++++++++++++-- osu.Game/Overlays/ChangelogOverlay.cs | 18 +----------------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index ccc976c4dc..9be6eef295 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -22,6 +22,8 @@ namespace osu.Game.Overlays.Changelog public Action ListingSelected; + public UpdateStreamBadgeArea Streams; + private const string listing_string = "Listing"; public ChangelogHeader() @@ -34,6 +36,12 @@ namespace osu.Game.Overlays.Changelog }; Current.ValueChanged += showBuild; + + Streams.Current.ValueChanged += e => + { + if (e.NewValue?.LatestBuild != null && e.NewValue != Current.Value?.UpdateStream) + Current.Value = e.NewValue.LatestBuild; + }; } [BackgroundDependencyLoader] @@ -54,11 +62,14 @@ namespace osu.Game.Overlays.Changelog TabControl.AddItem(e.NewValue.ToString()); TabControl.Current.Value = e.NewValue.ToString(); + Streams.Current.Value = e.NewValue.UpdateStream; + title.Version = e.NewValue.UpdateStream.DisplayName; } else { TabControl.Current.Value = listing_string; + Streams.Current.Value = null; title.Version = null; } } @@ -67,10 +78,11 @@ namespace osu.Game.Overlays.Changelog protected override Drawable CreateContent() => new Container { - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Children = new Drawable[] { - // todo: move badge display here + Streams = new UpdateStreamBadgeArea(), } }; diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 6176e93609..865c6b8de2 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -26,8 +26,6 @@ namespace osu.Game.Overlays { private ChangelogHeader header; - private UpdateStreamBadgeArea updateStreamBadges; - private Container content; private SampleChannel sampleBack; @@ -81,7 +79,6 @@ namespace osu.Game.Overlays { ListingSelected = ShowListing, }, - updateStreamBadges = new UpdateStreamBadgeArea(), content = new Container { RelativeSizeAxes = Axes.X, @@ -92,12 +89,6 @@ namespace osu.Game.Overlays }, }; - updateStreamBadges.Current.ValueChanged += e => - { - if (e.NewValue?.LatestBuild != null && e.NewValue != Current.Value?.UpdateStream) - ShowBuild(e.NewValue.LatestBuild); - }; - sampleBack = audio.Sample.Get(@"UI/generic-select-soft"); header.Current.BindTo(Current); @@ -105,16 +96,9 @@ namespace osu.Game.Overlays Current.BindValueChanged(e => { if (e.NewValue != null) - { - updateStreamBadges.Current.Value = e.NewValue.UpdateStream; - loadContent(new ChangelogSingleBuild(e.NewValue)); - } else - { - updateStreamBadges.Current.Value = null; loadContent(new ChangelogListing(builds)); - } }); } @@ -161,7 +145,7 @@ namespace osu.Game.Overlays res.Streams.ForEach(s => s.LatestBuild.UpdateStream = res.Streams.Find(s2 => s2.Id == s.LatestBuild.UpdateStream.Id)); builds = res.Builds; - updateStreamBadges.Populate(res.Streams); + header.Streams.Populate(res.Streams); Current.TriggerChange(); }; From ba98c68cbd2c017927d35790350dec0031f16377 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 May 2019 00:11:26 +0900 Subject: [PATCH 0934/5608] Add support for osu! user links --- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 09706a419e..2a207efe01 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; using System.Text.RegularExpressions; using osu.Game.Graphics.Sprites; +using osu.Game.Users; using osuTK.Graphics; namespace osu.Game.Overlays.Changelog @@ -84,18 +85,21 @@ namespace osu.Game.Overlays.Changelog if (!string.IsNullOrEmpty(entry.Repository)) { title.AddText(" (", t => t.Font = OsuFont.GetFont(size: 18)); - title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", - entry.GithubUrl, Online.Chat.LinkAction.External, null, - null, t => { t.Font = OsuFont.GetFont(size: 18); }); + title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, Online.Chat.LinkAction.External, + creationParameters: t => { t.Font = OsuFont.GetFont(size: 18); }); title.AddText(")", t => t.Font = OsuFont.GetFont(size: 18)); } title.AddText(" by ", t => t.Font = OsuFont.GetFont(size: 14)); - if (entry.GithubUser.GithubUrl != null) - title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, - Online.Chat.LinkAction.External, null, null, - t => t.Font = OsuFont.GetFont(size: 14)); + if (entry.GithubUser.UserId != null) + title.AddUserLink(new User + { + Username = entry.GithubUser.OsuUsername, + Id = entry.GithubUser.UserId.Value + }, t => t.Font = OsuFont.GetFont(size: 14)); + else if (entry.GithubUser.GithubUrl != null) + title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t => t.Font = OsuFont.GetFont(size: 14)); else title.AddText(entry.GithubUser.DisplayName, t => t.Font = OsuFont.GetFont(size: 12)); From c96d7bfb672196072efadd39fb1bdf2c63e99725 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 May 2019 00:13:47 +0900 Subject: [PATCH 0935/5608] Centralise font specification --- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 2a207efe01..6d0b7a8739 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.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; @@ -65,6 +65,9 @@ namespace osu.Game.Overlays.Changelog }); foreach (APIChangelogEntry entry in category.Value) + var fontMedium = OsuFont.GetFont(size: 14); + var fontSmall = OsuFont.GetFont(size: 12); + { LinkFlowContainer title = new LinkFlowContainer { @@ -76,51 +79,51 @@ namespace osu.Game.Overlays.Changelog title.AddIcon(FontAwesome.Solid.Check, t => { - t.Font = OsuFont.GetFont(size: 12); + t.Font = fontSmall; t.Padding = new MarginPadding { Left = -17, Right = 5 }; }); - title.AddText(entry.Title, t => { t.Font = OsuFont.GetFont(size: 18); }); + title.AddText(entry.Title, t => { t.Font = fontLarge; }); if (!string.IsNullOrEmpty(entry.Repository)) { - title.AddText(" (", t => t.Font = OsuFont.GetFont(size: 18)); + title.AddText(" (", t => t.Font = fontLarge); title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, Online.Chat.LinkAction.External, - creationParameters: t => { t.Font = OsuFont.GetFont(size: 18); }); - title.AddText(")", t => t.Font = OsuFont.GetFont(size: 18)); + creationParameters: t => { t.Font = fontLarge; }); + title.AddText(")", t => t.Font = fontLarge); } - title.AddText(" by ", t => t.Font = OsuFont.GetFont(size: 14)); + title.AddText(" by ", t => t.Font = fontMedium); if (entry.GithubUser.UserId != null) title.AddUserLink(new User { Username = entry.GithubUser.OsuUsername, Id = entry.GithubUser.UserId.Value - }, t => t.Font = OsuFont.GetFont(size: 14)); + }, t => t.Font = fontMedium); else if (entry.GithubUser.GithubUrl != null) - title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t => t.Font = OsuFont.GetFont(size: 14)); + title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t => t.Font = fontMedium); else - title.AddText(entry.GithubUser.DisplayName, t => t.Font = OsuFont.GetFont(size: 12)); + title.AddText(entry.GithubUser.DisplayName, t => t.Font = fontSmall); ChangelogEntries.Add(title); if (!string.IsNullOrEmpty(entry.MessageHtml)) { - TextFlowContainer messageContainer = new TextFlowContainer + TextFlowContainer message = new TextFlowContainer { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, }; // todo: use markdown parsing once API returns markdown - messageContainer.AddText(Regex.Replace(entry.MessageHtml, @"<(.|\n)*?>", string.Empty), t => + message.AddText(Regex.Replace(entry.MessageHtml, @"<(.|\n)*?>", string.Empty), t => { - t.Font = OsuFont.GetFont(size: 12); + t.Font = fontSmall; t.Colour = new Color4(235, 184, 254, 255); }); - ChangelogEntries.Add(messageContainer); + ChangelogEntries.Add(message); } } } From a0ddc6d77a3930bad3abb540b2a91e2caed863da Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 May 2019 00:13:59 +0900 Subject: [PATCH 0936/5608] Use linq instead of a temporary sorted list --- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 6d0b7a8739..a76211a0ae 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.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; @@ -8,7 +8,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; using System; -using System.Collections.Generic; +using System.Linq; using System.Text.RegularExpressions; using osu.Game.Graphics.Sprites; using osu.Game.Users; @@ -44,30 +44,20 @@ namespace osu.Game.Overlays.Changelog }, }; - var categories = new SortedDictionary>(); - - // sort entries by category - foreach (APIChangelogEntry entry in build.ChangelogEntries) - { - if (!categories.ContainsKey(entry.Category)) - categories.Add(entry.Category, new List { entry }); - else - categories[entry.Category].Add(entry); - } - - foreach (KeyValuePair> category in categories) + foreach (var categoryEntries in build.ChangelogEntries.GroupBy(b => b.Category).OrderBy(c => c.Key)) { ChangelogEntries.Add(new OsuSpriteText { - Text = category.Key, + Text = categoryEntries.Key, Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 24), Margin = new MarginPadding { Top = 35, Bottom = 15 }, }); - foreach (APIChangelogEntry entry in category.Value) + var fontLarge = OsuFont.GetFont(size: 18); var fontMedium = OsuFont.GetFont(size: 14); var fontSmall = OsuFont.GetFont(size: 12); + foreach (APIChangelogEntry entry in categoryEntries) { LinkFlowContainer title = new LinkFlowContainer { From cb620082802164d24b793ae990134db7f5857d93 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 May 2019 11:23:24 +0900 Subject: [PATCH 0937/5608] Cleanup pass --- osu.Game/Graphics/OsuColour.cs | 2 + .../Changelog/UpdateStreamBadgeArea.cs | 5 +-- osu.Game/Overlays/ChangelogOverlay.cs | 37 +++++++++---------- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 53693a1e38..63ec24f84f 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -40,8 +40,10 @@ namespace osu.Game.Graphics // See https://github.com/ppy/osu-web/blob/master/resources/assets/less/colors.less public readonly Color4 PurpleLighter = FromHex(@"eeeeff"); public readonly Color4 PurpleLight = FromHex(@"aa88ff"); + public readonly Color4 PurpleLightAlternative = FromHex(@"cba4da"); public readonly Color4 Purple = FromHex(@"8866ee"); public readonly Color4 PurpleDark = FromHex(@"6644cc"); + public readonly Color4 PurpleDarkAlternative = FromHex(@"312436"); public readonly Color4 PurpleDarker = FromHex(@"441188"); public readonly Color4 PinkLighter = FromHex(@"ffddee"); diff --git a/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs b/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs index 925be48cd1..f564f03652 100644 --- a/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs +++ b/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs @@ -31,10 +31,7 @@ namespace osu.Game.Overlays.Changelog { Current.Value = null; - foreach (APIUpdateStream updateStream in streams) - { - AddItem(updateStream); - } + foreach (APIUpdateStream updateStream in streams) AddItem(updateStream); } protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 865c6b8de2..17d2ab93dc 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -18,12 +18,13 @@ using osu.Game.Input.Bindings; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Changelog; -using osuTK.Graphics; namespace osu.Game.Overlays { public class ChangelogOverlay : FullscreenOverlay { + public readonly Bindable Current = new Bindable(); + private ChangelogHeader header; private Container content; @@ -32,23 +33,6 @@ namespace osu.Game.Overlays private List builds; - public readonly Bindable Current = new Bindable(); - - public void ShowListing() => Current.Value = null; - - /// - /// Fetches and shows a specific build from a specific update stream. - /// - /// Must contain at least and - /// . If and - /// are specified, the header will instantly display them. - public void ShowBuild([NotNull] APIChangelogBuild build) - { - if (build == null) throw new ArgumentNullException(nameof(build)); - - Current.Value = build; - } - [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colour) { @@ -62,7 +46,7 @@ namespace osu.Game.Overlays new Box { RelativeSizeAxes = Axes.Both, - Colour = new Color4(49, 36, 54, 255), + Colour = colour.PurpleDarkAlternative, }, new ScrollContainer { @@ -102,6 +86,21 @@ namespace osu.Game.Overlays }); } + public void ShowListing() => Current.Value = null; + + /// + /// Fetches and shows a specific build from a specific update stream. + /// + /// Must contain at least and + /// . If and + /// are specified, the header will instantly display them. + public void ShowBuild([NotNull] APIChangelogBuild build) + { + if (build == null) throw new ArgumentNullException(nameof(build)); + + Current.Value = build; + } + public override bool OnPressed(GlobalAction action) { switch (action) From 5a887dabfe660e40ed0d962e392d095c4b0dcdfa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 May 2019 11:38:13 +0900 Subject: [PATCH 0938/5608] Prepare changelog api requests to work when not logged in --- .../Changelog/ChangelogSingleBuild.cs | 23 +++++++++------- osu.Game/Overlays/ChangelogOverlay.cs | 26 +++++++++++-------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index 98fe68c015..81c7905e84 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -33,26 +33,31 @@ namespace osu.Game.Overlays.Changelog [BackgroundDependencyLoader] private void load(CancellationToken? cancellation, IAPIProvider api) { - var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); bool complete = false; + var req = new GetChangelogBuildRequest(build.UpdateStream.Name, build.Version); req.Success += res => { build = res; complete = true; }; - req.Failure += _ => complete = true; - api.Queue(req); + Task.Run(() => req.Perform(api)); - while (!complete && cancellation?.IsCancellationRequested != true) - Task.Delay(1); - - Children = new Drawable[] + while (!complete) { - new ChangelogBuildWithNavigation(build) { SelectBuild = SelectBuild }, - }; + if (cancellation?.IsCancellationRequested == true) + { + req.Cancel(); + return; + } + + Task.Delay(1); + } + + if (build != null) + Child = new ChangelogBuildWithNavigation(build) { SelectBuild = SelectBuild }; } public class ChangelogBuildWithNavigation : ChangelogBuild diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 17d2ab93dc..6ce82d342a 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Threading; +using System.Threading.Tasks; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -136,21 +137,24 @@ namespace osu.Game.Overlays { initialFetchPerformed = true; - var req = new GetChangelogRequest(); - req.Success += res => + Task.Run(() => { - // remap streams to builds to ensure model equality - res.Builds.ForEach(b => b.UpdateStream = res.Streams.Find(s => s.Id == b.UpdateStream.Id)); - res.Streams.ForEach(s => s.LatestBuild.UpdateStream = res.Streams.Find(s2 => s2.Id == s.LatestBuild.UpdateStream.Id)); + var req = new GetChangelogRequest(); + req.Success += res => + { + // remap streams to builds to ensure model equality + res.Builds.ForEach(b => b.UpdateStream = res.Streams.Find(s => s.Id == b.UpdateStream.Id)); + res.Streams.ForEach(s => s.LatestBuild.UpdateStream = res.Streams.Find(s2 => s2.Id == s.LatestBuild.UpdateStream.Id)); - builds = res.Builds; - header.Streams.Populate(res.Streams); + builds = res.Builds; + header.Streams.Populate(res.Streams); - Current.TriggerChange(); - }; - req.Failure += _ => initialFetchPerformed = false; + Current.TriggerChange(); + }; + req.Failure += _ => initialFetchPerformed = false; - API.Queue(req); + req.Perform(API); + }); } private CancellationTokenSource loadContentTask; From 372c5b081c985261d3f8cc0e43247600a6a646e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 May 2019 12:07:22 +0900 Subject: [PATCH 0939/5608] Fix audio preview buttons not correctly handling load failure states Closes #4593. --- osu.Game/Audio/PreviewTrack.cs | 25 ++++++++++++++++--------- osu.Game/Overlays/Direct/PlayButton.cs | 10 ++++++++-- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 3b21bdefc4..22ce7d4711 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -28,7 +28,8 @@ namespace osu.Game.Audio private void load() { track = GetTrack(); - track.Completed += () => Schedule(Stop); + if (track != null) + track.Completed += () => Schedule(Stop); } /// @@ -56,19 +57,25 @@ namespace osu.Game.Audio /// /// Starts playing this . /// - public void Start() => startDelegate = Schedule(() => + /// Whether the track is started or already playing. + public bool Start() { if (track == null) - return; + return false; - if (hasStarted) - return; + startDelegate = Schedule(() => + { + if (hasStarted) + return; - hasStarted = true; + hasStarted = true; - track.Restart(); - Started?.Invoke(); - }); + track.Restart(); + Started?.Invoke(); + }); + + return true; + } /// /// Stops playing this . diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 6daebb3c15..2a77e7ca26 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -129,7 +129,7 @@ namespace osu.Game.Overlays.Direct if (Preview != null) { - Preview.Start(); + attemptStart(); return; } @@ -147,7 +147,7 @@ namespace osu.Game.Overlays.Direct // user may have changed their mind. if (Playing.Value) - preview.Start(); + attemptStart(); }); } else @@ -157,6 +157,12 @@ namespace osu.Game.Overlays.Direct } } + private void attemptStart() + { + if (Preview?.Start() != true) + Playing.Value = false; + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From 7229975fef4b4ea6d365e459fe3d33f90bbefd47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 May 2019 12:41:45 +0900 Subject: [PATCH 0940/5608] Further minor refactoring --- osu.Game/Overlays/Changelog/UpdateStreamBadge.cs | 8 +++++--- osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs b/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs index 925412f94d..c39e6a6784 100644 --- a/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs +++ b/osu.Game/Overlays/Changelog/UpdateStreamBadge.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 Humanizer; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -14,6 +15,7 @@ using osu.Game.Online.API.Requests.Responses; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.Changelog @@ -37,9 +39,9 @@ namespace osu.Game.Overlays.Changelog public UpdateStreamBadge(APIUpdateStream stream) : base(stream) { - Height = badge_height; - Width = stream.IsFeatured ? badge_width * 2 : badge_width; + Size = new Vector2(stream.IsFeatured ? badge_width * 2 : badge_width, badge_height); Padding = new MarginPadding(5); + Child = fadeContainer = new Container { RelativeSizeAxes = Axes.Both, @@ -65,7 +67,7 @@ namespace osu.Game.Overlays.Changelog }, new OsuSpriteText { - Text = stream.LatestBuild.Users > 0 ? $"{stream.LatestBuild.Users:N0} users online" : null, + Text = stream.LatestBuild.Users > 0 ? $"{stream.LatestBuild.Users:N0} {"user".Pluralize(stream.LatestBuild.Users == 1)} online" : null, Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 10), Colour = new Color4(203, 164, 218, 255), }, diff --git a/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs b/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs index f564f03652..2b48811bd6 100644 --- a/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs +++ b/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs @@ -31,7 +31,8 @@ namespace osu.Game.Overlays.Changelog { Current.Value = null; - foreach (APIUpdateStream updateStream in streams) AddItem(updateStream); + foreach (APIUpdateStream updateStream in streams) + AddItem(updateStream); } protected override bool OnHover(HoverEvent e) From edfe47fb0268fdadd0848595cdcc1c7f046a32ed Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 23 May 2019 13:37:25 +0900 Subject: [PATCH 0941/5608] Rename button --- osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs index 974dbf0282..f92aae43d2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs @@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddStep(@"Collapse", () => expandingBar.Collapse()); - AddStep(@"Uncollapse", () => expandingBar.Expand()); + AddStep(@"Expand", () => expandingBar.Expand()); AddSliderStep(@"Resize container", 1, 300, 150, value => container.ResizeTo(value)); AddStep(@"Horizontal", () => expandingBar.RelativeSizeAxes = Axes.X); AddStep(@"Anchor top", () => expandingBar.Anchor = Anchor.TopCentre); From 7971261fbc6ea50a6b488b082538e16349057896 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 23 May 2019 15:59:22 +0900 Subject: [PATCH 0942/5608] Don't create a new drawable for the first background --- .../Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index bd80919851..2d83c1de01 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -39,7 +39,7 @@ namespace osu.Game.Beatmaps.Drawables { // If DelayedLoadUnloadWrapper is attempting to RELOAD the same content (Beatmap), that means that it was // previously UNLOADED and thus its children have been disposed of, so we need to recreate them here. - if (lastModel == Beatmap.Value) + if (lastModel != null && lastModel == Beatmap.Value) return CreateDrawable(Beatmap.Value); // If the model has changed since the previous unload (or if there was no load), then we can safely use the given content From f0d7728e81d91d4704bf180998e20b286a505574 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 23 May 2019 17:01:13 +0900 Subject: [PATCH 0943/5608] Fix failures with a null-model --- .../Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 2d83c1de01..96786f5f49 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -32,6 +32,7 @@ namespace osu.Game.Beatmaps.Drawables protected virtual double UnloadDelay => 10000; private BeatmapInfo lastModel; + private bool firstLoad = true; protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Drawable content, double timeBeforeLoad) { @@ -39,11 +40,12 @@ namespace osu.Game.Beatmaps.Drawables { // If DelayedLoadUnloadWrapper is attempting to RELOAD the same content (Beatmap), that means that it was // previously UNLOADED and thus its children have been disposed of, so we need to recreate them here. - if (lastModel != null && lastModel == Beatmap.Value) + if (!firstLoad && lastModel == Beatmap.Value) return CreateDrawable(Beatmap.Value); // If the model has changed since the previous unload (or if there was no load), then we can safely use the given content lastModel = Beatmap.Value; + firstLoad = false; return content; }, timeBeforeLoad, UnloadDelay); } From 9c6fbebb67040cf8ce367480cbda5a29ef647652 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 May 2019 17:55:18 +0900 Subject: [PATCH 0944/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 98b158134d..b77c724d1b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index b7549eeaef..fc047aa5f0 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From acaf2f9fbb538a3aa335ce1319ea624a33486a91 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 May 2019 18:54:42 +0900 Subject: [PATCH 0945/5608] Show changelog from new build notification --- osu.Desktop/Overlays/VersionManager.cs | 25 +++++++----- osu.Game/Overlays/ChangelogOverlay.cs | 56 +++++++++++++++++++++----- 2 files changed, 61 insertions(+), 20 deletions(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index e9c5d06f3c..7e4257c23b 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.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 osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -96,33 +95,37 @@ namespace osu.Desktop.Overlays var version = game.Version; var lastVersion = config.Get(OsuSetting.Version); - if (game.IsDeployedBuild && version != lastVersion) + //if (game.IsDeployedBuild && version != lastVersion) { config.Set(OsuSetting.Version, version); // only show a notification if we've previously saved a version to the config file (ie. not the first run). if (!string.IsNullOrEmpty(lastVersion)) - notificationOverlay.Post(new UpdateCompleteNotification(version, host.OpenUrlExternally)); + notificationOverlay.Post(new UpdateCompleteNotification(version)); } } private class UpdateCompleteNotification : SimpleNotification { - public UpdateCompleteNotification(string version, Action openUrl = null) + private readonly string version; + + public UpdateCompleteNotification(string version) { + this.version = version; Text = $"You are now running osu!lazer {version}.\nClick to see what's new!"; - Icon = FontAwesome.Solid.CheckSquare; - Activated = delegate - { - openUrl?.Invoke($"https://osu.ppy.sh/home/changelog/lazer/{version}"); - return true; - }; } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, ChangelogOverlay changelog) { + Icon = FontAwesome.Solid.CheckSquare; IconBackgound.Colour = colours.BlueDark; + + Activated = delegate + { + changelog.ShowBuild("lazer", version); + return true; + }; } } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 6ce82d342a..a957227c6b 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -34,6 +34,8 @@ namespace osu.Game.Overlays private List builds; + private List streams; + [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colour) { @@ -87,7 +89,11 @@ namespace osu.Game.Overlays }); } - public void ShowListing() => Current.Value = null; + public void ShowListing() + { + Current.Value = null; + State = Visibility.Visible; + } /// /// Fetches and shows a specific build from a specific update stream. @@ -100,6 +106,27 @@ namespace osu.Game.Overlays if (build == null) throw new ArgumentNullException(nameof(build)); Current.Value = build; + State = Visibility.Visible; + } + + public void ShowBuild([NotNull] string updateStream, [NotNull] string version) + { + if (updateStream == null) throw new ArgumentNullException(nameof(updateStream)); + if (version == null) throw new ArgumentNullException(nameof(version)); + + performAfterFetch(() => + { + var build = builds.Find(b => b.Version == version && b.UpdateStream.Name == updateStream) + ?? streams.Find(s => s.Name == updateStream)?.LatestBuild; + + if (build != null) + { + Current.Value = build; + State = Visibility.Visible; + } + }); + + State = Visibility.Visible; } public override bool OnPressed(GlobalAction action) @@ -127,15 +154,23 @@ namespace osu.Game.Overlays { base.PopIn(); - if (!initialFetchPerformed) - fetchListing(); + if (initialFetchTask == null) + // fetch and refresh to show listing, if no other request was made via Show methods + performAfterFetch(() => Current.TriggerChange()); } - private bool initialFetchPerformed; + private Task initialFetchTask; - private void fetchListing() + private void performAfterFetch(Action action) => fetchListing()?.ContinueWith(_ => Schedule(action)); + + private Task fetchListing() { - initialFetchPerformed = true; + if (initialFetchTask != null) + return initialFetchTask; + + var tcs = new TaskCompletionSource(); + + initialFetchTask = tcs.Task; Task.Run(() => { @@ -147,14 +182,17 @@ namespace osu.Game.Overlays res.Streams.ForEach(s => s.LatestBuild.UpdateStream = res.Streams.Find(s2 => s2.Id == s.LatestBuild.UpdateStream.Id)); builds = res.Builds; + streams = res.Streams; + header.Streams.Populate(res.Streams); - Current.TriggerChange(); + tcs.SetResult(true); }; - req.Failure += _ => initialFetchPerformed = false; - + req.Failure += _ => initialFetchTask = null; req.Perform(API); }); + + return initialFetchTask; } private CancellationTokenSource loadContentTask; From e034b3d514af9ec9e5e6d9976ecd8617ffb0b1dc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 May 2019 19:08:44 +0900 Subject: [PATCH 0946/5608] Use TaskCompletionSource in a better manner --- osu.Desktop/Overlays/VersionManager.cs | 5 +---- osu.Game/Overlays/ChangelogOverlay.cs | 12 +++++------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 7e4257c23b..2bba1723ec 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Platform; using osu.Game; using osu.Game.Configuration; using osu.Game.Graphics; @@ -24,15 +23,13 @@ namespace osu.Desktop.Overlays private OsuConfigManager config; private OsuGameBase game; private NotificationOverlay notificationOverlay; - private GameHost host; [BackgroundDependencyLoader] - private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config, GameHost host) + private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config) { notificationOverlay = notification; this.config = config; this.game = game; - this.host = host; AutoSizeAxes = Axes.Both; Anchor = Anchor.BottomCentre; diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index a957227c6b..552e213a45 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -168,12 +168,10 @@ namespace osu.Game.Overlays if (initialFetchTask != null) return initialFetchTask; - var tcs = new TaskCompletionSource(); - - initialFetchTask = tcs.Task; - - Task.Run(() => + return initialFetchTask = Task.Run(async () => { + var tcs = new TaskCompletionSource(); + var req = new GetChangelogRequest(); req.Success += res => { @@ -190,9 +188,9 @@ namespace osu.Game.Overlays }; req.Failure += _ => initialFetchTask = null; req.Perform(API); - }); - return initialFetchTask; + await tcs.Task; + }); } private CancellationTokenSource loadContentTask; From 492dd3eee266cb59c3882cc868d2762dc6cb6fba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 24 May 2019 10:53:02 +0900 Subject: [PATCH 0947/5608] Restore accidentally commented conditional --- osu.Desktop/Overlays/VersionManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 2bba1723ec..d2aad99f41 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -92,7 +92,7 @@ namespace osu.Desktop.Overlays var version = game.Version; var lastVersion = config.Get(OsuSetting.Version); - //if (game.IsDeployedBuild && version != lastVersion) + if (game.IsDeployedBuild && version != lastVersion) { config.Set(OsuSetting.Version, version); From a272004610ec31fa7499ccfb69ccd2df4f737bc8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 24 May 2019 11:04:36 +0900 Subject: [PATCH 0948/5608] Use a more friendly set method for tab control --- osu.Game/Overlays/Changelog/ChangelogHeader.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 9be6eef295..fca62fbb44 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -62,7 +63,7 @@ namespace osu.Game.Overlays.Changelog TabControl.AddItem(e.NewValue.ToString()); TabControl.Current.Value = e.NewValue.ToString(); - Streams.Current.Value = e.NewValue.UpdateStream; + Streams.Current.Value = Streams.Items.FirstOrDefault(s => s.Name == e.NewValue.UpdateStream.Name); title.Version = e.NewValue.UpdateStream.DisplayName; } From cda97a61fa751d6f2b2b643d37a6fa994d1b9b86 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Fri, 24 May 2019 19:43:53 +0300 Subject: [PATCH 0949/5608] Add a bit of smoothness to the rank graph --- .../Visual/Online/TestSceneRankGraph.cs | 25 ++++++++ .../Profile/Header/Components/RankGraph.cs | 63 ++++++++++--------- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs index c04a4249cc..709e75ab13 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs @@ -31,6 +31,7 @@ namespace osu.Game.Tests.Visual.Online var data = new int[89]; var dataWithZeros = new int[89]; var smallData = new int[89]; + var edgyData = new int[89]; for (int i = 0; i < 89; i++) data[i] = dataWithZeros[i] = (i + 1) * 1000; @@ -41,6 +42,14 @@ namespace osu.Game.Tests.Visual.Online for (int i = 79; i < 89; i++) smallData[i] = 100000 - i * 1000; + bool edge = true; + + for (int i = 0; i < 20; i++) + { + edgyData[i] = 100000 + (edge ? 1000 : -1000) * (i + 1); + edge = !edge; + } + Add(new Container { Anchor = Anchor.Centre, @@ -120,6 +129,22 @@ namespace osu.Game.Tests.Visual.Online } }; }); + + AddStep("graph with edges", () => + { + graph.User.Value = new User + { + Statistics = new UserStatistics + { + Ranks = new UserStatistics.UserRanks { Global = 12000 }, + PP = 12345, + }, + RankHistory = new User.RankHistoryData + { + Data = edgyData, + } + }; + }); } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 85ea2a175a..5ad6db9ff1 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -96,7 +96,7 @@ namespace osu.Game.Overlays.Profile.Header.Components if (ranks?.Length > 1) { graph.UpdateBallPosition(e.MousePosition.X); - graph.ShowBall(); + graph.ShowBar(); } return base.OnHover(e); @@ -114,7 +114,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { if (ranks?.Length > 1) { - graph.HideBall(); + graph.HideBar(); } base.OnHoverLost(e); @@ -123,31 +123,41 @@ namespace osu.Game.Overlays.Profile.Header.Components private class RankChartLineGraph : LineGraph { private readonly CircularContainer movingBall; + private readonly Container bar; private readonly Box ballBg; - private readonly Box movingBar; + private readonly Box line; public Action OnBallMove; public RankChartLineGraph() { - Add(movingBar = new Box + Add(bar = new Container { Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Y, - Width = 1.5f, + AutoSizeAxes = Axes.X, Alpha = 0, RelativePositionAxes = Axes.Both, - }); - - Add(movingBall = new CircularContainer - { - Origin = Anchor.Centre, - Size = new Vector2(18), - Alpha = 0, - Masking = true, - BorderThickness = 4, - RelativePositionAxes = Axes.Both, - Child = ballBg = new Box { RelativeSizeAxes = Axes.Both } + Children = new Drawable[] + { + line = new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Width = 1.5f, + }, + movingBall = new CircularContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre, + Size = new Vector2(18), + Masking = true, + BorderThickness = 4, + RelativePositionAxes = Axes.Y, + Child = ballBg = new Box { RelativeSizeAxes = Axes.Both } + } + } }); } @@ -155,29 +165,22 @@ namespace osu.Game.Overlays.Profile.Header.Components private void load(OsuColour colours) { ballBg.Colour = colours.GreySeafoamDarker; - movingBall.BorderColour = colours.Yellow; - movingBar.Colour = colours.Yellow; + movingBall.BorderColour = line.Colour = colours.Yellow; } public void UpdateBallPosition(float mouseXPosition) { + int duration = 200; int index = calculateIndex(mouseXPosition); - movingBall.Position = calculateBallPosition(index); - movingBar.X = movingBall.X; + Vector2 position = calculateBallPosition(index); + movingBall.MoveToY(position.Y, duration, Easing.OutQuint); + bar.MoveToX(position.X, duration, Easing.OutQuint); OnBallMove.Invoke(index); } - public void ShowBall() - { - movingBall.FadeIn(fade_duration); - movingBar.FadeIn(fade_duration); - } + public void ShowBar() => bar.FadeIn(fade_duration); - public void HideBall() - { - movingBall.FadeOut(fade_duration); - movingBar.FadeOut(fade_duration); - } + public void HideBar() => bar.FadeOut(fade_duration); private int calculateIndex(float mouseXPosition) => (int)Math.Round(mouseXPosition / DrawWidth * (DefaultValueCount - 1)); From 69ada11f4137ec09a2ffd22276a2f6e0680c4cbc Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Fri, 24 May 2019 20:01:47 +0300 Subject: [PATCH 0950/5608] use constant value --- osu.Game/Overlays/Profile/Header/Components/RankGraph.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 5ad6db9ff1..5f79386b76 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -170,7 +170,7 @@ namespace osu.Game.Overlays.Profile.Header.Components public void UpdateBallPosition(float mouseXPosition) { - int duration = 200; + const int duration = 200; int index = calculateIndex(mouseXPosition); Vector2 position = calculateBallPosition(index); movingBall.MoveToY(position.Y, duration, Easing.OutQuint); From 446210b81223a7635496071a1204ae64d95d25aa Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 25 May 2019 11:33:31 +0200 Subject: [PATCH 0951/5608] Use an if statement instead of a switch --- osu.Desktop/DiscordRichPresenceClient.cs | 26 ++++-------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/osu.Desktop/DiscordRichPresenceClient.cs b/osu.Desktop/DiscordRichPresenceClient.cs index 38e929c1ae..4a2f882e2b 100644 --- a/osu.Desktop/DiscordRichPresenceClient.cs +++ b/osu.Desktop/DiscordRichPresenceClient.cs @@ -77,28 +77,10 @@ namespace osu.Desktop private void setPresenceGamemode(RulesetInfo ruleset, RichPresence presence) { - switch (ruleset.ID) - { - case 0: - presence.Assets.SmallImageKey = ruleset.ShortName; - break; - - case 1: - presence.Assets.SmallImageKey = ruleset.ShortName; - break; - - case 2: - presence.Assets.SmallImageKey = ruleset.ShortName; - break; - - case 3: - presence.Assets.SmallImageKey = ruleset.ShortName; - break; - - default: - presence.Assets.SmallImageKey = "unknown"; - break; - } + if (ruleset.ID != null && ruleset.ID <= 3) //legacy rulesets use an ID between 0 and 3 + presence.Assets.SmallImageKey = ruleset.ShortName; + else + presence.Assets.SmallImageKey = "unknown"; //not a legay ruleset so let's display the unknown ruleset icon. presence.Assets.SmallImageText = ruleset.ShortName; } From b9f6372c3fa240bec91c25ded502e4f3e9c484fb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 25 May 2019 22:11:11 +0900 Subject: [PATCH 0952/5608] Fix Aquatico font lookups --- osu.Game/Graphics/OsuFont.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/OsuFont.cs b/osu.Game/Graphics/OsuFont.cs index 86a14a720e..6c4b46c3ad 100644 --- a/osu.Game/Graphics/OsuFont.cs +++ b/osu.Game/Graphics/OsuFont.cs @@ -73,7 +73,7 @@ namespace osu.Game.Graphics string weightString = weight.ToString(); // Only exo has an explicit "regular" weight, other fonts do not - if (family != GetFamilyString(Typeface.Exo) && weight == FontWeight.Regular) + if (weight == FontWeight.Regular && family != GetFamilyString(Typeface.Exo) && family != GetFamilyString(Typeface.Aquatico)) weightString = string.Empty; return weightString; From 5d77ae4a1e54a548548449b20da3d77fbdb86d9a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 May 2019 10:25:17 +0900 Subject: [PATCH 0953/5608] Fix regression in FileBasedIPC implementation --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 1086991eb4..8be10e2089 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Logging; +using osu.Framework.Platform; using osu.Framework.Platform.Windows; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; @@ -26,17 +27,17 @@ namespace osu.Game.Tournament.IPC private int lastBeatmapId; [BackgroundDependencyLoader] - private void load(LadderInfo ladder) + private void load(LadderInfo ladder, GameHost host) { StableStorage stable; try { - stable = new StableStorage(); + stable = new StableStorage(host as DesktopGameHost); } - catch + catch (Exception e) { - Logger.Log("Stable installation could not be found; disabling file based IPC"); + Logger.Error(e, "Stable installation could not be found; disabling file based IPC"); return; } @@ -170,8 +171,8 @@ namespace osu.Game.Tournament.IPC } } - public StableStorage() - : base(string.Empty, null) + public StableStorage(DesktopGameHost host) + : base(string.Empty, host) { } } From 53b22453305f3ed1dc676412115485fcfb5bbf4b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 27 May 2019 01:36:07 +0900 Subject: [PATCH 0954/5608] Move common settings sub-panel logic to own class --- osu.Game/Overlays/KeyBindingPanel.cs | 88 +--------------------- osu.Game/Overlays/SettingsPanel.cs | 2 - osu.Game/Overlays/SettingsSubPanel.cs | 103 ++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 89 deletions(-) create mode 100644 osu.Game/Overlays/SettingsSubPanel.cs diff --git a/osu.Game/Overlays/KeyBindingPanel.cs b/osu.Game/Overlays/KeyBindingPanel.cs index 301c8faca2..928bd080fa 100644 --- a/osu.Game/Overlays/KeyBindingPanel.cs +++ b/osu.Game/Overlays/KeyBindingPanel.cs @@ -3,22 +3,14 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; using osu.Game.Input.Bindings; using osu.Game.Overlays.KeyBinding; using osu.Game.Overlays.Settings; using osu.Game.Rulesets; -using osu.Game.Screens.Ranking; -using osuTK; namespace osu.Game.Overlays { - public class KeyBindingPanel : SettingsPanel + public class KeyBindingPanel : SettingsSubPanel { protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); @@ -29,84 +21,6 @@ namespace osu.Game.Overlays foreach (var ruleset in rulesets.AvailableRulesets) AddSection(new RulesetBindingsSection(ruleset)); - - AddInternal(new BackButton - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Action = Hide - }); - } - - public KeyBindingPanel() - : base(true) - { - } - - private class BackButton : OsuClickableContainer, IKeyBindingHandler - { - private AspectContainer aspect; - - [BackgroundDependencyLoader] - private void load() - { - Size = new Vector2(Sidebar.DEFAULT_WIDTH); - Children = new Drawable[] - { - aspect = new AspectContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Children = new Drawable[] - { - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Y = -15, - Size = new Vector2(15), - Shadow = true, - Icon = FontAwesome.Solid.ChevronLeft - }, - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Y = 15, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), - Text = @"back", - }, - } - } - }; - } - - protected override bool OnMouseDown(MouseDownEvent e) - { - aspect.ScaleTo(0.75f, 2000, Easing.OutQuint); - return base.OnMouseDown(e); - } - - protected override bool OnMouseUp(MouseUpEvent e) - { - aspect.ScaleTo(1, 1000, Easing.OutElastic); - return base.OnMouseUp(e); - } - - public bool OnPressed(GlobalAction action) - { - switch (action) - { - case GlobalAction.Back: - Click(); - return true; - } - - return false; - } - - public bool OnReleased(GlobalAction action) => false; } } } diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 85b74c0fad..474f529bb1 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -28,8 +28,6 @@ namespace osu.Game.Overlays protected const float WIDTH = 400; - private const float sidebar_padding = 10; - protected Container ContentContainer; protected override Container Content => ContentContainer; diff --git a/osu.Game/Overlays/SettingsSubPanel.cs b/osu.Game/Overlays/SettingsSubPanel.cs new file mode 100644 index 0000000000..576be71ee6 --- /dev/null +++ b/osu.Game/Overlays/SettingsSubPanel.cs @@ -0,0 +1,103 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Input.Bindings; +using osu.Game.Overlays.Settings; +using osu.Game.Screens.Ranking; +using osuTK; + +namespace osu.Game.Overlays +{ + public abstract class SettingsSubPanel : SettingsPanel + { + protected SettingsSubPanel() + : base(true) + { + } + + [BackgroundDependencyLoader] + private void load() + { + AddInternal(new BackButton + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Action = Hide + }); + } + + private class BackButton : OsuClickableContainer, IKeyBindingHandler + { + private AspectContainer aspect; + + [BackgroundDependencyLoader] + private void load() + { + Size = new Vector2(Sidebar.DEFAULT_WIDTH); + Children = new Drawable[] + { + aspect = new AspectContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Y = -15, + Size = new Vector2(15), + Shadow = true, + Icon = FontAwesome.Solid.ChevronLeft + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Y = 15, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Text = @"back", + }, + } + } + }; + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + aspect.ScaleTo(0.75f, 2000, Easing.OutQuint); + return base.OnMouseDown(e); + } + + protected override bool OnMouseUp(MouseUpEvent e) + { + aspect.ScaleTo(1, 1000, Easing.OutElastic); + return base.OnMouseUp(e); + } + + public bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.Back: + Click(); + return true; + } + + return false; + } + + public bool OnReleased(GlobalAction action) => false; + } + } +} From 02e2fb963a9c25a0bda62120b892b2714d0e2495 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 27 May 2019 01:45:37 +0900 Subject: [PATCH 0955/5608] Tidy up how subpanels are handled in SettingsOverlay --- osu.Game/Overlays/SettingsOverlay.cs | 34 +++++++++++++++++----------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 4f3a71a1b3..6e3eaae0a1 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -8,13 +8,12 @@ using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings.Sections; using osuTK.Graphics; using System.Collections.Generic; +using System.Linq; namespace osu.Game.Overlays { public class SettingsOverlay : SettingsPanel { - private readonly KeyBindingPanel keyBindingPanel; - protected override IEnumerable CreateSections() => new SettingsSection[] { new GeneralSection(), @@ -22,29 +21,37 @@ namespace osu.Game.Overlays new GameplaySection(), new AudioSection(), new SkinSection(), - new InputSection(keyBindingPanel), + new InputSection(createSubPanel(new KeyBindingPanel())), new OnlineSection(), new MaintenanceSection(), new DebugSection(), }; + private readonly List subPanels = new List(); + protected override Drawable CreateHeader() => new SettingsHeader("settings", "Change the way osu! behaves"); protected override Drawable CreateFooter() => new SettingsFooter(); public SettingsOverlay() : base(true) { - keyBindingPanel = new KeyBindingPanel - { - Depth = 1, - Anchor = Anchor.TopRight, - }; - keyBindingPanel.StateChanged += keyBindingPanelStateChanged; } - public override bool AcceptsFocus => keyBindingPanel.State != Visibility.Visible; + public override bool AcceptsFocus => subPanels.All(s => s.State != Visibility.Visible); - private void keyBindingPanelStateChanged(Visibility visibility) + private T createSubPanel(T subPanel) + where T : SettingsSubPanel + { + subPanel.Depth = 1; + subPanel.Anchor = Anchor.TopRight; + subPanel.StateChanged += subPanelStateChanged; + + subPanels.Add(subPanel); + + return subPanel; + } + + private void subPanelStateChanged(Visibility visibility) { switch (visibility) { @@ -66,12 +73,13 @@ namespace osu.Game.Overlays } } - protected override float ExpandedPosition => keyBindingPanel.State == Visibility.Visible ? -WIDTH : base.ExpandedPosition; + protected override float ExpandedPosition => subPanels.Any(s => s.State == Visibility.Visible) ? -WIDTH : base.ExpandedPosition; [BackgroundDependencyLoader] private void load() { - ContentContainer.Add(keyBindingPanel); + foreach (var s in subPanels) + ContentContainer.Add(s); } } } From e7b9d1efa32c7d7d46991071247b8ab3a860ec48 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 27 May 2019 00:55:12 +0900 Subject: [PATCH 0956/5608] Isolate alpha usage in OsuCheckbox --- osu.Game/Graphics/UserInterface/OsuCheckbox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index de3d93d845..2944fc87af 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -78,7 +78,7 @@ namespace osu.Game.Graphics.UserInterface Current.DisabledChanged += disabled => { - Alpha = disabled ? 0.3f : 1; + labelSpriteText.Alpha = Nub.Alpha = disabled ? 0.3f : 1; }; } From 127858d39855c7670377b3ff4e32af02fa864966 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 25 May 2019 15:00:53 +0900 Subject: [PATCH 0957/5608] Store databased settings based on string keys rather than ints Allows for rearranging/removal from enums without consequence. --- .../Configuration/DatabasedConfigManager.cs | 19 +++++++++++++++++-- osu.Game/Configuration/DatabasedSetting.cs | 11 +++-------- osu.Game/Configuration/SettingsStore.cs | 6 ++++++ .../Migrations/20180125143340_Settings.cs | 2 +- .../Migrations/OsuDbContextModelSnapshot.cs | 4 ++-- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs index 8f1780cab5..d5cdd7e4bc 100644 --- a/osu.Game/Configuration/DatabasedConfigManager.cs +++ b/osu.Game/Configuration/DatabasedConfigManager.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Game.Rulesets; @@ -19,6 +20,8 @@ namespace osu.Game.Configuration private readonly RulesetInfo ruleset; + private readonly bool legacySettingsExist; + protected DatabasedConfigManager(SettingsStore settings, RulesetInfo ruleset = null, int? variant = null) { this.settings = settings; @@ -26,6 +29,7 @@ namespace osu.Game.Configuration this.variant = variant; databasedSettings = settings.Query(ruleset?.ID, variant); + legacySettingsExist = databasedSettings.Any(s => int.TryParse(s.Key, out var _)); InitialiseDefaults(); } @@ -43,7 +47,18 @@ namespace osu.Game.Configuration { base.AddBindable(lookup, bindable); - var setting = databasedSettings.Find(s => (int)s.Key == (int)(object)lookup); + if (legacySettingsExist) + { + var legacySetting = databasedSettings.Find(s => s.Key == ((int)(object)lookup).ToString()); + + if (legacySetting != null) + { + bindable.Parse(legacySetting.Value); + settings.Delete(legacySetting); + } + } + + var setting = databasedSettings.Find(s => s.Key == lookup.ToString()); if (setting != null) { @@ -53,7 +68,7 @@ namespace osu.Game.Configuration { settings.Update(setting = new DatabasedSetting { - Key = lookup, + Key = lookup.ToString(), Value = bindable.Value, RulesetID = ruleset?.ID, Variant = variant, diff --git a/osu.Game/Configuration/DatabasedSetting.cs b/osu.Game/Configuration/DatabasedSetting.cs index d56ac49358..3e0a9ecd28 100644 --- a/osu.Game/Configuration/DatabasedSetting.cs +++ b/osu.Game/Configuration/DatabasedSetting.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.ComponentModel.DataAnnotations.Schema; @@ -16,11 +16,7 @@ namespace osu.Game.Configuration public int? Variant { get; set; } [Column("Key")] - public int IntKey - { - get => (int)Key; - private set => Key = value; - } + public string Key { get; set; } [Column("Value")] public string StringValue @@ -29,10 +25,9 @@ namespace osu.Game.Configuration set => Value = value; } - public object Key; public object Value; - public DatabasedSetting(object key, object value) + public DatabasedSetting(string key, object value) { Key = key; Value = value; diff --git a/osu.Game/Configuration/SettingsStore.cs b/osu.Game/Configuration/SettingsStore.cs index f15fd1f17b..f8c9bdeaf8 100644 --- a/osu.Game/Configuration/SettingsStore.cs +++ b/osu.Game/Configuration/SettingsStore.cs @@ -37,5 +37,11 @@ namespace osu.Game.Configuration SettingChanged?.Invoke(); } + + public void Delete(DatabasedSetting setting) + { + using (var usage = ContextFactory.GetForWrite()) + usage.Context.Remove(setting); + } } } diff --git a/osu.Game/Migrations/20180125143340_Settings.cs b/osu.Game/Migrations/20180125143340_Settings.cs index 2e2768dc7c..166d3c086d 100644 --- a/osu.Game/Migrations/20180125143340_Settings.cs +++ b/osu.Game/Migrations/20180125143340_Settings.cs @@ -16,7 +16,7 @@ namespace osu.Game.Migrations { ID = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), - Key = table.Column(type: "INTEGER", nullable: false), + Key = table.Column(type: "TEXT", nullable: false), RulesetID = table.Column(type: "INTEGER", nullable: true), Value = table.Column(type: "TEXT", nullable: true), Variant = table.Column(type: "INTEGER", nullable: true) diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 8430e00e4f..f942d357e8 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace osu.Game.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.1-servicing-10028"); + .HasAnnotation("ProductVersion", "2.2.4-servicing-10062"); modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => { @@ -198,7 +198,7 @@ namespace osu.Game.Migrations b.Property("ID") .ValueGeneratedOnAdd(); - b.Property("IntKey") + b.Property("Key") .HasColumnName("Key"); b.Property("RulesetID"); From 31e6a4fa5942a081f730e1ba2db676a045c9ccc5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 25 May 2019 15:09:31 +0900 Subject: [PATCH 0958/5608] Add optional skin foreign key to databased settings --- osu.Game/Configuration/DatabasedSetting.cs | 2 + .../20190525060824_SkinSettings.Designer.cs | 498 ++++++++++++++++++ .../Migrations/20190525060824_SkinSettings.cs | 45 ++ .../Migrations/OsuDbContextModelSnapshot.cs | 11 + osu.Game/Skinning/SkinInfo.cs | 3 + osu.Game/Skinning/SkinStore.cs | 6 + 6 files changed, 565 insertions(+) create mode 100644 osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs create mode 100644 osu.Game/Migrations/20190525060824_SkinSettings.cs diff --git a/osu.Game/Configuration/DatabasedSetting.cs b/osu.Game/Configuration/DatabasedSetting.cs index d56ac49358..035fc73f4f 100644 --- a/osu.Game/Configuration/DatabasedSetting.cs +++ b/osu.Game/Configuration/DatabasedSetting.cs @@ -15,6 +15,8 @@ namespace osu.Game.Configuration public int? Variant { get; set; } + public int? SkinInfoID { get; set; } + [Column("Key")] public int IntKey { diff --git a/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs b/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs new file mode 100644 index 0000000000..348c42adb9 --- /dev/null +++ b/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs @@ -0,0 +1,498 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using osu.Game.Database; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20190525060824_SkinSettings")] + partial class SkinSettings + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.4-servicing-10062"); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("ApproachRate"); + + b.Property("CircleSize"); + + b.Property("DrainRate"); + + b.Property("OverallDifficulty"); + + b.Property("SliderMultiplier"); + + b.Property("SliderTickRate"); + + b.HasKey("ID"); + + b.ToTable("BeatmapDifficulty"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("AudioLeadIn"); + + b.Property("BaseDifficultyID"); + + b.Property("BeatDivisor"); + + b.Property("BeatmapSetInfoID"); + + b.Property("Countdown"); + + b.Property("DistanceSpacing"); + + b.Property("GridSize"); + + b.Property("Hash"); + + b.Property("Hidden"); + + b.Property("LetterboxInBreaks"); + + b.Property("MD5Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapID"); + + b.Property("Path"); + + b.Property("RulesetID"); + + b.Property("SpecialStyle"); + + b.Property("StackLeniency"); + + b.Property("StarDifficulty"); + + b.Property("Status"); + + b.Property("StoredBookmarks"); + + b.Property("TimelineZoom"); + + b.Property("Version"); + + b.Property("WidescreenStoryboard"); + + b.HasKey("ID"); + + b.HasIndex("BaseDifficultyID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("Hash"); + + b.HasIndex("MD5Hash"); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("BeatmapInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Artist"); + + b.Property("ArtistUnicode"); + + b.Property("AudioFile"); + + b.Property("AuthorString") + .HasColumnName("Author"); + + b.Property("BackgroundFile"); + + b.Property("PreviewTime"); + + b.Property("Source"); + + b.Property("Tags"); + + b.Property("Title"); + + b.Property("TitleUnicode"); + + b.HasKey("ID"); + + b.ToTable("BeatmapMetadata"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("BeatmapSetInfoID"); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.HasKey("ID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("FileInfoID"); + + b.ToTable("BeatmapSetFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapSetID"); + + b.Property("Protected"); + + b.Property("Status"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapSetID") + .IsUnique(); + + b.ToTable("BeatmapSetInfo"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Key") + .HasColumnName("Key"); + + b.Property("RulesetID"); + + b.Property("SkinInfoID"); + + b.Property("StringValue") + .HasColumnName("Value"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("SkinInfoID"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("osu.Game.IO.FileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Hash"); + + b.Property("ReferenceCount"); + + b.HasKey("ID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("ReferenceCount"); + + b.ToTable("FileInfo"); + }); + + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntAction") + .HasColumnName("Action"); + + b.Property("KeysString") + .HasColumnName("Keys"); + + b.Property("RulesetID"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("IntAction"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("KeyBinding"); + }); + + modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Available"); + + b.Property("InstantiationInfo"); + + b.Property("Name"); + + b.Property("ShortName"); + + b.HasKey("ID"); + + b.HasIndex("Available"); + + b.HasIndex("ShortName") + .IsUnique(); + + b.ToTable("RulesetInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("ScoreInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("ScoreInfoID"); + + b.ToTable("ScoreFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Accuracy") + .HasColumnType("DECIMAL(1,4)"); + + b.Property("BeatmapInfoID"); + + b.Property("Combo"); + + b.Property("Date"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MaxCombo"); + + b.Property("ModsJson") + .HasColumnName("Mods"); + + b.Property("OnlineScoreID"); + + b.Property("PP"); + + b.Property("Rank"); + + b.Property("RulesetID"); + + b.Property("StatisticsJson") + .HasColumnName("Statistics"); + + b.Property("TotalScore"); + + b.Property("UserID") + .HasColumnName("UserID"); + + b.Property("UserString") + .HasColumnName("User"); + + b.HasKey("ID"); + + b.HasIndex("BeatmapInfoID"); + + b.HasIndex("OnlineScoreID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("ScoreInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("SkinInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("SkinInfoID"); + + b.ToTable("SkinFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Creator"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("Name"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.ToTable("SkinInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") + .WithMany() + .HasForeignKey("BaseDifficultyID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") + .WithMany("Beatmaps") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("Beatmaps") + .HasForeignKey("MetadataID"); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") + .WithMany("Files") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("BeatmapSets") + .HasForeignKey("MetadataID"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Settings") + .HasForeignKey("SkinInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Scoring.ScoreInfo") + .WithMany("Files") + .HasForeignKey("ScoreInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap") + .WithMany("Scores") + .HasForeignKey("BeatmapInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Files") + .HasForeignKey("SkinInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/osu.Game/Migrations/20190525060824_SkinSettings.cs b/osu.Game/Migrations/20190525060824_SkinSettings.cs new file mode 100644 index 0000000000..8bd429ca5c --- /dev/null +++ b/osu.Game/Migrations/20190525060824_SkinSettings.cs @@ -0,0 +1,45 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace osu.Game.Migrations +{ + public partial class SkinSettings : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SkinInfoID", + table: "Settings", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Settings_SkinInfoID", + table: "Settings", + column: "SkinInfoID"); + + // unsupported by sqlite + + // migrationBuilder.AddForeignKey( + // name: "FK_Settings_SkinInfo_SkinInfoID", + // table: "Settings", + // column: "SkinInfoID", + // principalTable: "SkinInfo", + // principalColumn: "ID", + // onDelete: ReferentialAction.Restrict); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Settings_SkinInfo_SkinInfoID", + table: "Settings"); + + migrationBuilder.DropIndex( + name: "IX_Settings_SkinInfoID", + table: "Settings"); + + migrationBuilder.DropColumn( + name: "SkinInfoID", + table: "Settings"); + } + } +} diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 8430e00e4f..d03c2358b5 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -203,6 +203,8 @@ namespace osu.Game.Migrations b.Property("RulesetID"); + b.Property("SkinInfoID"); + b.Property("StringValue") .HasColumnName("Value"); @@ -210,6 +212,8 @@ namespace osu.Game.Migrations b.HasKey("ID"); + b.HasIndex("SkinInfoID"); + b.HasIndex("RulesetID", "Variant"); b.ToTable("Settings"); @@ -442,6 +446,13 @@ namespace osu.Game.Migrations .HasForeignKey("MetadataID"); }); + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Settings") + .HasForeignKey("SkinInfoID"); + }); + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => { b.HasOne("osu.Game.IO.FileInfo", "FileInfo") diff --git a/osu.Game/Skinning/SkinInfo.cs b/osu.Game/Skinning/SkinInfo.cs index 07318b473a..187ea910a7 100644 --- a/osu.Game/Skinning/SkinInfo.cs +++ b/osu.Game/Skinning/SkinInfo.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using osu.Game.Configuration; using osu.Game.Database; namespace osu.Game.Skinning @@ -19,6 +20,8 @@ namespace osu.Game.Skinning public List Files { get; set; } + public List Settings { get; set; } + public bool DeletePending { get; set; } public string FullName => $"\"{Name}\" by {Creator}"; diff --git a/osu.Game/Skinning/SkinStore.cs b/osu.Game/Skinning/SkinStore.cs index 31cadb0a24..153eeda130 100644 --- a/osu.Game/Skinning/SkinStore.cs +++ b/osu.Game/Skinning/SkinStore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; +using Microsoft.EntityFrameworkCore; using osu.Framework.Platform; using osu.Game.Database; @@ -12,5 +14,9 @@ namespace osu.Game.Skinning : base(contextFactory, storage) { } + + protected override IQueryable AddIncludesForDeletion(IQueryable query) => + base.AddIncludesForDeletion(query) + .Include(s => s.Settings); // don't include FileInfo. these are handled by the FileStore itself. } } From e59a00ac6eb1f30cb368392aedb299177fd8a168 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 28 May 2019 14:04:33 +0900 Subject: [PATCH 0959/5608] Remove excessive selection updating --- .../SongSelect/TestScenePlaySongSelect.cs | 28 ++++++++++++++++++- osu.Game/Screens/Select/SongSelect.cs | 8 +++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 7e962dbc06..85811e3a0a 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -209,7 +209,33 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("start not requested", () => !startRequested); } - private void importForRuleset(int id) => AddStep($"import test map for ruleset {id}", () => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray()))); + [Test] + public void TestAddNewBeatmap() + { + const int test_count = 10; + int beatmapChangedCount = 0; + createSongSelect(); + AddStep("Setup counter", () => + { + beatmapChangedCount = 0; + songSelect.Carousel.BeatmapSetsChanged += () => beatmapChangedCount++; + }); + AddRepeatStep($"Create beatmaps {test_count} times", () => + { + manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == 0).ToArray())); + + Scheduler.AddDelayed(() => + { + // Wait for debounce + songSelect.Carousel.SelectNextRandom(); + }, 400); + }, test_count); + + AddAssert($"Beatmap changed {test_count} times", () => beatmapChangedCount == test_count); + } + + private void importForRuleset(int id) => AddStep($"import test map for ruleset {id}", + () => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray()))); private static int importId; private int getImportId() => ++importId; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index fed1f7a944..f30618ce3f 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -597,11 +597,17 @@ namespace osu.Game.Screens.Select { bindBindables(); + // As a selection was already obtained, do not attempt to update the selected beatmap. + if (Carousel.SelectedBeatmapSet != null) + return; + + // Attempt to select the current beatmap on the carousel, if it is valid to be selected. if (!Beatmap.IsDefault && Beatmap.Value.BeatmapSetInfo?.DeletePending == false && Beatmap.Value.BeatmapSetInfo?.Protected == false && Carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo, false)) return; - if (Carousel.SelectedBeatmapSet == null && !Carousel.SelectNextRandom()) + // If the current active beatmap could not be selected, select a new random beatmap. + if (!Carousel.SelectNextRandom()) { // in the case random selection failed, we want to trigger selectionChanged // to show the dummy beatmap (we have nothing else to display). From 436760de967e59400822e25356b502294bd487e3 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 28 May 2019 14:34:52 +0900 Subject: [PATCH 0960/5608] Change test name --- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 85811e3a0a..8e3fe57d92 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -210,7 +210,7 @@ namespace osu.Game.Tests.Visual.SongSelect } [Test] - public void TestAddNewBeatmap() + public void TestAddNewBeatmapWhileSelectingRandom() { const int test_count = 10; int beatmapChangedCount = 0; From 4ca34bd5e8a53752a37c1401c686757a67c943c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 May 2019 17:06:01 +0900 Subject: [PATCH 0961/5608] Update osu! in line with audio subsystem refactor --- .../TestScenePreviewTrackManager.cs | 4 ++-- osu.Game/Audio/PreviewTrackManager.cs | 20 +++++++++---------- osu.Game/Beatmaps/BindableBeatmap.cs | 2 +- .../Containers/OsuFocusedOverlayContainer.cs | 4 ++-- osu.Game/Graphics/ScreenshotManager.cs | 2 +- .../UserInterface/HoverClickSounds.cs | 2 +- .../Graphics/UserInterface/HoverSounds.cs | 2 +- .../Graphics/UserInterface/OsuCheckbox.cs | 4 ++-- osu.Game/Graphics/UserInterface/OsuMenu.cs | 4 ++-- .../Graphics/UserInterface/OsuSliderBar.cs | 2 +- osu.Game/OsuGameBase.cs | 2 +- osu.Game/Overlays/MedalOverlay.cs | 2 +- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 4 ++-- osu.Game/Screens/Menu/Button.cs | 4 ++-- osu.Game/Screens/Menu/ButtonSystem.cs | 2 +- osu.Game/Screens/Menu/Intro.cs | 4 ++-- osu.Game/Screens/Menu/OsuLogo.cs | 4 ++-- osu.Game/Screens/Multi/Multiplayer.cs | 2 +- osu.Game/Screens/OsuScreen.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Play/SkipOverlay.cs | 2 +- .../Select/Carousel/DrawableCarouselItem.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 8 ++++---- osu.Game/Skinning/LegacySkin.cs | 4 ++-- osu.Game/Skinning/SkinnableSound.cs | 2 +- osu.Game/osu.Game.csproj | 4 +++- osu.sln | 12 +++++++++++ 27 files changed, 61 insertions(+), 47 deletions(-) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 94412455a0..e85e879ef5 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -111,11 +111,11 @@ namespace osu.Game.Tests.Visual.Components private class TestPreviewTrackManager : PreviewTrackManager { - protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager) => new TestPreviewTrack(beatmapSetInfo, trackManager); + protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore); protected class TestPreviewTrack : TrackManagerPreviewTrack { - public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager) + public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackStore trackManager) : base(beatmapSetInfo, trackManager) { } diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 99c0d70ac9..695051f508 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -20,19 +20,19 @@ namespace osu.Game.Audio private readonly BindableDouble muteBindable = new BindableDouble(); private AudioManager audio; - private TrackManager trackManager; + private TrackStore trackStore; private TrackManagerPreviewTrack current; [BackgroundDependencyLoader] private void load(AudioManager audio, FrameworkConfigManager config) { - trackManager = new TrackManager(new OnlineStore()); + trackStore = new TrackStore(new OnlineStore()); this.audio = audio; - audio.AddItem(trackManager); + audio.AddItem(trackStore); - config.BindWith(FrameworkSetting.VolumeMusic, trackManager.Volume); + config.BindWith(FrameworkSetting.VolumeMusic, trackStore.Volume); } /// @@ -42,19 +42,19 @@ namespace osu.Game.Audio /// The playable . public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo) { - var track = CreatePreviewTrack(beatmapSetInfo, trackManager); + var track = CreatePreviewTrack(beatmapSetInfo, trackStore); track.Started += () => { current?.Stop(); current = track; - audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable); + audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); }; track.Stopped += () => { current = null; - audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); + audio.Tracks.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); }; return track; @@ -81,16 +81,16 @@ namespace osu.Game.Audio /// /// Creates the . /// - protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager) => new TrackManagerPreviewTrack(beatmapSetInfo, trackManager); + protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackStore trackStore) => new TrackManagerPreviewTrack(beatmapSetInfo, trackStore); protected class TrackManagerPreviewTrack : PreviewTrack { public IPreviewTrackOwner Owner { get; private set; } private readonly BeatmapSetInfo beatmapSetInfo; - private readonly TrackManager trackManager; + private readonly TrackStore trackManager; - public TrackManagerPreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager) + public TrackManagerPreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackStore trackManager) { this.beatmapSetInfo = beatmapSetInfo; this.trackManager = trackManager; diff --git a/osu.Game/Beatmaps/BindableBeatmap.cs b/osu.Game/Beatmaps/BindableBeatmap.cs index 27bad65062..dcce18b1be 100644 --- a/osu.Game/Beatmaps/BindableBeatmap.cs +++ b/osu.Game/Beatmaps/BindableBeatmap.cs @@ -56,7 +56,7 @@ namespace osu.Game.Beatmaps lastBeatmap.RecycleTrack(); } - audioManager.Track.AddItem(beatmap.Track); + audioManager.Tracks.AddItem(beatmap.Track); } lastBeatmap = beatmap; diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 3f84f77081..8b34459710 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -51,8 +51,8 @@ namespace osu.Game.Graphics.Containers if (osuGame != null) OverlayActivationMode.BindTo(osuGame.OverlayActivationMode); - samplePopIn = audio.Sample.Get(@"UI/overlay-pop-in"); - samplePopOut = audio.Sample.Get(@"UI/overlay-pop-out"); + samplePopIn = audio.Samples.Get(@"UI/overlay-pop-in"); + samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out"); StateChanged += onStateChanged; } diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 24a98e6dc9..5ad5e5569a 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -51,7 +51,7 @@ namespace osu.Game.Graphics screenshotFormat = config.GetBindable(OsuSetting.ScreenshotFormat); captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor); - shutter = audio.Sample.Get("UI/shutter"); + shutter = audio.Samples.Get("UI/shutter"); } public bool OnPressed(GlobalAction action) diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index cbbaa6d303..70d988f60e 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -31,7 +31,7 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(AudioManager audio) { - sampleClick = audio.Sample.Get($@"UI/generic-select{SampleSet.GetDescription()}"); + sampleClick = audio.Samples.Get($@"UI/generic-select{SampleSet.GetDescription()}"); } } } diff --git a/osu.Game/Graphics/UserInterface/HoverSounds.cs b/osu.Game/Graphics/UserInterface/HoverSounds.cs index b246092a7f..f1ac8ced6e 100644 --- a/osu.Game/Graphics/UserInterface/HoverSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverSounds.cs @@ -37,7 +37,7 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(AudioManager audio) { - sampleHover = audio.Sample.Get($@"UI/generic-hover{SampleSet.GetDescription()}"); + sampleHover = audio.Samples.Get($@"UI/generic-hover{SampleSet.GetDescription()}"); } } diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 2944fc87af..cd1147e3d3 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -112,8 +112,8 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(AudioManager audio) { - sampleChecked = audio.Sample.Get(@"UI/check-on"); - sampleUnchecked = audio.Sample.Get(@"UI/check-off"); + sampleChecked = audio.Samples.Get(@"UI/check-on"); + sampleUnchecked = audio.Samples.Get(@"UI/check-off"); } } } diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index 32994be78a..f8234cb81f 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -71,8 +71,8 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(AudioManager audio) { - sampleHover = audio.Sample.Get(@"UI/generic-hover"); - sampleClick = audio.Sample.Get(@"UI/generic-select"); + sampleHover = audio.Samples.Get(@"UI/generic-hover"); + sampleClick = audio.Samples.Get(@"UI/generic-select"); BackgroundColour = Color4.Transparent; BackgroundColourHover = OsuColour.FromHex(@"172023"); diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index c3c447ef83..5c706781e6 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -86,7 +86,7 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colours) { - sample = audio.Sample.Get(@"UI/sliderbar-notch"); + sample = audio.Samples.Get(@"UI/sliderbar-notch"); AccentColour = colours.Pink; } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 7b9aed8364..40cb26ec54 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -193,7 +193,7 @@ namespace osu.Game // tracks play so loud our samples can't keep up. // this adds a global reduction of track volume for the time being. - Audio.Track.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8)); + Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8)); beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio); diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 6d82db5603..1f15c773f4 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -145,7 +145,7 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load(OsuColour colours, TextureStore textures, AudioManager audio) { - getSample = audio.Sample.Get(@"MedalSplash/medal-get"); + getSample = audio.Samples.Get(@"MedalSplash/medal-get"); innerSpin.Texture = outerSpin.Texture = textures.Get(@"MedalSplash/disc-spin"); disc.EdgeEffect = leftStrip.EdgeEffect = rightStrip.EdgeEffect = new EdgeEffectParameters diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 97769fe5aa..b675a35970 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -56,8 +56,8 @@ namespace osu.Game.Overlays.Mods Ruleset.BindTo(ruleset); if (mods != null) SelectedMods.BindTo(mods); - sampleOn = audio.Sample.Get(@"UI/check-on"); - sampleOff = audio.Sample.Get(@"UI/check-off"); + sampleOn = audio.Samples.Get(@"UI/check-on"); + sampleOff = audio.Samples.Get(@"UI/check-off"); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index 7d48f619d9..badd1e0549 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -182,9 +182,9 @@ namespace osu.Game.Screens.Menu [BackgroundDependencyLoader] private void load(AudioManager audio) { - sampleHover = audio.Sample.Get(@"Menu/button-hover"); + sampleHover = audio.Samples.Get(@"Menu/button-hover"); if (!string.IsNullOrEmpty(sampleName)) - sampleClick = audio.Sample.Get($@"Menu/{sampleName}"); + sampleClick = audio.Samples.Get($@"Menu/{sampleName}"); } protected override bool OnMouseDown(MouseDownEvent e) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index a098d42c83..11b637801a 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -150,7 +150,7 @@ namespace osu.Game.Screens.Menu if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle); - sampleBack = audio.Sample.Get(@"Menu/button-back-select"); + sampleBack = audio.Samples.Get(@"Menu/button-back-select"); } private void onMulti() diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index 2392d650a0..98a2fe8f13 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -76,8 +76,8 @@ namespace osu.Game.Screens.Menu introBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); track = introBeatmap.Track; - welcome = audio.Sample.Get(@"welcome"); - seeya = audio.Sample.Get(@"seeya"); + welcome = audio.Samples.Get(@"welcome"); + seeya = audio.Samples.Get(@"seeya"); } private const double delay_step_one = 2300; diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 4631f4e222..479b3d80b6 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -255,8 +255,8 @@ namespace osu.Game.Screens.Menu [BackgroundDependencyLoader] private void load(TextureStore textures, AudioManager audio) { - sampleClick = audio.Sample.Get(@"Menu/osu-logo-select"); - sampleBeat = audio.Sample.Get(@"Menu/osu-logo-heartbeat"); + sampleClick = audio.Samples.Get(@"Menu/osu-logo-select"); + sampleBeat = audio.Samples.Get(@"Menu/osu-logo-heartbeat"); logo.Texture = textures.Get(@"Menu/logo"); ripple.Texture = textures.Get(@"Menu/logo"); diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 155665e0d5..9e5c11e098 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -255,7 +255,7 @@ namespace osu.Game.Screens.Multi if (!track.IsRunning) { - game.Audio.AddItemToList(track); + game.Audio.AddItem(track); track.Seek(Beatmap.Value.Metadata.PreviewTime); track.Start(); } diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 9d53e43b80..f7b90e9966 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -99,7 +99,7 @@ namespace osu.Game.Screens [BackgroundDependencyLoader(true)] private void load(OsuGame osu, AudioManager audio) { - sampleExit = audio.Sample.Get(@"UI/screen-back"); + sampleExit = audio.Samples.Get(@"UI/screen-back"); } public virtual bool OnPressed(GlobalAction action) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 30214d1b9c..cf743ee4f7 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -103,7 +103,7 @@ namespace osu.Game.Screens.Play if (working == null) return; - sampleRestart = audio.Sample.Get(@"Gameplay/restart"); + sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); showStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index e3c56e1c2c..4ecc15f22b 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -234,7 +234,7 @@ namespace osu.Game.Screens.Play colourNormal = colours.Yellow; colourHover = colours.YellowDark; - sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); + sampleConfirm = audio.Samples.Get(@"SongSelect/confirm-selection"); Children = new Drawable[] { diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index f1d6343e72..b906bd935c 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -69,7 +69,7 @@ namespace osu.Game.Screens.Select.Carousel } }; - sampleHover = audio.Sample.Get($@"SongSelect/song-ping-variation-{RNG.Next(1, 5)}"); + sampleHover = audio.Samples.Get($@"SongSelect/song-ping-variation-{RNG.Next(1, 5)}"); hoverLayer.Colour = colours.Blue.Opacity(0.1f); } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index fed1f7a944..b266a73eb5 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -242,9 +242,9 @@ namespace osu.Game.Screens.Select dialogOverlay = dialog; - sampleChangeDifficulty = audio.Sample.Get(@"SongSelect/select-difficulty"); - sampleChangeBeatmap = audio.Sample.Get(@"SongSelect/select-expand"); - SampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); + sampleChangeDifficulty = audio.Samples.Get(@"SongSelect/select-difficulty"); + sampleChangeBeatmap = audio.Samples.Get(@"SongSelect/select-expand"); + SampleConfirm = audio.Samples.Get(@"SongSelect/confirm-selection"); Carousel.LoadBeatmapSetsFromManager(this.beatmaps); @@ -582,7 +582,7 @@ namespace osu.Game.Screens.Select { // Ensure the track is added to the TrackManager, since it is removed after the player finishes the map. // Using AddItemToList rather than AddItem so that it doesn't attempt to register adjustment dependencies more than once. - Game.Audio.Track.AddItemToList(track); + Game.Audio.Tracks.AddItem(track); track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; track.Restart(); } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index ea4a777b47..9f31783a6b 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -21,7 +21,7 @@ namespace osu.Game.Skinning { protected TextureStore Textures; - protected SampleManager Samples; + protected SampleStore Samples; public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini") @@ -38,7 +38,7 @@ namespace osu.Game.Skinning else Configuration = new SkinConfiguration(); - Samples = audioManager.GetSampleManager(storage); + Samples = audioManager.GetSampleStore(storage); Textures = new TextureStore(new TextureLoaderStore(storage)); } diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index d6f3625be8..5e8a0ea43f 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -39,7 +39,7 @@ namespace osu.Game.Skinning { var ch = loadChannel(s, skin.GetSample); if (ch == null && allowFallback) - ch = loadChannel(s, audio.Sample.Get); + ch = loadChannel(s, audio.Samples.Get); return ch; }).Where(c => c != null).ToArray(); } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b77c724d1b..185aac4311 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,10 +15,12 @@ - + + + diff --git a/osu.sln b/osu.sln index 3c38309d86..3a60016bda 100644 --- a/osu.sln +++ b/osu.sln @@ -25,6 +25,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests", "osu.Game.Rulesets.Osu.Tests\osu.Game.Rulesets.Osu.Tests.csproj", "{DECCCC75-67AD-4C3D-BB84-FD0E01323511}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework", "..\osu-framework\osu.Framework\osu.Framework.csproj", "{7CCA1C51-AAC8-4153-BAC6-F0E4976602C0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework.NativeLibs", "..\osu-framework\osu.Framework.NativeLibs\osu.Framework.NativeLibs.csproj", "{8EFF6D45-9A38-40B6-9FDC-963DE8472576}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -79,6 +83,14 @@ Global {DECCCC75-67AD-4C3D-BB84-FD0E01323511}.Debug|Any CPU.Build.0 = Debug|Any CPU {DECCCC75-67AD-4C3D-BB84-FD0E01323511}.Release|Any CPU.ActiveCfg = Release|Any CPU {DECCCC75-67AD-4C3D-BB84-FD0E01323511}.Release|Any CPU.Build.0 = Release|Any CPU + {7CCA1C51-AAC8-4153-BAC6-F0E4976602C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7CCA1C51-AAC8-4153-BAC6-F0E4976602C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7CCA1C51-AAC8-4153-BAC6-F0E4976602C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7CCA1C51-AAC8-4153-BAC6-F0E4976602C0}.Release|Any CPU.Build.0 = Release|Any CPU + {8EFF6D45-9A38-40B6-9FDC-963DE8472576}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8EFF6D45-9A38-40B6-9FDC-963DE8472576}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8EFF6D45-9A38-40B6-9FDC-963DE8472576}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EFF6D45-9A38-40B6-9FDC-963DE8472576}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 23b5d303606b5edfcea4e25837b6bed927f8ea8e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 May 2019 17:10:46 +0900 Subject: [PATCH 0962/5608] Remove csproj changes --- osu.Game/osu.Game.csproj | 4 +--- osu.sln | 12 ------------ 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 185aac4311..b77c724d1b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,12 +15,10 @@ + - - - diff --git a/osu.sln b/osu.sln index 3a60016bda..3c38309d86 100644 --- a/osu.sln +++ b/osu.sln @@ -25,10 +25,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests", "osu.Game.Rulesets.Osu.Tests\osu.Game.Rulesets.Osu.Tests.csproj", "{DECCCC75-67AD-4C3D-BB84-FD0E01323511}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework", "..\osu-framework\osu.Framework\osu.Framework.csproj", "{7CCA1C51-AAC8-4153-BAC6-F0E4976602C0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework.NativeLibs", "..\osu-framework\osu.Framework.NativeLibs\osu.Framework.NativeLibs.csproj", "{8EFF6D45-9A38-40B6-9FDC-963DE8472576}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -83,14 +79,6 @@ Global {DECCCC75-67AD-4C3D-BB84-FD0E01323511}.Debug|Any CPU.Build.0 = Debug|Any CPU {DECCCC75-67AD-4C3D-BB84-FD0E01323511}.Release|Any CPU.ActiveCfg = Release|Any CPU {DECCCC75-67AD-4C3D-BB84-FD0E01323511}.Release|Any CPU.Build.0 = Release|Any CPU - {7CCA1C51-AAC8-4153-BAC6-F0E4976602C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7CCA1C51-AAC8-4153-BAC6-F0E4976602C0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7CCA1C51-AAC8-4153-BAC6-F0E4976602C0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7CCA1C51-AAC8-4153-BAC6-F0E4976602C0}.Release|Any CPU.Build.0 = Release|Any CPU - {8EFF6D45-9A38-40B6-9FDC-963DE8472576}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8EFF6D45-9A38-40B6-9FDC-963DE8472576}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8EFF6D45-9A38-40B6-9FDC-963DE8472576}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8EFF6D45-9A38-40B6-9FDC-963DE8472576}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 1a871af5520113372c38d70740337dc794fe2b30 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 28 May 2019 19:15:29 +0900 Subject: [PATCH 0963/5608] Fix hide selection, add test --- .../Visual/SongSelect/TestScenePlaySongSelect.cs | 12 ++++++++++++ osu.Game/Screens/Select/BeatmapCarousel.cs | 5 ++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 8e3fe57d92..c33528c3bf 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -234,6 +234,18 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert($"Beatmap changed {test_count} times", () => beatmapChangedCount == test_count); } + [Test] + public void TestHideSetSelectsCorrectBeatmap() + { + int? previousID = null; + createSongSelect(); + importForRuleset(0); + AddStep("Move to last difficulty", () => songSelect.Carousel.SelectBeatmap(songSelect.Carousel.BeatmapSets.First().Beatmaps.Last())); + AddStep("Store current ID", () => previousID = songSelect.Carousel.SelectedBeatmap.ID); + AddStep("Hide first beatmap", () => manager.Hide(songSelect.Carousel.SelectedBeatmapSet.Beatmaps.First())); + AddAssert("Selected beatmap has not changed", () => songSelect.Carousel.SelectedBeatmap.ID == previousID); + } + private void importForRuleset(int id) => AddStep($"import test map for ruleset {id}", () => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray()))); diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 63ad3b6ab2..0b3d0c448b 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -158,6 +158,9 @@ namespace osu.Game.Screens.Select var newSet = createCarouselSet(beatmapSet); + // Since we're about to remove the selected beatmap, store its ID so we can go back if needed. + var previouslySelectedID = selectedBeatmap?.Beatmap.ID; + if (existingSet != null) root.RemoveChild(existingSet); @@ -173,7 +176,7 @@ namespace osu.Game.Screens.Select //check if we can/need to maintain our current selection. if (hadSelection) - select((CarouselItem)newSet.Beatmaps.FirstOrDefault(b => b.Beatmap.ID == selectedBeatmap?.Beatmap.ID) ?? newSet); + select((CarouselItem)newSet.Beatmaps.FirstOrDefault(b => b.Beatmap.ID == previouslySelectedID) ?? newSet); itemsCache.Invalidate(); Schedule(() => BeatmapSetsChanged?.Invoke()); From 6ca3bd086f54894a0f02ca29ea7dfcd13bc91786 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 28 May 2019 17:04:05 +0300 Subject: [PATCH 0964/5608] ShowMore button update --- .../Beatmaps/PaginatedBeatmapContainer.cs | 4 +- .../PaginatedMostPlayedBeatmapContainer.cs | 4 +- .../Profile/Sections/PaginatedContainer.cs | 161 +++++++++++++++--- .../Sections/Ranks/PaginatedScoreContainer.cs | 10 +- .../PaginatedRecentActivityContainer.cs | 4 +- 5 files changed, 146 insertions(+), 37 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 0fc1398f5d..db291d0731 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -34,8 +34,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage); request.Success += sets => Schedule(() => { - ShowMoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0); - ShowMoreLoading.Hide(); + MoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0); + MoreButton.IsLoading = false; if (!sets.Any() && VisiblePages == 1) { diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index f2eb32c53b..0f86e0900e 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -29,8 +29,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); request.Success += beatmaps => Schedule(() => { - ShowMoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0); - ShowMoreLoading.Hide(); + MoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0); + MoreButton.IsLoading = false; if (!beatmaps.Any() && VisiblePages == 1) { diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 46c65b9db7..1ebc51b11f 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -7,11 +7,15 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Rulesets; +using osu.Framework.Input.Events; +using System; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osuTK.Graphics; using osu.Game.Users; namespace osu.Game.Overlays.Profile.Sections @@ -19,8 +23,7 @@ namespace osu.Game.Overlays.Profile.Sections public class PaginatedContainer : FillFlowContainer { protected readonly FillFlowContainer ItemsContainer; - protected readonly OsuHoverContainer ShowMoreButton; - protected readonly LoadingAnimation ShowMoreLoading; + protected readonly ShowMoreButton MoreButton; protected readonly OsuSpriteText MissingText; protected int VisiblePages; @@ -45,38 +48,25 @@ namespace osu.Game.Overlays.Profile.Sections new OsuSpriteText { Text = header, - Font = OsuFont.GetFont(size: 15, weight: FontWeight.Regular, italics: true), + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold), Margin = new MarginPadding { Top = 10, Bottom = 10 }, }, ItemsContainer = new FillFlowContainer { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, - Margin = new MarginPadding { Bottom = 10 } + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 2), }, - ShowMoreButton = new OsuHoverContainer + MoreButton = new ShowMoreButton { Alpha = 0, + Margin = new MarginPadding { Top = 10 }, Action = ShowMore, - AutoSizeAxes = Axes.Both, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Child = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 14), - Text = "show more", - Padding = new MarginPadding { Vertical = 10, Horizontal = 15 }, - } - }, - ShowMoreLoading = new LoadingAnimation - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Size = new Vector2(14), }, MissingText = new OsuSpriteText { - Font = OsuFont.GetFont(size: 14), + Font = OsuFont.GetFont(size: 15), Text = missing, Alpha = 0, }, @@ -97,16 +87,135 @@ namespace osu.Game.Overlays.Profile.Sections { VisiblePages = 0; ItemsContainer.Clear(); - ShowMoreButton.Hide(); if (e.NewValue != null) ShowMore(); } - protected virtual void ShowMore() + protected virtual void ShowMore() => MoreButton.IsLoading = true; + + protected class ShowMoreButton : CircularContainer { - ShowMoreLoading.Show(); - ShowMoreButton.Hide(); + private const int duration = 300; + private Color4 idleColour; + private Color4 hoveredColour; + + public Action Action; + private readonly Box background; + private readonly LoadingAnimation loading; + private readonly FillFlowContainer content; + + private bool isLoading; + public bool IsLoading + { + set + { + isLoading = value; + + if (value) + { + loading.FadeIn(duration, Easing.OutQuint); + content.FadeOut(duration, Easing.OutQuint); + } + else + { + loading.FadeOut(duration, Easing.OutQuint); + content.FadeIn(duration, Easing.OutQuint); + } + } + get + { + return isLoading; + } + } + + public ShowMoreButton() + { + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; + Masking = true; + Size = new Vector2(140, 30); + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + content = new FillFlowContainer + { + Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7), + Children = new Drawable[] + { + new ChevronIcon(), + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), + Text = "show more".ToUpper(), + }, + new ChevronIcon(), + } + }, + loading = new LoadingAnimation + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(20) + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colors) + { + background.Colour = idleColour = colors.GreySeafoam; + hoveredColour = colors.GreySeafoamLight; + } + + protected override bool OnHover(HoverEvent e) + { + background.FadeColour(hoveredColour, duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + background.FadeColour(idleColour, duration, Easing.OutQuint); + base.OnHoverLost(e); + } + + protected override bool OnClick(ClickEvent e) + { + Action.Invoke(); + return base.OnClick(e); + } + + private class ChevronIcon : SpriteIcon + { + private const int bottom_margin = 2; + private const int icon_size = 8; + + public ChevronIcon() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + Margin = new MarginPadding { Bottom = bottom_margin }; + Size = new Vector2(icon_size); + Icon = FontAwesome.Solid.ChevronDown; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colors) + { + Colour = colors.Yellow; + } + } } } } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 470bed2854..1d9e3d1cc1 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests; using osu.Game.Users; @@ -9,6 +8,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; +using osu.Framework.Graphics; namespace osu.Game.Overlays.Profile.Sections.Ranks { @@ -41,8 +41,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks if (!scores.Any() && VisiblePages == 1) { - ShowMoreButton.Hide(); - ShowMoreLoading.Hide(); + MoreButton.Hide(); + MoreButton.IsLoading = false; MissingText.Show(); return; } @@ -63,8 +63,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks LoadComponentsAsync(drawableScores, s => { MissingText.Hide(); - ShowMoreButton.FadeTo(scores.Count == ItemsPerPage ? 1 : 0); - ShowMoreLoading.Hide(); + MoreButton.FadeTo(scores.Count == ItemsPerPage ? 1 : 0); + MoreButton.IsLoading = false; ItemsContainer.AddRange(s); }); diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index 4b4acb8fbc..38134ad660 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -27,8 +27,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); request.Success += activities => Schedule(() => { - ShowMoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0); - ShowMoreLoading.Hide(); + MoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0); + MoreButton.IsLoading = false; if (!activities.Any() && VisiblePages == 1) { From 857eb9b83a5a5cfab6865d06807ad58af5aa1aa1 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 28 May 2019 17:21:34 +0300 Subject: [PATCH 0965/5608] Fix CI stuff --- osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 1ebc51b11f..7e13a90f25 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -106,6 +106,7 @@ namespace osu.Game.Overlays.Profile.Sections private readonly FillFlowContainer content; private bool isLoading; + public bool IsLoading { set @@ -123,10 +124,7 @@ namespace osu.Game.Overlays.Profile.Sections content.FadeIn(duration, Easing.OutQuint); } } - get - { - return isLoading; - } + get => isLoading; } public ShowMoreButton() From a20eda7b5f99eb4bd35b88c3c73bcf3e1d4dca95 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 May 2019 23:54:42 +0900 Subject: [PATCH 0966/5608] Fix remaining cases to work without things --- .../TestScenePreviewTrackManager.cs | 5 ++- osu.Game/Audio/PreviewTrackManager.cs | 11 +++--- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 18 ++++++--- osu.Game/Beatmaps/BindableBeatmap.cs | 38 +++++++------------ osu.Game/Beatmaps/WorkingBeatmap.cs | 6 ++- osu.Game/OsuGameBase.cs | 11 +++--- osu.Game/Overlays/MusicController.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 3 -- osu.Game/Skinning/LegacySkin.cs | 9 ++++- osu.Game/Tests/Visual/OsuTestScene.cs | 12 ++---- 10 files changed, 58 insertions(+), 57 deletions(-) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index e85e879ef5..0784725ea4 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -5,6 +5,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Containers; +using osu.Framework.IO.Stores; using osu.Game.Audio; using osu.Game.Beatmaps; @@ -111,11 +112,11 @@ namespace osu.Game.Tests.Visual.Components private class TestPreviewTrackManager : PreviewTrackManager { - protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore); + protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, IResourceStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore); protected class TestPreviewTrack : TrackManagerPreviewTrack { - public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackStore trackManager) + public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, IResourceStore trackManager) : base(beatmapSetInfo, trackManager) { } diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 695051f508..4b7277c3fd 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -20,17 +20,16 @@ namespace osu.Game.Audio private readonly BindableDouble muteBindable = new BindableDouble(); private AudioManager audio; - private TrackStore trackStore; + private IAdjustableResourceStore trackStore; private TrackManagerPreviewTrack current; [BackgroundDependencyLoader] private void load(AudioManager audio, FrameworkConfigManager config) { - trackStore = new TrackStore(new OnlineStore()); + trackStore = audio.GetTrackStore(new OnlineStore()); this.audio = audio; - audio.AddItem(trackStore); config.BindWith(FrameworkSetting.VolumeMusic, trackStore.Volume); } @@ -81,16 +80,16 @@ namespace osu.Game.Audio /// /// Creates the . /// - protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackStore trackStore) => new TrackManagerPreviewTrack(beatmapSetInfo, trackStore); + protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, IResourceStore trackStore) => new TrackManagerPreviewTrack(beatmapSetInfo, trackStore); protected class TrackManagerPreviewTrack : PreviewTrack { public IPreviewTrackOwner Owner { get; private set; } private readonly BeatmapSetInfo beatmapSetInfo; - private readonly TrackStore trackManager; + private readonly IResourceStore trackManager; - public TrackManagerPreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackStore trackManager) + public TrackManagerPreviewTrack(BeatmapSetInfo beatmapSetInfo, IResourceStore trackManager) { this.beatmapSetInfo = beatmapSetInfo; this.trackManager = trackManager; diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 0bdab22dd2..cfeb6b0a92 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -20,14 +20,13 @@ namespace osu.Game.Beatmaps protected class BeatmapManagerWorkingBeatmap : WorkingBeatmap { private readonly IResourceStore store; - private readonly AudioManager audioManager; public BeatmapManagerWorkingBeatmap(IResourceStore store, TextureStore textureStore, BeatmapInfo beatmapInfo, AudioManager audioManager) : base(beatmapInfo) { this.store = store; this.textureStore = textureStore; - this.audioManager = audioManager; + AudioManager = audioManager; } protected override IBeatmap GetBeatmap() @@ -47,6 +46,8 @@ namespace osu.Game.Beatmaps private TextureStore textureStore; + private IAdjustableResourceStore trackStore; + protected override bool BackgroundStillValid(Texture b) => false; // bypass lazy logic. we want to return a new background each time for refcounting purposes. protected override Texture GetBackground() @@ -68,8 +69,7 @@ namespace osu.Game.Beatmaps { try { - var trackData = store.GetStream(getPathForFile(Metadata.AudioFile)); - return trackData == null ? null : new TrackBass(trackData); + return (trackStore ?? (trackStore = AudioManager.GetTrackStore(store))).Get(getPathForFile(Metadata.AudioFile)); } catch { @@ -77,6 +77,14 @@ namespace osu.Game.Beatmaps } } + public override void RecycleTrack() + { + base.RecycleTrack(); + + trackStore?.Dispose(); + trackStore = null; + } + public override void TransferTo(WorkingBeatmap other) { base.TransferTo(other); @@ -135,7 +143,7 @@ namespace osu.Game.Beatmaps try { - skin = new LegacyBeatmapSkin(BeatmapInfo, store, audioManager); + skin = new LegacyBeatmapSkin(BeatmapInfo, store, AudioManager); } catch (Exception e) { diff --git a/osu.Game/Beatmaps/BindableBeatmap.cs b/osu.Game/Beatmaps/BindableBeatmap.cs index dcce18b1be..6614a6f2fb 100644 --- a/osu.Game/Beatmaps/BindableBeatmap.cs +++ b/osu.Game/Beatmaps/BindableBeatmap.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Audio; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; namespace osu.Game.Beatmaps @@ -16,32 +14,26 @@ namespace osu.Game.Beatmaps /// public abstract class BindableBeatmap : NonNullableBindable { - private AudioManager audioManager; + protected AudioManager AudioManager; + private WorkingBeatmap lastBeatmap; - protected BindableBeatmap(WorkingBeatmap defaultValue) + protected BindableBeatmap(WorkingBeatmap defaultValue, AudioManager audioManager) : base(defaultValue) { + // we don't want to attempt to update tracks if we are a bound copy. + if (audioManager != null) + { + AudioManager = audioManager; + ValueChanged += b => updateAudioTrack(b.NewValue); + + // If the track has changed prior to this being called, let's register it + if (Value != Default) + updateAudioTrack(Value); + } } - /// - /// Registers an for s to be added to. - /// - /// The to register. - protected void RegisterAudioManager([NotNull] AudioManager audioManager) - { - if (this.audioManager != null) throw new InvalidOperationException($"Cannot register multiple {nameof(AudioManager)}s."); - - this.audioManager = audioManager; - - ValueChanged += b => registerAudioTrack(b.NewValue); - - // If the track has changed prior to this being called, let's register it - if (Value != Default) - registerAudioTrack(Value); - } - - private void registerAudioTrack(WorkingBeatmap beatmap) + private void updateAudioTrack(WorkingBeatmap beatmap) { var trackLoaded = lastBeatmap?.TrackLoaded ?? false; @@ -55,8 +47,6 @@ namespace osu.Game.Beatmaps lastBeatmap.RecycleTrack(); } - - audioManager.Tracks.AddItem(beatmap.Track); } lastBeatmap = beatmap; diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 4b0720d867..288bd0773c 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -11,6 +11,7 @@ using osu.Framework.IO.File; using System.IO; using System.Linq; using System.Threading; +using osu.Framework.Audio; using osu.Game.IO.Serialization; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; @@ -150,6 +151,9 @@ namespace osu.Game.Beatmaps public bool SkinLoaded => skin.IsResultAvailable; public Skin Skin => skin.Value; + + public AudioManager AudioManager { get; set; } + protected virtual Skin GetSkin() => new DefaultSkin(); private readonly RecyclableLazy skin; @@ -175,7 +179,7 @@ namespace osu.Game.Beatmaps /// Eagerly dispose of the audio track associated with this (if any). /// Accessing track again will load a fresh instance. /// - public void RecycleTrack() => track.Recycle(); + public virtual void RecycleTrack() => track.Recycle(); public class RecyclableLazy { diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 40cb26ec54..8e663de8c5 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -281,20 +281,19 @@ namespace osu.Game private class OsuBindableBeatmap : BindableBeatmap { - public OsuBindableBeatmap(WorkingBeatmap defaultValue, AudioManager audioManager) - : this(defaultValue) + public OsuBindableBeatmap(WorkingBeatmap defaultValue) + : base(defaultValue, null) { - RegisterAudioManager(audioManager); } - public OsuBindableBeatmap(WorkingBeatmap defaultValue) - : base(defaultValue) + public OsuBindableBeatmap(WorkingBeatmap defaultValue, AudioManager audioManager) + : base(defaultValue, audioManager) { } public override BindableBeatmap GetBoundCopy() { - var copy = new OsuBindableBeatmap(Default); + var copy = new OsuBindableBeatmap(Default, AudioManager); copy.BindTo(this); return copy; } diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index ea3e1ca00c..d7b915efe3 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -350,7 +350,7 @@ namespace osu.Game.Overlays direction = last > next ? TransformDirection.Prev : TransformDirection.Next; } - current.Track.Completed -= currentTrackCompleted; + //current.Track.Completed -= currentTrackCompleted; } current = beatmap.NewValue; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index b266a73eb5..6d5be607f4 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -580,9 +580,6 @@ namespace osu.Game.Screens.Select if (!track.IsRunning || restart) { - // Ensure the track is added to the TrackManager, since it is removed after the player finishes the map. - // Using AddItemToList rather than AddItem so that it doesn't attempt to register adjustment dependencies more than once. - Game.Audio.Tracks.AddItem(track); track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; track.Restart(); } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 9f31783a6b..8d38f944d0 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -21,7 +21,7 @@ namespace osu.Game.Skinning { protected TextureStore Textures; - protected SampleStore Samples; + protected IResourceStore Samples; public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini") @@ -42,6 +42,13 @@ namespace osu.Game.Skinning Textures = new TextureStore(new TextureLoaderStore(storage)); } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + Textures?.Dispose(); + Samples?.Dispose(); + } + public override Drawable GetDrawableComponent(string componentName) { switch (componentName) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 9b775fd498..806b73b517 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual { [Cached(typeof(Bindable))] [Cached(typeof(IBindable))] - private readonly OsuTestBeatmap beatmap = new OsuTestBeatmap(new DummyWorkingBeatmap()); + private readonly OsuTestBeatmap beatmap = new OsuTestBeatmap(new DummyWorkingBeatmap(), null); protected BindableBeatmap Beatmap => beatmap; @@ -52,8 +52,6 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load(AudioManager audioManager, RulesetStore rulesets) { - beatmap.SetAudioManager(audioManager); - Ruleset.Value = rulesets.AvailableRulesets.First(); } @@ -95,16 +93,14 @@ namespace osu.Game.Tests.Visual private class OsuTestBeatmap : BindableBeatmap { - public OsuTestBeatmap(WorkingBeatmap defaultValue) - : base(defaultValue) + public OsuTestBeatmap(WorkingBeatmap defaultValue, AudioManager audioManager) + : base(defaultValue, audioManager) { } - public void SetAudioManager(AudioManager audioManager) => RegisterAudioManager(audioManager); - public override BindableBeatmap GetBoundCopy() { - var copy = new OsuTestBeatmap(Default); + var copy = new OsuTestBeatmap(Default, AudioManager); copy.BindTo(this); return copy; } From d4f3c60dd4d5b3c6fe8a899c6af07b8964fc1228 Mon Sep 17 00:00:00 2001 From: tangalbert919 Date: Tue, 28 May 2019 11:22:52 -0500 Subject: [PATCH 0967/5608] Update resources and framework for Android --- osu.Android.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 028b4bda83..6a4a29fcf8 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,7 +63,7 @@ - - + + From 19fbab68928128641a15681a84f1611d58cf2870 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 28 May 2019 19:39:31 +0300 Subject: [PATCH 0968/5608] Applied suggested changes --- .../Sections/Beatmaps/PaginatedBeatmapContainer.cs | 2 -- .../Historical/PaginatedMostPlayedBeatmapContainer.cs | 2 -- .../Overlays/Profile/Sections/PaginatedContainer.cs | 10 ++++++---- .../Profile/Sections/Ranks/PaginatedScoreContainer.cs | 2 -- .../Recent/PaginatedRecentActivityContainer.cs | 2 -- 5 files changed, 6 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index db291d0731..b6b0e605d7 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -29,8 +29,6 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps protected override void ShowMore() { - base.ShowMore(); - request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage); request.Success += sets => Schedule(() => { diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index 0f86e0900e..6085b0bc05 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -24,8 +24,6 @@ namespace osu.Game.Overlays.Profile.Sections.Historical protected override void ShowMore() { - base.ShowMore(); - request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); request.Success += beatmaps => Schedule(() => { diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 7e13a90f25..99229a9bce 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -20,7 +20,7 @@ using osu.Game.Users; namespace osu.Game.Overlays.Profile.Sections { - public class PaginatedContainer : FillFlowContainer + public abstract class PaginatedContainer : FillFlowContainer { protected readonly FillFlowContainer ItemsContainer; protected readonly ShowMoreButton MoreButton; @@ -92,7 +92,7 @@ namespace osu.Game.Overlays.Profile.Sections ShowMore(); } - protected virtual void ShowMore() => MoreButton.IsLoading = true; + protected abstract void ShowMore(); protected class ShowMoreButton : CircularContainer { @@ -109,8 +109,11 @@ namespace osu.Game.Overlays.Profile.Sections public bool IsLoading { + get => isLoading; set { + if (isLoading == value) + return; isLoading = value; if (value) @@ -124,7 +127,6 @@ namespace osu.Game.Overlays.Profile.Sections content.FadeIn(duration, Easing.OutQuint); } } - get => isLoading; } public ShowMoreButton() @@ -141,7 +143,6 @@ namespace osu.Game.Overlays.Profile.Sections }, content = new FillFlowContainer { - Alpha = 0, Anchor = Anchor.Centre, Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, @@ -190,6 +191,7 @@ namespace osu.Game.Overlays.Profile.Sections protected override bool OnClick(ClickEvent e) { + IsLoading = true; Action.Invoke(); return base.OnClick(e); } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 1d9e3d1cc1..a149cfa12e 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -31,8 +31,6 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks protected override void ShowMore() { - base.ShowMore(); - request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage); request.Success += scores => Schedule(() => { diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index 38134ad660..b72aec7a44 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -22,8 +22,6 @@ namespace osu.Game.Overlays.Profile.Sections.Recent protected override void ShowMore() { - base.ShowMore(); - request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); request.Success += activities => Schedule(() => { From 5169e31d54ea77eeabfc4fe14333fdb91d53147e Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 28 May 2019 19:53:00 +0300 Subject: [PATCH 0969/5608] Fix CI issues --- osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 99229a9bce..6e0729c7c5 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.Profile.Sections protected APIRequest RetrievalRequest; protected RulesetStore Rulesets; - public PaginatedContainer(Bindable user, string header, string missing) + protected PaginatedContainer(Bindable user, string header, string missing) { User.BindTo(user); @@ -114,6 +114,7 @@ namespace osu.Game.Overlays.Profile.Sections { if (isLoading == value) return; + isLoading = value; if (value) From 4f091417189baf51bf504cf401a914fe8d568234 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 29 May 2019 12:22:34 +0900 Subject: [PATCH 0970/5608] remove extra bool --- osu.Game/Screens/Select/BeatmapCarousel.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 0b3d0c448b..6e3bec106f 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -152,15 +152,15 @@ namespace osu.Game.Screens.Select { Schedule(() => { + int? previouslySelectedID = null; CarouselBeatmapSet existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID); - bool hadSelection = existingSet?.State?.Value == CarouselItemState.Selected; + // Since we're about to remove the selected beatmap, store its ID so we can go back if needed. + if (existingSet?.State?.Value == CarouselItemState.Selected) + previouslySelectedID = selectedBeatmap?.Beatmap.ID; var newSet = createCarouselSet(beatmapSet); - // Since we're about to remove the selected beatmap, store its ID so we can go back if needed. - var previouslySelectedID = selectedBeatmap?.Beatmap.ID; - if (existingSet != null) root.RemoveChild(existingSet); @@ -175,7 +175,7 @@ namespace osu.Game.Screens.Select applyActiveCriteria(false, false); //check if we can/need to maintain our current selection. - if (hadSelection) + if (previouslySelectedID != null) select((CarouselItem)newSet.Beatmaps.FirstOrDefault(b => b.Beatmap.ID == previouslySelectedID) ?? newSet); itemsCache.Invalidate(); From 08ab1e5df7ee4fc1bd48231bbcb2f0a35f9e680a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 May 2019 16:43:15 +0900 Subject: [PATCH 0971/5608] Use new ITrackStore interface --- .../Visual/Components/TestScenePreviewTrackManager.cs | 5 +++-- osu.Game/Audio/PreviewTrackManager.cs | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 0784725ea4..c966eb53d7 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.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 NUnit.Framework; @@ -112,11 +112,12 @@ namespace osu.Game.Tests.Visual.Components private class TestPreviewTrackManager : PreviewTrackManager { - protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, IResourceStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore); + protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore); protected class TestPreviewTrack : TrackManagerPreviewTrack { public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, IResourceStore trackManager) + public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackManager) : base(beatmapSetInfo, trackManager) { } diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 4b7277c3fd..d479483508 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -20,7 +20,7 @@ namespace osu.Game.Audio private readonly BindableDouble muteBindable = new BindableDouble(); private AudioManager audio; - private IAdjustableResourceStore trackStore; + private ITrackStore trackStore; private TrackManagerPreviewTrack current; @@ -80,16 +80,16 @@ namespace osu.Game.Audio /// /// Creates the . /// - protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, IResourceStore trackStore) => new TrackManagerPreviewTrack(beatmapSetInfo, trackStore); + protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TrackManagerPreviewTrack(beatmapSetInfo, trackStore); protected class TrackManagerPreviewTrack : PreviewTrack { public IPreviewTrackOwner Owner { get; private set; } private readonly BeatmapSetInfo beatmapSetInfo; - private readonly IResourceStore trackManager; + private readonly ITrackStore trackManager; - public TrackManagerPreviewTrack(BeatmapSetInfo beatmapSetInfo, IResourceStore trackManager) + public TrackManagerPreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackManager) { this.beatmapSetInfo = beatmapSetInfo; this.trackManager = trackManager; From a1cc8c448fb197bc40c6598b023a2c1693cc4923 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 May 2019 16:43:27 +0900 Subject: [PATCH 0972/5608] Update TrackVirtual consumption --- .../TestScenePreviewTrackManager.cs | 9 ++-- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 31 +++++++++++++- .../WorkingBeatmap_VirtualBeatmapTrack.cs | 41 ------------------- 4 files changed, 35 insertions(+), 48 deletions(-) delete mode 100644 osu.Game/Beatmaps/WorkingBeatmap_VirtualBeatmapTrack.cs diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index c966eb53d7..df6740421b 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -1,11 +1,10 @@ -// 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 NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Containers; -using osu.Framework.IO.Stores; using osu.Game.Audio; using osu.Game.Beatmaps; @@ -116,13 +115,15 @@ namespace osu.Game.Tests.Visual.Components protected class TestPreviewTrack : TrackManagerPreviewTrack { - public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, IResourceStore trackManager) + private readonly ITrackStore trackManager; + public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackManager) : base(beatmapSetInfo, trackManager) { + this.trackManager = trackManager; } - protected override Track GetTrack() => new TrackVirtual { Length = 100000 }; + protected override Track GetTrack() => trackManager.GetVirtual(100000); } } } diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 7d25ca3ede..b35e98085a 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -43,7 +43,7 @@ namespace osu.Game.Beatmaps protected override Texture GetBackground() => game?.Textures.Get(@"Backgrounds/bg4"); - protected override Track GetTrack() => new TrackVirtual { Length = 1000 }; + protected override Track GetTrack() => game?.Audio.Tracks.GetVirtual(1000); private class DummyRulesetInfo : RulesetInfo { diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 288bd0773c..6c8f283923 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -15,12 +15,13 @@ using osu.Framework.Audio; using osu.Game.IO.Serialization; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; using osu.Game.Skinning; namespace osu.Game.Beatmaps { - public abstract partial class WorkingBeatmap : IDisposable + public abstract class WorkingBeatmap : IDisposable { public readonly BeatmapInfo BeatmapInfo; @@ -47,13 +48,39 @@ namespace osu.Game.Beatmaps return b; }); - track = new RecyclableLazy(() => GetTrack() ?? new VirtualBeatmapTrack(Beatmap)); + track = new RecyclableLazy(() => GetTrack() ?? GetVirtualTrack(Beatmap)); background = new RecyclableLazy(GetBackground, BackgroundStillValid); waveform = new RecyclableLazy(GetWaveform); storyboard = new RecyclableLazy(GetStoryboard); skin = new RecyclableLazy(GetSkin); } + protected virtual Track GetVirtualTrack(IBeatmap beatmap) + { + const double excess_length = 1000; + + var lastObject = beatmap.HitObjects.LastOrDefault(); + + double length; + + switch (lastObject) + { + case null: + length = excess_length; + break; + + case IHasEndTime endTime: + length = endTime.EndTime + excess_length; + break; + + default: + length = lastObject.StartTime + excess_length; + break; + } + + return AudioManager.Tracks.GetVirtual(length); + } + /// /// Saves the . /// diff --git a/osu.Game/Beatmaps/WorkingBeatmap_VirtualBeatmapTrack.cs b/osu.Game/Beatmaps/WorkingBeatmap_VirtualBeatmapTrack.cs deleted file mode 100644 index 1e237a2b53..0000000000 --- a/osu.Game/Beatmaps/WorkingBeatmap_VirtualBeatmapTrack.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Linq; -using osu.Framework.Audio.Track; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; - -namespace osu.Game.Beatmaps -{ - public partial class WorkingBeatmap - { - /// - /// A type of which provides a valid length based on the s of an . - /// - protected class VirtualBeatmapTrack : TrackVirtual - { - private const double excess_length = 1000; - - public VirtualBeatmapTrack(IBeatmap beatmap) - { - var lastObject = beatmap.HitObjects.LastOrDefault(); - - switch (lastObject) - { - case null: - Length = excess_length; - break; - - case IHasEndTime endTime: - Length = endTime.EndTime + excess_length; - break; - - default: - Length = lastObject.StartTime + excess_length; - break; - } - } - } - } -} From 7e9f5a0939d41a262a9d19da778b54e140032346 Mon Sep 17 00:00:00 2001 From: HoLLy Date: Wed, 29 May 2019 11:22:51 +0200 Subject: [PATCH 0973/5608] Add Skills to DifficultyAttributes --- .../Difficulty/CatchDifficultyCalculator.cs | 5 +++-- .../Difficulty/ManiaDifficultyCalculator.cs | 3 ++- osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs | 5 +++-- .../Difficulty/TaikoDifficultyCalculator.cs | 3 ++- osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs | 5 ++++- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index d6a1ed632b..44e1a8e5cc 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) - return new CatchDifficultyAttributes { Mods = mods }; + return new CatchDifficultyAttributes { Mods = mods, Skills = skills }; // this is the same as osu!, so there's potential to share the implementation... maybe double preempt = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate; @@ -41,7 +41,8 @@ namespace osu.Game.Rulesets.Catch.Difficulty StarRating = Math.Sqrt(skills[0].DifficultyValue()) * star_scaling_factor, Mods = mods, ApproachRate = preempt > 1200.0 ? -(preempt - 1800.0) / 120.0 : -(preempt - 1200.0) / 150.0 + 5.0, - MaxCombo = beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet)) + MaxCombo = beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet)), + Skills = skills }; } diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index 59fed1031f..4a9c22d339 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) - return new ManiaDifficultyAttributes { Mods = mods }; + return new ManiaDifficultyAttributes { Mods = mods, Skills = skills }; return new ManiaDifficultyAttributes { @@ -38,6 +38,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty Mods = mods, // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate, + Skills = skills }; } diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index e2a1542574..c197933233 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) - return new OsuDifficultyAttributes { Mods = mods }; + return new OsuDifficultyAttributes { Mods = mods, Skills = skills }; double aimRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier; double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; @@ -50,7 +50,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty SpeedStrain = speedRating, ApproachRate = preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5, OverallDifficulty = (80 - hitWindowGreat) / 6, - MaxCombo = maxCombo + MaxCombo = maxCombo, + Skills = skills }; } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 685ad9949b..c8f3e18911 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) - return new TaikoDifficultyAttributes { Mods = mods }; + return new TaikoDifficultyAttributes { Mods = mods, Skills = skills }; return new TaikoDifficultyAttributes { @@ -36,6 +36,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate, MaxCombo = beatmap.HitObjects.Count(h => h is Hit), + Skills = skills }; } diff --git a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs index d808ee528e..b4b4bb9cd1 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Difficulty @@ -8,6 +9,7 @@ namespace osu.Game.Rulesets.Difficulty public class DifficultyAttributes { public Mod[] Mods; + public Skill[] Skills; public double StarRating; @@ -15,9 +17,10 @@ namespace osu.Game.Rulesets.Difficulty { } - public DifficultyAttributes(Mod[] mods, double starRating) + public DifficultyAttributes(Mod[] mods, Skill[] skills, double starRating) { Mods = mods; + Skills = skills; StarRating = starRating; } } From 2a295545a79b89c18447e0aee599eb5a6c27a04e Mon Sep 17 00:00:00 2001 From: HoLLy Date: Wed, 29 May 2019 11:25:25 +0200 Subject: [PATCH 0974/5608] Don't mutate strainPeaks --- osu.Game/Rulesets/Difficulty/Skills/Skill.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Difficulty/Skills/Skill.cs b/osu.Game/Rulesets/Difficulty/Skills/Skill.cs index e8020ed185..227f2f4018 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/Skill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/Skill.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Utils; @@ -17,7 +18,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills /// /// The peak strain for each section of the beatmap. /// - public IList StrainPeaks => strainPeaks; + public IReadOnlyList StrainPeaks => strainPeaks; /// /// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other. @@ -84,13 +85,12 @@ namespace osu.Game.Rulesets.Difficulty.Skills /// public double DifficultyValue() { - strainPeaks.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. - double difficulty = 0; double weight = 1; // Difficulty is the weighted sum of the highest strains from every section. - foreach (double strain in strainPeaks) + // We're sorting from highest to lowest strain. + foreach (double strain in strainPeaks.OrderByDescending(d => d)) { difficulty += strain * weight; weight *= DecayWeight; From 8bcb4485edc4e8d290f22b02693645954bb256b1 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Wed, 29 May 2019 19:00:20 +0300 Subject: [PATCH 0975/5608] implement UnderscoredLinkContainer --- .../Sections/UnderscoredLinkContainer.cs | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs diff --git a/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs b/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs new file mode 100644 index 0000000000..087bd03837 --- /dev/null +++ b/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs @@ -0,0 +1,79 @@ +// 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.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Sprites; +using System; +using System.Collections.Generic; + +namespace osu.Game.Overlays.Profile.Sections +{ + public class UnderscoredLinkContainer : Container + { + private const int duration = 200; + public Action ClickAction; + private readonly Container underscore; + private readonly FillFlowContainer textContent; + + public IReadOnlyList Text + { + get => textContent.Children; + set + { + textContent.Clear(); + textContent.AddRange(value); + } + } + + public UnderscoredLinkContainer() + { + AutoSizeAxes = Axes.Both; + Child = new Container + { + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + underscore = new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = 1, + Alpha = 0, + AlwaysPresent = true, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + } + }, + textContent = new FillFlowContainer + { + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + }, + }, + }; + } + + protected override bool OnHover(HoverEvent e) + { + underscore.FadeIn(duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + underscore.FadeOut(duration, Easing.OutQuint); + base.OnHoverLost(e); + } + + protected override bool OnClick(ClickEvent e) + { + ClickAction?.Invoke(); + return base.OnClick(e); + } + } +} From 52fad723a206ea5d86bb1384405aca64af106293 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Wed, 29 May 2019 19:51:59 +0300 Subject: [PATCH 0976/5608] Implement DrawableMostPlayedBeatmap --- .../Online/TestSceneHistoricalSection.cs | 2 +- .../Historical/DrawableMostPlayedBeatmap.cs | 190 ++++++++++++++++++ .../Historical/DrawableMostPlayedRow.cs | 77 ------- .../PaginatedMostPlayedBeatmapContainer.cs | 2 +- 4 files changed, 192 insertions(+), 79 deletions(-) create mode 100644 osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs delete mode 100644 osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs index 455807649a..f309112f0d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.Online { typeof(HistoricalSection), typeof(PaginatedMostPlayedBeatmapContainer), - typeof(DrawableMostPlayedRow), + typeof(DrawableMostPlayedBeatmap), typeof(DrawableProfileRow) }; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs new file mode 100644 index 0000000000..e8ce11555f --- /dev/null +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs @@ -0,0 +1,190 @@ +// 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.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Framework.Localisation; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Profile.Sections.Historical +{ + public class DrawableMostPlayedBeatmap : Container + { + private readonly BeatmapInfo beatmap; + private readonly OsuSpriteText mapperText; + private readonly int playCount; + private readonly Box background; + private Color4 idleBackgroundColour; + private Color4 hoveredBackgroundColour; + private const int duration = 200; + private const int cover_width = 100; + private const int corner_radius = 10; + private readonly SpriteIcon icon; + private readonly OsuSpriteText playCountText; + private readonly UnderscoredLinkContainer mapper; + private readonly UnderscoredLinkContainer beatmapName; + + public DrawableMostPlayedBeatmap(BeatmapInfo beatmap, int playCount) + { + this.beatmap = beatmap; + this.playCount = playCount; + + RelativeSizeAxes = Axes.X; + Height = 60; + Masking = true; + CornerRadius = corner_radius; + Children = new Drawable[] + { + new UpdateableBeatmapSetCover + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.Y, + Width = cover_width, + BeatmapSet = beatmap.BeatmapSet, + CoverType = BeatmapSetCoverType.List, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = cover_width - corner_radius }, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = corner_radius, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = 15, Right = 20 }, + Children = new Drawable[] + { + beatmapName = new UnderscoredLinkContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.BottomLeft, + Margin = new MarginPadding { Bottom = 2 }, + Text = new OsuSpriteText[] + { + new OsuSpriteText + { + Text = new LocalisedString(( + $"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ", + $"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] ")), + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold) + }, + new OsuSpriteText + { + Text = "by " + new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)), + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular) + }, + } + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.TopLeft, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding { Top = 2 }, + Children = new Drawable[] + { + mapperText = new OsuSpriteText + { + Text = "mapped by ", + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Regular), + }, + mapper = new UnderscoredLinkContainer + { + Text = new OsuSpriteText[] + { + new OsuSpriteText + { + Text = beatmap.Metadata.Author.Username, + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), + } + } + }, + } + }, + new FillFlowContainer + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + icon = new SpriteIcon + { + Icon = FontAwesome.Solid.CaretRight, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(20), + }, + playCountText = new OsuSpriteText + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Text = playCount.ToString(), + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Regular, fixedWidth: true), + }, + } + } + } + }, + } + } + } + } + }; + } + + [BackgroundDependencyLoader(permitNulls: true)] + private void load(OsuColour colors, UserProfileOverlay userProfileOverlay, BeatmapSetOverlay beatmapSetOverlay) + { + idleBackgroundColour = background.Colour = colors.GreySeafoam; + hoveredBackgroundColour = colors.GreySeafoamLight; + mapperText.Colour = mapper.Colour = colors.GreySeafoamLighter; + icon.Colour = playCountText.Colour = colors.Yellow; + + mapper.ClickAction = () => userProfileOverlay.ShowUser(beatmap.Metadata.Author.Id); + beatmapName.ClickAction = () => + { + if (beatmap.OnlineBeatmapID != null) + beatmapSetOverlay?.FetchAndShowBeatmap(beatmap.OnlineBeatmapID.Value); + else if (beatmap.BeatmapSet?.OnlineBeatmapSetID != null) + beatmapSetOverlay?.FetchAndShowBeatmapSet(beatmap.BeatmapSet.OnlineBeatmapSetID.Value); + }; + } + + protected override bool OnHover(HoverEvent e) + { + background.FadeColour(hoveredBackgroundColour, duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + background.FadeColour(idleBackgroundColour, duration, Easing.OutQuint); + base.OnHoverLost(e); + } + } +} diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs deleted file mode 100644 index 1b286f92d3..0000000000 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Drawables; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osuTK; - -namespace osu.Game.Overlays.Profile.Sections.Historical -{ - public class DrawableMostPlayedRow : DrawableProfileRow - { - private readonly BeatmapInfo beatmap; - private readonly int playCount; - - public DrawableMostPlayedRow(BeatmapInfo beatmap, int playCount) - { - this.beatmap = beatmap; - this.playCount = playCount; - } - - protected override Drawable CreateLeftVisual() => new UpdateableBeatmapSetCover - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(80, 50), - BeatmapSet = beatmap.BeatmapSet, - CoverType = BeatmapSetCoverType.List, - }; - - [BackgroundDependencyLoader] - private void load() - { - LeftFlowContainer.Add(new BeatmapMetadataContainer(beatmap)); - LeftFlowContainer.Add(new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: 12)) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - }.With(d => - { - d.AddText("mapped by "); - d.AddUserLink(beatmap.Metadata.Author); - })); - - RightFlowContainer.Add(new FillFlowContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new[] - { - new OsuSpriteText - { - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Text = playCount.ToString(), - Font = OsuFont.GetFont(size: 18, weight: FontWeight.SemiBold, italics: true) - }, - new OsuSpriteText - { - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Text = @"times played ", - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular, italics: true) - }, - } - }); - } - } -} diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index f2eb32c53b..13fe20d063 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical foreach (var beatmap in beatmaps) { - ItemsContainer.Add(new DrawableMostPlayedRow(beatmap.GetBeatmapInfo(Rulesets), beatmap.PlayCount)); + ItemsContainer.Add(new DrawableMostPlayedBeatmap(beatmap.GetBeatmapInfo(Rulesets), beatmap.PlayCount)); } }); From 6efa61b992a44cf4c3004ca9dc284da8952c90ba Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Wed, 29 May 2019 20:24:01 +0300 Subject: [PATCH 0977/5608] Split UnderscoredLinkContainer in different classes --- .../Historical/DrawableMostPlayedBeatmap.cs | 20 ++++--------- .../Sections/UnderscoredBeatmapLink.cs | 30 +++++++++++++++++++ .../Sections/UnderscoredLinkContainer.cs | 7 +++-- .../Profile/Sections/UnderscoredUserLink.cs | 23 ++++++++++++++ 4 files changed, 62 insertions(+), 18 deletions(-) create mode 100644 osu.Game/Overlays/Profile/Sections/UnderscoredBeatmapLink.cs create mode 100644 osu.Game/Overlays/Profile/Sections/UnderscoredUserLink.cs diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs index e8ce11555f..50f419e07c 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs @@ -30,8 +30,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical private const int corner_radius = 10; private readonly SpriteIcon icon; private readonly OsuSpriteText playCountText; - private readonly UnderscoredLinkContainer mapper; - private readonly UnderscoredLinkContainer beatmapName; + private readonly UnderscoredUserLink mapper; public DrawableMostPlayedBeatmap(BeatmapInfo beatmap, int playCount) { @@ -76,7 +75,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical Padding = new MarginPadding { Left = 15, Right = 20 }, Children = new Drawable[] { - beatmapName = new UnderscoredLinkContainer + new UnderscoredBeatmapLink(beatmap) { Anchor = Anchor.CentreLeft, Origin = Anchor.BottomLeft, @@ -111,7 +110,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical Text = "mapped by ", Font = OsuFont.GetFont(size: 15, weight: FontWeight.Regular), }, - mapper = new UnderscoredLinkContainer + mapper = new UnderscoredUserLink(beatmap.Metadata.Author.Id) { Text = new OsuSpriteText[] { @@ -157,22 +156,13 @@ namespace osu.Game.Overlays.Profile.Sections.Historical }; } - [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuColour colors, UserProfileOverlay userProfileOverlay, BeatmapSetOverlay beatmapSetOverlay) + [BackgroundDependencyLoader] + private void load(OsuColour colors) { idleBackgroundColour = background.Colour = colors.GreySeafoam; hoveredBackgroundColour = colors.GreySeafoamLight; mapperText.Colour = mapper.Colour = colors.GreySeafoamLighter; icon.Colour = playCountText.Colour = colors.Yellow; - - mapper.ClickAction = () => userProfileOverlay.ShowUser(beatmap.Metadata.Author.Id); - beatmapName.ClickAction = () => - { - if (beatmap.OnlineBeatmapID != null) - beatmapSetOverlay?.FetchAndShowBeatmap(beatmap.OnlineBeatmapID.Value); - else if (beatmap.BeatmapSet?.OnlineBeatmapSetID != null) - beatmapSetOverlay?.FetchAndShowBeatmapSet(beatmap.BeatmapSet.OnlineBeatmapSetID.Value); - }; } protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Overlays/Profile/Sections/UnderscoredBeatmapLink.cs b/osu.Game/Overlays/Profile/Sections/UnderscoredBeatmapLink.cs new file mode 100644 index 0000000000..370d6d84ef --- /dev/null +++ b/osu.Game/Overlays/Profile/Sections/UnderscoredBeatmapLink.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Game.Beatmaps; + +namespace osu.Game.Overlays.Profile.Sections +{ + public class UnderscoredBeatmapLink : UnderscoredLinkContainer + { + private readonly BeatmapInfo beatmap; + + public UnderscoredBeatmapLink(BeatmapInfo beatmap) + { + this.beatmap = beatmap; + } + + [BackgroundDependencyLoader(true)] + private void load(BeatmapSetOverlay beatmapSetOverlay) + { + ClickAction = () => + { + if (beatmap.OnlineBeatmapID != null) + beatmapSetOverlay?.FetchAndShowBeatmap(beatmap.OnlineBeatmapID.Value); + else if (beatmap.BeatmapSet?.OnlineBeatmapSetID != null) + beatmapSetOverlay?.FetchAndShowBeatmapSet(beatmap.BeatmapSet.OnlineBeatmapSetID.Value); + }; + } + } +} diff --git a/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs b/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs index 087bd03837..8daf0bd24d 100644 --- a/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs @@ -11,13 +11,14 @@ using System.Collections.Generic; namespace osu.Game.Overlays.Profile.Sections { - public class UnderscoredLinkContainer : Container + public abstract class UnderscoredLinkContainer : Container { private const int duration = 200; - public Action ClickAction; private readonly Container underscore; private readonly FillFlowContainer textContent; + protected Action ClickAction; + public IReadOnlyList Text { get => textContent.Children; @@ -28,7 +29,7 @@ namespace osu.Game.Overlays.Profile.Sections } } - public UnderscoredLinkContainer() + protected UnderscoredLinkContainer() { AutoSizeAxes = Axes.Both; Child = new Container diff --git a/osu.Game/Overlays/Profile/Sections/UnderscoredUserLink.cs b/osu.Game/Overlays/Profile/Sections/UnderscoredUserLink.cs new file mode 100644 index 0000000000..f50bc7f7ba --- /dev/null +++ b/osu.Game/Overlays/Profile/Sections/UnderscoredUserLink.cs @@ -0,0 +1,23 @@ +// 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; + +namespace osu.Game.Overlays.Profile.Sections +{ + public class UnderscoredUserLink : UnderscoredLinkContainer + { + private readonly long userId; + + public UnderscoredUserLink(long userId) + { + this.userId = userId; + } + + [BackgroundDependencyLoader(true)] + private void load(UserProfileOverlay userProfileOverlay) + { + ClickAction = () => userProfileOverlay?.ShowUser(userId); + } + } +} From 1baf922f2c3dace2bfa09f12e169cf8c078cb00b Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Wed, 29 May 2019 20:36:14 +0300 Subject: [PATCH 0978/5608] CI fixes --- .../Sections/Historical/DrawableMostPlayedBeatmap.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs index 50f419e07c..34b6884fe0 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs @@ -19,9 +19,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { public class DrawableMostPlayedBeatmap : Container { - private readonly BeatmapInfo beatmap; private readonly OsuSpriteText mapperText; - private readonly int playCount; private readonly Box background; private Color4 idleBackgroundColour; private Color4 hoveredBackgroundColour; @@ -34,9 +32,6 @@ namespace osu.Game.Overlays.Profile.Sections.Historical public DrawableMostPlayedBeatmap(BeatmapInfo beatmap, int playCount) { - this.beatmap = beatmap; - this.playCount = playCount; - RelativeSizeAxes = Axes.X; Height = 60; Masking = true; @@ -80,7 +75,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical Anchor = Anchor.CentreLeft, Origin = Anchor.BottomLeft, Margin = new MarginPadding { Bottom = 2 }, - Text = new OsuSpriteText[] + Text = new[] { new OsuSpriteText { @@ -112,7 +107,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical }, mapper = new UnderscoredUserLink(beatmap.Metadata.Author.Id) { - Text = new OsuSpriteText[] + Text = new[] { new OsuSpriteText { From 97dbc95bc64d7a10506bdcc00f271f218ddf3853 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Wed, 29 May 2019 21:02:20 +0300 Subject: [PATCH 0979/5608] Kudosu section update --- .../Profile/Sections/Kudosu/KudosuInfo.cs | 75 ++++++++----------- 1 file changed, 31 insertions(+), 44 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs index aeea5118a7..87a241936a 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -3,53 +3,38 @@ using osu.Framework.Bindables; using osuTK; -using osuTK.Graphics; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Users; +using osu.Framework.Allocation; namespace osu.Game.Overlays.Profile.Sections.Kudosu { public class KudosuInfo : Container { private readonly Bindable user = new Bindable(); - public KudosuInfo(Bindable user) { this.user.BindTo(user); - CountSection total; CountSection avaliable; - RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Masking = true; CornerRadius = 3; - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Offset = new Vector2(0f, 1f), - Radius = 3f, - Colour = Color4.Black.Opacity(0.2f), - }; Children = new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.Gray(0.2f) - }, new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), Children = new[] { total = new CountSection( @@ -63,31 +48,29 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu } } }; - this.user.ValueChanged += u => { total.Count = u.NewValue?.Kudosu.Total ?? 0; avaliable.Count = u.NewValue?.Kudosu.Available ?? 0; }; } - protected override bool OnClick(ClickEvent e) => true; - private class CountSection : Container { private readonly OsuSpriteText valueText; + private readonly OsuTextFlowContainer descriptionText; + private readonly Box lineBackground; public new int Count { set => valueText.Text = value.ToString(); } - public CountSection(string header, string description) { RelativeSizeAxes = Axes.X; Width = 0.5f; AutoSizeAxes = Axes.Y; - Padding = new MarginPadding { Horizontal = 10, Top = 10, Bottom = 20 }; + Padding = new MarginPadding { Top = 10, Bottom = 20 }; Child = new FillFlowContainer { AutoSizeAxes = Axes.Y, @@ -96,31 +79,28 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu Spacing = new Vector2(0, 5), Children = new Drawable[] { - new FillFlowContainer + new CircularContainer { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5, 0), - Children = new Drawable[] + Masking = true, + RelativeSizeAxes = Axes.X, + Height = 5, + Child = lineBackground = new Box { - new OsuSpriteText - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Text = header + ":", - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular, italics: true) - }, - valueText = new OsuSpriteText - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Text = "0", - Font = OsuFont.GetFont(size: 40, weight: FontWeight.Regular, italics: true), - UseFullGlyphHeight = false, - } + RelativeSizeAxes = Axes.Both, } }, - new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 19)) + new OsuSpriteText + { + Text = header, + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold) + }, + valueText = new OsuSpriteText + { + Text = "0", + Font = OsuFont.GetFont(size: 50, weight: FontWeight.Light), + UseFullGlyphHeight = false, + }, + descriptionText = new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 17)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -129,6 +109,13 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu } }; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + lineBackground.Colour = colours.Yellow; + descriptionText.Colour = colours.GreySeafoamLighter; + } } } } From 9a13c52ffd860e2c05289ec5fe0a2e27bf06a717 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Wed, 29 May 2019 21:19:03 +0300 Subject: [PATCH 0980/5608] Add missing lines --- osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs index 87a241936a..c8b803eb98 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -18,6 +18,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu public class KudosuInfo : Container { private readonly Bindable user = new Bindable(); + public KudosuInfo(Bindable user) { this.user.BindTo(user); @@ -54,7 +55,9 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu avaliable.Count = u.NewValue?.Kudosu.Available ?? 0; }; } + protected override bool OnClick(ClickEvent e) => true; + private class CountSection : Container { private readonly OsuSpriteText valueText; @@ -65,6 +68,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu { set => valueText.Text = value.ToString(); } + public CountSection(string header, string description) { RelativeSizeAxes = Axes.X; From e5999dd9b1daa448638ca88c5090c0b0d10b42bb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 May 2019 16:49:18 +0900 Subject: [PATCH 0981/5608] Update font sizes to match web --- osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs index c8b803eb98..a07ecc3bf3 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -96,15 +96,15 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu new OsuSpriteText { Text = header, - Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold) + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold) }, valueText = new OsuSpriteText { Text = "0", - Font = OsuFont.GetFont(size: 50, weight: FontWeight.Light), + Font = OsuFont.GetFont(size: 40, weight: FontWeight.Light), UseFullGlyphHeight = false, }, - descriptionText = new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 17)) + descriptionText = new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 14)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, From c950f37497da2b3bee4f65fbbb32f845ac445c32 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 May 2019 16:57:54 +0900 Subject: [PATCH 0982/5608] Ad missing link --- .../Profile/Sections/Kudosu/KudosuInfo.cs | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs index a07ecc3bf3..aabfa56ee6 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -38,14 +38,8 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu Spacing = new Vector2(5, 0), Children = new[] { - total = new CountSection( - "Total Kudosu Earned", - "Based on how much of a contribution the user has made to beatmap moderation. See this link for more information." - ), - avaliable = new CountSection( - "Kudosu Avaliable", - "Kudosu can be traded for kudosu stars, which will help your beatmap get more attention. This is the number of kudosu you haven't traded in yet." - ), + total = new CountTotal(), + avaliable = new CountAvailable() } } }; @@ -58,10 +52,30 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu protected override bool OnClick(ClickEvent e) => true; + private class CountAvailable : CountSection + { + public CountAvailable() + : base("Kudosu Avaliable") + { + DescriptionText.Text = "Kudosu can be traded for kudosu stars, which will help your beatmap get more attention. This is the number of kudosu you haven't traded in yet."; + } + } + + private class CountTotal : CountSection + { + public CountTotal() + : base("Total Kudosu Earned") + { + DescriptionText.AddText("Based on how much of a contribution the user has made to beatmap moderation. See "); + DescriptionText.AddLink("this link", "https://osu.ppy.sh/wiki/Kudosu"); + DescriptionText.AddText(" for more information."); + } + } + private class CountSection : Container { private readonly OsuSpriteText valueText; - private readonly OsuTextFlowContainer descriptionText; + protected readonly LinkFlowContainer DescriptionText; private readonly Box lineBackground; public new int Count @@ -69,7 +83,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu set => valueText.Text = value.ToString(); } - public CountSection(string header, string description) + public CountSection(string header) { RelativeSizeAxes = Axes.X; Width = 0.5f; @@ -104,11 +118,10 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu Font = OsuFont.GetFont(size: 40, weight: FontWeight.Light), UseFullGlyphHeight = false, }, - descriptionText = new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 14)) + DescriptionText = new LinkFlowContainer(t => t.Font = t.Font.With(size: 14)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Text = description } } }; @@ -118,7 +131,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu private void load(OsuColour colours) { lineBackground.Colour = colours.Yellow; - descriptionText.Colour = colours.GreySeafoamLighter; + DescriptionText.Colour = colours.GreySeafoamLighter; } } } From 73fb28f9f7fbc082e2fd58b787d759c175f98b35 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Thu, 30 May 2019 22:48:27 +0300 Subject: [PATCH 0983/5608] Make the button inherit from OsuHoverContainer --- .../Profile/Sections/PaginatedContainer.cs | 93 +++++++++---------- 1 file changed, 42 insertions(+), 51 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 6e0729c7c5..504f80fc97 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -12,11 +12,11 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Framework.Input.Events; -using System; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osuTK.Graphics; using osu.Game.Users; +using osu.Game.Graphics.Containers; +using System.Collections.Generic; namespace osu.Game.Overlays.Profile.Sections { @@ -94,17 +94,14 @@ namespace osu.Game.Overlays.Profile.Sections protected abstract void ShowMore(); - protected class ShowMoreButton : CircularContainer + protected class ShowMoreButton : OsuHoverContainer { - private const int duration = 300; - private Color4 idleColour; - private Color4 hoveredColour; - - public Action Action; private readonly Box background; private readonly LoadingAnimation loading; private readonly FillFlowContainer content; + protected override IEnumerable EffectTargets => new[] { background }; + private bool isLoading; public bool IsLoading @@ -119,13 +116,13 @@ namespace osu.Game.Overlays.Profile.Sections if (value) { - loading.FadeIn(duration, Easing.OutQuint); - content.FadeOut(duration, Easing.OutQuint); + loading.FadeIn(FADE_DURATION, Easing.OutQuint); + content.FadeOut(FADE_DURATION, Easing.OutQuint); } else { - loading.FadeOut(duration, Easing.OutQuint); - content.FadeIn(duration, Easing.OutQuint); + loading.FadeOut(FADE_DURATION, Easing.OutQuint); + content.FadeIn(FADE_DURATION, Easing.OutQuint); } } } @@ -134,66 +131,60 @@ namespace osu.Game.Overlays.Profile.Sections { Anchor = Anchor.TopCentre; Origin = Anchor.TopCentre; - Masking = true; - Size = new Vector2(140, 30); + AutoSizeAxes = Axes.Both; Children = new Drawable[] { - background = new Box + new CircularContainer { - RelativeSizeAxes = Axes.Both, - }, - content = new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7), + Masking = true, + Size = new Vector2(140, 30), Children = new Drawable[] { - new ChevronIcon(), - new OsuSpriteText + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + content = new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), - Text = "show more".ToUpper(), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7), + Children = new Drawable[] + { + new ChevronIcon(), + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Text = "show more".ToUpper(), + }, + new ChevronIcon(), + } + }, + loading = new LoadingAnimation + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(12) }, - new ChevronIcon(), } - }, - loading = new LoadingAnimation - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(20) - }, + } }; } [BackgroundDependencyLoader] private void load(OsuColour colors) { - background.Colour = idleColour = colors.GreySeafoam; - hoveredColour = colors.GreySeafoamLight; - } - - protected override bool OnHover(HoverEvent e) - { - background.FadeColour(hoveredColour, duration, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - background.FadeColour(idleColour, duration, Easing.OutQuint); - base.OnHoverLost(e); + IdleColour = colors.GreySeafoam; + HoverColour = colors.GreySeafoamLight; } protected override bool OnClick(ClickEvent e) { IsLoading = true; - Action.Invoke(); return base.OnClick(e); } From 2933169614bee615d4f8e75205d3414620c00be9 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Thu, 30 May 2019 22:55:59 +0300 Subject: [PATCH 0984/5608] Move the button into a separate class --- .../Profile/Sections/PaginatedContainer.cs | 122 ---------------- .../Profile/Sections/ShowMoreButton.cs | 134 ++++++++++++++++++ 2 files changed, 134 insertions(+), 122 deletions(-) create mode 100644 osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 504f80fc97..11803b0dc1 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -8,15 +8,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Rulesets; -using osu.Framework.Input.Events; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Game.Users; -using osu.Game.Graphics.Containers; -using System.Collections.Generic; namespace osu.Game.Overlays.Profile.Sections { @@ -93,121 +87,5 @@ namespace osu.Game.Overlays.Profile.Sections } protected abstract void ShowMore(); - - protected class ShowMoreButton : OsuHoverContainer - { - private readonly Box background; - private readonly LoadingAnimation loading; - private readonly FillFlowContainer content; - - protected override IEnumerable EffectTargets => new[] { background }; - - private bool isLoading; - - public bool IsLoading - { - get => isLoading; - set - { - if (isLoading == value) - return; - - isLoading = value; - - if (value) - { - loading.FadeIn(FADE_DURATION, Easing.OutQuint); - content.FadeOut(FADE_DURATION, Easing.OutQuint); - } - else - { - loading.FadeOut(FADE_DURATION, Easing.OutQuint); - content.FadeIn(FADE_DURATION, Easing.OutQuint); - } - } - } - - public ShowMoreButton() - { - Anchor = Anchor.TopCentre; - Origin = Anchor.TopCentre; - AutoSizeAxes = Axes.Both; - Children = new Drawable[] - { - new CircularContainer - { - Masking = true, - Size = new Vector2(140, 30), - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - content = new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7), - Children = new Drawable[] - { - new ChevronIcon(), - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), - Text = "show more".ToUpper(), - }, - new ChevronIcon(), - } - }, - loading = new LoadingAnimation - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(12) - }, - } - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colors) - { - IdleColour = colors.GreySeafoam; - HoverColour = colors.GreySeafoamLight; - } - - protected override bool OnClick(ClickEvent e) - { - IsLoading = true; - return base.OnClick(e); - } - - private class ChevronIcon : SpriteIcon - { - private const int bottom_margin = 2; - private const int icon_size = 8; - - public ChevronIcon() - { - Anchor = Anchor.Centre; - Origin = Anchor.Centre; - Margin = new MarginPadding { Bottom = bottom_margin }; - Size = new Vector2(icon_size); - Icon = FontAwesome.Solid.ChevronDown; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colors) - { - Colour = colors.Yellow; - } - } - } } } diff --git a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs new file mode 100644 index 0000000000..5979c971d1 --- /dev/null +++ b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs @@ -0,0 +1,134 @@ +// 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.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osuTK; +using System.Collections.Generic; + +namespace osu.Game.Overlays.Profile.Sections +{ + public class ShowMoreButton : OsuHoverContainer + { + private readonly Box background; + private readonly LoadingAnimation loading; + private readonly FillFlowContainer content; + + protected override IEnumerable EffectTargets => new[] { background }; + + private bool isLoading; + + public bool IsLoading + { + get => isLoading; + set + { + if (isLoading == value) + return; + + isLoading = value; + + if (value) + { + loading.FadeIn(FADE_DURATION, Easing.OutQuint); + content.FadeOut(FADE_DURATION, Easing.OutQuint); + } + else + { + loading.FadeOut(FADE_DURATION, Easing.OutQuint); + content.FadeIn(FADE_DURATION, Easing.OutQuint); + } + } + } + + public ShowMoreButton() + { + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; + AutoSizeAxes = Axes.Both; + Children = new Drawable[] + { + new CircularContainer + { + Masking = true, + Size = new Vector2(140, 30), + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + content = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7), + Children = new Drawable[] + { + new ChevronIcon(), + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Text = "show more".ToUpper(), + }, + new ChevronIcon(), + } + }, + loading = new LoadingAnimation + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(12) + }, + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colors) + { + IdleColour = colors.GreySeafoam; + HoverColour = colors.GreySeafoamLight; + } + + protected override bool OnClick(ClickEvent e) + { + IsLoading = true; + return base.OnClick(e); + } + + private class ChevronIcon : SpriteIcon + { + private const int bottom_margin = 2; + private const int icon_size = 8; + + public ChevronIcon() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + Margin = new MarginPadding { Bottom = bottom_margin }; + Size = new Vector2(icon_size); + Icon = FontAwesome.Solid.ChevronDown; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colors) + { + Colour = colors.Yellow; + } + } + } +} From fe9e53e383e5f2d35e382daffad3f5ba1b253a53 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Thu, 30 May 2019 23:07:04 +0300 Subject: [PATCH 0985/5608] Add a testcase --- .../Visual/Online/TestSceneShowMoreButton.cs | 31 +++++++++ .../Graphics/Containers/OsuHoverContainer.cs | 6 +- .../Profile/Sections/PaginatedContainer.cs | 2 + .../Profile/Sections/ShowMoreButton.cs | 68 +++++++++---------- 4 files changed, 70 insertions(+), 37 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs new file mode 100644 index 0000000000..8289e4a09c --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs @@ -0,0 +1,31 @@ +// 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.Overlays.Profile.Sections; +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneShowMoreButton : OsuTestScene + { + private readonly ShowMoreButton button; + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ShowMoreButton), + }; + + public TestSceneShowMoreButton() + { + Add(button = new ShowMoreButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + + AddStep("switch loading state", () => button.IsLoading = !button.IsLoading); + } + } +} diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index c4f85926ee..eb2d926424 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -24,7 +24,8 @@ namespace osu.Game.Graphics.Containers { Enabled.ValueChanged += e => { - if (!e.NewValue) unhover(); + if (!e.NewValue) + unhover(); }; } @@ -49,7 +50,8 @@ namespace osu.Game.Graphics.Containers private void unhover() { - if (!isHovered) return; + if (!isHovered) + return; isHovered = false; EffectTargets.ForEach(d => d.FadeColour(IdleColour, FADE_DURATION, Easing.OutQuint)); diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 11803b0dc1..8639acfc94 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -54,6 +54,8 @@ namespace osu.Game.Overlays.Profile.Sections }, MoreButton = new ShowMoreButton { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Alpha = 0, Margin = new MarginPadding { Top = 10 }, Action = ShowMore, diff --git a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs index 5979c971d1..31c73aaa96 100644 --- a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs +++ b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs @@ -51,49 +51,47 @@ namespace osu.Game.Overlays.Profile.Sections public ShowMoreButton() { - Anchor = Anchor.TopCentre; - Origin = Anchor.TopCentre; AutoSizeAxes = Axes.Both; Children = new Drawable[] { - new CircularContainer + new CircularContainer + { + Masking = true, + Size = new Vector2(140, 30), + Children = new Drawable[] { - Masking = true, - Size = new Vector2(140, 30), - Children = new Drawable[] + background = new Box { - background = new Box + RelativeSizeAxes = Axes.Both, + }, + content = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7), + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - }, - content = new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7), - Children = new Drawable[] + new ChevronIcon(), + new OsuSpriteText { - new ChevronIcon(), - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), - Text = "show more".ToUpper(), - }, - new ChevronIcon(), - } - }, - loading = new LoadingAnimation - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(12) - }, - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Text = "show more".ToUpper(), + }, + new ChevronIcon(), + } + }, + loading = new LoadingAnimation + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(12) + }, } + } }; } From cfa0ef6fd9c410cf0f2d7c32c9613daf5c179e62 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Thu, 30 May 2019 23:22:08 +0300 Subject: [PATCH 0986/5608] convert field to a local variable --- osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs index 8289e4a09c..0d6d378f4c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs @@ -10,8 +10,6 @@ namespace osu.Game.Tests.Visual.Online { public class TestSceneShowMoreButton : OsuTestScene { - private readonly ShowMoreButton button; - public override IReadOnlyList RequiredTypes => new[] { typeof(ShowMoreButton), @@ -19,6 +17,8 @@ namespace osu.Game.Tests.Visual.Online public TestSceneShowMoreButton() { + ShowMoreButton button; + Add(button = new ShowMoreButton { Anchor = Anchor.Centre, From b32ffab58054309c25c2a86895bfce998af3b987 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Fri, 31 May 2019 02:19:09 +0300 Subject: [PATCH 0987/5608] Make the DrawableMostPlayedBeatmap inherit OsuHoverContainer --- .../Historical/DrawableMostPlayedBeatmap.cs | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs index 34b6884fe0..98872d6141 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs @@ -6,32 +6,33 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; -using osuTK.Graphics; +using System.Collections.Generic; namespace osu.Game.Overlays.Profile.Sections.Historical { - public class DrawableMostPlayedBeatmap : Container + public class DrawableMostPlayedBeatmap : OsuHoverContainer { private readonly OsuSpriteText mapperText; private readonly Box background; - private Color4 idleBackgroundColour; - private Color4 hoveredBackgroundColour; - private const int duration = 200; private const int cover_width = 100; private const int corner_radius = 10; private readonly SpriteIcon icon; private readonly OsuSpriteText playCountText; private readonly UnderscoredUserLink mapper; + protected override IEnumerable EffectTargets => new[] { background }; + public DrawableMostPlayedBeatmap(BeatmapInfo beatmap, int playCount) { + Enabled.Value = true; //manually enabled, because we have no action + RelativeSizeAxes = Axes.X; Height = 60; Masking = true; @@ -154,22 +155,10 @@ namespace osu.Game.Overlays.Profile.Sections.Historical [BackgroundDependencyLoader] private void load(OsuColour colors) { - idleBackgroundColour = background.Colour = colors.GreySeafoam; - hoveredBackgroundColour = colors.GreySeafoamLight; + IdleColour = colors.GreySeafoam; + HoverColour = colors.GreySeafoamLight; mapperText.Colour = mapper.Colour = colors.GreySeafoamLighter; icon.Colour = playCountText.Colour = colors.Yellow; } - - protected override bool OnHover(HoverEvent e) - { - background.FadeColour(hoveredBackgroundColour, duration, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - background.FadeColour(idleBackgroundColour, duration, Easing.OutQuint); - base.OnHoverLost(e); - } } } From f780c80c17d406f7c6518066930072de27083727 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 31 May 2019 13:03:35 +0900 Subject: [PATCH 0988/5608] Fix bar not expanding/collapsing correctly --- osu.Game/Overlays/Changelog/UpdateStreamBadge.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs b/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs index c39e6a6784..4f1d95bc2c 100644 --- a/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs +++ b/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs @@ -84,7 +84,7 @@ namespace osu.Game.Overlays.Changelog } }; - SelectedTab.ValueChanged += _ => updateState(); + SelectedTab.BindValueChanged(_ => updateState(), true); } protected override void OnActivated() => updateState(); @@ -113,7 +113,13 @@ namespace osu.Game.Overlays.Changelog private void updateState() { - if (Active.Value || IsHovered || SelectedTab.Value == null) + // Expand based on the local state + bool shouldExpand = Active.Value || IsHovered; + + // Expand based on whether no build is selected and the badge area is hovered + shouldExpand |= SelectedTab.Value == null && !externalDimRequested; + + if (shouldExpand) { expandingBar.Expand(); fadeContainer.FadeTo(1, transition_duration); From 4dc77d64a32c37397e3adea7f7ea0a485af3154a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 31 May 2019 13:23:50 +0900 Subject: [PATCH 0989/5608] Fix overlay group + depth --- osu.Game/OsuGame.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 2bbd0b8303..ba9abcdefc 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -435,9 +435,9 @@ namespace osu.Game loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal, true); loadComponentSingleFile(chatOverlay = new ChatOverlay(), overlayContent.Add, true); loadComponentSingleFile(settings = new SettingsOverlay { GetToolbarHeight = () => ToolbarOffset }, leftFloatingOverlayContent.Add, true); + var changelogOverlay = loadComponentSingleFile(new ChangelogOverlay(), overlayContent.Add, true); loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true); - var changelogOverlay = loadComponentSingleFile(new ChangelogOverlay(), overlayContent.Add, true); loadComponentSingleFile(new LoginOverlay { @@ -479,7 +479,7 @@ namespace osu.Game } // eventually informational overlays should be displayed in a stack, but for now let's only allow one to stay open at a time. - var informationalOverlays = new OverlayContainer[] { beatmapSetOverlay, userProfile, changelogOverlay }; + var informationalOverlays = new OverlayContainer[] { beatmapSetOverlay, userProfile }; overlays.AddRange(informationalOverlays); foreach (var overlay in informationalOverlays) @@ -493,7 +493,7 @@ namespace osu.Game } // ensure only one of these overlays are open at once. - var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, social, direct }; + var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, social, direct, changelogOverlay }; overlays.AddRange(singleDisplayOverlays); foreach (var overlay in singleDisplayOverlays) From 57d648df6dcd0a44c63e46a19dceb264f233ad40 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 31 May 2019 13:38:48 +0900 Subject: [PATCH 0990/5608] Add comment + fix spinlocking --- osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index 81c7905e84..36ae5a756c 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -43,6 +43,7 @@ namespace osu.Game.Overlays.Changelog }; req.Failure += _ => complete = true; + // This is done on a separate thread to support cancellation below Task.Run(() => req.Perform(api)); while (!complete) @@ -53,7 +54,7 @@ namespace osu.Game.Overlays.Changelog return; } - Task.Delay(1); + Thread.Sleep(10); } if (build != null) From e7ae9c249fdd7ef3fee5f0b5384986a5abd3f0de Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 31 May 2019 13:53:55 +0900 Subject: [PATCH 0991/5608] Fix size of release stream separator in listing --- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 4 +++- osu.Game/Overlays/Changelog/ChangelogListing.cs | 10 ++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index a76211a0ae..57615332da 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -18,6 +18,8 @@ namespace osu.Game.Overlays.Changelog { public class ChangelogBuild : FillFlowContainer { + public const float HORIZONTAL_PADDING = 70; + public Action SelectBuild; protected readonly APIChangelogBuild Build; @@ -31,7 +33,7 @@ namespace osu.Game.Overlays.Changelog RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; - Padding = new MarginPadding { Horizontal = 70 }; + Padding = new MarginPadding { Horizontal = HORIZONTAL_PADDING }; Children = new Drawable[] { diff --git a/osu.Game/Overlays/Changelog/ChangelogListing.cs b/osu.Game/Overlays/Changelog/ChangelogListing.cs index 20b7a32eba..1856f93205 100644 --- a/osu.Game/Overlays/Changelog/ChangelogListing.cs +++ b/osu.Game/Overlays/Changelog/ChangelogListing.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -58,12 +59,17 @@ namespace osu.Game.Overlays.Changelog } else { - Add(new Box + Add(new Container { RelativeSizeAxes = Axes.X, Height = 1, - Colour = new Color4(32, 24, 35, 255), + Padding = new MarginPadding { Horizontal = ChangelogBuild.HORIZONTAL_PADDING }, Margin = new MarginPadding { Top = 30 }, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new Color4(32, 24, 35, 255), + } }); } From d7ccf939d8098483e4ab2ea5935e44c32286fdc3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 31 May 2019 13:54:40 +0900 Subject: [PATCH 0992/5608] General refactoring --- osu.Game/Overlays/Changelog/ChangelogListing.cs | 6 +++--- osu.Game/Overlays/Changelog/UpdateStreamBadge.cs | 14 +++++++------- osu.Game/Overlays/ChangelogOverlay.cs | 11 ++++------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogListing.cs b/osu.Game/Overlays/Changelog/ChangelogListing.cs index 1856f93205..41d8228475 100644 --- a/osu.Game/Overlays/Changelog/ChangelogListing.cs +++ b/osu.Game/Overlays/Changelog/ChangelogListing.cs @@ -47,12 +47,12 @@ namespace osu.Game.Overlays.Changelog Add(new OsuSpriteText { - Text = build.CreatedAt.Date.ToString("dd MMM yyyy"), - Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 24), - Colour = OsuColour.FromHex(@"FD5"), Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Margin = new MarginPadding { Top = 15 }, + Text = build.CreatedAt.Date.ToString("dd MMM yyyy"), + Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 24), + Colour = OsuColour.FromHex(@"FD5"), }); currentDate = build.CreatedAt.Date; diff --git a/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs b/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs index 4f1d95bc2c..514e75c31a 100644 --- a/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs +++ b/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs @@ -87,6 +87,13 @@ namespace osu.Game.Overlays.Changelog SelectedTab.BindValueChanged(_ => updateState(), true); } + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleClick = audio.Sample.Get(@"UI/generic-select-soft"); + sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); + } + protected override void OnActivated() => updateState(); protected override void OnDeactivated() => updateState(); @@ -146,12 +153,5 @@ namespace osu.Game.Overlays.Changelog externalDimRequested = false; updateState(); } - - [BackgroundDependencyLoader] - private void load(AudioManager audio) - { - sampleClick = audio.Sample.Get(@"UI/generic-select-soft"); - sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); - } } } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 552e213a45..7d791b2a88 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -120,10 +120,7 @@ namespace osu.Game.Overlays ?? streams.Find(s => s.Name == updateStream)?.LatestBuild; if (build != null) - { - Current.Value = build; - State = Visibility.Visible; - } + ShowBuild(build); }); State = Visibility.Visible; @@ -193,13 +190,13 @@ namespace osu.Game.Overlays }); } - private CancellationTokenSource loadContentTask; + private CancellationTokenSource loadContentCancellation; private void loadContent(ChangelogContent newContent) { content.FadeTo(0.2f, 300, Easing.OutQuint); - loadContentTask?.Cancel(); + loadContentCancellation?.Cancel(); LoadComponentAsync(newContent, c => { @@ -207,7 +204,7 @@ namespace osu.Game.Overlays c.BuildSelected = ShowBuild; content.Child = c; - }, (loadContentTask = new CancellationTokenSource()).Token); + }, (loadContentCancellation = new CancellationTokenSource()).Token); } } } From 465aa4e0f60db2ed81df136cf0da5c6613c4beef Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 31 May 2019 14:06:13 +0900 Subject: [PATCH 0993/5608] Prevent idle state from being updated incorrectly --- osu.Game/Screens/Menu/ButtonSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index a098d42c83..868d37d922 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -176,7 +176,7 @@ namespace osu.Game.Screens.Menu private void updateIdleState(bool isIdle) { - if (isIdle && State != ButtonSystemState.Exit) + if (isIdle && State != ButtonSystemState.Exit && State != ButtonSystemState.EnteringMode) State = ButtonSystemState.Initial; } From 1629534a0c79a3b6fae32820a17acb2f1dd3cc68 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 May 2019 22:07:14 +0900 Subject: [PATCH 0994/5608] More disposal? --- osu.Game/Skinning/SkinnableSound.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 5e8a0ea43f..e88e088f5e 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -58,5 +58,13 @@ namespace osu.Game.Skinning return null; } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + foreach (var c in channels) + c.Dispose(); + } } } From 80d65f9a3ba2e3e4d6486ca92f915f9ad8da24f5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 May 2019 14:33:18 +0900 Subject: [PATCH 0995/5608] Update resource stores with GetAvailableResources --- osu.Game/IO/Archives/ArchiveReader.cs | 2 ++ osu.Game/Skinning/LegacySkin.cs | 3 +++ 2 files changed, 5 insertions(+) diff --git a/osu.Game/IO/Archives/ArchiveReader.cs b/osu.Game/IO/Archives/ArchiveReader.cs index a561523799..4ee7a19ebc 100644 --- a/osu.Game/IO/Archives/ArchiveReader.cs +++ b/osu.Game/IO/Archives/ArchiveReader.cs @@ -15,6 +15,8 @@ namespace osu.Game.IO.Archives /// public abstract Stream GetStream(string name); + public IEnumerable GetAvailableResources() => Filenames; + public abstract void Dispose(); /// diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 8d38f944d0..7b658f86d0 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.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.IO; using System.Linq; using System.Threading.Tasks; @@ -140,6 +141,8 @@ namespace osu.Game.Skinning return path == null ? null : underlyingStore.GetStream(path); } + public IEnumerable GetAvailableResources() => source.Files.Select(f => f.Filename); + byte[] IResourceStore.Get(string name) => GetAsync(name).Result; public Task GetAsync(string name) From f33a5bc54cee705bcdb8d8d77f1f1e314b2f322c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 May 2019 14:40:53 +0900 Subject: [PATCH 0996/5608] Centralise and update WorkingBeatmap creation in test cases --- .../TestSceneAutoJuiceStream.cs | 4 +- .../TestSceneBananaShower.cs | 4 +- .../TestSceneCatchStacker.cs | 4 +- .../TestSceneHyperDash.cs | 4 +- .../TestSceneHitCircleLongCombo.cs | 4 +- .../TestSceneSliderInput.cs | 5 +- .../TestSceneTaikoPlayfield.cs | 5 +- .../TestSceneBackgroundScreenBeatmap.cs | 5 +- .../Visual/Editor/TestSceneEditorCompose.cs | 3 +- .../Editor/TestSceneEditorComposeTimeline.cs | 5 +- .../Editor/TestSceneEditorSeekSnapping.cs | 5 +- .../Editor/TestSceneEditorSummaryTimeline.cs | 3 +- .../Editor/TestSceneHitObjectComposer.cs | 3 +- .../Visual/Editor/TestScenePlaybackControl.cs | 5 +- .../Visual/Editor/TestSceneWaveform.cs | 10 +- .../Visual/Gameplay/TestScenePlayerLoader.cs | 5 +- .../TestScenePlayerReferenceLeaking.cs | 5 +- .../TestSceneMatchSettingsOverlay.cs | 5 +- .../Visual/Online/TestSceneDirectPanel.cs | 3 +- .../SongSelect/TestSceneBeatmapDetailArea.cs | 14 +- .../SongSelect/TestSceneBeatmapInfoWedge.cs | 5 +- .../SongSelect/TestScenePlaySongSelect.cs | 5 +- osu.Game.Tests/WaveformTestBeatmap.cs | 13 +- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 3 +- osu.Game/Beatmaps/BindableBeatmap.cs | 26 +-- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 6 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 7 +- osu.Game/OsuGameBase.cs | 16 +- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 112 +--------- osu.Game/Tests/Visual/AllPlayersTestScene.cs | 21 +- osu.Game/Tests/Visual/EditorTestScene.cs | 5 +- osu.Game/Tests/Visual/OsuTestScene.cs | 198 ++++++++++++++++-- osu.Game/Tests/Visual/PlayerTestScene.cs | 8 +- 34 files changed, 278 insertions(+), 250 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 9cec0d280d..ab3c040b4e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -20,14 +20,14 @@ namespace osu.Game.Rulesets.Catch.Tests { } - protected override IBeatmap CreateBeatmap(Ruleset ruleset) + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) { var beatmap = new Beatmap { BeatmapInfo = new BeatmapInfo { BaseDifficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 }, - Ruleset = ruleset.RulesetInfo + Ruleset = ruleset } }; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs index 035bbe4b4e..0ad72412fc 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs @@ -29,14 +29,14 @@ namespace osu.Game.Rulesets.Catch.Tests { } - protected override IBeatmap CreateBeatmap(Ruleset ruleset) + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) { var beatmap = new Beatmap { BeatmapInfo = new BeatmapInfo { BaseDifficulty = new BeatmapDifficulty { CircleSize = 6 }, - Ruleset = ruleset.RulesetInfo + Ruleset = ruleset } }; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs index 7d7528372a..9ce46ad6ba 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs @@ -16,14 +16,14 @@ namespace osu.Game.Rulesets.Catch.Tests { } - protected override IBeatmap CreateBeatmap(Ruleset ruleset) + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) { var beatmap = new Beatmap { BeatmapInfo = new BeatmapInfo { BaseDifficulty = new BeatmapDifficulty { CircleSize = 6 }, - Ruleset = ruleset.RulesetInfo + Ruleset = ruleset } }; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs index 7393f75e5a..9cbff8c5d3 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs @@ -23,13 +23,13 @@ namespace osu.Game.Rulesets.Catch.Tests AddAssert("First note is hyperdash", () => Beatmap.Value.Beatmap.HitObjects[0] is Fruit f && f.HyperDash); } - protected override IBeatmap CreateBeatmap(Ruleset ruleset) + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) { var beatmap = new Beatmap { BeatmapInfo = { - Ruleset = ruleset.RulesetInfo, + Ruleset = ruleset, BaseDifficulty = new BeatmapDifficulty { CircleSize = 3.6f } } }; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs index 921246751c..399cf22599 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs @@ -17,14 +17,14 @@ namespace osu.Game.Rulesets.Osu.Tests { } - protected override IBeatmap CreateBeatmap(Ruleset ruleset) + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) { var beatmap = new Beatmap { BeatmapInfo = new BeatmapInfo { BaseDifficulty = new BeatmapDifficulty { CircleSize = 6 }, - Ruleset = ruleset.RulesetInfo + Ruleset = ruleset } }; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index 193cfe9c94..2eb783233a 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -20,7 +20,6 @@ using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Play; -using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Visual; using osuTK; @@ -299,7 +298,7 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep("load player", () => { - Beatmap.Value = new TestWorkingBeatmap(new Beatmap + Beatmap.Value = CreateWorkingBeatmap(new Beatmap { HitObjects = { @@ -323,7 +322,7 @@ namespace osu.Game.Rulesets.Osu.Tests BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 }, Ruleset = new OsuRuleset().RulesetInfo }, - }, Clock); + }); var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }); diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index 3634ec7d4a..6f9856df83 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -18,7 +18,6 @@ using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.UI; -using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Visual; using osuTK; using osu.Game.Rulesets.Scoring; @@ -64,7 +63,7 @@ namespace osu.Game.Rulesets.Taiko.Tests var controlPointInfo = new ControlPointInfo(); controlPointInfo.TimingPoints.Add(new TimingControlPoint()); - WorkingBeatmap beatmap = new TestWorkingBeatmap(new Beatmap + WorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap { HitObjects = new List { new CentreHit() }, BeatmapInfo = new BeatmapInfo @@ -79,7 +78,7 @@ namespace osu.Game.Rulesets.Taiko.Tests Ruleset = new TaikoRuleset().RulesetInfo }, ControlPointInfo = controlPointInfo - }, Clock); + }); Add(playfieldContainer = new Container { diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs index c9bdcf928f..7104a420a3 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Events; @@ -54,7 +55,7 @@ namespace osu.Game.Tests.Visual.Background private RulesetStore rulesets; [BackgroundDependencyLoader] - private void load(GameHost host) + private void load(GameHost host, AudioManager audio) { factory = new DatabaseContextFactory(LocalStorage); factory.ResetDatabase(); @@ -68,7 +69,7 @@ namespace osu.Game.Tests.Visual.Background usage.Migrate(); Dependencies.Cache(rulesets = new RulesetStore(factory)); - Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, null, host, Beatmap.Default)); + Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, audio, host, Beatmap.Default)); Dependencies.Cache(new OsuConfigManager(LocalStorage)); manager.Import(TestResources.GetTestBeatmapForImport()); diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorCompose.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorCompose.cs index b537cb0beb..608df1965e 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorCompose.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorCompose.cs @@ -7,7 +7,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Edit.Compose; -using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual.Editor { @@ -19,7 +18,7 @@ namespace osu.Game.Tests.Visual.Editor [BackgroundDependencyLoader] private void load() { - Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, Clock); + Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); Child = new ComposeScreen(); } } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index 154c58dd99..a8c2362910 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -30,9 +31,9 @@ namespace osu.Game.Tests.Visual.Editor }; [BackgroundDependencyLoader] - private void load() + private void load(AudioManager audio) { - Beatmap.Value = new WaveformTestBeatmap(); + Beatmap.Value = new WaveformTestBeatmap(audio); Children = new Drawable[] { diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs index 590fa59107..b997d6aaeb 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.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 NUnit.Framework; @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Tests.Beatmaps; using osuTK; using osuTK.Graphics; @@ -48,7 +47,7 @@ namespace osu.Game.Tests.Visual.Editor } }; - Beatmap.Value = new TestWorkingBeatmap(testBeatmap, Clock); + Beatmap.Value = CreateWorkingBeatmap(testBeatmap); Child = new TimingPointVisualiser(testBeatmap, 5000) { Clock = Clock }; } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorSummaryTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorSummaryTimeline.cs index f20c921ff2..2e04eb50ca 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorSummaryTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorSummaryTimeline.cs @@ -8,7 +8,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Edit.Components.Timelines.Summary; -using osu.Game.Tests.Beatmaps; using osuTK; namespace osu.Game.Tests.Visual.Editor @@ -21,7 +20,7 @@ namespace osu.Game.Tests.Visual.Editor [BackgroundDependencyLoader] private void load() { - Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, null); + Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); Add(new SummaryTimeline { diff --git a/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs b/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs index 47aa059b62..7accbe2fa8 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs @@ -18,7 +18,6 @@ using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Compose.Components; -using osu.Game.Tests.Beatmaps; using osuTK; namespace osu.Game.Tests.Visual.Editor @@ -45,7 +44,7 @@ namespace osu.Game.Tests.Visual.Editor [BackgroundDependencyLoader] private void load() { - Beatmap.Value = new TestWorkingBeatmap(new Beatmap + Beatmap.Value = CreateWorkingBeatmap(new Beatmap { HitObjects = new List { diff --git a/osu.Game.Tests/Visual/Editor/TestScenePlaybackControl.cs b/osu.Game.Tests/Visual/Editor/TestScenePlaybackControl.cs index 126ab98291..0d4fe4366d 100644 --- a/osu.Game.Tests/Visual/Editor/TestScenePlaybackControl.cs +++ b/osu.Game.Tests/Visual/Editor/TestScenePlaybackControl.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 NUnit.Framework; @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Screens.Edit.Components; -using osu.Game.Tests.Beatmaps; using osuTK; namespace osu.Game.Tests.Visual.Editor @@ -29,7 +28,7 @@ namespace osu.Game.Tests.Visual.Editor Size = new Vector2(200, 100) }; - Beatmap.Value = new TestWorkingBeatmap(new Beatmap(), Clock); + Beatmap.Value = CreateWorkingBeatmap(new Beatmap()); Child = playback; } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs b/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs index e93789b1d3..6e2500d711 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Graphics; using osu.Framework.Graphics.Audio; @@ -19,10 +20,13 @@ namespace osu.Game.Tests.Visual.Editor { private WorkingBeatmap waveformBeatmap; + private OsuGameBase game; + [BackgroundDependencyLoader] - private void load() + private void load(AudioManager audio, OsuGameBase game) { - waveformBeatmap = new WaveformTestBeatmap(); + waveformBeatmap = new WaveformTestBeatmap(audio); + this.game = game; } [TestCase(1f)] @@ -91,7 +95,7 @@ namespace osu.Game.Tests.Visual.Editor Child = graph = new TestWaveformGraph { RelativeSizeAxes = Axes.Both, - Waveform = new DummyWorkingBeatmap().Waveform, + Waveform = new DummyWorkingBeatmap(game).Waveform, }, }; }); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 5c26f733ab..daee3a520c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.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; @@ -16,7 +16,6 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens; using osu.Game.Screens.Play; -using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual.Gameplay { @@ -29,7 +28,7 @@ namespace osu.Game.Tests.Visual.Gameplay public void Setup() => Schedule(() => { InputManager.Child = stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }; - Beatmap.Value = new TestWorkingBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo), Clock); + Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); }); [Test] diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs index c75fb2567b..65b56319e8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Lists; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Screens.Play; @@ -43,9 +42,9 @@ namespace osu.Game.Tests.Visual.Gameplay }); } - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock clock) + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) { - var working = base.CreateWorkingBeatmap(beatmap, clock); + var working = base.CreateWorkingBeatmap(beatmap); workingWeakReferences.Add(working); return working; } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs index 21b97fe73b..76a0604818 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs @@ -19,6 +19,9 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMatchSettingsOverlay : MultiplayerTestScene { + [Resolved] + private OsuGameBase game { get; set; } + public override IReadOnlyList RequiredTypes => new[] { typeof(MatchSettingsOverlay) @@ -57,7 +60,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("set name", () => Room.Name.Value = "Room name"); AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); - AddStep("set beatmap", () => Room.Playlist.Add(new PlaylistItem { Beatmap = new DummyWorkingBeatmap().BeatmapInfo })); + AddStep("set beatmap", () => Room.Playlist.Add(new PlaylistItem { Beatmap = new DummyWorkingBeatmap(game).BeatmapInfo })); AddAssert("button enabled", () => settings.ApplyButton.Enabled.Value); AddStep("clear name", () => Room.Name.Value = ""); diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs index a3d932a383..8b67892fbb 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Direct; using osu.Game.Rulesets.Osu; -using osu.Game.Tests.Beatmaps; using osuTK; namespace osu.Game.Tests.Visual.Online @@ -25,7 +24,7 @@ namespace osu.Game.Tests.Visual.Online [BackgroundDependencyLoader] private void load() { - var beatmap = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, null); + var beatmap = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); beatmap.BeatmapSetInfo.OnlineInfo.HasVideo = true; beatmap.BeatmapSetInfo.OnlineInfo.HasStoryboard = true; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index cf4362ba28..d398423b9a 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Screens.Select; @@ -18,7 +19,8 @@ namespace osu.Game.Tests.Visual.SongSelect { public override IReadOnlyList RequiredTypes => new[] { typeof(BeatmapDetails) }; - public TestSceneBeatmapDetailArea() + [BackgroundDependencyLoader] + private void load(OsuGameBase game) { BeatmapDetailArea detailsArea; Add(detailsArea = new BeatmapDetailArea @@ -28,7 +30,7 @@ namespace osu.Game.Tests.Visual.SongSelect Size = new Vector2(550f, 450f), }); - AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap + AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(game) { BeatmapInfo = { @@ -56,7 +58,7 @@ namespace osu.Game.Tests.Visual.SongSelect } ); - AddStep("all except source", () => detailsArea.Beatmap = new DummyWorkingBeatmap + AddStep("all except source", () => detailsArea.Beatmap = new DummyWorkingBeatmap(game) { BeatmapInfo = { @@ -82,7 +84,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - AddStep("ratings", () => detailsArea.Beatmap = new DummyWorkingBeatmap + AddStep("ratings", () => detailsArea.Beatmap = new DummyWorkingBeatmap(game) { BeatmapInfo = { @@ -107,7 +109,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - AddStep("fails+retries", () => detailsArea.Beatmap = new DummyWorkingBeatmap + AddStep("fails+retries", () => detailsArea.Beatmap = new DummyWorkingBeatmap(game) { BeatmapInfo = { @@ -133,7 +135,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - AddStep("null metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap + AddStep("null metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(game) { BeatmapInfo = { diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index b1ed5c46c2..9969795ecf 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; @@ -18,7 +18,6 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Taiko; using osu.Game.Screens.Select; -using osu.Game.Tests.Beatmaps; using osuTK; namespace osu.Game.Tests.Visual.SongSelect @@ -136,7 +135,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep($"select {b?.Metadata.Title ?? "null"} beatmap", () => { infoBefore = infoWedge.Info; - infoWedge.Beatmap = Beatmap.Value = b == null ? Beatmap.Default : new TestWorkingBeatmap(b); + infoWedge.Beatmap = Beatmap.Value = b == null ? Beatmap.Default : CreateWorkingBeatmap(b); }); AddUntilStep("wait for async load", () => infoWedge.Info != infoBefore); diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 7e962dbc06..ebee358730 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Text; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.MathUtils; @@ -79,7 +80,7 @@ namespace osu.Game.Tests.Visual.SongSelect } [BackgroundDependencyLoader] - private void load(GameHost host) + private void load(GameHost host, AudioManager audio) { factory = new DatabaseContextFactory(LocalStorage); factory.ResetDatabase(); @@ -93,7 +94,7 @@ namespace osu.Game.Tests.Visual.SongSelect usage.Migrate(); Dependencies.Cache(rulesets = new RulesetStore(factory)); - Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, null, host, defaultBeatmap = Beatmap.Default)); + Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, audio, host, defaultBeatmap = Beatmap.Default)); Beatmap.SetDefault(); } diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index f66b374cd7..36cc1e5ad2 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; +using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; @@ -19,12 +20,14 @@ namespace osu.Game.Tests { private readonly ZipArchiveReader reader; private readonly Stream stream; + private readonly ITrackStore trackStore; - public WaveformTestBeatmap() - : base(new BeatmapInfo()) + public WaveformTestBeatmap(AudioManager audioManager) + : base(new BeatmapInfo(), audioManager) { stream = TestResources.GetTestBeatmapStream(); reader = new ZipArchiveReader(stream); + trackStore = audioManager.GetTrackStore(reader); } public override void Dispose() @@ -32,17 +35,17 @@ namespace osu.Game.Tests base.Dispose(); stream?.Dispose(); reader?.Dispose(); + trackStore?.Dispose(); } protected override IBeatmap GetBeatmap() => createTestBeatmap(); protected override Texture GetBackground() => null; - protected override Waveform GetWaveform() => new Waveform(getAudioStream()); + protected override Waveform GetWaveform() => new Waveform(trackStore.GetStream(reader.Filenames.First(f => f.EndsWith(".mp3")))); - protected override Track GetTrack() => new TrackBass(getAudioStream()); + protected override Track GetTrack() => trackStore.Get(reader.Filenames.First(f => f.EndsWith(".mp3"))); - private Stream getAudioStream() => reader.GetStream(reader.Filenames.First(f => f.EndsWith(".mp3"))); private Stream getBeatmapStream() => reader.GetStream(reader.Filenames.First(f => f.EndsWith(".osu"))); private Beatmap createTestBeatmap() diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 798bca3ada..0200dd44ac 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -429,7 +429,7 @@ namespace osu.Game.Beatmaps private readonly IBeatmap beatmap; public DummyConversionBeatmap(IBeatmap beatmap) - : base(beatmap.BeatmapInfo) + : base(beatmap.BeatmapInfo, null) { this.beatmap = beatmap; } diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index cfeb6b0a92..e1cc5db3ad 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -22,11 +22,10 @@ namespace osu.Game.Beatmaps private readonly IResourceStore store; public BeatmapManagerWorkingBeatmap(IResourceStore store, TextureStore textureStore, BeatmapInfo beatmapInfo, AudioManager audioManager) - : base(beatmapInfo) + : base(beatmapInfo, audioManager) { this.store = store; this.textureStore = textureStore; - AudioManager = audioManager; } protected override IBeatmap GetBeatmap() diff --git a/osu.Game/Beatmaps/BindableBeatmap.cs b/osu.Game/Beatmaps/BindableBeatmap.cs index 6614a6f2fb..1e69a17ef7 100644 --- a/osu.Game/Beatmaps/BindableBeatmap.cs +++ b/osu.Game/Beatmaps/BindableBeatmap.cs @@ -2,8 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Diagnostics; -using JetBrains.Annotations; -using osu.Framework.Audio; using osu.Framework.Bindables; namespace osu.Game.Beatmaps @@ -14,29 +12,20 @@ namespace osu.Game.Beatmaps /// public abstract class BindableBeatmap : NonNullableBindable { - protected AudioManager AudioManager; - private WorkingBeatmap lastBeatmap; - protected BindableBeatmap(WorkingBeatmap defaultValue, AudioManager audioManager) + protected BindableBeatmap(WorkingBeatmap defaultValue) : base(defaultValue) { - // we don't want to attempt to update tracks if we are a bound copy. - if (audioManager != null) - { - AudioManager = audioManager; - ValueChanged += b => updateAudioTrack(b.NewValue); - - // If the track has changed prior to this being called, let's register it - if (Value != Default) - updateAudioTrack(Value); - } + BindValueChanged(b => updateAudioTrack(b.NewValue), true); } private void updateAudioTrack(WorkingBeatmap beatmap) { var trackLoaded = lastBeatmap?.TrackLoaded ?? false; + //beatmap.AudioManager = AudioManager; + // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo) if (!trackLoaded || lastBeatmap?.Track != beatmap.Track) { @@ -51,12 +40,5 @@ namespace osu.Game.Beatmaps lastBeatmap = beatmap; } - - /// - /// Retrieve a new instance weakly bound to this . - /// If you are further binding to events of the retrieved , ensure a local reference is held. - /// - [NotNull] - public new abstract BindableBeatmap GetBoundCopy(); } } diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index b35e98085a..72b477713a 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -18,7 +18,7 @@ namespace osu.Game.Beatmaps { private readonly OsuGameBase game; - public DummyWorkingBeatmap(OsuGameBase game = null) + public DummyWorkingBeatmap(OsuGameBase game) : base(new BeatmapInfo { Metadata = new BeatmapMetadata @@ -34,7 +34,7 @@ namespace osu.Game.Beatmaps OverallDifficulty = 0, }, Ruleset = new DummyRulesetInfo() - }) + }, game.Audio) { this.game = game; } @@ -43,7 +43,7 @@ namespace osu.Game.Beatmaps protected override Texture GetBackground() => game?.Textures.Get(@"Backgrounds/bg4"); - protected override Track GetTrack() => game?.Audio.Tracks.GetVirtual(1000); + protected override Track GetTrack() => game?.Audio?.Tracks.GetVirtual(1000); private class DummyRulesetInfo : RulesetInfo { diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 6c8f283923..cf1acaf46b 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -29,8 +29,11 @@ namespace osu.Game.Beatmaps public readonly BeatmapMetadata Metadata; - protected WorkingBeatmap(BeatmapInfo beatmapInfo) + protected AudioManager AudioManager { get; } + + protected WorkingBeatmap(BeatmapInfo beatmapInfo, AudioManager audioManager) { + AudioManager = audioManager; BeatmapInfo = beatmapInfo; BeatmapSetInfo = beatmapInfo.BeatmapSet; Metadata = beatmapInfo.Metadata ?? BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); @@ -179,8 +182,6 @@ namespace osu.Game.Beatmaps public bool SkinLoaded => skin.IsResultAvailable; public Skin Skin => skin.Value; - public AudioManager AudioManager { get; set; } - protected virtual Skin GetSkin() => new DefaultSkin(); private readonly RecyclableLazy skin; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 8e663de8c5..39f5144cf8 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -195,7 +195,7 @@ namespace osu.Game // this adds a global reduction of track volume for the time being. Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8)); - beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio); + beatmap = new OsuBindableBeatmap(defaultBeatmap); dependencies.CacheAs>(beatmap); dependencies.CacheAs(beatmap); @@ -282,21 +282,9 @@ namespace osu.Game private class OsuBindableBeatmap : BindableBeatmap { public OsuBindableBeatmap(WorkingBeatmap defaultValue) - : base(defaultValue, null) + : base(defaultValue) { } - - public OsuBindableBeatmap(WorkingBeatmap defaultValue, AudioManager audioManager) - : base(defaultValue, audioManager) - { - } - - public override BindableBeatmap GetBoundCopy() - { - var copy = new OsuBindableBeatmap(Default, AudioManager); - copy.BindTo(this); - return copy; - } } private class OsuUserInputManager : UserInputManager diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index c558275f62..0ef35879e3 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -1,134 +1,30 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; -using osu.Framework.Timing; using osu.Game.Beatmaps; -using osu.Game.Rulesets; -using osuTK; namespace osu.Game.Tests.Beatmaps { public class TestWorkingBeatmap : WorkingBeatmap { - private readonly TrackVirtualManual track; private readonly IBeatmap beatmap; - /// - /// Create an instance which creates a for the provided ruleset when requested. - /// - /// The target ruleset. - /// A clock which should be used instead of a stopwatch for virtual time progression. - public TestWorkingBeatmap(RulesetInfo ruleset, IFrameBasedClock referenceClock) - : this(new TestBeatmap(ruleset), referenceClock) - { - } - /// /// Create an instance which provides the when requested. /// /// The beatmap - /// An optional clock which should be used instead of a stopwatch for virtual time progression. - public TestWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock referenceClock = null) - : base(beatmap.BeatmapInfo) + public TestWorkingBeatmap(IBeatmap beatmap) + : base(beatmap.BeatmapInfo, null) { this.beatmap = beatmap; - - if (referenceClock != null) - track = new TrackVirtualManual(referenceClock); } protected override IBeatmap GetBeatmap() => beatmap; + protected override Texture GetBackground() => null; - protected override Track GetTrack() => track; - /// - /// A virtual track which tracks a reference clock. - /// - public class TrackVirtualManual : Track - { - private readonly IFrameBasedClock referenceClock; - - private readonly ManualClock clock = new ManualClock(); - - private bool running; - - /// - /// Local offset added to the reference clock to resolve correct time. - /// - private double offset; - - public TrackVirtualManual(IFrameBasedClock referenceClock) - { - this.referenceClock = referenceClock; - Length = double.PositiveInfinity; - } - - public override bool Seek(double seek) - { - offset = MathHelper.Clamp(seek, 0, Length); - lastReferenceTime = null; - - return offset == seek; - } - - public override void Start() - { - running = true; - } - - public override void Reset() - { - Seek(0); - base.Reset(); - } - - public override void Stop() - { - if (running) - { - running = false; - // on stopping, the current value should be transferred out of the clock, as we can no longer rely on - // the referenceClock (which will still be counting time). - offset = clock.CurrentTime; - lastReferenceTime = null; - } - } - - public override bool IsRunning => running; - - private double? lastReferenceTime; - - public override double CurrentTime => clock.CurrentTime; - - protected override void UpdateState() - { - base.UpdateState(); - - if (running) - { - double refTime = referenceClock.CurrentTime; - - if (!lastReferenceTime.HasValue) - { - // if the clock just started running, the current value should be transferred to the offset - // (to zero the progression of time). - offset -= refTime; - } - - lastReferenceTime = refTime; - } - - clock.CurrentTime = Math.Min((lastReferenceTime ?? 0) + offset, Length); - - if (CurrentTime >= Length) - { - Stop(); - RaiseCompleted(); - } - } - } + protected override Track GetTrack() => null; } } diff --git a/osu.Game/Tests/Visual/AllPlayersTestScene.cs b/osu.Game/Tests/Visual/AllPlayersTestScene.cs index 454fbe1222..b7d1979b0d 100644 --- a/osu.Game/Tests/Visual/AllPlayersTestScene.cs +++ b/osu.Game/Tests/Visual/AllPlayersTestScene.cs @@ -4,13 +4,10 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Screens; -using osu.Framework.Timing; -using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; -using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual { @@ -50,26 +47,20 @@ namespace osu.Game.Tests.Visual protected abstract void AddCheckSteps(); - protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo); - - protected virtual WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock clock) => - new TestWorkingBeatmap(beatmap, Clock); - - private Player loadPlayerFor(RulesetInfo ri) + private Player loadPlayerFor(RulesetInfo rulesetInfo) { - Ruleset.Value = ri; - var r = ri.CreateInstance(); + Ruleset.Value = rulesetInfo; + var ruleset = rulesetInfo.CreateInstance(); - var beatmap = CreateBeatmap(r); - var working = CreateWorkingBeatmap(beatmap, Clock); + var working = CreateWorkingBeatmap(rulesetInfo); Beatmap.Value = working; - Mods.Value = new[] { r.GetAllMods().First(m => m is ModNoFail) }; + Mods.Value = new[] { ruleset.GetAllMods().First(m => m is ModNoFail) }; Player?.Exit(); Player = null; - Player = CreatePlayer(r); + Player = CreatePlayer(ruleset); LoadScreen(Player); diff --git a/osu.Game/Tests/Visual/EditorTestScene.cs b/osu.Game/Tests/Visual/EditorTestScene.cs index 14c0f0950f..75bbb3e110 100644 --- a/osu.Game/Tests/Visual/EditorTestScene.cs +++ b/osu.Game/Tests/Visual/EditorTestScene.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; @@ -6,7 +6,6 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Rulesets; using osu.Game.Screens.Edit; -using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual { @@ -24,7 +23,7 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - Beatmap.Value = new TestWorkingBeatmap(ruleset.RulesetInfo, null); + Beatmap.Value = CreateWorkingBeatmap(ruleset.RulesetInfo); LoadScreen(new Editor()); } diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 806b73b517..d8a63d23e1 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -3,15 +3,21 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Platform; using osu.Framework.Testing; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Tests.Beatmaps; +using osuTK; namespace osu.Game.Tests.Visual { @@ -19,7 +25,7 @@ namespace osu.Game.Tests.Visual { [Cached(typeof(Bindable))] [Cached(typeof(IBindable))] - private readonly OsuTestBeatmap beatmap = new OsuTestBeatmap(new DummyWorkingBeatmap(), null); + private OsuTestBeatmap beatmap; protected BindableBeatmap Beatmap => beatmap; @@ -39,7 +45,10 @@ namespace osu.Game.Tests.Visual protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { // This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures - beatmap.Default = new DummyWorkingBeatmap(parent.Get()); + beatmap = new OsuTestBeatmap(new DummyWorkingBeatmap(parent.Get())) + { + Default = new DummyWorkingBeatmap(parent.Get()) + }; return Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); } @@ -49,8 +58,19 @@ namespace osu.Game.Tests.Visual localStorage = new Lazy(() => new NativeStorage($"{GetType().Name}-{Guid.NewGuid()}")); } + [Resolved] + private AudioManager audio { get; set; } + + protected virtual IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset); + + protected WorkingBeatmap CreateWorkingBeatmap(RulesetInfo ruleset = null) => + CreateWorkingBeatmap(CreateBeatmap(ruleset)); + + protected virtual WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) => + new ClockBackedTestWorkingBeatmap(beatmap, Clock, audio); + [BackgroundDependencyLoader] - private void load(AudioManager audioManager, RulesetStore rulesets) + private void load(RulesetStore rulesets) { Ruleset.Value = rulesets.AvailableRulesets.First(); } @@ -59,7 +79,8 @@ namespace osu.Game.Tests.Visual { base.Dispose(isDisposing); - beatmap?.Value.Track.Stop(); + if (beatmap?.Value.TrackLoaded == true) + beatmap.Value.Track.Stop(); if (localStorage.IsValueCreated) { @@ -76,6 +97,164 @@ namespace osu.Game.Tests.Visual protected override ITestSceneTestRunner CreateRunner() => new OsuTestSceneTestRunner(); + public class ClockBackedTestWorkingBeatmap : TestWorkingBeatmap + { + private readonly Track track; + + private readonly TrackVirtualStore store; + + /// + /// Create an instance which creates a for the provided ruleset when requested. + /// + /// The target ruleset. + /// A clock which should be used instead of a stopwatch for virtual time progression. + /// Audio manager. Required if a reference clock isn't provided. + public ClockBackedTestWorkingBeatmap(RulesetInfo ruleset, IFrameBasedClock referenceClock, AudioManager audio) + : this(new TestBeatmap(ruleset), referenceClock, audio) + { + } + + /// + /// Create an instance which provides the when requested. + /// + /// The beatmap + /// An optional clock which should be used instead of a stopwatch for virtual time progression. + /// Audio manager. Required if a reference clock isn't provided. + /// The length of the returned virtual track. + public ClockBackedTestWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock referenceClock, AudioManager audio, double length = 60000) + : base(beatmap) + { + if (referenceClock != null) + { + store = new TrackVirtualStore(referenceClock); + audio.AddItem(store); + track = store.GetVirtual(length); + } + else + track = audio?.Tracks.GetVirtual(length); + } + + public override void Dispose() + { + base.Dispose(); + store?.Dispose(); + } + + protected override Track GetTrack() => track; + + public class TrackVirtualStore : AudioCollectionManager, ITrackStore + { + private readonly IFrameBasedClock referenceClock; + + public TrackVirtualStore(IFrameBasedClock referenceClock) + { + this.referenceClock = referenceClock; + } + + public Track Get(string name) => throw new NotImplementedException(); + + public Task GetAsync(string name) => throw new NotImplementedException(); + + public Stream GetStream(string name) => throw new NotImplementedException(); + + public IEnumerable GetAvailableResources() => throw new NotImplementedException(); + + public Track GetVirtual(double length = Double.PositiveInfinity) + { + var track = new TrackVirtualManual(referenceClock) { Length = length }; + AddItem(track); + return track; + } + } + + /// + /// A virtual track which tracks a reference clock. + /// + public class TrackVirtualManual : Track + { + private readonly IFrameBasedClock referenceClock; + + private readonly ManualClock clock = new ManualClock(); + + private bool running; + + /// + /// Local offset added to the reference clock to resolve correct time. + /// + private double offset; + + public TrackVirtualManual(IFrameBasedClock referenceClock) + { + this.referenceClock = referenceClock; + Length = double.PositiveInfinity; + } + + public override bool Seek(double seek) + { + offset = MathHelper.Clamp(seek, 0, Length); + lastReferenceTime = null; + + return offset == seek; + } + + public override void Start() + { + running = true; + } + + public override void Reset() + { + Seek(0); + base.Reset(); + } + + public override void Stop() + { + if (running) + { + running = false; + // on stopping, the current value should be transferred out of the clock, as we can no longer rely on + // the referenceClock (which will still be counting time). + offset = clock.CurrentTime; + lastReferenceTime = null; + } + } + + public override bool IsRunning => running; + + private double? lastReferenceTime; + + public override double CurrentTime => clock.CurrentTime; + + protected override void UpdateState() + { + base.UpdateState(); + + if (running) + { + double refTime = referenceClock.CurrentTime; + + if (!lastReferenceTime.HasValue) + { + // if the clock just started running, the current value should be transferred to the offset + // (to zero the progression of time). + offset -= refTime; + } + + lastReferenceTime = refTime; + } + + clock.CurrentTime = Math.Min((lastReferenceTime ?? 0) + offset, Length); + + if (CurrentTime >= Length) + { + Stop(); + RaiseCompleted(); + } + } + } + } + public class OsuTestSceneTestRunner : OsuGameBase, ITestSceneTestRunner { private TestSceneTestRunner.TestRunner runner; @@ -93,17 +272,10 @@ namespace osu.Game.Tests.Visual private class OsuTestBeatmap : BindableBeatmap { - public OsuTestBeatmap(WorkingBeatmap defaultValue, AudioManager audioManager) - : base(defaultValue, audioManager) + public OsuTestBeatmap(WorkingBeatmap defaultValue) + : base(defaultValue) { } - - public override BindableBeatmap GetBoundCopy() - { - var copy = new OsuTestBeatmap(Default, AudioManager); - copy.BindTo(this); - return copy; - } } } } diff --git a/osu.Game/Tests/Visual/PlayerTestScene.cs b/osu.Game/Tests/Visual/PlayerTestScene.cs index 0c39194088..03e17a819c 100644 --- a/osu.Game/Tests/Visual/PlayerTestScene.cs +++ b/osu.Game/Tests/Visual/PlayerTestScene.cs @@ -4,12 +4,10 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Testing; -using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; -using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual { @@ -39,15 +37,13 @@ namespace osu.Game.Tests.Visual AddUntilStep("player loaded", () => Player.IsLoaded && Player.Alpha == 1); } - protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo); - protected virtual bool AllowFail => false; private void loadPlayer() { - var beatmap = CreateBeatmap(ruleset); + var beatmap = CreateBeatmap(ruleset.RulesetInfo); - Beatmap.Value = new TestWorkingBeatmap(beatmap, Clock); + Beatmap.Value = CreateWorkingBeatmap(beatmap); if (!AllowFail) Mods.Value = new[] { ruleset.GetAllMods().First(m => m is ModNoFail) }; From b52276c4892dd0585ad81ac014ab1fe4f969eb5b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 May 2019 14:51:12 +0900 Subject: [PATCH 0997/5608] Pass individual components to DummyWorkingBeatmap, not game --- osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs | 3 ++- .../Multiplayer/TestSceneMatchSettingsOverlay.cs | 3 +-- .../Visual/SongSelect/TestSceneBeatmapDetailArea.cs | 10 +++++----- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 13 +++++++------ osu.Game/OsuGameBase.cs | 2 +- osu.Game/Tests/Visual/OsuTestScene.cs | 9 ++++++--- 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs b/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs index 6e2500d711..7b27998d7f 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Osu; using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editor @@ -95,7 +96,7 @@ namespace osu.Game.Tests.Visual.Editor Child = graph = new TestWaveformGraph { RelativeSizeAxes = Axes.Both, - Waveform = new DummyWorkingBeatmap(game).Waveform, + Waveform = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).Waveform, }, }; }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs index 76a0604818..de4f4d9d25 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs @@ -8,7 +8,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; @@ -60,7 +59,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("set name", () => Room.Name.Value = "Room name"); AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); - AddStep("set beatmap", () => Room.Playlist.Add(new PlaylistItem { Beatmap = new DummyWorkingBeatmap(game).BeatmapInfo })); + AddStep("set beatmap", () => Room.Playlist.Add(new PlaylistItem { Beatmap = CreateBeatmap(Ruleset.Value).BeatmapInfo })); AddAssert("button enabled", () => settings.ApplyButton.Enabled.Value); AddStep("clear name", () => Room.Name.Value = ""); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index d398423b9a..8395ece457 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Visual.SongSelect Size = new Vector2(550f, 450f), }); - AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(game) + AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) { BeatmapInfo = { @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual.SongSelect } ); - AddStep("all except source", () => detailsArea.Beatmap = new DummyWorkingBeatmap(game) + AddStep("all except source", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) { BeatmapInfo = { @@ -84,7 +84,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - AddStep("ratings", () => detailsArea.Beatmap = new DummyWorkingBeatmap(game) + AddStep("ratings", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) { BeatmapInfo = { @@ -109,7 +109,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - AddStep("fails+retries", () => detailsArea.Beatmap = new DummyWorkingBeatmap(game) + AddStep("fails+retries", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) { BeatmapInfo = { @@ -135,7 +135,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - AddStep("null metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(game) + AddStep("null metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) { BeatmapInfo = { diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 72b477713a..9202c617bf 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Textures; @@ -16,9 +17,9 @@ namespace osu.Game.Beatmaps { public class DummyWorkingBeatmap : WorkingBeatmap { - private readonly OsuGameBase game; + private readonly TextureStore textures; - public DummyWorkingBeatmap(OsuGameBase game) + public DummyWorkingBeatmap(AudioManager audio, TextureStore textures) : base(new BeatmapInfo { Metadata = new BeatmapMetadata @@ -34,16 +35,16 @@ namespace osu.Game.Beatmaps OverallDifficulty = 0, }, Ruleset = new DummyRulesetInfo() - }, game.Audio) + }, audio) { - this.game = game; + this.textures = textures; } protected override IBeatmap GetBeatmap() => new Beatmap(); - protected override Texture GetBackground() => game?.Textures.Get(@"Backgrounds/bg4"); + protected override Texture GetBackground() => textures?.Get(@"Backgrounds/bg4"); - protected override Track GetTrack() => game?.Audio?.Tracks.GetVirtual(1000); + protected override Track GetTrack() => GetVirtualTrack(Beatmap); private class DummyRulesetInfo : RulesetInfo { diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 39f5144cf8..f9128687d6 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -161,7 +161,7 @@ namespace osu.Game dependencies.CacheAs(API); - var defaultBeatmap = new DummyWorkingBeatmap(this); + var defaultBeatmap = new DummyWorkingBeatmap(Audio, Textures); dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index d8a63d23e1..c8798448ae 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -10,6 +10,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; +using osu.Framework.Graphics.Textures; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Timing; @@ -45,9 +46,11 @@ namespace osu.Game.Tests.Visual protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { // This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures - beatmap = new OsuTestBeatmap(new DummyWorkingBeatmap(parent.Get())) + var working = new DummyWorkingBeatmap(parent.Get(), parent.Get()); + + beatmap = new OsuTestBeatmap(working) { - Default = new DummyWorkingBeatmap(parent.Get()) + Default = working }; return Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); @@ -63,7 +66,7 @@ namespace osu.Game.Tests.Visual protected virtual IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset); - protected WorkingBeatmap CreateWorkingBeatmap(RulesetInfo ruleset = null) => + protected WorkingBeatmap CreateWorkingBeatmap(RulesetInfo ruleset) => CreateWorkingBeatmap(CreateBeatmap(ruleset)); protected virtual WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) => From 7bed4eb23b73ec49bba20136d5aa6c257cb474f1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 May 2019 14:57:11 +0900 Subject: [PATCH 0998/5608] Tidy up WaveformTestBeatmap --- osu.Game.Tests/WaveformTestBeatmap.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index 36cc1e5ad2..fdb91b7c5b 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -42,9 +42,11 @@ namespace osu.Game.Tests protected override Texture GetBackground() => null; - protected override Waveform GetWaveform() => new Waveform(trackStore.GetStream(reader.Filenames.First(f => f.EndsWith(".mp3")))); + protected override Waveform GetWaveform() => new Waveform(trackStore.GetStream(firstAudioFile)); - protected override Track GetTrack() => trackStore.Get(reader.Filenames.First(f => f.EndsWith(".mp3"))); + protected override Track GetTrack() => trackStore.Get(firstAudioFile); + + private string firstAudioFile => reader.Filenames.First(f => f.EndsWith(".mp3")); private Stream getBeatmapStream() => reader.GetStream(reader.Filenames.First(f => f.EndsWith(".osu"))); From 651706b10e4ba85bea3faba3ccf70c2736cbf5aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 16:17:20 +0900 Subject: [PATCH 0999/5608] Account for user/system offsets when deciding on an initial seek time Closes #3043 Remove "AllowLeadIn" flag --- osu.Game/Screens/Play/GameplayClockContainer.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index c151e598f7..f6a23575e9 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -26,6 +26,10 @@ namespace osu.Game.Screens.Play private readonly WorkingBeatmap beatmap; private readonly IReadOnlyList mods; + private readonly bool allowLeadIn; + + private readonly double gameplayStartTime; + /// /// The original source (usually a 's track). /// @@ -60,6 +64,8 @@ namespace osu.Game.Screens.Play private readonly FramedOffsetClock platformOffsetClock; + private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset; + public GameplayClockContainer(WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime) { this.beatmap = beatmap; @@ -93,6 +99,9 @@ namespace osu.Game.Screens.Play userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); userAudioOffset.BindValueChanged(offset => userOffsetClock.Offset = offset.NewValue, true); + adjustableClock.Seek(Math.Min(0, gameplayStartTime - totalOffset - (allowLeadIn ? beatmap.BeatmapInfo.AudioLeadIn : 0))); + adjustableClock.ProcessFrame(); + UserPlaybackRate.ValueChanged += _ => updateRate(); Seek(Math.Min(-beatmap.BeatmapInfo.AudioLeadIn, gameplayStartTime)); From d1d1c4ee7a5df46e20330b28b293dc700c9da7e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 16:13:58 +0900 Subject: [PATCH 1000/5608] Add lead-in tests --- .../Visual/Gameplay/TestCaseLeadIn.cs | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs new file mode 100644 index 0000000000..0186ba1da1 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.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 System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets; +using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestCaseLeadIn : RateAdjustedBeatmapTestCase + { + private Ruleset ruleset; + + private LeadInPlayer player; + + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) + { + Add(new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Depth = int.MaxValue + }); + + ruleset = rulesets.AvailableRulesets.First().CreateInstance(); + } + + [Test] + public void TestShortLeadIn() + { + AddStep("create player", () => loadPlayerWithBeatmap(new TestBeatmap(ruleset.RulesetInfo) { BeatmapInfo = { AudioLeadIn = 1000 } })); + AddUntilStep("correct lead-in", () => player.FirstFrameClockTime == 0); + } + + [Test] + public void TestLongLeadIn() + { + AddStep("create player", () => loadPlayerWithBeatmap(new TestBeatmap(ruleset.RulesetInfo) { BeatmapInfo = { AudioLeadIn = 10000 } })); + AddUntilStep("correct lead-in", () => player.FirstFrameClockTime == player.GameplayStartTime - 10000); + } + + private void loadPlayerWithBeatmap(IBeatmap beatmap) + { + Beatmap.Value = new TestWorkingBeatmap(beatmap, Clock); + + LoadScreen(player = new LeadInPlayer + { + AllowPause = false, + AllowResults = false, + }); + } + + private class LeadInPlayer : Player + { + public double? FirstFrameClockTime; + + public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; + + public double GameplayStartTime => DrawableRuleset.GameplayStartTime; + + public double GameplayClockTime => GameplayClockContainer.GameplayClock.CurrentTime; + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + if (!FirstFrameClockTime.HasValue) + { + FirstFrameClockTime = GameplayClockContainer.GameplayClock.CurrentTime; + AddInternal(new OsuSpriteText + { + Text = $"GameplayStartTime: {DrawableRuleset.GameplayStartTime} " + + $"LeadInTime: {Beatmap.Value.BeatmapInfo.AudioLeadIn} " + + $"FirstFrameClockTime: {FirstFrameClockTime}" + }); + } + } + } + } +} From e03a664970e39158396b478dfef1f6aa7e0574b3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 16:18:15 +0900 Subject: [PATCH 1001/5608] Fix lead-in logic to match stable Also adds storyboard event priority support. --- osu.Game/Screens/Play/GameplayClock.cs | 1 - osu.Game/Screens/Play/GameplayClockContainer.cs | 8 +++++++- osu.Game/Storyboards/Storyboard.cs | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClock.cs b/osu.Game/Screens/Play/GameplayClock.cs index b1948d02d5..6c9dacfc39 100644 --- a/osu.Game/Screens/Play/GameplayClock.cs +++ b/osu.Game/Screens/Play/GameplayClock.cs @@ -34,7 +34,6 @@ namespace osu.Game.Screens.Play public void ProcessFrame() { // we do not want to process the underlying clock. - // this is handled by PauseContainer. } public double ElapsedFrameTime => underlyingClock.ElapsedFrameTime; diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index f6a23575e9..7abdc8ef66 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -99,7 +99,13 @@ namespace osu.Game.Screens.Play userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); userAudioOffset.BindValueChanged(offset => userOffsetClock.Offset = offset.NewValue, true); - adjustableClock.Seek(Math.Min(0, gameplayStartTime - totalOffset - (allowLeadIn ? beatmap.BeatmapInfo.AudioLeadIn : 0))); + double startTime = -beatmap.BeatmapInfo.AudioLeadIn; + + startTime = Math.Min(startTime, beatmap.Storyboard.FirstEventTime); + startTime = Math.Min(startTime, gameplayStartTime); + startTime = Math.Min(startTime, 0); + + Seek(startTime); adjustableClock.ProcessFrame(); UserPlaybackRate.ValueChanged += _ => updateRate(); diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 3d988c5fe3..401a7ce25a 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -17,6 +17,8 @@ namespace osu.Game.Storyboards public bool HasDrawable => Layers.Any(l => l.Elements.Any(e => e.IsDrawable)); + public double FirstEventTime => Layers.Min(l => l.Elements.FirstOrDefault()?.StartTime ?? 0); + public Storyboard() { layers.Add("Background", new StoryboardLayer("Background", 3)); From a2fbcb2bd39e756503d6e98a9cf25fb57dba021e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 May 2019 15:58:46 +0900 Subject: [PATCH 1002/5608] Fix rebase regressions --- osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs | 14 ++++++++------ osu.Game/Screens/Play/GameplayClockContainer.cs | 6 ------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs index 0186ba1da1..33f1e4062f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { - public class TestCaseLeadIn : RateAdjustedBeatmapTestCase + public class TestCaseLeadIn : RateAdjustedBeatmapTestScene { private Ruleset ruleset; @@ -52,15 +52,16 @@ namespace osu.Game.Tests.Visual.Gameplay { Beatmap.Value = new TestWorkingBeatmap(beatmap, Clock); - LoadScreen(player = new LeadInPlayer - { - AllowPause = false, - AllowResults = false, - }); + LoadScreen(player = new LeadInPlayer()); } private class LeadInPlayer : Player { + public LeadInPlayer() + : base(false, false) + { + } + public double? FirstFrameClockTime; public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; @@ -72,6 +73,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); + if (!FirstFrameClockTime.HasValue) { FirstFrameClockTime = GameplayClockContainer.GameplayClock.CurrentTime; diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 7abdc8ef66..d718424b29 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -26,10 +26,6 @@ namespace osu.Game.Screens.Play private readonly WorkingBeatmap beatmap; private readonly IReadOnlyList mods; - private readonly bool allowLeadIn; - - private readonly double gameplayStartTime; - /// /// The original source (usually a 's track). /// @@ -91,8 +87,6 @@ namespace osu.Game.Screens.Play GameplayClock.IsPaused.BindTo(IsPaused); } - private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset; - [BackgroundDependencyLoader] private void load(OsuConfigManager config) { From 55c0c6a1bbffebe94d7a620689e42d3525d3f84a Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 31 May 2019 17:43:58 +0200 Subject: [PATCH 1003/5608] Show changelog for current build by clicking on settings footer in settings overlay. --- osu.Game/Overlays/Settings/SettingsFooter.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index e8c2c1ffe8..33ad5b101b 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -17,8 +18,11 @@ namespace osu.Game.Overlays.Settings { public class SettingsFooter : FillFlowContainer { + private OsuGameBase game; + private ChangelogOverlay changelog; + [BackgroundDependencyLoader] - private void load(OsuGameBase game, OsuColour colours, RulesetStore rulesets) + private void load(OsuGameBase game, OsuColour colours, RulesetStore rulesets, ChangelogOverlay changelog) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -67,6 +71,17 @@ namespace osu.Game.Overlays.Settings Colour = DebugUtils.IsDebug ? colours.Red : Color4.White, }, }; + + this.game = game; + this.changelog = changelog; + } + + protected override bool OnClick(ClickEvent e) + { + if (!game.IsDeployedBuild) return base.OnClick(e); + + changelog?.ShowBuild("lazer", game.Version); + return base.OnClick(e); } } } From 0625f51e65447596f6f1a0a77faf130968958b84 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 31 May 2019 22:42:09 +0200 Subject: [PATCH 1004/5608] Allow dependencies to be null in certain cases (Unit tests) --- osu.Game/Overlays/Settings/SettingsFooter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index 33ad5b101b..317ba2f92d 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Settings private OsuGameBase game; private ChangelogOverlay changelog; - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(OsuGameBase game, OsuColour colours, RulesetStore rulesets, ChangelogOverlay changelog) { RelativeSizeAxes = Axes.X; From 58564579e4f679e64d470eeda0a85dfe6e70b670 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 1 Jun 2019 08:46:38 +0200 Subject: [PATCH 1005/5608] Invert if statement --- osu.Game/Overlays/Settings/SettingsFooter.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index 317ba2f92d..3e0eb6ffde 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -78,10 +78,11 @@ namespace osu.Game.Overlays.Settings protected override bool OnClick(ClickEvent e) { - if (!game.IsDeployedBuild) return base.OnClick(e); - - changelog?.ShowBuild("lazer", game.Version); - return base.OnClick(e); + if (game.IsDeployedBuild) + { + changelog?.ShowBuild("lazer", game.Version); + } + return true; } } } From 0a867e37aff8782cdc97e1e57f41703bfa429312 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 2 Jun 2019 12:40:18 +0200 Subject: [PATCH 1006/5608] Resolve dependencies via Resolved Attribute --- osu.Game/Overlays/Settings/SettingsFooter.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index 3e0eb6ffde..306512802b 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -18,11 +18,14 @@ namespace osu.Game.Overlays.Settings { public class SettingsFooter : FillFlowContainer { - private OsuGameBase game; - private ChangelogOverlay changelog; + [Resolved] + private OsuGameBase game { get; set; } + + [Resolved(CanBeNull = true)] + private ChangelogOverlay changelog { get; set; } [BackgroundDependencyLoader(true)] - private void load(OsuGameBase game, OsuColour colours, RulesetStore rulesets, ChangelogOverlay changelog) + private void load(OsuGameBase game, OsuColour colours, RulesetStore rulesets) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -71,9 +74,6 @@ namespace osu.Game.Overlays.Settings Colour = DebugUtils.IsDebug ? colours.Red : Color4.White, }, }; - - this.game = game; - this.changelog = changelog; } protected override bool OnClick(ClickEvent e) @@ -82,6 +82,7 @@ namespace osu.Game.Overlays.Settings { changelog?.ShowBuild("lazer", game.Version); } + return true; } } From d8f45f7299dd1531f7b5b485e9feaa6b7a7ba9ba Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 2 Jun 2019 15:17:03 +0200 Subject: [PATCH 1007/5608] Disallow null references for dependencies loaded via load() --- osu.Game/Overlays/Settings/SettingsFooter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index 306512802b..8403f70f49 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Settings [Resolved(CanBeNull = true)] private ChangelogOverlay changelog { get; set; } - [BackgroundDependencyLoader(true)] + [BackgroundDependencyLoader] private void load(OsuGameBase game, OsuColour colours, RulesetStore rulesets) { RelativeSizeAxes = Axes.X; From 115a75e4c6604a214316e7e97752547b3610faff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Jun 2019 13:16:05 +0900 Subject: [PATCH 1008/5608] Use a constant for lazer variables --- osu.Desktop/Overlays/VersionManager.cs | 2 +- osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs | 2 +- osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs | 2 +- osu.Game/OsuGameBase.cs | 2 ++ osu.Game/Overlays/Settings/SettingsFooter.cs | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index d2aad99f41..5a8cf32f14 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -120,7 +120,7 @@ namespace osu.Desktop.Overlays Activated = delegate { - changelog.ShowBuild("lazer", version); + changelog.ShowBuild(OsuGameBase.CLIENT_STREAM_NAME, version); return true; }; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index d1a7730bee..0655611230 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Online { Version = "2018.712.0", DisplayVersion = "2018.712.0", - UpdateStream = new APIUpdateStream { Name = "lazer" }, + UpdateStream = new APIUpdateStream { Name = OsuGameBase.CLIENT_STREAM_NAME }, ChangelogEntries = new List { new APIChangelogEntry diff --git a/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs index ef204c7687..d9e48373bb 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs @@ -45,7 +45,7 @@ namespace osu.Game.Online.API.Requests.Responses case "cuttingedge": return new Color4(238, 170, 0, 255); - case "lazer": + case OsuGameBase.CLIENT_STREAM_NAME: return new Color4(237, 18, 33, 255); case "web": diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 7b9aed8364..00672e82bd 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -44,6 +44,8 @@ namespace osu.Game /// public class OsuGameBase : Framework.Game, ICanAcceptFiles { + public const string CLIENT_STREAM_NAME = "lazer"; + protected OsuConfigManager LocalConfig; protected BeatmapManager BeatmapManager; diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index 8403f70f49..298991712b 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -80,7 +80,7 @@ namespace osu.Game.Overlays.Settings { if (game.IsDeployedBuild) { - changelog?.ShowBuild("lazer", game.Version); + changelog?.ShowBuild(OsuGameBase.CLIENT_STREAM_NAME, game.Version); } return true; From b249fb35446d1176a5bcdec7487fe1d949551e2e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Jun 2019 13:37:29 +0900 Subject: [PATCH 1009/5608] Update test scene to support dynamic compilation --- ...stSceneSettings.cs => TestSceneSettingsPanel.cs} | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) rename osu.Game.Tests/Visual/Settings/{TestSceneSettings.cs => TestSceneSettingsPanel.cs} (71%) diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettings.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs similarity index 71% rename from osu.Game.Tests/Visual/Settings/TestSceneSettings.cs rename to osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs index 964754f8d0..27e3cc1590 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettings.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs @@ -1,20 +1,29 @@ // 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 NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Game.Overlays; +using osu.Game.Overlays.Settings; namespace osu.Game.Tests.Visual.Settings { [TestFixture] - public class TestSceneSettings : OsuTestScene + public class TestSceneSettingsPanel : OsuTestScene { private readonly SettingsPanel settings; private readonly DialogOverlay dialogOverlay; - public TestSceneSettings() + public override IReadOnlyList RequiredTypes => new[] + { + typeof(SettingsFooter), + typeof(SettingsOverlay), + }; + + public TestSceneSettingsPanel() { settings = new SettingsOverlay { From 4e5788959ee6e72953e1a17a01ff20adc90e0840 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Jun 2019 13:38:06 +0900 Subject: [PATCH 1010/5608] Make clickable text actually a button --- osu.Game/Overlays/Settings/SettingsFooter.cs | 47 ++++++++++++++------ 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index 298991712b..7a7f7bdf73 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; @@ -18,9 +18,6 @@ namespace osu.Game.Overlays.Settings { public class SettingsFooter : FillFlowContainer { - [Resolved] - private OsuGameBase game { get; set; } - [Resolved(CanBeNull = true)] private ChangelogOverlay changelog { get; set; } @@ -65,25 +62,49 @@ namespace osu.Game.Overlays.Settings Text = game.Name, Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), }, - new OsuSpriteText + new BuildDisplay(game.Version, DebugUtils.IsDebug) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Font = OsuFont.GetFont(size: 14), - Text = game.Version, - Colour = DebugUtils.IsDebug ? colours.Red : Color4.White, - }, + } }; } - protected override bool OnClick(ClickEvent e) + private class BuildDisplay : OsuAnimatedButton { - if (game.IsDeployedBuild) + private readonly string version; + private readonly bool isDebug; + + [Resolved] + private OsuColour colours { get; set; } + + public BuildDisplay(string version, bool isDebug) { - changelog?.ShowBuild(OsuGameBase.CLIENT_STREAM_NAME, game.Version); + this.version = version; + this.isDebug = isDebug; + + Content.RelativeSizeAxes = Axes.Y; + Content.AutoSizeAxes = AutoSizeAxes = Axes.X; + Height = 20; } - return true; + [BackgroundDependencyLoader(true)] + private void load(ChangelogOverlay changelog) + { + if (!isDebug) + Action = () => changelog?.ShowBuild(OsuGameBase.CLIENT_STREAM_NAME, version); + + Add(new OsuSpriteText + { + Font = OsuFont.GetFont(size: 16), + + Text = version, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Padding = new MarginPadding(5), + Colour = isDebug ? colours.Red : Color4.White, + }); + } } } } From 3ef17a54f671b181bdd2bd599f3be9d818abac58 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Jun 2019 13:53:24 +0900 Subject: [PATCH 1011/5608] Fix sizing of OsuAnimatedButton and OsuClickableContainer Was incorrect under some combinations of relative and autosize usage. --- .../TestSceneOsuAnimatedButton.cs | 73 +++++++++++++++++++ .../Containers/OsuClickableContainer.cs | 2 +- .../UserInterface/OsuAnimatedButton.cs | 6 ++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs new file mode 100644 index 0000000000..4bee3907f5 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.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 System; +using osu.Framework.Graphics; +using osu.Framework.Testing; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osuTK; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneOsuAnimatedButton : GridTestScene + { + public TestSceneOsuAnimatedButton() + : base(3, 2) + { + Cell(0).Add(new BaseContainer("relative sized") + { + RelativeSizeAxes = Axes.Both, + }); + + Cell(1).Add(new BaseContainer("auto sized") + { + AutoSizeAxes = Axes.Both + }); + + Cell(2).Add(new BaseContainer("relative Y auto X") + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X + }); + + Cell(3).Add(new BaseContainer("relative X auto Y") + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }); + + Cell(4).Add(new BaseContainer("fixed") + { + Size = new Vector2(100), + }); + + Cell(5).Add(new BaseContainer("fixed") + { + Size = new Vector2(100, 50), + }); + + AddToggleStep("toggle enabled", toggle => + { + for (int i = 0; i < 6; i++) + ((BaseContainer)Cell(i).Child).Action = toggle ? () => { } : (Action)null; + }); + } + + public class BaseContainer : OsuAnimatedButton + { + public BaseContainer(string text) + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + Add(new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = text + }); + } + } + } +} diff --git a/osu.Game/Graphics/Containers/OsuClickableContainer.cs b/osu.Game/Graphics/Containers/OsuClickableContainer.cs index 6dbe340efb..1f31e4cdda 100644 --- a/osu.Game/Graphics/Containers/OsuClickableContainer.cs +++ b/osu.Game/Graphics/Containers/OsuClickableContainer.cs @@ -31,7 +31,7 @@ namespace osu.Game.Graphics.Containers { if (AutoSizeAxes != Axes.None) { - content.RelativeSizeAxes = RelativeSizeAxes; + content.RelativeSizeAxes = (Axes.Both & ~AutoSizeAxes); content.AutoSizeAxes = AutoSizeAxes; } diff --git a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs index a8041c79fc..236b72766f 100644 --- a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs @@ -74,6 +74,12 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(OsuColour colours) { + if (AutoSizeAxes != Axes.None) + { + content.RelativeSizeAxes = (Axes.Both & ~AutoSizeAxes); + content.AutoSizeAxes = AutoSizeAxes; + } + Enabled.BindValueChanged(enabled => this.FadeColour(enabled.NewValue ? Color4.White : colours.Gray9, 200, Easing.OutQuint), true); } From 65e3b7c2ae35840c53f0bbd06c388997af9a2054 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Jun 2019 13:58:55 +0900 Subject: [PATCH 1012/5608] Remove unused DI --- osu.Game/Overlays/Settings/SettingsFooter.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index 7a7f7bdf73..b5ee4b4f0c 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -18,9 +18,6 @@ namespace osu.Game.Overlays.Settings { public class SettingsFooter : FillFlowContainer { - [Resolved(CanBeNull = true)] - private ChangelogOverlay changelog { get; set; } - [BackgroundDependencyLoader] private void load(OsuGameBase game, OsuColour colours, RulesetStore rulesets) { From 171fc14776f193958722b24e573edefc3b493a3a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Jun 2019 16:33:45 +0900 Subject: [PATCH 1013/5608] Fix editor regressions --- osu.Game/Graphics/UserInterface/IconButton.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs index 6414e488e8..052e9194fa 100644 --- a/osu.Game/Graphics/UserInterface/IconButton.cs +++ b/osu.Game/Graphics/UserInterface/IconButton.cs @@ -66,6 +66,7 @@ namespace osu.Game.Graphics.UserInterface set { Content.RelativeSizeAxes = Axes.None; + Content.AutoSizeAxes = Axes.None; Content.Size = value; } } From 491c9e96e078004025613c05faa97a49faa89f37 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Jun 2019 16:41:27 +0900 Subject: [PATCH 1014/5608] Fix tests not ending execution after some exceptions --- osu.Game/Tests/Visual/OsuTestScene.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 9b775fd498..d03b490bd4 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -61,7 +61,8 @@ namespace osu.Game.Tests.Visual { base.Dispose(isDisposing); - beatmap?.Value.Track.Stop(); + if (beatmap?.Value.TrackLoaded == true) + beatmap.Value.Track.Stop(); if (localStorage.IsValueCreated) { From 17d04545fad1d6977fdd8a67761d46e4fb5bb059 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Jun 2019 16:45:18 +0900 Subject: [PATCH 1015/5608] Localise GridTestScene as an OsuGridTestScene --- .../Visual/UserInterface/TestSceneLoadingAnimation.cs | 3 +-- .../Visual/UserInterface/TestSceneOsuAnimatedButton.cs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingAnimation.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingAnimation.cs index b9a6d74f19..b0233d35f9 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingAnimation.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingAnimation.cs @@ -3,13 +3,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Framework.Testing; using osu.Game.Graphics.UserInterface; using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLoadingAnimation : GridTestScene //todo: this should be an OsuTestScene + public class TestSceneLoadingAnimation : OsuGridTestScene { public TestSceneLoadingAnimation() : base(2, 2) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs index 4bee3907f5..6a41d08f01 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs @@ -3,14 +3,13 @@ using System; using osu.Framework.Graphics; -using osu.Framework.Testing; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneOsuAnimatedButton : GridTestScene + public class TestSceneOsuAnimatedButton : OsuGridTestScene { public TestSceneOsuAnimatedButton() : base(3, 2) From e32f62db5bdf473579ee062a67d7c765fb95e2ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Jun 2019 16:48:44 +0900 Subject: [PATCH 1016/5608] Add missing file --- .../Visual/UserInterface/OsuGridTestScene.cs | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/OsuGridTestScene.cs diff --git a/osu.Game.Tests/Visual/UserInterface/OsuGridTestScene.cs b/osu.Game.Tests/Visual/UserInterface/OsuGridTestScene.cs new file mode 100644 index 0000000000..096ac951de --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/OsuGridTestScene.cs @@ -0,0 +1,50 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Tests.Visual.UserInterface +{ + /// + /// An abstract test case which exposes small cells arranged in a grid. + /// Useful for displaying multiple configurations of a tested component at a glance. + /// + public abstract class OsuGridTestScene : OsuTestScene + { + private readonly Drawable[,] cells; + + /// + /// The amount of rows in the grid. + /// + protected readonly int Rows; + + /// + /// The amount of columns in the grid. + /// + protected readonly int Cols; + + /// + /// Constructs a grid test case with the given dimensions. + /// + protected OsuGridTestScene(int rows, int cols) + { + Rows = rows; + Cols = cols; + + GridContainer testContainer; + Add(testContainer = new GridContainer { RelativeSizeAxes = Axes.Both }); + + cells = new Drawable[rows, cols]; + for (int r = 0; r < rows; r++) + for (int c = 0; c < cols; c++) + cells[r, c] = new Container { RelativeSizeAxes = Axes.Both }; + + testContainer.Content = cells.ToJagged(); + } + + protected Container Cell(int index) => (Container)cells[index / Cols, index % Cols]; + protected Container Cell(int row, int col) => (Container)cells[row, col]; + } +} From 1eab4e179ddb5583ded246af115edafdc41b89c1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Jun 2019 17:05:35 +0900 Subject: [PATCH 1017/5608] Add sample action to test so hover effect is visible --- osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs index 0d6d378f4c..936842bdfa 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs @@ -23,6 +23,7 @@ namespace osu.Game.Tests.Visual.Online { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Action = () => { } }); AddStep("switch loading state", () => button.IsLoading = !button.IsLoading); From c4f4f32db8a24f97922000610172e672d5e03e48 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Jun 2019 17:06:07 +0900 Subject: [PATCH 1018/5608] Shorten fade duration --- osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs index 31c73aaa96..6b7c37b42d 100644 --- a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs +++ b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs @@ -18,6 +18,8 @@ namespace osu.Game.Overlays.Profile.Sections { public class ShowMoreButton : OsuHoverContainer { + private const float fade_duration = 200; + private readonly Box background; private readonly LoadingAnimation loading; private readonly FillFlowContainer content; @@ -38,13 +40,13 @@ namespace osu.Game.Overlays.Profile.Sections if (value) { - loading.FadeIn(FADE_DURATION, Easing.OutQuint); - content.FadeOut(FADE_DURATION, Easing.OutQuint); + loading.FadeIn(fade_duration, Easing.OutQuint); + content.FadeOut(fade_duration, Easing.OutQuint); } else { - loading.FadeOut(FADE_DURATION, Easing.OutQuint); - content.FadeIn(FADE_DURATION, Easing.OutQuint); + loading.FadeOut(fade_duration, Easing.OutQuint); + content.FadeIn(fade_duration, Easing.OutQuint); } } } From 633c3b74ec5b746de3565a2dfe234641cfae1bea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Jun 2019 17:10:18 +0900 Subject: [PATCH 1019/5608] Don't handle clicks when in a loading state --- osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs index 6b7c37b42d..328a1fa6b7 100644 --- a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs +++ b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.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.Allocation; @@ -38,6 +38,8 @@ namespace osu.Game.Overlays.Profile.Sections isLoading = value; + Enabled.Value = !isLoading; + if (value) { loading.FadeIn(fade_duration, Easing.OutQuint); From 4e6d7137aa370d89c7a8381ffb1e41c357a77c10 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Mon, 3 Jun 2019 17:25:19 +0800 Subject: [PATCH 1020/5608] disallow current user from opening their own private channel --- osu.Game/Online/Chat/ChannelManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 2efc9f4968..3af11ff20f 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -81,6 +81,9 @@ namespace osu.Game.Online.Chat if (user == null) throw new ArgumentNullException(nameof(user)); + if (user.Id == api.LocalUser.Value.Id) + return; + CurrentChannel.Value = JoinedChannels.FirstOrDefault(c => c.Type == ChannelType.PM && c.Users.Count == 1 && c.Users.Any(u => u.Id == user.Id)) ?? new Channel(user); } From 516575a132fead92342b62aa02da527ebbccabe2 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Mon, 3 Jun 2019 18:54:29 +0800 Subject: [PATCH 1021/5608] don't create "Start Chat" option when the sender is the local user --- osu.Game/Overlays/Chat/ChatLine.cs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 66a6672ab1..86bbe91d35 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -14,6 +15,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; using osu.Game.Online.Chat; using osu.Game.Users; using osuTK; @@ -201,6 +203,9 @@ namespace osu.Game.Overlays.Chat private Action startChatAction; + [Resolved] + private IAPIProvider api { get; set; } + public MessageSender(User sender) { this.sender = sender; @@ -213,11 +218,21 @@ namespace osu.Game.Overlays.Chat startChatAction = () => chatManager?.OpenPrivateChannel(sender); } - public MenuItem[] ContextMenuItems => new MenuItem[] + public MenuItem[] ContextMenuItems { - new OsuMenuItem("View Profile", MenuItemType.Highlighted, Action), - new OsuMenuItem("Start Chat", MenuItemType.Standard, startChatAction), - }; + get + { + List items = new List + { + new OsuMenuItem("View Profile", MenuItemType.Highlighted, Action) + }; + + if (sender.Id != api.LocalUser.Value.Id) + items.Add(new OsuMenuItem("Start Chat", MenuItemType.Standard, startChatAction)); + + return items.ToArray(); + } + } } private static readonly Color4[] username_colours = From 194bb80354d7f8d49ed64ba26ac493e53c092151 Mon Sep 17 00:00:00 2001 From: Welsar55 Date: Mon, 3 Jun 2019 11:09:21 -0500 Subject: [PATCH 1022/5608] Added close button and indictors of hotkeys to buttons --- osu.Game/Overlays/Mods/ModSection.cs | 6 +----- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 25 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index f584eff0f9..50400e254f 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -57,11 +57,7 @@ namespace osu.Game.Overlays.Mods protected override bool OnKeyDown(KeyDownEvent e) { - if(e.Key == Key.Number1) - { - DeselectAll(); - } - else if (ToggleKeys != null) + if (ToggleKeys != null) { var index = Array.IndexOf(ToggleKeys, e.Key); if (index > -1 && index < buttons.Length) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 97769fe5aa..c304dc2eb3 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osuTK; +using osuTK.Input; using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -23,6 +24,7 @@ using osu.Game.Rulesets; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods.Sections; using osu.Game.Screens; +using osu.Framework.Input.Events; namespace osu.Game.Overlays.Mods { @@ -33,6 +35,7 @@ namespace osu.Game.Overlays.Mods protected Color4 LowMultiplierColour, HighMultiplierColour; protected readonly TriangleButton DeselectAllButton; + protected readonly TriangleButton CloseButton; protected readonly OsuSpriteText MultiplierLabel, UnrankedLabel; private readonly FillFlowContainer footerContainer; @@ -192,6 +195,16 @@ namespace osu.Game.Overlays.Mods refreshSelectedMods(); } + protected override bool OnKeyDown(KeyDownEvent e) + { + if (e.Key == Key.Number1) + DeselectAll(); + else if (e.Key == Key.Number2) + PopOut(); + + return base.OnKeyDown(e); + } + private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray(); public ModSelectOverlay() @@ -357,13 +370,23 @@ namespace osu.Game.Overlays.Mods DeselectAllButton = new TriangleButton { Width = 180, - Text = "Deselect All", + Text = "1. Deselect All", Action = DeselectAll, Margin = new MarginPadding { Right = 20 } }, + CloseButton = new TriangleButton + { + Width = 180, + Text = "2. Close", + Action = PopOut, + Margin = new MarginPadding + { + Right = 20 + } + }, new OsuSpriteText { Text = @"Score Multiplier:", From fe6b4112c6e5244779ada7ed0eea1ca805522c50 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 01:47:45 +0300 Subject: [PATCH 1023/5608] Adjust colors to match web design --- osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs index 328a1fa6b7..485595798d 100644 --- a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs +++ b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs @@ -102,8 +102,8 @@ namespace osu.Game.Overlays.Profile.Sections [BackgroundDependencyLoader] private void load(OsuColour colors) { - IdleColour = colors.GreySeafoam; - HoverColour = colors.GreySeafoamLight; + IdleColour = colors.GreySeafoamDark; + HoverColour = colors.GreySeafoam; } protected override bool OnClick(ClickEvent e) From 2c713712820d9f9a3152e1fc67143eb1fb730fca Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 02:06:15 +0300 Subject: [PATCH 1024/5608] Fix endless loading state --- osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs index 485595798d..82554faac8 100644 --- a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs +++ b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs @@ -38,8 +38,6 @@ namespace osu.Game.Overlays.Profile.Sections isLoading = value; - Enabled.Value = !isLoading; - if (value) { loading.FadeIn(fade_duration, Easing.OutQuint); @@ -108,6 +106,9 @@ namespace osu.Game.Overlays.Profile.Sections protected override bool OnClick(ClickEvent e) { + if (IsLoading) + return true; + IsLoading = true; return base.OnClick(e); } From d5a2ebf79f3f4b6e7633b7faf92b4a4ce35aa9c9 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 04:04:33 +0300 Subject: [PATCH 1025/5608] Fix endless loading state part 2 --- .../Overlays/Profile/Sections/ShowMoreButton.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs index 82554faac8..a1dcfc036e 100644 --- a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs +++ b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs @@ -38,6 +38,8 @@ namespace osu.Game.Overlays.Profile.Sections isLoading = value; + Enabled.Value = !isLoading; + if (value) { loading.FadeIn(fade_duration, Easing.OutQuint); @@ -106,11 +108,14 @@ namespace osu.Game.Overlays.Profile.Sections protected override bool OnClick(ClickEvent e) { - if (IsLoading) - return true; + var clickResult = base.OnClick(e); - IsLoading = true; - return base.OnClick(e); + if (IsLoading) + return clickResult; + + IsLoading |= clickResult; + + return clickResult; } private class ChevronIcon : SpriteIcon From e8315085c0021a1fcdd1e2fff515673915c11ddc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jun 2019 10:26:21 +0900 Subject: [PATCH 1026/5608] Better handle OnClick --- .../Profile/Sections/ShowMoreButton.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs index a1dcfc036e..5ed546c62b 100644 --- a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs +++ b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs @@ -108,14 +108,18 @@ namespace osu.Game.Overlays.Profile.Sections protected override bool OnClick(ClickEvent e) { - var clickResult = base.OnClick(e); + if (!Enabled.Value) + return false; - if (IsLoading) - return clickResult; - - IsLoading |= clickResult; - - return clickResult; + try + { + return base.OnClick(e); + } + finally + { + // run afterwards as this will disable this button. + IsLoading = true; + } } private class ChevronIcon : SpriteIcon From a5a025de6867edbfb70cf13df58353da4ea044cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jun 2019 10:26:35 +0900 Subject: [PATCH 1027/5608] Add proper tests --- .../Visual/Online/TestSceneShowMoreButton.cs | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs index 936842bdfa..bccb263600 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs @@ -17,16 +17,39 @@ namespace osu.Game.Tests.Visual.Online public TestSceneShowMoreButton() { - ShowMoreButton button; + ShowMoreButton button = null; + + int fireCount = 0; Add(button = new ShowMoreButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Action = () => { } + Action = () => + { + fireCount++; + // ReSharper disable once AccessToModifiedClosure + // ReSharper disable once PossibleNullReferenceException + Scheduler.AddDelayed(() => button.IsLoading = false, 2000); + } }); - AddStep("switch loading state", () => button.IsLoading = !button.IsLoading); + AddStep("click button", () => button.Click()); + + AddAssert("action fired once", () => fireCount == 1); + AddAssert("is in loading state", () => button.IsLoading); + + AddStep("click button", () => button.Click()); + + AddAssert("action not fired", () => fireCount == 1); + AddAssert("is in loading state", () => button.IsLoading); + + AddUntilStep("wait for loaded", () => !button.IsLoading); + + AddStep("click button", () => button.Click()); + + AddAssert("action fired twice", () => fireCount == 2); + AddAssert("is in loading state", () => button.IsLoading); } } } From cea353975fd46ff4eeb52dd9970eb2fa6fed19f3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Jun 2019 11:04:28 +0900 Subject: [PATCH 1028/5608] Update with further framework-side changes --- .../Visual/Editor/TestSceneWaveform.cs | 5 +---- ...tSceneUpdateableBeatmapBackgroundSprite.cs | 2 +- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- .../UpdateableBeatmapBackgroundSprite.cs | 21 +++---------------- .../Overlays/Changelog/UpdateStreamBadge.cs | 4 ++-- osu.Game/Overlays/ChangelogOverlay.cs | 2 +- .../Screens/Multi/Match/Components/Header.cs | 2 +- 7 files changed, 10 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs b/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs index 7b27998d7f..e2762f3d5f 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneWaveform.cs @@ -21,13 +21,10 @@ namespace osu.Game.Tests.Visual.Editor { private WorkingBeatmap waveformBeatmap; - private OsuGameBase game; - [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuGameBase game) + private void load(AudioManager audio) { waveformBeatmap = new WaveformTestBeatmap(audio); - this.game = game; } [TestCase(1f)] diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs index 23065629a6..d39358a972 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.UserInterface TestUpdateableBeatmapBackgroundSprite background = null; AddStep("load null beatmap", () => Child = background = new TestUpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }); - AddUntilStep("wait for load", () => background.ContentLoaded); + AddAssert("no content", () => !background.ContentLoaded); } [Test] diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index e1cc5db3ad..4b1bddbf0d 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -45,7 +45,7 @@ namespace osu.Game.Beatmaps private TextureStore textureStore; - private IAdjustableResourceStore trackStore; + private ITrackStore trackStore; protected override bool BackgroundStillValid(Texture b) => false; // bypass lazy logic. we want to return a new background each time for refcounting purposes. diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 96786f5f49..1fd3502799 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -31,24 +32,8 @@ namespace osu.Game.Beatmaps.Drawables /// protected virtual double UnloadDelay => 10000; - private BeatmapInfo lastModel; - private bool firstLoad = true; - - protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Drawable content, double timeBeforeLoad) - { - return new DelayedLoadUnloadWrapper(() => - { - // If DelayedLoadUnloadWrapper is attempting to RELOAD the same content (Beatmap), that means that it was - // previously UNLOADED and thus its children have been disposed of, so we need to recreate them here. - if (!firstLoad && lastModel == Beatmap.Value) - return CreateDrawable(Beatmap.Value); - - // If the model has changed since the previous unload (or if there was no load), then we can safely use the given content - lastModel = Beatmap.Value; - firstLoad = false; - return content; - }, timeBeforeLoad, UnloadDelay); - } + protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Func createContentFunc, double timeBeforeLoad) + => new DelayedLoadUnloadWrapper(createContentFunc, timeBeforeLoad, UnloadDelay); protected override Drawable CreateDrawable(BeatmapInfo model) { diff --git a/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs b/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs index 514e75c31a..52b77604d9 100644 --- a/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs +++ b/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs @@ -90,8 +90,8 @@ namespace osu.Game.Overlays.Changelog [BackgroundDependencyLoader] private void load(AudioManager audio) { - sampleClick = audio.Sample.Get(@"UI/generic-select-soft"); - sampleHover = audio.Sample.Get(@"UI/generic-hover-soft"); + sampleClick = audio.Samples.Get(@"UI/generic-select-soft"); + sampleHover = audio.Samples.Get(@"UI/generic-hover-soft"); } protected override void OnActivated() => updateState(); diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 7d791b2a88..4a6d53b480 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -76,7 +76,7 @@ namespace osu.Game.Overlays }, }; - sampleBack = audio.Sample.Get(@"UI/generic-select-soft"); + sampleBack = audio.Samples.Get(@"UI/generic-select-soft"); header.Current.BindTo(Current); diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index 2a6074882d..73994fa369 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -137,7 +137,7 @@ namespace osu.Game.Screens.Multi.Match.Components private class BackgroundSprite : UpdateableBeatmapBackgroundSprite { - protected override double FadeDuration => 200; + protected override double TransformDuration => 200; } } } From 474191fcec71e49c6fb1ca95c3b5972c76dbbb2c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Jun 2019 11:13:21 +0900 Subject: [PATCH 1029/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b77c724d1b..f84bb64fbf 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + From 4763a41c7ed32f6920a8ac0edf357edc292017fd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Jun 2019 11:25:18 +0900 Subject: [PATCH 1030/5608] Cleanups --- .../Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs | 3 --- osu.Game/Beatmaps/BindableBeatmap.cs | 2 -- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 6 +++--- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs index de4f4d9d25..8091e93471 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs @@ -18,9 +18,6 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMatchSettingsOverlay : MultiplayerTestScene { - [Resolved] - private OsuGameBase game { get; set; } - public override IReadOnlyList RequiredTypes => new[] { typeof(MatchSettingsOverlay) diff --git a/osu.Game/Beatmaps/BindableBeatmap.cs b/osu.Game/Beatmaps/BindableBeatmap.cs index 1e69a17ef7..af627cc6a9 100644 --- a/osu.Game/Beatmaps/BindableBeatmap.cs +++ b/osu.Game/Beatmaps/BindableBeatmap.cs @@ -24,8 +24,6 @@ namespace osu.Game.Beatmaps { var trackLoaded = lastBeatmap?.TrackLoaded ?? false; - //beatmap.AudioManager = AudioManager; - // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo) if (!trackLoaded || lastBeatmap?.Track != beatmap.Track) { diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 9202c617bf..3a4c677bd1 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -44,7 +44,7 @@ namespace osu.Game.Beatmaps protected override Texture GetBackground() => textures?.Get(@"Backgrounds/bg4"); - protected override Track GetTrack() => GetVirtualTrack(Beatmap); + protected override Track GetTrack() => GetVirtualTrack(); private class DummyRulesetInfo : RulesetInfo { diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index cf1acaf46b..328763fc9f 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -51,18 +51,18 @@ namespace osu.Game.Beatmaps return b; }); - track = new RecyclableLazy(() => GetTrack() ?? GetVirtualTrack(Beatmap)); + track = new RecyclableLazy(() => GetTrack() ?? GetVirtualTrack()); background = new RecyclableLazy(GetBackground, BackgroundStillValid); waveform = new RecyclableLazy(GetWaveform); storyboard = new RecyclableLazy(GetStoryboard); skin = new RecyclableLazy(GetSkin); } - protected virtual Track GetVirtualTrack(IBeatmap beatmap) + protected virtual Track GetVirtualTrack() { const double excess_length = 1000; - var lastObject = beatmap.HitObjects.LastOrDefault(); + var lastObject = Beatmap.HitObjects.LastOrDefault(); double length; From b8fc53512453ed87730c399e23ed0b5134ec7e5e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jun 2019 12:08:23 +0900 Subject: [PATCH 1031/5608] Fix blueprint tests crashing due to out-of-order operations --- osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs index c1561ffea1..2b177e264f 100644 --- a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs +++ b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs @@ -15,19 +15,18 @@ namespace osu.Game.Tests.Visual [Cached(Type = typeof(IPlacementHandler))] public abstract class PlacementBlueprintTestScene : OsuTestScene, IPlacementHandler { - protected readonly Container HitObjectContainer; + protected Container HitObjectContainer; private PlacementBlueprint currentBlueprint; protected PlacementBlueprintTestScene() { - Beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize = 2; - Add(HitObjectContainer = CreateHitObjectContainer()); } [BackgroundDependencyLoader] private void load() { + Beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize = 2; Add(currentBlueprint = CreateBlueprint()); } From 9c214c3f0ec9e8a09f46b2a276a043d55dd38c67 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jun 2019 16:13:16 +0900 Subject: [PATCH 1032/5608] Add animation on failing --- .../Visual/Gameplay/TestSceneFailAnimation.cs | 50 ++++++++ .../Visual/Gameplay/TestScenePause.cs | 2 +- osu.Game/Rulesets/UI/DrawableRuleset.cs | 7 +- osu.Game/Screens/Play/FailAnimation.cs | 113 ++++++++++++++++++ osu.Game/Screens/Play/Player.cs | 26 +++- 5 files changed, 191 insertions(+), 7 deletions(-) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs create mode 100644 osu.Game/Screens/Play/FailAnimation.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs new file mode 100644 index 0000000000..4878587dcd --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs @@ -0,0 +1,50 @@ +// 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.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestSceneFailAnimation : AllPlayersTestScene + { + protected override Player CreatePlayer(Ruleset ruleset) + { + Mods.Value = Array.Empty(); + return new FailPlayer(); + } + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(AllPlayersTestScene), + typeof(TestPlayer), + typeof(Player), + }; + + protected override void AddCheckSteps() + { + AddUntilStep("wait for fail", () => Player.HasFailed); + AddUntilStep("wait for fail overlay", () => ((FailPlayer)Player).FailOverlay.State == Visibility.Visible); + } + + private class FailPlayer : TestPlayer + { + public new FailOverlay FailOverlay => base.FailOverlay; + + public FailPlayer() + : base(false, false) + { + } + + protected override void LoadComplete() + { + base.LoadComplete(); + ScoreProcessor.FailConditions += _ => true; + } + } + } +} diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index b6f8638f4a..12e91df77c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -113,7 +113,7 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestPauseAfterFail() { AddUntilStep("wait for fail", () => Player.HasFailed); - AddAssert("fail overlay shown", () => Player.FailOverlayVisible); + AddUntilStep("fail overlay shown", () => Player.FailOverlayVisible); confirmClockRunning(false); diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 7db24d36a5..52fba9cab3 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.UI /// /// The playfield. /// - public Playfield Playfield => playfield.Value; + public override Playfield Playfield => playfield.Value; /// /// Place to put drawables above hit objects but below UI. @@ -342,6 +342,11 @@ namespace osu.Game.Rulesets.UI /// public readonly BindableBool IsPaused = new BindableBool(); + /// + /// The playfield. + /// + public abstract Playfield Playfield { get; } + /// /// The frame-stable clock which is being used for playfield display. /// diff --git a/osu.Game/Screens/Play/FailAnimation.cs b/osu.Game/Screens/Play/FailAnimation.cs new file mode 100644 index 0000000000..a3caffb620 --- /dev/null +++ b/osu.Game/Screens/Play/FailAnimation.cs @@ -0,0 +1,113 @@ +// 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.Audio; +using osu.Framework.Bindables; +using osu.Game.Rulesets.UI; +using System; +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Audio.Sample; +using osu.Framework.Audio.Track; +using osu.Framework.Graphics; +using osu.Framework.MathUtils; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects.Drawables; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Play +{ + /// + /// Manage the animation to be applied when a player fails. + /// Single file; automatically disposed after use. + /// + public class FailAnimation : Component + { + public Action OnComplete; + + private readonly DrawableRuleset drawableRuleset; + + private readonly BindableDouble trackFreq = new BindableDouble(1); + + private Track track; + + private const float duration = 2500; + + private SampleChannel failSample; + + public FailAnimation(DrawableRuleset drawableRuleset) + { + this.drawableRuleset = drawableRuleset; + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio, IBindable beatmap) + { + track = beatmap.Value.Track; + failSample = audio.Samples.Get(@"Gameplay/failsound"); + } + + private bool started; + + /// + /// Start the fail animation playing. + /// + /// Thrown if started more than once. + public void Start() + { + if (started) throw new InvalidOperationException("Animation cannot be started more than once."); + + started = true; + + failSample.Play(); + + this.TransformBindableTo(trackFreq, 0, duration).OnComplete(_ => + { + OnComplete?.Invoke(); + Expire(); + }); + + track.AddAdjustment(AdjustableProperty.Frequency, trackFreq); + + applyToPlayfield(drawableRuleset.Playfield); + drawableRuleset.Playfield.HitObjectContainer.FlashColour(Color4.Red, 500); + drawableRuleset.Playfield.HitObjectContainer.FadeOut(duration / 2); + } + + protected override void Update() + { + base.Update(); + + if (!started) + return; + + applyToPlayfield(drawableRuleset.Playfield); + } + + private readonly List appliedObjects = new List(); + + private void applyToPlayfield(Playfield playfield) + { + foreach (var nested in playfield.NestedPlayfields) + applyToPlayfield(nested); + + foreach (DrawableHitObject obj in playfield.HitObjectContainer.AliveObjects) + { + if (appliedObjects.Contains(obj)) + continue; + + obj.RotateTo(RNG.NextSingle(-90, 90), duration); + obj.ScaleTo(obj.Scale * 0.5f, duration); + obj.MoveToOffset(new Vector2(0, 400), duration); + appliedObjects.Add(obj); + } + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + track?.RemoveAdjustment(AdjustableProperty.Frequency, trackFreq); + } + } +} diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index cf743ee4f7..d8389fa6d9 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.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; @@ -173,7 +173,8 @@ namespace osu.Game.Screens.Play fadeOut(true); Restart(); }, - } + }, + failAnimation = new FailAnimation(DrawableRuleset) { OnComplete = onFailComplete, } }; DrawableRuleset.HasReplayLoaded.BindValueChanged(e => HUDOverlay.HoldToQuit.PauseOnFocusLost = !e.NewValue && PauseOnFocusLost, true); @@ -345,13 +346,13 @@ namespace osu.Game.Screens.Play protected FailOverlay FailOverlay { get; private set; } + private FailAnimation failAnimation; + private bool onFail() { if (Mods.Value.OfType().Any(m => !m.AllowFail)) return false; - GameplayClockContainer.Stop(); - HasFailed = true; // There is a chance that we could be in a paused state as the ruleset's internal clock (see FrameStabilityContainer) @@ -360,9 +361,17 @@ namespace osu.Game.Screens.Play if (PauseOverlay.State == Visibility.Visible) PauseOverlay.Hide(); + failAnimation.Start(); + return true; + } + + // Called back when the transform finishes + private void onFailComplete() + { + GameplayClockContainer.Stop(); + FailOverlay.Retries = RestartCount; FailOverlay.Show(); - return true; } #endregion @@ -489,6 +498,13 @@ namespace osu.Game.Screens.Play // still want to block if we are within the cooldown period and not already paused. return true; + if (HasFailed && ValidForResume && !FailOverlay.IsPresent) + // ValidForResume is false when restarting + { + failAnimation.FinishTransforms(true); + return true; + } + GameplayClockContainer.ResetLocalAdjustments(); fadeOut(); From 7d2a75b3502702aa035a7200fbd30b5885534199 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jun 2019 18:37:26 +0900 Subject: [PATCH 1033/5608] Dim music volume when holding to confirm --- osu.Game/Overlays/HoldToConfirmOverlay.cs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/HoldToConfirmOverlay.cs b/osu.Game/Overlays/HoldToConfirmOverlay.cs index fb38ddcbd1..fdc6f096bc 100644 --- a/osu.Game/Overlays/HoldToConfirmOverlay.cs +++ b/osu.Game/Overlays/HoldToConfirmOverlay.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; @@ -17,6 +19,11 @@ namespace osu.Game.Overlays { private Box overlay; + private readonly BindableDouble audioVolume = new BindableDouble(1); + + [Resolved] + private AudioManager audio { get; set; } + [BackgroundDependencyLoader] private void load() { @@ -33,7 +40,19 @@ namespace osu.Game.Overlays } }; - Progress.ValueChanged += p => overlay.Alpha = (float)p.NewValue; + Progress.ValueChanged += p => + { + audioVolume.Value = 1 - p.NewValue; + overlay.Alpha = (float)p.NewValue; + }; + + audio.Tracks.AddAdjustment(AdjustableProperty.Volume, audioVolume); + } + + protected override void Dispose(bool isDisposing) + { + audio.Tracks.RemoveAdjustment(AdjustableProperty.Volume, audioVolume); + base.Dispose(isDisposing); } } } From ff647940ca09fd7b0107edb198d44c1d481087e7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Jun 2019 19:25:34 +0900 Subject: [PATCH 1034/5608] Fix incorrect assertion --- .../UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs index d39358a972..f59458ef8d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.UserInterface TestUpdateableBeatmapBackgroundSprite background = null; AddStep("load null beatmap", () => Child = background = new TestUpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }); - AddAssert("no content", () => !background.ContentLoaded); + AddUntilStep("content loaded", () => background.ContentLoaded); } [Test] From 2e3d392a9f66470b6fe7fb3194c92f7b196d8243 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jun 2019 22:12:55 +0900 Subject: [PATCH 1035/5608] Mark OsuButton as abstract Not being used directly, so we probably shouldn't support it for now. --- osu.Game/Graphics/UserInterface/OsuButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 7a27f825f6..494d4e4262 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -17,11 +17,11 @@ namespace osu.Game.Graphics.UserInterface /// /// A button with added default sound effects. /// - public class OsuButton : Button + public abstract class OsuButton : Button { private Box hover; - public OsuButton() + protected OsuButton() { Height = 40; From 0abb48882cdeb636d20aa9030582642458dbb545 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 16:22:54 +0300 Subject: [PATCH 1036/5608] Implement GamemodeControl --- .../Header/Components/GamemodeControl.cs | 142 ++++++++++++++++++ osu.Game/Overlays/Profile/ProfileHeader.cs | 12 +- 2 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs diff --git a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs new file mode 100644 index 0000000000..5909082fc8 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs @@ -0,0 +1,142 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Profile.Header.Components +{ + public class GamemodeControl : TabControl + { + protected override Dropdown CreateDropdown() => null; + + protected override TabItem CreateTabItem(string value) => new GamemodeTabItem(value) + { + AccentColour = AccentColour + }; + + private Color4 accentColour = Color4.White; + + public Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) + return; + + accentColour = value; + + foreach (TabItem tabItem in TabContainer) + { + ((GamemodeTabItem)tabItem).AccentColour = value; + } + } + } + + public GamemodeControl() + { + TabContainer.Masking = false; + TabContainer.Spacing = new Vector2(15, 0); + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) + { + foreach (var r in rulesets.AvailableRulesets) + AddItem(r.Name); + } + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + }; + + private class GamemodeTabItem : TabItem + { + private readonly OsuSpriteText text; + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) + return; + + accentColour = value; + + updateState(); + } + } + + public GamemodeTabItem(string value) + : base(value) + { + AutoSizeAxes = Axes.Both; + + Children = new Drawable[] + { + text = new OsuSpriteText + { + Margin = new MarginPadding { Bottom = 10 }, + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + Text = value, + Font = OsuFont.GetFont() + }, + new HoverClickSounds() + }; + } + + protected override bool OnHover(HoverEvent e) + { + base.OnHover(e); + + updateState(); + + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + updateState(); + } + + protected override void OnActivated() => updateState(); + + protected override void OnDeactivated() => updateState(); + + private void updateState() + { + if (Active.Value || IsHovered) + { + text.FadeColour(Color4.White, 120, Easing.InQuad); + + if (Active.Value) + text.Font = text.Font.With(weight: FontWeight.Bold); + } + else + { + text.FadeColour(AccentColour, 120, Easing.InQuad); + text.Font = text.Font.With(weight: FontWeight.Medium); + } + } + } + } +} diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 76613c156d..46751eea25 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Profile.Header; +using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Users; namespace osu.Game.Overlays.Profile @@ -18,6 +19,7 @@ namespace osu.Game.Overlays.Profile public class ProfileHeader : OverlayHeader { private UserCoverBackground coverContainer; + private readonly GamemodeControl gamemodeControl; public Bindable User = new Bindable(); @@ -32,12 +34,20 @@ namespace osu.Game.Overlays.Profile TabControl.AddItem("Modding"); centreHeaderContainer.DetailsVisible.BindValueChanged(visible => detailHeaderContainer.Expanded = visible.NewValue, true); + + Add(gamemodeControl = new GamemodeControl + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Y = 100, + Margin = new MarginPadding { Right = 30 }, + }); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - TabControl.AccentColour = colours.Seafoam; + TabControl.AccentColour = gamemodeControl.AccentColour = colours.Seafoam; } protected override Drawable CreateBackground() => From e9c4b521afe76f4b0ec5af79fb0607eb1c1e51e5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Jun 2019 22:26:11 +0900 Subject: [PATCH 1037/5608] Test github "funding" button --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..0c6b80e97e --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +custom: https://osu.ppy.sh/home/support From a0f7f69f463eb8edefd68ed71b94dd74cb8f104d Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 17:51:56 +0300 Subject: [PATCH 1038/5608] retrieve user's default playmode --- .../Header/Components/GamemodeControl.cs | 64 +++++++++++++++++-- osu.Game/Overlays/Profile/ProfileHeader.cs | 12 +++- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs index 5909082fc8..f66023c958 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics; @@ -46,7 +47,7 @@ namespace osu.Game.Overlays.Profile.Header.Components public GamemodeControl() { TabContainer.Masking = false; - TabContainer.Spacing = new Vector2(15, 0); + TabContainer.Spacing = new Vector2(10, 0); AutoSizeAxes = Axes.Both; } @@ -54,7 +55,20 @@ namespace osu.Game.Overlays.Profile.Header.Components private void load(RulesetStore rulesets) { foreach (var r in rulesets.AvailableRulesets) - AddItem(r.Name); + AddItem(r.ShortName); + //AddItem(r.Name); + } + + public void SetDefaultGamemode(string gamemode) + { + foreach (GamemodeTabItem i in TabContainer) + { + if (i.Value == gamemode) + { + i.IsDefault = true; + return; + } + } } protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer @@ -66,6 +80,7 @@ namespace osu.Game.Overlays.Profile.Header.Components private class GamemodeTabItem : TabItem { private readonly OsuSpriteText text; + private readonly SpriteIcon icon; private Color4 accentColour; @@ -83,6 +98,22 @@ namespace osu.Game.Overlays.Profile.Header.Components } } + private bool isDefault; + + public bool IsDefault + { + get => isDefault; + set + { + if (isDefault == value) + return; + + isDefault = value; + + icon.FadeTo(isDefault ? 1 : 0, 100, Easing.OutQuint); + } + } + public GamemodeTabItem(string value) : base(value) { @@ -90,13 +121,32 @@ namespace osu.Game.Overlays.Profile.Header.Components Children = new Drawable[] { - text = new OsuSpriteText + new FillFlowContainer { - Margin = new MarginPadding { Bottom = 10 }, + AutoSizeAxes = Axes.Both, Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, - Text = value, - Font = OsuFont.GetFont() + Direction = FillDirection.Horizontal, + Spacing = new Vector2(3, 0), + Children = new Drawable[] + { + text = new OsuSpriteText + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Text = value, + Font = OsuFont.GetFont() + }, + icon = new SpriteIcon + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Alpha = 0, + AlwaysPresent = true, + Icon = FontAwesome.Solid.Star, + Size = new Vector2(12), + }, + } }, new HoverClickSounds() }; @@ -127,6 +177,7 @@ namespace osu.Game.Overlays.Profile.Header.Components if (Active.Value || IsHovered) { text.FadeColour(Color4.White, 120, Easing.InQuad); + icon.FadeColour(Color4.White, 120, Easing.InQuad); if (Active.Value) text.Font = text.Font.With(weight: FontWeight.Bold); @@ -134,6 +185,7 @@ namespace osu.Game.Overlays.Profile.Header.Components else { text.FadeColour(AccentColour, 120, Easing.InQuad); + icon.FadeColour(AccentColour, 120, Easing.InQuad); text.Font = text.Font.With(weight: FontWeight.Medium); } } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 46751eea25..23a31614a7 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -37,6 +37,7 @@ namespace osu.Game.Overlays.Profile Add(gamemodeControl = new GamemodeControl { + Alpha = 0, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Y = 100, @@ -105,7 +106,16 @@ namespace osu.Game.Overlays.Profile protected override ScreenTitle CreateTitle() => new ProfileHeaderTitle(); - private void updateDisplay(User user) => coverContainer.User = user; + private void updateDisplay(User user) + { + coverContainer.User = user; + + string playMode = user.PlayMode; + + gamemodeControl.Current.Value = playMode; + gamemodeControl.SetDefaultGamemode(playMode); + gamemodeControl.FadeInFromZero(100, Easing.OutQuint); + } private class ProfileHeaderTitle : ScreenTitle { From 367fdcf51987368bf3c7a79988f50af4f4cac599 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 18:07:52 +0300 Subject: [PATCH 1039/5608] Make GamemodeControl depend on rulesets --- .../Header/Components/GamemodeControl.cs | 24 ++++++++++--------- osu.Game/Overlays/Profile/ProfileHeader.cs | 1 - 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs index f66023c958..d0caeea62e 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs @@ -16,11 +16,11 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { - public class GamemodeControl : TabControl + public class GamemodeControl : TabControl { - protected override Dropdown CreateDropdown() => null; + protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(string value) => new GamemodeTabItem(value) + protected override TabItem CreateTabItem(RulesetInfo value) => new GamemodeTabItem(value) { AccentColour = AccentColour }; @@ -37,9 +37,9 @@ namespace osu.Game.Overlays.Profile.Header.Components accentColour = value; - foreach (TabItem tabItem in TabContainer) + foreach (GamemodeTabItem tabItem in TabContainer) { - ((GamemodeTabItem)tabItem).AccentColour = value; + tabItem.AccentColour = value; } } } @@ -55,17 +55,19 @@ namespace osu.Game.Overlays.Profile.Header.Components private void load(RulesetStore rulesets) { foreach (var r in rulesets.AvailableRulesets) - AddItem(r.ShortName); - //AddItem(r.Name); + { + AddItem(r); + } } public void SetDefaultGamemode(string gamemode) { foreach (GamemodeTabItem i in TabContainer) { - if (i.Value == gamemode) + if (i.Value.ShortName == gamemode) { i.IsDefault = true; + Current.Value = i.Value; return; } } @@ -77,7 +79,7 @@ namespace osu.Game.Overlays.Profile.Header.Components AutoSizeAxes = Axes.Both, }; - private class GamemodeTabItem : TabItem + private class GamemodeTabItem : TabItem { private readonly OsuSpriteText text; private readonly SpriteIcon icon; @@ -114,7 +116,7 @@ namespace osu.Game.Overlays.Profile.Header.Components } } - public GamemodeTabItem(string value) + public GamemodeTabItem(RulesetInfo value) : base(value) { AutoSizeAxes = Axes.Both; @@ -134,7 +136,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { Origin = Anchor.Centre, Anchor = Anchor.Centre, - Text = value, + Text = value.Name, Font = OsuFont.GetFont() }, icon = new SpriteIcon diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 23a31614a7..85541cd0ae 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -112,7 +112,6 @@ namespace osu.Game.Overlays.Profile string playMode = user.PlayMode; - gamemodeControl.Current.Value = playMode; gamemodeControl.SetDefaultGamemode(playMode); gamemodeControl.FadeInFromZero(100, Easing.OutQuint); } From d0d846469a6dcc4fec55767b5252c4eaef1b11f3 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 18:14:03 +0300 Subject: [PATCH 1040/5608] Move GamemodeTabItem to a distinct class --- .../Header/Components/GamemodeControl.cs | 119 ---------------- .../Header/Components/GamemodeTabItem.cs | 131 ++++++++++++++++++ 2 files changed, 131 insertions(+), 119 deletions(-) create mode 100644 osu.Game/Overlays/Profile/Header/Components/GamemodeTabItem.cs diff --git a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs index d0caeea62e..bca4cd0cfa 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs @@ -4,12 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Events; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; @@ -78,119 +73,5 @@ namespace osu.Game.Overlays.Profile.Header.Components Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, }; - - private class GamemodeTabItem : TabItem - { - private readonly OsuSpriteText text; - private readonly SpriteIcon icon; - - private Color4 accentColour; - - public Color4 AccentColour - { - get => accentColour; - set - { - if (accentColour == value) - return; - - accentColour = value; - - updateState(); - } - } - - private bool isDefault; - - public bool IsDefault - { - get => isDefault; - set - { - if (isDefault == value) - return; - - isDefault = value; - - icon.FadeTo(isDefault ? 1 : 0, 100, Easing.OutQuint); - } - } - - public GamemodeTabItem(RulesetInfo value) - : base(value) - { - AutoSizeAxes = Axes.Both; - - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Origin = Anchor.BottomLeft, - Anchor = Anchor.BottomLeft, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(3, 0), - Children = new Drawable[] - { - text = new OsuSpriteText - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Text = value.Name, - Font = OsuFont.GetFont() - }, - icon = new SpriteIcon - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Alpha = 0, - AlwaysPresent = true, - Icon = FontAwesome.Solid.Star, - Size = new Vector2(12), - }, - } - }, - new HoverClickSounds() - }; - } - - protected override bool OnHover(HoverEvent e) - { - base.OnHover(e); - - updateState(); - - return true; - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - - updateState(); - } - - protected override void OnActivated() => updateState(); - - protected override void OnDeactivated() => updateState(); - - private void updateState() - { - if (Active.Value || IsHovered) - { - text.FadeColour(Color4.White, 120, Easing.InQuad); - icon.FadeColour(Color4.White, 120, Easing.InQuad); - - if (Active.Value) - text.Font = text.Font.With(weight: FontWeight.Bold); - } - else - { - text.FadeColour(AccentColour, 120, Easing.InQuad); - icon.FadeColour(AccentColour, 120, Easing.InQuad); - text.Font = text.Font.With(weight: FontWeight.Medium); - } - } - } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/GamemodeTabItem.cs b/osu.Game/Overlays/Profile/Header/Components/GamemodeTabItem.cs new file mode 100644 index 0000000000..b6e27da522 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/Components/GamemodeTabItem.cs @@ -0,0 +1,131 @@ +// 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.Sprites; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Profile.Header.Components +{ + public class GamemodeTabItem : TabItem + { + private readonly OsuSpriteText text; + private readonly SpriteIcon icon; + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) + return; + + accentColour = value; + + updateState(); + } + } + + private bool isDefault; + + public bool IsDefault + { + get => isDefault; + set + { + if (isDefault == value) + return; + + isDefault = value; + + icon.FadeTo(isDefault ? 1 : 0, 100, Easing.OutQuint); + } + } + + public GamemodeTabItem(RulesetInfo value) + : base(value) + { + AutoSizeAxes = Axes.Both; + + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(3, 0), + Children = new Drawable[] + { + text = new OsuSpriteText + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Text = value.Name, + Font = OsuFont.GetFont() + }, + icon = new SpriteIcon + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Alpha = 0, + AlwaysPresent = true, + Icon = FontAwesome.Solid.Star, + Size = new Vector2(12), + }, + } + }, + new HoverClickSounds() + }; + } + + protected override bool OnHover(HoverEvent e) + { + base.OnHover(e); + + updateState(); + + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + updateState(); + } + + protected override void OnActivated() => updateState(); + + protected override void OnDeactivated() => updateState(); + + private void updateState() + { + if (Active.Value || IsHovered) + { + text.FadeColour(Color4.White, 120, Easing.InQuad); + icon.FadeColour(Color4.White, 120, Easing.InQuad); + + if (Active.Value) + text.Font = text.Font.With(weight: FontWeight.Bold); + } + else + { + text.FadeColour(AccentColour, 120, Easing.InQuad); + icon.FadeColour(AccentColour, 120, Easing.InQuad); + text.Font = text.Font.With(weight: FontWeight.Medium); + } + } + } +} From 0c48aec265275d24cef316e072ec1018a7eac30f Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 18:37:31 +0300 Subject: [PATCH 1041/5608] Split SetDefaultGamemode into two functions --- .../Header/Components/GamemodeControl.cs | 11 +++- .../Header/Components/GamemodeTabItem.cs | 54 +++++++++---------- osu.Game/Overlays/Profile/ProfileHeader.cs | 1 + 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs index bca4cd0cfa..59c8ec8ecb 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs @@ -59,9 +59,16 @@ namespace osu.Game.Overlays.Profile.Header.Components { foreach (GamemodeTabItem i in TabContainer) { - if (i.Value.ShortName == gamemode) + i.IsDefault = i.Value.ShortName == gamemode; + } + } + + public void SelectDefaultGamemode() + { + foreach (GamemodeTabItem i in TabContainer) + { + if (i.IsDefault) { - i.IsDefault = true; Current.Value = i.Value; return; } diff --git a/osu.Game/Overlays/Profile/Header/Components/GamemodeTabItem.cs b/osu.Game/Overlays/Profile/Header/Components/GamemodeTabItem.cs index b6e27da522..688109ad2f 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GamemodeTabItem.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GamemodeTabItem.cs @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Profile.Header.Components isDefault = value; - icon.FadeTo(isDefault ? 1 : 0, 100, Easing.OutQuint); + icon.FadeTo(isDefault ? 1 : 0, 200, Easing.OutQuint); } } @@ -59,34 +59,34 @@ namespace osu.Game.Overlays.Profile.Header.Components Children = new Drawable[] { - new FillFlowContainer + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(3, 0), + Children = new Drawable[] { - AutoSizeAxes = Axes.Both, - Origin = Anchor.BottomLeft, - Anchor = Anchor.BottomLeft, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(3, 0), - Children = new Drawable[] + text = new OsuSpriteText { - text = new OsuSpriteText - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Text = value.Name, - Font = OsuFont.GetFont() - }, - icon = new SpriteIcon - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Alpha = 0, - AlwaysPresent = true, - Icon = FontAwesome.Solid.Star, - Size = new Vector2(12), - }, - } - }, - new HoverClickSounds() + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Text = value.Name, + Font = OsuFont.GetFont() + }, + icon = new SpriteIcon + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Alpha = 0, + AlwaysPresent = true, + Icon = FontAwesome.Solid.Star, + Size = new Vector2(12), + }, + } + }, + new HoverClickSounds() }; } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 85541cd0ae..b0c1f9a587 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -113,6 +113,7 @@ namespace osu.Game.Overlays.Profile string playMode = user.PlayMode; gamemodeControl.SetDefaultGamemode(playMode); + gamemodeControl.SelectDefaultGamemode(); gamemodeControl.FadeInFromZero(100, Easing.OutQuint); } From 8dea191998e901c60b1867bd893bcad44c76e958 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 18:37:41 +0300 Subject: [PATCH 1042/5608] Add a testcase --- .../Visual/Online/TestSceneGamemodeControl.cs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs b/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs new file mode 100644 index 0000000000..02eaef09b8 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs @@ -0,0 +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.Allocation; +using osu.Framework.Graphics; +using osu.Framework.MathUtils; +using osu.Game.Graphics; +using osu.Game.Overlays.Profile.Header.Components; +using osuTK.Graphics; +using System; +using System.Collections.Generic; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneGamemodeControl : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(GamemodeControl), + typeof(GamemodeTabItem), + }; + + private readonly GamemodeControl control; + + public TestSceneGamemodeControl() + { + Child = control = new GamemodeControl + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + + AddStep("set osu! as default", () => control.SetDefaultGamemode("osu")); + AddStep("set mania as default", () => control.SetDefaultGamemode("mania")); + AddStep("set taiko as default", () => control.SetDefaultGamemode("taiko")); + AddStep("set catch as default", () => control.SetDefaultGamemode("fruits")); + AddStep("select default gamemode", () => control.SelectDefaultGamemode()); + + AddStep("set random colour", () => control.AccentColour = new Color4(RNG.NextSingle(), RNG.NextSingle(), RNG.NextSingle(), 1)); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + control.AccentColour = colours.Seafoam; + } + } +} From 8260b61db5ecc418a937a83303b49bcdd245570c Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 19:02:09 +0300 Subject: [PATCH 1043/5608] Fix CI issues --- .../Profile/Header/Components/GamemodeControl.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs index 59c8ec8ecb..3beee674fd 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs @@ -32,9 +32,9 @@ namespace osu.Game.Overlays.Profile.Header.Components accentColour = value; - foreach (GamemodeTabItem tabItem in TabContainer) + foreach (TabItem tabItem in TabContainer) { - tabItem.AccentColour = value; + ((GamemodeTabItem)tabItem).AccentColour = value; } } } @@ -57,19 +57,19 @@ namespace osu.Game.Overlays.Profile.Header.Components public void SetDefaultGamemode(string gamemode) { - foreach (GamemodeTabItem i in TabContainer) + foreach (TabItem tabItem in TabContainer) { - i.IsDefault = i.Value.ShortName == gamemode; + ((GamemodeTabItem)tabItem).IsDefault = ((GamemodeTabItem)tabItem).Value.ShortName == gamemode; } } public void SelectDefaultGamemode() { - foreach (GamemodeTabItem i in TabContainer) + foreach (TabItem tabItem in TabContainer) { - if (i.IsDefault) + if (((GamemodeTabItem)tabItem).IsDefault) { - Current.Value = i.Value; + Current.Value = ((GamemodeTabItem)tabItem).Value; return; } } From e9403bf2f7a59987bfccc8a97c692d1519f19e21 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 19:33:55 +0300 Subject: [PATCH 1044/5608] Move GamemodeControl to UserProfileOverlay --- .../Visual/Online/TestSceneGamemodeControl.cs | 8 ------- .../Header/Components/GamemodeControl.cs | 5 +++- osu.Game/Overlays/Profile/ProfileHeader.cs | 24 ++----------------- osu.Game/Overlays/UserProfileOverlay.cs | 20 ++++++++++++++-- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs b/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs index 02eaef09b8..7e3ddbfd3d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs @@ -1,10 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.MathUtils; -using osu.Game.Graphics; using osu.Game.Overlays.Profile.Header.Components; using osuTK.Graphics; using System; @@ -38,11 +36,5 @@ namespace osu.Game.Tests.Visual.Online AddStep("set random colour", () => control.AccentColour = new Color4(RNG.NextSingle(), RNG.NextSingle(), RNG.NextSingle(), 1)); } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - control.AccentColour = colours.Seafoam; - } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs index 3beee674fd..56f84741f3 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; @@ -47,12 +48,14 @@ namespace osu.Game.Overlays.Profile.Header.Components } [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) + private void load(RulesetStore rulesets, OsuColour colours) { foreach (var r in rulesets.AvailableRulesets) { AddItem(r); } + + AccentColour = colours.Seafoam; } public void SetDefaultGamemode(string gamemode) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index b0c1f9a587..76613c156d 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Profile.Header; -using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Users; namespace osu.Game.Overlays.Profile @@ -19,7 +18,6 @@ namespace osu.Game.Overlays.Profile public class ProfileHeader : OverlayHeader { private UserCoverBackground coverContainer; - private readonly GamemodeControl gamemodeControl; public Bindable User = new Bindable(); @@ -34,21 +32,12 @@ namespace osu.Game.Overlays.Profile TabControl.AddItem("Modding"); centreHeaderContainer.DetailsVisible.BindValueChanged(visible => detailHeaderContainer.Expanded = visible.NewValue, true); - - Add(gamemodeControl = new GamemodeControl - { - Alpha = 0, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Y = 100, - Margin = new MarginPadding { Right = 30 }, - }); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - TabControl.AccentColour = gamemodeControl.AccentColour = colours.Seafoam; + TabControl.AccentColour = colours.Seafoam; } protected override Drawable CreateBackground() => @@ -106,16 +95,7 @@ namespace osu.Game.Overlays.Profile protected override ScreenTitle CreateTitle() => new ProfileHeaderTitle(); - private void updateDisplay(User user) - { - coverContainer.User = user; - - string playMode = user.PlayMode; - - gamemodeControl.SetDefaultGamemode(playMode); - gamemodeControl.SelectDefaultGamemode(); - gamemodeControl.FadeInFromZero(100, Easing.OutQuint); - } + private void updateDisplay(User user) => coverContainer.User = user; private class ProfileHeaderTitle : ScreenTitle { diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 8a133a1d1e..f61ca0affc 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -11,6 +11,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Profile; +using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Overlays.Profile.Sections; using osu.Game.Users; using osuTK; @@ -25,6 +26,7 @@ namespace osu.Game.Overlays protected ProfileHeader Header; private SectionsContainer sectionsContainer; private ProfileTabControl tabs; + private GamemodeControl gamemodeControl; public const float CONTENT_X_MARGIN = 70; @@ -32,7 +34,8 @@ namespace osu.Game.Overlays public void ShowUser(User user, bool fetchOnline = true) { - if (user == User.SYSTEM_USER) return; + if (user == User.SYSTEM_USER) + return; Show(); @@ -77,7 +80,7 @@ namespace osu.Game.Overlays { Colour = OsuColour.Gray(34), RelativeSizeAxes = Axes.Both - } + }, }); sectionsContainer.SelectedSection.ValueChanged += section => { @@ -118,6 +121,15 @@ namespace osu.Game.Overlays } sectionsContainer.ScrollToTop(); + + Header.Add(gamemodeControl = new GamemodeControl + { + Alpha = 0, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Y = 100, + Margin = new MarginPadding { Right = 30 }, + }); } private void userLoadComplete(User user) @@ -139,6 +151,10 @@ namespace osu.Game.Overlays } } } + + gamemodeControl.SetDefaultGamemode(user.PlayMode); + gamemodeControl.SelectDefaultGamemode(); + gamemodeControl.FadeInFromZero(100, Easing.OutQuint); } private class ProfileTabControl : PageTabControl From 54800aa4dfb932bb751366f967251f5b07423a30 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 19:45:46 +0300 Subject: [PATCH 1045/5608] make the variable local --- osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs b/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs index 7e3ddbfd3d..a2a75566d5 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs @@ -18,10 +18,10 @@ namespace osu.Game.Tests.Visual.Online typeof(GamemodeTabItem), }; - private readonly GamemodeControl control; - public TestSceneGamemodeControl() { + GamemodeControl control; + Child = control = new GamemodeControl { Anchor = Anchor.Centre, @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("set mania as default", () => control.SetDefaultGamemode("mania")); AddStep("set taiko as default", () => control.SetDefaultGamemode("taiko")); AddStep("set catch as default", () => control.SetDefaultGamemode("fruits")); - AddStep("select default gamemode", () => control.SelectDefaultGamemode()); + AddStep("select default gamemode", control.SelectDefaultGamemode); AddStep("set random colour", () => control.AccentColour = new Color4(RNG.NextSingle(), RNG.NextSingle(), RNG.NextSingle(), 1)); } From 05aeb6697393cf6dcbd0cf14afc25c957991c24f Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 20:20:07 +0300 Subject: [PATCH 1046/5608] Fix possible crash due to null user or playmode --- osu.Game/Overlays/UserProfileOverlay.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index f61ca0affc..58d1fe4046 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -152,8 +152,9 @@ namespace osu.Game.Overlays } } - gamemodeControl.SetDefaultGamemode(user.PlayMode); + gamemodeControl.SetDefaultGamemode(user?.PlayMode ?? "osu"); gamemodeControl.SelectDefaultGamemode(); + gamemodeControl.FadeInFromZero(100, Easing.OutQuint); } From e20a8992655f86b57ed442fda10c011435773482 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Tue, 4 Jun 2019 21:46:43 +0300 Subject: [PATCH 1047/5608] remove excessive null check --- osu.Game/Overlays/UserProfileOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 58d1fe4046..1d8775ad04 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -152,7 +152,7 @@ namespace osu.Game.Overlays } } - gamemodeControl.SetDefaultGamemode(user?.PlayMode ?? "osu"); + gamemodeControl.SetDefaultGamemode(user.PlayMode ?? "osu"); gamemodeControl.SelectDefaultGamemode(); gamemodeControl.FadeInFromZero(100, Easing.OutQuint); From 5f4d7437bcdafc03434d62446683b5d1692940ae Mon Sep 17 00:00:00 2001 From: Arphox Date: Tue, 4 Jun 2019 21:30:49 +0200 Subject: [PATCH 1048/5608] Fix the issue When Enabled's value has been changed to true, it will now check if it is currently howered, and if yes, it will fade in correctly. --- osu.Game/Graphics/Containers/OsuHoverContainer.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index eb2d926424..d7dcd5b699 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -24,6 +24,9 @@ namespace osu.Game.Graphics.Containers { Enabled.ValueChanged += e => { + if (e.NewValue && isHovered) + fadeIn(); + if (!e.NewValue) unhover(); }; @@ -33,11 +36,12 @@ namespace osu.Game.Graphics.Containers protected override bool OnHover(HoverEvent e) { + isHovered = true; + if (!Enabled.Value) return false; - EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); - isHovered = true; + fadeIn(); return base.OnHover(e); } @@ -69,5 +73,10 @@ namespace osu.Game.Graphics.Containers base.LoadComplete(); EffectTargets.ForEach(d => d.FadeColour(IdleColour)); } + + private void fadeIn() + { + EffectTargets.ForEach(d => d.FadeColour(Color4.Black, FADE_DURATION * 10, Easing.OutQuint)); + } } } From 900cd5c4847c91a3bf0b1e20612505db343755d5 Mon Sep 17 00:00:00 2001 From: Arphox Date: Tue, 4 Jun 2019 21:37:10 +0200 Subject: [PATCH 1049/5608] Restore original values in FadeColour method call --- osu.Game/Graphics/Containers/OsuHoverContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index d7dcd5b699..0e4a5ae5c0 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -76,7 +76,7 @@ namespace osu.Game.Graphics.Containers private void fadeIn() { - EffectTargets.ForEach(d => d.FadeColour(Color4.Black, FADE_DURATION * 10, Easing.OutQuint)); + EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); } } } From a6dc5606bc588a52e03b13e9e62916617d95ecc2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Jun 2019 18:17:43 +0900 Subject: [PATCH 1050/5608] Allow beatmapsets to be sorted by date added --- osu.Game/Beatmaps/BeatmapManager.cs | 1 + osu.Game/Beatmaps/BeatmapSetInfo.cs | 3 + ...AddDateAddedColumnToBeatmapSet.Designer.cs | 489 ++++++++++++++++++ ...05091246_AddDateAddedColumnToBeatmapSet.cs | 24 + .../Migrations/OsuDbContextModelSnapshot.cs | 2 + .../Select/Carousel/CarouselBeatmapSet.cs | 3 + 6 files changed, 522 insertions(+) create mode 100644 osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs create mode 100644 osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.cs diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 0200dd44ac..b6fe7f88fa 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -342,6 +342,7 @@ namespace osu.Game.Beatmaps OnlineBeatmapSetID = beatmap.BeatmapInfo.BeatmapSet?.OnlineBeatmapSetID, Beatmaps = new List(), Metadata = beatmap.Metadata, + DateAdded = DateTimeOffset.UtcNow }; } diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index e111f77ba1..390236e053 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; @@ -20,6 +21,8 @@ namespace osu.Game.Beatmaps set => onlineBeatmapSetID = value > 0 ? value : null; } + public DateTimeOffset DateAdded { get; set; } + public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None; public BeatmapMetadata Metadata { get; set; } diff --git a/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs b/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs new file mode 100644 index 0000000000..9477369aa0 --- /dev/null +++ b/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs @@ -0,0 +1,489 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using osu.Game.Database; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20190605091246_AddDateAddedColumnToBeatmapSet")] + partial class AddDateAddedColumnToBeatmapSet + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.4-servicing-10062"); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("ApproachRate"); + + b.Property("CircleSize"); + + b.Property("DrainRate"); + + b.Property("OverallDifficulty"); + + b.Property("SliderMultiplier"); + + b.Property("SliderTickRate"); + + b.HasKey("ID"); + + b.ToTable("BeatmapDifficulty"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("AudioLeadIn"); + + b.Property("BaseDifficultyID"); + + b.Property("BeatDivisor"); + + b.Property("BeatmapSetInfoID"); + + b.Property("Countdown"); + + b.Property("DistanceSpacing"); + + b.Property("GridSize"); + + b.Property("Hash"); + + b.Property("Hidden"); + + b.Property("LetterboxInBreaks"); + + b.Property("MD5Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapID"); + + b.Property("Path"); + + b.Property("RulesetID"); + + b.Property("SpecialStyle"); + + b.Property("StackLeniency"); + + b.Property("StarDifficulty"); + + b.Property("Status"); + + b.Property("StoredBookmarks"); + + b.Property("TimelineZoom"); + + b.Property("Version"); + + b.Property("WidescreenStoryboard"); + + b.HasKey("ID"); + + b.HasIndex("BaseDifficultyID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("Hash"); + + b.HasIndex("MD5Hash"); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("BeatmapInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Artist"); + + b.Property("ArtistUnicode"); + + b.Property("AudioFile"); + + b.Property("AuthorString") + .HasColumnName("Author"); + + b.Property("BackgroundFile"); + + b.Property("PreviewTime"); + + b.Property("Source"); + + b.Property("Tags"); + + b.Property("Title"); + + b.Property("TitleUnicode"); + + b.HasKey("ID"); + + b.ToTable("BeatmapMetadata"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("BeatmapSetInfoID"); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.HasKey("ID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("FileInfoID"); + + b.ToTable("BeatmapSetFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("DateAdded"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapSetID"); + + b.Property("Protected"); + + b.Property("Status"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapSetID") + .IsUnique(); + + b.ToTable("BeatmapSetInfo"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Key") + .HasColumnName("Key"); + + b.Property("RulesetID"); + + b.Property("StringValue") + .HasColumnName("Value"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("osu.Game.IO.FileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Hash"); + + b.Property("ReferenceCount"); + + b.HasKey("ID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("ReferenceCount"); + + b.ToTable("FileInfo"); + }); + + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntAction") + .HasColumnName("Action"); + + b.Property("KeysString") + .HasColumnName("Keys"); + + b.Property("RulesetID"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("IntAction"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("KeyBinding"); + }); + + modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Available"); + + b.Property("InstantiationInfo"); + + b.Property("Name"); + + b.Property("ShortName"); + + b.HasKey("ID"); + + b.HasIndex("Available"); + + b.HasIndex("ShortName") + .IsUnique(); + + b.ToTable("RulesetInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("ScoreInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("ScoreInfoID"); + + b.ToTable("ScoreFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Accuracy") + .HasColumnType("DECIMAL(1,4)"); + + b.Property("BeatmapInfoID"); + + b.Property("Combo"); + + b.Property("Date"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MaxCombo"); + + b.Property("ModsJson") + .HasColumnName("Mods"); + + b.Property("OnlineScoreID"); + + b.Property("PP"); + + b.Property("Rank"); + + b.Property("RulesetID"); + + b.Property("StatisticsJson") + .HasColumnName("Statistics"); + + b.Property("TotalScore"); + + b.Property("UserID") + .HasColumnName("UserID"); + + b.Property("UserString") + .HasColumnName("User"); + + b.HasKey("ID"); + + b.HasIndex("BeatmapInfoID"); + + b.HasIndex("OnlineScoreID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("ScoreInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("SkinInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("SkinInfoID"); + + b.ToTable("SkinFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Creator"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("Name"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.ToTable("SkinInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") + .WithMany() + .HasForeignKey("BaseDifficultyID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") + .WithMany("Beatmaps") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("Beatmaps") + .HasForeignKey("MetadataID"); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") + .WithMany("Files") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("BeatmapSets") + .HasForeignKey("MetadataID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Scoring.ScoreInfo") + .WithMany("Files") + .HasForeignKey("ScoreInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap") + .WithMany("Scores") + .HasForeignKey("BeatmapInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Files") + .HasForeignKey("SkinInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.cs b/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.cs new file mode 100644 index 0000000000..55dc18b6a3 --- /dev/null +++ b/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.cs @@ -0,0 +1,24 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace osu.Game.Migrations +{ + public partial class AddDateAddedColumnToBeatmapSet : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "DateAdded", + table: "BeatmapSetInfo", + nullable: false, + defaultValue: new DateTimeOffset(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0))); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "DateAdded", + table: "BeatmapSetInfo"); + } + } +} diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index f942d357e8..a94b6df33a 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -166,6 +166,8 @@ namespace osu.Game.Migrations b.Property("ID") .ValueGeneratedOnAdd(); + b.Property("DateAdded"); + b.Property("DeletePending"); b.Property("Hash"); diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 5c334b126c..f1951e27ab 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -45,6 +45,9 @@ namespace osu.Game.Screens.Select.Carousel case SortMode.Author: return string.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username, StringComparison.InvariantCultureIgnoreCase); + case SortMode.DateAdded: + return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded); + case SortMode.Difficulty: return BeatmapSet.MaxStarDifficulty.CompareTo(otherSet.BeatmapSet.MaxStarDifficulty); } From da20be9a4be511ffaf1a194d4bcb7ce72eb888d7 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 5 Jun 2019 16:59:08 +0200 Subject: [PATCH 1051/5608] Fetch IAPIProvider via Resolved attribute --- osu.Game/Screens/OsuScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 1402aa1cce..c08d66ce10 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -114,7 +114,8 @@ namespace osu.Game.Screens [Resolved(canBeNull: true)] private OsuLogo logo { get; set; } - private IAPIProvider api; + [Resolved(canBeNull: true)] + private IAPIProvider api { get; set; } protected OsuScreen() { @@ -128,7 +129,6 @@ namespace osu.Game.Screens private void load(OsuGame osu, AudioManager audio, IAPIProvider provider) { sampleExit = audio.Sample.Get(@"UI/screen-back"); - api = provider; } public virtual bool OnPressed(GlobalAction action) From c04c6693c271020409596b796c5c00e8f8a6c3ed Mon Sep 17 00:00:00 2001 From: Welsar55 Date: Wed, 5 Jun 2019 13:01:21 -0500 Subject: [PATCH 1052/5608] Change close action from PopOut to Hide and switched to TriangleButton.Click() --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index c304dc2eb3..a7ba87e72a 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -198,9 +198,9 @@ namespace osu.Game.Overlays.Mods protected override bool OnKeyDown(KeyDownEvent e) { if (e.Key == Key.Number1) - DeselectAll(); + DeselectAllButton.Click(); else if (e.Key == Key.Number2) - PopOut(); + CloseButton.Click(); return base.OnKeyDown(e); } @@ -381,7 +381,7 @@ namespace osu.Game.Overlays.Mods { Width = 180, Text = "2. Close", - Action = PopOut, + Action = Hide, Margin = new MarginPadding { Right = 20 From 02283380c4b6ee648a741d695a35fa4cc5d6acf4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Jun 2019 13:33:30 +0900 Subject: [PATCH 1053/5608] Use manual migration --- .../Migrations/20190525060824_SkinSettings.cs | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/osu.Game/Migrations/20190525060824_SkinSettings.cs b/osu.Game/Migrations/20190525060824_SkinSettings.cs index 8bd429ca5c..99237419b7 100644 --- a/osu.Game/Migrations/20190525060824_SkinSettings.cs +++ b/osu.Game/Migrations/20190525060824_SkinSettings.cs @@ -6,25 +6,34 @@ namespace osu.Game.Migrations { protected override void Up(MigrationBuilder migrationBuilder) { - migrationBuilder.AddColumn( - name: "SkinInfoID", - table: "Settings", - nullable: true); + migrationBuilder.Sql(@"create table Settings_dg_tmp + ( + ID INTEGER not null + constraint PK_Settings + primary key autoincrement, + Key TEXT not null, + RulesetID INTEGER, + Value TEXT, + Variant INTEGER, + SkinInfoID int + constraint Settings_SkinInfo_ID_fk + references SkinInfo + on delete restrict + ); - migrationBuilder.CreateIndex( - name: "IX_Settings_SkinInfoID", - table: "Settings", - column: "SkinInfoID"); + insert into Settings_dg_tmp(ID, Key, RulesetID, Value, Variant) select ID, Key, RulesetID, Value, Variant from Settings; - // unsupported by sqlite + drop table Settings; - // migrationBuilder.AddForeignKey( - // name: "FK_Settings_SkinInfo_SkinInfoID", - // table: "Settings", - // column: "SkinInfoID", - // principalTable: "SkinInfo", - // principalColumn: "ID", - // onDelete: ReferentialAction.Restrict); + alter table Settings_dg_tmp rename to Settings; + + create index IX_Settings_RulesetID_Variant + on Settings (RulesetID, Variant); + + create index Settings_SkinInfoID_index + on Settings (SkinInfoID); + + "); } protected override void Down(MigrationBuilder migrationBuilder) From ae438213a52d2a51586e7cd16e131cffa46bd052 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Jun 2019 16:32:43 +0900 Subject: [PATCH 1054/5608] Remove secondary buffered container from slider body --- .../Objects/Drawables/Pieces/SliderBody.cs | 28 ++----------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 25e1aebd18..33b3667c4f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -2,13 +2,10 @@ // 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.Framework.Graphics.Lines; -using osu.Framework.Graphics.Primitives; using osuTK; using osuTK.Graphics; -using osuTK.Graphics.ES30; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { @@ -19,8 +16,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private readonly SliderPath path; protected Path Path => path; - private readonly BufferedContainer container; - public float PathRadius { get => path.PathRadius; @@ -44,8 +39,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces return; path.AccentColour = value; - - container.ForceRedraw(); } } @@ -61,8 +54,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces return; path.BorderColour = value; - - container.ForceRedraw(); } } @@ -78,23 +69,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces return; path.BorderSize = value; - - container.ForceRedraw(); } } - public Quad PathDrawQuad => container.ScreenSpaceDrawQuad; - protected SliderBody() { - InternalChild = container = new BufferedContainer - { - RelativeSizeAxes = Axes.Both, - CacheDrawnFrameBuffer = true, - Child = path = new SliderPath { Blending = BlendingMode.None } - }; - - container.Attach(RenderbufferInternalFormat.DepthComponent16); + InternalChild = path = new SliderPath(); } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => path.ReceivePositionalInputAt(screenSpacePos); @@ -103,11 +83,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces /// Sets the vertices of the path which should be drawn by this . /// /// The vertices - protected void SetVertices(IReadOnlyList vertices) - { - path.Vertices = vertices; - container.ForceRedraw(); - } + protected void SetVertices(IReadOnlyList vertices) => path.Vertices = vertices; private class SliderPath : SmoothPath { From c7d0fcd42ad4b171b0f7b5e1c273fb1bcc08607a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Jun 2019 16:33:14 +0900 Subject: [PATCH 1055/5608] Update drawnodes --- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 3 ++- osu.Game/Graphics/Backgrounds/Triangles.cs | 4 ++-- osu.Game/Rulesets/Mods/ModFlashlight.cs | 2 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 1b8fa0de01..1bc22da8ac 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -210,7 +210,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor Vector2 pos = parts[i].Position; float localTime = parts[i].Time; - texture.DrawQuad( + DrawQuad( + texture, new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y), DrawColourInfo.Colour, null, diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index e2c7693700..29113e0e2f 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -214,7 +214,6 @@ namespace osu.Game.Graphics.Backgrounds base.Draw(vertexAction); shader.Bind(); - texture.TextureGL.Bind(); Vector2 localInflationAmount = edge_smoothness * DrawInfo.MatrixInverse.ExtractScale().Xy; @@ -231,7 +230,8 @@ namespace osu.Game.Graphics.Backgrounds ColourInfo colourInfo = DrawColourInfo.Colour; colourInfo.ApplyChild(particle.Colour); - texture.DrawTriangle( + DrawTriangle( + texture, triangle, colourInfo, null, diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index e174a25df3..405d21c711 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -179,7 +179,7 @@ namespace osu.Game.Rulesets.Mods shader.GetUniform("flashlightSize").UpdateValue(ref flashlightSize); shader.GetUniform("flashlightDim").UpdateValue(ref flashlightDim); - Texture.WhitePixel.DrawQuad(screenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction); + DrawQuad(Texture.WhitePixel, screenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction); shader.Unbind(); } diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 2925689d20..c6de5857c2 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -189,7 +189,6 @@ namespace osu.Game.Screens.Menu base.Draw(vertexAction); shader.Bind(); - texture.TextureGL.Bind(); Vector2 inflation = DrawInfo.MatrixInverse.ExtractScale().Xy; @@ -224,7 +223,8 @@ namespace osu.Game.Screens.Menu Vector2Extensions.Transform(barPosition + bottomOffset + amplitudeOffset, DrawInfo.Matrix) ); - texture.DrawQuad( + DrawQuad( + texture, rectangle, colourInfo, null, From 4d035afcc6f93d808c28f4ebec36b26be2f1aee5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Jun 2019 16:49:42 +0900 Subject: [PATCH 1056/5608] Add setting to bypass front-to-back --- osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs index b671d0e0fd..f063898a9f 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs @@ -31,6 +31,11 @@ namespace osu.Game.Overlays.Settings.Sections.Debug LabelText = "Bypass caching (slow)", Bindable = config.GetBindable(DebugSetting.BypassCaching) }, + new SettingsCheckbox + { + LabelText = "Bypass front-to-back render pass", + Bindable = config.GetBindable(DebugSetting.BypassFrontToBackPass) + } }; } } From ac9a3e54a60bf1e97977fb9a9fad2f6c4e5be28b Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 6 Jun 2019 18:07:19 +0900 Subject: [PATCH 1057/5608] Fix cursor issue with stopped gameplay clock --- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 1b8fa0de01..341975c167 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -54,7 +54,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor for (int i = 0; i < max_sprites; i++) { - parts[i].InvalidationID = 0; + // InvalidationID 1 forces an update of each part of the cursor trail the first time ApplyState is ran on the draw node + parts[i].InvalidationID = 1; parts[i].WasUpdated = true; } } From 2a90af1d4e785e2d5cdf37c93243ed027257dbcf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Jun 2019 19:15:51 +0900 Subject: [PATCH 1058/5608] Update readme with direct download links --- README.md | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index abddb1faa1..91ea34e999 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ This project is still heavily under development, but is in a state where users a 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. +Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh/home/changelog). + ## Requirements - A desktop platform with the [.NET Core SDK 2.2](https://www.microsoft.com/net/learn/get-started) or higher installed. @@ -20,17 +22,24 @@ We are accepting bug reports (please report with as much detail as possible). Fe ### Releases -If you are not interested in developing the game, please head over to the [releases](https://github.com/ppy/osu/releases) to download a precompiled build with automatic updating enabled. +![](https://puu.sh/DCmvA/f6a74f5fbb.png) -- Windows (x64) users should download and run `install.exe`. -- macOS users (10.12 "Sierra" and higher) should download and run `osu.app.zip`. -- iOS users can join the [TestFlight beta program](https://t.co/xQJmHkfC18). +If you are not interested in developing the game, you can consume our [binary releases](https://github.com/ppy/osu/releases). + +**Latest build:*** + +| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) | +| ------------- | ------------- | + +- **Linux** users are recommended to self-compile until we have official deployment in place. +- **iOS** users can join the [TestFlight beta program](https://t.co/xQJmHkfC18) (note that due to high demand this is reulgarly full). +- **Android** users can self-compile, and expect a public beta soon. If your platform is not listed above, there is still a chance you can manually build it by following the instructions below. ### Downloading the source code -Clone the repository **including submodules**: +Clone the repository: ```shell git clone https://github.com/ppy/osu @@ -45,7 +54,7 @@ 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. +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). > Visual Studio Code users must run the `Restore` task before any build attempt. From 6bf6e221491f95b1bb0b44e87cb22e0530ff948f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Jun 2019 20:33:03 +0900 Subject: [PATCH 1059/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f84bb64fbf..55fa20188c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + From 8c1a62536cb15a559befbff2383259b687b39454 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Jun 2019 21:13:01 +0900 Subject: [PATCH 1060/5608] Update framework --- osu.iOS.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.iOS.props b/osu.iOS.props index fc047aa5f0..68f21df8ba 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 923f9fb6cdb1b2480420c43448ff048596023ffe Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Fri, 7 Jun 2019 01:43:26 +0300 Subject: [PATCH 1061/5608] Naming adjustments --- .../Visual/Online/TestSceneGamemodeControl.cs | 40 ------------------- .../Online/TestSceneProfileRulesetSelector.cs | 40 +++++++++++++++++++ ...deControl.cs => ProfileRulesetSelector.cs} | 14 +++---- .../{GamemodeTabItem.cs => RulesetTabItem.cs} | 4 +- osu.Game/Overlays/UserProfileOverlay.cs | 10 ++--- 5 files changed, 54 insertions(+), 54 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs create mode 100644 osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs rename osu.Game/Overlays/Profile/Header/Components/{GamemodeControl.cs => ProfileRulesetSelector.cs} (82%) rename osu.Game/Overlays/Profile/Header/Components/{GamemodeTabItem.cs => RulesetTabItem.cs} (97%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs b/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs deleted file mode 100644 index a2a75566d5..0000000000 --- a/osu.Game.Tests/Visual/Online/TestSceneGamemodeControl.cs +++ /dev/null @@ -1,40 +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.MathUtils; -using osu.Game.Overlays.Profile.Header.Components; -using osuTK.Graphics; -using System; -using System.Collections.Generic; - -namespace osu.Game.Tests.Visual.Online -{ - public class TestSceneGamemodeControl : OsuTestScene - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(GamemodeControl), - typeof(GamemodeTabItem), - }; - - public TestSceneGamemodeControl() - { - GamemodeControl control; - - Child = control = new GamemodeControl - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }; - - AddStep("set osu! as default", () => control.SetDefaultGamemode("osu")); - AddStep("set mania as default", () => control.SetDefaultGamemode("mania")); - AddStep("set taiko as default", () => control.SetDefaultGamemode("taiko")); - AddStep("set catch as default", () => control.SetDefaultGamemode("fruits")); - AddStep("select default gamemode", control.SelectDefaultGamemode); - - AddStep("set random colour", () => control.AccentColour = new Color4(RNG.NextSingle(), RNG.NextSingle(), RNG.NextSingle(), 1)); - } - } -} diff --git a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs new file mode 100644 index 0000000000..687cbbebad --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.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.Graphics; +using osu.Framework.MathUtils; +using osu.Game.Overlays.Profile.Header.Components; +using osuTK.Graphics; +using System; +using System.Collections.Generic; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneProfileRulesetSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ProfileRulesetSelector), + typeof(RulesetTabItem), + }; + + public TestSceneProfileRulesetSelector() + { + ProfileRulesetSelector selector; + + Child = selector = new ProfileRulesetSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + + AddStep("set osu! as default", () => selector.SetDefaultGamemode("osu")); + AddStep("set mania as default", () => selector.SetDefaultGamemode("mania")); + AddStep("set taiko as default", () => selector.SetDefaultGamemode("taiko")); + AddStep("set catch as default", () => selector.SetDefaultGamemode("fruits")); + AddStep("select default gamemode", selector.SelectDefaultGamemode); + + AddStep("set random colour", () => selector.AccentColour = new Color4(RNG.NextSingle(), RNG.NextSingle(), RNG.NextSingle(), 1)); + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs similarity index 82% rename from osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs rename to osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs index 56f84741f3..b189878b0d 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GamemodeControl.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs @@ -12,11 +12,11 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { - public class GamemodeControl : TabControl + public class ProfileRulesetSelector : TabControl { protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(RulesetInfo value) => new GamemodeTabItem(value) + protected override TabItem CreateTabItem(RulesetInfo value) => new RulesetTabItem(value) { AccentColour = AccentColour }; @@ -35,12 +35,12 @@ namespace osu.Game.Overlays.Profile.Header.Components foreach (TabItem tabItem in TabContainer) { - ((GamemodeTabItem)tabItem).AccentColour = value; + ((RulesetTabItem)tabItem).AccentColour = value; } } } - public GamemodeControl() + public ProfileRulesetSelector() { TabContainer.Masking = false; TabContainer.Spacing = new Vector2(10, 0); @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { foreach (TabItem tabItem in TabContainer) { - ((GamemodeTabItem)tabItem).IsDefault = ((GamemodeTabItem)tabItem).Value.ShortName == gamemode; + ((RulesetTabItem)tabItem).IsDefault = ((RulesetTabItem)tabItem).Value.ShortName == gamemode; } } @@ -70,9 +70,9 @@ namespace osu.Game.Overlays.Profile.Header.Components { foreach (TabItem tabItem in TabContainer) { - if (((GamemodeTabItem)tabItem).IsDefault) + if (((RulesetTabItem)tabItem).IsDefault) { - Current.Value = ((GamemodeTabItem)tabItem).Value; + Current.Value = ((RulesetTabItem)tabItem).Value; return; } } diff --git a/osu.Game/Overlays/Profile/Header/Components/GamemodeTabItem.cs b/osu.Game/Overlays/Profile/Header/Components/RulesetTabItem.cs similarity index 97% rename from osu.Game/Overlays/Profile/Header/Components/GamemodeTabItem.cs rename to osu.Game/Overlays/Profile/Header/Components/RulesetTabItem.cs index 688109ad2f..0a6f2f5123 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GamemodeTabItem.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RulesetTabItem.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { - public class GamemodeTabItem : TabItem + public class RulesetTabItem : TabItem { private readonly OsuSpriteText text; private readonly SpriteIcon icon; @@ -52,7 +52,7 @@ namespace osu.Game.Overlays.Profile.Header.Components } } - public GamemodeTabItem(RulesetInfo value) + public RulesetTabItem(RulesetInfo value) : base(value) { AutoSizeAxes = Axes.Both; diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 1d8775ad04..ec81193896 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays protected ProfileHeader Header; private SectionsContainer sectionsContainer; private ProfileTabControl tabs; - private GamemodeControl gamemodeControl; + private ProfileRulesetSelector rulesetSelector; public const float CONTENT_X_MARGIN = 70; @@ -122,7 +122,7 @@ namespace osu.Game.Overlays sectionsContainer.ScrollToTop(); - Header.Add(gamemodeControl = new GamemodeControl + Header.Add(rulesetSelector = new ProfileRulesetSelector { Alpha = 0, Anchor = Anchor.TopRight, @@ -152,10 +152,10 @@ namespace osu.Game.Overlays } } - gamemodeControl.SetDefaultGamemode(user.PlayMode ?? "osu"); - gamemodeControl.SelectDefaultGamemode(); + rulesetSelector.SetDefaultGamemode(user.PlayMode ?? "osu"); + rulesetSelector.SelectDefaultGamemode(); - gamemodeControl.FadeInFromZero(100, Easing.OutQuint); + rulesetSelector.FadeInFromZero(100, Easing.OutQuint); } private class ProfileTabControl : PageTabControl From 210437042fa0b7ee8613f52059c3c4c94f353706 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Fri, 7 Jun 2019 02:39:36 +0300 Subject: [PATCH 1062/5608] Remove useless update calls in ToolbarRulesetSelector --- osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 84a41b6547..90412ec1d1 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -31,6 +31,7 @@ namespace osu.Game.Overlays.Toolbar public ToolbarRulesetSelector() { RelativeSizeAxes = Axes.Y; + AutoSizeAxes = Axes.X; Children = new[] { @@ -111,12 +112,6 @@ namespace osu.Game.Overlays.Toolbar private void disabledChanged(bool isDisabled) => this.FadeColour(isDisabled ? Color4.Gray : Color4.White, 300); - protected override void Update() - { - base.Update(); - Size = new Vector2(modeButtons.DrawSize.X, 1); - } - private void rulesetChanged(ValueChangedEvent e) { foreach (ToolbarRulesetButton m in modeButtons.Children.Cast()) From e2118299e93ac4e657c1994d09a7617ca262bbe5 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 7 Jun 2019 10:36:36 +0900 Subject: [PATCH 1063/5608] update comment --- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 341975c167..888c77442f 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -54,7 +54,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor for (int i = 0; i < max_sprites; i++) { - // InvalidationID 1 forces an update of each part of the cursor trail the first time ApplyState is ran on the draw node + // InvalidationID 1 forces an update of each part of the cursor trail the first time ApplyState is run on the draw node + // This is to prevent garbage data from being sent to the vertex shader, resulting in visual issues on some platforms parts[i].InvalidationID = 1; parts[i].WasUpdated = true; } From 9f740f69bb8ab61459dc72bd7c6dce4062e78759 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 11:20:39 +0900 Subject: [PATCH 1064/5608] Fix preview tracks muting themselves Closes #4937 --- osu.Game/Audio/PreviewTrackManager.cs | 57 ++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index d479483508..6e162ca95e 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -1,6 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; @@ -12,22 +16,24 @@ using osu.Game.Beatmaps; namespace osu.Game.Audio { - /// - /// A central store for the retrieval of s. - /// public class PreviewTrackManager : Component { private readonly BindableDouble muteBindable = new BindableDouble(); private AudioManager audio; - private ITrackStore trackStore; + private PreviewTrackStore trackStore; private TrackManagerPreviewTrack current; [BackgroundDependencyLoader] private void load(AudioManager audio, FrameworkConfigManager config) { - trackStore = audio.GetTrackStore(new OnlineStore()); + // this is a temporary solution to get around muting ourselves. + // todo: update this once we have a BackgroundTrackManager or similar. + trackStore = new PreviewTrackStore(new OnlineStore()); + + audio.AddItem(trackStore); + trackStore.AddAdjustment(AdjustableProperty.Volume, audio.VolumeTrack); this.audio = audio; @@ -103,5 +109,46 @@ namespace osu.Game.Audio protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3"); } + + private class PreviewTrackStore : AudioCollectionManager, ITrackStore + { + private readonly IResourceStore store; + + internal PreviewTrackStore(IResourceStore store) + { + this.store = store; + } + + public Track GetVirtual(double length = double.PositiveInfinity) + { + if (IsDisposed) throw new ObjectDisposedException($"Cannot retrieve items for an already disposed {nameof(PreviewTrackStore)}"); + + var track = new TrackVirtual(length); + AddItem(track); + return track; + } + + public Track Get(string name) + { + if (IsDisposed) throw new ObjectDisposedException($"Cannot retrieve items for an already disposed {nameof(PreviewTrackStore)}"); + + if (string.IsNullOrEmpty(name)) return null; + + var dataStream = store.GetStream(name); + + if (dataStream == null) + return null; + + Track track = new TrackBass(dataStream); + AddItem(track); + return track; + } + + public Task GetAsync(string name) => Task.Run(() => Get(name)); + + public Stream GetStream(string name) => store.GetStream(name); + + public IEnumerable GetAvailableResources() => store.GetAvailableResources(); + } } } From 64d5aa318fd7baa6c5610e849cd9f7568ab7ae09 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 11:45:58 +0900 Subject: [PATCH 1065/5608] Apply rebased changes --- .../TestSceneOsuHoverContainer.cs | 216 ++++++++++++++++++ .../Graphics/Containers/OsuHoverContainer.cs | 30 ++- 2 files changed, 234 insertions(+), 12 deletions(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs new file mode 100644 index 0000000000..9fe1a4cd89 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs @@ -0,0 +1,216 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.UserInterface +{ + [TestFixture] + public class TestSceneOsuHoverContainer : ManualInputManagerTestScene + { + private OsuHoverTestContainer hoverContainer; + private OsuSpriteText textContainer; + private ColourInfo currentColour => textContainer.DrawColourInfo.Colour; + private ColourInfo idleColour => hoverContainer.IdleColourPublic; + private ColourInfo hoverColour => hoverContainer.HoverColourPublic; + + public TestSceneOsuHoverContainer() + { + setupUI(); + } + + [SetUp] + public void TestSceneOsuHoverContainer_SetUp() => Schedule(() => setupUI()); + + private void setupUI() + { + Child = hoverContainer = new OsuHoverTestContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Children = new[] + { + textContainer = new OsuSpriteText + { + Text = "Test", + Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 20), + }, + } + } + }; + } + + [Description("Checks IsHovered property value on a container when it is hovered/unhovered.")] + [TestCase(true, TestName = "Enabled_Check_IsHovered")] + [TestCase(false, TestName = "Disabled_Check_IsHovered")] + public void Check_IsHovered_HasProperValue(bool isEnabled) + { + moveOut(); + setContainerEnabledTo(isEnabled); + + checkNotHovered(); + + moveToText(); + checkHovered(); + + moveOut(); + checkNotHovered(); + + moveToText(); + checkHovered(); + + moveOut(); + checkNotHovered(); + + ReturnUserInput(); + } + + [Test] + [Description("Checks colour fading on an enabled container when it is hovered/unhovered.")] + public void WhenEnabled_Fades() + { + moveOut(); + enableContainer(); + + checkColour(idleColour); + + moveToText(); + waitUntilColourIs(hoverColour); + + moveOut(); + waitUntilColourIs(idleColour); + + moveToText(); + waitUntilColourIs(hoverColour); + + moveOut(); + waitUntilColourIs(idleColour); + + ReturnUserInput(); + } + + [Test] + [Description("Checks colour fading on a disabled container when it is hovered/unhovered.")] + public void WhenDisabled_DoesNotFade() + { + moveOut(); + disableContainer(); + + checkColour(idleColour); + + moveToText(); + checkColour(idleColour); + + moveOut(); + checkColour(idleColour); + + moveToText(); + checkColour(idleColour); + + moveOut(); + checkColour(idleColour); + + ReturnUserInput(); + } + + [Test] + [Description("Checks that when a disabled & hovered container gets enabled, colour fading happens")] + public void WhileHovering_WhenGetsEnabled_Fades() + { + moveOut(); + disableContainer(); + checkColour(idleColour); + + moveToText(); + checkColour(idleColour); + + enableContainer(); + waitUntilColourIs(hoverColour); + } + + [Test] + [Description("Checks that when an enabled & hovered container gets disabled, colour fading happens")] + public void WhileHovering_WhenGetsDisabled_Fades() + { + moveOut(); + enableContainer(); + checkColour(idleColour); + + moveToText(); + waitUntilColourIs(hoverColour); + + disableContainer(); + waitUntilColourIs(idleColour); + } + + [Test] + [Description("Checks that when a hovered container gets enabled and disabled multiple times, colour fading happens")] + public void WhileHovering_WhenEnabledChangesMultipleTimes_Fades() + { + moveOut(); + enableContainer(); + checkColour(idleColour); + + moveToText(); + waitUntilColourIs(hoverColour); + + disableContainer(); + waitUntilColourIs(idleColour); + + enableContainer(); + waitUntilColourIs(hoverColour); + + disableContainer(); + waitUntilColourIs(idleColour); + } + + private void enableContainer() => setContainerEnabledTo(true); + + private void disableContainer() => setContainerEnabledTo(false); + + private void setContainerEnabledTo(bool newValue) + { + string word = newValue ? "Enable" : "Disable"; + AddStep($"{word} container", () => hoverContainer.Enabled.Value = newValue); + } + + private void moveToText() => AddStep("Move mouse to text", () => InputManager.MoveMouseTo(hoverContainer)); + + private void moveOut() => AddStep("Move out", doMoveOut); + + private void checkHovered() => AddAssert("Check hovered", () => hoverContainer.IsHovered); + + private void checkNotHovered() => AddAssert("Check not hovered", () => !hoverContainer.IsHovered); + + private void checkColour(ColourInfo expectedColour) + => AddAssert($"Check colour to be '{expectedColour}'", () => currentColour.Equals(expectedColour)); + + private void waitUntilColourIs(ColourInfo expectedColour) + => AddUntilStep($"Wait until hover colour is {expectedColour}", () => currentColour.Equals(expectedColour)); + + /// + /// Moves the cursor to top left corner of the screen + /// + private void doMoveOut() + => InputManager.MoveMouseTo(new Vector2(InputManager.ScreenSpaceDrawQuad.TopLeft.X, InputManager.ScreenSpaceDrawQuad.TopLeft.Y)); + + private sealed class OsuHoverTestContainer : OsuHoverContainer + { + public Color4 HoverColourPublic => HoverColour; + public Color4 IdleColourPublic => IdleColour; + } + } +} diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index 0e4a5ae5c0..4ea28f74b9 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -24,11 +24,13 @@ namespace osu.Game.Graphics.Containers { Enabled.ValueChanged += e => { - if (e.NewValue && isHovered) - fadeIn(); - - if (!e.NewValue) - unhover(); + if (isHovered) + { + if (e.NewValue) + fadeIn(); + else + fadeOut(); + } }; } @@ -36,6 +38,9 @@ namespace osu.Game.Graphics.Containers protected override bool OnHover(HoverEvent e) { + if (isHovered) + return false; + isHovered = true; if (!Enabled.Value) @@ -47,18 +52,14 @@ namespace osu.Game.Graphics.Containers } protected override void OnHoverLost(HoverLostEvent e) - { - unhover(); - base.OnHoverLost(e); - } - - private void unhover() { if (!isHovered) return; isHovered = false; - EffectTargets.ForEach(d => d.FadeColour(IdleColour, FADE_DURATION, Easing.OutQuint)); + fadeOut(); + + base.OnHoverLost(e); } [BackgroundDependencyLoader] @@ -78,5 +79,10 @@ namespace osu.Game.Graphics.Containers { EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); } + + private void fadeOut() + { + EffectTargets.ForEach(d => d.FadeColour(IdleColour, FADE_DURATION, Easing.OutQuint)); + } } } From 694f2e3a4f9e5902d685b9d7cac0de42d5546384 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 11:59:07 +0900 Subject: [PATCH 1066/5608] Tidy up test scene's setup usage --- .../TestSceneOsuHoverContainer.cs | 77 +++++++++---------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs index 9fe1a4cd89..79aa6189af 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs @@ -20,18 +20,9 @@ namespace osu.Game.Tests.Visual.UserInterface private OsuHoverTestContainer hoverContainer; private OsuSpriteText textContainer; private ColourInfo currentColour => textContainer.DrawColourInfo.Colour; - private ColourInfo idleColour => hoverContainer.IdleColourPublic; - private ColourInfo hoverColour => hoverContainer.HoverColourPublic; - - public TestSceneOsuHoverContainer() - { - setupUI(); - } [SetUp] - public void TestSceneOsuHoverContainer_SetUp() => Schedule(() => setupUI()); - - private void setupUI() + public void SetUp() => Schedule(() => { Child = hoverContainer = new OsuHoverTestContainer { @@ -51,12 +42,12 @@ namespace osu.Game.Tests.Visual.UserInterface } } }; - } + }); [Description("Checks IsHovered property value on a container when it is hovered/unhovered.")] [TestCase(true, TestName = "Enabled_Check_IsHovered")] [TestCase(false, TestName = "Disabled_Check_IsHovered")] - public void Check_IsHovered_HasProperValue(bool isEnabled) + public void TestIsHoveredHasProperValue(bool isEnabled) { moveOut(); setContainerEnabledTo(isEnabled); @@ -80,101 +71,101 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] [Description("Checks colour fading on an enabled container when it is hovered/unhovered.")] - public void WhenEnabled_Fades() + public void TestTransitionWhileEnabled() { moveOut(); enableContainer(); - checkColour(idleColour); + checkColour(OsuHoverTestContainer.IDLE_COLOUR); moveToText(); - waitUntilColourIs(hoverColour); + waitUntilColourIs(OsuHoverTestContainer.HOVER_COLOUR); moveOut(); - waitUntilColourIs(idleColour); + waitUntilColourIs(OsuHoverTestContainer.IDLE_COLOUR); moveToText(); - waitUntilColourIs(hoverColour); + waitUntilColourIs(OsuHoverTestContainer.HOVER_COLOUR); moveOut(); - waitUntilColourIs(idleColour); + waitUntilColourIs(OsuHoverTestContainer.IDLE_COLOUR); ReturnUserInput(); } [Test] [Description("Checks colour fading on a disabled container when it is hovered/unhovered.")] - public void WhenDisabled_DoesNotFade() + public void TestNoTransitionWhileDisabled() { moveOut(); disableContainer(); - checkColour(idleColour); + checkColour(OsuHoverTestContainer.IDLE_COLOUR); moveToText(); - checkColour(idleColour); + checkColour(OsuHoverTestContainer.IDLE_COLOUR); moveOut(); - checkColour(idleColour); + checkColour(OsuHoverTestContainer.IDLE_COLOUR); moveToText(); - checkColour(idleColour); + checkColour(OsuHoverTestContainer.IDLE_COLOUR); moveOut(); - checkColour(idleColour); + checkColour(OsuHoverTestContainer.IDLE_COLOUR); ReturnUserInput(); } [Test] [Description("Checks that when a disabled & hovered container gets enabled, colour fading happens")] - public void WhileHovering_WhenGetsEnabled_Fades() + public void TestBecomesEnabledTransition() { moveOut(); disableContainer(); - checkColour(idleColour); + checkColour(OsuHoverTestContainer.IDLE_COLOUR); moveToText(); - checkColour(idleColour); + checkColour(OsuHoverTestContainer.IDLE_COLOUR); enableContainer(); - waitUntilColourIs(hoverColour); + waitUntilColourIs(OsuHoverTestContainer.HOVER_COLOUR); } [Test] [Description("Checks that when an enabled & hovered container gets disabled, colour fading happens")] - public void WhileHovering_WhenGetsDisabled_Fades() + public void TestBecomesDisabledTransition() { moveOut(); enableContainer(); - checkColour(idleColour); + checkColour(OsuHoverTestContainer.IDLE_COLOUR); moveToText(); - waitUntilColourIs(hoverColour); + waitUntilColourIs(OsuHoverTestContainer.HOVER_COLOUR); disableContainer(); - waitUntilColourIs(idleColour); + waitUntilColourIs(OsuHoverTestContainer.IDLE_COLOUR); } [Test] [Description("Checks that when a hovered container gets enabled and disabled multiple times, colour fading happens")] - public void WhileHovering_WhenEnabledChangesMultipleTimes_Fades() + public void TestDisabledChangesMultipleTimes() { moveOut(); enableContainer(); - checkColour(idleColour); + checkColour(OsuHoverTestContainer.IDLE_COLOUR); moveToText(); - waitUntilColourIs(hoverColour); + waitUntilColourIs(OsuHoverTestContainer.HOVER_COLOUR); disableContainer(); - waitUntilColourIs(idleColour); + waitUntilColourIs(OsuHoverTestContainer.IDLE_COLOUR); enableContainer(); - waitUntilColourIs(hoverColour); + waitUntilColourIs(OsuHoverTestContainer.HOVER_COLOUR); disableContainer(); - waitUntilColourIs(idleColour); + waitUntilColourIs(OsuHoverTestContainer.IDLE_COLOUR); } private void enableContainer() => setContainerEnabledTo(true); @@ -209,8 +200,14 @@ namespace osu.Game.Tests.Visual.UserInterface private sealed class OsuHoverTestContainer : OsuHoverContainer { - public Color4 HoverColourPublic => HoverColour; - public Color4 IdleColourPublic => IdleColour; + public static readonly Color4 HOVER_COLOUR = Color4.Red; + public static readonly Color4 IDLE_COLOUR = Color4.Green; + + public OsuHoverTestContainer() + { + HoverColour = HOVER_COLOUR; + IdleColour = IDLE_COLOUR; + } } } } From 58174425eda10e15e64f39f5ce4f6165ea8d4045 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 12:37:10 +0900 Subject: [PATCH 1067/5608] Make visual test more visible --- .../TestSceneOsuHoverContainer.cs | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs index 79aa6189af..6b2bca9b83 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs @@ -4,11 +4,8 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; +using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; @@ -18,8 +15,7 @@ namespace osu.Game.Tests.Visual.UserInterface public class TestSceneOsuHoverContainer : ManualInputManagerTestScene { private OsuHoverTestContainer hoverContainer; - private OsuSpriteText textContainer; - private ColourInfo currentColour => textContainer.DrawColourInfo.Colour; + private Box colourContainer; [SetUp] public void SetUp() => Schedule(() => @@ -28,19 +24,11 @@ namespace osu.Game.Tests.Visual.UserInterface { Anchor = Anchor.Centre, Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Child = new FillFlowContainer + Size = new Vector2(100), + Child = colourContainer = new Box { - AutoSizeAxes = Axes.Both, - Children = new[] - { - textContainer = new OsuSpriteText - { - Text = "Test", - Font = OsuFont.GetFont(weight: FontWeight.Medium, size: 20), - }, - } - } + RelativeSizeAxes = Axes.Both, + }, }; }); @@ -192,6 +180,8 @@ namespace osu.Game.Tests.Visual.UserInterface private void waitUntilColourIs(ColourInfo expectedColour) => AddUntilStep($"Wait until hover colour is {expectedColour}", () => currentColour.Equals(expectedColour)); + private ColourInfo currentColour => colourContainer.DrawColourInfo.Colour; + /// /// Moves the cursor to top left corner of the screen /// From 748c0e5c012e266dd4ca15f1c786de6654c3aefd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 12:42:01 +0900 Subject: [PATCH 1068/5608] Set default state of test to enabled --- .../Visual/UserInterface/TestSceneOsuHoverContainer.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs index 6b2bca9b83..3613122165 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs @@ -22,6 +22,7 @@ namespace osu.Game.Tests.Visual.UserInterface { Child = hoverContainer = new OsuHoverTestContainer { + Enabled = { Value = true }, Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(100), @@ -30,6 +31,8 @@ namespace osu.Game.Tests.Visual.UserInterface RelativeSizeAxes = Axes.Both, }, }; + + doMoveOut(); }); [Description("Checks IsHovered property value on a container when it is hovered/unhovered.")] @@ -37,7 +40,6 @@ namespace osu.Game.Tests.Visual.UserInterface [TestCase(false, TestName = "Disabled_Check_IsHovered")] public void TestIsHoveredHasProperValue(bool isEnabled) { - moveOut(); setContainerEnabledTo(isEnabled); checkNotHovered(); @@ -61,7 +63,6 @@ namespace osu.Game.Tests.Visual.UserInterface [Description("Checks colour fading on an enabled container when it is hovered/unhovered.")] public void TestTransitionWhileEnabled() { - moveOut(); enableContainer(); checkColour(OsuHoverTestContainer.IDLE_COLOUR); @@ -85,7 +86,6 @@ namespace osu.Game.Tests.Visual.UserInterface [Description("Checks colour fading on a disabled container when it is hovered/unhovered.")] public void TestNoTransitionWhileDisabled() { - moveOut(); disableContainer(); checkColour(OsuHoverTestContainer.IDLE_COLOUR); @@ -109,7 +109,6 @@ namespace osu.Game.Tests.Visual.UserInterface [Description("Checks that when a disabled & hovered container gets enabled, colour fading happens")] public void TestBecomesEnabledTransition() { - moveOut(); disableContainer(); checkColour(OsuHoverTestContainer.IDLE_COLOUR); @@ -124,7 +123,6 @@ namespace osu.Game.Tests.Visual.UserInterface [Description("Checks that when an enabled & hovered container gets disabled, colour fading happens")] public void TestBecomesDisabledTransition() { - moveOut(); enableContainer(); checkColour(OsuHoverTestContainer.IDLE_COLOUR); @@ -139,7 +137,6 @@ namespace osu.Game.Tests.Visual.UserInterface [Description("Checks that when a hovered container gets enabled and disabled multiple times, colour fading happens")] public void TestDisabledChangesMultipleTimes() { - moveOut(); enableContainer(); checkColour(OsuHoverTestContainer.IDLE_COLOUR); From 6f6b134ec8266c2d7ea5931052261d29ea7ad9c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 12:52:49 +0900 Subject: [PATCH 1069/5608] Remove return user input calls --- .../Visual/UserInterface/TestSceneOsuHoverContainer.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs index 3613122165..dbef7d1686 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs @@ -55,8 +55,6 @@ namespace osu.Game.Tests.Visual.UserInterface moveOut(); checkNotHovered(); - - ReturnUserInput(); } [Test] @@ -78,8 +76,6 @@ namespace osu.Game.Tests.Visual.UserInterface moveOut(); waitUntilColourIs(OsuHoverTestContainer.IDLE_COLOUR); - - ReturnUserInput(); } [Test] @@ -101,8 +97,6 @@ namespace osu.Game.Tests.Visual.UserInterface moveOut(); checkColour(OsuHoverTestContainer.IDLE_COLOUR); - - ReturnUserInput(); } [Test] From 0fc2c596b650bedc892695e46926c47691810f4c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 12:53:51 +0900 Subject: [PATCH 1070/5608] Add toggle for input priority in manual input tests --- .../Visual/ManualInputManagerTestScene.cs | 92 ++++++++++++++++++- 1 file changed, 88 insertions(+), 4 deletions(-) diff --git a/osu.Game/Tests/Visual/ManualInputManagerTestScene.cs b/osu.Game/Tests/Visual/ManualInputManagerTestScene.cs index a7a7f88ff7..460df8b84c 100644 --- a/osu.Game/Tests/Visual/ManualInputManagerTestScene.cs +++ b/osu.Game/Tests/Visual/ManualInputManagerTestScene.cs @@ -3,8 +3,13 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Testing.Input; using osu.Game.Graphics.Cursor; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Tests.Visual { @@ -15,12 +20,77 @@ namespace osu.Game.Tests.Visual protected readonly ManualInputManager InputManager; + private readonly TriangleButton buttonTest; + private readonly TriangleButton buttonLocal; + protected ManualInputManagerTestScene() { - base.Content.Add(InputManager = new ManualInputManager + base.Content.AddRange(new Drawable[] { - UseParentInput = true, - Child = content = new MenuCursorContainer { RelativeSizeAxes = Axes.Both }, + InputManager = new ManualInputManager + { + UseParentInput = true, + Child = content = new MenuCursorContainer { RelativeSizeAxes = Axes.Both }, + }, + new Container + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Margin = new MarginPadding(5), + CornerRadius = 5, + Masking = true, + Children = new Drawable[] + { + new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + Alpha = 0.5f, + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Margin = new MarginPadding(5), + Spacing = new Vector2(5), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Input Priority" + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Margin = new MarginPadding(5), + Spacing = new Vector2(5), + Direction = FillDirection.Horizontal, + + Children = new Drawable[] + { + buttonLocal = new TriangleButton + { + Text = "local", + Size = new Vector2(50, 30), + Action = returnUserInput + }, + buttonTest = new TriangleButton + { + Text = "test", + Size = new Vector2(50, 30), + Action = returnTestInput + }, + } + }, + } + }, + } + }, }); } @@ -29,7 +99,21 @@ namespace osu.Game.Tests.Visual /// protected void ReturnUserInput() { - AddStep("Return user input", () => InputManager.UseParentInput = true); + AddStep("Return user input", returnUserInput); } + + protected override void Update() + { + base.Update(); + + buttonTest.Enabled.Value = InputManager.UseParentInput; + buttonLocal.Enabled.Value = !InputManager.UseParentInput; + } + + private void returnUserInput() => + InputManager.UseParentInput = true; + + private void returnTestInput() => + InputManager.UseParentInput = false; } } From 1374da7c41b1f364b4012d047d6df7e2ed18de07 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 12:54:57 +0900 Subject: [PATCH 1071/5608] Remove all calls to return user input --- osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs | 1 - osu.Game/Tests/Visual/ManualInputManagerTestScene.cs | 8 -------- 2 files changed, 9 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs index 590ee4e720..8fe31b7ad6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs @@ -84,7 +84,6 @@ namespace osu.Game.Tests.Visual.UserInterface testLocalCursor(); testUserCursorOverride(); testMultipleLocalCursors(); - ReturnUserInput(); } /// diff --git a/osu.Game/Tests/Visual/ManualInputManagerTestScene.cs b/osu.Game/Tests/Visual/ManualInputManagerTestScene.cs index 460df8b84c..86191609a4 100644 --- a/osu.Game/Tests/Visual/ManualInputManagerTestScene.cs +++ b/osu.Game/Tests/Visual/ManualInputManagerTestScene.cs @@ -94,14 +94,6 @@ namespace osu.Game.Tests.Visual }); } - /// - /// Returns input back to the user. - /// - protected void ReturnUserInput() - { - AddStep("Return user input", returnUserInput); - } - protected override void Update() { base.Update(); From 60b70c0f45e11d7114d1769b62f8ef4f1e06c40a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 14:11:21 +0900 Subject: [PATCH 1072/5608] Use lambda for simple functions --- osu.Game/Graphics/Containers/OsuHoverContainer.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index 4ea28f74b9..67af79c763 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -75,14 +75,8 @@ namespace osu.Game.Graphics.Containers EffectTargets.ForEach(d => d.FadeColour(IdleColour)); } - private void fadeIn() - { - EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); - } + private void fadeIn() => EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); - private void fadeOut() - { - EffectTargets.ForEach(d => d.FadeColour(IdleColour, FADE_DURATION, Easing.OutQuint)); - } + private void fadeOut() => EffectTargets.ForEach(d => d.FadeColour(IdleColour, FADE_DURATION, Easing.OutQuint)); } } From 2531250f890245d4df9b8f70b666304027b3faea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 14:58:04 +0900 Subject: [PATCH 1073/5608] Fix paginated layouts only showing one column even if enough space is available for more --- osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 8639acfc94..b459afcb49 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -49,7 +49,6 @@ namespace osu.Game.Overlays.Profile.Sections { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, - Direction = FillDirection.Vertical, Spacing = new Vector2(0, 2), }, MoreButton = new ShowMoreButton From 0ce5c7468fcf155dea67469182fae578abecdaf7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 15:31:23 +0900 Subject: [PATCH 1074/5608] Use switch and consume/block input --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index a7ba87e72a..501679af03 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -197,10 +197,16 @@ namespace osu.Game.Overlays.Mods protected override bool OnKeyDown(KeyDownEvent e) { - if (e.Key == Key.Number1) - DeselectAllButton.Click(); - else if (e.Key == Key.Number2) - CloseButton.Click(); + switch (e.Key) + { + case Key.Number1: + DeselectAllButton.Click(); + return true; + + case Key.Number2: + CloseButton.Click(); + return true; + } return base.OnKeyDown(e); } From b914bb1e2eb9aa0c451addd8d60d076d15e64f9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 15:32:48 +0900 Subject: [PATCH 1075/5608] Remove key hints for now A proper design for this will come in the future. --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 501679af03..0e37e800ca 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -376,7 +376,7 @@ namespace osu.Game.Overlays.Mods DeselectAllButton = new TriangleButton { Width = 180, - Text = "1. Deselect All", + Text = "Deselect All", Action = DeselectAll, Margin = new MarginPadding { @@ -386,7 +386,7 @@ namespace osu.Game.Overlays.Mods CloseButton = new TriangleButton { Width = 180, - Text = "2. Close", + Text = "Close", Action = Hide, Margin = new MarginPadding { From 8f30c9b0a3ec210f6af2cd4e3f8353adda90a740 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 15:58:24 +0900 Subject: [PATCH 1076/5608] Fix file layout of ModSelectOverlay --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 365 +++++++++++---------- 1 file changed, 186 insertions(+), 179 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index b57e98d09e..dec58f4c9e 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -1,43 +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 osuTK; -using osuTK.Input; -using osuTK.Graphics; -using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Graphics.Backgrounds; -using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; -using osu.Game.Rulesets; +using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods.Sections; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Screens; -using osu.Framework.Input.Events; +using osuTK; +using osuTK.Graphics; +using osuTK.Input; namespace osu.Game.Overlays.Mods { public class ModSelectOverlay : WaveOverlayContainer { - private const float content_width = 0.8f; - - protected Color4 LowMultiplierColour, HighMultiplierColour; - protected readonly TriangleButton DeselectAllButton; protected readonly TriangleButton CloseButton; - protected readonly OsuSpriteText MultiplierLabel, UnrankedLabel; - private readonly FillFlowContainer footerContainer; + + protected readonly OsuSpriteText MultiplierLabel; + protected readonly OsuSpriteText UnrankedLabel; protected override bool BlockNonPositionalInput => false; @@ -49,170 +46,14 @@ namespace osu.Game.Overlays.Mods protected readonly IBindable Ruleset = new Bindable(); - [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, IBindable ruleset, AudioManager audio, Bindable> mods) - { - LowMultiplierColour = colours.Red; - HighMultiplierColour = colours.Green; - UnrankedLabel.Colour = colours.Blue; + protected Color4 LowMultiplierColour; + protected Color4 HighMultiplierColour; - Ruleset.BindTo(ruleset); - if (mods != null) SelectedMods.BindTo(mods); - - sampleOn = audio.Samples.Get(@"UI/check-on"); - sampleOff = audio.Samples.Get(@"UI/check-off"); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - Ruleset.BindValueChanged(rulesetChanged, true); - SelectedMods.BindValueChanged(selectedModsChanged, true); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - Ruleset.UnbindAll(); - SelectedMods.UnbindAll(); - } - - private void rulesetChanged(ValueChangedEvent e) - { - if (e.NewValue == null) return; - - var instance = e.NewValue.CreateInstance(); - - foreach (ModSection section in ModSectionsContainer.Children) - section.Mods = instance.GetModsFor(section.ModType); - - // attempt to re-select any already selected mods. - // this may be the first time we are receiving the ruleset, in which case they will still match. - selectedModsChanged(new ValueChangedEvent>(SelectedMods.Value, SelectedMods.Value)); - - // write the mods back to the SelectedMods bindable in the case a change was not applicable. - // this generally isn't required as the previous line will perform deselection; just here for safety. - refreshSelectedMods(); - } - - private void selectedModsChanged(ValueChangedEvent> e) - { - foreach (ModSection section in ModSectionsContainer.Children) - section.SelectTypes(e.NewValue.Select(m => m.GetType()).ToList()); - - updateMods(); - } - - private void updateMods() - { - double multiplier = 1.0; - bool ranked = true; - - foreach (Mod mod in SelectedMods.Value) - { - multiplier *= mod.ScoreMultiplier; - ranked &= mod.Ranked; - } - - MultiplierLabel.Text = $"{multiplier:N2}x"; - if (multiplier > 1.0) - MultiplierLabel.FadeColour(HighMultiplierColour, 200); - else if (multiplier < 1.0) - MultiplierLabel.FadeColour(LowMultiplierColour, 200); - else - MultiplierLabel.FadeColour(Color4.White, 200); - - UnrankedLabel.FadeTo(ranked ? 0 : 1, 200); - } - - protected override void PopOut() - { - base.PopOut(); - - footerContainer.MoveToX(footerContainer.DrawSize.X, WaveContainer.DISAPPEAR_DURATION, Easing.InSine); - footerContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine); - - foreach (ModSection section in ModSectionsContainer.Children) - { - section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), WaveContainer.DISAPPEAR_DURATION, Easing.InSine); - section.ButtonsContainer.MoveToX(100f, WaveContainer.DISAPPEAR_DURATION, Easing.InSine); - section.ButtonsContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine); - } - } - - protected override void PopIn() - { - base.PopIn(); - - footerContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); - footerContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint); - - foreach (ModSection section in ModSectionsContainer.Children) - { - section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), WaveContainer.APPEAR_DURATION, Easing.OutQuint); - section.ButtonsContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); - section.ButtonsContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint); - } - } - - public void DeselectAll() - { - foreach (ModSection section in ModSectionsContainer.Children) - section.DeselectAll(); - - refreshSelectedMods(); - } - - /// - /// Deselect one or more mods. - /// - /// The types of s which should be deselected. - /// Set to true to bypass animations and update selections immediately. - public void DeselectTypes(Type[] modTypes, bool immediate = false) - { - if (modTypes.Length == 0) return; - - foreach (ModSection section in ModSectionsContainer.Children) - section.DeselectTypes(modTypes, immediate); - } + private const float content_width = 0.8f; + private readonly FillFlowContainer footerContainer; private SampleChannel sampleOn, sampleOff; - private void modButtonPressed(Mod selectedMod) - { - if (selectedMod != null) - { - if (State == Visibility.Visible) sampleOn?.Play(); - DeselectTypes(selectedMod.IncompatibleMods, true); - } - else - { - if (State == Visibility.Visible) sampleOff?.Play(); - } - - refreshSelectedMods(); - } - - protected override bool OnKeyDown(KeyDownEvent e) - { - switch (e.Key) - { - case Key.Number1: - DeselectAllButton.Click(); - return true; - - case Key.Number2: - CloseButton.Click(); - return true; - } - - return base.OnKeyDown(e); - } - - private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray(); - public ModSelectOverlay() { Waves.FirstWaveColour = OsuColour.FromHex(@"19b0e2"); @@ -430,5 +271,171 @@ namespace osu.Game.Overlays.Mods }, }; } + + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours, IBindable ruleset, AudioManager audio, Bindable> mods) + { + LowMultiplierColour = colours.Red; + HighMultiplierColour = colours.Green; + UnrankedLabel.Colour = colours.Blue; + + Ruleset.BindTo(ruleset); + if (mods != null) SelectedMods.BindTo(mods); + + sampleOn = audio.Samples.Get(@"UI/check-on"); + sampleOff = audio.Samples.Get(@"UI/check-off"); + } + + public void DeselectAll() + { + foreach (var section in ModSectionsContainer.Children) + section.DeselectAll(); + + refreshSelectedMods(); + } + + /// + /// Deselect one or more mods. + /// + /// The types of s which should be deselected. + /// Set to true to bypass animations and update selections immediately. + public void DeselectTypes(Type[] modTypes, bool immediate = false) + { + if (modTypes.Length == 0) return; + + foreach (var section in ModSectionsContainer.Children) + section.DeselectTypes(modTypes, immediate); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Ruleset.BindValueChanged(rulesetChanged, true); + SelectedMods.BindValueChanged(selectedModsChanged, true); + } + + protected override void PopOut() + { + base.PopOut(); + + footerContainer.MoveToX(footerContainer.DrawSize.X, WaveContainer.DISAPPEAR_DURATION, Easing.InSine); + footerContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine); + + foreach (var section in ModSectionsContainer.Children) + { + section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), WaveContainer.DISAPPEAR_DURATION, Easing.InSine); + section.ButtonsContainer.MoveToX(100f, WaveContainer.DISAPPEAR_DURATION, Easing.InSine); + section.ButtonsContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine); + } + } + + protected override void PopIn() + { + base.PopIn(); + + footerContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); + footerContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint); + + foreach (var section in ModSectionsContainer.Children) + { + section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), WaveContainer.APPEAR_DURATION, Easing.OutQuint); + section.ButtonsContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); + section.ButtonsContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint); + } + } + + protected override bool OnKeyDown(KeyDownEvent e) + { + switch (e.Key) + { + case Key.Number1: + DeselectAllButton.Click(); + return true; + + case Key.Number2: + CloseButton.Click(); + return true; + } + + return base.OnKeyDown(e); + } + + private void rulesetChanged(ValueChangedEvent e) + { + if (e.NewValue == null) return; + + var instance = e.NewValue.CreateInstance(); + + foreach (var section in ModSectionsContainer.Children) + section.Mods = instance.GetModsFor(section.ModType); + + // attempt to re-select any already selected mods. + // this may be the first time we are receiving the ruleset, in which case they will still match. + selectedModsChanged(new ValueChangedEvent>(SelectedMods.Value, SelectedMods.Value)); + + // write the mods back to the SelectedMods bindable in the case a change was not applicable. + // this generally isn't required as the previous line will perform deselection; just here for safety. + refreshSelectedMods(); + } + + private void selectedModsChanged(ValueChangedEvent> e) + { + foreach (var section in ModSectionsContainer.Children) + section.SelectTypes(e.NewValue.Select(m => m.GetType()).ToList()); + + updateMods(); + } + + private void updateMods() + { + var multiplier = 1.0; + var ranked = true; + + foreach (var mod in SelectedMods.Value) + { + multiplier *= mod.ScoreMultiplier; + ranked &= mod.Ranked; + } + + MultiplierLabel.Text = $"{multiplier:N2}x"; + if (multiplier > 1.0) + MultiplierLabel.FadeColour(HighMultiplierColour, 200); + else if (multiplier < 1.0) + MultiplierLabel.FadeColour(LowMultiplierColour, 200); + else + MultiplierLabel.FadeColour(Color4.White, 200); + + UnrankedLabel.FadeTo(ranked ? 0 : 1, 200); + } + + private void modButtonPressed(Mod selectedMod) + { + if (selectedMod != null) + { + if (State == Visibility.Visible) sampleOn?.Play(); + DeselectTypes(selectedMod.IncompatibleMods, true); + } + else + { + if (State == Visibility.Visible) sampleOff?.Play(); + } + + refreshSelectedMods(); + } + + private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray(); + + #region Disposal + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + Ruleset.UnbindAll(); + SelectedMods.UnbindAll(); + } + + #endregion } } From cd4648a64729383356dcf0a26538126c902241ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Jun 2019 21:09:59 +0900 Subject: [PATCH 1077/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 55fa20188c..654c62e1d8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 68f21df8ba..8886184a2e 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From e5b64bfa39df31f0db308655c943272e6c7b9348 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 7 Jun 2019 18:51:43 +0200 Subject: [PATCH 1078/5608] Highlight major changes in changelog overlay --- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 51 ++++++++++++++++--- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 57615332da..627eb10426 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -69,34 +69,69 @@ namespace osu.Game.Overlays.Changelog Margin = new MarginPadding { Vertical = 5 }, }; + var entryColor = entry.Major != null && (bool)entry.Major ? OsuColour.FromHex("#fd5") : Color4.White; + title.AddIcon(FontAwesome.Solid.Check, t => { t.Font = fontSmall; + t.Colour = entryColor; t.Padding = new MarginPadding { Left = -17, Right = 5 }; }); - title.AddText(entry.Title, t => { t.Font = fontLarge; }); + title.AddText(entry.Title, t => + { + t.Font = fontLarge; + t.Colour = entryColor; + }); if (!string.IsNullOrEmpty(entry.Repository)) { - title.AddText(" (", t => t.Font = fontLarge); + title.AddText(" (", t => + { + t.Font = fontLarge; + t.Colour = entryColor; + }); title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, Online.Chat.LinkAction.External, - creationParameters: t => { t.Font = fontLarge; }); - title.AddText(")", t => t.Font = fontLarge); + creationParameters: t => + { + t.Font = fontLarge; + t.Colour = entryColor; + }); + title.AddText(")", t => + { + t.Font = fontLarge; + t.Colour = entryColor; + }); } - title.AddText(" by ", t => t.Font = fontMedium); + title.AddText(" by ", t => + { + t.Font = fontMedium; + t.Colour = entryColor; + }); if (entry.GithubUser.UserId != null) title.AddUserLink(new User { Username = entry.GithubUser.OsuUsername, Id = entry.GithubUser.UserId.Value - }, t => t.Font = fontMedium); + }, t => + { + t.Font = fontMedium; + t.Colour = entryColor; + }); else if (entry.GithubUser.GithubUrl != null) - title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t => t.Font = fontMedium); + title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t => + { + t.Font = fontMedium; + t.Colour = entryColor; + }); else - title.AddText(entry.GithubUser.DisplayName, t => t.Font = fontSmall); + title.AddText(entry.GithubUser.DisplayName, t => + { + t.Font = fontSmall; + t.Colour = entryColor; + }); ChangelogEntries.Add(title); From f326264a85abacef478d45cf71fc28867b3554e2 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Sat, 8 Jun 2019 00:42:57 +0700 Subject: [PATCH 1079/5608] Adding increase first object grow mod visibility setting --- osu.Game/Configuration/OsuConfigManager.cs | 3 +++ osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 795f0b43f7..b5a099aa3b 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -85,6 +85,8 @@ namespace osu.Game.Configuration Set(OsuSetting.IncreaseFirstObjectVisibility, true); + Set(OsuSetting.IncreaseFirstObjectGrowVisibility, true); + // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -158,6 +160,7 @@ namespace osu.Game.Configuration BeatmapSkins, BeatmapHitsounds, IncreaseFirstObjectVisibility, + IncreaseFirstObjectGrowVisibility, ScoreDisplayMode, ExternalLinkWarning, Scaling, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index 2cf14f5aff..538b2b2761 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -20,6 +20,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay LabelText = "Increase visibility of first object with \"Hidden\" mod", Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility) }, + new SettingsCheckbox + { + LabelText = "Increase visibility of first object with \"Grow\" mod", + Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectGrowVisibility) + }, }; } } From 8ac64b5c16c0d8fe05f680a2226bc1dc37e15a6f Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Sat, 8 Jun 2019 01:46:05 +0700 Subject: [PATCH 1080/5608] Make first object not applying custom state --- osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs index a2da2bbf53..a5df36e9ff 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs @@ -2,8 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; @@ -11,7 +14,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods { - internal class OsuModGrow : Mod, IApplicableToDrawableHitObjects + internal class OsuModGrow : Mod, IReadFromConfig, IApplicableToDrawableHitObjects { public override string Name => "Grow"; @@ -25,9 +28,16 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; + protected Bindable IncreaseFirstObjectGrowVisibility = new Bindable(); + + public void ReadFromConfig(OsuConfigManager config) + { + IncreaseFirstObjectGrowVisibility = config.GetBindable(OsuSetting.IncreaseFirstObjectGrowVisibility); + } + public void ApplyToDrawableHitObjects(IEnumerable drawables) { - foreach (var drawable in drawables) + foreach (var drawable in drawables.Skip(IncreaseFirstObjectGrowVisibility.Value ? 1 : 0)) { switch (drawable) { From 342e39776aaa5559401e86d2b6d656f01476acab Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 7 Jun 2019 20:59:56 +0200 Subject: [PATCH 1081/5608] Move ChangelogEntries populating logic from constructor to BDL load() to use OsuColour palette +apply review suggestions. --- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 627eb10426..ae5ba3fa4e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -13,6 +13,7 @@ using System.Text.RegularExpressions; using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK.Graphics; +using osu.Framework.Allocation; namespace osu.Game.Overlays.Changelog { @@ -45,8 +46,12 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Vertical, }, }; + } - foreach (var categoryEntries in build.ChangelogEntries.GroupBy(b => b.Category).OrderBy(c => c.Key)) + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + foreach (var categoryEntries in Build.ChangelogEntries.GroupBy(b => b.Category).OrderBy(c => c.Key)) { ChangelogEntries.Add(new OsuSpriteText { @@ -69,19 +74,19 @@ namespace osu.Game.Overlays.Changelog Margin = new MarginPadding { Vertical = 5 }, }; - var entryColor = entry.Major != null && (bool)entry.Major ? OsuColour.FromHex("#fd5") : Color4.White; + var entryColour = entry.Major != null && (bool)entry.Major ? colours.YellowLight : Color4.White; title.AddIcon(FontAwesome.Solid.Check, t => { t.Font = fontSmall; - t.Colour = entryColor; + t.Colour = entryColour; t.Padding = new MarginPadding { Left = -17, Right = 5 }; }); title.AddText(entry.Title, t => { t.Font = fontLarge; - t.Colour = entryColor; + t.Colour = entryColour; }); if (!string.IsNullOrEmpty(entry.Repository)) @@ -89,25 +94,25 @@ namespace osu.Game.Overlays.Changelog title.AddText(" (", t => { t.Font = fontLarge; - t.Colour = entryColor; + t.Colour = entryColour; }); title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, Online.Chat.LinkAction.External, creationParameters: t => { t.Font = fontLarge; - t.Colour = entryColor; + t.Colour = entryColour; }); title.AddText(")", t => { t.Font = fontLarge; - t.Colour = entryColor; + t.Colour = entryColour; }); } title.AddText(" by ", t => { t.Font = fontMedium; - t.Colour = entryColor; + t.Colour = entryColour; }); if (entry.GithubUser.UserId != null) @@ -118,19 +123,19 @@ namespace osu.Game.Overlays.Changelog }, t => { t.Font = fontMedium; - t.Colour = entryColor; + t.Colour = entryColour; }); else if (entry.GithubUser.GithubUrl != null) title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t => { t.Font = fontMedium; - t.Colour = entryColor; + t.Colour = entryColour; }); else title.AddText(entry.GithubUser.DisplayName, t => { t.Font = fontSmall; - t.Colour = entryColor; + t.Colour = entryColour; }); ChangelogEntries.Add(title); From d058f7779308c20c667b796fd490c01317a3aad2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 8 Jun 2019 16:36:48 +0900 Subject: [PATCH 1082/5608] Update resources for iOS --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 8886184a2e..3a5090d968 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -104,7 +104,7 @@ - + From e8c73f3127d953a0ca188f0e53b79066e847eb07 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 8 Jun 2019 09:45:34 +0200 Subject: [PATCH 1083/5608] Make APIChangelogEntry.Major a non-nullable property --- osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs | 2 +- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs index abaff9b7ae..140e228acd 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs @@ -36,7 +36,7 @@ namespace osu.Game.Online.API.Requests.Responses public string MessageHtml { get; set; } [JsonProperty("major")] - public bool? Major { get; set; } + public bool Major { get; set; } [JsonProperty("created_at")] public DateTimeOffset? CreatedAt { get; set; } diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index ae5ba3fa4e..3d145af562 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -74,7 +74,7 @@ namespace osu.Game.Overlays.Changelog Margin = new MarginPadding { Vertical = 5 }, }; - var entryColour = entry.Major != null && (bool)entry.Major ? colours.YellowLight : Color4.White; + var entryColour = entry.Major ? colours.YellowLight : Color4.White; title.AddIcon(FontAwesome.Solid.Check, t => { From d1d3cfa991b6a3c9c64b5b82128ecebfe7180fa4 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Sat, 8 Jun 2019 11:55:52 +0300 Subject: [PATCH 1084/5608] Remove ruleset selector from the user overlay --- osu.Game/Overlays/UserProfileOverlay.cs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index ec81193896..70ce83806e 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -11,7 +11,6 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Profile; -using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Overlays.Profile.Sections; using osu.Game.Users; using osuTK; @@ -26,7 +25,6 @@ namespace osu.Game.Overlays protected ProfileHeader Header; private SectionsContainer sectionsContainer; private ProfileTabControl tabs; - private ProfileRulesetSelector rulesetSelector; public const float CONTENT_X_MARGIN = 70; @@ -121,15 +119,6 @@ namespace osu.Game.Overlays } sectionsContainer.ScrollToTop(); - - Header.Add(rulesetSelector = new ProfileRulesetSelector - { - Alpha = 0, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Y = 100, - Margin = new MarginPadding { Right = 30 }, - }); } private void userLoadComplete(User user) @@ -151,11 +140,6 @@ namespace osu.Game.Overlays } } } - - rulesetSelector.SetDefaultGamemode(user.PlayMode ?? "osu"); - rulesetSelector.SelectDefaultGamemode(); - - rulesetSelector.FadeInFromZero(100, Easing.OutQuint); } private class ProfileTabControl : PageTabControl From 06dfa42a5ad09ca8ca31f128d433e56a0dc900cb Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Sat, 8 Jun 2019 18:27:40 +0300 Subject: [PATCH 1085/5608] Refactor --- .../Overlays/Toolbar/ToolbarRulesetButton.cs | 73 +++++++------ .../Toolbar/ToolbarRulesetSelector.cs | 101 +++++++++--------- 2 files changed, 90 insertions(+), 84 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs index 87b18ba9f4..efb540cd45 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs @@ -2,57 +2,68 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK.Graphics; +using osu.Framework.Graphics; namespace osu.Game.Overlays.Toolbar { - public class ToolbarRulesetButton : ToolbarButton + public class ToolbarRulesetButton : TabItem { - private RulesetInfo ruleset; + private readonly DrawableRuleset ruleset; - public RulesetInfo Ruleset + public ToolbarRulesetButton(RulesetInfo value) + : base(value) { - get => ruleset; - set + AutoSizeAxes = Axes.X; + RelativeSizeAxes = Axes.Y; + Child = ruleset = new DrawableRuleset { - ruleset = value; + Active = false, + }; - var rInstance = ruleset.CreateInstance(); + var rInstance = value.CreateInstance(); - TooltipMain = rInstance.Description; - TooltipSub = $"Play some {rInstance.Description}"; - SetIcon(rInstance.CreateIcon()); - } + ruleset.TooltipMain = rInstance.Description; + ruleset.TooltipSub = $"Play some {rInstance.Description}"; + ruleset.SetIcon(rInstance.CreateIcon()); } - public bool Active + protected override void OnActivated() => ruleset.Active = true; + + protected override void OnDeactivated() => ruleset.Active = false; + + private class DrawableRuleset : ToolbarButton { - set + public bool Active { - if (value) + set { - IconContainer.Colour = Color4.White; - IconContainer.EdgeEffect = new EdgeEffectParameters + if (value) { - Type = EdgeEffectType.Glow, - Colour = new Color4(255, 194, 224, 100), - Radius = 15, - Roundness = 15, - }; - } - else - { - IconContainer.Colour = new Color4(255, 194, 224, 255); - IconContainer.EdgeEffect = new EdgeEffectParameters(); + IconContainer.Colour = Color4.White; + IconContainer.EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = new Color4(255, 194, 224, 100), + Radius = 15, + Roundness = 15, + }; + } + else + { + IconContainer.Colour = new Color4(255, 194, 224, 255); + IconContainer.EdgeEffect = new EdgeEffectParameters(); + } } } - } - protected override void LoadComplete() - { - base.LoadComplete(); - IconContainer.Scale *= 1.4f; + protected override void LoadComplete() + { + base.LoadComplete(); + IconContainer.Scale *= 1.4f; + } } } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 90412ec1d1..abea9b217d 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -1,53 +1,54 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osuTK; -using osuTK.Input; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; using osu.Game.Rulesets; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Bindables; +using osu.Framework.Input.Events; +using osuTK.Input; +using System.Linq; namespace osu.Game.Overlays.Toolbar { - public class ToolbarRulesetSelector : Container + public class ToolbarRulesetSelector : TabControl { private const float padding = 10; - - private readonly FillFlowContainer modeButtons; private readonly Drawable modeButtonLine; - private ToolbarRulesetButton activeButton; - private RulesetStore rulesets; - private readonly Bindable ruleset = new Bindable(); + + public override bool HandleNonPositionalInput => !Current.Disabled && base.HandleNonPositionalInput; + public override bool HandlePositionalInput => !Current.Disabled && base.HandlePositionalInput; + + public override bool PropagatePositionalInputSubTree => !Current.Disabled && base.PropagatePositionalInputSubTree; + + private void disabledChanged(bool isDisabled) => this.FadeColour(isDisabled ? Color4.Gray : Color4.White, 300); + + protected override Dropdown CreateDropdown() => null; + + protected override TabItem CreateTabItem(RulesetInfo value) => new ToolbarRulesetButton(value); public ToolbarRulesetSelector() { RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; - Children = new[] + AddRangeInternal(new Drawable[] { - new OpaqueBackground(), - modeButtons = new FillFlowContainer + new OpaqueBackground { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Direction = FillDirection.Horizontal, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Padding = new MarginPadding { Left = padding, Right = padding }, + Depth = 1, }, modeButtonLine = new Container { - Size = new Vector2(padding * 2 + ToolbarButton.WIDTH, 3), + Size = new Vector2(padding* 2 + ToolbarButton.WIDTH, 3), Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft, Masking = true, @@ -58,17 +59,22 @@ namespace osu.Game.Overlays.Toolbar Radius = 15, Roundness = 15, }, - Children = new[] + Child = new Box { - new Box - { - RelativeSizeAxes = Axes.Both, - } + RelativeSizeAxes = Axes.Both, } } - }; + }); } + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Direction = FillDirection.Horizontal, + Padding = new MarginPadding { Left = padding, Right = padding }, + }; + [BackgroundDependencyLoader] private void load(RulesetStore rulesets, Bindable parentRuleset) { @@ -76,16 +82,13 @@ namespace osu.Game.Overlays.Toolbar foreach (var r in rulesets.AvailableRulesets) { - modeButtons.Add(new ToolbarRulesetButton - { - Ruleset = r, - Action = delegate { ruleset.Value = r; } - }); + AddItem(r); } - ruleset.ValueChanged += rulesetChanged; - ruleset.DisabledChanged += disabledChanged; - ruleset.BindTo(parentRuleset); + Current.BindTo(parentRuleset); + Current.Disabled = false; + Current.DisabledChanged += disabledChanged; + Current.BindValueChanged(rulesetChanged); } protected override bool OnKeyDown(KeyDownEvent e) @@ -98,43 +101,35 @@ namespace osu.Game.Overlays.Toolbar RulesetInfo found = rulesets.AvailableRulesets.Skip(requested).FirstOrDefault(); if (found != null) - ruleset.Value = found; + Current.Value = found; return true; } return false; } - public override bool HandleNonPositionalInput => !ruleset.Disabled && base.HandleNonPositionalInput; - public override bool HandlePositionalInput => !ruleset.Disabled && base.HandlePositionalInput; - - public override bool PropagatePositionalInputSubTree => !ruleset.Disabled && base.PropagatePositionalInputSubTree; - - private void disabledChanged(bool isDisabled) => this.FadeColour(isDisabled ? Color4.Gray : Color4.White, 300); + private readonly Cached activeMode = new Cached(); private void rulesetChanged(ValueChangedEvent e) { - foreach (ToolbarRulesetButton m in modeButtons.Children.Cast()) - { - bool isActive = m.Ruleset.ID == e.NewValue.ID; - m.Active = isActive; - if (isActive) - activeButton = m; - } - activeMode.Invalidate(); } - private Cached activeMode = new Cached(); - protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); if (!activeMode.IsValid) { - modeButtonLine.MoveToX(activeButton.DrawPosition.X, 200, Easing.OutQuint); - activeMode.Validate(); + foreach (TabItem tabItem in TabContainer) + { + if (tabItem.Value == Current.Value) + { + modeButtonLine.MoveToX(tabItem.DrawPosition.X, 200, Easing.OutQuint); + activeMode.Validate(); + return; + } + } } } } From 62eadf21c96964fa52f748d8b3a128f6c282c000 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Sat, 8 Jun 2019 18:38:52 +0300 Subject: [PATCH 1086/5608] Remove useless line --- osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index abea9b217d..8590c9fbc0 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -86,7 +86,6 @@ namespace osu.Game.Overlays.Toolbar } Current.BindTo(parentRuleset); - Current.Disabled = false; Current.DisabledChanged += disabledChanged; Current.BindValueChanged(rulesetChanged); } From 383b937a7e44b2eac1f20ba7b1b1a6cfce0bfae2 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 8 Jun 2019 19:10:00 +0300 Subject: [PATCH 1087/5608] Rename F grade to D --- osu.Game/Scoring/ScoreRank.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreRank.cs b/osu.Game/Scoring/ScoreRank.cs index a93d015f1b..d3479e21aa 100644 --- a/osu.Game/Scoring/ScoreRank.cs +++ b/osu.Game/Scoring/ScoreRank.cs @@ -7,10 +7,10 @@ namespace osu.Game.Scoring { public enum ScoreRank { - [Description(@"F")] + [Description(@"D")] F, - [Description(@"F")] + [Description(@"D")] D, [Description(@"C")] From 17362a368e2ab792c43e05cc992d6b729247b62e Mon Sep 17 00:00:00 2001 From: Ludde <48018938+yousef157@users.noreply.github.com> Date: Sat, 8 Jun 2019 20:10:52 +0400 Subject: [PATCH 1088/5608] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 91ea34e999..04f133fd56 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ If you are not interested in developing the game, you can consume our [binary re | ------------- | ------------- | - **Linux** users are recommended to self-compile until we have official deployment in place. -- **iOS** users can join the [TestFlight beta program](https://t.co/xQJmHkfC18) (note that due to high demand this is reulgarly full). +- **iOS** users can join the [TestFlight beta program](https://t.co/xQJmHkfC18) (note that due to high demand this is regularly full). - **Android** users can self-compile, and expect a public beta soon. If your platform is not listed above, there is still a chance you can manually build it by following the instructions below. From dfbc6528031fc340a9a718699db236172aeac207 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 8 Jun 2019 19:32:26 +0300 Subject: [PATCH 1089/5608] Use ScoreRank.D instead of F --- osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 89da0fc254..cbcf3e6160 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Text = "#1", Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true) }, - rank = new DrawableRank(ScoreRank.F) + rank = new DrawableRank(ScoreRank.D) { Anchor = Anchor.Centre, Origin = Anchor.Centre, From d3ff2c6dd5bbc9a14653e9fa6a72bb0093f6d519 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 8 Jun 2019 19:34:03 +0300 Subject: [PATCH 1090/5608] Use ScoreRank.D instead of F --- osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs index 3d75470328..9365e2c5b1 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs @@ -188,7 +188,7 @@ namespace osu.Game.Tests.Visual.SongSelect }, new ScoreInfo { - Rank = ScoreRank.F, + Rank = ScoreRank.D, Accuracy = 0.6025, MaxCombo = 244, TotalScore = 1707827, @@ -206,7 +206,7 @@ namespace osu.Game.Tests.Visual.SongSelect }, new ScoreInfo { - Rank = ScoreRank.F, + Rank = ScoreRank.D, Accuracy = 0.5140, MaxCombo = 244, TotalScore = 1707827, @@ -224,7 +224,7 @@ namespace osu.Game.Tests.Visual.SongSelect }, new ScoreInfo { - Rank = ScoreRank.F, + Rank = ScoreRank.D, Accuracy = 0.4222, MaxCombo = 244, TotalScore = 1707827, From fc8644a73e0a8cf37e90ec199f2c4b5ac2b785c5 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 8 Jun 2019 19:34:52 +0300 Subject: [PATCH 1091/5608] Use ScoreRank.D instead of F --- osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index 6815018be6..2f88a4b01d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -157,7 +157,7 @@ namespace osu.Game.Tests.Visual.Online FlagName = @"TH", }, }, - Rank = ScoreRank.F, + Rank = ScoreRank.D, PP = 160, MaxCombo = 1234, TotalScore = 123456, From a2b9dba92cce57e04a956efd1f4baa7906488373 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 8 Jun 2019 19:35:29 +0300 Subject: [PATCH 1092/5608] Remove ScoreRank.F --- osu.Game/Scoring/ScoreRank.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Scoring/ScoreRank.cs b/osu.Game/Scoring/ScoreRank.cs index d3479e21aa..696d493830 100644 --- a/osu.Game/Scoring/ScoreRank.cs +++ b/osu.Game/Scoring/ScoreRank.cs @@ -7,9 +7,6 @@ namespace osu.Game.Scoring { public enum ScoreRank { - [Description(@"D")] - F, - [Description(@"D")] D, From afc3a089536d72fe7f0b357866caa31dafb3c8fc Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Sun, 9 Jun 2019 13:11:40 +0700 Subject: [PATCH 1093/5608] Use existing setting instead Now it read IncreaseFirstObjectVisibility bindable instead --- osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs | 6 +++--- osu.Game/Configuration/OsuConfigManager.cs | 3 --- .../Overlays/Settings/Sections/Gameplay/ModsSettings.cs | 5 ----- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs index a5df36e9ff..3d64bb4ce8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs @@ -28,16 +28,16 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; - protected Bindable IncreaseFirstObjectGrowVisibility = new Bindable(); + protected Bindable IncreaseFirstObjectVisibility = new Bindable(); public void ReadFromConfig(OsuConfigManager config) { - IncreaseFirstObjectGrowVisibility = config.GetBindable(OsuSetting.IncreaseFirstObjectGrowVisibility); + IncreaseFirstObjectVisibility = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility); } public void ApplyToDrawableHitObjects(IEnumerable drawables) { - foreach (var drawable in drawables.Skip(IncreaseFirstObjectGrowVisibility.Value ? 1 : 0)) + foreach (var drawable in drawables.Skip(IncreaseFirstObjectVisibility.Value ? 1 : 0)) { switch (drawable) { diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index b5a099aa3b..795f0b43f7 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -85,8 +85,6 @@ namespace osu.Game.Configuration Set(OsuSetting.IncreaseFirstObjectVisibility, true); - Set(OsuSetting.IncreaseFirstObjectGrowVisibility, true); - // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -160,7 +158,6 @@ namespace osu.Game.Configuration BeatmapSkins, BeatmapHitsounds, IncreaseFirstObjectVisibility, - IncreaseFirstObjectGrowVisibility, ScoreDisplayMode, ExternalLinkWarning, Scaling, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index 538b2b2761..2cf14f5aff 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -20,11 +20,6 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay LabelText = "Increase visibility of first object with \"Hidden\" mod", Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility) }, - new SettingsCheckbox - { - LabelText = "Increase visibility of first object with \"Grow\" mod", - Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectGrowVisibility) - }, }; } } From 49193a2703edb7c5d35b04d0c206031e2a2708f9 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Sun, 9 Jun 2019 13:12:41 +0700 Subject: [PATCH 1094/5608] Rename the setting label --- osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index 2cf14f5aff..2c6b2663c6 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { new SettingsCheckbox { - LabelText = "Increase visibility of first object with \"Hidden\" mod", + LabelText = "Increase visibility of first object when visual impairment mods are enabled", Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility) }, }; From 8cdcf251b5aca691d3af18b459cbb12f5c1704b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 9 Jun 2019 16:30:04 +0900 Subject: [PATCH 1095/5608] Make local bindable private --- osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs index 3d64bb4ce8..8072dc09c1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs @@ -28,16 +28,16 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; - protected Bindable IncreaseFirstObjectVisibility = new Bindable(); + private Bindable increaseFirstObjectVisibility = new Bindable(); public void ReadFromConfig(OsuConfigManager config) { - IncreaseFirstObjectVisibility = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility); + increaseFirstObjectVisibility = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility); } public void ApplyToDrawableHitObjects(IEnumerable drawables) { - foreach (var drawable in drawables.Skip(IncreaseFirstObjectVisibility.Value ? 1 : 0)) + foreach (var drawable in drawables.Skip(increaseFirstObjectVisibility.Value ? 1 : 0)) { switch (drawable) { From d500f3605ef8c71f6a40256b86fe6a5a618d0558 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 9 Jun 2019 16:47:48 +0900 Subject: [PATCH 1096/5608] Fix checkboxes with long labels overlapping nub --- .../Graphics/UserInterface/OsuCheckbox.cs | 22 ++++++++++--------- .../Overlays/Settings/SettingsCheckbox.cs | 1 - 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index cd1147e3d3..dd126d8518 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -6,10 +6,9 @@ using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; -using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.Containers; using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface @@ -33,7 +32,6 @@ namespace osu.Game.Graphics.UserInterface public string LabelText { - get => labelSpriteText?.Text; set { if (labelSpriteText != null) @@ -53,7 +51,7 @@ namespace osu.Game.Graphics.UserInterface protected readonly Nub Nub; - private readonly SpriteText labelSpriteText; + private readonly OsuTextFlowContainer labelSpriteText; private SampleChannel sampleChecked; private SampleChannel sampleUnchecked; @@ -62,24 +60,28 @@ namespace osu.Game.Graphics.UserInterface AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; + const float nub_padding = 5; + Children = new Drawable[] { - labelSpriteText = new OsuSpriteText(), + labelSpriteText = new OsuTextFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Padding = new MarginPadding { Right = Nub.EXPANDED_SIZE + nub_padding } + }, Nub = new Nub { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Margin = new MarginPadding { Right = 5 }, + Margin = new MarginPadding { Right = nub_padding }, }, new HoverClickSounds() }; Nub.Current.BindTo(Current); - Current.DisabledChanged += disabled => - { - labelSpriteText.Alpha = Nub.Alpha = disabled ? 0.3f : 1; - }; + Current.DisabledChanged += disabled => { labelSpriteText.Alpha = Nub.Alpha = disabled ? 0.3f : 1; }; } protected override void LoadComplete() diff --git a/osu.Game/Overlays/Settings/SettingsCheckbox.cs b/osu.Game/Overlays/Settings/SettingsCheckbox.cs index 46c23c3bbf..a1501d8015 100644 --- a/osu.Game/Overlays/Settings/SettingsCheckbox.cs +++ b/osu.Game/Overlays/Settings/SettingsCheckbox.cs @@ -14,7 +14,6 @@ namespace osu.Game.Overlays.Settings public override string LabelText { - get => checkbox.LabelText; set => checkbox.LabelText = value; } } From cd89633dee31f80d9181a00467b00159ae20cf76 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 9 Jun 2019 17:07:23 +0900 Subject: [PATCH 1097/5608] Rename variable to match --- osu.Game/Graphics/UserInterface/OsuCheckbox.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index dd126d8518..5d41075725 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -34,24 +34,24 @@ namespace osu.Game.Graphics.UserInterface { set { - if (labelSpriteText != null) - labelSpriteText.Text = value; + if (labelText != null) + labelText.Text = value; } } public MarginPadding LabelPadding { - get => labelSpriteText?.Padding ?? new MarginPadding(); + get => labelText?.Padding ?? new MarginPadding(); set { - if (labelSpriteText != null) - labelSpriteText.Padding = value; + if (labelText != null) + labelText.Padding = value; } } protected readonly Nub Nub; - private readonly OsuTextFlowContainer labelSpriteText; + private readonly OsuTextFlowContainer labelText; private SampleChannel sampleChecked; private SampleChannel sampleUnchecked; @@ -64,7 +64,7 @@ namespace osu.Game.Graphics.UserInterface Children = new Drawable[] { - labelSpriteText = new OsuTextFlowContainer + labelText = new OsuTextFlowContainer { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, @@ -81,7 +81,7 @@ namespace osu.Game.Graphics.UserInterface Nub.Current.BindTo(Current); - Current.DisabledChanged += disabled => { labelSpriteText.Alpha = Nub.Alpha = disabled ? 0.3f : 1; }; + Current.DisabledChanged += disabled => { labelText.Alpha = Nub.Alpha = disabled ? 0.3f : 1; }; } protected override void LoadComplete() From 807d434be03898334671c6fd382cda252633d6c8 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sun, 9 Jun 2019 17:52:02 +0930 Subject: [PATCH 1098/5608] Access WindowModes via IBindableList --- osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 58d2eb1f1e..36c4fb5252 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private Bindable scalingMode; private Bindable sizeFullscreen; - private readonly BindableList windowModes = new BindableList(); + private readonly IBindableList windowModes = new BindableList(); private OsuGameBase game; private SettingsDropdown resolutionDropdown; From a5007b94dbd1b66d97d461c830fb11ef6f784764 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 9 Jun 2019 22:29:00 +0900 Subject: [PATCH 1099/5608] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 654c62e1d8..eeb1f2bee3 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + From d964f6ba9e0e166255fdedb1726472ef2e1bbd24 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 00:56:35 +0900 Subject: [PATCH 1100/5608] Tween track frequency on pause --- osu.Game/Screens/Play/GameplayClockContainer.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index c151e598f7..4b35e90f68 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -69,6 +69,7 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both; sourceClock = (IAdjustableClock)beatmap.Track ?? new StopwatchClock(); + (sourceClock as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; @@ -85,8 +86,16 @@ namespace osu.Game.Screens.Play GameplayClock.IsPaused.BindTo(IsPaused); } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + (sourceClock as IAdjustableAudioComponent)?.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); + } + private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset; + private readonly BindableDouble pauseFreqAdjust = new BindableDouble(1); + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { @@ -122,6 +131,8 @@ namespace osu.Game.Screens.Play Seek(GameplayClock.CurrentTime); adjustableClock.Start(); IsPaused.Value = false; + + this.TransformBindableTo(pauseFreqAdjust, 1, 200, Easing.In); } /// @@ -143,7 +154,8 @@ namespace osu.Game.Screens.Play public void Stop() { - adjustableClock.Stop(); + this.TransformBindableTo(pauseFreqAdjust, 0, 200, Easing.Out).OnComplete(_ => { adjustableClock.Stop(); }); + IsPaused.Value = true; } From 59b624d4ba4a8cf89b068e5abcf4cec2a38a02b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 01:08:39 +0900 Subject: [PATCH 1101/5608] Fix test regression --- osu.Game.Tests/Visual/Gameplay/TestScenePause.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 12e91df77c..0f5ee66f50 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -189,7 +189,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("pause overlay " + (isShown ? "shown" : "hidden"), () => Player.PauseOverlayVisible == isShown); private void confirmClockRunning(bool isRunning) => - AddAssert("clock " + (isRunning ? "running" : "stopped"), () => Player.GameplayClockContainer.GameplayClock.IsRunning == isRunning); + AddUntilStep("clock " + (isRunning ? "running" : "stopped"), () => Player.GameplayClockContainer.GameplayClock.IsRunning == isRunning); protected override bool AllowFail => true; From 5c2ea0b1a719348b5a1ae0bd251d3aecb45fa250 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 01:14:46 +0900 Subject: [PATCH 1102/5608] Move dispose to end of file --- osu.Game/Screens/Play/GameplayClockContainer.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 4b35e90f68..6a03271b86 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -86,12 +86,6 @@ namespace osu.Game.Screens.Play GameplayClock.IsPaused.BindTo(IsPaused); } - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - (sourceClock as IAdjustableAudioComponent)?.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); - } - private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset; private readonly BindableDouble pauseFreqAdjust = new BindableDouble(1); @@ -154,7 +148,7 @@ namespace osu.Game.Screens.Play public void Stop() { - this.TransformBindableTo(pauseFreqAdjust, 0, 200, Easing.Out).OnComplete(_ => { adjustableClock.Stop(); }); + this.TransformBindableTo(pauseFreqAdjust, 0, 200, Easing.Out).OnComplete(_ => adjustableClock.Stop()); IsPaused.Value = true; } @@ -187,5 +181,11 @@ namespace osu.Game.Screens.Play foreach (var mod in mods.OfType()) mod.ApplyToClock(sourceClock); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + (sourceClock as IAdjustableAudioComponent)?.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); + } } } From 4f6978f2aa59c7a95c9b7706ad42f6fe6c258643 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 9 Jun 2019 20:01:19 +0200 Subject: [PATCH 1103/5608] Apply review suggestions. --- osu.Game/Screens/OsuScreen.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 3f98595d0e..3b5e0fd0d6 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -64,17 +64,17 @@ namespace osu.Game.Screens /// protected UserActivity ScreenActivity { - get => activity; + get => screenActivity; set { - if (value == activity) return; + if (value == screenActivity) return; - activity = value; - setUserActivity(activity); + screenActivity = value; + setUserActivity(screenActivity); } } - private UserActivity activity; + private UserActivity screenActivity; /// /// Whether to disallow changes to game-wise Beatmap/Ruleset bindables for this screen (and all children). @@ -122,11 +122,11 @@ namespace osu.Game.Screens Anchor = Anchor.Centre; Origin = Anchor.Centre; - activity = null; + screenActivity = null; } [BackgroundDependencyLoader(true)] - private void load(OsuGame osu, AudioManager audio, IAPIProvider provider) + private void load(OsuGame osu, AudioManager audio) { sampleExit = audio.Samples.Get(@"UI/screen-back"); } @@ -152,7 +152,7 @@ namespace osu.Game.Screens sampleExit?.Play(); applyArrivingDefaults(true); - setUserActivity(activity); + setUserActivity(screenActivity); base.OnResuming(last); } From 9b8540d8180b9485c13f3043226f1840c07e8df6 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Mon, 10 Jun 2019 03:35:00 +0300 Subject: [PATCH 1104/5608] Add a testcase --- .../TestSceneToolbarRulesetSelector.cs | 35 +++++++++++++++++++ .../Toolbar/ToolbarRulesetSelector.cs | 4 +-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs new file mode 100644 index 0000000000..1a0e712337 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Game.Overlays.Toolbar; +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneToolbarRulesetSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ToolbarRulesetSelector), + typeof(ToolbarRulesetButton), + }; + + public TestSceneToolbarRulesetSelector() + { + ToolbarRulesetSelector selector; + + Add(new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.X, + Height = Toolbar.HEIGHT, + Child = selector = new ToolbarRulesetSelector() + + }); + } + } +} diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 8590c9fbc0..f8ac610a3a 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -40,7 +40,7 @@ namespace osu.Game.Overlays.Toolbar RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; - AddRangeInternal(new Drawable[] + AddRangeInternal(new[] { new OpaqueBackground { @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Toolbar }, modeButtonLine = new Container { - Size = new Vector2(padding* 2 + ToolbarButton.WIDTH, 3), + Size = new Vector2(padding * 2 + ToolbarButton.WIDTH, 3), Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft, Masking = true, From ff9dc189286ec6e8f9f48a14b12e1312ccb7839f Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Mon, 10 Jun 2019 03:54:15 +0300 Subject: [PATCH 1105/5608] TestCaseImprovements --- .../Visual/UserInterface/TestSceneToolbarRulesetSelector.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs index 1a0e712337..7d0491aa60 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs @@ -6,6 +6,8 @@ using osu.Game.Overlays.Toolbar; using System; using System.Collections.Generic; using osu.Framework.Graphics; +using System.Linq; +using osu.Framework.MathUtils; namespace osu.Game.Tests.Visual.UserInterface { @@ -28,7 +30,11 @@ namespace osu.Game.Tests.Visual.UserInterface AutoSizeAxes = Axes.X, Height = Toolbar.HEIGHT, Child = selector = new ToolbarRulesetSelector() + }); + AddStep("Select random", () => + { + selector.Current.Value = selector.Items.ElementAt(RNG.Next(selector.Items.Count())); }); } } From ec8c09dd39f86c21449638f994df3ae6449e19c2 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Mon, 10 Jun 2019 04:36:34 +0300 Subject: [PATCH 1106/5608] Fix unability to mannualy switch ruleset --- osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs index efb540cd45..defe1da5bf 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK.Graphics; using osu.Framework.Graphics; +using osu.Framework.Input.Events; namespace osu.Game.Overlays.Toolbar { @@ -59,6 +60,12 @@ namespace osu.Game.Overlays.Toolbar } } + protected override bool OnClick(ClickEvent e) + { + Parent.Click(); + return base.OnClick(e); + } + protected override void LoadComplete() { base.LoadComplete(); From 0ebd29c8510534a973a98b3e14c86ccccfb0e0cd Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Sun, 9 Jun 2019 21:15:05 -0500 Subject: [PATCH 1107/5608] Add @miterosan's suggestions --- osu.Android/Properties/AndroidManifest.xml | 14 +++++++------- .../MainActivity.cs | 3 +-- .../MainActivity.cs | 3 +-- .../MainActivity.cs | 3 +-- .../MainActivity.cs | 3 +-- osu.Game.Tests.Android/MainActivity.cs | 3 +-- 6 files changed, 12 insertions(+), 17 deletions(-) diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index 549ba9f46a..6f77560e01 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -1,10 +1,10 @@  - - - - - - - + + + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs index 8430a88f15..d918305f3d 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs @@ -11,7 +11,6 @@ namespace osu.Game.Rulesets.Catch.Tests.Android [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] public class MainActivity : AndroidGameActivity { - protected override Framework.Game CreateGame() - => new OsuTestBrowser(); + protected override Framework.Game CreateGame() => new OsuTestBrowser(); } } diff --git a/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs index 0f1d6756bc..0a3f05ae54 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs @@ -11,7 +11,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Android [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] public class MainActivity : AndroidGameActivity { - protected override Framework.Game CreateGame() - => new OsuTestBrowser(); + protected override Framework.Game CreateGame() => new OsuTestBrowser(); } } diff --git a/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs index d6f2ec546d..e6c508d99e 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs @@ -11,7 +11,6 @@ namespace osu.Game.Rulesets.Osu.Tests.Android [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] public class MainActivity : AndroidGameActivity { - protected override Framework.Game CreateGame() - => new OsuTestBrowser(); + protected override Framework.Game CreateGame() => new OsuTestBrowser(); } } diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs index cc92ad7080..1128a0d37f 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs @@ -11,7 +11,6 @@ namespace osu.Game.Rulesets.Taiko.Tests.Android [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] public class MainActivity : AndroidGameActivity { - protected override Framework.Game CreateGame() - => new OsuTestBrowser(); + protected override Framework.Game CreateGame() => new OsuTestBrowser(); } } diff --git a/osu.Game.Tests.Android/MainActivity.cs b/osu.Game.Tests.Android/MainActivity.cs index 6f68c372ef..0695c8e37b 100644 --- a/osu.Game.Tests.Android/MainActivity.cs +++ b/osu.Game.Tests.Android/MainActivity.cs @@ -10,7 +10,6 @@ namespace osu.Game.Tests.Android [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize, HardwareAccelerated = true)] public class MainActivity : AndroidGameActivity { - protected override Framework.Game CreateGame() - => new OsuTestBrowser(); + protected override Framework.Game CreateGame() => new OsuTestBrowser(); } } From f090e292c974c2147f7f34b3cc79a5461e7df817 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 28 May 2019 18:59:21 +0900 Subject: [PATCH 1108/5608] Move ArchiveModelManager import process to async flow --- .../Beatmaps/IO/ImportBeatmapTest.cs | 50 +++--- osu.Game.Tests/Scores/IO/ImportScoreTest.cs | 30 ++-- .../TestSceneBackgroundScreenBeatmap.cs | 2 +- ...tSceneUpdateableBeatmapBackgroundSprite.cs | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 5 + osu.Game/Beatmaps/BeatmapManager.cs | 163 +++++++++++++----- osu.Game/Database/ArchiveModelManager.cs | 158 +++++++++-------- osu.Game/Database/ICanAcceptFiles.cs | 4 +- osu.Game/IPC/ArchiveImportIPCChannel.cs | 2 +- osu.Game/OsuGameBase.cs | 5 +- .../Notifications/ProgressNotification.cs | 7 + osu.Game/Screens/Menu/Intro.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Skinning/SkinManager.cs | 6 +- 14 files changed, 273 insertions(+), 165 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index f020c2a805..4c9260f640 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -21,14 +21,14 @@ namespace osu.Game.Tests.Beatmaps.IO public class ImportBeatmapTest { [Test] - public void TestImportWhenClosed() + public async Task TestImportWhenClosed() { //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWhenClosed")) { try { - LoadOszIntoOsu(loadOsu(host)); + await LoadOszIntoOsu(loadOsu(host)); } finally { @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Beatmaps.IO } [Test] - public void TestImportThenDelete() + public async Task TestImportThenDelete() { //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenDelete")) @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = loadOsu(host); - var imported = LoadOszIntoOsu(osu); + var imported = await LoadOszIntoOsu(osu); deleteBeatmapSet(imported, osu); } @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Beatmaps.IO } [Test] - public void TestImportThenImport() + public async Task TestImportThenImport() { //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenImport")) @@ -68,8 +68,8 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = loadOsu(host); - var imported = LoadOszIntoOsu(osu); - var importedSecondTime = LoadOszIntoOsu(osu); + var imported = await LoadOszIntoOsu(osu); + var importedSecondTime = await LoadOszIntoOsu(osu); // check the newly "imported" beatmap is actually just the restored previous import. since it matches hash. Assert.IsTrue(imported.ID == importedSecondTime.ID); @@ -88,7 +88,7 @@ namespace osu.Game.Tests.Beatmaps.IO } [Test] - public void TestRollbackOnFailure() + public async Task TestRollbackOnFailure() { //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestRollbackOnFailure")) @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Beatmaps.IO manager.ItemAdded += (_, __) => fireCount++; manager.ItemRemoved += _ => fireCount++; - var imported = LoadOszIntoOsu(osu); + var imported = await LoadOszIntoOsu(osu); Assert.AreEqual(0, fireCount -= 1); @@ -132,7 +132,7 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.AreEqual(12, manager.QueryBeatmaps(_ => true).ToList().Count); // this will trigger purging of the existing beatmap (online set id match) but should rollback due to broken osu. - manager.Import(breakTemp); + await manager.Import(breakTemp); // no events should be fired in the case of a rollback. Assert.AreEqual(0, fireCount); @@ -149,7 +149,7 @@ namespace osu.Game.Tests.Beatmaps.IO } [Test] - public void TestImportThenImportDifferentHash() + public async Task TestImportThenImportDifferentHash() { //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenImportDifferentHash")) @@ -159,12 +159,12 @@ namespace osu.Game.Tests.Beatmaps.IO var osu = loadOsu(host); var manager = osu.Dependencies.Get(); - var imported = LoadOszIntoOsu(osu); + var imported = await LoadOszIntoOsu(osu); imported.Hash += "-changed"; manager.Update(imported); - var importedSecondTime = LoadOszIntoOsu(osu); + var importedSecondTime = await LoadOszIntoOsu(osu); Assert.IsTrue(imported.ID != importedSecondTime.ID); Assert.IsTrue(imported.Beatmaps.First().ID < importedSecondTime.Beatmaps.First().ID); @@ -181,7 +181,7 @@ namespace osu.Game.Tests.Beatmaps.IO } [Test] - public void TestImportThenDeleteThenImport() + public async Task TestImportThenDeleteThenImport() { //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenDeleteThenImport")) @@ -190,11 +190,11 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = loadOsu(host); - var imported = LoadOszIntoOsu(osu); + var imported = await LoadOszIntoOsu(osu); deleteBeatmapSet(imported, osu); - var importedSecondTime = LoadOszIntoOsu(osu); + var importedSecondTime = await LoadOszIntoOsu(osu); // check the newly "imported" beatmap is actually just the restored previous import. since it matches hash. Assert.IsTrue(imported.ID == importedSecondTime.ID); @@ -209,7 +209,7 @@ namespace osu.Game.Tests.Beatmaps.IO [TestCase(true)] [TestCase(false)] - public void TestImportThenDeleteThenImportWithOnlineIDMismatch(bool set) + public async Task TestImportThenDeleteThenImportWithOnlineIDMismatch(bool set) { //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. using (HeadlessGameHost host = new CleanRunHeadlessGameHost($"TestImportThenDeleteThenImport-{set}")) @@ -218,7 +218,7 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = loadOsu(host); - var imported = LoadOszIntoOsu(osu); + var imported = await LoadOszIntoOsu(osu); if (set) imported.OnlineBeatmapSetID = 1234; @@ -229,7 +229,7 @@ namespace osu.Game.Tests.Beatmaps.IO deleteBeatmapSet(imported, osu); - var importedSecondTime = LoadOszIntoOsu(osu); + var importedSecondTime = await LoadOszIntoOsu(osu); // check the newly "imported" beatmap has been reimported due to mismatch (even though hashes matched) Assert.IsTrue(imported.ID != importedSecondTime.ID); @@ -243,7 +243,7 @@ namespace osu.Game.Tests.Beatmaps.IO } [Test] - public void TestImportWithDuplicateBeatmapIDs() + public async Task TestImportWithDuplicateBeatmapIDs() { //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWithDuplicateBeatmapID")) @@ -284,7 +284,7 @@ namespace osu.Game.Tests.Beatmaps.IO var manager = osu.Dependencies.Get(); - var imported = manager.Import(toImport); + var imported = await manager.Import(toImport); Assert.NotNull(imported); Assert.AreEqual(null, imported.Beatmaps[0].OnlineBeatmapID); @@ -330,7 +330,7 @@ namespace osu.Game.Tests.Beatmaps.IO } [Test] - public void TestImportWhenFileOpen() + public async Task TestImportWhenFileOpen() { using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWhenFileOpen")) { @@ -339,7 +339,7 @@ namespace osu.Game.Tests.Beatmaps.IO var osu = loadOsu(host); var temp = TestResources.GetTestBeatmapForImport(); using (File.OpenRead(temp)) - osu.Dependencies.Get().Import(temp); + await osu.Dependencies.Get().Import(temp); ensureLoaded(osu); File.Delete(temp); Assert.IsFalse(File.Exists(temp), "We likely held a read lock on the file when we shouldn't"); @@ -351,13 +351,13 @@ namespace osu.Game.Tests.Beatmaps.IO } } - public static BeatmapSetInfo LoadOszIntoOsu(OsuGameBase osu, string path = null) + public static async Task LoadOszIntoOsu(OsuGameBase osu, string path = null) { var temp = path ?? TestResources.GetTestBeatmapForImport(); var manager = osu.Dependencies.Get(); - manager.Import(temp); + await manager.Import(temp); var imported = manager.GetAllUsableBeatmapSets(); diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs index e39f18c3cd..4babb07213 100644 --- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs @@ -23,13 +23,13 @@ namespace osu.Game.Tests.Scores.IO public class ImportScoreTest { [Test] - public void TestBasicImport() + public async Task TestBasicImport() { using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestBasicImport")) { try { - var osu = loadOsu(host); + var osu = await loadOsu(host); var toImport = new ScoreInfo { @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Scores.IO OnlineScoreID = 12345, }; - var imported = loadIntoOsu(osu, toImport); + var imported = await loadIntoOsu(osu, toImport); Assert.AreEqual(toImport.Rank, imported.Rank); Assert.AreEqual(toImport.TotalScore, imported.TotalScore); @@ -62,20 +62,20 @@ namespace osu.Game.Tests.Scores.IO } [Test] - public void TestImportMods() + public async Task TestImportMods() { using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportMods")) { try { - var osu = loadOsu(host); + var osu = await loadOsu(host); var toImport = new ScoreInfo { Mods = new Mod[] { new OsuModHardRock(), new OsuModDoubleTime() }, }; - var imported = loadIntoOsu(osu, toImport); + var imported = await loadIntoOsu(osu, toImport); Assert.IsTrue(imported.Mods.Any(m => m is OsuModHardRock)); Assert.IsTrue(imported.Mods.Any(m => m is OsuModDoubleTime)); @@ -88,13 +88,13 @@ namespace osu.Game.Tests.Scores.IO } [Test] - public void TestImportStatistics() + public async Task TestImportStatistics() { using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportStatistics")) { try { - var osu = loadOsu(host); + var osu = await loadOsu(host); var toImport = new ScoreInfo { @@ -105,7 +105,7 @@ namespace osu.Game.Tests.Scores.IO } }; - var imported = loadIntoOsu(osu, toImport); + var imported = await loadIntoOsu(osu, toImport); Assert.AreEqual(toImport.Statistics[HitResult.Perfect], imported.Statistics[HitResult.Perfect]); Assert.AreEqual(toImport.Statistics[HitResult.Miss], imported.Statistics[HitResult.Miss]); @@ -117,7 +117,7 @@ namespace osu.Game.Tests.Scores.IO } } - private ScoreInfo loadIntoOsu(OsuGameBase osu, ScoreInfo score) + private async Task loadIntoOsu(OsuGameBase osu, ScoreInfo score) { var beatmapManager = osu.Dependencies.Get(); @@ -125,20 +125,24 @@ namespace osu.Game.Tests.Scores.IO score.Ruleset = new OsuRuleset().RulesetInfo; var scoreManager = osu.Dependencies.Get(); - scoreManager.Import(score); + await scoreManager.Import(score); return scoreManager.GetAllUsableScores().First(); } - private OsuGameBase loadOsu(GameHost host) + private async Task loadOsu(GameHost host) { var osu = new OsuGameBase(); + +#pragma warning disable 4014 Task.Run(() => host.Run(osu)); +#pragma warning restore 4014 + waitForOrAssert(() => osu.IsLoaded, @"osu! failed to start in a reasonable amount of time"); var beatmapFile = TestResources.GetTestBeatmapForImport(); var beatmapManager = osu.Dependencies.Get(); - beatmapManager.Import(beatmapFile); + await beatmapManager.Import(beatmapFile); return osu; } diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs index 7104a420a3..8b941e4633 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs @@ -72,7 +72,7 @@ namespace osu.Game.Tests.Visual.Background Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, audio, host, Beatmap.Default)); Dependencies.Cache(new OsuConfigManager(LocalStorage)); - manager.Import(TestResources.GetTestBeatmapForImport()); + manager.Import(TestResources.GetTestBeatmapForImport()).Wait(); Beatmap.SetDefault(); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs index f59458ef8d..c361598354 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.UserInterface this.api = api; this.rulesets = rulesets; - testBeatmap = ImportBeatmapTest.LoadOszIntoOsu(osu); + testBeatmap = ImportBeatmapTest.LoadOszIntoOsu(osu).Result; } [Test] diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 11d70ee7be..403ae16885 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -18,4 +18,9 @@ + + + ..\..\..\..\..\usr\local\share\dotnet\sdk\NuGetFallbackFolder\microsoft.win32.registry\4.5.0\ref\netstandard2.0\Microsoft.Win32.Registry.dll + + \ No newline at end of file diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b6fe7f88fa..f5ef52a93b 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -2,10 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Linq.Expressions; +using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using osu.Framework.Audio; @@ -14,6 +16,7 @@ using osu.Framework.Extensions; using osu.Framework.Graphics.Textures; using osu.Framework.Logging; using osu.Framework.Platform; +using osu.Framework.Threading; using osu.Game.Beatmaps.Formats; using osu.Game.Database; using osu.Game.IO.Archives; @@ -72,6 +75,8 @@ namespace osu.Game.Beatmaps private readonly List currentDownloads = new List(); + private readonly BeatmapUpdateQueue updateQueue; + public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, AudioManager audioManager, GameHost host = null, WorkingBeatmap defaultBeatmap = null) : base(storage, contextFactory, new BeatmapStore(contextFactory), host) @@ -86,9 +91,11 @@ namespace osu.Game.Beatmaps beatmaps = (BeatmapStore)ModelStore; beatmaps.BeatmapHidden += b => BeatmapHidden?.Invoke(b); beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b); + + updateQueue = new BeatmapUpdateQueue(api); } - protected override void Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive) + protected override async Task Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive, CancellationToken cancellationToken = default) { if (archive != null) beatmapSet.Beatmaps = createBeatmapDifficulties(archive); @@ -104,8 +111,7 @@ namespace osu.Game.Beatmaps validateOnlineIds(beatmapSet); - foreach (BeatmapInfo b in beatmapSet.Beatmaps) - fetchAndPopulateOnlineValues(b); + await Task.WhenAll(beatmapSet.Beatmaps.Select(b => updateQueue.Enqueue(new UpdateItem(b, cancellationToken)).Task).ToArray()); } protected override void PreImport(BeatmapSetInfo beatmapSet) @@ -181,10 +187,10 @@ namespace osu.Game.Beatmaps request.Success += filename => { - Task.Factory.StartNew(() => + Task.Factory.StartNew(async () => { // This gets scheduled back to the update thread, but we want the import to run in the background. - Import(downloadNotification, filename); + await Import(downloadNotification, filename); currentDownloads.Remove(request); }, TaskCreationOptions.LongRunning); }; @@ -381,47 +387,6 @@ namespace osu.Game.Beatmaps return beatmapInfos; } - /// - /// Query the API to populate missing values like OnlineBeatmapID / OnlineBeatmapSetID or (Rank-)Status. - /// - /// The beatmap to populate. - /// Whether to re-query if the provided beatmap already has populated values. - /// True if population was successful. - private bool fetchAndPopulateOnlineValues(BeatmapInfo beatmap, bool force = false) - { - if (api?.State != APIState.Online) - return false; - - if (!force && beatmap.OnlineBeatmapID != null && beatmap.BeatmapSet.OnlineBeatmapSetID != null - && beatmap.Status != BeatmapSetOnlineStatus.None && beatmap.BeatmapSet.Status != BeatmapSetOnlineStatus.None) - return true; - - Logger.Log("Attempting online lookup for the missing values...", LoggingTarget.Database); - - try - { - var req = new GetBeatmapRequest(beatmap); - - req.Perform(api); - - var res = req.Result; - - Logger.Log($"Successfully mapped to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}.", LoggingTarget.Database); - - beatmap.Status = res.Status; - beatmap.BeatmapSet.Status = res.BeatmapSet.Status; - beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID; - beatmap.OnlineBeatmapID = res.OnlineBeatmapID; - - return true; - } - catch (Exception e) - { - Logger.Log($"Failed ({e})", LoggingTarget.Database); - return false; - } - } - /// /// A dummy WorkingBeatmap for the purpose of retrieving a beatmap for star difficulty calculation. /// @@ -455,5 +420,111 @@ namespace osu.Game.Beatmaps public override bool IsImportant => false; } } + + private class BeatmapUpdateQueue + { + private readonly IAPIProvider api; + private readonly Queue queue = new Queue(); + + private int activeThreads; + + public BeatmapUpdateQueue(IAPIProvider api) + { + this.api = api; + } + + public UpdateItem Enqueue(UpdateItem item) + { + lock (queue) + { + queue.Enqueue(item); + + if (activeThreads >= 16) + return item; + + new Thread(runWork) { IsBackground = true }.Start(); + activeThreads++; + } + + return item; + } + + private void runWork() + { + while (true) + { + UpdateItem toProcess; + + lock (queue) + { + if (queue.Count == 0) + break; + + toProcess = queue.Dequeue(); + } + + toProcess.PerformUpdate(api); + } + + lock (queue) + activeThreads--; + } + } + + private class UpdateItem + { + public Task Task => tcs.Task; + + private readonly BeatmapInfo beatmap; + private readonly CancellationToken cancellationToken; + + private readonly TaskCompletionSource tcs = new TaskCompletionSource(); + + public UpdateItem(BeatmapInfo beatmap, CancellationToken cancellationToken) + { + this.beatmap = beatmap; + this.cancellationToken = cancellationToken; + } + + public void PerformUpdate(IAPIProvider api) + { + if (cancellationToken.IsCancellationRequested) + { + tcs.SetCanceled(); + return; + } + + if (api?.State != APIState.Online) + { + tcs.SetResult(false); + return; + } + + Logger.Log("Attempting online lookup for the missing values...", LoggingTarget.Database); + + var req = new GetBeatmapRequest(beatmap); + + req.Success += res => + { + Logger.Log($"Successfully mapped to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}.", LoggingTarget.Database); + + beatmap.Status = res.Status; + beatmap.BeatmapSet.Status = res.BeatmapSet.Status; + beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID; + beatmap.OnlineBeatmapID = res.OnlineBeatmapID; + + tcs.SetResult(true); + }; + + req.Failure += e => + { + Logger.Log($"Failed ({e})", LoggingTarget.Database); + + tcs.SetResult(false); + }; + + req.Perform(api); + } + } } } diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 54dbae9ddc..afc614772e 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -5,14 +5,17 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using osu.Framework; using osu.Framework.Extensions; +using osu.Framework.Extensions.TypeExtensions; using osu.Framework.IO.File; using osu.Framework.Logging; using osu.Framework.Platform; +using osu.Framework.Threading; using osu.Game.IO; using osu.Game.IO.Archives; using osu.Game.IPC; @@ -109,8 +112,11 @@ namespace osu.Game.Database a.Invoke(); } + private readonly ThreadedTaskScheduler importScheduler; + protected ArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, MutableDatabaseBackedStoreWithFileIncludes modelStore, IIpcHost importHost = null) { + importScheduler = new ThreadedTaskScheduler(16, $"{GetType().ReadableName()}.Import"); ContextFactory = contextFactory; ModelStore = modelStore; @@ -130,92 +136,84 @@ namespace osu.Game.Database /// This will post notifications tracking progress. /// /// One or more archive locations on disk. - public void Import(params string[] paths) + public async Task Import(params string[] paths) { var notification = new ProgressNotification { State = ProgressNotificationState.Active }; PostNotification?.Invoke(notification); - Import(notification, paths); + + await Import(notification, paths); } - protected void Import(ProgressNotification notification, params string[] paths) + protected async Task Import(ProgressNotification notification, params string[] paths) { notification.Progress = 0; notification.Text = "Import is initialising..."; var term = $"{typeof(TModel).Name.Replace("Info", "").ToLower()}"; - List imported = new List(); + var tasks = new List(); int current = 0; foreach (string path in paths) { - if (notification.State == ProgressNotificationState.Cancelled) - // user requested abort - return; - - try + tasks.Add(Import(path, notification.CancellationToken).ContinueWith(t => { - var text = "Importing "; - - if (path.Length > 1) - text += $"{++current} of {paths.Length} {term}s.."; - else - text += $"{term}.."; - - // only show the filename if it isn't a temporary one (as those look ugly). - if (!path.Contains(Path.GetTempPath())) - text += $"\n{Path.GetFileName(path)}"; - - notification.Text = text; - - imported.Add(Import(path)); - - notification.Progress = (float)current / paths.Length; - } - catch (Exception e) - { - e = e.InnerException ?? e; - Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})"); - } - } - - if (imported.Count == 0) - { - notification.Text = "Import failed!"; - notification.State = ProgressNotificationState.Cancelled; - } - else - { - notification.CompletionText = imported.Count == 1 - ? $"Imported {imported.First()}!" - : $"Imported {current} {term}s!"; - - if (imported.Count > 0 && PresentImport != null) - { - notification.CompletionText += " Click to view."; - notification.CompletionClickAction = () => + lock (notification) { - PresentImport?.Invoke(imported); - return true; - }; - } + current++; - notification.State = ProgressNotificationState.Completed; + notification.Text = $"Imported {current} of {paths.Length} {term}s"; + notification.Progress = (float)current / paths.Length; + } + + if (t.Exception != null) + { + var e = t.Exception.InnerException ?? t.Exception; + Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})"); + } + })); } + + await Task.WhenAll(tasks); + + // if (imported.Count == 0) + // { + // notification.Text = "Import failed!"; + // notification.State = ProgressNotificationState.Cancelled; + // } + // else + // { + // notification.CompletionText = imported.Count == 1 + // ? $"Imported {imported.First()}!" + // : $"Imported {current} {term}s!"; + // + // if (imported.Count > 0 && PresentImport != null) + // { + // notification.CompletionText += " Click to view."; + // notification.CompletionClickAction = () => + // { + // PresentImport?.Invoke(imported); + // return true; + // }; + // } + // + // notification.State = ProgressNotificationState.Completed; + // } } /// /// Import one from the filesystem and delete the file on success. /// /// The archive location on disk. + /// An optional cancellation token. /// The imported model, if successful. - public TModel Import(string path) + public async Task Import(string path, CancellationToken cancellationToken = default) { TModel import; using (ArchiveReader reader = getReaderFrom(path)) - import = Import(reader); + import = await Import(reader, cancellationToken); // We may or may not want to delete the file depending on where it is stored. // e.g. reconstructing/repairing database with items from default storage. @@ -243,7 +241,8 @@ namespace osu.Game.Database /// Import an item from an . /// /// The archive to be imported. - public TModel Import(ArchiveReader archive) + /// An optional cancellation token. + public async Task Import(ArchiveReader archive, CancellationToken cancellationToken = default) { try { @@ -253,7 +252,7 @@ namespace osu.Game.Database model.Hash = computeHash(archive); - return Import(model, archive); + return await Import(model, archive, cancellationToken); } catch (Exception e) { @@ -288,7 +287,8 @@ namespace osu.Game.Database /// /// The model to be imported. /// An optional archive to use for model population. - public TModel Import(TModel item, ArchiveReader archive = null) + /// An optional cancellation token. + public async Task Import(TModel item, ArchiveReader archive = null, CancellationToken cancellationToken = default) => await Task.Factory.StartNew(async () => { delayEvents(); @@ -296,17 +296,31 @@ namespace osu.Game.Database { Logger.Log($"Importing {item}...", LoggingTarget.Database); + if (archive != null) + item.Files = createFileInfos(archive, Files); + + var localItem = item; + + try + { + await Populate(item, archive, cancellationToken); + } + catch (TaskCanceledException) + { + return item = null; + } + finally + { + if (!Delete(localItem)) + Files.Dereference(localItem.Files.Select(f => f.FileInfo).ToArray()); + } + using (var write = ContextFactory.GetForWrite()) // used to share a context for full import. keep in mind this will block all writes. { try { if (!write.IsTransactionLeader) throw new InvalidOperationException($"Ensure there is no parent transaction so errors can correctly be handled by {this}"); - if (archive != null) - item.Files = createFileInfos(archive, Files); - - Populate(item, archive); - var existing = CheckForExisting(item); if (existing != null) @@ -332,6 +346,9 @@ namespace osu.Game.Database } catch (Exception e) { + if (!Delete(item)) + Files.Dereference(item.Files.Select(f => f.FileInfo).ToArray()); + write.Errors.Add(e); throw; } @@ -351,7 +368,7 @@ namespace osu.Game.Database } return item; - } + }, CancellationToken.None, TaskCreationOptions.None, importScheduler).Unwrap(); /// /// Perform an update of the specified item. @@ -516,24 +533,24 @@ namespace osu.Game.Database /// /// This is a temporary method and will likely be replaced by a full-fledged (and more correctly placed) migration process in the future. /// - public Task ImportFromStableAsync() + public async Task ImportFromStableAsync() { var stable = GetStableStorage?.Invoke(); if (stable == null) { Logger.Log("No osu!stable installation available!", LoggingTarget.Information, LogLevel.Error); - return Task.CompletedTask; + return; } if (!stable.ExistsDirectory(ImportFromStablePath)) { // This handles situations like when the user does not have a Skins folder Logger.Log($"No {ImportFromStablePath} folder available in osu!stable installation", LoggingTarget.Information, LogLevel.Error); - return Task.CompletedTask; + return; } - return Task.Factory.StartNew(() => Import(stable.GetDirectories(ImportFromStablePath).Select(f => stable.GetFullPath(f)).ToArray()), TaskCreationOptions.LongRunning); + await Task.Run(async () => await Import(stable.GetDirectories(ImportFromStablePath).Select(f => stable.GetFullPath(f)).ToArray())); } #endregion @@ -552,9 +569,8 @@ namespace osu.Game.Database /// /// The model to populate. /// The archive to use as a reference for population. May be null. - protected virtual void Populate(TModel model, [CanBeNull] ArchiveReader archive) - { - } + /// An optional cancellation token. + protected virtual async Task Populate(TModel model, [CanBeNull] ArchiveReader archive, CancellationToken cancellationToken = default) => await Task.CompletedTask; /// /// Perform any final actions before the import to database executes. diff --git a/osu.Game/Database/ICanAcceptFiles.cs b/osu.Game/Database/ICanAcceptFiles.cs index f55d0c389e..b9f882468d 100644 --- a/osu.Game/Database/ICanAcceptFiles.cs +++ b/osu.Game/Database/ICanAcceptFiles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Threading.Tasks; + namespace osu.Game.Database { /// @@ -12,7 +14,7 @@ namespace osu.Game.Database /// Import the specified paths. /// /// The files which should be imported. - void Import(params string[] paths); + Task Import(params string[] paths); /// /// An array of accepted file extensions (in the standard format of ".abc"). diff --git a/osu.Game/IPC/ArchiveImportIPCChannel.cs b/osu.Game/IPC/ArchiveImportIPCChannel.cs index fc747cd446..484db932f8 100644 --- a/osu.Game/IPC/ArchiveImportIPCChannel.cs +++ b/osu.Game/IPC/ArchiveImportIPCChannel.cs @@ -38,7 +38,7 @@ namespace osu.Game.IPC } if (importer.HandledExtensions.Contains(Path.GetExtension(path)?.ToLowerInvariant())) - importer.Import(path); + await importer.Import(path); } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index f9128687d6..d6b8caaf5b 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; @@ -268,13 +269,13 @@ namespace osu.Game private readonly List fileImporters = new List(); - public void Import(params string[] paths) + public async Task Import(params string[] paths) { var extension = Path.GetExtension(paths.First())?.ToLowerInvariant(); foreach (var importer in fileImporters) if (importer.HandledExtensions.Contains(extension)) - importer.Import(paths); + await importer.Import(paths); } public string[] HandledExtensions => fileImporters.SelectMany(i => i.HandledExtensions).ToArray(); diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index 857a0bda9e..c8e081d29f 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Threading; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -36,6 +37,10 @@ namespace osu.Game.Overlays.Notifications State = state; } + private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); + + public CancellationToken CancellationToken => cancellationTokenSource.Token; + public virtual ProgressNotificationState State { get => state; @@ -62,6 +67,8 @@ namespace osu.Game.Overlays.Notifications break; case ProgressNotificationState.Cancelled: + cancellationTokenSource.Cancel(); + Light.Colour = colourCancelled; Light.Pulsate = false; progressBar.Active = false; diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index 98a2fe8f13..cf5d247482 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -66,7 +66,7 @@ namespace osu.Game.Screens.Menu if (setInfo == null) { // we need to import the default menu background beatmap - setInfo = beatmaps.Import(new ZipArchiveReader(game.Resources.GetStream(@"Tracks/circles.osz"), "circles.osz")); + setInfo = beatmaps.Import(new ZipArchiveReader(game.Resources.GetStream(@"Tracks/circles.osz"), "circles.osz")).Result; setInfo.Protected = true; beatmaps.Update(setInfo); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d8389fa6d9..949f9e5ff2 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -279,7 +279,7 @@ namespace osu.Game.Screens.Play var score = CreateScore(); if (DrawableRuleset.ReplayScore == null) - scoreManager.Import(score); + scoreManager.Import(score).Wait(); this.Push(CreateResults(score)); diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 3a4d44f608..73cc47ea47 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -5,6 +5,8 @@ using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -71,9 +73,9 @@ namespace osu.Game.Skinning protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name }; - protected override void Populate(SkinInfo model, ArchiveReader archive) + protected override async Task Populate(SkinInfo model, ArchiveReader archive, CancellationToken cancellationToken = default) { - base.Populate(model, archive); + await base.Populate(model, archive, cancellationToken); Skin reference = getSkin(model); From 600503ec8ebdb6233beab64b0faa53f02b91af4e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 12:46:21 +0900 Subject: [PATCH 1109/5608] Use Task.Run/Wait to avoid warnings --- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 4 ++-- osu.Game/Screens/Select/SongSelect.cs | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index ebee358730..c2e8078bd6 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -210,7 +210,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("start not requested", () => !startRequested); } - private void importForRuleset(int id) => AddStep($"import test map for ruleset {id}", () => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray()))); + private void importForRuleset(int id) => AddStep($"import test map for ruleset {id}", () => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray())).Wait()); private static int importId; private int getImportId() => ++importId; @@ -232,7 +232,7 @@ namespace osu.Game.Tests.Visual.SongSelect var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray(); for (int i = 0; i < 100; i += 10) - manager.Import(createTestBeatmapSet(i, usableRulesets)); + manager.Import(createTestBeatmapSet(i, usableRulesets)).Wait(); }); } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 6d5be607f4..196d655851 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -32,6 +32,7 @@ using osuTK.Input; using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using osu.Framework.Graphics.Sprites; namespace osu.Game.Screens.Select @@ -256,8 +257,8 @@ namespace osu.Game.Screens.Select if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable) dialogOverlay.Push(new ImportFromStablePopup(() => { - beatmaps.ImportFromStableAsync(); - skins.ImportFromStableAsync(); + Task.Run(beatmaps.ImportFromStableAsync); + Task.Run(skins.ImportFromStableAsync); })); }); } From b4d2d0bd0b245cba425d9e5d981e3831d9269931 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 13:19:58 +0900 Subject: [PATCH 1110/5608] Simplify and combine concurrency of ArchiveModelManager --- osu.Game/Beatmaps/BeatmapManager.cs | 77 ++----------------- osu.Game/Database/ArchiveModelManager.cs | 96 ++++++++++++------------ 2 files changed, 57 insertions(+), 116 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index f5ef52a93b..9e7b6d7971 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -111,7 +110,7 @@ namespace osu.Game.Beatmaps validateOnlineIds(beatmapSet); - await Task.WhenAll(beatmapSet.Beatmaps.Select(b => updateQueue.Enqueue(new UpdateItem(b, cancellationToken)).Task).ToArray()); + await Task.WhenAll(beatmapSet.Beatmaps.Select(b => updateQueue.Perform(b, cancellationToken)).ToArray()); } protected override void PreImport(BeatmapSetInfo beatmapSet) @@ -424,81 +423,24 @@ namespace osu.Game.Beatmaps private class BeatmapUpdateQueue { private readonly IAPIProvider api; - private readonly Queue queue = new Queue(); - private int activeThreads; + private readonly ThreadedTaskScheduler updateScheduler = new ThreadedTaskScheduler(4); public BeatmapUpdateQueue(IAPIProvider api) { this.api = api; } - public UpdateItem Enqueue(UpdateItem item) + public Task Perform(BeatmapInfo beatmap, CancellationToken cancellationToken) + => Task.Factory.StartNew(() => perform(beatmap, cancellationToken), cancellationToken, TaskCreationOptions.HideScheduler, updateScheduler); + + private void perform(BeatmapInfo beatmap, CancellationToken cancellation) { - lock (queue) - { - queue.Enqueue(item); - - if (activeThreads >= 16) - return item; - - new Thread(runWork) { IsBackground = true }.Start(); - activeThreads++; - } - - return item; - } - - private void runWork() - { - while (true) - { - UpdateItem toProcess; - - lock (queue) - { - if (queue.Count == 0) - break; - - toProcess = queue.Dequeue(); - } - - toProcess.PerformUpdate(api); - } - - lock (queue) - activeThreads--; - } - } - - private class UpdateItem - { - public Task Task => tcs.Task; - - private readonly BeatmapInfo beatmap; - private readonly CancellationToken cancellationToken; - - private readonly TaskCompletionSource tcs = new TaskCompletionSource(); - - public UpdateItem(BeatmapInfo beatmap, CancellationToken cancellationToken) - { - this.beatmap = beatmap; - this.cancellationToken = cancellationToken; - } - - public void PerformUpdate(IAPIProvider api) - { - if (cancellationToken.IsCancellationRequested) - { - tcs.SetCanceled(); + if (cancellation.IsCancellationRequested) return; - } if (api?.State != APIState.Online) - { - tcs.SetResult(false); return; - } Logger.Log("Attempting online lookup for the missing values...", LoggingTarget.Database); @@ -512,17 +454,14 @@ namespace osu.Game.Beatmaps beatmap.BeatmapSet.Status = res.BeatmapSet.Status; beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID; beatmap.OnlineBeatmapID = res.OnlineBeatmapID; - - tcs.SetResult(true); }; req.Failure += e => { Logger.Log($"Failed ({e})", LoggingTarget.Database); - - tcs.SetResult(false); }; + // intentionally blocking to limit web request concurrency req.Perform(api); } } diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index afc614772e..e30e1cd3ee 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.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; @@ -11,7 +11,6 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using osu.Framework; using osu.Framework.Extensions; -using osu.Framework.Extensions.TypeExtensions; using osu.Framework.IO.File; using osu.Framework.Logging; using osu.Framework.Platform; @@ -32,7 +31,7 @@ namespace osu.Game.Database /// /// The model type. /// The associated file join type. - public abstract class ArchiveModelManager : ICanAcceptFiles + public abstract class ArchiveModelManager : ArchiveModelManager, ICanAcceptFiles where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() { @@ -112,11 +111,8 @@ namespace osu.Game.Database a.Invoke(); } - private readonly ThreadedTaskScheduler importScheduler; - protected ArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, MutableDatabaseBackedStoreWithFileIncludes modelStore, IIpcHost importHost = null) { - importScheduler = new ThreadedTaskScheduler(16, $"{GetType().ReadableName()}.Import"); ContextFactory = contextFactory; ModelStore = modelStore; @@ -152,55 +148,55 @@ namespace osu.Game.Database var term = $"{typeof(TModel).Name.Replace("Info", "").ToLower()}"; - var tasks = new List(); - int current = 0; - foreach (string path in paths) + var imported = new List(); + + await Task.WhenAll(paths.Select(path => Import(path, notification.CancellationToken).ContinueWith(t => { - tasks.Add(Import(path, notification.CancellationToken).ContinueWith(t => + lock (notification) { - lock (notification) - { - current++; + current++; - notification.Text = $"Imported {current} of {paths.Length} {term}s"; - notification.Progress = (float)current / paths.Length; - } + notification.Text = $"Imported {current} of {paths.Length} {term}s"; + notification.Progress = (float)current / paths.Length; + } - if (t.Exception != null) - { - var e = t.Exception.InnerException ?? t.Exception; - Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})"); - } - })); + if (t.Exception == null) + { + lock (imported) + imported.Add(t.Result); + } + else + { + var e = t.Exception.InnerException ?? t.Exception; + Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})"); + } + }))); + + if (imported.Count == 0) + { + notification.Text = "Import failed!"; + notification.State = ProgressNotificationState.Cancelled; } + else + { + notification.CompletionText = imported.Count == 1 + ? $"Imported {imported.First()}!" + : $"Imported {current} {term}s!"; - await Task.WhenAll(tasks); + if (imported.Count > 0 && PresentImport != null) + { + notification.CompletionText += " Click to view."; + notification.CompletionClickAction = () => + { + PresentImport?.Invoke(imported); + return true; + }; + } - // if (imported.Count == 0) - // { - // notification.Text = "Import failed!"; - // notification.State = ProgressNotificationState.Cancelled; - // } - // else - // { - // notification.CompletionText = imported.Count == 1 - // ? $"Imported {imported.First()}!" - // : $"Imported {current} {term}s!"; - // - // if (imported.Count > 0 && PresentImport != null) - // { - // notification.CompletionText += " Click to view."; - // notification.CompletionClickAction = () => - // { - // PresentImport?.Invoke(imported); - // return true; - // }; - // } - // - // notification.State = ProgressNotificationState.Completed; - // } + notification.State = ProgressNotificationState.Completed; + } } /// @@ -368,7 +364,7 @@ namespace osu.Game.Database } return item; - }, CancellationToken.None, TaskCreationOptions.None, importScheduler).Unwrap(); + }, CancellationToken.None, TaskCreationOptions.HideScheduler, IMPORT_SCHEDULER).Unwrap(); /// /// Perform an update of the specified item. @@ -615,4 +611,10 @@ namespace osu.Game.Database throw new InvalidFormatException($"{path} is not a valid archive"); } } + + public abstract class ArchiveModelManager + { + // allow sharing static across all generic types + protected static readonly ThreadedTaskScheduler IMPORT_SCHEDULER = new ThreadedTaskScheduler(1); + } } From 2d1a54e63489b36cfb4fa5261abd0ed95c092051 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 13:37:20 +0900 Subject: [PATCH 1111/5608] Properly implement cancellation --- osu.Game/Database/ArchiveModelManager.cs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index e30e1cd3ee..1d576ff82f 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -154,6 +154,9 @@ namespace osu.Game.Database await Task.WhenAll(paths.Select(path => Import(path, notification.CancellationToken).ContinueWith(t => { + if (notification.CancellationToken.IsCancellationRequested) + return; + lock (notification) { current++; @@ -172,7 +175,7 @@ namespace osu.Game.Database var e = t.Exception.InnerException ?? t.Exception; Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})"); } - }))); + }, TaskContinuationOptions.NotOnCanceled))); if (imported.Count == 0) { @@ -207,6 +210,8 @@ namespace osu.Game.Database /// The imported model, if successful. public async Task Import(string path, CancellationToken cancellationToken = default) { + cancellationToken.ThrowIfCancellationRequested(); + TModel import; using (ArchiveReader reader = getReaderFrom(path)) import = await Import(reader, cancellationToken); @@ -240,6 +245,8 @@ namespace osu.Game.Database /// An optional cancellation token. public async Task Import(ArchiveReader archive, CancellationToken cancellationToken = default) { + cancellationToken.ThrowIfCancellationRequested(); + try { var model = CreateModel(archive); @@ -250,6 +257,10 @@ namespace osu.Game.Database return await Import(model, archive, cancellationToken); } + catch (TaskCanceledException) + { + throw; + } catch (Exception e) { Logger.Error(e, $"Model creation of {archive.Name} failed.", LoggingTarget.Database); @@ -286,6 +297,8 @@ namespace osu.Game.Database /// An optional cancellation token. public async Task Import(TModel item, ArchiveReader archive = null, CancellationToken cancellationToken = default) => await Task.Factory.StartNew(async () => { + cancellationToken.ThrowIfCancellationRequested(); + delayEvents(); try @@ -301,10 +314,6 @@ namespace osu.Game.Database { await Populate(item, archive, cancellationToken); } - catch (TaskCanceledException) - { - return item = null; - } finally { if (!Delete(localItem)) @@ -364,7 +373,7 @@ namespace osu.Game.Database } return item; - }, CancellationToken.None, TaskCreationOptions.HideScheduler, IMPORT_SCHEDULER).Unwrap(); + }, cancellationToken, TaskCreationOptions.HideScheduler, IMPORT_SCHEDULER).Unwrap(); /// /// Perform an update of the specified item. From e12b03e275c40de2b3629b92da24da45545be619 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 13:46:31 +0900 Subject: [PATCH 1112/5608] Remove unnecessary reference --- osu.Game.Tests/osu.Game.Tests.csproj | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 403ae16885..11d70ee7be 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -18,9 +18,4 @@ - - - ..\..\..\..\..\usr\local\share\dotnet\sdk\NuGetFallbackFolder\microsoft.win32.registry\4.5.0\ref\netstandard2.0\Microsoft.Win32.Registry.dll - - \ No newline at end of file From b79fdfc12f2d65da2f0fd80b68fa58aa2aa11882 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 13:48:58 +0900 Subject: [PATCH 1113/5608] Fix one more instance of improperly handled cancellation --- osu.Game/Beatmaps/BeatmapManager.cs | 3 +-- osu.Game/Database/ArchiveModelManager.cs | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 9e7b6d7971..cfc6a0be28 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -436,8 +436,7 @@ namespace osu.Game.Beatmaps private void perform(BeatmapInfo beatmap, CancellationToken cancellation) { - if (cancellation.IsCancellationRequested) - return; + cancellation.ThrowIfCancellationRequested(); if (api?.State != APIState.Online) return; diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 1d576ff82f..df96d9984a 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -361,6 +361,10 @@ namespace osu.Game.Database Logger.Log($"Import of {item} successfully completed!", LoggingTarget.Database); } + catch (TaskCanceledException) + { + throw; + } catch (Exception e) { Logger.Error(e, $"Import of {item} failed and has been rolled back.", LoggingTarget.Database); From e4bad93b6668868079dad7227b868b43736e6336 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 13:52:09 +0900 Subject: [PATCH 1114/5608] Use variable for web request concurrency for clarity --- osu.Game/Beatmaps/BeatmapManager.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index cfc6a0be28..435edcf722 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -424,7 +424,9 @@ namespace osu.Game.Beatmaps { private readonly IAPIProvider api; - private readonly ThreadedTaskScheduler updateScheduler = new ThreadedTaskScheduler(4); + private const int update_queue_request_concurrency = 4; + + private readonly ThreadedTaskScheduler updateScheduler = new ThreadedTaskScheduler(update_queue_request_concurrency); public BeatmapUpdateQueue(IAPIProvider api) { @@ -455,10 +457,7 @@ namespace osu.Game.Beatmaps beatmap.OnlineBeatmapID = res.OnlineBeatmapID; }; - req.Failure += e => - { - Logger.Log($"Failed ({e})", LoggingTarget.Database); - }; + req.Failure += e => { Logger.Log($"Failed ({e})", LoggingTarget.Database); }; // intentionally blocking to limit web request concurrency req.Perform(api); From e19f4935c3cbdd6d037d093d6b41e2f7cb1bf719 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 14:13:36 +0900 Subject: [PATCH 1115/5608] Fix incorrect undo logic on exception --- osu.Game/Database/ArchiveModelManager.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index df96d9984a..83c51e2abf 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -305,8 +305,7 @@ namespace osu.Game.Database { Logger.Log($"Importing {item}...", LoggingTarget.Database); - if (archive != null) - item.Files = createFileInfos(archive, Files); + item.Files = archive != null ? createFileInfos(archive, Files) : new List(); var localItem = item; @@ -314,7 +313,7 @@ namespace osu.Game.Database { await Populate(item, archive, cancellationToken); } - finally + catch (Exception) { if (!Delete(localItem)) Files.Dereference(localItem.Files.Select(f => f.FileInfo).ToArray()); From 27163c999686b4842ac41a170b63c2d41b2fa0fc Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Mon, 10 Jun 2019 09:18:48 +0300 Subject: [PATCH 1116/5608] Fix crashes in some cases When we want to switch ruleset from outside of the selector, but it's blocked (multiplayer is a good example) --- .../Overlays/Toolbar/ToolbarRulesetSelector.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index f8ac610a3a..1f35d0f293 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -23,6 +23,7 @@ namespace osu.Game.Overlays.Toolbar private const float padding = 10; private readonly Drawable modeButtonLine; private RulesetStore rulesets; + private readonly Bindable globalRuleset = new Bindable(); public override bool HandleNonPositionalInput => !Current.Disabled && base.HandleNonPositionalInput; public override bool HandlePositionalInput => !Current.Disabled && base.HandlePositionalInput; @@ -79,17 +80,20 @@ namespace osu.Game.Overlays.Toolbar private void load(RulesetStore rulesets, Bindable parentRuleset) { this.rulesets = rulesets; + globalRuleset.BindTo(parentRuleset); foreach (var r in rulesets.AvailableRulesets) { AddItem(r); } - Current.BindTo(parentRuleset); - Current.DisabledChanged += disabledChanged; - Current.BindValueChanged(rulesetChanged); + globalRuleset.BindValueChanged(globalRulesetChanged); + globalRuleset.DisabledChanged += disabledChanged; + Current.BindValueChanged(localRulesetChanged); } + private void globalRulesetChanged(ValueChangedEvent e) => Current.Value = e.NewValue; + protected override bool OnKeyDown(KeyDownEvent e) { base.OnKeyDown(e); @@ -109,8 +113,13 @@ namespace osu.Game.Overlays.Toolbar private readonly Cached activeMode = new Cached(); - private void rulesetChanged(ValueChangedEvent e) + private void localRulesetChanged(ValueChangedEvent e) { + if (!globalRuleset.Disabled) + { + globalRuleset.Value = e.NewValue; + } + activeMode.Invalidate(); } From f31b19e0d7b2837bfaa1c26fa381d6ab1df43e41 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 16:02:49 +0900 Subject: [PATCH 1117/5608] Don't unwrap exception manually --- osu.Game/Database/ArchiveModelManager.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 83c51e2abf..4c4878edee 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -172,8 +172,7 @@ namespace osu.Game.Database } else { - var e = t.Exception.InnerException ?? t.Exception; - Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})"); + Logger.Error(t.Exception, $@"Could not import ({Path.GetFileName(path)})"); } }, TaskContinuationOptions.NotOnCanceled))); From 9bdc8b47bb1e1c8ab8e57b48d0d8604d94ae5d3e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 16:13:51 +0900 Subject: [PATCH 1118/5608] Remove unnecessary async-await pair --- osu.Game/Database/ArchiveModelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 4c4878edee..fb7f0ffe5d 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -577,7 +577,7 @@ namespace osu.Game.Database /// The model to populate. /// The archive to use as a reference for population. May be null. /// An optional cancellation token. - protected virtual async Task Populate(TModel model, [CanBeNull] ArchiveReader archive, CancellationToken cancellationToken = default) => await Task.CompletedTask; + protected virtual Task Populate(TModel model, [CanBeNull] ArchiveReader archive, CancellationToken cancellationToken = default) => Task.CompletedTask; /// /// Perform any final actions before the import to database executes. From fae32b390171738feed00336df54db7046c9ecd8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 16:14:11 +0900 Subject: [PATCH 1119/5608] Return shorter class name in error messages --- osu.Game/Database/ArchiveModelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index fb7f0ffe5d..e2a07a860f 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -331,7 +331,7 @@ namespace osu.Game.Database if (CanUndelete(existing, item)) { Undelete(existing); - Logger.Log($"Found existing {typeof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); + Logger.Log($"Found existing {nameof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); handleEvent(() => ItemAdded?.Invoke(existing, true)); return existing; } From 02b376d962d364f7b2525e8478dd4c4e3dd7cf04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 16:14:42 +0900 Subject: [PATCH 1120/5608] Fix rollback logic not necessrily cleaning up file store --- osu.Game/Database/ArchiveModelManager.cs | 63 +++++++++++------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index e2a07a860f..45460dd11c 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -154,25 +154,22 @@ namespace osu.Game.Database await Task.WhenAll(paths.Select(path => Import(path, notification.CancellationToken).ContinueWith(t => { - if (notification.CancellationToken.IsCancellationRequested) - return; + notification.CancellationToken.ThrowIfCancellationRequested(); - lock (notification) + lock (imported) { - current++; + Interlocked.Increment(ref current); - notification.Text = $"Imported {current} of {paths.Length} {term}s"; - notification.Progress = (float)current / paths.Length; - } - - if (t.Exception == null) - { - lock (imported) + if (t.Exception == null) + { imported.Add(t.Result); - } - else - { - Logger.Error(t.Exception, $@"Could not import ({Path.GetFileName(path)})"); + notification.Text = $"Imported {current} of {paths.Length} {term}s"; + notification.Progress = (float)current / paths.Length; + } + else + { + Logger.Error(t.Exception, $@"Could not import ({Path.GetFileName(path)})"); + } } }, TaskContinuationOptions.NotOnCanceled))); @@ -300,23 +297,23 @@ namespace osu.Game.Database delayEvents(); + void rollback() + { + if (!Delete(item)) + { + // We may have not yet added the model to the underlying table, but should still clean up files. + Logger.Log($"Dereferencing files for incomplete import of {item}.", LoggingTarget.Database); + Files.Dereference(item.Files.Select(f => f.FileInfo).ToArray()); + } + } + try { Logger.Log($"Importing {item}...", LoggingTarget.Database); item.Files = archive != null ? createFileInfos(archive, Files) : new List(); - var localItem = item; - - try - { - await Populate(item, archive, cancellationToken); - } - catch (Exception) - { - if (!Delete(localItem)) - Files.Dereference(localItem.Files.Select(f => f.FileInfo).ToArray()); - } + await Populate(item, archive, cancellationToken); using (var write = ContextFactory.GetForWrite()) // used to share a context for full import. keep in mind this will block all writes. { @@ -333,6 +330,8 @@ namespace osu.Game.Database Undelete(existing); Logger.Log($"Found existing {nameof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); handleEvent(() => ItemAdded?.Invoke(existing, true)); + + rollback(); return existing; } else @@ -349,9 +348,6 @@ namespace osu.Game.Database } catch (Exception e) { - if (!Delete(item)) - Files.Dereference(item.Files.Select(f => f.FileInfo).ToArray()); - write.Errors.Add(e); throw; } @@ -359,13 +355,12 @@ namespace osu.Game.Database Logger.Log($"Import of {item} successfully completed!", LoggingTarget.Database); } - catch (TaskCanceledException) - { - throw; - } catch (Exception e) { - Logger.Error(e, $"Import of {item} failed and has been rolled back.", LoggingTarget.Database); + if (!(e is TaskCanceledException)) + Logger.Error(e, $"Import of {item} failed and has been rolled back.", LoggingTarget.Database); + + rollback(); item = null; } finally From 5b75060b94999e3a50a665a4e40cee3994162fa2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 16:45:45 +0900 Subject: [PATCH 1121/5608] Add test for rollback logic correctly dereferencing files --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 13 +++++++++++++ osu.Game/IO/FileStore.cs | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 4c9260f640..3f4f40781c 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -12,6 +12,7 @@ using osu.Framework.Platform; using osu.Game.IPC; using osu.Framework.Allocation; using osu.Game.Beatmaps; +using osu.Game.IO; using osu.Game.Tests.Resources; using SharpCompress.Archives.Zip; @@ -97,6 +98,7 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = loadOsu(host); var manager = osu.Dependencies.Get(); + var files = osu.Dependencies.Get(); int fireCount = 0; @@ -113,6 +115,12 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.AreEqual(0, fireCount -= 2); + Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count); + Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); + Assert.AreEqual(12, manager.QueryBeatmaps(_ => true).ToList().Count); + + Assert.AreEqual(18, files.QueryFiles(_ => true).Count()); + var breakTemp = TestResources.GetTestBeatmapForImport(); MemoryStream brokenOsu = new MemoryStream(new byte[] { 1, 3, 3, 7 }); @@ -131,6 +139,8 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); Assert.AreEqual(12, manager.QueryBeatmaps(_ => true).ToList().Count); + Assert.AreEqual(18, files.QueryFiles(_ => true).Count()); + // this will trigger purging of the existing beatmap (online set id match) but should rollback due to broken osu. await manager.Import(breakTemp); @@ -140,6 +150,9 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count); Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); Assert.AreEqual(12, manager.QueryBeatmaps(_ => true).ToList().Count); + + Assert.AreEqual(18, files.QueryFiles(_ => true).Count()); + Assert.AreEqual(18, files.QueryFiles(f => f.ReferenceCount == 1).Count()); } finally { diff --git a/osu.Game/IO/FileStore.cs b/osu.Game/IO/FileStore.cs index 458f8964f9..370d6786f5 100644 --- a/osu.Game/IO/FileStore.cs +++ b/osu.Game/IO/FileStore.cs @@ -2,8 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.IO; using System.Linq; +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore; using osu.Framework.Extensions; using osu.Framework.IO.Stores; using osu.Framework.Logging; @@ -27,6 +30,13 @@ namespace osu.Game.IO Store = new StorageBackedResourceStore(Storage); } + /// + /// Perform a lookup query on available s. + /// + /// The query. + /// Results from the provided query. + public IEnumerable QueryFiles(Expression> query) => ContextFactory.Get().Set().AsNoTracking().Where(f => f.ReferenceCount > 0).Where(query); + public FileInfo Add(Stream data, bool reference = true) { using (var usage = ContextFactory.GetForWrite()) From 559413f766fef4fef2f8c16e59e61a39f100d785 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 17:12:25 +0900 Subject: [PATCH 1122/5608] Avoid using ContinueWith in already async context --- osu.Game/Database/ArchiveModelManager.cs | 29 ++++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 45460dd11c..d09aa37d7e 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -152,26 +152,35 @@ namespace osu.Game.Database var imported = new List(); - await Task.WhenAll(paths.Select(path => Import(path, notification.CancellationToken).ContinueWith(t => + await Task.WhenAll(paths.Select(async path => { notification.CancellationToken.ThrowIfCancellationRequested(); - lock (imported) + try { - Interlocked.Increment(ref current); + var model = await Import(path, notification.CancellationToken); - if (t.Exception == null) + lock (imported) { - imported.Add(t.Result); + imported.Add(model); + notification.Text = $"Imported {current} of {paths.Length} {term}s"; notification.Progress = (float)current / paths.Length; } - else - { - Logger.Error(t.Exception, $@"Could not import ({Path.GetFileName(path)})"); - } } - }, TaskContinuationOptions.NotOnCanceled))); + catch (TaskCanceledException) + { + throw; + } + catch (Exception e) + { + Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})"); + } + finally + { + Interlocked.Increment(ref current); + } + })); if (imported.Count == 0) { From c8bd92659bab551a36e0c40dc1b604deca0e4fdb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 17:12:37 +0900 Subject: [PATCH 1123/5608] Clean up exception and null handling in Import process --- osu.Game/Database/ArchiveModelManager.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index d09aa37d7e..fa8301bb2e 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -252,15 +252,15 @@ namespace osu.Game.Database { cancellationToken.ThrowIfCancellationRequested(); + TModel model; + try { - var model = CreateModel(archive); + model = CreateModel(archive); if (model == null) return null; model.Hash = computeHash(archive); - - return await Import(model, archive, cancellationToken); } catch (TaskCanceledException) { @@ -271,6 +271,8 @@ namespace osu.Game.Database Logger.Error(e, $"Model creation of {archive.Name} failed.", LoggingTarget.Database); return null; } + + return await Import(model, archive, cancellationToken); } /// @@ -340,7 +342,9 @@ namespace osu.Game.Database Logger.Log($"Found existing {nameof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); handleEvent(() => ItemAdded?.Invoke(existing, true)); + // existing item will be used; rollback new import and exit early. rollback(); + flushEvents(true); return existing; } else @@ -370,14 +374,11 @@ namespace osu.Game.Database Logger.Error(e, $"Import of {item} failed and has been rolled back.", LoggingTarget.Database); rollback(); - item = null; - } - finally - { - // we only want to flush events after we've confirmed the write context didn't have any errors. - flushEvents(item != null); + flushEvents(false); + throw; } + flushEvents(true); return item; }, cancellationToken, TaskCreationOptions.HideScheduler, IMPORT_SCHEDULER).Unwrap(); From dcdb806120c6b581af4be341b60bd84cba5ea9c3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 17:26:56 +0900 Subject: [PATCH 1124/5608] Catch newly thrown exception in test --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 3f4f40781c..7f08674a95 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -135,14 +135,14 @@ namespace osu.Game.Tests.Beatmaps.IO zip.SaveTo(outStream, SharpCompress.Common.CompressionType.Deflate); } - Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count); - Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); - Assert.AreEqual(12, manager.QueryBeatmaps(_ => true).ToList().Count); - - Assert.AreEqual(18, files.QueryFiles(_ => true).Count()); - // this will trigger purging of the existing beatmap (online set id match) but should rollback due to broken osu. - await manager.Import(breakTemp); + try + { + await manager.Import(breakTemp); + } + catch + { + } // no events should be fired in the case of a rollback. Assert.AreEqual(0, fireCount); From 28b2a516e34354eb0f2d958c2f55da91dd8d4f78 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 18:13:33 +0900 Subject: [PATCH 1125/5608] Ensure exception is only thrown once on rollback --- .../Beatmaps/IO/ImportBeatmapTest.cs | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 7f08674a95..f3680e3c1e 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -11,6 +11,7 @@ using NUnit.Framework; using osu.Framework.Platform; using osu.Game.IPC; using osu.Framework.Allocation; +using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.IO; using osu.Game.Tests.Resources; @@ -96,24 +97,31 @@ namespace osu.Game.Tests.Beatmaps.IO { try { + int itemAddRemoveFireCount = 0; + int loggedExceptionCount = 0; + + Logger.NewEntry += l => + { + if (l.Target == LoggingTarget.Database && l.Exception != null) + Interlocked.Increment(ref loggedExceptionCount); + }; + var osu = loadOsu(host); var manager = osu.Dependencies.Get(); var files = osu.Dependencies.Get(); - int fireCount = 0; - // ReSharper disable once AccessToModifiedClosure - manager.ItemAdded += (_, __) => fireCount++; - manager.ItemRemoved += _ => fireCount++; + manager.ItemAdded += (_, __) => Interlocked.Increment(ref itemAddRemoveFireCount); + manager.ItemRemoved += _ => Interlocked.Increment(ref itemAddRemoveFireCount); var imported = await LoadOszIntoOsu(osu); - Assert.AreEqual(0, fireCount -= 1); + Assert.AreEqual(0, itemAddRemoveFireCount -= 1); imported.Hash += "-changed"; manager.Update(imported); - Assert.AreEqual(0, fireCount -= 2); + Assert.AreEqual(0, itemAddRemoveFireCount -= 2); Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count); Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); @@ -145,7 +153,7 @@ namespace osu.Game.Tests.Beatmaps.IO } // no events should be fired in the case of a rollback. - Assert.AreEqual(0, fireCount); + Assert.AreEqual(0, itemAddRemoveFireCount); Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count); Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); @@ -153,6 +161,8 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.AreEqual(18, files.QueryFiles(_ => true).Count()); Assert.AreEqual(18, files.QueryFiles(f => f.ReferenceCount == 1).Count()); + + Assert.AreEqual(1, loggedExceptionCount); } finally { From 1aa865c3fb154d0ce88321f38cbef309c7799c22 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 10 Jun 2019 18:34:24 +0900 Subject: [PATCH 1126/5608] split out method for reuse --- .../Visual/SongSelect/TestScenePlaySongSelect.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 8636890081..d6b5e0175f 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -138,7 +138,7 @@ namespace osu.Game.Tests.Visual.SongSelect { createSongSelect(); changeRuleset(2); - importForRuleset(0); + addRulesetImportStep(0); AddUntilStep("no selection", () => songSelect.Carousel.SelectedBeatmap == null); } @@ -147,8 +147,8 @@ namespace osu.Game.Tests.Visual.SongSelect { createSongSelect(); changeRuleset(2); - importForRuleset(2); - importForRuleset(1); + addRulesetImportStep(2); + addRulesetImportStep(1); AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmap.RulesetID == 2); changeRuleset(1); @@ -223,7 +223,7 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddRepeatStep($"Create beatmaps {test_count} times", () => { - manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == 0).ToArray())); + importForRuleset(0); Scheduler.AddDelayed(() => { @@ -240,15 +240,16 @@ namespace osu.Game.Tests.Visual.SongSelect { int? previousID = null; createSongSelect(); - importForRuleset(0); + addRulesetImportStep(0); AddStep("Move to last difficulty", () => songSelect.Carousel.SelectBeatmap(songSelect.Carousel.BeatmapSets.First().Beatmaps.Last())); AddStep("Store current ID", () => previousID = songSelect.Carousel.SelectedBeatmap.ID); AddStep("Hide first beatmap", () => manager.Hide(songSelect.Carousel.SelectedBeatmapSet.Beatmaps.First())); AddAssert("Selected beatmap has not changed", () => songSelect.Carousel.SelectedBeatmap.ID == previousID); } - private void importForRuleset(int id) => AddStep($"import test map for ruleset {id}", - () => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray()))); + private void addRulesetImportStep(int id) => AddStep($"import test map for ruleset {id}", () => importForRuleset(id)); + + private void importForRuleset(int id) => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray())); private static int importId; private int getImportId() => ++importId; From 12aa264657061f456405a65c0eaaf781f3461304 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 18:35:23 +0900 Subject: [PATCH 1127/5608] Consolidate tests and check for file reference counts --- .../Beatmaps/IO/ImportBeatmapTest.cs | 51 ++++++++++++------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index f3680e3c1e..5fc05a4b2f 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -77,10 +77,8 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.IsTrue(imported.ID == importedSecondTime.ID); Assert.IsTrue(imported.Beatmaps.First().ID == importedSecondTime.Beatmaps.First().ID); - var manager = osu.Dependencies.Get(); - - Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count); - Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); + checkBeatmapSetCount(osu, 1); + checkSingleReferencedFileCount(osu, 18); } finally { @@ -108,7 +106,6 @@ namespace osu.Game.Tests.Beatmaps.IO var osu = loadOsu(host); var manager = osu.Dependencies.Get(); - var files = osu.Dependencies.Get(); // ReSharper disable once AccessToModifiedClosure manager.ItemAdded += (_, __) => Interlocked.Increment(ref itemAddRemoveFireCount); @@ -123,11 +120,9 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.AreEqual(0, itemAddRemoveFireCount -= 2); - Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count); - Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); - Assert.AreEqual(12, manager.QueryBeatmaps(_ => true).ToList().Count); - - Assert.AreEqual(18, files.QueryFiles(_ => true).Count()); + checkBeatmapSetCount(osu, 1); + checkBeatmapCount(osu, 12); + checkSingleReferencedFileCount(osu, 18); var breakTemp = TestResources.GetTestBeatmapForImport(); @@ -155,12 +150,10 @@ namespace osu.Game.Tests.Beatmaps.IO // no events should be fired in the case of a rollback. Assert.AreEqual(0, itemAddRemoveFireCount); - Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count); - Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); - Assert.AreEqual(12, manager.QueryBeatmaps(_ => true).ToList().Count); + checkBeatmapSetCount(osu, 1); + checkBeatmapCount(osu, 12); - Assert.AreEqual(18, files.QueryFiles(_ => true).Count()); - Assert.AreEqual(18, files.QueryFiles(f => f.ReferenceCount == 1).Count()); + checkSingleReferencedFileCount(osu, 18); Assert.AreEqual(1, loggedExceptionCount); } @@ -193,8 +186,7 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.IsTrue(imported.Beatmaps.First().ID < importedSecondTime.Beatmaps.First().ID); // only one beatmap will exist as the online set ID matched, causing purging of the first import. - Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count); - Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); + checkBeatmapSetCount(osu, 1); } finally { @@ -396,11 +388,32 @@ namespace osu.Game.Tests.Beatmaps.IO var manager = osu.Dependencies.Get(); manager.Delete(imported); - Assert.IsTrue(manager.GetAllUsableBeatmapSets().Count == 0); - Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count); + checkBeatmapSetCount(osu, 0); + checkBeatmapSetCount(osu, 1, true); + checkSingleReferencedFileCount(osu, 0); + Assert.IsTrue(manager.QueryBeatmapSets(_ => true).First().DeletePending); } + private void checkBeatmapSetCount(OsuGameBase osu, int expected, bool includeDeletePending = false) + { + var manager = osu.Dependencies.Get(); + + Assert.AreEqual(expected, includeDeletePending + ? manager.QueryBeatmapSets(_ => true).ToList().Count + : manager.GetAllUsableBeatmapSets().Count); + } + + private void checkBeatmapCount(OsuGameBase osu, int expected) + { + Assert.AreEqual(expected, osu.Dependencies.Get().QueryBeatmaps(_ => true).ToList().Count); + } + + private void checkSingleReferencedFileCount(OsuGameBase osu, int expected) + { + Assert.AreEqual(expected, osu.Dependencies.Get().QueryFiles(f => f.ReferenceCount == 1).Count()); + } + private OsuGameBase loadOsu(GameHost host) { var osu = new OsuGameBase(); From f7a699e4a2e0031224661370ba840d7d9327df3f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 18:38:03 +0900 Subject: [PATCH 1128/5608] Better documentation for import scheduler singleton --- osu.Game/Database/ArchiveModelManager.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index fa8301bb2e..afc2690106 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -630,7 +630,15 @@ namespace osu.Game.Database public abstract class ArchiveModelManager { - // allow sharing static across all generic types - protected static readonly ThreadedTaskScheduler IMPORT_SCHEDULER = new ThreadedTaskScheduler(1); + private const int import_queue_request_concurrency = 1; + + /// + /// A singleton scheduler shared by all . + /// + /// + /// This scheduler generally performs IO and CPU intensive work so concurrency is limited harshly. + /// It is mainly being used as a queue mechanism for large imports. + /// + protected static readonly ThreadedTaskScheduler IMPORT_SCHEDULER = new ThreadedTaskScheduler(import_queue_request_concurrency); } } From 41e3e2222bc7d9c75e44a1340144c2d52e1f7acb Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 10 Jun 2019 18:40:49 +0900 Subject: [PATCH 1129/5608] fix test --- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index d6b5e0175f..bc15bc6b6d 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -219,7 +219,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("Setup counter", () => { beatmapChangedCount = 0; - songSelect.Carousel.BeatmapSetsChanged += () => beatmapChangedCount++; + songSelect.Carousel.SelectionChanged += _ => beatmapChangedCount++; }); AddRepeatStep($"Create beatmaps {test_count} times", () => { From 6cda2cdb8225000f1a7de5e8c842a8d3f0a02aaf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 18:41:56 +0900 Subject: [PATCH 1130/5608] Fix exception output to use humanised model name --- osu.Game/Database/ArchiveModelManager.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index afc2690106..93e924fab5 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -146,8 +146,6 @@ namespace osu.Game.Database notification.Progress = 0; notification.Text = "Import is initialising..."; - var term = $"{typeof(TModel).Name.Replace("Info", "").ToLower()}"; - int current = 0; var imported = new List(); @@ -164,7 +162,7 @@ namespace osu.Game.Database { imported.Add(model); - notification.Text = $"Imported {current} of {paths.Length} {term}s"; + notification.Text = $"Imported {current} of {paths.Length} {humanisedModelName}s"; notification.Progress = (float)current / paths.Length; } } @@ -191,7 +189,7 @@ namespace osu.Game.Database { notification.CompletionText = imported.Count == 1 ? $"Imported {imported.First()}!" - : $"Imported {current} {term}s!"; + : $"Imported {current} {humanisedModelName}s!"; if (imported.Count > 0 && PresentImport != null) { @@ -339,7 +337,7 @@ namespace osu.Game.Database if (CanUndelete(existing, item)) { Undelete(existing); - Logger.Log($"Found existing {nameof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); + Logger.Log($"Found existing {humanisedModelName} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); handleEvent(() => ItemAdded?.Invoke(existing, true)); // existing item will be used; rollback new import and exit early. @@ -610,6 +608,8 @@ namespace osu.Game.Database private DbSet queryModel() => ContextFactory.Get().Set(); + private string humanisedModelName => $"{typeof(TModel).Name.Replace("Info", "").ToLower()}"; + /// /// Creates an from a valid storage path. /// From 3fc604b60a6a2ee39b99c06beb3b0d3d6fb944fd Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Mon, 10 Jun 2019 13:18:38 +0300 Subject: [PATCH 1131/5608] Add Availability to BeatmapSetOnlineInfo --- osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs | 16 +++++++++++++++- .../API/Requests/Responses/APIBeatmapSet.cs | 7 +++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs index 0ccc9a924c..e88def6321 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs @@ -65,6 +65,11 @@ namespace osu.Game.Beatmaps /// The amount of people who have favourited this beatmap set. /// public int FavouriteCount { get; set; } + + /// + /// The availability of this beatmap set. + /// + public BeatmapSetOnlineAvailability Availability { get; set; } } public class BeatmapSetOnlineCovers @@ -73,7 +78,7 @@ namespace osu.Game.Beatmaps [JsonProperty(@"cover@2x")] public string Cover { get; set; } - + public string CardLowRes { get; set; } [JsonProperty(@"card@2x")] @@ -84,4 +89,13 @@ namespace osu.Game.Beatmaps [JsonProperty(@"list@2x")] public string List { get; set; } } + + public class BeatmapSetOnlineAvailability + { + [JsonProperty(@"download_disabled")] + public bool DownloadDisabled { get; set; } + + [JsonProperty(@"more_information")] + public string ExternalLink { get; set; } + } } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 1abb7c1a7d..2b8a783e2e 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -60,6 +60,12 @@ namespace osu.Game.Online.API.Requests.Responses set => Author.Id = value; } + [JsonProperty(@"availability")] + private BeatmapSetOnlineAvailability availability { get; set; } + + [JsonProperty(@"download_unavailable")] + private bool test { get; set; } + [JsonProperty(@"beatmaps")] private IEnumerable beatmaps { get; set; } @@ -83,6 +89,7 @@ namespace osu.Game.Online.API.Requests.Responses Submitted = submitted, Ranked = ranked, LastUpdated = lastUpdated, + Availability = availability, }, Beatmaps = beatmaps?.Select(b => b.ToBeatmap(rulesets)).ToList(), }; From 54497fb1e78dd5447111cd256067f3959c1a61dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 19:33:23 +0900 Subject: [PATCH 1132/5608] Fix prefixing spaces in BeatmapInfo's ToString when metadata is not populated yet --- osu.Game/Beatmaps/BeatmapInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 52238c26fe..3c082bb71e 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -119,7 +119,7 @@ namespace osu.Game.Beatmaps /// public List Scores { get; set; } - public override string ToString() => $"{Metadata} [{Version}]"; + public override string ToString() => $"{Metadata} [{Version}]".Trim(); public bool Equals(BeatmapInfo other) { From 29945f27c5f22bcbb36ed693d813fd34707053ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 19:33:55 +0900 Subject: [PATCH 1133/5608] Fix imported count incrementing on failures --- osu.Game/Database/ArchiveModelManager.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 93e924fab5..4e9478dc10 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -162,6 +162,7 @@ namespace osu.Game.Database { imported.Add(model); + Interlocked.Increment(ref current); notification.Text = $"Imported {current} of {paths.Length} {humanisedModelName}s"; notification.Progress = (float)current / paths.Length; } @@ -174,10 +175,6 @@ namespace osu.Game.Database { Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})"); } - finally - { - Interlocked.Increment(ref current); - } })); if (imported.Count == 0) From 6ca2fcebfce6467398d12fc69911ffb3f1c03eff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 19:34:32 +0900 Subject: [PATCH 1134/5608] Centalise and prefix all ArchiveModelManager database logging --- osu.Game/Beatmaps/BeatmapManager.cs | 28 ++++++++++-------- osu.Game/Database/ArchiveModelManager.cs | 36 +++++++++++++++--------- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 435edcf722..47411c69ec 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -110,7 +110,7 @@ namespace osu.Game.Beatmaps validateOnlineIds(beatmapSet); - await Task.WhenAll(beatmapSet.Beatmaps.Select(b => updateQueue.Perform(b, cancellationToken)).ToArray()); + await updateQueue.Perform(beatmapSet, cancellationToken); } protected override void PreImport(BeatmapSetInfo beatmapSet) @@ -127,7 +127,7 @@ namespace osu.Game.Beatmaps { Delete(existingOnlineId); beatmaps.PurgeDeletable(s => s.ID == existingOnlineId.ID); - Logger.Log($"Found existing beatmap set with same OnlineBeatmapSetID ({beatmapSet.OnlineBeatmapSetID}). It has been purged.", LoggingTarget.Database); + LogForModel(beatmapSet, $"Found existing beatmap set with same OnlineBeatmapSetID ({beatmapSet.OnlineBeatmapSetID}). It has been purged."); } } } @@ -433,23 +433,29 @@ namespace osu.Game.Beatmaps this.api = api; } - public Task Perform(BeatmapInfo beatmap, CancellationToken cancellationToken) - => Task.Factory.StartNew(() => perform(beatmap, cancellationToken), cancellationToken, TaskCreationOptions.HideScheduler, updateScheduler); - - private void perform(BeatmapInfo beatmap, CancellationToken cancellation) + public async Task Perform(BeatmapSetInfo beatmapSet, CancellationToken cancellationToken) { - cancellation.ThrowIfCancellationRequested(); - if (api?.State != APIState.Online) return; - Logger.Log("Attempting online lookup for the missing values...", LoggingTarget.Database); + LogForModel(beatmapSet, "Performing online lookups..."); + await Task.WhenAll(beatmapSet.Beatmaps.Select(b => Perform(beatmapSet, b, cancellationToken)).ToArray()); + } + + // todo: expose this when we need to do individual difficulty lookups. + protected Task Perform(BeatmapSetInfo beatmapSet, BeatmapInfo beatmap, CancellationToken cancellationToken) + => Task.Factory.StartNew(() => perform(beatmapSet, beatmap), cancellationToken, TaskCreationOptions.HideScheduler, updateScheduler); + + private void perform(BeatmapSetInfo set, BeatmapInfo beatmap) + { + if (api?.State != APIState.Online) + return; var req = new GetBeatmapRequest(beatmap); req.Success += res => { - Logger.Log($"Successfully mapped to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}.", LoggingTarget.Database); + LogForModel(set, $"Online retrieval mapped {beatmap} to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}."); beatmap.Status = res.Status; beatmap.BeatmapSet.Status = res.BeatmapSet.Status; @@ -457,7 +463,7 @@ namespace osu.Game.Beatmaps beatmap.OnlineBeatmapID = res.OnlineBeatmapID; }; - req.Failure += e => { Logger.Log($"Failed ({e})", LoggingTarget.Database); }; + req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap}", e); }; // intentionally blocking to limit web request concurrency req.Perform(api); diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 4e9478dc10..844ae622a5 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -173,7 +173,7 @@ namespace osu.Game.Database } catch (Exception e) { - Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})"); + Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})", LoggingTarget.Database); } })); @@ -227,7 +227,7 @@ namespace osu.Game.Database } catch (Exception e) { - Logger.Error(e, $@"Could not delete original file after import ({Path.GetFileName(path)})"); + LogForModel(import, $@"Could not delete original file after import ({Path.GetFileName(path)})", e); } return import; @@ -247,7 +247,7 @@ namespace osu.Game.Database { cancellationToken.ThrowIfCancellationRequested(); - TModel model; + TModel model = null; try { @@ -263,7 +263,7 @@ namespace osu.Game.Database } catch (Exception e) { - Logger.Error(e, $"Model creation of {archive.Name} failed.", LoggingTarget.Database); + LogForModel(model, $"Model creation of {archive.Name} failed.", e); return null; } @@ -277,6 +277,16 @@ namespace osu.Game.Database /// protected abstract string[] HashableFileTypes { get; } + protected static void LogForModel(TModel model, string message, Exception e = null) + { + string prefix = $"[{(model?.Hash ?? "?????").Substring(0, 5)}]"; + + if (e != null) + Logger.Error(e, $"{prefix} {message}", LoggingTarget.Database); + else + Logger.Log($"{prefix} {message}", LoggingTarget.Database); + } + /// /// Create a SHA-2 hash from the provided archive based on file content of all files matching . /// @@ -308,14 +318,14 @@ namespace osu.Game.Database if (!Delete(item)) { // We may have not yet added the model to the underlying table, but should still clean up files. - Logger.Log($"Dereferencing files for incomplete import of {item}.", LoggingTarget.Database); + LogForModel(item, "Dereferencing files for incomplete import."); Files.Dereference(item.Files.Select(f => f.FileInfo).ToArray()); } } try { - Logger.Log($"Importing {item}...", LoggingTarget.Database); + LogForModel(item, "Beginning import..."); item.Files = archive != null ? createFileInfos(archive, Files) : new List(); @@ -334,7 +344,7 @@ namespace osu.Game.Database if (CanUndelete(existing, item)) { Undelete(existing); - Logger.Log($"Found existing {humanisedModelName} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); + LogForModel(item, $"Found existing {humanisedModelName} for {item} (ID {existing.ID}) – skipping import."); handleEvent(() => ItemAdded?.Invoke(existing, true)); // existing item will be used; rollback new import and exit early. @@ -342,11 +352,9 @@ namespace osu.Game.Database flushEvents(true); return existing; } - else - { - Delete(existing); - ModelStore.PurgeDeletable(s => s.ID == existing.ID); - } + + Delete(existing); + ModelStore.PurgeDeletable(s => s.ID == existing.ID); } PreImport(item); @@ -361,12 +369,12 @@ namespace osu.Game.Database } } - Logger.Log($"Import of {item} successfully completed!", LoggingTarget.Database); + LogForModel(item, "Import successfully completed!"); } catch (Exception e) { if (!(e is TaskCanceledException)) - Logger.Error(e, $"Import of {item} failed and has been rolled back.", LoggingTarget.Database); + LogForModel(item, "Database import or population failed and has been rolled back.", e); rollback(); flushEvents(false); From adbf4d374e6f90f5a53e3abde23fc9b14f994bad Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Mon, 10 Jun 2019 14:15:49 +0300 Subject: [PATCH 1135/5608] Redirecting ShowBeatmapSet to FetchAndShowBeatmapSet --- osu.Game/Overlays/BeatmapSetOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 3ed398d31a..b7331f551e 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -120,8 +120,8 @@ namespace osu.Game.Overlays public void ShowBeatmapSet(BeatmapSetInfo set) { - beatmapSet.Value = set; - Show(); + // Re-fetching is the correct way forward. + FetchAndShowBeatmapSet((int)set.OnlineBeatmapSetID); scroll.ScrollTo(0); } } From 2b768bef96e28f438116f9458ce61130e76c17a5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 Jun 2019 20:29:01 +0900 Subject: [PATCH 1136/5608] Make CursorTrail use VertexBatch --- .../UI/Cursor/CursorTrail.cs | 76 ++++++------------- 1 file changed, 22 insertions(+), 54 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 2276b9f9f4..b986076593 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -6,7 +6,7 @@ using System.Diagnostics; using System.Runtime.InteropServices; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.OpenGL.Buffers; +using osu.Framework.Graphics.Batches; using osu.Framework.Graphics.OpenGL.Vertices; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Shaders; @@ -57,7 +57,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor // InvalidationID 1 forces an update of each part of the cursor trail the first time ApplyState is run on the draw node // This is to prevent garbage data from being sent to the vertex shader, resulting in visual issues on some platforms parts[i].InvalidationID = 1; - parts[i].WasUpdated = true; } } @@ -149,7 +148,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public Vector2 Position; public float Time; public long InvalidationID; - public bool WasUpdated; } private class TrailDrawNode : DrawNode @@ -164,16 +162,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly TrailPart[] parts = new TrailPart[max_sprites]; private Vector2 size; - private readonly VertexBuffer vertexBuffer = new QuadVertexBuffer(max_sprites, BufferUsageHint.DynamicDraw); + private readonly VertexBatch vertexBatch = new QuadBatch(max_sprites, 1); public TrailDrawNode(CursorTrail source) : base(source) { for (int i = 0; i < max_sprites; i++) - { parts[i].InvalidationID = 0; - parts[i].WasUpdated = false; - } } public override void ApplyState() @@ -194,56 +189,29 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public override void Draw(Action vertexAction) { - shader.GetUniform("g_FadeClock").UpdateValue(ref time); - - int updateStart = -1, updateEnd = 0; - - for (int i = 0; i < parts.Length; ++i) - { - if (parts[i].WasUpdated) - { - if (updateStart == -1) - updateStart = i; - updateEnd = i + 1; - - int start = i * 4; - int end = start; - - Vector2 pos = parts[i].Position; - float localTime = parts[i].Time; - - DrawQuad( - texture, - new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y), - DrawColourInfo.Colour, - null, - v => vertexBuffer.Vertices[end++] = new TexturedTrailVertex - { - Position = v.Position, - TexturePosition = v.TexturePosition, - Time = localTime + 1, - Colour = v.Colour, - }); - - parts[i].WasUpdated = false; - } - else if (updateStart != -1) - { - vertexBuffer.UpdateRange(updateStart * 4, updateEnd * 4); - updateStart = -1; - } - } - - // Update all remaining vertices that have been changed. - if (updateStart != -1) - vertexBuffer.UpdateRange(updateStart * 4, updateEnd * 4); - base.Draw(vertexAction); shader.Bind(); + shader.GetUniform("g_FadeClock").UpdateValue(ref time); - texture.TextureGL.Bind(); - vertexBuffer.Draw(); + for (int i = 0; i < parts.Length; ++i) + { + Vector2 pos = parts[i].Position; + float localTime = parts[i].Time; + + DrawQuad( + texture, + new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y), + DrawColourInfo.Colour, + null, + v => vertexBatch.Add(new TexturedTrailVertex + { + Position = v.Position, + TexturePosition = v.TexturePosition, + Time = localTime + 1, + Colour = v.Colour, + })); + } shader.Unbind(); } @@ -252,7 +220,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { base.Dispose(isDisposing); - vertexBuffer.Dispose(); + vertexBatch.Dispose(); } } From e87123342cab2004c7baea09310a1ddf83b6b547 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Jun 2019 23:50:44 +0900 Subject: [PATCH 1137/5608] Load results pages asynchronously Reduces performance burden when first displaying pages. Closes #4977. --- osu.Game/Screens/Ranking/Results.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index bebeaee00a..370c856d1d 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -275,7 +275,7 @@ namespace osu.Game.Screens.Ranking currentPage = page.NewValue?.CreatePage(); if (currentPage != null) - circleInner.Add(currentPage); + LoadComponentAsync(currentPage, circleInner.Add); }, true); } From 71e15fe0f112aa6fb693c54536bb486ad97eedef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Jun 2019 01:18:49 +0900 Subject: [PATCH 1138/5608] Fix incorrect xmldoc in OsuAnimatedButton --- osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs index 236b72766f..1a8fea4ff9 100644 --- a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs @@ -19,14 +19,14 @@ namespace osu.Game.Graphics.UserInterface public class OsuAnimatedButton : OsuClickableContainer { /// - /// The colour that should be flashed when the is clicked. + /// The colour that should be flashed when the is clicked. /// protected Color4 FlashColour = Color4.White.Opacity(0.3f); private Color4 hoverColour = Color4.White.Opacity(0.1f); /// - /// The background colour of the while it is hovered. + /// The background colour of the while it is hovered. /// protected Color4 HoverColour { From 3202110b80d805aed875587ac4935af6ea268cab Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Mon, 10 Jun 2019 20:17:44 +0300 Subject: [PATCH 1139/5608] Add a container for Beatmap Availability --- .../API/Requests/Responses/APIBeatmapSet.cs | 3 - .../BeatmapSet/BeatmapNotAvailable.cs | 69 +++++++++++++++++++ osu.Game/Overlays/BeatmapSet/Header.cs | 62 ++++++++++++----- 3 files changed, 112 insertions(+), 22 deletions(-) create mode 100644 osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 2b8a783e2e..82af723a9a 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -63,9 +63,6 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"availability")] private BeatmapSetOnlineAvailability availability { get; set; } - [JsonProperty(@"download_unavailable")] - private bool test { get; set; } - [JsonProperty(@"beatmaps")] private IEnumerable beatmaps { get; set; } diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs b/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs new file mode 100644 index 0000000000..15463b353a --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs @@ -0,0 +1,69 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Text; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.BeatmapSet +{ + public class BeatmapNotAvailable : Container + { + private LinkFlowContainer linkContainer; + + public override void Show() + { + AutoSizeAxes = Axes.Both; + Margin = new MarginPadding() { Top = 10 }; + + Children = new Drawable[] + { + new Box + { + Colour = Color4.Black.Opacity(0.6f), + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Margin = new MarginPadding() { Top = 10, Left = 5, Right = 20 }, + + Children = new Drawable[] + { + new OsuSpriteText + { + Margin = new MarginPadding() { Bottom = 10, Horizontal = 5 }, + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium), + Text = "This beatmap is currently not available for download.", + Colour = Color4.Orange, + }, + linkContainer = new LinkFlowContainer(text => text.Font = OsuFont.GetFont(size: 14)) + { + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Bottom = 10, Horizontal = 5 }, + }, + }, + }, + }; + + base.Show(); + } + + public string Link + { + set => linkContainer.AddLink("Check here for more information.", value); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index a0f71d05c0..0b24a8cdd8 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.BeatmapSet.Buttons; @@ -32,6 +33,7 @@ namespace osu.Game.Overlays.BeatmapSet private readonly UpdateableBeatmapSetCover cover; private readonly OsuSpriteText title, artist; private readonly AuthorInfo author; + private readonly BeatmapNotAvailable unavailableContainer; private readonly FillFlowContainer downloadButtonsContainer; private readonly BeatmapSetOnlineStatusPill onlineStatusPill; public Details Details; @@ -134,6 +136,7 @@ namespace osu.Game.Overlays.BeatmapSet Margin = new MarginPadding { Top = 20 }, Child = author = new AuthorInfo(), }, + unavailableContainer = new BeatmapNotAvailable(), new Container { RelativeSizeAxes = Axes.X, @@ -207,6 +210,18 @@ namespace osu.Game.Overlays.BeatmapSet downloadButtonsContainer.FadeOut(transition_duration); favouriteButton.FadeOut(transition_duration); } + + if (setInfo.NewValue?.OnlineInfo.Availability?.DownloadDisabled ?? false) + { + this.ResizeHeightTo(460, transition_duration / 2); + unavailableContainer.Show(); + unavailableContainer.Link = setInfo.NewValue.OnlineInfo.Availability.ExternalLink; + } + else + { + this.ResizeHeightTo(400, transition_duration / 2); + unavailableContainer.Hide(); + } updateDownloadButtons(); }, true); @@ -216,28 +231,37 @@ namespace osu.Game.Overlays.BeatmapSet { if (BeatmapSet.Value == null) return; - switch (State.Value) + if (BeatmapSet.Value.OnlineInfo.Availability?.DownloadDisabled ?? false) { - case DownloadState.LocallyAvailable: - // temporary for UX until new design is implemented. - downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet.Value) - { - Width = 50, - RelativeSizeAxes = Axes.Y - }; - break; + downloadButtonsContainer.RemoveAll(x => true); + return; + } - case DownloadState.Downloading: - case DownloadState.Downloaded: - // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. - downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); - break; + else + { + switch (State.Value) + { + case DownloadState.LocallyAvailable: + // temporary for UX until new design is implemented. + downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet.Value) + { + Width = 50, + RelativeSizeAxes = Axes.Y + }; + break; - default: - downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); - if (BeatmapSet.Value.OnlineInfo.HasVideo) - downloadButtonsContainer.Add(new DownloadButton(BeatmapSet.Value, true)); - break; + case DownloadState.Downloading: + case DownloadState.Downloaded: + // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. + downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); + break; + + default: + downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); + if (BeatmapSet.Value.OnlineInfo.HasVideo) + downloadButtonsContainer.Add(new DownloadButton(BeatmapSet.Value, true)); + break; + } } } } From 70fdd4ba5b4fe1cafca5dbbe84d1eca9e6cf4c57 Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Mon, 10 Jun 2019 21:13:37 +0300 Subject: [PATCH 1140/5608] Disable download button + Fix AppVeyor Errors --- osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs | 2 +- .../BeatmapSet/BeatmapNotAvailable.cs | 10 ++--- osu.Game/Overlays/BeatmapSet/Header.cs | 44 +++++++++---------- osu.Game/Overlays/BeatmapSetOverlay.cs | 2 +- osu.Game/Overlays/Direct/DownloadButton.cs | 6 +++ 5 files changed, 31 insertions(+), 33 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs index e88def6321..ea3f0b61b9 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs @@ -78,7 +78,7 @@ namespace osu.Game.Beatmaps [JsonProperty(@"cover@2x")] public string Cover { get; set; } - + public string CardLowRes { get; set; } [JsonProperty(@"card@2x")] diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs b/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs index 15463b353a..b893fd0703 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs @@ -1,9 +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.Collections.Generic; -using System.Text; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -11,7 +8,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet @@ -23,7 +19,7 @@ namespace osu.Game.Overlays.BeatmapSet public override void Show() { AutoSizeAxes = Axes.Both; - Margin = new MarginPadding() { Top = 10 }; + Margin = new MarginPadding { Top = 10 }; Children = new Drawable[] { @@ -36,13 +32,13 @@ namespace osu.Game.Overlays.BeatmapSet { AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, - Margin = new MarginPadding() { Top = 10, Left = 5, Right = 20 }, + Margin = new MarginPadding { Top = 10, Left = 5, Right = 20 }, Children = new Drawable[] { new OsuSpriteText { - Margin = new MarginPadding() { Bottom = 10, Horizontal = 5 }, + Margin = new MarginPadding { Bottom = 10, Horizontal = 5 }, Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium), Text = "This beatmap is currently not available for download.", Colour = Color4.Orange, diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 0b24a8cdd8..9a4e7d4754 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.BeatmapSet.Buttons; @@ -210,7 +209,7 @@ namespace osu.Game.Overlays.BeatmapSet downloadButtonsContainer.FadeOut(transition_duration); favouriteButton.FadeOut(transition_duration); } - + if (setInfo.NewValue?.OnlineInfo.Availability?.DownloadDisabled ?? false) { this.ResizeHeightTo(460, transition_duration / 2); @@ -237,31 +236,28 @@ namespace osu.Game.Overlays.BeatmapSet return; } - else + switch (State.Value) { - switch (State.Value) - { - case DownloadState.LocallyAvailable: - // temporary for UX until new design is implemented. - downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet.Value) - { - Width = 50, - RelativeSizeAxes = Axes.Y - }; - break; + case DownloadState.LocallyAvailable: + // temporary for UX until new design is implemented. + downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet.Value) + { + Width = 50, + RelativeSizeAxes = Axes.Y + }; + break; - case DownloadState.Downloading: - case DownloadState.Downloaded: - // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. - downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); - break; + case DownloadState.Downloading: + case DownloadState.Downloaded: + // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. + downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); + break; - default: - downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); - if (BeatmapSet.Value.OnlineInfo.HasVideo) - downloadButtonsContainer.Add(new DownloadButton(BeatmapSet.Value, true)); - break; - } + default: + downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); + if (BeatmapSet.Value.OnlineInfo.HasVideo) + downloadButtonsContainer.Add(new DownloadButton(BeatmapSet.Value, true)); + break; } } } diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index b7331f551e..8d3d78e79a 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -121,7 +121,7 @@ namespace osu.Game.Overlays public void ShowBeatmapSet(BeatmapSetInfo set) { // Re-fetching is the correct way forward. - FetchAndShowBeatmapSet((int)set.OnlineBeatmapSetID); + FetchAndShowBeatmapSet(set.OnlineBeatmapSetID ?? 0); scroll.ScrollTo(0); } } diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 3f44d854e5..deccf819ea 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -77,6 +77,12 @@ namespace osu.Game.Overlays.Direct { this.colours = colours; + if (BeatmapSet.Value.OnlineInfo.Availability?.DownloadDisabled ?? false) + { + button.Enabled.Value = false; + button.TooltipText = "Unavailable"; + } + button.Action = () => { switch (State.Value) From 75716af25e67f997a669096e0cddc012c6b5e881 Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Mon, 10 Jun 2019 21:14:12 +0300 Subject: [PATCH 1141/5608] Forgot to return --- osu.Game/Overlays/Direct/DownloadButton.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index deccf819ea..33e09e95aa 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -81,6 +81,7 @@ namespace osu.Game.Overlays.Direct { button.Enabled.Value = false; button.TooltipText = "Unavailable"; + return; } button.Action = () => From fc3e1e6a8686ccb1a8a85af180f3da3302910ade Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Mon, 10 Jun 2019 21:50:08 +0300 Subject: [PATCH 1142/5608] Fix issue --- osu.Game/Overlays/BeatmapSetOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 8d3d78e79a..6bd2e1b72e 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -121,7 +121,7 @@ namespace osu.Game.Overlays public void ShowBeatmapSet(BeatmapSetInfo set) { // Re-fetching is the correct way forward. - FetchAndShowBeatmapSet(set.OnlineBeatmapSetID ?? 0); + FetchAndShowBeatmapSet(set?.OnlineBeatmapSetID ?? 0); scroll.ScrollTo(0); } } From 94a7794ff71382d93cd28397aecb74d8ae95697a Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 10 Jun 2019 21:54:33 +0300 Subject: [PATCH 1143/5608] Fix issue --- osu.Game/Overlays/BeatmapSetOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 8d3d78e79a..6bd2e1b72e 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -121,7 +121,7 @@ namespace osu.Game.Overlays public void ShowBeatmapSet(BeatmapSetInfo set) { // Re-fetching is the correct way forward. - FetchAndShowBeatmapSet(set.OnlineBeatmapSetID ?? 0); + FetchAndShowBeatmapSet(set?.OnlineBeatmapSetID ?? 0); scroll.ScrollTo(0); } } From d4ba67747b37f4db9a0a482a5fef54470a6bcbfc Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 10 Jun 2019 18:58:03 +0900 Subject: [PATCH 1144/5608] fix test count --- .idea/.idea.osu/.idea/.name | 1 + .../Visual/SongSelect/TestScenePlaySongSelect.cs | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 .idea/.idea.osu/.idea/.name diff --git a/.idea/.idea.osu/.idea/.name b/.idea/.idea.osu/.idea/.name new file mode 100644 index 0000000000..21cb4db60e --- /dev/null +++ b/.idea/.idea.osu/.idea/.name @@ -0,0 +1 @@ +osu \ No newline at end of file diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index bc15bc6b6d..fa73a14252 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -11,6 +11,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Extensions; +using osu.Framework.Logging; using osu.Framework.MathUtils; using osu.Framework.Platform; using osu.Framework.Screens; @@ -215,11 +216,13 @@ namespace osu.Game.Tests.Visual.SongSelect { const int test_count = 10; int beatmapChangedCount = 0; + int debounceCount = 0; createSongSelect(); - AddStep("Setup counter", () => + AddStep("Setup counters", () => { beatmapChangedCount = 0; - songSelect.Carousel.SelectionChanged += _ => beatmapChangedCount++; + debounceCount = 0; + songSelect.Carousel.SelectionChanged += _ => beatmapChangedCount += 1; }); AddRepeatStep($"Create beatmaps {test_count} times", () => { @@ -229,10 +232,14 @@ namespace osu.Game.Tests.Visual.SongSelect { // Wait for debounce songSelect.Carousel.SelectNextRandom(); + ++debounceCount; }, 400); }, test_count); - AddAssert($"Beatmap changed {test_count} times", () => beatmapChangedCount == test_count); + AddUntilStep("Debounce limit reached", () => debounceCount == test_count); + + // The selected beatmap should have changed an additional 2 times since both initially loading songselect and the first import also triggers selectionChanged + AddAssert($"Beatmap changed {test_count + 2} times", () => beatmapChangedCount == test_count + 2); } [Test] From 609a82bc948dc14f8e604aa932d71b470e8657a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Jun 2019 14:28:52 +0900 Subject: [PATCH 1145/5608] Update VisibilityContainer usage in line with framework --- osu.Desktop/OsuGameDesktop.cs | 9 ++---- .../TestSceneResumeOverlay.cs | 4 +-- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 2 +- .../Visual/Gameplay/TestSceneFailAnimation.cs | 2 +- .../Gameplay/TestSceneGameplayMenuOverlay.cs | 6 ++-- .../Visual/Gameplay/TestScenePause.cs | 4 +-- .../Visual/Gameplay/TestSceneStoryboard.cs | 2 +- .../Visual/Menus/TestSceneToolbar.cs | 2 +- .../TestSceneMatchSettingsOverlay.cs | 2 +- .../Online/TestSceneAccountCreationOverlay.cs | 2 +- .../Visual/Online/TestSceneChatDisplay.cs | 2 +- .../Visual/Settings/TestSceneSettings.cs | 2 +- .../SongSelect/TestSceneBeatmapInfoWedge.cs | 9 +++--- .../Visual/UserInterface/TestSceneCursors.cs | 4 +-- .../UserInterface/TestSceneMusicController.cs | 4 +-- .../TestSceneNotificationOverlay.cs | 2 +- .../UserInterface/TestScenePopupDialog.cs | 2 +- .../Containers/OsuFocusedOverlayContainer.cs | 12 ++++---- osu.Game/Graphics/Containers/WaveContainer.cs | 4 +-- .../Graphics/Cursor/MenuCursorContainer.cs | 2 +- .../UserInterface/BreadcrumbControl.cs | 4 +++ .../UserInterface/ProcessingOverlay.cs | 2 +- osu.Game/OsuGame.cs | 28 +++++++++---------- osu.Game/Overlays/AccountCreationOverlay.cs | 2 +- osu.Game/Overlays/BeatmapSetOverlay.cs | 2 +- osu.Game/Overlays/ChangelogOverlay.cs | 8 +++--- osu.Game/Overlays/ChatOverlay.cs | 24 ++++++++-------- osu.Game/Overlays/DialogOverlay.cs | 8 +++--- osu.Game/Overlays/DirectOverlay.cs | 2 +- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 4 +-- osu.Game/Overlays/Music/PlaylistOverlay.cs | 2 +- osu.Game/Overlays/MusicController.cs | 4 +-- osu.Game/Overlays/NotificationOverlay.cs | 8 +++--- .../Sections/General/LoginSettings.cs | 2 +- osu.Game/Overlays/SettingsOverlay.cs | 11 ++++---- osu.Game/Overlays/Toolbar/Toolbar.cs | 4 +-- .../Toolbar/ToolbarOverlayToggleButton.cs | 20 ++++++------- osu.Game/Overlays/VolumeOverlay.cs | 6 ++-- .../Rulesets/UI/GameplayCursorContainer.cs | 2 +- osu.Game/Screens/Menu/ButtonArea.cs | 8 ++++-- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 2 +- .../Screens/Play/HUD/PlayerSettingsOverlay.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Play/SkipOverlay.cs | 14 ++++++---- osu.Game/Screens/Play/SongProgress.cs | 2 +- osu.Game/Screens/Select/BeatmapDetails.cs | 4 +-- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 4 +-- osu.Game/osu.Game.csproj | 4 ++- osu.sln | 12 ++++++++ 50 files changed, 150 insertions(+), 127 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 00cabbadf7..975b7f9f5a 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; using osu.Desktop.Overlays; -using osu.Framework.Graphics.Containers; using osu.Framework.Platform; using osu.Game; using osuTK.Input; @@ -56,7 +55,7 @@ namespace osu.Desktop LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, v => { Add(v); - v.State = Visibility.Visible; + v.Show(); }); if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows) @@ -74,13 +73,11 @@ namespace osu.Desktop { case Intro _: case MainMenu _: - if (versionManager != null) - versionManager.State = Visibility.Visible; + versionManager?.Show(); break; default: - if (versionManager != null) - versionManager.State = Visibility.Hidden; + versionManager?.Hide(); break; } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs index 12a3a8d27e..8e73d6152f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs @@ -46,11 +46,11 @@ namespace osu.Game.Rulesets.Osu.Tests AddStep("move mouse away", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.TopLeft)); AddStep("click", () => osuInputManager.GameClick()); - AddAssert("not dismissed", () => !resumeFired && resume.State == Visibility.Visible); + AddAssert("not dismissed", () => !resumeFired && resume.State.Value == Visibility.Visible); AddStep("move mouse back", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.Centre)); AddStep("click", () => osuInputManager.GameClick()); - AddAssert("dismissed", () => resumeFired && resume.State == Visibility.Hidden); + AddAssert("dismissed", () => resumeFired && resume.State.Value == Visibility.Hidden); } private class ManualOsuInputManager : OsuInputManager diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 0d4e7edb7b..9e5df0d6b1 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.UI private GameplayCursorContainer localCursorContainer; - public override CursorContainer LocalCursor => State == Visibility.Visible ? localCursorContainer : null; + public override CursorContainer LocalCursor => State.Value == Visibility.Visible ? localCursorContainer : null; protected override string Message => "Click the orange cursor to resume"; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs index 4878587dcd..f06f72615b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs @@ -28,7 +28,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void AddCheckSteps() { AddUntilStep("wait for fail", () => Player.HasFailed); - AddUntilStep("wait for fail overlay", () => ((FailPlayer)Player).FailOverlay.State == Visibility.Visible); + AddUntilStep("wait for fail overlay", () => ((FailPlayer)Player).FailOverlay.State.Value == Visibility.Visible); } private class FailPlayer : TestPlayer diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs index ba9c583b08..4727140d99 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs @@ -97,7 +97,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("Show overlay", () => pauseOverlay.Show()); AddStep("Press select", () => press(GlobalAction.Select)); - AddAssert("Overlay still open", () => pauseOverlay.State == Visibility.Visible); + AddAssert("Overlay still open", () => pauseOverlay.State.Value == Visibility.Visible); AddStep("Hide overlay", () => pauseOverlay.Hide()); } @@ -237,7 +237,7 @@ namespace osu.Game.Tests.Visual.Gameplay }); AddAssert("Action was triggered", () => triggered); - AddAssert("Overlay is closed", () => pauseOverlay.State == Visibility.Hidden); + AddAssert("Overlay is closed", () => pauseOverlay.State.Value == Visibility.Hidden); } /// @@ -272,7 +272,7 @@ namespace osu.Game.Tests.Visual.Gameplay return triggered; }); - AddAssert("Overlay is closed", () => pauseOverlay.State == Visibility.Hidden); + AddAssert("Overlay is closed", () => pauseOverlay.State.Value == Visibility.Hidden); } private void press(Key key) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 12e91df77c..0de0fcfc38 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -203,9 +203,9 @@ namespace osu.Game.Tests.Visual.Gameplay public new HUDOverlay HUDOverlay => base.HUDOverlay; - public bool FailOverlayVisible => FailOverlay.State == Visibility.Visible; + public bool FailOverlayVisible => FailOverlay.State.Value == Visibility.Visible; - public bool PauseOverlayVisible => PauseOverlay.State == Visibility.Visible; + public bool PauseOverlayVisible => PauseOverlay.State.Value == Visibility.Visible; public override void OnEntering(IScreen last) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs index 213cdf5e48..ead7a4b7fc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs @@ -46,7 +46,7 @@ namespace osu.Game.Tests.Visual.Gameplay { Origin = Anchor.TopRight, Anchor = Anchor.TopRight, - State = Visibility.Visible, + State = { Value = Visibility.Visible }, }); AddStep("Restart", restart); diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index 0c789d8cb7..0df6605cdd 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.Menus public TestSceneToolbar() { - var toolbar = new Toolbar { State = Visibility.Visible }; + var toolbar = new Toolbar { State = { Value = Visibility.Visible } }; ToolbarNotificationButton notificationButton = null; AddStep("create toolbar", () => diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs index 8091e93471..8d842fc865 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs @@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.Multiplayer settings = new TestRoomSettings { RelativeSizeAxes = Axes.Both, - State = Visibility.Visible + State = { Value = Visibility.Visible } }; Child = settings; diff --git a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs index a7e725ec3f..35449f5687 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs @@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual.Online api.Logout(); api.LocalUser.BindValueChanged(user => { userPanelArea.Child = new UserPanel(user.NewValue) { Width = 200 }; }, true); - AddStep("show", () => accountCreation.State = Visibility.Visible); + AddStep("show", () => accountCreation.Show()); AddStep("logout", () => api.Logout()); } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatDisplay.cs index 634176e65f..2789feef3d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatDisplay.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Online Children = new Drawable[] { channelManager, - new ChatOverlay { State = Visibility.Visible } + new ChatOverlay { State = { Value = Visibility.Visible } } }; } } diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettings.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettings.cs index 964754f8d0..f97ce8c69e 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettings.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettings.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Settings { settings = new SettingsOverlay { - State = Visibility.Visible + State = { Value = Visibility.Visible } }; Add(dialogOverlay = new DialogOverlay { diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index 9969795ecf..932e114580 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; @@ -7,7 +7,6 @@ using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; @@ -48,7 +47,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("show", () => { - infoWedge.State = Visibility.Visible; + infoWedge.Show(); infoWedge.Beatmap = Beatmap.Value; }); @@ -57,11 +56,11 @@ namespace osu.Game.Tests.Visual.SongSelect AddWaitStep("wait for select", 3); - AddStep("hide", () => { infoWedge.State = Visibility.Hidden; }); + AddStep("hide", () => { infoWedge.Hide(); }); AddWaitStep("wait for hide", 3); - AddStep("show", () => { infoWedge.State = Visibility.Visible; }); + AddStep("show", () => { infoWedge.Show(); }); foreach (var rulesetInfo in rulesets.AvailableRulesets) { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs index 8fe31b7ad6..e7dbbc8bc4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs @@ -176,7 +176,7 @@ namespace osu.Game.Tests.Visual.UserInterface /// Checks if a cursor is visible. /// /// The cursor to check. - private bool checkVisible(CursorContainer cursorContainer) => cursorContainer.State == Visibility.Visible; + private bool checkVisible(CursorContainer cursorContainer) => cursorContainer.State.Value == Visibility.Visible; /// /// Checks if a cursor is at the current inputmanager screen position. @@ -218,7 +218,7 @@ namespace osu.Game.Tests.Visual.UserInterface }, Cursor = new TestCursorContainer { - State = providesUserCursor ? Visibility.Hidden : Visibility.Visible, + State = { Value = providesUserCursor ? Visibility.Hidden : Visibility.Visible }, } }; } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs index a62fd6467b..2f2a40925f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs @@ -23,8 +23,8 @@ namespace osu.Game.Tests.Visual.UserInterface }; Add(mc); - AddToggleStep(@"toggle visibility", state => mc.State = state ? Visibility.Visible : Visibility.Hidden); - AddStep(@"show", () => mc.State = Visibility.Visible); + AddToggleStep(@"toggle visibility", state => mc.State.Value = state ? Visibility.Visible : Visibility.Hidden); + AddStep(@"show", () => mc.Show()); AddToggleStep(@"toggle beatmap lock", state => Beatmap.Disabled = state); } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs index 71033fcd2f..6b7427cef5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.UserInterface Content.Add(displayedCount); - void setState(Visibility state) => AddStep(state.ToString(), () => manager.State = state); + void setState(Visibility state) => AddStep(state.ToString(), () => manager.State.Value = state); void checkProgressingCount(int expected) => AddAssert($"progressing count is {expected}", () => progressingNotifications.Count == expected); manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count.NewValue}"; }; diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs index 24140125e0..9ddd8f4038 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.UserInterface var popup = new PopupDialog { RelativeSizeAxes = Axes.Both, - State = Framework.Graphics.Containers.Visibility.Visible, + State = { Value = Framework.Graphics.Containers.Visibility.Visible }, Icon = FontAwesome.Solid.AssistiveListeningSystems, HeaderText = @"This is a test popup", BodyText = "I can say lots of stuff and even wrap my words!", diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 8b34459710..f6db3102f2 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -54,7 +54,7 @@ namespace osu.Game.Graphics.Containers samplePopIn = audio.Samples.Get(@"UI/overlay-pop-in"); samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out"); - StateChanged += onStateChanged; + State.ValueChanged += onStateChanged; } /// @@ -70,7 +70,7 @@ namespace osu.Game.Graphics.Containers { if (!base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)) { - State = Visibility.Hidden; + Hide(); return true; } @@ -82,7 +82,7 @@ namespace osu.Game.Graphics.Containers switch (action) { case GlobalAction.Back: - State = Visibility.Hidden; + Hide(); return true; case GlobalAction.Select: @@ -94,9 +94,9 @@ namespace osu.Game.Graphics.Containers public bool OnReleased(GlobalAction action) => false; - private void onStateChanged(Visibility visibility) + private void onStateChanged(ValueChangedEvent state) { - switch (visibility) + switch (state.NewValue) { case Visibility.Visible: if (OverlayActivationMode.Value != OverlayActivation.Disabled) @@ -105,7 +105,7 @@ namespace osu.Game.Graphics.Containers if (BlockScreenWideMouse && DimMainContent) osuGame?.AddBlockingOverlay(this); } else - State = Visibility.Hidden; + Hide(); break; diff --git a/osu.Game/Graphics/Containers/WaveContainer.cs b/osu.Game/Graphics/Containers/WaveContainer.cs index 464682a0ad..f87909ab17 100644 --- a/osu.Game/Graphics/Containers/WaveContainer.cs +++ b/osu.Game/Graphics/Containers/WaveContainer.cs @@ -103,7 +103,7 @@ namespace osu.Game.Graphics.Containers protected override void PopIn() { foreach (var w in wavesContainer.Children) - w.State = Visibility.Visible; + w.Show(); this.FadeIn(100, Easing.OutQuint); contentContainer.MoveToY(0, APPEAR_DURATION, Easing.OutQuint); @@ -117,7 +117,7 @@ namespace osu.Game.Graphics.Containers contentContainer.MoveToY(DrawHeight * 2f, DISAPPEAR_DURATION, Easing.In); foreach (var w in wavesContainer.Children) - w.State = Visibility.Hidden; + w.Hide(); this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint); } diff --git a/osu.Game/Graphics/Cursor/MenuCursorContainer.cs b/osu.Game/Graphics/Cursor/MenuCursorContainer.cs index 92e5ba6195..b7ea1ba56a 100644 --- a/osu.Game/Graphics/Cursor/MenuCursorContainer.cs +++ b/osu.Game/Graphics/Cursor/MenuCursorContainer.cs @@ -29,7 +29,7 @@ namespace osu.Game.Graphics.Cursor { AddRangeInternal(new Drawable[] { - Cursor = new MenuCursor { State = Visibility.Hidden }, + Cursor = new MenuCursor { State = { Value = Visibility.Hidden } }, content = new Container { RelativeSizeAxes = Axes.Both } }); } diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index f5e57e5f27..d1e55fee24 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -82,6 +82,10 @@ namespace osu.Game.Graphics.UserInterface } } + public override void Hide() => State = Visibility.Hidden; + + public override void Show() => State = Visibility.Visible; + public BreadcrumbTabItem(T value) : base(value) { diff --git a/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs b/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs index 8b50f4a97a..d75e78e2d9 100644 --- a/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs +++ b/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs @@ -34,7 +34,7 @@ namespace osu.Game.Graphics.UserInterface RelativeSizeAxes = Axes.Both, Alpha = 0.9f, }, - new LoadingAnimation { State = Visibility.Visible } + new LoadingAnimation { State = { Value = Visibility.Visible } } }; } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ba9abcdefc..d5fbcdfee3 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -132,12 +132,12 @@ namespace osu.Game public void CloseAllOverlays(bool hideToolbarElements = true) { foreach (var overlay in overlays) - overlay.State = Visibility.Hidden; + overlay.Hide(); if (hideToolbarElements) { foreach (var overlay in toolbarElements) - overlay.State = Visibility.Hidden; + overlay.Hide(); } } @@ -461,7 +461,7 @@ namespace osu.Game loadComponentSingleFile(new DialogOverlay(), topMostOverlayContent.Add, true); loadComponentSingleFile(externalLinkOpener = new ExternalLinkOpener(), topMostOverlayContent.Add); - chatOverlay.StateChanged += state => channelManager.HighPollRate.Value = state == Visibility.Visible; + chatOverlay.State.ValueChanged += state => channelManager.HighPollRate.Value = state.NewValue == Visibility.Visible; Add(externalLinkOpener = new ExternalLinkOpener()); @@ -470,9 +470,9 @@ namespace osu.Game foreach (var overlay in singleDisplaySideOverlays) { - overlay.StateChanged += state => + overlay.State.ValueChanged += state => { - if (state == Visibility.Hidden) return; + if (state.NewValue == Visibility.Hidden) return; singleDisplaySideOverlays.Where(o => o != overlay).ForEach(o => o.Hide()); }; @@ -484,9 +484,9 @@ namespace osu.Game foreach (var overlay in informationalOverlays) { - overlay.StateChanged += state => + overlay.State.ValueChanged += state => { - if (state == Visibility.Hidden) return; + if (state.NewValue == Visibility.Hidden) return; informationalOverlays.Where(o => o != overlay).ForEach(o => o.Hide()); }; @@ -498,12 +498,12 @@ namespace osu.Game foreach (var overlay in singleDisplayOverlays) { - overlay.StateChanged += state => + overlay.State.ValueChanged += state => { // informational overlays should be dismissed on a show or hide of a full overlay. informationalOverlays.ForEach(o => o.Hide()); - if (state == Visibility.Hidden) return; + if (state.NewValue == Visibility.Hidden) return; singleDisplayOverlays.Where(o => o != overlay).ForEach(o => o.Hide()); }; @@ -518,16 +518,16 @@ namespace osu.Game { float offset = 0; - if (settings.State == Visibility.Visible) + if (settings.State.Value == Visibility.Visible) offset += ToolbarButton.WIDTH / 2; - if (notifications.State == Visibility.Visible) + if (notifications.State.Value == Visibility.Visible) offset -= ToolbarButton.WIDTH / 2; screenContainer.MoveToX(offset, SettingsPanel.TRANSITION_LENGTH, Easing.OutQuint); } - settings.StateChanged += _ => updateScreenOffset(); - notifications.StateChanged += _ => updateScreenOffset(); + settings.State.ValueChanged += _ => updateScreenOffset(); + notifications.State.ValueChanged += _ => updateScreenOffset(); } public class GameIdleTracker : IdleTracker @@ -768,7 +768,7 @@ namespace osu.Game if (newOsuScreen.HideOverlaysOnEnter) CloseAllOverlays(); else - Toolbar.State = Visibility.Visible; + Toolbar.Show(); } } diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs index 52d2917677..89d8cbde11 100644 --- a/osu.Game/Overlays/AccountCreationOverlay.cs +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -109,7 +109,7 @@ namespace osu.Game.Overlays break; case APIState.Online: - State = Visibility.Hidden; + Hide(); break; } } diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 3ed398d31a..e0852a890c 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -92,7 +92,7 @@ namespace osu.Game.Overlays protected override bool OnClick(ClickEvent e) { - State = Visibility.Hidden; + Hide(); return true; } diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 4a6d53b480..67f195580e 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -92,7 +92,7 @@ namespace osu.Game.Overlays public void ShowListing() { Current.Value = null; - State = Visibility.Visible; + Show(); } /// @@ -106,7 +106,7 @@ namespace osu.Game.Overlays if (build == null) throw new ArgumentNullException(nameof(build)); Current.Value = build; - State = Visibility.Visible; + Show(); } public void ShowBuild([NotNull] string updateStream, [NotNull] string version) @@ -123,7 +123,7 @@ namespace osu.Game.Overlays ShowBuild(build); }); - State = Visibility.Visible; + Show(); } public override bool OnPressed(GlobalAction action) @@ -133,7 +133,7 @@ namespace osu.Game.Overlays case GlobalAction.Back: if (Current.Value == null) { - State = Visibility.Hidden; + Hide(); } else { diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index eb95fabe02..0c1cca3d49 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -56,7 +56,7 @@ namespace osu.Game.Overlays private readonly Container channelSelectionContainer; private readonly ChannelSelectionOverlay channelSelectionOverlay; - public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceivePositionalInputAt(screenSpacePos) || channelSelectionOverlay.State == Visibility.Visible && channelSelectionOverlay.ReceivePositionalInputAt(screenSpacePos); + public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceivePositionalInputAt(screenSpacePos) || channelSelectionOverlay.State.Value == Visibility.Visible && channelSelectionOverlay.ReceivePositionalInputAt(screenSpacePos); public ChatOverlay() { @@ -130,7 +130,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Height = 1, PlaceholderText = "type your message", - Exit = () => State = Visibility.Hidden, + Exit = Hide, OnCommit = postMessage, ReleaseFocusOnCommit = false, HoldFocus = true, @@ -163,19 +163,19 @@ namespace osu.Game.Overlays }; channelTabControl.Current.ValueChanged += current => channelManager.CurrentChannel.Value = current.NewValue; - channelTabControl.ChannelSelectorActive.ValueChanged += active => channelSelectionOverlay.State = active.NewValue ? Visibility.Visible : Visibility.Hidden; - channelSelectionOverlay.StateChanged += state => + channelTabControl.ChannelSelectorActive.ValueChanged += active => channelSelectionOverlay.State.Value = active.NewValue ? Visibility.Visible : Visibility.Hidden; + channelSelectionOverlay.State.ValueChanged += state => { - if (state == Visibility.Hidden && channelManager.CurrentChannel.Value == null) + if (state.NewValue == Visibility.Hidden && channelManager.CurrentChannel.Value == null) { - channelSelectionOverlay.State = Visibility.Visible; - State = Visibility.Hidden; + channelSelectionOverlay.Show(); + Hide(); return; } - channelTabControl.ChannelSelectorActive.Value = state == Visibility.Visible; + channelTabControl.ChannelSelectorActive.Value = state.NewValue == Visibility.Visible; - if (state == Visibility.Visible) + if (state.NewValue == Visibility.Visible) { textbox.HoldFocus = false; if (1f - ChatHeight.Value < channel_selection_min_height) @@ -195,7 +195,7 @@ namespace osu.Game.Overlays { textbox.Current.Disabled = true; currentChannelContainer.Clear(false); - channelSelectionOverlay.State = Visibility.Visible; + channelSelectionOverlay.Show(); return; } @@ -253,7 +253,7 @@ namespace osu.Game.Overlays double targetChatHeight = startDragChatHeight - (e.MousePosition.Y - e.MouseDownPosition.Y) / Parent.DrawSize.Y; // If the channel selection screen is shown, mind its minimum height - if (channelSelectionOverlay.State == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height) + if (channelSelectionOverlay.State.Value == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height) targetChatHeight = 1f - channel_selection_min_height; ChatHeight.Value = targetChatHeight; @@ -325,7 +325,7 @@ namespace osu.Game.Overlays this.MoveToY(Height, transition_length, Easing.InSine); this.FadeOut(transition_length, Easing.InSine); - channelSelectionOverlay.State = Visibility.Hidden; + channelSelectionOverlay.Hide(); textbox.HoldFocus = false; base.PopOut(); diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index 2cc1c20a10..aaae7bcf5c 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -37,8 +37,8 @@ namespace osu.Game.Overlays dialogContainer.Add(currentDialog); currentDialog.Show(); - currentDialog.StateChanged += state => onDialogOnStateChanged(dialog, state); - State = Visibility.Visible; + currentDialog.State.ValueChanged += state => onDialogOnStateChanged(dialog, state.NewValue); + Show(); } protected override bool PlaySamplesOnStateChange => false; @@ -53,7 +53,7 @@ namespace osu.Game.Overlays dialog.Delay(PopupDialog.EXIT_DURATION).Expire(); if (dialog == currentDialog) - State = Visibility.Hidden; + Hide(); } protected override void PopIn() @@ -66,7 +66,7 @@ namespace osu.Game.Overlays { base.PopOut(); - if (currentDialog?.State == Visibility.Visible) + if (currentDialog?.State.Value == Visibility.Visible) { currentDialog.Hide(); return; diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 975bf4e3ca..7dcf76e41f 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -252,7 +252,7 @@ namespace osu.Game.Overlays if (!IsLoaded) return; - if (State == Visibility.Hidden) + if (State.Value == Visibility.Hidden) return; if (API == null) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index dec58f4c9e..8e5c9588ce 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -413,12 +413,12 @@ namespace osu.Game.Overlays.Mods { if (selectedMod != null) { - if (State == Visibility.Visible) sampleOn?.Play(); + if (State.Value == Visibility.Visible) sampleOn?.Play(); DeselectTypes(selectedMod.IncompatibleMods, true); } else { - if (State == Visibility.Visible) sampleOff?.Play(); + if (State.Value == Visibility.Visible) sampleOff?.Play(); } refreshSelectedMods(); diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 4431288a1a..ec3d708645 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -71,7 +71,7 @@ namespace osu.Game.Overlays.Music { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - ExitRequested = () => State = Visibility.Hidden, + ExitRequested = Hide, FilterChanged = search => list.Filter(search), Padding = new MarginPadding(10), }, diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index d7b915efe3..85524e992c 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -200,7 +200,7 @@ namespace osu.Game.Overlays beatmaps.ItemAdded += handleBeatmapAdded; beatmaps.ItemRemoved += handleBeatmapRemoved; - playlist.StateChanged += s => playlistButton.FadeColour(s == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint); + playlist.State.ValueChanged += s => playlistButton.FadeColour(s.NewValue == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint); } private ScheduledDelegate seekDelegate; @@ -449,7 +449,7 @@ namespace osu.Game.Overlays // This is here mostly as a performance fix. // If the playlist is not hidden it will update children even when the music controller is hidden (due to AlwaysPresent). - playlist.State = Visibility.Hidden; + playlist.Hide(); this.FadeOut(transition_length, Easing.OutQuint); dragContainer.ScaleTo(0.9f, transition_length, Easing.OutQuint); diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 8f75d3ebf0..2e4c504645 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -81,13 +81,13 @@ namespace osu.Game.Overlays private void updateProcessingMode() { - bool enabled = OverlayActivationMode.Value == OverlayActivation.All || State == Visibility.Visible; + bool enabled = OverlayActivationMode.Value == OverlayActivation.All || State.Value == Visibility.Visible; notificationsEnabler?.Cancel(); if (enabled) // we want a slight delay before toggling notifications on to avoid the user becoming overwhelmed. - notificationsEnabler = Scheduler.AddDelayed(() => processingPosts = true, State == Visibility.Visible ? 0 : 1000); + notificationsEnabler = Scheduler.AddDelayed(() => processingPosts = true, State.Value == Visibility.Visible ? 0 : 1000); else processingPosts = false; } @@ -96,7 +96,7 @@ namespace osu.Game.Overlays { base.LoadComplete(); - StateChanged += _ => updateProcessingMode(); + State.ValueChanged += _ => updateProcessingMode(); OverlayActivationMode.BindValueChanged(_ => updateProcessingMode(), true); } @@ -128,7 +128,7 @@ namespace osu.Game.Overlays section?.Add(notification, notification.DisplayOnTop ? -runningDepth : runningDepth); if (notification.IsImportant) - State = Visibility.Visible; + Show(); updateCounts(); }); diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 2f56ace24d..36d6a22165 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -97,7 +97,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { new LoadingAnimation { - State = Visibility.Visible, + State = { Value = Visibility.Visible }, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }, diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 6e3eaae0a1..bb84de5d3a 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -9,6 +9,7 @@ using osu.Game.Overlays.Settings.Sections; using osuTK.Graphics; using System.Collections.Generic; using System.Linq; +using osu.Framework.Bindables; namespace osu.Game.Overlays { @@ -37,23 +38,23 @@ namespace osu.Game.Overlays { } - public override bool AcceptsFocus => subPanels.All(s => s.State != Visibility.Visible); + public override bool AcceptsFocus => subPanels.All(s => s.State.Value != Visibility.Visible); private T createSubPanel(T subPanel) where T : SettingsSubPanel { subPanel.Depth = 1; subPanel.Anchor = Anchor.TopRight; - subPanel.StateChanged += subPanelStateChanged; + subPanel.State.ValueChanged += subPanelStateChanged; subPanels.Add(subPanel); return subPanel; } - private void subPanelStateChanged(Visibility visibility) + private void subPanelStateChanged(ValueChangedEvent state) { - switch (visibility) + switch (state.NewValue) { case Visibility.Visible: Background.FadeTo(0.9f, 300, Easing.OutQuint); @@ -73,7 +74,7 @@ namespace osu.Game.Overlays } } - protected override float ExpandedPosition => subPanels.Any(s => s.State == Visibility.Visible) ? -WIDTH : base.ExpandedPosition; + protected override float ExpandedPosition => subPanels.Any(s => s.State.Value == Visibility.Visible) ? -WIDTH : base.ExpandedPosition; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 3c8b96fe8a..982fb26b6b 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -84,10 +84,10 @@ namespace osu.Game.Overlays.Toolbar } }; - StateChanged += visibility => + State.ValueChanged += visibility => { if (overlayActivationMode.Value == OverlayActivation.Disabled) - State = Visibility.Hidden; + Hide(); }; if (osuGame != null) diff --git a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs index b2ae273e31..b286cbfb1d 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -15,6 +16,8 @@ namespace osu.Game.Overlays.Toolbar private OverlayContainer stateContainer; + private readonly Bindable overlayState = new Bindable(); + public OverlayContainer StateContainer { get => stateContainer; @@ -22,10 +25,12 @@ namespace osu.Game.Overlays.Toolbar { stateContainer = value; + overlayState.UnbindBindings(); + if (stateContainer != null) { Action = stateContainer.ToggleVisibility; - stateContainer.StateChanged += stateChanged; + overlayState.BindTo(stateContainer.State); } } } @@ -40,18 +45,13 @@ namespace osu.Game.Overlays.Toolbar Depth = 2, Alpha = 0, }); + + overlayState.ValueChanged += stateChanged; } - protected override void Dispose(bool isDisposing) + private void stateChanged(ValueChangedEvent state) { - base.Dispose(isDisposing); - if (stateContainer != null) - stateContainer.StateChanged -= stateChanged; - } - - private void stateChanged(Visibility state) - { - switch (state) + switch (state.NewValue) { case Visibility.Hidden: stateBackground.FadeOut(200); diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index 34b15d958d..02e0f59f26 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -100,14 +100,14 @@ namespace osu.Game.Overlays switch (action) { case GlobalAction.DecreaseVolume: - if (State == Visibility.Hidden) + if (State.Value == Visibility.Hidden) Show(); else volumeMeterMaster.Decrease(amount, isPrecise); return true; case GlobalAction.IncreaseVolume: - if (State == Visibility.Hidden) + if (State.Value == Visibility.Hidden) Show(); else volumeMeterMaster.Increase(amount, isPrecise); @@ -126,7 +126,7 @@ namespace osu.Game.Overlays public override void Show() { - if (State == Visibility.Visible) + if (State.Value == Visibility.Visible) schedulePopOut(); base.Show(); diff --git a/osu.Game/Rulesets/UI/GameplayCursorContainer.cs b/osu.Game/Rulesets/UI/GameplayCursorContainer.cs index 41edfa0b68..ae5f9c6111 100644 --- a/osu.Game/Rulesets/UI/GameplayCursorContainer.cs +++ b/osu.Game/Rulesets/UI/GameplayCursorContainer.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.UI protected override void Update() { base.Update(); - LastFrameState = State; + LastFrameState = State.Value; } } } diff --git a/osu.Game/Screens/Menu/ButtonArea.cs b/osu.Game/Screens/Menu/ButtonArea.cs index c7650a08fa..d59996a4eb 100644 --- a/osu.Game/Screens/Menu/ButtonArea.cs +++ b/osu.Game/Screens/Menu/ButtonArea.cs @@ -56,12 +56,12 @@ namespace osu.Game.Screens.Menu case ButtonSystemState.Exit: case ButtonSystemState.Initial: case ButtonSystemState.EnteringMode: - State = Visibility.Hidden; + Hide(); break; case ButtonSystemState.TopLevel: case ButtonSystemState.Play: - State = Visibility.Visible; + Show(); break; } @@ -82,6 +82,10 @@ namespace osu.Game.Screens.Menu } } + public override void Hide() => State = Visibility.Hidden; + + public override void Show() => State = Visibility.Visible; + public event Action StateChanged; private class ButtonAreaBackground : Box, IStateful diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 456fb4faf9..c7e762714c 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Play { RelativeSizeAxes = Axes.Both; - StateChanged += s => selectionIndex = -1; + State.ValueChanged += s => selectionIndex = -1; } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs index e99f6d836e..b2c3952f38 100644 --- a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs +++ b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Play.HUD } }; - State = Visibility.Visible; + Show(); } protected override void PopIn() => this.FadeIn(fade_duration); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d8389fa6d9..35ef7b3200 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -358,7 +358,7 @@ namespace osu.Game.Screens.Play // There is a chance that we could be in a paused state as the ruleset's internal clock (see FrameStabilityContainer) // could process an extra frame after the GameplayClock is stopped. // In such cases we want the fail state to precede a user triggered pause. - if (PauseOverlay.State == Visibility.Visible) + if (PauseOverlay.State.Value == Visibility.Visible) PauseOverlay.Hide(); failAnimation.Start(); diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 4ecc15f22b..38dd179f25 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Play { this.startTime = startTime; - State = Visibility.Visible; + Show(); RelativePositionAxes = Axes.Both; RelativeSizeAxes = Axes.X; @@ -136,7 +136,7 @@ namespace osu.Game.Screens.Play protected override bool OnMouseMove(MouseMoveEvent e) { if (!e.HasAnyButtonPressed) - fadeContainer.State = Visibility.Visible; + fadeContainer.Show(); return base.OnMouseMove(e); } @@ -181,7 +181,7 @@ namespace osu.Game.Screens.Play if (!IsHovered && !IsDragged) using (BeginDelayedSequence(1000)) - scheduledHide = Schedule(() => State = Visibility.Hidden); + scheduledHide = Schedule(Hide); break; case Visibility.Hidden: @@ -196,7 +196,7 @@ namespace osu.Game.Screens.Play protected override void LoadComplete() { base.LoadComplete(); - State = Visibility.Visible; + Show(); } protected override bool OnMouseDown(MouseDownEvent e) @@ -207,9 +207,13 @@ namespace osu.Game.Screens.Play protected override bool OnMouseUp(MouseUpEvent e) { - State = Visibility.Visible; + Show(); return base.OnMouseUp(e); } + + public override void Hide() => State = Visibility.Hidden; + + public override void Show() => State = Visibility.Visible; } private class Button : OsuClickableContainer diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index d478454f00..6642efdf8b 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -106,7 +106,7 @@ namespace osu.Game.Screens.Play protected override void LoadComplete() { - State = Visibility.Visible; + Show(); replayLoaded.ValueChanged += loaded => AllowSeeking = loaded.NewValue; replayLoaded.TriggerChange(); diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index a78ab97960..378b1b1dc6 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -360,13 +360,13 @@ namespace osu.Game.Screens.Select protected override void PopIn() { this.FadeIn(transition_duration, Easing.OutQuint); - loading.State = Visibility.Visible; + loading.Show(); } protected override void PopOut() { this.FadeOut(transition_duration, Easing.OutQuint); - loading.State = Visibility.Hidden; + loading.Hide(); } } } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 1508de2730..fa9ffd0706 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Select { void removeOldInfo() { - State = beatmap == null ? Visibility.Hidden : Visibility.Visible; + State.Value = beatmap == null ? Visibility.Hidden : Visibility.Visible; Info?.FadeOut(250); Info?.Expire(); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 6d5be607f4..5390d24892 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -278,7 +278,7 @@ namespace osu.Game.Screens.Select protected virtual void ExitFromBack() { - if (ModSelect.State == Visibility.Visible) + if (ModSelect.State.Value == Visibility.Visible) { ModSelect.Hide(); return; @@ -520,7 +520,7 @@ namespace osu.Game.Screens.Select if (base.OnExiting(next)) return true; - beatmapInfoWedge.State = Visibility.Hidden; + beatmapInfoWedge.Hide(); this.FadeOut(100); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index eeb1f2bee3..fb27caca11 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,10 +15,12 @@ - + + + diff --git a/osu.sln b/osu.sln index 3c38309d86..a106ab2800 100644 --- a/osu.sln +++ b/osu.sln @@ -25,6 +25,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests", "osu.Game.Rulesets.Osu.Tests\osu.Game.Rulesets.Osu.Tests.csproj", "{DECCCC75-67AD-4C3D-BB84-FD0E01323511}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework", "..\osu-framework\osu.Framework\osu.Framework.csproj", "{C7D2DA3C-97BF-403C-9F75-115C8A64DAC1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework.NativeLibs", "..\osu-framework\osu.Framework.NativeLibs\osu.Framework.NativeLibs.csproj", "{35AD7F4C-81DC-4060-BFD1-C376DC4C4801}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -79,6 +83,14 @@ Global {DECCCC75-67AD-4C3D-BB84-FD0E01323511}.Debug|Any CPU.Build.0 = Debug|Any CPU {DECCCC75-67AD-4C3D-BB84-FD0E01323511}.Release|Any CPU.ActiveCfg = Release|Any CPU {DECCCC75-67AD-4C3D-BB84-FD0E01323511}.Release|Any CPU.Build.0 = Release|Any CPU + {C7D2DA3C-97BF-403C-9F75-115C8A64DAC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7D2DA3C-97BF-403C-9F75-115C8A64DAC1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7D2DA3C-97BF-403C-9F75-115C8A64DAC1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7D2DA3C-97BF-403C-9F75-115C8A64DAC1}.Release|Any CPU.Build.0 = Release|Any CPU + {35AD7F4C-81DC-4060-BFD1-C376DC4C4801}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35AD7F4C-81DC-4060-BFD1-C376DC4C4801}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35AD7F4C-81DC-4060-BFD1-C376DC4C4801}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35AD7F4C-81DC-4060-BFD1-C376DC4C4801}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 8de62b608e76e268fea5d03551c0ba6a9fc10949 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Jun 2019 15:22:27 +0900 Subject: [PATCH 1146/5608] Allow FullscreenOverlay to surface to front on subsequent Show requests --- osu.Game/Overlays/FullscreenOverlay.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/osu.Game/Overlays/FullscreenOverlay.cs b/osu.Game/Overlays/FullscreenOverlay.cs index 9706f75087..0911ee84de 100644 --- a/osu.Game/Overlays/FullscreenOverlay.cs +++ b/osu.Game/Overlays/FullscreenOverlay.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -40,6 +41,19 @@ namespace osu.Game.Overlays }; } + public override void Show() + { + if (State.Value == Visibility.Visible) + { + // re-trigger the state changed so we can potentially surface to front + State.TriggerChange(); + } + else + { + base.Show(); + } + } + protected override void PopIn() { base.PopIn(); From 620c2311ac887eebf82c8c31583661bfe0aba517 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Jun 2019 15:39:12 +0900 Subject: [PATCH 1147/5608] Add test --- .../Online/TestSceneFullscreenOverlay.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs index 6dc3428bff..fe8437be17 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs @@ -18,8 +18,24 @@ namespace osu.Game.Tests.Visual.Online { base.LoadComplete(); + int fireCount = 0; + Add(overlay = new TestFullscreenOverlay()); - AddStep(@"toggle", overlay.ToggleVisibility); + + overlay.State.ValueChanged += _ => fireCount++; + + AddStep(@"show", overlay.Show); + + AddAssert("fire count 1", () => fireCount == 1); + + AddStep(@"show again", overlay.Show); + + // this logic is specific to FullscreenOverlay + AddAssert("fire count 2", () => fireCount == 2); + + AddStep(@"hide", overlay.Hide); + + AddAssert("fire count 3", () => fireCount == 3); } private class TestFullscreenOverlay : FullscreenOverlay From 975bb3db8a2aba107858543eb12b419f363cad44 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 11 Jun 2019 15:51:14 +0900 Subject: [PATCH 1148/5608] cleanup --- .idea/.idea.osu/.idea/.name | 1 - osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 .idea/.idea.osu/.idea/.name diff --git a/.idea/.idea.osu/.idea/.name b/.idea/.idea.osu/.idea/.name deleted file mode 100644 index 21cb4db60e..0000000000 --- a/.idea/.idea.osu/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -osu \ No newline at end of file diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index fa73a14252..198da2c5b1 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -222,7 +222,7 @@ namespace osu.Game.Tests.Visual.SongSelect { beatmapChangedCount = 0; debounceCount = 0; - songSelect.Carousel.SelectionChanged += _ => beatmapChangedCount += 1; + songSelect.Carousel.SelectionChanged += _ => beatmapChangedCount++; }); AddRepeatStep($"Create beatmaps {test_count} times", () => { From a53ade07a5ea39046b5b90d240435664010021a3 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 11 Jun 2019 15:51:57 +0900 Subject: [PATCH 1149/5608] remove unused using --- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 198da2c5b1..2664c7a42c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -11,7 +11,6 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Extensions; -using osu.Framework.Logging; using osu.Framework.MathUtils; using osu.Framework.Platform; using osu.Framework.Screens; From 07e17518e93cc81d64e9215a9b1465a0e8859be4 Mon Sep 17 00:00:00 2001 From: Arphox Date: Tue, 11 Jun 2019 10:28:16 +0200 Subject: [PATCH 1150/5608] Fix all "Maintainability" CodeFactor issues --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 4 ++-- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 4 ++-- osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs | 2 +- osu.Game/Graphics/Containers/HoldToConfirmContainer.cs | 2 +- osu.Game/Online/API/APIAccess.cs | 2 +- osu.Game/Online/Chat/MessageFormatter.cs | 2 +- osu.Game/Overlays/ChatOverlay.cs | 2 +- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 2 +- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 8 ++++---- 11 files changed, 16 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index e7c7fd77df..90052d9b11 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -379,8 +379,8 @@ namespace osu.Game.Rulesets.Catch.UI X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); // Correct overshooting. - if (hyperDashDirection > 0 && hyperDashTargetPosition < X || - hyperDashDirection < 0 && hyperDashTargetPosition > X) + if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || + (hyperDashDirection < 0 && hyperDashTargetPosition > X)) { X = hyperDashTargetPosition; SetHyperDashState(); diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index b2beda18f4..7bb1f42802 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps break; if (Vector2Extensions.Distance(stackBaseObject.Position, objectN.Position) < stack_distance - || stackBaseObject is Slider && Vector2Extensions.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance) + || (stackBaseObject is Slider && Vector2Extensions.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance)) { stackBaseIndex = n; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index ec23570f54..bc5d02258f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -37,11 +37,11 @@ namespace osu.Game.Rulesets.Osu.Mods if (time < osuHit.HitObject.StartTime - relax_leniency) continue; - if (osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime || osuHit.IsHit) + if ((osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime) || osuHit.IsHit) continue; requiresHit |= osuHit is DrawableHitCircle && osuHit.IsHovered && osuHit.HitObject.HitWindows.CanBeHit(relativetime); - requiresHold |= osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered) || osuHit is DrawableSpinner; + requiresHold |= (osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered)) || osuHit is DrawableSpinner; } if (requiresHit) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs index 8fe31b7ad6..f59cb75a46 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs @@ -192,7 +192,7 @@ namespace osu.Game.Tests.Visual.UserInterface public CursorContainer Cursor { get; } public bool ProvidingUserCursor { get; } - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) || SmoothTransition && !ProvidingUserCursor; + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) || (SmoothTransition && !ProvidingUserCursor); private readonly Box background; diff --git a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs index a5b5b7af42..cda5e150de 100644 --- a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs +++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs @@ -27,7 +27,7 @@ namespace osu.Game.Graphics.Containers protected void BeginConfirm() { - if (confirming || !AllowMultipleFires && fired) return; + if (confirming || (!AllowMultipleFires && fired)) return; confirming = true; diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 594bc1e3ca..343d6a67b7 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -37,7 +37,7 @@ namespace osu.Game.Online.API public Bindable LocalUser { get; } = new Bindable(createGuestUser()); - protected bool HasLogin => authentication.Token.Value != null || !string.IsNullOrEmpty(ProvidedUsername) && !string.IsNullOrEmpty(password); + protected bool HasLogin => authentication.Token.Value != null || (!string.IsNullOrEmpty(ProvidedUsername) && !string.IsNullOrEmpty(password)); private readonly CancellationTokenSource cancellationToken = new CancellationTokenSource(); diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index e1fc65da6c..4aaffdd161 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -69,7 +69,7 @@ namespace osu.Game.Online.Chat if (displayText.Length == 0 || linkText.Length == 0) continue; // Check for encapsulated links - if (result.Links.Find(l => l.Index <= index && l.Index + l.Length >= index + m.Length || index <= l.Index && index + m.Length >= l.Index + l.Length) == null) + if (result.Links.Find(l => (l.Index <= index && l.Index + l.Length >= index + m.Length) || (index <= l.Index && index + m.Length >= l.Index + l.Length)) == null) { result.Text = result.Text.Remove(index, m.Length).Insert(index, displayText); diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index eb95fabe02..978848d9fc 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -56,7 +56,7 @@ namespace osu.Game.Overlays private readonly Container channelSelectionContainer; private readonly ChannelSelectionOverlay channelSelectionOverlay; - public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceivePositionalInputAt(screenSpacePos) || channelSelectionOverlay.State == Visibility.Visible && channelSelectionOverlay.ReceivePositionalInputAt(screenSpacePos); + public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceivePositionalInputAt(screenSpacePos) || (channelSelectionOverlay.State == Visibility.Visible && channelSelectionOverlay.ReceivePositionalInputAt(screenSpacePos)); public ChatOverlay() { diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index e94604554c..0f77b8d584 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Edit /// public readonly DrawableHitObject HitObject; - protected override bool ShouldBeAlive => HitObject.IsAlive && HitObject.IsPresent || State == SelectionState.Selected; + protected override bool ShouldBeAlive => (HitObject.IsAlive && HitObject.IsPresent) || State == SelectionState.Selected; public override bool HandlePositionalInput => ShouldBeAlive; public override bool RemoveWhenNotAlive => false; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index e91100608b..ec7e6dc303 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.Objects.Drawables public override bool RemoveCompletedTransforms => false; protected override bool RequiresChildrenUpdate => true; - public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Clock?.CurrentTime >= LifetimeStart; + public override bool IsPresent => base.IsPresent || (State.Value == ArmedState.Idle && Clock?.CurrentTime >= LifetimeStart); public readonly Bindable State = new Bindable(); diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index d2c9ce81c3..0fdbd56c92 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -136,9 +136,9 @@ namespace osu.Game.Scoring.Legacy score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.XH : ScoreRank.X; else if (ratio300 > 0.9 && ratio50 <= 0.01 && countMiss == 0) score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.SH : ScoreRank.S; - else if (ratio300 > 0.8 && countMiss == 0 || ratio300 > 0.9) + else if ((ratio300 > 0.8 && countMiss == 0) || ratio300 > 0.9) score.Rank = ScoreRank.A; - else if (ratio300 > 0.7 && countMiss == 0 || ratio300 > 0.8) + else if ((ratio300 > 0.7 && countMiss == 0) || ratio300 > 0.8) score.Rank = ScoreRank.B; else if (ratio300 > 0.6) score.Rank = ScoreRank.C; @@ -159,9 +159,9 @@ namespace osu.Game.Scoring.Legacy score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.XH : ScoreRank.X; else if (ratio300 > 0.9 && ratio50 <= 0.01 && countMiss == 0) score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.SH : ScoreRank.S; - else if (ratio300 > 0.8 && countMiss == 0 || ratio300 > 0.9) + else if ((ratio300 > 0.8 && countMiss == 0) || ratio300 > 0.9) score.Rank = ScoreRank.A; - else if (ratio300 > 0.7 && countMiss == 0 || ratio300 > 0.8) + else if ((ratio300 > 0.7 && countMiss == 0) || ratio300 > 0.8) score.Rank = ScoreRank.B; else if (ratio300 > 0.6) score.Rank = ScoreRank.C; From e5417416a23a0ef743a53589ee42e5362f0f6937 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 Jun 2019 18:24:50 +0900 Subject: [PATCH 1151/5608] Remove braces --- osu.Game/Graphics/UserInterface/OsuCheckbox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 5d41075725..5ead5987a1 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -81,7 +81,7 @@ namespace osu.Game.Graphics.UserInterface Nub.Current.BindTo(Current); - Current.DisabledChanged += disabled => { labelText.Alpha = Nub.Alpha = disabled ? 0.3f : 1; }; + Current.DisabledChanged += disabled => labelText.Alpha = Nub.Alpha = disabled ? 0.3f : 1; } protected override void LoadComplete() From 130ff5688694921246ee1dba0faaac987c4b46b3 Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Tue, 11 Jun 2019 12:29:42 +0300 Subject: [PATCH 1152/5608] Move logic into BeatmapNotAvailable --- .../BeatmapSet/BeatmapNotAvailable.cs | 54 ++++++++++++++++--- osu.Game/Overlays/BeatmapSet/Header.cs | 36 +++++-------- 2 files changed, 59 insertions(+), 31 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs b/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs index b893fd0703..c111861206 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs @@ -5,6 +5,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -14,9 +15,36 @@ namespace osu.Game.Overlays.BeatmapSet { public class BeatmapNotAvailable : Container { - private LinkFlowContainer linkContainer; + private BeatmapSetInfo beatmapSet; - public override void Show() + public BeatmapSetInfo BeatmapSet + { + get => beatmapSet; + set + { + if (value == beatmapSet) return; + + beatmapSet = value; + + if (beatmapSet?.OnlineInfo.Availability != null) + { + Header?.ResizeHeightTo(450, 500); + Show(); + } + else + { + Header?.ResizeHeightTo(400, 500); + Hide(); + } + } + } + + public Header Header; + + private readonly OsuSpriteText text; + private readonly LinkFlowContainer link; + + public BeatmapNotAvailable() { AutoSizeAxes = Axes.Both; Margin = new MarginPadding { Top = 10 }; @@ -36,14 +64,13 @@ namespace osu.Game.Overlays.BeatmapSet Children = new Drawable[] { - new OsuSpriteText + text = new OsuSpriteText { Margin = new MarginPadding { Bottom = 10, Horizontal = 5 }, Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium), - Text = "This beatmap is currently not available for download.", Colour = Color4.Orange, }, - linkContainer = new LinkFlowContainer(text => text.Font = OsuFont.GetFont(size: 14)) + link = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: 14)) { Direction = FillDirection.Full, RelativeSizeAxes = Axes.X, @@ -54,12 +81,25 @@ namespace osu.Game.Overlays.BeatmapSet }, }; + Hide(); + } + + public override void Show() + { + text.Text = BeatmapSet.OnlineInfo.Availability.DownloadDisabled + ? "This beatmap is currently not available for download." + : "Portions of this beatmap have been removed at the request of the creator or a third-party rights holder."; + + link.AddLink("Check here for more information.", BeatmapSet.OnlineInfo.Availability.ExternalLink); + base.Show(); } - public string Link + public override void Hide() { - set => linkContainer.AddLink("Check here for more information.", value); + link.RemoveAll(x => true); + + base.Hide(); } } } diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 9a4e7d4754..a53b4a2e68 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -32,10 +32,10 @@ namespace osu.Game.Overlays.BeatmapSet private readonly UpdateableBeatmapSetCover cover; private readonly OsuSpriteText title, artist; private readonly AuthorInfo author; - private readonly BeatmapNotAvailable unavailableContainer; - private readonly FillFlowContainer downloadButtonsContainer; + private readonly BeatmapNotAvailable beatmapNotAvailable; private readonly BeatmapSetOnlineStatusPill onlineStatusPill; public Details Details; + public FillFlowContainer DownloadButtonsContainer; public readonly BeatmapPicker Picker; @@ -135,7 +135,7 @@ namespace osu.Game.Overlays.BeatmapSet Margin = new MarginPadding { Top = 20 }, Child = author = new AuthorInfo(), }, - unavailableContainer = new BeatmapNotAvailable(), + beatmapNotAvailable = new BeatmapNotAvailable { Header = this }, new Container { RelativeSizeAxes = Axes.X, @@ -144,7 +144,7 @@ namespace osu.Game.Overlays.BeatmapSet Children = new Drawable[] { favouriteButton = new FavouriteButton(), - downloadButtonsContainer = new FillFlowContainer + DownloadButtonsContainer = new FillFlowContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Left = buttons_height + buttons_spacing }, @@ -192,7 +192,7 @@ namespace osu.Game.Overlays.BeatmapSet BeatmapSet.BindValueChanged(setInfo => { - Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = setInfo.NewValue; + Picker.BeatmapSet = author.BeatmapSet = beatmapNotAvailable.BeatmapSet = Details.BeatmapSet = setInfo.NewValue; title.Text = setInfo.NewValue?.Metadata.Title ?? string.Empty; artist.Text = setInfo.NewValue?.Metadata.Artist ?? string.Empty; @@ -201,27 +201,15 @@ namespace osu.Game.Overlays.BeatmapSet if (setInfo.NewValue != null) { - downloadButtonsContainer.FadeIn(transition_duration); + DownloadButtonsContainer.FadeIn(transition_duration); favouriteButton.FadeIn(transition_duration); } else { - downloadButtonsContainer.FadeOut(transition_duration); + DownloadButtonsContainer.FadeOut(transition_duration); favouriteButton.FadeOut(transition_duration); } - if (setInfo.NewValue?.OnlineInfo.Availability?.DownloadDisabled ?? false) - { - this.ResizeHeightTo(460, transition_duration / 2); - unavailableContainer.Show(); - unavailableContainer.Link = setInfo.NewValue.OnlineInfo.Availability.ExternalLink; - } - else - { - this.ResizeHeightTo(400, transition_duration / 2); - unavailableContainer.Hide(); - } - updateDownloadButtons(); }, true); } @@ -232,7 +220,7 @@ namespace osu.Game.Overlays.BeatmapSet if (BeatmapSet.Value.OnlineInfo.Availability?.DownloadDisabled ?? false) { - downloadButtonsContainer.RemoveAll(x => true); + DownloadButtonsContainer.RemoveAll(x => true); return; } @@ -240,7 +228,7 @@ namespace osu.Game.Overlays.BeatmapSet { case DownloadState.LocallyAvailable: // temporary for UX until new design is implemented. - downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet.Value) + DownloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet.Value) { Width = 50, RelativeSizeAxes = Axes.Y @@ -250,13 +238,13 @@ namespace osu.Game.Overlays.BeatmapSet case DownloadState.Downloading: case DownloadState.Downloaded: // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. - downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); + DownloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); break; default: - downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); + DownloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); if (BeatmapSet.Value.OnlineInfo.HasVideo) - downloadButtonsContainer.Add(new DownloadButton(BeatmapSet.Value, true)); + DownloadButtonsContainer.Add(new DownloadButton(BeatmapSet.Value, true)); break; } } From 261badc770330dd1e086bb30880bb73f6bb90bb9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Jun 2019 19:24:54 +0900 Subject: [PATCH 1153/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index eeb1f2bee3..140d0c7f0e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 3a5090d968..39be738a5c 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 6a34d5575bd69b28393ab7dfb8f00448d03553ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Jun 2019 20:44:11 +0900 Subject: [PATCH 1154/5608] Bump framework version --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 140d0c7f0e..75a464d0b8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 39be738a5c..2c25498b89 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 13cd22e397f336eeb86b1be076f4cf6aabbafc85 Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Tue, 11 Jun 2019 14:58:46 +0300 Subject: [PATCH 1155/5608] Test scene for BeatmapNotAvailable --- .../Online/TestSceneBeatmapNotAvailable.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneBeatmapNotAvailable.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapNotAvailable.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapNotAvailable.cs new file mode 100644 index 0000000000..bd4570470d --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapNotAvailable.cs @@ -0,0 +1,54 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Overlays.BeatmapSet; + +namespace osu.Game.Tests.Visual.Online +{ + [TestFixture] + public class TestSceneBeatmapNotAvailable : OsuTestScene + { + public TestSceneBeatmapNotAvailable() + { + var container = new BeatmapNotAvailable(); + + Add(container); + + AddAssert("is container hidden", () => container.Alpha == 0); + AddStep("set undownloadable beatmapset", () => container.BeatmapSet = new BeatmapSetInfo + { + OnlineInfo = new BeatmapSetOnlineInfo + { + Availability = new BeatmapSetOnlineAvailability + { + DownloadDisabled = true, + ExternalLink = @"https://gist.githubusercontent.com/peppy/99e6959772083cdfde8a/raw", + }, + }, + }); + + AddAssert("is container visible", () => container.Alpha == 1); + AddStep("set downloadable beatmapset", () => container.BeatmapSet = new BeatmapSetInfo + { + OnlineInfo = new BeatmapSetOnlineInfo + { + Availability = new BeatmapSetOnlineAvailability + { + DownloadDisabled = false, + ExternalLink = @"https://gist.githubusercontent.com/peppy/99e6959772083cdfde8a/raw", + }, + }, + }); + + AddAssert("is container still visible", () => container.Alpha == 1); + AddStep("set normal beatmapset", () => container.BeatmapSet = new BeatmapSetInfo + { + OnlineInfo = new BeatmapSetOnlineInfo(), + }); + + AddAssert("is container hidden", () => container.Alpha == 0); + } + } +} From b4de51b612c62b563ec1303b84dead7a219be938 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 11 Jun 2019 18:29:33 +0530 Subject: [PATCH 1156/5608] Create a generic base archive download manager class --- .../Database/ArchiveDownloadModelManager.cs | 117 ++++++++++++++++++ .../Online/API/ArchiveDownloadModelRequest.cs | 23 ++++ 2 files changed, 140 insertions(+) create mode 100644 osu.Game/Database/ArchiveDownloadModelManager.cs create mode 100644 osu.Game/Online/API/ArchiveDownloadModelRequest.cs diff --git a/osu.Game/Database/ArchiveDownloadModelManager.cs b/osu.Game/Database/ArchiveDownloadModelManager.cs new file mode 100644 index 0000000000..8c7a0fba87 --- /dev/null +++ b/osu.Game/Database/ArchiveDownloadModelManager.cs @@ -0,0 +1,117 @@ +using osu.Framework.Logging; +using osu.Framework.Platform; +using osu.Game.Online.API; +using osu.Game.Overlays.Notifications; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace osu.Game.Database +{ + public abstract class ArchiveDownloadModelManager : ArchiveModelManager + where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete + where TFileModel : INamedFileInfo, new() + where TDownloadRequestModel : ArchiveDownloadModelRequest + { + public event Action DownloadBegan; + + public event Action DownloadFailed; + + private readonly IAPIProvider api; + + private readonly List currentDownloads = new List(); + + protected ArchiveDownloadModelManager(Storage storage, IDatabaseContextFactory contextFactory, IAPIProvider api, MutableDatabaseBackedStoreWithFileIncludes modelStore, IIpcHost importHost = null) + :base(storage, contextFactory, modelStore, importHost) + { + this.api = api; + } + + protected abstract TDownloadRequestModel CreateDownloadRequest(TModel model); + + public bool Download(TModel model) + { + var existing = GetExistingDownload(model); + + if (existing != null || api == null) return false; + + DownloadNotification notification = new DownloadNotification + { + Text = $"Downloading {model}", + }; + + var request = CreateDownloadRequest(model); + + request.DownloadProgressed += progress => + { + notification.State = ProgressNotificationState.Active; + notification.Progress = progress; + }; + + request.Success += filename => + { + Task.Factory.StartNew(() => + { + Import(notification, filename); + currentDownloads.Remove(request); + }, TaskCreationOptions.LongRunning); + }; + + request.Failure += error => + { + DownloadFailed?.Invoke(request); + + if (error is OperationCanceledException) return; + + notification.State = ProgressNotificationState.Cancelled; + // TODO: implement a Name for every model that we can use in this message + Logger.Error(error, "Download failed!"); + currentDownloads.Remove(request); + }; + + notification.CancelRequested += () => + { + request.Cancel(); + currentDownloads.Remove(request); + notification.State = ProgressNotificationState.Cancelled; + return true; + }; + + currentDownloads.Add(request); + PostNotification?.Invoke(notification); + + Task.Factory.StartNew(() => + { + try + { + request.Perform(api); + } + catch + { + } + }, TaskCreationOptions.LongRunning); + + DownloadBegan?.Invoke(request); + + return true; + } + + public TDownloadRequestModel GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Info.Equals(model)); + + private class DownloadNotification : ProgressNotification + { + public override bool IsImportant => false; + + protected override Notification CreateCompletionNotification() => new SilencedProgressCompletionNotification + { + Activated = CompletionClickAction, + Text = CompletionText + }; + + private class SilencedProgressCompletionNotification : ProgressCompletionNotification + { + public override bool IsImportant => false; + } + } + } +} diff --git a/osu.Game/Online/API/ArchiveDownloadModelRequest.cs b/osu.Game/Online/API/ArchiveDownloadModelRequest.cs new file mode 100644 index 0000000000..377166e657 --- /dev/null +++ b/osu.Game/Online/API/ArchiveDownloadModelRequest.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace osu.Game.Online.API +{ + public abstract class ArchiveDownloadModelRequest : APIDownloadRequest + where TModel : class + { + public readonly TModel Info; + + public float Progress; + + public event Action DownloadProgressed; + + protected ArchiveDownloadModelRequest(TModel model) + { + Info = model; + + Progressed += (current, total) => DownloadProgressed?.Invoke(Progress = (float)current / total); + } + } +} From 341d137f5c10c9e575419100e355fc6d312c0103 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 11 Jun 2019 19:36:08 +0530 Subject: [PATCH 1157/5608] Make BeatmapManager inherit from new base class --- osu.Game/Beatmaps/BeatmapManager.cs | 113 +----------------- .../Database/ArchiveDownloadModelManager.cs | 29 +++-- .../Online/API/ArchiveDownloadModelRequest.cs | 2 - .../API/Requests/DownloadBeatmapSetRequest.cs | 10 +- .../Direct/DownloadTrackingComposite.cs | 4 +- 5 files changed, 25 insertions(+), 133 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b6fe7f88fa..c4975501ed 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -27,7 +27,7 @@ namespace osu.Game.Beatmaps /// /// Handles the storage and retrieval of Beatmaps/WorkingBeatmaps. /// - public partial class BeatmapManager : ArchiveModelManager + public partial class BeatmapManager : ArchiveDownloadModelManager { /// /// Fired when a single difficulty has been hidden. @@ -39,16 +39,6 @@ namespace osu.Game.Beatmaps /// public event Action BeatmapRestored; - /// - /// Fired when a beatmap download begins. - /// - public event Action BeatmapDownloadBegan; - - /// - /// Fired when a beatmap download is interrupted, due to user cancellation or other failures. - /// - public event Action BeatmapDownloadFailed; - /// /// A default representation of a WorkingBeatmap to use when no beatmap is available. /// @@ -74,7 +64,7 @@ namespace osu.Game.Beatmaps public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, AudioManager audioManager, GameHost host = null, WorkingBeatmap defaultBeatmap = null) - : base(storage, contextFactory, new BeatmapStore(contextFactory), host) + : base(storage, contextFactory, api, new BeatmapStore(contextFactory), host) { this.rulesets = rulesets; this.api = api; @@ -88,6 +78,8 @@ namespace osu.Game.Beatmaps beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b); } + protected override DownloadBeatmapSetRequest CreateDownloadRequest(BeatmapSetInfo set) => new DownloadBeatmapSetRequest(set, false); + protected override void Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive) { if (archive != null) @@ -153,87 +145,6 @@ namespace osu.Game.Beatmaps void resetIds() => beatmapSet.Beatmaps.ForEach(b => b.OnlineBeatmapID = null); } - /// - /// Downloads a beatmap. - /// This will post notifications tracking progress. - /// - /// The to be downloaded. - /// Whether the beatmap should be downloaded without video. Defaults to false. - /// Downloading can happen - public bool Download(BeatmapSetInfo beatmapSetInfo, bool noVideo = false) - { - var existing = GetExistingDownload(beatmapSetInfo); - - if (existing != null || api == null) return false; - - var downloadNotification = new DownloadNotification - { - Text = $"Downloading {beatmapSetInfo}", - }; - - var request = new DownloadBeatmapSetRequest(beatmapSetInfo, noVideo); - - request.DownloadProgressed += progress => - { - downloadNotification.State = ProgressNotificationState.Active; - downloadNotification.Progress = progress; - }; - - request.Success += filename => - { - Task.Factory.StartNew(() => - { - // This gets scheduled back to the update thread, but we want the import to run in the background. - Import(downloadNotification, filename); - currentDownloads.Remove(request); - }, TaskCreationOptions.LongRunning); - }; - - request.Failure += error => - { - BeatmapDownloadFailed?.Invoke(request); - - if (error is OperationCanceledException) return; - - downloadNotification.State = ProgressNotificationState.Cancelled; - Logger.Error(error, "Beatmap download failed!"); - currentDownloads.Remove(request); - }; - - downloadNotification.CancelRequested += () => - { - request.Cancel(); - currentDownloads.Remove(request); - downloadNotification.State = ProgressNotificationState.Cancelled; - return true; - }; - - currentDownloads.Add(request); - PostNotification?.Invoke(downloadNotification); - - // don't run in the main api queue as this is a long-running task. - Task.Factory.StartNew(() => - { - try - { - request.Perform(api); - } - catch - { - // no need to handle here as exceptions will filter down to request.Failure above. - } - }, TaskCreationOptions.LongRunning); - BeatmapDownloadBegan?.Invoke(request); - return true; - } - - /// - /// Get an existing download request if it exists. - /// - /// The whose download request is wanted. - /// The object if it exists, or null. - public DownloadBeatmapSetRequest GetExistingDownload(BeatmapSetInfo beatmap) => currentDownloads.Find(d => d.BeatmapSet.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID); - /// /// Delete a beatmap difficulty. /// @@ -439,21 +350,5 @@ namespace osu.Game.Beatmaps protected override Texture GetBackground() => null; protected override Track GetTrack() => null; } - - private class DownloadNotification : ProgressNotification - { - public override bool IsImportant => false; - - protected override Notification CreateCompletionNotification() => new SilencedProgressCompletionNotification - { - Activated = CompletionClickAction, - Text = CompletionText - }; - - private class SilencedProgressCompletionNotification : ProgressCompletionNotification - { - public override bool IsImportant => false; - } - } } } diff --git a/osu.Game/Database/ArchiveDownloadModelManager.cs b/osu.Game/Database/ArchiveDownloadModelManager.cs index 8c7a0fba87..6580da0d54 100644 --- a/osu.Game/Database/ArchiveDownloadModelManager.cs +++ b/osu.Game/Database/ArchiveDownloadModelManager.cs @@ -31,17 +31,26 @@ namespace osu.Game.Database public bool Download(TModel model) { - var existing = GetExistingDownload(model); - - if (existing != null || api == null) return false; - - DownloadNotification notification = new DownloadNotification - { - Text = $"Downloading {model}", - }; + if (!canDownload(model)) return false; var request = CreateDownloadRequest(model); + performDownloadWithRequest(request); + + return true; + } + + public TDownloadRequestModel GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Info.Equals(model)); + + private bool canDownload(TModel model) => GetExistingDownload(model) == null && api != null; + + private void performDownloadWithRequest(TDownloadRequestModel request) + { + DownloadNotification notification = new DownloadNotification + { + Text = $"Downloading {request.Info}", + }; + request.DownloadProgressed += progress => { notification.State = ProgressNotificationState.Active; @@ -92,12 +101,8 @@ namespace osu.Game.Database }, TaskCreationOptions.LongRunning); DownloadBegan?.Invoke(request); - - return true; } - public TDownloadRequestModel GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Info.Equals(model)); - private class DownloadNotification : ProgressNotification { public override bool IsImportant => false; diff --git a/osu.Game/Online/API/ArchiveDownloadModelRequest.cs b/osu.Game/Online/API/ArchiveDownloadModelRequest.cs index 377166e657..862d017228 100644 --- a/osu.Game/Online/API/ArchiveDownloadModelRequest.cs +++ b/osu.Game/Online/API/ArchiveDownloadModelRequest.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace osu.Game.Online.API { diff --git a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs index 26e8acc2fc..7d0a8f9f46 100644 --- a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs @@ -2,26 +2,20 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; -using System; namespace osu.Game.Online.API.Requests { - public class DownloadBeatmapSetRequest : APIDownloadRequest + public class DownloadBeatmapSetRequest : ArchiveDownloadModelRequest { public readonly BeatmapSetInfo BeatmapSet; - public float Progress; - - public event Action DownloadProgressed; - private readonly bool noVideo; public DownloadBeatmapSetRequest(BeatmapSetInfo set, bool noVideo) + : base(set) { this.noVideo = noVideo; BeatmapSet = set; - - Progressed += (current, total) => DownloadProgressed?.Invoke(Progress = (float)current / total); } protected override string Target => $@"beatmapsets/{BeatmapSet.OnlineBeatmapSetID}/download{(noVideo ? "?noVideo=1" : "")}"; diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs index 37f13aefc8..9beedb195f 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs +++ b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays.Direct attachDownload(beatmaps.GetExistingDownload(setInfo.NewValue)); }, true); - beatmaps.BeatmapDownloadBegan += download => + beatmaps.DownloadBegan += download => { if (download.BeatmapSet.OnlineBeatmapSetID == BeatmapSet.Value?.OnlineBeatmapSetID) attachDownload(download); @@ -65,7 +65,7 @@ namespace osu.Game.Overlays.Direct if (beatmaps != null) { - beatmaps.BeatmapDownloadBegan -= attachDownload; + beatmaps.DownloadBegan -= attachDownload; beatmaps.ItemAdded -= setAdded; } From 8ff26a8fbcf7ef1f1d3483d4dd0047807ef05ff1 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 11 Jun 2019 19:49:10 +0530 Subject: [PATCH 1158/5608] Add license headers and xmldoc --- .../Database/ArchiveDownloadModelManager.cs | 31 +++++++++++++++++-- .../Online/API/ArchiveDownloadModelRequest.cs | 5 ++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/ArchiveDownloadModelManager.cs b/osu.Game/Database/ArchiveDownloadModelManager.cs index 6580da0d54..d0881fb251 100644 --- a/osu.Game/Database/ArchiveDownloadModelManager.cs +++ b/osu.Game/Database/ArchiveDownloadModelManager.cs @@ -1,4 +1,7 @@ -using osu.Framework.Logging; +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Online.API; using osu.Game.Overlays.Notifications; @@ -8,13 +11,26 @@ using System.Threading.Tasks; namespace osu.Game.Database { + /// + /// An that has the ability to download models using an and + /// import them into the store. + /// + /// The model type. + /// The associated file join type. + /// The associated for this model. public abstract class ArchiveDownloadModelManager : ArchiveModelManager where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() where TDownloadRequestModel : ArchiveDownloadModelRequest { + /// + /// Fired when a download begins. + /// public event Action DownloadBegan; + /// + /// Fired when a download is interrupted, either due to user cancellation or failure. + /// public event Action DownloadFailed; private readonly IAPIProvider api; @@ -29,6 +45,12 @@ namespace osu.Game.Database protected abstract TDownloadRequestModel CreateDownloadRequest(TModel model); + /// + /// Downloads a . + /// This will post notifications tracking progress. + /// + /// The to be downloaded. + /// Whether downloading can happen. public bool Download(TModel model) { if (!canDownload(model)) return false; @@ -40,6 +62,11 @@ namespace osu.Game.Database return true; } + /// + /// Gets an existing download request if it exists. + /// + /// The whose request is wanted. + /// The object if it exists, otherwise null. public TDownloadRequestModel GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Info.Equals(model)); private bool canDownload(TModel model) => GetExistingDownload(model) == null && api != null; @@ -73,7 +100,7 @@ namespace osu.Game.Database if (error is OperationCanceledException) return; notification.State = ProgressNotificationState.Cancelled; - // TODO: implement a Name for every model that we can use in this message + // TODO: maybe implement a Name for every model that we can use in this message? Logger.Error(error, "Download failed!"); currentDownloads.Remove(request); }; diff --git a/osu.Game/Online/API/ArchiveDownloadModelRequest.cs b/osu.Game/Online/API/ArchiveDownloadModelRequest.cs index 862d017228..7f161f1e98 100644 --- a/osu.Game/Online/API/ArchiveDownloadModelRequest.cs +++ b/osu.Game/Online/API/ArchiveDownloadModelRequest.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; namespace osu.Game.Online.API { From 802f48712d95b148efc45ae25bf8fa4fdc040423 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 11 Jun 2019 20:14:36 +0530 Subject: [PATCH 1159/5608] Add ability to perform a download request with options --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- .../Database/ArchiveDownloadModelManager.cs | 29 +++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index c4975501ed..6f27cbd7c6 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -78,7 +78,7 @@ namespace osu.Game.Beatmaps beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b); } - protected override DownloadBeatmapSetRequest CreateDownloadRequest(BeatmapSetInfo set) => new DownloadBeatmapSetRequest(set, false); + protected override DownloadBeatmapSetRequest CreateDownloadRequest(BeatmapSetInfo set, object[] options) => new DownloadBeatmapSetRequest(set, (options?.FirstOrDefault() as bool?) ?? false); protected override void Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive) { diff --git a/osu.Game/Database/ArchiveDownloadModelManager.cs b/osu.Game/Database/ArchiveDownloadModelManager.cs index d0881fb251..a4d2180559 100644 --- a/osu.Game/Database/ArchiveDownloadModelManager.cs +++ b/osu.Game/Database/ArchiveDownloadModelManager.cs @@ -43,7 +43,15 @@ namespace osu.Game.Database this.api = api; } - protected abstract TDownloadRequestModel CreateDownloadRequest(TModel model); + /// + /// Creates the download request for this . + /// The parameters will be provided when the download was initiated with extra options meant + /// to be used in the creation of the request. + /// + /// The to be downloaded. + /// Extra parameters for request creation, null if none were passed. + /// The request object. + protected abstract TDownloadRequestModel CreateDownloadRequest(TModel model, object[] options); /// /// Downloads a . @@ -55,7 +63,24 @@ namespace osu.Game.Database { if (!canDownload(model)) return false; - var request = CreateDownloadRequest(model); + var request = CreateDownloadRequest(model, null); + + performDownloadWithRequest(request); + + return true; + } + + /// + /// Downloads a with optional parameters for the download request. + /// + /// The to be downloaded. + /// Optional parameters to be used for creating the download request. + /// Whether downloading can happen. + public bool Download(TModel model, params object[] extra) + { + if (!canDownload(model)) return false; + + var request = CreateDownloadRequest(model, extra); performDownloadWithRequest(request); From 709ca03a08a3cad591a3911b01734fd100ad3923 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 11 Jun 2019 20:21:06 +0530 Subject: [PATCH 1160/5608] Remove unused usings --- osu.Game/Beatmaps/BeatmapManager.cs | 2 -- osu.Game/Database/ArchiveDownloadModelManager.cs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 6f27cbd7c6..6ad5ce6617 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Linq.Expressions; -using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using osu.Framework.Audio; using osu.Framework.Audio.Track; @@ -19,7 +18,6 @@ using osu.Game.Database; using osu.Game.IO.Archives; using osu.Game.Online.API; using osu.Game.Online.API.Requests; -using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; namespace osu.Game.Beatmaps diff --git a/osu.Game/Database/ArchiveDownloadModelManager.cs b/osu.Game/Database/ArchiveDownloadModelManager.cs index a4d2180559..629cb81440 100644 --- a/osu.Game/Database/ArchiveDownloadModelManager.cs +++ b/osu.Game/Database/ArchiveDownloadModelManager.cs @@ -38,7 +38,7 @@ namespace osu.Game.Database private readonly List currentDownloads = new List(); protected ArchiveDownloadModelManager(Storage storage, IDatabaseContextFactory contextFactory, IAPIProvider api, MutableDatabaseBackedStoreWithFileIncludes modelStore, IIpcHost importHost = null) - :base(storage, contextFactory, modelStore, importHost) + : base(storage, contextFactory, modelStore, importHost) { this.api = api; } From f4dab4da85df762b3998c1ad4d157529a42d031b Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 11 Jun 2019 20:53:44 +0530 Subject: [PATCH 1161/5608] Add method to check if model exists locally already --- osu.Game/Database/ArchiveDownloadModelManager.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Database/ArchiveDownloadModelManager.cs b/osu.Game/Database/ArchiveDownloadModelManager.cs index 629cb81440..3c0de0b566 100644 --- a/osu.Game/Database/ArchiveDownloadModelManager.cs +++ b/osu.Game/Database/ArchiveDownloadModelManager.cs @@ -7,6 +7,7 @@ using osu.Game.Online.API; using osu.Game.Overlays.Notifications; using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace osu.Game.Database @@ -37,10 +38,13 @@ namespace osu.Game.Database private readonly List currentDownloads = new List(); + private readonly MutableDatabaseBackedStoreWithFileIncludes modelStore; + protected ArchiveDownloadModelManager(Storage storage, IDatabaseContextFactory contextFactory, IAPIProvider api, MutableDatabaseBackedStoreWithFileIncludes modelStore, IIpcHost importHost = null) : base(storage, contextFactory, modelStore, importHost) { this.api = api; + this.modelStore = modelStore; } /// @@ -70,6 +74,13 @@ namespace osu.Game.Database return true; } + /// + /// Checks whether a given is available in the local store already. + /// + /// The whose existence needs to be checked. + /// Whether the exists locally. + public bool IsAvailableLocally(TModel model) => modelStore.ConsumableItems.Any(m => m.Equals(model)); + /// /// Downloads a with optional parameters for the download request. /// From 27054a744ed316fd623b33f4a8cfeeec9c787dc8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Jun 2019 00:35:13 +0900 Subject: [PATCH 1162/5608] Fill in thread pool names --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- osu.Game/Database/ArchiveModelManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 47411c69ec..67d3382e01 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -426,7 +426,7 @@ namespace osu.Game.Beatmaps private const int update_queue_request_concurrency = 4; - private readonly ThreadedTaskScheduler updateScheduler = new ThreadedTaskScheduler(update_queue_request_concurrency); + private readonly ThreadedTaskScheduler updateScheduler = new ThreadedTaskScheduler(update_queue_request_concurrency, nameof(BeatmapUpdateQueue)); public BeatmapUpdateQueue(IAPIProvider api) { diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 844ae622a5..d764601b32 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -644,6 +644,6 @@ namespace osu.Game.Database /// This scheduler generally performs IO and CPU intensive work so concurrency is limited harshly. /// It is mainly being used as a queue mechanism for large imports. /// - protected static readonly ThreadedTaskScheduler IMPORT_SCHEDULER = new ThreadedTaskScheduler(import_queue_request_concurrency); + protected static readonly ThreadedTaskScheduler IMPORT_SCHEDULER = new ThreadedTaskScheduler(import_queue_request_concurrency, nameof(ArchiveModelManager)); } } From 06a558c4b7127107b494d8dfe9db3f50263e86e5 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 11 Jun 2019 21:11:30 +0530 Subject: [PATCH 1163/5608] Remove unecessary third generic and change usages to match --- osu.Game/Beatmaps/BeatmapManager.cs | 6 ++---- .../Database/ArchiveDownloadModelManager.cs | 18 ++++++++---------- .../API/Requests/DownloadBeatmapSetRequest.cs | 7 +++---- .../Direct/DownloadTrackingComposite.cs | 8 ++++---- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 6ad5ce6617..2dcd1b137c 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -25,7 +25,7 @@ namespace osu.Game.Beatmaps /// /// Handles the storage and retrieval of Beatmaps/WorkingBeatmaps. /// - public partial class BeatmapManager : ArchiveDownloadModelManager + public partial class BeatmapManager : ArchiveDownloadModelManager { /// /// Fired when a single difficulty has been hidden. @@ -58,8 +58,6 @@ namespace osu.Game.Beatmaps private readonly GameHost host; - private readonly List currentDownloads = new List(); - public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, AudioManager audioManager, GameHost host = null, WorkingBeatmap defaultBeatmap = null) : base(storage, contextFactory, api, new BeatmapStore(contextFactory), host) @@ -76,7 +74,7 @@ namespace osu.Game.Beatmaps beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b); } - protected override DownloadBeatmapSetRequest CreateDownloadRequest(BeatmapSetInfo set, object[] options) => new DownloadBeatmapSetRequest(set, (options?.FirstOrDefault() as bool?) ?? false); + protected override ArchiveDownloadModelRequest CreateDownloadRequest(BeatmapSetInfo set, object[] options) => new DownloadBeatmapSetRequest(set, (options?.FirstOrDefault() as bool?) ?? false); protected override void Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive) { diff --git a/osu.Game/Database/ArchiveDownloadModelManager.cs b/osu.Game/Database/ArchiveDownloadModelManager.cs index 3c0de0b566..64920710bc 100644 --- a/osu.Game/Database/ArchiveDownloadModelManager.cs +++ b/osu.Game/Database/ArchiveDownloadModelManager.cs @@ -18,25 +18,23 @@ namespace osu.Game.Database /// /// The model type. /// The associated file join type. - /// The associated for this model. - public abstract class ArchiveDownloadModelManager : ArchiveModelManager + public abstract class ArchiveDownloadModelManager : ArchiveModelManager where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() - where TDownloadRequestModel : ArchiveDownloadModelRequest { /// /// Fired when a download begins. /// - public event Action DownloadBegan; + public event Action> DownloadBegan; /// /// Fired when a download is interrupted, either due to user cancellation or failure. /// - public event Action DownloadFailed; + public event Action> DownloadFailed; private readonly IAPIProvider api; - private readonly List currentDownloads = new List(); + private readonly List> currentDownloads = new List>(); private readonly MutableDatabaseBackedStoreWithFileIncludes modelStore; @@ -55,7 +53,7 @@ namespace osu.Game.Database /// The to be downloaded. /// Extra parameters for request creation, null if none were passed. /// The request object. - protected abstract TDownloadRequestModel CreateDownloadRequest(TModel model, object[] options); + protected abstract ArchiveDownloadModelRequest CreateDownloadRequest(TModel model, object[] options); /// /// Downloads a . @@ -102,12 +100,12 @@ namespace osu.Game.Database /// Gets an existing download request if it exists. /// /// The whose request is wanted. - /// The object if it exists, otherwise null. - public TDownloadRequestModel GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Info.Equals(model)); + /// The object if it exists, otherwise null. + public ArchiveDownloadModelRequest GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Info.Equals(model)); private bool canDownload(TModel model) => GetExistingDownload(model) == null && api != null; - private void performDownloadWithRequest(TDownloadRequestModel request) + private void performDownloadWithRequest(ArchiveDownloadModelRequest request) { DownloadNotification notification = new DownloadNotification { diff --git a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs index 7d0a8f9f46..8d636f6730 100644 --- a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs @@ -7,17 +7,16 @@ namespace osu.Game.Online.API.Requests { public class DownloadBeatmapSetRequest : ArchiveDownloadModelRequest { - public readonly BeatmapSetInfo BeatmapSet; - private readonly bool noVideo; + private readonly BeatmapSetInfo set; public DownloadBeatmapSetRequest(BeatmapSetInfo set, bool noVideo) : base(set) { this.noVideo = noVideo; - BeatmapSet = set; + this.set = set; } - protected override string Target => $@"beatmapsets/{BeatmapSet.OnlineBeatmapSetID}/download{(noVideo ? "?noVideo=1" : "")}"; + protected override string Target => $@"beatmapsets/{set.OnlineBeatmapSetID}/download{(noVideo ? "?noVideo=1" : "")}"; } } diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs index 9beedb195f..c1ff6ecb60 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs +++ b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs @@ -7,7 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests; +using osu.Game.Online.API; namespace osu.Game.Overlays.Direct { @@ -49,7 +49,7 @@ namespace osu.Game.Overlays.Direct beatmaps.DownloadBegan += download => { - if (download.BeatmapSet.OnlineBeatmapSetID == BeatmapSet.Value?.OnlineBeatmapSetID) + if (download.Info.OnlineBeatmapSetID == BeatmapSet.Value?.OnlineBeatmapSetID) attachDownload(download); }; @@ -76,9 +76,9 @@ namespace osu.Game.Overlays.Direct #endregion - private DownloadBeatmapSetRequest attachedRequest; + private ArchiveDownloadModelRequest attachedRequest; - private void attachDownload(DownloadBeatmapSetRequest request) + private void attachDownload(ArchiveDownloadModelRequest request) { if (attachedRequest != null) { From d903ad2186ed7c6e81fc2c4982eef2e5b89e5ee3 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 11 Jun 2019 21:30:25 +0530 Subject: [PATCH 1164/5608] Fix order --- osu.Game/Database/ArchiveDownloadModelManager.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Database/ArchiveDownloadModelManager.cs b/osu.Game/Database/ArchiveDownloadModelManager.cs index 64920710bc..2fb661ccce 100644 --- a/osu.Game/Database/ArchiveDownloadModelManager.cs +++ b/osu.Game/Database/ArchiveDownloadModelManager.cs @@ -72,15 +72,9 @@ namespace osu.Game.Database return true; } - /// - /// Checks whether a given is available in the local store already. - /// - /// The whose existence needs to be checked. - /// Whether the exists locally. - public bool IsAvailableLocally(TModel model) => modelStore.ConsumableItems.Any(m => m.Equals(model)); - /// /// Downloads a with optional parameters for the download request. + /// This will post notifications tracking progress. /// /// The to be downloaded. /// Optional parameters to be used for creating the download request. @@ -96,6 +90,13 @@ namespace osu.Game.Database return true; } + /// + /// Checks whether a given is available in the local store already. + /// + /// The whose existence needs to be checked. + /// Whether the exists locally. + public bool IsAvailableLocally(TModel model) => modelStore.ConsumableItems.Any(m => m.Equals(model)); + /// /// Gets an existing download request if it exists. /// From 4a6074865e270a66c170fa508a9cb1ee126f4dec Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 11 Jun 2019 22:42:57 +0530 Subject: [PATCH 1165/5608] Create interfaces for DownloadTrackingComposite to consume --- osu.Game/Beatmaps/BeatmapManager.cs | 2 + .../Database/ArchiveDownloadModelManager.cs | 28 +---------- osu.Game/Database/ArchiveModelManager.cs | 2 +- osu.Game/Database/IDownloadModelManager.cs | 47 +++++++++++++++++++ osu.Game/Database/IModelManager.cs | 20 ++++++++ 5 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 osu.Game/Database/IDownloadModelManager.cs create mode 100644 osu.Game/Database/IModelManager.cs diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 2dcd1b137c..e124e38dd9 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -229,6 +229,8 @@ namespace osu.Game.Beatmaps /// Results from the provided query. public IQueryable QueryBeatmaps(Expression> query) => beatmaps.Beatmaps.AsNoTracking().Where(query); + public override bool IsAvailableLocally(BeatmapSetInfo set) => beatmaps.ConsumableItems.Any(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending && !s.Protected); + protected override BeatmapSetInfo CreateModel(ArchiveReader reader) { // let's make sure there are actually .osu files to import. diff --git a/osu.Game/Database/ArchiveDownloadModelManager.cs b/osu.Game/Database/ArchiveDownloadModelManager.cs index 2fb661ccce..c868b8d1d5 100644 --- a/osu.Game/Database/ArchiveDownloadModelManager.cs +++ b/osu.Game/Database/ArchiveDownloadModelManager.cs @@ -18,18 +18,12 @@ namespace osu.Game.Database /// /// The model type. /// The associated file join type. - public abstract class ArchiveDownloadModelManager : ArchiveModelManager + public abstract class ArchiveDownloadModelManager : ArchiveModelManager, IDownloadModelManager where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() { - /// - /// Fired when a download begins. - /// public event Action> DownloadBegan; - /// - /// Fired when a download is interrupted, either due to user cancellation or failure. - /// public event Action> DownloadFailed; private readonly IAPIProvider api; @@ -55,12 +49,6 @@ namespace osu.Game.Database /// The request object. protected abstract ArchiveDownloadModelRequest CreateDownloadRequest(TModel model, object[] options); - /// - /// Downloads a . - /// This will post notifications tracking progress. - /// - /// The to be downloaded. - /// Whether downloading can happen. public bool Download(TModel model) { if (!canDownload(model)) return false; @@ -72,13 +60,6 @@ namespace osu.Game.Database return true; } - /// - /// Downloads a with optional parameters for the download request. - /// This will post notifications tracking progress. - /// - /// The to be downloaded. - /// Optional parameters to be used for creating the download request. - /// Whether downloading can happen. public bool Download(TModel model, params object[] extra) { if (!canDownload(model)) return false; @@ -90,12 +71,7 @@ namespace osu.Game.Database return true; } - /// - /// Checks whether a given is available in the local store already. - /// - /// The whose existence needs to be checked. - /// Whether the exists locally. - public bool IsAvailableLocally(TModel model) => modelStore.ConsumableItems.Any(m => m.Equals(model)); + public virtual bool IsAvailableLocally(TModel model) => modelStore.ConsumableItems.Any(m => m.Equals(model) && !m.DeletePending); /// /// Gets an existing download request if it exists. diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 54dbae9ddc..50cb9dac8b 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -29,7 +29,7 @@ namespace osu.Game.Database /// /// The model type. /// The associated file join type. - public abstract class ArchiveModelManager : ICanAcceptFiles + public abstract class ArchiveModelManager : ICanAcceptFiles, IModelManager where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() { diff --git a/osu.Game/Database/IDownloadModelManager.cs b/osu.Game/Database/IDownloadModelManager.cs new file mode 100644 index 0000000000..3231d855ea --- /dev/null +++ b/osu.Game/Database/IDownloadModelManager.cs @@ -0,0 +1,47 @@ +using osu.Game.Online.API; +using System; +using System.Collections.Generic; +using System.Text; + +namespace osu.Game.Database +{ + public interface IDownloadModelManager : IModelManager + where TModel : class + { + /// + /// Fired when a download begins. + /// + event Action> DownloadBegan; + + /// + /// Fired when a download is interrupted, either due to user cancellation or failure. + /// + event Action> DownloadFailed; + + bool IsAvailableLocally(TModel model); + + /// + /// Downloads a . + /// This will post notifications tracking progress. + /// + /// The to be downloaded. + /// Whether downloading can happen. + bool Download(TModel model); + + /// + /// Downloads a with optional parameters for the download request. + /// This will post notifications tracking progress. + /// + /// The to be downloaded. + /// Optional parameters to be used for creating the download request. + /// Whether downloading can happen. + bool Download(TModel model, params object[] extra); + + /// + /// Checks whether a given is available in the local store already. + /// + /// The whose existence needs to be checked. + /// Whether the exists locally. + ArchiveDownloadModelRequest GetExistingDownload(TModel model); + } +} diff --git a/osu.Game/Database/IModelManager.cs b/osu.Game/Database/IModelManager.cs new file mode 100644 index 0000000000..6a0b2bde44 --- /dev/null +++ b/osu.Game/Database/IModelManager.cs @@ -0,0 +1,20 @@ + +using System; + +namespace osu.Game.Database +{ + public interface IModelManager + { + /// + /// Fired when a new becomes available in the database. + /// This is not guaranteed to run on the update thread. + /// + event Action ItemAdded; + + /// + /// Fired when a is removed from the database. + /// This is not guaranteed to run on the update thread. + /// + event Action ItemRemoved; + } +} From 6c74998487166c9723e191a33c74f97dfe36164a Mon Sep 17 00:00:00 2001 From: Lucas A Date: Tue, 11 Jun 2019 19:24:36 +0200 Subject: [PATCH 1166/5608] Set ScreenActivity to InitialScreenActivity only when ScreenActivity hasn't been set manually before. --- osu.Game/Screens/OsuScreen.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 3b5e0fd0d6..582f97d46a 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -56,9 +56,13 @@ namespace osu.Game.Screens /// /// The to set the user's activity automatically to when this screen is entered + /// This will be automatically set to for this screen on entering unless + /// is manually set before. /// protected virtual UserActivity InitialScreenActivity => null; + private UserActivity screenActivity; + /// /// The for this screen. /// @@ -74,8 +78,6 @@ namespace osu.Game.Screens } } - private UserActivity screenActivity; - /// /// Whether to disallow changes to game-wise Beatmap/Ruleset bindables for this screen (and all children). /// @@ -170,7 +172,8 @@ namespace osu.Game.Screens backgroundStack?.Push(localBackground = CreateBackground()); - ScreenActivity = InitialScreenActivity; + if (screenActivity == null) + ScreenActivity = InitialScreenActivity; base.OnEntering(last); } From ab27d82cd581acba8e738a33704484335edd0f69 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 11 Jun 2019 23:01:01 +0530 Subject: [PATCH 1167/5608] Make beatmap download buttons inherit BeatmapDownloadTrackingComposite - Move DownloadTrackingComposite into the online namespace --- osu.Game/Database/ArchiveModelManager.cs | 4 +- .../Direct => Online}/DownloadState.cs | 2 +- .../DownloadTrackingComposite.cs | 53 ++++++++++--------- .../BeatmapSet/Buttons/DownloadButton.cs | 3 +- osu.Game/Overlays/BeatmapSet/Header.cs | 3 +- .../BeatmapDownloadTrackingComposite.cs | 16 ++++++ osu.Game/Overlays/Direct/DownloadButton.cs | 3 +- .../Overlays/Direct/DownloadProgressBar.cs | 3 +- 8 files changed, 55 insertions(+), 32 deletions(-) rename osu.Game/{Overlays/Direct => Online}/DownloadState.cs (89%) rename osu.Game/{Overlays/Direct => Online}/DownloadTrackingComposite.cs (63%) create mode 100644 osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 50cb9dac8b..ccaba99427 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -29,7 +29,7 @@ namespace osu.Game.Database /// /// The model type. /// The associated file join type. - public abstract class ArchiveModelManager : ICanAcceptFiles, IModelManager + public abstract class ArchiveModelManager : ICanAcceptFiles, IModelManager where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() { @@ -44,7 +44,7 @@ namespace osu.Game.Database /// Fired when a new becomes available in the database. /// This is not guaranteed to run on the update thread. /// - public event ItemAddedDelegate ItemAdded; + public event Action ItemAdded; /// /// Fired when a is removed from the database. diff --git a/osu.Game/Overlays/Direct/DownloadState.cs b/osu.Game/Online/DownloadState.cs similarity index 89% rename from osu.Game/Overlays/Direct/DownloadState.cs rename to osu.Game/Online/DownloadState.cs index a301c6a3bd..72efbc286e 100644 --- a/osu.Game/Overlays/Direct/DownloadState.cs +++ b/osu.Game/Online/DownloadState.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -namespace osu.Game.Overlays.Direct +namespace osu.Game.Online { public enum DownloadState { diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs b/osu.Game/Online/DownloadTrackingComposite.cs similarity index 63% rename from osu.Game/Overlays/Direct/DownloadTrackingComposite.cs rename to osu.Game/Online/DownloadTrackingComposite.cs index c1ff6ecb60..157211e6c2 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs +++ b/osu.Game/Online/DownloadTrackingComposite.cs @@ -7,18 +7,21 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; +using osu.Game.Database; using osu.Game.Online.API; -namespace osu.Game.Overlays.Direct +namespace osu.Game.Online { /// /// A component which tracks a beatmap through potential download/import/deletion. /// - public abstract class DownloadTrackingComposite : CompositeDrawable + public abstract class DownloadTrackingComposite : CompositeDrawable + where TModel : class + where TModelManager : class, IDownloadModelManager { - public readonly Bindable BeatmapSet = new Bindable(); + public readonly Bindable ModelInfo = new Bindable(); - private BeatmapManager beatmaps; + private TModelManager manager; /// /// Holds the current download state of the beatmap, whether is has already been downloaded, is in progress, or is not downloaded. @@ -27,34 +30,34 @@ namespace osu.Game.Overlays.Direct protected readonly Bindable Progress = new Bindable(); - protected DownloadTrackingComposite(BeatmapSetInfo beatmapSet = null) + protected DownloadTrackingComposite(TModel model = null) { - BeatmapSet.Value = beatmapSet; + ModelInfo.Value = model; } [BackgroundDependencyLoader(true)] - private void load(BeatmapManager beatmaps) + private void load(TModelManager manager) { - this.beatmaps = beatmaps; + this.manager = manager; - BeatmapSet.BindValueChanged(setInfo => + ModelInfo.BindValueChanged(modelInfo => { - if (setInfo.NewValue == null) + if (modelInfo.NewValue == null) attachDownload(null); - else if (beatmaps.GetAllUsableBeatmapSetsEnumerable().Any(s => s.OnlineBeatmapSetID == setInfo.NewValue.OnlineBeatmapSetID)) + else if (manager.IsAvailableLocally(modelInfo.NewValue)) State.Value = DownloadState.LocallyAvailable; else - attachDownload(beatmaps.GetExistingDownload(setInfo.NewValue)); + attachDownload(manager.GetExistingDownload(modelInfo.NewValue)); }, true); - beatmaps.DownloadBegan += download => + manager.DownloadBegan += download => { - if (download.Info.OnlineBeatmapSetID == BeatmapSet.Value?.OnlineBeatmapSetID) + if (download.Info.Equals(ModelInfo.Value)) attachDownload(download); }; - beatmaps.ItemAdded += setAdded; - beatmaps.ItemRemoved += setRemoved; + manager.ItemAdded += itemAdded; + manager.ItemRemoved += itemRemoved; } #region Disposal @@ -63,10 +66,10 @@ namespace osu.Game.Overlays.Direct { base.Dispose(isDisposing); - if (beatmaps != null) + if (manager != null) { - beatmaps.DownloadBegan -= attachDownload; - beatmaps.ItemAdded -= setAdded; + manager.DownloadBegan -= attachDownload; + manager.ItemAdded -= itemAdded; } State.UnbindAll(); @@ -76,9 +79,9 @@ namespace osu.Game.Overlays.Direct #endregion - private ArchiveDownloadModelRequest attachedRequest; + private ArchiveDownloadModelRequest attachedRequest; - private void attachDownload(ArchiveDownloadModelRequest request) + private void attachDownload(ArchiveDownloadModelRequest request) { if (attachedRequest != null) { @@ -118,13 +121,13 @@ namespace osu.Game.Overlays.Direct private void onRequestFailure(Exception e) => Schedule(() => attachDownload(null)); - private void setAdded(BeatmapSetInfo s, bool existing) => setDownloadStateFromManager(s, DownloadState.LocallyAvailable); + private void itemAdded(TModel s, bool existing) => setDownloadStateFromManager(s, DownloadState.LocallyAvailable); - private void setRemoved(BeatmapSetInfo s) => setDownloadStateFromManager(s, DownloadState.NotDownloaded); + private void itemRemoved(TModel s) => setDownloadStateFromManager(s, DownloadState.NotDownloaded); - private void setDownloadStateFromManager(BeatmapSetInfo s, DownloadState state) => Schedule(() => + private void setDownloadStateFromManager(TModel s, DownloadState state) => Schedule(() => { - if (s.OnlineBeatmapSetID != BeatmapSet.Value?.OnlineBeatmapSetID) + if (s.Equals(ModelInfo.Value)) return; State.Value = state; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 0a159507fe..3e8a5a8324 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -11,6 +11,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Overlays.Direct; using osu.Game.Users; @@ -19,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Buttons { - public class DownloadButton : DownloadTrackingComposite, IHasTooltip + public class DownloadButton : BeatmapDownloadTrackingComposite, IHasTooltip { private readonly bool noVideo; diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index a0f71d05c0..d0c6e4aa62 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Online; using osu.Game.Overlays.BeatmapSet.Buttons; using osu.Game.Overlays.Direct; using osuTK; @@ -21,7 +22,7 @@ using DownloadButton = osu.Game.Overlays.BeatmapSet.Buttons.DownloadButton; namespace osu.Game.Overlays.BeatmapSet { - public class Header : DownloadTrackingComposite + public class Header : BeatmapDownloadTrackingComposite { private const float transition_duration = 200; private const float tabs_height = 50; diff --git a/osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs new file mode 100644 index 0000000000..67fc5b48bd --- /dev/null +++ b/osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs @@ -0,0 +1,16 @@ +using osu.Framework.Bindables; +using osu.Game.Beatmaps; +using osu.Game.Online; + +namespace osu.Game.Overlays.Direct +{ + public abstract class BeatmapDownloadTrackingComposite : DownloadTrackingComposite + { + public Bindable BeatmapSet => ModelInfo; + + public BeatmapDownloadTrackingComposite(BeatmapSetInfo set = null) + : base(set) + { + } + } +} diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 3f44d854e5..348ce427bd 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -9,11 +9,12 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Online; using osuTK; namespace osu.Game.Overlays.Direct { - public class DownloadButton : DownloadTrackingComposite + public class DownloadButton : BeatmapDownloadTrackingComposite { private readonly bool noVideo; private readonly SpriteIcon icon; diff --git a/osu.Game/Overlays/Direct/DownloadProgressBar.cs b/osu.Game/Overlays/Direct/DownloadProgressBar.cs index 57500b3531..a6cefaae84 100644 --- a/osu.Game/Overlays/Direct/DownloadProgressBar.cs +++ b/osu.Game/Overlays/Direct/DownloadProgressBar.cs @@ -7,11 +7,12 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; +using osu.Game.Online; using osuTK.Graphics; namespace osu.Game.Overlays.Direct { - public class DownloadProgressBar : DownloadTrackingComposite + public class DownloadProgressBar : BeatmapDownloadTrackingComposite { private readonly ProgressBar progressBar; From 15893bbb754fa73003f578a385b9cb7fa98a3b7d Mon Sep 17 00:00:00 2001 From: Lucas A Date: Tue, 11 Jun 2019 19:41:48 +0200 Subject: [PATCH 1168/5608] Drop UserActivity prefix for subclasses nested in UserActivity + Change status messages. --- .../Visual/Online/TestSceneUserPanel.cs | 10 ++++---- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Select/PlaySongSelect.cs | 2 +- osu.Game/Users/UserActivity.cs | 24 +++++++++---------- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index 2c20ea98a3..18541e7637 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -61,11 +61,11 @@ namespace osu.Game.Tests.Visual.Online public void UserActivitiesTests() { AddStep("idle", () => { flyte.Activity.Value = null; }); - AddStep("spectating", () => { flyte.Activity.Value = new UserActivity.UserActivitySpectating(); }); - AddStep("solo", () => { flyte.Activity.Value = new UserActivity.UserActivitySoloGame(null, null); }); - AddStep("choosing", () => { flyte.Activity.Value = new UserActivity.UserActivityChoosingBeatmap(); }); - AddStep("editing", () => { flyte.Activity.Value = new UserActivity.UserActivityEditing(null); }); - AddStep("modding", () => { flyte.Activity.Value = new UserActivity.UserActivityModding(); }); + AddStep("spectating", () => { flyte.Activity.Value = new UserActivity.Spectating(); }); + AddStep("solo", () => { flyte.Activity.Value = new UserActivity.SoloGame(null, null); }); + AddStep("choosing", () => { flyte.Activity.Value = new UserActivity.ChoosingBeatmap(); }); + AddStep("editing", () => { flyte.Activity.Value = new UserActivity.Editing(null); }); + AddStep("modding", () => { flyte.Activity.Value = new UserActivity.Modding(); }); } } } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index a4cb659183..c6e1850af1 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -48,7 +48,7 @@ namespace osu.Game.Screens.Edit private DependencyContainer dependencies; private GameHost host; - protected override UserActivity InitialScreenActivity => new UserActivity.UserActivityEditing(Beatmap.Value.BeatmapInfo); + protected override UserActivity InitialScreenActivity => new UserActivity.Editing(Beatmap.Value.BeatmapInfo); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 22a0e65f91..e8fa99b397 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Play { protected override bool AllowBackButton => false; // handled by HoldForMenuButton - protected override UserActivity InitialScreenActivity => new UserActivity.UserActivitySoloGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); + protected override UserActivity InitialScreenActivity => new UserActivity.SoloGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); public override float BackgroundParallaxAmount => 0.1f; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index aba3343d69..f81bad6693 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Select public override bool AllowExternalScreenChange => true; - protected override UserActivity InitialScreenActivity => new UserActivity.UserActivityChoosingBeatmap(); + protected override UserActivity InitialScreenActivity => new UserActivity.ChoosingBeatmap(); [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index fe72f116ee..b088e8036d 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -12,25 +12,25 @@ namespace osu.Game.Users public abstract string Status { get; } public virtual Color4 GetAppropriateColour(OsuColour colours) => colours.GreenDarker; - public class UserActivityModding : UserActivity + public class Modding : UserActivity { public override string Status => "Modding a map"; public override Color4 GetAppropriateColour(OsuColour colours) => colours.PurpleDark; } - public class UserActivityChoosingBeatmap : UserActivity + public class ChoosingBeatmap : UserActivity { public override string Status => "Choosing a beatmap"; } - public class UserActivityMultiplayerGame : UserActivity + public class MultiplayerGame : UserActivity { - public override string Status => "Multiplaying"; + public override string Status => "Playing with others"; } - public class UserActivityEditing : UserActivity + public class Editing : UserActivity { - public UserActivityEditing(BeatmapInfo info) + public Editing(BeatmapInfo info) { Beatmap = info; } @@ -40,29 +40,29 @@ namespace osu.Game.Users public BeatmapInfo Beatmap { get; } } - public class UserActivitySoloGame : UserActivity + public class SoloGame : UserActivity { - public UserActivitySoloGame(BeatmapInfo info, Rulesets.RulesetInfo ruleset) + public SoloGame(BeatmapInfo info, Rulesets.RulesetInfo ruleset) { Beatmap = info; Ruleset = ruleset; } - public override string Status => @"Solo Game"; + public override string Status => @"Playing alone"; public BeatmapInfo Beatmap { get; } public Rulesets.RulesetInfo Ruleset { get; } } - public class UserActivitySpectating : UserActivity + public class Spectating : UserActivity { public override string Status => @"Spectating a game"; } - public class UserActivityInLobby : UserActivity + public class InLobby : UserActivity { - public override string Status => @"in Multiplayer Lobby"; + public override string Status => @"In a Multiplayer Lobby"; } } } From 41da491a7eb3d9287c7e1725214f4e456576bdd7 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 11 Jun 2019 23:23:40 +0530 Subject: [PATCH 1169/5608] Make BeatmapSetInfo equatable --- osu.Game/Beatmaps/BeatmapSetInfo.cs | 4 +++- osu.Game/Online/DownloadTrackingComposite.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 390236e053..aa5ed48641 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -9,7 +9,7 @@ using osu.Game.Database; namespace osu.Game.Beatmaps { - public class BeatmapSetInfo : IHasPrimaryKey, IHasFiles, ISoftDelete + public class BeatmapSetInfo : IHasPrimaryKey, IHasFiles, ISoftDelete, IEquatable { public int ID { get; set; } @@ -46,5 +46,7 @@ namespace osu.Game.Beatmaps public override string ToString() => Metadata?.ToString() ?? base.ToString(); public bool Protected { get; set; } + + public bool Equals(BeatmapSetInfo other) => OnlineBeatmapSetID == other?.OnlineBeatmapSetID; } } diff --git a/osu.Game/Online/DownloadTrackingComposite.cs b/osu.Game/Online/DownloadTrackingComposite.cs index 157211e6c2..d233be19f5 100644 --- a/osu.Game/Online/DownloadTrackingComposite.cs +++ b/osu.Game/Online/DownloadTrackingComposite.cs @@ -16,7 +16,7 @@ namespace osu.Game.Online /// A component which tracks a beatmap through potential download/import/deletion. /// public abstract class DownloadTrackingComposite : CompositeDrawable - where TModel : class + where TModel : class, IEquatable where TModelManager : class, IDownloadModelManager { public readonly Bindable ModelInfo = new Bindable(); From 51d428ef949f68e02803339fa2c32cfc4888495b Mon Sep 17 00:00:00 2001 From: Lucas A Date: Tue, 11 Jun 2019 20:00:14 +0200 Subject: [PATCH 1170/5608] Refactor UserPanel status display logic --- osu.Game/Users/UserPanel.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 1f31ead1e7..04f5a0a3fb 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -231,17 +231,18 @@ namespace osu.Game.Users statusBar.ResizeHeightTo(status_height, transition_duration, Easing.OutQuint); statusBar.FadeIn(transition_duration, Easing.OutQuint); this.ResizeHeightTo(height, transition_duration, Easing.OutQuint); - - if (status is UserStatusOnline && activity != null) - { - statusMessage.Text = activity.Status; - statusBg.FadeColour(activity.GetAppropriateColour(colours), 500, Easing.OutQuint); - return; - } } - statusMessage.Text = status?.Message; - statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint); + if (status is UserStatusOnline && activity != null) + { + statusMessage.Text = activity.Status; + statusBg.FadeColour(activity.GetAppropriateColour(colours), 500, Easing.OutQuint); + } + else + { + statusMessage.Text = status?.Message; + statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint); + } } public MenuItem[] ContextMenuItems => new MenuItem[] From c320b6110cf463a1f5e74050e320468a26a484a1 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 11 Jun 2019 23:47:05 +0530 Subject: [PATCH 1171/5608] Rename interface - Fix wrong inheritance in ArchiveModelManager - Add license headers --- osu.Game/Database/ArchiveDownloadModelManager.cs | 2 +- osu.Game/Database/ArchiveModelManager.cs | 4 ++-- ...{IDownloadModelManager.cs => IModelDownloader.cs} | 9 +++++---- osu.Game/Database/IModelManager.cs | 12 +++--------- 4 files changed, 11 insertions(+), 16 deletions(-) rename osu.Game/Database/{IDownloadModelManager.cs => IModelDownloader.cs} (87%) diff --git a/osu.Game/Database/ArchiveDownloadModelManager.cs b/osu.Game/Database/ArchiveDownloadModelManager.cs index c868b8d1d5..8d221bd3ea 100644 --- a/osu.Game/Database/ArchiveDownloadModelManager.cs +++ b/osu.Game/Database/ArchiveDownloadModelManager.cs @@ -18,7 +18,7 @@ namespace osu.Game.Database /// /// The model type. /// The associated file join type. - public abstract class ArchiveDownloadModelManager : ArchiveModelManager, IDownloadModelManager + public abstract class ArchiveDownloadModelManager : ArchiveModelManager, IModelDownloader where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() { diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 50cb9dac8b..ccaba99427 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -29,7 +29,7 @@ namespace osu.Game.Database /// /// The model type. /// The associated file join type. - public abstract class ArchiveModelManager : ICanAcceptFiles, IModelManager + public abstract class ArchiveModelManager : ICanAcceptFiles, IModelManager where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() { @@ -44,7 +44,7 @@ namespace osu.Game.Database /// Fired when a new becomes available in the database. /// This is not guaranteed to run on the update thread. /// - public event ItemAddedDelegate ItemAdded; + public event Action ItemAdded; /// /// Fired when a is removed from the database. diff --git a/osu.Game/Database/IDownloadModelManager.cs b/osu.Game/Database/IModelDownloader.cs similarity index 87% rename from osu.Game/Database/IDownloadModelManager.cs rename to osu.Game/Database/IModelDownloader.cs index 3231d855ea..bf987bb53c 100644 --- a/osu.Game/Database/IDownloadModelManager.cs +++ b/osu.Game/Database/IModelDownloader.cs @@ -1,11 +1,12 @@ -using osu.Game.Online.API; +// 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; using System; -using System.Collections.Generic; -using System.Text; namespace osu.Game.Database { - public interface IDownloadModelManager : IModelManager + public interface IModelDownloader : IModelManager where TModel : class { /// diff --git a/osu.Game/Database/IModelManager.cs b/osu.Game/Database/IModelManager.cs index 6a0b2bde44..ee78df3db4 100644 --- a/osu.Game/Database/IModelManager.cs +++ b/osu.Game/Database/IModelManager.cs @@ -1,20 +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; namespace osu.Game.Database { public interface IModelManager { - /// - /// Fired when a new becomes available in the database. - /// This is not guaranteed to run on the update thread. - /// event Action ItemAdded; - /// - /// Fired when a is removed from the database. - /// This is not guaranteed to run on the update thread. - /// event Action ItemRemoved; } } From c69d3e2d388c794a0fcc33efdbc8b37999c48c68 Mon Sep 17 00:00:00 2001 From: naoey Date: Wed, 12 Jun 2019 00:02:53 +0530 Subject: [PATCH 1172/5608] Fix doc move derp --- osu.Game/Database/ArchiveDownloadModelManager.cs | 10 +++++----- osu.Game/Database/IModelDownloader.cs | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Database/ArchiveDownloadModelManager.cs b/osu.Game/Database/ArchiveDownloadModelManager.cs index 8d221bd3ea..ded44337dd 100644 --- a/osu.Game/Database/ArchiveDownloadModelManager.cs +++ b/osu.Game/Database/ArchiveDownloadModelManager.cs @@ -71,13 +71,13 @@ namespace osu.Game.Database return true; } + /// + /// Checks whether a given is available in the local store already. + /// + /// The whose existence needs to be checked. + /// Whether the exists locally. public virtual bool IsAvailableLocally(TModel model) => modelStore.ConsumableItems.Any(m => m.Equals(model) && !m.DeletePending); - /// - /// Gets an existing download request if it exists. - /// - /// The whose request is wanted. - /// The object if it exists, otherwise null. public ArchiveDownloadModelRequest GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Info.Equals(model)); private bool canDownload(TModel model) => GetExistingDownload(model) == null && api != null; diff --git a/osu.Game/Database/IModelDownloader.cs b/osu.Game/Database/IModelDownloader.cs index bf987bb53c..150ad9522f 100644 --- a/osu.Game/Database/IModelDownloader.cs +++ b/osu.Game/Database/IModelDownloader.cs @@ -39,10 +39,10 @@ namespace osu.Game.Database bool Download(TModel model, params object[] extra); /// - /// Checks whether a given is available in the local store already. + /// Gets an existing download request if it exists. /// - /// The whose existence needs to be checked. - /// Whether the exists locally. + /// The whose request is wanted. + /// The object if it exists, otherwise null. ArchiveDownloadModelRequest GetExistingDownload(TModel model); } } From 7495bc5d3a97f457407a8f561b16d4b856f058ea Mon Sep 17 00:00:00 2001 From: naoey Date: Wed, 12 Jun 2019 00:41:17 +0530 Subject: [PATCH 1173/5608] Post merge and inverted condition fix --- osu.Game/Online/DownloadTrackingComposite.cs | 4 ++-- osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/DownloadTrackingComposite.cs b/osu.Game/Online/DownloadTrackingComposite.cs index d233be19f5..0cb3acf019 100644 --- a/osu.Game/Online/DownloadTrackingComposite.cs +++ b/osu.Game/Online/DownloadTrackingComposite.cs @@ -17,7 +17,7 @@ namespace osu.Game.Online /// public abstract class DownloadTrackingComposite : CompositeDrawable where TModel : class, IEquatable - where TModelManager : class, IDownloadModelManager + where TModelManager : class, IModelDownloader { public readonly Bindable ModelInfo = new Bindable(); @@ -127,7 +127,7 @@ namespace osu.Game.Online private void setDownloadStateFromManager(TModel s, DownloadState state) => Schedule(() => { - if (s.Equals(ModelInfo.Value)) + if (!s.Equals(ModelInfo.Value)) return; State.Value = state; diff --git a/osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs index 67fc5b48bd..b6304b82c4 100644 --- a/osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs +++ b/osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs @@ -1,4 +1,7 @@ -using osu.Framework.Bindables; +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Online; From ba6546038c582d1d7249a078dac56624a49ac657 Mon Sep 17 00:00:00 2001 From: naoey Date: Wed, 12 Jun 2019 00:47:02 +0530 Subject: [PATCH 1174/5608] Make ModelInfo and abstract class constructor protected - Implementing classes would be better off exposing it if necessary under a different name --- osu.Game/Online/DownloadTrackingComposite.cs | 4 +--- osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/DownloadTrackingComposite.cs b/osu.Game/Online/DownloadTrackingComposite.cs index 0cb3acf019..d07aed9206 100644 --- a/osu.Game/Online/DownloadTrackingComposite.cs +++ b/osu.Game/Online/DownloadTrackingComposite.cs @@ -2,11 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Online.API; @@ -19,7 +17,7 @@ namespace osu.Game.Online where TModel : class, IEquatable where TModelManager : class, IModelDownloader { - public readonly Bindable ModelInfo = new Bindable(); + protected readonly Bindable ModelInfo = new Bindable(); private TModelManager manager; diff --git a/osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs index b6304b82c4..6f348c4fd7 100644 --- a/osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs +++ b/osu.Game/Overlays/Direct/BeatmapDownloadTrackingComposite.cs @@ -11,7 +11,7 @@ namespace osu.Game.Overlays.Direct { public Bindable BeatmapSet => ModelInfo; - public BeatmapDownloadTrackingComposite(BeatmapSetInfo set = null) + protected BeatmapDownloadTrackingComposite(BeatmapSetInfo set = null) : base(set) { } From 35cc45c9d9dff91795a90ef8785aa3bf99fe7228 Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Tue, 11 Jun 2019 23:11:03 +0300 Subject: [PATCH 1175/5608] Small update --- osu.Game.Tests/Visual/Online/TestSceneBeatmapNotAvailable.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapNotAvailable.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapNotAvailable.cs index bd4570470d..e2a5ab1e35 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapNotAvailable.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapNotAvailable.cs @@ -1,13 +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 NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Overlays.BeatmapSet; namespace osu.Game.Tests.Visual.Online { - [TestFixture] public class TestSceneBeatmapNotAvailable : OsuTestScene { public TestSceneBeatmapNotAvailable() From eaeeffaa866fd7a16108ffc96ac7544319232cf8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Jun 2019 13:28:44 +0900 Subject: [PATCH 1176/5608] Rename to DownloadableArchiveModelManager --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- ...loadModelManager.cs => DownloadableArchiveModelManager.cs} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename osu.Game/Database/{ArchiveDownloadModelManager.cs => DownloadableArchiveModelManager.cs} (94%) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index e124e38dd9..023b6c74ea 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -25,7 +25,7 @@ namespace osu.Game.Beatmaps /// /// Handles the storage and retrieval of Beatmaps/WorkingBeatmaps. /// - public partial class BeatmapManager : ArchiveDownloadModelManager + public partial class BeatmapManager : DownloadableArchiveModelManager { /// /// Fired when a single difficulty has been hidden. diff --git a/osu.Game/Database/ArchiveDownloadModelManager.cs b/osu.Game/Database/DownloadableArchiveModelManager.cs similarity index 94% rename from osu.Game/Database/ArchiveDownloadModelManager.cs rename to osu.Game/Database/DownloadableArchiveModelManager.cs index ded44337dd..71bbbc4f78 100644 --- a/osu.Game/Database/ArchiveDownloadModelManager.cs +++ b/osu.Game/Database/DownloadableArchiveModelManager.cs @@ -18,7 +18,7 @@ namespace osu.Game.Database /// /// The model type. /// The associated file join type. - public abstract class ArchiveDownloadModelManager : ArchiveModelManager, IModelDownloader + public abstract class DownloadableArchiveModelManager : ArchiveModelManager, IModelDownloader where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() { @@ -32,7 +32,7 @@ namespace osu.Game.Database private readonly MutableDatabaseBackedStoreWithFileIncludes modelStore; - protected ArchiveDownloadModelManager(Storage storage, IDatabaseContextFactory contextFactory, IAPIProvider api, MutableDatabaseBackedStoreWithFileIncludes modelStore, IIpcHost importHost = null) + protected DownloadableArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, IAPIProvider api, MutableDatabaseBackedStoreWithFileIncludes modelStore, IIpcHost importHost = null) : base(storage, contextFactory, modelStore, importHost) { this.api = api; From c591a6f1fadd26a0c39855a867d95c2056bd6d82 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Jun 2019 13:30:23 +0900 Subject: [PATCH 1177/5608] Rename request type to be less verbose --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- osu.Game/Database/DownloadableArchiveModelManager.cs | 12 ++++++------ osu.Game/Database/IModelDownloader.cs | 8 ++++---- ...loadModelRequest.cs => ArchiveDownloadRequest.cs} | 4 ++-- .../Online/API/Requests/DownloadBeatmapSetRequest.cs | 2 +- .../Overlays/Direct/DownloadTrackingComposite.cs | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) rename osu.Game/Online/API/{ArchiveDownloadModelRequest.cs => ArchiveDownloadRequest.cs} (78%) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 023b6c74ea..3fc3de41e6 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -74,7 +74,7 @@ namespace osu.Game.Beatmaps beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b); } - protected override ArchiveDownloadModelRequest CreateDownloadRequest(BeatmapSetInfo set, object[] options) => new DownloadBeatmapSetRequest(set, (options?.FirstOrDefault() as bool?) ?? false); + protected override ArchiveDownloadRequest CreateDownloadRequest(BeatmapSetInfo set, object[] options) => new DownloadBeatmapSetRequest(set, (options?.FirstOrDefault() as bool?) ?? false); protected override void Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive) { diff --git a/osu.Game/Database/DownloadableArchiveModelManager.cs b/osu.Game/Database/DownloadableArchiveModelManager.cs index 71bbbc4f78..c22c8d7508 100644 --- a/osu.Game/Database/DownloadableArchiveModelManager.cs +++ b/osu.Game/Database/DownloadableArchiveModelManager.cs @@ -22,13 +22,13 @@ namespace osu.Game.Database where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() { - public event Action> DownloadBegan; + public event Action> DownloadBegan; - public event Action> DownloadFailed; + public event Action> DownloadFailed; private readonly IAPIProvider api; - private readonly List> currentDownloads = new List>(); + private readonly List> currentDownloads = new List>(); private readonly MutableDatabaseBackedStoreWithFileIncludes modelStore; @@ -47,7 +47,7 @@ namespace osu.Game.Database /// The to be downloaded. /// Extra parameters for request creation, null if none were passed. /// The request object. - protected abstract ArchiveDownloadModelRequest CreateDownloadRequest(TModel model, object[] options); + protected abstract ArchiveDownloadRequest CreateDownloadRequest(TModel model, object[] options); public bool Download(TModel model) { @@ -78,11 +78,11 @@ namespace osu.Game.Database /// Whether the exists locally. public virtual bool IsAvailableLocally(TModel model) => modelStore.ConsumableItems.Any(m => m.Equals(model) && !m.DeletePending); - public ArchiveDownloadModelRequest GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Info.Equals(model)); + public ArchiveDownloadRequest GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Info.Equals(model)); private bool canDownload(TModel model) => GetExistingDownload(model) == null && api != null; - private void performDownloadWithRequest(ArchiveDownloadModelRequest request) + private void performDownloadWithRequest(ArchiveDownloadRequest request) { DownloadNotification notification = new DownloadNotification { diff --git a/osu.Game/Database/IModelDownloader.cs b/osu.Game/Database/IModelDownloader.cs index 150ad9522f..83427bdc17 100644 --- a/osu.Game/Database/IModelDownloader.cs +++ b/osu.Game/Database/IModelDownloader.cs @@ -12,12 +12,12 @@ namespace osu.Game.Database /// /// Fired when a download begins. /// - event Action> DownloadBegan; + event Action> DownloadBegan; /// /// Fired when a download is interrupted, either due to user cancellation or failure. /// - event Action> DownloadFailed; + event Action> DownloadFailed; bool IsAvailableLocally(TModel model); @@ -42,7 +42,7 @@ namespace osu.Game.Database /// Gets an existing download request if it exists. /// /// The whose request is wanted. - /// The object if it exists, otherwise null. - ArchiveDownloadModelRequest GetExistingDownload(TModel model); + /// The object if it exists, otherwise null. + ArchiveDownloadRequest GetExistingDownload(TModel model); } } diff --git a/osu.Game/Online/API/ArchiveDownloadModelRequest.cs b/osu.Game/Online/API/ArchiveDownloadRequest.cs similarity index 78% rename from osu.Game/Online/API/ArchiveDownloadModelRequest.cs rename to osu.Game/Online/API/ArchiveDownloadRequest.cs index 7f161f1e98..01f066694d 100644 --- a/osu.Game/Online/API/ArchiveDownloadModelRequest.cs +++ b/osu.Game/Online/API/ArchiveDownloadRequest.cs @@ -5,7 +5,7 @@ using System; namespace osu.Game.Online.API { - public abstract class ArchiveDownloadModelRequest : APIDownloadRequest + public abstract class ArchiveDownloadRequest : APIDownloadRequest where TModel : class { public readonly TModel Info; @@ -14,7 +14,7 @@ namespace osu.Game.Online.API public event Action DownloadProgressed; - protected ArchiveDownloadModelRequest(TModel model) + protected ArchiveDownloadRequest(TModel model) { Info = model; diff --git a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs index 8d636f6730..999864a6eb 100644 --- a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs @@ -5,7 +5,7 @@ using osu.Game.Beatmaps; namespace osu.Game.Online.API.Requests { - public class DownloadBeatmapSetRequest : ArchiveDownloadModelRequest + public class DownloadBeatmapSetRequest : ArchiveDownloadRequest { private readonly bool noVideo; private readonly BeatmapSetInfo set; diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs index c1ff6ecb60..9d0266c00e 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs +++ b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs @@ -76,9 +76,9 @@ namespace osu.Game.Overlays.Direct #endregion - private ArchiveDownloadModelRequest attachedRequest; + private ArchiveDownloadRequest attachedRequest; - private void attachDownload(ArchiveDownloadModelRequest request) + private void attachDownload(ArchiveDownloadRequest request) { if (attachedRequest != null) { From 94e65a324456172971e1b387f039ec1fd7343c0d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Jun 2019 15:16:59 +0900 Subject: [PATCH 1178/5608] Fix settings checkboxes not being searchable --- osu.Game/Overlays/Settings/SettingsCheckbox.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/SettingsCheckbox.cs b/osu.Game/Overlays/Settings/SettingsCheckbox.cs index a1501d8015..a554159fd7 100644 --- a/osu.Game/Overlays/Settings/SettingsCheckbox.cs +++ b/osu.Game/Overlays/Settings/SettingsCheckbox.cs @@ -10,11 +10,14 @@ namespace osu.Game.Overlays.Settings { private OsuCheckbox checkbox; + private string labelText; + protected override Drawable CreateControl() => checkbox = new OsuCheckbox(); public override string LabelText { - set => checkbox.LabelText = value; + get => labelText; + set => checkbox.LabelText = labelText = value; } } } From fc1f778b82edc316d7c0d01eb8526ff247ea97c1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Jun 2019 15:53:53 +0900 Subject: [PATCH 1179/5608] Remove implicit null --- osu.Game/Screens/OsuScreen.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 582f97d46a..874ac35e39 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -123,8 +123,6 @@ namespace osu.Game.Screens { Anchor = Anchor.Centre; Origin = Anchor.Centre; - - screenActivity = null; } [BackgroundDependencyLoader(true)] From bb8a77d27d7a671f4a5c1b065d3cf1d2e7a3618e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Jun 2019 15:59:52 +0900 Subject: [PATCH 1180/5608] Apply all steps to same user panel so interactions can be observed --- .../Visual/Online/TestSceneUserPanel.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index 18541e7637..30814ad9c7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -12,11 +12,12 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneUserPanel : OsuTestScene { - private readonly UserPanel flyte; private readonly UserPanel peppy; public TestSceneUserPanel() { + UserPanel flyte; + Add(new FillFlowContainer { Anchor = Anchor.Centre, @@ -60,12 +61,12 @@ namespace osu.Game.Tests.Visual.Online [Test] public void UserActivitiesTests() { - AddStep("idle", () => { flyte.Activity.Value = null; }); - AddStep("spectating", () => { flyte.Activity.Value = new UserActivity.Spectating(); }); - AddStep("solo", () => { flyte.Activity.Value = new UserActivity.SoloGame(null, null); }); - AddStep("choosing", () => { flyte.Activity.Value = new UserActivity.ChoosingBeatmap(); }); - AddStep("editing", () => { flyte.Activity.Value = new UserActivity.Editing(null); }); - AddStep("modding", () => { flyte.Activity.Value = new UserActivity.Modding(); }); + AddStep("idle", () => { peppy.Activity.Value = null; }); + AddStep("spectating", () => { peppy.Activity.Value = new UserActivity.Spectating(); }); + AddStep("solo", () => { peppy.Activity.Value = new UserActivity.SoloGame(null, null); }); + AddStep("choosing", () => { peppy.Activity.Value = new UserActivity.ChoosingBeatmap(); }); + AddStep("editing", () => { peppy.Activity.Value = new UserActivity.Editing(null); }); + AddStep("modding", () => { peppy.Activity.Value = new UserActivity.Modding(); }); } } } From 13234fb4a4b5e9a26a3480c3ac3c960fd7f56c60 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Jun 2019 16:07:35 +0900 Subject: [PATCH 1181/5608] Adjust comments a bit --- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 6e3bec106f..cf21c78c7f 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -155,7 +155,7 @@ namespace osu.Game.Screens.Select int? previouslySelectedID = null; CarouselBeatmapSet existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID); - // Since we're about to remove the selected beatmap, store its ID so we can go back if needed. + // If the selected beatmap is about to be removed, store its ID so it can be re-selected if required if (existingSet?.State?.Value == CarouselItemState.Selected) previouslySelectedID = selectedBeatmap?.Beatmap.ID; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index dcfe1de8f2..d0645dbab6 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -594,7 +594,7 @@ namespace osu.Game.Screens.Select { bindBindables(); - // As a selection was already obtained, do not attempt to update the selected beatmap. + // If a selection was already obtained, do not attempt to update the selected beatmap. if (Carousel.SelectedBeatmapSet != null) return; From 20b43c20c8f35147f5517f0e50e9730ed20fe9ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Jun 2019 16:33:15 +0900 Subject: [PATCH 1182/5608] Rename variables to remove redundant "screen" terminology --- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/OsuScreen.cs | 33 +++++++++++------------ osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- osu.Game/Screens/Select/PlaySongSelect.cs | 2 +- osu.Game/Users/UserActivity.cs | 12 ++++----- 6 files changed, 26 insertions(+), 27 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index c6e1850af1..de0f3870c6 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -48,7 +48,7 @@ namespace osu.Game.Screens.Edit private DependencyContainer dependencies; private GameHost host; - protected override UserActivity InitialScreenActivity => new UserActivity.Editing(Beatmap.Value.BeatmapInfo); + protected override UserActivity InitialActivity => new UserActivity.Editing(Beatmap.Value.BeatmapInfo); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 874ac35e39..fe53ad17c3 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -56,25 +56,25 @@ namespace osu.Game.Screens /// /// The to set the user's activity automatically to when this screen is entered - /// This will be automatically set to for this screen on entering unless - /// is manually set before. + /// This will be automatically set to for this screen on entering unless + /// is manually set before. /// - protected virtual UserActivity InitialScreenActivity => null; + protected virtual UserActivity InitialActivity => null; - private UserActivity screenActivity; + private UserActivity activity; /// - /// The for this screen. + /// The current for this screen. /// - protected UserActivity ScreenActivity + protected UserActivity Activity { - get => screenActivity; + get => activity; set { - if (value == screenActivity) return; + if (value == activity) return; - screenActivity = value; - setUserActivity(screenActivity); + activity = value; + updateActivity(); } } @@ -152,7 +152,7 @@ namespace osu.Game.Screens sampleExit?.Play(); applyArrivingDefaults(true); - setUserActivity(screenActivity); + updateActivity(); base.OnResuming(last); } @@ -170,8 +170,8 @@ namespace osu.Game.Screens backgroundStack?.Push(localBackground = CreateBackground()); - if (screenActivity == null) - ScreenActivity = InitialScreenActivity; + if (activity == null) + Activity = InitialActivity; base.OnEntering(last); } @@ -190,11 +190,10 @@ namespace osu.Game.Screens return false; } - private void setUserActivity(UserActivity activity) + private void updateActivity() { - if (api == null) return; - - api.LocalUser.Value.Activity.Value = activity; + if (api != null) + api.LocalUser.Value.Activity.Value = activity; } /// diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a545d77184..a25b8a1de7 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Play { protected override bool AllowBackButton => false; // handled by HoldForMenuButton - protected override UserActivity InitialScreenActivity => new UserActivity.SoloGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); + protected override UserActivity InitialActivity => new UserActivity.SoloGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); public override float BackgroundParallaxAmount => 0.1f; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 33d100c871..9de9f5cec8 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Play private bool hideOverlays; public override bool HideOverlaysOnEnter => hideOverlays; - protected override UserActivity InitialScreenActivity => null; //shows the previous screen status + protected override UserActivity InitialActivity => null; //shows the previous screen status public override bool DisallowExternalBeatmapRulesetChanges => true; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index f81bad6693..4df6e6a3f3 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Select public override bool AllowExternalScreenChange => true; - protected override UserActivity InitialScreenActivity => new UserActivity.ChoosingBeatmap(); + protected override UserActivity InitialActivity => new UserActivity.ChoosingBeatmap(); [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index b088e8036d..918c547978 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -30,18 +30,22 @@ namespace osu.Game.Users public class Editing : UserActivity { + public BeatmapInfo Beatmap { get; } + public Editing(BeatmapInfo info) { Beatmap = info; } public override string Status => @"Editing a beatmap"; - - public BeatmapInfo Beatmap { get; } } public class SoloGame : UserActivity { + public BeatmapInfo Beatmap { get; } + + public Rulesets.RulesetInfo Ruleset { get; } + public SoloGame(BeatmapInfo info, Rulesets.RulesetInfo ruleset) { Beatmap = info; @@ -49,10 +53,6 @@ namespace osu.Game.Users } public override string Status => @"Playing alone"; - - public BeatmapInfo Beatmap { get; } - - public Rulesets.RulesetInfo Ruleset { get; } } public class Spectating : UserActivity From c4f54d94bc5e8aa9d52b7e17c0dd3508693cc6bc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Jun 2019 17:00:27 +0900 Subject: [PATCH 1183/5608] Rename methods --- osu.Game/Beatmaps/BeatmapManager.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 67d3382e01..5204bda353 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -110,7 +110,7 @@ namespace osu.Game.Beatmaps validateOnlineIds(beatmapSet); - await updateQueue.Perform(beatmapSet, cancellationToken); + await updateQueue.UpdateAsync(beatmapSet, cancellationToken); } protected override void PreImport(BeatmapSetInfo beatmapSet) @@ -433,20 +433,20 @@ namespace osu.Game.Beatmaps this.api = api; } - public async Task Perform(BeatmapSetInfo beatmapSet, CancellationToken cancellationToken) + public async Task UpdateAsync(BeatmapSetInfo beatmapSet, CancellationToken cancellationToken) { if (api?.State != APIState.Online) return; LogForModel(beatmapSet, "Performing online lookups..."); - await Task.WhenAll(beatmapSet.Beatmaps.Select(b => Perform(beatmapSet, b, cancellationToken)).ToArray()); + await Task.WhenAll(beatmapSet.Beatmaps.Select(b => UpdateAsync(beatmapSet, b, cancellationToken)).ToArray()); } // todo: expose this when we need to do individual difficulty lookups. - protected Task Perform(BeatmapSetInfo beatmapSet, BeatmapInfo beatmap, CancellationToken cancellationToken) - => Task.Factory.StartNew(() => perform(beatmapSet, beatmap), cancellationToken, TaskCreationOptions.HideScheduler, updateScheduler); + protected Task UpdateAsync(BeatmapSetInfo beatmapSet, BeatmapInfo beatmap, CancellationToken cancellationToken) + => Task.Factory.StartNew(() => update(beatmapSet, beatmap), cancellationToken, TaskCreationOptions.HideScheduler, updateScheduler); - private void perform(BeatmapSetInfo set, BeatmapInfo beatmap) + private void update(BeatmapSetInfo set, BeatmapInfo beatmap) { if (api?.State != APIState.Online) return; From fd7dc9504e6c91b9502c5e389d28677be49b81d5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Jun 2019 17:08:50 +0900 Subject: [PATCH 1184/5608] Remove async when not required --- osu.Game/Beatmaps/BeatmapManager.cs | 10 +++++----- osu.Game/Database/ArchiveModelManager.cs | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 5204bda353..d90657bff5 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -94,7 +94,7 @@ namespace osu.Game.Beatmaps updateQueue = new BeatmapUpdateQueue(api); } - protected override async Task Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive, CancellationToken cancellationToken = default) + protected override Task Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive, CancellationToken cancellationToken = default) { if (archive != null) beatmapSet.Beatmaps = createBeatmapDifficulties(archive); @@ -110,7 +110,7 @@ namespace osu.Game.Beatmaps validateOnlineIds(beatmapSet); - await updateQueue.UpdateAsync(beatmapSet, cancellationToken); + return updateQueue.UpdateAsync(beatmapSet, cancellationToken); } protected override void PreImport(BeatmapSetInfo beatmapSet) @@ -433,13 +433,13 @@ namespace osu.Game.Beatmaps this.api = api; } - public async Task UpdateAsync(BeatmapSetInfo beatmapSet, CancellationToken cancellationToken) + public Task UpdateAsync(BeatmapSetInfo beatmapSet, CancellationToken cancellationToken) { if (api?.State != APIState.Online) - return; + return Task.CompletedTask; LogForModel(beatmapSet, "Performing online lookups..."); - await Task.WhenAll(beatmapSet.Beatmaps.Select(b => UpdateAsync(beatmapSet, b, cancellationToken)).ToArray()); + return Task.WhenAll(beatmapSet.Beatmaps.Select(b => UpdateAsync(beatmapSet, b, cancellationToken)).ToArray()); } // todo: expose this when we need to do individual difficulty lookups. diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index d764601b32..0cf7816250 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.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; @@ -132,13 +132,13 @@ namespace osu.Game.Database /// This will post notifications tracking progress. /// /// One or more archive locations on disk. - public async Task Import(params string[] paths) + public Task Import(params string[] paths) { var notification = new ProgressNotification { State = ProgressNotificationState.Active }; PostNotification?.Invoke(notification); - await Import(notification, paths); + return Import(notification, paths); } protected async Task Import(ProgressNotification notification, params string[] paths) @@ -243,7 +243,7 @@ namespace osu.Game.Database /// /// The archive to be imported. /// An optional cancellation token. - public async Task Import(ArchiveReader archive, CancellationToken cancellationToken = default) + public Task Import(ArchiveReader archive, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); @@ -267,7 +267,7 @@ namespace osu.Game.Database return null; } - return await Import(model, archive, cancellationToken); + return Import(model, archive, cancellationToken); } /// @@ -548,24 +548,24 @@ namespace osu.Game.Database /// /// This is a temporary method and will likely be replaced by a full-fledged (and more correctly placed) migration process in the future. /// - public async Task ImportFromStableAsync() + public Task ImportFromStableAsync() { var stable = GetStableStorage?.Invoke(); if (stable == null) { Logger.Log("No osu!stable installation available!", LoggingTarget.Information, LogLevel.Error); - return; + return Task.CompletedTask; } if (!stable.ExistsDirectory(ImportFromStablePath)) { // This handles situations like when the user does not have a Skins folder Logger.Log($"No {ImportFromStablePath} folder available in osu!stable installation", LoggingTarget.Information, LogLevel.Error); - return; + return Task.CompletedTask; } - await Task.Run(async () => await Import(stable.GetDirectories(ImportFromStablePath).Select(f => stable.GetFullPath(f)).ToArray())); + return Task.Run(async () => await Import(stable.GetDirectories(ImportFromStablePath).Select(f => stable.GetFullPath(f)).ToArray())); } #endregion From 2a67944889c302fe69a87838f70d835c63b50740 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Jun 2019 17:10:55 +0900 Subject: [PATCH 1185/5608] Remove interlocked within a lock --- osu.Game/Database/ArchiveModelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 0cf7816250..1c17adf7b7 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -161,8 +161,8 @@ namespace osu.Game.Database lock (imported) { imported.Add(model); + current++; - Interlocked.Increment(ref current); notification.Text = $"Imported {current} of {paths.Length} {humanisedModelName}s"; notification.Progress = (float)current / paths.Length; } From d4deac48ee78e025f14bace79fc2388923a4eef9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Jun 2019 17:27:15 +0900 Subject: [PATCH 1186/5608] Improve model deletion notification text --- osu.Game/Database/ArchiveModelManager.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 54dbae9ddc..b5a9c70e47 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -392,7 +392,8 @@ namespace osu.Game.Database var notification = new ProgressNotification { Progress = 0, - CompletionText = $"Deleted all {typeof(TModel).Name.Replace("Info", "").ToLower()}s!", + Text = $"Preparing to delete all {humanisedModelName}s...", + CompletionText = $"Deleted all {humanisedModelName}s!", State = ProgressNotificationState.Active, }; @@ -409,7 +410,7 @@ namespace osu.Game.Database // user requested abort return; - notification.Text = $"Deleting ({++i} of {items.Count})"; + notification.Text = $"Deleting {humanisedModelName}s ({++i} of {items.Count})"; Delete(b); From f358fce9abe950fa0f60e69bea2776196ef64ccc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Jun 2019 18:04:57 +0900 Subject: [PATCH 1187/5608] Move activity (writable) bindable to APIAccess so it correctly transfers between users --- .../Visual/Online/TestSceneUserPanel.cs | 17 +++++++++++------ osu.Game/Online/API/APIAccess.cs | 8 ++++++++ osu.Game/Online/API/DummyAPIAccess.cs | 11 +++++++++++ osu.Game/Online/API/IAPIProvider.cs | 5 +++++ .../Settings/Sections/General/LoginSettings.cs | 6 ++---- osu.Game/Screens/OsuScreen.cs | 2 +- osu.Game/Users/User.cs | 2 +- osu.Game/Users/UserPanel.cs | 2 +- 8 files changed, 40 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index 30814ad9c7..54f06d6ad2 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Users; @@ -61,12 +62,16 @@ namespace osu.Game.Tests.Visual.Online [Test] public void UserActivitiesTests() { - AddStep("idle", () => { peppy.Activity.Value = null; }); - AddStep("spectating", () => { peppy.Activity.Value = new UserActivity.Spectating(); }); - AddStep("solo", () => { peppy.Activity.Value = new UserActivity.SoloGame(null, null); }); - AddStep("choosing", () => { peppy.Activity.Value = new UserActivity.ChoosingBeatmap(); }); - AddStep("editing", () => { peppy.Activity.Value = new UserActivity.Editing(null); }); - AddStep("modding", () => { peppy.Activity.Value = new UserActivity.Modding(); }); + Bindable activity = new Bindable(); + + peppy.Activity.BindTo(activity); + + AddStep("idle", () => { activity.Value = null; }); + AddStep("spectating", () => { activity.Value = new UserActivity.Spectating(); }); + AddStep("solo", () => { activity.Value = new UserActivity.SoloGame(null, null); }); + AddStep("choosing", () => { activity.Value = new UserActivity.ChoosingBeatmap(); }); + AddStep("editing", () => { activity.Value = new UserActivity.Editing(null); }); + AddStep("modding", () => { activity.Value = new UserActivity.Modding(); }); } } } diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 343d6a67b7..12b38fab1e 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -37,6 +37,8 @@ namespace osu.Game.Online.API public Bindable LocalUser { get; } = new Bindable(createGuestUser()); + public Bindable Activity { get; } = new Bindable(); + protected bool HasLogin => authentication.Token.Value != null || (!string.IsNullOrEmpty(ProvidedUsername) && !string.IsNullOrEmpty(password)); private readonly CancellationTokenSource cancellationToken = new CancellationTokenSource(); @@ -55,6 +57,12 @@ namespace osu.Game.Online.API authentication.TokenString = config.Get(OsuSetting.Token); authentication.Token.ValueChanged += onTokenChanged; + LocalUser.BindValueChanged(u => + { + u.OldValue?.Activity.UnbindFrom(Activity); + u.NewValue.Activity.BindTo(Activity); + }, true); + var thread = new Thread(run) { Name = "APIAccess", diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 99fde10309..6c04c77dc0 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -17,6 +17,8 @@ namespace osu.Game.Online.API Id = 1001, }); + public Bindable Activity { get; } = new Bindable(); + public bool IsLoggedIn => true; public string ProvidedUsername => LocalUser.Value.Username; @@ -41,6 +43,15 @@ namespace osu.Game.Online.API } } + public DummyAPIAccess() + { + LocalUser.BindValueChanged(u => + { + u.OldValue?.Activity.UnbindFrom(Activity); + u.NewValue.Activity.BindTo(Activity); + }, true); + } + public virtual void Queue(APIRequest request) { } diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index 7c1f850943..0cd41aee26 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.cs @@ -13,6 +13,11 @@ namespace osu.Game.Online.API /// Bindable LocalUser { get; } + /// + /// The current user's activity. + /// + Bindable Activity { get; } + /// /// Returns whether the local user is logged in. /// diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 223c2aaf13..1454b6592d 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -156,7 +156,7 @@ namespace osu.Game.Overlays.Settings.Sections.General panel.Status.BindTo(api.LocalUser.Value.Status); panel.Activity.BindTo(api.LocalUser.Value.Activity); - dropdown.Current.ValueChanged += action => + dropdown.Current.BindValueChanged(action => { switch (action.NewValue) { @@ -179,9 +179,7 @@ namespace osu.Game.Overlays.Settings.Sections.General api.Logout(); break; } - }; - dropdown.Current.TriggerChange(); - + }, true); break; } diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index fe53ad17c3..e2aeb41de1 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -193,7 +193,7 @@ namespace osu.Game.Screens private void updateActivity() { if (api != null) - api.LocalUser.Value.Activity.Value = activity; + api.Activity.Value = activity; } /// diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index cf67af7bb8..c3ecd62e10 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -25,7 +25,7 @@ namespace osu.Game.Users public Bindable Status = new Bindable(); - public Bindable Activity = new Bindable(); + public IBindable Activity = new Bindable(); //public Team Team; diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 04f5a0a3fb..833c62013b 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -42,7 +42,7 @@ namespace osu.Game.Users public readonly Bindable Status = new Bindable(); - public readonly Bindable Activity = new Bindable(); + public readonly IBindable Activity = new Bindable(); public new Action Action; From 9faba94978de1db4008a2124c90f909117e4e93a Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 12 Jun 2019 12:22:52 +0200 Subject: [PATCH 1188/5608] Fix references to UserActivities --- osu.Desktop/DiscordRichPresenceClient.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/DiscordRichPresenceClient.cs b/osu.Desktop/DiscordRichPresenceClient.cs index 4a2f882e2b..15d5770041 100644 --- a/osu.Desktop/DiscordRichPresenceClient.cs +++ b/osu.Desktop/DiscordRichPresenceClient.cs @@ -60,12 +60,12 @@ namespace osu.Desktop switch (a) { - case UserActivitySoloGame game: + case UserActivity.SoloGame game: presence.State = $"{game.Beatmap.Metadata.Artist} - {game.Beatmap.Metadata.Title} [{game.Beatmap.Version}]"; setPresenceGamemode(game.Ruleset, presence); break; - case UserActivityEditing editing: + case UserActivity.Editing editing: presence.State = $"{editing.Beatmap.Metadata.Artist} - {editing.Beatmap.Metadata.Title} " + (!string.IsNullOrEmpty(editing.Beatmap.Version) ? $"[{editing.Beatmap.Version}]" : ""); presence.Assets.SmallImageKey = "edit"; presence.Assets.SmallImageText = "editing"; From 0f000fcc1402fababafc3df53eacffff17b918e8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Jun 2019 19:58:26 +0900 Subject: [PATCH 1189/5608] Fix abysmal load performance when showing the social overlay --- osu.Game/Users/UserCoverBackground.cs | 52 +++++++++++++++++---------- osu.Game/Users/UserPanel.cs | 11 +++--- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/osu.Game/Users/UserCoverBackground.cs b/osu.Game/Users/UserCoverBackground.cs index dbc132995a..e583acac9f 100644 --- a/osu.Game/Users/UserCoverBackground.cs +++ b/osu.Game/Users/UserCoverBackground.cs @@ -21,31 +21,45 @@ namespace osu.Game.Users set => Model = value; } - [Resolved] - private LargeTextureStore textures { get; set; } + protected override Drawable CreateDrawable(User user) => new Cover(user); - protected override Drawable CreateDrawable(User user) + private class Cover : CompositeDrawable { - if (user == null) + private readonly User user; + + public Cover(User user) { - return new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.1f), Color4.Black.Opacity(0.75f)) - }; + this.user = user; + + RelativeSizeAxes = Axes.Both; } - else + + [BackgroundDependencyLoader] + private void load(LargeTextureStore textures) { - var sprite = new Sprite + if (user == null) { - RelativeSizeAxes = Axes.Both, - Texture = textures.Get(user.CoverUrl), - FillMode = FillMode.Fill, - Anchor = Anchor.Centre, - Origin = Anchor.Centre - }; - sprite.OnLoadComplete += d => d.FadeInFromZero(400); - return sprite; + InternalChild = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.1f), Color4.Black.Opacity(0.75f)) + }; + } + else + InternalChild = new Sprite + { + RelativeSizeAxes = Axes.Both, + Texture = textures.Get(user.CoverUrl), + FillMode = FillMode.Fill, + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + this.FadeInFromZero(400); } } } diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 47571b673d..3f6fce98f7 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -61,8 +61,6 @@ namespace osu.Game.Users FillFlowContainer infoContainer; - UserCoverBackground coverBackground; - AddInternal(content = new Container { RelativeSizeAxes = Axes.Both, @@ -77,13 +75,16 @@ namespace osu.Game.Users Children = new Drawable[] { - new DelayedLoadWrapper(coverBackground = new UserCoverBackground + new DelayedLoadUnloadWrapper(() => new UserCoverBackground { RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, User = user, - }, 300) { RelativeSizeAxes = Axes.Both }, + }, 300, 5000) + { + RelativeSizeAxes = Axes.Both, + }, new Box { RelativeSizeAxes = Axes.Both, @@ -184,8 +185,6 @@ namespace osu.Game.Users } }); - coverBackground.OnLoadComplete += d => d.FadeInFromZero(400, Easing.Out); - if (user.IsSupporter) { infoContainer.Add(new SupporterIcon From 4275f70cf453aeb3799d934fe9bfd67c81040b8f Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 12 Jun 2019 13:14:01 +0200 Subject: [PATCH 1190/5608] Fix CI inspections. --- osu.Desktop/DiscordRichPresenceClient.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/DiscordRichPresenceClient.cs b/osu.Desktop/DiscordRichPresenceClient.cs index 15d5770041..81ab995b41 100644 --- a/osu.Desktop/DiscordRichPresenceClient.cs +++ b/osu.Desktop/DiscordRichPresenceClient.cs @@ -60,12 +60,12 @@ namespace osu.Desktop switch (a) { - case UserActivity.SoloGame game: + case SoloGame game: presence.State = $"{game.Beatmap.Metadata.Artist} - {game.Beatmap.Metadata.Title} [{game.Beatmap.Version}]"; setPresenceGamemode(game.Ruleset, presence); break; - case UserActivity.Editing editing: + case Editing editing: presence.State = $"{editing.Beatmap.Metadata.Artist} - {editing.Beatmap.Metadata.Title} " + (!string.IsNullOrEmpty(editing.Beatmap.Version) ? $"[{editing.Beatmap.Version}]" : ""); presence.Assets.SmallImageKey = "edit"; presence.Assets.SmallImageText = "editing"; From a17d480f51b099ed88994bce1ebf5e613c0a6881 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Jun 2019 20:41:02 +0900 Subject: [PATCH 1191/5608] Use "beatmap" as the model name --- osu.Game/Beatmaps/BeatmapManager.cs | 2 ++ osu.Game/Database/ArchiveModelManager.cs | 14 +++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index d90657bff5..3734c8d05c 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -327,6 +327,8 @@ namespace osu.Game.Beatmaps /// Results from the provided query. public IQueryable QueryBeatmaps(Expression> query) => beatmaps.Beatmaps.AsNoTracking().Where(query); + protected override string HumanisedModelName => "beatmap"; + protected override BeatmapSetInfo CreateModel(ArchiveReader reader) { // let's make sure there are actually .osu files to import. diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 20919f0899..1c8e722589 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -163,7 +163,7 @@ namespace osu.Game.Database imported.Add(model); current++; - notification.Text = $"Imported {current} of {paths.Length} {humanisedModelName}s"; + notification.Text = $"Imported {current} of {paths.Length} {HumanisedModelName}s"; notification.Progress = (float)current / paths.Length; } } @@ -186,7 +186,7 @@ namespace osu.Game.Database { notification.CompletionText = imported.Count == 1 ? $"Imported {imported.First()}!" - : $"Imported {current} {humanisedModelName}s!"; + : $"Imported {current} {HumanisedModelName}s!"; if (imported.Count > 0 && PresentImport != null) { @@ -344,7 +344,7 @@ namespace osu.Game.Database if (CanUndelete(existing, item)) { Undelete(existing); - LogForModel(item, $"Found existing {humanisedModelName} for {item} (ID {existing.ID}) – skipping import."); + LogForModel(item, $"Found existing {HumanisedModelName} for {item} (ID {existing.ID}) – skipping import."); handleEvent(() => ItemAdded?.Invoke(existing, true)); // existing item will be used; rollback new import and exit early. @@ -424,8 +424,8 @@ namespace osu.Game.Database var notification = new ProgressNotification { Progress = 0, - Text = $"Preparing to delete all {humanisedModelName}s...", - CompletionText = $"Deleted all {humanisedModelName}s!", + Text = $"Preparing to delete all {HumanisedModelName}s...", + CompletionText = $"Deleted all {HumanisedModelName}s!", State = ProgressNotificationState.Active, }; @@ -442,7 +442,7 @@ namespace osu.Game.Database // user requested abort return; - notification.Text = $"Deleting {humanisedModelName}s ({++i} of {items.Count})"; + notification.Text = $"Deleting {HumanisedModelName}s ({++i} of {items.Count})"; Delete(b); @@ -614,7 +614,7 @@ namespace osu.Game.Database private DbSet queryModel() => ContextFactory.Get().Set(); - private string humanisedModelName => $"{typeof(TModel).Name.Replace("Info", "").ToLower()}"; + protected virtual string HumanisedModelName => $"{typeof(TModel).Name.Replace("Info", "").ToLower()}"; /// /// Creates an from a valid storage path. From 03c98ff57b7f8dcb1da9e96ed476ba6196031ad5 Mon Sep 17 00:00:00 2001 From: Ludde <48018938+yousef157@users.noreply.github.com> Date: Wed, 12 Jun 2019 15:55:06 +0400 Subject: [PATCH 1192/5608] Update TestFlight --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 04f133fd56..9c63d31e15 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ If you are not interested in developing the game, you can consume our [binary re | ------------- | ------------- | - **Linux** users are recommended to self-compile until we have official deployment in place. -- **iOS** users can join the [TestFlight beta program](https://t.co/xQJmHkfC18) (note that due to high demand this is regularly full). +- **iOS** users can join the [TestFlight beta program](https://t.co/PasE1zrHhw) (new link added, please only install if you use it on a regular daily basis). - **Android** users can self-compile, and expect a public beta soon. If your platform is not listed above, there is still a chance you can manually build it by following the instructions below. From 9cd5519da3d2244b6a250d676a25fd951578197d Mon Sep 17 00:00:00 2001 From: naoey Date: Wed, 12 Jun 2019 18:35:34 +0530 Subject: [PATCH 1193/5608] Remove unused delegate, use model name in notifications, add more xmldoc - Applies a `class` constraint to the generic type in `IModelManager` - Add xmldoc --- osu.Game/Beatmaps/BeatmapManager.cs | 5 +---- osu.Game/Database/ArchiveModelManager.cs | 2 -- osu.Game/Database/DownloadableArchiveModelManager.cs | 4 ++-- osu.Game/Database/IModelDownloader.cs | 8 ++++++-- osu.Game/Database/IModelManager.cs | 5 +++++ 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index c2adf1ac5b..2cb7e8b901 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -55,8 +55,6 @@ namespace osu.Game.Beatmaps private readonly BeatmapStore beatmaps; - private readonly IAPIProvider api; - private readonly AudioManager audioManager; private readonly GameHost host; @@ -68,7 +66,6 @@ namespace osu.Game.Beatmaps : base(storage, contextFactory, api, new BeatmapStore(contextFactory), host) { this.rulesets = rulesets; - this.api = api; this.audioManager = audioManager; this.host = host; @@ -80,7 +77,7 @@ namespace osu.Game.Beatmaps updateQueue = new BeatmapUpdateQueue(api); } - + protected override ArchiveDownloadRequest CreateDownloadRequest(BeatmapSetInfo set, object[] options) => new DownloadBeatmapSetRequest(set, (options?.FirstOrDefault() as bool?) ?? false); protected override Task Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive, CancellationToken cancellationToken = default) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 49e0330c21..434e5b9525 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -35,8 +35,6 @@ namespace osu.Game.Database where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() { - public delegate void ItemAddedDelegate(TModel model, bool existing); - /// /// Set an endpoint for notifications to be posted to. /// diff --git a/osu.Game/Database/DownloadableArchiveModelManager.cs b/osu.Game/Database/DownloadableArchiveModelManager.cs index 519b22b912..4a21673d2b 100644 --- a/osu.Game/Database/DownloadableArchiveModelManager.cs +++ b/osu.Game/Database/DownloadableArchiveModelManager.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 Humanizer; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Online.API; @@ -112,8 +113,7 @@ namespace osu.Game.Database if (error is OperationCanceledException) return; notification.State = ProgressNotificationState.Cancelled; - // TODO: maybe implement a Name for every model that we can use in this message? - Logger.Error(error, "Download failed!"); + Logger.Error(error, $"{HumanisedModelName.Titleize()} download failed!"); currentDownloads.Remove(request); }; diff --git a/osu.Game/Database/IModelDownloader.cs b/osu.Game/Database/IModelDownloader.cs index 83427bdc17..42c64ba67b 100644 --- a/osu.Game/Database/IModelDownloader.cs +++ b/osu.Game/Database/IModelDownloader.cs @@ -6,6 +6,10 @@ using System; namespace osu.Game.Database { + /// + /// Represents a that can download new models from an external source. + /// + /// The model type. public interface IModelDownloader : IModelManager where TModel : class { @@ -23,7 +27,7 @@ namespace osu.Game.Database /// /// Downloads a . - /// This will post notifications tracking progress. + /// This may post notifications tracking progress. /// /// The to be downloaded. /// Whether downloading can happen. @@ -31,7 +35,7 @@ namespace osu.Game.Database /// /// Downloads a with optional parameters for the download request. - /// This will post notifications tracking progress. + /// This may post notifications tracking progress. /// /// The to be downloaded. /// Optional parameters to be used for creating the download request. diff --git a/osu.Game/Database/IModelManager.cs b/osu.Game/Database/IModelManager.cs index ee78df3db4..cb80ce49b2 100644 --- a/osu.Game/Database/IModelManager.cs +++ b/osu.Game/Database/IModelManager.cs @@ -5,7 +5,12 @@ using System; namespace osu.Game.Database { + /// + /// Represents a model manager that publishes events when s are added or removed. + /// + /// The model type. public interface IModelManager + where TModel : class { event Action ItemAdded; From efd9766fb301121f46776b1d4a64b7ce849b53c1 Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Wed, 12 Jun 2019 17:37:34 +0300 Subject: [PATCH 1194/5608] Make Header accessible by BeatmapSetOverlay --- osu.Game/Overlays/BeatmapSetOverlay.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 6bd2e1b72e..f0525aa843 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays public const float X_PADDING = 40; public const float RIGHT_WIDTH = 275; - private readonly Header header; + public readonly Header Header; private RulesetStore rulesets; @@ -60,7 +60,7 @@ namespace osu.Game.Overlays Direction = FillDirection.Vertical, Children = new Drawable[] { - header = new Header(), + Header = new Header(), info = new Info(), scores = new ScoresContainer(), }, @@ -68,10 +68,10 @@ namespace osu.Game.Overlays }, }; - header.BeatmapSet.BindTo(beatmapSet); + Header.BeatmapSet.BindTo(beatmapSet); info.BeatmapSet.BindTo(beatmapSet); - header.Picker.Beatmap.ValueChanged += b => + Header.Picker.Beatmap.ValueChanged += b => { info.Beatmap = b.NewValue; scores.Beatmap = b.NewValue; @@ -103,7 +103,7 @@ namespace osu.Game.Overlays req.Success += res => { beatmapSet.Value = res.ToBeatmapSet(rulesets); - header.Picker.Beatmap.Value = header.BeatmapSet.Value.Beatmaps.First(b => b.OnlineBeatmapID == beatmapId); + Header.Picker.Beatmap.Value = Header.BeatmapSet.Value.Beatmaps.First(b => b.OnlineBeatmapID == beatmapId); }; API.Queue(req); Show(); From d868280b2dab9a2acd16065ad9d4044bd987ece0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Jun 2019 23:51:01 +0900 Subject: [PATCH 1195/5608] Update outdated game resources in iOS project --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 2c25498b89..5e151f916b 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -104,7 +104,7 @@ - + From 50999c36771a620f2a76d8327e54feea4ffe001e Mon Sep 17 00:00:00 2001 From: Ludde <48018938+yousef157@users.noreply.github.com> Date: Wed, 12 Jun 2019 18:53:39 +0400 Subject: [PATCH 1196/5608] revert change in paranthesses --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c63d31e15..0df99f7d6b 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ If you are not interested in developing the game, you can consume our [binary re | ------------- | ------------- | - **Linux** users are recommended to self-compile until we have official deployment in place. -- **iOS** users can join the [TestFlight beta program](https://t.co/PasE1zrHhw) (new link added, please only install if you use it on a regular daily basis). +- **iOS** users can join the [TestFlight beta program](https://t.co/PasE1zrHhw) (note that due to high demand this is regularly full). - **Android** users can self-compile, and expect a public beta soon. If your platform is not listed above, there is still a chance you can manually build it by following the instructions below. From a069a3029e995ad200694abd1588c2053d59ffea Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Wed, 12 Jun 2019 18:07:57 +0300 Subject: [PATCH 1197/5608] Make DownloadButton accessible by DirectPanel --- osu.Game/Overlays/Direct/DirectGridPanel.cs | 4 +++- osu.Game/Overlays/Direct/DirectListPanel.cs | 4 +++- osu.Game/Overlays/Direct/DirectPanel.cs | 1 + osu.Game/Overlays/Direct/DownloadButton.cs | 7 ++++++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index 5756a4593d..9e7aa5372b 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -25,9 +25,11 @@ namespace osu.Game.Overlays.Direct private const float vertical_padding = 5; private FillFlowContainer bottomPanel, statusContainer; + private DownloadButton downloadButton; private PlayButton playButton; private Box progressBar; + public override DownloadButton DownloadButton => downloadButton; protected override PlayButton PlayButton => playButton; protected override Box PreviewBar => progressBar; @@ -155,7 +157,7 @@ namespace osu.Game.Overlays.Direct }, }, }, - new DownloadButton(SetInfo) + downloadButton = new DownloadButton(SetInfo) { Size = new Vector2(50, 30), Margin = new MarginPadding(horizontal_padding), diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index b731e95d54..076fed19bd 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -27,11 +27,13 @@ namespace osu.Game.Overlays.Direct private const float height = 70; private FillFlowContainer statusContainer; + private DownloadButton downloadButton; private PlayButton playButton; private Box progressBar; protected override bool FadePlayButton => false; + public override DownloadButton DownloadButton => downloadButton; protected override PlayButton PlayButton => playButton; protected override Box PreviewBar => progressBar; @@ -149,7 +151,7 @@ namespace osu.Game.Overlays.Direct Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, AutoSizeAxes = Axes.Both, - Child = new DownloadButton(SetInfo) + Child = downloadButton = new DownloadButton(SetInfo) { Size = new Vector2(height - vertical_padding * 3), Margin = new MarginPadding { Left = vertical_padding * 2, Right = vertical_padding }, diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index f413dc3771..c9fe4aaa05 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -34,6 +34,7 @@ namespace osu.Game.Overlays.Direct public PreviewTrack Preview => PlayButton.Preview; public Bindable PreviewPlaying => PlayButton.Playing; + public abstract DownloadButton DownloadButton { get; } protected abstract PlayButton PlayButton { get; } protected abstract Box PreviewBar { get; } diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 33e09e95aa..10e6f8a6e1 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; @@ -26,6 +27,8 @@ namespace osu.Game.Overlays.Direct private readonly OsuAnimatedButton button; + public readonly BindableBool Enabled = new BindableBool(true); + public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) : base(beatmapSet) { @@ -62,6 +65,8 @@ namespace osu.Game.Overlays.Direct } } }; + + Enabled.BindTo(button.Enabled); } protected override void LoadComplete() @@ -79,7 +84,7 @@ namespace osu.Game.Overlays.Direct if (BeatmapSet.Value.OnlineInfo.Availability?.DownloadDisabled ?? false) { - button.Enabled.Value = false; + Enabled.Value = false; button.TooltipText = "Unavailable"; return; } From c5c6f6b9e05ee517fc6483344d3125d675ba6ee4 Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Wed, 12 Jun 2019 18:36:47 +0300 Subject: [PATCH 1198/5608] Allow for not refetching in ShowBeatmapSet (will be used for tests) --- osu.Game/Overlays/BeatmapSetOverlay.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index f0525aa843..a44a7fa45f 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -118,10 +118,17 @@ namespace osu.Game.Overlays Show(); } - public void ShowBeatmapSet(BeatmapSetInfo set) + public void ShowBeatmapSet(BeatmapSetInfo set, bool refetch = true) { // Re-fetching is the correct way forward. - FetchAndShowBeatmapSet(set?.OnlineBeatmapSetID ?? 0); + if (refetch) + FetchAndShowBeatmapSet(set?.OnlineBeatmapSetID ?? 0); + else + { + beatmapSet.Value = set; + Show(); + } + scroll.ScrollTo(0); } } From 744f32ab35dc7a397a4ebb8954152c80bdb3b6f3 Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Wed, 12 Jun 2019 19:11:05 +0300 Subject: [PATCH 1199/5608] Fix little bug --- osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs b/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs index c111861206..b9c0a1af39 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs @@ -26,6 +26,7 @@ namespace osu.Game.Overlays.BeatmapSet beatmapSet = value; + removeLinks(); if (beatmapSet?.OnlineInfo.Availability != null) { Header?.ResizeHeightTo(450, 500); @@ -95,11 +96,6 @@ namespace osu.Game.Overlays.BeatmapSet base.Show(); } - public override void Hide() - { - link.RemoveAll(x => true); - - base.Hide(); - } + private void removeLinks() => link?.RemoveAll(x => true); } } From 7ba676ad31328fc63353d98036d471498f983afe Mon Sep 17 00:00:00 2001 From: naoey Date: Wed, 12 Jun 2019 21:56:36 +0530 Subject: [PATCH 1200/5608] Rename Info to Model --- osu.Game/Database/DownloadableArchiveModelManager.cs | 4 ++-- osu.Game/Online/API/ArchiveDownloadRequest.cs | 4 ++-- osu.Game/Overlays/Direct/DownloadTrackingComposite.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Database/DownloadableArchiveModelManager.cs b/osu.Game/Database/DownloadableArchiveModelManager.cs index 4a21673d2b..0735452ce3 100644 --- a/osu.Game/Database/DownloadableArchiveModelManager.cs +++ b/osu.Game/Database/DownloadableArchiveModelManager.cs @@ -79,7 +79,7 @@ namespace osu.Game.Database /// Whether the exists locally. public virtual bool IsAvailableLocally(TModel model) => modelStore.ConsumableItems.Any(m => m.Equals(model) && !m.DeletePending); - public ArchiveDownloadRequest GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Info.Equals(model)); + public ArchiveDownloadRequest GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Model.Equals(model)); private bool canDownload(TModel model) => GetExistingDownload(model) == null && api != null; @@ -87,7 +87,7 @@ namespace osu.Game.Database { DownloadNotification notification = new DownloadNotification { - Text = $"Downloading {request.Info}", + Text = $"Downloading {request.Model}", }; request.DownloadProgressed += progress => diff --git a/osu.Game/Online/API/ArchiveDownloadRequest.cs b/osu.Game/Online/API/ArchiveDownloadRequest.cs index 01f066694d..f1966aeb2b 100644 --- a/osu.Game/Online/API/ArchiveDownloadRequest.cs +++ b/osu.Game/Online/API/ArchiveDownloadRequest.cs @@ -8,7 +8,7 @@ namespace osu.Game.Online.API public abstract class ArchiveDownloadRequest : APIDownloadRequest where TModel : class { - public readonly TModel Info; + public readonly TModel Model; public float Progress; @@ -16,7 +16,7 @@ namespace osu.Game.Online.API protected ArchiveDownloadRequest(TModel model) { - Info = model; + Model = model; Progressed += (current, total) => DownloadProgressed?.Invoke(Progress = (float)current / total); } diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs index 9d0266c00e..494b18307e 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs +++ b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs @@ -49,7 +49,7 @@ namespace osu.Game.Overlays.Direct beatmaps.DownloadBegan += download => { - if (download.Info.OnlineBeatmapSetID == BeatmapSet.Value?.OnlineBeatmapSetID) + if (download.Model.OnlineBeatmapSetID == BeatmapSet.Value?.OnlineBeatmapSetID) attachDownload(download); }; From 1a50544c9465ec75278420b8d0c22666612be8c1 Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Wed, 12 Jun 2019 20:42:52 +0300 Subject: [PATCH 1201/5608] Add tests for undownloadable / parts-removed beatmapsets --- .../Online/TestSceneBeatmapSetOverlay.cs | 306 +++++++++++++++++- .../Visual/Online/TestSceneDirectPanel.cs | 43 ++- .../BeatmapSet/BeatmapNotAvailable.cs | 1 + 3 files changed, 342 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 5910da7b88..5e7ccc7ed4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -39,6 +39,7 @@ namespace osu.Game.Tests.Visual.Online typeof(Info), typeof(PreviewButton), typeof(SuccessRate), + typeof(BeatmapNotAvailable), }; public TestSceneBeatmapSetOverlay() @@ -49,6 +50,7 @@ namespace osu.Game.Tests.Visual.Online [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { + var osu = rulesets.GetRuleset(0); var mania = rulesets.GetRuleset(3); var taiko = rulesets.GetRuleset(1); @@ -225,7 +227,7 @@ namespace osu.Game.Tests.Visual.Online }, }, }, - }); + }, false); }); AddStep(@"show second", () => @@ -396,9 +398,309 @@ namespace osu.Game.Tests.Visual.Online }, }, }, - }); + }, false); }); + AddStep(@"show parts-removed", () => + { + overlay.ShowBeatmapSet(new BeatmapSetInfo + { + Metadata = new BeatmapMetadata + { + Title = @"Sakura Kagetsu", + Artist = @"AKITO", + Source = @"DJMAX", + Tags = @"J-Trance Pasonia", + Author = new User + { + Username = @"Kharl", + Id = 452, + }, + }, + OnlineInfo = new BeatmapSetOnlineInfo + { + Availability = new BeatmapSetOnlineAvailability + { + DownloadDisabled = false, + ExternalLink = @"https://gist.githubusercontent.com/peppy/079dc3f77e316f9cd40077d411319a72/raw", + }, + Preview = @"https://b.ppy.sh/preview/119.mp3", + PlayCount = 626927, + FavouriteCount = 157, + Submitted = new DateTime(2007, 10, 24), + Ranked = new DateTime(2008, 4, 21), + Status = BeatmapSetOnlineStatus.Ranked, + BPM = 138, + Covers = new BeatmapSetOnlineCovers + { + Cover = @"https://assets.ppy.sh/beatmaps/119/covers/cover.jpg?1539847784", + }, + }, + Beatmaps = new List + { + new BeatmapInfo + { + StarDifficulty = 1.51, + Version = "Easy", + Ruleset = osu, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 4, + DrainRate = 2, + OverallDifficulty = 1, + ApproachRate = 1, + }, + OnlineInfo = new BeatmapOnlineInfo + { + Length = 126000, + CircleCount = 371, + SliderCount = 35, + PlayCount = 84498, + PassCount = 37482, + }, + Metrics = new BeatmapMetrics + { + Ratings = Enumerable.Range(0, 11), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + }, + }, + new BeatmapInfo + { + StarDifficulty = 2.23, + Version = "Normal", + Ruleset = osu, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 5, + DrainRate = 4, + OverallDifficulty = 3, + ApproachRate = 3, + }, + OnlineInfo = new BeatmapOnlineInfo + { + Length = 126000, + CircleCount = 98, + SliderCount = 28, + PlayCount = 86427, + PassCount = 23273, + }, + Metrics = new BeatmapMetrics + { + Ratings = Enumerable.Range(0, 11), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + }, + }, + new BeatmapInfo + { + StarDifficulty = 2.83, + Version = "Hard", + Ruleset = osu, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 6, + DrainRate = 6, + OverallDifficulty = 6, + ApproachRate = 6, + }, + OnlineInfo = new BeatmapOnlineInfo + { + Length = 126000, + CircleCount = 139, + SliderCount = 37, + PlayCount = 206523, + PassCount = 44366, + }, + Metrics = new BeatmapMetrics + { + Ratings = Enumerable.Range(0, 11), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + }, + }, + new BeatmapInfo + { + StarDifficulty = 4.26, + Version = "Pasonia's Insane", + Ruleset = osu, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 6, + DrainRate = 6, + OverallDifficulty = 6, + ApproachRate = 6, + }, + OnlineInfo = new BeatmapOnlineInfo + { + Length = 126000, + CircleCount = 371, + SliderCount = 35, + PlayCount = 249479, + PassCount = 14042, + }, + Metrics = new BeatmapMetrics + { + Ratings = Enumerable.Range(0, 11), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + }, + }, + }, + }, false); + }); + + AddStep(@"show undownloadable", () => + { + overlay.ShowBeatmapSet(new BeatmapSetInfo + { + Metadata = new BeatmapMetadata + { + Title = @"China Express", + Artist = @"Ryu*", + Source = @"REFLEC BEAT", + Tags = @"konami bemani lincle link iidx iidx18 iidx19 resort anthem plus la cataline mmzz", + Author = new User + { + Username = @"yeahyeahyeahhh", + Id = 58042, + }, + }, + OnlineInfo = new BeatmapSetOnlineInfo + { + Availability = new BeatmapSetOnlineAvailability + { + DownloadDisabled = true, + ExternalLink = @"https://gist.githubusercontent.com/peppy/99e6959772083cdfde8a/raw", + }, + Preview = @"https://b.ppy.sh/preview/53853.mp3", + PlayCount = 436213, + FavouriteCount = 105, + Submitted = new DateTime(2012, 7, 1), + Ranked = new DateTime(2012, 7, 18), + Status = BeatmapSetOnlineStatus.Ranked, + BPM = 171, + Covers = new BeatmapSetOnlineCovers + { + Cover = @"https://assets.ppy.sh/beatmaps/53853/covers/cover.jpg?1456498562", + }, + }, + Beatmaps = new List + { + new BeatmapInfo + { + StarDifficulty = 1.85, + Version = "Easy", + Ruleset = osu, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 3, + DrainRate = 2, + OverallDifficulty = 2, + ApproachRate = 3, + }, + OnlineInfo = new BeatmapOnlineInfo + { + Length = 95000, + CircleCount = 49, + SliderCount = 60, + PlayCount = 20308, + PassCount = 10233, + }, + Metrics = new BeatmapMetrics + { + Ratings = Enumerable.Range(0, 11), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + }, + }, + new BeatmapInfo + { + StarDifficulty = 2.36, + Version = "Normal", + Ruleset = osu, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 3, + DrainRate = 2, + OverallDifficulty = 2, + ApproachRate = 5, + }, + OnlineInfo = new BeatmapOnlineInfo + { + Length = 96000, + CircleCount = 86, + SliderCount = 67, + PlayCount = 54015, + PassCount = 25603, + }, + Metrics = new BeatmapMetrics + { + Ratings = Enumerable.Range(0, 11), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + }, + }, + new BeatmapInfo + { + StarDifficulty = 4.42, + Version = "Hyper", + Ruleset = osu, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 4, + DrainRate = 7, + OverallDifficulty = 6, + ApproachRate = 8, + }, + OnlineInfo = new BeatmapOnlineInfo + { + Length = 96000, + CircleCount = 215, + SliderCount = 120, + PlayCount = 111400, + PassCount = 12583, + }, + Metrics = new BeatmapMetrics + { + Ratings = Enumerable.Range(0, 11), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + }, + }, + new BeatmapInfo + { + StarDifficulty = 5.05, + Version = "Another", + Ruleset = osu, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 4, + DrainRate = 7, + OverallDifficulty = 9, + ApproachRate = 9, + }, + OnlineInfo = new BeatmapOnlineInfo + { + Length = 96000, + CircleCount = 250, + SliderCount = 75, + PlayCount = 228253, + PassCount = 53037, + }, + Metrics = new BeatmapMetrics + { + Ratings = Enumerable.Range(0, 11), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + }, + }, + }, + }, false); + }); + + AddAssert(@"is download button removed", () => overlay.Header.DownloadButtonsContainer.Count == 0); + AddStep(@"hide", overlay.Hide); AddStep(@"show without reload", overlay.Show); } diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs index 8b67892fbb..a2767611ac 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs @@ -6,7 +6,9 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; using osu.Game.Overlays.Direct; +using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osuTK; @@ -21,12 +23,34 @@ namespace osu.Game.Tests.Visual.Online typeof(IconPill) }; + private BeatmapSetInfo getBeatmapSet(RulesetInfo ruleset, bool downloadable) + { + var beatmap = CreateWorkingBeatmap(ruleset).BeatmapSetInfo; + beatmap.OnlineInfo.HasVideo = true; + beatmap.OnlineInfo.HasStoryboard = true; + + beatmap.OnlineInfo.Availability = new BeatmapSetOnlineAvailability + { + DownloadDisabled = !downloadable, + ExternalLink = "http://localhost", + }; + + return beatmap; + } + [BackgroundDependencyLoader] private void load() { - var beatmap = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); - beatmap.BeatmapSetInfo.OnlineInfo.HasVideo = true; - beatmap.BeatmapSetInfo.OnlineInfo.HasStoryboard = true; + var ruleset = new OsuRuleset().RulesetInfo; + + var normal = CreateWorkingBeatmap(ruleset).BeatmapSetInfo; + normal.OnlineInfo.HasVideo = true; + normal.OnlineInfo.HasStoryboard = true; + + var downloadable = getBeatmapSet(ruleset, true); + var undownloadable = getBeatmapSet(ruleset, false); + + DirectPanel undownloadableGridPanel, undownloadableListPanel; Child = new FillFlowContainer { @@ -37,10 +61,17 @@ namespace osu.Game.Tests.Visual.Online Spacing = new Vector2(0, 20), Children = new Drawable[] { - new DirectGridPanel(beatmap.BeatmapSetInfo), - new DirectListPanel(beatmap.BeatmapSetInfo) - } + new DirectGridPanel(normal), + new DirectGridPanel(downloadable), + undownloadableGridPanel = new DirectGridPanel(undownloadable), + new DirectListPanel(normal), + new DirectListPanel(downloadable), + undownloadableListPanel = new DirectListPanel(undownloadable), + }, }; + + AddAssert("is download button disabled on last grid panel", () => !undownloadableGridPanel.DownloadButton.Enabled.Value); + AddAssert("is download button disabled on last list panel", () => !undownloadableListPanel.DownloadButton.Enabled.Value); } } } diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs b/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs index b9c0a1af39..31ed0d9396 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs @@ -27,6 +27,7 @@ namespace osu.Game.Overlays.BeatmapSet beatmapSet = value; removeLinks(); + if (beatmapSet?.OnlineInfo.Availability != null) { Header?.ResizeHeightTo(450, 500); From 3150b5cfb42d9c33960606698bf3ccdf824a11f9 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Wed, 12 Jun 2019 20:51:21 +0300 Subject: [PATCH 1202/5608] Naming adjustments --- osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs | 2 +- .../UserInterface/TestSceneToolbarRulesetSelector.cs | 2 +- osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs | 2 +- ...lbarRulesetButton.cs => ToolbarRulesetTabButton.cs} | 10 +++++----- 4 files changed, 8 insertions(+), 8 deletions(-) rename osu.Game/Overlays/Toolbar/{ToolbarRulesetButton.cs => ToolbarRulesetTabButton.cs} (88%) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index 0df6605cdd..f24589ed35 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.Menus { typeof(ToolbarButton), typeof(ToolbarRulesetSelector), - typeof(ToolbarRulesetButton), + typeof(ToolbarRulesetTabButton), typeof(ToolbarNotificationButton), }; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs index 7d0491aa60..3e61da73a5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.UserInterface public override IReadOnlyList RequiredTypes => new[] { typeof(ToolbarRulesetSelector), - typeof(ToolbarRulesetButton), + typeof(ToolbarRulesetTabButton), }; public TestSceneToolbarRulesetSelector() diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 1f35d0f293..63cf2bba9c 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Toolbar protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(RulesetInfo value) => new ToolbarRulesetButton(value); + protected override TabItem CreateTabItem(RulesetInfo value) => new ToolbarRulesetTabButton(value); public ToolbarRulesetSelector() { diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs similarity index 88% rename from osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs rename to osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs index defe1da5bf..a5194ea752 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs @@ -10,16 +10,16 @@ using osu.Framework.Input.Events; namespace osu.Game.Overlays.Toolbar { - public class ToolbarRulesetButton : TabItem + public class ToolbarRulesetTabButton : TabItem { - private readonly DrawableRuleset ruleset; + private readonly RulesetButton ruleset; - public ToolbarRulesetButton(RulesetInfo value) + public ToolbarRulesetTabButton(RulesetInfo value) : base(value) { AutoSizeAxes = Axes.X; RelativeSizeAxes = Axes.Y; - Child = ruleset = new DrawableRuleset + Child = ruleset = new RulesetButton { Active = false, }; @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.Toolbar protected override void OnDeactivated() => ruleset.Active = false; - private class DrawableRuleset : ToolbarButton + private class RulesetButton : ToolbarButton { public bool Active { From 8d8615773ceecd629038441ad12421f6d9840bac Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Wed, 12 Jun 2019 20:54:19 +0300 Subject: [PATCH 1203/5608] Fix selection is being possible even in disabled state --- osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 63cf2bba9c..3baf9a1e49 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -25,10 +25,10 @@ namespace osu.Game.Overlays.Toolbar private RulesetStore rulesets; private readonly Bindable globalRuleset = new Bindable(); - public override bool HandleNonPositionalInput => !Current.Disabled && base.HandleNonPositionalInput; - public override bool HandlePositionalInput => !Current.Disabled && base.HandlePositionalInput; + public override bool HandleNonPositionalInput => !globalRuleset.Disabled && base.HandleNonPositionalInput; + public override bool HandlePositionalInput => !globalRuleset.Disabled && base.HandlePositionalInput; - public override bool PropagatePositionalInputSubTree => !Current.Disabled && base.PropagatePositionalInputSubTree; + public override bool PropagatePositionalInputSubTree => !globalRuleset.Disabled && base.PropagatePositionalInputSubTree; private void disabledChanged(bool isDisabled) => this.FadeColour(isDisabled ? Color4.Gray : Color4.White, 300); From e5a6d920cda80b2946c7fcde80c3b8545e50f047 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Wed, 12 Jun 2019 23:23:01 +0300 Subject: [PATCH 1204/5608] Implement an abstract RulesetSelector class --- .../Toolbar/ToolbarRulesetSelector.cs | 42 +++---------- osu.Game/Rulesets/RulesetSelector.cs | 63 +++++++++++++++++++ 2 files changed, 72 insertions(+), 33 deletions(-) create mode 100644 osu.Game/Rulesets/RulesetSelector.cs diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 3baf9a1e49..bd7ac13c9e 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -18,22 +17,18 @@ using System.Linq; namespace osu.Game.Overlays.Toolbar { - public class ToolbarRulesetSelector : TabControl + public class ToolbarRulesetSelector : RulesetSelector { private const float padding = 10; private readonly Drawable modeButtonLine; - private RulesetStore rulesets; - private readonly Bindable globalRuleset = new Bindable(); - public override bool HandleNonPositionalInput => !globalRuleset.Disabled && base.HandleNonPositionalInput; - public override bool HandlePositionalInput => !globalRuleset.Disabled && base.HandlePositionalInput; + public override bool HandleNonPositionalInput => !GlobalRuleset.Disabled && base.HandleNonPositionalInput; + public override bool HandlePositionalInput => !GlobalRuleset.Disabled && base.HandlePositionalInput; - public override bool PropagatePositionalInputSubTree => !globalRuleset.Disabled && base.PropagatePositionalInputSubTree; + public override bool PropagatePositionalInputSubTree => !GlobalRuleset.Disabled && base.PropagatePositionalInputSubTree; private void disabledChanged(bool isDisabled) => this.FadeColour(isDisabled ? Color4.Gray : Color4.White, 300); - protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(RulesetInfo value) => new ToolbarRulesetTabButton(value); public ToolbarRulesetSelector() @@ -66,6 +61,8 @@ namespace osu.Game.Overlays.Toolbar } } }); + + GlobalRuleset.DisabledChanged += disabledChanged; } protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer @@ -76,24 +73,6 @@ namespace osu.Game.Overlays.Toolbar Padding = new MarginPadding { Left = padding, Right = padding }, }; - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets, Bindable parentRuleset) - { - this.rulesets = rulesets; - globalRuleset.BindTo(parentRuleset); - - foreach (var r in rulesets.AvailableRulesets) - { - AddItem(r); - } - - globalRuleset.BindValueChanged(globalRulesetChanged); - globalRuleset.DisabledChanged += disabledChanged; - Current.BindValueChanged(localRulesetChanged); - } - - private void globalRulesetChanged(ValueChangedEvent e) => Current.Value = e.NewValue; - protected override bool OnKeyDown(KeyDownEvent e) { base.OnKeyDown(e); @@ -102,7 +81,7 @@ namespace osu.Game.Overlays.Toolbar { int requested = e.Key - Key.Number1; - RulesetInfo found = rulesets.AvailableRulesets.Skip(requested).FirstOrDefault(); + RulesetInfo found = AvaliableRulesets.AvailableRulesets.Skip(requested).FirstOrDefault(); if (found != null) Current.Value = found; return true; @@ -113,12 +92,9 @@ namespace osu.Game.Overlays.Toolbar private readonly Cached activeMode = new Cached(); - private void localRulesetChanged(ValueChangedEvent e) + protected override void OnLocalRulesetChanged(ValueChangedEvent e) { - if (!globalRuleset.Disabled) - { - globalRuleset.Value = e.NewValue; - } + base.OnLocalRulesetChanged(e); activeMode.Invalidate(); } diff --git a/osu.Game/Rulesets/RulesetSelector.cs b/osu.Game/Rulesets/RulesetSelector.cs new file mode 100644 index 0000000000..e646c2676b --- /dev/null +++ b/osu.Game/Rulesets/RulesetSelector.cs @@ -0,0 +1,63 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Bindables; +using osu.Framework.Allocation; + +namespace osu.Game.Rulesets +{ + public abstract class RulesetSelector : TabControl + { + protected RulesetStore AvaliableRulesets; + protected readonly Bindable GlobalRuleset = new Bindable(); + + protected override Dropdown CreateDropdown() => null; + + /// + /// Whether we want to change a global ruleset when local one is changed. + /// + protected virtual bool AllowGlobalRulesetChange => true; + + /// + /// Whether we want to change a local ruleset when global one is changed. + /// /// + protected virtual bool AllowLocalRulesetChange => true; + + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets, Bindable parentRuleset) + { + AvaliableRulesets = rulesets; + GlobalRuleset.BindTo(parentRuleset); + + foreach (var r in rulesets.AvailableRulesets) + { + AddItem(r); + } + + GlobalRuleset.BindValueChanged(globalRulesetChanged); + Current.BindValueChanged(OnLocalRulesetChanged); + } + + private void globalRulesetChanged(ValueChangedEvent e) + { + if (AllowLocalRulesetChange) + { + OnGlobalRulesetChanged(e); + } + } + + protected virtual void OnGlobalRulesetChanged(ValueChangedEvent e) + { + Current.Value = e.NewValue; + } + + protected virtual void OnLocalRulesetChanged(ValueChangedEvent e) + { + if (!GlobalRuleset.Disabled && AllowGlobalRulesetChange) + { + GlobalRuleset.Value = e.NewValue; + } + } + } +} From 27fdda8b91c070838c9a8d7f0a4d0092b53f59df Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 12:21:49 +0900 Subject: [PATCH 1205/5608] Don't update hitobject results when rewinding --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index ec7e6dc303..fe9f6f9e51 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -243,6 +243,10 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Whether a scoring result has occurred from this or any nested . protected bool UpdateResult(bool userTriggered) { + // It's possible for input to get into a bad state when rewinding gameplay, so results should not be processed + if (Time.Elapsed < 0) + return false; + judgementOccurred = false; if (AllJudged) From 44d2514f1a94b5aa49a36e9966d0d65bf8af9b72 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 14:41:10 +0900 Subject: [PATCH 1206/5608] Add test scene --- .../Gameplay/TestSceneGameplayRewinding.cs | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs new file mode 100644 index 0000000000..b3c98c9aaa --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -0,0 +1,101 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.MathUtils; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.UI; +using osu.Game.Screens.Play; +using osuTK; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestSceneGameplayRewinding : PlayerTestScene + { + private RulesetExposingPlayer player => (RulesetExposingPlayer)Player; + + [Resolved] + private AudioManager audioManager { get; set; } + + public TestSceneGameplayRewinding() + : base(new OsuRuleset()) + { + } + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) + => new ClockBackedTestWorkingBeatmap(beatmap, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + + [Test] + public void TestNotJudgementsOnRewind() + { + addSeekStep(3000); + AddAssert("all judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged)); + AddStep("clear results", () => player.AppliedResults.Clear()); + addSeekStep(0); + AddAssert("none judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => !h.Judged)); + AddAssert("no results triggered", () => player.AppliedResults.Count == 0); + } + + private void addSeekStep(double time) + { + AddStep($"seek to {time}", () => player.GameplayClockContainer.Seek(time)); + + // Allow 2 frames of lenience + AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, player.DrawableRuleset.FrameStableClock.CurrentTime, 32)); + } + + protected override Player CreatePlayer(Ruleset ruleset) + { + Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); + return new RulesetExposingPlayer(); + } + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) + { + var beatmap = new Beatmap + { + BeatmapInfo = { BaseDifficulty = { ApproachRate = 9 } }, + }; + + for (int i = 0; i < 15; i++) + { + beatmap.HitObjects.Add(new HitCircle + { + Position = new Vector2(256, 192), + StartTime = 1000 + 30 * i + }); + } + + return beatmap; + } + + private class RulesetExposingPlayer : Player + { + public readonly List AppliedResults = new List(); + + public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; + + public new DrawableRuleset DrawableRuleset => base.DrawableRuleset; + + public RulesetExposingPlayer() + : base(false, false) + { + } + + [BackgroundDependencyLoader] + private void load() + { + ScoreProcessor.NewJudgement += r => AppliedResults.Add(r); + } + } + } +} From 4818187d8f6f01226eeac89e794b00e6a1a1e800 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 14:55:52 +0900 Subject: [PATCH 1207/5608] Reset result timeoffset to 0 when rewound --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index ec7e6dc303..02d29de367 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -167,6 +167,7 @@ namespace osu.Game.Rulesets.Objects.Drawables { OnRevertResult?.Invoke(this, Result); + Result.TimeOffset = 0; Result.Type = HitResult.None; State.Value = ArmedState.Idle; } From 1f2454188335222c8825365f7801eb62728892d7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Jun 2019 15:43:03 +0900 Subject: [PATCH 1208/5608] Re-expose OsuButton --- osu.Game/Graphics/UserInterface/OsuButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 494d4e4262..7a27f825f6 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -17,11 +17,11 @@ namespace osu.Game.Graphics.UserInterface /// /// A button with added default sound effects. /// - public abstract class OsuButton : Button + public class OsuButton : Button { private Box hover; - protected OsuButton() + public OsuButton() { Height = 40; From f12caaf9079126123b3eeb44f7d96de49c471a33 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 15:47:21 +0900 Subject: [PATCH 1209/5608] Increase leniency --- osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index b3c98c9aaa..0176301c03 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -49,8 +49,8 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep($"seek to {time}", () => player.GameplayClockContainer.Seek(time)); - // Allow 2 frames of lenience - AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, player.DrawableRuleset.FrameStableClock.CurrentTime, 32)); + // Allow a few frames of lenience + AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, player.DrawableRuleset.FrameStableClock.CurrentTime, 100)); } protected override Player CreatePlayer(Ruleset ruleset) From a0503fcbe30bfa59dd9ea0d2f5820d62a3ca4fdf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Jun 2019 16:05:34 +0900 Subject: [PATCH 1210/5608] Reduce update rate of paths --- osu.Game.Tournament/Screens/Ladder/LadderScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 86b1884579..ffdc20c9e7 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -59,7 +59,7 @@ namespace osu.Game.Tournament.Screens.Ladder AddPairing(pairing); // todo: fix this - Scheduler.AddDelayed(() => layout.Invalidate(), 100, true); + Scheduler.AddDelayed(() => layout.Invalidate(), 1000, true); } protected virtual void AddPairing(MatchPairing pairing) From aef94ce9f15f17beca530d7425a9bd9ace22cfe9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 16:30:38 +0900 Subject: [PATCH 1211/5608] Make BeatmapMetrics non-IEnumerables --- .../Online/TestSceneBeatmapSetOverlay.cs | 60 +++++++++---------- .../SongSelect/TestSceneBeatmapDetailArea.cs | 18 +++--- .../SongSelect/TestSceneBeatmapDetails.cs | 18 +++--- .../Visual/SongSelect/TestSceneLeaderboard.cs | 6 +- osu.Game/Beatmaps/BeatmapMetrics.cs | 8 +-- 5 files changed, 55 insertions(+), 55 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 5910da7b88..f970e180d8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -111,9 +111,9 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }, new BeatmapInfo @@ -138,9 +138,9 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }, new BeatmapInfo @@ -165,9 +165,9 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }, new BeatmapInfo @@ -192,9 +192,9 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }, new BeatmapInfo @@ -219,9 +219,9 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }, }, @@ -282,9 +282,9 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }, new BeatmapInfo @@ -309,9 +309,9 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }, new BeatmapInfo @@ -336,9 +336,9 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }, new BeatmapInfo @@ -363,9 +363,9 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }, new BeatmapInfo @@ -390,9 +390,9 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }, }, diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index 8395ece457..f10237ec57 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -50,9 +50,9 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 5.3f, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, } } @@ -77,9 +77,9 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 5.3f, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, } }); @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 4.8f, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), + Ratings = Enumerable.Range(0, 11).ToArray(), }, } }); @@ -129,8 +129,8 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 2.91f, Metrics = new BeatmapMetrics { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, } }); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index acbbd4e18b..26e4fc9e1c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -39,9 +39,9 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 5.3f, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }); @@ -62,9 +62,9 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 5.3f, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }); @@ -86,7 +86,7 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 4.8f, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), + Ratings = Enumerable.Range(0, 11).ToArray(), }, }); @@ -108,8 +108,8 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 2.91f, Metrics = new BeatmapMetrics { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs index 9365e2c5b1..ecfdb10b60 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs @@ -270,9 +270,9 @@ namespace osu.Game.Tests.Visual.SongSelect }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11), - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + Ratings = Enumerable.Range(0, 11).ToArray(), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }; } diff --git a/osu.Game/Beatmaps/BeatmapMetrics.cs b/osu.Game/Beatmaps/BeatmapMetrics.cs index 95413e6d2a..a31f7e26cf 100644 --- a/osu.Game/Beatmaps/BeatmapMetrics.cs +++ b/osu.Game/Beatmaps/BeatmapMetrics.cs @@ -1,7 +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; using Newtonsoft.Json; namespace osu.Game.Beatmaps @@ -14,18 +14,18 @@ namespace osu.Game.Beatmaps /// /// Total vote counts of user ratings on a scale of 0..10 where 0 is unused (probably will be fixed at API?). /// - public IEnumerable Ratings { get; set; } + public int[] Ratings { get; set; } = Array.Empty(); /// /// Points of failure on a relative time scale (usually 0..100). /// [JsonProperty(@"fail")] - public IEnumerable Fails { get; set; } + public int[] Fails { get; set; } = Array.Empty(); /// /// Points of retry on a relative time scale (usually 0..100). /// [JsonProperty(@"exit")] - public IEnumerable Retries { get; set; } + public int[] Retries { get; set; } = Array.Empty(); } } From 4af16262e3b88bf53673e3d2c8f243b30f2c7c7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Jun 2019 16:11:15 +0900 Subject: [PATCH 1212/5608] Limit zoom range of bracket display --- ...{ScrollableContainer.cs => LadderDragContainer.cs} | 11 +++++++---- osu.Game.Tournament/Screens/Ladder/LadderScreen.cs | 7 ++----- 2 files changed, 9 insertions(+), 9 deletions(-) rename osu.Game.Tournament/Screens/Ladder/{ScrollableContainer.cs => LadderDragContainer.cs} (74%) diff --git a/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs similarity index 74% rename from osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs rename to osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index 832e218b74..6687ca13f9 100644 --- a/osu.Game.Tournament/Screens/Ladder/ScrollableContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -8,7 +8,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Ladder { - public class ScrollableContainer : Container + public class LadderDragContainer : Container { protected override bool OnDragStart(DragStartEvent e) => true; @@ -24,12 +24,15 @@ namespace osu.Game.Tournament.Screens.Ladder return true; } + private const float min_scale = 0.6f; + private const float max_scale = 1.4f; + protected override bool OnScroll(ScrollEvent e) { - var newScale = scale + e.ScrollDelta.Y / 15 * scale; - this.MoveTo(target = target - e.MousePosition * (newScale - scale), 1000, Easing.OutQuint); + var newScale = MathHelper.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); - this.ScaleTo(scale = newScale, 1000, Easing.OutQuint); + this.MoveTo(target = target - e.MousePosition * (newScale - scale), 2000, Easing.OutQuint); + this.ScaleTo(scale = newScale, 2000, Easing.OutQuint); return true; } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index ffdc20c9e7..e54bcffe2e 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tournament.Screens.Ladder private Container paths; private Container headings; - protected ScrollableContainer ScrollContent; + protected LadderDragContainer ScrollContent; [BackgroundDependencyLoader] private void load(OsuColour colours, Storage storage) @@ -42,7 +42,7 @@ namespace osu.Game.Tournament.Screens.Ladder RelativeSizeAxes = Axes.Both, Loop = true, }, - ScrollContent = new ScrollableContainer + ScrollContent = new LadderDragContainer { RelativeSizeAxes = Axes.Both, Children = new Drawable[] @@ -133,8 +133,5 @@ namespace osu.Game.Tournament.Screens.Ladder layout.Validate(); } - - // todo: remove after ppy/osu-framework#1980 is merged. - public override bool HandlePositionalInput => true; } } From ba475ef6c878bff4c5eb870aad62d669ac786f19 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Jun 2019 16:38:45 +0900 Subject: [PATCH 1213/5608] Remove unnecessary invalidation --- osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index 6687ca13f9..3aa06185cb 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -36,11 +36,5 @@ namespace osu.Game.Tournament.Screens.Ladder return true; } - - protected override void Update() - { - base.Update(); - Invalidate(); - } } } From f240a157b247f0acbf2d9234c7ce60432a773dfc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 16:39:38 +0900 Subject: [PATCH 1214/5608] Deserialize API metrics --- osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index edbcbed59f..bcbe060f82 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -57,6 +57,9 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"version")] private string version { get; set; } + [JsonProperty(@"failtimes")] + private BeatmapMetrics metrics { get; set; } + public BeatmapInfo ToBeatmap(RulesetStore rulesets) { var set = BeatmapSet?.ToBeatmapSet(rulesets); @@ -70,6 +73,7 @@ namespace osu.Game.Online.API.Requests.Responses Version = version, Status = Status, BeatmapSet = set, + Metrics = metrics, BaseDifficulty = new BeatmapDifficulty { DrainRate = drainRate, From 0a79b444d93036b1005f613f29753464e0af7cb3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 16:52:49 +0900 Subject: [PATCH 1215/5608] Move metrics to beatmap set --- .../Online/TestSceneBeatmapSetOverlay.cs | 12 ++--------- .../SongSelect/TestSceneBeatmapDetailArea.cs | 20 ++++++++++++------- .../SongSelect/TestSceneBeatmapDetails.cs | 19 +++++++++++------- .../Visual/SongSelect/TestSceneLeaderboard.cs | 1 - osu.Game/Beatmaps/BeatmapMetrics.cs | 7 +------ osu.Game/Beatmaps/BeatmapSetInfo.cs | 3 +++ osu.Game/Beatmaps/BeatmapSetMetrics.cs | 17 ++++++++++++++++ .../Requests/Responses/APIBeatmapMetrics.cs | 6 +++++- .../API/Requests/Responses/APIBeatmapSet.cs | 4 ++++ osu.Game/Overlays/BeatmapSet/Details.cs | 2 +- osu.Game/Screens/Select/BeatmapDetails.cs | 15 +++++++------- .../Screens/Select/Details/UserRatings.cs | 4 ++-- 12 files changed, 67 insertions(+), 43 deletions(-) create mode 100644 osu.Game/Beatmaps/BeatmapSetMetrics.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index f970e180d8..38388218c2 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -87,6 +87,7 @@ namespace osu.Game.Tests.Visual.Online Cover = @"https://assets.ppy.sh/beatmaps/415886/covers/cover.jpg?1465651778", }, }, + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = new List { new BeatmapInfo @@ -111,7 +112,6 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, @@ -138,7 +138,6 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, @@ -165,7 +164,6 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, @@ -192,7 +190,6 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, @@ -219,7 +216,6 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, @@ -258,6 +254,7 @@ namespace osu.Game.Tests.Visual.Online Cover = @"https://assets.ppy.sh/beatmaps/625493/covers/cover.jpg?1499167472", }, }, + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = new List { new BeatmapInfo @@ -282,7 +279,6 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, @@ -309,7 +305,6 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, @@ -336,7 +331,6 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, @@ -363,7 +357,6 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, @@ -390,7 +383,6 @@ namespace osu.Game.Tests.Visual.Online }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index f10237ec57..7b97a27732 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -32,6 +32,10 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) { + BeatmapSetInfo = + { + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + }, BeatmapInfo = { Version = "All Metrics", @@ -50,7 +54,6 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 5.3f, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, @@ -60,6 +63,10 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("all except source", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) { + BeatmapSetInfo = + { + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + }, BeatmapInfo = { Version = "All Metrics", @@ -77,7 +84,6 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 5.3f, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, @@ -86,6 +92,10 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("ratings", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) { + BeatmapSetInfo = + { + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + }, BeatmapInfo = { Version = "Only Ratings", @@ -101,11 +111,7 @@ namespace osu.Game.Tests.Visual.SongSelect OverallDifficulty = 6, ApproachRate = 6, }, - StarDifficulty = 4.8f, - Metrics = new BeatmapMetrics - { - Ratings = Enumerable.Range(0, 11).ToArray(), - }, + StarDifficulty = 4.8f } }); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index 26e4fc9e1c..124a261521 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -23,6 +23,10 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("all metrics", () => details.Beatmap = new BeatmapInfo { + BeatmapSet = new BeatmapSetInfo + { + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + }, Version = "All Metrics", Metadata = new BeatmapMetadata { @@ -39,7 +43,6 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 5.3f, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, @@ -47,6 +50,10 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("all except source", () => details.Beatmap = new BeatmapInfo { + BeatmapSet = new BeatmapSetInfo + { + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + }, Version = "All Metrics", Metadata = new BeatmapMetadata { @@ -62,7 +69,6 @@ namespace osu.Game.Tests.Visual.SongSelect StarDifficulty = 5.3f, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, @@ -70,6 +76,10 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("ratings", () => details.Beatmap = new BeatmapInfo { + BeatmapSet = new BeatmapSetInfo + { + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + }, Version = "Only Ratings", Metadata = new BeatmapMetadata { @@ -84,10 +94,6 @@ namespace osu.Game.Tests.Visual.SongSelect ApproachRate = 6, }, StarDifficulty = 4.8f, - Metrics = new BeatmapMetrics - { - Ratings = Enumerable.Range(0, 11).ToArray(), - }, }); AddStep("fails retries", () => details.Beatmap = new BeatmapInfo @@ -129,7 +135,6 @@ namespace osu.Game.Tests.Visual.SongSelect ApproachRate = 6.5f, }, StarDifficulty = 1.97f, - Metrics = new BeatmapMetrics(), }); AddStep("null beatmap", () => details.Beatmap = null); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs index ecfdb10b60..157e572606 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs @@ -270,7 +270,6 @@ namespace osu.Game.Tests.Visual.SongSelect }, Metrics = new BeatmapMetrics { - Ratings = Enumerable.Range(0, 11).ToArray(), Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, diff --git a/osu.Game/Beatmaps/BeatmapMetrics.cs b/osu.Game/Beatmaps/BeatmapMetrics.cs index a31f7e26cf..b164aa6b30 100644 --- a/osu.Game/Beatmaps/BeatmapMetrics.cs +++ b/osu.Game/Beatmaps/BeatmapMetrics.cs @@ -7,15 +7,10 @@ using Newtonsoft.Json; namespace osu.Game.Beatmaps { /// - /// Beatmap metrics based on acculumated online data from community plays. + /// Beatmap metrics based on accumulated online data from community plays. /// public class BeatmapMetrics { - /// - /// Total vote counts of user ratings on a scale of 0..10 where 0 is unused (probably will be fixed at API?). - /// - public int[] Ratings { get; set; } = Array.Empty(); - /// /// Points of failure on a relative time scale (usually 0..100). /// diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 390236e053..c09119ab14 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -32,6 +32,9 @@ namespace osu.Game.Beatmaps [NotMapped] public BeatmapSetOnlineInfo OnlineInfo { get; set; } + [NotMapped] + public BeatmapSetMetrics Metrics { get; set; } + public double MaxStarDifficulty => Beatmaps?.Max(b => b.StarDifficulty) ?? 0; [NotMapped] diff --git a/osu.Game/Beatmaps/BeatmapSetMetrics.cs b/osu.Game/Beatmaps/BeatmapSetMetrics.cs new file mode 100644 index 0000000000..51c5de19a6 --- /dev/null +++ b/osu.Game/Beatmaps/BeatmapSetMetrics.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using Newtonsoft.Json; + +namespace osu.Game.Beatmaps +{ + public class BeatmapSetMetrics + { + /// + /// Total vote counts of user ratings on a scale of 0..10 where 0 is unused (probably will be fixed at API?). + /// + [JsonProperty("ratings")] + public int[] Ratings { get; set; } = Array.Empty(); + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapMetrics.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapMetrics.cs index f049b3aed4..32a036b7c2 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapMetrics.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapMetrics.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 Newtonsoft.Json; using osu.Game.Beatmaps; @@ -19,9 +20,12 @@ namespace osu.Game.Online.API.Requests.Responses } } + public int[] Ratings { get; set; } = Array.Empty(); + //and other metrics in the beatmap set. + // Todo: What [JsonProperty(@"beatmapset")] - private BeatmapMetrics beatmapSet + private BeatmapSetMetrics beatmapSet { set => Ratings = value.Ratings; } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 1abb7c1a7d..05e647d107 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -54,6 +54,9 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"last_updated")] private DateTimeOffset lastUpdated { get; set; } + [JsonProperty(@"ratings")] + private int[] ratings { get; set; } + [JsonProperty(@"user_id")] private long creatorId { @@ -70,6 +73,7 @@ namespace osu.Game.Online.API.Requests.Responses OnlineBeatmapSetID = OnlineBeatmapSetID, Metadata = this, Status = Status, + Metrics = new BeatmapSetMetrics { Ratings = ratings }, OnlineInfo = new BeatmapSetOnlineInfo { Covers = covers, diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index fad5c973b7..82f674ea86 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -52,7 +52,7 @@ namespace osu.Game.Overlays.BeatmapSet private void updateDisplay() { - ratings.Metrics = Beatmap?.Metrics; + ratings.Metrics = Beatmap?.BeatmapSet?.Metrics; } public Details() diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 378b1b1dc6..83f9e5b063 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -18,6 +18,7 @@ using osu.Game.Screens.Select.Details; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Screens.Select { @@ -181,9 +182,10 @@ namespace osu.Game.Screens.Select tags.Text = Beatmap?.Metadata?.Tags; // metrics may have been previously fetched - if (Beatmap?.Metrics != null) + // Todo: + if (Beatmap?.BeatmapSet?.Metrics != null) { - updateMetrics(Beatmap.Metrics); + updateMetrics(new APIBeatmapMetrics { Ratings = Beatmap.BeatmapSet.Metrics.Ratings }); return; } @@ -210,22 +212,19 @@ namespace osu.Game.Screens.Select updateMetrics(); } - private void updateMetrics(BeatmapMetrics metrics = null) + private void updateMetrics(APIBeatmapMetrics metrics = null) { var hasRatings = metrics?.Ratings?.Any() ?? false; var hasRetriesFails = (metrics?.Retries?.Any() ?? false) && (metrics.Fails?.Any() ?? false); if (hasRatings) { - ratings.Metrics = metrics; + ratings.Metrics = new BeatmapSetMetrics { Ratings = metrics.Ratings }; ratingsContainer.FadeIn(transition_duration); } else { - ratings.Metrics = new BeatmapMetrics - { - Ratings = new int[10], - }; + ratings.Metrics = new BeatmapSetMetrics { Ratings = new int[10] }; ratingsContainer.FadeTo(0.25f, transition_duration); } diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs index b17a3f79e9..c1e01e3572 100644 --- a/osu.Game/Screens/Select/Details/UserRatings.cs +++ b/osu.Game/Screens/Select/Details/UserRatings.cs @@ -20,9 +20,9 @@ namespace osu.Game.Screens.Select.Details private readonly Container graphContainer; private readonly BarGraph graph; - private BeatmapMetrics metrics; + private BeatmapSetMetrics metrics; - public BeatmapMetrics Metrics + public BeatmapSetMetrics Metrics { get => metrics; set From 583bb53f53c268b69c23ead81c67fded43569f96 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 16:57:19 +0900 Subject: [PATCH 1216/5608] Remove GetBeatmapDetailsRequest --- .../API/Requests/GetBeatmapDetailsRequest.cs | 20 ----------- .../Requests/Responses/APIBeatmapMetrics.cs | 33 ------------------- osu.Game/Screens/Select/BeatmapDetails.cs | 30 ++++++++++------- 3 files changed, 18 insertions(+), 65 deletions(-) delete mode 100644 osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs delete mode 100644 osu.Game/Online/API/Requests/Responses/APIBeatmapMetrics.cs diff --git a/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs deleted file mode 100644 index ed5efa2849..0000000000 --- a/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; - -namespace osu.Game.Online.API.Requests -{ - public class GetBeatmapDetailsRequest : APIRequest - { - private readonly BeatmapInfo beatmap; - - public GetBeatmapDetailsRequest(BeatmapInfo beatmap) - { - this.beatmap = beatmap; - } - - protected override string Target => $@"beatmaps/{beatmap.OnlineBeatmapID}"; - } -} diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapMetrics.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapMetrics.cs deleted file mode 100644 index 32a036b7c2..0000000000 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapMetrics.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using Newtonsoft.Json; -using osu.Game.Beatmaps; - -namespace osu.Game.Online.API.Requests.Responses -{ - public class APIBeatmapMetrics : BeatmapMetrics - { - //the online API returns some metrics as a nested object. - [JsonProperty(@"failtimes")] - private BeatmapMetrics failTimes - { - set - { - Fails = value.Fails; - Retries = value.Retries; - } - } - - public int[] Ratings { get; set; } = Array.Empty(); - - //and other metrics in the beatmap set. - // Todo: What - [JsonProperty(@"beatmapset")] - private BeatmapSetMetrics beatmapSet - { - set => Ratings = value.Ratings; - } - } -} diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 83f9e5b063..1b4608b0fd 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -10,7 +10,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using System.Linq; using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Framework.Threading; using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.Color4Extensions; @@ -18,7 +17,8 @@ using osu.Game.Screens.Select.Details; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.API.Requests; +using osu.Game.Rulesets; namespace osu.Game.Screens.Select { @@ -41,6 +41,9 @@ namespace osu.Game.Screens.Select private ScheduledDelegate pendingBeatmapSwitch; + [Resolved] + private RulesetStore rulesets { get; set; } + private BeatmapInfo beatmap; public BeatmapInfo Beatmap @@ -182,10 +185,9 @@ namespace osu.Game.Screens.Select tags.Text = Beatmap?.Metadata?.Tags; // metrics may have been previously fetched - // Todo: if (Beatmap?.BeatmapSet?.Metrics != null) { - updateMetrics(new APIBeatmapMetrics { Ratings = Beatmap.BeatmapSet.Metrics.Ratings }); + updateMetrics(Beatmap); return; } @@ -193,15 +195,19 @@ namespace osu.Game.Screens.Select if (Beatmap?.OnlineBeatmapID != null) { var requestedBeatmap = Beatmap; - var lookup = new GetBeatmapDetailsRequest(requestedBeatmap); + var lookup = new GetBeatmapRequest(requestedBeatmap); lookup.Success += res => { if (beatmap != requestedBeatmap) //the beatmap has been changed since we started the lookup. return; - requestedBeatmap.Metrics = res; - Schedule(() => updateMetrics(res)); + var b = res.ToBeatmap(rulesets); + + requestedBeatmap.BeatmapSet.Metrics = b.BeatmapSet.Metrics; + requestedBeatmap.Metrics = b.Metrics; + + Schedule(() => updateMetrics(requestedBeatmap)); }; lookup.Failure += e => Schedule(() => updateMetrics()); api.Queue(lookup); @@ -212,14 +218,14 @@ namespace osu.Game.Screens.Select updateMetrics(); } - private void updateMetrics(APIBeatmapMetrics metrics = null) + private void updateMetrics(BeatmapInfo beatmap = null) { - var hasRatings = metrics?.Ratings?.Any() ?? false; - var hasRetriesFails = (metrics?.Retries?.Any() ?? false) && (metrics.Fails?.Any() ?? false); + var hasRatings = beatmap?.BeatmapSet?.Metrics?.Ratings?.Any() ?? false; + var hasRetriesFails = (beatmap?.Metrics?.Retries?.Any() ?? false) && (beatmap.Metrics.Fails?.Any() ?? false); if (hasRatings) { - ratings.Metrics = new BeatmapSetMetrics { Ratings = metrics.Ratings }; + ratings.Metrics = beatmap.BeatmapSet.Metrics; ratingsContainer.FadeIn(transition_duration); } else @@ -230,7 +236,7 @@ namespace osu.Game.Screens.Select if (hasRetriesFails) { - failRetryGraph.Metrics = metrics; + failRetryGraph.Metrics = beatmap.Metrics; failRetryContainer.FadeIn(transition_duration); } else From dd7335079fd6ce03a06cc9f29d172dbc56541de1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 17:01:57 +0900 Subject: [PATCH 1217/5608] Fix beatmap set overlay not showing ratings --- osu.Game/Overlays/BeatmapSet/Details.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index 82f674ea86..55e9500859 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -52,7 +52,7 @@ namespace osu.Game.Overlays.BeatmapSet private void updateDisplay() { - ratings.Metrics = Beatmap?.BeatmapSet?.Metrics; + ratings.Metrics = BeatmapSet?.Metrics; } public Details() From eb0f0aefba7bdd76a66ed5c25c50c3f1d8622f48 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Jun 2019 17:04:57 +0900 Subject: [PATCH 1218/5608] Apply review changes --- .../Components/ControlPanel.cs | 4 ---- osu.Game.Tournament/Components/DateTextBox.cs | 3 ++- .../Components/MatchChatDisplay.cs | 4 ++-- osu.Game.Tournament/Components/SongBar.cs | 15 ++++++------- .../Components/TournamentBeatmapPanel.cs | 6 ++---- .../Ladder/Components/DrawableMatchTeam.cs | 5 ++--- .../Components/TournamentProgression.cs | 21 ++++++++++++++----- .../Screens/Ladder/LadderEditorScreen.cs | 10 ++++----- .../Screens/Ladder/LadderScreen.cs | 4 +++- osu.Game.Tournament/TournamentGameBase.cs | 4 ++-- 10 files changed, 42 insertions(+), 34 deletions(-) diff --git a/osu.Game.Tournament/Components/ControlPanel.cs b/osu.Game.Tournament/Components/ControlPanel.cs index 0d228fb3b4..a9bb1bf42f 100644 --- a/osu.Game.Tournament/Components/ControlPanel.cs +++ b/osu.Game.Tournament/Components/ControlPanel.cs @@ -39,7 +39,6 @@ namespace osu.Game.Tournament.Components { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Text = "Control Panel", Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22) }, @@ -47,13 +46,10 @@ namespace osu.Game.Tournament.Components { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Width = 0.75f, - Position = new Vector2(0, 35f), - Direction = FillDirection.Vertical, Spacing = new Vector2(0, 5f), }, diff --git a/osu.Game.Tournament/Components/DateTextBox.cs b/osu.Game.Tournament/Components/DateTextBox.cs index f25c4b6e78..ee7e350970 100644 --- a/osu.Game.Tournament/Components/DateTextBox.cs +++ b/osu.Game.Tournament/Components/DateTextBox.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tournament.Components get => bindable; set { - bindable = value; + bindable = value.GetBoundCopy(); bindable.BindValueChanged(dto => base.Bindable.Value = dto.NewValue.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"), true); } @@ -35,6 +35,7 @@ namespace osu.Game.Tournament.Components } catch { + // reset textbox content to its last valid state on a parse failure. bindable.TriggerChange(); } }; diff --git a/osu.Game.Tournament/Components/MatchChatDisplay.cs b/osu.Game.Tournament/Components/MatchChatDisplay.cs index dd567ed290..174b215732 100644 --- a/osu.Game.Tournament/Components/MatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/MatchChatDisplay.cs @@ -15,8 +15,6 @@ namespace osu.Game.Tournament.Components { private readonly Bindable chatChannel = new Bindable(); - protected override ChatLine CreateMessage(Message message) => new MatchMessage(message); - private ChannelManager manager; [BackgroundDependencyLoader(true)] @@ -55,6 +53,8 @@ namespace osu.Game.Tournament.Components } } + protected override ChatLine CreateMessage(Message message) => new MatchMessage(message); + protected class MatchMessage : StandAloneMessage { public MatchMessage(Message message) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index a08333571b..c07882ddd0 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -228,21 +228,22 @@ namespace osu.Game.Tournament.Components s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15); } - bool first = true; - - foreach (var t in tuples) + for (var i = 0; i < tuples.Length; i++) { - if (!first) + var tuple = tuples[i]; + + if (i > 0) + { AddText(" / ", s => { cp(s, OsuColour.Gray(0.33f)); s.Spacing = new Vector2(-2, 0); }); + } - AddText(new OsuSpriteText { Text = t.heading }, s => cp(s, OsuColour.Gray(0.33f))); + AddText(new OsuSpriteText { Text = tuple.heading }, s => cp(s, OsuColour.Gray(0.33f))); AddText(" ", s => cp(s, OsuColour.Gray(0.33f))); - AddText(new OsuSpriteText { Text = t.content }, s => cp(s, OsuColour.Gray(0.5f))); - first = false; + AddText(new OsuSpriteText { Text = tuple.content }, s => cp(s, OsuColour.Gray(0.5f))); } } } diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 818d25d559..cf826ee2c7 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -11,9 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.IO.Stores; using osu.Framework.Localisation; -using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; @@ -48,7 +46,7 @@ namespace osu.Game.Tournament.Components } [BackgroundDependencyLoader] - private void load(LadderInfo ladder, Storage storage) + private void load(LadderInfo ladder, TextureStore textures) { currentMatch.BindValueChanged(matchChanged); currentMatch.BindTo(ladder.CurrentMatch); @@ -135,7 +133,7 @@ namespace osu.Game.Tournament.Components if (!string.IsNullOrEmpty(mods)) AddInternal(new Sprite { - Texture = new LargeTextureStore(new TextureLoaderStore(new StorageBackedResourceStore(storage))).Get($"mods/{mods}"), + Texture = textures.Get($"mods/{mods}"), Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Margin = new MarginPadding(20), diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 35b6dfb606..6d5ac74267 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -138,7 +138,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components }, true); } - //TODO: use OnClick instead once we have per-button clicks. protected override bool OnClick(ClickEvent e) { if (Team == null || editorInfo != null) return false; @@ -196,8 +195,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components return new MenuItem[] { new OsuMenuItem("Set as current", MenuItemType.Standard, setCurrent), - new OsuMenuItem("Join with", MenuItemType.Standard, () => ladderEditor.RequestJoin(pairing, false)), - new OsuMenuItem("Join with (loser)", MenuItemType.Standard, () => ladderEditor.RequestJoin(pairing, true)), + new OsuMenuItem("Join with", MenuItemType.Standard, () => ladderEditor.BeginJoin(pairing, false)), + new OsuMenuItem("Join with (loser)", MenuItemType.Standard, () => ladderEditor.BeginJoin(pairing, true)), new OsuMenuItem("Remove", MenuItemType.Destructive, () => ladderEditor.Remove(pairing)), }; } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs index 241e1d1d0b..0019dc8d79 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs @@ -5,15 +5,26 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public class TournamentProgression { - public int Item1; - public int Item2; + public int SourceID; + public int TargetID; + + // migration + public int Item1 + { + set => SourceID = value; + } + + public int Item2 + { + set => TargetID = value; + } public bool Losers; - public TournamentProgression(int item1, int item2, bool losers = false) + public TournamentProgression(int sourceID, int targetID, bool losers = false) { - Item1 = item1; - Item2 = item2; + SourceID = sourceID; + TargetID = targetID; Losers = losers; } } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs index e605de9a7c..4a35f1ad30 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tournament.Screens.Ladder [BackgroundDependencyLoader] private void load() { - ((Container)InternalChild).Add(new LadderEditorSettings + Content.Add(new LadderEditorSettings { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -58,9 +58,9 @@ namespace osu.Game.Tournament.Screens.Ladder updateInfo(); } - public void RequestJoin(MatchPairing pairing, bool losers) + public void BeginJoin(MatchPairing pairing, bool losers) { - ScrollContent.Add(new JoinRequestHandler(PairingsContainer, pairing, losers, updateInfo)); + ScrollContent.Add(new JoinVisualiser(PairingsContainer, pairing, losers, updateInfo)); } public MenuItem[] ContextMenuItems @@ -91,7 +91,7 @@ namespace osu.Game.Tournament.Screens.Ladder PairingsContainer.FirstOrDefault(p => p.Pairing == pairing)?.Remove(); } - private class JoinRequestHandler : CompositeDrawable + private class JoinVisualiser : CompositeDrawable { private readonly Container pairingsContainer; public readonly MatchPairing Source; @@ -100,7 +100,7 @@ namespace osu.Game.Tournament.Screens.Ladder private ProgressionPath path; - public JoinRequestHandler(Container pairingsContainer, MatchPairing source, bool losers, Action complete) + public JoinVisualiser(Container pairingsContainer, MatchPairing source, bool losers, Action complete) { this.pairingsContainer = pairingsContainer; RelativeSizeAxes = Axes.Both; diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index e54bcffe2e..f2d4ebbb71 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -24,6 +24,8 @@ namespace osu.Game.Tournament.Screens.Ladder protected LadderDragContainer ScrollContent; + protected Container Content; + [BackgroundDependencyLoader] private void load(OsuColour colours, Storage storage) { @@ -32,7 +34,7 @@ namespace osu.Game.Tournament.Screens.Ladder RelativeSizeAxes = Axes.Both; - InternalChild = new Container + InternalChild = Content = new Container { RelativeSizeAxes = Axes.Both, Children = new Drawable[] diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 4f54da2723..739fabca9d 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -110,8 +110,8 @@ namespace osu.Game.Tournament // assign progressions foreach (var pair in ladder.Progressions) { - var src = ladder.Pairings.FirstOrDefault(p => p.ID == pair.Item1); - var dest = ladder.Pairings.FirstOrDefault(p => p.ID == pair.Item2); + var src = ladder.Pairings.FirstOrDefault(p => p.ID == pair.SourceID); + var dest = ladder.Pairings.FirstOrDefault(p => p.ID == pair.TargetID); if (src == null) throw new InvalidOperationException(); From f54f6e552ba2c95bacf3cc83be5dbf4a083ce26b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 17:10:09 +0900 Subject: [PATCH 1219/5608] Fix beatmap details potentially using the incorrect metrics --- .../SongSelect/TestSceneBeatmapDetails.cs | 19 ++++++++++++ osu.Game/Screens/Select/BeatmapDetails.cs | 29 ++++++++++++------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index 124a261521..f4f3c2b8d1 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -138,6 +138,25 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddStep("null beatmap", () => details.Beatmap = null); + + AddStep("online ratings/retries/fails", () => details.Beatmap = new BeatmapInfo + { + OnlineBeatmapID = 162, + Version = "online ratings/retries/fails", + Metadata = new BeatmapMetadata + { + Source = "osu!lazer", + Tags = "this beatmap has online ratings/retries/fails", + }, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 7, + DrainRate = 1, + OverallDifficulty = 5.7f, + ApproachRate = 3.5f, + }, + StarDifficulty = 5.3f + }); } } } diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 1b4608b0fd..de78fe6572 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -185,9 +185,9 @@ namespace osu.Game.Screens.Select tags.Text = Beatmap?.Metadata?.Tags; // metrics may have been previously fetched - if (Beatmap?.BeatmapSet?.Metrics != null) + if (Beatmap?.BeatmapSet?.Metrics != null && Beatmap?.Metrics != null) { - updateMetrics(Beatmap); + updateMetrics(Beatmap.BeatmapSet.Metrics, Beatmap.Metrics); return; } @@ -195,6 +195,7 @@ namespace osu.Game.Screens.Select if (Beatmap?.OnlineBeatmapID != null) { var requestedBeatmap = Beatmap; + var lookup = new GetBeatmapRequest(requestedBeatmap); lookup.Success += res => { @@ -204,28 +205,34 @@ namespace osu.Game.Screens.Select var b = res.ToBeatmap(rulesets); - requestedBeatmap.BeatmapSet.Metrics = b.BeatmapSet.Metrics; + if (requestedBeatmap.BeatmapSet == null) + requestedBeatmap.BeatmapSet = b.BeatmapSet; + else + requestedBeatmap.BeatmapSet.Metrics = b.BeatmapSet.Metrics; + requestedBeatmap.Metrics = b.Metrics; - Schedule(() => updateMetrics(requestedBeatmap)); + Schedule(() => updateMetrics(b.BeatmapSet.Metrics, b.Metrics)); }; - lookup.Failure += e => Schedule(() => updateMetrics()); + + lookup.Failure += e => Schedule(() => updateMetrics(Beatmap?.BeatmapSet?.Metrics, Beatmap?.Metrics)); + api.Queue(lookup); loading.Show(); return; } - updateMetrics(); + updateMetrics(Beatmap?.BeatmapSet?.Metrics, Beatmap?.Metrics); } - private void updateMetrics(BeatmapInfo beatmap = null) + private void updateMetrics(BeatmapSetMetrics setMetrics, BeatmapMetrics beatmapMetrics) { - var hasRatings = beatmap?.BeatmapSet?.Metrics?.Ratings?.Any() ?? false; - var hasRetriesFails = (beatmap?.Metrics?.Retries?.Any() ?? false) && (beatmap.Metrics.Fails?.Any() ?? false); + var hasRatings = setMetrics?.Ratings?.Any() ?? false; + var hasRetriesFails = (beatmapMetrics?.Retries?.Any() ?? false) && (beatmapMetrics.Fails?.Any() ?? false); if (hasRatings) { - ratings.Metrics = beatmap.BeatmapSet.Metrics; + ratings.Metrics = setMetrics; ratingsContainer.FadeIn(transition_duration); } else @@ -236,7 +243,7 @@ namespace osu.Game.Screens.Select if (hasRetriesFails) { - failRetryGraph.Metrics = beatmap.Metrics; + failRetryGraph.Metrics = beatmapMetrics; failRetryContainer.FadeIn(transition_duration); } else From 89c68c78d1b74a65e4295a0a54fdb34c9bc079b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Jun 2019 18:06:24 +0900 Subject: [PATCH 1220/5608] Reduce size of paths --- .../Screens/Ladder/Components/ProgressionPath.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs index ddf41b0117..5468844f66 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs @@ -25,6 +25,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components protected override void LoadComplete() { base.LoadComplete(); + Vector2 getCenteredVector(Vector2 top, Vector2 bottom) => new Vector2(top.X, top.Y + (bottom.Y - top.Y) / 2); var q1 = Source.ScreenSpaceDrawQuad; @@ -56,7 +57,15 @@ namespace osu.Game.Tournament.Screens.Ladder.Components var p3 = new Vector2(p2.X, c2.Y); var p4 = new Vector2(c2.X, p3.Y); - Vertices = new[] { p1, p2, p3, p4 }.Select(ToLocalSpace).ToList(); + var points = new[] { p1, p2, p3, p4 }; + + float minX = points.Min(p => p.X); + float minY = points.Min(p => p.Y); + + var topLeft = new Vector2(minX, minY); + + Position = Parent.ToLocalSpace(topLeft); + Vertices = points.Select(p => Parent.ToLocalSpace(p) - Parent.ToLocalSpace(topLeft)).ToList(); } } } From 72f729cf3b99dc2c3ab1d680d200b35b104db753 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 18:14:57 +0900 Subject: [PATCH 1221/5608] Refactor beatmap set overlay test scene --- .../Online/TestSceneBeatmapSetOverlay.cs | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 38388218c2..fb2d4efc68 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -41,6 +41,9 @@ namespace osu.Game.Tests.Visual.Online typeof(SuccessRate), }; + private RulesetInfo maniaRuleset; + private RulesetInfo taikoRuleset; + public TestSceneBeatmapSetOverlay() { Add(overlay = new BeatmapSetOverlay()); @@ -49,13 +52,25 @@ namespace osu.Game.Tests.Visual.Online [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - var mania = rulesets.GetRuleset(3); - var taiko = rulesets.GetRuleset(1); + maniaRuleset = rulesets.GetRuleset(3); + taikoRuleset = rulesets.GetRuleset(1); + } + [Test] + public void TestLoading() + { AddStep(@"show loading", () => overlay.ShowBeatmapSet(null)); + } + [Test] + public void TestOnline() + { AddStep(@"show online", () => overlay.FetchAndShowBeatmapSet(55)); + } + [Test] + public void TestLocalBeatmaps() + { AddStep(@"show first", () => { overlay.ShowBeatmapSet(new BeatmapSetInfo @@ -94,7 +109,7 @@ namespace osu.Game.Tests.Visual.Online { StarDifficulty = 1.36, Version = @"BASIC", - Ruleset = mania, + Ruleset = maniaRuleset, BaseDifficulty = new BeatmapDifficulty { CircleSize = 4, @@ -120,7 +135,7 @@ namespace osu.Game.Tests.Visual.Online { StarDifficulty = 2.22, Version = @"NOVICE", - Ruleset = mania, + Ruleset = maniaRuleset, BaseDifficulty = new BeatmapDifficulty { CircleSize = 4, @@ -146,7 +161,7 @@ namespace osu.Game.Tests.Visual.Online { StarDifficulty = 3.49, Version = @"ADVANCED", - Ruleset = mania, + Ruleset = maniaRuleset, BaseDifficulty = new BeatmapDifficulty { CircleSize = 4, @@ -172,7 +187,7 @@ namespace osu.Game.Tests.Visual.Online { StarDifficulty = 4.24, Version = @"EXHAUST", - Ruleset = mania, + Ruleset = maniaRuleset, BaseDifficulty = new BeatmapDifficulty { CircleSize = 4, @@ -198,7 +213,7 @@ namespace osu.Game.Tests.Visual.Online { StarDifficulty = 5.26, Version = @"GRAVITY", - Ruleset = mania, + Ruleset = maniaRuleset, BaseDifficulty = new BeatmapDifficulty { CircleSize = 4, @@ -261,7 +276,7 @@ namespace osu.Game.Tests.Visual.Online { StarDifficulty = 1.40, Version = @"yzrin's Kantan", - Ruleset = taiko, + Ruleset = taikoRuleset, BaseDifficulty = new BeatmapDifficulty { CircleSize = 2, @@ -287,7 +302,7 @@ namespace osu.Game.Tests.Visual.Online { StarDifficulty = 2.23, Version = @"Futsuu", - Ruleset = taiko, + Ruleset = taikoRuleset, BaseDifficulty = new BeatmapDifficulty { CircleSize = 2, @@ -313,7 +328,7 @@ namespace osu.Game.Tests.Visual.Online { StarDifficulty = 3.19, Version = @"Muzukashii", - Ruleset = taiko, + Ruleset = taikoRuleset, BaseDifficulty = new BeatmapDifficulty { CircleSize = 2, @@ -339,7 +354,7 @@ namespace osu.Game.Tests.Visual.Online { StarDifficulty = 3.97, Version = @"Charlotte's Oni", - Ruleset = taiko, + Ruleset = taikoRuleset, BaseDifficulty = new BeatmapDifficulty { CircleSize = 5, @@ -365,7 +380,7 @@ namespace osu.Game.Tests.Visual.Online { StarDifficulty = 5.08, Version = @"Labyrinth Oni", - Ruleset = taiko, + Ruleset = taikoRuleset, BaseDifficulty = new BeatmapDifficulty { CircleSize = 5, @@ -390,8 +405,17 @@ namespace osu.Game.Tests.Visual.Online }, }); }); + } + [Test] + public void TestHide() + { AddStep(@"hide", overlay.Hide); + } + + [Test] + public void TestShowWithNoReload() + { AddStep(@"show without reload", overlay.Show); } } From 7af2d650cd4eb8d3533c645735dda07821e87d87 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 18:31:12 +0900 Subject: [PATCH 1222/5608] Fix potential nullref --- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 8ed52dade5..6a583baf38 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -50,7 +50,7 @@ namespace osu.Game.Overlays.BeatmapSet private void updateDisplay() { - bpm.Value = BeatmapSet?.OnlineInfo.BPM.ToString(@"0.##") ?? "-"; + bpm.Value = BeatmapSet?.OnlineInfo?.BPM.ToString(@"0.##") ?? "-"; if (beatmap == null) { From f2b5f274cff2d88869be2f4720eb757914eb6010 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 18:31:39 +0900 Subject: [PATCH 1223/5608] Add details test scene + fix metrics not getting updated correctly --- .../TestSceneBeatmapSetOverlayDetails.cs | 68 +++++++++++++++++++ osu.Game/Overlays/BeatmapSet/Details.cs | 9 +-- 2 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs new file mode 100644 index 0000000000..f7009f9df3 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs @@ -0,0 +1,68 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Overlays.BeatmapSet; +using osu.Game.Screens.Select.Details; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneBeatmapSetOverlayDetails : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(Details) + }; + + private RatingsExposingDetails details; + + [SetUp] + public void Setup() => Schedule(() => + { + Child = details = new RatingsExposingDetails + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }; + }); + + [Test] + public void TestMetrics() + { + var firstSet = createSet(); + var secondSet = createSet(); + + AddStep("set first set", () => details.BeatmapSet = firstSet); + AddAssert("ratings set", () => details.Ratings.Metrics == firstSet.Metrics); + + AddStep("set second set", () => details.BeatmapSet = secondSet); + AddAssert("ratings set", () => details.Ratings.Metrics == secondSet.Metrics); + + BeatmapSetInfo createSet() => new BeatmapSetInfo + { + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, + Beatmaps = new List + { + new BeatmapInfo + { + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + } + } + } + }; + } + + private class RatingsExposingDetails : Details + { + public new UserRatings Ratings => base.Ratings; + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index 55e9500859..d76f6a43db 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -16,10 +16,11 @@ namespace osu.Game.Overlays.BeatmapSet { public class Details : FillFlowContainer { + protected readonly UserRatings Ratings; + private readonly PreviewButton preview; private readonly BasicStats basic; private readonly AdvancedStats advanced; - private readonly UserRatings ratings; private BeatmapSetInfo beatmapSet; @@ -33,6 +34,7 @@ namespace osu.Game.Overlays.BeatmapSet beatmapSet = value; basic.BeatmapSet = preview.BeatmapSet = BeatmapSet; + updateDisplay(); } } @@ -46,13 +48,12 @@ namespace osu.Game.Overlays.BeatmapSet if (value == beatmap) return; basic.Beatmap = advanced.Beatmap = beatmap = value; - updateDisplay(); } } private void updateDisplay() { - ratings.Metrics = BeatmapSet?.Metrics; + Ratings.Metrics = BeatmapSet?.Metrics; } public Details() @@ -87,7 +88,7 @@ namespace osu.Game.Overlays.BeatmapSet }, new DetailBox { - Child = ratings = new UserRatings + Child = Ratings = new UserRatings { RelativeSizeAxes = Axes.X, Height = 95, From f9f32311b7cc0d9162c7e0690a65d77b6395f469 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 18:43:44 +0900 Subject: [PATCH 1224/5608] Add some randomness --- .../Visual/Online/TestSceneBeatmapSetOverlayDetails.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs index f7009f9df3..2a45e68c0a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Overlays.BeatmapSet; using osu.Game.Screens.Select.Details; @@ -45,15 +46,15 @@ namespace osu.Game.Tests.Visual.Online BeatmapSetInfo createSet() => new BeatmapSetInfo { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).Select(_ => RNG.Next(10)).ToArray() }, Beatmaps = new List { new BeatmapInfo { Metrics = new BeatmapMetrics { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + Fails = Enumerable.Range(1, 100).Select(_ => RNG.Next(10)).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(_ => RNG.Next(10)).ToArray(), } } } From 6b615d763aa5c6cc285b159e3f8e110ce3e34902 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 18:43:51 +0900 Subject: [PATCH 1225/5608] Fix potential nullref --- osu.Game/Overlays/BeatmapSet/SuccessRate.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs index c89bddca63..c0e749b117 100644 --- a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs +++ b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs @@ -37,8 +37,8 @@ namespace osu.Game.Overlays.BeatmapSet private void updateDisplay() { - int passCount = beatmap?.OnlineInfo.PassCount ?? 0; - int playCount = beatmap?.OnlineInfo.PlayCount ?? 0; + int passCount = beatmap?.OnlineInfo?.PassCount ?? 0; + int playCount = beatmap?.OnlineInfo?.PlayCount ?? 0; var rate = playCount != 0 ? (float)passCount / playCount : 0; successPercent.Text = rate.ToString("P0"); From 39f9deea9640a8ee58d8cbf5a461d89963b41a73 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 18:44:00 +0900 Subject: [PATCH 1226/5608] Add success rate test scene --- .../TestSceneBeatmapSetOverlaySuccessRate.cs | 82 +++++++++++++++++++ osu.Game/Overlays/BeatmapSet/SuccessRate.cs | 9 +- 2 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs new file mode 100644 index 0000000000..05f5c117e4 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs @@ -0,0 +1,82 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.MathUtils; +using osu.Game.Beatmaps; +using osu.Game.Overlays.BeatmapSet; +using osu.Game.Screens.Select.Details; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneBeatmapSetOverlaySuccessRate : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(Details) + }; + + private GraphExposingSuccessRate successRate; + + [SetUp] + public void Setup() => Schedule(() => + { + Child = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(275, 220), + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray, + }, + successRate = new GraphExposingSuccessRate + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(275, 220), + Padding = new MarginPadding(20) + } + } + }; + }); + + [Test] + public void TestMetrics() + { + var firstBeatmap = createBeatmap(); + var secondBeatmap = createBeatmap(); + + AddStep("set first set", () => successRate.Beatmap = firstBeatmap); + AddAssert("ratings set", () => successRate.Graph.Metrics == firstBeatmap.Metrics); + + AddStep("set second set", () => successRate.Beatmap = secondBeatmap); + AddAssert("ratings set", () => successRate.Graph.Metrics == secondBeatmap.Metrics); + + BeatmapInfo createBeatmap() => new BeatmapInfo + { + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(_ => RNG.Next(10)).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(_ => RNG.Next(10)).ToArray(), + } + }; + } + + private class GraphExposingSuccessRate : SuccessRate + { + public new FailRetryGraph Graph => base.Graph; + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs index c0e749b117..0258a0301a 100644 --- a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs +++ b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs @@ -14,11 +14,12 @@ namespace osu.Game.Overlays.BeatmapSet { public class SuccessRate : Container { + protected readonly FailRetryGraph Graph; + private readonly FillFlowContainer header; private readonly OsuSpriteText successRateLabel, successPercent, graphLabel; private readonly Bar successRate; private readonly Container percentContainer; - private readonly FailRetryGraph graph; private BeatmapInfo beatmap; @@ -45,7 +46,7 @@ namespace osu.Game.Overlays.BeatmapSet successRate.Length = rate; percentContainer.ResizeWidthTo(successRate.Length, 250, Easing.InOutCubic); - graph.Metrics = beatmap?.Metrics; + Graph.Metrics = beatmap?.Metrics; } public SuccessRate() @@ -94,7 +95,7 @@ namespace osu.Game.Overlays.BeatmapSet }, }, }, - graph = new FailRetryGraph + Graph = new FailRetryGraph { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -117,7 +118,7 @@ namespace osu.Game.Overlays.BeatmapSet { base.UpdateAfterChildren(); - graph.Padding = new MarginPadding { Top = header.DrawHeight }; + Graph.Padding = new MarginPadding { Top = header.DrawHeight }; } } } From 2ad4045b2eb7eadcc28bc1a1bb5507916147182e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 18:51:41 +0900 Subject: [PATCH 1227/5608] Refactor beatmap details testcase --- .../SongSelect/TestSceneBeatmapDetails.cs | 57 ++++++++++++------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index f4f3c2b8d1..64bad66919 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -1,26 +1,33 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.ComponentModel; +using System.Collections.Generic; using System.Linq; +using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.SongSelect { - [Description("PlaySongSelect beatmap details")] + [System.ComponentModel.Description("PlaySongSelect beatmap details")] public class TestSceneBeatmapDetails : OsuTestScene { - public TestSceneBeatmapDetails() + private BeatmapDetails details; + + [SetUp] + public void Setup() => Schedule(() => { - BeatmapDetails details; - Add(details = new BeatmapDetails + Child = details = new BeatmapDetails { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding(150), - }); + }; + }); + [Test] + public void TestAllMetrics() + { AddStep("all metrics", () => details.Beatmap = new BeatmapInfo { BeatmapSet = new BeatmapSetInfo @@ -47,7 +54,11 @@ namespace osu.Game.Tests.Visual.SongSelect Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }); + } + [Test] + public void TestAllMetricsExceptSource() + { AddStep("all except source", () => details.Beatmap = new BeatmapInfo { BeatmapSet = new BeatmapSetInfo @@ -73,7 +84,11 @@ namespace osu.Game.Tests.Visual.SongSelect Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }); + } + [Test] + public void TestOnlyRatings() + { AddStep("ratings", () => details.Beatmap = new BeatmapInfo { BeatmapSet = new BeatmapSetInfo @@ -95,7 +110,11 @@ namespace osu.Game.Tests.Visual.SongSelect }, StarDifficulty = 4.8f, }); + } + [Test] + public void TestOnlyFailsAndRetries() + { AddStep("fails retries", () => details.Beatmap = new BeatmapInfo { Version = "Only Retries and Fails", @@ -118,7 +137,11 @@ namespace osu.Game.Tests.Visual.SongSelect Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, }); + } + [Test] + public void TestNoMetrics() + { AddStep("no metrics", () => details.Beatmap = new BeatmapInfo { Version = "No Metrics", @@ -136,26 +159,20 @@ namespace osu.Game.Tests.Visual.SongSelect }, StarDifficulty = 1.97f, }); + } + [Test] + public void TestNullBeatmap() + { AddStep("null beatmap", () => details.Beatmap = null); + } + [Test] + public void TestOnlineMetrics() + { AddStep("online ratings/retries/fails", () => details.Beatmap = new BeatmapInfo { OnlineBeatmapID = 162, - Version = "online ratings/retries/fails", - Metadata = new BeatmapMetadata - { - Source = "osu!lazer", - Tags = "this beatmap has online ratings/retries/fails", - }, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 7, - DrainRate = 1, - OverallDifficulty = 5.7f, - ApproachRate = 3.5f, - }, - StarDifficulty = 5.3f }); } } From d744c900c240f0eb174b3aa604548109a06ba84e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Jun 2019 19:04:59 +0900 Subject: [PATCH 1228/5608] Fix incorrect unbind logic --- osu.Game/Overlays/Settings/SettingsItem.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 4b992d6179..ae840c8c00 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -63,7 +63,9 @@ namespace osu.Game.Overlays.Settings set { - controlWithCurrent?.Current.UnbindBindings(); + if (bindable != null) + controlWithCurrent?.Current.UnbindFrom(bindable); + bindable = value; controlWithCurrent?.Current.BindTo(bindable); From ee9d82f0fef6573d8ba29bc96e0e27047151bd5c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Jun 2019 19:10:57 +0900 Subject: [PATCH 1229/5608] Revert right click handling for now --- osu.Game.Tournament/TournamentGameBase.cs | 30 +++++++++++++++++++++++ osu.Game/OsuGameBase.cs | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 739fabca9d..fd7a20ecb9 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -12,6 +12,7 @@ using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; +using osu.Framework.Input; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Game.Beatmaps; @@ -20,6 +21,7 @@ using osu.Game.Online.API.Requests; using osu.Game.Rulesets; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; +using osuTK.Input; namespace osu.Game.Tournament { @@ -250,5 +252,33 @@ namespace osu.Game.Tournament })); } } + + protected override UserInputManager CreateUserInputManager() => new TournamentInputManager(); + + private class TournamentInputManager : UserInputManager + { + protected override MouseButtonEventManager CreateButtonManagerFor(MouseButton button) + { + switch (button) + { + case MouseButton.Right: + return new RightMouseManager(button); + } + + return base.CreateButtonManagerFor(button); + } + + private class RightMouseManager : MouseButtonEventManager + { + public RightMouseManager(MouseButton button) + : base(button) + { + } + + public override bool EnableDrag => true; // allow right-mouse dragging for absolute scroll in scroll containers. + public override bool EnableClick => true; + public override bool ChangeFocusOnClick => false; + } + } } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 4c1266c3a6..637708a0e5 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -311,7 +311,7 @@ namespace osu.Game } public override bool EnableDrag => true; // allow right-mouse dragging for absolute scroll in scroll containers. - public override bool EnableClick => true; + public override bool EnableClick => false; public override bool ChangeFocusOnClick => false; } } From 389997dbc452ddebfe04930bb1294c89bf060a8f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 19:14:58 +0900 Subject: [PATCH 1230/5608] Fix metrics being populated with null ratings --- osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 05e647d107..00e08633dd 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -73,7 +73,7 @@ namespace osu.Game.Online.API.Requests.Responses OnlineBeatmapSetID = OnlineBeatmapSetID, Metadata = this, Status = Status, - Metrics = new BeatmapSetMetrics { Ratings = ratings }, + Metrics = ratings == null ? null : new BeatmapSetMetrics { Ratings = ratings }, OnlineInfo = new BeatmapSetOnlineInfo { Covers = covers, From d8ef18c56a8ffe04eee42e3fde14394f8a267316 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Jun 2019 19:16:19 +0900 Subject: [PATCH 1231/5608] Remove unused using --- osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index 64bad66919..acf037198f 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.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.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; From 9e4f2c7eb9ce3f600f910bf544edfdaa591b4dad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Jun 2019 19:41:01 +0900 Subject: [PATCH 1232/5608] Move font local --- .../Gameplay/Components/MatchHeader.cs | 4 +- .../Gameplay/Components/MatchScoreDisplay.cs | 4 +- .../Screens/TeamIntro/TeamIntroScreen.cs | 4 +- .../Screens/TeamWin/TeamWinScreen.cs | 8 +-- osu.Game.Tournament/TournamentFont.cs | 70 +++++++++++++++++++ osu.Game.Tournament/TournamentGame.cs | 28 ++++++++ osu.Game/Graphics/OsuFont.cs | 6 +- 7 files changed, 109 insertions(+), 15 deletions(-) create mode 100644 osu.Game.Tournament/TournamentFont.cs diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index 22aa6995cf..f9ec16c357 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -176,7 +176,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components X = (flip ? -1 : 1) * 90, Y = -10, Colour = colour, - Font = OsuFont.GetFont(typeface: Typeface.Aquatico, weight: FontWeight.Regular, size: 20), + Font = TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Regular, size: 20), Origin = anchor, Anchor = anchor, }, @@ -219,7 +219,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components Origin = Anchor.Centre, Colour = Color4.White, Text = match.NewValue.Grouping.Value?.Name.Value ?? "Unknown Grouping", - Font = OsuFont.GetFont(typeface: Typeface.Aquatico, weight: FontWeight.Regular, size: 18), + Font = TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Regular, size: 18), }, }; } diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs index 62a785398f..fc28ddccfd 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs @@ -122,8 +122,8 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components public bool Winning { set => DisplayedCountSpriteText.Font = value - ? OsuFont.GetFont(typeface: Typeface.Aquatico, weight: FontWeight.Regular, size: 60) - : OsuFont.GetFont(typeface: Typeface.Aquatico, weight: FontWeight.Light, size: 40); + ? TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Regular, size: 60) + : TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Light, size: 40); } } } diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 7000d776f0..1efe667eaa 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -200,7 +200,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro new OsuSpriteText { Text = team?.FullName.ToUpper() ?? "???", - Font = OsuFont.GetFont(Typeface.Aquatico, 40, FontWeight.Light), + Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 40, FontWeight.Light), Colour = Color4.Black, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, @@ -208,7 +208,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro new OsuSpriteText { Text = teamName.ToUpper(), - Font = OsuFont.GetFont(Typeface.Aquatico, 20, FontWeight.Regular), + Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 20, FontWeight.Regular), Colour = colour, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs index 69c088efbc..6d5f7e7ad5 100644 --- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -127,7 +127,7 @@ namespace osu.Game.Tournament.Screens.TeamWin Origin = Anchor.TopCentre, Colour = col, Text = "WINNER", - Font = OsuFont.GetFont(Typeface.Aquatico, 15, FontWeight.Regular), + Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 15, FontWeight.Regular), }, new OsuSpriteText { @@ -135,7 +135,7 @@ namespace osu.Game.Tournament.Screens.TeamWin Origin = Anchor.TopCentre, Colour = col, Text = pairing.Grouping.Value?.Name.Value ?? "Unknown Grouping", - Font = OsuFont.GetFont(Typeface.Aquatico, 50, FontWeight.Light), + Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 50, FontWeight.Light), Spacing = new Vector2(10, 0), }, new OsuSpriteText @@ -144,7 +144,7 @@ namespace osu.Game.Tournament.Screens.TeamWin Origin = Anchor.TopCentre, Colour = col, Text = pairing.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"), - Font = OsuFont.GetFont(Typeface.Aquatico, 20, FontWeight.Light), + Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 20, FontWeight.Light), }, } } @@ -204,7 +204,7 @@ namespace osu.Game.Tournament.Screens.TeamWin new OsuSpriteText { Text = team?.FullName.ToUpper() ?? "???", - Font = OsuFont.GetFont(Typeface.Aquatico, 40, FontWeight.Light), + Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 40, FontWeight.Light), Colour = Color4.Black, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, diff --git a/osu.Game.Tournament/TournamentFont.cs b/osu.Game.Tournament/TournamentFont.cs new file mode 100644 index 0000000000..d2925d7632 --- /dev/null +++ b/osu.Game.Tournament/TournamentFont.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 osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; + +namespace osu.Game.Tournament +{ + public static class TournamentFont + { + /// + /// The default font size. + /// + public const float DEFAULT_FONT_SIZE = 16; + + /// + /// Retrieves a . + /// + /// The font typeface. + /// The size of the text in local space. For a value of 16, a single line will have a height of 16px. + /// The font weight. + /// Whether the font is italic. + /// Whether all characters should be spaced the same distance apart. + /// The . + public static FontUsage GetFont(TournamentTypeface typeface = TournamentTypeface.Aquatico, float size = DEFAULT_FONT_SIZE, FontWeight weight = FontWeight.Medium, bool italics = false, bool fixedWidth = false) + => new FontUsage(GetFamilyString(typeface), size, GetWeightString(typeface, weight), italics, fixedWidth); + + /// + /// Retrieves the string representation of a . + /// + /// The . + /// The string representation. + public static string GetFamilyString(TournamentTypeface typeface) + { + switch (typeface) + { + case TournamentTypeface.Aquatico: + return "Aquatico"; + } + + return null; + } + + /// + /// Retrieves the string representation of a . + /// + /// The . + /// The . + /// The string representation of in the specified . + public static string GetWeightString(TournamentTypeface typeface, FontWeight weight) + => GetWeightString(GetFamilyString(typeface), weight); + + /// + /// Retrieves the string representation of a . + /// + /// The family string. + /// The . + /// The string representation of in the specified . + public static string GetWeightString(string family, FontWeight weight) + { + string weightString = weight.ToString(); + + // Only exo has an explicit "regular" weight, other fonts do not + if (weight == FontWeight.Regular && family != GetFamilyString(TournamentTypeface.Aquatico) && family != GetFamilyString(TournamentTypeface.Aquatico)) + weightString = string.Empty; + + return weightString; + } + } +} diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index bb5682bb42..0f142e4d74 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -2,7 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; using osu.Framework.Screens; +using osu.Game.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Tournament.Screens; @@ -23,4 +25,30 @@ namespace osu.Game.Tournament MenuCursorContainer.Cursor.Alpha = 0; } } + + public static class TournamentFontExtensions + { + /// + /// Creates a new by applying adjustments to this . + /// + /// The base . + /// The font typeface. If null, the value is copied from this . + /// The text size. If null, the value is copied from this . + /// The font weight. If null, the value is copied from this . + /// Whether the font is italic. If null, the value is copied from this . + /// Whether all characters should be spaced apart the same distance. If null, the value is copied from this . + /// The resulting . + public static FontUsage With(this FontUsage usage, TournamentTypeface? typeface = null, float? size = null, FontWeight? weight = null, bool? italics = null, bool? fixedWidth = null) + { + string familyString = typeface != null ? TournamentFont.GetFamilyString(typeface.Value) : usage.Family; + string weightString = weight != null ? TournamentFont.GetWeightString(familyString, weight.Value) : usage.Weight; + + return usage.With(familyString, size, weightString, italics, fixedWidth); + } + } + + public enum TournamentTypeface + { + Aquatico + } } diff --git a/osu.Game/Graphics/OsuFont.cs b/osu.Game/Graphics/OsuFont.cs index 6c4b46c3ad..2c2f075563 100644 --- a/osu.Game/Graphics/OsuFont.cs +++ b/osu.Game/Graphics/OsuFont.cs @@ -45,9 +45,6 @@ namespace osu.Game.Graphics case Typeface.Venera: return "Venera"; - - case Typeface.Aquatico: - return "Aquatico"; } return null; @@ -73,7 +70,7 @@ namespace osu.Game.Graphics string weightString = weight.ToString(); // Only exo has an explicit "regular" weight, other fonts do not - if (weight == FontWeight.Regular && family != GetFamilyString(Typeface.Exo) && family != GetFamilyString(Typeface.Aquatico)) + if (weight == FontWeight.Regular && family != GetFamilyString(Typeface.Exo)) weightString = string.Empty; return weightString; @@ -105,7 +102,6 @@ namespace osu.Game.Graphics { Exo, Venera, - Aquatico // tournament use only } public enum FontWeight From 52c7ed99607028bef24a0f13073638866e09931f Mon Sep 17 00:00:00 2001 From: naoey Date: Thu, 13 Jun 2019 16:16:48 +0530 Subject: [PATCH 1233/5608] Add ability to change the flie extension of API download requests --- osu.Game/Online/API/APIDownloadRequest.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIDownloadRequest.cs b/osu.Game/Online/API/APIDownloadRequest.cs index efc832a71e..a8f768553b 100644 --- a/osu.Game/Online/API/APIDownloadRequest.cs +++ b/osu.Game/Online/API/APIDownloadRequest.cs @@ -10,9 +10,18 @@ namespace osu.Game.Online.API { private string filename; + /// + /// Sets the extension of the file outputted by this request. + /// + protected virtual string FileExtension { get; } = @".tmp"; + protected override WebRequest CreateWebRequest() { - var request = new FileWebRequest(filename = Path.GetTempFileName(), Uri); + var file = Path.GetTempFileName(); + + File.Move(file, filename = Path.ChangeExtension(file, FileExtension)); + + var request = new FileWebRequest(filename, Uri); request.DownloadProgress += request_Progress; return request; } From aa7cae0879be9a0ca5ffb51f9f2af1c9fbab227e Mon Sep 17 00:00:00 2001 From: naoey Date: Thu, 13 Jun 2019 16:55:41 +0530 Subject: [PATCH 1234/5608] Rephrase xmldoc --- osu.Game/Online/API/APIDownloadRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIDownloadRequest.cs b/osu.Game/Online/API/APIDownloadRequest.cs index a8f768553b..940b9b4803 100644 --- a/osu.Game/Online/API/APIDownloadRequest.cs +++ b/osu.Game/Online/API/APIDownloadRequest.cs @@ -11,7 +11,7 @@ namespace osu.Game.Online.API private string filename; /// - /// Sets the extension of the file outputted by this request. + /// Used to set the extension of the file returned by this request. /// protected virtual string FileExtension { get; } = @".tmp"; From 155f7c7e03541a3e8f825a6c6ce229f015c0d78d Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Thu, 13 Jun 2019 17:32:27 +0300 Subject: [PATCH 1235/5608] Use OsuTextFlowContainer for multi-lines --- .../BeatmapSet/BeatmapNotAvailable.cs | 26 +++++++------------ osu.Game/Overlays/BeatmapSet/Header.cs | 2 +- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs b/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs index 31ed0d9396..59ac8ce6e2 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapNotAvailable.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet @@ -29,47 +28,42 @@ namespace osu.Game.Overlays.BeatmapSet removeLinks(); if (beatmapSet?.OnlineInfo.Availability != null) - { - Header?.ResizeHeightTo(450, 500); Show(); - } else - { - Header?.ResizeHeightTo(400, 500); Hide(); - } } } - public Header Header; - - private readonly OsuSpriteText text; + private readonly OsuTextFlowContainer text; private readonly LinkFlowContainer link; public BeatmapNotAvailable() { - AutoSizeAxes = Axes.Both; - Margin = new MarginPadding { Top = 10 }; + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Padding = new MarginPadding { Top = 10, Right = 20 }; Children = new Drawable[] { new Box { - Colour = Color4.Black.Opacity(0.6f), RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0.6f), }, new FillFlowContainer { - AutoSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, Margin = new MarginPadding { Top = 10, Left = 5, Right = 20 }, Children = new Drawable[] { - text = new OsuSpriteText + text = new OsuTextFlowContainer(t => t.Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium)) { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Margin = new MarginPadding { Bottom = 10, Horizontal = 5 }, - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium), Colour = Color4.Orange, }, link = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: 14)) diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index a53b4a2e68..0f3ce008cf 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -135,7 +135,7 @@ namespace osu.Game.Overlays.BeatmapSet Margin = new MarginPadding { Top = 20 }, Child = author = new AuthorInfo(), }, - beatmapNotAvailable = new BeatmapNotAvailable { Header = this }, + beatmapNotAvailable = new BeatmapNotAvailable(), new Container { RelativeSizeAxes = Axes.X, From 3c2a2b23901baad45667c3fddbe044a1c0da7339 Mon Sep 17 00:00:00 2001 From: naoey Date: Thu, 13 Jun 2019 21:28:32 +0530 Subject: [PATCH 1236/5608] Move doc to interface --- osu.Game/Database/DownloadableArchiveModelManager.cs | 5 ----- osu.Game/Database/IModelDownloader.cs | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Database/DownloadableArchiveModelManager.cs b/osu.Game/Database/DownloadableArchiveModelManager.cs index 0735452ce3..fc50a4720a 100644 --- a/osu.Game/Database/DownloadableArchiveModelManager.cs +++ b/osu.Game/Database/DownloadableArchiveModelManager.cs @@ -72,11 +72,6 @@ namespace osu.Game.Database return true; } - /// - /// Checks whether a given is available in the local store already. - /// - /// The whose existence needs to be checked. - /// Whether the exists locally. public virtual bool IsAvailableLocally(TModel model) => modelStore.ConsumableItems.Any(m => m.Equals(model) && !m.DeletePending); public ArchiveDownloadRequest GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Model.Equals(model)); diff --git a/osu.Game/Database/IModelDownloader.cs b/osu.Game/Database/IModelDownloader.cs index 42c64ba67b..b4f8c1e24a 100644 --- a/osu.Game/Database/IModelDownloader.cs +++ b/osu.Game/Database/IModelDownloader.cs @@ -23,6 +23,12 @@ namespace osu.Game.Database /// event Action> DownloadFailed; + + /// + /// Checks whether a given is already available in the local store. + /// + /// The whose existence needs to be checked. + /// Whether the exists. bool IsAvailableLocally(TModel model); /// From 4f0aff3d9c2ad06df4c0197644f51cf6ec63df0c Mon Sep 17 00:00:00 2001 From: andy840119 Date: Fri, 14 Jun 2019 01:12:56 +0900 Subject: [PATCH 1237/5608] hide label when mod is empty --- osu.Game/Overlays/Mods/ModSection.cs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 50400e254f..9d9bb2ba6e 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -50,6 +50,34 @@ namespace osu.Game.Overlays.Mods ButtonsContainer.Children = modContainers; buttons = modContainers.OfType().ToArray(); + + Expanded = value.Any(); + } + } + + private bool expanded = true; + + public bool Expanded + { + set + { + if (expanded == value) return; + + expanded = value; + + this.ClearTransforms(); + + if (expanded) + { + this.AutoSizeAxes = Axes.Y; + this.headerLabel.FadeIn(200); + } + else + { + this.AutoSizeAxes = Axes.None; + this.headerLabel.FadeOut(200); + this.ResizeHeightTo(0, 200, Easing.OutQuint); + } } } From 3a14794c431a1fb13a09b5e3ec5eb77e586006ef Mon Sep 17 00:00:00 2001 From: andy840119 Date: Fri, 14 Jun 2019 01:43:20 +0900 Subject: [PATCH 1238/5608] use show/hide instead because FillFlowContainer's spacing --- osu.Game/Overlays/Mods/ModSection.cs | 19 +++---------------- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 ++ 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 9d9bb2ba6e..7b032f1fcf 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -51,32 +51,19 @@ namespace osu.Game.Overlays.Mods ButtonsContainer.Children = modContainers; buttons = modContainers.OfType().ToArray(); - Expanded = value.Any(); - } - } - - private bool expanded = true; - - public bool Expanded - { - set - { - if (expanded == value) return; - - expanded = value; - - this.ClearTransforms(); + var expanded = value.Any(); if (expanded) { this.AutoSizeAxes = Axes.Y; this.headerLabel.FadeIn(200); + Show(); } else { this.AutoSizeAxes = Axes.None; this.headerLabel.FadeOut(200); - this.ResizeHeightTo(0, 200, Easing.OutQuint); + this.ResizeHeightTo(0, 200, Easing.OutQuint).OnComplete((c) => Hide()); } } } diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 8e5c9588ce..9ff320841a 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -172,6 +172,8 @@ namespace osu.Game.Overlays.Mods AutoSizeAxes = Axes.Y, Spacing = new Vector2(0f, 10f), Width = content_width, + LayoutDuration = 200, + LayoutEasing = Easing.OutQuint, Children = new ModSection[] { new DifficultyReductionSection { Action = modButtonPressed }, From c30e4677179f426e066175f62b84cc6b49fd86c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=82=BA=E4=BB=80=E9=BA=BC?= Date: Fri, 14 Jun 2019 11:12:30 +0800 Subject: [PATCH 1239/5608] oops --- osu.Game/Overlays/Mods/ModSection.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 7b032f1fcf..07b1c53b3b 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -55,15 +55,15 @@ namespace osu.Game.Overlays.Mods if (expanded) { - this.AutoSizeAxes = Axes.Y; - this.headerLabel.FadeIn(200); + AutoSizeAxes = Axes.Y; + headerLabel.FadeIn(200); Show(); } else { - this.AutoSizeAxes = Axes.None; - this.headerLabel.FadeOut(200); - this.ResizeHeightTo(0, 200, Easing.OutQuint).OnComplete((c) => Hide()); + AutoSizeAxes = Axes.None; + headerLabel.FadeOut(200); + this.ResizeHeightTo(0, 200, Easing.OutQuint).OnComplete(c => Hide()); } } } From 0db9816321c893c5cdb073e763819f83c1ed0a56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=82=BA=E4=BB=80=E9=BA=BC?= Date: Fri, 14 Jun 2019 11:23:41 +0800 Subject: [PATCH 1240/5608] expanded -> expand --- osu.Game/Overlays/Mods/ModSection.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 07b1c53b3b..34dede62de 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -51,9 +51,9 @@ namespace osu.Game.Overlays.Mods ButtonsContainer.Children = modContainers; buttons = modContainers.OfType().ToArray(); - var expanded = value.Any(); + var expand = value.Any(); - if (expanded) + if (expand) { AutoSizeAxes = Axes.Y; headerLabel.FadeIn(200); From 9114c8dee7ee96f1a6bb81fcc3312350f8c54e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=82=BA=E4=BB=80=E9=BA=BC?= Date: Fri, 14 Jun 2019 11:44:03 +0800 Subject: [PATCH 1241/5608] remve unnecessary effect. --- osu.Game/Overlays/Mods/ModSection.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 34dede62de..c110f58b7a 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -55,15 +55,13 @@ namespace osu.Game.Overlays.Mods if (expand) { - AutoSizeAxes = Axes.Y; headerLabel.FadeIn(200); Show(); } else { - AutoSizeAxes = Axes.None; headerLabel.FadeOut(200); - this.ResizeHeightTo(0, 200, Easing.OutQuint).OnComplete(c => Hide()); + Hide(); } } } From 15b9b53d35b0c7c7e4a46b5efc5f89022bf224f1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 13:40:32 +0900 Subject: [PATCH 1242/5608] Fix IconButtons not being scaled correctly --- .../UserInterface/TestSceneIconButton.cs | 13 +++---------- .../UserInterface/TestSceneMusicController.cs | 3 +-- osu.Game/Graphics/UserInterface/IconButton.cs | 19 ++----------------- osu.Game/Overlays/MusicController.cs | 14 ++++++++++++++ .../Compose/Components/BeatDivisorControl.cs | 2 +- .../Components/Timeline/TimelineButton.cs | 4 ++-- 6 files changed, 23 insertions(+), 32 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs index 0c9ce50288..c80b3e6297 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs @@ -26,8 +26,7 @@ namespace osu.Game.Tests.Visual.UserInterface { new NamedIconButton("No change", new IconButton()), new NamedIconButton("Background colours", new ColouredIconButton()), - new NamedIconButton("Full-width", new IconButton { ButtonSize = new Vector2(200, 30) }), - new NamedIconButton("Unchanging size", new IconButton(), false), + new NamedIconButton("Full-width", new IconButton { Size = new Vector2(200, 30) }), new NamedIconButton("Icon colours", new IconButton { IconColour = Color4.Green, @@ -48,7 +47,7 @@ namespace osu.Game.Tests.Visual.UserInterface private class NamedIconButton : Container { - public NamedIconButton(string name, IconButton button, bool allowSizeChange = true) + public NamedIconButton(string name, IconButton button) { AutoSizeAxes = Axes.Y; Width = 200; @@ -101,13 +100,7 @@ namespace osu.Game.Tests.Visual.UserInterface } }; - if (allowSizeChange) - iconContainer.AutoSizeAxes = Axes.Both; - else - { - iconContainer.RelativeSizeAxes = Axes.X; - iconContainer.Height = 30; - } + iconContainer.AutoSizeAxes = Axes.Both; button.Anchor = Anchor.Centre; button.Origin = Anchor.Centre; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs index 2f2a40925f..ab2ca47100 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs @@ -3,7 +3,6 @@ using NUnit.Framework; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Overlays; @@ -23,9 +22,9 @@ namespace osu.Game.Tests.Visual.UserInterface }; Add(mc); - AddToggleStep(@"toggle visibility", state => mc.State.Value = state ? Visibility.Visible : Visibility.Hidden); AddStep(@"show", () => mc.Show()); AddToggleStep(@"toggle beatmap lock", state => Beatmap.Disabled = state); + AddStep(@"show", () => mc.Hide()); } } } diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs index 052e9194fa..27427581fd 100644 --- a/osu.Game/Graphics/UserInterface/IconButton.cs +++ b/osu.Game/Graphics/UserInterface/IconButton.cs @@ -11,7 +11,7 @@ namespace osu.Game.Graphics.UserInterface { public class IconButton : OsuAnimatedButton { - public const float BUTTON_SIZE = 30; + public const float DEFAULT_BUTTON_SIZE = 30; private Color4? iconColour; @@ -57,26 +57,11 @@ namespace osu.Game.Graphics.UserInterface set => icon.Scale = value; } - /// - /// The size of the while it is not being pressed. - /// - public Vector2 ButtonSize - { - get => Content.Size; - set - { - Content.RelativeSizeAxes = Axes.None; - Content.AutoSizeAxes = Axes.None; - Content.Size = value; - } - } - private readonly SpriteIcon icon; public IconButton() { - AutoSizeAxes = Axes.Both; - ButtonSize = new Vector2(BUTTON_SIZE); + Size = new Vector2(DEFAULT_BUTTON_SIZE); Add(icon = new SpriteIcon { diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 85524e992c..8b9bac877b 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -464,12 +464,26 @@ namespace osu.Game.Overlays private class MusicIconButton : IconButton { + public MusicIconButton() + { + AutoSizeAxes = Axes.Both; + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { HoverColour = colours.YellowDark.Opacity(0.6f); FlashColour = colours.Yellow; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + // works with AutoSizeAxes above to make buttons autosize with the scale animation. + Content.AutoSizeAxes = Axes.None; + Content.Size = new Vector2(DEFAULT_BUTTON_SIZE); + } } private class Background : BufferedContainer diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index ebf8c9c309..c615656d60 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -171,7 +171,7 @@ namespace osu.Game.Screens.Edit.Compose.Components // Small offset to look a bit better centered along with the divisor text Y = 1; - ButtonSize = new Vector2(20); + Size = new Vector2(20); IconScale = new Vector2(0.6f); } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs index 49e97e698b..8865bf31ea 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs @@ -31,14 +31,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline InternalChild = button = new TimelineIconButton { Action = () => Action?.Invoke() }; button.Enabled.BindTo(Enabled); - Width = button.ButtonSize.X; + Width = button.Width; } protected override void Update() { base.Update(); - button.ButtonSize = new Vector2(button.ButtonSize.X, DrawHeight); + button.Size = new Vector2(button.Width, DrawHeight); } private class TimelineIconButton : IconButton From bc574520bf3c0911fa942bdb954da2172e6915ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 15:55:32 +0900 Subject: [PATCH 1243/5608] Update ScrollContainer usages in line with framework changes --- .../Online/TestSceneHistoricalSection.cs | 4 +- .../TestSceneUserProfileRecentSection.cs | 3 +- .../Visual/Online/TestSceneUserRanks.cs | 3 +- .../Visual/UserInterface/TestSceneOsuIcon.cs | 3 +- ...tSceneUpdateableBeatmapBackgroundSprite.cs | 5 +- .../Graphics/Containers/OsuScrollContainer.cs | 94 ++++++++++++++++++- .../Graphics/Containers/SectionsContainer.cs | 4 +- osu.Game/Online/Leaderboards/Leaderboard.cs | 2 +- osu.Game/Overlays/BeatmapSetOverlay.cs | 4 +- osu.Game/Overlays/ChangelogOverlay.cs | 2 +- osu.Game/Overlays/Chat/DrawableChannel.cs | 2 +- osu.Game/Overlays/Settings/Sidebar.cs | 3 +- .../Timeline/ZoomableScrollContainer.cs | 3 +- .../Multi/Lounge/Components/RoomInspector.cs | 3 +- .../Screens/Multi/Lounge/LoungeSubScreen.cs | 3 +- .../Match/Components/MatchSettingsOverlay.cs | 3 +- .../Multi/Match/Components/Participants.cs | 3 +- osu.Game/Screens/Select/BeatmapDetails.cs | 4 +- 18 files changed, 125 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs index 455807649a..883f0c5e3f 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs @@ -5,9 +5,9 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Overlays.Profile.Sections; using osu.Game.Overlays.Profile.Sections.Historical; using osu.Game.Users; @@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.Online Colour = OsuColour.Gray(0.2f) }); - Add(new ScrollContainer + Add(new OsuScrollContainer { RelativeSizeAxes = Axes.Both, Child = section = new HistoricalSection(), diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs index d60e723102..f022425bf6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Profile.Sections; @@ -36,7 +37,7 @@ namespace osu.Game.Tests.Visual.Online RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.2f) }, - new ScrollContainer + new OsuScrollContainer { RelativeSizeAxes = Axes.Both, Child = new FillFlowContainer diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs index 70118b5ebd..9f0a8c769a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Overlays.Profile.Sections; using osu.Game.Overlays.Profile.Sections.Ranks; using osu.Game.Users; @@ -33,7 +34,7 @@ namespace osu.Game.Tests.Visual.Online RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.2f) }, - new ScrollContainer + new OsuScrollContainer { RelativeSizeAxes = Axes.Both, Child = ranks = new RanksSection(), diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs index 2c2a28394c..061039b297 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osuTK; using osuTK.Graphics; @@ -29,7 +30,7 @@ namespace osu.Game.Tests.Visual.UserInterface Colour = Color4.Teal, RelativeSizeAxes = Axes.Both, }, - new ScrollContainer + new OsuScrollContainer { RelativeSizeAxes = Axes.Both, Child = flow = new FillFlowContainer diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs index c361598354..9cdfcb6cc4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics.Containers; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Rulesets; @@ -92,13 +93,13 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestUnloadAndReload() { var backgrounds = new List(); - ScrollContainer scrollContainer = null; + OsuScrollContainer scrollContainer = null; AddStep("create backgrounds hierarchy", () => { FillFlowContainer backgroundFlow; - Child = scrollContainer = new ScrollContainer + Child = scrollContainer = new OsuScrollContainer { Size = new Vector2(500), Child = backgroundFlow = new FillFlowContainer diff --git a/osu.Game/Graphics/Containers/OsuScrollContainer.cs b/osu.Game/Graphics/Containers/OsuScrollContainer.cs index f7d406a419..53092ddc9e 100644 --- a/osu.Game/Graphics/Containers/OsuScrollContainer.cs +++ b/osu.Game/Graphics/Containers/OsuScrollContainer.cs @@ -1,13 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; +using osuTK; +using osuTK.Graphics; using osuTK.Input; namespace osu.Game.Graphics.Containers { - public class OsuScrollContainer : ScrollContainer + public class OsuScrollContainer : ScrollContainer { /// /// Allows controlling the scroll bar from any position in the container using the right mouse button. @@ -28,6 +33,11 @@ namespace osu.Game.Graphics.Containers protected override bool IsDragging => base.IsDragging || mouseScrollBarDragging; + public OsuScrollContainer(Direction scrollDirection = Direction.Vertical) + : base(scrollDirection) + { + } + protected override bool OnMouseDown(MouseDownEvent e) { if (shouldPerformRightMouseScroll(e)) @@ -71,5 +81,87 @@ namespace osu.Game.Graphics.Containers return base.OnDragEnd(e); } + + protected override ScrollbarContainer CreateScrollbar(Direction direction) => new OsuScrollbar(direction); + + protected class OsuScrollbar : ScrollbarContainer + { + private const float dim_size = 10; + + private Color4 hoverColour; + private Color4 defaultColour; + private Color4 highlightColour; + + private readonly Box box; + + public OsuScrollbar(Direction scrollDir) + : base(scrollDir) + { + Blending = BlendingMode.Additive; + + CornerRadius = 5; + + const float margin = 3; + + Margin = new MarginPadding + { + Left = scrollDir == Direction.Vertical ? margin : 0, + Right = scrollDir == Direction.Vertical ? margin : 0, + Top = scrollDir == Direction.Horizontal ? margin : 0, + Bottom = scrollDir == Direction.Horizontal ? margin : 0, + }; + + Masking = true; + Child = box = new Box { RelativeSizeAxes = Axes.Both }; + + ResizeTo(1); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = defaultColour = colours.Gray8; + hoverColour = colours.GrayF; + highlightColour = colours.Green; + } + + public override void ResizeTo(float val, int duration = 0, Easing easing = Easing.None) + { + Vector2 size = new Vector2(dim_size) + { + [(int)ScrollDirection] = val + }; + this.ResizeTo(size, duration, easing); + } + + protected override bool OnHover(HoverEvent e) + { + this.FadeColour(hoverColour, 100); + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + this.FadeColour(defaultColour, 100); + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + if (!base.OnMouseDown(e)) return false; + + //note that we are changing the colour of the box here as to not interfere with the hover effect. + box.FadeColour(highlightColour, 100); + return true; + } + + protected override bool OnMouseUp(MouseUpEvent e) + { + if (e.Button != MouseButton.Left) return false; + + box.FadeColour(Color4.White, 100); + + return base.OnMouseUp(e); + } + } } } diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index a8d0e03c01..9d886c457f 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -16,7 +16,7 @@ namespace osu.Game.Graphics.Containers where T : Drawable { private Drawable expandableHeader, fixedHeader, footer, headerBackground; - private readonly ScrollContainer scrollContainer; + private readonly OsuScrollContainer scrollContainer; private readonly Container headerBackgroundContainer; private readonly FlowContainer scrollContentContainer; @@ -124,7 +124,7 @@ namespace osu.Game.Graphics.Containers public SectionsContainer() { - AddInternal(scrollContainer = new ScrollContainer + AddInternal(scrollContainer = new OsuScrollContainer { RelativeSizeAxes = Axes.Both, Masking = true, diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 3ce71cccba..b91de93a4a 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -23,7 +23,7 @@ namespace osu.Game.Online.Leaderboards { private const double fade_duration = 300; - private readonly ScrollContainer scrollContainer; + private readonly OsuScrollContainer scrollContainer; private readonly Container placeholderContainer; private FillFlowContainer scrollFlow; diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index e0852a890c..1e687267a3 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -30,7 +30,7 @@ namespace osu.Game.Overlays private RulesetStore rulesets; - private readonly ScrollContainer scroll; + private readonly OsuScrollContainer scroll; private readonly Bindable beatmapSet = new Bindable(); @@ -49,7 +49,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.2f) }, - scroll = new ScrollContainer + scroll = new OsuScrollContainer { RelativeSizeAxes = Axes.Both, ScrollbarVisible = false, diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 67f195580e..7755c8a6a6 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -51,7 +51,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Colour = colour.PurpleDarkAlternative, }, - new ScrollContainer + new OsuScrollContainer { RelativeSizeAxes = Axes.Both, ScrollbarVisible = false, diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index aec78b962f..7d28df3210 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Chat { public readonly Channel Channel; protected readonly ChatLineContainer ChatLineFlow; - private readonly ScrollContainer scroll; + private readonly OsuScrollContainer scroll; public DrawableChannel(Channel channel) { diff --git a/osu.Game/Overlays/Settings/Sidebar.cs b/osu.Game/Overlays/Settings/Sidebar.cs index 3c18627f23..a80b7c1108 100644 --- a/osu.Game/Overlays/Settings/Sidebar.cs +++ b/osu.Game/Overlays/Settings/Sidebar.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.Threading; +using osu.Game.Graphics.Containers; using osu.Game.Overlays.Toolbar; namespace osu.Game.Overlays.Settings @@ -76,7 +77,7 @@ namespace osu.Game.Overlays.Settings return base.OnMouseMove(e); } - private class SidebarScrollContainer : ScrollContainer + private class SidebarScrollContainer : OsuScrollContainer { public SidebarScrollContainer() { diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index 829437d599..cffb6bedf3 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -7,11 +7,12 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Transforms; using osu.Framework.Input.Events; using osu.Framework.MathUtils; +using osu.Game.Graphics.Containers; using osuTK; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class ZoomableScrollContainer : ScrollContainer + public class ZoomableScrollContainer : OsuScrollContainer { /// /// The time to zoom into/out of a point. diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index d597e5bb0f..1a18f742a9 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.API; using osu.Game.Online.API.Requests; @@ -226,7 +227,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components { Padding = new MarginPadding { Horizontal = 10 }; - InternalChild = new ScrollContainer + InternalChild = new OsuScrollContainer { RelativeSizeAxes = Axes.Both, Child = fill = new FillFlowContainer diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index 7cbae611ea..7f8e690516 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Screens; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; @@ -43,7 +44,7 @@ namespace osu.Game.Screens.Multi.Lounge Width = 0.55f, Children = new Drawable[] { - new ScrollContainer + new OsuScrollContainer { RelativeSizeAxes = Axes.Both, ScrollbarOverlapsContent = false, diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 359b5824c0..410aaed788 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; @@ -91,7 +92,7 @@ namespace osu.Game.Screens.Multi.Match.Components { new Drawable[] { - new ScrollContainer + new OsuScrollContainer { Padding = new MarginPadding { diff --git a/osu.Game/Screens/Multi/Match/Components/Participants.cs b/osu.Game/Screens/Multi/Match/Components/Participants.cs index 09d25572ec..ad38ec6a99 100644 --- a/osu.Game/Screens/Multi/Match/Components/Participants.cs +++ b/osu.Game/Screens/Multi/Match/Components/Participants.cs @@ -5,6 +5,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Containers; using osu.Game.Overlays.SearchableList; using osu.Game.Screens.Multi.Components; using osu.Game.Users; @@ -25,7 +26,7 @@ namespace osu.Game.Screens.Multi.Match.Components Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, Children = new Drawable[] { - new ScrollContainer + new OsuScrollContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = 10 }, diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 378b1b1dc6..90989d7ebb 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -30,7 +30,7 @@ namespace osu.Game.Screens.Select private readonly AdvancedStats advanced; private readonly DetailBox ratingsContainer; private readonly UserRatings ratings; - private readonly ScrollContainer metadataScroll; + private readonly OsuScrollContainer metadataScroll; private readonly MetadataSection description, source, tags; private readonly Container failRetryContainer; private readonly FailRetryGraph failRetryGraph; @@ -107,7 +107,7 @@ namespace osu.Game.Screens.Select }, }, }, - metadataScroll = new ScrollContainer + metadataScroll = new OsuScrollContainer { RelativeSizeAxes = Axes.X, Width = 0.5f, From 4972f862e64ca302c7294e698822dd2727b01d7d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Jun 2019 19:35:31 +0900 Subject: [PATCH 1244/5608] Seek track instead --- .../Visual/Gameplay/TestSceneGameplayRewinding.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index 0176301c03..787b8ddfed 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -6,6 +6,7 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Audio.Track; using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Beatmaps; @@ -31,8 +32,14 @@ namespace osu.Game.Tests.Visual.Gameplay { } + private Track track; + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) - => new ClockBackedTestWorkingBeatmap(beatmap, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + { + var working = new ClockBackedTestWorkingBeatmap(beatmap, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + track = working.Track; + return working; + } [Test] public void TestNotJudgementsOnRewind() @@ -47,7 +54,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void addSeekStep(double time) { - AddStep($"seek to {time}", () => player.GameplayClockContainer.Seek(time)); + AddStep($"seek to {time}", () => track.Seek(time)); // Allow a few frames of lenience AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, player.DrawableRuleset.FrameStableClock.CurrentTime, 100)); From 95082d2fccb0f709ac4f3978f15a1cf8796f4daa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Jun 2019 19:35:47 +0900 Subject: [PATCH 1245/5608] Rename testcase --- osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index 787b8ddfed..a1746084a3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Gameplay } [Test] - public void TestNotJudgementsOnRewind() + public void TestNoJudgementsOnRewind() { addSeekStep(3000); AddAssert("all judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged)); From 0c293be89cccbd1d12f0e22cf4997aee49520cf3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Jun 2019 19:51:31 +0900 Subject: [PATCH 1246/5608] Wait for track to start running before seeking --- osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index a1746084a3..237fee1594 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -44,6 +44,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestNoJudgementsOnRewind() { + AddUntilStep("wait for track to start running", () => track.IsRunning); addSeekStep(3000); AddAssert("all judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged)); AddStep("clear results", () => player.AppliedResults.Clear()); From 512b9dfd820d0e6a1c6852979f1a825b6d2e8fb5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Jun 2019 20:18:22 +0900 Subject: [PATCH 1247/5608] Fix potential songselect testcase failures --- .../Visual/SongSelect/TestScenePlaySongSelect.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index f5115c50a9..738b7f14f3 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -18,6 +18,7 @@ using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Taiko; using osu.Game.Screens.Select; @@ -100,8 +101,11 @@ namespace osu.Game.Tests.Visual.SongSelect } [SetUp] - public virtual void SetUp() => - Schedule(() => { manager?.Delete(manager.GetAllUsableBeatmapSets()); }); + public virtual void SetUp() => Schedule(() => + { + Ruleset.Value = new OsuRuleset().RulesetInfo; + manager?.Delete(manager.GetAllUsableBeatmapSets()); + }); [Test] public void TestDummy() @@ -185,7 +189,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("empty mods", () => !Mods.Value.Any()); void onModChange(ValueChangedEvent> e) => modChangeIndex = actionIndex++; - void onRulesetChange(ValueChangedEvent e) => rulesetChangeIndex = actionIndex--; + void onRulesetChange(ValueChangedEvent e) => rulesetChangeIndex = actionIndex++; } [Test] From 831686d20b5288fe7c5ef8f968d0e7d4f5bfee23 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 16:23:38 +0900 Subject: [PATCH 1248/5608] Fix crash when starting with an empty bracket --- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 0e3a9b0dfd..fb7a7a8983 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -104,9 +104,10 @@ namespace osu.Game.Tournament.Screens.MapPool private void beatmapChanged(ValueChangedEvent beatmap) { - if (currentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) < 2) + if (currentMatch.Value == null || currentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) < 2) return; + // if bans have already been placed, beatmap changes result in a selection being made autoamtically if (beatmap.NewValue.OnlineBeatmapID != null) addForBeatmap(beatmap.NewValue.OnlineBeatmapID.Value); } From 2b4384bb30d44aa482b4ea13cb765189a6001bdb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 16:23:53 +0900 Subject: [PATCH 1249/5608] Fix crash when setting a match as current which doesn't have a grouping --- osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index 093a1ba2d9..0e17936079 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -48,9 +48,9 @@ namespace osu.Game.Tournament.Screens.Schedule currentMatch.BindTo(ladder.CurrentMatch); } - private void matchChanged(ValueChangedEvent pairing) + private void matchChanged(ValueChangedEvent match) { - if (pairing.NewValue == null) + if (match.NewValue == null) { mainContainer.Clear(); return; @@ -110,14 +110,14 @@ namespace osu.Game.Tournament.Screens.Schedule { Margin = new MarginPadding { Left = -10, Bottom = 10, Top = -5 }, Spacing = new Vector2(10, 0), - Text = currentMatch.Value.Grouping.Value.Name.Value, + Text = match.NewValue.Grouping.Value?.Name.Value, Colour = Color4.Black, Font = OsuFont.GetFont(size: 20) }, - new SchedulePairing(currentMatch.Value, false), + new SchedulePairing(match.NewValue, false), new OsuSpriteText { - Text = "Start Time " + pairing.NewValue.Date.Value.ToUniversalTime().ToString("HH:mm UTC"), + Text = "Start Time " + match.NewValue.Date.Value.ToUniversalTime().ToString("HH:mm UTC"), Colour = Color4.Black, Font = OsuFont.GetFont(size: 20) }, From d4808ded0b824768a6ff9a52b2b90200bbba49f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 16:28:59 +0900 Subject: [PATCH 1250/5608] Fix tooltips not showing at correct location --- osu.Game.Tournament/TournamentGameBase.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index fd7a20ecb9..c773844cec 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -223,7 +223,9 @@ namespace osu.Game.Tournament protected override void LoadComplete() { + MenuCursorContainer.Cursor.AlwaysPresent = true; // required for tooltip display MenuCursorContainer.Cursor.Alpha = 0; + base.LoadComplete(); } From 1eb15c39f96098681eeceea20cc2acfd6b10a464 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 16:38:29 +0900 Subject: [PATCH 1251/5608] Fix tests not working --- osu.Game.Tournament.Tests/TournamentTestBrowser.cs | 4 ++-- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament.Tests/TournamentTestBrowser.cs b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs index 6d4063ec4f..f7ad757926 100644 --- a/osu.Game.Tournament.Tests/TournamentTestBrowser.cs +++ b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs @@ -3,7 +3,7 @@ using osu.Framework.Testing; using osu.Game.Graphics; -using osu.Game.Screens.Backgrounds; +using osu.Game.Graphics.Backgrounds; namespace osu.Game.Tournament.Tests { @@ -13,7 +13,7 @@ namespace osu.Game.Tournament.Tests { base.LoadComplete(); - LoadComponentAsync(new BackgroundScreenDefault + LoadComponentAsync(new Background("Menu/menu-background-0") { Colour = OsuColour.Gray(0.5f), Depth = 10 diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index b76fc261f0..cf0752f764 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -14,6 +14,10 @@ netcoreapp2.1 + + + + \ No newline at end of file From 4cd6955a96c46da40e77c8d2f0820556c293dd0b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 16:57:29 +0900 Subject: [PATCH 1252/5608] Fix GameplayScreen test not working --- ...tCaseGameplay.cs => TestCaseGameplayScreen.cs} | 12 +++++------- .../Components/MatchChatDisplay.cs | 12 ++++++++++++ .../Screens/Gameplay/GameplayScreen.cs | 15 ++++++++------- .../Screens/TournamentSceneManager.cs | 11 +---------- 4 files changed, 26 insertions(+), 24 deletions(-) rename osu.Game.Tournament.Tests/{TestCaseGameplay.cs => TestCaseGameplayScreen.cs} (66%) diff --git a/osu.Game.Tournament.Tests/TestCaseGameplay.cs b/osu.Game.Tournament.Tests/TestCaseGameplayScreen.cs similarity index 66% rename from osu.Game.Tournament.Tests/TestCaseGameplay.cs rename to osu.Game.Tournament.Tests/TestCaseGameplayScreen.cs index c881f09cb9..b44cb11ec4 100644 --- a/osu.Game.Tournament.Tests/TestCaseGameplay.cs +++ b/osu.Game.Tournament.Tests/TestCaseGameplayScreen.cs @@ -1,25 +1,23 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Tests.Visual; +using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Gameplay; namespace osu.Game.Tournament.Tests { - public class TestCaseGameplay : OsuTestScene + public class TestCaseGameplayScreen : OsuTestScene { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(GameplayScreen) - }; + [Cached] + private MatchChatDisplay chat = new MatchChatDisplay(); [BackgroundDependencyLoader] private void load() { Add(new GameplayScreen()); + Add(chat); } } } diff --git a/osu.Game.Tournament/Components/MatchChatDisplay.cs b/osu.Game.Tournament/Components/MatchChatDisplay.cs index 174b215732..fbf6949540 100644 --- a/osu.Game.Tournament/Components/MatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/MatchChatDisplay.cs @@ -4,9 +4,11 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Online.Chat; using osu.Game.Overlays.Chat; using osu.Game.Tournament.IPC; +using osuTK; using osuTK.Graphics; namespace osu.Game.Tournament.Components @@ -17,6 +19,16 @@ namespace osu.Game.Tournament.Components private ChannelManager manager; + public MatchChatDisplay() + { + RelativeSizeAxes = Axes.X; + Y = 100; + Size = new Vector2(0.45f, 112); + Margin = new MarginPadding(10); + Anchor = Anchor.BottomCentre; + Origin = Anchor.BottomCentre; + } + [BackgroundDependencyLoader(true)] private void load(MatchIPCInfo ipc) { diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 9883f03581..ca7d017bf3 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -32,13 +32,15 @@ namespace osu.Game.Tournament.Screens.Gameplay private readonly Color4 red = new Color4(186, 0, 18, 255); private readonly Color4 blue = new Color4(17, 136, 170, 255); - [Resolved] + [Resolved(canBeNull: true)] private TournamentSceneManager sceneManager { get; set; } + [Resolved] + private MatchChatDisplay chat { get; set; } + [BackgroundDependencyLoader] - private void load(LadderInfo ladder, MatchIPCInfo ipc, MatchChatDisplay chat) + private void load(LadderInfo ladder, MatchIPCInfo ipc) { - this.chat = chat; this.ipc = ipc; AddRangeInternal(new Drawable[] @@ -132,7 +134,6 @@ namespace osu.Game.Tournament.Screens.Gameplay } private ScheduledDelegate scheduledOperation; - private MatchChatDisplay chat; private MatchScoreDisplay scoreDisplay; private TourneyState lastState; @@ -155,7 +156,7 @@ namespace osu.Game.Tournament.Screens.Gameplay void expand() { - chat.Expand(); + chat?.Expand(); using (BeginDelayedSequence(300, true)) { @@ -168,8 +169,8 @@ namespace osu.Game.Tournament.Screens.Gameplay { SongBar.Expanded = false; scoreDisplay.FadeOut(100); - using (chat.BeginDelayedSequence(500)) - chat.Contract(); + using (chat?.BeginDelayedSequence(500)) + chat?.Contract(); } switch (state.NewValue) diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index 6bc624dca0..cec4f52751 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -32,17 +32,8 @@ namespace osu.Game.Tournament.Screens private Container screens; private VideoSprite video; - //todo: make less temporary [Cached] - private MatchChatDisplay chat = new MatchChatDisplay - { - RelativeSizeAxes = Axes.X, - Y = 100, - Size = new Vector2(0.45f, 112), - Margin = new MarginPadding(10), - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - }; + private MatchChatDisplay chat = new MatchChatDisplay(); private Container chatContainer; From 0db013b7825c50366ce45bcfed54631eca243b34 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 17:08:26 +0900 Subject: [PATCH 1253/5608] Fix save button not being topmost --- osu.Game.Tournament/TournamentGameBase.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index c773844cec..2d7e4cd83a 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -71,6 +71,7 @@ namespace osu.Game.Tournament Text = "Save Changes", Width = 140, Height = 50, + Depth = float.MinValue, Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Padding = new MarginPadding(10), From 8da448fca793b2b4b4336f179a95ea2a9f7ac1a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 17:08:44 +0900 Subject: [PATCH 1254/5608] Improve usability of grouping editor screen --- .../Groupings/GroupingsEditorScreen.cs | 90 ++++++++++++++----- 1 file changed, 66 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs index 9c35ff21d4..1641b4205a 100644 --- a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs @@ -8,10 +8,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; +using osuTK; namespace osu.Game.Tournament.Screens.Groupings { @@ -28,26 +30,27 @@ namespace osu.Game.Tournament.Screens.Groupings RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.2f), }, - new FillFlowContainer + new OsuScrollContainer { - Direction = FillDirection.Vertical, RelativeSizeAxes = Axes.Both, Width = 0.9f, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Child = items = new FillFlowContainer + { + Direction = FillDirection.Vertical, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + }, + new ControlPanel + { Children = new Drawable[] { - items = new FillFlowContainer - { - Direction = FillDirection.Vertical, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, new TriangleButton { - Margin = new MarginPadding(20), - Width = 100, - Text = "Add", + RelativeSizeAxes = Axes.X, + Text = "Add new", Action = addNew }, } @@ -70,7 +73,13 @@ namespace osu.Game.Tournament.Screens.Groupings private void addNew() { - items.Add(new GroupingRow(new TournamentGrouping { StartDate = { Value = DateTimeOffset.UtcNow } }, updateGroupings)); + items.Add(new GroupingRow(new TournamentGrouping + { + StartDate = + { + Value = DateTimeOffset.UtcNow + } + }, updateGroupings)); updateGroupings(); } @@ -85,31 +94,64 @@ namespace osu.Game.Tournament.Screens.Groupings public GroupingRow(TournamentGrouping grouping, Action onDelete) { + Margin = new MarginPadding(10); + Grouping = grouping; InternalChildren = new Drawable[] { + new Box + { + Colour = OsuColour.Gray(0.1f), + RelativeSizeAxes = Axes.Both, + }, new FillFlowContainer { + Margin = new MarginPadding(5), + Padding = new MarginPadding { Right = 160 }, + Spacing = new Vector2(5), Direction = FillDirection.Full, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Children = new Drawable[] { - new SettingsTextBox { Width = 0.3f, Bindable = Grouping.Name }, - new SettingsTextBox { Width = 0.3f, Bindable = Grouping.Description }, - new SettingsSlider { LabelText = "Best of", Width = 0.3f, Bindable = Grouping.BestOf }, - new DangerousSettingsButton + new SettingsTextBox { - Width = 0.1f, - Text = "Delete", - Action = () => - { - Expire(); - onDelete(); - } + LabelText = "Name", + Width = 0.33f, + Bindable = Grouping.Name + }, + new SettingsTextBox + { + LabelText = "Description", + Width = 0.33f, + Bindable = Grouping.Description + }, + new DateTextBox + { + LabelText = "Start Time", + Width = 0.33f, + Bindable = Grouping.StartDate + }, + new SettingsSlider + { + LabelText = "Best of", + Width = 0.33f, + Bindable = Grouping.BestOf }, - new DateTextBox { Width = 0.3f, Bindable = Grouping.StartDate }, } + }, + new DangerousSettingsButton + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.None, + Width = 150, + Text = "Delete", + Action = () => + { + Expire(); + onDelete(); + }, } }; From a7fcec8d9775faa43b80b336b085aca3f04aeac9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 17:17:47 +0900 Subject: [PATCH 1255/5608] Fix TournamentSceneManager test --- osu.Game.Tournament/Screens/TournamentSceneManager.cs | 8 ++++++-- osu.Game.Tournament/TournamentGame.cs | 3 +-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index cec4f52751..083f26240b 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Video; using osu.Framework.Platform; using osu.Game.Graphics.UserInterface; -using osu.Game.Screens; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Drawings; using osu.Game.Tournament.Screens.Gameplay; @@ -27,7 +26,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens { [Cached] - public class TournamentSceneManager : OsuScreen + public class TournamentSceneManager : CompositeDrawable { private Container screens; private VideoSprite video; @@ -37,6 +36,11 @@ namespace osu.Game.Tournament.Screens private Container chatContainer; + public TournamentSceneManager() + { + RelativeSizeAxes = Axes.Both; + } + [BackgroundDependencyLoader] private void load(LadderInfo ladder, Storage storage) { diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index 0f142e4d74..c8c462a458 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -3,7 +3,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Tournament.Screens; @@ -19,7 +18,7 @@ namespace osu.Game.Tournament Add(new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - Child = new ScreenStack(new TournamentSceneManager()) { RelativeSizeAxes = Axes.Both } + Child = new TournamentSceneManager() }); MenuCursorContainer.Cursor.Alpha = 0; From 9818637b8de5255cc44aa46734baf04d45cb2bed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 17:20:15 +0900 Subject: [PATCH 1256/5608] Fix MapPoolScreen test --- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index fb7a7a8983..47d5a36a4b 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -28,6 +28,9 @@ namespace osu.Game.Tournament.Screens.MapPool private readonly Bindable currentMatch = new Bindable(); + [Resolved(canBeNull: true)] + private TournamentSceneManager sceneManager { get; set; } + private TeamColour pickColour; private ChoiceType pickType; @@ -169,9 +172,6 @@ namespace osu.Game.Tournament.Screens.MapPool setNextMode(); } - [Resolved] - private TournamentSceneManager sceneManager { get; set; } - private ScheduledDelegate scheduledChange; private void addForBeatmap(int beatmapId) From d4ff9dc833dcbeed8060f7d4e253f4ca8f42412c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 17:25:07 +0900 Subject: [PATCH 1257/5608] TestCase -> TestScene --- .../{LadderTestCase.cs => LadderTestScene.cs} | 2 +- .../{TestCaseBeatmapPanel.cs => TestSceneBeatmapPanel.cs} | 2 +- .../{TestCaseGameplayScreen.cs => TestSceneGameplayScreen.cs} | 2 +- ...pingsEditorScreen.cs => TestSceneGroupingsEditorScreen.cs} | 4 ++-- .../{TestCaseLadderManager.cs => TestSceneLadderManager.cs} | 2 +- .../{TestCaseMapPool.cs => TestSceneMapPool.cs} | 2 +- ...stCaseMatchChatDisplay.cs => TestSceneMatchChatDisplay.cs} | 4 ++-- .../{TestCaseMatchPairings.cs => TestSceneMatchPairings.cs} | 4 ++-- ...CaseMatchScoreDisplay.cs => TestSceneMatchScoreDisplay.cs} | 4 ++-- .../{TestCaseSceneManager.cs => TestSceneSceneManager.cs} | 2 +- .../{TestCaseSchedule.cs => TestSceneSchedule.cs} | 2 +- .../{TestCaseShowcase.cs => TestSceneShowcase.cs} | 2 +- .../{TestCaseTeamIntro.cs => TestSceneTeamIntro.cs} | 2 +- .../{TestCaseTeamWin.cs => TestSceneTeamWin.cs} | 2 +- 14 files changed, 18 insertions(+), 18 deletions(-) rename osu.Game.Tournament.Tests/{LadderTestCase.cs => LadderTestScene.cs} (87%) rename osu.Game.Tournament.Tests/{TestCaseBeatmapPanel.cs => TestSceneBeatmapPanel.cs} (96%) rename osu.Game.Tournament.Tests/{TestCaseGameplayScreen.cs => TestSceneGameplayScreen.cs} (91%) rename osu.Game.Tournament.Tests/{TestCaseGroupingsEditorScreen.cs => TestSceneGroupingsEditorScreen.cs} (73%) rename osu.Game.Tournament.Tests/{TestCaseLadderManager.cs => TestSceneLadderManager.cs} (91%) rename osu.Game.Tournament.Tests/{TestCaseMapPool.cs => TestSceneMapPool.cs} (91%) rename osu.Game.Tournament.Tests/{TestCaseMatchChatDisplay.cs => TestSceneMatchChatDisplay.cs} (96%) rename osu.Game.Tournament.Tests/{TestCaseMatchPairings.cs => TestSceneMatchPairings.cs} (97%) rename osu.Game.Tournament.Tests/{TestCaseMatchScoreDisplay.cs => TestSceneMatchScoreDisplay.cs} (90%) rename osu.Game.Tournament.Tests/{TestCaseSceneManager.cs => TestSceneSceneManager.cs} (89%) rename osu.Game.Tournament.Tests/{TestCaseSchedule.cs => TestSceneSchedule.cs} (92%) rename osu.Game.Tournament.Tests/{TestCaseShowcase.cs => TestSceneShowcase.cs} (92%) rename osu.Game.Tournament.Tests/{TestCaseTeamIntro.cs => TestSceneTeamIntro.cs} (95%) rename osu.Game.Tournament.Tests/{TestCaseTeamWin.cs => TestSceneTeamWin.cs} (95%) diff --git a/osu.Game.Tournament.Tests/LadderTestCase.cs b/osu.Game.Tournament.Tests/LadderTestScene.cs similarity index 87% rename from osu.Game.Tournament.Tests/LadderTestCase.cs rename to osu.Game.Tournament.Tests/LadderTestScene.cs index 450626fd43..cb55f543f6 100644 --- a/osu.Game.Tournament.Tests/LadderTestCase.cs +++ b/osu.Game.Tournament.Tests/LadderTestScene.cs @@ -6,7 +6,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tournament.Tests { - public class LadderTestCase : OsuTestScene + public class LadderTestScene : OsuTestScene { [Resolved] protected LadderInfo Ladder { get; private set; } diff --git a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs b/osu.Game.Tournament.Tests/TestSceneBeatmapPanel.cs similarity index 96% rename from osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs rename to osu.Game.Tournament.Tests/TestSceneBeatmapPanel.cs index 6ebdcc511b..50169adad3 100644 --- a/osu.Game.Tournament.Tests/TestCaseBeatmapPanel.cs +++ b/osu.Game.Tournament.Tests/TestSceneBeatmapPanel.cs @@ -15,7 +15,7 @@ using osu.Game.Tournament.Components; namespace osu.Game.Tournament.Tests { - public class TestCaseBeatmapPanel : OsuTestScene + public class TestSceneBeatmapPanel : OsuTestScene { [Resolved] private IAPIProvider api { get; set; } diff --git a/osu.Game.Tournament.Tests/TestCaseGameplayScreen.cs b/osu.Game.Tournament.Tests/TestSceneGameplayScreen.cs similarity index 91% rename from osu.Game.Tournament.Tests/TestCaseGameplayScreen.cs rename to osu.Game.Tournament.Tests/TestSceneGameplayScreen.cs index b44cb11ec4..1b73c798fc 100644 --- a/osu.Game.Tournament.Tests/TestCaseGameplayScreen.cs +++ b/osu.Game.Tournament.Tests/TestSceneGameplayScreen.cs @@ -8,7 +8,7 @@ using osu.Game.Tournament.Screens.Gameplay; namespace osu.Game.Tournament.Tests { - public class TestCaseGameplayScreen : OsuTestScene + public class TestSceneGameplayScreen : OsuTestScene { [Cached] private MatchChatDisplay chat = new MatchChatDisplay(); diff --git a/osu.Game.Tournament.Tests/TestCaseGroupingsEditorScreen.cs b/osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs similarity index 73% rename from osu.Game.Tournament.Tests/TestCaseGroupingsEditorScreen.cs rename to osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs index d3ef011535..993a233960 100644 --- a/osu.Game.Tournament.Tests/TestCaseGroupingsEditorScreen.cs +++ b/osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs @@ -5,9 +5,9 @@ using osu.Game.Tournament.Screens.Groupings; namespace osu.Game.Tournament.Tests { - public class TestCaseGroupingsEditorScreen : LadderTestCase + public class TestSceneGroupingsEditorScreen : LadderTestScene { - public TestCaseGroupingsEditorScreen() + public TestSceneGroupingsEditorScreen() { Add(new GroupingsEditorScreen()); } diff --git a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs b/osu.Game.Tournament.Tests/TestSceneLadderManager.cs similarity index 91% rename from osu.Game.Tournament.Tests/TestCaseLadderManager.cs rename to osu.Game.Tournament.Tests/TestSceneLadderManager.cs index 8704c3aec5..c9ea740f92 100644 --- a/osu.Game.Tournament.Tests/TestCaseLadderManager.cs +++ b/osu.Game.Tournament.Tests/TestSceneLadderManager.cs @@ -8,7 +8,7 @@ using osu.Game.Tournament.Screens.Ladder; namespace osu.Game.Tournament.Tests { - public class TestCaseLadderManager : LadderTestCase + public class TestSceneLadderManager : LadderTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament.Tests/TestCaseMapPool.cs b/osu.Game.Tournament.Tests/TestSceneMapPool.cs similarity index 91% rename from osu.Game.Tournament.Tests/TestCaseMapPool.cs rename to osu.Game.Tournament.Tests/TestSceneMapPool.cs index 6d2f64e7a7..43f4831a2a 100644 --- a/osu.Game.Tournament.Tests/TestCaseMapPool.cs +++ b/osu.Game.Tournament.Tests/TestSceneMapPool.cs @@ -8,7 +8,7 @@ using osu.Game.Tournament.Screens.MapPool; namespace osu.Game.Tournament.Tests { - public class TestCaseMapPool : LadderTestCase + public class TestSceneMapPool : LadderTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs b/osu.Game.Tournament.Tests/TestSceneMatchChatDisplay.cs similarity index 96% rename from osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs rename to osu.Game.Tournament.Tests/TestSceneMatchChatDisplay.cs index cec6095598..fb31cd0f7c 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/TestSceneMatchChatDisplay.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tournament.Tests { - public class TestCaseMatchChatDisplay : OsuTestScene + public class TestSceneMatchChatDisplay : OsuTestScene { private readonly Channel testChannel = new Channel(); @@ -43,7 +43,7 @@ namespace osu.Game.Tournament.Tests [Cached] private MatchIPCInfo matchInfo = new MatchIPCInfo(); // hide parent - public TestCaseMatchChatDisplay() + public TestSceneMatchChatDisplay() { MatchChatDisplay chatDisplay; diff --git a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs b/osu.Game.Tournament.Tests/TestSceneMatchPairings.cs similarity index 97% rename from osu.Game.Tournament.Tests/TestCaseMatchPairings.cs rename to osu.Game.Tournament.Tests/TestSceneMatchPairings.cs index e7a329d35f..4d92e209be 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestSceneMatchPairings.cs @@ -11,7 +11,7 @@ using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Tests { - public class TestCaseMatchPairings : OsuTestScene + public class TestSceneMatchPairings : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -21,7 +21,7 @@ namespace osu.Game.Tournament.Tests typeof(DrawableTournamentTeam), }; - public TestCaseMatchPairings() + public TestSceneMatchPairings() { Container level1; Container level2; diff --git a/osu.Game.Tournament.Tests/TestCaseMatchScoreDisplay.cs b/osu.Game.Tournament.Tests/TestSceneMatchScoreDisplay.cs similarity index 90% rename from osu.Game.Tournament.Tests/TestCaseMatchScoreDisplay.cs rename to osu.Game.Tournament.Tests/TestSceneMatchScoreDisplay.cs index c7de5cf8ce..7e9b83a61b 100644 --- a/osu.Game.Tournament.Tests/TestCaseMatchScoreDisplay.cs +++ b/osu.Game.Tournament.Tests/TestSceneMatchScoreDisplay.cs @@ -9,12 +9,12 @@ using osu.Game.Tournament.Screens.Gameplay.Components; namespace osu.Game.Tournament.Tests { - public class TestCaseMatchScoreDisplay : LadderTestCase + public class TestSceneMatchScoreDisplay : LadderTestScene { [Cached(Type = typeof(MatchIPCInfo))] private MatchIPCInfo matchInfo = new MatchIPCInfo(); - public TestCaseMatchScoreDisplay() + public TestSceneMatchScoreDisplay() { Add(new MatchScoreDisplay { diff --git a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs b/osu.Game.Tournament.Tests/TestSceneSceneManager.cs similarity index 89% rename from osu.Game.Tournament.Tests/TestCaseSceneManager.cs rename to osu.Game.Tournament.Tests/TestSceneSceneManager.cs index 7c1b794e16..385dc09d58 100644 --- a/osu.Game.Tournament.Tests/TestCaseSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestSceneSceneManager.cs @@ -8,7 +8,7 @@ using osu.Game.Tournament.Screens; namespace osu.Game.Tournament.Tests { - public class TestCaseSceneManager : OsuTestScene + public class TestSceneSceneManager : OsuTestScene { [BackgroundDependencyLoader] private void load(Storage storage) diff --git a/osu.Game.Tournament.Tests/TestCaseSchedule.cs b/osu.Game.Tournament.Tests/TestSceneSchedule.cs similarity index 92% rename from osu.Game.Tournament.Tests/TestCaseSchedule.cs rename to osu.Game.Tournament.Tests/TestSceneSchedule.cs index b5a80d7bee..00eb4c4e41 100644 --- a/osu.Game.Tournament.Tests/TestCaseSchedule.cs +++ b/osu.Game.Tournament.Tests/TestSceneSchedule.cs @@ -9,7 +9,7 @@ using osu.Game.Tournament.Screens.Schedule; namespace osu.Game.Tournament.Tests { - public class TestCaseSchedule : OsuTestScene + public class TestSceneSchedule : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tournament.Tests/TestCaseShowcase.cs b/osu.Game.Tournament.Tests/TestSceneShowcase.cs similarity index 92% rename from osu.Game.Tournament.Tests/TestCaseShowcase.cs rename to osu.Game.Tournament.Tests/TestSceneShowcase.cs index c0816e3594..a4d518eedd 100644 --- a/osu.Game.Tournament.Tests/TestCaseShowcase.cs +++ b/osu.Game.Tournament.Tests/TestSceneShowcase.cs @@ -9,7 +9,7 @@ using osu.Game.Tournament.Screens.Showcase; namespace osu.Game.Tournament.Tests { - public class TestCaseShowcase : OsuTestScene + public class TestSceneShowcase : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs b/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs similarity index 95% rename from osu.Game.Tournament.Tests/TestCaseTeamIntro.cs rename to osu.Game.Tournament.Tests/TestSceneTeamIntro.cs index 78614518ce..b9245c0c25 100644 --- a/osu.Game.Tournament.Tests/TestCaseTeamIntro.cs +++ b/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs @@ -10,7 +10,7 @@ using osu.Game.Tournament.Screens.TeamIntro; namespace osu.Game.Tournament.Tests { - public class TestCaseTeamIntro : LadderTestCase + public class TestSceneTeamIntro : LadderTestScene { [Cached] private readonly Bindable currentMatch = new Bindable(); diff --git a/osu.Game.Tournament.Tests/TestCaseTeamWin.cs b/osu.Game.Tournament.Tests/TestSceneTeamWin.cs similarity index 95% rename from osu.Game.Tournament.Tests/TestCaseTeamWin.cs rename to osu.Game.Tournament.Tests/TestSceneTeamWin.cs index df24877f09..3d6813b8d6 100644 --- a/osu.Game.Tournament.Tests/TestCaseTeamWin.cs +++ b/osu.Game.Tournament.Tests/TestSceneTeamWin.cs @@ -10,7 +10,7 @@ using osu.Game.Tournament.Screens.TeamWin; namespace osu.Game.Tournament.Tests { - public class TestCaseTeamWin : LadderTestCase + public class TestSceneTeamWin : LadderTestScene { [Cached] private readonly Bindable currentMatch = new Bindable(); From eb86d43d19ac790d9903e7cb24762bc479626204 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 17:56:47 +0900 Subject: [PATCH 1258/5608] Update grouping dropdown after new groupings are added --- osu.Game.Tournament/LadderInfo.cs | 2 +- .../Screens/Groupings/GroupingsEditorScreen.cs | 6 ++++-- .../Ladder/Components/LadderEditorSettings.cs | 16 ++++++++++++---- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tournament/LadderInfo.cs b/osu.Game.Tournament/LadderInfo.cs index 9ddca460e2..fae4dcdede 100644 --- a/osu.Game.Tournament/LadderInfo.cs +++ b/osu.Game.Tournament/LadderInfo.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tournament { public List Pairings = new List(); public List Progressions = new List(); - public List Groupings = new List(); + public BindableList Groupings = new BindableList(); public List Teams = new List(); [JsonIgnore] diff --git a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs index 1641b4205a..c90a166581 100644 --- a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs @@ -68,7 +68,7 @@ namespace osu.Game.Tournament.Screens.Groupings protected override void LoadComplete() { base.LoadComplete(); - Scheduler.AddDelayed(() => LadderInfo.Groupings = items.Children.Select(c => c.Grouping).ToList(), 500, true); + Scheduler.AddDelayed(updateGroupings, 500, true); } private void addNew() @@ -80,12 +80,14 @@ namespace osu.Game.Tournament.Screens.Groupings Value = DateTimeOffset.UtcNow } }, updateGroupings)); + updateGroupings(); } private void updateGroupings() { - LadderInfo.Groupings = items.Children.Select(c => c.Grouping).ToList(); + LadderInfo.Groupings.Clear(); + LadderInfo.Groupings.AddRange(items.Children.Select(c => c.Grouping)); } public class GroupingRow : CompositeDrawable diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index be95b404f8..f701432ea0 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -39,8 +39,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { var teamEntries = ladderInfo.Teams; - var groupingOptions = ladderInfo.Groupings.Prepend(new TournamentGrouping()); - Children = new Drawable[] { new Container @@ -77,8 +75,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components textboxTeam2 = new OsuTextBox { RelativeSizeAxes = Axes.X, Height = 20 }, groupingDropdown = new SettingsDropdown { - Bindable = new Bindable { Default = groupingOptions.First() }, - Items = groupingOptions + Bindable = new Bindable(), }, losersCheckbox = new PlayerCheckbox { @@ -91,6 +88,17 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } }; + var groupingOptions = ladderInfo.Groupings.Prepend(new TournamentGrouping()); + + void updateDropdownItems() + { + groupingOptions = ladderInfo.Groupings.Prepend(new TournamentGrouping()); + groupingDropdown.Items = groupingOptions; + } + + ladderInfo.Groupings.ItemsRemoved += _ => updateDropdownItems(); + ladderInfo.Groupings.ItemsAdded += _ => updateDropdownItems(); + editorInfo.Selected.ValueChanged += selection => { textboxTeam1.Text = selection.NewValue?.Team1.Value?.Acronym; From ef21a9e1d2e6e1e115e9f12780db56e1e893c237 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 19:16:20 +0900 Subject: [PATCH 1259/5608] Use bindable flow to avoid scheduled updates --- osu.Game.Tournament/LadderInfo.cs | 8 ++- .../Ladder/Components/DrawableMatchPairing.cs | 64 ++++++++++++++----- .../Ladder/Components/LadderEditorSettings.cs | 5 +- .../Ladder/Components/TournamentGrouping.cs | 1 + .../Screens/Ladder/LadderEditorScreen.cs | 29 ++------- .../Screens/Ladder/LadderScreen.cs | 47 ++++++++++++-- osu.Game.Tournament/TournamentGameBase.cs | 8 +++ 7 files changed, 111 insertions(+), 51 deletions(-) diff --git a/osu.Game.Tournament/LadderInfo.cs b/osu.Game.Tournament/LadderInfo.cs index fae4dcdede..08ef5d9062 100644 --- a/osu.Game.Tournament/LadderInfo.cs +++ b/osu.Game.Tournament/LadderInfo.cs @@ -11,10 +11,12 @@ namespace osu.Game.Tournament { public class LadderInfo { - public List Pairings = new List(); - public List Progressions = new List(); + public BindableList Pairings = new BindableList(); public BindableList Groupings = new BindableList(); - public List Teams = new List(); + public BindableList Teams = new BindableList(); + + // only used for serialisation + public List Progressions = new List(); [JsonIgnore] public Bindable CurrentMatch = new Bindable(); diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index cf9fe3f2be..fcd7ed241a 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -73,26 +75,56 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } }; - pairing.Team1.BindValueChanged(_ => updateTeams()); - pairing.Team2.BindValueChanged(_ => updateTeams()); - pairing.Team1Score.BindValueChanged(_ => updateWinConditions()); - pairing.Team2Score.BindValueChanged(_ => updateWinConditions()); - pairing.Grouping.BindValueChanged(_ => updateWinConditions()); - pairing.Completed.BindValueChanged(_ => updateProgression()); - pairing.Progression.BindValueChanged(_ => updateProgression()); - pairing.LosersProgression.BindValueChanged(_ => updateProgression()); - pairing.Losers.BindValueChanged(_ => updateTeams()); - pairing.Current.BindValueChanged(_ => updateCurrentMatch(), true); - pairing.Position.BindValueChanged(pos => + boundReference(pairing.Team1).BindValueChanged(_ => updateTeams()); + boundReference(pairing.Team2).BindValueChanged(_ => updateTeams()); + boundReference(pairing.Team1Score).BindValueChanged(_ => updateWinConditions()); + boundReference(pairing.Team2Score).BindValueChanged(_ => updateWinConditions()); + boundReference(pairing.Grouping).BindValueChanged(_ => { - if (IsDragged) return; - - Position = new Vector2(pos.NewValue.X, pos.NewValue.Y); + updateWinConditions(); + Changed?.Invoke(); + }); + boundReference(pairing.Completed).BindValueChanged(_ => updateProgression()); + boundReference(pairing.Progression).BindValueChanged(_ => updateProgression()); + boundReference(pairing.LosersProgression).BindValueChanged(_ => updateProgression()); + boundReference(pairing.Losers).BindValueChanged(_ => + { + updateTeams(); + Changed?.Invoke(); + }); + boundReference(pairing.Current).BindValueChanged(_ => updateCurrentMatch(), true); + boundReference(pairing.Position).BindValueChanged(pos => + { + if (!IsDragged) + Position = new Vector2(pos.NewValue.X, pos.NewValue.Y); + Changed?.Invoke(); }, true); updateTeams(); } + /// + /// Fired when somethign changed that requires a ladder redraw. + /// + public Action Changed; + + private readonly List refBindables = new List(); + + private T boundReference(T obj) + where T : IBindable + { + obj = (T)obj.GetBoundCopy(); + refBindables.Add(obj); + return obj; + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + foreach (var b in refBindables) + b.UnbindAll(); + } + private void updateCurrentMatch() { if (Pairing.Current.Value) @@ -149,6 +181,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components transferProgression(Pairing.Progression?.Value, Pairing.Winner); transferProgression(Pairing.LosersProgression?.Value, Pairing.Loser); } + + Changed?.Invoke(); } private void transferProgression(MatchPairing destination, TournamentTeam team) @@ -273,7 +307,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Pairing.Progression.Value = null; Pairing.LosersProgression.Value = null; - Expire(); + ladderInfo.Pairings.Remove(Pairing); } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index f701432ea0..21d20e1175 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.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.Framework.Allocation; using osu.Framework.Bindables; @@ -88,7 +89,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } }; - var groupingOptions = ladderInfo.Groupings.Prepend(new TournamentGrouping()); + IEnumerable groupingOptions = null; void updateDropdownItems() { @@ -99,6 +100,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components ladderInfo.Groupings.ItemsRemoved += _ => updateDropdownItems(); ladderInfo.Groupings.ItemsAdded += _ => updateDropdownItems(); + updateDropdownItems(); + editorInfo.Selected.ValueChanged += selection => { textboxTeam1.Text = selection.NewValue?.Team1.Value?.Acronym; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs index e38b684c28..d6e6b11f28 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs @@ -21,6 +21,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly Bindable StartDate = new Bindable(); + // only used for serialisation public List Pairings = new List(); public override string ToString() => Name.Value ?? "None"; diff --git a/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs index 4a35f1ad30..fc98753e0a 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs @@ -24,6 +24,8 @@ namespace osu.Game.Tournament.Screens.Ladder [Cached] private LadderEditorInfo editorInfo = new LadderEditorInfo(); + protected override bool DrawLoserPaths => true; + [BackgroundDependencyLoader] private void load() { @@ -35,32 +37,9 @@ namespace osu.Game.Tournament.Screens.Ladder }); } - private void updateInfo() - { - LadderInfo.Pairings = PairingsContainer.Select(p => p.Pairing).ToList(); - foreach (var g in LadderInfo.Groupings) - g.Pairings = LadderInfo.Pairings.Where(p => p.Grouping.Value == g).Select(p => p.ID).ToList(); - - LadderInfo.Progressions = LadderInfo.Pairings.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( - LadderInfo.Pairings.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) - .ToList(); - } - - protected override void AddPairing(MatchPairing pairing) - { - base.AddPairing(pairing); - updateInfo(); - } - - protected override void UpdateLayout() - { - base.UpdateLayout(); - updateInfo(); - } - public void BeginJoin(MatchPairing pairing, bool losers) { - ScrollContent.Add(new JoinVisualiser(PairingsContainer, pairing, losers, updateInfo)); + ScrollContent.Add(new JoinVisualiser(PairingsContainer, pairing, losers, UpdateLayout)); } public MenuItem[] ContextMenuItems @@ -75,7 +54,7 @@ namespace osu.Game.Tournament.Screens.Ladder new OsuMenuItem("Create new match", MenuItemType.Highlighted, () => { var pos = PairingsContainer.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position); - AddPairing(new MatchPairing { Position = { Value = new Point((int)pos.X, (int)pos.Y) } }); + LadderInfo.Pairings.Add(new MatchPairing { Position = { Value = new Point((int)pos.X, (int)pos.Y) } }); }), new OsuMenuItem("Reset teams", MenuItemType.Destructive, () => { diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index f2d4ebbb71..1457992003 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -57,16 +57,33 @@ namespace osu.Game.Tournament.Screens.Ladder } }; + void addPairing(MatchPairing pairing) => + PairingsContainer.Add(new DrawableMatchPairing(pairing, this is LadderEditorScreen) + { + Changed = () => layout.Invalidate() + }); + foreach (var pairing in LadderInfo.Pairings) - AddPairing(pairing); + addPairing(pairing); - // todo: fix this - Scheduler.AddDelayed(() => layout.Invalidate(), 1000, true); - } + LadderInfo.Groupings.ItemsAdded += _ => layout.Invalidate(); + LadderInfo.Groupings.ItemsRemoved += _ => layout.Invalidate(); - protected virtual void AddPairing(MatchPairing pairing) - { - PairingsContainer.Add(new DrawableMatchPairing(pairing, this is LadderEditorScreen)); + LadderInfo.Pairings.ItemsAdded += pairings => + { + foreach (var p in pairings) + addPairing(p); + layout.Invalidate(); + }; + + LadderInfo.Pairings.ItemsRemoved += pairings => + { + foreach (var p in pairings) + foreach (var d in PairingsContainer.Where(d => d.Pairing == p)) + d.Expire(); + + layout.Invalidate(); + }; } private Cached layout = new Cached(); @@ -82,6 +99,8 @@ namespace osu.Game.Tournament.Screens.Ladder private Color4 normalPathColour; private Color4 losersPathColour; + protected virtual bool DrawLoserPaths => false; + protected virtual void UpdateLayout() { paths.Clear(); @@ -103,6 +122,20 @@ namespace osu.Game.Tournament.Screens.Ladder else paths.Add(new ProgressionPath(pairing, dest) { Colour = pairing.Pairing.Losers.Value ? losersPathColour : normalPathColour }); } + + if (DrawLoserPaths) + { + if (pairing.Pairing.LosersProgression.Value != null) + { + var dest = PairingsContainer.FirstOrDefault(p => p.Pairing == pairing.Pairing.LosersProgression.Value); + + if (dest == null) + // clean up outdated progressions. + pairing.Pairing.LosersProgression.Value = null; + else + paths.Add(new ProgressionPath(pairing, dest) { Colour = losersPathColour.Opacity(0.1f) }); + } + } } foreach (var group in LadderInfo.Groupings) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 2d7e4cd83a..54d47625fa 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -21,6 +21,7 @@ using osu.Game.Online.API.Requests; using osu.Game.Rulesets; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Screens.Ladder.Components; using osuTK.Input; namespace osu.Game.Tournament @@ -244,6 +245,13 @@ namespace osu.Game.Tournament protected virtual void SaveChanges() { + foreach (var g in ladder.Groupings) + g.Pairings = ladder.Pairings.Where(p => p.Grouping.Value == g).Select(p => p.ID).ToList(); + + ladder.Progressions = ladder.Pairings.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( + ladder.Pairings.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) + .ToList(); + using (var stream = storage.GetStream(bracket_filename, FileAccess.Write, FileMode.Create)) using (var sw = new StreamWriter(stream)) { From c9bd62e8157b9779157f75062cf40e1ee21a8565 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 20:30:09 +0900 Subject: [PATCH 1260/5608] Use bindable logic for grouping name/description updates --- .../Groupings/GroupingsEditorScreen.cs | 29 ++++------ .../Components/DrawableTournamentGrouping.cs | 23 ++++++-- .../Ladder/Components/LadderEditorSettings.cs | 55 +++++++++++++------ 3 files changed, 66 insertions(+), 41 deletions(-) diff --git a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs index c90a166581..87a975aadc 100644 --- a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -62,39 +61,31 @@ namespace osu.Game.Tournament.Screens.Groupings private void load() { foreach (var g in LadderInfo.Groupings) - items.Add(new GroupingRow(g, updateGroupings)); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - Scheduler.AddDelayed(updateGroupings, 500, true); + items.Add(new GroupingRow(g)); } private void addNew() { - items.Add(new GroupingRow(new TournamentGrouping + var grouping = new TournamentGrouping { StartDate = { Value = DateTimeOffset.UtcNow } - }, updateGroupings)); + }; - updateGroupings(); - } - - private void updateGroupings() - { - LadderInfo.Groupings.Clear(); - LadderInfo.Groupings.AddRange(items.Children.Select(c => c.Grouping)); + items.Add(new GroupingRow(grouping)); + LadderInfo.Groupings.Add(grouping); } public class GroupingRow : CompositeDrawable { public readonly TournamentGrouping Grouping; - public GroupingRow(TournamentGrouping grouping, Action onDelete) + [Resolved] + private LadderInfo ladderInfo { get; set; } + + public GroupingRow(TournamentGrouping grouping) { Margin = new MarginPadding(10); @@ -152,7 +143,7 @@ namespace osu.Game.Tournament.Screens.Groupings Action = () => { Expire(); - onDelete(); + ladderInfo.Groupings.Remove(Grouping); }, } }; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs index 40adc24dc4..a3a7bf4f64 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using JetBrains.Annotations; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -11,8 +13,17 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public class DrawableTournamentGrouping : CompositeDrawable { + [UsedImplicitly] + private readonly Bindable name; + + [UsedImplicitly] + private readonly Bindable description; + public DrawableTournamentGrouping(TournamentGrouping grouping, bool losers = false) { + OsuSpriteText textName; + OsuSpriteText textDescription; + AutoSizeAxes = Axes.Both; InternalChild = new FillFlowContainer { @@ -20,16 +31,14 @@ namespace osu.Game.Tournament.Screens.Ladder.Components AutoSizeAxes = Axes.Both, Children = new Drawable[] { - new OsuSpriteText + textDescription = new OsuSpriteText { - Text = grouping.Description.Value.ToUpper(), Colour = Color4.Black, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre }, - new OsuSpriteText + textName = new OsuSpriteText { - Text = ((losers ? "Losers " : "") + grouping.Name).ToUpper(), Font = OsuFont.GetFont(weight: FontWeight.Bold), Colour = Color4.Black, Origin = Anchor.TopCentre, @@ -37,6 +46,12 @@ namespace osu.Game.Tournament.Screens.Ladder.Components }, } }; + + name = grouping.Name.GetBoundCopy(); + name.BindValueChanged(n => textName.Text = ((losers ? "Losers " : "") + grouping.Name).ToUpper(), true); + + description = grouping.Name.GetBoundCopy(); + description.BindValueChanged(n => textDescription.Text = grouping.Description.Value.ToUpper(), true); } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index 21d20e1175..7d6b7ae57f 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -74,10 +75,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components }, }, textboxTeam2 = new OsuTextBox { RelativeSizeAxes = Axes.X, Height = 20 }, - groupingDropdown = new SettingsDropdown - { - Bindable = new Bindable(), - }, + groupingDropdown = new SettingsGroupingDropdown(ladderInfo.Groupings), losersCheckbox = new PlayerCheckbox { LabelText = "Losers Bracket", @@ -89,24 +87,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } }; - IEnumerable groupingOptions = null; - - void updateDropdownItems() - { - groupingOptions = ladderInfo.Groupings.Prepend(new TournamentGrouping()); - groupingDropdown.Items = groupingOptions; - } - - ladderInfo.Groupings.ItemsRemoved += _ => updateDropdownItems(); - ladderInfo.Groupings.ItemsAdded += _ => updateDropdownItems(); - - updateDropdownItems(); - editorInfo.Selected.ValueChanged += selection => { textboxTeam1.Text = selection.NewValue?.Team1.Value?.Acronym; textboxTeam2.Text = selection.NewValue?.Team2.Value?.Acronym; - groupingDropdown.Bindable.Value = selection.NewValue?.Grouping.Value ?? groupingOptions.First(); + groupingDropdown.Bindable.Value = selection.NewValue?.Grouping.Value; losersCheckbox.Current.Value = selection.NewValue?.Losers.Value ?? false; dateTimeBox.Bindable.Value = selection.NewValue?.Date.Value ?? DateTimeOffset.UtcNow; }; @@ -164,5 +149,39 @@ namespace osu.Game.Tournament.Screens.Ladder.Components protected override void OnHoverLost(HoverLostEvent e) { } + + private class SettingsGroupingDropdown : SettingsDropdown + { + public SettingsGroupingDropdown(BindableList groupings) + { + Bindable = new Bindable(); + + foreach (var g in groupings.Prepend(new TournamentGrouping())) + add(g); + + groupings.ItemsRemoved += items => items.ForEach(i => Control.RemoveDropdownItem(i)); + groupings.ItemsAdded += items => items.ForEach(add); + } + + private readonly List refBindables = new List(); + + private T boundReference(T obj) + where T : IBindable + { + obj = (T)obj.GetBoundCopy(); + refBindables.Add(obj); + return obj; + } + + private void add(TournamentGrouping grouping) + { + Control.AddDropdownItem(grouping); + boundReference(grouping.Name).BindValueChanged(_ => + { + Control.RemoveDropdownItem(grouping); + Control.AddDropdownItem(grouping); + }); + } + } } } From 0ca33e16dd9d4c54fea216daef7c586633fb9d75 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 23:25:29 +0900 Subject: [PATCH 1261/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 75a464d0b8..89c89faa5e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 5e151f916b..46e508c910 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 1a731782603d6eebd7918cabf2b2d4d56e183226 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Sat, 15 Jun 2019 13:28:03 +0800 Subject: [PATCH 1262/5608] using FadeTo() instead of FadeIn()/FadeOut() --- osu.Game/Overlays/Mods/ModSection.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index c110f58b7a..1eaa3deea4 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -52,17 +52,12 @@ namespace osu.Game.Overlays.Mods buttons = modContainers.OfType().ToArray(); var expand = value.Any(); - if (expand) - { - headerLabel.FadeIn(200); Show(); - } else - { - headerLabel.FadeOut(200); Hide(); - } + + headerLabel.FadeTo(expand ? 1 : 0, 200); } } From 2b48f5d3e08d7781a96aefe26943e507a7392b85 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 15 Jun 2019 14:45:51 +0900 Subject: [PATCH 1263/5608] Tidy up updateMetrics flow --- osu.Game/Screens/Select/BeatmapDetails.cs | 52 ++++++++++++++--------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 8ddb3e1cc1..23dd87d8ea 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -187,17 +187,24 @@ namespace osu.Game.Screens.Select // metrics may have been previously fetched if (Beatmap?.BeatmapSet?.Metrics != null && Beatmap?.Metrics != null) { - updateMetrics(Beatmap.BeatmapSet.Metrics, Beatmap.Metrics); + updateMetrics(); return; } - // metrics may not be fetched but can be - if (Beatmap?.OnlineBeatmapID != null) + // for now, let's early abort if an OnlineBeatmapID is not present (should have been populated at import time). + if (Beatmap?.OnlineBeatmapID == null) { - var requestedBeatmap = Beatmap; + updateMetrics(); + return; + } - var lookup = new GetBeatmapRequest(requestedBeatmap); - lookup.Success += res => + var requestedBeatmap = Beatmap; + + var lookup = new GetBeatmapRequest(requestedBeatmap); + + lookup.Success += res => + { + Schedule(() => { if (beatmap != requestedBeatmap) //the beatmap has been changed since we started the lookup. @@ -212,27 +219,34 @@ namespace osu.Game.Screens.Select requestedBeatmap.Metrics = b.Metrics; - Schedule(() => updateMetrics(b.BeatmapSet.Metrics, b.Metrics)); - }; + updateMetrics(); + }); + }; - lookup.Failure += e => Schedule(() => updateMetrics(Beatmap?.BeatmapSet?.Metrics, Beatmap?.Metrics)); + lookup.Failure += e => + { + Schedule(() => + { + if (beatmap != requestedBeatmap) + //the beatmap has been changed since we started the lookup. + return; - api.Queue(lookup); - loading.Show(); - return; - } + updateMetrics(); + }); + }; - updateMetrics(Beatmap?.BeatmapSet?.Metrics, Beatmap?.Metrics); + api.Queue(lookup); + loading.Show(); } - private void updateMetrics(BeatmapSetMetrics setMetrics, BeatmapMetrics beatmapMetrics) + private void updateMetrics() { - var hasRatings = setMetrics?.Ratings?.Any() ?? false; - var hasRetriesFails = (beatmapMetrics?.Retries?.Any() ?? false) && (beatmapMetrics.Fails?.Any() ?? false); + var hasRatings = beatmap?.BeatmapSet?.Metrics?.Ratings?.Any() ?? false; + var hasRetriesFails = (beatmap?.Metrics?.Retries?.Any() ?? false) && (beatmap?.Metrics.Fails?.Any() ?? false); if (hasRatings) { - ratings.Metrics = setMetrics; + ratings.Metrics = beatmap.BeatmapSet.Metrics; ratingsContainer.FadeIn(transition_duration); } else @@ -243,7 +257,7 @@ namespace osu.Game.Screens.Select if (hasRetriesFails) { - failRetryGraph.Metrics = beatmapMetrics; + failRetryGraph.Metrics = beatmap.Metrics; failRetryContainer.FadeIn(transition_duration); } else From 4a16ac53bab407adeceadc992c5ec6c8eb1dd10e Mon Sep 17 00:00:00 2001 From: naoey Date: Sat, 15 Jun 2019 12:28:23 +0530 Subject: [PATCH 1264/5608] Remove extra newline --- osu.Game/Database/IModelDownloader.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Database/IModelDownloader.cs b/osu.Game/Database/IModelDownloader.cs index b4f8c1e24a..b4df7cc0e3 100644 --- a/osu.Game/Database/IModelDownloader.cs +++ b/osu.Game/Database/IModelDownloader.cs @@ -23,7 +23,6 @@ namespace osu.Game.Database /// event Action> DownloadFailed; - /// /// Checks whether a given is already available in the local store. /// From d7bea3aa1837958244d48f028f5ca924174b803b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 15 Jun 2019 19:38:05 +0900 Subject: [PATCH 1265/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 89c89faa5e..957d365724 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 46e508c910..9b146fa490 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 2e7922c3f9a98a985dbc3f9e2cb453a534b3f9e9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 15 Jun 2019 23:53:28 +0900 Subject: [PATCH 1266/5608] Fix 0-length sliders not getting correct lengths --- .../Objects/Legacy/Catch/ConvertHitObjectParser.cs | 3 ++- .../Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 9 +++++++-- .../Objects/Legacy/Mania/ConvertHitObjectParser.cs | 3 ++- .../Objects/Legacy/Osu/ConvertHitObjectParser.cs | 6 +++--- .../Objects/Legacy/Taiko/ConvertHitObjectParser.cs | 3 ++- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index 48f637dfe8..c968fe469a 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -37,7 +37,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + List> nodeSamples) { newCombo |= forceNewCombo; comboOffset += extraComboOffset; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index c14f3b6a42..36ae15efcc 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Objects.Legacy else if (type.HasFlag(ConvertHitObjectType.Slider)) { PathType pathType = PathType.Catmull; - double length = 0; + double? length = null; string[] pointSplit = split[5].Split('|'); @@ -130,7 +130,11 @@ namespace osu.Game.Rulesets.Objects.Legacy repeatCount = Math.Max(0, repeatCount - 1); if (split.Length > 7) + { length = Math.Max(0, Parsing.ParseDouble(split[7])); + if (length == 0) + length = null; + } if (split.Length > 10) readCustomSampleBanks(split[10], bankInfo); @@ -291,7 +295,8 @@ namespace osu.Game.Rulesets.Objects.Legacy /// The slider repeat count. /// The samples to be played when the slider nodes are hit. This includes the head and tail of the slider. /// The hit object. - protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples); + protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + List> nodeSamples); /// /// Creates a legacy Spinner-type hit object. diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index 8a3e232e60..5acc085ba1 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -26,7 +26,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + List> nodeSamples) { return new ConvertSlider { diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index b98de32bd0..d46e1fa86a 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.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 osuTK; using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; @@ -38,7 +37,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + List> nodeSamples) { newCombo |= forceNewCombo; comboOffset += extraComboOffset; @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu Position = position, NewCombo = FirstObject || newCombo, ComboOffset = comboOffset, - Path = new SliderPath(pathType, controlPoints, Math.Max(0, length)), + Path = new SliderPath(pathType, controlPoints, length), NodeSamples = nodeSamples, RepeatCount = repeatCount }; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs index bab21b31ad..39fb9e3b3a 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -23,7 +23,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko return new ConvertHit(); } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + List> nodeSamples) { return new ConvertSlider { From d693b2a329b4b6af487c995e4c1ca47c5dd4667e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 16 Jun 2019 00:31:14 +0900 Subject: [PATCH 1267/5608] Fix multiplayer score submission failing silently --- osu.Game/Online/API/APIAccess.cs | 3 ++- osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 12b38fab1e..d722c7a98a 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -262,8 +262,9 @@ namespace osu.Game.Online.API handleWebException(we); return false; } - catch + catch (Exception ex) { + Logger.Error(ex, "Error occurred while handling an API request."); return false; } } diff --git a/osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs b/osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs index 1a2503f339..50b62cd6ed 100644 --- a/osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs +++ b/osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs @@ -30,7 +30,10 @@ namespace osu.Game.Online.API.Requests req.ContentType = "application/json"; req.Method = HttpMethod.Put; - req.AddRaw(JsonConvert.SerializeObject(scoreInfo)); + req.AddRaw(JsonConvert.SerializeObject(scoreInfo, new JsonSerializerSettings + { + ReferenceLoopHandling = ReferenceLoopHandling.Ignore + })); return req; } From 515534cb34c4433d09224988e54848105e343f99 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Sun, 16 Jun 2019 00:02:26 +0700 Subject: [PATCH 1268/5608] Adding custom tooltip to DifficultyIcon --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 94 ++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 0a0ad28fdf..22a3fd0c8a 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.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; @@ -6,17 +6,20 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables { - public class DifficultyIcon : DifficultyColouredContainer + public class DifficultyIcon : DifficultyColouredContainer, IHasCustomTooltip { private readonly RulesetInfo ruleset; @@ -27,10 +30,97 @@ namespace osu.Game.Beatmaps.Drawables throw new ArgumentNullException(nameof(beatmap)); this.ruleset = ruleset ?? beatmap.Ruleset; + TooltipText = $"{beatmap.Version}${beatmap.StarDifficulty.ToString("0.##")}"; Size = new Vector2(20); } + public string TooltipText { get; set; } + + public ITooltip GetCustomTooltip() => new DifficultyIconTooltip(); + + public class DifficultyIconTooltip : VisibilityContainer, ITooltip + { + private readonly OsuSpriteText difficultyName, starRating; + private readonly Box background; + + public string TooltipText { get; set; } + + public DifficultyIconTooltip() + { + AutoSizeAxes = Axes.Both; + Masking = true; + CornerRadius = 5; + + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Padding = new MarginPadding(10), + Children = new Drawable[] + { + difficultyName = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 16, weight: FontWeight.Bold), + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + starRating = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 16, weight: FontWeight.Regular), + }, + new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Left = 4 }, + Icon = FontAwesome.Solid.Star, + Size = new Vector2(12), + Colour = Color4.White, + }, + } + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.GreyCarmineDark; + } + + public void Refresh() + { + var info = TooltipText.Split('$'); + difficultyName.Text = info[0]; + starRating.Text = info[1]; + } + + public void Move(Vector2 pos) => this.Position = pos; + + protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); + + protected override void PopOut() => this.FadeOut(200, Easing.OutQuint); + } + [BackgroundDependencyLoader] private void load() { From d735d4cd7f0ad19a8818bf1b60eb864ab05a5863 Mon Sep 17 00:00:00 2001 From: HoLLy Date: Sat, 15 Jun 2019 19:11:29 +0200 Subject: [PATCH 1269/5608] Fix crash on 2B hitobjects --- osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index daa3f61de3..8f10f51461 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.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; @@ -47,6 +47,7 @@ namespace osu.Game.Rulesets.Catch.Replays double speedRequired = positionChange / timeAvailable; bool dashRequired = speedRequired > movement_speed && h.StartTime != 0; + bool impossibleJump = speedRequired > movement_speed * 2 && h.StartTime != 0; // todo: get correct catcher size, based on difficulty CS. const float catcher_width_half = CatcherArea.CATCHER_SIZE / CatchPlayfield.BASE_WIDTH * 0.3f * 0.5f; @@ -59,7 +60,7 @@ namespace osu.Game.Rulesets.Catch.Replays return; } - if (h is Banana) + if (h is Banana || impossibleJump) { // auto bananas unrealistically warp to catch 100% combo. Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); From f97cab58156cf8abda751dd8e8689f6e7da6028f Mon Sep 17 00:00:00 2001 From: HoLLy Date: Sat, 15 Jun 2019 19:14:24 +0200 Subject: [PATCH 1270/5608] Prevent speedRequired from being NaN --- osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 8f10f51461..c85518717a 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Catch.Replays double timeAvailable = h.StartTime - lastTime; //So we can either make it there without a dash or not. - double speedRequired = positionChange / timeAvailable; + double speedRequired = positionChange == 0 ? 0 : positionChange / timeAvailable; bool dashRequired = speedRequired > movement_speed && h.StartTime != 0; bool impossibleJump = speedRequired > movement_speed * 2 && h.StartTime != 0; From 4d690a2b14b25c0e70bf345e14e252f19e659d54 Mon Sep 17 00:00:00 2001 From: HoLLy Date: Sat, 15 Jun 2019 19:21:00 +0200 Subject: [PATCH 1271/5608] Use normal movement for bananas when possible --- osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index c85518717a..1a7d837683 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.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; @@ -60,9 +60,8 @@ namespace osu.Game.Rulesets.Catch.Replays return; } - if (h is Banana || impossibleJump) + if (impossibleJump) { - // auto bananas unrealistically warp to catch 100% combo. Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); } else if (h.HyperDash) From 1f2f26a5038be22a0b92fecb728ce2d862d191b8 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Sun, 16 Jun 2019 00:40:44 +0700 Subject: [PATCH 1272/5608] Add color to star rating and star sprite icon --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 22a3fd0c8a..350e450877 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -37,7 +37,7 @@ namespace osu.Game.Beatmaps.Drawables public string TooltipText { get; set; } - public ITooltip GetCustomTooltip() => new DifficultyIconTooltip(); + public ITooltip GetCustomTooltip() => new DifficultyIconTooltip(AccentColour); public class DifficultyIconTooltip : VisibilityContainer, ITooltip { @@ -46,7 +46,7 @@ namespace osu.Game.Beatmaps.Drawables public string TooltipText { get; set; } - public DifficultyIconTooltip() + public DifficultyIconTooltip(Color4 accentColour) { AutoSizeAxes = Axes.Both; Masking = true; @@ -84,6 +84,7 @@ namespace osu.Game.Beatmaps.Drawables Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 16, weight: FontWeight.Regular), + Colour = accentColour }, new SpriteIcon { @@ -92,7 +93,7 @@ namespace osu.Game.Beatmaps.Drawables Margin = new MarginPadding { Left = 4 }, Icon = FontAwesome.Solid.Star, Size = new Vector2(12), - Colour = Color4.White, + Colour = accentColour, }, } } From c723ec5a9db37fff40f04670081d9731e34c0a5a Mon Sep 17 00:00:00 2001 From: HoLLy Date: Sat, 15 Jun 2019 19:40:56 +0200 Subject: [PATCH 1273/5608] Remove unneeded checks against h.StartTime --- osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 1a7d837683..e7e9c5b003 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -46,8 +46,8 @@ namespace osu.Game.Rulesets.Catch.Replays //So we can either make it there without a dash or not. double speedRequired = positionChange == 0 ? 0 : positionChange / timeAvailable; - bool dashRequired = speedRequired > movement_speed && h.StartTime != 0; - bool impossibleJump = speedRequired > movement_speed * 2 && h.StartTime != 0; + bool dashRequired = speedRequired > movement_speed; + bool impossibleJump = speedRequired > movement_speed * 2; // todo: get correct catcher size, based on difficulty CS. const float catcher_width_half = CatcherArea.CATCHER_SIZE / CatchPlayfield.BASE_WIDTH * 0.3f * 0.5f; From 1a9efb3d7a6a1bc96ab9e31511868927b7046b58 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sat, 15 Jun 2019 11:05:58 -0700 Subject: [PATCH 1274/5608] Fix editor play button --- osu.Game/Screens/Edit/Components/PlaybackControl.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index f5c9f74f62..8d4ad0efa9 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -36,12 +36,11 @@ namespace osu.Game.Screens.Edit.Components playButton = new IconButton { Anchor = Anchor.CentreLeft, - Origin = Anchor.Centre, + Origin = Anchor.CentreLeft, Scale = new Vector2(1.4f), IconScale = new Vector2(1.4f), Icon = FontAwesome.Regular.PlayCircle, Action = togglePause, - Padding = new MarginPadding { Left = 20 } }, new OsuSpriteText { From 53a7d919c769b729ad856972c844366e440248e1 Mon Sep 17 00:00:00 2001 From: HoLLy Date: Sat, 15 Jun 2019 22:41:10 +0200 Subject: [PATCH 1275/5608] Clarify speedRequired --- osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index e7e9c5b003..d418e7278a 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -43,7 +43,8 @@ namespace osu.Game.Rulesets.Catch.Replays float positionChange = Math.Abs(lastPosition - h.X); double timeAvailable = h.StartTime - lastTime; - //So we can either make it there without a dash or not. + // So we can either make it there without a dash or not. + // If positionChange is 0, we don't need to move so speedRequired should also be 0 (could be NaN if timeAvailable is 0 too) double speedRequired = positionChange == 0 ? 0 : positionChange / timeAvailable; bool dashRequired = speedRequired > movement_speed; From 1916fdd247b687f08fb5eefacf1e3a7608cc88af Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 16 Jun 2019 05:57:52 +0900 Subject: [PATCH 1276/5608] Add comment specifically about infinity being ok --- osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index d418e7278a..8dd00756f2 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -44,7 +44,8 @@ namespace osu.Game.Rulesets.Catch.Replays double timeAvailable = h.StartTime - lastTime; // So we can either make it there without a dash or not. - // If positionChange is 0, we don't need to move so speedRequired should also be 0 (could be NaN if timeAvailable is 0 too) + // If positionChange is 0, we don't need to move, so speedRequired should also be 0 (could be NaN if timeAvailable is 0 too) + // The case where positionChange > 0 and timeAvailable == 0 results in PositiveInfinity which provides expected beheaviour. double speedRequired = positionChange == 0 ? 0 : positionChange / timeAvailable; bool dashRequired = speedRequired > movement_speed; From 84b4e877f8fa443d79969c7c25bf89847781b50b Mon Sep 17 00:00:00 2001 From: andy840119 Date: Sun, 16 Jun 2019 13:27:01 +0900 Subject: [PATCH 1277/5608] using FadeTo instead of show/hide headerLabel.FadeTo() is still remain because effect can be visible when expand== true --- osu.Game/Overlays/Mods/ModSection.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 1eaa3deea4..155e8ebb75 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -52,12 +52,8 @@ namespace osu.Game.Overlays.Mods buttons = modContainers.OfType().ToArray(); var expand = value.Any(); - if (expand) - Show(); - else - Hide(); - headerLabel.FadeTo(expand ? 1 : 0, 200); + this.FadeTo(expand ? 1 : 0); } } From bc35a30a257e3509fd360c43c55684dfc622b5f2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 17 Jun 2019 12:27:53 +0900 Subject: [PATCH 1278/5608] Fix audio being dimmed during multiplayer --- osu.Game/Screens/Multi/Multiplayer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 9e5c11e098..9939915e16 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -255,7 +255,6 @@ namespace osu.Game.Screens.Multi if (!track.IsRunning) { - game.Audio.AddItem(track); track.Seek(Beatmap.Value.Metadata.PreviewTime); track.Start(); } From c1d2fff651b090da3337f763324f77d516c9d47e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 17 Jun 2019 12:44:19 +0900 Subject: [PATCH 1279/5608] Use RestartPoint --- osu.Game/Screens/Multi/Multiplayer.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 9939915e16..c76f132395 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -251,13 +251,11 @@ namespace osu.Game.Screens.Multi if (track != null) { + track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; track.Looping = true; if (!track.IsRunning) - { - track.Seek(Beatmap.Value.Metadata.PreviewTime); - track.Start(); - } + track.Restart(); } createButton.Hide(); From 98f8b1d59a7b49813ebac070eda65421bddba92c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 17 Jun 2019 06:44:24 +0300 Subject: [PATCH 1280/5608] Use ModelBackedDrawable in DrawableFlag --- osu.Game/Users/Country.cs | 44 +++++++++++++-------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/osu.Game/Users/Country.cs b/osu.Game/Users/Country.cs index b513b460bc..a84641d1fd 100644 --- a/osu.Game/Users/Country.cs +++ b/osu.Game/Users/Country.cs @@ -27,53 +27,39 @@ namespace osu.Game.Users public string FlagName; } - public class DrawableFlag : Container, IHasTooltip + public class DrawableFlag : ModelBackedDrawable, IHasTooltip { - private readonly Sprite sprite; private TextureStore textures; - private Country country; + private readonly Country country; public Country Country { - get => country; - set - { - if (value == country) - return; - - country = value; - - if (LoadState >= LoadState.Ready) - sprite.Texture = getFlagTexture(); - } + get => Model; + set => Model = value; } - public string TooltipText => country?.FullName; + public string TooltipText => Country?.FullName; public DrawableFlag(Country country = null) { this.country = country; - - Children = new Drawable[] - { - sprite = new Sprite - { - RelativeSizeAxes = Axes.Both, - }, - }; } [BackgroundDependencyLoader] private void load(TextureStore ts) { - if (ts == null) - throw new ArgumentNullException(nameof(ts)); - - textures = ts; - sprite.Texture = getFlagTexture(); + textures = ts ?? throw new ArgumentNullException(nameof(ts)); + Country = country; } - private Texture getFlagTexture() => textures.Get($@"Flags/{country?.FlagName ?? @"__"}"); + protected override Drawable CreateDrawable(Country country) + { + return new Sprite + { + RelativeSizeAxes = Axes.Both, + Texture = textures.Get($@"Flags/{country?.FlagName ?? @"__"}"), + }; + } } } From 4cb9563af20b43a6a9e64c1631c1ac2bcdaebfc5 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 17 Jun 2019 07:16:38 +0300 Subject: [PATCH 1281/5608] Use ModelBackedDrawable in UpdateableAvatar --- osu.Game/Users/UpdateableAvatar.cs | 34 ++++++------------------------ 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/osu.Game/Users/UpdateableAvatar.cs b/osu.Game/Users/UpdateableAvatar.cs index 7259468674..8eb08f963d 100644 --- a/osu.Game/Users/UpdateableAvatar.cs +++ b/osu.Game/Users/UpdateableAvatar.cs @@ -10,12 +10,8 @@ namespace osu.Game.Users /// /// An avatar which can update to a new user when needed. /// - public class UpdateableAvatar : Container + public class UpdateableAvatar : ModelBackedDrawable { - private Drawable displayedAvatar; - - private User user; - /// /// Whether to show a default guest representation on null user (as opposed to nothing). /// @@ -23,17 +19,8 @@ namespace osu.Game.Users public User User { - get => user; - set - { - if (user?.Id == value?.Id) - return; - - user = value; - - if (IsLoaded) - updateAvatar(); - } + get => Model; + set => Model = value; } /// @@ -41,17 +28,8 @@ namespace osu.Game.Users /// public readonly BindableBool OpenOnClick = new BindableBool(true); - protected override void LoadComplete() + protected override Drawable CreateDrawable(User user) { - base.LoadComplete(); - updateAvatar(); - } - - private void updateAvatar() - { - displayedAvatar?.FadeOut(300); - displayedAvatar?.Expire(); - if (user != null || ShowGuestOnNull) { var avatar = new Avatar(user) @@ -62,8 +40,10 @@ namespace osu.Game.Users avatar.OnLoadComplete += d => d.FadeInFromZero(300, Easing.OutQuint); avatar.OpenOnClick.BindTo(OpenOnClick); - Add(displayedAvatar = new DelayedLoadWrapper(avatar)); + return avatar; } + + return null; } } } From 3087099b32b6d79bee36f126ebbbad09279d8e35 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 17 Jun 2019 07:34:35 +0300 Subject: [PATCH 1282/5608] Use ModelBackedDrawable in DrawableRank --- osu.Game/Online/Leaderboards/DrawableRank.cs | 64 +++++++++----------- 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/osu.Game/Online/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs index ce64395dde..b7beb4ffb0 100644 --- a/osu.Game/Online/Leaderboards/DrawableRank.cs +++ b/osu.Game/Online/Leaderboards/DrawableRank.cs @@ -8,67 +8,59 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Scoring; +using System; namespace osu.Game.Online.Leaderboards { - public class DrawableRank : Container + public class DrawableRank : ModelBackedDrawable { - private readonly Sprite rankSprite; private TextureStore textures; - public ScoreRank Rank { get; private set; } + public ScoreRank Rank + { + get => Model; + set => Model = value; + } + + private ScoreRank rank; public DrawableRank(ScoreRank rank) { - Rank = rank; - - Children = new Drawable[] - { - rankSprite = new Sprite - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - FillMode = FillMode.Fit - }, - }; + this.rank = rank; } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private void load(TextureStore ts) { - this.textures = textures; - updateTexture(); + textures = ts ?? throw new ArgumentNullException(nameof(ts)); + Rank = rank; } - private void updateTexture() + protected override Drawable CreateDrawable(ScoreRank rank) { - string textureName; + return new Sprite + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fit, + Texture = textures.Get($"Grades/{getTextureName()}"), + }; + } + private string getTextureName() + { switch (Rank) { default: - textureName = Rank.GetDescription(); - break; + return Rank.GetDescription(); case ScoreRank.SH: - textureName = "SPlus"; - break; + return "SPlus"; case ScoreRank.XH: - textureName = "SSPlus"; - break; + return "SSPlus"; } - - rankSprite.Texture = textures.Get($@"Grades/{textureName}"); - } - - public void UpdateRank(ScoreRank newRank) - { - Rank = newRank; - - if (LoadState >= LoadState.Ready) - updateTexture(); } } } From 84a0b948e134092237e2cd5c7668c34f3da75a5c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Jun 2019 16:32:38 +0900 Subject: [PATCH 1283/5608] Fix typo in VersionNavigation class name --- osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs index 40f1b791f9..36407c7b0e 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs @@ -31,9 +31,9 @@ namespace osu.Game.Online.API.Requests.Responses public List ChangelogEntries { get; set; } [JsonProperty("versions")] - public VersionNatigation Versions { get; set; } + public VersionNavigation Versions { get; set; } - public class VersionNatigation + public class VersionNavigation { [JsonProperty("next")] public APIChangelogBuild Next { get; set; } From e58d2594986c0381afa0fe3773afd3569681f549 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Jun 2019 20:32:02 +0900 Subject: [PATCH 1284/5608] Create wireframe for team editor --- .../TestSceneTeamsEditorScreen.cs | 15 ++ .../Screens/Teams/TeamsEditorScreen.cs | 156 ++++++++++++++++++ .../Screens/TournamentSceneManager.cs | 5 +- 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tournament.Tests/TestSceneTeamsEditorScreen.cs create mode 100644 osu.Game.Tournament/Screens/Teams/TeamsEditorScreen.cs diff --git a/osu.Game.Tournament.Tests/TestSceneTeamsEditorScreen.cs b/osu.Game.Tournament.Tests/TestSceneTeamsEditorScreen.cs new file mode 100644 index 0000000000..d3268219b3 --- /dev/null +++ b/osu.Game.Tournament.Tests/TestSceneTeamsEditorScreen.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 osu.Game.Tournament.Screens.Teams; + +namespace osu.Game.Tournament.Tests +{ + public class TestSceneTeamsEditorScreen : LadderTestScene + { + public TestSceneTeamsEditorScreen() + { + Add(new TeamsEditorScreen()); + } + } +} diff --git a/osu.Game.Tournament/Screens/Teams/TeamsEditorScreen.cs b/osu.Game.Tournament/Screens/Teams/TeamsEditorScreen.cs new file mode 100644 index 0000000000..b2392e5dc0 --- /dev/null +++ b/osu.Game.Tournament/Screens/Teams/TeamsEditorScreen.cs @@ -0,0 +1,156 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Settings; +using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Ladder.Components; +using osuTK; + +namespace osu.Game.Tournament.Screens.Teams +{ + public class TeamsEditorScreen : TournamentScreen, IProvideVideo + { + private readonly FillFlowContainer items; + + public TeamsEditorScreen() + { + AddRangeInternal(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.2f), + }, + new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + Width = 0.9f, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Child = items = new FillFlowContainer + { + Direction = FillDirection.Vertical, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + }, + new ControlPanel + { + Children = new Drawable[] + { + new TriangleButton + { + RelativeSizeAxes = Axes.X, + Text = "Add new", + Action = addNew + }, + } + } + }); + } + + [BackgroundDependencyLoader] + private void load() + { + foreach (var g in LadderInfo.Teams) + items.Add(new TeamRow(g)); + } + + private void addNew() + { + var team = new TournamentTeam + { + StartDate = + { + Value = DateTimeOffset.UtcNow + } + }; + + items.Add(new TeamRow(team)); + LadderInfo.Teams.Add(team); + } + + public class TeamRow : CompositeDrawable + { + public readonly TournamentTeam Team; + + [Resolved] + private LadderInfo ladderInfo { get; set; } + + public TeamRow(TournamentTeam team) + { + Margin = new MarginPadding(10); + + Team = team; + InternalChildren = new Drawable[] + { + new Box + { + Colour = OsuColour.Gray(0.1f), + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + Margin = new MarginPadding(5), + Padding = new MarginPadding { Right = 160 }, + Spacing = new Vector2(5), + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new SettingsTextBox + { + LabelText = "Name", + Width = 0.33f, + Bindable = Team.Acronym + }, + new SettingsTextBox + { + LabelText = "Description", + Width = 0.33f, + Bindable = Team.Description + }, + new DateTextBox + { + LabelText = "Start Time", + Width = 0.33f, + Bindable = Team.StartDate + }, + new SettingsSlider + { + LabelText = "Best of", + Width = 0.33f, + Bindable = Team.BestOf + }, + } + }, + new DangerousSettingsButton + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.None, + Width = 150, + Text = "Delete", + Action = () => + { + Expire(); + ladderInfo.Teams.Remove(Team); + }, + } + }; + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + } + } + } +} diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index 083f26240b..8393cd52a2 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -19,6 +19,7 @@ using osu.Game.Tournament.Screens.MapPool; using osu.Game.Tournament.Screens.Schedule; using osu.Game.Tournament.Screens.Showcase; using osu.Game.Tournament.Screens.TeamIntro; +using osu.Game.Tournament.Screens.Teams; using osu.Game.Tournament.Screens.TeamWin; using osuTK; using osuTK.Graphics; @@ -72,6 +73,7 @@ namespace osu.Game.Tournament.Screens new ScheduleScreen(), new LadderScreen(), new LadderEditorScreen(), + new TeamsEditorScreen(), new GroupingsEditorScreen(), new ShowcaseScreen(), new MapPoolScreen(), @@ -105,8 +107,9 @@ namespace osu.Game.Tournament.Screens Direction = FillDirection.Vertical, Children = new Drawable[] { - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Team Editor", Action = () => SetScreen(typeof(TeamsEditorScreen)) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Groupings Editor", Action = () => SetScreen(typeof(GroupingsEditorScreen)) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => SetScreen(typeof(DrawingsScreen)) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => SetScreen(typeof(ShowcaseScreen)) }, From 93fc14426bb4c3000164321c188c321c922b41a2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Jun 2019 16:28:58 +0900 Subject: [PATCH 1285/5608] Convert TournamentTeam props to use binadbles --- .../.idea/runConfigurations/VisualTests.xml | 7 ++- .../TestSceneMatchChatDisplay.cs | 6 +- .../TestSceneMatchPairings.cs | 10 +-- .../TestSceneTeamIntro.cs | 4 +- osu.Game.Tournament.Tests/TestSceneTeamWin.cs | 4 +- .../Components/DrawableTournamentTeam.cs | 2 +- .../Components/TournamentTeam.cs | 41 ++++++------ .../Screens/Drawings/Components/Group.cs | 6 +- .../Components/StorageBackedTeamList.cs | 6 +- .../Screens/Drawings/DrawingsScreen.cs | 6 +- .../Gameplay/Components/MatchHeader.cs | 2 +- .../Ladder/Components/LadderEditorSettings.cs | 8 +-- .../Screens/Ladder/Components/MatchPairing.cs | 4 +- .../Screens/TeamIntro/TeamIntroScreen.cs | 2 +- .../Screens/TeamWin/TeamWinScreen.cs | 2 +- .../Screens/Teams/TeamsEditorScreen.cs | 62 ++++++++++++------- osu.Game.Tournament/TournamentGameBase.cs | 10 +-- 17 files changed, 103 insertions(+), 79 deletions(-) diff --git a/.idea/.idea.osu/.idea/runConfigurations/VisualTests.xml b/.idea/.idea.osu/.idea/runConfigurations/VisualTests.xml index 95cb4c0e62..34a83af3a1 100644 --- a/.idea/.idea.osu/.idea/runConfigurations/VisualTests.xml +++ b/.idea/.idea.osu/.idea/runConfigurations/VisualTests.xml @@ -6,12 +6,15 @@ public readonly BindableBool OpenOnClick = new BindableBool(true); + public UpdateableAvatar(User user = null) + { + User = user; + } + protected override Drawable CreateDrawable(User user) { if (user == null && !ShowGuestOnNull) diff --git a/osu.Game/Users/Drawables/DrawableFlag.cs b/osu.Game/Users/Drawables/DrawableFlag.cs index 5a2d1185fe..6f259d3253 100644 --- a/osu.Game/Users/Drawables/DrawableFlag.cs +++ b/osu.Game/Users/Drawables/DrawableFlag.cs @@ -19,7 +19,10 @@ namespace osu.Game.Users.Drawables set => Model = value; } - public UpdateableFlag(Country country = null) => Country = country; + public UpdateableFlag(Country country = null) + { + Country = country; + } protected override Drawable CreateDrawable(Country country) => new DrawableFlag(country) { @@ -33,7 +36,10 @@ namespace osu.Game.Users.Drawables public string TooltipText => country?.FullName; - public DrawableFlag(Country country) => this.country = country; + public DrawableFlag(Country country) + { + this.country = country; + } [BackgroundDependencyLoader] private void load(TextureStore ts) From c95e3da3ec6b3f577ae5116f491701bd6275bfd2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 18 Jun 2019 00:23:00 +0300 Subject: [PATCH 1303/5608] Implement a BindableRulesetSelector --- .../Toolbar/ToolbarRulesetSelector.cs | 2 +- osu.Game/Rulesets/BindableRulesetSelector.cs | 37 ++++++++++++++++++ osu.Game/Rulesets/RulesetSelector.cs | 39 +------------------ 3 files changed, 39 insertions(+), 39 deletions(-) create mode 100644 osu.Game/Rulesets/BindableRulesetSelector.cs diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index bd7ac13c9e..62abca06c6 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -17,7 +17,7 @@ using System.Linq; namespace osu.Game.Overlays.Toolbar { - public class ToolbarRulesetSelector : RulesetSelector + public class ToolbarRulesetSelector : BindableRulesetSelector { private const float padding = 10; private readonly Drawable modeButtonLine; diff --git a/osu.Game/Rulesets/BindableRulesetSelector.cs b/osu.Game/Rulesets/BindableRulesetSelector.cs new file mode 100644 index 0000000000..0da79af263 --- /dev/null +++ b/osu.Game/Rulesets/BindableRulesetSelector.cs @@ -0,0 +1,37 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; + +namespace osu.Game.Rulesets +{ + public abstract class BindableRulesetSelector : RulesetSelector + { + protected readonly Bindable GlobalRuleset = new Bindable(); + + [BackgroundDependencyLoader] + private void load(Bindable parentRuleset) + { + GlobalRuleset.BindTo(parentRuleset); + + GlobalRuleset.BindValueChanged(globalRulesetChanged); + Current.BindValueChanged(OnLocalRulesetChanged); + } + + private void globalRulesetChanged(ValueChangedEvent e) => OnGlobalRulesetChanged(e); + + protected virtual void OnGlobalRulesetChanged(ValueChangedEvent e) + { + Current.Value = e.NewValue; + } + + protected virtual void OnLocalRulesetChanged(ValueChangedEvent e) + { + if (!GlobalRuleset.Disabled) + { + GlobalRuleset.Value = e.NewValue; + } + } + } +} diff --git a/osu.Game/Rulesets/RulesetSelector.cs b/osu.Game/Rulesets/RulesetSelector.cs index e646c2676b..d7ffb866ab 100644 --- a/osu.Game/Rulesets/RulesetSelector.cs +++ b/osu.Game/Rulesets/RulesetSelector.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.UserInterface; -using osu.Framework.Bindables; using osu.Framework.Allocation; namespace osu.Game.Rulesets @@ -10,54 +9,18 @@ namespace osu.Game.Rulesets public abstract class RulesetSelector : TabControl { protected RulesetStore AvaliableRulesets; - protected readonly Bindable GlobalRuleset = new Bindable(); protected override Dropdown CreateDropdown() => null; - /// - /// Whether we want to change a global ruleset when local one is changed. - /// - protected virtual bool AllowGlobalRulesetChange => true; - - /// - /// Whether we want to change a local ruleset when global one is changed. - /// /// - protected virtual bool AllowLocalRulesetChange => true; - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets, Bindable parentRuleset) + private void load(RulesetStore rulesets) { AvaliableRulesets = rulesets; - GlobalRuleset.BindTo(parentRuleset); foreach (var r in rulesets.AvailableRulesets) { AddItem(r); } - - GlobalRuleset.BindValueChanged(globalRulesetChanged); - Current.BindValueChanged(OnLocalRulesetChanged); - } - - private void globalRulesetChanged(ValueChangedEvent e) - { - if (AllowLocalRulesetChange) - { - OnGlobalRulesetChanged(e); - } - } - - protected virtual void OnGlobalRulesetChanged(ValueChangedEvent e) - { - Current.Value = e.NewValue; - } - - protected virtual void OnLocalRulesetChanged(ValueChangedEvent e) - { - if (!GlobalRuleset.Disabled && AllowGlobalRulesetChange) - { - GlobalRuleset.Value = e.NewValue; - } } } } From 413c2158e25a56728d9116aab22078453d364004 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 18 Jun 2019 01:11:05 +0300 Subject: [PATCH 1304/5608] Simplify bindables usage --- .../Toolbar/ToolbarRulesetSelector.cs | 12 +++++------ osu.Game/Rulesets/BindableRulesetSelector.cs | 21 +++++-------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 62abca06c6..d89418b50c 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -22,10 +22,10 @@ namespace osu.Game.Overlays.Toolbar private const float padding = 10; private readonly Drawable modeButtonLine; - public override bool HandleNonPositionalInput => !GlobalRuleset.Disabled && base.HandleNonPositionalInput; - public override bool HandlePositionalInput => !GlobalRuleset.Disabled && base.HandlePositionalInput; + public override bool HandleNonPositionalInput => !Current.Disabled && base.HandleNonPositionalInput; + public override bool HandlePositionalInput => !Current.Disabled && base.HandlePositionalInput; - public override bool PropagatePositionalInputSubTree => !GlobalRuleset.Disabled && base.PropagatePositionalInputSubTree; + public override bool PropagatePositionalInputSubTree => !Current.Disabled && base.PropagatePositionalInputSubTree; private void disabledChanged(bool isDisabled) => this.FadeColour(isDisabled ? Color4.Gray : Color4.White, 300); @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Toolbar } }); - GlobalRuleset.DisabledChanged += disabledChanged; + Current.DisabledChanged += disabledChanged; } protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer @@ -92,9 +92,9 @@ namespace osu.Game.Overlays.Toolbar private readonly Cached activeMode = new Cached(); - protected override void OnLocalRulesetChanged(ValueChangedEvent e) + protected override void OnRulesetChanged(ValueChangedEvent e) { - base.OnLocalRulesetChanged(e); + base.OnRulesetChanged(e); activeMode.Invalidate(); } diff --git a/osu.Game/Rulesets/BindableRulesetSelector.cs b/osu.Game/Rulesets/BindableRulesetSelector.cs index 0da79af263..8c9bbcea0d 100644 --- a/osu.Game/Rulesets/BindableRulesetSelector.cs +++ b/osu.Game/Rulesets/BindableRulesetSelector.cs @@ -8,29 +8,18 @@ namespace osu.Game.Rulesets { public abstract class BindableRulesetSelector : RulesetSelector { - protected readonly Bindable GlobalRuleset = new Bindable(); - [BackgroundDependencyLoader] private void load(Bindable parentRuleset) { - GlobalRuleset.BindTo(parentRuleset); - - GlobalRuleset.BindValueChanged(globalRulesetChanged); - Current.BindValueChanged(OnLocalRulesetChanged); + Current.BindTo(parentRuleset); + Current.BindValueChanged(OnRulesetChanged); } - private void globalRulesetChanged(ValueChangedEvent e) => OnGlobalRulesetChanged(e); - - protected virtual void OnGlobalRulesetChanged(ValueChangedEvent e) + protected virtual void OnRulesetChanged(ValueChangedEvent e) { - Current.Value = e.NewValue; - } - - protected virtual void OnLocalRulesetChanged(ValueChangedEvent e) - { - if (!GlobalRuleset.Disabled) + if (Current.Disabled) { - GlobalRuleset.Value = e.NewValue; + return; } } } From 796afc0bf963b487a9da2749a96927900fb60832 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 13:44:38 +0900 Subject: [PATCH 1305/5608] Rename and expand chat tests --- .../TestSceneGameplayScreen.cs | 2 +- ...=> TestSceneTournamentMatchChatDisplay.cs} | 47 ++++++++++++++----- ...splay.cs => TournamentMatchChatDisplay.cs} | 4 +- .../Screens/Gameplay/GameplayScreen.cs | 2 +- .../Screens/TournamentSceneManager.cs | 2 +- 5 files changed, 40 insertions(+), 17 deletions(-) rename osu.Game.Tournament.Tests/{TestSceneMatchChatDisplay.cs => TestSceneTournamentMatchChatDisplay.cs} (64%) rename osu.Game.Tournament/Components/{MatchChatDisplay.cs => TournamentMatchChatDisplay.cs} (96%) diff --git a/osu.Game.Tournament.Tests/TestSceneGameplayScreen.cs b/osu.Game.Tournament.Tests/TestSceneGameplayScreen.cs index 1b73c798fc..74d8615db0 100644 --- a/osu.Game.Tournament.Tests/TestSceneGameplayScreen.cs +++ b/osu.Game.Tournament.Tests/TestSceneGameplayScreen.cs @@ -11,7 +11,7 @@ namespace osu.Game.Tournament.Tests public class TestSceneGameplayScreen : OsuTestScene { [Cached] - private MatchChatDisplay chat = new MatchChatDisplay(); + private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay(); [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament.Tests/TestSceneMatchChatDisplay.cs b/osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs similarity index 64% rename from osu.Game.Tournament.Tests/TestSceneMatchChatDisplay.cs rename to osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs index 4fccb2996b..8a3950bac3 100644 --- a/osu.Game.Tournament.Tests/TestSceneMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs @@ -10,13 +10,13 @@ using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Screens.Ladder.Components; using osu.Game.Users; -using osuTK; namespace osu.Game.Tournament.Tests { - public class TestSceneMatchChatDisplay : OsuTestScene + public class TestSceneTournamentMatchChatDisplay : OsuTestScene { private readonly Channel testChannel = new Channel(); + private readonly Channel testChannel2 = new Channel(); private readonly User admin = new User { @@ -43,15 +43,14 @@ namespace osu.Game.Tournament.Tests [Cached] private MatchIPCInfo matchInfo = new MatchIPCInfo(); // hide parent - public TestSceneMatchChatDisplay() - { - MatchChatDisplay chatDisplay; + private readonly TournamentMatchChatDisplay chatDisplay; - Add(chatDisplay = new MatchChatDisplay + public TestSceneTournamentMatchChatDisplay() + { + Add(chatDisplay = new TournamentMatchChatDisplay { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(400, 80) }); ladderInfo.CurrentMatch.Value = new MatchPairing @@ -73,35 +72,59 @@ namespace osu.Game.Tournament.Tests { base.LoadComplete(); - AddStep("message from admin", () => testChannel.AddLocalEcho(new LocalEchoMessage + AddStep("message from admin", () => testChannel.AddNewMessages(new Message(nextMessageId()) { Sender = admin, Content = "I am a wang!" })); - AddStep("message from team red", () => testChannel.AddLocalEcho(new LocalEchoMessage + AddStep("message from team red", () => testChannel.AddNewMessages(new Message(nextMessageId()) { Sender = redUser, Content = "I am team red." })); - AddStep("message from team red", () => testChannel.AddLocalEcho(new LocalEchoMessage + AddStep("message from team red", () => testChannel.AddNewMessages(new Message(nextMessageId()) { Sender = redUser, Content = "I plan to win!" })); - AddStep("message from team blue", () => testChannel.AddLocalEcho(new LocalEchoMessage + AddStep("message from team blue", () => testChannel.AddNewMessages(new Message(nextMessageId()) { Sender = blueUser, Content = "Not on my watch. Prepare to eat saaaaaaaaaand. Lots and lots of saaaaaaand." })); - AddStep("message from admin", () => testChannel.AddLocalEcho(new LocalEchoMessage + AddStep("message from admin", () => testChannel.AddNewMessages(new Message(nextMessageId()) { Sender = admin, Content = "Okay okay, calm down guys. Let's do this!" })); + + AddStep("multiple messages", () => testChannel.AddNewMessages(new Message(nextMessageId()) + { + Sender = admin, + Content = "I spam you!" + }, + new Message(nextMessageId()) + { + Sender = admin, + Content = "I spam you!!!1" + }, + new Message(nextMessageId()) + { + Sender = admin, + Content = "I spam you!1!1" + })); + + AddStep("change channel to 2", () => chatDisplay.Channel.Value = testChannel2); + + AddStep("change channel to 1", () => chatDisplay.Channel.Value = testChannel); } + + private int messageId; + + private long? nextMessageId() => messageId++; } } diff --git a/osu.Game.Tournament/Components/MatchChatDisplay.cs b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs similarity index 96% rename from osu.Game.Tournament/Components/MatchChatDisplay.cs rename to osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs index fbf6949540..2afbb0f5ff 100644 --- a/osu.Game.Tournament/Components/MatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs @@ -13,13 +13,13 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Components { - public class MatchChatDisplay : StandAloneChatDisplay + public class TournamentMatchChatDisplay : StandAloneChatDisplay { private readonly Bindable chatChannel = new Bindable(); private ChannelManager manager; - public MatchChatDisplay() + public TournamentMatchChatDisplay() { RelativeSizeAxes = Axes.X; Y = 100; diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index ca7d017bf3..fad1919510 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -36,7 +36,7 @@ namespace osu.Game.Tournament.Screens.Gameplay private TournamentSceneManager sceneManager { get; set; } [Resolved] - private MatchChatDisplay chat { get; set; } + private TournamentMatchChatDisplay chat { get; set; } [BackgroundDependencyLoader] private void load(LadderInfo ladder, MatchIPCInfo ipc) diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index f1a2f2219b..2c620f4e56 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tournament.Screens private TourneyVideo video; [Cached] - private MatchChatDisplay chat = new MatchChatDisplay(); + private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay(); private Container chatContainer; From 40eb6f49860887d7aebb4828b4a81fbbb1ef07a2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 14:14:36 +0900 Subject: [PATCH 1306/5608] Undo ordering change to OsuFont --- osu.Game/Graphics/OsuFont.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/OsuFont.cs b/osu.Game/Graphics/OsuFont.cs index 2c2f075563..22250d4a56 100644 --- a/osu.Game/Graphics/OsuFont.cs +++ b/osu.Game/Graphics/OsuFont.cs @@ -70,7 +70,7 @@ namespace osu.Game.Graphics string weightString = weight.ToString(); // Only exo has an explicit "regular" weight, other fonts do not - if (weight == FontWeight.Regular && family != GetFamilyString(Typeface.Exo)) + if (family != GetFamilyString(Typeface.Exo) && weight == FontWeight.Regular) weightString = string.Empty; return weightString; From 07ea0f9755268e163c282847f4f01b5106936c4f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 14:16:54 +0900 Subject: [PATCH 1307/5608] Make OsuButton non-abstract again --- osu.Game/Graphics/UserInterface/OsuButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 494d4e4262..7a27f825f6 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -17,11 +17,11 @@ namespace osu.Game.Graphics.UserInterface /// /// A button with added default sound effects. /// - public abstract class OsuButton : Button + public class OsuButton : Button { private Box hover; - protected OsuButton() + public OsuButton() { Height = 40; From 5bb8649f3b3502707db16c9a5963d74b7f98039a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 14:22:59 +0900 Subject: [PATCH 1308/5608] Remove unused property from chat message --- osu.Game/Online/Chat/Message.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Online/Chat/Message.cs b/osu.Game/Online/Chat/Message.cs index 62f20daddf..2e41038a59 100644 --- a/osu.Game/Online/Chat/Message.cs +++ b/osu.Game/Online/Chat/Message.cs @@ -13,10 +13,6 @@ namespace osu.Game.Online.Chat [JsonProperty(@"message_id")] public readonly long? Id; - //todo: this should be inside sender. - [JsonProperty(@"sender_id")] - public long UserId; - [JsonProperty(@"channel_id")] public long ChannelId; From 6823ba1ab08ce335f08b7b5a82c8c715cce2e315 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 14:24:44 +0900 Subject: [PATCH 1309/5608] Unbind from previous bindable when rebinding a SettingsItem --- osu.Game/Overlays/Settings/SettingsItem.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 4776cd6442..ae840c8c00 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -63,6 +63,9 @@ namespace osu.Game.Overlays.Settings set { + if (bindable != null) + controlWithCurrent?.Current.UnbindFrom(bindable); + bindable = value; controlWithCurrent?.Current.BindTo(bindable); From 4f5abeb79f3093503db833c084f40e8016974219 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 14:44:15 +0900 Subject: [PATCH 1310/5608] Grouping -> Round --- .../TestSceneGroupingsEditorScreen.cs | 4 +- .../TestSceneTeamIntro.cs | 2 +- osu.Game.Tournament.Tests/TestSceneTeamWin.cs | 2 +- osu.Game.Tournament/IPC/FileBasedIPC.cs | 2 +- osu.Game.Tournament/LadderInfo.cs | 2 +- .../Gameplay/Components/MatchHeader.cs | 2 +- .../Ladder/Components/DrawableMatchPairing.cs | 10 ++--- ...Grouping.cs => DrawableTournamentRound.cs} | 12 +++--- .../Ladder/Components/LadderEditorSettings.cs | 40 +++++++++---------- .../Screens/Ladder/Components/MatchPairing.cs | 4 +- .../{GroupingBeatmap.cs => RoundBeatmap.cs} | 2 +- ...urnamentGrouping.cs => TournamentRound.cs} | 4 +- .../Screens/Ladder/LadderScreen.cs | 16 ++++---- .../Screens/MapPool/MapPoolScreen.cs | 6 +-- .../RoundEditorScreen.cs} | 38 +++++++++--------- .../Screens/Schedule/ScheduleScreen.cs | 2 +- .../Screens/TeamIntro/TeamIntroScreen.cs | 2 +- .../Screens/TeamWin/TeamWinScreen.cs | 2 +- .../Screens/Teams/TeamsEditorScreen.cs | 4 +- .../Screens/TournamentSceneManager.cs | 6 +-- osu.Game.Tournament/TournamentGameBase.cs | 22 +++++----- 21 files changed, 92 insertions(+), 92 deletions(-) rename osu.Game.Tournament/Screens/Ladder/Components/{DrawableTournamentGrouping.cs => DrawableTournamentRound.cs} (82%) rename osu.Game.Tournament/Screens/Ladder/Components/{GroupingBeatmap.cs => RoundBeatmap.cs} (91%) rename osu.Game.Tournament/Screens/Ladder/Components/{TournamentGrouping.cs => TournamentRound.cs} (87%) rename osu.Game.Tournament/Screens/{Groupings/GroupingsEditorScreen.cs => Rounds/RoundEditorScreen.cs} (80%) diff --git a/osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs b/osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs index 993a233960..0ef19c2948 100644 --- a/osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs +++ b/osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Tournament.Screens.Groupings; +using osu.Game.Tournament.Screens.Rounds; namespace osu.Game.Tournament.Tests { @@ -9,7 +9,7 @@ namespace osu.Game.Tournament.Tests { public TestSceneGroupingsEditorScreen() { - Add(new GroupingsEditorScreen()); + Add(new RoundEditorScreen()); } } } diff --git a/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs b/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs index 7d10923949..560a8f9521 100644 --- a/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs +++ b/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tournament.Tests var pairing = new MatchPairing(); pairing.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA"); pairing.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN"); - pairing.Grouping.Value = Ladder.Groupings.FirstOrDefault(g => g.Name.Value == "Finals"); + pairing.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals"); currentMatch.Value = pairing; Add(new TeamIntroScreen diff --git a/osu.Game.Tournament.Tests/TestSceneTeamWin.cs b/osu.Game.Tournament.Tests/TestSceneTeamWin.cs index 1ef81b7550..9f642103de 100644 --- a/osu.Game.Tournament.Tests/TestSceneTeamWin.cs +++ b/osu.Game.Tournament.Tests/TestSceneTeamWin.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tournament.Tests var pairing = new MatchPairing(); pairing.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA"); pairing.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN"); - pairing.Grouping.Value = Ladder.Groupings.FirstOrDefault(g => g.Name.Value == "Finals"); + pairing.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals"); currentMatch.Value = pairing; Add(new TeamWinScreen diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 8be10e2089..438e32c20f 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -61,7 +61,7 @@ namespace osu.Game.Tournament.IPC { lastBeatmapId = beatmapId; - var existing = ladder.CurrentMatch.Value?.Grouping.Value?.Beatmaps.FirstOrDefault(b => b.ID == beatmapId && b.BeatmapInfo != null); + var existing = ladder.CurrentMatch.Value?.Round.Value?.Beatmaps.FirstOrDefault(b => b.ID == beatmapId && b.BeatmapInfo != null); if (existing != null) Beatmap.Value = existing.BeatmapInfo; diff --git a/osu.Game.Tournament/LadderInfo.cs b/osu.Game.Tournament/LadderInfo.cs index 08ef5d9062..fc825d1a9c 100644 --- a/osu.Game.Tournament/LadderInfo.cs +++ b/osu.Game.Tournament/LadderInfo.cs @@ -12,7 +12,7 @@ namespace osu.Game.Tournament public class LadderInfo { public BindableList Pairings = new BindableList(); - public BindableList Groupings = new BindableList(); + public BindableList Rounds = new BindableList(); public BindableList Teams = new BindableList(); // only used for serialisation diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index c921967836..71cfacdc32 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -218,7 +218,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components Anchor = Anchor.Centre, Origin = Anchor.Centre, Colour = Color4.White, - Text = match.NewValue.Grouping.Value?.Name.Value ?? "Unknown Grouping", + Text = match.NewValue.Round.Value?.Name.Value ?? "Unknown Round", Font = TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Regular, size: 18), }, }; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index fcd7ed241a..35741cbb55 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -79,7 +79,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components boundReference(pairing.Team2).BindValueChanged(_ => updateTeams()); boundReference(pairing.Team1Score).BindValueChanged(_ => updateWinConditions()); boundReference(pairing.Team2Score).BindValueChanged(_ => updateWinConditions()); - boundReference(pairing.Grouping).BindValueChanged(_ => + boundReference(pairing.Round).BindValueChanged(_ => { updateWinConditions(); Changed?.Invoke(); @@ -210,12 +210,12 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private void updateWinConditions() { - if (Pairing.Grouping.Value == null) return; + if (Pairing.Round.Value == null) return; - var instaWinAmount = Pairing.Grouping.Value.BestOf.Value / 2; + var instaWinAmount = Pairing.Round.Value.BestOf.Value / 2; - Pairing.Completed.Value = Pairing.Grouping.Value.BestOf.Value > 0 - && (Pairing.Team1Score.Value + Pairing.Team2Score.Value >= Pairing.Grouping.Value.BestOf.Value || Pairing.Team1Score.Value > instaWinAmount || Pairing.Team2Score.Value > instaWinAmount); + Pairing.Completed.Value = Pairing.Round.Value.BestOf.Value > 0 + && (Pairing.Team1Score.Value + Pairing.Team2Score.Value >= Pairing.Round.Value.BestOf.Value || Pairing.Team1Score.Value > instaWinAmount || Pairing.Team2Score.Value > instaWinAmount); } protected override void LoadComplete() diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs similarity index 82% rename from osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs rename to osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs index a3a7bf4f64..844c89a968 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Ladder.Components { - public class DrawableTournamentGrouping : CompositeDrawable + public class DrawableTournamentRound : CompositeDrawable { [UsedImplicitly] private readonly Bindable name; @@ -19,7 +19,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [UsedImplicitly] private readonly Bindable description; - public DrawableTournamentGrouping(TournamentGrouping grouping, bool losers = false) + public DrawableTournamentRound(TournamentRound round, bool losers = false) { OsuSpriteText textName; OsuSpriteText textDescription; @@ -47,11 +47,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } }; - name = grouping.Name.GetBoundCopy(); - name.BindValueChanged(n => textName.Text = ((losers ? "Losers " : "") + grouping.Name).ToUpper(), true); + name = round.Name.GetBoundCopy(); + name.BindValueChanged(n => textName.Text = ((losers ? "Losers " : "") + round.Name).ToUpper(), true); - description = grouping.Name.GetBoundCopy(); - description.BindValueChanged(n => textDescription.Text = grouping.Description.Value.ToUpper(), true); + description = round.Name.GetBoundCopy(); + description.BindValueChanged(n => textDescription.Text = round.Description.Value.ToUpper(), true); } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index 4c280519df..a4b74f00a2 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components protected override string Title => @"ladder"; - private SettingsDropdown groupingDropdown; + private SettingsDropdown roundDropdown; private PlayerCheckbox losersCheckbox; private DateTextBox dateTimeBox; private SettingsTeamDropdown team1Dropdown; @@ -39,14 +39,14 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { team1Dropdown = new SettingsTeamDropdown(ladderInfo.Teams) { LabelText = "Team 1" }, team2Dropdown = new SettingsTeamDropdown(ladderInfo.Teams) { LabelText = "Team 2" }, - groupingDropdown = new SettingsGroupingDropdown(ladderInfo.Groupings) { LabelText = "Grouping" }, + roundDropdown = new SettingsRoundDropdown(ladderInfo.Rounds) { LabelText = "Round" }, losersCheckbox = new PlayerCheckbox { LabelText = "Losers Bracket" }, dateTimeBox = new DateTextBox { LabelText = "Match Time" }, }; editorInfo.Selected.ValueChanged += selection => { - groupingDropdown.Bindable = selection.NewValue?.Grouping; + roundDropdown.Bindable = selection.NewValue?.Round; losersCheckbox.Current = selection.NewValue?.Losers; dateTimeBox.Bindable = selection.NewValue?.Date; @@ -54,11 +54,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components team2Dropdown.Bindable = selection.NewValue?.Team2; }; - groupingDropdown.Bindable.ValueChanged += grouping => + roundDropdown.Bindable.ValueChanged += round => { - if (editorInfo.Selected.Value?.Date.Value < grouping.NewValue?.StartDate.Value) + if (editorInfo.Selected.Value?.Date.Value < round.NewValue?.StartDate.Value) { - editorInfo.Selected.Value.Date.Value = grouping.NewValue.StartDate.Value; + editorInfo.Selected.Value.Date.Value = round.NewValue.StartDate.Value; editorInfo.Selected.TriggerChange(); } }; @@ -79,17 +79,17 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { } - private class SettingsGroupingDropdown : SettingsDropdown + private class SettingsRoundDropdown : SettingsDropdown { - public SettingsGroupingDropdown(BindableList groupings) + public SettingsRoundDropdown(BindableList rounds) { - Bindable = new Bindable(); + Bindable = new Bindable(); - foreach (var g in groupings.Prepend(new TournamentGrouping())) - add(g); + foreach (var r in rounds.Prepend(new TournamentRound())) + add(r); - groupings.ItemsRemoved += items => items.ForEach(i => Control.RemoveDropdownItem(i)); - groupings.ItemsAdded += items => items.ForEach(add); + rounds.ItemsRemoved += items => items.ForEach(i => Control.RemoveDropdownItem(i)); + rounds.ItemsAdded += items => items.ForEach(add); } private readonly List refBindables = new List(); @@ -102,13 +102,13 @@ namespace osu.Game.Tournament.Screens.Ladder.Components return obj; } - private void add(TournamentGrouping grouping) + private void add(TournamentRound round) { - Control.AddDropdownItem(grouping); - boundReference(grouping.Name).BindValueChanged(_ => + Control.AddDropdownItem(round); + boundReference(round.Name).BindValueChanged(_ => { - Control.RemoveDropdownItem(grouping); - Control.AddDropdownItem(grouping); + Control.RemoveDropdownItem(round); + Control.AddDropdownItem(round); }); } } @@ -117,8 +117,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public SettingsTeamDropdown(BindableList teams) { - foreach (var g in teams.Prepend(new TournamentTeam())) - add(g); + foreach (var t in teams.Prepend(new TournamentTeam())) + add(t); teams.ItemsRemoved += items => items.ForEach(i => Control.RemoveDropdownItem(i)); teams.ItemsAdded += items => items.ForEach(add); diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs index f80263e41a..4ff2df1388 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs @@ -51,7 +51,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly ObservableCollection PicksBans = new ObservableCollection(); [JsonIgnore] - public readonly Bindable Grouping = new Bindable(); + public readonly Bindable Round = new Bindable(); [JsonIgnore] public readonly Bindable Progression = new Bindable(); @@ -90,7 +90,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [JsonIgnore] public TournamentTeam Loser => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team2.Value : Team1.Value; - public int PointsToWin => Grouping.Value?.BestOf.Value / 2 + 1 ?? 0; + public int PointsToWin => Round.Value?.BestOf.Value / 2 + 1 ?? 0; /// /// Remove scores from the match, in case of a false click or false start. diff --git a/osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs b/osu.Game.Tournament/Screens/Ladder/Components/RoundBeatmap.cs similarity index 91% rename from osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs rename to osu.Game.Tournament/Screens/Ladder/Components/RoundBeatmap.cs index b16ba13f65..ef608c3f06 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/GroupingBeatmap.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/RoundBeatmap.cs @@ -5,7 +5,7 @@ using osu.Game.Beatmaps; namespace osu.Game.Tournament.Screens.Ladder.Components { - public class GroupingBeatmap + public class RoundBeatmap { public int ID; public string Mods; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs b/osu.Game.Tournament/Screens/Ladder/Components/TournamentRound.cs similarity index 87% rename from osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs rename to osu.Game.Tournament/Screens/Ladder/Components/TournamentRound.cs index d6e6b11f28..79b94e06a2 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentGrouping.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/TournamentRound.cs @@ -9,7 +9,7 @@ using osu.Framework.Bindables; namespace osu.Game.Tournament.Screens.Ladder.Components { [Serializable] - public class TournamentGrouping + public class TournamentRound { public readonly Bindable Name = new Bindable(); public readonly Bindable Description = new Bindable(); @@ -17,7 +17,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components public readonly BindableInt BestOf = new BindableInt(9) { Default = 9, MinValue = 3, MaxValue = 23 }; [JsonProperty] - public readonly List Beatmaps = new List(); + public readonly List Beatmaps = new List(); public readonly Bindable StartDate = new Bindable(); diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 4a50db9997..6a77c6c20e 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -66,8 +66,8 @@ namespace osu.Game.Tournament.Screens.Ladder foreach (var pairing in LadderInfo.Pairings) addPairing(pairing); - LadderInfo.Groupings.ItemsAdded += _ => layout.Invalidate(); - LadderInfo.Groupings.ItemsRemoved += _ => layout.Invalidate(); + LadderInfo.Rounds.ItemsAdded += _ => layout.Invalidate(); + LadderInfo.Rounds.ItemsRemoved += _ => layout.Invalidate(); LadderInfo.Pairings.ItemsAdded += pairings => { @@ -138,13 +138,13 @@ namespace osu.Game.Tournament.Screens.Ladder } } - foreach (var group in LadderInfo.Groupings) + foreach (var round in LadderInfo.Rounds) { - var topPairing = PairingsContainer.Where(p => !p.Pairing.Losers.Value && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); + var topPairing = PairingsContainer.Where(p => !p.Pairing.Losers.Value && p.Pairing.Round.Value == round).OrderBy(p => p.Y).FirstOrDefault(); if (topPairing == null) continue; - headings.Add(new DrawableTournamentGrouping(group) + headings.Add(new DrawableTournamentRound(round) { Position = headings.ToLocalSpace((topPairing.ScreenSpaceDrawQuad.TopLeft + topPairing.ScreenSpaceDrawQuad.TopRight) / 2), Margin = new MarginPadding { Bottom = 10 }, @@ -152,13 +152,13 @@ namespace osu.Game.Tournament.Screens.Ladder }); } - foreach (var group in LadderInfo.Groupings) + foreach (var round in LadderInfo.Rounds) { - var topPairing = PairingsContainer.Where(p => p.Pairing.Losers.Value && p.Pairing.Grouping.Value == group).OrderBy(p => p.Y).FirstOrDefault(); + var topPairing = PairingsContainer.Where(p => p.Pairing.Losers.Value && p.Pairing.Round.Value == round).OrderBy(p => p.Y).FirstOrDefault(); if (topPairing == null) continue; - headings.Add(new DrawableTournamentGrouping(group, true) + headings.Add(new DrawableTournamentRound(round, true) { Position = headings.ToLocalSpace((topPairing.ScreenSpaceDrawQuad.TopLeft + topPairing.ScreenSpaceDrawQuad.TopRight) / 2), Margin = new MarginPadding { Bottom = 10 }, diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 47d5a36a4b..2c14dad38b 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -179,7 +179,7 @@ namespace osu.Game.Tournament.Screens.MapPool if (currentMatch.Value == null) return; - if (currentMatch.Value.Grouping.Value.Beatmaps.All(b => b.BeatmapInfo.OnlineBeatmapID != beatmapId)) + if (currentMatch.Value.Round.Value.Beatmaps.All(b => b.BeatmapInfo.OnlineBeatmapID != beatmapId)) // don't attempt to add if the beatmap isn't in our pool return; @@ -207,12 +207,12 @@ namespace osu.Game.Tournament.Screens.MapPool { mapFlows.Clear(); - if (match.NewValue.Grouping.Value != null) + if (match.NewValue.Round.Value != null) { FillFlowContainer currentFlow = null; string currentMod = null; - foreach (var b in match.NewValue.Grouping.Value.Beatmaps) + foreach (var b in match.NewValue.Round.Value.Beatmaps) { if (currentFlow == null || currentMod != b.Mods) { diff --git a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs b/osu.Game.Tournament/Screens/Rounds/RoundEditorScreen.cs similarity index 80% rename from osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs rename to osu.Game.Tournament/Screens/Rounds/RoundEditorScreen.cs index 45dc769c19..69808032cc 100644 --- a/osu.Game.Tournament/Screens/Groupings/GroupingsEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Rounds/RoundEditorScreen.cs @@ -14,13 +14,13 @@ using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Ladder.Components; using osuTK; -namespace osu.Game.Tournament.Screens.Groupings +namespace osu.Game.Tournament.Screens.Rounds { - public class GroupingsEditorScreen : TournamentScreen, IProvideVideo + public class RoundEditorScreen : TournamentScreen, IProvideVideo { - private readonly FillFlowContainer items; + private readonly FillFlowContainer items; - public GroupingsEditorScreen() + public RoundEditorScreen() { AddRangeInternal(new Drawable[] { @@ -35,7 +35,7 @@ namespace osu.Game.Tournament.Screens.Groupings Width = 0.9f, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Child = items = new FillFlowContainer + Child = items = new FillFlowContainer { Direction = FillDirection.Vertical, RelativeSizeAxes = Axes.X, @@ -62,13 +62,13 @@ namespace osu.Game.Tournament.Screens.Groupings [BackgroundDependencyLoader] private void load() { - foreach (var g in LadderInfo.Groupings) - items.Add(new GroupingRow(g)); + foreach (var r in LadderInfo.Rounds) + items.Add(new RoundRow(r)); } private void addNew() { - var grouping = new TournamentGrouping + var round = new TournamentRound { StartDate = { @@ -76,22 +76,22 @@ namespace osu.Game.Tournament.Screens.Groupings } }; - items.Add(new GroupingRow(grouping)); - LadderInfo.Groupings.Add(grouping); + items.Add(new RoundRow(round)); + LadderInfo.Rounds.Add(round); } - public class GroupingRow : CompositeDrawable + public class RoundRow : CompositeDrawable { - public readonly TournamentGrouping Grouping; + public readonly TournamentRound Round; [Resolved] private LadderInfo ladderInfo { get; set; } - public GroupingRow(TournamentGrouping grouping) + public RoundRow(TournamentRound round) { Margin = new MarginPadding(10); - Grouping = grouping; + Round = round; InternalChildren = new Drawable[] { new Box @@ -113,25 +113,25 @@ namespace osu.Game.Tournament.Screens.Groupings { LabelText = "Name", Width = 0.33f, - Bindable = Grouping.Name + Bindable = Round.Name }, new SettingsTextBox { LabelText = "Description", Width = 0.33f, - Bindable = Grouping.Description + Bindable = Round.Description }, new DateTextBox { LabelText = "Start Time", Width = 0.33f, - Bindable = Grouping.StartDate + Bindable = Round.StartDate }, new SettingsSlider { LabelText = "Best of", Width = 0.33f, - Bindable = Grouping.BestOf + Bindable = Round.BestOf }, } }, @@ -145,7 +145,7 @@ namespace osu.Game.Tournament.Screens.Groupings Action = () => { Expire(); - ladderInfo.Groupings.Remove(Grouping); + ladderInfo.Rounds.Remove(Round); }, } }; diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index be934afe8e..956dd836bb 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -110,7 +110,7 @@ namespace osu.Game.Tournament.Screens.Schedule { Margin = new MarginPadding { Left = -10, Bottom = 10, Top = -5 }, Spacing = new Vector2(10, 0), - Text = match.NewValue.Grouping.Value?.Name.Value, + Text = match.NewValue.Round.Value?.Name.Value, Colour = Color4.Black, Font = OsuFont.GetFont(size: 20) }, diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 078d823d81..3bb26499bf 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -112,7 +112,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Colour = col, - Text = pairing.Grouping.Value?.Name.Value ?? "Unknown Grouping", + Text = pairing.Round.Value?.Name.Value ?? "Unknown Round", Spacing = new Vector2(10, 0), Font = OsuFont.GetFont(size: 50, weight: FontWeight.Light) }, diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs index c80f3b2dfb..8360b17c39 100644 --- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -133,7 +133,7 @@ namespace osu.Game.Tournament.Screens.TeamWin Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Colour = col, - Text = pairing.Grouping.Value?.Name.Value ?? "Unknown Grouping", + Text = pairing.Round.Value?.Name.Value ?? "Unknown Round", Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 50, FontWeight.Light), Spacing = new Vector2(10, 0), }, diff --git a/osu.Game.Tournament/Screens/Teams/TeamsEditorScreen.cs b/osu.Game.Tournament/Screens/Teams/TeamsEditorScreen.cs index 503e7468b0..8f536361c3 100644 --- a/osu.Game.Tournament/Screens/Teams/TeamsEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Teams/TeamsEditorScreen.cs @@ -66,8 +66,8 @@ namespace osu.Game.Tournament.Screens.Teams [BackgroundDependencyLoader] private void load() { - foreach (var g in LadderInfo.Teams) - items.Add(new TeamRow(g)); + foreach (var t in LadderInfo.Teams) + items.Add(new TeamRow(t)); } private void addNew() diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/Screens/TournamentSceneManager.cs index 2c620f4e56..720e216e96 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/Screens/TournamentSceneManager.cs @@ -12,9 +12,9 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Drawings; using osu.Game.Tournament.Screens.Gameplay; -using osu.Game.Tournament.Screens.Groupings; using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.MapPool; +using osu.Game.Tournament.Screens.Rounds; using osu.Game.Tournament.Screens.Schedule; using osu.Game.Tournament.Screens.Showcase; using osu.Game.Tournament.Screens.TeamIntro; @@ -72,7 +72,7 @@ namespace osu.Game.Tournament.Screens new LadderScreen(), new LadderEditorScreen(), new TeamsEditorScreen(), - new GroupingsEditorScreen(), + new RoundEditorScreen(), new ShowcaseScreen(), new MapPoolScreen(), new TeamIntroScreen(), @@ -106,7 +106,7 @@ namespace osu.Game.Tournament.Screens Children = new Drawable[] { new OsuButton { RelativeSizeAxes = Axes.X, Text = "Team Editor", Action = () => SetScreen(typeof(TeamsEditorScreen)) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Groupings Editor", Action = () => SetScreen(typeof(GroupingsEditorScreen)) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Rounds Editor", Action = () => SetScreen(typeof(RoundEditorScreen)) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => SetScreen(typeof(DrawingsScreen)) }, diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index e9e2d0f054..49e626d057 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -107,7 +107,7 @@ namespace osu.Game.Tournament { conditional.Team1.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == conditional.Team1Acronym); conditional.Team2.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == conditional.Team2Acronym); - conditional.Grouping.Value = pairing.Grouping.Value; + conditional.Round.Value = pairing.Round.Value; } } @@ -128,17 +128,17 @@ namespace osu.Game.Tournament } } - // link pairings to groupings - foreach (var group in ladder.Groupings) - foreach (var id in group.Pairings) + // link pairings to rounds + foreach (var round in ladder.Rounds) + foreach (var id in round.Pairings) { var found = ladder.Pairings.FirstOrDefault(p => p.ID == id); if (found != null) { - found.Grouping.Value = group; - if (group.StartDate.Value > found.Date.Value) - found.Date.Value = group.StartDate.Value; + found.Round.Value = round; + if (round.StartDate.Value > found.Date.Value) + found.Date.Value = round.StartDate.Value; } } @@ -179,8 +179,8 @@ namespace osu.Game.Tournament { bool addedInfo = false; - foreach (var g in ladder.Groupings) - foreach (var b in g.Beatmaps) + foreach (var r in ladder.Rounds) + foreach (var b in r.Beatmaps) if (b.BeatmapInfo == null) { var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); @@ -245,8 +245,8 @@ namespace osu.Game.Tournament protected virtual void SaveChanges() { - foreach (var g in ladder.Groupings) - g.Pairings = ladder.Pairings.Where(p => p.Grouping.Value == g).Select(p => p.ID).ToList(); + foreach (var r in ladder.Rounds) + r.Pairings = ladder.Pairings.Where(p => p.Round.Value == r).Select(p => p.ID).ToList(); ladder.Progressions = ladder.Pairings.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( ladder.Pairings.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) From 96e24ebd20eec8a005fc469da3d868ea576dce41 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 14:51:48 +0900 Subject: [PATCH 1311/5608] General namespace tidy-up --- osu.Game.Tournament.Tests/LadderTestScene.cs | 1 + .../TestSceneGroupingsEditorScreen.cs | 2 +- osu.Game.Tournament.Tests/TestSceneMatchPairings.cs | 1 + osu.Game.Tournament.Tests/TestSceneSceneManager.cs | 1 - osu.Game.Tournament.Tests/TestSceneTeamIntro.cs | 2 +- osu.Game.Tournament.Tests/TestSceneTeamWin.cs | 2 +- osu.Game.Tournament.Tests/TestSceneTeamsEditorScreen.cs | 2 +- .../TestSceneTournamentMatchChatDisplay.cs | 2 +- osu.Game.Tournament/Components/DrawableTournamentTeam.cs | 1 + osu.Game.Tournament/Components/TournamentBeatmapPanel.cs | 2 +- .../Components/TournamentMatchChatDisplay.cs | 1 + osu.Game.Tournament/IPC/FileBasedIPC.cs | 1 + .../{Screens/Ladder/Components => Models}/BeatmapChoice.cs | 2 +- .../Ladder/Components => Models}/LadderEditorInfo.cs | 2 +- osu.Game.Tournament/{ => Models}/LadderInfo.cs | 4 +--- .../{Screens/Ladder/Components => Models}/MatchPairing.cs | 4 ++-- .../{Screens/Ladder/Components => Models}/RoundBeatmap.cs | 2 +- .../Ladder/Components => Models}/TournamentProgression.cs | 2 +- .../Ladder/Components => Models}/TournamentRound.cs | 2 +- .../{Components => Models}/TournamentTeam.cs | 2 +- osu.Game.Tournament/Screens/Drawings/Components/Group.cs | 1 + .../Screens/Drawings/Components/GroupContainer.cs | 2 +- .../Screens/Drawings/Components/ITeamList.cs | 2 +- .../Screens/Drawings/Components/ScrollingTeamContainer.cs | 1 + .../Screens/Drawings/Components/StorageBackedTeamList.cs | 2 +- osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs | 1 + .../Screens/{Ladder => Editors}/LadderEditorScreen.cs | 4 +++- .../Screens/{Rounds => Editors}/RoundEditorScreen.cs | 4 ++-- .../Screens/{Teams => Editors}/TeamsEditorScreen.cs | 3 ++- .../Screens/Gameplay/Components/MatchHeader.cs | 2 +- .../Screens/Gameplay/Components/MatchScoreDisplay.cs | 1 + osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs | 2 +- osu.Game.Tournament/Screens/IProvideVideo.cs | 3 +++ .../Screens/Ladder/Components/ConditionalMatchPairing.cs | 2 ++ .../Screens/Ladder/Components/DrawableMatchPairing.cs | 2 +- .../Screens/Ladder/Components/DrawableMatchTeam.cs | 2 ++ .../Screens/Ladder/Components/DrawableTournamentRound.cs | 1 + .../Screens/Ladder/Components/LadderEditorSettings.cs | 1 + osu.Game.Tournament/Screens/Ladder/LadderScreen.cs | 2 ++ osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 2 +- osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs | 1 + osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs | 2 +- osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs | 2 +- osu.Game.Tournament/Screens/TournamentScreen.cs | 5 +++-- osu.Game.Tournament/TournamentGame.cs | 1 - osu.Game.Tournament/TournamentGameBase.cs | 3 +-- .../{Screens => }/TournamentSceneManager.cs | 7 ++++--- osu.Game.Tournament/osu.Game.Tournament.csproj | 3 +++ 48 files changed, 63 insertions(+), 39 deletions(-) rename osu.Game.Tournament/{Screens/Ladder/Components => Models}/BeatmapChoice.cs (92%) rename osu.Game.Tournament/{Screens/Ladder/Components => Models}/LadderEditorInfo.cs (85%) rename osu.Game.Tournament/{ => Models}/LadderInfo.cs (86%) rename osu.Game.Tournament/{Screens/Ladder/Components => Models}/MatchPairing.cs (97%) rename osu.Game.Tournament/{Screens/Ladder/Components => Models}/RoundBeatmap.cs (84%) rename osu.Game.Tournament/{Screens/Ladder/Components => Models}/TournamentProgression.cs (92%) rename osu.Game.Tournament/{Screens/Ladder/Components => Models}/TournamentRound.cs (94%) rename osu.Game.Tournament/{Components => Models}/TournamentTeam.cs (97%) rename osu.Game.Tournament/Screens/{Ladder => Editors}/LadderEditorScreen.cs (97%) rename osu.Game.Tournament/Screens/{Rounds => Editors}/RoundEditorScreen.cs (98%) rename osu.Game.Tournament/Screens/{Teams => Editors}/TeamsEditorScreen.cs (99%) rename osu.Game.Tournament/{Screens => }/TournamentSceneManager.cs (97%) diff --git a/osu.Game.Tournament.Tests/LadderTestScene.cs b/osu.Game.Tournament.Tests/LadderTestScene.cs index cb55f543f6..5bb8112157 100644 --- a/osu.Game.Tournament.Tests/LadderTestScene.cs +++ b/osu.Game.Tournament.Tests/LadderTestScene.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Game.Tests.Visual; +using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Tests { diff --git a/osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs b/osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs index 0ef19c2948..e0a6f8e8b9 100644 --- a/osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs +++ b/osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Tournament.Screens.Rounds; +using osu.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests { diff --git a/osu.Game.Tournament.Tests/TestSceneMatchPairings.cs b/osu.Game.Tournament.Tests/TestSceneMatchPairings.cs index 611e87717a..42b68d654c 100644 --- a/osu.Game.Tournament.Tests/TestSceneMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestSceneMatchPairings.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Tests diff --git a/osu.Game.Tournament.Tests/TestSceneSceneManager.cs b/osu.Game.Tournament.Tests/TestSceneSceneManager.cs index 385dc09d58..aa333e39b1 100644 --- a/osu.Game.Tournament.Tests/TestSceneSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestSceneSceneManager.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Platform; using osu.Game.Tests.Visual; -using osu.Game.Tournament.Screens; namespace osu.Game.Tournament.Tests { diff --git a/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs b/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs index 560a8f9521..9f0d59fcbc 100644 --- a/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs +++ b/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs @@ -5,7 +5,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.TeamIntro; namespace osu.Game.Tournament.Tests diff --git a/osu.Game.Tournament.Tests/TestSceneTeamWin.cs b/osu.Game.Tournament.Tests/TestSceneTeamWin.cs index 9f642103de..8beeb50513 100644 --- a/osu.Game.Tournament.Tests/TestSceneTeamWin.cs +++ b/osu.Game.Tournament.Tests/TestSceneTeamWin.cs @@ -5,7 +5,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.TeamWin; namespace osu.Game.Tournament.Tests diff --git a/osu.Game.Tournament.Tests/TestSceneTeamsEditorScreen.cs b/osu.Game.Tournament.Tests/TestSceneTeamsEditorScreen.cs index d3268219b3..60323e1d84 100644 --- a/osu.Game.Tournament.Tests/TestSceneTeamsEditorScreen.cs +++ b/osu.Game.Tournament.Tests/TestSceneTeamsEditorScreen.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Tournament.Screens.Teams; +using osu.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests { diff --git a/osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs index 8a3950bac3..125bf5679c 100644 --- a/osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs @@ -8,7 +8,7 @@ using osu.Game.Online.Chat; using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; -using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Models; using osu.Game.Users; namespace osu.Game.Tournament.Tests diff --git a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs index 704d5a47de..361bd92770 100644 --- a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Components { diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index cf826ee2c7..aee7f914e7 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -16,7 +16,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Models; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs index 2afbb0f5ff..48c5b9bd35 100644 --- a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Game.Online.Chat; using osu.Game.Overlays.Chat; using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Models; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 438e32c20f..23ebe2f39c 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps.Legacy; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Rulesets; +using osu.Game.Tournament.Models; namespace osu.Game.Tournament.IPC { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs b/osu.Game.Tournament/Models/BeatmapChoice.cs similarity index 92% rename from osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs rename to osu.Game.Tournament/Models/BeatmapChoice.cs index bb9ed39b82..c22077553b 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/BeatmapChoice.cs +++ b/osu.Game.Tournament/Models/BeatmapChoice.cs @@ -4,7 +4,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; -namespace osu.Game.Tournament.Screens.Ladder.Components +namespace osu.Game.Tournament.Models { public class BeatmapChoice { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs b/osu.Game.Tournament/Models/LadderEditorInfo.cs similarity index 85% rename from osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs rename to osu.Game.Tournament/Models/LadderEditorInfo.cs index d6b5d172de..9bf01e76f5 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorInfo.cs +++ b/osu.Game.Tournament/Models/LadderEditorInfo.cs @@ -3,7 +3,7 @@ using osu.Framework.Bindables; -namespace osu.Game.Tournament.Screens.Ladder.Components +namespace osu.Game.Tournament.Models { public class LadderEditorInfo { diff --git a/osu.Game.Tournament/LadderInfo.cs b/osu.Game.Tournament/Models/LadderInfo.cs similarity index 86% rename from osu.Game.Tournament/LadderInfo.cs rename to osu.Game.Tournament/Models/LadderInfo.cs index fc825d1a9c..2fdf1b06b1 100644 --- a/osu.Game.Tournament/LadderInfo.cs +++ b/osu.Game.Tournament/Models/LadderInfo.cs @@ -4,10 +4,8 @@ using System.Collections.Generic; using Newtonsoft.Json; using osu.Framework.Bindables; -using osu.Game.Tournament.Components; -using osu.Game.Tournament.Screens.Ladder.Components; -namespace osu.Game.Tournament +namespace osu.Game.Tournament.Models { public class LadderInfo { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs b/osu.Game.Tournament/Models/MatchPairing.cs similarity index 97% rename from osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs rename to osu.Game.Tournament/Models/MatchPairing.cs index 4ff2df1388..caafe8af47 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/MatchPairing.cs +++ b/osu.Game.Tournament/Models/MatchPairing.cs @@ -6,10 +6,10 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using Newtonsoft.Json; using osu.Framework.Bindables; -using osu.Game.Tournament.Components; +using osu.Game.Tournament.Screens.Ladder.Components; using SixLabors.Primitives; -namespace osu.Game.Tournament.Screens.Ladder.Components +namespace osu.Game.Tournament.Models { /// /// A collection of two teams competing in a head-to-head match. diff --git a/osu.Game.Tournament/Screens/Ladder/Components/RoundBeatmap.cs b/osu.Game.Tournament/Models/RoundBeatmap.cs similarity index 84% rename from osu.Game.Tournament/Screens/Ladder/Components/RoundBeatmap.cs rename to osu.Game.Tournament/Models/RoundBeatmap.cs index ef608c3f06..5d43d0ca66 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/RoundBeatmap.cs +++ b/osu.Game.Tournament/Models/RoundBeatmap.cs @@ -3,7 +3,7 @@ using osu.Game.Beatmaps; -namespace osu.Game.Tournament.Screens.Ladder.Components +namespace osu.Game.Tournament.Models { public class RoundBeatmap { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs b/osu.Game.Tournament/Models/TournamentProgression.cs similarity index 92% rename from osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs rename to osu.Game.Tournament/Models/TournamentProgression.cs index 0019dc8d79..4ef4be599d 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentProgression.cs +++ b/osu.Game.Tournament/Models/TournamentProgression.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -namespace osu.Game.Tournament.Screens.Ladder.Components +namespace osu.Game.Tournament.Models { public class TournamentProgression { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/TournamentRound.cs b/osu.Game.Tournament/Models/TournamentRound.cs similarity index 94% rename from osu.Game.Tournament/Screens/Ladder/Components/TournamentRound.cs rename to osu.Game.Tournament/Models/TournamentRound.cs index 79b94e06a2..6fe4b20fa5 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/TournamentRound.cs +++ b/osu.Game.Tournament/Models/TournamentRound.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using Newtonsoft.Json; using osu.Framework.Bindables; -namespace osu.Game.Tournament.Screens.Ladder.Components +namespace osu.Game.Tournament.Models { [Serializable] public class TournamentRound diff --git a/osu.Game.Tournament/Components/TournamentTeam.cs b/osu.Game.Tournament/Models/TournamentTeam.cs similarity index 97% rename from osu.Game.Tournament/Components/TournamentTeam.cs rename to osu.Game.Tournament/Models/TournamentTeam.cs index 043dcc7084..eea1ef8104 100644 --- a/osu.Game.Tournament/Components/TournamentTeam.cs +++ b/osu.Game.Tournament/Models/TournamentTeam.cs @@ -6,7 +6,7 @@ using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Game.Users; -namespace osu.Game.Tournament.Components +namespace osu.Game.Tournament.Models { [Serializable] public class TournamentTeam diff --git a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs index adeead277c..549ff26018 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs index 6e56dca2fb..8a66ca7bf6 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs @@ -7,7 +7,7 @@ using System.Linq; using System.Text; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; using osuTK; namespace osu.Game.Tournament.Screens.Drawings.Components diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs index a532f47176..09208818a9 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens.Drawings.Components { diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index 486ce7fe74..b147d680f0 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs index ca3536965f..f96ec01cbb 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.IO; using osu.Framework.Logging; using osu.Framework.Platform; -using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens.Drawings.Components { diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 2ef7f513b6..52ba73c27c 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -17,6 +17,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Drawings.Components; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs similarity index 97% rename from osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs rename to osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs index fc98753e0a..9b298df91d 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs @@ -11,12 +11,14 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Graphics.UserInterface; +using osu.Game.Tournament.Models; +using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.Ladder.Components; using osuTK; using osuTK.Graphics; using SixLabors.Primitives; -namespace osu.Game.Tournament.Screens.Ladder +namespace osu.Game.Tournament.Screens.Editors { [Cached] public class LadderEditorScreen : LadderScreen, IHasContextMenu diff --git a/osu.Game.Tournament/Screens/Rounds/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs similarity index 98% rename from osu.Game.Tournament/Screens/Rounds/RoundEditorScreen.cs rename to osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 69808032cc..c8c2461b10 100644 --- a/osu.Game.Tournament/Screens/Rounds/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -11,10 +11,10 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; -using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Models; using osuTK; -namespace osu.Game.Tournament.Screens.Rounds +namespace osu.Game.Tournament.Screens.Editors { public class RoundEditorScreen : TournamentScreen, IProvideVideo { diff --git a/osu.Game.Tournament/Screens/Teams/TeamsEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamsEditorScreen.cs similarity index 99% rename from osu.Game.Tournament/Screens/Teams/TeamsEditorScreen.cs rename to osu.Game.Tournament/Screens/Editors/TeamsEditorScreen.cs index 8f536361c3..1bf3f1c6b9 100644 --- a/osu.Game.Tournament/Screens/Teams/TeamsEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamsEditorScreen.cs @@ -14,10 +14,11 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; using osu.Game.Users; using osuTK; -namespace osu.Game.Tournament.Screens.Teams +namespace osu.Game.Tournament.Screens.Editors { public class TeamsEditorScreen : TournamentScreen, IProvideVideo { diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index 71cfacdc32..e75872cda4 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; -using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Showcase; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs index fc28ddccfd..78455c8bb7 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Models; using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Gameplay.Components diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index fad1919510..7b108731f3 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -10,8 +10,8 @@ using osu.Framework.Threading; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Gameplay.Components; -using osu.Game.Tournament.Screens.Ladder.Components; using osu.Game.Tournament.Screens.MapPool; using osu.Game.Tournament.Screens.TeamWin; using osuTK; diff --git a/osu.Game.Tournament/Screens/IProvideVideo.cs b/osu.Game.Tournament/Screens/IProvideVideo.cs index c11c921412..61989d8448 100644 --- a/osu.Game.Tournament/Screens/IProvideVideo.cs +++ b/osu.Game.Tournament/Screens/IProvideVideo.cs @@ -3,6 +3,9 @@ namespace osu.Game.Tournament.Screens { + /// + /// Marker interface for a screen which provides its own local video background. + /// public interface IProvideVideo { } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs index 7831cac84d..f3b5678c7c 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Tournament.Models; + namespace osu.Game.Tournament.Screens.Ladder.Components { /// diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index 35741cbb55..e48155ab0e 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; -using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; using osuTK; using osuTK.Graphics; using osuTK.Input; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 6d5ac74267..5514dfce3e 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -14,6 +14,8 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; +using osu.Game.Tournament.Screens.Editors; using osuTK; using osuTK.Graphics; using osuTK.Input; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs index 844c89a968..67d6bc4fa6 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Tournament.Models; using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Ladder.Components diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index a4b74f00a2..d947215cfa 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -11,6 +11,7 @@ using osu.Framework.Input.Events; using osu.Game.Overlays.Settings; using osu.Game.Screens.Play.PlayerSettings; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens.Ladder.Components { diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 6a77c6c20e..50675a6147 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -11,6 +11,8 @@ using osu.Framework.Graphics.Lines; using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; +using osu.Game.Tournament.Screens.Editors; using osu.Game.Tournament.Screens.Ladder.Components; using osuTK.Graphics; diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 2c14dad38b..ab03adbce9 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -13,9 +13,9 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Gameplay; using osu.Game.Tournament.Screens.Gameplay.Components; -using osu.Game.Tournament.Screens.Ladder.Components; using osuTK; using osuTK.Graphics; using osuTK.Input; diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index 956dd836bb..457fb80141 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -12,6 +12,7 @@ using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Ladder.Components; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 3bb26499bf..4e0bb23a62 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -9,7 +9,7 @@ using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Tournament.Components; -using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Showcase; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs index 8360b17c39..0a37cf6c4a 100644 --- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -9,7 +9,7 @@ using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Tournament.Components; -using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Showcase; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Tournament/Screens/TournamentScreen.cs b/osu.Game.Tournament/Screens/TournamentScreen.cs index 7f6c5f8e18..9d58ca2240 100644 --- a/osu.Game.Tournament/Screens/TournamentScreen.cs +++ b/osu.Game.Tournament/Screens/TournamentScreen.cs @@ -4,15 +4,16 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens { - public class TournamentScreen : CompositeDrawable + public abstract class TournamentScreen : CompositeDrawable { [Resolved] protected LadderInfo LadderInfo { get; private set; } - public TournamentScreen() + protected TournamentScreen() { RelativeSizeAxes = Axes.Both; } diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index c8c462a458..42e4ab3c13 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Cursor; -using osu.Game.Tournament.Screens; namespace osu.Game.Tournament { diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 49e626d057..e35e0b0d30 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -19,9 +19,8 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests; using osu.Game.Rulesets; -using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; -using osu.Game.Tournament.Screens.Ladder.Components; +using osu.Game.Tournament.Models; using osuTK.Input; namespace osu.Game.Tournament diff --git a/osu.Game.Tournament/Screens/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs similarity index 97% rename from osu.Game.Tournament/Screens/TournamentSceneManager.cs rename to osu.Game.Tournament/TournamentSceneManager.cs index 720e216e96..29f8eba579 100644 --- a/osu.Game.Tournament/Screens/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -10,20 +10,21 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Platform; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; +using osu.Game.Tournament.Screens; using osu.Game.Tournament.Screens.Drawings; +using osu.Game.Tournament.Screens.Editors; using osu.Game.Tournament.Screens.Gameplay; using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.MapPool; -using osu.Game.Tournament.Screens.Rounds; using osu.Game.Tournament.Screens.Schedule; using osu.Game.Tournament.Screens.Showcase; using osu.Game.Tournament.Screens.TeamIntro; -using osu.Game.Tournament.Screens.Teams; using osu.Game.Tournament.Screens.TeamWin; using osuTK; using osuTK.Graphics; -namespace osu.Game.Tournament.Screens +namespace osu.Game.Tournament { [Cached] public class TournamentSceneManager : CompositeDrawable diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index 8adff80820..8412166250 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -10,4 +10,7 @@ + + + \ No newline at end of file From da20904a57bb48dc8b1bd3d20a6c0b857967fa36 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 14:57:05 +0900 Subject: [PATCH 1312/5608] MatchPairing -> TournamentMatch --- .../TestSceneMatchPairings.cs | 50 ++++----- .../TestSceneTeamIntro.cs | 12 +-- osu.Game.Tournament.Tests/TestSceneTeamWin.cs | 12 +-- .../TestSceneTournamentMatchChatDisplay.cs | 2 +- .../Components/TournamentBeatmapPanel.cs | 10 +- .../Models/LadderEditorInfo.cs | 2 +- osu.Game.Tournament/Models/LadderInfo.cs | 4 +- .../{MatchPairing.cs => TournamentMatch.cs} | 12 +-- osu.Game.Tournament/Models/TournamentRound.cs | 2 +- .../Screens/Editors/LadderEditorScreen.cs | 36 +++---- .../Gameplay/Components/MatchHeader.cs | 8 +- .../Screens/Gameplay/GameplayScreen.cs | 2 +- ...iring.cs => ConditionalTournamentMatch.cs} | 4 +- .../Ladder/Components/DrawableMatchPairing.cs | 102 +++++++++--------- .../Ladder/Components/DrawableMatchTeam.cs | 34 +++--- .../Ladder/Components/ProgressionPath.cs | 6 +- .../Screens/Ladder/LadderScreen.cs | 56 +++++----- .../Screens/MapPool/MapPoolScreen.cs | 4 +- .../Screens/Schedule/ScheduleScreen.cs | 30 +++--- .../Screens/TeamIntro/TeamIntroScreen.cs | 18 ++-- .../Screens/TeamWin/TeamWinScreen.cs | 22 ++-- osu.Game.Tournament/TournamentGameBase.cs | 28 ++--- 22 files changed, 228 insertions(+), 228 deletions(-) rename osu.Game.Tournament/Models/{MatchPairing.cs => TournamentMatch.cs} (88%) rename osu.Game.Tournament/Screens/Ladder/Components/{ConditionalMatchPairing.cs => ConditionalTournamentMatch.cs} (72%) diff --git a/osu.Game.Tournament.Tests/TestSceneMatchPairings.cs b/osu.Game.Tournament.Tests/TestSceneMatchPairings.cs index 42b68d654c..9c8ee2965e 100644 --- a/osu.Game.Tournament.Tests/TestSceneMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestSceneMatchPairings.cs @@ -12,22 +12,22 @@ using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Tests { - public class TestSceneMatchPairings : OsuTestScene + public class TestSceneMatches : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { - typeof(MatchPairing), - typeof(DrawableMatchPairing), + typeof(TournamentMatch), + typeof(DrawableTournamentMatch), typeof(DrawableMatchTeam), typeof(DrawableTournamentTeam), }; - public TestSceneMatchPairings() + public TestSceneMatches() { - Container level1; - Container level2; + Container level1; + Container level2; - var pairing1 = new MatchPairing( + var match1 = new TournamentMatch( new TournamentTeam { FlagName = { Value = "AU" }, FullName = { Value = "Australia" }, }, new TournamentTeam { FlagName = { Value = "JP" }, FullName = { Value = "Japan" }, Acronym = { Value = "JPN" } }) { @@ -35,7 +35,7 @@ namespace osu.Game.Tournament.Tests Team2Score = { Value = 1 }, }; - var pairing2 = new MatchPairing( + var match2 = new TournamentMatch( new TournamentTeam { FlagName = { Value = "RO" }, @@ -49,47 +49,47 @@ namespace osu.Game.Tournament.Tests Direction = FillDirection.Horizontal, Children = new Drawable[] { - level1 = new FillFlowContainer + level1 = new FillFlowContainer { AutoSizeAxes = Axes.X, Direction = FillDirection.Vertical, Children = new[] { - new DrawableMatchPairing(pairing1), - new DrawableMatchPairing(pairing2), - new DrawableMatchPairing(new MatchPairing()), + new DrawableTournamentMatch(match1), + new DrawableTournamentMatch(match2), + new DrawableTournamentMatch(new TournamentMatch()), } }, - level2 = new FillFlowContainer + level2 = new FillFlowContainer { AutoSizeAxes = Axes.X, Direction = FillDirection.Vertical, Margin = new MarginPadding(20), Children = new[] { - new DrawableMatchPairing(new MatchPairing()), - new DrawableMatchPairing(new MatchPairing()) + new DrawableTournamentMatch(new TournamentMatch()), + new DrawableTournamentMatch(new TournamentMatch()) } } } }; - level1.Children[0].Pairing.Progression.Value = level2.Children[0].Pairing; - level1.Children[1].Pairing.Progression.Value = level2.Children[0].Pairing; + level1.Children[0].Match.Progression.Value = level2.Children[0].Match; + level1.Children[1].Match.Progression.Value = level2.Children[0].Match; - AddRepeatStep("change scores", () => pairing1.Team2Score.Value++, 4); - AddStep("add new team", () => pairing2.Team2.Value = new TournamentTeam { FlagName = { Value = "PT" }, FullName = { Value = "Portugal" } }); - AddStep("Add progression", () => level1.Children[2].Pairing.Progression.Value = level2.Children[1].Pairing); + AddRepeatStep("change scores", () => match1.Team2Score.Value++, 4); + AddStep("add new team", () => match2.Team2.Value = new TournamentTeam { FlagName = { Value = "PT" }, FullName = { Value = "Portugal" } }); + AddStep("Add progression", () => level1.Children[2].Match.Progression.Value = level2.Children[1].Match); - AddStep("start match", () => pairing2.StartMatch()); + AddStep("start match", () => match2.StartMatch()); - AddRepeatStep("change scores", () => pairing2.Team1Score.Value++, 10); + AddRepeatStep("change scores", () => match2.Team1Score.Value++, 10); - AddStep("start submatch", () => level2.Children[0].Pairing.StartMatch()); + AddStep("start submatch", () => level2.Children[0].Match.StartMatch()); - AddRepeatStep("change scores", () => level2.Children[0].Pairing.Team1Score.Value++, 5); + AddRepeatStep("change scores", () => level2.Children[0].Match.Team1Score.Value++, 5); - AddRepeatStep("change scores", () => level2.Children[0].Pairing.Team2Score.Value++, 4); + AddRepeatStep("change scores", () => level2.Children[0].Match.Team2Score.Value++, 4); } } } diff --git a/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs b/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs index 9f0d59fcbc..6b31fd2742 100644 --- a/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs +++ b/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs @@ -13,16 +13,16 @@ namespace osu.Game.Tournament.Tests public class TestSceneTeamIntro : LadderTestScene { [Cached] - private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentMatch = new Bindable(); [BackgroundDependencyLoader] private void load() { - var pairing = new MatchPairing(); - pairing.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA"); - pairing.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN"); - pairing.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals"); - currentMatch.Value = pairing; + var match = new TournamentMatch(); + match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA"); + match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN"); + match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals"); + currentMatch.Value = match; Add(new TeamIntroScreen { diff --git a/osu.Game.Tournament.Tests/TestSceneTeamWin.cs b/osu.Game.Tournament.Tests/TestSceneTeamWin.cs index 8beeb50513..d195ad42ca 100644 --- a/osu.Game.Tournament.Tests/TestSceneTeamWin.cs +++ b/osu.Game.Tournament.Tests/TestSceneTeamWin.cs @@ -13,16 +13,16 @@ namespace osu.Game.Tournament.Tests public class TestSceneTeamWin : LadderTestScene { [Cached] - private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentMatch = new Bindable(); [BackgroundDependencyLoader] private void load() { - var pairing = new MatchPairing(); - pairing.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA"); - pairing.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN"); - pairing.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals"); - currentMatch.Value = pairing; + var match = new TournamentMatch(); + match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA"); + match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN"); + match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals"); + currentMatch.Value = match; Add(new TeamWinScreen { diff --git a/osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs index 125bf5679c..829d8629e5 100644 --- a/osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs @@ -53,7 +53,7 @@ namespace osu.Game.Tournament.Tests Origin = Anchor.Centre, }); - ladderInfo.CurrentMatch.Value = new MatchPairing + ladderInfo.CurrentMatch.Value = new TournamentMatch { Team1 = { diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index aee7f914e7..f7ca25adba 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tournament.Components public const float HEIGHT = 50; - private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentMatch = new Bindable(); private Box flash; public TournamentBeatmapPanel(BeatmapInfo beatmap, string mods = null) @@ -141,11 +141,11 @@ namespace osu.Game.Tournament.Components }); } - private void matchChanged(ValueChangedEvent pairing) + private void matchChanged(ValueChangedEvent match) { - if (pairing.OldValue != null) - pairing.OldValue.PicksBans.CollectionChanged -= picksBansOnCollectionChanged; - pairing.NewValue.PicksBans.CollectionChanged += picksBansOnCollectionChanged; + if (match.OldValue != null) + match.OldValue.PicksBans.CollectionChanged -= picksBansOnCollectionChanged; + match.NewValue.PicksBans.CollectionChanged += picksBansOnCollectionChanged; updateState(); } diff --git a/osu.Game.Tournament/Models/LadderEditorInfo.cs b/osu.Game.Tournament/Models/LadderEditorInfo.cs index 9bf01e76f5..70fd115e25 100644 --- a/osu.Game.Tournament/Models/LadderEditorInfo.cs +++ b/osu.Game.Tournament/Models/LadderEditorInfo.cs @@ -7,6 +7,6 @@ namespace osu.Game.Tournament.Models { public class LadderEditorInfo { - public readonly Bindable Selected = new Bindable(); + public readonly Bindable Selected = new Bindable(); } } diff --git a/osu.Game.Tournament/Models/LadderInfo.cs b/osu.Game.Tournament/Models/LadderInfo.cs index 2fdf1b06b1..b6dc59c0d9 100644 --- a/osu.Game.Tournament/Models/LadderInfo.cs +++ b/osu.Game.Tournament/Models/LadderInfo.cs @@ -9,7 +9,7 @@ namespace osu.Game.Tournament.Models { public class LadderInfo { - public BindableList Pairings = new BindableList(); + public BindableList Matches = new BindableList(); public BindableList Rounds = new BindableList(); public BindableList Teams = new BindableList(); @@ -17,6 +17,6 @@ namespace osu.Game.Tournament.Models public List Progressions = new List(); [JsonIgnore] - public Bindable CurrentMatch = new Bindable(); + public Bindable CurrentMatch = new Bindable(); } } diff --git a/osu.Game.Tournament/Models/MatchPairing.cs b/osu.Game.Tournament/Models/TournamentMatch.cs similarity index 88% rename from osu.Game.Tournament/Models/MatchPairing.cs rename to osu.Game.Tournament/Models/TournamentMatch.cs index caafe8af47..db41e83038 100644 --- a/osu.Game.Tournament/Models/MatchPairing.cs +++ b/osu.Game.Tournament/Models/TournamentMatch.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tournament.Models /// A collection of two teams competing in a head-to-head match. /// [Serializable] - public class MatchPairing + public class TournamentMatch { public int ID; @@ -54,10 +54,10 @@ namespace osu.Game.Tournament.Models public readonly Bindable Round = new Bindable(); [JsonIgnore] - public readonly Bindable Progression = new Bindable(); + public readonly Bindable Progression = new Bindable(); [JsonIgnore] - public readonly Bindable LosersProgression = new Bindable(); + public readonly Bindable LosersProgression = new Bindable(); /// /// Should not be set directly. Use LadderInfo.CurrentMatch.Value = this instead. @@ -67,17 +67,17 @@ namespace osu.Game.Tournament.Models public readonly Bindable Date = new Bindable(); [JsonProperty] - public readonly BindableList ConditionalPairings = new BindableList(); + public readonly BindableList ConditionalMatches = new BindableList(); public readonly Bindable Position = new Bindable(); - public MatchPairing() + public TournamentMatch() { Team1.BindValueChanged(t => Team1Acronym = t.NewValue?.Acronym.Value, true); Team2.BindValueChanged(t => Team2Acronym = t.NewValue?.Acronym.Value, true); } - public MatchPairing(TournamentTeam team1 = null, TournamentTeam team2 = null) + public TournamentMatch(TournamentTeam team1 = null, TournamentTeam team2 = null) : this() { Team1.Value = team1; diff --git a/osu.Game.Tournament/Models/TournamentRound.cs b/osu.Game.Tournament/Models/TournamentRound.cs index 6fe4b20fa5..e325ad4b96 100644 --- a/osu.Game.Tournament/Models/TournamentRound.cs +++ b/osu.Game.Tournament/Models/TournamentRound.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tournament.Models public readonly Bindable StartDate = new Bindable(); // only used for serialisation - public List Pairings = new List(); + public List Matches = new List(); public override string ToString() => Name.Value ?? "None"; } diff --git a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs index 9b298df91d..ba63013886 100644 --- a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs @@ -39,9 +39,9 @@ namespace osu.Game.Tournament.Screens.Editors }); } - public void BeginJoin(MatchPairing pairing, bool losers) + public void BeginJoin(TournamentMatch match, bool losers) { - ScrollContent.Add(new JoinVisualiser(PairingsContainer, pairing, losers, UpdateLayout)); + ScrollContent.Add(new JoinVisualiser(MatchesContainer, match, losers, UpdateLayout)); } public MenuItem[] ContextMenuItems @@ -55,35 +55,35 @@ namespace osu.Game.Tournament.Screens.Editors { new OsuMenuItem("Create new match", MenuItemType.Highlighted, () => { - var pos = PairingsContainer.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position); - LadderInfo.Pairings.Add(new MatchPairing { Position = { Value = new Point((int)pos.X, (int)pos.Y) } }); + var pos = MatchesContainer.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position); + LadderInfo.Matches.Add(new TournamentMatch { Position = { Value = new Point((int)pos.X, (int)pos.Y) } }); }), new OsuMenuItem("Reset teams", MenuItemType.Destructive, () => { - foreach (var p in PairingsContainer) - p.Pairing.Reset(); + foreach (var p in MatchesContainer) + p.Match.Reset(); }) }; } } - public void Remove(MatchPairing pairing) + public void Remove(TournamentMatch match) { - PairingsContainer.FirstOrDefault(p => p.Pairing == pairing)?.Remove(); + MatchesContainer.FirstOrDefault(p => p.Match == match)?.Remove(); } private class JoinVisualiser : CompositeDrawable { - private readonly Container pairingsContainer; - public readonly MatchPairing Source; + private readonly Container matchesContainer; + public readonly TournamentMatch Source; private readonly bool losers; private readonly Action complete; private ProgressionPath path; - public JoinVisualiser(Container pairingsContainer, MatchPairing source, bool losers, Action complete) + public JoinVisualiser(Container matchesContainer, TournamentMatch source, bool losers, Action complete) { - this.pairingsContainer = pairingsContainer; + this.matchesContainer = matchesContainer; RelativeSizeAxes = Axes.Both; Source = source; @@ -95,9 +95,9 @@ namespace osu.Game.Tournament.Screens.Editors Source.Progression.Value = null; } - private DrawableMatchPairing findTarget(InputState state) + private DrawableTournamentMatch findTarget(InputState state) { - return pairingsContainer.FirstOrDefault(d => d.ReceivePositionalInputAt(state.Mouse.Position)); + return matchesContainer.FirstOrDefault(d => d.ReceivePositionalInputAt(state.Mouse.Position)); } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) @@ -118,7 +118,7 @@ namespace osu.Game.Tournament.Screens.Editors if (found == null) return false; - AddInternal(path = new ProgressionPath(pairingsContainer.First(c => c.Pairing == Source), found) + AddInternal(path = new ProgressionPath(matchesContainer.First(c => c.Match == Source), found) { Colour = Color4.Yellow, }); @@ -132,12 +132,12 @@ namespace osu.Game.Tournament.Screens.Editors if (found != null) { - if (found.Pairing != Source) + if (found.Match != Source) { if (losers) - Source.LosersProgression.Value = found.Pairing; + Source.LosersProgression.Value = found.Match; else - Source.Progression.Value = found.Pairing; + Source.Progression.Value = found.Match; } complete?.Invoke(); diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index e75872cda4..cfa44537d6 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -55,7 +55,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components private readonly Color4 red = new Color4(129, 68, 65, 255); private readonly Color4 blue = new Color4(41, 91, 97, 255); - private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentMatch = new Bindable(); private readonly Bindable currentTeam = new Bindable(); private readonly Bindable currentTeamScore = new Bindable(); @@ -74,7 +74,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components currentMatch.BindTo(ladder.CurrentMatch); } - private void matchChanged(ValueChangedEvent match) + private void matchChanged(ValueChangedEvent match) { currentTeamScore.UnbindBindings(); currentTeamScore.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1Score : match.NewValue.Team2Score); @@ -187,7 +187,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components private class RoundDisplay : CompositeDrawable { - private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentMatch = new Bindable(); public RoundDisplay() { @@ -204,7 +204,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components currentMatch.BindTo(ladder.CurrentMatch); } - private void matchChanged(ValueChangedEvent match) + private void matchChanged(ValueChangedEvent match) { InternalChildren = new Drawable[] { diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 7b108731f3..5bbd049cc0 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tournament.Screens.Gameplay { private readonly BindableBool warmup = new BindableBool(); - private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentMatch = new Bindable(); public readonly Bindable State = new Bindable(); private TriangleButton warmupButton; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/ConditionalTournamentMatch.cs similarity index 72% rename from osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs rename to osu.Game.Tournament/Screens/Ladder/Components/ConditionalTournamentMatch.cs index f3b5678c7c..16224a7fb4 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ConditionalMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ConditionalTournamentMatch.cs @@ -6,9 +6,9 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens.Ladder.Components { /// - /// A pairing that may not necessarily occur. + /// A match that may not necessarily occur. /// - public class ConditionalMatchPairing : MatchPairing + public class ConditionalTournamentMatch : TournamentMatch { } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs index e48155ab0e..dde280ccd8 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs @@ -17,14 +17,14 @@ using SixLabors.Primitives; namespace osu.Game.Tournament.Screens.Ladder.Components { - public class DrawableMatchPairing : CompositeDrawable + public class DrawableTournamentMatch : CompositeDrawable { - public readonly MatchPairing Pairing; + public readonly TournamentMatch Match; private readonly bool editor; protected readonly FillFlowContainer Flow; private readonly Drawable selectionBox; private readonly Drawable currentMatchSelectionBox; - private Bindable globalSelection; + private Bindable globalSelection; [Resolved(CanBeNull = true)] private LadderEditorInfo editorInfo { get; set; } @@ -32,9 +32,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components [Resolved(CanBeNull = true)] private LadderInfo ladderInfo { get; set; } - public DrawableMatchPairing(MatchPairing pairing, bool editor = false) + public DrawableTournamentMatch(TournamentMatch match, bool editor = false) { - Pairing = pairing; + Match = match; this.editor = editor; AutoSizeAxes = Axes.Both; @@ -75,25 +75,25 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } }; - boundReference(pairing.Team1).BindValueChanged(_ => updateTeams()); - boundReference(pairing.Team2).BindValueChanged(_ => updateTeams()); - boundReference(pairing.Team1Score).BindValueChanged(_ => updateWinConditions()); - boundReference(pairing.Team2Score).BindValueChanged(_ => updateWinConditions()); - boundReference(pairing.Round).BindValueChanged(_ => + boundReference(match.Team1).BindValueChanged(_ => updateTeams()); + boundReference(match.Team2).BindValueChanged(_ => updateTeams()); + boundReference(match.Team1Score).BindValueChanged(_ => updateWinConditions()); + boundReference(match.Team2Score).BindValueChanged(_ => updateWinConditions()); + boundReference(match.Round).BindValueChanged(_ => { updateWinConditions(); Changed?.Invoke(); }); - boundReference(pairing.Completed).BindValueChanged(_ => updateProgression()); - boundReference(pairing.Progression).BindValueChanged(_ => updateProgression()); - boundReference(pairing.LosersProgression).BindValueChanged(_ => updateProgression()); - boundReference(pairing.Losers).BindValueChanged(_ => + boundReference(match.Completed).BindValueChanged(_ => updateProgression()); + boundReference(match.Progression).BindValueChanged(_ => updateProgression()); + boundReference(match.LosersProgression).BindValueChanged(_ => updateProgression()); + boundReference(match.Losers).BindValueChanged(_ => { updateTeams(); Changed?.Invoke(); }); - boundReference(pairing.Current).BindValueChanged(_ => updateCurrentMatch(), true); - boundReference(pairing.Position).BindValueChanged(pos => + boundReference(match.Current).BindValueChanged(_ => updateCurrentMatch(), true); + boundReference(match.Position).BindValueChanged(pos => { if (!IsDragged) Position = new Vector2(pos.NewValue.X, pos.NewValue.Y); @@ -127,7 +127,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private void updateCurrentMatch() { - if (Pairing.Current.Value) + if (Match.Current.Value) currentMatchSelectionBox.Show(); else currentMatchSelectionBox.Hide(); @@ -149,9 +149,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { selectionBox.Show(); if (editor) - editorInfo.Selected.Value = Pairing; + editorInfo.Selected.Value = Match; else - ladderInfo.CurrentMatch.Value = Pairing; + ladderInfo.CurrentMatch.Value = Match; } else selectionBox.Hide(); @@ -160,36 +160,36 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private void updateProgression() { - if (!Pairing.Completed.Value) + if (!Match.Completed.Value) { // ensure we clear any of our teams from our progression. // this is not pretty logic but should suffice for now. - if (Pairing.Progression.Value != null && Pairing.Progression.Value.Team1.Value == Pairing.Team1.Value) - Pairing.Progression.Value.Team1.Value = null; + if (Match.Progression.Value != null && Match.Progression.Value.Team1.Value == Match.Team1.Value) + Match.Progression.Value.Team1.Value = null; - if (Pairing.Progression.Value != null && Pairing.Progression.Value.Team2.Value == Pairing.Team2.Value) - Pairing.Progression.Value.Team2.Value = null; + if (Match.Progression.Value != null && Match.Progression.Value.Team2.Value == Match.Team2.Value) + Match.Progression.Value.Team2.Value = null; - if (Pairing.LosersProgression.Value != null && Pairing.LosersProgression.Value.Team1.Value == Pairing.Team1.Value) - Pairing.LosersProgression.Value.Team1.Value = null; + if (Match.LosersProgression.Value != null && Match.LosersProgression.Value.Team1.Value == Match.Team1.Value) + Match.LosersProgression.Value.Team1.Value = null; - if (Pairing.LosersProgression.Value != null && Pairing.LosersProgression.Value.Team2.Value == Pairing.Team2.Value) - Pairing.LosersProgression.Value.Team2.Value = null; + if (Match.LosersProgression.Value != null && Match.LosersProgression.Value.Team2.Value == Match.Team2.Value) + Match.LosersProgression.Value.Team2.Value = null; } else { - transferProgression(Pairing.Progression?.Value, Pairing.Winner); - transferProgression(Pairing.LosersProgression?.Value, Pairing.Loser); + transferProgression(Match.Progression?.Value, Match.Winner); + transferProgression(Match.LosersProgression?.Value, Match.Loser); } Changed?.Invoke(); } - private void transferProgression(MatchPairing destination, TournamentTeam team) + private void transferProgression(TournamentMatch destination, TournamentTeam team) { if (destination == null) return; - bool progressionAbove = destination.ID < Pairing.ID; + bool progressionAbove = destination.ID < Match.ID; Bindable destinationTeam; @@ -210,12 +210,12 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private void updateWinConditions() { - if (Pairing.Round.Value == null) return; + if (Match.Round.Value == null) return; - var instaWinAmount = Pairing.Round.Value.BestOf.Value / 2; + var instaWinAmount = Match.Round.Value.BestOf.Value / 2; - Pairing.Completed.Value = Pairing.Round.Value.BestOf.Value > 0 - && (Pairing.Team1Score.Value + Pairing.Team2Score.Value >= Pairing.Round.Value.BestOf.Value || Pairing.Team1Score.Value > instaWinAmount || Pairing.Team2Score.Value > instaWinAmount); + Match.Completed.Value = Match.Round.Value.BestOf.Value > 0 + && (Match.Team1Score.Value + Match.Team2Score.Value >= Match.Round.Value.BestOf.Value || Match.Team1Score.Value > instaWinAmount || Match.Team2Score.Value > instaWinAmount); } protected override void LoadComplete() @@ -228,7 +228,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components globalSelection = editorInfo.Selected.GetBoundCopy(); globalSelection.BindValueChanged(s => { - if (s.NewValue != Pairing) Selected = false; + if (s.NewValue != Match) Selected = false; }); } } @@ -240,25 +240,25 @@ namespace osu.Game.Tournament.Screens.Ladder.Components // todo: teams may need to be bindable for transitions at a later point. - if (Pairing.Team1.Value == null || Pairing.Team2.Value == null) - Pairing.CancelMatchStart(); + if (Match.Team1.Value == null || Match.Team2.Value == null) + Match.CancelMatchStart(); - if (Pairing.ConditionalPairings.Count > 0) + if (Match.ConditionalMatches.Count > 0) { - foreach (var conditional in Pairing.ConditionalPairings) + foreach (var conditional in Match.ConditionalMatches) { - var team1Match = conditional.Acronyms.Contains(Pairing.Team1Acronym); - var team2Match = conditional.Acronyms.Contains(Pairing.Team2Acronym); + var team1Match = conditional.Acronyms.Contains(Match.Team1Acronym); + var team2Match = conditional.Acronyms.Contains(Match.Team2Acronym); if (team1Match && team2Match) - Pairing.Date.Value = conditional.Date.Value; + Match.Date.Value = conditional.Date.Value; } } Flow.Children = new[] { - new DrawableMatchTeam(Pairing.Team1.Value, Pairing, Pairing.Losers.Value), - new DrawableMatchTeam(Pairing.Team2.Value, Pairing, Pairing.Losers.Value) + new DrawableMatchTeam(Match.Team1.Value, Match, Match.Losers.Value), + new DrawableMatchTeam(Match.Team2.Value, Match, Match.Losers.Value) }; SchedulerAfterChildren.Add(() => Scheduler.Add(updateProgression)); @@ -282,7 +282,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components protected override bool OnClick(ClickEvent e) { - if (editorInfo == null || Pairing is ConditionalMatchPairing) + if (editorInfo == null || Match is ConditionalTournamentMatch) return false; Selected = true; @@ -297,17 +297,17 @@ namespace osu.Game.Tournament.Screens.Ladder.Components this.MoveToOffset(e.Delta); var pos = Position; - Pairing.Position.Value = new Point((int)pos.X, (int)pos.Y); + Match.Position.Value = new Point((int)pos.X, (int)pos.Y); return true; } public void Remove() { Selected = false; - Pairing.Progression.Value = null; - Pairing.LosersProgression.Value = null; + Match.Progression.Value = null; + Match.LosersProgression.Value = null; - ladderInfo.Pairings.Remove(Pairing); + ladderInfo.Matches.Remove(Match); } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 5514dfce3e..ded21730f3 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public class DrawableMatchTeam : DrawableTournamentTeam, IHasContextMenu { - private readonly MatchPairing pairing; + private readonly TournamentMatch match; private readonly bool losers; private OsuSpriteText scoreText; private Box background; @@ -47,17 +47,17 @@ namespace osu.Game.Tournament.Screens.Ladder.Components if (ladderInfo.CurrentMatch.Value != null) ladderInfo.CurrentMatch.Value.Current.Value = false; - ladderInfo.CurrentMatch.Value = pairing; + ladderInfo.CurrentMatch.Value = match; ladderInfo.CurrentMatch.Value.Current.Value = true; } [Resolved(CanBeNull = true)] private LadderEditorInfo editorInfo { get; set; } - public DrawableMatchTeam(TournamentTeam team, MatchPairing pairing, bool losers) + public DrawableMatchTeam(TournamentTeam team, TournamentMatch match, bool losers) : base(team) { - this.pairing = pairing; + this.match = match; this.losers = losers; Size = new Vector2(150, 40); @@ -71,13 +71,13 @@ namespace osu.Game.Tournament.Screens.Ladder.Components AcronymText.Padding = new MarginPadding { Left = 50 }; AcronymText.Font = OsuFont.GetFont(size: 24); - if (pairing != null) + if (match != null) { - isWinner = () => pairing.Winner == Team; + isWinner = () => match.Winner == Team; - completed.BindTo(pairing.Completed); + completed.BindTo(match.Completed); if (team != null) - score.BindTo(team == pairing.Team1.Value ? pairing.Team1Score : pairing.Team2Score); + score.BindTo(team == match.Team1.Value ? match.Team1Score : match.Team2Score); } } @@ -144,7 +144,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { if (Team == null || editorInfo != null) return false; - if (!pairing.Current.Value) + if (!match.Current.Value) { setCurrent(); return true; @@ -154,25 +154,25 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { if (score.Value == null) { - pairing.StartMatch(); + match.StartMatch(); } - else if (!pairing.Completed.Value) + else if (!match.Completed.Value) score.Value++; } else { - if (pairing.Progression.Value?.Completed.Value == true) + if (match.Progression.Value?.Completed.Value == true) // don't allow changing scores if the match has a progression. can cause large data loss return false; - if (pairing.Completed.Value && pairing.Winner != Team) + if (match.Completed.Value && match.Winner != Team) // don't allow changing scores from the non-winner return false; if (score.Value > 0) score.Value--; else - pairing.CancelMatchStart(); + match.CancelMatchStart(); } return false; @@ -197,9 +197,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components return new MenuItem[] { new OsuMenuItem("Set as current", MenuItemType.Standard, setCurrent), - new OsuMenuItem("Join with", MenuItemType.Standard, () => ladderEditor.BeginJoin(pairing, false)), - new OsuMenuItem("Join with (loser)", MenuItemType.Standard, () => ladderEditor.BeginJoin(pairing, true)), - new OsuMenuItem("Remove", MenuItemType.Destructive, () => ladderEditor.Remove(pairing)), + new OsuMenuItem("Join with", MenuItemType.Standard, () => ladderEditor.BeginJoin(match, false)), + new OsuMenuItem("Join with (loser)", MenuItemType.Standard, () => ladderEditor.BeginJoin(match, true)), + new OsuMenuItem("Remove", MenuItemType.Destructive, () => ladderEditor.Remove(match)), }; } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs index 5468844f66..34e0dc770f 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs @@ -10,10 +10,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public class ProgressionPath : Path { - public DrawableMatchPairing Source { get; private set; } - public DrawableMatchPairing Destination { get; private set; } + public DrawableTournamentMatch Source { get; private set; } + public DrawableTournamentMatch Destination { get; private set; } - public ProgressionPath(DrawableMatchPairing source, DrawableMatchPairing destination) + public ProgressionPath(DrawableTournamentMatch source, DrawableTournamentMatch destination) { Source = source; Destination = destination; diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 50675a6147..67531ce5d3 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tournament.Screens.Ladder { public class LadderScreen : TournamentScreen, IProvideVideo { - protected Container PairingsContainer; + protected Container MatchesContainer; private Container paths; private Container headings; @@ -53,35 +53,35 @@ namespace osu.Game.Tournament.Screens.Ladder { paths = new Container { RelativeSizeAxes = Axes.Both }, headings = new Container { RelativeSizeAxes = Axes.Both }, - PairingsContainer = new Container { RelativeSizeAxes = Axes.Both }, + MatchesContainer = new Container { RelativeSizeAxes = Axes.Both }, } }, } }; - void addPairing(MatchPairing pairing) => - PairingsContainer.Add(new DrawableMatchPairing(pairing, this is LadderEditorScreen) + void addMatch(TournamentMatch match) => + MatchesContainer.Add(new DrawableTournamentMatch(match, this is LadderEditorScreen) { Changed = () => layout.Invalidate() }); - foreach (var pairing in LadderInfo.Pairings) - addPairing(pairing); + foreach (var match in LadderInfo.Matches) + addMatch(match); LadderInfo.Rounds.ItemsAdded += _ => layout.Invalidate(); LadderInfo.Rounds.ItemsRemoved += _ => layout.Invalidate(); - LadderInfo.Pairings.ItemsAdded += pairings => + LadderInfo.Matches.ItemsAdded += matches => { - foreach (var p in pairings) - addPairing(p); + foreach (var p in matches) + addMatch(p); layout.Invalidate(); }; - LadderInfo.Pairings.ItemsRemoved += pairings => + LadderInfo.Matches.ItemsRemoved += matches => { - foreach (var p in pairings) - foreach (var d in PairingsContainer.Where(d => d.Pairing == p)) + foreach (var p in matches) + foreach (var d in MatchesContainer.Where(d => d.Match == p)) d.Expire(); layout.Invalidate(); @@ -110,45 +110,45 @@ namespace osu.Game.Tournament.Screens.Ladder int id = 1; - foreach (var pairing in PairingsContainer.OrderBy(d => d.Y).ThenBy(d => d.X)) + foreach (var match in MatchesContainer.OrderBy(d => d.Y).ThenBy(d => d.X)) { - pairing.Pairing.ID = id++; + match.Match.ID = id++; - if (pairing.Pairing.Progression.Value != null) + if (match.Match.Progression.Value != null) { - var dest = PairingsContainer.FirstOrDefault(p => p.Pairing == pairing.Pairing.Progression.Value); + var dest = MatchesContainer.FirstOrDefault(p => p.Match == match.Match.Progression.Value); if (dest == null) // clean up outdated progressions. - pairing.Pairing.Progression.Value = null; + match.Match.Progression.Value = null; else - paths.Add(new ProgressionPath(pairing, dest) { Colour = pairing.Pairing.Losers.Value ? losersPathColour : normalPathColour }); + paths.Add(new ProgressionPath(match, dest) { Colour = match.Match.Losers.Value ? losersPathColour : normalPathColour }); } if (DrawLoserPaths) { - if (pairing.Pairing.LosersProgression.Value != null) + if (match.Match.LosersProgression.Value != null) { - var dest = PairingsContainer.FirstOrDefault(p => p.Pairing == pairing.Pairing.LosersProgression.Value); + var dest = MatchesContainer.FirstOrDefault(p => p.Match == match.Match.LosersProgression.Value); if (dest == null) // clean up outdated progressions. - pairing.Pairing.LosersProgression.Value = null; + match.Match.LosersProgression.Value = null; else - paths.Add(new ProgressionPath(pairing, dest) { Colour = losersPathColour.Opacity(0.1f) }); + paths.Add(new ProgressionPath(match, dest) { Colour = losersPathColour.Opacity(0.1f) }); } } } foreach (var round in LadderInfo.Rounds) { - var topPairing = PairingsContainer.Where(p => !p.Pairing.Losers.Value && p.Pairing.Round.Value == round).OrderBy(p => p.Y).FirstOrDefault(); + var topMatch = MatchesContainer.Where(p => !p.Match.Losers.Value && p.Match.Round.Value == round).OrderBy(p => p.Y).FirstOrDefault(); - if (topPairing == null) continue; + if (topMatch == null) continue; headings.Add(new DrawableTournamentRound(round) { - Position = headings.ToLocalSpace((topPairing.ScreenSpaceDrawQuad.TopLeft + topPairing.ScreenSpaceDrawQuad.TopRight) / 2), + Position = headings.ToLocalSpace((topMatch.ScreenSpaceDrawQuad.TopLeft + topMatch.ScreenSpaceDrawQuad.TopRight) / 2), Margin = new MarginPadding { Bottom = 10 }, Origin = Anchor.BottomCentre, }); @@ -156,13 +156,13 @@ namespace osu.Game.Tournament.Screens.Ladder foreach (var round in LadderInfo.Rounds) { - var topPairing = PairingsContainer.Where(p => p.Pairing.Losers.Value && p.Pairing.Round.Value == round).OrderBy(p => p.Y).FirstOrDefault(); + var topMatch = MatchesContainer.Where(p => p.Match.Losers.Value && p.Match.Round.Value == round).OrderBy(p => p.Y).FirstOrDefault(); - if (topPairing == null) continue; + if (topMatch == null) continue; headings.Add(new DrawableTournamentRound(round, true) { - Position = headings.ToLocalSpace((topPairing.ScreenSpaceDrawQuad.TopLeft + topPairing.ScreenSpaceDrawQuad.TopRight) / 2), + Position = headings.ToLocalSpace((topMatch.ScreenSpaceDrawQuad.TopLeft + topMatch.ScreenSpaceDrawQuad.TopRight) / 2), Margin = new MarginPadding { Bottom = 10 }, Origin = Anchor.BottomCentre, }); diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index ab03adbce9..1c5f07ce19 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -26,7 +26,7 @@ namespace osu.Game.Tournament.Screens.MapPool { private readonly FillFlowContainer> mapFlows; - private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentMatch = new Bindable(); [Resolved(canBeNull: true)] private TournamentSceneManager sceneManager { get; set; } @@ -203,7 +203,7 @@ namespace osu.Game.Tournament.Screens.MapPool } } - private void matchChanged(ValueChangedEvent match) + private void matchChanged(ValueChangedEvent match) { mapFlows.Clear(); diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index 457fb80141..4b46264055 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tournament.Screens.Schedule { public class ScheduleScreen : TournamentScreen, IProvideVideo { - private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentMatch = new Bindable(); private Container mainContainer; private LadderInfo ladder; @@ -49,7 +49,7 @@ namespace osu.Game.Tournament.Screens.Schedule currentMatch.BindTo(ladder.CurrentMatch); } - private void matchChanged(ValueChangedEvent match) + private void matchChanged(ValueChangedEvent match) { if (match.NewValue == null) { @@ -57,10 +57,10 @@ namespace osu.Game.Tournament.Screens.Schedule return; } - var upcoming = ladder.Pairings.Where(p => !p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4); + var upcoming = ladder.Matches.Where(p => !p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4); var conditionals = ladder - .Pairings.Where(p => !p.Completed.Value && (p.Team1.Value == null || p.Team2.Value == null) && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4) - .SelectMany(m => m.ConditionalPairings.Where(cp => m.Acronyms.TrueForAll(a => cp.Acronyms.Contains(a)))); + .Matches.Where(p => !p.Completed.Value && (p.Team1.Value == null || p.Team2.Value == null) && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4) + .SelectMany(m => m.ConditionalMatches.Where(cp => m.Acronyms.TrueForAll(a => cp.Acronyms.Contains(a)))); upcoming = upcoming.Concat(conditionals); upcoming = upcoming.OrderBy(p => p.Date.Value).Take(12); @@ -85,18 +85,18 @@ namespace osu.Game.Tournament.Screens.Schedule { RelativeSizeAxes = Axes.Both, Width = 0.4f, - ChildrenEnumerable = ladder.Pairings + ChildrenEnumerable = ladder.Matches .Where(p => p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4) .OrderByDescending(p => p.Date.Value) .Take(8) - .Select(p => new SchedulePairing(p)) + .Select(p => new ScheduleMatch(p)) }, new ScheduleContainer("match overview") { RelativeSizeAxes = Axes.Both, Width = 0.6f, - ChildrenEnumerable = upcoming.Select(p => new SchedulePairing(p)) + ChildrenEnumerable = upcoming.Select(p => new ScheduleMatch(p)) }, } } @@ -115,7 +115,7 @@ namespace osu.Game.Tournament.Screens.Schedule Colour = Color4.Black, Font = OsuFont.GetFont(size: 20) }, - new SchedulePairing(match.NewValue, false), + new ScheduleMatch(match.NewValue, false), new OsuSpriteText { Text = "Start Time " + match.NewValue.Date.Value.ToUniversalTime().ToString("HH:mm UTC"), @@ -128,21 +128,21 @@ namespace osu.Game.Tournament.Screens.Schedule }; } - public class SchedulePairing : DrawableMatchPairing + public class ScheduleMatch : DrawableTournamentMatch { - public SchedulePairing(MatchPairing pairing, bool showTimestamp = true) - : base(pairing) + public ScheduleMatch(TournamentMatch match, bool showTimestamp = true) + : base(match) { Flow.Direction = FillDirection.Horizontal; - bool conditional = pairing is ConditionalMatchPairing; + bool conditional = match is ConditionalTournamentMatch; if (conditional) Colour = OsuColour.Gray(0.5f); if (showTimestamp) { - AddInternal(new DrawableDate(Pairing.Date.Value) + AddInternal(new DrawableDate(Match.Date.Value) { Anchor = Anchor.TopRight, Origin = Anchor.TopLeft, @@ -157,7 +157,7 @@ namespace osu.Game.Tournament.Screens.Schedule Colour = Color4.Black, Alpha = conditional ? 0.6f : 1, Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, - Text = pairing.Date.Value.ToUniversalTime().ToString("HH:mm UTC") + (conditional ? " (conditional)" : "") + Text = match.Date.Value.ToUniversalTime().ToString("HH:mm UTC") + (conditional ? " (conditional)" : "") }); } } diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 4e0bb23a62..2cb4ffe4e9 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro { private Container mainContainer; - private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentMatch = new Bindable(); [BackgroundDependencyLoader] private void load(Storage storage) @@ -45,9 +45,9 @@ namespace osu.Game.Tournament.Screens.TeamIntro currentMatch.BindTo(LadderInfo.CurrentMatch); } - private void matchChanged(ValueChangedEvent pairing) + private void matchChanged(ValueChangedEvent match) { - if (pairing.NewValue == null) + if (match.NewValue == null) { mainContainer.Clear(); return; @@ -55,7 +55,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro mainContainer.Children = new Drawable[] { - new TeamWithPlayers(pairing.NewValue.Team1.Value, true) + new TeamWithPlayers(match.NewValue.Team1.Value, true) { RelativeSizeAxes = Axes.Both, Width = 0.5f, @@ -63,7 +63,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.Centre, Origin = Anchor.CentreRight }, - new TeamWithPlayers(pairing.NewValue.Team2.Value) + new TeamWithPlayers(match.NewValue.Team2.Value) { RelativeSizeAxes = Axes.Both, Width = 0.5f, @@ -71,7 +71,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.Centre, Origin = Anchor.CentreLeft }, - new RoundDisplay(pairing.NewValue) + new RoundDisplay(match.NewValue) { RelativeSizeAxes = Axes.Both, Height = 0.25f, @@ -83,7 +83,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro private class RoundDisplay : CompositeDrawable { - public RoundDisplay(MatchPairing pairing) + public RoundDisplay(TournamentMatch match) { var col = OsuColour.Gray(0.33f); @@ -112,7 +112,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Colour = col, - Text = pairing.Round.Value?.Name.Value ?? "Unknown Round", + Text = match.Round.Value?.Name.Value ?? "Unknown Round", Spacing = new Vector2(10, 0), Font = OsuFont.GetFont(size: 50, weight: FontWeight.Light) }, @@ -121,7 +121,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Colour = col, - Text = pairing.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"), + Text = match.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"), Font = OsuFont.GetFont(size: 20) }, } diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs index 0a37cf6c4a..efe4ee92fc 100644 --- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tournament.Screens.TeamWin { private Container mainContainer; - private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentMatch = new Bindable(); private readonly Bindable currentCompleted = new Bindable(); private TourneyVideo blueWinVideo; @@ -61,31 +61,31 @@ namespace osu.Game.Tournament.Screens.TeamWin currentCompleted.BindValueChanged(_ => update()); } - private void matchChanged(ValueChangedEvent pairing) + private void matchChanged(ValueChangedEvent match) { currentCompleted.UnbindBindings(); - currentCompleted.BindTo(pairing.NewValue.Completed); + currentCompleted.BindTo(match.NewValue.Completed); update(); } private void update() { - var pairing = currentMatch.Value; + var match = currentMatch.Value; - if (pairing.Winner == null) + if (match.Winner == null) { mainContainer.Clear(); return; } - bool redWin = pairing.Winner == pairing.Team1.Value; + bool redWin = match.Winner == match.Team1.Value; redWinVideo.Alpha = redWin ? 1 : 0; blueWinVideo.Alpha = redWin ? 0 : 1; mainContainer.Children = new Drawable[] { - new TeamWithPlayers(pairing.Winner, redWin) + new TeamWithPlayers(match.Winner, redWin) { RelativeSizeAxes = Axes.Both, Width = 0.5f, @@ -93,7 +93,7 @@ namespace osu.Game.Tournament.Screens.TeamWin Anchor = Anchor.Centre, Origin = Anchor.Centre }, - new RoundDisplay(pairing) + new RoundDisplay(match) { RelativeSizeAxes = Axes.Both, Height = 0.25f, @@ -105,7 +105,7 @@ namespace osu.Game.Tournament.Screens.TeamWin private class RoundDisplay : CompositeDrawable { - public RoundDisplay(MatchPairing pairing) + public RoundDisplay(TournamentMatch match) { var col = OsuColour.Gray(0.33f); @@ -133,7 +133,7 @@ namespace osu.Game.Tournament.Screens.TeamWin Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Colour = col, - Text = pairing.Round.Value?.Name.Value ?? "Unknown Round", + Text = match.Round.Value?.Name.Value ?? "Unknown Round", Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 50, FontWeight.Light), Spacing = new Vector2(10, 0), }, @@ -142,7 +142,7 @@ namespace osu.Game.Tournament.Screens.TeamWin Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Colour = col, - Text = pairing.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"), + Text = match.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"), Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 20, FontWeight.Light), }, } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index e35e0b0d30..fb96641bcf 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -61,7 +61,7 @@ namespace osu.Game.Tournament readBracket(); - ladder.CurrentMatch.Value = ladder.Pairings.FirstOrDefault(p => p.Current.Value); + ladder.CurrentMatch.Value = ladder.Matches.FirstOrDefault(p => p.Current.Value); dependencies.CacheAs(ipc = new FileBasedIPC()); Add(ipc); @@ -97,24 +97,24 @@ namespace osu.Game.Tournament bool addedInfo = false; // assign teams - foreach (var pairing in ladder.Pairings) + foreach (var match in ladder.Matches) { - pairing.Team1.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == pairing.Team1Acronym); - pairing.Team2.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == pairing.Team2Acronym); + match.Team1.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == match.Team1Acronym); + match.Team2.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == match.Team2Acronym); - foreach (var conditional in pairing.ConditionalPairings) + foreach (var conditional in match.ConditionalMatches) { conditional.Team1.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == conditional.Team1Acronym); conditional.Team2.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == conditional.Team2Acronym); - conditional.Round.Value = pairing.Round.Value; + conditional.Round.Value = match.Round.Value; } } // assign progressions foreach (var pair in ladder.Progressions) { - var src = ladder.Pairings.FirstOrDefault(p => p.ID == pair.SourceID); - var dest = ladder.Pairings.FirstOrDefault(p => p.ID == pair.TargetID); + var src = ladder.Matches.FirstOrDefault(p => p.ID == pair.SourceID); + var dest = ladder.Matches.FirstOrDefault(p => p.ID == pair.TargetID); if (src == null) throw new InvalidOperationException(); @@ -127,11 +127,11 @@ namespace osu.Game.Tournament } } - // link pairings to rounds + // link matches to rounds foreach (var round in ladder.Rounds) - foreach (var id in round.Pairings) + foreach (var id in round.Matches) { - var found = ladder.Pairings.FirstOrDefault(p => p.ID == id); + var found = ladder.Matches.FirstOrDefault(p => p.ID == id); if (found != null) { @@ -245,10 +245,10 @@ namespace osu.Game.Tournament protected virtual void SaveChanges() { foreach (var r in ladder.Rounds) - r.Pairings = ladder.Pairings.Where(p => p.Round.Value == r).Select(p => p.ID).ToList(); + r.Matches = ladder.Matches.Where(p => p.Round.Value == r).Select(p => p.ID).ToList(); - ladder.Progressions = ladder.Pairings.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( - ladder.Pairings.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) + ladder.Progressions = ladder.Matches.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( + ladder.Matches.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) .ToList(); using (var stream = storage.GetStream(bracket_filename, FileAccess.Write, FileMode.Create)) From 6226889d1c9f04e96bfd08d9045afed614e123cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 15:00:33 +0900 Subject: [PATCH 1313/5608] Add xmldoc and serialisable attributes --- osu.Game.Tournament/Models/BeatmapChoice.cs | 5 +++++ osu.Game.Tournament/Models/LadderInfo.cs | 5 +++++ osu.Game.Tournament/Models/TournamentProgression.cs | 7 +++++++ osu.Game.Tournament/Models/TournamentRound.cs | 3 +++ osu.Game.Tournament/Models/TournamentTeam.cs | 3 +++ 5 files changed, 23 insertions(+) diff --git a/osu.Game.Tournament/Models/BeatmapChoice.cs b/osu.Game.Tournament/Models/BeatmapChoice.cs index c22077553b..384b349b24 100644 --- a/osu.Game.Tournament/Models/BeatmapChoice.cs +++ b/osu.Game.Tournament/Models/BeatmapChoice.cs @@ -1,11 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace osu.Game.Tournament.Models { + /// + /// A beatmap choice by a team from a tournament's map pool. + /// + [Serializable] public class BeatmapChoice { [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] diff --git a/osu.Game.Tournament/Models/LadderInfo.cs b/osu.Game.Tournament/Models/LadderInfo.cs index b6dc59c0d9..547c4eab08 100644 --- a/osu.Game.Tournament/Models/LadderInfo.cs +++ b/osu.Game.Tournament/Models/LadderInfo.cs @@ -1,12 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using Newtonsoft.Json; using osu.Framework.Bindables; namespace osu.Game.Tournament.Models { + /// + /// Holds the complete data required to operate the tournament system. + /// + [Serializable] public class LadderInfo { public BindableList Matches = new BindableList(); diff --git a/osu.Game.Tournament/Models/TournamentProgression.cs b/osu.Game.Tournament/Models/TournamentProgression.cs index 4ef4be599d..3e9b2e05c5 100644 --- a/osu.Game.Tournament/Models/TournamentProgression.cs +++ b/osu.Game.Tournament/Models/TournamentProgression.cs @@ -1,8 +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; + namespace osu.Game.Tournament.Models { + /// + /// A mapping between two es. + /// Used for serialisation exclusively. + /// + [Serializable] public class TournamentProgression { public int SourceID; diff --git a/osu.Game.Tournament/Models/TournamentRound.cs b/osu.Game.Tournament/Models/TournamentRound.cs index e325ad4b96..35215e90c5 100644 --- a/osu.Game.Tournament/Models/TournamentRound.cs +++ b/osu.Game.Tournament/Models/TournamentRound.cs @@ -8,6 +8,9 @@ using osu.Framework.Bindables; namespace osu.Game.Tournament.Models { + /// + /// A tournament round, containing many matches, generally executed in a short time period. + /// [Serializable] public class TournamentRound { diff --git a/osu.Game.Tournament/Models/TournamentTeam.cs b/osu.Game.Tournament/Models/TournamentTeam.cs index eea1ef8104..54b8a35180 100644 --- a/osu.Game.Tournament/Models/TournamentTeam.cs +++ b/osu.Game.Tournament/Models/TournamentTeam.cs @@ -8,6 +8,9 @@ using osu.Game.Users; namespace osu.Game.Tournament.Models { + /// + /// A team representation. For official tournaments this is generally a country. + /// [Serializable] public class TournamentTeam { From 21138e6e2caf7a4e6f5fef7bc5092cbf9915d7be Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 15:05:55 +0900 Subject: [PATCH 1314/5608] Fix mismatching filenames --- ...eMatchPairings.cs => TestSceneDrawableTournamentMatch.cs} | 5 ++--- .../{DrawableMatchPairing.cs => DrawableTournamentMatch.cs} | 0 2 files changed, 2 insertions(+), 3 deletions(-) rename osu.Game.Tournament.Tests/{TestSceneMatchPairings.cs => TestSceneDrawableTournamentMatch.cs} (96%) rename osu.Game.Tournament/Screens/Ladder/Components/{DrawableMatchPairing.cs => DrawableTournamentMatch.cs} (100%) diff --git a/osu.Game.Tournament.Tests/TestSceneMatchPairings.cs b/osu.Game.Tournament.Tests/TestSceneDrawableTournamentMatch.cs similarity index 96% rename from osu.Game.Tournament.Tests/TestSceneMatchPairings.cs rename to osu.Game.Tournament.Tests/TestSceneDrawableTournamentMatch.cs index 9c8ee2965e..c3a4519597 100644 --- a/osu.Game.Tournament.Tests/TestSceneMatchPairings.cs +++ b/osu.Game.Tournament.Tests/TestSceneDrawableTournamentMatch.cs @@ -12,17 +12,16 @@ using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Tests { - public class TestSceneMatches : OsuTestScene + public class TestSceneDrawableTournamentMatch : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(TournamentMatch), typeof(DrawableTournamentMatch), - typeof(DrawableMatchTeam), typeof(DrawableTournamentTeam), }; - public TestSceneMatches() + public TestSceneDrawableTournamentMatch() { Container level1; Container level2; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs similarity index 100% rename from osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchPairing.cs rename to osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs From 7652339dc0ff985abf5b5dd1f619b134696f7f84 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 15:07:33 +0900 Subject: [PATCH 1315/5608] Remove test file --- osu.Game.Tournament.Tests/teams.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 osu.Game.Tournament.Tests/teams.json diff --git a/osu.Game.Tournament.Tests/teams.json b/osu.Game.Tournament.Tests/teams.json deleted file mode 100644 index 7df0040469..0000000000 --- a/osu.Game.Tournament.Tests/teams.json +++ /dev/null @@ -1 +0,0 @@ -[{"Players":[{"id":3632846,"username":"lxLucasxl"},{"id":7110363,"username":"BubShish"},{"id":5748843,"username":"Fisk-"},{"id":4585260,"username":"A b y s s"},{"id":9513273,"username":"VorticalEx"},{"id":7341471,"username":"Bossplays_02"}],"Name":"Argentina","Acronym":"ARG"},{"Players":[{"id":2956184,"username":"Lusty Platypus"},{"id":2145124,"username":"Spartan-"},{"id":4018184,"username":"Rek"},{"id":4247722,"username":"PotassiumF"},{"id":9527845,"username":"AngeLItchysick"},{"id":8832989,"username":"[Crz]Yukikaze-"}],"Name":"Australia","Acronym":"AUS"},{"Players":[{"id":9530019,"username":"Lothus"},{"id":2288363,"username":"SillyFangirl"},{"id":4917435,"username":"FelipeLink"},{"id":5691061,"username":"andreymc"},{"id":4794096,"username":"Shedin"},{"id":3224958,"username":"Lazarento"}],"Name":"Brazil","Acronym":"BRA"},{"Players":[{"id":2747704,"username":"Dawt"},{"id":7025841,"username":"CommandoBlack"},{"id":5390121,"username":"Piggy"},{"id":2198070,"username":"beary605"},{"id":2777647,"username":"Freeflow"},{"id":9675053,"username":"Kiyora"}],"Name":"Canada","Acronym":"CAN"},{"Players":[{"id":5281416,"username":"WalterToro"},{"id":2225008,"username":"Skalim"},{"id":469808,"username":"Sophti"},{"id":4686036,"username":"sebaex"},{"id":4116072,"username":"Arkener"},{"id":4531184,"username":"Raizenn"}],"Name":"Chile","Acronym":"CHL"},{"Players":[{"id":89545,"username":"ZhangFan"},{"id":7215250,"username":"[Crz]Mix0130"},{"id":7961511,"username":"[Crz]Hina"},{"id":7082178,"username":"[Crz]Satori"},{"id":6659363,"username":"Wilben_Chan"},{"id":5270332,"username":"[Crz]Lucifer"}],"Name":"China","Acronym":"CHN"},{"Players":[{"id":2883132,"username":"Jole"},{"id":5001658,"username":"FreakyHands"},{"id":4402263,"username":"mart732c"},{"id":6751666,"username":"tailsdk"},{"id":5352616,"username":"Kainura"},{"id":8969233,"username":"zyglrox"}],"Name":"Denmark","Acronym":"DNK"},{"Players":[{"id":8132964,"username":"Camopoltergeist"},{"id":4789005,"username":"princesswell"},{"id":9663200,"username":"--Vanilla--"},{"id":1982941,"username":"matti644"},{"id":8370443,"username":"Your Daughter"},{"id":8105584,"username":"Twist-X"}],"Name":"Finland","Acronym":"FIN"},{"Players":[{"id":1594604,"username":"Azubeur"},{"id":2284328,"username":"Elementaires"},{"id":3897919,"username":"AntoAa"},{"id":4056690,"username":"Todestrieb"},{"id":7190228,"username":"Cunu"},{"id":3909293,"username":"DemonWaves"}],"Name":"France","Acronym":"FRA"},{"Players":[{"id":4516252,"username":"Malox"},{"id":3357640,"username":"ElectroYan"},{"id":5587671,"username":"-Dom-"},{"id":9764403,"username":"tyro901"},{"id":7009106,"username":"Nediz"},{"id":6232245,"username":"LastExceed"}],"Name":"Germany","Acronym":"GER"},{"Players":[{"id":5417362,"username":"Mooncha"},{"id":2121137,"username":"ng051106"},{"id":4544555,"username":"Opean"},{"id":643394,"username":"Snow Note"}],"Name":"['Hong Kong']","Acronym":"HKG"},{"Players":[{"id":5767941,"username":"RemFangirl"},{"id":4557440,"username":"reyss"},{"id":5492871,"username":"LovelySerenade"},{"id":6045757,"username":"Nixeria-sama"},{"id":5114499,"username":"lombit"},{"id":3497139,"username":"LordBoker-"}],"Name":"Indonesia","Acronym":"IDN"},{"Players":[{"id":3461860,"username":"Yomiel"},{"id":5245132,"username":"BadIsTheNewGod"},{"id":3244389,"username":"Mura7797"},{"id":8889323,"username":"extramen"},{"id":8485394,"username":"Cribob"},{"id":6380163,"username":"CribobFanBoy"}],"Name":"Italy","Acronym":"ITA"},{"Players":[{"id":1824775,"username":"inteliser"},{"id":7540718,"username":"tinpura"},{"id":1847698,"username":"PiraTom"},{"id":10011429,"username":"[ misa ]"},{"id":8679066,"username":"mach_jp"},{"id":10242062,"username":"AMDuskia1996"}],"Name":"Japan","Acronym":"JPN"},{"Players":[{"id":3946113,"username":"idqoos123"},{"id":10543278,"username":"hh27v5Fangirl"},{"id":8566617,"username":"capchon"},{"id":5315736,"username":"my2tic"}],"Name":"Macau","Acronym":"MAC"},{"Players":[{"id":7727987,"username":"Neokje"},{"id":8287005,"username":"[MY]xRay"},{"id":9627666,"username":"Minisora"},{"id":6237337,"username":"watarakisah"},{"id":6363947,"username":"Kiritolow"},{"id":4477497,"username":"cheewee10"}],"Name":"Malaysia","Acronym":"MYS"},{"Players":[{"id":1098581,"username":"mrdawn2"},{"id":9369363,"username":"TheSnooperPS"},{"id":6964358,"username":"Redenor"},{"id":9630674,"username":"Freek"},{"id":2827823,"username":"Boots"},{"id":5183940,"username":"2fast4you98"}],"Name":"Netherlands","Acronym":"NLD"},{"Players":[{"id":86188,"username":"Staiain"},{"id":7676585,"username":"Bizarrely_F4st"},{"id":3494742,"username":"KarlF"},{"id":3750387,"username":"Falniir"},{"id":9000473,"username":"Jesen"},{"id":2764122,"username":"Hjeg"}],"Name":"Norway","Acronym":"NOR"},{"Players":[{"id":914472,"username":"akuma123"},{"id":6114633,"username":"DaZeRo5"},{"id":11885200,"username":"DaKub"},{"id":10218427,"username":"Ovento17"}],"Name":"Peru","Acronym":"PER"},{"Players":[{"id":2039089,"username":"arcwinolivirus"},{"id":4469895,"username":"SurfChu85"},{"id":2471512,"username":"JztCallMeRon"},{"id":9770359,"username":"Toyohime-"},{"id":2722489,"username":"Cielo Day"},{"id":3770641,"username":"Ainyan"}],"Name":"Philippines","Acronym":"PHL"},{"Players":[{"id":743282,"username":"Tidek"},{"id":1654221,"username":"Hudonom"},{"id":6382502,"username":"Kroly-"},{"id":6905790,"username":"Arkitev"},{"id":2235750,"username":"_underjoy"},{"id":3353343,"username":"[-Agonys-]"}],"Name":"Poland","Acronym":"POL"},{"Players":[{"id":9074986,"username":"AngeloLagusa"},{"id":5145890,"username":"Jormungand"},{"id":9847747,"username":"MAZAFUKER1337"},{"id":8035172,"username":"fegasaren"},{"id":7767168,"username":"claer"}],"Name":"['Russian Federation']","Acronym":"RUS"},{"Players":[{"id":7199159,"username":"ByeForNow"},{"id":876528,"username":"Tamaneko"},{"id":8612061,"username":"Polytetral"},{"id":7462804,"username":"Lindyes"},{"id":4574597,"username":"OrienST8"},{"id":9362562,"username":"LuigiClaren"}],"Name":"Singapore","Acronym":"SGP"},{"Players":[{"id":6699923,"username":"SuddenDeath"},{"id":7014697,"username":"Estonians"},{"id":8474029,"username":"wonder5193"},{"id":8283444,"username":"[ Special ]"},{"id":903155,"username":"Nausicaa"},{"id":7945868,"username":"SnowScent"}],"Name":"['South Korea']","Acronym":"KOR"},{"Players":[{"id":3154852,"username":"aitor98"},{"id":8141215,"username":"David5_"},{"id":7935867,"username":"miguel-580"},{"id":6809566,"username":"itsdarious555"},{"id":8497100,"username":"GreenSoul"}],"Name":"Spain","Acronym":"ESP"},{"Players":[{"id":1612580,"username":"Vent"},{"id":6872025,"username":"Couil"},{"id":2229274,"username":"Xytox"},{"id":4899311,"username":"Stug"},{"id":5045509,"username":"YoShiZoRi"},{"id":3918056,"username":"Craty"}],"Name":"Sweden","Acronym":"SWE"},{"Players":[{"id":4952941,"username":"Gamer97"},{"id":8642966,"username":"Adyrem"},{"id":8372292,"username":"doere_"},{"id":9593126,"username":"Monogai"},{"id":3974114,"username":"Haprapra"},{"id":2573716,"username":"Akayro"}],"Name":"Switzerland","Acronym":"CHE"},{"Players":[{"id":766374,"username":"LostCool"},{"id":2838908,"username":"4ksrub"},{"id":6535376,"username":"SharpKunG1412"},{"id":2772110,"username":"BossMadWolf"},{"id":8521723,"username":"MyZterioN-"},{"id":6456531,"username":"-[DaNieL_TH]-"}],"Name":"Thailand","Acronym":"THA"},{"Players":[{"id":2656856,"username":"Sakaki"},{"id":6193819,"username":"SaKuRaLaN"},{"id":1990582,"username":"mspstommy"},{"id":8819232,"username":"Tamamo Desu"},{"id":11531528,"username":"Red MewFew"},{"id":1967808,"username":"luckygino"}],"Name":"Taiwan","Acronym":"TWN"},{"Players":[{"id":3359035,"username":"Amascite"},{"id":4168230,"username":"PikachuNick"},{"id":3617889,"username":"itsjakey"},{"id":3799946,"username":"xSnaggles"},{"id":6814203,"username":"Civilization"},{"id":6701945,"username":"Domblade"}],"Name":"['United Kingdom']","Acronym":"GBR"},{"Players":[{"id":7616811,"username":"TheToaphster"},{"id":2141612,"username":"stupud man"},{"id":7687954,"username":"Neuro-"},{"id":3251373,"username":"-Electro-"},{"id":5610085,"username":"EtienneXC"},{"id":2594280,"username":"Chrubble"}],"Name":"['United States']","Acronym":"USA"},{"Players":[{"id":2243452,"username":"Nakatoru"},{"id":8065567,"username":"Aezlack"},{"id":8301758,"username":"Edvo"},{"id":2140739,"username":"[_Chichinya_]"},{"id":8198818,"username":"[_Gearfrik_]"},{"id":1489811,"username":"_Yisus_"}],"Name":"Venezuela","Acronym":"VEN"}] \ No newline at end of file From 7c163ad911f4c29b927dbd391cd000b1e0503802 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 15:08:36 +0900 Subject: [PATCH 1316/5608] Move font-related code out of TournamentGame --- osu.Game.Tournament/TournamentFont.cs | 5 +++++ osu.Game.Tournament/TournamentGame.cs | 29 +-------------------------- 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tournament/TournamentFont.cs b/osu.Game.Tournament/TournamentFont.cs index d2925d7632..f9e60ff2bc 100644 --- a/osu.Game.Tournament/TournamentFont.cs +++ b/osu.Game.Tournament/TournamentFont.cs @@ -67,4 +67,9 @@ namespace osu.Game.Tournament return weightString; } } + + public enum TournamentTypeface + { + Aquatico + } } diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index 42e4ab3c13..7dbcf37af6 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -2,8 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; using osu.Game.Graphics.Cursor; namespace osu.Game.Tournament @@ -20,33 +18,8 @@ namespace osu.Game.Tournament Child = new TournamentSceneManager() }); + // we don't want to show the menu cursor as it would appear on stream output. MenuCursorContainer.Cursor.Alpha = 0; } } - - public static class TournamentFontExtensions - { - /// - /// Creates a new by applying adjustments to this . - /// - /// The base . - /// The font typeface. If null, the value is copied from this . - /// The text size. If null, the value is copied from this . - /// The font weight. If null, the value is copied from this . - /// Whether the font is italic. If null, the value is copied from this . - /// Whether all characters should be spaced apart the same distance. If null, the value is copied from this . - /// The resulting . - public static FontUsage With(this FontUsage usage, TournamentTypeface? typeface = null, float? size = null, FontWeight? weight = null, bool? italics = null, bool? fixedWidth = null) - { - string familyString = typeface != null ? TournamentFont.GetFamilyString(typeface.Value) : usage.Family; - string weightString = weight != null ? TournamentFont.GetWeightString(familyString, weight.Value) : usage.Weight; - - return usage.With(familyString, size, weightString, italics, fixedWidth); - } - } - - public enum TournamentTypeface - { - Aquatico - } } From 3db6913a9c107d6b8b670833ffe419f2f72051e8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 15:15:28 +0900 Subject: [PATCH 1317/5608] Rename editor screens removing plurals --- ...oupingsEditorScreen.cs => TestSceneRoundEditorScreen.cs} | 4 ++-- ...eneTeamsEditorScreen.cs => TestSceneTeamEditorScreen.cs} | 6 +++--- .../Editors/{TeamsEditorScreen.cs => TeamEditorScreen.cs} | 4 ++-- osu.Game.Tournament/TournamentSceneManager.cs | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) rename osu.Game.Tournament.Tests/{TestSceneGroupingsEditorScreen.cs => TestSceneRoundEditorScreen.cs} (72%) rename osu.Game.Tournament.Tests/{TestSceneTeamsEditorScreen.cs => TestSceneTeamEditorScreen.cs} (64%) rename osu.Game.Tournament/Screens/Editors/{TeamsEditorScreen.cs => TeamEditorScreen.cs} (99%) diff --git a/osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs b/osu.Game.Tournament.Tests/TestSceneRoundEditorScreen.cs similarity index 72% rename from osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs rename to osu.Game.Tournament.Tests/TestSceneRoundEditorScreen.cs index e0a6f8e8b9..9c1207a718 100644 --- a/osu.Game.Tournament.Tests/TestSceneGroupingsEditorScreen.cs +++ b/osu.Game.Tournament.Tests/TestSceneRoundEditorScreen.cs @@ -5,9 +5,9 @@ using osu.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests { - public class TestSceneGroupingsEditorScreen : LadderTestScene + public class TestSceneRoundEditorScreen : LadderTestScene { - public TestSceneGroupingsEditorScreen() + public TestSceneRoundEditorScreen() { Add(new RoundEditorScreen()); } diff --git a/osu.Game.Tournament.Tests/TestSceneTeamsEditorScreen.cs b/osu.Game.Tournament.Tests/TestSceneTeamEditorScreen.cs similarity index 64% rename from osu.Game.Tournament.Tests/TestSceneTeamsEditorScreen.cs rename to osu.Game.Tournament.Tests/TestSceneTeamEditorScreen.cs index 60323e1d84..df0b79d8a9 100644 --- a/osu.Game.Tournament.Tests/TestSceneTeamsEditorScreen.cs +++ b/osu.Game.Tournament.Tests/TestSceneTeamEditorScreen.cs @@ -5,11 +5,11 @@ using osu.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests { - public class TestSceneTeamsEditorScreen : LadderTestScene + public class TestSceneTeamEditorScreen : LadderTestScene { - public TestSceneTeamsEditorScreen() + public TestSceneTeamEditorScreen() { - Add(new TeamsEditorScreen()); + Add(new TeamEditorScreen()); } } } diff --git a/osu.Game.Tournament/Screens/Editors/TeamsEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs similarity index 99% rename from osu.Game.Tournament/Screens/Editors/TeamsEditorScreen.cs rename to osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index 1bf3f1c6b9..ff272d5123 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamsEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -20,11 +20,11 @@ using osuTK; namespace osu.Game.Tournament.Screens.Editors { - public class TeamsEditorScreen : TournamentScreen, IProvideVideo + public class TeamEditorScreen : TournamentScreen, IProvideVideo { private readonly FillFlowContainer items; - public TeamsEditorScreen() + public TeamEditorScreen() { AddRangeInternal(new Drawable[] { diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 29f8eba579..4c255be463 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -72,7 +72,7 @@ namespace osu.Game.Tournament new ScheduleScreen(), new LadderScreen(), new LadderEditorScreen(), - new TeamsEditorScreen(), + new TeamEditorScreen(), new RoundEditorScreen(), new ShowcaseScreen(), new MapPoolScreen(), @@ -106,7 +106,7 @@ namespace osu.Game.Tournament Direction = FillDirection.Vertical, Children = new Drawable[] { - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Team Editor", Action = () => SetScreen(typeof(TeamsEditorScreen)) }, + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Team Editor", Action = () => SetScreen(typeof(TeamEditorScreen)) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Rounds Editor", Action = () => SetScreen(typeof(RoundEditorScreen)) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, From 1a9226365284a02c676f49fce7ddc774d421ac58 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 15:18:06 +0900 Subject: [PATCH 1318/5608] Ignore parse errors rather than dying --- osu.Game.Tournament/TournamentGameBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index fb96641bcf..9f63cc2302 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.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.Collections.Generic; using System.Drawing; using System.IO; @@ -116,7 +115,8 @@ namespace osu.Game.Tournament var src = ladder.Matches.FirstOrDefault(p => p.ID == pair.SourceID); var dest = ladder.Matches.FirstOrDefault(p => p.ID == pair.TargetID); - if (src == null) throw new InvalidOperationException(); + if (src == null) + continue; if (dest != null) { From fa61b08a05211ddcda53dc68a238c68ef703ecdd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 15:20:28 +0900 Subject: [PATCH 1319/5608] Mark LadderTestScene abstract --- osu.Game.Tournament.Tests/LadderTestScene.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament.Tests/LadderTestScene.cs b/osu.Game.Tournament.Tests/LadderTestScene.cs index 5bb8112157..b49341d0d1 100644 --- a/osu.Game.Tournament.Tests/LadderTestScene.cs +++ b/osu.Game.Tournament.Tests/LadderTestScene.cs @@ -7,7 +7,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Tests { - public class LadderTestScene : OsuTestScene + public abstract class LadderTestScene : OsuTestScene { [Resolved] protected LadderInfo Ladder { get; private set; } From 3fcb8081dd9bcab26656b7aa15d652d1ecc1c09f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 15:20:36 +0900 Subject: [PATCH 1320/5608] Remove unused ruleset bindable --- osu.Game.Tournament/TournamentGameBase.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 9f63cc2302..2f8d084848 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -17,7 +17,6 @@ using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests; -using osu.Game.Rulesets; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; using osuTK.Input; @@ -34,8 +33,6 @@ namespace osu.Game.Tournament private DependencyContainer dependencies; - private readonly Bindable ruleset = new Bindable(); - private Bindable windowSize; private FileBasedIPC ipc; From 926a11ab8ccd3f7728ddca773e997c8e73f005b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 15:28:36 +0900 Subject: [PATCH 1321/5608] Group, rename and standardise tests --- .../TestSceneDrawableTournamentMatch.cs | 3 +-- .../TestSceneMatchScoreDisplay.cs | 2 +- .../TestSceneTournamentBeatmapPanel.cs} | 11 ++------- .../TestSceneTournamentMatchChatDisplay.cs | 2 +- .../{ => Screens}/TestSceneGameplayScreen.cs | 2 +- .../Screens/TestSceneLadderEditorScreen.cs | 23 +++++++++++++++++++ .../TestSceneLadderScreen.cs} | 4 ++-- .../TestSceneMapPoolScreen.cs} | 4 ++-- .../TestSceneRoundEditorScreen.cs | 2 +- .../TestSceneScheduleScreen.cs} | 11 ++------- .../TestSceneShowcaseScreen.cs} | 11 ++------- .../TestSceneTeamEditorScreen.cs | 2 +- .../TestSceneTeamIntroScreen.cs} | 4 ++-- .../TestSceneTeamWinScreen.cs} | 4 ++-- ....cs => TestSceneTournamentSceneManager.cs} | 2 +- .../osu.Game.Tournament.csproj | 3 --- 16 files changed, 44 insertions(+), 46 deletions(-) rename osu.Game.Tournament.Tests/{ => Components}/TestSceneDrawableTournamentMatch.cs (97%) rename osu.Game.Tournament.Tests/{ => Components}/TestSceneMatchScoreDisplay.cs (96%) rename osu.Game.Tournament.Tests/{TestSceneBeatmapPanel.cs => Components/TestSceneTournamentBeatmapPanel.cs} (80%) rename osu.Game.Tournament.Tests/{ => Components}/TestSceneTournamentMatchChatDisplay.cs (98%) rename osu.Game.Tournament.Tests/{ => Screens}/TestSceneGameplayScreen.cs (93%) create mode 100644 osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs rename osu.Game.Tournament.Tests/{TestSceneLadderManager.cs => Screens/TestSceneLadderScreen.cs} (84%) rename osu.Game.Tournament.Tests/{TestSceneMapPool.cs => Screens/TestSceneMapPoolScreen.cs} (84%) rename osu.Game.Tournament.Tests/{ => Screens}/TestSceneRoundEditorScreen.cs (89%) rename osu.Game.Tournament.Tests/{TestSceneSchedule.cs => Screens/TestSceneScheduleScreen.cs} (60%) rename osu.Game.Tournament.Tests/{TestSceneShowcase.cs => Screens/TestSceneShowcaseScreen.cs} (60%) rename osu.Game.Tournament.Tests/{ => Screens}/TestSceneTeamEditorScreen.cs (89%) rename osu.Game.Tournament.Tests/{TestSceneTeamIntro.cs => Screens/TestSceneTeamIntroScreen.cs} (91%) rename osu.Game.Tournament.Tests/{TestSceneTeamWin.cs => Screens/TestSceneTeamWinScreen.cs} (91%) rename osu.Game.Tournament.Tests/{TestSceneSceneManager.cs => TestSceneTournamentSceneManager.cs} (87%) diff --git a/osu.Game.Tournament.Tests/TestSceneDrawableTournamentMatch.cs b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs similarity index 97% rename from osu.Game.Tournament.Tests/TestSceneDrawableTournamentMatch.cs rename to osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs index c3a4519597..f329623703 100644 --- a/osu.Game.Tournament.Tests/TestSceneDrawableTournamentMatch.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs @@ -10,14 +10,13 @@ using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Ladder.Components; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Tests.Components { public class TestSceneDrawableTournamentMatch : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(TournamentMatch), - typeof(DrawableTournamentMatch), typeof(DrawableTournamentTeam), }; diff --git a/osu.Game.Tournament.Tests/TestSceneMatchScoreDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs similarity index 96% rename from osu.Game.Tournament.Tests/TestSceneMatchScoreDisplay.cs rename to osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs index 7e9b83a61b..72d9eb0e07 100644 --- a/osu.Game.Tournament.Tests/TestSceneMatchScoreDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs @@ -7,7 +7,7 @@ using osu.Framework.MathUtils; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Screens.Gameplay.Components; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Tests.Components { public class TestSceneMatchScoreDisplay : LadderTestScene { diff --git a/osu.Game.Tournament.Tests/TestSceneBeatmapPanel.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs similarity index 80% rename from osu.Game.Tournament.Tests/TestSceneBeatmapPanel.cs rename to osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs index 50169adad3..77fa411058 100644 --- a/osu.Game.Tournament.Tests/TestSceneBeatmapPanel.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; @@ -13,9 +11,9 @@ using osu.Game.Rulesets; using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Tests.Components { - public class TestSceneBeatmapPanel : OsuTestScene + public class TestSceneTournamentBeatmapPanel : OsuTestScene { [Resolved] private IAPIProvider api { get; set; } @@ -23,11 +21,6 @@ namespace osu.Game.Tournament.Tests [Resolved] private RulesetStore rulesets { get; set; } - public override IReadOnlyList RequiredTypes => new[] - { - typeof(TournamentBeatmapPanel), - }; - [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs similarity index 98% rename from osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs rename to osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index 829d8629e5..41d32d9448 100644 --- a/osu.Game.Tournament.Tests/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -11,7 +11,7 @@ using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; using osu.Game.Users; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Tests.Components { public class TestSceneTournamentMatchChatDisplay : OsuTestScene { diff --git a/osu.Game.Tournament.Tests/TestSceneGameplayScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs similarity index 93% rename from osu.Game.Tournament.Tests/TestSceneGameplayScreen.cs rename to osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs index 74d8615db0..201736f38a 100644 --- a/osu.Game.Tournament.Tests/TestSceneGameplayScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs @@ -6,7 +6,7 @@ using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Gameplay; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Tests.Screens { public class TestSceneGameplayScreen : OsuTestScene { diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs new file mode 100644 index 0000000000..a45c5de2bd --- /dev/null +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs @@ -0,0 +1,23 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Graphics.Cursor; +using osu.Game.Tournament.Screens.Editors; + +namespace osu.Game.Tournament.Tests.Screens +{ + public class TestSceneLadderEditorScreen : LadderTestScene + { + [BackgroundDependencyLoader] + private void load() + { + Add(new OsuContextMenuContainer + { + RelativeSizeAxes = Axes.Both, + Child = new LadderEditorScreen() + }); + } + } +} diff --git a/osu.Game.Tournament.Tests/TestSceneLadderManager.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs similarity index 84% rename from osu.Game.Tournament.Tests/TestSceneLadderManager.cs rename to osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs index c9ea740f92..2be0564c82 100644 --- a/osu.Game.Tournament.Tests/TestSceneLadderManager.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs @@ -6,9 +6,9 @@ using osu.Framework.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Tournament.Screens.Ladder; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneLadderManager : LadderTestScene + public class TestSceneLadderScreen : LadderTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament.Tests/TestSceneMapPool.cs b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs similarity index 84% rename from osu.Game.Tournament.Tests/TestSceneMapPool.cs rename to osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs index 43f4831a2a..a7011c6d3c 100644 --- a/osu.Game.Tournament.Tests/TestSceneMapPool.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Tournament.Screens.MapPool; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneMapPool : LadderTestScene + public class TestSceneMapPoolScreen : LadderTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tournament.Tests/TestSceneRoundEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs similarity index 89% rename from osu.Game.Tournament.Tests/TestSceneRoundEditorScreen.cs rename to osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs index 9c1207a718..6203d68e80 100644 --- a/osu.Game.Tournament.Tests/TestSceneRoundEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs @@ -3,7 +3,7 @@ using osu.Game.Tournament.Screens.Editors; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Tests.Screens { public class TestSceneRoundEditorScreen : LadderTestScene { diff --git a/osu.Game.Tournament.Tests/TestSceneSchedule.cs b/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs similarity index 60% rename from osu.Game.Tournament.Tests/TestSceneSchedule.cs rename to osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs index 00eb4c4e41..f3e65919eb 100644 --- a/osu.Game.Tournament.Tests/TestSceneSchedule.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs @@ -1,21 +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.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Tests.Visual; using osu.Game.Tournament.Screens.Schedule; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneSchedule : OsuTestScene + public class TestSceneScheduleScreen : OsuTestScene { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(ScheduleScreen) - }; - [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game.Tournament.Tests/TestSceneShowcase.cs b/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs similarity index 60% rename from osu.Game.Tournament.Tests/TestSceneShowcase.cs rename to osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs index a4d518eedd..edf1477b06 100644 --- a/osu.Game.Tournament.Tests/TestSceneShowcase.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs @@ -1,21 +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.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Tests.Visual; using osu.Game.Tournament.Screens.Showcase; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneShowcase : OsuTestScene + public class TestSceneShowcaseScreen : OsuTestScene { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(ShowcaseScreen) - }; - [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game.Tournament.Tests/TestSceneTeamEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs similarity index 89% rename from osu.Game.Tournament.Tests/TestSceneTeamEditorScreen.cs rename to osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs index df0b79d8a9..126e0c2fda 100644 --- a/osu.Game.Tournament.Tests/TestSceneTeamEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs @@ -3,7 +3,7 @@ using osu.Game.Tournament.Screens.Editors; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Tests.Screens { public class TestSceneTeamEditorScreen : LadderTestScene { diff --git a/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs similarity index 91% rename from osu.Game.Tournament.Tests/TestSceneTeamIntro.cs rename to osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs index 6b31fd2742..3d340e393c 100644 --- a/osu.Game.Tournament.Tests/TestSceneTeamIntro.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs @@ -8,9 +8,9 @@ using osu.Framework.Graphics; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.TeamIntro; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneTeamIntro : LadderTestScene + public class TestSceneTeamIntroScreen : LadderTestScene { [Cached] private readonly Bindable currentMatch = new Bindable(); diff --git a/osu.Game.Tournament.Tests/TestSceneTeamWin.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs similarity index 91% rename from osu.Game.Tournament.Tests/TestSceneTeamWin.cs rename to osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs index d195ad42ca..6f5e17a36e 100644 --- a/osu.Game.Tournament.Tests/TestSceneTeamWin.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs @@ -8,9 +8,9 @@ using osu.Framework.Graphics; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.TeamWin; -namespace osu.Game.Tournament.Tests +namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneTeamWin : LadderTestScene + public class TestSceneTeamWinScreen : LadderTestScene { [Cached] private readonly Bindable currentMatch = new Bindable(); diff --git a/osu.Game.Tournament.Tests/TestSceneSceneManager.cs b/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs similarity index 87% rename from osu.Game.Tournament.Tests/TestSceneSceneManager.cs rename to osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs index aa333e39b1..378614343a 100644 --- a/osu.Game.Tournament.Tests/TestSceneSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs @@ -7,7 +7,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tournament.Tests { - public class TestSceneSceneManager : OsuTestScene + public class TestSceneTournamentSceneManager : OsuTestScene { [BackgroundDependencyLoader] private void load(Storage storage) diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index 8412166250..8adff80820 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -10,7 +10,4 @@ - - - \ No newline at end of file From e4eae3a6d5868952ae0d31492456cc0534d7f069 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 15:40:57 +0900 Subject: [PATCH 1322/5608] Move rider configurations into folders --- ...RulesetTests__catch_.xml => CatchRuleset__Tests_.xml} | 9 ++++++--- ...RulesetTests__mania_.xml => ManiaRuleset__Tests_.xml} | 9 ++++++--- .../{RulesetTests__osu__.xml => OsuRuleset__Tests_.xml} | 9 ++++++--- ...RulesetTests__taiko_.xml => TaikoRuleset__Tests_.xml} | 9 ++++++--- .../{osu___Tournament_.xml => Tournament.xml} | 6 +++--- .../{TournamentTests.xml => Tournament__Tests_.xml} | 7 +++++-- .idea/.idea.osu/.idea/runConfigurations/osu_.xml | 2 +- .../{VisualTests.xml => osu___Tests_.xml} | 2 +- 8 files changed, 34 insertions(+), 19 deletions(-) rename .idea/.idea.osu/.idea/runConfigurations/{RulesetTests__catch_.xml => CatchRuleset__Tests_.xml} (73%) rename .idea/.idea.osu/.idea/runConfigurations/{RulesetTests__mania_.xml => ManiaRuleset__Tests_.xml} (73%) rename .idea/.idea.osu/.idea/runConfigurations/{RulesetTests__osu__.xml => OsuRuleset__Tests_.xml} (73%) rename .idea/.idea.osu/.idea/runConfigurations/{RulesetTests__taiko_.xml => TaikoRuleset__Tests_.xml} (73%) rename .idea/.idea.osu/.idea/runConfigurations/{osu___Tournament_.xml => Tournament.xml} (79%) rename .idea/.idea.osu/.idea/runConfigurations/{TournamentTests.xml => Tournament__Tests_.xml} (78%) rename .idea/.idea.osu/.idea/runConfigurations/{VisualTests.xml => osu___Tests_.xml} (89%) diff --git a/.idea/.idea.osu/.idea/runConfigurations/RulesetTests__catch_.xml b/.idea/.idea.osu/.idea/runConfigurations/CatchRuleset__Tests_.xml similarity index 73% rename from .idea/.idea.osu/.idea/runConfigurations/RulesetTests__catch_.xml rename to .idea/.idea.osu/.idea/runConfigurations/CatchRuleset__Tests_.xml index 2eff16cc91..6463dd6ea5 100644 --- a/.idea/.idea.osu/.idea/runConfigurations/RulesetTests__catch_.xml +++ b/.idea/.idea.osu/.idea/runConfigurations/CatchRuleset__Tests_.xml @@ -1,18 +1,21 @@ - + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/runConfigurations/RulesetTests__mania_.xml b/.idea/.idea.osu/.idea/runConfigurations/ManiaRuleset__Tests_.xml similarity index 73% rename from .idea/.idea.osu/.idea/runConfigurations/RulesetTests__mania_.xml rename to .idea/.idea.osu/.idea/runConfigurations/ManiaRuleset__Tests_.xml index cae9754560..0b63b2d966 100644 --- a/.idea/.idea.osu/.idea/runConfigurations/RulesetTests__mania_.xml +++ b/.idea/.idea.osu/.idea/runConfigurations/ManiaRuleset__Tests_.xml @@ -1,18 +1,21 @@ - + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/runConfigurations/RulesetTests__osu__.xml b/.idea/.idea.osu/.idea/runConfigurations/OsuRuleset__Tests_.xml similarity index 73% rename from .idea/.idea.osu/.idea/runConfigurations/RulesetTests__osu__.xml rename to .idea/.idea.osu/.idea/runConfigurations/OsuRuleset__Tests_.xml index 49ec93e1b3..750ece648b 100644 --- a/.idea/.idea.osu/.idea/runConfigurations/RulesetTests__osu__.xml +++ b/.idea/.idea.osu/.idea/runConfigurations/OsuRuleset__Tests_.xml @@ -1,18 +1,21 @@ - + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/runConfigurations/RulesetTests__taiko_.xml b/.idea/.idea.osu/.idea/runConfigurations/TaikoRuleset__Tests_.xml similarity index 73% rename from .idea/.idea.osu/.idea/runConfigurations/RulesetTests__taiko_.xml rename to .idea/.idea.osu/.idea/runConfigurations/TaikoRuleset__Tests_.xml index d0964c6f68..7b359a1ca0 100644 --- a/.idea/.idea.osu/.idea/runConfigurations/RulesetTests__taiko_.xml +++ b/.idea/.idea.osu/.idea/runConfigurations/TaikoRuleset__Tests_.xml @@ -1,18 +1,21 @@ - + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/runConfigurations/osu___Tournament_.xml b/.idea/.idea.osu/.idea/runConfigurations/Tournament.xml similarity index 79% rename from .idea/.idea.osu/.idea/runConfigurations/osu___Tournament_.xml rename to .idea/.idea.osu/.idea/runConfigurations/Tournament.xml index a5f93489e8..3722f3dc04 100644 --- a/.idea/.idea.osu/.idea/runConfigurations/osu___Tournament_.xml +++ b/.idea/.idea.osu/.idea/runConfigurations/Tournament.xml @@ -1,6 +1,6 @@ - - /// The time to retrieve the sample info list from. /// - private List sampleInfoListAt(double time) + private List sampleInfoListAt(double time) { var curveData = HitObject as IHasCurve; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index 9e95be35fa..b3be08e1f7 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy switch (TotalColumns) { - case 8 when HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && endTime - HitObject.StartTime < 1000: + case 8 when HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH) && endTime - HitObject.StartTime < 1000: addToPattern(pattern, 0, generateHold); break; @@ -72,9 +72,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy }; if (hold.Head.Samples == null) - hold.Head.Samples = new List(); + hold.Head.Samples = new List(); - hold.Head.Samples.Add(new SampleInfo { Name = SampleInfo.HIT_NORMAL }); + hold.Head.Samples.Add(new HitSampleInfo { Name = HitSampleInfo.HIT_NORMAL }); hold.Tail.Samples = HitObject.Samples; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index d13b21183b..decd159ee9 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -79,9 +79,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (!convertType.HasFlag(PatternType.KeepSingle)) { - if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && TotalColumns != 8) + if (HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH) && TotalColumns != 8) convertType |= PatternType.Mirror; - else if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_CLAP)) + else if (HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP)) convertType |= PatternType.Gathered; } } @@ -263,7 +263,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// /// Whether this hit object can generate a note in the special column. /// - private bool hasSpecialColumn => HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_CLAP) && HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH); + private bool hasSpecialColumn => HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP) && HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH); /// /// Generates a random pattern. @@ -364,7 +364,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy break; } - if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_CLAP)) + if (HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP)) p2 = 1; return GetRandomNoteCount(p2, p3, p4, p5); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 1ba6d107be..c5a27205d6 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -248,9 +248,9 @@ namespace osu.Game.Rulesets.Osu.Tests private void createCatmull(int repeats = 0) { - var repeatSamples = new List>(); + var repeatSamples = new List>(); for (int i = 0; i < repeats; i++) - repeatSamples.Add(new List()); + repeatSamples.Add(new List()); var slider = new Slider { @@ -270,11 +270,11 @@ namespace osu.Game.Rulesets.Osu.Tests addSlider(slider, 3, 1); } - private List> createEmptySamples(int repeats) + private List> createEmptySamples(int repeats) { - var repeatSamples = new List>(); + var repeatSamples = new List>(); for (int i = 0; i < repeats; i++) - repeatSamples.Add(new List()); + repeatSamples.Add(new List()); return repeatSamples; } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index a8aec005d1..a4638c31f2 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Objects /// internal float LazyTravelDistance; - public List> NodeSamples { get; set; } = new List>(); + public List> NodeSamples { get; set; } = new List>(); private int repeatCount; @@ -157,12 +157,12 @@ namespace osu.Game.Rulesets.Osu.Objects foreach (var e in SliderEventGenerator.Generate(StartTime, SpanDuration, Velocity, TickDistance, Path.Distance, this.SpanCount(), LegacyLastTickOffset)) { - var firstSample = Samples.Find(s => s.Name == SampleInfo.HIT_NORMAL) + var firstSample = Samples.Find(s => s.Name == HitSampleInfo.HIT_NORMAL) ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) - var sampleList = new List(); + var sampleList = new List(); if (firstSample != null) - sampleList.Add(new SampleInfo + sampleList.Add(new HitSampleInfo { Bank = firstSample.Bank, Volume = firstSample.Volume, @@ -225,7 +225,7 @@ namespace osu.Game.Rulesets.Osu.Objects } } - private List getNodeSamples(int nodeIndex) => + private List getNodeSamples(int nodeIndex) => nodeIndex < NodeSamples.Count ? NodeSamples[nodeIndex] : Samples; public override Judgement CreateJudgement() => new OsuJudgement(); diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneInputDrum.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneInputDrum.cs index 02300a5dde..8c1b0c4c62 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneInputDrum.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneInputDrum.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Taiko.Tests { typeof(InputDrum), typeof(DrumSampleMapping), - typeof(SampleInfo), + typeof(HitSampleInfo), typeof(SampleControlPoint) }; diff --git a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs index d7fa661e8a..ad2596931d 100644 --- a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs +++ b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Taiko.Audio foreach (var s in samplePoints) { var centre = s.GetSampleInfo(); - var rim = s.GetSampleInfo(SampleInfo.HIT_CLAP); + var rim = s.GetSampleInfo(HitSampleInfo.HIT_CLAP); // todo: this is ugly centre.Namespace = "taiko"; @@ -43,9 +43,9 @@ namespace osu.Game.Rulesets.Taiko.Audio } } - private SkinnableSound addSound(SampleInfo sampleInfo) + private SkinnableSound addSound(HitSampleInfo hitSampleInfo) { - var drawable = new SkinnableSound(sampleInfo); + var drawable = new SkinnableSound(hitSampleInfo); Sounds.Add(drawable); return drawable; } diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index f8672037cd..f0cf8d9c7d 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -79,9 +79,9 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps var curveData = obj as IHasCurve; // Old osu! used hit sounding to determine various hit type information - List samples = obj.Samples; + List samples = obj.Samples; - bool strong = samples.Any(s => s.Name == SampleInfo.HIT_FINISH); + bool strong = samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH); if (distanceData != null) { @@ -117,15 +117,15 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength) { - List> allSamples = curveData != null ? curveData.NodeSamples : new List>(new[] { samples }); + List> allSamples = curveData != null ? curveData.NodeSamples : new List>(new[] { samples }); int i = 0; for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing) { - List currentSamples = allSamples[i]; - bool isRim = currentSamples.Any(s => s.Name == SampleInfo.HIT_CLAP || s.Name == SampleInfo.HIT_WHISTLE); - strong = currentSamples.Any(s => s.Name == SampleInfo.HIT_FINISH); + List currentSamples = allSamples[i]; + bool isRim = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE); + strong = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_FINISH); if (isRim) { @@ -175,7 +175,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps } else { - bool isRim = samples.Any(s => s.Name == SampleInfo.HIT_CLAP || s.Name == SampleInfo.HIT_WHISTLE); + bool isRim = samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE); if (isRim) { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 119940536e..bd45b52d7b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } // Normal and clap samples are handled by the drum - protected override IEnumerable GetSamples() => HitObject.Samples.Where(s => s.Name != SampleInfo.HIT_NORMAL && s.Name != SampleInfo.HIT_CLAP); + protected override IEnumerable GetSamples() => HitObject.Samples.Where(s => s.Name != HitSampleInfo.HIT_NORMAL && s.Name != HitSampleInfo.HIT_CLAP); protected override string SampleNamespace => "Taiko"; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 5fd5fe342d..d087251e7e 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -354,14 +354,14 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.IsNotNull(curveData); Assert.AreEqual(new Vector2(192, 168), positionData.Position); Assert.AreEqual(956, hitObjects[0].StartTime); - Assert.IsTrue(hitObjects[0].Samples.Any(s => s.Name == SampleInfo.HIT_NORMAL)); + Assert.IsTrue(hitObjects[0].Samples.Any(s => s.Name == HitSampleInfo.HIT_NORMAL)); positionData = hitObjects[1] as IHasPosition; Assert.IsNotNull(positionData); Assert.AreEqual(new Vector2(304, 56), positionData.Position); Assert.AreEqual(1285, hitObjects[1].StartTime); - Assert.IsTrue(hitObjects[1].Samples.Any(s => s.Name == SampleInfo.HIT_CLAP)); + Assert.IsTrue(hitObjects[1].Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP)); } } @@ -384,7 +384,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual("soft-hitnormal8", getTestableSampleInfo(hitObjects[4]).LookupNames.First()); } - SampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); + HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); } [Test] @@ -402,7 +402,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual("normal-hitnormal3", getTestableSampleInfo(hitObjects[2]).LookupNames.First()); } - SampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); + HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); } [Test] @@ -422,7 +422,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(70, getTestableSampleInfo(hitObjects[3]).Volume); } - SampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); + HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); } [Test] @@ -438,34 +438,34 @@ namespace osu.Game.Tests.Beatmaps.Formats var slider1 = (ConvertSlider)hitObjects[0]; Assert.AreEqual(1, slider1.NodeSamples[0].Count); - Assert.AreEqual(SampleInfo.HIT_NORMAL, slider1.NodeSamples[0][0].Name); + Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider1.NodeSamples[0][0].Name); Assert.AreEqual(1, slider1.NodeSamples[1].Count); - Assert.AreEqual(SampleInfo.HIT_NORMAL, slider1.NodeSamples[1][0].Name); + Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider1.NodeSamples[1][0].Name); Assert.AreEqual(1, slider1.NodeSamples[2].Count); - Assert.AreEqual(SampleInfo.HIT_NORMAL, slider1.NodeSamples[2][0].Name); + Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider1.NodeSamples[2][0].Name); var slider2 = (ConvertSlider)hitObjects[1]; Assert.AreEqual(2, slider2.NodeSamples[0].Count); - Assert.AreEqual(SampleInfo.HIT_NORMAL, slider2.NodeSamples[0][0].Name); - Assert.AreEqual(SampleInfo.HIT_CLAP, slider2.NodeSamples[0][1].Name); + Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider2.NodeSamples[0][0].Name); + Assert.AreEqual(HitSampleInfo.HIT_CLAP, slider2.NodeSamples[0][1].Name); Assert.AreEqual(2, slider2.NodeSamples[1].Count); - Assert.AreEqual(SampleInfo.HIT_NORMAL, slider2.NodeSamples[1][0].Name); - Assert.AreEqual(SampleInfo.HIT_CLAP, slider2.NodeSamples[1][1].Name); + Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider2.NodeSamples[1][0].Name); + Assert.AreEqual(HitSampleInfo.HIT_CLAP, slider2.NodeSamples[1][1].Name); Assert.AreEqual(2, slider2.NodeSamples[2].Count); - Assert.AreEqual(SampleInfo.HIT_NORMAL, slider2.NodeSamples[2][0].Name); - Assert.AreEqual(SampleInfo.HIT_CLAP, slider2.NodeSamples[2][1].Name); + Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider2.NodeSamples[2][0].Name); + Assert.AreEqual(HitSampleInfo.HIT_CLAP, slider2.NodeSamples[2][1].Name); var slider3 = (ConvertSlider)hitObjects[2]; Assert.AreEqual(2, slider3.NodeSamples[0].Count); - Assert.AreEqual(SampleInfo.HIT_NORMAL, slider3.NodeSamples[0][0].Name); - Assert.AreEqual(SampleInfo.HIT_WHISTLE, slider3.NodeSamples[0][1].Name); + Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider3.NodeSamples[0][0].Name); + Assert.AreEqual(HitSampleInfo.HIT_WHISTLE, slider3.NodeSamples[0][1].Name); Assert.AreEqual(1, slider3.NodeSamples[1].Count); - Assert.AreEqual(SampleInfo.HIT_NORMAL, slider3.NodeSamples[1][0].Name); + Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider3.NodeSamples[1][0].Name); Assert.AreEqual(2, slider3.NodeSamples[2].Count); - Assert.AreEqual(SampleInfo.HIT_NORMAL, slider3.NodeSamples[2][0].Name); - Assert.AreEqual(SampleInfo.HIT_CLAP, slider3.NodeSamples[2][1].Name); + Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider3.NodeSamples[2][0].Name); + Assert.AreEqual(HitSampleInfo.HIT_CLAP, slider3.NodeSamples[2][1].Name); } } diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs index 39b7735a55..a725c58462 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs @@ -101,14 +101,14 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.IsNotNull(curveData); Assert.AreEqual(new Vector2(192, 168), positionData.Position); Assert.AreEqual(956, beatmap.HitObjects[0].StartTime); - Assert.IsTrue(beatmap.HitObjects[0].Samples.Any(s => s.Name == SampleInfo.HIT_NORMAL)); + Assert.IsTrue(beatmap.HitObjects[0].Samples.Any(s => s.Name == HitSampleInfo.HIT_NORMAL)); positionData = beatmap.HitObjects[1] as IHasPosition; Assert.IsNotNull(positionData); Assert.AreEqual(new Vector2(304, 56), positionData.Position); Assert.AreEqual(1285, beatmap.HitObjects[1].StartTime); - Assert.IsTrue(beatmap.HitObjects[1].Samples.Any(s => s.Name == SampleInfo.HIT_CLAP)); + Assert.IsTrue(beatmap.HitObjects[1].Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP)); } [TestCase(normal)] diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs new file mode 100644 index 0000000000..23a74d3fa6 --- /dev/null +++ b/osu.Game/Audio/HitSampleInfo.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; +using System.Collections.Generic; + +namespace osu.Game.Audio +{ + /// + /// Describes a gameplay hit sample. + /// + [Serializable] + public class HitSampleInfo : ISampleInfo + { + public const string HIT_WHISTLE = @"hitwhistle"; + public const string HIT_FINISH = @"hitfinish"; + public const string HIT_NORMAL = @"hitnormal"; + public const string HIT_CLAP = @"hitclap"; + + /// + /// An optional ruleset namespace. + /// + public string Namespace; + + /// + /// The bank to load the sample from. + /// + public string Bank; + + /// + /// The name of the sample to load. + /// + public string Name; + + /// + /// An optional suffix to provide priority lookup. Falls back to non-suffixed . + /// + public string Suffix; + + /// + /// The sample volume. + /// + public int Volume { get; set; } + + /// + /// Retrieve all possible filenames that can be used as a source, returned in order of preference (highest first). + /// + public virtual IEnumerable LookupNames + { + get + { + if (!string.IsNullOrEmpty(Namespace)) + { + if (!string.IsNullOrEmpty(Suffix)) + yield return $"{Namespace}/{Bank}-{Name}{Suffix}"; + + yield return $"{Namespace}/{Bank}-{Name}"; + } + + // check non-namespace as a fallback even when we have a namespace + if (!string.IsNullOrEmpty(Suffix)) + yield return $"{Bank}-{Name}{Suffix}"; + + yield return $"{Bank}-{Name}"; + } + } + + public HitSampleInfo Clone() => (HitSampleInfo)MemberwiseClone(); + } +} diff --git a/osu.Game/Audio/ISampleInfo.cs b/osu.Game/Audio/ISampleInfo.cs new file mode 100644 index 0000000000..4f81d37e78 --- /dev/null +++ b/osu.Game/Audio/ISampleInfo.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; + +namespace osu.Game.Audio +{ + public interface ISampleInfo + { + /// + /// Retrieve all possible filenames that can be used as a source, returned in order of preference (highest first). + /// + IEnumerable LookupNames { get; } + + int Volume { get; } + } +} diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs index 5bc6dce60b..66c07209f3 100644 --- a/osu.Game/Audio/SampleInfo.cs +++ b/osu.Game/Audio/SampleInfo.cs @@ -1,67 +1,24 @@ -// 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; using System.Collections.Generic; namespace osu.Game.Audio { - [Serializable] - public class SampleInfo + /// + /// Describes a gameplay sample. + /// + public class SampleInfo : ISampleInfo { - public const string HIT_WHISTLE = @"hitwhistle"; - public const string HIT_FINISH = @"hitfinish"; - public const string HIT_NORMAL = @"hitnormal"; - public const string HIT_CLAP = @"hitclap"; + private readonly string sampleName; - /// - /// An optional ruleset namespace. - /// - public string Namespace; - - /// - /// The bank to load the sample from. - /// - public string Bank; - - /// - /// The name of the sample to load. - /// - public string Name; - - /// - /// An optional suffix to provide priority lookup. Falls back to non-suffixed . - /// - public string Suffix; - - /// - /// The sample volume. - /// - public int Volume; - - /// - /// Retrieve all possible filenames that can be used as a source, returned in order of preference (highest first). - /// - public virtual IEnumerable LookupNames + public SampleInfo(string sampleName) { - get - { - if (!string.IsNullOrEmpty(Namespace)) - { - if (!string.IsNullOrEmpty(Suffix)) - yield return $"{Namespace}/{Bank}-{Name}{Suffix}"; - - yield return $"{Namespace}/{Bank}-{Name}"; - } - - // check non-namespace as a fallback even when we have a namespace - if (!string.IsNullOrEmpty(Suffix)) - yield return $"{Bank}-{Name}{Suffix}"; - - yield return $"{Bank}-{Name}"; - } + this.sampleName = sampleName; } - public SampleInfo Clone() => (SampleInfo)MemberwiseClone(); + public IEnumerable LookupNames => new[] { sampleName }; + + public int Volume { get; set; } = 100; } } diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 4c45bef862..7bc7a9056d 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -24,8 +24,8 @@ namespace osu.Game.Beatmaps.ControlPoints /// Create a SampleInfo based on the sample settings in this control point. /// /// The name of the same. - /// A populated . - public SampleInfo GetSampleInfo(string sampleName = SampleInfo.HIT_NORMAL) => new SampleInfo + /// A populated . + public HitSampleInfo GetSampleInfo(string sampleName = HitSampleInfo.HIT_NORMAL) => new HitSampleInfo { Bank = SampleBank, Name = sampleName, @@ -33,15 +33,15 @@ namespace osu.Game.Beatmaps.ControlPoints }; /// - /// Applies and to a if necessary, returning the modified . + /// Applies and to a if necessary, returning the modified . /// - /// The . This will not be modified. - /// The modified . This does not share a reference with . - public virtual SampleInfo ApplyTo(SampleInfo sampleInfo) + /// The . This will not be modified. + /// The modified . This does not share a reference with . + public virtual HitSampleInfo ApplyTo(HitSampleInfo hitSampleInfo) { - var newSampleInfo = sampleInfo.Clone(); - newSampleInfo.Bank = sampleInfo.Bank ?? SampleBank; - newSampleInfo.Volume = sampleInfo.Volume > 0 ? sampleInfo.Volume : SampleVolume; + var newSampleInfo = hitSampleInfo.Clone(); + newSampleInfo.Bank = hitSampleInfo.Bank ?? SampleBank; + newSampleInfo.Volume = hitSampleInfo.Volume > 0 ? hitSampleInfo.Volume : SampleVolume; return newSampleInfo; } diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 7b7e0e7101..7999c82761 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -193,9 +193,9 @@ namespace osu.Game.Beatmaps.Formats { public int CustomSampleBank; - public override SampleInfo ApplyTo(SampleInfo sampleInfo) + public override HitSampleInfo ApplyTo(HitSampleInfo hitSampleInfo) { - var baseInfo = base.ApplyTo(sampleInfo); + var baseInfo = base.ApplyTo(hitSampleInfo); if (string.IsNullOrEmpty(baseInfo.Suffix) && CustomSampleBank > 1) baseInfo.Suffix = CustomSampleBank.ToString(); diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 35c3a0e5e4..1f6ca4dd73 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Objects.Drawables protected SkinnableSound Samples; - protected virtual IEnumerable GetSamples() => HitObject.Samples; + protected virtual IEnumerable GetSamples() => HitObject.Samples; private readonly Lazy> nestedHitObjects = new Lazy>(); public IEnumerable NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : Enumerable.Empty(); @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Objects.Drawables var samples = GetSamples().ToArray(); - if (samples.Any()) + if (samples.Length > 0) { if (HitObject.SampleControlPoint == null) throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index cede2e50d0..bf04963b76 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Objects /// public virtual double StartTime { get; set; } - private List samples; + private List samples; /// /// The samples to be played when this hit object is hit. @@ -38,9 +38,9 @@ namespace osu.Game.Rulesets.Objects /// and can be treated as the default samples for the hit object. /// /// - public List Samples + public List Samples { - get => samples ?? (samples = new List()); + get => samples ?? (samples = new List()); set => samples = value; } diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index 48f637dfe8..6e79d0b766 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) { newCombo |= forceNewCombo; comboOffset += extraComboOffset; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index c14f3b6a42..f5b1cbcebf 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -180,7 +180,7 @@ namespace osu.Game.Rulesets.Objects.Legacy } // Generate the final per-node samples - var nodeSamples = new List>(nodes); + var nodeSamples = new List>(nodes); for (int i = 0; i < nodes; i++) nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i])); @@ -291,7 +291,7 @@ namespace osu.Game.Rulesets.Objects.Legacy /// The slider repeat count. /// The samples to be played when the slider nodes are hit. This includes the head and tail of the slider. /// The hit object. - protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples); + protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples); /// /// Creates a legacy Spinner-type hit object. @@ -312,14 +312,14 @@ namespace osu.Game.Rulesets.Objects.Legacy /// The hold end time. protected abstract HitObject CreateHold(Vector2 position, bool newCombo, int comboOffset, double endTime); - private List convertSoundType(LegacySoundType type, SampleBankInfo bankInfo) + private List convertSoundType(LegacySoundType type, SampleBankInfo bankInfo) { // Todo: This should return the normal SampleInfos if the specified sample file isn't found, but that's a pretty edge-case scenario if (!string.IsNullOrEmpty(bankInfo.Filename)) { - return new List + return new List { - new FileSampleInfo + new FileHitSampleInfo { Filename = bankInfo.Filename, Volume = bankInfo.Volume @@ -327,12 +327,12 @@ namespace osu.Game.Rulesets.Objects.Legacy }; } - var soundTypes = new List + var soundTypes = new List { - new LegacySampleInfo + new LegacyHitSampleInfo { Bank = bankInfo.Normal, - Name = SampleInfo.HIT_NORMAL, + Name = HitSampleInfo.HIT_NORMAL, Volume = bankInfo.Volume, CustomSampleBank = bankInfo.CustomSampleBank } @@ -340,10 +340,10 @@ namespace osu.Game.Rulesets.Objects.Legacy if (type.HasFlag(LegacySoundType.Finish)) { - soundTypes.Add(new LegacySampleInfo + soundTypes.Add(new LegacyHitSampleInfo { Bank = bankInfo.Add, - Name = SampleInfo.HIT_FINISH, + Name = HitSampleInfo.HIT_FINISH, Volume = bankInfo.Volume, CustomSampleBank = bankInfo.CustomSampleBank }); @@ -351,10 +351,10 @@ namespace osu.Game.Rulesets.Objects.Legacy if (type.HasFlag(LegacySoundType.Whistle)) { - soundTypes.Add(new LegacySampleInfo + soundTypes.Add(new LegacyHitSampleInfo { Bank = bankInfo.Add, - Name = SampleInfo.HIT_WHISTLE, + Name = HitSampleInfo.HIT_WHISTLE, Volume = bankInfo.Volume, CustomSampleBank = bankInfo.CustomSampleBank }); @@ -362,10 +362,10 @@ namespace osu.Game.Rulesets.Objects.Legacy if (type.HasFlag(LegacySoundType.Clap)) { - soundTypes.Add(new LegacySampleInfo + soundTypes.Add(new LegacyHitSampleInfo { Bank = bankInfo.Add, - Name = SampleInfo.HIT_CLAP, + Name = HitSampleInfo.HIT_CLAP, Volume = bankInfo.Volume, CustomSampleBank = bankInfo.CustomSampleBank }); @@ -387,7 +387,7 @@ namespace osu.Game.Rulesets.Objects.Legacy public SampleBankInfo Clone() => (SampleBankInfo)MemberwiseClone(); } - private class LegacySampleInfo : SampleInfo + private class LegacyHitSampleInfo : HitSampleInfo { public int CustomSampleBank { @@ -399,7 +399,7 @@ namespace osu.Game.Rulesets.Objects.Legacy } } - private class FileSampleInfo : SampleInfo + private class FileHitSampleInfo : HitSampleInfo { public string Filename; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index bb1a5e200d..ff6b9be8b5 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Objects.Legacy public double Distance => Path.Distance; - public List> NodeSamples { get; set; } + public List> NodeSamples { get; set; } public int RepeatCount { get; set; } public double EndTime => StartTime + this.SpanCount() * Distance / Velocity; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index 8a3e232e60..b20a027e78 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) { return new ConvertSlider { diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index b98de32bd0..0a4e38df02 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) { newCombo |= forceNewCombo; comboOffset += extraComboOffset; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs index bab21b31ad..7c1514c1eb 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko return new ConvertHit(); } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) { return new ConvertSlider { diff --git a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs index 8be95c063d..697adeda98 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Objects.Types /// n-1: The last repeat.
/// n: The last node. ///
- List> NodeSamples { get; } + List> NodeSamples { get; } } public static class HasRepeatsExtensions diff --git a/osu.Game/Screens/Play/ComboEffects.cs b/osu.Game/Screens/Play/ComboEffects.cs index d752f4a556..1c4ac921f0 100644 --- a/osu.Game/Screens/Play/ComboEffects.cs +++ b/osu.Game/Screens/Play/ComboEffects.cs @@ -2,10 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; +using osu.Game.Audio; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; @@ -13,23 +12,31 @@ namespace osu.Game.Screens.Play { public class ComboEffects : CompositeDrawable { - private SampleChannel sampleComboBreak; + private readonly ScoreProcessor processor; + + private SkinnableSound comboBreakSample; public ComboEffects(ScoreProcessor processor) { - processor.Combo.BindValueChanged(onComboChange); + this.processor = processor; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = comboBreakSample = new SkinnableSound(new SampleInfo("combobreak")); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + processor.Combo.BindValueChanged(onComboChange, true); } private void onComboChange(ValueChangedEvent combo) { if (combo.NewValue == 0 && combo.OldValue > 20) - sampleComboBreak?.Play(); - } - - [BackgroundDependencyLoader] - private void load(ISkinSource skin, AudioManager audio) - { - sampleComboBreak = skin.GetSample(@"Gameplay/combobreak") ?? audio.Samples.Get(@"Gameplay/combobreak"); + comboBreakSample?.Play(); } } -} \ No newline at end of file +} diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index e88e088f5e..8e2b5cec98 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.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.Framework.Allocation; using osu.Framework.Audio; @@ -13,14 +14,19 @@ namespace osu.Game.Skinning { public class SkinnableSound : SkinReloadableDrawable { - private readonly SampleInfo[] samples; + private readonly ISampleInfo[] hitSamples; private SampleChannel[] channels; private AudioManager audio; - public SkinnableSound(params SampleInfo[] samples) + public SkinnableSound(IEnumerable hitSamples) { - this.samples = samples; + this.hitSamples = hitSamples.ToArray(); + } + + public SkinnableSound(ISampleInfo hitSamples) + { + this.hitSamples = new[] { hitSamples }; } [BackgroundDependencyLoader] @@ -35,7 +41,7 @@ namespace osu.Game.Skinning protected override void SkinChanged(ISkinSource skin, bool allowFallback) { - channels = samples.Select(s => + channels = hitSamples.Select(s => { var ch = loadChannel(s, skin.GetSample); if (ch == null && allowFallback) @@ -44,7 +50,7 @@ namespace osu.Game.Skinning }).Where(c => c != null).ToArray(); } - private SampleChannel loadChannel(SampleInfo info, Func getSampleFunction) + private SampleChannel loadChannel(ISampleInfo info, Func getSampleFunction) { foreach (var lookup in info.LookupNames) { From 8703f0ad40ec532c98e1fbdfbd7d03bbf51c0829 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 30 Jun 2019 22:23:48 +0900 Subject: [PATCH 1597/5608] Change song select initialisation to promote db context sharing --- osu.Game/Screens/Select/BeatmapCarousel.cs | 43 ++++++++++------------ osu.Game/Screens/Select/SongSelect.cs | 2 - 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index a6fbb1ff94..16354534f4 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -11,7 +11,6 @@ using osu.Game.Configuration; using osuTK.Input; using osu.Framework.MathUtils; using System.Diagnostics; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Caching; @@ -64,35 +63,29 @@ namespace osu.Game.Screens.Select public IEnumerable BeatmapSets { get => beatmapSets.Select(g => g.BeatmapSet); - set => loadBeatmapSets(() => value); + set => loadBeatmapSets(value); } - public void LoadBeatmapSetsFromManager(BeatmapManager manager) => loadBeatmapSets(manager.GetAllUsableBeatmapSetsEnumerable); - - private void loadBeatmapSets(Func> beatmapSets) + private void loadBeatmapSets(IEnumerable beatmapSets) { CarouselRoot newRoot = new CarouselRoot(this); - Task.Run(() => - { - beatmapSets().Select(createCarouselSet).Where(g => g != null).ForEach(newRoot.AddChild); - newRoot.Filter(activeCriteria); + beatmapSets.Select(createCarouselSet).Where(g => g != null).ForEach(newRoot.AddChild); + newRoot.Filter(activeCriteria); - // preload drawables as the ctor overhead is quite high currently. - var _ = newRoot.Drawables; - }).ContinueWith(_ => Schedule(() => - { - root = newRoot; - scrollableContent.Clear(false); - itemsCache.Invalidate(); - scrollPositionCache.Invalidate(); + // preload drawables as the ctor overhead is quite high currently. + var _ = newRoot.Drawables; - Schedule(() => - { - BeatmapSetsChanged?.Invoke(); - BeatmapSetsLoaded = true; - }); - })); + root = newRoot; + scrollableContent.Clear(false); + itemsCache.Invalidate(); + scrollPositionCache.Invalidate(); + + Schedule(() => + { + BeatmapSetsChanged?.Invoke(); + BeatmapSetsLoaded = true; + }); } private readonly List yPositions = new List(); @@ -125,13 +118,15 @@ namespace osu.Game.Screens.Select } [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuConfigManager config) + private void load(OsuConfigManager config, BeatmapManager beatmaps) { config.BindWith(OsuSetting.RandomSelectAlgorithm, RandomAlgorithm); config.BindWith(OsuSetting.SongSelectRightMouseScroll, RightClickScrollingEnabled); RightClickScrollingEnabled.ValueChanged += enabled => RightMouseScrollbar = enabled.NewValue; RightClickScrollingEnabled.TriggerChange(); + + loadBeatmapSets(beatmaps.GetAllUsableBeatmapSetsEnumerable()); } public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 7c62a49a97..3581ed5534 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -244,8 +244,6 @@ namespace osu.Game.Screens.Select sampleChangeBeatmap = audio.Samples.Get(@"SongSelect/select-expand"); SampleConfirm = audio.Samples.Get(@"SongSelect/confirm-selection"); - Carousel.LoadBeatmapSetsFromManager(this.beatmaps); - if (dialogOverlay != null) { Schedule(() => From 489ca7b45786c762b1fea01cdfa60fb5b3e3b40b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 30 Jun 2019 22:26:49 +0900 Subject: [PATCH 1598/5608] Update resources in ios props --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index ce8b62cc3f..a8013914af 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -104,7 +104,7 @@ - + From 79fc143422815a9b1335f33c87cfc857b1ad14b8 Mon Sep 17 00:00:00 2001 From: HoLLy Date: Sun, 30 Jun 2019 16:52:39 +0200 Subject: [PATCH 1599/5608] Only remove .osk files when importing skin archives --- osu.Game/Skinning/SkinManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index cf1e9368bc..00e6fddc6a 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Linq.Expressions; using System.Threading; @@ -56,7 +57,7 @@ namespace osu.Game.Skinning protected override IEnumerable GetStableImportPaths() => GetStableStorage().GetDirectories(ImportFromStablePath); - protected override bool ShouldRemoveArchive(string path) => true; + protected override bool ShouldRemoveArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osk"; /// /// Returns a list of all usable s. Includes the special default skin plus all skins from . From f42ded343779ab6d168538892d0dc77d6a3ee00b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 30 Jun 2019 18:27:47 +0300 Subject: [PATCH 1600/5608] Move to DrawableOsuHitObject --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs | 2 ++ osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 10b37af957..eb5b6aab36 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { private readonly ShakeContainer shakeContainer; + public override bool HandlePositionalInput => true; + protected DrawableOsuHitObject(OsuHitObject hitObject) : base(hitObject) { diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index cc1a1f370f..1f6ca4dd73 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -81,8 +81,6 @@ namespace osu.Game.Rulesets.Objects.Drawables public override bool RemoveCompletedTransforms => false; protected override bool RequiresChildrenUpdate => true; - public override bool HandlePositionalInput => true; - public override bool IsPresent => base.IsPresent || (State.Value == ArmedState.Idle && Clock?.CurrentTime >= LifetimeStart); public readonly Bindable State = new Bindable(); From d11b799571df4d06973b4955994b94ad0e520da9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 30 Jun 2019 18:28:20 +0300 Subject: [PATCH 1601/5608] Add explaining comment --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index eb5b6aab36..f372cb65ce 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -18,6 +18,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { private readonly ShakeContainer shakeContainer; + // Must be set to update IsHovered as it's used in relax mdo to detect osu hit objects. public override bool HandlePositionalInput => true; protected DrawableOsuHitObject(OsuHitObject hitObject) From 9de4bb342311e0573163dba38c41be8878667567 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Jul 2019 16:12:20 +0900 Subject: [PATCH 1602/5608] Remove all non-transform LogoVisualisation per-frame allocations --- osu.Game/Screens/Menu/LogoVisualisation.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index c6de5857c2..2ba82b5d9b 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -96,13 +96,13 @@ namespace osu.Game.Screens.Menu var track = beatmap.Value.TrackLoaded ? beatmap.Value.Track : null; var effect = beatmap.Value.BeatmapLoaded ? beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(track?.CurrentTime ?? Time.Current) : null; - float[] temporalAmplitudes = track?.CurrentAmplitudes.FrequencyAmplitudes ?? new float[256]; + float[] temporalAmplitudes = track?.CurrentAmplitudes.FrequencyAmplitudes; for (int i = 0; i < bars_per_visualiser; i++) { if (track?.IsRunning ?? false) { - float targetAmplitude = temporalAmplitudes[(i + indexOffset) % bars_per_visualiser] * (effect?.KiaiMode == true ? 1 : 0.5f); + float targetAmplitude = (temporalAmplitudes?[(i + indexOffset) % bars_per_visualiser] ?? 0) * (effect?.KiaiMode == true ? 1 : 0.5f); if (targetAmplitude > frequencyAmplitudes[i]) frequencyAmplitudes[i] = targetAmplitude; } @@ -115,7 +115,6 @@ namespace osu.Game.Screens.Menu } indexOffset = (indexOffset + index_change) % bars_per_visualiser; - Scheduler.AddDelayed(updateAmplitudes, time_between_updates); } private void updateColour() @@ -131,7 +130,8 @@ namespace osu.Game.Screens.Menu protected override void LoadComplete() { base.LoadComplete(); - updateAmplitudes(); + + Scheduler.AddDelayed(updateAmplitudes, time_between_updates, true); } protected override void Update() From 665da09ed76c5a74bd688ddf2a41c5dd325b3ba7 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 1 Jul 2019 09:45:14 +0200 Subject: [PATCH 1603/5608] disable HD for taiko --- osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs index 502dd54e9e..a6f902208c 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs @@ -9,5 +9,6 @@ namespace osu.Game.Rulesets.Taiko.Mods { public override string Description => @"Beats fade out before you hit them!"; public override double ScoreMultiplier => 1.06; + public override bool HasImplementation => false; } } From 0636df5660c50ae08adb2732527fbf11ffb5e412 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Jul 2019 18:13:14 +0900 Subject: [PATCH 1604/5608] Add support for legacy skins which use animation frames to hide elements --- osu.Game/Skinning/LegacySkin.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 7b658f86d0..d6424df9fe 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -81,7 +81,10 @@ namespace osu.Game.Skinning }; } - var texture = GetTexture(componentName); + // temporary allowance is given for skins the fact that stable handles non-animatable items such as hitcircles (incorrectly) + // by (incorrectly) displaying the first frame of animation rather than the non-animated version. + // users have userd this to "hide" certain elements like hit300. + var texture = GetTexture($"{componentName}-0") ?? GetTexture(componentName); if (texture == null) return null; From b875ab2f5809623f2b146042d987e8bbeacd57f5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 1 Jul 2019 12:15:53 +0300 Subject: [PATCH 1605/5608] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b4af007447..5a5f93046c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + From e6c1b059bc7a4899de9a418731d386d5b37d3ca1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Jul 2019 18:49:36 +0900 Subject: [PATCH 1606/5608] Disable dimming main content --- osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs index 71e9e4bdf3..e0ded11ec9 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs @@ -32,6 +32,8 @@ namespace osu.Game.Overlays.Chat.Selection private readonly SearchTextBox search; private readonly SearchContainer sectionsFlow; + protected override bool DimMainContent => false; + public Action OnRequestJoin; public Action OnRequestLeave; From e25158f434e6a44bc396e81dd5955c6044c60551 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Jul 2019 19:35:04 +0900 Subject: [PATCH 1607/5608] Rename move and fix tests --- .../Visual/Online/TestSceneChatOverlay.cs | 135 +++++++++++++++-- .../TestSceneChatOverlayScenarios.cs | 137 ------------------ 2 files changed, 124 insertions(+), 148 deletions(-) delete mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneChatOverlayScenarios.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index c75348112f..4d3992ce13 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -3,19 +3,23 @@ using System; using System.Collections.Generic; -using System.ComponentModel; +using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; using osu.Game.Online.Chat; using osu.Game.Overlays; using osu.Game.Overlays.Chat; +using osu.Game.Overlays.Chat.Selection; using osu.Game.Overlays.Chat.Tabs; +using osu.Game.Users; +using osuTK.Input; namespace osu.Game.Tests.Visual.Online { - [Description("Testing chat api and overlay")] - public class TestSceneChatOverlay : OsuTestScene + public class TestSceneChatOverlay : ManualInputManagerTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -28,17 +32,126 @@ namespace osu.Game.Tests.Visual.Online typeof(TabCloseButton) }; - [Cached] - private readonly ChannelManager channelManager = new ChannelManager(); + private TestChatOverlay chatOverlay; + private ChannelManager channelManager; - [BackgroundDependencyLoader] - private void load() + private readonly Channel channel1 = new Channel(new User()) { Name = "test1" }; + private readonly Channel channel2 = new Channel(new User()) { Name = "test2" }; + + [SetUp] + public void Setup() { - Children = new Drawable[] + Schedule(() => { - channelManager, - new ChatOverlay { State = { Value = Visibility.Visible } } - }; + ChannelManagerContainer container; + + Child = container = new ChannelManagerContainer(new List { channel1, channel2 }) + { + RelativeSizeAxes = Axes.Both, + }; + + chatOverlay = container.ChatOverlay; + channelManager = container.ChannelManager; + }); + } + + [Test] + public void TestHideOverlay() + { + AddAssert("Chat overlay is visible", () => chatOverlay.State.Value == Visibility.Visible); + AddAssert("Selector is visible", () => chatOverlay.SelectionOverlayState == Visibility.Visible); + + AddStep("Close chat overlay", () => chatOverlay.Hide()); + + AddAssert("Chat overlay was hidden", () => chatOverlay.State.Value == Visibility.Hidden); + AddAssert("Channel selection overlay was hidden", () => chatOverlay.SelectionOverlayState == Visibility.Hidden); + } + + [Test] + public void TestSelectingChannelClosesSelector() + { + AddAssert("Selector is visible", () => chatOverlay.SelectionOverlayState == Visibility.Visible); + + AddStep("Join channel 1", () => channelManager.JoinChannel(channel1)); + AddStep("Switch to channel 1", () => clickDrawable(chatOverlay.TabMap[channel1])); + + AddAssert("Current channel is channel 1", () => channelManager.CurrentChannel.Value == channel1); + AddAssert("Channel selector was closed", () => chatOverlay.SelectionOverlayState == Visibility.Hidden); + } + + [Test] + public void TestCloseChannelWhileSelectorClosed() + { + AddStep("Join channel 1", () => channelManager.JoinChannel(channel1)); + AddStep("Join channel 2", () => channelManager.JoinChannel(channel2)); + + AddStep("Switch to channel 2", () => clickDrawable(chatOverlay.TabMap[channel2])); + AddStep("Close channel 2", () => clickDrawable(((TestChannelTabItem)chatOverlay.TabMap[channel2]).CloseButton.Child)); + + AddAssert("Selector remained closed", () => chatOverlay.SelectionOverlayState == Visibility.Hidden); + AddAssert("Current channel is channel 1", () => channelManager.CurrentChannel.Value == channel1); + + AddStep("Close channel 1", () => clickDrawable(((TestChannelTabItem)chatOverlay.TabMap[channel1]).CloseButton.Child)); + + AddAssert("Selector is visible", () => chatOverlay.SelectionOverlayState == Visibility.Visible); + } + + private void clickDrawable(Drawable d) + { + InputManager.MoveMouseTo(d); + InputManager.Click(MouseButton.Left); + } + + private class ChannelManagerContainer : Container + { + public TestChatOverlay ChatOverlay { get; private set; } + + [Cached] + public ChannelManager ChannelManager { get; } = new ChannelManager(); + + private readonly List channels; + + public ChannelManagerContainer(List channels) + { + this.channels = channels; + } + + [BackgroundDependencyLoader] + private void load() + { + ((BindableList)ChannelManager.AvailableChannels).AddRange(channels); + + Child = ChatOverlay = new TestChatOverlay { RelativeSizeAxes = Axes.Both, }; + ChatOverlay.Show(); + } + } + + private class TestChatOverlay : ChatOverlay + { + public Visibility SelectionOverlayState => ChannelSelectionOverlay.State.Value; + + public new ChannelSelectionOverlay ChannelSelectionOverlay => base.ChannelSelectionOverlay; + + protected override ChannelTabControl CreateChannelTabControl() => new TestTabControl(); + + public IReadOnlyDictionary> TabMap => ((TestTabControl)ChannelTabControl).TabMap; + } + + private class TestTabControl : ChannelTabControl + { + protected override TabItem CreateTabItem(Channel value) => new TestChannelTabItem(value); + + public new IReadOnlyDictionary> TabMap => base.TabMap; + } + + private class TestChannelTabItem : PrivateChannelTabItem + { + public TestChannelTabItem(Channel channel) + : base(channel) + { + } + + public new ClickableContainer CloseButton => base.CloseButton; } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneChatOverlayScenarios.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneChatOverlayScenarios.cs deleted file mode 100644 index 2886bcfe56..0000000000 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneChatOverlayScenarios.cs +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.UserInterface; -using osu.Game.Online.Chat; -using osu.Game.Overlays; -using osu.Game.Overlays.Chat.Selection; -using osu.Game.Overlays.Chat.Tabs; -using osu.Game.Users; -using osuTK.Input; - -namespace osu.Game.Tests.Visual.UserInterface -{ - public class TestSceneChatOverlayScenarios : ManualInputManagerTestScene - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(ChannelTabControl), - typeof(ChannelTabItem), - typeof(ChatOverlay), - }; - - private TestChatOverlay chatOverlay; - private ChannelManager channelManager; - - private readonly Channel channel1 = new Channel(new User()) { Name = "test1" }; - private readonly Channel channel2 = new Channel(new User()) { Name = "test2" }; - - [SetUp] - public void Setup() - { - Schedule(() => - { - ChannelManagerContainer container; - Child = container = new ChannelManagerContainer(new List { channel1, channel2 }) { RelativeSizeAxes = Axes.Both, }; - chatOverlay = container.ChatOverlay; - channelManager = container.ChannelManager; - }); - } - - [Test] - public void TestHideOverlay() - { - AddStep("Close chat overlay", () => chatOverlay.Hide()); - AddAssert("Channel selection overlay was hidden", () => chatOverlay.SelectionOverlayState == Visibility.Hidden); - AddAssert("Chat overlay was hidden", () => chatOverlay.State.Value == Visibility.Hidden); - } - - [Test] - public void TestTabbingAwayClosesSelector() - { - AddAssert("Selector is visible", () => chatOverlay.SelectionOverlayState == Visibility.Visible); - AddStep("Join channel 1", () => channelManager.JoinChannel(channel1)); - AddStep("Switch to channel 1", () => clickDrawable(chatOverlay.TabMap[channel1])); - AddAssert("Current channel is channel 1", () => channelManager.CurrentChannel.Value == channel1); - AddAssert("Channel selector was closed", () => chatOverlay.SelectionOverlayState == Visibility.Hidden); - } - - [Test] - public void TestCloseChannelWhileSelectorClosed() - { - AddStep("Join channel 1", () => channelManager.JoinChannel(channel1)); - AddStep("Join channel 2", () => channelManager.JoinChannel(channel2)); - AddStep("Switch to channel 2", () => clickDrawable(chatOverlay.TabMap[channel2])); - AddStep("Close channel 2", () => clickDrawable(((TestChannelTabItem)chatOverlay.TabMap[channel2]).CloseButton.Child)); - AddAssert("Selector remained closed", () => chatOverlay.SelectionOverlayState == Visibility.Hidden); - AddAssert("Current channel is channel 1", () => channelManager.CurrentChannel.Value == channel1); - AddStep("Close channel 1", () => clickDrawable(((TestChannelTabItem)chatOverlay.TabMap[channel1]).CloseButton.Child)); - AddAssert("Selector is visible", () => chatOverlay.SelectionOverlayState == Visibility.Visible); - } - - private void clickDrawable(Drawable d) - { - InputManager.MoveMouseTo(d); - InputManager.Click(MouseButton.Left); - } - - private class ChannelManagerContainer : Container - { - public TestChatOverlay ChatOverlay { get; private set; } - - [Cached] - public ChannelManager ChannelManager { get; } = new ChannelManager(); - - private readonly List channels; - - public ChannelManagerContainer(List channels) - { - this.channels = channels; - } - - [BackgroundDependencyLoader] - private void load() - { - ((BindableList)ChannelManager.AvailableChannels).AddRange(channels); - - Child = ChatOverlay = new TestChatOverlay { RelativeSizeAxes = Axes.Both, }; - ChatOverlay.Show(); - } - } - - private class TestChatOverlay : ChatOverlay - { - public Visibility SelectionOverlayState => ChannelSelectionOverlay.State.Value; - - public new ChannelSelectionOverlay ChannelSelectionOverlay => base.ChannelSelectionOverlay; - - protected override ChannelTabControl CreateChannelTabControl() => new TestTabControl(); - - public IReadOnlyDictionary> TabMap => ((TestTabControl)ChannelTabControl).TabMap; - } - - private class TestTabControl : ChannelTabControl - { - protected override TabItem CreateTabItem(Channel value) => new TestChannelTabItem(value); - - public new IReadOnlyDictionary> TabMap => base.TabMap; - } - - private class TestChannelTabItem : PrivateChannelTabItem - { - public TestChannelTabItem(Channel channel) - : base(channel) - { - } - - public new ClickableContainer CloseButton => base.CloseButton; - } - } -} From cd5e1bc4b14297e4f4fd694240ab97f5b0f15df8 Mon Sep 17 00:00:00 2001 From: MaxOhnh Date: Mon, 1 Jul 2019 13:55:09 +0200 Subject: [PATCH 1608/5608] Replace deflate progress with modified copy-paste of grow mod --- osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs | 106 ++++++++++---------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs index 2638d5bf78..56f64d14b8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -1,84 +1,84 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using System.Collections.Generic; -using OpenTK; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModDeflate : Mod, IApplicableToDrawableHitObjects + public class OsuModDeflate : Mod, IReadFromConfig, IApplicableToDrawableHitObjects { public override string Name => "Deflate"; - public override string ShortenedName => "DF"; - public override FontAwesome Icon => FontAwesome.fa_compress; + + public override string Acronym => "DF"; + + public override IconUsage Icon => FontAwesome.Solid.CompressArrowsAlt; + public override ModType Type => ModType.Fun; + public override string Description => "Become one with the approach circle..."; + public override double ScoreMultiplier => 1; + private Bindable increaseFirstObjectVisibility = new Bindable(); + + public void ReadFromConfig(OsuConfigManager config) + { + increaseFirstObjectVisibility = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility); + } + public void ApplyToDrawableHitObjects(IEnumerable drawables) { - foreach (var drawable in drawables) - drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState; + foreach (var drawable in drawables.Skip(increaseFirstObjectVisibility.Value ? 1 : 0)) + { + switch (drawable) + { + case DrawableSpinner _: + continue; + + default: + drawable.ApplyCustomUpdateState += ApplyCustomState; + break; + } + } } - private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state) + protected virtual void ApplyCustomState(DrawableHitObject drawable, ArmedState state) { - if (!(drawable is DrawableOsuHitObject d)) - return; - - var h = d.HitObject; - - const float rescale = 2; + var h = (OsuHitObject)drawable.HitObject; + // apply grow effect switch (drawable) { - case DrawableHitCircle c: - c.ApproachCircle.Hide(); - using (d.BeginAbsoluteSequence(h.StartTime - h.TimePreempt)) - { - var origScale = d.Scale; - d.ScaleTo(1.1f, 1) - .Then() - .ScaleTo(origScale, h.TimePreempt); - } - switch (state) - { - case ArmedState.Miss: - d.FadeOut(100); - break; - case ArmedState.Hit: - d.FadeOut(800) - .ScaleTo(d.Scale * 1.5f, 400, Easing.OutQuad); - break; - } + case DrawableSliderHead _: + case DrawableSliderTail _: + // special cases we should *not* be scaling. break; - case DrawableSlider s: - using (d.BeginAbsoluteSequence(h.StartTime - h.TimePreempt + 1, true)) + case DrawableSlider _: + case DrawableHitCircle _: { - float origPathWidth = s.Body.PathWidth; - var origBodySize = s.Body.Size; - var origBodyDrawPos = s.Body.DrawPosition; - - // Fits nicely for CS=4, too big on lower CS, too small on higher CS - s.Body.Animate( - b => b.MoveTo(origBodyDrawPos - new Vector2(origPathWidth)).MoveTo(origBodyDrawPos, h.TimePreempt), - b => b.ResizeTo(origBodySize * rescale).ResizeTo(origBodySize, h.TimePreempt), - b => b.TransformTo("PathWidth", origPathWidth * rescale).TransformTo("PathWidth", origPathWidth, h.TimePreempt) - ); - } - break; - case DrawableRepeatPoint rp: - if (!rp.IsFirstRepeat) + using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + drawable.ScaleTo(2f).Then().ScaleTo(1f, h.TimePreempt); // sole difference to grow mod break; - var origSizeRp = rp.Size; - using (d.BeginAbsoluteSequence(h.StartTime - h.TimePreempt + 1, true)) - rp.ResizeTo(origSizeRp * rescale).ResizeTo(origSizeRp, h.TimePreempt); + } + } + + // remove approach circles + switch (drawable) + { + case DrawableHitCircle circle: + // we don't want to see the approach circle + using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + circle.ApproachCircle.Hide(); break; } } From 02b9e89f431b3164f5850587ae6eca5df3d67b44 Mon Sep 17 00:00:00 2001 From: MaxOhnh Date: Mon, 1 Jul 2019 14:46:17 +0200 Subject: [PATCH 1609/5608] Removed old unnecessary change, updated license header and apply deflating onto first object regardless --- osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs | 15 ++++----------- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 -- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs index 56f64d14b8..56bb55c13e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; @@ -14,7 +14,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModDeflate : Mod, IReadFromConfig, IApplicableToDrawableHitObjects + public class OsuModDeflate : Mod, IApplicableToDrawableHitObjects { public override string Name => "Deflate"; @@ -28,16 +28,9 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; - private Bindable increaseFirstObjectVisibility = new Bindable(); - - public void ReadFromConfig(OsuConfigManager config) - { - increaseFirstObjectVisibility = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility); - } - public void ApplyToDrawableHitObjects(IEnumerable drawables) { - foreach (var drawable in drawables.Skip(increaseFirstObjectVisibility.Value ? 1 : 0)) + foreach (var drawable in drawables) { switch (drawable) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 29a84b53a9..cce6dfe106 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -41,8 +41,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }; } - public bool IsFirstRepeat => repeatPoint.RepeatIndex == 0; - protected override void CheckForResult(bool userTriggered, double timeOffset) { if (repeatPoint.StartTime <= Time.Current) From 6e739411144163839767ed11f1e09b835e1c047b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Jul 2019 22:06:54 +0900 Subject: [PATCH 1610/5608] Update iOS resources --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index a8013914af..48d2e6846a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -104,7 +104,7 @@ - + From fc8dee612388d453437dce5f19985ade52ead788 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 1 Jul 2019 23:26:53 +0930 Subject: [PATCH 1611/5608] Fix typo --- osu.Game/Skinning/LegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index d6424df9fe..513a024a36 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -83,7 +83,7 @@ namespace osu.Game.Skinning // temporary allowance is given for skins the fact that stable handles non-animatable items such as hitcircles (incorrectly) // by (incorrectly) displaying the first frame of animation rather than the non-animated version. - // users have userd this to "hide" certain elements like hit300. + // users have used this to "hide" certain elements like hit300. var texture = GetTexture($"{componentName}-0") ?? GetTexture(componentName); if (texture == null) From 313648b8694863772dcd7e8750be2f76d6e67fe0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 00:34:43 +0900 Subject: [PATCH 1612/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b430c36264..d6a998bf55 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 48d2e6846a..de4a14f01f 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 0c95dff3d690bd73dccf74f7ccdcdf45d1b275ea Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Mon, 1 Jul 2019 18:41:08 +0300 Subject: [PATCH 1613/5608] Make FlowContainer insertion cleaner --- .../Changelog/ChangelogSingleBuild.cs | 24 +++++++------------ osu.Game/Overlays/Music/PlaylistList.cs | 5 +--- .../Profile/Header/MedalHeaderContainer.cs | 4 +--- .../Sections/Ranks/DrawableProfileScore.cs | 3 +-- osu.Game/Overlays/Settings/SettingsItem.cs | 3 +-- 5 files changed, 12 insertions(+), 27 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index 36ae5a756c..fdd3d6d555 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -88,24 +88,16 @@ namespace osu.Game.Overlays.Changelog }); } - NavigationIconButton left, right; - - fill.AddRange(new[] + fill.Insert(-1, new NavigationIconButton(Build.Versions?.Previous) { - left = new NavigationIconButton(Build.Versions?.Previous) - { - Icon = FontAwesome.Solid.ChevronLeft, - SelectBuild = b => SelectBuild(b) - }, - right = new NavigationIconButton(Build.Versions?.Next) - { - Icon = FontAwesome.Solid.ChevronRight, - SelectBuild = b => SelectBuild(b) - }, + Icon = FontAwesome.Solid.ChevronLeft, + SelectBuild = b => SelectBuild(b) + }); + fill.Insert(1, new NavigationIconButton(Build.Versions?.Next) + { + Icon = FontAwesome.Solid.ChevronRight, + SelectBuild = b => SelectBuild(b) }); - - fill.SetLayoutPosition(left, -1); - fill.SetLayoutPosition(right, 1); return fill; } diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 07040f166d..539601c359 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -85,10 +85,7 @@ namespace osu.Game.Overlays.Music private void addBeatmapSet(BeatmapSetInfo obj) => Schedule(() => { - var newItem = new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }; - - items.Add(newItem); - items.SetLayoutPosition(newItem, items.Count - 1); + items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }); }); private void removeBeatmapSet(BeatmapSetInfo obj) => Schedule(() => diff --git a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs index 67229a80c0..45bc60f794 100644 --- a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs @@ -78,10 +78,8 @@ namespace osu.Game.Overlays.Profile.Header int displayIndex = index; LoadComponentAsync(new DrawableBadge(badges[index]), asyncBadge => { - badgeFlowContainer.Add(asyncBadge); - // load in stable order regardless of async load order. - badgeFlowContainer.SetLayoutPosition(asyncBadge, displayIndex); + badgeFlowContainer.Insert(displayIndex, asyncBadge); }); } } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index 0a90c9b135..b77357edd8 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -49,8 +49,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Font = OsuFont.GetFont(size: 11, weight: FontWeight.Regular, italics: true) }; - RightFlowContainer.Add(text); - RightFlowContainer.SetLayoutPosition(text, 1); + RightFlowContainer.Insert(1, text); LeftFlowContainer.Add(new BeatmapMetadataContainer(Score.Beatmap)); LeftFlowContainer.Add(new DrawableDate(Score.Date)); diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index ae840c8c00..d48c0b6b66 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -46,8 +46,7 @@ namespace osu.Game.Overlays.Settings if (text == null) { // construct lazily for cases where the label is not needed (may be provided by the Control). - Add(text = new OsuSpriteText()); - FlowContent.SetLayoutPosition(text, -1); + FlowContent.Insert(-1, text = new OsuSpriteText()); } text.Text = value; From 7bdf73795669a69582126c13211acea559f1f261 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Mon, 1 Jul 2019 18:41:40 +0300 Subject: [PATCH 1614/5608] Make notification insertion cleaner --- osu.Game/Overlays/Notifications/NotificationSection.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index f9278bbbd2..17a2d4cf9f 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -26,8 +26,7 @@ namespace osu.Game.Overlays.Notifications public void Add(Notification notification, float position) { - notifications.Add(notification); - notifications.SetLayoutPosition(notification, position); + notifications.Insert((int)position, notification); } public IEnumerable AcceptTypes; From 9037fb59de95a3cdcd6dd4de68b0461244b33a35 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Mon, 1 Jul 2019 18:42:18 +0300 Subject: [PATCH 1615/5608] Make BeatmapOptionsButton insertion cleaner --- osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs index 669264cef0..ede526f9da 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs @@ -110,8 +110,7 @@ namespace osu.Game.Screens.Select.Options HotKey = hotkey }; - buttonsContainer.Add(button); - buttonsContainer.SetLayoutPosition(button, depth); + buttonsContainer.Insert((int)depth, button); } } } From 48a828b7466a6ce369d4d977af8670ca1c38f889 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Mon, 1 Jul 2019 17:49:37 +0200 Subject: [PATCH 1616/5608] Removed redundant imports and fixed indentation --- osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs index 56bb55c13e..cbefc42c3b 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -2,11 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Linq; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; @@ -58,11 +55,11 @@ namespace osu.Game.Rulesets.Osu.Mods case DrawableSlider _: case DrawableHitCircle _: - { - using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) - drawable.ScaleTo(2f).Then().ScaleTo(1f, h.TimePreempt); // sole difference to grow mod - break; - } + { + using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + drawable.ScaleTo(2f).Then().ScaleTo(1f, h.TimePreempt); // sole difference to grow mod + break; + } } // remove approach circles From 5496b8bc58fae51b4dc242bb5eb0051a7d2039a1 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Mon, 1 Jul 2019 20:11:50 +0200 Subject: [PATCH 1617/5608] Rewrote traceable mod to inherit from hidden --- osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs | 3 + osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 2 + osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 90 ++++++++----------- .../Objects/Drawables/DrawableHitCircle.cs | 23 ++--- osu.Game/Overlays/Mods/ModSection.cs | 4 +- 5 files changed, 48 insertions(+), 74 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs index 8072dc09c1..9b1f43b209 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; @@ -28,6 +29,8 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; + public override Type[] IncompatibleMods => new[] { typeof(OsuModTraceable) }; + private Bindable increaseFirstObjectVisibility = new Bindable(); public void ReadFromConfig(OsuConfigManager config) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index ddf708d0f1..5887cb2865 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -17,6 +17,8 @@ namespace osu.Game.Rulesets.Osu.Mods { public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; + public override Type[] IncompatibleMods => new[] { typeof(OsuModTraceable) }; + private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index a6d8d35125..858b7e15c8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -2,83 +2,63 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Linq; using System.Collections.Generic; -using osu.Game.Graphics; +using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Framework.Graphics; -using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Osu.Mods { - internal class OsuModTraceable : Mod, IApplicableToDrawableHitObjects + internal class OsuModTraceable : OsuModHidden, IReadFromConfig, IApplicableToDrawableHitObjects { public override string Name => "Traceable"; - public override string ShortenedName => "TC"; - public override FontAwesome Icon => FontAwesome.fa_snapchat_ghost; + public override string Acronym => "TC"; + public override IconUsage Icon => FontAwesome.Brands.SnapchatGhost; public override ModType Type => ModType.Fun; public override string Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; + public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModGrow) }; - public void ApplyToDrawableHitObjects(IEnumerable drawables) + public override void ApplyToDrawableHitObjects(IEnumerable drawables) { - foreach (var drawable in drawables) - drawable.ApplyCustomUpdateState += ApplyTraceableState; + foreach (var drawable in drawables.Skip(IncreaseFirstObjectVisibility.Value ? 1 : 0)) + { + switch (drawable) + { + case DrawableHitCircle _: + drawable.ApplyCustomUpdateState += ApplyTraceableState; + break; + case DrawableSlider slider: + slider.ApplyCustomUpdateState += ApplyHiddenState; + slider.HeadCircle.ApplyCustomUpdateState += ApplyTraceableState; + break; + default: + drawable.ApplyCustomUpdateState += ApplyHiddenState; + break; + } + } } - /* Similar to ApplyHiddenState, only different if drawable is DrawableHitCircle. - * If we'd use ApplyHiddenState instead but only on non-DrawableHitCircle's, then - * the nested object HeadCircle of DrawableSlider would still use ApplyHiddenState, - * thus treating the DrawableHitCircle with the hidden mod instead of the traceable mod. - */ protected void ApplyTraceableState(DrawableHitObject drawable, ArmedState state) { - if (!(drawable is DrawableOsuHitObject d)) + if (!(drawable is DrawableHitCircle circle)) return; - var h = d.HitObject; + var h = circle.HitObject; - var fadeOutStartTime = h.StartTime - h.TimePreempt + h.TimeFadeIn; - - // new duration from completed fade in to end (before fading out) - var longFadeDuration = ((h as IHasEndTime)?.EndTime ?? h.StartTime) - fadeOutStartTime; - - switch (drawable) + // we only want to see the approach circle + using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) { - case DrawableHitCircle circle: - // we only want to see the approach circle - using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) - circle.HideButApproachCircle(); - - // approach circle fades out quickly at StartTime - using (drawable.BeginAbsoluteSequence(h.StartTime, true)) - circle.ApproachCircle.FadeOut(50); - - break; - case DrawableSlider slider: - using (slider.BeginAbsoluteSequence(fadeOutStartTime, true)) - slider.Body.FadeOut(longFadeDuration, Easing.Out); - - break; - case DrawableSliderTick sliderTick: - // slider ticks fade out over up to one second - var tickFadeOutDuration = Math.Min(sliderTick.HitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000); - - using (sliderTick.BeginAbsoluteSequence(sliderTick.HitObject.StartTime - tickFadeOutDuration, true)) - sliderTick.FadeOut(tickFadeOutDuration); - - break; - case DrawableSpinner spinner: - // hide elements we don't care about. - spinner.Disc.Hide(); - spinner.Ticks.Hide(); - spinner.Background.Hide(); - - using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true)) - spinner.FadeOut(h.TimePreempt); - - break; + circle.circle.Hide(); // CirclePiece + circle.circle.AlwaysPresent = true; + circle.ring.Hide(); + circle.flash.Hide(); + circle.explode.Hide(); + circle.number.Hide(); + circle.glow.Hide(); + circle.ApproachCircle.Show(); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 67c8371340..31c86474cd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -17,12 +17,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public class DrawableHitCircle : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { public ApproachCircle ApproachCircle; - private readonly CirclePiece circle; - private readonly RingPiece ring; - private readonly FlashPiece flash; - private readonly ExplodePiece explode; - private readonly NumberPiece number; - private readonly GlowPiece glow; + public readonly CirclePiece circle; + public readonly RingPiece ring; + public readonly FlashPiece flash; + public readonly ExplodePiece explode; + public readonly NumberPiece number; + public readonly GlowPiece glow; private readonly IBindable positionBindable = new Bindable(); private readonly IBindable stackHeightBindable = new Bindable(); @@ -113,17 +113,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - public void HideButApproachCircle() - { - circle.Hide(); - circle.AlwaysPresent = true; - ring.Hide(); - flash.Hide(); - explode.Hide(); - number.Hide(); - glow.Hide(); - } - protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!userTriggered) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index dedd397fa5..0eca1bcbec 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -112,7 +112,7 @@ namespace osu.Game.Overlays.Mods if (selected == null) continue; foreach (var type in modTypes) - if (type.IsInstanceOfType(selected)) + if (type.IsInstanceOfType(selected) && !selected.GetType().IsSubclassOf(type)) { if (immediate) button.Deselect(); @@ -130,7 +130,7 @@ namespace osu.Game.Overlays.Mods { foreach (var button in buttons) { - int i = Array.FindIndex(button.Mods, m => modTypes.Any(t => t.IsInstanceOfType(m))); + int i = Array.FindIndex(button.Mods, m => modTypes.Any(t => t.IsInstanceOfType(m) && !m.GetType().IsSubclassOf(t))); if (i >= 0) button.SelectAt(i); From d753f446e4fb995ea8ad403c851e22ff9bf46d13 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Mon, 1 Jul 2019 20:20:25 +0200 Subject: [PATCH 1618/5608] Updated license header --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 858b7e15c8..fe1b20c0cc 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Linq; From 72e5cbb07f6ec411c5774c8dbc19229ad2625507 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 2 Jul 2019 01:45:09 +0300 Subject: [PATCH 1619/5608] Add checkbox for hiding health bar --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 795f0b43f7..b5097e95c8 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -77,6 +77,7 @@ namespace osu.Game.Configuration Set(OsuSetting.BlurLevel, 0, 0, 1, 0.01); Set(OsuSetting.ShowInterface, true); + Set(OsuSetting.HideHealthBar, true); Set(OsuSetting.KeyOverlay, false); Set(OsuSetting.FloatingComments, false); @@ -131,6 +132,7 @@ namespace osu.Game.Configuration KeyOverlay, FloatingComments, ShowInterface, + HideHealthBar, MouseDisableButtons, MouseDisableWheel, AudioOffset, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 997d1354b3..2d208c5f71 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -35,6 +35,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay Bindable = config.GetBindable(OsuSetting.ShowInterface) }, new SettingsCheckbox + { + LabelText = "Hide health bar if you can't fail", + Bindable = config.GetBindable(OsuSetting.HideHealthBar), + }, + new SettingsCheckbox { LabelText = "Always show key overlay", Bindable = config.GetBindable(OsuSetting.KeyOverlay) From a8e8650dddb79298df8e4a99fddae7500de2cf10 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 2 Jul 2019 01:47:39 +0300 Subject: [PATCH 1620/5608] Move blocking fail logic into a base class --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 7 +----- osu.Game/Rulesets/Mods/ModBlockFail.cs | 30 +++++++++++++++++++++++ osu.Game/Rulesets/Mods/ModNoFail.cs | 10 +------- osu.Game/Rulesets/Mods/ModRelax.cs | 2 +- osu.sln | 12 +++++++++ 5 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 osu.Game/Rulesets/Mods/ModBlockFail.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index a6a81fa989..5625028707 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -9,18 +9,15 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.UI; -using osu.Game.Screens.Play; using static osu.Game.Input.Handlers.ReplayInputHandler; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModRelax : ModRelax, IApplicableFailOverride, IUpdatableByPlayfield, IApplicableToDrawableRuleset, IApplicableToHUD + public class OsuModRelax : ModRelax, IUpdatableByPlayfield, IApplicableToDrawableRuleset { public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things."; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray(); - public bool AllowFail => false; - public void Update(Playfield playfield) { bool requiresHold = false; @@ -86,7 +83,5 @@ namespace osu.Game.Rulesets.Osu.Mods osuInputManager = (OsuInputManager)drawableRuleset.KeyBindingInputManager; osuInputManager.AllowUserPresses = false; } - - public void ApplyToHUD(HUDOverlay overlay) => overlay.HealthDisplay.Hide(); } } diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs new file mode 100644 index 0000000000..42ec82f8aa --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Configuration; +using osu.Game.Screens.Play; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModBlockFail : Mod, IApplicableFailOverride, IApplicableToHUD, IReadFromConfig + { + private Bindable hideHealthBar = new Bindable(); + + /// + /// We never fail, 'yo. + /// + public bool AllowFail => false; + + public void ReadFromConfig(OsuConfigManager config) + { + hideHealthBar = config.GetBindable(OsuSetting.HideHealthBar); + } + + public void ApplyToHUD(HUDOverlay overlay) + { + if (hideHealthBar.Value) + overlay.HealthDisplay.Hide(); + } + } +} diff --git a/osu.Game/Rulesets/Mods/ModNoFail.cs b/osu.Game/Rulesets/Mods/ModNoFail.cs index 171ebb78bc..49ee3354c3 100644 --- a/osu.Game/Rulesets/Mods/ModNoFail.cs +++ b/osu.Game/Rulesets/Mods/ModNoFail.cs @@ -4,11 +4,10 @@ using System; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osu.Game.Screens.Play; namespace osu.Game.Rulesets.Mods { - public abstract class ModNoFail : Mod, IApplicableFailOverride, IApplicableToHUD + public abstract class ModNoFail : ModBlockFail { public override string Name => "No Fail"; public override string Acronym => "NF"; @@ -18,12 +17,5 @@ namespace osu.Game.Rulesets.Mods public override double ScoreMultiplier => 0.5; public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModAutoplay) }; - - /// - /// We never fail, 'yo. - /// - public bool AllowFail => false; - - public void ApplyToHUD(HUDOverlay overlay) => overlay.HealthDisplay.Hide(); } } diff --git a/osu.Game/Rulesets/Mods/ModRelax.cs b/osu.Game/Rulesets/Mods/ModRelax.cs index 4feb89186c..7c355577d4 100644 --- a/osu.Game/Rulesets/Mods/ModRelax.cs +++ b/osu.Game/Rulesets/Mods/ModRelax.cs @@ -7,7 +7,7 @@ using osu.Game.Graphics; namespace osu.Game.Rulesets.Mods { - public abstract class ModRelax : Mod + public abstract class ModRelax : ModBlockFail { public override string Name => "Relax"; public override string Acronym => "RX"; diff --git a/osu.sln b/osu.sln index 688339fab5..cee2be106e 100644 --- a/osu.sln +++ b/osu.sln @@ -29,6 +29,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament", "osu. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament.Tests", "osu.Game.Tournament.Tests\osu.Game.Tournament.Tests.csproj", "{5789E78D-38F9-4072-AB7B-978F34B2C17F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework", "..\..\..\Desktop\osu-framework-master\osu.Framework\osu.Framework.csproj", "{05FD51FA-88EA-4895-85A0-FDE2D7DCF6F2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework.NativeLibs", "..\..\..\Desktop\osu-framework-master\osu.Framework.NativeLibs\osu.Framework.NativeLibs.csproj", "{2E9365F4-25A1-41D1-90ED-F91B5A946DBD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -87,6 +91,14 @@ Global {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|Any CPU.Build.0 = Debug|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.ActiveCfg = Release|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.Build.0 = Release|Any CPU + {05FD51FA-88EA-4895-85A0-FDE2D7DCF6F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05FD51FA-88EA-4895-85A0-FDE2D7DCF6F2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05FD51FA-88EA-4895-85A0-FDE2D7DCF6F2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05FD51FA-88EA-4895-85A0-FDE2D7DCF6F2}.Release|Any CPU.Build.0 = Release|Any CPU + {2E9365F4-25A1-41D1-90ED-F91B5A946DBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E9365F4-25A1-41D1-90ED-F91B5A946DBD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E9365F4-25A1-41D1-90ED-F91B5A946DBD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E9365F4-25A1-41D1-90ED-F91B5A946DBD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 6a79349f4aefde437804ca8db4e6025c61e85e02 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 2 Jul 2019 02:19:59 +0300 Subject: [PATCH 1621/5608] Move health display out of the visibility container --- osu.Game/Screens/Play/HUDOverlay.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 017bf70133..6488bf9452 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -40,6 +41,7 @@ namespace osu.Game.Screens.Play private readonly IReadOnlyList mods; private Bindable showHud; + private Bindable hideHealthbar; private readonly Container visibilityContainer; private readonly BindableBool replayLoaded = new BindableBool(); @@ -77,11 +79,11 @@ namespace osu.Game.Screens.Play ComboCounter = CreateComboCounter(), }, }, - HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), ModDisplay = CreateModsContainer(), } }, + HealthDisplay = CreateHealthDisplay(), PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), new FillFlowContainer { @@ -112,8 +114,14 @@ namespace osu.Game.Screens.Play ModDisplay.Current.Value = mods; + hideHealthbar = config.GetBindable(OsuSetting.HideHealthBar); showHud = config.GetBindable(OsuSetting.ShowInterface); - showHud.ValueChanged += visible => visibilityContainer.FadeTo(visible.NewValue ? 1 : 0, duration); + showHud.ValueChanged += visible => + { + visibilityContainer.FadeTo(visible.NewValue ? 1 : 0, duration); + if (!(hideHealthbar.Value && mods.OfType().Any())) + HealthDisplay.FadeTo(visible.NewValue ? 1 : 0, duration); + }; showHud.TriggerChange(); if (!showHud.Value && !hasShownNotificationOnce) From 7c1fc075e0ca6243eb9aa6028c583e580070db2c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 2 Jul 2019 02:24:04 +0300 Subject: [PATCH 1622/5608] Remove mistaken change --- osu.sln | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/osu.sln b/osu.sln index cee2be106e..688339fab5 100644 --- a/osu.sln +++ b/osu.sln @@ -29,10 +29,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament", "osu. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament.Tests", "osu.Game.Tournament.Tests\osu.Game.Tournament.Tests.csproj", "{5789E78D-38F9-4072-AB7B-978F34B2C17F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework", "..\..\..\Desktop\osu-framework-master\osu.Framework\osu.Framework.csproj", "{05FD51FA-88EA-4895-85A0-FDE2D7DCF6F2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Framework.NativeLibs", "..\..\..\Desktop\osu-framework-master\osu.Framework.NativeLibs\osu.Framework.NativeLibs.csproj", "{2E9365F4-25A1-41D1-90ED-F91B5A946DBD}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -91,14 +87,6 @@ Global {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|Any CPU.Build.0 = Debug|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.ActiveCfg = Release|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.Build.0 = Release|Any CPU - {05FD51FA-88EA-4895-85A0-FDE2D7DCF6F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {05FD51FA-88EA-4895-85A0-FDE2D7DCF6F2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {05FD51FA-88EA-4895-85A0-FDE2D7DCF6F2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {05FD51FA-88EA-4895-85A0-FDE2D7DCF6F2}.Release|Any CPU.Build.0 = Release|Any CPU - {2E9365F4-25A1-41D1-90ED-F91B5A946DBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2E9365F4-25A1-41D1-90ED-F91B5A946DBD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2E9365F4-25A1-41D1-90ED-F91B5A946DBD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2E9365F4-25A1-41D1-90ED-F91B5A946DBD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 4145173ac905e0b3eef36e77ae542695dc68712c Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Tue, 2 Jul 2019 04:04:07 +0200 Subject: [PATCH 1623/5608] Combined hidden with traceable as multi mod --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 1 - osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 22 +++++---- .../Objects/Drawables/DrawableHitCircle.cs | 48 +++++++++---------- osu.Game.Rulesets.Osu/OsuRuleset.cs | 4 +- .../TestSceneModSelectOverlay.cs | 5 +- osu.Game/Overlays/Mods/ModSection.cs | 6 ++- 6 files changed, 44 insertions(+), 42 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 5887cb2865..2723be9df8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -17,7 +17,6 @@ namespace osu.Game.Rulesets.Osu.Mods { public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; - public override Type[] IncompatibleMods => new[] { typeof(OsuModTraceable) }; private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index fe1b20c0cc..64a331213f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -11,15 +11,15 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods { - internal class OsuModTraceable : OsuModHidden, IReadFromConfig, IApplicableToDrawableHitObjects + internal class OsuModTraceable : OsuModHidden { public override string Name => "Traceable"; public override string Acronym => "TC"; public override IconUsage Icon => FontAwesome.Brands.SnapchatGhost; - public override ModType Type => ModType.Fun; + public override ModType Type => ModType.DifficultyIncrease; public override string Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModGrow) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModGrow) }; public override void ApplyToDrawableHitObjects(IEnumerable drawables) { @@ -30,10 +30,12 @@ namespace osu.Game.Rulesets.Osu.Mods case DrawableHitCircle _: drawable.ApplyCustomUpdateState += ApplyTraceableState; break; + case DrawableSlider slider: slider.ApplyCustomUpdateState += ApplyHiddenState; slider.HeadCircle.ApplyCustomUpdateState += ApplyTraceableState; break; + default: drawable.ApplyCustomUpdateState += ApplyHiddenState; break; @@ -51,13 +53,13 @@ namespace osu.Game.Rulesets.Osu.Mods // we only want to see the approach circle using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) { - circle.circle.Hide(); // CirclePiece - circle.circle.AlwaysPresent = true; - circle.ring.Hide(); - circle.flash.Hide(); - circle.explode.Hide(); - circle.number.Hide(); - circle.glow.Hide(); + circle.Circle.Hide(); // CirclePiece + circle.Circle.AlwaysPresent = true; + circle.Ring.Hide(); + circle.Flash.Hide(); + circle.Explode.Hide(); + circle.Number.Hide(); + circle.Glow.Hide(); circle.ApproachCircle.Show(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 31c86474cd..e8a2f94c14 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -17,18 +17,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public class DrawableHitCircle : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { public ApproachCircle ApproachCircle; - public readonly CirclePiece circle; - public readonly RingPiece ring; - public readonly FlashPiece flash; - public readonly ExplodePiece explode; - public readonly NumberPiece number; - public readonly GlowPiece glow; + public readonly CirclePiece Circle; + public readonly RingPiece Ring; + public readonly FlashPiece Flash; + public readonly ExplodePiece Explode; + public readonly NumberPiece Number; + public readonly GlowPiece Glow; private readonly IBindable positionBindable = new Bindable(); private readonly IBindable stackHeightBindable = new Bindable(); private readonly IBindable scaleBindable = new Bindable(); - public OsuAction? HitAction => circle.HitAction; + public OsuAction? HitAction => Circle.HitAction; private readonly Container explodeContainer; @@ -55,8 +55,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Anchor = Anchor.Centre, Children = new Drawable[] { - glow = new GlowPiece(), - circle = new CirclePiece + Glow = new GlowPiece(), + Circle = new CirclePiece { Hit = () => { @@ -67,13 +67,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return true; }, }, - number = new NumberPiece + Number = new NumberPiece { Text = (HitObject.IndexInCurrentCombo + 1).ToString(), }, - ring = new RingPiece(), - flash = new FlashPiece(), - explode = new ExplodePiece(), + Ring = new RingPiece(), + Flash = new FlashPiece(), + Explode = new ExplodePiece(), ApproachCircle = new ApproachCircle { Alpha = 0, @@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }; //may not be so correct - Size = circle.DrawSize; + Size = Circle.DrawSize; } [BackgroundDependencyLoader] @@ -106,9 +106,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables set { base.AccentColour = value; - explode.Colour = AccentColour; - glow.Colour = AccentColour; - circle.Colour = AccentColour; + Explode.Colour = AccentColour; + Glow.Colour = AccentColour; + Circle.Colour = AccentColour; ApproachCircle.Colour = AccentColour; } } @@ -145,7 +145,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateCurrentState(ArmedState state) { - glow.FadeOut(400); + Glow.FadeOut(400); switch (state) { @@ -154,7 +154,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Expire(true); - circle.HitAction = null; + Circle.HitAction = null; // override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early. LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.HalfWindowFor(HitResult.Miss); @@ -170,18 +170,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ApproachCircle.FadeOut(50); const double flash_in = 40; - flash.FadeTo(0.8f, flash_in) + Flash.FadeTo(0.8f, flash_in) .Then() .FadeOut(100); - explode.FadeIn(flash_in); + Explode.FadeIn(flash_in); using (BeginDelayedSequence(flash_in, true)) { //after the flash, we can hide some elements that were behind it - ring.FadeOut(); - circle.FadeOut(); - number.FadeOut(); + Ring.FadeOut(); + Circle.FadeOut(); + Number.FadeOut(); this.FadeOut(800); explodeContainer.ScaleTo(1.5f, 400, Easing.OutQuad); diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 169d54d64a..9c48169a24 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Osu new OsuModHardRock(), new MultiMod(new OsuModSuddenDeath(), new OsuModPerfect()), new MultiMod(new OsuModDoubleTime(), new OsuModNightcore()), - new OsuModHidden(), + new MultiMod(new OsuModHidden(), new OsuModTraceable()), new MultiMod(new OsuModFlashlight(), new OsuModBlinds()), }; @@ -136,8 +136,6 @@ namespace osu.Game.Rulesets.Osu new OsuModWiggle(), new OsuModGrow(), new MultiMod(new ModWindUp(), new ModWindDown()), - - new OsuModTraceable(), }; default: diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 80408ab43b..9074b64eb8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -85,7 +85,7 @@ namespace osu.Game.Tests.Visual.UserInterface var assistMods = instance.GetModsFor(ModType.Automation); var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); - var hiddenMod = harderMods.FirstOrDefault(m => m is OsuModHidden); + var hiddenMod = harderMods.OfType().FirstOrDefault(m => m.Mods.Any(a => a is OsuModHidden)); var doubleTimeMod = harderMods.OfType().FirstOrDefault(m => m.Mods.Any(a => a is OsuModDoubleTime)); @@ -96,10 +96,11 @@ namespace osu.Game.Tests.Visual.UserInterface testSingleMod(noFailMod); testMultiMod(doubleTimeMod); + testMultiMod(hiddenMod); testIncompatibleMods(easy, hardRock); testDeselectAll(easierMods.Where(m => !(m is MultiMod))); testMultiplierTextColour(noFailMod, modSelect.LowMultiplierColour); - testMultiplierTextColour(hiddenMod, modSelect.HighMultiplierColour); + testMultiplierTextColour(hardRock, modSelect.HighMultiplierColour); testUnimplementedMod(autoPilotMod); } diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 0eca1bcbec..5c2ab8e18c 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -112,13 +112,15 @@ namespace osu.Game.Overlays.Mods if (selected == null) continue; foreach (var type in modTypes) - if (type.IsInstanceOfType(selected) && !selected.GetType().IsSubclassOf(type)) + { + if (type.IsInstanceOfType(selected)) { if (immediate) button.Deselect(); else Scheduler.AddDelayed(button.Deselect, delay += 50); } + } } } @@ -130,7 +132,7 @@ namespace osu.Game.Overlays.Mods { foreach (var button in buttons) { - int i = Array.FindIndex(button.Mods, m => modTypes.Any(t => t.IsInstanceOfType(m) && !m.GetType().IsSubclassOf(t))); + int i = Array.FindIndex(button.Mods, m => modTypes.Any(t => t.IsInstanceOfType(m))); if (i >= 0) button.SelectAt(i); From 8e54990f62a72dbd3789549fce975ff02e62a884 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 13:40:40 +0900 Subject: [PATCH 1624/5608] Add database statistics to GlobalStatistics --- osu.Game/Database/DatabaseContextFactory.cs | 19 ++++++++++++++++++- osu.Game/Database/OsuDbContext.cs | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index 554337c477..bb6bef1c50 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading; using Microsoft.EntityFrameworkCore.Storage; using osu.Framework.Platform; +using osu.Framework.Statistics; namespace osu.Game.Database { @@ -31,11 +32,20 @@ namespace osu.Game.Database recycleThreadContexts(); } + private static readonly GlobalStatistic reads = GlobalStatistics.Get("Database", "Get (Read)"); + private static readonly GlobalStatistic writes = GlobalStatistics.Get("Database", "Get (Write)"); + private static readonly GlobalStatistic commits = GlobalStatistics.Get("Database", "Commits"); + private static readonly GlobalStatistic rollbacks = GlobalStatistics.Get("Database", "Rollbacks"); + /// /// Get a context for the current thread for read-only usage. /// If a is in progress, the existing write-safe context will be returned. /// - public OsuDbContext Get() => threadContexts.Value; + public OsuDbContext Get() + { + reads.Value++; + return threadContexts.Value; + } /// /// Request a context for write usage. Can be consumed in a nested fashion (and will return the same underlying context). @@ -45,6 +55,7 @@ namespace osu.Game.Database /// A usage containing a usable context. public DatabaseWriteUsage GetForWrite(bool withTransaction = true) { + writes.Value++; Monitor.Enter(writeLock); OsuDbContext context; @@ -90,9 +101,15 @@ namespace osu.Game.Database if (usages == 0) { if (currentWriteDidError) + { + rollbacks.Value++; currentWriteTransaction?.Rollback(); + } else + { + commits.Value++; currentWriteTransaction?.Commit(); + } if (currentWriteDidWrite || currentWriteDidError) { diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index d31d7cbff7..538ec41b3d 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -6,6 +6,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Logging; using osu.Framework.Logging; +using osu.Framework.Statistics; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.IO; @@ -34,6 +35,8 @@ namespace osu.Game.Database private static readonly Lazy logger = new Lazy(() => new OsuDbLoggerFactory()); + private static readonly GlobalStatistic contexts = GlobalStatistics.Get("Database", "Contexts"); + static OsuDbContext() { // required to initialise native SQLite libraries on some platforms. @@ -76,6 +79,8 @@ namespace osu.Game.Database connection.Close(); throw; } + + contexts.Value++; } ~OsuDbContext() @@ -85,6 +90,20 @@ namespace osu.Game.Database Dispose(); } + private bool isDisposed; + + public override void Dispose() + { + if (isDisposed) return; + + isDisposed = true; + + base.Dispose(); + + contexts.Value--; + GC.SuppressFinalize(this); + } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); From 2645967dc4c3aa26ae1c53a8daf5a9ed53b68ce9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 15:17:35 +0900 Subject: [PATCH 1625/5608] Fix wave-based overlays always being present before initial display --- .../Graphics/Containers/OsuFocusedOverlayContainer.cs | 2 +- osu.Game/Graphics/Containers/WaveContainer.cs | 9 ++------- osu.Game/Overlays/WaveOverlayContainer.cs | 4 ++++ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index f6db3102f2..5606328575 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -15,7 +15,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.Containers { - public class OsuFocusedOverlayContainer : FocusedOverlayContainer, IPreviewTrackOwner, IKeyBindingHandler + public abstract class OsuFocusedOverlayContainer : FocusedOverlayContainer, IPreviewTrackOwner, IKeyBindingHandler { private SampleChannel samplePopIn; private SampleChannel samplePopOut; diff --git a/osu.Game/Graphics/Containers/WaveContainer.cs b/osu.Game/Graphics/Containers/WaveContainer.cs index f87909ab17..64a897088b 100644 --- a/osu.Game/Graphics/Containers/WaveContainer.cs +++ b/osu.Game/Graphics/Containers/WaveContainer.cs @@ -95,6 +95,7 @@ namespace osu.Game.Graphics.Containers AddInternal(contentContainer = new Container { RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, }); @@ -105,21 +106,15 @@ namespace osu.Game.Graphics.Containers foreach (var w in wavesContainer.Children) w.Show(); - this.FadeIn(100, Easing.OutQuint); contentContainer.MoveToY(0, APPEAR_DURATION, Easing.OutQuint); - - this.FadeIn(100, Easing.OutQuint); } protected override void PopOut() { - this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint); - contentContainer.MoveToY(DrawHeight * 2f, DISAPPEAR_DURATION, Easing.In); - foreach (var w in wavesContainer.Children) w.Hide(); - this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint); + contentContainer.MoveToY(2, DISAPPEAR_DURATION, Easing.In); } protected override void UpdateAfterChildren() diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index 05d3e7df0a..5059b136ee 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.cs @@ -25,13 +25,17 @@ namespace osu.Game.Overlays protected override void PopIn() { base.PopIn(); + Waves.Show(); + this.FadeIn(100, Easing.OutQuint); } protected override void PopOut() { base.PopOut(); + Waves.Hide(); + this.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InQuint); } } } From d27a0db45c2bfe2df8e7788c1c9b8cda5682ac2f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 15:21:57 +0900 Subject: [PATCH 1626/5608] Enforce StartHidden on relevant overlays --- osu.Game/Graphics/Containers/WaveContainer.cs | 2 ++ osu.Game/Overlays/WaveOverlayContainer.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/osu.Game/Graphics/Containers/WaveContainer.cs b/osu.Game/Graphics/Containers/WaveContainer.cs index 64a897088b..9050e775f7 100644 --- a/osu.Game/Graphics/Containers/WaveContainer.cs +++ b/osu.Game/Graphics/Containers/WaveContainer.cs @@ -29,6 +29,8 @@ namespace osu.Game.Graphics.Containers protected override Container Content => contentContainer; + protected override bool StartHidden => true; + public Color4 FirstWaveColour { get => firstWave.Colour; diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index 5059b136ee..5c87096dd4 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.cs @@ -14,6 +14,8 @@ namespace osu.Game.Overlays protected override bool BlockNonPositionalInput => true; protected override Container Content => Waves; + protected override bool StartHidden => true; + protected WaveOverlayContainer() { AddInternal(Waves = new WaveContainer From 451765784a9f5324c1f011e6c9593e714ffe749b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 15:17:15 +0900 Subject: [PATCH 1627/5608] Centralise SocialOverlay's scheduling logic Just some clean-ups to make it easier to confirm correct logic --- osu.Game/Overlays/SocialOverlay.cs | 91 +++++++++++++++--------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 780a80b4fc..4def249200 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -66,24 +66,64 @@ namespace osu.Game.Overlays } }; - Header.Tabs.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); + Header.Tabs.Current.ValueChanged += _ => queueUpdate(); - Filter.Tabs.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); + Filter.Tabs.Current.ValueChanged += _ => queueUpdate(); Filter.DisplayStyleControl.DisplayStyle.ValueChanged += style => recreatePanels(style.NewValue); - Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); + Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => queueUpdate(); + currentQuery.BindTo(Filter.Search.Current); currentQuery.ValueChanged += query => { queryChangedDebounce?.Cancel(); if (string.IsNullOrEmpty(query.NewValue)) - Scheduler.AddOnce(updateSearch); + queueUpdate(); else queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); }; + } - currentQuery.BindTo(Filter.Search.Current); + private APIRequest getUsersRequest; + + private readonly Bindable currentQuery = new Bindable(); + + private ScheduledDelegate queryChangedDebounce; + + private void queueUpdate() => Scheduler.AddOnce(updateSearch); + + private void updateSearch() + { + queryChangedDebounce?.Cancel(); + + if (!IsLoaded) + return; + + Users = null; + clearPanels(); + loading.Hide(); + getUsersRequest?.Cancel(); + + if (API?.IsLoggedIn != true) + return; + + switch (Header.Tabs.Current.Value) + { + case SocialTab.Friends: + var friendRequest = new GetFriendsRequest(); // TODO filter arguments? + friendRequest.Success += updateUsers; + API.Queue(getUsersRequest = friendRequest); + break; + + default: + var userRequest = new GetUsersRequest(); // TODO filter arguments! + userRequest.Success += response => updateUsers(response.Select(r => r.User)); + API.Queue(getUsersRequest = userRequest); + break; + } + + loading.Show(); } private void recreatePanels(PanelDisplayStyle displayStyle) @@ -133,45 +173,6 @@ namespace osu.Game.Overlays }); } - private APIRequest getUsersRequest; - - private readonly Bindable currentQuery = new Bindable(); - - private ScheduledDelegate queryChangedDebounce; - - private void updateSearch() - { - queryChangedDebounce?.Cancel(); - - if (!IsLoaded) - return; - - Users = null; - clearPanels(); - loading.Hide(); - getUsersRequest?.Cancel(); - - if (API?.IsLoggedIn != true) - return; - - switch (Header.Tabs.Current.Value) - { - case SocialTab.Friends: - var friendRequest = new GetFriendsRequest(); // TODO filter arguments? - friendRequest.Success += updateUsers; - API.Queue(getUsersRequest = friendRequest); - break; - - default: - var userRequest = new GetUsersRequest(); // TODO filter arguments! - userRequest.Success += response => updateUsers(response.Select(r => r.User)); - API.Queue(getUsersRequest = userRequest); - break; - } - - loading.Show(); - } - private void updateUsers(IEnumerable newUsers) { Users = newUsers; @@ -193,7 +194,7 @@ namespace osu.Game.Overlays switch (state) { case APIState.Online: - Scheduler.AddOnce(updateSearch); + queueUpdate(); break; default: From 29bb227de28fc264a77ded4cc1180e0a28244b55 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 16:28:06 +0900 Subject: [PATCH 1628/5608] Avoid Intro screen holding references to the intro beatmap --- osu.Game/Screens/Menu/Intro.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index c52e8541c5..dab5066c52 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -86,6 +86,7 @@ namespace osu.Game.Screens.Menu if (!resuming) { Beatmap.Value = introBeatmap; + introBeatmap = null; if (menuVoice.Value) welcome.Play(); @@ -94,7 +95,10 @@ namespace osu.Game.Screens.Menu { // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu. if (menuMusic.Value) + { track.Start(); + track = null; + } LoadComponentAsync(mainMenu = new MainMenu()); From 6c7b97931e2642090c7d28c8779498d4a46959f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 17:45:46 +0900 Subject: [PATCH 1629/5608] Avoid using a BufferedContainer for backgrounds unless required --- osu.Game/Graphics/Backgrounds/Background.cs | 36 ++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index db055d15e5..8fdb8ebcdd 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -6,23 +6,28 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Transforms; +using osuTK; namespace osu.Game.Graphics.Backgrounds { - public class Background : BufferedContainer + /// + /// A background which offer blurring on demand. + /// + public class Background : CompositeDrawable { public Sprite Sprite; private readonly string textureName; + private BufferedContainer bufferedContainer; + public Background(string textureName = @"") { - CacheDrawnFrameBuffer = true; - this.textureName = textureName; RelativeSizeAxes = Axes.Both; - Add(Sprite = new Sprite + AddInternal(Sprite = new Sprite { RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, @@ -37,5 +42,28 @@ namespace osu.Game.Graphics.Backgrounds if (!string.IsNullOrEmpty(textureName)) Sprite.Texture = textures.Get(textureName); } + + public Vector2 BlurSigma => bufferedContainer?.BlurSigma ?? Vector2.Zero; + + /// + /// Smoothly adjusts over time. + /// + /// A to which further transforms can be added. + public void BlurTo(Vector2 newBlurSigma, double duration = 0, Easing easing = Easing.None) + { + if (bufferedContainer == null) + { + RemoveInternal(Sprite); + + AddInternal(bufferedContainer = new BufferedContainer + { + CacheDrawnFrameBuffer = true, + RelativeSizeAxes = Axes.Both, + Child = Sprite + }); + } + + bufferedContainer.BlurTo(newBlurSigma, duration, easing); + } } } From 7b2227c5053f78fb3bda55854259fa7a6422e768 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 17:47:19 +0900 Subject: [PATCH 1630/5608] Fix xmldoc --- 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 8fdb8ebcdd..526b3da8a6 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Graphics.Backgrounds { /// - /// A background which offer blurring on demand. + /// A background which offers blurring via a on demand. /// public class Background : CompositeDrawable { From 587be955c3e20d667067660be5b8aa9d1f72aa31 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 17:57:23 +0900 Subject: [PATCH 1631/5608] Increase number of backgrounds in line with resources --- osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 7092ac0c4a..55338ea01a 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Backgrounds private Background background; private int currentDisplay; - private const int background_count = 5; + private const int background_count = 7; private string backgroundName => $@"Menu/menu-background-{currentDisplay % background_count + 1}"; From 79b0deb353c0d13bcf0a86ad46059ef2b82dc05a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 17:59:25 +0900 Subject: [PATCH 1632/5608] Update resources reference --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index d6a998bf55..8c4f5dcb7d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index de4a14f01f..113874f6f6 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -104,7 +104,7 @@ - + From 08dfe413c11d3112735e020dd146a9f0d63923da Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 2 Jul 2019 13:07:36 +0300 Subject: [PATCH 1633/5608] Refactor Ruleset Selector in Direct --- .../Overlays/Direct/DirectRulesetSelector.cs | 94 +++++++++++++++++++ osu.Game/Overlays/Direct/FilterControl.cs | 85 +---------------- 2 files changed, 99 insertions(+), 80 deletions(-) create mode 100644 osu.Game/Overlays/Direct/DirectRulesetSelector.cs diff --git a/osu.Game/Overlays/Direct/DirectRulesetSelector.cs b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs new file mode 100644 index 0000000000..b42633eed3 --- /dev/null +++ b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs @@ -0,0 +1,94 @@ +// 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.Sprites; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Direct +{ + public class DirectRulesetSelector : RulesetSelector + { + public override bool HandleNonPositionalInput => !Current.Disabled && base.HandleNonPositionalInput; + + public override bool HandlePositionalInput => !Current.Disabled && base.HandlePositionalInput; + + public override bool PropagatePositionalInputSubTree => !Current.Disabled && base.PropagatePositionalInputSubTree; + + public DirectRulesetSelector() + { + TabContainer.Masking = false; + TabContainer.Spacing = new Vector2(10, 0); + AutoSizeAxes = Axes.Both; + + Current.DisabledChanged += value => SelectedTab.FadeColour(value ? Color4.DarkGray : Color4.White, 200, Easing.OutQuint); + } + + protected override TabItem CreateTabItem(RulesetInfo value) => new DirectRulesetTabItem(value); + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + }; + + private class DirectRulesetTabItem : TabItem + { + private readonly SpriteIcon icon; + + public DirectRulesetTabItem(RulesetInfo value) + : base(value) + { + AutoSizeAxes = Axes.Both; + + Children = new Drawable[] + { + icon = (SpriteIcon)value.CreateInstance().CreateIcon(), + new HoverClickSounds() + }; + + icon.Size = new Vector2(30); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + updateState(); + } + + protected override bool OnHover(HoverEvent e) + { + base.OnHover(e); + updateState(); + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + updateState(); + } + + protected override void OnActivated() => updateState(); + + protected override void OnDeactivated() => updateState(); + + private void updateState() + { + if (IsHovered || Active.Value) + { + icon.FadeColour(Color4.White, 120, Easing.InQuad); + } + else + icon.FadeColour(Color4.Gray, 120, Easing.InQuad); + } + } + } +} diff --git a/osu.Game/Overlays/Direct/FilterControl.cs b/osu.Game/Overlays/Direct/FilterControl.cs index 268e011350..4b43542b43 100644 --- a/osu.Game/Overlays/Direct/FilterControl.cs +++ b/osu.Game/Overlays/Direct/FilterControl.cs @@ -4,105 +4,30 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests; using osu.Game.Overlays.SearchableList; using osu.Game.Rulesets; -using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.Direct { public class FilterControl : SearchableListFilterControl { - public readonly Bindable Ruleset = new Bindable(); - private FillFlowContainer modeButtons; + private DirectRulesetSelector rulesetSelector; protected override Color4 BackgroundColour => OsuColour.FromHex(@"384552"); protected override DirectSortCriteria DefaultTab => DirectSortCriteria.Ranked; - protected override Drawable CreateSupplementaryControls() - { - modeButtons = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Spacing = new Vector2(10f, 0f), - }; + protected override Drawable CreateSupplementaryControls() => rulesetSelector = new DirectRulesetSelector(); - return modeButtons; - } + public Bindable Ruleset => rulesetSelector.Current; [BackgroundDependencyLoader(true)] - private void load(RulesetStore rulesets, OsuColour colours, Bindable ruleset) + private void load(OsuColour colours, Bindable ruleset) { DisplayStyleControl.Dropdown.AccentColour = colours.BlueDark; - - Ruleset.Value = ruleset.Value ?? rulesets.GetRuleset(0); - foreach (var r in rulesets.AvailableRulesets) - modeButtons.Add(new RulesetToggleButton(Ruleset, r)); - } - - private class RulesetToggleButton : OsuClickableContainer - { - private Drawable icon - { - get => iconContainer.Icon; - set => iconContainer.Icon = value; - } - - private RulesetInfo ruleset; - - public RulesetInfo Ruleset - { - get => ruleset; - set - { - ruleset = value; - icon = Ruleset.CreateInstance().CreateIcon(); - } - } - - private readonly Bindable bindable; - - private readonly ConstrainedIconContainer iconContainer; - - private void Bindable_ValueChanged(ValueChangedEvent e) - { - iconContainer.FadeTo(Ruleset.ID == e.NewValue?.ID ? 1f : 0.5f, 100); - } - - public override bool HandleNonPositionalInput => !bindable.Disabled && base.HandleNonPositionalInput; - public override bool HandlePositionalInput => !bindable.Disabled && base.HandlePositionalInput; - - public RulesetToggleButton(Bindable bindable, RulesetInfo ruleset) - { - this.bindable = bindable; - AutoSizeAxes = Axes.Both; - - Children = new[] - { - iconContainer = new ConstrainedIconContainer - { - Origin = Anchor.TopLeft, - Anchor = Anchor.TopLeft, - Size = new Vector2(32), - } - }; - - Ruleset = ruleset; - bindable.ValueChanged += Bindable_ValueChanged; - Bindable_ValueChanged(new ValueChangedEvent(bindable.Value, bindable.Value)); - Action = () => bindable.Value = Ruleset; - } - - protected override void Dispose(bool isDisposing) - { - if (bindable != null) - bindable.ValueChanged -= Bindable_ValueChanged; - base.Dispose(isDisposing); - } + rulesetSelector.Current.BindTo(ruleset); } } From 2971bd8cbcf3ed62c98d4e703963ac0bdcde35fb Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 2 Jul 2019 13:22:38 +0300 Subject: [PATCH 1634/5608] Add disable trigger to a testcase --- .../Visual/Online/TestSceneDirectOverlay.cs | 40 +++++++------------ .../Overlays/Direct/DirectRulesetSelector.cs | 2 +- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs index efc12c5fdd..75c2a2a6a1 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs @@ -3,10 +3,8 @@ using System.Collections.Generic; using NUnit.Framework; -using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Overlays; -using osu.Game.Rulesets; namespace osu.Game.Tests.Visual.Online { @@ -14,7 +12,6 @@ namespace osu.Game.Tests.Visual.Online public class TestSceneDirectOverlay : OsuTestScene { private DirectOverlay direct; - private RulesetStore rulesets; protected override void LoadComplete() { @@ -25,18 +22,11 @@ namespace osu.Game.Tests.Visual.Online AddStep(@"toggle", direct.ToggleVisibility); AddStep(@"result counts", () => direct.ResultAmounts = new DirectOverlay.ResultCounts(1, 4, 13)); - } - - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) - { - this.rulesets = rulesets; + AddStep(@"trigger disabled", () => Ruleset.Disabled = !Ruleset.Disabled); } private void newBeatmaps() { - var ruleset = rulesets.GetRuleset(0); - direct.BeatmapSets = new[] { new BeatmapSetInfo @@ -65,7 +55,7 @@ namespace osu.Game.Tests.Visual.Online { new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 5.35f, Metadata = new BeatmapMetadata(), }, @@ -97,7 +87,7 @@ namespace osu.Game.Tests.Visual.Online { new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 5.81f, Metadata = new BeatmapMetadata(), }, @@ -129,23 +119,23 @@ namespace osu.Game.Tests.Visual.Online { new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 0.9f, Metadata = new BeatmapMetadata(), }, new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 1.1f, }, new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 2.02f, }, new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 3.49f, }, }, @@ -176,43 +166,43 @@ namespace osu.Game.Tests.Visual.Online { new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 1.26f, Metadata = new BeatmapMetadata(), }, new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 2.01f, }, new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 2.87f, }, new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 3.76f, }, new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 3.93f, }, new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 4.37f, }, new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 5.13f, }, new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, StarDifficulty = 5.42f, }, }, diff --git a/osu.Game/Overlays/Direct/DirectRulesetSelector.cs b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs index b42633eed3..289c44a822 100644 --- a/osu.Game/Overlays/Direct/DirectRulesetSelector.cs +++ b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.Direct private readonly SpriteIcon icon; public DirectRulesetTabItem(RulesetInfo value) - : base(value) + : base(value) { AutoSizeAxes = Axes.Both; From ee516d2515c47a3b7728805b6b7f3c8332afb528 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 2 Jul 2019 15:55:30 +0530 Subject: [PATCH 1635/5608] Make direct panel download and replay buttons share UI --- .../Gameplay/TestSceneReplayDownloadButton.cs | 2 + .../UserInterface/OsuDownloadButton.cs | 87 ++++++++++++++ osu.Game/Overlays/Direct/DownloadButton.cs | 61 ++-------- osu.Game/Screens/Play/ReplayDownloadButton.cs | 108 ++++-------------- .../Screens/Ranking/Pages/ScoreResultsPage.cs | 3 +- 5 files changed, 119 insertions(+), 142 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/OsuDownloadButton.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs index e71b2d596e..0dfcda122f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Osu; using osu.Game.Scoring; using osu.Game.Screens.Play; using osu.Game.Users; +using osuTK; using System; using System.Collections.Generic; @@ -41,6 +42,7 @@ namespace osu.Game.Tests.Visual.Gameplay { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Size = new Vector2(80, 40), }; }); } diff --git a/osu.Game/Graphics/UserInterface/OsuDownloadButton.cs b/osu.Game/Graphics/UserInterface/OsuDownloadButton.cs new file mode 100644 index 0000000000..6e95c7e291 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/OsuDownloadButton.cs @@ -0,0 +1,87 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Online; +using osuTK; + +namespace osu.Game.Graphics.UserInterface +{ + public class OsuDownloadButton : OsuAnimatedButton + { + public readonly Bindable State = new Bindable(); + + private readonly SpriteIcon icon; + private readonly SpriteIcon checkmark; + private readonly Box background; + + private OsuColour colours; + + public OsuDownloadButton() + { + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + Depth = float.MaxValue + }, + icon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(13), + Icon = FontAwesome.Solid.Download, + }, + checkmark = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + X = 8, + Size = Vector2.Zero, + Icon = FontAwesome.Solid.Check, + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + this.colours = colours; + + State.BindValueChanged(updateState, true); + } + + private void updateState(ValueChangedEvent state) + { + switch (state.NewValue) + { + case DownloadState.NotDownloaded: + background.FadeColour(colours.Gray4, 500, Easing.InOutExpo); + icon.MoveToX(0, 500, Easing.InOutExpo); + checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo); + break; + + case DownloadState.Downloading: + background.FadeColour(colours.Blue, 500, Easing.InOutExpo); + icon.MoveToX(0, 500, Easing.InOutExpo); + checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo); + break; + + case DownloadState.Downloaded: + background.FadeColour(colours.Yellow, 500, Easing.InOutExpo); + break; + + case DownloadState.LocallyAvailable: + background.FadeColour(colours.Green, 500, Easing.InOutExpo); + icon.MoveToX(-8, 500, Easing.InOutExpo); + checkmark.ScaleTo(new Vector2(13), 500, Easing.InOutExpo); + break; + } + } + } +} diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 81709187e7..9aec7bcd0c 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.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.Allocation; @@ -10,7 +10,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online; -using osuTK; namespace osu.Game.Overlays.Direct { @@ -25,7 +24,7 @@ namespace osu.Game.Overlays.Direct private OsuColour colours; private readonly ShakeContainer shakeContainer; - private readonly OsuAnimatedButton button; + private readonly OsuDownloadButton button; public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) : base(beatmapSet) @@ -35,33 +34,10 @@ namespace osu.Game.Overlays.Direct InternalChild = shakeContainer = new ShakeContainer { RelativeSizeAxes = Axes.Both, - Child = button = new OsuAnimatedButton + Child = button = new OsuDownloadButton { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - Depth = float.MaxValue - }, - icon = new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(13), - Icon = FontAwesome.Solid.Download, - }, - checkmark = new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - X = 8, - Size = Vector2.Zero, - Icon = FontAwesome.Solid.Check, - } - } - } + }, }; } @@ -69,7 +45,7 @@ namespace osu.Game.Overlays.Direct { base.LoadComplete(); - State.BindValueChanged(state => updateState(state.NewValue), true); + button.State.BindTo(State); FinishTransforms(true); } @@ -105,32 +81,11 @@ namespace osu.Game.Overlays.Direct }; } - private void updateState(DownloadState state) + protected override void Dispose(bool isDisposing) { - switch (state) - { - case DownloadState.NotDownloaded: - background.FadeColour(colours.Gray4, 500, Easing.InOutExpo); - icon.MoveToX(0, 500, Easing.InOutExpo); - checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo); - break; + base.Dispose(isDisposing); - case DownloadState.Downloading: - background.FadeColour(colours.Blue, 500, Easing.InOutExpo); - icon.MoveToX(0, 500, Easing.InOutExpo); - checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo); - break; - - case DownloadState.Downloaded: - background.FadeColour(colours.Yellow, 500, Easing.InOutExpo); - break; - - case DownloadState.LocallyAvailable: - background.FadeColour(colours.Green, 500, Easing.InOutExpo); - icon.MoveToX(-8, 500, Easing.InOutExpo); - checkmark.ScaleTo(new Vector2(13), 500, Easing.InOutExpo); - break; - } + button?.State.UnbindAll(); } } } diff --git a/osu.Game/Screens/Play/ReplayDownloadButton.cs b/osu.Game/Screens/Play/ReplayDownloadButton.cs index d715f17109..9655bde36a 100644 --- a/osu.Game/Screens/Play/ReplayDownloadButton.cs +++ b/osu.Game/Screens/Play/ReplayDownloadButton.cs @@ -2,57 +2,28 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics; -using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online; using osu.Game.Scoring; -using osuTK; -using osu.Framework.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; -using osu.Framework.Graphics.Effects; -using osuTK.Graphics; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Play { - public class ReplayDownloadButton : DownloadTrackingComposite, IHasTooltip + public class ReplayDownloadButton : DownloadTrackingComposite { [Resolved] private ScoreManager scores { get; set; } - private OsuClickableContainer button; - private SpriteIcon downloadIcon; - private SpriteIcon playIcon; + private OsuDownloadButton button; private ShakeContainer shakeContainer; - private CircularContainer circle; - - public string TooltipText - { - get - { - switch (replayAvailability) - { - case ReplayAvailability.Local: - return @"Watch replay"; - - case ReplayAvailability.Online: - return @"Download replay"; - - default: - return @"Replay unavailable"; - } - } - } private ReplayAvailability replayAvailability { get { - if (scores.IsAvailableLocally(Model.Value)) + if (State.Value == DownloadState.LocallyAvailable) return ReplayAvailability.Local; if (Model.Value is APILegacyScoreInfo apiScore && apiScore.Replay) @@ -65,54 +36,18 @@ namespace osu.Game.Screens.Play public ReplayDownloadButton(ScoreInfo score) : base(score) { - AutoSizeAxes = Axes.Both; } [BackgroundDependencyLoader(true)] - private void load(OsuGame game, OsuColour colours) + private void load(OsuGame game) { InternalChild = shakeContainer = new ShakeContainer { - AutoSizeAxes = Axes.Both, - Child = circle = new CircularContainer + RelativeSizeAxes = Axes.Both, + Child = button = new OsuDownloadButton { - Masking = true, - Size = new Vector2(40), - EdgeEffect = new EdgeEffectParameters - { - Colour = Color4.Black.Opacity(0.4f), - Type = EdgeEffectType.Shadow, - Radius = 5, - }, - Child = button = new OsuClickableContainer - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.GrayF, - }, - playIcon = new SpriteIcon - { - Icon = FontAwesome.Solid.Play, - Size = Vector2.Zero, - Colour = colours.Gray3, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - downloadIcon = new SpriteIcon - { - Icon = FontAwesome.Solid.FileDownload, - Size = Vector2.Zero, - Colour = colours.Gray3, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - }, - } - }, + RelativeSizeAxes = Axes.Both, + } }; button.Action = () => @@ -127,32 +62,29 @@ namespace osu.Game.Screens.Play scores.Download(Model.Value); break; + case DownloadState.Downloaded: case DownloadState.Downloading: shakeContainer.Shake(); break; } }; - State.BindValueChanged(state => + State.BindValueChanged((state) => { - switch (state.NewValue) + button.State.Value = state.NewValue; + + switch (replayAvailability) { - case DownloadState.Downloading: - playIcon.ResizeTo(Vector2.Zero, 400, Easing.OutQuint); - downloadIcon.ResizeTo(13, 400, Easing.OutQuint); - circle.FadeEdgeEffectTo(colours.Yellow, 400, Easing.OutQuint); + case ReplayAvailability.Local: + button.TooltipText = @"Watch replay"; break; - case DownloadState.LocallyAvailable: - playIcon.ResizeTo(13, 400, Easing.OutQuint); - downloadIcon.ResizeTo(Vector2.Zero, 400, Easing.OutQuint); - circle.FadeEdgeEffectTo(Color4.Black.Opacity(0.4f), 400, Easing.OutQuint); + case ReplayAvailability.Online: + button.TooltipText = @"Download replay"; break; - case DownloadState.NotDownloaded: - playIcon.ResizeTo(Vector2.Zero, 400, Easing.OutQuint); - downloadIcon.ResizeTo(13, 400, Easing.OutQuint); - circle.FadeEdgeEffectTo(Color4.Black.Opacity(0.4f), 400, Easing.OutQuint); + default: + button.TooltipText = @"Replay unavailable"; break; } }, true); diff --git a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs index 676c1e3adf..7c35742ff6 100644 --- a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs +++ b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs @@ -173,7 +173,8 @@ namespace osu.Game.Screens.Ranking.Pages { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - Margin = new MarginPadding { Bottom = 5 }, + Margin = new MarginPadding { Bottom = 10 }, + Size = new Vector2(50, 30), }, }; From 082fa0d808c153c105f269ee9a017dfdb0ec83ef Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 2 Jul 2019 13:35:02 +0300 Subject: [PATCH 1636/5608] simplify updateState logic --- osu.Game/Overlays/Direct/DirectRulesetSelector.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectRulesetSelector.cs b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs index 289c44a822..f2abca9ce6 100644 --- a/osu.Game/Overlays/Direct/DirectRulesetSelector.cs +++ b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs @@ -80,15 +80,7 @@ namespace osu.Game.Overlays.Direct protected override void OnDeactivated() => updateState(); - private void updateState() - { - if (IsHovered || Active.Value) - { - icon.FadeColour(Color4.White, 120, Easing.InQuad); - } - else - icon.FadeColour(Color4.Gray, 120, Easing.InQuad); - } + private void updateState() => icon.FadeColour(IsHovered || Active.Value ? Color4.White : Color4.Gray, 120, Easing.InQuad); } } } From bc821fcc5d0e16ee9b2891c9e7ce3ff04da4121c Mon Sep 17 00:00:00 2001 From: miterosan Date: Mon, 1 Jul 2019 15:28:34 +0200 Subject: [PATCH 1637/5608] Add native bass libs for x86 Android --- osu.Android/lib/x86/libbass.so | Bin 0 -> 316716 bytes osu.Android/lib/x86/libbass_fx.so | Bin 0 -> 153532 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 osu.Android/lib/x86/libbass.so create mode 100644 osu.Android/lib/x86/libbass_fx.so diff --git a/osu.Android/lib/x86/libbass.so b/osu.Android/lib/x86/libbass.so new file mode 100644 index 0000000000000000000000000000000000000000..b0f758a42b7397b3289557f51de6b55df7b3b4ea GIT binary patch literal 316716 zcmd44e_T{m{y%<)8F949d&gL#qMX{P9hEKEsAR<&2oYRF6vP>0{gHr>h@>-$y-~pn z#`QWyX=R)3x|_S}R-2Ztsr_(9RM53Tw6tA!L$ey3Qv8vkYw&r#&OHO;)V`(n_n+@P zxc7CQ=e*AAob!5}-}l_hl2MsyI-O1k{`7)g2%-ddt~y{~K?#CI=quQS8-+naBz!0= zc(uY!7je=Rj1MRK?cZq-=;}jA(!y8lH3%y{)h=US$eO8Raw$9lZ0kQT2@-;lRdMBZNnI_yph?z`x+Q4){6XgBxcIdQHZD^BjsQOo zJeG%_0{$F0SU!tU5UzhcLU@~p4+q`_91Jf7J_S6D=YJ`1)*BH*6y%Wnw}2o0TMz#U z;1$4=xx8LW1x|dw zC;o@PGk~As;a>os2?>wBP7rR{5g~lS%QqDGjJL;L4&a~qdgRRp9vgyx3%mfB<~gL_ zO~9){a1-#Gz}tEF$H238_SC0NU=MK6o@SFEq&D=VX9q3=UdZE*0saa&*dLSwm+XrW zzTn|YfwTS|Aw=-Z7vNw1D?)fULc{L?FZwJ($mjSQ;7^Z52=DRybpb#B zc?6p;Q~aL~5QKfetKd&K33$qx2w?(GZzk}(vk}589LvCi&h_*k?*KP^+fyGu0Cr!9 z5K=h*e}LZx4%VL=ML~$ai1c{=#sSA%ju6Ih{u1CK;1wMI4mkK52*ewcymo$1`r-|!f52Hh{%yd~3wq*b0RIyBK_2b^t^f|UM;Uk}aA`1o;4a`aj&}o( zs^|%C0e%zs6`r5}0OvlT7yiTfBclXi-2e2*|2gnuz`^o70K6h3{MW#L2Db9}#lU|L z34a>+OWGH?L+XB=k%53K3Q-vZ#D0|)c-B=D?|@J+zWfS=*<8-Q=D?a}vX;6&hH z{V?1J{e*S1M}fP52XlNL z__inY!u=c@qfuW%@NnSez_;`8OyJjmhjLsA{4sE_|MdVrtLTM)^YHD!<;(SKy-)3H zAMkwOVE!)vKLdLjMyIen0T9Ug+tc#sOCV2lHD4Jadg+xR1ww8F&rw8jf3l zhrg^BW<_Z7zX5*bcRlv9-Yf{mfP?mZ2-vt*FRbP9=L4??4u(Gi{1Nc)d3Y0W`R{w` z|6$;lfP?ypKtXo{2m4nu6`cRjRR}kQ;oE_qY1Runc>TQ}xN5&%SOs3vUnX$W2R-#+ zF>nzuhD;Xz6!1fcAFMCifwNom!e=~w0QjDRdZCEpJ~5a-0td&V5x}<}>ZzYazz+il z^Irj64jddW{{(!)$9mx&E^jMv3h*S3zXW~}IJjQE0Q~wVdSNCHzXKDU8xHs6?-#&l zfrI_g6yT^MJ@Ot0o&{{<Y!kMn^VR#R)*B;p&E=-*|qhk8h zqLQ-dr6o@kayZ>pSW)5vnCF^4W7gCe#j~asO)n`GW=}6Ioijrynp;>Xl)H-O7EUji zIExdrZWB4snC&nuiU zo4IEc&m}L{9CxVz{&|JM?84bB3<)CooN^cW%$_s9P(Vgl#)5fb=}&jL=1wgsLpi?h zjZC{1miH7w%kY0;E+|Ak<}4J-=PVGWyQY^3MWu7*%oS$LnI{xhlnbTv3JYi5pFo)? z5Q?BNmry!qrcgAeyb!D?%gG6rzq4cf%QT$_g~C&%Vn3%>U83 zbEX%-#yuus-rq}(WXvm>i8^_;+y&D^tjVHM1u7u#sk7&l&2h~sE15C14E3k5tN;d? zF(2A2oIAH{4tz=rXSjrU#co%@oCQ#mYcBp+@q=}aTZ1$L8$!d=3kqPMB1A@gD|Eqb zWiC|4Ib~%eidsPr$GjQS%Zh|C)8|j0I%Cf4sqV4_REx5yk4~RAZ)!?%PL6hqpHMhs z&fJ30g{};e`(xP4-L9Ht}GL#VoeV1 zu(W_GIx7ZPAI_e5ZK0fx#mSjIyS%h8je3o1=01csBrZzSJB4Y{gX|#^C_ly1VY$*? zXhf3|8YM(hj%!YNZ_B}WXHq{0UAoI=PcJ9J8U}0fv&l!3?Lq^e-Af(y@UpnPV90Oo z^qKQQ<-sehq_i-5&b$&=$(*uYWSfZ&j~0@{Y&VmbijJ_i(n6y!Nn_pfN@nz~s6DKq zCC!+ZJi}Fjj{lm~iL0hNLZ}p!GPQ7i$&B8M>4_04CuO0laNaL+(6Y-4dQrJ}madK! zDvwM01>@*-5wDIFDlcPRPH9O&N!iR^%j$^{DhH+SeMRc2lihK`WMvkX&2$y_I!{QQ z)$ZP!9Q-_m&~!6tPSRTuj5#zm`jwo8Wixs$AjlsoV?rTKS$>q5kSL*&AU!oF`^RL4 z*h3{~f`5#Vo*1EWpzC{6yY1Xt^Q$-Sw`Se%tSie+N&^AH}7 z$<$_Qy{<~kteiVEPtfxJDNo_?LS?f2{^(Be>R8ihk%?6<7Uwg|!fG-%&9!Y9KAXjw zh_4q}b~9*+JfjfH`)eAMv0hciUd@GhPT6EQG=QGKt#xRa75B0yVZCLLJv9B^s)6U=2eg6u+q+C~ z5kdaYT);20aDHLwsES_eA|%QWN&3-pt{QG(;U77z?}?$=r}qNFVv>4#xuWP{WodT9 z-gWF(vj-*gIxb_>%Icbq?V)Qnq#VY^WAtkIOC1B_?`0zoY28?TP;!L@*UncDtCqJy zSKgdbcW-t{U^&jpVnU(4joHH*O!MB`X#(d3ou=dsDA%uOK6frR|0FZXY0oHzY0_kFJ?vEpE@) zrQx2Y+e-mG5khhRW%RbiYsvOR_#r91Yr$cXdRlXLzz=$r^Bu&Hgi)r9GWcKHa@|VP z_(No%L_bPKH-Cr>t$*pQA$mF^$jZYWXRo%lLU>uqqvpUAg)^P8Jsu13gxX4fMI(IF4kUjX6jUE9O;1L#9JyQ#@_?eDH+@pB3 zgvX7TzfGmbU8NnhCjtU81y6~oh61~;8gisYD{~h(CGJ`6l|kiz@}!UR-o$DENzogWATwxJQ3b zIT#3vV;e$Q2>uh?CAjDuNAULr9Q|;u33_mP1oTy0cZKBX10MDp(C4`OG0=6m2H^TV z_gf3vfa?%09gp7*cP*|*aGk>yjq7J2veyHr;VQ*-J@-EeckuTp98cmp74+crM({or z=J)?cX!&0DUk|XD{xIEfZs%ou=^t17lz;mxZ4g|#oa{q;aVDkGvPMl zdOXCBoPWmkZ|*k-)QjtRTy9)ja2>_<2`)b_`qgQK-G736KCZVy{C);^K?n{yKZ0XC zuD5Zua8Hp_BA?^hjjKN@#A))t?+>`rak&Wa-+9nB?!FV$2>!o={uI|@?mq$aGOqV< z(K~yiL6_sApA(k>ewRS!;-Yss$u9MruHtkxr)xM}%jr5!*K_(hryDul%;{E6-{sWH z=`K#2INi@_GpC0*J;LcxPFp!W!Kt6quQ_e!^gO2>oL=En_=i?b1E)q#O`J-cMsXU= zX$+?pPOY5UIF02rj?)BAhjW_5sh!hQPSZJca5|0CVoobKt>Uzf(|S%R!(i4#&R0RX#%H7oZ2}}<(Vr>i+#!|7U1*Kztf zryDul%;{E6-{sWH=`K#2INi@_GpC0*J;LcxPFp!W!Kt6qc23W8dWBN~?~GGFWZ=}u zsfkmG(g|H#&Md!>2OYyIJI+{%4s^MnVe>Gn#-w!(|k^+aazD> zF{h=RmUHUjw1U%0POCVr;k1s^6`a;{x{A})oUY+?EvM@^6>x5u>623=AI4jv z{jsJcdL7nhL`{OQpXl{iD-s=mIXh7dm`8|WLUfcU2J}{<1F>c#dIQF3qET2=6U6}C zPIM67(;#{y*0e-1$-hGMCRDi3KyOC9BYF$QQ=&0g4-&;>P9l06&W#hrgeRJ)1#1|h zw+n)WC??8Qq8Nm2M6GyFg(wE-IHGsqJu9M^91JHqL=cjQ4iyAD(OA4!M-&sybfTC@ zWfHvy>oua7Am$Q{$GnT^FEH;Qiiy=Uq6wID5WNrYYZAR5>lLDy9F-Hr^dY#iY85C?=aVL`PzNL-aw+3y401c>z&7&cPE+#`>6O3f5&rAIAGhL{qWWB0388 zCz=NP6UD@1Bhhr&pJ)c`Pjn3IPxM!?KT%B1b`c#5`xDKA{fXw%`^KOXVSl32V1J_1 zVSl2J!u~{O!2U!FV1J?;VSl1;!u~`tkvmTm3*io;SV&(X8r-ZvHR#%8p!+M-X6V=T z3M!#cOwP8}F8p3Wr4x!NxUHFCR5GEMJlnhsqf!aQbZgtlFe;HyY$3dsVR9DR2-h=g zB@D|7ZB-0YP%$hew3RcAN+A^62~T5~Sc}sMXEO|=3&q)l?F>`YVh7GE7MquO_^a z;e5ht39n^%8sYVX>luczgyM~as~D!N6>lY6&TuJVFX3qnQ&x+c2xl|wBHT>a&M;-Y z_z2-RhARoT61Fg0Mc7YRVz`EIJ7Iz0I>H@<+rOjouOLk8v$j@->j~3zyRDhwRfK6v zrp?RnYQnTt(zcP|HH2x4r)@36YYEeKVOu@J>j=jYu3~sS;o*eK8GfCxo$xej`@qCe;_OCcKg1qlDKIUdwPR;q`>;89qUHBjGBB$uz}V370ecHDNE| zX$+I8ikk>$Gkl(KGhsW!WV+%bgyR^#Lb#Q%g<%2CVn1PtVOj+hw-Xi^HWKb2-2NXb zKkWz>(>HC}S{arI(5$KscMQo#Ekx9fac;P9i*wu!Uhe;bOuP!>NSJ z2@4FT6RsfKewnp@!c~M@8O|nLN4S~cT*CE)y$m}DuO_^aVS0Yo9x z+AdeK(iu3S%3cfhmM>8Fui&rBTY(9UWGEknAaoBy*&N-@P&!9900nOCPSF5J$z1u8 zCG#?p`CP5JEe-{j_ZUgoafHa7c6Xa9+u%!HAHmBb+qpz)4<5Ochds(r5)aE|D1oCi zhGIDy&JaFGz+~Qq3aZK*p;ft~%XJ$ivjB!CIt|HbL4>BGJ5*&WqSbm`1JpS3dk`E- zd*GBuws3L(L|j!qKV4JEZA?NtM-oG=K#*WmN!?u&qG3eokttIfCQizWzmVhqiHR)P zvXa?*RilC0gWyTEI+Rqa!GE*^;t9xKLyUj>Xgqch&8gPtM!5-$$b|4Opnqjr)4`Um z$W|EptT=SfS&N24?RhLgJ=QSVFXzLwWpmEovLkASJyewoN2X)Hs3kXA$Ks3$$lhNYBl=%U7~Oa z;a8`)Hm$3R%R47dKGVo$o`r;Z1R=J|YCJ1amIl{Ln8J8bb`nwDsnb)jrCiGT z-NE=?f*{t8M+-%cx!A2n$}*Qbq#fn(BE#|(Eq_OlLO$|W!o~LJqL}F-m<^_rX0*aI zxwG884nk25?>TYGr?{XN^P1>Z ze3%K2nrLB?PLRC@xx?aqC;kFi2bnZZ#1GUoapJcRX;%8^Vz-rCtf;3D{q;@ju<-`_ zh!)sq=ld-vGD@~5%rsO`0cu2UIv}kQ1+D54r)lmu#I4)pI>5wblDW5dR{AmEdS3Hy z!#l6>7d&Y?dP`P7-Loqwh4lI+7YeL&9BlPubshXl?u>wpQfoAFfWi-LT%t!M@MJ}> zSO>rI$fPR7dqtx|FOGvcTH#?sJeSo%apJ*XF0dvb%Sd91pGmaw@@#{tdu(_K%JM0> z)>NvpimDaz%(^n?i>Kwsn!G-Gv7KK5?S@0{C5>`H2G%3_9cTD6S9C{WPy@3 zr@kkQmb)HuKiRmHhDiEB+LHc_wLz%5toG`i)GVrZ(_QW~i?#niuK;OkJ}OnbH@*e# zl}8@#>Z-mhqDC%>8`%Xxp1G3ZTikaWwa+0)Y-o*I{u6Xw>KfF9V78t?CJb*Xdpyf^ z=%C~;2g{v<#nc0ePd@gLeCZ*#UYxYgF7LFABq{FSd0w+1GWz5*TkS{!1>Q6q_C5$} z5A`ZLeU~E?zb9$nS#e4`Yf90cab2i%T!9I&s0~VF>Y*NC<+n_O7Ws4pMDZ3VRaz|& z(1@6$US*IUc>UB*;GM!K&(!RoQEVkNt``iTZ=8736iv z>i)EPrv+t7JnQ~DYB{TXY&5Oww#6jmiE>4Owpg#MLu>M`8U%G;N!7vyb@UQY5hH_8T- z_3)-&Kjhiez7J-QjllRl#Jc20xdV?y-g>(Hp+@-%T!)(D-*1!!uq?VIbw{K8HT?2p zDiPWaSL&@B5PBZ2cRbb|p3z@)tVSP^IGl>uM;=tGlzDk1Qjz7G@FLCpQL2 zseBkPFS~--W$icaSoA2-KNLTvCw>7*nY`=j__QXi{pRY_*LJ7=@AmH0b6M=2SI54> zVuz>R6aTk8@mU!rH}u4(9KUCRBBAVMv^DVJ#qZ?H{oG<>B&oMCjSUll$I+-*ry62N z^uOpp{c)N(;pFCI21nkiW!X`=%n44-hjE?Se3UofX4cA3vqwET9_m9SW zS?;=Btj$O18f8Bgtmh2(JrwWVPPNrDrc2kNtdI*ZtlMeEajH>10XGWJ73YO$*}*1T zG)r*G>!C`>d^dX9I#hnYVI-{q-N)iFplmZjn(uhDCt;v+vHIfMxB3jVEy`Ij{cwgm zpsbP$5W_x_O&VJ~@0_r(^}?C=K&j=i@ju>s@CyunyOno0?Sj8H6Trw%vj;CaRT`6M z0=a_C8E9<6>;-vr${V{)95~%=VvOAg3k&}{!fCkTl~Ah&$L)!J6l>;{%I7eNGm5n{ zs844L3BL}zZrUose*qhD9+{R9{s42*`oZ7IoV0lGf6SZ~bYuQ~aPp}o;sh5H7xA1j zzQrS7Gm%i77g+M750>5tX@2$}b z)xHm(Gzg8=!!ggNUxONBZSZekA)66WQcY8P&(>cX?Fw@?k`#Sg4wBCNlYLj-b;(dDGkt(vC(eo2ZJ>%&(@1u());8><0O`-gl{w@A!4TR(-#H z{dOwN4HG?&U7DmcVsVmqYSB>D@W7p27jVd@s~z1<^zzgPBIMR2xg&OgN$K#v1-;50 zkxPteffl)`D-fZyQ-N~)4aRRX<&NbT)ejdxng|3XMBHRd~8+weLhTE3~GNh#a_GD)mQD;uLwHJ-=MTB`?N(Lq!&x7JxU#8QX2c6cA1rrd|iVR8|NCq*)~5yX;Yfi{=-tF z>SOf171w}T?~?v%|EgmKw_cxOB>lpe29`MTQ+3?vie$!akntrMag|rx;%%6y?4G3M z?@m>!KF$RFl#1ZGRV}xw6*k51FNcldTZZhp>2N?&-4=C`HDFZBCFLTrgX~_OGHg`z z)LSOT{2DtBsB8Xy;8za!Yjnk^1E5_=O{~VE9yyGZ7eY6Y!_uN}$%}EKlq_%8tAfw3 zm)mu6tB&d+Ws6xSB?TjKXBpDfQcM*6<& zn=Bt+((kN%$>9FllhS`m11ba*V4?+dj{g&MSk({AXL{KAu`Q?jG0k9VQ9sGIAfs|8`Z1vx-yc1+y?@k6EDqO>3M z_wzq;dk0fBMC?RqVP;E)GA8Drzd^M}qpn2X$z;?lB^iw=F?c8FklGRAC3WH{-Zn4dbpj%7m4 zO*G|4NUAAa_8H_$cK2T8lF}Lf4H(ms;DxBk7!;%xw@#xq=5B+03V!Bf$duA75R@Fl zmmAe%=CQ>V`b#N=4iplDEgCwv?)F?sz zhLWxsPz5ha{-!D|qf`!Q)Okp&8Bou{w6)d%iTtfB&RXVgP91>!Ni_pDGMGOqil?4B zAdZz)az7{Uv5!cwx@*DrN<9)#F2S{O6Ytbr6h>O@N63>XWC8)z-S68$A_T=-K8kAG^ksgxEv4H>)m=@+EFVgr5#HM^Q zT_qz|QgWqe@~!11Emau(;a+8}V&=glh18R3MQJ6M z6~)Eev>1ZER_BmaKgUHyI^Y?L(mR?INObIxzZ9#E>5zy4JW`F7Q~-bE1X}?H*C5Xd z$?+UoLyZ*u42bD3o~Vt1DEKm1qXnAY^hB*^sT!39kYj#RFtEJ2tR|p%T)$w!5(~pv z%}_K$Xypu9aId7v24bWAF~8x+N+*1_RcTz6);RdkJnPM>pcH#Ij~1)a8r#jIDaK_@ zhYxCl`Au&yH3xi7;exi!f3a)6rPgftU^)aoCfyN$`}cM&r2^|TgdQb+FH6aB9PStG zTB`ZhOoSdJey^rNY%-b0BXd}BM8Wy2poz(~#xSHs%e9i)3#>`Fm(q5N;|dF98KSHp zb}IR33UGW3_x38SSV^SmXSp77t@((IjV|*as zRVEj)4v-wJOi0ea&g&ZE+X4@K1%yOyY>));xG zU2dx?QWgo&MwAXp7?EqWiM8i27@~MpMrh6RKIT~hP@UGYoy&|2JD=kI^%86G&gUig zW70s0Qr7FDHUFog;jhnR?UxEsZ{hqFCP(A7abBC|$N1tnUt9{eb+iA$p8K zoD@ka>%a|r5SkLH4rH7UBBt*4AVQ6BW_%q)WS9(p5TSlJX+YDYkYO@fg9x?7nQ=6T ztb~pP5vxFlf+&{4nu7>6$(gY~h!O}j1rh3%GhB^aIof7^wL{NOn&@;A@RQfP`*9 zaiKMK`o4?=W*q@M;)0z48b9L2ASl=YL?LTYkVns{;7nI8`)@{X1hc2ZyesRleuaQ& zwQ`%)!zwYVg$*sLtFmS)bd%&Tk!%#(OMsvLc4(%exMt8 z`Ukp!7k;1{c>3yYz)ADLNZl!|eZSV-zER;(iZQ9;q)`G&odU!fy4E~VNkSTVCLvf# z3(F?-br9tef=#tB2O-!^L-~YSgJ>F|qd`k&*Xd6xGI zHD&`fW?CRcWA~=I;p6$NEx(J^VJ@22G_*bxT_PXu~{Cnm{cSO2Xb-H0~^R%5a2tpq)ZNj@|G@o5Y>wqh<<|QsUS|+X0QpsLpm;rHcWx@kBPRAMB8QZK}^r%mwIjWf|U!omy1b+nY z4$%fd`A`)K1#8l}4J#oe=GfDdpaXe?WE46d`jb}D#yUcqffJBV=@r^vXAjJsUy8P~ z@J0|VM`@Li-`XwGU=?k&ctXlfwi6Gr&>~6+whu+yIfRi=#DKpA=&Wel1(1M<2+W6Q zG!Enr>ohU}S_kA&LA82{bxsXI6Ee18J}bD|A9K}@N%Em2&Ga3twmxrU3}tkIX&YE<3G zsF_yY&S}MnQc7z)^GwtREuXAD*#VuX84lVAGFQ{wTC~B+&S|7j49t!qILyDVViR6z zS~-GHKJ!e}ai_fiuF+`gh`=@}rlBq&9o(I*TE~?Jw*&Ic)wF)pL}w!|^^T4_ILyz` zYrTk;?Lw?(cuay)VLzvR8l-lcSc;{5j7D>m?6}dK!I1_B^30a1&g@u{h@1JDDoA9S zb$l$^!061bAi3zpncRFXx0Ek^heKvQ>qAFF>yn*R&&0!le6!`IGaDvy0K~)O79I}pI;P-eeo^SFNva8vlthxU zA)%D|H}hyTI?4o1m$3b=^=oz`M5N({{6eT^v~mdUxtk zAVzZ7$Pau|Np~-5x^tGtz&AK>E=WM|euTcst5!LR?1TVmD%c!|Y<`g%Cp;)a&X=?S z*I9ugJE+fDf}S3I84X#ElcJ5LAt;@Bo7QmiS%z2eUS}03YZNq8+>$;E@fLI3_`hTFW9n3%nuLF^=l7qSa%k9hq~CrrK9cwGVt0oB9#z6}tNY z2aMyGij+_)t!JV7>_m1Pqahc3+S-(Mfwsm8jUsFia~2Svnf;0XoiOdp;N7If|>H$L>mlGOD!6V zo8UY`xgsNhzC=c2y%E*M{DX{(ES}$n1evi=M)Mdb)af7<-%Q@nA=$<}#s~-5#GC?6 zGFy<2tEqQ{C#TM0GRI#uQ$y3tdZEYlf3YMMzb(_HRf+lNu_k` zbfXGDvvP9^%wA}}+<%|{kB!%-%DYz08;V@!j9snxWiuw*-C zsH<%kY;e~ylMT_Sy_x4yr3sozs|^SWnx2g4Ap5iFG$GA$Yz99;`ku|8Vm3g_+*m4a zVY@Udp)KZX(@+OG;e0=mwnG8z89)j-(#c?KCBcSx)JV4Wa5|6$^JLt*EfxU}T$-gG zgQm=M>#-3nEZFJ-)Ol(5l`SB*m5x9;7F1>T#d5oD@@8n6S`^xZA5ORM3sp~<)pfvQdORa zRx6^E$70mdj|^(kN6K7-@>rDegp{l+H&NcST=Fc2K36x zR)eq2pzN$ZCgN9pydA%O`;=y%Kf-rB;?8^Vt3JLTzkWMChJgo8-uWti)yL^LXuoFu zXje62crmJYRvzz7JRm;1Q+xr>Pg{mGH>B5k7k4KICId=Ej006+ScJAg*6p#J5#p@Qgl{&V5FSH7`Obh?1&4 zX~*C}`)BYFR5LZ&^0tOHC{W9t?Fon1@txYjS$eogW=APEfP(d-zdy7~E3WMDf>Y242Ey_Av< zqOHpAVX;=FeMkp3*2$`VU&mm@7vF|`H`5SoBP#wEFJk+z_8U)nmnT~XZ%H{o_7~IP zL>ZXR$G-0d$DbT>5_KhN2$so-r^KvNiKiFcg2JbJqPD3fYE0CCYSeflos#o-O!TMA@TO(aQ>`0Tl+-Zt`UI{UY&F#iP}U z<7UpxaZgg0)gUx6d4S8*xQzaR8dNU?9#+TqSCb><%U$k1bP7IBeX0^+!hCwnD3|XRi7dLc<+d3DE^`wJSjR&gj#KZ zhq%QcHJ}#?9Hn}_o+7NI2zbWikQCCv@!~=^X6~^!gPNU!~$|e@CoZ_i# zEqJ$2=ShyJ8?RGjLXR}m9WeS_17t4_#k7c9ylwlCJM934@=1>0&0_xovC*S#R?|&5 zn{TBy0Yy?Zr&CNObrkia^pJ^a8f-g0is}XINgKzyk@cD8(_#&MfM&rhBb9GV1I3yn z03(Ydt~@E$L_^VS3T`8x9l7tct9ay^N54Gnl19d^eDJhb%ic{%2e;fADL%ObY--J> zt=NOp9qGa#hg79cap4t!=m1Vz<8&T7P8I5pY7~uZCbiMIQes&LmOup)c(*3-&<_fv zh;4TwZHlxCk=l-O@B@jU*`kw9YNLaP#J`5+BVS%i@z#XL8{YN;yyQ-U_~dJFpiJ%E zS#ZefSzM?5I-@9ywXK*-*vPzaT0a<+&^Go5g4%}ukSBf1h^6@e97xlk3+fT)_aHFv zEajYBZ8*)vim{oeM!kCgzFv25=C)%?BWN>Rfl=ti0=<+6!VW=8jCzyIhc$ z1pN$^jFQ?FB0caZ`7|+~e0e`;pqNCBSaK`L(H46>x@jgkpP>U`DaoCBcOk_;$|WA5 z_?Sao9f4ICTi`b0JQTvo{9^;O@JhAD!R|fJPic@DMUOtZ#$z}N^kEGfjUkhDLd&y_ z9@D_ObYsn4_pNHW!85)~$;MH^iW^nQGe)Nvmk;!04%C4`e19jMjX{q<$IIB+S{xyJ z7mCoe>-NC;CY*SS=_DN@V+~L_j8kYhskA!Cm`Z253Q*Jor_=BnTgp zZ8}(NR1MajqR9NbAUkBn&M+x^Xach6CUtSTxFty(u{df`f3?gmzFoOU&~+pSKBpmI z;v^VK9g|zTx1s`rx8y0QQcmJQY5d3XDa(+Po@c9&oVekvud|Q-ZF=8LcSbFb#Vk;l zEVx8@M=88;icJ5s3y$hbG~8=re%1ku`7L6`K5Yu*yaMiyOw|<1$^a|6J#aR+rLig1)wX;)bR40-?B}$=7BM=zVS1E6ZPp zM}sQWwk+(|2uV2PQGH>Dqd#nX#{-A#hJyEVG99lCf z%XcAC;AT~$12w<3iFZNRAHNvjseHHjNME`<9oU9UWCgs;}r z^R`7J-S`%?E90=b6<~nNq#EiEc8Kq{C$?i=6`rI}cF)?@AB9O~ z^suLShGO_@QS{amPCqxH0m?fKnC1;lyMhjw_8U^JxZ7yO1fkb4p-qoKD5kOUrNxV{ zm$%nJbAnhyZy6(*HFZt>pqR&X7wmUiu)bH9Q#bsni_G2-L9hxb$xdFEmTL(wrq^%z>E^H&v2FR2EcB2E>r$sRBNg#%EzqT+XZg5UH zr*UfIifF@P+lePQmrf~X)eZ%*(;P!f=|Rs>yorQ6p5eg8G$WVkfjd%df_pVdf!mL(85gC)c6_DP zTIxWUn@OuFZ5St3-RNgAq>XDCML2RKt)>YI76LZq3`}bCT@v9*E1$jMjwDgsk$HWD z@-5^yRDVGW7PzpTKjf0Qfer)i0lV&!ypp?kuh)>EeR8^6X~Ib8h}n$41Gx{aPcP&+qU zjk)TQ(F)_kgIK%kdh8)8`$XGO_Voi~W34vvGOwo6Vo;%1Px(QLmkyB59nKJ)lb+eb z1n8VJUx_u_|5u%tLg#h=i_Trp`99y}puSt6??K{@+(8j^h!FbzGDP2(#SQetWDnSN zmwWVm{J-iOw#2gmrgJ=+j)P{IlF4Y;l8gOBHxZ|1N#D)78@amcdadqM*L6@gDVydG z|C_SM7d6@=>GZ6)r9!79S>wA#n5>Ipi_~(X`1Yy9j~APYYA-0AV#e7brQC>K`c~A7 zD8V%d91%sj^2mTmlYl!G9?A4J>7|?8+Z|*~HQS=5NOyM9Tg)jECQd%jW9_s>zWpOI z@PbL`P%2EAG}y87y(n%-Ht5=Y9mWegjq2k@G4-Ul;grrV?(ir2yL&!y$Euvxn`w+$ zD2Y2dp!N5u&r}wge3y;#Wl0=+R(V`Iie8_KPFby^Rf@dNpfHF6Jb;Oe8eeg4NdE(xrBtM&YISvauS>9!Am#C>MtdeA3hsE8gvBL} zuEzUhf(1d~4&2PzoaDNW`AYB&^hFf3D{ZYylc&j41ls%Zs~ZbQF=f;7fbK5`YEni2>_R%A7Y^w6S@&R^CqI};;I5a1r1evEG$=ReP z?XjcNO&G!UJZS$m^E;u^hfK5CQ*DUj-xwF z%acdoO@hkvB$3S{+~{nbSq620yvIo5M~@&CnKM7YO9BQ@)bh$*fi)vA-NjB16&sJe z?dmv#YBI|^jg1Dfxe)ja9bW=_zZYk7 zy@N^KtbG?@2PKYy%z%bLX?YCISa;I#R5-uGyY2MakizW29c-^Me5ptOv-K#JG2ikdQ@n}tP4)Z0Bo#bQ$g{ow6Sd-fCvTs4YHqN8v3*6 zSJG@)pa~dV=uY@MzhylsJq4miGR{Mgh)PKhAfyQ>Ts|IKm~;EXB~3uF=%@f7T#hmD zbEHsF$%QEqSVj?FsSytiXfjiHMN2Bz2qVxiOo@=a!xPFzMzn;ClvUc+))F$pn1+UGZT5_Z$xjxNE9Gfq@j(+pRuh#G+-i)>1(`3{}TS?DdNHz0h=G znN(>~?^e!W=h~>83VcoTbycTCDCU4s`K3}%u~?sv_j}^K)W?6am->&D<5~Z4qDZbB zg(;Ta9{6^aH`1=)Mei|Nv>Jhz#YWNbN37)q@$C+|YsrG2)OO*0n7T-@<~6EQ=oXYu z0-q{7i_p<^6jfgqj<|0xQYS{RH(h+K{XL85@U%gDd!}DA&O8e`VNax&t&p~1wkar= z51y>WOIZgxWM3a+WZ<;Y^d81N0q;&K9YYQ%`wsezk@(1fR`Zl**&nHNj;iw=Jf)nW z*WUM5)s3Y!`B!8R`DEmQlO-*$z541jN*20B2col7;XFV-`l%12d4MM1L zn)>k$l}*3U*S)5Wv2KiPTx#hseO@NoWl=gn~ z%iGbTD@$ov8t*OHORq(rdsR(|#WwH(m`F`AR$Hx5CEHHKyO&SK!YwCRv9f$TQ+b<~ zuHu$AS3s1qAXj<2g5g)`Lqm;E)&O8WDkvK&;c^Ya0?KV}9Gwd-bu~UotmLv+H&Uv} z)ah0J4#m<|_{wh9%~Cyjs*!Z~t8thsXuGKgMyRx#x;PpcI-s0JhS~0FymuJeTdjzx zZCM_=svjJ-i)_oEtED9Uq)q8SMiKi@-HU8}Ji)m|#Zuo(j_&`5>4zEgTCCKsL!FWC!%T$6-`~*K+^HB&-=WZ(GJKa3N58b>L z!t)Qt^FlX|ooD=oZXUKXljDDrF_vkJC#doH?}px0`CSW5O4XHKP?KpJHEKq;vjo4(Gzk9P z==;=7E~o*M!G4L0GhGHmJ?9^Zc(g%JMmIC|55W!<9*x_RTI*$gABvLB+n> z&7&o~oAE8Bq{~>+G&9wbHt?i3ge3huW6$Xp8`N`7w^-D;#~IVz8q-m{&5LFw;5h(o zsvG>n!3xDiZ?mU}!Z7xso|1My9$a--9_)JP*rNy=6ZFNeSV5133p%|~6NFdFaePvf zgg2g5DGfW2NU@4O;6UHYF~S3Su{{FdYnT-8&GCQOK+^5`w&Hm`U-)?XA8fw6_axlbvnk)zwnRJPNPh(ahKVQEiLoeTweB4jC}) zsiM#>8f&ZfSn#1v$Qle;_<+kv2}5psyIZXBR$N!qN6-~1wSF)|lDsGXnMKv71|Xd0&to>4l|FKQ&p9_@b>iJ;`@O)=Y#ansv}bz_CV zVC5Yqv;BZySxITgO;TN7v^zYDqrq0y#^CPpR?~Wpe-O*$!SrC$&(%R0NR`S&wxjpv z@rFBUL_8A41K?F&s3H0hY_?(}k6M|s2jBK+xp*eWzt2lrc~Xrv z_AHdNu!#6<02;9k$(c~JSpR2#W%^5Cn^G9OJPGUo1lm6ne77d}1hN)~HP?`4Pi!rO z2_C}(Xc#oNHuzsB5mEOjXE16WKKClJs&$LZAVZm$uST=7o`4b)k6E`E#D z)U*V-!{ELXA${e=aacCt0aLWA0(cxvq-oKCiiElRp1=&bBf@=;xPvpYuhkIquf!dr zu>_+}PKEHZ??wdf5x4ZkUauy)JH}1omeD$Re=kylC(nVMgT=$~zyVoEt%;TwXR>Wl zsbCKlX6zUrtzD$dJvi8h<5Kx2k;75~bi|ZS`O(2XbM77sJzbM>mmvhp5l3FMn2Tj{ zK06;H-otie=VFfKA1xVDZ2tF_jQ4#GBV}q}CIZ%;7<6*BZkdIVQgS_YO zSF;k3+kJSS9$Z-1Irh709V6md#3d*>cCR~1+|icUhBvw{;f<~{^hTE$7%09^ev$B# z&n%IBRdu3Wzc@k7l18M(VM#46TTi2HS`?03;E~ZjF>_~^$*QD9v3cy%7w{bz)Uxgs z5ZvccvuFitL(Ph%nq@@IG6rjwQO%3Ob44`l`7w&gs%AwWw6e+_?^W|+@PLmpEs23B z`Empve(ewgk>VB+`69ikS$MsESm`noG(ziFDfNwn_o%7DnMcKLh9Xe$oRGoZP|bac zbmB|KuAKPr2av908JSl4LMxX^E6t>peTn-*-vGRkv_gK7c-SSMT_W$Ss=EQrt072=o=V(6XGgLF;d-9&|p} zIY7mvoz6fyeCRA-cBsUehDsRQOd}i0p&Y&!jv<$o!}4jN;(9Wlt1nEcYr%39kI1?V zR&6zQ@Z=798ZzV~<&v6Y#nZ&g$bd;$XuQ}`jSmqCEN#jY(v{LF@hoIRq7}L`jc6Y}5URDb0nD?VzX2U4-5}<>OVu4XCL8DmE!rx{H(w8WSP+4!8YnLwo)@#soT2|45Iu#vEn?Y&ovr&v>{-JS|i*yQBS9Z!A?yS z{xj<70=M!$?dq`Wdipdk9YVpQI~ty`2LvkNqajpgsueNv?kIKadDI&iR{Aw|f$&7& zb9^5|Ijm;G%lR`5@6iZ0q2Ypq9z7hUhsyLt6a)6j4X_bAy=;9S%D}<&ufcH|7BPcP zB~u=Ta;P`Kky5jhJU&BIs#ZtgF&Hv$#sC9O`G8TPRM4@642endD1LT;#s@fg?%Uw=8@=j3_EUu7$p`PS*cNn)nU2#;O}8J;<7UD_cllano-dW}wNTm zl0|zKMdD&F4rNZtVOwq04Sh9vN91>+@xdm+l>!s8^GsOoQN}T=HQ+<}sLoFLYjhp> z<`q8l1^$yE z=OM&130tj0_i5jwgi$pkPlOo&BIsVQFHa>DtNoM;c$V`B|W0nljjtrz8++1gZ8lB;`$18Qtd!$ z%-+aI4HKg!MPKw9&%WAa!Lk(}cx~dTq+o{;3UYrG_%q_8H<7Zjqx?ByeXhNHLn9a4 zvfagA!J~PRW0yGTg!Yv%k~!Hc-m}YfGagDD!9{HsVx}~KW}_uxm$!j>G>D;RsuI0j zDLKhC9xhUc6CDb@-bBNogwBl}_QcTRgt&Zq9Kpt|Wa6fmEg7rb*ftiO7@N^MHj^QK zlEiAzI#h8N1`hNWcvgd9Hp&ybopr~HP>pNp`=F{liJj{}O7a!x3rCFXIDfkp8w6Va zIrMQ#YY$RpPkQK!ka&_z{kz}y`>Vf%hH117axmg(@Ajb7PE{DiDipq(iZ>bjPaz8G z5*R~2kLHwZFa$CxVRK<+95c$$0UkpwswJ(ou&F?r&t;R!l?F{>3;Al_q?>$(WzXV2 z{X5o|Ge&#_PeKM((&QiZLEBJ93Gv_H`_E(;)Opjr_YSqwiVleowSihdV`~FCJF<%y zYSdOzj1eiKSI9&vxpXFWC^|&eTcX~gnGA<`e7ugz_r_Y50r;VOaVRP77)8O3kLcmS zK5JtptpI-b#9ICTgD8yAPEn8?A~O{sx)XCyQlf+yKuo{%ZC?kz6-uAwgO3GLu!0%| zDe3?%(O5b!hwNrBou!Y66vz4$!>gl4l;WiEieacKFs-CL&)O@F^EDdi;2O?zy>G&N zq(TsD{)twAt(^hLhfLpeRmbix2n0V8fU1yyq#E8v!d`fj)}R}(axLG7gpkN^)*m1xoF+g@ zEhqw89pdB)5^YI5x#$kc4qHFvXVzbVm`^oes%H<~oW1})wd{w#-#rAZHmzeILF#H& z)AFGgI@ZEkGgTCC;0}boLTfJVbv&F+*{|`?l*UOssNVcDi>Lv?{%J}FzO{)@iRNn! zL$Hp``9ov{13wOHLm1UcoZ5yK(h?1CyH4OSP>i^O&Sf&2^G&RL zHYDcw@4~)Tb;IWmupWc$Z^P8IZ)PGJLzlGkVS{n$z@`6sqZ?qlxZ>QFk_S$XN|Rr(ggEvFhf8R@?yteQ$ag! zJ7~uQ+k!d%xh(oUTJ#h6-kqmdkNS!)-I8`*q`1rIfD$ZjWYr3Hr<_hTIWJbftOg^B z?6=X=bBXGC6O~SDQL#;)XDb-Lr4C2@>=p?=aT8nL_>V}m24S2uDBb%;kBynikps?Y}%NqQ>j)i*K~Xe-r2<@6ju}shHvxpRXeVgMi6D7mXhJWnUev z!}@Heufrf8)BBDY`Zf94Q!ND6jn-`(S<~XWNj@$rZ5{*LfD*SHz~Q-m&Hj6+-)Qqp zGSrQZsM)I=-Z;`VkX04G-1?B;%oC_f>1uPry{E4Ln}%)f{0VzM)eST5WA*QAnvfw+ zHt^9$kP>RY5o@-gH)2PmH^QN``P%T6-3TbaJ+l^1+a)B_-+x^O6!C z5&~FIw8~GbwN`ft*bp|{B;@A07DciBwY9dj{;6$!v=-u{kOU#Y`Ur@MO4~?L?{c-` zqajcw|L>W*8dT<`9`NzsmWq7^c zrtbQe8~P&rGipB<9C`$YmZLbl#jr(-vlD3GVS5M?PI-M>#Q3#T zx%&mk_ub^s3;-w5A6vwvM+^n7fjKRLr<~tyRDND%V_la>PadA$j{}<{I9u`yu3s!M zmK~`I?}TCliqqg_veM^FxzK6mEPu`m%T6-AIFZDk7a zD=>_k49v~rf=D>q{L>Tk1L|B%FOvWC6ya0;+{RzbNR{VEBaCsgu|k}BDit-8iJ;XN z47$UbfaL_PCf6wU8Z|x=#QH^fsJxADPTEglf5>S-fLkoeIJD@M+Wgy3DcV*$ z$v#UwXe zgicgy$U zn5n)~jT0 z+P7Xf*e~$ig?*H$8dqM6x;$rxwxKaK9pq5mz1n|nqjCdk&ob*h(V1=(fTd8Nn=)w9XbmcyPO}MT52TA6&2~bp#MBvN z^u9~P#=z8nM|$*558Wn*VgvV`R6u!%Go6mkFe<#!#*+l1QQ>Q-%9W>J5zvjP9`?!W zBcW6E-jzWE^^}im38S^9JHg*RU3nXAe5^&P+s|>;UTjX;TPK&fdiLRWqva=d~(B~s;_?Y>^9k&gli;efTZfutMZKQa7u@jZu|7!1DE7oUO7V| zIK;Bgp7=RbcS#;`;Uc5kc!fwD)k2Xsw~y)g$m{Nh#53*DEZ05-R~dENW1KMAT*est zy4L2`>ChwH%gT)d`P=gcBFoMX)_xEIOk^pP_TzYXFgg>@TXwP2LCd6SI!l)v5x+m0L-4AO*J)F|_yf@@)ZT=fzUCn>xPhZ9P?(kT1waTCioEL%4+HOL$FSqvB2JI#7oQkm z8Leuy<2p&MH(YM2FSA*p(5z6n(C9{<3wv`~BS5uN-K*r6)ikOC)=ytz9&ZWxtKDw8gMRqthyLmKZU?U%8GWQYbvRcRMdmCEP`cmCmV>7uf5reJp^{i1*%#fFRTF3Ww zdP0+0%ONDI=%eu2k-bTwlMBm}STWFFb4I3V8#szA@n{=Mn^O(^TNB(+Mx=n^KFGd;j;i$+8hF>It6~8IAZ|?iSQN9lanI zh&6x`dT4Ld(;O|{q;33Os&SJ~+c+!LnC&mxU!S9G40?0+!##bnLDDu>cysvexE?u^ z{`APDVxLixj@_@*W^*?7+bg|X?tb5&V_{mIj<3;@KwoN7h!e>2q#|$$YeoAx{CD~@ zIWjsaAtNc{93?09H|>lY5zBx8nQiNX;ZfU~EkdsKo^aYWHBVh#>L5fS zyP8E}lz+5cnV$7M@7Ee}`s<23^AwFiGHT?neka?xda?BwK*7?m<+*G))2aX&S{suC z*rO+{%HU&}w?+N3y0`A)+gv5MLt3t;^^VTr|oTO5<*6k?k|5$u)iF%UCBZ*4cQRZf=rbSF=!q@b>7u0b|`hDUok% zl3(t=d7WgzA#{3QvjFyo#!XQr>6T{6Cja`H`RxwEm% zb}w^k-E9|+$axDnamlZ-N21;@+=cR9062O10GHfE$?gOqoS`A@iOKxLhT4>CF+ zJ6uFlWY4I9R)%y5SZSMmGYvsPd;DehH?ZR-KGW?Lgz(i%KNN&_*q5mSY|&JKf*B|U z4r$yX$dy84j6-};k`GyWlDTo?_PRryLbiJqfQ~p~R{|!$FyzWG2x=MOsZ^ImYYYrm z_8T8@t%qAqkg|KH>hpp$YRTj>P+C&XC)(q0$h9ASaq=-sdaEG(f?a9sCo2_aNupdH zN>ll1rcsb({4?jUbAgB}EM&?Rc#@I)ZY~oYh1BMlRjVbmAFT4oEq#Og0N6g zwu397TnTZwjcx2}wBNZE=H3pCWP!t2E{u&$QrE*sbjty`>SH*EyHGl}Qt&Sfci8j) zBLF%o7a$BCa6m!1W6*?d1QIcM?i)X6w6X~n@SCe3uTOAV$Y1d?5>=BRVwxpQDhw~C zh-yf2mcWTONvKu`M=;;+H0(b#DNZ=q3BnO4zs2E=_I3Xe6!qi{X&e-VuL;$-L6~ZG zh^a`tdHfdA%sf@cgF~8Wyl$>*hd-Ei3s;jnJZ@L$TjnNVqD6=bNf*ylvfe{+#aQX6dAOyWV3jZm5Q`X_;wWnQn|V)@4fiC)VG&U?N(Lr;$7C zUcn^OR4Y;(T2I|ya(aeCb1>AR%~Is|!V4UEKQ8Xy*7tl;Xk6=+0ex@E5zK3N*7@+KanF^5OjacorEv+ShBWpxx3>%uQ(YvGNe7Ft3Iy`@0l-h6w9uxwrrs2Q2aiL z$!O?G>CDr3gpK2!CFb{!Ea`aJTe-xz{YcoB$~@syi92lueJvDj}eCrNun5{*0i!|#j8#vwU_2`~7Jdemx1-MQLiuC|C&daQNX%{75Q z6cZ}!nqCkclUP=zn>Fdj8kS8K!?MZx)(EZS?8u)+7Je3R4Cj}F;WRl*Ru`H_^P!yj zD-$y;>lUc1R2)wE#k>Ck<;-ybAvs1?c8n#y;~1IkFWP^Mk(tB|H8RsX0?GC1Sn7MU zQePH6p|l@f#^k00dQ}+*HlqsIQ5>K(oYM4kl6a2hes`^DI*2U-CK; z{7O>fo=8_v$?{#neUehNqt5CpzrY`w8f_Li)eti$pV{;|`5Dr4%_z5FWIr-6JKbzn z_5ImH%#ix@t?3+x`ob@OVcdlIjQeHcy_FF^2xHysV_9;W`eGiyih9-nFEq+}t^uZz zVr}Jzq8w%^72rGfN!bS}J9~<{!?5C1YthT_2JY6;+JYynzw>1$>n{&nB^OH)s>9!? za!aJnhqHEZUp7)WS!;ZgHtNr2fH6E$v{X@jiQ75riRw2>h*PdD9NKbMPG9Dvq>IHb z&-lm*w#UWJjJat&P98d>TH+=HN8)~~;*8FaoEfGYh{i0y^qMJ->&hD$EG$f2JvsyBg`K#)g?3f^*bSkYV#mv`vR>7yyS2$XmR`#l>GorcS1>=w;F!;x zl+Y&26QA4fU>5k*1xamQx1Edu1Eb5~ zZigH^s>=vQ&zy;_NYKR*Mk@5cL7ZjZE6A?@3MX^T507TdHq}A9Nya)kD-54=uuD87 zhE9sS>~*4S&FG)Vs_7ctW2o~)vpjcwB&_w7=X#yvyO{X*VYCzXrHT&frf!*ZK`CiepIlw{wmQC3c!5o5A}GkO zuiv^~Dd4~>mqd7tb4?C;-jn88GUD`hX`4dzI^#3*0c>RC~HUkQ6>w z+l+0U*t<%syx1{42tzzT3HjQAe<5B9kkDzm(ZrDqu>~xsF zyNUVW6k7QgDfF{Wd%K#G4)xEmj{H!F{n^vh%sgN=t6TQ!uikq_Wq1KS=xK-D42091 zM7{S9hDx`;22BoB&cZ#=yA9hO8mIVybw{1z1=bJvZDT}S_N1aeMi`**+l+}^hp=YV zgWZ0#**jNi<~pfR-}?tc1sJ2mo8`_up=%U+84h~8gs177W>JEHS|}7XBeQ9zS&|h> zGLp=7*(4No-jO`1BqOKO!Il!~dT&*w)|5kbb*6wd0fq_84@A|LcK~HJXHgI*0iALM zQO-<1hNF}q_e>_^QvbB%l01FySw)A#@5KHg`Df>fDE$yY@?mqs?G~85fW-@j&K641Uhz0p0oh7jvTA9xglvnZ$S!?C3v> zK!8Id%;DWgH<%>_aBJWd{?4LIqSwjevlgG4EGkETPM6UydP8O>(~-464l8MGhAWgq zcbT&@is+N2VYV^ib<5qvsOZBH|8|Qg*UQ!Cu9<-@qX;ChU&~l~x6;&w*Z=z-` z57-ki-cPPcM{QjmpjwxmCKDy-YLh?sj3m!Mxfd;I_#*0O&S&6Js=6VSbGh)@+J@Qg zq8?mMfv53_EMD}NDD?IA>DKrdg7@a~@ibf6(erx%!&|z)VYz1tIhUS}=TE{@#&+hE9pM zQ=aL)022HnT0X!dxI7$l^M~h0i&rKu_q(m+5})??eR|vJOf0#8^whKW5&TwiNnpm+ z(Lj^5`x>pZGjR|0d{zJcQ=ADM{bQ!kHs+>paRb&|E0hk)@kgini@L%o1Jk^=#~f#W zAUV3pK|9q16!w7qrzvfD5LmR_zup}>d(#@K%Xyij$Mp>RlYE#{>vr_#Y>O@p#(v4C zoUG&<-J5)bW$n#C;>URw{BmYp&g&ewzbD+Z@sBTp2o`%7Amkpfzr%sgh0zk<2}-pb zzf^(Iy;-U;Z?6-Bo(=^6jSC2TCL6!EE z)_!2#+X4)k(6fZ0Jl4op(SCNyeCeBh$CnG6gY85;*kQa*eR z9I(Kac&SwsqL`LIO-RJMh~)zQMDy~O#azkCx3kph$X+}zHwhq=b%(D2wU4lbR>fb#Q{SeztTU#t~~<}h_qrh_k*&?&E`7Uxa3%diqRf_&8>Dm<~kR6sn5?y zH>{jnvKAk7B)1OjcRd=DwL)HIuriC*rhc}znXW8pd>n+zsgs0yCC6=>2IVrL#gtDshuPW zA}6Q$m?(;tk296h|KOVk|2k=%sB!EG>roInY8iCq>s})H>$f&jZ8V?(Sevg67@b^3~0A(DPg^JPl5f59O>3npWVI0pBq~l+Mvip?19+veMHH?M=}ssu!wgoHeXkkLvZAL&{^c!i9l5z@^x zY&Z!4PLYu>K|=IgoJ53`B6h_`sMu8G0su8W{5s=;SVfMZR8VObP+fsSL8vpqiih)I zp`ipHK1w@6#jy|^2&Mnx*jif1vNJ1wIHV-m1B0i*s~8~jQN@V6%vG|TH1?0~4BZ;% z7Ff`Pt}}nQ5Slx<`^Sm%KfeoinRg5SGPru$ENtGeNGJ9aLop#7QmkuS+cq5&}P^trEwwa*A?*?v__ZGLe_%9wu&XwZ=shYaP=x&@y)Aw-F<^ z2V2G-+>Ia{jaHJp*cvpCK+Lg0aDxi>UM+gK9cP7IEM9L)34L(>BK zGtWtN6bPDkdbgEkWx0q>H^s$KCdVUFJ=%Rll8!-XE|D3(5ep@)QT%6d!2)GtdWvy@ z)_8>2uI5_=82@mGaE)1hquyV;avr89O=FgD)E=6C^T2faFp#{w(5Uz7D+^o<)I5Qa zkz~}=asPN@X_K&O;}a^(uxdU-Dr=VhGn#kv*Q^K>HOu0);vDpG=64qp>TbJEUz*3x`Iv5T*aQk|-C>`)Kz~m0qPZQa%{X zh?@6wXyj={TcIn==3I&tHOSxal%kyQf0<2EoNJ3AE?IKi@@rT^CAPffHx^;pnk<$> zr^Mt=8*0`uUFy{%%5slD>fs16Bm7Hk1B46vXgN9eDw3c3 zMj?`Bx{OUyz1DP{RCRw);TalFPfThm6|TfNT#9V3XuFyl=k&HC;kQnJmK>_eF%<-Qirl-scK`6(SKE!LD+DgnI1pN13y%2#Iw- z0Kzg3lErCFuEJU2rZveG0w@URr?4WAp)&)pwB(9H?qJw>2aNOa3V&1kvSg#Y+N|)2 z)A44hQ6Oh(O;@9UkU=mG;LPnj5Jr_T%4tpN(cT|KRv4WtmLr9lro$LexuL)oB6>lX zqxH_;Y4WMCbFJx{Ohk!`miVm8UZnuxSgAz5lHVRX2ay8=o33HbcAbdz&L>f(&Y-4a zj`ax2H10pSlp1ayHRl;yMLqSdhAv~Qw)&ewqK*1b$5GGg^1=oZ!ATwOCK-?Z2+Zv< zSRebfritXzH;ch8Oj4fj&^IeJQ;2jqTuKor%~B#qi2-)mAef&H0rNL{V-U;^^)U>L zyaZr2O9{6EbF@Qazaq(abQejn9}#R_wTB?4@V3thcD(Ds?tQe?q6{=+A%Qf+WZGfv zPGjbiMt0*n)m^I+tlW51Mk;oR6jSEda$lwBab=?XHMu2rt^z3EP|wL|gAs+B#u90J zMJV=-!l4z1ON2rEG5p^hck^w1GH4CF)MPdufB$MdPC!6X_3)fM~akmPUO*pI-7`I zHV|T>P=K=>*tV}VwWU+vJNn2AnsWEGK8W+@-pwtkOiaX$)xz3+SRng^XEFT{*;{(D zl3HY!j+}hblyZy+L~swwPBw#5`~;-r7y`2O%s{=9UUzMTLkL$WP09FDs?Lu;ktBPb zi1#T|%Ka;@Q1fuVvT9?a%J!H$dceSt(mMQ!nt=Yk64vf1dVRVpe6hGAsl+XycGpeJ zGkc-{$^=l|>7;mq81#vKoZ9jVh>d`-N1Ns8sQ%sMqH2(vV7O!G==ZBPB%Ie3Qo=Gp zJ3mjBzT1T$j4`@?C&v}%*rOZnR0|^)+G;p#omAu3uIOZqC>M`xDG!2S1vdy_cf$RM z@3#*8jL1|LrpJCqREjWA8Wa~0NM8aM(H`Gwd?I%OnkA2!nxe!5l}m&Jas|mHA%W|VUY&*1Z3G9dUb`!z#B?!}ShrBuE zi`B$HC*MBoxZQ;UVu7BC#-7uv9?r>7>sr6ORu0?Go3WUa_H>S|7~}XsRl8BX*uFs& z{-YJj_D{j8Jm5z4nTjR((7vEi2dt+!DWMYvyP&T;&)t>@ZrsJAK%UbfDyu=(L{Fpw zR^Oy{1X|-fTH1QI7|F@?j8*_N)@OD>87&4MrjQipqxWA`qh4W zqLLY!wyW1Hw3&w-$!1jBH|lnCMAo*Z_AR-4Z8Z0SE|WHXI+_1re7}CcY*jO>O}2A4 z%~Cr&Sc5Nl%?CszOas1ZJ|nq`4slHJik)P<*3cQ>qWMA|2187p3lR-B1c zkn=p3{?9ea_82`s)^FHz0F78#cift*Y?oQKFL8RKHOi``x5*ie%Z!MK9rmv0`1l4w z>)qjrk~h-Nhlr$=a`JP)Y>|_nqo+Rhx#r!1D(AAr4esJqU7iMMesD@zZ{3IXCMOX% zeF}V12m#(KUga)sP&qy$#epS-Vz2T?)hTrtWxL5ccQ+IoSY^z8zT+^4)}2KR7@S2u z@mKc=@3ySiv&0BgC~!N>6)zf9yXi_(J<)95qtt?sAGz3r`PsI?fx+LyOrQ$vbHoi% z6*WyM>*ge5#h##ExB7Ee=s+9IcFD25xndu8npR6Eg)WxQJ=*3#MaSN;?ts&X4+op) zfr+YvdH4la{oc6gR464{=}~Wi zZNXtYuav-D1|M*Jo~-@GGS5KOJ|9 zV#C0?=Y@!!mNpAT$d>M~^$<6#qc?n(FjSmljr*=ln^!(l)8;c1g@wraI#*CvD=kQ) zz8i5|gmI=gXZunz_Lc9^SL%kfk6|%qWt+jQNhRs0&(4U+QSXqPmrBl(bSx}l2V{i1 zt%by>_ub@$3a#-k#G2^!x^crQn;tQhF#2&`bLo#ogvlRZO9+kl+0B{D)6JVQcz3eP zI51(q@tSpCJLl+P+cDuaV}ERoKpO1;;^<1~UaXfwKQO*N#;FI5lp`4 z3H};Aa#ZG;RFbJxcK(6F#o=|;F$Ew#t^<^Fx`WKnOf{&|hnKQ@7IIgW{#ww$WaHhM zqb3{F?pHl4iNHTzpDrBUFHx@bs2-Q&vut{u&KJKS%D8CY%FyuKBgUuhnAB_q%K@NZ zc?Rx{Fy1O7e-apdNuBpLj?Dk%INp2L|1tlM68RZ^Q0kR&PHdE{QNN_8=gK1}J|?6e zeiJa~2Ke!c>o=N&F3rM}Rk}Bm(-4sX67BjAcy=f1{a@zamB=qxT8b`i`UTk4$Wfb5 z-gyzM#wU<^#6b#g2med>BFvICLp>t18~DZ6=t20-sj;*k-@#Pm=Qq!(SD5gSdhd4X z&E|^nAf6p;KL+s}k^kyr@Pw+qj2=WipzutzODOd?bhhSyneRu5e9Hb8`^P210G|D) zVgS2Dr63HCMtbnIg2Cc|Xi~RE%~m(RoMK1yyCfu&KfdEcx9>R2ksYkF6SZn-rYT28 zB)*v*)$fj%W_}JjH~%*bP<_YCh|%U?nfacmzUDZEwv8w>HeTq>`NDP_iFim)eOb>w zl<0~7Wqy%{$(k`pVKNfx#M-Gv&3o2v(H>+(ho*=z?oS}#V`p%aC z@{R!HJ?`+t0iFFNfHpIL^vM5dq@F+8i>w&aua`a?{ejbm`milMrV4y5snc54rEeQ7{*r_oGFG{==q*FfRJr~(nCl-Savc#`)-xp6+Akyx#unAxNyA_fnPIha zcwy-23f>q=AA!|FD&42j{l`gqZ zSLM3Mft4USDPRRihh1hEx<}qqV3@@62>P0n zD5&_1&w5rBayf-=94sUe@^6r+24#-_up+&fpejnLmH9v9mtBaO%ZdEV{~_|)y+2K) z&y{T|nGTq9eZo-xBu#o<+oZgii3N1ycAn;0eo#|PM-#=jVw~lG4 zI@q{<`I*{=k2{W}>Myq&A4hLXYVo#K9gIKxQ|Y$li&rCByi+504!GEL9I&?;hh=jt zoCvNz0Rk4GE_#EgViR{o=2$(8W$r~WW2b$)kR5`F5^tbxHmkgBhyfARZS$2&KMbi6fC`541wJLuE;$4oYd^(#AQGmF( zf<|LRYNo%u);+?=2Sw{eVnBf${WFv@Kvt&DYaB_2ogphwHrQo5v)oIz8Zd*6bU8|4|GY>H%A|L*~+V{P09a&mIvvd;WejYqaj zc@Pn#iFQ%KV}%4&o{JL*azZHe-=Zie1E?bF`%J9i1+`HLk~#7(Y6vMCtx^F*qvTX7 zwhN_rLgM9KGnf@v6OO@VjcDKHsA>c@U~6HlK7cI>NvdWr2$&TT98&uMr#p=8Cl?U5jMku6Q>-hcFwYuYzDy39t-HUpKOk4u7nU;O=*BF@(=;Y{$!5 ze*~{FrzGm3Q>`ne@&1%;1#|jsFImo{A!2vt9qiM%oOK2bQOcDn=~`u)Mt6&p?-vdr z4LUjnACndh?@u)cVme42?a*S-FSNSvABp;9z z1U`0HAAn3`h>vz`GLVOLEFZmeq=U(&$6)d&d{vzYlau}rnB32R4##9UkmH!JB^t6L zVk!(>AAXdWy^0E&za>;~`9BmD>@yQbRdi!lnNW^0P^Tj6F=hbsx6!eddX- zy8FOb1Zl>42OD-&hJyXJUkLKG276G0^d_x8qFky2pb zV*CB81igp%D)c^}<1!6MY)OT{MlUjkwxLdpKfMw#dU)ap(tc8vy45MQM}PJS=J-H3 zGphgBliX<&q=hB{wCD;o8VCuJ#Z-SKelGD;uq~X4Dk2jEEi}EVBsz$}Tm#%LqQ_C< za^;l3XI4a5MNm`(qxEInYkIIAsGUCOb1r!~K))tsE(*f?hvzg!i>Rw~Vr;k#6;n3o|$JZHjigS~Fu(&^3J6~)T zDIUjdu=p8di>32Nbw$`&H2sEOHBk}UgatC1ulF8hIUG_>cR_W+r-knXLVjxsCA)A2 zi#GTl{Fzc;dHX5aYPmGe_y?wxm!h2KL$61zHAZz}?9Y4)50V~bRbd3z+KMPMrUEoQ zoE!|jZr*x5`l6s&lf}JIu9=b-M~oA;b2k z91@OiM;?+{%%T?6H#i}$)g?LT4hVaxOysEk{9vZH;**{pvwrU6lbioDoP6&M<{Ovn z)FSz6$;bTK8p?KZoh50i%C8T}HQRxf0UOb*iK<<4KmkX&o@tp*$5{(6cYw-kU!|%s zYh>WXs;v_Dbi^j?yscUil!CCr6E*h%jl_WQJwIL&38mvAkso{}$^t*#;K>!b${7b<}S;*eH%N1|PthlPv zT07Ng$X051RGeM=i7AsSBdoB}lEOq~zb8etq>Pq4_La}2CB+7Md9PuC^wHb3*7~`E z^bLO<9Ct@1x+SZW=cj4D)_6S~3f!n(C)f%#{EI7h1iX-gqg}CnLC@jQv2i|msVWd% ztF$mIlW`if z*32(~_2EBYPbGDrW7yDI?E{A#|?4W{Fn9U zH|#sWFf#wupdtdxpjxlW#1gu2KwGENW;xKB+XEy~t_==byab@F2S*fokME;}M7uUP zKtoF1IHJ@O!%ML#9~_Dyr7j#%>Q1NBoAZ6jzsgv7Kzs5FwQ?^ABbLdXwdWDKn!_~z z+TAR1+T>Sjg$Qr;X_I;REA6}cYDa66f1Atc`qFXMBL}7P0t_6+XmSOB12!{{G_3EO zlSEm6oOeFb7ICnqUQH+y>kSqIYu{yxK+1alx@fl;cN9?am~!fw1I{C@4Nh*o4YdBc z2pIlwkCx5vRWI}ZhTX`=AS$)U+s9X7AaK<_{_|$TY@RQe&F=zpF>4IJyZHYig$_$I z3#pYb?>U^;(kL{jr4{o3Hawav_zSiCB%MMSDeO=cq?K`cm^QbUCM@Fg@x1AUeu5cU z&e7sk^5%pfI~rukPs0RH{#^AQ0V(013x<9L<@&;Oy(^#(EDJx(sU*bKCUZbd2whREt5^nVKzqJUly4XafPFBWid4i-enbbF{xiRU`l%hu^%*e7D8_PT*-IefW*OEn^6?sbyzs?Pfc5B4!hsDczm_hU)I8 zjxrmiAr@vc*vWtS$1sk-X}z_Sepk$9>0k{pG4qDg46YhJhvD?byPRIqZ|FT>mhFaN zU_hb9Z^`?^KwFRTZI<;OWj2GIJcI${k0`W!SRr9HgFQN=)W0DNHB@oFcDYjuP5uzJ zvEz<;(6|}&8y(ulo{pHG`M{m&^LXxRf!@nBg{tL!8AZw3tQ>&aq=#dO0lDALX({I0N!mnf&-rY5$)Sx_d1LREM^xEe19SGD7P zUN43(P{bkuw=>HCMByp{#INwM1-xRC1u-chTbLXr;bZynoBj=+Ty^kio-9Xk_GxQTB%sqRWa%jnEplWG?bSst^xtzD925UJtW)! z9iB1M-mjjTdZqzpA?D4Q>bZ>8*;2nBxLkGXhX{RR87)0sZDn09A|tlpED+P6%l6mjF6Kv!!X;hFN)0{W^i6WR~kC z~H>A-YuA*DDEC6`C42}2-d%f<$a)v>sbsxhiBP3Y{zt7GXs#`Vb!n5|s?{VJ!S5fn zDSX0}H?TVx8L9o_C;5&>j{k}p7^E9ez7L zxPyG@k-s{8>0asdkz2nYlXq}MmEjpC?ELEQCuS!lGOR#hpnhi1 zP(TGy{lOCgO8XK(kBHdJM5NzG+;d zCSK1_=CnJpX?#(?VRwAfs3;;XUs(@AKSMdwdwe75nR8z>t9pbp4G#MdiR`8kg`ON% zNI28r7!N6R(TGw%7+wm_G&rC`N`0|sID%!vOTnB5M{h`}t`Vg)r_`JC{YqxMT3&I~ zCU2>oBwWMcNN?4OAb6{n&1G$X&=R=KuG%q#X86VH-Z<-W1ouIfa~XZuX})X$MYuENJvk&Ko>#f?L{3u}CG}LvF0fF`CT?Lr)$nARdWw;-Uw5isw3RH& zkg5czNS+JSyLRA#3^f5fBVPpd;~4o@ZR=0YlQzAmp1m_x^cZi%vw@$Z4sZoqIp3_EJw``yks1uojF5rRd*JRtf;c=M$nhn9KJ6s>(ogS*~<- z#Mu)_PaI$zZu7Go+`}ej*mCe-iEx8&Z9lr`sh8njx)ExZJ|txAl&jql5V;+ z`^`Apbu5f-8M+Vu2p%TjM9dRF!Kgklg(e(lMM<~3Ujpcn5r9fhEHbBCn|GfWqeUYC zRYvvP6JoUVO8^DpfTC-aH3NqUX61CwvW^AD`DwZ}2~eC)4DBQ0eb&!t^w1ufMZ=B- z0Rf>5x87qA=|<6u%fddas~e930+Z^fUU@7SYV=#b00@})hk#I+oC1K@r(dvs&Dxh( zU5-_HesHN!>~FRyid9NagegbwnF?vCB`iU%#@s#DC9e+S6JUM>Kh*J9SQmlK5>_*g;GNM$KQz~i-je(<4wM&WSipoZm z-JY29@$E*8Z)dNe#M0eNI%VgfdPdQhi1KSklzQ7K<&cl`$^srS-=)erqQ0V)MI%bB zNYvFMY+I!NGjWKmP5w)5C1KrJYj@X9;iCrW|ApFobTGBKd@g}$`gPI4Xw}ball6yK z-fB-F4o5AMyG7TlKTOn8zx52#sk0Er?n34viz$-7ITbMSa=j=j7QA3|!OXRdtj_15 zLRg@S4w=~_FAtyhin=<*7f%(ZUB|+>Ky3+FAZ70Whv!k`X+Cp?->B-HGHp7~#Z0R% znvt&Ek83-9MX$@?ZL&jJqqFb0s@x}Xegqv*H-vt4b)9dDe@jP^BP;FW=gDf(+a%f> zQHadv?hM(lvOwZH>00AsK;b@S*Hmugp~{)+XmqA#^1++n?yjlX5(=GmyHD;*P2idE zP_13(L~pk5a0*<84@gyVvygDMCi7h-{{c(3!WNBCxsa z;R&A;N5r0>GRQvM38*RrtIg3ni`C-6indwAVPy(7xkAvwKB25WcwQHIX$)?w%ujT|86g>}nIgY~O1D%)e7#;}=Hy=rF?VDA)X(ickrHDu493?KpElp7y6IKH1Gi<1KbCgBy)^nP;R5v)pmJkYO7C?EL=G@;Kr+-76+!4n4tw+K@7svTm zyN#+noDm?piUv9(%bNUE>4e>mhPbRZE;|dGOPr;}c^lnt{W6QpRePMw--Wwf^)C2b z>$So6Jecr8cU;;p@y2~ON0&QP3iDV+ixc87=c)I6T_|zJCb6)1iJdM_9AmM7g#}l> zu&~G&w6H)2YRLuO(NKxLJ;oMu#0SVj#h9wQrQWRA?|wNJKE z6jriO46!D`azUQZ{Kdu6-m4wd=ma`9MUqc(Lg+gBix9%(Gmh!@MWsB%IgG z4CIPGk{TZ`IMn#faa{E3=uI-PxT(&{vU-pyah8z36VegO5VTbfh+pMAYkD;)Sdcb} zT~wadCEW*-0se;Lqe}l zk9x!cN})V06O?bkD6Kq$2ctUPPZG{{F_GAFSacY-mj%i4biB-B5BuYT^>VzQZkA^l z#VyIa4@AiHv=EmE%A`{R2+Ka8KzqE0xbz%ekd|`NpQ@~wtau(R+5ebiR!Zn1AE*_p^2c<>jHk9*tq#|)gf@3TIDb2_9o@M`pU_kQKOTJ9<{Z#T* zy{z&PC06s9PQLW1xG&FM@k=Sm>)eoawz1Je*Q#tAz0??+3Nnvi8CN~IK}qAOUn1^%hKTvf$(T^9&eEK z81vGd01njWrMr3KeT~7)ZI|K|rShiFYQT|1*C?CrXu%qD9yZfnqgJMGz`fJ`38q=| zilZ!Jm|$*ZaB)2L$`WLFZDzmBQh0JkzS_z{@;>9GsruHW=(K?)M%58x$0Q`UqK-OS zX7-XUPkqo;f$v{GpBeo6csDRm_k5d-lM-LA7Z)hFEPydfZ`?d9bNWrejK%a9-h@GX zlxlYYD@D+(&$#IgmC|X{6fyx0ub9{sDI_Z$%N_AtZ|LOw?Msa6mN6yzp=IHJO-+&9 z_8UWM!|gL~g?0+({U5YR4O`}IRGfF8sb|99&EICrUo(rp?yb>MZ$C5ITeMYMEw)%} zc_#AYhAVsuv$EmP{OVa%A#cN>IsAt2Y*^t^fyMe(4^!WJ$JN@#GGQhj47V@2pnOgh zZ*P>Px=+Y0`YVkcs{n>qGJpX#fC7~OZg~As{i^rB2C|0en zKw8TEoWR^h)}kYKXszQThsT6cTKv(VyWIYeXyx4HlBz38uL%2iy0i6Wv>sxVc8T;_ zXw)Uro8j?o{fwp6JqwtYH3!BRTP1leuPmP*{u-J-XN@cB*2=pf#SH6x1bd+^ql;c@ z5>L|hXF- z>7Q~OkcLi@wP%9*^gwQiRX7HdnE-WDccOW6odSxJbnr%`K{D-}?fV|DNYIu8pv-H79?n=j|@G@fWALKV>N>txwm)5168 zm2IrKi%`BiQPXJFojx#d^C5JGYFmE52o?I>pSWM=Nn>rs>rAWE@NQ$xL*$PJ?w1-M zT6Hz4bAoF38Wq=pNU+?`xg6`Q`>^{Bwz}GkH+Z!vsQ0Ia_sPgmlwIX5)W)F5B(ct7 z$&&#(0?Nh#n(lb~r`;b?$gOUAR;=5`n$@p1mU|p_h|Rzkw*7$D(N~-_ncx6>mCNaKS$8|)03)me zYK5DtavmIA`y)26QT@mK?b0Pd;9LFwCNiG%3zDq&heSLn5w8=$@Qb(vIvqp_rhh%n z!BlH3B>|F%>OGPq1ir`S3Er}k$!q= z9RA1DZRkDmbn(!n>d#4}?@;M4#?yBs(l1V=KdI8Y-=or>kEh>5I_;Mg z#uZ5M75I9mvp(lMsP`fpL!EU=HTJ+Xl%AS@S>*VkN#H1IDTKylnydS z1E1B!GjOF3Mk;7pD_^AhxW_D%AVYa&fZuYjF!%};grmzw`AayuN{)lei-Vgj-3Pej zqu}~a5y;1YOB=dC#5^*!)XqG1h}Fru@H$1@#Y0w$XTK_wXW3(Mu35^hC!|=Z?CaD( z=Q$oRST_^A*6}ZG;gk35gMVxF^N!P~$l=VTsrI=1K6`9%29FeaBXxNLnYAf1n)N74dl@4OI@L}k!#CKO;1~e0GL7al=}3#4~UcROI0@9UoSB0 z3-dpma%*NC?s0f=s-i&enqDSZU_AKY`#^$z6?{s95Y2$yW0n_8sn1vuaHQA@)8m)4 z7~^N}lhEG@Ij-o9gKS5Mc}Ze$X-H6n5a%vWo67b9*h~DQ>gyKSd z2X-Jof`hdgdUXb8U_2eC5Y6BiPk;k3z%mo_@vUy*DnQ&*st^JTOsV&*7@MFn>vITT zzo7FsLZWX_!?eTskoau`*^FiiR4%4%=FJr*MrGKC52#27oF<>Y9Upg z;R`A{y3_d*u-_vX2b+F%>{`Bn$|Q}|5RA>{&m1d^j;&$Kg^$Lk>)QJ=Wqa^2e^H95 zKFlE>caX+yOX5AFslZhX;SZVvOX{=%+hfQTPI*Q-&SoyStbdhCzM3R5YK`i-v%|qQAy7?umW@u06bEZ3Ak&IJM&%OG zal5U}?0Ld#UmrPqW9`ZM{*tylDY9XweNN=??GkfSTYfyoA30oCJ5Jw!N85!?jMYG$ z_63o{?MrhahhM1W?ScDFsX$C_V^hlEPUP^eTEE_TahnhpFs(bt-&&qr42G*fy0UnJ zwt6`MO#5)j>w;;E4=`HcX*-)Djo3qr@8sAlm4{f=YA$=U%5XA4>l^^azldni3?W+Xruu6~$V~EO5wn>t( zP$g&tBZtq@R*xmIEmsmQR|&H4+l4APUV`VV;Q10fM+Jou#C9{>>Wg>I5`8zBp!Gc3 z8tbV=!YQ|<#A=;s?d9P*kM%wT&z2M7f4Ty7MuB$M6(lot;(YCy#Q+eZFFH%+PTwOC z{li(IHz@T~)s5DZInhc{RQ`=CT zHCr6@ml`!Z;#i$^rM#!HQC!i~WXty~@dCTPT8Mz*L$65k@s}e+v@=6r$`e9c+9&)Gq2d2yj)SW*K zMYC;%C+6>zdzM-w%eP2y2}#Y`a*`^z4P8t*Q#*ganudjqd8<0x!}~Xc=5l}N-ioT; z#{}nPJ@xHn&DmPDZxql`pnQMU3FU$ zUV>8xRFL--dg76GS5^3Vm}^B*SKUvN%Xur4E|gbl7o!Ht<*8Dyu;|v(thwSnnBO`4 z2DpvtTTvq3fj10G7^2GOoqR?cvmz8?1-P|PP(c{bqA7F@ zJ;IwHF8ady-DOVxY2=rVdS(_Stl4uRu*R$>2tOmbPHT1_{axm2crHuEe9q-p&e58F zPYCzRSyB1jcwg4t{PGaXXdW8z7-d<4MJrKeW7b3b7-bmen)hX`A&h2Ln~BfN0BQHB zv~)tEoH5EW1f)#Yt}+%&mie+wK1lGjHfH^t5Rc@Il1LcGdJl9|mFbQ=mnF{TJ>k&} zRhgnNvwch8^wW}{x2nt}oVm)cze3+SU8m_uu}?&PKz&Q0L@)8_lTSJ-!15kI&-Jtm zg8uZk(pxhBprJ}=$ax!;HVO%S_fn_({z6G0_yvNsMnxK1c^*Rmex$#DR%>bT;*R%I zlNt7j2PCpo-hSN7ci`aGOd>*G=g4o8HJ75rUl^TBJuRc`ad6@%ec~>CuLg0rds;?W z1!QQcaN7yWJh(L|rO%|f8Ln`e6%YWyKk&#zPs_X{J5IF???%X_HC{`HS|48`Ad;<^ z`t`)rz8TyB;SXv}#Hv@{5lcn)%A&~}4j_m~MNvJx-0T>}PE!lBtY-~GijVF5zG6*l{u|g9&#FCDw_qzhYVB1y zVp~aQ>2!Kkw^DWSdnwyX*1Q|zYhHezEOtVK_Q_6IsJ3G-Pyg&}lkJ)P-x3{KVUJe7 z;ds)ik~CdKT_;)3lJ8;(WfHP_i&>!kLH#B7zOb?afXe%{-p3s37=^f zw_PNeE^bqc*adB}fZ1Ow9vku$j|z(qMQ=k<`Sj|7&{@S=?diqI;c>`_V-u_QTT^IJ ziuEsktSvQaYmgF4hISGwTCDG1I2CD|3RGFuzKx=xVN2#iYE^rfd>mcLy{xXm70sFf zEKbMagi5!ew|lIIK2{8?t1L@IhOV;g75wmQDjub4&kh=4Y)c8wJiWxI;ti*YuWT0C zEeK0e{u}7m>ZEgS-Wh)kMVt9X%Y7-rfKe!BhW`f1d)R1h2%g#1B>XVQ|1NaZ{J_AB zvdr)(^rDZ#QuU6=%FiS_nUjsOJoW_**oLwa{S7sRAJ)w26#Rvf!V`Q`R=}cVC}mbX zBLb1Nb*95&zLnt6GMrZX0os>JE^k+PCMhnXJWHYeRUXLoa>%7s$-A#)I1e?UI()r= zwLLr*-n){=USzZpsVF>-fGp`3vE<6{g>0bc$N`56BcDX{{Sl)^-aRRBhqN92`ixBX zj{3lk`V0V9=-Z~pq zP?V(>E%#cx|1B+=vLb!O?Yy(@SM+X$ikRrU+&#;!zr#~C9-bv0{X$EPTif90;hM&s z;goHuE;~ibs>~j=5@EbyQYK#b+1yM2Lpl`YDJKBiEk-3$XL^kIMolbT{BBFRyPIe$Z{Cf3g zYcslYQ1qe|VwaiU*Xm1(E^|i?WiIs?M{w-3J&ejDDHCxJPYHGJZ1Y@rvW_iPHawiC zHmWalulybRBYO-_E_t-3TNog-j3X?wD%1Ro%t zGwon4lkYwBL=9Vh_0#`P+q=g{Rh$pp+2jxwTs<3Iah0g6u9`@!Nt@Qh#JWkdNuUIx z5N=Xy`$MXg`lEK2i%mkpNk|TdqgZd%-do$B)mpW-3SMFYl8tw63bwS3ih9-sjY_!{ z$@_ig>?Ww~``7#Wk?fqgJoC&m&&)jY%rnoZ!PoH#VE!Cl3%kL*i;o$AXEiYOze6p= z$DHu{GCAEI{)o1e#+1O4ZM&hFn%P7)AG$7)*2-}81H&{K+JP00&UW~p}0LUju!3T;5S=~ z;$!8dcE;KM4UA3+BR{mg2vK{sWO&vCU2k%jka+WqqzFt9M+&)D*GWLsA1`YkmUio14?+o7jO771y;I&Ui&oqaXns6Fi~x(FRk{C?Vd7Ke=HqwXhD2j|4Nw~SENqi@ztkgB5gk;fA#4vb+1;lW;M@V z#UB&N?pMTDerf3#WZKju!}${CMq*^anCRtL6{`xlmkQHkV1%9KTw?(nZtOLC%~jhe ziGcfqH{6LO#TJdvFTLr0?&33bEi!}g=4HHVy&~71;z5S*=v^)@tpd)GQh1j@cSk^I zy4w9gGR(;J*&`usBt%E2Wqs!<$|Irue0uUlX0-jTh^pxwjV#MnYpF04!y+@4GoHN_ zSb*3il1%@}qKH|CbEyKOcU%a%3z4Qp<{kFvU1x*Sx(k5dtR#oI=?Phs?MTSk$ti+4 zw&b})S1F*{h~>F?dOV-QkjG{=L5oNEGrKCOgk$7j-{2UtOPtp za>hdQ_OAE&kjO*)%J&ezEVie{U+wNvzV~+$vF<{l(A8i16onq+-i|pIJWoZXGBNEJ z=~$Ht51@C+sXbYOoI@%?628Rjn&ZY+m|gP;{r^YUyb;0%MhV*!onUrF1cRQYQ_Q<+ z6fR9Cns*7Y^~ah{GVhw|hE6l@5;h}lV&9wD=3O)S;E@7Ptk`1by(Rss+l2Nv)$^5y z<--5cliLrUDZgX-4rZsac|J~6W#1vpZ+A%_I`3c0e0_(ge(WxJgvI$g5&C0y%^+OT z%bW0QqB^?f@fC`shU`1GtDFOp^HFlPJuMMg%i#ivL(0D8Ik)6M%c)G4U7PtbHiY`# z93venUy;;XZ7r2qG2NKX3u2E&E9=d!XNhMk;cZV`O|z04j>tUa&XTx<7fX)TGG;oN z<)ii>}0KL1RbZkWOR6%eX)z|s(>0ytfT>FHL@2l1LoM( zRnxocDpyxc>#ns}Q!N_ulZCVr@%>gK;q{jv(CTz@{2mQE1gp=$12yJyrK(ngq z6LlfloMqO9+m?S}I6h8&v+kcprA%JxQ_JENA;xF>bn<%nI5C^;@br*J9v5PRJUx_6 zTsi}b10Q~#{HY6>8;s}u=Ijs=s6UJW8X#c~gH>YN%N`QjmYCTPfgBd zdK7JdTIT3JrbH!c@+&(h%xvh*%*wXI6$&}HlLZW+t@sg^I<=G)NIx-U%7$B(Ct1>l zzo2@%b3fln(ec>JhK+YGTfL@I)~0Ue*tP}yW6~ez9Cs1B+?quq)fC#sK-asoz2N9X%0-(ftV`n3D9+I@>>@L3UCTSrV-e>^bW49L3<0h#y2zynF!-Hr#?j^_ggCv9xU z<=BRGN)#iWnCMsTBZP2pyt58V63E&q<2N(bq|4TlAuW@1tnB5(xtW}<{E#A~R7N?@ zPY9*~dt-U5!57t&E5ydpX(Ne<-G2k6v_faYLY%z~iM-SpJKh*N(>H&USWUeB0p_LI}AWHxOaTkO!9x`7t z4|xtPG_~=36!RihLy*rwf6ldP)LY^25$j)TGI=wDtPh&{S(ynLRW6&sKHl_h`?uc#LPrnf|&^ zK3@57wsQalIDIa9(+i#7@y*!ID4OAZ zcS9k2iF>@Vmzcd)>3;r<>B-gYPl~;lJncHVmtdYyYPlsR+D+KCh>@J*LvKZg1?lOa zdC)xEcks-T4Q3O^Zr*eAY0H>OKsfavK`y`21314xPDEqb$;Kx?@hL3;`*Q|~e>o=? zZLdML6v9Ir#%t`|eZq-R;*8$5RI9icGCJGime+c<4vb6V!L8SWn&i1;@KQvjS*3Xr`aSZyIfkV zNj)Y)@S|d~6RlUdmq#r{ACzgg+()-sE%{hN2Co0;4CvrrXvHqRU}4|OY=rh3M?Fh4 z&;G&>tI;k8n*ZK+XuN&-u=%oa__C!pm2A}?^Z6?p0?j2Z*z>@%`KgTEqP|*PZ8tYoLI^j&e5Z~g+<*^T~KefDa9-yxK# zex*WK-I%R(1v#r5bGm0~s}W!#9%6XgY}|&}<=8iIpTlolt2Q9&S}>QU^8#V#6m%MF zRLa<>sK4`+=b=R^pL=B*wF8&H<``?$Z&7cgJ2#bsqN2YxTP)&&S-SZE$jRZGCmvW` ztKFyT9io@KZzz6R@+kt9+3|_1XKCmdXYAjg$Huh1ITW94up)YrKa=F+W8*7Nh+o{+ zs(F@_2s^YrBTTp~9(GH8Wu#OQ6^0qwWwl4+A%VaPM0VpRZHK)}$I7QSH67U|7fAjk zQHjW|fQFOLnlN?_BLVCS>e*U zn)Za^9xR-lzp&&nePfUDi0Ep{`4Ko9uQ0vdhdYT94H0nVDIq-$xvTshQ@LGCjm zUaCbQ6-Nmbt+BMVtTE?SS2P8ihf;5^777JC@vpZX(&Cf)vvLsjP&@eJ@7UVKtI>AF zUNv7v|7EWYvVQRZH#Qs{yqjtf0mZo#0c-kxBb&b($D*bOaIcJ zb$se!RLfH{*0gq{SXLt+D!BHI&zbIOgrHRn$ug6WVg@QHqZP$y`Dzi&xCPJ!Ph-IR z&oGm8!pd@PB_J!tGU0XZq%5@Rc$o&33fhb@+wlaK)z!t$r~HPaYE`iW`qL>55y_a zmcfKqIrRv{zlcK==C6K>s5Rs{_*(|$lX`CCw|onOs)38mw}*wRkh5>%$743-%c-Zb zWaJ2<)t%dvb)zQGz`l(iq1WP_N`&C%N`tTEJS$o+s!KuLGoU|Kwy=E1jVE*izeB}E zIPs`Ty^65Dh#aHxfYDp&+Bl9JYmtTKU8D=`p-(PY^ z!pVZfN5}xTv5#knzmUu!#vZx03534c5D$PD)c+Lq-#Xd$mprch*yV>gebaTKoNQpgrh zG&I_RC1Wvn_(y1XxV9qBB=sF(Nt)vPo+vO*swTu{S5$4pKA0- z!y$mIAF}Q+lJc7`9<9f8^sa}H>zsiXReL(W&j+%Qh?sIL9n0d$Tq;lgj0nmXxup3! z`dXk?s>R0{M21p_0l6i;QfLN+{w+Kl3(sA@LvT9q@%-lg)Z*B(?agWn1) zNhH4Tp!43DvR#UWXJ8q9@S7`6!OTLND^tH+nP)sdypWql)jLu-1R9xvs5{I{z+!e`0%4l*T)dBoSfQWQ+YPvob2rP2m= zDB+-crBVcTgk?+Ly;78cfAWy=R05ph%TE^1)4Do8yK4@$annMo5Dh8Ikk1%s>sIP2 z;?5whyG!=ie25aJyK9#F5mFzs-H+4w0J!{Mma@59X}BmMk7{>!^}3nFQmMPE&;1Y; zT6fn5_e0$Lc6V*$10aQbD6NSmRtFcUFFC{Z8TDGWD7Y^mYLpjL7p@W=*OCdsmNTyB z8UfsuzVYJD*CFs?0w9%TCZyX3`E;2)eg>@BuQ|k?HU>-IvM^I?>aU+=yoIiFtoDqZ(3ZS-s%i%4DwyX$-z=Jb5BSn#g~n5VWMUgT5H9gAEY_l8Bek-I_-3WQX+nb$;VC~o;Z&8 zpgXNBC)Pa$Q%7K&g>edY!pJF@^Mw~O%ZlzvBp;WP!FYc1b$-Q|fiBEQ5L_O6ZHDs# zhS2RByW5ojv70IXd~*i_OrGSyO8dYTrYg;u_%0hBOcWC=u9|Z^wzsMAd}FWl?QOta zAbR{X*jMF--3%wDz?P)JI;W!SwjNzf?Iq7~ir!G(s>R1!x!efWO;0MX{03j_L-Rvi z&%bFJlFQ;+dZRzl_G9{7{%e2ps5GR}?-a&gCW9i&xd9N;WYu7|wX0M;Uvujja>jm9S{swr%Hy5?Q{Fl?K8M!IO(l$3Ohb~K z?~{wAdzxU;+9+2ES@uqpO6y!i4qZKz{{g>!PT9|Z1s|InTNB|En^Jx^!}bwlStyIf)sSA#h?B=k@?(>XbyLACD|WWk zT`#@xa1DRUxhHm`e`#)cEF4@Sj=SXoXTH_FmNYuB#QMG%&t8CG>zMr>PwXtf2LUZw zKlinnz|Hhiu&GRUs4>nI|nKBB&5UC`OspUq-01zj-2LV z|4ECA*1<*R4reXJ<;eR`zG9ay+S$D^Ski z%QbKZj97L9VV;6;%71`h!q{(sV+Nw_n()8Bn<&>TUg)EY36C1RY}&*CT|woFNn1CV z&v1^Q)o9!85ww=TO(T`8`e{1$YGPqPF5H~e1%V)jt*o5M zDdbZnZ>A@#RezAL((ssG`6ZuoB`BtG5y^e2LZZ|~Lftqdx815a=e!|J@ls4YPdTL& zlSbzg&5XzFa{_&(CYeLfA(fI$XQng#-&?8#mm4+%UVqxfE5m>m5SI5j*elYF~V; zvl197%{noaa10k{0kJIvs^&xtvPtPW;hl_Ru1-L zJ%3L{y5|)?O{6szX3Ogxk-1U5Ubi(;t!K#u!>La`ZYMV1ec&jQTfV1{$vC(li=J4M z$)eTw4;i<-IaJ5R54%NUXN1fz{P5< zBS7O5jhBa0Ws+YIr40CaohK=m>SqpRHyAt3IDA8Vr!weEop4`vJl7cfw;A;^Y2FV7 zm_yY<36os?p%C-*GyK|1)YZ{%#nx}61h#Dr{A&QizDlo4t zQ(&Hj@f+<`GWfwv{I%p zzNBs(%GT?+vY+MO_O5la8s%sy3J;aP#8yb4tP)tLeins`auoEFT)3=o$IKGI)|{U& zOt@g-N_IF8~%1RnC@j!9rBF>_vDu3GCeG8hO6!wl)S?>a-Dprjy)T zIhQjs(##+;?ePlm^Gg(9HPeEqsCEjhX-E{|A_NraYp;O|6NbO(3&*^}x2=^L&KSOJ zjr>l4PQv_N$>6SA|AzgkMa{K}=YIRXG~nBAJ@WKXJ?ObiicvZP<`l-eNRNmGsVkkM zXzI<{sdlZr^(We*nvvEpeE5#2x=1r&R%B!D)}xDy`;nIl0ojn5@&r_!le0{!^I zKo38|eNJe0dTyBEj8nMv$DzT!;i=MB9pPswc;Lf@>qA-BZIwBM>NuOGkwtPk zZSFY2;dDp1ms}_v9zX_&@Lp&^21$P1H3~+iXVfV4s)pg3Q#OLl262JL_WB6R%Rg){X!?$(7#?msOv)$@*dH6fWj8tiA{1BX> z3Mo&pTsX%tJLTJYS~5t9h?Jm}c`EN_H?N<(5%X#JazR-Npya>At-*O? zhhR47<{yDA-{kVbDXj3VX=E+81+?cUl!8SkSqclV8pi{cdgt>TRg7k;dzL+#DBzMm zMMS}G-{-*WR-CSPzD~y_I(Jbixw(%$pRNHMJ~H@N;C@)-v5af^pyE?(qZ??>ye3*^ zNDd?O4ZQAZRu|$JDIK*DrVrWA5DKS zo&NP>)9)T_^307iS;lel_qsIs>CaXFD^>D7RlVME5AC##=RTL~hbq^->0F|f=E0cH z%-6GdP}&)kkvzK+(koe zeQ1jc^7Lsl1Ixd^|q z9{l`O$;_G4=n&Csj<#KvrFYzx&hqbVGKysYAsQbn9P$j5A22&#sX&e^cetd8(K-)C?ovJk@9j<*Y~DA)|NHL7CyrP-OTu(~yxWoqUKXeH1;b z#fKJ}^>zzufSRIY6|e^cKcbA5{Hz08?C%eA4I5(!V)(jT{E}|9Iwh0cQ9MA)?3(N| z+y}8^;fsuShK#4x6k-15S!vietUF}#V|s$TR)czuTox3XB`b|{7yV_I=30s@37yXL#wBMhGKWfY>S_LL_x~&rciW)TfMBww(&$7 z46B&WIRj9h{!am*1JYCS`OYTJPNY;CgB=+R-ldye3{C(8%h(5L-IbFHKFs9mBbTRN z-A|urMg1cgva!lh3(7B5hW*iiCw8)G;>qb0qd(7?vHj?j^`1GSME*?HdtdS@>*up&WI^$`=U&oX+MDBN#nyqv#uK1CkmY2h3u@UNkF_)qM= zhZ==z#;WwsuM01x(?4Kb{HNvT59xGX*GjK9Y1XjqA;Iwu;e43DXIl%-bm^kkC~gtX zU;%dSQ4nJ1jZWQnKTSb*2r<|#zSfC2ksL&yW_1c!99`{4%4*dxnYNbXr#{4hCF+%7 zL_Ta7#iOk=@qIG#d*ug!N_r8H?K|24PF`?R0<%=0KhP;v@*{~6+ZF)A_6Tt!w1CP=X5PM4 z_4CbF(okAL>EEbg`j0knGf(+jvF;FF$+Qs~0L$x46r`UPUdnk|P7RLX%Pl>sDXH;>MJ5KdZ zd8-BI0>-!8<;~}kS`d}OwsCrK}K~4{B)HTOHafLkaE+h zwlOs`YfMsk7N_$>j?MFpOrEhS&!TjmeDVz6mWJASg8Gv3oZa^0yNPxvhCLfsBc^dR z3FQY`@+}n-8c8~)uF^Ce^4FyXu>pLGXQM@2mpYP9a-1`Kn=H4`pD+;taKGUIgc+pv?YecC7T+`Tz1Xa?USb`LFGoF10+Vj!k+* zkI%z+Zgp-0)xdTsF4GGpRmU`##`;|(v0qWWA`LA7iqPRFFQ~5Apm&}Ci=#42P5|lwjM?U@lUluIC^;XZTThFKkv;}=KMu%qo|D=4$qrr# z7;-<3RqW>Tq(Ia=GC`>AzM#u)NHnc#%RimW#=$Xq=Qo)>GKqMy6B4`IV`tU#?mTs= zf~CtWqmtM za_7;Bf|uIVg2>#**Ey`=?nggpx$|l zqMfW!E@6aeWs2_Z+^13$oXT)_=fBjaRM6eIUxlUG?#=@$EXZ_sex$;JVt41qDlAf= zi^jLzvEp??kQ>SOLsNBx$iG6@&vTEw;VazZ$Ycz&FmEZTpJhVa1<6X`XpDE^wtmS# z#K=z7In01_RR9PI(kPj6Gt1H6NpuBHDaYPBouWD0REn(pYFT$>b8fJz#<9>SUB zpO%g;|M~-e5jyhI#*Yk1TNR}J{t@<66F)H=yC|det%|2xzoGv|mC}FI%M;k0``KU*P~770Gf>tEhGJY27LT*cHvQ=Qtx(c$Fp0maZhb-(e>c}9PB^5=XzQ-$Rj z)W^mAP9zi7JHJT59+|R|%M=2#)F(p(GfvI1U(kw@Yp7<{3|pM+qL@Ngo>;YxLh>I2 zm-pW$4G#-V-VdEat%S7dd5E^9X} z2;gf$e)IV?R$y3uu2q*$9o{s=pv5gC7dSz60RGXRXzz+5=I(B)a?UvsNd1=KV-gdx zTXjVMB&0cgi%A-CeAJGtE@oe!&+{|#7%O-geS%$ADVTkAH`J&rlc4?4}6VRgvY0vZJ+=>+; zt8+TTZCnRU7)k(l391xr9VZPBuWeetfT)tKq7~FpTC{I`ktr2*+X9G+PFK3hddmIz zLs(82@L+{Cr-{QCGU*%aujJVYGFSb=zSvqeiZ17XV=khUFD zvmn-xpGj4;{8VbbZRPg;+jRt~q0LqT2!8XTiqo?Fw-fK$OirWu^f3lE6;8TV^%{*iGbp^Ym4PNpm& zl6ay|UolsxiwrV+g=@hc*F`8H198qRr>pV>N-D%Y0azn2z%mFvvg+i^FGY?8W=-=k z7;L(4!eq2)6y)b5mn&$m;_1B|7<3yNO7TL zdiQ7PObqt3+4;6_{O6Tw8r>sc(a>^EZyQIKv9W-nwsAGzCarn_vO8msm$}h42Hd4t zlbQCaYl$LX zbVGVyb_5sUY4fi*pz(j_A}eo22qB$)&%g~}RFg)the2>W32oTgstW*k!1Z!BfX0=& zPKj}Qi^Ys{lqLwV(r3x))agW3#Vhj^J*0{dkfi%9oQpAci2lIm99>F-H;q>Lb(tke zbgPYu%Xyy}_nVu~B>^)tV8F0m`;q%FQ38)Lvn60Q`EawsN2LrAag72c=g<}kd#!e{ za=_Hu{Jjd0)F4UGW1g%Kr$O?9#y8Oiv~SE$ql`RRZ$%oPprR~eolJsRai6g)ko~7@ zy`d40@+MMj;0`q;M3BAe0h*G)lIq-}B7oHSt=dL&>~QT&v$c`t3yV5B&E@um2iqRr z8bKw~^da0sET^#U%mLp|GY!<1q36#M=P!X`U=s0Y1H9-418X4IqBFsIUg6>G#RDJ zWtAMv@iAn@y+*4yYlU2ATPMAUkD%eZ4}8^(?n9q(1~IOxd1hEIeAa9lViMJjYleo5 zH-;)&_O)DKHR1o;Y}n)6MFmy^_#>LHk1f_8%C&e%rC|>aK*Y6QYRmP}eMiiOA!fzs z9xE3TMMs`T=`)A8-PCfvnJ7FUP|rY9&h0d<%W4_2D!X|5OVd?Up4JsfZMUL(a^m}{ zJ<*|xCa3v{WEJ$cuQ{mNHG5XceqphIv4U1j=OB3&%!VDRvmY@R>|$TDPO+wohFE`S zgI&~qeg6?0=?$45PSV0$O*$Q-1#2sia6zEv;Um;tWAlbl9^v>-iEn-=^?TvDbagYF zU$S>^-}sGLYQ{N8d70R`_7qw=&-$~W*qdi-WNrDPUF3zu?dE@F35O?^mRmP@JqN6@ z+Z^MQ&=PS&CLC_9&*-K=%7rhqMK#5bAmsB5o8T2=EWOXTxGg7)j4+1i9j`8#2Afrz92E2^d1v6k*ElE zCK4wC3WXgsV-hE-2e!p-oMJgykM(XjBqK>qIFUyslUmZL6{sW+P1C7o=|3h=HrM$$7&dKo`~mNTuVR!MsKD=k&lA~HPn zbUunlV}&m(RvbzFO%>``D{&T&_Gz74TTiuGeQKTKI#c<;it$t8`&pnEd*fv-_{Q&K z&q$}JM>(2im#}|wZe;V?zVRZwT!_U4m?2lP?q#K)tdWk=!u3q3jOMU2>-#Rb6gm23 zaGS8P>b88kVYuR}En#V@67opBo>Z0}=BOU6yiafFs{>4aYA5VhU>+c62s+9FCYSNK zCh{C#QeJfth>x=kcw^*5Q<>i2DxB&=`k?ijw0s|qB9cXd_M5WHf(m>8lj}VruJB1<$P49 z{xnQ0cpZk_X+bE7WsTyi494FEQp8*pp8s%u8-n|b@NC^Q8?JXfC%av^1 zwjdm;n9#Dos<~6kd1_S~$!NF2#_(mj!XDa%g?25M$=nZd1aX1|&Ic^N!k@tJxKlYd z>Ar>1@D{foIthWWtb9e%!qnr{sUJ%}*f-Y*j;rLa{AVvho>*1Smu!nVv+UWP2(Jx6 ztq*NOUKuhH*|bJrV{1MPZA=R&(bOYg{=VpCSO*n_TQUGxpq(4YPV?DOnKgF?mz`A+4WfMS=v1S48KYP?%CcI=S69pmG;hq%V%@LP zgEW0ffCouj&+P{-4Awn6%8!1E)oUFuwQvPG^$r8uD~rIa9zlXm^;%V$(K{9s%&T%d z8$~XfM*?HMbwCJPftwr3xQ4$6K7K%4dq?Q{+F%xKhQ{*cyvv-R9xBR$rq1i~RqL0; z5TDPhPq|zYHdo1oK;ZeW6oVk%{2{DVGwd5DVY+j`MB@MJuONwQFZqfJs!NB@5>&V; zza)qR3PO{sJ=lW&sD0zj({p5+2v}Zg8Rl4tD!DX_8-UV0b5oxa?0ef=UD9uLJi6ds z7}Y61+`QYYnxI$-G}P`!wwmtATNBl(c`zR=XE=*h1s765h8j>hjF(+HnxShyJu zp@#$32{5?V^o4npO(fl)()zT;w{jw)6>ct1w4P=^b&1eQMuBUw)S*ad@`hM$jxq*U z277RZW>tH009jG3t;j`2WiQ4G>RPM)6=hTV#=E8|td#jE1!i(qX?@kY!RtvBZW3R; z@vj-5oTh}Oe?pG-%cg(lJNSydTal*jG^2MS7zfKYHUC4LKutdlcLK+8A8qW!h-X?b zwHJa0#cg425YK4k&Wd%`^a&IQqm&5ITe3jXiV(9&(78dD2HCL^SuuSAcQ2<;!0LcC zcB?fl7(3p)#FIb`%}cN5O?XLEJ7~{9qE@ZD9#&`AivLoVG~g&B9i5Jo?YIou>7)yj zXpbvh*ce4Fb3|}Yf?NfYk`=8*0s85;)uQymt`Q;zQ$~pEa{75`ViTp2Hq=yyL ze22`O>RU~LLT+v32qatk$aGcX&SX*x6u+lq+`HPQ|Qi5`}sz1g8 zD#ii)*fqJH@@Q~HF}pu`KnY69krRYG4rn;dK&9c&O&wguJ6d6!DI_=TyD=_#%<*Z3zQBZUg-ALaLjoA2g^ zcrJAoH2)oDP^%xC611(ga?SzgaiL8sk7_Nan^DoM$irJuv{V{;HVuL?OWEHNYl%LX z0y&%j@&JYeJq^NPK_#M41odb{*yo?&DQg5dkIWKGn(tjTX| zym_?!Wf3RLV$ct^D+@S1+E-QW20BSJb8ps@q$MIU&u1kf zit`c?HRKWzHQ*8vHQJa^{!>mx+(abg7FT?hXsZzn_%G2W=(r(SkKK?Up-9p;XCzKM zSh}fKkAxPaL)1LOnSg$$edD&tYKZQngNl^`oJ8zeQm3P|T^)QL~cnWjT?fC~b2@PVW$W5TW=)V?Jaw2ms#1gL26&9EYQGYv}_7)f|=X0W0RC%^-M^RIE1RSuy5OYoijV~V?Gi0Z@5R6xzyB%aqz78KTEc< zt#F&xa`6alj!!qRt#WKu>~vVyC&28=I}!hT39V*VUwy&UFAGnHc9rKDi2_T->QBpuj67=1FDJ5vOB^_VEq9vF7sd4o z{h_3K(X;$u^H}{M24iZ>GZIgq_*2i9|EqQEel^n7!pFE`C^r*ZTF zx~Oz<(cy`GiPLPoa|?|?Q!MYZ&7(B*`i;EW&etO4%}ot)N(GW*$SK|0$wGWgHVTzI z=Vq5|z=A%RQb8WLWVf@3qHs)oR_u7>nYKziZgu=Z`X^V>kXfl-pDk;kPpN&pc4ZgJ z2>4B7EyQiI=uDt7*ByN=3#n^^IdJ!ZPw=_3QRqvZA)_^)zP`Y>R-gGI8J^?a_LoR! zEYItW<>&>Q-RebpU{%2F_(RzO-gA(#tgTe;ndEtKZJquQ+vU2{?evkiN_?h^W(vel zR*3UtvCs9oluX_w4fuk&nVDR!P;fPJliLWXpdQ!hpd2&@)FWnH(l)#-IxSa{)o)Eh zn=)^MCy_yWy|m^39rX#aj9BITrKV3j3Bh(fh%-PW*d9s!N^nko1C&8P)T-$l5F>)H z+~-kJ@b)`}T|_Eyo+G#({RlJs#}BZYhbSknz&t|ys0b}=rb^zUN~%Tt78MjZ&FK&z z$EAU|05&!u?n{(w@h(nc+BZ&SQ%CZ%DA{mm@BmitxWsNmoJP@vSmU!M!yG&b`HQ{? z3O>&(sdvf3g${1Mw~C!XuHJFG@GI8xE^nkQIh>o=gP74>=7!AMywROTZ`vrdCVZwD z-ECa6dkA~X4sl*7?yq*6fp%kq7GZ3DWco1iEN3ezoQss8L}%$SXZ!;qEPV#npsk_P z3mexA4mp$W6G>(}atmT?bSJlzW(DPsJP*;Z+lmfazFQ|X?2_kg1KrhZ3zCWGZfc+n zyLn)Hn7_XE@|NAq+zsSyw}2JsZhpg}F%Wjr9duN5kWnBK2WEb1c>h!M+O^z!NYoYx ztPIE&UqzkPQj2ELn(pPsTf?rl@~qY`SuKNB({8G=19w^Dt=6Ea-D0)uvQAvB^XO@} z?-VJ(^R7LC?21_htvNVpj->u%wCwi8i;dO-PyB*JZ5Xo4mP`h=v*nvoe<%^rRICym zP?s)~u3;}*kGa0#Xitn$sBM=#V$#yESvkTt4v*8PZoodQHf;87y9VXu_VoO8lYot~ z*$K&^Q>8vh#h})Ct8C&^0}!Iqy`O@rNiR`kW;=-{?D zt%l9VHSILDTX|V)TA;kLoulFCPWm`f5#7z3UC}|%hOU%s{ua^eMK5l(?4Hyzc&P;S zy1u?aU7a2vqe(>VD^|0q;1>FX`am<0#9$d)`!51rfho`#cTkSttK32t~8?q z?9k({q`KwV>!uga33xc!#iz?HpqN@Iv+*1hIHL8uX5Z+VcqVF(_KmyH^)T4BGvP$& zxiB?2r?7m(V!!9M*qH}d`H7TBCx0Y9(N=at9=A}>G%t8?G zyqa9XSP?WsX*yjc^`ksFChF@dDsXJu%ZNgqEl)VB@hzB#Rkr+y-q8W9v;c8D1c^_y zZeTt7Lh9s_y(p$|F#=Ei&wlFJgq{9gTYHfFvZ)s8I1_&(tPm=}T>&R0tVU>N(+ed! z04fqnIgh`~m|(HP?+NKusjZzT>e#8wl1){>XdZuLIIikB8=EM^r)>4=sk_+CvSM6f zlmi@f#qea2SvkTTkJ$)EOM9$YK}%bS(M?IO9E14D9mJE3Pq;AaPVN7T|~BpzOc>c4eou$TMVXU7+dw`d1Ks6ABV~0do9qJ2TAG z@YQUCUS?Zkl+`N6EL(`6RBu*+=~q6|ui9c>=VLUM;6;Xv1Ln|{gRaPI&+O7jmyME$ zI5-HieX5_yM&w+YsP<4Qy};@G^-=sI`q5(`Rfh;IkiYYG(Zu`@R7U69Foq=B#!iG! zvfz5co_e8&YzS5Axak9`yr3_tz_Sa(hr9w`?3@R9=w6uyj=qRe2ULZ{;8s92Hy&}T z`L~<(Gk6#q*aYOwJIFzaUte<}g9e6L^tje{Fo$JIsHr{81eIlM5<2wOeYS-m=Qog7 zRTu&Z*(k!jx#I_sb^Xn&;IA?z zA|nIWAKmu0-5~cByz9>fokC%%GS-XTTUBqC!LNaB4x&iSC)$Cn=dib#V$S>|OI{K4 zH?wKI;APnj{g`S2d$qe0%8U46p3yx$IU@4RZxBx4XEDDoz>lvHzFPZOpAT~Wh@Y4N zJ~rwFuM_+$!7U&?C&-^h68(+H(*8LCy#Sw@^Xq+jL5ggR$f@)95ZI*`yur_)UhoMq z1A4&*zK-$_&zgBxORj$rsF&(wt6j#whzRG4rJEW9;z!|96ie+J50~d;HNy8&<$3(O zA*2_;RsLEj`ga1nK~W%xifhj$g7pTy0FZOu<{uc(r)hb$VG@nSQQ6eY-ON7<_^&D= zWg$X(-UR+l1D<~xwflL#qJZ9<^B&=af~mCo1|p?_v@LIzM7||COZ5T>lXnA<{5KR6 zTIkgaUXpS=e?6bBn6sT<(4F(Xlq0)fB-nwK|0-#<6dOUQR!A_5M)+q5ou@(FH_0q@ zO{=7&RJO28FBl{e^5$JduKBbjZy~99JeyG(Hu^)(DF_^h`F?REahwPr%($p4VRJ3{ z^lCNt&2awlu#opBWol;Wr3OoeC0S=$&EYu=wmAsn{acPQ+c0-B*(rx0o_@RXanJK~ z$V`#w7&zu83r{#AyvAf2_Bdugz^c8*2dW)jlr6N7XAPnBTy~}XM9+sC^2U;__6UDw z9VDe%lCLO8r`1VsR6`&CtRWY`6+)-leVKIWDET5?3QOV@Wh|L2`Xg}L?g=^PNvs|B84;Q6Oe{b=HRl_)hKlRJpDR?D4ATn3GN7Tr{79+PB;ciVJzsf~ z`Qx9mnLqPL7zGa%T=3+adxa!blgR}yMdk_}Cl`GhJR`{kFQx1G%9|{MYs#R2-#rT6 zg)D@=LSm~W{pwH#ycC(smwz&o!?D1Km`cvz4>DK~Ll@)~j{fzV<+Tq6Pf#h9=t!jkH4kkYq;retOYgRWJZ3RS zIgDLURAOu*AEbtrSL1Di_LNY1SuYfS6wLj$Zvw7i?V=TY2-8#orwBz0()o*0P>dgxWMP{hBeXEEWKJ@o(EYQdK!c>X)2H1`Pg zSeYn)EpZH#JXPLrECUa<&H{wub6Ll!XD+MP+}HUh^=_x!f}TZ`lT~<85A>%N7y&tA z{tiCo_Y^A-vJ$8BK*Bi(RLu|!EElQuOc2*LM|GL z)XhB+w=^`RCQ8?+`lc$f%t5G-cF7buS4glxssIA8fCzW{<5{#xRhGe9_2~kEGv|Pd zuHzyv4Dkm4gyCbEdgn_UuE|nRH6sy1NkEvX$vK;iqaBSHd)rJlEdjo$jszrF+=_oJ z#xTt+in1_H_gONZ&Jl6g?Avn4_T56zXTHK5HxoS~9|0SET8)xdMB+dO2^zh!xS&WACaAfl2=Ik#)G@{J^bRaBP;qN5iQ{A|AwX)K+E}W*$=Eigr=z< z^7RUhdzLUPI+xKh_xnJc+d%%g-x{*M3&=T}2;U|p^n&*lxcPg`_w<6DZjDNK-mKQo zIh(BSLFD=HW!{`2{>&D_NA}sJ;E?yfzD<uPQ_pHvX%?iXQWi7tCCo{8dMYxb9#Y zE3i{oD(py^`z=yjjQAB)=WGHsa_s>tzUch<8H@-jbSRQ{3Wh~q;or!S@`F$@C|GIw z%Ad&u#zO=UUQD*cm5poYJCk7RHpgZ!!I(=82^j!h(fZaq0hOG_tL%O6?F=SJjD zJ)drA?bC_Uef8uREltz?)k4uJgyu%%Pd%TiG^^dQX+qt4GK>~JQa+%s#1EIq&VGob zp*)zwyTkAKkvHupg)H!*K!FB%5uZLA$v3YG1dx&?1`%1ss5XFW9+yh^+MY zk@77!{vXw7#v)XB!szq|c_LtyCx{B_c~vS3Xn9pax5!XAT%1?sTlyT^z=*3tL}Raf zlkU7%b^&)3sa?RmCc5lMrP;I_3z$fm^?fw7+qrjS#$PlWHe1>%Gy0U-kD0^)b8!f} zpU)V}o+HMx1DtjeFs>OGGMk>ox3T(ocF2tH!s6o`Guk_%zF%itvukLJV_efagw~Z; z16r`5d7L{ZU81A2T3+PEseDdot(NW9?YET)g{PN_qFZY>T{Y716@IG;MgK0WpR_;e zcVK@);1O%A)v(hFJY3RSi*fe-R&;a4Vy*d?qK;qJ0cg%54z?6nana6Ox3B6Z%J$tV zAynU1d{@LSz0;a-T%I|>%u8)A*`HQEbEMF+yFAvV#ft@g%Pu=$BdKR$t!p*V^gmlo zJBOn?&B|Lv&(CMM)i6M!S(#_GY>uF}Z|;#cHtn<;UbH$Muc6*rYfXDTI!?qvn({1f zycUUQfW&V#4e-O|%k9<`Whk_e@UTW0G`YNSxxeCKea%AIOhk99JFIlG+P<;DwA!SJ zsMgUYTG6M(H(qpS=X1*zOV#x6?YBsKnOIBLN?2MPSj)i>rpGJ!lfP=A-YN%A-`LeT z+uZ)nB=qKK_iJLFcCz#s^d*~mU(u|_Ia}Id z|9Nyg?Hjua)o9qw{3n(erPiz(d)ZjyU6I*+wsuNIZGGz{)(w%)y|FVg$0g_9tQ1r} z&n%wcX*3Hk!Z*2+&{_|tI$jdZ+DM|dMzPDR8VlcWJIvM^#$*1Kp3O?z=Z;8X9=5Wv zIhT{JKDl=l-Dg$%t;;obZHez!>b7xvF~Br;6>fn{B|Ph2%2`C#zBo3 zqeq>JI0>E|bwzwow?&z3v^ZIKu^TEG)*p)QGvm*~e@S^R zlyg8%epHtZxlVAM68Eq{@7P8=&c)Rn>bX{wz&tmwWv zkDT^AYnP4%`{svJmr1o(aHd3^y_V*O-?mvz`xwS9lWxvw*hxs;hz|UTp=bwI3o{Nk z`6Kb)r}B*GZY?Qh;loiUiLHoO=)0cFP&b$C=lOj-US=M*E) zXeG}fG?W4wow3$(lF^LX8tW46aSrtC$)4KOySVW?n;}wQKRV++e6w=X&_eYNufjWA zHpOY$!G%J+?$XcItysD_Z8>)_CpO~bTw2Yooh$+o z_?!!hFv|#M=L%;phL_BuwCWulDMK9&KIE#MG)JtODP5x!?TcHEXG||LDpzL3$3;?m z^$vMG%jSXl=g3o8F&+L55yPfj*cgUUGdF4V)GZzf!^CD`2Q52k*{hea#}4cE+r&cf zJYvEnd-aFFn+&C?1w_ads8YT(T4Ey0F5pZ<9s7uztBP7USrq2h?0ou}*=!{k7O_xe z$N!WRlO9yjk(Qf)Q$#{BQzQ?)&Ri9YpF&hYlx?EBp?BCqmNjopHCnS3W8$RR<;?>jJQ{%CAl0oT$SVy zOSqlcPszw*g2!hz)?z94{Y}UUf(8X;$j6~jKCK*VSxX6Td`!mkhnPBtGwR>q)0|| z{W(D0rXJlXXe5GjzfR5omtAswZ;{fTx}8^+fprS71PtvcP68xzV*A&3x$#F+pHRCG&6=(b=E;GoqdrV!SemDp^+ zf2(Lrh!*BsT|Oe(S)J5@chRc$wAR%JBmi&{ zMqR;l{M{18W7%Q@x23Spvl)xF$peCr9T?~KYvDlofXy}bhW8Y_z@6Acf4%&@<`c>X zTD8LGQ-Q(_2ezh8kY{VgR&P0c;IF)XdKd@+&+|Nx3SMSlmD`f`@G6C{i@y7j8ZTMf zUTQOatAs$@o=EP2KI%X*k~wID*X0nshP)ALX~4c#EU1`$poZp*e?j#t%Ym|jep@K2 z{5fHjvw4j`BL zRw0QI$n&kj?4{*Ib5r3<6&Ey%9-(H{5wkD#`fB(Zc-Z|F0%ke+!gk7WlxKO(^viH!WE~&(5i> zS8c0RP5T?RWe7v0C0wVjp4$3^D;Xtf8=-@obf)hmxVO8M9L5l0+F=5+>dRO*Kogh& zCLwoP@jG*b98n<>CN$~ENONZNyT{|{3Cg+bId$=>(=Q`HxRgg+(?`-_l9;~Z$TfkYl>~pY_QO%Sa%ixfonLQiCNmQwg$2R^xbOu z!o!U|T8N!qlfQYVn^V>hH>Yf&tm$Q+%^7IkY1N5n<*fT(D&cBP>_YZ*N*eK5ft6DI z&q;w)K1k(_R8(orgP3_pkxmkXQw}&kB(z?qQR#~$F0WEZu_k7uvCEmj8jxN2skQJ0 z67j=O!-+_N{A@XFHii?CA~&ko{V8>S)aqq6Vnvv!s#H-`a$|9L^u|WP9YW%_Aq#}x zO{Ma(L9w+sUnqSpT}sCYZsrHvwb8<|;c#*<0rhAZ_oc}$*6Y}B?U(B!b;YV*G~0b| z!}_Omv5X*Mlt+N&5|isZM`k&q!rVr4o^n5o9+|*+r&x=fBZZ<~g-k>ZK)DG3&HU|D zf(*7b_5JH>gGCZ`Q#rV-lA?54$DMLZNepnJ3>vBT`VB?&p*Kh6ko@=TaK~#{#;Zu) zZW&4Pk|a?HHwt93xaAaVzAwq6C2A^=?V4{bmiSK5L9 zT%7w|sV_6Hbo97XWe-Ms-+UF$bEAYpbrr3_=3TNzO+kKE>j3vQ`K)AoyZ4nwZOoqh zkuck`(-gBk45KaJpzB(>{XkzajmWKVyjvijg!PU^(!Qv_JnCy58__$zp+32SA`&tb z3>t@JU|nl1=0&{XL^MPn$!k3EG0eF!nF_DPgCu6?6_=OA$5d36#?G`f%>LAvNkr4b z#T^t8H7FFcM&1@KHK`;jTlH(@y1w2qmyYDiXZaq6dLdC}XzS1&$|(-y5yjk#K$Qe}qFwF;h0KraQWP)9 z4j7h~?1wm$KcaleRu8w%Gm1FIfUU93R6|g%k09*2aAi)5YB`l_jh3KL^jgGz-`dy- z;y2WMIUdM?Iy@dp2TP1y>d|XHRAeaPAzd~q*Ka-oWopO(4g59!BZO)|uK7I zo+BwFIpcy;z6@-Ajc^YANGIzxkQ|43%t_(+IC2E!vEL#9_*`cWIJV&QR^;FoKU4xM zA3GH8QE4mr^bCOpGXWN1jS*3kGRmuIo)$li%C+J6NhBpAl|slwBqBelFSEA0urX^# zp(TCiLX;rq|7^|<^bMcMi1WFH=m zRhPdK*UDduT~hu^bMXp7OD-sU4QHzqHkN@&K8DGYTKwfl&4c>1{t_(s^vMU2f_RAm zQHWMG$Zq^vd{`ho_!IcD1v3l+$E<6iV_5_n-TBJCPprnd#@bKZkd1Nid(Pv3kUM^6 zV%bovhO0B0eWwULWXGG`+xlEbt@nGjRMh)ce(Q06A>T6D}v3qpfVg6T3NLZ7Hp(I1N_;s7Y5M2-+^yK`F!1!exh)8K+|Fs)v_ zevPar1>CwKQiPX`;PR^AGF;K>#o)E32f39B15}vWBeA}g39_isH4s`MbMTsB{D{8I ztI&HZZt%C9V|B^uO6p10U24f?jJhWVI68{5SMT_xn{BbNjIYig$=9-cdG@S@ zplrxOY1C$c8q2|A#=l4JJV30ZW)Lq+r(y?tY@xG8qP@pPj~|Iv{y#EReEfu4g;_Of zZVgd(jYO;MAdIPKwMn8Eg@fIF=6l=TG*6KVGHJgjP2wTIV$x=7s(Cl}Lk5XLTN2nJBA(=V#?u*=fQw?Wq`9b~W5TD$w2DtOkg{t{6j8SpRIz*>Bk3Qq_ zM}|UM;1@c#`#r`Poe?Y93pPr=<_NJ$1DhDp!HRmVrCD%S<$!ayDrffV-49DiT-UiQ zlkap;14Z%+`^sO|Z}}0acFh-*LQw(B62z9rm91>d4iuOkPAln?)7)Y)6hJ}C;~83* z5P!AyqAz%oc!^R5^g=gj!|BvrzwU>`io76#U?BNL7Ymo`I^?{LZLAEJu>?gn(r=NF zG(k8Fi(=~BzD{iHqd~MrqS9R~sEKRQ|A(=+fsd-X_P=M60R|j7L8FG6>Zq|MCDx?I znv|deWVg`hxX!!-8*gFDc8UD;{;bp-b|%x=HJzmr6Y{3n98Vsg`q z%YJ`y$yq_|=&V+(B0eDcUzEdK{h;CoayaG?j+=tknj2{`knkrM>`}BLDX$tTBa4x( zR_1bYh=9mb+EXz;S+?xqldJs0W2V6x&Uc+c*1uovPI3WLgyXKonwPa#XPg%IHma8G zy{d%>fXZfdz>$*kg4H>?{BW%f0G zt*+isOuYL=il`6GiAp6Kh+1c@IqjVk@gpbYYf?T&k<)F?f0gf9ymnbxwb?lEva-jh z18+K+H&vJT;<^Y6O7CSw@3Xw$@C!5OG4M*UL-lxrskNS2W+-My+Sf&4+Ev5zREbohqAHMA8`SeL7AxE{poE#^``M0SA z7wy5Zn&U%fmEbMELaOzXv$cLGTe-8UMcK|G+vzl;l52t>RY{e17oDVR_?$KlfEK?P zb(xiEVAD)?y>45f0`c+5n6>_!?44DYMlG{uLS1oivl$HNysW#9zYCZ?$e=qsw6Uk^cg3<*(GNs#2B*$E;HWSL- zH-nZD|95|m5L!Vs#=DlV`e_Qk9F$^{bro$^^WY7`weLQv1D^A87mBh+#h<4^Yb9cBKfr_UcjYJS4FjEB3wln?umw<8QGgYMKP_!cx@%&=UK4ab$vjg z2mt!6yOVr{kF1M)suedoO~=!Jb&luG2y&E-gACBIvUpbEUw~e%`^iJm!qUx_FD;f9 z3#qx$wc~tQTiZ(UVMBxtsH*K_!{EuWhb2F3Aibwi8}k?5Cdyfv>GUjH%<9N4YFz0U z2+k9Nx_AUFsCDm%0x1el;0C_<>iG%TrM~dA@>_ ze)HBmT@dnhQ5Zd>pV4pDCvn^N_~YNGt7CiIgk?Q;b(rm}wRO_z9Li;%qmZ?=#NlC= zWYo$G@F}!?ML#yF)LV4s_Bdhot$Yr{=?Fg~n0fgbi6;?$PH~cPpq}2Z?`*1Nv@BzQ)F%#z|6MQ_%hcN;7 zXX^SA<_|4i^CSMdL^~s>tO;Y9pj%+0!45OFYJ-lVR~nsw1?UIUFNV@QA@Lms97DKb z*@FzpI4#hqXy#x$Ze{L-;I|N(BMl|e%uP0Mv=IZJ#BZ zza8@!XV3P|08oXu2+vP=KLKdP+ut3ge)JxBg}*=fY9aE$Vb?L$d5=uv?@5umpY1&& zm(GgBd5W|yC8(0utva82)&>u_ue!j5&HL@Es!Z5C-@fWX6V~hP)?=$MX9ziKcIad4 zs%rD`RPa%2J{tII?Ot`U`DoO~)>W67k7j-BT2*I0xJRpxdVVC|oi#0r*t+V|Cbcd2 zxYT^K>*KLi0_?1r9(;Vpe9X|t)>W#-So$>JOJp8#%cc#VXv0s?JuIQ+r{Uc1+NpG)5kgVO9}0(iQN6!#NL)HOw+C7tPJXH^ zHN}4iyB3BYsy6BP{eGQnWZz-z<R0-I+joz#wd+^+qBN(MyULea+|GO0Qx0=#C z68i#s-nPfhq&eVU01#lx1xkBp=_vD{Ywqhz{!AHd-Gj4|*Il0)+dX*A)af%)pXeT( zI;CYw`a&QdVW8(L>wEmW084*GQ^+y|QytHf`hFiCcVU2bf1If_eQ*AIe>*?czY+LW zBV~XoGGeC4xI%D@rpPLOqg*mQ>Q6;huwOR!+!v3scJ6)TT>H&)Yn}}skY|{HlImSd&{d(`4;DXa4c@4r{HjGDtQ!tR0}4$%o__5A7lnk6xQp2H?eR$;wGHoi72@G&=KYjE(6{>U?K#9u$e& zFTamFp?UU-(ecGGd#E(stZ*WInfAYv0k6y4X-%1uh1O%OAUmyuLqv4s+qDR`kCx$^ zXP!1R`E%@{F}y81RFZyPP$KEQ^Vmo(*`sP}%cS}^2mbVNFRY#2bV~cfKF%VgnsU}- zUyIRR3iHSa%cJ>a=z61j*3#-!we?s_6&D6R*#iQn$tEH=w)rIYIRk$}NU&?m^O#3` zQujnLp7=x|gv z5WZ5g1KE-P(NOARq5`Fh$Cgij*-Xn(XJWJPtmWRaGZ8Xru0s1Fr$T|-y6gR6Xw|x( z+;hAHtMMMqyD$(E&|b;Ye~KL^KhEQL<>7nnGmmGiFiqzW%x zC4X#J%fvnz(JM7c8QROXzAVX~F_U8TdoM(T7OLMHC@LqFd6PJ7(`pV4brmu&_XsdQ zj~y`5P?ik6sF1p!T=BkXbcQz~?x8k!N8pnm^$XJ2--V6?2F6i_juz~%VMhzI%PfVb zXnd(T5eojFPYnVpB6c4=+I-h~8`gyhaS-9zZzwZB1Wn>q8{w@VDR-Q2hGeB@zf;JK zU&a=K@aQnmuEiY;IFkrD?AB|Q7ILT+d< z<78TOe5Aw!DiP4CqX^yf&ePyTe!uTI*s0<(aY%}gr6&xJJFmE4$(#M&xg=xy)>Yx{PNlL8tbqP3m~4c+rP>qs@p zY`ELhqRSBl?wJt3NH8)Rr-Njx9Qx-ND-;@~Qe(nH^gCC4b48Q2S|r+keqd$+GeG4sg2j zG*@A{NpW?gnA*wxHWG`Q)avVHM_Ahy4&vuP75`Q25e4 ze5fP28RQ&E;$E2}Neut?Le!D4u2T7HFOl@XQAULQ} zEDmZ{L`yKpAQhMBN+J|-d?&`~+h<`TnGUqE9;tAq<5H&5nI0E{)1&?YK=~ERj77kT zSZL`PJd8r?hwQtz(Fb8pm6^ab(HR>!SXxh2Y`$G=bH|aOH|%Y5vp6AVl}Fvx&7`{bCHPAT4ox_BW*zOA2D7Sp zKbk(@y)xft|HuH~J2kqy&s0E1g{Z(BeHV}{3_PvP@R=x6GEIcZ&_huxt2ZWfa(A#` z$;8tqGX2VSsVruhUgYcaYRH@OY;Fy#rMBP&BMerizq@Ka$cBTcW%k)W7=i!5)p z*AatSL|vWKiI|pXQeDUOOLT=ygf&)4BDzY^{8kr!YxT>_F4i=9TWmH)zKH+ZEi=>v zoFReYk&(}*Mm6;GtX`i9ok8{#!JXfm~zee>7?e`Hjb^#3DELyehCnx>Yu*(2aAnsmaPfLX1 zhJP?yHFj=obhy28dMI^@H+i}P@BH@?T8^nN!LwNryOU=tSZ0E43Jx>DISLN4W6ob} zHp?9EV=c-t&Axmkn{FC%hP|R$Z~D%Pl2z>GU;TNB_7;`wp`_bt;B7I%cE$de2^uuM zV}dgjyU_$Y6m(3`V6?&n4H|cv;9O;xZ-UJVe$E8vD|np=E>LhXL3_o*Q0jvEpw{@Yu&*A&<>Wz>yoVvzay`F%gAAvmH>P+FQYq7q*RrtEk zq^&J{t-p!ZuKuCE8mfl%=oi`G&-@&_!4=Cwspg>#8JHUd)#@%1q1f55rg^6^umsgX z3UrJ53C-87%k(J-r)arGXCfTR5cWA;+t*U@zFXDZ*T4Nicl-Bqsgerp*U_L-*1Y;# zfO2`MfJTczw}$j729y(RbB6PuCaSEMW25}u2Se12p< z!*g17dRS9y6|UD;8@W<$)~~KMCEz-A-$Jq?$Va$mcD?M*g99B&vcr-^GgEGIp|gKvZ)zf5wcX{_U@33M)vPS! zpca_T0+lAGrWOJ8{ne?R?^nqgOJHiz46iMffvQ1`>n8q*MI#vcR{lVEMQx9Qj- zF1l?~Q)s@JY3E-IGyOug_6d0f&~miJu+eFFSR8Gwk-~xIuen%E zHkGShR_0!4V=qM^G1t8%#=51#@$ZKhE1OG&!^UBBn3YMk zC=?&VS&f_hF^P1`SnxPDZqsJI&i1wm+OZIm?4HGFaT^^rlv=Ap?xC3tu<_X^z;!=u zz+o%g2{`(uwcmgQ0x#1FoU>ElK&4Oyj8c^W7Tr%5MfrFNI{-;?MWnde3Rd(t%%a<4 zG7#>p#2`}69Aa1$mV*#_%G~)d%njZ>75@uuY!J?w>`nj zn_8aWX}iDGEHp^z)*Fk?i}SXJq)nZ{O+LJ;njvfN5?VY*A#DN=l4#!0zy8)X{m2rq zwH>VD{jJq>E%9c^8p$x6+Z=J?G+Dru{sggPYm6AOnI+N5@{Mq?7C7G?OC0PE=eMJw|hs0ls?zMySo|5e}i4jQ_9 zE<|?$ELnd$qhh zl)hL-)v3?qf9;z7x|sf=I*IP$@>AW%((iNzW4XVHLxpk4_6g6kK3)9OhliHgoWIUq zwEM~Lzh-#pDYOIA)i4o#$!qPwUZm`kjqEJ-R*CIZ1ukz<`GEtJgT9Pzb<{TW^ zm%75``S0brc`V7=0VDH@8h>#tugTfz8%GMWa5=MZWnmVsFtf1k%yqa^BV3jFGJOOC z0!oNL;ttwWj&d5n;v^!8&IXwo8K-v96KLewqL8oQu}}gG5FQvaNQad# zxoOdGI;-r?>%}kiL*ocDZI&|=YnRuzI7XH6@Lt8|BZTFJunb!!$T5yZlehVd9;$>! z0lUqhq7Fz4vl*k44iZHdp7U5rGvev%-K@Gt405MzioGp8d@}v{{?#1t0lkCUlOnd6 z$Vz9%9WyPSKDEj*Go!i~8>rS^rde)>$T^sAa?#+Fnp8rGDI-Z=&lh3!3}4wLYlqy&MEoXjZHaQC#Xmm}$| zVmEh5nR|Pz=C9c|ycxqn*0k5SJKkYU<_|32+w`>6`m@p{5w)c0>9-$TERVP|oE*1p zbxWkod6DN50?uM!O)LxhM=Cn_)ifq+vcu9Eo*HK=Vp> zigB_;|LU&A^DMd<=5aWdu4b@TnZZ8VEV(Nd4`*qrZd4N>cIgde<8I)^qZQTIu^x(^ zGC7(a!Djfqx8W%@cv5WKq%wM|!)oP^DGB;&7C3a!2muj|N*9*B{a`7_+tYC&@K7Ap zfohnHOLU$`awf-kJBjH}qtHPmbmKqJNt25+a&zGcPa_h4&9<=n$@~6jMB+x?qtJLk z&8n5oe*bXtLTFTamj2z8LXye@3reKE3{VqN6I=0xJXT|s`O!yB?Twp9HCxmyH)hc$$jWxs)) z8EnQgJ(=Gin1K|svil^q?L+Jai_(Z+(`J!^-mBAWSXd04hlY*l1asR_bV`!*tI!QY zwHX6zFR+F{h_+rrlLA%VhvC$}ZQwKm=f?(4>Y`jz07w_t6Khd5klHePYfwk!@?grVC(oGv=)AI_i~QcZ_cGjivvt|2!)AB{OCCDlV zrKD1jS|C9e%BHgjr%;m+Ev`cg5HAHH1?v1|HwI%*3;B-{p!_dX3pAfmQN)r1PzX@q z|9vMI?ZmLYT5swG!}`1e=pTT$YcC{kVdQ{Jxl>RM$!i%F&-VNipiU&+tRxQHTzkRa zCSI)uFucjo%$35m_nJzcA|tY595e}J1#~P_G?K=Uxt)QzwnJ@3PK;3@Mze&DI|AY% zCydq$<~t!LwD)SKuve^jBalD7c z!mD}lKLDt4Tp&TQzG|j;Gk2oLCmUAq)K`P4BB?8VM$>Y6(lijgGSHjZi%xf^Hae_~ z4$54uDCemjp!A4_XLD)B2>T!l35g;v6bKJLJa>YWCn$4~D09?bgnkLC#9%b~JCr*^ z#Q8|mOWrVS)66QP(X2A8tW@*Z3;YA}{|^MI(M%t?pP|_yOX7I?DwCX|85O`UJDHS^ zybe73m6LEfiOx4r8QY&6_xKE?_tR7DC)C4Kbvtov0t)St^!5Lo7pz~M1gp^Vmf!$a znI@A-cMC5mz#Ou&RY9s^$ekrOX-HMo&p+(GH}hQaPvhZtvMtgab^E^%ky z*xZpDBa?cql@Al#_9CmcF4Gl-q9FT-lnB3w?F+$-(=tnGR~Z9)6bZlsdJ$ zzqK*=nXey4xOCx0`Z6dq^+{8piPk^$uL0vxdlg(?RF)RpK<>XzoPXDE;QR-xSR5LA ze^VS<>K8Pftky05tk+FyRCM>UIuZz2DB^$PFH~V-CS2G0nFcHKZ5FB%uA9=@YGpPk z*m})%Q?2Yb3A&qfkk>spaZ2k|shIg~wX!RelGQ<)v~)y$8;#8sq`eeK$ExNH8*=RsTcA;G-1ZX$<*>LW$eB#&m@R-x`?0_ z`^6#utr|*r>U(Emi)Xje4Fc(9KTnh@1Yza%_fH6xGe6=x=oqDr;!6CC{VsY+J|2aNc&@iMUdio;(%hi zi~yxCJc07RA*d$!_@ymVLe5_Q7KRl_^g5<4$J7-(uj3^~!6lv$t0}OCV2m|QE%0*@ z8`H~GpyHbRG_|RKCVZD}qEY_$#?$7V>LaR~+?J{evKlditZb*v#~2Lx*vXijJb3J$ zLx0oypZqCk{r8xK)#5lk=w%IKLCZpC(C^;?a`#RqilK>dd@Carw-`gU zh?9SYTgoCvg5kA{IOJr@2w~XgY$+F{<4!ip@A#eiYuR5`9g}f&9d&OwYCkjN>@+N# zjgea4^VW|XuY%B#P5SE^+12JXmwDHO114}iK_6#$xyf|1wWbV^nidA2yWE=i{JI99 zeQ0=U6jraPujF1(W<D>socYQ-gAPTblP3%JeMr1lvJGkKvX_dYNjf`%7w zU73o7p>%QhxmiOKvV9xjwsdb!=iLIIe;27@V5_FEVUBFu&e@1PU;C=oi5UbZ0u3icPs5KthYn!fz!;+*A7 zoUJkcsM0ry#3F{~E!H&tWq`#9A1 zUwRV!8ToHd`0^JQrLceqmKmKL6r5xVhGDVp!4m!!3O=h%XJPX1$bAWXCVV;lm3aDd z_8@NIPZcT!Aaeln{$cPf$99NPGCH*~d18Wg76b;oC#tK{Z~o)Z(5=Jq*B@yzOt&cQ zESZzrPKgP3-nMXomHiPxd$7t{^<4wS48_j5)U%0i)l++-9^2#)z5ceIA%@Ydt(DjV z#_7kZLS<2B$=qDK05K>0pYtH>m3%ar;ccz?x`8KQP+XX;x%s5zn+WGtvZRK%!2-s= zprJ@9+&dYjaVEA|nb(x5f4c@CTC9LpuZ=PjO|VMMeL`Z*jA}_24HEn42y69GE!cNf zsYSv1<=DtKt;{aq1boqNhJ#q&-6F9%e&eHM=SobjC5kh|iT2T$wOaa5Z~9qGTlUKX zHNOz)x#x620g*oqXoT8*X43oBABuP|NxT!nG{My1Zng)IeBx%Qw*KA%;MVpv9BBr3`RlDA%lzFrXrPf*@N;FB zjl73oBrf?m>>rS1^S|^GU?wjJ50siLeTf0qjzzpuUk`ZD_D7;=A={GAtea6c%-Y&s zSDHCsZ5>QSy$zQz6X%C}8!pqv1T#$lv)(m}AnN}Xc;+v4J(0pIuX9TnWaU*}^Uu17 z*dC|#HOF4?&A6})1R-^^#&R%LpW*T11o=F_A^`wHI`~DQMSTuvLxh=*fYw{Wzij`Ma&+$IXc{W zUUw8y=ewZ`Wx_1QT#uTG6XQsz#|m{54keH#Q6w2ymW2+twnS1NvsW~noO7U%6H({3 zHfSdP4){2O^?SNs4#kcSr9Xl4=;a>bx(D@_+hiB&*PP&ElHRz-${yg`Ia=2I&qMi>z$j@vt*|`izoGnS=O}GHG&DhfQaAJ$Oq;k8^^5BL)e#_3<=R#S~LXl~Q?zBa~r-+sB& zIoA8e=^VBW+J7wV<*Adumh|Rg-1OA7&zCG`)@*06mw8V7_O%)IT)dT`d5Su%9nQ2l z&aAmg9Z6ni)_etrlQBlFm~wGtuJN6( zmF24_97WLUpZ#69?P zu;ujcaH6FIuI+?DLTSCsqLY_Sl;8{NiCM}_bPvDeXiyG*HLa{9Pj&Cys_J1mrMg=l z;xFrhvjU?C2GeIyl?wtHY{-NnojHCKCo_dlk}s>SWv?2U@TQTF=A zdhPLT_@tYlKdfrG<6%M%ClmDtw(EH9$l>|}N8SXUj`d~>IRm9XI7ra9&f!-O8OIIR zU%&+7d=d+0Mss#D7@6$6OifCmQ{G=T&7In^P2F+0w16#+Sw1{ zQj&(yU>|uEjpMWK`l<}yW+wdk{y&HN=+ZHP7UlgtfnM769v}zhb&613>ZuxM=SKdb zTFs|vD{zIH65$|V-vZlrD`P;SlqH3KdvQbMW5l) zw*F)rnFD&K>fIy{XGZ9^`MpQaQ}0%d` zzf53Tqk$;*{V<>P&uIGjIdC86zv|ATQYk!vehw9ZW=pZaK9j_(OpPs8cAZKM3rcM< zN#(`Q@0rhv`ez=8gg}LNTKs#7>^(G0h0Sqm%Uz8V?PI0s-}bl0b+CjXt@`;=9z zbGCt0UHqJCK5Gk~-F>34-$>+Sr}e?{%NwoLcw3;eXUNY$%Mc_--7d#7)?N22VR>Zy za$bOFL2_&Oz?J9G3WT0G&i}-JBf@c-{c+;#?{|v)xwV5hV*r=26h?dYE8M9(eZGl~3UQge zW^b=wiuVmZ7ngOvrr++{%2|knoSAaBvLb|gL%tYVwaCh&;{vv`oSy@nA=*aeb0BD& z@!C0uXC@nKj=lX~!RTPLv{~5{Z2;2BkU1HTQ%J|tZLIBD`vE&$(pizg*lHy=u@cE~ zP=r}0n1N=bwX$KqZ{&9%-?DK;9>I7hRpVwKqyS=5=j)q(NO(y#qt9W%-RqgDF?-)w zB=+erS%|$dbL?~2@iryPQe_;?YibyW6v-Vu+cd4Q$-rCkQ2ym2vroSp)(j|s@Wclm zkeZ3h{kyvJSc#Qgz^*hmU*jX-OZcwYA4?W!ge}Qk<%Z#2E{@V6^9WPCz@+|w`K;>y zkim9t0pJQlMebu|Ot=F7BZ=0uSK++gUn zru7;(x}`dAh2Y_2B%I_83oH8^1#`dTPwHdhhu&=ny^!;)7-N|I^105;%5V}#JTuVj zrg?d5ZV56Y!A@dB>?-zgEqn5(dyzzGa_%iXlG0wLbmNtzZmilz{o5sno#Zm?-nr&R zn5*}g#b>HINQ84{(4mHdyd6~u>aFkDo`C~VWACVXh}JX@>;^MP~FT4KTKK z9nN}l{rF;aJzXOlBr&LOE%^BqfHGU9fcVg^W1)j~;)-tZZU{&US zLTYSzVT(N0Y9EiLU)rT!BZhar?Biqb-DPbp#~q8we5~>0%onWqRqjpXf%E3JC}mza z$~3B3Ejuxip2{oO1i>Hf!eQYD6>bp>o5a1lvvHhoz++Pi^HT+`37~ z-l)#&l=HEc!^wr={zRP$r({4emx=5VKDv+J4Mmq=m$zMGqt|D*!3rm1Kyx;E$g=-b z+Uu7%8>?EV%-LMk&JWLLWvbc;NpLUDs$7RXd}k(IB7u#AG^o1@F8E7e_} zG1dFdvzT$$fsL8Ry3lxwY2XdU*P=9lJi-;DXZuKXve-Ig^G zg0;}bjQbR^ldE|St4Ph#$+d3FYAq)_$nyXddG=<_F@0$5_YozLWV6-wRfr~m^qTuI6xP1*Extrgmi12p z$=Y3yEe|W0ja5G+g|1Rf{%28P(LoA76n2BOR3v=3=FNF-7%x1{*6xAq;m)TRR;j7> zQ7c{Mp5^#8ShV>6f+ET8v2bqs;6dZqsJVbXv)Lb{WD1ytO$__qx+A~3kUF|94O-|- ze6JVzajkv)WQc8)@)nBDb?)Xzi%`w{2-*hUbpjlO0bBrDKft`(1$bvT%cZ&!JK)%8 z?z>tl8TvGOnI|_hyMm%J76_9i*v(XSCBt~-KS5Td;akw!eYxY?{gNRfzh55Is_;W$ zL!KjK5qY4^FWHg-Oy{;K|H<3r2%s*_H2xD3Uh{Pv)HZJ~fTlsF+FyhBNQX#Sjg3YI&w|nvDzDP zt~6%Kd&_#8c%TLgy78U2I@qGo8<29qUX;Aa*L%%F@Jg0-~g@h+kv zeQkZu3onEIe&e;BuMbdSE8Dp!8VuMp-ZJ+){v@-rd(1ZI6*h|MqJ1wMGS87Thq)v8 z$sT$)z!79e048lJBc7mZ)Ew#?ZnEE+&(fDNNo#jE9H6N6r05`ftcV}aB z3mL~JQ+J+X?VeSFi_wPr^8X^Puy<@043t;JU3wA-Vkq_BfC#$iw+ZoF%7xBk<)l?M zkF|kik>h);@L>`E8sU!@8WT<}O$< zgo91J6YR;;%CM)hAQZ%&ut2TJCMJd55Q}xaNAV69^>#$mPK^~evp%4Nm3f8Cq%kmQFH{=CwFJ1M70)J7CpR)eQf)U52+iN?FeoSeY#l ziILHEuB-c)@Jc_O>jo&apuGQmm6&0qjpgj$e@vCsKVvq=?c>M-6rN5F-qSk?#_#e8 zd*yqf)Mr6}x4%C>8JSpi7qE1@Rf?qA{YCV{!%QndGt4x= z$)Uvnx5d67NK&!FYX}^I)w+K&b2i7HP(@ZsFSFaqor2sU5p~;W25L3%X9GTz$4Ej` zFw2$RmxpmDusZ#ZnV$5yh}95sRdu>2t}H%s2CQekflGY6v6gEhGLvBz14W222m znUHV{T%LnO@y)u~PRWAH>!L1q<{W%CjmC(X6<^C9C#y(^SA9a4T4ONf`JRGiD279Z zaG?B!I1Q{5su!J-s|BL9{zwi(zc2kP(Eh*1M{bmA;-&<%6ROnkQKNscTKa0xl+d8* zxu?k0Uwl=poXSJ}fr2P^39<@I=5}-2O;(irCK~B8erwfMep}3M;P=ZkpX}q4sJ{Mr z0P-WXtn3Ad06E7XMf$yRK56V>KEqyNGbx(W2OX+hJ4!1vh3;lKFG*?c56y5BM`0h0 zs!ZwYd+Dm-p8fi>rcXL(-VD3*J+!7NYH4O#L>vIGE(Saj>uznq!!0LL&C7<<-F4}_ zDbW~8pG~e>)#?=nc(8oTjQ{{tuPa$OYS(2X=f=@&@+MBo%V&!|3#%wChg4T9s)&Vd zYRznS#u}-^7S`~_)ne=6XTv|gnwm?IcKeDDw@TZo7zD^r zi;B6H>YXw06Jq7CCF7Qtgr7t&M#eBGiUf zzMf!B(jLoyg9a`%Ct1)rksC=tGPIOhcO7Kl@JFtEOG40T!Ul+pu1( zdsfq1E6W6_Hi9*CI-i?MetSpeK@IKnpOk0a`b<o zmapNnnOBuAI6=Ta7KxWy^8xkVf_l%1KNH-CoMAJa}9r3Es!~rmH2&3(uInK+Uk1rylxa}USgorCo@g|Mg9zZ{aT25FC zD{n~~>&Lh1p8>sZjXg9g9I{`dkIEh#8@d7i{Oahk^3hiH>-^GZH@;TrzZdv@>TPQ_ zUS~Vh`J?#H>Z2D|z47#;lkGmV`8@s{G5b#qpJmzFTlR%O;Fjm*6~#Uh_A+D2{-gNq zrG}vuLWQE{+I=jVMk!IFF8migzdA$fXiqYP@n zEa+X~4#7w(GZ%ys>_2WfAS4}ZVAh+$La>y={9j1M*wBjw){yjw6!kMmleUE2+m`=V zvp=cXldgqvYMG$h4I6SKO}I`Sz^|FiSvJ&K>-V8g$zOWwvu*H1La$>PS>3|90Nc~m ziQboZ&v%U^=6PBL>L5tRui=FiV>&Ct2Ws}O zyLQA{_^j(?^wXn)B6Wg)VhJ|VT^hBXhYRYwr7?bLS-vDnxVETy?Q-kq*e#5pv9*zW zjsN2~CK7$2IHQ-R6fqsD7#2#P|La@)zo0T3@F=ipzCc7$4UFaHP`WypBiFT$2sg$? zEE$WK|8n{b7@Om~&6L>AX%({Q?eD4<4d7a7P$Pm7bNha8%qk5fyrsH) zP@9X8Z~K(5&AYv6Z~9bG)-(q<>+Dl!c$=ELsp6$@>U14RZPSV6t~h_JWM5v7m6~&^ z9#+#@^MHQMp6<`insnV1D?5N;p~3%j9=;fEZCx~irQXN^C;I?7UGsOs1GHsDEc;A4 z%1z23!BaBtp5%;a0*^-qW*yvpPy#M+WUn}BbbrRQid_d5@*gzVwDO(b!7X3AS%UNc z8Me>6o&Gt8oZK{<%{ibmU@l-~jpKbV0SmS5QC*1lSl-BgjMk_OX2*-k|ADzoJ{Hi= zF$OeXQSjb`7uD3yi?_{O#;bUZh6T6AEBysMY;m6EMMs>$A%|2KSDR|Fc?fKt_!U1%4ARo0`I>>Qtp1tYcVG?|&zuY2L()|{1NYPFN`Tk;S9~1lj1>eY zyTs`VBJYgS#9CQJ3}8t(b}$^I#W9R9WDZZ{=&@tWwUwCvB%1?P+H-4iMyWHikuyiA zTEW}G_Qtb?NW!zHb-znsx|JCMO{UaS7%LSem{&|~DLFz=Dg*NsHD92bI@PmhW#1hl z2g(*5j#T=Gq0h)YT(Ha>0E{>kR}_Sl=q}{l-PDreErm+jWFP(7;(2!8DDR2sERMaF z;onjdyRNt;J;ih>6O$X&<}BUhv32th>|}^~_KjqR3T4E|fd|vjNIqi@Q_*Xq1h*6c z6W9*5vc8Nj`hmfkM&OspbM-HR`7RX6pa^$mA4{}*2oW7V8_U1iZD_~7Eqz5WC0aQ zNYjIvr;owGtsE=nN!wEmEKGfvc6MQyCg=!Y|7-PPP} zzZ5BYqv<|AhJR*QV+O*?TlriDqhHJX=nl39A+m*Xkzq(&O`=xDJdYFjPkq|6zoaomw~I7meqag*H|Y4@ z{X;oR!5_4G>-fn;ydP6ur@#9_gEGxpnH$Ci02rQqX91x9`|_+Qem!NyH{4;2{4oB{5$+lb1n=I-aCl7|H3u zB7@ADA~K)(2r{qGRQ$kX`as)$B1(QH!hhy3t&E6bp8cOH%VW^CQWfQ22xIF;OzKNa zI-dQLBJh6`!`nM>{^Z$v70HwY7(Z*`x0(3go)mwZiQjDE|9VpVOcVcO;`5{W4LoWE zJwc}9=JB`K?BVJv2GAbZhj$A~MwwpZU4RRNkhTQP{%0_cVxBOCATkAp?p+2HxVKrQ z`#gJbNwMU`DhV`ohyNa(<<9(2$$wVKU{LBths>_-6P+cz0K7q1p5T$f`0n#>-)y)b z0!@?%2=zA(d_@+6N1wxNJSt3moSr(9@bZ5CP6#11xATqQ; zgcQl29@-$u}w%yN6TFoq4oBLNV z+;tIuayvoR{`pXDi`sn{3zZ^J-RH<`AlC5Y(uf}KxHgviGBHy9n?Vs;IucI|H%&n? zAC=s$2?Y(z9;S)-@Q@jPKsi5!u`>ARoWw|9Jxk6|ULtOI+MixZYRG<{=W#Dmm1OiD zeTp54u`Y4uH+r4b`0=JU`-gZ|oGqbqLkv`_oog!js&a0StFyQ>If}pE7dgN==sZtE z9ZHvKXHglxIcuG-mm^d;-T6mQFv?BlwKBrSBgaYI7AY)j{5(jZXksYDsM%jXgxkac ze9~+GiR|H7SUi_r%X&RPQuZ&y%@useZN%5EAFzlc?Icmh;BIiXX-mUv zT7Re{owI|(!QL>Os>de(-J?kK>Rsln%Qj{A*le+4?!l`KBZ{~5XaLxP19xWNFHEQ_Nd1o4G@v)`_Yog{{%DjC|g zj3ldtd?zIGR3Jf-r;*2<1}JETa{q@vbX;H|g#8_jZl)J;OvZ(A79m5^BL-mLT`o1# z^Li-ZOcl#DbU&l353IQMT1kXI=v0KX$q74I<-&2e`R#hH5MdgX#@wSsoI*?X##3#JFA?{f>kfJ#>8f5i z1PvhI6cnzw{5|9AGcJAmcZL~msrpc!AhTL?XX)RxW)4wBeCY!Z>tyP!=FLCOPwpPB zRNg0iED`f!JU1b~Qqh`yrFbV|kQa2WYJDMJ5_m$)=op;)OvItOYB|Gub^g$qX23afSIbqxaqPr`>iU$XbEQ8k5JKG;5OGQ|`14z=Cy)o+DdbAjUWyaE^wL;%@*Ig%>d=##W15 zRmm_@5}^fd1*v5nW)@?{T!>hXE?hq-*!cASF~z_(Mntv6Td zJbUCf4B^J8mE=4nc$h89b7S-LG8>?$Tf2|~B*b2?vl77h?mhnY*QwW?Oh#B&(WyeT;{gWp8%Fso;H7cdoUFKhO|)!go& z^$j>uEE+KL9N^mz)+AeSq)1)y8b*(m)r3|UPUDDxlok0|?#y=WN!@gtvmYRF?4E-$ z38^Z$wuJbi>Udb8;-Gr*Apnt#A}frgp#U8@oIQZszM1V9@4`MvJn2W*1i`A(^i=?< zFgmmgczCaS?fZ7FG|(402Yde%#iK7~0|&XbKySz4;Q!4_Ur`lK zVlsoeT||3aceB?yc|XeXX=vXleizzKW+sV@5e{YU~9{=ecGPi*UKBkcVy)Omre6h%DxNJ4T*nHX|NR3) zmu_Mow;V^1V`etyTR7uMV2D6JrB!oPZW~u*rTxouqQiEJ@ zm$$LdslbWwFnE&*>s!?R!CdxjoaA>udDFeY#tys}a;4Va_oL$EpZg>e1B)JM@VrNV z0h9X6Npzkz0>SI*0h-4<2HaFyR@JHI$IUEGiO|{i%d?oRv#RpEgj(}x$?uR zkcOTP#wcn$`=Y2>hQq~X?dKkQAE}*+^}#U(=@^BDDu5L7?`Sbg>MAe$x*+#@j96-} z2DBsaG_dIE zUDe=GXx{sHAlAC^ul)L7qL@>c>tV{Inq{HX{g`-mk(qXw^{|8fg5~lMTkhP~kvtB| z>EFEb{!mxrB@PDp%8G~L9yi_0)n}Zv;KFe?z(Pk@K{#)&3uBy6=9E{ll=m}Km|Fsj z=1Z(>oJ{z!7|T!1o2aSL5FuD(7v31&OQrr9R02OW%KaGe$R*>$veG%o{Wvx)p8*=B z8qm8NYH8u3a_1@S}5oI@fr2a!7 zKL<8u^{Y;ersXv+5*K`QX0LKL6`l#~h^6~EiGKcXNSvVad27uj^k;ytx1pJi^uJ0k zaUq&SZ^IPzY_@`Mkj0;>MD3q~Jyd6ZG6rZaDMY2kErUbUCM!9E_jvdZ0;3&B@LB3} zvQ>h^n0Q?KXaCp#N^7!DQM$Wv%2hYUt!%Jk;)v}{x^I(Gx|&Cg;vJt&&k>$zzgE)p z?8-mEgjt!wpMa#*f$s_$0kP;Eqy`6j+m+@VscQKaL`9nOwNxpGAm3v*wsIYfOcyjZ()|zWzA1sWUPqkV= zyQ}%rqjWET+wsD=W&q!jCgk*^rggHf5b5mn^_Q_{wtR4o`xdwuJRsN{d#8vWN`Ioz zA-|qj>=07N)E^jU09sS_;p2ylC^b7ZR8toP<3*~bF3O+iZw>Ndvo&fUT&MGAcT*3U z7~~b9k^2fPRNOJNePqYL(*L`1HB~n;w*#T4vHGX`V3n=kmt=&2bSsF+{fhi|6A4wg z=D}v+L%XX9Y+}2g9CU--6;ip*9sYgsP5Kn?2kq?EbH4zX_k@B-l=coul++dIH3t0e z-!CO#`etVF0sprf>F!pZJg_qVO9^+@f?{(Eds4U$H~P6ACAMzsZ>=N%ck=8BcJArX z{eklKo z6G%YFhj6=)?OEBAvq;pAtG=f=OUd!T;S!PYQ7-V2_KLf0EnUDte3P*?9??Hp>&ejJ z$%%04OmDLGkbZJBa3(h>c;=}vtc;SY)!fAw)4+4w&N$`Ib-aTyOV6?2S-bonZGb*30`pK_e;uD&OT80pTE z7-nbduGXtuKrxkj>e*fE6*H9jxHq|67_EB~T8>a?|8E0)p5fPBJ)dme6RXF*H>9*J ziu=)A6@3HK@R{W-7o(`Dncs#^Yg!&npQ3j$7;kmoAR`+hv?R=g{&JODP!-GXbq35` zwE_=$PfRL%Z^(b=9&S_dv0i0GN+5P({_$f)-&kC(S=YOZZ`k<%yI^?aW z?C(;W_0Rj!W=5>rr9%TZFT( z(*M+WF^PBAMn&S~XsJ9YgauiL<467V=W6tHzUeZZ1Wk<+)Lo;9|Fg8pcK#fulUAcx zpy%SCiC&R~W?_bk_>X^~t`ubWl`1rimxAI*Z|26;dT^rB+B_NuXGG)fmP3FH9V;;lt zpOwiNI+LSA~;|IdCRJznTP!+Tz`(%We`RIgDO-euSC?_i{e ziPvy!Bnk2G&HPFaPPpwRI)Z(O+_3V~2J&%Vi!z3+~##HTGEdo&k=j?fpCtrv(fr?NyaW_KDbi=V_x|=j;Wcy7QzC zkZ5V3P3R;+Ai>gyofw9hV`K#q@%OSi0I9t)S0OpLhK|`*fZW32ZUX;@Luiz+hSbtX z-6}?^YT|cEY*8iQIN`Fzr%_oQm^3&8Bk>*Af#eWXM4f=?ehR0vN`7(N7BRYKYB+nR zcpaG9<~BQw(KjwL2$g;fnKsFtUO*sqaj{++p{Fa#tu_0AXRYGUNK5uO4;I&RS=u2~=56n<9E zO!83di{@$4vF}P49b9FE(PrwKWA8HaM_@1E-Y2PJWe4d(6g~ID3TC=La!hD@s|yT> zT7_xPQ%fc9uer^LzPk(`Fa+Hn2?_>{*YxrrDOt)^PP5-1w&D_SZT6BwZuu%*f#f({ z5pH|Qdrqtb6$cK;IMW6y(J@}2x8IMflkRmzqhP7d#&C3u{r;LSbO*Qs*0=O|D5CyP9U%YL<|}wYS2WYCW=ZV z)PUrojgXeBciNXy5FVv^j-UmSxK9Gx-2-0H_OY#PwWVUgS{1xOfXCl|qNB%E{Hq4+UEhUN8S>}<$N4kS; zjW}Y(mNCcA>M-8lB3-V!M8;Czo=(Ot_w#m3;Xp;>Rt0=wuZ$7*Wt{f28R!pTInuQBR zPX7vR7nUkox6T*p7HO^#TE^{9FJ-vA`Wv|lRPF#3-ZQb9r8)h?@{I1}&UezK@%0F( z@=%Eq`SyxF(mTq~TUcN&f)@Lz`bXSs7eBFy(B*|~`|2wN> zJx`3nFqSMwr}}8oQk>i?hDqMHS+KP>tkQwij#K%c`kMzl#Pcjl`@!D|NWXnNJf|&m zKJ|v9(n9S0^%!=(`GLF`ckbXX1J43jj_b4A4Kadd_&9$F- zLr4_0+M4C?M8e)L`JNng48PR4dv&#T@c+`mjG34ICW5_;7l7xG@H!s-WD9sKP~2vb zI4d0eSc|Z@pgY^CNS;=sHP6<`n{uuFCppkwp0)$ydwJ z{~5XmVx%h{F-@y<)}AW41gay`Ksbz9z!$+uo15bBjQ_W!fU^x5$mgl40bs>+SKbG+ z=)+0OUi}vm(d2NdWkGNB>y;(XvV8y2X z`|Ac+B(5D3!LX6O&tg1z11W`?A`RW%E-CXRqIl_i?_MQP6L-P2i&Lg-zTMb=qqX4t z`xY3p|7rjRYyL}qc}|=2Da*>R&IQZF?O zV_QZ_EjPXeNpm7c5Dd2M`iP9k7CAaT%}J~^^iC18r=#+u3M;k&gct~u_-q2ms@^aB zgc2Z`HLvhlPOk4l+I%Q8IXAx6|lN zvdby$FvEuV$8Kq0RC7X?V;^d;YX7>Wo`UwFdJb^O z#^d!N=f&1{!*iW!i!-P_&)OVHds>PF+wD#YY<*e_bk&lnk(o8EVAjgLw54zo-*(Q%Q?3hT-JUV+~@?iaT>+#Jrip1)2Lw>WR_S4`H^lATxywmqs)!h77ccV{vLpD35QmgNWB=PC#xYOK6Z(i`en?qA*m z^_Z6S9=mAS_LtCH_)&9|{EyU>Hn#l5S zdh~R+DraC-b|mB+!lWc#KrPnBrec0t_hx6xCRra3oe3{+&r7reC-qV@%EN{%@=Yb} zm9`31($Sm3l4Lo{hZT`vf@phjw(~6PyHJ30>NPW1bL2O%0jn#VOw>bpwqUZfJ)>ah~=;bRY$DYAB5AAahp3O zQs&(tB3KR|^m&Q+gdoA&hLAlMB;Lnk33B_51L70Xr0kOuf(?g%0H};`4*f^;AAY?wk)Mp|oWjD_CEw?8Ad2MYz3=M%@|3 z9ovJEbL`DIP&5#kNK!FD);uX$8H}o}xgr(WA9R|_iFnh=WFO*aNe|Kwp^SSEc;2^U{ORD3#y5a~yF&N@ z%y?jpqd`m_N_?E0d*zdRue>HwAuYx%YvYU9Z{^{bSH$&- z);-ze%xo9RIL$)2Xoj;!2$O{TQH8a!#XFw7&IT!w1Yk9>HSccI_e+2m@Nl)qmUL)z zEd6kBtDcGtw>w8JAL2BR0h+U79)&$$;~vdzd{<4VAI>7sm7CtFD&}l9ansC4g zu+jdDcMP8lfA~P+P93vI*x9BX63}<@aR1rqY7{)LRN#Gc9<}NxF{vTHrwtiAiAy=sv zY?fBTqf&0URgWnAu&se>bo#HY;S1dX(#;Km1>EOKdvjR6Mr(93GRT^fUur?Rtyw-o zzQ8EyGwz;8@{T);s%C6MLlFoJT&twxvV-&h0bJQ;1rze^H0KN*MeoajNh5yuM0ygIVq> znKewlu%iRTT_gFh5ezRK!O03%ftov7?YBlqnHc9*)!Y_hr7+{J%WXm^N-k4p&T*)hf7g)VFl6C+Gf+A4t(isH-Ki+OM1o&&{%6 z$v+Uu!VrPNK1~E(wp+#M4b_#kE`=!yt>s_u@b4uRy*A9=EG0w2KczdQ0dBJ{uxoXJ z-4~f+FAEQdPQna}vsSEnyCa!%$N8;3%X(yIwm&WOL%+F*Z^t=1t&Q4F*bo!wBS*IH z=Iw(F<^KvK{*atze%q6{I@(v{T7bS1v`(@&3(G(Y<7x{AYJKPidyq`6;35)q%9@AF znQbCB$gT=Y`>G|*qarQIDP%xw)X5gU`g#6-Zl?H|hPf+6VOP3);7U=j;A)F}yPcin z$wE($`ZD^S$Yf_P@MSV8DWMXvAT2k4f|0AnVPSmbT5kG^fWdGv{c)e{-XoM#L27qo z62-=pO$l>3#&(>kO1PL`*-sZbI@q7W`l4~WLT;nCO#s-uF_s*N+1L&|pE|W}yo)RpMERLFNJ+_@^2Ta;YJ_#qZ}Fs0%#;(LrX2W;{lzLq;9J;3IFn%GB_O$8^80 z5{3tZ!d+P*<8-Zv>SZtK)xJ-#g8IaHkwK$};W9?zrmOpE+|pd*Y`sc5SD>1KKvI8N zE2WX*9*a7iovEYtaeIW^oj+7^zha&p!44OLm+73rF>Bhal~2)Gt}VXU+-aR5*KU!} znA>}dM2@p-DuNvi57M4sWKh5R`GvCPMYeMG^85h9rrF=kTwG(tsuY-ji06n3TrU&Q zAsof|br8;Vwgq2xr*oO*4#|P2Q0Usv=2N7myX?j2@y^yuI3Cp$=A394%I^q7|H+8_ zz_lMIA8C2Cp~lfz5&lHelYO6y*_j-!h0O2q6Kt-L#?t3&IgE2RKMr{?aXG_0%5}ve zb){iVZlevH$=L6{&$C7+BK!@W-(rx2rHR}A!Z6&dLkAtt#{WUl#_tw>-RpAMndNKy zkF&RlZHBp*^fv$52#MY&+4q}g{>J>JRGAFv<_D7le6+@tTT#ym#01T`n=s@}i52G8 zTqs371&r$^W2Tu-RN&sv;fZ#fb2qFZmEDW*Sx$ONJHAVaD>>tm<$;|^WKh|XTzT*y z&wPZ)QLgTgjnDu62RbrDzm#wO!9`2g9y?nfp&sVW$SbSMiuP}-2unw? zul1m9mf1yJ485$l>c^iFEg~M1o9h_7^3UF0(AHd-jI=f9_Js11q0iPi2mjcBv*bAi zI{#$jJ=NU#j-WFoiB6JPMbC_HN_D__FLEfui1VF^_@izu7h7!V6cV4x_l~OJAx;)H z%W@(Yao9fjm3aHGqf<+^{7b=J53dHQI)9)Zrwvpimw|fh7yYl^UT@vu_l+EIyUlXE zB&<|D%$gr;qD!dw59CRd*_&&nQci1|Wg5F{WJs&G+9U^}NK#Cdy~xbMQqb z{eG;lb9)K1bAa@IKO+a{Rf%^}Ro%{_>dKjEYQ<{0kCEx#BPhpff^L(v0N;sDT+&m_%j{EuR-XqI26Zcg2R*`C~jgN^eCPK!3r||*FaqC)i3{K;Ngn2OYkCNs* zB{5kAbV>j9-=v|}{2y)T`(UC52J!VeM;PeU?aZ^u`PiUu7HoznJ=vEJcXe=)-g)px zdCnRcY0h`@Wo{HugeLZAL8hAVTFK$>Yb6gdXqUR11ow^=CxdWWB$FZ0Y05rlFCbo} zqgm!IDA})_4#On@cAM^MQI@=H82II^*JJn)AiW$jg)uykH;ULsk=D4T)O0p6dyA-5 z*o@p+fM#{Y5{YCmDl#z3zC1C>of$@ju|hNy>G$sEZ(BpBj1K_U5s?l-W;K1pzR1e|#T1cY@L!mmGr zSBN+%V~V?1-Q6psj5nDQWT=p8=3~Ar6{T+!4Be`_?ae0$1_-M1!$0?4Da7zfpIEfj zxwn%DhhKbfX3TbHs)k^=y+x7(HxIJ6$fkw~+i@bI!oFlW`*yHMev5?VJZ?S-Zq-7k ziic#lyhg0yAK4-Z=O?QL!5Sa|gpe3;iY{-gr0|=v>MBgeRS8RafyCV^QBmM5#;saZ zh7#e15pH#{BaAHf_ae_*P0!O{FP~0gU76&dgwqnWVz?f8xpW5xVzoDBBVbIzDK?&s zC!;XABv_6@!J^>e;pJ?SW#3YsVa1LBu&X_CX2K~SV#OMXEgpo+znJWcJ!H!6@?0x+ zKE=vMTe06s;#DMKSKD}q?G8Lbgk=8-W&8~tKo%`A)3~hw${<&=HjMAD;mo_^I;wJl z5q31WTu6HO0ENnC=LT(8L2BF9f5P*_(BP8?D3VTIAbOC|cRp+`wn~hcH@o zr3N~wX_Bc4QWJrORnqBciQ^g%b@4em)bDg^}UTCg;$ ztxEbo;5CqAeygggFomrOdDjaUtuCe=!#Hn?i7`F%j_W{8(+M)U3q&vc0%o-Cnh^Dg z_SXtz?s8U14DFWwcD#VhAqf$S(gi%{6V!picl`y)v4X6J`CGTsE;^0QepV9)Z4%oP z5_jN?B1OcC!6CXExmMLciM0*1zc_w}gps5;m?-w1;d@7QF}?gpA3ze^Z-`kNW8aRA zR0+Mv^vs36*mkSOD3kT};~`fvvJ0hbU~WV!1rBR|A#5{B?fAp`%!0eKE(nJY4e zbIpo5I);&{;}fK9PA6KOi^yp%n%335z4;v}HrB2juwX}R`joL{lf%(# zIp)hvgT{zoGeXwJNw>W>XC-wzeZ#AOGYfKkxRZC^4`Zgw)?>t})$tf@+w;t&}V4eP#cdjhRJ)p*< z2e4FWsnQWyc)*&~dcZ0+j-t`=LdaSF1{FldfkpwfC(dR^neJdBOAjU$aOOVFXP_8$ zTN|f69CC6XnpuHtlf+4JEK}miB9R&lZOxAWTK;(!B7BmrA%e+i7wJ!bm1RVRN@eEC z@3Wx`74SKb7~WBRMp&KG2zOKGG$#|#d;`G7lMC(AC8Jhy9N}xahBWPq4$?}n9IBcZ zpO>6n*6M*Wmf&xqxF$m(SLem)Ws!`BaOBuN7(-2}33z|wkLI*uJ0-}wb5XVz^H7-T z^q^AJPXf?KDk?ph!7Fr;`H-m(R+obcy}n9&UB-~l+ec1eZy}@WOC2w*H-!Q$)$x;( zM3%BX6g@wcAvt3Xb;YM0)9v@jzbaEbGENJBeP6KC-lshAQg?;&L=`(C7b=@8qtPV+ z6jf#*3}!K#sw7XMV;IXkpsFj~)ya{e{c%ej=jpXdt!O1BCTP1-BUvb9W|D>8Di&Gz zWH_HwwG_tFIU8sLd`N7fhBYPmjubi@)G$TeS4MCe`bnhPgm{~nQU#GIAB3b zZF=?Cal_rZ{K&}-?`B82<&wjl8u8QUFGX~6N_I&M?9Fj*YQUZ1H(cBy>4+P~nwSfj z`Z5}A?N8`9Hc`?nA3ZV-*2XiMYuN-(7Ec9mvXKp&RaT1*Pic_xw%&)imF`RQdrrV8 z;W-gPg2>b=>crY@bB=tAJIf%1jGl`e(;}oTk6Q>$qvYHpPKT2;n zeAeO@tS5K7vAgzjCXLg8u|cUBCQN4LnRTf@;p_g;~lon5?sa45U}@}ix3{We}<{q*1=R9BH2n?tzo zCdwQBk;bcfz8Hlkbboj!Dh`r9d#7y$hntft>cp=L=b z(y8a&`5&O%)ECO#eV|;WP$VVjL#ZX97Yle|C{mD=+VLyFgkCv%_AbC^fVZ7**F4AG6CrtU-;q$3?BW+RB(GJ-}u3P{ze8m1{dWk zoBy5yc|{@YhOy@TR-~P8pxAAEQv}LDfIXpxH&N1Cl>E|*kjYF!BojG1&Fzw}rU$y; z3sJ-#f9yq%g*D&?CRIf)7IoeTiD?TmRyO08?#t+VB=v1Gz@o^5Y#;s?jfC~&Dnkb5 zbcX$DJv(me$u)125NF}J$yJm`Q6#p_%9hwa?HyEpNG?|N!$1& z^<$c8A5z_G|Cc+{Q}Z-lb*1?Qc6PF@FxL>ctywS&G)wi~G*Ib_Bu|-3it<9M={&-C zt8PHvX*}{E`6I)`==(X@vW%BM)?_@=*njEfl~QN@643I}zYH+;Dd%UY{wTya!rMba z&yMhAjp%L>MKuz%6>E{CBNdw}sK7a3P2R>8CJ9zuNl*P;?jQTx6z|?XknfkZx|sx@ zLp(}>M25Rwe(lYV^Ea?0?DH;B01GUU1g7*tb5{sos43G$YAHL|5K*u>8<=jhKtM-$ zVhy8HBi?a>WEHmMbmjb^BTO}$uoKU>3kR<(qP&nSxJTJUuX z$6dGR#_bKu0#@{t+b#`ir#BqBkS8;&s;y9_PuKsNeVn~5E%BGW?La4pEue6WP&8b$ zz5(cojG&f^>tFLLilzGd8p7Ue3LFKZY4ZOC#MOO3Q{Yy&UK%4{ryoyGs7D{H{;p z^lC3ol}V(|Pl8IkrMqY-yISgpvWiDs|C(xY&Hsy(9(O&6g{g*f3lTe$jjJ^O-0!!p zu~o8RgVuKuXnIY~BL~Y??$3l8TMYz>&&Xlf#2mU7K4=~~g=xJ(vh^((`#CAJsGoD) ztVFtd-K-RU87Cy5aKK2h%_KSN5gfp5JaxeWY8=G_sChq9v<8_j{K zHTjCfnY@){-Q7wuVnQl;QlcCta(pT(GD9dD;*Ffq{**|Z0+0++)3E69m37fnrrnVY zfBq!r&HPV#=gnz^y+W{*uF*+NPsyb2NB??O-w%jHV*U29l<4@EusUITuoI66qJqe8 z50D_-S$;_h>K4&!@0tSQ9OD}5uAUkmq353tb{KWT}n>dv_y#1p?8a`ltS1cKvWbBD!YFHJp z?~x@S5k9!vStFtUu;RRfjiGEgt=OCBp1b|ECzJ&qh}3BNEmLdR3@uj z&S$$Fs-ETb*ChYtu-#h;l;obpiv3tXRxPRF18rQrkf@Bh-pz@x;0>CGKuBeSjtVSf zeQqw$E}#SwH_~;F#67?tm!$BV4~TsQtJ`#O5DEVa?BjhYoB;=tFCtx|#2M%pWA9%38-b&3mA*4&nd1w(ij!f2YE|g9CPZ ziKBX&tV>`#9S1;LQ!D(`4vy!%Jw2(5{M0>?`XZ?-S1ke~Zwo=j2y6ZmgzQ6E)`~|6 zxH0$RWL5L84+}qaSI99z`UY7@L_gE;oGKY37h&H)QknX`iJps87#YH=uaV>1nnZTw zzd&LnMj^tgi_OOfzZ}(w{DbD&ad{m}=B1fs- zNYeaiF_v^;Wb&)yld%*XlH#lr7J&RcZdv@ci5ZY)?e z&8?coOHY|lTnLvKtkVAS{?Y@)`RZsVcsV{6@Y;DvQpj&=uEhTJ3Ej9^l15sq4UvP} zvMC=qot15qKniXU8^*>h^4H%`tdO9if4wKAI63plS)@5_&6#gq+Be&3vibcXl8y9- z{Py%m4+X|0PB@w%1w!qfp2;gxu?B+BGrfHf+#sTly+!^8ZXVF4nFxZlBsCCPo=lZ+ z>Av|%fhr|Tee~gxZUm&IAA0}zXNrv>J>Ljbl%tC%eFKr(nq~Iiwnm)lv^6i}FaKdI zo?f07DK1ZsjOBnS%X)IF_z};eopV<1wD;F@rV(sG?2NCJLl3L6HBn3Yo`!OL5E2N9 z@(b1o_#28$@n+$wYoz8;-Tc|!EOiCWkc!wnws!X84j|z!P4~_RUG}MxJxxJa8(LQ? zdObP4VdOb_#so19Bgo=guN{Ro5c;n#){#vWH?-O93 zBQMBl;3kQw;OvH0O2Y3*SkRIi|4Dygd-lzr2jUYx=K2cBsHnF!e$)sQxh?tmBo5A> z!v4jJ@NKR;>3U;5`HEs;@2STT2*nd;C>9zQL=q?P=!w;IkrWuUpJRy5?BoNo%|GGu z!Rq2bZ~|h?$z(ufN)mHXS$&J4qJbnkMxAZ@OI_GmQ!ZdL($~wce=KAl$@Evn`i#u2 z(eo2|_K{)r0|^#y8UXI#aO8w~D|2fk&)%04^mj8uhz{CxBA<)QQ5&1~4|)Z(X2RZz zk3nsw8VLsj(f{%lyQ1_$)n1>~rkWm5LFqkSj;8A^thU6SPdX|{LgQ~GB=(ny68SWm zVnZgm2}F=&=HvaX#)z$+<0ophn~@+b#$h=d_{mc0~tJZJdtfL$F+JNAgK>0+nbfVkrB%Izk7aHcZXk7 zq<>PO@17}#20R@HR5^QiOQ8GWAp%6Qs;IB<9V+E3L)gyT&j$th6HKLqD}qpVG~&q! zaMfDCO&Onl;AZrbqukNeW0?1I=eG=dYp$r{ut^O@%aS&!m_-ysi`5o&2KrId@4g|b zuXC|B?(SoV+G(c#1$z7!=tiGTG~1hZ3c*Ba{bvG>I^d6`8oOqSFA9RLz#{ z%SHHo(rPYEtV@|yTtVl_*b{|!Sblv%!3E4iZ*x^|oI534+L69mP?`Tv#nIoV%b{9l zRq!Ko=ea6ep=b5OLs0<5n(Y|wqUg^e`ot+1xDhms3R_yU}>!{?up~i zWV5W;XMkaHs4t35NJRBSRtqGV8scQZKe8*{$?@vNTirE}lHX~T%1Kzcnl{*5mXaO4 z!>vS;b}Nj~$V6X|LZs!5VdZl_dww&Jl2%y{zi-?V$GN$!Vzxg|cz4h&Rw6ZmQ3U}YLYvW=+P9~Bhyn2Zi zysWijTLy62N#_4zkFdN9CgELHY%TTl2#k~4nx*IDU&9BXw&u^1k;rLov&?;W)%*Ol zHrH~Jfo;La($*r}j3~8R4-KA>I8nxIbe6mNN@+><+O+8Bn(|L~wREDhbM$%v>8$GH z?`W+{dYFmhG=Cu<3{gaHq5+7^`wqEn&5~FCA)v1j>>P#R4^4#gTpp)E4{dL$p@u+o zgsbYy3P*p&ttcebia*RJ%&f{?e=u#BMe67XCeiW~hTs2b(P6vxIUnu%sCNWdl^@|$ zk8J)J6nD&DyoDO`pZJ}@iLh0*UB;w8G!}EN2D8ge8cpqCj7CzkMy?3+vPQ}P>Cl_p z`^OkIvA)M*sui$26}L6bTY&F7HOzY8C8YZrhJq>t?IRa@pUUEf?NzD@UJ`ndb~Rw9 zzr>m-PuX0l?!ayr3&#te5EHX6Fdrj*zst4g_(nA^!`RaNiebD$EX#O;oprfF1~d~| zZ_^Ib+V37EFVz;2C>P`%3Oz4{h|_YhvG%Qp35eOd8q=9&7a@eUM9#-bZ!qA*;Y|2y zeLK$HR7({+=IP!p)_-opB>v)`?RKfzZ4gWn{jlzJq!Cyb`{wkR(qq^6*PQ|t+u|oK zLwl;0*Z6*`$;D#kgmI0sbBTnSy&};l-)ORd;LPXQd1S zqXph`@}WZP)<43vP{^I0&Dm@BPBmR^lJ~0;yBoViXo&WAFYrDkcVkz&M8obaA#bn7 z;bYJzmb z7*s^rSSpo8Fd`vwXK(BBSDJrrTXon8Qq9d^?{q@#)J@2v2)~<2AY@bX1mY-{oxjc;bn_EA$moN|1kv z^;f)C*@u#TS2kkXINRN@R2sT3QiwNr%&e!lyb;q<)P;D!qbi^uBv`|4q^siWN)zPnqtb+S2YK{9;KxjQeW z$Tro~{ZU5rpt7D3U93DOIkF!@J|OSWBilp~K^VExRweC;ZiC-pc;l86&;GbATw8%r zW|CH)ZBkl!9S}x7A)WB)3?b8ddMY0s4DT>z-2^z7zyCBHIN?Mv!gYdGg*6C$$zLm` z{J4^*(L;zR*+9#JXw$a+{%>Wz;uxVa z3wO-mVek3311PCvx<0>CFl2gR;_P5MuAL}`2VDWcXG#)EzcedYDOsFLv&LPD;fvyY zu!2E5UGDA;<>Qv^LS1{2N2q}825$`)2gycWNq>`Ia3#4p}9P{~Eg5*bQ7 zf(vujmzq3`B6y=aWh>v8RemvEIy7>et#-bFh_Jv$~U##Ix?|Ai44$^-a{I#z`|DpA<~5^%77c+ z%?D)kcc~?2aeR|5bJ(T_|65#8L4!8Yfzlt_OxMqFRJ^bLyNOzD!M9N(L9h$mI=#Mg zN5i{mJlUe0do*dhH;7?gMabT?iRw7c`W7_VB=T?K7?=+hT~^Z#Bykg{AJ>5NLbq># zJ=JXagV1Z~xknRK1a%0{L}ZD+U$b21XZe`1nh&mH%e4_(2(SGPTXvC;Ty2;#P$9Sv0J@ zyE!kWU1`{nn9m5icjc!l$SgY$=_g=61KAudBGLbkX#bBnx;^I|HAu+(3UsaDUREB> z5%2po=FS(Dg>Q?DHgRgvp^Q^D%;vV?zA5}pUICVKS^T-WoegYO!8@UXMCeWP<{qH= zw@jy+8?^GXdMhtxj+FFpIAM>>ott}*5dr91TIS#9D8f6FXcbcz*349dn>=%H2g_0` z?7wLT-n?USC5P|squB2?wi0OoNjA;1>@X>8ppj`Lb~~}T;$RA!KU_&=za#%6h|=U- znw*z7`2cRFzVuCe3-CQI+x`Z45*AvH?`J?JIf*KPnLnK!!11_12o@n1=kKth++en$~tyyicAcA7}OdIQU(p(F9{xEy?qaX++d zQC2jQ1&ez!VZ7G{5+9Xz@PLiXQS%{ruWtSE-~@P*v0^Wv!Xt0K-Q6!THeP)Y+u@r^8oQBk@jxA~{#4@mG6mT$5EWRi?Ku?va%WajNfa`r6 z&m0^Fy@pGDrDF8n!z#$tednX}5I#2m4>X>XgW2~*$dyg$aB!11al?9YEv01jlx(TW ztEKi+sJ%i6nRpc8ylEA*NK)c7@`W3~I90t?Av{O+l46>?&8wwm#rv`W+8rTtA$T(q zct`OyK*jB6gG{1@%C&hb?g?Vrg-W`xIam%Ds!67q8;R4CB2MMU?ZpBVGc{rKLg@bY zqW6_^co6uVh~y%hx%!?Ql5yN#D*0uA_|TD^(ND>9J&1Ht3k}GZZ?d%&c<;$Q6RC}N z0VnE(%D7#hY>2=%Yu5BucpeoZNJ^I%$L*$6RU(on8*_nQl`zS#RJEjURVO8L2vQ+a z+NY9TXy1A(alfXLSH~;PUt7trzLi{fR3(4Dr?({wkE-O(uc>6wf2d@=-%6ioS4kyt z`@SU6%n$lh)9;lT#Tv0D@bVw49+m9tNqoBzWI3ga%q9PMr#$@kg6(HU| z{>b`qQt58q-r3WiD_w%(r0k4|9N%QN+lNC@W48=QjI+B3<5-DX!q&zK`i>s+Hek2- zu0-3tN{ka5yH%4gLZ&}(15OUJALA{l*2^VByeYt;rf=T3;@f1QRdIWhPp^>q0V;Hv z**sTsl326_WLx9aNIoUI%yeL-W_fZ_98-4m48LQnFb-*kEAS~0GJnGWg8(zW_ie~` zjwZc%=K}5Ie8D!!17seXkwQj+RufL~DY})*zez3-GUFMCKJ>kQQ^4@xm!Q{w1N2tm z!UDaHQGQ*|!TjTR3MPDzS%oA&?)SjY7v-b0|ehkL>E_-0}?pab#q#&+- z26zY(Uwi${o;a6x`x%cP03hdk36LQ12*;* zk*1nf&Ar^u{Q_uA1C3dX@++kSh|lJ?fZsX%7V=wXE>sj%$M!!gTmB~1lVe+^biV%v zR(#^WSx>FzYEtdPVJr460`ZBTvDjM8NX{e&2V>dLqX?JwKTZwmvN}cJl zDll?dJ4f=9WiC3+m$$t^QmCQ;BE7`yDNJos7((jRke)3joUQBwZsA^Z( z7FJUy&1HYA;oF2K^K0F|jd5P8JN|D(jL&>4h+zJe9 z_m_5yuvyQhdgFFILs~L-+=Q&fXSm<_iy=^cg=54q!?WBD*Qi`>o@&~EA;YBUR2?R7 zP)6Pf(vzZ|NjVA6;r776Jfp$Bi5z425|S)VsK9VMFW?GQ2Rqf=tl-Y`!HJHg7GYCF zAed!^*^k9LzHhes(l(2?DL98Ip5e4{n8nROQm7+j25TxQqHYn9OA&Ian93dSyCfcy zQW*BZ$5|dSqkWW89*@{szV~x!nnXwvaU!{$jm)k!R4^Hp$&@L@?1y~b9sGF z7L5>@YaFP!1SYOhxV*b-)=SC#P_<7J^0f)?6lfFPr<~qEH&2iD3r22=uT>Wf6o1-b z)3|1~OsCzE8D+PGqL-=@nd-KQyc~uky=oH|<%3ewFUe|t{#t62$z;lAXW7?_!pCOy z>%AA%y&ubpJv8xKDg1pYyc73aJ^HCU;XOL6essT3{7fHR1G*yiNOKFNxu^FqAKCa< zYTh(Iuj=qkm<{RL?k=Dj^m<1X}Y2-{kh25FQq=c&1MTwx>t5J&WyC)~R zexW|&UBU+X7IWECe%Z+N?xS<0!#g4~%dQJWC$nKoUTmgMEnW|CIMB#$tHM5BWP8D( ztV-UzsmhWLDW}%Pwv_VRjg;M!4@yw;#F#Prrp`}^zMbq@slJm)D4>78V&-UZ5fA$c47e*&C zAiij!rhWF1^tJH1zksBK{ZXmJeB-Br;5{cPG35b;c|3_XhJ8*UZ_SHa+bq`kFf^gV zcp?RaOLsuRvq5Abxo1ls9fDC1U!-v+g6GF08b^=$ChvX4Q@|I47A;p78q!8TuUrS08il9uZ-VgcskqU|U}NnGzNr zyIl75|3`$AyVJ)=!ZX=uX#=W-j;4!4a~bD)Q$EB^`A|VO4zHral5C67H86%2^l_l)Qy?gXnz%nL|WLi!4(AH!PbDs+Zs9>Jl-*)8xIxT(Vcj$cK`+mpB+6u)cChyNCCC{weBZ!(0O z{XVuP^LdyRtgg+>u;B?;i$q@?@){MX+S#-r+JB44CyC4HTmgU#4NBs@RRC7dHrK8p zV|UK&V25LHr;UqSJ`0By-M4Zg&|-IYM@mcp=)ARe+Qe~p3FxI85)W=U8Q8tKcadAw z7|vMr+?LWtzt6Ul{y(9o|3wom^&hn;b@^fgO2etMt29r#pJ$KYqsI|&Wph2wrc^8%WajmNPYkh_aO2!E(=}-n$ifWglr71QTrOz# zVE0&qk1kGfmuI`TOS3qK8H#I$9XR|QlE`s14c|EzuzX~2OnjK*;{ztX<4euF89=6y z+UWFrpB3J5mo#kh@jXN8sBZ7oKMUvof#yA#yk^E@;%j1^(frpuSVT#{IAFyGf5m_VR^+$Uv_C^B{DSXuPeB)oE;N z*saNFd$1)Q^3Cw*#Rt$T%(d&&f@}eCyHzWrTCzKpIWPh4sNj7Q)1{WVZuMYmV|^Ck z9dlbvI;Kqa9;{tC4|6JW>9O+9@VmgN?Si%odFrEb3?B5$WtePTP6I2$aL40B-28k2 z4g4OJwuw%bKKFjh&w|%SI?)jBc`LESlWTo7PGud&1Gf=Wp6gvq!xhh)2APw!I5)!s zi7jx*_X(IcFsVbYVQ0an+nQFA#Ag4(wx*x(Te#r5$xh`GkR03A6eD3CRkt-Y^n`9F zB-!mf`E8Z+G}Kw>fxw|CbgQbc+e1#3Z^Wb7 zksgz;M!k2t421`BbtpV88WxdNlS@$skq{^0X9~@Cvx=irJCE!1xFbKiVazlJe2%9 z{VJsQ9@DRcES`uUS3YOWBOxr0JYZX3#n$k>aWbN6cAz499Q~9_UQ+@9M_rQf(zsdp zrZhZ^b^-fHZf_*y3F~NoDF!6QT82Q&$11%9XwoszsJWPMB##Fq0wL-V|0>2(yo8H* zOa{CQ8p`{=V`cR6|BE>GD7YXsY-O;LSX*$mq`bjE7QnM8D!*6i?`7n;%&n+oI*S^= zm^bH&fmFOB9tvW#F4R|oLwIu?TR*2NUrs}QM$Pu}P+I*c!5!+T*1+Vo2p5EebJ&2k z1x^=Kuh&Lq+hSkmH;39~6~VbB-S{eNS?2N_*KX%~{FzCtmrnCoaAUQW73f(ufM&ov z2#OnXSusrB8%R{@^Un;?pzJ1120?RfJM$2!AnTc~Zceb#gjMC42`8wS`k}k-*?cA= zysCxYvQO~yRlbRbG^!JyIfr69q7y+Uey{Y2h$8VU5m?0SOUOL`V|q{|5-sU_Tx@+e zoopd#!h?Kv)YW69qjmT-IAb>XjumCSl4&b9Eu4=ox%n)-f#)qdm&uhE&)Fxn6nU+C z)2S*P&&pN_YEpJsAYTAvnEvFvvaFpq>~LO9wD?ePAs7!CC)-&f8`ZoD-({oO-X?rD zf#pMDkaO66H=K=u|nvZvrxl32kW z5_ls*NU;#ngNFfVL#{6v4&cG2J;8%-h}Rxz*a7kz@)MCKdq4Jr1>lusMx~SmnHueP z8;t$If}N6u)8DJ`mk6JKTUff;@2f1t3+w#GF8aSAdd!;@vr~uP`uz5zuRyEDF3@V= zf|~+F0Wv`<2 z66I+H+lE;@^kH`%Ssad6Yb%SWu#V1`2mi7_KxEKber3GXI1Ekn7v0{kXayPcuO=$HRpPx8Xn=dNFNr)_i#GXDJ zufyL%aPjHXBlT6#=QYVXWiVt*(?}od&~^kKkt6HR>TL*>sA4g>jOA%XZw}FlUf?AW zD|Ru%*6zH}iXDJxi$~a*Q}@nIzv}KQo8?cuO)4UTb`tQ174p$wif}J&%uOio%s( zVj_ib0m%3Gx)|jW=i47*v{gp}kl^uw=#x^DaCmACKvl<;dIOU|yXzE=ci0+X^T&d3t@txJ?Jl(R?*eo2OnDk6rswXbqL}ur`K?=JnX$V< zSmeV8?5=)R>=@3Fz3o7-yTYvK0_xV48qKs~KhW$0c#IvG-UFIEjO*4?17HVPv6l&2 zx31u?-GxU9hd_LtNHuoXQ13NG=~yc^x*r9OwY!e7V)ts+;dm+`;9aU9b9v^1BJp)% ziEnou@BLg0o=4N9;5ByF8CL8}37&3u6UfCD-?_wO1d z;U;lLXTDX;MrB@}Cx-O#b)tOmP9P{lrD=s^IDrh9uXsaKsXvm`<)nJupvWMLuTvo? z_5o45Gt*je1C=nUiU&YI@2{y$J3$)XCqx-A+2&^C6h;#^zR@A(xw{z9w&ak1iT{Ii zws?Smpe~&7*qw833QKejQ3@41nm2KV*8XP&{KFLB{3Kw|PB3b1T(_9QQn zZ@ZJt!R%HvC#61ik;wS$(*gm%5(!BqM~ihwOLUjn*~n{1QMMX=&e=j^)-7T&5w_P~InC#g_AT{D;CQ z1_=yt>Fr%BX)Dp4SjdZ5E?hw+1)MiN9?yL=7}9}e4X%keI7`wZy-kd`O>f3 z;%=^QfH0C7m#Je!48{fNKt82}@5a}Kg%#aNP+8Fz1k78{Fw6e*IC*+>9sQ~>YdmP` zo>gX2=aeLF)cmpzF^B8?-GAb0c$BP(mGO1&%kTL3x;$38#JQUJmje8=B9)D@O))N< z+Qidmz!Q^Ex1uC5BEBvcbP^fybvgX{l;NG?N^vJy=L9#=yg*`}a;8c>;J2Td2K+$e zBB!%-w_Gq|W(Yn>NsVaOwd=?tLawjQ6p!Wu5d-VkQS$p+H3BT~`#x;*go-8|6Eix+>Z=&(~*w(F)rJabdD%i%6VO%|7LYC=iZ z>1`EqUK{Wqcu4LgL`gV}zLKG4-r=fIQgdI5s!m+~XSsE~mT|ISsHk&bjyLHpA!3<_ zwFogWy&fiw0xNlcV$5d`n$sWz1W4`~rkZmbr1=N>_lVP9Yp35(Aiay7zGZ3^y6{_| zkD(`eTgPda>O$T_wQFORS zb_l(6n2y0Mw2072^f3Fxbg1D>%;$hnI$B1p40JtZlTC|IY+|l^ZI)83y=GGb8LZ0f z>DT6QWcRRpZCF#FpYutPXWx<=1{~>+L(SBM7IvyJ*X4`nMZO;`#KotMD zj59*>*G)>`Q{#(xapI{VRKoe6KiD{+>CUXwt8Q}kw+p(Mv-#6Q+H8MF>oMT2WkTCk z{gk#bcI%?ZLnk8(T!;<#eMH@73-0Gf267bG3^r`eKZarUPWe3Z`(X%E_#WYupRS<4|3Ht5ni-or5#@^E9y`|Oos!!?XbCeoiDSd8lX))&u`Lygjik7*i=^IKP z6r6m_C-s)TE4gX*dm`6Ve?#e~dQ1DKRod?V{!;18Zz%oa-qN+bb${_C%>Tz9Ghb=< z_}q8Mm&(f7UeKlWc%TppmBv}$>daUjF&Ox3CF{YG07S)jz`!(y3+aR|91z5b8bL%iBC0hLV zZr$7Eg80B0;eoe5$khP1qS%=c<~klP)n&@X;xO+Ts6%>u;ADl6`Vtqf<<$rxX%Z=4 z+YmWf`~_z=P7Vhu5N`(J=MRl}7&QD!$u(Ra%?+cpk#}a&8n*^1>deTZ8hLiNndUc6 z&H_7B81@!v50z^Tq%3e(ELD6_cvO_bTM@9%v9~nz$wf+K&xOf6dr6*OJVUY;b1(r- z`qA>N#7JI_K-v)4fd)QWc8jXeaAuJeB*E1yo~*U_H7@5V0pZeT-+ZKdR3MPsk_l0# zFw@&MF64U9juE%sOnc>zTzJ%Qg`R=vZm>D*H@bB*Z-Q4@k zG}1W}L-fwXe5sbkN++=p(lrxnohp5AYdn^?RLJd(I~gpxB2GVnwdcvaZ&-V#FP61u zDBf(y|F|0|n9ahI&kz)`Wu7#Iv$^DQ!>OojuJhvS#D4)G9`m_^5paIHkQiC zrN-A9>S&fj|LTSx~KW2i{tjMgt2~2>9zl%^l-m)N!(VZ{xzkq{ST$z@LM$|ZvXBZ>Ms5drGMs^ z9vipUe?#ei`u(EJ{mV4JQcBC|rY?dZb3aT*slJVrzBbfP2yl3kc>rh$ZLgOO2^J>k?=w9y?A8D4+-LWkE246T%wRYmgiG3pS8!W0r$;$mYnTe zc#wenT9bS`##yH%ZGjKIc1olmH&cw+>dfRjQ{3)jGD~6R9SX($ks<)(N;onyzCmpf zIJzzT9!DtR2JAZz5g_3-66`I)+<0SLtL)klh!pph=$OscrWQ-e13nLQvIx%`5l4OLsceIl{Xm6JXt?+Z+EOJhpVZvp9!q^V0kmxLZq=Ircw7T5E->g4$69 zCB*PXR9xn!AETi<;mhRT1hX*bjiB=uqEKPi*JCq&;f>O5UmVtMGgMQO>~~)zO`1+1 z+sWP`w{&;%96zkZw)w?GknJP6nop0@(K7~IM|Q*t9t5v&M7Dur>?It^4mCq_g-7|v zDc<=E07PHOg@~Ug`;{J1Uk*@W1rLy<6!u1-XNEwP%f>nTpRNE3r*US`1DriqUE32s@=H03-ow|YMQcNr#_i%2 z!@SRj%EYtSur<8R*MTeE(7%#%;EMP4ui-DwWuK9L3`8$hv-sle4U#cf+5$z3<2l=i z1R7pSo9oEy2n{oDx%8<3;VIyh~~tz&SQz66`wHJ;f!cfL9Lm71rRF7 z3NiyI2v4qHJ_O=ZGRRmLugef_966zM_guI3-tb(fwk|_L8H8qLOe{OF^uxpeMoFFX zdhjLn_)rVjkXt#13d|b{d<;+5Y9q?*LVCxF-zdV3F~9sV{KBt#HQnu2=9E?D-IR_+ zkQ>b_i{{=CvVV~O*RskQNvm-yYsxAo-O#`B2l?G%I;rQN$K_d=epCXGZG_s@^VLH zm?jN!r`JHIilVJ^-JBT<_IEM(LUWyI=VwHJtH3Y=k>MB38yC&t!7*MAUqxIijfc*Q z%%mTRJ0=uk)X+a#Qi^p|Bp5 z8?az!7kCYkS|^04zF%}-;wAUe++dq@HBY|L^kDl>4|Wl#nCph><~oz6WK6IRg_tA{ z(UPh3!MMtt=(n}4arPhiVDnA5s6!!l`XtQ~+#Ng&$`ctkkqH^n_UL|3EO41Ks6n%a z#>ZH5+a^_Uey1Nl^J&sFTC#wSwWT)P)#J*l^-v~`Vy#t!_*%BhiudE!Ik=hL3RqjJ zL-r?W)`sm>xTu=zRA-dE6#dA14 z<=+3og0bn*yaU$dAGCI6U_~dZtJ5TIt%CbmxgL_U$9QOk!)&QWzIB@9pg;!jQpwV$ zHe$u@qf&qibIzt|1Xx|h#*3c-QXu$AdQG0QNt}(fg}8d&aN)$V7ngnx$%@@2#bQo` zfTK)ItcCIe&XH2KzNa@x%be|U5_X>+TV1}N1^_m3jTCjbpA36p=#RBGBT&Lx2aEVt zI1^^kEQcqqdi!FfKgsUQUp%x%MkoF*xjd}d#Xn%Dl;fYhJ$D?CqfdCEO{4NQRxtSh z%Y_;R6}t1TwF<@YnR~yF&LPmjgv$Jb8lhxG(>`d)FNAzqx9+u+TGP&Y6d`n({Q$*| z0viDA<$HiKN2KW_6!pUZ3>-wzH`l0x2p}3@t#60>B`y(I4}L8ypFm+V?LWin1lDGO zRc&t%HFh`9POGUu4Tr8JGV1)*l~|2KpFjR@6o5U#Pmp3L&a=%5Rx%s8EaNmSzI zEohmg1FZ+v!&8rRFSti?&+=*c)Nnx2g0b;Q*=wD)WN&@;5Qf6CIjZq~16LQwZd@Ng z-QzTg?+j8@`gn$0K#*q&H|Y2owo_U2gFZ;+^2t%qv}4Ioe4}q+UF{%EgNOO#lCA zdl&Gis;mEh5=Iyxcm|CcHPzI{8Zg#S)0z}oBa(|2X;dzOMx-sZv{FT!0km8aP68Yc zqrOFJTl>DXuiElfD_X7M4H8fi@djS8wQc0Jdd8_5yg;;S{-5tUGYRP1zQ6yC=OJ^> zKKruvT5GSp_S$Q&ZJCiFbd66`QjX>)-%9yDb8^HA6=*f?WkpRa=!7k7$MVGCqL=jL zjP{2rv_EtwX?o6`Sls*_(QPRk|D+n-teHkChG-B)#1iC?%+h2=Gs0O~ID1JCmB_3D zhyan6rJ-#(&9(-P4jXudj#iRUu8~!sfIBdtat)XBH7@n0>FRI%<>M_PAdL-UK-;@$ z$NNx}u%jXDBm$E7ceIcQYfSRS`D@yE_D1ljA(8;}_!=$Bof#d@$=!)6_W|vBN1U?G zL^-qKPG-fz(jaq=O|3DT6!|;T?Y8JiO>UF@&guv|KH3gdg_dx9UGd2~FSzpCLR$Un zhO}pu&+QQoin$mGw{NFyJng~zbATeaWEkUcUW2#IHkw;b!{&XVKjUCbs&;IkPP|VZzaj0Esy7sU?1W9ue6I9#BTv>pqNe2NiW z*C^t9h~@h@aglxi7;G>kDm{FXr^^AcC^cP6g2L4FN`B(0>9*&VnlA6$SZaD1Khc0w zaQ&I1*=Q$zC$e-1vA^{<89Tn86$sF9UsdR1-BmYLV={P(=tLH}%wu)?Tx!5=dUD_} z(E`*%oO=VZsuyp_ONWYcLjw(bIdCAD=N+(3V{kBR ztbGTr_e9h*Z~zWBl410-hG@0H7p=G$pPliAq4V*l9FF0g27G&t5$3355}htU%M&XH zTVCUaje94Tjx`0eX5Su8=gX)wnX4E=Ct9(4jmIjoFCe&+VA+=Vac~|D`*o8wz_iDE zUN8rvUF+7*U;@YvFA++^NAgdEtI0MmIXEzc4%vSQS)VBYyi*x0nl(yQ5Ii(6j3zUr z8i8HM{>y@b6(%>T$XG^!azRVRQlv)ceT#@BbD8f@_X3iDL! z*4eKa_&J-sKrKo!i1{t#SCdhkUx{!z_{;1OuU4lAH zgG}a-CHPkyGn(Rl@DTm#9+JSveW_vZm(WgjFsLt6UmZsV+x@+y0j- zckdmjaw$*_R5>-QazP}~Olu2FfL3PPGuc`koHJ0hcE!b#2SU4gui1FZK z`S$>o%BH`SZ-Zw4v)1#QHE71*M269kCOf z6uu|y9pU{M-pwwWh;Bi-L74wo(>9!nS~m%}?`hIsU13xIf0NVQbq2ofGkPSV0Ag-wrBn7A z4=DYl^3Y5m)froO;DkDVQ9JoNx3r4CD5^mVyEs%+HoYz7K$G3@W$0HS4%W+d%zT0K4ccx-!irbai@Ul{Slse-LJ<348c$A)0G<`dN=;kZ@@8JKVL>qk=1@)#- zC2gj3+?s~IFM|Z~jsA7m=FFQGV7Gy^;Q0cGIok3m{|>9u(m}!K+x4Dl2uBv*Zwi@U zHY0D*Q6NPSUiG+@nfbEnxBQGiwLbc)u(t3^m@B?IRM+Dhq=kb}F-eA+zn9>Tzuv&o z@T778i*Jw|APf94`y2Da#F;=nb2&5G%-QpuGD82)oKE4{Ag(!Z%BZkO!iAx!j7pYt znN4@%u2AhvwZ~VCozJ&kig7a+c3JPWa)V4=h7!Fj8r!w1hYWh|S|uWdPeNt*B)aHd z=15p`QDK+eLH)^0YC~y=uz^FUS=lSGI~Q|S>(&izQT>|4~dSGs$HsO5D!Q`TB8FZ{uX+d>iloamKd0y)o}^GuJ) z=Gon7TqnD?86D1lY|#bI$?NXmWzlrd=-$nfIIIV$0(#d)dB4ypW1!4*H(HTdPru`w zzZLnkOI!)(-LT6f&`h42-{F1R+s^r0ct-Nfde~&L`%|OD*yo%w*@z!axh2d+o>r){ z$vM*xthMGoK6YV=Bna&+ao1ch@y_XniFKl@`%%gLC3KAL_-m<>eH7|(>Yf|7*X+1k z#sS;xZt(cU>UmKXc*)O_wT3lgGnjOyZejhm_#o0V`Ro;NeBPOaODm>Ue66>$?r{1i z#!?gGQvcEuu=wKeDU(HDaNzGmy9mQ$g1m^)j`WYxv$oIf~V21kV7 zc?`eL^!sw)lW*oaML4#$8_|N|wB$$XQGx6k*cyPQnbd5jo3~e^H&X5~*zHkJULe7O zk%>qCI%{7+8-i>$Eo%CijgW~elP)14H?d}tZ%})|5IjiG!3s`y+Lux$6@5eKzUYZQ z=u)t67k>-$^jzd^x#*G8(9W7r+~QQ`YcAwNiTirY?XvjzPT5XAH5g`LH4RI7(ZI7JwJM(3hI^;=8mf?q^FynO zWMviBnAWZD?J`+;Gt^uV{E6eG8g!fh|29jK(4RSdJ_9gS(~K+ujitdOU&Z9$uC*0S z*@<;c5`Pd*N#I4Ag(N4@PqNNpiTmyeKa{ zTZxCT%-)4rAH?V{gr~l|1bMn6Roa|E<{3gBcZnY!xevT6Q3or zw&K|2pI%xWtT-}xw15A8rB+0%mqne4I}thCDHnw0R#DD-B=fjm*Ff_(tTz!HU$BIi zc_{4h8(YZ0?>ST5%a`WyaC#Ge&TN*6t@(NWGdVXu4zqXgAGtb{A)+Z4o&Myliv`1{ zAQue7fMEz)oPbEslUINc@yJ{K1XaFa0uywjd%&+#KD>R+Gu8^ z1;5|UNFwt61jr^LoiAk977$yWY>`Bg6Bk6cxsMIfi1z}nr&<|@Mw=+q;(mn!7;!Q+ zo~HVr<=#g+SBEMtGp1ixMW#Z(PNoTs!@3IlK+ofK<@QKyqR?JZTc8S-r7?bKGN~gE zRoJ?3`V+PuWQ2yvgz=COZ$~!b2YY+lfx};?LzCdo!hIP2BxOf8s3Ckpu&sqHs-0){ zSr{T_dh4!|c03ru&cGa9i)`BONF9y^2HhKEkiUAk)H;Ep9-6K|!e z@s6)BNH($>_rdmOH3$!w0Rl;gv<8Acd}8JW#ltNyRf*07xYoDIuQN7Fn# zv>t^4$GvUm1(#a>FNFD@rK`okuT^Uo2QLAYKu5$(sn?cHBz1evO)ihdbGIwBKglO| zQ=@Vu7rL9~>LD=<_oyAqfnNb5xHI)9is{h)^m06DCq$C$wv8Psw9?lQv%ymBAl7L@ zG|UPKmp=feSIO|CfBveeJaw&7L&6re084Q%jao1Zm>vOnnH$`Y4wIh4C|v3_l%96l@9zYpZAA()$#Ds8?|W z)0gf6ju2HnABV69TYDv*g=x#Bt%a@Au$3d%=NMq05nwl$-n<#Aw3RNX0sq&QCioFg zh^K|i4yWx3j?}q*A9Fz39zJr~=JBwvt#k=_`NwUnl-Enh_qK0!@{P!t5Bibg#5Zj_ z6%9!DuAyWU4;IW%%oM#0fjftHI_(FM4H#6Fg>3z6+tbMta~A=zt1rGf+83S<^CSNy zH-bcg7v@j@8Aw`hwz4Q2f5!Px)wDclKau1Y{8~kfD7Hwh;!4C5{?+^xSo>f#xsxy* z0Lh(I`vF;!Sn57B*(encE_q8hJ&C5$bHPC_PAq1u2-lUJzn)XglMeE$6s3Lq!wGrnhVEA7iK==w`vzt-{+9b&@0A@GmS@scja~prR!86 z8#*^J4y8gApzb0W$WS$kO&p+dWbd?UMDh@9hf?Xo`IGGumx$gAbbhJ@Txsh40A<|0 zPiGjI?%%MNpXw!at@*~CdhvRH79w&B*jPBCT9yL$9$}5{joS+uiYXy-6zLbTm*D?V za@kQAeOx@`zF$xScLe$~3UW+Zm+A5ETuQRD;ZDI}(D(k#+3=*ZfexwG)PxcHUey?( zvZ6c?lAcC;IfmmVR3IIoirBmDOM<6;3DpUYzXA@_WV$ilGqH6K@)xY3r;aQ7q0FPg-QL%6WoLK^AKR{tJX+Ds45e2wdw$qICcn_kp z-DW!8PB?{=`d5Yp6mYmK+fuoHL%^L?yBR$Gu;9*ykNR6SA0a_bumS#xaxdmAfn|T) zASlod{A*D3!t~j;NnHM@bI;w*-F$W5|F&>$_i3&e;oS3}Bd00vW58_i_5pMmGv|u{ zJb6qPwWBtUeSw;)&;uVs#|h1wZinfyGg+nRZpJ39R{S+#8td!M%MP_Ux9ml#gLBH# zR~uZ-wr(lSB{yW|TC23RA15}ziL66usVvKvyv@{`^)CF1Wva|rl%*S*SQ#v84Q0j* zTwjw*3-`ldP3}vl<48966I~wKlrgSw+*kl_d4*vh{hJ6)s^M`8(`4q7fve)CX#|d6 zqa#Vq>OUij7V0!$(fBng>$s1R;$Np{_bX6FufZ=agsDur{*G5?j{IFWVQTSB&>^;40ks+ zh*0~@*`Vsro?|mT52MRul`pgQlo)Zl8j=e85S(Qf>q`ToM0MqjeL-C z73!8=sYP)jeZOJAWJ*HlT_izJ7ul3>X1OrI*r&2C*Sy7^Q8x?1j_ zRsF*cb+6Oj%9Cm((z*D++tT@FT<6X>AhueLO@6B;T<`i4Jzp=T^X`rCci*nA)rI`( zpL?IR-L*QFP3T%3%|3be%5}-RUYh(13wB4!>JyV0Dy5-%D#TZNU2{!QLy%T8=nPcQP!6N{*DSj18jhK^raT6WoOsx#!qkAnt| zQ)GNn%AVao_;BHb!bdi6$X@LNwsVyp6*GXm=&PO&$dV%kuE1+es`&G`v{eHfHg%#doRtuxe@!tA-g*yu;{wr$|F@YCJER$w@)PHTg2%5=+-VNcaj%n(*9~1COMID^o_+4}#)vmGF($RV z(ZhFQ^;x(-Wam*f7%pR6%IhF|Ro_Qv;$+ai777FW2*X#f>}b+bHsPbkJP-K$iP^IK zC;XYGvxV}h%fSXG_y3cLe>L^Du&AqziUI%0l?B&qGki@z2Y`HZpybFGAcXD8Q%p`K zF+UHA*&6k=U37rdP;2QreUeDfb^2uecnd1MB~|H>8V7$cEn%$I4JhA6V$@5g~mcvn^7!<5|!Y$RKJ7b`9Zz??>exQ;?jwNI5|<%Pk(YeLM8}) zk0{iHgV%DqmLE2*!kMV&ui-3|8knZ$jzxuenp{4s9B7JUEd3`8a5dlL&odZ08Z`s#5UzRD- z-5VOVMoq0s%3%9w{|+oh;~vdJSYvfAt?o?@9Ye**UkN@qKrCfSq*ncX7ib!m9&kTe zBMzpvJmd*`g(d5PlPV7$3xY2{ZubIJa4y5h`j@xh!-Ikjjt~0RsS11}jEwH?zj|Q; z^6T0%giCMwNXQWUqem*r@l>Dg<}7jB*;39Mp?Ta>I1d6<*<7yJ_#iUwftwg=xPvLjg(F2iwO=F(=axoM8Hz(=>Ub(M{9pP1&?67e^h zI2#a3!uuas!HwyB<~0T*M6L?1Dz&{5!Z19gT3NuG<6;RPHANTf+XHA)f8+xioWx-O zJTK`16>8C1MMz=r@OeV$vnzV6KP9|}k4-45s!|31*|}MXyMzS)6MU(xeu^@+IySE> zf2l~7R&@pn<{AtB;2{{07GE5V4e_-FTHXjH1kJ6mv#~|kCZpb|>|z+I1lcgMdVQ=b zxElvY(C34iOG7msYl$4Ci#p#rmOfQ_eOd>#;pYmGY9Nwg7-x>#-}W^)mwD}z`08EP zz~6!4G~9*}E>RjrpB@#Gs5T-V#0|EE79#+(Gg0HWoBjdMcpFW)Tq8llrIfj=$4S@P z(7Prfh~haT3>{ih;x(4~f6y=me{rkSX{!f<^coSZT}%WO*z;(B3-dWkig!EbNjt!1 zjZr9h?D#2#$#cgqk8`&Tybwv$f%}GB4>CnKZzWHmX0B{3hZHsXDq8H181NkSjd-?w z4>QupVWI?Ff_Xa=Y1GWUR|h zy9L{n7kKjPyhwQ>4r~NTtO0{d@H?CjQW8emlm*5#`mn*rqDBH&&XYs9q6~*$HrsSgJ z;^5vN(v@{pbMh2{PWBT05S^wKrSrG!9Pn;~xHc$}OFWn>qV@P-3#^${u$)gFmKmi5>LpHpLffvAMx}CACc6?Q)zfyyCd1n>~P!T`(KoT@Oc=XFL(Pb zntuMRtL0$i|dJ6Z}a+S!x0BiCAy({>kV)oXr&t<$l! z5r0Op8f~JyLcu#5I=QW9=$IX{eRJ|Q1YY*UU2^Ve?WQ>SQv%Z6eb8C7Sx(SteoEk( zB8wlzV0w`v^IonEghd93br zru1Ul-$&^3G0!t?U!{!;>F=ojQU^4($$6K@XmITY?F2jRr-Y>y;b4MLRFpWzL*48z zwmrgw5l<7S#g3t6qWTUm7a@Jga~DSk!(v;=R;+A^THvb`t4p1!?sg`3bEX_;;p*O{ zhm%}2=ItST@N~m(vBaL8IF~ux#@2SuL{NW8mdldT#fryIeYkR2sfe|)g%Z?Ktl<_R zV4b@xrf_sarhZt#milkA{bW1YYD?3_EI$&tRU$}~MfH4%M>|y#esz2P5o%PKF}car zX+wSzYqwmi#JMm|Imd0Z3T4yu9`bO{N7>aS9^R&0vx<3+69)%ufd;|(n>ohv7F*5! zb!*`a#M6<4DU@lh9zD;!g1ZxH;p8+ol^}?5hmyUwNGxz7*nkbXoelIqZ##DX$#18L zekBo9I=)?e?X-Uh@kGPTG@Sm9L{%0z-K^lWpJOS?c_L*lAL>sl88WeWJZ!aMaQ=|} z9<&KTL-6oujJw32w^hm-x59Xye_ zqM>?Xqto^$-m<|4&5f+% zS$mFqY^YsNR++~s1KDckXy{hAl|D>4XG-{s(K>ucIPNB~K}1qt4t)kzG=y(`O+p6) zCWmJ1XwbJqgel7cLK_5T&_X{wB3cy-ToODID^jk7@>fRmW@yZzb;=GV4> zgeJuLk$$Z^wm0&`xO*Y`7k)-f&F&q{vA14obc z-DWrDRNn-nemI;IEy+zC`vVGZY^e{G+J>cx}C45qB^Qs z2`isiTYCABA+^Qhp5DhnMUdZ_I4z4sr~Psu=9-iVz=u4zh&Q&d_4d)~wOKNUzc{q2B9_zoiL4;JLb?l^0JannjVKZ= zf6Mc0<|fas-m&ORurt|R!JQ`UlLf@pyC{Me(kS;nEi^Q?NzQ_uI9j>=t0le;$TONe zkYO(AFf+bl37;RtZUr+oY-KxT6R2=n$k@5#o*q(L zIwb7FzGQLgPU>v&V4|@&$u_y6(@H+JJS03K!lq_-jI^wO=D z`*@jHy~SC%orm;W5?vTr5Hv)vn)E{2R|2-{pE);gDeCNz`dfaYI6-zN928|M^UxTz zw*R-=kp;Ss8G~&ni%wh2MsT{I4qhkVz!u4OcSh3RSEVTpUG0g_hnnuPC4|W#?2}6n zn65D|P<2)H$CqjOIJNyzy%7{jc@);G%AH$U6?Ivk<)M z8`pt~#;;Qw3Nd&0JGeIT-quEofIr#4*JQP})u;DYPistEOx^3U5^=^Hm}@EtH>p0P zM~F{E*ZGp*Q>y&dJX%EX|y#Px;Bioy}kL_QAm8J|6RN z=#a5|SmxlCue2nGqf^(MnS4;*u48xPMoN=Y_HybEj{_M(ayM6b;|Ulq{7HKUfNEad zk>H>}bK&*8mhk#43zov`@o;=$`1=`_M!e{Y1>}fCCXUB*Z{eo2OLd&qFz^1^Z&Ut< zlc@E(ljOqP^s=9vq*m;ZMh{>w&3DRnB#&(0yJ7@!w-a%v?Agpno|KBW;d6pSn(_W{ z;KTU8z_E1U%?$lRq>g0iussG9GDkQwn3A?6o%BECu(+&-VX=oNDC_ooWTOp1keC49 z4Nj^J1mtOCTcNhNy0(O|FfF#RMZ`S2z!a=8JBf~C`qi}3a7HcgmzBa$4Su_gtq!OC zJfzg1NPItrNE{B=PEB7gZ6^z&$m_Hzz&VBI8%dD?WsVuqfv5pj<4)`Zn=4O;h_6x} zqQnbV@c^-!3Rej&{1Kg+3RmiFWeo~U)xyWAtT}=S2Wwxdk}UCPD|xgLJBMsTDf2Mz zQ8_0^^M|nHhFvO&(c|@v>8;-9oYB`mxpcnMz8F!MJ_Z2s`N?y)wfx@%1U}rTiD8*p@?3OF67UrQS?+6wp67utLXnT6#WPk0Ys&@ zjJ=DHu*}kBSsL>=cMRuNO?g?8<<0b!;y`ID9Mcv4q1AO_ z5vQGN1{60?GRuZijwgCM`$j+0V>}UUC4+Wiyx!x*8S0dniGJ@!Isq8+2?i08DKKAT z3S*DMqgL+jkP(r6G(3j?m3O8J_CRtTp=NwS_`1(I{7s68X*r|hhU{D7-d1`IDX`a~ zxYP7yj`TTA+mgQ*5=A>yk@*lPUTz{$Dd4Xhl#bRPO*u{FEAij&Jt z=H_T1jxOg({qrF(>7NdPkPg?2 z4$U(Dtu-Wpu2f+jus4Drb&GUEaoBA>Om*%F(REMdh*aTOIdoa#Ugp7UVh&vcJnJ;y zDqV9w*3Duq%errJNHY1$0j!1N|6gJ40M7mD0M^C|;i>=MG1qp2?4EOV1Yt<&Bk4ws0_PUm2JK6mC8RFPeacev>9dEJZ;2?r!-h;hnGZpNc9 zSM!!|DBA(@E&B3l9qCh|_1;ej0u#oHsVXLA!FiBn!Ps0jE7f zM_>d~Ub4NdRBxr{SZ{l?QiI-JYx3FITsV=n-h6)RDDm_dV;?MH!deMsIO3xtJ@LYo zB$(XE~KTDC7gy1*{|n^sONbaezGx47=rcke-MHHdiFU+ zoqt*9H6SdF+!fA*BChyK9W~93aIuQXi4Ymv309`&?V<5)q~@I%rtTzFeS9w0M-w%? z{ELb6xBK_8K#cPLDRpx*tP%Jl48C|0+y?cso&?$Z{U#hG^WOWvvdw~a}c+GT(Bfo$boSE?@VvFK;!4{jOCyuNCO zm0=NFs7&srm-NGHnSPz?I>=h&^|?JYJX8b|&NFY1QhkI3gkXKJgls9>5DafEolKOB z@-|F ztjF-ee5gkQx1qWoi{&qQcOTOJ0V}e_yac~Imkt3``rGhL@L8%0?jUL4&a!W@AFWHH zr~1nZJ^|0^pMvM)PlED8O}HT_EA+S@D3|D+8_#YCeirtDt~U9rgi02or~AvfiW__J ztz?6ZTC|7ZoLo1@Y5y5dx!c8$f=3rW}-!t^P6sE?0? zmDaZ;4@rMZ@YKt+oIErHt{&r5jaMH}*YSxMC0PPpD?X~+->3Nm+Dx_I%=RP@@NrUb zn4qXHHQ$j57T%;1>-{5qlXrqFqfvfKl)X3jC@>ppu~8)PO+Lu*zTmQk><&lbM9z~< z3iprU2CVp9?TtXMe_dv1*Hds%J$s#>p^}!zqd?7r%h9F!IBRXAuUFsbx0kBd7(}u6 zvL9aK_8jY3T4zr*FYt(fJVUm+hSC%9b-^+^qu6Vde3}HLLE{i(>dFW^b@lO7%G~`6 zN{^33Baz{ZvfyMgK>0%Tpt{pJTbt5_X&k=Nl`|NnsgcaXW{bH!)B$5c(TqL4=dQeqH0Zr%ec!(EB1ayKm7{ zAq|vNjp28r$V}Nn*%9kxVlOntcG_l0WNg}~GEUoBk|)!f-Q|-xzeTOi2FcKg#B8o> z3ZGZ{byNN6bJ+rzGRKRuIN!mzEKg0iP8GlqRTvqIX$Twd4zD+L?GYrmum<1aY3Dv` z(Vfk%8 zyRp&GXHb9Lubb;%46p$^33+b}xwzRYkOO{!5J0zM-h6DkXK?_*pE9-jsml(dGh^N# z*OB+Mvthfl;f1`{WqjH>AIGUQUBxYk{tT&W+PA0?TnhEmuys#tDyaukHh%U099r;%n|?Z5OH_?&uv3aD;58?QVl6=*3a_8uHKYG%^_=B^0aXs z!F>VVFk8lTv=beDp6oLp^|LwamT*kiugDB1`>|yAw#h9hSadJ5Z$xaCeu8mNSZ~h1 zTbj1f(z=Q#7&;k&v%D~pI4t3vbItba<07eNKMBT+3v9?Q<0A$ zgg-s`1sV zSI)S~cZAa9XMDFPmx*+%BpM9)wS6q;sw)R1E@b8p5oX8;XC7`f4rYEHZu07oNCU;^ z+yp+>6{_C4@~*l{2F+;z6%zL#YMG+JN`>=OI;7b5`!!7by17g)^tGA2v7hoW6~-)LIeKlF)tk}?@o-&a zQ#;44e7#wD<^9FXlL{f@ac&rKV?JNz@w&iwp9QJROjyKy_u<_0Qf~XTXP|4NBDh|F zuHi@jsJ?|CQr7aLe=HvatPMd#|B|jc?Gh`;HTd%@uvvywBI7`sVh!RVWtz1zW=z8v0nrBwKVtD(Duo%Wx210-~+yvrTnMA zjsH-1WFg0i1^)C#sUh6Xp!TOs_3P&5J(|~%hib6}h=arW6bcpvtC>7MZek16_UOT{?HRvXrJPi&URTfK*`LJ$l(od3XgMJ{HBdY_JSFy=U+8x`VB!GS!{E z%Wn<+SYw_&^w;*J7r+yK?JLMY^PHCI2+{ZX!jqx7?OzF@_hP9Up*l_X`%~Y2 z*BC}LJ102jy6~Fe#4+whp*)g1aQS)Qgt=eg2tTcjw$r+Ab76w%R&LKhvxtGBbxa>D z6A$pElxnvvIfA6v?DUCftHD|+comi~u7g<7l|#j#d$=W?w19GDLdd;>X>KVocH{~e zw>(dTd3ssPm3Y{X@@J@e77Eo=*%c`Q&h+p20TK|;l=YY#+)j`f77U}3J2 z8uhQ-p&m6x&&&pj@){bsN4bHE#%jC(*sqL)Wr?YoWfNLr2=S5f9hdaLLqERH!r|dBPrMyGf;`S*1HM8^M}#_vRKY?_vj$ z>`3hwYI-PQlUz~^gYCq;;QIu>ekyL-a}hrUR&!;k+?zt-Q>qGrub^#a9Dk@5_mu9x zrW-2B6;U2!-Xm1N#P*Fj)KI1x_$}8jE3PmGtY5D~W>uPo&5WY^bM&Q&$#5+5*zA{i z)^D26b1mrJe3OS!xUD}`Z_~}G9L8Z_ugRzF{?$UXyE&8^Z8|p-Oh3({_pw94$puZ> zto>N+%Y{;F_xh<&38UGT-l2To=1hGOc6O$1b*6X9e}UX(03jpw+t~SF-y?G-lG8Ep z%1&7|eEFBtOK3`cp?PkW#g6ki-U>7n{d(wAFSC$%!4Rhb^EEt-gZqg=XKgg*Xmu8O zCa9xq^5V-p!y%L%eCu9x80kDIwBfA! zc|7oaAO=JsYeRB;LPR zilVdOk=92jjx8bIqh$Jx4*_xP8(b>y%#tx7ephHPYRX1Lo*e+jd-TG>G%CDr@b(1b zu?NEQGddqLn-!sTv`7{Z=c?=B58mOzoYn8DW^w1nuw=-cI}|{~S^0OM$#N*dhBXw7 z`67i)KZR3!#Ho)vQ(ppHXWDjW`eR;iSU2gN!C9}G*MHlGR1-9X^;48@rq{elp=#?5i@!4PYu+^Ulq(dC*+oBBXHp+-$ifw*E* zM#2^li_!JRCD#XIsnmU7y|q3{b0L%L)hHjC%E7B-Z+)G`(;#4ngxS!BXd)6!eGKxj zn7NKz!Pimm(%*pVG$Y>rk%)6qJBv$38aGNJsUpcQ1b>1DxF=L{Ya7ieXioKAdL?Xt zC97V5O@9NsNN~r0N?kafq}-G~-ReD*dg;}Gc5|hs8`ExVIv!`4-fXi>52qezql-RH zLj!!qLgq&Bh0F|A#lqibo*$%>IBxB*{T4Cxrh8saQgA*<<6yRXp8`#?5#!(WI6boo zjjN=by58!$gwaLIbT&Mw(M3qE5*j@FsqS6;YUVrOPm~EhlLosSChDp&{^+WSX+`GA z_`{{t_vz#sY>h>uJjX&BBClmW)I|3gNL;S>eY}T_)Z`jj`0p24K*1q9gWxGvHo2Y; z^2?1J^9injWJ7M))xzH{SAX@-kcOi@7&(GQILq?Ql#Tt=rd;H#)h9qS;Cb#fFqREJ$Z!)^ zbANG;tCx3<59%f_uL_IOux&eaR9#il{*~*azO^pceI8)(Eos><~0m_*L9v>lKvd zrK{gxbo7Z6N{282q z0meN&V_ZMuYWfF4)uAgx)`kNb{q@!)v1r(5@oP&7qY>G+2d-*F_tba%em9&RlYWqm zt%gNjxC*}1s>m9w@a5=VOk}mCrGzX+2M-G#l*Jl(^7_G2DVxWTt5yv(yetP$_bBI9L5yRO0(|zKfRKrAoiNg1knyDPg(B z`?bpGvNfj&o1@DO9tWDPAwiw<|4q{JEaEBF>YQ6)`n&L>KdoZS4zG)y)nyR{4shyO z+8|{Al8SzXGbqUj#7BoN3vT`!5NrwiDTdIYFTXZC7s?Kf&;w9K0N+2Y43G(7^!ulo zODNmk?@g;nuFb*xb81r7U=fF84rFZJdSQhUl>)@@G8vr*F9^PVxO4z+lNRGKRT>e{ zb17o?fkb}?3kJc@PBAU+t8`&haMQo%gkk1X@<$a67398lp{c#20@uC|13#G~a`g=V z52WZ1?1QvDCFic}D!}H}y7kc&1Cq27V6@Glp4$~pJj;M#>qq&XP&$m!dS39muqI5&nImAcm$6~6lTzoCT{U!R{S5~qDgO7H_KuURBLjPiTy504Z5 z>y6|%ce5?VlgH8l!)2tQzrTUC_hP&FYBPn?4^hnBY$lJ(zk(o=hTh`!WqC3umV@(d zH7Z!6tJUaxTtd|q0c-ts)GeonU;SGMYy9*ra$#M#LTv|kj1!@~ZHd`_P0X)p$W8vE zg5Oy^Z1+VnXX7bzSgu9IfC8iGx#;!mLlcZj@u@NUvJnxk68L)c8%8yo{nH;&Q!v}A z6E9eV-cT<%FX(?y^n7qx$P5YxqXS|C)JNv-PyL;i`>HVavvi;)ID*TjC{f6~G#uQh zfy`liDfHK`Wt@WTLXt&;;O8Hqc69frCySQku+8KKzaiTC8rWLlY~Y60KHZg-P)%Az zWgbh_7SdZ9C<>0;{UK*7xNZD{L{`Wv{G~qD#yC)s zDvafQFn(He`6V{=rr8#rS6G_2LwybAsAR3Jz&H{U=B#Dh7WzXw`-ZU3j~uOwr7H7n z@YUKF|3E+*7Q=AmBuG8sCZHP$tHL`9BSLFsb0d@6v^!_a8>7%-6>4 zrGiHFn?hP9H+X>8tM!~Jctn;TsYu$QI2-tw=2&zYG z09l;&`vD{yr`-kCtm)`xOBI?j3sM_x$kW2e9#CX6IYa(1wK<%WV6kP^G?Fk0FO%p#n8VQ!&0>!9e8<_w)95&m?te5O$e_rs++v>nIR}2Ww1BQx@ zN|HS%D1U94zoX1ImnQgzN9lUn!bWr>KU^xuHd>+p2*l{=D_}p=;>~eG#v{q`yj**d zO}8cRneu69rOzcFWGF#eXi&Hv%_7Lhe}Nkb6_chnnJ+Rwuy2Mmb5<$4K8!$<$c3v| zGloQ`{Yd^ox)N$t7H7r0Z%KcD%PCi9;K1eQDl@;^c6bcSDc!_y0xj3eW=MyiVbd;`l8il z6nl?uZs0F7OE3d+P!EsUwd!20RcF1#8tVd?farN8L_Z)43s|yn#ShEPDuAwmQSkyD zeaVNoq$ujZc5iw){nAh0;uuJaNH`Gj=WL4O#EnWWG^0-)!nD$RY#+0dJcK2N8E zi(i7av?Pg_z6?fW&*^4*Wn4T*UlLzoj-s~Mezi$5n8d=4ytqIwaA9N&zv^x4tAOG> z^QK+(VA-hQIN%w_b_`o7W#(pKP`$#ipvZM(NwME3jhijzF*_wj zyzNfI3%nMme+}Pqf(|wv$?jd-xWUd)QHd%#phC+@)n(eEP?WRq1is$hh}uvrbC)R0 z(^lSusyB`_EojT-g@Z1Hwx5*VoXxL@#}#9`G!QNyAr|t7b8&ES``*y=kKiQ*rD?@y z;1u)C0w_6F!q$i4)o(j>Z;yLAuXo?6-i!+J1%-b?tQAYz_NH$d0H`dIlx{68Q;{j^ zdM#!I6fX`M-hsubig~HNB3n_qNF9?ly3-$4z0IlbRn{?k{Ke7Bk08Bh--~0q^R}@} z5ww>^y`4~*0jYWdk<|r37_cJ$E>jc~sJ(r?@@J#x zwBG_(q<=yRb5b+9Z)CQKJrI)o94rw_S=6~4U&XQ_@900GqjgIffyYQFgwzOK}wY6;_GZks7NgP+ zK?fNu=A{axerh?#MdbUoNw0Hi-`cmWg$Mr->YSfEvh&TD_rlJ8_tm_-j~SRJdvD*T z;+avx@B-=$gPd&G&Xl9Z3)6nN;EzcKMULq(@eHaj!uS4SBo} zDYazjAKkF~v2+jRh;R9Uzt%u>dp-n?5+IF_;0h{^?RGlbwybfsZT~a(ig2Zf{GiUk z9cpx*v#sNA{6_yPRgmWS)oj{pxiq&U%6Yu;)VB2Z)xCKChAnu+6?iUH@NcO?tjO^Z z;e9s~KV;)x$A>#=pk7JnQ7~}%pf$(Ygc`!AJjQ-dT)X^sofMVRTuvBfJEfyy_L*!E zeFhyBh~}~=*9TQNYwysCQ;Y#q%y>AI{LjF{!SribXTk(&#o5TBc9WC?P*TK&8zL?Y zIc6L_(K)-uVJ|T8_a{!s4mn#tGlYJ?q5O?iv(|DnO`wEuY@poXLp4CDGYnd;P%P2>IeEO_bfBh1~8^1SCcbtdgF zyoo*~o+&JaeOM+Rjg?TgBlMxQ6dSYx{Rm@N>(;7E|Iann`%|CPSihF-z(3JgzaJhD z*-v8y0t?S0ks!9dT+!w}p|S1`1lTVZ7+`mU&iRbZIncM+JdH|N`p)%wp>Z=SxeFJE zc0n}kP;Z}_+X%c9?j zQ}AnhmkyEEeFtI?R!ma=&{LpFAqT)QDRL=YJh;O0nm+jqc`;efWqDgErD`tgoF~SI z?m~!$h_^-DfioXflqL^lK$qlYH^;@BsPud<@ZK6YF~VUHng;T-!)~$j{^iW+7T<%l zA3-CxIqe=5n@}Wj20~qx#+>#^JW|#SJr{Nk`st>>3%H>SRr^JQ?Q4@umwJ@zay7X0 zt!GT%GIg8o@I?w^JXl90PK2Ge2(HSt5T%9mbJ^CTPFpW9X+-McJA;-LnOrOF@IWDh zb#`a+BqVS=m1vLXSt zybWbV^%0lldq>n*H-%EL;dVx+B>$BDGs3|T=(OKKX}2%F{JZ0xw(AMA@acx$0r=i} z+Ij0wUC}85r)$y_15aRuFd@C2OU~+Ra9)4RxnyFWbIFU&n_HYqb|haFc+QHLv!W*E zEZ(HvAcNw0d%Ycby|7LpUEe%H1hWXhVd_r1iV|!EPNQAG$RoD{vTaH^3zo8wd9xWL=&oO_ z@iGjkrongi1;`09xM^{B9@!>cOOu1x*`3~qQy2^E1GWNdu%)$b{pbhTsUyL1Pr*=z zLLWIkpxhWI_h0iaT~_@H$4C!iI6)}fQg*|gXESUJ)e+vqNzL63P6f7;2C|F$e_R+! zvSOeJ4K6eAr^PmZKgOWet&2k_cBqV~z~om(IjKH10%XJsH%;)6X20T$Dny$NIBpC4 zaDSx5VB??%-4;fSFe1Z?uqtlxTGxm$ybYuzN{ha#f=>MwudDO5c_HSZDXyu-5FDTX7+?k*{etcV9cw^UIyokuE)&$#OPhQz6<#mx{q z=zBtj)u2MhB_J$LEb3{>EKP5wF;iBq*R?f2eWGqT6(vpC&5TBS;Y~J|| z6{c$K@fUhrHMlWS99&5X2S=df1Y;wby5&!>PhE*_e@Yz5l%SL4S_U*$0f-ch;B#zP zrlyzP*FtmbwQ&<2)F}2YHf^wh8ux?Y5yikz4=PCa*fl8=3|ZDomjSz82CP$G!V=QD z_3iHs5cvS>6syuKu?M}%(v&dE+o+(XUE~qIGshdUM+GNYl8~J_Bq-qpr%M{d`|NkT z=!p#lnCl^oG_6~&7;M*=>n8)u#rXKSWtl;ibAoH(7H*B`);8TS!MCZ(U#F8S;~vG9 z7_ELg8TGm|2l7X6BB%m#R${7_1|cT&i6pKsua@RBn?Em7`V)kA7_kA;A@44R=IVVp{m5|)kwrXOVM6{ zED6>^Kk{!$AkXd-3wrzBxz)Xbz5S9GC(dEe$NZHKlZ-rzd7MvL*`YkkE4{ihf92zP zt}FK^&gD!2Rod3k;lQltaG%F)!Jjpd|MFb}`C2THEfh4lGzjq)4izz&B;iuGUYrjH zhfeVf7)h_-EWh=C9ddiyyg5tiZC?x^==_qfl?K2pYl_?4j*|Qo&(|Q|KPFeT2`$BCAgugHX19cX{tU$Xa^~6K)FT)Gy+Ji6Fcsi-OJV|J>r2&F6k!z# z-DYcu+GI~|&*soGHupNJf%+zvNba0PeRY|8La)8N#BpNi8`&bK$-~WI^|x>0N^nrC zh6>!@pE-8W%iyZl7)8(XM;xhPwS;UTcWNY@7p%f?)w=bJ?^wtCg5FR*#mrCo-QZ$Z zct{)^Z2#E21`5(ul((I$0t%mLg@@(}KRO^2XyM&pTv#~HMoA0^Nh?Ud-?Crv5mvkl zsl&IvplhJG$;M#MN+ZIy#G%0!E0*&N`=v$Hrc6wN>0vBTty^1jwR8;BBD(&@KF$q4 zqCx3OV`c;FD8Y}j)jMsaHnl~y)wy}a!2EbHsVwTsvWvP~?29ex-i0UJCFPOC%;0=Z z{Fy#e#t!vv)|D*wI4%~$p~fa1?9x&o?5_qP_mh@GKO2r`U79N^OVKJSrAS?6TFWZZrfUV~;R2N=>e*3?q`( zl)~29Vv~*%yw!sPZPJd59>YRg7CerN0%SZmYye0WN12(<=1HZ;@N^;CSfYYSze5NL z3_*6?x!Yh!5QNunGX!CyN0sL9EYtsSU;8F?T32GB!XDyTx&!)NjE-`C;Jo0xUFv!~ z>{MTXCxI}-kU`d?tHqfr3YlAqf(p16Sij;fnJ?e#?=T5^lVqPguH%C9X|f0VQtQ@#zhFOX(?kDKa8YIfZ^ICL_LAUbsK7gU z06d%GzGe{qW41x~Fx_utev|4W?=4r-~~2Qa&Mj2MEoq5SsfXJ5mQAE{jL|tvTFqz`QUCPl$h?uK#}ZTgiP4eyBPYfZlTv@U zhWy@BULlblxbtIK2>`eMLTPVH&QU|^q4m55-{A|bM6K?WZ9TkmOYqLII31^QY)@BB zg?a{1^}L@7^_OQg0&c)3m=8D8`z0K(DWT^J(Efz=)O;?`*Z{}yZK={}KKP~HuPto> z082u9UmGT=o1EdBWXW6r#WqE7sXp<5O)5MIiRG!AM-`W^0``*toGg{!c}%BQ2xTf0 zM3nHwKoFcCO1|b#&`K9bl`;fHE3HE1+hcP<;4tLyHEv^WL8UmO%Ogn^s8x#&RyIfO|PmIOcDp9o-l z%_oQeU6O-DFam(QZzb&n$z%|Y zTb~x}E##wgU-0mNJPy@}0=$nH5Ze-;4{G0)&t(CUVL3Me56e301h0-Ve6XaNwIqBB zmsCHniciQ@yx)=s&EjnPI6}~2fn=R?7ARCZ$uF4!H@I@W5qGvrgu$49S22?~K?3@M zI5*?y0+ zWhvfF2P{juyW0MGdDfR$)9a~2)Su0&@{ zH#2K6k3%Cc_fg)y``B#2B=OFzU3KP0KNGq?47jt5&XjyN7$0UH860BWkfM~;$nA4+ z`1v?=SGFr!PFp@INGH@^>8_cP!AthCU#atgR$P?v|0U)MHHdjoC{QJ`Dn?dp8AJVi zfT76wN^l3hIlwKq7}M8Id%-Bmw_QTKrKOQxZ0k_YI~KO6gt!Kq=S^5Psjzg z=SjC?ZsrIs72GIlEg$8(uTbmGfcQLhogQ~>aO9KrSSa!n!wgDOrVe3#lIAgX8a~uK zn8C_c1F_&Q@7eHpBr%#3;K6^rfu#B(KzL=DQ@YH*iWVaK=uD&qSA@@bNYO|7R3!O% z6(G3>unjndCTxTz4Z28CiCL|M91wlpLu1LpIlryd7doT`EBs%AnqBMySzsd$I$yj26_f2e~)`Dw>vNm z^{Vp0{l|^bgQNMd@&%8pgT-M7`+~oPyqjAld#vPqjU6qDD=q7u^9&b#0k%jJo3=bS zFF4%3J`;Yu+0?{BV6>qB!Ea~T-X;D$HvS5eQgBLwLx*McTzPkn3XZ0=aBDJC4ofB? zL=EA0NrcO^PI0coI^D*t1Y93QWSK*PH&7wNu}=*Cey$%>k!a#*zMm3t+HR3^nJQtP zpX}7mFI|v{qN^-W!v(6{+f$(ymR5EVG+d**Y>Ury-!E`hKPDUhTEB#2b9pcJzZ@3( z9?{7Ouj8!wfUijjDZ92w7E6CbW~l#-n15!}xpxnvl@%bXy0HWk*IrB07AQW7jS#w2 zQ^_*9p}d_aK9?ggNLeXwI*jRWKF^-zcS)ndQB-c}=?zFMURa>s!cz#yw{n173LxYj zqgrg|=l;Q+AHNSKwuPjxogYDxq1w^)?B2|@?H;X#-vc!yYKXz2f2_j&Z8u3d5L9Wp zJOrV>Fn!zr2p0$hbKY9Po&$2;x%w3us5%n1Ut`rV%pe4HmjvI!vzlJ;$eC=Coi^Q( z$37$rzR~qX>5D@!R%%Zw{jL1~u!LLbCZ);uE93gZlx}}O1JVo#L=aI zGMz%}bhFlhB%-GSRDvX9|DxMnLSSuM3MjSOhi+V8j{PJSEL>>XX2@10qTNH*DmQto ztP;q#^BUr8Y?#nTDpl81rQhT!cop@sD{{El@Mg>Ew0#Vy{z|jzL5E(wfj+10)qyUI zc0Zo$tmc$9ch{DrzfL)LKP?I?-zM@2l6!Lbowk+KZ`*C%i%v{Wqnz^nB%AN5T)xCb z7%G^?w0L*_j)}s*vdN&0U)gNG=XbY@Q!UkLe};159-h}k&wisn{8Nv zod9hcbw+V?MjdqA7}ptbmwh0(jN-n3qN3hRP@|$C2JZWxs@t6=1pU7E{oe1r@ArER zC->f}Q&p!{QQAL(NV5mF! zUW#ju@_qI#=iD?ENhzuNbc8rp-J_Cfu+;PwDOc=@t9}c&foshvdYl-=lN9t!E#)Ye zpT)&Og?`)LRKbI!9wte&e#o-$w+Y37Bn(vC_zrY-t;&;-I$xov{Cm0>d$(s~!{7AV z9>x)CpWwaB;bIn8oXoJ=*tDj1$<+UJ9RiDkrzc#&TnT2=9mF62t0b=J-;l*@)8XO; zTm4V3HrRK>q3-h?ED3A+r(m7XkZF&!xm)l@|I=%`5}fbg=!dm}bF$!|bsQ~UDV^lg zLnV2C2TvZFf9E;L9Ma%gm7`JQSiPn$4vIW9Pi6KuYd~Ma0PR?8_F1(o{9AR3PBBbU z2%n@H^3Z%XTk8s!R>|4szqaQI(>G0j7EH}y3LRhG)gpd}&04FI+J-#>lK%&LB7N$112nLZh#3lCxQY&vDV$Hv0nC z-b8sQ|D}P{pSV~8rnR= zl;5LyvJUs`ZJG#Uf;!7Fj#5nTKajlX}9iJ%eqBpG3`8SN%9!JKW z1)Qhoab5cbS+m&3)5TT)fvhgWH}riQM;%$FCcaZN5O0p?6-M0mxQv`!^^ZEZG@*yS z+7nnZ>_DJArZv#n+PS^ePI=q4DgcV>TIq^X8eP7nJZT-pbBVKx=7iW?Nd$!9g4C~o zQcYETu4FIo+0)D?bNF!1w{qq@VCS@8=Oymvc!clTT`hl~ zx}LxOEWT#(Pl=U!HR^2$44>qyMVVrsN9m>o>OKP9w^8f{U-nw-XA80Vt@PHPLc~7I zt#B(4H+O4-Z*y!4Omx-X>Vy&?j2pa}gI(%Y5IA>dg7&61N~e*sxw&1BEsFO4Ecg+x@1Gs*UnyNy#7j`& z@!#s<-e*av;^xXnI#!E(jj~dz(YW#!{>rcENB+P>!RCX68?He==2{851sayddSa~^ zRM&r?>ElpiY-Rf!2(6;v-u{R{7EJ;x!<$6t2xtl@7HN;R^0Ek#iZunE5&~F(FU&`% zV&zktCfzt9rnSaKxatPrlmEn?|8=}Ok@>-e!W(hmx%Y65MrcocIEp!ch1Ofz^VXFu~OpE7JSGvR+NNaN5?wJWnhAVq8T#0&q zUh_t*WekiIGZZam$jbgf4_;(2f5j#l0iBW+8q6Paj^MA@Xfl^q4}&+$Jjt0l=_f2W zA$UERyY=>S(Anr)2uJ1Tf2rU1SQvehr`y`ew~>J-$#J4hZ@1|Q}ICX0af<~=O_#_FG_%Klv|K7$FpfIjNfAQ!Cx_l z^0IWxD@Q6hA$jeQ+AKJ3`oE62{%&T4Q# zGYn}P=5OTmdA*IAmMC)Tgjviw;Iq3vBf+lB0}Q6cBYTG@k^O#KhEH%Wo$ym;_Xy9$ ze9a=C=g5eKrr{;umGaq20z=t{S|M=SggECj6d8?aJURMq+GbhQCF7sVGFh)QHB+{l z8wzn?S<8gAdTvKXbBKmWkdBM7n$STWldQ3PUJ8=V6Pnq@(4DensS9!8uuUqE*%+~v z6M^-Te|KYMg0v9$y&K|X-G4mRFLM_xk8i4@4dCbNm&y>5CAMSToZRFj>=DS0Tk&ZZ z1kLwzC(q`_%oxdrc`vzWGTv~=5dO%NC@Pfv9G-{rGiE<-Jlix01+F@IAxkN7Ptn;} z+*?JuJXXV^{I0qW2;yaZU~;^lnf^xq+g5fL+wRv0sR<{)&8m0(rL&(M8JT<`3@6{W zP&U(EMwz~!)e_J0PQHU`{yZJ&Y{fNithYd(Vf0p5kL>gx3m^OE(M-Wz@MJJ^*=iYG z%KBD04lxQQnOP#(#M1C(u_+5Z!pmc0 z=$TjIMd;)NYb_sw>g}^SbLKbuCz+GKqy3SbWp+;^&{iiiK5YV;v9h&9j5(s%wCSsGwF{62;paMIAi-f;qXZ z?Luuir><^i{rR%)D-LOW$^6k-F)yaOA+#6WUw4Y@HD7;_Mr4x}NRyi~Y8q+@w#o1NGv-O*yc({*6V+Kc$`+?dd|?(FWXF8$7D6b(5uTR!p9OlJIqc0L>%TaLaK*MMZM4ZO z-E@7}4;B&`@NbtHNj+03(k4@B5GltM2KPOdEp7GJW)W;ecPP@^%inSV{EKiFDY!CP znum#D9Yh7^cah70>Jy-`IB}|L(C+yOPTYX`$6JMbUlf{{lCLVHJW%!eO9uT3`{lFX zIO~P)5s!yNm_cA(2ZRLPjGdH{5$ioJFg|9mKF7*do^xbh|1X%ql@^s|lB+h!an=tk z_RvY=sG|(LDIm`3iR78kdbyUaU=g0e7TuIye zN`JyWs^0Fdq;1WtEu;aauJ{r(2IPMd>_OW&h>qw%ue(;hMnLoF92xFCk1d-P$m?}| zOmZ`4-o*v>F;;1gBbEoBJa}W+b;l|G$_!|jCOa3Q#8D5(r-%Jt!`{m-IdI~Lips}@ zvQw0F6V`(J^!f(D<0UHnK`S{f?cK}}X}U~`v6Nk`QO}ItRu#;(p4x^s+Iq5)?n2l= zqzu@Mq-r5}71!Jveg(@hPISnX!=CZq;6_s(f6#&vdP2CsI{#^rvu`g6xeD|>P@GJz zBBy3bcYu?7l86}jIxfRxY^i>6Lu1FFe)7Gdej7#?79;-Pl}+pa&88fpYcD+|<*YL0 z$S2l$$a5+Qbbo|}=r3jPt|0V@b=S-FH02KO@o-OON34d8hwR7g=1l#Cb)h(#4t+Te zePe~bQYr{BVc)Hw2ScUC@ps71igJwjPycc83P$Q z_@0S+hCPR%VhYKjKE?gMk7%)eB6qC$>K|y>h?c?H?#l7JA`Zix#NEi#xvi(FET7#S zL3G~!_xPJ2CLoTT4isB)Cv>u|rd0_}rJBnStLcM(BDZviOcs`N9qL?1I9KiFl47iJ zYM93_^qlIm)q)u2k*LM|9uO*^9~Nx-WDw|~o)rbyqXF5l1Hmkp-S-qEfb{!Jp^4mrj(+V`$7 zF2<>F54&1?mE8$7uCof6ziO zlQ{*EZwsJg1<~yHy4mVX|Jik`f9LB5h@T0$?k%515zI(O+O#`?t23rD1lrxD>sBgN zs8&z9%#%tf)0H=kOP+e>8QyJpQ#=H@Q=37)*kv#SG2-z4YwdcEJlCD35iSBt&WX<9A zJ;qz^3KhMZzM&$*&B$dFX_Yzbe#2Wxrj_O_>inK>30(#TogLlYpRUgnPN2iX)DFcE zV#?*!hgf@afNjtR^=HiV#`~8}XJ<-J;;_snIzjy!J{qEip<7EJz3tUr$=^lo&P>rt zeT!AjPGj;`n`v#{C;OgnrC(NFSEFxF5nB?&t0uPdBfPg5NLPI^Z&Pq+8hmB)t`8}- zZq2~JunvnYynMm1Yb6XGHTWKoAhSx#Dt9m&8+`vXm@Iq#!Q90Jd{VN`@sb=;`wsBf z;OlanE(XM@<}Qfnz_A-xkc?jDVMYY6wx9pav;ad&InMhBze=0~~f zxNhGIe|;Zm{C5TGm=y2SnD1#!%j67)zjMlH%U#;{4vqVk#*OR|Y>fftE{t!2TcvS# zY24HhZf1wL=^FPHja%bjG~7ImySDPfTP|MX?*yL#&6Y>C#=7ZXPHgl^p!^zr|8(w} z&z4qi@Lk(s(J!V8qXbur@*fNm=nou;E>*fy<8C&^j-yzLWM@4IkRMY>$VS7>Px2Qz z5?PX0*2yCCrn3>b8){9~*?36R;HyIJMCKX-`m+EB+ga3)O-izc>6Wk3*pCTE2-H$~ zB(4>w@ya#c`d`7bH1FnUyyru;{aWrA9~k|Nv386Vw!EOR>=4!ot|PIoA0t@LXe_tH zQR4>Rh3&9PHP(8Kbx8=Tq#ahO#(G?1Rfe!uw!=C_V?C^~ejmbmp&iz~(b~-r1MLl;lelVux4tk+cZ{dD6do7m3XnnxwBEs1rKX=A{6OT1k;VAU`mE*|2XPW0^8C)R>+dqi4qG#VOvPLwgY z2$5AHYC)6mX`}9xoN75%N^HdESzu(v$SVYc>lFGT_mYOpLo>gWCV6p6%sz*7Cxo4sW!VmK(bjcj3P0a|P#ayD_}6At zqP*nU^cDOK_*#OjYfCthgudr@5}~|#oMdn`#(trXj3~+)G?M!)NRj@Kz;F^?3&ZQ8 z@n|e<#UJ`WSQz5<2u*RTpg7sSH$t+F*HmZqM)0%*X36vu{+J#ynBh$qKQ8F3? zjwngv8+=8l7*ZWJ$U%RaR5PH2JXrAN$!6}%Ro4S2)2N|@ue%w2%1Q{TE+OwRcS3si zIvJpO@|~Cvs~pxz+N4z3+|&wHAtYPpQH91VGjz)urrRTHj$E3KLuvw9)9L1i268zd z$#w76ZY*4qAV^h*y zk8O#NX}Ki-&i%8~sR!p}Cy7jO4&hi={oPCz%61bGp0k4zDJPx5pqXa;6CKtpFO7oP zj)4^sh5u)5;oaQZVnVE@VI*u|&Xm%^Q>~*hWy;i5_XC{w%UNOjf^vAt8i{k&zaNbG zIT(}Z#K;y1Dlq_=Ky@)Vjq+wIteWv_jI7iwPfGoVR zo{;p8IXT0W5wfv8d3MIlsf?nBE|u2`Lruw8OYv7IL%J-(@V|mj0Gx8wQ-AbMoG9&% znWoVtJ}EV`ggA1t9vQ|HvsCvl!JeN0{p98lND&8uMYN3#7fPRirEjq|-op?;I$icf zrL+9bI3^#y{V1KcPQ_7TUf^JicgYShqEk5{x_G);Wq&fby82I3=7WCD5~jF2?~6O$_!P z4Zdz>?Ns#1FZ#AbvfrB9$}!%Kc8u4HSce42sKV7k(Uh@%I>#2v#T;9(l&6PM%9ODI zB3|#h#Z`BUw6N|VrE3iD5_vXlhA`Sz7}A{;58H-@~-_l&+y)!)I&Q4%%s zHXS_YpoFmq+*oRy(|jfeEtt0{ZE~jQW1!(9O`=3U2S!Jd5CZ{hXy-Ac<)=zd+1xXu=(ZduE%!zb8~bV zX9dgn*>oYAr5%;=6`bQ-WXjldXImMwbs2fbDkD#LohzI5CyFk?_Nd$(cCi$b2y_Q-W;^PqrluSks8n>G=?UF4$evG@6O3YqNcqQ8c5PBwW~ zmTz-(SHp$@U)%O%w%OlRVEz6MnbVxWci&8R-fN*$%D<*nu9IT?^%ghs1x`TU$@-D6 zZ2yz#B!}Rx0ogqzPIcWH(5JhJ^2iv-Uw?pP4fSX8R!6GuyHB1Y1ND+^*ERCs$H6(1 zjm`rGX{%Y8vf|+QTv>=OOWH@~XI?ne(`96Sc4nqGcEyJNWHu#ja)zhx$jsdQ@vi#U z#FZrRWYWT%a{i2}mQn9=mUsxmt zCJYz6-oxZQ1^ben3F3+k!Z)d-5S`!&X_D;w@VDS?4C!pNwq-u~D9RlR#H zOz<%L*|Q5=^)bTIr|PE>u;PVI)49yAtiH-s-y+VH7F$zSD*@l$U;i+bk)G&viN5Kd zWbc1>iyc+}#&efslhK5Ofty~Cz%`<6ft!{{1#4xgrGL#(Lj3i~{B7`kwH&)tKTL2m zC!OjyJSoZi^>JHfepfGz7Xr* zo+AN0WX?Gso@AvIt0If;YfSHA);J5aByN;_=i$=b*VLCqU{i`akl;=me_pg?^x zE$Q0ndOAOL|7XLsEP9Sl(Q;aS;)0kI9Wp=GudjX`Zc2}OQjCPZDz4WC5o-U!c%-&& ziWE9A+P{mG-cgUGL6+X!)A8btl2V-^vW zH~TyN4X+R+Z;oUA4ZFDYuX&5VR`zKyMCZ|OM?l+Y&ilB=?O()bz_fy^&L>PuixwVx z76k@uyJMQJnrNNhIR z6{sI8oL-Z|-*CxlswA=R!12%Vfe^1^cloxS?)$8z-&=fQeilb$mNv?P30S8XM*(>G z?0-_kShT)n@L_wn=@RPSfu2C;Qs03|uDVmnle;`uT~E0inLFE6KZL%%DN+jCo7_-; zo{#~Ne8qm2V`jc;kva$&er?;OfEy_Q;#~C$CHMNFq#FEF>6V=_rHx%8ly7qv-|hpZ zE0!L&)SuPETOqknR)?GzMScNob4Qkz!@66xavgHM=ft`7h&q<7+*?> zqQ92sx-_2a-f-2YaDB#2{!$vm1aw`VJ)MyL4HrS6CeNRRdoheB*UmRB86#r&A3TN1 zERW$dr;ReYZ(7GXiGX%Z{0B3st>J_9A!vSWMEq3=O}kh}Y&v!NO1~B$W1wUWV4P{m zHfO;Ij1eC3$Gyje`pFB;s*Gc@CNWt$AMrh;Kli2v8d8PZZ@3sE#0=Ns>EG#E^(`$} z9XniWi_7;ZPZ3(t`e`vfS>rXG3elz`TQI+BuB*Pgu7ub{>rweUNY@S)s3uvn*4AL+ zA|2_8+`!4UO|P)N3H#pr->e;|V=xzZQd{rF#?*9aXuk|H$wcmTW^%QDK9{DRz_PHw zX24)-KHu(Nvj_BmPIT@Xu`&KNoB4Zc zgEqen|KvWUL2z8Yo5Zg%Ss3c-pCOzqUf^PMoSmqQnzQVFa{P1R(pmjv*@`vjKk zkTyBn?Ramj44xeCs{0qRvSL$j;!er<z5S%3+e0Bj}M-^yAzqu~Ac^BX;>VNG7Tw zuhmt51$hr&BUaC~O7?V@b0~AC;ubYbwC8RfIQI=##IC5Une{*M#n>~a!Zl5R=Va4Q zI(yh=IL1@6^?>yXpE()19qaOokm_EyxybeO6KU!Og) zb)$N07&|ABT5fu1!?EU5 z8#U)d*4iYuxf35ocgec0%ZNV9eiVyWHk_jt+g^vk0wC03lz2H)_o*egwJ zYFpa$u-H@+d#1$7qAZSY3yVEd$GYnG5o0PR6 zzUAeka~hSa{xcp-ADq&-;50~Y@J*4DXn!lPTqoJ;>9GR`w`=WkJ9XK|xy|nwzrcus ze~oa?=9mf7Gsucd-Nt0qmx$%mKpQ%lW0Zc`IuT9<^Z+Pe(&oyi=%pqj>%e9R*Wtbc z@ob%;1xNHLMF?FS(R8+qpPrW$LdsQtqEzKo#_A%`U3qY*pv*SDtoYDqMH5>~TQ{GI zfnF@)wMGVY&*=VpXrk|6FV=PGS|2Krd5)x}&fgQA3WuAvqGBU!Di?S>y+=;Sosi+G zTQ4D=1(h|fx^>((50^E^s_8GHi`rGcJ@BL`_FQd+mhx)Xzf)f8e$QS~V&Ke3!Bzhl z$uhu9eg2t&H(I*D*e#d`%eyi^;q|_s61x#s&9pl_8!Od@J2% zx=p)`4HF~!Z5^&1d6zFrrx4lDD+r@Sx+q+U^epNtLmDyi3~BVtbYqr&i4Zix(mw=D z_ds>h;(Ae^iSbQYni_Ask1vWe-2rVq{aHhs%Z*E!vek38UB8p$z76s>(j{-7?0#F> zI*#I9D_faoX*!=EzNuM0HG(Y&SgR*4N6L=*NxsA9EXX%KRf_gdtGhaO*^^@g(bzpx zbH6t8nbw%YFhJio>XM~eylm1LG+j@5;YpjC2{7H0G^0^+-Joyi2r;XYK~uCeNM5QL zk@~-1@fl+k~4k>ny6E{0> z?Fu*(g#q?C3$Pp!A(Yp21FVr+u36AO6BPM;W-7CIGCwNsJ!JJ~g3!o9zBrLv!crMJ z#G_}u^@xEs^;Sz?;&GGhR8GjV&`Ik;1|72K&eP3$W)KE7GeM4sY$#4lW+yfl-fr>B zeAcp_%x4uRzDKS(lsXo(+LIpz^_IdZAfDhoI$U3KiU%;L_(Iw~}Fj0XAi0H#R?`3pE9!$jOC|ADJ}Q0X0{ z6Idk65Y=8j{{*YzLB`Je2ZrVbwvo=tqlf05iV)*()ZhI1K8=L!N!}e`Z2}PYak?KVa34r&1ZziNtPdln7C5BOC8ME0CFEmE1@JOD6Y|i8V;qqYnto z1IVY=ylZ7f*c^dV8O^6Qt{e0l=*&EbOJws6GEFk|kZKL!^ky!h&uC?~7T!Gw^QClh z8xZL&C23Ma`alU{TOHS?{;o~qB6+hrAfid$Exi77sXr$}Z;$S-{*=sx57dsY8Ru>u z<)4&*6B)4;&ap@~MzX)(gC;lrE~4T3;}k7z=<;o;U7gcOrQ$wn zq=3T0yg&yQ0c`GP=(ERGLW z?@q6Fug(g1W6sTpX~^s2-(qG0Od9rbx_3u(Bzv*2^)#Zil~Y-_!acuM#kfF-aX7~t z#W1vSZ@0ZmGwB4Yq!;?SbWg~m{bEuB{W97{z{D z(s!MjSNU2Xl!OgsSPF*_WhHV`8VIp@f%5Q(gvC@utT^+q>W z>O+MFAXIV2cnIQ59uu^)rK{nrbFdzfi8lGrq>=3p%r-^AWud%!>;46HB?fL-*(Yl& zF%@enFXhN1+By;9IMCAc4CY%Lz0vhY)M%*nS0n_28a?usOHTYYtG{Hf#gHzYfb>$y zel+;yYqT8d?I^cmv(|qZ>VYoor-jfdC(-PuU0{v$2@?-?(@cB|^^`9kWKo>dw$M~u zvd`1BmKthyc+wpV!IbD6iRL=i4;2i$49#tuHSy-N(;m$Q_%Wt;SdGn500q|iYlV<& z3?UX-B}rDR|D`q7e0{R#Igx*&5{csCwk99Y_3erPBs3K!IhzzGn4a(|ons%9Bbszo zR~pH~nt>(sqL51iSes6S6sn+S0(qVXX?3!n)x2}0Cz5ZC*w1Pl)6-%Lj8K_%mez%5 zl5{)#{2Ee*>6e}mJW1;QHK(Xb3x`%@##+f>gC`sFCg@fA+`Ofa`qTW@^+~o??$`C{ zZmp(x(1Q-c0KJ9!?^g(mCUn(p)k0O0sES*v@tEeg=N#WRah#^TK;GcHsg^z$m(rRZ z?86pde>z*L^dnWGY&Pj6!Z0dD=lc`ikQ1>78IbP~lC9I9N9(^{B%2=&<j75%>5Jnguc%eA9yCnRBc3cxJn2p)*PpJ@-@_yM|%~#0sXow6y!& zgRv!b<_)rPQP$*_I?iyD0CViYT*L9+He41)wSD<;ja zbFc;kvU}Do3hyO7X^c%OF4x8zd*|HoobQslLvh@PyPnaI+SWT}u;ECd7DqS_`EN^Nz=!9NpY2)wd(IdAHSgRi0khJ5E5B$f!VMwiP!m>ZCG`9qB$+V zdb}5MA%0m7Rt=-q;QKp;a!8%b_26?$a%iF38DPa=tiY8{D~38HnQ%dgw&tH?@@eor zE9uECkT35xj>=@)3CGT4uw=q_x|*QQq>c#*9GPhz}mGzu)h*8Z-8Y>iaWV z0^YqG%9*hT{jvFSk}1YF)cy~^tN&?Hd?3TxKZ#uS64PiR-eJqepS_n1U%GF8&w#fj zK!z>*_xpD=?Ib^RsJkA{@loGTII&Cj(IB7IMhfg?=l8zHsA2qW|D+biKd=Xe!JJ8Z=XYVvviGCrGki<; zvD0x-YN%DlKI(?tWb8qPb^^NwztQwBDm~oWGQS%w=ik}1kw@2tcc50wPM_i9_xg9j zrTwmzcN4{c!@u*~jE_!T`d*WW8FJj1vCpkz_V&xzw|WcAfi_%0XE7`hu>*Gg{{N zNIB^3219q8>)m_m_&wy-ujS;|L{JaXR+i-QndE{H3-jEi~um zmJehs^psQ-mlV6lR~CEAOD=Y+YBi{;x^mW_nv(L;LGy~LYSf_eva7Bts;N1zrm~yr zThq5jWvYd0ky@;ZDvGNs%ZdlhD=9838kFWOE~_l8E}Au0C1vYhzsYJuSw)%W5|zYl zX}Py%j*jY=t!9^a#+Ox$_Li2GR2P&jE+O26PAKw}%`eIIdaAshf}(j<Wb zfkz&yio7-aEiYQ6s!PgCig-xM%mkyR#8coYsV=FUTv_g&N9g4R*^=*q>N1j1rlzr= zq^72yi;i{sD ztc$B5vl_ZCAFYb2t0Be7Orz#rb#=)s&v0s;nVpj{CMUNbBQHO9Oouq*G)_*&gm8@Z zB!!U?%sX4B%g;zlHwnjefHO_w6l7#v`d`d^vP#dLG9f3|$$VDjyg}ZIp*1BX6@x?; z28~WDC`gn)Gt#FHn~|R}IU|3xD$TCQDk`f`rTHcB=Bn{!3xl_XWw5MtY}xENnbjrN z1YIQL0Pe9jw;pV{6_kWF=KO8>68*rdi5er zOJ+$)@l_(9r8y;~p7atCpwfJZa_*<8^1Px76aE`{r)L)w=H?e>=T1El;LRLn;Dorn` z68^MNP(Gz-eo1L%^*o7_8kgtI5smqk3T957F*!G9()f%Sx(QTiVNo^8LqmA0t7!`Y zq&>@doL{0;dP!-Kx7-uFx|52^i>l}KYkQtwSvISrpTdshR+Ur~f>bHyA`EL* zWkm&6L8qAIsV>(yrPU?WojhRhjFRf=%4+>2xk+eMNy%J&1FMSl4K{8@sdGEW>nW~W zP@%((jVsJ4m@%uoj7FLxELd`2$sOFKps7lQPZ%DB`6_?d`Bt~D$;7fUls&p=152;mO@1VY3{;Iy` z4TW3h^{-KVYeuS^%ks0w6r7)&tjY?#6$Rt-MytLH-TJ@Moncs4X9AAwijHA7(rTn? zFw5}?L^INK;P|47qS+0sQfDLJk4LVsHCV`GMXpmakTPiHwe+K zK9-@C?9=ixW{l3Bkd}X$np?8SaW#%)_i!bvu$3WIJ5L?-@{?7;WfR7j9zHwUAhgTI z32o<`q!;8lss7W6vQm@xiYoZ)SyUx%nHPJmYP9dB+d=zF>1DIa zMpt4pFt_uI%DpgAdI{IZe-g9^OW ztlKYX3k@%zdJ+0HJR1)cbto;H?L|^+JP0-}Z77?t1WpO!L>uSaVM)?B{Oe+Icf2Lp z6*%pN72+6o$bHEm46mjwLz7UNEjxRh5O#E)9TBEk71jX5!w52z1}Vy(MyAeypghbuuwA6=Fi6J=w~Ft8mJ z(r=uQlT%qSyTjO{a};zVmmMXLMxi>tQecN{G^yGKSRG|;aHJP6sPtB25g>ct%BWZmF?ksz}DhgXUEYEgFcyny1QY1{M{2 zFqt*Q1Ct$FIgo7VEik1OCFKKW>3W}6RbHdcn>WOZxkIK*HmcYuaZ-)K_K9s6Sgc+9 z;8Rsmu{a#sVHM|9JFaqbR>?w-~$QHI;+TKX0fi)O~Q8 z>4T@p&>lZQcg3_}i7Kqb`x)bO#aX%wHd2sYRx?W#mdvZFB)V!5eb*e1N$BJi^gD#; zOG_3lz-_}bCePWG)r(YCb)~mTxSB)KSv4xHcz#)pMDTmb{>AR8TI~{`3W$j`@H_5r z0bT~qifFZG15X0M_)oZ>(!JF#1y%qz0e=P_0Q$zZ+W9~_@C(nEPieKU0hR#Y12+P9 z0uKRC0b79AfRBMM0X4PNJ_+ax3<1)B9AFwy0xSdkz%9UEfJcC5fZQu73#bMb0}a5P zz{9|1U?;E}IE_yi&H?HiIFIWEVb2mi!g(I!T*rmQS8_iQm=7!kisz-kO5jG|HsD@h<|8cO1j-*hY_EOnu-*Id!}e#u*E}D`^W%W~ z?}zP&36pCJ&r`YH3%mq;1N8dGVf#X04j^qHZPC$>R~&XY$igrI*6e6tK_wbt+bj&U zSu3c4MW8mTl5Mu^w^@>Ev+udhT2i|O;FAKI1$cHdz^X!tym32-tCj3)rgfxiK-11&&TR!W=-^aaiV+<*)Ck+@yJTA&0t9eA01$^o1FR{{!{ zOW7|$%PGJW(D(=FewHX{tKA66Cx>jC^APQ45r|t5h++hyKf>@Of^a*6kk0z!CIn&C zceZ^7!tnGrww;48e9~;&HS9y%mBm?q{R-Y96ivL+x*aAKd}iCHAROO*V%u;3hi(7s zV`StbWbi}U0k{!?i2(laKKTPD1IGh{fknW-fz`wpfIFUa3rYVL`4sQA?IiL(lXCJY z?^%R#Ds&8jrc~(jL#uoRvxB-kNB!g+qjB(R4{!RP>`6Ot`qB5NDmDEK_HaI1sZA_l zT7SM$Z?T`vsiTxym7&y$Ika~^ZG0KaIcF+WJ)18>D&Vsh{;~;>?Ne%4fOh?ZQV${= z@2yqp@B>Pn@EC3Qlv15HDE0m}7KXe;o4l^nb$prm(#J}D{5gxJo0Ka1R;iB=rd|h? z>V_6?jEYbLSuaw^;;TWdNZQydLbY;qNz=)EWx!h5#?vFzdUu4%J~KkCJS#%Y;hXIi z;Pk!`>Y=~=ZPdSBd1X|}4WEzdoBfAT{?)5T#hg($>Wr9cM@2`j7`39dc9c7{c2tbJ zc2s0s?Wl;D+EFSRhy)^PN7bs@QGdGqFO|7L# z?8xZOe030`y0TiXyNcx`!XA7~-jlO;PEaSQlU0K1!>ZW6s-GID&Q}+y5scTfRi2uv ziqu>+UtOziRClUJ)JFBX`cfTICq)d2m>5wLaa+Weh;Jg?k&`3;5cyVQLR5Lwwy4DD z8=@mS`8vgQeyH>0F2~30j@j0AL$_Vs?bw_i&$)7XcIov^eCLx2PyXoC`%ZuAj1&64 zl=R7f%LiY2;j_d4k(NGoS?)Dc2F-l6>?)7FTv3+!HzeZr2o+fxsiJ_$+bP|IV=+df zooPz#O#9a>*N;NY_|>K%g8XjUqEr=eCyImt2LZtsI5@_D;K}n&3ExUuS>!0c)JT1i zG^ykf{#%@0dA#r9?r)DD;oImL@#M$RBNrD;967q%=_6wz7L7b}vQnF`kerwXewgd? zq+P01Pge5mK9Ah`n7rIvk^$M)DHX^AW&%|}EpQXC7I+-k4D1H9Gr$G)qWzSTZDQO& z5|9l1R$id|x6-;vp9;(bYJs)DW?(lUw7G#)U?xxttOYg$@^b^fM&nxIHv_u?MVeHg zHZ1LL)p0G!HUqnXV0yXzzx|UcgoDVHfXHYNsc)^$Sf-iXsUhpUB1TXj#T)_+ex^N>a&w^<%>ALJ-8Yy4mf@$Pg zaDw#6y~Kyp6ReM<3CeLW{~)d5`3LI?y8N&MDk@4vL_|bJL`6nKMn*(TsLc;XPwNPSI?EH;<>Y#i1aYeJLG$vxHmko#k| z>x_wK)SvP48NJTD;7kRH{DgG*(fFbJ;Ik9&G&W7G<}tBN2l;&68r(Hg5F4jjkE<2_Ww?*HlO zqmZUx{X44r|Md7sS~I+U|Nr^d`4KM99m&J5>4Hl|Z2s@2|DP^z|F`K6@;^!)vi~b~ zOxi9^Mb!SklKy|k9*5Ka|I>@r`>*w9|1a<_Tz}frFZBKY__qG~{{(-+`$ysT|LN!N zn9*Ze$9Ca?F(aa7*0ztM&t|>`x7Eb3k@D!;>7wq$NIAFico^e4s4y$j8J)}O-xUK3no_0J77 z{~eTmrROkPbeeC}*M$Cu+UwN!RrN8?&CDD~jvuLi@$_%?C_bs-$A@YIA+M+=9eU|x1r}~PgW$Gnms}t;N>?fG}Y^(3X>Um<{Qw`82W$k9Tf)q zr#^KkJYBub^A)O5$1YKC@$?KQdVd;fhw*A1VSiFPG)B34lc$mD4JZ9TW>lEpQ@_)( zr!nhk+tby9>RX3D*D)7r+y7KKI{qnUV}y$1)MmBK$zgHy%WcX}Xo6bra3hvkg(ozAcgFB{>(;y!jQiEqI`ogMWtDQeF$>WZe#!lCwOWV$ zL*1v&b;_Qm{!Xe>)vf$3Q{$jIC`{^#@pO;s@1#6Mt>k%*TA*WZ zVYbP(Z&oRcQQA0H&-@efmCQd$`LmgwV)mNZDkC{{%oa0yt)}Q$A9EkfVKY+|Du+?zE<{fGTHkOjpIJ5Ao(SY=OK<{rW7JTc>uAQ_wmn3p zIT9JqQ>wNI=c}{0AI$umP%0E8qw{An&SuUQa69&+Cu2Tlb+!G7I^6Z}ki#1e-%j~o zgrx7+tiVCiK86*L{KXC&aBA0P1?-S*5L>Vh{9G)+%ixQB`T?8uwYFKp&Ao((wu}DX z1w6`(p>2Ny{D-6c&FUjv*1ypCf2$vL8@xjN2h1!A4PT+z4?7&a1I_$GeTb#`tHXis zRg3x#>^|x>wEhR3x{2qP)eAbcrEcKqeYMP~#q;Vto*S4!90rUZTlTy9=iTD?_&(-MdME=bUYAHf6~(QH21$_7WERREU`7rx~nU6PK{~_ zPj9Jb)RS1KFG5y*9X7zW#R5oex2x&cCnL)bs_TfkUHwzX%tfQOY5oY_lj=6KS^5g* z+SMQVdmiu^7AR;##hTdmKy{j??FsG|p{uVudFQC72pPfJblctv3{aP|CtZ*m30M-_ zUav0IC5!$KcUs^+HBJ44xO35Q!|hXfdYm~Vq3Tvu#?!s%yy22)yV3N&sx|5!^%vgl ze1dcYxp*1+eu_>hI-l*Nx?*5wYyUA}YJ)Pt(mVob2(SM^we?a#od^Yyz_Zs_T z;=8Ik9Xb{p!22vLKy#=(u>?svRxH2@eb*cPmt1NUOHmx1yNHyNRWW}>`%PUk)g)$N zuhCo*$v%nLE^3xed!Z`iDMMYQpU!4}+_p~y!~%%z6C1!g6zl+ROSJBb#!qB+_Ykf8z5Js|8jQ*vuj6M0Hgms505!~=i#3ZXWI?*jBkg@ zovjX&;#=nJjXr*&S{>PV&FQUwA!ZY>SH0@Qe5{OhXx61~M00tggslk5++XO!ZCiS8 zq3HnD!}Q`tp6|kwu$jRBK*vgdE?$N7{4H9uB+UzsmtpkwN2iaU5$fYj%S*2=*mt7M z`}AF|`hlEA(a(RvJ5qyHp}r?<5b!1bh~R(68x7l*KHpIEg?f(Xht!oi_FYH&Cxq%F zeLwFa)jK+V9-7UYF7;<8^=F}8Us_45L7T>l4-#zGHq8&(i*-&8(*GOXm)?J1$gaMD z4S1ax@c<<6)41P`WohpP{F4yTWWkxs{q0(BxACUNaNq&0-&YeOeYfo&PCW5jycw)FGHMxV=5u%{QV^j4=%W$IpH#?jMD zehZcK^}*h^t-qJJyB*yZ{a)#$o}+Fdb+)=$*Gcq!0orY}{$;2R@>Kf&VDB$l|9d== zU-JMwPORuZZ=0E~HrQFJmgg9BUnpYL7Ec$U`9X?B|Je)}y_fi4&oBPLEGLJfbzd+| z-!Hb#=)YJ4@dJ$h3&up|z~w3)z!)d5q3FJCi{=}xPgAK*OG@7_*wMT#8LaPm>Aruz zs6x^j+x9KvfKSwa;6bxm0gE6d zeS1a&cJ3q;$SblZv#zaPC` zuAd&^=>sf+lq@#jr;rZbpnfFoef$QAn?X-*+b^O2M#5zrBH<6?(~lxXtblm?&5jL_ zQHjKhr{Chp^d0yR&*@On_&uRM^?H1I>FxgvJgaqE?1k88(J%3Bf|f$O1Mvzj(X^YM zcQ+xQ;u8e*s>dJAL=-I{)91v-ky4kK6GAMj$Pw-4^4K zucwEXm|faFh|ln&BNH+{ux%L~*!H%tk$_-duKkC%>3xhgCxGME)+3g?HvPXE{eOax z;lS#U?u!R7P5bxbxRYL9I3(Ws0yUd)z>nHH{X1`%q%83cWF&B}BjsWdY`e`Cybcwn zHQOx0N^F9uqgaF#ozKmxo^(^ue1jeA|Ha$)X$p+D@6p&<=(K3`MGiGGMi6Rb>|)z8 zPB8wy=(qUw*K(E7!MpU4LH|U&e;E%*UoXACX*AyV52*BungMBA! ze#GBw8-*=^gR@B+93_=14^LT)fF!MWL2|taf2Z21@j2QT5-TWm6mEzGG$SCXo8Zeh zh&3d@OkFn_4GFgJpa?%ma0-<8LE-@g?WvsRlF%L3i0LytiSN76KRHO%P%9q z?~p+w8EKjW?MHwnSL6R3uhXAFda3=9_TOi(Vr|zW_KS|qH+cp*;MMd@QNjbEET}W$ z2g|ecgmRrk+g?ci(i;YKBNKfP88{m#bfkYK_afof(7r)QnT38BYNg#Lf)Q+S$=T?L z@JsqZk$6L4a1@+MjBr43qgjQ*N-|nsp2P<>@^4bKX+T@+vrj#}-Mjb=ZDWo}=xqTh zMG`Y;70D~8lN0rmw1~8Yv`MO?0YQ4A2^D%wjf^&m92#HTgr2F~&X_z>=NCR6-^5D1 z?dapDp)sLi)BODTHgeuc^L0a-Ohk_DoYAqZ}BSk!O6~R{I+dx93#oER! zX2wEtI-XD?u|aKB%o@tvL9izrLQ0cER9Fs%ze3gV$a@?y(&EP6eU9HP^DIHV8$$ZC zoYB%?O~=s|GhAMNfD6IW!`m^!u_@wIiEeg;6P}OZNt+#(be)0VItW?6An)g8O~U}- zLSQtI2h0RK!1cg`z)s*BAb~380oMb&fNq$&R55q_WI2M&7>DQY=D9yG3>XI#19iZo zz-B;x{}r05!CwvB18fB>faP&22e{6mDdAUWIt6^GudMgE1dzJU0VL1$z-B;x{}r14 zyL>tpO)H@zoKNBWm327rK>IcvN|@A3cs&iM03;vb*FOPiLpOYy4BP{B)OM0LOCz;x zByp8IM+1ex)qwD7Ga$d;qDk8Rd|(7H7MKc19<{(7z((LpKsEy$2h{!sO$p$h4M?7; zfV5vRungD?$nUpk3YYbK@Jj(nFZ65$T7V?zCj7mgpsWv+b%M1Bk*o=nwSmEPfs%}0t^Vu$ z!2q%v@`zv75l;#;9rgoXSQP$yE&PG|+;-2xuJ*s$umH(F1VT?Z5H}1MW!6!;(;z=p zsZ8*9jD|Dvyor^Kqt))8GSu#$(|I1HHZRO1j`&!h1sqwcxp{Q!^5Ge>zVe$T%gL`+ z>X|y~g44NQn_60Wc4~BF#0b{d4!^N=OUgG*cMU%2>50Q`Y)!kE`}0qF`gNg0nmzfZ z1=Gf}R`)q9YX;Yg7i?V4y4{?Stlb@{YKLz}LsPj2_h5Rrch4FD4y}<&Sk5J%F203( zUY4oa33t`JnyS=08N{W@dfY30<)cpcb{p}vGr$r0pj*u#{RWkqkf}C*uzjQNFBh}M z_XYCW@X+7-Z}`*u4~m{p)b@xrneKT(>E; zSolP{)DBy}{(Z#0c68+fr13%{eKJ`zx%kRZeDR<`IlljStQNN3SH0#sFbxwY9&@R7b=NZ|dKA$dL zFW0qMpMKzkUzW-ndc^o5b9=b+ zd&Hz|>k%#XhelVICb!}vo1cW`0mBJ9%?Xn{ih*>(21*$Dtc=X;;Vveh9VVYTf+rF$ zHdB6*&uu_9VW&#~za-#cpnxz@e#xgkGQCIas;DtN;#Nj4+|eU8t&u#p_lTA<-vh1& z7jxD|`(Z9b2OH*xkCwioUk+r)AdXd2V04^%q)9!}q#lu}VHF`-=(-pD!{DDO`1~Xf z*}W-taH}z{nirH4o<};&NQW8VN*yim`-7j%z0kZWk}_9HnODQOAa$m^_(-MB1NUUX z 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 kkiFcJ zjhWMV*i57ch}_tfydQ^7&%Xjn^2E%0+VNB~DUyy#+>gaw;v(sg=e|U?2K!U72XT4t zIXgZB<-v-D=Kdwgi4RnLY@Q-s_D>rr=6R(W8^hK-DuRJ;!zMm4C zx3TGy`qqxlKhPP&wOKc*ESHAwiOb0sy_qAjSqOcBY^Z;fxm22GcvzT2fQ%AJdf%rI z*`8TJ$91K|wH){TaGxEnhmk&ze$$u|Gaiag9Xg|r393^Q=;XxcNZZ?r&c(fh;rBV} zvovE!6?+QeXFKj!;65~gpJ&AQ*&m&pi+N}8u|dAQ$j`Z){7&c6B@au{U5)M_OIPRN z72zx#8Om>odkwOmA$yc1tK)9%XGnc%!2NUFPj-lVsID1@I?qYO|2FhL$aeN$;+lR5 z{Rr;QTj59gMcS9`{EqnLM|RY4&VEUr72{rn`&i2_dppu`l?UHO#8++cdnvlp(LKr1 z)%jq(he*nB74CC!|HN{SuJ?Y=8!_!#{A@)ht4}aI9%?_wne{@(kTfEC67DRObQ#N@FaU;zN6z(so(Cc+_FuYH#^Ur!ucOhQY;(i$JoepWW;$6swinRc; zPgdo~bNsA46F=MVb4_kA{Cu8-$y3m}Z;(2hekpSw+!u45u$|u+@44s}qC5O=!9?%g zl=o!%J?w|KIueIsbeqs! zW9i1`?_+Uu7>R>D_snvv$De`yozp7$yB_ypxGzi`M~+xH<}atD;v2oRlgwh?laV0I z0k{vq{Z8DsByOAjMCZiC|4Q_aJl(l}7x$&OpNzXx-zx5_a37e!Jq`C}+=t zyVhdbsLf8syQB&9(b&DlwK*5E`YxYmS?qY{L-yauI*rXf)C+O{9`{gxA6?!)&toxd zL()-=PT3jG>6H3chx-iNXLBv_v-{~Ok@pBvi}j#1qz5Mf!$Xw#-Gc5*=pJh6N?#Yc zw=zKNSkOF=yVJd8t8V*@5_f!ug{l|hNB@TbLFMP#jN4#Y1Ms3~bCi@glpxb}V9@sc z2kQ6)1gv|3)wu7Ed#S^^HoPBE;JjBTdA=I`GyFkyw-pEbeL42&kMYciZq`!f?dU8< z=Qc~n%2QeHbDlDkpXU5J>k9fVWWNjhZ=bXJJlmqX5#48uLFe&7LFI9ylxVK_LwvS+ z5wAhF^z2}Gt*OT+POa$y3U?{DMr4*Dvn!c@BL3^W04vW5jg8LtPj&jyA2mD}ekVxe zJy=o4()C&>tAz8jHd%Y$?UCB{#KNq%<@odJsGu4b_9xPotaua~XS4ShKP2gTzXJWuMM3pOxLxr`f&KmI zBU1~FTKX#oeaX{S^hb>jn(tj9FZFzrH3j1OTteEF?Dyhcvu`M!aq%OcD))_Vxn_S@ zi2iF=1o?KMsc*Jjf4J>R`=~%>Co*qaGLin=^IB>OPv2Mz49WLeWN#`7I_|^C(&>)4 zY>%JAc=2Z^{%pe^rbN09nei$J$4lyMN-1;Si9x>VYsxsZMW3fJKIKxs^3knF_oi^U zFb-H}BSP)ixPo$FW*AjZ(3L)XKKlQj2N!~T% zejDyi^EUBw!heu=lD4d?sI&M}v$r~Xy>p$FHDw9SwE%* z`CQ~fd!TlC+WWQtSG1)px8ld?__2WN*ghlF&YaGVOM26<=6McuE4zerhsL(CVq-j8 z@eXAv`bFrkof=d*Vg0x^#C^_mM-N252K^T+g6bh76n>n3xp9m0d>|8*P3Wi0a$Zx4 z|82M*g!^^jx*GA{8aw^QSm(Mb^(vQ+y3C3&-J)B3U6_Ik(&-!@orvuSj zpE{1-$JdjQ_)?4#yz zxdi)#*uN64qxO6C&${jR>a&qwkNg3v7@x%->QZEnTb?5i4=H+n)`n~jvL{%wdM}c* zygJ=OdJGR`fW+TBg?Ahwdz2-s$4hG}Ds91!`-!-JZ@EXtGP5nLiE9ha>)ZMGvoS$9 z(md*M{}^|jKK|F`kDcd@pvp_!Pf-7J96Jip??k_AQ&9EWTm3o6xnCFk0ZefJ_*YOp z8ZM)ly1}-RaYSfu%3c8n^^o$eME}CKBYS4{yt^rSSvTTsTPaGpG@?5lU8i!9xNXJ# zI^0(zj$5Izm_E*7o+NS0DCeEPtAlDa*9pcCpXZr)bs5Wx(4D*{GS`S6zcOS6YR?Q^ zmh;hh0G&vEkDOn$`m#c!#yP%4gt;F5)OA7icZc{&vx*xtJ^nZ=;uW=lCi(2WmNLTM z(=C5>{Vz4=7=_sRai5C&CyDdf$GIqnK2%OH#*d&9W(|J+ygu>x)qwk-xXX6|6O@hL zSU_GmjL%ZGZRlV6Zg6k!AMtx`j#roT`q(IZ4c)!gi$@%j%XVyhWs~$)<7c1uocBMZ zF4y6ni~I43``}u)k>=P3OM17Xf5fK$KD|<}ywho?=suo!E>mn2IG3++vg2|}?+?tv z-?g6wRW)HGDnk$NkBKcpAL0$@rfv(WCoSFExF5&-gL#AWxvU9db`T|xccOC>I!^tC zlxuPYdwsaSy|+5G)H$6_1uJ2W!_U^woy%3mtV-Pf!hHnSk_UPmx*EbAdm{D7 zW;Q#=UypydACCK(VZZ2$^}FTdnXB;QvD&XTWPQjw?TJZ!NxzO~3vp+9pyL%8OL_nO z$iyA9luaSJW6>QN)+HX{vhhucDH`+nZ*(Tx!i(-Nz4Dk%REO!bPc7|a1OD8DKTjks zL&n3~9XnAO%Ts31H+&IP9gcDLdOnqS*ajjq9ySZ~q}+?}=czB9^H0aKbnx4(&C)gQkPqBzY6y;T*vk^ydlUoDdyc3{1@8F6TdTOaeo!vP@B?YUzr)a z_&oskCvczO!8}>5H{nz=ZpWK%}5$t zY^v9O6I3f5{264P8!P974{`ml)Pn)&9`bEaJ?)??aai;p#-SR2Zor=<4*rDW!2QP9 z(K8MCCUieV_gK;8C*`&YyC1M~>ffZVY{UIK+(YH6`(5t6S@Zv>e%H(9$sY;)lKk`I z{wwbHa4q%A-WEL9M)#HH(^Z6)z!J|&bcbzE+@~+a{T$r?lks6ave)dzubsG0#(k6( z&&Zhu+3t@XAJT8&+il1?<)5TE7x#s@Go)H+W`D%$<2{!}r&;>TP?}|YC`WeXKe;xRf79rxJUMEGFLsBDg%#h> zJuyjV`W(LBfV=2Rz74n1nS=e23G@aaT7Y{d?suo~5B}Q6@lZQ9W;(vMOP9+6^so8N zT9?y-$a~`@zIE7FVXw<8l)o}wS$o#2abJvk7(ppPX_Ld zxNpW?_j}~YJkJEZX(RF8gj)-4wOl8Nx8E~AzP^aRX*W^i9nSvd;5HJs$M)tgXJRRr zsQH@YaVfeD=;}EKc|6G~+bZnWVeiy-M6VY2k8sy}HQYgyIwASni2V-iZwT*wM9N(6 zVU9{&w2v_^;oe6(`bR3}`x1zAU1hHLYr+f-WD8c*fkDTk7op;`Baq@J%rb}q6DELn&C#_zPpFYT)x-OcDa ztp~+D;}*so+^u@&Q;g7@Em2nkBO9BO`Y~* zzX1EovA@Xj(>|BrEK+IQtXei~7+*uVBJtXYAJ^f>{%-zp&U<-KFs_Y?Zpy9n;U_5D zJCfqYDIc3xak_=*=A%0k-Iy}hd)Zds&uJ3JeG%&|MNwN%y5C=lpPs(XWh8ZF74Av6 zhw{t1hcCyrhYfs>ult*ksq`1E zjxWK`?H~RAk9MeaR=LEKt?>_c^pZ)&-lgblezwDWKO+B&-3sjP_9>ObwfrO>R%3S) zcH_cjPW#l~m0$%Cd98((ZAJEle)jqimhBcRn>m+p^(3VR#{1jPE}KOh@{w(LphH#3 zJ`t}AOHDbqXOD`cS+27VIit@>@&yg^=RVXpW5M-GwRmXj$Zt|gr9IN2>aoj(Z9%0v z$fpL_g|yQ(sYBs<+>e0GZ~$zDSHZL!l)4UP!TVr;xCNF#_wo)^4UdCM;Q4SloCTZU ztFRfiLRY0yr##o8d~giRgUetA+yZOiZrA|3KTmw%sc<_S0NdeX&^Je^PhlSH-9Y%T zZ)1mA4Le@%P)Rou&T8TbAAF}nmBCNp68QGJ9clyo5VpYm-XlL?KbU-zQfI8c z!1p^;IeZJ&!tJmD{sq^=<31pL@N(#?QmPte!Uv%bzV#9Ma1X48hkQ&q!1LfHxCEx% ztkf!)1vkU~a3?H)`+d@(is8es2Cjik@PbX054;^F-J;ZTm;uk-+@bQ}yKollzlHE% z1zZiEhb?fQPYL%{rHri|Di_ZDjBuTB%;m#0PGMHLw#l zz~5TPN7(;s>eF1M27g2SfD2$XobzpmYJ|-~f~(-M zJ1IwaJIuIUslR=X|L`JM1{JJ_1An00;S$&ecS7GCO5ObcQD9=>A@SHc$f z6HK~WsdYxD@smkHiU66;fVLj~9wNtHzOJOTiFmn<0u^Zn|g`LTKI}En(!?)z% zeckz%C%htsZzSA<|IiN$_r-tsJ*;8M5&z6Q6$t*{gB zf$0x2=J<&xoCQna{jdst3maf7Tn|$R5nng}w!=$c+Cxg+0<+hdDHnJN ztb=#JRq!>q3H|`v;30#_&xa{5=!5sdLiiReg+IV5*ekD7ErGk>CYU*-Q|*EUFlj0I z2s7d0p@a|D!g9DPpL~Rw=a3Fq09#-gY=>u_OTIm#)QI7fJDdS4;G=K>`~cR$oPtiZ z6lHj;S#o&F4F!V?OK7rX*i!)IIy51?hT%eq$o}4lAxAo-nJ7^wiNl%lSSS{QX+K-wJQ7 zAbhw9ZiiE^BR`*{{lamuZ6^5w1AL3O8J>PU?Q$9Q_y*b~oB>PW$V&1VzBC7aV4oZD z=PBlyH+8BaI0w#$0k|68TE%y3>M7To@dwU^rEp9&>46JjGyDa*o@QK_i+}Ju=!fO7 z7}n0CUxJ-*BfRG}^8Xp~8TN! z^NgR+3pX~9PcY?W>MxuHSHRa`GfZ2F{0o#j%!Qs;$S*h&*1)@A1N;i^f~Ado|7iu| zKkN@1_(o3!{1euS{p-XNc3nk&{X?nA&<~T|p#Oq*z*s!?YKb`WcRa_r6Iz zhGRaWUx1gxjqpj>2|GWgKX^&09h+&#@W3t9BX|j11?ylld=j?8dYIHeeTJFvSC|X$ z_>}yG55fxQ;yV>9;0tgUobeg$>}ARk=0OFkV8%A`1s?x7?GqZ!gafC+td&XyVKIF4 zOXT1gUsEnH?;Fzj3gb4+g9~9X48R(A*0=QAa2{-jPr$TBr4HYYJnRq0z>B}5yy4iL z)Gs&}?t%)sUZs4#Cm!&tA86Ur?4Dm{YAdRT(|ftipUA7&rzb2rv-hm5=KkULgU8>;{*a)Aw2Y=wedwFNp zyY!d$5pOv2LGl6CKSVyjipOw&kM+Vb+~FbhxWm;?;||YxmU7s@xCZ_3_ZO&F@XZ$~ zSGWysg4Z>Y{`YCO|D?R&hj0-*;mv?r4Xa^09JrcveL%m?J5b7C1zZ3hfpyTop8SM& z!ORb77tjy?fMej*?@$lmBd`G~xD%fGF7fI--|Nf*r z;BHtA|Hkv~jj#!}K{wB`dpFTup&yP8ke_fCtcAUUyuSkG!(H$Rn7x_!z5^^JR2^6|2&v{fegRXyV!nDj@rDaw8T<~`!AUvD!H;2P3;h7}!9gcb zKJfZ}ln;F4WS(<{2cHsD1HPu5d2X;0cJI$U82IQA(hFOm>l@~8Ln%KvdKmt|2Dk)P z=TpwmIG5*rzh!<3^Wh(`6ka==_`|Lv$PYLUdbiWRz!G@UNa_K6zKD3kZ5QMI9qsi} zo;ikphgC3rJoNysfXO=;N6HBYJ~b<-=EL7BDPQ>UBHaH?zjQzDaMuI4!}&{sYB}^j zPCbFQz?7ZLqhJ=iwvPG&8(P?sjzlJ67o);(|c;O1t315QgKhn>oEG z@WxlDkMQh9>eWxIN1zWr@UNgMhrYM)2Y$RRsFHrByg0k(haIp29`+8;7QmKwgK8)2 z{vPq&%{UEn;q|ZxHo_|S39N-@ZJ<8DxiGDj_5sJhnh&T4@a_*u7kmb~exdzCFZ?(3 z!yX$cPuLq)!Si7)EQ3vO-ABaZSK2wuhHrh$Gt=-3SO)+03GEn8hwI@cnDiU#yv^h@ z%-ur!gFnFa@V-xpXB+KrEB?SyuozB;Rq$E39Ik~M;6ee(T5edcUW8C(gg z;770)ehnL8C)^6}{E_~#opOOb_%keoPqord!Dd(wXZ=Ed0>Ax@di^KsM>cu$U_LB{ zJK<8;^LPA*D_|S^9H#um_`ZjB4o`x4@VP(fhhTXsV>N8@vi5^TN3z$}K|6*8@TM&0 zGVmj~0xs%J9fMPkWi8jqxB~Oxglzf@cq^=fE8uE)!Ewyt1GGz+0Y8J|;I2N*HQ)uu zQ|9ob9KsC}KBVhW&%z4$$%*V?D8_ME2v6?E91#vZNyak#{@?F^Iq<(6_+JkEF9-gY z1OGqFfyY`6-Z^Nvp2xh5c^%V)S%Y~W^9klN>-tN$9rH8hFHF~83|CJ~2IfdiHfC(D z+x7BcZddnAx2rbba=m#!_rT>tS?_Z1e1zLo$+@Ph&vd)$VGS?Cx*z^~kXxU%dSSEM zb=e(mSHsb6S6BRTV=`WIyLxi|w}TfLzj2J)H5$7f7=wd&*FPSe;hBesN z!eooxE$(Yk%Oxkd>>ixsc8z?1=LIN}?FYGCxd*siv(eq#Z&AU1yWcq8?P`3;)XUn>?K-BX+cg2b zocqq)JrK8-A2i+WNO8OF;$_*V<96@BcXv1czX)${ak>4clwRNTp}sYl;f?F&cJ1!s zb{$1{rJl~)emKtU8no1O+s%tG`tUJ{EuG}?7fG%(OlNbFD|Z`b95EF}lB>a;aBdJKDVd=X~;+j~msV>~=kg8QjNqlyJ+8oG9@i24KlUt-E0>pKpE|_j8u7i`^}@wGBZ&KcV`zhz z9lyCIUEEZ_)nMX;Wu3_smn{gH0yRF!5qZ@i~O7| zh5K11|8(Ac#dSUvcYi4Lm1+Fccc9eebgG@ySvmJ2b-V^4X#=|t&TcM|Td!wDP~4eU<;kZ}}aL5x-@5VAgiA{m*~(lxOHSX)y1r z!OX)f#w^3E#H__^!R)~7!F0_d4>7$lr(lL+Mq?&nW?<%F7GsuSR$|s-wqSN(_F%dW zK_Al_a|&iCW;A9JW(H;+W-(?NW+i4VW(#HqW)G(8Q1mgqF{faLVn$;oVP;_FVHRVS zVOC<+Vzyv*VD@0T4nrT)8*>U~C}uQf5@rTw9%eCS8D=GBEoKX52WAhZD|P%pOmEC7 zn4y@_m`Ru!n0c7Rm}Quin6(&JOOos8M&4_HdHPk(qrS!&e4X)b*DrTd2Y=@bTL!T7bZ_>s5f>ik&F$OYm4vJGxk4;mS57S}@%HQ6kLt?7>*=M_E2dRU zxZKsZWcHNlvnQLZnC9wRI$?ULtM9alW#VF9l$TYw`c_Pw#ouXDOD0rIaP^&7I)2i$ z36m#AuEv*^pe?RidD_&zWmB)1Q0D48>8dGLjh`@W+JxDzzFby>u5F?^^a+!%y291> z%Bh6HpT0U!GqB62Pj~gbV(R3{6Q|%fWopI5zE@7U4ym$|6J|`DHvOupQzTLU*-zTC z7#SI)ZHuX*1CakEPbI&kJxX6-V8mY9yclWop`V%me7^;YE*O!MzCg_CP=IUd~oeib05+i+=gon6}pUCyagzO4w$71xkH|*snX^?PF#)Rag zPZu+Nv82rWh5DY;_*dj4euZBd+PG*RpD>4_01=}Wh7z(1}-zmR{ku#kRN z#BT|5HOOTbO9HR7si3715pG*UERx(VD+15Ha(Vp||BsfIR|O3P|EYFT=- z*&pHt5_5k_e>|58g_Qm`uIoQ#@qGxc9j)iT2!)=a4@#d%vVS9Z=%~`C>$&?={j;+P zpwj6n>7PtV-!vsXG9~@jDd~6e(nZ`)gRbnK+S`wG*&(6O$G8`LM@@NNHznOLB|T?K z`ot;e)+y=5Q_>w%(%+quK4(h0Z%X=tDe3+x>1(E>Z=I4JnUa2FN_r>hV;?Lqd=Y-8UtDDe2({3PR^Xhv@t9l;<~0Ne`1A z>kEZW*vpoGV#@QErlbof*W@vdoPLy$zMk}rF8z7ZSAH)Pn&Hx?lO7>`h)e&3bjY7b z|5<7GC;q%PCA}8|d*q@}sE23j&!#1PLbn4W-?m@SQm&{T}dSlg{?{4AR?4 z|J6PJ1?iC=he8RL&X6u+P=C|OYdVIg|H_H_i%EA~6$&M3NBCEf9{c%3d;O%Zye1Sn z+2Q+d(%XL-3jNU0e>>^*zYc|Na`<VJlG<)1>K%Uyfpq(>gl(+_O>;y+K|`#R|>NoV=vkYEaUo74pOeP@YFo|0U$W?7QN znaNX5`_`hhjLzC*Al1#2#v}`$q zy*K;JCCTJjT}viE`A3Db?bE+RXzA*e%aTh%$DOk3ltrhlIAc-w^6E2}ELpzj)Kktp zbCKzA6+O<~ROQjTXhC~t)2h&!%a(^0Em(faH$$hbIFq~fQ^-7H$r-10oh5L_id9*@ zc6F~@vS`(^mC5c?IzwG6R;$|TZ>kXVhnB4AvMl*p$0^H~FX^1SB-ym$%w?MJL5WXINl5H_@mmoS#RR zbA*`uxk)gbL3UzU=aR{f92%ZApK|({llntm_m+!fs` zPn*zUgOKbK!N|32#Xqko`Lz7g+Ldk3k?}9ro1inl`^TJ>Tyo~;=Po&I#qxG16Z&L_ zS&nxa!5XkUX*y-)DQ7H6GQ{8WR7&}epMDL6Iu(;~;u0xzJ_%M2>*h9vy3g!fvcze+ zMwV+fTa^YTRV1xi23KD3Iy%$71X?FqsnfepS=m0Ny6N=i4GaEx;fbm$aU-9se_9&v zscrf3uh*aG<-cBcvZVg?`jhqGU#~wgw4K-{I+HKVEQ9k@#+7egdCKxLJ99(Xiyqa%+~zBh<~E@{~EOuY@fYy<%*SNoVQOHv=f)CVpuQ9w~;W`*{OIEp+!sDW&IZ| zI+eK^Uu7lMV9E0KQ0KB!HGTivnJaXAX0rXXLl1R{GaNk4!S+sfW9Iv%Yn0;eYg~)D zTDgwkTEKM@SCs2hT(i0KSI_kou5WN1%k@>R1nq&^wC%M|V6ho5ib~w1x z!NQYme#F6;gT)S(I9TdnnS*f$%N=ZRu+hOL2b&#iaj?z7#SXSR*x}&$4qo73zk`=J zc$tG&IC!OlS37u(gIgWE*TE47A9nCD2cL9syMsF%3>++MbNq3z!NEocn;dL*u*JbP z2Nyfo?qG+5oep+6c)o)dIN0ytB@SNZ;1v#DcRRSp!4NS<=}*|fLI)!b#vGjK;4BAg9jtS(!NCp(J00wDFzMhL2iH2d-oai6 z&v)ELz;cQ_b0xYNNg z2VYxg`M1Zx&?3iA2MZmHIT#|CC4R>pEO)TN!Ab|K9h~XlEC*{HtaGrz!6pZr9c*{7 z!@*7myBth9xW>V?4z72w*TM50?04`I2XArkHU|eByu-n*4&LkFh=UJ1_?m;e9o*w! z=oHJJQU}W%j5}EFV4Z^v4mLX2h#9JLI)!b#vCkmu*AVq2g@9cJ6P@DOb2H< zSnFW3gDnoWIk?!tP6xXjOggy6!F~rXaquz+uW;~s2XA!n76)&0@LmT;9DLZp#~chC z-09$$gReOlB3@3MjWhgu+qV52WL9iMua;}pbsy+jbl z@-jgjuPX#`WUmy&NxNFGJQTV{5XbadK^(a21#zlw6vR2YMeyI)M-#-E8W6;ByF(CX zeXHQiQ0QJk9N`f`9N&ipanK(VJSG%+Qt(9lDnXq49fB>PP#}oozf%y$e@qZ(`ZYm0 zV(xGJ26=+xS4lVZH-42o#tz+PwvY37mAuLhJFr9Fne=+41Epgo-K+GN(jk*RU+LXS zkG-S*U!b(sXqoLM-LG_^(jz8)iPABp2Tb}hrAw5)-lVTkx=iUSP5Mfu%a!go>8q8l zRC>KhU!(L)rMpb}TBU21UTo6WE8U=UlS$vGbd%DxCVh+2ElO9K^leHnR=Uij2bAtm zI%d*$DBY!W$fU*Ejx|b;?NR^lReHVB+f7=m?l@oR5tDvc>3*dLOj@k(xJ>EmP5Mct zuT=Ubm!oUv7nU<&(vMo^KN(=&!+J#dg}Sa7KFJc3PR2_`kQToA1bNl*U@tYxGf|aId&zh>ooWQ17*HVWl-v(U7vd)`9P(2; zY#$3TjiGGyy`?f%HV(6*gqFJixPuNgo&C z--(6k;_s0mOjIbU>kFj@3SNoM7_52Ym1tWKy{HCm_-o^3^lU|pn+op;>Cwpx7ky)> zYFE|3=%@tk^vUpVUkqu_(07kCEFXhMl~gN-e-)O09ees-h+g<*%fGnc-x~3+%kpn+ zJPhTxih<(ai*SsALDojgzl!^#3{1}To0H|KNKy8cdgIS4RLCd?RU#Y@iJO| z2U){B+6tDG7*CqKmXT=r5P+-oFTgE4-ekGdx|6)C92Vt&6AD^rBDO$m%W(af3tq!Q zo#vg6L1rMZC5)J*m+`$<4S4lSX z?eSW1N?WGTK_}|SQ_&k^HJlLtL!jnfz7dv zPG*#Ay}=2E@+}ORma%nhbh$7+Yg)Q`-*m-3RRekYNZs&x{EM7RO(foma>R-^aPtUN zH9{KuLZsASb_j%f;Qx`~c=zVL8smj%-`aSwUmZsP)hYPJ;HVfzwgUw)F?yZ!8`ib$ zu7Stt;@`l%b7Ikp9+K>=B*LDIX@o&jW<)oY`J<2K+rzuDYCS_=nd$8D#@8_AR4?;l z9)`V?U?hl`6|GdTR{v=#e9%_dnNFDsNh<84*<&EUCGmGTQllrZu{(VQ7 z26y_ZNxd85p^yxt#pmrqw-Pa0HV7uhJCucoYhzN4A+g<#e}nP67NfPFN!iX+P(UA~ zhd-vgI#q=^j9q>&cFAu*^@=s&OqE|E{Cma7HJYX)q6Gs;1%}VqhJrIRS|!8-$iIvG zyOGu)a0t7>z$%KLizxfYY~!+Qc6=T2rbM#oOU|A#5Gh;^{T2RKy;K7xn>IM3BmHOpX z#Qm?w{Bw#aQdl)^x{|sRixI1hs5`NSa4H;^!F|wb+YI!50b^rUlEL6xu#N7Hk;dv5t=dCL_|SSUnT(O5<-7atn%wp92wjKb=tXD9w%0MYRm436 zfTi|k!h+bzUSQ1oc-0G|nS6aQ^8MUy@#FF@S{0?%O!!fWII5k!DL{@9$$5vBbA=o% z{<2K*J0xtzL7{RftfnjchDbV`b~$0&D&9arXnN3xaA%CHtEZSm{}hAWstF9pjc>~} zdXDsSngE*?U~h^lHpr-M?Y@66=90ZS<1vPEVL{&u={~C(TLyQ>3c_)3IC|aS;NN4@ z-$9HO>Ed&-W8R7wV>=SPXocn0OpJk72`PnUB#Ke4f7u?5KA!b?MDTn3i@)y@|4!xz zCd z(1=zBLd$)?hcH<1uVr(={mk`NRc4?|MM*Q)n|XfgIlraDrHpcvmC4%7G=+IHjcd=! z-_U>g7xL)GKbWAuV_ft5ruU=2>3!&rK>usde;lH1d&PBtnKSlL?w_Co(*OIpo_1s4 zxa=6vaDRl}3ErdLakJn}dNvCKy?7w~=(>5*`*+jyuO3_3Gj!|c z-FTP(qVb;fUu4D*zV!QlY#;4--y|7jjXTPWq!z2YUE!=+hvRhh5h-)q!w~o+*S2+4 zsM!1JbF18v+@$36_vyW=EUp+S|N zY?YQl)^*5|$k=`c|Nk|0_I?g=QUDJn)+n5@)RRWxn8-2HG??09(iJ0KQ!%J9!5-7m zeT0t8AQ*D`F*o>t!MD!gOK(i#oCt@VzuG1$m}Lm_&*QI(fa7fi<}XtrH-8;U1&{gY z(=Wa6{53cDp{agAuD$9>?d@cF;t0&Px6D*{s?v0r_DqFbd$&?S?cMO=`?d$Y(@p&! zx%y~^nJ-fW&BQk8fWy9 zsggmTkE(G3m0fR5u{Tu%+3DV{_l$m@Zd!ceaKnLKzc;QJg@0}QG67?bQ$Zmr-Yyl_ zDNKrJQB^f=Y*B|*YG}fY@;@2x$lQ)&srjE#I}iU@Gg9luinGjeX9U7;u=cAhX=*gb zTX=rMYeuD5FBv3F!Pj3fHqNi6-cxPy5;VC{P;g$5`~jA0RzLLM)xS;yZ>(shzZiwR(wi!zdz5K-_e-HRYHU z7PA=G!DXYS2DesdFhE@y5$R%q9J4Ix80gr>u<2i0v*Ga4Lw|fB=&ysN+{w7_cOwscwJ|qPjfb}OWN*xQXuC%LHnDy%SR2!xU#z1dbw>W zMaHE3$Y^c*)87dq-j(`@`RSlPn=&NxhhnJ_74tq%R+9t?T5N8`cS3|cnfjWa4x zHdZGsghOIy6M$F%b*-`^Z9@-O^yfU@e_e z?N&K+OUlUFVX|UmDRA$LOf>uBE|nR*C=TsIYn`4jL{0& zFnO$FVPn`P8?#43FxZal!svx(Sz`vnbH>bf#_VsDyB}i)L(%F=$e1#-lmz$u&8P%p z6xD@tn&!3LPFZlP%PW?Hh&sJKGL@xD=ZwBl!fE zBw@6|vZeKL(wcIPCn{vD=m;4oRSO<{3j&Gx&Ipep=pglkF~q15tS7=T#|5h#@fw&U|OJ)=w5j=^#Z{O?#)2Xd|sZH z^%N-e&)F;D|BPkgzn`=IXL{p}ll-@eqWAc3zc3X(ZY$uwnF<&f8}E1a*7W%ldCaY@%9!OZfg_yaSXwYd#jYRA3q<+u=sowBJiGfe1i~Cd}ns`NBY0z`6 zkHI0Kw;>+COZp@8-1&7qHdAq(ER30ufAd!(>WLZCPGg$TZ6Raxm=$JHfnNR8 zmM7Ou;6~wEQ=NvcmQ>O}EmDiZGAa<1+CtcqG`GorgUT)7ZjM(X7W&5QP)lz|P|!a` z``X~Kc=0e^%ILX@v&Sx93q}Rt7utclsoAs;yGkpU?0TGX5!{*bhe0|{l(d3-yf1}U zHV;l)8f^yuye&(k^YNtQEG!tq>Qwh={W#XW*~o}We#no(!3YNoLTuU;dUiQ9eqwRo zc(Tx&6%THF)~tFeq$QH^)uhpqHnXD6i%)`4-i)33YQve^a47QQEqczvv(RgbnEgX- zPh5j(=@}}GPYa>ETE-R!KO>3@8nZ}a9IQh*iV|T+(~2*1x{%sILM&%Ey{->s)2Y$oj<48 zR|pd3l#Vx*py5i5Hx(*aMpz8=CBX&qJ}5vROI&-kRESX~;?Zy0_Lpee)K^X6DE4QE z9GdZ_au{3T?KZ5P8+;E#*E96)A=aKiKV#KH0?%@~f`Ylosii*{gn*vG2PjU_aQfoc zH2Pz?JuB!6`^S_-uREsLKaq9(x!HxT+wV{%pPi$uewp&(-*K^;!BzWBA1pYg#5*oF zG<=L1Zr;}Sug^lu>>myZpNpps*Oq8xPF}ykE29to(XpD5ReO6U#Jmv`c+KtSeGh9v z|38(rr|J+`-TM2-Q}rPoAL ze;@06p}WC~Ueg<+FcLgRDO5Y+tqXhe3n%EbJY)HRsj1BJF!OizKAgRQ=Mjlvd9m&F z;B(V3kCFtuFARPpyoo}gW)J`3(VqlWOjA9BU;SiuJW3nA7zGN4Yt2^GaII0i;aa1N zlgA3NDa>+V8H$Z74GE@XI3U;gg;J+wPu+Hphh}lkmDIORRnxcEv z#SO7RlETzRu!yplLM01j4D9~ELC;7!{wItAWTk^X7N;wmbkLlaCR+a7BxGU)xaguZ z6LyD#4NqoC%P~0L-eCS}Bk9Pc8h};X-gtS)kHnpsum-vW*lN1VeNBh>n_&BvSXrziYxFSS6N7F*_Sl|0)i*4S_~OH zdsM1Mv1Nlr*<5Bt#{T7bUtuIMt=b?F>m#$TM2_e!T6K-T4m|Np+eUT(c^Cl+OfAB3c_@4Tx#b+=vh=6E#mpdMeQ$MeHpqS)gM#k13lA1muF)4qv^ zkg1aZItCRSt-bQWua{)!J88EU%guFmkv3(@Gb=Xd9uC)*szcfNi{9gphI9Vte5BYO ze+*@*gu%1W+uEAr!mDTa(^BsiB#%wKJ1rSUdt&(95gyK@P&IuZ%PeZ})~R03$upjr zGE<&w`s8u{Kdc`fy*+uQqcza>&!?;F;ax?@I?}`8&nGr`8U5RtC@9VqP8AV&3`#x#vWfZ5erk z7+FM1pTiT2|M!%SXUogKV`*sc=J4g(D|!F+a?eZO|2ZT~#veE3f|uV=f5$(P?Qb!2 zQr>zd*FM&RHKpzIhg=ibJLwOKZ-zw?dNeoqGG?o1=+_{mRFK{{c|CE#Lq?r*>k0P% zO!;-W@*+SScKd%*$}@Z)XT-7pXDd93qE#9Ks?F#u@e}QS%-mWwYNEuf5d|=NVXHn% z+P8a?F4hsop@ieXf8qKx@-#Sf43@An!S%2P`J}i31ez^L9#iuds^~vCd>WF$B#04gsIXREr>q|I!wTw z!Iy1hr`Q{#K!5gmIQRT}Y-9<+i+^DA1{$Y#dV~J+IC$H0T(@XBI6L>;H$I;EBMEDD{6e~Jc=FzkOCE4Vkr)_exgs8=XV*bcmV>`!yks5# zVfH+OC4*)~HDr}gGw8)8h!pdZOx}E-*hL86*cC8its=% zM7c@wx(kcZGj!AkC*&pWyh^VHKX%WAc&KK^_kWlg``a2jP!Y2LNcYpF^>Y1D@j0{j zH@}XRi1rxG=7|4;D{&VhQTuz`ST!EZ)8BgO(y!K;XmZ{wlVUKNZlXpDhBzwrIh7y8R1 zqd)1N8~mPO+B5WT5yOsv&Qe;fWEWDxomq5P*N zczD&d_8`gSy>=UBei@kwyeV3(!aU1*Yj|ano`S_jdJ_JeLjOD|So%8sH%JjONQGVtiURV=h1nEC z186*EvFoU$3WX`6*2?AgDb8FrQCMpW!fCj&37y=tYhU@XELkgNEZFP5exVJvFzta8wBY#yfD> z2pJ}aqP@@Y|0umU9PRxLw>UE$fZzwiXe-mHab^&GD7bMKIqM38oxJ->Kg~X&OdkwM z)Om(1Zs(wmtm^eotV+zn!T>cpej2BXirhNmIGmUXVrVNjU_-xIg_5!1lHA>8?(WVF zSLjYC6}ZS7Hd%^y+?hwQapR_0iZjQ;tflfJP0w!2FQIx8f?tD!+=$9H=TbP?)gF$R5`+xgb{-^>K;Sa6yKhvf< zcEMuyJLd*7OnX130=Tq)Y7V{+*Op7~aJXXBkUt)Auuzck#Inl_+K=+qHZ`@6nw`HM z-6{_JyG6MJV_fOi&*WvqzwJA?eLuw$2R`Wy8iy~M7_8bwkAmtujC$G)U-rpc>Y2VO z1`e&SjvhNkZ3wWQUj=XRD3Vqf^iaj$SCriarPc)2jGg_tR44DWB+JaB!u5KTHFS19 z!>HAat$jRi`il3xz^-6LJh*=dly?31s_oX){R-s!CW90Ihp))e?Ry#IwP`z3#en6I z76EF;Dg>4Rv*s=KLCiL8`C&26&!%?o6Fu)Bnf2b(PG**Z$HuqgCh@$1DhhcTR6v6Y zn2+jbta)ycfFPk->ohEIL)Advw&%ZL?|DOJ zFY>Df%=_K&+rwn^4860L<2MWx&m9x@i=Ov8%f!O(Iwl(JW=3J?v_$OmkMeWeGFYVE z7%z!YIcFBjqz`F$YAG$}D4JRYDuqXw)U|JdZ_aId*)1hI)9uXx0Cm~b#Xh1odG%tWcUpX=ANCxCf1#WM2ySSAs;xS8 zUoqHC{MkAmCfrUp9*mx=l@{F?ao!=YVsmC5naE*2e4zqo01iDSMsYKfL^m8^t7Lm_ z`mF9|KEVU&rKS6W_Rxe>?!EoZ_Cczj**{y)DAQlUV(5_d4bN0~qbM;sX-hZGz zPn|u|>pZ>dB&mKmJpOv)_7uzI!TVjoBCgzH0PK7k!ZoDlMZDs8@Dxe*OCkkZ{Cd-| zwX9^>ZhpS|z`kwi@PW~08)}o+pQ-2HjsH8O?mdZjfl9>~k;M#<62FN(w;2Tb*B#5I$K`tY&|lLT zE$86&!c5gb^rUTSU;80?pD?ah2-y^A;}~zN-a^z1w|8*QtD;5b1w!^{wwWORjrr?A z!{5Je76B(i0G+>@#=F?bO6@*4df~5h%$8G~f6$!`C#9pGj2_NJwCV#Sff(?L)RtJf;f3@|Vv6J4Lw?GadTcl2#GT)=B`^zN~BbN!}HjnILm{gnPtYO@a5ni2XSlG%>b9)>3E zaK}z$$2!)&fi2ipo|)0B=e%iU$~50TbEP6#NZBHi6*%+VKYPX&98!sFm{R=eOm-B_s*qhb2i=m@$ z8~SgAeT&mNFU5-><_MG&Oly5KOFA~*gew`l>S|o!)VksVcY3qa%3EMlQaBY^#S9#m(igLG`Qxi=tbZh z_g-|{HBw)>5sgNDvow!Bo4^Q6MOiXLk`7wN^S5p@d(-6M9+lC<^Aa@j1OLU;La-efr#O z;?U&;pUrsC1`#uk>iFjGh?@_1jeASGc zPrB`U;&I#g{5MB?8ovkUTN}@haQaA?^;HNxFsB%{ue~|-V!_~x)6$XO%FTq-FAP32 zZSe2Y(#3_-cNc8U=`Wa%*^_$S639GYs*iND&V)cXyHT87c`#g69PwGQ;}cxv#b7vL z98DC=t|GJh&FsJW4K00l5fHZ#n(oN>35uJRnswp$33?B^w1297g#V0No!u~I5Ehm8 zX^t&R?(KJ!dxx{BvA^HZR>d2*$wR%bm|e6ri>r3AEmQ1OaVT+bzqZ<&rdNloU*1(Y z`gi$VYbr)ZfYSfp8~uO7NH-fM#zg20Bjd#`D~q!qhX`ieq`f5tE2ItP#7*9M8PW^`aI3%sV%;aU^6(V9>8(EC&L=DYdIPtRMS z!s`wPCr6g_m5$a_iNR}hC)-8?c&9Y9>QcX3m2_A&^3@6oaQyK`px?J zw%OERfz8e8yY>HWQIAjFMUUltp3ufRwC{T`&_AofKbk!!&R;I8^uJyH`-hG{m7|02 zdb{6vp5v#32G-_l+&eJqG4p?+v_Vm7{%TzdUtEe!Y8Ly@y@BCnwk2?VVL& zK0r40{4DGLo7LMhUU$}l$s3~Z4;d?oT5LlQ;1l@s+3AmY56S_P(Qi#aZBarix9r+# zYr$6Bz{bsc;jkql=o+(}-k<$Xga3mTztvY+qWLk81Hqfm{)Rul3%xf7cRq0gEhXS+ zq7Wr#ejAu{h{v7ZdF(gL7m2RaKoq^!%$C|d<|R7wLQj91h>BU2&)JLlMi_`S!Zgcl zF{j+yieTRSD~BXFjYiHZa%P5NqQxU7E-zo#?cdxn1Ws*$HTuK}6WHHpIH zJPuf?vGfMBIAs0yhixLlW+svzIh)AIz8Q@XlN2y2lY(V_qC89W3vw6R%^40$2JQdi zw`%|6wtdb6ULy5@Svn8cr42AOQ~f_w%#m>*TX<>P{{FgsznwArJ^=WSHTeJV%7pzB zJ5vxUc=`2)B4g*UCzLiVqVrbS#+GQd2AHPxkIX=I>C3TE# ztqD}mk`e(6-is>F-h$6F_}+Qh$|t?i@u$)|P%JQ~&EdE`JCK$%Tw5o%}ThZCJPv&#bMHP4K)I33D`%4e0`c6;M+qSh9v2Te(#JOK#jM;K##<9=Gz8d_JurJzMY1JZgt26{bOzgLM407UMV^)5_TZEj5 zrh_sREWeJrgy!xH9=3{QPi5rQ&)kZf^U}s%A7LU~771_IHR)~kXU9B_>%p|(Xf)eDzA*J>LGpyuo6~$eZ`Tt3cJfQ(Cp4%q zC0)b8c9c_D&O#h5%mj7ce1i@6!yOyOPpBQ;D*s>-w(%3{Mt@`GQ^TKwej|?iFBy*O zd?r(yJ)39t9R$V95<_@ej5L|oJC?_Yf{eXfs0FYr~hUSA^U z9fRM@4)w9&`gU%)Z>^`L+ypT|tMyHk*oqU$98y%@lC@VKJ+o2lae9s87vjaX-#>mjCrmz9~~0 zy>5j)^%04u!`B$8+YIk^&4i*z;Uqfq#qvAwWnOb?jk1;a`}$q8B$*XF zQAv+o$Ul*hUXetVTWxNsUmqjSH2NiMh5vP_LbP`?q@oVVc{sSy>+W~;Ik{VEb|3d0 zZ)(V^c`sYJd##Q!z)H=j4l$-g9h?)Z*?RWT{S&%r?HBWsIr;`k>BuWtjI|s>v(K~T zGdF0;M33M&v!ZNtdX_nm68z`gLa!C585Uk79&Feob7@$Wd7OESIBb49zsa^!mpNK` zI>r7m$Ql3q${mgGq``7DQkwyCL=Ar?EZtFbH#-%wrSxyKl_lJLFT>k%(tPhvbAvA! ztUtF{ALh88+3k&9*S8-27ToElv?uQy^F>C;pSOl_Io?#}r?pXt9~iyqP45r7Pe=Yp zUyG~8v$eb%%~6G-N2_*$_qOyU)Hm@IWBB}eYb~bre=wVh-hF?xNJG&2JC&_nev>fBD_w z3f=H4;ryJ#$?E1<|JI$b9K{PBrIw#s47>UU)_unJ+qtXSX4f~>7qcY#K+WsxrHcV)b3w`;&cv%g*UVIL-^kp>e)&nB%_s2Ok=G-YsH->(yulkxTt{qJQ4i zsEOF|?lsV-jdgKK^zv%m#M3dJ=HUlD_=Vl=HffC~{49<_9G9KR0%z3&(ZkQXfP%?8 z{rbje`D4+WM+So!YoM)M3OV?09mE?Q3m+$PFpFBz^S+1`CQ+-zx!UQpRIv6!5BcAQ z5<>4BD55o#kd^W?P>d07XKI?y3sTt{xc;hPs8F35)X97iNm_a3=soXz$c*-Wj3*Eu zSIfNzkkC@EQmMnYM$h|^${e1mHbiRro#4*qpVOwrRtYtdH`Kt$ppX-rS-xbcDl*N9 zo*z;#^E1rvRC;<1Jw8uz^sFNxdde+5tBZJ2q5BOQZAQLXyAU?-Sxf$zx3Mx=i8dlp zI6q+NDGFr{mEkvbQgSm~f?J`?hbQNYIVNAo^2&=ylmAznpPs!t_1x~%?lsX3KO-m8 z2?r;5^yB}|aiSa^yc5_a)u74@{o6*m zsX8ReIidA3-i(kwalxP0h*?eZwN%1N=7X(=UN4y|y6`;XskKj|49T*8FoQ_*LX9uQ zFS2n4-IG`GviAnd`n|4~@_zUhnSS4zZ@e;jgxKc6-Jb+Rg4Py3g(s`t=>1k_P7Z$5 z`-4uLq}CLUC%@z@0ec4KEO`V0G{ORfmtvegZ-yCePSP6%*1^R7=h*!Ht6|&mUHb->ZFM;GzMM946!UsX5%voUwDhU>Vr|odqMB(s0!2P$-zE2gH570{%C;cRl?g zuPfrMiRl=37!||#nHc~bdG0DBVCObtSLu0)_pbNS=&yvf`{$5Q0_6~rSx!yaMfoiy zqv3Mvv zZ?wem>rbi8;na8bgxuS}$-|w#J8y{Dk%PKnu^UG(I7%%fc|||bnM!mOq^oCUIrIgd z@TUJ3y$OgPJ>?Cdh|P=%OmOLsKOG-`1MOzuhPpo@N_W-HFN^l-6{+Fbg@&bi8|#KZ z%smhaA{1%@%5|y}MW%bTYdpQtV%%wOHeY0}IQU&TrZJwDpe8!88_CxCAjpNnRW;*r z1B7_9!z|X1@b{rdB6Bv1o#ba~#1bWARpXgW7*_8^Zhoqp*ST54O*S55?86b555E8TtkVar|Exd2 zifY22X&mm$odoO4odoN%P8+remji~%;c?DR4BDbMX*jDV)&W{e9?23ffQO}3+k)@D zP6uWa*ElCK`uU~(eEp`TyK7xJ!!%udy*~{W?o6!-k9YrVSZnkU&yh{=+?C_wlso6K z_xJ}A5!yUq119VL+~7EdUeD0&&zQ~z6puSb^Ny4eo_@ywKI%y6s?glvqo(|Y|G4~J zlgmGk;`092KQ8}^{PKqXH=8Pl+A2G&K4ac0)zc?_0)Kqt``xv!!cWQf^DArKO&(!v z)#!)ZxZ6U~@7lwI3TvcZm>3s72M0Z}XP3M!wuX%d*+Rp!#alD=eOK+-olsu$?_}0W zn6T5jBdW|i9R58b`82O)8LlM^$4*xrHlf3}h~i_Fn%}9-sdZiF+^^~EOJwaztSaa( zaj13V(;cOikZ1P;Ig_Ukgp{ZumCMA6yGGGIyjzLs%*-rfLzea*NyE_%!&r>; z`FvtnpE!;-3=*gA`#yPDEZCoM{mDC@b&Kv!Ht}cKp~q4U_!pVSg@XMx)|=j=%t1qp zf}Wuxo^~=dZY2HY(=)_OG(Su%G3iQ~Q)ZY`wXJ{+IWHXN0&+a<1^7h?$G^j>SkYdj5?x>quC+ z_Lk^{ztj_E2a9p-ubo}aP01&!WuE7lW<oz&WxT-MB(G?68WfwDpw>>7bps3`G(Y z9p@_&++ilo+;c*yM=Wgoa#hOu01uMNl)_uNm*6mNA@253WcAlKYkZ|Oss%G^eoU5R-G(Y_C8rFr3c z(i}Ld^skLK*Ao4o?fBx)Z>CBGjE{Mnqu0%EVp`7)1o8efg_ulrI?BuHg9Tfrt5MoX zet|4rKpK4OlW)9<(=~WY2-I(^YSJj9?qD#DGcfgAO%!LJ@g}}Z-+hs12{6+!#)4pv`XBB4rG`k3o8m#O;elCB&)7sT@(*w=r7N=E$atOJ6zaVVYr4g+ zz6M$_tga2!s)A$pGT6=b3OZ`pf2?7Dv`-&Yki4ROI<&L?b~CX@dykN;d*e;D2ALU| zUYH*rF+LPOKT_sILQ8S#!E<>DhjLtmHp_U~tL(!J)FXc&k0E;At@vgu3v0GUQ~$%= zbbWod+=dyC@m zwV(A(#;p@!nUUA+2C*@Ug<0G*GkyY_W*hXZz&0pZXT}jsR$s97-k9s^^q0K1g3XLe zFUYK+Q7ca>6P2Oe616)-UFp%=>^1n8n8D+X*>m#+hhlC5y^odoky^0fJr|FYfBthu z58wZJ+}K7;$ruCMFJu^=kcORAFBrzu#TSb!o8SsF@@IC{#b=ZyH7PC*e*S{VJ1r|D zlucjqGUmC_3+&#hn|F;It6sqDhU14$Eu{66l`~Iu%x^LZ>=15BJI}5`xWU*DAp7rn z!GQxZNI-MWP6CknTE}r3qr207MB3CGZ%4b?9llk_Kh43Jo@cKJ#lPw$lF(oNnbXFf z;CE;^kj?IK+OPOD&bKxk*)(LlDp+J*vLanZy2RtH4D&itiI-TzP_tj<;&*W}9|U_= ze&D?Z)&9QP*Y2Z6Fg9RL6Df8XJLw#|JY53boE9=Gy+oror;WR6Z_Z-COm9v*V3s$h z1F+bevsQADjE5CFNBy~1R=9;g74_z9@`pvm#o)Cey(H!gdsj6RGWQLs>bzTTGU6 z^lE2`hn_#An%rl;GTHAyo*>E`qOre8&T;pJRogNrYQ#YJXwQ51>yKr`aQ^8LGrAN% zFAG+|NaD#x*ZT-kC$&&l>yVgO%M7pWP&2=izqiR(rg>-DDVW=zp0dqS#A6e+G-H%vs;BU!G=!OToNx?5 zM~(w2^*9%_v3jxo$i(=ybhGU_wV*RV+4nyT{Xc%#uqUtz1M!6t!tLK@Ksn^re#{Nt z(x@L=o-MCQ717b}a@DB77TOxNmAS#)ruw*DSyC}^4j!$zw*Z4 zIo(uw;vv(8tC{-O!!&IvVw6~p2ItWY-VF9O_dJUg3PpSG!8)P7Yq4f)_>>rys|2-P ziw^PyBfUe}9bp7gw=|WEm-2%f?g;C=4)!Rz3BSfJzwJ9Fn0A$p?{FeAyS|1GCDHQD z_@Xu}i0Itu>6LuWX@(JF^zhBy=YZq*3M^&wJ>4gBCa4KCtCkMWu9SZJv#aIXn7DLz zrPp0;zH+^G^-qQU$h!ENq~aK6nB03YUDJ{q-e1o>JZj6g_fkO}X6E&VRo8$X>^gJ4 zNzIp`X#5aU5N#ff9{${_c9O>{l&uG`Go)quP;2XK^iN-{YD52G$8)B-_4q=imPXeN z`~t_}oa9O>&5rO!Bfa7F49djLsE8g;rJ~ufRi75licFL-+8;f9Q=_{2BcUOxPGh4N zGoMmJAKm3+%&W!MHjXjrOT0RguJ861&8`4_MlWewy&9fvJj`hM-Ee#Kd)av_8BbEU z-NX#dp1iRs(dlhE4z16A%7015*G6w5rjNMm#E_=qh}3+n&ljgOx+2N4c8x*<3bMjDkv!yPG#ZNd){yySF$!(N$4TN=G+l3R{`9t$f61fR-8)RX))#(Hi zn;rkYmJ+I?^HnuigPx&ZJz)BBub+BNb4N1XXjboaKC5`_YB@8({IJO?HyJTaOiW0% z5{{0o>mcBPYKTa5&@Ioyy$5t-{`(QwKXilNKeEjQzUGIYBXm^b-$55gjI}cn@-z|} z06P0uG>w~7GvkC2P+Lcx3No3@bH16>*7#;6c5jSd(#t)|%~yQ!>g1{CEl)C^Ym>hA z4E^$c!-DJS{9<%PI%C|M1~`phrD>(fEc4h`#rt>}HQ_Y)oh%VBlIb-`j~%>>qZ_U_g=1H>Sw{RFK4=s#twSKV=iDOS+ypv+d3^?}YaOG^cIq+^m{Z^7r&`P}tu6c;dFv3z0uCK>lsNeO1*T^-!QhOMkg*QYbH z^obXd__{UpL-IRDM>q(meUYMdQW>`WU-Hda31}4xif?K&rwoM#6!^7zA%nBl{N%yH z$4r07;Y<6$7pZAD8MBSYQj5jla()g+CdL^?J}r(ph?#!1u_;qDr;sjj_CI!cyX6_> z^$|Q#+a2U- zWB@h4vFKJR;I&61aX&lMtk={so81dmmrg0Q>cmZ zYey!m+)j_)v-VekXm34*-;ctqxx~KGY{A`_A>4RbB1V{J=$ZbGK26GAdvGu)hZF3z zX}NzQk&=hSnM9YH#7xxrQuSkgGtu8qP4>r_T6B0h=v9G4GiKohckuAp^N?Grksqb4 zNi?_}HP%K)=6Apx((qG;KTM*TrziB_f2aGD^YdBpWm)N5Y-|h9^83_Vp~tde(AxqD z+51`C8_&Z|9a+crQtIb1Hm4k=6GshvmV=6WnCXGIM@i=6v|;?sHy9Q@L*Kf~Xu~CL zy&hAbOsgbJX|3UHZ+tyTQM8NZVBI00B z>IY}-wstr9Eyr$KB-*=PUhIV3&n@}ck+v9_#`B)%R{Q_pxyF{+&tFDAk^34oeg#s- z=x>SkR?wO^{JT$(>y5p-2?jTKI1<`No894PW#4l`MnzP$vQMumuy5MO~c8{5HO=S)%_>LPrj{h4K0WPhXd-gt|)N&iFO(;g{vSEgPz+v=+w9~T(1 z*r-=*rX;ge&#i5+%9=brPZ1?NqiFhp=HQ2KNlgM;GwWS3+dTX$j_8CkJ=_a5+W!QO z-rz>%ZP`}M=TAnj!2a6!H^Yti_ZG(I)$!#2faeB8EZJNVznXq?b4C1GF<>89uJZ)f z#&03%^~Tp4wwM6iZSmVoS-m>0pGWBaZn}k`a*FY8*K26IL%F2KIb@O$1#sCr@tH= zeCKxm@p6MW5$?o;8!(tcAuwwftl9t0`$bG1HXzgXOkJd6r?g(7`WX7005zed=&SGjH^? zPY`|IWG)<#Rfb`GO~Ih zS>@c9t!`!~qRo56^`2G>%cM5MN!8SYG?m&to~-DhtRAEwEkxxwl}lFFto$(dW!#sa zd06g!43D*wGyzi7WG+OM9lO06yR%zR$wx-do8YVFr9AE0m!uhF^HltQ=gOCQB(vmo zSvl%xtM*Um#i*H`qP_bGlN}eq@XPRfb7tVZlF(1q2bZB0Q-rpdE*beM9Ioel|8}#P zUdLFSl=-|f!cK=6r{m~r{R7j!e)(GKJ${XPtr4%DY1KFWeVI4LG|wzQ=`Jx7@>c)^lvd^k2sDj5;KT)M${iO+L&=P%ly;*K5a_B+b8#% z23TtHpCAG~FU|2lw!MwESm5%Xhy+iI$!ic_uEI>imrC^!-;J8H z{vELVVLiahHR2L;7-BJLt?Celxv!uxlMDw1~f9e~>S`k?6e;V_FlW1Z%E>L*?3VGcZwHPzF)kk@_ph(_ksXAvJ0U9N4)5#YAR(K z$cq;l{W-!=x9Jb2OM1Vfi2p_ zYxfxuYi}gOC%TY*Nx=it@0)IRl)LYuQ1I=Kke}#y9CyOX0c|iJ5{>$awsbL0-3&gu zuyu7KTRbepKIXG6CGQ%OM)^d$9Tm{Vr`6`K?R&xd!FudmwC~&4P70RtB={9Z5%x@+ z8yvQ8vTE+3u>3!zKOG8xn`S0yJ}@l<$kg~!<=Q- zN!H&$eQ5bfXV~@WZLB3RG}G5=#UM~sMbIjZQByqay>Ya|*dzsuzHw~z5B#3N|IV%d zf8f7wbP9f>51%tFTy9%%`>)16w)3C$nJ>@WL~x2QN9+dleNihn=1q-Uc)wV@FM{`S z8+eUe?%j;CXm5gIpfG_RJSu(V`Ss{|e7BWXtxwW7hu(>vH;t4~1cQ6BHtKX`HE|Xz z+BeH$z(;j89$on*l{RMDOu!$|Jm|(a8ku*oqL*&wh)McqJc-_{Z>-cW_D*V}(Awd8qYGYr7t{TEuzB^; z(=yyI$dEA<3J(jfQzQuBPczU||XJY2tcDr7|sWfm}&&3n-}wn*p&X=6^eoQwKvdh(BS>ku|-q&% zn0VfBc!g}E9rc>@<6iwtK)F{x3sB+J*8(cN`Z_?hSKk1b>D4y^W_jjix5Zw4<-{WJ zkD&Kcnmy7TL=nZ(N@w% z#xR5}Z&mq{$>ge}^<}dGFK2J_x@1@4sPANd_bqgS{ok7mweknbf_)9OoD#KL z7?Lwe08wTXgoB$g1>n&h_50y3Ir;J6@$J^1cJbCrO(Xl+Mx6hkII1N0yCi(@B~SVs zQK$RvI_IE_zM{l=Vm|Vt+?qF|7ygVKf1}Zo@b49Vt>iP$^e*|+R zcoax%bNrf)>YKLmh`i`zbZ$b+UYID~`y-W~SbpThk@bDd`2K(Q;S+i2DknA6JEeEM zhwxYdmXE<*!M(&~*V}0Cr}PvJ)01U9$;1pc@fKzjN-QU?R7Y}p5AjyR@-QNeb$ z?;H53R2AZ=QF3h_Ro1quhKrHrJn@JUJU46Z{b zbl7SwN(ymhUcwsLgf+4WYh)AF$R@0jO;{tFutqka_{Cx`k!NHVfPSixon?)zn-$hj zLYBXqW}Tr;&U}xdJw$l;h0kH@JF3DSX*5|mKcg$_XFSUj`59eaVzD=0eg+;6%T&da z?3fG=LBG7jTAYFDyaoIW6`Uo+aq&5omf{Dc)~)dp9VFI(pv+s>g31+cQS(Ojlef__88O`U=?%K@0Qm5QL$RAcf zE_P-K15xlky!Fxb5MIvt6@K*L;DOZkcX?BQFNCaxd6~P+9jk@g2~Ttwq8QkLP=mc_$=?_6uoAuzN@Rw{6)_W5C2m{g zgjLDz%UFE4@iS?j4>n}6qEKZtCB-Tg%(g&s8Bzxg)lhE-pJv|@ss$6slRTbzA4*0 zQFc=NgYJbjXV}-+V6uLf#b}Uy|Hj1s7_>b@6&B-m#uA^oDU;^(+$oJ`)Ju1hs^I`H8ra z&i&-;Ic6Lqr0dvO^izAFq9(x^HqhtJS-P;n{1)ar9d6ani|C=TN9UOq-`?a}aCYb*5Vfq(FI=iU{JbG;POLpux+!xza$9{dLvcaI7rJ5-hlW2vG+dkag}A>cT$En zVB}0BLXaqNH$J2oZR-=)MuNtgNkX?R5t243rQov_K?`C@8dO>ulF%LxgJmm-qT(*> z0}2YSbhT*VY1%?UDH598VHwDO`4bzz#Uo+tbxdt_IDc5Cad zH2V#Eo2M>tFpV?$AJgQ|w>w6`xdf}ipdqW`AF7{Q@g;VxeDs-X++MS_e9w0OH*wI#7`-aWlci#2lMrSIYD2 zxsF>HrBhCk5n&UtnrN~-%Wyp!>i(V(t!Fg_jB z+Z6UpC;twPbk~-Taj%wn*r}7xLW)^aa_tQk-$0xF^@R*P?>7Aj&Rz87;TrGew7<7+?=k)!;*p&3%Ioe&eW`yZ&|dZH ziASbWDl=~C8Msq6L4NH z7GV|y`f6GIGdr`4agMn6$ASIU99kH9CZpf`F(`xhS2u+5@*0U;Tv~nqit6CJGPY50 z7T7HryDV9FrN3G6P)|FQGsvavmu;OWK>|s(qP$a!YG323{qvxWjJ?e8M}xKS>+5aW zw=(TbpwJ2*vG{dHrHf*g&R6>_#R_puN*Ny7$r6n+m|sRwiH4~UFx{M-pd5+axpYZU zh2~^H>sQfP&DZX74pI9wpfcMPoJfD3##mVD!1E0b-8}Y(7Pbt>=OH7 zR4LLMxl4H=`N+91(#cUK{^|c_JlB=)_yZm8DX%MIBsZ1U@<9)K${YE@deASOg{N64 z9NrT(ySL^O>SPpexJ$}-)L}T?M*eb(2kD876b`ahwg?!=Unit)a9`dPw6ynfm;Mp< z1r@VuFX`A4OJJf(=w2oLF!h%k24SRtvC;p_hP<-8+OBQXt?hba_!thpu6Llz)80b{ zw9}bw{JJlwale0M*Ng|IzVS-OOmJ%n(x_^1|4OA(w+M^0C^+6H!@;;fyNOmX5o?5=YN%e?9v}t;eY-OQU1G zyZ(gy_HT5roSBd319)CwKDUJK=~~HB6E)QH)H(mey7c>GZO{<#`tJBB9$_<)sM(ym zcscs~1e6la7`oTZC+U)xTb>&bl}*BpdpTUcR=y2$3BHL&;jW#LfP5g#6BxFNPjO;1 zwXTnRgq_kaz-ciEBlY{jS_L+|3$L@`Nk3%)h*m!3;Ub6;vvWllf#1=I zc}wt%_oi+0di37iUvP8nQ z+SrvyZQTFuPfJ>t9AAHyrt#l+!BO?5)h}spB^sfS!A^D$u;x|ty9iGsJW`3GT4a5T z+){~?LC@(3U#uev4jJ|12?l@Wk}(}&s_U1e{|Fh%)t`;j6Q{TG`pmWXETw-iQdAhF z_x(O^v+@F~8SAe#-0oP`QTA%~H!77l#T1LFIQUrdtlh~A4h>EQ<;DxUs$cfzyg*8# zllE4>e$muqXTJa3$o)g9*yXx>a4-y%KN$LdSMMQuQL6n=(MY$C7th$_=p}oGJ*U%6 zyJfUn3cfD(?ticEtVX+xVOzv4 zZBimEdzjpn-4AdJ;^E~FviD1g6g0Hm^hNw|=xM#VZEL)kEI6}bh@2!-%7H5jW(*b6 z-tnJ_t%xU!XX0*iMPBE-{6R8~3>nRI^!}98?>MzxTju?Xot8b}#Fa9b;_88mS{a^V zXI1C@gP*%ew-e zD0t+BQyss&z`AhHkE{!i(feBFu!b=yjf#{XN`>WuFoBnRHiVvYNadRnJ!hKYsdKcI zSpQ_9oMD9KV|ReKN~<@we_Y+ZgdP`)(F^i81)QP*yAgs)%1XBd=NW2k>u$Ht);`7E z+cQ+O_V`3>g_mq%MPgUlG!CqI-lnnoz6<{$I44&9;)-d>1-g3{r~Oi<`-oWQG<9X@ zaIIVQbM0R8>-ki_qw{EgZ}qkne_{&CnF6;Cocp2G{@%5IUtju|j-4=3d^}z~c+n$T zfz4WhkbiLVe~IQF{ISpZ=h8}M{!xo_5nt9FjFsBPnf-H0>Y>kT3;g3XHve1M0XIz6P>t@KiZuqk9_WmuMDK3mhoknU!q z2b=qx9}S{R^T3&23oXo-vnE)=>n#OpBu}u0;!#6ROa6mIEAa0+C3QG1NnKl3|G?I8 zXRvC!Y_fr=w~vtZDZl&aWBi}#DQCy=#>L`BNR?NXobyxC1}GQ#Wpjc%RHo=Tzxgs< zJ%y=^1^GEuRGa{Mb(b{yV~I7>A1k> zPZZw{6R+ai)#~D{i*Hw9@$G7dhoks*70QQv-02$V55I2%O#$1aAwJ6#^aK7NeX6k` z&JD--omUpC%9mZ0^%OmeO}v!lCjFz=^92w|hW`$3*HDn+*8DFq2^7(;;ByI|L_e?= z`e^~?ZnL+hm%>vilrIk#_wsx8((9e1`g0oz{f*2oIt-ArxEzbq9H5L+*p+XpmmS5! zp+cP}i!al-@`4~ym#mSsATNmB!sdLIAXAe%o{UH>L9nAW30kBYsPLtQklYiuN<0yX zp``*{Z&z3vNeGF$Acms@j~Ppzk6d_vbw}exmuJU+g^mA#3+lt++_O+)?fAs*L`94Q zGzZ)MDO4L#2l$j!$1OmcoL{w#qSu<_-s^;znE-Z&vo44DCrBW6c)dTOe)o!E;$9sO z!cf5vyQxy)?V0X8>dH5aI` zOUKeBavTtA75;xswPdJ--V+E&e0#L4yC~*ce=fU8WuWJzhDfEZLIXrU!H1=!3^_@f zi!yG{so!SvnoB@(RQz3T!;}&1)9WFZHBmpAv2QS*?pF)Eo^2W!dVe_JKl|JKC|^>d zaOxn99z;*nX>&@5r4DXYk4y6(B20eAqs&LyRP8dhA>VC6Phm>Z7LmcUb*U|MzI)F{ zyxxQ8`iuwA$P0yq{1>-CGs~s@VtWM~e-`w!5>tX0pHJrHn|!#L+3RBovzE=nrqKK0CZgS@X-WQXbo4AYZbm;Ev=oXu?Mlub_U9G`b4$EmG#3r8 zX&UZ$nr1SyoW26^#&4O0(8YFQL(~M)e$3QaijEpREI>=G3;EhgnhQHv3oJy+WAj-^ z-lgvmK>B}I-wVg&-*x{RjN!6!jbR0GZAz%NMC*{hH(7XIC_tON-TUP->>-o7pPN)Y zaHfCW8yzn&x(anQfA`c^v?=@*h1wSuNaD=37arQZf@qVgZ_}RbXjCirvUXGmagRm8 z(v+5t#6E|)R{!6|KZXRpbr%#l8p*Ht9wZGbp^LeRUk()=&2fuRP~cF{i!D09alfTF zeH-PpeyC5+JBXBgeQ!+CT>M-tvkYpc0yqGWpSQ=q;5F`-I?bA` zYu_^mxrNoLvbgC(fxULdCZYy>NK*kf%eL;hc`x5t)u{vF5h;5&>%1z1U-j<8T4i^D z+}oiiGVxshxIi>Q4H7SHvN>W?a%Yb*-q zns(t_|8NTPzbnH4Xugd8c3N9Q-?p}P&@;tyZAxLN7!GbRCW16rzaW@n?T0TY_TNxE z#`6jfC(%${`5X(bSk2LE3~3+n2svQw#=aGD5aWa;6q6C6wQOKD*WYmGeC>8E~Hn!qz4!4ygn_~X!Gd2-h@!jZAqBw!=E3_R3I$jtRQ;{}HlAp=vj!PegTzB$I zeb|pfnFP8^OvSp9F%|RmLRz4aF%^+!nTKJ8R*Vx|k=b(!XLlYMsEea`8*P+y+{%T(s#qTTIPfoo|hmn3|ATNb4GTV!hH+zLb9PugqNoiVi&b z(8|Ca`fX~KnnNGae(QQ8PK6Enqqe;IyVP7*)H_)R*IRQR0H@y7@mn3LsZ1#Bm!x(k zmVH@D=s#GC6~(C^$>ciPL&V?Z?;ZNYTJ((S84IlwR;XoRN8~acKW}1D`+lXh?Y-MX z#g40kUxy2z*$%ww-*hywLUZ`xWHR(N>WY9pbV$F~iy}+9Qnf@Y5uZ}Pi211oOVf1} z5nb5@ewfbp)N^bz9^~3%Ug1&KmM>rK&N|?y!~a$Vjg5pQs|e1kW7F>r%PSsiO|NDg zwdBFoUy8NA*X{pjGRNATD}X@93Gix6-@y#l;BxyrW?H&Go|JhKhJ(xi$fa+#Ul&;a z?pbU7+X|dkreP676rE~fn561yw3GXy0?t1)K?^4zrHRf!sqAow3(|7clwk2H6u}!&#tGKXMPyho4M6% ze7DzoE#=h6?pit2KCW7c0?KQ8mW+z*c?Lt2Y@twJ;vAYB=WsH(LmQzy*duHTDpNK>*%&4f0;@TYsDDC43I`ui} zw<_sa_ufhE*QZZoM4Inc=sgY9dcD#=GgN-$nYWc&MTy^7hskwPUs?iQJhe&@(vUKlGD(&<+96c^Q0I+c{nGLJa`+R*?UeN z`m{}im|0vd>ATU~K@h?Ry-*Ws*U}R3mo5jCW zd-Wx1dX>J;uj8P8HmFA&Sy=_2KPvvEoz5>>ow_LgrK^ThU-inyF#aWvcGu6!CwEo7 z)wq)fpzGB8`ONezL(i}0WDx%=X;Z$QeIa@J45nT?iFlVr(uJU0yvqxdO+kBdjv`%l zwwyng2$#t@$-M5bEy}y#0xD@^l@f&VuA}xI^wnnnp~JtX#UV3XD)?uS8IuMFgq62C! zpB~x;{i2)}G?R)d9yIqh1$DhRzo2jmBXhc#oY}~l zinobN`XFkj`_Z>;KL3+WV;08QoCzjVZowJ|FH1Ov;;zGbswkW3?{IwN+HPv5C`zZR z354WohP2A>AKDNG$b3JOm@~CH=iHZwq-tMT?2SpiiZ7$+PbVh|``rIcYsRqpjh2Fa2jX7c2a``atgeN^-gUy!+j z8Nub#X*~@7oz$aFrUwu5TLTG$*~t!k+$HL!#(>czFD<5zX_CFFl|zRAlW)_rixQPI zE-AL0Wvu8y&2R~$M^T+u*8b_>ViScnt^9b@lVFw|+08Ury?6P_oC%#`YeYXnk7(K( zRq1wBdT7~Eop)E?WpurB(@1$mm9s9_Bks|CXcTm-zw9^FyS&vGXmF;N7`kI5Jj177 z{6`J=(KR9daPb4DBS-a$^T6I$7NYPov?gb3Za0fJZ9gr%r*b95n5Q$M(Wuy88c=}j zMT7J&yhOul3F^?pmoMo&S!GlCe--zq&;Zw~dX}+^d|(-CsGAxw&T;*0bE-SL7WbR~ z5Az$WOEGraRPO-+iH9D356w#~34zflGAI`8yDM< z2Dw>NU)%Mx;v3S>Fu38JQE}YT!BGs&)b!${0*j{4Vn?u%SO$4V>*7uo#9P zci+!=Y8jygwP_g>{fW^^nSXADk84YP89ypXqs9mE45#x^<(z_N`sNf|yz#;eQt3S4rmqFPM)V&bBGMP|$(}g@2>N-p zU}twXOW-_u-_Ls|%X_`&u@p1@l&;}J<49vXaQh8(bT>PwYs(3}b~>MDn#)pmy$I-u z;twiTcE&G`{d%x9sE6X5X=?JQ4mWhKU;eWJ2_QISYcX4u$Dhu2=9^D|f2%xQ8Wxc0s7x$%&adwnp^;*)g8W^n;X1nGvM&bF$Iq1&CTBUN_GT9PSSbUjq z8?>zyOe@|%`gu7$)w3_+4f0^A=TE#Lu5bK_D-(TDJ!w8m(j7V|2zr_G`xDM+*Om`p z?VzcYaVoRQf|F|^THN=#A7RYhy{}+q+MPxkNCvF zN=6^QQQo6)<<~CZ)58fDL^$Ja)}namu(jw22((_}^?Xm2cqYf3YhU!b|H>$+Y@S;F zb9|d$XI@#0HupVsF!uOu2hAr~TzsXbws?(m;EB&Ba%6lNQ{VO~MTl9}`U>B7;nnpq zd=OqCC^2CvI}XB!m3hY*EdF)YqxB7bSfxD_{5pY6Rw{gPSW*sP%hbp+)=J=tRL5X0 z!xLx}&{opm6scs<*I8dBzF9Pz+r2CAa{yrwY*YJD_$R;ik6|}_9X?>l4pwj$C-IP^2?)qllThZ$0kZ?L4)~e`t9qTgVPqs3>XVR17 zSzcraRw|fZ&Yocn6-BX8IF;|Q)Et;}9f?T429Sk#)7+Cb0$_2@&F`%0Q>Gg1yz>C!`I1Fxgw6C%1>-` zI#+T;=lO}9Ue8u-(J48!!!Aqti2+E*6ngD&01q>i<9|`3`}yf1@u(|5#t{&|Ws{#6 z45oB{VQ`m58?;zFci(w_hN#6eIwZ^j#LKVJR;JF}O%#6Qv<*yjf5Al!6FKhDIC+l)?x~hA>N{IP2$(xwu zx%??=ERFzWsK7n|p$g3lItH~u>%qc&1{WYy$*JlDeyqFDer)cX&U*5@HResbr}OW< zX}|0I06!ar7uLBDm-lxT60TRrarvo|PqK_*Ms7J`>&$OFHd3dt4kO?&G6tNC%`D(m5c=U>K;^SB%T%=tYECeZy2=n0R` zDkg-l*L@DZ2(hcspo-jX`aRH%(rLB3#@=;Lp4Q=Ai>X%i|q~dehD=_IifE zS;2~ppdw+)mW@Ft*sJI(APO?6{l)v`U6u(1XoUg`geODy#-h&n{VyOq zox>8f5+S%kh)wR6R47XDN6tD$CpGF%oisRAUlYwJ!tIQ|h2^PBXBrJTXVc@S4f1{k ze-_@ym&5>rY@u&OC)I|yG7Z=iec|rc!q-8DEL_n=XnFuc3GQwPYU+3Z=D_NwP=l~0 z*UPg@=P0Sk<>?mCVCv=LL;l_9b0hY;0-;(2;?Oi7Gv{j9s@K z!54%`_*P`9L`*VSOMySX9LuObzanUf`|~SN^Z4_L|64-lYupk<>dUAmggbv`sv3Q{yaK>dQ3lSItcRdgNu~Gy$)Cp7TIvX>#sJyOv&|%*qf&pD+b_YVlQDA*6_Bq8 zh#WUE>0`A%qL~7qelu&sO}PM|^*`neasR{hPV#Z3Q~IzpWvD2E_q_5j9vi{QOPFsN zR4O!s90|VK5)41UgVdI)3{&fNQue-GqcyOR>&oNFIlU3F0Ywy7#PLW$AzZ!^2Okr9`7^H*=WEG(m)89i(VrYR1FIDgWbE@e*9_Af z_0i=U|2NP7e(dw6GkN~5vCmt%^PK)GXmeD%n?P0RN5?*IBt&m|%h>0)%;x!xW1pXO zE6)|_ZxsCaW}bgz?DL9Kc#fWJbopIh<@rC3eZJ==p8wCW&j-KF^P|T;FZeRg4;uS? z@Hadkf{{geWN|*A<3>OF*#&n|QUILY3zkX@8kLuN@AbjB0qb7o1}n zt>il6bEO`03lS{=INB*Y!u9;;{ZMv{h&ME@p2KOs65`wb;St1|u%(tmzTyZ?mqZ1k-?6Kau^vsGIdU|ad6U+X8bj1|3qv5_OFEPn?9t; zhg_}ws7QBtY7L*@@vJ`NNUIUJ8ap_rO}iVU5An2aBlIB(Cm?-Du`a^((T|{$n<>Fp zN>DvO_e${NLdwt4_pqj=-nI9ie<2fgQZ3gKp49AqWzIn-HSt+`3x7Vy|Ie^j+P3q* zp^jglqf8sR5nZK?pD1=)9CT}xljEcso{)G$4EM@AyP!^{{E&vA==0iiNAdr2TCvXn zs3>*|Gb|^qyyH>icy;&VqlnqJ*y}wV+#YHG_#G@T4FFta0LIdB6D3d0-ea@n*vZU2 zvpVJwyG8Hgpv9oU=<{fK|EpY?2a=Nb7N-Yq%-VpN;=1x%R+z*?y!dF_W zpc|OADfhCKp-EgzQ(vNt8ZD&Abc*1bC@Y#y5$#j@8L#&;7DHta$9UuQ9ART_r9DAJ zwn?$FFLu9C;I00jm;-{ITboxhf5j!kPlbFoH?{?!z?-IQDN6-J5(xw8?y-qmxNF2L z(L)wC^?o`>zql6?U!uPYccdR?Wn^E~Xu17C>n5`;DR0#5EOpataX&DrQ^kT{GwnZT z+5y9x5TL!)T_%l_zXoC9F4LtEu3*(gUhi>ixc)>9KR(@`sHML+_td$MM)xsC9~{m_ zSvlE+Z?ss9jsH3mi5dTx7+|4;C8 z7oWV~8>txDZk5u3?@va>m8$_2m{)Nh^^i?lIrA(Ghraa>Jb9L}rKtz_HrBOGP15oX zJ|1*vlj5f_xkU-85EF%lAjo`QOmjsojeKE#icaHs5#hqK^T^%C7x_;ki$N@H*Se0W zA$J4VB==S&*P-STjf^xIPthfMyqNB{QgYFQytB@>Z3Tvgyd&a2fn%wBXyYON-^YbJ zDrg*GQ>_DGCjo9vp!WT3`Xf2>Z<#w(m)2ZITwNY9hl?Hx$Cjzj@B3*con|4~znQ|+ zk8U-`ySKA{1&?QTvf@|k;+nTWr)EhxePE1>pQH&iz>B~dieR8=r!*(FO*0>kl|xpW zUZJ*x$9Qf7bNzMgIVjdv*sfwOcngG=vu(L{w0kJedKi4Q^Oz+E3eR^m2CstVTUnHN z;D+Lw^%gLlMRN>>&6jHeDBbR2UNjzU2RBWdVN`X_Gks-^NSLDTE@HDgxPU=iGG(*6 zJoGcl+q$}QG2m6a#*-Vv-J_j^LOy=0JBh7;(=2%vF9P=kuj2O_72u_;=Q$6xORWUw zagnM&?^Qg*bNy%IgH7hRk$4qPcom8!u}Dvh^g)QJpnXW-R;?PpqJ79AVRNz_AA8Nw z8JQa@zzmOg75At6^>Dp>3CK@t`sNRTiMqCYmy61rk@fCs3`%6(rrGT$c7%?;PUZZ0 zT|61fuO|jAyb%IpuwsXJH2ASB$1WEx(>gnjJ&EBM=A&gJlISrat=-S=3R(umx~nQu zK*-)5rk@ga6Fc}Ivao3~TL#IjC;)S}`&0bHRudCYI2*6-L5XwAv}uof7Y|smq6KjdkIWg9oRxC6dU8?$qncgd&jPCzEu>!2|Dq2? zvx-siq`tVD;g72w9eQ7QZgO5b`2qd5bH+x$eWa2ebg9D`{kHj;H57Juw0$~k&cp2q z!<#v9GWzphNX}oeBbbu@HRv^>bMY@y?dfGQye%Nt+{5Xqq7^m`{JGYR`iah;F(I8l zCZ$vQ5WP=*_^knDlzbLGB_ zkRg5U8gwaseN%E>Rx<0acT7)x;l10ppODqz_Sc)Hx4+)JpS9z1y~YIFPRO~2S* zU&7#&`J}*9a&J+;`-uh@wwu@=Bi2q65;*_nkHHQ@>tTn#-6n)xh=f0`$4H2| zelGkhob$FlMnZp#jqe!1&>tgX4LpDzBJ%$K(jQ~N{29AXNgV+i=-Tql)9rxlLIF?~ zG?eu>aAv`2#l89n8tPcx0u-~~_%dnGtJfr^z8fr5YTDf}cE)I{Vb{o~I zJIgxZGUV%+6A*>dnd2;KevYnx%ZbO@wdJ|Rx&5mH+oW#KbfMJY&4A$Cu2tS%6Snjm zPgVL`{Kk@+e)X*NR`AF+5{8t|4B<^Asu%5^_wf81jhQYdVNBujf(CE$_T*_ndzbUrPV# zRkk#7{$jW24tL=OvYYVh5QyX40(s!eDJ4a@adTe5VM0U5y$zxNnzFn^J4Fyn_q|BHbM{4X-JBJ{r) zeCz%f+r?<(f3YLL&~e0bw`*z+!2bfN zHlEn@CjJ*H^#6qaMFE&8%b(IH{uetY_P&cPwaoO+WBAX5Su@d{{_Az z_+Lzx|3&-hDp)VfW1bqz<9x#{#6370qwdpCmUumfGmSGg-A2w6d+Wb~@57`S@VlkDM}hOhEF4YBgIR@seMK-UF5h&73|!M^ zmB=%FmYg4q=ap1dKQr0A6@WrlsjvPgD2z4)2k&p5mFQ|PxN!Ih%R@AKB&D@3GK^);&cb+_j^)Lzo@2UQmlj|x1h0^D0%_k<`{NRerO zl#9iM+|LnWq8p=KEJn*Uz!~Fbk>L+)zOO$@^L_M!aK1(6_$#wrIRnn@My~>J7$`vZi)OJR zr{8H=m>y#;X>MUHj|YG*b02}NGV#`MVc>nyZ1BBP(4r8XRgl}aFg~XRmzxx>ju2m7 zo;0y-p?yteB2>Nwse_7Kh|?KZO;B6Y+lBY3=hnZheO2=Vb<+F*L_9R#+!XD^);awk zg3kE^`MYp2t~y@~@AUL{#cuY`G6N6Oot`beSYxY8!*ve(53zPN@W^MuBR7aQ7LQ!T zr+8#7t~l8mpH1_B9<@#5oShhwalpT#Wc%`=1{$}RPWi}83(LQVw)!Y z8_GJe5$c2Ai#s#?@8`lDm-Rp1I*R|Dqb-R4aRxVs{O|S&`CsLG8s&d%$P)$KNdM#Q zrVV~m{ulq_fuLo3j@Gj_<29VYd5*_pbrKu*!2pi{<-BY&OlJn$y(zmm4wMYjnNckt z0F(?Dogocx4kY4SnI29}d@g^A8Z&@02zMWVay*AOf&l>%OgC0=pz{#o)Xn7k@`X9r zHqv5_^7bV*Y=+wuddaEb@H0+}+c{Ri=f-%);Lw$!{BHipSJxR{kxMWx$;8uKClBAw zHIzOBt>|OkYGi99#A_?nHH8Zo!N=$K9?!T?Z`##W_C{V{yfKGnXWyKb#^H^p<|r(g z=L>MF4AXA5n3phtuB9aY0RPYAsKcF(=1GfMs5p`_U27d)tofD#ec`KS5>Gu|XzeGq zrehF1gZ*?doNm!dFz75#S&MBbk5Qv#&Pz24Uf4AI8o`*vpOY!j^RU{zwfaOxogYSTxEqM zkI@Hb_|G#AkpEOzVb=J+l>hwm+hE3Y+XaTqxjZ$5{AWfyJ^#nL&MT8(_$P z?s*$S{%_2Gew`yn{*M!Fvl{c+Ut7o4#z)Lla{aZn`jxZs_0#;rGJI&3za##o!TVtj zJh2Gv1^eJfU%?5sYs;5im8}6TaKh_(N?d3?*Qj|^ z$x*PYa(vz@ysoQq{RsZN6SqTpuaW$x*WJ$mC{4s+Z`u~GNAXtqc_vmc@N3(4uNfY( zK89u6Yktt{PV>6Ez7Abx{8Qevz1}5P@qp_ewaX6%>CLYV=G7=-k1n9ks|n`KctQauCcXpWvsqTh7QN9Rq`oj z%@mrcqaLuSbehcW`kH)oZs;aQ-_&FQyzC|h0(-p}ADBf?c++0${0I7~5pM6Vucb32 zJO~x8ZS*Jo1sb;g_1D|lr@>(6Pu5>wc<4iaU!&|2cWD|4`+E@MyZ_bdd37t^LnFFK zxOfjOz9tG#7(!6=4|_{kBP&_U z3E0V3*=CXQaEeS!WMFn_wxo zd8?Om9s;}@&`Qn{LnvLrEEv!}V}so-vNH>o38|1lqXSeFzq$l`=Gevg@sV7jX*S!o zWFF#YC6mi>!eA0+#n4G?1_@L$F*9@KKxZmSxAu})v;~tn?CYKXj&6&7k>A8W`D}(i zlWb}H+2fPO@MrJg-P`2PN?^sn2;>8Kjp2s;+4KqcvrB*Rw)wNw2Wx!)IqOaMvo#0E zpACa9SiJvI{_K>u!K{pAr$YYh)OQSE$e(3y*uGQz+2j>q;RAF4_;1UfaT*`t%yn&< zTWh;D%nz1LRy&g^DR6oxr;-2F8*hLzvIS~J7x=CUWW^YV4G>ha-u`A8clW($zs=ge z_tUxUo4V*n*3wL|cUSNgsVkM_Q=oKbz@Rw$hd~G&gfJe0_&XHz(l=(}At-4|BZ#0x znU3xDY<(%-|L1}&T`n!5M44z%?oo`WQQQV7b`3@L36g4f*Yw4DcsrpjLcW zTbqAYhl=oJ5Oh&^D`0ZJq(I?D*_kZD34CH(y%JtX$cM!QhCM3eXMPUj7Y`Y~yu;F$PVu6%eAk>1Xrq8m?dO%^2GB_QV#*2b1XHjmXA07LC>!ecKAxvN`r{L9kL237 zH;vNoEtRt;`n?Qp4f(N&;|u%+IxtGVCj{%aY#pWF8-Ve)0Ok9(Z=+7zYVid&GR6dd zvi9u^QqA&X8}_Z<%R-tfNLl-K2A#es4>Y1b4oZd}%iz!hfs*0JGKlldp+x)`kpWOa z#hs!2t@C3oIys3A{w(KFIq0p%^FezmxJsvYTA#Q2A9eOk8F%gXdB!_2QGfJSe~cI2 zv`4(vQ(cv_V5Xk-Rx6ygC*|6E+~Y>hQ~X*vMtjqq^j5#dDGcKXc&lG@XIQGd9p36E z?bWpwl3?`?omSo9--K4qn+6XSUf~ks|7md$+QsL6<+V44hu*z5_n+bCPM&vd z8LD>t5U8V3yqE6d|A{m1^l`tY*QSpXV$JY-D`Ni2{m{qNNFV1+!u3_D0VW7HsqCYf zsejiaUD2wN-nay%Os3NJ*GLIcg5BhI_IX8xI&xcrVw4&1}D-=|7O`pdE!(4SHK-9YfsH87F++=_aVkl!t<8$lt*k_I`&#njZ+mX0PX0oGoQe!9;nizEV|S|7wqGU>`e_ z&rd3}GE&##YY7&+Zzvwg?{mt}0M=&;l7*iqYYMDYu!0jdrKc?v-NO`i#%jc3(+ljI6K6Y_@vL=oZpjKqc4xa>AVSN@sZo2UW0Vtmst8F{om z&gHTqt-NXu&(m|>rxk=-^f}^#U;2yVgU@-LxiUA|G5W_3ZZvFCngP0)vVmS>-yWw|@SO~kkss8aj)ELF@8ejTfpnn|2q_P4Btbg2p zPIVkl%nZN#mNbV(30g*I4l^vTQ3lcGeXzV{iJrSdmykXa4;kMu(Aa(}9_Q|0PojAI zj6~E-2&_-?BNGDaBV0A(w^I?8Nkw=xKSzeZ!t(7xV72Dp=nNmXfAO#686NS3b`R0~ zFQwQI<+*J9tDqKi*?tH*#@+R$`5ggYh)hdAqo7vKVx5U=RoroOPQQeaBK0Bcx0DUY z<6gzBk6|?TZZ_jKHtmWxGP=o4V_hw!myD;p%`Z>#n%_9nTekZcZxOc|PyN%G-it3F z%ccnW8znBOH|lfp3*dnHwWu=tLlWn=>=1&8iSQSsHvfruLC&a=o=3M*T_6odpT5Jl zt}XAH=J+{Kf@~aMvBuQ90XoXwOi-CDe|uo|=Ce4$V4+y*H#wZ^Dq(_gIM+GbCgfa4 z@)4}>7`}Ba{$IN^xQ`Mn9#oVXvrasWXuS3T^xd}#uYV+mzFUm&`=58@{cb)(@=m^O zhwoaf&fTsK@dM+20<1?Kh>eO(w1?^5UH|TUhNl>UXBg=%4m#G$k*s5bpWyq(U_LbV ziVrY|?k9ImC0QsJH9H2nzc8>%pAb3IEGM=`^d0dHVB5K@>d)OFULh~2*^tez)VsHxEL(%! zi5-yQ)>s$BKmP&wqXlz!5K{v_>^Pi(7jMRWygRWypGK=YP^}lm)-1cuV!IXLSB{N4 zvBT|F>lRCojH%u|{v5sQEFeBve#fTcTQ)71)H-*2`u)t9Sd;a^iVfATw7-uL1hrz2 zU3^7UKVYuZv|n(#Tuz*pok3pp=8n%sCp@BSr7V_MpGzT9ArP6?EMN+qSg%er{yPLL z!9|baw26UdvFRgz&&hv0K>qu%J0B2ZlXnzL=iORLWSu8Q$U4X?b=8s$kX_c)_P-ycACU_}-fy3kfxl+0zwP*Wv1QM@J(66vb|gmExL2gZwWQHh7con6cD#M5D{un^bjmBiugXJYR1hj&>jPow`k_*x>y<1ixk?JZDaGRa8OJGHb@A_@i~Owf~%9Cp^x$Rf}iW zo&=;_+6FJJDOUaF@}}c)o=r~Shk9`=pE|XqsIO#mGy%7m?-hK;`P9}dwDk4iF74+) ztJmvvM;`pqgg4TB&&+qFKD`^ zA3>{l+t74fKZ2%YF9+N=W;tYWn;;9y$Qs4_&aR}UFI-K&DYLXzQ;lk6wW{ky4#q*F zH90t8z1fj-N@egulrc$sNX~o5=W^0Vyq}y_sN=P^P39NaE|C#$zI0sisVfr0ii6V1E zOk~4yFD~RRqU5&Qte7a5IVay|OK0OzAn@5KA@)Ig`LUY9?q@RbC=f}IOu~uwB%v_P z6UCz#@Ih=_qtLvW7!aexno%&W(lW`5c`%rg6u2@S^U*qR!M2Ec)t zXgt=JmVsoq9WyVtJEjnfVn6^zv*KbvjF}Y&C5j{g6lqKp!$L<(^1S)_sZg7?^4Af1KvC_XD%9xEEMty!4W(-8PAJt*-*W(gBjOcgqWO= z5(88a1Q$912eONQ&l6n93cT){_|{)Gp|(&g6`ul}(Wlc+=Fs6e&)s<(6+gM- z)QGd(w>=@~*b#6vrCo7$Mi*d#FXoM zH$rf+?+Q|vQYp6`>+iAF->b_q{0jj(C2y+Rjj2NzozT`@sZWDx82kAsh}Qi`G!Y@3 zpfT)FB#Qcy0JSgP&J9?lxG#@~b2$M=Yt0JT}*6){GP)#r$gCWbr5IzNd(5< zJ7y#|Xz@tCjm#o&Mq zkA*QiQV%g=_N%0t`Z9~fvFg*R#?~$}bph@QOI*A_+I#er)H6@2y@js5?OJfF-pJoM zY!S?d9>*&mMb2UiW+j z7IE?v<%)8z^SVmYMYyWePblNU>6OtC9kU83hR9X0@ISoXZ?YWLA4X^q>!>6bORoa^ zBSWqv`V7CHwJ1<+DV~J^q>ypqC&(F>i5Ilk&Vm3Y=AgR^}!yoZW-c<{5{xaBO+Ul z%ID+aJ6y>I?AmhZ`)&V*@h1v`BS}eEIf~y;#&!pF7c1t(p`6jw?T;cK9f{ety0hS- zKa$}~@nKTe^OVj^6yJeYuW>#~g4zOL(8#&^HRDfYKWr=>)gC&AguQ)$WVh`VDBMTd zJN7$%C$@s_JIjx+Det(6_G1y=1K)lZ4A8aZ-K9B)w;tv9rb8nAnrVOj`aAH1%VPHT zl9!GUPDGSS#x^Bm7c-93pHXIY*B9g)MWKyse9uo<3pZk-=dt{IYN^P$J2mE!;|V6y z(fkx$Wk1yFusRA?8?&$RKz@!n)RxVcp|*WiM3k>KqG=>J^*9y5`Y>vPq!3oI`P`iEp8?Swt46SCoZoZHpjFLz}xi_6X* z#gfW)1zKUn843t)rt3{GDH&U%E`5Y9Me|k8ky8Hm7^D}{QT@4sm9;^BviJdK^U%07 zm`S|kT)HvphZq2xo=N&5R#>Mr&%kaGyu|iN^fxQSuyW2#U5t?%l!NLo<-ZHTi^x35y`5HhYF0JCQwu`tBhK+ z>7yJ?<0qHq@8P3@|7YMcPvAd8DNT&0O@6KxG;%gwZj;V?5f_mxu4-S`lZq3m@F90G zoU;nLH`AG-l4=FHJ45SR8|%27>C%ApCUyftxS7Ma`xx`;23*P)qKQ-pi7Y8Ev^`H$ zyPksR2yzpK-94YV(AtrM3WhG;^esMW;2=q~qTC@X# zI9kTwR7H9y=*?6E_yY$p^dB&P(etPagPl5yPpV|;$14x13tx6MLjO?3LpmLvnA4x} z59LJiGZP*Vk_I zy76!a<;EA2JN`sIR~A?}&_!GNo`M{;KIT$o6>orr68kc{l0OT1lgW|=L)G>$NbP;F zG>>NjMK2JaBpaY*$@))zSS7He%aZkawj`Wq(L#}qg~F8L&n!!pU@laatWiLf94r3y zQi>W>>a-bDrOFx&wM0-soDM2=tfvdhvQWJq0_=b1AyOdW~A{WwZeG_Hs;mzyk@V>ro`PX=8Tq?`JWY#y& zxLf`VdfDXlI^+HN|3PQ+LKj$Gh6%G2{}ZW6!i?mv)X_gMWFOIYKzs>~_}=vAMFiyU zR`=e7&-_{$TJxs@?Mj6-?{u+k8Y2=hb>o^r1Jg9uXV+sOuE8Hy1#Wj zzleWynB#XrajoL&(IUjLLL5-2x4HooR{_Ol$l=Ve}e4ig%b`8BN4aq7>&#^a4N;Uqi zSLBe@9J;uXc@bTFFXUA^Q?M=y(-HSa(%%m0BJHHP2NEfCoITgsU*7v0Et3B(oAfZ| z3(k>bazpL0!h(Y1IPwYcX1ETV5eZ^wV_ODgpCnrMW=y>Dk8rwPXER6bFPDR7ne6W8 z%aYx)4@S^2i8N=g^6T0?#0w860YM0Mpv z#!_&j084?`vxS@dS%q%bCdnU_x9Tt6apb#jc`yR54zvbK$cPbUz|b0G2~!|0(E>({jj4tp2>4sn&Xx_kuSos8+XcX#N! zrh7_4L6>Gxkl`Q2Umc5ognahWO+!AmB@atBa}84vBSVcY_nN0WoRJK{c5dyaA^0d*f}M~fzNvHb}1Qy^Q4Mw z*?|e_eUbkNcPGym5vjYl99OvNT^%pvtO(U3BsFx@7&~Evk4ECJ<44*R=^qxZz3Ii; zw(u)7Ra-W6b*|m8*jj-|{vve;J9wo2nDyrw>wj>#{vrJ?-ntL^{T-|FE>|U_--kfI zuhD#r&@agOTQ@FC_$XcpT zl!!d*HLb#H)q6W06AUB3DAr}2RQ$CFzp1g93iuG=PhXaEmR&26d|Ji$M2F`xZw|^B zI{f)0)%LgPWKc)MF~>6%V6bd>dEsSneKQ<2}NU2lHY+7h~ra_)P@?9y?8i7eHlHtKQb}XP3z|8N4L&@*Z}1L9+Y# zy^s`4kam)=>oAn*nhE+ce6lh*$ncW0cC0K|OwWyYhKA12UT{k4OItL&-{-w0`totB z^kY}a^gl4SqAxdu_n#yB(k|yBT^+JT0C?cn~5>NmV z_ozOM+xRM`oyNUi7=Mg^cC3~?WA5Nj?3%hY*_~oWaQZt2?{J?)Ds#CPy@Tyzq_irh z0oHst%=kD0%UnnUeqxhz?zv2dJ=uLc_0R(+a2z^8AQBrw;+j~W?EZ{Bxn(4M30gKW zDH4(*zIQ$IZ%$&w(zh{eM2Sfm8!L`S8#H8yuPTHiACqM0`>M!@TGj`XA3q8Y9|}|T z76H+`WhZS+RU_@Hir-C++tX(<9c)_Eofs@Ue#KU=_tP9xBC{rLI#V9>wFPH-(+a#^ zi(j=jzx^ZpY%IKuuH-F$U;4LvAm?GJuPy1`RLHwL@8Uan=#bsB$=Jz}eV9#LTd9+M z-$r+`RV?VZDOhnsfInVCWwP*Oj`t|v-lu+zr2v<+h6*ODp$vcA{s!_A64t4qiu!qe zL%BPY{S7nqJ10+ri9th0j?0I`vE=5(>G=Fe{vzj`XZQ%+gANve-B&*8ued3V|3$6| zL-R3AD2bu#wc%`CS(4$V3-J$3A4b{K%>R@1mlyuyC-{#W=irdgzG2g|mJzd}sWp7^ zDr?_3(rN^*hWv5Q2wEzX;ZlpRJ0VuY5E@tZxFWg86bU375X~$VqDxE^x4er3 z3etQf%wGi^Egvd1`NMz6&Ess%W1n|%JKIMmrjL1~!%X5PN>?(A4>Os`VrzmPHh(9a z&kuz2X)T|aEdCDjB4y6WnipjqT)1rpen+hXnvXPrik#d-H!73O-b*7(4-JO<9rtbo zn5yzS*e*(D9^)f#xT!24r^kimi+10c-%;TIru&)v?%nzRpMU$T|Hh2rsk?$(l_2G) zy~Y@51)Hgwy*vT^{G67+-Uvte;DD>)7TA#T?O{{?iu&^Q!DWF7ZmHt3iZ-a%)Al;s zpqLbV(~7V3x}Q<65_bBnh7sQM$0-x>x6Odne%~V*5^+?N-Cgcf>#b_J>te8*_}V8a z1KO;>Xy?zJ&dk7c#ZT8xtV|YPZgYwH>vweP@0c#!s^pNc@KIDQN=UjTeLjcU-<3bu zo#I5~Zp!qT>b3DXIuw3_kk;br+VFz8gimu|07kq_F!{eDg!?dXf1AEX{o0&ftdHFx zKLH-tNyo~dY?Xlpn$(73I1HeGuZI7JPj07NsnYBkzy9p6gketIV;JT-x^e+H<2><@ ziSgM7Y2>&#Bf72Ayo+ytL0DvNS@PE=qr!d|k0|wsL>rO<+Uh!D6j5&; zM?#7L6i3Bg7KyBkb>=!zRt8i;bTtMMDzLOo!ka{HJ8NQED%3Tj(x#}^m6(K_W-dDmAj$3o`~b`X zv9XigC-R+dq)!kF!8bxv7zY8HoRQD#LLNdQW3=8#5>@1w*4&B2HxsSf&4*@qc&*Tn zz2u?hiit`+!lvU#MKX3#Fqa){*PAF_Np0{~Jk~V=U~LXS&K!Fy;yNfRX&AWdI1Scb zyH&eW{<+gJsNZ8B+cAL*~rtwv4k5sZ16|w(>PM! zB4ZoO326L$+>3JWB_+!2q!6U70#zI{<2RsXDfb%+hyGQJM|gf^PHFw6j^p;1>^MFF z#+sv5MD9ubhFk1VFQO29pGTNe9%2o;cU&+$d|Mc{c(Om~U|y|42tpCe?QmgSe|9XG z2flZzU=TMqv*v+|7WetH3xj!ae>Or>u|K;wm{;P@E+MI5|Ew~HX^Upn__IrsK@3Eo z*&?0YK>(Ea!_H<6s#rxQ{uHCimH1P}l#DC?l!fxo=_B)dpG|xcNtR!zO1PlhN~%i(Qj|1t`SQc@p?9D zY3mDSJfJAD5Ag=ZReVl4W8xE=nwIs^;*O4{@M1B#YYI`;q9a3VM%Sm-*qGL zH|oxbV%@ zmr5of25RV`+Et*SHcWG3Yj{Itq=w6cG(i%5%?XXqIS(aRBe+?JM!Otx6{S{Nbk?cL z5cSj##B4bRSr%>-xt+?I;Zk)^>svlvoPZH>5y|J7r${y$2OqML!}w5B{1rQft_ar; z^)Nf1rkaSx^}F-0LW+c^yKpTRJQ)5Iw&W&n+5)6H`liGgMJH8G7#!fsY)IKj7VPvY zZgjx`8Zd?yEx>O1a=(-M-ZVzQ6W-?Mi4pKJF#=vDM!++~2-r!CfTuYVPxuWrk&N14 z7~-Qp11&U64;pIN4w+YmF%Gv^Rqj=UrKmLuja~Rtu#{ELlo^A`S}Bt*U~s7qa9T#{ z4-Eet%VXldzhJw62lyvrZ#&Ix_rSKh$S#ZiCiXV0c6LIv$ypb!mTBYL_GYKsJr!eX zAn7?u(;S5%=d_M?>~+WtgftsEVp|`DzqIm>W=A03DmaWL&L|h&4;x<%sS~J9h(%Ga zbgm}8SD2&7jrM1jf{d@vH8UKsSK(|J0VtA@@r4{77$avD3|%$OdUf8c^%{EKtrw`U zR#ZU#5`VhU2>e}M&pIBNzl1KegyyrtK;|=yXqeBqRfhQtBO2y2{3wdeh=%#Be6;xt z#<^I;n}Mf(vzHTMBTB9-6KgM;p1s3k?9pSyQ|IY;&JogUWaoo@;`Ex85nVrR3;q$` zW8-&iIm``iKl~%UWaWQP_)Q3Fie)PEA-L;*vJd;pC#=eiu8Q`1lkR3YyF6Uh9DtaA zMCcnKUJ3q2kv%~NnaG~E%6XIDH~t9z2`pa1o$RGZ_>QoI{1~f(>*j;!Cn&gBq_lVq zIO(^1In1lr>@{yiDql`g_KJ_eKKT{-?pSwC6*b~KTP#4JIJx@9V zukJw!@~?J$-)uEUy9-~Er=0U4A{&@Gbu~s?CML4C0;YcY(9bh*&M#%2B*#i{pTJ+@ zw)1(#RHTWi5yj7Z`6eyW+0WUe=h90!#yx<_*eC7eLNAw&p_dccCzr7=On+?75tGe6 zNid72OlzDBELToQGC7XWJqd4XjW&%(E;l8ECPX4BBeyc8mLL*xxjiDghKr2%XKE4~ z_X(+cksv{M1<7Jf&W7yO?jF+dO_lR6g+O|1&lX&obUZSJwGszGMBhu5GF2bFrTr#{lhd&FS z2GSR+hU-+u@z_85da|n$#TJ0R zhPn5&i6deN0v4Bzzz}U{R!d5TEG4toBk3!_1>9Mo@c8ugt%9=yW8_-;|J)wF)!t>u zwSYvi0G1j@qH#yVJWz5yX8#Lk=E~n8ou=D4G+OfnV_C#4r^rjD5Z2T*a?alF*8h52 z|EJyhL$7N@QADp#xGtjCSM$i|wa1sY>FzQ;q}ToR_|~lYbgE%5Xe%V!wG)u-ImHu` zZPW`n^TYldL$@>fq*GGA<5+fWnYYshYxI~~g#ERq*9vvl-pvGcs4d8daPgrE`U!%feVbY`9WciKQ9sqhw|GtCKpWqz5VM-;c={YFWnC;EGtj zck^DIyxZ}vXq(LQQt#%KAjQ@`$=>XoIVa?q-=X%ESND)=5~dMZypS6T<;mjeWj|E| zk%(L(DxtoG2RRav&7N}$5;fy?ri_pciR9$#m=n?YcaNa+l7}<;>idy@_^qMqdAY^Q zW{t`i7Rg{7TN9}FadGQSvE+jMWFa|K;&n+44}(VAoa7$wW`%aN(Y10^ikkJZb(^Uk zyt?~|16ei+B>+AsIysHJj5qFaGr`~5Js3aA82+*=(kO}|exsLj(zWH)CvDAh{h=@@ zjNmuchuHD^qxg-9?bV;8MvgOP)*tF@r%5d^f2bYe{YlYh?Ei$!24N#|DZ8?i70Eh= zlK8w3n)A=(IpM$nhM(uSoI(zDAHaScIY-%bN6gu4nz*Rh_3Engh}W?C2G%E7F-Ukh zz)m^7A=W-O=qyG{*xz8Mj&yR#LQ8e&-8{giHPJ%n?HbP8NyUm3(jaT7ck}ER>ut6e zANEnSuT*8SJiE3+==Qmv_Rbj*hY{K-valkqBrDhNO@oAnQx~vTqy1+1b2Sghf5CBO zdpr6`a01yEaFH@$bL4VMn2PKR5=B_MtZm`vnk}eFD4!<6*fO@-p;niHGm~$Lct+&u z9AO2>lPz}^Tu7ddKtLEHP4172XRg25zU0V+{JZPuJi2p~9$yI000E&uzRg&xmaQ}`Er0!_(F_58pH7lEx5UmL>pqIqgUxQPEk7^|3tu_CY) zVXSZ~A&eFAYtT&+*b3Do4$>7C*b3jwCK0R3YyvzsU~2MfS%TF%l3*=`R+yYwQ#vuh z8b{9Dz|I;@%cK{Q=Z(kGapDsn_ajZl46NK?;=mBSD&Ui3#M-XOAxP z=gkC%fTX1g-oY3A39CTV^Eelzryyxqa%ob0Pz!(BbVYiAJtqZk8_ZtY{FuaEo^IAL zx*~7r+tTw!_V{{np(0|Dg(f0mW{)2t0w|La+2bSnwexC6zg{;zuko>??X5-B45vc$ zt1PWJ!=ZjR@k6b_ZI9X_o4mRLb1)k-l2?aAf7&`(9^t9CihhV8f7AH4%I)^I__sza zLM-Q5{4J@7v-jP0gxa;J51NS2`v`8FB8C4mtivjYzfe;LN0*q zGzG9dj-Mj~*peF61+e|%DEyd%0yFe!|KizV{mw|!*?6||g>b-|^k76hTZzf*h-0e= zwl)}Dg9%eR6m*p2bOW#%l6xtrlbgfY*tNw}dM9GnX7tkahMBJX4%lsejbEQZe@jgt8wT0-4*e!MB5*Yd>@qA^_UVWAJ(|S_=&E zA8Ys=!G9cSH3C;7M?Y@&2l3s})H@zz4$~BeloOxZ>sg~7*B9anSI2dDGseRG&Eyvm zR);>~?#s-pg6}Yq7v=*ccF25`W|)t-Kd-927M??Sv9LqWs|r?1ao%jHsl;AzuR%_9 z(wbWgts^B*>p;M1{Aia`}oYjNWXw8D(_faNtOD@}O`{2*aUTl(*S% z`{QZaQETTKrY+aH^y89q(T@*0$=B3?EWo%@ud_?%NYR6=^IZNEjn$94;SFjr$A#r2 zXaPvbg`3ZaUGP@xW(N-mDpb#eGlbH^eh6=l$#gd`!J*_n&`usM!9zB6CkW zsQ|AV`Xpp_daR>;0%E;i{=i=Ey)+%k$Rq6D8U7<<_uiZS2ezdB~uk z19^Fbf%*ZCNE8AJUR)}g_`VI)Gc#6bLlMbufo3{qVxx}mkRL-UWy%CrvVhd0saG$9 z8E`(*X#&>|r#AfaDEYmg2k5`ikAY^K{2uZHk^bAZzu4_J=Lg2>zyCkX4`j{NZnFZ{jV1A*3g8KfX2a`gUs|SAQ@F7}4(mK1a~+1y<3h9D#0Ys|QeZ2B=)5{vA%1^BLKaVawvy$UBP zJ6hExuHm*muY#Iwg&RVaBesDT6%4pIp8*$py{}0>k(mA~4TMG$l^Sd;*_f{i{=h5G z`2%zhkcmp`W7xs_y=hP28{T=AH?8|RnNm*&uA9hc{%t~gZx*+aV_#CgLgRqtP?%7! zvaZ?qok*|3;26uFBjDZwWeM#t8ef_Igc@=B{)jJH@=eDVDaf_BXGr>J{mbR2aFFN@ zU2^)D8z>v{Lw8=PLsGrX_HZsgG+KWj`PUU=!-l|w1Oe};H}|j0<%i5)poMIgJK$qb z$978lZl-?eXLGHEWB8$fFx#PTU5m6@?}3969Mj@olmmw;;B`ynVK*L2l*7qv*KXhs zH=WV>X8@WU7IqAP``}~*0B(-B^b2rl+uV6Lzh}d*^vUKQ+`y(;K0AjKiMWRmHvf*3 zBTgfyWX9gV!`b_f#NK~3_JlzGd__mf&)Agq{5UB#=GN0Ssk_-48T+5fYY*`R`JXt^ zqv?I*PiD)zfAoH=KbbA&82KN(Z~*>fTF`yS|51GT{cumq5a|DY{$$7cTCc0`a_hyB zm-5@>>mT$+^!Y{}nSJ^&VelIjXOgV%lCKpN#U~DUOQAo%Bxs5I^GnGe|<1#U(sJ*nU^>1v#GCM!oI2J^1@9b*Q3JlY{kCiwjFm*C!pMw|I^_J z2!ulZ2!#i#8M!)H1styB4&KUuOgE5YNKfPK2PICZ^K1cDv zuhEzx(4Xke5NJCezqA@3b~ScF8*8C6#0P)(#PPwKr&#|=qd2({Uf$lL1yX$QFms;J zat+8TmdYoqlyKh2_~7pXkc$tV$wa|XVhUY+@TFAZ&}P~R@%O>j$s&?EJd0@q*a>&%q-hk8bNcTjt(|axfl~VR%oP z^VCUXml?BZH)#LwGf(e``>E3-3bAi{t-MqBrjM2G_inb}DE!Y8@c(ApEnC^&t?ch+ z*=sw--yRd?7y2I*XFpel>_&z5HS9%`PUzoZr`Apj^}?`W$-tIZlwqlH4kGn15ff4d zb7hY_jfY)m0>vGWK3J^+DY?$JUI-6~cLbGrlTZ)zG&FlOmD{zYv3^Um5z!dFO%U;5 z%$jmSb5ocgF60!+*oSlTlQ7hRBtBg^6ZoW)21r3t4vioBp6L~&ZY=>_b#1wHlP#a_ z4@r&@hDyD$G9m}&6FbGP$Cm&Sfcq0FR#dmLWuU;dlmMt$NeO_8m6QObs9wK}V}cg$ z#EaN3y0@Gn!JY79vU>mw50NOK9jAEh%|ZV=a?yVkwx!Sjy#13I^glg={{Qdx&Obh? z;_Cl5yHTRqCX0<4Yg)H9`h=R|qNxoJQ8wf!b%6x}1dJLqiJ?YFApx{Og9*qsiP9D= zt??;ssiifov_(s6)QAXZqm4o-?GxK*QyV1KXj4ENa=-60_wHtY+{M_h|9oHH?kkhe zy));WnK^Uj=bbxOy*w0SpRv{ZLyM+#Eu30C`zQH$7@W{af3F@eIW4}_1tUeYea74t_EpDF6c7;8E z7I}N(;)bTau-{WI+28M}FreCi8UcS#{b6}!$b8>&&3Z}fFDRNAG{{vz;G=&4W1Mh>$8~MjBtlG>ytGgUsJ@u6T@7%D>Ik{QR z3A^=po!TDB_W~GpIqh}nybw0=Oq{$aHgUF-e}$?03ti{N&3=1-VfyRq2BwQwhWv92 zMYjC&$ZhfdLZ36|sVDarmfX7elp-sYF@x+x33POMDAr$CD{HgWv^r!wusu)Nt=y}Y zF3>>+_Fs#^t7_}?WKegd>GjAKCkHp$v+DT*yhHe8${O|?qQU(1^eMbh_12W*Qa9pd zQ&>9t)l}t?^T>OWo4#k#-THo=G!yphmZI9W73EF)E82?H6oUn9;&aCTjOii+CvIsv zoF&gm`+pXGJT!Nv?Kh@j2e{6q#aGAR9biWK!ur<(Q_>d+Tgm}?%(@pZ9^v2XBs>Mi ziQebrjd+gKYdT4;O83ePv;INSnn8vod+|Flt=%M4_KR}@c@LI5t&R!q23bZV*J7pD zn=hi7`cn0u3QGO&H0lC{-ZD(z#4E$RF{$i9N{-q}laNW{PKnCCS^1X2OAYFDNy2#F z8Z#(me=T2D;L4dSuQKzRc@K!Yfi1oh@pC4b+(~A7BEE;f`G*wz`e#S^o;wsL+gch} zmQYfQ`ClWiuxI=WnK&#pjsLt;XvAE~Id;xpbH_RMNa5w_iSjOfsU-UeBkIMIxIYBhU%)pYeNbMYBpbb4^9J`~*cTHv zk!vSr2~|JuUjNPTT|ya7M1k^U41C{1&TpZ3iBJ-;V>w>l#`{MB#N=mry+0gzNpUo}J>CIxXThi4-n$~m~XNW!H$_Q-a z7U8Yw(ynvSoW7k4EL%-x$cwzNsWwEjtkbe9eKVmgo#|TyI?}fqwB_`-6^gc+|EPN4 zr>D?;P`Xk+xidmj)m|vNCAC|?+-&U}_=>@@6Op7tu^>twB6*P1ArTS_1zL_51JEACAthAJ=JZ3xMQi#INt-O4v9`m%S@NoO^8vaz_MUgOHK*?&oQNM0 zYf-y%O7Pr%jYHgS<-3x@R868qQQD5 zvNMkVyu+p1#as2d{YKP6#-(Ub(}t$gw&hQ)ZR!#W$Z9EwKLg)J_T+bATIP;;(R*9U z>bCf)B%3$GX+Ah;oa?gm;y5aVGa*iDu{V7!*WUA~UIv!+UlqYA7X7eJbNx5L zkHPl9FTW1iSn-S#Q1FW7+9FhozHChZA+OH$C|5beqQ;A#4@g(&yP=6Ro7VDROtx} z8#>U9j2Xh;ZxWk{S6N4mf4GKmq@e=wPgn0bNz_wxp2y90w9S=m&VkIRtO#rbiEAB!k-uaV2v2j1w2=yAjh-6 zxq965>;IScHIAVaX?eo-HxGtRZ}S-xnbX_MnZfC8 zi<@@hZHRwJ)&&18@gh;8*o7=fHT?juftkm|{P6!u?3fZH&nV$1|Gu~)R>pS0-WE6q zRkWX~ic5}kQd$<>q62fIQ20_*jZ(e&*1N2asRC-b%UmE+kFdt{7kt&hd~x1fi!;w* zifn4>?n376Vf$Z#>sWz_zI2<)(y#y-K{$(K`)dLA66L-M~u<)5hn6pV(`W%rM2y_&jY*e%0sx5|Ir9TDqeggBb3}Y>*4kFsX zA%`9zDa?9W;w0ZLK$FvT@_A?Nq%FDdBy+D~?&LGB*=_N=xy%U87pWWRa$fc4L`Y3~ z7RxiV60Wv}`?a_i{3qMk#Td5!Cj&_)VN-kR|4BNsvCT`xs^*hv?sM86aC3$2_7Pd8 zU-mIPqDjkT?~&t{el10mobeAP)M>}AGNQr4WkkAI4*espy<+j2zc_VT zaZ1C4{T|b()0*Ct(0A&5EybxV)lT#6j#(OOQ7^4$P0ZLHA)n8aPZ>IWR4etqpAXrk za^BBAlj^?x9%az-S-VZrPmvZs-vWK<*Wyj=SFsk_l3_+rAQ70Xb?B-Gv2v;bLSLR% zjO?;!U|B$d6C|~!2|7q^9mgjeIQEOp$r%SFs^3UF>-USTz;I^MzIYb8GLkp&Aw@a6 zAk(ygmf5r=6ia%rykw8*=gE=d9{(O9pY7t2X*I=*BKx$#=hZO2wJQn18KoLCyB75BI7{gRRKiRO~H&K;!u( z23n>jl&NKRufPbzXbpe&(QBZU^z{pohpGXg&+7v3y9CbnmG6MdQh_mX}ZDkp49n^Sp95&Cr?)jCXCE@=#I^e0p%0L1gmf z2Ujl&>1-^wq9kwlI>`z=Yz%!~AKZ`fTkIK`JYeF$rwxJj%vtW>+rw+VlYIGK)_hw| zddT<}`;@7h-|r$t)PA4K&+@qQ8=dNQ@mv`KEMxh6qK8ijv(2gO6vR!^ic*)qQD-n! zr*rcUh{_!;b5qr~iYH3rws;6P(2|?tUnHZ2HL08ryn}{e;)*omIS7|G62rtf&Xze@ zU@{MSZX{V#*n8`gb0^AIg8>u}Bhii_`x?@-Lqm`xyKI z$$F}hb(&UZ%U*ST1O5|}kLJ>e47^`OcRIG8T^4UZD>r1Moek`^=`=$1R0*YJ@o}9I8J?A2Kr=xI5%snN*Z!o(;7{J$M*LgyEZ_rBI%~E`{eF(a^Cr6>mrt!_(ONQ?nZ-=qjDT@q<*40aU#H*|P7d z>M?|dT+0@wI$SmxMM@;_8;?@xx4Uno;Af}ONLXMj4clM zcb%WWwSQ0jn<1$YVd`rD#>baPP2d5ZT1_Q6i&b)7+@_Kfx?gx3aZ5>U1*yo!dhwGK zvnIK?Sg}1|uKmxWva+l~XB$IpS73df#b651 z<$urL6L-|kX|VDk&ULp2*3S@dPTW!cb4EhO3w%-DFZ*-5C%w&ozBwuA;5 z%LUQmmvC<|>dOH6c)g5POMB(3tbIrGFcn@x%DHQ{sBD;Kwk`j2Y)$3~lssd(0ZlF8 z+tc#BCF7(aL=IeYz4`pqC0bP>17{n4HR-8Gza|eMD$>2m1daYs&3A6Wde=YuzcjUk zHuGGLLe!2I$t&Y8&|J1OtH*jWOqWUQLj``#fM+?F|BOtzd5sUKy6 zG%?Pgy)VO4nRX3)UiA=$?H%-G90H;-4o<`T(^@u);iAO&js88CaY7vS3`O$;TB91D zL)x+;!LO+J1Wl{-0VE=gf_C~h3$MHcSdw0*9<{$l=!UoMoZfa%wPw@Wc0DRUXqvem z&?r)wL$wr-H0_Ztd&WrI^HYcR=ijH2PcriFE3H4=R#fVLlfFypFuAT7h?CKEQ3*NU z^cGQ2E_XRdD8;oVzwOa7PaIxi5Fj6uUi9F6-lOu=eLhp%~ z-#K|bjWG;G&4@r1H^X9{`ts;(@eAM)Rm|LQQOYCWxjeO&C)Yeza}Bgn_@Ws(zMKU9 ziHJBZS9G~k+a|gcfli*}!+(&g2DvKh!?sRvhXf+niw_Tqo!{6(y+s?l6e|op?D7KKn9_E)tG5?N4ZWj^}-gzai!e=WQc~sKr!M63KyCTzMcJ zBJi=3Ph;_F)-?eYn^s8TGuj@l;56r8OPI;WndMNFgn_4*kh`LiKnRN+(pI+JQ{EUC zY%m`bnl&X;y4XIp=_j*hU6&i@ z?XQ;vP&e6?;7F-zWw^wwT%?AkM~Ok;l9PyNc&t>h4BQJP1}~@QhtZ)U+D3?$ z^g&+nSXuIh&q%d0^6Wol7QTO=Wl_S^o^_vZYc}idH&qo5eSd+`ZM<1sOVJl*VpLnc zPe3K5zEb4czycXutVr1KR`R`fa*tLXF=iSo*mzTt+$`g!%0Ln$kr9 z^q{9#%>D$<{Qae()qAQNrHzuk6HBOW>fN~3yAxbu5Xyr(Q%ZGMGC&qPRDg8L1NEIP zb9^lE+`E@JRWtN+VQSm*RRRBy8Ijqa6O*(}h-e(XQP&y0za<6z%wKKv#Io4m*1Spa zF-{m*u}JEJ7vtuA+B>I;O|>lY(afg#{~mX^E&gjK{>Vo&+OmG;KN`~iney|UBYghs zZE3CPp301kKcug0+M?9tf<5?^$050l=*#J{s*^Xk-$$vm|I>`Fpl*`v)05S`U@ws{ z)=S9BLxrCa%olmznQo>*bwZ+ZvZ&5d5M8iA6`k|R>;n<{7WI}ko9dltTo~$n^(bda z>Z;pVOptWLJqL~3sivxlEWy9c6-CcViqdV=uvfYq(458XcBvh zaVuUGV_B*``Z1V@8t;sw*ULUb%A;+k6v9#ZQ9Zo;0{fq7h1NfNJ0GMY>s#36!N)-T z1uU$nPl1{*v6x4QTu37(ODbLA&r>+>De%byHt$mSoDMYhMCCq=DY&X4+`nE&%4c=8 zHSl>p9;r0_ZK!3|0i_UF$5!gk6G^nCa`+@!H`hbpYubl^mh(cERVIiW5n?QzC?SCl z6Ilv5U_3AgJ35oeI4_~7ClW793N6})z|zw_r*hzaV&;hr@Q%Rr`n7d~@% zRcDXvjxE?pW59PPlP4yzWj48aM4FKTNG5u+LD^?muzgy=-sEPP+>%`Ot|Z@k1=s3R zNa_=3ERp(q4)#qQYWOEMLPJ-ucZzI^`@Y#ZRqj9%EnnXm(#Ub%CCz!|ZW%8@yPw9c zU^hP0j~D03(Uu4N@55X`53;zagzgPvY7w!eP5pFjG=VH(Oyt8hvMi9rX4IymaZP=3 zFTa1*(1z#ldaI?rM`ptXJ@I_h$-hx+)b;wUq`PI^F8`4K-Dd`P8}FjHA?5@{CH|ok z>vsCtFk9qnE9etTl+GUwXf5;*c1;?XAC=Gw%JPM?pikOolKetTk&o;=Gii^1k(ZPg z(I3kwdU3%H@fM$a=$ni_p(wk)Ml|V5WdrX`Q}ijv88GZOXIA^-_(ZS2$6h2;vjpiK z1H+FqWJDzi$UrHKX?bNmk|eI@4C#x7$PUpomV@41`7mZVwP1T)B5_K{(Ra{b6JH*{Fm(&#OG7dSdrzDsBozkcd zx0MZtkObcorU9(mar6#pRcGzp@cf;Q{RLg3;-d!*qDM@k+jbmX0MS4K{{#Jr@%#%9 zo_}$&7p+~```T}bu|~CR^iX5p-!&@eSj+Zplf~SpUliZgqS`jv5Gr%vAuvsftco$k z3M^q#p4_RnjpZY%whDHrRxW(2{sf~vk_OLw*eLB}n6!|M`Yln?zOD`_p2N2(q)Ail zlWcqBv~fAiFCdb}6VE{M&QrZIg=LB($Vi%Tn%f+n*h&L8CJcJn@u(hRLmOCZJ-rxs zj3rvWsKUuD(j7`XhM0f|IueOGm=e_u>=La<8X=__@~|~>ox^D4geLmjQ}y(mDy9x^ zk#i3M=aWmb$M>UYVP`mx-D{rL@_XtA?|-n}Pwau8uY{2m^?2R@Q9X|3sPweODMZ{$dSEn|(bgUmTI zM0Ig#ODTUAt3qEbGv*l~x|OP>R%AlXby33xGT+Zf6a@JMl;Vg29$q1LE7VZm6Yx zxc>5~@2o!4f71W%u}^GxzTTmlmnpBDs2^m{M!_&w@3a&Qop{IJGv$?|y+noQ)Plj) zv{6GX3x zh`GO|eh|X_1%oc`{qId$H+b+3|DLbT8a((W3p5J`4)&c@Kj1IuMGCQOdd7eF;NSi4 z9ekau1;Z^1hDe1_p2g<@hYr4upa0zxFdRNn**o=J|9=0=YtEWR>`7DKtv}oUvVZ?& z>v}JoH2~M7lNY@7)mi-q2Z#&0p@V(goweV868Y~ot?Se3CY(5;G=LdYxN%s zYIPU_G{SOSLH~*4&>UBaeGx58s~=i@HreqXILiANDD^OUXsRE$sQ#j9r1ik6gsCTz zH-48O^yfctSwZiG>y8}#n%s*fhg~XUa8d#4LT3lx*!1$jx6v2MUN?AFeZPMnMRxFS zn_d=`4fx;juR{SX1$_r!|LUw^@epNlCwY1Q1oXc@Q8_sEeg8f~nL{Y^eWlEOm(>qm zIIACNlZGz%Z3}9DpD(MS&|#R7a`0{c`zX&P$|FtYZ$|F?`8O7p{T@ zolCr2t1DNoTDD@jE8~jES*~TPTq`TTT)%8(WyK`;ZeDTQ<@L+6R#jFmzx<}9t5#iZ z3Q1Quqp=gld} zEh!iu?ZP?U1+zXB?TrPq7mDobydRuHNN=1yC%<4C^y8-<4{fe*oOTwpo$={I%6L5S z3*8mt$rE%}j)Shyn>)Km74Qe^$ve)x&nsA1FmJ~A@?AKuz@+}*_NP3yv`^ReanXe|p6^P5%u_e4Za1s;2!oFyq_b z`qnj9UU?-n8vdGx^yCs}j@I}@LHUgDeGFb&$UF9G+BU+rb>08;;VZSqpXLqD-F-ED zPtW{%h4A1!o=Ii*NqVojZ%;k(2Yy4>7*|6Q2frbY0fB}ROW3(a`* zJ%<0;X87k#|11+HdzubBf1CTpz0=L~c4_LDZic6rsA-?N`^omf+vCjmXL}~9-`A#Z zua%4qP2c^g4aes0{=1ppKbUlVc}70|IsNUalCQ&tzvn(vuFJFUrIo+^!J0Ks{Yi#u z`rA(%={aQbYmJ)uQ^6Q&$bInI^lJ=+nMmuP1)cX_r}R2pJ8mzoA2;~^DLozBGIC1q zJatNM#mrf^wJUFAxxDz9?6!lI?imTOfrmM*VYv#g@7TC19?Rn6C`W-VJje@$g&Emup| znpY*&D=Sx3uc)a|aV%S*Rpr*z8Btc&R4!dbbR|ny-cnhIkosi;`IR+GZGGRl%B!!NQ)MWp zYTk+!x6NO62fq1BZzIEtlpbnk5x-XDTUK{-_5A8(Rpe%V>>mxhbS z4RRFCAzUYJJFXemj*PNz5{}#c0Q9)w`-vAN z`IZ^J(UzO!XtK{qa@&4)E_rbThU{v21n?K9mZp|+`VZ}jn6^-hjo@uH!iqxiXWBJwSMjKx5nGp;Hr+aY$x{vd+h>mIq4v>;-!}Zzt8~_B zO0zv^EmL&T1;6Wyqk13LF?5n<+Y_5#qmp&OKNOok-PUc*FZSVqzxLWuox$mteXJR) zGv$PDBRrP5ADm2>5T6=;my19g0bln4g`NFY&P5k=ttHDpM<)_MD;>T~Q zc%c7#q+Q-9?Q&E6if1X-ec14Rqd!aMIH?9`^G#am@7ya58_&ispYRUCH=E%WZM?^} zIw>VDqJ>#c zL8}&W(Ek|ix-eSN?{;WApFrM5`lY8og(lD7lUo`m*tlXjyGvPx`}+=>nd2v1l%s#lre7B=d( z&5qWgq%Hky>;vBOgqNTAW#e}Ze$w>FF9+wvFAKj1V)u`3`)cd4hVZw-zlBW*>EZl& zA!DU9`x(~!qOWfFn;BQn;9B%GW>d?Kc z+3$#pRvzSTTm}3NHo3`%twPFCwKXyr{b7WiiGH`jvlX71!oyGeI`BJ$A7-n5lJ+kA zdhlx&AC>3AB==os8wH=6c)fWw12WBp8{)!!!>C@)wa}}vI|Z)>?|4Z(DGa)5prLzF zKk>`JuNuEVJ0xv*4t{k3Kg?}D6-)d}@Nd9h^vt}$b+hSTgZ~!%U8etarhha3?G|#{ z@!xLYzYG742sx6*Zv1xz=((4)^x@ZqUuZugv?uXDfWKVJFAe8l)oU+)pB0aQZp^W+ zgl7_dC`NcD;a9gHWs}b38P@0nN zPDu~^WJUeNuLr*#`~o&2e*O5#p6r018^4qI9l-Bq;Uuq-ZQra2n^gH{P!nH1s!uj~ znrI3jl%oDd{?Z-vRut<~m%b%fiwnw8PN$ zLMzXO!f9`aqID7B5VV20e9)#{H$~BUp^d+JRR3a>+|^OEYoX16_6tGU0gnv+(ZIGY z!=i9lMUb@k;MXd~bfDVTwMO&mCa9KhH{p4v{0KX}EyCnfJFy)eFFcbh#>D0tg3rFt zs$a}Y%p#tC_;YyUX|`#H5pl|tH*BC&WZGF81I&_J!pG8X{L1mWT++`E)oS_pHAK*r z;l%Hhw$)+qo7UTI%R#vrdH0RP&8~ssesT zO?bbs7Qa;d0&`-io2~ez;J4C@C)7@DHK8MMbPr7@^cB#@$DTvi+IQP5E34Sc2>e+b z10ZUZpQORbgvX6vn|P4dur%Bgo(8cW5A>U%?=!awR=$DIaCHl6&y z%29m^*D}V#jN=Oui?A3&kEMhsa3st15*}eQwt}-m7S{?Br5)G=eKz#@CVj9jxoXF9 zLYS1>E@;c3bqFm#@jHNDDSipc2U%b*ekJ$~h#zS%W!i2z+pLT9v*m&7qQu#zui{NT zpY+#_>aUr+QDtMRgfncx7Hc==Z6)w_!dq_g2J@0?^M+<7i||HhhoHSDlGbIrDWue{ zP0SzTOoetge8u&ny5!Ty+e$UB6&pT8SPfy{FvCn6rj%@75}D@Au`rO{cm(!Be@9T3 zIUaM{s>Wh9^5%xty_#nTk+d$GCz7@d+6rhTO(FW1ab75?n(JNdQ4Df3^0S1 zj2N+%UC=f_`$4uMw0+QSgZ7_Xho!-7do@(B&^j)l{aa(TesyEWXw$H_Y-l$@8yJI0 zefHwljNgT^>y!txiEa$A9MNYh{1t1N%f;^JJ@(hE>SS?Zg@xE+3Rv>hkKA^)%0|zN zzZ9whW%tfcFkgc9PwW#j7b zYsJqi9uaMWIi7LXMMt4{cfz|3-rIt_j2pwBr?_o%qnSm&gYX`L_wv~Ng~wK6p~!+n z+XB4l!ow=OOsajz&1Z7iap$Q1i(s0lKapu-YGd(;=gw$P+AQR3MP}+O?Qv#ugBJb$M!;W zZly12=3h?J*!W(J>#j4#XcE4if8NuC?+s0(mqI_&$weXgD zC315<$@rmpRDUtHT%WzlN|$*uI8*ji7}68UgUB4@Zb5DbAEj6pl&jVlL)XE4wx=x; zMvGnp{~`E$`S8T|W7+wVx^bSqgj6~ZB3vc49CcgYnG1lgp^W0eR z%}FY^F*c2gtvGR!g>PP>RJO>JVZd3$wUfAz0u2vM_O0NQ*6P-~fEt z@a;1Bl#SVLm*p{5FA5WHGA`7dA>|_G63_~t#Gz;xj@e@t;k|^%S|=(Ye30;qL-~DU z{B?wn#0XdAPq>2*&MkrGmt4CYb>w5&YuUXYYP zsmE)@gl~m5`|GSFo9)y+vd(TkpTV5Un6g3}9LwY-+LIaRhxrA^WBtf#-NH`!uy`?l z6>m{6Ua8a0Pt!(1>onuF)ZN_{_DKqSQY4X`1eIFqWHoYkJTR(16uV5Rk~0txxeuTy zk@2!seTY#@C==p4LVQQQHL5=mE53P2+a8LuY~GaKWNejoG40$#qxvIUOFamk3(4~l z=8$3Q2Ki_*tOP^`t^zro$N|RclUW}mo@N5N3IB^39v+WJX0GFkryDtS|6{!$MC#Qb z;oAw9ud&1!clap8Xk9}t`N;eX_WK>{d`P|X65dbvHm*bD|J(IW(!33s?rn_SVyD?- zJ7i%tw3kxn`r!9`cT`_urYTrI-7MZl)K5n``WpwWq$?ZR9njXrb7MV*E4R<5N=Dgp zVWO1zTKETk5Zks^Q07#nUYF87bheb!{j#2&Fb|e0%d7|`v`4(y@NL*$S5sjdQ zFJ&n@?;x)HM@IF>!_yzSm#EzKzC~Ot=;gyd2>;%WQT-s-qN~Vy_MLIov#d)QZ~er& z9!NbYA-sn0tIT**nS}2DBD^&QzZ0G1a04SSJ+r#K}bcAdYtlKq#wS(oYA68Gi|>YoVO%NL{PB?A_5GQf4gpGF1C z|JkU%h-=ZgsXyC%bD>1W{T^rKl03`!(m9F#AO6E;n!@Xd%eFkCj>x>q312aM zTOS+SlOeh(!*4r&%PrDkD+^r%D@tTh#*t_4{F8KSh4%=&w+DGy01BN`+Lk{XUgE}F zzXv|o<70amL(5}r$Xo+8X(P~PLEC7?A@$TL%TB7zEWntJ@tBlV27}#A(B2-atmY(T z+Xm5VWYfuf)M`*EWz~SpUBBeHcx;(I`wy(2tBZa+;m`WjsQ#dtelxGCJvY}X+_t-- z?L^A!B)nVUmG(-0;^(-G^1{!pe2hNdgn)GG6o$-b1)^0yor=P<@+g z8Rho%)?;;h$r%=gXsqpSMee39_6AE@lw6B-4qtTMBu$6l?S%I<;~bAIuwE~Q7ua%2 zH}{xDisX5a2f3M<$bN=BxVAu=qUvkkZ2R}DGONavVn?;e*!C>@nYoUkFSqq0(KXST zMTF#cFER&_>4}xDIY~bI_14LgOeT7I zqgEoKYdtbcaplPMJwLWC6xp6K+zA`jbv3d(k=>8%2TwQlYO~0- z5*gJ}6(rVM&|>^q#FfDV&(s$`+`5C$XY@p;XcA+jg__$UQ77J zq5S6DNy@E@@J7PVjjaQZy;a8HktJ6gYpAJgKb1zXxMx(K6&mkqW5z6b$tHX);Y6?U zH8!@oE@U)ijD0GgZGg5lw#|C%msrge@)N1r+IIN6U*UCm#_>iyn(?tS^6s&3jBh%_ zK4?4p+1!1(`*WY;&4oN;{R8^U-;e5Vn`yJMW!r9xvX&)?C_Nc-hYTKc9YE%R*fQO+ zm=!sDpOI*_plqzuG$1qo$f$lQD3dAKJ@(M~NV)BY7DDq9YolW_(%FN|A!Kd~%8Y2E zWy6`(dcusv+oL;gV@#2L1?BjM4}Rt&^~48lEwl}0S%=qmk8Fero6FPGsy2KRe7pa5 zR6lV#8@b)ej$PneCs;)@m)^n5- zQexYS$9BNN24mC}$y*6B8{YhA+a#*A)`8sox0q|2X*F$&`qC6H>rv~%mkiXrsSlo= z@GOnNGc(*A)jT`p^Nc6p8HioBKKt_6Wl#ct``hf-uqp$K_Np2BntzPyx5SRmW53KQ zzCz0eOUmE~GB*v6>N`(YpQc&Wr=LcRuOJPFVL> zIRw=b?j-z6vC~y+q?I1jh@QXvk&9Q*!wwv&L!cV(TEW^r< z4Ba}IRAt$8eX*6@E)Lagq0(&*^c8$`?9XO;Ec@9HsoTxS975(tsaqMZ3?R2SLD%cd zw2qBeYz$Z!8>u~~Mn8};mHG?qe@D?)MU8Dd(C&n`?{sxH&r0Wo%AOnH_noclKeN*L z+R*m8Na=hh^nD-G^$Dkm&-NP&d$w*WRNosT zPF*iG^{B?ayl0~t3;d*98liDb)W_B5c0ijB?cZXj(`Wx5D_t9X;~@NpKCbJJTIsqy z)V_^zWZE?PvhzPW`lyPmajx{3@cbXpDH>GTHsiFUB z;&EP0eIz_FXd_WN^4Tk_>O!pfl(p)l{2GXB_*1(6)nHs9<(Cm&_r*3kpfBNMQW*=0 z?Tpz*S(t732tERBDYQQ^X)Sc;<}pdsd?lYPanZi$1UZ@4Fg`}+{@5}-wixqmtMX9w zADM2>)m>rAl=qg5cL8i+o5X0owGL?Op#6+l|AVw1dp)&2_%w^{I-AGtjJ3T1c&jhb zgYV3V4o5^DeoM``Bgd1GV?#-UdphksJZ&aVlwR|bQf-aV8kD@&z#D(5uHR_#j+LM7 z+R*e$JX@j7hW3AA#WN?#W7}vQkDS=i4)1-zczAYhy!U>4Xgp2{_u&3ZH{OHglIo$Q z;Fp8nd9ms<&;RZ5R_(0O&XmBP#y3De>NSZDhA4hZD%*(DVL3}FF6Tq zDzu%k`x1}+Qmb*O(U)ZBQbwQSfIX{msKpq+8v2t{I8{aCN7|$8M#}R;tVyIHrW2W4 z_(qadUn1eXgl{MOVlz&quaNQL2;sX3&x$)unqIYRB-CE%oEh-*eW$T!0wL{}C$#@5 zQvFX2^zon9_3xf0K4Z=t*#Q;A?0{rEz8AS=eD3{p`!1_2vcaQ?$1S|ozF5&;S{~z# zFIekWbe=`3cE?V|e~WUJdkzvSXJ=E8+cwYe9KYeUHcXJ&P2xMk#$)H~ibD z>iQRL+{Ci6zrY`<-dIyUTQ0_011-<4OU!5O>HXhm&LD^CI^~Kmzsoo{bWMa0LZ(gtj z&qOQ9Rn5i%vA=x$d-2~8TW+m=lHEe_vDdC7TXM=*N|CO=A@Nb3;cIDb+s~uc(%2(G z*#)CXsFPR>HFh_naoLv20b^rX#{XhqZv9O@`?9rBK}(eRe`I^z(FG z4#(bwO@4Ga8uQ9s$ZX&fOJ$+DvlWER zD~~|48=CQ~<;KsXen8t5JMTW*YZhr_&w%JUAO4($x_&aqAEN87P+c4Spq%9ADAo1c zAbnIjR0czK&e?$k3|7x_#7BKkq@>E`jp z(42&3Jo>JKb_7~q>~#8U$1PICo71B2UGO`u)Ad`eY`Z3W9xv^4KlI)kbbWTPor%`B z{f}0*9b4ftAIiCwvM>MW+6@;nHzTtLnWxkBE@&K_+B_az_d)A~_Nv&r_SpUuTh}fx z{5R=(f|ahbqIK|LoC*Ec0<4R){nj~bk4^9Y8WG#II2&6-OEG8=BQUUSJHo@T<^370u}*jUmPy{@qn+HKJOBzF2f)Vf9{a^mM;3&{Mh zVA+M}eki*A&Jy|+y8cA4tfJZzpM8;4dlGvdBjdeR!R-t8Jn`w>?rM=7KUj;Om#?H6L_MSx##g<>IzTAn- zMr3+c>H0+yFF#rP*n*!IznJ}4ep0&ac=V9L4Q~&;t~y=6TZBc8nO*Ef3w!*mxgd+5 zi+#fL1v6jL4mjuMgfH zcu&Q$zd1>@_U~HtOU5%n7fRXOtm}pG2vg|}X&ZkM+W#B-8hp_2+@$O0$JQT}Wsy~c zykz!Jv;v4$>h%ufu5HnS=NyI4gBhdajSTEFGoUpz1 z_J=I1spcWBV)#qjbba0gZmi3f^Zaf()1qd{78q5xT9Hw=g|!bWU0)QcYh%vV34PYL zbp4vxW$Ups*Navv4+AZlX_-jSd}=8RS^IkM1D-LyV38AfNh50RZLC35BlEY&ygR60 z?5I%oaB(77VEYzvOSx@<_L7Hm{px7iDWSCK&~`zq4V=`?pj2As#DvkDbzs@oNBGKV~f$9OAxX@RaTbyTNME z@zyDQ6PO9^0CT`j&N2z}BHt`Y>4bE@xLi!aZ05c7u(e z;~$)J4W@xz;2@}V==#Voa>2~w(1AJN7V!rUfxRbA=_x-!&Pn8fY3~s)=mocctzZ|} z3HE^_pyQ{6bJlh?*bY{J9pGB96Koa#QSt?P?Yx8WDEa}jz)r9n906Oww0O=00ljCA z>iu91coJ*?9Xp{1vq8s%QN0vw2e*LT;4W|wJRso-oOKMQfkU7djQ<(>0#m^TFcWMC zJzzIj4yK(&IwTz24Gx0CpyO=zWB;7=fcaoqBIiPZ9pFx|7wiQcj!}ICYyh)=q3d4< zyAu#9TWI z&KuQxKshJ9U;M$7U@z$SCG_XR2R4A^U^`d`c7vP1vQ+d0j)2bH&|QE&!49w%Y`>87 z$vxN$4uT24!d}y`7qA8_2Rp%5a0J{f;h!AUkAP+1Nw5`6|26cV;(Tkc6Kn<@7eNo^ zd>T5i^2ztRSU@O=Kc7uK32skX^>DYBA^p{W$VEd)S zBbb3cpF}R04Yp3Ae8CQ|73>7JfjOT=ub}sH=;bN$0j7h4U;tR;_kz8kwio_9$^+~MJHXxo?Eg9Via28v>@CK=LB~w=4d#GHz#8x**!o4vV;}kQ zj_NzW?pfpyY?zDO{qUC%ADFX%dJB$#83)kM!cn~#ECZ{-R&W#83GM*XI8$;!?!lbr zNe@^8mR*Ov$UWErw%$NGz_c65_Y25f%05=Go3pnD!PaW*?>EH147&hpz^!1}m#{Ce z1Jt_Vuc2OnUa%Y-1b2Zs%h5mB4!T|>{h$|YScQFonRT=qU@NG-g#6W{6LfGMM;F-r z75sloJPqU*>;bo40~`R;zKI@xNBFmB55R8l2 z8|(o)MxpyFd^+s_m=nkTKtY?X$G<_o!E~_o4A$Skw6mBifnIPB905IlL*CiCz6H!l zBpj^y7-3*5=p5i0%m-VObiENA1UuwDnK3z-=G66+qws+lVCzI(uLe6(kOz){ePHIf z=;TfK&lg>hzBC+I^GRLr0o%bLup4w9gZ3iU!ogM-@q#%Qv!@Fz`wVMhgZP6!u5&16zu*ydIUSKVm>ea zUqFv;+TbMGwWKL-32bz6l(>mi&MtUe*f#0skx_g(1rLCZg{(h=-bL(f_$M-!=z4`<8EFP{u1D|3;RoGdH&_OimE#9`Z^928xfy+& z04sRL3FcJl`c|+8+zX~vk&lzmSL=E)==c)l0*-(KVA-wEyhpx457=9S{edIk4$!e& z*ZaYCF!g=HR}cr7_GR=2=B(27U0^$S1ndUm|3!Z5u~We{(1G1+abWN5q;~|l>j)FP zQ`dKc-Qcj`dh~G$`5Vy(nBzwuU^mDVMIQmvM)7MQ?O@tB$Peh)irs?VZ)5kmuFroE z`QY!`$p;viWBmvJqk;cu;6EDpj|Tpuf&XaWKN|S|RRdi-%p5WwXu4gowcufO+K1cx z8E7uyInAZufAKt&{VG28^0;xQ`!zzl8CTAtdF>=9C&Pmie$VGVn19=6c~*m~y^Q#H zxVIUeF5GzIck*DxjdNbfGgq*S_s@oK9hTo2($V*bIJb<_<8u=mq%VeKE4?Ixrzy+3_PIxWG~xh+)iAN={IDeK@tAHmWSy> zIN^8lU?r4)n>?q+34hlIlyg9;6S~cko^jeoAM$&6-mB8j^U_+b<#}=-{cf%$e&6+h z7{YPrR>Eq`^sfw0e~+Y_FqQtL&{ZJ6l04mv{2Opp#Erk3>++j4O&-sr+-TEm;7*>w zoDXjO1b*N|({-JrY5ZwNc!u_IFagK3XT>q_Ok4_lJfc!(wVWaM(47sQdlt{|!AvLL zF$538DEOL*e>d^CiKAc=;S=B^30mJ0n|im^!Sw~WLGCXEAyaVy+NW?57t<{DDL(Q0 zFhAc>gSzHs8{ZeOX%)C?ocwlvkN1GCH?HNrDoxW?<2K?Rz&(t69Jdd5821M5IPT0( zYT9|YOL14>3ULc@Rk+o-jkpJJ591!k?ZX|$y@5N9JCjVEhr1Ma6|NAs5Lbm;joXNO z0QWHNaoj%KVcZ+In?KKXp7UzM+ngsE&pntAqtN{SInvj>mO%B_pvx_h!;G!aedK- zTSaCLANI{LWNOoeuJ+tGt>^qWt@fNa&Be9+UhK~4;ych!4$jSf3fgOg&T|oQemYKb zrp0MppNiAgJayM}aR$9tq0qTGgx<#oF5PVI>EQ#1&MENmVu|U#92P&s zM#7yqQ_j=h{?-Lg6DN7@@^C_i(o^kBc;#c5h46DN;Sz^)9(kLO{{m#rC7#7xm*TGD zdJ*y81m6wFuOc0wv-E=LReZ}@cz51PUT?$ku?08R>YLa~zwax(xmTgDI^?WD9@qS) zmr{vcUqQ|~++F1Vj$pdw+sIFmE+xBXJ#jY?z7hFc3-6ELxq`T>RJiY}gtZ|1Uh?mc z)8xC^E6%Y`lXN-xC{)iD!XF^rUlU#_ccUzKeha;Qo3M7|axHQtP0k(2`4R3Bcz&q- zO+ICF@QVyh6ZwrlkJCJllfIv#yPpN*6G-DE?UT@Wo+6(8gm)uP4$~^i%lmIvM$zmA zlU!Movo&cOY3dZ>solc&d0kT`Pnm+BHhER`s=AeROK;L9SKPjQ)$O+#ShrG}T)lKv zwKjQWWsQUw7qvBY+T^;*wftYXqGD;?Qf+c&^^H|4m-3n2;MI-Q6>wMaA>JF8u3X92 zeJ9H|c>~wNrG&0rp`u!P+p?Rr$+xUPB>yI>7!1ibty-l`=ELf@@f~7q^70jRm6LB- zUJq4G#phO6u3WWj#d68PxPH=ah_m6O9}y>=irmYk=!ot^^*hpjC_4HV>0_jS3H*ds ze$qckA0%|r?}*#NO(0z4iTgB8*o98|H*wOxh0;kmG7M96GeGGV#YsOYbkg^UETNl> z3;6ly1H`Gl5BSSZ@*uQV;sSIs9u>C_TMGPyPJX;juIMCvn_t0>a3j*unZE#CF89JM zbgi$(DK{W{FU+6BDZguR0lK;@n(eHjmlSLn3sNaeLQZCDa({#+*B35q_2PWs&8SrEY(AQgEc{~laG z-tZ03v3cBuU*H#rw-t{7os4f%=Ge6U01+6VyFY|ZDuf376mh E0opfv^#A|> literal 0 HcmV?d00001 From 1a3cc25d6c375784f1a285c56d9367ba89cb551a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 19:40:33 +0900 Subject: [PATCH 1638/5608] Update in accordance with visual studio changes Adds x86 emulator deployment target --- osu.Android/Properties/AndroidManifest.xml | 14 +++++++------- osu.Android/osu.Android.csproj | 1 + .../osu.Game.Rulesets.Catch.Tests.Android.csproj | 1 + .../osu.Game.Rulesets.Mania.Tests.Android.csproj | 1 + .../osu.Game.Rulesets.Osu.Tests.Android.csproj | 1 + .../osu.Game.Rulesets.Taiko.Tests.Android.csproj | 1 + .../osu.Game.Tests.Android.csproj | 1 + 7 files changed, 13 insertions(+), 7 deletions(-) diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index 6f77560e01..edbf651d09 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -1,10 +1,10 @@  - - - - - - - + + + + + + + \ No newline at end of file diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 6a859742ee..f56d38ac5c 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -12,6 +12,7 @@ osu.Android osu.Android Properties\AndroidManifest.xml + armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj index ed746921be..88b420ffad 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj +++ b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj @@ -12,6 +12,7 @@ osu.Game.Rulesets.Catch.Tests osu.Game.Rulesets.Catch.Tests.Android Properties\AndroidManifest.xml + armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj index b366958342..0e557cb260 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj +++ b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj @@ -12,6 +12,7 @@ osu.Game.Rulesets.Mania.Tests osu.Game.Rulesets.Mania.Tests.Android Properties\AndroidManifest.xml + armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj index a40f7ca588..dcf1573522 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj +++ b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj @@ -12,6 +12,7 @@ osu.Game.Rulesets.Osu.Tests osu.Game.Rulesets.Osu.Tests.Android Properties\AndroidManifest.xml + armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj index bc7b00ffc8..392442b713 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj @@ -12,6 +12,7 @@ osu.Game.Rulesets.Taiko.Tests osu.Game.Rulesets.Taiko.Tests.Android Properties\AndroidManifest.xml + armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj index 4e83234e7d..c2dd194e09 100644 --- a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj +++ b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj @@ -12,6 +12,7 @@ osu.Game.Tests osu.Game.Tests.Android Properties\AndroidManifest.xml + armeabi-v7a;x86;arm64-v8a From eaa19d5a49faf44645e824ca48c62651249621d2 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 2 Jul 2019 16:13:47 +0530 Subject: [PATCH 1639/5608] Remove unused/unnecessary fields --- osu.Game/Overlays/Direct/DownloadButton.cs | 10 +--------- osu.Game/Screens/Play/ReplayDownloadButton.cs | 7 ++----- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 9aec7bcd0c..6bac07fc88 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -3,8 +3,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -18,11 +16,7 @@ namespace osu.Game.Overlays.Direct protected bool DownloadEnabled => button.Enabled.Value; private readonly bool noVideo; - private readonly SpriteIcon icon; - private readonly SpriteIcon checkmark; - private readonly Box background; - private OsuColour colours; private readonly ShakeContainer shakeContainer; private readonly OsuDownloadButton button; @@ -50,10 +44,8 @@ namespace osu.Game.Overlays.Direct } [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, OsuGame game, BeatmapManager beatmaps) + private void load(OsuGame game, BeatmapManager beatmaps) { - this.colours = colours; - if (BeatmapSet.Value.OnlineInfo.Availability?.DownloadDisabled ?? false) { button.Enabled.Value = false; diff --git a/osu.Game/Screens/Play/ReplayDownloadButton.cs b/osu.Game/Screens/Play/ReplayDownloadButton.cs index 9655bde36a..5acf4e83d9 100644 --- a/osu.Game/Screens/Play/ReplayDownloadButton.cs +++ b/osu.Game/Screens/Play/ReplayDownloadButton.cs @@ -13,9 +13,6 @@ namespace osu.Game.Screens.Play { public class ReplayDownloadButton : DownloadTrackingComposite { - [Resolved] - private ScoreManager scores { get; set; } - private OsuDownloadButton button; private ShakeContainer shakeContainer; @@ -39,7 +36,7 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader(true)] - private void load(OsuGame game) + private void load(OsuGame game, ScoreManager scores) { InternalChild = shakeContainer = new ShakeContainer { @@ -69,7 +66,7 @@ namespace osu.Game.Screens.Play } }; - State.BindValueChanged((state) => + State.BindValueChanged(state => { button.State.Value = state.NewValue; From 486e7e4e1e4e156824423852cea22e37230b4c81 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 19:44:04 +0900 Subject: [PATCH 1640/5608] Remove unnecessary file --- osu.Android/monogc.txt | 1 - osu.Android/osu.Android.csproj | 3 --- 2 files changed, 4 deletions(-) delete mode 100644 osu.Android/monogc.txt diff --git a/osu.Android/monogc.txt b/osu.Android/monogc.txt deleted file mode 100644 index d15a2bd2ae..0000000000 --- a/osu.Android/monogc.txt +++ /dev/null @@ -1 +0,0 @@ -MONO_GC_PARAMS=nursery-size=8m \ No newline at end of file diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index f56d38ac5c..42a3185cd1 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -46,8 +46,5 @@ - - - \ No newline at end of file From 7dbba87e4c83d98defef5d4f01bb3b37607d9e06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 19:55:16 +0900 Subject: [PATCH 1641/5608] Update dependencies oops --- osu.Android.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 74fe16ebf6..ead059cdf2 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,7 +63,7 @@ - - + + From f45b42021ff01782b0594a2c97ee89f5dfc2e7b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 19:45:55 +0900 Subject: [PATCH 1642/5608] Change app label to just "osu!" --- osu.Android/Properties/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index edbf651d09..326d32f7ab 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -6,5 +6,5 @@ - + \ No newline at end of file From 1ff6a9d085da89471a8d608cd4dd72251cef4a52 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 2 Jul 2019 16:25:40 +0530 Subject: [PATCH 1643/5608] Remove unused using --- osu.Game/Overlays/Direct/DownloadButton.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 6bac07fc88..dac1521bf3 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; -using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online; From a26b14a4f89a44ee8d9adb96774b75fa4989e46e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 22:21:56 +0900 Subject: [PATCH 1644/5608] Move finaliser inside disposal region --- osu.Game/Beatmaps/WorkingBeatmap.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 61390fe51b..40b3d70262 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -46,11 +46,6 @@ namespace osu.Game.Beatmaps skin = new RecyclableLazy(GetSkin); } - ~WorkingBeatmap() - { - Dispose(false); - } - protected virtual Track GetVirtualTrack() { const double excess_length = 1000; @@ -229,6 +224,11 @@ namespace osu.Game.Beatmaps beatmapCancellation.Cancel(); } + ~WorkingBeatmap() + { + Dispose(false); + } + #endregion public class RecyclableLazy From 0b66f139020b9a13e3816814c76078db25c97a72 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 22:22:33 +0900 Subject: [PATCH 1645/5608] Add todo about beatmap load cancellation --- osu.Game/Beatmaps/WorkingBeatmap.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 40b3d70262..2f611b8409 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -145,6 +145,7 @@ namespace osu.Game.Beatmaps public Task LoadBeatmapAsync() => (beatmapLoadTask ?? (beatmapLoadTask = Task.Factory.StartNew(() => { + // Todo: Handle cancellation during beatmap parsing var b = GetBeatmap() ?? new Beatmap(); // The original beatmap version needs to be preserved as the database doesn't contain it From a6acc1f99f25e9dfbd344679ba9cc147e5eb9e3b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 22:25:51 +0900 Subject: [PATCH 1646/5608] Catch exception and return null for safety . --- osu.Game/Beatmaps/WorkingBeatmap.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 2f611b8409..a4324ecb0c 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -157,7 +157,20 @@ namespace osu.Game.Beatmaps return b; }, beatmapCancellation.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default))); - public IBeatmap Beatmap => LoadBeatmapAsync().Result; + public IBeatmap Beatmap + { + get + { + try + { + return LoadBeatmapAsync().Result; + } + catch (TaskCanceledException) + { + return null; + } + } + } private readonly CancellationTokenSource beatmapCancellation = new CancellationTokenSource(); protected abstract IBeatmap GetBeatmap(); From 9e33fb35e9241dda9fa34c33804bae5f7a9e9670 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 22:24:08 +0900 Subject: [PATCH 1647/5608] Fix typo --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index a4324ecb0c..00ba8963cb 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -231,7 +231,7 @@ namespace osu.Game.Beatmaps { // recycling logic is not here for the time being, as components which use // retrieved objects from WorkingBeatmap may not hold a reference to the WorkingBeatmap itself. - // this should be fine as each retrieved comopnent do have their own finalizers. + // this should be fine as each retrieved component do have their own finalizers. // cancelling the beatmap load is safe for now since the retrieval is a synchronous // operation. if we add an async retrieval method this may need to be reconsidered. From f31d840c13eecb92af95e69aceb26fad15a69a0f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 22:25:03 +0900 Subject: [PATCH 1648/5608] Dispose previous WorkingBeatmap on change --- osu.Game/OsuGame.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index bfa4aeadef..49c543537a 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -296,6 +296,8 @@ namespace osu.Game if (nextBeatmap?.Track != null) nextBeatmap.Track.Completed += currentTrackCompleted; + beatmap.OldValue?.Dispose(); + nextBeatmap?.LoadBeatmapAsync(); } From 93511266e5d771b4c2099ddd1b5b45b39b6c81b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 22:33:33 +0900 Subject: [PATCH 1649/5608] Fix waves not displaying at all --- osu.Game/Graphics/Containers/WaveContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/WaveContainer.cs b/osu.Game/Graphics/Containers/WaveContainer.cs index 9050e775f7..17e4f0afd5 100644 --- a/osu.Game/Graphics/Containers/WaveContainer.cs +++ b/osu.Game/Graphics/Containers/WaveContainer.cs @@ -125,7 +125,7 @@ namespace osu.Game.Graphics.Containers // This is done as an optimization, such that invisible parts of the waves // are masked away, and thus do not consume fill rate. - wavesContainer.Height = Math.Max(0, DrawHeight - (contentContainer.DrawHeight - contentContainer.Y)); + wavesContainer.Height = Math.Max(0, DrawHeight - (contentContainer.DrawHeight - contentContainer.Y * DrawHeight)); } private class Wave : VisibilityContainer From e7a7f2f660c0eed21b1d7696f3236038f59c2edf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 22:39:42 +0900 Subject: [PATCH 1650/5608] Add statistic for count of alive WorkingBeatmaps --- osu.Game/Beatmaps/WorkingBeatmap.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 00ba8963cb..138d911556 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -13,6 +13,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using osu.Framework.Audio; +using osu.Framework.Statistics; using osu.Game.IO.Serialization; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; @@ -32,6 +33,8 @@ namespace osu.Game.Beatmaps protected AudioManager AudioManager { get; } + private static readonly GlobalStatistic total_count = GlobalStatistics.Get(nameof(Beatmaps), $"Total {nameof(WorkingBeatmap)}s"); + protected WorkingBeatmap(BeatmapInfo beatmapInfo, AudioManager audioManager) { AudioManager = audioManager; @@ -44,6 +47,8 @@ namespace osu.Game.Beatmaps waveform = new RecyclableLazy(GetWaveform); storyboard = new RecyclableLazy(GetStoryboard); skin = new RecyclableLazy(GetSkin); + + total_count.Value++; } protected virtual Track GetVirtualTrack() @@ -227,8 +232,15 @@ namespace osu.Game.Beatmaps GC.SuppressFinalize(this); } + private bool isDisposed; + protected virtual void Dispose(bool isDisposing) { + if (isDisposed) + return; + + isDisposed = true; + // recycling logic is not here for the time being, as components which use // retrieved objects from WorkingBeatmap may not hold a reference to the WorkingBeatmap itself. // this should be fine as each retrieved component do have their own finalizers. @@ -236,6 +248,8 @@ namespace osu.Game.Beatmaps // cancelling the beatmap load is safe for now since the retrieval is a synchronous // operation. if we add an async retrieval method this may need to be reconsidered. beatmapCancellation.Cancel(); + + total_count.Value--; } ~WorkingBeatmap() From 8e0b5f16225f00266c52c61818636b798502770d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 Jul 2019 23:21:13 +0900 Subject: [PATCH 1651/5608] Fix weird merge conflict --- osu.Game/Beatmaps/WorkingBeatmap.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index c6f26423dd..37aa0024da 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -51,11 +51,6 @@ namespace osu.Game.Beatmaps total_count.Value++; } - ~WorkingBeatmap() - { - Dispose(false); - } - protected virtual Track GetVirtualTrack() { const double excess_length = 1000; From 778c36c7d7a243696380f14fb0942ad08153cc9d Mon Sep 17 00:00:00 2001 From: miterosan Date: Tue, 2 Jul 2019 17:05:04 +0200 Subject: [PATCH 1652/5608] Allow discover of rulesets that are already loaded. --- osu.Game/Rulesets/RulesetStore.cs | 42 +++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 0ebadd73d2..919b5dde22 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -22,8 +22,20 @@ namespace osu.Game.Rulesets { AppDomain.CurrentDomain.AssemblyResolve += currentDomain_AssemblyResolve; - foreach (string file in Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll") - .Where(f => !Path.GetFileName(f).Contains("Tests"))) + addLoadedRulesets(); + + IEnumerable files = new string[0]; + + try + { + files = Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll"); + } + catch (Exception e) + { + Logger.Error(e, $"Could not load rulesets from directory {Environment.CurrentDirectory}"); + } + + foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) loadRulesetFromFile(file); } @@ -111,6 +123,17 @@ namespace osu.Game.Rulesets } } + private static void addLoadedRulesets() + { + // on android the rulesets are already loaded + var loadedRulesets = AppDomain.CurrentDomain.GetAssemblies() + .Where(assembly => assembly.GetName().Name.StartsWith(ruleset_library_prefix, StringComparison.InvariantCultureIgnoreCase)) + .Where(assembly => !assembly.GetName().Name.Contains("Tests")); + + foreach (var ruleset in loadedRulesets) + addRuleset(ruleset); + } + private static void loadRulesetFromFile(string file) { var filename = Path.GetFileNameWithoutExtension(file); @@ -128,5 +151,20 @@ namespace osu.Game.Rulesets Logger.Error(e, $"Failed to load ruleset {filename}"); } } + + private static void addRuleset(Assembly assembly) + { + if (loaded_assemblies.ContainsKey(assembly)) + return; + + try + { + loaded_assemblies[assembly] = assembly.GetTypes().First(t => t.IsPublic && t.IsSubclassOf(typeof(Ruleset))); + } + catch (Exception e) + { + Logger.Error(e, $"Failed to add ruleset {assembly}"); + } + } } } From e1d0d2666997580a47f510c088cc3d0af4046f18 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 00:21:16 +0900 Subject: [PATCH 1653/5608] Add a note about local optimisation that may not be required in the future --- osu.Game/Graphics/Containers/WaveContainer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Graphics/Containers/WaveContainer.cs b/osu.Game/Graphics/Containers/WaveContainer.cs index 17e4f0afd5..c01674f5b4 100644 --- a/osu.Game/Graphics/Containers/WaveContainer.cs +++ b/osu.Game/Graphics/Containers/WaveContainer.cs @@ -125,6 +125,7 @@ namespace osu.Game.Graphics.Containers // This is done as an optimization, such that invisible parts of the waves // are masked away, and thus do not consume fill rate. + // todo: revert https://github.com/ppy/osu/commit/aff9e3617da0c8fe252169fae287e39b44575b5e after FTB is fixed on iOS. wavesContainer.Height = Math.Max(0, DrawHeight - (contentContainer.DrawHeight - contentContainer.Y * DrawHeight)); } From f1ceea8361e18ce23e9e5f4dc031f5bd40a393c5 Mon Sep 17 00:00:00 2001 From: miterosan Date: Tue, 2 Jul 2019 17:25:12 +0200 Subject: [PATCH 1654/5608] style fixes --- osu.Game/Rulesets/RulesetStore.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 919b5dde22..17834f8545 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -24,19 +24,17 @@ namespace osu.Game.Rulesets addLoadedRulesets(); - IEnumerable files = new string[0]; - try { - files = Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll"); + string[] files = Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll"); + + foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) + loadRulesetFromFile(file); } catch (Exception e) { Logger.Error(e, $"Could not load rulesets from directory {Environment.CurrentDirectory}"); } - - foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) - loadRulesetFromFile(file); } public RulesetStore(IDatabaseContextFactory factory) @@ -125,13 +123,15 @@ namespace osu.Game.Rulesets private static void addLoadedRulesets() { - // on android the rulesets are already loaded - var loadedRulesets = AppDomain.CurrentDomain.GetAssemblies() - .Where(assembly => assembly.GetName().Name.StartsWith(ruleset_library_prefix, StringComparison.InvariantCultureIgnoreCase)) - .Where(assembly => !assembly.GetName().Name.Contains("Tests")); + foreach (var ruleset in AppDomain.CurrentDomain.GetAssemblies()) + { + string rulesetName = ruleset.GetName().Name; + + if (!rulesetName.StartsWith(ruleset_library_prefix, StringComparison.InvariantCultureIgnoreCase) || ruleset.GetName().Name.Contains("Tests")) + continue; - foreach (var ruleset in loadedRulesets) addRuleset(ruleset); + } } private static void loadRulesetFromFile(string file) From f9c24f2281dc82ffd14ec3f47b7fc155112d9a66 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 00:35:55 +0900 Subject: [PATCH 1655/5608] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8c4f5dcb7d..b59828a52e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 113874f6f6..ddbdaf3d18 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From d387629e5348aaa8ac3322a169401415e5ba6747 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 2 Jul 2019 10:52:24 -0700 Subject: [PATCH 1656/5608] Fix layout of profile top header to match web --- .../Profile/Header/TopHeaderContainer.cs | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index dc6c3f56f8..bdf047478d 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -72,18 +72,30 @@ namespace osu.Game.Overlays.Profile.Header new FillFlowContainer { AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, + Direction = FillDirection.Vertical, Children = new Drawable[] { - usernameText = new OsuSpriteText + new FillFlowContainer { - Font = OsuFont.GetFont(size: 24, weight: FontWeight.Regular) + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + usernameText = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Regular) + }, + openUserExternally = new ExternalLinkButton + { + Margin = new MarginPadding { Left = 5 }, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + } }, - openUserExternally = new ExternalLinkButton + titleText = new OsuSpriteText { - Margin = new MarginPadding { Left = 5 }, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Regular) }, } }, @@ -95,10 +107,6 @@ namespace osu.Game.Overlays.Profile.Header AutoSizeAxes = Axes.Both, Children = new Drawable[] { - titleText = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 18, weight: FontWeight.Regular) - }, supporterTag = new SupporterIcon { Height = 20, From a1fb41ea66c7489d1036f7e17ca0f9eb5d9f9ba5 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 2 Jul 2019 10:53:52 -0700 Subject: [PATCH 1657/5608] Use FillFlowContainer on flag and country --- osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index bdf047478d..b0d7070994 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -119,10 +119,11 @@ namespace osu.Game.Overlays.Profile.Header Margin = new MarginPadding { Top = 10 }, Colour = colours.GreySeafoamLighter, }, - new Container + new FillFlowContainer { AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Top = 5 }, + Direction = FillDirection.Horizontal, Children = new Drawable[] { userFlag = new UpdateableFlag @@ -133,7 +134,7 @@ namespace osu.Game.Overlays.Profile.Header userCountryText = new OsuSpriteText { Font = OsuFont.GetFont(size: 17.5f, weight: FontWeight.Regular), - Margin = new MarginPadding { Left = 40 }, + Margin = new MarginPadding { Left = 10 }, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, Colour = colours.GreySeafoamLighter, From 8b4ef52c13b2ce84c7ea387c9e1f08450b9a19bb Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 3 Jul 2019 07:27:24 +0300 Subject: [PATCH 1658/5608] Revert unnecessary changes --- osu.Game/Screens/Play/HUDOverlay.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 6488bf9452..017bf70133 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -41,7 +40,6 @@ namespace osu.Game.Screens.Play private readonly IReadOnlyList mods; private Bindable showHud; - private Bindable hideHealthbar; private readonly Container visibilityContainer; private readonly BindableBool replayLoaded = new BindableBool(); @@ -79,11 +77,11 @@ namespace osu.Game.Screens.Play ComboCounter = CreateComboCounter(), }, }, + HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), ModDisplay = CreateModsContainer(), } }, - HealthDisplay = CreateHealthDisplay(), PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), new FillFlowContainer { @@ -114,14 +112,8 @@ namespace osu.Game.Screens.Play ModDisplay.Current.Value = mods; - hideHealthbar = config.GetBindable(OsuSetting.HideHealthBar); showHud = config.GetBindable(OsuSetting.ShowInterface); - showHud.ValueChanged += visible => - { - visibilityContainer.FadeTo(visible.NewValue ? 1 : 0, duration); - if (!(hideHealthbar.Value && mods.OfType().Any())) - HealthDisplay.FadeTo(visible.NewValue ? 1 : 0, duration); - }; + showHud.ValueChanged += visible => visibilityContainer.FadeTo(visible.NewValue ? 1 : 0, duration); showHud.TriggerChange(); if (!showHud.Value && !hasShownNotificationOnce) From 3f39541cc2daa11b9e319a96ae5b2739db25af51 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 3 Jul 2019 05:11:11 +0300 Subject: [PATCH 1659/5608] Fade health bar on value change --- osu.Game/Rulesets/Mods/ModBlockFail.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index 42ec82f8aa..f98521da69 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -2,14 +2,17 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Configuration; using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; namespace osu.Game.Rulesets.Mods { public abstract class ModBlockFail : Mod, IApplicableFailOverride, IApplicableToHUD, IReadFromConfig { - private Bindable hideHealthBar = new Bindable(); + private Bindable hideHealthBar; + private HealthDisplay healthDisplay; /// /// We never fail, 'yo. @@ -19,12 +22,13 @@ namespace osu.Game.Rulesets.Mods public void ReadFromConfig(OsuConfigManager config) { hideHealthBar = config.GetBindable(OsuSetting.HideHealthBar); + hideHealthBar.ValueChanged += v => healthDisplay?.FadeTo(v.NewValue ? 0 : 1, 250, Easing.OutQuint); } public void ApplyToHUD(HUDOverlay overlay) { - if (hideHealthBar.Value) - overlay.HealthDisplay.Hide(); + healthDisplay = overlay.HealthDisplay; + hideHealthBar?.TriggerChange(); } } } From 23acddcb562fcdfd6d66e2182177901d1db55595 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 12:02:35 +0900 Subject: [PATCH 1660/5608] Rename download buttons to avoid ambiguity --- .../Visual/Online/TestSceneBeatmapSetOverlay.cs | 2 +- .../Visual/Online/TestSceneDirectDownloadButton.cs | 4 ++-- .../{OsuDownloadButton.cs => DownloadButton.cs} | 4 ++-- .../{DownloadButton.cs => HeaderDownloadButton.cs} | 4 ++-- osu.Game/Overlays/BeatmapSet/Header.cs | 9 ++++----- osu.Game/Overlays/Direct/DirectGridPanel.cs | 2 +- osu.Game/Overlays/Direct/DirectListPanel.cs | 4 ++-- .../{DownloadButton.cs => PanelDownloadButton.cs} | 10 +++++----- osu.Game/Screens/Play/ReplayDownloadButton.cs | 4 ++-- 9 files changed, 21 insertions(+), 22 deletions(-) rename osu.Game/Graphics/UserInterface/{OsuDownloadButton.cs => DownloadButton.cs} (96%) rename osu.Game/Overlays/BeatmapSet/Buttons/{DownloadButton.cs => HeaderDownloadButton.cs} (97%) rename osu.Game/Overlays/Direct/{DownloadButton.cs => PanelDownloadButton.cs} (86%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index c494f5ef33..a9c44c9020 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Online typeof(BasicStats), typeof(BeatmapPicker), typeof(Details), - typeof(DownloadButton), + typeof(HeaderDownloadButton), typeof(FavouriteButton), typeof(Header), typeof(HeaderButton), diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs index 5a5833feb6..5b0c2d3c67 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.Online { public override IReadOnlyList RequiredTypes => new[] { - typeof(DownloadButton) + typeof(PanelDownloadButton) }; private TestDownloadButton downloadButton; @@ -143,7 +143,7 @@ namespace osu.Game.Tests.Visual.Online return beatmap; } - private class TestDownloadButton : DownloadButton + private class TestDownloadButton : PanelDownloadButton { public new bool DownloadEnabled => base.DownloadEnabled; diff --git a/osu.Game/Graphics/UserInterface/OsuDownloadButton.cs b/osu.Game/Graphics/UserInterface/DownloadButton.cs similarity index 96% rename from osu.Game/Graphics/UserInterface/OsuDownloadButton.cs rename to osu.Game/Graphics/UserInterface/DownloadButton.cs index 6e95c7e291..41b90d3802 100644 --- a/osu.Game/Graphics/UserInterface/OsuDownloadButton.cs +++ b/osu.Game/Graphics/UserInterface/DownloadButton.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class OsuDownloadButton : OsuAnimatedButton + public class DownloadButton : OsuAnimatedButton { public readonly Bindable State = new Bindable(); @@ -21,7 +21,7 @@ namespace osu.Game.Graphics.UserInterface private OsuColour colours; - public OsuDownloadButton() + public DownloadButton() { Children = new Drawable[] { diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs similarity index 97% rename from osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs rename to osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs index 3e8a5a8324..fe10287491 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Buttons { - public class DownloadButton : BeatmapDownloadTrackingComposite, IHasTooltip + public class HeaderDownloadButton : BeatmapDownloadTrackingComposite, IHasTooltip { private readonly bool noVideo; @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private ShakeContainer shakeContainer; private HeaderButton button; - public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) + public HeaderDownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) : base(beatmapSet) { this.noVideo = noVideo; diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 1c1167d08e..b50eac2c1a 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -18,7 +18,6 @@ using osu.Game.Overlays.BeatmapSet.Buttons; using osu.Game.Overlays.Direct; using osuTK; using osuTK.Graphics; -using DownloadButton = osu.Game.Overlays.BeatmapSet.Buttons.DownloadButton; namespace osu.Game.Overlays.BeatmapSet { @@ -268,7 +267,7 @@ namespace osu.Game.Overlays.BeatmapSet { case DownloadState.LocallyAvailable: // temporary for UX until new design is implemented. - downloadButtonsContainer.Child = new Direct.DownloadButton(BeatmapSet.Value) + downloadButtonsContainer.Child = new PanelDownloadButton(BeatmapSet.Value) { Width = 50, RelativeSizeAxes = Axes.Y @@ -278,13 +277,13 @@ namespace osu.Game.Overlays.BeatmapSet case DownloadState.Downloading: case DownloadState.Downloaded: // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. - downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); + downloadButtonsContainer.Child = new HeaderDownloadButton(BeatmapSet.Value); break; default: - downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); + downloadButtonsContainer.Child = new HeaderDownloadButton(BeatmapSet.Value); if (BeatmapSet.Value.OnlineInfo.HasVideo) - downloadButtonsContainer.Add(new DownloadButton(BeatmapSet.Value, true)); + downloadButtonsContainer.Add(new HeaderDownloadButton(BeatmapSet.Value, true)); break; } } diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index 5756a4593d..243e79eb9b 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -155,7 +155,7 @@ namespace osu.Game.Overlays.Direct }, }, }, - new DownloadButton(SetInfo) + new PanelDownloadButton(SetInfo) { Size = new Vector2(50, 30), Margin = new MarginPadding(horizontal_padding), diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index 6f3b5bc5f1..5757e1445b 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Direct private const float height = 70; private FillFlowContainer statusContainer; - protected DownloadButton DownloadButton; + protected PanelDownloadButton DownloadButton; private PlayButton playButton; private Box progressBar; @@ -150,7 +150,7 @@ namespace osu.Game.Overlays.Direct Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, AutoSizeAxes = Axes.Both, - Child = DownloadButton = new DownloadButton(SetInfo) + Child = DownloadButton = new PanelDownloadButton(SetInfo) { Size = new Vector2(height - vertical_padding * 3), Margin = new MarginPadding { Left = vertical_padding * 2, Right = vertical_padding }, diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/PanelDownloadButton.cs similarity index 86% rename from osu.Game/Overlays/Direct/DownloadButton.cs rename to osu.Game/Overlays/Direct/PanelDownloadButton.cs index dac1521bf3..017f92abaa 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/PanelDownloadButton.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.Allocation; @@ -10,16 +10,16 @@ using osu.Game.Online; namespace osu.Game.Overlays.Direct { - public class DownloadButton : BeatmapDownloadTrackingComposite + public class PanelDownloadButton : BeatmapDownloadTrackingComposite { protected bool DownloadEnabled => button.Enabled.Value; private readonly bool noVideo; private readonly ShakeContainer shakeContainer; - private readonly OsuDownloadButton button; + private readonly DownloadButton button; - public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) + public PanelDownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) : base(beatmapSet) { this.noVideo = noVideo; @@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Direct InternalChild = shakeContainer = new ShakeContainer { RelativeSizeAxes = Axes.Both, - Child = button = new OsuDownloadButton + Child = button = new DownloadButton { RelativeSizeAxes = Axes.Both, }, diff --git a/osu.Game/Screens/Play/ReplayDownloadButton.cs b/osu.Game/Screens/Play/ReplayDownloadButton.cs index 5acf4e83d9..748fe8cc90 100644 --- a/osu.Game/Screens/Play/ReplayDownloadButton.cs +++ b/osu.Game/Screens/Play/ReplayDownloadButton.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.Play { public class ReplayDownloadButton : DownloadTrackingComposite { - private OsuDownloadButton button; + private DownloadButton button; private ShakeContainer shakeContainer; private ReplayAvailability replayAvailability @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Play InternalChild = shakeContainer = new ShakeContainer { RelativeSizeAxes = Axes.Both, - Child = button = new OsuDownloadButton + Child = button = new DownloadButton { RelativeSizeAxes = Axes.Both, } From d22a1229cbba13668b9f2abd5b33a220041d9658 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 12:06:20 +0900 Subject: [PATCH 1661/5608] Remove unnecessary disposal --- osu.Game/Overlays/Direct/PanelDownloadButton.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/osu.Game/Overlays/Direct/PanelDownloadButton.cs b/osu.Game/Overlays/Direct/PanelDownloadButton.cs index 017f92abaa..4037cd46f3 100644 --- a/osu.Game/Overlays/Direct/PanelDownloadButton.cs +++ b/osu.Game/Overlays/Direct/PanelDownloadButton.cs @@ -71,12 +71,5 @@ namespace osu.Game.Overlays.Direct } }; } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - button?.State.UnbindAll(); - } } } From 98daaf634ae4851fec97326efe1e9a0eea65137f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 3 Jul 2019 06:44:17 +0300 Subject: [PATCH 1662/5608] Simplify changes --- osu.Game/Rulesets/Mods/ModBlockFail.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index f98521da69..e37b1b0698 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -22,13 +22,12 @@ namespace osu.Game.Rulesets.Mods public void ReadFromConfig(OsuConfigManager config) { hideHealthBar = config.GetBindable(OsuSetting.HideHealthBar); - hideHealthBar.ValueChanged += v => healthDisplay?.FadeTo(v.NewValue ? 0 : 1, 250, Easing.OutQuint); } public void ApplyToHUD(HUDOverlay overlay) { healthDisplay = overlay.HealthDisplay; - hideHealthBar?.TriggerChange(); + hideHealthBar.BindValueChanged(v => healthDisplay.FadeTo(v.NewValue ? 0 : 1, 250, Easing.OutQuint), true); } } } From 1189092e2033daa69f9fc224604de88fdbce546a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 12:49:16 +0900 Subject: [PATCH 1663/5608] Remove redundant scale specification --- osu.Game/Online/Leaderboards/DrawableRank.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs index 4d81ead494..50cb58c6ab 100644 --- a/osu.Game/Online/Leaderboards/DrawableRank.cs +++ b/osu.Game/Online/Leaderboards/DrawableRank.cs @@ -49,7 +49,6 @@ namespace osu.Game.Online.Leaderboards RelativeSizeAxes = Axes.Both, ColourDark = rankColour.Darken(0.1f), ColourLight = rankColour.Lighten(0.1f), - TriangleScale = 1, Velocity = 0.25f, }, new OsuSpriteText From 9eef8243c0906efb59013c66da45a7044a18fc1b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 14:22:14 +0900 Subject: [PATCH 1664/5608] Update bounty/contribution information --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 55f2eebec9..6ef56149ab 100644 --- a/README.md +++ b/README.md @@ -92,11 +92,13 @@ Code analysis can be run with `powershell ./build.ps1` or `build.sh`. This is cu 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 on 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. -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**. +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). -Contributions can be made via pull requests to this repository. We hope to credit and reward larger contributions via a [bounty system](https://www.bountysource.com/teams/ppy). If you're unsure of what you can help with, check out the [list of open issues](https://github.com/ppy/osu/issues). +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. I 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; 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. + +For those interested, we love to reward quality contributions via [awarding bounties](https://docs.google.com/forms/d/e/1FAIpQLSet_8iFAgPMG526pBZ2Kic6HSh7XPM3fE8xPcnWNkMzINDdYg/viewform). Don't hesitate to request a bounty for your work on this project. ## Licence From 6c46643c26c6d5ad5539e2bbb812d4b30377cc2e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 14:26:19 +0900 Subject: [PATCH 1665/5608] Update icon --- README.md | 6 ++++-- assets/lazer.png | Bin 0 -> 39498 bytes 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 assets/lazer.png diff --git a/README.md b/README.md index 6ef56149ab..18663353b4 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +

+ +

+ # osu! [![Build status](https://ci.appveyor.com/api/projects/status/u2p01nx7l6og8buh?svg=true)](https://ci.appveyor.com/project/peppy/osu) [![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) @@ -22,8 +26,6 @@ Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh ### Releases -![](https://puu.sh/DCmvA/f6a74f5fbb.png) - If you are not interested in developing the game, you can still consume our [binary releases](https://github.com/ppy/osu/releases). **Latest build:** diff --git a/assets/lazer.png b/assets/lazer.png new file mode 100644 index 0000000000000000000000000000000000000000..075a8e7184ad508cedd8fe9ae549d8cea696b51a GIT binary patch literal 39498 zcmY&fby(By*B(7eMk76>8%d={m!#6&jFgfN>FyRJ6%eGm8|fO|NQd<3ci-QC@3!mu ztgb!J&biMy_lYM`?SmXH7C9CG0Kip{m(~CPkPuIi06=ua#o+T#E5rrWT2e(40H}_~ zel$fxyrwmm*H8ffycq$2zz_i79`RP-J^ANSCfql#!O5o_!heEhk8F9M`SPd0o7W z;wySfkmL8D?u5%Z+c=WdkM2jGR@a~U&+sZYu>SvJ54fd)w}F*Lqjxmzn)`H?lQ;gT z4a{#2&a*YZ2c+}V!3enPU~wS2tcks3jXxo#WGWqJKX7{G?>q8P2{isNgHUj2k#%Z6 zXai~jF_h6H6Og7AOED|1g}6_>)|yPo2q6)5u=j65hLCbWbWO9aE@;uc#7NGsC7=~` zuqgx1d3!S1a8t6QAeF99ChedCP3S5XeV~vDA*UOPTJa?iZ0EhEca$mIsme?wLW`%2 zYzywIg0&b!{Uo7&vWi|tz^RIQYBFkSYA6&s0t7!QiF#^ti&p{zKcZLElT%T}{?I6W zwSL=(3BHkM`8}<7Mg;kVp@&J@EYnoNb->Gxg{|^aQW?2dLeQB&2!|4F9Pk8*C}o3~ zx^G4Sn))X7C?v2Jjvt=ISpJT6iJ4$eqDzN@E;Qm@6K_cXuT6kL*p#S7#E>?$9F&0& z&{{F|-UKgVb>c9Xo=wGem(>RP#)l2ritA5cX)JEe>&lLp+e%E8NcD|huzPoKpKIk& zhi%sGJ8<6)@!6!#PDA~~8kQJgHb7P6K$ogV?34mq!Wg%ypdo?y zB4qX$Mf)@6I}# zi~*N~|0YHKvNU+<=bMio7nB%d_FDmec}3E9guLKLzdD;xe$b-$saR%a!v=(EoS@;~ zzR%u9z`qd%07yVri|YOH{{60l2`aHvFyz(ABA{XFmZW?OA{^x6c5jLIeIb*4AAZ#h zBG6=wc}=5haJ9+FHL15vV!+91GL?YA7SdJ2!CAt)Kkb_z{emuo+kNRLvW|@=3EDuT zcHG!L2$aCoTIn{*rt5Iv7&bhLbg&<^i+eMcnp~}S)CRlf2lu_Og~0PcX1@KL9g63! z9Dq7l+EGg*Yw>eEXv+{10lzRNdh`ui=_31YOa4vK$IVEO)i~2L85*VvD4HxdwgxMI zqgh)s*4nu^FM{>EZqwvy`EgKYa>VN;3(ubbv9ChE!t%q^re7h)2h(7o3jV`X4oZx| zU!9gbJRGCl(?BA${c{PU{5jDAVR}2Co5#{DpDICHf`RTM zRD-vdoQoa!19+Z1{u}Jgr(n1D@j+c0=xKb_De5bKEo}-(NgsS4n$I4ZDwW=a%Wcyl z1jJtSD|eR6Cic~z-ZL3Pq>5go(oc-e4&Nd?fna&Z8r{52@?@h78n+XB!?d{b!H#f#akjHA!*1+Go%lf@!id>UN zXVOBa96FyC8qv%_X)_AOhPOP$K`g`?SoEK}(TqL(D_jgo*Nu%j(=@PVe%ZG|dwxo* zY|Dg`gODV@N0Upc3r~u1BGH)=E-opI#4als)noqP2vQr_`^s^TVTAHr(AoJS2c56{ zrUx4~u!J|`1N5Mo6MLSzY1eXHa?$m-BhKJ|Z{JP-@Oka^7xkdm5Z;@dalcj2sO2(+ z{qCerAIEq7hnmjolerpptADXX`};` zyI{Pg9RZSRvxR>z_>dg9*D&*AGYHUc_=2MGCjjqQKdvhG72l~%R;1M4YwvS1%^yDM zcL2H93x9e(F@|aUWZ=9%II>mAS7XLr=U^&I(MkJQf@V`e;o%pH4hBv(b*OfG4&R}D z?vOK4$f=;JTWg4(t=F&CPXaE&wHwIMPImadYY^ zD=j{;NdoaX?QxObUy;J8y(SorNST2&g>Mut$AoR$-36!IIe>-dyOQb@@F>t0Z+}^D zp6+_r#4mu5+kQg5&+X|$szyLTeaA<|#YsUKAF<3z@PN_#5BFW~cBHB0vW6rIk=0AK z1j!{qYRp7wZE!_azY4Js4IMSC#mUux8-AMLcac<2#&V zN>TRIk~#5v>Fk!6QH|Dc37yki?65<7lBfb8K!QkAz=2zfm8r&OAm@(*aBPC!n4Q|pke z#fsLout0X_+flL|0>a)!V<)by56lGC4Y*_H=h6OSw#hTtpwm>>b6QpzS=HYB1(p0c z;8JZp(2$sJ>r$z zCcz9)T2fVuqLarhp;MJes8d*}`L-+UVP4NfAuvwIHdWqn_QKT5o%^WE!g-$w`k&d4 zkB=K;JO@A`aAV*9P9J}Jv!o!K_YV1MvUIARWtLqT+l5w7TH@mEuh zVR=Fko>mb+beQ zG#$rL7_!Jjc40AdvAh7kDH*yRMt*!32ejUmigt8%|zctt?0MQH$%F{3|XrfIpAG+qe60vn^_+dg2O-e(ld0ms;e| z0?EycGD;Nq$Sb~ZAxrX+GvrNZ^YKboA68ATr|UD@RIsge+Gfr8$3)*EDaup!_C+wL zlgs{?Ru*y37&c%1<#nr4w^oDwm))Tg1X<{kOCGkc7R!6_OtWlvdG{WJOBi=!Go0qr zna}#en$_}+F<_pfK0*$vQUZ;rJZtZQm;Z1UQLnpHp=*%RtSK!UJMyAlwD(w~3Wy!L zC50p?Ge*kpHHPzM;t&!NUWcM_Ky{6aGUGZkZ!4C|bVvH;FfDW9LjE zT@5GimcmnNj;WOfTl+s-sM=k?QBQc5*4#x^1ns5tlr%%4Ash7n&O$)qO*wR^>9K%G zJ^hZe00b4c*7#HGb2+6N3!J<4!ch+2lty}Yl$>YdliKdCV zoWFXf+ODEC@P#=9KJd4P$5|H`NDDls1^PQ~9KxyY>i`JSgc- zlPg8Tm5%_78n(PGtji({@Qk(v{t;t}&nIPSgphqLrtGk9h% zYI8BB0a*G+%0;Jl?rp2}c#iJ1-Ges7J(bjSPHMmRUv+lU37d7@t zlV4)89E{BTKsIkIfzNsZXK-?})lSmj%s$Z{KCK{y0O=Bk3N$>G@W1M*b0|0Jph{NR zfQ4JtN|Pe#qLh_g*dR*uAJ|a}*Zor0&e|e`1)4KPj6@ni4q>K`>9G`o&*OHa$mK9p zU~t!s$eA%&*m(k|z;cRdI%~N0Dd%ZvW(V&UBxr9I#`|qp`-qMZ0*W6TnblZsNYqFg z`AgpNz+bjBQNylLI$IE$a`q4t7YF+lHV>isgkART`LKJm4Q;t$?>ZnvMwSy{5rjss z>I=V(8@I#`g~1qPFzaA%x}>^Zj4F1!%7_3m;py_w`Q z@ae)rlgf? zpUWf_BOR8d=@QXGlQ=K%ELKFe?{NI(Vs4CEQv23$l`gPtD#C+l;qi*4Totl|8)dvm zMt;{HYt@*25hn3NN%t}6XzJxka{O^jHNh{LZ;_{U1WNEpJBu8T=x9F=dYOeyWb!Cl(;yg$L#32y^ zEPwOvJ6_Z)uFI6#TCXZ9t^VheoP3s-*R06~jOAJ8Id4S#8@fVi+979+#`H;Ze7g9Q zmic8u_lGVCwiVS5t@i0`RGqV-`b$sgW%o)fY+;O`C( z%@RLS+KxJ$_PESKJ`#*O)T&H*Hh@7#u}m_?uU3@ZS+B;N({i%}RrTGbSl8iy{k2>c zAaXS+b&>aS8Sso9X6pM%vDvbE50N_Nyxd&kJi&3zI_OMgs&HH-t#b8@35vC3QZ*Et zEuwzOmUc|p)K!uOfKyH@J{bqXyw|dx?GAclr~LsTDSZV~GMJKxEwU=x29hR-%}IgN znOd6trWB+g5k)B%C89nzlqnjy0rv+#v_nBU9AW@eVBqD#;;`Vps=CzhgkJtV(B>l? zFfcICfM7Wgpv$V+L?VrX>+V^e$yW0=eX7)o8+WlfDgQi#OKJFA8<+Q6$aMk2EA7*H zwuh=YiAmNY=W4jGAE&I!mOX1IQV#0Yple|fGadt3-awxJ@?QBJ$*ffOPXUND=YJ!L z2Av3!;(*({SUf&gOf6BJ`+|txx9kFq;(|is2V7#ZyMJf+Si&=^`K*l@Qr;r?BJ)S+ zcODw@;`{89W{cl1zCQ(jblpDH$cQepC-ncb;5V(-5sI7P1~Y>)rfE%O4@KoH1?-=l#mf~=1uzvqZkQ=~yMEoyxtrd$SQnD( zagHEb^d@PAmvb1+@IkSh6j+Y*=wtuD5so0bKP|OFPEj{qPgFQpe3^$iRDyL*&HFsG zuC8AKps2W&CiN$3t8-52MbJnm3Zw>!z^kvXe{ykha4(&5zOgLQtz*N_)y|YZHo5#6W+{x=SJ&-R zJ5d=ddr1OVE?wT$@b+@&(>X5XgM_B#UZzKp^cC;8^z`)up60ZT4UN*~yv~jYB%mB3 z6FxsQ4xLCwHnqvJw?@~+B@yDKkFsowHF)GT{*xqCO8q6b(WKs_u^HCO9WvtGt5v_xZXA21I z>|B5Xe~zdkr9au9_x8iRMO}IFWG%=Bk~|$)ETyFKF4y9(F+GPMi*5abp?qK}mdmabOYLWt4#09ldb@GAGMNSezXM-Z zwf4l@eI2*9J;ox zMDTBqZyQ)hc1lbj!8i9J3BZIzWQkre46Nu`>b>dl2Vo^eMn+m@f4x&1fkQ2^HNt`} z+GO5Ila?2A5X-6)PLdDgiFZ4%lw3bU6RrG~lwCM{xyfUx5lP^rais-C4KX1i_fDMH zTX!TIc##9D-_A_?cWu-<@xXiMBQa!oe!nEi@%&JaGM~Sw5oA3U6crp9QfMMdS&EoL zmfROH#Q7b#Ej02etsR6@8ln425^S<{-b)q-{HKv@~|`&jY@--QU69zf$y!)?`DUJ_(a(lDB0@ zv(E5o)8DIKi(!rhHN6I(vd9L&8I$E&Oz|PQz-m~{uNM(9u@3j*flfN)?~RRuB+>oP zv7oKAeoApKkHFL4Peg1d__aA?99@Y^gL=$Gku4(^OPcXi_x%&3J~z5d6Z>H~@VyozXFs z%=Z(?wGEOa2(8$>=@3g_#Yp(@!*kHA8sS0g%WieV^*4INJ0g7Q;u&YU%Xk}KG$f$0 zXLs_hr?r>u1DCrTSP+vl!|17Zw~00t!<})pKiS~5d^fi zOsJ!a$)&V{Ckh_GyDFk1af)zy;kSr9!+m4_bDWnhnnXZAfCxe4VZbheIkb<5JxQ`_fz6ssKe^y8w;iavZh!^8k)cZze~-Xj=PCjY)ACq* z6lb5m!SlnZlS;J?MHNfq*%@~Py&jR@#2+)UoFoiDU-$ae7Z_=p?2at|tXkK|N1C{G zz6?z`bA-u3W3wj+*+2h^wIk4oT=LoVOh*{y<$_Gcn}ja2t!gQY4>vHsSKyE&4S%=2 z@o#7T`}yH%Cx49_2w#o@o_-4=LQ@5Z?&DeYT|Vah%em!o9nF%~z+v(gwyBjDw6ND- z>1%GDhmzC=*SLbN>Vgw^w8XF#jy95Zwl2@i5}7G5j(`fD(V(I9W&A#mDbR1ZO-GvNF>4Fx*gU-b~9TpQ9?jrDHnog9S^7a zx?x-GVG}#eu6r6&HdlC|AopZ%D<4_1=P8Q5wkp?=QAg2Oi#0>m!)vr(0zf3Vq$Q+` zR${(cGj+c)T}mlg<3n~}nq`IJ;JU9Ggn)-~mkK8} zfXG`4sJ-{Wi)(AoM&Lf-BaW+cS2T2gIJuoOEBn7hSD)4jMvm`k%lfzt-BMl)0$nsYhaa*6U2{(~ay%FxbMEvZ? zy(o)iTO~@p)$v^N&W$H=>kS#P`?t_PirN&11b{Hq`rzA7mWj}baN3``^C?QUsB~y_ zj$aKjs^1YrvPVZ&6M%s1r4babPV=c5Z}JRdSQ4rn9&W|%hE*$}I}79jg?OS@2~#lG z4G+uT*lX(SBO3FasV8ZaQ1g%Rx9Mb-6my~0r5Rj;-*@}D&<2)>rhGg$b1CQ^wn~XN zqpmMG^(Ibyi|ZNLrAk#$7nE$!7?;d+I^9IO55R5nPRZy zDvf_#9T@bJvFQ=uYna*^z?epGGea;tmaQ(lq`thY_5j=Ja1Ps0!}GSQ4CIp0`rNz{ zb@!3{#B(|jtE-dy&xZMf?n`xRqSc8~mHfBc?_`LnAd>+KXey%drOX$uCM>lj5x;Y6{CylzOecsYM?Q4&WMqtjF^RvqRvzCzZ`?(_d= zCq0X$5@dl|UyjmT{rWStH@onlGK;MN8^fa#RUCO})n$S-;9w1W9P1zi)ws?r>F16) z$E6SuxqUhd2pEq34&FLh^Eq2JCmZ+;qqw=8)|I7RjZemCjni76BO&?4#`+y~y!96U z1@4fsEDRdxm!nOg|NP*gC1;i;?fOnk@y{W-1c-JLJI_2ctbc=NA+VFaTB;=Wf@*V%k3=zg&UvXCQOU$-hdfOhlP?E|uN!3d))9WaS8s8Y=eR zyAB?O-mrEqFc6xEu`|#WB2{-_ZZF}c>N`P)au1niL=AYTnu}yAh{zRmje?U*Z6<~J zhZaT#k34{iERFQZ!|~z>y(x`H=v`oW4+^hU41nTcmGB3$rsw`X*b7ca?JKbwEua4=(s_d-n=2Z8N+$-%_l2dguA$-i&z{(AGefDA5&_@{RXv3di`~z4?I{lbc8!J_s{on7kn6Ki+OMiKWse)7T^){ZK5LF##Lit$5gXZ2 z?R$NkE*@=cpodZE<5&N&J;`+asw@@|++=EAdRO0*I*a`M{Pj0*Y6hL1&d$1!YQ9rl z$9At>x3NE>Lf7iYvaM4G_<{(1F==UOcnGQ3ef}w$H)S1XqD<67{=$IX_DSjUnrp^RT`^9<$(UnVGGoUQz{$iYd%WJx&C5oqmM{x6|Jf&mncIO6=bdR zS}RXa20@8~uS`_Egu)_|u(7ke_j}W#{!SsI@(4rtunDn88`$S*hYmLLQOlHNg3K-*iSd9%}RJzH*NE+ z^_*x1ip_Xp`Y$Er71#;DR!dD7TnU|O#!3K|V$-bM@PIu}{~xC<*$1xdyWhj9z2!aJ z+(c+Y7W5}vmM&ihJTt>m;)_SarhHO`?zo6|Yahy=RuhsUYKEwVCibCBY^N=6?M&Be zv2!e&8d=LaJlLQB4Njw(X`7wOS25pGvo}d(nO^&Cfu_2E4lf#GX1K%hvHPrAmwuyz zg;hWunL|GPOr6ZY;dIrx3N#?N($T@e&!n0kIr{xRX}~#YHr3$W&y<=<^1sJ-;F^b4 z=afi0=ZqtbEab~}qB&HFQmxqw)UWYvl8)bNm==~6gIwma!k|b?c&zg%s4Y<@u$ewa zUh&E!4QK32e*;aEwFY9-Y~n$ls~ySUN}hr=(LpeKao_FJ;oi*(@!T^xF^QI9C~-i-CvdYJ3)eU zR(73{IJJ||M7mkzVC-!iv5vg1Z){JY4qGejgj=x;-IGR^NZ+yj`#UlG)m+Z^F1@hs zAakl>#({<>WXnseapo6pG=&qC;L78}m$O{MkEaDhnqXpYcP6N1FB6s(VR;5i&#r{*sgVf zbM=9fgvY?I=X>#qVlcyV&w(_7QK;Z|3Krh-5Tw#-q9#}`gl&YfsSk*#8i%=oY0nfj}`E%ByFf7f@m3kD7 zde5D2p1FXwKOefjZ%E>Dd2*Chk(d~FVnUTdSB;^v#^N&171(?-TV$8){|HtWiaoBz zJ6`&~FSUoHY%%T@$?cB0y1Tpuf)P_iPV4PHo~u-$2o^(gHza2vLLC5D(3)^LmCqWb zuy#qAa$XJ)NJ}a-!n0d_g5I?!B}Kd)ra7{N-@PHG>8R!mb>H5-uMdp6VCj$*(!%~J3o28bkPu6A(b%Fgt!Mm=& ztUq0t^u6&k^vj}rw{nVGD;>B~9f0{LaH0x+3>DSF?OAsVR8FP<{{-rWmiLwOOTV?2 zSirz3f1m$}$8qDC)9Wu+DgsYS%L%n@yJez5h!L?1aS@{3 z;|Xd_Xw1;p2eoXygi_`nfqyM>!=3)Gcv=Visc8a1f6d-Yyz#6vU2DR;42u==iZ>A% zncWT_7S(KKH>~T6SZl8RwNxE4tmzjc?vvud^hsMthj=j@!KXB+4SUt5L+s{+pa+@X zrS}Q{oQlgmhH(tpoQxZ@{Jj?TIBr7!5=P!HH^z41n)i@{A3sP#1eujFPkOf;zs?`U z5KDY=T)Q$Cd^z{XbyfP_D&M(ic((kg(poffTw0sOc~`&jj%-G6LXlCuOk`i*A4GKD{gC;vDb zWEeCqI`uST7zu((R+vhDeB+))luz=VD<)Z7yl&&nI-em?zU>GR63V=S?To;J>%Ok7 zwpq9HQt*j@}i^pxbLn}Ew0EPflZGUp@A8quoE|FNF+fD8?bVyu=06#W%7R> zUE{qpyYDluMH!$O|^Ur@_|+8ds6Z5qR!U6|1WLg zC6Dbuk)OSIASj75l!*DuZLv)lV3!j^%t7HWl!2tlYF|O-v&*gd<6-wvc7Q5JHxvQ^ z;(&+qsB<*+O&o1xC!7~Bds<$iK6Je!50tG?0-wA-rK=du*_R;>emC*4!h!DdQNz0_ zjFUSYF&D(hW<-WSONM-1M*P{sOx)U>8V2&EFls$)=fdlAvq5a0h*5VxMTW`YerU^p zx&@y9;D4kj>(Ph*Y5za^oQ=@+Ea3y*1*ay)xH;5Ifx;(E2<4NuPbJ!bfg8|!+Y6oA z>+8_{CoMPGxNrdU?EQuC(mCF(%ENK07V1}9ER=1s^XM_&kNU`oRa0-8otvXrm!%fo z)g23Spbdnj)u2)B7}hX7aEGv$FU~7&AY5%BgTUVGL2`SHs82`}H_#w`lrAq^A|)}g zGHp*dPipeAt!0qZCiX^zaZO0&BJISLvghNT91uYjL_JsCwb>>cC(od|nPyM-*FK>j zVLSK<-^J7Rmp!?j$#sUbNu@Q0UD^J$fKd%IrLQa9oU+E>^x5ePK4s8RHZ%98f_}EC z-e}#qYGYz7l316R>pV#I&ziS=Kennb=7yySUtUPrwyjlHSv11+aeu~gNIR~)4L=;2 z2>BRqwbaY$^~4|j(3K-}51~Y(vm4u_F?hw7B&Ljo7|A(pHodsEMn63~K3-A6bvg+~ z-ausTnvv35j$r8%%8z=vzB|H8(u8!2_{7JoKZpzPh8q$=sAW6s=dR+_-4o_1K< zP+FL{L@#~$maHMJHOW@x3nFxvlH0gkQ;K? z$cN^9mg4>Xs+%rEUY0J==d|^#1C5FvTP*ekPV-`ps8qKeoj+rEr5|r%>-;3feHsgw zu?7yXo1HbM?fhQ*a4~<@wJ_aa!jvrw=0n4AQ!Ul`X%I`)5afCrcK`tgb%C(XdYDfa zVt~P*3<~{8UMFMie@LVM^{VhI)Ms(fX-+UK;%>eNM}t*x$@KMHDwl<^ z8=7~70Kr9;x}GlwdCv#IVy&Sh^$UplmR0fW$7`H6ZlR!c-cLmjdQ`|JJg?qxbTxZn z!z%eV&00;dOV``u_l0l5D4%1g&HLC#DhWfHkp$2WNL3RmH$ZO%(n+ycSis+y=J^et zTlrN$Eb}J2v$;@1S;E~rvHwtRLGAQb>3M}VEaTjsLk5wq|NP=rM9XaTc#!KtS8Kao z+_f?nsi*0)wd6bDbbptHb#!=5AMikpkmjp7N^C#s5;~7{YKy&#q>2JtvPhdD>f(Q# zF^M!~6F6#$hV`bsVPotj=C|z z=)2x_pSUy1@Oldc^foK(`cjh$GpW;qDe=KWb#Fz=g){++cbf;kJ@3Nw)^c!+lZXIf z0#6Wy>65(DDrGKs_x2lz-sHpIJQ(?k8UR&qTd7BD?R7Ngy09!aAAiLkC~zk3wj%Gc zOeJ^U^l`CJy7(hCCV|PRk<^9YDgE7%=XZfdcAE-L`A0BB@fwcdM1QC6X?kMB%Y;3p zlT7cu?pRmdc4qnJpf@FDXc&1h`RST^DOa($(wYT%0}+L4?3X)GelEi2D&sx9t14w_ z*dq1n0S@wXPRn0)O~VPodOEyChXefas&5S_-e;samzVJ>Y?(K1t~6yXa2Z9rE(@rU zs{SnMBSAln^q0*QfB!?r#wtHS!bD!?c@*$G+n=I~U#$ksiYl>CchCEFEqFo-LJh*h zC#zos>HF8G&tJv91v*3zuvR%wFZpWo@L)6hQ{=H%DD;o31SQIl7Y(fndYLzy$y4; zA>3~ghp6(Nj;;6H{m0k<)L%A&NQ!51uYZoMNu#d{tGgBqYS@&Je%0IW^V>ouTIBs9nD@8BeFchj% zXX&#S(T|_#<2#%eEYf0zl`xN*ye3c#^9SI!%*Y(bTGIi$uBYD9za(&|YaJG7axphq ze7G_Lg}oq_)s1eq{?xmaw0-7`r~dI2p8O4yfTsDixgk%X0dQ2Mf?nL8!p_{1WT(tt zRfBe(fAjGISBRzqzdqk<^FuEW_R+lx>WD(~2NbGcI{HNS)-abrs45l#1Xw&9>lE;? zyr;67=kzxcQN*!N)PVKho!!KNXV89;*Vfq$Cpz(wlo3waVA0VEid37hmZ%Xx_E$`+eN~wtDIk*2b~y5LFn}Yp>CXxw4qZ9ZP8PQ7aZ!AI2d3K^$fzyN1h=kF~<>v+cfp6TLF-|w-V?Qa%K9^fo(*lX^JnZb<%VQn_;QvAJJGK)i<7 zlq<*l?}M1s1f|)=ffQ;jrSqaKK80QpQ#^yAxWYkf~e@`46$3w@aW zWOwwjZ=H2gKV)57_I!YjE$HvPd*~k=x{e>$<#siDR4izy-+VmeSU77XS71qC^ydQyUz{`npq3U z;(DV5)Y3$KD0BbWAoQ%3Wm4lET`nOdmTta3^iFz~uA#KhzI#|2)!dKwG*i;;J?Zop zV9GLn3;-Kc~=;Q(ZQHELD+7JEz53j1yQ&dyr2A<4A(P1wjW%qE;+s{ z&JzyH`P?lKvEE5q$Pq(-Ai;aF1HL-Q|F_6UNkG$rSy;GIF6L5~9puz5KdQYTTYdJ` z0p#{&nc2FLoKOvx(br-WQ$*b@o=i7Bza<^)GxhEH zu>IF8-Ck_ReXkYJX@moL(wI!&OOMgLY+$vy7GIndGZbL*A)%EjtTYju&Ke#6s6XYw z*=AA|e{z#i&~ir?zskpBP@Y-QSH1r&o-2u`n!nSJlvWqGDB_)}QZ>%t%yB?kU%m20wX-YS|WnvQRF+R8%^KUQWpmMy{I_ z6H~W+*?;Yt0Z=GKWc-T8=nk7KS_qwxc+ceVI0Ry1+zQ@70TD1>?6h#+V~5y&7vKx$ zXkjM!Iv#lQcrf{0{=Fq}pg*JB>8QleB3D<7{~K7^MFFqVTe%lJ)ZW9PzaeR2(a{rW}@P!2wB4hU4h3ZJ9EZJYTQT|`&r0fnbccnG8xY%4`^sr8m zAz>+!(gyEIk9hCeymHmUi&I!*sGai*lCO5ekd9kCZ6L+UZkcqAZ4r0%`Qi%Cro~10 zXw8do*a2FmWDe$r@g>5CICQit-drY2HSL9sK%9#0J41*ii9TQXZofmGH(wQYf~3jw zg?6pgruBt8nr$6%^?o6dl1K3VfE(svr~u)**AylbA%0G)=aze{nFW?b{B=T`DFq}9 z4X`^vf~81{%##k#3QyV43*QaS+EkgijVHt@QHLPLS_?c+SUtV%#)d`)hiOjohpVIp z^N1E2?ZJrXV41SPOWMhk0XCK4!iu3w(U50IbZ{B<@i1Gfv+Y(^rn0GNe}g09mvEl0 zN;`w5vDDKLn_w&VM=2>?V>&o}>o^TU%V>zzZoUAu`>_Lp*sryDxiWD>(0YHA0c>n- z7t!l9*y;vO$h(0OKQ9zGtDBlCTTSGD^zF>-$Nh>9lK39d#iOkJI?3IlO(dC%a&KRM z&$ji56}A>2n#j+wiCpgXYNV^#ly`Uc(_2+4hT9&N;H#K_2I`aa(#)v$9hYw--|qeHTgLU#QZWmd6q&$HY&MUz*Rku9IgZ#pW1@s<7CJ`+4U-5j{yK{zmzTdxbiOb zzn(_0eNgGyncQDPdsFUf7@Dl{JIUpCZPiYq8Xe{o@i|rQ490aq0SFQ>HFcL0e?WBtjrd-JMlpUzq;4hN$?s&1#D_NsF`QfFA{3J|zI6$( zE59x&Xk9X#n+vX|RlZCkY6-^_p|OPx?Ea{alP#Pw?22dgGj`$Yyvy#iZGU+>d$CTl zT-7-Oe07UkQB~a_a_h&DC??W7%6boH-w|ok0ztlq;Fw>q&SE{frA%Q zd4Y_cH5{bAkF%_>2zRhRjtw7rPz#`fAC{-V!c}yR@A^b!*2O!dZ*PqUCJe74fy=Zvm3~5= zrxN5?O3c#6S>1zpDTbO0=!rfari^quRv{>%>(OBnc%UwGs~5EGUHz4&5uhnb*mtXROhXiG z8rJ=8S9w_Xe-Jm8ap*VHAtn*$UGbg15d1~|=&d}2Zzoo1%ER02?scaaH-z(fNjqw@QTHcfI?h4S&J6RoXyk417I3Cx6 z-{Ou9-Sklo=z`J8SfZLsueUrArGd4tS77hKxSFawSk`8GoVw7GlExyLiuzWkn|a1- z9lb7I(twFy{ag|yX40ptGCSi`m)^JT--oYb-~PLjM4T6iQzn%s7nq8Otr$h4@>OIB zrfu3O`Kv)0jGS->@N^Cyf-TKt7N;C}9xqHG$BaK$CILVk92``Th_p~uKYXKgA;svj zj>!HU+3b?YJ+Ja{BIay%)G!dUrRi|h3{)W7`uJQb=1g4b!Ee55cMa;iltk>w|GGAE ztr5djjww@ao$h7VYse>`k(QEqhwQN%N^8>VV+9Pd2o-APo8usIdSt3Ug;~%;N$Bt zX=`=Azlei5_rv~ldZvSKOsRTtv$>wFywAnoTc2Z(bS<@}4WT?#HPn6LDx1#g*{7G{ zqO^o(Hcm=u_NB;-DiC=-EGdpF>2=w0qXpCIq)4d&gQnH?sVZ)pU>0u|k#elk-c%I; zsvLa2rqozr5uczT3S2R)RMu95&q`%#6>fjZbpgt%S-_K98y?H~8;-YcyzV=m=-&L! zH5o$@oc2HB9Q_h%_#y22emH*p!)aN)1+{3*yl@z19|wl|5D)xmUZOYbcI~~xODRlf z7;jxUf#bXCHIJ8F;O1W3P?9A%m@Fgj;c*CKbCZy(-I zfsbUl2Q-Ke8e9trQpl0dS$Oh^T;ngq3k-|=&pLWk6L=l`S=7HN6xSnsxc8>+&Gx7+>nd^{gz*fyQSol{Lt~3gYkY=5>u!<6zp0;f!elvlYVY9PZ z>V?0V0qi47(xSwHXz?cO`l%saQdGqoAh z$u2lBZzOnJbro9u8Y6m5GF&c*ze>b-0Az4!m>ne$^;A|QX!YLC=~SgWvfAn=>{H2x z8@5KYUmixAO5rA3KL|Z|#`lII96=NO<7`id3-46p8LsU>89PAy?5#^t^z-0tvM?-~ zP@cdlCc@ObjGMex=PbdLtQ>-^qpYI_z>@U0i2A;fZ$|`x07v-7Vnf6_YgXOj0AK!f zW28DPXCIjX{_NmuhGr$RE1F8qyK~)r)p-??sZaWZ@@Yyu!RrW_>BCK8%R6OyMf($W zrC3}%PDYR)oaC3NDKh?ESftbx<(F?=*Na!(!aPyc0j`>CDm3k>8*CGALd3&~o2DlH zCGI!8ej(F4uE}1s&%aT!c+=k>aE~2dFcF)??)|r7%t4x_iQH#BtSn#j9@flPO3FLBk(KKFW1Don!4M$g_+s90I$=Mja|Yrc+@7wo;n9d0 z-1O&^2W%1MMXdOowRf75$&Rs0tVxicrMfP(c+{5=Wi`*9Fa8ao{WZ#4ghS!ajB;Sh zIB~;!HK2fXfa9T0C_9?D%<)MfhM(nE`w>X70Aq$(^^Nb?LMb-lRHWHp3-=B)sw|We z>Pj)Z>>2W^z%u4LkR_thso&O#?i|}koq=TIp#LTLpr6L!1A)&nH33Zc(W-4|3}g_hE>*o?QEQEH(_dW zlPBAnY)`g1+2&-|WZTwMlkFy*Y`pvVzn}Wjb)9|o`R%>dy4Q_xpkZCiX_6Cg0>$3t zHL$!UabffhC(@9MX_|M4u;}cj_td(Fw)hY43i8RY5z@9}N@eS|aM z9=}xF3hMjQhv$mPElwJEK%PRc{F2pK>5XF)=DIy>i){VYHz=#E7o58t%U_WK1z9H2?3}`)F+|P_Q*6hjK z^P3pI$0cg=@mjrAc}I|L1a?)K_{9d{h@4LGMKp2k*;rQLuOjp3-v0aM<$q1MXaB43 z3U*3?|M!#zT*dx27P$@9EUu)j^}sR!ALoit+bAWHXN$Io?eq^O3P8!o1gZZ~m!em1 zFkxFahuzeKBRQ^!aCeTyqQs3G!5UIk99oSn3|hI>7(Ik)-g@d&X>3_$NGJ^!(8 z1ee1v#1c=V?Q%JkZK;We*%WV`sl>O+>gGniL_LuC@r2u)h|kA+rOyM8%Ce;)tEnUt zVU&q|jU46x3+2y7hS~nNRV4%zYNjPWSw9av2cbsPz|0qgbN&?nkV@>vChwfdwe1x4 z9jdAMpYe)$3Z~Icdb-Xk3s(z9mph*R4EK{s7dDzf?-}V(4x7U|lXsa2?9I$Oc$01?+`Kia=0;I^+%lYDHho^sH?^7bh}OLjXtq z5OnNC>zy!0(AALf};TLRZmL9@%`IzU8RY{@eaJS4)eD zoi$afJ(vCr{!^iV*k-#>k#~Cem~;u6oAb#lsN>@f-g32TM`g=g9b1C--_uB1{7=zMovX27QWKw(}=IO8?fK7Y6%6K~^#40L$!OsB0h?#<9 zwqH}`Y2UKaK$wQyq9y*pbsCD4lr-NhBA1&LGVg7u+g!gW=&-qLPHjGkEfe*wu0%8y z{#<6(4OtVAxp(0DCwk=gMYyrSO{Pp1vZE^E&RrLEKy|QsGq?fJpx!Pt=3_Pv&vfhq zUGE7YwQqe`Ir|&-^DqL9vlJPlnIXZ~Ri{f=6Rt=$@bagieC&6qSm{8BrOFm%1mJAk z1J&5v96A*dV#zf`rK0-VxL@BV0bT_PA`WV+JrzC^LdZ`zh!cIRa=KfE+n)O~F>F2s zX+Xy(_Nh>et2tq{Bcf!3D5A=KKu#iIc)ih(z`ge2_t0ij=pf%c#=h=k$$`CV7q*n@ z?0cXNNM(A9QQZ19NYcnBQtp8qi`H8z_w3Uedk}yWJ`>7*X0$StL7rC{Qp$%C?7d^I z+URCX?+fSL(nk2Vb`k~9G712FT02~=+qrgra^&Iw3~}qXz#|Np_P_RrN2JBUWTKym z&33Kjg>mVmu(&Si2sgL=_Ubd_X};uQZ16+0&C7 z(yaJTQD`p%(VYj<2BUE#ZJ7^Fe*z3WdU|cq#^L!ex{G2CNpY#`eDW0VdGqi z9cs1vJt`8h7aieb9wJ!fbGzT0m*e&R*uS2cD{5F_B@HF5j(1(R6$Xg(!z)R6O%Wq} z%$N`|m`C1TR39IMy*tIk3j&j~w!-k%n1<#MpwMvWH6<($yPc`|sPnxYif%u(Vi5pB z<08ceHpf@siYPi0=z~v95F)5hp!`jYutmb>lUg7oWU&@ok3hSB(RGg&)HLwvveusHG z1@!H8-3ngwN;pRYLlJN^^Uh23#7^>pyZ?^fqB!p)ET!|W#qs?L?Tn)kYuz?Mlru9# z2vJ_$2}w7Scz^u@XvhN&@LNOrf4Nyf#TZ4xzK~Ccs*GD%TW4`0LAdTi2uY#jzo}G4 zOuz#jjhNjQX<`a?XFR(7ea}5}p z!*~6|{Na_cc{6J%CsPy2|G@C}-uQO*mV!L6C9X}wrdh6rttQKywGbf~a4e>}mU;!2 zMrVTi?2QfTm1cD0eeq50w9R5CML(S{yA)C25kr|jDn(lFU z;(^jYX@C8gO?m%5Y0dnE?J_%)7v%>>(HqW-+&rjnixAlz&tOU1xM+lx&g%=&4L%AD z4LvM{U25-sl`$$SpgOG}lNeB&p^t%|2n6yIL+ zY{Jmc5pKw#XK3k)9Z!@PkOmCcb771i|F{(V8LA0}C`Lgkj@)4b5kiS>$H?`cOa()bskWcg9yySw|!mIV@o zt=9K#PklWY-+ncOfjo+#6$Ti37%zuJkr`0mFY2gElkhg1s-S{%^*;B{$q0BA*R$-6 zw;5Mpo)PjAJkOP_D0QQ8HV`Y(3bE*KdBc`zBNy$3S`}8ew@q(4UHp6pH-r{ze0y?| zW=Z!qGuJ^l;eeV>p2%_#lo?@~t=Okp-}*LUzxCnT6O*7hZHr`;1^EEyqv?O-2sEcW z|)(f8L0GZE`R zkkp76FO7r+X7vVsYGSGLBeYfL%|O1;G06zoM6m5Vo|efjd_K5HJJtvUQzrEN&|LEz zMBy0=*2LpuU4W=^RnlF%;e)(+dJSG&#S-~T2cb54>_kwIFu`zH>CqwHiZxyq^CQCO zw|q#HuP8FGwakbP4*ABp?+R~MHm8pkB5cPyu$*uswiJpgcIZHcO%z)9uL@3Hcg%4ch&l^7O+!Z$r7I@CtBX~0>} zJqQ*ifC(FEPum*3tQ;KALCt24^-3HDY0>hHxocU%0t;Bj{Fbl6&z3Jcq@y%m_&t6~ z-kUX^a872jyAL}Y=Yp}-9x4y+@LkA)HVK<{dUX~Y4%Za>+5{Boj1mE&h-&Mh@D*qG zt%5x4aymAgq4iCG9;4vW93aRavc(?iZHG`}jqUG|Xvk(TTZjKw>XHBkG7wC~EE<*v z7cB<+9{#k0ixlFBiwOakH0%jMmcf~VJU5=j0|mU>*!X!u41nP6QrRgy-*n_@~WmBs2`vCutf3_XP@Wb{X_FCu3D^6 z+h#emBQk9oRk~i)W{Obu_YZ3@tw|i5;0=&X(%Fp zyhcbd0hWi)GlFVO?x)yfN{vhQ$s4XDuAqVKY2jY~WHdy`cc_w^9iS2^y_Y_&-ZaX=p)t_roSo(T5B2 z%1yd-t{&NU8ubHMrrwgQI!9ma=K_ak4#&`9Ssm-cW(STk_%~#YETIx^Sc3Z#kYvSK zzCd^I2=6v$Q*XK9EUq55TlX^K1Sc-*tky1W2*0MD%L%v!uP2bM>ypker}CnkXPoi% zEk}*SBZiF*yJgVjW*RuBJ+Y8cphXa5T4y@gSvG&6eCQ-o3G{ZRNVIGcb%^SBM)C z7#R$FvBgGnP4axk4`~n;(?vIcrvL|n6LPQVIu}I2`AlAvaQB(!i5*Kx!1;bmRrsyu zv#N%mn_G_66<)9W!xkmr9U@ zCixlT>tJ$oV3!5S)yu=~nO0csQFl5oLORfZJNPE9Emdba?5I6}L~FA1_F@IZR#gwO zqYH4SzpT}|)lfW)Yt_$W_kweKuc3(t`j;U6l=0<~%5n%yx9i^0s}OhBmg0f0v>$ti z(A&i#BQ_fKgeN;nf#8!XG~OO%%>>I4P^>i84%@pOfkj)-XbMIA&8Ibf=E&Qm4$x93 z$cTY3kh3S=*DpKNPW3?M7@z0D+VS~a;Fyy{5hFg~I1*fMrdZbQbIcYC;bU6M^3@r% zMvl5>#n+81d~>H1{ZK@oy&1Kp8!?^%_v9{@+{+4(cqC~}3%sgI7zp%TMoF$*Zt7Td zS<#MX?9_nBvkJt(JxHgSsQWp5!WSv*;dLl7vMzO!1vQ-dEI)Cq=q5}*q$L1dfQ(pp z3x`pRS;Ab!mop7$nUda) znjRy^eVlOiVBTjrX-oEi4Fl}qf08+OtS(o+3VIbs zNp$|)I;x|8@0(G;LfaS?vv6ThwkCG*BoNP#N_vHLz1ng5HCK{Az#;Sw+?KK&de4J0 zB4LrZ3^13vjo4Q#ViN@az^aB&GLz%06f{YTS^JzTW+7c9$Bil&5`9fv?KoMymSaw< z&D+Qn8vcO?ArwDxF#YiG@WQwceSC3&Mngl>zF4hy3P3v(u(boNE&g`Fxlg(Qgl@$2 zFtKcPDazU7+6Zd0(Z?iw;Tv7Zg#ubBIgEVV(;<@jX4_-X_^PDx3HVn{RU9AV=VCRh z9_1D=2siIsZ^LiV{%_(X_qnu5GYNk8+#|6Mwf7rb^NvgU(OS$^N|?^pM8nV6_wqWU z-(0aDJOtafV?o@?{iP<~CTb!i2JxbSYs!!qj? zH^3AY7UD(b_h!Nbuwa{8B+9OtdYUQ8u9c|FDsdXoVWA}uwSZniDgk^$P5uNBV}|PU z2`@e9ll!~Hm(_-ADI1e~Y4m$l_+|Z70U1>gyldvPT>cpO1cS7v3R4|6zlvQ_*8Iux zJ%vvxHRNiQ;CE2pU!~OQ8vd!{K6V?Qt#j(;nr!Euezw|&s*&|oi5;P1y4!Y%akdYc zZX9*FCbY^o!nN^AQ-v}(KA0g6i{ZH$6F#&GDlHAl^hMtJt*tH5kjyt3_lk~=4tTq^ zgH+{WHQ6dW)+NrQCxSQ_M%NJx46LIQ)Iso8R8wKYk0oMYMb-g#{9KAh;QJ5%J89+= zU96E&3)k#x|0msUb z!Y+CV!y?SF*^fh@)T(gB`YU7ey>S%WG?{6o$A+9q{dLs^!B7E?63}Xz*(sZtb+&6? z_W*9J-=F&5@|*@m+X=qsDE&Ix{&@?({T8w;*?bjC`Zv2$0gP4TRd30-T3$V6+m2Uu z2Fu>z1WZch{RrhKhxt7?+{mcLw&VcI9iz)_{&siCPv}Dx9uV6j!$4aB=6Y7`=E&bw zeI0k(k0`-x_h-uWBQNPEBouAlZ;g@6#8?0W&Z`2V3rmyI<}tqkb~yHz#hDtq`RC9L zZ6jJNC<0d2mSz*ZCbVQ~{0zoQUjv!tn(rLr6qcEXF5!;!P(m`&jJTqb^3i-PlvzLQ zxBhb(cn-^_+pp$?~TjQ*0!eo6h3EWd6r4xeWMVCznRQ>yl^ZMlReu3PcN(B zU7`7udu^ByX7TcBg;Ccn6!)915H;wAj0!w6@8%?G>l+QgC zEylp+Oc|@F_gD(k-;hkc$A^7d{j}e08Aq{d47HT!qYGH@FO*)+peL!JAudH45=CP1%&41lQQL=#m#&T%a93LT9umcG~omE1t}e`RTL2ki^IBAd{mmZ)fs z2L#PLMj%I%^29~1a-Ww+nn%UwH~ih~AT=>z2i!jS5_1lfbQKuI5t7wD5^0pLk-r>v zeMR}H$p{B^JB&RXll9{s5=Iz=f`;aIv-R=f|G|%g;LiYfLEAexTt2qDo;o$TA>)?x zuP;ZsUqVGiz@(S(WGCs>XMC3}-6sEY6Z*!aAd-%a)8VN(h*Q~sDYwT|i<;bG@aKqvDCv+wRPP7gGt-@Fm^3AqzCspbr@RYa(ggy%G z6IUBBs7Nbv`@c$ezWqR=eVKiO#A43g?=-1`Unb~ zRBM(6&f$!nC&a>*9HRkmyHD-iRmQO$wWw#-T*h|RBVKQeNs6R>*#~qsXYA-8*)ptn zm1&;lTdo?k8?(dV<5P&b=JL(of6hinM-fHFt9g(sRx|dY(fL6uUEU8b$tq1(N{E5e zxT9U3q*_Pp2`a{G_l=Dy;;vSl=}=8HnWO3Q`-fE=zPDeE-Ot5}3)C0vNGt(7^w<0I zyzb-lO?V%DqIq!ZKWsezbY?>v%aQ}Gi{Ta3ob$AAYcu6NPprHB+=%Q!X6efSGwo{g zbetmw@OZ`RerGJ#JGJUIqZJ9=JiY*T4X)Ji2WCVjtvC5SKm6xXcCWEzw!eTy?OsD$ zPjd^&Fh3~Z66mwUa@cNOK(tzF)+xuWbcv{dP63_Hy%cupN$pmhwK*G7&eGBtX0En` z@JL8+T828xVqgr|-VTIK2VjaF&VCOzGqn9N)Mie_W*%1Dm+@K8CGGtZPn}k2^^Jjq zws;WzHIv6heu5G=hBCNUBky8eI}HoaeY~gXd;PmX7kqU<$N3eoa2vioglBN(tk+VR zL&UXIM6Rz91O@Wqvf$G*uTV_GL=Jfiw%yk4NI2Z`B%11RM8A)n_Wabym$KJiSmSuy zN1b~Wz0PaKrjdgGmGW(yGNw69gWn4{GJdW4VQl1SOR$-Eg-A`PC|gqAGMXZWwUWQ zG(r3OyH%|JMVQ>LRwcbDJg7oWgj58(63po6!<`T(HI-bmN-pIE$_-+?cj3UOl)w6wn(c!ivA&gy!+|t`k`E+obA7Oej+R;;=>ctpJ%|zLr(!^2TID>{S_c&n#} zg^lgn+}gTQGKS=5u`N*SsN6eyN)DI->)+oMNoM#GmM^-Ls(A&s%(5FBp+6$0z}J7` z$>g1P>X!a_-=gko#ugc2)!9xOWBeIHgaod?TyZ_3tEo6{hl~j=Y{c{fQ9;}WRqFPnQp5c zYMYUCfn$woT?RXIQ5L~cauV1;$97*TAiS9)6|sXuX@ab-uSYq zFRmfZO^bVadU}#&yAZ)oQNFKf27XVvU49VOdhGS|^?7k7=Fu+S@I&jan^qh8kSvV#e0YgUAA4{gnu#g#7ceRjz|>-9!*FY_@~Jg%aTW|N6vR5Uh_ z*osI8t4L9RcyfJaMu&K6QGb(U|ED>?_dR5J+HrYm*jf&9UYch45T@V#4r4K1`ckRL z-u~f|0m3Vxbb3%QCToREpnD*a#yCV7ln+bB`NW39a`~pgbBniC^bs=f_~iM^4@!+q zwd*z zhF#I`qI36$v9XB%nF(1(pX0C7AI*V`KVSbr25nw>0xxh38cfQ>fR0(8nyxW3bi%b@Pw~BW9{w#lJnC^b>+JZCM7tlHfN}l zae^#4BF*$}y)99_ypa!4iSi{zS{E|`XJg5a$GDG2zMnsTI(tCKq=RjqQ#AC)P*G4i z3!17kt^s=#?-}h|eq?ca^_yLTNpKoe6(=O2^#h@{-^;g5{}=tU%0>05?W}Lp==g%0 zQwcrqw9`I2%BJ?2=Ik=Sy#=p2n~McBH6$Hwb;4WA>Z|}$5oqzv|3$nYhmzOi%KB6I zMgy|9j^xU}SDT#o+|Iy+E7s!v_4UZix{mh3B$z_gd=TcOBMqWzzWQi=X)yJcfJl7L z{OK4Q!wy z{2y`m8Gp3pje_lEex_T^+l+*JN6waR?pA%gqcZW|^KPoyZ5~l34+0Xflf9PtYi96B zo8v@*)mde6P}HYe;$I}JEb^vLPQmOCCO7U%g<$KY0J_I0;V7h88e7zA?3mVb_7zUg_9{IxrZ@!f1 ze-np_N+zK)Uv*x1%fPbv49H7{S2gX{06og%IBR?NJxW3+)5R;hexiKUAb5?PmdNJp z4-Xrl=f$YFzMtka>lu596&cRn^c=J)U6q3)qd*L$xuRjJmnsJ|GOFoBhD30;r38K# zQl5#)5Jx9>noD*S>pe98A`?`SfxJ`1~2I^6W;U8B$SH>tOY04LuA01ETdmkCPEeE zMcx4G4=Ywv`C&Uh1aL#XIqi=^_L?L>LG=2c)s0La-aKL5>8@MK0-bKP$Hvg=t%}TV zLLWF;Vfu^Hb|z>=(sYx(X^CwwlrF!ZmiKENU5`htGsm=K94ae`S_{BPr*8_U^|C7s zUvSRV(PB1p_NN8+!vSsW9I4|#pBj5`xJjbN5-0wbgDb=TlqiMvhPWI^fw7rDMK#~l zwfun3_o|vbURexJ9EueidXGr*yoSc(dqEO425U!s$NYqiVa4{|@95NZfSuUS8nMyi z?j@NfVu%+ap3UFuy)_53;b?f6~=tI;#|Gv+v`u79XIx#%;nXVTpr2mRG*XNoT znd4kn3IfL9X4fUjII3x1%Okz9Rt|`L4*ll zn8|4HsvY1wKts7?%jEvUYHE~-mY(=@K-pZXWEO)N`2)6EGT)jSg%3%@0&uW&f*WZD zLH!F6F)>FCZfe89XaGSmno)+bp}gIGx&56zy9`u^qu6-HR05G+7l*hz$9r&Yx*bt< zS3o{q?A#l=;86Bts9xq#zOJf>apj*z%Q_QH6WI2icSifSgBF5K|4hT2O9LaD#7(kJ z5hJ#a*2ALW{k+{@WyW|%#X<;yW|_`z{&W=|d}~KPtZ&ei;Q>^Q+4pI}AZH%I^eeDJ z@$&KE_doetj_0#g(`8i#;`Uyo#5`!8RKdGcfgSZpr(a2lU#1Jq8{`MT;cyu z&-Tav1MWYs4Mt|mx;^R=EUzDAS&4~dMpVzVJWpJLhy8H|2e(__B9F7ljY5vH=%q}p zf9>+3R@{^2&U$Nx&tCnLj)jrQPh*6=aLd(g1F4_Jj|e~KFz5<3XP7XiT+|c zuku|+>u^PvF}5LJds#wO^-X#{T@rb>GP$9sC+elUVHF zma>G74M+P2t1SvjX1tAlLfl@E*JrCJxz%^?Q5CNPEHyH?zNnBlaHTUY6njA6^$hC! z{avquN8xf*3@-8mOt$j9UpS7)jFG|aHvF?psG7Z zK5V3rdBL}TigC38Z|F@4esBhFCmQg8g{Hxr>)?(ltE4_&wo=UGd5s!hE%q_erk?;Vo?FZ)KB_n+6!+G}eOTTRvq z_;iB&eSZM;jEfXM5+KGI&^Fjyre6|>rVB=vJ#`3~L9~*I`1(mZjIUN~J5E6vKVt_O z1IpWib`=S^IT>(`C4U>IXS1-V8$<3d$gW%jVDeG3hW&b;P9MmBu**#Qakqf!6bm#) z$+cG#-uPsz+;Nf;uKf38pe#F>rzd^fz!QH63Yynjg9J759wcih!`QjUQLxHW1GE7i zgg6MstUE#|XnkIb`6HK!Zo429t@IjD@1`9sA`jUJ{%g^u8>=9q`4L@xi}V4a=zy)DJtwe;?|_VtCq zoO#*+_8mX794HYpJ2Lphp9Baoxc*zN3Lt#%S>0)b)8&v4|HTCb0zT_$1bN!Kn%;{G z$yXZ8=GX9yus1kn$@+8Y4ANr=^b9h8Ygy7-Pc=l+A1M!iX&{HMcgBn^5FIWD0yat# zIi67n#Tz}xbn9KsjP`vqxBw~PO9>gCyonYCx==WqMG`0vYBZZjY-amFb&Q2rlMS4l z3~-x)Qzw^mlI?7NpX!GBpvPH-8u}nxXAs0%CC+Iqi8DkD=gn)1KX9C7dRF&y*)!%# z%qKyK7mpsK6VoX)gJrfU>{otkw}=~ zb$6Fhy($hzyI?N0OSpu5Rx$~#*-$v)SEq=8tyK4PvS*A3sB+DE5 zn7JD1BYNIWYUz&|9ULK z!Jy^lt}}idZFrAt*8OKSy^*JGLBIXc1X{rH*!l11jNWOsW$(*{dyh9u+C-Q7Qjs`g z^eIqFb$KLK49U+UJ}Ch7U-a%Ot5;6a5e^?wR!P(I2tR-&|%1O&rx zgRZ|H;;iB#PzX&;ZTtbcn70F`Elb&gMe0&m?=cHwGibP6?tt8E^;#-&w>R7ZE}IPJ zjg;f*HG~~oKptS$CmZ-3>ZTnPq4b+PRoVo}>wQa)Z+!eqO$kX$j`}~}0|oMs)q%oM&AX%T6P+foga`Ni@P4c@jH zy};u5tW6jjGbrkJW51Gf#HV72PZPw7OfbK`Z=MxPOBtlN-dm~mLW2{QR&!!-K=PBl(iH|t_~I4hW&XQFd%#V!vh58==pUQh_ZBi z@Ncf{sBa*c({%3cW}_3vfTs+aNr40vT1<8Dn&JxnlD#oSeMbH1k1C)Q&3QZRc|TSC zd;G?nznR>=T?&-S{n;Hj2ie6d0WGeWuHphoEe_D2vQzV?TfS1 zBlrYoo?p>2Lb1j0WCmg;8ghtMTcr1!hL%?g&(V52&YP_sy)U+)=xLX)%P2eO%7}Xb(n0tW%AOTqECrA%% z4^lK}${TnLHlQFz{ef=M@8J2gW-C{Y23-Cm^@-JPeQ;lv)~NGJ8-npQAhn}#a?%k- z7;wb<6W}}rSHNXk)yfw~!Y_MRWrz7mrj`H{FxtK!d&}Z>Ox$&%K53eqZiJD&fG=gO zcZSR1j*>#CfB-|Ov%QW-O3Tg}!j&NW1ma|*{ElsYfJKLK2pgSCYI-|0-?-)L`qUIm z?lyqy1b~SC2XY%3{*?ruWL{*zTKuHBTqOFmHh=GkPLSRp<>ckNo|r^CbEV?qR<4-T=lCTRzcfvxLiUhDbNQu=jO{Y2qcy1kjdy{9&V!TCr+j;@#m7IXeOuO$v04lNm(DU&|3uyPpywI>iDZNI} z#OnRnLW?Oc-|B6e%{rzT;Z5?aowbU-cfTs8ntf9Al6*6;Es8NZgx`$E+wlLQ3tFrQfn zdUuzW9>EJ|uT`|w!M=n}Igiq%VlgaO*Y3Ky*yOdj9hsIE(4+}g<6PQ@8=L&mEePxPoHl>Fbhjy6Te6EyN16Wum5n$r@jJqZFbc$ zF3(Q=lk0FJj^V=56l&X2`~9u{G>L`p+nQKb*)grMC` z=mE#Qs}4y5&wn06JS^JA)TGPs_eku5%6WI?m=hjeHRuefro> zQuKS7%wSJq?0?eeSJ^CspnHAF{dh_U3=AZ*tU4tOp3NZ#43b=8e5Y|advVZS7T9vw zD2$|x?K_aHRS!P5*=*5KDUuBf=Zl%JA6Aq<_p6YLi&8m>gQm<7%3ui^{uRR#K{%yhdQT6uz4p>jOeB5uv)`tHvSb0qK@ZYR68JUaw_I%s| z#Jh#G$6`Yrl~kqk@tyGgj+NF<7()L`e3B(VQpg&G8UTbziPFp~ydu{NIlxy}Z49bnL~1J`o#(TM3P0YHAi4)Xp_( zemXus{BIDLGpI(daKnIRiUFe2*Oyf$j*#@TXl&V8a!j{u-Mrs2 z2Fsx6KZ)--w{zx?-*5;NhctGdY*fJAe(l!IRX|J-`275BgrMUik=m7NlMy@^frTab z*oWS&MTdQ2i~?2bUNh8YW-Ur0R5=8MqjaMIt$E7mCMr%3y6%5IIe-pLb1sjyx+en~ z9nWhhrnHaGatwuGHYXy15n7Rij+rsj@%$K72LRWV9&~_yYT3??V8tsnC}TAuH3)F- zkI-%EzPQ=Hc~brVk6nLD`?a!&011La&aH{vxfWfq>9-5!>pD7ozV&TJ|k zyMXjBz>71QzJ&=c%j?Ww>Qy;F2p-iDa+0a@vvSy29Wk`xSvn4#8p zt<-Fz%(9dVIz8y3+-~v)ZzpKQ8>S(imLq(>t#p-Sa5`6ns9FNGXqc%#lFz!^9=3((}F1=1h`YT0`D}1 z@YA6|miaI7PH2(_5$)DZR*>34XN%{9cANSwsRu9be|HALdT!JFpVE#3_))LtzRqdR zg@_0rIkn}tbe-FJ19o5cnNLs%>@YFY)FFGm$G5x3-9O1S6E^(mcf@08xH60`{}6lt{%%?czEs&=_;WM81Ubz~6mjuOmU}nWLQ2pb z&EwB6^|7t(HfGY{WMau$B3V0jXJ8OpVk~dvx!L4 zBc3o0Yun+Usy6z(DnzF~FV{6LdbzmVUI{)W2|k@J8Tk9gvs{%@ST?qZk#RfpcAZvt z47b>>x#a>BT6z6RAygtjs&7+(8?mu5uZJ!>~jd#s7UQ`?W%}+Jf)3%@BTJj zf^GJ`#Qd-KajaV(@TcQk>gqG&xS=O+W*{U%FF$wlc3mo>MdTG7nbJ7%`Lc>zqpH&T z;eo&Aqi%%srRQVb|5-6CK)m$ryT|}6L|z;T-`96wg6jB^BBRGFM)J>E#L$KMinbn* zHlCb&h<6sz76 zGdF9&9s0Qq>hi#Ybj%nTm>H?P?4QuOT{Qfejw^4Zad-0@N*XZ-od_h4jWU1O2>-F4Z1T0o_s@~d<@n!I^(Yo$X;P&*JAbjyiV zv25OcA|NF7VXHpdlpLsuS)GxyQ+kxCiA*DOV(iOl0$GWcIO;yKYs~6k)%! z6~QrYnhQAV#1Y`Cgb`3r)>e5H#WtT9mDPOZ^{9)s?femF6El0;mo=f?w1hNsLxV=l zecAJI27EAeZJE~x>`05;!#NQ8BLDthu!kQ%H}~U!S0yaunO^oFX{UMLpKY1)_la^d z1Q?N@1^0(kH|GI2%9@I4<=>-(Wdm{XtRYX@z+SMX5hlIy71e4-wO@44JIakR8TyX| z;hTj4*2UhLw(3K^FbD?tK?Gm_z`_?wqMUnOSDm9+J|fP}OL@^Ov!+k|0!BS!k4!$YFscFLRAK50|1t#b!c< z{x|QuZz<8}Z_|%J$^q5a*lg#l+Qk4}Cik@i9xIQRT}YFP(!fgzTcLj zlkj_7-bAs&2Ag2|KQyUlQU6wJ+LF;P#icNumhmYMmZ1rvyMx9~855-Vjrq%#G#U57 z$0TdT$)}twxNPzTVL8eM)!;gf5gzYg-SGz?+n4S>dX6;PMDDxkynTOr5&Zb4=>N=; zzvREtuQQR&QN^Ai=WsZg(e2*3M`FEq^|;wy02O>*9OF8Lt$w|0fw?1e zk&snUlZE4pn&>wX1pb+Uhc~MoA{c;S_}2%#a99{W101mxPog(vqAaVYm=4yZq7zaR z5R9LJ!4}uYCHlvuJsJsb+Y;Mj60WppH?{ zr}+Bq4JVdr#@j$#y*Y>EPrYrj%249p-TqmS$2Y&ep_w#)sHIB6QvGtCG?i)TgD)X( zsdEx?ILq<1eiqOQ3BRJ!lK)zHVwM9=GlV0vaIp$S31UqhXWYtpLg z#&&NY^iSaOdN$_foRR<=`@Av`l!+}8^}fPw{>JKp(*O$)(7MxZw-H;Bxa9LmaG~=- zfm+2qAxc8Aa&Cwn0|v4!-x2A}`Mh- z75HhsLooOx9oq1F}DMGkKIOlwRKI` zJ={D8->GjzaDHub^IoZQ>jo8aCS3YE__saNy9ja}k7O72u~T&T^N*?6F7xLe_~xP?ftPV=ezR zOW<*c+3#vT_i5517Q^dJgVFu}>blCPsJga&h8!4#p-Tys78t+>5QHH_0VzS07#akn zTYBh5L8K)gL_)fxkyIK)c<7KEQlw+v?a%MWch*^J{>)i>=Ip)ixb}VBmsftF&Rw(M zkw`HR<)b*vfztzEne^<}M$cS@QV&zVqp%nK~EoD>AUE}%J zUCDQsBwf!c`11EK#|exPKcc+9`hyiCujnBem@>vs!9a-+-<(q)!(`gR1GPy?aY8~p zisZR#O3i{ zyye|_$fvAhgNJuYwv{-CO@xRNwQr}Vt={g3bG}uLA6j|#D0TflFSU`-$CNJn#J99& zF27aN2^8RJV;JqpvLsuM2bTs|x(5zZs?$6>rIQ1N40IdKEx*gI##_(k9h>&MIRtEu zhdT4kHGg0Oc4qELe9*{hIT)0d0Ag7UAA%qtGGV{l$(q@T%SsU^HQ$$v=a(+fj%qtj z{&@8nq8P&@UgFOE6`N%JG1tpY6R9IHq?6H<`2ojWQH*C+pifbjI_|(8KY^q}_QkUE41niEJXGilJoTy>Q`-eYt-T^+n zWTW*^CXS-R#-u+unHu5qh(`*yq*gEa^TO;_{!?Y+atboeSgh4_v;onT=u2_k8thG$ zLgEwwOoxfNcG{37&BvSmySml>f5c;yrY@A;;Nt=OWSey+fd{1?WF_@uj^aW!5LOHR z`fu*JUNd1lT?Hz{Sg&;`3$8vG6>;|P2yy-Dp|J6L1$`W3HN5Wa zj>QM~tg*3tq8PTOETj(GO3|hL0jD1)`%cJoJ2+N+zunn=q zEhk6|B^7X35p#IaOuD0$w+2gZ3^_0J)VzRU5<-PHRL|9wnnV{om>O%cG|uMkQQjZ2 zw)3W93}8^BigJ}+I5VUD-O_TikQ_~`^n_$6Q|7!6sM!z#9H*mKt21EKXYdcHG8Q&` z;os^F4wdJ^+5IK;Fqo#WWl6rm-G^koH+jJABnE|W&*Rcz?Rs~T_Nz@r4=&YL?F7Vh z4N%{(3z&Z|KOQi{Athaor}c|h;o)W`jdu&D{AqP{9}Q-q@s2|>$1}U7m@lFs6b~%!&#x*^6!T86;>Wd5EDMM^hU>ROu*+VZFT}9o z<2^B?SC!n`5-X(Ko*xWRwA6WtgT`I+YUO*#^rFSdYKDv4i^M_Yr(nGOrLGT#bq;>J z7pDiZmj8WsOo%0bI>iVj9Os^DWXaBgYRv0ku(MaA(=e#>Yw*)AZCeZrFOVrn#_U7_ zXN&JdNw4cnL{mr-zgz7D42+oQ7qv^jRXwwqF%^51L*HT5ZG=Y=bE_7$(j}mnO z1A5lk{r7t=6v5d49xWZDM%()g22ofW{UZ~2h?{sr&&XJ&A%%iN*NOQCNL3GFw%hdn zJT?qcb4O^a#ujzmo*8f(5CGf=?=%C;RAywx>SSe1=~W`OSSV=4=Nhu5!Lpm@NCPa< z9B>kBa=HEpJ>|Lh6*RHePhU@`tkj3FM4Af#WPkp*3AWjro+|$T=s2Mc8Nq7UxP#nS zVEgcAi(WO0G#objwn{3qp$sgJ#j0YX;dmng%Y3Nmj$G?J4IKNzv5!oDW$NYfPkm)j z;v1zmUFMhe_V)Ox(b3l!T*m^-_Nq z<=B|sxHJuDp*SIUxF%o$4iJ@YU(ZZuUG|#XI_lpISnjQ00-YTUS{Qqrvvs~4SvK%+ z&ZI^zcYF+?iLes-72tWz&bC;t^GDE|{o~_IN#~{H=~{bfx5LeG`F>}UfJ)0oQq!-{ zCkqRU%|Jp@ZyXL+_7oTdM9_l9M^Dp>ox*r-%qEE?Jrh~54aLRvd}7Dg)9-s%64c+F zX&*-9zkcJ2lI^#Ynr6I7RxTkFjQc`rW@MbE9YuwDb>6Y)1Z3v?{tOw`+MRZ;9i$ev zlt}oSUcn*c5M`&i$jU-{@MV5}{s$0981hHu@^Dde5OoR#{h)(|iksf1U>R>)m3QL3y zw8wI^Y>4z(wp(crR3L0U{8Ld8o3w}B+vWP!&w3TPlP{`txy3XW9`DgvR*WGDpqUhk zdrYY{e^~PAo~fiwDGfp|j2=u48l~jzn}xhpL5sPoI{EwE!vxGz;C@#o68d3BhR`UK z6Hw=wJ5A2QU#x8x6~z%mn6fdWQFyTV84-m=MH%6k^p$(i3B9mL}48SxKz`x0yjG_lVn+c88}PUVOBnjSqJ3qN&e%8Fs)b z(7rOQZF~r`NYDh}`P_uD&-Qa^&z&s-RMZ{*-4A33PyYT*NJ|(~kCb&??e7{detr&& zPOAc+`@a|2PY9N3gH3i|Yn6(us-x^oQ%bq5E32g!`+)anJ+?jjb&Tb}6?{d4LGkSY2JMfDBnm%~bW}f#)xfZb~ZkbS`hR`M$1c*=}NnF9twyAoGj6VPAiq*nwTmu6I3Etz+`bgbhgL)3$l|Qsf zm*w?kJ}brt?27$*tf-U}KOhz0)9&=GZQ^iBjkCr|eCpGu+K~zzpD_f3eDYLE?O(tD z`zVP^dR2fm<#qq-@3&bI3w*CNVI{1a3$Hi*l>?rC@aQ0gbae^A5l$=q5FoNgpzrHN zGJt30nS}67bGw?|&D>z-z;|?4Kt0M8P^2E(+}u1(n%ggdr-haGB)YR!W&&+g5xEP8PPzPSDA%P+~-MUibX#Rp)cg&-|nVRUc>f z+>ItW7WdW)G_$UbZ%BJwOtko&doKyK>d&}pGNYY#!9p$PTF2p{cc$xhMTZVRDW0vM zc>3p?ALbyaqoyVjDG+Vi+)87!s22|fK+THAPnUdn->j|Xw(kh_${enoM&j(`$3VeI~MbVL;$wKW3UDgC{wiR?U z#CsjjdI|$cVkm}T&dYF8Oot%>N;&Q$EQg%H^fEM^Z5G?I`)pM()J@O!J7ZjUWc!I; zM8H@n<+quGjzX!CN1~!1~_XA{PSLYxPkz70Ueq>s5CUOU>i;fQkON$N*wUM;#11QXOM4+tcckfh< zZC0csVpYhX;MH(X?(lg}_92CQqZGv|LXN6ChB-|CgtsUv$Vu{kGnRvsgMf51u}ydo zOf11;b+VI61*g;6>bt9Ij7AeHrl{8&;Lvxs_3)=*fRxLx2>k)ZKxc)aAiYCc{Z9m@ zbJF4a_JLKvllh(>ZEOCRmT_Xgyu>7pU8%gGloRngl7^s5sM=cXaV`A#vHJfBOjEy zxx4$7gLZ~*fK$2p?8bQEqyRS!(e%X`4gdZVOd=LqH2D>{% zKDQ0EO0qWMg0P7Q$nVF${l&B1^D4+|@+*zqZ1a5gI@ z1By{Jg9p-M2bTAL;eYX<3w_Qu3R(^I^-t}e(Di9&-g_(b^oH7#_OIl6C=!MUx#LIe z7u4kypPmFGlVU}!ln8b1T1e+~6`YF3v=Y2%b@0s)77@x6n{f>kH+KI44hIz#*;3JT5m<7x~l=|1(pT=WHFo_G_iDD!yAE3NAXY=P0+E&n9+!4 z*5AW@=ZAMM6VgD9JEia@xw*MZh6%Ud(<)Tfz1OtHehhv|p+y^GGTwgo zhL)Q}an9|ZHB9GjNCNl|<;HzC4AE=KkXz8Bv1it3fx1%MtGg_~J#NdKfq}0$9Zp~~ z4krljan0L40qLnL;+#&6vxC4UJq^I0&*OhqTJ^OEs*H-pEw5U?oRg4)cdvcKsL{iSjfF+j$WJUQOYB0Wm#l3zm6r(2>&7JLd#?{P!Gi^!mtMq;ZD6{b zGhAzNa2H?ZZlMAM|Xar=tl663%ITGRA#8tU;v%cOXUxGDO>V zgk9TV$Di~Rv$C?b>S}9`@`BJyPz>%e0}PL@ep1=FZwqi0wYPkZw(bR7ob2c5-C+n@ z+)Qt8&REn8&Vc%_>%i|sM9X`5eX#%nrn;K4rH`wjDSKQp*A7OP7%BmZ>-4Ff-eqP!~ z;*Q1giM4|dpbZEH2T*5eO1ArwOmL#FsH4LtzFsv$%>LxRh&Y{rd}UQpH}Gp418*aJZ;xZoVudrDEHX z^4OXj9v;>rs$*>q%Sg`>XIOnFah_rvm@1Dn>!i4o%c}~G5xfB6b&}wY`zdJB;Px`O zZ^b}JMO*)VdfR;QH1Uh!Y&_x5xTrPP46;Bh5{{Nmi}&n_gG^n3=(x^xk@tIO{p@S3^%vFMvQGl2sC(a>Es1 zoDaV1@wr5;H7Z(c}RVrXNb0n=YSI@ zY768)h2%uH1yOliZ#NoB*BjWL&{^GOh@Pb&B6#j6Yf?9XYaX4O^Z#5^eZE1@*1afZ%1@_Gby-r{ZGQ=g*%D z^YiiT*JDaW!#kebjLJ2n>mtZp15i6F=Ytqe(ciQLaXOnyOlmyYPu&XI_kOH9eb6TnVAl#Z@~b3I`jk(P*`}l`m#pT)0nco$dU7m z5o>G)WXbr^^X)p<-aE{7$e2#4rKCiSS6DciUqHbA{rmSvOH1aDR8%6x(CGP>b<;P* z(+7l956s(d`~Ag&$xnIMsmy_MI2jn$#!$}M_znf$$s10+(?@|7>Z^QN9@%Z%uxao$U-R`pcy=Vocp; X{r?ZpP_kcw2Ot$CjR&O)ra}J$c_$^Y literal 0 HcmV?d00001 From 299e9c9c33c7d1c1423813c616eac6085c67b714 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 14:34:51 +0900 Subject: [PATCH 1666/5608] Update bounty line --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 18663353b4..2c330e403c 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ Before starting, please make sure you are familiar with the [development and tes 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. -For those interested, we love to reward quality contributions via [awarding bounties](https://docs.google.com/forms/d/e/1FAIpQLSet_8iFAgPMG526pBZ2Kic6HSh7XPM3fE8xPcnWNkMzINDdYg/viewform). Don't hesitate to request a bounty for your work on this project. +For those interested, we love to reward quality contributions via bounties, 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 From 6e308945b184e3ae8ae4bcc24a724be60de82491 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 15:22:17 +0900 Subject: [PATCH 1667/5608] Fix logo visualisation trying to catch up after being off-screen --- osu.Game/Screens/Menu/LogoVisualisation.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 2ba82b5d9b..39bda799b5 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -131,7 +131,8 @@ namespace osu.Game.Screens.Menu { base.LoadComplete(); - Scheduler.AddDelayed(updateAmplitudes, time_between_updates, true); + var delayed = Scheduler.AddDelayed(updateAmplitudes, time_between_updates, true); + delayed.PerformRepeatCatchUpExecutions = false; } protected override void Update() From 6391d21af1b5c671fc99d6cfc9d483971840b6f6 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 3 Jul 2019 15:54:21 +0900 Subject: [PATCH 1668/5608] Remove test used for visualization --- .../UserInterface/TestSceneButtonSystem.cs | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs index 6c4d9b20f7..c8cc864089 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Shapes; using osu.Game.Screens.Menu; -using osuTK; using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface @@ -43,25 +42,7 @@ namespace osu.Game.Tests.Visual.UserInterface buttons.SetOsuLogo(logo); foreach (var s in Enum.GetValues(typeof(ButtonSystemState)).OfType().Skip(1)) - AddStep($"State to {s}", () => - { - buttons.State = s; - - if (buttons.State == ButtonSystemState.EnteringMode) - { - buttons.FadeOut(400, Easing.InSine); - buttons.MoveTo(new Vector2(-800, 0), 400, Easing.InSine); - logo.FadeOut(300, Easing.InSine) - .ScaleTo(0.2f, 300, Easing.InSine); - } - else - { - buttons.FadeIn(400, Easing.OutQuint); - buttons.MoveTo(new Vector2(0), 400, Easing.OutQuint); - logo.FadeColour(Color4.White, 100, Easing.OutQuint); - logo.FadeIn(100, Easing.OutQuint); - } - }); + AddStep($"State to {s}", () => buttons.State = s); } } } From d9e646d9ef75290af7cf6a79ef59c006e121928e Mon Sep 17 00:00:00 2001 From: miterosan Date: Wed, 3 Jul 2019 09:51:09 +0200 Subject: [PATCH 1669/5608] Use addRuleset inside loadRulesetFromFile --- osu.Game/Rulesets/RulesetStore.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 17834f8545..15adc258a1 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -143,8 +143,7 @@ namespace osu.Game.Rulesets try { - var assembly = Assembly.LoadFrom(file); - loaded_assemblies[assembly] = assembly.GetTypes().First(t => t.IsPublic && t.IsSubclassOf(typeof(Ruleset))); + addRuleset(Assembly.LoadFrom(file)); } catch (Exception e) { From ab244d1b7f7cb1ab4abf7c65aa043571cc8165b9 Mon Sep 17 00:00:00 2001 From: miterosan Date: Wed, 3 Jul 2019 10:21:18 +0200 Subject: [PATCH 1670/5608] Only log that the rulesets could not be loaded from a directory. --- osu.Game/Rulesets/RulesetStore.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 15adc258a1..31c8d03df4 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -31,9 +31,9 @@ namespace osu.Game.Rulesets foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) loadRulesetFromFile(file); } - catch (Exception e) + catch { - Logger.Error(e, $"Could not load rulesets from directory {Environment.CurrentDirectory}"); + Logger.Log($"Could not load rulesets from directory {Environment.CurrentDirectory}"); } } From 43d7f66c5bb095bd63ba02de3d34eaefe4c34d79 Mon Sep 17 00:00:00 2001 From: miterosan Date: Wed, 3 Jul 2019 10:54:10 +0200 Subject: [PATCH 1671/5608] Add comment about the android ruleset situation. --- osu.Game/Rulesets/RulesetStore.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 31c8d03df4..d0f6971e1c 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -22,6 +22,8 @@ namespace osu.Game.Rulesets { AppDomain.CurrentDomain.AssemblyResolve += currentDomain_AssemblyResolve; + // On android in release configuration the assemblies are loaded from the apk directly into memory. + // In this case there is no way to access the ruleset assemblies from the filesystem. addLoadedRulesets(); try From 9805adc61d527063082a0740f5ebbeda9c64bc8d Mon Sep 17 00:00:00 2001 From: naoey Date: Wed, 3 Jul 2019 14:25:59 +0530 Subject: [PATCH 1672/5608] Fix online ScoreInfo having the wrong ruleset --- osu.Game/Online/API/Requests/GetScoresRequest.cs | 3 +++ .../API/Requests/Responses/APILegacyScoreInfo.cs | 11 ----------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 0b6f65a0e0..e56df05570 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -34,7 +34,10 @@ namespace osu.Game.Online.API.Requests private void onSuccess(APILegacyScores r) { foreach (APILegacyScoreInfo score in r.Scores) + { score.Beatmap = beatmap; + score.Ruleset = ruleset; + } } protected override WebRequest CreateWebRequest() diff --git a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs index 5a18cf63f9..17da255873 100644 --- a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs @@ -116,17 +116,6 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"mods")] private string[] modStrings { get; set; } - public override BeatmapInfo Beatmap - { - get => base.Beatmap; - set - { - base.Beatmap = value; - if (Beatmap.Ruleset != null) - Ruleset = value.Ruleset; - } - } - public override RulesetInfo Ruleset { get => base.Ruleset; From 5ecb764cdcf65ddd0f9a0bae68f30cda46072542 Mon Sep 17 00:00:00 2001 From: miterosan Date: Wed, 3 Jul 2019 10:57:09 +0200 Subject: [PATCH 1673/5608] Remove whitespaces and lowercase the comments --- osu.Game/Rulesets/RulesetStore.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index d0f6971e1c..a7d62665db 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -22,8 +22,8 @@ namespace osu.Game.Rulesets { AppDomain.CurrentDomain.AssemblyResolve += currentDomain_AssemblyResolve; - // On android in release configuration the assemblies are loaded from the apk directly into memory. - // In this case there is no way to access the ruleset assemblies from the filesystem. + //on android in release configuration the assemblies are loaded from the apk directly into memory. + //in this case there is no way to access the rulesets assemblies from the filesystem. addLoadedRulesets(); try From ccae4ce95ef77a5475ea122653bbc5f393a886e2 Mon Sep 17 00:00:00 2001 From: naoey Date: Wed, 3 Jul 2019 14:39:11 +0530 Subject: [PATCH 1674/5608] Fix local beatmap leaderboard displaying scores from all game modes --- osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index aafa6bb0eb..62f93afbbb 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -55,7 +55,9 @@ namespace osu.Game.Screens.Select.Leaderboards { if (Scope == BeatmapLeaderboardScope.Local) { - Scores = scoreManager.QueryScores(s => !s.DeletePending && s.Beatmap.ID == Beatmap.ID).OrderByDescending(s => s.TotalScore).ToArray(); + Scores = scoreManager + .QueryScores(s => !s.DeletePending && s.Beatmap.ID == Beatmap.ID && s.Ruleset.ID == ruleset.Value.ID) + .OrderByDescending(s => s.TotalScore).ToArray(); PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; return null; } From 62dd89197c7fce70d38744a01beea5ad74056872 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 18:36:04 +0900 Subject: [PATCH 1675/5608] Refactor comment slightly --- osu.Game/Rulesets/RulesetStore.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index a7d62665db..4476f16e32 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -22,8 +22,8 @@ namespace osu.Game.Rulesets { AppDomain.CurrentDomain.AssemblyResolve += currentDomain_AssemblyResolve; - //on android in release configuration the assemblies are loaded from the apk directly into memory. - //in this case there is no way to access the rulesets assemblies from the filesystem. + // On android in release configuration assemblies are loaded from the apk directly into memory. + // We cannot read assemblies from cwd, so should check loaded assemblies isntead. addLoadedRulesets(); try From 06ef8f71e96e2af7242c558c2cd279afe3c72a6c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 18:41:01 +0900 Subject: [PATCH 1676/5608] Fix typo --- osu.Game/Rulesets/RulesetStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 4476f16e32..69ce5f97b6 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets AppDomain.CurrentDomain.AssemblyResolve += currentDomain_AssemblyResolve; // On android in release configuration assemblies are loaded from the apk directly into memory. - // We cannot read assemblies from cwd, so should check loaded assemblies isntead. + // We cannot read assemblies from cwd, so should check loaded assemblies instead. addLoadedRulesets(); try From 8120bb36bc598acadb0d30952bd370fdeb639fae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 18:42:10 +0900 Subject: [PATCH 1677/5608] More methods --- osu.Game/Rulesets/RulesetStore.cs | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 69ce5f97b6..fd42f96c92 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -24,19 +24,9 @@ namespace osu.Game.Rulesets // On android in release configuration assemblies are loaded from the apk directly into memory. // We cannot read assemblies from cwd, so should check loaded assemblies instead. - addLoadedRulesets(); + loadFromAppDomain(); - try - { - string[] files = Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll"); - - foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) - loadRulesetFromFile(file); - } - catch - { - Logger.Log($"Could not load rulesets from directory {Environment.CurrentDirectory}"); - } + loadFromDisk(); } public RulesetStore(IDatabaseContextFactory factory) @@ -123,7 +113,7 @@ namespace osu.Game.Rulesets } } - private static void addLoadedRulesets() + private static void loadFromAppDomain() { foreach (var ruleset in AppDomain.CurrentDomain.GetAssemblies()) { @@ -136,6 +126,21 @@ namespace osu.Game.Rulesets } } + private static void loadFromDisk() + { + try + { + string[] files = Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll"); + + foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) + loadRulesetFromFile(file); + } + catch + { + Logger.Log($"Could not load rulesets from directory {Environment.CurrentDirectory}"); + } + } + private static void loadRulesetFromFile(string file) { var filename = Path.GetFileNameWithoutExtension(file); From cc9a28afa81042a16284b7ce11d9164d548261a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 19:42:16 +0900 Subject: [PATCH 1678/5608] Add shared base class for both mod imlpementations --- osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs | 62 +------------- osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs | 70 +--------------- .../Mods/OsuModeObjectScaleTween.cs | 84 +++++++++++++++++++ 3 files changed, 89 insertions(+), 127 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs index cbefc42c3b..adca95cf8a 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -1,17 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModDeflate : Mod, IApplicableToDrawableHitObjects + public class OsuModDeflate : OsuModeObjectScaleTween { public override string Name => "Deflate"; @@ -19,58 +13,8 @@ namespace osu.Game.Rulesets.Osu.Mods public override IconUsage Icon => FontAwesome.Solid.CompressArrowsAlt; - public override ModType Type => ModType.Fun; + public override string Description => "Hit them at the right size!"; - public override string Description => "Become one with the approach circle..."; - - public override double ScoreMultiplier => 1; - - public void ApplyToDrawableHitObjects(IEnumerable drawables) - { - foreach (var drawable in drawables) - { - switch (drawable) - { - case DrawableSpinner _: - continue; - - default: - drawable.ApplyCustomUpdateState += ApplyCustomState; - break; - } - } - } - - protected virtual void ApplyCustomState(DrawableHitObject drawable, ArmedState state) - { - var h = (OsuHitObject)drawable.HitObject; - - // apply grow effect - switch (drawable) - { - case DrawableSliderHead _: - case DrawableSliderTail _: - // special cases we should *not* be scaling. - break; - - case DrawableSlider _: - case DrawableHitCircle _: - { - using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) - drawable.ScaleTo(2f).Then().ScaleTo(1f, h.TimePreempt); // sole difference to grow mod - break; - } - } - - // remove approach circles - switch (drawable) - { - case DrawableHitCircle circle: - // we don't want to see the approach circle - using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) - circle.ApproachCircle.Hide(); - break; - } - } + protected override float StartScale => 2f; } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs index 8072dc09c1..3c81203ad7 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs @@ -1,20 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; -using osu.Framework.Bindables; -using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Game.Configuration; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods { - internal class OsuModGrow : Mod, IReadFromConfig, IApplicableToDrawableHitObjects + internal class OsuModGrow : OsuModeObjectScaleTween { public override string Name => "Grow"; @@ -22,65 +13,8 @@ namespace osu.Game.Rulesets.Osu.Mods public override IconUsage Icon => FontAwesome.Solid.ArrowsAltV; - public override ModType Type => ModType.Fun; - public override string Description => "Hit them at the right size!"; - public override double ScoreMultiplier => 1; - - private Bindable increaseFirstObjectVisibility = new Bindable(); - - public void ReadFromConfig(OsuConfigManager config) - { - increaseFirstObjectVisibility = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility); - } - - public void ApplyToDrawableHitObjects(IEnumerable drawables) - { - foreach (var drawable in drawables.Skip(increaseFirstObjectVisibility.Value ? 1 : 0)) - { - switch (drawable) - { - case DrawableSpinner _: - continue; - - default: - drawable.ApplyCustomUpdateState += ApplyCustomState; - break; - } - } - } - - protected virtual void ApplyCustomState(DrawableHitObject drawable, ArmedState state) - { - var h = (OsuHitObject)drawable.HitObject; - - // apply grow effect - switch (drawable) - { - case DrawableSliderHead _: - case DrawableSliderTail _: - // special cases we should *not* be scaling. - break; - - case DrawableSlider _: - case DrawableHitCircle _: - { - using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) - drawable.ScaleTo(0.5f).Then().ScaleTo(1, h.TimePreempt, Easing.OutSine); - break; - } - } - - // remove approach circles - switch (drawable) - { - case DrawableHitCircle circle: - // we don't want to see the approach circle - using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) - circle.ApproachCircle.Hide(); - break; - } - } + protected override float StartScale => 0.5f; } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs b/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs new file mode 100644 index 0000000000..ad6a15718a --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs @@ -0,0 +1,84 @@ +// 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.Bindables; +using osu.Framework.Graphics; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; + +namespace osu.Game.Rulesets.Osu.Mods +{ + /// + /// Adjusts the size of hit objects during their fade in animation. + /// + public abstract class OsuModeObjectScaleTween : Mod, IReadFromConfig, IApplicableToDrawableHitObjects + { + public override ModType Type => ModType.Fun; + + public override double ScoreMultiplier => 1; + + protected virtual float StartScale => 1; + + protected virtual float EndScale => 1; + + private Bindable increaseFirstObjectVisibility = new Bindable(); + + public void ReadFromConfig(OsuConfigManager config) + { + increaseFirstObjectVisibility = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility); + } + + public void ApplyToDrawableHitObjects(IEnumerable drawables) + { + foreach (var drawable in drawables.Skip(increaseFirstObjectVisibility.Value ? 1 : 0)) + { + switch (drawable) + { + case DrawableSpinner _: + continue; + + default: + drawable.ApplyCustomUpdateState += ApplyCustomState; + break; + } + } + } + + protected virtual void ApplyCustomState(DrawableHitObject drawable, ArmedState state) + { + var h = (OsuHitObject)drawable.HitObject; + + // apply grow effect + switch (drawable) + { + case DrawableSliderHead _: + case DrawableSliderTail _: + // special cases we should *not* be scaling. + break; + + case DrawableSlider _: + case DrawableHitCircle _: + { + using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + drawable.ScaleTo(StartScale).Then().ScaleTo(EndScale, h.TimePreempt, Easing.OutSine); + break; + } + } + + // remove approach circles + switch (drawable) + { + case DrawableHitCircle circle: + // we don't want to see the approach circle + using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + circle.ApproachCircle.Hide(); + break; + } + } + } +} From 0740fff0c9d70d3c6a92dc4f6f4249cb278aaf63 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 19:53:25 +0900 Subject: [PATCH 1679/5608] Update android package dependencies --- osu.Android.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index ead059cdf2..8ef635fe75 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,7 +63,7 @@ - - + + From 4ba60ed089636efeb6e276c2a80d7f7aee485d98 Mon Sep 17 00:00:00 2001 From: naoey Date: Wed, 3 Jul 2019 17:04:20 +0530 Subject: [PATCH 1680/5608] Apply currently selected mods to filter leaderboard scores Modifies GetScoresRequest to build query string locally instead of using WebRequest.AddParameter since it doesn't support array parameters --- .../Online/API/Requests/GetScoresRequest.cs | 26 ++++++++------ osu.Game/Screens/Select/BeatmapDetailArea.cs | 2 ++ .../Select/Leaderboards/BeatmapLeaderboard.cs | 35 ++++++++++++++++++- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 0b6f65a0e0..2de0fcef9c 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -5,8 +5,10 @@ using System; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Screens.Select.Leaderboards; -using osu.Framework.IO.Network; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets.Mods; +using System.Text; +using System.Collections.Generic; namespace osu.Game.Online.API.Requests { @@ -15,8 +17,9 @@ namespace osu.Game.Online.API.Requests private readonly BeatmapInfo beatmap; private readonly BeatmapLeaderboardScope scope; private readonly RulesetInfo ruleset; + private readonly IEnumerable mods; - public GetScoresRequest(BeatmapInfo beatmap, RulesetInfo ruleset, BeatmapLeaderboardScope scope = BeatmapLeaderboardScope.Global) + public GetScoresRequest(BeatmapInfo beatmap, RulesetInfo ruleset, BeatmapLeaderboardScope scope = BeatmapLeaderboardScope.Global, IEnumerable mods = null) { if (!beatmap.OnlineBeatmapID.HasValue) throw new InvalidOperationException($"Cannot lookup a beatmap's scores without having a populated {nameof(BeatmapInfo.OnlineBeatmapID)}."); @@ -27,6 +30,7 @@ namespace osu.Game.Online.API.Requests this.beatmap = beatmap; this.scope = scope; this.ruleset = ruleset ?? throw new ArgumentNullException(nameof(ruleset)); + this.mods = mods ?? Array.Empty(); Success += onSuccess; } @@ -37,17 +41,19 @@ namespace osu.Game.Online.API.Requests score.Beatmap = beatmap; } - protected override WebRequest CreateWebRequest() + protected override string Target => $@"beatmaps/{beatmap.OnlineBeatmapID}/scores{createQueryParameters()}"; + + private string createQueryParameters() { - var req = base.CreateWebRequest(); + StringBuilder query = new StringBuilder(@"?"); - req.Timeout = 30000; - req.AddParameter(@"type", scope.ToString().ToLowerInvariant()); - req.AddParameter(@"mode", ruleset.ShortName); + query.Append($@"type={scope.ToString().ToLowerInvariant()}&"); + query.Append($@"mode={ruleset.ShortName}&"); - return req; + foreach (var mod in mods) + query.Append($@"mods[]={mod.Acronym}&"); + + return query.ToString().TrimEnd('&'); } - - protected override string Target => $@"beatmaps/{beatmap.OnlineBeatmapID}/scores"; } } diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index 477037355c..b66a2ffe0f 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -41,6 +41,8 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.X, OnFilter = (tab, mods) => { + Leaderboard.FilterMods = mods; + switch (tab) { case BeatmapDetailTab.Details: diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index aafa6bb0eb..890cc7e9a3 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -11,6 +11,7 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Leaderboards; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Scoring; namespace osu.Game.Screens.Select.Leaderboards @@ -36,12 +37,31 @@ namespace osu.Game.Screens.Select.Leaderboards } } + private bool filterMods; + + public bool FilterMods + { + get => filterMods; + set + { + if (value == filterMods) + return; + + filterMods = value; + + UpdateScores(); + } + } + [Resolved] private ScoreManager scoreManager { get; set; } [Resolved] private IBindable ruleset { get; set; } + [Resolved] + private IBindable> mods { get; set; } + [Resolved] private IAPIProvider api { get; set; } @@ -49,6 +69,11 @@ namespace osu.Game.Screens.Select.Leaderboards private void load() { ruleset.ValueChanged += _ => UpdateScores(); + mods.ValueChanged += _ => + { + if (filterMods) + UpdateScores(); + }; } protected override APIRequest FetchScores(Action> scoresCallback) @@ -72,7 +97,15 @@ namespace osu.Game.Screens.Select.Leaderboards return null; } - var req = new GetScoresRequest(Beatmap, ruleset.Value ?? Beatmap.Ruleset, Scope); + IReadOnlyList requestMods = null; + + if (filterMods && mods.Value.Count == 0) + // add nomod for the request + requestMods = new Mod[] { new ModNoMod() }; + else if (filterMods) + requestMods = mods.Value; + + var req = new GetScoresRequest(Beatmap, ruleset.Value ?? Beatmap.Ruleset, Scope, requestMods); req.Success += r => scoresCallback?.Invoke(r.Scores); From cfac90b228a382854242d6ce99fb33ccb8b0d255 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 3 Jul 2019 14:34:24 +0300 Subject: [PATCH 1681/5608] Use ConstrainedIconContainer instead of SpriteIcon --- osu.Game/Overlays/Direct/DirectRulesetSelector.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectRulesetSelector.cs b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs index f2abca9ce6..fdab9f1b90 100644 --- a/osu.Game/Overlays/Direct/DirectRulesetSelector.cs +++ b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs @@ -3,9 +3,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK; @@ -40,7 +40,7 @@ namespace osu.Game.Overlays.Direct private class DirectRulesetTabItem : TabItem { - private readonly SpriteIcon icon; + private readonly ConstrainedIconContainer iconContainer; public DirectRulesetTabItem(RulesetInfo value) : base(value) @@ -49,11 +49,13 @@ namespace osu.Game.Overlays.Direct Children = new Drawable[] { - icon = (SpriteIcon)value.CreateInstance().CreateIcon(), + iconContainer = new ConstrainedIconContainer + { + Icon = value.CreateInstance().CreateIcon(), + Size = new Vector2(32), + }, new HoverClickSounds() }; - - icon.Size = new Vector2(30); } protected override void LoadComplete() @@ -80,7 +82,7 @@ namespace osu.Game.Overlays.Direct protected override void OnDeactivated() => updateState(); - private void updateState() => icon.FadeColour(IsHovered || Active.Value ? Color4.White : Color4.Gray, 120, Easing.InQuad); + private void updateState() => iconContainer.FadeColour(IsHovered || Active.Value ? Color4.White : Color4.Gray, 120, Easing.InQuad); } } } From 66eb979fff5f92698d750bb7d807c6b6a07b0938 Mon Sep 17 00:00:00 2001 From: miterosan Date: Wed, 3 Jul 2019 15:51:20 +0200 Subject: [PATCH 1682/5608] Massivly deduplicate properties. Removed bass.dll. is it unused (and not included in the apk) --- osu.Android.props | 44 +++++++++--------- osu.Android/bass.dll | Bin 210944 -> 0 bytes osu.Android/osu.Android.csproj | 8 ---- ...u.Game.Rulesets.Catch.Tests.Android.csproj | 8 ---- ...u.Game.Rulesets.Mania.Tests.Android.csproj | 8 ---- ...osu.Game.Rulesets.Osu.Tests.Android.csproj | 8 ---- ...u.Game.Rulesets.Taiko.Tests.Android.csproj | 8 ---- .../osu.Game.Tests.Android.csproj | 8 ---- 8 files changed, 21 insertions(+), 71 deletions(-) delete mode 100644 osu.Android/bass.dll diff --git a/osu.Android.props b/osu.Android.props index 8ef635fe75..217b7ebdab 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -13,37 +13,36 @@ Xamarin.Android.Net.AndroidClientHandler v8.1 false + true + armeabi-v7a;x86;arm64-v8a + true + cjk,mideast,other,rare,west + SdkOnly + False + prompt + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {122416d6-6b49-4ee2-a1e8-b825f31c79fe} + Debug + AnyCPU + 8.0.30703 + 2.0 - + True portable False DEBUG;TRACE - prompt - false - false - SdkOnly - true - false - cjk,mideast,other,rare,west - true - armeabi-v7a;x86;arm64-v8a - true + False + True + False - - false + + False None True - prompt - true - false - SdkOnly + true False - true - cjk,mideast,other,rare,west - true - armeabi-v7a;x86;arm64-v8a - true + True @@ -52,7 +51,6 @@ Always - diff --git a/osu.Android/bass.dll b/osu.Android/bass.dll deleted file mode 100644 index 3cd403c3acbd9e89ad071c5069392ea208baaa38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 210944 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 S(A~_h>u%w{`TPGJ1^#c6n$Mj8 diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 42a3185cd1..3654e0301e 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -2,17 +2,9 @@ - Debug - AnyCPU - 8.0.30703 - 2.0 - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} osu.Android osu.Android Properties\AndroidManifest.xml - armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj index 88b420ffad..c886ddf92e 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj +++ b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj @@ -2,17 +2,9 @@ - Debug - AnyCPU - 8.0.30703 - 2.0 - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} osu.Game.Rulesets.Catch.Tests osu.Game.Rulesets.Catch.Tests.Android Properties\AndroidManifest.xml - armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj index 0e557cb260..27a5ebefcd 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj +++ b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj @@ -2,17 +2,9 @@ - Debug - AnyCPU - 8.0.30703 - 2.0 - {531F1092-DB27-445D-AA33-2A77C7187C99} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} osu.Game.Rulesets.Mania.Tests osu.Game.Rulesets.Mania.Tests.Android Properties\AndroidManifest.xml - armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj index dcf1573522..7d4389557b 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj +++ b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj @@ -2,17 +2,9 @@ - Debug - AnyCPU - 8.0.30703 - 2.0 - {90CAB706-39CB-4B93-9629-3218A6FF8E9B} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} osu.Game.Rulesets.Osu.Tests osu.Game.Rulesets.Osu.Tests.Android Properties\AndroidManifest.xml - armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj index 392442b713..6ed16c0b6a 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj @@ -2,17 +2,9 @@ - Debug - AnyCPU - 8.0.30703 - 2.0 - {3701A0A1-8476-42C6-B5C4-D24129B4A484} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} osu.Game.Rulesets.Taiko.Tests osu.Game.Rulesets.Taiko.Tests.Android Properties\AndroidManifest.xml - armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj index c2dd194e09..394157f832 100644 --- a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj +++ b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj @@ -2,17 +2,9 @@ - Debug - AnyCPU - 8.0.30703 - 2.0 - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} osu.Game.Tests osu.Game.Tests.Android Properties\AndroidManifest.xml - armeabi-v7a;x86;arm64-v8a From b901aab19da0572328ddc6851cd18a78e91f1f0a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Jul 2019 23:06:16 +0900 Subject: [PATCH 1683/5608] Fix update notification not correctly restarting the game --- osu.Desktop/Updater/SquirrelUpdateManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index 69064a40cb..78a1e680ec 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -129,7 +129,7 @@ namespace osu.Desktop.Updater Activated = () => { updateManager.PrepareUpdateAsync() - .ContinueWith(_ => Schedule(() => game.GracefullyExit())); + .ContinueWith(_ => updateManager.Schedule(() => game.GracefullyExit())); return true; } }; From 0acaf53c9b1cb73079d36231a3792d395335698e Mon Sep 17 00:00:00 2001 From: miterosan Date: Wed, 3 Jul 2019 17:25:42 +0200 Subject: [PATCH 1684/5608] Revert everything except removall of the bass.dll --- osu.Android.props | 43 ++++++++++--------- osu.Android/osu.Android.csproj | 8 ++++ ...u.Game.Rulesets.Catch.Tests.Android.csproj | 8 ++++ ...u.Game.Rulesets.Mania.Tests.Android.csproj | 8 ++++ ...osu.Game.Rulesets.Osu.Tests.Android.csproj | 8 ++++ ...u.Game.Rulesets.Taiko.Tests.Android.csproj | 8 ++++ .../osu.Game.Tests.Android.csproj | 8 ++++ 7 files changed, 70 insertions(+), 21 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 217b7ebdab..d47615d4b3 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -13,36 +13,37 @@ Xamarin.Android.Net.AndroidClientHandler v8.1 false - true - armeabi-v7a;x86;arm64-v8a - true - cjk,mideast,other,rare,west - SdkOnly - False - prompt - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} - Debug - AnyCPU - 8.0.30703 - 2.0 - + True portable False DEBUG;TRACE - False - True - False + prompt + false + false + SdkOnly + true + false + cjk,mideast,other,rare,west + true + armeabi-v7a;x86;arm64-v8a + true - - False + + false None True - true + prompt + true + false + SdkOnly False - True + true + cjk,mideast,other,rare,west + true + armeabi-v7a;x86;arm64-v8a + true diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 3654e0301e..42a3185cd1 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -2,9 +2,17 @@ + Debug + AnyCPU + 8.0.30703 + 2.0 + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {122416d6-6b49-4ee2-a1e8-b825f31c79fe} osu.Android osu.Android Properties\AndroidManifest.xml + armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj index c886ddf92e..88b420ffad 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj +++ b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj @@ -2,9 +2,17 @@ + Debug + AnyCPU + 8.0.30703 + 2.0 + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {122416d6-6b49-4ee2-a1e8-b825f31c79fe} osu.Game.Rulesets.Catch.Tests osu.Game.Rulesets.Catch.Tests.Android Properties\AndroidManifest.xml + armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj index 27a5ebefcd..0e557cb260 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj +++ b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj @@ -2,9 +2,17 @@ + Debug + AnyCPU + 8.0.30703 + 2.0 + {531F1092-DB27-445D-AA33-2A77C7187C99} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {122416d6-6b49-4ee2-a1e8-b825f31c79fe} osu.Game.Rulesets.Mania.Tests osu.Game.Rulesets.Mania.Tests.Android Properties\AndroidManifest.xml + armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj index 7d4389557b..dcf1573522 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj +++ b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj @@ -2,9 +2,17 @@ + Debug + AnyCPU + 8.0.30703 + 2.0 + {90CAB706-39CB-4B93-9629-3218A6FF8E9B} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {122416d6-6b49-4ee2-a1e8-b825f31c79fe} osu.Game.Rulesets.Osu.Tests osu.Game.Rulesets.Osu.Tests.Android Properties\AndroidManifest.xml + armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj index 6ed16c0b6a..392442b713 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj @@ -2,9 +2,17 @@ + Debug + AnyCPU + 8.0.30703 + 2.0 + {3701A0A1-8476-42C6-B5C4-D24129B4A484} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {122416d6-6b49-4ee2-a1e8-b825f31c79fe} osu.Game.Rulesets.Taiko.Tests osu.Game.Rulesets.Taiko.Tests.Android Properties\AndroidManifest.xml + armeabi-v7a;x86;arm64-v8a diff --git a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj index 394157f832..c2dd194e09 100644 --- a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj +++ b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj @@ -2,9 +2,17 @@ + Debug + AnyCPU + 8.0.30703 + 2.0 + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {122416d6-6b49-4ee2-a1e8-b825f31c79fe} osu.Game.Tests osu.Game.Tests.Android Properties\AndroidManifest.xml + armeabi-v7a;x86;arm64-v8a From 1824d2999650969f54ff50c45e4dcc150b41a5a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jul 2019 00:34:39 +0900 Subject: [PATCH 1685/5608] 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 8ef635fe75..400b43dbe6 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -64,6 +64,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b59828a52e..e872cd1387 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index ddbdaf3d18..a319094cb1 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 664257fbbe31f7b1617fc55527e59a088dc5c259 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Wed, 3 Jul 2019 18:42:02 +0200 Subject: [PATCH 1686/5608] Sliders no longer modified by HD but have transparent body now --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 1 - osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 60 ++++++++++--------- osu.Game/Overlays/Mods/ModSection.cs | 2 - 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 2723be9df8..ddf708d0f1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -17,7 +17,6 @@ namespace osu.Game.Rulesets.Osu.Mods { public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; - private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 64a331213f..8ccff6b258 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; +using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods { @@ -24,43 +25,44 @@ namespace osu.Game.Rulesets.Osu.Mods public override void ApplyToDrawableHitObjects(IEnumerable drawables) { foreach (var drawable in drawables.Skip(IncreaseFirstObjectVisibility.Value ? 1 : 0)) - { - switch (drawable) - { - case DrawableHitCircle _: - drawable.ApplyCustomUpdateState += ApplyTraceableState; - break; - - case DrawableSlider slider: - slider.ApplyCustomUpdateState += ApplyHiddenState; - slider.HeadCircle.ApplyCustomUpdateState += ApplyTraceableState; - break; - - default: - drawable.ApplyCustomUpdateState += ApplyHiddenState; - break; - } - } + drawable.ApplyCustomUpdateState += ApplyTraceableState; } protected void ApplyTraceableState(DrawableHitObject drawable, ArmedState state) { - if (!(drawable is DrawableHitCircle circle)) + if (!(drawable is DrawableOsuHitObject d)) return; - var h = circle.HitObject; + var h = d.HitObject; - // we only want to see the approach circle - using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + switch (drawable) { - circle.Circle.Hide(); // CirclePiece - circle.Circle.AlwaysPresent = true; - circle.Ring.Hide(); - circle.Flash.Hide(); - circle.Explode.Hide(); - circle.Number.Hide(); - circle.Glow.Hide(); - circle.ApproachCircle.Show(); + case DrawableHitCircle circle: + // we only want to see the approach circle + using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + { + circle.Circle.Hide(); // CirclePiece + circle.Circle.AlwaysPresent = true; + circle.Ring.Hide(); + circle.Flash.Hide(); + circle.Explode.Hide(); + circle.Number.Hide(); + circle.Glow.Hide(); + circle.ApproachCircle.Show(); + } + + break; + + case DrawableSlider slider: + ApplyTraceableState(slider.HeadCircle, state); + slider.Body.AccentColour = Color4.Transparent; + + break; + + default: + ApplyHiddenState(drawable, state); + + break; } } } diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 5c2ab8e18c..dedd397fa5 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -112,7 +112,6 @@ namespace osu.Game.Overlays.Mods if (selected == null) continue; foreach (var type in modTypes) - { if (type.IsInstanceOfType(selected)) { if (immediate) @@ -120,7 +119,6 @@ namespace osu.Game.Overlays.Mods else Scheduler.AddDelayed(button.Deselect, delay += 50); } - } } } From 5b4640d3ead5a89f31cb30b95c2234e79beb03c4 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Wed, 3 Jul 2019 21:40:14 +0200 Subject: [PATCH 1687/5608] Traceable no longer inherits from OsuModHidden and is no longer multi mod --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 1 + osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 24 +++++++++++++------ .../Mods/OsuModeObjectScaleTween.cs | 2 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 3 ++- .../TestSceneModSelectOverlay.cs | 5 ++-- 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index ddf708d0f1..74f9398f18 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; + public override Type[] IncompatibleMods => new[] { typeof(OsuModTraceable) }; private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index c5b5a064a6..1d68793c50 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -3,8 +3,10 @@ using System; using System.Linq; +using osu.Framework.Bindables; using System.Collections.Generic; using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -12,19 +14,25 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods { - internal class OsuModTraceable : OsuModHidden + internal class OsuModTraceable : Mod, IReadFromConfig, IApplicableToDrawableHitObjects { public override string Name => "Traceable"; public override string Acronym => "TC"; public override IconUsage Icon => FontAwesome.Brands.SnapchatGhost; - public override ModType Type => ModType.DifficultyIncrease; + public override ModType Type => ModType.Fun; public override string Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModeObjectScaleTween) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModeObjectScaleTween) }; + private Bindable increaseFirstObjectVisibility = new Bindable(); - public override void ApplyToDrawableHitObjects(IEnumerable drawables) + public void ReadFromConfig(OsuConfigManager config) { - foreach (var drawable in drawables.Skip(IncreaseFirstObjectVisibility.Value ? 1 : 0)) + increaseFirstObjectVisibility = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility); + } + + public void ApplyToDrawableHitObjects(IEnumerable drawables) + { + foreach (var drawable in drawables.Skip(increaseFirstObjectVisibility.Value ? 1 : 0)) drawable.ApplyCustomUpdateState += ApplyTraceableState; } @@ -59,8 +67,10 @@ namespace osu.Game.Rulesets.Osu.Mods break; - default: - ApplyHiddenState(drawable, state); + case DrawableSpinner spinner: + spinner.Disc.Hide(); + //spinner.Ticks.Hide(); // do they contribute to the theme? debatable + spinner.Background.Hide(); break; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs b/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs index de277100b5..db61c15846 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModeObjectScaleTween) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModTraceable) }; protected virtual float StartScale => 1; diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 949b473ca6..c0e2809b38 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Osu new OsuModHardRock(), new MultiMod(new OsuModSuddenDeath(), new OsuModPerfect()), new MultiMod(new OsuModDoubleTime(), new OsuModNightcore()), - new MultiMod(new OsuModHidden(), new OsuModTraceable()), + new OsuModHidden(), new MultiMod(new OsuModFlashlight(), new OsuModBlinds()), }; @@ -136,6 +136,7 @@ namespace osu.Game.Rulesets.Osu new OsuModWiggle(), new MultiMod(new OsuModGrow(), new OsuModDeflate()), new MultiMod(new ModWindUp(), new ModWindDown()), + new OsuModTraceable(), }; default: diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 9074b64eb8..80408ab43b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -85,7 +85,7 @@ namespace osu.Game.Tests.Visual.UserInterface var assistMods = instance.GetModsFor(ModType.Automation); var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); - var hiddenMod = harderMods.OfType().FirstOrDefault(m => m.Mods.Any(a => a is OsuModHidden)); + var hiddenMod = harderMods.FirstOrDefault(m => m is OsuModHidden); var doubleTimeMod = harderMods.OfType().FirstOrDefault(m => m.Mods.Any(a => a is OsuModDoubleTime)); @@ -96,11 +96,10 @@ namespace osu.Game.Tests.Visual.UserInterface testSingleMod(noFailMod); testMultiMod(doubleTimeMod); - testMultiMod(hiddenMod); testIncompatibleMods(easy, hardRock); testDeselectAll(easierMods.Where(m => !(m is MultiMod))); testMultiplierTextColour(noFailMod, modSelect.LowMultiplierColour); - testMultiplierTextColour(hardRock, modSelect.HighMultiplierColour); + testMultiplierTextColour(hiddenMod, modSelect.HighMultiplierColour); testUnimplementedMod(autoPilotMod); } From 99603ca0b67f29edc9fad584cc1e6a4e1fa5526b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 4 Jul 2019 04:50:49 +0300 Subject: [PATCH 1688/5608] Fade out game volume on exiting Invokes 'this.Exit()' on completion (simplify lines) --- osu.Game/Screens/Menu/Intro.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index dab5066c52..2883559bbd 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -33,6 +33,8 @@ namespace osu.Game.Screens.Menu protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack(); + private readonly BindableDouble exitingVolumeFade = new BindableDouble(1); + private Bindable menuVoice; private Bindable menuMusic; private Track track; @@ -72,6 +74,8 @@ namespace osu.Game.Screens.Menu welcome = audio.Samples.Get(@"welcome"); seeya = audio.Samples.Get(@"seeya"); + + audio.AddAdjustment(AdjustableProperty.Volume, exitingVolumeFade); } private const double delay_step_one = 2300; @@ -161,7 +165,7 @@ namespace osu.Game.Screens.Menu else fadeOutTime = 500; - Scheduler.AddDelayed(this.Exit, fadeOutTime); + this.TransformBindableTo(exitingVolumeFade, 0, fadeOutTime).OnComplete(_ => this.Exit()); //don't want to fade out completely else we will stop running updates. Game.FadeTo(0.01f, fadeOutTime); From b53aeec90de21feca625932e2163d45ab379d757 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 4 Jul 2019 05:18:29 +0300 Subject: [PATCH 1689/5608] Move audio adjustment inside OnResuming --- osu.Game/Screens/Menu/Intro.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index 2883559bbd..f6fbcf6498 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -35,13 +35,16 @@ namespace osu.Game.Screens.Menu private readonly BindableDouble exitingVolumeFade = new BindableDouble(1); + [Resolved] + private AudioManager audio { get; set; } + private Bindable menuVoice; private Bindable menuMusic; private Track track; private WorkingBeatmap introBeatmap; [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game) + private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game) { menuVoice = config.GetBindable(OsuSetting.MenuVoice); menuMusic = config.GetBindable(OsuSetting.MenuMusic); @@ -74,8 +77,6 @@ namespace osu.Game.Screens.Menu welcome = audio.Samples.Get(@"welcome"); seeya = audio.Samples.Get(@"seeya"); - - audio.AddAdjustment(AdjustableProperty.Volume, exitingVolumeFade); } private const double delay_step_one = 2300; @@ -165,6 +166,7 @@ namespace osu.Game.Screens.Menu else fadeOutTime = 500; + audio.AddAdjustment(AdjustableProperty.Volume, exitingVolumeFade); this.TransformBindableTo(exitingVolumeFade, 0, fadeOutTime).OnComplete(_ => this.Exit()); //don't want to fade out completely else we will stop running updates. From 7795a16c36d3809768a72240c89ba6c64d681085 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jul 2019 11:38:25 +0900 Subject: [PATCH 1690/5608] Update android metadata in line with standards --- osu.Android/Properties/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index 326d32f7ab..0cf2b786b1 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + From 70e2b83f294a943dca2369198d9d8a0f73b434a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jul 2019 11:40:05 +0900 Subject: [PATCH 1691/5608] Target newer api version --- osu.Android/Properties/AndroidManifest.xml | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../Properties/AndroidManifest.xml | 2 +- osu.Game.Tests.Android/Properties/AndroidManifest.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index 0cf2b786b1..acd21f9587 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -1,6 +1,6 @@  - + diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml index b04b0718f5..db95e18f13 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml index c315581606..e6728c801d 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml index dac9c19477..aad907b241 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml index f731042a4c..cd4b74aa16 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Tests.Android/Properties/AndroidManifest.xml index 146f96c2a3..bb996dc5ca 100644 --- a/osu.Game.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file From d2ebf296d99858c715a4e09a14150c6680589197 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jul 2019 13:07:59 +0900 Subject: [PATCH 1692/5608] Release with better compilation options --- osu.Android/osu.Android.csproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 42a3185cd1..ac3905a372 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -14,6 +14,11 @@ Properties\AndroidManifest.xml armeabi-v7a;x86;arm64-v8a + + cjk;mideast;other;rare;west + d8 + r8 + From 32bb9633933cd3398c63ca2faa3a771ea03becc6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jul 2019 14:33:00 +0900 Subject: [PATCH 1693/5608] Lock WorkingBeatmap cache to avoid threading issues --- osu.Game/Beatmaps/BeatmapManager.cs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 860c7fc0fa..ab08d35f52 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -176,20 +176,23 @@ namespace osu.Game.Beatmaps if (beatmapInfo?.BeatmapSet == null || beatmapInfo == DefaultBeatmap?.BeatmapInfo) return DefaultBeatmap; - var cached = workingCache.FirstOrDefault(w => w.BeatmapInfo?.ID == beatmapInfo.ID); + lock (workingCache) + { + var cached = workingCache.FirstOrDefault(w => w.BeatmapInfo?.ID == beatmapInfo.ID); - if (cached != null) - return cached; + if (cached != null) + return cached; - if (beatmapInfo.Metadata == null) - beatmapInfo.Metadata = beatmapInfo.BeatmapSet.Metadata; + if (beatmapInfo.Metadata == null) + beatmapInfo.Metadata = beatmapInfo.BeatmapSet.Metadata; - WorkingBeatmap working = new BeatmapManagerWorkingBeatmap(Files.Store, new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)), beatmapInfo, audioManager); + WorkingBeatmap working = new BeatmapManagerWorkingBeatmap(Files.Store, new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)), beatmapInfo, audioManager); - previous?.TransferTo(working); - workingCache.Add(working); + previous?.TransferTo(working); + workingCache.Add(working); - return working; + return working; + } } /// From 4885f0f0c72c05a1174a521c77c2392dafbbfe8b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jul 2019 15:47:06 +0900 Subject: [PATCH 1694/5608] Add messaging telling users how to leave changelog comments --- .../Online/TestSceneChangelogOverlay.cs | 1 + .../Requests/Responses/APIChangelogBuild.cs | 2 + .../Changelog/ChangelogSingleBuild.cs | 6 +- osu.Game/Overlays/Changelog/Comments.cs | 79 +++++++++++++++++++ 4 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Overlays/Changelog/Comments.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 0655611230..cf8bac7642 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -24,6 +24,7 @@ namespace osu.Game.Tests.Visual.Online typeof(ChangelogListing), typeof(ChangelogSingleBuild), typeof(ChangelogBuild), + typeof(Comments), }; protected override void LoadComplete() diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs index 36407c7b0e..d11e2d454b 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs @@ -33,6 +33,8 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("versions")] public VersionNavigation Versions { get; set; } + public object Url => $"https://osu.ppy.sh/home/changelog/{UpdateStream.Name}/{Version}"; + public class VersionNavigation { [JsonProperty("next")] diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index 36ae5a756c..44552b214f 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -58,7 +58,11 @@ namespace osu.Game.Overlays.Changelog } if (build != null) - Child = new ChangelogBuildWithNavigation(build) { SelectBuild = SelectBuild }; + Children = new Drawable[] + { + new ChangelogBuildWithNavigation(build) { SelectBuild = SelectBuild }, + new Comments(build) + }; } public class ChangelogBuildWithNavigation : ChangelogBuild diff --git a/osu.Game/Overlays/Changelog/Comments.cs b/osu.Game/Overlays/Changelog/Comments.cs new file mode 100644 index 0000000000..4cf39e7b44 --- /dev/null +++ b/osu.Game/Overlays/Changelog/Comments.cs @@ -0,0 +1,79 @@ +// 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.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Online.API.Requests.Responses; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Changelog +{ + public class Comments : CompositeDrawable + { + private readonly APIChangelogBuild build; + + public Comments(APIChangelogBuild build) + { + this.build = build; + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Padding = new MarginPadding + { + Horizontal = 50, + Vertical = 20, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + LinkFlowContainer text; + + InternalChildren = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 10, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.GreyVioletDarker + }, + }, + text = new LinkFlowContainer(t => + { + t.Colour = colours.PinkLighter; + t.Font = OsuFont.Default.With(size: 14); + }) + { + Padding = new MarginPadding(20), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } + }; + + text.AddParagraph("Got feedback?", t => + { + t.Colour = Color4.White; + t.Font = OsuFont.Default.With(italics: true, size: 20); + t.Padding = new MarginPadding { Bottom = 20 }; + }); + + text.AddParagraph("We would love to hear what you think of this update! "); + text.AddIcon(FontAwesome.Regular.GrinHearts); + + text.AddParagraph("Please visit the "); + text.AddLink("web version", $"{build.Url}#comments"); + text.AddText(" of this changelog to leave any comments."); + } + } +} From 2b9f7d551f7214fba14b38f8629ba6b539700c4a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jul 2019 16:16:17 +0900 Subject: [PATCH 1695/5608] Fix incorrect type specification --- osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs index d11e2d454b..56005e15f8 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs @@ -33,7 +33,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("versions")] public VersionNavigation Versions { get; set; } - public object Url => $"https://osu.ppy.sh/home/changelog/{UpdateStream.Name}/{Version}"; + public string Url => $"https://osu.ppy.sh/home/changelog/{UpdateStream.Name}/{Version}"; public class VersionNavigation { From a20d5baa57c3b84557f2a584cef3796091d400ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jul 2019 16:21:01 +0900 Subject: [PATCH 1696/5608] Fix skip button not being clickable after fade out --- osu.Game/Screens/Play/SkipOverlay.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 38dd179f25..d0912db63c 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -201,14 +201,15 @@ namespace osu.Game.Screens.Play protected override bool OnMouseDown(MouseDownEvent e) { + Show(); scheduledHide?.Cancel(); - return base.OnMouseDown(e); + return true; } protected override bool OnMouseUp(MouseUpEvent e) { Show(); - return base.OnMouseUp(e); + return true; } public override void Hide() => State = Visibility.Hidden; From db24ac28ec21ebac80e7525a51b787b5b920274c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jul 2019 16:53:08 +0900 Subject: [PATCH 1697/5608] Add tests --- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 63 +++++++++++++++++-- osu.Game/Screens/Play/SkipOverlay.cs | 2 + 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index 0519660477..8d2f71d9b4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -1,19 +1,72 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using NUnit.Framework; using osu.Game.Screens.Play; +using osuTK; +using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestSceneSkipOverlay : OsuTestScene + public class TestSceneSkipOverlay : ManualInputManagerTestScene { - protected override void LoadComplete() - { - base.LoadComplete(); + private SkipOverlay skip; + private int requestCount; - Add(new SkipOverlay(Clock.CurrentTime + 5000)); + [SetUp] + public void SetUp() => Schedule(() => + { + requestCount = 0; + Child = skip = new SkipOverlay(Clock.CurrentTime + 5000) + { + RequestSeek = _ => requestCount++ + }; + }); + + [Test] + public void TestFadeOnIdle() + { + AddStep("move mouse", () => InputManager.MoveMouseTo(Vector2.Zero)); + AddUntilStep("wait for fade", () => skip.Children.First().Alpha == 0); + AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); + AddUntilStep("visible again", () => skip.Children.First().Alpha > 0); + AddUntilStep("wait for fade", () => skip.Children.First().Alpha == 0); } + + [Test] + public void TestClickableAfterFade() + { + AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); + AddUntilStep("wait for fade", () => skip.Children.First().Alpha == 0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkRequestCount(1); + } + + [Test] + public void TestClickOnlyActuatesOnce() + { + AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkRequestCount(1); + } + + [Test] + public void TestDoesntFadeOnMouseDown() + { + AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); + AddStep("button down", () => InputManager.PressButton(MouseButton.Left)); + AddUntilStep("wait for overlay disapper", () => !skip.IsAlive); + AddAssert("ensure button didn't disappear", () => skip.Children.First().Alpha > 0); + AddStep("button up", () => InputManager.ReleaseButton(MouseButton.Left)); + checkRequestCount(0); + } + + private void checkRequestCount(int expected) => + AddAssert($"request count is {expected}", () => requestCount == expected); } } diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index d0912db63c..d6c2b59d98 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -161,6 +161,8 @@ namespace osu.Game.Screens.Play private Visibility state; private ScheduledDelegate scheduledHide; + public override bool IsPresent => true; + public Visibility State { get => state; From 530675f3642a5da7729e9720276c4a4fe34c159e Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 4 Jul 2019 17:05:29 +0900 Subject: [PATCH 1698/5608] Add tests as separate steps --- .../UserInterface/TestSceneButtonSystem.cs | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs index 6c4d9b20f7..88129308db 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs @@ -43,25 +43,25 @@ namespace osu.Game.Tests.Visual.UserInterface buttons.SetOsuLogo(logo); foreach (var s in Enum.GetValues(typeof(ButtonSystemState)).OfType().Skip(1)) - AddStep($"State to {s}", () => - { - buttons.State = s; + AddStep($"State to {s}", () => buttons.State = s); - if (buttons.State == ButtonSystemState.EnteringMode) - { - buttons.FadeOut(400, Easing.InSine); - buttons.MoveTo(new Vector2(-800, 0), 400, Easing.InSine); - logo.FadeOut(300, Easing.InSine) - .ScaleTo(0.2f, 300, Easing.InSine); - } - else - { - buttons.FadeIn(400, Easing.OutQuint); - buttons.MoveTo(new Vector2(0), 400, Easing.OutQuint); - logo.FadeColour(Color4.White, 100, Easing.OutQuint); - logo.FadeIn(100, Easing.OutQuint); - } - }); + AddStep("Exiting menu", () => + { + buttons.State = ButtonSystemState.EnteringMode; + buttons.FadeOut(400, Easing.InSine); + buttons.MoveTo(new Vector2(-800, 0), 400, Easing.InSine); + logo.FadeOut(300, Easing.InSine) + .ScaleTo(0.2f, 300, Easing.InSine); + }); + + AddStep("Entering menu", () => + { + buttons.State = ButtonSystemState.Play; + buttons.FadeIn(400, Easing.OutQuint); + buttons.MoveTo(new Vector2(0), 400, Easing.OutQuint); + logo.FadeColour(Color4.White, 100, Easing.OutQuint); + logo.FadeIn(100, Easing.OutQuint); + }); } } } From 07078b735c7909fd192570d531bfd3a883312afb Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 4 Jul 2019 17:06:28 +0900 Subject: [PATCH 1699/5608] use new vector2 --- osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs index e5a27dac81..88129308db 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Shapes; using osu.Game.Screens.Menu; +using osuTK; using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface From be4e7d0f5059ea1d5d6d00eea71c368207c6bc36 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 4 Jul 2019 17:08:21 +0900 Subject: [PATCH 1700/5608] remove comment --- osu.Game/Screens/Menu/ButtonSystem.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 040a9f8843..87c009c437 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -332,7 +332,6 @@ namespace osu.Game.Screens.Menu break; case ButtonSystemState.EnteringMode: - // When coming from the Initial (untracked) state, interpolate to the tracking position over a brief duration instead of tracking immediately. logoTrackingContainer.StartTracking(logo, lastState == ButtonSystemState.Initial ? 400 : 0, Easing.InSine); break; } From 73bc71f8b2b891a33d6e87fb33e0929d90c53758 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jul 2019 17:32:58 +0900 Subject: [PATCH 1701/5608] Use local clock to add consistency to skip times --- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index 8d2f71d9b4..a0e2e10c00 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -3,6 +3,9 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Timing; using osu.Game.Screens.Play; using osuTK; using osuTK.Input; @@ -19,9 +22,20 @@ namespace osu.Game.Tests.Visual.Gameplay public void SetUp() => Schedule(() => { requestCount = 0; - Child = skip = new SkipOverlay(Clock.CurrentTime + 5000) + Child = new Container { - RequestSeek = _ => requestCount++ + RelativeSizeAxes = Axes.Both, + Clock = new FramedOffsetClock(Clock) + { + Offset = -Clock.CurrentTime, + }, + Children = new Drawable[] + { + skip = new SkipOverlay(5000) + { + RequestSeek = _ => requestCount++ + } + }, }; }); From 86e9d97b6a3006f89fc4b9b67adda55e31b51386 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jul 2019 18:38:29 +0900 Subject: [PATCH 1702/5608] Adjust variables and test length to avoid random failures --- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index a0e2e10c00..94ae243bb9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Gameplay }, Children = new Drawable[] { - skip = new SkipOverlay(5000) + skip = new SkipOverlay(6000) { RequestSeek = _ => requestCount++ } @@ -42,11 +42,12 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestFadeOnIdle() { - AddStep("move mouse", () => InputManager.MoveMouseTo(Vector2.Zero)); - AddUntilStep("wait for fade", () => skip.Children.First().Alpha == 0); + AddUntilStep("fully visible", () => skip.Children.First().Alpha == 1); + AddUntilStep("wait for fade", () => skip.Children.First().Alpha < 1); + AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); - AddUntilStep("visible again", () => skip.Children.First().Alpha > 0); - AddUntilStep("wait for fade", () => skip.Children.First().Alpha == 0); + AddUntilStep("fully visible", () => skip.Children.First().Alpha == 1); + AddUntilStep("wait for fade", () => skip.Children.First().Alpha < 1); } [Test] From 2dc356a24e794eb9c3e31ff216c3b688660dc730 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jul 2019 18:47:43 +0900 Subject: [PATCH 1703/5608] Remove using --- osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index 94ae243bb9..2a08d2ad19 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Screens.Play; -using osuTK; using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay From 608223cbb408d33b27c45c8183c13c0d49172c4f Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 4 Jul 2019 11:59:38 +0200 Subject: [PATCH 1704/5608] Add setting to collapse the song progress graph --- .../Visual/Gameplay/TestSceneSongProgress.cs | 16 +++- osu.Game/Configuration/OsuConfigManager.cs | 2 + .../Sections/Gameplay/GeneralSettings.cs | 5 + osu.Game/Screens/Play/SongProgress.cs | 93 +++++++++++-------- osu.Game/Screens/Play/SongProgressBar.cs | 5 +- 5 files changed, 77 insertions(+), 44 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index af21007efe..eef7a25c7a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; @@ -15,6 +16,11 @@ namespace osu.Game.Tests.Visual.Gameplay [TestFixture] public class TestSceneSongProgress : OsuTestScene { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(SongProgressBar), + }; + private readonly SongProgress progress; private readonly TestSongProgressGraph graph; @@ -46,24 +52,26 @@ namespace osu.Game.Tests.Visual.Gameplay Origin = Anchor.TopLeft, }); - AddWaitStep("wait some", 5); AddAssert("ensure not created", () => graph.CreationCount == 0); AddStep("display values", displayNewValues); - AddWaitStep("wait some", 5); AddUntilStep("wait for creation count", () => graph.CreationCount == 1); AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking); - AddWaitStep("wait some", 5); AddUntilStep("wait for creation count", () => graph.CreationCount == 1); AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking); - AddWaitStep("wait some", 5); AddUntilStep("wait for creation count", () => graph.CreationCount == 1); AddRepeatStep("New Values", displayNewValues, 5); AddWaitStep("wait some", 5); AddAssert("ensure debounced", () => graph.CreationCount == 2); + + AddStep("hide graph", () => progress.CollapseGraph.Value = true); + AddStep("show graph", () => progress.CollapseGraph.Value = false); + + AddStep("start", clock.Start); + AddStep("pause", clock.Stop); } private void displayNewValues() diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 795f0b43f7..f3792fcb7f 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -77,6 +77,7 @@ namespace osu.Game.Configuration Set(OsuSetting.BlurLevel, 0, 0, 1, 0.01); Set(OsuSetting.ShowInterface, true); + Set(OsuSetting.CollapseProgressGraph, false); Set(OsuSetting.KeyOverlay, false); Set(OsuSetting.FloatingComments, false); @@ -131,6 +132,7 @@ namespace osu.Game.Configuration KeyOverlay, FloatingComments, ShowInterface, + CollapseProgressGraph, MouseDisableButtons, MouseDisableWheel, AudioOffset, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 997d1354b3..e365973c4b 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -35,6 +35,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay Bindable = config.GetBindable(OsuSetting.ShowInterface) }, new SettingsCheckbox + { + LabelText = "Collapse song progress graph", + Bindable = config.GetBindable(OsuSetting.CollapseProgressGraph) + }, + new SettingsCheckbox { LabelText = "Always show key overlay", Bindable = config.GetBindable(OsuSetting.KeyOverlay) diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 6642efdf8b..a535dc3333 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -11,6 +11,7 @@ using osu.Framework.Allocation; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Timing; +using osu.Game.Configuration; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; @@ -20,7 +21,7 @@ namespace osu.Game.Screens.Play public class SongProgress : OverlayContainer { private const int bottom_bar_height = 5; - + private const float graph_height = SquareGraph.Column.WIDTH * 6; private static readonly Vector2 handle_size = new Vector2(10, 18); private const float transition_duration = 200; @@ -30,13 +31,13 @@ namespace osu.Game.Screens.Play private readonly SongProgressInfo info; public Action RequestSeek; + public readonly Bindable CollapseGraph = new Bindable(); public override bool HandleNonPositionalInput => AllowSeeking; public override bool HandlePositionalInput => AllowSeeking; - private double lastHitTime => ((objects.Last() as IHasEndTime)?.EndTime ?? objects.Last().StartTime) + 1; - private double firstHitTime => objects.First().StartTime; + private double lastHitTime => ((objects.Last() as IHasEndTime)?.EndTime ?? objects.Last().StartTime) + 1; private IEnumerable objects; @@ -54,25 +55,28 @@ namespace osu.Game.Screens.Play } } + private bool allowSeeking; + + public bool AllowSeeking + { + get => allowSeeking; + set + { + if (allowSeeking == value) return; + + allowSeeking = value; + updateBarVisibility(); + } + } + private readonly BindableBool replayLoaded = new BindableBool(); public IClock ReferenceClock; private IClock gameplayClock; - [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, GameplayClock clock) - { - if (clock != null) - gameplayClock = clock; - - graph.FillColour = bar.FillColour = colours.BlueLighter; - } - public SongProgress() { - const float graph_height = SquareGraph.Column.WIDTH * 6; - Height = bottom_bar_height + graph_height + handle_size.Y; Y = bottom_bar_height; @@ -104,12 +108,23 @@ namespace osu.Game.Screens.Play }; } + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours, GameplayClock clock, OsuConfigManager config) + { + if (clock != null) + gameplayClock = clock; + + config.BindWith(OsuSetting.CollapseProgressGraph, CollapseGraph); + + graph.FillColour = bar.FillColour = colours.BlueLighter; + } + protected override void LoadComplete() { Show(); - replayLoaded.ValueChanged += loaded => AllowSeeking = loaded.NewValue; - replayLoaded.TriggerChange(); + replayLoaded.BindValueChanged(loaded => AllowSeeking = loaded.NewValue, true); + CollapseGraph.BindValueChanged(_ => updateGraphVisibility(), true); } public void BindDrawableRuleset(DrawableRuleset drawableRuleset) @@ -117,28 +132,6 @@ namespace osu.Game.Screens.Play replayLoaded.BindTo(drawableRuleset.HasReplayLoaded); } - private bool allowSeeking; - - public bool AllowSeeking - { - get => allowSeeking; - set - { - if (allowSeeking == value) return; - - allowSeeking = value; - updateBarVisibility(); - } - } - - private void updateBarVisibility() - { - bar.FadeTo(allowSeeking ? 1 : 0, transition_duration, Easing.In); - this.MoveTo(new Vector2(0, allowSeeking ? 0 : bottom_bar_height), transition_duration, Easing.In); - - info.Margin = new MarginPadding { Bottom = Height - (allowSeeking ? 0 : handle_size.Y) }; - } - protected override void PopIn() { updateBarVisibility(); @@ -165,5 +158,29 @@ namespace osu.Game.Screens.Play bar.CurrentTime = gameplayTime; graph.Progress = (int)(graph.ColumnCount * progress); } + + private void updateBarVisibility() + { + bar.FadeTo(allowSeeking ? 1 : 0, transition_duration, Easing.In); + this.MoveTo(new Vector2(0, allowSeeking ? 0 : bottom_bar_height), transition_duration, Easing.In); + + updateInfoMargin(); + } + + private void updateGraphVisibility() + { + float barHeight = bottom_bar_height + handle_size.Y; + + bar.ResizeHeightTo(CollapseGraph.Value ? barHeight : barHeight + graph_height, transition_duration, Easing.In); + graph.MoveToY(CollapseGraph.Value ? graph_height : 0, transition_duration, Easing.In); + + updateInfoMargin(); + } + + private void updateInfoMargin() + { + float finalMargin = bottom_bar_height + (allowSeeking ? handle_size.Y : 0) + (CollapseGraph.Value ? 0 : graph_height); + info.TransformTo(nameof(info.Margin), new MarginPadding { Bottom = finalMargin }, transition_duration, Easing.In); + } } } diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index dd7b5826d5..0a906845fc 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -18,6 +18,7 @@ namespace osu.Game.Screens.Play private readonly Box fill; private readonly Container handleBase; + private readonly Container handleContainer; public Color4 FillColour { @@ -73,7 +74,6 @@ namespace osu.Game.Screens.Play Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, Width = 2, - Height = barHeight + handleBarHeight, Colour = Color4.White, Position = new Vector2(2, 0), Children = new Drawable[] @@ -83,7 +83,7 @@ namespace osu.Game.Screens.Play Name = "HandleBar box", RelativeSizeAxes = Axes.Both, }, - new Container + handleContainer = new Container { Name = "Handle container", Origin = Anchor.BottomCentre, @@ -115,6 +115,7 @@ namespace osu.Game.Screens.Play { base.Update(); + handleBase.Height = Height - handleContainer.Height; float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, MathHelper.Clamp(Time.Elapsed / 40, 0, 1)); fill.Width = newX; From 1b368601695164d2789097156e02788e678add66 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jul 2019 19:26:12 +0900 Subject: [PATCH 1705/5608] Fix test cross-talk --- osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index 2a08d2ad19..b152c21454 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Screens.Play; +using osuTK; using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay @@ -41,6 +42,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestFadeOnIdle() { + AddStep("move mouse", () => InputManager.MoveMouseTo(Vector2.Zero)); AddUntilStep("fully visible", () => skip.Children.First().Alpha == 1); AddUntilStep("wait for fade", () => skip.Children.First().Alpha < 1); From 4758914f7fced0da59361bfb18d8556f5f42eaeb Mon Sep 17 00:00:00 2001 From: Morilli <35152647+Morilli@users.noreply.github.com> Date: Thu, 4 Jul 2019 15:14:15 +0200 Subject: [PATCH 1706/5608] Bump android TargetFrameworkVersion --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index 7b22b76e0e..5ee0573c58 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ Off True Xamarin.Android.Net.AndroidClientHandler - v8.1 + v9.0 false From 9b2ebed669aacbbfc81b46379f017c111a897c1e Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 4 Jul 2019 08:36:34 -0700 Subject: [PATCH 1707/5608] Remove unused EditSongSelect file --- osu.Game/Screens/Select/EditSongSelect.cs | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 osu.Game/Screens/Select/EditSongSelect.cs diff --git a/osu.Game/Screens/Select/EditSongSelect.cs b/osu.Game/Screens/Select/EditSongSelect.cs deleted file mode 100644 index bdf5f905fe..0000000000 --- a/osu.Game/Screens/Select/EditSongSelect.cs +++ /dev/null @@ -1,18 +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.Screens; - -namespace osu.Game.Screens.Select -{ - public class EditSongSelect : SongSelect - { - protected override bool ShowFooter => false; - - protected override bool OnStart() - { - this.Exit(); - return true; - } - } -} From f04adb719252aaf723c89250aaf30e53c63e043d Mon Sep 17 00:00:00 2001 From: naoey Date: Wed, 3 Jul 2019 22:28:13 +0530 Subject: [PATCH 1708/5608] Apply mods filter to local scores too --- .../Select/Leaderboards/BeatmapLeaderboard.cs | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 08f9632462..c1cbc40680 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -39,6 +39,9 @@ namespace osu.Game.Screens.Select.Leaderboards private bool filterMods; + /// + /// Whether to apply the game's currently selected mods as a filter when retrieving scores. + /// public bool FilterMods { get => filterMods; @@ -80,10 +83,25 @@ namespace osu.Game.Screens.Select.Leaderboards { if (Scope == BeatmapLeaderboardScope.Local) { - Scores = scoreManager - .QueryScores(s => !s.DeletePending && s.Beatmap.ID == Beatmap.ID && s.Ruleset.ID == ruleset.Value.ID) - .OrderByDescending(s => s.TotalScore).ToArray(); + var scores = scoreManager + .QueryScores(s => !s.DeletePending && s.Beatmap.ID == Beatmap.ID && s.Ruleset.ID == ruleset.Value.ID); + + if (filterMods && !mods.Value.Any()) + { + // we need to filter out all scores that have any mods to get all local nomod scores + scores = scores.Where(s => !s.Mods.Any()); + } + else if (filterMods) + { + // otherwise find all the scores that have *any* of the currently selected mods (similar to how web applies mod filters) + // we're creating and using a string list representation of selected mods so that it can be translated into the DB query itself + var selectedMods = mods.Value.Select(m => m.Acronym); + scores = scores.Where(s => s.Mods.Any(m => selectedMods.Contains(m.Acronym))); + } + + Scores = scores.OrderByDescending(s => s.TotalScore).ToArray(); PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; + return null; } @@ -101,7 +119,7 @@ namespace osu.Game.Screens.Select.Leaderboards IReadOnlyList requestMods = null; - if (filterMods && mods.Value.Count == 0) + if (filterMods && !mods.Value.Any()) // add nomod for the request requestMods = new Mod[] { new ModNoMod() }; else if (filterMods) From 5f6544eebfc913cde2c505825a37eb429311951f Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 4 Jul 2019 12:05:07 -0700 Subject: [PATCH 1709/5608] Fix beatmap leaderboards requiring supporter when signed out --- osu.Game/Online/Leaderboards/Leaderboard.cs | 6 ------ osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index b91de93a4a..dea2ff1a21 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -231,12 +231,6 @@ namespace osu.Game.Online.Leaderboards if (getScoresRequest == null) return; - if (api?.IsLoggedIn != true) - { - PlaceholderState = PlaceholderState.NotLoggedIn; - return; - } - getScoresRequest.Failure += e => Schedule(() => { if (e is OperationCanceledException) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 62f93afbbb..68f153a97d 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -62,6 +62,12 @@ namespace osu.Game.Screens.Select.Leaderboards return null; } + if (api?.IsLoggedIn != true) + { + PlaceholderState = PlaceholderState.NotLoggedIn; + return null; + } + if (Beatmap?.OnlineBeatmapID == null) { PlaceholderState = PlaceholderState.Unavailable; From ae7da2557e15e634d140340d7e0a150a0ad31eb3 Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 4 Jul 2019 13:24:13 -0700 Subject: [PATCH 1710/5608] Fix initial colour of leaderboard mod filter --- .../UserInterface/OsuTabControlCheckbox.cs | 29 +++++-------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index 869005d05c..908fbb67bb 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -37,6 +37,8 @@ namespace osu.Game.Graphics.UserInterface text.Colour = AccentColour; icon.Colour = AccentColour; } + + updateFade(); } } @@ -48,28 +50,22 @@ namespace osu.Game.Graphics.UserInterface private const float transition_length = 500; - private void fadeIn() + private void updateFade() { - box.FadeIn(transition_length, Easing.OutQuint); - text.FadeColour(Color4.White, transition_length, Easing.OutQuint); - } - - private void fadeOut() - { - box.FadeOut(transition_length, Easing.OutQuint); - text.FadeColour(AccentColour, transition_length, Easing.OutQuint); + box.FadeTo(IsHovered ? 1 : 0, transition_length, Easing.OutQuint); + text.FadeColour(IsHovered ? Color4.White : AccentColour, transition_length, Easing.OutQuint); } protected override bool OnHover(HoverEvent e) { - fadeIn(); + updateFade(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { if (!Current.Value) - fadeOut(); + updateFade(); base.OnHoverLost(e); } @@ -117,16 +113,7 @@ namespace osu.Game.Graphics.UserInterface Current.ValueChanged += selected => { - if (selected.NewValue) - { - fadeIn(); - icon.Icon = FontAwesome.Regular.CheckCircle; - } - else - { - fadeOut(); - icon.Icon = FontAwesome.Regular.Circle; - } + icon.Icon = selected.NewValue ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.Circle; }; } } From 38dceddc2710567b683144a908e1cc19374726fd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Jul 2019 10:07:45 +0900 Subject: [PATCH 1711/5608] Fix file ordering --- .../UserInterface/OsuTabControlCheckbox.cs | 59 +++++++++---------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index 908fbb67bb..8134cfb42d 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -50,33 +50,6 @@ namespace osu.Game.Graphics.UserInterface private const float transition_length = 500; - private void updateFade() - { - box.FadeTo(IsHovered ? 1 : 0, transition_length, Easing.OutQuint); - text.FadeColour(IsHovered ? Color4.White : AccentColour, transition_length, Easing.OutQuint); - } - - protected override bool OnHover(HoverEvent e) - { - updateFade(); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - if (!Current.Value) - updateFade(); - - base.OnHoverLost(e); - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - if (accentColour == null) - AccentColour = colours.Blue; - } - public OsuTabControlCheckbox() { AutoSizeAxes = Axes.Both; @@ -111,10 +84,34 @@ namespace osu.Game.Graphics.UserInterface } }; - Current.ValueChanged += selected => - { - icon.Icon = selected.NewValue ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.Circle; - }; + Current.ValueChanged += selected => { icon.Icon = selected.NewValue ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.Circle; }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + if (accentColour == null) + AccentColour = colours.Blue; + } + + protected override bool OnHover(HoverEvent e) + { + updateFade(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + if (!Current.Value) + updateFade(); + + base.OnHoverLost(e); + } + + private void updateFade() + { + box.FadeTo(IsHovered ? 1 : 0, transition_length, Easing.OutQuint); + text.FadeColour(IsHovered ? Color4.White : AccentColour, transition_length, Easing.OutQuint); } } } From bff5ad22f4fedf8c3a1c1ae9bb1e6cf791ed676e Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 5 Jul 2019 05:16:40 +0300 Subject: [PATCH 1712/5608] Check if the locally available score has files --- osu.Game/Scoring/ScoreManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 2d82987da0..f0d897701c 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -65,6 +65,6 @@ namespace osu.Game.Scoring protected override ArchiveDownloadRequest CreateDownloadRequest(ScoreInfo score, bool minimiseDownload) => new DownloadReplayRequest(score); - protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) => items.Any(s => s.OnlineScoreID == model.OnlineScoreID); + protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) => items.Any(s => s.OnlineScoreID == model.OnlineScoreID && s.Files.Any()); } } From d624157c45afc11187b58f523c8ff0e61d005c81 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 5 Jul 2019 05:17:36 +0300 Subject: [PATCH 1713/5608] Remove unnecessary fading --- osu.Game/Screens/Play/ReplayDownloadButton.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/ReplayDownloadButton.cs b/osu.Game/Screens/Play/ReplayDownloadButton.cs index 748fe8cc90..290e00f287 100644 --- a/osu.Game/Screens/Play/ReplayDownloadButton.cs +++ b/osu.Game/Screens/Play/ReplayDownloadButton.cs @@ -86,11 +86,7 @@ namespace osu.Game.Screens.Play } }, true); - if (replayAvailability == ReplayAvailability.NotAvailable) - { - button.Enabled.Value = false; - button.Alpha = 0.6f; - } + button.Enabled.Value = replayAvailability != ReplayAvailability.NotAvailable; } private enum ReplayAvailability From 29bc2a27514a8573f17ebc1a9acf1e2e7813f003 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Jul 2019 11:29:47 +0900 Subject: [PATCH 1714/5608] Split out tests --- .../UserInterface/TestSceneButtonSystem.cs | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs index 88129308db..3b790d33b6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs @@ -24,11 +24,12 @@ namespace osu.Game.Tests.Visual.UserInterface typeof(Button) }; - public TestSceneButtonSystem() - { - OsuLogo logo; - ButtonSystem buttons; + private OsuLogo logo; + private ButtonSystem buttons; + [SetUp] + public void SetUp() => Schedule(() => + { Children = new Drawable[] { new Box @@ -37,15 +38,23 @@ namespace osu.Game.Tests.Visual.UserInterface RelativeSizeAxes = Axes.Both, }, buttons = new ButtonSystem(), - logo = new OsuLogo { RelativePositionAxes = Axes.Both } + logo = new OsuLogo + { + RelativePositionAxes = Axes.Both, + Position = new Vector2(0.5f) + } }; buttons.SetOsuLogo(logo); + }); + [Test] + public void TestAllStates() + { foreach (var s in Enum.GetValues(typeof(ButtonSystemState)).OfType().Skip(1)) AddStep($"State to {s}", () => buttons.State = s); - AddStep("Exiting menu", () => + AddStep("Enter mode", () => { buttons.State = ButtonSystemState.EnteringMode; buttons.FadeOut(400, Easing.InSine); @@ -54,7 +63,7 @@ namespace osu.Game.Tests.Visual.UserInterface .ScaleTo(0.2f, 300, Easing.InSine); }); - AddStep("Entering menu", () => + AddStep("Return to menu", () => { buttons.State = ButtonSystemState.Play; buttons.FadeIn(400, Easing.OutQuint); @@ -63,5 +72,18 @@ namespace osu.Game.Tests.Visual.UserInterface logo.FadeIn(100, Easing.OutQuint); }); } + + [Test] + public void TestSmoothExit() + { + AddStep("Enter mode", () => + { + buttons.State = ButtonSystemState.EnteringMode; + buttons.FadeOut(400, Easing.InSine); + buttons.MoveTo(new Vector2(-800, 0), 400, Easing.InSine); + logo.FadeOut(300, Easing.InSine) + .ScaleTo(0.2f, 300, Easing.InSine); + }); + } } } From a30f0c03bb071dbb4d959dc7da0c09ed4314ce51 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 5 Jul 2019 05:32:30 +0300 Subject: [PATCH 1715/5608] Fix incorrect xmldoc --- osu.Game/Online/DownloadTrackingComposite.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/DownloadTrackingComposite.cs b/osu.Game/Online/DownloadTrackingComposite.cs index 786afdf450..62d6efcb6f 100644 --- a/osu.Game/Online/DownloadTrackingComposite.cs +++ b/osu.Game/Online/DownloadTrackingComposite.cs @@ -11,7 +11,7 @@ using osu.Game.Online.API; namespace osu.Game.Online { /// - /// A component which tracks a beatmap through potential download/import/deletion. + /// A component which tracks a through potential download/import/deletion. /// public abstract class DownloadTrackingComposite : CompositeDrawable where TModel : class, IEquatable @@ -22,7 +22,7 @@ namespace osu.Game.Online private TModelManager manager; /// - /// Holds the current download state of the beatmap, whether is has already been downloaded, is in progress, or is not downloaded. + /// Holds the current download state of the , whether is has already been downloaded, is in progress, or is not downloaded. /// protected readonly Bindable State = new Bindable(); From 1dab363be309abd7e94e57b161bd63ff74fb8af5 Mon Sep 17 00:00:00 2001 From: naoey Date: Fri, 5 Jul 2019 08:42:44 +0530 Subject: [PATCH 1716/5608] Require supporter for filtering mods on online leaderboards --- osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 88ce5dc117..76bfd96305 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -117,7 +117,7 @@ namespace osu.Game.Screens.Select.Leaderboards return null; } - if (Scope != BeatmapLeaderboardScope.Global && !api.LocalUser.Value.IsSupporter) + if (!api.LocalUser.Value.IsSupporter && (Scope != BeatmapLeaderboardScope.Global || filterMods)) { PlaceholderState = PlaceholderState.NotSupporter; return null; From f1dab946fff325ae420f87364a2636af4293316f Mon Sep 17 00:00:00 2001 From: naoey Date: Fri, 5 Jul 2019 08:46:17 +0530 Subject: [PATCH 1717/5608] Remove need to trim query string --- osu.Game/Online/API/Requests/GetScoresRequest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 53349e15d5..6b0e680eb5 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -50,13 +50,13 @@ namespace osu.Game.Online.API.Requests { StringBuilder query = new StringBuilder(@"?"); - query.Append($@"type={scope.ToString().ToLowerInvariant()}&"); - query.Append($@"mode={ruleset.ShortName}&"); + query.Append($@"type={scope.ToString().ToLowerInvariant()}"); + query.Append($@"&mode={ruleset.ShortName}"); foreach (var mod in mods) - query.Append($@"mods[]={mod.Acronym}&"); + query.Append($@"&mods[]={mod.Acronym}"); - return query.ToString().TrimEnd('&'); + return query.ToString(); } } } From 79d6670dc581ed27edaef31a0b57466fce707aeb Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 5 Jul 2019 13:08:45 +0900 Subject: [PATCH 1718/5608] Expose durations from MainMenu and reorder --- .../UserInterface/TestSceneButtonSystem.cs | 8 ++++---- osu.Game/Screens/Menu/MainMenu.cs | 20 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs index 88129308db..461db4a30c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs @@ -48,8 +48,8 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Exiting menu", () => { buttons.State = ButtonSystemState.EnteringMode; - buttons.FadeOut(400, Easing.InSine); - buttons.MoveTo(new Vector2(-800, 0), 400, Easing.InSine); + buttons.FadeOut(MainMenu.FADE_OUT_DURATION, Easing.InSine); + buttons.MoveTo(new Vector2(-800, 0), MainMenu.FADE_OUT_DURATION, Easing.InSine); logo.FadeOut(300, Easing.InSine) .ScaleTo(0.2f, 300, Easing.InSine); }); @@ -57,8 +57,8 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Entering menu", () => { buttons.State = ButtonSystemState.Play; - buttons.FadeIn(400, Easing.OutQuint); - buttons.MoveTo(new Vector2(0), 400, Easing.OutQuint); + buttons.FadeIn(MainMenu.FADE_IN_DURATION, Easing.OutQuint); + buttons.MoveTo(new Vector2(0), MainMenu.FADE_IN_DURATION, Easing.OutQuint); logo.FadeColour(Color4.White, 100, Easing.OutQuint); logo.FadeIn(100, Easing.OutQuint); }); diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 7e6de54d1b..c64bea840f 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -23,7 +23,9 @@ namespace osu.Game.Screens.Menu { public class MainMenu : OsuScreen { - private ButtonSystem buttons; + public const float FADE_IN_DURATION = 300; + + public const float FADE_OUT_DURATION = 400; public override bool HideOverlaysOnEnter => buttons == null || buttons.State == ButtonSystemState.Initial; @@ -35,6 +37,8 @@ namespace osu.Game.Screens.Menu private MenuSideFlashes sideFlashes; + private ButtonSystem buttons; + [Resolved] private GameHost host { get; set; } @@ -141,12 +145,10 @@ namespace osu.Game.Screens.Menu { buttons.State = ButtonSystemState.TopLevel; - const float length = 300; + this.FadeIn(FADE_IN_DURATION, Easing.OutQuint); + this.MoveTo(new Vector2(0, 0), FADE_IN_DURATION, Easing.OutQuint); - this.FadeIn(length, Easing.OutQuint); - this.MoveTo(new Vector2(0, 0), length, Easing.OutQuint); - - sideFlashes.Delay(length).FadeIn(64, Easing.InQuint); + sideFlashes.Delay(FADE_IN_DURATION).FadeIn(64, Easing.InQuint); } } @@ -171,12 +173,10 @@ namespace osu.Game.Screens.Menu { base.OnSuspending(next); - const float length = 400; - buttons.State = ButtonSystemState.EnteringMode; - this.FadeOut(length, Easing.InSine); - this.MoveTo(new Vector2(-800, 0), length, Easing.InSine); + this.FadeOut(FADE_OUT_DURATION, Easing.InSine); + this.MoveTo(new Vector2(-800, 0), FADE_OUT_DURATION, Easing.InSine); sideFlashes.FadeOut(64, Easing.OutQuint); } From 4eb01b12be4f0cba9ec6a8aa8d17cabafb88284d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 5 Jul 2019 13:10:59 +0900 Subject: [PATCH 1719/5608] Convert to method --- .../UserInterface/TestSceneButtonSystem.cs | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs index 9bc8f332f4..f0e1c38525 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs @@ -54,14 +54,7 @@ namespace osu.Game.Tests.Visual.UserInterface foreach (var s in Enum.GetValues(typeof(ButtonSystemState)).OfType().Skip(1)) AddStep($"State to {s}", () => buttons.State = s); - AddStep("Enter mode", () => - { - buttons.State = ButtonSystemState.EnteringMode; - buttons.FadeOut(MainMenu.FADE_OUT_DURATION, Easing.InSine); - buttons.MoveTo(new Vector2(-800, 0), MainMenu.FADE_OUT_DURATION, Easing.InSine); - logo.FadeOut(300, Easing.InSine) - .ScaleTo(0.2f, 300, Easing.InSine); - }); + AddStep("Enter mode", performEnterMode); AddStep("Return to menu", () => { @@ -76,14 +69,16 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TestSmoothExit() { - AddStep("Enter mode", () => - { - buttons.State = ButtonSystemState.EnteringMode; - buttons.FadeOut(400, Easing.InSine); - buttons.MoveTo(new Vector2(-800, 0), 400, Easing.InSine); - logo.FadeOut(300, Easing.InSine) - .ScaleTo(0.2f, 300, Easing.InSine); - }); + AddStep("Enter mode", performEnterMode); + } + + private void performEnterMode() + { + buttons.State = ButtonSystemState.EnteringMode; + buttons.FadeOut(MainMenu.FADE_OUT_DURATION, Easing.InSine); + buttons.MoveTo(new Vector2(-800, 0), MainMenu.FADE_OUT_DURATION, Easing.InSine); + logo.FadeOut(300, Easing.InSine) + .ScaleTo(0.2f, 300, Easing.InSine); } } } From e8168037f915a506b1026723a7ad687495a31ef1 Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 4 Jul 2019 21:19:51 -0700 Subject: [PATCH 1720/5608] Fix unranked beatmap leaderboards showing "no records" placeholder --- .../Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 68f153a97d..34f46608da 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -68,10 +68,14 @@ namespace osu.Game.Screens.Select.Leaderboards return null; } - if (Beatmap?.OnlineBeatmapID == null) + switch (Beatmap?.Status) { - PlaceholderState = PlaceholderState.Unavailable; - return null; + case BeatmapSetOnlineStatus.Graveyard: + case BeatmapSetOnlineStatus.None: + case BeatmapSetOnlineStatus.Pending: + case BeatmapSetOnlineStatus.WIP: + PlaceholderState = PlaceholderState.Unavailable; + return null; } if (Scope != BeatmapLeaderboardScope.Global && !api.LocalUser.Value.IsSupporter) From 04ef6c4d45741bae700e266370c10d9ea574079c Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 4 Jul 2019 21:25:10 -0700 Subject: [PATCH 1721/5608] Add beatmap status tests --- .../Visual/SongSelect/TestSceneLeaderboard.cs | 98 ++++++++++++++----- 1 file changed, 73 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs index 157e572606..fc42048984 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs @@ -47,7 +47,14 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter)); AddStep(@"Not logged in", () => leaderboard.SetRetrievalState(PlaceholderState.NotLoggedIn)); AddStep(@"Unavailable", () => leaderboard.SetRetrievalState(PlaceholderState.Unavailable)); - AddStep(@"Real beatmap", realBeatmap); + AddStep(@"Ranked beatmap", rankedBeatmap); + AddStep(@"Approved beatmap", approvedBeatmap); + AddStep(@"Qualified beatmap", qualifiedBeatmap); + AddStep(@"Loved beatmap", lovedBeatmap); + AddStep(@"Pending beatmap", pendingBeatmap); + AddStep(@"WIP beatmap", wipBeatmap); + AddStep(@"Graveyard beatmap", graveyardBeatmap); + AddStep(@"Unpublished beatmap", unpublishedBeatmap); } [BackgroundDependencyLoader] @@ -245,34 +252,75 @@ namespace osu.Game.Tests.Visual.SongSelect leaderboard.Scores = scores; } - private void realBeatmap() + private void rankedBeatmap() { leaderboard.Beatmap = new BeatmapInfo { - StarDifficulty = 1.36, - Version = @"BASIC", OnlineBeatmapID = 1113057, - Ruleset = rulesets.GetRuleset(0), - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 4, - DrainRate = 6.5f, - OverallDifficulty = 6.5f, - ApproachRate = 5, - }, - OnlineInfo = new BeatmapOnlineInfo - { - Length = 115000, - CircleCount = 265, - SliderCount = 71, - PlayCount = 47906, - PassCount = 19899, - }, - Metrics = new BeatmapMetrics - { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, + Status = BeatmapSetOnlineStatus.Ranked, + }; + } + + private void approvedBeatmap() + { + leaderboard.Beatmap = new BeatmapInfo + { + OnlineBeatmapID = 1113057, + Status = BeatmapSetOnlineStatus.Approved, + }; + } + + private void qualifiedBeatmap() + { + leaderboard.Beatmap = new BeatmapInfo + { + OnlineBeatmapID = 1113057, + Status = BeatmapSetOnlineStatus.Qualified, + }; + } + + private void lovedBeatmap() + { + leaderboard.Beatmap = new BeatmapInfo + { + OnlineBeatmapID = 1113057, + Status = BeatmapSetOnlineStatus.Loved, + }; + } + + private void pendingBeatmap() + { + leaderboard.Beatmap = new BeatmapInfo + { + OnlineBeatmapID = 1113057, + Status = BeatmapSetOnlineStatus.Pending, + }; + } + + private void wipBeatmap() + { + leaderboard.Beatmap = new BeatmapInfo + { + OnlineBeatmapID = 1113057, + Status = BeatmapSetOnlineStatus.WIP, + }; + } + + private void graveyardBeatmap() + { + leaderboard.Beatmap = new BeatmapInfo + { + OnlineBeatmapID = 1113057, + Status = BeatmapSetOnlineStatus.Graveyard, + }; + } + + private void unpublishedBeatmap() + { + leaderboard.Beatmap = new BeatmapInfo + { + OnlineBeatmapID = null, + Status = BeatmapSetOnlineStatus.None, }; } From 1534b75d27658a3bc671a3a483f276bc49e67766 Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 4 Jul 2019 21:39:21 -0700 Subject: [PATCH 1722/5608] Fix ci errors --- .../Visual/SongSelect/TestSceneLeaderboard.cs | 11 ----------- .../Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 6 ++++++ 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs index fc42048984..f6164c8a73 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs @@ -4,12 +4,9 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.Leaderboards; -using osu.Game.Rulesets; using osu.Game.Scoring; using osu.Game.Screens.Select.Leaderboards; using osu.Game.Users; @@ -27,8 +24,6 @@ namespace osu.Game.Tests.Visual.SongSelect typeof(RetrievalFailurePlaceholder), }; - private RulesetStore rulesets; - private readonly FailableLeaderboard leaderboard; public TestSceneLeaderboard() @@ -57,12 +52,6 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"Unpublished beatmap", unpublishedBeatmap); } - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) - { - this.rulesets = rulesets; - } - private void newScores() { var scores = new[] diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 34f46608da..550e87bcdc 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -68,6 +68,12 @@ namespace osu.Game.Screens.Select.Leaderboards return null; } + if (Beatmap?.OnlineBeatmapID == null) + { + PlaceholderState = PlaceholderState.Unavailable; + return null; + } + switch (Beatmap?.Status) { case BeatmapSetOnlineStatus.Graveyard: From 8346c50ce113cdecea9378cf2a723795251c197b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Jul 2019 13:49:54 +0900 Subject: [PATCH 1723/5608] Rename delete method and improve xmldoc --- osu.Game/Beatmaps/BeatmapManager.cs | 4 +--- osu.Game/Database/ArchiveModelManager.cs | 8 +++++--- osu.Game/Skinning/SkinManager.cs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 643fef5904..df9c8973ea 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -82,9 +82,7 @@ namespace osu.Game.Beatmaps protected override ArchiveDownloadRequest CreateDownloadRequest(BeatmapSetInfo set, bool minimiseDownloadSize) => new DownloadBeatmapSetRequest(set, minimiseDownloadSize); - protected override IEnumerable GetStableImportPaths() => GetStableStorage().GetDirectories(ImportFromStablePath); - - protected override bool ShouldRemoveArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osz"; + protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osz"; protected override Task Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive, CancellationToken cancellationToken = default) { diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 939333c6f4..dabd8fa2ef 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -176,7 +176,7 @@ namespace osu.Game.Database // TODO: Add a check to prevent files from storage to be deleted. try { - if (import != null && File.Exists(path) && ShouldRemoveArchive(path)) + if (import != null && File.Exists(path) && ShouldDeleteArchive(path)) File.Delete(path); } catch (Exception e) @@ -504,9 +504,11 @@ namespace osu.Game.Database protected abstract IEnumerable GetStableImportPaths(); /// - /// Should this archive be removed after importing? + /// Whether this specified path should be removed after successful import. /// - protected virtual bool ShouldRemoveArchive(string path) => false; + /// The path for consideration. May be a file or a directory. + /// Whether to perform deletion. + protected virtual bool ShouldDeleteArchive(string path) => false; /// /// This is a temporary method and will likely be replaced by a full-fledged (and more correctly placed) migration process in the future. diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 00e6fddc6a..3509263e6f 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -57,7 +57,7 @@ namespace osu.Game.Skinning protected override IEnumerable GetStableImportPaths() => GetStableStorage().GetDirectories(ImportFromStablePath); - protected override bool ShouldRemoveArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osk"; + protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osk"; /// /// Returns a list of all usable s. Includes the special default skin plus all skins from . From ba8df3ba9244034db85fa92828e19c7c9ce4c689 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Jul 2019 13:59:31 +0900 Subject: [PATCH 1724/5608] Clean up stable lookup and mutate logic --- osu.Game/Database/ArchiveModelManager.cs | 6 +++--- osu.Game/Scoring/ScoreManager.cs | 5 ++--- osu.Game/Skinning/SkinManager.cs | 2 -- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index dabd8fa2ef..445c8feb3b 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -486,7 +486,7 @@ namespace osu.Game.Database /// /// Set a storage with access to an osu-stable install for import purposes. /// - public Func GetStableStorage { protected get; set; } + public Func GetStableStorage { private get; set; } /// /// Denotes whether an osu-stable installation is present to perform automated imports from. @@ -501,7 +501,7 @@ namespace osu.Game.Database /// /// Selects paths to import from. /// - protected abstract IEnumerable GetStableImportPaths(); + protected virtual IEnumerable GetStableImportPaths(Storage stableStoage) => stableStoage.GetDirectories(ImportFromStablePath); /// /// Whether this specified path should be removed after successful import. @@ -530,7 +530,7 @@ namespace osu.Game.Database return Task.CompletedTask; } - return Task.Run(async () => await Import(GetStableImportPaths().Select(f => stable.GetFullPath(f)).ToArray())); + return Task.Run(async () => await Import(GetStableImportPaths(GetStableStorage()).Select(f => stable.GetFullPath(f)).ToArray())); } #endregion diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 4c7de90d6f..770b56e1fe 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -56,9 +56,8 @@ namespace osu.Game.Scoring } } - protected override IEnumerable GetStableImportPaths() - => GetStableStorage().GetFiles(ImportFromStablePath) - .Where(p => HandledExtensions.Any(ext => Path.GetExtension(p)?.Equals(ext, StringComparison.InvariantCultureIgnoreCase) ?? false)); + protected override IEnumerable GetStableImportPaths(Storage stableStorage) + => stableStorage.GetFiles(ImportFromStablePath).Where(p => HandledExtensions.Any(ext => Path.GetExtension(p)?.Equals(ext, StringComparison.InvariantCultureIgnoreCase) ?? false)); public Score GetScore(ScoreInfo score) => new LegacyDatabasedScore(score, rulesets, beatmaps(), Files.Store); diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 3509263e6f..70abfac501 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -55,8 +55,6 @@ namespace osu.Game.Skinning }; } - protected override IEnumerable GetStableImportPaths() => GetStableStorage().GetDirectories(ImportFromStablePath); - protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osk"; /// From 99da04527d5ca2b2e130acce60d1f5a1f831413d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Jul 2019 14:07:14 +0900 Subject: [PATCH 1725/5608] Replays -> scores --- .../Overlays/Settings/Sections/Maintenance/GeneralSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs index e3f5acc8ac..832673703b 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs @@ -58,7 +58,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { Add(importScoresButton = new SettingsButton { - Text = "Import replays from stable", + Text = "Import scores from stable", Action = () => { importScoresButton.Enabled.Value = false; From 87c8fd0035ec6fa0b7cf37dbe10f674f695127ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Jul 2019 14:15:29 +0900 Subject: [PATCH 1726/5608] Fix path specification not being cross-platform compliant --- osu.Game/Scoring/ScoreManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 770b56e1fe..d78e9e073e 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -25,7 +25,7 @@ namespace osu.Game.Scoring protected override string[] HashableFileTypes => new[] { ".osr" }; - protected override string ImportFromStablePath => @"Data\r"; + protected override string ImportFromStablePath => Path.Combine("Data", "r"); private readonly RulesetStore rulesets; private readonly Func beatmaps; From 80d8ce83928a09042fd52c5d985fc051d836445f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Jul 2019 14:21:56 +0900 Subject: [PATCH 1727/5608] Fix GetStableImportPaths xmldoc --- osu.Game/Database/ArchiveModelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 445c8feb3b..355411063d 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -499,7 +499,7 @@ namespace osu.Game.Database protected virtual string ImportFromStablePath => null; /// - /// Selects paths to import from. + /// Select paths to import from stable. Default implementation iterates all directories in . /// protected virtual IEnumerable GetStableImportPaths(Storage stableStoage) => stableStoage.GetDirectories(ImportFromStablePath); From adf6d6c942b2c32c4522458c0023fb89da32915c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Jul 2019 14:25:52 +0900 Subject: [PATCH 1728/5608] Update initial run import process to include scores --- osu.Game/Screens/Select/ImportFromStablePopup.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/ImportFromStablePopup.cs b/osu.Game/Screens/Select/ImportFromStablePopup.cs index 54e4c096f6..20494829ae 100644 --- a/osu.Game/Screens/Select/ImportFromStablePopup.cs +++ b/osu.Game/Screens/Select/ImportFromStablePopup.cs @@ -12,7 +12,7 @@ namespace osu.Game.Screens.Select public ImportFromStablePopup(Action importFromStable) { HeaderText = @"You have no beatmaps!"; - BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps (and skins)?"; + BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps, skins and scores?"; Icon = FontAwesome.Solid.Plane; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 3581ed5534..bf5857f725 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -35,6 +35,7 @@ using System.Linq; using System.Threading.Tasks; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; +using osu.Game.Scoring; namespace osu.Game.Screens.Select { @@ -215,7 +216,7 @@ namespace osu.Game.Screens.Select } [BackgroundDependencyLoader(true)] - private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins) + private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { mods.BindTo(Mods); @@ -252,7 +253,7 @@ namespace osu.Game.Screens.Select if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable) dialogOverlay.Push(new ImportFromStablePopup(() => { - Task.Run(beatmaps.ImportFromStableAsync); + Task.Run(beatmaps.ImportFromStableAsync).ContinueWith(_ => scores.ImportFromStableAsync(), TaskContinuationOptions.OnlyOnRanToCompletion); Task.Run(skins.ImportFromStableAsync); })); }); From df7d31350c8fe8e22478d88f5a57da0b83d88a30 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Jul 2019 14:47:55 +0900 Subject: [PATCH 1729/5608] Stop import failures from being added to the imported model list --- osu.Game/Database/ArchiveModelManager.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 01455e7d50..7d81b95203 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -114,7 +114,8 @@ namespace osu.Game.Database lock (imported) { - imported.Add(model); + if (model != null) + imported.Add(model); current++; notification.Text = $"Imported {current} of {paths.Length} {HumanisedModelName}s"; @@ -140,7 +141,7 @@ namespace osu.Game.Database { notification.CompletionText = imported.Count == 1 ? $"Imported {imported.First()}!" - : $"Imported {current} {HumanisedModelName}s!"; + : $"Imported {imported.Count} {HumanisedModelName}s!"; if (imported.Count > 0 && PresentImport != null) { From e69160a0ce1f80bee073cc618c7205106ac5a206 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 5 Jul 2019 08:05:18 +0200 Subject: [PATCH 1730/5608] fix graph not completely hiding --- osu.Game/Screens/Play/SongProgress.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index a535dc3333..a201b04864 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -172,7 +172,7 @@ namespace osu.Game.Screens.Play float barHeight = bottom_bar_height + handle_size.Y; bar.ResizeHeightTo(CollapseGraph.Value ? barHeight : barHeight + graph_height, transition_duration, Easing.In); - graph.MoveToY(CollapseGraph.Value ? graph_height : 0, transition_duration, Easing.In); + graph.MoveToY(CollapseGraph.Value ? bottom_bar_height + graph_height : 0, transition_duration, Easing.In); updateInfoMargin(); } From c22667bdf79eed3048331c1350526041553761f5 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 5 Jul 2019 08:05:23 +0200 Subject: [PATCH 1731/5608] reorganise tests --- .../Visual/Gameplay/TestSceneSongProgress.cs | 128 ++++++++++++------ 1 file changed, 84 insertions(+), 44 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index eef7a25c7a..810659233b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.MathUtils; +using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Play; @@ -21,65 +22,104 @@ namespace osu.Game.Tests.Visual.Gameplay typeof(SongProgressBar), }; - private readonly SongProgress progress; - private readonly TestSongProgressGraph graph; + private SongProgress progress; + private TestSongProgressGraph graph; private readonly StopwatchClock clock; + private readonly FramedClock framedClock; [Cached] private readonly GameplayClock gameplayClock; - private readonly FramedClock framedClock; - public TestSceneSongProgress() { - clock = new StopwatchClock(true); - + clock = new StopwatchClock(); gameplayClock = new GameplayClock(framedClock = new FramedClock(clock)); - - Add(progress = new SongProgress - { - RelativeSizeAxes = Axes.X, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - }); - - Add(graph = new TestSongProgressGraph - { - RelativeSizeAxes = Axes.X, - Height = 200, - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - }); - - AddAssert("ensure not created", () => graph.CreationCount == 0); - - AddStep("display values", displayNewValues); - AddUntilStep("wait for creation count", () => graph.CreationCount == 1); - - AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking); - AddUntilStep("wait for creation count", () => graph.CreationCount == 1); - - AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking); - AddUntilStep("wait for creation count", () => graph.CreationCount == 1); - AddRepeatStep("New Values", displayNewValues, 5); - - AddWaitStep("wait some", 5); - AddAssert("ensure debounced", () => graph.CreationCount == 2); - - AddStep("hide graph", () => progress.CollapseGraph.Value = true); - AddStep("show graph", () => progress.CollapseGraph.Value = false); - - AddStep("start", clock.Start); - AddStep("pause", clock.Stop); } - private void displayNewValues() + [SetUpSteps] + public void SetupSteps() { - List objects = new List(); + AddStep("add new song progress", () => + { + if (progress != null) + { + progress.Expire(); + progress = null; + } + + Add(progress = new SongProgress + { + RelativeSizeAxes = Axes.X, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + }); + }); + + AddStep("add new big graph", () => + { + if (graph != null) + { + graph.Expire(); + graph = null; + } + + Add(graph = new TestSongProgressGraph + { + RelativeSizeAxes = Axes.X, + Height = 200, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }); + }); + + AddStep("reset clock", clock.Reset); + } + + [Test] + public void TestGraphRecreation() + { + AddAssert("ensure not created", () => graph.CreationCount == 0); + AddStep("display values", displayRandomValues); + AddUntilStep("wait for creation count", () => graph.CreationCount == 1); + AddRepeatStep("new values", displayRandomValues, 5); + AddWaitStep("wait some", 5); + AddAssert("ensure recreation debounced", () => graph.CreationCount == 2); + } + + [Test] + public void TestDisplay() + { + AddStep("display max values", displayMaxValues); + AddStep("start", clock.Start); + AddStep("show bar", () => progress.AllowSeeking = true); + AddStep("hide graph", () => progress.CollapseGraph.Value = true); + AddStep("hide Bar", () => progress.AllowSeeking = false); + AddStep("show bar", () => progress.AllowSeeking = true); + AddStep("show graph", () => progress.CollapseGraph.Value = false); + AddStep("stop", clock.Stop); + } + + private void displayRandomValues() + { + var objects = new List(); for (double i = 0; i < 5000; i += RNG.NextDouble() * 10 + i / 1000) objects.Add(new HitObject { StartTime = i }); + replaceObjects(objects); + } + + private void displayMaxValues() + { + var objects = new List(); + for (double i = 0; i < 5000; i++) + objects.Add(new HitObject { StartTime = i }); + + replaceObjects(objects); + } + + private void replaceObjects(List objects) + { progress.Objects = objects; graph.Objects = objects; From 3d12c709a53bf0d8343797c327daf8296644f15d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 5 Jul 2019 15:40:47 +0930 Subject: [PATCH 1732/5608] Add test case --- .../OsuDifficultyCalculatorTest.cs | 1 + .../Testing/Beatmaps/zero-length-sliders.osu | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/zero-length-sliders.osu diff --git a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs index e55dc1f902..693faee3b7 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs @@ -15,6 +15,7 @@ namespace osu.Game.Rulesets.Osu.Tests protected override string ResourceAssembly => "osu.Game.Rulesets.Osu"; [TestCase(6.931145117263422, "diffcalc-test")] + [TestCase(1.0736587013228804d, "zero-length-sliders")] public void Test(double expected, string name) => base.Test(expected, name); diff --git a/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/zero-length-sliders.osu b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/zero-length-sliders.osu new file mode 100644 index 0000000000..18736043b5 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/zero-length-sliders.osu @@ -0,0 +1,28 @@ +osu file format v14 + +[Difficulty] +HPDrainRate:3 +CircleSize:3 +OverallDifficulty:3 +ApproachRate:4.5 +SliderMultiplier:0.799999999999999 +SliderTickRate:1 + +[TimingPoints] +800,260.869565217391,3,2,10,60,1,0 + +[HitObjects] +// Linear +78,193,2365,2,0,L|330:193,1,0 +78,193,3669,2,0,L|330:193,1,0 +78,193,4973,2,0,L|330:193,1,0 + +// Perfect-curve +151,206,6278,2,0,P|293:75|345:204,1,0 +151,206,8104,2,0,P|293:75|345:204,1,0 +151,206,9930,2,0,P|293:75|345:204,1,0 + +// Bezier +76,191,11756,2,0,B|176:59|358:340|438:190,1,0 +76,191,13582,2,0,B|176:59|358:340|438:190,1,0 +76,191,15408,2,0,B|176:59|358:340|438:190,1,0 From 1cb7a9617be89f5f01f6b21bc6ce280fdf8e2c95 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 5 Jul 2019 08:29:57 +0200 Subject: [PATCH 1733/5608] move songprogress up to be able to see below for masking --- .../Visual/Gameplay/TestSceneSongProgress.cs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index 810659233b..550115846b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -6,9 +6,12 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; using osu.Framework.Testing; using osu.Framework.Timing; +using osu.Game.Graphics; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Play; @@ -24,6 +27,7 @@ namespace osu.Game.Tests.Visual.Gameplay private SongProgress progress; private TestSongProgressGraph graph; + private readonly Container progressContainer; private readonly StopwatchClock clock; private readonly FramedClock framedClock; @@ -35,6 +39,20 @@ namespace osu.Game.Tests.Visual.Gameplay { clock = new StopwatchClock(); gameplayClock = new GameplayClock(framedClock = new FramedClock(clock)); + + Add(progressContainer = new Container + { + RelativeSizeAxes = Axes.X, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Height = 100, + Y = -100, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(1), + } + }); } [SetUpSteps] @@ -48,7 +66,7 @@ namespace osu.Game.Tests.Visual.Gameplay progress = null; } - Add(progress = new SongProgress + progressContainer.Add(progress = new SongProgress { RelativeSizeAxes = Axes.X, Anchor = Anchor.BottomLeft, @@ -91,6 +109,7 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestDisplay() { AddStep("display max values", displayMaxValues); + AddUntilStep("wait for graph", () => graph.CreationCount == 1); AddStep("start", clock.Start); AddStep("show bar", () => progress.AllowSeeking = true); AddStep("hide graph", () => progress.CollapseGraph.Value = true); From ed22c23f37bf57a9d1de77db3a905a718a5394db Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 5 Jul 2019 08:30:32 +0200 Subject: [PATCH 1734/5608] mask SongProgress --- osu.Game/Screens/Play/SongProgress.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index a201b04864..9ebfeb5c82 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -77,8 +77,8 @@ namespace osu.Game.Screens.Play public SongProgress() { - Height = bottom_bar_height + graph_height + handle_size.Y; - Y = bottom_bar_height; + Masking = true; + Height = bottom_bar_height + graph_height + handle_size.Y + OsuFont.Numeric.Size; Children = new Drawable[] { @@ -88,7 +88,6 @@ namespace osu.Game.Screens.Play Anchor = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Bottom = bottom_bar_height + graph_height }, }, graph = new SongProgressGraph { From b902457f8dbe8609b679cdbdfce50cfba3d113d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Jul 2019 15:32:07 +0900 Subject: [PATCH 1735/5608] Allow PlayerLoader to proceed even if the mouse is hovering an overlay panel --- osu.Game/Screens/Play/PlayerLoader.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 681ce701d0..5396321160 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -18,6 +18,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Input; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Menu; using osu.Game.Screens.Play.HUD; @@ -53,6 +54,8 @@ namespace osu.Game.Screens.Play private InputManager inputManager; + private IdleTracker idleTracker; + public PlayerLoader(Func createPlayer) { this.createPlayer = createPlayer; @@ -93,7 +96,8 @@ namespace osu.Game.Screens.Play VisualSettings = new VisualSettings(), new InputSettings() } - } + }, + idleTracker = new IdleTracker(750) }); loadNewPlayer(); @@ -193,7 +197,7 @@ namespace osu.Game.Screens.Play // Here because IsHovered will not update unless we do so. public override bool HandlePositionalInput => true; - private bool readyForPush => player.LoadState == LoadState.Ready && IsHovered && GetContainingInputManager()?.DraggedDrawable == null; + private bool readyForPush => player.LoadState == LoadState.Ready && (IsHovered || idleTracker.IsIdle.Value) && inputManager?.DraggedDrawable == null; private void pushWhenLoaded() { From b425df6c75afa792aa97165a798d3a884c6a8c04 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 5 Jul 2019 08:48:40 +0200 Subject: [PATCH 1736/5608] various fixes - make AllowSeeking a Bindable which fixes incorrect initial position and removes unnecessary variables - make SongProgressInfo fixed height --- .../Visual/Gameplay/TestSceneSongProgress.cs | 6 +-- osu.Game/Screens/Play/SongProgress.cs | 45 ++++++++----------- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index 550115846b..e16ad42558 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -111,10 +111,10 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("display max values", displayMaxValues); AddUntilStep("wait for graph", () => graph.CreationCount == 1); AddStep("start", clock.Start); - AddStep("show bar", () => progress.AllowSeeking = true); + AddStep("show bar", () => progress.AllowSeeking.Value = true); AddStep("hide graph", () => progress.CollapseGraph.Value = true); - AddStep("hide Bar", () => progress.AllowSeeking = false); - AddStep("show bar", () => progress.AllowSeeking = true); + AddStep("hide Bar", () => progress.AllowSeeking.Value = false); + AddStep("show bar", () => progress.AllowSeeking.Value = true); AddStep("show graph", () => progress.CollapseGraph.Value = false); AddStep("stop", clock.Stop); } diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 9ebfeb5c82..9d1978e4cd 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -20,6 +20,7 @@ namespace osu.Game.Screens.Play { public class SongProgress : OverlayContainer { + private const int info_height = 20; private const int bottom_bar_height = 5; private const float graph_height = SquareGraph.Column.WIDTH * 6; private static readonly Vector2 handle_size = new Vector2(10, 18); @@ -31,10 +32,19 @@ namespace osu.Game.Screens.Play private readonly SongProgressInfo info; public Action RequestSeek; + + /// + /// Whether seeking is allowed and the progress bar should be shown. + /// + public readonly Bindable AllowSeeking = new Bindable(); + + /// + /// Whether the difficulty graph should be shown. + /// public readonly Bindable CollapseGraph = new Bindable(); - public override bool HandleNonPositionalInput => AllowSeeking; - public override bool HandlePositionalInput => AllowSeeking; + public override bool HandleNonPositionalInput => AllowSeeking.Value; + public override bool HandlePositionalInput => AllowSeeking.Value; private double firstHitTime => objects.First().StartTime; private double lastHitTime => ((objects.Last() as IHasEndTime)?.EndTime ?? objects.Last().StartTime) + 1; @@ -55,22 +65,6 @@ namespace osu.Game.Screens.Play } } - private bool allowSeeking; - - public bool AllowSeeking - { - get => allowSeeking; - set - { - if (allowSeeking == value) return; - - allowSeeking = value; - updateBarVisibility(); - } - } - - private readonly BindableBool replayLoaded = new BindableBool(); - public IClock ReferenceClock; private IClock gameplayClock; @@ -78,7 +72,7 @@ namespace osu.Game.Screens.Play public SongProgress() { Masking = true; - Height = bottom_bar_height + graph_height + handle_size.Y + OsuFont.Numeric.Size; + Height = bottom_bar_height + graph_height + handle_size.Y + info_height; Children = new Drawable[] { @@ -87,7 +81,7 @@ namespace osu.Game.Screens.Play Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, + Height = info_height, }, graph = new SongProgressGraph { @@ -122,18 +116,17 @@ namespace osu.Game.Screens.Play { Show(); - replayLoaded.BindValueChanged(loaded => AllowSeeking = loaded.NewValue, true); + AllowSeeking.BindValueChanged(_ => updateBarVisibility(), true); CollapseGraph.BindValueChanged(_ => updateGraphVisibility(), true); } public void BindDrawableRuleset(DrawableRuleset drawableRuleset) { - replayLoaded.BindTo(drawableRuleset.HasReplayLoaded); + AllowSeeking.BindTo(drawableRuleset.HasReplayLoaded); } protected override void PopIn() { - updateBarVisibility(); this.FadeIn(500, Easing.OutQuint); } @@ -160,8 +153,8 @@ namespace osu.Game.Screens.Play private void updateBarVisibility() { - bar.FadeTo(allowSeeking ? 1 : 0, transition_duration, Easing.In); - this.MoveTo(new Vector2(0, allowSeeking ? 0 : bottom_bar_height), transition_duration, Easing.In); + bar.FadeTo(AllowSeeking.Value ? 1 : 0, transition_duration, Easing.In); + this.MoveTo(new Vector2(0, AllowSeeking.Value ? 0 : bottom_bar_height), transition_duration, Easing.In); updateInfoMargin(); } @@ -178,7 +171,7 @@ namespace osu.Game.Screens.Play private void updateInfoMargin() { - float finalMargin = bottom_bar_height + (allowSeeking ? handle_size.Y : 0) + (CollapseGraph.Value ? 0 : graph_height); + float finalMargin = bottom_bar_height + (AllowSeeking.Value ? handle_size.Y : 0) + (CollapseGraph.Value ? 0 : graph_height); info.TransformTo(nameof(info.Margin), new MarginPadding { Bottom = finalMargin }, transition_duration, Easing.In); } } From 2d5fd7f1c4fc789daabbebd0dad891ed3033a8f2 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 5 Jul 2019 08:49:56 +0200 Subject: [PATCH 1737/5608] remove unnecessarily setting value of bindable that was already bound to --- osu.Game/Screens/Play/HUDOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 017bf70133..e0036cdeb9 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -106,7 +106,6 @@ namespace osu.Game.Screens.Play BindDrawableRuleset(drawableRuleset); Progress.Objects = drawableRuleset.Objects; - Progress.AllowSeeking = drawableRuleset.HasReplayLoaded.Value; Progress.RequestSeek = time => RequestSeek(time); Progress.ReferenceClock = drawableRuleset.FrameStableClock; From 39bd5e6478daefc5369c34c89ba30bceab73716c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Jul 2019 15:50:31 +0900 Subject: [PATCH 1738/5608] Add test --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index daee3a520c..18edaf1b92 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -9,6 +9,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.MathUtils; using osu.Framework.Screens; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; @@ -16,12 +17,13 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens; using osu.Game.Screens.Play; +using osu.Game.Screens.Play.PlayerSettings; namespace osu.Game.Tests.Visual.Gameplay { public class TestScenePlayerLoader : ManualInputManagerTestScene { - private PlayerLoader loader; + private TestPlayerLoader loader; private OsuScreenStack stack; [SetUp] @@ -31,19 +33,28 @@ namespace osu.Game.Tests.Visual.Gameplay Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); }); + [Test] + public void TestBlockLoadViaMouseMovement() + { + AddStep("load dummy beatmap", () => stack.Push(loader = new TestPlayerLoader(() => new TestPlayer(false, false)))); + AddRepeatStep("move mouse", () => InputManager.MoveMouseTo(loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft + (loader.VisualSettings.ScreenSpaceDrawQuad.BottomRight - loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft) * RNG.NextSingle()), 20); + AddAssert("loader still active", () => loader.IsCurrentScreen()); + AddUntilStep("loads after idle", () => !loader.IsCurrentScreen()); + } + [Test] public void TestLoadContinuation() { Player player = null; SlowLoadPlayer slowPlayer = null; - AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => player = new TestPlayer(false, false)))); + AddStep("load dummy beatmap", () => stack.Push(loader = new TestPlayerLoader(() => player = new TestPlayer(false, false)))); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); AddUntilStep("wait for player to be current", () => player.IsCurrentScreen()); AddStep("load slow dummy beatmap", () => { - stack.Push(loader = new PlayerLoader(() => slowPlayer = new SlowLoadPlayer(false, false))); + stack.Push(loader = new TestPlayerLoader(() => slowPlayer = new SlowLoadPlayer(false, false))); Scheduler.AddDelayed(() => slowPlayer.AllowLoad.Set(), 5000); }); @@ -61,7 +72,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("load player", () => { Mods.Value = new[] { gameMod = new TestMod() }; - stack.Push(loader = new PlayerLoader(() => player = new TestPlayer())); + stack.Push(loader = new TestPlayerLoader(() => player = new TestPlayer())); }); AddUntilStep("wait for loader to become current", () => loader.IsCurrentScreen()); @@ -85,6 +96,16 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("player mods applied", () => playerMod2.Applied); } + private class TestPlayerLoader : PlayerLoader + { + public new VisualSettings VisualSettings => base.VisualSettings; + + public TestPlayerLoader(Func createPlayer) + : base(createPlayer) + { + } + } + private class TestMod : Mod, IApplicableToScoreProcessor { public override string Name => string.Empty; From ee44caf964c59439449e8d65dfa4bf73ea9fb887 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 5 Jul 2019 08:52:44 +0200 Subject: [PATCH 1739/5608] better setting description --- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 4 ++-- osu.Game/Screens/Play/SongProgress.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index f3792fcb7f..c055d7d321 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -77,7 +77,7 @@ namespace osu.Game.Configuration Set(OsuSetting.BlurLevel, 0, 0, 1, 0.01); Set(OsuSetting.ShowInterface, true); - Set(OsuSetting.CollapseProgressGraph, false); + Set(OsuSetting.ShowProgressGraph, true); Set(OsuSetting.KeyOverlay, false); Set(OsuSetting.FloatingComments, false); @@ -132,7 +132,7 @@ namespace osu.Game.Configuration KeyOverlay, FloatingComments, ShowInterface, - CollapseProgressGraph, + ShowProgressGraph, MouseDisableButtons, MouseDisableWheel, AudioOffset, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index e365973c4b..2169fc69cc 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -36,8 +36,8 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay }, new SettingsCheckbox { - LabelText = "Collapse song progress graph", - Bindable = config.GetBindable(OsuSetting.CollapseProgressGraph) + LabelText = "Show difficulty graph on progress bar", + Bindable = config.GetBindable(OsuSetting.ShowProgressGraph) }, new SettingsCheckbox { diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 9d1978e4cd..7411afb688 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -107,7 +107,7 @@ namespace osu.Game.Screens.Play if (clock != null) gameplayClock = clock; - config.BindWith(OsuSetting.CollapseProgressGraph, CollapseGraph); + config.BindWith(OsuSetting.ShowProgressGraph, CollapseGraph); graph.FillColour = bar.FillColour = colours.BlueLighter; } From a259247a98fa40d4beb3db268032225533df2e34 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 5 Jul 2019 16:07:17 +0900 Subject: [PATCH 1740/5608] use const --- osu.Game/Screens/Menu/ButtonSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 87c009c437..1a3e1213b4 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -332,7 +332,7 @@ namespace osu.Game.Screens.Menu break; case ButtonSystemState.EnteringMode: - logoTrackingContainer.StartTracking(logo, lastState == ButtonSystemState.Initial ? 400 : 0, Easing.InSine); + logoTrackingContainer.StartTracking(logo, lastState == ButtonSystemState.Initial ? MainMenu.FADE_OUT_DURATION : 0, Easing.InSine); break; } } From d05512a12a3d7c41f8276473d0fb08c31e2ba092 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 5 Jul 2019 09:16:50 +0200 Subject: [PATCH 1741/5608] invert usage corresponding to previous description change --- .../Visual/Gameplay/TestSceneSongProgress.cs | 4 ++-- osu.Game/Screens/Play/SongProgress.cs | 15 ++++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index e16ad42558..15bf907b4f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -112,10 +112,10 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for graph", () => graph.CreationCount == 1); AddStep("start", clock.Start); AddStep("show bar", () => progress.AllowSeeking.Value = true); - AddStep("hide graph", () => progress.CollapseGraph.Value = true); + AddStep("hide graph", () => progress.ShowGraph.Value = false); AddStep("hide Bar", () => progress.AllowSeeking.Value = false); AddStep("show bar", () => progress.AllowSeeking.Value = true); - AddStep("show graph", () => progress.CollapseGraph.Value = false); + AddStep("show graph", () => progress.ShowGraph.Value = true); AddStep("stop", clock.Stop); } diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 7411afb688..727fad84c9 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -38,10 +38,7 @@ namespace osu.Game.Screens.Play /// public readonly Bindable AllowSeeking = new Bindable(); - /// - /// Whether the difficulty graph should be shown. - /// - public readonly Bindable CollapseGraph = new Bindable(); + public readonly Bindable ShowGraph = new Bindable(); public override bool HandleNonPositionalInput => AllowSeeking.Value; public override bool HandlePositionalInput => AllowSeeking.Value; @@ -107,7 +104,7 @@ namespace osu.Game.Screens.Play if (clock != null) gameplayClock = clock; - config.BindWith(OsuSetting.ShowProgressGraph, CollapseGraph); + config.BindWith(OsuSetting.ShowProgressGraph, ShowGraph); graph.FillColour = bar.FillColour = colours.BlueLighter; } @@ -117,7 +114,7 @@ namespace osu.Game.Screens.Play Show(); AllowSeeking.BindValueChanged(_ => updateBarVisibility(), true); - CollapseGraph.BindValueChanged(_ => updateGraphVisibility(), true); + ShowGraph.BindValueChanged(_ => updateGraphVisibility(), true); } public void BindDrawableRuleset(DrawableRuleset drawableRuleset) @@ -163,15 +160,15 @@ namespace osu.Game.Screens.Play { float barHeight = bottom_bar_height + handle_size.Y; - bar.ResizeHeightTo(CollapseGraph.Value ? barHeight : barHeight + graph_height, transition_duration, Easing.In); - graph.MoveToY(CollapseGraph.Value ? bottom_bar_height + graph_height : 0, transition_duration, Easing.In); + bar.ResizeHeightTo(ShowGraph.Value ? barHeight + graph_height : barHeight, transition_duration, Easing.In); + graph.MoveToY(ShowGraph.Value ? 0 : bottom_bar_height + graph_height, transition_duration, Easing.In); updateInfoMargin(); } private void updateInfoMargin() { - float finalMargin = bottom_bar_height + (AllowSeeking.Value ? handle_size.Y : 0) + (CollapseGraph.Value ? 0 : graph_height); + float finalMargin = bottom_bar_height + (AllowSeeking.Value ? handle_size.Y : 0) + (ShowGraph.Value ? graph_height : 0); info.TransformTo(nameof(info.Margin), new MarginPadding { Bottom = finalMargin }, transition_duration, Easing.In); } } From 6288cc6e5c32fcc8790a9a31bf1b22f64292b11a Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 5 Jul 2019 16:03:22 +0200 Subject: [PATCH 1742/5608] Refactor OnScreenDisplay to allow displaying of custom messages on OSD --- osu.Game/Overlays/OSD/OsdToast.cs | 40 ++++++ osu.Game/Overlays/OnScreenDisplay.cs | 203 ++------------------------- osu.Game/osu.Game.csproj | 3 + 3 files changed, 55 insertions(+), 191 deletions(-) create mode 100644 osu.Game/Overlays/OSD/OsdToast.cs diff --git a/osu.Game/Overlays/OSD/OsdToast.cs b/osu.Game/Overlays/OSD/OsdToast.cs new file mode 100644 index 0000000000..f700577ba1 --- /dev/null +++ b/osu.Game/Overlays/OSD/OsdToast.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.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osuTK.Graphics; + +namespace osu.Game.Overlays.OSD +{ + public class OsdToast : Container + { + private readonly Container content; + protected override Container Content => content; + + public OsdToast() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + Width = 240; + RelativeSizeAxes = Axes.Y; + + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.7f + }, + content = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + } + }; + } + } +} diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 88a1edddc5..0577257080 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -8,17 +8,11 @@ using osu.Framework.Configuration; using osu.Framework.Configuration.Tracking; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; using osuTK; -using osuTK.Graphics; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Transforms; using osu.Framework.Threading; using osu.Game.Configuration; -using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.OSD; namespace osu.Game.Overlays { @@ -26,16 +20,9 @@ namespace osu.Game.Overlays { private readonly Container box; - private readonly SpriteText textLine1; - private readonly SpriteText textLine2; - private readonly SpriteText textLine3; - private const float height = 110; - private const float height_notext = 98; private const float height_contracted = height * 0.9f; - private readonly FillFlowContainer optionLights; - public OnScreenDisplay() { RelativeSizeAxes = Axes.Both; @@ -52,64 +39,6 @@ namespace osu.Game.Overlays Height = height_contracted, Alpha = 0, CornerRadius = 20, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.7f, - }, - new Container // purely to add a minimum width - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Width = 240, - RelativeSizeAxes = Axes.Y, - }, - textLine1 = new OsuSpriteText - { - Padding = new MarginPadding(10), - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Black), - Spacing = new Vector2(1, 0), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - }, - textLine2 = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), - Padding = new MarginPadding { Left = 10, Right = 10 }, - Anchor = Anchor.Centre, - Origin = Anchor.BottomCentre, - }, - new FillFlowContainer - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - optionLights = new FillFlowContainer - { - Padding = new MarginPadding { Top = 20, Bottom = 5 }, - Spacing = new Vector2(5, 0), - Direction = FillDirection.Horizontal, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - AutoSizeAxes = Axes.Both - }, - textLine3 = new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Margin = new MarginPadding { Bottom = 15 }, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), - Alpha = 0.3f, - }, - } - } - } }, }; } @@ -142,7 +71,7 @@ namespace osu.Game.Overlays return; configManager.LoadInto(trackedSettings); - trackedSettings.SettingChanged += display; + trackedSettings.SettingChanged += displayTrackedSettingChange; trackedConfigManagers.Add((source, configManager), trackedSettings); } @@ -162,56 +91,23 @@ namespace osu.Game.Overlays return; existing.Unload(); - existing.SettingChanged -= display; + existing.SettingChanged -= displayTrackedSettingChange; trackedConfigManagers.Remove((source, configManager)); } - private void display(SettingDescription description) + /// + /// Displays the given as parameter on the OSD + /// + /// + public void Display(OsdToast toast) { - Schedule(() => - { - textLine1.Text = description.Name.ToUpperInvariant(); - textLine2.Text = description.Value; - textLine3.Text = description.Shortcut.ToUpperInvariant(); - - if (string.IsNullOrEmpty(textLine3.Text)) - textLine3.Text = "NO KEY BOUND"; - - DisplayTemporarily(box); - - int optionCount = 0; - int selectedOption = -1; - - switch (description.RawValue) - { - case bool val: - optionCount = 1; - if (val) selectedOption = 0; - break; - - case Enum _: - var values = Enum.GetValues(description.RawValue.GetType()); - optionCount = values.Length; - selectedOption = Convert.ToInt32(description.RawValue); - break; - } - - textLine2.Origin = optionCount > 0 ? Anchor.BottomCentre : Anchor.Centre; - textLine2.Y = optionCount > 0 ? 0 : 5; - - if (optionLights.Children.Count != optionCount) - { - optionLights.Clear(); - for (int i = 0; i < optionCount; i++) - optionLights.Add(new OptionLight()); - } - - for (int i = 0; i < optionCount; i++) - optionLights.Children[i].Glowing = i == selectedOption; - }); + box.Child = toast; + DisplayTemporarily(box); } + private void displayTrackedSettingChange(SettingDescription description) => Schedule(() => Display(new OsdTrackedSettingToast(description))); + private TransformSequence fadeIn; private ScheduledDelegate fadeOut; @@ -236,80 +132,5 @@ namespace osu.Game.Overlays b => b.ResizeHeightTo(height_contracted, 1500, Easing.InQuint)); }, 500); } - - private class OptionLight : Container - { - private Color4 glowingColour, idleColour; - - private const float transition_speed = 300; - - private const float glow_strength = 0.4f; - - private readonly Box fill; - - public OptionLight() - { - Children = new[] - { - fill = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 1, - }, - }; - } - - private bool glowing; - - public bool Glowing - { - set - { - glowing = value; - if (!IsLoaded) return; - - updateGlow(); - } - } - - private void updateGlow() - { - if (glowing) - { - fill.FadeColour(glowingColour, transition_speed, Easing.OutQuint); - FadeEdgeEffectTo(glow_strength, transition_speed, Easing.OutQuint); - } - else - { - FadeEdgeEffectTo(0, transition_speed, Easing.OutQuint); - fill.FadeColour(idleColour, transition_speed, Easing.OutQuint); - } - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - fill.Colour = idleColour = Color4.White.Opacity(0.4f); - glowingColour = Color4.White; - - Size = new Vector2(25, 5); - - Masking = true; - CornerRadius = 3; - - EdgeEffect = new EdgeEffectParameters - { - Colour = colours.BlueDark.Opacity(glow_strength), - Type = EdgeEffectType.Glow, - Radius = 8, - }; - } - - protected override void LoadComplete() - { - updateGlow(); - FinishTransforms(true); - } - } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e872cd1387..950a940fec 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -21,4 +21,7 @@ + + + From 4f0429d046da8d5ca21d43d26c40a1773febdd4b Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 5 Jul 2019 16:03:46 +0200 Subject: [PATCH 1743/5608] Add OsdTrackedSettingToast --- .../Overlays/OSD/OsdTrackedSettingToast.cs | 180 ++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 osu.Game/Overlays/OSD/OsdTrackedSettingToast.cs diff --git a/osu.Game/Overlays/OSD/OsdTrackedSettingToast.cs b/osu.Game/Overlays/OSD/OsdTrackedSettingToast.cs new file mode 100644 index 0000000000..411a33b000 --- /dev/null +++ b/osu.Game/Overlays/OSD/OsdTrackedSettingToast.cs @@ -0,0 +1,180 @@ +// 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.Configuration.Tracking; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; +using System; + +namespace osu.Game.Overlays.OSD +{ + public class OsdTrackedSettingToast : OsdToast + { + public OsdTrackedSettingToast(SettingDescription description) + { + SpriteText textLine2; + FillFlowContainer optionLights; + + Children = new Drawable[] + { + new OsuSpriteText + { + Padding = new MarginPadding(10), + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Black), + Spacing = new Vector2(1, 0), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = description.Name.ToUpperInvariant() + }, + textLine2 = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), + Padding = new MarginPadding { Left = 10, Right = 10 }, + Anchor = Anchor.Centre, + Origin = Anchor.BottomCentre, + Text = description.Value + }, + new FillFlowContainer + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + optionLights = new FillFlowContainer + { + Padding = new MarginPadding { Top = 20, Bottom = 5 }, + Spacing = new Vector2(5, 0), + Direction = FillDirection.Horizontal, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Margin = new MarginPadding { Bottom = 15 }, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Alpha = 0.3f, + Text = string.IsNullOrEmpty(description.Shortcut) ? "NO KEY BOUND" : description.Shortcut.ToUpperInvariant() + }, + } + } + }; + + int optionCount = 0; + int selectedOption = -1; + + switch (description.RawValue) + { + case bool val: + optionCount = 1; + if (val) selectedOption = 0; + break; + + case Enum _: + var values = Enum.GetValues(description.RawValue.GetType()); + optionCount = values.Length; + selectedOption = Convert.ToInt32(description.RawValue); + break; + } + + textLine2.Origin = optionCount > 0 ? Anchor.BottomCentre : Anchor.Centre; + textLine2.Y = optionCount > 0 ? 0 : 5; + + for (int i = 0; i < optionCount; i++) + { + optionLights.Add(new OptionLight + { + Glowing = i == selectedOption + }); + } + } + + private class OptionLight : Container + { + private Color4 glowingColour, idleColour; + + private const float transition_speed = 300; + + private const float glow_strength = 0.4f; + + private readonly Box fill; + + public OptionLight() + { + Children = new[] + { + fill = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 1, + }, + }; + } + + private bool glowing; + + public bool Glowing + { + set + { + glowing = value; + if (!IsLoaded) return; + + updateGlow(); + } + } + + private void updateGlow() + { + if (glowing) + { + fill.FadeColour(glowingColour, transition_speed, Easing.OutQuint); + FadeEdgeEffectTo(glow_strength, transition_speed, Easing.OutQuint); + } + else + { + FadeEdgeEffectTo(0, transition_speed, Easing.OutQuint); + fill.FadeColour(idleColour, transition_speed, Easing.OutQuint); + } + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + fill.Colour = idleColour = Color4.White.Opacity(0.4f); + glowingColour = Color4.White; + + Size = new Vector2(25, 5); + + Masking = true; + CornerRadius = 3; + + EdgeEffect = new EdgeEffectParameters + { + Colour = colours.BlueDark.Opacity(glow_strength), + Type = EdgeEffectType.Glow, + Radius = 8, + }; + } + + protected override void LoadComplete() + { + updateGlow(); + FinishTransforms(true); + } + } + } +} From bc60b1dc13d2b069518d3b4b4d1698c43aa48ab9 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 5 Jul 2019 16:04:47 +0200 Subject: [PATCH 1744/5608] Add test for empty OsdToast --- osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs index d900526c07..b28f794a58 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs @@ -22,6 +22,7 @@ namespace osu.Game.Tests.Visual.UserInterface osd.BeginTracking(this, config); Add(osd); + AddStep("Display empty osd toast", () => osd.Display(new Overlays.OSD.OsdToast())); AddRepeatStep("Change toggle (no bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingNoKeybind), 2); AddRepeatStep("Change toggle (with bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingWithKeybind), 2); AddRepeatStep("Change enum (no bind)", () => config.IncrementEnumSetting(TestConfigSetting.EnumSettingNoKeybind), 3); From df75f9d3124f169e2d7950fd317af11c5b481b1a Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 5 Jul 2019 16:08:02 +0200 Subject: [PATCH 1745/5608] Revert changes made by VS to csproj --- osu.Game/osu.Game.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 950a940fec..e872cd1387 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -21,7 +21,4 @@ - - - From 70372dd03d1e1735de241d431b629bdb684ae9c1 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 5 Jul 2019 16:14:04 +0200 Subject: [PATCH 1746/5608] Add global actions for game-wide music jukebox manipulation --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 14d356f889..6d85a69804 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -38,6 +38,10 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.MouseWheelDown, GlobalAction.DecreaseVolume), new KeyBinding(InputKey.F4, GlobalAction.ToggleMute), + new KeyBinding(InputKey.F5, GlobalAction.MusicPrev), + new KeyBinding(InputKey.F6, GlobalAction.MusicNext), + new KeyBinding(InputKey.X, GlobalAction.MusicPlay), + new KeyBinding(InputKey.Escape, GlobalAction.Back), new KeyBinding(InputKey.MouseButton1, GlobalAction.Back), @@ -88,6 +92,16 @@ namespace osu.Game.Input.Bindings [Description("Toggle mute")] ToggleMute, + // Game-wide beatmap jukebox keybindings + [Description("Jukebox next track")] + MusicNext, + + [Description("Jukebox previous track")] + MusicPrev, + + [Description("Jukebox play / pause current track")] + MusicPlay, + // In-Game Keybindings [Description("Skip cutscene")] SkipCutscene, From b5bd863dd080d25f0c01f9cdd30c0d6cde4a9c5d Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 5 Jul 2019 16:21:50 +0200 Subject: [PATCH 1747/5608] Add methods to MusicController to play or pause, select next or previous track --- osu.Game/Overlays/MusicController.cs | 31 +++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 29ae5983be..91fa2f5a95 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -529,6 +529,35 @@ namespace osu.Game.Overlays /// /// Play the next random or playlist track. /// - public void NextTrack() => next(); + /// Returns whether the track could be changed or not + public bool NextTrack() + { + if (beatmap.Disabled) return false; + + next(); + return true; + } + + /// + /// Play the previous random or playlist track. + /// + public bool PreviousTrack() + { + if (beatmap.Disabled) return false; + + prev(); + return true; + } + + /// + /// Play or pause the current beatmap track. + /// Returns whether the current track could be played / paused or not + public bool PlayTrack() + { + if (beatmap.Disabled) return false; + + play(); + return true; + } } } From c9e44e5e34aa481ce0210898616829c1770a67c0 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 5 Jul 2019 16:25:09 +0200 Subject: [PATCH 1748/5608] Add OsdIconToast + test --- .../UserInterface/TestSceneOnScreenDisplay.cs | 2 + osu.Game/Overlays/OSD/OsdIconToast.cs | 42 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 osu.Game/Overlays/OSD/OsdIconToast.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs index b28f794a58..047c89ae54 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Configuration.Tracking; using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface @@ -23,6 +24,7 @@ namespace osu.Game.Tests.Visual.UserInterface Add(osd); AddStep("Display empty osd toast", () => osd.Display(new Overlays.OSD.OsdToast())); + AddStep("Display osd toast with icon and message", () => osd.Display(new Overlays.OSD.OsdIconToast("Hey there !", FontAwesome.Solid.HandSpock))); AddRepeatStep("Change toggle (no bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingNoKeybind), 2); AddRepeatStep("Change toggle (with bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingWithKeybind), 2); AddRepeatStep("Change enum (no bind)", () => config.IncrementEnumSetting(TestConfigSetting.EnumSettingNoKeybind), 3); diff --git a/osu.Game/Overlays/OSD/OsdIconToast.cs b/osu.Game/Overlays/OSD/OsdIconToast.cs new file mode 100644 index 0000000000..c00949d48b --- /dev/null +++ b/osu.Game/Overlays/OSD/OsdIconToast.cs @@ -0,0 +1,42 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Overlays.OSD +{ + public class OsdIconToast : OsdToast + { + public OsdIconToast(string message, IconUsage icon) + { + Children = new Drawable[] + { + new FillFlowContainer() + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Direction = FillDirection.Vertical, + Spacing = new osuTK.Vector2(10), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.BottomCentre, + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), + Text = message + }, + new SpriteIcon + { + Icon = icon, + Size = new osuTK.Vector2(45), + Anchor = Anchor.Centre, + Origin = Anchor.BottomCentre, + } + } + } + }; + } + } +} From 5cad2b21927199dd4baf026c5d27baf85c29c43b Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 5 Jul 2019 16:28:37 +0200 Subject: [PATCH 1749/5608] Add missing function to MusicController --- osu.Game/Overlays/MusicController.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 91fa2f5a95..f6d67e9981 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -559,5 +559,10 @@ namespace osu.Game.Overlays play(); return true; } + + /// + /// Returns whether the current beatmap track is playing. + /// + public bool IsPlaying => beatmap.Value.Track.IsRunning; } } From 89acd9da3e0c9e5aa55d1bdc2647c5349ec1a556 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 5 Jul 2019 16:33:13 +0200 Subject: [PATCH 1750/5608] Add game-wide jukebox keybindings handling to OsuGame --- osu.Game/OsuGame.cs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 0a472d4dc1..32539055a7 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -67,6 +67,8 @@ namespace osu.Game private BeatmapSetOverlay beatmapSetOverlay; + private OnScreenDisplay osd; + [Cached] private readonly ScreenshotManager screenshotManager = new ScreenshotManager(); @@ -456,7 +458,7 @@ namespace osu.Game }); loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add); - loadComponentSingleFile(new OnScreenDisplay(), Add, true); + loadComponentSingleFile(osd = new OnScreenDisplay(), Add, true); loadComponentSingleFile(notifications = new NotificationOverlay { @@ -719,6 +721,24 @@ namespace osu.Game case GlobalAction.ToggleGameplayMouseButtons: LocalConfig.Set(OsuSetting.MouseDisableButtons, !LocalConfig.Get(OsuSetting.MouseDisableButtons)); return true; + + case GlobalAction.MusicPlay: + if (!musicController.IsLoaded) return true; + if (musicController.PlayTrack()) + osd.Display(new Overlays.OSD.OsdIconToast(musicController.IsPlaying ? "Play track" : "Pause track", musicController.IsPlaying ? FontAwesome.Solid.PlayCircle : FontAwesome.Solid.PauseCircle)); + return true; + + case GlobalAction.MusicNext: + if (!musicController.IsLoaded) return true; + if (musicController.NextTrack()) + osd.Display(new Overlays.OSD.OsdIconToast("Next track", FontAwesome.Solid.FastForward)); + return true; + + case GlobalAction.MusicPrev: + if (!musicController.IsLoaded) return true; + if (musicController.PreviousTrack()) + osd.Display(new Overlays.OSD.OsdIconToast("Previous track", FontAwesome.Solid.FastForward)); + return true; } return false; From 5f8bd6eca7a7e0f43b890ef1726da86d41cb0c82 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 5 Jul 2019 16:37:37 +0200 Subject: [PATCH 1751/5608] Fix CI issues + minor issues --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 8 ++++---- osu.Game/OsuGame.cs | 5 ++++- osu.Game/Overlays/MusicController.cs | 1 + osu.Game/Overlays/OSD/OsdIconToast.cs | 7 +++++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 6d85a69804..e756694285 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -38,16 +38,16 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.MouseWheelDown, GlobalAction.DecreaseVolume), new KeyBinding(InputKey.F4, GlobalAction.ToggleMute), - new KeyBinding(InputKey.F5, GlobalAction.MusicPrev), - new KeyBinding(InputKey.F6, GlobalAction.MusicNext), - new KeyBinding(InputKey.X, GlobalAction.MusicPlay), - new KeyBinding(InputKey.Escape, GlobalAction.Back), new KeyBinding(InputKey.MouseButton1, GlobalAction.Back), new KeyBinding(InputKey.Space, GlobalAction.Select), new KeyBinding(InputKey.Enter, GlobalAction.Select), new KeyBinding(InputKey.KeypadEnter, GlobalAction.Select), + + new KeyBinding(InputKey.F5, GlobalAction.MusicPrev), + new KeyBinding(InputKey.F6, GlobalAction.MusicNext), + new KeyBinding(InputKey.X, GlobalAction.MusicPlay), }; public IEnumerable InGameKeyBindings => new[] diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 32539055a7..bae301a8a6 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -724,20 +724,23 @@ namespace osu.Game case GlobalAction.MusicPlay: if (!musicController.IsLoaded) return true; + if (musicController.PlayTrack()) osd.Display(new Overlays.OSD.OsdIconToast(musicController.IsPlaying ? "Play track" : "Pause track", musicController.IsPlaying ? FontAwesome.Solid.PlayCircle : FontAwesome.Solid.PauseCircle)); return true; case GlobalAction.MusicNext: if (!musicController.IsLoaded) return true; + if (musicController.NextTrack()) osd.Display(new Overlays.OSD.OsdIconToast("Next track", FontAwesome.Solid.FastForward)); return true; case GlobalAction.MusicPrev: if (!musicController.IsLoaded) return true; + if (musicController.PreviousTrack()) - osd.Display(new Overlays.OSD.OsdIconToast("Previous track", FontAwesome.Solid.FastForward)); + osd.Display(new Overlays.OSD.OsdIconToast("Previous track", FontAwesome.Solid.FastBackward)); return true; } diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index f6d67e9981..618187069d 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -551,6 +551,7 @@ namespace osu.Game.Overlays /// /// Play or pause the current beatmap track. + /// /// Returns whether the current track could be played / paused or not public bool PlayTrack() { diff --git a/osu.Game/Overlays/OSD/OsdIconToast.cs b/osu.Game/Overlays/OSD/OsdIconToast.cs index c00949d48b..0e2bcd377f 100644 --- a/osu.Game/Overlays/OSD/OsdIconToast.cs +++ b/osu.Game/Overlays/OSD/OsdIconToast.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.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; @@ -12,7 +15,7 @@ namespace osu.Game.Overlays.OSD { Children = new Drawable[] { - new FillFlowContainer() + new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 71e40b46843e69d9bba072cbf6eb7aeede9a3d46 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 6 Jul 2019 12:32:16 +0900 Subject: [PATCH 1752/5608] Force SQLite to multithreading mode --- osu.Game/Database/OsuDbContext.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 538ec41b3d..ea3318598f 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -41,6 +41,9 @@ namespace osu.Game.Database { // required to initialise native SQLite libraries on some platforms. SQLitePCL.Batteries_V2.Init(); + + // https://github.com/aspnet/EntityFrameworkCore/issues/9994#issuecomment-508588678 + SQLitePCL.raw.sqlite3_config(2 /*SQLITE_CONFIG_MULTITHREAD*/); } /// From 530e07110f0425aed5d7c3c56eed920c03e80483 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 6 Jul 2019 06:32:25 +0300 Subject: [PATCH 1753/5608] Use a descriptive name for the setting --- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- osu.Game/Rulesets/Mods/ModBlockFail.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index b5097e95c8..c56a5cc6e4 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -77,7 +77,7 @@ namespace osu.Game.Configuration Set(OsuSetting.BlurLevel, 0, 0, 1, 0.01); Set(OsuSetting.ShowInterface, true); - Set(OsuSetting.HideHealthBar, true); + Set(OsuSetting.HideHealthBarWhenCantFail, true); Set(OsuSetting.KeyOverlay, false); Set(OsuSetting.FloatingComments, false); @@ -132,7 +132,7 @@ namespace osu.Game.Configuration KeyOverlay, FloatingComments, ShowInterface, - HideHealthBar, + HideHealthBarWhenCantFail, MouseDisableButtons, MouseDisableWheel, AudioOffset, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 2d208c5f71..7aeefe959f 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -37,7 +37,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay new SettingsCheckbox { LabelText = "Hide health bar if you can't fail", - Bindable = config.GetBindable(OsuSetting.HideHealthBar), + Bindable = config.GetBindable(OsuSetting.HideHealthBarWhenCantFail), }, new SettingsCheckbox { diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index e37b1b0698..de509a7ea7 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mods public void ReadFromConfig(OsuConfigManager config) { - hideHealthBar = config.GetBindable(OsuSetting.HideHealthBar); + hideHealthBar = config.GetBindable(OsuSetting.HideHealthBarWhenCantFail); } public void ApplyToHUD(HUDOverlay overlay) From 64de3840b0f84f805077d7434b30e4295372e922 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 6 Jul 2019 15:25:53 +0900 Subject: [PATCH 1754/5608] Add missing wait step in TestScenePlayerLoader --- osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 18edaf1b92..ab519360ac 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -37,6 +37,7 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestBlockLoadViaMouseMovement() { AddStep("load dummy beatmap", () => stack.Push(loader = new TestPlayerLoader(() => new TestPlayer(false, false)))); + AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddRepeatStep("move mouse", () => InputManager.MoveMouseTo(loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft + (loader.VisualSettings.ScreenSpaceDrawQuad.BottomRight - loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft) * RNG.NextSingle()), 20); AddAssert("loader still active", () => loader.IsCurrentScreen()); AddUntilStep("loads after idle", () => !loader.IsCurrentScreen()); From 6fd3ad5c1dac275e6a8112f4ae8af31f64ee99f4 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 6 Jul 2019 12:10:30 +0300 Subject: [PATCH 1755/5608] Remove unnecessary fading --- .../Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 1fd3502799..30346a8a96 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -35,15 +35,15 @@ namespace osu.Game.Beatmaps.Drawables protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Func createContentFunc, double timeBeforeLoad) => new DelayedLoadUnloadWrapper(createContentFunc, timeBeforeLoad, UnloadDelay); + protected override double TransformDuration => 400; + protected override Drawable CreateDrawable(BeatmapInfo model) { - Drawable drawable = getDrawableForModel(model); - + var drawable = getDrawableForModel(model); drawable.RelativeSizeAxes = Axes.Both; drawable.Anchor = Anchor.Centre; drawable.Origin = Anchor.Centre; drawable.FillMode = FillMode.Fill; - drawable.OnLoadComplete += d => d.FadeInFromZero(400); return drawable; } From 58183ad3d5b01a9bf49bfa11c43186ad19644424 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 6 Jul 2019 19:05:12 +0900 Subject: [PATCH 1756/5608] Change intro test to test full intro screen --- .../Visual/Menus/TestSceneIntroSequence.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroSequence.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroSequence.cs index b59fb18428..9cb335c3a3 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroSequence.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroSequence.cs @@ -4,10 +4,12 @@ using System; using System.Collections.Generic; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Timing; +using osu.Game.Screens; using osu.Game.Screens.Menu; using osuTK.Graphics; @@ -19,12 +21,16 @@ namespace osu.Game.Tests.Visual.Menus public override IReadOnlyList RequiredTypes => new[] { typeof(OsuLogo), + typeof(Intro), + typeof(StartupScreen), + typeof(OsuScreen) }; + [Cached] + private OsuLogo logo; + public TestSceneIntroSequence() { - OsuLogo logo; - var rateAdjustClock = new StopwatchClock(true); var framedClock = new FramedClock(rateAdjustClock); framedClock.ProcessFrame(); @@ -40,14 +46,17 @@ namespace osu.Game.Tests.Visual.Menus RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, + new OsuScreenStack(new Intro()) + { + RelativeSizeAxes = Axes.Both, + }, logo = new OsuLogo { Anchor = Anchor.Centre, - } + }, } }); - AddStep(@"Restart", logo.PlayIntro); AddSliderStep("Playback speed", 0.0, 2.0, 1, v => rateAdjustClock.Rate = v); } } From 6bee26cfc9764bf0db15d168d3a3fa6d4691d507 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 6 Jul 2019 19:05:37 +0900 Subject: [PATCH 1757/5608] Rename to match --- .../Menus/{TestSceneIntroSequence.cs => TestSceneIntro.cs} | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) rename osu.Game.Tests/Visual/Menus/{TestSceneIntroSequence.cs => TestSceneIntro.cs} (93%) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroSequence.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntro.cs similarity index 93% rename from osu.Game.Tests/Visual/Menus/TestSceneIntroSequence.cs rename to osu.Game.Tests/Visual/Menus/TestSceneIntro.cs index 9cb335c3a3..15b5c2338e 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroSequence.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntro.cs @@ -16,12 +16,11 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Menus { [TestFixture] - public class TestSceneIntroSequence : OsuTestScene + public class TestSceneIntro : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(OsuLogo), - typeof(Intro), typeof(StartupScreen), typeof(OsuScreen) }; @@ -29,7 +28,7 @@ namespace osu.Game.Tests.Visual.Menus [Cached] private OsuLogo logo; - public TestSceneIntroSequence() + public TestSceneIntro() { var rateAdjustClock = new StopwatchClock(true); var framedClock = new FramedClock(rateAdjustClock); From ea911b2fd222d8ab9673927abfdd00fd73c0b78a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 6 Jul 2019 19:05:42 +0900 Subject: [PATCH 1758/5608] Ensure intro restarts track --- osu.Game/Screens/Menu/Intro.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index f6fbcf6498..3fb16eaf90 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -101,7 +101,7 @@ namespace osu.Game.Screens.Menu // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu. if (menuMusic.Value) { - track.Start(); + track.Restart(); track = null; } From a42c79895d907351d3764f019f9e6ca475a41760 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 6 Jul 2019 18:38:41 +0300 Subject: [PATCH 1759/5608] Remove unnecessary private field --- osu.Game/Rulesets/Mods/ModBlockFail.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index de509a7ea7..1eb997ec58 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -5,14 +5,12 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Configuration; using osu.Game.Screens.Play; -using osu.Game.Screens.Play.HUD; namespace osu.Game.Rulesets.Mods { public abstract class ModBlockFail : Mod, IApplicableFailOverride, IApplicableToHUD, IReadFromConfig { private Bindable hideHealthBar; - private HealthDisplay healthDisplay; /// /// We never fail, 'yo. @@ -26,7 +24,6 @@ namespace osu.Game.Rulesets.Mods public void ApplyToHUD(HUDOverlay overlay) { - healthDisplay = overlay.HealthDisplay; hideHealthBar.BindValueChanged(v => healthDisplay.FadeTo(v.NewValue ? 0 : 1, 250, Easing.OutQuint), true); } } From 1f13b94c729302707b59e60cbd84073708e16a28 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 6 Jul 2019 18:44:55 +0300 Subject: [PATCH 1760/5608] Fix build error --- osu.Game/Rulesets/Mods/ModBlockFail.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index 1eb997ec58..e90b79bb11 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Mods public void ApplyToHUD(HUDOverlay overlay) { - hideHealthBar.BindValueChanged(v => healthDisplay.FadeTo(v.NewValue ? 0 : 1, 250, Easing.OutQuint), true); + hideHealthBar.BindValueChanged(v => overlay.HealthDisplay.FadeTo(v.NewValue ? 0 : 1, 250, Easing.OutQuint), true); } } } From 5767f4360e02cd91dcfdb1e42ce45bd7d3fb840c Mon Sep 17 00:00:00 2001 From: Joehu Date: Sat, 6 Jul 2019 12:07:13 -0700 Subject: [PATCH 1761/5608] Remove unnecessary test checks --- .../Visual/SongSelect/TestSceneLeaderboard.cs | 60 ------------------- 1 file changed, 60 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs index f6164c8a73..9472696295 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs @@ -43,13 +43,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"Not logged in", () => leaderboard.SetRetrievalState(PlaceholderState.NotLoggedIn)); AddStep(@"Unavailable", () => leaderboard.SetRetrievalState(PlaceholderState.Unavailable)); AddStep(@"Ranked beatmap", rankedBeatmap); - AddStep(@"Approved beatmap", approvedBeatmap); - AddStep(@"Qualified beatmap", qualifiedBeatmap); - AddStep(@"Loved beatmap", lovedBeatmap); AddStep(@"Pending beatmap", pendingBeatmap); - AddStep(@"WIP beatmap", wipBeatmap); - AddStep(@"Graveyard beatmap", graveyardBeatmap); - AddStep(@"Unpublished beatmap", unpublishedBeatmap); } private void newScores() @@ -250,33 +244,6 @@ namespace osu.Game.Tests.Visual.SongSelect }; } - private void approvedBeatmap() - { - leaderboard.Beatmap = new BeatmapInfo - { - OnlineBeatmapID = 1113057, - Status = BeatmapSetOnlineStatus.Approved, - }; - } - - private void qualifiedBeatmap() - { - leaderboard.Beatmap = new BeatmapInfo - { - OnlineBeatmapID = 1113057, - Status = BeatmapSetOnlineStatus.Qualified, - }; - } - - private void lovedBeatmap() - { - leaderboard.Beatmap = new BeatmapInfo - { - OnlineBeatmapID = 1113057, - Status = BeatmapSetOnlineStatus.Loved, - }; - } - private void pendingBeatmap() { leaderboard.Beatmap = new BeatmapInfo @@ -286,33 +253,6 @@ namespace osu.Game.Tests.Visual.SongSelect }; } - private void wipBeatmap() - { - leaderboard.Beatmap = new BeatmapInfo - { - OnlineBeatmapID = 1113057, - Status = BeatmapSetOnlineStatus.WIP, - }; - } - - private void graveyardBeatmap() - { - leaderboard.Beatmap = new BeatmapInfo - { - OnlineBeatmapID = 1113057, - Status = BeatmapSetOnlineStatus.Graveyard, - }; - } - - private void unpublishedBeatmap() - { - leaderboard.Beatmap = new BeatmapInfo - { - OnlineBeatmapID = null, - Status = BeatmapSetOnlineStatus.None, - }; - } - private class FailableLeaderboard : BeatmapLeaderboard { public void SetRetrievalState(PlaceholderState state) From bf41fd5d9dd590e7a51301c484db0030293ef41f Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 6 Jul 2019 23:29:35 +0300 Subject: [PATCH 1762/5608] Update package references --- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- .../osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 265ecb7688..9acf47a67c 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index dbade6ff8d..df5131dd8b 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index a99a93c3e9..bb3e5a66f3 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 216cc0222f..5510c3a9d9 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 11d70ee7be..659f5415c3 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -3,7 +3,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 1c169184fb..dad2fe0877 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -5,9 +5,9 @@ - + - + WinExe From 84919d70bb37cfcb8cd859e01dac2bcdfc0c9da1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 7 Jul 2019 05:30:30 +0900 Subject: [PATCH 1763/5608] Health bar -> Health display Also inverts logic --- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 4 ++-- osu.Game/Rulesets/Mods/ModBlockFail.cs | 7 +++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index c56a5cc6e4..1da7c7ec1d 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -77,7 +77,7 @@ namespace osu.Game.Configuration Set(OsuSetting.BlurLevel, 0, 0, 1, 0.01); Set(OsuSetting.ShowInterface, true); - Set(OsuSetting.HideHealthBarWhenCantFail, true); + Set(OsuSetting.ShowHealthDisplayWhenCantFail, true); Set(OsuSetting.KeyOverlay, false); Set(OsuSetting.FloatingComments, false); @@ -132,7 +132,7 @@ namespace osu.Game.Configuration KeyOverlay, FloatingComments, ShowInterface, - HideHealthBarWhenCantFail, + ShowHealthDisplayWhenCantFail, MouseDisableButtons, MouseDisableWheel, AudioOffset, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 7aeefe959f..13a494f51f 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -36,8 +36,8 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay }, new SettingsCheckbox { - LabelText = "Hide health bar if you can't fail", - Bindable = config.GetBindable(OsuSetting.HideHealthBarWhenCantFail), + LabelText = "Show health display even when can't fail", + Bindable = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), }, new SettingsCheckbox { diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index e90b79bb11..26efc3932d 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; -using osu.Framework.Graphics; using osu.Game.Configuration; using osu.Game.Screens.Play; @@ -10,7 +9,7 @@ namespace osu.Game.Rulesets.Mods { public abstract class ModBlockFail : Mod, IApplicableFailOverride, IApplicableToHUD, IReadFromConfig { - private Bindable hideHealthBar; + private Bindable showHealthBar; /// /// We never fail, 'yo. @@ -19,12 +18,12 @@ namespace osu.Game.Rulesets.Mods public void ReadFromConfig(OsuConfigManager config) { - hideHealthBar = config.GetBindable(OsuSetting.HideHealthBarWhenCantFail); + showHealthBar = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail); } public void ApplyToHUD(HUDOverlay overlay) { - hideHealthBar.BindValueChanged(v => overlay.HealthDisplay.FadeTo(v.NewValue ? 0 : 1, 250, Easing.OutQuint), true); + overlay.ShowHealthbar.BindTo(showHealthBar); } } } From 8f2ec736262e3c69ffd4ba35479eb0044539edca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 7 Jul 2019 05:30:53 +0900 Subject: [PATCH 1764/5608] Move logic inside of HUDOverlay Add vertical offset adjust. --- osu.Game/Screens/Play/HUDOverlay.cs | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 017bf70133..43b9491750 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -23,7 +23,8 @@ namespace osu.Game.Screens.Play { public class HUDOverlay : Container { - private const int duration = 100; + private const int duration = 250; + private const Easing easing = Easing.OutQuint; public readonly KeyCounterDisplay KeyCounter; public readonly RollingCounter ComboCounter; @@ -35,6 +36,8 @@ namespace osu.Game.Screens.Play public readonly HoldForMenuButton HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; + public Bindable ShowHealthbar = new Bindable(true); + private readonly ScoreProcessor scoreProcessor; private readonly DrawableRuleset drawableRuleset; private readonly IReadOnlyList mods; @@ -47,6 +50,8 @@ namespace osu.Game.Screens.Play public Action RequestSeek; + private readonly Container topScoreContainer; + public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, IReadOnlyList mods) { this.scoreProcessor = scoreProcessor; @@ -62,11 +67,10 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Container + topScoreContainer = new Container { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Y = 30, AutoSizeAxes = Axes.Both, AutoSizeDuration = 200, AutoSizeEasing = Easing.Out, @@ -113,8 +117,21 @@ namespace osu.Game.Screens.Play ModDisplay.Current.Value = mods; showHud = config.GetBindable(OsuSetting.ShowInterface); - showHud.ValueChanged += visible => visibilityContainer.FadeTo(visible.NewValue ? 1 : 0, duration); - showHud.TriggerChange(); + showHud.BindValueChanged(visible => visibilityContainer.FadeTo(visible.NewValue ? 1 : 0, duration, easing), true); + + ShowHealthbar.BindValueChanged(healthBar => + { + if (healthBar.NewValue) + { + HealthDisplay.FadeIn(duration, easing); + topScoreContainer.MoveToY(30, duration, easing); + } + else + { + HealthDisplay.FadeOut(duration, easing); + topScoreContainer.MoveToY(0, duration, easing); + } + }, true); if (!showHud.Value && !hasShownNotificationOnce) { From b10c35b6ab5c74d10f6c100b0a9fa7e081687dc2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 7 Jul 2019 06:13:27 +0300 Subject: [PATCH 1765/5608] Update label text Co-Authored-By: Aergwyn --- osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 13a494f51f..9142492610 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -36,7 +36,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay }, new SettingsCheckbox { - LabelText = "Show health display even when can't fail", + LabelText = "Show health display even when you can't fail", Bindable = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), }, new SettingsCheckbox From cd31d2bc051e40528a8946c9f31a7e73f8b4091e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 7 Jul 2019 13:06:31 +0900 Subject: [PATCH 1766/5608] Simplify tests --- .../Visual/SongSelect/TestSceneLeaderboard.cs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs index 9472696295..8e358a77db 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs @@ -42,8 +42,8 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter)); AddStep(@"Not logged in", () => leaderboard.SetRetrievalState(PlaceholderState.NotLoggedIn)); AddStep(@"Unavailable", () => leaderboard.SetRetrievalState(PlaceholderState.Unavailable)); - AddStep(@"Ranked beatmap", rankedBeatmap); - AddStep(@"Pending beatmap", pendingBeatmap); + foreach (BeatmapSetOnlineStatus status in Enum.GetValues(typeof(BeatmapSetOnlineStatus))) + AddStep($"{status} beatmap", () => showBeatmapWithStatus(status)); } private void newScores() @@ -235,21 +235,12 @@ namespace osu.Game.Tests.Visual.SongSelect leaderboard.Scores = scores; } - private void rankedBeatmap() + private void showBeatmapWithStatus(BeatmapSetOnlineStatus status) { leaderboard.Beatmap = new BeatmapInfo { OnlineBeatmapID = 1113057, - Status = BeatmapSetOnlineStatus.Ranked, - }; - } - - private void pendingBeatmap() - { - leaderboard.Beatmap = new BeatmapInfo - { - OnlineBeatmapID = 1113057, - Status = BeatmapSetOnlineStatus.Pending, + Status = status, }; } From ebc0e502958e157d21ec5cf7005e39349c57bb44 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 7 Jul 2019 13:21:41 +0900 Subject: [PATCH 1767/5608] Simplify conditions --- .../Select/Leaderboards/BeatmapLeaderboard.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 5c568c6983..0f6d4f3188 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -111,22 +111,12 @@ namespace osu.Game.Screens.Select.Leaderboards return null; } - if (Beatmap?.OnlineBeatmapID == null) + if (Beatmap?.OnlineBeatmapID == null || Beatmap?.Status <= BeatmapSetOnlineStatus.Pending) { PlaceholderState = PlaceholderState.Unavailable; return null; } - switch (Beatmap?.Status) - { - case BeatmapSetOnlineStatus.Graveyard: - case BeatmapSetOnlineStatus.None: - case BeatmapSetOnlineStatus.Pending: - case BeatmapSetOnlineStatus.WIP: - PlaceholderState = PlaceholderState.Unavailable; - return null; - } - if (!api.LocalUser.Value.IsSupporter && (Scope != BeatmapLeaderboardScope.Global || filterMods)) { PlaceholderState = PlaceholderState.NotSupporter; From 1a117d1511d48523a7103693e4340a8bd858141d Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Sun, 7 Jul 2019 17:05:53 +0200 Subject: [PATCH 1768/5608] Closes #5277 --- osu.Game/Screens/Edit/Editor.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 89da9ae063..69fbf7d387 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -168,6 +168,8 @@ namespace osu.Game.Screens.Edit menuBar.Mode.ValueChanged += onModeChanged; + host.Exiting += onQuittingGame; + bottomBackground.Colour = colours.Gray2; } @@ -235,16 +237,27 @@ namespace osu.Game.Screens.Edit Beatmap.Value.Track?.Stop(); } + private bool isExitingGame = false; + public override bool OnExiting(IScreen next) { Background.FadeColour(Color4.White, 500); if (Beatmap.Value.Track != null) { - Beatmap.Value.Track.Tempo.Value = 1; - Beatmap.Value.Track.Start(); + if (isExitingGame) + { + Beatmap.Value.Track.Stop(); + } + else + { + Beatmap.Value.Track.Tempo.Value = 1; + Beatmap.Value.Track.Start(); + } } + host.Exiting -= onQuittingGame; + return base.OnExiting(next); } @@ -281,5 +294,7 @@ namespace osu.Game.Screens.Edit else clock.SeekForward(!clock.IsRunning, amount); } + + private bool onQuittingGame() => isExitingGame = true; } } From 84cadc688a4f12df27485e7ec4c1b570acf065bf Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Sun, 7 Jul 2019 17:11:54 +0200 Subject: [PATCH 1769/5608] Change method name --- osu.Game/Screens/Edit/Editor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 69fbf7d387..0a9f7672d3 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -168,7 +168,7 @@ namespace osu.Game.Screens.Edit menuBar.Mode.ValueChanged += onModeChanged; - host.Exiting += onQuittingGame; + host.Exiting += onExitingGame; bottomBackground.Colour = colours.Gray2; } @@ -256,7 +256,7 @@ namespace osu.Game.Screens.Edit } } - host.Exiting -= onQuittingGame; + host.Exiting -= onExitingGame; return base.OnExiting(next); } @@ -295,6 +295,6 @@ namespace osu.Game.Screens.Edit clock.SeekForward(!clock.IsRunning, amount); } - private bool onQuittingGame() => isExitingGame = true; + private bool onExitingGame() => isExitingGame = true; } } From 188c80374e2401032d9522a0a1f596882228be1c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 7 Jul 2019 18:14:23 +0300 Subject: [PATCH 1770/5608] Add sorting by BPM --- osu.Game/Beatmaps/BeatmapManager.cs | 6 +++++- osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 7ef50da7d3..c2d8e06d53 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -271,7 +271,11 @@ namespace osu.Game.Beatmaps OnlineBeatmapSetID = beatmap.BeatmapInfo.BeatmapSet?.OnlineBeatmapSetID, Beatmaps = new List(), Metadata = beatmap.Metadata, - DateAdded = DateTimeOffset.UtcNow + DateAdded = DateTimeOffset.UtcNow, + OnlineInfo = new BeatmapSetOnlineInfo + { + BPM = beatmap.ControlPointInfo.BPMMode, + } }; } diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index f1951e27ab..c51638277d 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -48,6 +48,9 @@ namespace osu.Game.Screens.Select.Carousel case SortMode.DateAdded: return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded); + case SortMode.BPM: + return BeatmapSet.OnlineInfo.BPM.CompareTo(otherSet.BeatmapSet.OnlineInfo.BPM); + case SortMode.Difficulty: return BeatmapSet.MaxStarDifficulty.CompareTo(otherSet.BeatmapSet.MaxStarDifficulty); } From 65c8249c94212dacfff06683b0156e2a2eea0fb7 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 7 Jul 2019 18:25:52 +0300 Subject: [PATCH 1771/5608] Add beatmap extension for calculating length --- osu.Game/Beatmaps/Beatmap.cs | 12 ++++++++++++ osu.Game/Screens/Select/BeatmapInfoWedge.cs | 5 +---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 4ebeee40bf..7fca13a1e2 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -8,6 +8,7 @@ using System.Linq; using osu.Game.Beatmaps.ControlPoints; using Newtonsoft.Json; using osu.Game.IO.Serialization.Converters; +using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Beatmaps { @@ -61,4 +62,15 @@ namespace osu.Game.Beatmaps { public new Beatmap Clone() => (Beatmap)base.Clone(); } + + public static class BeatmapExtensions + { + public static double CalculateLength(this IBeatmap b) + { + HitObject lastObject = b.HitObjects.LastOrDefault(); + var endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0; + + return endTime - b.HitObjects.FirstOrDefault()?.StartTime ?? 0; + } + } } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index fa9ffd0706..e0521307fc 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -289,14 +289,11 @@ namespace osu.Game.Screens.Select if (b?.HitObjects?.Any() == true) { - HitObject lastObject = b.HitObjects.LastOrDefault(); - double endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0; - labels.Add(new InfoLabel(new BeatmapStatistic { Name = "Length", Icon = FontAwesome.Regular.Clock, - Content = TimeSpan.FromMilliseconds(endTime - b.HitObjects.First().StartTime).ToString(@"m\:ss"), + Content = TimeSpan.FromMilliseconds(b.CalculateLength()).ToString(@"m\:ss"), })); labels.Add(new InfoLabel(new BeatmapStatistic From b4ef64fa61a56cc02f09294ab8442fe5739da944 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 7 Jul 2019 18:26:56 +0300 Subject: [PATCH 1772/5608] Add sorting by Length --- osu.Game/Beatmaps/BeatmapManager.cs | 5 +++++ osu.Game/Beatmaps/BeatmapSetInfo.cs | 2 ++ osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs | 7 +++++++ osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 3 +++ 4 files changed, 17 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index c2d8e06d53..b4c211ad53 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -307,6 +307,11 @@ namespace osu.Game.Beatmaps // TODO: this should be done in a better place once we actually need to dynamically update it. beatmap.BeatmapInfo.StarDifficulty = ruleset?.CreateInstance().CreateDifficultyCalculator(new DummyConversionBeatmap(beatmap)).Calculate().StarRating ?? 0; + beatmap.BeatmapInfo.OnlineInfo = new BeatmapOnlineInfo + { + Length = beatmap.CalculateLength(), + }; + beatmapInfos.Add(beatmap.BeatmapInfo); } } diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 524ed0ed56..cdf8ddb5a1 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -37,6 +37,8 @@ namespace osu.Game.Beatmaps public double MaxStarDifficulty => Beatmaps?.Max(b => b.StarDifficulty) ?? 0; + public double MaxLength => Beatmaps?.Max(b => b.OnlineInfo.Length) ?? 0; + [NotMapped] public bool DeletePending { get; set; } diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 712ab7b571..fa24a64d51 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -47,6 +47,13 @@ namespace osu.Game.Screens.Select.Carousel if (ruleset != 0) return ruleset; return Beatmap.StarDifficulty.CompareTo(otherBeatmap.Beatmap.StarDifficulty); + + case SortMode.Length: + // Length comparing must be in seconds + if (TimeSpan.FromMilliseconds(Beatmap.OnlineInfo.Length).Seconds != TimeSpan.FromMilliseconds(otherBeatmap.Beatmap.OnlineInfo.Length).Seconds) + return Beatmap.OnlineInfo.Length.CompareTo(otherBeatmap.Beatmap.OnlineInfo.Length); + + goto case SortMode.Difficulty; } } diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index c51638277d..7934cf388f 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -51,6 +51,9 @@ namespace osu.Game.Screens.Select.Carousel case SortMode.BPM: return BeatmapSet.OnlineInfo.BPM.CompareTo(otherSet.BeatmapSet.OnlineInfo.BPM); + case SortMode.Length: + return BeatmapSet.MaxLength.CompareTo(otherSet.BeatmapSet.MaxLength); + case SortMode.Difficulty: return BeatmapSet.MaxStarDifficulty.CompareTo(otherSet.BeatmapSet.MaxStarDifficulty); } From 31e1d204d4d1d63debe92159443e09db9ddb1cd1 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 7 Jul 2019 18:27:12 +0300 Subject: [PATCH 1773/5608] Add test for sorting by BPM and Length --- .../SongSelect/TestScenePlaySongSelect.cs | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 962e0fb362..04c75d70e3 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -133,6 +133,9 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; }); AddStep(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; }); AddStep(@"Sort by Author", delegate { songSelect.FilterControl.Sort = SortMode.Author; }); + AddStep(@"Sort by DateAdded", delegate { songSelect.FilterControl.Sort = SortMode.DateAdded; }); + AddStep(@"Sort by BPM", delegate { songSelect.FilterControl.Sort = SortMode.BPM; }); + AddStep(@"Sort by Length", delegate { songSelect.FilterControl.Sort = SortMode.Length; }); AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; }); } @@ -264,20 +267,26 @@ namespace osu.Game.Tests.Visual.SongSelect for (int i = 0; i < 6; i++) { int beatmapId = setId * 10 + i; + int length = RNG.Next(30000, 200000); beatmaps.Add(new BeatmapInfo { Ruleset = getRuleset(), OnlineBeatmapID = beatmapId, Path = "normal.osu", - Version = $"{beatmapId}", + Version = $"{beatmapId} (length {TimeSpan.FromMilliseconds(length):m\\:ss})", BaseDifficulty = new BeatmapDifficulty { OverallDifficulty = 3.5f, + }, + OnlineInfo = new BeatmapOnlineInfo + { + Length = length, } }); } + double bpm = RNG.NextSingle(80, 200); return new BeatmapSetInfo { OnlineBeatmapSetID = setId, @@ -286,10 +295,15 @@ namespace osu.Game.Tests.Visual.SongSelect { // Create random metadata, then we can check if sorting works based on these Artist = "Some Artist " + RNG.Next(0, 9), - Title = $"Some Song (set id {setId})", + Title = $"Some Song (set id {setId}, bpm {bpm:0.#})", AuthorString = "Some Guy " + RNG.Next(0, 9), }, - Beatmaps = beatmaps + Beatmaps = beatmaps, + DateAdded = DateTimeOffset.UtcNow, + OnlineInfo = new BeatmapSetOnlineInfo + { + BPM = bpm, + } }; } } From 28cc797fb61ee60fa82193982e84f2dc86c2d48f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 7 Jul 2019 18:29:25 +0300 Subject: [PATCH 1774/5608] Add migrations --- ...7134040_AddBPMAndLengthSorting.Designer.cs | 500 ++++++++++++++++++ .../20190707134040_AddBPMAndLengthSorting.cs | 17 + 2 files changed, 517 insertions(+) create mode 100644 osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.Designer.cs create mode 100644 osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.cs diff --git a/osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.Designer.cs b/osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.Designer.cs new file mode 100644 index 0000000000..7038fcba6e --- /dev/null +++ b/osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.Designer.cs @@ -0,0 +1,500 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using osu.Game.Database; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20190707134040_AddBPMAndLengthSorting")] + partial class AddBPMAndLengthSorting + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.4-servicing-10062"); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("ApproachRate"); + + b.Property("CircleSize"); + + b.Property("DrainRate"); + + b.Property("OverallDifficulty"); + + b.Property("SliderMultiplier"); + + b.Property("SliderTickRate"); + + b.HasKey("ID"); + + b.ToTable("BeatmapDifficulty"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("AudioLeadIn"); + + b.Property("BaseDifficultyID"); + + b.Property("BeatDivisor"); + + b.Property("BeatmapSetInfoID"); + + b.Property("Countdown"); + + b.Property("DistanceSpacing"); + + b.Property("GridSize"); + + b.Property("Hash"); + + b.Property("Hidden"); + + b.Property("LetterboxInBreaks"); + + b.Property("MD5Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapID"); + + b.Property("Path"); + + b.Property("RulesetID"); + + b.Property("SpecialStyle"); + + b.Property("StackLeniency"); + + b.Property("StarDifficulty"); + + b.Property("Status"); + + b.Property("StoredBookmarks"); + + b.Property("TimelineZoom"); + + b.Property("Version"); + + b.Property("WidescreenStoryboard"); + + b.HasKey("ID"); + + b.HasIndex("BaseDifficultyID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("Hash"); + + b.HasIndex("MD5Hash"); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("BeatmapInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Artist"); + + b.Property("ArtistUnicode"); + + b.Property("AudioFile"); + + b.Property("AuthorString") + .HasColumnName("Author"); + + b.Property("BackgroundFile"); + + b.Property("PreviewTime"); + + b.Property("Source"); + + b.Property("Tags"); + + b.Property("Title"); + + b.Property("TitleUnicode"); + + b.HasKey("ID"); + + b.ToTable("BeatmapMetadata"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("BeatmapSetInfoID"); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.HasKey("ID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("FileInfoID"); + + b.ToTable("BeatmapSetFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("DateAdded"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapSetID"); + + b.Property("Protected"); + + b.Property("Status"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapSetID") + .IsUnique(); + + b.ToTable("BeatmapSetInfo"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Key") + .HasColumnName("Key"); + + b.Property("RulesetID"); + + b.Property("SkinInfoID"); + + b.Property("StringValue") + .HasColumnName("Value"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("SkinInfoID"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("osu.Game.IO.FileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Hash"); + + b.Property("ReferenceCount"); + + b.HasKey("ID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("ReferenceCount"); + + b.ToTable("FileInfo"); + }); + + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntAction") + .HasColumnName("Action"); + + b.Property("KeysString") + .HasColumnName("Keys"); + + b.Property("RulesetID"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("IntAction"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("KeyBinding"); + }); + + modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Available"); + + b.Property("InstantiationInfo"); + + b.Property("Name"); + + b.Property("ShortName"); + + b.HasKey("ID"); + + b.HasIndex("Available"); + + b.HasIndex("ShortName") + .IsUnique(); + + b.ToTable("RulesetInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("ScoreInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("ScoreInfoID"); + + b.ToTable("ScoreFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Accuracy") + .HasColumnType("DECIMAL(1,4)"); + + b.Property("BeatmapInfoID"); + + b.Property("Combo"); + + b.Property("Date"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MaxCombo"); + + b.Property("ModsJson") + .HasColumnName("Mods"); + + b.Property("OnlineScoreID"); + + b.Property("PP"); + + b.Property("Rank"); + + b.Property("RulesetID"); + + b.Property("StatisticsJson") + .HasColumnName("Statistics"); + + b.Property("TotalScore"); + + b.Property("UserID") + .HasColumnName("UserID"); + + b.Property("UserString") + .HasColumnName("User"); + + b.HasKey("ID"); + + b.HasIndex("BeatmapInfoID"); + + b.HasIndex("OnlineScoreID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("ScoreInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("SkinInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("SkinInfoID"); + + b.ToTable("SkinFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Creator"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("Name"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.ToTable("SkinInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") + .WithMany() + .HasForeignKey("BaseDifficultyID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") + .WithMany("Beatmaps") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("Beatmaps") + .HasForeignKey("MetadataID"); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") + .WithMany("Files") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("BeatmapSets") + .HasForeignKey("MetadataID"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Settings") + .HasForeignKey("SkinInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Scoring.ScoreInfo") + .WithMany("Files") + .HasForeignKey("ScoreInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap") + .WithMany("Scores") + .HasForeignKey("BeatmapInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Files") + .HasForeignKey("SkinInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.cs b/osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.cs new file mode 100644 index 0000000000..98a94b1c4e --- /dev/null +++ b/osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace osu.Game.Migrations +{ + public partial class AddBPMAndLengthSorting : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} From 6ee10640e31f5343fc3eeba33913ab43a1b96591 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 7 Jul 2019 19:26:41 +0300 Subject: [PATCH 1775/5608] Remove unnecessary migration + Fix CI issues --- ...7134040_AddBPMAndLengthSorting.Designer.cs | 500 ------------------ .../20190707134040_AddBPMAndLengthSorting.cs | 17 - osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 - 3 files changed, 519 deletions(-) delete mode 100644 osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.Designer.cs delete mode 100644 osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.cs diff --git a/osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.Designer.cs b/osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.Designer.cs deleted file mode 100644 index 7038fcba6e..0000000000 --- a/osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.Designer.cs +++ /dev/null @@ -1,500 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using osu.Game.Database; - -namespace osu.Game.Migrations -{ - [DbContext(typeof(OsuDbContext))] - [Migration("20190707134040_AddBPMAndLengthSorting")] - partial class AddBPMAndLengthSorting - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.2.4-servicing-10062"); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("ApproachRate"); - - b.Property("CircleSize"); - - b.Property("DrainRate"); - - b.Property("OverallDifficulty"); - - b.Property("SliderMultiplier"); - - b.Property("SliderTickRate"); - - b.HasKey("ID"); - - b.ToTable("BeatmapDifficulty"); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("AudioLeadIn"); - - b.Property("BaseDifficultyID"); - - b.Property("BeatDivisor"); - - b.Property("BeatmapSetInfoID"); - - b.Property("Countdown"); - - b.Property("DistanceSpacing"); - - b.Property("GridSize"); - - b.Property("Hash"); - - b.Property("Hidden"); - - b.Property("LetterboxInBreaks"); - - b.Property("MD5Hash"); - - b.Property("MetadataID"); - - b.Property("OnlineBeatmapID"); - - b.Property("Path"); - - b.Property("RulesetID"); - - b.Property("SpecialStyle"); - - b.Property("StackLeniency"); - - b.Property("StarDifficulty"); - - b.Property("Status"); - - b.Property("StoredBookmarks"); - - b.Property("TimelineZoom"); - - b.Property("Version"); - - b.Property("WidescreenStoryboard"); - - b.HasKey("ID"); - - b.HasIndex("BaseDifficultyID"); - - b.HasIndex("BeatmapSetInfoID"); - - b.HasIndex("Hash"); - - b.HasIndex("MD5Hash"); - - b.HasIndex("MetadataID"); - - b.HasIndex("OnlineBeatmapID") - .IsUnique(); - - b.HasIndex("RulesetID"); - - b.ToTable("BeatmapInfo"); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("Artist"); - - b.Property("ArtistUnicode"); - - b.Property("AudioFile"); - - b.Property("AuthorString") - .HasColumnName("Author"); - - b.Property("BackgroundFile"); - - b.Property("PreviewTime"); - - b.Property("Source"); - - b.Property("Tags"); - - b.Property("Title"); - - b.Property("TitleUnicode"); - - b.HasKey("ID"); - - b.ToTable("BeatmapMetadata"); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("BeatmapSetInfoID"); - - b.Property("FileInfoID"); - - b.Property("Filename") - .IsRequired(); - - b.HasKey("ID"); - - b.HasIndex("BeatmapSetInfoID"); - - b.HasIndex("FileInfoID"); - - b.ToTable("BeatmapSetFileInfo"); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("DeletePending"); - - b.Property("Hash"); - - b.Property("MetadataID"); - - b.Property("OnlineBeatmapSetID"); - - b.Property("Protected"); - - b.Property("Status"); - - b.HasKey("ID"); - - b.HasIndex("DeletePending"); - - b.HasIndex("Hash") - .IsUnique(); - - b.HasIndex("MetadataID"); - - b.HasIndex("OnlineBeatmapSetID") - .IsUnique(); - - b.ToTable("BeatmapSetInfo"); - }); - - modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("Key") - .HasColumnName("Key"); - - b.Property("RulesetID"); - - b.Property("SkinInfoID"); - - b.Property("StringValue") - .HasColumnName("Value"); - - b.Property("Variant"); - - b.HasKey("ID"); - - b.HasIndex("SkinInfoID"); - - b.HasIndex("RulesetID", "Variant"); - - b.ToTable("Settings"); - }); - - modelBuilder.Entity("osu.Game.IO.FileInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("Hash"); - - b.Property("ReferenceCount"); - - b.HasKey("ID"); - - b.HasIndex("Hash") - .IsUnique(); - - b.HasIndex("ReferenceCount"); - - b.ToTable("FileInfo"); - }); - - modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("IntAction") - .HasColumnName("Action"); - - b.Property("KeysString") - .HasColumnName("Keys"); - - b.Property("RulesetID"); - - b.Property("Variant"); - - b.HasKey("ID"); - - b.HasIndex("IntAction"); - - b.HasIndex("RulesetID", "Variant"); - - b.ToTable("KeyBinding"); - }); - - modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("Available"); - - b.Property("InstantiationInfo"); - - b.Property("Name"); - - b.Property("ShortName"); - - b.HasKey("ID"); - - b.HasIndex("Available"); - - b.HasIndex("ShortName") - .IsUnique(); - - b.ToTable("RulesetInfo"); - }); - - modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("FileInfoID"); - - b.Property("Filename") - .IsRequired(); - - b.Property("ScoreInfoID"); - - b.HasKey("ID"); - - b.HasIndex("FileInfoID"); - - b.HasIndex("ScoreInfoID"); - - b.ToTable("ScoreFileInfo"); - }); - - modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("Accuracy") - .HasColumnType("DECIMAL(1,4)"); - - b.Property("BeatmapInfoID"); - - b.Property("Combo"); - - b.Property("Date"); - - b.Property("DeletePending"); - - b.Property("Hash"); - - b.Property("MaxCombo"); - - b.Property("ModsJson") - .HasColumnName("Mods"); - - b.Property("OnlineScoreID"); - - b.Property("PP"); - - b.Property("Rank"); - - b.Property("RulesetID"); - - b.Property("StatisticsJson") - .HasColumnName("Statistics"); - - b.Property("TotalScore"); - - b.Property("UserID") - .HasColumnName("UserID"); - - b.Property("UserString") - .HasColumnName("User"); - - b.HasKey("ID"); - - b.HasIndex("BeatmapInfoID"); - - b.HasIndex("OnlineScoreID") - .IsUnique(); - - b.HasIndex("RulesetID"); - - b.ToTable("ScoreInfo"); - }); - - modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("FileInfoID"); - - b.Property("Filename") - .IsRequired(); - - b.Property("SkinInfoID"); - - b.HasKey("ID"); - - b.HasIndex("FileInfoID"); - - b.HasIndex("SkinInfoID"); - - b.ToTable("SkinFileInfo"); - }); - - modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("Creator"); - - b.Property("DeletePending"); - - b.Property("Hash"); - - b.Property("Name"); - - b.HasKey("ID"); - - b.HasIndex("DeletePending"); - - b.HasIndex("Hash") - .IsUnique(); - - b.ToTable("SkinInfo"); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => - { - b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") - .WithMany() - .HasForeignKey("BaseDifficultyID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") - .WithMany("Beatmaps") - .HasForeignKey("BeatmapSetInfoID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") - .WithMany("Beatmaps") - .HasForeignKey("MetadataID"); - - b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") - .WithMany() - .HasForeignKey("RulesetID") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => - { - b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") - .WithMany("Files") - .HasForeignKey("BeatmapSetInfoID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("osu.Game.IO.FileInfo", "FileInfo") - .WithMany() - .HasForeignKey("FileInfoID") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => - { - b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") - .WithMany("BeatmapSets") - .HasForeignKey("MetadataID"); - }); - - modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => - { - b.HasOne("osu.Game.Skinning.SkinInfo") - .WithMany("Settings") - .HasForeignKey("SkinInfoID"); - }); - - modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => - { - b.HasOne("osu.Game.IO.FileInfo", "FileInfo") - .WithMany() - .HasForeignKey("FileInfoID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("osu.Game.Scoring.ScoreInfo") - .WithMany("Files") - .HasForeignKey("ScoreInfoID"); - }); - - modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => - { - b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap") - .WithMany("Scores") - .HasForeignKey("BeatmapInfoID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") - .WithMany() - .HasForeignKey("RulesetID") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => - { - b.HasOne("osu.Game.IO.FileInfo", "FileInfo") - .WithMany() - .HasForeignKey("FileInfoID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("osu.Game.Skinning.SkinInfo") - .WithMany("Files") - .HasForeignKey("SkinInfoID") - .OnDelete(DeleteBehavior.Cascade); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.cs b/osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.cs deleted file mode 100644 index 98a94b1c4e..0000000000 --- a/osu.Game/Migrations/20190707134040_AddBPMAndLengthSorting.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -namespace osu.Game.Migrations -{ - public partial class AddBPMAndLengthSorting : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - - } - } -} diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index e0521307fc..26a83f930c 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -18,8 +18,6 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; From 3ea9629daf6cdbd22658ec4ef5f457d8f86f4d3d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 7 Jul 2019 20:11:44 +0300 Subject: [PATCH 1776/5608] Move BPM out of OnlineInfo --- osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs | 4 ++-- osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs | 2 +- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 5 +---- osu.Game.Tournament/Components/SongBar.cs | 2 +- osu.Game/Beatmaps/BeatmapManager.cs | 5 +---- osu.Game/Beatmaps/BeatmapSetInfo.cs | 5 +++++ osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs | 5 ----- osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs | 2 +- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 2 +- osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 2 +- 10 files changed, 14 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index a9c44c9020..75e8c88f9d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -96,11 +96,11 @@ namespace osu.Game.Tests.Visual.Online FavouriteCount = 456, Submitted = DateTime.Now, Ranked = DateTime.Now, - BPM = 111, HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), }, + BPM = 111, Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = new List { @@ -169,11 +169,11 @@ namespace osu.Game.Tests.Visual.Online FavouriteCount = 456, Submitted = DateTime.Now, Ranked = DateTime.Now, - BPM = 111, HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), }, + BPM = 111, Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = new List { diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs index 53dbaeddda..5f80223541 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs @@ -47,11 +47,11 @@ namespace osu.Game.Tests.Visual.Online Preview = @"https://b.ppy.sh/preview/12345.mp3", PlayCount = 123, FavouriteCount = 456, - BPM = 111, HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), }, + BPM = 111, Beatmaps = new List { new BeatmapInfo diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 04c75d70e3..5813e9e6d5 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -300,10 +300,7 @@ namespace osu.Game.Tests.Visual.SongSelect }, Beatmaps = beatmaps, DateAdded = DateTimeOffset.UtcNow, - OnlineInfo = new BeatmapSetOnlineInfo - { - BPM = bpm, - } + BPM = bpm, }; } } diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index c07882ddd0..06541bc264 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -158,7 +158,7 @@ namespace osu.Game.Tournament.Components return; } - var bpm = beatmap.BeatmapSet.OnlineInfo.BPM; + var bpm = beatmap.BeatmapSet.BPM; var length = beatmap.OnlineInfo.Length; string hardRockExtra = ""; string srExtra = ""; diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b4c211ad53..f94c461c9a 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -272,10 +272,7 @@ namespace osu.Game.Beatmaps Beatmaps = new List(), Metadata = beatmap.Metadata, DateAdded = DateTimeOffset.UtcNow, - OnlineInfo = new BeatmapSetOnlineInfo - { - BPM = beatmap.ControlPointInfo.BPMMode, - } + BPM = beatmap.ControlPointInfo.BPMMode, }; } diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index cdf8ddb5a1..2b4ef961ce 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -35,6 +35,11 @@ namespace osu.Game.Beatmaps [NotMapped] public BeatmapSetMetrics Metrics { get; set; } + /// + /// The beats per minute of this beatmap set's song. + /// + public double BPM { get; set; } + public double MaxStarDifficulty => Beatmaps?.Max(b => b.StarDifficulty) ?? 0; public double MaxLength => Beatmaps?.Max(b => b.OnlineInfo.Length) ?? 0; diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs index ea3f0b61b9..903d07bea0 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs @@ -51,11 +51,6 @@ namespace osu.Game.Beatmaps /// public string Preview { get; set; } - /// - /// The beats per minute of this beatmap set's song. - /// - public double BPM { get; set; } - /// /// The amount of plays this beatmap set has. /// diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 200a705500..50128bde7a 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -77,13 +77,13 @@ namespace osu.Game.Online.API.Requests.Responses Metadata = this, Status = Status, Metrics = ratings == null ? null : new BeatmapSetMetrics { Ratings = ratings }, + BPM = bpm, OnlineInfo = new BeatmapSetOnlineInfo { Covers = covers, Preview = preview, PlayCount = playCount, FavouriteCount = favouriteCount, - BPM = bpm, Status = Status, HasVideo = hasVideo, HasStoryboard = hasStoryboard, diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 6a583baf38..651ef30bdc 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -50,7 +50,7 @@ namespace osu.Game.Overlays.BeatmapSet private void updateDisplay() { - bpm.Value = BeatmapSet?.OnlineInfo?.BPM.ToString(@"0.##") ?? "-"; + bpm.Value = BeatmapSet?.BPM.ToString(@"0.##") ?? "-"; if (beatmap == null) { diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 7934cf388f..6457f78746 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -49,7 +49,7 @@ namespace osu.Game.Screens.Select.Carousel return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded); case SortMode.BPM: - return BeatmapSet.OnlineInfo.BPM.CompareTo(otherSet.BeatmapSet.OnlineInfo.BPM); + return BeatmapSet.BPM.CompareTo(otherSet.BeatmapSet.BPM); case SortMode.Length: return BeatmapSet.MaxLength.CompareTo(otherSet.BeatmapSet.MaxLength); From 729f0901f7bca3595c2834822a440f2f92433910 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 7 Jul 2019 20:25:36 +0300 Subject: [PATCH 1777/5608] Move Length out of OnlineInfo --- osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs | 4 ++-- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 5 +---- osu.Game.Tournament/Components/SongBar.cs | 2 +- osu.Game/Beatmaps/BeatmapInfo.cs | 5 +++++ osu.Game/Beatmaps/BeatmapManager.cs | 6 +----- osu.Game/Beatmaps/BeatmapOnlineInfo.cs | 5 ----- osu.Game/Beatmaps/BeatmapSetInfo.cs | 2 +- osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 2 +- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 2 +- osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs | 4 ++-- 10 files changed, 15 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 75e8c88f9d..02b26acb7c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -108,6 +108,7 @@ namespace osu.Game.Tests.Visual.Online { StarDifficulty = 9.99, Version = @"TEST", + Length = 456000, Ruleset = maniaRuleset, BaseDifficulty = new BeatmapDifficulty { @@ -118,7 +119,6 @@ namespace osu.Game.Tests.Visual.Online }, OnlineInfo = new BeatmapOnlineInfo { - Length = 456000, CircleCount = 111, SliderCount = 12, PlayCount = 222, @@ -181,6 +181,7 @@ namespace osu.Game.Tests.Visual.Online { StarDifficulty = 5.67, Version = @"ANOTHER TEST", + Length = 123000, Ruleset = taikoRuleset, BaseDifficulty = new BeatmapDifficulty { @@ -191,7 +192,6 @@ namespace osu.Game.Tests.Visual.Online }, OnlineInfo = new BeatmapOnlineInfo { - Length = 123000, CircleCount = 123, SliderCount = 45, PlayCount = 567, diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 5813e9e6d5..0b0f65f572 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -275,14 +275,11 @@ namespace osu.Game.Tests.Visual.SongSelect OnlineBeatmapID = beatmapId, Path = "normal.osu", Version = $"{beatmapId} (length {TimeSpan.FromMilliseconds(length):m\\:ss})", + Length = length, BaseDifficulty = new BeatmapDifficulty { OverallDifficulty = 3.5f, }, - OnlineInfo = new BeatmapOnlineInfo - { - Length = length, - } }); } diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 06541bc264..938fbba303 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -159,7 +159,7 @@ namespace osu.Game.Tournament.Components } var bpm = beatmap.BeatmapSet.BPM; - var length = beatmap.OnlineInfo.Length; + var length = beatmap.Length; string hardRockExtra = ""; string srExtra = ""; diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 3c082bb71e..1610e37620 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -51,6 +51,11 @@ namespace osu.Game.Beatmaps [NotMapped] public BeatmapOnlineInfo OnlineInfo { get; set; } + /// + /// The length in milliseconds of this beatmap's song. + /// + public double Length { get; set; } + public string Path { get; set; } [JsonProperty("file_sha2")] diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index f94c461c9a..810db1589e 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -303,11 +303,7 @@ namespace osu.Game.Beatmaps beatmap.BeatmapInfo.Ruleset = ruleset; // TODO: this should be done in a better place once we actually need to dynamically update it. beatmap.BeatmapInfo.StarDifficulty = ruleset?.CreateInstance().CreateDifficultyCalculator(new DummyConversionBeatmap(beatmap)).Calculate().StarRating ?? 0; - - beatmap.BeatmapInfo.OnlineInfo = new BeatmapOnlineInfo - { - Length = beatmap.CalculateLength(), - }; + beatmap.BeatmapInfo.Length = beatmap.CalculateLength(); beatmapInfos.Add(beatmap.BeatmapInfo); } diff --git a/osu.Game/Beatmaps/BeatmapOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapOnlineInfo.cs index faae74db88..bfeacd9bfc 100644 --- a/osu.Game/Beatmaps/BeatmapOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapOnlineInfo.cs @@ -8,11 +8,6 @@ namespace osu.Game.Beatmaps /// public class BeatmapOnlineInfo { - /// - /// The length in milliseconds of this beatmap's song. - /// - public double Length { get; set; } - /// /// The amount of circles in this beatmap. /// diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 2b4ef961ce..62366cab4e 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -42,7 +42,7 @@ namespace osu.Game.Beatmaps public double MaxStarDifficulty => Beatmaps?.Max(b => b.StarDifficulty) ?? 0; - public double MaxLength => Beatmaps?.Max(b => b.OnlineInfo.Length) ?? 0; + public double MaxLength => Beatmaps?.Max(b => b.Length) ?? 0; [NotMapped] public bool DeletePending { get; set; } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index bcbe060f82..ff4d240bf0 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -71,6 +71,7 @@ namespace osu.Game.Online.API.Requests.Responses StarDifficulty = starDifficulty, OnlineBeatmapID = OnlineBeatmapID, Version = version, + Length = length, Status = Status, BeatmapSet = set, Metrics = metrics, @@ -85,7 +86,6 @@ namespace osu.Game.Online.API.Requests.Responses { PlayCount = playCount, PassCount = passCount, - Length = length, CircleCount = circleCount, SliderCount = sliderCount, }, diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 651ef30bdc..f97212f180 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.BeatmapSet } else { - length.Value = TimeSpan.FromSeconds(beatmap.OnlineInfo.Length).ToString(@"m\:ss"); + length.Value = TimeSpan.FromSeconds(beatmap.Length).ToString(@"m\:ss"); circleCount.Value = beatmap.OnlineInfo.CircleCount.ToString(); sliderCount.Value = beatmap.OnlineInfo.SliderCount.ToString(); } diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index fa24a64d51..490012da61 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -50,8 +50,8 @@ namespace osu.Game.Screens.Select.Carousel case SortMode.Length: // Length comparing must be in seconds - if (TimeSpan.FromMilliseconds(Beatmap.OnlineInfo.Length).Seconds != TimeSpan.FromMilliseconds(otherBeatmap.Beatmap.OnlineInfo.Length).Seconds) - return Beatmap.OnlineInfo.Length.CompareTo(otherBeatmap.Beatmap.OnlineInfo.Length); + if (TimeSpan.FromMilliseconds(Beatmap.Length).Seconds != TimeSpan.FromMilliseconds(otherBeatmap.Beatmap.Length).Seconds) + return Beatmap.Length.CompareTo(otherBeatmap.Beatmap.Length); goto case SortMode.Difficulty; } From d8745746129c26f25d6ac40ac67a5d1c2b52effc Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 7 Jul 2019 20:25:59 +0300 Subject: [PATCH 1778/5608] Add migration --- ...7172237_AddBPMAndLengthColumns.Designer.cs | 504 ++++++++++++++++++ .../20190707172237_AddBPMAndLengthColumns.cs | 33 ++ .../Migrations/OsuDbContextModelSnapshot.cs | 4 + 3 files changed, 541 insertions(+) create mode 100644 osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.Designer.cs create mode 100644 osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.cs diff --git a/osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.Designer.cs b/osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.Designer.cs new file mode 100644 index 0000000000..c1e9f5071a --- /dev/null +++ b/osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.Designer.cs @@ -0,0 +1,504 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using osu.Game.Database; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20190707172237_AddBPMAndLengthColumns")] + partial class AddBPMAndLengthColumns + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.4-servicing-10062"); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("ApproachRate"); + + b.Property("CircleSize"); + + b.Property("DrainRate"); + + b.Property("OverallDifficulty"); + + b.Property("SliderMultiplier"); + + b.Property("SliderTickRate"); + + b.HasKey("ID"); + + b.ToTable("BeatmapDifficulty"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("AudioLeadIn"); + + b.Property("BaseDifficultyID"); + + b.Property("BeatDivisor"); + + b.Property("BeatmapSetInfoID"); + + b.Property("Countdown"); + + b.Property("DistanceSpacing"); + + b.Property("GridSize"); + + b.Property("Hash"); + + b.Property("Hidden"); + + b.Property("Length"); + + b.Property("LetterboxInBreaks"); + + b.Property("MD5Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapID"); + + b.Property("Path"); + + b.Property("RulesetID"); + + b.Property("SpecialStyle"); + + b.Property("StackLeniency"); + + b.Property("StarDifficulty"); + + b.Property("Status"); + + b.Property("StoredBookmarks"); + + b.Property("TimelineZoom"); + + b.Property("Version"); + + b.Property("WidescreenStoryboard"); + + b.HasKey("ID"); + + b.HasIndex("BaseDifficultyID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("Hash"); + + b.HasIndex("MD5Hash"); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("BeatmapInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Artist"); + + b.Property("ArtistUnicode"); + + b.Property("AudioFile"); + + b.Property("AuthorString") + .HasColumnName("Author"); + + b.Property("BackgroundFile"); + + b.Property("PreviewTime"); + + b.Property("Source"); + + b.Property("Tags"); + + b.Property("Title"); + + b.Property("TitleUnicode"); + + b.HasKey("ID"); + + b.ToTable("BeatmapMetadata"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("BeatmapSetInfoID"); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.HasKey("ID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("FileInfoID"); + + b.ToTable("BeatmapSetFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("BPM"); + + b.Property("DateAdded"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapSetID"); + + b.Property("Protected"); + + b.Property("Status"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapSetID") + .IsUnique(); + + b.ToTable("BeatmapSetInfo"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Key") + .HasColumnName("Key"); + + b.Property("RulesetID"); + + b.Property("SkinInfoID"); + + b.Property("StringValue") + .HasColumnName("Value"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("SkinInfoID"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("osu.Game.IO.FileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Hash"); + + b.Property("ReferenceCount"); + + b.HasKey("ID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("ReferenceCount"); + + b.ToTable("FileInfo"); + }); + + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntAction") + .HasColumnName("Action"); + + b.Property("KeysString") + .HasColumnName("Keys"); + + b.Property("RulesetID"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("IntAction"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("KeyBinding"); + }); + + modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Available"); + + b.Property("InstantiationInfo"); + + b.Property("Name"); + + b.Property("ShortName"); + + b.HasKey("ID"); + + b.HasIndex("Available"); + + b.HasIndex("ShortName") + .IsUnique(); + + b.ToTable("RulesetInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("ScoreInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("ScoreInfoID"); + + b.ToTable("ScoreFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Accuracy") + .HasColumnType("DECIMAL(1,4)"); + + b.Property("BeatmapInfoID"); + + b.Property("Combo"); + + b.Property("Date"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MaxCombo"); + + b.Property("ModsJson") + .HasColumnName("Mods"); + + b.Property("OnlineScoreID"); + + b.Property("PP"); + + b.Property("Rank"); + + b.Property("RulesetID"); + + b.Property("StatisticsJson") + .HasColumnName("Statistics"); + + b.Property("TotalScore"); + + b.Property("UserID") + .HasColumnName("UserID"); + + b.Property("UserString") + .HasColumnName("User"); + + b.HasKey("ID"); + + b.HasIndex("BeatmapInfoID"); + + b.HasIndex("OnlineScoreID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("ScoreInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("SkinInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("SkinInfoID"); + + b.ToTable("SkinFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Creator"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("Name"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.ToTable("SkinInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") + .WithMany() + .HasForeignKey("BaseDifficultyID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") + .WithMany("Beatmaps") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("Beatmaps") + .HasForeignKey("MetadataID"); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") + .WithMany("Files") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("BeatmapSets") + .HasForeignKey("MetadataID"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Settings") + .HasForeignKey("SkinInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Scoring.ScoreInfo") + .WithMany("Files") + .HasForeignKey("ScoreInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap") + .WithMany("Scores") + .HasForeignKey("BeatmapInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Files") + .HasForeignKey("SkinInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.cs b/osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.cs new file mode 100644 index 0000000000..b14722daf6 --- /dev/null +++ b/osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.cs @@ -0,0 +1,33 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace osu.Game.Migrations +{ + public partial class AddBPMAndLengthColumns : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "BPM", + table: "BeatmapSetInfo", + nullable: false, + defaultValue: 0.0); + + migrationBuilder.AddColumn( + name: "Length", + table: "BeatmapInfo", + nullable: false, + defaultValue: 0.0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "BPM", + table: "BeatmapSetInfo"); + + migrationBuilder.DropColumn( + name: "Length", + table: "BeatmapInfo"); + } + } +} diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 11b032a941..9e65dc7f0f 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -61,6 +61,8 @@ namespace osu.Game.Migrations b.Property("Hidden"); + b.Property("Length"); + b.Property("LetterboxInBreaks"); b.Property("MD5Hash"); @@ -166,6 +168,8 @@ namespace osu.Game.Migrations b.Property("ID") .ValueGeneratedOnAdd(); + b.Property("BPM"); + b.Property("DateAdded"); b.Property("DeletePending"); From 2747d7692b1db44559f305c3e4873e78048a6f48 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 8 Jul 2019 14:55:05 +0900 Subject: [PATCH 1779/5608] Create ReplayPlayerLoader for local mod caching --- osu.Game/OsuGame.cs | 3 +- osu.Game/Screens/Play/ReplayPlayerLoader.cs | 32 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Screens/Play/ReplayPlayerLoader.cs diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 0a472d4dc1..ab7efc6e38 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -284,9 +284,8 @@ namespace osu.Game { Ruleset.Value = databasedScoreInfo.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); - Mods.Value = databasedScoreInfo.Mods; - menuScreen.Push(new PlayerLoader(() => new ReplayPlayer(databasedScore))); + menuScreen.Push(new ReplayPlayerLoader(() => new ReplayPlayer(databasedScore), databasedScoreInfo.Mods)); }, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true); } diff --git a/osu.Game/Screens/Play/ReplayPlayerLoader.cs b/osu.Game/Screens/Play/ReplayPlayerLoader.cs new file mode 100644 index 0000000000..1c24709e41 --- /dev/null +++ b/osu.Game/Screens/Play/ReplayPlayerLoader.cs @@ -0,0 +1,32 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Screens.Play +{ + public class ReplayPlayerLoader : PlayerLoader + { + private readonly IReadOnlyList mods; + + public ReplayPlayerLoader(Func player, IReadOnlyList mods) + : base(player) + { + this.mods = mods; + } + + private DependencyContainer dependencies; + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + dependencies = new DependencyContainer(parent); + dependencies.Cache(new Bindable>(mods)); + + return base.CreateChildDependencies(dependencies); + } + } +} From 90d5484818b9e0372694a1d99a3801d340699bd3 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 8 Jul 2019 09:10:41 +0300 Subject: [PATCH 1780/5608] Return BPM back to OnlineInfo Revert commit of "Move BPM out of OnlineInfo" --- osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs | 4 ++-- osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs | 2 +- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 5 ++++- osu.Game/Beatmaps/BeatmapManager.cs | 5 ++++- osu.Game/Beatmaps/BeatmapSetInfo.cs | 5 ----- osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs | 5 +++++ osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs | 2 +- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 2 +- osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 2 +- 9 files changed, 19 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 02b26acb7c..daee419b52 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -96,11 +96,11 @@ namespace osu.Game.Tests.Visual.Online FavouriteCount = 456, Submitted = DateTime.Now, Ranked = DateTime.Now, + BPM = 111, HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), }, - BPM = 111, Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = new List { @@ -169,11 +169,11 @@ namespace osu.Game.Tests.Visual.Online FavouriteCount = 456, Submitted = DateTime.Now, Ranked = DateTime.Now, + BPM = 111, HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), }, - BPM = 111, Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = new List { diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs index 5f80223541..53dbaeddda 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs @@ -47,11 +47,11 @@ namespace osu.Game.Tests.Visual.Online Preview = @"https://b.ppy.sh/preview/12345.mp3", PlayCount = 123, FavouriteCount = 456, + BPM = 111, HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), }, - BPM = 111, Beatmaps = new List { new BeatmapInfo diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 0b0f65f572..27a341ffb7 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -297,7 +297,10 @@ namespace osu.Game.Tests.Visual.SongSelect }, Beatmaps = beatmaps, DateAdded = DateTimeOffset.UtcNow, - BPM = bpm, + OnlineInfo = new BeatmapSetOnlineInfo + { + BPM = bpm, + } }; } } diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 810db1589e..34a8ddf5c9 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -272,7 +272,10 @@ namespace osu.Game.Beatmaps Beatmaps = new List(), Metadata = beatmap.Metadata, DateAdded = DateTimeOffset.UtcNow, - BPM = beatmap.ControlPointInfo.BPMMode, + OnlineInfo = new BeatmapSetOnlineInfo + { + BPM = beatmap.ControlPointInfo.BPMMode, + } }; } diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 62366cab4e..a77dfa2148 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -35,11 +35,6 @@ namespace osu.Game.Beatmaps [NotMapped] public BeatmapSetMetrics Metrics { get; set; } - /// - /// The beats per minute of this beatmap set's song. - /// - public double BPM { get; set; } - public double MaxStarDifficulty => Beatmaps?.Max(b => b.StarDifficulty) ?? 0; public double MaxLength => Beatmaps?.Max(b => b.Length) ?? 0; diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs index 903d07bea0..ea3f0b61b9 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs @@ -51,6 +51,11 @@ namespace osu.Game.Beatmaps /// public string Preview { get; set; } + /// + /// The beats per minute of this beatmap set's song. + /// + public double BPM { get; set; } + /// /// The amount of plays this beatmap set has. /// diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 50128bde7a..200a705500 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -77,13 +77,13 @@ namespace osu.Game.Online.API.Requests.Responses Metadata = this, Status = Status, Metrics = ratings == null ? null : new BeatmapSetMetrics { Ratings = ratings }, - BPM = bpm, OnlineInfo = new BeatmapSetOnlineInfo { Covers = covers, Preview = preview, PlayCount = playCount, FavouriteCount = favouriteCount, + BPM = bpm, Status = Status, HasVideo = hasVideo, HasStoryboard = hasStoryboard, diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index f97212f180..2926c82631 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -50,7 +50,7 @@ namespace osu.Game.Overlays.BeatmapSet private void updateDisplay() { - bpm.Value = BeatmapSet?.BPM.ToString(@"0.##") ?? "-"; + bpm.Value = BeatmapSet?.OnlineInfo?.BPM.ToString(@"0.##") ?? "-"; if (beatmap == null) { diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 6457f78746..7934cf388f 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -49,7 +49,7 @@ namespace osu.Game.Screens.Select.Carousel return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded); case SortMode.BPM: - return BeatmapSet.BPM.CompareTo(otherSet.BeatmapSet.BPM); + return BeatmapSet.OnlineInfo.BPM.CompareTo(otherSet.BeatmapSet.OnlineInfo.BPM); case SortMode.Length: return BeatmapSet.MaxLength.CompareTo(otherSet.BeatmapSet.MaxLength); From 79ddb8d5d36f76131d5c75da5f6650d91ffa22c9 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 8 Jul 2019 09:23:01 +0300 Subject: [PATCH 1781/5608] Change to a more convenient xmldoc --- osu.Game/Beatmaps/BeatmapInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 1610e37620..609f75461c 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -52,7 +52,7 @@ namespace osu.Game.Beatmaps public BeatmapOnlineInfo OnlineInfo { get; set; } /// - /// The length in milliseconds of this beatmap's song. + /// The playable length of this beatmap. /// public double Length { get; set; } From 2d0c924bdf579bd935f1eaf9fa19ce50aba39d5f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 8 Jul 2019 09:35:12 +0300 Subject: [PATCH 1782/5608] Add xmldoc for MaxStarDifficulty and MaxLength --- osu.Game/Beatmaps/BeatmapSetInfo.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index a77dfa2148..3e6385bdd5 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -35,8 +35,14 @@ namespace osu.Game.Beatmaps [NotMapped] public BeatmapSetMetrics Metrics { get; set; } + /// + /// The maximum star difficulty of all beatmaps in this set. + /// public double MaxStarDifficulty => Beatmaps?.Max(b => b.StarDifficulty) ?? 0; + /// + /// The maximum playable length of all beatmaps in this set. + /// public double MaxLength => Beatmaps?.Max(b => b.Length) ?? 0; [NotMapped] From 5853a877c257a14316cf03e5a39dd2a70e912e90 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 8 Jul 2019 15:40:10 +0900 Subject: [PATCH 1783/5608] create base dependencies before caching, create player in playerloader --- osu.Game/OsuGame.cs | 2 +- osu.Game/Screens/Play/ReplayPlayerLoader.cs | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ab7efc6e38..1c426d928f 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -285,7 +285,7 @@ namespace osu.Game Ruleset.Value = databasedScoreInfo.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); - menuScreen.Push(new ReplayPlayerLoader(() => new ReplayPlayer(databasedScore), databasedScoreInfo.Mods)); + menuScreen.Push(new ReplayPlayerLoader(databasedScore, databasedScoreInfo.Mods)); }, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true); } diff --git a/osu.Game/Screens/Play/ReplayPlayerLoader.cs b/osu.Game/Screens/Play/ReplayPlayerLoader.cs index 1c24709e41..41f02b5cb1 100644 --- a/osu.Game/Screens/Play/ReplayPlayerLoader.cs +++ b/osu.Game/Screens/Play/ReplayPlayerLoader.cs @@ -1,32 +1,33 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Rulesets.Mods; +using osu.Game.Scoring; namespace osu.Game.Screens.Play { public class ReplayPlayerLoader : PlayerLoader { - private readonly IReadOnlyList mods; + private readonly Bindable> mods; - public ReplayPlayerLoader(Func player, IReadOnlyList mods) - : base(player) + public ReplayPlayerLoader(Score score, IReadOnlyList mods) + : base(() => new ReplayPlayer(score)) { - this.mods = mods; + this.mods = new Bindable>(mods); } - private DependencyContainer dependencies; - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - dependencies = new DependencyContainer(parent); - dependencies.Cache(new Bindable>(mods)); + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.Cache(mods); - return base.CreateChildDependencies(dependencies); + // Overwrite the global mods here for use in the mod hud. + Mods.Value = mods.Value; + + return dependencies; } } } From 6a86f62d17b05a899059337ed9f82d25a92f2d5d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 8 Jul 2019 16:13:03 +0900 Subject: [PATCH 1784/5608] Get mods from score info --- osu.Game/OsuGame.cs | 2 +- osu.Game/Screens/Play/ReplayPlayerLoader.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 1c426d928f..2260c5bb57 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -285,7 +285,7 @@ namespace osu.Game Ruleset.Value = databasedScoreInfo.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); - menuScreen.Push(new ReplayPlayerLoader(databasedScore, databasedScoreInfo.Mods)); + menuScreen.Push(new ReplayPlayerLoader(databasedScore)); }, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true); } diff --git a/osu.Game/Screens/Play/ReplayPlayerLoader.cs b/osu.Game/Screens/Play/ReplayPlayerLoader.cs index 41f02b5cb1..da30ed80b6 100644 --- a/osu.Game/Screens/Play/ReplayPlayerLoader.cs +++ b/osu.Game/Screens/Play/ReplayPlayerLoader.cs @@ -13,10 +13,10 @@ namespace osu.Game.Screens.Play { private readonly Bindable> mods; - public ReplayPlayerLoader(Score score, IReadOnlyList mods) + public ReplayPlayerLoader(Score score) : base(() => new ReplayPlayer(score)) { - this.mods = new Bindable>(mods); + mods = new Bindable>(score.ScoreInfo.Mods); } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) From ef22ab9340d152cb9713b4aded8957321f6b5412 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 8 Jul 2019 16:32:11 +0900 Subject: [PATCH 1785/5608] remove bindable --- osu.Game/Screens/Play/ReplayPlayerLoader.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/ReplayPlayerLoader.cs b/osu.Game/Screens/Play/ReplayPlayerLoader.cs index da30ed80b6..b877e7e2ca 100644 --- a/osu.Game/Screens/Play/ReplayPlayerLoader.cs +++ b/osu.Game/Screens/Play/ReplayPlayerLoader.cs @@ -11,21 +11,20 @@ namespace osu.Game.Screens.Play { public class ReplayPlayerLoader : PlayerLoader { - private readonly Bindable> mods; + private readonly IReadOnlyList mods; public ReplayPlayerLoader(Score score) : base(() => new ReplayPlayer(score)) { - mods = new Bindable>(score.ScoreInfo.Mods); + mods = score.ScoreInfo.Mods; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.Cache(mods); // Overwrite the global mods here for use in the mod hud. - Mods.Value = mods.Value; + Mods.Value = mods; return dependencies; } From 72362d92d47e388af4bb9457ed0b963bc1bd77ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 Jul 2019 16:34:11 +0900 Subject: [PATCH 1786/5608] Fix a few inspections from EAP r# --- osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs | 2 +- osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs | 7 ++++--- .../UserInterface/TestSceneScreenBreadcrumbControl.cs | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs b/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs index 364c986723..16e47c5df9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs @@ -70,7 +70,7 @@ namespace osu.Game.Tests.Visual.Online }); channelTabControl.OnRequestLeave += channel => channelTabControl.RemoveChannel(channel); - channelTabControl.Current.ValueChanged += channel => currentText.Text = "Currently selected channel: " + channel.NewValue.ToString(); + channelTabControl.Current.ValueChanged += channel => currentText.Text = "Currently selected channel: " + channel.NewValue; AddStep("Add random private channel", addRandomPrivateChannel); AddAssert("There is only one channels", () => channelTabControl.Items.Count() == 2); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs index 867b3130c9..38a9af05d8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs @@ -14,8 +14,6 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneBackButton : OsuTestScene { - private readonly BackButton button; - public override IReadOnlyList RequiredTypes => new[] { typeof(TwoLayerButton) @@ -23,6 +21,8 @@ namespace osu.Game.Tests.Visual.UserInterface public TestSceneBackButton() { + BackButton button; + Child = new Container { Anchor = Anchor.Centre, @@ -40,11 +40,12 @@ namespace osu.Game.Tests.Visual.UserInterface { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Action = () => button.Hide(), } } }; + button.Action = () => button.Hide(); + AddStep("show button", () => button.Show()); AddStep("hide button", () => button.Hide()); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs index 9c83fdf96c..0cb8683d72 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.UserInterface }, }; - breadcrumbs.Current.ValueChanged += screen => titleText.Text = $"Changed to {screen.NewValue.ToString()}"; + breadcrumbs.Current.ValueChanged += screen => titleText.Text = $"Changed to {screen.NewValue}"; breadcrumbs.Current.TriggerChange(); waitForCurrent(); From 129899f41950da4d0f11557000e5af1a617777d7 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 8 Jul 2019 10:43:35 +0300 Subject: [PATCH 1787/5608] Add a BPM property in BeatmapInfo --- .../Visual/SongSelect/TestScenePlaySongSelect.cs | 12 +++++------- osu.Game.Tournament/Components/SongBar.cs | 2 +- osu.Game/Beatmaps/BeatmapInfo.cs | 5 +++++ osu.Game/Beatmaps/BeatmapManager.cs | 7 ++----- osu.Game/Beatmaps/BeatmapSetInfo.cs | 5 +++++ .../Screens/Select/Carousel/CarouselBeatmapSet.cs | 2 +- 6 files changed, 19 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 27a341ffb7..f3255814f2 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -267,15 +267,18 @@ namespace osu.Game.Tests.Visual.SongSelect for (int i = 0; i < 6; i++) { int beatmapId = setId * 10 + i; + int length = RNG.Next(30000, 200000); + double bpm = RNG.NextSingle(80, 200); beatmaps.Add(new BeatmapInfo { Ruleset = getRuleset(), OnlineBeatmapID = beatmapId, Path = "normal.osu", - Version = $"{beatmapId} (length {TimeSpan.FromMilliseconds(length):m\\:ss})", + Version = $"{beatmapId} (length {TimeSpan.FromMilliseconds(length):m\\:ss}, bpm {bpm:0.#})", Length = length, + BPM = bpm, BaseDifficulty = new BeatmapDifficulty { OverallDifficulty = 3.5f, @@ -283,7 +286,6 @@ namespace osu.Game.Tests.Visual.SongSelect }); } - double bpm = RNG.NextSingle(80, 200); return new BeatmapSetInfo { OnlineBeatmapSetID = setId, @@ -292,15 +294,11 @@ namespace osu.Game.Tests.Visual.SongSelect { // Create random metadata, then we can check if sorting works based on these Artist = "Some Artist " + RNG.Next(0, 9), - Title = $"Some Song (set id {setId}, bpm {bpm:0.#})", + Title = $"Some Song (set id {setId}, max bpm {beatmaps.Max(b => b.BPM):0.#})", AuthorString = "Some Guy " + RNG.Next(0, 9), }, Beatmaps = beatmaps, DateAdded = DateTimeOffset.UtcNow, - OnlineInfo = new BeatmapSetOnlineInfo - { - BPM = bpm, - } }; } } diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 938fbba303..ec021a8d1f 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -158,7 +158,7 @@ namespace osu.Game.Tournament.Components return; } - var bpm = beatmap.BeatmapSet.BPM; + var bpm = beatmap.BeatmapSet.OnlineInfo.BPM; var length = beatmap.Length; string hardRockExtra = ""; string srExtra = ""; diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 609f75461c..fa1282647e 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -56,6 +56,11 @@ namespace osu.Game.Beatmaps /// public double Length { get; set; } + /// + /// The most common BPM of this beatmap. + /// + public double BPM { get; set; } + public string Path { get; set; } [JsonProperty("file_sha2")] diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 34a8ddf5c9..56816607ee 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -271,11 +271,7 @@ namespace osu.Game.Beatmaps OnlineBeatmapSetID = beatmap.BeatmapInfo.BeatmapSet?.OnlineBeatmapSetID, Beatmaps = new List(), Metadata = beatmap.Metadata, - DateAdded = DateTimeOffset.UtcNow, - OnlineInfo = new BeatmapSetOnlineInfo - { - BPM = beatmap.ControlPointInfo.BPMMode, - } + DateAdded = DateTimeOffset.UtcNow }; } @@ -307,6 +303,7 @@ namespace osu.Game.Beatmaps // TODO: this should be done in a better place once we actually need to dynamically update it. beatmap.BeatmapInfo.StarDifficulty = ruleset?.CreateInstance().CreateDifficultyCalculator(new DummyConversionBeatmap(beatmap)).Calculate().StarRating ?? 0; beatmap.BeatmapInfo.Length = beatmap.CalculateLength(); + beatmap.BeatmapInfo.BPM = beatmap.ControlPointInfo.BPMMode; beatmapInfos.Add(beatmap.BeatmapInfo); } diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 3e6385bdd5..4075263e12 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -45,6 +45,11 @@ namespace osu.Game.Beatmaps /// public double MaxLength => Beatmaps?.Max(b => b.Length) ?? 0; + /// + /// The maximum BPM of all beatmaps in this set. + /// + public double MaxBPM => Beatmaps?.Max(b => b.BPM) ?? 0; + [NotMapped] public bool DeletePending { get; set; } diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 7934cf388f..5a3996bb49 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -49,7 +49,7 @@ namespace osu.Game.Screens.Select.Carousel return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded); case SortMode.BPM: - return BeatmapSet.OnlineInfo.BPM.CompareTo(otherSet.BeatmapSet.OnlineInfo.BPM); + return BeatmapSet.MaxBPM.CompareTo(otherSet.BeatmapSet.MaxBPM); case SortMode.Length: return BeatmapSet.MaxLength.CompareTo(otherSet.BeatmapSet.MaxLength); From 574d9a51b393a1baae947eab18d08ff1fa74da85 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 8 Jul 2019 10:44:23 +0300 Subject: [PATCH 1788/5608] Update migrations --- ...cs => 20190708070844_AddBPMAndLengthColumns.Designer.cs} | 6 +++--- ...hColumns.cs => 20190708070844_AddBPMAndLengthColumns.cs} | 4 ++-- osu.Game/Migrations/OsuDbContextModelSnapshot.cs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) rename osu.Game/Migrations/{20190707172237_AddBPMAndLengthColumns.Designer.cs => 20190708070844_AddBPMAndLengthColumns.Designer.cs} (99%) rename osu.Game/Migrations/{20190707172237_AddBPMAndLengthColumns.cs => 20190708070844_AddBPMAndLengthColumns.cs} (91%) diff --git a/osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.Designer.cs b/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs similarity index 99% rename from osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.Designer.cs rename to osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs index c1e9f5071a..c5fcc16f84 100644 --- a/osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.Designer.cs +++ b/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs @@ -9,7 +9,7 @@ using osu.Game.Database; namespace osu.Game.Migrations { [DbContext(typeof(OsuDbContext))] - [Migration("20190707172237_AddBPMAndLengthColumns")] + [Migration("20190708070844_AddBPMAndLengthColumns")] partial class AddBPMAndLengthColumns { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -47,6 +47,8 @@ namespace osu.Game.Migrations b.Property("AudioLeadIn"); + b.Property("BPM"); + b.Property("BaseDifficultyID"); b.Property("BeatDivisor"); @@ -170,8 +172,6 @@ namespace osu.Game.Migrations b.Property("ID") .ValueGeneratedOnAdd(); - b.Property("BPM"); - b.Property("DateAdded"); b.Property("DeletePending"); diff --git a/osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.cs b/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.cs similarity index 91% rename from osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.cs rename to osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.cs index b14722daf6..f5963ebf5e 100644 --- a/osu.Game/Migrations/20190707172237_AddBPMAndLengthColumns.cs +++ b/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.cs @@ -8,7 +8,7 @@ namespace osu.Game.Migrations { migrationBuilder.AddColumn( name: "BPM", - table: "BeatmapSetInfo", + table: "BeatmapInfo", nullable: false, defaultValue: 0.0); @@ -23,7 +23,7 @@ namespace osu.Game.Migrations { migrationBuilder.DropColumn( name: "BPM", - table: "BeatmapSetInfo"); + table: "BeatmapInfo"); migrationBuilder.DropColumn( name: "Length", diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 9e65dc7f0f..761dca2801 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -45,6 +45,8 @@ namespace osu.Game.Migrations b.Property("AudioLeadIn"); + b.Property("BPM"); + b.Property("BaseDifficultyID"); b.Property("BeatDivisor"); @@ -168,8 +170,6 @@ namespace osu.Game.Migrations b.Property("ID") .ValueGeneratedOnAdd(); - b.Property("BPM"); - b.Property("DateAdded"); b.Property("DeletePending"); From e78e326f34d84ce8cc3abbcc581adf35f8194bad Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 8 Jul 2019 17:02:42 +0900 Subject: [PATCH 1789/5608] remove unused using --- osu.Game/Screens/Play/ReplayPlayerLoader.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/ReplayPlayerLoader.cs b/osu.Game/Screens/Play/ReplayPlayerLoader.cs index b877e7e2ca..62edb661b9 100644 --- a/osu.Game/Screens/Play/ReplayPlayerLoader.cs +++ b/osu.Game/Screens/Play/ReplayPlayerLoader.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; From 16c993579bf943cb8ca71e89654e4ffd1115302c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 Jul 2019 17:10:12 +0900 Subject: [PATCH 1790/5608] Fix track transfer not running when beatmap is retrieved from cache --- osu.Game/Beatmaps/BeatmapManager.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 7ef50da7d3..5031176790 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -180,19 +180,18 @@ namespace osu.Game.Beatmaps lock (workingCache) { - var cached = workingCache.FirstOrDefault(w => w.BeatmapInfo?.ID == beatmapInfo.ID); + var working = workingCache.FirstOrDefault(w => w.BeatmapInfo?.ID == beatmapInfo.ID); - if (cached != null) - return cached; + if (working == null) + { + if (beatmapInfo.Metadata == null) + beatmapInfo.Metadata = beatmapInfo.BeatmapSet.Metadata; - if (beatmapInfo.Metadata == null) - beatmapInfo.Metadata = beatmapInfo.BeatmapSet.Metadata; - - WorkingBeatmap working = new BeatmapManagerWorkingBeatmap(Files.Store, new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)), beatmapInfo, audioManager); + workingCache.Add(working = new BeatmapManagerWorkingBeatmap(Files.Store, + new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)), beatmapInfo, audioManager)); + } previous?.TransferTo(working); - workingCache.Add(working); - return working; } } From a0efd50f629476bda2f1bfa86e7d801cd2662a48 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 8 Jul 2019 11:25:25 +0300 Subject: [PATCH 1791/5608] Extend APILegacyScores request --- osu.Game/Online/API/Requests/GetScoresRequest.cs | 8 ++++++++ .../Online/API/Requests/Responses/APILegacyScores.cs | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 6b0e680eb5..50844fa256 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -42,6 +42,14 @@ namespace osu.Game.Online.API.Requests score.Beatmap = beatmap; score.Ruleset = ruleset; } + + var userScore = r.UserScore; + + if (userScore != null) + { + userScore.Score.Beatmap = beatmap; + userScore.Score.Ruleset = ruleset; + } } protected override string Target => $@"beatmaps/{beatmap.OnlineBeatmapID}/scores{createQueryParameters()}"; diff --git a/osu.Game/Online/API/Requests/Responses/APILegacyScores.cs b/osu.Game/Online/API/Requests/Responses/APILegacyScores.cs index c629caaa6f..318fcb00de 100644 --- a/osu.Game/Online/API/Requests/Responses/APILegacyScores.cs +++ b/osu.Game/Online/API/Requests/Responses/APILegacyScores.cs @@ -10,5 +10,17 @@ namespace osu.Game.Online.API.Requests.Responses { [JsonProperty(@"scores")] public List Scores; + + [JsonProperty(@"userScore")] + public APILegacyUserTopScoreInfo UserScore; + } + + public class APILegacyUserTopScoreInfo + { + [JsonProperty(@"position")] + public int Position; + + [JsonProperty(@"score")] + public APILegacyScoreInfo Score; } } From fbd300e6643a582b9fab5299265633e907e16d6b Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 8 Jul 2019 17:37:20 +0900 Subject: [PATCH 1792/5608] Move ruleset into ReplayPlayerLoader as well --- osu.Game/OsuGame.cs | 1 - osu.Game/Screens/Play/ReplayPlayerLoader.cs | 9 ++++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 2260c5bb57..361ff62155 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -282,7 +282,6 @@ namespace osu.Game performFromMainMenu(() => { - Ruleset.Value = databasedScoreInfo.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); menuScreen.Push(new ReplayPlayerLoader(databasedScore)); diff --git a/osu.Game/Screens/Play/ReplayPlayerLoader.cs b/osu.Game/Screens/Play/ReplayPlayerLoader.cs index 62edb661b9..329e799f7c 100644 --- a/osu.Game/Screens/Play/ReplayPlayerLoader.cs +++ b/osu.Game/Screens/Play/ReplayPlayerLoader.cs @@ -1,21 +1,19 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Game.Rulesets.Mods; using osu.Game.Scoring; namespace osu.Game.Screens.Play { public class ReplayPlayerLoader : PlayerLoader { - private readonly IReadOnlyList mods; + private readonly ScoreInfo scoreInfo; public ReplayPlayerLoader(Score score) : base(() => new ReplayPlayer(score)) { - mods = score.ScoreInfo.Mods; + scoreInfo = score.ScoreInfo; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -23,7 +21,8 @@ namespace osu.Game.Screens.Play var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); // Overwrite the global mods here for use in the mod hud. - Mods.Value = mods; + Mods.Value = scoreInfo.Mods; + Ruleset.Value = scoreInfo.Ruleset; return dependencies; } From 67a6abb96c7e08c0afa5e4f5eb49c0e6bbeb369c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 8 Jul 2019 11:49:33 +0300 Subject: [PATCH 1793/5608] Add user top score on selected beatmap --- .../BeatmapSet/Scores/DrawableTopScore.cs | 22 +++------- .../BeatmapSet/Scores/ScoresContainer.cs | 41 +++++++++++++++---- .../BeatmapSet/Scores/TopScoreUserSection.cs | 4 +- 3 files changed, 41 insertions(+), 26 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 8e806c6747..bdae730f7e 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -23,10 +23,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private Color4 backgroundHoveredColour; private readonly Box background; - private readonly TopScoreUserSection userSection; - private readonly TopScoreStatisticsSection statisticsSection; - public DrawableTopScore() + public DrawableTopScore(ScoreInfo score, int position = 1) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -61,16 +59,18 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { new Drawable[] { - userSection = new TopScoreUserSection + new TopScoreUserSection(position) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, + Score = score, }, null, - statisticsSection = new TopScoreStatisticsSection + new TopScoreStatisticsSection { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, + Score = score, } }, }, @@ -91,18 +91,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores background.Colour = backgroundIdleColour; } - /// - /// Sets the score to be displayed. - /// - public ScoreInfo Score - { - set - { - userSection.Score = value; - statisticsSection.Score = value; - } - } - protected override bool OnHover(HoverEvent e) { background.FadeColour(backgroundHoveredColour, fade_duration, Easing.OutQuint); diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 3e6c938802..30685fb826 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -14,6 +14,7 @@ using osuTK; using System.Collections.Generic; using System.Linq; using osu.Game.Scoring; +using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -25,7 +26,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly Box background; private readonly ScoreTable scoreTable; - private readonly DrawableTopScore topScore; + private readonly FillFlowContainer topScoresContainer; private readonly LoadingAnimation loadingAnimation; [Resolved] @@ -54,7 +55,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { - topScore = new DrawableTopScore(), + topScoresContainer = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + }, scoreTable = new ScoreTable { Anchor = Anchor.TopCentre, @@ -97,6 +104,20 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } + private APILegacyUserTopScoreInfo userScore; + + public APILegacyUserTopScoreInfo UserScore + { + get => userScore; + set + { + getScoresRequest?.Cancel(); + userScore = value; + + updateDisplay(); + } + } + private BeatmapInfo beatmap; public BeatmapInfo Beatmap @@ -114,7 +135,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores loading = true; getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); - getScoresRequest.Success += r => Schedule(() => Scores = r.Scores); + getScoresRequest.Success += r => Schedule(() => + { + scores = r.Scores; + userScore = r.UserScore; + updateDisplay(); + }); api.Queue(getScoresRequest); } } @@ -122,17 +148,18 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void updateDisplay() { loading = false; + topScoresContainer.Clear(); scoreTable.Scores = scores?.Count > 1 ? scores : new List(); scoreTable.FadeTo(scores?.Count > 1 ? 1 : 0); if (scores?.Any() == true) { - topScore.Score = scores.FirstOrDefault(); - topScore.Show(); + topScoresContainer.Add(new DrawableTopScore(scores.FirstOrDefault())); + + if (userScore != null && userScore.Position != 1) + topScoresContainer.Add(new DrawableTopScore(userScore.Score, userScore.Position)); } - else - topScore.Hide(); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 1d9c4e7fc8..1314573cb4 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly SpriteText date; private readonly UpdateableFlag flag; - public TopScoreUserSection() + public TopScoreUserSection(int position) { AutoSizeAxes = Axes.Both; @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Text = "#1", + Text = position.ToString(), Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true) }, rank = new UpdateableRank(ScoreRank.D) From 5f3f59629ec04a69132f3419d8e2667795500ffb Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 8 Jul 2019 11:55:07 +0300 Subject: [PATCH 1794/5608] Use the length field instead of recalculating --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 26a83f930c..2551ffe2fc 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -291,7 +291,7 @@ namespace osu.Game.Screens.Select { Name = "Length", Icon = FontAwesome.Regular.Clock, - Content = TimeSpan.FromMilliseconds(b.CalculateLength()).ToString(@"m\:ss"), + Content = TimeSpan.FromMilliseconds(b.BeatmapInfo.Length).ToString(@"m\:ss"), })); labels.Add(new InfoLabel(new BeatmapStatistic From b62e69d170ebd0ed24c704a2a1ebf6397af32a82 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 8 Jul 2019 11:56:48 +0300 Subject: [PATCH 1795/5608] Calculate length inside BeatmapManager --- osu.Game/Beatmaps/BeatmapManager.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 56816607ee..6fe70b6ec6 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -23,6 +23,7 @@ using osu.Game.IO.Archives; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Rulesets; +using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Beatmaps { @@ -302,7 +303,7 @@ namespace osu.Game.Beatmaps beatmap.BeatmapInfo.Ruleset = ruleset; // TODO: this should be done in a better place once we actually need to dynamically update it. beatmap.BeatmapInfo.StarDifficulty = ruleset?.CreateInstance().CreateDifficultyCalculator(new DummyConversionBeatmap(beatmap)).Calculate().StarRating ?? 0; - beatmap.BeatmapInfo.Length = beatmap.CalculateLength(); + beatmap.BeatmapInfo.Length = calculateLength(beatmap); beatmap.BeatmapInfo.BPM = beatmap.ControlPointInfo.BPMMode; beatmapInfos.Add(beatmap.BeatmapInfo); @@ -312,6 +313,14 @@ namespace osu.Game.Beatmaps return beatmapInfos; } + private double calculateLength(IBeatmap b) + { + var lastObject = b.HitObjects.LastOrDefault(); + var endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0; + + return endTime - b.HitObjects.FirstOrDefault()?.StartTime ?? 0; + } + /// /// A dummy WorkingBeatmap for the purpose of retrieving a beatmap for star difficulty calculation. /// From 11ef65e3e2d72cd750f4dc1626c3373f0df92864 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 8 Jul 2019 11:57:02 +0300 Subject: [PATCH 1796/5608] Remove unnecessary extension --- osu.Game/Beatmaps/Beatmap.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 7fca13a1e2..4ebeee40bf 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -8,7 +8,6 @@ using System.Linq; using osu.Game.Beatmaps.ControlPoints; using Newtonsoft.Json; using osu.Game.IO.Serialization.Converters; -using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Beatmaps { @@ -62,15 +61,4 @@ namespace osu.Game.Beatmaps { public new Beatmap Clone() => (Beatmap)base.Clone(); } - - public static class BeatmapExtensions - { - public static double CalculateLength(this IBeatmap b) - { - HitObject lastObject = b.HitObjects.LastOrDefault(); - var endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0; - - return endTime - b.HitObjects.FirstOrDefault()?.StartTime ?? 0; - } - } } From d489a77fe18c3a3f06b1cccb733fdb8a410bcb39 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 8 Jul 2019 17:57:29 +0900 Subject: [PATCH 1797/5608] remove new container and comment --- osu.Game/Screens/Play/ReplayPlayerLoader.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/ReplayPlayerLoader.cs b/osu.Game/Screens/Play/ReplayPlayerLoader.cs index 329e799f7c..8681ae6887 100644 --- a/osu.Game/Screens/Play/ReplayPlayerLoader.cs +++ b/osu.Game/Screens/Play/ReplayPlayerLoader.cs @@ -18,9 +18,8 @@ namespace osu.Game.Screens.Play protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + var dependencies = base.CreateChildDependencies(parent); - // Overwrite the global mods here for use in the mod hud. Mods.Value = scoreInfo.Mods; Ruleset.Value = scoreInfo.Ruleset; From 59cfd39670c62df39ba8ce95f71e23c86395e7f1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 8 Jul 2019 12:02:10 +0300 Subject: [PATCH 1798/5608] Add testcase --- .../Visual/Online/TestSceneScoresContainer.cs | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index 06414af865..e4e6acec06 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; using osu.Game.Graphics; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; @@ -165,6 +166,29 @@ namespace osu.Game.Tests.Visual.Online }, }; + var myBestScore = new APILegacyUserTopScoreInfo + { + Score = new APILegacyScoreInfo + { + User = new User + { + Id = 7151382, + Username = @"Mayuri Hana", + Country = new Country + { + FullName = @"Thailand", + FlagName = @"TH", + }, + }, + Rank = ScoreRank.D, + PP = 160, + MaxCombo = 1234, + TotalScore = 123456, + Accuracy = 0.6543, + }, + Position = 1337, + }; + foreach (var s in scores) { s.Statistics.Add(HitResult.Great, RNG.Next(2000)); @@ -173,9 +197,18 @@ namespace osu.Game.Tests.Visual.Online s.Statistics.Add(HitResult.Miss, RNG.Next(2000)); } - AddStep("Load all scores", () => scoresContainer.Scores = scores); - AddStep("Load null scores", () => scoresContainer.Scores = null); + AddStep("Load all scores", () => + { + scoresContainer.Scores = scores; + scoresContainer.UserScore = myBestScore; + }); + AddStep("Load null scores", () => + { + scoresContainer.Scores = null; + scoresContainer.UserScore = null; + }); AddStep("Load only one score", () => scoresContainer.Scores = new[] { scores.First() }); + AddStep("Add my best score", () => scoresContainer.UserScore = myBestScore); } [BackgroundDependencyLoader] From 1e5639acee4858571dfe4c832354a04fef38432d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 8 Jul 2019 12:10:08 +0300 Subject: [PATCH 1799/5608] Add forgotten symbol --- osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 1314573cb4..385d8ff38c 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Text = position.ToString(), + Text = $"#{position.ToString()}", Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true) }, rank = new UpdateableRank(ScoreRank.D) From 39f04e497d5734ec57393b7a974cb255540f4ae6 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Mon, 8 Jul 2019 11:24:06 +0200 Subject: [PATCH 1800/5608] Add UserRequestedPause --- osu.Game/Overlays/MusicController.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 29ae5983be..3db71d39ee 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -66,6 +66,8 @@ namespace osu.Game.Overlays /// public Func GetToolbarHeight; + public bool UserRequestedPause { get; private set; } + public MusicController() { Width = 400; @@ -287,6 +289,8 @@ namespace osu.Game.Overlays return; } + UserRequestedPause = track.IsRunning; + if (track.IsRunning) track.Stop(); else From 0cf4bf2352048fd6feca7495a69b6d9e09b992f9 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 8 Jul 2019 18:46:12 +0900 Subject: [PATCH 1801/5608] Manually set clock for storyboard if loading before being given a parent --- osu.Game/Screens/Play/Player.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0da9c77f25..ea614e7658 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -362,7 +362,12 @@ namespace osu.Game.Screens.Play storyboard.Masking = true; if (asyncLoad) - LoadComponentAsync(storyboard, StoryboardContainer.Add); + LoadComponentAsync(storyboard, c => + { + // Since the storyboard was loaded before it can be added to the draw hierarchy, manually set the clock for it here. + c.Clock = GameplayClockContainer.GameplayClock; + StoryboardContainer.Add(c); + }); else StoryboardContainer.Add(storyboard); } From 581ffb7fb09d50fc0b64bb422841f830c61d1ac7 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Mon, 8 Jul 2019 13:52:15 +0200 Subject: [PATCH 1802/5608] Adjusted slider border colour --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 1d68793c50..4918ea60b2 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -64,14 +64,13 @@ namespace osu.Game.Rulesets.Osu.Mods case DrawableSlider slider: ApplyTraceableState(slider.HeadCircle, state); slider.Body.AccentColour = Color4.Transparent; - + slider.Body.BorderColour = slider.HeadCircle.AccentColour; break; case DrawableSpinner spinner: spinner.Disc.Hide(); //spinner.Ticks.Hide(); // do they contribute to the theme? debatable spinner.Background.Hide(); - break; } } From 54f5e6aedf4ffcce98f62a830020f1252eb42d93 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 Jul 2019 22:37:39 +0900 Subject: [PATCH 1803/5608] Add assertion and comment about lease logic --- osu.Game/Screens/Play/ReplayPlayerLoader.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/Play/ReplayPlayerLoader.cs b/osu.Game/Screens/Play/ReplayPlayerLoader.cs index 8681ae6887..86179ef067 100644 --- a/osu.Game/Screens/Play/ReplayPlayerLoader.cs +++ b/osu.Game/Screens/Play/ReplayPlayerLoader.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Game.Scoring; @@ -13,6 +14,9 @@ namespace osu.Game.Screens.Play public ReplayPlayerLoader(Score score) : base(() => new ReplayPlayer(score)) { + if (score.Replay == null) + throw new ArgumentNullException(nameof(score.Replay), $"{nameof(score)} must have a non-null {nameof(score.Replay)}."); + scoreInfo = score.ScoreInfo; } @@ -20,6 +24,7 @@ namespace osu.Game.Screens.Play { var dependencies = base.CreateChildDependencies(parent); + // these will be reverted thanks to PlayerLoader's lease. Mods.Value = scoreInfo.Mods; Ruleset.Value = scoreInfo.Ruleset; From 338371c3fcec0e9c45ac7ec440e732e083eae972 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Tue, 9 Jul 2019 00:08:18 +0200 Subject: [PATCH 1804/5608] Fix music playing while exiting from editor --- osu.Game/OsuGame.cs | 6 +++--- osu.Game/Screens/Edit/Editor.cs | 6 ------ osu.Game/Screens/Menu/MainMenu.cs | 4 +++- osu.Game/Screens/OsuScreen.cs | 11 ++++++++++- osu.Game/Screens/Select/SongSelect.cs | 2 ++ 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 0a472d4dc1..325d2cbd85 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -306,7 +306,7 @@ namespace osu.Game private void currentTrackCompleted() { if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled) - musicController.NextTrack(); + MusicController.NextTrack(); } #endregion @@ -484,7 +484,7 @@ namespace osu.Game Origin = Anchor.TopRight, }, rightFloatingOverlayContent.Add, true); - loadComponentSingleFile(musicController = new MusicController + loadComponentSingleFile(MusicController = new MusicController { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, @@ -752,7 +752,7 @@ namespace osu.Game private ScalingContainer screenContainer; - private MusicController musicController; + public MusicController MusicController { get; private set; } protected override bool OnExiting() { diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 89da9ae063..676e060433 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -239,12 +239,6 @@ namespace osu.Game.Screens.Edit { Background.FadeColour(Color4.White, 500); - if (Beatmap.Value.Track != null) - { - Beatmap.Value.Track.Tempo.Value = 1; - Beatmap.Value.Track.Start(); - } - return base.OnExiting(next); } diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index c64bea840f..dcce49179d 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -120,7 +120,7 @@ namespace osu.Game.Screens.Menu var track = Beatmap.Value.Track; var metadata = Beatmap.Value.Metadata; - if (last is Intro && track != null) + if (last is Intro && track != null && !Game.MusicController.UserRequestedPause) { if (!track.IsRunning) { @@ -189,6 +189,8 @@ namespace osu.Game.Screens.Menu //we may have consumed our preloaded instance, so let's make another. preloadSongSelect(); + + ResumeIfNoUserPauseRequested(); } public override bool OnExiting(IScreen next) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 328631ff9c..0682710133 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens public virtual bool CursorVisible => true; - protected new OsuGameBase Game => base.Game as OsuGameBase; + protected new OsuGame Game => base.Game as OsuGame; /// /// The to set the user's activity automatically to when this screen is entered @@ -179,6 +179,15 @@ namespace osu.Game.Screens api.Activity.Value = activity; } + protected void ResumeIfNoUserPauseRequested() + { + if (Beatmap.Value.Track != null && !Game.MusicController.UserRequestedPause) + { + Beatmap.Value.Track.Tempo.Value = 1; + Beatmap.Value.Track.Start(); + } + } + /// /// Fired when this screen was entered or resumed and the logo state is required to be adjusted. /// diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index bf5857f725..17b2ae376f 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -426,6 +426,8 @@ namespace osu.Game.Screens.Select { base.OnEntering(last); + ResumeIfNoUserPauseRequested(); + this.FadeInFromZero(250); FilterControl.Activate(); } From 8f7476e9ccf2f8dd3744315cb56a852d5ff4197a Mon Sep 17 00:00:00 2001 From: Oskar Solecki <31374466+Desconocidosmh@users.noreply.github.com> Date: Tue, 9 Jul 2019 00:26:57 +0200 Subject: [PATCH 1805/5608] Remove unused stuff --- osu.Game/Screens/Edit/Editor.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index cffe756548..676e060433 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -168,8 +168,6 @@ namespace osu.Game.Screens.Edit menuBar.Mode.ValueChanged += onModeChanged; - host.Exiting += onExitingGame; - bottomBackground.Colour = colours.Gray2; } @@ -237,8 +235,6 @@ namespace osu.Game.Screens.Edit Beatmap.Value.Track?.Stop(); } - private bool isExitingGame = false; - public override bool OnExiting(IScreen next) { Background.FadeColour(Color4.White, 500); @@ -279,7 +275,5 @@ namespace osu.Game.Screens.Edit else clock.SeekForward(!clock.IsRunning, amount); } - - private bool onExitingGame() => isExitingGame = true; } } From 5d81445454bd03c1018bce7c660e65fc931af915 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 9 Jul 2019 08:05:34 +0300 Subject: [PATCH 1806/5608] Move api request outside the scores container --- .../Visual/Online/TestSceneScoresContainer.cs | 243 ++++++++++-------- .../BeatmapSet/Scores/ScoresContainer.cs | 82 ++---- osu.Game/Overlays/BeatmapSetOverlay.cs | 30 ++- 3 files changed, 184 insertions(+), 171 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index e4e6acec06..730bf0d4e2 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -50,120 +50,123 @@ namespace osu.Game.Tests.Visual.Online } }; - var scores = new List + var allScores = new APILegacyScores { - new ScoreInfo + Scores = new List { - User = new User + new APILegacyScoreInfo { - Id = 6602580, - Username = @"waaiiru", - Country = new Country + User = new User { - FullName = @"Spain", - FlagName = @"ES", + Id = 6602580, + Username = @"waaiiru", + Country = new Country + { + FullName = @"Spain", + FlagName = @"ES", + }, }, - }, - Mods = new Mod[] - { - new OsuModDoubleTime(), - new OsuModHidden(), - new OsuModFlashlight(), - new OsuModHardRock(), - }, - Rank = ScoreRank.XH, - PP = 200, - MaxCombo = 1234, - TotalScore = 1234567890, - Accuracy = 1, - }, - new ScoreInfo - { - User = new User - { - Id = 4608074, - Username = @"Skycries", - Country = new Country + Mods = new Mod[] { - FullName = @"Brazil", - FlagName = @"BR", + new OsuModDoubleTime(), + new OsuModHidden(), + new OsuModFlashlight(), + new OsuModHardRock(), }, + Rank = ScoreRank.XH, + PP = 200, + MaxCombo = 1234, + TotalScore = 1234567890, + Accuracy = 1, }, - Mods = new Mod[] + new APILegacyScoreInfo { - new OsuModDoubleTime(), - new OsuModHidden(), - new OsuModFlashlight(), - }, - Rank = ScoreRank.S, - PP = 190, - MaxCombo = 1234, - TotalScore = 1234789, - Accuracy = 0.9997, - }, - new ScoreInfo - { - User = new User - { - Id = 1014222, - Username = @"eLy", - Country = new Country + User = new User { - FullName = @"Japan", - FlagName = @"JP", + Id = 4608074, + Username = @"Skycries", + Country = new Country + { + FullName = @"Brazil", + FlagName = @"BR", + }, }, - }, - Mods = new Mod[] - { - new OsuModDoubleTime(), - new OsuModHidden(), - }, - Rank = ScoreRank.B, - PP = 180, - MaxCombo = 1234, - TotalScore = 12345678, - Accuracy = 0.9854, - }, - new ScoreInfo - { - User = new User - { - Id = 1541390, - Username = @"Toukai", - Country = new Country + Mods = new Mod[] { - FullName = @"Canada", - FlagName = @"CA", + new OsuModDoubleTime(), + new OsuModHidden(), + new OsuModFlashlight(), }, + Rank = ScoreRank.S, + PP = 190, + MaxCombo = 1234, + TotalScore = 1234789, + Accuracy = 0.9997, }, - Mods = new Mod[] + new APILegacyScoreInfo { - new OsuModDoubleTime(), - }, - Rank = ScoreRank.C, - PP = 170, - MaxCombo = 1234, - TotalScore = 1234567, - Accuracy = 0.8765, - }, - new ScoreInfo - { - User = new User - { - Id = 7151382, - Username = @"Mayuri Hana", - Country = new Country + User = new User { - FullName = @"Thailand", - FlagName = @"TH", + Id = 1014222, + Username = @"eLy", + Country = new Country + { + FullName = @"Japan", + FlagName = @"JP", + }, }, + Mods = new Mod[] + { + new OsuModDoubleTime(), + new OsuModHidden(), + }, + Rank = ScoreRank.B, + PP = 180, + MaxCombo = 1234, + TotalScore = 12345678, + Accuracy = 0.9854, }, - Rank = ScoreRank.D, - PP = 160, - MaxCombo = 1234, - TotalScore = 123456, - Accuracy = 0.6543, - }, + new APILegacyScoreInfo + { + User = new User + { + Id = 1541390, + Username = @"Toukai", + Country = new Country + { + FullName = @"Canada", + FlagName = @"CA", + }, + }, + Mods = new Mod[] + { + new OsuModDoubleTime(), + }, + Rank = ScoreRank.C, + PP = 170, + MaxCombo = 1234, + TotalScore = 1234567, + Accuracy = 0.8765, + }, + new APILegacyScoreInfo + { + User = new User + { + Id = 7151382, + Username = @"Mayuri Hana", + Country = new Country + { + FullName = @"Thailand", + FlagName = @"TH", + }, + }, + Rank = ScoreRank.D, + PP = 160, + MaxCombo = 1234, + TotalScore = 123456, + Accuracy = 0.6543, + }, + } }; var myBestScore = new APILegacyUserTopScoreInfo @@ -189,7 +192,39 @@ namespace osu.Game.Tests.Visual.Online Position = 1337, }; - foreach (var s in scores) + var oneScore = new APILegacyScores + { + Scores = new List + { + new APILegacyScoreInfo + { + User = new User + { + Id = 6602580, + Username = @"waaiiru", + Country = new Country + { + FullName = @"Spain", + FlagName = @"ES", + }, + }, + Mods = new Mod[] + { + new OsuModDoubleTime(), + new OsuModHidden(), + new OsuModFlashlight(), + new OsuModHardRock(), + }, + Rank = ScoreRank.XH, + PP = 200, + MaxCombo = 1234, + TotalScore = 1234567890, + Accuracy = 1, + } + } + }; + + foreach (var s in allScores.Scores) { s.Statistics.Add(HitResult.Great, RNG.Next(2000)); s.Statistics.Add(HitResult.Good, RNG.Next(2000)); @@ -199,16 +234,16 @@ namespace osu.Game.Tests.Visual.Online AddStep("Load all scores", () => { - scoresContainer.Scores = scores; - scoresContainer.UserScore = myBestScore; + allScores.UserScore = null; + scoresContainer.Scores = allScores; }); - AddStep("Load null scores", () => + AddStep("Load null scores", () => scoresContainer.Scores = null); + AddStep("Load only one score", () => scoresContainer.Scores = oneScore); + AddStep("Load scores with my best", () => { - scoresContainer.Scores = null; - scoresContainer.UserScore = null; + allScores.UserScore = myBestScore; + scoresContainer.Scores = allScores; }); - AddStep("Load only one score", () => scoresContainer.Scores = new[] { scores.First() }); - AddStep("Add my best score", () => scoresContainer.UserScore = myBestScore); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 30685fb826..7e0f3d0b1c 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -5,15 +5,11 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osuTK; using System.Collections.Generic; using System.Linq; -using osu.Game.Scoring; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.BeatmapSet.Scores @@ -29,9 +25,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly FillFlowContainer topScoresContainer; private readonly LoadingAnimation loadingAnimation; - [Resolved] - private IAPIProvider api { get; set; } - public ScoresContainer() { RelativeSizeAxes = Axes.X; @@ -72,7 +65,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores loadingAnimation = new LoadingAnimation { Alpha = 0, - Margin = new MarginPadding(20) + Margin = new MarginPadding(20), }, }; } @@ -84,87 +77,46 @@ namespace osu.Game.Overlays.BeatmapSet.Scores updateDisplay(); } - private bool loading + public bool Loading { - set => loadingAnimation.FadeTo(value ? 1 : 0, fade_duration); + set + { + loadingAnimation.FadeTo(value ? 1 : 0, fade_duration); + + if (value) + Scores = null; + } } - private GetScoresRequest getScoresRequest; - private IReadOnlyList scores; + private APILegacyScores scores; - public IReadOnlyList Scores + public APILegacyScores Scores { get => scores; set { - getScoresRequest?.Cancel(); scores = value; updateDisplay(); } } - private APILegacyUserTopScoreInfo userScore; - - public APILegacyUserTopScoreInfo UserScore - { - get => userScore; - set - { - getScoresRequest?.Cancel(); - userScore = value; - - updateDisplay(); - } - } - - private BeatmapInfo beatmap; - - public BeatmapInfo Beatmap - { - get => beatmap; - set - { - beatmap = value; - - Scores = null; - - if (beatmap?.OnlineBeatmapID.HasValue != true) - return; - - loading = true; - - getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); - getScoresRequest.Success += r => Schedule(() => - { - scores = r.Scores; - userScore = r.UserScore; - updateDisplay(); - }); - api.Queue(getScoresRequest); - } - } - private void updateDisplay() { - loading = false; topScoresContainer.Clear(); - scoreTable.Scores = scores?.Count > 1 ? scores : new List(); - scoreTable.FadeTo(scores?.Count > 1 ? 1 : 0); + scoreTable.Scores = scores?.Scores.Count > 1 ? scores.Scores : new List(); + scoreTable.FadeTo(scores?.Scores.Count > 1 ? 1 : 0); - if (scores?.Any() == true) + if (scores?.Scores.Any() == true) { - topScoresContainer.Add(new DrawableTopScore(scores.FirstOrDefault())); + topScoresContainer.Add(new DrawableTopScore(scores.Scores.FirstOrDefault())); + + var userScore = scores.UserScore; if (userScore != null && userScore.Position != 1) topScoresContainer.Add(new DrawableTopScore(userScore.Score, userScore.Position)); } } - - protected override void Dispose(bool isDisposing) - { - getScoresRequest?.Cancel(); - } } } diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 19f6a3f692..df132f9d47 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -11,6 +11,7 @@ using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.BeatmapSet; using osu.Game.Overlays.BeatmapSet.Scores; @@ -30,9 +31,14 @@ namespace osu.Game.Overlays protected readonly Header Header; private RulesetStore rulesets; + private ScoresContainer scores; + private GetScoresRequest getScoresRequest; private readonly Bindable beatmapSet = new Bindable(); + [Resolved] + private IAPIProvider api { get; set; } + // receive input outside our bounds so we can trigger a close event on ourselves. public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; @@ -40,7 +46,6 @@ namespace osu.Game.Overlays { OsuScrollContainer scroll; Info info; - ScoresContainer scores; Children = new Drawable[] { @@ -74,12 +79,33 @@ namespace osu.Game.Overlays Header.Picker.Beatmap.ValueChanged += b => { info.Beatmap = b.NewValue; - scores.Beatmap = b.NewValue; + getScores(b.NewValue); scroll.ScrollToStart(); }; } + private void getScores(BeatmapInfo b) + { + getScoresRequest?.Cancel(); + + if (b?.OnlineBeatmapID.HasValue != true) + { + scores.Scores = null; + return; + } + + scores.Loading = true; + + getScoresRequest = new GetScoresRequest(b, b.Ruleset); + getScoresRequest.Success += r => Schedule(() => + { + scores.Scores = r; + scores.Loading = false; + }); + api.Queue(getScoresRequest); + } + [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { From 8d46d4a28e6fc0a6ba3c72df86faac97c4439dfd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 9 Jul 2019 08:09:31 +0300 Subject: [PATCH 1807/5608] Fix grade layout --- .../BeatmapSet/Scores/TopScoreUserSection.cs | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 385d8ff38c..056fe71a39 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -39,19 +39,30 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(10, 0), Children = new Drawable[] { - rankText = new OsuSpriteText + new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Text = $"#{position.ToString()}", - Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true) - }, - rank = new UpdateableRank(ScoreRank.D) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(40), - FillMode = FillMode.Fit, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 3), + Children = new Drawable[] + { + rankText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = $"#{position.ToString()}", + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true) + }, + rank = new UpdateableRank(ScoreRank.D) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(40), + FillMode = FillMode.Fit, + }, + } }, avatar = new UpdateableAvatar(hideImmediately: true) { From eb4ef8f6ac8a2c32cb53f4f1cc006e687e7252dc Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 9 Jul 2019 08:25:10 +0300 Subject: [PATCH 1808/5608] CI fixes --- osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs | 1 - osu.Game/Overlays/BeatmapSetOverlay.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index 730bf0d4e2..827a300a5e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index df132f9d47..44475dc53c 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays protected readonly Header Header; private RulesetStore rulesets; - private ScoresContainer scores; + private readonly ScoresContainer scores; private GetScoresRequest getScoresRequest; private readonly Bindable beatmapSet = new Bindable(); From 89cb8a0cacb4ac50a1b83cbf32923d40ba5d13d7 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 9 Jul 2019 16:23:59 +0900 Subject: [PATCH 1809/5608] Move storyboard initialization to new StoryboardContainer --- .../TestSceneBackgroundScreenBeatmap.cs | 26 ++++---- .../Containers/StoryboardContainer.cs | 59 +++++++++++++++++++ .../Graphics/Containers/UserDimContainer.cs | 52 ++++++++-------- osu.Game/Screens/Play/Player.cs | 42 ++----------- 4 files changed, 103 insertions(+), 76 deletions(-) create mode 100644 osu.Game/Graphics/Containers/StoryboardContainer.cs diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs index 8b941e4633..0d62bf9bdc 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs @@ -28,6 +28,7 @@ using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Play; using osu.Game.Screens.Play.PlayerSettings; using osu.Game.Screens.Select; +using osu.Game.Storyboards; using osu.Game.Tests.Resources; using osu.Game.Users; using osuTK; @@ -333,9 +334,9 @@ namespace osu.Game.Tests.Visual.Background { protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); - protected override UserDimContainer CreateStoryboardContainer() + protected override StoryboardContainer CreateStoryboardContainer(Storyboard storyboard) { - return new TestUserDimContainer(true) + return new TestStoryboardContainer { RelativeSizeAxes = Axes.Both, Alpha = 1, @@ -343,7 +344,7 @@ namespace osu.Game.Tests.Visual.Background }; } - public UserDimContainer CurrentStoryboardContainer => StoryboardContainer; + public TestStoryboardContainer CurrentStoryboardContainer => (TestStoryboardContainer)StoryboardContainer; // Whether or not the player should be allowed to load. public bool BlockLoad; @@ -357,9 +358,9 @@ namespace osu.Game.Tests.Visual.Background { } - public bool IsStoryboardVisible() => ((TestUserDimContainer)CurrentStoryboardContainer).CurrentAlpha == 1; + public bool IsStoryboardVisible() => CurrentStoryboardContainer.CurrentAlpha == 1; - public bool IsStoryboardInvisible() => ((TestUserDimContainer)CurrentStoryboardContainer).CurrentAlpha <= 1; + public bool IsStoryboardInvisible() => CurrentStoryboardContainer.CurrentAlpha <= 1; [BackgroundDependencyLoader] private void load(OsuConfigManager config, CancellationToken token) @@ -408,15 +409,20 @@ namespace osu.Game.Tests.Visual.Background } } + private class TestStoryboardContainer : StoryboardContainer + { + public float CurrentAlpha => DimContainer.Alpha; + + public TestStoryboardContainer() + : base(new Storyboard()) + { + } + } + private class TestUserDimContainer : UserDimContainer { public Color4 CurrentColour => DimContainer.Colour; public float CurrentAlpha => DimContainer.Alpha; - - public TestUserDimContainer(bool isStoryboard = false) - : base(isStoryboard) - { - } } } } diff --git a/osu.Game/Graphics/Containers/StoryboardContainer.cs b/osu.Game/Graphics/Containers/StoryboardContainer.cs new file mode 100644 index 0000000000..c425d38d48 --- /dev/null +++ b/osu.Game/Graphics/Containers/StoryboardContainer.cs @@ -0,0 +1,59 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Storyboards; +using osu.Game.Storyboards.Drawables; + +namespace osu.Game.Graphics.Containers +{ + /// + /// A container that handles loading, as well as applies user-specified visual settings to it. + /// + public class StoryboardContainer : UserDimContainer + { + private readonly Storyboard storyboard; + private DrawableStoryboard drawableStoryboard; + + public StoryboardContainer(Storyboard storyboard) + { + this.storyboard = storyboard; + } + + [BackgroundDependencyLoader] + private void load() + { + initializeStoryboard(false); + } + + protected override void LoadComplete() + { + ShowStoryboard.ValueChanged += _ => initializeStoryboard(true); + base.LoadComplete(); + } + + protected override void ApplyFade() + { + // Storyboards cannot be blurred, so we should just hide the storyboard if it gets toggled. + DimContainer.FadeTo(!ShowStoryboard.Value || UserDimLevel.Value == 1 ? 0 : 1, BACKGROUND_FADE_DURATION, Easing.OutQuint); + } + + private void initializeStoryboard(bool async) + { + if (drawableStoryboard != null) + return; + + if (!ShowStoryboard.Value) + return; + + drawableStoryboard = storyboard.CreateDrawable(); + drawableStoryboard.Masking = true; + + if (async) + LoadComponentAsync(drawableStoryboard, Add); + else + Add(drawableStoryboard); + } + } +} diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index fe9eb7baf4..b14051f432 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -16,11 +16,10 @@ namespace osu.Game.Graphics.Containers { /// /// A container that applies user-configured visual settings to its contents. - /// This container specifies behavior that applies to both Storyboards and Backgrounds. /// public class UserDimContainer : Container { - private const float background_fade_duration = 800; + protected const float BACKGROUND_FADE_DURATION = 800; /// /// Whether or not user-configured dim levels should be applied to the container. @@ -40,17 +39,15 @@ namespace osu.Game.Graphics.Containers /// public readonly Bindable BlurAmount = new Bindable(); - private Bindable userDimLevel { get; set; } + protected Bindable UserDimLevel { get; private set; } - private Bindable userBlurLevel { get; set; } - - private Bindable showStoryboard { get; set; } + protected Bindable ShowStoryboard { get; private set; } protected Container DimContainer { get; } protected override Container Content => DimContainer; - private readonly bool isStoryboard; + private Bindable userBlurLevel { get; set; } /// /// As an optimisation, we add the two blur portions to be applied rather than actually applying two separate blurs. @@ -62,15 +59,12 @@ namespace osu.Game.Graphics.Containers /// /// Creates a new . /// - /// Whether or not this instance contains a storyboard. /// - /// While both backgrounds and storyboards allow user dim levels to be applied, storyboards can be toggled via + /// While both backgrounds and storyboards allow user dim levels to be applied, storyboards can be toggled via /// and can cause backgrounds to become hidden via . Storyboards are also currently unable to be blurred. /// - /// - public UserDimContainer(bool isStoryboard = false) + public UserDimContainer() { - this.isStoryboard = isStoryboard; AddInternal(DimContainer = new Container { RelativeSizeAxes = Axes.Both }); } @@ -97,16 +91,16 @@ namespace osu.Game.Graphics.Containers [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - userDimLevel = config.GetBindable(OsuSetting.DimLevel); + UserDimLevel = config.GetBindable(OsuSetting.DimLevel); userBlurLevel = config.GetBindable(OsuSetting.BlurLevel); - showStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); + ShowStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); EnableUserDim.ValueChanged += _ => updateVisuals(); - userDimLevel.ValueChanged += _ => updateVisuals(); - userBlurLevel.ValueChanged += _ => updateVisuals(); - showStoryboard.ValueChanged += _ => updateVisuals(); + UserDimLevel.ValueChanged += _ => updateVisuals(); + ShowStoryboard.ValueChanged += _ => updateVisuals(); StoryboardReplacesBackground.ValueChanged += _ => updateVisuals(); BlurAmount.ValueChanged += _ => updateVisuals(); + userBlurLevel.ValueChanged += _ => updateVisuals(); } protected override void LoadComplete() @@ -115,21 +109,21 @@ namespace osu.Game.Graphics.Containers updateVisuals(); } + /// + /// Apply non-dim related settings to the background, such as hiding and blurring. + /// + protected virtual void ApplyFade() + { + // The background needs to be hidden in the case of it being replaced by the storyboard + DimContainer.FadeTo(ShowStoryboard.Value && StoryboardReplacesBackground.Value ? 0 : 1, BACKGROUND_FADE_DURATION, Easing.OutQuint); + Background?.BlurTo(blurTarget, BACKGROUND_FADE_DURATION, Easing.OutQuint); + } + private void updateVisuals() { - if (isStoryboard) - { - DimContainer.FadeTo(!showStoryboard.Value || userDimLevel.Value == 1 ? 0 : 1, background_fade_duration, Easing.OutQuint); - } - else - { - // The background needs to be hidden in the case of it being replaced by the storyboard - DimContainer.FadeTo(showStoryboard.Value && StoryboardReplacesBackground.Value ? 0 : 1, background_fade_duration, Easing.OutQuint); + ApplyFade(); - Background?.BlurTo(blurTarget, background_fade_duration, Easing.OutQuint); - } - - DimContainer.FadeColour(EnableUserDim.Value ? OsuColour.Gray(1 - (float)userDimLevel.Value) : Color4.White, background_fade_duration, Easing.OutQuint); + DimContainer.FadeColour(EnableUserDim.Value ? OsuColour.Gray(1 - (float)UserDimLevel.Value) : Color4.White, BACKGROUND_FADE_DURATION, Easing.OutQuint); } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index ea614e7658..621df0b562 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -26,7 +26,7 @@ using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Ranking; using osu.Game.Skinning; -using osu.Game.Storyboards.Drawables; +using osu.Game.Storyboards; using osu.Game.Users; namespace osu.Game.Screens.Play @@ -109,7 +109,7 @@ namespace osu.Game.Screens.Play sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); - showStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); + config.GetBindable(OsuSetting.ShowStoryboard); ScoreProcessor = DrawableRuleset.CreateScoreProcessor(); ScoreProcessor.Mods.BindTo(Mods); @@ -121,7 +121,7 @@ namespace osu.Game.Screens.Play GameplayClockContainer.Children = new[] { - StoryboardContainer = CreateStoryboardContainer(), + StoryboardContainer = CreateStoryboardContainer(Beatmap.Value.Storyboard), new ScalingContainer(ScalingMode.Gameplay) { Child = new LocalSkinOverrideContainer(working.Skin) @@ -199,9 +199,6 @@ namespace osu.Game.Screens.Play // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); - // load storyboard as part of player's load if we can - initializeStoryboard(false); - // Bind ScoreProcessor to ourselves ScoreProcessor.AllJudged += onCompletion; ScoreProcessor.Failed += onFail; @@ -336,42 +333,15 @@ namespace osu.Game.Screens.Play #region Storyboard - private DrawableStoryboard storyboard; - protected UserDimContainer StoryboardContainer { get; private set; } + protected StoryboardContainer StoryboardContainer { get; private set; } - protected virtual UserDimContainer CreateStoryboardContainer() => new UserDimContainer(true) + protected virtual StoryboardContainer CreateStoryboardContainer(Storyboard storyboard) => new StoryboardContainer(storyboard) { RelativeSizeAxes = Axes.Both, Alpha = 1, EnableUserDim = { Value = true } }; - private Bindable showStoryboard; - - private void initializeStoryboard(bool asyncLoad) - { - if (StoryboardContainer == null || storyboard != null) - return; - - if (!showStoryboard.Value) - return; - - var beatmap = Beatmap.Value; - - storyboard = beatmap.Storyboard.CreateDrawable(); - storyboard.Masking = true; - - if (asyncLoad) - LoadComponentAsync(storyboard, c => - { - // Since the storyboard was loaded before it can be added to the draw hierarchy, manually set the clock for it here. - c.Clock = GameplayClockContainer.GameplayClock; - StoryboardContainer.Add(c); - }); - else - StoryboardContainer.Add(storyboard); - } - #endregion #region Fail Logic @@ -491,8 +461,6 @@ namespace osu.Game.Screens.Play .Delay(250) .FadeIn(250); - showStoryboard.ValueChanged += _ => initializeStoryboard(true); - Background.EnableUserDim.Value = true; Background.BlurAmount.Value = 0; From 1b5fadf93f468ea0c6894cba50e80f03797d48f0 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 9 Jul 2019 16:38:12 +0900 Subject: [PATCH 1810/5608] move comment to more relevant location --- osu.Game/Graphics/Containers/UserDimContainer.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index b14051f432..89c1821425 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -59,10 +59,6 @@ namespace osu.Game.Graphics.Containers /// /// Creates a new . /// - /// - /// While both backgrounds and storyboards allow user dim levels to be applied, storyboards can be toggled via - /// and can cause backgrounds to become hidden via . Storyboards are also currently unable to be blurred. - /// public UserDimContainer() { AddInternal(DimContainer = new Container { RelativeSizeAxes = Axes.Both }); @@ -112,6 +108,10 @@ namespace osu.Game.Graphics.Containers /// /// Apply non-dim related settings to the background, such as hiding and blurring. /// + /// + /// While both backgrounds and storyboards allow user dim levels to be applied, storyboards can be toggled via + /// and can cause backgrounds to become hidden via . Storyboards are also currently unable to be blurred. + /// protected virtual void ApplyFade() { // The background needs to be hidden in the case of it being replaced by the storyboard From 5bb21ecae0aa027c80ef2108ac3a1991495ed6f3 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 9 Jul 2019 16:50:37 +0900 Subject: [PATCH 1811/5608] remove storyboard region --- .../Containers/StoryboardContainer.cs | 2 +- .../Graphics/Containers/UserDimContainer.cs | 2 +- osu.Game/Screens/Play/Player.cs | 22 ++++++++----------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/osu.Game/Graphics/Containers/StoryboardContainer.cs b/osu.Game/Graphics/Containers/StoryboardContainer.cs index c425d38d48..472e22e212 100644 --- a/osu.Game/Graphics/Containers/StoryboardContainer.cs +++ b/osu.Game/Graphics/Containers/StoryboardContainer.cs @@ -35,7 +35,7 @@ namespace osu.Game.Graphics.Containers protected override void ApplyFade() { - // Storyboards cannot be blurred, so we should just hide the storyboard if it gets toggled. + // Storyboards cannot be blurred, so just hide the storyboard if it gets toggled. DimContainer.FadeTo(!ShowStoryboard.Value || UserDimLevel.Value == 1 ? 0 : 1, BACKGROUND_FADE_DURATION, Easing.OutQuint); } diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 89c1821425..ad6f73eff5 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -106,7 +106,7 @@ namespace osu.Game.Graphics.Containers } /// - /// Apply non-dim related settings to the background, such as hiding and blurring. + /// Apply non-dim related settings to the content, such as hiding and blurring. /// /// /// While both backgrounds and storyboards allow user dim levels to be applied, storyboards can be toggled via diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 621df0b562..d9e050a681 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -76,6 +76,15 @@ namespace osu.Game.Screens.Play protected GameplayClockContainer GameplayClockContainer { get; private set; } + protected StoryboardContainer StoryboardContainer { get; private set; } + + protected virtual StoryboardContainer CreateStoryboardContainer(Storyboard storyboard) => new StoryboardContainer(storyboard) + { + RelativeSizeAxes = Axes.Both, + Alpha = 1, + EnableUserDim = { Value = true } + }; + [Cached] [Cached(Type = typeof(IBindable>))] protected new readonly Bindable> Mods = new Bindable>(Array.Empty()); @@ -331,19 +340,6 @@ namespace osu.Game.Screens.Play protected virtual Results CreateResults(ScoreInfo score) => new SoloResults(score); - #region Storyboard - - protected StoryboardContainer StoryboardContainer { get; private set; } - - protected virtual StoryboardContainer CreateStoryboardContainer(Storyboard storyboard) => new StoryboardContainer(storyboard) - { - RelativeSizeAxes = Axes.Both, - Alpha = 1, - EnableUserDim = { Value = true } - }; - - #endregion - #region Fail Logic protected FailOverlay FailOverlay { get; private set; } From 8d6af1625abda2a84879c508419e116c57448e75 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 9 Jul 2019 11:40:51 +0300 Subject: [PATCH 1812/5608] Visibility improvements --- .../Visual/Online/TestSceneScoresContainer.cs | 1 + .../BeatmapSet/Scores/ScoresContainer.cs | 142 ++++++++++++++---- osu.Game/Overlays/BeatmapSetOverlay.cs | 6 +- 3 files changed, 118 insertions(+), 31 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index 827a300a5e..c414b6b940 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -243,6 +243,7 @@ namespace osu.Game.Tests.Visual.Online allScores.UserScore = myBestScore; scoresContainer.Scores = allScores; }); + AddStep("Trigger loading", () => scoresContainer.Loading = !scoresContainer.Loading); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 7e0f3d0b1c..eacbe6200a 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -17,13 +17,14 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public class ScoresContainer : CompositeDrawable { private const int spacing = 15; - private const int fade_duration = 200; + private const int padding = 20; private readonly Box background; private readonly ScoreTable scoreTable; private readonly FillFlowContainer topScoresContainer; - private readonly LoadingAnimation loadingAnimation; + private readonly ContentContainer resizableContainer; + private readonly LoadingContainer loadingContainer; public ScoresContainer() { @@ -38,53 +39,85 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }, new FillFlowContainer { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Width = 0.95f, Direction = FillDirection.Vertical, - Spacing = new Vector2(0, spacing), - Margin = new MarginPadding { Vertical = spacing }, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, Children = new Drawable[] { - topScoresContainer = new FillFlowContainer + loadingContainer = new LoadingContainer { RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), + Masking = true, }, - scoreTable = new ScoreTable + resizableContainer = new ContentContainer { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - } + RelativeSizeAxes = Axes.X, + Masking = true, + Children = new Drawable[] + { + new FillFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Width = 0.95f, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, spacing), + Padding = new MarginPadding { Vertical = padding }, + Children = new Drawable[] + { + topScoresContainer = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + }, + scoreTable = new ScoreTable + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + } + } + }, + } + }, } - }, - loadingAnimation = new LoadingAnimation - { - Alpha = 0, - Margin = new MarginPadding(20), - }, + } }; + + Loading = true; } [BackgroundDependencyLoader] private void load(OsuColour colours) { background.Colour = colours.Gray2; - updateDisplay(); } + private bool loading; + public bool Loading { + get => loading; set { - loadingAnimation.FadeTo(value ? 1 : 0, fade_duration); + if (loading == value) + return; + + loading = value; if (value) - Scores = null; + { + loadingContainer.Show(); + resizableContainer.Hide(); + } + else + { + loadingContainer.Hide(); + resizableContainer.Show(); + } } } @@ -117,6 +150,63 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (userScore != null && userScore.Position != 1) topScoresContainer.Add(new DrawableTopScore(userScore.Score, userScore.Position)); } + + Loading = false; + } + + private class ContentContainer : VisibilityContainer + { + private const int duration = 300; + + private float maxHeight; + + protected override void PopIn() => this.ResizeHeightTo(maxHeight, duration, Easing.OutQuint); + + protected override void PopOut() => this.ResizeHeightTo(0, duration, Easing.OutQuint); + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + if (State.Value == Visibility.Hidden) + return; + + float height = 0; + + foreach (var c in Children) + { + height += c.Height; + } + + maxHeight = height; + + this.ResizeHeightTo(maxHeight, duration, Easing.OutQuint); + } + } + + private class LoadingContainer : VisibilityContainer + { + private const int duration = 300; + private const int height = 50; + + private readonly LoadingAnimation loadingAnimation; + + public LoadingContainer() + { + Child = loadingAnimation = new LoadingAnimation(); + } + + protected override void PopIn() + { + this.ResizeHeightTo(height, duration, Easing.OutQuint); + loadingAnimation.Show(); + } + + protected override void PopOut() + { + this.ResizeHeightTo(0, duration, Easing.OutQuint); + loadingAnimation.Hide(); + } } } } diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 44475dc53c..1c408ead54 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -98,11 +98,7 @@ namespace osu.Game.Overlays scores.Loading = true; getScoresRequest = new GetScoresRequest(b, b.Ruleset); - getScoresRequest.Success += r => Schedule(() => - { - scores.Scores = r; - scores.Loading = false; - }); + getScoresRequest.Success += r => Schedule(() => scores.Scores = r); api.Queue(getScoresRequest); } From 0580c322639e62dc155ed969deb7c7f1a97fda94 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 9 Jul 2019 17:59:40 +0900 Subject: [PATCH 1813/5608] Abstract intro screen logic to base class --- osu.Desktop/OsuGameDesktop.cs | 2 +- osu.Game.Tests/Visual/Menus/TestSceneIntro.cs | 7 +- osu.Game/OsuGame.cs | 7 +- .../Menu/{Intro.cs => IntroCircles.cs} | 94 ++------------- osu.Game/Screens/Menu/IntroScreen.cs | 114 ++++++++++++++++++ osu.Game/Screens/Menu/MainMenu.cs | 2 +- 6 files changed, 136 insertions(+), 90 deletions(-) rename osu.Game/Screens/Menu/{Intro.cs => IntroCircles.cs} (52%) create mode 100644 osu.Game/Screens/Menu/IntroScreen.cs diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 975b7f9f5a..18f0cd1f80 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -71,7 +71,7 @@ namespace osu.Desktop switch (newScreen) { - case Intro _: + case IntroScreen _: case MainMenu _: versionManager?.Show(); break; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntro.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntro.cs index 15b5c2338e..8b993f618f 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntro.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntro.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Timing; using osu.Game.Screens; using osu.Game.Screens.Menu; +using osuTK; using osuTK.Graphics; namespace osu.Game.Tests.Visual.Menus @@ -45,13 +46,15 @@ namespace osu.Game.Tests.Visual.Menus RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, - new OsuScreenStack(new Intro()) + new OsuScreenStack(new IntroCircles()) { RelativeSizeAxes = Axes.Both, }, logo = new OsuLogo { - Anchor = Anchor.Centre, + Alpha = 0, + RelativePositionAxes = Axes.Both, + Position = new Vector2(0.5f), }, } }); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 361ff62155..1ca4527786 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -86,7 +86,8 @@ namespace osu.Game private BackButton backButton; private MainMenu menuScreen; - private Intro introScreen; + + private IntroScreen introScreen; private Bindable configRuleset; @@ -760,7 +761,7 @@ namespace osu.Game if (introScreen == null) return true; - if (!introScreen.DidLoadMenu || !(screenStack.CurrentScreen is Intro)) + if (!introScreen.DidLoadMenu || !(screenStack.CurrentScreen is IntroScreen)) { Scheduler.Add(introScreen.MakeCurrent); return true; @@ -795,7 +796,7 @@ namespace osu.Game { switch (newScreen) { - case Intro intro: + case IntroScreen intro: introScreen = intro; break; diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/IntroCircles.cs similarity index 52% rename from osu.Game/Screens/Menu/Intro.cs rename to osu.Game/Screens/Menu/IntroCircles.cs index 3fb16eaf90..4fa1a81123 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/IntroCircles.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; using osu.Framework.Bindables; @@ -12,41 +11,24 @@ using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.IO.Archives; -using osu.Game.Screens.Backgrounds; -using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.Menu { - public class Intro : StartupScreen + public class IntroCircles : IntroScreen { private const string menu_music_beatmap_hash = "3c8b1fcc9434dbb29e2fb613d3b9eada9d7bb6c125ceb32396c3b53437280c83"; - /// - /// Whether we have loaded the menu previously. - /// - public bool DidLoadMenu; - - private MainMenu mainMenu; private SampleChannel welcome; - private SampleChannel seeya; - protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack(); - - private readonly BindableDouble exitingVolumeFade = new BindableDouble(1); - - [Resolved] - private AudioManager audio { get; set; } - - private Bindable menuVoice; private Bindable menuMusic; + private Track track; + private WorkingBeatmap introBeatmap; [BackgroundDependencyLoader] - private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game) + private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game, ISampleStore samples) { - menuVoice = config.GetBindable(OsuSetting.MenuVoice); menuMusic = config.GetBindable(OsuSetting.MenuMusic); BeatmapSetInfo setInfo = null; @@ -75,15 +57,13 @@ namespace osu.Game.Screens.Menu introBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); track = introBeatmap.Track; - welcome = audio.Samples.Get(@"welcome"); - seeya = audio.Samples.Get(@"seeya"); + if (config.Get(OsuSetting.MenuVoice)) + welcome = samples.Get(@"welcome"); } private const double delay_step_one = 2300; private const double delay_step_two = 600; - public const int EXIT_DELAY = 3000; - protected override void LogoArriving(OsuLogo logo, bool resuming) { base.LogoArriving(logo, resuming); @@ -93,8 +73,7 @@ namespace osu.Game.Screens.Menu Beatmap.Value = introBeatmap; introBeatmap = null; - if (menuVoice.Value) - welcome.Play(); + welcome?.Play(); Scheduler.AddDelayed(delegate { @@ -105,74 +84,23 @@ namespace osu.Game.Screens.Menu track = null; } - LoadComponentAsync(mainMenu = new MainMenu()); + PrepareMenuLoad(); - Scheduler.AddDelayed(delegate - { - DidLoadMenu = true; - this.Push(mainMenu); - }, delay_step_one); + Scheduler.AddDelayed(LoadMenu, delay_step_one); }, delay_step_two); - } - logo.Colour = Color4.White; - logo.Ripple = false; - - const int quick_appear = 350; - - int initialMovementTime = logo.Alpha > 0.2f ? quick_appear : 0; - - logo.MoveTo(new Vector2(0.5f), initialMovementTime, Easing.OutQuint); - - if (!resuming) - { logo.ScaleTo(1); logo.FadeIn(); logo.PlayIntro(); } - else - { - logo.Triangles = false; - - logo - .ScaleTo(1, initialMovementTime, Easing.OutQuint) - .FadeIn(quick_appear, Easing.OutQuint) - .Then() - .RotateTo(20, EXIT_DELAY * 1.5f) - .FadeOut(EXIT_DELAY); - } } public override void OnSuspending(IScreen next) { + track = null; + this.FadeOut(300); base.OnSuspending(next); } - - public override bool OnExiting(IScreen next) - { - //cancel exiting if we haven't loaded the menu yet. - return !DidLoadMenu; - } - - public override void OnResuming(IScreen last) - { - this.FadeIn(300); - - double fadeOutTime = EXIT_DELAY; - //we also handle the exit transition. - if (menuVoice.Value) - seeya.Play(); - else - fadeOutTime = 500; - - audio.AddAdjustment(AdjustableProperty.Volume, exitingVolumeFade); - this.TransformBindableTo(exitingVolumeFade, 0, fadeOutTime).OnComplete(_ => this.Exit()); - - //don't want to fade out completely else we will stop running updates. - Game.FadeTo(0.01f, fadeOutTime); - - base.OnResuming(last); - } } } diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs new file mode 100644 index 0000000000..27f3c9a45b --- /dev/null +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -0,0 +1,114 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Screens; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Screens.Backgrounds; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Menu +{ + public abstract class IntroScreen : StartupScreen + { + private readonly BindableDouble exitingVolumeFade = new BindableDouble(1); + + public const int EXIT_DELAY = 3000; + + [Resolved] + private AudioManager audio { get; set; } + + private SampleChannel seeya; + + private Bindable menuVoice; + + protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack(); + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game) + { + menuVoice = config.GetBindable(OsuSetting.MenuVoice); + seeya = audio.Samples.Get(@"seeya"); + } + + /// + /// Whether we have loaded the menu previously. + /// + public bool DidLoadMenu { get; private set; } + + public override bool OnExiting(IScreen next) + { + //cancel exiting if we haven't loaded the menu yet. + return !DidLoadMenu; + } + + public override void OnResuming(IScreen last) + { + this.FadeIn(300); + + double fadeOutTime = EXIT_DELAY; + //we also handle the exit transition. + if (menuVoice.Value) + seeya.Play(); + else + fadeOutTime = 500; + + audio.AddAdjustment(AdjustableProperty.Volume, exitingVolumeFade); + this.TransformBindableTo(exitingVolumeFade, 0, fadeOutTime).OnComplete(_ => this.Exit()); + + //don't want to fade out completely else we will stop running updates. + Game.FadeTo(0.01f, fadeOutTime); + + base.OnResuming(last); + } + + protected override void LogoArriving(OsuLogo logo, bool resuming) + { + base.LogoArriving(logo, resuming); + + logo.Colour = Color4.White; + logo.Triangles = false; + logo.Ripple = false; + + if (!resuming) + { + logo.MoveTo(new Vector2(0.5f)); + logo.ScaleTo(Vector2.One); + logo.Hide(); + } + else + { + const int quick_appear = 350; + int initialMovementTime = logo.Alpha > 0.2f ? quick_appear : 0; + + logo.MoveTo(new Vector2(0.5f), initialMovementTime, Easing.OutQuint); + + logo + .ScaleTo(1, initialMovementTime, Easing.OutQuint) + .FadeIn(quick_appear, Easing.OutQuint) + .Then() + .RotateTo(20, EXIT_DELAY * 1.5f) + .FadeOut(EXIT_DELAY); + } + } + + private MainMenu mainMenu; + + protected void PrepareMenuLoad() + { + LoadComponentAsync(mainMenu = new MainMenu()); + } + + protected void LoadMenu() + { + DidLoadMenu = true; + this.Push(mainMenu); + } + } +} diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index c64bea840f..f73de6f730 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -120,7 +120,7 @@ namespace osu.Game.Screens.Menu var track = Beatmap.Value.Track; var metadata = Beatmap.Value.Metadata; - if (last is Intro && track != null) + if (last is IntroScreen && track != null) { if (!track.IsRunning) { From e835cd0f6f498cd3db205c31d16f6a1ba0343924 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 9 Jul 2019 18:06:49 +0900 Subject: [PATCH 1814/5608] Improve information flow to Disclaimer --- osu.Game/Screens/Loader.cs | 10 +++++++++- osu.Game/Screens/Menu/Disclaimer.cs | 11 +++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index 8add730c4e..de00ba2e9f 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -45,7 +45,15 @@ namespace osu.Game.Screens private OsuScreen loadableScreen; private ShaderPrecompiler precompiler; - protected virtual OsuScreen CreateLoadableScreen() => showDisclaimer ? (OsuScreen)new Disclaimer() : new Intro(); + protected virtual OsuScreen CreateLoadableScreen() + { + if (showDisclaimer) + return new Disclaimer(getIntroSequence()); + + return getIntroSequence(); + } + + private IntroScreen getIntroSequence() => new IntroCircles(); protected virtual ShaderPrecompiler CreateShaderPrecompiler() => new ShaderPrecompiler(); diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index 97231a1331..073ab639e3 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -21,7 +21,6 @@ namespace osu.Game.Screens.Menu { public class Disclaimer : StartupScreen { - private Intro intro; private SpriteIcon icon; private Color4 iconColour; private LinkFlowContainer textFlow; @@ -32,10 +31,13 @@ namespace osu.Game.Screens.Menu private const float icon_y = -85; private const float icon_size = 30; + private readonly OsuScreen nextScreen; + private readonly Bindable currentUser = new Bindable(); - public Disclaimer() + public Disclaimer(OsuScreen nextScreen = null) { + this.nextScreen = nextScreen; ValidForResume = false; } @@ -146,7 +148,8 @@ namespace osu.Game.Screens.Menu protected override void LoadComplete() { base.LoadComplete(); - LoadComponentAsync(intro = new Intro()); + if (nextScreen != null) + LoadComponentAsync(nextScreen); } public override void OnEntering(IScreen last) @@ -170,7 +173,7 @@ namespace osu.Game.Screens.Menu .Then(5500) .FadeOut(250) .ScaleTo(0.9f, 250, Easing.InQuint) - .Finally(d => this.Push(intro)); + .Finally(d => this.Push(nextScreen)); } } } From e8b9b1b0bfe52812948b27b6fbaf834699f27ef3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 9 Jul 2019 12:16:58 +0300 Subject: [PATCH 1815/5608] visibility logic adjustments --- .../Visual/Online/TestSceneScoresContainer.cs | 15 ++--- .../BeatmapSet/Scores/ScoresContainer.cs | 67 ++++++++----------- 2 files changed, 35 insertions(+), 47 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index c414b6b940..10207ea192 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -3,12 +3,10 @@ using System; using System.Collections.Generic; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; -using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Rulesets.Mods; @@ -16,6 +14,7 @@ using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Users; +using osuTK.Graphics; namespace osu.Game.Tests.Visual.Online { @@ -44,7 +43,11 @@ namespace osu.Game.Tests.Visual.Online Width = 0.8f, Children = new Drawable[] { - background = new Box { RelativeSizeAxes = Axes.Both }, + background = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, scoresContainer = new ScoresContainer(), } }; @@ -245,11 +248,5 @@ namespace osu.Game.Tests.Visual.Online }); AddStep("Trigger loading", () => scoresContainer.Loading = !scoresContainer.Loading); } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = colours.Gray2; - } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index eacbe6200a..63e18f3da7 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly ScoreTable scoreTable; private readonly FillFlowContainer topScoresContainer; - private readonly ContentContainer resizableContainer; + private readonly ContentContainer contentContainer; private readonly LoadingContainer loadingContainer; public ScoresContainer() @@ -49,36 +49,33 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativeSizeAxes = Axes.X, Masking = true, }, - resizableContainer = new ContentContainer + contentContainer = new ContentContainer { RelativeSizeAxes = Axes.X, Masking = true, - Children = new Drawable[] + Child = new FillFlowContainer { - new FillFlowContainer + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Width = 0.95f, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, spacing), + Padding = new MarginPadding { Vertical = padding }, + Children = new Drawable[] { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Width = 0.95f, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, spacing), - Padding = new MarginPadding { Vertical = padding }, - Children = new Drawable[] + topScoresContainer = new FillFlowContainer { - topScoresContainer = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), - }, - scoreTable = new ScoreTable - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - } + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + }, + scoreTable = new ScoreTable + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, } }, } @@ -103,20 +100,21 @@ namespace osu.Game.Overlays.BeatmapSet.Scores get => loading; set { - if (loading == value) - return; - loading = value; if (value) { loadingContainer.Show(); - resizableContainer.Hide(); + contentContainer.Hide(); } else { loadingContainer.Hide(); - resizableContainer.Show(); + + if (scores == null || scores?.Scores.Count < 1) + contentContainer.Hide(); + else + contentContainer.Show(); } } } @@ -171,14 +169,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (State.Value == Visibility.Hidden) return; - float height = 0; - - foreach (var c in Children) - { - height += c.Height; - } - - maxHeight = height; + maxHeight = Child.DrawHeight; this.ResizeHeightTo(maxHeight, duration, Easing.OutQuint); } From e3e72a627607751a84560077586ecdb80cfd1fee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 9 Jul 2019 18:15:31 +0900 Subject: [PATCH 1816/5608] Reorganise tests and add restart step --- osu.Game.Tests/Visual/Menus/IntroTestScene.cs | 66 +++++++++++++++++++ osu.Game.Tests/Visual/Menus/TestSceneIntro.cs | 65 ------------------ .../Visual/Menus/TestSceneIntroCircles.cs | 15 +++++ 3 files changed, 81 insertions(+), 65 deletions(-) create mode 100644 osu.Game.Tests/Visual/Menus/IntroTestScene.cs delete mode 100644 osu.Game.Tests/Visual/Menus/TestSceneIntro.cs create mode 100644 osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs diff --git a/osu.Game.Tests/Visual/Menus/IntroTestScene.cs b/osu.Game.Tests/Visual/Menus/IntroTestScene.cs new file mode 100644 index 0000000000..0d78a43cf6 --- /dev/null +++ b/osu.Game.Tests/Visual/Menus/IntroTestScene.cs @@ -0,0 +1,66 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Screens; +using osu.Game.Screens; +using osu.Game.Screens.Menu; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Menus +{ + [TestFixture] + public abstract class IntroTestScene : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuLogo), + typeof(StartupScreen), + typeof(IntroScreen), + typeof(OsuScreen), + typeof(IntroTestScene), + }; + + [Cached] + private OsuLogo logo; + + protected IntroTestScene() + { + Drawable introStack = null; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Depth = float.MaxValue, + Colour = Color4.Black, + }, + logo = new OsuLogo + { + Alpha = 0, + RelativePositionAxes = Axes.Both, + Depth = float.MinValue, + Position = new Vector2(0.5f), + } + }; + + AddStep("restart sequence", () => + { + introStack?.Expire(); + Add(introStack = new OsuScreenStack(CreateScreen()) + { + RelativeSizeAxes = Axes.Both, + }); + }); + } + + protected abstract IScreen CreateScreen(); + } +} diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntro.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntro.cs deleted file mode 100644 index 8b993f618f..0000000000 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntro.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Timing; -using osu.Game.Screens; -using osu.Game.Screens.Menu; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Tests.Visual.Menus -{ - [TestFixture] - public class TestSceneIntro : OsuTestScene - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(OsuLogo), - typeof(StartupScreen), - typeof(OsuScreen) - }; - - [Cached] - private OsuLogo logo; - - public TestSceneIntro() - { - var rateAdjustClock = new StopwatchClock(true); - var framedClock = new FramedClock(rateAdjustClock); - framedClock.ProcessFrame(); - - Add(new Container - { - RelativeSizeAxes = Axes.Both, - Clock = framedClock, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - new OsuScreenStack(new IntroCircles()) - { - RelativeSizeAxes = Axes.Both, - }, - logo = new OsuLogo - { - Alpha = 0, - RelativePositionAxes = Axes.Both, - Position = new Vector2(0.5f), - }, - } - }); - - AddSliderStep("Playback speed", 0.0, 2.0, 1, v => rateAdjustClock.Rate = v); - } - } -} diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs new file mode 100644 index 0000000000..107734cc8d --- /dev/null +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.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 NUnit.Framework; +using osu.Framework.Screens; +using osu.Game.Screens.Menu; + +namespace osu.Game.Tests.Visual.Menus +{ + [TestFixture] + public class TestSceneIntroCircles : IntroTestScene + { + protected override IScreen CreateScreen() => new IntroCircles(); + } +} From 276873ff8ada90e18a9fde2b8f6e2641828c2e17 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 9 Jul 2019 12:28:59 +0300 Subject: [PATCH 1817/5608] remove unused field --- osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index 10207ea192..4ce689ce6b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -29,8 +29,6 @@ namespace osu.Game.Tests.Visual.Online typeof(ScoreTableRowBackground), }; - private readonly Box background; - public TestSceneScoresContainer() { ScoresContainer scoresContainer; @@ -43,7 +41,7 @@ namespace osu.Game.Tests.Visual.Online Width = 0.8f, Children = new Drawable[] { - background = new Box + new Box { RelativeSizeAxes = Axes.Both, Colour = Color4.Black, From 2546f647be43d3e44477fa962a22f6dcd768e510 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Tue, 9 Jul 2019 11:32:49 +0200 Subject: [PATCH 1818/5608] Completely change the way we fix the bug --- osu.Game/OsuGame.cs | 6 +++--- osu.Game/Overlays/MusicController.cs | 4 ++-- osu.Game/Screens/Menu/MainMenu.cs | 18 ++++++++---------- osu.Game/Screens/OsuScreen.cs | 11 +---------- osu.Game/Screens/Select/SongSelect.cs | 7 ++++--- 5 files changed, 18 insertions(+), 28 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 325d2cbd85..0a472d4dc1 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -306,7 +306,7 @@ namespace osu.Game private void currentTrackCompleted() { if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled) - MusicController.NextTrack(); + musicController.NextTrack(); } #endregion @@ -484,7 +484,7 @@ namespace osu.Game Origin = Anchor.TopRight, }, rightFloatingOverlayContent.Add, true); - loadComponentSingleFile(MusicController = new MusicController + loadComponentSingleFile(musicController = new MusicController { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, @@ -752,7 +752,7 @@ namespace osu.Game private ScalingContainer screenContainer; - public MusicController MusicController { get; private set; } + private MusicController musicController; protected override bool OnExiting() { diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 3db71d39ee..ad0c0717ac 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -55,6 +55,8 @@ namespace osu.Game.Overlays private Container dragContainer; private Container playerContainer; + public bool UserRequestedPause { get; private set; } + [Resolved] private Bindable beatmap { get; set; } @@ -66,8 +68,6 @@ namespace osu.Game.Overlays /// public Func GetToolbarHeight; - public bool UserRequestedPause { get; private set; } - public MusicController() { Width = 400; diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index dcce49179d..078f9c5a15 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -42,6 +42,9 @@ namespace osu.Game.Screens.Menu [Resolved] private GameHost host { get; set; } + [Resolved] + private MusicController musicController { get; set; } + private BackgroundScreenDefault background; protected override BackgroundScreen CreateBackground() => background; @@ -120,15 +123,6 @@ namespace osu.Game.Screens.Menu var track = Beatmap.Value.Track; var metadata = Beatmap.Value.Metadata; - if (last is Intro && track != null && !Game.MusicController.UserRequestedPause) - { - if (!track.IsRunning) - { - track.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * track.Length); - track.Start(); - } - } - Beatmap.ValueChanged += beatmap_ValueChanged; } @@ -190,7 +184,11 @@ namespace osu.Game.Screens.Menu //we may have consumed our preloaded instance, so let's make another. preloadSongSelect(); - ResumeIfNoUserPauseRequested(); + if (Beatmap.Value.Track != null && !musicController.UserRequestedPause) + { + Beatmap.Value.Track.Tempo.Value = 1; + Beatmap.Value.Track.Start(); + } } public override bool OnExiting(IScreen next) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 0682710133..328631ff9c 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens public virtual bool CursorVisible => true; - protected new OsuGame Game => base.Game as OsuGame; + protected new OsuGameBase Game => base.Game as OsuGameBase; /// /// The to set the user's activity automatically to when this screen is entered @@ -179,15 +179,6 @@ namespace osu.Game.Screens api.Activity.Value = activity; } - protected void ResumeIfNoUserPauseRequested() - { - if (Beatmap.Value.Track != null && !Game.MusicController.UserRequestedPause) - { - Beatmap.Value.Track.Tempo.Value = 1; - Beatmap.Value.Track.Start(); - } - } - /// /// Fired when this screen was entered or resumed and the logo state is required to be adjusted. /// diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 17b2ae376f..dd115e04d4 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -87,6 +87,9 @@ namespace osu.Game.Screens.Select private readonly Bindable decoupledRuleset = new Bindable(); + [Resolved] + private MusicController musicController { get; set; } + [Cached] [Cached(Type = typeof(IBindable>))] private readonly Bindable> mods = new Bindable>(Array.Empty()); // Bound to the game's mods, but is not reset on exiting @@ -426,8 +429,6 @@ namespace osu.Game.Screens.Select { base.OnEntering(last); - ResumeIfNoUserPauseRequested(); - this.FadeInFromZero(250); FilterControl.Activate(); } @@ -572,7 +573,7 @@ namespace osu.Game.Screens.Select { Track track = Beatmap.Value.Track; - if (!track.IsRunning || restart) + if ((!track.IsRunning || restart) && !musicController.UserRequestedPause) { track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; track.Restart(); From 8eeba069cc06fdced468da0e8184e834914f6cc3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 9 Jul 2019 18:51:10 +0900 Subject: [PATCH 1819/5608] Ensure logo isn't left in a bad state on re-run --- osu.Game.Tests/Visual/Menus/IntroTestScene.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Menus/IntroTestScene.cs b/osu.Game.Tests/Visual/Menus/IntroTestScene.cs index 0d78a43cf6..e8addf59ed 100644 --- a/osu.Game.Tests/Visual/Menus/IntroTestScene.cs +++ b/osu.Game.Tests/Visual/Menus/IntroTestScene.cs @@ -53,7 +53,9 @@ namespace osu.Game.Tests.Visual.Menus AddStep("restart sequence", () => { + logo.FinishTransforms(); introStack?.Expire(); + Add(introStack = new OsuScreenStack(CreateScreen()) { RelativeSizeAxes = Axes.Both, From 2d0e6652f90e645538f9b1a87d20d8641e96fece Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 9 Jul 2019 18:59:56 +0900 Subject: [PATCH 1820/5608] Ensure logo doesn't get stuck tracking --- osu.Game.Tests/Visual/Menus/IntroTestScene.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Menus/IntroTestScene.cs b/osu.Game.Tests/Visual/Menus/IntroTestScene.cs index e8addf59ed..aa27ed48df 100644 --- a/osu.Game.Tests/Visual/Menus/IntroTestScene.cs +++ b/osu.Game.Tests/Visual/Menus/IntroTestScene.cs @@ -54,6 +54,8 @@ namespace osu.Game.Tests.Visual.Menus AddStep("restart sequence", () => { logo.FinishTransforms(); + logo.IsTracking = false; + introStack?.Expire(); Add(introStack = new OsuScreenStack(CreateScreen()) From a0d048ad8ddca7cda23f6a8ab023c0a28c87952f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 9 Jul 2019 19:31:53 +0900 Subject: [PATCH 1821/5608] Don't test the logo Breaks main menu adding --- osu.Game.Tests/Visual/Menus/IntroTestScene.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Menus/IntroTestScene.cs b/osu.Game.Tests/Visual/Menus/IntroTestScene.cs index aa27ed48df..d03d341ee4 100644 --- a/osu.Game.Tests/Visual/Menus/IntroTestScene.cs +++ b/osu.Game.Tests/Visual/Menus/IntroTestScene.cs @@ -20,7 +20,6 @@ namespace osu.Game.Tests.Visual.Menus { public override IReadOnlyList RequiredTypes => new[] { - typeof(OsuLogo), typeof(StartupScreen), typeof(IntroScreen), typeof(OsuScreen), From 3472979d0b4d9d2d652ded1a3b9f9c56e2642e1f Mon Sep 17 00:00:00 2001 From: Oskar Solecki <31374466+Desconocidosmh@users.noreply.github.com> Date: Tue, 9 Jul 2019 12:53:40 +0200 Subject: [PATCH 1822/5608] Make sure exiting editor doesn't unpause the music --- osu.Game/Screens/Edit/Editor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 676e060433..8b3cf1ec90 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -238,7 +238,7 @@ namespace osu.Game.Screens.Edit public override bool OnExiting(IScreen next) { Background.FadeColour(Color4.White, 500); - + Beatmap.Value.Track?.Stop(); return base.OnExiting(next); } From 2472c6b4b121d788c5ef835e5156eb179d582f8e Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Tue, 9 Jul 2019 21:07:29 +0930 Subject: [PATCH 1823/5608] Fix iOS visual tests not supporting raw keyboard handler --- osu.Game.Rulesets.Catch.Tests.iOS/Application.cs | 2 +- osu.Game.Rulesets.Mania.Tests.iOS/Application.cs | 2 +- osu.Game.Rulesets.Osu.Tests.iOS/Application.cs | 2 +- osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs | 2 +- osu.Game.Tests.iOS/Application.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs index 44817c1304..beca477943 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Catch.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, null, "AppDelegate"); + UIApplication.Main(args, "GameUIApplication", "AppDelegate"); } } } diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs index d47ac4643f..0362402320 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Mania.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, null, "AppDelegate"); + UIApplication.Main(args, "GameUIApplication", "AppDelegate"); } } } diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs index 7a0797a909..3718264a42 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Osu.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, null, "AppDelegate"); + UIApplication.Main(args, "GameUIApplication", "AppDelegate"); } } } diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs index 6613e9e2b4..330cb42901 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, null, "AppDelegate"); + UIApplication.Main(args, "GameUIApplication", "AppDelegate"); } } } diff --git a/osu.Game.Tests.iOS/Application.cs b/osu.Game.Tests.iOS/Application.cs index a23fe4e129..d96a3e27a4 100644 --- a/osu.Game.Tests.iOS/Application.cs +++ b/osu.Game.Tests.iOS/Application.cs @@ -9,7 +9,7 @@ namespace osu.Game.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, null, "AppDelegate"); + UIApplication.Main(args, "GameUIApplication", "AppDelegate"); } } } From e0c1fb78181571b926f12e84e4f6a508861191ad Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 9 Jul 2019 14:47:54 +0300 Subject: [PATCH 1824/5608] Compare by milliseconds for length --- osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 490012da61..c38b13cfca 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -49,11 +49,7 @@ namespace osu.Game.Screens.Select.Carousel return Beatmap.StarDifficulty.CompareTo(otherBeatmap.Beatmap.StarDifficulty); case SortMode.Length: - // Length comparing must be in seconds - if (TimeSpan.FromMilliseconds(Beatmap.Length).Seconds != TimeSpan.FromMilliseconds(otherBeatmap.Beatmap.Length).Seconds) - return Beatmap.Length.CompareTo(otherBeatmap.Beatmap.Length); - - goto case SortMode.Difficulty; + return Beatmap.Length.CompareTo(otherBeatmap.Beatmap.Length); } } From 38bc652bf2b8b740fcf1008dcb67759f93fccc52 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 9 Jul 2019 17:02:51 +0300 Subject: [PATCH 1825/5608] Remove sorting by length for beatmaps --- osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index c38b13cfca..712ab7b571 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -47,9 +47,6 @@ namespace osu.Game.Screens.Select.Carousel if (ruleset != 0) return ruleset; return Beatmap.StarDifficulty.CompareTo(otherBeatmap.Beatmap.StarDifficulty); - - case SortMode.Length: - return Beatmap.Length.CompareTo(otherBeatmap.Beatmap.Length); } } From f3329f4d792dc97f064f5ab0f0e51384b9ae795c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 9 Jul 2019 17:22:21 +0300 Subject: [PATCH 1826/5608] Use a more readable code for calculating length --- osu.Game/Beatmaps/BeatmapManager.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 6fe70b6ec6..4f67139706 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -315,10 +315,15 @@ namespace osu.Game.Beatmaps private double calculateLength(IBeatmap b) { - var lastObject = b.HitObjects.LastOrDefault(); - var endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0; + if (!b.HitObjects.Any()) + return 0; - return endTime - b.HitObjects.FirstOrDefault()?.StartTime ?? 0; + var lastObject = b.HitObjects.Last(); + + double endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime; + double startTime = b.HitObjects.First().StartTime; + + return endTime - startTime; } /// From 1485c273ab1f3b36f7357823db220536e79c4a6b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 9 Jul 2019 17:31:15 +0300 Subject: [PATCH 1827/5608] Describe the xmldoc mo --- osu.Game/Beatmaps/BeatmapInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index fa1282647e..8042f6b4b9 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -52,7 +52,7 @@ namespace osu.Game.Beatmaps public BeatmapOnlineInfo OnlineInfo { get; set; } /// - /// The playable length of this beatmap. + /// The playable length in milliseconds of this beatmap. /// public double Length { get; set; } From 9907a58ec4aaf3427769b2044248d060f3a0563b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 9 Jul 2019 17:38:17 +0300 Subject: [PATCH 1828/5608] Revert animations and apply suggested changes --- .../Visual/Online/TestSceneScoresContainer.cs | 1 - .../BeatmapSet/Scores/DrawableTopScore.cs | 3 +- .../BeatmapSet/Scores/ScoresContainer.cs | 137 ++++-------------- .../BeatmapSet/Scores/TopScoreUserSection.cs | 9 +- osu.Game/Overlays/BeatmapSetOverlay.cs | 14 +- 5 files changed, 45 insertions(+), 119 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index 4ce689ce6b..824280fe68 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -244,7 +244,6 @@ namespace osu.Game.Tests.Visual.Online allScores.UserScore = myBestScore; scoresContainer.Scores = allScores; }); - AddStep("Trigger loading", () => scoresContainer.Loading = !scoresContainer.Loading); } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index bdae730f7e..d263483046 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -59,11 +59,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { new Drawable[] { - new TopScoreUserSection(position) + new TopScoreUserSection { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Score = score, + ScorePosition = position, }, null, new TopScoreStatisticsSection diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 63e18f3da7..94bcfdee4f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -17,20 +17,17 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public class ScoresContainer : CompositeDrawable { private const int spacing = 15; - private const int padding = 20; + private const int fade_duration = 200; private readonly Box background; private readonly ScoreTable scoreTable; - private readonly FillFlowContainer topScoresContainer; - private readonly ContentContainer contentContainer; - private readonly LoadingContainer loadingContainer; + private readonly LoadingAnimation loadingAnimation; public ScoresContainer() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - InternalChildren = new Drawable[] { background = new Box @@ -39,83 +36,53 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }, new FillFlowContainer { - Direction = FillDirection.Vertical, - AutoSizeAxes = Axes.Y, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Width = 0.95f, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, spacing), + Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { - loadingContainer = new LoadingContainer + topScoresContainer = new FillFlowContainer { RelativeSizeAxes = Axes.X, - Masking = true, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), }, - contentContainer = new ContentContainer + scoreTable = new ScoreTable { - RelativeSizeAxes = Axes.X, - Masking = true, - Child = new FillFlowContainer - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Width = 0.95f, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, spacing), - Padding = new MarginPadding { Vertical = padding }, - Children = new Drawable[] - { - topScoresContainer = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), - }, - scoreTable = new ScoreTable - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - } - }, - } - }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + } } - } + }, + loadingAnimation = new LoadingAnimation + { + Alpha = 0, + Margin = new MarginPadding(20), + }, }; - - Loading = true; } [BackgroundDependencyLoader] private void load(OsuColour colours) { background.Colour = colours.Gray2; + updateDisplay(); } - private bool loading; - public bool Loading { - get => loading; set { - loading = value; + loadingAnimation.FadeTo(value ? 1 : 0, fade_duration); if (value) - { - loadingContainer.Show(); - contentContainer.Hide(); - } - else - { - loadingContainer.Hide(); - - if (scores == null || scores?.Scores.Count < 1) - contentContainer.Hide(); - else - contentContainer.Show(); - } + Scores = null; } } @@ -139,7 +106,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores scoreTable.Scores = scores?.Scores.Count > 1 ? scores.Scores : new List(); scoreTable.FadeTo(scores?.Scores.Count > 1 ? 1 : 0); - if (scores?.Scores.Any() == true) + if (scores?.Scores.Any() ?? false) { topScoresContainer.Add(new DrawableTopScore(scores.Scores.FirstOrDefault())); @@ -148,56 +115,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (userScore != null && userScore.Position != 1) topScoresContainer.Add(new DrawableTopScore(userScore.Score, userScore.Position)); } - - Loading = false; - } - - private class ContentContainer : VisibilityContainer - { - private const int duration = 300; - - private float maxHeight; - - protected override void PopIn() => this.ResizeHeightTo(maxHeight, duration, Easing.OutQuint); - - protected override void PopOut() => this.ResizeHeightTo(0, duration, Easing.OutQuint); - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - if (State.Value == Visibility.Hidden) - return; - - maxHeight = Child.DrawHeight; - - this.ResizeHeightTo(maxHeight, duration, Easing.OutQuint); - } - } - - private class LoadingContainer : VisibilityContainer - { - private const int duration = 300; - private const int height = 50; - - private readonly LoadingAnimation loadingAnimation; - - public LoadingContainer() - { - Child = loadingAnimation = new LoadingAnimation(); - } - - protected override void PopIn() - { - this.ResizeHeightTo(height, duration, Easing.OutQuint); - loadingAnimation.Show(); - } - - protected override void PopOut() - { - this.ResizeHeightTo(0, duration, Easing.OutQuint); - loadingAnimation.Hide(); - } } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 056fe71a39..36e60b3fd9 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -28,7 +28,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly SpriteText date; private readonly UpdateableFlag flag; - public TopScoreUserSection(int position) + public int ScorePosition + { + set => rankText.Text = $"#{value}"; + } + + public TopScoreUserSection() { AutoSizeAxes = Axes.Both; @@ -52,7 +57,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Text = $"#{position.ToString()}", + Text = $"#1", Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true) }, rank = new UpdateableRank(ScoreRank.D) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 1c408ead54..abd86df920 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -17,17 +17,14 @@ using osu.Game.Overlays.BeatmapSet; using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Rulesets; using osuTK; - namespace osu.Game.Overlays { public class BeatmapSetOverlay : FullscreenOverlay { private const int fade_duration = 300; - public const float X_PADDING = 40; public const float TOP_PADDING = 25; public const float RIGHT_WIDTH = 275; - protected readonly Header Header; private RulesetStore rulesets; @@ -46,7 +43,6 @@ namespace osu.Game.Overlays { OsuScrollContainer scroll; Info info; - Children = new Drawable[] { new Box @@ -98,7 +94,11 @@ namespace osu.Game.Overlays scores.Loading = true; getScoresRequest = new GetScoresRequest(b, b.Ruleset); - getScoresRequest.Success += r => Schedule(() => scores.Scores = r); + getScoresRequest.Success += r => Schedule(() => + { + scores.Scores = r; + scores.Loading = false; + }); api.Queue(getScoresRequest); } @@ -123,6 +123,7 @@ namespace osu.Game.Overlays public void FetchAndShowBeatmap(int beatmapId) { beatmapSet.Value = null; + var req = new GetBeatmapSetRequest(beatmapId, BeatmapSetLookupType.BeatmapId); req.Success += res => { @@ -130,15 +131,18 @@ namespace osu.Game.Overlays Header.Picker.Beatmap.Value = Header.BeatmapSet.Value.Beatmaps.First(b => b.OnlineBeatmapID == beatmapId); }; API.Queue(req); + Show(); } public void FetchAndShowBeatmapSet(int beatmapSetId) { beatmapSet.Value = null; + var req = new GetBeatmapSetRequest(beatmapSetId); req.Success += res => beatmapSet.Value = res.ToBeatmapSet(rulesets); API.Queue(req); + Show(); } From e73f22eff8844b3ee429764801c8b4164a194eb6 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 9 Jul 2019 17:53:34 +0300 Subject: [PATCH 1829/5608] Convert length retrieved from online to milliseconds --- osu.Game.Tournament/Components/SongBar.cs | 2 +- osu.Game/Beatmaps/BeatmapSetInfo.cs | 2 +- osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index ec021a8d1f..7005c068ae 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -180,7 +180,7 @@ namespace osu.Game.Tournament.Components panelContents.Children = new Drawable[] { - new DiffPiece(("Length", TimeSpan.FromSeconds(length).ToString(@"mm\:ss"))) + new DiffPiece(("Length", TimeSpan.FromMilliseconds(length).ToString(@"mm\:ss"))) { Anchor = Anchor.CentreLeft, Origin = Anchor.BottomLeft, diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 4075263e12..03bc7c7312 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -41,7 +41,7 @@ namespace osu.Game.Beatmaps public double MaxStarDifficulty => Beatmaps?.Max(b => b.StarDifficulty) ?? 0; /// - /// The maximum playable length of all beatmaps in this set. + /// The maximum playable length in milliseconds of all beatmaps in this set. /// public double MaxLength => Beatmaps?.Max(b => b.Length) ?? 0; diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index ff4d240bf0..f50e281dd0 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.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 Newtonsoft.Json; using osu.Game.Beatmaps; using osu.Game.Rulesets; @@ -71,7 +72,7 @@ namespace osu.Game.Online.API.Requests.Responses StarDifficulty = starDifficulty, OnlineBeatmapID = OnlineBeatmapID, Version = version, - Length = length, + Length = TimeSpan.FromSeconds(length).Milliseconds, Status = Status, BeatmapSet = set, Metrics = metrics, From a0389c338ba2d89e6c07579b397e101d6c4e1c1d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 9 Jul 2019 17:56:08 +0300 Subject: [PATCH 1830/5608] CI fixes --- osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs | 1 - osu.Game/Overlays/BeatmapSetOverlay.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 36e60b3fd9..6d43ec6177 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -57,7 +57,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Text = $"#1", Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true) }, rank = new UpdateableRank(ScoreRank.D) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index abd86df920..3a17b6eec1 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -17,11 +17,11 @@ using osu.Game.Overlays.BeatmapSet; using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Rulesets; using osuTK; + namespace osu.Game.Overlays { public class BeatmapSetOverlay : FullscreenOverlay { - private const int fade_duration = 300; public const float X_PADDING = 40; public const float TOP_PADDING = 25; public const float RIGHT_WIDTH = 275; From b9be4080d315007715870c8f2381448961691f03 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 9 Jul 2019 07:59:38 -0700 Subject: [PATCH 1831/5608] Update beatmap leaderboard to placeholder when signing out --- osu.Game/Online/Leaderboards/Leaderboard.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index dea2ff1a21..35f7ba1c1b 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -203,8 +203,13 @@ namespace osu.Game.Online.Leaderboards public void APIStateChanged(IAPIProvider api, APIState state) { - if (state == APIState.Online) - UpdateScores(); + switch (state) + { + case APIState.Online: + case APIState.Offline: + UpdateScores(); + break; + } } protected void UpdateScores() From 41afe89c0b1ee2f194c48f45c119fcab5dde72f3 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 10 Jul 2019 00:46:34 +0900 Subject: [PATCH 1832/5608] delete no longer needed bindable --- osu.Game/Screens/Play/Player.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d9e050a681..663113f747 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -118,7 +118,6 @@ namespace osu.Game.Screens.Play sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); - config.GetBindable(OsuSetting.ShowStoryboard); ScoreProcessor = DrawableRuleset.CreateScoreProcessor(); ScoreProcessor.Mods.BindTo(Mods); From 80ddfc3b1e33f3c93c5174fef01fd4819bbccfcb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 Jul 2019 10:27:51 +0900 Subject: [PATCH 1833/5608] Disable frame accurate replay playback I want to prioritise better playback performance over accuracy for now. Also, in my testing this is still 100% accurate due to the addition of the FrameStabilityContainer, which is pretty cool. --- osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 3830fa5cbe..4c011388fa 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -84,7 +84,7 @@ namespace osu.Game.Rulesets.Replays /// When set, we will ensure frames executed by nested drawables are frame-accurate to replay data. /// Disabling this can make replay playback smoother (useful for autoplay, currently). /// - public bool FrameAccuratePlayback = true; + public bool FrameAccuratePlayback = false; protected bool HasFrames => Frames.Count > 0; From 2a3601e43b26c70f93f7d4532e0313db92d72c03 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 Jul 2019 11:42:30 +0900 Subject: [PATCH 1834/5608] Fix test class filename case --- ...eplayinputHandlerTest.cs => FramedReplayInputHandlerTest.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Tests/NonVisual/{FramedReplayinputHandlerTest.cs => FramedReplayInputHandlerTest.cs} (99%) diff --git a/osu.Game.Tests/NonVisual/FramedReplayinputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs similarity index 99% rename from osu.Game.Tests/NonVisual/FramedReplayinputHandlerTest.cs rename to osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs index 73387fa5ab..aa5bb02cdd 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayinputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Replays; namespace osu.Game.Tests.NonVisual { [TestFixture] - public class FramedReplayinputHandlerTest + public class FramedReplayInputHandlerTest { private Replay replay; private TestInputHandler handler; From bd53a96507ee406e28e38272fe904cb7607597eb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 Jul 2019 11:47:50 +0900 Subject: [PATCH 1835/5608] Ensure tests cannot run forever --- .../NonVisual/FramedReplayInputHandlerTest.cs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs index aa5bb02cdd..2f1c4831a4 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using NUnit.Framework; using osu.Game.Replays; @@ -160,10 +161,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestRewindInsideImportantSection() { - // fast forward to important section - while (handler.SetFrameFromTime(3000) != null) - { - } + fastForwardToPoint(3000); setTime(4000, 4000); confirmCurrentFrame(4); @@ -205,10 +203,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestRewindOutOfImportantSection() { - // fast forward to important section - while (handler.SetFrameFromTime(3500) != null) - { - } + fastForwardToPoint(3500); confirmCurrentFrame(3); confirmNextFrame(4); @@ -227,6 +222,15 @@ namespace osu.Game.Tests.NonVisual confirmNextFrame(2); } + private void fastForwardToPoint(double destination) + { + for (int i = 0; i < 1000; i++) + if (handler.SetFrameFromTime(destination) == null) + return; + + throw new TimeoutException("Seek was never fulfilled"); + } + private void setTime(double set, double? expect) { Assert.AreEqual(expect, handler.SetFrameFromTime(set)); From 5e2adf59beaff47a0dd0724067852df1dfd2dc8e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 Jul 2019 11:53:34 +0900 Subject: [PATCH 1836/5608] Enforce frame accuracy for tests --- osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs index 2f1c4831a4..18cbd4e7c5 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs @@ -278,6 +278,7 @@ namespace osu.Game.Tests.NonVisual public TestInputHandler(Replay replay) : base(replay) { + FrameAccuratePlayback = true; } protected override double AllowedImportantTimeSpan => 1000; From 7929104b8a8297c7333cc127b97d16370d453a71 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 10 Jul 2019 12:24:05 +0900 Subject: [PATCH 1837/5608] move default into StoryboardContainer, fix load bug, remove comment --- .../Background/TestSceneBackgroundScreenBeatmap.cs | 10 +--------- osu.Game/Graphics/Containers/StoryboardContainer.cs | 5 +++-- osu.Game/Screens/Play/Player.cs | 7 +------ 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs index 0d62bf9bdc..f0e50f8498 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs @@ -334,15 +334,7 @@ namespace osu.Game.Tests.Visual.Background { protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); - protected override StoryboardContainer CreateStoryboardContainer(Storyboard storyboard) - { - return new TestStoryboardContainer - { - RelativeSizeAxes = Axes.Both, - Alpha = 1, - EnableUserDim = { Value = true } - }; - } + protected override StoryboardContainer CreateStoryboardContainer(Storyboard storyboard) => new TestStoryboardContainer { RelativeSizeAxes = Axes.Both }; public TestStoryboardContainer CurrentStoryboardContainer => (TestStoryboardContainer)StoryboardContainer; diff --git a/osu.Game/Graphics/Containers/StoryboardContainer.cs b/osu.Game/Graphics/Containers/StoryboardContainer.cs index 472e22e212..899cbe1f0d 100644 --- a/osu.Game/Graphics/Containers/StoryboardContainer.cs +++ b/osu.Game/Graphics/Containers/StoryboardContainer.cs @@ -19,6 +19,8 @@ namespace osu.Game.Graphics.Containers public StoryboardContainer(Storyboard storyboard) { this.storyboard = storyboard; + EnableUserDim.Default = true; + EnableUserDim.Value = true; } [BackgroundDependencyLoader] @@ -29,13 +31,12 @@ namespace osu.Game.Graphics.Containers protected override void LoadComplete() { - ShowStoryboard.ValueChanged += _ => initializeStoryboard(true); + ShowStoryboard.BindValueChanged(_ => initializeStoryboard(true), true); base.LoadComplete(); } protected override void ApplyFade() { - // Storyboards cannot be blurred, so just hide the storyboard if it gets toggled. DimContainer.FadeTo(!ShowStoryboard.Value || UserDimLevel.Value == 1 ? 0 : 1, BACKGROUND_FADE_DURATION, Easing.OutQuint); } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 663113f747..f44cb069a9 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -78,12 +78,7 @@ namespace osu.Game.Screens.Play protected StoryboardContainer StoryboardContainer { get; private set; } - protected virtual StoryboardContainer CreateStoryboardContainer(Storyboard storyboard) => new StoryboardContainer(storyboard) - { - RelativeSizeAxes = Axes.Both, - Alpha = 1, - EnableUserDim = { Value = true } - }; + protected virtual StoryboardContainer CreateStoryboardContainer(Storyboard storyboard) => new StoryboardContainer(storyboard) { RelativeSizeAxes = Axes.Both }; [Cached] [Cached(Type = typeof(IBindable>))] From 221ee58f550549a6f0e65c68a0baf4e68771cad6 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 10 Jul 2019 12:36:58 +0900 Subject: [PATCH 1838/5608] make storyboard text more visible --- .../Visual/Background/TestSceneBackgroundScreenBeatmap.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs index f0e50f8498..d9f4631ea8 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs @@ -10,6 +10,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Framework.Platform; @@ -244,12 +245,13 @@ namespace osu.Game.Tests.Visual.Background player.ReplacesBackground.Value = false; player.CurrentStoryboardContainer.Add(new OsuSpriteText { - Size = new Vector2(250, 50), + Size = new Vector2(500, 50), Alpha = 1, - Colour = Color4.Tomato, + Colour = Color4.White, Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = "THIS IS A STORYBOARD", + Font = new FontUsage(size: 50) }); }); From 8b8e67fd726d5b1a2ae2380a3afd62ecbeb38ddc Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Wed, 10 Jul 2019 10:41:52 +0200 Subject: [PATCH 1839/5608] Add accidentally deleted code --- osu.Game/Screens/Menu/MainMenu.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 078f9c5a15..b67801f9ba 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -123,6 +123,15 @@ namespace osu.Game.Screens.Menu var track = Beatmap.Value.Track; var metadata = Beatmap.Value.Metadata; + if (last is Intro && track != null) + { + if (!track.IsRunning) + { + track.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * track.Length); + track.Start(); + } + } + Beatmap.ValueChanged += beatmap_ValueChanged; } From 100d15e651f3c8d27de36a689d6660c7a4e89083 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Wed, 10 Jul 2019 10:43:02 +0200 Subject: [PATCH 1840/5608] Move reseting tempo to Editor --- osu.Game/Screens/Edit/Editor.cs | 8 +++++++- osu.Game/Screens/Menu/MainMenu.cs | 3 --- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 8b3cf1ec90..310ce27d45 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -238,7 +238,13 @@ namespace osu.Game.Screens.Edit public override bool OnExiting(IScreen next) { Background.FadeColour(Color4.White, 500); - Beatmap.Value.Track?.Stop(); + + if (Beatmap.Value.Track != null) + { + Beatmap.Value.Track.Tempo.Value = 1; + Beatmap.Value.Track.Stop(); + } + return base.OnExiting(next); } diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index b67801f9ba..6e1c471c1a 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -194,10 +194,7 @@ namespace osu.Game.Screens.Menu preloadSongSelect(); if (Beatmap.Value.Track != null && !musicController.UserRequestedPause) - { - Beatmap.Value.Track.Tempo.Value = 1; Beatmap.Value.Track.Start(); - } } public override bool OnExiting(IScreen next) From fae3348a69127b10fcadff6437c1823ab8c9ade4 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Wed, 10 Jul 2019 13:20:23 +0200 Subject: [PATCH 1841/5608] Add caching MusicController in tests --- .../Visual/Background/TestSceneBackgroundScreenBeatmap.cs | 3 ++- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs index 8b941e4633..a4bb5a38f0 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs @@ -20,6 +20,7 @@ using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; @@ -71,7 +72,7 @@ namespace osu.Game.Tests.Visual.Background Dependencies.Cache(rulesets = new RulesetStore(factory)); Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, audio, host, Beatmap.Default)); Dependencies.Cache(new OsuConfigManager(LocalStorage)); - + Dependencies.Cache(new MusicController()); manager.Import(TestResources.GetTestBeatmapForImport()).Wait(); Beatmap.SetDefault(); diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 962e0fb362..446a632b31 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -16,6 +16,7 @@ using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Database; +using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; @@ -96,6 +97,7 @@ namespace osu.Game.Tests.Visual.SongSelect Dependencies.Cache(rulesets = new RulesetStore(factory)); Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, audio, host, defaultBeatmap = Beatmap.Default)); + Dependencies.Cache(new MusicController()); Beatmap.SetDefault(); } From c3315e805f92e2cb2e38d3ad42bdca7fa8283416 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 10 Jul 2019 16:49:32 +0300 Subject: [PATCH 1842/5608] Use milliseconds for BasicStats' beatmap length --- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 2926c82631..5b10c4e0bb 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.BeatmapSet } else { - length.Value = TimeSpan.FromSeconds(beatmap.Length).ToString(@"m\:ss"); + length.Value = TimeSpan.FromMilliseconds(beatmap.Length).ToString(@"m\:ss"); circleCount.Value = beatmap.OnlineInfo.CircleCount.ToString(); sliderCount.Value = beatmap.OnlineInfo.SliderCount.ToString(); } From 9986178bf41b051c2c288549ed8087f630e2331b Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Wed, 10 Jul 2019 13:20:23 +0200 Subject: [PATCH 1843/5608] Revert "Add caching MusicController in tests" This reverts commit fae3348a69127b10fcadff6437c1823ab8c9ade4. --- .../Visual/Background/TestSceneBackgroundScreenBeatmap.cs | 3 +-- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs index a4bb5a38f0..8b941e4633 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs @@ -20,7 +20,6 @@ using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; @@ -72,7 +71,7 @@ namespace osu.Game.Tests.Visual.Background Dependencies.Cache(rulesets = new RulesetStore(factory)); Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, audio, host, Beatmap.Default)); Dependencies.Cache(new OsuConfigManager(LocalStorage)); - Dependencies.Cache(new MusicController()); + manager.Import(TestResources.GetTestBeatmapForImport()).Wait(); Beatmap.SetDefault(); diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 446a632b31..962e0fb362 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -16,7 +16,6 @@ using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Database; -using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; @@ -97,7 +96,6 @@ namespace osu.Game.Tests.Visual.SongSelect Dependencies.Cache(rulesets = new RulesetStore(factory)); Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, audio, host, defaultBeatmap = Beatmap.Default)); - Dependencies.Cache(new MusicController()); Beatmap.SetDefault(); } From b225b2eb3958cf7c3f1d4fd245a1703885d3d228 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jul 2019 00:18:19 +0900 Subject: [PATCH 1844/5608] Rename to IsUserPaused --- osu.Game/Overlays/MusicController.cs | 14 +++++++++----- osu.Game/Screens/Menu/MainMenu.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index ad0c0717ac..abbcec5094 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -55,7 +55,7 @@ namespace osu.Game.Overlays private Container dragContainer; private Container playerContainer; - public bool UserRequestedPause { get; private set; } + public bool IsUserPaused { get; private set; } [Resolved] private Bindable beatmap { get; set; } @@ -159,7 +159,7 @@ namespace osu.Game.Overlays Origin = Anchor.Centre, Scale = new Vector2(1.4f), IconScale = new Vector2(1.4f), - Action = play, + Action = togglePause, Icon = FontAwesome.Regular.PlayCircle, }, nextButton = new MusicIconButton @@ -278,7 +278,7 @@ namespace osu.Game.Overlays } } - private void play() + private void togglePause() { var track = current?.Track; @@ -289,12 +289,16 @@ namespace osu.Game.Overlays return; } - UserRequestedPause = track.IsRunning; - if (track.IsRunning) + { + IsUserPaused = true; track.Stop(); + } else + { track.Start(); + IsUserPaused = false; + } } private void prev() diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 6e1c471c1a..93c413452d 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -193,7 +193,7 @@ namespace osu.Game.Screens.Menu //we may have consumed our preloaded instance, so let's make another. preloadSongSelect(); - if (Beatmap.Value.Track != null && !musicController.UserRequestedPause) + if (Beatmap.Value.Track != null && !musicController.IsUserPaused) Beatmap.Value.Track.Start(); } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index dd115e04d4..085232b27f 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -573,7 +573,7 @@ namespace osu.Game.Screens.Select { Track track = Beatmap.Value.Track; - if ((!track.IsRunning || restart) && !musicController.UserRequestedPause) + if ((!track.IsRunning || restart) && !musicController.IsUserPaused) { track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; track.Restart(); From 6819c528db75c4d88f75ab35c837f1f3e81e13bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jul 2019 00:20:01 +0900 Subject: [PATCH 1845/5608] Use canBeNull instead of needlessly caching MusicController for tests --- osu.Game/Screens/Menu/MainMenu.cs | 6 +++--- osu.Game/Screens/Select/SongSelect.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 93c413452d..5999cbdfb5 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -42,8 +42,8 @@ namespace osu.Game.Screens.Menu [Resolved] private GameHost host { get; set; } - [Resolved] - private MusicController musicController { get; set; } + [Resolved(canBeNull: true)] + private MusicController music { get; set; } private BackgroundScreenDefault background; @@ -193,7 +193,7 @@ namespace osu.Game.Screens.Menu //we may have consumed our preloaded instance, so let's make another. preloadSongSelect(); - if (Beatmap.Value.Track != null && !musicController.IsUserPaused) + if (Beatmap.Value.Track != null && music?.IsUserPaused != true) Beatmap.Value.Track.Start(); } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 085232b27f..0eeffda5eb 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -87,8 +87,8 @@ namespace osu.Game.Screens.Select private readonly Bindable decoupledRuleset = new Bindable(); - [Resolved] - private MusicController musicController { get; set; } + [Resolved(canBeNull: true)] + private MusicController music { get; set; } [Cached] [Cached(Type = typeof(IBindable>))] @@ -573,7 +573,7 @@ namespace osu.Game.Screens.Select { Track track = Beatmap.Value.Track; - if ((!track.IsRunning || restart) && !musicController.IsUserPaused) + if ((!track.IsRunning || restart) && music?.IsUserPaused != true) { track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; track.Restart(); From ad873b542a09334a86956be8b34249bce849b2f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jul 2019 00:22:40 +0900 Subject: [PATCH 1846/5608] Simplify editor logic --- osu.Game/Screens/Edit/Editor.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 310ce27d45..8cc227d9be 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -224,30 +224,32 @@ namespace osu.Game.Screens.Edit public override void OnResuming(IScreen last) { - Beatmap.Value.Track?.Stop(); base.OnResuming(last); + Beatmap.Value.Track?.Stop(); } public override void OnEntering(IScreen last) { base.OnEntering(last); + Background.FadeColour(Color4.DarkGray, 500); - Beatmap.Value.Track?.Stop(); + resetTrack(); } public override bool OnExiting(IScreen next) { Background.FadeColour(Color4.White, 500); - - if (Beatmap.Value.Track != null) - { - Beatmap.Value.Track.Tempo.Value = 1; - Beatmap.Value.Track.Stop(); - } + resetTrack(); return base.OnExiting(next); } + private void resetTrack() + { + Beatmap.Value.Track?.ResetSpeedAdjustments(); + Beatmap.Value.Track?.Stop(); + } + private void exportBeatmap() => host.OpenFileExternally(Beatmap.Value.Save()); private void onModeChanged(ValueChangedEvent e) From f21e700b7af378f7196732cf1a725137433de8fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jul 2019 00:42:14 +0900 Subject: [PATCH 1847/5608] Code style cleanup --- osu.Game/Overlays/BeatmapSetOverlay.cs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 3a17b6eec1..154e6f20f6 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -28,7 +28,9 @@ namespace osu.Game.Overlays protected readonly Header Header; private RulesetStore rulesets; - private readonly ScoresContainer scores; + + private readonly ScoresContainer scoreContainer; + private GetScoresRequest getScoresRequest; private readonly Bindable beatmapSet = new Bindable(); @@ -63,7 +65,7 @@ namespace osu.Game.Overlays { Header = new Header(), info = new Info(), - scores = new ScoresContainer(), + scoreContainer = new ScoresContainer(), }, }, }, @@ -81,23 +83,24 @@ namespace osu.Game.Overlays }; } - private void getScores(BeatmapInfo b) + private void getScores(BeatmapInfo beatmap) { getScoresRequest?.Cancel(); + getScoresRequest = null; - if (b?.OnlineBeatmapID.HasValue != true) + if (beatmap?.OnlineBeatmapID.HasValue != true) { - scores.Scores = null; + scoreContainer.Scores = null; return; } - scores.Loading = true; + scoreContainer.Loading = true; - getScoresRequest = new GetScoresRequest(b, b.Ruleset); - getScoresRequest.Success += r => Schedule(() => + getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); + getScoresRequest.Success += scores => Schedule(() => { - scores.Scores = r; - scores.Loading = false; + scoreContainer.Scores = scores; + scoreContainer.Loading = false; }); api.Queue(getScoresRequest); } From 953d32366c8f067fe11f41825d64268e18889ed4 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 10 Jul 2019 19:40:29 +0300 Subject: [PATCH 1848/5608] Move request inside the ScoresContainer again --- .../Visual/Online/TestSceneScoresContainer.cs | 12 +++- .../BeatmapSet/Scores/ScoresContainer.cs | 64 ++++++++++++++++--- osu.Game/Overlays/BeatmapSetOverlay.cs | 34 +--------- 3 files changed, 68 insertions(+), 42 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index 824280fe68..b26de1984a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Online public TestSceneScoresContainer() { - ScoresContainer scoresContainer; + TestScoresContainer scoresContainer; Child = new Container { @@ -46,7 +46,7 @@ namespace osu.Game.Tests.Visual.Online RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, - scoresContainer = new ScoresContainer(), + scoresContainer = new TestScoresContainer(), } }; @@ -245,5 +245,13 @@ namespace osu.Game.Tests.Visual.Online scoresContainer.Scores = allScores; }); } + + private class TestScoresContainer : ScoresContainer + { + public new APILegacyScores Scores + { + set => base.Scores = value; + } + } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 94bcfdee4f..bcb9383d0b 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -11,6 +11,9 @@ using osuTK; using System.Collections.Generic; using System.Linq; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Beatmaps; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -24,6 +27,40 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly FillFlowContainer topScoresContainer; private readonly LoadingAnimation loadingAnimation; + [Resolved] + private IAPIProvider api { get; set; } + + private GetScoresRequest getScoresRequest; + + private APILegacyScores scores; + + protected APILegacyScores Scores + { + get => scores; + set + { + scores = value; + + updateDisplay(); + } + } + + private BeatmapInfo beatmap; + + public BeatmapInfo Beatmap + { + get => beatmap; + set + { + if (beatmap == value) + return; + + beatmap = value; + + getScores(beatmap); + } + } + public ScoresContainer() { RelativeSizeAxes = Axes.X; @@ -75,7 +112,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores updateDisplay(); } - public bool Loading + private bool loading { set { @@ -86,17 +123,26 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } - private APILegacyScores scores; - - public APILegacyScores Scores + private void getScores(BeatmapInfo beatmap) { - get => scores; - set - { - scores = value; + getScoresRequest?.Cancel(); + getScoresRequest = null; - updateDisplay(); + if (beatmap?.OnlineBeatmapID.HasValue != true) + { + Scores = null; + return; } + + loading = true; + + getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); + getScoresRequest.Success += scores => Schedule(() => + { + Scores = scores; + loading = false; + }); + api.Queue(getScoresRequest); } private void updateDisplay() diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 154e6f20f6..c20e6368d8 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -11,7 +11,6 @@ using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.BeatmapSet; using osu.Game.Overlays.BeatmapSet.Scores; @@ -29,15 +28,8 @@ namespace osu.Game.Overlays private RulesetStore rulesets; - private readonly ScoresContainer scoreContainer; - - private GetScoresRequest getScoresRequest; - private readonly Bindable beatmapSet = new Bindable(); - [Resolved] - private IAPIProvider api { get; set; } - // receive input outside our bounds so we can trigger a close event on ourselves. public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; @@ -45,6 +37,8 @@ namespace osu.Game.Overlays { OsuScrollContainer scroll; Info info; + ScoresContainer scoreContainer; + Children = new Drawable[] { new Box @@ -77,34 +71,12 @@ namespace osu.Game.Overlays Header.Picker.Beatmap.ValueChanged += b => { info.Beatmap = b.NewValue; - getScores(b.NewValue); + scoreContainer.Beatmap = b.NewValue; scroll.ScrollToStart(); }; } - private void getScores(BeatmapInfo beatmap) - { - getScoresRequest?.Cancel(); - getScoresRequest = null; - - if (beatmap?.OnlineBeatmapID.HasValue != true) - { - scoreContainer.Scores = null; - return; - } - - scoreContainer.Loading = true; - - getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); - getScoresRequest.Success += scores => Schedule(() => - { - scoreContainer.Scores = scores; - scoreContainer.Loading = false; - }); - api.Queue(getScoresRequest); - } - [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { From b32b078e48d38a88cfd222c085cb5e9d648e98e8 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 10 Jul 2019 21:55:43 +0200 Subject: [PATCH 1849/5608] Set default keybindings for jukebox to stable's ones. --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index e756694285..cdd821c173 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -45,9 +45,9 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.Enter, GlobalAction.Select), new KeyBinding(InputKey.KeypadEnter, GlobalAction.Select), - new KeyBinding(InputKey.F5, GlobalAction.MusicPrev), - new KeyBinding(InputKey.F6, GlobalAction.MusicNext), - new KeyBinding(InputKey.X, GlobalAction.MusicPlay), + new KeyBinding(InputKey.F1, GlobalAction.MusicPrev), + new KeyBinding(InputKey.F5, GlobalAction.MusicNext), + new KeyBinding(InputKey.F3, GlobalAction.MusicPlay), }; public IEnumerable InGameKeyBindings => new[] From b2f23a10c87437db39a20b98a1fd2ad6afcf738f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 10 Jul 2019 23:12:18 +0300 Subject: [PATCH 1850/5608] Use the correct property to retrieve the milliseconds --- osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index f50e281dd0..f4d67a56aa 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -72,7 +72,7 @@ namespace osu.Game.Online.API.Requests.Responses StarDifficulty = starDifficulty, OnlineBeatmapID = OnlineBeatmapID, Version = version, - Length = TimeSpan.FromSeconds(length).Milliseconds, + Length = TimeSpan.FromSeconds(length).TotalMilliseconds, Status = Status, BeatmapSet = set, Metrics = metrics, From a49bde7ed3369a734f27957b3a08e4456cbc8f90 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jul 2019 10:38:32 +0900 Subject: [PATCH 1851/5608] Move protected below public --- .../BeatmapSet/Scores/ScoresContainer.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index bcb9383d0b..dfe6c45750 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -32,19 +32,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private GetScoresRequest getScoresRequest; - private APILegacyScores scores; - - protected APILegacyScores Scores - { - get => scores; - set - { - scores = value; - - updateDisplay(); - } - } - private BeatmapInfo beatmap; public BeatmapInfo Beatmap @@ -61,6 +48,19 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } + private APILegacyScores scores; + + protected APILegacyScores Scores + { + get => scores; + set + { + scores = value; + + updateDisplay(); + } + } + public ScoresContainer() { RelativeSizeAxes = Axes.X; From cc9ee472d6090584587c56098c92bee6f5e34d30 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jul 2019 11:07:30 +0900 Subject: [PATCH 1852/5608] Move score nulling out of loading property --- .../Overlays/BeatmapSet/Scores/ScoresContainer.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index dfe6c45750..5f200d7343 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -114,13 +114,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private bool loading { - set - { - loadingAnimation.FadeTo(value ? 1 : 0, fade_duration); - - if (value) - Scores = null; - } + set => loadingAnimation.FadeTo(value ? 1 : 0, fade_duration); } private void getScores(BeatmapInfo beatmap) @@ -128,11 +122,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores getScoresRequest?.Cancel(); getScoresRequest = null; + Scores = null; + if (beatmap?.OnlineBeatmapID.HasValue != true) - { - Scores = null; return; - } loading = true; From 8f9b8ed5a19d121977a08c16b308dc734ef2d3a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jul 2019 11:17:33 +0900 Subject: [PATCH 1853/5608] Simplify information propagation logic --- .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 2 +- .../BeatmapSet/Scores/ScoresContainer.cs | 60 +++++++++---------- 2 files changed, 29 insertions(+), 33 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 15816be327..347522fb48 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Content = null; backgroundFlow.Clear(); - if (value == null || !value.Any()) + if (value?.Any() != true) return; for (int i = 0; i < value.Count; i++) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 5f200d7343..22d7ea9c97 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osuTK; -using System.Collections.Generic; using System.Linq; using osu.Game.Online.API.Requests.Responses; using osu.Game.Beatmaps; @@ -48,16 +47,34 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } - private APILegacyScores scores; - protected APILegacyScores Scores { - get => scores; set { - scores = value; + Schedule(() => + { + loading = false; - updateDisplay(); + topScoresContainer.Clear(); + + if (value?.Scores.Any() != true) + { + scoreTable.Scores = null; + scoreTable.Hide(); + return; + } + + scoreTable.Scores = value.Scores; + scoreTable.Show(); + + var topScore = value.Scores.First(); + var userScore = value.UserScore; + + topScoresContainer.Add(new DrawableTopScore(topScore)); + + if (userScore != null && userScore.Score.OnlineScoreID != topScore.OnlineScoreID) + topScoresContainer.Add(new DrawableTopScore(userScore.Score, userScore.Position)); + }); } } @@ -109,7 +126,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void load(OsuColour colours) { background.Colour = colours.Gray2; - updateDisplay(); } private bool loading @@ -125,35 +141,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Scores = null; if (beatmap?.OnlineBeatmapID.HasValue != true) + { + loading = false; return; - - loading = true; + } getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); - getScoresRequest.Success += scores => Schedule(() => - { - Scores = scores; - loading = false; - }); + getScoresRequest.Success += scores => Scores = scores; api.Queue(getScoresRequest); - } - - private void updateDisplay() - { - topScoresContainer.Clear(); - - scoreTable.Scores = scores?.Scores.Count > 1 ? scores.Scores : new List(); - scoreTable.FadeTo(scores?.Scores.Count > 1 ? 1 : 0); - - if (scores?.Scores.Any() ?? false) - { - topScoresContainer.Add(new DrawableTopScore(scores.Scores.FirstOrDefault())); - - var userScore = scores.UserScore; - - if (userScore != null && userScore.Position != 1) - topScoresContainer.Add(new DrawableTopScore(userScore.Score, userScore.Position)); - } + loading = true; } } } From 85f2212ebcb8d3612e41304f49d4caf0289374ec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jul 2019 11:32:42 +0900 Subject: [PATCH 1854/5608] Reduce spacing and font for rank position --- .../BeatmapSet/Scores/TopScoreUserSection.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 6d43ec6177..a15d3c5fd1 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -28,11 +28,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly SpriteText date; private readonly UpdateableFlag flag; - public int ScorePosition - { - set => rankText.Text = $"#{value}"; - } - public TopScoreUserSection() { AutoSizeAxes = Axes.Both; @@ -50,14 +45,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 3), Children = new Drawable[] { rankText = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true) + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Bold, italics: true) }, rank = new UpdateableRank(ScoreRank.D) { @@ -124,6 +118,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores rankText.Colour = colours.Yellow; } + public int ScorePosition + { + set => rankText.Text = $"#{value}"; + } + /// /// Sets the score to be displayed. /// From 321266e96fc1de7735441dbb70ead7c856bff191 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 11 Jul 2019 13:17:28 +0900 Subject: [PATCH 1855/5608] Make UserDimContainer abstract --- .../TestSceneBackgroundScreenBeatmap.cs | 20 +++--- .../Containers/DimmableBackgroundContainer.cs | 68 +++++++++++++++++++ ...iner.cs => DimmableStoryboardContainer.cs} | 6 +- .../Graphics/Containers/UserDimContainer.cs | 67 +++--------------- .../Backgrounds/BackgroundScreenBeatmap.cs | 4 +- osu.Game/Screens/Play/Player.cs | 8 +-- 6 files changed, 95 insertions(+), 78 deletions(-) create mode 100644 osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs rename osu.Game/Graphics/Containers/{StoryboardContainer.cs => DimmableStoryboardContainer.cs} (89%) diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs index d9f4631ea8..09aaee4adc 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs @@ -243,7 +243,7 @@ namespace osu.Game.Tests.Visual.Background { player.StoryboardEnabled.Value = false; player.ReplacesBackground.Value = false; - player.CurrentStoryboardContainer.Add(new OsuSpriteText + player.CurrentDimmableStoryboardContainer.Add(new OsuSpriteText { Size = new Vector2(500, 50), Alpha = 1, @@ -336,9 +336,9 @@ namespace osu.Game.Tests.Visual.Background { protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); - protected override StoryboardContainer CreateStoryboardContainer(Storyboard storyboard) => new TestStoryboardContainer { RelativeSizeAxes = Axes.Both }; + protected override DimmableStoryboardContainer CreateStoryboardContainer(Storyboard storyboard) => new TestDimmableStoryboardContainer { RelativeSizeAxes = Axes.Both }; - public TestStoryboardContainer CurrentStoryboardContainer => (TestStoryboardContainer)StoryboardContainer; + public TestDimmableStoryboardContainer CurrentDimmableStoryboardContainer => (TestDimmableStoryboardContainer)DimmableStoryboardContainer; // Whether or not the player should be allowed to load. public bool BlockLoad; @@ -352,9 +352,9 @@ namespace osu.Game.Tests.Visual.Background { } - public bool IsStoryboardVisible() => CurrentStoryboardContainer.CurrentAlpha == 1; + public bool IsStoryboardVisible() => CurrentDimmableStoryboardContainer.CurrentAlpha == 1; - public bool IsStoryboardInvisible() => CurrentStoryboardContainer.CurrentAlpha <= 1; + public bool IsStoryboardInvisible() => CurrentDimmableStoryboardContainer.CurrentAlpha <= 1; [BackgroundDependencyLoader] private void load(OsuConfigManager config, CancellationToken token) @@ -387,7 +387,7 @@ namespace osu.Game.Tests.Visual.Background private class FadeAccessibleBackground : BackgroundScreenBeatmap { - protected override UserDimContainer CreateFadeContainer() => fadeContainer = new TestUserDimContainer { RelativeSizeAxes = Axes.Both }; + protected override DimmableBackgroundContainer CreateFadeContainer() => fadeContainer = new TestDimmableBackgroundContainer { RelativeSizeAxes = Axes.Both }; public Color4 CurrentColour => fadeContainer.CurrentColour; @@ -395,7 +395,7 @@ namespace osu.Game.Tests.Visual.Background public Vector2 CurrentBlur => Background.BlurSigma; - private TestUserDimContainer fadeContainer; + private TestDimmableBackgroundContainer fadeContainer; public FadeAccessibleBackground(WorkingBeatmap beatmap) : base(beatmap) @@ -403,17 +403,17 @@ namespace osu.Game.Tests.Visual.Background } } - private class TestStoryboardContainer : StoryboardContainer + private class TestDimmableStoryboardContainer : DimmableStoryboardContainer { public float CurrentAlpha => DimContainer.Alpha; - public TestStoryboardContainer() + public TestDimmableStoryboardContainer() : base(new Storyboard()) { } } - private class TestUserDimContainer : UserDimContainer + private class TestDimmableBackgroundContainer : DimmableBackgroundContainer { public Color4 CurrentColour => DimContainer.Colour; public float CurrentAlpha => DimContainer.Alpha; diff --git a/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs b/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs new file mode 100644 index 0000000000..2d010943bd --- /dev/null +++ b/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs @@ -0,0 +1,68 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Configuration; +using osu.Game.Graphics.Backgrounds; +using osuTK; + +namespace osu.Game.Graphics.Containers +{ + public class DimmableBackgroundContainer : UserDimContainer + { + /// + /// The amount of blur to be applied to the background in addition to user-specified blur. + /// + /// + /// Used in contexts where there can potentially be both user and screen-specified blurring occuring at the same time, such as in + /// + public readonly Bindable BlurAmount = new Bindable(); + + private Bindable userBlurLevel { get; set; } + + private Background background; + + public Background Background + { + get => background; + set + { + base.Add(background = value); + background.BlurTo(blurTarget, 0, Easing.OutQuint); + } + } + + public override void Add(Drawable drawable) + { + if (drawable is Background) + throw new InvalidOperationException($"Use {nameof(Background)} to set a background."); + + base.Add(drawable); + } + + /// + /// As an optimisation, we add the two blur portions to be applied rather than actually applying two separate blurs. + /// + private Vector2 blurTarget => EnableUserDim.Value + ? new Vector2(BlurAmount.Value + (float)userBlurLevel.Value * 25) + : new Vector2(BlurAmount.Value); + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + userBlurLevel = config.GetBindable(OsuSetting.BlurLevel); + BlurAmount.ValueChanged += _ => UpdateVisuals(); + userBlurLevel.ValueChanged += _ => UpdateVisuals(); + } + + protected override void ApplyFade() + { + // The background needs to be hidden in the case of it being replaced by the storyboard + DimContainer.FadeTo(ShowStoryboard.Value && StoryboardReplacesBackground.Value ? 0 : 1, BACKGROUND_FADE_DURATION, Easing.OutQuint); + Background?.BlurTo(blurTarget, BACKGROUND_FADE_DURATION, Easing.OutQuint); + } + } +} diff --git a/osu.Game/Graphics/Containers/StoryboardContainer.cs b/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs similarity index 89% rename from osu.Game/Graphics/Containers/StoryboardContainer.cs rename to osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs index 899cbe1f0d..a8a7b67e01 100644 --- a/osu.Game/Graphics/Containers/StoryboardContainer.cs +++ b/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs @@ -11,16 +11,14 @@ namespace osu.Game.Graphics.Containers /// /// A container that handles loading, as well as applies user-specified visual settings to it. /// - public class StoryboardContainer : UserDimContainer + public class DimmableStoryboardContainer : UserDimContainer { private readonly Storyboard storyboard; private DrawableStoryboard drawableStoryboard; - public StoryboardContainer(Storyboard storyboard) + public DimmableStoryboardContainer(Storyboard storyboard) { this.storyboard = storyboard; - EnableUserDim.Default = true; - EnableUserDim.Value = true; } [BackgroundDependencyLoader] diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index ad6f73eff5..e6a040fcd8 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -1,15 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; -using osu.Game.Graphics.Backgrounds; -using osu.Game.Screens.Play; -using osuTK; using osuTK.Graphics; namespace osu.Game.Graphics.Containers @@ -17,7 +13,7 @@ namespace osu.Game.Graphics.Containers /// /// A container that applies user-configured visual settings to its contents. /// - public class UserDimContainer : Container + public abstract class UserDimContainer : Container { protected const float BACKGROUND_FADE_DURATION = 800; @@ -31,14 +27,6 @@ namespace osu.Game.Graphics.Containers /// public readonly Bindable StoryboardReplacesBackground = new Bindable(); - /// - /// The amount of blur to be applied to the background in addition to user-specified blur. - /// - /// - /// Used in contexts where there can potentially be both user and screen-specified blurring occuring at the same time, such as in - /// - public readonly Bindable BlurAmount = new Bindable(); - protected Bindable UserDimLevel { get; private set; } protected Bindable ShowStoryboard { get; private set; } @@ -47,62 +35,30 @@ namespace osu.Game.Graphics.Containers protected override Container Content => DimContainer; - private Bindable userBlurLevel { get; set; } - - /// - /// As an optimisation, we add the two blur portions to be applied rather than actually applying two separate blurs. - /// - private Vector2 blurTarget => EnableUserDim.Value - ? new Vector2(BlurAmount.Value + (float)userBlurLevel.Value * 25) - : new Vector2(BlurAmount.Value); - /// /// Creates a new . /// - public UserDimContainer() + protected UserDimContainer() { AddInternal(DimContainer = new Container { RelativeSizeAxes = Axes.Both }); } - private Background background; - - public Background Background - { - get => background; - set - { - base.Add(background = value); - background.BlurTo(blurTarget, 0, Easing.OutQuint); - } - } - - public override void Add(Drawable drawable) - { - if (drawable is Background) - throw new InvalidOperationException($"Use {nameof(Background)} to set a background."); - - base.Add(drawable); - } - [BackgroundDependencyLoader] private void load(OsuConfigManager config) { UserDimLevel = config.GetBindable(OsuSetting.DimLevel); - userBlurLevel = config.GetBindable(OsuSetting.BlurLevel); ShowStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); - EnableUserDim.ValueChanged += _ => updateVisuals(); - UserDimLevel.ValueChanged += _ => updateVisuals(); - ShowStoryboard.ValueChanged += _ => updateVisuals(); - StoryboardReplacesBackground.ValueChanged += _ => updateVisuals(); - BlurAmount.ValueChanged += _ => updateVisuals(); - userBlurLevel.ValueChanged += _ => updateVisuals(); + EnableUserDim.ValueChanged += _ => UpdateVisuals(); + UserDimLevel.ValueChanged += _ => UpdateVisuals(); + ShowStoryboard.ValueChanged += _ => UpdateVisuals(); + StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals(); } protected override void LoadComplete() { base.LoadComplete(); - updateVisuals(); + UpdateVisuals(); } /// @@ -112,14 +68,9 @@ namespace osu.Game.Graphics.Containers /// While both backgrounds and storyboards allow user dim levels to be applied, storyboards can be toggled via /// and can cause backgrounds to become hidden via . Storyboards are also currently unable to be blurred. /// - protected virtual void ApplyFade() - { - // The background needs to be hidden in the case of it being replaced by the storyboard - DimContainer.FadeTo(ShowStoryboard.Value && StoryboardReplacesBackground.Value ? 0 : 1, BACKGROUND_FADE_DURATION, Easing.OutQuint); - Background?.BlurTo(blurTarget, BACKGROUND_FADE_DURATION, Easing.OutQuint); - } + protected abstract void ApplyFade(); - private void updateVisuals() + protected void UpdateVisuals() { ApplyFade(); diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index b6c2d016d2..1bb613755b 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -30,9 +30,9 @@ namespace osu.Game.Screens.Backgrounds /// public readonly Bindable BlurAmount = new Bindable(); - private readonly UserDimContainer fadeContainer; + private readonly DimmableBackgroundContainer fadeContainer; - protected virtual UserDimContainer CreateFadeContainer() => new UserDimContainer { RelativeSizeAxes = Axes.Both }; + protected virtual DimmableBackgroundContainer CreateFadeContainer() => new DimmableBackgroundContainer() { RelativeSizeAxes = Axes.Both }; public BackgroundScreenBeatmap(WorkingBeatmap beatmap = null) { diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index f44cb069a9..55e759d215 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -76,9 +76,9 @@ namespace osu.Game.Screens.Play protected GameplayClockContainer GameplayClockContainer { get; private set; } - protected StoryboardContainer StoryboardContainer { get; private set; } + protected DimmableStoryboardContainer DimmableStoryboardContainer { get; private set; } - protected virtual StoryboardContainer CreateStoryboardContainer(Storyboard storyboard) => new StoryboardContainer(storyboard) { RelativeSizeAxes = Axes.Both }; + protected virtual DimmableStoryboardContainer CreateStoryboardContainer(Storyboard storyboard) => new DimmableStoryboardContainer(storyboard) { RelativeSizeAxes = Axes.Both }; [Cached] [Cached(Type = typeof(IBindable>))] @@ -124,7 +124,7 @@ namespace osu.Game.Screens.Play GameplayClockContainer.Children = new[] { - StoryboardContainer = CreateStoryboardContainer(Beatmap.Value.Storyboard), + DimmableStoryboardContainer = CreateStoryboardContainer(Beatmap.Value.Storyboard), new ScalingContainer(ScalingMode.Gameplay) { Child = new LocalSkinOverrideContainer(working.Skin) @@ -455,7 +455,7 @@ namespace osu.Game.Screens.Play Background.BlurAmount.Value = 0; Background.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); - StoryboardContainer.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); + DimmableStoryboardContainer.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); storyboardReplacesBackground.Value = Beatmap.Value.Storyboard.ReplacesBackground && Beatmap.Value.Storyboard.HasDrawable; From ac170a695749c8b1e9b9662d193de78348a93e7c Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 11 Jul 2019 14:00:25 +0900 Subject: [PATCH 1856/5608] add comment and cleanup --- osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs | 1 + osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs | 4 ++++ osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs b/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs index 2d010943bd..f415792993 100644 --- a/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs +++ b/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs @@ -7,6 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Configuration; using osu.Game.Graphics.Backgrounds; +using osu.Game.Screens.Play; using osuTK; namespace osu.Game.Graphics.Containers diff --git a/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs b/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs index a8a7b67e01..16379baeab 100644 --- a/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs +++ b/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs @@ -19,6 +19,10 @@ namespace osu.Game.Graphics.Containers public DimmableStoryboardContainer(Storyboard storyboard) { this.storyboard = storyboard; + + // Storyboards current do not get used in scenarios without user dim, so default to enabled here. + EnableUserDim.Default = true; + EnableUserDim.Value = true; } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 1bb613755b..97f77f789a 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Backgrounds private readonly DimmableBackgroundContainer fadeContainer; - protected virtual DimmableBackgroundContainer CreateFadeContainer() => new DimmableBackgroundContainer() { RelativeSizeAxes = Axes.Both }; + protected virtual DimmableBackgroundContainer CreateFadeContainer() => new DimmableBackgroundContainer { RelativeSizeAxes = Axes.Both }; public BackgroundScreenBeatmap(WorkingBeatmap beatmap = null) { From 932243cfd4c7908d548d15df939d4eb2df6e8eb1 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 11 Jul 2019 14:14:00 +0900 Subject: [PATCH 1857/5608] public before private --- .../Graphics/Containers/DimmableBackgroundContainer.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs b/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs index f415792993..7339548069 100644 --- a/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs +++ b/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs @@ -22,10 +22,6 @@ namespace osu.Game.Graphics.Containers /// public readonly Bindable BlurAmount = new Bindable(); - private Bindable userBlurLevel { get; set; } - - private Background background; - public Background Background { get => background; @@ -36,6 +32,10 @@ namespace osu.Game.Graphics.Containers } } + private Bindable userBlurLevel { get; set; } + + private Background background; + public override void Add(Drawable drawable) { if (drawable is Background) From 3bc789fca892d8120e9916c6b285d56f64490086 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jul 2019 15:09:06 +0900 Subject: [PATCH 1858/5608] Remove osd prefix and prefer upper-case OSD --- .../Visual/UserInterface/TestSceneOnScreenDisplay.cs | 3 ++- osu.Game/Overlays/OSD/{OsdToast.cs => Toast.cs} | 6 +++--- .../{OsdTrackedSettingToast.cs => TrackedSettingToast.cs} | 6 +++--- osu.Game/Overlays/OnScreenDisplay.cs | 6 +++--- 4 files changed, 11 insertions(+), 10 deletions(-) rename osu.Game/Overlays/OSD/{OsdToast.cs => Toast.cs} (94%) rename osu.Game/Overlays/OSD/{OsdTrackedSettingToast.cs => TrackedSettingToast.cs} (98%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs index b28f794a58..59a35591bd 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs @@ -7,6 +7,7 @@ using osu.Framework.Configuration; using osu.Framework.Configuration.Tracking; using osu.Framework.Graphics; using osu.Game.Overlays; +using osu.Game.Overlays.OSD; namespace osu.Game.Tests.Visual.UserInterface { @@ -22,7 +23,7 @@ namespace osu.Game.Tests.Visual.UserInterface osd.BeginTracking(this, config); Add(osd); - AddStep("Display empty osd toast", () => osd.Display(new Overlays.OSD.OsdToast())); + AddStep("Display empty osd toast", () => osd.Display(new Toast())); AddRepeatStep("Change toggle (no bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingNoKeybind), 2); AddRepeatStep("Change toggle (with bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingWithKeybind), 2); AddRepeatStep("Change enum (no bind)", () => config.IncrementEnumSetting(TestConfigSetting.EnumSettingNoKeybind), 3); diff --git a/osu.Game/Overlays/OSD/OsdToast.cs b/osu.Game/Overlays/OSD/Toast.cs similarity index 94% rename from osu.Game/Overlays/OSD/OsdToast.cs rename to osu.Game/Overlays/OSD/Toast.cs index f700577ba1..6634959bca 100644 --- a/osu.Game/Overlays/OSD/OsdToast.cs +++ b/osu.Game/Overlays/OSD/Toast.cs @@ -1,19 +1,19 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osuTK.Graphics; namespace osu.Game.Overlays.OSD { - public class OsdToast : Container + public class Toast : Container { private readonly Container content; protected override Container Content => content; - public OsdToast() + public Toast() { Anchor = Anchor.Centre; Origin = Anchor.Centre; diff --git a/osu.Game/Overlays/OSD/OsdTrackedSettingToast.cs b/osu.Game/Overlays/OSD/TrackedSettingToast.cs similarity index 98% rename from osu.Game/Overlays/OSD/OsdTrackedSettingToast.cs rename to osu.Game/Overlays/OSD/TrackedSettingToast.cs index 411a33b000..8def8476f0 100644 --- a/osu.Game/Overlays/OSD/OsdTrackedSettingToast.cs +++ b/osu.Game/Overlays/OSD/TrackedSettingToast.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Configuration.Tracking; using osu.Framework.Extensions.Color4Extensions; @@ -13,13 +14,12 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; -using System; namespace osu.Game.Overlays.OSD { - public class OsdTrackedSettingToast : OsdToast + public class TrackedSettingToast : Toast { - public OsdTrackedSettingToast(SettingDescription description) + public TrackedSettingToast(SettingDescription description) { SpriteText textLine2; FillFlowContainer optionLights; diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 0577257080..a30ce5c56f 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -97,16 +97,16 @@ namespace osu.Game.Overlays } /// - /// Displays the given as parameter on the OSD + /// Displays the given as parameter on the OSD /// /// - public void Display(OsdToast toast) + public void Display(Toast toast) { box.Child = toast; DisplayTemporarily(box); } - private void displayTrackedSettingChange(SettingDescription description) => Schedule(() => Display(new OsdTrackedSettingToast(description))); + private void displayTrackedSettingChange(SettingDescription description) => Schedule(() => Display(new TrackedSettingToast(description))); private TransformSequence fadeIn; private ScheduledDelegate fadeOut; From dd13e2508ae854c483b60afcfa8aadd994393bc5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jul 2019 15:14:57 +0900 Subject: [PATCH 1859/5608] Add note about toast height --- osu.Game/Overlays/OSD/Toast.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/OSD/Toast.cs b/osu.Game/Overlays/OSD/Toast.cs index 6634959bca..3ca010c5f4 100644 --- a/osu.Game/Overlays/OSD/Toast.cs +++ b/osu.Game/Overlays/OSD/Toast.cs @@ -18,6 +18,8 @@ namespace osu.Game.Overlays.OSD Anchor = Anchor.Centre; Origin = Anchor.Centre; Width = 240; + + // A toast's height is decided (and transformed) by the containing OnScreenDisplay. RelativeSizeAxes = Axes.Y; InternalChildren = new Drawable[] From 2c62891c4836ceb5b24957331dd6aa615ca8f85e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jul 2019 15:15:34 +0900 Subject: [PATCH 1860/5608] Make Toast base class abstract --- .../Visual/UserInterface/TestSceneOnScreenDisplay.cs | 6 +++++- osu.Game/Overlays/OSD/Toast.cs | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs index 59a35591bd..ca14822205 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.UserInterface osd.BeginTracking(this, config); Add(osd); - AddStep("Display empty osd toast", () => osd.Display(new Toast())); + AddStep("Display empty osd toast", () => osd.Display(new EmptyToast())); AddRepeatStep("Change toggle (no bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingNoKeybind), 2); AddRepeatStep("Change toggle (with bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingWithKeybind), 2); AddRepeatStep("Change enum (no bind)", () => config.IncrementEnumSetting(TestConfigSetting.EnumSettingNoKeybind), 3); @@ -88,6 +88,10 @@ namespace osu.Game.Tests.Visual.UserInterface Setting4 } + private class EmptyToast : Toast + { + } + private class TestOnScreenDisplay : OnScreenDisplay { protected override void DisplayTemporarily(Drawable toDisplay) => toDisplay.FadeIn().ResizeHeightTo(110); diff --git a/osu.Game/Overlays/OSD/Toast.cs b/osu.Game/Overlays/OSD/Toast.cs index 3ca010c5f4..c6e3227cd1 100644 --- a/osu.Game/Overlays/OSD/Toast.cs +++ b/osu.Game/Overlays/OSD/Toast.cs @@ -8,12 +8,12 @@ using osuTK.Graphics; namespace osu.Game.Overlays.OSD { - public class Toast : Container + public abstract class Toast : Container { private readonly Container content; protected override Container Content => content; - public Toast() + protected Toast() { Anchor = Anchor.Centre; Origin = Anchor.Centre; From b6e15fb79186fc94379f2993694b8474af35c076 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jul 2019 22:21:37 +0900 Subject: [PATCH 1861/5608] Update framework --- osu.Android.props | 2 +- osu.Game/Input/Bindings/GlobalActionContainer.cs | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 5ee0573c58..98f9bf1a42 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 14d356f889..669fd62e45 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -39,7 +39,7 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.F4, GlobalAction.ToggleMute), new KeyBinding(InputKey.Escape, GlobalAction.Back), - new KeyBinding(InputKey.MouseButton1, GlobalAction.Back), + new KeyBinding(InputKey.ExtraMouseButton1, GlobalAction.Back), new KeyBinding(InputKey.Space, GlobalAction.Select), new KeyBinding(InputKey.Enter, GlobalAction.Select), diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e872cd1387..436ba90a88 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index a319094cb1..c24349bcb5 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From cd7c03c13a0519c069b531b4c7c127539b85871f Mon Sep 17 00:00:00 2001 From: StanR Date: Thu, 11 Jul 2019 16:44:48 +0300 Subject: [PATCH 1862/5608] Add genre and language sections to beatmapset overlay --- .../Online/TestSceneBeatmapSetOverlay.cs | 2 ++ osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs | 20 ++++++++++++++++++ osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs | 10 +++++++++ osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs | 21 +++++++++++++++++++ .../API/Requests/Responses/APIBeatmapSet.cs | 8 +++++++ osu.Game/Overlays/BeatmapSet/Info.cs | 21 ++++++++++++++++++- 6 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs create mode 100644 osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index daee419b52..d87d9910c3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -173,6 +173,8 @@ namespace osu.Game.Tests.Visual.Online HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), + Language = BeatmapSetOnlineLanguage.English, + Genre = BeatmapSetOnlineGenre.Rock, }, Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = new List diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs b/osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs new file mode 100644 index 0000000000..cea9d94987 --- /dev/null +++ b/osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Beatmaps +{ + public enum BeatmapSetOnlineGenre + { + Any = 0, + Unspecified = 1, + VideoGame = 2, + Anime = 3, + Rock = 4, + Pop = 5, + Other = 6, + Novelty = 7, + // genre_id 8 doesnt exist + HipHop = 9, + Electronic = 10 + } +} diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs index ea3f0b61b9..2d2f06a57c 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs @@ -70,6 +70,16 @@ namespace osu.Game.Beatmaps /// The availability of this beatmap set. /// public BeatmapSetOnlineAvailability Availability { get; set; } + + /// + /// Beatmap set's song genre. + /// + public BeatmapSetOnlineGenre Genre { get; set; } + + /// + /// Beatmap set's song language. + /// + public BeatmapSetOnlineLanguage Language { get; set; } } public class BeatmapSetOnlineCovers diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs b/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs new file mode 100644 index 0000000000..0fb0dec904 --- /dev/null +++ b/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Beatmaps +{ + public enum BeatmapSetOnlineLanguage + { + Any = 0, + Other = 1, + English = 2, + Japanese = 3, + Chinese = 4, + Instrumental = 5, + Korean = 6, + French = 7, + German = 8, + Swedish = 9, + Spanish = 10, + Italian = 11 + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 200a705500..9ca2cb0b81 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -66,6 +66,12 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"availability")] private BeatmapSetOnlineAvailability availability { get; set; } + [JsonProperty(@"genre_id")] + private BeatmapSetOnlineGenre genre { get; set; } + + [JsonProperty(@"language_id")] + private BeatmapSetOnlineLanguage language { get; set; } + [JsonProperty(@"beatmaps")] private IEnumerable beatmaps { get; set; } @@ -91,6 +97,8 @@ namespace osu.Game.Online.API.Requests.Responses Ranked = ranked, LastUpdated = lastUpdated, Availability = availability, + Genre = genre, + Language = language }, Beatmaps = beatmaps?.Select(b => b.ToBeatmap(rulesets)).ToList(), }; diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 44827f0a0c..27ca58fbd3 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -36,7 +36,7 @@ namespace osu.Game.Overlays.BeatmapSet public Info() { - MetadataSection source, tags; + MetadataSection source, tags, genre, language; RelativeSizeAxes = Axes.X; Height = 220; Masking = true; @@ -88,6 +88,19 @@ namespace osu.Game.Overlays.BeatmapSet Children = new[] { source = new MetadataSection("Source"), + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Width = 0.5f, + FillMode = FillMode.Fit, + Children = new Drawable[] + { + genre = new MetadataSection("Genre"), + language = new MetadataSection("Language"), + } + }, tags = new MetadataSection("Tags"), }, }, @@ -119,6 +132,12 @@ namespace osu.Game.Overlays.BeatmapSet { source.Text = b.NewValue?.Metadata.Source ?? string.Empty; tags.Text = b.NewValue?.Metadata.Tags ?? string.Empty; + + var genreId = b.NewValue?.OnlineInfo.Genre ?? BeatmapSetOnlineGenre.Unspecified; + genre.Text = genreId.ToString(); + + var languageId = b.NewValue?.OnlineInfo.Language ?? BeatmapSetOnlineLanguage.Other; + language.Text = languageId.ToString(); }; } From 1e04fcc6b54d8dab5d24478794ad27478cf38b80 Mon Sep 17 00:00:00 2001 From: StanR Date: Thu, 11 Jul 2019 17:47:09 +0300 Subject: [PATCH 1863/5608] Apply fixes --- osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs | 20 ------- osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs | 56 ++++++++++++++++++- osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs | 21 ------- osu.Game/Overlays/BeatmapSet/Info.cs | 9 +-- 4 files changed, 57 insertions(+), 49 deletions(-) delete mode 100644 osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs delete mode 100644 osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs b/osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs deleted file mode 100644 index cea9d94987..0000000000 --- a/osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Beatmaps -{ - public enum BeatmapSetOnlineGenre - { - Any = 0, - Unspecified = 1, - VideoGame = 2, - Anime = 3, - Rock = 4, - Pop = 5, - Other = 6, - Novelty = 7, - // genre_id 8 doesnt exist - HipHop = 9, - Electronic = 10 - } -} diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs index 2d2f06a57c..4cb50b59fb 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.ComponentModel; using Newtonsoft.Json; namespace osu.Game.Beatmaps @@ -72,16 +73,67 @@ namespace osu.Game.Beatmaps public BeatmapSetOnlineAvailability Availability { get; set; } /// - /// Beatmap set's song genre. + /// The song genre of this beatmap set. /// public BeatmapSetOnlineGenre Genre { get; set; } /// - /// Beatmap set's song language. + /// The song language of this beatmap set. /// public BeatmapSetOnlineLanguage Language { get; set; } } + public enum BeatmapSetOnlineGenre + { + [Description("Any")] + Any = 0, + + [Description("Unspecified")] + Unspecified = 1, + + [Description("Video Game")] + VideoGame = 2, + + [Description("Anime")] + Anime = 3, + + [Description("Rock")] + Rock = 4, + + [Description("Pop")] + Pop = 5, + + [Description("Other")] + Other = 6, + + [Description("Novelty")] + Novelty = 7, + + // genre_id 8 doesn't exist + + [Description("Hip-Hop")] + HipHop = 9, + + [Description("Electronic")] + Electronic = 10 + } + + public enum BeatmapSetOnlineLanguage + { + Any, + Other, + English, + Japanese, + Chinese, + Instrumental, + Korean, + French, + German, + Swedish, + Spanish, + Italian + } + public class BeatmapSetOnlineCovers { public string CoverLowRes { get; set; } diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs b/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs deleted file mode 100644 index 0fb0dec904..0000000000 --- a/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Beatmaps -{ - public enum BeatmapSetOnlineLanguage - { - Any = 0, - Other = 1, - English = 2, - Japanese = 3, - Chinese = 4, - Instrumental = 5, - Korean = 6, - French = 7, - German = 8, - Swedish = 9, - Spanish = 10, - Italian = 11 - } -} diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 27ca58fbd3..0e4e9db948 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -132,12 +133,8 @@ namespace osu.Game.Overlays.BeatmapSet { source.Text = b.NewValue?.Metadata.Source ?? string.Empty; tags.Text = b.NewValue?.Metadata.Tags ?? string.Empty; - - var genreId = b.NewValue?.OnlineInfo.Genre ?? BeatmapSetOnlineGenre.Unspecified; - genre.Text = genreId.ToString(); - - var languageId = b.NewValue?.OnlineInfo.Language ?? BeatmapSetOnlineLanguage.Other; - language.Text = languageId.ToString(); + genre.Text = (b.NewValue?.OnlineInfo.Genre ?? BeatmapSetOnlineGenre.Unspecified).GetDescription(); + language.Text = (b.NewValue?.OnlineInfo.Language ?? BeatmapSetOnlineLanguage.Other).ToString(); }; } From 0d9f978857a869f433bd6733d3640a0fb387cdcd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jul 2019 11:38:15 +0900 Subject: [PATCH 1864/5608] Don't expose DimContainer --- .../TestSceneBackgroundScreenBeatmap.cs | 6 ++--- .../Containers/DimmableBackgroundContainer.cs | 10 ++++---- .../Containers/DimmableStoryboardContainer.cs | 6 +---- .../Graphics/Containers/UserDimContainer.cs | 24 +++++++++---------- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs index 09aaee4adc..6a4145b24f 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs @@ -405,7 +405,7 @@ namespace osu.Game.Tests.Visual.Background private class TestDimmableStoryboardContainer : DimmableStoryboardContainer { - public float CurrentAlpha => DimContainer.Alpha; + public float CurrentAlpha => Content.Alpha; public TestDimmableStoryboardContainer() : base(new Storyboard()) @@ -415,8 +415,8 @@ namespace osu.Game.Tests.Visual.Background private class TestDimmableBackgroundContainer : DimmableBackgroundContainer { - public Color4 CurrentColour => DimContainer.Colour; - public float CurrentAlpha => DimContainer.Alpha; + public Color4 CurrentColour => Content.Colour; + public float CurrentAlpha => Content.Alpha; } } } diff --git a/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs b/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs index 7339548069..32b333528f 100644 --- a/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs +++ b/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs @@ -55,14 +55,16 @@ namespace osu.Game.Graphics.Containers private void load(OsuConfigManager config) { userBlurLevel = config.GetBindable(OsuSetting.BlurLevel); - BlurAmount.ValueChanged += _ => UpdateVisuals(); userBlurLevel.ValueChanged += _ => UpdateVisuals(); + BlurAmount.ValueChanged += _ => UpdateVisuals(); } - protected override void ApplyFade() + protected override bool ShowDimContent => !ShowStoryboard.Value || !StoryboardReplacesBackground.Value; // The background needs to be hidden in the case of it being replaced by the storyboard + + protected override void UpdateVisuals() { - // The background needs to be hidden in the case of it being replaced by the storyboard - DimContainer.FadeTo(ShowStoryboard.Value && StoryboardReplacesBackground.Value ? 0 : 1, BACKGROUND_FADE_DURATION, Easing.OutQuint); + base.UpdateVisuals(); + Background?.BlurTo(blurTarget, BACKGROUND_FADE_DURATION, Easing.OutQuint); } } diff --git a/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs b/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs index 16379baeab..0d87e64447 100644 --- a/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs +++ b/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Game.Storyboards; using osu.Game.Storyboards.Drawables; @@ -37,10 +36,7 @@ namespace osu.Game.Graphics.Containers base.LoadComplete(); } - protected override void ApplyFade() - { - DimContainer.FadeTo(!ShowStoryboard.Value || UserDimLevel.Value == 1 ? 0 : 1, BACKGROUND_FADE_DURATION, Easing.OutQuint); - } + protected override bool ShowDimContent => ShowStoryboard.Value && UserDimLevel.Value < 1; private void initializeStoryboard(bool async) { diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index e6a040fcd8..93af0be923 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -31,16 +31,16 @@ namespace osu.Game.Graphics.Containers protected Bindable ShowStoryboard { get; private set; } - protected Container DimContainer { get; } + protected override Container Content => dimContent; - protected override Container Content => DimContainer; + private Container dimContent { get; } /// /// Creates a new . /// protected UserDimContainer() { - AddInternal(DimContainer = new Container { RelativeSizeAxes = Axes.Both }); + AddInternal(dimContent = new Container { RelativeSizeAxes = Axes.Both }); } [BackgroundDependencyLoader] @@ -62,19 +62,17 @@ namespace osu.Game.Graphics.Containers } /// - /// Apply non-dim related settings to the content, such as hiding and blurring. + /// Whether the content of this container should currently be visible. /// - /// - /// While both backgrounds and storyboards allow user dim levels to be applied, storyboards can be toggled via - /// and can cause backgrounds to become hidden via . Storyboards are also currently unable to be blurred. - /// - protected abstract void ApplyFade(); + protected virtual bool ShowDimContent => true; - protected void UpdateVisuals() + /// + /// Should be invoked when any dependent dim level or user setting is changed and bring the visual state up-to-date. + /// + protected virtual void UpdateVisuals() { - ApplyFade(); - - DimContainer.FadeColour(EnableUserDim.Value ? OsuColour.Gray(1 - (float)UserDimLevel.Value) : Color4.White, BACKGROUND_FADE_DURATION, Easing.OutQuint); + dimContent.FadeTo(ShowDimContent ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint); + dimContent.FadeColour(EnableUserDim.Value ? OsuColour.Gray(1 - (float)UserDimLevel.Value) : Color4.White, BACKGROUND_FADE_DURATION, Easing.OutQuint); } } } From b5ca7faca4dad93ea1bb0c31a3426f2e74433d67 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jul 2019 11:40:32 +0900 Subject: [PATCH 1865/5608] Move default value for EnableUserDim to base class --- osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs | 4 ---- osu.Game/Graphics/Containers/UserDimContainer.cs | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs b/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs index 0d87e64447..d0ef7a2c25 100644 --- a/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs +++ b/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs @@ -18,10 +18,6 @@ namespace osu.Game.Graphics.Containers public DimmableStoryboardContainer(Storyboard storyboard) { this.storyboard = storyboard; - - // Storyboards current do not get used in scenarios without user dim, so default to enabled here. - EnableUserDim.Default = true; - EnableUserDim.Value = true; } [BackgroundDependencyLoader] diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 93af0be923..f5958a092b 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -20,7 +20,7 @@ namespace osu.Game.Graphics.Containers /// /// Whether or not user-configured dim levels should be applied to the container. /// - public readonly Bindable EnableUserDim = new Bindable(); + public readonly Bindable EnableUserDim = new Bindable(true); /// /// Whether or not the storyboard loaded should completely hide the background behind it. From 46f7bb885bbd445c851c4259663d3260d2ada4e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jul 2019 11:50:06 +0900 Subject: [PATCH 1866/5608] Move classes to local namespaces Also renames test scene to more appropriate name. --- ...eatmap.cs => TestSceneUserDimContainer.cs} | 26 +++---- .../Containers/DimmableBackgroundContainer.cs | 71 ----------------- .../Backgrounds/BackgroundScreenBeatmap.cs | 76 +++++++++++++++++-- .../Play/DimmableStoryboard.cs} | 7 +- osu.Game/Screens/Play/Player.cs | 8 +- 5 files changed, 90 insertions(+), 98 deletions(-) rename osu.Game.Tests/Visual/Background/{TestSceneBackgroundScreenBeatmap.cs => TestSceneUserDimContainer.cs} (92%) delete mode 100644 osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs rename osu.Game/{Graphics/Containers/DimmableStoryboardContainer.cs => Screens/Play/DimmableStoryboard.cs} (89%) diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs similarity index 92% rename from osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs rename to osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index 6a4145b24f..5578fee42d 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -38,7 +38,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Background { [TestFixture] - public class TestSceneBackgroundScreenBeatmap : ManualInputManagerTestScene + public class TestSceneUserDimContainer : ManualInputManagerTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -243,7 +243,7 @@ namespace osu.Game.Tests.Visual.Background { player.StoryboardEnabled.Value = false; player.ReplacesBackground.Value = false; - player.CurrentDimmableStoryboardContainer.Add(new OsuSpriteText + player.DimmableStoryboard.Add(new OsuSpriteText { Size = new Vector2(500, 50), Alpha = 1, @@ -336,9 +336,9 @@ namespace osu.Game.Tests.Visual.Background { protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); - protected override DimmableStoryboardContainer CreateStoryboardContainer(Storyboard storyboard) => new TestDimmableStoryboardContainer { RelativeSizeAxes = Axes.Both }; + protected override DimmableStoryboard CreateStoryboardContainer(Storyboard storyboard) => new TestDimmableStoryboard { RelativeSizeAxes = Axes.Both }; - public TestDimmableStoryboardContainer CurrentDimmableStoryboardContainer => (TestDimmableStoryboardContainer)DimmableStoryboardContainer; + public new TestDimmableStoryboard DimmableStoryboard => (TestDimmableStoryboard)base.DimmableStoryboard; // Whether or not the player should be allowed to load. public bool BlockLoad; @@ -352,9 +352,9 @@ namespace osu.Game.Tests.Visual.Background { } - public bool IsStoryboardVisible() => CurrentDimmableStoryboardContainer.CurrentAlpha == 1; + public bool IsStoryboardVisible() => DimmableStoryboard.CurrentAlpha == 1; - public bool IsStoryboardInvisible() => CurrentDimmableStoryboardContainer.CurrentAlpha <= 1; + public bool IsStoryboardInvisible() => DimmableStoryboard.CurrentAlpha <= 1; [BackgroundDependencyLoader] private void load(OsuConfigManager config, CancellationToken token) @@ -387,15 +387,15 @@ namespace osu.Game.Tests.Visual.Background private class FadeAccessibleBackground : BackgroundScreenBeatmap { - protected override DimmableBackgroundContainer CreateFadeContainer() => fadeContainer = new TestDimmableBackgroundContainer { RelativeSizeAxes = Axes.Both }; + protected override DimmableBackground CreateFadeContainer() => dimmable = new TestDimmableBackground { RelativeSizeAxes = Axes.Both }; - public Color4 CurrentColour => fadeContainer.CurrentColour; + public Color4 CurrentColour => dimmable.CurrentColour; - public float CurrentAlpha => fadeContainer.CurrentAlpha; + public float CurrentAlpha => dimmable.CurrentAlpha; public Vector2 CurrentBlur => Background.BlurSigma; - private TestDimmableBackgroundContainer fadeContainer; + private TestDimmableBackground dimmable; public FadeAccessibleBackground(WorkingBeatmap beatmap) : base(beatmap) @@ -403,17 +403,17 @@ namespace osu.Game.Tests.Visual.Background } } - private class TestDimmableStoryboardContainer : DimmableStoryboardContainer + private class TestDimmableStoryboard : DimmableStoryboard { public float CurrentAlpha => Content.Alpha; - public TestDimmableStoryboardContainer() + public TestDimmableStoryboard() : base(new Storyboard()) { } } - private class TestDimmableBackgroundContainer : DimmableBackgroundContainer + private class TestDimmableBackground : BackgroundScreenBeatmap.DimmableBackground { public Color4 CurrentColour => Content.Colour; public float CurrentAlpha => Content.Alpha; diff --git a/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs b/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs deleted file mode 100644 index 32b333528f..0000000000 --- a/osu.Game/Graphics/Containers/DimmableBackgroundContainer.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Game.Configuration; -using osu.Game.Graphics.Backgrounds; -using osu.Game.Screens.Play; -using osuTK; - -namespace osu.Game.Graphics.Containers -{ - public class DimmableBackgroundContainer : UserDimContainer - { - /// - /// The amount of blur to be applied to the background in addition to user-specified blur. - /// - /// - /// Used in contexts where there can potentially be both user and screen-specified blurring occuring at the same time, such as in - /// - public readonly Bindable BlurAmount = new Bindable(); - - public Background Background - { - get => background; - set - { - base.Add(background = value); - background.BlurTo(blurTarget, 0, Easing.OutQuint); - } - } - - private Bindable userBlurLevel { get; set; } - - private Background background; - - public override void Add(Drawable drawable) - { - if (drawable is Background) - throw new InvalidOperationException($"Use {nameof(Background)} to set a background."); - - base.Add(drawable); - } - - /// - /// As an optimisation, we add the two blur portions to be applied rather than actually applying two separate blurs. - /// - private Vector2 blurTarget => EnableUserDim.Value - ? new Vector2(BlurAmount.Value + (float)userBlurLevel.Value * 25) - : new Vector2(BlurAmount.Value); - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - userBlurLevel = config.GetBindable(OsuSetting.BlurLevel); - userBlurLevel.ValueChanged += _ => UpdateVisuals(); - BlurAmount.ValueChanged += _ => UpdateVisuals(); - } - - protected override bool ShowDimContent => !ShowStoryboard.Value || !StoryboardReplacesBackground.Value; // The background needs to be hidden in the case of it being replaced by the storyboard - - protected override void UpdateVisuals() - { - base.UpdateVisuals(); - - Background?.BlurTo(blurTarget, BACKGROUND_FADE_DURATION, Easing.OutQuint); - } - } -} diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 97f77f789a..8d6caf4c71 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -1,14 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; +using osu.Game.Screens.Play; +using osuTK; namespace osu.Game.Screens.Backgrounds { @@ -30,16 +34,17 @@ namespace osu.Game.Screens.Backgrounds /// public readonly Bindable BlurAmount = new Bindable(); - private readonly DimmableBackgroundContainer fadeContainer; + private readonly DimmableBackground dimmable; - protected virtual DimmableBackgroundContainer CreateFadeContainer() => new DimmableBackgroundContainer { RelativeSizeAxes = Axes.Both }; + protected virtual DimmableBackground CreateFadeContainer() => new DimmableBackground { RelativeSizeAxes = Axes.Both }; public BackgroundScreenBeatmap(WorkingBeatmap beatmap = null) { Beatmap = beatmap; - InternalChild = fadeContainer = CreateFadeContainer(); - fadeContainer.EnableUserDim.BindTo(EnableUserDim); - fadeContainer.BlurAmount.BindTo(BlurAmount); + + InternalChild = dimmable = CreateFadeContainer(); + dimmable.EnableUserDim.BindTo(EnableUserDim); + dimmable.BlurAmount.BindTo(BlurAmount); } [BackgroundDependencyLoader] @@ -86,8 +91,8 @@ namespace osu.Game.Screens.Backgrounds } b.Depth = newDepth; - fadeContainer.Background = Background = b; - StoryboardReplacesBackground.BindTo(fadeContainer.StoryboardReplacesBackground); + dimmable.Background = Background = b; + StoryboardReplacesBackground.BindTo(dimmable.StoryboardReplacesBackground); } public override bool Equals(BackgroundScreen other) @@ -112,5 +117,62 @@ namespace osu.Game.Screens.Backgrounds Sprite.Texture = Beatmap?.Background ?? textures.Get(@"Backgrounds/bg1"); } } + + public class DimmableBackground : UserDimContainer + { + /// + /// The amount of blur to be applied to the background in addition to user-specified blur. + /// + /// + /// Used in contexts where there can potentially be both user and screen-specified blurring occuring at the same time, such as in + /// + public readonly Bindable BlurAmount = new Bindable(); + + public Background Background + { + get => background; + set + { + base.Add(background = value); + background.BlurTo(blurTarget, 0, Easing.OutQuint); + } + } + + private Bindable userBlurLevel { get; set; } + + private Background background; + + public override void Add(Drawable drawable) + { + if (drawable is Background) + throw new InvalidOperationException($"Use {nameof(Background)} to set a background."); + + base.Add(drawable); + } + + /// + /// As an optimisation, we add the two blur portions to be applied rather than actually applying two separate blurs. + /// + private Vector2 blurTarget => EnableUserDim.Value + ? new Vector2(BlurAmount.Value + (float)userBlurLevel.Value * 25) + : new Vector2(BlurAmount.Value); + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + userBlurLevel = config.GetBindable(OsuSetting.BlurLevel); + userBlurLevel.ValueChanged += _ => UpdateVisuals(); + BlurAmount.ValueChanged += _ => UpdateVisuals(); + } + + protected override bool ShowDimContent => !ShowStoryboard.Value || !StoryboardReplacesBackground.Value; // The background needs to be hidden in the case of it being replaced by the storyboard + + protected override void UpdateVisuals() + { + base.UpdateVisuals(); + + Background?.BlurTo(blurTarget, BACKGROUND_FADE_DURATION, Easing.OutQuint); + } + } } } diff --git a/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs b/osu.Game/Screens/Play/DimmableStoryboard.cs similarity index 89% rename from osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs rename to osu.Game/Screens/Play/DimmableStoryboard.cs index d0ef7a2c25..45dff039b6 100644 --- a/osu.Game/Graphics/Containers/DimmableStoryboardContainer.cs +++ b/osu.Game/Screens/Play/DimmableStoryboard.cs @@ -2,20 +2,21 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Game.Graphics.Containers; using osu.Game.Storyboards; using osu.Game.Storyboards.Drawables; -namespace osu.Game.Graphics.Containers +namespace osu.Game.Screens.Play { /// /// A container that handles loading, as well as applies user-specified visual settings to it. /// - public class DimmableStoryboardContainer : UserDimContainer + public class DimmableStoryboard : UserDimContainer { private readonly Storyboard storyboard; private DrawableStoryboard drawableStoryboard; - public DimmableStoryboardContainer(Storyboard storyboard) + public DimmableStoryboard(Storyboard storyboard) { this.storyboard = storyboard; } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 55e759d215..0396d85d75 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -76,9 +76,9 @@ namespace osu.Game.Screens.Play protected GameplayClockContainer GameplayClockContainer { get; private set; } - protected DimmableStoryboardContainer DimmableStoryboardContainer { get; private set; } + protected DimmableStoryboard DimmableStoryboard { get; private set; } - protected virtual DimmableStoryboardContainer CreateStoryboardContainer(Storyboard storyboard) => new DimmableStoryboardContainer(storyboard) { RelativeSizeAxes = Axes.Both }; + protected virtual DimmableStoryboard CreateStoryboardContainer(Storyboard storyboard) => new DimmableStoryboard(storyboard) { RelativeSizeAxes = Axes.Both }; [Cached] [Cached(Type = typeof(IBindable>))] @@ -124,7 +124,7 @@ namespace osu.Game.Screens.Play GameplayClockContainer.Children = new[] { - DimmableStoryboardContainer = CreateStoryboardContainer(Beatmap.Value.Storyboard), + DimmableStoryboard = CreateStoryboardContainer(Beatmap.Value.Storyboard), new ScalingContainer(ScalingMode.Gameplay) { Child = new LocalSkinOverrideContainer(working.Skin) @@ -455,7 +455,7 @@ namespace osu.Game.Screens.Play Background.BlurAmount.Value = 0; Background.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); - DimmableStoryboardContainer.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); + DimmableStoryboard.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); storyboardReplacesBackground.Value = Beatmap.Value.Storyboard.ReplacesBackground && Beatmap.Value.Storyboard.HasDrawable; From 8b67f88d161283548df4ff732d7f2e33fefa528c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jul 2019 12:04:45 +0900 Subject: [PATCH 1867/5608] Don't expose dimmable container creation in player --- .../Background/TestSceneUserDimContainer.cs | 23 ++++--------------- .../Graphics/Containers/UserDimContainer.cs | 9 +++++++- osu.Game/Screens/Play/Player.cs | 5 +--- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index 5578fee42d..f0893abadc 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -29,7 +29,6 @@ using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Play; using osu.Game.Screens.Play.PlayerSettings; using osu.Game.Screens.Select; -using osu.Game.Storyboards; using osu.Game.Tests.Resources; using osu.Game.Users; using osuTK; @@ -139,14 +138,14 @@ namespace osu.Game.Tests.Visual.Background player.StoryboardEnabled.Value = true; }); waitForDim(); - AddAssert("Background is invisible, storyboard is visible", () => songSelect.IsBackgroundInvisible() && player.IsStoryboardVisible()); + AddAssert("Background is invisible, storyboard is visible", () => songSelect.IsBackgroundInvisible() && player.IsStoryboardVisible); AddStep("Storyboard Disabled", () => { player.ReplacesBackground.Value = false; player.StoryboardEnabled.Value = false; }); waitForDim(); - AddAssert("Background is visible, storyboard is invisible", () => songSelect.IsBackgroundVisible() && player.IsStoryboardInvisible()); + AddAssert("Background is visible, storyboard is invisible", () => songSelect.IsBackgroundVisible() && !player.IsStoryboardVisible); } /// @@ -336,9 +335,7 @@ namespace osu.Game.Tests.Visual.Background { protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); - protected override DimmableStoryboard CreateStoryboardContainer(Storyboard storyboard) => new TestDimmableStoryboard { RelativeSizeAxes = Axes.Both }; - - public new TestDimmableStoryboard DimmableStoryboard => (TestDimmableStoryboard)base.DimmableStoryboard; + public new DimmableStoryboard DimmableStoryboard => base.DimmableStoryboard; // Whether or not the player should be allowed to load. public bool BlockLoad; @@ -352,9 +349,7 @@ namespace osu.Game.Tests.Visual.Background { } - public bool IsStoryboardVisible() => DimmableStoryboard.CurrentAlpha == 1; - - public bool IsStoryboardInvisible() => DimmableStoryboard.CurrentAlpha <= 1; + public bool IsStoryboardVisible => DimmableStoryboard.ContentDisplayed; [BackgroundDependencyLoader] private void load(OsuConfigManager config, CancellationToken token) @@ -403,16 +398,6 @@ namespace osu.Game.Tests.Visual.Background } } - private class TestDimmableStoryboard : DimmableStoryboard - { - public float CurrentAlpha => Content.Alpha; - - public TestDimmableStoryboard() - : base(new Storyboard()) - { - } - } - private class TestDimmableBackground : BackgroundScreenBeatmap.DimmableBackground { public Color4 CurrentColour => Content.Colour; diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index f5958a092b..03de5f651f 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -27,6 +27,11 @@ namespace osu.Game.Graphics.Containers /// public readonly Bindable StoryboardReplacesBackground = new Bindable(); + /// + /// Whether the content of this container is currently being displayed. + /// + public bool ContentDisplayed { get; private set; } + protected Bindable UserDimLevel { get; private set; } protected Bindable ShowStoryboard { get; private set; } @@ -71,7 +76,9 @@ namespace osu.Game.Graphics.Containers /// protected virtual void UpdateVisuals() { - dimContent.FadeTo(ShowDimContent ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint); + ContentDisplayed = ShowDimContent; + + dimContent.FadeTo((ContentDisplayed) ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint); dimContent.FadeColour(EnableUserDim.Value ? OsuColour.Gray(1 - (float)UserDimLevel.Value) : Color4.White, BACKGROUND_FADE_DURATION, Easing.OutQuint); } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0396d85d75..8dc16af575 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -26,7 +26,6 @@ using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Ranking; using osu.Game.Skinning; -using osu.Game.Storyboards; using osu.Game.Users; namespace osu.Game.Screens.Play @@ -78,8 +77,6 @@ namespace osu.Game.Screens.Play protected DimmableStoryboard DimmableStoryboard { get; private set; } - protected virtual DimmableStoryboard CreateStoryboardContainer(Storyboard storyboard) => new DimmableStoryboard(storyboard) { RelativeSizeAxes = Axes.Both }; - [Cached] [Cached(Type = typeof(IBindable>))] protected new readonly Bindable> Mods = new Bindable>(Array.Empty()); @@ -124,7 +121,7 @@ namespace osu.Game.Screens.Play GameplayClockContainer.Children = new[] { - DimmableStoryboard = CreateStoryboardContainer(Beatmap.Value.Storyboard), + DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both }, new ScalingContainer(ScalingMode.Gameplay) { Child = new LocalSkinOverrideContainer(working.Skin) From 671f7f99cd139bf255a3d7e393d9e8ac211517df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jul 2019 13:44:43 +0900 Subject: [PATCH 1868/5608] Use constant for blur amount --- .../Visual/Background/TestSceneUserDimContainer.cs | 2 +- osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index f0893abadc..dc4ceed59e 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -302,7 +302,7 @@ namespace osu.Game.Tests.Visual.Background public bool IsBackgroundUndimmed() => ((FadeAccessibleBackground)Background).CurrentColour == Color4.White; - public bool IsUserBlurApplied() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2((float)BlurLevel.Value * 25); + public bool IsUserBlurApplied() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2((float)BlurLevel.Value * BackgroundScreenBeatmap.USER_BLUR_FACTOR); public bool IsUserBlurDisabled() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(0); diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 8d6caf4c71..7b4feb1819 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -18,6 +18,11 @@ namespace osu.Game.Screens.Backgrounds { public class BackgroundScreenBeatmap : BackgroundScreen { + /// + /// The amount of blur to apply when full user blur is requested. + /// + public const float USER_BLUR_FACTOR = 25; + protected Background Background; private WorkingBeatmap beatmap; @@ -154,7 +159,7 @@ namespace osu.Game.Screens.Backgrounds /// As an optimisation, we add the two blur portions to be applied rather than actually applying two separate blurs. /// private Vector2 blurTarget => EnableUserDim.Value - ? new Vector2(BlurAmount.Value + (float)userBlurLevel.Value * 25) + ? new Vector2(BlurAmount.Value + (float)userBlurLevel.Value * USER_BLUR_FACTOR) : new Vector2(BlurAmount.Value); [BackgroundDependencyLoader] From 44855d8bb2203af41b8c57c7f56b1f12172c208e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jul 2019 13:45:34 +0900 Subject: [PATCH 1869/5608] Ensure any existing background is expired if set more than once --- osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 7b4feb1819..08f1881038 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -138,6 +138,8 @@ namespace osu.Game.Screens.Backgrounds get => background; set { + background?.Expire(); + base.Add(background = value); background.BlurTo(blurTarget, 0, Easing.OutQuint); } From 09d679de8d6367ec6894e470318d3cda625d5fd3 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 12 Jul 2019 08:50:53 +0200 Subject: [PATCH 1870/5608] Move text display layout to Toast. --- .../UserInterface/TestSceneOnScreenDisplay.cs | 4 ++ osu.Game/Overlays/OSD/Toast.cs | 35 +++++++++++++++- osu.Game/Overlays/OSD/TrackedSettingToast.cs | 41 +++---------------- 3 files changed, 42 insertions(+), 38 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs index ca14822205..4decfc7dd6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs @@ -90,6 +90,10 @@ namespace osu.Game.Tests.Visual.UserInterface private class EmptyToast : Toast { + public EmptyToast() + : base("", "", "") + { + } } private class TestOnScreenDisplay : OnScreenDisplay diff --git a/osu.Game/Overlays/OSD/Toast.cs b/osu.Game/Overlays/OSD/Toast.cs index c6e3227cd1..6572830d10 100644 --- a/osu.Game/Overlays/OSD/Toast.cs +++ b/osu.Game/Overlays/OSD/Toast.cs @@ -4,6 +4,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.OSD @@ -13,7 +16,7 @@ namespace osu.Game.Overlays.OSD private readonly Container content; protected override Container Content => content; - protected Toast() + protected Toast(string description, string value, string keybinding) { Anchor = Anchor.Centre; Origin = Anchor.Centre; @@ -35,7 +38,35 @@ namespace osu.Game.Overlays.OSD Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - } + }, + new OsuSpriteText + { + Padding = new MarginPadding(10), + Name = "Description", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Black), + Spacing = new Vector2(1, 0), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = description.ToUpperInvariant() + }, + new OsuSpriteText + { + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), + Padding = new MarginPadding { Left = 10, Right = 10 }, + Name = "Value", + Anchor = Anchor.Centre, + Origin = Anchor.BottomCentre, + Text = value + }, + new OsuSpriteText + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Name = "Shortcut", + Margin = new MarginPadding { Bottom = 15 }, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Text = string.IsNullOrEmpty(keybinding) ? "NO KEY BOUND" : keybinding.ToUpperInvariant() + }, }; } } diff --git a/osu.Game/Overlays/OSD/TrackedSettingToast.cs b/osu.Game/Overlays/OSD/TrackedSettingToast.cs index 8def8476f0..454ba84d70 100644 --- a/osu.Game/Overlays/OSD/TrackedSettingToast.cs +++ b/osu.Game/Overlays/OSD/TrackedSettingToast.cs @@ -9,9 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; @@ -20,55 +18,29 @@ namespace osu.Game.Overlays.OSD public class TrackedSettingToast : Toast { public TrackedSettingToast(SettingDescription description) + : base(description.Name, description.Value, description.Shortcut) { - SpriteText textLine2; FillFlowContainer optionLights; Children = new Drawable[] { - new OsuSpriteText - { - Padding = new MarginPadding(10), - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Black), - Spacing = new Vector2(1, 0), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = description.Name.ToUpperInvariant() - }, - textLine2 = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), - Padding = new MarginPadding { Left = 10, Right = 10 }, - Anchor = Anchor.Centre, - Origin = Anchor.BottomCentre, - Text = description.Value - }, new FillFlowContainer { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Direction = FillDirection.Vertical, + Margin = new MarginPadding { Top = 70 }, Children = new Drawable[] { optionLights = new FillFlowContainer { - Padding = new MarginPadding { Top = 20, Bottom = 5 }, + Padding = new MarginPadding { Bottom = 5 }, Spacing = new Vector2(5, 0), Direction = FillDirection.Horizontal, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both }, - new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Margin = new MarginPadding { Bottom = 15 }, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), - Alpha = 0.3f, - Text = string.IsNullOrEmpty(description.Shortcut) ? "NO KEY BOUND" : description.Shortcut.ToUpperInvariant() - }, } } }; @@ -90,9 +62,6 @@ namespace osu.Game.Overlays.OSD break; } - textLine2.Origin = optionCount > 0 ? Anchor.BottomCentre : Anchor.Centre; - textLine2.Y = optionCount > 0 ? 0 : 5; - for (int i = 0; i < optionCount; i++) { optionLights.Add(new OptionLight From b24a6e64bdf994fd729bf4bd1e99d4161460ad9f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jul 2019 16:22:02 +0900 Subject: [PATCH 1871/5608] Add link to bounty history to readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2c330e403c..35dc010d93 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ Before starting, please make sure you are familiar with the [development and tes 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. -For those interested, we love to reward quality contributions via bounties, 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. +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 From 376d228add3a4fa34a0d16fbd2af635fd20a994d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jul 2019 17:49:59 +0900 Subject: [PATCH 1872/5608] Use new logo style for icons / readme --- README.md | 2 +- assets/lazer.png | Bin 39498 -> 77579 bytes osu.Desktop/lazer.ico | Bin 93005 -> 86650 bytes .../AppIcon.appiconset/Contents.json | 250 +----------------- .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 1237 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 3602 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 6457 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 2250 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 6069 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 10842 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 3602 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 9677 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 16681 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 16681 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 28381 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 8946 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 22553 -> 0 bytes .../Icon-App-83.5x83.5@2x.png | Bin 25862 -> 0 bytes .../AppIcon.appiconset/ItunesArtwork@2x.png | Bin 251219 -> 0 bytes .../AppIcon.appiconset/iOSAppStore.png | Bin 0 -> 350640 bytes .../AppIcon.appiconset/iPadApp1x.png | Bin 0 -> 10106 bytes .../AppIcon.appiconset/iPadApp2x.png | Bin 0 -> 24966 bytes .../AppIcon.appiconset/iPadNotification1x.png | Bin 0 -> 2227 bytes .../AppIcon.appiconset/iPadNotification2x.png | Bin 0 -> 4485 bytes .../AppIcon.appiconset/iPadProApp2x.png | Bin 0 -> 28089 bytes .../AppIcon.appiconset/iPadSettings1x.png | Bin 0 -> 3192 bytes .../AppIcon.appiconset/iPadSettings2x.png | Bin 0 -> 7156 bytes .../AppIcon.appiconset/iPadSpotlight1x.png | Bin 0 -> 4485 bytes .../AppIcon.appiconset/iPadSpotlight2x.png | Bin 0 -> 10768 bytes .../AppIcon.appiconset/iPhoneApp2x.png | Bin 0 -> 18204 bytes .../AppIcon.appiconset/iPhoneApp3x.png | Bin 0 -> 30946 bytes .../iPhoneNotification2x.png | Bin 0 -> 4485 bytes .../iPhoneNotification3x.png | Bin 0 -> 7458 bytes .../AppIcon.appiconset/iPhoneSettings2x.png | Bin 0 -> 7156 bytes .../AppIcon.appiconset/iPhoneSettings3x.png | Bin 0 -> 12085 bytes .../AppIcon.appiconset/iPhoneSpotlight2x.png | Bin 0 -> 10768 bytes .../AppIcon.appiconset/iPhoneSpotlight3x.png | Bin 0 -> 18204 bytes osu.iOS/iTunesArtwork | Bin 99849 -> 142214 bytes osu.iOS/iTunesArtwork@2x | Bin 251219 -> 350640 bytes osu.iOS/osu.iOS.csproj | 41 +-- 40 files changed, 24 insertions(+), 269 deletions(-) mode change 100644 => 100755 osu.Desktop/lazer.ico delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iOSAppStore.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadApp1x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadApp2x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification1x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification2x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadProApp2x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings1x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings2x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight1x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight2x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp2x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp3x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification2x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification3x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings2x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings3x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight2x.png create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight3x.png diff --git a/README.md b/README.md index 35dc010d93..590442f01b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- +

# osu! diff --git a/assets/lazer.png b/assets/lazer.png index 075a8e7184ad508cedd8fe9ae549d8cea696b51a..19b5fc2151e570bf321596998437072943422c26 100644 GIT binary patch literal 77579 zcmeFZ*F#g?^F5q|(5u*}f*L@YARSZ^8y!KUBLt;MSE@)!0K4?wL8;OO0jU8CND&aE zNlAR@(n1fUocBaOzw7rO_;M324twu2vu4ej*%MwG-_+)06JUctAe_27*G(W0IQT0Z z!omc8V1%V3!4H1F8EoMCb_w|&QQ1p z0m!%1-OMWoUsFV);)UNg4?SbmsWF#!RaHACW(U{dGlsCj;6JWCz(Sc6hZQ52^=)l& z<$XD&J(Jz#eU}y;!;nXwp4!>zGj(!u%E50?`Zv_Lz%&2f&;MEA|19wTXMyS)k=Gy) zY`Qr0$LLOPdZG98(1AdWh5ec)wa}@kgVxsh4dtea%QKfD5FKzW<1zcN;6tZLGG5V6 zR8I5a{z?T5_Go$`5x%wiv=NQo32U8Pst-`thd@N3;JV8l)P56tfOw}G_xXt4d_?ZC zG|ltszAq!R8vMgQGe97$;G%3C#OGo58_e6e`(F9*{l_y$kVlBJ8)X#0E`PG^+j}Sk zOQ$5=E3|sW%(_&2;O<5laQXH6syhCc#L>x_9@~x6-B|sZv1zS_)?O>Fzgwd&Gf;&W zz24DcE?gn|K=9{Ie;ZI#mw$P{Pwjrf-alQ)cv6Sse=n77kLhA37XFywcX@wcr+y{W zVLf0{UIwcw7A~LOd&)r1=mhC9)7)l6>amaQnGFA4ZK8vgUTBYNZ+3B5mJSb9e;Ls| zH1?@ag7JL9F$g3MJTS_r8smI^950C&N9J_oX0}SStEyh9zN2nzz!;8zpYIc6ysyFX z@3b);w3L$s{X8H@Vnc!U?5W~GV%o$;3j@By;YanHS|hp@Fz`WY(ze3AgI+>)*;Y5- zG5*`+GGRZGDlAboK|SCPJsL6g@Vak{?k7O-a_N1U7@1Ere9~NpqvYv0{Dr+T_*4Oe z74!?;>aRFRsV=*{94fI4`f`tRxfQyO&Jg9lYkeUXEw}bISYw}n{sZlf#UfL&m>@0O z680hQk)KDWQWFvPQ|@$MK%b5?GWmZ`mm1Lvd`WSV_X=BA0c&PUG7W$d+X{81bhZNY2LlQD6|)98y`NECW;&C4tMT&nLq#J zmWl}{vG2}R>>u#7;EA#ES8&K);D&^|6($}EJUWjOG-BCV@lroM*mn@pD{)%%I21!L z7XAl4dC{eP23q#A!^L6SrH^+mcG)C|5ERQ|O&4cP>QFhl;j>RreJ5fz1F|Q4!jbp= zCI^Vl(7zae#Yu{d(I->$kfE-a+V~9t&xp|Rlw)ZdB5@T#b2+&j4+=E$x=j9=5k~D0!ov7+c^<5b zGnrqod#8c@e~*02Ll#?wA(!}FxWXWcN`iqRWntnq674!*BBsaQ2^ip8#z>V;LXpG2 zKQd^K6+pl<%4GR1D*~~Z9QSvAEe0w6^;n+W6`+5oH?=hn-5QTR6+O7%LXuq8meoc_ ze`O0d)6`#1ga+Fw5CR2T_ZVk5{sOSXc@TG*x|Mcv$2;}J&h1fd1g6v6_I#WyfAxwO zLs;_<_l+&Be{Pt*g2Pp!VSr*GBeidffnVEM-IUo;pXpB0b?i0VKkHYYC*mItrI4z4 zcWP5a&OO6l%rmoAz>2{jC>R7{e`QcEoTl!gGKs4QIBEGNK38zZh=F#bmV#2xukVyO zBFY*rlRKvSr!>pf#r*h#oYMdK^enilb1ii-sfrREwGz#G7|w=ZSm1^J5t-fQGK2nI zJWp(Ce{2u=yQF{5MRrqSiMceBLkD-=e(a6ZKRfENQW`+hczR;aIw)R<2+PaqhU|*L z!m6-U??JIckK8#y5;>a^m_$R3%6`>?Q&IB?&- z+TO;M*HX_m?K32&`m2WfnL(SmdKvzDLez|aTVtg1QY2CjT+-K4J6hm0g<0-AJ8Qc$ zqHD_6TBT4Cz;=JRlzl1#7X$(B+&jDSxuf3?RXO?{T{)wWnd)4h>raK8s65M0W{her zJzdxP?O=I#AyCjgn_cL^U*ExL&lz@isbT!y8SR+W?>o2u;}%{2HPrLK^A=hY!HUIu zmHRIph0xc}O9==N60ECaa_g6sBF{rTv;B*9=^oLPrAt=C)UmtK0c!TM3unZM3QnK1yzqU+CXt4fp7 zxp!FC^$mFY#F%s<_~jD}8ZV(*?~13a=e;x9JX|6o?p0XoC!BJM*ta*}jha8-3Nf>PtMvlzL1u>Y|qdh>0D&?ynJ z)$%)HTsdB`!u&i zYwCh3Bui)~`^P|H>h;+3_%zz8{o{;hh~iO=n=6qv-JAP6E&?mUk%VSBEx7D&w*-IpmMC_0Z~S3YIYZrb z55!z<3+oCMLXNDEUjxX{w)`LGMsOou4cpPp8`FLQ`(82>+@+8T?R6Y^C3dDt;(|Qx z^|hStw+Hhu89{lmBM)ZMWjV*^|GktkD`iB3+{{^N4X52;@>NF3ub#`{sAT_0`R?Q5{bms*69tR2)U;T1CpZBr^f>s zg1yb{V3c^lpZmV7>qmh#*F5!8E|cOWypZT;6W1WfBck0hC9J3v@~5k_YtmMAf9ri;VUZ{f6yFC&M=!!cfw)Pp?C{ELqtO*|xjpt-gd zd-weLxSmT3J*JvL$`a<`z1`tcseDR4UNY*r9E4wSMrZ8H{VG}s23b|gqprtT==l11 znV4$r;7SZUzsEfJDx1nmInK1F-nVt~!=APCy0-UvW9{MRu^HC#M%AxUwScB86W=eM zL7%W>6ghtX;&<+xfQ)^Qg@%H>_ojt4J?DCmf!YWLA6@u2|G<);A_VDZ{}jf*6ync8 z!~H>2Y^Qd(*qqi8kWS7YO~l1uMixTV2XgdkFQI)d#43&p@jGWRQpx8@b;XzI&kPXT^}4B~a98vuGF@VwI2F zYBOID>VLQgkUVSiPTRjL-qhX*OoVOKNp^>u32-g^7#{*IJ*cp187=W>)!5_xu*q8M zk~L9-wdInb$Axh=0bReFD319tPwQEsB#&l{UdtGo`bcnoY88et$8(a<&2DoU)Ryug zlAMpIariUr)13c??hxb2u}2xw$*gm?gi#84CGPb}aNWfADqmwLJ<<%tt;6@m{1ZFIvRuPyrdUhl5C~Qr8 zeISR&vQCw$7d|8bOCU4c@pB%5oK!2JixsSGI4-KksT0^-lFqx=h_mK*{kn0&Zl7lU zZ1+E}L1h2b+8yT|ZM$}4$fl1cjD}h@X%OxA zQ`Cf^D1N2U6c!Ra4f~s;FGgUjX60&Wlkvy`1&4xBozhZ!(prJTRwvnV&zTzdmKiHGPn&^Md(G3VT*!*>V>JQjj6F_Z{kwJ5yixwQPE33;oD~*>%~R?ekgLHTr*hX~tQ1?63c0CKl_-rnuU6}Zwe7e6D-tLKWY{R$e=v25zv-R@ zEvn<%v&vcCIsNJlW~xpxxaN;yW;2KesT*>TA;ll(ZxN$m&RDWaO330U68I|;k% zzLmC{3Z2Q*nx}&~{R)Fvo=dR^)A6gCP<|=@`?9}#Pzdx$|YlEL4#*lO{7Os?xr1|G@HA0fFzr+iv z96q}9pg_PrzqvP^jm{|Lrzp9*5dhH&Ncl7x=9RiAP#(D3z@e`^E>f(aGON0u)lr*T z6l)tnJJY|<+d$QiiY|f4tMCsV)U7Sg-Yq^DO!-eFfqx^Z71`-)6KsBnecUC!+$1>y z$sc!v=)x|2=Ks5oBRi#`r5*5?J8s}4yI9TSRN>l7x!u1PTeZ<#ONsObp2(8foIinK z^zp?rY*Atb<3)g&@8yr$p5gqua-*jd+a$w%UpXNYe%R{pmiw!s-5LAX+N1QuVa!bn zEJEi5{5N_SXy#0nw(HDLA&L~blf>q!3d3^fTbHt*h&c6A2-k z=~0vir%7@4PH1%fyWo7jr-3jQaQJ9t8}>7Fen)%Zd_6QzK(2Kk`rKWv51I zeRjp{P;Zhgke5O)mGhBQTvmRYm1&mF$X6#CbH=sYZolDDk06|JLC~Y>fhq~9N!<^3O&v&gvT_c%*KKxR zRHBwb#XU-{qdt>=w~4+Zs(T#!G&O#?&bRS-Bmz43I{R4vTp8)Tls3i@ju&6NRob9fk*zPtfUaHp@SF8kVdtm0yyVFO<2 zP3ee%R>oZQ3_|6t7qQAk5-pTlPmSA22Lux9$Oj~iu5oJkdMvlM31*gFjg80f2n2KFQ|D0;E)@7YEe zfVl*KzRGy0b={YM{}^cwPocXr;fePSFu~O=XVqA znM^5jfAuE_Xn_<;{YYMuFUq!Ra&waLe+NwFqFG2E1ddtUOd9=Yp+dA+Ucv>3o*?1E zrb|*a__(q=uxwA7i?_e@%$_!bWZ&$1HEZKoBkAE8n*8BZBYv4OD)I9WPC5?tH-LXr zAJiRJ4j21d^OxKuirn79>&&>lbBoj(sr%px0~X~jCT`s9O0e+a=Z_LTC47O56gkTA zywi)E`slFUx>Jtv-0b-18_Bl_SW?3ggG81RYape-u@ZN~b4NMuf9qZ+;N}@=i)R>q z-@Gb%t8k4vw_BRjSHwwi>cnickEc#=>}S7mDqMdWc3vi%nk!)jDeA|byiCSidQtl5 zc>5=J!(n;j%7?;V;fp0#L6@z;3gu8cE0;IKV3xdp^}I9)gM-vvn#-rNEZ)@nNm9y( z?vI5(nC<;EU;E>Ig|N{UJ^TJ5Iku6{UVt)b$9cLIKg8Ys)3>s3*0?M@-|dX3VJ)h0 zRNwf{)9Y1wk*LNt?lS|otk{U>^#A5rdmAEVl%3Xawd#_tEv?LCt4e{-;3!FiYdz&q z@Dzz0Q`7<6zqD}e!pSVX1I+O>OGe|-RbW%QMavA*`w}~w%`kfLKnzxzuw!P;%hRae zo|6iH^h{cu9&jMdZ|vYSs9V>Uyz7rOQ7j7Q&~+WTcu^@yA}~{EMZnxQTKpSFq)+5^(Ffko~&e6A`$BTg6mv8<&^y(?kEVG>t3pu;EtJniyz_Fyk@-^0+L7GBG_@-t3kSuLl|96quhzWN5#nnIY;|NPsR}) zzEw-%gL6q_vdy6wr(Iyx#YE&m{Op}ZCu-2cpBomHKSK)#bZ@u-i_0D?CBb{ZBjX## zQSu9+OCN@*sk#2vI8qx)WQWXv5N?x_VSl0js#pItUWzCk{e68*y_RkixoVNNo_bC@Vd7 zux}$VtcSTdn)SE2e>ui!rXd1bRg>KsF(C&F)3Q_qsfw?j%3eCWd9L|%-pdXgM#z$l zXJCz+m?`4la3rdAp>&72I>-v!EPd5L*(wB$onD^RS7QFlfVV)YSBvv1%UGdOYkoR& z&C`YmMm<#SvW8Pxp1{?cFWFRSuT2)}vEm{&rI2IiD~1W^6vi(qY^Js+cjA6>p zlcG)GGT)(escx)8#PqY%A`2$a4R2Sd+fw^g#*w&l)Q)z}N54az-3Cc=dJU7Z^Q4R{ zkGE{7Y?FMHddl=GId+{U{I^i&V+X$wtPgT(S?M$%1P6FYx$Gj#7JjW56RVZ)1 zjMbuCIMC~Dp*ij}iM!#SMcq$+FPq2Nl_G^rTKp~{;`12TQrx6MO;Z@hTc!*^8ba0- ze>>=O-oMq4pyzx?PD=hos%i@X86chiKAS;4*$R{F1F$0>isPp%92n*Jp80 z2_M!+cy6e`l|sRSNI~~F>d>Kn=Ai~Xp0{msUx>7p%CJ}03FQ6InYr2^G9g54`ONi~ zroZt~wEYf^&VBvh--_!g$Anxf;+NdV95S!3Vr(O9>!~)T±JV~w(ThIDK>wg};C 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 X{r?ZpP_kcw2Ot$CjR&O)ra}J$c_$^Y diff --git a/osu.Desktop/lazer.ico b/osu.Desktop/lazer.ico old mode 100644 new mode 100755 index 0c894dca412abb8566e630dbc82397e4c79395c9..a6aa8abb9f3f10a2aac07c1168d9a2adb25ce1ea GIT binary patch literal 86650 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

@r7l@_>dLwGP1inIvgp>RYo9-;{?Vr` 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 V!WImv>?mfrbAj*puHX3W{{h`h-3$N# diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json index bbd5f4f3ba..af4b103867 100644 --- a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,249 +1 @@ -{ - "images": [ - { - "filename": "Icon-App-20x20@2x.png", - "size": "20x20", - "scale": "2x", - "idiom": "iphone" - }, - { - "filename": "Icon-App-20x20@3x.png", - "size": "20x20", - "scale": "3x", - "idiom": "iphone" - }, - { - "filename": "Icon-App-29x29@2x.png", - "size": "29x29", - "scale": "2x", - "idiom": "iphone" - }, - { - "filename": "Icon-App-29x29@3x.png", - "size": "29x29", - "scale": "3x", - "idiom": "iphone" - }, - { - "filename": "Icon-App-40x40@2x.png", - "size": "40x40", - "scale": "2x", - "idiom": "iphone" - }, - { - "filename": "Icon-App-40x40@3x.png", - "size": "40x40", - "scale": "3x", - "idiom": "iphone" - }, - { - "filename": "Icon-App-60x60@2x.png", - "size": "60x60", - "scale": "2x", - "idiom": "iphone" - }, - { - "filename": "Icon-App-60x60@3x.png", - "size": "60x60", - "scale": "3x", - "idiom": "iphone" - }, - { - "filename": "Icon-App-20x20@1x.png", - "size": "20x20", - "scale": "1x", - "idiom": "ipad" - }, - { - "filename": "Icon-App-20x20@2x.png", - "size": "20x20", - "scale": "2x", - "idiom": "ipad" - }, - { - "filename": "Icon-App-29x29@1x.png", - "size": "29x29", - "scale": "1x", - "idiom": "ipad" - }, - { - "filename": "Icon-App-29x29@2x.png", - "size": "29x29", - "scale": "2x", - "idiom": "ipad" - }, - { - "filename": "Icon-App-40x40@1x.png", - "size": "40x40", - "scale": "1x", - "idiom": "ipad" - }, - { - "filename": "Icon-App-40x40@2x.png", - "size": "40x40", - "scale": "2x", - "idiom": "ipad" - }, - { - "filename": "Icon-App-83.5x83.5@2x.png", - "size": "83.5x83.5", - "scale": "2x", - "idiom": "ipad" - }, - { - "filename": "Icon-App-76x76@1x.png", - "size": "76x76", - "scale": "1x", - "idiom": "ipad" - }, - { - "filename": "Icon-App-76x76@2x.png", - "size": "76x76", - "scale": "2x", - "idiom": "ipad" - }, - { - "filename": "ItunesArtwork@2x.png", - "size": "1024x1024", - "scale": "1x", - "idiom": "ios-marketing" - }, - { - "size": "60x60", - "scale": "2x", - "idiom": "car" - }, - { - "size": "60x60", - "scale": "3x", - "idiom": "car" - }, - { - "role": "notificationCenter", - "size": "24x24", - "subtype": "38mm", - "scale": "2x", - "idiom": "watch" - }, - { - "role": "notificationCenter", - "size": "27.5x27.5", - "subtype": "42mm", - "scale": "2x", - "idiom": "watch" - }, - { - "role": "companionSettings", - "size": "29x29", - "scale": "2x", - "idiom": "watch" - }, - { - "role": "companionSettings", - "size": "29x29", - "scale": "3x", - "idiom": "watch" - }, - { - "role": "appLauncher", - "size": "40x40", - "subtype": "38mm", - "scale": "2x", - "idiom": "watch" - }, - { - "role": "appLauncher", - "size": "44x44", - "subtype": "40mm", - "scale": "2x", - "idiom": "watch" - }, - { - "role": "appLauncher", - "size": "50x50", - "subtype": "44mm", - "scale": "2x", - "idiom": "watch" - }, - { - "role": "quickLook", - "size": "86x86", - "subtype": "38mm", - "scale": "2x", - "idiom": "watch" - }, - { - "role": "quickLook", - "size": "98x98", - "subtype": "42mm", - "scale": "2x", - "idiom": "watch" - }, - { - "role": "quickLook", - "size": "108x108", - "subtype": "44mm", - "scale": "2x", - "idiom": "watch" - }, - { - "size": "1024x1024", - "scale": "1x", - "idiom": "watch-marketing" - }, - { - "size": "16x16", - "scale": "1x", - "idiom": "mac" - }, - { - "size": "16x16", - "scale": "2x", - "idiom": "mac" - }, - { - "size": "32x32", - "scale": "1x", - "idiom": "mac" - }, - { - "size": "32x32", - "scale": "2x", - "idiom": "mac" - }, - { - "size": "128x128", - "scale": "1x", - "idiom": "mac" - }, - { - "size": "128x128", - "scale": "2x", - "idiom": "mac" - }, - { - "size": "256x256", - "scale": "1x", - "idiom": "mac" - }, - { - "size": "256x256", - "scale": "2x", - "idiom": "mac" - }, - { - "size": "512x512", - "scale": "1x", - "idiom": "mac" - }, - { - "size": "512x512", - "scale": "2x", - "idiom": "mac" - } - ], - "info": { - "version": 1, - "author": "xcode" - } -} \ No newline at end of file +{"images":[{"size":"20x20","idiom":"iphone","filename":"iPhoneNotification2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"iPhoneNotification3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"iPhoneSettings2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"iPhoneSettings3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"iPhoneSpotlight2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"iPhoneSpotlight3x.png","scale":"3x"},{"size":"60x60","idiom":"iphone","filename":"iPhoneApp2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"iPhoneApp3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"iPadNotification1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"iPadNotification2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"iPadSettings1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"iPadSettings2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"iPadSpotlight1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"iPadSpotlight2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"iPadApp1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"iPadApp2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"iPadProApp2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"iOSAppStore.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}} \ No newline at end of file diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index dfcce1297b8ad9b84ca073334fb12d949c51d250..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1237 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 Y2YK{MGIEg$@&Et;07*qoM6N<$g67-*fB*mh diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index 8a21d9f81d2a2c0f6b8658761476e32ad36565f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6457 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 T58IaJ00000NkvXXu0mjfwzQG) diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index 4477ece73a546a35bbb5abc8fc20c1645683e607..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2250 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 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png deleted file mode 100644 index 0f8c36a03870c9e7c0561fe0ca1e80d9fb7446a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10842 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 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png deleted file mode 100644 index d563e8cf5e44bfb5c1dd733564da90f9379defdb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3602 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 Y2YK{MGIEg$@&Et;07*qoM6N<$g67-*fB*mh diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index 0208f80e3bc60c86225146f78a3497db63738b23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9677 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 P00000NkvXXu0mjfGd9th diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index f7ad8bb6bbbf3adf4610e6d613db4057bc46eb45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16681 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 BAs_$% diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index f7ad8bb6bbbf3adf4610e6d613db4057bc46eb45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16681 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 BAs_$% diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index 3d85a133aa71f1e744c51c96acfda1d19f9edfb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28381 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 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index edd53bc9542a7dfcb242f917db19752046a120df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8946 zcmV#q0ixo6nF z-~Nr?-)|pr-g)oS{QoiQAtxTt`rYwQYyGaT{X?D$pp<&o*S^zdo5?>>6cL6Y08&aU z%bN8~!Z1W@jSvE@^*g#2AP9n#Xv?xN3}aSAXsro?04XI=6k!;~tgjV95JeF|5CF5M zStbuon5DHwDMb`T2q9*?fl>;sHHKjzrA#L>n`@<%DWj#77>0pTD*c`uOFqf{TM0G{ z10e*aX%a=ztfgftn!_-hao%R@7a>F{C9_>6t#wLB7=|g))15D6Yz3ky!t*?8wHm(f zr_UBb;5bftZ>2O^$4oQ~1Ix0oEGuQGl#(C_#?5^;i*-A*VLdisC^H9Su z2!bH}KZ+tu(;PQ}n4#c#K8;2Lt)WoJvuM#G7A)wdyL$oi=FOwCvx7pRfNk4Atg6*& zm7$>_dV700c(8{3kBYooT#Vno|i&R;~5oS#!Oq4oaz1 zMSzrnl}ZJzHQn9aoPPQ`)~{dB+O=z0xNu?0oY@Y~^Eh)ANtS-*|1>)rBZ3qwHla7iKaVe zczBo>UU-4u{N`a^eDOu<^*Z@{KAppC=KW6S9mlXgbR_nmTrQK%X1Vaf3%T;jD_FgH zb$ZT38xwdw!B7Q%u!28aA*y-kASP7WCRQPXSval+0zm3W{*cfmrE#_lOLRRkz7vOG7&ICU!Z76g^UvqnYd_7(l`G>3M+#}g_8|;I zs=Irsy>*CScOR;E6jAXB%XM@RBD6pt01ZN5yAIlvC`%CKZDe;5`-HjV)+{1-LN{h} zF0Ielv113{|Nfmk@x&7thJkI{<2>qYhf*qaV5Vu#j$y6wN)$z@t50H<#CQ%553_99 zGOoMsuQ}(Ob7Cfk5r!EPR6Tf%k!N?{y?PL%uZj~1EYrfYEtCK+@F688o|4w_L>=2E z3PMy65(OcC5a62{7L;&KUqbPWRpb}Vne@!Z9(#=2Z@+_s2M^NL)DQ(wu}X zmSxS%Fo>nX_kDsONLMTgFqKl2%VjRT^irv!9>>6$YK zw5GqmAK&-KMf+0?KL~JKhhm|KH(I4nSIK|my>y&+3Zi8ZpLpU4zVVH35{4nRZO@p4 zw$f~xW-OiW#7idX;&~pqT#nmryOp(T*An^xrfty}sc`6jJ&Jt!5ZQc=T(N*S^{xNfw882f#b+tQqA0@m{ZvgRohT*ca+#ZM`U>mU zzc*#p&>Q>c|L#My;UHWK9Y$%8=(=vIMy~6os@1ASF<%s=QVGLxK+5=I#D7iKrC2Pc zM1^69X_`|e`G#ST&1Tbcb)>*G>BJ@Y=Vz$y8e`h#&6~OY`s?ZM?@vAAtQpn{btID1 zsxF2RyXR}JxtdEZxr8uis^Okq25*0al9fSQGWLMYkuYXtWQ5Vt(bN-8rCL%-eBWne zV1SXKAw~uV89p|^$lxF&gM;b$i49F+zt$vQYfUbjo2+6=qby0gk-`7|v(yhY)iVgW z>Z&Wb;);(jJUon)a#rxpxVtA3Fzy5?snu$%S+j=guKR0L6k(VqjlnW~xBrHsw$Y{p zHD0U}*X(&7p68|BFbu;f)xKJ-QmIs^lq*yNkA|(O`W}_hGPPPQolC1dv~7DFXz94l z)aun_TAOmH-}x*-xfV-kq`2|M8(6h!74>?3b{JkloRo50Dv-GFWCAzdcms~(f{u^% zfB$iE!y&llBxX%qfJACjLvP5IsD5l=q-7$!kj&;2nD_0gan>zH_#x6XQWZ}nNC*ro zwvSqCa=F~`304|hlhRN``A5&A1?hD+-Sm|-b($5!fE1XsEGu0(DJ7$$qg-~`pK{u1 zrxAtmwqJiZf=v&SS< z3NQ>r7-s__Y}%}*DheUcfNlg>A37Pz9?^^Y(ZKM?a5HJ2f=F|WObr-@p#F=OF;AM0 zJFg9`G=K3IpW(?TpPbQ-O$sX#6_ip^sZ_Z9^2_P!>Ow1x7J|`xUm~Lnl!%F+h^|gG zgb*M=YS1N@!l%!o^wBeL=az5`3&(YF90$j7a5FBJFhGDM4IIZMlg-A@K|>HC<`u9n zIt6jb$@o%((gc1$y-Dh+!1rlH0cJH~ zQvO<{>xwHr5+jnPLFM)R7;hZK$T^^NYHVi%?W#y2ER*o?FvouSEFx=TUvLt-?vEjZ zQUC(oRC66h2q`cv3n4&Ai4GLj2iJgr(VskzSq+euK_-()N{<1he359&+p(If7(zeioO7sFt7&m10S6Kqrev5>3fs21 z_~MJu8iXOKzkLL`dk~Sa$9cup5?fMoOF!swYL3=u2~H#!xa(=KP27u5Mb!gD&cWWW z43V+WepA94A)+ITxoH`p(D?NRnM+S2Qi|HoUn1vZ&?2@`X`(EcLxF;k2cV*i3+1Q26LQPrIl`a;K@u&3eHkWY|BQe2qV-4zuO!0S!+%^ z?NnB*SV6sB2S|%MiEvC}m=FTb^Vqz3b6iCMf=V6z=24_$PZ@J1QkFUZA<%w^XwSyK z*Mm6KNme_EFqL5Rr_U2Me6m+>Alx^A-#?1AYHmz0po0i=)g0X>5CVTkFLI;-=JduraR5R}bfl04mpT9CGTN`d z5Tm<<8m*@U7zLN?g=;bTY7G43IjmC`Vy~Ek_sRjxljftFi=w5#Sk_7X`Q2pJEx|lt zF30}$No-$}yJ|hMkRehELmKF^hqI=ejvFtc<8Lm;Skyix)6yKaiHKkth=D5J&R%5m z+)bM{;y6wk`z7%yOpzM-zR%pbb6LH5ReWDS>>j{2ERSoTjuOxTrI&>JJD;{CHL;jOz(($RYssHj7YCZiF{`?I5R}UcP77-Z>g&RJIT++eOCtjyft2K)v<27O; zB%}cYfxrE5dhEm#Po%T6BP|rS#&P2U*Tgd{U%rf7E|(f?*)xL7x_Eva%W(@j-eK&;ofu0y>Hn)cng7}M!@7m+zu|{u4phioa0={OR;^ek)}zww?B1GZEbBVS+bN@UU?s44ONjtbxg;`AzqmTuAK@7LV!RZER&*LBzU!t-fj0Xc=jshfAmZ`|MQ2* zKD>>A|NSKU{`RLV|K>ILgB1quf05#!oJyl-5bNXxXg|bVyAW@GKc&mobM&6y(Y|3d z)`w1J-{=38f-mX#>ZMqxFQ#&2fZ_kM1^Id}?N$aor;~c4F(tEFX*JE5p~95VUnLx^ zVU%(RVEOXp{Qmd9pClA1!xG|s-)HgSMPmZfUqv(`a1CtBrd%#J1!;z+53NyJV-_;B zDUJ8&F7`jWoBU;`Gw+g(Ec)Y>^nLe1_I&-vEdA<77`pozbjBik%HlXM*5E9igELem z^n66wBYVXL_I~+p=B`~%>9gn2Xf!x>*Au8Gc9Az6>_U+U9S5e(FlV}v7=I}x!jj0k zPjsw;QOW_ZWXX~#V@oq3KIw~a9EbVyyT|ArtRka0zA;S`(=@46DznP$AqMd@;I!q) z6f%_m^?7#Pzm@h+oWKCA|g#>OWObTQaVGZKmHc|zu3y# z55LCTKRb&Bn^wfhwq;CiqR<-YSg0VR`=e(u`0_5wH*TS`qm%Cc_yIV55s@qL|KUO8 zKoom&4W?mWX+;=>(>87hAqYH=P=!SGI_|(|`deFD+mv~7+U}G@%eHNk&1O^DgOMtJ zwTciSsIgXo>FgJwihCmxrU`)%pvn>ZzI89w+65HfyMp=WUykY-W_0Hv#L5LRMwZ-T zJXJB%ER(3_A%`0*{_KTBIg7r1N2%Za?}R)1$PWcrT8{IHT5D7kPTT0B5!hM~c_F&$ z5e-(;-*UO!^bCWsmc=CYNakKISMf$iF|?Z|+*5`XO=ii?JVsYOPH!R=C(@C^2o=U~ zgW7}J=zr)92IdwpR?K1UCF|1+AWpug7)_>Gr5xGKD>?SN9Yp&EG0Hw!X<~KHg(b$6 zl4MRkG~w0)D+=*PsyK@}Q~IWB9i6fRaeN(4jJaSjx$HD{u|(AyxSN(y`pAYErV02F z{=g_W7HJ>A@hJlhZby-YA3kH|`@hSPboxv;CNZqFIXFJUXu9WSN6mCYYou*a-Eo-e z123Tc5FP1Q!a_yl2Sg1YUH6IV0YZS`Sj@e6J$6TaMz5RvUfzCy!7bZRqxBg6F%5)m zg3*MAv`Xs^Gk2Xe>6U_^T%)jgHQg8f5isUOTX{1j!-60fSH72-W{2R69d8;O6LuaW zcb}YS}(V35p@hq#uT5EJ`kv7yQt%&+Z*>&qLX}oq2IqcDK z_8OM_)g?5%21o9Hf$mE;rc7^6X8iv`a`5iQnS0TDnRDK$4BYtygI~ReVqABNE|B~9l4ZYeSLi?95iieln~t0)05uToL2`C(l827wP%sbCe(0%JQ#VPXBXn(f*$07+I%z%UHCW^}b<7UfW05@M%212Tuj8 z`o=XhzW*${|I1IP*qXMlUQFjr7h`mnh(_wMgte%4Gy$4U=09fN1R~O87jz=pvWTW! z95}F_OeT{;I|*Vjj$sL$v1iYoxU&U;v`x q1s6C9c^_cU&A_fDRS@U>S36fzJQ* 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 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index edff3788f08b1e096269fd187f08fdf65594dab1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25862 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 BVm<%> diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png deleted file mode 100644 index c04f6f3ec4965f7b06e29a1bda5b8d5fe27ba72c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 251219 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 ihBCBv)8__?8cC&XLrk0D^;$L%D zq}FTyFI5bD6of?v5C>%A=h|NSpUuqppBGlm3A7RMY&F@}qJ)QJ_4K`KH%5E!G-Vt2 zBijqx>1&RKL_?rol~jiM7kL%dq%;{Cx*J@m?d!Y{rNhm}7lvEsHK2ZLQmY*Sw~#UP z=FBt3Mz%$O&7u07TAaz14GEYJTXz6aBVU$?Ix{g&NZ=8M;$uW>6T#%)t)aPULvcDx zw@bMXwb~8EcCWKSuToVH^>b%oCIr`KxktQ11U5Uko$e`dcyUmb_vn72s{ga8*qM!$ z$pA>g!pXrNBs; zE0w%{hJ?lUFm_#7*vo2-m)|MEw0+K7WId)gyUJ%k3^T<(1YzY}9geF;hKIAw2ju{un zA0Jks;?)mnYlHX<O2m$B7tDTT*^n`q578;YjWaBMCbbLG- zoiy5b?{`VHZ)j+RYi*@eO$x!MMz%c7<7&Fzn>(`%E=GD=Hl$GN>3q@CndiZ^<9wnf zDeKogg*sKH`Y!&-R6=hosSGxOuBRfSf!>3!PsV2NwC0{2b+`_noDI-tpqD15CWr<0 zV@PqiZaG`uEJFtrN^JS6)q^5SoA2`fdibx!Tyv()OsBn#R+nI9sXimp_pfR}dl! zgw*rpJ!BqI<=o*AYK4-mKwAiV0zcfVK4hy(E->}f?dN6$a3-(9Zz7AY` zXl4w09EHWQGH$#%-ZZ7B5My_GOi4ksa*Wa>gtLc*LSVj&#ySf zJD>T-jDR$83bOq(nA`gvW@w%p(7ntzdPJjE#8+KZY z_ZKlE5G0fYG{3pi7`(+p!2=2MMk{u8hCDe@y=|XUzCB_Uu31 z{3%X$^TG&{I+^X@D73ASZMM^MEl>vR5BdA;qX)!a$f@zs&>W*;$biOS@XQ>^=zU z))J=wT@2#O^)`sm$Cro%HwMIYNv<|7xi&^e+5Sxa1y}Uo)j{|*%ti0%@OzI&Ti|Ym zl;Z9_1M0bk>PDb!?$7A-X zy883)qq1wK%$-1Yk-wB#3&Nvow zHuta)zOZ~(y2HaN`UsQ`SKxHT%nfI$mU!l}`;xzBm z9(iBvXNmq%@JIVN<>DZiBT?hKhx>{KWyMcLZ;*PZbrj^}^PRpTuiU{(tMPy5Zf|Kx z<|7B@6Y=b|l(HRM{ELGdzNT_fy?qbiNg#f|Lc%(B+^?~f!f~BCy}xQIo2`S|p!J%8 znjR?-e zO9w@gUB3rc$2u+oM10>)TiM$;HbJjYnn}rj7mB>_AUOR%e}q`oRK>hhYb8fhH5iQ+ z)e(BL{jD>i;b~WKz&v?HLO7&9Dc%AAG@~<(k59MBvr)NG;C#6<6N>UpcuC{-*5p3@ z?8F6Al8kP@ca+NgPowT={5hN-1XDTbXNC%y3cg6e%LfxUGlr)aOcUyN z&~p-peCf+5;|$?MPs^7cqe4j7_>L*brDC9U_hXES3Ki)-%EB>BHd(=^man%4Z=!{@ z>@fW~7k>1~^`;BBScno6U!Z6->nnPtr`|1`>bH~8l{6kpRh=Tlqc5(4Z+lO|uUxk; zMP#9$(oAYSrC31TSL8ZwliqZn?ci`%ehR`&lMgJ-gVN;KDr*RBX^o}F-_zyGOT@8I zQ;n>;XzVs70T*>z(!l%Z*XIv{$Ck8mVeEMy&a;W1u*-@UJ7yyzlnxgQSzk_PIV57p z&}+GWBvh24%y|3?!_xM*BZP$C(CZW_dIq$a#l_3Lzww(E*A<%9TAGCd>Tg+_3;J;8 z`=6^bc48!`w%obL#jPb$=yp~6AKN2u^WXh{7{vdYRL-Y}7&XR}BjfUA1Z=+aOKOkK z4r85LYD7;FX+5sP>*nL?PCW{8r@_0zfJtzryxpC)0#%nljyQvYui+ukwIbfg){Aj&b~FX%45YTz}yfK z0i_;RQfs@5`7-+$3TK+I<9heWO53Nk>Od1aaUaW(LUV%)JiL ze=C9W9owHD{(4GWB?b(3L!fz{^*N+wy8efaX^Pb2HMapVcXw;^q>UeGF{DRhZ8rw% zvg&04z!bNr-Dn|@LL7~r(8dMRCmuV3a4TDWE!rTHTH^as(We9e2M7dwz?TCULv66v zM&T) zkCc^)F6j9l*nnb=1dF43X4*XNSAIF=s#E{4dx#pkoBNHc%Nsl@G4^ISCQt1|xWx8( zKSgnxB|(|&9tb{$)1y~#zrZ<313=%62}C>-=i5Q&Oxx`Jck$Ev%`@;D6|Ac{E+`G= z(|@PccC1J;!T?4S#Lgub;_SD4RRst6NQsG1F2SRpk7gq-%fZz)Be zp0Nh3fkx8X+gqMPvN46+VM(~N@3Jlt!GE=B( zCDrzWp_*uSzQvBhw0;(pxR>fI#*drU-mEg!tH^z5bG4Kl#3y@A5{{K&EDe`R5c{qAA1OmNDL=w1pI`5`{HWJ~}=8i>k$jKUqh)gDV;B<`S0P=b^o~L5&X4bu8SQ-hBxjkZ!yZI3wCCi~x3R zv=A6nC*9tL`jgAhiT|gnSKI>aeh%{)#_AMud|m~_BA4PkJdC|o5>YrcV5CjMo;yL`gZO$Z0E1{1+a(1b+&!53~Mw zebPe9r?a@;TtZs0B;!Zkm+JAQr78KEL2^VPF&jVXw{R~EGE-2h$_X{@mS;W204U2j zPYV*~w4Z27sCv^KIu9Nb2G@f3PV*hyd5%gyzomLxIE6OVRla~J=~%ShK=JqO$LnMs z^B)`G@J$TOcijE1zDU*5SAJVtPX??cYu-m3miL87V4cGruS%OR*;Hi44q;f$i! zNn*dVml4?F9-a_Bvp6eTg1hYeH5mkob#y1Fe)h$xA` zg+3!L-cWT()CC+Rr$#j8nSFcnLBLTFO%m;8^~y|_x7NfL27==Mj1X@oe+fY!m>eQ1 zn_L6z$7eeegtQ`WhX|lM{XC3#*AX=+$kAUpn>c~!Y$%!)8RjGKnSk%HqJZaYr>4Lv}KS z+K7DS$UNs)EQ-VfPQ`GCdP~;EysZv#!=(3Z*IIL2ILKhR@=kLK#`aS|x<1&7c_Os#Jr^lI}*?!+9 zR7`?b#&YQJ`ulp%?I-%m}aHm2X)o?U46xS2P|2*AJ#L&stOL5sK;pBRh(rPy9 zH44Ph9G(@`hQgR5=~SFkLeAU6W0@k$nCcO7uGj>A*wiO z9E166?D#in#F>Fi4HIc9TqX~Ug3XA7z{kIO?t$xSA;tCyHgi>MNeZ2(<5LSI*eTP} zASP_MtCpxjNO{*v5|LF*S+17_6(Ut@(SI}dA>kb=R4qA|$S5RY9TzhowIZpe)XMBv zKo!{>$J4wRQ={F0ibt3`_3BweviIt;a`3?{J3KC@{EF{eR06piDlHL&*TkeYQ`Bg@ zHXR1RVU(o>uzm!71Z15&%%55b>1J)bxnKy(NN8}`MX|$Pkz-l|8^{5o@&3nzRze&P zV{Y8Bq;wsvI5;*uUiWV{ds_5zsO*M*xz75*w~Z5IN^`;T7x^1uO(u1zEty zq1+G0LZQ{2Wj&7ND^o$jGfQqWKw(42hJrv6 z$nv1VbxcF_t0QsMTUCPzP;ro|)}17h6Du(=o>(a-x*JihW)GOc`kFDD3m{Ms)-Yg_2g7gElBEiY2obfc{NzQzRodQ_IT z5DKFu9Ew*JZPDe0KI2)eB{Z1qd7HLp8(L8#v*C`x_zMIqb>mT&1j0QNU6@xSLA(_vGMrTPnw6AiohY{io{h0xI+YW?6&c z<8BlkAncW(9JNO^6ag~1-j z5kT~Z!PGY+Da<^nIhFu2(fqx0Z|a!K3I)c^3vuCXRD2!#ErGRlECOB;y$~Y&ofC#K zDMx$P?N*xp^}ozhcgHWEO{;AwR^8`Eg2C>?*F2f!o{P~-Rn7APkvtQnzWeQ}_ zkhQ*IMej97gC&&pJ{2_yo5BVzcKA*jB8RfWelc)syk?2Rvax%saw6eS=~IgWl$LYl z*~VQvXE_s-NDC3>O6~T`Cp7H2i8Zhu2q?bA8x5Fytn)CL{p=!bmZobfZZBrF{_?1onameksK&jtr6pY8^lAcYF9L)_O`x1V)BWWMZR8C`_~OVJs(%JP&mF zNV<294Ce&WH_3^xYZ_{IY)JE~i_%lZarITm0RdZWL(XJqL@M+n3dasgKRY8(wfQDs z=|km1_U)!n><0;&A)XA&i44CHe7GuW65|Wz-Mh!&$j%Y@L84MNdTx*6X3Gx|2d+IJ=UO;(kjtnOpB+ zTB{jsKJi?;U9oxG&UW{EO!cfMZ!~+whH*X-^KX*cdM>}38Naj_T0MvE=Vwf%^x}nl zu0jR5d`qr0b)EBQi10Ee5tfjqucRTEe4YRK%e4xm(}3`|_+qUDST^@3`s8@U9D!!8 zW~`Lq>k*OjzzUJEH204TCzK3y`=LcR8J%5mzp)4a{uvMXR-&AY=lkjweHTe++HB0S zH>g9_E6-4X>nOcuez8^czx7 z10NDJV-nwgjDsfV=q5pZs98TZFjmI%e^d4xVmg@o@ShJwc^02KiB#fnjS8(zS<&($ z({V1i4l?=p{auLgpH_p#>r0wX#!p+-10lRqEN^n*vY?5=>~15cBSKo#BM81(u;;5> z>kmjEY<#VI{5K`X*CpXz1*k6@T3KR+Kl zv;hECT+0sO_gkmh;Bcl)ZYXd*<^-l9azIae@yC$Nwwgi3Q%C*aeREbP!d+en#?ON- z@kOxA*w9O;>6j)<_m1gFwD~|H?%}EKYEANs{#+*Wr_l~UzVgM`kQbgP!B>D}92&ju zq*|VUrUQf6$(v)Jw!6zEvf96Pw*7v!T<&War3^F;Z1IFK%<;q>g76J22P{EUqjjF{ z?$1}hey!~Ao@JeWPEY!vHnXDE$kry}{~PcrE9Z6ixY~Y|vUZc1N9L&z9*<}B^GA(p zWJ6ig72I4Q&9?|IY%#HSlyMi{vz}KrieQXTAS5CpRQP~bcU*l?;ZLc<#`|}Yts{Z4 zwe$hqQT@K-O7wMyZcmGS8MiT+kC5XCi<7^%>*Kl?L|)2Kzw`_m{D({FcScgiv65JKSR|beyYM(6Q>cx@59etHa8SQkli%zS$^m=MxN7s~b)v<zIE9Ez zgja@xtRkM>4?OP<>!#o8ED!NfJ~|-MaOA#1=Ty=Y%aWHZ3lrF>*w72)NEl_dO8=c1 z-d=1yUFd~n`~LI_g>UX&#_z2y-;~SV#|Jt`u$j%R{S>1evH3^{(Er=r;;)d?t~Dm- zI2VHwe$A>3cD>YnV^#5Z825MCW&C)dZpi7_krTbC4E$>Z(fxVVX%cOv6jylMnuE#v zbwn{qfnm<1;-I>UI>*h{im|7oB++jtNz1_RX6IyZLJJ(e_A<6JYsbFYC>e7=xMiwq z)br0KwNweaHL5(WbcSA6%O1T<&n8A*;$nCFd*0;m(Dk$tlf5iUdS45ttBa$py1E2; zM0=Z?8RY$L_E-RW(~6r4JsB4A!_h>6ePBvXAF~GvBs?}Lh;5wQYwzX+_X8CQgcY;M zeeKdywK#Y2KYb8YP69DnLOyZU@h=_oYPF?d z#M>Q26ey=@pGA~c&Nq{~Yrp=I0Y0_z;L`;S&MOT`Ra#pGv;KX>->4rQ&}KDoum}=D zH!HMRG^t;wCFr>)GMYy&a81QfI5a2)R{G=bVdVPS}@E_l*XFNx9 z=WuYp1T$j9E>#NH^3p9eP6$iJ3MUWYr<6Whr6Z%MiI15qd;9LcqTG?Ewz!jrEAjW` zAuJD+u!oNqChy&Y zw=pv@XW0LYwljA%-rio!{l@&$yJszL5Us1FLj-MOnUN`R5c0_bUxBl+Wd1378L`!j z+qd$b&A%i}2p_Ab9ecB{`!zE5XWe*SL69Gs>{5MwyR?|Ob4)bj>UFA!%4%;=gEwrG z1Y^-HDqRdu`-`Cf@^Hhnk&u^ALTsU1&ETXddzcX5v7zQc&njBFg zY9ZYv!KBzrG)MNFUvq!Wcw*VvyM?S_MMTed^WakS$E6P*;vW{oXWp7Q+=o7koNH&u z;Qanc8td6}QMbbh^g0sL4mf(!ue=bi+Xb1L}VKaZ37fBsK>t6|xg{SVK@x=tVWB99n{15E@tvw=kSBW;5bVjdq3$-yK% zXvwTKX`07j@cldT8!vlm@>^5!xIXyrL$+xOm9CSi6>c z1)cpcx{8g~;HQ6h+_76pYN_#Pb#J6AJ%LsE`B^HR33+JMOV`^-ER=4dccLns$zkJF zVESkMi<0$f_)wU-Sx0nR+&H9x7;{zej-W`qI zl0hXhyiA`~+p^VlTPW-;7PuL}NDqAEWSU1iqQZYsxWiBMMwy9%hfu-R!f+|fDOxe2 zBARY}924RCV|ia4DV&)V8L#|@M?Pg!0-%=|C6MOi_Pr(My6p7{#UsOGw~G{Q5bJ z70gj24#d?VzA`vgaU=El@vRj^0}2L&YRxN=a{ZozG&Ew3$3HFJJSFUP{fQFvyG71c zL~BamELd$3wvKg;yqoSN&ri{kSuRt88H*Y^7=iA{X988hhk*%J-++lhYXMK&g>POU z)-4z(+KS`KL3=db={lByEu8B!4YFq-KUFj$=N^oJJ3?{6=PIQ!{dbfm=TxDgq z*ZzB=`e!%EDzw>p9ifE)b5h6qj|F%(|3fks@Ut-P1pX}T9sh?@%prDodqF&=-ri(O z_0%!)C0PU$1(~$c<<;JPR-=VQEL2P3A@T(!x@b%Ifd;#hn}l-}ZQi_IAAn_5eq9p+ zcnJ6yi<7 zl-FFBA?1h#Mj$O_jEVn||D9$iW~YkPR_%AX-_QRnqe7Teb=1jTY$X80HG|;vfv7bW z)Z&PHqEKVg2uHe4Yh1)QV+PqxDgd0dFoTl&l)}1F$;Yp-&yk`dW+)<$nZx{DgajWS zpH+3UF$x6jy~;+K3q7|};b9`Oo~K^o(saP6MGJMvY1w_RdLV9aKI0!o0^JJh&mXS{ z{BRlYYFr5~9GEXZxL>&Tq2vWanJJ#GHLO=GlY5`4>JBb5eNO$RuBo9!ad6jTtSLHy zRj~CEf~Z$PNUM3iZHs(yvQeUx+)Kw-MN`SwOG@1c&@-f5P#`a}xgfwRoWE$d*KW_M z#s=W0|dQQA3Ml`xd6;&*k1wvS(4o(KXZES|-xa`lj9eShj>iLP40yfd*2>CuCB^ zw4QKkR54>&q~N1YZty_z7TJlA*~NMNa^q&{K7UInT;4m!x0u1>m4_{>F?g$ z6!5VUzK-5`+P^@5@Bk165x=qap07<^oYA!^WCr#0sumL{S2 z_FzQtlBvL`Tf{hGg(lbja;|CWV`Do0b2x!gvh1q+{ey5e`C51%BilH)?4ZTP$+mchyN}?Q%F!l*{BK!<#BBBvYpEOg-i8iFCG zMXP6r%jrdb{3|tWX5!su{bfI^EuMQA%z8HH+L@VzhZF5sR-lFFF-JHsu<`Po9aVSz zJ^%IYzo&4j54}k!?}%~cGDt#ewRy6dD0c0BywHn%W=UtjJ3P!GUnISBYhX zT2~D|6letRi3Zl&6Ksj~ERO@{&)q%j4xJ-x^6KEJ*46GG{}78$2$x&7_f zI8`aqOrGK;od&bVAf)$_lP-Aw!mMwx=C8g0GSRp&zJUOnmwSf)$JaUM&j{scpLx_5 ztO%-x!3X^CM)jbW{M+`JlfsP{_S)xt+@G#D!g_0VE1qWjx?+bUsE~vH-`Mm;AMws2 z-6%{+b1%5iJU;8SNQ9FQ{cV>=4vx#H(4*k7!;Fd!4y=mNUww)#!h(@!{A-%Pq0PL|>EO+-C?tFgB7_v=U? z{NmE&*|J9|6Gp}q)NN-wXTv>okNh++90AB78VQp;UZPnhXoQ$>@ZMQe5J}BJKi0a? z8mazPj?|`OGq3!a8)hhUIi+lQEV+bFAQAkjZg)#-3PF%u{!mG(Ki1F{Wn8rz(0zde zqgN_O#rp!XXxiK%)K)(goK~KfiN6@J+#m!@?=_}wY6zO z(l@vrO4|4x+W+qUdMCamgzk3vM1YyZalY1Vhtnz;BAoGIl|skE*RIXy>#~mSGbbu& z$=`vZzd~Q$Z5b_F7bJTBt{uXs7EOVY#=SQEu(A1TA7N+vuLl#e%Y?SSr<#(aO1GVEEtdJBer zprs-FP$)tVuh3|^FqQeqjn4)YajBTYae(KF+~Q0w(=J0U*_Ae0-#NYpNWBa6sr zm>YS}4u3V(|1a$86r0E8psGx$jFYo2ebY#`|^i z0p2fYB=MYjag7i%?E%EWmqYPzb*9I?fTvhmB)P_af6mk1>G#q3HEsAybe9lz{*4NQ zMT(8b<=7-CxQs2fXM-VzT7lSmKEeI(aEbH{76@`Np!D#OPT6YuVpSLUq=q^B(?bhw zc|)BciPv(8Sp~4Tp@mrIv$o-DUA=@@a&<{!!5>qPydLEApP|3>x5^zum6NBHFb&h? z?ey4>w^JMMS~!u{i#_V>-wvzdwy=w~_#yQW(LRC00G_E*-eyjtZsjvsHB|t)?X9)- z?H4NnbjwSD!?ZB+4GPqhGOU3B%-z?`mi-Dde0+vIB+_|z(iZ-OA+PrIR~%+C-uVK= zGD+Ma(!KsG7ODghf0xLsNgvf$nfOpj7I`a-93Bpk0wm+H>cwQ%tAs%NGqxg^&baAJ z(z-bIl_gPim6ukhH9~A6V76%nv0A5c=I3RX4PuwEBwndewEV3MVH^9cdc(9a)7>MR zE&lCd$LLccI&l!6qv{&&?sG>RSig!HBrr-Kw^*c1ob&Vz{SE=PWE>3JZ2g`|7{8#k z48pye|7#k}LK$y)z+M}&U*T(*|t;(>40-TN?A%VSAFPSMg7f%3Xm^2_i`*N;JYCRSXPT-fMx1OQq* z`GBT7)&4nzMc+L%2iYIxul!{i6M|IGRp8Y_xyIN|)|N28QLPl_z*TKy<2aWq-cR+Zp+|E3^Ex8I=efdYx_d;za zSw1JPz0aBJq$-9?onPfV5$9~huBxUSF$*fu97MstJwx)ph^n-(6^p;KF*U)0rv9%} z`n2uTfV`EIK&TAGGubYWKcqy}1yZT8iAtbSK58=y6T1T4T!{n(keb?lC(+AXw$Y-7 z4`2Kb7vJ2S`0Vc2Rg(?MEac@OK7V;{IjJOzCP7~{eQtHs{%a1kJ~@y8=x?UbbbpCp z>$jBzg0axw?L)APKA@NMRYxfp|7Wo*UDP%r4=H5lhez>o9mkeWQsI^2c@|ghT$nnM zqjEB0ydpD~kwRnCtRNru>`b(7bMRrWlAizWMTs9{6!NL=l4x$zlOV}v%2*G%h2JP; zY!+?f0gC{8HXFhASP z6n0bXxY%wcZPf2givFmAXPeA@pPla!j)ck76|Qe8ZFRXws`f4Y3;+nqWzF4}&r3jc z&>SXZ1~}g*OS9EMCA$ZmY{#^VhoUkwNXjsaK-EZ|4TYYz_M)pkcM5g+z&i>+MyldR z7d$o1TYM2GLLt<6PF0uW<=w^ZEW>YrHTIf?buL)7+Ej&;06^h|p|aAGo=5h?4;j9` z-DZo5s^JtSn4|Rkb=}5=f7Cj)as#wm4~w&r%l$@|w3ie>?Fprgw(Q*Aj?K7-^oSLY zi=K@(+AUFR8ot%YVZbVzwDndE|cx8y4h2#+){FAu0Z&XBGop=Shi<8HH~`{DD}is;pjJ&Z{AD4%7u_X|D+tyd+yI4Xc- zzf;E{%p z9L3Gi6M-B744c1Iden6@1Z@cnrCO-f59>*fFOD`<3)>VYf9&729nvn64`l3EP7|Ug zc;d_}l#GikWOP7sMoh}UwkQR}_Nvb*M-r>LEcLC!fc0m2_HR18<$Yn##m*=Gi;GY- z0sxm)`NPo$rxwNu&9`GokmRuu+rEKMeA?~=$Y%AI9e)EiKUyH`KaP!g5JS5Eb<(vt ztmY+ZB5;SpaR_T?iKqd{7I)qx%(2bf$I(W`>ngWdT|*(?CT|;!T-j_R65wrE8!vb3 zA9{L%J5;!IL7~W`$Rcx4$5=YRezun>wdJQ@-q3==^zaW!9ufXxf;iChU6=cxNiy)4 zAT&TD;3-zDxY?fxG|IPxYUG8~cw75xafdIQwHtqi>p3o{VVjoEw{5zf^G-gHL7!6z z)p(tenk#&yKJxz_%#jQ|_tLQDTNM`?^%-;*{EWdfaeI2c9`t-{Y|I>njRYjZugRe)ipt+#aB&F39Zis;J+JW5GZx zc+W$~Tjp&MD&70UsqSF6o!KE-{nF0=9%-5Hd3oWB8(amU0s~0e;Sf?>>+m}wp8w{i zuEW3l@n6)zMenw90N6s)DqjkHr7G^IgCISAP;?k8N@-z!3S=NZ3Xt7#Wr`<%PpK6D zyXCmHMBQ!clwwOzpFrP9Q%LVa#p{Jnu-*2X2^=I(03UOhSX_m~Vd+qb=9U^$dzA8v z%kW*tr-!T4)eaGol%CtexV281^EHTE<*`@HuBOYf?h^gX8b5{f1Le5T>5}f+gsxac zqW8tjT$cA?>FUrdCKiD7_-@s1PhZvgBY374C2&=D01wNAA$ChNuZDenR8z8kc5ztw z({JlKr@W&@!>gVJ!K>4opPD;X0~M2Q0w(T}iFRn;?WmTt1DkBOyX(ckx|wG6OkXz| zIJ9m$gcy5LK{dKlTT=n*u8$grOFqAIrzUlb{bt=vVuc{0<=dH~kXop~#a9AJG_jrR zE|ypmHUV0iOv^ZBhtL4>?;5B_QjWiGUSd-FL4X>O*RZ+I4BSU=-1%cMof>8v$H_H$t!1aM8MBSSCY&t$@cywt-b2m+qSyfA9-c@oFj1&?|1rJox$ z(=U)-e7U}~Dnbbz^5=CkG;v#cPf~p;l>Vh>a!&5CuFGJ^dnjNmELTkIb)?gApRhv}tL0RidWnq0d^Go&W$D{=5C-Tenl=YVtT(>#VI+ zerU+T)Au3BrY^#?^OOSc2t15G__NMan4+)fb0W%QFCCWFW)m9~oTKx_eLI4qGaQG)!s0+o(1eku~}@^Sa?AMF>5_U5AF zPSQBZ8E-B{$Oap9@8Xj+m>*i;8#jLTBGk{J04z}<{79z#?YnWQv=JQ-u8#95@M&?} z`{YIg0HHs(hN*84fO^db0iC5PAyi%KkaTZU58q4XNZpvb*~4;aZ`7t}n(+OFkIX@(g9kiRyWr_7Beh3H_+i?+GCVKu%C@qQMGTlC>={ z3ODV{ofIr*lmW84^t*!IPk{`EFt-#5Jdp`eJw+{iomLepYcBkn0o=1M3j6*;=vOWZ zxNg;E9S(W-*@g@wi^xaY>usKb#(N_^*Y5wtp7XuN>9G2+jZ>Q;dSG&DSU8oQrSFq)A5tCU*LjUS!#2f=ccyZ)>yvlR`scQhTod*$5h4HkvfPougvGkb^i|Zpy(- z5-Qq8<`62=cOBS$H5UVno1W#&?~lA{A*1a!b0^?;t$C>S0viiB9CZUxR-4xQt~{F0 zpUEK-H`(by7+h@FG2ZSzAa5d^RvPWQKDBAZ<2RO@sIRolgi7Ju%@C+}KCa z2znU}phUd3Rbe4iTXg4#WLbZ1xkL)SQu-!-F+)?JyX{$^S;4y%<7MF#%!B%F!c z=QB<9SwzYUn~mQ#cfexjKafEq7@f{HJG8@X{HO8kwN{WMC$@xQK?=6zsY6x?br#0{ zH}ZJ~$f$fm0!@ol_aYGk@bad(oNs5CAa3}qT|?b@ju8#$4&@<^d1|afE^c4qIV0eR zSN!}J6G6`h+?C1RFg>vcKZ*b`kVUT>flA*@M1f}ch2>0$@w~#Y`I|8VSC#ug+6H%8 zO9qq~>zTF3%K+UauA>cF4&#_RZDp<6ZV&*(kJrM6@Cj@!RByY2E@2jTYbZJ+Xc>c7!nbv%r|V zA6fq~cVj1a-MFe2AH40IvbwGZn19bhx^Jy;1+^a=D{aEVNwMQd-kO2elZDM$uoY=A z0K49^tB@`0SQx$K{XIDNvy z_g<)q+HMI%)c`6jdE?dP{`gDs&bteAy7$1I0 z|1v%AUpRSaZu$KFNx|%*ZsqKG9yqV)@e#WGWS0&vVadx7z;OQ$6)+tI&uN|So%?Vv zl@uCyfn&I>4wmSLY+NmCt2UcdY+PcH#?KG-85}v+KZ8IDnn`hbw`uhAXQR*G-#wFK z20wHznplhSMM2!0xKiq)f!43{CYX{E$rLZ21=h_n4cQ(2Mgfw1W!c*BS>K^T=*2YB z>j0;3%=Dt4_MC-k-wV!jb_x?f`EYbonVPt{2=;!sgN=W^LBA$#`5!p#B!HYhvuc+8 z{S5?PG|iY;QRV1U0Pr@0@_n0%48H_df8U;%;aN4>COy??-RKT0r(Jl@4D>6%_Y$#K zJaKslxqvCf1w`xdlos@S=i*m1UUYwO~x0y4-|i+ z5Qy_)Qu;AMx%=KDn+#F|7l?eQ6G%y5Tp?egk-X@x{kNK5u=i=*>y0fXD+ESz424SU zf>R$_Npn=I)iym_9&XrOG5BQn@HY3IDtO}+gGUFAzf2N^666?Q1JPzUem56EKBwL| z-W#lKtKG?2Z!S-w`cz4b9uYn!~9+o_066r_fQ{|A%pz?%>HvjSI z()(1Z_%Su&&r|G65o+Ia6*4%Y-&MWu`HDH=!{>t56z?B{P7N(Fw0dMI&--dL9_sWt zF(oJb8kF)c)?ArAzRFDD!(~*a&&OsjRkgLa2E6qEGPlmB$GfL(5c=TkoTs5<$;?fb zttw`xbiQjWW`MX7#lOSWr)VyT<|)#x#NYYdSB*YCDS(ES(re1F$}RjiqWpVFR)IKp z)m;yc)8xt3YuZ{>-3yjVhy`3fFA6NEy%^UW4+y}wI|NUsc1&}Q3X%X^(TdpD%)(v1 zJV~HElY_%@+SpNKP^NKqmm>tkL+vwQa=KcvUq{;TV?KQHzN5i}a(ecl7b|wus7Xka zWG2w%97#&R6v_2W*mMtu_kBIY8a4*s;uKdL_-p83pW z>a3L*seB9RW?SjKPh+te9;t(&_!#ySJZGRAk;ZF#U*rSGl%bN zi`}YrsW-?yDCA)uF@6L>=D$UCe4+)ziwzBqKf~5evO98<7Y(73c|p&+9M8XN;cVrb zNwR3&rJDhZ;x%}53J1p9Y6@9j;^;wS*^`qgV1fsT4pEC;AvBzU^ z$K)8<>j9StH#N;Spsjg`(?du=j(VS5XN8}>HD=yO_D;4~n46z;J^9&~B7UV9ytv%| z7WHUIu?G~4(7<(V(yt$se|7NRo;<3Ts)L{I*7+6+hi7HOjCF%P=eP|DVLXVHv_SL= z#iobmChCeRCv+|(p{)5{tu!>IPdz6`0ai(hC&9gFOK9-ReP?$6f|>5OpA2j&W473r zAE}N5nbXq#axT7l%!&eX!WIoB3Yt}Y9`>HInh*Ro+f6+bCITGuz-@vyM6$j??j7-i z(vk4wFDMW`GBZVqDUVDc$2vmEIm;f=)yg~EwkAwQ#;be00N^WsF+X6sAn0L?n&F^I zFT+QIY#adyfNl}fAYE}%t^f9G(z$493F!Fp7^j8@uke>2wtrLJ!}j zGddg7xD(4Iam-{-Iy@4BzL*$rRR!7>vsJ(k024AebaW4g+73N966^vvbZ$FVuc!et z`2BMLRFX!YakU$bX55QUSB7lhbJguX2`7EE62O?WY0xb%Jn^D#N|bLY?hU!Lu&~h6 zKu8yWBnX8<>xR~eN;g@1oF_qSJm_RQwcHlBDgf|_-)tv~E%DZ7>bYFVeZSv|;2y3>{jFr%eA;ap$wSmWn+i`FSL*E5K$6T)av=XdhVcv$&l z4_~|5o0)aZ&P?9gh{PfNdnh{Y@^YQxGpV#O`IrW|2v_0EgQe)(Tf-}s!ckD&18=oA zmczKXBq+dcS)I{0(9|Fiu{cyC+u%w78P^k*pOASdp<+RUrF9)l|DlC%C>CBb1-AI>WJGuFPYUQfFtBz%_{xr`iWvllNzTG^(E8_wo4R(l7{e z^3Q)irtr%mItEHFoo=M~LgddgRg08(r#T?TVKS)`&#njjGQ$2%BfW-CuQ}~tNaMQ( z_eMG?p5Mh!_-K>)@DNbAViv9X&T<_d@9M438y{?c$rMq@= z&Y#sGEZRCEx46HK{YqAMD4mm2_6@B=>DaobhcGWtzE$02XEC>S{tj+-YVm_GqE0l{ zR$lJux3@Ji71u4--j^1*3+(Qk-`;+*>Ls~yf#b}q#v5WQ#o}QzdVKVs(zn%mto?eY zcjr-!Y)&OPhLoVIsA7kQZeHcLV2q7K>20+XZ50eYv^c3xucvHB`ZZ80nPu4z%PX!=L>P}>K6=qCD=IoFYodsfgMFg<5n5Iz!zA#y@omFyv)@>$ zSxitCUvJzN?tUa>vq-Wi`zRY@SfZaU;RXSO=t;s<3k026=0xK+j|aBY^zMytcCcFa zE#9(CSNBKJ$PXTx`>Z5^HF}#?-~mNFv!ey8%DRP@{@K}UWe`Il6Zu*jf%t*yq&a6e{xCT5@1MYm z5SZ%&aL}*bO%{s39_cj2AZz#@1Em9=!ae07Q~>_)bdd*dL>vWz#K_VPQ}BJO93>$5 zmezION2NI;dhuYEty1zttHo!2yqalcCVWSaxbWLMkEi#~g4d1)B$~4S^+$aPeL!p? z&@sQ~Y>^VUOPjZrIVt@piW1eR%Q+T!^)(>KkG`EQ`p%2~7cogB3RMB1753uUnRgz$ zb*u_iBB)B}G|22o=bZNOm3_nSvUNB-Jj~=ZJwX}y>nHBj^QYu;Uw`VB=>PSzEP0UJ z3p%jGpDYFL2V|%I)d@av2926UJMXhIE}Mc;1F?S*j<_e^B=IoZz?&{6FaPz&EMy@$ z{jn5u(2G6~|9zgJ$7MO%>@cXqj{p$>jvaEfMQ{7VHw*|yNFKj2qU4Bqm5E6ufGG%@ z5%bBu+V=W8Imes@3!U+j(e`y~vA8ct38`>u3**X}uVE~lg~^3V6}ac%5oj}fbgWc9 z8ECAw-*wJ@7R;B?=(${Vt3yas-P~L0`BHw1-3L4hU~xiq`D zg@^R}h6b|Vukd7OPykX+{>0sOFy7_s%h8zHFqu+4-f;U~KMJi^er^~2*OijwA5NJo zMktFP#*21F(MJ7gpFF4Dsg>@^oWZg^Mp2G^kA77wt(%rM8!%sESULOE~+2K$(~zkD1a7$HfD?WRi}yABm~ z;=^zVoN8xK^!gP&ITy_v#SSR9T6N0Mf>*x6id>vj%` zdt6QHzN({RmQpenx01w4?!e`Wql2HKLb)CAM<+Po0J|b-Rg>}ZH21u5D3SzD!uxE- z=ZmL1VL+DeNpxx^QEXGA+h&q9Hm`C>U2!o5%h}O+s8Z1|5XBAU{+_ZrwD{A-oe80! zhE^{w{?aOWw5O)KJ0b2mbla*xjR#Dd(pC(bVKHsk#p1b&*l7Lyy3v!67mGknefGV_ znU<2WPH#}hd_lw>r6y8;;_fjjfz}LRc^mv5_wKp()T^4L-h!bafiEVn>n`ji8FKLE z!B~kRJx4wK@1q}83lOlhK7vzbgC9;M92?C8X9%HsY`;;j61|*+Y_&e^z8;s!R(JC+m8vNsENB@%j)1*Hi zsieCR=0_Hedx`;6q)cvKcPEAQ4y-?pQneW?iG6m;e2WCacF#tm@0fwQ>ecn*$MW|m z6A;9XHmLH7TMrOO?&r7WZ<9hR+Og$Thb|k@Z!iD(_LvCKMbZ5hL8w6&hTA4Mo)?OF zzVtE(5tf8A)02KUaq52B3hK9LZQU71%yAdaKe)4eJ+xjG;)kN!)7;y%>Pw;ZosR6? z-6ZlH3TkHi$z*z<&zXzyag#^!#!o48A7E(sWx(mPbLM%!t_=;c zIBOtE{DJ`Aa+N#AFF(E0RZ2i$fk;04+Y;rHBR7FLBmhWN)O^YNkJq(WNmL(s^ zbg{3}j}oAez3M*MnVP#8ts$4)jEK?9>3ZEbKd&pv9`*Da-=d%RY8b}w?%K0}k`x1K zo)~L8=I<0a4<(GXKbNJSb+5?HL`p%?*0a>iem-Ntm)XyXQw%?SyH2mDMOL5fSh|iUYX}%X9Jh5B4WOe`x=FP2tZY^!_`Lr8s72vJ zkqHXr>=hgjs4i!Rm&zD@4o0vB*;7sOZ(-1GvHefHJ%f!7r-KS@Y@eHl`xo96>xi{v z`LRL8CGGvKaFg#_`j3JEX-}!J{mSiMIshhdX>o!QCx2JlA`d z*zOP}+4b!RJsF7*f)CMn~F3?_7yPBgkx!dGlYl=KMQ2O#)K%UpV&pPQ{=0 zG{ee2#lm&w*7$9<&T~`b=o;Qs}(J@kTjr*lZ)df>|d>~ z)YhhB7sxoT0Tp+C|LRPfcC2`x80o*C_-Ji@U-77Zi0H-QVQpcHHci_PFSSiH!Q%A> z3Gy-$VTJ5aa0Ufw0^sKl&U5`E*rCdpW{? zBGXhx$&>iQC^Zd846;N{N^4GD1`q>`0XO~EEdl1|?}&+0iHYOm*|ooJj}sE$zj-dB z#Ho`nrT;Fe3#3aK5fy_LhoEEEWk;M~-<`N$bu7yy(-K#KAwWemwcSetdLm-{zxU9Z zJ3(?NLeM;m6mKPhJmfjzQ2r|-Xa)o-=%iCr2W)|Y9?Duz0>T$ zmfg_IAHKu%&!K54M)G8PBJYEvFssn>lm|rjnF2Z(mM#PTM$5NzN2(U+)S1TQa&w$i zQJlsPC%fzfr_X{PPGH_VqS=T5fcTX2<1vet-R4V(96O#U5((hbzdGO-e~`h4XP=|d zcAz{hMDM2fBeENL+c91&Ci&(oF$U3Da7T-dQ#Me9fYA5#Q)jk@r9$OAw#vyv1|zT+ zlcXY%^D?qi^#^oXOEcuOt(JV--zBl`h`&vtW@!a)%I!aQj97&PMvUZ`qFIZUwjPM{ zY5wH?B~ZN;TDxg)AQUa9UYsf%pCxn(-hJJFTTZ7XA`U-|D|Arm>U_|@i7T7%@{hs}`fME=M!;1oS64+gXfi!2aH7 zGKKU-h`}DscLf{w<69n_Pind}W6&yb%hcen3RF0*Saggl>F%brk7_(DsWz@8zQt`3?&ePRk|$P* zwOFOXkSwy}hOY&R4)v^l=RA`$I0rgLoU{nlGlL_pS5xNd>GiAIIL(TDax~i_k$es| z%bl4=K*p!@;s=Wp!*(@o3SFD-7AZxJu<$*z+ZS;TWPMh$^j|MqHsIxAbr zDkUVxWn$x|AU!uV;V%Q@NyA!si#YnR!&X`Y)Ps5?4fLj)F_S^P z1h`AVKwPqE4^I%HOP@r$@sv0oMjOxhHAr#=Od6nktSZSxw_<-KthW^4^*Xw+_qQ%p>$!^9`2z38azw3ZFZ}}JOt8c@*f10ix3}XT&mdT< zu-(4Jv##Xzd${t2;)XYM{#zw2Mf%@R_-F@@7cnOl!z7|bX3Y4IYRquqst1i?QG_hW zu=bP67@AAreIXHcC=A-LIgt(V3$LQ=+Ty()k$gP_1x2%K^?`PC zp0|tBD=~3TbrG&YjAJU=RL2HjY=!u3Mil<`_XK))?WG6{ZJyN=-&BvYiMq2UUaQq* zH36p|`7MI=TYbxuNh2e{WW>p@EhnBSvz{|#QI!J*XPiH!umzhpU@nPMkem> zDXq{iLNVWZr`?sC4T%7VhkXPr0=&RMt?qfI$ryAoV-k=ur!9(me9@$s${98 z`9i$QEc_<@=9da(f(%}0Xg+`)rR)U77sk?px07pn-hBcYO2m=ow3Y_cYc4KZSfXkAI2uTMw_T;+@}W_80tOYI9xdvKoI>j5 zB=09b0~Nc+pYlXK(*-bwWEPx6C^~LuSAi(p6siQv9kt=y{;#3_Ihkr%= zUe+P;om(dkD0MSy1rN|qSuf=eNZO7LB`KuNphw>NHRSYtX|Wd3Y@MUXUx|Qty+V2w z9nEbP76WOi$-^JSyj_*gn$Os;M~h$J8gvHfE&N>%SNm0YGXCBWz2F}18zO%<_aGGm z>JsSQmlC=3kUHKvm#nhGOPM$gpg;B+Y?a#}Iwnr8;t1Spn`_?hy!%$hVM-2+Srfy$ zjHK?XE20jfKeHLeo2Qi*Te`FE@vG?&Tb8tIiydUWzpflTEjX$1weel+kEIfDG8@Zg zMGrq@iaVYodnso9cWZ_v5$&4?K&X!j*@wk$I{id2Dmbg3Up^a{`aA;d-5$<2Pi22$ zlo-_oLog8d@jnVa)6coeo0i&G*>_iv1!GG3b<#l^Iwd|EIK8!a3151{tynVaD#|?o zy=2*J8yq6@UL!-dCX%r6$AEz zUfq#+fXCF#?Nh$o>|Dd}%bDv(FsOB3&d!aGtG@tZ)?>`f?-U%@oJIii*+Hs%)ozP# zo(Vpl?3F3T7^Yj4=)1q_qWGX?3wcQsycnTn+P_3Vx#1v94MFz==QX^Z$o-%bc{?@u zc6=h?_v<@naflFL_%WB|Qx#M>^2{|Qk`O8QNx=$#$DzP`m&v5}G6rzx_a=#>3_jwa zwq|LZo;2L1^s`wroHcBRl#j+l#SqH>#@W&d@Qqpajg4g|y$G@eFx=47S--(8=f;I~ z=ID&i4*xFuhY^nAHQM6$LpUKw9>Nkgc>aEjVebjB`DjuD5J=&TCibT0FSBJ(}Kk zEt@LYiO!6~a>cZXQSB|5(K>2eFnl)7;5jAk&1y(__pvGQ{(@RYJ6>Turzkmc0>>=iFeZf$RKIhB+sF0nLEXH*xS?zO-$*aqhb(9-M`8Ljrv zi|i>eGt0W&*N^4c7K*coS{<>zhy696p(_~&1iw*elzuL-w7mi=if7%!_ma_mvDB9A z+G?-izL9L%Lv1Ou6Mh-n#U^^ZBjZd?{WzD^73s@=0XjZuskhC9jPn=3ql%#Gc$*5+ zZhiseaH@~D_8vI)k$Sli$D27>$`w?dG+m!cNgsCJm?r|{p@}RlBxBJk3=k_#{GK5K z47b^OhKN+1UGzx+ihcFwijphrW<*6a=F8Rqw1;G6@D&S%)ZRSEdw3P)`aX3Dw_F%B zwqEJ7eNWzc42q(uFy8u{9e5G1%DHO12^IbX)U)<0bb5T6Xa4?ik@BZ`eyj}hO>Hc+>? zy#~pl)__XIf1O9V$RE5M$GgTy=G3wSyb0sRWgr47UVl2kHFsdYyPIVB4yF&zhPeWF z4}Q*FKe#vW|1vLiiCZ;@zklGPT7e96OO|QU7ronlT_RzLT@XRmo2B-co|S{LpzGKq z)dIu&%dEI&gcooD1%bxY)c+uo%w7M_0(Rp|u5y$^TpD!F{#(PbkJMfY?2?MIEQ<9w z1)0E44O*4kjeD=T^{L}uR7;)2_mU=O4TZm`f+3iFF0f$ZI!gmpDgbEVc!I3NZQo0; zOGwdBpdFAo)yG#y(UcY26F>;?A;g9ihKL7b_?)0&H*Wh$i{D1KIM?Z>4HDhje#w_Q zbM>Y+fQ2rg;z!+iLf&J_T*^9F9@f*&uCS%c>qie*P-RvGUVE$oazX917op1FtQ9P~ z4g<;ruCo6c`pO6H)DsmleThJ|gUsyo8c_I2AgDw9bk|6)@y0Zu^P)E6g*Jts;Y0{l z|BbI6DJp-LV@Nc{@02_AVH(fY-%)k{<(?}3*A(G+K$O!^jD;)>OQuNHXEZ~io)~yl z9JqW+gBxCM1osbVG2jaW4RNus?epRqDx_stUpxLXZOG)O4e1(b&e0QAVn89-=Q%l+~9hUM^2j6 z3#dmeWvKB&R0}37t~U*^#$xTkOhlmM%1KFi)+_$mdfK107pO9-N4zw6j+oK+cnCy@ z)lU_GQ^q$*+~+$Bwgn0cuX!z7>(c-lP%0?dAeE3RC+#aSs5Y&Phd}V=^L~4!MOug2 zdO_eckMi~t>htEHy*B#TS5w5lO|$?n!uZ7%d%C&f(HHgXDsjA(E9;EoO3w5D=D9^nHX@=O(E0kg%*-qiN~ zzU7B@<2H4x_FCYn*6BT#yBmLcok{<8Ykul)JRAioTIot<+>X5Xf%Vjkdm$L@x|3B| z8M36blYj(YC5pdHb_Lr414OM=6mp;ENFnHPS_l`9P{ucYbK=(aTZplnRKUG0Hb#B7 z{p{79~E?TPq1Fr_AZQw+4p9B)Szi7mrA`oD5HG3 zN2ni#f%)|Sl;zYFM!_z6(9c9Yn9x2{;W~@|`b3faoXe)PbTB2VukcqytSS7X(+dt> zD6jZOTFQ!Kof`rK0E)djz75=|+ssh!S3^yM_dPFG#xaWMR_Ocbqg|#tyx%McBoGOr z4Y5)O>r1h+GTU$w0D=l3)g+!hp)(;q)D$Ln{qGyQ%BEbr&uL&sqcOC1mDzUdYF*k2 zWeh>OBm*<=&e_OM{G4b`mt_{a90?9jTX}q#uQpUpL9Z%=J~n?&h>H3iiq2;6eath@ z*(&i;C6((qd;$hgaDLN~{$u0&Z`I}$aYCZ3EzMba7-G^Glh`4`QWq(;V!koA@260r zf8D_!C@vkK&XZ}38<_41Kr_cn0@w0Qk%Xx}j+^7MH%qebo~I;DM8MErM$U-%3O(3d z3kbh8-!Vk7Q{ZYW9nxNzz^8s0ZT`uA=JxN&(r%0J&fMgs%E|QM@KJT9d4(JuBj!h;b_oX?S&`w@dH)0C6eI9;W3aaSR;L z7{jV2lNT9hKE)=1;o~60CK~uNtb2FTU;h*?HAr9KQSYH}^Xsv< zG!ooU(GmpR{VH3RH_kzqQza%fKhP62OyJG$+t`YHl*OX_ywuNn%dtoNPK7Wz;I7)N zQ2rc0>kh6v$#(~)GI&o|A1L>CaRfmDICZ6t<|PYes}ZOE5`7&8AdhR8*%E-^jXmBy zr2JzJfTSF2Zkf;cug=3w*kmL2IlE5na@5e>**pCoZEekeFye*34?W#7bS)|rEipU% z)C)`>i1}k+a3$@dL>8Qludgqt$1iR-O#bgp=gL1Ut6*k;fBtMAc=0z|QTu}kmj}2M zhwV#aRYyiLK-|}pCfJ;V0USc{ue~`)(&iv5m9}3_tAt#@GZpYbgilJ__f?t2eQt`XbDVE;gkjeL8DMADANb6k%^V=MI6ZlNO+jK-0X{m-`4yr-pd5&tQEAW z%tzO&p9WuaIdfB0O9wLYB%jJ+3 z-iaLaaR`VvvOz0yi2X6PWButrH@=&w_(_MOTO4-AiTGpl7z7hI1}diIJkHxn7o-MX z6mDAhPqyEphuVZ);Q=Tb#Ubzn-U3zAJO!Wr?JfVn1)#uh9;tLg0ZnS6(2?cv3*f`&-h- z!@6LRG=<=<^_{EdSusZ2TIcjKf}0MJFjeq$kYe$g&nYBem{3Ju;NEhCEa5iYqAxNzv=7wv!-6ef;;O1$67Jxi3ve( zdRt<|6o0eptHPULmV+B>WWnJfqBqty<5p`AO9K{Ivq+E(~eFqoGHG) zunwUbL+%YPca;@}j3wU<$5`$Bo0DQ@mMWB@0M!HVrHX$R#lz>pK;N+S0wPT*w>1z*_%Mg%1;QK-9lRRiOm zAMs4b4m4#s5FrfD9IIZt_ji>lDNYdM8Z@3C=B2ZE&)1Y>wjd~Qrxf5r&|-hqisBRa zj18O*CK7d?jhb*E+a_cD5l>;7tCfoB6_KYjENTjfc?{A#&B-3|3YP80tE;rt>M#Y2 z`GoNfu2Y;VgRaXmr>ntpGG$RZD3S=`yCG^u2`&G4r>SF9kG&ZeUl&KO;8l$p-z^AM zqO;M9G-P!sNLn?kd0E7i^=|gCzVvs71NbF#qphoT!t%BJRzF%n5V;806~b`HE64~6 zp>b0dtw6)j?N)i-i`U6?12R0i*cOnLybv37kjSPS!(g2z2>fK8k5m9x2a(3%pMJfP z5s=jo8+5hAO(F#5V&Ll&H4f7zB6zT<=GR`uz$v1RMkR(|wRz{<4f zZ0)t_VH)Bf3BR(SI~RaLxh>sHg9~VafUL{gTNOP~(7hSnc0jvUr~@C<`qE zatBqhja&Y1Z9Lj_o1&S0WUmqBqpC^?4{!hc?WSA80|P~chVc~?=C3tVw@uDi=6_T3 zvrJy)o_s)BA^u~uefT0|H*~Q{k-%T*w}U5_7R)WlYXs&XVnvCm*{yOgp{Vw4DTqzU z@$8(G`K(ty#Tz-`^$e5WV8^V9R)qb%?iB3HVhp$4AOj!=A3XJYAk{AbR9S!kU~;sT zrSai@P0_xBXSXac{{siIa=gBdY?|89mEYy!>WYYy{T1-on#W~^2ta-vaRmQd1G-ec zE98e7vRcFjEZ!rly5$5#PfU7U5W_(#%3&_kg8>e?muth)1o+_eiKBM8YJaZji)?`d z5}-`_+VI*>N=opXe=H;wT=VW*`~dKwYJw)$s(p6Ue@6xNGh67b9AlS;1sQ}=5h5tz z1#f}}ogCwVE*)QQPG{$R@#vd=&9&T-s>X7^9byZly5HtAPj z5nUdu8p5AKf#A4Q6;@uoPH(^6afyb*oUQWNtq3?sfa|G@+!cG2R${}=u+=SVe0R{v zf9UVz#`m>u8b*zqP-kkuq-6gh-XqAHNf2UV+gUf-0&aA3=L23#Vs>_(JGY7N=6(Cg zv`q3CTwK&V=bs^{(9ubjo4s(5xbAA@|C5;$kh^oph?_5H1OdxuwqY_RqsA3JXF<&E zt{F)aVq;mi71_!27NhBD_@;-m{|JMbUv@pNPf(<4Dya#u*Fr@288;-^2?IMkV!hH4x8Vx3l8OPat zG)M(h)-KB~?+SwqC4342jgT|F#U<-s5Oi@NJopl14DIZ=y_gdl}YcX?6v zEx22dkrWXjpv}82dq1kdi4cc%5&$3@?cBGm4UFLtRz|KADS%;vV^4-;aKE7%J|yB5 zI{?xS|8jB3xQn}UIM+~~+?>?qX*F-g;-?JX2(s3}c6;n_V~3YeI&@tZe`K*GhjHL2 z-#7~;0c9|pHV$f~p!fwl>$R&ZRJOYlTM+|8u6__%VyQ!tKVBoDm?5GBc6^K<5nU>x zoC;{{qrZN5OR0rOm1EFIz9N03;XnUf-L`|tdGYtB$Ff%ou_?r>7dNYgH~=h#1C*?( zfXze(AmvB4fB8%K!i@s`2_k+cSH`zqG9jyAs!7%h(oD#9Kx9r~+e`!o&TF zZ$}puH*rD5fYr|4(ZBRZ);8GBNr=QL?)Z4XR?!6a+KB)Z73BCH7yahm8V}*^zMzKR z9c)pxG$Z9U8joOzLwmG++ex1cxTLmv#q#8mdbe)8!9`ctgwWk=^qp6e>!NX;s>!CQUNsCT@* zh*96>!M?+H-%u!?0=Fl>!B{8<8D!kn<=u~8t#_N;mm`Jb1#PYyCg&c_P4EBBzG?Tk zkuX1#xzy<lU-vkKd z5*+;`28g-^V9VsKIlsA0R|4tb)_ovJa(`G?%eEH+T6mE3opF`s2*~n{>C2^NW9i=P zXVX=A&fJlhHhteqyIXwAN#@P7Ie*dr+o;WDO|e)H(ms&bXUQKvv)E8UIhvBUjsQo5 zI@>W3&^T+2Ek1Hc-FEpMX=kY<1xiryt84Xdua?UhP*yGE_VqmR zCSkC&4V)1XhIJa5>=L8o?9~mg1B$<2x;)fje;=j(FX&s&@vf^JP?P!9b1IAv zW(Vg*E=Imj7HXgDn7~EL8QhOShoHW|Zzmy7ltS<*q=L?h3}#p_g$4g>{%6m*6oqJW z3jWJlQ^}IX$S+2@iICN1N=U0Bx3PDySdyQ)aO9w)goh>aa6lky16>fK2{>15^}u$ zjuv~LrUJzby|lf$PL682mMX92Pfs+IYq#d#opoE&XY!6rQuu=+TlVbuRCUATDPi(u zO{Tf{Hn2D@4$yrp<9rc5(`KeE0YySc1>%u5q=BsELP<=IWbYXKxKZap0Smb`tBKBU z;e(u?ayg7672CZF-{v%9{!B6?CO)Vn>@uJZt)(*x{UuvFDru`x*e$Dh0VHCjGYp;Zi zmL>c#HvJb`bv&(>CBr8g9FsWdE~)sZ#WOyKt9!qzWR2M&9qO9rMB#rg41g+uKuR*# zHz!#TIgL_-^u(_g&4Wgtp>4;3aO7frmjJ5}B_82Y$IsZ8l1IzD*A8T+_AhAoBxYoH z*-f}?_%y`crCbx_%hF%LKs8HTQPX|U&W17(=vdk8_E?LVb9p|RA-o1mdyHkq%G6IB zN{P+t^i<%3*8<6PV_mX%_eH9i_(|dYxYRy1jCwql7GkPTnVF(FNu~pN!q0c_ZEXl;vN&Ts>|9 zR0jSIx-UCtDZ9e9yw4T!+0_>l)lq%- zzu;NiTNp@Zj_7^1#^x@0{|U4TR>{9JyT3A}TDC)NVU(^TNOXB6p(!ii^&zc#)UlwE z`U&BRp)Z1J7&-f}`Xtert^Z%abBcSxl{cRY3!9Hic55Z(>o4p#@t0>?TfswFEx0hm z@^p~pYMzLQf;p7z-4Nw}Tf2;3fL(Q8yF46sGgjx3Rcu(*pzbLj6&8nfwe{Mj6|B%ms)F4v;6kkCQkCR$JOqxm3 z^Jf>3>V~ajB8S z&H}XtA3L-s9U_ zuZq%&h8M2nXk5Rui>JlgYJNyR(u_|u^(iG_Itvq_9vYfRZuYp$!=0y>;Wj_H6lO@F zxct>ADPGQcuJ0#@RKN*s5S(@|pC*}DVajz11(tVz6m;I-$K%HYtnY^d>c=2^*Lz;+$e)TUE$gOM)dy9 zRv%z(lbq7i!2{;VH^?YyW_H+{C%@I@im|RzAS0Q=9@0_#KAD6lr{s7%iwL7Xp~SXNhDG< zM#zI$2%5fev`Nkvi{-QW}`s69RUm(bZp}z%WnmC);NAC*l|B*gUFn!NVzEEwiK)<5#Iuxr- z)zUpmBFe&U#BuR(KqB++FG*^6ykgKBn@vzHCA~LIOsM_&agnqbkw$BM}z?x291{ssoRrvE2|tb{)QDbwh!Vgwp1}QtaCXw0xMp8c9T(A z0AWR=XmL3?R`~gIL@nz{EZ7T1{I?fI6F#D!N!&{+^B;KOSI=q`kK+9YDj1uV4k*(nZ{=L|Q=z6#^Oee3{{1X>S%I3ehcGyqZHZfdOVVfwn9DZdt;U^!jDs1RzK+&Se9Zu-Vi6 zmCu5#hP~79Y2xfg^J(H0kY5fzT@KlLo5KJBaG;CR^={5qtEHe;aphP(&U3=8`yTi{ zyWW&ET`Nm}U4Q;5oSBb?Bsy5z<-4NzN6PaRbDjL#fSnyDuor-vu+P38iVgfw2kI%m z4=k}X{b@YTcPS)9rD{N{=7!v!vGy)!izA>9;STy~RjjW-@}!1po=%ABZ6R}ZbY_io z^@?nO+tipd?~eHPFxB4+OE6nC>1UVc%_f{`&)f=`l=4>I7QcXBR`{Vw=i+&m zjv5u8A^>3znYERJKaJ0Wanjy`RTzq8!9Qq>-;_{!Jm8T>csA1t7?E{Gf<{u)ZgaXC zyIQ;fKT~_sYh+Kl!4P%+tC)=BArB7lGWw9 zrO)HuKFwM=)uP=X98p=*$sM?DFOeKRukd0t?(bHsLG>LwN0BG+F74*IDrC%(nC@Q( znH*|8c^8lRsQd`(M{*9a*yp1v_q&a0$6~tvCM7oqbmieTw#u##+9oS>bXZ<=_ zZiym1czSn~*(tlKYZAOmw25l(IqZgj!U)5yeA!FyDXNaCg8Z5l0FAn!&f7TXK3L1Ghhj(^Qw4H}^Tfv-X9Gf%~8kNHMzXeAK+~!8Kg+s~u$s zCa8^PiKSk+bl8Sx_>1IQj7{o_jH%64eSU5v3=NCQ$Iw);jg=NdnE}9vn1c zF#A!P^1cO$kYL`*^o>^%xX#&83 zb$7V8A?tjR9}K^3xMcBZ!#95@lN*2giGY)S+J~+l>jEPOtLS3%?TEO|=h|q9aG4xZ z7Ix9RK^f12Unf%Y!DSd%tEZhlT6}I%s&&---JQtv?EedBV=&P8KHb9E4;99^*mP@c zn;2yE_XY0C4U`vakkc#5vzocUuHEa|-KHg`-R_LLXc#n)rM~#!pm|eQ^7sY9D!lD; z3X9L&oX>(U)^3IK0okMYe3@)moZNk?i1$PtuzQ5^5ha%QKjOn9I+Yi>C8~~B*rsNs zHZtk6k0ZR)OZ@DxtZ`_C)rAV4+-StChq zg;->evwGs7Cp`?Xd%@&g|9btn@MlAwV!vZU>S9#z3^~gAU?|Y@Bc+>4h}#;pz8`<` z$XrLvN5f(86O)%z#a4BHK~wlMN_?kI6*L56DB$+zGnAHUEQm4!POy4~l~=cPDp~XK z1w(_s8gY;A62W_W@V3JY#&_h7N7jjJxt_+(=eM;Ew~sd3q1bb%g0YgdR!tbNqKbK&eF6qKk#^8FB-<=%>~lYyzVq=ox)B zX?4lK0A(GO(C$`YGUrKSCn+uL=ZMlI!A`wo`RfBI|Zm)DZpkWw9+o*q-P7e{DF>tW;PY|XF1;nG!fAmAh(Ff+bu@xaQ= z!GW$;uI^Zte^JJPiH{@WH|wWM2vVmtl19i$hq*$#hphl6ZKvfBT^uZB9qH7y__Khi z#g|>`;SxRR{V(GaI_lhbFSDv1V#M~YMFYGcds1ay@Xjzau@F&cofiouGG1RJVC9eN z=Rxbj!t9+#mo0FZ3c&XT2>v{r0k;6~utd^j-j$qx`^ z=8gRzZ)hvK3w!`5c!Mc=CzIB;~gq^!7<_wsrVh%QY?Xv-dAt>jK)=pQjME9 z4z?cz!lye^r^jVMY}iZj%++Lg{@K{b_X$yfQ1PabB=Wyn9--20rV0_?ywUD_6 z`Ul9<-2P5sSz^X~?~&U3zJu~9W#hX5nhezMq{uty-!UYXOn;K7(@OH2*E=i%G@_;( zMh$=<3q8jC%}I+$*7KQC2M%QWwoe=4(JQ!u?M> zUVx^3oH>F#>|_*k+3U5qA+h<(swDSgU$#*{vraUtgxyx@aR_?cw&RVF;L*2{A(sW{ zx8=zDaM}b;P~$)YakPp}VqK{aEvDtUm9H(pqolun$DCtgg@dUERw0-*R^;?D${|s3 zSR{^i)4W6gA6h_nyP!XTF%CWMJr8Z$AbX4t&QQIPcT2EVkAy^=5{J+3b*KvP+C;aP z>NUNFJ&10J3^kvx`|@`lfh_)ztrkK~#s_dAb-rm_-HfymaM^2|Qg32gOsZd=PYedG zUN-YmzWI^;l>TNg7h5Uu{|9P4`AvWnK*&>qy}KE>SrQ@bVmfyw@yd8KZ}yLKc}m03 z?4%+#cOJfcc^FVY`#twgE{DE$CVl9!=5rKUQ&d~XFF!!%9rn2`h6et=vdD6yH;AB> z!NS$Pun~g@W;qKT*OKoyP6Gd{>b^+o*@47$r(!=2Bw1N zV5Qg-_xBWxtXvADx%($g1w(Z2`s^K?q{bd*c< zD@7w5_zGm>z5%yxZS;G#P{w00;|T7?vqiPJtJRvDpFw9hyP>Sd_`wwvX67@^We4L< zb~6l0o;+hr>b@7nel)#7_ODD5)GF3XcEWju-jw9PUzQQ@Rz%cdd`XH1Ap) z1U6h!WvwY=%UdLKX(5_ReF27hLnA=`!scjs9tMo^v+aLOy7$1AaO9UEE0Poj&p|(Z zsr?BCkgz}3aUc{QjTCTjq!H10RDr(axx-vE}J&zCPD+qm9 zsS}w>#6>!Uxe8{ylZKH4qn9x3R-|D+K!mFGy6#PJjsY`S#gYGCwpegPBxk65IXkw7?CX`j_mA_ z88VW+va&+5$2sSB`~DvOiGMoxx!>a&uj~1G1-PQ71I4LU)ZJGGoiEkl9Q<0k*TF0_ zG%!x^UD5k)o7_BZ#-v#(Sqw2*HdTsCG)nMyX@}QZ9)5uxNpQx6Zy6#4-La7db$8i2 zTV8*k$^bbq9t{lDx z*CW91&}_yReo;?{FQuy6V2)X%#|1e$5{bUMuMG6Q)4qL!wOheomT*UE(WQ=|aeOuFT{!)MZGd_3C(Zv^47OJ@+a}7fCveXw4G>uH2%XVB)g_N%mfDa0(Lim zvJ7l`Hyb{bHclclmg(h*a95yJ zX)s3v%$(8DX;%q`cg(;6Wv1wQ)oLBVG27y|2goh%|8cXlSy3Q?Mt#W@`6k+Ew>hEYs$Fn#>+jGb-c9azi#s!Oh(z z|BCD%g#Ngg*I7~^#0QyGVEm?Wd2+#6>|v+i+DD36Q><)n?TliV$^kG0UT#R*Lnxhd z`eFO#-TD1;HHgXthoC9Yd1OzR>H?sK@Lq=F_QTLafZ{!7Cn1bn_|p&bPe*L-Or*GU zb#vpCwp#^cgh~U`sdHf2J@&4-B8!XyD8J=e4BxJ zE1|WDT4rAE26h`L=@)XsBWMJ-OiPfuXNA?(oT>Ks4u@ zGKKm@x|J%ucTddn4ED@hxR91oIgPHiD)rN$!vcPU5Rp7dTJVn{Bob8AK$GbT>?3ag zl~(%{+k8AK3#gSdlnS>aajb;A={Rc*&rkB`(&pgloIZ8}#X?<@2o4gk(@ELiP#8&s zU5zO(LB}DpJGt|Bllkwa)6N29+(qW-Xw>sG8t0LK)o$RzX(_Od_uc3s%SXk_BM1mp-;ur=2y5mir58Gz&o*#9K8m0QEsEz z7Z+1LW@7@~4VYU4YG5;cnR0#LfRzgW?`Iq1nea6}gfCq)v3TV~2E<^WGjVv`F)f3c zCQCt}W^ZR|YfMi2@s18$k2cDd0co1bPCH6r@;(%#~p*8s3v`bbp5dSM_4xDF;kjp8fk!D~-jot4%H znqj}eqRoHUK_FBPFJ*JuRF@a6gP4E}ylFfb5&E;Luwi=MRQ4uCKMy-1Z9*f zCu}nc1wt!8#Z@%&CoxG+wQ&Wc2E|Yuus@G6L7bWhawbQqv=Nd-+OxMpo6d5!P3P|6 zpGZ|Q#RE(+g8}IG~Q71f8Nz<>gbfYI$L$2%ZSKar_j|A&MXd=>s z*z@nUS?^N3B5LFN~DE?XrSi!)q=f_w2@?-u7$Fy{B==Jiz@N{1!P z@{#EkBNQ6BLEH^YlS^xi3%>G-n`YC*_3C9Q_!(=tGKV6=wN2j#5X0C;RgQOkBW$U7 z!u998)kP`4^u_^*<;O?g+~Q2~(#`hrQIsrFfBQPGlmNSG8|=^1xmwBJ2f`k}+pM4N zv#UvOS+7pU)g`-aP)4At)C(H?Z#RSO?7Go+R^-d>ozBP7-$z&ou#&h{_C}ADXOU+0 z(U9&4bC}E}&ml4*aoCn!CEPn>xGkCdW9|#$XQVC~V+zF5S5xh^3`pu*LcSb9dc^q+ zAg>m956Mp(#eVk)^8vaNRfitCASwQUS^GcC57T3{UWs>XZ(kpGukn zz^FIc*mCT1eb<*$bBJD{uCuGe`YvA31kv}!AJy4_L!6~AECD0=I&Av*1~5uE--6)) zgX$9*z{@FY>+1xS1+9+B)mO>tDyx?&m8_wW-{)}0w%@AmfL|Y%I9wy3@Rj5FGEWMBNLK2i5jr=}i3drTZOrI}PEjRZFPK?EaLynCD}{gz8pbSDX?^BpZE{z19M2 z4d)@9#H9ofCxr;|Ni~D(v95+{u_5YUlAW_f;8V0HMmWwN7ykl@ZN`=C4|8s zj@1jE&!<&S?&mx_on=(;77LK)%6#zVuFb4x=uhHMIv&hizLlkWUWNOpuhs<&gI{F) zEkEcFzAAj^L9wjtIPz0C8r2|8U&RRja|xIil&SByzeyf5XQZa)thXf~*u(ZwEYC5E zxnWxGoB;)toy)EK(LGzsI^UBm`8V-QxM87Ch`L)a#UARuz z(7_q#$^_Oq&Q9D{&b@dfO+>YIBhj%I3uDcS$!m#|-m$f4O=}Y8p zBggm<_(z-Rn;lt7mUl7!>_+Pyy+153ZCM7Ivld7p-*!gHZ11p7=Yx|*6X zsKaZ`azpjusHb0rxr%P-#mp-g{hgPRIPT)OR(=xsK)ZkWoyWhdSJ*OLSr}?^FF|XA zu(_KE<*1Ep^*H6;SaQMIZNn*}fVC$}c_~?PV?vpZ^oUrxe<5&!7~S)M5v3Ajb!%^) zDZe^uoXn%)PA|MoUqHQAD)y6HT!>iR(M>$D4)w%wn`X(&9;P+T<~JB52gn9cK=ob= zWdRhJtdcLyB`yH29CwVsIQ;>~8J`s0@?^+K2R9n?F6)!0QhtPEAi- zR`$679W&Jf=xEJn!-qS2)APdQTlWA1%S!{vkf!%D&KUlZ#rCI@PKg8-6-MX=^Sw^o zb>~XUY0T4@R#swg^_sQs?go3i_S)?9T4FIhG*xSHgqV4Nv3+L_35WsP;DUE#3*HD3 zK=uMv-P%#)!VT&OHey;`^6{ikT1tNu2bO+^U{pB1YMyRe#j5M_^7b)i&ecpajS(nv zT8}Yt0`^X9d6a^(?n`B_;5zs(>PbhB5I}g=8HPEXNdR(=z^ZxPxSj)A)U4)juaz%5 zxm6=ytmTu6F96_TX>$HCUbZe4(PX(>+*s|PH()Uovn+0nITcYXTH#JoHmzi z|L*6xdsq$;NnF<~`CB!cliclZ1#%&3ypk!j^WHQo;ELT zFjt`QO{pdJimgHY5JUSakA^JI}2uRlUVc{1_d`eMYpB2hrSxfL`onM?}5vFVX}6~eSRC>{hVce3J-x@ zV9ybrx8$Bol1LKp_Rei?nE!?Ii6}pu!&8Z!BeN-szI<6J(SQ8h@D7-~{?J2KJqj-| z*l$&x8O%Y7L~>Nu@dalok$`|^!nrR)inPw-{E1`R4ld8JiYQIm`0$n7g)x`b8z_>vA{isn=(B1{tvjj7h>Lmc?z1G2%D zCyy0Xksvw%6_5?wH8TmllMZ@ZaaW+}`L^!;HdOH5<(K*KmF-#-ul-4?IzsR3XF(QTDh~$D@1BkGg^RrLLrL)Pt2Y~P?)yvU)hY6Y!?hwDT{ngYhMp~-l zg{K+l4p|hK6a6ZHT9G3=JNM>I#en6&O69VuB&_qi{SX*o>xok8p6hj)@_2}876r!W z@3MDGZ|&4>er=NT-;m?X(S2b+U#&{q)&Apyfv*yvGZW^7Cal3g03 z4{H=zKHC>Utdd!)CpFghcu)~=*p1E$A9XI-NX*U6+npGvEM9p;z31s+>-(qNDVS|A zVRkhS^e})19|a|@2$<+g^y2}e;%OF^5uis9?vY3de#U4HROkKImf<#hJQ|crwzV4of1rdwl**zvhZBB`T)t3%=-u7=n)Un5S)jgTvBaHmsdvT!4qmqpv>K6?Q1!yV;Y$Uzb6dBIHw6R) zj9BJl{y4#Ix~VKhx@Z#H?{Y*atPY9s;N}+G88jKX!SV_@J`wZ^VP-8zRBvbyZ@kDS z9hs|kj&uS-5cR-c7oT;AoF1IpF#f3}mRE^e!k8lsT z;vcvQa2Bnws46~6=cYSXnBZbqzcq^U|AfpuzpWfzEuCb!cndD=KMj@7^wUHH6#9X* zdVydjQ?UJ}mQ1LrAZd3V^R{a+STL3<(=n_uiib=gvT^6I`77pT(CtC1>JN?Lw{O2f zj@u|N8Q#1>F^qkl`YK$>XUr3{3?ZNne@D4|Jn}P6wn(ax1DZRf4*WSHmITl3tQX zhtC(nf+^soJyfqM42LC{r$UjG9h6Wg$9)$&v@ejYf~nwLM~x*5;z+Li@4g#$AIHrH z9?49g|Hd_p@WkG$bg90itnU046~yX zy7K-$M*QT)TtlaZY~pch{nnz00z50na5vCKN}wG@G(%w28CZ_<<6@m2kj zA2dK)moWt-rf#9I*TCo=_O}Q2Hw-&~+m=!>3!#K45F}*ZtbbW3*Yq2%aK)fZJ@@gr znExQ4`sOoN=-&%u)JUH_gnIS#L$uu3aGJ{l;2-rO?nZerWXo?T<4@nM^JYl-<9&EM zd%h#{RXy?}>Ym8`LKF!H#5`^(7-ZuwvBAp1mO2I)q$_oFDWitik;X>- z-TqlUPzzTmeckv_Gxz56vPs*8ugNE|KZ@U}oB}#7*5Uv$HN8rtIwyAyVG%H9uToL` z*>l?eu9`ic&nv^+A>);o?8sLhFeNkJ?+u$<7yrgHu4e&I53r546u_0VMMTzplfkA3ui21CnKT zZ9OgmIG9U;jza-#$3>E8yTYwUq*+Mp4->L7}jKZJRz$3D_8AvKhEC)28>N)=(~DoI_#!3cC+Gh z$9x*i5FNE59L=0{LofN)#ceH%l-lgQGnf(rR)7ODI4?&Ax3|5i$~L!I>EMAK)7-&g zieIa_YfX3OTu>YUtr^5Amf|>FDbBC`@UoOXp-wxnxtk4Zd$sn)qRbO42l!rus ziDJ&nj{F8~3P_J|Y@!Eg-LLm}gi%1}2Eu2j{SpN#xv_0O( z-zA;0NeDF93ILtdUEHu=1cxoT)Km5XDbb>Oe*#(N0f3niAFq%hWRn=)EyDlAUer0f zX%y)Wv^c`Mk9>9Sy6O|9m!;V{%=(@f;0(Wly+fZv2!zoFhu=t&KalbUn>=Cm4DDvh z^o5g>;yE=^gnXffI2!TN0X|H4AiU(YEX||Xy2seV!@{D>&9ByypA%W6|7{_#D**?K zcZm%G#ofJx-<#RO*TRPYp>bA7tAI5T9E-#QRDr6ao3;4?&V zgDzO{x-k=m>{$u2qr=SChWlE5^>2X3;WpV){L-=NxO(U~_CX}W`XAYNh zp{c0`Mkkp!uYA{lM-sbtp8elIx8uxJ07nsk^q#o|3q)|JQzS%pbn82&R+2oNK-jVM&0>vl&YFq=1XDeXetQWuVPJ;jyl>lp!m}QE)?+FeZm1bp{s3pTn--mb;>T2 z6Y#0wu_kd?^3jFYXKFlTf$m^7|FSdz!+KUMLC|_(&oeJneUZE-~3XP`4CsSy{&}R<@8^K+WI$EWMTK*c|t(Nsa4As zI=8rFr#UEBUZxfI8DQwP7oxU_)snDXyzp3-^*)`ueUSTHu|;V$KU4pf6*I97ixfcB+8{Gh{Dz@g2bNNeH>gf^7Wujax1Jw4ByIe7(?-xx%88Q*^%Hxs(se{^o0?eLwQc;@)l z*Y{RtpjAP71kk7AwGvc^66y-Fjd?Pe&A`K?HJ5V%j4?ohu^W4vF@>WN@WSYK-FD^W zJg5ev5~mdivVA5)S8#v;=M)IZ1|Hyv?&DKO5QhHiZ9$xe`Tf2EN-HR$ReV5>hglm` zmo1G(#nY)-NWHjMg{&a%I8^SZaR3P7jS_;%E*xj`i-x^5|7ts|9zBwor!*$FU~rqe zlSf)aVgLNj47P4>CgfxYZYS8&`c{k`xEF54A_sq0djvCbcEhUJb`ke~5TLHhiWkN8 zL{xei#I}dm^eMFSqRAK~i4ey?c%p2ep|*Dd20DW+@2nCMu29=r)>r=k>UA@@;S@<% zthD?76>cvyWEbvRNwDa|-qm2kz{=`wP!ETjmalDp{Qf=V9w}s^pSPrT+Rz9tla3t$ zS8p+~LEanVZ&BsqL(!l9B1pMT$OuPX2VWDBM8KyrKDlB4y1U`NErbj6b$xqi@v=g{ z{N@~ooujv!{e3MDYI$WndhvE@{Z%(KH%XchPo4IKtBtAu{@#6$ zV$1sRa-DCdM+g-pFmJ|@2J~AW&nH3`{zO*x8i=nPf#R|mJs~)gnEG&pVh^`}{WH48 z`4jo#n4cP;@>ZfI*oQrY>I=}l;i#ry{KCRdjCywEGrKND>34=0_>r$ne3nB%opNL5 z7K!5R>zy0YeMAB8b>0uCwWERn*oxk|DF6%BaF(=8$-$w#?J+68E8lqAifzYXugRhm z;1<2Goh!TnuXK}p7TfJd_uSkWqP0DapLi5FWQ4_uHZZH+m-|*iEGzS}@p0Q!jA};b z!oTNJ9SI`tpXAvO@ogR&IK%sHBc{d^ODdyREq_79sJs;w^e-occ&1K#sBRn(}b(SfKZ z&M}G?>ZABBOL^u!xYA>Aqfw}}7}#WP>2(0${1Os!GOYbMF{6`PM*$AZQg5WF;nsw( zYG^v8v-HMXD$nk6X6(}S>ski3N2k0Z2R7(Ox1h;qaY3y2BzS3S!uIm9a_RrFbpWZ2$+gFUh9p=jg0S37_=468S$+2OARBvo;JPDf; zK1bU6*wZ;#p3D%Bn~%LW{b*c)Ud0K?Fr15AImLkm8?YUEbD(FrS<;m_-0w z@GgJ-6Pv~?oKL(E$rcQdbibw6(Z}{#b<|c6S@~!CN}I2;v8|l*1@A(q=cTN|8amOQ z;=NXh9MHxC{1d0A!xSTJW*R0K(FF zRngf3Fctx*Jw$cj#_L|E^d(PU8~jEpkw2ZZK2kb|>enFCk{1PP@H}+o{5ft{spr-u zs>)COm^tT8)2ymnf(h_ICSVIUIZ@FyZ{_`gew4b~*m0XuVUyF?vJT?vRs?QIMA)r6 zhHnwpe}%ZVG8dy6GyHIzrKN6PY~N1D9V>jiy}eB;JZdZpj~CH=U#T~u!e!A2Je0G( z%mJ8Y;J{U2(!aXBYyW`XQS^j_UkTo4mr_^f&N(~SUzc8UZq>AE-SHm$A7&N?l5$u* zL>ykjutz#i#)v_V-g;kUj(H?0-`mE!knhWusy3LrXUC4Fdxy{eq>x(m^*i*c`E~LJ zpkiAjmMSyaw@^}VoJ%PK>Q=radvvZO)vs5LTY=Bsi@K{m8t7@yLa~h5zW87&Kxe@{ zeB9=gAA07Ke{E527~uf1ygxuF6S~wHCW&TlsIygTQJ9|psy=bNpl=|@8KKlo74hUw zb)_OajGDu-;!1J?@3~cO=QGsueqoS=XX&eH8U?=e0VXC}mH4f|?kC+7oS=#RY2)If zbIaPJvE}cCLf172Q1!IvvE2FM@#g1{C}}j!M)cPeY4YG|MzENq$|j`7xB@UE;I}ZV zzRT+6MV&>JOyJZIeBAZ{aoZ5F5R|M!3bM?RMcwmgI|}$0oWpABHoW<-jnv@SyKS-E zXOcH@z27WdzRQKMx&dm3PC#qVn`I7f!Z4GtODfzdOq}h}BsE^|zex|atJdH(d@&30 z@o0!3w6`q`a}{>)2Sl$#U;6bgiLDP#63xA)gQ=L~W97WUf4C{e;TY*&pEe4VvvqJv` zw5+j#j-DL0u3(nG07H|BAK^Wb>tM^Et9iuft7T!PQN#If_^83bL3MTq@ydogk-p`j zJKp4wkv|SeW}HwxTJ)gCl;g~P6bHq%-SokH7qX)6@bC^NG}g$rDYby)ajd%pOYlk` z&~sR?{dg7Ca@q-O5!{tEZg06gcrU86YFCmqY`U|Lnv+aC;ZBcdVVAc3J6OZG{{8O_ zuU%hwiib@zIs#rR4YOTyv2v=)-ozX}&e~$qfRM?%`A=He@6*fdcd+qVgK5hVaUP@| zt#L&I?h=Ok2S7(Tp>COPsD8Od02UbgoncAKQV`bXm1+#o-WsF%`1tsf%L>lK_;_b~ z;}6Y^Ybo6woz)|sy_YW%5;zfpg+Q5r@PZOp3Z+#@AuG5~vh zd%+TsW++Yx{cPTuoSe+R9C2!N5AME)mDz=f-L3f#7f$rxh~@Yz;7ql(sOJkP11hF= zq3kak#_8^~mDcB%+H1D=7X+N{j<|GdySYhQ; zN+nI^=&;{n2<*kW&R_2xvBQ5L`n;9{T*zmcKxlUMy=>S^TNRLPNJxAu%{OxbXpx+U z?+b!VmET-ytk9zR$8&LL8JTjFWzBP;vw4~+&9#@G|L}~u|Ft|hwUDERaPOwz#vd@O zo6}}i+|6%t#lSkl!F2-fV0;~aql6X#^-Bl4f_}jY*I6eA*#ouv`if^K_ayHDPXmb2 z7@{pF-z=4}(AOJ2RC)A7lK%dIR**2D1tKluiW(rJZ3)z^m;#5D(LZhk z=-t!=_$di@@2JMk9~&1+eft;npV_vS$&Ng<97EA#OZ5WTwQSaxdP0bw60ae7$|%S! z3yecBRWZ%J#!UD*(?>Sa%zOL&qxx)#_bFjt8f@Pp#`)=0PM@fjakm0n@ylkqS z^=3PJ>d>h5zxAp9IsS3Q?qxOeD)IHIWZH0+_k)2D&ztt-=;&%px#J%UwKNfdqaa<} zak*k)F)6@G)i2+uyp&3$7hPPJN-P5I^z>ne%xB(iisnIfXbII$pd6f!J;`U63-Xn| z1VNXdKgQw~u8*a@4PA}1<3jT4jE&C!h>ehwiwTc#Tqh!-V9k*kF3BR1RJis*`>sSB z_qpq0Q9r{M6y!hV^(h;1LD-jfOzY(p&NKAyIGd9SA&QzBl*$EQ!mS&E z{0{#xV(ZTjSF9_H-G@bG&xCud|EoFj8g6_GARWOy!mq@4-*hC0DZoWF==?}I1vo(< zJTLinBpKe@7utt7N{G@^?PtanQ+X94bleTeYcHlM1g$Ws$3fTTmQge9wry`U z6JluM2u?vADBNnlus)n|dLk$8H{>uZu<(o&^4RRFCqD6TZM5b!F^G?k9KYxRC(Ke; z;={{PBDQXEj#`1?#)Rum1Js~U=A+?Vho9N%Hu_{S&fjruzNcEF_(itQl^rAAlI+jc ztYd)5zl{wp9!%YthuM=86M?hqrj1qq9ALGhJ*;#NSAFB-qaQnEC-1cY`eAw%#eNVk z=;2X?h2WQ5qJl2}dO1#zX+}w@VKqHc;sc=3(Yg%)YZ`8BK0-(cMx!_PmM@BaG(TU9 zVbXwx+Yk4%4(yzczvgrJcHI9kJ+C9yHbtG!ec^2WbcRU)HOLpD<#bY7UD?MCF6s7V zYW~MO;1w@FEe(Gm)WUqlBE%V4Nn{gOY=!%pE+kKelDha=oVf>uzc8CVSOV_3gU*n( znB2-I)%|1movN~{)gHWR?#&j)Xz7JdI>$f8sZ-n(FLT<*2Qr2-416z^_ugzey0XX) zGo~4qXZhr9HN+NyK=7j&0RGalS0(gR1You!xq`o6%)>$yH`m-(;Zr_~Ll;ed;!M&3 z$ISuOyAAAix&>RA(dbj2$9w>X6|R1yh6_vF|MIY5xPM*BxqX1g?zsF2PLnRc@< zLT&?!%BDTsMXW<+KDg_9WeZNmQcVJLQ_&f82mt!NA4knjmi@z?wjmX*Jy!L;w?0fK zo!R*`Ae-_OBb;|QtQVChNMd=A;JnQ@_ zwVpoIt^Br2ptR>Lm$#)82^oKkP3gb938E+kWFLG>T~iZ(ulQ)^4rh~s&+G@^K~AV` zjD88rv&f};L^SVMs?6N_XK)kuHtW97mTb`L8x>ACw*hVX_MOuALz|*okm_BbNSo(K zDz=2rW4fzSiS7$I>1cizvCsx1k?8av`Fr9jU4*J7Sbo#8nFx^t_5P%gjotsA$;1SckpE&81c4O_Ou2D^u%*Are+7J5w?p$lq>B0n3$2nQ z5nn@$wFsdRL$gg=6f-{`Kiz60zfvN?hYWIAjWAYAk5j9zGjDk!9`@X-$;$iPu;%@Q$-O(iV2&Gq*Q$A+0Nz!Gn z)E`UxRLYK={BEkp=NHzfR( zZ%S17T3ao>)Ha*X3H634u4Anklu%N!RN5>>TxON|Y!GD88zbCC@$E}E$dKs!hpDT> z8RTD;bzZl2`mnrR$2}wi{y!3z77vl-pU%QsP2RdIR}mk5qbUpgM=k{%-aw0}Gk_mw zGbPQ3={Ep+p>3TNQ4?^u%r;eU0!-+D!lyTRV)@6?=!VQ^iMJBceh6g(fvc_j#|I!t zp~Lk91j)6Es@{m43{fa2zWq@;$VI)3?B@xYZbj6+~{I|0Tlw%EZ8H5mh{yunB2VLY~(Tk8Beg3ObIiI9a3 z*!(;Wb@-mfercyk~U7zm^!_xw+a+QqjekbChbi_L%F$9!OLI4!pZHTvSaPvTV%z4`Ev0)dJ~ z2%&l^oWu+8&uib3Lrgh~&uiao;u!VB#QEYqnXi;97{`6@U3B0MS1x`_%vco1ni7R( zvAzKj*e#gvrEhg-Oo`tEgHLNksPW>HlHM!kDMxHw^F|N5s=(Q9F8uZwm}c? z-WvsTfEWBDse8Bz38PU%w~p4wS3`AYLd+>}Q%via+41gH;TA~of8P>tZniE1&_SK2 zPd}97BCauei3ocT18qM@SbT!)NBS`GeKelJx8vLJ6BrfB-}qTj_~YYmq&qTU7;TbE zR_0#dN|35>vU{bWIovqV-(Ri3KEbO5Puy$inZ5c?>T=*uFL`NVG~xY8%{ANBnL1@S z>X%ewN~B-}3V45E6{`KNktT;!!A_#0@)%aP4 zS#Tcu=3Nn+qrdmVPbLrV{V`zTM3F@CUSg?Vy?#O(Mk4eQDbT?rrIEeTU^fR!w5Km^ zHCIg5Z>d^vp$3H$aQ#OS{Jr+n<05@CGcSTg_2KBue+{@?*?^ACM;@U!M?4`b>xR7T zecF-4J(wd+eI=>|%q4`)GWxzF$SuqCKbhK9 zxoCpJdF2gHpP6=IzYA66gj&=sIoYP+O3yk24m$#X-49S@6-xANn}ulUjRj8L14(TmW&&$-Q59mJHhYhVo#MoDH5xOUFlw&Vb#9-k8Zl+>Rn>#6;>^vwTZJe=cz zFRrf8gvdt=k8`{cEgZjmz1)cf`qsV83U4|_E|oc+nR#Hafu4&G13yysRv;wPiTFy^ zThfneIA>H;$$|KNq3Uq*Z;S&2kw&fW7Iu^pOu|Xm{GhzSdA8G+q-yW$Uu!4ZRp_;M zb0uO9K>m!=9T~o{YrdMI|BPYJG+Pf_tw)3fC{o{ST6b*8u3Wxqw%~>iyEfi@sVp6S zHjLx@(JFRA0qoZK?A@-Y2n0{NfjrwqeB)ZN7pYAnw9D9CAdlw7>M)A?B2DK$m*Q98Cem@YhrB)Cyr!rs-=b|{w9Q9%e zSJ5gIV1jQ1=B>B1-Ox~TAl+4nD}KrDVK-u@gjzwYaRdESS9V*(vJm;d;Z$Mk%quqg z)+C&fC5C;Qxf%G)l z7iEdaAOe5M8BJ)dyIaUy?HYwHKQ~v&Ud!m;1}p(mIQ|91dy<%J&F=UJ_0bGpVToeL zj{@#1F!0eK6a*Pg*Q~RkfavuGQ!TtV_IN$)A<%h}RvJmWD^H!0CaRGNtgSZyg5Ctk z4L@O={$ZsdA9WAEj|bd-Itn?GWV072V2B+!aIO;rZu$WBtVvrC=$9ZhsN;SZ#_*_C z43v^c@FL*&-mPQTWry_>{Bq}y^VSTtBcyO~G)y)MlNrZCmh4ZEs%%E~OKP;5qKw%H zHF)}DXoAP zC)-&OBBbrB6V8ZvT`w-crX29h*a6By?y~+*Ob3HNR$PR!abL_o%d;D2?ARpGEhN2Q z(to7*_A|F%uL5Ys&%L#R$U-t%UsX?hyMmY8a@?Yn=N_dcEz+++(YjAR;$!_w@?x&M zcjiaTP9Cq1)>W8dzyEDglo^ z%G`(UTw`ygkAQ2L!$2ZyR6M>g!RvoPdk8DkLQ+wT%mbRrgET@Pt?{9E2K3SJ-)&<;vVBLJO5Sut z3iQFDn>oX*6CrQq-S!e*JJFzF3m2Dv?3k5NAcr5*rvI&R-&U;lLt0H1p$LL*g`?B# zN<%q~sP_Q3+MEX=)&md5FjbXT2Cd(#2s?gKPiFRS82kpsemy%-)qZAvz*fPtX`Z1_ zAHVGJP6)UseIwO)sQ1g@O8uR$&E$b7fd&6be|BZURvdBYJ;D#nfeOkJ#7vXZ`O#q<3fvmrO^*3q zPdAeU{d8cZs0W?Nj#!Sh70l8~C~y^fTbfK>Ka$(ePm***7Wx3Ic$+pfW@0_bMO!$1 zcoVSn*r4#Zm;`_g)gPM`fSF$<)YhwepJjBatX2QRH-a)TGatXLg@vvvo`hJF z&yBuCX+YO!#j(~TC|&_KJx5RqSHvm_m^y{p@xY_ATK6%OH1$W^Gj!YU=IQ871p?D2 z`|LjybAa!r{wxWVQSvFwh)!2b6t=x5L3^idBXx_pP-KMcN2Af1jxd}?@8{krU~PG@ zTLEixUwF*tPt1 zt-`x4GLO$FAd+XlEIo z?4aq931I5f=)RE3RYPa_Lz0066doaU*-hDW#0lz3#s5~+rjC03t1H~R!PPMQRX8fW zMq~jeF;@jbZUf3)UH6+Z8ac`D~XoQX9i1%cgillx2nQYxTc48xDCKHB-PdBf8V|wyit~5IR=5~KhfXmKxw`{ybOa(je`}zyzvhA zy@Y1XgXXgA0?P|N!NdcM;E_NscYns}+GXV&l-(j9kfK=^_H;m}r|5PwuJWSej1Z?D zsazQkc2BSR6PRJZWsnp2JFD`LPXEWnBk1@+&%eF%AIiZsFN@u~BYuQm+y@M`L;^R| z^%9CWBOiJwLjAd>M@_oGg48+`t!oQE(gr(7l4m@1<6!0cc0Q~l zcY1O=#<}3p+5Ry!9F$#RPtauBd`i3(H{3YKZK37#ST-DLX(;E$XrE)BLl=Vxq zw)TG5I_>qBu_7<_QgB4n&kRV4`@;JAy5qhTSE9RY;&a28hu{o{);!7WifwS3vDk^3 zIrX^zVv%DJxg3`QQA(xSsLJzU#Os*QAJL9HNV~9QcqGb}p<_#E<@j<8QE2G;8&f8T zqnly}j&oCS;OG*_7;zSU^=za#0&nnK>n$Z~(89tp7C;mh%xVZNa?*mv=3ZdBFMZd7 zvPt<8ZL!O8(1+>6d57;gy1xD*Hyb;Li(o=j@WM4qQXR~cXKY=tx+|?TcT?PDm3*BF znhFWSksLhCzofClqk^5g;NU4!#a4`P&I4IMV?GLm02S8P<|X>Z#g88i*9zF0O-gjy z)FYH7d25v%8AN}6{ZIln18oE@Z)~J=Uc?220kt=!UZqiDo7dkSblDrvewLxPuFj?5 zD+5y>A4@}09`s&ZTsVI;#zzi%S0vH@|fy^yH3vw^g{J^&EIrp7HM8yMXP8Y{%ty51?YK&I8oT(x;BtT4f9tP+U9{CGWf7nrYFmTmi(0iDx<<_67ERpJMWmdM> z(a)d$!VC5muiLyFMq}>6=_xl>yAMX#8l2#9w}(A~d$KHibh9MFd&ybGRLdrvDPM8( zHgk5&{PUGKE$uY+cB%Z9Y`?tP>oh4hY@$J4WBA`@Phcr52iQ&s8C3BaguUqQ<3{el z;Hm2B8jbD`H2!r{h4GRDwpL3k-&rh#rC3Q6bHc=5S>%OWhqd_7zkY0Jfs)N;dI|@7 zg@inD76+(3h5>=bz6IVK4Xm6sepxw<11e#)Kd@1nIGyX+h;KI{ zzW0Feq2&(L@g)fQ%sT~cW0sM2l9F`e-e4XI)cwi&8UcVXl4K@+t}~!&vBf;>Jk#@I z^spv~^#Mi`I(FPYFu+5}`tXEpS_d^)<37fPJAnY!_p1OjBB;Ff#6)Lkv~3RqC|a=iB?wDDv6jP;N84}o9`Lz<0lh5Ajw6aiwtApEj#40Kq^9@i z`_8}l<*=Cby6_M3k>|5>aR|idVR{gnjzBRS7AYTr>~O)%1ppCX8*ie8iu= zeBb{4=$x48?(Up6(`}}{YSTI0-7!qg#+YW)HB8OSFw;G3y1RLv=e_)n_uzl-tIzXO zAmY7q`1H?<1qe?&5AVfwFU^T^iX3y@8vQU04q=vvh=hduk!9U^Wv3iez549OkEDy` zP{KO%8nK;oqFKHu8-|rI)<}FwEW)R{MPuZCmyBpoxS*=F$XR}q`|ziHLz#7Qi2WeW z0v$y308c32j@`w;OPN)F87CygrR)pOi1UJ)8UA-~vBEyGZMDkfPGUJUrDqUB(j!Pf z>V7OBa9r)%;j})O8QlW=A~@U7SMvd{zvc~S4DP=ROPk15l@MaKY5lKy#__dMFZWpk z6CohQof&YO{WpW(n;O$E_Ekqkt&y8O;N0Gg9$IkEWsXlb!aM4fM?*6v7_EQaadwx< zC$Vg@kb-81$OG??oQLS4UBs*HA{*H4Z~+;C&aJ|Lg%+m;s>4CvL@5h0O}3 z5yt_*+QN77JeGjYewbmO{%uCIAd9a(A6=}8RwJVt4P$c_MvcSrJ4Mt z@txdRZY}p%I)*xa&Fzq>Ep?s%6UeJxx(5-X-qH}^x0TZT!DF{~aH^XyRhZxzVacaA zN@*%k4s%)@Vc+EB8b?{~-My-xEze8u-zuchraNFE^>jIy@Pay~KJgD&96E7NFbSTQ zmHx`E<56Vhc5-(9MGi$q$2scjySpp<7t`ZdiJWr%%H~B4rI+s@Vsl@%pn?P{qN8f} zPSOpL)94pF?(|{kug&NC;zWR2&54_s`5m>;%zyV)nMO>mN!o5pnk}MYJzG9&R$MqSt^aBXe8?+U8WkQ`4 z_gd-YRHeavu2l7xl?0+X7`+H8)>bv!`Xz1gqO#&#G=&08A&v=5{fD>RV}6H=k&yEO zEgco+-UPW}?;g+r*N(B@WRt+6ZFT$C@XGZpdA755 zQQ{sZmSmKqgx%!S6-bN;8-E(J;GM%~hU;KK$)%dM#0wT6 z*vqfPYK*T>aDU``GIqy_BN(O-zWV_u0KL1cYFRR=$Oso2jr#jetZK~e6iynlDnt@x zl>%)s*`9V$;$U*YcVd}U$3;KhIcX>YGrUj8s}$sH^F9#{y6}vT|A?zUobTUu@0NtU z%@Z)5CRILvyJ6fRt)?yX(2P6R%SWe~bhLzZW92iB=Y`s}N^*^*xV*9cT+~=`&8N`0%Njgzcc0w- z{A4}2ELQ6z==JN>Q^;$~s*14jMt9WNhK9)zT_FVnlG`ySR+QqLWi527fuDVR@({@5 z-~agWLy6%5^oN-QlFx01wS3Ny^}}*qR((wGpl zuK4P81S%Id@x}fe-7kjiGT&@9mSjKevO6pobT?E`)1p6FBAVw@;abYtzwM@WXk&fW z$Y5>62z~BvP=7mi`(us3R@^_iH$&+sPLw$*cL}pvafV(*2KI7yKnLP()8eGLr31cI zBu3gPU9LqrQ+k{KMm7k`hgLEC?`);G5f%|f4+4Ihrud+j%(Ip-Z1XnL!#{2#jS_q$ zQ6zo2!6zpAl1j=ialEtUk&r4Qm3+~A9(f{pwK=RlKZm<|{cPlX&hN^)jcetVQ^UI5 zd-RYFzNHL^iSq~g6$q(Qr*~i;{?w+imH=|IYFZL3RXzunWi!`2jGx?XZ~x@SUwlY0 zLl2fP?t3(cAu1?*d{k;0fN9_cy=eNcyix(2brx8y#^QI@2| zn~E{Td-|GIuht|l;ae@?&X66=D^eFVmvzLZu*L&j}%BV?NKV%ylZ}0lGgLh0AUkpbD zBOOQi9BIm9jCZc))0pE6C1~Lfn}5!r`COYY{b3`H6AP z7)i;!eqICT7%puO#~*woena{C)#{JepbwC55wKm7_gVa@!Z6OPf1GPj+`%#vbC?rq zp;3wWRnih$3VW6p@@!$XVb)6T+g8w;Vl!s>4;x|mz?bPHp zBt9FTHQW`~GOQV^mBVm=YIl~cV#9wAql$u5ESe3zO!;N?GcP_HNF@idBzX#e8qhaL zH~hNth@Y}5oW${SFgcsAG&b^_d`~8+8oik(>aA3e^^29!t*>*}3f7XYHqLmOr}+#R zM7vD^Mdtm5?QTRo4BfMkP*|KhIfm7jznc$f=v7`8kdGA2Y=maexM^@PPsHx3Aqo^PJ&A^e18N2pBnVtz=du zMAIdam#i3PQl@x9;ZedSl-E38!ZTlC$HYh_@W(-Q3?Fg>cWRu zjHD18r-s#U481%2_vsq{xN9k|(ph3Kc$&?e0+B~D1 zsmlbYvz4ou<)Trrwz5Z<#iY;(_M4CY5 zEq5)SN^z(TUuwd5QDcOW{#boUPJ)s2SiOX{7uA&rE*DdB4l23B?eU9Y#=^tfAG(t4 zH!cu+&tUJ=N)8^PnI~*A-^ge+<7=ur9N#p@ESN5aHysf}!=DdO#6 zMCiMGz1${xgGxmL`nk%FPU;tE?d&_syX2RK&pAidGXPXCb*jHzd zg<}z7Ll@MgrXR4}0{xcL+k3o6N$InrL^aSlEjSI;Sg*_2U;Wqeyz0S?LYv$?afY1` zMZF3K)%lIHGCfKv9+Pp(pVgVF8@J8p9|8+seJ0|%u<=8E?058c`EGbQ=ym~VweX<* zI&;Qi+vzK@?cT zQOHYP&?0{1#UA=$@h}7tKuR)9Dznp9v*IY@GbxIJ)lF0yp=sl&;Mi2oBgcleNGx8*0^xq z5t;ksANVhEd?aj`@OpzNvDln%J9DmQ4R5R=VanIFO=iN98^O!@W*qt3^R@vAA9`$8 zpr_0ew9kye3z4PdDT*q|Q@+5tp{27@G0+huYJ@?hiEH2dc79+!KyEG`PhduG7Q8GA zrO_OG`LcR9%^gXG19UlljvgMPWaH=>jHBH2D5~XRJ9BR3aw^t(1Y=EHBTH>3V!w}@ zY0>%LRd#V+!~YSuT>;X@7thUVy$ZD9H;M{a23Ltt`PYpnTJ!(7Nc|D`>| z9J;+d(CZ7ZQQBk(kDO{y7v!J)f&NbJ(_;zN6iyyDM?`G@YSkFY*HB-~`G6}Y57b+4 ziR_2!IWq@e5WmKQ%Zouq#Ns*pswy@y!j$LtB0aa@-32XiE3R9f7@ue}@$Cx=Sx>){ zo4`-V^Px2rGe6PCqNC+GFvYbmTCIYj9=`6XVR20+Jods$f1T`&N#7>Rfm2$SBv$?j z{DERU5lqGHc8n_ozBkyAqRgNqxQVIP-<5H4nveV@d)F)b?32OBDa1Z}t;|rW{xY!u zUX-EQWHNMxAbQgj`c`5nKkf?=ZZWbOBD#D_8pt z^O0G9p}qhkkxqckxaUu@?*Wmf~5J2c0sk8gS~T zV{e#ZQ)EMS??GV@q@f}0G&-|{IxdjYlf0O|+|eG=zd9Kgbr`{-^b4arDP_Sn!9qa( zJM$ZT{q*{VG2Y%JRkU}wc$DXgtPnjFQD1z6|M>~ohtB(JbPke%oRTUFVklh zX{3&XndyV5zO%mtlX@M}`k$!9ua$`5tO5gpKa?YX=y8SsrR5je3&!*xZz`DM_L^3Q zKKPE;lYQ8sZbGq~Hx+nM-k2Xt8?Xhmc)`HaRx*&-v>i@g_|qQA{|7^k5G^1Ag9w`e zfMg2+%X7H?rS!bxl*{lpnT*!_$7wgyEXFvL@bUWPDQ7^t}XljDN@uIS9BZe#o9;`Y& zG1*ps&F(QK88`%PtAkHop<%%N=9Ba~u!BKv0Z8rpL&>@LoQ<~fugKC9**lgl{>WGo z2(&48+pbxiRny8Je8klmpVTS+dSm!$N>DS(UujlqDalIyY!v#7M}7WDt!IR8AfoAK zb*PX*D*X#WwAa(Wo(2NK!~H zyhy0gM*u5IQICny^ot#}q|cn{l0&~RQn*k;Hq{YnMSjn}xB;--!EL*_ki(ahLWp zbQLNo0^bEwd^R%7FScSJer3y|s#o>=yb=Q03;7e_$&Vcu>EL5@NMP?EMn1p+!x^3< zJ$TITy^7jIC;gVX5@(s`zxVV@vM%Wrz>x2>mtN3}@0^dgF|-DkfIkSMF$4+0jNxj#wpzN0}(2}Xpje;F&N zX=9qz8Tn$rz-mvZ+gY{p!dy)DMvN};ujWU+3Ud6ava|2d-v#4OQ(i-Y`TqH2@-*Jo zh!fl6!{5x`|9f4qnf@yy$(r0mJnbh(WNI?G^{0_~ZqcI^aZ-glV03>H3a^>T8nUUL zqdbeg#H$)nx;he4uI_5NnNYUmBxJ$d{|5Hevwze1PrsP-=F%rHCzqC%&TElyl5!H2 zvnQBcI*49lt41`~XkK5lW%15(a&Bv+MJz8H>p1=ZVTw0mp{HU5(v7{RL0Z--?Qr2> zWFP0X!K9c8G@Z;&tWmuQ?ZaU z-GC$7e!XPp7(q1Vo-3Yg$N3~@VD_gk6HoR~(Px@uMsUeHigZY(+8BS>JZ`k)i0?=L z?jAJulnil*go6jO3*E67y?sU7r^OD>o!CpUgMbJ}T_FzpFYVF9Z&uq%B@WrcYHT%=pk=71Sf@M6&Y{MpZI{~^VbBk6y>hkf3~ zWjN!1h?^c__1}mqUKmP`Qqj_h1y&D*#WusRLr?PRpP*Bo6j{Xg{CnFv_r6D|&2ChG znl6c_5%Ex6&`n*59gSI6;LIfcrO3e?OWDphsvUa>=ifDGk0@g|sVVD%LgM4OA_@w} z7;({|vJU+#4k8g0wV(4}3cY%!$32@Dc7MP!c4X`GBh_x_KztuyWr1t(nugRiM92Ha z&>YEV67%_PD+S;K+C%@|jJPb*w3xY5E34(u;SS#lw&1v!O2{d`R$^KuvCY%WbUN|L zXO724IZHmEf}n!=204@4_an^&y|q=|KY7ZHO5P7h{Y`I(9<>)fIq4UL2yiDx_S&ik z#q}0n;#}^V)f2vPl<%(Zaf$JF$V!WnQwfX-_|O6r8~{f#16r!XUGvK}wGzQW7Feq2 za%xnyfsAir=-`hVGwo+?cQ&htvb8sD>=IiK7WeoWxBWX`PG1s5Mb%2xJp1%K@iP(? zB2+EVeePcdbj+!#pD`7!X++FJE~Zb=7xpx{VB-H?3BSK%H=>jKexLdbhN3R;ptT?L z-2U#E({wBu>SCFp5c&U3J1F#~R`wk`5fCb|^Gu{I`8#~3;EYk5mgR8#ZIhsPbcRy) z$i`Z@S3LQ2kp_RU@HU^DApWP9*SK^LHRI0_jE(vf;~%JYe-D94@C$vBPzs7;1;vHt zb26LNsb6U9XoGa4d&9Bi%316#4~vtt_2!#t`j2Iir*=Mjv&SIwE>;}50_SSr@luW59Xba+eiPH zIuD67H}4u9k#R<~#i37sJpD9YH3d@?*4Oso{TH3=tM`0I@U(z_3U%&ChrojncPF1(a-7P?S(f@ ziNaJm5b55j?!IS_tL#yZJG7^sLK-}yC5j_o5>+)vk%I!g1 zBuXV>R13Ch)zP-pHz#@RyXn6a)Gng)*qGZ5wKnI?_T`8?gvdcf-y0IrDl{K`h$@H7 zRNoM)pK318rTWhMSJbmp8PTXWD4u-&%k2Tm*7!)Cb;6a1c?7d+VIa*cIQNz3t?e0~ z%c!UkMgV%|=KewpfWYsaWu=bVX5cjW?NBTSs-%2Pw?Dt!^*yXyIve^S zEtwvv|GZCm85R+)h#J>jPt)%?@Oif=G2^dz^{SHm@uzSWRTybMWuLtf3YH~yDl;1u zNqUF7|8~SG+|JEA*`QLkhxl!1H-cXA>-C0db?40v;M^VwGngG3%0hAS4}8nRsFd$=+(6Vrgv zrNWfr0>O#0Uh=9KT4Q*fX7|iy_iBgCz3>#sk5-L>m~CDFn(qUIipxTx|( z@vpzR@RL5naC$~n<}U(Tb-fgO=gO&q5_*wF^Wf;`oqyhTgm%02Xj|a(4cV2M50+E@ zl;b%_w%fcnPf$+QsK2POxwXa*QwU7<8<-N4c_Z3pP`fEy^wHfZ3!QJK5?7tIw!5Ze z;Zcw@=j+@^2saRXuGbu-GdG(Mw3``(AYcpOIRX5*jla4|U(YW1DpM^g()^po`E#wa zcoctq_qnR6z=c6*MA$tT(5u+dy1Kgiw(kgHZ^Rr_qhIgV`8HWGigF)(7hVW}Agh52 zsX(Xgq?eI_KAMYXa$vU~cQQ@CO<}<-*KPvOAFpV^QJ_`<+3 zK#Zl5R$EZ*esR;UDmWLWXwqNJVd1B+eYcujurrd7K)6!ZPuqU8^9iUHSr?k6M;K6C z>C${|>`WipX8L(d$m|Cu?Z<-2b#P&f5L?2Y72 z^sSD{zE z`3j4N7qv>om&gI5-iO6pK|U_HJf&iy>N0jQjinMozCE&je1yHNR@{UWcv8yja)u@I9IRAAYFE z086$UCGNpUAO*A9Rs5*uolwfT_5z92-LJ_M+Rw;60MQWrlPFxH4-MK2%f)`Y^B3)wj{gUpda@v@(Jl4d(ojr~raYj!>pvlwW#6kLMeoy%1g+fetj zS~QY*$)c+uMUcY-%pT>vZ63avdgW{hYeGRuFde!1&qP8rl{08%vRIJXg19hC;eWjM zDjuLs+T}7oPLREdlr?I0p3}od=bzQULBZ{KI1|WLO<>{YxZh7OmJR5 z)i%c+=jYL|`>y6sS_BtXFMZs6Qz$zrGm8{c0h9BqQ}(%nR*eCyPh^_mE-lMudDH68DZ10=`TjnHgpw^ zQ4$P@J{kAAlMbziP39O0ilGnpSb15V&tvX99jI{<11fCyZ)*2HzglP0UPP$uvk}A+ z9BO|1ezI>nGU~d9&QNH``H}F6NXoBK0>TbGjt}oRgVy0*B1g48M1OCh6bF@1!985< zN9Mw1);PS_{J>0vB&fprmj5gIEAQoA81b9kCdLixTJU?! zhjwPiAh?=#6UA>`CHYPQKbd!B`|ETSgU?{lc4LCB-Lz_&_OC+>mG|1Ezj4cXoasQt zW|3dS*dZzm;<3tSoU+#g+K4snrTg`<^QpRR@boK-HLBdu9|(AWC-a3K=e!(|taHDt z-l-ypy_C(QuEy?{U&c@m%fJ;y{W9P0ZdL^6laKr9L+y%gbY_rEjGZNtL?P$UOd#@t z*wW4DAV2VH=n|>#(EJ8WUHd$CQtQe0Tae_6L@Xl%S6_?GH=FThPb3p5)LhzJ7C2rB zZ8_25wB1UqxnQqG(U6#lLL0xTw~=Cw7sU^l{GVD`r2+mz)7Go!ejx`<`%R{iJk{!q`{bmq$s3_3dcFz=Ew8H!N6`(>s0JuR^r zGEy-oWDMx!)8O3HLy!M&nc!P$8d@TJxKNRG`sf#imMQUolA=`-OTV;t5mF>**zlJd3$hA67iifsHt@^J!EKqHmZbKV0T+a zy_z4SakbWSlb13Ta`NhGOQuq7$aAa(wqb=q2*P-iSKso@r$s~D3{uN(la7wv&bqqs zLzQtp^uS^>?xArCyVmzgwe7k7>rFTBmKw5`AKE5MCYF?yTSI8?%`V^zT^%68Gm0?x z0(Co1Px>&FgBiZLZ7qMWQn+~W%tff>+#>t;{+7^U3S>RLyTF>honn2X#}lJbrgENe z-AjrziIGVsd;i;z#W@cUw51f@azz^3&SH?$(S>g0*xmDomI8LGkekT6!-rbpuq;b< z$YUM${(0;B=LWnob?(dhP5DwJe=fbGbRRZH+h7`FzB@OsefZmn=GxWhonJLstS)u5 z(V2hSe_Cj05c~iuYM3!3f!LU!oAmb>*H_Qv(~+e;S9AR45?;4~N(ARB67WODn~+}n z2hxE-%l#XTeu^ZOJ7lJS76 zsFugo^3(qWrR7d*-tw_;KM&=4a@ak6;;Nw@DB0!PX8mHGlLUf{$lpD&x(Z`fy$?bC z6MQKRPSxFz!^@BqGQ}m%wzC)<1trlP7Kukz-*z>K6_V(3BE zxI=%O!ONY&EX(GU2)Ibx)!#^hkh@jn6=1YMMCv7aysH+zcb>YJX-C4i43h=R&F4)N zZe*oT{7AdPm|iR}pyp`tUr+BVsqPXj3PXYe)2RvB9~8%$H?>>#hVGKAazFCvDA5RW z$UV`Lnenk&UAR)>dIBiysq^8@F4+J2-S^rKK0d*`=fN+!_tUuf^-=-4t2p_5DP6D} z7lGW&MT^@}i(6di`s9xe?WvHvS76Iozfk+qd_-OA@d!n+d3UFG316L}8vT-*4M^fb z-xs4kh&!B``fEu7Ln5K zd${q!VjahM|FpsD4l%K|fLLqV|HbxAa)YtKYA*Gs25hL^{&a9Qt^G-G@eom1QiwJU z-il2Te*)u-H(3#5t@C2I;Z<%teT>!<+Yu zBeEg-Y;>l_dTA~T(5pr7ndQL4;2N+~tG}M8X;GWB?Y^-EM}LRw^{mYh*T@|0-mF>I z>G6%Uk3>t1f)20GWsjjcLv^$NrerV(Xw zC@Y=1cFVU?JpK0P@Hq0PfKZuuS5U}4$mTF2kua+W1t?!8h8aY&qz??hpoQil_HjCf zLVi3l4s$DVTkAwKO$vvN)`^{3UM&Xxvy7y9O;GnWBrh>2PTC8L-{hDO5ymh;{vR+c ziHI;~CHUg7iZeiG^l-^;>GVU_4d}4e$X=(*&UFS$at~KReP`TO_M|xZ%>%M76SG1O zdr$*+WCMkR{IrA06X-{q2IObXbNl8lVu&K+sQWLZYIJMJY(E^}rDjYfG5Bi3Hzp;~ zR8(S!6tSf(Zfv)&nHKtgsUl(IcZEnz3 zVeeA#16q#T@p|qDDCK2GR`P^bxI7O5w$Eo8BtQX|VKTk5F`7-Jyit{T?_{3yGVW(* z=weN`Y?PJtLUQLIVYtol@85$7P77YW_+m?-N~-~mgrU1F=FcmhWqGlOjp0Va@`|2| zD_60DXZP9n&YQ({O5a1A{8oFnR�uQq-!;;T$Ly_XnHfc`g|20DW<=@@=+9<}YDj3FvsRccUuZ+! z@s0)S%EYRW2zwY*@a%+uR_f{vpifVmx?SfZPenHKLuqB*E6P%vNO5pSE}Gqrn%&~~ zBw75{a<&f2_VOMM2*onM8hOrWYEv;KBe{L(RC-@nYNu{yI!;v-etMy&HukJiz1x4`$yw`NQMf_gM(;@!s3knsa4oJ@$hxlj zP%$4|bz+7=0Y5^gA)|=oP@2q`;Vutu>51&4M^!Lc?!tycuH3B8YkyF9JU{+*o zueMTif`W`OKVC1o@@ua%k|kjVVi>bB6o(~OKgbyM<$Rj%{=fh>c5WRz1~q_9Z%{KH zireqyNC+$JsC-fLnD(~}um6V1-PY3DhsEQUf$5Rn8Br``X1LBUMO<=rTXG6;D-`lS z=#3abM^$4sA^m$72{l8E2@fm#1(Ou}JexnegR?TPaZDnls@%TgPJ-j-XCbJ7#cIi8 zs0vt5fn>bkOB}1~PQDUnmjl_V8{F_cL`+G?e+~0Rf~*<78iwOW!Id++Ih$%6yXS3( zw=|qu3RoQJ^k8T{!98PqSWn~>16bI06Ihjte9x>2jeh6@4SXlb?CIB_C+yH)Dg2RB zTkS*J3Vgr==)F^oiyKL;bMkJ8vT@?zL+gt;_b_jrWc*#7DB)JPlwY~u)An9oHpy%X z!hVyQ<^luUqp@;}!2L3}j`RNelhxuVVu-<8nZg~#zUoo)==_&I^Ivj*FECzG$J5Qy zAWw4E>QGNqKuhL3YG17bHc60ZhLt%X5zfC`bCHAu8L}jBuEN+$NZ2?0xTL-q(tp>Z zth**Q#ynmE#P z*{R#%n_snT>X+U1jv1HZ&6;RwdegfiGv_DhS&!R7MP;|*eT`za_-pd}o6YWydL zHzNDLle>cuE+dheDaT5Zx0=!-;o3B$F;)N&?0SqF3-ofkO1i})GWM)?iFyMmtIT{{ zI79USiDK`5&)Fm@x zOshDkL52bD`sbYr;odt#(rp*LW2eOnudzv@{$4sK5`W8G50HzQMj z@R$^UFYg$`Sprt>$rDK|*lr(B`JhV)epTp19EQ;V&L|L&!k7MHMjegP@rzV3UK=j0_eZlEtN%>mo(~1@V4P^Hd zOI~H+8igIl-eU;qr9bLR-ha)q0c_(O?U&?wJLdtc?}3ktS6XJdHPq-#2OUWPFRWj0 z?oexjDfTVkKc@oD1A@2ZHl5VUw>+OceHecSUeec zG8qTyX8iYRe?v~-Wey)qJXs7dhEX{Aa1x!MNlT8f#!NPPLS5-pc|6g1F0O+CWl1)d zS1mQZ(>$1_6SqBU*VbcXQ=mP(3HYMlQ$o&|I0n3>8RI7w;blB9gKeiEq(7m6Y8rqB z+Q*$2HmWNg@3{|=9ah>6pY;4bF`V%h3Upm!`o%lncSa-lOH~^WBCT<3ssz-RLg4E1 z=q9P6mfY|4U&hQ|=fafui{tiAVU#g+$;3OY@s8^|-=8xBPD6%i1gd6Eriv_iV>s$N z*k~hcRtl@Pz}$^lHRxY7S;v8QP2kcgFGd*4V~H;hXNgChhDs?1CSq4_eftRxGut1G zJwv6T`j5&57cGMMC3cc%oKelxywYX@24D`mKnNJoN|YHQ%(BYjfV%64tV?>kOJ0)? z#q74sQ=aBJdF5yW0-DEHIU_+Az|>~ue`jvWusI^N^i}-`-MA=nqADbT&v3D z?S&7OB^c)Pnm?;MDAE_z!au6NmVe~wNPyP*)YZ2A%@>?sORPe9-3bLaSUZMkx)fHn zPTzH~1m&S*iJQ*le~W9spAEVR4>iokpq$x5o0-SF`ZZ#MHpoG)njrYDMVI@klF?v# zq-62bw)zykzXzkgmxb5i#DM-oofQ5zMjqYGJ^MIRapfT}^RiUF*5k^jx3iWIKpFdf4K)A}zb9%80NdXoTg z)yv4?M?Wl+!gV9k({`sE85%734OXzN$#EeSEVG5>`X4f`uYJdrd~Y%8{ z-Su-`A5yyw@ti#*V)O}WLDepetxl)F{!XuE!D9(os?U2@mr^w@k{3b7*hH<>3zllHXua1*W+A9sB7@t6lld>;jETz=s&I_RBEQ~KF{BQ^ZhV2#i6)71Z29Xl zwCR$4wV5wv^Q1y_v?eR2<%UrDm2i8Ap;2yfev*90Cd$pWWIVn&_EcuwG#ze^xY6cU z{sU%RU%h_VUPhh&E;X1|0(#h9qQK$x6o*QJ4bPBn zdn8SIO~ufqj_%QS1Ca>N-vl`Xt7F>#3FOMgNTS=&t_l9W?j-9C0*G@rntW>h*iaLV z%cEcp8?iZGY{<7`#7{AaKqRDXMpPxV-8XEo`HTUpgEI_M zJK#f_W91B0NgC3r>%s{<9S>a=10o(r&gE>B8Vh`mMkiLC;t%n%IGIJP#iM%6Fc{M}j|wZ<)ua_1#25~66`74Yzt9~B^i#vf zvpe^ELpCedhq5CnXr(Mpuoaqg4&Eo^KV}YXW%IvzRo{g(g)vWRgyQlh23_Of$CaLn zZh1nyY>a-FAVLO)gqLc}PqA@or;{a=tGrsOF7unlWE^ukLi`i6-0t9~@*~%+`^^h7 z@a<3_<9JWh<1MZ7{@NNZY?@YC zoBRH=^LeXn;r7IEs}&a3S_dTrah3mic#Ub+Oz%=Bl^9ejx5U&G{(@BaExd&`(bnK611SUQH#Ye3SIT%b8mO z%yNgz?jn!V;=^f)UBiO1Yf9!EtB%vBhVXl>@JPr;!}9fS-v@LOg_P|!iwFe?gnZLA zII;L5nmL*v`lz>_TQ&36-hBIeEIyTm^g=dCyJ#9ap|ab`XppC-9Ytp62x7i(*OA-k zGkg=d;|~N3$^^}@lN8T!tCsO_qnK8ur=hvpzdtcM-8rBY>1f+2#fJP6F;qZb+S|0Y9l!PlK9C-pCLO!2gAbF(BAg|r;Q!H0$P`sRFtHWb?tdNxX*@ne;h;#G%Ys7}g zwC>R7M^*YvnlU3QI+>mFgn$CMi~!!K_t6NScm)D}r&Ql?J?uWa-bQ!f5{1cO^(4=u zV@{ptWjxuUkRH84U@9Q-AdOERr&;-esNnrkT=yVaL-o-N{_c6_=zwNT@RC9|M}PNpQmU>RH5V(j)dwtu-2HUXJB6Dki~y8t#u5+Ng2 z#Qd|S+a2!>B{oHOlr$^|U182U#rz+2!@NvDbh}MnyMGmX%K@b`?>pxFzK_K8@ms*P z21rb0efw!-Sx`n!zu>-IS`pg3avQrHj+irxB9!WkpVzFd<4%m+!JSo2XVx7yI|&rl zekIt6L`=w{Lbku*C@$8-*{>T?oA8e~i2mIrh$kBi72Hw%V;0r-lsI{n@F4cBV5nZ3 zh**-|Zg#+n4HW=wvZ@vuiZ_|zpI3P1JVpa_aaCyeD}6GWoQWzm+UwPn<$(1}Lv#Oi z_2S0h3n9{%XqKl)hZh983Ub87#cv^OuFj@H=PFuHu^RUj*+KKJU*-mN^JSOhC0)2% zP1=CHb_+rmu0flHPJ|MF%1h7lv_$}#grSB|6+I~1T1yo5KdpB$eRNg1U$ZZY136OV zm3Z1O^mNA{Mh#KrdaMfOV%3=#)s0wH-%YV+mE~jzg^apWkDUGrs4LcS>9bA48CB$J z$Wy_GU)`zB+h$ZmYZIV%d*O_FaT1bY(<=~0>5Z$hxghtKJ9nP)-2nTd;~evu+E>q% z=|74&z#J7lE~EYg8_~X1yP#J6Ad{3HoUwCA(@bCt8tWyo74I zd`PkNe>K8>Au@7oe^V&YKBt+VCbzNYqVkk^npxEn{J5ld`z+g@2QO7h!bqegQ}2g6 z8f2H}eF1Q*1wPOl!vBU$4C)M1jJddekA3~fh;`RMjaHgk@q z33phRS-X`ha5^BR3>?vOVR9C!@dP?fLa;*EQLXBRH2r;kw_;jY+DWnx}EFB!dR&)5+V|Fld^;`7|~oYhAMqL^BWEN zvtuyymmeJ7xJrJEnf-d?+1waqqBr(-L}n31aDUFSmsM#ZmT}#j zX5l?$0L+z1-+qJz$DAP>-HG+dhbqF7h3z?0F-z?ai~mSIjdiLg(iMp^k&{P>vuD~B zpJ?hsDSM)VUIsK@@ANo`D z+=y%N%V*~*c4Hg9-M^S{{VBC@{EjFx)9E8tR@P3$c_@&4cU=ScqJ9H&c z-|2o*K$d3+E0hVX-O574l3Jho^h%e>J&WESgcQ&yr=6PN&@=1GorfJ5=%kbDi?v=q z6SG{cH=e4yxsN^?8|Q(Y4{rag)d;RtbXG#W|KRKO><+-CkcFR3e4M%wIm^s>j9byg zMjTT?(xCgMq^l`~;+^{$xr~;gBBD2b`-HmOh^k&on>}g+OSKsPsa|wY@9} zwkR}&thXZtK9?DI*|372?RN`^skjWQ&R@Jz9p;tu8|Y1}=$bQ_sB+YRwa9DQe3!sg z?FTZGe1MYdWYsY#*^1w*)KxD-j!>8I2~$Qa>bvrZ?-^2)sp1F$|a z)60cNT#huBLr_#eyl}wi#rpiv-U^Gv<%@=|ZRRK+Lu|R;$BFmq6Vtz#>r2D$#AP8< zPcHxR;wg5v;rBseZoYT{f?z5sOzHOEHm#ve0;N?t`hZvUCV4j(Ey&gTwg5;QCLl7K zd8%mdbD8gRv5N>{ARN!>1jXbE|7_mm=%biPh@V_3^D92&@JWZ4==UTh6S%6Kn&x$t zX}srbvf&4Zh~F3c3os2~OZKrx6LW5wxj!Azno=FZKga5%Sc?=?=x9w_adtbhfBN`2 zI+b}i=&fP|vqoIpyB;(fJWEcDLECQO?WZM^BZeBK6X~U)Aaq&~L#@xK)Bs;J;%|UG z3`Lhd@GRQt-&=x5WP`lCr+r`e25GZsxLb|fKdveCJ?s=(Sbw8?7E5Awp8xJ$+d03qAusTtNGoVfD1v^tz#uQ;>}?n!BVI3m zQWl@Z#cmhkzSiq<-^eLDrO@ad{l~If9+UiR_Ss^YqJnf`0Q)YHh(ftC_%i8YB|Iw> zT?Jk4UbGc*Mr?PGDNh~A9EVM;8XsjOYIayZCt-Ks)ZF@9zE~~jF@Ze2xaeaPYFHN3 zuK<29`W0rrrQv^wWWkgs8%zfN%Pyb&wu~&@T?u|$5%KIb2;!kE-tq&b`aQkuzAOP) z0)AL!OHtOpiL@hBhx(Gi3(TS$D!j;UatNc>a_e6TX;MTw_{MTC;t zGn9Lvn?fxTD{rt)S>6*{4tnCo9GuI7czaNvE&^`F;pdxdHJRn1+@)oWlYieVN|2}6 z!)Z4BcsM}Jj)z*5ho729^P_8<6~-82MgDYbFq7+lrN>EHb}nelN#)G0p}(eVvyiIk z7}AhQT^2S)YJ z`SPs3J8T<0p0FU3za8%JJIKb#=>r)SwAU%fs}W#ChyZjec@l>}-TkPs2s-ZjWLSgo z5TBnMFHz1A9=`>s1Go3v4ZN9Wo1EAR|MtW|VR2b3!l-h^w$Lr20bAC(^gR_`Z#eLK zi(x2q(IYI$i-6?ZC@Kj=R;^wu#HE9{p!>HS8Sp@)5_4TUeR~2$_KZrj9Rd_U^5DxV zC_hr}g|L_p_Q<~J35^N0A~+W<;P2v}ykq%kNzMt(U-R`nZe4>H%#~M+j|Pavj1itCIRhPur`)D z{{Hybc!=B-v{fcDl-$D~^}mtPJFyM(xY&G;w$1WQkpv9}IU98$TFEScQSD8k(1_H; zGi)lnm}cv&XfRYar63L%?9H7Di#kTbF7Q5-~(%WH19!6_;U^)Mjo&==syG0MJaWHmZxzeu0955y_yx8i<4w z1RVy>EWhf-2d_5!H0I>htq#d+e&_AoWv}Zej<9l}_f374r9AY17cJ zzK24J-(gR924W3@7^12#8&)moi5H+GV{N<`1xs+&d?at=!n1EfesqBSoW#&U5`Vfv zV}6*!jLqo!=gaZ9dVVOl1@nF89XR>oR&Q-Nz}jn&*V3STOQ-xeF}K%BgoY zfZ%S^f8NY`gBr$pv7S!e-_@g|_`i=xYG(N+fm%R8p~4k&U27{xpS&vKG@ToAd% zmdN|%FN!M_4lBJSe-iIai==AW?O_)ZQ}(JSCB*Brmq3>KDUsdn(HqXze9s#L$<8Ly%CA5`m=~>0XdVM7osRV@SYpQKq@D>%XGJmr(%Jd(>)b)J&zR`-teKNzldm zW~TS;&UD#7-2hAhtvL%eYIv&@Bara8dfmMJ!}#@AKm!*Est{t|UsfyUG}I7cTfW`d zn>;xWQ$2Yq7S_d!`rkGsN}|Z2z8#z3{~`%_2T*6dt|lc(ao`Ny-{M9=KAs;1rA`%! zA5K3xXSduQ=)LILOBnpG8xXY@gHCre2rSA)pp8{$uWSg?mLGhJ71pI`fBywyuwmjD z>q8Jd23}K+_|kv$EQ(s_5T}`P(W|{W?yqZ!Af~nW+3dNaTckf{0afQWAEn0z`syi9 ze|oF}*haHeZ!Ft~2~=}u&x^+GUBU{(Tcy*dP$lAfbIOEWNYeFhR*(ieiWq^dYxeLZ zPKdAr6tXIU(+yN?R%4Mz8JiO47o#0(K;+GvI&w6b8D|$a%-01oOg2pCifiz?$K81XXk4d!6AdCwkexCmpt8*MDB|r=HvLLj5A{4U(1; zA%=D7I}~dpZZ*Fy2puGN`NNEMgz2-pu!DA25#%iyZ zrlzJquKK*2?sg^FIOzJ{Y8d*6JGp81$~as6~=MWKwu>6?s_v5NW^^}fM!p|5P^kID5_71$^r`r_Srfp z<$ncehiu;s3Ul#x?b{_a*VKwh!;^ zL8%R(a9UPE@kS)iGj!BNr#*`Y!$0qiTkv`SF{31LI*8ZdQXn{1OI}DAAe)J1%?_v? zx1R%oTFH*1RY_Mfl~VB=myOm}GL_wNT^0t8_b13;Vkn+mff~zxpPYFTr5obV1*xJ1 zTnetvhBLs&Ye=|W&D&)k14`4wIjcAtDyJXlYCY9myy83QUy3g!K%5WOZW*YKdW=e* z?=3WN;>#1z}6AzRu2SnTu06&}9CL=B2i)v)k*D>}8+T zkANZbq>qUZOBUEem@xn}P1!H0?a~%*6-)og)^&`hSheAWF5J6@t})aG1pYueiaRCR zw)^`phJ4P3`anqL*SiXGkfFVw7Rc_DaOYXXpma~r--KGEr4a%E@85gw%V_h(o4WsW zyKlB{(Xe(-n;#~x&MhL8Sr%~KIztMi^RrF}Cs+MZ=*7EI)Rcq4Xdl3K!Ibw0Mh@KM zj7nq#P;+pjPSF_-l(|`4OFEC%2LYg|32eaiP`s?b`=R?^#Z!{n4pmzwX(DROri{y` z?_n-r=s={#YyXo3R z*m39y-3bM1ygsUZidF zkp=ye$11geQydGJ%MtP5Akc?@Fjr&c=*WRD-|IRdLDxUx57TyeTw!j1A-(@8VC>}R zDHNaP|JIjXa95@#Ks)}@Q1t;uh_>rQ?j)4-{V-d!K7OZ@!~PRII}{MZR| zId(zY8h-pIs+zeCc~3v&-Scx1f?5plW4>V6y`{EdqY5Ag0m$OI%&}7S&lo0$b$E94 zDDUctaxB|vFvI?%!Q_Q*C?gqBQiWurbV8aa?41Habn@6^NoXlou5Mj>VWJ>rQ_8{WP zPrItdok+p%$f!BtvC=?Uy4^DKkPB`oegwvUldhII$_+WeV%8Rd2f=>Gn0lS5ZgOc}qYbyr3Wn4CeFiS0soM z-eS=<-DUY7WTvL3W@IQRfT<5oB)aRKsk`f^6x}pJ(c-<1(ff)nL$q!PFuNH67h{*j z)&qeabjUMRAz8JOTL6-HFW*_3AV!-r|6EXon4JWPc=}qx4-k~xA6vk@(Cjc-1bR;y z^8IUAEQ%gb`Jorq@thc$K`aV`XDdw`e|jNFH1@zoV+FPyA0km1?RixXlYZ!$6SC`F zEPgKUgsXW;muqd3;#Fq@!pt5(vJQ5;kZl!oWcUG-B!B!24&bfO{mDyI*c}mmm;$bP zLEvdLfhT;M8SZB)teJws!iazix6?ew9bT)Mr`_NBo>kR8Srw52QOsL3EMWJO!D+*1i|ZXx zv?W7zjWl=phEH;*h~p)U0W}CC=<5bo1v3CeRU|iU0!skC^I83*`XHCRN@7Tn!|CY_ z)rSbT<4ynZgXNC9`-@ChSY#0Jgus6XDg&k9H!CuU%)rDX_hgERx?wyyihwg`x1vBQ z3?(0T_k!_J?#)?5mVkRh$i!)}PRPHPS*$tU`dayzkdV4OQDwGRD}_hjjOuKs&-Ph? zMZLbaZop-{tTf@1lB#5NF8Co6{b{=T`#7$ak#=9{v?CC80~e;(O}`?5I@JdFc7EU| z)kjRaem`kOj`y#p_hb*}x(PY`=}8_!R=2@H4D1DQd{{2sP!bLLWLleF#suTra>*PT zH6!bgsCYJ&MCK2~01jwY$S*9cFM15#0Qf7tGJTh&){CZ9#2g~CgJZoGBj4wvShM83 zFk^l2-EAaYkTp<00PD4Ne?rziX<*9o3JLXO1@*d~lo*?|KIlAS{!(L7ni8zuJ-Trj z_TSzN;l=FylJGU1qGHfu3*$n_TD>d1%_u}DXdkLRBr{B$`hdv(2c)34kNFqsD~jIt zFynM#*h1?CxVFto?i!Bz&D3Qz_#W4Qi}j$na3pq)DP~k|6x*TH&>Ibq5veq7xo_ES zIc(nq>#_gX86)$=i6aOP{!2(-HuO;lO6u#{di!# z)MSa>pPuAPcQ-W!l-tDtkB2;=aTt9@T3RB&HtzdYKJ-d+mPo?VzB~ll!>|chJnQoHE)#F-E}fjV-<q1QR}-)Ct={E9iP| zf@}fJ8GutDx6S{YMk>GukV1pTTwt^28eNvV!m!>)t?N|8!|Gi5x5X|N1BcHE9r~;K z{4ZVoutO4(8BmF)g$IV}b80gFI2LJm@l42NQ1gFYAAGkI?}4n<$lm zlSFB@W+`TV>rL@;5xQ2ADobz8EU4K5+$6Vod%$$*^nC&Wht=7*=GE8DudAzrN3-y3 z4QH}x?!>34H9tEe>9GO%L%vq9-}ymHuJGjY4U>(iNUdVL#6)Pk)I~0^+y)pF;2w3#|X)~Cd2`;zBjkF!M z!)c&J>||WoWw8kme+HaI&+<%fh5Oppo*dywh-p3A2X+qJBSn1vjIFJ$>1as$0%IU? zv8Lln4fKH>8#rvfQHUf@Q}@{z$_;0(IG9xU1wW6@(yt1RMu9B2URGHgxDZ*SOMl2? z`*3tHckyjWu-8>hrnB=kKZ_Bb84BCJz{b6fOdH7)E6Ae=W);eh5sr@SeRWz!q?^r^ zA26Z#6a`6^P$eyeitTDV`H}??LRY4%G#y^!3rNZ_qwvy*E?$?pjgk-%U0vwr5kaig zP;XHl%8I{V6Om8s6N&v-g@Dm`PF)gE36~qxES}$h&<0R(BLFFn-~K`a=*;+G1S4tItqGx23>z747c(FHMcLmZ=fm^xCMMaN6LHg|AXCugn_4lhZ zq_M-)&IgZr;biaBoOb*~T`sX1g_XSuc1IKbapQXjxedymOw zbJ9lK%xsiV`^$F;^=v?$7gGi$RR?EsRrx}Cm^~ICqjhF1EFSVc_7T@pZk>1IdoJ6Dd5IO9 zg<}a?bpI)>-A3p6S}!nFr&%uZ_E*ybpQ(gjQ`6BMKW7;|m2i1rYI!!+m2vV)C3{wK zz~mxhmIU4MAt2KM@{~V2?m7>CYS2jqtaZMUumiIz-X5-?+1d?@%)Q0PAOn6T11@iLW>G|A6q!sj0`Q`CkJOXRWzc47~ zby+ulV|tV`@*uO)7HXTv_Pfok2+ekZGgp9R7;G)imV+-sn4OwopkcGN<<;XSsw^Mb z&C|pZF{10J^jHSe8q*v2nD8+{2^v#&On6ew*Esy4$%A5(;vI-0b#JL!VFjdasnutc zqTvD63=e7TrN<0zA6-$Vo!@Op5a#KJ98&)h?_m`M6Gt@#?Z=h76`<94zV`3HoKK+% zcgi3L1H?8`t@O)HM5TnKg!TUhE+1b57YIBu0PK0&n+GNo(CWA}OSSy@>DCnK+@ zC{S>5Y*+xy#7xSuV9(t99Kg2$l2hO};41-)Y-;MXvKf_#dM*^+wk8I~P5Y8sF-a%$ zHpXZ&*1I(w?}czw`r!))QQl)MkHI#(Emn}YlYOKpa6_8zsY-VEWsHM)2U(FuH?$Tb z51OiDp2FUTMEyrtwP{w8B*^mevORwmceM6pGaz$1K)tpRFzeuhM8K8ui6ShQ+HfIU z8q|jo87-l~W1jpWMWcyt7ioVGZ(OyzT5y46z=KeF7k6#S1P^Lup|k!zX#H`9E1ZT3 z4VEIjd~Q0sKXd90rS40@t*7l=P6;UKJi%GG!G&-v@K(riOv{?Dzpaa;LDtX=);48T zn^cyYwYkmLu76f7yq88eyvkZ_TD7v;ovktlaowCjp-JVx_Fh%YT~0?Gt@A?i=YC=y zq6z%t1QHRM=M6?}Mwtr$t^n8x!|3t5L-5>zKL;s{@450CF3zw?{H`l^LxFY zRN~ECgJh@|$9A651mFJ5^dVVg+*jmvSi=O-OV3_10NiKnswN^>`pXyfrN31NX}5eE zbbOD(;foYWwuf&-tJ2QmMImlw8Af9Z8$?72fI;|>%7Fs*Fd?PAb=4g3rM${a$V2$i zoR?;?#PxZa0wvosvKSQJch!c5RkO!ks!P*k8BL=|D0#^j%HE-VLn`9{&!pTaAWsjN z8{&>Df4sl)HTP%T3irMc>P5ho&s($;E0aeIx!ztURA_}FeuXA4yEda}wXC|u)jNL5 znPq#?d&-4$OJhHHu=}L6>?6z=cq8pWSwrmDU9kb-)JeXQsWi|j zst{or&y2IV3AnzDDx^e3`>C>$hOI!ZHP6;AlmAr+Ald7 zLv0KZ``F`Cd()fwFMpRFTN9tly2Grc9B)D2*Yf#P8=2e|v50?DchfcAFc$|Uge~2@ z9WRaB6GkE(6-6#MSlhf+C4^51fHYd5W%~-_-$7mCOmth~@Svh;Ah_J#6BU--94l37 zcagQ$S}bU?VTU3(tx9zHPt~3iDBy>Jg!y&0?(o64WC72hXH>WiAA67pQ;yGMUPlic z{QtsqY`(yCm?!0a1q5k5FL5nJs5a2p(>&v=kpH}GSujniW{g|@x9mA2WXP#BN8yL2 z7DIasqO`bKM%kzw_kG_?qZ&t~*}1I)g-{Or<`+YrYwI)To;0K70H@e)T7Iu~)C92v zG5*6`m)qp_c#FZePK7@6y0e{kep$UNC_8~8NgaH%n^tW2<#~Wg=W87W>%zAgK~j6* z&%leTJghO{rlPW7hWG3IcrO<1{4<|RZ3HrU-4M<2*b0KrM9nfwms{Uye8Kk2@|ITc;Og zbTfUy%BkIM8z<=<{c;LlUJlttyfKk7MO>g6{E7v3_UsXPjrE!8meSB-lTTzcqS3dA zSfxSPO|D}{J?HzgY`0NQb(oOA2>SrDDlrk^h~QFmLgb{i0O8T^iC-hVr&$37yUm%_ zY`6^nuKge%QeK_`WXB7Sk3)?bZ8wW#+`5da8+}7n74r(iy*YX>T+aC#4KRF->OwR# z5ia#b>-CYdEDXBH7w-h~W5~${2a?wkXKG`NHpR-O)f!}E6dqu2&31-+Qydc$`N|5s z9Zra(s$0tkVooL9WaJzQI3;BbpVVlj)Xbkx#_Q(0ynP|BVHq5tRNv%QTk*~!?e#Ec z?h==J&$CmEiv0+rR~0&Fjh_2dYY_}L#Erzz4?L0#o-2300@lEQ{l;&OMmze`%NkyM zy(i7;K}%fQ@RpXQ(e8 zBXN@UVE?V*^}u#x?eJO7#i>?Qa>iAwS!NKx(F&(b*}2WXnvAQ{&SKWKSu5*q`pH{g zN5_`wku^_$+Wij-c_;^TU>;bKUZP@`Ag~~Cd&h_99NT@oiS&$(HbYK#G~Dde8M?%M zV&-2>4%Xi9eeIir{P$5&ufFmxNZa`~m@escf4)X7jMXxw;G?lfJa0Zq9;nT9b>yF%T#!~q3J}(6E%amDp*eb-bl#y%Ry%B{Ac#~5!=s9d@ufHVLP~@C;>q?iM#a@U;473h; z=vWjhHTu~@BR(R61ogATbQ9<7s_6QkQ*S;Uxj2D4hw$QyV!L=v{Qfo{b7|J!et~fE zFX~rirKBWsr9$KWH?&6&=@c%Y#j>z!FyZDIDzU^5v1C||k97KMOJ0t#=ozcz`qa?$ z4g2uL%rSEA`vE#y)~_rHieRP9g*&dH-$bL`+Qn4F89z+vv**>`qTW=2Y|i@J zYe|dCUIbh*<0O%t=RlyDiNhUbFKcs+&NIfwaNSL1ct$U7m!i_WS>R|k2lMY5vafcz z(Wt^UgEE7uKC1CGRC~@l-Z%dEmb@d!GpJxyWbvD#WS{ne3bcziDJN;ZO`GMj%?!2b zAabJtXGdeRM}Vhsk7reQ*s)~oMZieBKOhtk@tIqX{~O{){_DCc!?~?51r4J9X6O;C z)r5c!dm+$8|(P;&yYTkl_M`Zd>izpev1eP z3Vpz4d=sEeUV-qvyF@SUX?pRA`Byj}2~t;`Ah1gJZ{bC|D#O!RqA)8lxKX3ptm8Ai zJVnR5%lY3TGbBNe;I{dD0)yVU{EsMYymmM#(}U5z(lRL6cIIj`DwAfsRg`KQt#9Ma zx-3r&*4%B+qy6>P1fcCW1+a(`8i(MNY`b`-Qh#iqC?Z{?4HzG-7Q&jd)Shv4j8oyF z@Yur-xH57QL}Q|wBCmeWl1ZVRf1aS5J&rxWB1hy2|}_5I5q6s;9H?R1k>i!0UnVIpRZ>D2~q3ih#HQzTaVx7PLKs*vwfDC1sJ>!IeR zs_^9yU&ZO4Rs#y#1G|(FC}!LnC;6u&SvZB}8jq)3*l>MsSXV1Ur_Ps8^;niE5;G}d zCw~`CcfZKA!Vf{Y58{c1!Xt)TT5bA$?@Y}H4PGDh^dd6#dWM2TRqIW8_*J!$c2AVB zGH8M$O{cd|?K(wlM~IY7VsR8X6=CXZ(l-;C@wT!HtfVkfAyt;AxR z1~_y>y6Wc{5zTj-LycN)E!E`UFx|u0o%Z8ud@eOu zUOoBIUhf;vq9Ds3M_gp3Wto>k!5W5Fhg$j!MPZ$8S2lxL!3OrgW#zwuT?-@9loA^^YGu!H{bkfixGTDarwK;V++N1|$Sbkz zXc#6p=~gvm zNl>87zVid;#k&p8d>1BoGt(#LhOK^n6cM*F+dd)@p84ZwV-BCAhesLMg=;eLVog~fm*?4^TcR67kv3WbB<2yKS&@DTK(>wFQy@GK1x*VG!(P!tA zQj5a~Qdf%6p8@28AjHEr^WY!Um%8eZ7W0;RQm}st)pHi?vvwGDfDFm89>uFTq~90@ zNZNLAQL9D|SQFbGc>ds9Zi()H$|Uz)Z3m;OGq8zP{;)4Kv$c@hIki8O94<;;uSOPM zBY`Koq5ijGim>zcOu3)Uf&!`S;F_5|_TQw%1yn==U+X2f;ve&uO1~Q5Qx3T{6LRiG z@MA)VD4tY2T>JUOH@wBg3A-x$l8FLY>)uginaYqiU-){(+H2w(gDN6<=-|_QdQO~~ zmh-Fyfm_(z=Cl#4N%*!DD@$5c^LNuLe1#SeL#V2%KzNbO2exJG8|ek*{GX0|p$AY^3RhwR;CNxU9%O7&ne z_;QE+JoXnW6V>d|5hK6+Q??79X3!GcBv=}|5WxD`99sRh;!ZjeWNz2VNKE)!_B#6( zORuG-?u1^AtUde`!-u-{l&?d800-?QHNi1U$N3uR?(OpTYp>KsluLibh=WfZ@4LN> zkJGQJO>-IKk$uOVpX&qAh3bIy%z?1!@ULbLG>u(ynfay{?CViP&iCBq+(~$Ap4bJ-#p*>|mVBJ4d?1a_A(g(qLGb-*Nkyq?o}b|6d!MmZs(Tyd zw@{K#>6Tjp-Ebd=RGzTrIQRB14roS@1>4sIUZ#EIDQk33IcM4U@MVV(Lx$>(P+>qA zLlLE%zt1n8!S7-Kz1VlaKCE)E0`Jq=C&-EIy*Vx8wH;hUUXL{bSS%@jcp0R%KDE3Z!UdRBFuQND@=z&^+ov0l#!^5 zQW_cbc>$vbF)&e{!f_}Bjj0a3{4h(Z_>&Bu=L zo@Kif0*b0x2Ix44;Kh0w8|_C~)0kZM4YkR>7O3Bgr8R>X@&MUW z&9)inquToAr!}4Yua)#K%QKegb?Mo9&O;+|@o<|g*B3-YbYo9%xOhY_*zM@G3)6Cx!)t{U7ddX)*`Qz^JQTPU? zxxxMcq4snF8NerIry!b7nbx_E9Ulk52PCWK)Py^)@M#hWxn*CY{30lqcEaYdzhr7P zx2^2uvR7p7$QgDb)28b?-21V|g$u7>wKA?n8EeFNayZ^M$ILt0ELB(WfEY2&-#(`n zQsQ#PLPd31w%Kb!h>Y^=MzzSDpc`M6$jmO-RW4mUb}bI_GsMR$s_2z;2eb@DL7Tg*yiS(6{;zWR#8CYUncxlX#}(4h016qYQn;bD--lI^x;1+lZcK63 zd(U_&*NG{k)JomE9d`98%4BvLrfi1bhePk}<%v+Vi^q?nseXTL*-yy%S*g#b38F|Y z#wYhe4|Rr=`yCJ0(8kK&*fCB8Hsx{zly+z;)q}oBrnlPPPINyGeH@|Ap8X`Irf%Hn zE?{eSNAe3F?{SCm`nl>oC32v_*j#?XIN|9OKiLx_M3-7q$-7jReH6t1PpKTo-HI>}&qKu&DOKGR60^Umlo03+C+%*^Np= zq5AYkhN1Ab#J2iC0~M3m;de~@GuXSIj)^O7r&B49*rH!}n<{9nU9}(ZzM*FQkY^ZB zAB|3As5sdprjm#lOy+}ph*d4sA};jEH$)#gmOvsz83mVnMm$XiYsCU8gIEIHp;XNn zEhTwu+O>}q6Dp&RL&tt$mEjYr$XXtuVBEx#za^({@`#-8Oe^aE$JkO&K}41r(cthl?oOQe^ON zYr9Bn9fWV|&(~Ij?NM+{W4Xavewwdoc9g{EZh~pAlGP9P^f)exaY~k>63W(`VQ!0Z z+TXcSZ?@U|AQI4+#$ad0C<{Pz^V`}T z>g&n#*i$_u?B-n#QXb9U`dwz63_$Sw>4i!BR?D^ap6Am9Xv}r`Yu+`86AxLmkfFSR znv(Fg3`@=Gn&N1EsL}=Iduryx9*la=6zlr$F`I?*Ah+iOa?{r9Zl;aL5Xpa2Jbft<_?Pji_Iq21v=Y*rG6h8?ayuWI5?u~1isMAy~LnuN&a=crKblO-ZIG(hq zXB0ClC6p9hHmGh--rYt%Zbgzk|Dak!Fu3}jDS*wm{y2R^`6w1CoT>syO(d2F9U0sg?c+mgnQZ{3x(YQzXI<5a^8O1ST%x(o*C$A!lj9~pvb=5|{WxFe0%9$ON9nyQR8X z8J#U`2>BnJe;Yb!2D`?@rqvJ-V>8h*0deF*Q?(DG#lI$TkSMY+ zlFDVCi}T@AfTJo9Y#?{!8^a}_tx7A$SUB|Z4I|_1+TYq4VT#0`6d(s!b&>YY<`vpB23bBDXG2U{2;m0g=y1{@vw?sKyR?5_dT1AXF;3@eETc4 zUEkfbbMo_d2s6&M(pnMvCN2a^ORQa5BMX$S>|b zjzybp*ql5@(TiLJif?T~Qc_}8e6xBPazuM%=CkYKF14%rVE7AOE&M_CT6q;ZVFDty z15eg^K7=#Z<+xpE(H57d(DYdBul!Ku-`&U(A zu8GzhZwoeBYO^6W$D{{;b_(o?Cw<>#wo;ebUr4<)84$f2d`1Sb{s2DAPTp_AGDtbKnIFxGFZzD|U1(PY8F^2)=MQ56T%VZ{ z=_N5*Q_k&CZJS;PtJ5N3qq79{Kq-Gxh=`TH?Y_Gefw}z}(o-^?Mi^13IBwTA)#BqPqI{#!fS{%8_|X^KdP+Bu!oa=2+Ry4FMP8I|6S*rRKT>bm}fcg`*WpP$A$2 z(41OwYQ($I1ycAI&(b)*2~_;>;hZ8Dw85!2E%G3w>~{Ms-4xA{W@-QHqT)iS8v-;H zse2`)oJZQUB~zJk%5F^r7ti_*ng!I*ExuTy<-oGpBO1JNyG;52RcWhw>Hbmg?~r@l zr43K`nKt0SCRqAj6$yD%fJcT$D=wB?ZIT)w`to-$7wwq z<%S6SF(VDpPtUgGdY1H0Ep9^)Z;Wm7^PaHl9=?SqcI9NQSu<|$L?R}_qf9t$CaMVV z2XW3_`p=VX`0>)(KWz}&UwI^pk;s{czFD4oa6S-&GWI@krsuZ?4QLd=RDWtMki*#+ zQ%}odTP#=~?kN=eOztUq+-yr_QV=CBf!!gSfJH)Hp?V%!{eelLgqNHRNHz6?1`ggiGV5@V9?tBc9V2Sv{eYj8c)}DZcXa zvRY4GZM$cd37W$=Nly9Q7#|g*pGW!@3+CCRk{nELHFJ}j)UFIW$xf!ffle>ytb~Jt z6S7fOqniC8{B!OuTdwv#zpdyGi!EvvVOv>&6M~=7e0F5<0C6MVk^|Sr!3+bp nV$desP5kY?weA1UkKcEMwG8W48y!zqAmC3$QC*=@&LZ@G&FLxc diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iOSAppStore.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iOSAppStore.png new file mode 100644 index 0000000000000000000000000000000000000000..0e8bb029bc964d313c07fea891a1fcfa1b10e139 GIT binary patch literal 350640 zcmeFYRa_h07d9F~fZ)O1Til8ScWWsWC@n4liWMvFkl=06LXn~^1=`~75Zt9uG`PFF zetFOB`G5E4;^byBncvLbS$nUwp7pF}K5D;GBgCV{0{{SoFP>ZXmC%ZNWL%UCPkdNp4i)xyeH{iK)886Es209=weg}-yTAF&#QZ~cajhx?1+y!Y zW#z^%{HQpLqk^{sUKoBi2~2W3MvNDhTeZ*RI|cmemaV2b++~Ae>}}R~SH`2T-s--O zN`b@;c3r6w+&(LtG|$m|zx!uv{fA|`=X_52heL~pY^OH6@KdLbf|0ar*|0+klUp9q zr<=<6W6rphbv}FG*uKvUlv>66H ziJxxOR%ZNT4G`R=C4 z_xVMjTeighcEHwYSTY~ZU0zC3C`D&zRPc9Ig^SIVhw?df2qw*Y+VvN~{9kg3j0ILr zo$|LvUJ_7={bPDbxqE|no%5(%`PmI#YKUE^6CI;9%U8d%d#%$oOcjtF5DqOw1h)`Y z;$m^83Pv{LX&PXXyyKL|UZkA1`yEPzEks^SPV>q9yA2iHCQ|xDvMOz;t))Hbp|{sO z^tx`iiu+xpYzSoq?OkjU<+$~6VYrDEnOqRB7*LL#hM9CGbi_>P#YKXv5C*I7Cuz-# zMEVM{cZWCA>W(UA(qfbMP0_-y^V3!4C8`>8V2{Gw8Ya3^MZ82c5o`low^*jlciraY zCfmGXIyEaanGO2G*XGx|cS09Dckh2L1+VEJ*Shr>4K`M2bnH1AxO=~)b;4eyJo=l~ z^|6cL)b)5xpI9|0xi4+A^vqP+(1o8!wI~Ja=KZxE&8ryYqO;Jm$SU4ujzG@)?&hJu z{=lKY;lMUiV1m>@=4#6_{|6>_^X`lHr?f_k{*=DdwYJ;I4n^uLY>pI+ly2?NWgQEl z6Al8fm7>lxBDr|?mNHu)ONN2SifNRxvbMa{m%MTYyGu7L|00e?05M;1>(rce6JiQ;O!m5#Bb+{*E?fY3xPnx zaY^T0!XXOpmt%>Rw53q)`-{sy#>y404(EY#dxlZ?@ zO+I+Fm{ex#;-SZ+to&mkz&0irBPToHEv5)EIS)YL?sCLSmUf3kij3e&H-&9zYxQ zgzhW)lXhMh-5b^0TU1Ugd-Xv^1q=cr}x>nBXuB7;)2@Pv`&TegeQ>od3(vGH`inzy0v|gwL2f5&~|4$gn^F2vY}u;QC_Nog@of1pBc(9uPtbM9757i?skCR#r!ZE2~xefB+Lhpbd4@1WE2>T5dA}&bIVPRvKerbeO7l z<|q9JCygt_G1e8Ps}_C-;7S<`s-eTk?hEby*hl~qLi`OdrTe~qK539mYSnr-alB{^ z7krptp|VFHht-hh@Sj$#+rVxnN1@Sc)$Ig zjOW2T0vq)+(Vh9P;}e`wLt+H9Bk)1>74UXQ0EQzg2xuHGU$U3Gl#UqLqNCl+fMFwF zIfZ0B15(GJ-eFkDb;}9^nXjZ`B9|6%2kI!nj$**kAlU~xCOB0p!O|TvZm2k107C?GnbB?kMuznzHw)#o^8Rk)?P{~RIK5l(?|ckqr-eR~tIXRH(C2Is=? z!Ox*bFAET{ubR_KH3xtR!E1S$ZePq$o5M)qZhr#W&VXW+VJygJajRR*Wx0d^iQ{k9 zE}ot$VFBdsnA5S%5KjSt&i>;Hl8xV=0hmZSn5E@wEKm`g1#}i-zlICKj+1|t3l&r< zxYK^X4PC{TaOvCa6b4vWy}brD!Q9*w-+L~|<0~ow!odjS28kdGlb^An#hw@&9RGCQ z_RP;-A#FHjl4iA-pWt)!tbAbX>AeNo9p&z z>O>3&p$Dy!qKM+K4U1 zl;EYfM3zhobWvY05!^s17`4ZQhtV$K9E574TGAPPJUM9q0}9_Wi9_S{lWP zL4HciR82#bwklgF`?=_#=C74$Cf8TQBZlT;p^G~^b+mUmr{|vO=lHJ|35H!=m`A06 z*3HQ1hb)^4g+ps6UfTo#!S2%hyu9i`@hE42dDL;R)pWP1aSSq61d#eQ*fh-F=8oj3 z_Vuw#Fjlt#M12qpi-6-k_4CGYZsmFXUxbJU*D)V_k_%uh7*d%0=WhsRy6CX7GXw!l zBGO1;-J>>m{sMe%*gymTEO<~_l)B>L;j$ou3XR3RuL}JLjwTru%aZfK>Wp1Ro$CFV zYz_yk7L8mrn!)-Xy_T2!aIqDAC;}XQSTjejx1-L@ek_=gOj}?B$nrIj-n)!(At&=P zbx#+j4rX{w?ltH`C4?jSO|FdEovW_`sWDQ|l>i?Ua!}2#GU!-*qlUB}#txpmS;d>9 z)5?Kv;&;ur%$t_Z((+98L-m7K=66qS4Mdd#90^*G(SQNW9bfJ01GJehpg{1y`sM7p z(#CxXs_p=~$NEqovi$%EfH zr_&FnVAO6FYaxj1yv@W~U;!MPGR;R=CrHdA@|7TIjQo7)Ae-8W!>mnMFE*Yv*bKo?{*+st9+tx^tv!e zT`&xwB=&#}OjiRa&@C*fDo7ogl$>Ivhue$NlLoAyTqN7#0XyknRckY3x%025Kky=Wp2>$812_nRwJV5Kb2BHD9p2Wx2_GP=`e zOf5xS24!0-m{?nf6dg zPPj}tDp_8IYC^sdpo;)2<}zK#Gzm6qQzr=Xl-YMkFA?BIl#e#KG(!j=f+5oFp66QI1IOk_cWn9{8$iQ~GH-E|3pllZiD zz8!W63H61Pp$@~UK8rs3uo*P&5MX3QkO10y$dKf58OsER=PG>&N7&Nb>l-K20k2*I=%UgI6l7Q5PDrgtL#By9H4^~jQXDfO%S=9_ z{3yRhA|44HVs&^`S=QhwiaI>yBMAVp*aWmIFb3FbiB4DY7BVBV(AXe=a&X|!M(pW- zZm0+doJ|5&KDaM@6qxq&7oJ@Yy@1(|_=a-f9I;*jRTWW*a4XZYnoUNP0RGXWX#`VX+*y{Ji6n63Sz@{DLsIp#MvR)GNUb0|Y zx2i3b+OP}wJ|mxcij_5#jF$!!-kVgtMj&6Q01hS7mmMf`iuZjkt_;47&+AF+^B+}y zr&^Fx8Oe6T*I+~vZ3%}~(fM}ys!9ZBV4)+w6mXczZ3J~8{ZsJb^eNFB>MfDWtHKev zx;IlesYBUW-M6+TO~KkHPKOn4nkp@D5~OsPq5x+uxh*ObSwjsd+gYaUu&s2=G;I_j zq$kMWU$UA<^$r>~cP*IQ`-Rh6R;S4wxEE&A0RLDsFQxC2QYsRF=^VVP=g<+^OA45O zmo6pPuTXj7G62tc;eLC#_`_M<*B3g1y}mFY)FK}QBJt@=C*@naU$0M*O^;EK)%XGP@>v>7@N`@*yYch2XB zpfE1{?q@K1_OQ)O6`S@3dZr|&4+XMOt-gUo1lTFENkp!y5XAyfh>WL!OxHz1ENL#b zy6bJse|5$XSbXSPAzy!RpxIVZ^;ylJja9p-H64>8io8VZ#YezZA1tnsfQyn-vG)fB*KDBYG>M^>5JpMP@I<<{UV!}nB| zAGQ+&Mt@`ug=in*%KMku&?*@w-WXB%b-DgmwNe5{1u!edof@%_*qSydv4ayA=^k=O zcGoGpeD0`c>p_@=`3Knw)&LA8j;ATv9pQkI%JNh?#wJ4a?OwvbQ6@!MRrrPLOxD~M zvE(89+Gf9)HI38EYxI(=jU=;w--^+^0FdstLEz3mi{M>u=ev=**9e z!gs3GbwxPEl7VZ}%DfOxHdy6q?|$YL5U+vjv8D>jA;- zfS_3qHo|#iUzekz*8m9CvQTmI4&f~M*}(v>e2SJ863kz>F(Ck0p)s<|8dT(;*2T+F zdo6}HI%aSEsG;9K*R3#PD0+o`du$bIB zOwFjeaiW2|QbH-K4?BV_Fh#rwxn%cO6_|CM_l5J5?+A}Dd% z#qk$gizZRYp5C6)2V7HZxXpE&Ty#mVmMJ^VzePU%uQY-er7s!0qqqAF@~Up1qI`#u22A$mCngE-k`nRH=F42ek%#3MGdVF3%Szz6VpMg^g;6Fi z?k`~=wR>p!bdhzY!gph-RX^skbdp}2b-z4-1!~JxaCd{G|NFpuK`dZ+yX{7yL_;>6 zc}_DYi5)m#`3Z`m>OX2HFtP zu-~sd^7Kp^kH%rfsZ)SIqwkKG9###AN{e|edpgq5 zI9Juwp+kW<(AW|n*zOfR&vy#F@*5A_kTE|!)bCfbq6AOWceQ?WO*-5Q+Q7!JA{7jK zOH(zl8#DXzS#G%DZJ=(48~?0&*-Q){qG=8;jt}x;2EKCP2h_2YOuxzgDr{vEoPI_= zaO{(&pX3YiZPHvrWt0y`0|sxF36U^!!WII&@X$?^N#MlTDjEWCf!FwJ7d8v|at~1@ z3!@6nf6>T>9J>kZco*qSz@JJg?`vaVK-M5agG_!}#lytEHy(tVt}Bs|mTQ;oR~fG) zJmC8AQywM)5u|Bc@UhW?%fjT=HoR_7z3#KriypR(8ly>-x{`OuCQ9wI&)E{2{HH`K zy`tSgiqVgFN_R7gpc)N2Ya}$U`F=Z0@7+;PbxK?L@H$Z&{XkRw&bnT3KP^FK zaa(TmIs*rYMhI7k{ja*`8P5o)PhGD!ab&&~HM<7nbQI%NeZ9!dj*ij9B{u9o3vI%x z!dVE3gb2m*VfB`(@j|GfKx-#2&T0iuC?>26F=ic|^khyRzlAwtPP8Q^}Q^eVg?7^8u_qiWS_N}JjQCjdS)4sIThhBpj z=Q{ZV7!arg^3=!NhYBDhX}S-VX?C9dN~YXIAf45aO_uS+PAf$>P0=Z`x2?YGtwuL` znd!2y5uFVuL6Xg97wedEi+^fVWDv+vLIA{j9Jvh?N`7RY5~ur6{)O*11QzP@O4|4s zZ=XhQe2i34{*)0L`dNnqV8C;4*bXkEaN*mTo&htHr|S?laH5kd!MDLb3R<}ZcU0Lp zU5i)7-jT(Ee%PCL8^op-BL~4JHV>HX~UX9^2ch1@e-997QX~aOJZXR(lRVo z<*=hnv`fo)*L4p5m>hP&A|UBVLBB{wDe_&BW0jRHpO2o zM%yg-{y?x#kgyPKDa|}bOmZA6P)Q7sy1w9j>B!*)?wH#_gE2&)nSgfrG7Ex1)Q>|;^Cf4BRL%fFnjE8CbQX(9&hy;2esf4YS>MN6C=_&RO-w-I zX;rsx1ru2quH_8vg9x8Z%*z!`s@0*tye@xkuEtovq9Zf#PR}Hc+7= z;v*~+2Y``;1v1SIig*t|&JSS^d(}$tS{d{^MU)0j&ZUNtb?YgN{btPSfHDiQW=%giBxxs zRUM?*;IQ42(|w6X^gocDBoEJIrk0ASATRHuwnzkQH2*uOe0 zt74vG%h28Ky9YO75RZF0zEH~ajz6YA5$6muSI`MY*-oc{2_^t=6qB?2yrLK`pQ1*8&HMFL&IpBU+=EWWSkd)| zEGP%VF5T)Dj$>XX;8KM@n)?|m03*C78nEw3#k<4-RwV%<{;I)Uhv$rUC!2FQ*$8gE zn+HZ5tYo?|oA!4O1U45NgbgS~8Y(Jy_un%;+JB^hLatC#{HS|r{rhI)%O^Uz%w-H< zB-tQOZ}+1cU8=ZMbWv`m+wfn>%Hu`pu-#_bd4u=n1a!p(pC@Cvfl9Y{a1t@f7B9pk zuO;|~vv*%zNF71=a8B92kDabCM@XluTh+=vs3{it-2ltNbbeAaP#$O>{aAN`NkgmrZQ~&?}7OnVh_`)DGY(iZbeqj6{wS00`hU*G!%E zpf>^0tO=CkG7i40$cx+0myTNWJhIt%iV#j=nlM_~ZHwqOYH}ZP%*&X#j1qJlZz+^?)7oA(>p{g zO^)U$413&!lB?KXC-gM9Tu976ok$sC;jl4I%(|4y@(ybqAe3 zpgxiTR4bzotH!&Jyh0gN2hY!s_iR6Xv_RgQ2;YbWX{&Ic%bEF)@~3qpr<4?z3t5ZZ z8mm+)arE8qP$mJV{UV-gCo254u-@#{rPKB1zGHUbt1;LbVD)JihiDpd2fU!I%)Zhg z53@rPa)4PWabm>hINS|SU?uJ;bX@h|MyReLvyGaVvJLloLYSsyzrJa%1+&7!3J7o| zyQn?2|8XD>D}=y4oGMglpbU10?n`TH3?#Y*rZe!3Dqv@Jn^q?=rqIRTtD;%0rwM*1 z)^cwwDHLkKA{FN4RgKF^mTJ&g4aGPFr2<<9-Z< zP9`<$VJ*Q#TMBUp7RVrz^y7+Wk|Ts)B(&PWbuBHtBGP=G|8@Zr-neMz1YVukjbM!Y zlumcd8A3ay1)E^iUmPkbs-!|1ft665_VEiFE znG7?Mi&*NO29?c==2K%>VG+%rlrt#0m!`7;aONSv{;qvYur~d6zJ`>*jNRv<`IMO! z?q=4`I{6Owb5d9{-zXrgUvryzAc7fv7T(K&78K8dh}3=Umzs$~t%> zXcT#|K`{4w2PW!mbf3CV+qAjVp!?OwaaFQuC&A5n>7$G~z-$q_MtkXWf~|^g{8#uo zzAHN5S%RW%xHS~ArpT>yKhZGz6RN7MISY*YMEzx?b9ZLf)-q*C`gmmFd9H^!Vw;Xp zK?S%>LYb{oG=HV7S7pHH{*;!M<^g*Q_%<(w@}s{QIQ!=zS@%J3Xk@5%>~q4$KHU12 zc%ohxx5~_BgAXh%?5h(Uk#S?8IK*T9ZubQrvSs{}8D;(Av!nyRWyu6*O;!#!HC1IW z%K5U|YgN+JUmP<@mK|4VZ^y>YIx-}px05dSw0^n+qvplauocm(@M8kIR_`EvUbdD0 zu*;HAXF-y$nf(e=%cqOY*mRGYlfPrpKZvkgMt|0R5kQSd zc(2(lN&aCscfVS2HEtz~rxx0>EzUJH$R?kq>m11c>2V(Ca(q=yOZnP7;odEIe7@0p zJn)5;9zzH6{`Rtq^XLg5pTO^DfK}udAF_CFLjp{PG0Gh_xpom%U^Ll3En2HnLCmU` zroH?Z&Yz}FWp@egWH;E>+yhhjqAM^FnQ-{I=lA5ApzK)k8?&*P~_p z8e4Dx*23Q`TWY>fLYLe?Ofdl9N$59Rub|H!1x|xI!nPSs(F1^>Ut36sBG-a z#R%ZxvFTg&^Z%vkI6}#VKt{2}pJFlooI6~`1&{ixP;W?R>L`IZt=j6h$hZN5JoFag z;8c?Cg;4yQNgPd*%^O+QF1diMvcZ3cFY$#MgRVwNboMrt)6Ada5Px(NzGCbK`Z22YnZzQ*rTd@_J{I72oiu#cK{vTp%lb*? zQ{xFK8M0-dlA zj|q=AcVT&lr=1BgztAbE)5Q;$i zU3|?_`}0z%s2U0gE&>T=kq;I_)Mm=9Nn5yZHsuFQ$`#_i5R4AcN+9tYV*C5%O2lEG ziilCYhl*-^C4p__N2>sz`rT4n==OAZmj`K{neEO#4{?B|<$E_H3a=)>5drK4-R_0$ zJ7}vbj1E`1rX>M<=c5jG3yl0M!2b&egAqVYa0E6;n0b6EjrlGZ2z@j%YUhEe#9&Ri zEIc2v4h~7Lb5S$g64{Fgsv698-Q(cuy z-!m4Qy~XCq1VV6#yK?0(7&*BQC;S5CvfoQ?9*GjXTC*pX0*ziosHigw!a(0{8+;oG z(|rlAT%m92N8U%YahvyXs6*c>%+Z5A{>v7Cv#a+7HOYdx6Uu8tgWq>`_l^kI0aaF{ zVJ#izCL%8QBz7zK#?xVZC4ctLM~5GGe77jY+#>aGv?d5o-(}t}cSMdSbgX<65WeBO z6UY=#h^3d|R=+FaJQH5Ymn)be>NWC*_NOPNJs9d78B2*dOp!g+%zFE1^u+(<;XNduRj@nK7QRYlsTv_R~AF*PWA4i;deI} zG2-bnu(aQaxD096<9A*zpBs%9OJ+Jq#U_A`VxiezV7`ej0)gXZnoKd5{1ohcFgGDU zSN4L1cucu;RN}t+zQI>HA?q|`NXB7~0UXT@^#6z*%^`nz9--h7if-eVkx+laK&qZ! z5M_AZH1x0r-^zGOc-t7cqhiYI*Yt+;Wfs%4sEYAG&^Y-(bMKq7)eQ%lV$xIwM?FT> zT|?|eqq$B)+mUWR_o8MhtZc32p^<&6%X`e5?M9`Q?qFq;tILsrYRpqhfOr~FAMaxw zSf6t+Ng+TZIlEkTaU6Th$adGr!0Wa8uHNT&2i2>IrKJ^(6U_;`A~{NINuBFjGQU%J zp2RtOe6>E%E?Su8uB6y5W^|sc_%6!#;?-&Yw79E!vfoj7MDAGJ`DN6*p5dF6dLM`_i@He6woKh#2Rf+B;UTrVWIVcsA@<>)ZAT;V#(7A~ z;%3N;$KEam1k#RqDX@9kX!o+Ny&Au_D}ZEiA3R-LK0a z?(q=3OiM4Ze2C^+e0lCaoWF1ITmR&PH%GdPocDN10Mg2mPH3u_lWzhioApxROHt?*p%19P<2po#}&HRFsErJCc{(D~loUP7Xm;@dSX0act~; z@YALBRyOeR-h2BGHTZ}XhN+lLyJQV-`*eutz|>Tjg<-xd{*)*W<6xCv8uemm^@dbipx*z z(fXNUE}K4_EteAe@kFjwYwm7y<1EqNU1+sIYo+qX*_2aBgGH*z-71g*?oEoT$FMaCymNRvOna&c412Nz`?p^?q6Z^SLx= zA#jsnh6kC9E1g0JHe~$pQX0FZB|zf-YL$39)=|Xg@gWes!%Iy3jksA~p{bovz^a_T zg$U{9f$u+`FY+)DWcnF40NMd7-gxi%a*qU%!2WGc2coR{bN=t3JZu*Nm+cp^tN;KN zz*xqYj1lIEfs8JaeDvb+W?u~ND{akRZ4PHqi0$N7NVV=EM=0;a1V$NkY$w&xTVAA4zLex7_N>^+}2?@YlB8jc7#!ELv#utlD33Y-mK zighXha*^JPkIc6Ob4gm1vZL0ZTyCoK=(q3Y*1_+jn=iPmh%<}~Sf4?tg@8)W0Kbm( z#*gNmu0z`blPdpG25J|+O{#ht@Wb=}elBi$fvE1Y4EX`x*Y}-S5>}qh~=NiWrb|7z(%ji%e zw5&@pGtN)Z%Zzub(u2<n-+Qfrp_cRao# z!Bgq|6KC#|22~!kt&@HxALA!ytF(uWryAaHUp{MFRvDYxMjwPUuFAKxldGYTEsjMGoI;1}$G{6^@B$qyiRbJPm29f75 zFb)-B&TppLnZ8?4V#)Gpgi!y$$jSW0;&uCs*?Ef1C9t_`lYf#3yC`)2r2%=i+zJBD zGFtegneO;~_Pt<`_CFKvF?ZDLeP16}X0`1`PEqpT5kFHtsr_B8|n^^Rf|C*Bsz#F$u zY8Q88foQ}14a8#X{esaVdvtfLJL4dKK_6dAxbzfWgr-udRX|$}Zz~wPHn&QLuoiUc z%I!(3+(WteSLHXq!)njC*4@jBfp{@0ynk@4mc_f^T+`=75dz zwp>kJDt}gMyqWL$gol~Qtropp7Ex5=qwMuNrtE#IDG!@#v2%hybbqNTm>7P|ivHQ` z!2U?3|8CXKOfykcd|Y5-qNe(3(g2;;EzawpAz=^R+K{--;y~}O%5tI`39Z3nqMEFo z_OE${c&OVGB*A|F@bV5!K2CXUHF`&{{mLe-LP_3->*de{xx3#Q8B$Tj{Y)8Y;_ZJJ zS>s42=(hV$=Jt%tN-q_jY1Su#3jejHay{X5Vgk$ zO7fHE3;F ztV`eQ#pX!1R>7-`HESw;r|+D~>kiLr&XTX^MG~yk@*nKfhx=5fU(2 zd2UnY6aASJ$5}(~?dqc>UfiF)Pi%b@a=o&*Or=te;AY z4(&+w?XIiF3@}}iGsirb&g#Rx21+Lud;if7hT5nTINlnk4S)K(Uo5sbs)?B`>!07V zE9R2#(sIonc)Xr+vW{@ECPtv%3r6Ju`KDPbV!+gW3d|G@PxEB#>5L`s{CuLC@jFuzW?0AecnR*XudAFh0zGk8V?oallb3OOXqPato=r-0KCY6 znb$y(5f_)yke!tNjagp?>Aa8G1hsO}ecb`KW81m~;}U7E(!M)C>8-uY$sd#|yv(Q0 zn55&i?*a*f7x#6n<;JgkCnn~vZu!f4=&Jm;vjbEozfW0tt=NWznw9~>sbp^h4hd`F$`j=2BT#>{JMb5Pt{&dbC^kGsh# ztzCurp?@Y;pV+K<24bT%GyqmIt48Lf<|ze25euvimb)(V2_v*IXgnJN2%NhDdT2!o zjEh;ZV6sZX1V%&o2>+NLf(|m*a$m6gFfDdtA`Sk8STx|3?0 zWTyCW>3e8}|Mhnf4u?C#+L6X(bHZI`ftJpNb!A`r;I#tR&ozs6ACr<#o&>(+<9)4H zo=zf=X^Y!crTK=b_COwVMlsdA#H)F0IVqRs^XuSkyr-d+x?#^m74O0!o4!lvaCMBK z0@=(*XlV{J`47*xirJ%F11{5_F%LsF2S&)!u@@3Y2o{o_Vv4O70&CZJF!f7KwWdnU zHT6qO67I1M3cga{P2uf+imj4|jf2;$zQw1G0`_J?E8bs^2mTm5q`uFMdBlR?#erlm z3WYu^=0{-zG38-P*nnA3c_sTovERDa>}=ID8oS+Oyy%$kkSU&_bvLi!G-t=RN`-O)T|3LDO?OPxv_*PzE7;SrDbK_J%wV1cYyRrkZ zI)L^%zTV`A3jkbexg_{#G=%fIN99NwcQbV3sI1kr#XB-Q2Ai2s*HzPsz0Ne?k+!tDXDcGHyNYX5PD*mk$%mW#pcxRJVepR@`c7HX`_BU!w=lS|f=K(i#(Y1fP z%3*JKK@tT46VM{&z)R5*rEP2P-ob-7I*q~-sU|;pHca+cZ9ktnE`J?LCpkH}!w#@R zYh)&?n#Zcd=h5Uu7XT0;p);Crn$X`ZEZO4i;by$V820#;VtC-v+R*D?+nRBDc@<4# zldtO9ke;Shguuavy%pCGOMtpq0!aVvZPppVT8htcRqHoa zZ|3;(Yz-Y(35E)f7Uj8HCRaQ8+h&{h)~m6ESbVAvRdz4cziU~s`Mi%-J!5%di~oi|hrL3Gk=8rzz=s*RF|i64WOd=xyK7`<)e}|t#QN7N zR`pLjyqXire$1ozKo9E_|H8oj9+mB-u|>aAVAaVthi)RhC)pbr^Ci;@D(7pHk3KQS zi!IYS#Z<Hdhk-xVdv}nE(?E0bnIf(NQzZMm|DO*{%cv05Y%pA0NQDWMsPSpya0` zuToYVrxsk(_zJB=3Jbet9#1NNNfjII?58mx#Ib>mG#ICTG*cL5HyKc#g*X5bZl9%G zSU9Sa*4@OvEHd%uMzVn3rXwcHJ!k_+2=sz(PwLiNueZ+G+|sI>^F#6^i;LOMDqlTb zm9MhywI(e1tiG1yIk^992`~`zu!eBdT4E7sJ#3O(OmsQ?_z}9OYc$u2mWx3j$;efsD8pEA`kOn#*e>H{H zR9NWz`S(0bm4dFjdI(z*Lr#Csw0q10Z-jQbI5XWzZH@`-2tsg^of1Y@Gbu3}_PnM2 zqWk5_)hv(W#Q|+yEp^7>RslGVzr-Q^36ZAt1eFU{H;47(k8n)<8@9vn%FVI#(w2mv z(^K>OTjGPhF*H7nWC~6azz@iJIKJNeC_u=|*KBt@^Z#ffB+(L&2*p<%dAs^AB3%<+ zw5}ZeE0!j}vz&Zg-_{-6ZQcD&IK((GQ++#NXbrrR`uZ9;9}Zis@|pU$Nx#oW^!eNO z|u@Al2&W_q!1X=%u7th0+-A+4Q!eP5g; zG^QEUH85a&4|aP!+56|nobjtB?(zBKe(@@e>9g%j*QyjUG~N6Q&77(k+Q1@k$nA|i zWy>qlA%LNj?LP;GT*S0bN{9I42S5ac1^zUi>y+afAC4v2RX#l9n+U^C$Ku>@`IL@a z4fvi}KqGK;(ojps=mvYl&^gii`I(A8|E17Cu$kIvNyLp)6o6bm!^3-doS z&xLpX3fMCJSQT-R2bw1t`)WHNK=`YNEs2>YigR(ao6?HRg6&|R>dQ zCt237ZMuC~h7J$C{s~pw-jRikme5ZAeAfSd-C&}Dd);zN+G9)G$iQG!Mj<&ld2F>n zYpnF}o_oI0pCj$n_zlVEt3Rs=G563|KmG>x zPsg30Z4J_^uN%2>$38$IMp6xlT3qFobiyQs87NBbX&0BPtsBAmr5R3^$i_dtAg|e9 z?@F*E94Xfy5#?i@F$TTs-B99aO4Lo?LnNsK9Bj8X04?2A;kU{jP47| z8~0m2^`7+z7*|y(P13l8u<8WUs-3`7ba(WxG8{oZYl9mZB81$Z&Ta*ju4=7ap_tVm4m`otc{!5Otmt((mx6ja=&5LJ%4F79Kzw@v9 zXeZH0GXWWAJ8ffpq@+s(kJEs(P>|#k(l;%AzCjMqu|y3#H^cs&=+^(_MDn+-cdn91 zh&=oNX4a1s7a(OEjMV578KzTwM#uQc8N%E+g@LHqWiAG0PL;obd3mujNO*`BXSc?q zYoF8-lRyj%_XGcQ#gD;?fKy}Md6p0xT%w!jMt20Z5pNJ4WIJSI0RZwqRRzKYp;xI3_Pu<`|DjiYe+Krh(h?;0PP!=sW)0b2CJD zQO_cf+JpekhRJ0Vmf4ujm+d3xdLAf^rA@><6eMEZ;1k%m0x2-WbiH*lza_TF?Oe;A zA%wpXk1l15@=)T)`|GuvXN2@+Pg~`eDW)7SfHvA37sfL zcCqNS6y$rq_eNqzsMg@t!NL6$(Z+(Y-O`q0b}Qa3#Rm8tS@@mor8x^lWu&|{;e!reJ^?~YR=?W3T>iwI!@P zH#6L+ph`FaYfXy0KTRI6b_tZnBqlMdXARtaiiy#`qQllmcSpdT;em zEN7H_XSpO0Y$)hEiqj$9xLM>sn|7zk770?zpb_^OjNTg@VK+@#@DXn2YSlOQRk3-b z8gJU$8i`$~ySk)@{QB1>e-uVTVZqn!&#x_X((V&Dc;mYEwT1xW$@5+!FVbL4gnSMm zf-(k@z*Lz#`jd9Jm(QN_o-gzHih4&N#Q7PI>-E|x->eHJT1$Q+y@?pb zZ^=IqjD$@$rhquzetX*Z|Pg*|MZ~o2|ZaU8u zJbtz9pgB#Gx5^NiVKVeRb9GaqPRxoo5KYzS46Ok-eS3=5m>}2$-(UiYts{b+2pyQL zUOI@3;~+SvA)#rd)uNzcZ%m6?=_`x*T*5tt2N|bK|0^S zR)4%PphP`)47Wd)mXr)smgR^ad+9b}c>Mh4sQGd{S1oRgSU*U^Jn+6cNOQ?0`0>en zJRyh;1cWXuzlv*`i^Z{eVwK0$1!b?hga=EGLkoCIcOU)j%HMtsg$s@2!~2HQ*R@&R-|tR+ zTWY)V9`|b(UzM8HrM}7#&mv-w&iFqxU3FZO@7Eq<5(1J6h_sY+NyF$C5CO>nlG5F5 zAc)f4ohmT}RGO)D3rKeelWrIrd&l?pdH>t<=bq=>=f2K4*L9u5{<@o?^NUB5;x9da zdYVO5(;YMm_4m1kYtL?}jY!$4r{c1F1Y(K>u$K|@p*d zHwTeZd-E+SES)m8IPPlRAN5sxwFTLmSUnFbz~CUSCFery#qL5Ay;!cCwQDmwg#Nkh zVlz1v|GXbjlbu{6p^tr#t*sUaV^6O=R}m(9Z-(fF;~gJ%#0*^_V5qb?Rj$#&t-{;E;moMR$q_eED7emh#o;gj`S9d4KYG1%4q{Vg$lU5g=k)>TJ1y-Pc_Ie=h+2 zSt6R;y0>S3@%XPkN#=3si}#Mmn=qPQGBPPvqPO-63JbNk^ztVYu1ET7W~FkDIz9Iz zciY0AFs69;=;@8pbs9v=cfy~(T>xZj+yF@8)}}o^6KoC0h1Q%6vWd6VF281j;`DW- z6nGVyS7m%J5)T1gHB$s{x~}ZwOK1z9Z!ixSK8^@}p`P;7DE_3Zd>ZtWB0ncbvzIoh zT79BIVo5^*cgOo;P~wY{hu6%VI9Pn8+H$;}(fGJ1?o*N2M;^&kH72~YnAzB3Dz2+qZA&pXcoYl*ZJTJAt}43Awc-)pc4g@WF?13s&N&N(pp z^8BPBrHgrl#^LGko3XvBvUtZab|f7k3k`3tyqsu_;;(lp{>u5>d&2{rqSeyCs-txK zD62&LP?j(j4RIGPYTiW4PM;x2}flg^E{MvIp_IAKF=5 z9BJ(tvA7#1bqRVQw>WmtIF!klKKylI@I%!I>{q(T6T0}rA^&f)?R2zS`9Z?Jw(9BX z=)>DXG*j4dV=jLnaIAi!q2B274SMD!1=H%O?!)O2;*FCwR~C(YX(5rud3SRT5oe|B z>=`aA-DB~HGWBtn`lNpTtJeSq!jaM8s;~wh7{h zltTCbldu(*eZ^j(FILz4*B#+>ciIwzF2mZHc$Om>7+l!}3~w-ISMN4c{j(h-71Efa zYbtc+21zS}BpRRa(9$?YAedAEwAg-4rw`9kqdJ5@V8afsz8>d3(s+O_y;MPJDj~Jm z$;r*D5!w|p!?X$K<%OEMRRtf^=IKe%4PV&dQV24=sehlg0{ZOfq-|wQ;#S7%%KiZm zN90dPR0*Bn;-u%#vR`5bms0fI`;IOxC% zEH?Rx%7vg_;0V$eLGOrK$?)=M)<0I-A$RK^d8J)csZ>fFC}iGH4Uu>@ylNP3oY*{R zX?vFFyE{yn4iyCmHQS_RY(D=jJm#ZwM_J%KuD}xqzG4nNw29kzYbm94G)@IF@Boc@ zX@JZZUfJ9$0NEO%+-j4XXY~b=>c8|JwOATdxf?$CM?4`*{&~NoN$fxu+?RK40LR@X#v`yLby8E`6LWo4=9U^m`5P1w+_HPVFvfrFTT`dhu-Wo~kbQBIhJjoO z&OrNgg>kZ5U^Z(hR1|airl`_Hpo2~6pmcw&^RuV^w1mG4d}M~ToIRUGm_}KFV!LdB zS&pqnTM>n($*!OsObo=GcN`rqDo7HmuM9|fg09#!n(Qt6WoU+Hm5NyreC_LGS(AXc zW*(#kG4=ICTT|CDgC=CXW)x_(oSu z1}PPEjUz~rGDYx<1I9wr&nh_HjXI3%FcAY|h;-@UMC}<2HIJx<=@9Sm@qWIr<~$=+ z?UAntm|6zMzg*Y93@f1AN#(t7^z37nJxR^pQOgt4#(U@T*}1mFiZvMc8ub>=x&c7O zO7u`JL(O5d^psdnNFs=6l4Hg=vyL)NcQ$3&e>335dO*Rx46TgCWa(}mrr;`0BpTP` z!4$RS;U;D>ji zlm+i_ekU;Y;x>*~LWlCD!H;o8%96Xf_#;5w?F?Bk6zm?G`$|87)v-zh`8ixA3}i5EMXo0=qH;3k7b%Z z$_V3C;%|bzJv4sRgEgn5GY^D-b2ZS;0c;aDl7x_UyjtWJcBxfC6K)x*JJrgRHVjYf z=fWg@5^kWqu@`7AJ!B80u76W-dYGkdlc^K!wzj|yMdwct{pU#Is|;A0c#hr#g;YNT z-6iOExA$C}t?t>3lCw0E{oV|aAX1q*%Bj#M~q{urWA`;L^} zCV&M-I&39H7wDM-r~XKPjZA%dQ})5b_4)8wROp(!vba6ekMToUwXU=B-e|TtoI6157dbV-7>}KWV!z^c1O|_}{po8*wV${l#a~MOwFIOvoP6+*+03PV%hjAKID@sqIU?t@yX(mjr5@R;l-Z~$yP>#7bzy-I`q7}5zfVZPw z2VdierMMZycumbtuX%}+Qw_iF9hW*g%6nml6&BeK)V6S5Bzk0c=?wp~<&me^WpH&oRmx^+zR9aRK`W{XuGi8r(J zP|yhg&G+$ElJHk&Q9%pg^>{x7A0$$6b^Uap|6A87Tn#Dd>nN?fG{1JLs%3n;(w;5y zg@M}UaIGN%9ofhD5!Xmuq_9rDh)Dl2Sw3>!>fK?T=fWm52VN=+@Z>ox{UWBIP?Y#c zx~2|8yKxfc(Rt?Ia@tejyM3rQJLXX|av9*J?NVENNZ4TKs&f>BLByZ-r8&fZ9Lgjh zR7|JAsa!+IBQojO?`ARZQ2JYRur3Wu;L9FzVThB|`y$=^R!v=LE_P=de6g#_XGE9i zxY2I*l``L}n1f07mHr7X={FVx_WVXs|8n!ms#=r)}}SNe<0cG_Lc2dwk(WH9U}VLYyfJ;u}365G(=wd|s7y$E5dx*KgrL z`Ud~MpS0;M7}SJ%%GlGt4QKLSb^xtjUB9!>d-o$<=_(){=QD8n21bvkLt*_<-_Wze z+SqTKUjj%6p(FKyE$ctMPTgJZRKRTPeV_1vo|xwxK{*)Zd{w5-nUhCNhwURZ3|$(0 zg&nkd>OU{&i5hhzE70j0IXz{nsQBJcCXn!c@V`^)3c%Yk-8G0*1SrFVH$*&kj2ln* z>|Y%d3RZ^tSDd@sb=!O0hn9xiSvZ|hOH)va!)up`f=A$kXWI#`*kB`wEp#hyRZgSe||BT5sHGp&cXTCuMdKv>eu8%MI$O?{4gEJus zDlzH1=%EC_p_HBrcZ}EC$54^OCCoJvH?c#`dvt0;Z+3c-o$@Hj#SR~tcmP?`-l<(Y zfP0z_n9VJg(^mJVa#!^HRe6A(4ZUlOkW`;e=guAf@;BpzGIvDvPrrQ(s`6elV-a!! zeOm+|@SC~7`&P?2#X@59u0@p1JPVoM3`&+Q1BMEE<$0Xq34znbPi^%=bgsUS#*BTt zO|qY*Ky)wZJ>AB-yYDGm_;_}J?@cYedemjVye&+vpXcFW`J)(duf6J7p%!!ap<*z0 z@nU?iYP7t&Th$2d=;&Y;#K3+C_^Q~){As^En68w#<9PS)Z^5nCZ+3@h8Rn^O4V`da zU{63Resn;Rd>q6XV}AfJT9rj!*e1vf>( zV$w8C>F4j_^CJc2dEH-hR`%W`ozTdiIm!e-zfhx3_%4u$`!6d*;5Qwt zP90YcGW@~eiO&wy;@lq(If7Qm#_G0CLaMq{54!rPkw2SBkZV^YxLC4EE5Hc;pJo;aW;HY^sU2} zhMe_;5Ii6Ds2%oh6t4Qmc{`ck+=o>Xz6En~;^cQZ2fk}4!%pg^ESo4v&M0SgV2to= zg}+}$y@qI|b!10|%f(-vD0=7-{Er=b_~36h7_8)w1K)w}L@)KK{Xa##A`75EIJ^E8 zw%oHi z#L_+C2ePNit<(2I5-SZif`J@{bz2<9wA;{0N2~t75flSZ#^)*DsBxSzCcwS7lyKAe z8CsU2gi+#!lPSi8nXt*jM{4Qe1e6TI=30VLdl%B8U%sl*0j!_QTK~=Y&o2gF72!OY zi9hq*Kf%N`UQnmc^(H;^<16>&P-!o8VDR;L#pwj?4MF!29kA+lfkuOwh)9 zr&+p|cj(sNImGU9h>@P>RjGxVsUA0kx2QQECIG`5;3AW4&zHeTM+zbkiJ|~WJ|Xvp zF4o<7wa|Qz0NCf8qh7|Dny_{)^!(!S2L%ecFpxDK-5p(ul^M6H6_lfuh3uz+8^VKj z993X>`ap+S-d95o?;)X^MgcugkNE78czoL+CC0<)bFbw_KoDi!8jOT||4mtS1_mQE@o_5#DCSG2yQ# z^%)E=LpHxGS(D+A8>E0Wg^*k9CL##}0+CVH8X2ffVD$pp~6`@1N{ zXc+&U&tHn{+je&N==Z~V!YRmq9fRhb=%Sa?!)5N3o^rEO(8&X3mT(re4rAhj%w9!j z4VF@bf|{*1xqj-;HZmW?Vh>yGCMj^ue_YT0*!EGBV75Apo@Dq9(XYi6W%Y4}WBSgb zwv)8eZ#8?+y+0;@_Mi^IYTNUUN4%*Hal{&^Y#qJkAMn)LZxx>(KkOY!56=AASl>9u zfTJ4XzE%VnObP3?1z20&51q~;lGK~hVZ7nSX6!Vb?J((?E`=gKgQT)PRy6YE0hd~Q zcyYYV`&Yq;??^%Db#(U@BJ~X{=G;L#NOcMBXH@^J^N?h3+*psJc&?tZ zYCK|$=$Lc4c;p&ailcU{6YXZ}0%YVODIesuf}J?c;r(xgc6Qct#yoy@SUA&@d}{0X zh|YHkdn4p+_Q-ZrjfM5Nl8Wut+#1Y;6>|4x1s`ws04&Cm*bPrH&JSjdYUWTusu)2k|bg5kbN)ts&#3v*pG9G z0J8&6Cwk%v;C@YR#aY`2I9gwxz|SEO3&Kt$-Vhbnu`JdS=GdG|8$vpVkM4#mj8@Np`-|gL01b-e7B`&^0_E< zr+ZgVZ{x^ny??>Iyv}wFfB)#SfH#Z*KM?ZN%c%f-bAEZZJuZh=L94@;0~IHLQJn&V ziuO$Y3B8rb91b_XVPn+{)7|oMqBJW|Ws76ZC-KN$U-c2-<9zsegWgug7 z{rdptzlG~D=zxmi+;`4GEJF0GC5h4JI+{Nxl=A-c@iS^nu%dKwtvryUj4`d z$Ig$^eK<@GwTzo3|Pp8bY#s#70ai^J~;|DWqwsV3-mlHo)6Tf9FY?8++ zlyz(&qscy`3Oae(^$aYKZ{YAQjoVx>XxlKu3~5r^p$g@-m~KLU)aJFD_iTLWZpiv( zzm?N|>#Nl829KHo1(~18j!95^?#ni*wGaZlgU&1^-kSs_?mZ+K9%!{9bjsw&)etP<%#q%Z< zm9>21gVOguQxGURGfyAJ{I&1tbo;ipxPR!#9L0IRCpvv7Dx0Th7b_$VHhDT5`}F_IQ%0yYjyeD`;oPgk!GDlWp0-CI2O z+qiGkC(>P)a;^@)DwICCVH5jTi8pJ1pL4z;^La8A#d$Jy%9X`obrys6_nv+t)|I!c zx$(BE#;gesWMaGG-opN|KWH$9cVG2Td?*tiw}|w}c=DdVJw9-?XAWJ-9mu>itaxM&;67;rpuN0q`+Cv=KpR# z%7~Q9yNIW2)JC|T8sZx}OWt)qK|#ayUtBlt7jnGf`?v=blXp5|?$OV6bFXT4c2;b4 zAnZ$R-DTR;+yZ&Y=j@N1`#@G8OFfGctCt?UnIqNzA@I1+fQTr(Q8Wb0zX@Uc#C_S# z7`QugAZ^8`pu=oBFT|VmLaG{=Z|Sa4w;+3I2%k=>eRwyD+){bMf&Q~((XQ)R+%D%R zRaX&S{Tp&rokdVq7Mw{ol_+e2b`GU{&R4k4q>vBSl9CU1QdkW)XP0N!9!cz{#eZ;* zuY96PuS&W82cNy(;56vccLm2P8Xp+&rUQxuuHW8>GSm@=fSH^F4zv5Xr$|8EO+$ky za;!udCDjQ<{qg8p#1=Gi=UwBp$8k0=J-KEOmjq2|ZlZox*rGBXzZG2hWky&tY^-WW zS(QTNbNpvf$`2iS2PEaxf`zXhe|q~5^JnLmEc~3;L@d@X)i~=};Xh3Gb?#cQUKRsm zL#4nIE zK7Ec(W#R4%B!q0NaaZZ6@Xg7$RX^4RGgqZ%!o zlKr+`47!cft@bo01Kf>41nisR(tD(L(0OfznvG$u{BHjjd-~C^z8c%s=O;e!=)=cx zR`ta{MT?lnr=`~V^aI#f^gC*_ljBhU7wgJ_X*4?0`T*ITwKRCmywUJGOe?I)T4kUm z)41yD-F@nLJ#mk{qJgllLG@ko_5T>#Z7Y|Z4_dUr>e<4;pnN>9B6uMHoDB0`7@hW3()(+C>!z4g~W+j$8 zYvPBt&QiBci?EZ$@5m%5$`Cc7&RoGD9t2N0- zpg?S`d~pE>yegw`(|OZPb=OLqZsR-IW8+=?IrUgIw)Y{}@z7iwmOpB&3^;ntik00z zeoo@{Q(~*UB-##E*Zz6+xNv{?6<--V&FZ`{N`xSp@EDxD7N~Gv zEdl|ibjp6l;KXR~^7j7%zY@j29}|}o&#($cau}c?dRbPT=>qLXYSPg2n!4+vbb9D< zdSp>rji_YKF=XI{PbsiT!@>1X<&n*ZBgUm(eVl@FW$`M+m$5E`lah8sli|hK#c+{r zvXAa@nZ>%rglv&-=6KLq%hr5LS<8KRO~u(({p^f4`A)nMyQ!v&Hm|czVZ{SuQm4R~ zA)RvJvvMR_HrLVYSWi3rY-l?lYHgx@p#EN3aE>{Cy(NH8U{H5GI!j~uq%EimWydQg z_^pcWB4dB}UzJ%d@~jM;`sI(W6xVx5RIMVQCag?ht&Jftu|xUFFgPiiGbQl{BCBKj z7{=GY04(?T-R|J%up#B5bRYEj@exF;K74&(xTJq zC#*U76{^UZPA6>NO!w)x;Cj#oA4u%!`9vU*m99P+$KrAdFXn~P!=IvyVF+zsn1~b=iXDs$brllf9vtYZeHaD&nvD zN;o=>O53c{wV-|VBe#hKt`J-&CR7KbRm@_GTI%^*Ier-t_GvPJ*VolJ-iM^Y*)?1` zLH9w1TeIP|Az488li0ftqRY4ydzZMeNhE1$!>2@FrFUA-2MbVzp5t6U zS%&cs^agVC^R);!UGRL?7X8te?|qNZ(Wf5u5(w5luwTaL^@*>DfWYiTf=slbBsOcrG1!sgawZ$MeViaO1nZhpaU3=0$JKWVEYp2g@e#JV-_3foc%*cdS@KtKn6(q#W3PEf>?MQ# z3)P$hXSJdL9>^-)Ny48tuqJaJrL??ITF)UxvJk;=><{Zut8s_=MpNOZkMbvckK>tB zE97IkFZGN4;I%9ZC;2DVknVk_+Om8t z+qxYVkY?1qC&y9@H@`Wo3mW|szW4$Jk1c|V!$RABy-sed*xdBJz^UzLvmoW2VaMN3 zw>mLKSwym7s2AT#y$GJS3*#tBxDP-l3$y{y$yOTJ;&O!;i;%Ez&Pb6=UikTs7^K|n zB39SyTET0#sqO^ce#b`VCQi+^!RaA<*z}o7vKkV8cXHFh>!}k69mWd2p2L)mcU?26 zcyeeidl(lFEaa>dFuoA+=q5DqDk0?w&~=!cR(%f%;k%1^<%JA;qF^v%^c#At^Z=M9 zuvI!!J@}<*2M&M7rkA(zy@O9lAy!JUFnX~|7}OX~Aj=$!=bZEWM^*0&)0J@kKKFww zcv~595SJ~1(A>YP9xKrS?VbjFI6y*7qu^C)Wg)QeZx6w-7F`|{JDx(bd{2EOX3bKF zs}Ow5U{0|Pqa&r->N=8^%LYLL^Z`^m ztFt{nbMnw+7bGsB{`|izj1OiZ1>ggOV{cRR2+`*TtTq=U)e-|O48Mwll$!{&r6#`L z!J-%Pn^19M5Yi`({mdYNf@nol>X_=y^B>xNJT%<>@W_TGdg$8-z(GtvX{V0H->!*| zX)X-+xD^(L48r-FCF2@LI7p@m>87muhEVJVf3J`=XcD7;Cd_ha^g)LIrXla13yPj- zMxBe(1kGa1GXmc4kjgil*hYNJd4&ne6}Gr+i6eQAE+pH@rIb!H%5Xu-`1IaCLVI#EY{+9f}{)C?6a zjx^54*{dU9ltlOl7+%5}E}7t1ssaV`5_!)Gq%*8SHjQRyv0O;Z#geY$Mm{6f0Ikh{ zZU!eD)`;HZto+ek^0vvQhbnR3y!{2n4ruFFsNJo7BGLAJ*U0UY*3zpTE{-GV29wvD zs59L^srNZz8=IEkiy7jlA}*chFBW#Ma|mdr>h1 z1%4}+?i1IrZgfR89*c|@lZK+Z*iQ9W-vTAx61~o|>%2!_nZ0*CvpODL{R%l|o{d9; z*XT|Q+XFM}tlBx>!UQL(AfbiwSJzy~ox$aq*tQL4PzL8L${Kc{D6G<)~^t5GR2X|nt z0ms1;YrGoBgmt$?$`d(D9@ZFjtQy~j~(=@%%m^ZN6a}0xVhf1llPz)-9j+pZSdHE6baT?~% z%o}U;J36wNA&MIn`hlu0p_L=6qGnY=(u<>-R>*GtEwqz#x!0elw*(xLspkX~w)wrVP za8-E`?0J9PKI%X4PXGf40!RT}+-wvxJ47s_EN&wsBbDE+prV)yC}#Tf{b zct=uP;;gWdv-L0B5?U;Z+6gEs|HDAliP5mQ@>+L1$HlQd*?-Bs7UHXPs+ug(~*r-0`YP!1?7|rdHt0L+-Ogn5ooXNKZP&=;MR%y5eg+aVt=Ug3MU@PWvc=(Y<$;p%0GdyoY736hXp zPw1(xVmI}mDOO>7e|(Q>nnal_l5-k#zFZ7FvK&*TQ@R36dgFb}hTjiheZXo(_3B$^ z^iU;R_XP|5$CCCrn{-Fgy{|2is{`_;?_HA1)Em;n@72sg+RqUVrw4J~P!osK&0ao* zor|=ZiRt0%!U2cS7Bz_UAm_iGDz{(5t%bS|V}a)S4+spZQkkp(rA@mt?Er$K;yfN@ z2__n4*e-MN5^$FmArGuCw_YRCChjr^$Kz3}Zw82nlDejcpLXmzgh=%;81R)$bKYr~ zKl!>1W}^dX`OdY>)TTErMZr3Fdqn#YO@9yScsiBud2~r`669)yx8*X)ho|G%KLs6_ zeQ#9JZFzkGMUVPIWI_JKKGm{b|6NkXtQ1TD^Jw2mYNA~w(97z}xoUU?1dAKEC|@-$ zU-@iJ{J1A1&(#p`wdwKn|#7m;R@&Zo~$ylBk^o7ZX_K?n%BVCppK@aW4d^o=Ai~ zI}}W>FDNrxljBvGuAw)Qu>S_0RHi`QsI2^u_Tk?|7J|I%LNk5C&AzCxoyNn~I0fIc z%Nk$RSnu_~UMt?n`;w*)1>!f^wAu@0O!HnaTfEe`-nyuw?oFy#?|t^4l4u#T8h{*x zcWU8AOw^8%U+We>nT6r(_-^Bq0JeP#bH})VJI-n}SoT}v00AqV&Z|FgT$ElZa4?{C z_2K|EJFJ#JQ%c`|Dt^+tRs*dvGn&mJ-RDFCUsr{!naKg&omS;w3MHCCU#ricMtz%9 zl*Db+G}Mt+gCJ{dB=SI7W_M5ky)!hYKpkxrutKW}@!y*EyIvdb?BNW%;LuGEJA-YJ zpM6U-4GI3_)g{tjMy!PLaN^IBrct~pwtGui%=EgL=SeT0pefZlO^6O+xtQlFNzqzK z7T9z76R{d(D#CK4TptC~CAt{gB0ge5cp~%?fMVexLgqAhw#JOrJ}xgn?~WD26rD03k+sU!gGcmO>T06Jwlt2VKl?=da+G%0i9*hT6rExP@p> zU|qL86ft&0rOgCeW1(cYMO2D5vJ*4mfor0nou&Dd`qOK&+^ChzfQc5i3ALlL5+*i3 zlUmebX=q}hT;;iNo_&iglW6=(l2SQUt2r8G3B(}N{V7&yt0 z$Nvx;Wyd{yZ)$Ojm8>L#7SVcG*K%>4>Sez7U)x+t!PM5mqI?4px?my^u>F_-X_7Z7s|!Sf8^Qd-nM3c2Ro zPA0pv*%0|k)HXg11HvVT7+9#iHM*P*Ux?IG)=$4fnnjy9KRk%6olf`6&;B63#kx1V z=p@Q&8T_T;BNZ?4GwkAa$F%ghmONCj4S$Ka2iEeX{$0$PAawFF#|F|S;B|@gxiUi( z;5_?oSti(XoONONMNy~T_k)FJyu53=8DVP;-sZPS7I);8aP<~HH`{GX%m|cxk!(4$ zh&?lb=wdIR*v@fy__>d1T%hdmaDS!A5TD7LyE5KsBbV%lFGOFAe2hZ&u1WW4WlFj! zvHYT4eSQb}9(Vj1_A`00yl}+AKaR-b(Gb=Ih2Y0a=AZr0rH6wp7$b+X&dx03y2UKN zNfFT}TJl=hInnthy&Yujj9i9`Zd52ntVGtY=+J|R>nYxbgn`&Yw-4n_AGtuqh8@yE zGW?|e&q;yxvfy;=5jBbP@h;^NUGga9aT=UFe(Lzf5-l#n&}EGzf^(g7u>Rua4pqleJTZ9bxyX?5m)M|^DO z=`4Wn757Ge3}() z&cQ&8a;+&5Q+FhQ+s^?glc-hpV&8lt_Sn^II?yDAkRSue8V5@e>!U0|S2_O{gR>;#-crGBEpJA2 z>DZG!+Zl)(9dhCNQ+pDE6(>{*XXD65596nGpIU_2ELn6!s(*+}HAW2?_eT?rYq>no zEN57wlx7F?ti(n{E3E7}mtW8z%tSsR1iY-bs+`eC;XX{LJNX4}?9p^Is1|lCCGT)O zeeiyKG!au1k-3QeDgf;a-~E!?o~L_wzl@Fv0J8dRd}mMV*wG@LDifqKLjcOJE9k-b zkPu(B03bADdiQK8k_AcPizKr-?Pn2}rRA^0tUnqFDndkLRYa&gFpm}2b4x-rM-bEm1K^wiP)dT1Mt4pgWO4N7i^bjak+c54)G#wl zobO&B+edrf?_$`C?|xnQE5^GdUR{c)9iSD?=4UF(90n%sXW0YecnTD9IiE4V5X7@t zsE-G$NM}-Qckq%KxnNUiNy&|0Dfj&9WP53n8+vX*Ckz44?6sf0I)P(_~5-TTvNtqm|=BU+bk&9dyf zms>T#eE6qGV~r@DXyelhjr`Nfl?x3kBecC?$Da_riGKkBXW#vm{r7PA@Mh?^p%5Bm z>Tq4*X)(p_dKd4}%{0PtDJx{%^%H_@p=MDVRTzYKIyd`N-(aC$5wub8j?&uVDV0t` zy$(1NKb|>T)B|=B=X|_on=2{Jm3MDIgim-b@v6tCz^bC%cU_8(c5zIDBt-n_gCMOz zOSur0OTDAu%twTZh-H$&zmsv#sHAP`(55$+<5J)k9adn&!|*SsY&da@Oc)v`!Cc1N zT;K+D^12cpi_bk^f%JE3*dE@#EZo#e9TF<*&jJAU*%RSUOc?%0dHmjaql-Edgl1T^ zUuv02e(tn9;*yEw3Be-y3^_kGQT#fyEe1wWC(7@@{T_&_wnYPG*g|*oo-ZDbM|te@ zD0OAMv@RO)CfGhER3+KRGwG*IY=^N}jW-$I6)tIdEep-oxy7v$w2$E5rOB}U^X4u8ul4B_+y?1RVDe-ZSpvl6{&g5T zZ)I0&wXD#faC4;>9tqepPY<=qtbh>-DVufAr^L}7UNvuV=&sGDz&dVxht#^|1Bbpo|v_((G%}mVaUDcFF3n;v$p|7rkPMZMM zCMhO{>^D_X4=EH8Tt#886|Of0cO5$~o1=h5T;@P6MKJGS=CT$MDKAJ15Ape%t0|lc zC`CcksAweCot=1;_x<{yecCGMh$Cd}sCVxH{Z-!d@9_2Avr%cT8YW>P0dbN+bAjys)a3`8ORT834RjTduM#Yj|^}kjiz>M&t z7+r4uxYW-uPk2Wt89u2{mtkdjiSIy)J<~ccqSrGh{Tcgt_J;xJz6quGs zlP>(@=+(8I47jS%g_%6*+0I4AM&)56cYlEWay$b!{6_4;uGdvTx)z`1$^sYuY zd392M`UMq`1N0UjSV4(cb?U8uzybOOhydH!JlgI{VfUYA4A^$++}cC-7JbH%!sgQ7 zfsHY*qwpKm9?P;(j>lfb9KwFa#dmgkl)NmXc}(R+S%{d2^8@j+rL$F6n`1kz*cQwm zuj*_bzfIhj@Cwb!T69|Op*KBL@aca#BA`XbLUJQvtZepsz&Gx6KyNP^aN1&ysdBsS zD~S{0#P@hb$30IKGov2Od{&A8aAH0Nhjl+~^mAO-W+dU72T+sL)3f}Au0K{M8FFyXqvKu!P3TmJ-YD6v4@4arz)Wef&H-3fNF9}4fVBKueBRJx?F^~F_(Q?Z zp2Gq^2;5pE9chMt?8CwCIzkaVN2&6F-Kr{w-EVmw8SQ;i^VR&}TuIE|FP?=tRmr3J z>I4Kh5zppqqZA>=?NJDBu=QHkdur?!_lw4wSHuwpZvl-UmBpc<_{HEse)m;u1})^9 zV`1C(fkl@F|`z) zjm^F5Y!F-ltzv<}Dj~)<6Mm<4JZ*UUD{x=jmXzMnpY+m3#lgy#;HtZ>q2c{g9H1KM zdt*#eBJ*T{`1W_!VyxNu45 z5`ynQSh<}d49?%(=9^0WpXrCPRgk_ox}erKq~EA>oq zzaro^DdB@6yh#uMabwd-D&TxHIDg3C%5f9>vA6K^LD*Jn9SV9`sr>w^XcV$%bHEx8 z6$2937;N-)hBrwc4|I?&2?^fOH zT+EiMWmYw6&|Bdr>`CvHO&{D>E(Q>feG8xbI2>%1`xod5Bm%-O0>I#^ z&Y9ivgwX*jM2G1#X?BzLL!0l*<+VT&kWA4G2{#qNWJ?s2EuC~6iKGj&IX>H(n35`) z$bLn&GD{>?Z5vN}W3DorEIS|Nz5{}I$rJ+l9%mvj8*fVb6hgLCN=or z{$~5Ku8X^$I%@tENW-sHi2-$HoAu|YSAU?UI-MuzyvJ13ya$#r*!fMIM!*?#b1I2{ zog07$J5()s9Z1V!q9~-Xsq&?Skohzs$Y<55@7nBInJT z$87%n1pI7WozY$E77L@;?)72`2tx?!ycV9^Uc!4dnG0T7^U=j~W#==;z4M*%f%>rX zZrbw`2=?dAbyjC1&JSazZaLW@TjuP2{pV0P?Kn zBJF{5W*wXbkpjJ+P!j$EtA{_(>d6Drcw-k>TgUVBU0YHC3 za;VGzc7`?8+Vb z@$%xL#*PKiR_Ko-bopOM?ECKABq$@yY2{@a`%eG_9a1<23OB)jfEi|z@`00=taYlLE@5;Jq<t#efB8l51MK0D)g<^-}A*kvh{3T`%o!Yy@1o z)W4CI9pC#u0Lwr$zpBP|8wqdD+%+TmqtT^$7J9`*x2#is2v`1oAoD> zBMftt<6XrgDt^xVlE{cU;NV~cNXbhPJROD#7Vm(}T{mRmp5b#A11pln=&&$x?!w)@VZ+!Q4 zd-{nd?Z5%;-<-%%^g$K?Ar;jJiwFkb3zN!z|Fj`G{72P6X92IcZ6d-B|5gq-;#jrv z6?)y>FQLFvgjft$g;>^#e)amQjQEN0{!~`{Pkn70Snfs`up||K1Oo^VN;fbNKmf3T zP=|3fAkMqD`Z@+h$6>@uH^LB5Zx?pjMP~ z_x`8xqzg>t0WOVwYO}88crrnjam!Q`DvWT8_$q&#m*Tw$9?U^L59toU`_forQi-Nb3HF;@9jLZF1epg^D$01Qe?mE|lUkbwa6 zcNE{Fws%5j`ab{6bN1a=Ua`CGxXZ2nXQGJ6l8-a}qOuSI@Ln{N*9ZiKfx-0r^gOB# zI6<7c;KTtJ;I|n(fTI&x3K*Y57$M;}7aF0!DTfpQ! z$874sn{E8o12#6DBY=(ot92hefLlE+o^^!|7DMLW;~bb~VtF2A2TXw-LKPRR;F04Z z?6|M#hrRwepj%p6vX4If)ZYEayY|c9{M!Eb_Mhzf^&3foA?>X+RZa;?uMz?!1bPU8 zQUK6H;FnpK5ZDO>>U>|At&bczY~OzN1$*x4XY8K4@3j*$^fx^{)tod$75o2CSBLWt zb9Zw%d?2DA3Rt1cAqw&%4XH11bH-mk+&6<=1OqU1!c;J1q1WLEOk;rNdqpbzZqVjdc)mDtZZvhx};>-sS7Xq|IA_G{t zvdFuG0H{)P&-ng5Hhx4#0*}c?z{vwPb>DHDkm0~Fj0P5Qi*Y`3=3m7?t<5#n9Outc7Bwv@KO%k)?^3b+O$g2D^@ke4R8v82(VO;5l7^qF|MS+Ld--##vKzjl^h*Df~3okjp zG!SrusKQvH!!vo$3GQABUs+ssW`F(EIqk2#Bm;lfWXb=ARj=qMrnp_8D1PZbFc6?? zXt(shGXDUYuI)bvwZ?hdY)}xPbRz))`uCa;--YW|xw>rQG8{Pep>W!JU)kjChi&{D zMl0lzE^9c=o68{ivrU7WiTa7|53YCGYAJ-FvSr!kHmK4QO+Ho$uyzAtTnYc2?= z$`(U5=_Go2DU=qSNsy6>HdF&po3K4MZ* zKMPyegj6Gw+8Db2#=IA83XFqC<$)jg7`!}c&g-mtS2R#3bdQ37EF6HV8*tPIgeMyc z7#9Ta(mi^YMx8T3}hfi$nFS6(_ z%l_3xt@yi9KZR|I-y;9=(*QsqsQ(YD>VFo%U>mpk&VzGU*%0OX$U?wZgS}%2j|q_p zFIFW8s7m0uaYiQy$e^h$uZ#JY5ka;ED2Sgf0l?DpRFZ__LhzxV9N>XA?{cJrbSmO- z;*%ctQFC7BSaAU%!Xyg^V8*w&Z~#pZqj}gdUx1jOo3|r}4%?o&J$8NRhAm!QwB?m$ z*90I~tt~xH`BOrmgg`$+ptJ$dkF8Rcsf0iZ0)hFj`ow$tt+&~;+Ux)Px1O~J?!Dh7 z@DniiSqIb4@qSKB=~@4|&WSV4@G!4DH%#`qF^1EV6(a~A?(TGtk3}_(uyeg`0WQ6| zl!hbWAf&XdqH=9Xmi%>u-#e#m{iE|by6?JGZ>(6AXBV)?1(ocu$_4N!7FC>lA~Z3flDO?WrH;Img!u0bU+82MoDj z@Z+3U1Owp1g}~bBgT{d1vTHZ4+1F>!*)M+kYx}?d*MHb2pM7TQIwc@LmiBLqQ@)iD zC?U{45Gc0*^iNxqB`G0LgFv87l4(?v==9W#j`#bf{nP8O+vATsYDbS8vpuu3weYnE zCfq4ePY3`K0=@Pv``|0q$|I%bmkl!1?~#zK5ki6)U~A=Q5(r3N>DQh2NJ#RWb@icMa=ZsXUaGU>+PXs;Y0PEK0g^1`^&dSzYJ^a^$>+o8=z=Q)Ia z6Z^_g)U@9JVf0)eFa-4qJsyc&x15eu+!XP2t1Ml}2LKBvRj=TA$8VER;83%{K;pU6LrvpK&k=w7YJUuqxjSCh4`ES*r+Jz8NN1?VWTxKPS77Lu z>Rv?%pce!wd7QfY>D#m}HxQ_>%zKGL@V9^Oe%m*<*Y@w(fVbX$+m@Df zT8-cvKwAm|BFxHr34wlsK&b)HPpwgwrG$VW5GGA#Y0b}4ML)Q3(4K$pIs3tD-?RJf zxyKId*WO8O1!!>2%xa=`b${KN)bkvP!_<*{B!WU#d7+2X4_E;w?tm%Yi)sse99|HN zdT{uqfR=i!C4tJT2;Az27p(gJIWwvI8%F&Wb%dW(Up>LRc(nw2_rOZ^n$Cb;U)MH; z6v5ZK5)F3F9QC(R6~jZH@QyUt^+}hW;lucu9G}#pq8N$+cVS2-?bNmL8F0~13IV)> zY@t&SPIKD${Irc9-DeXg58C+MM{M%0BQ}0mrwPm!tX0MI!Qpg2ga9>xz$W?9zHvT` zczu&7L-iTh`321MTqFpf(heuxnGX;K@Sbv2&52j9FWUPbeqg`-{qO9}KmOiMeRRr} zmo?wHD}?|laFvfG1o{F31z5E&%2pPlguuu^ATytOz4yw<&e5aC?4kP~u~pn?V)SJN+rHHCeOmReetOC5+G;TD*CKAKVsz`9(|Kb4D>@Up$_g2Mt8}}900ICA z>5ID!h1>?Ju)vIl9?_?(Znl|uW7v4c5;M$5+zFxF(*$c4q zi#8@XO7maFBJR>75|^VaVRSo~lzc zlt}fM6LUb~aB^5CA6*DghsT)W?ccl49=Pv*X(sNm`MvWtw`b1Yd;dMVx+r@Oa%qs} zfxVtu`BXxngg`eSPznIL0p&7}u0WtZ!7#HGxqg>Kha>(lvUB&HcT3&>5&M?*{D1TQ z2W@U{PV;bPc4oqcp{=cGXTC=;01_BF7?GU)d@e)qS`t1`j{b#l6&x-#F=CHGo(h2m>vv#Sw+P|xB_D`_}wj?nB z5tf6|19k%HAmEUmgNLqZxkT;+}Q%1+4RzA=< z^U|CeKeE>*ZoA1QA3R}`w;Z%F2?5-2V8rXOxyFdBGNNFG9011F@x7jbYY}KkhwmI| z8Sy>u1A?Uvp5C{W0JD7P7 zSAD=Ymu(CpA=mW|0i^4LF|FB|8GG=72kgf`d_z|LU$#3nq2@CGsO_QOUARehQ z%s*0lCgCCwSJvGd|8TK_q*aH{t@tN*PAQU4XZZ%f2>3N$IIFqT8@)XBw2G2EJj zl!H)j6+djx=;2_Es0kpBx}zC%6e=23l`GPy5`NwIMBAyfjmqYxY<$m@giXTfxLkNC z0ft;`PC%L)js)c5ckWrif(ICpAK;aSMYh`UTNIk`J;Io%g7M_!q-y{ilbxc22M)Rh zz{QJ~Y(w)(J#g>nEs9*a;e$Y$j!xGu&@!n`n*ONgfEM_k7iPHoX=wu>(;3Rw{)Rvp z2G}pSa&YRI0hOBo346^RB3&Vdp{85CA67hfy;Ess^~V zatr2isUm8yT`v&&{5XpcVz{?1*KMSrRKBRpskuPD8q`m4OCaj!`YcWqtA zb@j9`!;yJKcxjzIvj_l20HSP7nh>tSZpr3@t-PSsQ}+M<*MHfsbyC2WUwvt-tI~*bH{8rsQpxhxB?ttglbUHY z@4_F@{~|t*_oAYJbLq~I+R)p9KafolrZN$dMMIz{y+QFWw*U-EOO0?jBZH3wnSmTs z$r_0@c&_bmU15Mjn@3^*App|A2@$Ze%IqUQerrGQvj}N!&mOx?NBq6?-1GLzOE23U zx7{vH09pCZVxBlDv!cznq9TILoOpo&*%oNpU)gS^2;l-uT=kRZU$^^Qxu|5K1EaWlr#UlsU8@Q=fPBQ7005hlap_R-khayQ7K`R=&`n zcZWx&;y$+mBSqjefp}bC5)2w^UMB=RD7ygr_wBRWZn@ch_2!%Qx4*w@mo7_iE^NV+ z8eAz1h>$4nTZ2I03*ZMdEOlZLeF;At^mVwlmR1NAkO6cMZfuObMDPPVN5OV@_5efh zQ*Hqmf<_$1Dg*{uD#>E{xz;fdj{R$xbjcp3-;em)g!zw*tWVZp5sacRAg{7C1n}`~5$a5FrHA&3R}#;S;a$;Q{!cDi<*hHQ`p3`B z{&v=?pGg34Nh+z!?D5abWH9^~Yp`yp{<8(3bi0QDeFj5{qvk}$JEjZ*R*+WzJCTYi zWFQ!OU)oTbFz58XG<{hDHCI*J1MIp40WuU=kuad5EdmGyIAx`(d2(#ebTV&y(>CIC z=0|Vx&X z;$@xrcLo>cU+-LLN3s;wnSVVykyFnr9dxLkfenNQDxNU@T)-|1pIB)?0+Z{8qI3sN ze#t)vT&VP8#lQOA*H#tNZ|{C(hT1=8Sg$D&;tsH*^spR}`48i7fGgAoMGwPJI4cpR z40aFMK0tjHTVoJ=CIjId$@f<)1<(x${Cd^MYBB@?)umOdupR5XgaOzHxW1-Ee|?;p z48{V}{g7tnLeA*}l{;|8Q!X7g_=LHHATChW0~!U+?2cIb)W!)gh`>qiygPh!=Q#t@ z2?+t_bUMJHLx*f(--1A2vBkw}+9IHKO9`Dz!B+y$@|J->q{##0ADI5MMsPBIGqHC6 zTIUJIWc-qTiy$E23j_e+c~JXpxdmYNJ)}&bO%RC8|C$&pqBzLLBef28Rz)lc zNAlOtF3vd-H}^|fLE#)$Qo1cbfR#B30XDR^oMQwx*dB1{x=jmBkA35&AOyfrZf)*P z(nJWrDE0YL-zW8qntv;}JCmz9+B=LAAbh`do}_whyHP(Ek|%R5a4H(tt|_7KoD{IG z@Wdmy+_)Az_Ue>?`|r6|&ttZ-ykbks%XaC?C0kpQ5C@z|R7ERY34sU!aCBUShc}3; z@L762hHvjZ>AXrbZWl%nurB&>T&IkTORzO5nw_!?q7b0e0BCP-DO1}f1VH$~1ttUo zF-Z5|MZ&jQfEchR_b@r7Cn%(UTbrrU^}yKRo;|a6{Ma#j_2pOWU;gPQ_Q1Vj{^xbZ zF{{_nku>Q;xH$2m=c4?`02OvFCum|KLwW}euIkTS@NuF{&qWUSK!`Yu)UjahL!> zz>jZI>92lv$tu78*s8z$$n3-OR@FZLK|0Q_v0}wd(nIwzcKIBrtA@EC!aTydgs9>!iH~LagYg|?&LQ$Ib{b9 z9I#`@j_bbQ%>UKJMKM*HcWd)92^BYie=L878Ul2M$oQ|XulqJ&5pweDeYKh20#6XO z2Qbgk-EsXq=YaZxEdH?|iI0JfZ4aPqVrsi3rxL^!A4EKe5AUKN#Ad^d& zU;-mw-{)VPe)>zuBNzk0Vn3I1PX}put|O{C##&g|Z;w9oh>ZQcU{5^uxSc$H!ltL$ z@1KgwGmLHA(;g_nRDjeYjP05(U&ToI59=dDS7iRFW5l|7^#$w@b*$LK>CzzF3taVr z&MJOaYW^QzFgv>_1AihOuWRo=X$+xbEUZh|=3|esF@$yOW|e@at0wwNR*R0-%|i7c zuZYUfmYR^}RD)5r9+amjOM1MoCiQE_7jARHvSD&4s!i$N1Od$zk(oeMf1@cmOC*nj=}XZDLXf2DWX)oE~b#;U=)d>MKO#4W&R z14lk#tCfxndC=Gm2EL01a+)s)>iydhG6dw{bDj8sDQt8N(5V6C7J#kxs4`sJA;6%H zhCISPf3ir;5Sbk7b2ewq!t|q>&wz{b`DQb9-~mIjgOufF)Qy&^+@ci(ZR?ccAXjC5vh&H2QtADI6s-Kj8sd5(z{ zVuSn8^BMvI1R2CwTYI9CrJ7^ve8oEDUq0>(0x*=o()-@dk{F6uj5da+<5Q_iPP&1P{;HZ| zgn*>`t6=HUsC-q;0j*G7I(Yex8pJpc;xV5`;Y(n-*)=U8K(yS5Fo%} zG=9U%da(Z$nE#~1w5Wb$_*s+-&m7$c(b(KAi;_VQ068860tf*_AIbPQ9Tt?3@4|<` z%MfQn3xiXBl32_?KVEFJ{nYe>e9XZQO4ZC1+&ippOgw2cizJl z274Iz$*PGWA3h$OibE|@SVBFQ@Cg1L1fLwDxXp>=`>48Jq~sw6OR0YE{8 zYp~G+D>6|4kQ3b1LdE#o=a*&RPZs_Ea>lAs^*8+3`|rY_oQOl>MIT*r>$&Bzf9+^e zVFYJ*9hbEu!2wSLbcXZ0?px56p%ao30=BQV;1|ZzM zt|MEQq;9SYH#RFR6&Uy|l<6Ds@_>3_j?QZgkDh#p-wEr+@Q6Hw4%lGugF7w{HVzB@ z5RPZUq{baI*t7%z`}gm&x%qipmsY^F>(^{qwgFfH4z!df5~7k%>4p{pVf$}YT8V4} zj_sdcUAj`Fd@*RKuKzUDo52>YaUa}afHNpz{Nvzkh_dCE zdfGu4z+i1mlkyaf_T(FafQS@GhwNjV;6F7vZAXtDv1gxp#(wbK@B5j!d*|k*78|6K z#PBG*!~92Me=!*kko-`jxZ)r0>F-1JEC2u^F61O}uYXY;LAt)`uRFvZ4180Ul7|EX z)f*!Gq~2eVVLupu`>R&|&s%VGYecxcEKAJWhq!(QVyJ5#;V(=su?FRRhY&#UTUiuy`L&Lq!#=?3hKvMG z*_c#!$2ew}c{dAdCsL9OeO^u`=j7H+?B8z-vJJ4IRo6uc0hX4Qe1Ry0jr3Jaw7d@+1cJ(c&HHm-c zTQZk>SIY~iB!#z<&0^T_#fO$_b`n1EA0)TqEl}{ap0P3+Y{~H?^{3Emc0mN8gZ~fF%U8N@s z#?BTn4Ad}K8 z)d4I2YzJWC%)?)#y@^VDQOO3%p9X;O$B+ulevjjn%JRU6A$zHJ79!2GYf+CMx(k%P8Iy?<(I+L`~jI^PZEI@0x#FW{YH z0XY&d-vuE7nt}DW&HX(;ZufjM7ErpEahcO-L4bjcgb%gjKzuP%G&>k>CIKX8nl*KA z4$}>vFt4KlKzWb?Qg*K90Uzpva04EG%nlwpWG_GWqE`N2v3u^m+YaA!$m>)qcbo)~ zCbly6N5WhPz{xisWVK`m`oRe#0fsxkZ{?iv7d)H@Q$XGeTvd#}TlUvJfBQ<7{m)+y zmi-ID53{#-C$aw<9H~<>|7~e%jQ&BuL;+x15*@NcfK63nw4zm0R4F$Z-5snwcmiQ< z2ear{(v-U*)Yzj5v19e>gM_sWfa3z!t}NNcmy0(3_b+YYp_4ZKxK0ev=>bjiQJila zp{g?>xJQs*wDKJVH!jdtc;<7`7|4FONqc#{R58^2;V$T|+4&p<0Ac6G0TmXlM$JnR z9?*YB4;^vifY=5=An>za{ld$>anSs{d}Se)y``^%|i? z(Q4JA>jmob3AQ)eo8w!mCr$X;F*i90Y!6I==}9L-@|o(ETpT@vF8X6GN6iCn0U4IJ8=?+ zw$QZbrUMHLcH-Cxc2nDx#jCcmvMg-?jvt7w6aqv@4Bj2#`G&2^=yDNF4Wl0y1yT7& z17LIJKM3XBE|1a=3wPm;;c*u6!WF~CEqu)7^rz5yTjj&Iv^GE;0c2YtjPIZcz%b}9 z99{|lvh7vAw;clTZR=9u;?9+IVQygGJ;pr3-uvK}4cVJ_$`Yh^b>xsmSku!}cGJOw zZsGs?uYS)S{pQ0qKd1ADQSA>nAlxJKA6E?Gw{+Ej5zIgH94b*cFiQs?%x8egrP4JZ$0)V*kAHT)BI+q{crQB>Xqt(^Zf`ZY$;=Al(X4Zq^dz_m&V)_XsBjthkK; zj;?b9fy`Cd2hf!?LOq#Um(qhb5FQGj*G%}47U7)HAep>?_z!_gKoRPjsSnlmOFx9; zN)tPR(WHa`3lai=GZq&YZFzM?#sP2m7B)hYKo}F@t^6Gv2n5xCnD4YeCtZG+f3Es| z|Mb`FGxIRQcDCUR1uf4FU`@I{uoDb_s)wq{Es{k_s*@@vc>ygBnPI03&# zaOH&_JU=IZRBX{wVbx!70zP?;`bT)M>JRgu2NQj(%DS_CddVtpown-lKQlYUo=*7@ zZ^Rud{u?r`Q(FFSS4R;0uf7Oe`77P#5QsxuWKbbdwRtK#3;|(CI}LbKF(m{dGeUER z@F=6Th5%hfE0dK=*KOnURh=5J7#?fs_d0i8qYS z;h~CoopUNkSB{GTgiXUiaX2C1piT!kaq|hA-@DfZ0hcac7EOtIWZLx)W0fvd`P>Wv z+OBa+aC4Zj^3Q&M1_{h_a~OOgQ_m_p^bH2ag8(27Mrif?xY0LS_YZ;q(!mg6+`k_~ zHTSPDjDtUmgd3s>f(Aj16YfDsfM7v2QMe+ZLSwAXzm)=j&ck?wbHLbGu=pQ@0nMPO zpWhkx{Wpi{C!a9j!(2wWIK%b2Q%?&|8!9 zc*%UoN75qNusP}kZR1XrbeP5Wy0^oMMF9c;L&7C)dV1P!S~zGYjvuoH9T&KG?W$e8 zc*z;H7$)4CnY705;BX@}_#CyTL?Plwyt zK%(2#uee1ZGVK9!dCWV0v7E*E)1eU%P@nz~0+a%PUXO+$&7Z-kajrobE&exGG+6Y6 z@yFO7QojCmAccrj;^0Mi@vWzywg2OP{7-w~ThH08CvUM?Ed5946P(0>V$xb=9`VrFWbg>8I*;H-#a7w06Dg_iQ{vZ9=z-6$J;H_X3>wi5E95g>t`5G z3xLiEgj6vs0D!|G!oY#&O+2pcp>uoY?D)~+cJky&TUuVWvtOUh*aRS`+Qs4M(aN7b zg8-}lYtVLesZgqf7}wL*4?pG)Mme7^VD1h3_@f{ptk|a#YRhBjuEAyiqG;2m&z>4dP|`7H$i-GTE+Qo+P~!j00=1jGp@3t zBV#@~XRB|1WR>53YW6oQ{9o0If4R>;11f)YX*()ydBDtzQ2G@@fbLik&I$M?r*js@ zEI-sCAh?OhV+BoGtDG31<72C5bw2$U(mK=DfT|eN z@qO6)QELRkqh2%m9rIf3e|*n|Av6t%Kl5YMii>ghJ}fT6g9=0TWnmHFP=k{^0s-a_ zV4-Msdd7|%I&4P{AMvq$?Z!13l3Q_Y(=?cR&0M9+Qa%R=FmHx!h^+oMLj~raJ^xcW z3c85-4;lo)sCZP>Z%(OwK0bWCtU>6{U=7`q&YE@M8>fd=wdJzdRTFz>d1(~KYWJ5? z0MKrTmgxxs4DvA0o26g@=VKY4E2_r0e}FJ2MaaE#^ohjfA33Md+SqM|J#>Vm0ISwR%Ub}OX;!@plb<` z9Qn5)se2wsvr)?T))2txpKqhcB8Jw{%C9L12phKYVq>&l3mp)0jvtwU1*2gz;u}iuF7Ru|J51IOTYZUR^R#3 zHZExOMgHTGw)*K2xqv2<(R2Z{!PpMl07|zz2(X%55dq^?!grTc8QbvzgizQI*?xe~ zTDalv_kqwXLayzHYMEjR0%A6+V*WWUu&TL<`F?ChiyFz?UnmG*o=T1ybK)Sc`J7Nn z^4TC`lgU=!^D=zNTd(;>P~(nKKu<&As!)jcyEj92`)vk;oo zc}YOR4g?;Zn*ThDO@B%Oz@{K718fHZfdLPO|MKFw^j3^?SpDBAW@dYV7(yK%0&f@) zL4Ag(3jxAFggFeeNM4DW{j%v1g28&^$WeRx$*1gf8T)(Y@h9CfZIkT+82)Ki|8*5* zO9lu4hLQPawubRX^8vv~kpKjss_nc1*#hCrKb{#U7*%hq+Qz3BY*{M*OTYNg);~FC zmFp{3m4Qjxnm#p&9SQGF{*y^$^j=|q_+#~-t8}}EKotTcnb7OlX7}liatb1oe8rS| zTb(zMM!>K)l$gRS0oqnLmWj27fN+9q16+}zz^|@Y<*K#^sLzen;Rf{4vzm+%|M|nEy##FvJkfjV{piVZT3ufL;%V(7gif z>BG0FbJ5x8b7(?0(_bNYReS|n03n^m8h7Wd6aaJw&Lfly%z0qUvICt?k7^GFKAITk zEkcMiuSaCla4QUTeCzH%(G8(170A0~wir2$vLi8frwnseferovCUF;V)J7qqUFE z+49dnuw_>L|N4cm`eT{7MhrO^6Cr^5R@)hg=3)(m4fA6~UFAKVfVS0Ji|Ij#)7a9*+G4uz)0|T$s zdpGtM37|AEy&_1R~Jtw z#B(VK$U>yk?}27VW4F1}21Y$B3g+jR@H+x0ci#%+vo1w34!oI z0DxtF7AS+jfO0mMHJy7XEAtHTLq3h)!y8?f`sX={56j5k>#x0Luf6n&-6BE2 zBx>#H8QKl~X=3MiJ5-mFxw)Y=W6Q zB^?_mjQ|}PSdmb`bX?%rycQ3_1XV96ofaCwFWOSiG$lk++C@K?BM>I@JsoxspMe98 zyTc%-e$?6N3=bK?CXamLn83p~9kRoR4%zIUJ+>&rfQ#3zB_Yx`7`F6#`P?Z8zz=Z2 zz&E@4N`0Q{f6yFY>j10&&9T!ybw-{o#yXjU#W<v@E4S=$S`04s|<2mO5({5y2<}qv#h=VKMo9hSjA696) zi+DjkXdg6}sFly2*;%{olq$pGwvwH?e{x)mca`>MZH|uktsCwXW;>uIbJ4Ca4=FgpEzL? zf-hSGE?>TES0n_ueqBZyOV=X^z$VccfAe zdwfuprP_6*%p1%zSCo|Dw=)MrUnI?IPLcdDEW+SS56l=c4B*DHvKQ(8d+xLEyz-j8 z`0R7qTXvh_*WiR4d=igp{|z6L7m@`SQSCo3%pm#+!8!pF?H#ldetI00HWD1bpsakZN!pCc zSpww&tVMqnnPdNeYYEQ|wu^{)AGibx!&x1m`H?y~AQ0(mRQQ`2 zU6}Tuejirr8;bxl9qoOEbQ-^hw~z)JzSGjMiL3bOkXzFLXyi=-uK?emVa1sARsM9U z&CgDMs_*6T8HA=jzMznbN?5KU{v;K&Bafv3pd(-%%|v0$o$<&ZWT3&G9Mp2QE1AoK zB!eg*lbnoF5qypmGZ+kf#MS$HfPhq*(|F+C`|V$U^w0KfG5@#Re6t@nQ;(%5q|Y*B z=zIQ))c#?7xv*707R}i-BsnlI5FD=dFXAHrIKSuscTII?zrSlg5G)G>wWIb(uKoE7 zyYV0I*vea<*~V9_m`LT{C9nBO7x|JUIWP%0LT#X|iee3qKjQ)|h;^yjmB;?=zFlD? z9jC!m24u1OM9UO%As}T-U+oh)R7gPOMvR_}{jr4k2MLU#gHDB@95KAt_f1XL)*Lvw zykX<#v=S{rKvnbT*gk0jXaS*lOMn`ZKI|F+p-p|R%~mvN?;@4>Z1914r~Zy}RmoV- zrV8i-^oW>02UrS6Lj%ld3&8Qi$84VrHebAW(KseB*p5mk1ineXm(T5mfM}9+X~2k{ zYo0@4-h-jOJf@ksm(#wA)$l{xk;e4&wA!&~k#8$o02&1Vz##GuO5VF-bNSPdq7zk} z?xe$}`xJFUh!C_O8Yibv@1QjR&Dw2O3IMtd@gdHSfgaRc8Y_vE4*@_JppD{IZ28!x;q7l>&giYTI%3=P4FIG#`zzEkL#b#=er3 zdKn3{6{-AlQow9R!;l)#rI`=8b1~mCHnJ{`7fs9VcqjZYIB>7mosONUJFoabhry)* zpwymiaLLTfj2%6E*bW~)WUDKycKPZRHw>6%=CbtRFo3Qf>fm&V8_-q1&p2o_RQ7{i zu*Q!;V1V(zJi7rgY*4L7JC}5_-6MwDi3UK7OPcfz?%ow!&;mYpsUK3WY=4UJ^R!UN zi|`G+Ml3*w@1+2s!vG$IHrsk2de(8{JZdjnLFk5TGa~m+K10f#CBOUE`+BUwH zksc6zCU`35mLFjRTw_axgy4es8U;taH#E_rYS#uZjsnP9))AwB!SG+nTDAmK8$U8q zeYEBfP_46}$E%%M5NEC957AdZA)HqV0s5m&ov?=v5sfhswFRLKuCLk{Hg0rmVD-|H z1nZ(L79Dgu33g`e9DX&TBq+^aC?o`-bO`IO>jz^$c&}H~M+qH_w z7zX5ofWtQ(_R|5*UzBm-TznCjy%@c`?+yYmyl7oyVI7#|uq_z+JL?d>!~AnEa?toe zvp9d{KgQdQ0Dv?CGarr!+{!!?G@bLtUg($Etq=hgXsrT=?)Jab@@52Ac`qTbeF!kX zvx7XQLIyZ5ep?9qq5 zY4_Z9m+jrRHyQM)LPoWBnExUNu43{@Pe4Us2f|-#Mf*_cOY_((@IovNw{ju{m;*-mVu0+bWuLHe?WR0)lGDor79GVa2+QfE;qT zwW^-uGsbZV&Q@S*`!~?YnBZO=Z#1UVGNZDM8o>h)hac@V*11pLpg$lTTp$xk2k)=y z&R;yQIkOoyfUTYMYN{9``51VE z=Bfuey%RA`kcpRQZc!5j6cXB8XasL zbYXx}P7utz)czlT_)&ZHrI&Pn#Eu<3CTV?UhCwpttN*&kQJt*{6A7!{T)1X11pk5g zRRzJ#fPzVt=UDe_9lYMj%D>k;Re8a=3gMy^kM+}+ZTWW}+sdCl*Ixh2$?<-vu-SBX z@lL9fDmO=q(NBifCGbZ5e@)W%yzw`*b?;ck*fXepn?oFSEXy)shd>;uzF5l7rY_=- zc;7U_&<6m9;mD~7&7rSyUse$4Lx;EqWYIhXH?gv2c2&m&N+2)>?E$SZtyRqip?lJn zk*{S=b74TH>K;r#+~XBg;xYjT>^0Ua7CW!*e2aDFIfW9S0j8&>Y_I6OJvu6I@!F!D zJ$Fuf%vaOFk^~q(Bv88DKD2S&002M$Nkl>=@|I(r3hr z8URK4$HhH(i_Pqc?N$STGEheP1jCiR{6&s%b-_fo6Ty1~djyT~!?tF&Nat-IXbjul zw^9S3z3?2_)QY5H44N=_wnEHp2Yd`juKG$5hyxb~tDgKl`fK=V05XWNNLq15|K7Xq zHmvUpG)P?%(qIwO%Unsi`*qX2;EBq>KNok4t{xm@c37}AIZm7wnI zYlO+C-gRL6b5+QHL#rGcAD^?8cTd~u-@erGev1KK9fVU=?aO|6-v;3AR#bt4dJTwo z0J*l`Bz<~7irv@649tIGP_C~_I(&r_iR6_6Kcfx}E^p-mx`D826>7A;IVgmVw0q!_tWO_e z#z{Lq|0-atdR*PECNxQwE+H!?ykg@j;s%~Ef#^R#cQ3krTqv9LCFqm1i}jA`FER=m zPGAawU>4ch`OW(u5aYjQ*KaJ@AKv<-Ew3!4@CO-Tuq}WvoqYMcT?j#fHUOnz87s~4g^jkPLo9-QiFbmFNL0CWPX zBbO!}w`jmRR`&U*0NX$$zcXM7f&kL453+hrb;2+VE|`C|4Y11pzk_|dIX5fuLwN6>G;WUvEJONd(LVp zhW^%1owwC@#Q1;kwKM=OTJ@S%I=bL!iZyAZOiZlXWJQcbmPqPC8M=`L1ToA%N7a?C z4G>U2b^*XJjOA9~$PVj%s;|mYkzjF51iaQy10HHsm!UwsEi1Uqk2EF?9PitV-lpKp zy$E7WLV96fwP&`|Z9OAa)!@pQW(GyeDQY8bN%*0PRWIsK+)sePJUn1h?V6ORxt?)%S+Ulen9{;|AhAHYN8ImdbWq2A5?CTKl)w~SpaNhH82 zwk#*RX5?1UfpCU-LldJd|p<+_MU03u;9hIx=L+9@J5P|NhVa zYOg-`ZJif;ppiiYr$BJTbMA{O0Q1X4?2~He>(tpCRB0y`G;uPg7BS3#k_mNP57gg5 z%TL{*@?VjGqm_5g*yVX9m& z>LP&FjQ>T7u@~j&LY}@dDdS`~H@4)f7G21A3t1r4Vx-cy$3<)vja$O0#j?}R7IGN= zAOS6l@phEgeY{7@1csgVQU2o+=J;`K+lRfY3eyinORQ?;mUJ6uob9LC=@=ONV+)!a z{@YGwt_^U-?9vUZoWEw{7jLoZ14nJ_@O&^77}IikOD_`sngrY~6kzK>wyB*6Q#cr6 zreEe@1Obf%QcQI)?xAznSNG}US$c(fJ3XTxoht0ciIYwPBgfXyXP$Uc^ue081njZD z{r%mHO@P?LN^O8nbc#Ajo$au(Yex7t=T7^4D?Vd^e)_PQ~?`j^f=)yG!jAY*_Xkiox)AAHDu z^!gk2$_p>r!Mv4!Eb<~zN3u>OvW{dK;V{9CS!6>F#yfQcr-4+td&A`vo#sXI$;Ik} z*S!t^)cq@3!PxlZf-V2{V_W{shqfjSfaAk+#`zoS!t1Zj=ICyd6jQDGB4JCZ=jcKiW>)OJzGb?mlb~SjYyE z3oUk7QW*8C5}HepUR`F+)jRZv34!JGU7U{`cR;I-?5cZ6jvtm4Xfay7s5VJi^8E?C~t zcj1&S_PpodcELYv)6MUs;Dq$)UYnI8?z?YpS7L^(2w~s;R`3&L3gyeoH{dsHks$zp zm~M2GrTJ6@@}+-q5Z)T!cU_F~gxZX@E~;Kv3)P0qV1OWmiwtkJA&Zep z0^)!b=U(>JZUG!d3_@d41h5lRs`uI&%wi7*YF_2lCbSFMEq**&I*j9>J}Ym!e0}jO z__zT$-MfhR=tr(jt+q=$+LFGv9fu7U_WJrf%~T~E&T|;6jp=VE-A;w2b{suBAx0aa z^Nt-=<2YT8$X)%ys%Le7_?V47c--v3o*)eHHdR2vvZ{|Q9-a~8^NqqpS9{h2R`PM! z1<15f_%I;9Ni~9SggVP3+s~;tLXWsb0{SJ$|eBM*KS<5t5>ht;`OT; zu#gc6m2Nu_plb!q;Ko>?iGb&BV7i;Qjpf*nRihYp=cdl07Mde@BlTZD#(NBsOFIU4;(Jree3o18uEWXA%=&ocU++ zR1N_%H)cg0nJ}rh3qAB4f$a4cxhHLa%K1eZ_|x%z?`g09r#fB-<{yHj4_rl){>Hcr z0!meK90AV|xX7>$(qz-uU{{}psTc)#!u(HbhwT@f=BR}ZBivKP z&}-~G3C;-!IC_@%VhALVDP56nMh+!gbmss(~|yS!v$noFzeIyMlYzylHl9Nw!f0m-P~=J3`- zZI0G+?v?-&*Eh5YfZ?Fq1@L}NRa6&@v*p%V{&YFDOHKHZ2mxrTg?;;U4D{VD09agH zv_HN5mJ9=~G|dHoxEn)AB^?siZ=-YfU>&yhF9iU*?-OMTeF6cW1HCMD#KV9^73aQt z?z4Y+<45+)lTV5HKP=T(8PXE)Z4B6e|pJQ{`j%2{^hie_mlLTV~y&KkxjMh?{4ge69GgxqI%XY z;;icxNiu{iz zZ(B+7>}b8Vm^fvF)?n}dR)ri}N?J5WmF)mJO4lyQV!ez7jz4~j*{!l&gqxspEfHgft^tuL9xwvsjq7I&nnqVb%5gft z;X{Y)xu>3SVG~+)Z@=@`!qWjrIf6WsOZhqy5QrUa@GDyi00zGe%Nhs*bvmFvI6>0W z)3f$~R{nqbqo3G|&pzii05B|7b4-Lxl3aM_VRn*alH|hGvk32l^h^C%1b4>T~nju`h3zK2d^4^Rbp2DM?(EyT^?e0dU9IB9@amM0qzJy*G2fQ z$|`nW4BAu=0jE?%*ttD(&6Za>7|v>o8~17?Tj zZEQNxY;(}-2lamJdhiatgOER4DEz!{=)2Q5$$PuY-i`FU-pVM_Xpz22=S_bbS3qn$ z0SmM#8Z-g+yAS}FA$ zm{#}hD4O6}@^@DdKz)|0ks)CqfCNCMOxm4rk(kJ)%}Vdw+`K)g zmH(go@JII2bI;pBodMg#{4*JF6*2!*iF&~hH&!p3W&gj^AZR$$2!b3W1)iq9YkG*x ze+GGTyx+zbmu>CcGq&=Zk8DlH{8bm1n+UPUVDtlE!t^7eQ~iQfrLdaV4<*}r8K?t9 zG=~4yqbADMqn9CbAOJjB@nJ>}eIzH)FnIaUpRn1P83{!t0LX9y;7c3~T)!|>S+Iw- zf66)3EtRcyo8AN5(#&+560Rjft4Nf#Y5zeC5SW9|=V}Qg5BMUeg2~UL8zNod`7v%= zQRCUfJM>O{rda*gLPEzi%vOc3qzPabByhj6?sJ;WX-r2UK&&GG0yf-n02bh-T>xef z5a1ufro#-R1F%Lx-mrCof(-ZV&`+1)sIk2q0y{h+nf|!%%k0K zJp0coM_j{=U&~Av1WP16Ckh!O55VsFZ>46kdg}FO;;Go@o=bd8wU$m#6 ze8LvQ{5PoOfw<$!KhJrXoXLR;=AX(8tWyOMaBxj}WmVst%DA8dVTZm&NqP+CAP}*o zc>%LPJF>^|^U`C-s})ob7> zwSIsn-FyVB{tML3plFpJ#;V9o$`$~c00?tkC{h%#7yiOOpkgV1=i};Llxd*y1c3|b z!xVJ@?;$?h8uL%?Fzpf)NE<5;2SW&>MjwSz&0r4n1`7*r1XXi)uY~}<$N|yslWcQ| z+v-CTE^E#`ec8seEugX}8v!e_4{+xp8{0drd0rEJoZktHuo(J<_DA^7)#UUI)Ik4W zI{-Amz|JwM12mhrh3<)PlN!|=@KOKqIz#J#ToSi$?_PWCkwR4NG(>aG5k z#SN;>El!u#QeIXXWPt-SHtNQcO znyq~#=KptE_5a{&S^2*q3&oo-|1qzAfS<~MKnhjo3GD@(a6?EP0(+a2^)9F%nE%cT z)!JP6K26S<5W%z=XZ2};cUmlsK^Uz`5xl;qI)`ZGJ1Wcw0anMvOt6eff=3YvL001Gr*3w$0#7aB;8JtMG zEo9v?y`6rfl!!8X<-g5fEi4nTUe!3o*sg5uRM85+-F4W;=49U}+A?AcQ>Ge2uXh;Y z4BTq~bm0Jy)HSGf0VuxLnTO=LslE!}+W}}jg(GN!@92MrbUgHf_ucPv!-WeM?ae>@ zE@Kmbgo)DJhr^fhcQXhCa6@c1j`Pq|jegm*ScOM^gUdE;@NNHZC~v+-L(DDUGqeEc zfQ^p6LK-2R#&4m+X8k(|y^ivO7KA=wD_GKv z5QHAwzhK|I|3O>H%fUG7!pgl8bm#+?iBEBH$lm$@ISQ^LXi$c+k z85i*lnraghG+4GHXCk!el{qnNbm?uDm8n8>LolV4t4DGd|ks_M#qe{gB0{VIzqw(+@E{onfB zmVfb~j`=&QZ2&7x;Yg~Li-LewVY>B=K8isxUuB|Sc7P~uXI*F#SN-?CP9v3WR}c_9 zvHI_V!+{;(TZDjyKE&+o?6j-*Z)W=f8ySR=NL9F1D~x^MU<%p3wOQHwpr`{;1fSB> zFLsUhNJvaL_%w{Atye$htzxJgnxnitnyTDLW&Ym(Z0e4=)n8-&+3($Wr%z5vu!cq% zQ*O_k+XawDo-_igmzTx6Yo6FUV`DR!H9p!5Apnz#7dQcYy5RUjFZg%D_OfE>g6;H~ zO3P87Y*pM(p3q4+r-8yF^y=*NjGZ`k+!iDZxO#2TE?t)GqxID+nWP9IVFy`=KJvf7 zFOE&_X~(y4!R#lnPY3Y%C)F4Y-@;2wBR_sULSWpBY?Fl5dbaSy^y)F|Poex_PDBV$ zuZ-&upwnuWa4CFtpc8<> z5QG4E1KpF@(oY?SkQau~)-{-d&|!XVE@A$EYOlQT?O^RcjaVom#{Q6e7cs<)OILvx z;sN&zs-rzN({ca_al9YQzZ;a(GxblojSJUo?ayNTf2$+@bl>>mQdn_Fh1v2W@aO6m zr@F%IKzwGAb-xrbmLoD_$_;|R~vwF?4*DQ(;agp6jAdWjSIJ1rg4LL`78g4wFFRp+%( z0)A3Nb^_aKB0CI6xhEuCL%OD)sr&^3fmW{pGyzKB86t1cINl@t;);779Es0&rQo^l>bNF7GyllL$j7t!RA<*XXASh)%&08dG6aeHV-XYIY0MH@8j$*P55C(4=*8&IL z!=TVg&JK}dNYgR7OVHNW*?W$f(3stF;-o$D(8KoQAG~2Ne(QNVfWg0XM&t?OAJyK{ z-(o`{G53}K1oKD#LAz5o4E+@eIj9fygz5JyQ(plZ)qbq}ul(*~TY2+iTl?^wj`)M1 z$b{V{Y}!F^ZZpfm;GrfU-hg}?`b%M~?th@)W2g@8nyl(!_e(SQInwShwWF~5PoIW( zozb=^U*Xs)0Wb7{hD_8t>1C_e#^+Yc-pj%cTHdttF5n9D4}PMb?A(PC1grltQYkII z?c(APKCCtdyuS0&Y$qlHwXpi%dTY&g(rimu=5-y>J9bg01V}SrY*qq*8C{|a8ej{s zXgiuueZiUiYyl#z#CNV;^p|YXU45tQfrt!Mpk7{|q!j)xkF>xe)tS&Fy-9|pp)CV0 zt=jpE7nNixP_071x%M*B4^`J5$rB_80J$cn#!*ARtU*kgXrg_J9ciG=sis6rtN`e{ z6#xXa|3HJ~w|6KZ+mXOy2s5)~aXL=?5j;}XF~`NY*>9bG&*%qrI=eFcVTJ&RF&uFb z24<`)g9iS3EIG?L`fu+Z5N#MpAQXs?s_m7<)`uQ=(4K$hTlUmrPs;lLfyTi{QT(Vs ztswE7ha_NZ8JCg4&BN*2D{K!!t8y%oAx!0-S5HdCDuM6!PbPi<8l9f2`c}ETWGjFE zOh^2kvW@dnDU_kV+Tsq*j5~H!vh6DRNW+?4x?oG!WSp31oIhWcN{}dR&w$ z%s)hLs@wOtNFB@GS5>t-30~fggC*0D@RiNU@ioZ_S+&?s3hfFjoCaanK&iJY?GaDM z8x;8N5Dp$+xG5m19VSvAhGL<`do>fzTTPh04j!jGt%&rkrngx*2>fx4t5D|6LU-|d z9H$rv{OYP33WQb~e_RcHWUm=^0bp`*w4EFJ6F%hFUuXsv4zdn^Xo`q5u?rBNvtj%7 z9k@_zXgr>$lKN)LOBied2qZx`LSR5MW}FW2z`ggmK=shVLHpv&8M}D-l7DafAr1+Z zj;;gjV9;U2vo82G!^_8)`svshb65WSVC+U=^M6Uig5{4p=ei-VDm z&+!{~;)W~j%X5eae0t$Z4S-%ieMs|U;?3{mnm;s{gJf*`9i4%mc5yJWy7kz@kJ!sE zzGRO|1K`%1Pr3xI7M8IEV}}5Mi7gL1kTy&)7cP@m@a*?r)eW#hwa0qq)s@MQz5c8a z_ykw4tgr6Nn((^R2Up+z)K-80sgC%&BIcic!1ZvuhD5-3yH2JZ3B;nXzt|CX-%Z*G z&NTVxDp&v8(c*z&+3tSjcI4dcG@$XPCZ=shC!*}6Z~NE~4uN@ad>aQ#mnuSb?5}3t z;IDM;hX7F3x_SP*xP|PT0QZSx3xQh%nUKmXE3Byg=Mm2>qWY)ULtI#zB^EY|yu?d0IHKnXx622x5{Qb>|B%^v4Dl zV1(K{c)r=;2MrWf`J2Dv6T-m!*VAZ(Jv@oe`MJ0u#B;3r5TG;00&?HK?M+|N7VPM6#&EbKx4Z34VS5tBN8d zrHb>!}}B{<(P1V6&?B4z7K0)>gFNAJu=h0913-mD0)XdcYtH0jMwa%hpp~?g!e5tFkG^l|Bmdzp#Iw&Ck!Xxl%*;Pnj){so z@|?vx00f*1(}Tf31Rbf#jL*1rsS2*X{h6)4bK2HVowLf~a`@1xU&`6stewiOWx5cH z>l{X4q}3;#uN~FOrr|h1d;ewhk1L>r zJj9TV*!&Jd#UAHMWlE@n9;v?A70`uMku(w4T)NU{_Yj~>X=NI9>wSdK&iuEbGqCCp z;XL80zPqatMqQPX%2t&|yGp66-Q5)^!K_TVwnCpX{}G&wU5*O8wrrIvn%i%z*!aUI zZS0t~1f;jVK^wT5w(cCy=!*)Oe&GPnk2A+`b$WJMuicQ2h3~*U7Bw#XXzmYN98!6K ze1Jg|0-!mW#6tkIcYd!u_2}cG9X5RX;5+aB&92|jDGUvc2-v33FK`=KhlVB0bTa^e zO%O1{iV7EH;Do>h`(bNRVo5q$b0YE~owYR`?JTlC#DOs8+MXkwpskSDUD63-o4K%m zKhlnk6$tgC?iz!y|oBZm$*uH2F=%>T3oe-ZP~goT6xwSS+y(zy@9vnq+o z6gZO!oM-Btbxd$^zdv=Y1J<9b+6u67=CUondCFFP{gJJIdcmqXN4V1tlCz(jlZon= z6M|!~l-}F&L5CrjSd*s9Mply6Pke0YIeU2B_@YDJldM>V#-R`KrP$$66HZ zVmAQ-rkRM@PU*H1miYl94&tb{<8Ujb9f~l*H(Q0Z_W@0sp+D@V_JIzVk%r1tVmNCz zsS%gn;`IQ3y0A|VZFX+>Ph7@s>=m@RNLx=1a9o!*z`5&A7mUqGJBSkkG~gQApKx(Y zBtV6}$U4Sm^yl*+Y6DQu*hNr{$l@E`)AeLxPPrK!5qRXLL)sFs*KRCb7X!Lxi`TBD zLZly?ncMW&VSk47ESf*)dk*GYoFC@_=AO-obu@$P`Osbn{>eMf`aVzx4~0A^gKxPM z-GwbPo;P#Eg@F$%_{{WY)>!Y06hg?%sYTSlT`Kks;z%{#n#^b+*beenQffCDq^6s zgnhkm;VBA&vi?1L7le(Q}8 z`tPLgr)E_ZW_q`dG~!rQuk;fsI@vFMf3;g8-+kG4TlbNQ@A!`z7sH)dgtl)-`*Z5b zRNSVLH;3&I_@TcNSww#zM0S``b2RM4Fh4-Q6ho;wUf=mZA7I=UZ2-3WsXn$Ky8tYl z#I}fcr^gf?+A8|R3dMJT!Q~w!ejK2CEIUPZJ}%R`)Dy2*U+S4SaO2F(tnHuQC;3O! zK0ot?UAip$Ne;Ids(vT@XgcN*k>6}bZE^u7Vf(NHx&~^3#`%Z%0j{YAXi6)10RC`A z4S*tsK5WsT^FkwVFKWAVR+I@kk(GbP2RZFZI&6Dp^*^sW5Pu3meGlo)QUH){)$+Lw z5MTf^h@vDeFUhEOgX&rRd)^@7D+A=_6F1v;UwYNP{rrn|-(7dxtdMTakp>eKj4_sO zeL&T|h6l#>pfmr}Yb(q@5=X8G(1>xXfKC|u%RqlXUIVj( zR5x^?ROjqc4Oq1bYG@JwbScka&W0g?x^kG@hq$Jo22}rDrFu%}5K6W^&Y3C(gkT8) z=f^0vC+UV%$Ol{>h~(~%y@tY!+zarIurH`Q^M}vvyTeSV&rizo_w@9Xwp?NSsvy4| zdM7n;LcU#E0E{L-tw4ec%0KW9W@mX#ng9|4XhC3%?UMUuZEQxG0I@*;BuyQg+X1T| z?$Hs}ujrwB44?Aq`$y`;WRX`N3ZJec;Zk)3*P@*|zh~a@*H>Sk)m8v$R1&VqF~*ua zhu$OB8JMs=C+ouZusGa z@C&lXaC~5XebIOj{zI6Usp}St(UxGP0H7^kEE7pXAQEtO6`b@}@GJu|P3#5S+kjP* zC=i5)w9o2C-~XY#@!i+$fqU+2Wc~@KN!eKSkH`HbaceiSL+zc5=l0@*S~eYh07=07 zyXwF0S)>u`7@2>UW~NFcm~UJb^Z(Xow)~3^Y+XWt$|YF_&OyehSRH?a=cYRvy|LlgsOGm|r7syOzK70ULHD=eN1oa&=m zJ?sEDA*88CC(0iCM0qcQ0CS4I`7P6T)Yg&l->o2xlwqW2#QbCZpZ0FQ^GbMK5CF8J ztBz|-h1GvFYlg%D7#U78(FJzly4pfC)c%!1z7B3>vJc zs9d@}!6)%ky}bT{74&4{z+Lv_{3YNa&?|c6BoMHZ}QukXw zeZ^LO|FJFq`jl;acHXMXn$3yVYe#$KwONnK6}w?nN9!gt!lbsL6A2(%OSgLn08iI$ z8Fp}L{Gd)fBj&$ds{dK&GY&vKsOWPdK)Y=LkS>H3_tNzW0<^KWbW;JCuPbe^|9}y_ zX%W6K|7-*3l#Bfp#?@EgcG0gWGeR{#t9uvebgHhqPM7(HtpE}PU&cHCb!lpE>h4@<`0nuV&^~tN=jZJB zk)zsSv1VUiIB!eKH=N-OA+o;#r)GVJ_1(J%FqO*}B=V81!^{N%7kS{+Pv9BwKtK?* zjGLM$6~29sp-kh_Sn^X#guBAZe^Q|&BZdyR03(r1lKmDhl*f(yw-HF_En85rC8AC{b1sca< zV1!|YLDKpkEJuBGVIPSJ2O$9OSx4P`)n5!f0uF$hI5*a`xMJ%cowt?W%F_RDKeozO z+MkB;pFRQz#9F_&xYC7|Cxl-&)IELDPV_&V`o+;RUOvpR1%rl z_3PJlJm7UPg!#-MiA9jbG=}*e$9zB~b-2Ykr`7vI*k<_P9|Z*A&bEN&v|^gOyNA4j zu|8J)gTcSR{5PkJuo1?;$c7W;MbORmr&zz{RJ!NWF7vD1D{-0AfIuJ&T%_hw8r6Vc zhG}%+cntj53scd65Z5Kgz}UBUpWSoUJ@$iFzh~dL^>$x1@Q?8a;WTRhFvlTU{1Wb9 z7_LE8`)6*6EC19eZb`oDc!aqKpRBRIi z(*i?GIGqT7Y2c;54d-)Ep@(UQaA(E8v7WrcM8hm=s_}4H@Pj{K$^$L|KPjcuQG3}m z8*|v&TS!}7K!srCAGQ5}xANNytp)@D>!Qi?1QJnL(Q50!)=JjCP^AE%eXuN3%0PfY z%OKs@5J9F@evJ*e#?j7xAOr+s9KR-p3n2goRqp)89roN)&)A)}-=RJKGmR-Tv7q`7 z0?uRp2@OJq0U-ItEcx2!j(Pz+T}%$#vW_~T^6$p}l8+JV>5hv3+J|5J5r1o^&RIo! z{QBD1A9d`Lb`ta?HxhFrRjz6k#;T~3WgBJt?=%^#&xRiIjKyp}#WDsbT?AOtl0)o3 z4NeG&H~}BZ!Sr;}k$zka8Pj$Zr@Y#bp`)(0G?vEZ12sQH9S?uZiE3vb#T}Evw&s^KJLw z{sVXO=1oNcJP`SsbwXR5f>h&D{G7#jL^r7Sp$78me~K7^CTz*a_k?KdmkBp2)epRP z9@^J?1`&M`ui6FjFt>quNLJWKVy64pG3pn`=7VfArB1g z>Zs-UgZdGd01S%qWAR)%x$o#OKF|Ep9Uo!cUt@5vmi1fje&Bxio$tE$WdJyI;D81n z47OgFgh=+sntwi71+Vz9dj6poXfdfWE2PNT;2o*M%&0v8Mcn8Q2+pWkHE7I6+%Mft$p{pQoEv2>z zG@Mk=$fm6~BKZ4h zL(6@nSD^IcsrTOh@a*iqi~fQkgJm9hOP+y|w!#vE@V?VH_xpD=0Q8&UWA;2cz7Kst zU}OLpH?32lc^rhvmrtB<|MlH=uX3*Fr@8t`rsYl5oL=?*8UHoU>t)d zfKQR$0L&-=EO+Vm*ct?VGM|Z~;ii@ZC^?`d1e~8T=S!u<+i#tud3&xAKvYMzp$uD2 zfH0L1Q510SnE1aYx6!NgNyudM8=_bD?b+j&m-n~}moB@j*RN)Hy+dQZXBx{2r$+P} z9H9?#6>~P9tioyk33kHwgI1VvhaCC-d}*y+8H|K2iKxo-`@h+aEU# z2-#1AHv$`5{VB<|DgQc=QNT0#+%oZ#XaLA~VewRVDL{w!ojy6xTL(OrvFDE-b$_RX zf8Ublf8YMSt-=CKR$)GEm4BKv#Tc&9T^xGbns7rdG6M&bOb&+wx1jt3Py$E1{?#kD z-I})dd-Ts=SonY0z5czWX_s1;u)^9eZ^X)ZFWY<+0_nOE)v@(o-UPVKrpNX+%PW#2 zOpFpy5NIY*s@V3=BBZ+8H#^a)!PCXtQL4%oabXId`T-%_WfHhL(X}ksE$koTPI8jj z7I5O7Qld%zN0f>+$Gp|=4-eE3@pvUB&K#T&*e9hFpbU(CQBpul3@B%U?bbA}tpbS( zpaixPA^}j4jUU<7<{z{+>e{#H&k};6EA$(|oh6@zIVU)u61XATE-lQvX(b1|dhMFK zbMKBRjEO3#!+a$-RdJ|)2EL4J)o%Xqr1dhAbszrdJ=j+c1;YG9+kVMf*vTWQ{D)(% z1%p9oH@|-ZkLACS>_)ObK6yrP;Gk{4tgUIS$ID9*NxJgM56NF6?$sW z`w(B7ox9OwdD{>_#4|aid z`hE;Co_1QSXNuXeBMn=l?Wi#QZFa&U(_5YF+l6e4B z(F#i7(&Cak^~M|S)~#Fa!NZ5P9Dwia!ZQLZX3C(3|YZ#c2hc;t}x1A0{ zf<1DDVN~%E#X(`;d`~ZE=oNj|`V;a`jsl;jAnWPgX@qfs2t5qZS+xdxE*by^OaHNW zdJqg@gbZAYSAaG&n3eQTd#Aqm{4w|8JMXzC9(&A~L6a~VH6&Ug?gO7bOgR z-SP+QpwAHm6+y=Jk1exha#uhNx!|n3C0y*_8OX zMeAw2H=So5rG6KTOlqY+1$gl=DXF#Lh5^8E&^eROtU@L%^r=Jp54yKx1o--!(?-Xy z&zv?zGV2EV>7aRg7F^vvN0$gj0K}km83~CpX%&e)T}`|vDoK5Y>*x}`t~Vkyx>uKh z46p=c--rC`o$KX?Ynva5VFIToJDmCB&2#8}yh!7>j)SCjI@x@HgNm;n}RoX$}THa6Mc1 zuL;=moF<;KLT;SD=~n*jYq$E_vu@+UZC6_vZsot6ugwdM7A9tvTsr5@%7*&unuOx4 z?P7M;@_61&2w_bMX#Rve8gzk0Oi8F|X3n}a ze;ti3(RD0LNybCl#X_4H=yvk)5ef9L=DJ}ID}s2jPbZX6{3kT7%3xgU1Z&@~Lwb?} zYDoaw30J14TxCvq0dUTQfzNl4#TakMHZ}+o(1vkH(!5O<6ZOh?2ri9DMnAwc?8ek# z$k4auCEqSAEJ%6X?JiutY&!$wp*cw2o(EH}&V#GRmvL-F&V3Z*_aXRRAm%sS%$H_o z3*9VSDf-=bz4aTK;r`z9k3$H4lV5z;KL(02ZTXi4Z!`d8Q6--18U?b(i688KyFd0y z{lWJ>(VnRvx#cBUltZz}LqCWZn5rwt;ad2H`QjZ9p8s}ZGTc*^ZzNKT8*r`=N|uBT zT(G9Eh{;*D|Kvq6z*U9)pSj^4{r4}-0I+dIp8sToKx_4(`(?^SNuX|aE6><>lEs?w zfH{F>1z3`sZI=YuAq0a7+DB3V{0LK2EQ64LpZHJ0H$u~Z1!#l7JYf~<)Aa4K6@xL* zYP(Wl*^uf5Jayj0c*>f$d-2Gvw}~-F1EB}+k?}O4`Ise%M6|?`K>>#M{Z&`Ft}X2p zX;>jI6FC8Z_&L`{O;<&zjQLQls2IBzM|&iFa1&ifcfmJ=i3} zeC*I6w_lF0hmTg=>2u#G^gYjMBhFQ<+4c_|nyVVy>MMLG@S%1E9u@M>m|Rt7THcTV zi`YK#{IgN`S>LZMwUv9TS|!VWdzgIA0iRpIM<@Wp_TgxUe>bj013)*Z7~9CCfFF;{ z7@G?rtRHH-zhC|AXYQTX-ZbUEF<=?E@BlpjAtQde2~++x7%>23KO%icNq!4A!r%D7 z=rWamA;fxrt%)+_KZRda6Y$y>SKP|KeCbwxd&bqYF0Z{svLvW)5sXHE*y4RXsczkj z^=I-9>9c*<2>bVW1xE3m^@R2v8r@(Wp7=o-mCp{KZ|O2@acXkfw*9m9g(VRz1eV4F z`#O8WR!P8W&=&S-hLRnP+eULEe4r7eNt^KhG8e{y=fCv4?iKQCkgRaGl1A)6cjz8K zWo}6h2q)#&-CMQg{FMb6BxkiOAXylA$Z00e;KwyYz|rFS0*ZJi zvcj{%$1CV8{qi4l5HDx>I)TLgJlFhnZ%E*trqUnQ`SY!g9B$3|#&`kTc>M|c4?LvY zeL5Nda$aXVy?qKWsC;Q0gcCNHv5YV5SS7{_69P&9@ciek z`!~TZ5S<5}f95MCHI8U}z2<^Voq`nNS@I!@qc%<9fVxAxg(xAJRQj+OAQrgeFq z!Icl&u0WJQqOP>N-9|JU!Q8hK1z_(_&t=OPGXKZ2a|-y-bI~#}PIlgE`C32-Vjby> z3;^t0M~eM?h7$s zfXR&U`bMv@xmhPYtZe~qhfLqDMFT+JNF5&p1qiPr%m2@R@FQ*a_ntejZ=ajc{=kjG z$U*Tp&p%ex#+Bv)BiIZ8?FVP`hLRkC8)5&!sNuOp6FAVZ_5R=omug<(xORWVt^VhE zxB72ix%Drvx#}%>{>?g>s22}=Mgg&PwOun05uu_TW~59w5U|%et|803HJ;o=0a@#r z+zU+9n{FMl69`4@qdqmIwf`n$W--RWA?3%0VAA^_!X?SN1_xE@$r1v6Hs*5CE(PUa zelov^KHd;87!Zm+)lZuOSO>n}6}>aR9tv47?6xSd`M1O?401fzD8&yH4IrmYWqH=` z4v-vT)Z>HmgE@4QlB{#-`cy4b(b%y32iKJd@%(M)_4vgSPJyuQe>;&~ouM7! z8cbz4Ewn`-xdGg)!2wsZVtk~`c`aQ3u5Euap6t?=F{!@Q>cCL9`jBp+f4;xCq-;oFScCs|I*t5G` zD;fa0P0=xK&-1N3=H=WTDgUpYc-j5x$3Jx^kH2KhuR$(GG72(#%VGq`8rgXIhS~Ek zCT7;}G!q9e3;UNPJ?;4yfofWFX3GCRe(KggzvQY96n2+8Ni--L4|+fWKb34f7l1@- zy;^SoU=oUDhZGPk*+#J&dzJ4HlAhm=VvX`YrL5bmPcCbbNF=rmbE{Zi$3Ro20(|gI z6h1r7nq$fYaGzj-9Wjpb6^}jvvW3Uk`&0dHECtw2=&lU&B-o5)n-oBXF(ZHs0XR9> z9Y8q&S`0L>1M6%Whb)6kkH7Fc><&Vs^_JyRW(*OWK07*naRQKag ze(2tL<4rd|SKscBYH&2>UQ_;ckj3DbVDS9&Jv2p#z_1AW56XWUcJRT1&Q>xQHxk7X zo00JEuk!r=w@=;brBohPDfr|i9@F->B zFiz)e{4k#6{U5GUpAYo46R$mM{--pqY)j1&%`wCEF6z)Czi5j+g9G1YzPv`M)gX|7(X+Wc;Wr zt69~P=ZHQb4;C`=zXb7z`i>FB-Q)ZQsJE@sZ2>XZt?`f|{{=y)@2U_)l z9yXuZGn61yksUtVKNtXl$A5r*bcgRb8US`kz;VC5$)vKm6@zkicE)}C-4ERlzVjXT z&YN$!C0RQgqm>F6&samn+W)LkY|6hl?64{S7&R>6pYY0>4C)h%830nap=7eP-|C+( z*fxJ_f4%4v(2TgkGc4oDCLAeeUXj3Nl|Km}T(g}_Y1c*%3(@OvqWoLTe*GHlv_ zt1dMu;c!Ol{wKBme809LeC`-N>0rt#pHUa=49gpH)p8xh|c$taw zs#gu8HdN@tx9~7$%T+x8O7_Q^|4znxj2f21Nk#yoAJ`%h`L94Bf!w}5dt?OI<8I%* z(a(XxNGQ}QIkPzpr9JSQ3F>a658UEpe!gow9<`oP@@BD8`(Sp z2kk6Oe^@MRX|84E#3k%_a0w);m1X?0q$#@GlHhHAO6wd8XIS@90}_)oya-wlM%ex2 z&Tatq!gc=^&5o!4sZY+t^D;Ca*+}0!Efqg!PtZvq-Y6rU%1DjtiyF%aq0-#*2bqj4 z;b?TnHZ^Asnb@n1%)slk>MTrezhV(2#+jAd6JToPrV31oVGSo@t0iR=S426(Y8#xr z(vRkAqE#iJ3N*4C-K9(uWJ(WJjo{r@22_#MW5Y5@#xDK1U|F;i4-nMT$4Z<9CqjtM#XAfBHLF=fVp$;#Q^U*FNf6Pv?WVytpl5Z34Cu{C{m8H#T_ek)^ok>c#8SxwzsL-lc?H( zur!$caxOIg&W>2;G~yYZT9vK3Vad1J#YqtTB=+YNz@i8di;^*!u1Y?nt_qM?gM@1JF#Byic6d)Y(&+qk3)NBh?$^}cRJqsm*PEHWWR=gys9Ni923B814uOpL zqzoKcFW`C9to7B;ITNA6MiNFqGv*Fw04(rAf3Co(Hg>>gS})||)O^bMM!=BXozt?t zSD{>c%^=ke-YxgYR-AtYsmap{tqdJ^?4m`KE7H)iE6&I&tiq1?Pt|7QJ88fi~1WXco$V=8f=O(4POd6ed368+ZU% z2$$;=18YZs2@U7|_Q(V?+ZpTG*FNJE9-RUIG&E2;ooQW#w8_}C+xkR4fj}EyFlUXg z-iQhBoUQj9oNW%ApRM&cTfcd}E3URPrygjTVSKzSdHFtZK9K(#@auXk@TEx|pHXAb z0YH99w#IoQK0QT7V`p!-rpnv93){{HADf9?#$5p%xDDARJJpaPm2&SvAF9E#BI)Sk zpdw3lH8bTs5U#K64c%Dtr+O!FP;Gb-MdJp{5M6+@m~d zOnwGwAR<)VZW&?1I)d()RESs!s~tr9ub>(x4iTK@G1Gi&Uiy)hkS>cx zCzRhV7FeOC3bS+-H$lylrW4N+C5-w?mY66 z-_c$ug)FYNRN#*W3xu?8eW}eCWkD$rH+sH5(dGO8ttaFKT^17}4J%3XN?;G96(?aKhJ&ve5sy7pns=~)wSQ0MaHzMV( z8P+He>WfXt^^+GJ6Nc_i1Yu6Q6*6)<;P`LOdmV+uZ?%(DE9O489ro+v@D~+l*xsXk ztQ1!+u~ZkENmI(7?q&rtg+a5;nLyXFhn%a1?vQl~G!*elnil*@{kP)isCYL_u?%Qw zqOoYGD(*$jE-2@4L`vXl)giNKfQ%VwylvAeDKd0#$5Fv#seS8p_Rxd$Bdr8Y1j8=K z|2*w@mpLvLe#JIdc8y1jDP<)kkMh3K7R6BCEYyZ6R6Xx0!XuYimR?xkG(SwryE~U$ zE8XohwOzkIW9g`Y>WWN+y%f+jodNcdQ~J9WJtu;a#U#wjZcmCCIc+X-PE(hH&e1S) zeqBFuor<(f{249OrTa(AJL1Fg7sl4YpiAcaGn4b~^WYm---|)%{EWJHBE()<%+U0! zq6)TQq069a3E~P#{x>)PiVsU3-#FpY!!K`!EwHvGmEK|-txZjyyL7e&LX5Pd7%}9 z#TrF=+jV#bA>5Mu@4Xh;paDqn{(w4bD#-eRpCnO{7;uw)ZXU3Jk;Dv1?$hj>_#!PU zmq_s;^X2=|{#<-jpcJs3Zy_%rt4r^WgW(fT1wJF|CH)$0#0O(Z9NvU%XYcEcD^d%^ zM=)Dw#$kg`bR^j2cJWseJ-N{pdzGgALwD}qRb-8EjKOw)iKv0CK3yDyj4mCr3yk=$xFJ6U6c!a;N9_C9?pL_>AM$nw2cXy z0n=;*J=`@pz4Og09oH~fJ{fJ+8|g>;6Qv_8=M^Y(&N@g1HR2c`Xp*YZ}WOAl*E<5FgNoevY9s8^e~%+=E!CRLrVTg zry-qZ4U>8cNXpFliHtdLU8@~l5D7hyn6}6SN=Y_AbO1S4Ri&b%XuDJ2IG#>#mRrs? zpgxZPhneeD4fUVLsYqIMlmIIbn;ejr59O@)k#vb7;b`?7eAo{^JvU^TrPu>HsQus* z7X*C9wu^$zGHw59e=7-pmtQ14Dma8W4H^eMROE^}7!H9l;Bzh&&RG|l&M@v1_?LwO zM*$hFqzXaQ-YuTI?DC6^P&A`T2+bjN1~nv#0&sD4)XA?g`16S%8W57;55_0>T*`+$ z_<1(G++X(!rl~ploE+*R5huyF8wIQ5mj>H?$l$$sz47ZNgEB@|<4)*7!58u;=}pzA ziM@yQ99+NbUag%n^`(~;IOa|dqhNd9A?{CtS&Hqu`&K3?OyGK20zf5=RlNfftMQH-9!>BK4&Bl%aj5M{eP)I8`aE^yrJRpH% ztk5jwBM@zX9`t+K&W8TS6;_gH$u3mMtU!LV&%_S@Jxa>*&*-P@GfCT@iU~zH#av8HMZ|j7cc3Tw0ofM$5hiyLNs{(9CH1heV@>W)T?u@+==wCq(rhv{MKm|wgtRD8KR8h) z)eeMnAePhG7lT_EzmRapo+*~jN1(}Me83-GQEs73nQGM%`qV1lF*@3#!4pGB5|Iq6 zK;BEZi<6JtTIFYp&R0ldDZE(r%x887pn}-JjpFg%^R-Y`UU@F$NC*DP}t77HU<8$l>u@b=?CnP)Sl>mjy6X8S{@1}kF zb>Li`f&gv6^~dWhqOCufoM+K#NIol+jZs;BKiJzP=Kg#8m4pOCf&Fz&+H`6YGLLiV znq6>R3b?KEHA8tn?9b#CooltD+w<)+}iXLm>X3{Lvt0)z8e% z*DFQ5-HPz5D3j+G6}5*0<(9eui~w79vk)oUy=pxGE*}zi`bP};y`X^RSKgfqJTZVp z#jfJoln3|M?a(sNBpVou0Ps5bgLW09`unJbe*!Jz-q0TibvFcq81J5}4i}#1IOi-G|r1+3LsF(3$@DIEa0T9FL4{Bjm z>SK0ooGK4h1zBrv>K<9IT4|%~CjeUX{B+7V*sQ1-mny-&o+00VO-*(ojA$o=&>lBi zJ%x<5@R!v8oiIKuIb^953|Dr*w9`)`*39DFQESCD&Hj7j`!Pk@9_aHO2ac#(GoM>9 z0{L<6(V`{GB7W=DA)Tc7EhZ&CCptESJTKKy{8BXpb2i>+^t`Qah8B5p!t1qo+Mle8 zmJQoAfo8I?cA``~Z1CHQkx%zq!ZHqCfgM~Ar;^*Yo0O6L>!<0COJ^wNs+6oSzN@8U zW=&0vW!Urr?_2&%%fP_=?Y2TLao5wfr)$wbo9ueNm7^|z$`9RcX%;~M-_IoNZPznG zT1bS7OxyZOdhidk zslKPAv%CDgUI9?)gR0&TPywG@bF1I@bY@h%u+o?KCa5mCVQ>7!v;$m_j_y|c7S*Sf z;?LDS{O@Md=H`r9@1HYq z23Q9En6v>m(+SFVtufcvXF}QVKXl@no;d@ws~4*$#lEdOKPvE&{K^+Y@3fOCNu$AZ zwwD6a{PCT{_Ia^h)dqU5JTx$8EeIC)y2xn8*|I_sD)+hY(q12rbz60J+1SkZQ;qZS z+5YM3S$7t4Yy8naCiBSloqInWx}_-y(er0-6RcKit~C(}i5)Y)vz+Ix_4~E-WC^#} znmpVEiZ^J$p^oNpEq_=Pz#;M!_UD05dYQ7J`>Lq-)v!T$Zre1E2?U<_Q3rP3&}zFj zwz}g9#M+&FMm;+TAh~W=4qF!r5em!qvK$8iI?(gF{nQj4CH(lUs8AI*ug%Yak-i#p zL}h3r732lc4Wtqq7bH^!PvC*32=!qIzgABFZ+AezrFe<}qhS5dOZJTu`aPYO^jmmY zXRS5UM&*;e`gkq#_VW&^!Sj1n24<>dKx;oI*CWe2p{vZj2u!jg;+f~Ruf)q-?kalk zS;Tner#2C=>Qww7xVV-9u;xl3@max8d3$#MlFRlTA`csQkl3;IyyEC=r+}6&{$)PN zm!{Q`&y3O;>jy??QwVf zO3N*h2~^%JKC8|?PiIa=1qMsAv-7Zha_j1S!*vXn;26ce+Kcj5OrcQy{Z>=g!M#6k>C?+XEaj}*xl&*uJkT z3TGRozb(4t)G5{oa{zocrH?^+e4VD%&6*^B21_o2jt5^%^|a#@GkcO8?~L@yw$G~L z(Y?mr|9Q_xEW$cIQ1`s(o0lH#0uQRv`sO&1Kd;H#r3kSjiVp$!Ad z%+&wIJz70K6~*f+*R{`lE)Rd@x>T*C zm^;#UK7Rp3jta+lJ3zNrOZgwu*?M=Guq#$oS!zt{Szmg1_Gl^U)S^s*hCe}!Wijot zwY%~YEEdtc>P}rtf5X#|G=6o?9!zzL`MTvJcCoq6(%+8|vZs_w2?3bC5+sXpkTcC2 z8GrDC?;!;5&F8zHXQSVT+adMRqFn7K$8kVF#XD2{lNgqrfh}}eVmRWhe;F3mF!`ec0JW*OI^YUk zVCq5>+w(_3SFC)kX}S^oq$EZ30qdhN_cZUST#=l~<(08SviXogRkldf5*#U7_>I05 zGVrcfq@0>N!#qVZ>-e-t-Wk*X{q@D}r~x$*psVt_r?uDR=HY5m*v&O~-aR)zzRZpy zl`BgrObT&qFfu-GdiUowSn;L)tqVBa4%syOW^YqhXO;Dqt8Em&vC(odm*&n=LVQ@!sBdweSk^2@nfonwMfu_zdA*O zlh$Ya_GDjQneA%1F+A4DH%9;RTY_?3s&vbVZowfOk+1! z2*p}eJpV1~8#N}p@4dn5?e{zAPcy{xcPQZ1LF$J(kB{dAG? zoR25zrAZS~I)AN+%{FexZ}jqohmTogwz2j(28ccail?BO&H78*3`MW3InNuKT+lTC zSTpc$XF+m+FcbdCoV;w4O;l};4Q{kv&BorjDCrb`r=Z!GZ7C~5?H5(@KI84ML2}(# zM(&4=v8)Q+;h51Rx=Pv>;b&1=S8T&>VLV;~xj3D%iUo#qjMKGzip}-I=b7IR!#M$P z{?5E6k`eq;h`}DL7fD_~~fLZ}DnIQ-b{9^!EkHFa@@T9qAZE~o5_O|3};QyV|k!vuHpdv(s$iD=2ct0tzEPH<3V}} zoO7Y2{^bBvCjN<(N2V+_BTAXYNGhz&MvcR;G@T7|IuW~LtqcrZse^6T)@-E6>o2Su zKFI=gJ5`x(w+QqPD?eFmId4WvWzwH@GgXGP67{KX7_a*+ zQEL+icx6K$WNaG}0Bn#1#8d^g8_y6%@RcRZB9>iM@OGe-yV`TK6MfWa?=LS9_1Ui4 zYNoL~bcNDG`yCMLDneO)n}?kiP`%mfJ!{(U)g{m5>YoIadbJ$%wvYmZfS`j9eb?&b zf$xB?G7Ox~2K%8Z5BG)7WA`Cjhye}N5&wj+60+Z185++zH&>(BV--QvZ6)w&$oX9E zk%Ft<*;>rmys+lcOTV3H4?68PdF*Id9|s4WW`h0Ot^R>f)w&Mh)+U9cuO}$y*a@|p z3i;Qwjh%d9miM!46+FAow8K!cWai_+;GyOpp_Fc|0wo93e`pO=N5h<7l0puoGUEw;z5DCBiKHrR9*vlNbVB4!59+ixj7x8S<)!pAW!ZUNRvV z?AkC?JH5n%=rE*DmNGl%PLE7G)<$T6u^hHrZq&YhyNJ078Y=;>s7-WXQ~w^JA^W}3x$vCHE;ygO{V`UK3r`$IJ)JB<9#b$ z(qn3EoT6d`R9r`{QLN0M$vP^I%N!`))?FZfY>Qdv`0$%k zI{?4FN$T|kYpB{H#e@4(#Xb_mj2yfk9?RWF36b6>qiKtPxMHhMl<=cPuuHQ#w5yK8 ziO~!eV1mg%1t^Idg8-cSV-5HWpoSlza(Qp#p1R-Vd!o;-tm8VdYIxVa{Uqv(ijGGO>mMQ;wG6X4AIUARc(k}~03 zwT>SW__1RxOx@J@@|=aXYl{Y$_uy3Lk07uh2OPKb)!AT1JW!%=*HTyK4nq+)-Q{6} zU1{OX8$U#PTZ4+~0=f^)zF*u)BY%$^T|<`4nh<2?Wo!a>Tm@x}sjF3zX>x<}6)+RY zo}}6$y8uJ)Ep`k*-M1SKc#M{5yeBp&d|4;vO|gA1)YjPe0)>_3uS;Lfg*L}YX{c)M z;*rKNwYqL+=2Hf203NC;I5|mg4hF9FELJU?E=2$j-6Da%^IEEyf z!N(bh9aE_MS^n4hLf>WrCjk~Z+B=_i02Q0$ZqEloM|dZIhuiPfI2xjey#I$rF6$XU zfvC!UU+=Y+GQ7UK4OG~23vUx>c(WR5DE`|OtC%j*d#v3p$e}(2ng~ zCh27cL<2t;r*gH=qjSaD51+az{sRSbS#ne0t)_{t`N8vgv0K15%N0wkQX6$?n97tn z6-WoJ82oy#SaV>x;zwQ&hnQ-6-fWP#gaejRQ^UG`S}$+IBi_$Z8%yyOI#=ZKtZMzc z(XtR5WmQb#?|CG3EBkjaGeUvn1yl7NvN~21g%`$XTyK!xEB^r*|(l;!K`T(oCSxcO4=BeAFHc+I8=+UCJ2_i{_1v9X!6@ygv-c}X)7bp)|_ zP5gqPo~ub{jX^j)eoH;tE^C#K$REE+u1c?O&6aO)KXiv#53KN6*Eqa0(rjI6IDj17 z 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

?+l7 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�Kv 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 z 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 VRQY{WNd^D_002ovPDHLkV1gW!zV844 literal 0 HcmV?d00001 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification1x.png new file mode 100644 index 0000000000000000000000000000000000000000..8c483a0a7a92ab5a46e6cfcfa49f8fdf5ddb173b GIT binary patch literal 2227 zcmV;k2u$~hP)Hg1+lHrgWSWcKdPn90sKGrRqvPeo9CG3uKX#J{(IASm?@+di}}l?o-=)F3E6 zwD^Ni=!>T7nL9I?X}YoAW$t|Qo$sD|?zw001?ah|SeB6#0T!CBEf+H4bBB+JJu8re zhoBb*p;u8ID_yBf0ya+zcePvJL&AGs+11_tpRKn>9TgyPA7ZoSs0)aX0r00)%XR^J z`jH<$>RKN5V(7OqK*TS4xZz{h!*f1C3ECFkK$#7nA@pGN!$;%jYv zwjAKwmYb0gKL(K8-kPtb5${A?tlI~wzMrJ6wTdBr=Y%%%EaEMQ&o}4FQ^DA)s*}Z> z!FI&AHCpoWI|RUqx?7s@$8!5^Q=anY%X@i5{QA6kNcMelpE>R6eCYFpmMsVT zrI(b06~u#xf1yS}_UGdMvD``!0~u->P=lA4?YN`hilQ z|3tHka)7T{2CGqwjZfMwx$5irQN_*|e4l)UHmiYuz74Yp1t^#>hrJ3-SOXDcC_o0^ z7T9R1gAN8V6s;5)ieI5-7aQlmJn}lUna#nz!j%5V$X|o`xX!dHWQRV27P1=rj;t2b zW$~+pTw@bIek?ZvKPDL<64`^#UNTAck#RBsB6*5DP4<%UA_FqU$I>2EH_cM;u)Q~SI+rg`Rn{L z_AC5qq~L$#SMj%U$6Cz0vP{G5Y*=%5RT^yu;}-DInZ=349rJPVM6C3K^oO)8y(fJr{l>k`ead~!ea?NsT>_Ci%bnxC;Vy6= zb6>{xYV#Ue-+LB$7`JEXmTRm^AtP)R9u{)KHsMiWGV&)32xCG~*nyU<>-!d;FP=Re z4r3qYr~6#KE>;1F`>_J_P5xC?ROxV(DIHdCO*p$HRQI@7^PwV@Pvuf+ z5K}u-6REM(K@W$srgorh0{i?O)v0c>QtHxU-hBdD(>iYJ4b2sIOVX2K8m~4gmYVA5 zh^QEb$V`rCQ-|7ZS{nuL-t>?3n=-o(6I(7vocj#GzCZEo`!3>+v;dYIfPu#&ZWzzX z2i^rZ^Mu;6+rb@?NPG+6)c5T6zxpzGe*M(x+{AON=PiJ>H#?ob-|uwRK0yDg0B4PV z0id6JRRdfL?*ISMZUrf*k6*ChPpT+|w%)~?&LZ-nb17Y3hFmq)L#-QuEuI;_O zzdYwVMi9SEyY}95Kj(ZtpL5PcPfu@12SNxudH9;=dGLK-UFP3>q#+@7`M-E|lkan2 zys@ zorE0Ap?WEYT45b7G0=ntUDA7d4Dr5w(B4hq`>|1+J^LjBdXArGR(fk|>o5blu7^*C zhH&QS2^2s53C@*y$^wvzu%Z^E89^XI1a%LXdjKQ5g5HyFA|iE6{544lg_2B(W|JOA z`VM1o;60Q+y9jS_6`mpB2fnJBvxh-IMri7xNZdkrw}jw}-*CF?b@cbXjDWM#(Kwj( z`S625gcoiAOC@Ngp(xZnR|)U>9z3FD5G8)ssDP>-z+NpwpIyP3L+`*eO$DiOU?!bb z22?N4K@bIsMM%^_a#nbx4X83o>eOsiv0bSm=uSZI>x46V2dTz3?0c?*l6sIn^;(Jm zH_ z3cR%qB%7KMl6D%2MNLb#`vEp=qC%iSp+X=o{8AMgKl}l?zZJ5j5#BvAB4&`&F0kPs zBu0ibsGTAVqmIUoEZqCu5ogS#E@u@E> z>r`o56Rxe@#&rH~NCxCGTmty!yK^v(zX*NTGtfwIp%#Up&7vb>utu93iTlm6O!%au zo@j*3wBg&!7nGsA7xZK@In2TTEG)p--hjiWjv|eGe5%Z?o1@8a=002ovPDHLkV1i)_ BI!^!q literal 0 HcmV?d00001 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a45b01b91c65e3a8d8feefe5122bef85c77a78fe GIT binary patch literal 4485 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 X5L}ax?^OsQ00000NkvXXu0mjf-pQ8F literal 0 HcmV?d00001 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadProApp2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadProApp2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d2ba8f3a7ee97837b87d619cb0f7c1f3243d7591 GIT binary patch literal 28089 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 Y0}pcCLt@!TD*ylh07*qoM6N<$f{85HlmGw# literal 0 HcmV?d00001 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings1x.png new file mode 100644 index 0000000000000000000000000000000000000000..43d577040eeca37d88ca15030a9994678c44f14a GIT binary patch literal 3192 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 X5L}ax?^OsQ00000NkvXXu0mjf-pQ8F literal 0 HcmV?d00001 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight2x.png new file mode 100644 index 0000000000000000000000000000000000000000..717603dd684e9a71f55243678b954a70b89f0a13 GIT binary patch literal 10768 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

rD-NlRi2>YR3M-xKh z9c4Kh`=aD%&%Ndl%vr+n}RYro+f%j>+#f{sNr+KALrZ~C8bYLjxa@X>BCtfCeq)hRhhs? z-~Ze8kq>^v>i6|nL7#UsKJXM&7f7IQ(oXjL*|Yt8=K*~{qg%%f_dd1Bk3Ou|TxhF~ z2R;?RLiDUj3Ce<@%1B4+NMiZeWYZ-&PXE^PtU-h`2#bZxI%d(;2}@#BvKTk7g^9y+ z+U;{+_?&&}Z$B#>X-AnK$A@;mOJC9E1dwPl($bZjwyd%li%*|(_C-NEjWm9lkd#unpyJ7=zK)B?Fr-tiZ9*AMTJ!78ttRC177RC3a{L)=iQ ziNBvx0*C4bl^qiqLU&7=r|EkGzy7Q5w)gz{do+<;#bVEI`ukM=gjLIj!l=b9RwR4E%ntJ5Nj4jgyMV-8EAae!#FgIqyHd;Ln%J#0GK3n2Lw@H zPOxDKl7?(WCIgPBKjzp3S;`I}e)5!*Pkzh*=?iYABQ3gyyY0?zf6Ko34}WhPHg5Fw z%Pf+kp9L2IAED0;S)Ite8lKa6O&Eb8T<~F|dU&Q1G%5_S2m`Pnd6&2*6C;dSET#$1 zSiZvE^~>+Hx4h*oHhbD>a&4-gdu@LrK_DAM$HY!DEFoMEs5|;&JZ3CH;4UU`=SfKC zeXQz&M3W~MV_BZ5B6*|pQNW2oEqIP|o-hK3X-0@iC1^yb3=IoJrf|Z;l@L0SW+c0>FCp}T zdGqbfx7}vH@C$FV^UlI zm&P;iCWOEgL;*C6DMuuk`Cb4*QYqY>G3OE<-UoGqt2C%@^62f=7dF*@tz5a%ZWFPu zx#k*Mdio-{Je5-YqG|Yq)5JdkAfro#C4_?Lz*xlNy;nhh{LXXfH|dd5so$LXW1Fkt z5MSYz=HI-1tNrwW2kh><@3!Zjd(I9YIqYq1(Q+fS71{|zC+$s$OHpy#c|H*ccqV`F z9r6U1xH&Og(|Dc`0z-_@$52=x7!^QrA#iw~ZrBK+QQILcgdQ1Q^(j3cyO=72?ELf3 zvsJ6Ew5zVVQr7n}ecwsQhu}yxYr{B2R(+|TMTPGhwHs6~1Oy-;#22FY>;T6y<~UQD z)B89wP^SmUf$jw5sNM~mHrk_)K5CCW`k1}2<^|igZ@*7=z|eT1KsfCHxvY9*+|RqD zDCaW&eX@TL9&ieAacAei|!XHzExT4OpkF`aOI1+H0FO*{kc<+nP0NY~9**wr9^CKeYf=$UJQzCddS- zTrf2T6`6zhKwxs8C}5*m!a$|tCQE`v{z&&JBQOYu2q1k#MN0zIScHaE4{6m=t7&t@u~Y|Q<0DTDG|KIji;*;3ty(+W(J|SkPoM4=Gc;4COtJP!?WH|E$)b3s2>W__ z{iO6GI&1mxp+k01*Wts5?TAj;?a?Rg1T{nTY5 zCkz6vLia^E{00JZHF9E}97$meJU|`*_sVO8=!8RL z`X1CI4W!}D7`)SSvfQ-P&6YGY5}eeIsZmLw(lV=rM6w2pIo@P}d3;a$(?lI7e)fP& z+8Pi|dy(W5T|+ezrb%0a=gSP%fKLzBFD~X zK|*L2AB;#ijT;)O(?!3Bkt2nx#uB%#o&GV=BA!9UpM(z+0tG_F_k_@}LmY>-QpxEy zw2zB2xv)7-6>+IPngJ#Pz%u}oSHts!5g4S!SOts>9 z!U!B1L!$#{g|Lad2LvW}2$vuf1cP*xaft`Y#2&x=K-?r|D1)a!^sGFHmz0_H_SA;e zisuO@@TqN9I`>M#ByW>2BsnHjI%WF#c;cqh{=fYE|2cuHqxRn`!K$}7`_2Ca1L!4r T1Z_6R00000NkvXXu0mjfx&MOR literal 0 HcmV?d00001 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp3x.png new file mode 100644 index 0000000000000000000000000000000000000000..78ef8d12b73234c4a0d842db591fddf8646b5efa GIT binary patch literal 30946 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 Va~q+uY%u@;002ovPDHLkV1i*114sY> literal 0 HcmV?d00001 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a45b01b91c65e3a8d8feefe5122bef85c77a78fe GIT binary patch literal 4485 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 X5L}ax?^OsQ00000NkvXXu0mjf-pQ8F literal 0 HcmV?d00001 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification3x.png new file mode 100644 index 0000000000000000000000000000000000000000..46ddf1179de6fe5a5d0ea2907a1b2823ad0d14b5 GIT binary patch literal 7458 zcmV+-9o^!IP)Hg1+lHrgWSWcKdPn90sKGrRqvPeo9CG3uKX#J{(IASm?@+di}}l?o-=)F3E6 zwD^Ni=!>T7nL9I?X}YoAW$t|Qo$sD|?zw001?ah|SeB6#0T!CBEf+H4bBB+JJu8re zhoBb*p;u8ID_yBf0ya+zcePvJL&AGs+11_tpRKn>9TgyPA7ZoSs0)aX0r00)%XR^J z`jH<$>RKN5V(7OqK*TS4xZz{h!*f1C3ECFkK$#7nA@pGN!$;%jYv zwjAKwmYb0gKL(K8-kPtb5${A?tlI~wzMrJ6wTdBr=Y%%%EaEMQ&o}4FQ^DA)s*}Z> z!FI&AHCpoWI|RUqx?7s@$8!5^Q=anY%X@i5{QA6kNcMelpE>R6eCYFpmMsVT zrI(b06~u#xf1yS}_UGdMvD``!0~u->P=lA4?YN`hilQ z|3tHka)7T{2CGqwjZfMwx$5irQN_*|e4l)UHmiYuz74Yp1t^#>hrJ3-SOXDcC_o0^ z7T9R1gAN8V6s;5)ieI5-7aQlmJn}lUna#nz!j%5V$X|o`xX!dHWQRV27P1=rj;t2b zW$~+pTw@bIek?ZvKPDL<64`^#UNTAck#RBsB6*5DP4<%UA_FqU$I>2EH_cM;u)Q~SI+rg`Rn{L z_AC5qq~L$#SMj%U$6Cz0vP{G5Y*=%5RT^yu;}-DInZ=349rJPVM6C3K^oO)8y(fJr{l>k`ead~!ea?NsT>_Ci%bnxC;Vy6= zb6>{xYV#Ue-+LB$7`JEXmTRm^AtP)R9u{)KHsMiWGV&)32xCG~*nyU<>-!d;FP=Re z4r3qYr~6#KE>;1F`>_J_P5xC?ROxV(DIHdCO*p$HRQI@7^PwV@Pvuf+ z5K}u-6REM(K@W$srgorh0{i?O)v0c>QtHxU-hBdD(>iYJ4b2sIOVX2K8m~4gmYVA5 zh^QEb$V`rCQ-|7ZS{nuL-t>?3n=-o(6I(7vocj#GzCZEo`!3>+v;dYIfPu#&ZWzzX z2i^rZ^Mu;6+rb@?NPG+6)c5T6zxpzGe*M(x+{AON=PiJ>H#?ob-|uwRK0yDg0B4PV z0id6JRRdfL?*IT8#7RU!RA>d|TWOG7)ph<}uhZSLX-2b3LJOl25?ZW?@O=bGcmUnTYrI)pb6fFM;wiRL|5`bE;1? z8bvS|ERA)cAL^^aHqor(V$GnkoxRDy$-_p{BIIJtPHNAZG?U37Ph!FZQBzZc=H@0e zH#MVfdL62&st_wHGsBJ~lj!U3Lq|skk4|)Ubz*RE5E(K*MBrk=WHe|#Jrm7hlCGx= zcr2)kgB<(5cO}WC(`m%xaV%Q65bM^i#i~`SFn?YPY6&_J4Fi)6%~e!LXVKf&hr>sY zVEfJ;*s^6S+77j0baWJvNMuT2CZcQnJ;xd?amq?b9Q!z`m87Hu>Xut>!KZG&14|b# zK{y@-@|-S9wR3q0Y=D2HHAZuYQszQ7qfq?qP$k1WsMWb-8oT%H#V=m@CEj@RP4xEm zA`&HVy~8G2Exo#)s!EpttCK6jNZDj+q<8#H60ImN$6a^ciO>AueV9FOZV@Ecv;c-l zxj?4L%)wE(gDDh7GH@wPGe;zZKq3OCGKN4U)jY}-Ch%EuO3VoJnnRpAegZ%Jub<(i zmtV%v(2!Z{qC;AxLt{;q<}rXZ$W)p*DCmvk$Co%7CqPmBlTiHGTBqM{xiB4;TYSE8_vBbPD@Aka_a} zG9R8owr9wbRFG0GTF`9Xv*?rw`v#37NULe(;PP;&5rJt5gqO`k^rkBiUNXbe5&@5d zY4Nl8$@9Jw-FkV42&)LG-nCh4purdSIeY-(!yJ9BrEKk8&vxb^ZDJoEH- zv2^(|f+ZNPIjzm1f7=B2`JD)Mj&SqBHF@vvqHYtS^O*0#>p2u}&HBs-sA zpMLU5%x!7mgajK4BfGa91K;>HM&CP%0<|_8D>EvZCU>Qkr&cc~B4Ng;~0X?mLI@YdUgZH;>Lw8S436!13N>ya& zx5m9F;2c%3zOD}6d+O=)V9UZ7ed_=QzxBE?P7bZD2ox73ozYBs3|Mj8s;CJ7m`(Rio!()h~6eU&u z_EwJg>a}cfEsKD7EJg{J83J^jk?IqbVO9~aB{rQCLx4EnH*?6v!1K56NjucnFpKvKCLZtxh|2vGgAH>>pvi>7kG7+* z@i5Rah{B0(Tos#($Nu;s%D^*}8cRT}WWCWY060yxTzBo;8-*a?K{6eTTEr zRBB>>^G%@11Y8o#Q|fB^Ey=10pbj;2ulSz8+a@gu(-29+WZcFy1DcHa@pjK0)|JCO z+= zG%}3gRMG=mbZ2^3Oh}HV&^yqNzQJ?m&~M$-GbI|Ov)<IfUCYez=OEWy*q5ONi;|7#9y<&4guvwjPxQlm|2Uj^H7E>>U_qz> zci(o0No4H2{`dL;wJruCH>7fIP?It#domnppqH5nDZ6}5fkqtoMp z7lor_wJ};|OoptAspDF6n~%b|sTBoAd^6FAo3FhdFTA|IWH&4gh8hv4i4}q+VsYGc z`<>pPlJ4$y#@xs;@LgO<9?{zYFd#U7WJ6vxE55nwv^lm4A#9U~!5wVNvT9ShkFzV}>e8jn2N+ zX5w0ZC;MCB-1zlqul0_8OARm7q_zrFbV#CtD4>$Cf{#*Tv=yw1A@RU!M6Yi}*&Rz! ze%n%n6ym8V&fddFtezHoIEBU2W})@+`DPsN1@G?|eJgNnC{znGKh?~IPNsOf&rE2Q z)m?=7U5OpoN=VllQ@|%{lB{j=w|ZCh#9D3p%$^myXOA)6JadkzW}fRiYr<9ruE^{? z1D6KY4N=ucT&!Jw6$25^FWdfO)^Lc{_o|hvNF^UrP4fFY=#EmJud_YuSs-XALVP#J ziCr?tq1BX@jBhy_L*^^qGSPc-DI`o1R7$9WNRbZ|kSzM`2(>4~K{Jfz#C(OUim5e- zt2x*|mq{U+8ikXmO7mag><}tC&LP4m40NNbS{5TD&GoesU~#&-sv4~=^9>Miz2q2Z zh^Qzh*LpO;0w;5+?tyY9?X3+6)K?%x^~;>@L$-}6A`^>}pC)}u^McLQh%9JEfGVl# zNB-;pa;N%`ryB{>BoLZiYusI-Z^TG1z<$B1ID&Jg6BijVkVN)ym(;~$nqUjNyhyRh zpfMUpj;=GZ>@wiYAX;WMn~KcH@JPupmH^AlH`Ow z5mNbONfY9qUyC3ez8E7BBnT|q)`g+x-a+PIhXEj}%I{r;_}weK5{{KVC7Pun?0;ed z%GS+C`NP)|41t|wQ1X=*5lZC|V&x;E0ziKfPDK>wp85@3%`GW&N&{7z;cH4MrRwfg za}9H9LJ2h2HDXWiK2u!OtEDxZXXoa|CIp${X~4oj3OQCR%2-mhYc(K_w$!2GFK$I( zHlrKEW&!phwD6)vRR8sD2+gd4OG%flo`>>3x&}_10fdNC|Dtb~-&Ac&a|wj^oJ&OU zuVD;Tl=By;3GN6(McorvgOq)EDeduYXb{R+YEK4RK8V`uuFBR ztEF`1YF%=QYaqlhvW(e{2GEcuK)7oeInMZ&+;)4D82?r1k0ri^M? zRwy+A9~$H2u>3l@>jYx-my)2

#ey>)?|3_`yyL|7a`H`_C`|$RPW{X#!{8F#Ruy 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 literal 0 HcmV?d00001 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1ebec1390b7d9dd55bda6e79f655d2ddbf5114dd GIT binary patch literal 7156 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 literal 0 HcmV?d00001 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight2x.png new file mode 100644 index 0000000000000000000000000000000000000000..717603dd684e9a71f55243678b954a70b89f0a13 GIT binary patch literal 10768 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

rD-NlRi2>YR3M-xKh z9c4Kh`=aD%&%Ndl%vr+n}RYro+f%j>+#f{sNr+KALrZ~C8bYLjxa@X>BCtfCeq)hRhhs? z-~Ze8kq>^v>i6|nL7#UsKJXM&7f7IQ(oXjL*|Yt8=K*~{qg%%f_dd1Bk3Ou|TxhF~ z2R;?RLiDUj3Ce<@%1B4+NMiZeWYZ-&PXE^PtU-h`2#bZxI%d(;2}@#BvKTk7g^9y+ z+U;{+_?&&}Z$B#>X-AnK$A@;mOJC9E1dwPl($bZjwyd%li%*|(_C-NEjWm9lkd#unpyJ7=zK)B?Fr-tiZ9*AMTJ!78ttRC177RC3a{L)=iQ ziNBvx0*C4bl^qiqLU&7=r|EkGzy7Q5w)gz{do+<;#bVEI`ukM=gjLIj!l=b9RwR4E%ntJ5Nj4jgyMV-8EAae!#FgIqyHd;Ln%J#0GK3n2Lw@H zPOxDKl7?(WCIgPBKjzp3S;`I}e)5!*Pkzh*=?iYABQ3gyyY0?zf6Ko34}WhPHg5Fw z%Pf+kp9L2IAED0;S)Ite8lKa6O&Eb8T<~F|dU&Q1G%5_S2m`Pnd6&2*6C;dSET#$1 zSiZvE^~>+Hx4h*oHhbD>a&4-gdu@LrK_DAM$HY!DEFoMEs5|;&JZ3CH;4UU`=SfKC zeXQz&M3W~MV_BZ5B6*|pQNW2oEqIP|o-hK3X-0@iC1^yb3=IoJrf|Z;l@L0SW+c0>FCp}T zdGqbfx7}vH@C$FV^UlI zm&P;iCWOEgL;*C6DMuuk`Cb4*QYqY>G3OE<-UoGqt2C%@^62f=7dF*@tz5a%ZWFPu zx#k*Mdio-{Je5-YqG|Yq)5JdkAfro#C4_?Lz*xlNy;nhh{LXXfH|dd5so$LXW1Fkt z5MSYz=HI-1tNrwW2kh><@3!Zjd(I9YIqYq1(Q+fS71{|zC+$s$OHpy#c|H*ccqV`F z9r6U1xH&Og(|Dc`0z-_@$52=x7!^QrA#iw~ZrBK+QQILcgdQ1Q^(j3cyO=72?ELf3 zvsJ6Ew5zVVQr7n}ecwsQhu}yxYr{B2R(+|TMTPGhwHs6~1Oy-;#22FY>;T6y<~UQD z)B89wP^SmUf$jw5sNM~mHrk_)K5CCW`k1}2<^|igZ@*7=z|eT1KsfCHxvY9*+|RqD zDCaW&eX@TL9&ieAacAei|!XHzExT4OpkF`aOI1+H0FO*{kc<+nP0NY~9**wr9^CKeYf=$UJQzCddS- zTrf2T6`6zhKwxs8C}5*m!a$|tCQE`v{z&&JBQOYu2q1k#MN0zIScHaE4{6m=t7&t@u~Y|Q<0DTDG|KIji;*;3ty(+W(J|SkPoM4=Gc;4COtJP!?WH|E$)b3s2>W__ z{iO6GI&1mxp+k01*Wts5?TAj;?a?Rg1T{nTY5 zCkz6vLia^E{00JZHF9E}97$meJU|`*_sVO8=!8RL z`X1CI4W!}D7`)SSvfQ-P&6YGY5}eeIsZmLw(lV=rM6w2pIo@P}d3;a$(?lI7e)fP& z+8Pi|dy(W5T|+ezrb%0a=gSP%fKLzBFD~X zK|*L2AB;#ijT;)O(?!3Bkt2nx#uB%#o&GV=BA!9UpM(z+0tG_F_k_@}LmY>-QpxEy zw2zB2xv)7-6>+IPngJ#Pz%u}oSHts!5g4S!SOts>9 z!U!B1L!$#{g|Lad2LvW}2$vuf1cP*xaft`Y#2&x=K-?r|D1)a!^sGFHmz0_H_SA;e zisuO@@TqN9I`>M#ByW>2BsnHjI%WF#c;cqh{=fYE|2cuHqxRn`!K$}7`_2Ca1L!4r T1Z_6R00000NkvXXu0mjfx&MOR literal 0 HcmV?d00001 diff --git a/osu.iOS/iTunesArtwork b/osu.iOS/iTunesArtwork index ef7441433ad414ffc56fd513e5956d279aef8551..1939459992eba68e1067c5af904fa25624cef86d 100644 GIT binary patch literal 142214 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 Z{y%t>pLdzx&T#+$002ovPDHLkV1j&!dny0` literal 99849 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�vg)9FoZZi~G>J|56a#Nu`6$e1IG|S%b(^!Thc3o|pCt0POu* z3{guoFO<7EejWk2p`7W7l#IMMU0<#Ii-?Kb#H;N$ZGNiP=vnf2)JVP~lh!|0`XrgB z{(ktAH7P0xWHAi%wqwE^Wc>+29RY?f;_^J$3^${~k(h=%^8l7eHZSL-OeFR;%n`je+3PXB%Q7g=p1J5?-v{ME=>e$;60@&ypWVh zer1RSA<*!#)K%;#Zv{Yo^dq@k)8ZPT1wW;I?IV!%i+Bz$q#DzqDfoM zuPP)D)W~n==P|AXZ!$a#8t7osP1yozw?R;NNPS^FyU*S%W9f)yw+zS$*ms%eGZyHS zchX$3X<*zjTSgou4V418e;^vfKx*ly)kljulnN>J@$y_b9P78cK zZJ(_FlIIZ(gk?d_oW3E7*{yAi%_)J6LT(FM%;laTd}?Bq%<}prnipHoU4X_LA6qL6 z2QjDPS`yNZK6{9qE2B^IR-q36Pw$~xzAW$wTySqbrs;N|2n+)P z;H-nWWD>#biGD0$jVEJbKk=)t-poF9M^gw?8Z@-1Gw~JM8`!<|6dX(li{b`0!sqe* zi>QqLbm`Qf;CFhbB{{O;X2T7YO`BLxKdsOaU==c|yJI59^#wpn-rpLo1NliYTcN6o zi%so~3xc=?#!zPvHX29HR|)p@u2{JfcVWFS zTOM>{B{szYouFBT$QfIutCPG5e_&MAl>y&N4KYS86nGCg-^|Ig2+10nwZUJDAD|9DWvMO~8ow@B1fHS1rB zb@ZOs>fYXa?3+<^I4F+0x4z)D60<{}4rZO~n)qEpRG34r0x9XE2FEARE^q7@6|3 z&@tBYg~AQK{8z$*BG*ySJOmh|X6=DTMft&{6w-8A_TTEhHFk`=dZ}dU!hf@y_KBHH z+VGCkSmJ{7hk{LQHWt)eLos{2YL-otkv)FMdxAyxy?Ws1q2M=68W|X{n}@*kzbW<1 z3OfyLuQZ~9TKAZ~O21fRjXibe5M>^Jb4n4@NX6o~X#Cl!k8X%oBbGQ&*FhVVnX4fP zFs>7Cb{MPSJUY6bO8PHeIm~z`gm*KH7gD=;NZYOOpu%bAE@85lIDn-={kGKXZ(P>I zhK3z{C0ALCx9O;M2rvkK zkIlqopa(Dpy@X%-$~pQjKTBpWvez&>ptb%*?HQz<`)qufsPkDe?Z*A;$;U^2QPGI2 zvhqaM?$U-xckyyNRViT4ATGTz$@bpuIk74!Bf=PuH-qA!#2uZRagD#DG6jR5=l^3j z4YLS_l_sYX%GC(A;TNsjoWItr$HJ*A z^+QT`gw<9_%|5xBKU1G)%;0bVz6(UP14Zl~&*i@vZ?beT)x*{oaeMdB=g64zH|(1( zVPt{xpt-WGeo8P5thN_f&~y?&{{dzsA6G2AMox=b`1U$w4L1iLV-g)F`srkWDTX{0 zKVXz3C?%8TP{7x6?R4~Xh2%t-uu#iZqDTg#b|3^+SFyLGo!8*_?x|m4LhDz}^gguc z(97aR)Gog%tB{L-%gFD}D*C(p`4TngCp-9>8SAexSLH z6+-dJ`)1;ZXiSRYnKnZ=sj=HcM~9@!chwz6Wz^E>Ht2vTMZ%PRCxFJsY>~F^(Q@QW z1OJaneYb1FC;Lh(K$_cje=rTqT9{vlwqqjz1HOWyBFRsUKQGt(Et)8ts8Gc~kh!cP zv>EKDmppGa`=`c|%-^t9NrOQ5-BM2MT1!)rW;hv$4-yi8L=ogBSVTSZhu`U2L0c69 zGN7;iC*$)cU1oD7)lg>|@uj7(Osw^nNUf~%!LQ`p|IfdFR ziXlDFDC$_IlUANMS+lV|^mGx&-LJ;F<85w{Qi|ielXV_f2up==&v1f#qn;H{8n&q$ zP5ssrJs7be*VuC(YP^;NH-M&Q@Wb=Ph8DTpDFRzN5svF2B6!D78)9L4BFWltm=Gg- z!yu$dl+!apq z&B|5&qK^MrsSO$`5P4dX<*|66^L?=fnYi5UDQ?SJq#nK~^|=nMu2E857kC$$@|gD& zPVdisn^(SQ@Cm1trhMe8Kv45->Bb80bi3K)|&5((gnX`$G%x?a|&3k>G$xjhvo&XUzNK)%?6}ii!=&5PV|R^yEg+i9*BOnYUd)R=xw+$Kp;f(ByX*j zB#1dUdN5g$WO%d+iGDy*Bnf#vdm(=FJK?WhTWEC@Jh+;j^`|YVvNk0qs6$`q{pJS= zE(X#$8&I(-0v5*&K1zyY_>6)ei~i$kc(YW=nmap7^vzYa!Meu(NrB$qJ^Fm%#>b}V z(1|7C;C!l4lhEqR<25wdiar!xG<_t&Of*sGIejH6z1@8?`-BP#_)YlRW2FY8Q8TN& z)fy2dQ~&9F6PJR2x*m*4le$?~m4W)k08XHArbdXT9UC_+dKtUbR8q1Vh|Pg$Jd!{_ zU*CuYEsUEi^FBtK8U!V3GP6efae9BPO#@2O7UuU;@l6RpV({HS|5A_q?)ac)tqIDzgL34 zr30mF=A-392V<_oq?ups^3!0n@SO}t0q%wu>E9wm2kH>gM12e|yj^xXW_?Rv4IS_| zXW;abG4Dj0xNWfiSk}}65~5x97~83qFpCqhBuQ5K(*REZL?;y>lt`v+OtgmF0%lX$Vl`(>*&6ox~2y*LOAW zmfV6mt@^;+uU5Fd9$dlPGlADznJa5{DAcN3JYyZh7WR_ypabSD6Pv446B zAY(+)9m!VC2XBdGA1V%86ui&2wdgmk--)sbcyGOptK-857GG=*K~w00_smCHP``tO z`n=!xx$(kVikkgU*za@|9qAGb!Xmnj7S&P-^XjcZQv|y=&!Kt47MCLa{VJuiQ zh3Xcu$H8TE%rYSL);5F1f&$EaGovKFS@phaDGfFd?41!i7KEs07W1))xO(s-BtCC~ z(Nn)s$Mv2d4rS2DlYbVI&L;e#<0Cb7%T1cLTJM{@;Jv2vFE-Xo9!Z5EMPGvr>@i1N0YS-&>%7p zC9G1Kl>~91b1RpSO-Pf>SZOy@f#|$X^>ji;T*MhqF1et}f2ECgmJP@+s?O1Q~ z{_lV>sDd=iy5Ip&jnv0>28>%l2)o{D1;%|W^^baGdw@u5V8?M!6Z~F1$R+f-WR0Ft z&1Uy2yIDz}Yigpy3AskV?$K&0EId+)N|4|oK}AVyuChQY>EOSGgBqt)$(l#0Ez*8r zH`$WDnOp_QU*Bxl3~nnU#J0DsF_xpI9C45UHN?9C%NWiq$AdmER@kXP96Bv!mG)Pf z+CpD*35lNv#Wf|_1vU9r`ZL+6qf~V=e_HCY{UvA6Ac&^NB~KZj&_L}$V2+6geK>)X z{@d1VjHN~ff>g9X8s5yhId*&#=VWF+^hXj!6b2xSQ!Z zx&ODjRv;-Uvl)*m@l_BU+C)#M0?N4hyr#y}A5YPjabL#WRnLRd1+dFYjmNV@t2ii< z9*1pv%>^;LBk_Y{T43aM77iwf{GEDMJ=4`-bm6O=*L!$kw$JsjFq1TcaujxQmRnC# z@aImbVnLAi-`A~ddV3BEI0VV~3MW(=0;Nzgi7+}czT&+BUA^`NA$|)!r+Gfoojw`U zP;c`)2nGrjIM$ZNqWON41AN?WCe^hjQ*!)IQQ|*skZPxDH&?>&qZTiSLjW{Uv(`@* zlP0)~F$^9EV=$x(FBLEvzYqAXDUew(%QoA*85Kz?vvNRTgeF6bsN9VfYt-6}xGMKb zkcOg2et%nG)Y{_V{=RH)gGiPj!KHECS?kl-C1qa?FhR?q&$)^7*Os6<|98M8#_?pa zRTiMhr&Rjz^H^WBFwom)yKNZcEm`dLijrE5nhChZd6t9fw!dM2F3Sd?+z8^Gp(+{WrB{?)7sQJp_FQ!{T%mP_ zFv*@>@Lt{KhXU`g{T#063ziq;R4GLRPpC?zTlXKZ?s3ZkX5}HT!?0w5$`#?9hAoX_fwUT7PbbZ@Zt{c3#E)>I;g(cp|s3NeIJYaxsWj z^TS19!hsV(0OI`{7qWRV|IfB-IVM(AbGjUfD%T2;twXBOaxUWm!tTfB!k<8alG@Tt zzu%2Q?Y!uK59;)nD+QUvf0ppevAhN#K4h6e96;RtRcNugxH3juQ00>!6SQN|Qx(wF z*`EE!Py%-40cZ(17X;Kyh4Fhuj&dxi=rs?9kmOxh;}UPY67J2tSk~NO;(!`{;vGtzIaX8tCwr~m|vwM$TWS$eyOAKxP$W)7twOe{9XDa1pu5mNxa_Q66tOE4?0pWIt}&B5j?C7X`2G zJpNcwkZ(V}dD(m{uySBC+4wa%vEeWUu1S+Gt(3)slAGwv(;OW)C>9A|ow??g7qU0; zTIf&zypj10l4rk2unBo&x zw$EOzc(}?WzH2r)TnV?p1ookw_~J8Q-hsq`b=~lbPfoy`#=Ix4ItIAKaBnolyV?&V zxE&;hZ(b~LNL#ReH+V|7GyCXdc&{g!i9J>29dLxL*z@7GiM&>olI$Te#b(uoKyWhZ zkABnP^e_cV+;6hPLixFRQl)G3f-}mGeRF;l*fessZ%yU?Loo!%xJQo=VVY3v9zKLhCK`ndLwXLPpQ;#o9Y(sUA|}f zxwfJFhxHCM(9^rUruw)3jT-WdMQ7@URRe!FP}lylH->PxrrFwH8rxwz@2ACK^EUVB`wIv9|*4)hk@IR;tM9GUt9^lW1=hyUk z3dgX=3+@WxT%!vRMC%fP-5brS43oXjOJ|7X;4l=81NuXBJ*;VkD;t$3M}8SV>jlk5X7P7Fe26^;>7z)K7RHu471{p+_^3S+2SVHPSqIU?^zG z{bKBBCdA2ziwO+U8}hE{OAMt52zVhPj~Tw4l^Fq@EiG(Zp0_1U1Prw2Rgfjrml_$p`?5E ze#?~Uph%>OaRdk~TUhk9)13lc!mst`Mz`i#26^csRHjr(wP8$9HFk!5STM9a4eXuB*GYYj z4i5$*^MNhGpe8>WVn!>;bRtH6EWG(iRp`M#rVa!uVmM_oB(m&>9{E0^G07fx8;n*M zC+_>)kN_4n!h2NS_(Ss+grr#JO{HkXO$DhwHrgH;d&1T|?3FiMg+zl?Ph^7!Q+93;iM41z*fwo0v986t?b@T-S4B=8Zm(ImxW z4pDdwzQ1#;w`DLo`V+>|;sUMow}L$bgbi^xBvfXOUdn?Yg(I_7tL8oH295OExMNks z-gLW}b@{s$q^@f_BoUf#myx*O$K@&0+9}*(#%5KIyNryQF510Rwcjz zzI4v|*}9ibhluCQdY|crv2zPYuy$DWR2fJy>WjYNyJ2H<8r%Ax z-}Sz8%@>$+=A6CPUeCJk?oxWpMA`u^MoskS19WoV-`|`}oF>VECYn_@oCQw-UW)QQ|W9$-L3T@EVw9n7+$!otjyz`u*}( zbqLj8$zP89ut2|7jLB4{<~KGcg-S>Pn%LE2Lh(!=-)TQieggONNj+4K5n-5G#l>Hu z#Y=)!GkU0&qH!zZUZR&$yL!d+hmnR5g<3G)U}$?sK^x4Y1%*4`NRL-(;3 z3OZbK@OKi;rbMqDuA)j6j%8Z7QXx(u&_LaQrbFe9qB}B_S^g-FL2kXd?b=pFt|znWDEIR2JlZ<~YTx$Bq|F*ufg+H{F;jW={*dO0if!_7;~8yxd5SSv za2liI;cu3Jdo8j7A|+NkQE-va_*caOnIO*)iS3ULnazBuu&BszSKUq z@dKyRCVm9;v?5}-J5Uu)i!qfji^1C+q#pO%j#+K;1mfxeee7X7pryakSS+Y@M;tMX zIMXEDWYFG3A5bzkn2#Ee5}Desgp43MJ;>zn%EhufkIY$mi3Cf=w3p@9mlxel*5aKX z`fZ;(mPHJV0#U5yFTRgtG!!>66AaB6lx5A^#fM;?bG7T`=Lrq-EgP!?QhdK_g#X0F3o|Tiyo_iz3mK`;jD!$ z;xggTBCxP!j1s!t%#%}|oZtj^G3QToeDJ_Y-M-?U6>1FY)LKr$QPX`Mk#P`Iz^@kl z!7!jv_`RG+kKa4c3eJ?%W?2%^Y;{5T&?k;>rVq9ak-sg2ne%Zzgj-jcl2Jz2n>zv7 z(BV_>f)5aW=Bws&*<#eKlKoi`?4VcT1Yz9#yF?!3_X|vaA^NwY{!iMTg)uK?g(uPAB z_dG9ut6(?;GR}@`9Nkkfv zBJfIbR>srC{GD6*5<92ptQ-{>mZXFo>`5Tb^yp>Mady9kv?h<46D zZwHCg(6y&}i5m9AJ+244ydEJF6PRpT~PUF!Y-Jj`iub<$1BbriJ#6T-J z{d^Ops&fvcJ@P=|sI+Ju5?pQ{BKZxwFxOFcs#lknrOk~a>}WRqWF^sWSJz1_f%f8S zD@%#csODo!D83N&Upp`3j^2O>ztHjkPzFLo&Th&)2I1h{7!*;NJ{CMEKizp*wbbO3 zkNH)u_DptLi|U;C&T2HV0H=IgYeHoVBety&$dy3>}1F(uNQ2)b;`FPxw~r^+T&jvKS=H z>~$NhCfHtgjq90ermTNceejA=>((spQzZYG*52cvi66GGo4p`WoVt5k0mgGT#>Wg#Nsg zWR<^mdEQNGRaVX^I11j=9l+cPBaw8{1iXiq8^xc{R|a5~%CXGysSmFP@Ia7Y8ELMN zMrOl^?;zoV*o-o=oHf6*5mWDHsPWsZdjZmc+jRaU&+cw_)00}l?>0kXrSf5tM~qB( zV}(CmvV3M%R_eM*1tW&8qP?#0g{Mw}dYBujbVOCQk35ZI{Oxl?4W9Q+3f^AKE!ORG zC^9;yP(B+X;eQ8MoE{H0-H+45UEFPE#dGO#S;FWvza}u+2+?TdsYuDUm*U&Chyuv< zNNoXQH&?L56Z1Ndm1&IfaA*0?-RevL0?p*2cG?U$TOo{G%KdR!7Ogn@!u%-_1Tt@u zq=G`+zA4Vdv3Z>RbN{y7eb#xa;H#MVWV|2$)#&7*%TK^ZV``NVYBcM*V94uKN}3xdQ#>K@%EUAuoZs(B0i$j=%X`4P{#-FbD=rh}q#O ztR0~~(_^2Rw08H()ceh(nt)9bPbT9q9KOJb@1t464EIOm#fZ=D&ZY1Ju5dm74)~0z zOjeV&Y+#2T^SI6IY%~LqI+D5iB3F6FXDf zeN+F;|1#L`Vu?6==x7uDCE>SX=+TA+Ye*Fhly<;aQ{@Y*$7o8@Dh$&?rPiVltcf@i z43Ht;F#_DSx?LT&3h*G3?o*I)f8Ar_4GbHufYNoG#t2NBp&9fvS|3!b{mTRZW^?%m zfIy$$qCFo+3|8g!M#=v2;*&u8Z(Yq{zy7&B3$&1SMx-{Fpv6FJrgXj2wb{7KH@FUf1AN>j_?- zYDL|{EPZk2`sc^?GO>2vAHWjJWSnDO{jH?}9-*3C)5-}ZgL6=z!0AEL=lin`$nW>M z<93(Uz9Yhaa@3UMnLYM|%att7mAR{=xzIiKC${JEcJE+;>csB>AYUapzClfejr#D+j%>$M7ywCHV}*0upKoBVJ4u~NxR#&LNXq?IcJ3bGGm|9f3#6B zlXm4e=^0;52ID=|6U7SXC}E=%KD%3i>y)o?p+JSxU)(I#uew}*YVPE!j7x`}_{{w? z;F){%VgP{4CxTUNO>H^p7#M>TYRZsG__r4tNS%^v4@Ew&)c(N-=$;KN;#LUE`^yBj z55-VlmR}cuyPHLzTU2VIrPE+B`9o&9Ua43}_fKNn-;%jK@Z02qIM3U|E&$ud65YNT z&td&?T?donlqgPOhJMOvy6UWQ#|Srb&8<%_DEyBJsr$q!JiW4ZHyQ z3mE^lejQ_M_TE*+$YV!g`s(r9PoNWTHi}xrs4XEZZ_VVgK2ox@fzovCk08B<+$EBv6K*klll=#>9BqHw z#a!Dd)Kvo?4lsvT$KA=%km3HXAIE^(6G-O+m;u#<$ao=>a93@ccaLh3;WQjVtuWU~ zOybvbj!6EtdXtYY`PncQ<4^ zGs8^+H?`ILZ_DoycSyHLH-#M}6huW+E*_4>*$G#F?i&evJ& zLxKhoMjC*Oo*Jtkd9vz1n_sjC3ek`|tE zb+Iah8{jR!sTK`(Je@@R?@LevH1358z}Oi?rg^?yCfG@k)TT9xY7hnDim z@1!aBvR!ZLSBN1AtIxrVSCblCSCN~dtH@&s!?L@0E+8^AU)uy7#Oags)wg-Akcl5Q z9T^ed39?N{z`#6&`?F2Q(X@#VO`f`D7!qlY;CC^e*(*yI$f8d?*DGxAP3@I8w4j7e z`}V&gK1FnB^(KE|Kn$~f7S~nAL|`(XXL&deh5G$Cje;cXn|Xf{CK(Ib$t95Uy7H#%lnQfyCk)tP`(UlKm?ENt_sVp4BKn{ z5g5`hF7O&zJM8=)N-mezOsh{)Bml5A7h=G|D$4VJ1s&HZbsSF)Bq-_Y{aNya4?zm1 zG;$$Yx;*7U-t5#snBn0hfztW4thg-n10(M*lu6UfE2MX0%UWVVyKlh0;$`90P_r7L z7yk-Ko4=0AdC$%uum_qM0fkA>_SP0C8DyRa1tP(4A?(xs`aFj|4nd2xTF!T83)?B9 zgeU#oW5z2ivZtC+52xOQDQ&Nzxc~77ND@PGWO`r>byArP+y@_FMJh!f38*@cRx~m7kcnsUsx>9p9X=KxMX&OwY-ZrJyD&#ReWpX5Z>#&r(&iq<2a?#Le;mlEKP{5b*75f{6=<`@7~3U#g5agzo?X60b8CIP$He zCiB4XK&hlUv^>1B5clj=Vtk#p?$RO2KU|y>^3vU;|&NQO#Di~m|b39 zBTF@(%@$*oiUrnS|MEv_gOHMdn!>AsecE=DnI3>eaIjqchSqv+kjVZ8m95pJ@}CDJ zd{;Ym%oywk4~zAyt=k0HoBlcF4$v1erG^HEQ`hb+L7Cy9|~C`>^p*6H)2Z}JCi`qt=O&dXqL+X~>O6G_S~tMVO96~53L z4Izr`b=V6Z39FSVC9|KO(0jPg1Y9}@wBF|my!&``zw>CR^TE9OIl`EkXbS)@GkF@f z@KzAeB9qPkJ3CpYSCO*m4c2r5GF+ev?bf{NYMZCI-lA1F@bD!ts+}821nNl4&kUAo zt!qpQ57Az<)1h=j^iZNNFU`XFPlz0nL!H~e1H>Zj6A7s(3)ciS`8xRyvnICNv)bzfe)BLeBGag?*-I#V&+~x?12v?n!ggASiay0(L^c&IKIM!~V7{e0G*-Ly$lbeC=w)xVu<-h7qx3 z*I{)Jx?C8LSN_*EKV81KBboa1=Dkd@kl^c7j-OkZ^=ND=$qHYD{Mx|$|LsnBTMA8T zHboCLqQ1~;P|k``nIV{oU0pR8^#)hl>vj>*FI)b|MwC16ZO``n$Jo_zD#a15{kOh^ z@zj;tteB9oMq6zqYnO)W9P5G$2J$cG)rrln~O?zzZ;| zj-^(UWo>-2%PTTBJFl})Uaq5v*NnmxMwyvPeOf9IeK8J?C-Gj&)zpup=7gP;hG28h zW)%Qkg`8&UpchZK-81X^xiJQvUv#%7nW<#AqwvvFef~C`gL|kDi0XG~SJn(%Gf~^| z=!)nLyy9X-aD#9xpqXNev|8b^pKB0}J<4>8E@I4pg?>@=O4 z$?APeAcpPxp;2YiTGe1x`ZW(@Rx#65o4fO0oB;|dIpTQJ)herjU9Py~t}D75Z7D70+Qk>tb(U z-Mi1-29IpjF(-N@_hHc_9~2j=9&}1RKxirH$g^)Utlo6rtmb3i9MYlv>bVvmtH@OPKT%sx*r$% zQ0^nV4bq8dt^%|&@i@=^^~7*B-4Ve!H)K9s$&F0UzhC|l31G{L?E@nfZu%q>Q73x0 z$QgQ055%Cx_7|K#Q+D6%-b7j$ZbgkZYqBdaT%31TT|}Pp9&<@z-DSYCD&Q(tn!$<3 zR9*tZtg#>ri?Gk|Ukyf3Cy(sNa@gU%wLuE(F@?Wc^|^;uHHZYYpT^5cCd0o zSUY(0t9NbL>Uv7MfjftuTYE~U+ITh5#b2=}Sk7`se#c;S3Q6fl-EktZS@b-8AuS8TnrOxBQf>M?Z+ zGcZ#jt(?YLnvn3-|rVcW-ljCn(%E^$(z^x zbi94~jZ1xHl=}Di%+XrcKyCvuU)lp=p7?X9Z+mAnIP28gvK^QHxisJlAzbTt09xFt zh)=!yZ{<40QfZ%%aIogFM&uAL<4GWvWXkr;*z$L~`M6Z`OIdX|RL}z8E`M;^8kB+} z)h8GRO7U?+mP$2WR1nF@5wH_&ad!m6aapuWMched=>{_4rHQYs%fuHigm<9iar`Ho`u0 z>e)!<%Mh!_`yG!uN5$@<$fQHJZFfuC96Q2lKm=@(M6o;Z2EY5o&436P8eAKI-{BTd zts0PTTEWtEzSr7_>KpPLrJgjSU`Z%8N9bEBBgm#emt@j%{#WJn1XcVl%eOWx0gWuu zjPZ6MJsr5c0r|QQv1f$09fD*ABPm<%6@7~b4)6Qk4Zj8K@}`(-H*UMT*4}S692p?F zCBtvK6-?0fVujPnWbc1C4t(xUCr>SmOZI;R`Qp)Zc0W!P6R**ImNKbFIHYKakEx<0 z94xH7VVAjI3ggDQe{Pp&Xn(v4ldu1V`B;3 zp}VewVf&oe^Pfb>!X}YFk%PB8cwr49@-vdqpQ?_vCkP-5zP<#ptVK93fmem;U~7^L zM~cjgj(R{Ud{yq_bFoPjjaZn<9yPBy^rBW}^Zx4Mey>{`j;Rzyq5J`dMBKU@l_>u3 zZY|Y@ulZgH<+~EG-~eyp`#=2U*#?FL1tu}ykG#XNusZKo{S+)CNPa!t_jq00aQo_# z%uUCfY{n_@Ai+vA4m%`4LyAJ*6KYcf^nct7=taKE0ki+Ac7X_BAVb3IqBi9UC9+q= zg7>}iEpOA8R2k~MI0S|i>cEs+hwg`u>|APktOB(guiafNEp9$Ve30dzx(rLOU7ro~ zsE8QqzCEtlbdcX}w`=GdYi8X_G73!{@U8khvx>i8q7qaVTrU^wQnth={1oD@is`d| zDfYgyA~S6>(5Xndmjtbpc7*Jsd&%ePH`l;}_O2hJq9&=r4(^ePhqVcPzg>!81pNY5 zXkau>zgC_K(0(hHDwitfQPo}Yli?XuwH?uzw!#5F^hRP738NrxNrb!(A+KfdlllBU z0feRWqnz()16l+v18**xGY3hhG(YV(qUU5{{^xNYm#dk|1;Y%VEdtfzh}wqa*H$$M z|DEwd>R(}WpfCrCD@(U%KS~$zT$yxr8lAsCE-3T+7Qen!cOfWNQHxXI;DHCw4wZl1 zkJbw;Z4}^12S|S1aA#E^+ixxWy>3^l|NE8uZyNiT)cqm0V!stTJ)|FXb{{~{f`1EZ zT>nK}5tNuFeU7tPVGDgg(R=n5cyAHfmK0~6pd~`+NA3iza2pqnUM<>{6iqI zBy2z?g%I!-yznfRStK!iZu6;d-J|;pgA5Cjr?nRWqeP_&rP8R3%7vFPh){>=vM5c>Sq~N@vllIR=TjQ^;CrVI~+xNoa&8`@}kH4B* zJ@1)Ak))`fzs*(OzCRR7drS%+BJStxea1K4i)dKr7i~3jJKMF9>NqvVVAXe9m`@L< z1b~tI94@cXj1i~&u@gm#rG`DqLT!FGyxUX^OUgRmlmy}Js8vS}e9%E81rZ*@JBpm7 zD=AzRTAJP7oy_4h!qYqalR?)2EBoWat?mkU`#QS1iG>fq>Q^jv&1yFOgO{T9fs>nc z;L8r{moLYhS-a?CI1U8G$}~D*Q%@7V@I9ztE||TDA6Qc8qat}b?So#$&MzC?P2E>3 zPQ>n3_NQni3gSgtNWD!Fg#xz89>;01jQrTAJb&UC?2%WLwGyGeqGy3Zpt!HrH#fzG zEMNY$0|8F25K>dcV{ZHIho?6IA9a=@)E2*Dgn5-S~s zl|JI>;S<>A+SQC?Bm-YWlP(pBJ2+b2xqUTjU7o6j+zVYwY_C?QvR-?Um8jqj3%(Tm z)iLtUes4!qs?Q{QvUu%MK3(jq1NTOA|#E1HxI-_wcF34IK zOwIlpa34Fd$ina_coBzEIHM}#fyv19KSgt9Dd{lqQ^;C}rH9G?8L%N;qK)%=!$JnX|>^7A=o|}j?FOyamJ0L$P(|xbo{My_Hf+p{x1(=>P zvBim3q6$MOwc8{0LPDf-L4qMrD-L|omTb@ z0k6Ms0i|QeVSTUyW@-gWo!taT1a;{G=Fp-tc#S4s#WCZsBu3q=KgJLVsM+;?ZTO0J z4@4X*iex1Uj6xH4b=XBGfFf$S={lOb!QA7EVCZjWMiwf)U%y{7dwW~l&T+1BUFD(L z@rX>prQWos{1LX?&2x+HF-j{VT`kh{aCvMpeoc)ka9(q3gkTZ`&!#8dbq~kmj9-6f za9*ophVCh7J2h`y!280O?lxus0&ta%ZEvUIrN^py81avbhj7+W`BbjA-(*tgoPN&- z?7$1MGr{@(Xm!fFTU?W8@+bt4E^2cqq)eLgpC2B1y$m`sRQi6R{$o4ivwqu%%eY(7 z&G(zn=TUDHy?r**4aMynra`5EFq2_WxTOZgbr(+u&w}cd=hGwaXO6=A)J{sGHEmAE zq03H3Em>%XR>y#ZZ_e*)`0l8J5|~M}$pk9;MAW(PJvc0VV~2hV*xzA&0Z|L@CQ85U z%n@yUJM8V!=G&YdFlJXCwjEORv83?#k+mxIe%smA{y0bv85tx~;-vc>Aqt|^FHJ^6 zk~dRCph_{60{Ia8If^m5tLC~74@YE(6H(QQAU>?Lg9arT<>mDMYbaNz;q}GkA?D{J z>V>i^k@+L@@uek>=G0y?sTM(BSftTkXi$D&?v*F+7K>(Pe1W^46b~ZAdQ^`|_%gXH zPg|-~{s+(#QXKVSNT89ZJv~vp*j0;ZIYZ;!;b-$JVNCCz8-o0hpIKS(O7turVZUPjg zZSnJ%jKeU&6F$e0p)PA#VG-hNFpf+2ZC;kcCB>s>6Wu9l*>Emoy|ab~I$2 zx5AW%J!G&B`B7siiqD!vK@y^z&tC?T?OiO@?|YwF)T#rn*`rjX8gbTqIz8sfVyi8w z`5aOZCbbb(Nc;`gu+a?sn=Id>f38^R%~f{>|6pcN1?E)_?>BylNf|_+VJ#OxXN?q0 zdSAD$=`4PvU8O*!?d7*{AXwypGK43`ZepK)@F;(LxoE28qja$18YIUOf}~BJOm$;D zJlGjGiGxh1bbacdW35WHCq=grN^u}au?``PMD%6HNfett#VgYYw*2%{Vz&qJUX)#T z%A57iEq;b9xh;-B%N7&cpP60MU@?OMJ~rVhPfmGdA_H-WC*MI?CH5)nxrjzgqmJW5t$mD^z>_9I~{q!GC)N`HkuKk8m)| z7=b_Df>+@v86GvhRGDr1N%l0%|8pS1cQO+sT!YyQd5hFNOv2ALTrF15u~Ca_HD@r@ zm&t~|p85nkjp(vR-uhn8PA$Z{pE~&YM$m{1;PJj0-LFGj2R z3BRIAQvD1aoRvPq-t0M9TW?b+@h&&J*X3Qh{)asNa8sZty(DERHl8A1in4y%?S^iz zN**C=rDSf8Oh-VI@vy+U9)0SopCUn#pp4i$Uby$|a`Fha?lIZ`aIA+hXWfNGQ>XrUB-sI;X(!guvJZXIgo1n%!7C9o9&P*ft$-IRRRBH9*WKI{ zzGh(i z%jCYw^O;t)`#Q1DAtwpZrb{)l@o>F%q1F0ugrf2mmtAr2%a5aoXk}e5$$so4i^ubU0=IR&IeMCt z)EfsP`BARDFn0Qx{H9nSwwu!R&VQacJ-q7}E*MVK_x~iD%l_-%S{wJRA5Y+Xb_)AN zb-bq|PPW@apwi|t+HI6;X+ZjIqRQ2_BFhjCheAA%LR z@aRH%tgKKyZn=4Q%ut<@jB8=w`=_(?y)N3wT^1O#kK5GKi~K{Xj#sQfL+S*>Lbg&+ zX`gnw6o!mvi&@A+M((}ZjZ$|`S-SS5!s4a;Pb#tXk>d%T>)w=ZrEBPbslmwEP}o>f{fov4 z={k>&jMTA5IsOn#D98xU#T=>)oDId=%5%%Mdh8VnJU^9+H&;HFF7DZA!!ex>)CN%- zoOVCo%>+AR5N&+;HQ)sY<|Ua1S+(|>pmaTqGOpjO5^q(dZNaF|TD|{E-^um&I3>{h z1VIgX3u|)feys9i2pN^t5<5TZWiUcD|yjK*H=3E8` z6tLJDr0w`IgG?(id$Rh0XRhMw+KzfLE*D7Zt(E|Xx{#06V&QZu3nFtsKi~Wb1QfOQ zt(G+3f(b!@@H#fG;mqAS-IoNuLV9qVKj#CJh>+k8QmURbGlNV4TE~t@U~*fN&kMj` zv(~=PU8GQL>Sw$CRk7ft5c=1{+QmlW+shy%FIl#>M`6sbW`&rkV}C0=`(ajw_?^T> zMVJrdCrI}roLq*2`X>_@O8@M4b;+COiCb4BrE$H3`t@5Wg|4Jmp$WLqOHoNyd~)Ifw`yu_FLUd_`+I*cgNR z0)o|vn$U}tVrJA@A%PDH3OeYTObpc=1~Kg*Dd1E^BylUII+91ZXD`in@AuR-uXWw= zRV${N;SZZ@K{Zz8pEeUy@zz<~tgim5$n*RV0!FnM|7^q8up8ZFJ9q9W;X2up#`MQ= zX`3uJY29D!r{$lg^XI?9CSCWQO<&Gg&ZxzcKGR5c9WM;PaOBft>?ULv{ydBf`b0_W zem0T6YFZH|K~7MLff)R0uyF6?CA8F2X-eBL#Z4qgGL3~kOI_aot&XfrW5O~j5nYg8$>bv-HHE42eP#0I8KS0nrdyza;MJwJ=Xq=R>e=%b|;pj~ zh{)1A$|le2DSc`byPO1e0G+wZ?$}N6Sy@@6Y-ebxn!5~6_FHe$9Eue}yLd;!`GMDm zKGfN5MJDSH)WsbHcZ?!n4&pU--4;jc+@{V$ZI~^(?}B(a$~1kcZ-)|KR^RjIQsuhl z=H`7&<3NqSpd3Rl3_>L{nc0*nA!wlkJ5ze?U%!hC!h@z! zRX)vbAyjm+3G0u*vix#2ZBU*tbCB#Ggz>qaP91Kpe%-R*K5KJs8>-cOpi45g@4gz^ zk-Llb^rF3qdgvP8fnT-nZjRO;Nb;{zT3>`{jVOFrTmL+<1irF;Ks6TgaYtdJ;E1Z^Ie|bqK>k z8M>Z7Qnjo-GSJWJwRI2H9~>KD#zoLT6I#2lz5HDVIql=v>F zqUnjHK_enTL3uYh0S)V`7ZipwG?ATYyv^pCistUk#1<%d1>;hepyqyH>)Egvkr>PB zXxP|YdVm0qAtg0H&J&@C{ed11BAlWpJY0SZ)*V^zdMiWO%nkk0B3Zp3jezq)bT^m&`;O4LwbYa5MqliS4E@7uy*?0>2-W z^Sfp*rUsTG!rUg+YLne(>mIK+89$V3<#`ofb5v?v*Sh3)7=BbBCBwZ+GPHR)C+2+; z*Zq`av?_2@wiV?BQj&VgD8JcR3eEbW`=BtT)Xt?>MSo7MMs^KU3W!5Ee-W}8MJv`9 zMGE2dBdhkx>t0sKcb*D8oscbb>|5AvWRdOFdi?jzz~3d^M#e4&Bfq`aQ1H{rB~p92wW z@5RMM;cX2A8rX>o13&pv8?*v4(bu4;rHgmH{;aSlxIehNf2w1rCJ?D2Z>J2614DLP zfbav2Wh)NBjBGSz!em^*_3oMR#(Jav>eQv$8$xTe)u$Y309>EdMearV#Lcxd_jQVd z7qXp~2~d+2r&oX4EwN8_I}Kx9sM%L9Ja_luD6iMj_)VWI$zL(D?z1x7T{}X|3MyBn z;;*-cY3#~jB1=3DpysJTat9uo<<-Ng@LLJ=iRDU!mI(S{im}$j}tS zlAL@Ha3IPd`MnFNIardVqO1IW{z9okM>7xIO)?L0LXyOAgK`s;;!42GVPpmqY}Kix z6Sig>U$u`d@OIsPmMXiaqOD+X&%PDyL&hqs{G_d&Bn=* z{6H=)4l*!>?QEH>Pi6Aa@>mZgmJW$7)PQq$o2zg`lK7{AdYBIfZ{3&CCN` z8>)yNFf4L+o06qAO_kP=n&Bk9Raxiod@D1&xmWNH8p1*Civ_Xd30RSW1iC~9W=T^% z)W0jMsHmR@1IGyD3;@Mzc>KE`E;lHBvEDw#jzCMPDxuDOT=Uqz^`uP(FXwa^fGu>L zo7AN)$jznsD~@0rbE=WW;t&vMha@tZ0W&m=9r&tQ&+~?IHBCBIR&pJ$N&h5l+@3GT z!YOy=guz4qB$T1K@|YzCz#oJ|$^O>b&p2fWZT`y=cwIRZ*Hyn)x`)_k1}kBHEQ1Ng z&s6pFM*#Rm>?vew*g$^{q*xOXXD9L3Y2i(=rSu&J_h6K#eZoV(GWa3$RIg?Tm` zw6)s<7=L7HHOq=x@sg2&FD!f1jCQ^Fw4XlxK=?4!l0X)fFICPM;jp2JijNA8MHQL< zS+g*+vBB>pYed8xPAIqzwIt))sdy{n`?(OmI?al>TzO0ZgI=TVYxcPCu~iQ|NEtr% zk12SmLXSGP3X&K$IPUtiTj7^8o~xedkOYBBtHH*Kr$`LgG1+5srpC7iEmM)0XF5jgK7%F zgIvYUo2}`v!anC=Q-;1uT(myf_6HSIIZz0jiaw~Xfw4-LjGZ2Rk?xn(=e4jRXP=kv zPzpNj6%EJI$GBmsxv~hIH)Xw&jj97p8m+c^1^fA0*Z(-r@{GP1_d>@hu6S=TA@NOp zA)C6kR2*4(63U%66$~HDbHcn!qbWVG&%-dIQBGNhW%Nanfc;*mowaGiXvOq5k*dX- z8j)S+pwl`NFrm<#X?IVwdgFFdBBMAbHxreg@E5iR_ky|oX?sJM%gIgDMOjl(e-Yfh znyS5D!>RJxLXKS4cMD)rekz>Jiqo%02cmb1cfI7-%bgv-mTHSJ=i;~oC`;S#RUN~V zQbmwPz=Q0&TI^ES8vJ!vM_IhB=q(nC8=rThWR8x=KMY1JKn|klk-!S@c83Z=xbc!I zWBXXL>7+;Ih$Xkt6K;)tZSad$SY9A!6T^tmJPAp&b|0_J=Aex%J3cSf_hqcG#JEbI zY(XUNH1G=jR>uermbRQuwky@ALA8+Aq);L}*?7UNe(yR%;62>vnC)~cqz>HfV%@hI z?(ZyiI;WZwqaiK$5?CUVYnw7x6((Hh^?si_7j4yj)PLW+UPrY2A+|w70(@xixHE$- z>v^3jd7qOE9|x@TXA*@0Xg#imIT-$XlV#2(yY{tq)VixtSry%#y=U1FL6u80RU-&A z$V`c!Rh@qYJvdfmRj&3z+JTgz)mchJIZBBJ%j6PEuughfXqjQ=YDTFvL51#TfZ_!m zf$uFOYFE7%qF-z3&q@( zk+fF2P*sb3kBD>!8nfDHBA3Z73uH*;s_c&2?VTXi#JycN@&?Mn3;NDwzy5cAuq?{y zAs&w__Ytl$ZH#PT;W>J$Xh{`(uhRr$Wy{zKH>nXXk39*giF<|g$`-*_j-w-U`f4VJ z3HPrByPQo(AW)!Cuak}xVx1KR(@*leH-^RA1J}GFjPI5y+Un%!i%wF7iiL`;edWE% zbBxCR*zIt^(OLYD7oS-6;VifvI4VZhTNs??SyFF~ej(2X1GH##>Xz!4@PP23TJukz$@>0eoSW<+0FU}~oCJj<*;^1fIWOiAx#ZOx2UVs8h+}NJ!FAl!Tz*+Yxb8Xv`pvcg~ z4{Q;>Z#`tO+u;lbdKCw`5b-?i6Sotl?gbew<1ZetSIJaa58KTS!#48IUrI&Y!@|?; zyH&T0c?_z!m#8m$)wSH3x^3d}^I}COIM^&DsJFvvX4bgR^!@ZDukLm`X=iL3@Ru3y zOjm8?0B~mx5KoBP=^IymbfW|@RL+_Ji~GaGbXL{OYjGIm^G+-oSb{vT+>m<|2iq6A z6?O<=)Hlf0?m;DFWT~(SO_EJZk_wv40KoYG8(*`T)mu?H%VLFX-KYakcd6tsg!lWm{6DN+ z?`7q$YC4tA!(;7oWyN>Ko3^ae+HKT~s_I#rvnNNx==ZG2Q68zf$jL%SLpOAjR#bRyZhBtIV#bGG)C1wUEjpC=fpL{q1 z1NBl@jfT7sLJV^VTVVYv$6tlT-%`bMIyySoYM*mZla@!hQ2M9sg&P+%EmrXs;I*iR zxX>qe^jno_s0*={pw##CXu01Fdcml;U%n1SFsDVZ7mS+b8yE}iMJc996NnZHn?#>; z*_|BAaXl&@q$NJ$FB)@H%2b`{MOCbx9~AB)SQ)|dX2YMgv$veDI54(I$F}U29m< zy@rZ)r`3iIjpYwdBAxOv-^^at8m#|%hZjwgA|<4Zm9(dT%>xa^+U;d9PvSH;DABIz zWFFL{v?!l{A)5?BlSGQmD=~rtedB9sYHAu(n77U}HvC)&anrPDM_?L~zEDeoKY8{B zKPXkQ#tUm;frW=S#Wj~q?&HFhu#i^eddN!O%0~Y2n_12FO3luZ~ zuTy8oKF-7rh0Scqt=2}sO`Kh>@Mr&Q$F!A^qW*& zx+;XdQbwmy8TQPvaCbcC&?N}R=H5b#*j%_143fr)bh<@872xW)e;C1N$!|rs7;oMM-tn zAcl!`DD}U?gG(%eyNsvrlU4waOHiR>Dvzm?xP4SbO;VEiLe;@pcp=h zJPlTqtYU=|L9ju4^ygDfPied6FX?UWqRzWVCr;&PCXHZwMqkNytl5J|C$k$9&vjpL=ToZD@1^BmlW{$#kQFdF>SGcO(0B*R4rg~8EB z>tV{JchD6qaEcIfC?%A`2c*Ym_{V&m_0PdPu3JyEtM&M5`_|gYn%!%o6j%-YyLlf} z#e0-4Z+fPCmHL4P6(xf%lW2O71r3p$klbitH{uf@4q>IR63S-&_&L^_e%fdGh!LD{ zJfxY;@v8S)l}hgB$igto@0%oOTZO?JtdiHZ-r6_KOJ#j0Lup!PWqE}$gV8M@AkAvU z=;2L(3c^7XhZUR*)OXg>YhY$(WnR?eUg20tVTzIro{Bo-o4MUGPL!fpq#xa=VfW}? z*-Mi>n^0kYnFXPe+*$Ft-j(VAizc?*-LQdC5LIGA)Yb0*!ATHT4pWA3W6Zc8v!2Ar z(P%x52I9$_?GJ@hMqDshm?E_#p%@=qxG4bBEbQP2#307p(&}5=D%l>x?$qz};SofJ zXfXTH*Vp{-=u!62tL}XJ!no(HPu4T8IWIv8?rBiBDmJdqji$T?4+gGG&k~#Ufi{&S zNnj2hlDzZ~4my5iWK?TNV!mGky8<)8ntRFlve!S!YF3Y9;+KYQx^7NMb!;&E_qFG> zF4k!4`_v!I0ghMCH5R{-)6-dU^Xq>$STsF#-EQ@w$H>iINj>ybXCcbst7wIZ%DNOHVgYEil;B5a4Qh< zc@R%uIJRg>`5lOReiI35fHDw7#}Q5w#AktBiK%*x1C_44d=k{ld1B&t!Vw`H4wC-k z_SZk5&862t_5*5U6fVn98AUh<7Hl^yXy}O4v3x@70b64EPDIE_KGmT3Fo!F6@Z z`E;uLHZ9wO6&!1}A-oFme6vQ^)jZMb7mV6f<)MaFz<1c3&>hY)S%=JDYzihX^SYDf-(Y)ZGBFP}@Sj|DB}=MVJw9=qbakZ?(gnkaC^j=4Ty+c!q9<5)hD*M!LI{?vzGSy1S7c zx}~JMyFoex=`Ja0>1N*h`M&whk74eaefBAIq5+r~wXV(8*2A_qf9Gw*IDvi2dVH zz@t&_lhbqcnUKo?t8~2ALtA&23dtz{uqMl85L*Krc);b&uozA0LZz$u=ZH6KhzAGH zpNNa|m%r@5v|-33Fpdl1S=giboKr@OP{$vq$n{@{9w7Hp#WMZx#{yA!aA5X8`7_2A ztbFTC&7?S?Ni5~Ozkx{`Y`LE@B4k$WS=66`tYLGsJhV}Ym5PN7v2OSww0JgAU+`?o zVWeNl1`FNz^sRc_B!`)5a+BiEXb?FptQ^u%O^pcyq6Kl6SuQSm%u%%QMID4j;_C{? zehBoIXfUw0nRI2M?c-KxF>+>0@=G(1VfChWZ*1_h{7i2Blfyxk3`d-)Sri7Plr(;e zQAZoqH2wX{ld@zTyRLfWG3}Dn%7E%AvSMB2I02rGDeUbqZ4|?dK$Iepw)X7MK-d?% zM)o?Ss;cQ0={m9zGoJzL^${q07zW0C@yf!fP`+_WkZOb?@Q!;o~ZE3R{;>MO8=#lkl{DisWlEj;OThQ9$)~^RO1QFpVeTcoaw@&!=PSWA26ITpP}jieMK_x3-ns)3^~n zDvk}d)`n^_An!g!%FOnXFvR2|ze=PDP7#EaqH+)gc{n{xN??$$;Y(ulFesM>x}eLG z=S(30ysFLmr~yK#;_<;n7gX zs%kP-rf1OzEv@)cpbm8ds3oxyC_!#{s-;i35PfMnWEq>R2G=bbKo7~bH?plZG(asj zsmcK%#i$Lh;VT=@+FND z79a&ixa0+`9FOQbh3fDFr$4Lvfk8${dzm-w6?f7&hIdW`2DD3{;iW$f;-5BXwnIBpRp0RIn-TELxS*e z3?jl=;cF7lS=@EM>4DGGWhSt>cyg6PM~Rq-XP<*c%Nj@fRSN7@Eu&$2`|TL2+`SE> zU(ksnvJw-MzT`1t{uMFr)y7Dtwf~W&j})x#J2Q?wl5QqHU9?}J{PB(3EgOA<@LF&}X#Kt2jn8NlMl1U@}MrFJm z$01IF3r*>1Sbi84t8ZupfsE0Lgb*a8zH2Fm;6TJkiHGjZp7ee#%vrV0(qGOC;jGlB z6MW~%L*k&|Q})W|+^as-un`;>%lfNO|4s1M$JS@nnsClt;#^B#k6APjTd16`H@(0L zA=zO}$Ky`7Dp3W9LJmpohjE~$CEK>3Xxt{2PmP<^QlpUp9EgNlKQCDeL2S_}nkED! z!9e@*^sXup;H}><*((O%e^kZ)T2)1o?uirua8Oj_6r0?vqJZKkH9&NHd>r1U3D;U8 z#u0_-=ueXzY^RzMKUtQmgtN(O>dg}{?=`>$ks(3o{d%i|w*-qB*A9=tA<7>SE0nb{ zj>y54=WsSxs{X2eEU;T&IYKkk)swT<8wRh>Z>4aCGtcS3>^K*u)Rcz@qKED@^t)R^ z$d99aKK;@`j8Jh*Cgq0@!*n6sKcBOf6f5arx^)nU4efNU=*w~`)9|XKhf7;_{am5! z{GZN>SRcekN6}Y2^y~jLU~SSw@lsDYOTGGmT&j&F`Tm% zBbpGVQ^FY$(Mg2FOudTwSo3k6H4UrB`u!FId7P$XTsuVt*6_$qXV?2J3NgN`uqBfs zPzKMQU~8et_0kgYm{T4kCfl$M4XH zK15UnXsDbjt4JbtmaaN86jF@}--4#~-vOH6VgyF8smm$7Ke4*_@x73;-Oe`?J9;R? zOd%%PP-3-yhGxZ;wPLvbEN!aA{kH)nNn7-YU&ACCEzPc>C=y)$3LM3s@~zkY&HFbK z2l#;b@#Hzbd>!g|Vg&v6Go6ln{p;x9T1Y1%Y!)U5u`!-NQs}KcLe+If0{j?V?6Iar z)l1fFY*Gve=#}tR=E%l7J7;HS+X*-{<^^=|YAe@DNjn@CNus*Paz$UF5eC0ZUkNen zU5gkesEP6T&`8OLH*kY!ytdRFocxu~&2^R{F^;%*iI-fZIEE%t zJEaSE(pzr1d#=SnQ1ld({Z^$m{RJn|`F1d5+ReabtSY>gU~7n~_GN$RmpJga3NrzD zEHCElec)iLCKNdKe*XPiy3;6-6b~Y-=E!0VV!?&=o)^b5kH3$w%Vu4gQ)l=DakCIs zGSP?igV2)LM`Z*XL1*6T@l97v>wb>y4oyO<%+k8g<^&~d2{Etx#0Fe zk}E2oFP4rE)B#^>5BOt;blUU*8h9B#LLZmc?%;haD&?n7p8$8^%F2pvB^Uyxy31Z7 z(zEgozNc^%%-eJBDmY1Cwopi@|z6yTX2(lS{wR?LLBV~3BDZfWCFvB{ z`Z(oJviiRnlS4qjr4lf!zOcS~x8~RAT5c2$aKZ1(a0a=p_Og`oOFaNEzT&M`%;FW-7#@`24~k>xSVX6Ug^yg<+Gf9FlZ)Vf!~qG!meV;# z4Fc{cbwBEp^YOiU_Ms~wAbe%`?EN3U=EJ+<$R8h%;D759Mpu=bR|#sKmi;8C6l@h^ z!@RC%j0mi=YAj{KVf$29WrJi>0OxSJHg^ByPh{ zbe%KEw(a7UHS-^sQJ3vW>N5pnv$RD-hW6fTo+tOZ6@O# zVw_43IQ6hQ>(=9kv?ko}g(l}{nPl(;QoZhJRqw9F* zyK*{VQEfEuz8W?$G;iorY>!ne57ER%-sxsv0e$&8RW_3WCh!!q`01AO^emz$W}zKi ztPU?ja$Pur1ak3qjvmCNnsa$fT^H?NuQiWFqqOy@O`fTjXj)K|O^^Nr9}1*OrEc1b z3MfBN5EFl|RzEbKKvMUgM}-b-`_ZNKK2*CmINNK`$B_zf*B)EJCJU&gC#56{tW>;X z58630wtD%0h~YzB`uN$2(ATqay*KU3TGj^C-+|)u#yhK$QBbllbTlh3g8#_9n&@T6tBVl1$rS9p1a7w6Iau2r*bNs4BKc&OT;EUU^0-n?j zH8oX#f*;*jO1*+7o^!bq>6AQgM)wS9pkfwdU&w;G*up1rQGW%wuj()!|6EO$x$eRJ zmr#f*{%0_1$A|QPe+H>_@uNc*HlZL8N3K~l*O30`Ovn`qmG#(_q?l<0)8~^TROBHI z7XCWXAK%X_SH716Z@vys7@n1kWXa3b3Kn^}3@#tgN895!YoiC|EA)T47o9&IcF%0~7vaJmo%G&-F42)a#0ppX_6&ec(Jn0+ZQ zEimO`*IvP@Vj5rVr(GJvUmo&j?h@W>5CFa&%FU{+YY;s;6RK8Fv z+kSYdLe#+H^|Pb_#`P@`*!@;j8)R3339W#z_n z#tAl zBS5{vgAGB%#Bgq*i4*%cLqz!uUj8V(#5+iz?y|==+H;`dLsKa(Ow%J5XMO9^Pr${d zfTzF-IoR%7Vr)UMZy5DXF9KU1k!2R;4lrB-TxRyZQrwK``i4Bts|~^D)kUy^-6Ly> zetehb4sxER>haOBd<*h$k#MB`b_XyVq&6M)nnZ^mJ%SLEnG? z*3+jck@^=vN2ke>uu@AEFy4NGX@gfm%MlR>;*TX0C=pU9*PXB} zSt4-WjRpE%``+%G5=iQc7wywk4d!`=#kJmQzi>%9{)DC#1~LT#*o;V(ThNT_a4DUr zNvV_`g)5^~pV<3VY?IT+^C!BN$F99jQiqqHcfa$tpj!i1`@ws%du@I- z;D-}OFh&7drTu1evUl&QH5lbIJ4W|qhJ(Z0gNk(u6XGQzUSD5>f`R}JS5rG0D0qY} z|LZED(U5|pVGJRH6vbib<>>2%ro6x0qdk#CH)`mUty05vN(u}f{ z92In&lXrXUN0L>%Ykexm?pd&thX*TeK(yCE;GlN<&#&#~MV8ov-B({+J99g5lf_Kq z0{-?C*N)QyF`%09jc?Nbj9SJDP1Ns5SgGrh6brC{{h=59b}s8&{}#sIQ9Nz3{$xd&pcd=rmo zTB%lsfrZ7Q*Id~|1_D$5&`l+ycJbQ%#)=<7>*mi5kBdV2Lu2D=*r+U7zBdC{c*!{p z@v&ji>u}Eyj(l!nQHi0ia3=>5Q*&4}e(RPKc62!k((_~it8l)k@A*O!>eSAE1G>V6 zmt7XTW50ka6=%hg#f+}qTQI^mjJSZE!;KPmWV;N&?@PAiZnYk6)bSkCLTT)hrd5N@ zd41MB*5&4Q5$P8y?Vh=zy3Yh5ZLISnCQYEkVTZ$ot|BB*;w43j4=W7Ur&1gd^ZPij zW=OXPJeXOWa=5rJdEn2qJ&TQ(gE6RlpNMt>*f_P;Q}Y<>^8Rcv;tGvC4X5W0FEaXT>q^{7C1+- zFrNN?L=Ge4G1+kOciG}^JS^$NSk@t7_^tN2-d1X<^4<7w@+KiB_#$}cuC)-?3!qOO34UuPwT zEC0wh()Ak#Fpk)1RkCRl3Nmg?MV&g7fp3%mmlw3OAcK!z z(_1t?wmg&9>N8j6HD|OMbE){8ba!|2SAsx41ZKBnOrfon@KK>5l-4XyoW%1P$+$tp zY!M>~bw@CcN&@c8Rud^>D>=%KbuK$&6CLNSHAWV3m?(ImG}g7BAPJb{B3-cDckh;+ z25w#`a+3lTP_PmfbDEU))V>5#!im*V<@Q(*WD_}a21Pbrx4Nz+oJt$s-vsEtbZgi6 zO;yCNo~2rZ6&R9F-j`vo?XA1GZRe5geUJtPdX=kQ_ZW^NO2K^@K%l0|3u>I^#!X=V z$(Ab!MW?lXHV`(Nn_>{3YbW|g12;pf^S#1ayaj=zkX+C`%Sp>&Xdh@pEoYE?&lDoQ zLEPSa^~)}1HSE+2ju?(53%MeoDGnc@Wjp*WgD^?JPH4MfV!?b75r`p9b>Lp;`ynq5 zkLo4z+(aYNjbB6Ct#HFh?_bmnh?|<5AY(XcjiY#cd%H%&3s}*bFvvBT8&s3hrX*Ul zCVR~f5%fH3;ZIDGO>-+dZ+? z9~LmSUB_)HIUy)3>g{O$H&KD5gf>dVYi`xvdtHpjlr2zR7uJOT4G=Z8K+RP z6vEebBsN%1CCkw;X)Q*PupwX!CMuX4@lyVgu=oIM6nGk9Z!9#dOfaC+fVK8^)}f0N zaOHW;z^7NwpkoehT=tFxO^J9vPFDqA0M0|OM}~$1pG5uih|m0d8|-<7cA;m%-?z>U zHJ-9E&ajSd;0fpA|!X2bG*4_P@ zmzVc-psYkX8%4t!_oNegB{tkZa?VQ)q#CHxhv4>+@Dy$MSL})F@rReWh#W+98N>+% z{BsdS@d*o27{i$n-*!B7?BkC^Mmt>GjDJzCDZ|~JYHG&iV9p^1Aq2?AHugo!zC|F; zdAO*)4%>U3S>uO&Ly=;3yzF`0e}z5iw06lC`GqO4u_z4SeAH`R;%q<0Gdk&n72k+n zdAEEpFc;u@`MG%1KamvKva!4FH^1cJk?QXZlB2xJW(=`H(utS;<11}u4fu0TLkwDP zB4uO%2U>z$xiIQ)D#_`$e+#7J-k^ml(5f@1LZ?;nH5pUd8|e<#&_pCTQ%fK}-PRxf zrUL@4j(}4V)=v1XEJCzU;C%RC(B3#m2BH9!67b{7ND*ppc{rKAdih5L8p~0FJX>mH zfdjzOkFM8MxNDxXjKD`aHhUd5g?(qgar|gs{GlXJP(eUKhL+FLyEV&qedr{>KSr@Y zvVSKQqd%|CF5sV+0hYsa%$+4~b;i^bHzDMZP2_Q&oc#HuAS1@c9##+_8r$#9fbFWn9L4n#*pM&L(%zLko(!y~)eESStojkO!$p zOT)vS$D=xj^U@Q(*ucMIS6HERRGge5OG3dTR#k0~=q*oMo;6zKH_5wi5l|`Ea(3-d zLFwqyFB2IJS`WilYZ7_JMZ(9FothERJ4Vn_p;}RKF83yz4&?U70IHJ`{RUP+8&+73-)jve>|4TAE=idf7MG^J?!i zb)ynTbOXqSkYT6cQ!huGm?9n&De`nLz0$-ei-cn)!7kO(a-+PPzi-iNGL2vQlm?kJ z4WD<@#!8T^D(g=@L;|kIm5<~!PFva?Yj;Sn{mziXUmvE;EW17bPE3lvs_COu+~}c) ziG52vcwIey@u}gVrlD;$o7iTADD`UgW-EvQ*zoS2$Aw$b`{$*LcdMVp)jwYA7~o-y za@#E%dHdaJZ@gdd_*=&j%I?fF-zC<2nDXNdRs$KAD51{By~FT7lZaBgK!8e{6U`U? z9s#uCL0mex-XM5n+bF1u;Z$<6+<&*X0U7@v_8d$Bn0v$_OWWrvOw@$YgKQX8FhPfQ z^Sa2-(y^pL3z1^Y1QdNPsI%%@)eR#gOY-H9O0WA%o7F9Cp8%zQ(d(Q5BICcu89sSxE9x`%32iM?6- zbGfzi{<`nyo#7l^csi3fYC8T0Vh)R2#Jqialt2Uwc*CdIee^3ov+j;o(0K6A09dfTi&#*sK$mE}LZ zp0^<9^2ggx@%Iwfr*paPrfzubtch+ht7N_|>I5`@Xv#JIX?>6*o<)%ZVvk8TyW+Ab>*aCFKQB?4+Q1ICofpg&o9MaqI~z19KNRmV;_$un1- z#o0!9wWWffqPfu|x~ReY4|Xk7DB|BDCd-?r4`L@fBAd0>+}7T3wX*7RW!&@Wu_3?- ztHBx3Y`V)I1!WFC?2?vKP^ee^&hfl|fY0@Ne?lg^KNBT8*gBqKCc!2p_&&#!OGQT5 zQT|m_q5f6H;NZ8V|L>QPW>>upfE>~n%8UiA^xm4BDCYhR;N+z#C!hQV_Hm#DnmU)= z+MiZCN+Hg)Kd3ih1J&@d=SR5#Hr(H8dXga#9HK9ByOsa42|o@=kMGl+QQ<*R$aSO(>bFmmlQXl(Kk&7Dk}-&@N^pV= zNS8LY5OuR6lGS1cq$ktKVmOS9j;w zmA1#eQ%uG`RhU2^wmOSo)^FCy0FIyYzay#bv1F6&3_JBQ_x9?%&1Y*?*;AH~D)4sg z&_R@L=CvKW%U%E3@CtmG+fKswrn||&3=Uxngb~j^nt(dwH6cZ-7s*)CeW3tDM_vSg zIs)g*D6mTtQv318~c$M%KDW`H4Jguw4@S)qVL(kc8rib$QMnLdoIeK6_1COzl4b;cb>2O z*@wRfvR`zgKu8*Qe_2i9IIQvAs&*>WJch>r7&L@(?6*yXQY-LgCTz$d z?&;o6dO{|oXiuxnOqI&u%tLp5w)sXT5Wmx-K`wpV0JDmn&jw0jJSp~W+K6+ zh54LU&WwZgX6C$$`Yw;5DqyO?=kED|7q_gCj&w>3ipXnfewV7*w|-nPSKvY?Hsa{H z8Oa%U`n!nj9TONjHL)OPrEV0&z~yPj+FrqzchLTcf4Jw_>@2Ja&qyIK%X}k1`<#v( zcSN5OGhVg?3-;3g(<5~w;7W=dgc7E9-i-+-lx`v($-{wsULw@3YFzbXL7?@-PX=jHF_`)dfce)2P1{b8ljXC~FH#;wk_ zlc1N_;fv?O9=OdKq!kQB{HwjsjhDV3nrL)a{r>(onJigtSlCG%EthL(dU9iKhBtG7cl{vq%2rQ}R1Dn-!NU%V;q&`ev1PtC!?LA2I3rNL?ed5g;t5 zYMz|Cc)j?kKfFH_KG)}Zz#}(F!A#%^H$CJhjv8P=i>XEphm+vaAL)cupCF&*j6Gs^ zyFL$!zSbW+RjXh*)4Z1s3mYK-X6kvVw^(3MY``glVeA#JLCQugoHcgl4W?!8%KFPh z&b8+Fv-!jAYR#u<~y3EIN;uSn@Ai?d3RLwYE%8;)i_SUn+1nbCGi$E-_myM+IiU?DFTEp(2%zhrx3lS z{rc$<|Jg}dOv?DL4zDpE^3ZC1(U-61M!pS}R~wkH?U+bSvYR-b8^5YINGi3vBs>o_ zI--v+02*kcNIFW$@f1}#z=aS+pgQ(L)-X3oe=DjO0)sh`)_%PR4u5rp^{zJ+htwCh zvrdOB3-Q$!x05B+qO1&j=>ztJrc$ilH*I}T$Vg%!O9N@(_UXz~D=8^V zu8cm4)w8XVd!qezoQMc7E?H+tUerOmtQUY1{t zpI)C9@c@qB0a^*b2H!E1h+apX_?%^t3M5eO+FpC!#fm;_e|G9)`=jF%-t%@xcM?7aDn z?$e>wbFNvj>4lBwE0AOL0s$FE(5(S}S+uh*i`~^#G-a~DdJ*1S%R2Tc#=KNY&iN$e zxv18C1d1~!=&x~#~y8oo(PQaSNC{AlEs?U((iTQPj zJ>!A9?8=xq>Dqkp8^6Ol@3oQ&F0iMW^Y27dI_{yF$yC`!$sOoVtKkO(3J9_2O|_mP z|85ootq?xyluP>3%dio#h$9+*X6er%2nJ$J8_U&I4Yw-B${Z^?9EVhFY3sjlNsuv1 z#*|<5U&3LB(}e!VxnZ}Y(nGX4pVXHgYuTM;X<@l%=g;dN?JYp80a^-Gdb^YDHXAl` z(_4t@*wwA?v_35!B;mm8AowE!-q(?bwQ|s}JUHL2-ad&uwsX|Ft1opQHTVt+3QT#> z=NKWNxq9X)It8u+hGK-+9WHZfu61I4+;oQ3AWCP8s5}PE&W=U5=MBLt*tyMa;x+%Q z=u1X+*uU*$X*oZDIAWE}L|6b8Lm?P|S zLhF*?G8ugYIvM61I@x%^ZOj^#08yPWHnsoK$mbto);v0xv;5+A&q6s-dTX;sI;JY5 zuc6KQ74{2xC1CHvq-KmW)`4IYJCOfc`}B9;=wbCG;E7C@IeQ#w4fWd&(=d)2+a!_c z%~um+n?!tULSRSZu%Zi-U5BFl==U6^>sAr+#CMCb9v&WG&e9c2h=7*QT4+ z0XF@X`N|RS*2hv4_H4C|2!h~141=#PPsT^=DV%ypz&g4yLwzMN!uHhTJ0S{XvNeri zs|ugPuxV3?M`^Es`h$^ge!Pqp_Nupr`1gkdEN zC8znpvO#!PRXp$;Fa3l}(mo*?!Gl{4`lw04&_4l9k=CtVr)M=3kUnbPH#2=I z4}%uxe4|yqkRw*``S&8`Z8pqAR8gF)*M)|5jlM@4X6t$5^ZCUAQ<_~UH2^zPq2-jF zn6e?{C*FL{W02Q?sl8DVH`mZCGiVXL}r&7J<|Kx4zOKpwQA7mCLj@ft2|tp*tKf6 z2mW87stQZ{>HPTramCx)+mqFz9W34~gDF7td!(Wp+-z)Y6=9*We_lYtcP7=N&Giuz5>D0i}69NAQuY+c{+6=W5fjsx!k(6JGIdRv%fPHoH_kW z7|N6^WwU{HY*FZ6(jgsgjaWBRR^4RxQbi@Khk@ z4OiseLSu}ec(4r3PEg%thPY4i3Nm;;BbCVoe+aHE4drKbP(z%ZLp{)C1YdX9hg2%7 zLNO4XiDY|#je)iE4%v>^$x zdM90URFi|1^#`{f)PKoj{P_Su=xZ&(5|@7K;;)I2PlIjTB7%(l?ky2fyz^@Z)nxQw zHCU$sh$iy@I#8?Zsc-*HO&77rsCvxsOG8l^o%K!wD<5MS5dDearG)jVI7R_?>@ME9 za?cLWei`G1Dbl7R2Li%~&c#XZt?28|X3_h_R!hEB!w@t{Prj5oiu@VY)v3TDNO-^e5|PILXtze21souy(zD9YlF8&Q+6y#FG(+g4qm zQNT-spdPstMd~6oYj~YudUv+2if<6F%1`(w9vW)WYB{ww1`123&UQN$fR@oH=C$i= zDHz&@Gd4PxM@O_v-Se>_gcYms?EMb7na>Wm-dOAD(cZ=5eE$GiDi0P93v_(Wv*dyO z*>n}{=FE_#!9yiCmuT;H#7~2Jc;Al=(mbv~-+K=5w>yf-?EU@C_>FZkYzJG|=Wp&i z*?rD;N!2P*n(L9m$ab!0)OSB#%6S+3BO&ahZw0Ti4?@f&*!!q<>~+SHD_6ff!S>YQ zy-Vp+8o7g3)~aO>D)`tMXTym&uyll6EiQ*Id8;WR#oh-#bd%?jiCm3nrFWKnM9AN@ zsYyE)bghFMfvB>bp$>yHCJ(}LmRrtidNl1+avV9bf@lwpXdX5_IT6S3nUYw^v}_&} z7Fyu+X`ZDRbIDem|F!{%Ou!QDtHb6)biWD{1_YeovtB>B>1VkLV9wkM|MbBPdgr0T zd*625@yM?J^hk=}Ynk7=>Pe?WiZoWUA-1CG?p}Xgds{iZ*>FHJX{phd;{i-uwQk0f z4`=HgCM>7MAkdZ};67!tMpjo9ErC-K)H==Y-Cbd&V*9iw6PJ>$I4&sidfRN|TcDeg z>s3TJN#L{mFHe2yW-48@e2QPL-!Aa==pSkBKh)>hMid$Q<|AL`H>4OI8;p8WGDV+dhv4fLm89`UT5?2r#{CeaG=nBON1SaibRGT??95Nc3o;v zg(f8#K{jzL68f#yOT-_V>=NkXI5O+H47xR^C2FLUb-4uy)I|R?a@g zrKtUdR%F^GAzOIVAM$0U-{DvH*1^&pf&?0;8e{ffL@TyTO^&~4ibyDY9H?vZ2~RkF-0xo0z!1C|DApeX%`=`Io&}q^ z?9lege8t>858*jm1z}-2XcB=V@62qux3@4%@HE8nyo91?URFp zLZ>r)dhtSTeBIB{Zo8g4{&z>;avd{V+i>wJVLHppjZ`lyG3wkHab(A5FWc2p00p0Y z$gOhyI2EkWxRBDFP--c~S3h|mJ!%s`ip*r8jeZLzMz)IzpOVgxo4*<8$4B;@Qt?2e-iD(ZtNSd*$5GQgm+_M zKcDCN(4=xF?^B=lzeZk{L~M}8K?@tgK=rxE-8Jj$CLmdoFH|oxo3W&VC{d8o0HNE8 zc=!GM$D6OyyqZ<8UC7!VW2 zBe@8ulN9QjGMx{(Po1xOE$ZO1R)|rHs_owh^b{oWUi`EijT~3pjO#vSzk`z`!IBHG z5aF)>jiRlaQe3j}B`p#N1eoS*V)fbf9k*qN31f%NfF9IB&GMbU$rbBsE?!)>F_Sar zIvUqpI4~Z1y!LefX%aWgBm?k>=|60^cp=jYxZ=J!L#U7hNEY|1EJbkkJs%E=KorBV zCij-^FBrui09dlovs~g4A|?c3@9UG)IM`LS zDC{lM;Nh))Z_$({g@H0XfSnSGQvv0d4bVod2Hbq;TPG3YZFrR$QAz733%CybCl$b$ z@D!s^kbTZs!}|0st8I}brhkd!jGtrC$+6M-Pv#U?8Uu~kC?|RA zIMI4-H^D=~yR;x@+{oSTo_mYUg^<~YK-+j&6K}NJsdwwr9QV=pr3^bl$cO<8{5FEb zgTDFdsw49n5F~N=^W4w=WEbj{KR;Ww5T0Oi`Ffo8I{GwA-kymc7aqM+^N_`c_aW(l zjGi_$J${{gsI_`gNJnZe1!ZwJqePcBaK+rn`>^Qj?A@@FE*#O}U%f+s`a2 z(J@=x9Hl@X)ry;whM{ZeGWp@FjP+#n1PNr62>w&J>Y3=;;)9-pOSK_Kha77b)9sO* z>y{C@&%QRy{cot`f5)vCI4Q`{?~qUbvdmLtXA&?gD)625Jcv0SX#U7#{}cfUZ1lPa z@bhv#nATv~f%9mib`oMDSJkHKexKqqm7SyxyVVhMy^a=5?B!zvXR#ME<>_v!o;swj z!OL5;+?_iBM7R${oH=N7(_!+>bZaM&gMH>=C`hNdv(O^)TrUbUN=$ zDV`?lTA!(~R$a_yazuXT!J_fPbMKs;lZT`ltaHI>DYoin6y>J}qk!mE3t1s9o<43R zV|eY*T_Sab`=3DTR-o`0=_;}co9MO_d2Ep;f0m7*6WGCF#|)w4JnwQjB<~TuC?-)L z%B0WXC1-0gE?FO*+WE9r{tb=&O#T=D-OG=|#We`A=|Gb_NVjFxeeZ)_^PB*PMZxJJ zm>(ns-MMc&XztBQGI~`6a?BdD;iRq>rns-L>Jh`)>lVKKC}{O;L6H+_OEYPoe6aXF3{Ni1?iyGB{o zTS)8|4M9{%iV|ZmDpLN+tey?>j!IPYaC=^zndW++du>)t0TBcU2|r^sU=H*>R z5UYCooFhoF$7QdFBL)8odgibNCpe;fhjoQJd21j0D5g9YpN zpol;eVkT_p$@6$k&%cW)jo7>5)dtkXoAk?+V^ry7upwu_P^8#JU4O~l%UuBGlXQi+ z`OapH_|R>@qfbfClW)1O5rL0!J|nR zU=$-j;f=2zFUra};GAC>GTwrc3N^j#HSArB>%ubm zl4?9A0_s!cy5vj1VU$jZyM@FM)=_{!4zp-gO@7>xkP)&nDFwRj*Xve1eh&~ZyCnDUEc8)S`fNcXziS-3`*6(%qdRAl+R8!b*3?e(!hA_Xlv!vhVG^bLY;T zL2sbz_~j1Ne2OzKz@@$ONU;}rU{CJjTQI$m0+oKe_DeJIzRwUFR!BryzdWt1zV8%l zUo@8d?9-4m>Dsyb&eIg-^KiK8LrnOnxe7-=J!OQcu!e%DQ=`ttV%6DOkaF69so}TT zD`AvSu`qA|P73qoA+5T>Z4n_mR!qF2*@Bi>>{lE(kbq+u9KhHHI+=M|Fpv>7YIbfr z{?YHmKrr7y_7JV7N+J7p`saL;HCwo-SO=5v0DIk>4wvI3Y+!povXi-@J?n zh<^~DLq>o{2WS&>p|>VK7cP7hrYpS{59_URZF}(pA|#}N)Qtxlz*VE5?E|RErq!Nl z2dMGObdQ9Z8Q4vyp#KayZMS|fG*AmK?$50$=RwS3>M07LQhE>-mt^0 zNV8e|IQpUil2u>Q)ahcSnn}w|58Jty<_)FXZ}*{>2@ayTPGSZhq~T@uSFi$xZiwKO z53J&81LA~MlZ8NGLAcz>32<#dV1(Ks$rhGHig=pYU{rQZY)M&^8(KM7(eK7O-{MIn z%;@)8(@)=pN2{j!vh(182&(S_dXH3`?Q+gr2Y_lJ5p@^YPy%oj&jJc(P?|i4#Frb6 zMzw|75m~OmkSX;bA-D=R8eGKwgR_sl4{5Lae@%5Ov!1N?PjRUwxHW{YABNjh_#K7w zU5}Q!N#MZLZ?8!$k%FGXBIEH5`;;^#TIi;(pr7QMoCqMtM@MVTwrR8h24a-cj|(jS zrDV+v6}0pmdgY!yiR0Y!wAI)SUoRsn7bum*Yk!8&IO%_#%I&tC%ohJe*!+UqhokuI zKaNo#+vke~^AlI}yLSd<@?xfq7&K}>1g1&@cV_&bsHqhA%m3fCMIXz9VfPU`xDfk|veO3A+0*b$>o&$vBO)h{)BDwpBCFKX-?XLBMSg2>a9kjczb?ndJ_e=2x*5a-mMc0LMg214RuUmoE zj_{GhaKw^<vFm6K$H6z{ zKMLq-xr`=v6hY{Ceda(SxA|4`!l`1IsK7B8f#;%V#)}(jI?hV-U(p3 zx#m))_2I3k0hB*7aDq8SvJ~B&(m#{q|M2Gu_L4U?>^*nVF4q1ZZWS&^to68^e5v$~ z^JFa=gK%b;?O8pY`8Yu7d;dBec-M@D;;Cx+$6ZLz^xEq0#JNwH??!+weo0P!vJCI; zOZ#oJ_9kXPy87%dYOV8@5u3_^nrN&>2!ThiO6iv30@y+`=R2`UfXeTkZPXJZb zdOy~?*odJ2a(;fRVmq{aKu@YAAi{fqT-x(Vg}O91DR~pGl8%NjlfRW}c_-TDwbj$> z#lWh5`+CFINx711Gv=k|slvpHwEHPbyY4GpE_m@8($1VMRuM2#L|NpL@jBt1_wcVY zPWV3Q@ObJ%Sovve=7*)C|IrFnQsQq~T^yM&q~@~JS(A=h5d(v&{}MB`vXb$ZR-P53 z^X6;1ysj*&F`>_RU*NQl99V&DCkr<%Fr%fF?MqN)=E9J>^=* zL)u68#{x_INHeC4%XGAmBgSFmSDurc2QM7k2Xlaz;mDACFQpybpn!<_ws>HWpk6dx zS~A~7)Ln57NEvPCWdHUkG(|rvgA}u*g97fe!nf0d!;h9h1ckn{;Icpi|)xKKa`+^2hNXESxpFWrra-p-!NBj!zZ)L6}!q zwm;|=@&bv{U4GTrSQ7V++`3uR9h^!O)VUumqA!E=hO5ZM+VyG#%@~8J%32{(%4)Tb zaj~&)&_X2&lvvYZIe3xY7hn7Ko+8*i1>2);wqFebce?_N!6YWRmkv6`W6F{sX?JLo zSo)6^2>P@R-wO#96#`u#(!t+<(ZdQN9TTS~==9!(_b*c?&q=k@N*o)h=xu0ivf$x2 z5+?TRqwx7U;{>x%&Vxspr8|HrYSKrN-|W*8){*Vq^=M{U<9==}@Ll4|T|_`ya!1Tn zEuyNP(KK*JT;^B71QEn%H{(r%G@eT|RIez}ECw#v z#%y|8tyM1oM3!N;o^UuHoF$V*7jIlmlKpKf=f}HuK$Ic(MXyS`THM$hG}EeIWOZ&$ zx@eIFVGMD=WeihF^kAJzM(uF?%JUl_g`>v}UJZ3=tjYZISIVu+dVl`&mCtShP2;S< z>M7UP1=`2;ga5O8RiLtoRJK1^p5b;L<5cuvb(OMu;bO{%F3eAi-dwh|h+xOK{4x6W4#?)vh&)M)b9F#xiCF$8J((@=^b?&;Y|Lz$B&c(VRC%J6 zwZz&%Ti>B2zZ|9KU4Z;P6M-KM|LY)SN(V~3@6o|T?>*nk)bW>nPE^rzW#rk55EVVA zMVbZ6u(A;qmvEsTC!f7%$$tY&GqDaMMy-IX9aA0U@b^Z1rO?O!y&03 zxz|wDXxGL5C54SZT>%Tsct}cCWnQyFAR!0}NK||bdk2LdOtF?$>&xAU>ww^0 z5GUJBfXKnOHN$FxNzTQB&usCIum4KF87@1TMq4$x-8YJ!`)o;3-%E%n@OtR|)oV9z zi+NW~l`d-rcp_U+T#AamUc~=k*vU2&gD)Fop&&PnX?~627z_FgscxPC%hNrn+V=#S z!!7s*__E=y1l65Hcwdgt8?$Otg@OJ6{?VFHcY%gEh3pbeKXlOK!;Wx1m(`Vc;QEy? z89MN*EX97^_*&fW#*5FMfuoSGC)8HoqHeexK4tOdy=fHcVCChEyrIlZprNeXNcAUv zU}xN?HRwt4dC_I4DYSNB zUd!3oEF=NWW#~OVK>fJE*WitgwLk}w5ZIn4p&l=L!P{0B_e*(Lir4fisFCZF!Mb3o zLOz}kmfK8tkelN?#*E`N<8< z=(aD_1*MsjelIt?tS$ZvI%})7)uU+CAgVai&U~nsZmUC`4A{q~93DX4h(g_RmZDZDnU$HsPR9oi@6Fz>vqDlmNap{AsfLGZT%R;A zJ@Hl97(DTWL;wa3cmGvF1sS85iy^TsCk)=|>?Vh1q!?LTM7(^kP5&FMi~o>#r?#4|}~rPv_{7cAwzV!r{@VhZGov8PVjn4I)gLI%khP%|PjiWUA>2M-{c%Dhs6P)PjFqIsksgQwU z`sAsc5T{0afn(+hB9Xo2mVP8b!CkwV+lwUQq|G55_W5EQ4U7BCXE}OnMPQZ{zW9Yb zz~1%enKC-#qu32EzV-sRk0Hu#fB2iV?JJ36%Ep;zuI3%wjbD97YU`r2Nba|tNP43< zJt~@&To(tuNmG*`wtdw`u@ejTbYk#d9V!WRlU&9;=Cm)9Qq@M^wkZMKC9-pUwiisF zhLrp4nKL8;fsNw8-@=e42T!e9Z)r2WgRH!noJK@BeUP_-FfRLz1Ur9ei*yTK45(pc zz)&78lIg1JLJhSY$D&E^@G#gyT@3cP7xs=D!mjlL0a!CroC!SvC&NsB29?OI{(mg$lkI%e<43fuEB~U(+Hvd#&isLh>W$=z;bJ*|OO#P1k_WkIMGVH&Rjd8l z;>LzZDFh7;RAlHXqFOQ7(jZ{8%?rmX^>J>l>~vju*(0VRN9#PspV^3o;)4)hm0Yif z>D($C2n3Hy{_+zat$jy@Q};#WbL+hGv129#L<=9_fH-H*1c8E4ZE@PiAW(%Y_H-R}0I{4!nPsdU&F@WR-L3{RYKRlr!ra_bQl2o9 z>j?ac%6aqHLsSf7Xtdo$8Iu4XY{97drpm1JxFv_W5ut_kXWv#(3!M``<5)jCxxHkskr?m?0D`a?~I0Skrlr# zvHk|H*a(Cdd^koY)n!S43MGAw~5BnL#Xix7E0+kdpKt!!B9t(+HG2kM{2+3bLsoZY}#A)5}2< zRfO`0PoA(%3)tE9b5V6N0=3Kc{9n6lRAKdO!1x6bjt5;58|Z4$m5S<+kc4r z`SEz5n{qi8;&Jk4l<;6$cbL}0wNayJkpBtiZZztlH8=tTiGArxZfm*x%prqi(e1P< zqQS9erQJhYk3nADu8V3LW&%$v`1bQXHijFc+0okI>TP?nf3^63U|=d+z&qjGpG7Aj zC;+e=bw@M(L2u;)MRd8>qzP_MJp++8LEEBR4MoP-4D?(Q3! zzZehmQ$zFqxY??VObXwTLMyD5#u`klErKW__2ao}0-nktQ}2XEeFs$S;6dPYJaWo* zO+{))zY8;LLNKI=OjD0cRTEWdxc+YR#+4BUAMnBc{*;nYDfms3C*KmFJh;hK- zqJz*GwB85y3BK7K6~88Qw@vhMCTS0_K^ix_%f0!;OIqG>p5AK19=KR7Eo^XXRQCBx z4f#Ef)MYp@ht9uaOOCs}j|>Ts8N@&&A7nXsSYio|qzD1!uZs}e#)3a{bZ)leAcDb2 zStZj^iKJBdbfKW3?+A;l{X+vdF8c=E+*tG#vo!hS13T>$m}$VFfp+?6?y}9fd?h}h zNG7xAyvor(-4@+l@6J!+orDWy!ex~a;H!nVA}krl(7=NJ=?`Y>Y2yM1JqQm7n3iDm zg*Dx*I+`Ae+VBQ9;SQy@@$RftNDkarxNLBE=6*f@BQ8W^fdzC{n)Z@d!;SJU#$%l= zsT_vM(^m>#JKhJ1t$yEmi0?vkih6WYH}7%V>7Nkiq)u?=jkJp^8!OORW4#(d^#*&d zpnslHp-%o8C6>Q%TfT|Y5Y}}t5U*4X$6XIgJ!2?hAU~omEV2Fu(6s}ZcE%@vzoN28 z(|)7e(iYwj9jqEY{Fwg|T>C3VRGcyM%DUx48bZXrz1xv+fUzE0PUjK_5G8I{c0xeu z^*13Q0k<;RC-MYjmsTrs@My;d#M2$WvSXA!N=Im&y=^>J)I~1CYO0uts<0eLU%VK= z7R7L7NyGsKxNa@D61=r}xo@^;UDRYZvygk~3JJ&_d^b3c(8^!ATC$_IeBOJcI|Z=} z7v8ePdqn^REe<&rf^-I#`{!an_H#raQ2IBz2oQf(4KkGgHMgY!F1WamD;U2tSUeV^ z!x(k!zGNlDh8b&Hkd^Q!K0qks6|QXKMyPoU!cIF2CCWdBxcp4py9|!a)>{hHsqv&X zisw$c;xLx8Uh1?I5j#3oq}j;^*!p2g*tUeNYD+){mR6l)Pt&41MQJi8hGZ73p3d** zaHFVh0)N#_^onor;;LZ4V;j*EAr7ltu9hyj0jaqIwuO&Ad(m*s0C#6ebX4#Lyob5@?I(D4fXO;iv=Qs7r9uEM>WG$XpJpJHPLP2=bi&{bGu}o&dBP!028O4_^8910S|%`)A5CXb*yg!*Sae zIIvL!nyG2ys-Pkfsldh~_!H^Y-CRaYF_GMzP1uaI@gyiqtCsQ zU{24U%RGGcXp#WThvr3PdmV`%gKTMIp%T;%O3amNOs1x$?njQ$fn_^IqOjZWk#~N{ zF5kSp{m+9bL4Dbue&H1Sne0At=L)Qr0^u_5{UNxtoHK3NePN~kmBR3}?QMh5o9PV_ zr8VXqaalyNDazhFV9Ecco z709dO(_aFoeb55}vQY`M>L15e@ic1 zQrB+jS?uoeeif@XiqYC*)!*}R++k-e#;L!(vh8G{#^0sEjDuc%0;d0j4mWRHU**7{ zt(ViU_7q604XNYWR&d(5U=VQlxG2mMC1EOmQu_KRTP%So=zO!!=RI}2CLo%|Q0q98 ztg`jAIRMzVmNOIKg0t5al`LmN@U@Af5r(Gi%Tt``8bqTJXfpXIn1-#2{`I=Ns3G(o zZ-1}f$pDOi9k6F*P=idl`VnZ1h%^gN&+N%J{by~C)#$xA-b)ta`+jRW1sRSA1TAzcB8{jbZBzi`08;JWoA{x--9?_NZw=NE>mYOj_v3*H!KL*F zRYagFMk)H!ZeB9R^U%C7PmcW1WGra5v+|K#`laX)Ke4nqXALxizhre_ngE%af_c|H z$H&?tZd=s!_;t1m zgXN!^j~5MEkP+;)8~CGf-@A>{W`_ioNDtW9Py%|%6Bnquf)bl zFx6v;&-n*@wJw1E!SwT_ia#}wTd6Qd5QZ=_`J_JkXQWot_rakMfJ1UjMgQul(Q zM)A0`+-Hn`fycP$!cF4%B%L5rI^mTh3NjOORjM_>22D@~XY~6e^uC-pVq;=9x3<1B z0IaGBd4Z%CAvRDQaBD$`82Hldz;2Mrs0JM{lK;5M3Pfs~)s%J%Mu=!Ca^_gs~)Y|ZeT9;YjLanetq)ZOB_$$?xi;4 zclj%K7Vkl;A_I4$ostwNMpfk2C{vL>VaAumkh=cBG)vR^N!vb3I$LJ#r6& z>o+D&);C&4#t|R%y-SOrvx!k&@4?mNHvAflJpbLXkmFF3V?VkqpwL)JNrRRJO9%rC z%!R?l?(Nvzb9egi;#_gsReo4ebNWqPUtK>hrl|9=y7g29y58s$M^Iwl9%rv}`th&i zLOfOk!yCHUk;qQUJWs2+>6t0oVvCgosvsKghw0y>ikbIQTe<@>R*M_mO;jON#fKg) zfUi0Y2?+_OoT~%00+jM$`zm!ra_CS+jR)@5M^0Y;WuI?}9&dd%zq3em{0p3zl#}ae z@7a@H&sZGEhkrj<$zSo+%ftjU#-obhEU|Ds4R$7l&X((p2e!j0C)dhCyU5@f5{ajT zj=bhHUvb0nmT&yr7u+C~2-6j1>bH1-#w|uQIv=m2c1i5Za6v|MijHrP_B_pVx4*R# zM1hmlrRjFNDtGTenO)vZkjEF6+6=6P6?JK}2%{cfV`rwnR zFIEvm1#TlYV@=y_q69gSl@hbs(a65x*88|1&Sdpd@z>|Kn8FN=R_b?gbIu1E_FDGQp zk7_J1%O1+%eMgE2>N|{MdwNdMjhfUzt#XV_W!E>RD^B6eDLQ!1GR$MYRA*;RV&Z_O z0ZEovoo$--e5_cLS%}ATwm(PL_-0v!R&q5BEjB{`+|49VtVRQD5%4B5U`5iz(5ec$ zr!4xm$Ge)&({JbfC`luy6|b=-)bI)Vg1OLo7z*eoyP0-gELGZAy~Z@7WG<9PGI^+C zwk4-px3xyUlTgQwFdmFpo<=(E6v^ExDIz3i z1RYKZY_O%#_IU73RNlbb;(j4%u@>>&J4>OQ$0mEnz?oJYZqO@OHpk})GAil%$4aRj zYAl%3V&BPl6h-ykyyxDlJ{=YhOiU-OTe)%`rnjY^zOdpNP^FrC<)%r$7oKt@8?Nbd zCVLThir#1bB{H=JRHazH&4_9oh~!E_=C=cmHkLQ@>^vR_9i!cAMrGf2jyMDuM__z8_ zY}_BFKweuj#6L9`so&$E_74xR5UF0}TZX{8n1rjv5aYKQ=o`pY>~z#7W%JY1-;IeT z(qRw+8X`6kviusyI^w#AUSQ{RRNMP8Lk`cq_5r(|0Tiokd#KZ8#F^1`x9NS>wi}lU z1a>2qyT$>@mSGPzEt`W<{A`UK6X}g;1uGL#1pR6sZ)ShwsJoN;!6ke5IClH#Z%0~o zo6Sm4L%P>t%lQFDHAEnyLIXmj7%@roQ{a?TJtus3q%-*xh2<)uK39yvXl) zm$DXc*C=*od5f%jute4hUE}*Qe3)1`3KS)@EM|#)MChl_R2333EQ;}64}U*J!sMQW zbGCeLDDg%@LJM&vbz|~naXbmBoG`@P%8m))ioeq_uq7-%jtQmZxW{a-x}#K+VSfDJ z4=Z5@@8$D)@=_HN06q$#+g!S>llJ=5-wVacUku#{#VU(?BidY{lZMYbnGl+py;;hg z4Y*%e6rE=PXa?~SFJVc%=*EH$964FBRXF99-$p7;59f^Q{ z1df#P@ZUvP53m9tri#54^5;H01+~eFq2a(2jBk?gJAlO)Ln42Ep>27+oSZcyd`EWB zC`>&w&1`5yA-pN#A@?>Ynj_QcRr*rWRQua=Y-v;3#foXY_uXk_O-JGc?3CW=8I%J61SVlU{SkfgCb2Ivm}G?2A+1Y9KjYHXH0)LTK7))WlV^qn3~4L{`}wCB4VHo zqru9ORbm$+Zm^#7{S7^F^~I~?Ak6hxS!;Z?ywFj(CE5 zpVKAnXC$uBK^i;m2s6yB=2JXH9JXU=EO&b~wPO+g^_A(ne;ahszChsEA z=DsH7N&yK`GOr^N<1EZbN-&awgXgzldu;EF*#TA7oy3L-4-CL35%@Tv_N5LCe=ky2Z6*1DvBNhU5z%tMLR-Y>7B%x*XY0mQe*wnWztV zrLt;Y5yS>=_w-1gqjqB@cdIbzXqKGGmrio8Lp1ud-#5O%{l@NZ9NzNyboABu3Pvyb zaFC?v0HBj@s)wU%}+g|XFW%XBW|M*YN=s-ZA5T%=uf+^bnqZ;ETBL5212DA%e}j z`zV&Vt8o(Z_MkqG82gyqRyvHIS{_UgGomnS?Nsv*76`>!)D}5L@Go}8f8FUduwoU)7K?8`pTiB5L1YTlg>rPRPe4ERxtfrOAX2fy3EOl*(+>JMxw30q zreotl$!xL`5h5EHK&3g}W!x-~n>+9nFD5JUu&c|G*kVk=FS^-EB!(EkuNkdxJgSfa zmptMBN(_fdP;(NYSNAZwC287j5QkhVSEaqD_{LJj0^c zImtTH!k<5=LQ4Xd3M1&E*RQ~d1gSC;PIJ(4wdr7#xpvfyGaH>-33MUp2%k9e7Xcfv zDrsJ7$;3hginncC8uRA?A9@=bwdu9;yv869yvl&12xe@U1{W?(MPlzolrGs=OQq(QREnd8Ni0-Rny`#%i%@$_8foGB(0+Q{dfYtPJ50Yl^qAn`pbVr{ z4v3jhTrzI+XW*B>MV|c)zD#B(s)tN57Pf${`}M-P_W0?v^K8|&cEXHvn*X4TdB!vz z9Tf4;E0R9<{_2h9bCEg_;@4d^IWu)JDbTPHm(MEu@;++#`LmMLmY|ba@7Fwp`MNCx zTpHw+pZm;?SLt{1M1TY^U|AY2*}R9K0Bubljc|MjF*G28K^cIzfy?*1x@GlwB!L8| zYhhs~r4K1pCxB_u=t`gN0A<0zizuyjT`jxD>Y_J7KyzYv=4&3?9aeM#1 z`Z42eXdg<=`mjq0yI--)ixo$ygS#n7a_W`SI$vvop47}w-RFiN-uLt#-Nid`FfWud znqI*UY|oe+Hcx2rEzna8A!gbw3uf`9+SK3M0}hiJ5kUEYdn(YDj9$#cGaT`JcCq)I z2j$+cUA7yh?$(8o(u}-%5;U?}Ol4aJZCDY%oj0`i(r|t{XP;VYtfGYwFzL!=`+1g7 ze^F2RLr2TE;Wk&@x~ahd^B#Gc`p1FPw;LVNa$>jD^U}HXVnBul3J@#GE@;gmeDo9I zeNh`;)Fmh*Qpd#wE3flh{gV>yelp$Kxaq?m@0Kc99nSj{5-}*krD*6Ho~DpNg-MP3 zmj4cC#)EvxS!sNxsS=K)IQP;}u3XEybpmeI=yL>ss{>~_G1i*$9!IK+ELLK^s~i(e zIIKMUUaHlB9l%)REo3HZZzymxO02atL?-N4T4qpYj6&)Nh~7n-`(M$#HotK?w5->9 zUTl5Umt{0>$F|0pTG77V#6P0)rb}wy&$OlZ_OF1bupeGL;pyb|v4MDJ7oow#^^z@EcDaiashI3Qvz6Q7L_wsUJVoD6NJ1Gi5vj+<*X<1mEm zcA%4}!b8%>s;T7=P?OP6R}10y?YjHy!{rl4Ka!yS*#Mz!PyOY6hGN35 zdV6lh9T!p85E=K^!clQ^q>sPCpnUHBaMQj&1Z9u z9JIZcC_moU#=k6`1?dIipE0OKq;IuY9<6pJWi-J_wB#EWCzGYVr&(($&UXC#4iTOj zBCtGXL~0~`Tb&e@=iDem#{l`xAV+P#=66`yT25s~E(XaaeVktvf}Qs}etaD`GM64n zpq7;Gw~xxo?aF?%Ci)bt-LH$-I7wJQAE1Ib=XKUJFv}*`;10ze_G`7@y3INB(Y*7a zWC)m~?m%sOxm`1rLw&<&`H$QZv0mdaOnh2|nchJC*M}KeSxueXCcF|6ZeFJ6^ZGN` zJ~riZ>%>wm!v5mt<@-5Zql!O*agiqdBckdYG7z_o!!~oSw{VOkcZkR!?Q#NDS;nY# zdMc0`;Aq9Gk|W_h@E~?S4_xu#;(BAc>e%ezk^KZmCX=8cG|9 zGvl0X5$8r;`q`WetVU~y;r-*xhgwW{&^O|~+W%>>#ePkAYImQDL(h$4x^imb&-k9B z-<2*tK7Msch(xh&Up)%ll!##Z=->|cuw~itxdJSXW-N0c%S=tKm@YFWACD2bR!Z@F zsCat+&tLA@`f9uc_=3ItO&IJ0k{RBzyu|vRD76?sEi*J8yT|*H(Lg2h2JkA?9<6aE zA32C1hzOyPv(6i(ejZt93)dy~cRmljulFmI`>#zrT)f$`@A0i@G3kw$Q`z@?3Xh7C zRZ||d&!lOriCRP)-PdT((Tfv$1;&VEhIXEDC8~5=Pocf{59jCX+#8}+HDTCG? z2Z{h|A~H%vxc)WajrAHd!om5D0oaww+vjzhxxxhMw-07d59XCd6H7wFKFF&|OG-zQ zEj!$zj&XL=-8A-Jv>YWr7Y=Yf z%cEq$H1(VZDPe7Ks-kbD9!)U`eaa~`Ko}5ijCbImTHlkSY#U-p?Eo6vJ*`JJ1+0=Q z*OF*%u`>@JJ$6L2NGsF>@IZ>j&pOqXG}-s$)+7?FZAb6W+_G2jl_QdO1y#5|>&xVe z1#*1F5Yzf3z>)7lY9oLL$jaIR$f?mFU!>noTr1I?c%mB9$_?|ds1hN|3c%9QaJ5U! zb*_NB+WKTAM5U;Jp-tB~r)rlW33Q`_ULY~SA9m+hI>*Sc^x~lqVk4MM1@_ru16GGB zBX_=&47%xb|Ll?Sw*+z&w!EM@q7NgArpt(80z}^h?}(oM1_zI<{~Qfg*DUt)V8;p! zfDffE4*Vz0WxSl*#4?a9u@kgUiYw5<9NST2Q-fip!$eKuGI>TIuPuc<@zk!-GZT6O z#sw*ZsqN;@i&EI_mg?*W*h9Dp5B{WYwz$WGBEeX8=VK=5cdL4Ap{i477@!u~iijP|9< z8*I4RskEf~oT>2;ya)zn>wLg9kK1NhtewTK;GGPlX_`@40R?XsuY^`!Bo}?min^F( z%pqTiG-piRbVCv6eW+-LyP^R1)hfQYGV_xs^3sce|I5vi{@oF@)9;y8ehFmPx!Vd1;w_}c%?08UIBC197|`}Vl~ekaK7nxt$ddUuio=MwRCvXTj3~|vTXk4bfpn$YxtCDzb4^U zw)>7I%oy8ODMq+@%H?OKa5k&-fUmsG%h3%qY3h#!t7LHhYn zv-j~~%AexLyWawr0oR7vWD0v(XDu`8<#`1*A7aaIP^`pX=1cr|`5Q8ll?bH8sF)!H zjlRWuQy6e~wxPZm$5y$ft0JmF*8V!gqSwJ5NtZNiVA#dZ{-GNim%SC2Zd4iKt%C??yo zAtKK`Z1)Ndh?rpcUDEY`Fmz~tNCiN_==QcTh~TQKMHhrKbN8ahIxMQ2`X=QpA8Kqa zIw}~+gLsCVtkSOMFuA_xrv$2E`cjMs@~mmKoXV~Be<9`g{!6_E3vu9#U-IME_v4cr zPCtN;IdEDh__id3ANq?MdV74dYq`g5L1j`*PXNb7H;+&XPl|VxK4Qa4l6SbPe#Z@0 zj5O?5sbqnAl38vLM(_$@z1aD|SvL0S=lpf(hBC~!Knd768HL9a zT9KhmYV=`I=74~pFX4Fnk^%N{=v8d*58zYEmP-`$2~K+)12K3<03)B)`&^vNncCA2 zdXIPe@5vA&PNttsojuyY*_J(H&qNfdPeO7>0{k_XCTwG_F}3AXzX|c@ch@LnZp6_J zyB{}NwU(iW0S{a2jasSpIv4Mq@e<5+!_1rg%G&}|Lb#BQyq;oTCbY%6W^CUaKR*Br z4wOF62iOnL1nF7v4s-!-_{$w%$+AXjn?5t7jX5)6qXA$aGTML6Mel02D$HzUv;}s7&!B|IG;}&JznyTCLkL| zyV(TsIgq%OPkuOvxloSgyrT{- zF0O20n@kH4;^j3VP+a0u4>m|ecB~;ko8Wz}?`_7E|0_EBQ>Wk!oa%Ji(>-ZlfKn= z!!2ErUh!BG1>xX&H?9=M%EE>=>0j|tVjrXx7FA?{w)2htwgnyp+Pd>na199wrY}~p z_VoN4M(WUZ+(0?B3x)?#izz?e(DPeTP#kB3GSztF!OFA1WjyN7JtE;76@?^ri+# z?+qqsJvqF$g$nHXXZGNlujeB6=4ffS1OX?|>aRW+3tWA4Vs|SgRr{>jmr_YV^HN{`~`+&~y3| ziR09r&V0$&VwpTbQ%>6AmVXUtMQTR5^S}^OkCBa=L=Y=iQ+cBRXy8gp=tOVI6=Cv>N3kukGc00=JZhEgnW_GgYAy;|lxxAFVaj(i$`_dXBe= z(u~jL$G;FrQ_!pz55xi@h!~hOzc1!+K_F2|i(7PVgb`L57V6XSz9w8Tea40=^c|XB^gr`EKl1lH)zv*PJp2cBiv1=mzja{Q_?$s z|I^9ZXTFDznI#o%1v*}Dt#XEH;H}-xmR3D!@Don>V@cI`P#HsaJB}4LynTy{Oyxzp zyvA~lqK#!1>LV}-;*2d-tk)VyxqdSj*JXhNG3Tl_&gc_mVz%zL&;!$@>FDX`1clKU zq}WrMv2=T2NVP1bcFoU-!WU?vKP^9At=RDjadWTNcNi{f!kv@z%&c|Q3N>rM2Nv46eVG-Tuv7QPIoeEt)Hui$x8Y4|1{3kMuk6+Ha;<9Xr+?Aew& z#Ac$kA{n?BHlV3DeY#!LMR!l&&J<;zJigTK;sQrRlo->gpmMoc@h0E@>Nk83wtyrSK-~#geooGMGM7SFkTKguKJo<=| zX&+XcX7D&H`s%#WU`{^v6cQy>iQbuyB+F4Pt%boWje77v1cI?2@%!A(bc3V zg^vOhyBEo(e$l?Hi0O5DoS3J*IJvnYf{KnAwi`b+?R+)X{DYqcp>;y|=T-(FMc+f! zJd3!ZWjskqS)jG=SC@uyg(BfAFc#yD6q#!msaaT+ea(t)0mrScdI+~L;Vz)(P#4l- zPSquqWN~k(P4pIR(*dyBPL<>hsY#r^sSwF98xhz@hY&@%3sOj&IKSAR5Qe4A9zhWD z-f3{y(7slWu=WIYzZ>uWFb4bQm75%v4DVb(e%yilqKB$iOz+kH$*`?~uT;+BU!2hC zeX0Lrsi)@-5uUj6{=#tSR-ItFmh>8khEt9!MK(bN2t{Z}ET5lUM|6VIWbw9VEzaO^ z3+p=&{fRS6Fq`cDiaLO!q9NSNu>Xfkox7H7={Bg6f!}fCsw+-}FpIPPmm>)rZp2TO zx@SqYySR_+HBFQ)$*%3|u-C1;jP!ITea(nT^Vfft)1sfr`O!NwKXM$ZX71I6>UV$X zE5JKpjQ$kNvmAyH0DxA?*K^U@p2x%G28jYPd}1?Cq^(6 zMc-wuKFt?FB#n^jBEL@s$u?q!@< z`s=CP6<1;e%bLP_yczlgm6F+m;t~Le*#{Q%9I6znaNOz>DCQ%h;4rFOK_eZo37+P% z6z9D26!N$4jK-{4Lr!bs zCiF@i>YngVTkv@;PYp-M*rkO9#BOT1@I1iT2as~SPxbM>b|xn9%D=ee1)$Oq7uY#R zRR+XzW(DoOAh@Erg9^4!j45*O35SBFfBYd!Bx+~`f%tFNQbVrW`QVz)Jvc7l;i?CJ zSYIWMwCHJq{b__;HZv3WvI%}%TQ0#~?za4Aqzq+>6Ild>Qt!0U4Zzv$Qx-??iEY=6 z9aUAE3Wcq2K%lx2MM&3?rL~Igry_Fk1Ghs!2lNVv4&;jt_l71(!Jv@T`s1LqwP6Y( zg}?jPNC_(I)1`|VQq;2dj?5qmw#5v&0u&J0Q>Ho!m^#A9%}mB2TQ@iFXPjhm@t^gn z{?F=*xKAjq2Ot6({o#dyr+-XKO1(i5>#3w_960rAmuoulOpt+3@W&nc$4+%PKcgbA zy!y}aB8hsDQeP!&g`A(s+3fVv_}HvSA5`-muZLnu=MK1287T=>nOq)NMbj6otuYZs!%#8db&9?8`LiIr7Ei58Ak1tg?a0cntuUSJWVJES|LyGtYm+ zDZgRNDB>WtZLcCM)MmA@Q5reXHW?IbyaYX4UMF>L*?d`lv_m4oVIspFK*WS}&251O z3o*RkN>&UrvFHSf6As^%C_>>QquZOnkfyySWwo)Qv?=}5e?axY=T21Q|G`9*Do0D7 zVA|rOA8DOsQvdE7`2-1qJ)Zrn@xKD8}sHU-=p^@>H3^x9Yd8yPbj&^zOaygP5`}Rq+o#TBf^c zCjWGg>fLajTS3lCR6GxN`v6W^IPmWl78XeyhWB@eAXw_|LaXE=dQ2G|RipODU1k}J zX!)#+5AgwsyllZrT-=0SdwP{boyg6eZ$Xwfh9EX`?u1hRMrDa%9{H$VG|gupi0cAC zO~KZUoT3Zq-8xZw@&uQa@C_URkcQLH$+bga+;E6V(tX{c`~1!F1Im0Y+klCnaegMp zvN5emwz3gjOroaN_4^VMD+#PZ;=4baD2VU#l2eT;V&VRwyA7&IewOumicf=&A>@x3 zzkD5}WDbGAdz|=eJ@*bD?mK2}Yxyk79kI}*V8$Fb+bsKQ1UL+pg4C_59I5id)DCMhR+)thL`quv!1s%(jZ>p zF}Bi);Zqz8YFq~Ci5tjp+3}rfwsP+l?vCsAzl~|oQZ$N)A@_Ag?lVH|^9n7&BEs_v zv)QKzgk-9G{E0kMq71{H{|l^0uCpgZ9{@qtkZ8Eyns&iFf*g)C8Q;qxX!`W=dk75G zq}1%Fn%yP7_aMv}%r~QE z;{x@5FcWZ5A%Yg8m+W_Is3ukq$)sNrVS!D{rKG0~4#R_kr#?$38Q_&@sT-8>Vel7X z3xCU6`j+os=RO-b>+bIU@^t%Ux%Nx@<>sa>^0zQr7@fIbdd!B6UfZ(QEALtcif4f& zeZL~Y=ziUq3OP1z(uJg?r44R555=ItP(G?%jn!oe9OuTbMPDEP2Efe8NWe1SOGO0* znbBpfS-pSPp+LFtIwZ2QxmRo*Lz6TbM8yjG7#Y7dlVRId>V4{p+z%kkF`wQ z?4mCx6N4i5=x45YOMPG=lmuS`HG$c8R`C07Z%u#Hv1}Lko<@9n zl~&wk>p#v<1pv*6h&aIhTLY2JeHBX75#?BU0%L|il+SeSI1$J?!=Z-Bu?0@$l~L^1J#ld=Oi1Hif_T5~;CI-hXBce1 zgZ)^p$%)1H%b+U}YkDlm_E`T@(}3&o%vDzC2OP^Z*wt#sUyfKUV~F@nanOhScFt7U z)TGJXF(X(dYtJVpr8rZ=sK(H(^-ruqbo1vB^)N`q{O`#_xexzv4zBh6hkAZ`MPaf8 zo3PUsz<{wgU#Y_hOEXyGPSEhQ9@Xj*2^B37U7XB674Y5i!yVA(MpVH+ zwe4i*32WUBG4=nae)=_YTOwSZVcbS%$OP@9qh4MY!Iup=x>q`~yU8~D0-Lai=P;>> z{DSrNHi9Jfx3>-uMXOX^dSWD2uJcs(+D*XUq2aVOPf?6%|KTzG_s zZLICL?}aHR4#XVH5*e5bQdJk2dPl=VfB4;;zi#Z|)W#HcsP{djpg4c2YxAGz7wq6P z14V3eCa7UgkCBQ=OO^280=oE0F@B`!4_*_GZhuRuoKRXUm^Z6FtoaPn~ZEvLN<+M2sp! zNM7w~lhLnXha$KXEsp2Yk7MG9eC<8Gjp?+Msu_)%Y->)TfYndxHBS&`sZ$2HkBFdm zBHXE3&+1m=%M#x*p67GOJ%j=Bv4iH`kt}pj;3aashI%d9n*t4^{HY){9MRDs3AWMS zVPdx{si~>8+Ys0@=M5jFuqTA-@fct-NlE0rN$}VuQ z8bnXl6l9*k;TcEN^wLhnD`Lzj(}J$!l6#^mt4n8`?tfTV7eNzvUg9!MSfDTkx00My9-wb3JzG7E|}k zU#BtCmYS6D8jZ3S=Ei_oscx`?QhW&i&hvOj{WII=);rPrKXLpSc##0k_1^^NB1(RH zU!Y=X0rEF>=8rGUZpJITiO?{V@k`Jk|Bhi(x(;_UJ)#Dzq-!HpZ_rU`AD6wBxSxC* ziG|}5@=;)W+C}8KKnHWFoLlIbOLIy*EmpX?Z?+MW6l+0sdMJbia*-KkHl`y73U{tVAweKBTcpX`Tf&ZV@s5kGt~4c*uTR6X#G_)_F}QE# zH$SZr3jUT0SfOqZ?yilYV7=paSh~%)_<2z<^ffFr6gtMU(R!jrh=#$5>&hAECk|Xd z{0oj9J)-AaOPHMw{;*(}@9<~O2Xe<-6q^PJ1b;z1?eQE74qS#@t4A8fOd2_t{EMLa z*fabkMVJ|jos4chF40@bsrP^9kWd-_EFAi+GY*-bhph5*T(xc!MmrA^YD!Hvivbtl zPYv&%r#AfomZNIp`Bkm2-t&YQgAZE)fvG;-9QsaiM8BtFPgY4K9W zLZ1(GJkN*&n0y95VN8h>Dp9?{i7KxP@AxZ)BK>X$vO*KOWz7R>)yR-6(v&bCmNTFb z#_1=0x$o^D)Fpf#=&a#eOlKH=dAEF$abdf3dpbG_h2Y)ZyX1@%(7wZ@43+Py1CyX? zSa3J<;fgXX@=4243Fn*9O!xevgAe*T@-v)Y*HXBRYaQlEPtZDXVzghV6_Az99&`zd zh)`9}c1_^Oy$l;)Gf}k>f}+3`wl?Be7Fq-~Vi-+F&dkbBf#b6WB%k?#Y=b_t&=hhz z+Pkez_~}THm0#=3%nXn<9D@ZAxQn*B9{F;)c$L6=>Br^oRL2RN!ZiXD@z3%|iugD- z!L$@rG2XeYTM$bU$)Z&=#!~&6U_!1SQ}r`Vq3@XY##qFIn_?sK;reVB_?}wk8{Br` z*CV)S7^B3VvUKg>ozlT-y1&{woT+$j(M*e9N-QUIte@BVK1S6ag3(fIl=835AJ*?Aqp62Z4v%3k4-50H`h%6XG;~>7jkZNvMoOp@hiG%Rh4+6@NJ9 zNT&9`T;Xz&mTqg@G|4LU)4m&dV=TjI&ch5O6m>=9&c{d^_yCGsCylP7w{ zgg6y;P~NYBfMtCPokUSnQv+9f!-wnX)kB){L$-mo>afi0_te4q0`l5=;*TKV+Am2x z?3b4`;tjCkMxE1=-_b#0#kTrA8ne_($Zp%P2oF_vTIaT zaGhvF(WS8B6Ece^qrMgX44&iAczC2cu@{%?`Qkq~t;FHZhdHs5HD31?|N8?fv<20w zLQ+8~Fg#ox8Ug{s=DXZ-)Q$^|GbahEcCMnD?&E)!*jyK%m$O7=;6r4HLsri1=4A>L zPc!WRn*9$OI=ilm4WCU-b&n^|;6t%H-5CG)#$@+{MZFeP%5Bm6#|;xPsx1?gk&yxXBJ~3e*bCGPZ*&s|v2)W? zGQQYcM1N11;mu`n@cV+pLV@Lzii?%700tIX{%*@mso&d!fd{r`Z1PDV*N zZl5`WY)N{jvES+DWL2i*5Uoi98DDek@un`@&V2oHL?H@V;qWH9ZBFsRY6EdZztlrV@4}{S%F($|--amcp zN!14Vhc_~7Z~`&j-R^yk3i`+bA-(%YlivyKIDJn@BU!Sv3ET=RGy;tv^3vV^5ulSm z98(r;Y#eTjfrGMG9c1sL`X~YUtCUJ;D^BwY_y!PKAKC7D;m=l!`cTG_s7 z-gJ~kOuPAb_gY}w;CKyzD?@$h#q5axxkj0{xlczsWW!fE2qb5SX#6;6qaqYz62|== zLV#le`|pMC8t2z(~AQ7eq~ ze?;00st*4@m5gV`)@wx}E9!rgtgq;Z#9LYGFS*uVYM4_o-a*k>M=w2loL2w1&3UmR zP>69b(y5H+Yt40j`V>Z9{4t!>QD-IfTiy~oLlTVMK)?wA_oKvLzeAx1falXz^RnvI z^FvTk&E(>zi@)9up($e_emx4*sb8OS43N!Ly}L-4=%RlmBC=@zG@27{jQ6Yvs})z1 z>_1cz3*7GG)1zG_*-RgKfth*4lX1-~$>z+fLCdm6`~9P%a$~Z6nF}+^H`&U8I04uf zF%GPwGdi7bIEkFtBsdiBub3d<`9P|Y5$ zf&n~%*3P+5WqC1Ra9+vbw<8A%vYiKJn?bDdP9Igg)^fUG9TCdtqAu?g12oQBC&H|< z#6t%`3*-xS9`$Z@QXjA@J`Z4wd&QNja)^4bpA~I5qGmNw2ZX=An=UhaC{Xgd&JLrd zprW!Zq^c_K}i$@CN7c4 z$oS)*>dZrP`LU+Fd$hsfmGm$sb68yXjT;)F9&#HnCZ<_xGZ+-fC zMeMWj8a^*2hB)tkKV5p){)hIxI;v)8{ZB(V1jSwsa#DM7XIUL;Zj{YT49|`+B+@g#H=1aOZ-*` z_57p0b?4cNioduVx9htG7lPY?LRie_qOcH~%_Ql(`y1+j6Y71|9Jr2ju}t&1=gl_Ik)nyx0$SE%&s8B ziYzn%=H8BqU?s-c>yEf~%t0B}QF;Lz=MkVK;IpR-b_XVC46^L*wQzA@mrQ z8EJn#0U@f-*gDnvV<}=3h83(VJF5~*i-5{tWXc9PjmoSpd|Tw!%%(#TTsaBq&A80{ zYJa`@w51wos{poI$T~P9Eg8n04f~h{OTIJ+?-keuWmYyv`K4nejr6BkVolk<#vszd zfP+MWuLx3IJ8}3dly2a)zumOkN9eoC_abezoDLW>>#+tUPx%#GV1*PSBa(>HaA3iV zh=_|DQ}SIk1>&;z+1v-TGmM6XcR%EJJ z1?EnB7aOfWXP_!;@EzckM6v*7_O-_N?M1D70T5lGCIRBY{k4n}8=gtxjE)vzoH55z zf*7F~w5q?RN43LFX|{X=C{F;eH%k%P=44v?(bT_03gf*r8hYvs=3n z)Cl&rZQD&gaV88R>XKSGEv@pB7P3{?is$dIZwtI(*-wb>_LJ}5O#qB29+Ke#Yz%UU6v5Ge&XGqhYZ$&r6yHCJYGV zw*6YyIP+1_koSi!BcU-K1p_{DC?_4doXC>MS<@h-;4jQ7ert`Tn-;E-0 zLZ_jm?7(S?h0bWkcoQfcPfV`c4}KVmN%wvnK~K$y>cr;@MgJK)eRbe+yy{BwMFXN< z(ASOimr?z($W{VsG4(fNW6~HAeghZO=VsFHa!u>My-?!CfUK>p?M{nbmwMdo16-x; zALvs|DM&;fQy3Iyw)r3=aCU5JX@8@3o_mH=5K_Tec}ELP2o5!5(h6c_+8O!%>9F-; z{^kII_zp2KbvNmw4zXb%3@wk*j(fd@WqH=`%;bP6)uMQknUQfnH{I;sMWQuR%l+zA z@IIZ#`y;Zsptj8NUmFU2X`fz1T!X5a2>v^d2uAaTyGshb&EO18PKJFmp-9I|YR zc|2>0=pf7_7O!?pDo!^z9@g|d7SH;W{Eu7F2>0~NUgtbQ^uKL6{xKmJJG^+;IT#&F zJneuXMqK*QV(|ztF+w{nvz{b#WisTTxJpzK$=X*yxf%BG{6a9ZJGQ^{NQWW@V|2nO`sltJq z8aM}No>pvUKDj-ZqcYRk?CtFZ5}!u5-Gi%bX|d}~{uXTJ#H5)FTfv3aJ_>HIk*lkjxA*2Zn!Da1{^e7`ha*B3&EiqIkQib1u<(IY ziF2Zxd0@Di6-~YCFrA&J!R0$dg|BEEVbP*WrCrbNvi@L0CDQ9jPffMnT|mkv&D>65 z4Y-P_W6-d6crQ6$oN5gJ`5@K)=%vGrAk#IS$z>UkGqV_8{SmoX;1(7xHVvY3xltEy z%(_DPF-<1zBv3m48zHLt&@Z+vf@sVXelw_xvfYclB~yX*UfAFn%k+JX6>)YSz7}DS zDI&UqQaI>`bBLSet5jG03m_XE`amdpIu`365|0o9bOrDmStS@12I zlDUIl_2rQ!Z>r<~WPsDQDDUR38e;xx$-(-VyI6XJ)GA)tO3rb`S1oToABPnXGCl3rw-IA|5@gH`oC@y!$KWaw}mKP zu2i`i$cwQ+hUd(jMkE$EKbchYUS%!7ET^6j#p&>R>YW+{J)y5D{$ zLBxHj*w(?Vi}g6Wt~MF-s}ND!zIL}JS}P85XdFx;=lXyMK`axQPo~`06Jkf@7wFPY zckYDQCr|&jt}4bKzt-q`0)RxeK)jgqvfqXID{{pK%Q8Z_2LdsYz4u6Krx6$dKO5ivt+o5UJe~bkuls*^=Oo2K*1C^}Q9FUj9ID>c;B2gql@wtE6Ofa(IOSJ>e zGf{ufkt!yYq(h6za=tQmaK7f6J<*%5Eo(dgz|2&7z&+?Ob0|!QVANi>SrQM!gtX~# znKd7DP87v*-0hINEhqh6v7Cq@N5Ff~B~eEoPoN`S;9JkSb7l6p+gPba+Sr+qZX?uj zG_uh{c`~^7(#n4cSR=hgt**$1xA%+d@_a3ko+JPQ@jdyv+^`zS5=@)_!W)Oq#D22| zQZ6UUUm}4>Qv8Yi8x%Dv+7K*MF~gmNR=>7OGDVl3%}Q7!=1Ep?xMp3Y@)|qNweGqz zC$*5`lXXqbYse5?wm`~tB2KWi8j~t3^&LwUvo%ImY6WjR4`lP?N{_wKVrb{7-q8xc zc1Z>Ihzf(P_Yp6A@uc(v^hHkZ&mH~A~B%WPt^$aA77!6 zpus;6{F>q#aZ-9`P1TG#)PK5-S_Pd1 zZWek7qCh0OeJzKw>qufMAOXVt*jGGe>Wrvha}CX6qFZbcB#0 zY+LJ%RcPtcX_ED^mRBE{A&zJ`_n$q`iqS8_3JRF$j@TRo4$){l9{?FmQ=X#o#7_O# z;Yt1PG0P8_wIKmZ;!nKb@BxVA!J^2i5VS)3<$C2TAF#9r?tX%_5f%^!B20DW1f2u6 zFh+PYTQVJ42zI;TZ}9BC2?IeI!-VMe;}+2bS~qn#-(C>?ZvpxFp-37r!q6dHV&q0w{HT{VS9I*HO{ z!j(LrC@(L1=rwW!%I-0^s#8Eb``I^{3x9-G7pufy8FkeD&Mx^gA~bQpijJO(kkf?W z_?6;W8;-L?jpT_h^au-XN1+TBRd+xYjPW((-xA+BXr)`wrh5 zlu_HeC$5T7_L!Q@Jg}Qy*AW>AKr4K;N5(dXo{sISBsdnPy3|-~lstwpBW01lq6|)R z2z`Iw%{{NaWQn8_B~pObtNw7ZEWe*Us@VTC%hZ1p7@oxHfSX0=hhTkG$<1A%S0tR0 z4dXi}LiE>Y#>`4n{igQIs&}@f5hG-+TnNL8=Z5G3nfk+Z*~9r!2chLF>v{LAv^5Uq z`eOYTcjVf1PG}H|>h+O`aEvd*`^JvRk^_~l(HZvCS*h$kxF`15K{qxzK5q5&km%kjT-R zPj|1*3pa*UMk)w&?OEjxMUX=4qIY`W?8>amL`6;QFVmNw0O>>u1`E>jeWehv2V&$Ri+u8xN1g^Iu~15u%__4Uj46gngPX zI@Ao9#PR*T&NbdeIYD*W*9>B*wvULI)F!yhv>1RG2S=JZLwA^`tthUot zyPH4*w;=zPr8A2WT@<)E&F7IVofkWJ%=+sji%%Sfi`mn@Cetlo{?7g#$Qb}buCGM0 z6H?uu`7M`0qq)|C71Jiqu^{UwSGIgUokY?fYp5-8TrNi*r{w(3tcvjMl~xC3!hFk zrb5`1n#ZE#oduP!eJNRn)Ha8WULB6gm>3tA)76I9eZa$E3ovLUDO%2uw}w8LBzmyn z?U|S#@~Eo{c*RZO@N8C3(~D}L3}Cn+l4ZDw$v@si{nfvPD{D{uhl8=X+Hnp?*}A`sj9ZT79n!3)0nA zrurODsB7F*?J_mv1zw^T z*v%{WH06C&jy9|F>*Rn9kBBKe>8DJT&9!zH)dGzG5)&nlW1G^EGdSZ4CyP$2KB^YM zqv|b*X4Rl#K(3>&zf&T5=*OYO^I|V7D6mF=uqsDog0lhd0sY)~2jAv8jamY^UV!PH&o9-1q1H@!^0D?R9#VzDmw} z`}D^6X^i(3tA>%rbe0{QFq<9&LL`CY#B*y6dFZ^3*OwG2d0~oPgd(Cjwof#|Y$wS} z#=cMVi|ztsF6QPcjK99wt6IJq_DFMV#~$6VflD%COyamo*)(J^I9Hp#*-yz%=eF_C zRM@aCgmirlhN5bSVi2L{EU|3sefeQV#KPvUUb{;YwAs%9QOjZ)oTWH^-6MNAw0a(Sb-VI?rXHL3n? zos+kIi=Q+}T9bEfZ2e7O}*1J9yWCeD8q<>qBs&R?$V z5fym-pg|oxfeE3Zv!NoliaSrRpL`!Xjd zGrY9rK6HS+5%kA$Qw9EWCUc$BsVe?>h_bpqDK znaH)yaQ*c*;P2CbzpGC(J9M<=yT&N}v%SQNF!K+$bjUc5AFdU*r8=YY7s1Ti`hY@1D|K$Ux=_p@(0lv zD66qL$;V>DhhDeoyKDZI`uje{OkxR7gLa;Q`hC@YEAJ8b=>`8I9HY0ig^#KkAc35C zm9uGwHv`EWVxZy}UiE9G`5yN@ds$jZin%SNUhmDo!0-=Rsd+!Wuv< zA|cEh3J5Sz%X2l;|90-Le0CC@2$-=BDU6do5$dxu|7iL6zjinZtH4AErpyyh&c62* z+MpY;2tauZu74$$>bT6!%)F)%8%5WTnNyg5q9p8eGE{ea;L+j(;=;gp+43sgRhRd7 zKRw*orSUD1g90swYeku%43kE#J$;U9LCVl3#OmRW@HMEc!=g8PlSN7tDAX@6B5|@J_(@qYsBKLCsAeqwnUgqPE$&TzxM!;T8DjgXui6? zIb5zV4TH9y=#5uj&X4Jcd|1dp;Q{?Nv~T_O}YvHwkBB=CSBD{ct-% z6)Sw)n<3&80?pV;%`GtZOI!#G>Jx+GgO3a*xI^8ivszW&72r{ zqe!#Nz^|W)@n0NoM@Pq46kb9bDreCsW*`VL5B{fpZz8mD$_MzEXw{rADa z`x;0ybyZqHx$}dQE+NYFr*#g?&Bh&};Fh`QbJ#@5C*1sgI)+od)=ntKjx3k&py)Cc zlfom=0<1|i9^4XaqviX2A2I9>lLGaZ#0jbyTP5JQ_iySt^-%dNfZsqaL8?51H?OE) zpEqNUq!y)A0O&ZtZ#&}%Zq3U94}P)0A^}oZmubv&$oE9o zs`To7N}a5eHRRP@CVzMG_yN(fElDVH3dl>lxoT^`SObod^Hbz#@?7P#;(bs+Kp^SZ z2o5}1TmoSsr4@DW82E0RE;8mnQhp6V_(O53^z#lyacB~dI25ekG@GZU4vq$4QhRP^ zhdp!ZBnm5e=XTVe`0d-bT01Qfcy)^_VMIN1EcqbA0Sbs#w4blN1L+F1AkdtDJyr8b5#mbSyOw@Dk;QYa4bgHC5kYm+Kd(DWHSSF0@$~nA2^jGf5GgSFr zRVK0!if(725sKY&q6BacHr?qw1_GT;dY$V;y*<;KJEK7T#O>l@^PFFdW*>qcBiu zk?yF`4>^w}N5q00*bB5}jw}DSOcH?N^x&?2~8&uYt7cMY`hG z+}TT#!c&EP++hK%Geuj~o^|K?f`Wp5fc4H+o`DRKSuoTfJdMwOAq8M;8L3R9QHU4F z^@tu8KJN|YF#r948^|r}CsXl%<~7oPD&AGHBxun)WNqms3TqA(1vP{2O}$-3@BEEJ zX47I#}aj+bq zx!^nn-fO=Dt8Ni%svaszN-7#dJ{}%dFlPv2Kj9G)f<*!(r1Q1uig{`U>X!dS1-E8? zNz3?>!A^_=49!bmeRp=QpMx)C>*Z}@^9LLc(o<3Zmj?$W`5kL_eTU`^q)&=ePi`b!ikuJGuHT^0!dy~! zx*2kC_59>K}O-c zjCJeV{QIWaSZ2S%sL?>yn2e#P;{)wzyQ1t)13RPl8xqJK%kGWR0r&qg)61_8pS%5i zcPeuiZ8ggn0-D;rCAaa`kTByWPQ1V7ghk@;z$)$Lozet)3YCZ+zP;0L> zt|nB<`w9|F_WQpiVRZgVHK0Hw3~XqZSN~(HcS9TX6hz^(;Di5?u}&P z+RIg57-aq7&&Z@fhfjG0~e(S+hY>u-F94CjSHti*?&*@#15 zN~z+|g{;janeW0_5u@XIuqhOkBhrkgmg<;@*gYRwP)C`Gac)^SRF?>?Pe^Sns1A1k zfo`Zjtq(iMn$zgx8W6-x#%BOt(2%csiEs8snqGqWmN{}V^6so6p)3-uDmAy!;7An^ zo8c)VTVBiM#JS0jbV1&wDH+hJ4*4Iny>{OVUqA8NhnBK! zHk(E1^0NPoxZVlGg=OZIaer+HQwQ=DU z9LMV@XDxbsohy<3S>{Dj_=075L@u&r$x*rmtJZk7_hYywaA<0?R@Ssdxiamcd1|yb zA8;?+hI4qYuce%& z`7z50_4q%EvvBIgu2ja`aI!_ZzlsAV!b_ecQBuQ_+DH9qlb90U@gH>3Wa4Q0W4`rr zZ75xa^^Z*QM;c{f{_}4LK?rnC@Qgjs4`pW5veU~Utue1^8C~;1n%5{_KWDuQ#NwI)#V8wj8;U>VBE zYfBQVVne^>>7K^Yfj1=?)m2NSTTKtL1=~q!c?8^=5`Krwgkbiqc6fS|hoX=ymJ{;< zgi0p@(wdR^Q9mSFuXeGzthS`}di1TKMhiQcFBKEL(Bs)*BL^~vXIF`ogFNn=f8v~; zVX}CA_G4-C2cGcas}ae;r@`MV%E5yGg{;%&LpajDnAY1{adnG&lS zScY$hg-LAZH``V@Ww=ek38%!3no%)T=N|T=@C=gnZdddQm@(x(XuLbqa{soII7=^4 z67-)o1QKY80sEtGk*)lD<}EkjH~og6^kK64O5AxDf~Uo!{Yu{|o|Rp*yf?i6$({RV zD_aX`Otz;yxl|>v{FH^MmbHgs= z<{(9mC`~OoFf<_EG<9;-D6!z7P;ARr6k^0(ujVi+uze9(D9A_k0@wVpY zi1BB4cCt+r`!tf{_O|{>WprER#RtnO`Wp&#X;d zjeV$^Hh!gkt9hR~)`0_I33{GCSn@GdU8Q6|)R5GXOUyo5ywS;|&wCZl^|jki!1Y#D z+xSK&<>JkIX~aZo%pGG_VU|~mj$<8xzToH#<5JY`5 z()&M|PcMvDr6vfh7Ly9USo=|;$58q46+PO1cUre12Iq%ttqL62VJN?U!{(_nncG-> zY$Ou$gE*sBGpT*FMsz4?!m%sdYQ1bEw3NAq0>+hxk<}-H0RB3vD!Z`}GW~d1P)|tU8pgI?@t2U6{F3XP3I%VJDktT%E?rb^OY-i}oCj*K5uc(-!cj+221+AqSwbYT-{Ak7HDN<$Q z$sHt8d#P^1rly~mJqU9OT!ocLKY#DB+}Y(ZNNf_hI`!P)vu;rQ?qw8$qMn=xMx-#f zmdKUu<9*urnJa_yq|O37+G{x{VAZ!Ke`ic-R8`*6d~mL!62(*JIBSRN&}XwPpEJ^e z=g-)0US0Z(ncB4$=eoe{%+t{`I&j|I}#4%<2N2z~yTa0O@HomZS~I+^lFu(S)6!jHn$?b_-qkkImaP5k$Ued{^x#)rV3gHC+($bt zA5_*ZPjlzx$JG2ICzt<<9%3R4B`~+k@=cavQ=18_KVbTWiYZ%pI}<)c!#`W}Lk3wx zKup4~lb?^SP=(Rz#lqO>riv=tG;6jn<4Qc2_(5Z@jd@^QZ>TXQR<`!fLAEeJNhD5L zMm*UH-J=%X7yKd1kUx9%t-M{dw`Iy%^`O|S=LupaTO<`(ixG-VO+qP&?Pyh3x z%3=(ulr#{A!4^R+)lj%2pYn1BVcImXn0D>9owL-nU6`QC@EChYTaSM92U}Ru{TFxw z^NXG{`)NXvARRm>%x93_wVY#OQeNLYQLPVXKbV{xI+FN6@qu=%Vh1Q)sXS^xz|Cmf|)VT$~)JlxF!(qFF|~Y z@;F`_j{?EIYWh1$k%R^&;fWpfI$}6t)>bnw%ISuArtT-ZAnRNvr5#QSg5p`_^I-lj zkXEkm-UnEAGtNSK>DPU9r;4KP{IrFlZpDgP*xRN#Vv-7Ko+Bqo;bBQIg_R;rbCDp; zM&>PBoMlEFh)qK-N}%I+0F53H0W!kS~LZxY$91=0RXulLI|(<9uopG0Ad*>L9kImPrnOz|s& z_dv~SrDYw27QOm^1)dt3UVWaq72}47cwh7q@4i8@UYRvWv#6g-k2zCjXgBY20G~>iaxOotUw%ATUM^rCxgne*z*gBD7DH+6p|cOu zAldfP*iF+D%-2uE6B$2s+(EOj`zg$FEsMhGY9PC2Pbs|rnsl1>XY=>0c+5>Rx@pNe zp6M5eTce+`w!-7Di|bsAr@LEa&)!a$lz6;gtY8&?F8M)&p{&2VlMPop@o%-&HgmZT zQ2Lb47QA{lo3UZ0ONC=l=~9G~7Gy;BsIj*&lz@2(laNZOl3vL5cGcF#so#A9=R>ZXmC%ZNWL%UCPkdNp4i)xyeH{iK)886Es209=weg}-yTAF&#QZ~cajhx?1+y!Y zW#z^%{HQpLqk^{sUKoBi2~2W3MvNDhTeZ*RI|cmemaV2b++~Ae>}}R~SH`2T-s--O zN`b@;c3r6w+&(LtG|$m|zx!uv{fA|`=X_52heL~pY^OH6@KdLbf|0ar*|0+klUp9q zr<=<6W6rphbv}FG*uKvUlv>66H ziJxxOR%ZNT4G`R=C4 z_xVMjTeighcEHwYSTY~ZU0zC3C`D&zRPc9Ig^SIVhw?df2qw*Y+VvN~{9kg3j0ILr zo$|LvUJ_7={bPDbxqE|no%5(%`PmI#YKUE^6CI;9%U8d%d#%$oOcjtF5DqOw1h)`Y z;$m^83Pv{LX&PXXyyKL|UZkA1`yEPzEks^SPV>q9yA2iHCQ|xDvMOz;t))Hbp|{sO z^tx`iiu+xpYzSoq?OkjU<+$~6VYrDEnOqRB7*LL#hM9CGbi_>P#YKXv5C*I7Cuz-# zMEVM{cZWCA>W(UA(qfbMP0_-y^V3!4C8`>8V2{Gw8Ya3^MZ82c5o`low^*jlciraY zCfmGXIyEaanGO2G*XGx|cS09Dckh2L1+VEJ*Shr>4K`M2bnH1AxO=~)b;4eyJo=l~ z^|6cL)b)5xpI9|0xi4+A^vqP+(1o8!wI~Ja=KZxE&8ryYqO;Jm$SU4ujzG@)?&hJu z{=lKY;lMUiV1m>@=4#6_{|6>_^X`lHr?f_k{*=DdwYJ;I4n^uLY>pI+ly2?NWgQEl z6Al8fm7>lxBDr|?mNHu)ONN2SifNRxvbMa{m%MTYyGu7L|00e?05M;1>(rce6JiQ;O!m5#Bb+{*E?fY3xPnx zaY^T0!XXOpmt%>Rw53q)`-{sy#>y404(EY#dxlZ?@ zO+I+Fm{ex#;-SZ+to&mkz&0irBPToHEv5)EIS)YL?sCLSmUf3kij3e&H-&9zYxQ zgzhW)lXhMh-5b^0TU1Ugd-Xv^1q=cr}x>nBXuB7;)2@Pv`&TegeQ>od3(vGH`inzy0v|gwL2f5&~|4$gn^F2vY}u;QC_Nog@of1pBc(9uPtbM9757i?skCR#r!ZE2~xefB+Lhpbd4@1WE2>T5dA}&bIVPRvKerbeO7l z<|q9JCygt_G1e8Ps}_C-;7S<`s-eTk?hEby*hl~qLi`OdrTe~qK539mYSnr-alB{^ z7krptp|VFHht-hh@Sj$#+rVxnN1@Sc)$Ig zjOW2T0vq)+(Vh9P;}e`wLt+H9Bk)1>74UXQ0EQzg2xuHGU$U3Gl#UqLqNCl+fMFwF zIfZ0B15(GJ-eFkDb;}9^nXjZ`B9|6%2kI!nj$**kAlU~xCOB0p!O|TvZm2k107C?GnbB?kMuznzHw)#o^8Rk)?P{~RIK5l(?|ckqr-eR~tIXRH(C2Is=? z!Ox*bFAET{ubR_KH3xtR!E1S$ZePq$o5M)qZhr#W&VXW+VJygJajRR*Wx0d^iQ{k9 zE}ot$VFBdsnA5S%5KjSt&i>;Hl8xV=0hmZSn5E@wEKm`g1#}i-zlICKj+1|t3l&r< zxYK^X4PC{TaOvCa6b4vWy}brD!Q9*w-+L~|<0~ow!odjS28kdGlb^An#hw@&9RGCQ z_RP;-A#FHjl4iA-pWt)!tbAbX>AeNo9p&z z>O>3&p$Dy!qKM+K4U1 zl;EYfM3zhobWvY05!^s17`4ZQhtV$K9E574TGAPPJUM9q0}9_Wi9_S{lWP zL4HciR82#bwklgF`?=_#=C74$Cf8TQBZlT;p^G~^b+mUmr{|vO=lHJ|35H!=m`A06 z*3HQ1hb)^4g+ps6UfTo#!S2%hyu9i`@hE42dDL;R)pWP1aSSq61d#eQ*fh-F=8oj3 z_Vuw#Fjlt#M12qpi-6-k_4CGYZsmFXUxbJU*D)V_k_%uh7*d%0=WhsRy6CX7GXw!l zBGO1;-J>>m{sMe%*gymTEO<~_l)B>L;j$ou3XR3RuL}JLjwTru%aZfK>Wp1Ro$CFV zYz_yk7L8mrn!)-Xy_T2!aIqDAC;}XQSTjejx1-L@ek_=gOj}?B$nrIj-n)!(At&=P zbx#+j4rX{w?ltH`C4?jSO|FdEovW_`sWDQ|l>i?Ua!}2#GU!-*qlUB}#txpmS;d>9 z)5?Kv;&;ur%$t_Z((+98L-m7K=66qS4Mdd#90^*G(SQNW9bfJ01GJehpg{1y`sM7p z(#CxXs_p=~$NEqovi$%EfH zr_&FnVAO6FYaxj1yv@W~U;!MPGR;R=CrHdA@|7TIjQo7)Ae-8W!>mnMFE*Yv*bKo?{*+st9+tx^tv!e zT`&xwB=&#}OjiRa&@C*fDo7ogl$>Ivhue$NlLoAyTqN7#0XyknRckY3x%025Kky=Wp2>$812_nRwJV5Kb2BHD9p2Wx2_GP=`e zOf5xS24!0-m{?nf6dg zPPj}tDp_8IYC^sdpo;)2<}zK#Gzm6qQzr=Xl-YMkFA?BIl#e#KG(!j=f+5oFp66QI1IOk_cWn9{8$iQ~GH-E|3pllZiD zz8!W63H61Pp$@~UK8rs3uo*P&5MX3QkO10y$dKf58OsER=PG>&N7&Nb>l-K20k2*I=%UgI6l7Q5PDrgtL#By9H4^~jQXDfO%S=9_ z{3yRhA|44HVs&^`S=QhwiaI>yBMAVp*aWmIFb3FbiB4DY7BVBV(AXe=a&X|!M(pW- zZm0+doJ|5&KDaM@6qxq&7oJ@Yy@1(|_=a-f9I;*jRTWW*a4XZYnoUNP0RGXWX#`VX+*y{Ji6n63Sz@{DLsIp#MvR)GNUb0|Y zx2i3b+OP}wJ|mxcij_5#jF$!!-kVgtMj&6Q01hS7mmMf`iuZjkt_;47&+AF+^B+}y zr&^Fx8Oe6T*I+~vZ3%}~(fM}ys!9ZBV4)+w6mXczZ3J~8{ZsJb^eNFB>MfDWtHKev zx;IlesYBUW-M6+TO~KkHPKOn4nkp@D5~OsPq5x+uxh*ObSwjsd+gYaUu&s2=G;I_j zq$kMWU$UA<^$r>~cP*IQ`-Rh6R;S4wxEE&A0RLDsFQxC2QYsRF=^VVP=g<+^OA45O zmo6pPuTXj7G62tc;eLC#_`_M<*B3g1y}mFY)FK}QBJt@=C*@naU$0M*O^;EK)%XGP@>v>7@N`@*yYch2XB zpfE1{?q@K1_OQ)O6`S@3dZr|&4+XMOt-gUo1lTFENkp!y5XAyfh>WL!OxHz1ENL#b zy6bJse|5$XSbXSPAzy!RpxIVZ^;ylJja9p-H64>8io8VZ#YezZA1tnsfQyn-vG)fB*KDBYG>M^>5JpMP@I<<{UV!}nB| zAGQ+&Mt@`ug=in*%KMku&?*@w-WXB%b-DgmwNe5{1u!edof@%_*qSydv4ayA=^k=O zcGoGpeD0`c>p_@=`3Knw)&LA8j;ATv9pQkI%JNh?#wJ4a?OwvbQ6@!MRrrPLOxD~M zvE(89+Gf9)HI38EYxI(=jU=;w--^+^0FdstLEz3mi{M>u=ev=**9e z!gs3GbwxPEl7VZ}%DfOxHdy6q?|$YL5U+vjv8D>jA;- zfS_3qHo|#iUzekz*8m9CvQTmI4&f~M*}(v>e2SJ863kz>F(Ck0p)s<|8dT(;*2T+F zdo6}HI%aSEsG;9K*R3#PD0+o`du$bIB zOwFjeaiW2|QbH-K4?BV_Fh#rwxn%cO6_|CM_l5J5?+A}Dd% z#qk$gizZRYp5C6)2V7HZxXpE&Ty#mVmMJ^VzePU%uQY-er7s!0qqqAF@~Up1qI`#u22A$mCngE-k`nRH=F42ek%#3MGdVF3%Szz6VpMg^g;6Fi z?k`~=wR>p!bdhzY!gph-RX^skbdp}2b-z4-1!~JxaCd{G|NFpuK`dZ+yX{7yL_;>6 zc}_DYi5)m#`3Z`m>OX2HFtP zu-~sd^7Kp^kH%rfsZ)SIqwkKG9###AN{e|edpgq5 zI9Juwp+kW<(AW|n*zOfR&vy#F@*5A_kTE|!)bCfbq6AOWceQ?WO*-5Q+Q7!JA{7jK zOH(zl8#DXzS#G%DZJ=(48~?0&*-Q){qG=8;jt}x;2EKCP2h_2YOuxzgDr{vEoPI_= zaO{(&pX3YiZPHvrWt0y`0|sxF36U^!!WII&@X$?^N#MlTDjEWCf!FwJ7d8v|at~1@ z3!@6nf6>T>9J>kZco*qSz@JJg?`vaVK-M5agG_!}#lytEHy(tVt}Bs|mTQ;oR~fG) zJmC8AQywM)5u|Bc@UhW?%fjT=HoR_7z3#KriypR(8ly>-x{`OuCQ9wI&)E{2{HH`K zy`tSgiqVgFN_R7gpc)N2Ya}$U`F=Z0@7+;PbxK?L@H$Z&{XkRw&bnT3KP^FK zaa(TmIs*rYMhI7k{ja*`8P5o)PhGD!ab&&~HM<7nbQI%NeZ9!dj*ij9B{u9o3vI%x z!dVE3gb2m*VfB`(@j|GfKx-#2&T0iuC?>26F=ic|^khyRzlAwtPP8Q^}Q^eVg?7^8u_qiWS_N}JjQCjdS)4sIThhBpj z=Q{ZV7!arg^3=!NhYBDhX}S-VX?C9dN~YXIAf45aO_uS+PAf$>P0=Z`x2?YGtwuL` znd!2y5uFVuL6Xg97wedEi+^fVWDv+vLIA{j9Jvh?N`7RY5~ur6{)O*11QzP@O4|4s zZ=XhQe2i34{*)0L`dNnqV8C;4*bXkEaN*mTo&htHr|S?laH5kd!MDLb3R<}ZcU0Lp zU5i)7-jT(Ee%PCL8^op-BL~4JHV>HX~UX9^2ch1@e-997QX~aOJZXR(lRVo z<*=hnv`fo)*L4p5m>hP&A|UBVLBB{wDe_&BW0jRHpO2o zM%yg-{y?x#kgyPKDa|}bOmZA6P)Q7sy1w9j>B!*)?wH#_gE2&)nSgfrG7Ex1)Q>|;^Cf4BRL%fFnjE8CbQX(9&hy;2esf4YS>MN6C=_&RO-w-I zX;rsx1ru2quH_8vg9x8Z%*z!`s@0*tye@xkuEtovq9Zf#PR}Hc+7= z;v*~+2Y``;1v1SIig*t|&JSS^d(}$tS{d{^MU)0j&ZUNtb?YgN{btPSfHDiQW=%giBxxs zRUM?*;IQ42(|w6X^gocDBoEJIrk0ASATRHuwnzkQH2*uOe0 zt74vG%h28Ky9YO75RZF0zEH~ajz6YA5$6muSI`MY*-oc{2_^t=6qB?2yrLK`pQ1*8&HMFL&IpBU+=EWWSkd)| zEGP%VF5T)Dj$>XX;8KM@n)?|m03*C78nEw3#k<4-RwV%<{;I)Uhv$rUC!2FQ*$8gE zn+HZ5tYo?|oA!4O1U45NgbgS~8Y(Jy_un%;+JB^hLatC#{HS|r{rhI)%O^Uz%w-H< zB-tQOZ}+1cU8=ZMbWv`m+wfn>%Hu`pu-#_bd4u=n1a!p(pC@Cvfl9Y{a1t@f7B9pk zuO;|~vv*%zNF71=a8B92kDabCM@XluTh+=vs3{it-2ltNbbeAaP#$O>{aAN`NkgmrZQ~&?}7OnVh_`)DGY(iZbeqj6{wS00`hU*G!%E zpf>^0tO=CkG7i40$cx+0myTNWJhIt%iV#j=nlM_~ZHwqOYH}ZP%*&X#j1qJlZz+^?)7oA(>p{g zO^)U$413&!lB?KXC-gM9Tu976ok$sC;jl4I%(|4y@(ybqAe3 zpgxiTR4bzotH!&Jyh0gN2hY!s_iR6Xv_RgQ2;YbWX{&Ic%bEF)@~3qpr<4?z3t5ZZ z8mm+)arE8qP$mJV{UV-gCo254u-@#{rPKB1zGHUbt1;LbVD)JihiDpd2fU!I%)Zhg z53@rPa)4PWabm>hINS|SU?uJ;bX@h|MyReLvyGaVvJLloLYSsyzrJa%1+&7!3J7o| zyQn?2|8XD>D}=y4oGMglpbU10?n`TH3?#Y*rZe!3Dqv@Jn^q?=rqIRTtD;%0rwM*1 z)^cwwDHLkKA{FN4RgKF^mTJ&g4aGPFr2<<9-Z< zP9`<$VJ*Q#TMBUp7RVrz^y7+Wk|Ts)B(&PWbuBHtBGP=G|8@Zr-neMz1YVukjbM!Y zlumcd8A3ay1)E^iUmPkbs-!|1ft665_VEiFE znG7?Mi&*NO29?c==2K%>VG+%rlrt#0m!`7;aONSv{;qvYur~d6zJ`>*jNRv<`IMO! z?q=4`I{6Owb5d9{-zXrgUvryzAc7fv7T(K&78K8dh}3=Umzs$~t%> zXcT#|K`{4w2PW!mbf3CV+qAjVp!?OwaaFQuC&A5n>7$G~z-$q_MtkXWf~|^g{8#uo zzAHN5S%RW%xHS~ArpT>yKhZGz6RN7MISY*YMEzx?b9ZLf)-q*C`gmmFd9H^!Vw;Xp zK?S%>LYb{oG=HV7S7pHH{*;!M<^g*Q_%<(w@}s{QIQ!=zS@%J3Xk@5%>~q4$KHU12 zc%ohxx5~_BgAXh%?5h(Uk#S?8IK*T9ZubQrvSs{}8D;(Av!nyRWyu6*O;!#!HC1IW z%K5U|YgN+JUmP<@mK|4VZ^y>YIx-}px05dSw0^n+qvplauocm(@M8kIR_`EvUbdD0 zu*;HAXF-y$nf(e=%cqOY*mRGYlfPrpKZvkgMt|0R5kQSd zc(2(lN&aCscfVS2HEtz~rxx0>EzUJH$R?kq>m11c>2V(Ca(q=yOZnP7;odEIe7@0p zJn)5;9zzH6{`Rtq^XLg5pTO^DfK}udAF_CFLjp{PG0Gh_xpom%U^Ll3En2HnLCmU` zroH?Z&Yz}FWp@egWH;E>+yhhjqAM^FnQ-{I=lA5ApzK)k8?&*P~_p z8e4Dx*23Q`TWY>fLYLe?Ofdl9N$59Rub|H!1x|xI!nPSs(F1^>Ut36sBG-a z#R%ZxvFTg&^Z%vkI6}#VKt{2}pJFlooI6~`1&{ixP;W?R>L`IZt=j6h$hZN5JoFag z;8c?Cg;4yQNgPd*%^O+QF1diMvcZ3cFY$#MgRVwNboMrt)6Ada5Px(NzGCbK`Z22YnZzQ*rTd@_J{I72oiu#cK{vTp%lb*? zQ{xFK8M0-dlA zj|q=AcVT&lr=1BgztAbE)5Q;$i zU3|?_`}0z%s2U0gE&>T=kq;I_)Mm=9Nn5yZHsuFQ$`#_i5R4AcN+9tYV*C5%O2lEG ziilCYhl*-^C4p__N2>sz`rT4n==OAZmj`K{neEO#4{?B|<$E_H3a=)>5drK4-R_0$ zJ7}vbj1E`1rX>M<=c5jG3yl0M!2b&egAqVYa0E6;n0b6EjrlGZ2z@j%YUhEe#9&Ri zEIc2v4h~7Lb5S$g64{Fgsv698-Q(cuy z-!m4Qy~XCq1VV6#yK?0(7&*BQC;S5CvfoQ?9*GjXTC*pX0*ziosHigw!a(0{8+;oG z(|rlAT%m92N8U%YahvyXs6*c>%+Z5A{>v7Cv#a+7HOYdx6Uu8tgWq>`_l^kI0aaF{ zVJ#izCL%8QBz7zK#?xVZC4ctLM~5GGe77jY+#>aGv?d5o-(}t}cSMdSbgX<65WeBO z6UY=#h^3d|R=+FaJQH5Ymn)be>NWC*_NOPNJs9d78B2*dOp!g+%zFE1^u+(<;XNduRj@nK7QRYlsTv_R~AF*PWA4i;deI} zG2-bnu(aQaxD096<9A*zpBs%9OJ+Jq#U_A`VxiezV7`ej0)gXZnoKd5{1ohcFgGDU zSN4L1cucu;RN}t+zQI>HA?q|`NXB7~0UXT@^#6z*%^`nz9--h7if-eVkx+laK&qZ! z5M_AZH1x0r-^zGOc-t7cqhiYI*Yt+;Wfs%4sEYAG&^Y-(bMKq7)eQ%lV$xIwM?FT> zT|?|eqq$B)+mUWR_o8MhtZc32p^<&6%X`e5?M9`Q?qFq;tILsrYRpqhfOr~FAMaxw zSf6t+Ng+TZIlEkTaU6Th$adGr!0Wa8uHNT&2i2>IrKJ^(6U_;`A~{NINuBFjGQU%J zp2RtOe6>E%E?Su8uB6y5W^|sc_%6!#;?-&Yw79E!vfoj7MDAGJ`DN6*p5dF6dLM`_i@He6woKh#2Rf+B;UTrVWIVcsA@<>)ZAT;V#(7A~ z;%3N;$KEam1k#RqDX@9kX!o+Ny&Au_D}ZEiA3R-LK0a z?(q=3OiM4Ze2C^+e0lCaoWF1ITmR&PH%GdPocDN10Mg2mPH3u_lWzhioApxROHt?*p%19P<2po#}&HRFsErJCc{(D~loUP7Xm;@dSX0act~; z@YALBRyOeR-h2BGHTZ}XhN+lLyJQV-`*eutz|>Tjg<-xd{*)*W<6xCv8uemm^@dbipx*z z(fXNUE}K4_EteAe@kFjwYwm7y<1EqNU1+sIYo+qX*_2aBgGH*z-71g*?oEoT$FMaCymNRvOna&c412Nz`?p^?q6Z^SLx= zA#jsnh6kC9E1g0JHe~$pQX0FZB|zf-YL$39)=|Xg@gWes!%Iy3jksA~p{bovz^a_T zg$U{9f$u+`FY+)DWcnF40NMd7-gxi%a*qU%!2WGc2coR{bN=t3JZu*Nm+cp^tN;KN zz*xqYj1lIEfs8JaeDvb+W?u~ND{akRZ4PHqi0$N7NVV=EM=0;a1V$NkY$w&xTVAA4zLex7_N>^+}2?@YlB8jc7#!ELv#utlD33Y-mK zighXha*^JPkIc6Ob4gm1vZL0ZTyCoK=(q3Y*1_+jn=iPmh%<}~Sf4?tg@8)W0Kbm( z#*gNmu0z`blPdpG25J|+O{#ht@Wb=}elBi$fvE1Y4EX`x*Y}-S5>}qh~=NiWrb|7z(%ji%e zw5&@pGtN)Z%Zzub(u2<n-+Qfrp_cRao# z!Bgq|6KC#|22~!kt&@HxALA!ytF(uWryAaHUp{MFRvDYxMjwPUuFAKxldGYTEsjMGoI;1}$G{6^@B$qyiRbJPm29f75 zFb)-B&TppLnZ8?4V#)Gpgi!y$$jSW0;&uCs*?Ef1C9t_`lYf#3yC`)2r2%=i+zJBD zGFtegneO;~_Pt<`_CFKvF?ZDLeP16}X0`1`PEqpT5kFHtsr_B8|n^^Rf|C*Bsz#F$u zY8Q88foQ}14a8#X{esaVdvtfLJL4dKK_6dAxbzfWgr-udRX|$}Zz~wPHn&QLuoiUc z%I!(3+(WteSLHXq!)njC*4@jBfp{@0ynk@4mc_f^T+`=75dz zwp>kJDt}gMyqWL$gol~Qtropp7Ex5=qwMuNrtE#IDG!@#v2%hybbqNTm>7P|ivHQ` z!2U?3|8CXKOfykcd|Y5-qNe(3(g2;;EzawpAz=^R+K{--;y~}O%5tI`39Z3nqMEFo z_OE${c&OVGB*A|F@bV5!K2CXUHF`&{{mLe-LP_3->*de{xx3#Q8B$Tj{Y)8Y;_ZJJ zS>s42=(hV$=Jt%tN-q_jY1Su#3jejHay{X5Vgk$ zO7fHE3;F ztV`eQ#pX!1R>7-`HESw;r|+D~>kiLr&XTX^MG~yk@*nKfhx=5fU(2 zd2UnY6aASJ$5}(~?dqc>UfiF)Pi%b@a=o&*Or=te;AY z4(&+w?XIiF3@}}iGsirb&g#Rx21+Lud;if7hT5nTINlnk4S)K(Uo5sbs)?B`>!07V zE9R2#(sIonc)Xr+vW{@ECPtv%3r6Ju`KDPbV!+gW3d|G@PxEB#>5L`s{CuLC@jFuzW?0AecnR*XudAFh0zGk8V?oallb3OOXqPato=r-0KCY6 znb$y(5f_)yke!tNjagp?>Aa8G1hsO}ecb`KW81m~;}U7E(!M)C>8-uY$sd#|yv(Q0 zn55&i?*a*f7x#6n<;JgkCnn~vZu!f4=&Jm;vjbEozfW0tt=NWznw9~>sbp^h4hd`F$`j=2BT#>{JMb5Pt{&dbC^kGsh# ztzCurp?@Y;pV+K<24bT%GyqmIt48Lf<|ze25euvimb)(V2_v*IXgnJN2%NhDdT2!o zjEh;ZV6sZX1V%&o2>+NLf(|m*a$m6gFfDdtA`Sk8STx|3?0 zWTyCW>3e8}|Mhnf4u?C#+L6X(bHZI`ftJpNb!A`r;I#tR&ozs6ACr<#o&>(+<9)4H zo=zf=X^Y!crTK=b_COwVMlsdA#H)F0IVqRs^XuSkyr-d+x?#^m74O0!o4!lvaCMBK z0@=(*XlV{J`47*xirJ%F11{5_F%LsF2S&)!u@@3Y2o{o_Vv4O70&CZJF!f7KwWdnU zHT6qO67I1M3cga{P2uf+imj4|jf2;$zQw1G0`_J?E8bs^2mTm5q`uFMdBlR?#erlm z3WYu^=0{-zG38-P*nnA3c_sTovERDa>}=ID8oS+Oyy%$kkSU&_bvLi!G-t=RN`-O)T|3LDO?OPxv_*PzE7;SrDbK_J%wV1cYyRrkZ zI)L^%zTV`A3jkbexg_{#G=%fIN99NwcQbV3sI1kr#XB-Q2Ai2s*HzPsz0Ne?k+!tDXDcGHyNYX5PD*mk$%mW#pcxRJVepR@`c7HX`_BU!w=lS|f=K(i#(Y1fP z%3*JKK@tT46VM{&z)R5*rEP2P-ob-7I*q~-sU|;pHca+cZ9ktnE`J?LCpkH}!w#@R zYh)&?n#Zcd=h5Uu7XT0;p);Crn$X`ZEZO4i;by$V820#;VtC-v+R*D?+nRBDc@<4# zldtO9ke;Shguuavy%pCGOMtpq0!aVvZPppVT8htcRqHoa zZ|3;(Yz-Y(35E)f7Uj8HCRaQ8+h&{h)~m6ESbVAvRdz4cziU~s`Mi%-J!5%di~oi|hrL3Gk=8rzz=s*RF|i64WOd=xyK7`<)e}|t#QN7N zR`pLjyqXire$1ozKo9E_|H8oj9+mB-u|>aAVAaVthi)RhC)pbr^Ci;@D(7pHk3KQS zi!IYS#Z<Hdhk-xVdv}nE(?E0bnIf(NQzZMm|DO*{%cv05Y%pA0NQDWMsPSpya0` zuToYVrxsk(_zJB=3Jbet9#1NNNfjII?58mx#Ib>mG#ICTG*cL5HyKc#g*X5bZl9%G zSU9Sa*4@OvEHd%uMzVn3rXwcHJ!k_+2=sz(PwLiNueZ+G+|sI>^F#6^i;LOMDqlTb zm9MhywI(e1tiG1yIk^992`~`zu!eBdT4E7sJ#3O(OmsQ?_z}9OYc$u2mWx3j$;efsD8pEA`kOn#*e>H{H zR9NWz`S(0bm4dFjdI(z*Lr#Csw0q10Z-jQbI5XWzZH@`-2tsg^of1Y@Gbu3}_PnM2 zqWk5_)hv(W#Q|+yEp^7>RslGVzr-Q^36ZAt1eFU{H;47(k8n)<8@9vn%FVI#(w2mv z(^K>OTjGPhF*H7nWC~6azz@iJIKJNeC_u=|*KBt@^Z#ffB+(L&2*p<%dAs^AB3%<+ zw5}ZeE0!j}vz&Zg-_{-6ZQcD&IK((GQ++#NXbrrR`uZ9;9}Zis@|pU$Nx#oW^!eNO z|u@Al2&W_q!1X=%u7th0+-A+4Q!eP5g; zG^QEUH85a&4|aP!+56|nobjtB?(zBKe(@@e>9g%j*QyjUG~N6Q&77(k+Q1@k$nA|i zWy>qlA%LNj?LP;GT*S0bN{9I42S5ac1^zUi>y+afAC4v2RX#l9n+U^C$Ku>@`IL@a z4fvi}KqGK;(ojps=mvYl&^gii`I(A8|E17Cu$kIvNyLp)6o6bm!^3-doS z&xLpX3fMCJSQT-R2bw1t`)WHNK=`YNEs2>YigR(ao6?HRg6&|R>dQ zCt237ZMuC~h7J$C{s~pw-jRikme5ZAeAfSd-C&}Dd);zN+G9)G$iQG!Mj<&ld2F>n zYpnF}o_oI0pCj$n_zlVEt3Rs=G563|KmG>x zPsg30Z4J_^uN%2>$38$IMp6xlT3qFobiyQs87NBbX&0BPtsBAmr5R3^$i_dtAg|e9 z?@F*E94Xfy5#?i@F$TTs-B99aO4Lo?LnNsK9Bj8X04?2A;kU{jP47| z8~0m2^`7+z7*|y(P13l8u<8WUs-3`7ba(WxG8{oZYl9mZB81$Z&Ta*ju4=7ap_tVm4m`otc{!5Otmt((mx6ja=&5LJ%4F79Kzw@v9 zXeZH0GXWWAJ8ffpq@+s(kJEs(P>|#k(l;%AzCjMqu|y3#H^cs&=+^(_MDn+-cdn91 zh&=oNX4a1s7a(OEjMV578KzTwM#uQc8N%E+g@LHqWiAG0PL;obd3mujNO*`BXSc?q zYoF8-lRyj%_XGcQ#gD;?fKy}Md6p0xT%w!jMt20Z5pNJ4WIJSI0RZwqRRzKYp;xI3_Pu<`|DjiYe+Krh(h?;0PP!=sW)0b2CJD zQO_cf+JpekhRJ0Vmf4ujm+d3xdLAf^rA@><6eMEZ;1k%m0x2-WbiH*lza_TF?Oe;A zA%wpXk1l15@=)T)`|GuvXN2@+Pg~`eDW)7SfHvA37sfL zcCqNS6y$rq_eNqzsMg@t!NL6$(Z+(Y-O`q0b}Qa3#Rm8tS@@mor8x^lWu&|{;e!reJ^?~YR=?W3T>iwI!@P zH#6L+ph`FaYfXy0KTRI6b_tZnBqlMdXARtaiiy#`qQllmcSpdT;em zEN7H_XSpO0Y$)hEiqj$9xLM>sn|7zk770?zpb_^OjNTg@VK+@#@DXn2YSlOQRk3-b z8gJU$8i`$~ySk)@{QB1>e-uVTVZqn!&#x_X((V&Dc;mYEwT1xW$@5+!FVbL4gnSMm zf-(k@z*Lz#`jd9Jm(QN_o-gzHih4&N#Q7PI>-E|x->eHJT1$Q+y@?pb zZ^=IqjD$@$rhquzetX*Z|Pg*|MZ~o2|ZaU8u zJbtz9pgB#Gx5^NiVKVeRb9GaqPRxoo5KYzS46Ok-eS3=5m>}2$-(UiYts{b+2pyQL zUOI@3;~+SvA)#rd)uNzcZ%m6?=_`x*T*5tt2N|bK|0^S zR)4%PphP`)47Wd)mXr)smgR^ad+9b}c>Mh4sQGd{S1oRgSU*U^Jn+6cNOQ?0`0>en zJRyh;1cWXuzlv*`i^Z{eVwK0$1!b?hga=EGLkoCIcOU)j%HMtsg$s@2!~2HQ*R@&R-|tR+ zTWY)V9`|b(UzM8HrM}7#&mv-w&iFqxU3FZO@7Eq<5(1J6h_sY+NyF$C5CO>nlG5F5 zAc)f4ohmT}RGO)D3rKeelWrIrd&l?pdH>t<=bq=>=f2K4*L9u5{<@o?^NUB5;x9da zdYVO5(;YMm_4m1kYtL?}jY!$4r{c1F1Y(K>u$K|@p*d zHwTeZd-E+SES)m8IPPlRAN5sxwFTLmSUnFbz~CUSCFery#qL5Ay;!cCwQDmwg#Nkh zVlz1v|GXbjlbu{6p^tr#t*sUaV^6O=R}m(9Z-(fF;~gJ%#0*^_V5qb?Rj$#&t-{;E;moMR$q_eED7emh#o;gj`S9d4KYG1%4q{Vg$lU5g=k)>TJ1y-Pc_Ie=h+2 zSt6R;y0>S3@%XPkN#=3si}#Mmn=qPQGBPPvqPO-63JbNk^ztVYu1ET7W~FkDIz9Iz zciY0AFs69;=;@8pbs9v=cfy~(T>xZj+yF@8)}}o^6KoC0h1Q%6vWd6VF281j;`DW- z6nGVyS7m%J5)T1gHB$s{x~}ZwOK1z9Z!ixSK8^@}p`P;7DE_3Zd>ZtWB0ncbvzIoh zT79BIVo5^*cgOo;P~wY{hu6%VI9Pn8+H$;}(fGJ1?o*N2M;^&kH72~YnAzB3Dz2+qZA&pXcoYl*ZJTJAt}43Awc-)pc4g@WF?13s&N&N(pp z^8BPBrHgrl#^LGko3XvBvUtZab|f7k3k`3tyqsu_;;(lp{>u5>d&2{rqSeyCs-txK zD62&LP?j(j4RIGPYTiW4PM;x2}flg^E{MvIp_IAKF=5 z9BJ(tvA7#1bqRVQw>WmtIF!klKKylI@I%!I>{q(T6T0}rA^&f)?R2zS`9Z?Jw(9BX z=)>DXG*j4dV=jLnaIAi!q2B274SMD!1=H%O?!)O2;*FCwR~C(YX(5rud3SRT5oe|B z>=`aA-DB~HGWBtn`lNpTtJeSq!jaM8s;~wh7{h zltTCbldu(*eZ^j(FILz4*B#+>ciIwzF2mZHc$Om>7+l!}3~w-ISMN4c{j(h-71Efa zYbtc+21zS}BpRRa(9$?YAedAEwAg-4rw`9kqdJ5@V8afsz8>d3(s+O_y;MPJDj~Jm z$;r*D5!w|p!?X$K<%OEMRRtf^=IKe%4PV&dQV24=sehlg0{ZOfq-|wQ;#S7%%KiZm zN90dPR0*Bn;-u%#vR`5bms0fI`;IOxC% zEH?Rx%7vg_;0V$eLGOrK$?)=M)<0I-A$RK^d8J)csZ>fFC}iGH4Uu>@ylNP3oY*{R zX?vFFyE{yn4iyCmHQS_RY(D=jJm#ZwM_J%KuD}xqzG4nNw29kzYbm94G)@IF@Boc@ zX@JZZUfJ9$0NEO%+-j4XXY~b=>c8|JwOATdxf?$CM?4`*{&~NoN$fxu+?RK40LR@X#v`yLby8E`6LWo4=9U^m`5P1w+_HPVFvfrFTT`dhu-Wo~kbQBIhJjoO z&OrNgg>kZ5U^Z(hR1|airl`_Hpo2~6pmcw&^RuV^w1mG4d}M~ToIRUGm_}KFV!LdB zS&pqnTM>n($*!OsObo=GcN`rqDo7HmuM9|fg09#!n(Qt6WoU+Hm5NyreC_LGS(AXc zW*(#kG4=ICTT|CDgC=CXW)x_(oSu z1}PPEjUz~rGDYx<1I9wr&nh_HjXI3%FcAY|h;-@UMC}<2HIJx<=@9Sm@qWIr<~$=+ z?UAntm|6zMzg*Y93@f1AN#(t7^z37nJxR^pQOgt4#(U@T*}1mFiZvMc8ub>=x&c7O zO7u`JL(O5d^psdnNFs=6l4Hg=vyL)NcQ$3&e>335dO*Rx46TgCWa(}mrr;`0BpTP` z!4$RS;U;D>ji zlm+i_ekU;Y;x>*~LWlCD!H;o8%96Xf_#;5w?F?Bk6zm?G`$|87)v-zh`8ixA3}i5EMXo0=qH;3k7b%Z z$_V3C;%|bzJv4sRgEgn5GY^D-b2ZS;0c;aDl7x_UyjtWJcBxfC6K)x*JJrgRHVjYf z=fWg@5^kWqu@`7AJ!B80u76W-dYGkdlc^K!wzj|yMdwct{pU#Is|;A0c#hr#g;YNT z-6iOExA$C}t?t>3lCw0E{oV|aAX1q*%Bj#M~q{urWA`;L^} zCV&M-I&39H7wDM-r~XKPjZA%dQ})5b_4)8wROp(!vba6ekMToUwXU=B-e|TtoI6157dbV-7>}KWV!z^c1O|_}{po8*wV${l#a~MOwFIOvoP6+*+03PV%hjAKID@sqIU?t@yX(mjr5@R;l-Z~$yP>#7bzy-I`q7}5zfVZPw z2VdierMMZycumbtuX%}+Qw_iF9hW*g%6nml6&BeK)V6S5Bzk0c=?wp~<&me^WpH&oRmx^+zR9aRK`W{XuGi8r(J zP|yhg&G+$ElJHk&Q9%pg^>{x7A0$$6b^Uap|6A87Tn#Dd>nN?fG{1JLs%3n;(w;5y zg@M}UaIGN%9ofhD5!Xmuq_9rDh)Dl2Sw3>!>fK?T=fWm52VN=+@Z>ox{UWBIP?Y#c zx~2|8yKxfc(Rt?Ia@tejyM3rQJLXX|av9*J?NVENNZ4TKs&f>BLByZ-r8&fZ9Lgjh zR7|JAsa!+IBQojO?`ARZQ2JYRur3Wu;L9FzVThB|`y$=^R!v=LE_P=de6g#_XGE9i zxY2I*l``L}n1f07mHr7X={FVx_WVXs|8n!ms#=r)}}SNe<0cG_Lc2dwk(WH9U}VLYyfJ;u}365G(=wd|s7y$E5dx*KgrL z`Ud~MpS0;M7}SJ%%GlGt4QKLSb^xtjUB9!>d-o$<=_(){=QD8n21bvkLt*_<-_Wze z+SqTKUjj%6p(FKyE$ctMPTgJZRKRTPeV_1vo|xwxK{*)Zd{w5-nUhCNhwURZ3|$(0 zg&nkd>OU{&i5hhzE70j0IXz{nsQBJcCXn!c@V`^)3c%Yk-8G0*1SrFVH$*&kj2ln* z>|Y%d3RZ^tSDd@sb=!O0hn9xiSvZ|hOH)va!)up`f=A$kXWI#`*kB`wEp#hyRZgSe||BT5sHGp&cXTCuMdKv>eu8%MI$O?{4gEJus zDlzH1=%EC_p_HBrcZ}EC$54^OCCoJvH?c#`dvt0;Z+3c-o$@Hj#SR~tcmP?`-l<(Y zfP0z_n9VJg(^mJVa#!^HRe6A(4ZUlOkW`;e=guAf@;BpzGIvDvPrrQ(s`6elV-a!! zeOm+|@SC~7`&P?2#X@59u0@p1JPVoM3`&+Q1BMEE<$0Xq34znbPi^%=bgsUS#*BTt zO|qY*Ky)wZJ>AB-yYDGm_;_}J?@cYedemjVye&+vpXcFW`J)(duf6J7p%!!ap<*z0 z@nU?iYP7t&Th$2d=;&Y;#K3+C_^Q~){As^En68w#<9PS)Z^5nCZ+3@h8Rn^O4V`da zU{63Resn;Rd>q6XV}AfJT9rj!*e1vf>( zV$w8C>F4j_^CJc2dEH-hR`%W`ozTdiIm!e-zfhx3_%4u$`!6d*;5Qwt zP90YcGW@~eiO&wy;@lq(If7Qm#_G0CLaMq{54!rPkw2SBkZV^YxLC4EE5Hc;pJo;aW;HY^sU2} zhMe_;5Ii6Ds2%oh6t4Qmc{`ck+=o>Xz6En~;^cQZ2fk}4!%pg^ESo4v&M0SgV2to= zg}+}$y@qI|b!10|%f(-vD0=7-{Er=b_~36h7_8)w1K)w}L@)KK{Xa##A`75EIJ^E8 zw%oHi z#L_+C2ePNit<(2I5-SZif`J@{bz2<9wA;{0N2~t75flSZ#^)*DsBxSzCcwS7lyKAe z8CsU2gi+#!lPSi8nXt*jM{4Qe1e6TI=30VLdl%B8U%sl*0j!_QTK~=Y&o2gF72!OY zi9hq*Kf%N`UQnmc^(H;^<16>&P-!o8VDR;L#pwj?4MF!29kA+lfkuOwh)9 zr&+p|cj(sNImGU9h>@P>RjGxVsUA0kx2QQECIG`5;3AW4&zHeTM+zbkiJ|~WJ|Xvp zF4o<7wa|Qz0NCf8qh7|Dny_{)^!(!S2L%ecFpxDK-5p(ul^M6H6_lfuh3uz+8^VKj z993X>`ap+S-d95o?;)X^MgcugkNE78czoL+CC0<)bFbw_KoDi!8jOT||4mtS1_mQE@o_5#DCSG2yQ# z^%)E=LpHxGS(D+A8>E0Wg^*k9CL##}0+CVH8X2ffVD$pp~6`@1N{ zXc+&U&tHn{+je&N==Z~V!YRmq9fRhb=%Sa?!)5N3o^rEO(8&X3mT(re4rAhj%w9!j z4VF@bf|{*1xqj-;HZmW?Vh>yGCMj^ue_YT0*!EGBV75Apo@Dq9(XYi6W%Y4}WBSgb zwv)8eZ#8?+y+0;@_Mi^IYTNUUN4%*Hal{&^Y#qJkAMn)LZxx>(KkOY!56=AASl>9u zfTJ4XzE%VnObP3?1z20&51q~;lGK~hVZ7nSX6!Vb?J((?E`=gKgQT)PRy6YE0hd~Q zcyYYV`&Yq;??^%Db#(U@BJ~X{=G;L#NOcMBXH@^J^N?h3+*psJc&?tZ zYCK|$=$Lc4c;p&ailcU{6YXZ}0%YVODIesuf}J?c;r(xgc6Qct#yoy@SUA&@d}{0X zh|YHkdn4p+_Q-ZrjfM5Nl8Wut+#1Y;6>|4x1s`ws04&Cm*bPrH&JSjdYUWTusu)2k|bg5kbN)ts&#3v*pG9G z0J8&6Cwk%v;C@YR#aY`2I9gwxz|SEO3&Kt$-Vhbnu`JdS=GdG|8$vpVkM4#mj8@Np`-|gL01b-e7B`&^0_E< zr+ZgVZ{x^ny??>Iyv}wFfB)#SfH#Z*KM?ZN%c%f-bAEZZJuZh=L94@;0~IHLQJn&V ziuO$Y3B8rb91b_XVPn+{)7|oMqBJW|Ws76ZC-KN$U-c2-<9zsegWgug7 z{rdptzlG~D=zxmi+;`4GEJF0GC5h4JI+{Nxl=A-c@iS^nu%dKwtvryUj4`d z$Ig$^eK<@GwTzo3|Pp8bY#s#70ai^J~;|DWqwsV3-mlHo)6Tf9FY?8++ zlyz(&qscy`3Oae(^$aYKZ{YAQjoVx>XxlKu3~5r^p$g@-m~KLU)aJFD_iTLWZpiv( zzm?N|>#Nl829KHo1(~18j!95^?#ni*wGaZlgU&1^-kSs_?mZ+K9%!{9bjsw&)etP<%#q%Z< zm9>21gVOguQxGURGfyAJ{I&1tbo;ipxPR!#9L0IRCpvv7Dx0Th7b_$VHhDT5`}F_IQ%0yYjyeD`;oPgk!GDlWp0-CI2O z+qiGkC(>P)a;^@)DwICCVH5jTi8pJ1pL4z;^La8A#d$Jy%9X`obrys6_nv+t)|I!c zx$(BE#;gesWMaGG-opN|KWH$9cVG2Td?*tiw}|w}c=DdVJw9-?XAWJ-9mu>itaxM&;67;rpuN0q`+Cv=KpR# z%7~Q9yNIW2)JC|T8sZx}OWt)qK|#ayUtBlt7jnGf`?v=blXp5|?$OV6bFXT4c2;b4 zAnZ$R-DTR;+yZ&Y=j@N1`#@G8OFfGctCt?UnIqNzA@I1+fQTr(Q8Wb0zX@Uc#C_S# z7`QugAZ^8`pu=oBFT|VmLaG{=Z|Sa4w;+3I2%k=>eRwyD+){bMf&Q~((XQ)R+%D%R zRaX&S{Tp&rokdVq7Mw{ol_+e2b`GU{&R4k4q>vBSl9CU1QdkW)XP0N!9!cz{#eZ;* zuY96PuS&W82cNy(;56vccLm2P8Xp+&rUQxuuHW8>GSm@=fSH^F4zv5Xr$|8EO+$ky za;!udCDjQ<{qg8p#1=Gi=UwBp$8k0=J-KEOmjq2|ZlZox*rGBXzZG2hWky&tY^-WW zS(QTNbNpvf$`2iS2PEaxf`zXhe|q~5^JnLmEc~3;L@d@X)i~=};Xh3Gb?#cQUKRsm zL#4nIE zK7Ec(W#R4%B!q0NaaZZ6@Xg7$RX^4RGgqZ%!o zlKr+`47!cft@bo01Kf>41nisR(tD(L(0OfznvG$u{BHjjd-~C^z8c%s=O;e!=)=cx zR`ta{MT?lnr=`~V^aI#f^gC*_ljBhU7wgJ_X*4?0`T*ITwKRCmywUJGOe?I)T4kUm z)41yD-F@nLJ#mk{qJgllLG@ko_5T>#Z7Y|Z4_dUr>e<4;pnN>9B6uMHoDB0`7@hW3()(+C>!z4g~W+j$8 zYvPBt&QiBci?EZ$@5m%5$`Cc7&RoGD9t2N0- zpg?S`d~pE>yegw`(|OZPb=OLqZsR-IW8+=?IrUgIw)Y{}@z7iwmOpB&3^;ntik00z zeoo@{Q(~*UB-##E*Zz6+xNv{?6<--V&FZ`{N`xSp@EDxD7N~Gv zEdl|ibjp6l;KXR~^7j7%zY@j29}|}o&#($cau}c?dRbPT=>qLXYSPg2n!4+vbb9D< zdSp>rji_YKF=XI{PbsiT!@>1X<&n*ZBgUm(eVl@FW$`M+m$5E`lah8sli|hK#c+{r zvXAa@nZ>%rglv&-=6KLq%hr5LS<8KRO~u(({p^f4`A)nMyQ!v&Hm|czVZ{SuQm4R~ zA)RvJvvMR_HrLVYSWi3rY-l?lYHgx@p#EN3aE>{Cy(NH8U{H5GI!j~uq%EimWydQg z_^pcWB4dB}UzJ%d@~jM;`sI(W6xVx5RIMVQCag?ht&Jftu|xUFFgPiiGbQl{BCBKj z7{=GY04(?T-R|J%up#B5bRYEj@exF;K74&(xTJq zC#*U76{^UZPA6>NO!w)x;Cj#oA4u%!`9vU*m99P+$KrAdFXn~P!=IvyVF+zsn1~b=iXDs$brllf9vtYZeHaD&nvD zN;o=>O53c{wV-|VBe#hKt`J-&CR7KbRm@_GTI%^*Ier-t_GvPJ*VolJ-iM^Y*)?1` zLH9w1TeIP|Az488li0ftqRY4ydzZMeNhE1$!>2@FrFUA-2MbVzp5t6U zS%&cs^agVC^R);!UGRL?7X8te?|qNZ(Wf5u5(w5luwTaL^@*>DfWYiTf=slbBsOcrG1!sgawZ$MeViaO1nZhpaU3=0$JKWVEYp2g@e#JV-_3foc%*cdS@KtKn6(q#W3PEf>?MQ# z3)P$hXSJdL9>^-)Ny48tuqJaJrL??ITF)UxvJk;=><{Zut8s_=MpNOZkMbvckK>tB zE97IkFZGN4;I%9ZC;2DVknVk_+Om8t z+qxYVkY?1qC&y9@H@`Wo3mW|szW4$Jk1c|V!$RABy-sed*xdBJz^UzLvmoW2VaMN3 zw>mLKSwym7s2AT#y$GJS3*#tBxDP-l3$y{y$yOTJ;&O!;i;%Ez&Pb6=UikTs7^K|n zB39SyTET0#sqO^ce#b`VCQi+^!RaA<*z}o7vKkV8cXHFh>!}k69mWd2p2L)mcU?26 zcyeeidl(lFEaa>dFuoA+=q5DqDk0?w&~=!cR(%f%;k%1^<%JA;qF^v%^c#At^Z=M9 zuvI!!J@}<*2M&M7rkA(zy@O9lAy!JUFnX~|7}OX~Aj=$!=bZEWM^*0&)0J@kKKFww zcv~595SJ~1(A>YP9xKrS?VbjFI6y*7qu^C)Wg)QeZx6w-7F`|{JDx(bd{2EOX3bKF zs}Ow5U{0|Pqa&r->N=8^%LYLL^Z`^m ztFt{nbMnw+7bGsB{`|izj1OiZ1>ggOV{cRR2+`*TtTq=U)e-|O48Mwll$!{&r6#`L z!J-%Pn^19M5Yi`({mdYNf@nol>X_=y^B>xNJT%<>@W_TGdg$8-z(GtvX{V0H->!*| zX)X-+xD^(L48r-FCF2@LI7p@m>87muhEVJVf3J`=XcD7;Cd_ha^g)LIrXla13yPj- zMxBe(1kGa1GXmc4kjgil*hYNJd4&ne6}Gr+i6eQAE+pH@rIb!H%5Xu-`1IaCLVI#EY{+9f}{)C?6a zjx^54*{dU9ltlOl7+%5}E}7t1ssaV`5_!)Gq%*8SHjQRyv0O;Z#geY$Mm{6f0Ikh{ zZU!eD)`;HZto+ek^0vvQhbnR3y!{2n4ruFFsNJo7BGLAJ*U0UY*3zpTE{-GV29wvD zs59L^srNZz8=IEkiy7jlA}*chFBW#Ma|mdr>h1 z1%4}+?i1IrZgfR89*c|@lZK+Z*iQ9W-vTAx61~o|>%2!_nZ0*CvpODL{R%l|o{d9; z*XT|Q+XFM}tlBx>!UQL(AfbiwSJzy~ox$aq*tQL4PzL8L${Kc{D6G<)~^t5GR2X|nt z0ms1;YrGoBgmt$?$`d(D9@ZFjtQy~j~(=@%%m^ZN6a}0xVhf1llPz)-9j+pZSdHE6baT?~% z%o}U;J36wNA&MIn`hlu0p_L=6qGnY=(u<>-R>*GtEwqz#x!0elw*(xLspkX~w)wrVP za8-E`?0J9PKI%X4PXGf40!RT}+-wvxJ47s_EN&wsBbDE+prV)yC}#Tf{b zct=uP;;gWdv-L0B5?U;Z+6gEs|HDAliP5mQ@>+L1$HlQd*?-Bs7UHXPs+ug(~*r-0`YP!1?7|rdHt0L+-Ogn5ooXNKZP&=;MR%y5eg+aVt=Ug3MU@PWvc=(Y<$;p%0GdyoY736hXp zPw1(xVmI}mDOO>7e|(Q>nnal_l5-k#zFZ7FvK&*TQ@R36dgFb}hTjiheZXo(_3B$^ z^iU;R_XP|5$CCCrn{-Fgy{|2is{`_;?_HA1)Em;n@72sg+RqUVrw4J~P!osK&0ao* zor|=ZiRt0%!U2cS7Bz_UAm_iGDz{(5t%bS|V}a)S4+spZQkkp(rA@mt?Er$K;yfN@ z2__n4*e-MN5^$FmArGuCw_YRCChjr^$Kz3}Zw82nlDejcpLXmzgh=%;81R)$bKYr~ zKl!>1W}^dX`OdY>)TTErMZr3Fdqn#YO@9yScsiBud2~r`669)yx8*X)ho|G%KLs6_ zeQ#9JZFzkGMUVPIWI_JKKGm{b|6NkXtQ1TD^Jw2mYNA~w(97z}xoUU?1dAKEC|@-$ zU-@iJ{J1A1&(#p`wdwKn|#7m;R@&Zo~$ylBk^o7ZX_K?n%BVCppK@aW4d^o=Ai~ zI}}W>FDNrxljBvGuAw)Qu>S_0RHi`QsI2^u_Tk?|7J|I%LNk5C&AzCxoyNn~I0fIc z%Nk$RSnu_~UMt?n`;w*)1>!f^wAu@0O!HnaTfEe`-nyuw?oFy#?|t^4l4u#T8h{*x zcWU8AOw^8%U+We>nT6r(_-^Bq0JeP#bH})VJI-n}SoT}v00AqV&Z|FgT$ElZa4?{C z_2K|EJFJ#JQ%c`|Dt^+tRs*dvGn&mJ-RDFCUsr{!naKg&omS;w3MHCCU#ricMtz%9 zl*Db+G}Mt+gCJ{dB=SI7W_M5ky)!hYKpkxrutKW}@!y*EyIvdb?BNW%;LuGEJA-YJ zpM6U-4GI3_)g{tjMy!PLaN^IBrct~pwtGui%=EgL=SeT0pefZlO^6O+xtQlFNzqzK z7T9z76R{d(D#CK4TptC~CAt{gB0ge5cp~%?fMVexLgqAhw#JOrJ}xgn?~WD26rD03k+sU!gGcmO>T06Jwlt2VKl?=da+G%0i9*hT6rExP@p> zU|qL86ft&0rOgCeW1(cYMO2D5vJ*4mfor0nou&Dd`qOK&+^ChzfQc5i3ALlL5+*i3 zlUmebX=q}hT;;iNo_&iglW6=(l2SQUt2r8G3B(}N{V7&yt0 z$Nvx;Wyd{yZ)$Ojm8>L#7SVcG*K%>4>Sez7U)x+t!PM5mqI?4px?my^u>F_-X_7Z7s|!Sf8^Qd-nM3c2Ro zPA0pv*%0|k)HXg11HvVT7+9#iHM*P*Ux?IG)=$4fnnjy9KRk%6olf`6&;B63#kx1V z=p@Q&8T_T;BNZ?4GwkAa$F%ghmONCj4S$Ka2iEeX{$0$PAawFF#|F|S;B|@gxiUi( z;5_?oSti(XoONONMNy~T_k)FJyu53=8DVP;-sZPS7I);8aP<~HH`{GX%m|cxk!(4$ zh&?lb=wdIR*v@fy__>d1T%hdmaDS!A5TD7LyE5KsBbV%lFGOFAe2hZ&u1WW4WlFj! zvHYT4eSQb}9(Vj1_A`00yl}+AKaR-b(Gb=Ih2Y0a=AZr0rH6wp7$b+X&dx03y2UKN zNfFT}TJl=hInnthy&Yujj9i9`Zd52ntVGtY=+J|R>nYxbgn`&Yw-4n_AGtuqh8@yE zGW?|e&q;yxvfy;=5jBbP@h;^NUGga9aT=UFe(Lzf5-l#n&}EGzf^(g7u>Rua4pqleJTZ9bxyX?5m)M|^DO z=`4Wn757Ge3}() z&cQ&8a;+&5Q+FhQ+s^?glc-hpV&8lt_Sn^II?yDAkRSue8V5@e>!U0|S2_O{gR>;#-crGBEpJA2 z>DZG!+Zl)(9dhCNQ+pDE6(>{*XXD65596nGpIU_2ELn6!s(*+}HAW2?_eT?rYq>no zEN57wlx7F?ti(n{E3E7}mtW8z%tSsR1iY-bs+`eC;XX{LJNX4}?9p^Is1|lCCGT)O zeeiyKG!au1k-3QeDgf;a-~E!?o~L_wzl@Fv0J8dRd}mMV*wG@LDifqKLjcOJE9k-b zkPu(B03bADdiQK8k_AcPizKr-?Pn2}rRA^0tUnqFDndkLRYa&gFpm}2b4x-rM-bEm1K^wiP)dT1Mt4pgWO4N7i^bjak+c54)G#wl zobO&B+edrf?_$`C?|xnQE5^GdUR{c)9iSD?=4UF(90n%sXW0YecnTD9IiE4V5X7@t zsE-G$NM}-Qckq%KxnNUiNy&|0Dfj&9WP53n8+vX*Ckz44?6sf0I)P(_~5-TTvNtqm|=BU+bk&9dyf zms>T#eE6qGV~r@DXyelhjr`Nfl?x3kBecC?$Da_riGKkBXW#vm{r7PA@Mh?^p%5Bm z>Tq4*X)(p_dKd4}%{0PtDJx{%^%H_@p=MDVRTzYKIyd`N-(aC$5wub8j?&uVDV0t` zy$(1NKb|>T)B|=B=X|_on=2{Jm3MDIgim-b@v6tCz^bC%cU_8(c5zIDBt-n_gCMOz zOSur0OTDAu%twTZh-H$&zmsv#sHAP`(55$+<5J)k9adn&!|*SsY&da@Oc)v`!Cc1N zT;K+D^12cpi_bk^f%JE3*dE@#EZo#e9TF<*&jJAU*%RSUOc?%0dHmjaql-Edgl1T^ zUuv02e(tn9;*yEw3Be-y3^_kGQT#fyEe1wWC(7@@{T_&_wnYPG*g|*oo-ZDbM|te@ zD0OAMv@RO)CfGhER3+KRGwG*IY=^N}jW-$I6)tIdEep-oxy7v$w2$E5rOB}U^X4u8ul4B_+y?1RVDe-ZSpvl6{&g5T zZ)I0&wXD#faC4;>9tqepPY<=qtbh>-DVufAr^L}7UNvuV=&sGDz&dVxht#^|1Bbpo|v_((G%}mVaUDcFF3n;v$p|7rkPMZMM zCMhO{>^D_X4=EH8Tt#886|Of0cO5$~o1=h5T;@P6MKJGS=CT$MDKAJ15Ape%t0|lc zC`CcksAweCot=1;_x<{yecCGMh$Cd}sCVxH{Z-!d@9_2Avr%cT8YW>P0dbN+bAjys)a3`8ORT834RjTduM#Yj|^}kjiz>M&t z7+r4uxYW-uPk2Wt89u2{mtkdjiSIy)J<~ccqSrGh{Tcgt_J;xJz6quGs zlP>(@=+(8I47jS%g_%6*+0I4AM&)56cYlEWay$b!{6_4;uGdvTx)z`1$^sYuY zd392M`UMq`1N0UjSV4(cb?U8uzybOOhydH!JlgI{VfUYA4A^$++}cC-7JbH%!sgQ7 zfsHY*qwpKm9?P;(j>lfb9KwFa#dmgkl)NmXc}(R+S%{d2^8@j+rL$F6n`1kz*cQwm zuj*_bzfIhj@Cwb!T69|Op*KBL@aca#BA`XbLUJQvtZepsz&Gx6KyNP^aN1&ysdBsS zD~S{0#P@hb$30IKGov2Od{&A8aAH0Nhjl+~^mAO-W+dU72T+sL)3f}Au0K{M8FFyXqvKu!P3TmJ-YD6v4@4arz)Wef&H-3fNF9}4fVBKueBRJx?F^~F_(Q?Z zp2Gq^2;5pE9chMt?8CwCIzkaVN2&6F-Kr{w-EVmw8SQ;i^VR&}TuIE|FP?=tRmr3J z>I4Kh5zppqqZA>=?NJDBu=QHkdur?!_lw4wSHuwpZvl-UmBpc<_{HEse)m;u1})^9 zV`1C(fkl@F|`z) zjm^F5Y!F-ltzv<}Dj~)<6Mm<4JZ*UUD{x=jmXzMnpY+m3#lgy#;HtZ>q2c{g9H1KM zdt*#eBJ*T{`1W_!VyxNu45 z5`ynQSh<}d49?%(=9^0WpXrCPRgk_ox}erKq~EA>oq zzaro^DdB@6yh#uMabwd-D&TxHIDg3C%5f9>vA6K^LD*Jn9SV9`sr>w^XcV$%bHEx8 z6$2937;N-)hBrwc4|I?&2?^fOH zT+EiMWmYw6&|Bdr>`CvHO&{D>E(Q>feG8xbI2>%1`xod5Bm%-O0>I#^ z&Y9ivgwX*jM2G1#X?BzLL!0l*<+VT&kWA4G2{#qNWJ?s2EuC~6iKGj&IX>H(n35`) z$bLn&GD{>?Z5vN}W3DorEIS|Nz5{}I$rJ+l9%mvj8*fVb6hgLCN=or z{$~5Ku8X^$I%@tENW-sHi2-$HoAu|YSAU?UI-MuzyvJ13ya$#r*!fMIM!*?#b1I2{ zog07$J5()s9Z1V!q9~-Xsq&?Skohzs$Y<55@7nBInJT z$87%n1pI7WozY$E77L@;?)72`2tx?!ycV9^Uc!4dnG0T7^U=j~W#==;z4M*%f%>rX zZrbw`2=?dAbyjC1&JSazZaLW@TjuP2{pV0P?Kn zBJF{5W*wXbkpjJ+P!j$EtA{_(>d6Drcw-k>TgUVBU0YHC3 za;VGzc7`?8+Vb z@$%xL#*PKiR_Ko-bopOM?ECKABq$@yY2{@a`%eG_9a1<23OB)jfEi|z@`00=taYlLE@5;Jq<t#efB8l51MK0D)g<^-}A*kvh{3T`%o!Yy@1o z)W4CI9pC#u0Lwr$zpBP|8wqdD+%+TmqtT^$7J9`*x2#is2v`1oAoD> zBMftt<6XrgDt^xVlE{cU;NV~cNXbhPJROD#7Vm(}T{mRmp5b#A11pln=&&$x?!w)@VZ+!Q4 zd-{nd?Z5%;-<-%%^g$K?Ar;jJiwFkb3zN!z|Fj`G{72P6X92IcZ6d-B|5gq-;#jrv z6?)y>FQLFvgjft$g;>^#e)amQjQEN0{!~`{Pkn70Snfs`up||K1Oo^VN;fbNKmf3T zP=|3fAkMqD`Z@+h$6>@uH^LB5Zx?pjMP~ z_x`8xqzg>t0WOVwYO}88crrnjam!Q`DvWT8_$q&#m*Tw$9?U^L59toU`_forQi-Nb3HF;@9jLZF1epg^D$01Qe?mE|lUkbwa6 zcNE{Fws%5j`ab{6bN1a=Ua`CGxXZ2nXQGJ6l8-a}qOuSI@Ln{N*9ZiKfx-0r^gOB# zI6<7c;KTtJ;I|n(fTI&x3K*Y57$M;}7aF0!DTfpQ! z$874sn{E8o12#6DBY=(ot92hefLlE+o^^!|7DMLW;~bb~VtF2A2TXw-LKPRR;F04Z z?6|M#hrRwepj%p6vX4If)ZYEayY|c9{M!Eb_Mhzf^&3foA?>X+RZa;?uMz?!1bPU8 zQUK6H;FnpK5ZDO>>U>|At&bczY~OzN1$*x4XY8K4@3j*$^fx^{)tod$75o2CSBLWt zb9Zw%d?2DA3Rt1cAqw&%4XH11bH-mk+&6<=1OqU1!c;J1q1WLEOk;rNdqpbzZqVjdc)mDtZZvhx};>-sS7Xq|IA_G{t zvdFuG0H{)P&-ng5Hhx4#0*}c?z{vwPb>DHDkm0~Fj0P5Qi*Y`3=3m7?t<5#n9Outc7Bwv@KO%k)?^3b+O$g2D^@ke4R8v82(VO;5l7^qF|MS+Ld--##vKzjl^h*Df~3okjp zG!SrusKQvH!!vo$3GQABUs+ssW`F(EIqk2#Bm;lfWXb=ARj=qMrnp_8D1PZbFc6?? zXt(shGXDUYuI)bvwZ?hdY)}xPbRz))`uCa;--YW|xw>rQG8{Pep>W!JU)kjChi&{D zMl0lzE^9c=o68{ivrU7WiTa7|53YCGYAJ-FvSr!kHmK4QO+Ho$uyzAtTnYc2?= z$`(U5=_Go2DU=qSNsy6>HdF&po3K4MZ* zKMPyegj6Gw+8Db2#=IA83XFqC<$)jg7`!}c&g-mtS2R#3bdQ37EF6HV8*tPIgeMyc z7#9Ta(mi^YMx8T3}hfi$nFS6(_ z%l_3xt@yi9KZR|I-y;9=(*QsqsQ(YD>VFo%U>mpk&VzGU*%0OX$U?wZgS}%2j|q_p zFIFW8s7m0uaYiQy$e^h$uZ#JY5ka;ED2Sgf0l?DpRFZ__LhzxV9N>XA?{cJrbSmO- z;*%ctQFC7BSaAU%!Xyg^V8*w&Z~#pZqj}gdUx1jOo3|r}4%?o&J$8NRhAm!QwB?m$ z*90I~tt~xH`BOrmgg`$+ptJ$dkF8Rcsf0iZ0)hFj`ow$tt+&~;+Ux)Px1O~J?!Dh7 z@DniiSqIb4@qSKB=~@4|&WSV4@G!4DH%#`qF^1EV6(a~A?(TGtk3}_(uyeg`0WQ6| zl!hbWAf&XdqH=9Xmi%>u-#e#m{iE|by6?JGZ>(6AXBV)?1(ocu$_4N!7FC>lA~Z3flDO?WrH;Img!u0bU+82MoDj z@Z+3U1Owp1g}~bBgT{d1vTHZ4+1F>!*)M+kYx}?d*MHb2pM7TQIwc@LmiBLqQ@)iD zC?U{45Gc0*^iNxqB`G0LgFv87l4(?v==9W#j`#bf{nP8O+vATsYDbS8vpuu3weYnE zCfq4ePY3`K0=@Pv``|0q$|I%bmkl!1?~#zK5ki6)U~A=Q5(r3N>DQh2NJ#RWb@icMa=ZsXUaGU>+PXs;Y0PEK0g^1`^&dSzYJ^a^$>+o8=z=Q)Ia z6Z^_g)U@9JVf0)eFa-4qJsyc&x15eu+!XP2t1Ml}2LKBvRj=TA$8VER;83%{K;pU6LrvpK&k=w7YJUuqxjSCh4`ES*r+Jz8NN1?VWTxKPS77Lu z>Rv?%pce!wd7QfY>D#m}HxQ_>%zKGL@V9^Oe%m*<*Y@w(fVbX$+m@Df zT8-cvKwAm|BFxHr34wlsK&b)HPpwgwrG$VW5GGA#Y0b}4ML)Q3(4K$pIs3tD-?RJf zxyKId*WO8O1!!>2%xa=`b${KN)bkvP!_<*{B!WU#d7+2X4_E;w?tm%Yi)sse99|HN zdT{uqfR=i!C4tJT2;Az27p(gJIWwvI8%F&Wb%dW(Up>LRc(nw2_rOZ^n$Cb;U)MH; z6v5ZK5)F3F9QC(R6~jZH@QyUt^+}hW;lucu9G}#pq8N$+cVS2-?bNmL8F0~13IV)> zY@t&SPIKD${Irc9-DeXg58C+MM{M%0BQ}0mrwPm!tX0MI!Qpg2ga9>xz$W?9zHvT` zczu&7L-iTh`321MTqFpf(heuxnGX;K@Sbv2&52j9FWUPbeqg`-{qO9}KmOiMeRRr} zmo?wHD}?|laFvfG1o{F31z5E&%2pPlguuu^ATytOz4yw<&e5aC?4kP~u~pn?V)SJN+rHHCeOmReetOC5+G;TD*CKAKVsz`9(|Kb4D>@Up$_g2Mt8}}900ICA z>5ID!h1>?Ju)vIl9?_?(Znl|uW7v4c5;M$5+zFxF(*$c4q zi#8@XO7maFBJR>75|^VaVRSo~lzc zlt}fM6LUb~aB^5CA6*DghsT)W?ccl49=Pv*X(sNm`MvWtw`b1Yd;dMVx+r@Oa%qs} zfxVtu`BXxngg`eSPznIL0p&7}u0WtZ!7#HGxqg>Kha>(lvUB&HcT3&>5&M?*{D1TQ z2W@U{PV;bPc4oqcp{=cGXTC=;01_BF7?GU)d@e)qS`t1`j{b#l6&x-#F=CHGo(h2m>vv#Sw+P|xB_D`_}wj?nB z5tf6|19k%HAmEUmgNLqZxkT;+}Q%1+4RzA=< z^U|CeKeE>*ZoA1QA3R}`w;Z%F2?5-2V8rXOxyFdBGNNFG9011F@x7jbYY}KkhwmI| z8Sy>u1A?Uvp5C{W0JD7P7 zSAD=Ymu(CpA=mW|0i^4LF|FB|8GG=72kgf`d_z|LU$#3nq2@CGsO_QOUARehQ z%s*0lCgCCwSJvGd|8TK_q*aH{t@tN*PAQU4XZZ%f2>3N$IIFqT8@)XBw2G2EJj zl!H)j6+djx=;2_Es0kpBx}zC%6e=23l`GPy5`NwIMBAyfjmqYxY<$m@giXTfxLkNC z0ft;`PC%L)js)c5ckWrif(ICpAK;aSMYh`UTNIk`J;Io%g7M_!q-y{ilbxc22M)Rh zz{QJ~Y(w)(J#g>nEs9*a;e$Y$j!xGu&@!n`n*ONgfEM_k7iPHoX=wu>(;3Rw{)Rvp z2G}pSa&YRI0hOBo346^RB3&Vdp{85CA67hfy;Ess^~V zatr2isUm8yT`v&&{5XpcVz{?1*KMSrRKBRpskuPD8q`m4OCaj!`YcWqtA zb@j9`!;yJKcxjzIvj_l20HSP7nh>tSZpr3@t-PSsQ}+M<*MHfsbyC2WUwvt-tI~*bH{8rsQpxhxB?ttglbUHY z@4_F@{~|t*_oAYJbLq~I+R)p9KafolrZN$dMMIz{y+QFWw*U-EOO0?jBZH3wnSmTs z$r_0@c&_bmU15Mjn@3^*App|A2@$Ze%IqUQerrGQvj}N!&mOx?NBq6?-1GLzOE23U zx7{vH09pCZVxBlDv!cznq9TILoOpo&*%oNpU)gS^2;l-uT=kRZU$^^Qxu|5K1EaWlr#UlsU8@Q=fPBQ7005hlap_R-khayQ7K`R=&`n zcZWx&;y$+mBSqjefp}bC5)2w^UMB=RD7ygr_wBRWZn@ch_2!%Qx4*w@mo7_iE^NV+ z8eAz1h>$4nTZ2I03*ZMdEOlZLeF;At^mVwlmR1NAkO6cMZfuObMDPPVN5OV@_5efh zQ*Hqmf<_$1Dg*{uD#>E{xz;fdj{R$xbjcp3-;em)g!zw*tWVZp5sacRAg{7C1n}`~5$a5FrHA&3R}#;S;a$;Q{!cDi<*hHQ`p3`B z{&v=?pGg34Nh+z!?D5abWH9^~Yp`yp{<8(3bi0QDeFj5{qvk}$JEjZ*R*+WzJCTYi zWFQ!OU)oTbFz58XG<{hDHCI*J1MIp40WuU=kuad5EdmGyIAx`(d2(#ebTV&y(>CIC z=0|Vx&X z;$@xrcLo>cU+-LLN3s;wnSVVykyFnr9dxLkfenNQDxNU@T)-|1pIB)?0+Z{8qI3sN ze#t)vT&VP8#lQOA*H#tNZ|{C(hT1=8Sg$D&;tsH*^spR}`48i7fGgAoMGwPJI4cpR z40aFMK0tjHTVoJ=CIjId$@f<)1<(x${Cd^MYBB@?)umOdupR5XgaOzHxW1-Ee|?;p z48{V}{g7tnLeA*}l{;|8Q!X7g_=LHHATChW0~!U+?2cIb)W!)gh`>qiygPh!=Q#t@ z2?+t_bUMJHLx*f(--1A2vBkw}+9IHKO9`Dz!B+y$@|J->q{##0ADI5MMsPBIGqHC6 zTIUJIWc-qTiy$E23j_e+c~JXpxdmYNJ)}&bO%RC8|C$&pqBzLLBef28Rz)lc zNAlOtF3vd-H}^|fLE#)$Qo1cbfR#B30XDR^oMQwx*dB1{x=jmBkA35&AOyfrZf)*P z(nJWrDE0YL-zW8qntv;}JCmz9+B=LAAbh`do}_whyHP(Ek|%R5a4H(tt|_7KoD{IG z@Wdmy+_)Az_Ue>?`|r6|&ttZ-ykbks%XaC?C0kpQ5C@z|R7ERY34sU!aCBUShc}3; z@L762hHvjZ>AXrbZWl%nurB&>T&IkTORzO5nw_!?q7b0e0BCP-DO1}f1VH$~1ttUo zF-Z5|MZ&jQfEchR_b@r7Cn%(UTbrrU^}yKRo;|a6{Ma#j_2pOWU;gPQ_Q1Vj{^xbZ zF{{_nku>Q;xH$2m=c4?`02OvFCum|KLwW}euIkTS@NuF{&qWUSK!`Yu)UjahL!> zz>jZI>92lv$tu78*s8z$$n3-OR@FZLK|0Q_v0}wd(nIwzcKIBrtA@EC!aTydgs9>!iH~LagYg|?&LQ$Ib{b9 z9I#`@j_bbQ%>UKJMKM*HcWd)92^BYie=L878Ul2M$oQ|XulqJ&5pweDeYKh20#6XO z2Qbgk-EsXq=YaZxEdH?|iI0JfZ4aPqVrsi3rxL^!A4EKe5AUKN#Ad^d& zU;-mw-{)VPe)>zuBNzk0Vn3I1PX}put|O{C##&g|Z;w9oh>ZQcU{5^uxSc$H!ltL$ z@1KgwGmLHA(;g_nRDjeYjP05(U&ToI59=dDS7iRFW5l|7^#$w@b*$LK>CzzF3taVr z&MJOaYW^QzFgv>_1AihOuWRo=X$+xbEUZh|=3|esF@$yOW|e@at0wwNR*R0-%|i7c zuZYUfmYR^}RD)5r9+amjOM1MoCiQE_7jARHvSD&4s!i$N1Od$zk(oeMf1@cmOC*nj=}XZDLXf2DWX)oE~b#;U=)d>MKO#4W&R z14lk#tCfxndC=Gm2EL01a+)s)>iydhG6dw{bDj8sDQt8N(5V6C7J#kxs4`sJA;6%H zhCISPf3ir;5Sbk7b2ewq!t|q>&wz{b`DQb9-~mIjgOufF)Qy&^+@ci(ZR?ccAXjC5vh&H2QtADI6s-Kj8sd5(z{ zVuSn8^BMvI1R2CwTYI9CrJ7^ve8oEDUq0>(0x*=o()-@dk{F6uj5da+<5Q_iPP&1P{;HZ| zgn*>`t6=HUsC-q;0j*G7I(Yex8pJpc;xV5`;Y(n-*)=U8K(yS5Fo%} zG=9U%da(Z$nE#~1w5Wb$_*s+-&m7$c(b(KAi;_VQ068860tf*_AIbPQ9Tt?3@4|<` z%MfQn3xiXBl32_?KVEFJ{nYe>e9XZQO4ZC1+&ippOgw2cizJl z274Iz$*PGWA3h$OibE|@SVBFQ@Cg1L1fLwDxXp>=`>48Jq~sw6OR0YE{8 zYp~G+D>6|4kQ3b1LdE#o=a*&RPZs_Ea>lAs^*8+3`|rY_oQOl>MIT*r>$&Bzf9+^e zVFYJ*9hbEu!2wSLbcXZ0?px56p%ao30=BQV;1|ZzM zt|MEQq;9SYH#RFR6&Uy|l<6Ds@_>3_j?QZgkDh#p-wEr+@Q6Hw4%lGugF7w{HVzB@ z5RPZUq{baI*t7%z`}gm&x%qipmsY^F>(^{qwgFfH4z!df5~7k%>4p{pVf$}YT8V4} zj_sdcUAj`Fd@*RKuKzUDo52>YaUa}afHNpz{Nvzkh_dCE zdfGu4z+i1mlkyaf_T(FafQS@GhwNjV;6F7vZAXtDv1gxp#(wbK@B5j!d*|k*78|6K z#PBG*!~92Me=!*kko-`jxZ)r0>F-1JEC2u^F61O}uYXY;LAt)`uRFvZ4180Ul7|EX z)f*!Gq~2eVVLupu`>R&|&s%VGYecxcEKAJWhq!(QVyJ5#;V(=su?FRRhY&#UTUiuy`L&Lq!#=?3hKvMG z*_c#!$2ew}c{dAdCsL9OeO^u`=j7H+?B8z-vJJ4IRo6uc0hX4Qe1Ry0jr3Jaw7d@+1cJ(c&HHm-c zTQZk>SIY~iB!#z<&0^T_#fO$_b`n1EA0)TqEl}{ap0P3+Y{~H?^{3Emc0mN8gZ~fF%U8N@s z#?BTn4Ad}K8 z)d4I2YzJWC%)?)#y@^VDQOO3%p9X;O$B+ulevjjn%JRU6A$zHJ79!2GYf+CMx(k%P8Iy?<(I+L`~jI^PZEI@0x#FW{YH z0XY&d-vuE7nt}DW&HX(;ZufjM7ErpEahcO-L4bjcgb%gjKzuP%G&>k>CIKX8nl*KA z4$}>vFt4KlKzWb?Qg*K90Uzpva04EG%nlwpWG_GWqE`N2v3u^m+YaA!$m>)qcbo)~ zCbly6N5WhPz{xisWVK`m`oRe#0fsxkZ{?iv7d)H@Q$XGeTvd#}TlUvJfBQ<7{m)+y zmi-ID53{#-C$aw<9H~<>|7~e%jQ&BuL;+x15*@NcfK63nw4zm0R4F$Z-5snwcmiQ< z2ear{(v-U*)Yzj5v19e>gM_sWfa3z!t}NNcmy0(3_b+YYp_4ZKxK0ev=>bjiQJila zp{g?>xJQs*wDKJVH!jdtc;<7`7|4FONqc#{R58^2;V$T|+4&p<0Ac6G0TmXlM$JnR z9?*YB4;^vifY=5=An>za{ld$>anSs{d}Se)y``^%|i? z(Q4JA>jmob3AQ)eo8w!mCr$X;F*i90Y!6I==}9L-@|o(ETpT@vF8X6GN6iCn0U4IJ8=?+ zw$QZbrUMHLcH-Cxc2nDx#jCcmvMg-?jvt7w6aqv@4Bj2#`G&2^=yDNF4Wl0y1yT7& z17LIJKM3XBE|1a=3wPm;;c*u6!WF~CEqu)7^rz5yTjj&Iv^GE;0c2YtjPIZcz%b}9 z99{|lvh7vAw;clTZR=9u;?9+IVQygGJ;pr3-uvK}4cVJ_$`Yh^b>xsmSku!}cGJOw zZsGs?uYS)S{pQ0qKd1ADQSA>nAlxJKA6E?Gw{+Ej5zIgH94b*cFiQs?%x8egrP4JZ$0)V*kAHT)BI+q{crQB>Xqt(^Zf`ZY$;=Al(X4Zq^dz_m&V)_XsBjthkK; zj;?b9fy`Cd2hf!?LOq#Um(qhb5FQGj*G%}47U7)HAep>?_z!_gKoRPjsSnlmOFx9; zN)tPR(WHa`3lai=GZq&YZFzM?#sP2m7B)hYKo}F@t^6Gv2n5xCnD4YeCtZG+f3Es| z|Mb`FGxIRQcDCUR1uf4FU`@I{uoDb_s)wq{Es{k_s*@@vc>ygBnPI03&# zaOH&_JU=IZRBX{wVbx!70zP?;`bT)M>JRgu2NQj(%DS_CddVtpown-lKQlYUo=*7@ zZ^Rud{u?r`Q(FFSS4R;0uf7Oe`77P#5QsxuWKbbdwRtK#3;|(CI}LbKF(m{dGeUER z@F=6Th5%hfE0dK=*KOnURh=5J7#?fs_d0i8qYS z;h~CoopUNkSB{GTgiXUiaX2C1piT!kaq|hA-@DfZ0hcac7EOtIWZLx)W0fvd`P>Wv z+OBa+aC4Zj^3Q&M1_{h_a~OOgQ_m_p^bH2ag8(27Mrif?xY0LS_YZ;q(!mg6+`k_~ zHTSPDjDtUmgd3s>f(Aj16YfDsfM7v2QMe+ZLSwAXzm)=j&ck?wbHLbGu=pQ@0nMPO zpWhkx{Wpi{C!a9j!(2wWIK%b2Q%?&|8!9 zc*%UoN75qNusP}kZR1XrbeP5Wy0^oMMF9c;L&7C)dV1P!S~zGYjvuoH9T&KG?W$e8 zc*z;H7$)4CnY705;BX@}_#CyTL?Plwyt zK%(2#uee1ZGVK9!dCWV0v7E*E)1eU%P@nz~0+a%PUXO+$&7Z-kajrobE&exGG+6Y6 z@yFO7QojCmAccrj;^0Mi@vWzywg2OP{7-w~ThH08CvUM?Ed5946P(0>V$xb=9`VrFWbg>8I*;H-#a7w06Dg_iQ{vZ9=z-6$J;H_X3>wi5E95g>t`5G z3xLiEgj6vs0D!|G!oY#&O+2pcp>uoY?D)~+cJky&TUuVWvtOUh*aRS`+Qs4M(aN7b zg8-}lYtVLesZgqf7}wL*4?pG)Mme7^VD1h3_@f{ptk|a#YRhBjuEAyiqG;2m&z>4dP|`7H$i-GTE+Qo+P~!j00=1jGp@3t zBV#@~XRB|1WR>53YW6oQ{9o0If4R>;11f)YX*()ydBDtzQ2G@@fbLik&I$M?r*js@ zEI-sCAh?OhV+BoGtDG31<72C5bw2$U(mK=DfT|eN z@qO6)QELRkqh2%m9rIf3e|*n|Av6t%Kl5YMii>ghJ}fT6g9=0TWnmHFP=k{^0s-a_ zV4-Msdd7|%I&4P{AMvq$?Z!13l3Q_Y(=?cR&0M9+Qa%R=FmHx!h^+oMLj~raJ^xcW z3c85-4;lo)sCZP>Z%(OwK0bWCtU>6{U=7`q&YE@M8>fd=wdJzdRTFz>d1(~KYWJ5? z0MKrTmgxxs4DvA0o26g@=VKY4E2_r0e}FJ2MaaE#^ohjfA33Md+SqM|J#>Vm0ISwR%Ub}OX;!@plb<` z9Qn5)se2wsvr)?T))2txpKqhcB8Jw{%C9L12phKYVq>&l3mp)0jvtwU1*2gz;u}iuF7Ru|J51IOTYZUR^R#3 zHZExOMgHTGw)*K2xqv2<(R2Z{!PpMl07|zz2(X%55dq^?!grTc8QbvzgizQI*?xe~ zTDalv_kqwXLayzHYMEjR0%A6+V*WWUu&TL<`F?ChiyFz?UnmG*o=T1ybK)Sc`J7Nn z^4TC`lgU=!^D=zNTd(;>P~(nKKu<&As!)jcyEj92`)vk;oo zc}YOR4g?;Zn*ThDO@B%Oz@{K718fHZfdLPO|MKFw^j3^?SpDBAW@dYV7(yK%0&f@) zL4Ag(3jxAFggFeeNM4DW{j%v1g28&^$WeRx$*1gf8T)(Y@h9CfZIkT+82)Ki|8*5* zO9lu4hLQPawubRX^8vv~kpKjss_nc1*#hCrKb{#U7*%hq+Qz3BY*{M*OTYNg);~FC zmFp{3m4Qjxnm#p&9SQGF{*y^$^j=|q_+#~-t8}}EKotTcnb7OlX7}liatb1oe8rS| zTb(zMM!>K)l$gRS0oqnLmWj27fN+9q16+}zz^|@Y<*K#^sLzen;Rf{4vzm+%|M|nEy##FvJkfjV{piVZT3ufL;%V(7gif z>BG0FbJ5x8b7(?0(_bNYReS|n03n^m8h7Wd6aaJw&Lfly%z0qUvICt?k7^GFKAITk zEkcMiuSaCla4QUTeCzH%(G8(170A0~wir2$vLi8frwnseferovCUF;V)J7qqUFE z+49dnuw_>L|N4cm`eT{7MhrO^6Cr^5R@)hg=3)(m4fA6~UFAKVfVS0Ji|Ij#)7a9*+G4uz)0|T$s zdpGtM37|AEy&_1R~Jtw z#B(VK$U>yk?}27VW4F1}21Y$B3g+jR@H+x0ci#%+vo1w34!oI z0DxtF7AS+jfO0mMHJy7XEAtHTLq3h)!y8?f`sX={56j5k>#x0Luf6n&-6BE2 zBx>#H8QKl~X=3MiJ5-mFxw)Y=W6Q zB^?_mjQ|}PSdmb`bX?%rycQ3_1XV96ofaCwFWOSiG$lk++C@K?BM>I@JsoxspMe98 zyTc%-e$?6N3=bK?CXamLn83p~9kRoR4%zIUJ+>&rfQ#3zB_Yx`7`F6#`P?Z8zz=Z2 zz&E@4N`0Q{f6yFY>j10&&9T!ybw-{o#yXjU#W<v@E4S=$S`04s|<2mO5({5y2<}qv#h=VKMo9hSjA696) zi+DjkXdg6}sFly2*;%{olq$pGwvwH?e{x)mca`>MZH|uktsCwXW;>uIbJ4Ca4=FgpEzL? zf-hSGE?>TES0n_ueqBZyOV=X^z$VccfAe zdwfuprP_6*%p1%zSCo|Dw=)MrUnI?IPLcdDEW+SS56l=c4B*DHvKQ(8d+xLEyz-j8 z`0R7qTXvh_*WiR4d=igp{|z6L7m@`SQSCo3%pm#+!8!pF?H#ldetI00HWD1bpsakZN!pCc zSpww&tVMqnnPdNeYYEQ|wu^{)AGibx!&x1m`H?y~AQ0(mRQQ`2 zU6}Tuejirr8;bxl9qoOEbQ-^hw~z)JzSGjMiL3bOkXzFLXyi=-uK?emVa1sARsM9U z&CgDMs_*6T8HA=jzMznbN?5KU{v;K&Bafv3pd(-%%|v0$o$<&ZWT3&G9Mp2QE1AoK zB!eg*lbnoF5qypmGZ+kf#MS$HfPhq*(|F+C`|V$U^w0KfG5@#Re6t@nQ;(%5q|Y*B z=zIQ))c#?7xv*707R}i-BsnlI5FD=dFXAHrIKSuscTII?zrSlg5G)G>wWIb(uKoE7 zyYV0I*vea<*~V9_m`LT{C9nBO7x|JUIWP%0LT#X|iee3qKjQ)|h;^yjmB;?=zFlD? z9jC!m24u1OM9UO%As}T-U+oh)R7gPOMvR_}{jr4k2MLU#gHDB@95KAt_f1XL)*Lvw zykX<#v=S{rKvnbT*gk0jXaS*lOMn`ZKI|F+p-p|R%~mvN?;@4>Z1914r~Zy}RmoV- zrV8i-^oW>02UrS6Lj%ld3&8Qi$84VrHebAW(KseB*p5mk1ineXm(T5mfM}9+X~2k{ zYo0@4-h-jOJf@ksm(#wA)$l{xk;e4&wA!&~k#8$o02&1Vz##GuO5VF-bNSPdq7zk} z?xe$}`xJFUh!C_O8Yibv@1QjR&Dw2O3IMtd@gdHSfgaRc8Y_vE4*@_JppD{IZ28!x;q7l>&giYTI%3=P4FIG#`zzEkL#b#=er3 zdKn3{6{-AlQow9R!;l)#rI`=8b1~mCHnJ{`7fs9VcqjZYIB>7mosONUJFoabhry)* zpwymiaLLTfj2%6E*bW~)WUDKycKPZRHw>6%=CbtRFo3Qf>fm&V8_-q1&p2o_RQ7{i zu*Q!;V1V(zJi7rgY*4L7JC}5_-6MwDi3UK7OPcfz?%ow!&;mYpsUK3WY=4UJ^R!UN zi|`G+Ml3*w@1+2s!vG$IHrsk2de(8{JZdjnLFk5TGa~m+K10f#CBOUE`+BUwH zksc6zCU`35mLFjRTw_axgy4es8U;taH#E_rYS#uZjsnP9))AwB!SG+nTDAmK8$U8q zeYEBfP_46}$E%%M5NEC957AdZA)HqV0s5m&ov?=v5sfhswFRLKuCLk{Hg0rmVD-|H z1nZ(L79Dgu33g`e9DX&TBq+^aC?o`-bO`IO>jz^$c&}H~M+qH_w z7zX5ofWtQ(_R|5*UzBm-TznCjy%@c`?+yYmyl7oyVI7#|uq_z+JL?d>!~AnEa?toe zvp9d{KgQdQ0Dv?CGarr!+{!!?G@bLtUg($Etq=hgXsrT=?)Jab@@52Ac`qTbeF!kX zvx7XQLIyZ5ep?9qq5 zY4_Z9m+jrRHyQM)LPoWBnExUNu43{@Pe4Us2f|-#Mf*_cOY_((@IovNw{ju{m;*-mVu0+bWuLHe?WR0)lGDor79GVa2+QfE;qT zwW^-uGsbZV&Q@S*`!~?YnBZO=Z#1UVGNZDM8o>h)hac@V*11pLpg$lTTp$xk2k)=y z&R;yQIkOoyfUTYMYN{9``51VE z=Bfuey%RA`kcpRQZc!5j6cXB8XasL zbYXx}P7utz)czlT_)&ZHrI&Pn#Eu<3CTV?UhCwpttN*&kQJt*{6A7!{T)1X11pk5g zRRzJ#fPzVt=UDe_9lYMj%D>k;Re8a=3gMy^kM+}+ZTWW}+sdCl*Ixh2$?<-vu-SBX z@lL9fDmO=q(NBifCGbZ5e@)W%yzw`*b?;ck*fXepn?oFSEXy)shd>;uzF5l7rY_=- zc;7U_&<6m9;mD~7&7rSyUse$4Lx;EqWYIhXH?gv2c2&m&N+2)>?E$SZtyRqip?lJn zk*{S=b74TH>K;r#+~XBg;xYjT>^0Ua7CW!*e2aDFIfW9S0j8&>Y_I6OJvu6I@!F!D zJ$Fuf%vaOFk^~q(Bv88DKD2S&002M$Nkl>=@|I(r3hr z8URK4$HhH(i_Pqc?N$STGEheP1jCiR{6&s%b-_fo6Ty1~djyT~!?tF&Nat-IXbjul zw^9S3z3?2_)QY5H44N=_wnEHp2Yd`juKG$5hyxb~tDgKl`fK=V05XWNNLq15|K7Xq zHmvUpG)P?%(qIwO%Unsi`*qX2;EBq>KNok4t{xm@c37}AIZm7wnI zYlO+C-gRL6b5+QHL#rGcAD^?8cTd~u-@erGev1KK9fVU=?aO|6-v;3AR#bt4dJTwo z0J*l`Bz<~7irv@649tIGP_C~_I(&r_iR6_6Kcfx}E^p-mx`D826>7A;IVgmVw0q!_tWO_e z#z{Lq|0-atdR*PECNxQwE+H!?ykg@j;s%~Ef#^R#cQ3krTqv9LCFqm1i}jA`FER=m zPGAawU>4ch`OW(u5aYjQ*KaJ@AKv<-Ew3!4@CO-Tuq}WvoqYMcT?j#fHUOnz87s~4g^jkPLo9-QiFbmFNL0CWPX zBbO!}w`jmRR`&U*0NX$$zcXM7f&kL453+hrb;2+VE|`C|4Y11pzk_|dIX5fuLwN6>G;WUvEJONd(LVp zhW^%1owwC@#Q1;kwKM=OTJ@S%I=bL!iZyAZOiZlXWJQcbmPqPC8M=`L1ToA%N7a?C z4G>U2b^*XJjOA9~$PVj%s;|mYkzjF51iaQy10HHsm!UwsEi1Uqk2EF?9PitV-lpKp zy$E7WLV96fwP&`|Z9OAa)!@pQW(GyeDQY8bN%*0PRWIsK+)sePJUn1h?V6ORxt?)%S+Ulen9{;|AhAHYN8ImdbWq2A5?CTKl)w~SpaNhH82 zwk#*RX5?1UfpCU-LldJd|p<+_MU03u;9hIx=L+9@J5P|NhVa zYOg-`ZJif;ppiiYr$BJTbMA{O0Q1X4?2~He>(tpCRB0y`G;uPg7BS3#k_mNP57gg5 z%TL{*@?VjGqm_5g*yVX9m& z>LP&FjQ>T7u@~j&LY}@dDdS`~H@4)f7G21A3t1r4Vx-cy$3<)vja$O0#j?}R7IGN= zAOS6l@phEgeY{7@1csgVQU2o+=J;`K+lRfY3eyinORQ?;mUJ6uob9LC=@=ONV+)!a z{@YGwt_^U-?9vUZoWEw{7jLoZ14nJ_@O&^77}IikOD_`sngrY~6kzK>wyB*6Q#cr6 zreEe@1Obf%QcQI)?xAznSNG}US$c(fJ3XTxoht0ciIYwPBgfXyXP$Uc^ue081njZD z{r%mHO@P?LN^O8nbc#Ajo$au(Yex7t=T7^4D?Vd^e)_PQ~?`j^f=)yG!jAY*_Xkiox)AAHDu z^!gk2$_p>r!Mv4!Eb<~zN3u>OvW{dK;V{9CS!6>F#yfQcr-4+td&A`vo#sXI$;Ik} z*S!t^)cq@3!PxlZf-V2{V_W{shqfjSfaAk+#`zoS!t1Zj=ICyd6jQDGB4JCZ=jcKiW>)OJzGb?mlb~SjYyE z3oUk7QW*8C5}HepUR`F+)jRZv34!JGU7U{`cR;I-?5cZ6jvtm4Xfay7s5VJi^8E?C~t zcj1&S_PpodcELYv)6MUs;Dq$)UYnI8?z?YpS7L^(2w~s;R`3&L3gyeoH{dsHks$zp zm~M2GrTJ6@@}+-q5Z)T!cU_F~gxZX@E~;Kv3)P0qV1OWmiwtkJA&Zep z0^)!b=U(>JZUG!d3_@d41h5lRs`uI&%wi7*YF_2lCbSFMEq**&I*j9>J}Ym!e0}jO z__zT$-MfhR=tr(jt+q=$+LFGv9fu7U_WJrf%~T~E&T|;6jp=VE-A;w2b{suBAx0aa z^Nt-=<2YT8$X)%ys%Le7_?V47c--v3o*)eHHdR2vvZ{|Q9-a~8^NqqpS9{h2R`PM! z1<15f_%I;9Ni~9SggVP3+s~;tLXWsb0{SJ$|eBM*KS<5t5>ht;`OT; zu#gc6m2Nu_plb!q;Ko>?iGb&BV7i;Qjpf*nRihYp=cdl07Mde@BlTZD#(NBsOFIU4;(Jree3o18uEWXA%=&ocU++ zR1N_%H)cg0nJ}rh3qAB4f$a4cxhHLa%K1eZ_|x%z?`g09r#fB-<{yHj4_rl){>Hcr z0!meK90AV|xX7>$(qz-uU{{}psTc)#!u(HbhwT@f=BR}ZBivKP z&}-~G3C;-!IC_@%VhALVDP56nMh+!gbmss(~|yS!v$noFzeIyMlYzylHl9Nw!f0m-P~=J3`- zZI0G+?v?-&*Eh5YfZ?Fq1@L}NRa6&@v*p%V{&YFDOHKHZ2mxrTg?;;U4D{VD09agH zv_HN5mJ9=~G|dHoxEn)AB^?siZ=-YfU>&yhF9iU*?-OMTeF6cW1HCMD#KV9^73aQt z?z4Y+<45+)lTV5HKP=T(8PXE)Z4B6e|pJQ{`j%2{^hie_mlLTV~y&KkxjMh?{4ge69GgxqI%XY z;;icxNiu{iz zZ(B+7>}b8Vm^fvF)?n}dR)ri}N?J5WmF)mJO4lyQV!ez7jz4~j*{!l&gqxspEfHgft^tuL9xwvsjq7I&nnqVb%5gft z;X{Y)xu>3SVG~+)Z@=@`!qWjrIf6WsOZhqy5QrUa@GDyi00zGe%Nhs*bvmFvI6>0W z)3f$~R{nqbqo3G|&pzii05B|7b4-Lxl3aM_VRn*alH|hGvk32l^h^C%1b4>T~nju`h3zK2d^4^Rbp2DM?(EyT^?e0dU9IB9@amM0qzJy*G2fQ z$|`nW4BAu=0jE?%*ttD(&6Za>7|v>o8~17?Tj zZEQNxY;(}-2lamJdhiatgOER4DEz!{=)2Q5$$PuY-i`FU-pVM_Xpz22=S_bbS3qn$ z0SmM#8Z-g+yAS}FA$ zm{#}hD4O6}@^@DdKz)|0ks)CqfCNCMOxm4rk(kJ)%}Vdw+`K)g zmH(go@JII2bI;pBodMg#{4*JF6*2!*iF&~hH&!p3W&gj^AZR$$2!b3W1)iq9YkG*x ze+GGTyx+zbmu>CcGq&=Zk8DlH{8bm1n+UPUVDtlE!t^7eQ~iQfrLdaV4<*}r8K?t9 zG=~4yqbADMqn9CbAOJjB@nJ>}eIzH)FnIaUpRn1P83{!t0LX9y;7c3~T)!|>S+Iw- zf66)3EtRcyo8AN5(#&+560Rjft4Nf#Y5zeC5SW9|=V}Qg5BMUeg2~UL8zNod`7v%= zQRCUfJM>O{rda*gLPEzi%vOc3qzPabByhj6?sJ;WX-r2UK&&GG0yf-n02bh-T>xef z5a1ufro#-R1F%Lx-mrCof(-ZV&`+1)sIk2q0y{h+nf|!%%k0K zJp0coM_j{=U&~Av1WP16Ckh!O55VsFZ>46kdg}FO;;Go@o=bd8wU$m#6 ze8LvQ{5PoOfw<$!KhJrXoXLR;=AX(8tWyOMaBxj}WmVst%DA8dVTZm&NqP+CAP}*o zc>%LPJF>^|^U`C-s})ob7> zwSIsn-FyVB{tML3plFpJ#;V9o$`$~c00?tkC{h%#7yiOOpkgV1=i};Llxd*y1c3|b z!xVJ@?;$?h8uL%?Fzpf)NE<5;2SW&>MjwSz&0r4n1`7*r1XXi)uY~}<$N|yslWcQ| z+v-CTE^E#`ec8seEugX}8v!e_4{+xp8{0drd0rEJoZktHuo(J<_DA^7)#UUI)Ik4W zI{-Amz|JwM12mhrh3<)PlN!|=@KOKqIz#J#ToSi$?_PWCkwR4NG(>aG5k z#SN;>El!u#QeIXXWPt-SHtNQcO znyq~#=KptE_5a{&S^2*q3&oo-|1qzAfS<~MKnhjo3GD@(a6?EP0(+a2^)9F%nE%cT z)!JP6K26S<5W%z=XZ2};cUmlsK^Uz`5xl;qI)`ZGJ1Wcw0anMvOt6eff=3YvL001Gr*3w$0#7aB;8JtMG zEo9v?y`6rfl!!8X<-g5fEi4nTUe!3o*sg5uRM85+-F4W;=49U}+A?AcQ>Ge2uXh;Y z4BTq~bm0Jy)HSGf0VuxLnTO=LslE!}+W}}jg(GN!@92MrbUgHf_ucPv!-WeM?ae>@ zE@Kmbgo)DJhr^fhcQXhCa6@c1j`Pq|jegm*ScOM^gUdE;@NNHZC~v+-L(DDUGqeEc zfQ^p6LK-2R#&4m+X8k(|y^ivO7KA=wD_GKv z5QHAwzhK|I|3O>H%fUG7!pgl8bm#+?iBEBH$lm$@ISQ^LXi$c+k z85i*lnraghG+4GHXCk!el{qnNbm?uDm8n8>LolV4t4DGd|ks_M#qe{gB0{VIzqw(+@E{onfB zmVfb~j`=&QZ2&7x;Yg~Li-LewVY>B=K8isxUuB|Sc7P~uXI*F#SN-?CP9v3WR}c_9 zvHI_V!+{;(TZDjyKE&+o?6j-*Z)W=f8ySR=NL9F1D~x^MU<%p3wOQHwpr`{;1fSB> zFLsUhNJvaL_%w{Atye$htzxJgnxnitnyTDLW&Ym(Z0e4=)n8-&+3($Wr%z5vu!cq% zQ*O_k+XawDo-_igmzTx6Yo6FUV`DR!H9p!5Apnz#7dQcYy5RUjFZg%D_OfE>g6;H~ zO3P87Y*pM(p3q4+r-8yF^y=*NjGZ`k+!iDZxO#2TE?t)GqxID+nWP9IVFy`=KJvf7 zFOE&_X~(y4!R#lnPY3Y%C)F4Y-@;2wBR_sULSWpBY?Fl5dbaSy^y)F|Poex_PDBV$ zuZ-&upwnuWa4CFtpc8<> z5QG4E1KpF@(oY?SkQau~)-{-d&|!XVE@A$EYOlQT?O^RcjaVom#{Q6e7cs<)OILvx z;sN&zs-rzN({ca_al9YQzZ;a(GxblojSJUo?ayNTf2$+@bl>>mQdn_Fh1v2W@aO6m zr@F%IKzwGAb-xrbmLoD_$_;|R~vwF?4*DQ(;agp6jAdWjSIJ1rg4LL`78g4wFFRp+%( z0)A3Nb^_aKB0CI6xhEuCL%OD)sr&^3fmW{pGyzKB86t1cINl@t;);779Es0&rQo^l>bNF7GyllL$j7t!RA<*XXASh)%&08dG6aeHV-XYIY0MH@8j$*P55C(4=*8&IL z!=TVg&JK}dNYgR7OVHNW*?W$f(3stF;-o$D(8KoQAG~2Ne(QNVfWg0XM&t?OAJyK{ z-(o`{G53}K1oKD#LAz5o4E+@eIj9fygz5JyQ(plZ)qbq}ul(*~TY2+iTl?^wj`)M1 z$b{V{Y}!F^ZZpfm;GrfU-hg}?`b%M~?th@)W2g@8nyl(!_e(SQInwShwWF~5PoIW( zozb=^U*Xs)0Wb7{hD_8t>1C_e#^+Yc-pj%cTHdttF5n9D4}PMb?A(PC1grltQYkII z?c(APKCCtdyuS0&Y$qlHwXpi%dTY&g(rimu=5-y>J9bg01V}SrY*qq*8C{|a8ej{s zXgiuueZiUiYyl#z#CNV;^p|YXU45tQfrt!Mpk7{|q!j)xkF>xe)tS&Fy-9|pp)CV0 zt=jpE7nNixP_071x%M*B4^`J5$rB_80J$cn#!*ARtU*kgXrg_J9ciG=sis6rtN`e{ z6#xXa|3HJ~w|6KZ+mXOy2s5)~aXL=?5j;}XF~`NY*>9bG&*%qrI=eFcVTJ&RF&uFb z24<`)g9iS3EIG?L`fu+Z5N#MpAQXs?s_m7<)`uQ=(4K$hTlUmrPs;lLfyTi{QT(Vs ztswE7ha_NZ8JCg4&BN*2D{K!!t8y%oAx!0-S5HdCDuM6!PbPi<8l9f2`c}ETWGjFE zOh^2kvW@dnDU_kV+Tsq*j5~H!vh6DRNW+?4x?oG!WSp31oIhWcN{}dR&w$ z%s)hLs@wOtNFB@GS5>t-30~fggC*0D@RiNU@ioZ_S+&?s3hfFjoCaanK&iJY?GaDM z8x;8N5Dp$+xG5m19VSvAhGL<`do>fzTTPh04j!jGt%&rkrngx*2>fx4t5D|6LU-|d z9H$rv{OYP33WQb~e_RcHWUm=^0bp`*w4EFJ6F%hFUuXsv4zdn^Xo`q5u?rBNvtj%7 z9k@_zXgr>$lKN)LOBied2qZx`LSR5MW}FW2z`ggmK=shVLHpv&8M}D-l7DafAr1+Z zj;;gjV9;U2vo82G!^_8)`svshb65WSVC+U=^M6Uig5{4p=ei-VDm z&+!{~;)W~j%X5eae0t$Z4S-%ieMs|U;?3{mnm;s{gJf*`9i4%mc5yJWy7kz@kJ!sE zzGRO|1K`%1Pr3xI7M8IEV}}5Mi7gL1kTy&)7cP@m@a*?r)eW#hwa0qq)s@MQz5c8a z_ykw4tgr6Nn((^R2Up+z)K-80sgC%&BIcic!1ZvuhD5-3yH2JZ3B;nXzt|CX-%Z*G z&NTVxDp&v8(c*z&+3tSjcI4dcG@$XPCZ=shC!*}6Z~NE~4uN@ad>aQ#mnuSb?5}3t z;IDM;hX7F3x_SP*xP|PT0QZSx3xQh%nUKmXE3Byg=Mm2>qWY)ULtI#zB^EY|yu?d0IHKnXx622x5{Qb>|B%^v4Dl zV1(K{c)r=;2MrWf`J2Dv6T-m!*VAZ(Jv@oe`MJ0u#B;3r5TG;00&?HK?M+|N7VPM6#&EbKx4Z34VS5tBN8d zrHb>!}}B{<(P1V6&?B4z7K0)>gFNAJu=h0913-mD0)XdcYtH0jMwa%hpp~?g!e5tFkG^l|Bmdzp#Iw&Ck!Xxl%*;Pnj){so z@|?vx00f*1(}Tf31Rbf#jL*1rsS2*X{h6)4bK2HVowLf~a`@1xU&`6stewiOWx5cH z>l{X4q}3;#uN~FOrr|h1d;ewhk1L>r zJj9TV*!&Jd#UAHMWlE@n9;v?A70`uMku(w4T)NU{_Yj~>X=NI9>wSdK&iuEbGqCCp z;XL80zPqatMqQPX%2t&|yGp66-Q5)^!K_TVwnCpX{}G&wU5*O8wrrIvn%i%z*!aUI zZS0t~1f;jVK^wT5w(cCy=!*)Oe&GPnk2A+`b$WJMuicQ2h3~*U7Bw#XXzmYN98!6K ze1Jg|0-!mW#6tkIcYd!u_2}cG9X5RX;5+aB&92|jDGUvc2-v33FK`=KhlVB0bTa^e zO%O1{iV7EH;Do>h`(bNRVo5q$b0YE~owYR`?JTlC#DOs8+MXkwpskSDUD63-o4K%m zKhlnk6$tgC?iz!y|oBZm$*uH2F=%>T3oe-ZP~goT6xwSS+y(zy@9vnq+o z6gZO!oM-Btbxd$^zdv=Y1J<9b+6u67=CUondCFFP{gJJIdcmqXN4V1tlCz(jlZon= z6M|!~l-}F&L5CrjSd*s9Mply6Pke0YIeU2B_@YDJldM>V#-R`KrP$$66HZ zVmAQ-rkRM@PU*H1miYl94&tb{<8Ujb9f~l*H(Q0Z_W@0sp+D@V_JIzVk%r1tVmNCz zsS%gn;`IQ3y0A|VZFX+>Ph7@s>=m@RNLx=1a9o!*z`5&A7mUqGJBSkkG~gQApKx(Y zBtV6}$U4Sm^yl*+Y6DQu*hNr{$l@E`)AeLxPPrK!5qRXLL)sFs*KRCb7X!Lxi`TBD zLZly?ncMW&VSk47ESf*)dk*GYoFC@_=AO-obu@$P`Osbn{>eMf`aVzx4~0A^gKxPM z-GwbPo;P#Eg@F$%_{{WY)>!Y06hg?%sYTSlT`Kks;z%{#n#^b+*beenQffCDq^6s zgnhkm;VBA&vi?1L7le(Q}8 z`tPLgr)E_ZW_q`dG~!rQuk;fsI@vFMf3;g8-+kG4TlbNQ@A!`z7sH)dgtl)-`*Z5b zRNSVLH;3&I_@TcNSww#zM0S``b2RM4Fh4-Q6ho;wUf=mZA7I=UZ2-3WsXn$Ky8tYl z#I}fcr^gf?+A8|R3dMJT!Q~w!ejK2CEIUPZJ}%R`)Dy2*U+S4SaO2F(tnHuQC;3O! zK0ot?UAip$Ne;Ids(vT@XgcN*k>6}bZE^u7Vf(NHx&~^3#`%Z%0j{YAXi6)10RC`A z4S*tsK5WsT^FkwVFKWAVR+I@kk(GbP2RZFZI&6Dp^*^sW5Pu3meGlo)QUH){)$+Lw z5MTf^h@vDeFUhEOgX&rRd)^@7D+A=_6F1v;UwYNP{rrn|-(7dxtdMTakp>eKj4_sO zeL&T|h6l#>pfmr}Yb(q@5=X8G(1>xXfKC|u%RqlXUIVj( zR5x^?ROjqc4Oq1bYG@JwbScka&W0g?x^kG@hq$Jo22}rDrFu%}5K6W^&Y3C(gkT8) z=f^0vC+UV%$Ol{>h~(~%y@tY!+zarIurH`Q^M}vvyTeSV&rizo_w@9Xwp?NSsvy4| zdM7n;LcU#E0E{L-tw4ec%0KW9W@mX#ng9|4XhC3%?UMUuZEQxG0I@*;BuyQg+X1T| z?$Hs}ujrwB44?Aq`$y`;WRX`N3ZJec;Zk)3*P@*|zh~a@*H>Sk)m8v$R1&VqF~*ua zhu$OB8JMs=C+ouZusGa z@C&lXaC~5XebIOj{zI6Usp}St(UxGP0H7^kEE7pXAQEtO6`b@}@GJu|P3#5S+kjP* zC=i5)w9o2C-~XY#@!i+$fqU+2Wc~@KN!eKSkH`HbaceiSL+zc5=l0@*S~eYh07=07 zyXwF0S)>u`7@2>UW~NFcm~UJb^Z(Xow)~3^Y+XWt$|YF_&OyehSRH?a=cYRvy|LlgsOGm|r7syOzK70ULHD=eN1oa&=m zJ?sEDA*88CC(0iCM0qcQ0CS4I`7P6T)Yg&l->o2xlwqW2#QbCZpZ0FQ^GbMK5CF8J ztBz|-h1GvFYlg%D7#U78(FJzly4pfC)c%!1z7B3>vJc zs9d@}!6)%ky}bT{74&4{z+Lv_{3YNa&?|c6BoMHZ}QukXw zeZ^LO|FJFq`jl;acHXMXn$3yVYe#$KwONnK6}w?nN9!gt!lbsL6A2(%OSgLn08iI$ z8Fp}L{Gd)fBj&$ds{dK&GY&vKsOWPdK)Y=LkS>H3_tNzW0<^KWbW;JCuPbe^|9}y_ zX%W6K|7-*3l#Bfp#?@EgcG0gWGeR{#t9uvebgHhqPM7(HtpE}PU&cHCb!lpE>h4@<`0nuV&^~tN=jZJB zk)zsSv1VUiIB!eKH=N-OA+o;#r)GVJ_1(J%FqO*}B=V81!^{N%7kS{+Pv9BwKtK?* zjGLM$6~29sp-kh_Sn^X#guBAZe^Q|&BZdyR03(r1lKmDhl*f(yw-HF_En85rC8AC{b1sca< zV1!|YLDKpkEJuBGVIPSJ2O$9OSx4P`)n5!f0uF$hI5*a`xMJ%cowt?W%F_RDKeozO z+MkB;pFRQz#9F_&xYC7|Cxl-&)IELDPV_&V`o+;RUOvpR1%rl z_3PJlJm7UPg!#-MiA9jbG=}*e$9zB~b-2Ykr`7vI*k<_P9|Z*A&bEN&v|^gOyNA4j zu|8J)gTcSR{5PkJuo1?;$c7W;MbORmr&zz{RJ!NWF7vD1D{-0AfIuJ&T%_hw8r6Vc zhG}%+cntj53scd65Z5Kgz}UBUpWSoUJ@$iFzh~dL^>$x1@Q?8a;WTRhFvlTU{1Wb9 z7_LE8`)6*6EC19eZb`oDc!aqKpRBRIi z(*i?GIGqT7Y2c;54d-)Ep@(UQaA(E8v7WrcM8hm=s_}4H@Pj{K$^$L|KPjcuQG3}m z8*|v&TS!}7K!srCAGQ5}xANNytp)@D>!Qi?1QJnL(Q50!)=JjCP^AE%eXuN3%0PfY z%OKs@5J9F@evJ*e#?j7xAOr+s9KR-p3n2goRqp)89roN)&)A)}-=RJKGmR-Tv7q`7 z0?uRp2@OJq0U-ItEcx2!j(Pz+T}%$#vW_~T^6$p}l8+JV>5hv3+J|5J5r1o^&RIo! z{QBD1A9d`Lb`ta?HxhFrRjz6k#;T~3WgBJt?=%^#&xRiIjKyp}#WDsbT?AOtl0)o3 z4NeG&H~}BZ!Sr;}k$zka8Pj$Zr@Y#bp`)(0G?vEZ12sQH9S?uZiE3vb#T}Evw&s^KJLw z{sVXO=1oNcJP`SsbwXR5f>h&D{G7#jL^r7Sp$78me~K7^CTz*a_k?KdmkBp2)epRP z9@^J?1`&M`ui6FjFt>quNLJWKVy64pG3pn`=7VfArB1g z>Zs-UgZdGd01S%qWAR)%x$o#OKF|Ep9Uo!cUt@5vmi1fje&Bxio$tE$WdJyI;D81n z47OgFgh=+sntwi71+Vz9dj6poXfdfWE2PNT;2o*M%&0v8Mcn8Q2+pWkHE7I6+%Mft$p{pQoEv2>z zG@Mk=$fm6~BKZ4h zL(6@nSD^IcsrTOh@a*iqi~fQkgJm9hOP+y|w!#vE@V?VH_xpD=0Q8&UWA;2cz7Kst zU}OLpH?32lc^rhvmrtB<|MlH=uX3*Fr@8t`rsYl5oL=?*8UHoU>t)d zfKQR$0L&-=EO+Vm*ct?VGM|Z~;ii@ZC^?`d1e~8T=S!u<+i#tud3&xAKvYMzp$uD2 zfH0L1Q510SnE1aYx6!NgNyudM8=_bD?b+j&m-n~}moB@j*RN)Hy+dQZXBx{2r$+P} z9H9?#6>~P9tioyk33kHwgI1VvhaCC-d}*y+8H|K2iKxo-`@h+aEU# z2-#1AHv$`5{VB<|DgQc=QNT0#+%oZ#XaLA~VewRVDL{w!ojy6xTL(OrvFDE-b$_RX zf8Ublf8YMSt-=CKR$)GEm4BKv#Tc&9T^xGbns7rdG6M&bOb&+wx1jt3Py$E1{?#kD z-I})dd-Ts=SonY0z5czWX_s1;u)^9eZ^X)ZFWY<+0_nOE)v@(o-UPVKrpNX+%PW#2 zOpFpy5NIY*s@V3=BBZ+8H#^a)!PCXtQL4%oabXId`T-%_WfHhL(X}ksE$koTPI8jj z7I5O7Qld%zN0f>+$Gp|=4-eE3@pvUB&K#T&*e9hFpbU(CQBpul3@B%U?bbA}tpbS( zpaixPA^}j4jUU<7<{z{+>e{#H&k};6EA$(|oh6@zIVU)u61XATE-lQvX(b1|dhMFK zbMKBRjEO3#!+a$-RdJ|)2EL4J)o%Xqr1dhAbszrdJ=j+c1;YG9+kVMf*vTWQ{D)(% z1%p9oH@|-ZkLACS>_)ObK6yrP;Gk{4tgUIS$ID9*NxJgM56NF6?$sW z`w(B7ox9OwdD{>_#4|aid z`hE;Co_1QSXNuXeBMn=l?Wi#QZFa&U(_5YF+l6e4B z(F#i7(&Cak^~M|S)~#Fa!NZ5P9Dwia!ZQLZX3C(3|YZ#c2hc;t}x1A0{ zf<1DDVN~%E#X(`;d`~ZE=oNj|`V;a`jsl;jAnWPgX@qfs2t5qZS+xdxE*by^OaHNW zdJqg@gbZAYSAaG&n3eQTd#Aqm{4w|8JMXzC9(&A~L6a~VH6&Ug?gO7bOgR z-SP+QpwAHm6+y=Jk1exha#uhNx!|n3C0y*_8OX zMeAw2H=So5rG6KTOlqY+1$gl=DXF#Lh5^8E&^eROtU@L%^r=Jp54yKx1o--!(?-Xy z&zv?zGV2EV>7aRg7F^vvN0$gj0K}km83~CpX%&e)T}`|vDoK5Y>*x}`t~Vkyx>uKh z46p=c--rC`o$KX?Ynva5VFIToJDmCB&2#8}yh!7>j)SCjI@x@HgNm;n}RoX$}THa6Mc1 zuL;=moF<;KLT;SD=~n*jYq$E_vu@+UZC6_vZsot6ugwdM7A9tvTsr5@%7*&unuOx4 z?P7M;@_61&2w_bMX#Rve8gzk0Oi8F|X3n}a ze;ti3(RD0LNybCl#X_4H=yvk)5ef9L=DJ}ID}s2jPbZX6{3kT7%3xgU1Z&@~Lwb?} zYDoaw30J14TxCvq0dUTQfzNl4#TakMHZ}+o(1vkH(!5O<6ZOh?2ri9DMnAwc?8ek# z$k4auCEqSAEJ%6X?JiutY&!$wp*cw2o(EH}&V#GRmvL-F&V3Z*_aXRRAm%sS%$H_o z3*9VSDf-=bz4aTK;r`z9k3$H4lV5z;KL(02ZTXi4Z!`d8Q6--18U?b(i688KyFd0y z{lWJ>(VnRvx#cBUltZz}LqCWZn5rwt;ad2H`QjZ9p8s}ZGTc*^ZzNKT8*r`=N|uBT zT(G9Eh{;*D|Kvq6z*U9)pSj^4{r4}-0I+dIp8sToKx_4(`(?^SNuX|aE6><>lEs?w zfH{F>1z3`sZI=YuAq0a7+DB3V{0LK2EQ64LpZHJ0H$u~Z1!#l7JYf~<)Aa4K6@xL* zYP(Wl*^uf5Jayj0c*>f$d-2Gvw}~-F1EB}+k?}O4`Ise%M6|?`K>>#M{Z&`Ft}X2p zX;>jI6FC8Z_&L`{O;<&zjQLQls2IBzM|&iFa1&ifcfmJ=i3} zeC*I6w_lF0hmTg=>2u#G^gYjMBhFQ<+4c_|nyVVy>MMLG@S%1E9u@M>m|Rt7THcTV zi`YK#{IgN`S>LZMwUv9TS|!VWdzgIA0iRpIM<@Wp_TgxUe>bj013)*Z7~9CCfFF;{ z7@G?rtRHH-zhC|AXYQTX-ZbUEF<=?E@BlpjAtQde2~++x7%>23KO%icNq!4A!r%D7 z=rWamA;fxrt%)+_KZRda6Y$y>SKP|KeCbwxd&bqYF0Z{svLvW)5sXHE*y4RXsczkj z^=I-9>9c*<2>bVW1xE3m^@R2v8r@(Wp7=o-mCp{KZ|O2@acXkfw*9m9g(VRz1eV4F z`#O8WR!P8W&=&S-hLRnP+eULEe4r7eNt^KhG8e{y=fCv4?iKQCkgRaGl1A)6cjz8K zWo}6h2q)#&-CMQg{FMb6BxkiOAXylA$Z00e;KwyYz|rFS0*ZJi zvcj{%$1CV8{qi4l5HDx>I)TLgJlFhnZ%E*trqUnQ`SY!g9B$3|#&`kTc>M|c4?LvY zeL5Nda$aXVy?qKWsC;Q0gcCNHv5YV5SS7{_69P&9@ciek z`!~TZ5S<5}f95MCHI8U}z2<^Voq`nNS@I!@qc%<9fVxAxg(xAJRQj+OAQrgeFq z!Icl&u0WJQqOP>N-9|JU!Q8hK1z_(_&t=OPGXKZ2a|-y-bI~#}PIlgE`C32-Vjby> z3;^t0M~eM?h7$s zfXR&U`bMv@xmhPYtZe~qhfLqDMFT+JNF5&p1qiPr%m2@R@FQ*a_ntejZ=ajc{=kjG z$U*Tp&p%ex#+Bv)BiIZ8?FVP`hLRkC8)5&!sNuOp6FAVZ_5R=omug<(xORWVt^VhE zxB72ix%Drvx#}%>{>?g>s22}=Mgg&PwOun05uu_TW~59w5U|%et|803HJ;o=0a@#r z+zU+9n{FMl69`4@qdqmIwf`n$W--RWA?3%0VAA^_!X?SN1_xE@$r1v6Hs*5CE(PUa zelov^KHd;87!Zm+)lZuOSO>n}6}>aR9tv47?6xSd`M1O?401fzD8&yH4IrmYWqH=` z4v-vT)Z>HmgE@4QlB{#-`cy4b(b%y32iKJd@%(M)_4vgSPJyuQe>;&~ouM7! z8cbz4Ewn`-xdGg)!2wsZVtk~`c`aQ3u5Euap6t?=F{!@Q>cCL9`jBp+f4;xCq-;oFScCs|I*t5G` zD;fa0P0=xK&-1N3=H=WTDgUpYc-j5x$3Jx^kH2KhuR$(GG72(#%VGq`8rgXIhS~Ek zCT7;}G!q9e3;UNPJ?;4yfofWFX3GCRe(KggzvQY96n2+8Ni--L4|+fWKb34f7l1@- zy;^SoU=oUDhZGPk*+#J&dzJ4HlAhm=VvX`YrL5bmPcCbbNF=rmbE{Zi$3Ro20(|gI z6h1r7nq$fYaGzj-9Wjpb6^}jvvW3Uk`&0dHECtw2=&lU&B-o5)n-oBXF(ZHs0XR9> z9Y8q&S`0L>1M6%Whb)6kkH7Fc><&Vs^_JyRW(*OWK07*naRQKag ze(2tL<4rd|SKscBYH&2>UQ_;ckj3DbVDS9&Jv2p#z_1AW56XWUcJRT1&Q>xQHxk7X zo00JEuk!r=w@=;brBohPDfr|i9@F->B zFiz)e{4k#6{U5GUpAYo46R$mM{--pqY)j1&%`wCEF6z)Czi5j+g9G1YzPv`M)gX|7(X+Wc;Wr zt69~P=ZHQb4;C`=zXb7z`i>FB-Q)ZQsJE@sZ2>XZt?`f|{{=y)@2U_)l z9yXuZGn61yksUtVKNtXl$A5r*bcgRb8US`kz;VC5$)vKm6@zkicE)}C-4ERlzVjXT z&YN$!C0RQgqm>F6&samn+W)LkY|6hl?64{S7&R>6pYY0>4C)h%830nap=7eP-|C+( z*fxJ_f4%4v(2TgkGc4oDCLAeeUXj3Nl|Km}T(g}_Y1c*%3(@OvqWoLTe*GHlv_ zt1dMu;c!Ol{wKBme809LeC`-N>0rt#pHUa=49gpH)p8xh|c$taw zs#gu8HdN@tx9~7$%T+x8O7_Q^|4znxj2f21Nk#yoAJ`%h`L94Bf!w}5dt?OI<8I%* z(a(XxNGQ}QIkPzpr9JSQ3F>a658UEpe!gow9<`oP@@BD8`(Sp z2kk6Oe^@MRX|84E#3k%_a0w);m1X?0q$#@GlHhHAO6wd8XIS@90}_)oya-wlM%ex2 z&Tatq!gc=^&5o!4sZY+t^D;Ca*+}0!Efqg!PtZvq-Y6rU%1DjtiyF%aq0-#*2bqj4 z;b?TnHZ^Asnb@n1%)slk>MTrezhV(2#+jAd6JToPrV31oVGSo@t0iR=S426(Y8#xr z(vRkAqE#iJ3N*4C-K9(uWJ(WJjo{r@22_#MW5Y5@#xDK1U|F;i4-nMT$4Z<9CqjtM#XAfBHLF=fVp$;#Q^U*FNf6Pv?WVytpl5Z34Cu{C{m8H#T_ek)^ok>c#8SxwzsL-lc?H( zur!$caxOIg&W>2;G~yYZT9vK3Vad1J#YqtTB=+YNz@i8di;^*!u1Y?nt_qM?gM@1JF#Byic6d)Y(&+qk3)NBh?$^}cRJqsm*PEHWWR=gys9Ni923B814uOpL zqzoKcFW`C9to7B;ITNA6MiNFqGv*Fw04(rAf3Co(Hg>>gS})||)O^bMM!=BXozt?t zSD{>c%^=ke-YxgYR-AtYsmap{tqdJ^?4m`KE7H)iE6&I&tiq1?Pt|7QJ88fi~1WXco$V=8f=O(4POd6ed368+ZU% z2$$;=18YZs2@U7|_Q(V?+ZpTG*FNJE9-RUIG&E2;ooQW#w8_}C+xkR4fj}EyFlUXg z-iQhBoUQj9oNW%ApRM&cTfcd}E3URPrygjTVSKzSdHFtZK9K(#@auXk@TEx|pHXAb z0YH99w#IoQK0QT7V`p!-rpnv93){{HADf9?#$5p%xDDARJJpaPm2&SvAF9E#BI)Sk zpdw3lH8bTs5U#K64c%Dtr+O!FP;Gb-MdJp{5M6+@m~d zOnwGwAR<)VZW&?1I)d()RESs!s~tr9ub>(x4iTK@G1Gi&Uiy)hkS>cx zCzRhV7FeOC3bS+-H$lylrW4N+C5-w?mY66 z-_c$ug)FYNRN#*W3xu?8eW}eCWkD$rH+sH5(dGO8ttaFKT^17}4J%3XN?;G96(?aKhJ&ve5sy7pns=~)wSQ0MaHzMV( z8P+He>WfXt^^+GJ6Nc_i1Yu6Q6*6)<;P`LOdmV+uZ?%(DE9O489ro+v@D~+l*xsXk ztQ1!+u~ZkENmI(7?q&rtg+a5;nLyXFhn%a1?vQl~G!*elnil*@{kP)isCYL_u?%Qw zqOoYGD(*$jE-2@4L`vXl)giNKfQ%VwylvAeDKd0#$5Fv#seS8p_Rxd$Bdr8Y1j8=K z|2*w@mpLvLe#JIdc8y1jDP<)kkMh3K7R6BCEYyZ6R6Xx0!XuYimR?xkG(SwryE~U$ zE8XohwOzkIW9g`Y>WWN+y%f+jodNcdQ~J9WJtu;a#U#wjZcmCCIc+X-PE(hH&e1S) zeqBFuor<(f{249OrTa(AJL1Fg7sl4YpiAcaGn4b~^WYm---|)%{EWJHBE()<%+U0! zq6)TQq069a3E~P#{x>)PiVsU3-#FpY!!K`!EwHvGmEK|-txZjyyL7e&LX5Pd7%}9 z#TrF=+jV#bA>5Mu@4Xh;paDqn{(w4bD#-eRpCnO{7;uw)ZXU3Jk;Dv1?$hj>_#!PU zmq_s;^X2=|{#<-jpcJs3Zy_%rt4r^WgW(fT1wJF|CH)$0#0O(Z9NvU%XYcEcD^d%^ zM=)Dw#$kg`bR^j2cJWseJ-N{pdzGgALwD}qRb-8EjKOw)iKv0CK3yDyj4mCr3yk=$xFJ6U6c!a;N9_C9?pL_>AM$nw2cXy z0n=;*J=`@pz4Og09oH~fJ{fJ+8|g>;6Qv_8=M^Y(&N@g1HR2c`Xp*YZ}WOAl*E<5FgNoevY9s8^e~%+=E!CRLrVTg zry-qZ4U>8cNXpFliHtdLU8@~l5D7hyn6}6SN=Y_AbO1S4Ri&b%XuDJ2IG#>#mRrs? zpgxZPhneeD4fUVLsYqIMlmIIbn;ejr59O@)k#vb7;b`?7eAo{^JvU^TrPu>HsQus* z7X*C9wu^$zGHw59e=7-pmtQ14Dma8W4H^eMROE^}7!H9l;Bzh&&RG|l&M@v1_?LwO zM*$hFqzXaQ-YuTI?DC6^P&A`T2+bjN1~nv#0&sD4)XA?g`16S%8W57;55_0>T*`+$ z_<1(G++X(!rl~ploE+*R5huyF8wIQ5mj>H?$l$$sz47ZNgEB@|<4)*7!58u;=}pzA ziM@yQ99+NbUag%n^`(~;IOa|dqhNd9A?{CtS&Hqu`&K3?OyGK20zf5=RlNfftMQH-9!>BK4&Bl%aj5M{eP)I8`aE^yrJRpH% ztk5jwBM@zX9`t+K&W8TS6;_gH$u3mMtU!LV&%_S@Jxa>*&*-P@GfCT@iU~zH#av8HMZ|j7cc3Tw0ofM$5hiyLNs{(9CH1heV@>W)T?u@+==wCq(rhv{MKm|wgtRD8KR8h) z)eeMnAePhG7lT_EzmRapo+*~jN1(}Me83-GQEs73nQGM%`qV1lF*@3#!4pGB5|Iq6 zK;BEZi<6JtTIFYp&R0ldDZE(r%x887pn}-JjpFg%^R-Y`UU@F$NC*DP}t77HU<8$l>u@b=?CnP)Sl>mjy6X8S{@1}kF zb>Li`f&gv6^~dWhqOCufoM+K#NIol+jZs;BKiJzP=Kg#8m4pOCf&Fz&+H`6YGLLiV znq6>R3b?KEHA8tn?9b#CooltD+w<)+}iXLm>X3{Lvt0)z8e% z*DFQ5-HPz5D3j+G6}5*0<(9eui~w79vk)oUy=pxGE*}zi`bP};y`X^RSKgfqJTZVp z#jfJoln3|M?a(sNBpVou0Ps5bgLW09`unJbe*!Jz-q0TibvFcq81J5}4i}#1IOi-G|r1+3LsF(3$@DIEa0T9FL4{Bjm z>SK0ooGK4h1zBrv>K<9IT4|%~CjeUX{B+7V*sQ1-mny-&o+00VO-*(ojA$o=&>lBi zJ%x<5@R!v8oiIKuIb^953|Dr*w9`)`*39DFQESCD&Hj7j`!Pk@9_aHO2ac#(GoM>9 z0{L<6(V`{GB7W=DA)Tc7EhZ&CCptESJTKKy{8BXpb2i>+^t`Qah8B5p!t1qo+Mle8 zmJQoAfo8I?cA``~Z1CHQkx%zq!ZHqCfgM~Ar;^*Yo0O6L>!<0COJ^wNs+6oSzN@8U zW=&0vW!Urr?_2&%%fP_=?Y2TLao5wfr)$wbo9ueNm7^|z$`9RcX%;~M-_IoNZPznG zT1bS7OxyZOdhidk zslKPAv%CDgUI9?)gR0&TPywG@bF1I@bY@h%u+o?KCa5mCVQ>7!v;$m_j_y|c7S*Sf z;?LDS{O@Md=H`r9@1HYq z23Q9En6v>m(+SFVtufcvXF}QVKXl@no;d@ws~4*$#lEdOKPvE&{K^+Y@3fOCNu$AZ zwwD6a{PCT{_Ia^h)dqU5JTx$8EeIC)y2xn8*|I_sD)+hY(q12rbz60J+1SkZQ;qZS z+5YM3S$7t4Yy8naCiBSloqInWx}_-y(er0-6RcKit~C(}i5)Y)vz+Ix_4~E-WC^#} znmpVEiZ^J$p^oNpEq_=Pz#;M!_UD05dYQ7J`>Lq-)v!T$Zre1E2?U<_Q3rP3&}zFj zwz}g9#M+&FMm;+TAh~W=4qF!r5em!qvK$8iI?(gF{nQj4CH(lUs8AI*ug%Yak-i#p zL}h3r732lc4Wtqq7bH^!PvC*32=!qIzgABFZ+AezrFe<}qhS5dOZJTu`aPYO^jmmY zXRS5UM&*;e`gkq#_VW&^!Sj1n24<>dKx;oI*CWe2p{vZj2u!jg;+f~Ruf)q-?kalk zS;Tner#2C=>Qww7xVV-9u;xl3@max8d3$#MlFRlTA`csQkl3;IyyEC=r+}6&{$)PN zm!{Q`&y3O;>jy??QwVf zO3N*h2~^%JKC8|?PiIa=1qMsAv-7Zha_j1S!*vXn;26ce+Kcj5OrcQy{Z>=g!M#6k>C?+XEaj}*xl&*uJkT z3TGRozb(4t)G5{oa{zocrH?^+e4VD%&6*^B21_o2jt5^%^|a#@GkcO8?~L@yw$G~L z(Y?mr|9Q_xEW$cIQ1`s(o0lH#0uQRv`sO&1Kd;H#r3kSjiVp$!Ad z%+&wIJz70K6~*f+*R{`lE)Rd@x>T*C zm^;#UK7Rp3jta+lJ3zNrOZgwu*?M=Guq#$oS!zt{Szmg1_Gl^U)S^s*hCe}!Wijot zwY%~YEEdtc>P}rtf5X#|G=6o?9!zzL`MTvJcCoq6(%+8|vZs_w2?3bC5+sXpkTcC2 z8GrDC?;!;5&F8zHXQSVT+adMRqFn7K$8kVF#XD2{lNgqrfh}}eVmRWhe;F3mF!`ec0JW*OI^YUk zVCq5>+w(_3SFC)kX}S^oq$EZ30qdhN_cZUST#=l~<(08SviXogRkldf5*#U7_>I05 zGVrcfq@0>N!#qVZ>-e-t-Wk*X{q@D}r~x$*psVt_r?uDR=HY5m*v&O~-aR)zzRZpy zl`BgrObT&qFfu-GdiUowSn;L)tqVBa4%syOW^YqhXO;Dqt8Em&vC(odm*&n=LVQ@!sBdweSk^2@nfonwMfu_zdA*O zlh$Ya_GDjQneA%1F+A4DH%9;RTY_?3s&vbVZowfOk+1! z2*p}eJpV1~8#N}p@4dn5?e{zAPcy{xcPQZ1LF$J(kB{dAG? zoR25zrAZS~I)AN+%{FexZ}jqohmTogwz2j(28ccail?BO&H78*3`MW3InNuKT+lTC zSTpc$XF+m+FcbdCoV;w4O;l};4Q{kv&BorjDCrb`r=Z!GZ7C~5?H5(@KI84ML2}(# zM(&4=v8)Q+;h51Rx=Pv>;b&1=S8T&>VLV;~xj3D%iUo#qjMKGzip}-I=b7IR!#M$P z{?5E6k`eq;h`}DL7fD_~~fLZ}DnIQ-b{9^!EkHFa@@T9qAZE~o5_O|3};QyV|k!vuHpdv(s$iD=2ct0tzEPH<3V}} zoO7Y2{^bBvCjN<(N2V+_BTAXYNGhz&MvcR;G@T7|IuW~LtqcrZse^6T)@-E6>o2Su zKFI=gJ5`x(w+QqPD?eFmId4WvWzwH@GgXGP67{KX7_a*+ zQEL+icx6K$WNaG}0Bn#1#8d^g8_y6%@RcRZB9>iM@OGe-yV`TK6MfWa?=LS9_1Ui4 zYNoL~bcNDG`yCMLDneO)n}?kiP`%mfJ!{(U)g{m5>YoIadbJ$%wvYmZfS`j9eb?&b zf$xB?G7Ox~2K%8Z5BG)7WA`Cjhye}N5&wj+60+Z185++zH&>(BV--QvZ6)w&$oX9E zk%Ft<*;>rmys+lcOTV3H4?68PdF*Id9|s4WW`h0Ot^R>f)w&Mh)+U9cuO}$y*a@|p z3i;Qwjh%d9miM!46+FAow8K!cWai_+;GyOpp_Fc|0wo93e`pO=N5h<7l0puoGUEw;z5DCBiKHrR9*vlNbVB4!59+ixj7x8S<)!pAW!ZUNRvV z?AkC?JH5n%=rE*DmNGl%PLE7G)<$T6u^hHrZq&YhyNJ078Y=;>s7-WXQ~w^JA^W}3x$vCHE;ygO{V`UK3r`$IJ)JB<9#b$ z(qn3EoT6d`R9r`{QLN0M$vP^I%N!`))?FZfY>Qdv`0$%k zI{?4FN$T|kYpB{H#e@4(#Xb_mj2yfk9?RWF36b6>qiKtPxMHhMl<=cPuuHQ#w5yK8 ziO~!eV1mg%1t^Idg8-cSV-5HWpoSlza(Qp#p1R-Vd!o;-tm8VdYIxVa{Uqv(ijGGO>mMQ;wG6X4AIUARc(k}~03 zwT>SW__1RxOx@J@@|=aXYl{Y$_uy3Lk07uh2OPKb)!AT1JW!%=*HTyK4nq+)-Q{6} zU1{OX8$U#PTZ4+~0=f^)zF*u)BY%$^T|<`4nh<2?Wo!a>Tm@x}sjF3zX>x<}6)+RY zo}}6$y8uJ)Ep`k*-M1SKc#M{5yeBp&d|4;vO|gA1)YjPe0)>_3uS;Lfg*L}YX{c)M z;*rKNwYqL+=2Hf203NC;I5|mg4hF9FELJU?E=2$j-6Da%^IEEyf z!N(bh9aE_MS^n4hLf>WrCjk~Z+B=_i02Q0$ZqEloM|dZIhuiPfI2xjey#I$rF6$XU zfvC!UU+=Y+GQ7UK4OG~23vUx>c(WR5DE`|OtC%j*d#v3p$e}(2ng~ zCh27cL<2t;r*gH=qjSaD51+az{sRSbS#ne0t)_{t`N8vgv0K15%N0wkQX6$?n97tn z6-WoJ82oy#SaV>x;zwQ&hnQ-6-fWP#gaejRQ^UG`S}$+IBi_$Z8%yyOI#=ZKtZMzc z(XtR5WmQb#?|CG3EBkjaGeUvn1yl7NvN~21g%`$XTyK!xEB^r*|(l;!K`T(oCSxcO4=BeAFHc+I8=+UCJ2_i{_1v9X!6@ygv-c}X)7bp)|_ zP5gqPo~ub{jX^j)eoH;tE^C#K$REE+u1c?O&6aO)KXiv#53KN6*Eqa0(rjI6IDj17 z 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

?+l7 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�Kv z<_-Nu*c%I#O1lQZh?&~O#Du^vD)edjKW8>BHwW6W_S=d+J~RGCw|4Ui#*8aZ?-Um= zzA3C`-y9x58{pO;iJiMTfUWOxKG%@d!H&V#5X4}uZ}@p|E4z8s4!e(l@YXIjz) zw#>>dlQU;6T3AM-5&J+E#XeBrW7ak$)FFX%}B;k0Jjz}VxV@`KaL_FHt1mXpQM1N7tA;G$lz0ch}^weOWPiN=l01=nz2@q|*HJT6fpfRb(#a)>$Y z;cfqB6S_5hx*jWD4C}b?T?j=(kx03ctSz5yc;}v+f=%sjAe&pqu3yc!ML~*_Kw!w* zah2!Azo!bZ^nw33ty=sbV@K0Ez=UyJOZ{WX_$JcgeO@W~>o(RJRA^+FVlS~RdcOv| zS}fjylLDV_A&?z}Q$*|Rb$4%UL6w0@ZVQJioJvmB7<%5tj(!4OvxW%5-{W#@wt&4si zhc_ja1aC{|^`V9Q&bQACG4zYRZJmp6*;HJ9TuX|_U~C^Y&#}HM z27E5=O=kzCa1^{{(m0m z2?IGjB|&$8iwRyn59;hI9JE(4(|MK+6N%&%Uv!B2ebQ&=nd0&8vO4qll?q8qV!U#T zKS~z_+0aJX68b?f^U%v4-~F8l-yQf`ZRmCT(m+~cDTGeC!OeK1Q~fHY^CQ@RkCO~d zU3t3CZEWT{eVhFTJyH6CeyRrr#!r{+7rm(p6dvKOWx~~Tdx#L&Nj*<;?Ctj3{PxV6 z1CXzkz`OcEsPGG-DDF(p^61*9+4JaQ{KQ*!ZsFD+mij$$B3ng|_GV*llcx7nvfo@T z>ye0B6MXWK3IvMCrPKek{i|c@Sb@*_sA6y9PiA|7P?ayY=hCc7@&)~D@wj2M)MB9K zAYa%3V=jLDiv|1hV7H#qhc2$ac>ybtG0YRmdTKF>u?oiv6F8}b_wdUUUbsQV3(f-k zB+tKW?sAc0+Bkq0L?hT;m>;^Qup;jJ%yO}oI8N0cLpF5_yof&5W0bDVvO;T>+oC`z zri=k=IY4Sm+5G?z2~|EXF!TfGR`j(`#{t}jEe1QARp@&yGtzYaJqj$(Yo2mlaCG8u zq=~$G`yH&jPO}I1brFW;J^bISC z@Xq_OO&x9&zy-^MuHVmk*FOB;HKxi~NuThAA!4?( z45C{S*Bk51R$S^L7}lW@F_z$*jKq1^aDl#3@)Vi@JQ|m1w$q z``?txhY*8H`yRwsE8;vG~JeN4kKAf$$YOB?i-4S*V1sQ}IBr z=g~>0`SjTE(#aE(*y9D&v&ZYz@s-B5JMV!i&`(5267Y%elX;+>okKCTs+?i~UNCj? zEZHeEVCCIk>#UUXvmJF!j^G($jcExRccdC=^|>HaDZwFXm!;F)%t`MIVwGSN2w&npb%AI|p6RDvBgcrONm)K#Gcn7!cYg2MnXaJ8 z&#{3gt1fI-cX_>RZdExTfKllC76OjnB$49>#oU)@RO`RW@qCqoJ+es646=&aqn>+J z@|T;*RJ$yeDM}uc9m{YQ2~z}Vq325)ob&(-%mcf;G2 z#tW19(8^OW@Cs{_#gf<|WJdv{C4JAL&b9GirW*NsKT-0()tw?${SYwixUEJW5$fy7 zONsUR%uD%=(I=5NYv+a|>m!X4EyYI2MkF`6j%jC5!%2V%y=))yujgez zAP)x;?%Q#q5#NiuN7D1v>lW_pTwQi676?N9f+%{BMLP79LZw$1F-BAlgOy}1Dvn(WSeSl)@#!+$cvxrG1F{-7Z)Zr}(V zYO>An2_!gHm#amo0l8W!=I#u$Mk#$pwD_}C6Dlin)$$@=F18S5scu{Nzsann*X)2k zj{Zi1%qcNd%4ujpmziG{`*tIZ#Vb`;e(Tqlg`RtAgTS1?Z&pCe`+<8R+ZIBl0TaDr zZ;oYA_se!)6?CQ;wcT8)oCQue1UN%L!6ah3r?=UUw2|!B^+Cz4Y{%TP@!) zb<@Jk1e{LS{w)b&EAkMheYI5Pb!KgNmE8J>L?Nt39Re=(& zl-|eZfbgrs<6#Q=xVhr>gZ>n!UiaaC8ouP4kx(JF1g&KszT8&MA*qk$Q)cCFmgFA) zEdMvZrb_?o0I?y#Ln&%*SYvq59_!t567^4mWJ(9x#7N^{ZPQiDyYgaT=$?F_^WWf3 z23C&?;FMPlvrrraP3(=YdYBvgv0mPI%(4LUhAu)3>Q8FcCE1b`o7l0RqstC$90%7TsX5(pX#XdTRM2g}4*QO}^Yg}=w@OW44%*Gy+L+UC z?LjrU)l9k-#MuGe-WHFB2|uEvyDz($1pdgDO`#QThV4a?YoW6%(ra^>BB4(!*7Er8 zw=vADh51^PKTUhI+DmzpC;z?4n;U=4zt`?4>=#;uD1lmIeUP1Dq{x)C&_oD!#^`vK zG+P0pqUwc<4hi7vgUZtAn?1u~3UdQVMXjny$&RT1MgsKYOMO>#Z!$QISa4Ev{D%Pi zzGvrf$Nfs^G{pPg#c9T@@%lfA&(WAJ$PzFkwA2h9QmYHPlLZRBlcg9e(B>h6_qZmw z#eyows%*G|Cv{x>9G~OMu!roNcHbdv7FmM#p4cLB_n&Ia`khqFT5i2Dad3R8s~(-F z__>};sO?XZ)CRTYK*x^K{Ug0swpjMb`IAq>mRS~4JNb%QHk;j!Z8zo;RiD~XQ;nM` zo?Xv8y!tlb>~5An;r?B4%4Vsje%Ra+_S;^)v$uU{r2UTt-ZkKjy%7a9H~ZWRY6@y3 z=)KW9&7F|&gYRZFZS{FhX;SQfw}Ok>sns^P!ybizc`y8GeLP;3>sw7LUoYou=D8E* zd1MZc(xU3+N{Ri%zZmu9h3OK5dS@{s61^T1!RIIS3glh#%9V}c$duW9TC0{NXi_(= zsEe-uLKquTH+H~=juZJkKQBe*-JH;veKghmFRR+G4A;i;^IT}*)~iI|A4~X;{Jd-- zf`}I~ShCn4PR{glWGB16;Bt}rn#Xd!A?a$${>qBC9Pj!Qz1pA_kpfw| z6t~8TWnE%3PS1HEIV<3c<&e6`u2`TggfyTYzX zcfD|(slb$L4+BwD!M3l6~q59N3ur z%*;d4@P5nN9=K&o{n}cW7Eaq<&C|Gj`P=#g+rG28)Md6zlKTI#76AP=hr;8+<3wK>M#&V36yY00Gh9Pw z19=-f7PE=+zO?L6g5p&nJOfE7-k#ikjYloYg*mtoecUdy<<@}`?@g_@m=_Gqj^o90 z8oU{R%IXq1w$af# zyyq~K%TR$4_-$O;O4OrRNpouddA8|FwSl)?UGbD|k{_9Ll@-XuONWPU3&@O}r2B%v zRuWsb!g5}@w*ze=`@g1EP9gFBbIM78yvMe7Qw^0bMH!>#+-h5}&kF}OUSBozUU}4n#zB!CC27Wi=wo ze>u$j3fgV5XJg6kV|`dfJ@2<>e?9TNZr>n{qG_x5_1yVJzvC0&ycf9rgl%sruPY(^ zMP^QuVjS6hgB@@2g>0C2ID*#kPo_9bTZuFpy^GjC8{t#meEp)nJSBW@AxnAolVf{**lSj~c^agT-w=IP*qe5yEv=&i2Ht8unwL1~FVl6Boa_I+1~ZRHc5VN$yyDf6?`k($!aTdY zuz260DBXxi2~|0ipdTmZA-iamtso>oCjzf~QU3`wiE@?&-RnhU+Xbld#WfSMg{Tx~ zF~uPcK3$V%z%45>6-&$yT({Y;@#g1MvdsP*($MAFXoAbVQrf?DX(>#{s;A8?@47@* z*P>+;?qo@RtbUWsXLOpCJ*u$|#Bc%F88kvO@A`JsSx7wTzPzPN|H3d(y0XUxl z6>kh~V#rnXKid7=Db?`@-LLW@C?4^kuORG00&vpo*?#lrn5mHTJJ0Q~3pUw5`zRt` zzVC>8ngZ=MaBkmcBq0?bwQKn*658BhQq1|gg!F}qry*1TsK)LOEf>;ZBHgVUP$EMN zIShP^24?kzzuOV{1^@Onu>INf{Q`f!%X_8YpCGt(L5|H6xl~QKU{zaWt3LdBL&|i5 zzxRqjFHSBCl+$t76HL%rIl-2Iwa^3o39tep@dwKZ863Sem$O|q@_x{*f6(^j36kyc z3g`RqTakd37b{!Va*y|A*z7G8^+TS)BjXDLsF!3kJLy!&%G!MX!XAV2+oa}Cr4=@b z)L-&_iFcQeF-~A$&bk9{=*pOpWgTw}DC*)sU>Q>Dq*V2i()B#f3sYkyw_@GqEt^%( zbY+yIn9`2jeT>~d8Jmpa1t+&FdELG6Y1lu3P!FxS{ZP}A_)#Vfqh+&TN|OW>^_~=U zI&cR-f)}B^sHubMNwMK`0G=o(f2cFhsY%=VBP)?1*TohEF4$q??!KXKL)6T6 z+P=Vqh>HVngFYTFSkn>51H&24_In)c;Yv&Z;g)BP90HUf@Gs)A=9>?R#)MmdF+h80hQlYBEUvesC&okslI{+W;wFTBM@s}Ngl|!39b3XayL@?okS3OA ze#p3|Yj!1W-IPppiMm}~jurh63OgO>FFp+=?($cBYe#=REeS5=vy_g-eT^l@8r+^L z{Sxp=fFz&4Il0L6@`c!ipW>4IRA#Kjnz^n%T5oF=!7K`?)TIjjRUm>hd1?{=h9@7M z5?}4wo*4z@gav%N|4-pbB&ktc!G5%zCegsb@)R0q)_9%v>69=b_iWMnvhoKWQ)ll)`>wC$Mu$%t>&ah+6+ z-Jpe1jno6njpuJE3I7CFi8>6gPRMW+&V*7$sq97M%BI>4sS7BcQ863D$l@3;JdiBe)Lnbm)gCwDm>^L`tQmkpe#!XD* zN=|1<`PFj&$STA~u6X!wvFfyDqx<1inwYh&d4=_m7@l{I`WgkfzB)y8;Do`hIY$l} zo&6tQ-O7mx0p8mJyo$r;(K^pqorgL4KULE8KL})x(W2t~nEcuVA!~gBuIH&l`_7K) zg@OD&(DO3@vEF7%Uo~}FTFoLz$H*L0*zhaQGi+YjV}3M#@U!0ueDgKpHuG+U320#{dR)3zanIe zaSKu<%6fj=z6;a_{*W#H*-jrWSiB``I6bIEqTt^>3vuCHRMG=g{wxq6IlVh&m{b8G z2i%IL80;{r)D5J_-jH`d)D#ZzosJB6ObYuH;6WXijtf;jPC>f^f>WFxxWA(`mo7m_ zOxk3&YRkyYN@ZTYMlfgUX&sGE+0(;@v8W?W3b{G)rRp>sMxN!S{rk^x?01h(e4w0Ma_5BpA{2ik>k;DJsR2{#LkxAu zgkpI*nEt_Pz1t`)TP;E-8-RA+t zjr0rJSBNhl$*wn8|4S}E*MwJdOki39=$qunKk6_@=o$^T87QrQ}9oGc#h{-XS6 zs_Pxhf8&?@{CUN_DRDvI^#*%sb>@{Ta!G@vR2(QzF_YY;deM<#l0NcdMw!i6d3+G$vkQ6UH$SyJvHd2~ zj@)*zW!u{=q|Pmltj?byahI*IL88rNGSQ2yO&$L<1G{fBQz0PLqQsEwbT8~M($GE# z^Bqv8^7r-MJU)HE>)ez_W|K}5eS3C(gAaxMZKuZ9qNw7^T@}m#JOAW7B4>-}*JXd# zHTm!?R$G^a?4t4x(JJBo!1xOKx+Sg;&Bt9^+Jcbblz4-tj(yBGEhMxt%CZFv=bH^C&K6!A9;#5)-^NksJJ zhWfK|RES>mGSR2MUy}b0^a=uP{L5hRaCSgQb;+DDXe-85^AB1>e z4Pvawb+-Jig+P^cOem|SS&XdM`E1XwGPR?vUQ{pmd!H=+Ws5$U8Fjo=OW!rL6n0Oy zVu)r=X}RejX6-wnecs%!D2&$+m2WoFCei`=o%{s!@4to1jM1~e{QZ21-nXg>eD>t^ z-?MB;QQwjB8L3ym>hWT<>HZfE#cxB8TOx1+Z0|{ zU{g+RJi4bI{sieV`(75*rOmGm+)(Fs6W%@KOXnNksa~(?6A^rnW<*jSp%L}e5~lfb ztV?;S95FxUKaYH}oW&X-tBSh0n3c0}Lv2T@>R9FMyBml8Zl~*m-9rC0q2-~QtI2uZ zJDCF~z7=UIWcO%{rnp1(aB%V!^1Z$=wGh~?s>=eyZ_!p8p1oWC+r!Ay6=I+UQAk&u zW)mXZc8Q}wmcTmFvQ-Fgl-!+e5EB9w4i-Da59aFm-RkQdOgC_jz?6=mEjhsd&jO$b zbxBa(2k!rj$|P?WlJL+1m=bF4bXLrZLGwCk!I(siRNQc{*pcYMI?sz-c?Y@&3d~2& zI_d{rR!$v7%7cC4ExAc!F>SruGdbp$(U@NpIg5XO=LGk2Gg)rXxV|kuMi?C}%P|z_ z5hcUsI%0(<=YHR6oW=^p5B@<6QP=1mhACtX;{8%Q7{8uOjdpDSF?*saT3qihL8Gsp zmP!`=o4O7RgbO7r3@fJ#O7Ljk1Y>bGbT`^XmM2tMZQzNAffp#fm!2D+V8JgrXxJ$` zE7Je+-GA8sj21VkS%WJwWtSk@Lv2ZdR$CDML9?<(9%-F1!52$B77GlQjY!w>)#A!m z!U4A?I*z`3Ov5s&x6ehqZ>Qbr=ms5&9~D5 z#I6;ntgsiu!zQ`0@2+2XZ!n)uOG@0_TLN;}Nc;NhA3t~Q7CW=yW~6JXXEiAn(0N7F zOnnzk>33N>n|p-JWHpkSy~+)unX(OkO4^r`0OuAMG=abq3)%>n!SO<4A6OR!2d+>e zTzmm5AmhnS8ld%Y_D@0(wOn?J5w%W~&6mbO;%(7&LYqL27=+G#~d$K{3XLjK0K@9Esc=`OMiOC7 zw|jOT!tNNZ(f%>()9;w7L64mE49x+jYc(73%*inr)_cR6lOFbP>pW`_bF)J)O$;Vt zF1GmYx~X;HI_-k+V?!D?wrP|ybLw1#EwMFSbhx{R&+8G%QHE2+q}bS`1?FpCvtHg- z+(_Ck$D7m+IOwyq9v=~WwpNE+rowIEjusS#m49@jKHO%PW?twciDyA~aq$UY4VhFP zCOhxLvIh%98Pwih;*Ynf4w{wP?(p2JWMv!=7WK&ARyM$tmHD?VcItjFM~oR{d*RJN zH{GhKYF=Hek&mzRqZ~gwxsjp?JtvJ(=8#vPVz{iEs(RwXM{x5?L{;!7?;IdnNcRqa&=S`%q*mBlK|HqAN80t0=4;e#_UvwKyd0H-dEw3fme#`MV zDl!}_on_=x4Vusae@sL7q|P~Fc>IfwMFYB=8QDD@hEs7%BI>9xkUtu!AIK(TTgxJn za6#4+mK`->^YEvNK{k|Sb^Qs(F}tUfE5%5WzQPxMqqT;xAN?W~(WMv3kup#>bxZ$5 z{L)af_1Bj#{$qxts=?>)o9#*iI|w5cQ(w51r@r^6-4j_b6h%)5)-;}c80&VpW}}jc>dCUT0gOQS zu?1p05wm-0;}O;C|B>vkZ_$$_0>nLh?y4)%MRnC0-Jy8f)Wz~ZcGOv6$)7G8jUc*@ zOI=qD<|QZ8x8$5_S|{$kR$S_WQfw6K{~=8Z-{DF%?GEo2cHCnsaS1pYpjQ|d+F}ee zjCT6Qo8NmB^1QxB$W~=%VRpyM4=Zc$6k!hMu7|oGcU_e%f6#Rz&2h7GAz-nf!3I-dWDAJem5%=rp-#_%P@m zrFmi5z_6QS0(m>wo#_+qogJ4t^!!N}xpJP$mJj)`gk4`4xe5i*3OE6;?{W%pLoMoE*c)2KnS^|qjc+7}PZj`5En$>7DlZyk_43Q)du z{+2<*OY@ZmS$d%(AzbD{=twd_Waivx(Japhbfr>p7>XO{pSS!RqBhZ+Ao*+~|3UtP z^A`^uJZ5@-0UBg*Tw2RxJJoU92x{-YUk;Bjb(g#;THD*O5l}{8?&&yZOFCqr$h->7 z&aXJFRC<{(p)oZC1Yx}^NUQDId)g9c)ER3Vz8@77=BW_Qizpw@zCe$sC>PQ(1{gEm z;I~W)KfK@-S}+<8{t@twzm}PPlNACL1*) z25!Q~1}^Z*4`EKp{R)NTA?WAFA`rO2mO^X);Dyp$R@bv)N^YS7nVr-Xeir!8l`jaD zMwLvD*Hcj*%cC(s5%B6f)r#Qz1QZd!pW-KujdEc5l%d5ibiFYpgk#%UFivCeKf z4aH)dw&{G;a^}XG?r;gjgsCSTd>t$6>cti&B&6V#pA+oOkK+DMA5hx$|g=bEX7#apQ+W<8kXAZ zA4NGe-V*qdx5VIOJmM`&@D1Nr^9Brh^VVCK&9dj0Z8){em}SQm^+lwSk1<>-cEDNx z!x1%HTY+d;R`FBf1$@}uY(N(Ds~Pgn!`ik>wxm5OyK`SfqhgF!199w;E?v0Gib>7^>2W6spM&gxrJzR43R+=m0$ zaSLatj{maN-ttiCS>xcsfvR#<=t?ry2Qm8H@_OF)s3jJ;-&BLC0o#V+{jlpp;wSH} z&-P9tj$7ndj#HFS0&kzaTRua3J1?F4o^6=mG%+4N`Beagz)y-0&T7z;7z515dV9yj zblRyt4igHh_heLmGMh`mek1*ZuZ9|n0$3AR`C>D}-PiqTeNm^RNeth|*C&qraxt;CR zF zh*FnBa#2W%AkVt$Jz4m-Au|fIKn9AWrzw?C)?V0+XQ%T@o*AwuH{q^iiXLx7J3Tw^d}^g&r#Wsb znh&IT`|{t$9R`Ok=M1XTs7gkvIa4XHs(6mX#cP-Q*G~~n(S-&3EyrWKY9fu9{9)e` zCOr;un55uh+*lqCRMutFuqR&ui)9lpqG1!??71qpYX4?94%iMPQN&7$o}{0S@{}k3llds`jASpwk~F+0+%L}pYT!q(Z!6$)>otXl?pFVHDJ5; zDO=pq*D&Df&=!vp#-n}Ps8K8prDJV2?k@v#We^&w!Ue>&rS8q@=k5gB@ziE zGm?qzd@B#i6$*Y>Yd+l><(VQLQ!|(c>bdIV`W-|%^^rjM(q4SXmT7!SlPz@>AORS* z>C>dzdrTsvU`-v!7A&K6aB`&4M)S^uBV4A@Py3vY19MNzT*N4=SwQBOgEeYk>+ zc&2djv7QnIl?z?bH8Rdf7IHzNUHMZ4#Z0J7Ecfqwv`9Kiq>P@pra6=l0kr@v4U5OaAKx4E zWhI^*1ciWfdv@S1x6yY9J+YBIj!CeuD@A>g!!?kI^fNucE5R=JAy%bEB3E}+Z3YW4!GRjnS5>)pR@U3&N#!tKEGJ(m z-SqQkLZkmC3@GB?5|zC#ZX4%gCbV4VIK;yp**lIcLjE;oJ0&Z7-R(gAO0eO@5uL*D zE}hQB%#{lPUJ-EG^xKT*PT-1j@fDwo@n^YMx`j(D1Mwe?2Ni_%yhsGZ*Hv_VNSdvu z@NA~UyO-UW-r8d7F7o{(dCOGrm7Xa@%CX|3MM{#CDTrCN?M8~{+B@;BB|UPj(zEfK z;QEL^Ey;CkLo}o$xXa+}s*OkTagVyvCfh_0t=@JeoNz{digP^GwGg+&eMn(2vqeiK zixWOllpN>$xoOMFQVufKrcV0R{v- z2hc|Nd?8;lz^fqR+CAO_Za`3~UJ1*}UpVlzW=uYZBijF&1YU`((M_O^vJRYH9|7V{ z@B8Xe`pHIl&-?5xCZF`YT5tDUL&p!>6BYgCC9Pl7Q949Rz=!Qx`(D|O!=ZfFuiO6o z+qcrq8#mJ#bLIc=!;kXsi?6=0llo8DVV+mV`}gx!0N$l>s0Gm_t}*Dui=g9uZ%wPr zcS1_5;m9LBCjF5gX-*;Hl71JQXaWztlBSnM8hx1ZWRMX3l6I6>U#ZNXTjmD7r@D-| z_cH7L(;=4)*C}T36tjMVi^t-5 z?(|&&dziV~=R@>Hihc$IH{aWZ#G+>ne7R)H%MBbb<#i^qf&SPt=M$Z`IgHa*_wU+P z6AtfVb^pxSGwJiszet~c`f2+1^tb8U`E%*=cbClN|3?0FABXncv3KCE9b~J%VJy&* zfYk4B<9)@_Bqw^&zc`)zP{yR7?eyj5i>rTrxyLYZp@Xw@U(VZ`kaI1YCcW|y&vE6n1`2}&9)twC-{IA1 z9}l8Flu6^B+`zpLc~BfKrQE>)uoP(xup2-E4B(R+FqLHR_fPpOuhQKe#lzG&EU(^u zSUzzge{uPDQEAGq9!Q)%T1BB?jR=*v!gF}yHhi;u@cDs@!mbHmJY)12De~k+y5q%` zgUD-^QQil?O`}8!71t`?@4;d4Ez2tD07u^H1SZ$~*l*15yG!3?!fY4VxnpPIb7SxR z>D_e14iP+f@L)PyQYyMsa5(|R-aQ4n@cldj3=De7yP%ezhH~!v?E9#AetvL$K#xkgJumy8SLpMF z8ONZ`7y#D)GkQok>>j+P z8En_4f>P);323f})*MLrXOQk2sB8GXyEsUw2?5=1c{L$7%Ds1rOMf3qIWcfVaGIpl zbp5$?EB1~TI4VOc@S-0Id!|kaIm2;tYBmJqUrU#-TuEPl^L4I2 zTLAX&+h+!V!**`K6Y1G!pRvOQpUr0q?B26C?cHtX2iO?``}Xcld-m+fTMM=s&bYZ4 z6Q*vcz#NUPm9nA#&fzL=pJE)sdXs>?^ZCCFVVOI-zi*B8#`T-_{$H|#`mWd>{cCC7 z3}n|WK6CC&`r`91ZU6pP>Fjwswg2KpGYZ&Bzn$biIr#go*xRJXlX1IpolejdEfiJ3 zd)$Rh8u|2Z@~#8PX(>FWE(?`e^C0|?!5A@!bzGIasyt|W-5lZGNKUHP zUHe=aCztd4wF zrqAsYd|#jVI(=iG);w=6{jBm|GuX+&+bdAIZnn3{_+7a{$7yEj`V|>h#|35DD!VMxOCe3^(5{2>ygTzaU;?3uyJ^#w-0!NNgU^yzl}EXZ z`&-PD#f=7nQ+`=q^p`3<`dH>dg)u0Yvn%A}WqHP8a(1{O9we|aB;ajFeM48BXvd>- zaT?jod#WQ(8u_!lg?_4RhnsC2c+K^6xOf|1{Y^W4mMITjGn-}Y2HI;Vfvy*x z;x*9rH}sXU2;CUSX? z!#oOiF$Z$_my@x@B%tR4jamt|CpLa$&~=*QL?i5JC9IcM^5QrP_D*;{oqus-4!vHU zcmYRvUbat&WgsAr@?|6tRWGM3TRaABhoQduiH74qsjP2}?>vRlFB(oCZ0N>)Nh{~_ zXVKvJ9)mFLnH#jl^R^Ot;o|x9*Z2Nv5~2=s_Qip%W*9h>jvYHT+A{D|I{x_M=`s89 zIl?`5xZpN31nk(cJs&WLx4^DlyY1k?ILUue#s`2w0*grCjvdZ--B$1Km^=RMJ9q4$ zzMFOk-wj)_znNF}&)PwKU!6FSPMD(4KK}C;F50U8`Mjc^w*c6THLpBdtkzi;80|aS zYS|u3*ri+t-KNs1Hrmc7z3vOj@&sSv3SMp1aZ3!YNmu#chq5a=C3N(y!pYbpfPOsn ztpbyw!OJW0m9~{_M&=E0&kpA-J@mv2#(!7-WBhN*Zp2X4UwWEijsNt~5nOiE!{wl~ zfElg^32Zb8^u6QWM)1;%cJH;Hqzp5+T3Fyae4ItoN8c%}UQEAeGr&>5(M?zVmh_A+ z2=U&|@jjuQGuxEG05DtmJ~Gt%8mt~U@QT4lWf+ik3C!W0~mobqGg&x>|gH{&}8KlT_8YtJUxGT-`LJrX7eRh7v7rD&3 zoPeRe!s*BNG90TrhF{e!=poyZkMg>k3aO$ae!8KeoJ`T$@;&=US+q^QIDqRkUmT!K zZ`rJ`2ykA&p543CVcSaZMD`kZG99w(qlb^A7wy2oC!RQN-T~&tV>q<+EnFK83cway z2_(rvL?wFSfV+uy8yY^$n=iJ$I=?mQTP0_z#d-YFz zeIkAH^|$G}%irb0`RyoRkyW8?|Bpu58T{EaGXr+)c1gmkJ z{=)fo%G}GluiOft{?6V0g;UGN@jY(R_4Ih$-hWFDo)4bW_p~7%B(M=Bz8?ylaPIG0}-o-yO0A6w!0;{ytn)vDw!E5Km!DE&((drc zsm2k3Cf%AU^^{w1d}=Wu9G9}8?e~(U`1$8djK8-95%R{?E>Z@uz&CVbYTDfY%Dlx2NCW+us`j!^9ArOfDXohO)y}AJ|m~u z%moDkIS%3BmVhR1QWEd+KIJhZ49A?nf6d(X*@J)14&=LNF8Wu^MW3@Pu2|Z&`T2C| z^5t|n@6n&no&Z<4zjD>yOFNa{l>T}$TfQ?~>z-F^^qQ@LK!avCvE`QAMOSH2k2Z|= zHME_s;B8xZZk%sIw&~UoK2ED&8L;F9hw? zzH(kMHr9PvltjOxU)%6V{iUb0RrnflfRJFVSYpzC-kYTF9SHLs6Tzeb=W?pAJ;J;;_Np<{`ju zj~yEnM%Ok9q5n#wBJk18s+hMN`7}t(Z6a+{k)y5KX3c9=AO| zoCdrMMn#v#5I+hMpkL4ehuWp;tTxO%nMJtvXJu)ho9(l+tnzmS<^;5T+7tSK+Eo|i z%G1Ov^9}P&M7fv{nB@ydjR^N2l>aEBNs$SHEN=H~rEe_^AudFUXM zX0N;BB9q{mYsXa#UGW-lDodOzPuD7+Yp2n?794*a&uOb}@a_|Ru07~Fcq2W|P#Cl9 z;6+Scv#fjfkVF4~t8yd@e`lN|3LDBBKj4~1IVKEy_Uy7R670A01&*epM~<1|zcU@R z>w^alSlVND#=v8F%fL1}Phhi6Qnqc~mbT}!2DaGs_I%C&hlTCjxyuXvymdQ&Hjn4c=kxB|zGG)goKL6EoVI=YH_|!#yxzs{ zY=8cD-=#BW&YCg6PUg22e)lk08n4agt$W^Mf0vg=uMgVkHp?r^QGcUJWFMVoy3_Nq zyQJ4Hv%5}$Q@NY+*r$GlbkP-_76^idmkm!{o_B+O zVQy|q@jL?FOCTBp3n@ZP=6Yvd** zPB1(mhi1S!7#6~2?r`6ffI9T(Aemfga@mCJyLa67d(s>%L>oGe!*$>_;Y&EJ@H=cM zyqQAY?_bi?-ZtpDXMn?bd0|k%avr$y3;>#e&lP>;#~@i6BVuA5Nxl)!83AV0swzOABuvl)5?swS-&FlSq zwt$~6;Cv$2GO(?H?F4*r08fG=M-H3!z}~#2;LxE%`D+BnA3vU+eDZkOY~Ds&jE~Lc zeZbiRcpq^nVLorb$ok72+qapKVOv?`BXf-shYLL}`1F^=w@qQc zd+%;qV1?J7EsFVFQ}A)!XOBKVKCj2=`X^7FO4m)Pzk2yfR_bxfKX0GY!&RSy`uMaS zEB`AC_4~kkLMUI8@_Mz(YQBffGM$eyeQ`cY-plJuWyHGrjDA`n59bkB+Oftr8QUD+ zW3_YIq1ve9mi&u>x((Ccl!1OM#{ROeE1|?AeGUqQZ$IoWv&1d0qpoG@q-)J}Fj}h5 zDPbvpZf-bxq?E~Uy|E>r_AkY_xq2=Io_TUxFQBc^pP*CRV?1a#C&N?wPU((~q3VCi zHoh8?RUd+p8Q1^*#R%%jnBL`a1n-P*UE2qQCvS(<;CHDs1_QuSB{slMkN^W5gJ!$6 zssS*XYb9U;kwvn+(Julra1c!Cc+@i9uZJi(|u_Y4qU;TfQI z+ zhizt1U{$0mz{3_ZFaX2#tOBd;x9y<31!iv@;hwo=a*!U%d)d~2&n}df@98M-=g*$c z2kGISKYwlB_TZmO*REd6lfGNGZ1vtw(!Xp9J|15fYxv!=)qZHu*Lv_iKGP=8ev5~G zIn7XnBetUK=JRTo-46?~HhfMUm80ttX7Tb0)S~T_cqP4DLN>mkY{P5t>y$9y@kqRV zHt~fcygIL@B|6P#Tf=yn&Ij)XiUjvH?SS;FvW}iMT?`Md%vi6~V3BgE`(ou!SJnVE zNZ{d+0PP7cxjT2FudX>~KEGfvbt-q@$^g)9P;(60H=p+2whba(`|llcX)$y~Tgrd4 zO$Rm22dJm_Ig!T|a~x>ZseVU2yS71i{w(7TvCp!&f%Zn00DE@s-J>z^!ZRSoD2Nr0 z#wmCFwUq)5m*4CMUl}KSf?L*-vat|qf`M#?uv`h~IZB3IvYtd&@&_W`&3reyjd!F} zf`KUC=fDkkUEzIy!>E6R*jJPoec2O?eN^Vj7F zFWM6rD{LX_n(x4FUX{i<8743+^m!iyw)kf?`?{S+fO|QUeLMj8ZMKS2>rK}Fw{CL} z0IQj~3t|k|x@DWen|F})pLhsx4#7@4%+Le%z_`HSh8$kl75FN`0rOMU)O!?>80*@g8PXGc& z16K02>dz-7wdb2j+2l~aTLByCdKZ;bUI*-IU6p0VwNsC>$*c2u=cfxbp1=1&8!Dn- zrj^%qIijch^16f)bHF$qTyb^Ho1wPr7;2~950M&`D`_}<$f7P^^u51OUK7XpiF93+ z>E-n(w+TMwz4L7X0)RXKrzAXp4HDQe62SAtdhk|#==bT*7Z$qCSUeTHi#FZ|MQDR1@ zZAxcyUi#W6(Ct7O1aIR}H&UY{(trClyto)mh;F$>wMgR^m zECcBrPKY6(D?o$%UFLbv^d9JfUrrkJK!LwuC+6d(-xb(%f8(a*+k~xD)OjwqY=8cp zJGZO!E*cvn&D*1D!#fi181Hx)+7rNlE#bPZp%wI2KE8&le9hOrS_sb-S!#o3z2D%%IVPSn7ROdFnHCC}CH>L-}2JOD%hVA0+Uw zNr10$X?(BSEp3K&!C11{`Uf{4M*TFdN}=ylpn;~pVT-Z03+U6ov^UM0f?nU1^F@rp z&(pWI-F%MS3boS^e*M0)V(s}Vqd8aw%@U4wqd^UR#WVT*Y9*iYf(8@%s0VKKUf-Yr zA1ces0LS6Tt$7wNq?e(Dk979NNimQdDzXMfIr5M}wj~WI6dKISbkVM5qcoIF+8e(J zDmU)^N;KgILj!!c_1_^T#op(&2mj!;mSIf|eD#+q8y9hWZsx@wkJyXH5||%cE|7U>SW$8Q_=t#@wjP z9j*rnY-|be?$ai4b1x0~s-$(p-tB9Qf&u?UUQa7V<|=e#%`5&H<#CJr+t!^ zaZ-H3qm=(zhiT%%8}wOlP}{B{sI&KlWnbk`;QE|LeVXU2T|5{7)=t)sL`m8Pz*Yb> zbQ*JvhFI3{?$k;_+vR6E0Wp~JX+Ih%7(u^@PXnW2!c((jX~M4LUV}gU$VIhDtL(&P z$w#x?N9mqtjcjA`)&E{}%Ow-AEa3$m-q#wVJqS5Kl-a~7pL8w{zjg?hZCPwR8EDcBOs^9IHO4z=h(~{>4qNl=sqpPTPg5-ULbopn z&-Mh3}$gsVQMR=mqH1Ae-zy1pfjlz%29UHs@ob9f)ZAc03w0&D@m zz^;|>S^|vKeA0W%79R`id<+NX0B3EUg+JSR*44zuC|Zc4oK2fB0*EI4PIu6lFQuP8 zWwiZlVi{0UKZ5cvkHfCEt$xb4wAJNn-r!pn>b$kP8w>zzC+kO~B%NqUqh6e!(pMX-(G6X$rhy^QAMQt81{Nh@G$g%ek{5{@7do(OP+4Ti*VzH)#joT{uAZr8g;+_kmNE+g(mUG>__w^J)10)= z&bO}d5Jes%0BxPN);BjRWu~!raaUo@I~Iov+G@)zEK2!r_bb#@eVz23z||G~+*&M7 zHp^|^4+emyM27nnNq~t9je-Vn_bvmX2InBUkWcKSLs8;3|1=NW98R!@jOZpE%EL&y4tbI za(MBkzoP9tiKe^o!Jki*LoTEVp0=!QM1e0}e6YnJf)OF;j7oKJHxz!CN6DeCqx^PW zof5n#ok@!Nu!gm!K$CIO%NR44A)u$#i2`AY%O)RFpbQ`#$~Zy^S=P_S1vXuN8#nNr zQW@9q-u4|LaGP*r2*1d2KYZW^OoeJUz=UENaDm&MU(yL!$JfMGF7e(!IfmLS6L|1^ zyP)Sb`BLHn0PXNswy7$zV6lZa*{)hz{c-dxO-Jx%3 z_Teg-`taqOuI+rnah;$We-`|=X$}T}woHbURgeG;gu^{}xoO-Ubg6GXZ{5nEs8s{c zpC;BsLyGm>oH`Wnu;gjL^}Oi@@oCEJf}t*~X7H00v4(Nl=?9 zt9g!15aHkJlR)%>4SCc9)vZu{(bqAX(V4zL8y$d>%DN9CRfJ71H2EA@v0MXUcY zur`lNYgw+3Wzm6~QfJfCd1?}XY~f`5II|L9-nwISooFxEC83=Ju4}DL$}QLOE|wIe zjgdu3n=EB9I8i%8`{lzJ=(=q4YW*s=47CrI@vQTFy`N>#em%=|7~#DvA36T3sgScz zR>@!6w=PGte%?*%b1Ah>hmLjH@;RkXs-@^^Miw+d2j55*&o+~Ceiguz^U^+iN#*XZ zWkD;uy)I>dl>>tEO$7w)Pa1#Jwpz>Dxzw>nN0}xq=w6$Kv~z(s5G0$Vn&ccWPQ7aCF||XL}q@Fmj}pr@n@V zsGuj=bjYG0pT9>QcJkl9Pd`(2ZnT=-|Dv3Z|Iyzdcw{}lkL>b!7~iXF>)JkQehzzi zwjuPFyy7#Bxr5d@Tjx?Hw4Qti-&iKTgbiUo6I}-ZWS7g(5uLAX9?P{}c+@s1U>5wQ z;H+Ik_%FKJx^T_FU%dL-xF;DQW!;XT+n=KISNk%YMSTin0KnhUp$Wmdj3wU8pGCmW zrO(0V=W3~+aCvatnp(D@lsvCDWjYaf zM+ER!R`GxRqHnDGY1#>YBLJVNeOYLcN1MXy0F1l!-JU($_pd{pc91{W&o{`JWAu$F z?SOtoK;Hyg(iW@#OBBz^&j7%4aDGEAMCw?b#}TN0>+HNDzy~+zBiwwvcVEFdRfE%WZp2 z`+cv^-!~<o~D$EB>Hp)!hENP-_d4*T(@2LD+6Wfqk(=aW2DDcmS@+&=dx@jeH|Zl z(%6QdyKH?|b-~Y>FwlnPkq9IL_%!~mew6WZ+Xv%IEDU~pXr;d#-y1(?YQD zp_OI&+s@dE1iik%&V-RoP@tbS?c+m}|K6Tx7Z|%7;m82M5$?h_w1Gi_B6S1-_;RN^ z_~ z;0a35OSdQP@DT)Hg-{WHPnMCXgM8$8(m+RlDLLmWt$Rl2OdYUMD{Sf+T<%b)ESNo2Ca077+gy`U`9TpM4~{c)*cU+_gaYq-dywtn-5 z_OiESiDyhl**^S2PS_H8)FkrHS4HLO31&@KkbNd4*M8*eWj@ZNWuHFR7q!bdGl^!fuYq+dH|XosEM3hNSG~Paww8iNJS6Aa()hm4LR6il6Ii{7WAN#HZ9B^TE+S&uvUB z#+BohR{G4f+84Eb_^}ooc;yr2DG$oL%F(t=TNOb9^&41WhmV z_A+Wx%MF>XWt7Krr?Q^5a57ir5~qp>{BrgvWZ+_vRQboND;bItRvi7@SjeKIKU zDUA(Iz2A(IkPEdtla^mH zL!{~2{GcFJ+aNn@in231bDRanpf@J*QNPhg1cOfU?Z=m^a|b8=vMJ~-SLZrD#)LlV zK%Kn{fQf!h%VYss1_Eehuw4fM%084fg)PS%u>J7|^t`&@!3DCS(;eYVeRLm~v_w5r zPp%`Vp}bQTxhG-B)8qy{mUB)P|EMo^>VEj17X)zDm(3Mel)9VZ!(5j4=Ie}F#xm|{ zZC#CR&)?p&n!c7*Us+c8BIWD+@w_hMX}M=9$tyz5Csj+s^+?_* zFN8>spLt#d(EGabk)R_b|7Y+{z>fhkd@bHJ&&<`>?itROMt-iqOw)5YVeJ)cTLp_W;I|X0;dpJN2zU&%r_Z`B9soc8K$7D2`0>|yZg7;dpw@undry z6x&(a0XWx84wzUoAYm|%vmYT+CR>?E@Lo^+-tPz|>dNY#R{v>;_{-z<5h(BDXaKvf zhU#R3r}c*@DfN;*&xWJ8NR=`}Uda#f^|qJtNuxu-JmgwWZJ#F>vIiRP0+1cZaj;J- z{UyI?t&7z*uL4*fy6Xd(YB$iq4uYOG@Cn|iUrFDlOZ#k>2N;w^kRT+J(jY?Z!f?h_ zlP_EuPZy8s;j(9*1G{HxUDL&VEAO3X^}Ma|-LtH|&+WbIHOb}{%l10>_R0^=?NpB) zJj=GU5^LMw(^s>#2+&e6*(|ysl)QrTrM|Fg0ff{oO8HRFx#BwB!&F)GI;vZJQcpyDu{Uup6>u*o%NC#&qmV z^0igAc1AnsuV4BwAdLe719)-fuQ+5As}tJZtCj!SZri2CM?s5-Zn`wjuZn=5y>a6{ zTdVc~uAd?6@ENJ->vfg`Yh=`NT5DQ)bVl_t^UVM_dR?V#%VdJy+f+}A;UjRMy2XmP zJ_xAq3(#qo^0_9WPlwASnl?eJ0jhsVi!GWoL;$hJ5m_yE^>tT#uB7UxGGT%oY+pLm zez{#J@81%~e12Q+dCpg*Y@gq{9>QZx(_>ZADc#fXEY&*3S2dBIzn~n;sGkLB#&pOj zdf378N zUG2AjEK#p0%Ews*&>}`p%ROhz!YUu<_8I6oGA9vucLeZrw(heysB!iP5&4`xw#obR z1leLSV8o%e)WLu;#r3(2MOa+GX1#LIf6UO*X@{8jvkRK^(b|O!0QgSj`Jo8lj5scX zng9O#b#|V95UznaTY}V?dL@AEzYjI967B)MRwd~Cm%sK8qdR{ZCq*gy0ac|SFJ2CT z7*Oio`Wd;dBK7kz@&n|CPW-}}J`+$l^K_2yl2B`>>ILv);AW09%u3>?>(5($2v{b_mg)s58a3Qobm+@F+WCv6oo(GMvNN zD}uBSY*TC}TBgN*{-_^;i=mk&-aL=$xXJXz1S3qhO^W*t?YfMbc8Pu*MDBUlZ0qeP zpP{qno}{op3emf)JLqIhZTm7`-$9Q1%vS!{^3I-RJ+jKS#g(5=$sh64Ho&3-3u=tQrt4EoIuwxb7rjUC`&+&y|9_pnSQgueU6$uWAQ4zX zfHsss-`{`#-}yCQ^{qX%g8*tbc*RDq3O&O2d+o}h|90O`(EsCu515mu^7_BpD&{di zfBtod%Kly^u~IKzz1Y6w6 zzH%4<02Ee9L_t(?Js~b~`m9r7*btP+?DGd%CCj2L6OClLtUP-gEI|PEt>@*mlH{DG z4Pda%_F(#d`4GXh()N2#{PAhpE44B7|7*K@j4xaM8RTQ*HjZ6YGb0grYXtD=-@hFM zAUKHck0J5AfPUYBb>;@M?ax^1b}nrdV-UXvywxty*K6`muwvZiZfku!MFs#Kk8x_a zAfV0>$NhcoF!jYu2Gn%wy~ooL^IM_(eSEOG&MKOm-Kzq(cDT{dcwkRtPuq>KDaz~H zD7_5oWAgv#MyR$Rua1I%p9SpE^U^=d^R{Y$>*soDl`Nh$(U0lM!E$Yr<=ZaoF6&X| zJ6)dJ)ql#yuK*yo)(tJX%D@0=b_mgFeti6K>S#YM_CU=Mb-`8-(wU6I7drx64{@2# z^{xGR4Lj*L{XgrHK2`yjS1vy_o|IvaS1+yG<(!>Y+f!1^rURE*jw8_-hkZ7U>%1&$ ziN4QYmeE>R@+w{OmT5nOA)%hQ*0e#@^HJ985=Uu|Wh~Lg^JmKbJd$UsWx1yCIoc`b zXkg5iSYG#2FwJFdCnO)=Q2!5J`uQvd`w9lE*=Kp%XSbW2`BU&;-}}M$mk$N>@N;(l z<;wpuQdyD+Y$2c^06(|)*QxJU|G(5Xx-Vuj{_&v?|LJS}ZWHSEbxZfCT)NA?pE(Ha z!Sd^VlH+!PZU4tz`FEW&0AM8Y{6qv891~Id>*Q3wPMs%?Hr~n`jQ|d)&R>Il-Uo)q z0f9O5Lmu?3Fv!WZl~*hO`1Ebi9kD;ub;R5b?yhy{h$;b zJslI+QlFpCGP6vVw2^M>Ly6?Jove2WSdV0!1Lwu$JtWsFf9RnNAXwn7!gTN&px1WR zHZf?Y{;~T&D{<|TXe}e`s3$|J8*KviaFz{qn^4!Wm4$x)jqXcJUtTYzW!F;avGVKt z^Jv?~_u_UN+UJLf>sDQQTjuS6cg#PQ(bHnxn0Ald$i-J``6IdH@m%(0HE*k3K0*Jf z_hRvLj?pu&JozJmdHc3sC)ADr^hsxL%UN{yPrgk()qb#|SNgl!osR945qj9V%&!*Z zUQSC)*|52_p0C1E$@kVyYCkO&iX(E11y!G+FaO@fo z98X&UHPFY&wc@B%L#SggQ1g~oZcxGM8+|&I z#~totW}aUUU}X(=FtE!UGaNm~=6O{#6ptNS6)K9iCh_jjwjwIl|MZOQ1l zscA;K`n<5M=9W*6>6dw08C>@=Otmhj%cW z(T@xO9Q_V`WBW8dr*%?0)<57`BOkZI}F;2l@kKD z3%$kozHu@($m2kV1|42~2pz`kOt|^4tV>O7optW3UIji|HK^;o%vaO3Qd_?E`nuJ9 z{CcE!lou8)J@;!i^!6_4M$fwbGewxQklL0}GLGyk%a_wyDP!Qy${)cy{89e8#HFB| zx8jOV6LE34p9Uiz?*HTLHo+8IXWeW1eggk~y=RLn%M*b_U_S!#GklJnzsvn{DcSA9 zCH{ZzlW7BJ8#p{3Fpv7?m~Ut&(*AbAyA9Y4r1osNjkoTjoHGD$lsoaJc4%OI`hmdn zM|60nhxY=Bz5xgw`0}6_3J(BN!LLpDI%koA8dizf3Y2{H8GM8jTe(*>ABCoXZ(kF*%G@VpwQY{{6@HzgpOUT=F z!=}CtA#yf)9~??WecBSP70iLg0}9SdTmD*EYxZupDN*l{Wyi{E@B5r}Enah6rYdzt zdQGOvg4UAaJf7rJz9#qdBjjWN;1Q^%%-skuh{l2b{+m|kRkn&@9z6^4IT^pFh_)_?)A&^4Daol`;5RI@bB%TH<}|WdE#r z+qlna1?iH#pQO7IZCfR~_y`!U(dgA5y_Zi(tkUgLauabmz*pd3HqX3faFgO>P6QHx z3j+9@UaRAkUj+h~8!%SjZ?2EO7o2LF)h24b^6EQ*GXQX}XCvj@jDR{=9Nw=5XvOdJ za==NpR^H_BYlH0T%_s*YevinL56a5&>$N0jBG4n?PKA&iJI`$iPqCLHB>Fup^ zYPqUQO%Yf9M8fqQ>4#6hB0z`x^SnyPjvNI7G!TH_G8h!Z(d&vbrCj$mzrSYkt~LPu z1OaFxXqRNS^{(k0mxcYk*6*Bi+k(j$%fL(JYtQ0ZndBg2Sr7bkGQz4zX)qbrk=mAN z+S0Z%?Q)&BY{QJm$@FBJj!x_}Qlpbf#R#KzmfP))%;b%3?w{_cK8V*u^+W7mPoY1e`eDX)BF0N|DH-kaDihts=2 zR9XJ5_W}t7Xh48-`%gOtbS-BsomXi)HV&O1^?8#==_RY_XV=E-`ENTjm+m?D9T~oa zzDplE6efG3C}>-odinCn;B95O1esAbk|P`OT_y*oxcr4x!9fNF8UWNm2n`sl#piOe zqO>LiWoM5K(Y}~-be7%aWMo9OmeI4Ujk z*5u9AbG{BEUG04r&6dpY%c#pE2d|HlEsVAGmb%!t@pY#)4zQp27dljP@f$Dq_t>jd zJ@ABPguNu>|3n}WI35BD*0Erx{=Zxp)Z9Sr0+!P@Fea!E2O8BDs2xynLCwMUZWl5D zP(KZM^#Tasm~`-*d0((Ub@1x7t?$zzO!FwKa^kL7uO*699*KE~gUZ*9^>2{sWHG7_Yu4m=-baS}$ ze7EL+8@jbKpqFMpS4rHLCA`0?9=+w6lL#aN*CU`dPyXzk0wHa0yFfp()MkX#S59RB z;Fa&*8{59-n2!Ey04|W$=-(K|ton;15dBkhRHI4mE!7+Z1Cj0o}7p6V>|0f zbkuo)`a~|8R&EURx9smF@86d1cBq$iznmJ28mIedX(hF|w&nM{j(fIG>Rub?^wfCI zSTt*g==RH(4I>|&v2LDb4xf2>w^5G$+cLqj^@U^EZ%gx>2qXgcLtwofbX#1u4e#A9 zWB}lP&t6J82m&#Pvcn(5urwnPcme|P{7YF(y6>la+|iaDYv?NVhi$!YmUO|rmKy6@ z<8WEn;hg?l+p~9|;DAA2&tB7fPHj`o_l$r88n>|9DzB}cy}BO9$JkTaJ+f_-7d$gI zt<$W_4^7vn*7aX6_Zghy_URd#Q%53@2pkmwwP}xUJC9ob)~*Zyw20(&B9I6q0xyq1 z+sR!&S-usD(L`cxBHQb0>tc#=oksdTIX+pIWSY|FPX=e?`K1t;z0a!D+OxA>G5~O2JX2aCkO(9KheALTjCw$?3HZGyx3!J{ zVNTD|L})o!u%r*oW1UMn!q#|AVT4;rH%iB=1#7mAIA`*_t6)q!Q@1hay>lN?ciXsk zCx-cSz8<6N>U6z6?7dEBUE`Un+c2HckTi)vB9I6q0>?ri0|3XmA8Ab@kO(9K4@aP# z+{VQ95voTMnehaDqabbMXS#u_5>o9WFTwK{@DrFG6vU9{=z=jJkF9iYg_QWa_U+fx9fZ#9M_(;Z5x8( zUUEX>Oe!b)GbklZB9I6q0`G)C1_0jaZf9K+fkYq?m_Q&VWHEtSUYVW{I7zZRL0X=K zTXZ?89@%fY@?7$i`E?o$w)F?kHf`7!T$$QJAfCl7%GuTQYwp7w&mLR1Yco%gll^(D zk}?rU1QLPwMIZwJ?|bjF=7~TekO+Jm1lA^Ia})hFD6W~%Z3hC@G-g?e0Qg^X4@#5# z{Bmo0W}H`$8Yn8kLF)nv+CBQ2ppNZjzU1$He{w!F>Dw|%GVGAs{lo|2wjF|v zGY<5!9?kl`COXhIe;ZZ8Beei zIH)@h_;Td<{wn%ZBfRJ2pA?pD^Pa2Ep8N{zYmif!8hIE*5>g;>3@WHIM7PclkbQi$ z(Kh01>5ap4x463~Z2u(xaorMMs1>h)79_~d*YSn8&q9I8yODABuPR2S=y}f{D@+jn z^Y~8p78P(vxIBmhIVa9z*&Jxt99GyMs&L=}kC4o>vf4&P%bow3E(E7S-O32cAB=fU zvp|UkXx)bzmb508h^dWD&+pHUHaT|Q;GU9dB{Wop8sB#wn16qBROD)?*%%ZsUS%0n zrGPz2sE4Ik(#pA})e%N$R%87>E?CL#;Mf*$i z3oQCR?E0>!>ko4nJhs59mH`v%0h18V8Q6{AqsR20|3Pul(LIqy(}2f~GI+ZBxvX%NU(jYKtkd~A#87Ux$#OUrE-GV3~qepj%l(Zw28jW;^bR#VwaKHTC z+_(1+xO+3Uv1iYz&-tA5oG0>)x+1}2>c=1uh(K9MUJC@m1pdSX;i3aie}Y>kKxiP4 zvb?OePv-uucP7i$yOk$7u=WkaLTEb5j7`c(S#5aL7|ND-lYg_RDe*7CB z^#3pZZ#u}k3B*thO&hNwu8#FyrQ*{Xb$8#;d$|z0smGLQD|#I|ulyV8HGrD6(q7aU0j8Nxk53Vc^S%IF2eSHT?@6VBz{I%Qmr4z`Q@pzWW zn?z>igu;UBiV9!zo?0Mka%JbKh)Un8yiaVBHK)f95rG#xC#fYt zJe4E4SENO$uooq5`9dAo%n0S{rW7>EP;O0XJgRl_{?Tix5fUS(5+hhI!O=|ORZ2wcxZF+Pqie4zeR=Z^YQ)G^~H?zUpjBr%YZ6KMI81=d;ZCL`~bSoAgc zIMo?%Zq=U!)N8!sn|*ZST;)+%s4f_p!`qg~W28K=snFv_i}_wa>Sn-?22{#O4k0F! zcv|{gX)JXD-kY659c^dj3cbQa4W!Ys6PmJ_(coxySPpUU=#^%!b0p@{L+v!d9?*7q zKS-TnQXhk*)9^y9yj%@q%Js?HpQ_QjV{>Nn=mst}|m}AU6*0uT`iADVM zkH{rwIVDG6`5PcmwJ3|r)(3GrH`zo_F7lSM5~M1Xg{3SkFC?gX2|J{|!MG~g)XF3U zOZ_aUuclYU7&T=*$TjJ?*uTGi{sMmyA$k&#Q*K;E*)1c_X>g11Ebuye*L$6eAf)s* zDGh(z`O7JdCT&840-}k^A|Vc3)+k%n`Z>UDYljHt@NuKvDpbEvivL58JGC|qJ4@a- z)+ehVKT6h0Pax&C_#A;4@1b2C-u|9wJ>dH`OyIUOAU;`)xTVgtb$gn~1zM`@j`pQ3 zgg4-K^wfa{F9#HrNynIwRkQYNHl`d;O~Mkaad^`<&##yv0;h>lK$Y;$Th8_2An2j9 zOo_}psb#FoVyEs*Ow_)kS!ho6#=BhOVH!Rif)E30nuw=wTE1-g$`XC|$kl`_JdIH( zuz0N;@HGE=fOBAxv#7tNz!pn(<)T04v!#v4#G~%`oS3$ zhsmew<&OH3z#6tO*zv4EPkCN%!!b1GGM-cZjX^TjxGC3(|qsTukl-{#hGbCJ#;a( z<>Kfj2x)j&e9K#t`!hcVTtBtp-gnu$pbvR#xN)>f^?aV6W3EZ~@E@VE0!PEVz ze^7;;kF%MZZzsv_>g7#AosM4rNVM@|(O{$@MYJ&IYfUocC(y<^0`XO)=hk=S;dsK3 zsVu0SC-SHfh3HtZtKL{xK8a)a$S7@;1R%Z2 zYFBTz4*m)dGNHogFJJ|u&!jcUxbHL!<`u75r?EoH7dzF!RP|79f~)~@ATE%G zUQ5x$3c>@K253!NA(3z%%lY3M@T7fyi8cc0q4prrM>LQP*wbA)f%=f5E>Gd2-!MOA z-`t_epf3$FIS|fA6Y~+bkhDUR#gmbX&xCru!p=%cW_O00$Mz(g3N&kst6w)|MrG|3 zQunV_n?tnJ0B7nKC{D@Txpu!H->f;(f3DAl7{ZY(I;%52_GL9*mPiT9M)>ZRqp(r@ z_?x#2TrB&wQtYF42u&V5Lmh=JIM~cGroVNj;(ZgBkR4mj0{_hMzn#r=VeZ~+L>h~L zxWO5taLD%soqIg7YxD*-3kre(PdtwP?9^5qH+yZ4Y6DF-~ADF+mZKp`*u+nTn*8TC-L zmUGqV-|I?`Xd;CX{#9KXwYp@a<5rGOc)>Zj65Hn!@0mTa6Z7HS>G1fxHS5`G9PI>V z;A_GI8^#c>PvPO==81^2DCBqFQ7$)p;*&1e-p4}z$}Pzxm7;R?4Chs6SsG>e$zeoD zi4%TQ8A7{6X#$L>Duie<@0lHz4DS0H^UTq!$H22fXj<@eq|+xfM_d!{ve)`rz#7kSd{Ku(e?ZwcN(q6p@cMtdML`dYX?m= zfOx+3O3Z6>*a)gKSadH2N0UAKmT$}LR!jEs<9EjO=t;rmm5VR$%>(SL*gWvL5{h%k zli}G|AX`D|0U>nC9qNf=N0OudEQTn?6o28*>j~OuGQ#CWw$Oa-zED<8k7^0s0DuxENaWj~d( zfG_T5|Gm|{i-^+S3)w4LOaC@uUM;h$85)okL1EV&pDnQ0O-jyZpiM88l6>n0XBqRy z0L^pfyGzZPixnjOqwp@Du;G=og;}{q=#^^sZ@4!m#li*rnj%x?c|YOm$GTUac!*p* zTFy}Y-P_hiJybdq2Jw@s+;@bd$z$@~M4izMI3e654w$W-db&GZah)zjXV*f#W0?U364F+U+MLZ1&q=p<@nL`#c|QuB%Vl@{*FTu`~C zc}j%+rRPYF!td$3?LC#y-)l-k1K&E2jq*A8s%Ve1+c}`p3NaryhezW)KH|TgKNEy;BS)uM-6_`TNL@~=ZS}Gh*{yxAHSW_`^D^f zCAkp+8eK18R4&6~EuI?_hb+7sB`tqhcTHLKiTaUW!gf3Z|jIJy2Qe#O(hf2OsM{X{Tb_~LCr1Dagt6Jb$ zB!vykB_SJH5S^V2SZ3T34G5y^;LN^*_{@Ne9iW!%Jvcl9Qx3sblf}nG2R}wEKLlz>n_+Ug__vOmdv&AeMBMV$%D5)kx=zzIXW%AxeiZ~0IMd~DkWlnsV=FpBrDe) z4_a0HW%H12>kSN_ozYXD`wLYYkM$C)dAX-wSZLNJ+J(3H+`M_n!te9E@-+Mz4X9hj ztXi&RZEcWzvLeKgq4>?j5iB}=;hVt(c1|XnjCQq^q=<5*5{nvt#Cmf6PU_9-hu*e~ zeph<~u~BNT8fdzsI`TtLzGB$C=Wot7+pj(3VW4iUmHnU{Eg`@KLL0a+WN<@e&NzGv zFgv5y*vH6FR@}DTm;!9jPPn$Nb&f?N7Iz6NdB%szl`(Ku3s}Iv*5I3fIIuYl>JjpA zvKUbjDS6OhW77s>cq(#H^J2izSDd&=)U}Kk;a-l>o$os8ujBgl1%BXi3i%s~^n5rA z+8bM(jg;++=S#7q6=rN~p7})^aP}!;a`Dbe{E<`lN)c=I1m;Fk&Z3%V`{Am6Dw(LC zTjVweH*Ej~Y%=y7{1u0#wonF^v;wpH>1Cq5*!S=l-4y<*tzGkpdu$xG(`%g`ZAJmJ zf;p7G9h-t1Q-dJfYWb?O7GnK68mq~m6<=e%t&;E78&mp?CWKg`eLD@4SwvE8WQA1x zU#ItGS(J+lctn~#T7k~qUmANd)9e&{yYky=gj7v9HaRi%L%hrh@{u|r@A zOD1(ucRi=)TIC5gEyOPeJ?XZADq{bOQx*N$?D1H)P@M&V$tXx~qX_Jv5u|HS^n)y% zXg({JWhHgYttMP0q= z5J5=(E5=|P&Y_L%Uai8ezNufDhQ2kGrN+c4H$Dftd5gDx{@kdQaksqZekEd+cCAhC z^NnYYqmUmKvke!kz33~iEIK+s&1Cw&5bhY@<@s6zkF&7u*1BJP?G1i=g8p9@I9II< z*8lNf*&b}SqQ%9qcrNh5T$BT$W$k__!T#>c0cR-*RBkol(wXxjHZ!~~Ng(sh9QYM# z^~TEWe7nMKZWJN%n>=fUKq}h6O)}5miKn4@H2M~ph7Zx4OCGCF08T-X8jo_@I>^To zgyb1;Wtxi8!Xev7=?(msUB4{OehDO|%BT z41;rMRI90d?9^^y){(VDA47}eIdqlXinaVIiehPpgZ9?#yY!+a&UN^s*=fO~L59ey z7d6GcgbUdn`V!o{NX<$5?|*1pSuQbQs-L)ck)M`2H;Q~XH18>RDLl0r70zZrB4%M( zaH+`b*M6i=Ifl`m^S~gH-tagy8*ojg)!Tg$eV`I6q5(OVQa_D4@IcIT=6)*RguQYd z>-cKug4pK+H@c!^G#65*R(%=FsXm%xxHh901^lxqF@KV%&1Tx3|6>L34X%pYq2&6F z>s5~Q)N~gX#OIjH+M5cLcnLz_H&)KuuTYGO#%g|?ht1u>)ZNczpKvaK9Tc7EpwXhu zgZno@rP?PF8f4-lr~Ml>dRVHy{$8H1+XNDl}!~cm1Q5vtCYGU_ix(dF&@eUgh~+$;+_I!dUf?;;mE7=P zfEKw%#Zhkk=>M^^Z-zA3{oW(yCl||xMk#<-%k(U_g51hKk->K*X~L6_*JFVe|eh;>NT{l=5ZC}{yLRc@yQ~KUF>fR-zUj4P8k=%Lt-E-ot|*gPx4;SQUZh0-{=$!BNqz?>GRO|I>F9Ya4v{9+$5Ma7 zl!d>QsnE@felxbl5DyOu50A(mw-&$PDaL0phDxRaI$suL;gE`)b*$ufYgqfLcV@e;Kr9~HL!@c=3*rBfS-A!;Jz(BVz^GCjV=h0r z-wOq5v)Jz4kr?9?zDZ)yOA5pjh@N&7>L(FU)YK+x&zDOD8xlxnm2LNq-i*L5+=`*2 ztE=G=ZnV5s!e%cmQQ;lV+(_D4CK&7+%fI!yx}R)Y(d6^)JLpXBS&0+4rsfn1MoH0n zsX^e41-{Rg11#d3+3ZE`4ocLRddHz3Bh2O2De4yLE#D7;i|f7c=2jAGH!R;nn?|4W zPq`h~3ulyR$f-g&1G~9xnLyqg1iT-KU=9&nyx_^pqH#?Wr!nU=`A2brCthb!OTpRE zo)tj(+SZz3@j9qZg^%dc zK)8D7DS}C6bdUXs*v(@`zw8u$CPoF#I&&oO^W8&QJW2k1l-};pxoX>AsajLgxZD=yivYZrB$hgh)v72_s z;Wn-)N)Q=om6cWL^xi-{n*7bk=1OsucOv%|H;n?bFV|kQP!AcTY~G(z+5bQfw|>E& z)46BZg^zkY^h37|x2oE)Tl8BCtiBjGTFRHId?B^Z2#(QghKAu+O7QnZdee2~Up5)p zpANXg$&_`c%M}X@QY=xf@v5CXy9>X%Rq>1v#iZu1f&K*Y7o&!XPE^Ws?6Itb28HrI z+K>g~=TD47Kv20C~h70caBR51KfKv9V2|Hg`PilI1@yt zPzEaTWPRPI3$&f8!#_<1n`FD310R|OWE-`l(S?!7A?sS>DsKsT{LY1Fh)Y_uH~}%_ z-Ro;Ju3P-YY)_ZP`%uz~c!n+3-YeqVMWU*LO)y0B>rjrXngg8)XEs}_{6%;E+mVAp zhyHXbkp8rPqsI(Au2_0%{`mBsXMC9XU_8>QRyaegGeKgF!i=$P!AKfxDp>vn;sSP|Iernh8d|dGpzRbIihc0cgegkEmD0p2m(7tB!CjC~S^k%IO9T!1;=D#hvB}98V$$axKi~T}0F_CEdck;C zy00D;VaHTTR-{e!5e(sjCq9(!@mf(W6ezb=V;4c{Zir@GRX(NO)TH5pomG3W1^d}u zY=+L)BH^M4U3C_@F0InKZ{Ok)Lp*q2ComuM`25pAj(%ZNE|V%P_!n-Ln#g@jv1M6i zLDs?dtye0E;CZAixxhE^w&}}TIQy%`jx1H?gQr3sQ;3OfmTc%9oF0dW3ooP2mB5^_elwGn> z;+SeXaCD25v^1}9$m>c|Yk7Xwcq(?wv8cIeF|VP818{ryvyw>x0g%B!gef`b$ zm8N8o45NSYJ|u-oYNnSaV3d#Hol}w4&W9sN*9&~ukU)ge{txoyg#F~%8@Id@Vy3|2 z()B{)xy-%(%fMMPaUNSRrvzGV0WZ_dl2)nq#J-hsUwT&CQ9+rwiRx4ri0B;ZkVSyr z}bb&AlasVOVPU^;V82=_~^aH$Rt_!n)k(t1l`g#)Fq{a{{MU=?!iRS!H|1Hpbkle+djB@25Wr4OX25N~gS=vK5RHT7)`OqakKSik>>1a* z89J2$Pe4SPNJDtO(!v+55>Aewxr`!h4&|YcBR~tu0~%h-q$YB)9z&s!`&2A)tzB5_b>~6clu{)Ovb)8lzCFW00DW z;quU^h57mUd3hBZyL7qHLgMkaBi6nOD?7@6m)*eRNpKxAi z430u&IY{jg6F$BIyE9S85HEa@=4rmm-!2wQ9;}&nYfG<&S+J) z4XC(SRHI(4^DOnd!gB7tYKoNLsVd$`J~!Iwy?Vb^K0ZFTe)f{ju@8@!SPjQH!Fs3p zhSJhfz>O<($|miLv}Wt<#=E+@9v`xCS}(R8K0>x4*QQlbQ2+Jb-%N^dU_)0|SAMN+ z-`R$%!XD?zGr#Mdz#giR(@=WLhM7a$Y$$H3-I4f2j)=UYAhjqs zB0|hsrF>CRUNgzz3?8xJJ}Ww)Kr-4wNkLJ=%MYXa*d2sjn%;)4Sn)gvXwPP*m{(Lx z+KblKT5xvcGKVehj%Ytg#C4Mu)(MC`#Z;OETmE?HU?PYPp{KUcRM<#>!K=g0bGd-puG z$@JY!GiY#}ZSovgU!MR}(ADKb^udhkgW2~8AIsYXRl`J_pV8HZldi}9&cX%OwZxFo zj*gDe0>zS&l2}?%zdtMQZ*MN||9rX}9vM;9l&_u5%*mllG>DUSY?{U|=x72GLA18_ zJg2|9;sMqR z+W#dQx0r2r4OwSFNqc^QbcA@rmk3^Gj-;HJIG<{ZCWcHd}06&26;Rb}j5jCnQU6m=_yQGGoM<;X-EaFcV@f-M=j8z_#k z$k|0Xxvrcb1WW93#eU(rpX5s|@Z7m(>s19UoB0p{XgmLlY_p%;@h5Kdq`Qo^B`0>W zp9u-8`F+(>m1L;vw`az^2=>HHpx`F1FjUEaB@=-4A#Anp`9K^Hz%7YQ?*9J$3rG}j zh}=?FQ^S&dQ=tPRNp51RVL{uw-*bGf_3o9|hkQIcGqb!=+X?&nR{zT-uX!gRD$6JB zYin!$FQwj9O^+=pt}6An1rmKm+t;qcPHU}c3?guF8qH$Z+hRNvMMcE3u6i%bMKR&R zj=~#ub7~oy!6SnJB`vsI?0-V*fbydPg{}`%n53AImc{;!AW{v5x(P?w-d9QvJntA& zXJ+e3h|5y<*BgRql)a5oDCdeV%Vb{B6L%kB*{UHKsDOeq($ic1bl|B=dMY9fmyoA* zwZmd%7LTB^Yu>S~BZcqHZ5t^Ld}eBIasvP4eX`!NE{RoN_Fe`IDEY2zGGoZr*;!}o zkZ&9z=zrpQEd(!_byUz4m@grpQ;jKndud;_KQnEW6&(wBoZ$H07x5zHe`N~_EZ$1g z!5cvwbN5=CS0aAB*H1yeikNlF6-tRr-dD1|Y>(K@Q4q+wkZy7<80AV&Svd4)sF}(v zwdEemQK4m4C!iIqfq$vHVvRou)UfyRK3otL)>*8!K(VA4@{5W-{rG!gLi+;0G#0sL z2gXo6v=|-~Ei*NHc;wAGO5L7~doSOHVc=v-`kigJ1!{~84g$%8ty%~%=OKQO9vY!J z;V9U2n4AD@U7%6Ts;|+d2wVU4?DKZOJq-~b9*hOazN4P5GCHQg>CXAJz0QaI+A8y6 znR03p6z3OWxaT2jDF?k)8arTgN6ar4v48S8k7|#eniI8siQe5|C_5P9SQbYbh4`nm zo9VvxsJ6t@VM-=ms#$x-=HoZA*Pk_BJEa2;v8{cW*P(=yz5O_QNoEaf%dT6XcR0nm zs`8R|MNgn6FC*WJ1~PiM*!+Z6L_|Q~bmi3(spG$-im|k5X<0^kU-TVtAMNPjXzB4< z&?}QDi*VVi&bIR3da8fdRdI{Px8MGri!|NDR&)&6r|sm*v};O6nDb;)V;*Gl@RwB< zychuJ%hsM4qN9l#K)nbOUoL1`DRW;w>%DcE^2&GiWML!gnt-s5-5x(pe zkx|lW0w0TD+LcMPa1BCb@i(5N+-at&h7BLNut-!FT6|C8;F9cslfGuJ1F@TZ zScCICv_iY5r^nr<*E%)?_QwU^9V;4{)1%BUE+8N&*=jSAsIl*BelKuyDOK+cJlR-V zTk6MQF?%=E=UU`h9_H8NMxHQxCkwe)Vj1)sKLYU=_61_n4swP46T4GlW?odNRiU;N z6qLmup19!2e#5BFvs`Xc-iQWr;;ha1@TfG?v!!wW@zO!77IZ}}jV7vl?KAu0MUcp- z7mv%nFmM4*%hh|m^x zH&94m2GC1G>S~=Sc3;Y8d!?Y+Tl!*#bbMT~`@Ls}si#I9U*DpFB@fToj`5=`;kWv~ z3avtEOjmmoHX~&z``$w+$KdQqvpFhu@A2|3Q>3Us6?jbjgH_DR6vRnZ40371nXg{P zdA>@B;Xi*Tue{%rb#kug2NQ1S3*Z?3HxQ-nQ~EZ>9;1+wtOl54Ikc2^50w)rre5Jzp6yH` zBqe>7ifGt&7)nih4uus{nc)F)`I!CY_J!QF-M`>HGLvJOmnh|z+H z8wYlWLOkxzC3v$4H@(K%#x*cIA#6owBF-u! zub$yn&QPkJLqYrqsQeb2FY`VgRN{*Dj#KLNv7aZ-P_H$GslhiRNU!-O9-p#5MVo)#Lh5 zuLRClCYR!idWFHiC+52jJ~D6R1TQ^g9YA+E!FN~l4NgOCWd{Zj`K=xAv-g4nqHIB$ z6D{|5ICOz$ql(Xb*Bj=Y6YaWySq3N9l%W9=f|~Rq2k7yKolr!jwcRv*qplbNuR-yC zGpP=aQxbNe_0wRh*^?_AjUV(OvqYYm%f_}id`myLqO)2Aa^%h-$_SZNmT@qe*$Nq? z({D;({T1eK*LbO@ePXhcd>A2Tpox7OBASpLrHfj{#bGao~ULzkIWV z@kHXA%W_*uP7w8+)1eL>MQ^KQjH}!xMnZ=3CWRnsx9_Vl0IY$;^A_hn4hqADemn(% z`gjzHy(W$KWay$ZqCLvf{*-P0-Vs1(@dCW*7zm)1MBIriO_2<}Yyji*oV7}6TW67WpR*Gmi(2v!X)y?(rAf==i(~HF z-`}rjT)IB53JyG4D!JI7#Q>3!t+|T$ML%o`^;JY_gbk5q2UuZqQr9G~4~S{c z$>a#`+aA#yFq{!Ajw^Y4)^-%I)vO^=y>&6~l981K)HD&PI{4zMfY!@NY(OHkaB@af z#W_+xcXxLb91OVjD4y}3jt8BdZVtKYp|q4fb;iF+2n5m7P|P&CEVo`R-DCla{{BQa z+aBD`r%=3Hx4g=Q_NlX)Bol4LRRkehSxHG;Qe52NvK({_1dG>f5wJZ^BFr5$*Os^A zzg@YA`w9jwNCE-mYrDTaT8520IcmRe1Ij5Xi`ve|Su78$g#RaGWM3Um_3CkzPMJ+k z;054uSO2!8gQqKv3>u$hOmKGIEOe~8mM54`8MYb+pY*XEwVV#)&;@MY-5iN~Y=7fJ z^qv#Ci_i{qJ_P|2!F*cx`Jbt|lT{voS#&Ei@M=SM!L{=|F_9Ehf#Ke&2H5&ZUtrg& zNZbA04PDUR-{ObgPv7G_OU=$k}rV?dd7(p(r%8kL&!chxwlk z)_R-%Rn!A$BEFSbTh(^GtIC7)n6AvSi)w#P;e75YaxGWgaJTX^?1|Lh6{p68tfbpm&LlA0~hS>>KUBg(&QF>5l0iQsI`=CGsU89H28%VPPJWNbB-%s^?Lin1o=l z02H_}c#USc<#Ne??_5m4p~6Z*G1z4ih(y8%;e^FX2c+Q^pqU!0ft`|^J3!}0U&|`z z>K#&O*Py;)v>58cBGLeHBh`?&i*Z@-03>@R;%XWcB!&Nq(Y+uXOo$@_1oljCugx-) zbEtbn;&d>Yr)iso*Y_Au1Lem&TBb*+z*aRto%l5fkbv~*pumHMF5A3M!QKme($Yu1 z*;@Trn6z*LIN%9z0>!USnImP_>2Zg}k6LtFR>^gZJSY3ua=1|6E2RigZxU~C6*WBu zxEmK>Ba$zd0|tPEy67kzxa>`iPKf&04LAS_TQ2>R5<;5TX}Rrox2)O;JdHiMvjQxNReyy(F&!>Lw4g44K@q0zO#oGt{j!0fg{P}?~ zCOYw;k(iJNjl_pXeCE?63peut5KiL$YNYvWOqI9ouX%;ggRN&~lw@SuveVL#0Qv@> zW-PaCAPgudC_wc1uSyxW_awz=;q@I4(tL@(xUdsU2Z8{|3fG(_R|Nq2b|Sb9)M8sGc64 z*0ZscwzDE&9iw_E*7U&gZ&we76v{g9qb1&;@PD1a`|3hleY1KJnJ%s$aM5qQ2@O0D7pFFO8DF zb@K5)_#2gTL@!i5AvLYhY2K@oV7h&kyh`M9;WS_w<3SR*RRSKl6yRx%%Rx7~Z71(a zNf0||l@h=gy&g7z&&fX^5XCrh>UFqqwMyCk7btoq@Bf`{l*~Ss29k>&kN)M)fB*gg zK6a8^6|iyG9Q;E1<$>GM`?Q0y?N2vvkegW7^yFVS zeZWGn`?BfHJcLek^KO2F~tIKGSIm-gHA?wr1=ELjh;M=hW7+UYuEG5CV!4{!?^#HQ)-}G5qLc+pcKd~rV z)`18;gt?@qr=zEAOLJLH+@SlQqeL+bIuU7UF&ka(=C8>ztQ|AlNZ4q*8`4rms@*ye zv;0&5f>_MzH6TbkL77wy3&+rPVnzl=dx8&zM3HYeLGs~Wl1}PRBp%nD2>E3{mIPma zA!iS#j>jd6C(=munR=%tF-rGy)TQQKhbGyg|52dH-ARf|>p3C}=Lu8j8NR1=NGBiJ zecD*#$P^&0T0@B7>@y4NwWLxD6XI>@t zlAeBw9J$Xn=Y|70cGG%ULU1TE145cMS~6s16&pj*Yqol734kV(`|IiU%hn^Xh$|6D zVg$z0L5Nye1Fm6MxW@A@1HFBYWWZQW56-V^=mu#hZNK?L_}Fe34+BK+>BHk#u7*$J zusgK*8`(38+&q($Xf~zRZ21*oLz$2ClQ4+ga%gxufAKRe6`{Bc?dzd{t?DJ?Fuvi` zzLWr>~_WfB14#s837un9E}%Qv3eU$+GV{HGO&P@kW8*(N+G zKTGd!H&PvftM>!cUrXr5ZrLBpbxx!Yy%LD&JRRy37>!33K4Sx#&6N}*(@sq4>6!!c zOJgGj&Mpd!qx-}LyOQR`a7sRdQ-kuOq3r|qRO8%J7uF+oTc=dX&A+Dtf7=vQl%bjf zZcn)VL(*nn2w>FevEWlU?lG$nhf5_(JeD+i?6I;_t@7P!a9M)b`Pn5KXVdF&?F zs_SDK=kI0#0r;7_%e+3CF*&oWtm*o;w5fKqnWc1@ktJJeX%ANPuw=+KdZCFv1?~KS zk05?TWS$6mVXp!{Ma>D{tBM(ibmP4Iy6VRCb3 zuN(pokt0{fboa-=jjJo3>0qP2=^ctXt4-U=XCqVjowetH$!-<*Mrccqq^WrYUo-K? z^iEj3z$Ry4NMK}CkjY0}X5kViJXbI8z6gh2b69Y?eJSeTuM_aEdHLSyCS;|{&)MLS zqS(b|H$KRD<0j1N2Px7C=_K&HsJ;Z!sWF6OZJHDTQdQ9uXJxpMX_iALrb2sK`qUX?lBI8Ffti_N9~S&g!a&xn(ZKr}#1l^7M`RIW0(!U4-f02Wib?HjZu;{Dy`8Mt8a|LQJ}h|89?h?@jJD zOxiA6Gk~)PiIKM|NLv7KaUTG8TR-sby)m{$U){!gZIB+V%p=RZ3MG$0})Bp`+FQ;Aqg6i?0|Yb3&;aiwJ>Rd6X_fNB3y-rQOSdjL_SNo-)cuHy>|bLyrqOrQ@` z@+r?FW~{{mIUwJCbL6J6Ai+cQO|O$;XG;s|%vRTXoM?Y{%6H$LI$_W7U}4svyX4gK z>c((TNheEUJ~r}R3|x!JX+EDa*xKCed_e@OUVgdl>S+6r=g)ACui2DIAfrGAHazS z93mUSO&y$HbP%Xn25b@Ulgh{~Y3kimto1$rNO3lw1vUkl7T*o#%`J5v z8^(|hL}G!oq9i7Ftscd3EX*9LEvsy~aPDJPtbLixBgMsq8V5>v;hWZuTADJx9uI(9 zU6oLT;DYD|Zlx=+=?gA-`N||EZQ0#D%eB4POR!B%F~1E)_2T{0!AAql^8|ptRm{lk z-DsD%guni7{bn4cqyxA`Oo9CY`_a=I@f- zo7gT`jAffOlWMvWJ3V7K^O_^ejy##40=>+~2@T%v-m-&BgTZZ16$3ffe;qi1FpV zOc_w;!RpGH;=xSFYcWJuu=Riw-uwA@ti(vt7hz_2ad!h#FLLV5fz*G9BRvHHM`1)eqM+T}T z;6<0~Nq67fT)i&xN;aR(w|_e_Jt%!O`df4bVXhJNri5J*_t#-rSj34?em}>plGDaB zVj299h9kP_BGWxB3AS^&`NaB8xwBl6~gctFhJHXY>RS3&^{}3 zl^mlv=`O0&J~AZc7S4%jSOz9`PV75yzJ!4 z825HWeEzHe<;J8&;BMm0r8LdQJP(<}ql1l$q1B!yKpRxV*l(0!!0i0EI>g$cyT1Fx z^8zHx&JvVz#(mqgMSw>P(M)3Q0~!{m>C-LOKzU$A^>Ib}elkw%Mj%*b{xjtT7&_zc z<9ykc_9^G9G;C&qbUxxu{E3iV;9xv&sVuiu>p8F4HH@BK=1m2k;d53rG<0-66;STv z;@dVE8RxxQrqV*L}TA>$LgM^&=ZDjMyrztYSl#|faWu^ z75}x3$XbmwkzgCEt*KqR`B3gP)UsssPUBqr;z#*sB*f@H-fA4&ehU7J0_X?ckhL~P zy-v4hbK-usZG}+JixN4H{nUN+^vW4$Hcu`&4yc@F-CVeZ5->9QBgL8#Kf!l6r$=yus?Y4u-%^c85MhmGI4itnJjj8YU zau^ps6N()iI+~RZTuy|=N{{M(e*QyJ1cum z%2=+j0nN4ii>_8c?jk5+ei93}VpF1`ib}6Pa5R-UDj$(@ulF_}q=n_z9rt`=BX;ml zAvT~nvi?~;=SB$5eu=uzwmXrE;`iFe`E_xpS~9AG_eNoWg6jnaGwW~1EKse}-ZkR= zZ2HAxyN&RRd^>?;6h#Q}8$UdjM>N82j%)I|9Vf~eD&h^Vv)V0ITe5yDzx`RfHueG9 z^W&RTbz6K4cEFbS^3|Y?6zt}}8x*qT`|ZL$&M~y+6RWa$ELMz|$xEZk`l%i3T`w&~ zVtKMg#{}jcD&h)AzJWfTfE9SX|0$^RL%EQ0LYG^n$|MP$$<#J8P#Xg!OKgx@ytGTf zC>0G&@Y1RC-<_Ph9pKOs51<6-P`_ZEpR1drS4h;w$Wf5rW?o=za}L~QYgW(nj|v)= zlq{zkUC5(IH1dWs9~Mz5kkS{bh$Jdd{$&X^2)Jk#=W}A<+4@W6G;~vVNOJ$qW4rqTv#L9d+x7jiF#&jfk!_pxlee; zvq@AlYoWDFfoA(ou}k2;wfjHY1+h^D_6LtKf8sb669hNaWwzH~FAlnR`%{Og!gcZzhIeDx&o6{&`f_Mtgb*;&ECk+Mb1j^Yir` zdCkJ4rqw9UrN2EdADVOkVMu|L;O7)hl^=);UUuE>_~)ehI|iTrcr9VTRPk;lUZ;?p zIL`_skJvFxKx+KRjUb8xkryvY66cbmk$75AdHkzk5{pa*EHS z-E*WmGST)`>4$vsioXZoeYC^BEFre;Qz5ojGI7Ebat%6S1o{K`%$YRP^w8fy_8shxfU_u+KIv%ckKCBWgdT-tdtm)UkZsCi+7t%6SoUkzeY|gopU?*S5{!YVZ%#!R zvSr`<PSv>$Vt#pNg+d(HYGjFA)$NS?C;{coRub?{hWJq z*n9~n>R)5~?ZM8@&NFrVh&84$8rpr|+rDFc1{(ne13x}rOw~ddKuZT3#9ny^;4WoM?F_7*N5+dE*-J!q` zgwY`&B?!_Xok~heBV+7$eBb|I=j=K6bH{ak?nmUq2}_%nAAE6%IT1jUz1m}0;yvn1 zI%`^=d0oI7Oh@|408~E@sUYks6J9;&=G#~rn7yXU54hZ4in$(NMcbl&0_C;}m=1TF zb4H!G(JpFL)pf#=Q8?{2;gQ14IUvpB| zxX=QMkA#uIKmF)0mc`!w+FGISJ)6dIqsvHURFwq5TfPoG1|_;?Ju}S{85@KOkPunc zyTDiF#&G+y;nan>Nup}j1r1JMGTa9PIB=-6atdX9b~(59PX2td+MN*Ur=xwXIu5e$ z2KtvW*9|GaxIlUyx^ZJv22%T~LpwAz9LHW@lkL*r-Wu3sy2|)=Dcb6{_a_3Sbk=XI zlbMB%amBcK9bUwr+^C`c(TsRflZPI1V^kn4d}emF89;0oo~1=b>iH?;MAgZSv7;&$ zdZr4_)a}hjDU@mEUyw%sx+p<^DY>gE@t^Q2#^T%Ci)_9}4Ka;b?cIa4%4tC0 zui^eAhvYZbs+{K{I5NbTSQsp!w`WxdlsZalyA{mOwX zNHt^V(&_A=vHhFB#WxEF3oHZX*e3l+upLe`43*lyt7=8|kpF6s&zCEv?@=f+ti^7g3J zO!FtWTss4puLNFITcGaudj7>VXG9i+8xJRTtEW<8*zma|C$Up@{8bK4;bQ*g?#f?iI)Dj zH&$zGwM>Vh%YE`FLT6m&-ayExO;4fwV_-@wv^HSZa8C;io>d(p3j#+W>}7-;ZgMd~ z@s6cRnln<~)R;Qlx$1=U+Y1W~x)~Gesw2DKZEhK=w+_0+(LQ7NeogPn|KXUv%!Lxl zgkhOyX8#Rj3B%xN$~wdnt``&=XTeOL#+qkmcM?m}jk5ZiIiB(Cgj#klb2woV??npy zU20P>oy3fmGccAcx!>mK0UEy(V`H&7&ig6d|AaOMQo^9`V)+Ls4GD*ij6n~cHSzeB zO0q}D?w$cj?N{XNeF+stz?6&(cnE6Hi*_p>13E8#hvsdgb zj#e9ec>yKjfeU3o_n{!hfjBLbS%(wO3K;Jyv0~L*mM_Yb;R8E$w#$5+3Qm)Ccwwet zAP^%fuI^CdUqP>+zrk7*at+N3n`4Ud)UD>7gyDid-+n~}R_N}co3gMF-K8$P5sp`h ztMQ=knpT#hF1?|dWLT8kUbw7Hc#BXm3Z9ik-C_PBsaMhg$n5G#I!RRd%&>mDi+d4%**t}cyh?)0~lMV+|yDH?aS6Q9uf0o9dfI=DZ!WrMxHcu8(WU5ee$9{g*i6_U{fVpWXSYLj#9aM9;<*}B#gq9c} zXr*v44?~7{G%6;n*kK{!Y!G6lLq{0>pzOYSgQpPQe$W#`Z8V#fj(%5W ziT675{kuiw(pdr1#gfrXM8`LxN-_kIxt>im=-NZl5y7ko0aVfjfq9?oh8!A zrC&)oOaZQKxwJaeCPBb>7k$Pcd$u$gOabZ_c>WlR`JW#6)Pj>d`WHzV#Od!Y%AbbBBnYtwAbazGR(u@eiDj-Nu0r2HRrta zObN-KrA~6j(~Yw{A>bsP_cl?DNd42qvpAYJo&26BZznGRm`8%8eV=B|q*2#FmU{?t zrOjmtlW&jX5yQgdBT8o^A#kz=K1ebY1-)_i_Qh4>*3tXfR&gp+u`I<%lJ3^Br(^0@ z>b!H;W)R3G>=Q-=Z&F{umXnh*9PJ$8S|<<1oA)eR!oKMPRJ|VNm)C`j6Ia)Te>Ffh zlGGqxVNe*xlzJ#V$n>?s2l&aTC59!8_3YzoS;oH#p}lwr0nAXl(O7oDR;q%5_Z0_J z99rg{gY(tJ`b%#i6+jTfPG%X$!wlsQ+8;$<>XZP|3Wi9lT;8Y31NKdMKk{<@_Idrw zKkH{o{r9Dxr1WG{i~Ccww8#8Q+%UIj_$hMDzv^Rm;EJ-XvH3@_QiME*VE+lqlJ%M6 zH}!lVAHlP)opWw?;8_mg*dZbAqtq{y$dP=`t4178@d+<5Memes+} z(vpMZonE_ZoIcVmMPq@8Fo}rYaQ8eS7B4&N@8CuaMd*=H{a|wJv`X_3>w+rh_AOsc zAV!w3n4QPQ@GSen?QH8^@^~>#xpA-%k1<-uggl-oUA2utxTcB?ap#vmuWt|NvQbKU zA$O}Mmb{0l=7e?F_iulVg>I=8RRJP0hKEDKkSmx)L0%p~znoa7crrk6m>>nD^aIT~ zn-g_&&L$~~B*K0j@Msom03?F-LIvPQCG0OHJPT0etE2?2m8!))Kcezhemd8VTZ7z<kKl)`(*3 z^9%2^%-JLB>I8&>^Ufs;akzpK_OZw7SUHf~@m;*A+s`HiB0)7xGEvipM~^@tRna#( zGMtFUC~I0MtaTNK-9}PX2km{ z;0?4&B8rwDcs9jUIr8d`mf&l)2@Ze>&SWyiv>hbJNv(J*Or}!JwQB^nn?YKBpKPtEoC8 zNl+f%<)vgdV~P_tHTMwND5^w*2OsR0AdjbNA(xy`nhO=H-80(5(FOS-ITo z8_c!$it@0WXigh%zy85i~L!J@y3<*PBwml$muC?Hui*Wmflqcu4}51M>Z0tjj3}c(LOgwb6lb) z;ZNNVb`2FRJ=NtfO%P~N{ad}Ay(MerpghH*u@jRsftU5tdl4dMEoxj=fXOB-Hm+*) z6^L8zz$`{Tr`Tkz1wn4{^1Sx-(L1<}gO_~7xmZkG@kGCok0X1L7&M<$^le}ZC zY58Z!Vae%?PR0eZo^=AFEI-+s*0!RMb-$nSL0$x-d9VON`p;K={cW;RodFC(HCQ^2 zxhT6>RJopLcFb4`^W86sn@S1oeL=ac4)uuN^5 zP{>CF?QP9Oa97f1u7_Tza(#9fQJTvNsNT}GT6d9p6t~81C0}H09#a?-Yw>wp>EeJ| zy`9SsI|sMU>+mWK?FDip?p0>qr^%(eK$`Hk=Qg3ocQ?-g$a!)echp{vfI<~6vR~Q5 z#P9Hg7o712X>+`ocFpcwC3QZ(3R)*+(+W3|z)&6l%&9J7P1IW>BceqZQz4!$J!?Xz zJN3nmXp?v<7diqGC-J%d!>2;$2`>u9feu;M6~a9Tb!frC%P!V@KnS9;lPa#(+34Bp zeRnGBxllGe?ZQU&SGT8x|gu@$x?CceZIhrM&t^%J^8hhIaKW*`%q;OxEO-_%j-_P;7ilM9a9i zo5=9Zr;jCHj@zHPbf4E8)Mh{;Xf4YMFwQYnyO7g_LBADWtaHPuAEn3sRz z$eLI*^R%x6(XUByo_WMO(Y1Vz5 zzsz4)(Dyuy^T*62*41FS%K#APfAuZ|ruf;sGy>5}i#{oOt=YUl7hY5i0vjCv-2B%1 zN0x(oz`9b#-tpAj^)`h$`k^gC0RV7@0^MZ&e$AtXEisMaUkSRqYicFrJI4*SFsA zEWiHjB~Wu98bO4?;Zp9r*w`?mmx+PLqi6tQ#V6qMBi%b*yuMEmv+&UN>x5BxkJ$kV zu(-f5BVu2FKlONf}%rn|A}}8Y25EG zKce^Z9Im<>>zAbN z!50M)jEnD+(TTOaV@V&AX}e%Izf2jRzTUFN*CQV+o@R)<&C)zpRZG|DjOt;AsH&C| ziGE*Djh)Ir*I3lPb|N^owj47CDdG!@Y{h2S+8h{flgUViSR}#a=Nek*;I*fYp=XShV zI8%&@S)4Mba(e!=VTc|%+H+rR>fS{T%7nB)rQ?&~u#fcfa7s}7hrCTf^KJS@$Ij^^Kqr|bgKJxQez=*Sx%K(saG&{%b?q;r4wox+>AZgnvs?dVZ_teUly zj)ng|{NI2o;O|aO-=O!sgFy%l+eM1B*Y&a5-BJ*vw>A2aso3fX?Z}|ID`;R);j4>XIVFfoWN@%WS!BZ?>&9g z?$wt|9ot+hq)(ZgY9}r)F9ESxluq!uJ|K~HNgn_W**(Mtz&xzTgf1 zV)N$tW5pq%lNO)p$8_WZ4NCeep6&VthC-6P)7&-Q0kDYJZ-eL=!$5?c#(axeRW&3& zwlUo`kt)wz?p))WhZ&#I`gwMV-#E-%T1KYWjU3h8`L=xL85pFxOVdOs<#)RqV;_7Q znP;vW#-N!5gJV$f_<|cmAM3&3dTqNtX*01M$K$M1Gi|cRdq3{Pc>f&l)pbzR3m%^R zN5@8FwcjtIY^tWt#(@eY!ffO5Fqlz)2Exd~#IdcJ`yM?kVA_oPz4X-}lvQz_a&!>0 z^iy`1x`Y#0<#aXZ@==P>q`1?{)t-CT$rs?Z5JrV7kCB|l-$x-@GBPq`Q9opZfG%>- zHVZ=+>Ut%YsX#w1`zgP+9^*IV<7;!h(Z(%#3fXl*T}qqAQAy$*`a;2qy)LTGG*&e} zSuZW(KmpGhe&YU*av;pQ-Hr>(on?ZGoO|FF zO)+wn2K1(%cZ8}gL_}IP=*C9HE!gp-FQ|gvkBxs-O1@I}{w8)=-%-5bh+Bsno`#o| z{?#H=rZ{qD&Ve=FKS!08WB%oFNPDwkE9o+5X4)?3q>A6Tb%2XQ1|jwt6pElwI5tYf zg(BE+Up>7~XHYo<+Ts(Z!S?8dll8zgKMrYhX+x7X zlTv-(;C~dt&9>4L&Xom!ec^?*F!RBoceNw!)ueHot;qm5Vcyjd%x*|aA z_1{8$3-A4H9LZ^z(SPnwsI(O^0E405kmS0@^^!x#Wf=qN7vbsanC?RLDi1(Rf=+ziW}Tn|K;*6=wA^wH$QJ)q@NAi{=q;Cp++5oLmHF_Ww|Vm%1_P1wg{Owx5ca@Z!_RE}9I(jPpuAviCH&E%7$L^kTKB|u zK(QLUWAv~F46|8MEXy3xRC7J8H&bZ^4B~+o5lIdeS%&8D^2~J2p#8lvHBM#)2$216~i4CU=_3aDUMOMT|Kq6C=>7l z72_UYyP5uaC1g9E*QgMoUPUEv#~w)iSp2y8hs>X_8;du6e?!nW41kjY@Q1@bY2o%jt*{TZ3c*&k7|I6YeGW^ss>aw7Z>S7i!faCcM3(F$m7w>x3f2G{z(EW?*$Y0An3T9-VfgzUFcJOqTZabH7S_rpZa)Tj%DxWa zh{Dzm_$>Ak>%D9_InC1B4~}NFXujM|43F2_CtmG-_9z_UJiz){3@DIgZ@k=tfNubl zw>!n6{pn7aN9y6|*QxZI%j`#hAm;6FoQzlLR$ZaxsxNQa2tZ1zrKo`NT&B20W~I%Y z$>&HK-P4$BYzi3Z029TB17n;x07Q#0gozad{S{{{6;w;FG}E14PI3hCjN&?W;oCiZ z0V+*r>Q}{+>&@5W7SY7bY#0p3vDS4#IOLLQ_fpFK@qVwBN!#vqGtD3+(Db{o6J93{_@4A>d(XpRPj?W~=P!vP#X#KE`tb|l5DduMsickcYLJFJojF#(m7k$EV-xgT6| zC_$yA1a6-VG311)v$Qh3^jGb%weipi`@D1rzvQfLiv0Glp6$68etzC zh`YQQbEKllXI0Bx5It>*5x`1Po^0{){OYBub-far|380GcXS{h$EPQc(8ztAPxmI+}}R0cjwd zz{wxnQBDXt8XEksL^Bf}Ab`vZ^yjM=2g-g=1PO z%L%!Va~X^@GTD#HCE^YnZ1BrM8$7rA)PD+xRI_CG%v{fQ_4|9)Bl8_Kw8*V=zmZJ`6x^FqDMjKQ-}@vvd?|p zYde5Ythi{Ntw#i4FUH4#0Iaz|^&}w|&NiolQhZt}C@mFF&pwT7;CXzyIPQA=unZjl z5ZP#}_sm_o@P?-skWZTbG~&u?Z*PBig|#A{9JI0VvtzoE3xfg!g9;QHH)WhaK}J-{ zHv4_PUi7DlNOX-Ier4uI5?B)8pNN*y(ehI(99wPT@IRUw<4ti18vaI_Q>@+1@lN8a zeW(Ghj+R!}zwh*SDL#571bGV34zhK7owYly#+QG=E1gUJSvuVK-VNIjjF8htV9o0@W|om|AqCn1>fDu z$KC=ada6P*qx#TjKPToWbs!g3SDPRl(R&PyQxtlW$tyxb{O65v(4nGrqNu%Z3xj>F zVfFG2Q|GJzNUjCyDwgj-apt#a^$rz^g{xiOrwrXf@_6f`58NtSL6izPF* z;lW}|!_9cFM#O7l%_G1Kzvs;eyLLEP5=Qo}$7#HCMW$&C@vlb3Z!5>#MAVBry-3dK zxhLl+@;=|VAKzH@{?P^ibZa$+W;nYKBVSw4MaWGvcQM(>E##f zV=n2ozFG7z*PlqM_EoD63SrJyRfZKGKO)~a@E$4ekGDMUdW=acSy1^1?|UrvSnQZ) zInQ%2rg}|Ut;Il`0xXwodC?e?^dMA9$8Tg{_|mm=FZgzQdk*NV48!NVbh6g1J$I*B zv>tT;7Ao{l!iSKMbB>Vv9sUp;5JjG8+wGF)+EPwd@z8KRj2Gl($B>>+X{_d~blD zN)SZn-Lc!u9i-LecbU948N6THzBc(B{6wTno-EU)~q6FR)5#(;1j zF)v9CRFn8Lbygj+@<3B_l8P;>9coa5izwIzH>&Qh{y)8m;Y&&4&MoU=cJ_%`m z;%`0bHMw%XnJ_BZHev@-Zj#9bjAo>yTMW0okN7_S{0fwqK)OP27M3aG<>UO>F-aTA z5V)-dPaC$5A|bZhdxH@5Y1$+PA{H-XQ3*3%}?Wb zi0xD~@g;`&cJT->|7pzO5WlrUb0mJxAN)DzIVd~zr3;*V#t!>1 z`gD*>9cDdWiKoX2QKfEC0fY0KZ;|9&n2e0zR^Eu(tV@2ypdGk<)Bb9M3Dop|)dM>^frML#2MVXqv`OxD>YiTPSK689K z?jHOD7_A|np^^M2U$!Rf=Fa0!LCNn*2zCLPVcKY1s>(hx_%7by)i;kXPgBzK66me; zsP(5uOz=1c5bdb)T!?$(uv=s!f34yglkh0^fRZgt07U`pN0{E;9^glx^YKO{Dj*1EVjiLA>rh#|uaGLkYD5#pPe>_#jTmvI zsVsb!#PQ=FMl7t-7S+env+=HDKVxE4xiSwtu1IVt#d@-<)pK1Cun?xtcMHVZcHaY0=0ZT`To&RvBCK1J0?+G=^t zmP=E;_{J2S&BH???C1V!o@s0iMA`2qfR=`m+s^T`*hNPXfQdFAT5Z5(qGWcyydW~H z>67o-UZ}-Cx>hj2&6PDmz1IIYwFi>U`p>B$xqhYr_%q?#{YgKU^Yu_PleE&ehycP3 zZ}+XAHAYXpB^c$bf%uz&iHMUjNZ+YTgZ}uUn&Bb^N&p}3m`sk354%)c-Cf~QSLwKl z(V)81vTP8D0gR5jdvqZ7Mg;UXwMpmmI%9`Jynqd4^RPcySjv{ z?l|KRG27JG^@}wO)~nSB&O=+{L=D5#09Bt&>5Nyad(aY_X|4ZLKWa;nagbwYHemnT zK&@?{P#YmG!NKb{K~&Xks#x6rhO0|bo*OrSAZLi?T@5YFwaa``rd!~NovN9CqF@E^ zm+ia8CIF{=FP;dncsABy%cpj>ee)m=mCtMwA3d{k))cyb&l=q zJO&>A`mX_d)1b9b7_iJ;S1gVek)u_kk;D86!0G5teTRlu+CqL$%6i}a`Q_Qp)3w{t zr4cx|-v$}lKM#q<;hfbhvCPNG3<_809G*4qeEWphOSxiOW?M>h>8X;2Rj5G+L2RT; zCZsBOa!ilR&g*OkFq1Zgg|C-pjwDHe2gH-T^hWzkT4SHbZ+f<0?!G{81E;q_9WIsc zBzt`DvLJU~@*TtNh;-A9Y#iP%-z@Ly86&-bPtVfW;i`UM);g?KK%bqkg^qmIJP)87 zDStYjzE#df?i@g{aDB$9}g31HpId@4)nj)N#)r!1HTx5_s8+_MXh$K#et7Ap0&|2@CwUvoMeSB4ZPwoJpm3 zKt0E%*iDp1MgmG7c$zI{N=95TzN?$ke#{%|$XjO`6VuWQrNNf3GJt-%CIt14Tzr~4 zxNF9KyNup6hGjw5H?zGY`04DGdj;^+I9n;wbgAhuiAWk+RB^K!m60q@^ehS+9$<&Jyt}@|=>(QjNC~lwI`ljSB)7J2@5&u!VgFAS?k^W&S^)t*?C*cE_KdFZ)rV)vMz$P=@z75poh?1tCl8geu|ybQ@8=dm;`9T*otu>e>nnoO z2j=sC9Y@8-&N*jgLLm=2kG-l4oJFXw{DZW#U`7P(*x5yR&G~`TjCfxdLD?o>6JrN@ zWHxG;a+VRMz<;$vmS zgfc9o*zs&PdiI*iY54T*f;p1A=bRe=&kf>Lpac>I-L|%W9}}LUzur76_BC{ZV=)km zreeZH)n4eN*uLj)u@B%>n$hf9TXKl|6ym?{U-s)sXeMzbN_5_EWM{alDoaXlz`o35 z`;V1*f1tpu|C>knPsub+(`^y2O~%wWD>L-<&E0fGKv+%9ZoZ_ zoeQrS>r;}l&6(?(ATZeH*>;w&756>?cpm|FSg{8HU(vIV4Gg@IrE#dbK1CJyG#Ze9 zL;?IjGiepdXr&D8!PjawQ{=MZPWvn-cHbDtw}8byRXyar*7uB?G#j^rz>I1S_!@pY zq4!Td|5!go}d@G>~#s){u% z9VvZprnO^*6gyrvw#0t68>QfXl9PeX!0-U*jlphiNsZosWn$k))_=&FN6>)TsgD~! zUdRjh1<6TopHMV-Guv2Nj*hwTHZ{2Pvd^=M0m#6yaaO?KrbW{KeXLNV>@#tcq}ZwN zj_8U-U{!6TXYGfi%D0Rt*oOb1YsjTa$Rz-7N$3$v-m00T1Q9hrs-9SKyAJ)w>F)&O zvp~sl)|AbvRyJ*{#Ue_~HF;4k-sH<6L8HhCyg9=+6904!={&|}{NN?!$vrOrNa$BC!Ub<8u?cO)1Y;|(#mlxdKV%)DTA<^0Xa=ll*5T!>wK}Z% z<%Wiav$(h&Hngq0=H~6x2gSkM;*eF_01Yoi+Jq)B7GpB$ZWd+0JQUGYrKRsY?IK8_ z2L^7w5+Z=@R=ROFE<30+kCEEI8-{W%q_`ahmk$%<;6*3+qm(1J2>U0 z4#?a*m4n;O%uV7d{>iaSgl62o>F`@sloBwue4ViZWi#4(<{D&pyO>5teZXe6%~H2( zhwn&7#!@E@0t}6Njh@SdI^S>HjAeW&m`)KPyQmi%=z)(tUY8Hja}5n~`p=4Yh z*QDun%?iLsC{x)0yyzSlKdOB@92%Qs-{kSdy`QNm6&du5djNVEuwH>MC7=Fe;4<*H zy*)24uQl`PF_qK)NJviKf3BhA9B2^8R8mGzk1HqVIWGkz29L0?vB01wz^<5YbXvBx zcVmyY>F24E2N7|2n86O5eF3zE?D0@7AZY$iz*#zcfcNd?@9BTSqJI<7VQ9fgLHej( zl|kXP>?|1)^-kk3eNHHzne)^vekPrsg&L{?=YEk1GCVGQi`xrgN?rse|C|{6t(O{t z@lU9aD(b#ZFu4Ynw|*|G0haESjyClS%YqHuMfk+g_cvemqyY@o1Bq7AhYwxo@l%QV zy^`*Wv3Dn;51}{`n{#S{6v2hI=l;ISVe2B~t5a==tW{9MWnZ+?{Q#$Z`?$ znl6@TNR5`Gzo5t(QIwz0WmL_r`Jg7>JQhPppIBNMBM$=4E_-dZ@(^J(cxmXG%orU# zJY%y5z&w7Z&Kx)Q=?R+ufTG# zrsS-9^LJ~VfLZ(>FsPXpjc}b5DGjpdzKEM#H`{opnxjDHKZ0reJPNKwnvtIg8NqTo zQ+u3cd(YB}8-OrA)sY8uDeI0;JZd%E<-srj=Kkc=khe_jh3itd^k4GWgO=sA{+IxA zY*iF-wd|ZSR$8S7@v-wN8YCbnK~+;}SZ;?4GUg<1orh{Kj!lful|@@=yQJ3(&Qps~ z3{#Twi^%=TKAhaR>Yy2%Sbkdeik1hN*>bI4a(B7$aJ+G{(PI(a#0P-r1;O41*;14E z{q<$=v6jU^rrYB2 z6%KnO$)xr+aNR{?u{b+rz)b^n#5Ns#_vK(&A3gr+*aM@>cm_9A)8r2Vz0-5Q0Pys* zw6(A6-<6b|ZpUL_Bi?$HL$cjQ7Ma!abFuZvcJhNC!y!&t(Qx3DBq!tah0njl3oo|a zZYvw)Z4%36C;><%zJd6CM-Zir;e4(72m!#LYTiRM(wZJbQ1#WP zb${^s$1Uc?P^}SNF%fn#oB$7!Vvw*Xm=#=CQ_4&ir;sce*?#$P_Vzxl6}Q+nfd3M=y6=Lt!b2ym&@4EQH>R>M$5%I zlr)1in^c=bEWIk<_=j1gAN*$~L)QTiJx+BDlCP8~g9qMTjR{ZQ50?b~G2OT`Y=LG4 z%cHvaRR~o{KYGzr+UneP_o%8*l1%c84t%?nVpdPNrC+23l;_42`|R9WmjgN3D^KG0 zhUppMm}||nRk--!?^SyG&Qqs`vUv+aPzxKV(q~;n%F0OhXGmq0J$mG9+fDEzE&J(dDjn+x*ej<0 zxJ}J31IcPbT-@CJ0|mfArj_v(kmy$GYn*I+NqiktQkm0`#KeYtr-pvrppyWx|K0?I4lth zFt%Y=9f$WBUla9aDc1$MT8;vof6Tj9yP}o|N|*2NFE71&WO7NY-bENR)!3i#g8*t^ zBpfmcXCuG?eH|Oqq~!>;M5u)(wfsk8ld-snUDGfRK(_>3%G#;@4w{W#w{5j7{MA2x zKk$cNw=qWz_CDn9<0Pd`^L&5jgm~k3?PXq=!R6cODd?JH>`z}TnO8FaRp&0@>->17 zaXH7f`pE|1c}eueAHe-x@p<%FmG6$N#`o)z19oE}%Fh4pw%FuXWL(%&VCoh~=KfV&z9=yx2@{h5h_QEewxZb7ZXQbI zaw3Do#2ko=+p64n(de1$=j_?od^caR)&Np@N_Vh(24x8EHBy%#1%Yyz)C?Ezfc+JZ z`{Rby%vijLL&Ml|-UhpwOQFUF1t?)8+SV(d9;+sb@)XT1u^Up=7JH3w*7dj@jCg^R zS;5mbsVyPwfYTc}qXQ4@{;t3Y;AiL|&>4B$xFW23!E2M7 zzTj6bv$L#keMN3b(mI$skRPcvHc0(+go#MhewTCB6p%w*GjuI)7~oLi2s6$dcLRur zhozDrM;{+$W$a62H?1^FJWy;B&zfDFb&VDWtt%Fwp4!CpZy&b!wxZ zY=8`zt2X}&>$!#j$tYPfx^+wT0j03|O!SJqlU-m+$mtz5wD46Ijqw5a{gpuYUX% zCTRgAeM+o%uVr=?79YT zh#s(@`Cy}SMe6Cl2X?|@V0tZ?eT)4=uH5a%P;ek5#uT&m zUo{HKW7~*3i~0HPJy7e@(G=tsnt9nh1re3mUjVg9`g+H1&S4-vC3fE+g{5Y?FT8_= zwCZ3nciwr4x#z3wOEGF-TbHes4K6<5ilFHqG}cZO>@}wpSX|7FOp+HE1bd0T<}JF6 zAJy^yw$lNnPBOu09AEPoDgpxEqY~fEI7U1(zNzO-_MwiBLf81&*X_gcVIl#Un_;3~ zjDV+SIsa1A!t9VP&Aud0#{mD0f+RAl@`!}XFTjP z3jdR=wtW8-9h`u zk+^7SGDfjpfb#rL4|9|(dGZAF*&|9(aL)_*Wv5ad*BSPB+7M8UKfiXfB#6iFR7#Nz960%A;eT* z*Uitoyv-?=eXMFOzklP!41n?B)PQ!acn{%QojPX=;InJIizIPq2#K-;!QX5r0-N(Fd3Rws9 z7neV;am=c&OhNT^vUGxXUagq>Q#pwWiS_nH#60{?dHB7u@!$h&mi7ppW?3_YV9Cj} zmX=#_ABAYX&?xv^Qy}1SsX6k2-PDp#pMyf8Vyo>i1v2ZRyyLkKP_Y&Oo9UJYVJZQS z3ol87U_g&AlC)l9pcM|M9xQ0!Kas`s|Vve8zFT zZNTkIYIcK+F&Jg&FlB?_TX02f75|02JJ^{-1Sp{{%d3 zZfkelH>mk5AS_%i_pHk51)-;7(33eOs9nOWj}gvMAUuJ$e*=Uza#X|E71V8nN7WqJ zO6|+0pM+Z~1xa=vx$;rd z8MJyzJm%sm%i^2OOKIGN!KlFyaTPRqg9)&|Nd-!oFs+r;!ed81eIImu68%Bc{%&5y zIfX&|D(Qub-#ShxUUpdYc|X1@jpdIDtsc}$4;}Wee`1tqtHsj-&l=u{R$~dQ-UjXG za3BK$IK6iz4?j+UMcCgIEzVc2Wu*f~u?RzMEuIy>BumU{fyAfj5`XxpS_Y|TxH?T4mONPVatsqWD4M{ycRWKfaqU@wq1()LEkA?p zet6IHGKPuG=eoa}PM%&m^e>5{tlr}#DdB(z1}sxk2{1V;7NG*U@7Z993i&nQANVP# zot#~U^>+s}C5K5lF&#q2E}`o1bKw0OQsS1Nj`mn9cPN~P?&=#1byRv7OZ~fo@Af;_ z(GTeR!o5OC;QwinBjXpLM-IFwx!)`3TRgYTqWn*lJJW@MP%VQQtW_?5{~#wvXNuy% zVU91YG_NzNp0hh9ilrP17S*NC$Zkxp6abYON80~G?M=ASkyJ<`=*80TQ$B7N9ma%D5)R6;nUypJW zNQWME-$z6Zl}I0RScnJza`LQY(t1SVu1y(z8hq2)FK|EmQRdjsJjB%d|8b!;5@29i z%LE|FL*JL6f8;q7ORO#fE5@;=k4_xu@BTb{x_0Gg%z4%@#`#vHz9ic+0A zxK!kRh0-T#Ft3ZT`n;OQs5fgX7ORMKIOR+y5@qa|9kJZ?gm3;04rvCq%*cf{GzjKt z&eZ8NV`JPcPWVa-+Uxp%Qzfz#b$wsnAWzh6-!c42^*acA;Cr?zF$oh1V}occ-hWUq z?E8h|NVTkw_Vh_=UuQFjmWv}Zohr$fX;<62_$LgA6=(Vq>5bbn{Q$A?Cb9WW zNz2bM?sz)XBaI#i`>}ri#qtmgtLYl1ew?Tlr}Bqzx-=ku2ISDrj3?DL|n?)cI4r9CK|&KOk4~CW>YMA zIVb~a9SfN2o!k!Z>Ad!!=&i57f`20iEUo;$#W(LlZr)j2C$$<#-X#=Z{WRttxcLWa zM6aI)Ssu>wDi;3zQ7c^F_q!_Q;ST@DjSLkK8rYlP>k)J5a7T@(Fe}k>Vq(fU-C}`a zrTHKkzGvIp+mNSjVg*Uc{Xv8Jz`nl3TqNRU9U07(^9jcbclLoR_lF-C1O5oHpi4)F z7C!Lf{`VF}7LRO8b$d>kQ$${v^?mxc9LMjhihch*D9_6#*T&vP(5p9Mg>($QeyT^Wpww}hGS)qzv7U?oGCTm$51vHBp3j)xLM3o zuV6my^K5Of`Pt&)C{fhiTiStIeHR}1e&L>#5%`%H;SFF#lM_3W$odbw{OFiS6ouG4 zo&qrCL;MM$jB6a96-q?DhEWJO;Rp^KbZ)+pMuKJ(x@zD@bk;o5Ji;z`rp6%n;tW@j ze)Ki!Mv`w0xHa!3Xwke(MZaqEbRg4t^OX5Hl3U2^V@MGjHC1P93f9}K53C-BQ@x#J z!rf~ub430sBptXCVAmy8feN|~N{6<2@Vg5-YpyMkiB_vq5MH{yR zBG8T7NkNMrI4&j(qzdvXp68qBkuDcw(hjuGe!HG*K)F!acnGBO9cHfi(X=QzUFZJd z4S@2Q9UN5D2$6j37k3*>{a1^_^3eMDOmL?-%_$JWiilZrvnq+xUfjk6hvTzNB?-yo0)u1zZc@1OiZ%xzis{kj)j zGVp${xxbb1LZtD=uo}nJB8|<2nMV9os38!WJL$bReN!1eR#UV(|J6BMft_B>x7hwZ zW9*N`D_W*zk=lp|u;oqTTS>)qAExiR4e}528<4mFrG-JC@|TljTKr-1H2c-GlrUA? z_G>LcM`Y7MkMJCri@5)7Kv{K7ESM9imlw%hrR8>&DF)JH{N=gb(b*X-dl>z4wXp0T zzBNhtxKzGnKgF7&yT)M3EWfI@3>6JJ=@_8i;1VL`{gZoMeaFfT7}@`|m$Qm~zUr5+ z1tXu2=K5*)FRqs;D?y@r??uiCP-nj*JJ*p&H3ni-w5elCTe0n^rCW3hPRzWQ|KcmQ zc`h|&=Jm%0HREzAp`^63G=qjG*(-i36r7V%FA{%qU=QJcP6#imjferj+$T%>&XDxP zV;l#*6+H*|^4jAKvga*yK#D*_a;XG(Gw}o~k3O6RglF}Q&{Q>vHs==&Yyaj5liN6h z^!kS`NGA32TCJ%GK;12?)v_#BGog43xn_gh3c9Xk879M)P}d%*lOn<{$cIF&b$jms zQ2FehdrWWmk}T`&_FnBVKRtEBdCSc-AR4bo68Z+{R+51a46lAaD}3N=xg3=xM^21< zQ$-q1M4k*`q8A*BRfri9y5+j#hD2eETz=XV6=^HuVs;hqX4bKZeY7qXFQ>15TfGNA zyaxu(DZH$@*K_QDzP!6^&Qyf6_Ue}=oGBB^Dk>H#&mFI-J?twc>?L6Fr;_{IYA&Oh z#J^QSpAmG=N&-!kz>lX^WXgEI3U~5g$K2ffnXux_b6DJVP2YCFY<0(9^88)sh@n&0 z9cs5|E1ueMUDtldIDXYuvq%>;GWWevC*|l9mx}?*WCtOxwQkE@xHQ8G`$N{{KL|IS zKqTn5EXhg~!FfP@L|jT@%pPt=bFtsE;PDrYg$IAew1sksQZnC|kGk<0q-)GsAx)p? zf3ZK7C3;nP6TDQe+c>s;eZ6SEqzcHgRcEWEFp+FxV^POck59=BNIR>kf!7i4sWXCbQbY z;wL9rsCu0|Dmfz3Uwu!y`qO5h|H*wS@ih848>Fa`w)65)`5%z#7hPG2Ee^;2Yc|^&jAh1BeI$5hk z8!8AZ!A$nP_y|W|9M=mTWP>?+5)Ih)6&dXZ-HaRiS9NRVA;@#6FQ1=v;5MRE!6>dP#)&yN8~21L+!XbD+&)6h{zodchT&4#o=}kP)#Eu`+Qoq*RwA zi*OMas*?N!{gU+j8SH5L`ffap{%+vbgD@n+MxwX~IOM>P>nr49ffjD=HuwjU$TUv{ z={(>p0!{{y6|qK(pQn8&=lBEV&4Pj__7@kNb}SKmQ^)VKh!tyyj^5V6!gK|xb$N91 zs*Fh+8($~~StLRMrK7Ix9+qcr_kNhxi?I`&t%%|_RZ+E!PSm$!e#v*brSDDHI>Izu zfT;C`TZhC+m6Sjt1GhBn>ikO-ej6bY)M4q8c9WE7{yf5#jtIg^_jXuFtu7Wa2FL@*uQkyctN_6N=V>0q7YWDXv+tb5Fv= zw~+IhEw2r6E4M>k1pwP?_)d6~W~{h9I^mp|Dtk4Ai{jrJOE#F=e;KE3t)a?Z zpBANhBrQ%mwp`T?4&7>B2^GY50K*H<$V@&JI(-gRICiMMdB&Pbd05^-Il-IAQdQ3e6MFnYc$9;#5 z(6~nw@uu<}FuDMXU-LM-AT3HO--*0TsQakJ9*%D(u|_*Dp@09rm>PBjPyhqV{5wbB$|=JF2$208Fc$ z<={zgkf@zgl)0TM$>0}$!cAH-+o4WH;%P#U?q^F~G)>x?+u%fgl|qt&qr}ZmZx@<4 za8u0&@OKHUpIv^5GDNQ{?w%!pRoNJ5I@IgLr?ai!7S_@1#EGHM zwk(*Fd#?Ac65AMeA(&$jPzZSp6&Hl-woHdHoz_vG@*Mr(_(N>>_3~HZFvnjTQ;SC z{5WP~p&K0i7)!PhnrY6xf}MT!U>dwVv##@n?1`;?A?6jPF1~J;ZiJo{aq{!b#g;xN z!%v}Ewg{ng1BCgP=3UwWVs0l07cpHSH;j5&Sdh|`9nilLN)RpGJ;_!avpBSp8T?$F zj%GMhyy7oK*q%@Dn$Mjd+ciKX$F()EwoV4_hSwTWi@Z9s7$EW5&{vjlXokBH4a2%y zIdCKD@M8`A<#)Xf!;hAA204%p4@*)$&ShZX8duPNHft2Z zm+)5B&(i}feWhT>-vIh}Nn#Trrp*Fa43T(dm{H{v$5V${?e8WXM2C3~O!-lgt4xJj z%gHopG_`AjgJ!x>P2f`-oICl=13&olT?<3B@bdUd&GCJSd}480Dr)(iS`A1L5p*Ffly*&kMd->z zV&2Z#8sMRs76Jb4JifK#mb7NUoWwT3-><%fug^eyw6_Q1bm@>kw5_j7N3`@O?w-sH zCn7$@GvED+a+1ALM?z(I=Ur`?A7{{7O&ddsu_c#_hNX-Cea;lyV~e`L^`-H$WnrD_61c{Jt>y>Q@*rdO6h3Z47(HhOuJOdm)B4D0zm*8twkD(+ z!ny9ukhBs8wiqc6h&O_ih7~5@J>rhEXXON=2c-`gI-c4dqi<`+Kjlh2?^}=XuLR>) zagk%J=KWMwC}##lkUObXOK50nV#=&%w1>wy?4X4M2Xn za|-5jK@1EGo;P_GwLc3aj!8=0XtY;U1>CbUpg~w~+6}65@S=$`OGjR5nHr7WJ=-l% z*y|4vvf{5TV|+iCO}yk+0_NQ*#uU}1i?RG3JHf4Q@LM|9Y35G+N;ea!eA&xkv+dR6 zd@-*BZqlgs+aiw@tBjE}yUR5UHpn%vFp>B0xsKqWz zkaJngLPQA%+Dz^#qE{`B;6E?!}hvRn{6_j}|^JnS%lX6A5C$#WU| zLwNdwLaFrI_~4_o1MqJgMj_abu`b9hIDQ-!Q~vl))hh-kr;4lp`W2Ca13+EL7VD0s*q|m~k1tu^ijrdkGNY0&TT)^xG{?wqX3ly=X zure``kXnji$bmwsBIq;nN3ywc%TtQ@34{0Y&t`Uzw5#G5-a~anml~<2rCYn4MTIfe zvg7Z#jJ9uXT>-4~TCcT4(CI4X$hfn8XtADVJ3ekDoW}rM?SFN8f+n%)TKQVbE~3Lv zBVmh;Za>1ucdkyXiFNmt8tb?<*`2`s*|WHYKHadApL~_VtG-;+Ym1}?v6t_nHJZ%1 z`bwHyQM#l!V+JJ3^JW!hu@A{a3Ylun%m_#v{)9uC2&w;;dq1{M1Pv{@@^-ujykS$t z<0ayb5|wGF-5qSFhw|~pZk8--k%X zbN7E!_luSoL_0Pl`nkQVWqMe)BFpO?Yu-(MXOc*32QG{v(bSPH?3@3q(voIU=6`dg33HJy}7p=MCx z&;a+_01XnKJk`T)Y2>QNCfXuFHXbmt{`mZDv8Qkt|9$LmZD@yf4$EJVNHdVZ*U9*v zFC~}5T2Nz3eFQ0oMn2UnF2j*PxHEcJo}Mi%^I8UwP_x+WotWKL*eWQ?~HL_<1?gLGfq4i72h{7j8RX zXNdv9V_H#~z++;gGDFD2{=*XB_mwPZKQUb?Pp3(f^4<$94N5r^`#83ZhEEZ)|0Nq^ zfuoxCov#x{VaJbzjg$q$rAu$mx-vD#J$_y|x0dlMK`zXw!Cu2i1>)l*=<{;9IkugjM1FBLxs|c8wtc z?&`V;1~v6!-8+JhOqs;$>ZAITKjKxMAcc6;EdbVt0N(T7?J^I}KmTP|ayJe)+(qUfGSQ#^x@ zo~q;<|c zd5&48`}2yvv$x+}-S{`I^+y_K2x{C?{)^ljVX%=)P_fgQq9=yZ#gOYH8!V?Dq#x*< z#ggkVL^9Za^-;v167UnNpcsh(R)tE`WuBzRMaPeD&UL?mlF^~4v|o22#zeZ3#_7E$pJB6U6rg%`;h?p79I>~NzXqN}1XXD7;^x8)S>_(8;|{73cg;qbfgR{7^m?ng-G zY{V&jr75K-5IJ==dB*bJ(Q!abO`9j@p~fe){nXL!o-VGR&)`P75?){DgJAX?W}J4V z#&Rb!ZwQOl7aIpFy`ACbV#FbfGtqMa{)Yw19}xNyDnyZ$2qxjkN+KpnNV1Cho^x`s zp}?v5U`S#Tq9b!VQ|#%W=kMb6Tio;j$1ETc13Cby2p%`o=6V#TrzlOBP3Wg^<1(5( ztj`{-s&H<&;g+*gXji1#uvJDe`-5ychzh4FCq0qrdl9L-31M$}7hj&WZOc#JBTQ>e zz?T>nvU(L+-_*7$-ENGzOmQhR5yF)bj-3DY{P1Jwl^K#6oQkjgFucoPH={D@tbJ1S z>L`3z9@1|Crdy8&s^lK5Qt#E@DV`bygFO#c&*uCR|RlC^<${`aW@IUSK?9{|cEGiK|3dHdQj(f8-Ec%!f($*jf z$Hj@l&m=W^U{FdnhbJEMEmzakKG>)799|#0M>p)YM{WDx*p$Ps2S;4xMoC3Jz8eM% zr1q-pESz+4?cKw7yRJ{d!jj(M6|U`(2K`EL*w=;=hZwtFxWNsgI$AX~$JgVCOjM@c z%k&7CP{=(t6>*I8c3 zhvws+eGl{*c-0e+67XDJecwhlvy)3m{y#jNoEYGj*rue{66&27Nr_QYJimn6I3 z|5yywFKDG?eI-8|R|GCH6r6&*%t>!ENeUte9oSxUGH?W9%VI5}i7144^>rD}h#@aB zurgAAH5Il2QFESkYJ(0et@?OoPJ&+f1&Y#&;VNpMZjPg)wLR_ZxOj7a{jwD1*B1br z>?h=3)ahSWGMKuv(5#75KKrXn7c*2(VVZ66b-a@CE<<#0Y&xyC`WT~i6E^$2P1POX|0Su^`>OM_h*ZIWtK~C&ucEICko&$IZ^>M>C_rNHkEk<9 z;5^zAIj}`Is~DHbnm-j>EHn9PI%!41-#}`wM@Q-x^imj6ZX)!=vwelIX^lghR^YP*@%ogSTr@P^!s;pGTOwKT--&RRIB=K&}8F==rl7)gB34R z9PM2mx@3?NQ92LtB|nWOr^%K5GGB?R{#yNDvCXv93Hjh>It@GZpj8t-iCrWYC4@bO zK<4Z5AgT2Tj-A6R_cM*%c#y8U0+XWPP}!C`ndbiLt~u4nNLxTD-SOHgF_%Y_D&W`g zht|e%^gC8TMv6!^u2^nm(QG9ZhTsE15QZVZ9B0IM_L#TN`Qd-SZ}dIa?21$pM1y-cSMcxX%^LyZXTf@K$ zp9J&ZlPZ=XV~QNc;&x)sIQ{d(v}dbC4~l62U59Dfi!>MxS1^Uu`1} zGQ{#Sv@viL5R3MP)X|m|CfN=_9H$<|r`S$?m@SJxWq*C13-xaq+AUG3xr|w>*BzMy zvLf7;ZigR3pmyaQ)+kHR5)46yPd>n_&8b=q1y}fc8Yv#VR5h6Y`0rH9WV&Ys5 z^Y3Z5;8T?fV|#rwKVNvD`F5H^j4hFcw?FSNNq-(k3{-+CYS{LmwnzL=s z+;4rIV-HC=kOB`M5*uMGT3VyLR9Q56vIi5mzVXHs-rn=$RxG&EvSwyr@<}Frn`X7GOr=yZ7|CVdL8Ai>(LuE}C*qtA3bY{z$Xz+PGXs1#hsTWX zaG`qi{Q?o_*<1MF-L3v@RYr|SHQU)GAm{SiX}w9(F0Q8nI~s>O&%>XlHtp2sWuD~p z>!}qQt}pY;t|=S~qzkjjpXNOJG{zpdmkQ)(>PxCcbVP0LNeUrD_)|_L zH#3_J`6XVz(wxk2_e$w+wNhmR(n^NV4)5{0pFePs&$=TC@*(8!L$VOvJ_Qc_LN=u_ zbWYCbWGH%Cz$up{AAQ`@n74@7SBs?m6O`OV-I8;&I8dW*b~8Nx}1Qzyj|kj=&}mdnRnJ#W@~XT1ogZ8)V5 ztJ`oyf)8QI7W;vsq8D%C(R{Xgi3rto>GIuZ0>APi1`Xe6A{>?5G3haPhZ2_**AT3U4je%6(RTa<0-ht>KWz=?tm5lD?Q)m!4irF7x00m#j zKI-xCY?Ob1OK8;g0}5>Mcs8QLdzC%>#O8X_(VE)4OAeLE^+G52%i_0|&#C0)n8`-J zI|r__(>2` zN{&4_Op=>VhHFdXq45`d(4NK(#eYXv!KdS7lG{o}Ohgn(DlPF_Qd8v`=d}h9HoU?h zS>^ucynsXb#Es+8s7ApM`*FDec>&oe$d{-OILRlRauAB^hgK5?&x1Oramd)dJZ8(U zSdX&O398?978l@KifnKFzIQwE*R12(<4@QAEqu~h6}@%>yCp_9{Th-DpU%AUWUZe;QoX!l!!g<9Aw_q3(KxvdNxmd+S^+me=|DwB%!X zb&RD{VK6tz6gwPaD58DwnOw9*gjwz*uwc%kgjq@ob7}}>3bFh79csbxqYj^mGmr6* zSzhd>8T!>+&`GRz*-&czFIO-=yp(K$B9#X>WLqe=mclFeuD3aIuaVd~pY(H@>nE-| z?|LmJ|7H+hU5A|h^!n7k!D_?5X|?>rr+?blZZ;eX-{)2auD7QZ(qgbNOsj5bO-U>f z-9A8)Pl0~!_Mhvx*EHlO=x-Z4gk9Pv70eHry9>F;OQ^mQl_I2UN6$MoRPipv2Bj22 z+?EyFZ40C-Zphyd3nC@399qI=Uh`~u0C!rdaAe~)lAs7r?tfX}r6iaB-HKC}E^|Nc z=fHPys%dkS9NUPBii+NP+^AHlEz-h`8~Iw+LiS=iz=|+E=q@+#jdq?tkR|HUZvDEQ z>0LeaoZ3I4gtKdQgCOnXSz^p)_Jd9rRp;6w$~8;+E; zbhi{*H=>r{7sZp6sVq%R!I!A1QTVxmS*7`~P_8-BG$<2AHa7`J8&|xRaddqZYB}dq z;LJi&*K%ra7*~0(X1eEP&aEGo3x}|ZT3zr?9Aa3X2~EgAJNJwDiMi}KW;jjcB{bV)C!_CeK-JDt~){m+3cyKBNsqFT)q77?#v?s1g9(7Qpx@2}S!^IU2q zSSOFAmUsQzJtOX-mgSNODVAgN4$^@Qaj>5{m7s(UTV7Fpi%%wsmq=S-IwdWiz<-od zENUkug&Bkp@u@j|J|VLy#SN6EWg#$1m`w~i*tn7;Sw!qgeoRn1li3BvgTQQ;_d~hL zajZ32(YiPR&Xtgu;m!fh>%bmrHWE)rU|soG3nminZmRYuYYld_Ux%F#g9qikUqwOP z{;3^iyrBM!KaL6yt+YgKf-Wa%PjBPflWbVjf9u9${|v=h`l&R3)`{8HV%GLAEDJPrH2SA#8pj zm$vuOg5WQvaY64sGsN7(n5GiD0BE%>dzL9k{Pyk%Wtb*!k@))Z>q7 zS7ml%O!a<$3eI|?xHqT=%Rl?-OG4m}zIVG-fH=hI9lLmHAmNF z29NhF+K6_`>4uls*n@|H0tVzcKH(>n5|Z^y+vnPK2E+dPgMN{)C0VCc)3~`Z&c>Ha zGTBt8Ri&?oS;NpI1%!(=rNgYj_{d{xMFs3Q`fMTjUcF{-8H);++enlSRG3$zO@$mr z{(yIH?)z(cuuIXs&GM3#?5O_xv^CdxR>q>gyZhn{%a3((acOA{%QYGmF;JQ09u4O% zRN4eP>nJ9VQNXCez8DK8MgF&xE6GRR%K7z!>-apD6i9w$O}dC_An76B+H~Jvaaglf z`ju?)rnlXq`IC}~GN{86JTAaotjTA6h|6B@laUszgT=${w$2FOQfr?o9k0$JrRtiZ zFPLtOh3}(BEbq2UKf za&JEoqD#)FUwR^V3kXBZKnsaVSyT}2n_l7X9+sAu?(glvEKJDQAtX9(;Q9>~Wd{;B z|1PSZ(}bLmTPeFdxa!v%Fv~PF5hn6w!p2H0W*mJmb_En@55;yRYlBDSoRR&A5`Uq+ z6HM)>DSYV!tt2g-<+5u*3dw!LadD=+eYWvw_$Y$g6cJl%H}}s>kkj=g{vF?88B=RD zOPib<(pX{2r^Sb)uQ~ZO_vt-PaN-rSclp}O5@nCK9lT!_AdZW?s6u~#(ux}q#3 zg-zZ}(M~wx-#zZ%)wV_6wkt`lFvU*Ifjy)K?_5I%F+x^M=MCL6<6AW%8h@!iC-`$N zQ529tc!_Q7+BwN>h{%7+Wg$M2B?ccAz-#bH9PtB|S&keK2;Bm>@;AYV;czid?2c7k zrB%Tf!GlqYy$$_eGM&?pP&djncOmga?`##4n?on-yaIB5953Vv)UCanpM7|L*JDkZ z=V<>ZYTVR&i3V0_@)1C93h-_GO380})k*2SWCkZ3-hUC>N1x z@$_Q3mI877=CxRam$!rE8${d(jPU5L4GrX3p$P3^iIT|uK1uH@bB)~f4gTti&mx<7 zLl|qEWM;@cs_j%HrH%eJ5Q>!p6qKaM5Lr9We`n{POp)iK%DAJNK~2`&iQvNBNu~l@u-KXn8O~+usUNv;FF0V z;8D|I?i9}A!S1C74x!L_hCq@0WGQ#l@;XJN5v@b~@Fs~k7lWH!yRI-&=Z0M*;~fx; zYQLpLII9MgUh#waeEMdVdGHwU0M7MOZsM@ySfkaQ!(TK*hS@M@EvusWUL2L6JS6|? z*m-wj9(qb?fBQmd@Kf4myt!`%d~2d{$aahW&*R7+VLorhE9G_ya9@=zngjhl2R@f)ew=k9Sasjsxf2IjoEZ=Dz-{f`j()Ikpu;!<%kFm8Zdz965$EPw z9VZ|{Ad^`YH;AWrIbSWa2n6oz?%nN~AUa$8-e7BUD&V4t+yktVIm9`8;hk9q-wE2!cS*(yhlIo}0s#b%H+uHEMfxYhX_C_0CoeQu}!GFkk(NnvLCg*$+u>8ke z*_Y2;Nwreyt(r_T<~kzzTKVv%Ph&wBck58BLrO`LePH5E5;a1DmtYanXmy>_DD459 zhMD{)Vmk=p)L&`gV#iEg7KfRi(Sl=q-RFiyu9K3e&}Cj`9lA|?2D1%Cb3?GO5Tq8> z@?oj$_SHS_?~-Vi9DGCoBaMt`j$qkQDmf_U4EA?U4q@6rkCFA30IXd%)yb4CD`t}& zZd%33!;)}wC{T!cqlLeQSyePR(UXWf$~H4udh|MXlDGIQu)vGcqG;#^$RS-_RFw*p zh)H=85f*)ew0pbL=Q{;|jG5?avdH%SOkFBLfv!)}sr0#*2pu@76f5n5iA!rP`fqF( zykl1W_jPo6_4LA~(^{E&z_Cv8i`dm~yUhU{{_BO{`(`?}3C$zDd+_3pf5|SS7WLIWB(ff)SgocenCGNOj}k&mROd$7JhQ)#{%R5M-cR zZ2a@%3*1CF;rnrcMF}>Aove*l=XvwY8Vf}rtDW;i*Dx^@HC}9q&-LPQiTc88eTkh%t;-um~z+TVAnBLS=}3@A&GjAf}h`9_q^ z7ZQ_HU^qETiGPh3O5a8g>Y;9ZJdDq~ay#!$D=QhdsZjdm?VVb1;oyygLpkG}dw22C z=p3AlkCe1d7=;Coiw&P0H=5Y^FG&}Ypl2^W_ETV>T_;5ud$U!IS^ni%D#Vf&ZWtUV z0`r@jROmlk{!FR-N>Hx3m|8|QmUn+Vi~sAW~S-Dtx*{xU2Qi~$5yzN+EroxNEQ#cag0Pz$jo`y*XiIr zy>HJ`-m+#TGYNB>s_3<8M^HyD-~4M+GWN5AbqlecyE8)zZYest;mnY`%y^G5L_E6? ztyb={(iQ>X`50XlSUEY9r;4tmoAI)ErT{OQQ$7A&K^vK~q%hUy9|mjOrrE!S ztpP9%(0wGNlkza}s$@OxhSo}*!_fY(+)=od}LrfWC7_~s~xR223Wu~zsCPX-ob`qjIAQR$lF<(beM zD8ui^%6Ilcvv{jrZWF;uOyjtEU-`%}Llye@hS=`rdfpAqs(&;B5^n)-G=UD~U|2<_ z!l^dW7MsphYH`COUN^E!eY79vtI%uiIyR~k~Zk{VqQ1RvxPOY|=R z`%q%{nQ!~xU<*$bz5sK#hY8G1FHpPk!g7i+JWEwOr*`wKArEnMbJ#Dbt6-VL+`{V? z?!yiSbj~C;+^(bkZm(}BVx~Q_tPszTIr;hc@%m^p0H%8vpKoYl(TFL0>D{mujzFPWkV{zVpm`RJZn8RqA^#qx*ZF<8E-u zNQK7xmYkepZec;v;=m}a%^*?3?Z{X37mi&Fb)M~huKH!oFc9;#plL1t2kztS_b$)Ptd~zF_n*~Pyno|iNEZGwIW(MB>2$9( zsYu{}<6QqESbE+7umPKC1rOx%5woQxGEXD)=oSQa)Dd*39P}A|tizBj;q;UkXp5@H zud2R$B~)U-1diN?rmRxFF7Es61l;(pKxvfDw{6zhb2Mhk4Nzg`x}I%wY%UOXk`&Ne z!)vXMsm;AHd?O{97WPjLqVG;n0d6rp$4|1|1c@fxjQoygu7lSNt6DnM{>B>4NyFJq zR&v9bzrz$mz6z>P@-P)ac1rttR?e+xhJc<&;-AzC-+mHyA`N@v!FJ8UkR&984)Wgo z8inmj*EYsO*%PnqXDC+C^?`PNnnd|xua&SxI44A9(4-u8;1$C-pC$YYNFJ&a8~k)5 z3#>h17Y_u-K3o9=a%cLVERTTeM7nTMwr<=NnNtxm(3iYMnfFZ9d6koVie3l*rC;5z zZpFM$bghl$a+M|zR?L0nB%H(uGV8gm+Ls<0#7%V2PwZd+r>6ScxbHl6IpJSs> zqfK$AQ|{#ZV9>vGv!_89`<>~=>ALNo@C9AxyAIFl<(m2wygmN;as`q7G;^@V_ePc9n$2uaSp9v^(aW+4uPlBXDmcPF`W5HiYrB@>!@uAB@AN zD?rG`60c|HAQA(0qPy&D?>(Q~13^eLrw+9|n;@WX%C&K2T3OV6is_;Lmk=jY;Ne6t zCVQMml1F5ETG`%|_-NRG`fIvhgy79z%=+%vD9hC>9L>P>CH-U0r!aC^Gmr7%R*p55 zw*Is{FK*6BlJE;D9tju(J%ax9)0mi6lMu>H@!a&M_@@@{lPdH8k3g8r>#AM>)w) zG_|;;lX7_gw-|sOW|qN>pK+DzjCU+=HTZy!`;<_>2|8rd&}(7ym-f+jqE;EhQ`S(( zt=DBzE1g{(qLzWm?8|02|Cj+#yzf?Jz8cL^1$vxob z(?n3dQ_Y-va!oTRh(Ds9tD_WC&wx1WGC#StmMg(W)jIRJhi|jxJy=kxK!xqpb*t@u zzNb@>p2fozjsAGCkV~E(oW<9A{P){s*Dt_n)~v=7S?f;SL51S)7-@S?rOV;JQMtD+ z@>~rBg|vuor}n)^VTzpG3*^^&R=mOYyqWr(7%H6J6HXg^Fd)CX*PURLR8I0RWbbF( z?(S($nLhYo9khi_veV4)`&LeE;2FIHojgs1$!`ah^TStaKrStL-vr7j;;y_m z498adrhi0kE>5A=9-GW4!Jt~~z(q@-Wp8b6eLC1V6^XgZ{@BPqkwKLdas_r%CFM8o zhV@l4qMx^Q7N3VL8YKVnndXnUu3A2wiBYU|mR$pLJx|r9|7hr;!hHImSTCtHlv4CO z&GI?HpRR~B`zG-Iy#4O+L3&jnu+929Yq~uVVP3nvboTA#bacfRwO6_HB(EW>>DGJ9 zXN{s*Jjjdaht$&?2OFG%p`ApIotTi`MMbgjj1aqak|`;_)Alr zHKFZX;dEW(4tw@qT$&F_U|rXBH9t}FIlI2zaQ`1@Ljh7%$SoZb>v-ck@20bLAwOgI z>^`W#(sj>Pb37Wb|9<3oW!bmrC?0;pkqzGTU(I`Y#!Dh-l08Wm-66mS;VlWQvN)oH zu03@5^B|>-6~4hN%r^GJ#(vBA;Me1u@@s5iRNR~v0mE5iMc3YxsYSiehHtie8Zaw@ zW;{e+l-i(jti*hhQLW}hr?ryBpEm;GN+CXXfg2frWI%X5_VEnWtH|GIBJ>91bZf35 zue$Z;EeOYi#}o8L>z#DnLz(EqfY?FSE2{H(p=yQm{Xx4dAY~-`_PPRyHUv*w6thd& z(xGMw@ChilK|FY?`Qjfgt(4G#I=Cf3z8R}0ZZuTMDAcdZAemxnDf~D7d~JbHX#4t= z%6NBoC54-N*_1~j*ZWytD;1T;?=+?lNr)hi`>!ERHEsR`prH~};UdiX$E4^R82fMX zQ1>u_c;lP@CE7xQbRhJF+;`iE+>neGR3G?Uf6#27ezN{%N&NPEm<{)bJp}~ z+p#nH{I+f`6&sbbM=}=w)45^m*I;8|d@Nh`SzPc{Q?Tcs9}R8_Iy}HFp7txM>F@Wx z*^p=mkzowQJCrIW&c5DY7-z}=vkqV!a77^e4PW@O^qJPvq=Q3d7k$c0W5q{f z>yl75Lm4M6IHKqnMdl?~bV*`~u&sfMIm(~p6w*~FNn%i3wuW(8GkgwRP8Y|?>r#I% zS{Syig1-JPrT_mW#4$L(+xtugxqz~< znwlZ}f}bY7S=SYUDv1iKu1-0h02BAC^FGB~)n9rD&~uO0)ed>9Uml_v0<|i=u2?2I z2?1M>Jy(&me=C+HEY#DuXXNUVM{{ZJZ*ZF3I2u1l3JQ_teVX=|OW6NZjkSHyCHYR) zz9wkHkfXa>h5`6zD7&gy+?>3LY`A#r4a2n%f`(Zdh)m`B^(YaR>s56oE(pN!rj70W zw?0*}3D9T)3dJ+;l9Rns)P)c$Po$%@KvApz_shq1Mn2D;Rhm`ge(>#y9{*b_buIs= zL-z#MKl`mWvfFsxN-TQl>N;j&!+e;QH2^dUek*5HpWV+HnwDC&Qa zHV4J{)`z|A1Dz%sS{F?KOKL3m=7_JX2|yA`hq$sW z@*A_}(ot_ksZ%lb4lB9jG*qThhVlVDvIma{lcZ!X7{TRX``-%?b&}AVv+<=gDh5Oa zxsPU2ze_L!n7IJ0VIl%Ej)`09^dWvLG~LMdZxi`FXI^L|(7igkpP}QtS7PiQFr<5# z!rTfCSnH?MCQxbHoTtrr^tnWHw`$5+fkRYE>QSlD$0=u)J`WaN%@nTa^th8=0-zcI z39w}k*-!R%ZvXbATrS{M#Q+Saf5am|Wb(GR*9-(-?)Egl+17i{^0r^JTA7t^H3H9+ zY{nL{JD2On6S(xy&xy{(ql^^q2rGz*XK7TN~0z(CXLGVyXvHIhdAu!9N+Ew(cr=! zbiO!klO)OPwf?Y!v&SjUuIgw@_3|eqTvrdhBE7iZc(^c~jsDrywh6SmRBpX$unrUa zwEOiMpgou1{kyQyQ+?u|o8|BB`1pcL&QR;AEnyEPE?i^M$!<3|9H&(pvDve(!PG4k z2LBdaH+|P~*EjWrj2Z}xglq%sdcf4;ilT^k7l+2Yp3b3oOiu&tV$9(h2<_z%jY0Kh z_u>o_c0*uXP#d}$EKW2@8u2Y(w|d(>H+odQ;?+E}N9gN!J~UfyV1=W}2YLzzJ&I}u zE7?cli86m2>lsad^wzZl&$hKMt*QCCe~D!omE4@NZbouFm&Kd@c|(7_7`ojw_d=WA zB^aFa9RI+5&v$3lM!RhqUrw-TG&YYJ|} zr~P9>rK|52@lrbq*M#8=;0^+=DGC^zG;CP8Jeaqjfu!5X;%*lUuX>#vBQ@e3%D5+H zw%SmchkR~vqOv1s@QsT})%6(Z-KgY7S19#8nN#w4}N3 zXUvCNp04^I5RZv4w+K}?oC2u;_#fZfKfWF`2HuP-d560y?AM9BCjETfp)tVoTpS`H znj=l$A0y$Ts!hPz{AW}q@2KYPfSI`8QwSjfPND?8ii1k!mH?r9S|FSToUv%iq~fxz zGd5coBajRy19Hwc$5g{V18E}Y@Sb^Mq;ZcBqYj;;72auYq2sj@iO>T5Z-5(fGg-oh z={c}<6tazzp4f53ihcDDSKyu;gluJ_-0~#q@V@^YvmbIFQ=vW@2>|5M4)1y2^(RSx z36R3~6)yJ_t9I`(>d&T<%Jl^TtLQ>7D`!D_XF#jl+QF8o(h85c6=zN)-2GBpSV4vD(Y1!n@yv z=^^fYp%_q8ko%0+77WaH7uc~OUrKF#|I7WA*a`z7nS9l^_f>7rfNK7b( z_J)(ofGVUBc*jL+Mlv{%Fz^}p3%f0Q3f5iswh#?q`3v4zpGnL+$Yc*G9WY9QK+(yB z2+C-_s&iA)B%{z_8N)~!w)Q0vIpSdM`)JweMF^k3O6;Ek zVghQht7)5ZNtgIxoP+orKJ|M-`zeQhqmh!lFF$#ARluqbFE6hrvDZp}R&R6o@3zI& zq4eNQZR^mTRp(w3B!_WN{nC>lWr-Esp22et1ao-jd94-!Xu;Wh?VV3xKn zJbtzqpuR|+K|d;^$1?I`Nrr{*Nk;SSO&*8=t;hXl3vndo*=-on-LFXzISal53X)`G z3-6*J)*V47Q;!yc@z+HYEZ+?bvCJ+@z+BTS74?6}u>5inxOueC1`jScIz4v$C zQ_H1@E_vd;WG!m!O2+uOr86?$iW-nu(~BKOy;Ze2!VmQFhtF|&EI~bvA=H?9`xaO< z4CUmOAECZDl@yBXw=0Wf3&L|_l&vY^Vl#jbqdweWmy@|cx zo7Z+W(#F3D`f;Rb4#qlhI{mVwlnNKq$?1xnaSg<$S{{zMzH5$(SF>CLQw8eL0Y!}9 zEJE^sNbefkUQ(HMhQkdG2&{$O|D=EDtu8H}4P+V(urP2i@Mh2FJYMh`CLi$_b{4?@ z^RXQm?9op1JlM0Vm&7FMgvbtt=G=t+_E!)-FkR=Ky8ihmn=BOV($=##KuzHHL?6ke z9O0_LWK0TRP-=c1HHq|GIo1}#R+h1OH^(JF!1oWWBFM$57;1&G69zah&Hey`$m{dI zy|EvyXRCn{dwVk{g$$V*f<=tvHK^X6I31W(V1fDeLRe<{tMO+>jP+DWivQ^lfDJ5| zSp#~_90}q510U+qfq&fRpRh0=&bG4@mI9=BLBt@aJz#o#9GPhT4Ax zpV<~O`=IS4vT}2Qvn_J}{(T2wqR;k8av)Bu=P2XRemB*XlWt^jJIL>F%qK5_YB)pG z-Y6~$=!ZC|IUq_^(;ez{-^~-=+37dQH{D23LD8Biw7IY8UW95u3QI+fm8E>oJ4o!v z0iI|^pYa=H)}N3A6M3v*59WPFgBUQ(xEdc~x4%sS0*yBR>*;`{BVbLEad+eDcfYJ& zoW--_&-<#H*RpoJZm7{S*XM#!RyRmKOxy-xMImf?3)yru-a!EJR2{uJg<0l~IiM-5QFI=~Q)`@%GUVQ52trR;Or`s?!Oz(T# z9nnI=$JiINZ!HR`0$+}P2+o5=ale!IuB)`7-3mJx^eDb5 zcyII7SaLqRmUELUh1YHMTn_R49c|6#d#%#x>g96w_8Slp7*RJWE2vqd`#9kl@I`fpHQkKKZVv@liq`K776G(jIx_z8E`==6=&G z(3#KpD*XKjAh>6W5nN?NjaNm(Fs}MfC(QVPhcRIUOmHBVUBTT^z?2gb-T&EZJ>c@c zyxO}1CA&$tbC9j>NrWtWI(;)Ct$YNn+(yp@&*n zmNpQ=z@ljFW3*XI>#IF(8XrpwUze+{;Oh(%vf&K95BHHsthNQIe=zFz`+1UApIjIv zq8>|6KJX?0gO#PsS1HO)?yRG~?aK_MK5FX4pNIVPhS5FF2OCm$-Mxd}w(C#-uZRMS z0DHWFj(dh;^?^33&fR_CXlBSU==6<2;(_!z(^aWn;MPH3FhFp7BT6nYvTJV9&x+;v zmw0v#U>9EPcj+bg3H7P`v-JI02rT~m$Hrq-l0e*741D^eqkY?P%hkB(wWqM&Ukdh_ z319*h*Xeu2T~gCfM5?Pwb7o=KiWd+3Dh`5GnJ`$iRURMnG`vvW5;&3hfwZOBlq39| zO|#wU#AJI?mFL=PD>l^75z1FX1M%u3;$wau+KXQJ93mns;rmSc&*sPr8+w%pvyk^| zL^xnubA;bb9iDQYw>+V>S?d*$TfVxH^|;UFEu1XfsA-!zGuzYrNAZ>S(u8O6-O3a0 z;6gSbbRo6P)W?Uw-ee&7$o)q5*)`R_%a8p0RR`|xSNFe{fS5#_?uG%(b?n zJp|xxAcUEzXkP1U5&5>$N#fI9w_T^`0uV)*b{B77b(x zie`z)N5VKzGWyB`{TKX>qUabk2 zPkw-hqBI&bX(Xa}gdPoD#Q429pME-zIo}6o@Cu%)li-K-?&jzzz7*9uXw6Mjp4qLk7~y20~2DWW=tE%#E+>h)J6)vF|FQ z?r-0v2bkcxfq!3EuyK3R*&iFtJSG?K{$QSOkoSFS`n z-h)I77neA`w4hIZB9S$z?fi`?(&^G7KL5R}CGyF;rp|g|4ETuN8QGOIKmShn!8a)M z&U8mSq1!XFD&c$bz6XUX3~%QuyG=ylOgdo*C|~%F`JO8lDefwEM2REy>v+%_+Wx!^93W{T@-b{+9{c|or$ zA;&8eToB@68=XTy!|4CM@!Ee($LiG^;mBD7=wVhE6|f!#W?|-lgJMKaA%r-p_uh#* znW9H3muaKxY}NITsym8IC!aw1&$Oo~S$iMBsL#`ZmIr=keJQpd7fF4Vafwmm@3C z^XGhCtM|0yv%&k^*x>&}+RvAOrNkMK+cw|RgQ+By)ff8Vn@9NS6c3aK|8J@cPjG+# z>l{_LE_YLe({mo$-s>Ta_V}=pXUx|NC|s!HRvP8jT~j8XzJNiN5{$VTFB>UR@hj~c z?_8XGYo38}?(HuCC0@ToSJlVL9!O(FL45i5YkqE6;HA2`2gav~#?*$3PxeB>D~-Z7 z`C2_W#l2W{+%zIW9Rg2gBNSUX{~l6Q`we!GP4orQBPzTcN*~OIcxjSe*VK_gK@g-p z51_Y^Boj2&D*L4vR8#L|UF=72wRw3l796xXm?jhDHs1e6^Rv_MFd)ehXr%97?Wj;a zai)%?LEk%^ZVc3GEp0GpUuWPT06#C>_kkjpELv?h^Z89E!}Yc2TpwCiJ1lMc==?pc z*qT$TaTlR60OdblCQ@+s5;r$J{Dxmf3de8#={Yr)njpZ5-zGwVmU`aUd3O7?J$tfe zL~6~5gc#(zFX*2a%8i7jcZGw0rl-&$o>oXST-hU*hbYr4n(MenJ9cp6IMYNv91VOQM(sLiFsMfQ+MjzT`3DbAH`fr8(ms_O_ zF&!)K!R&3gQg}K;jE}VtsapzcDdj#ya)MU_cK^~D8VLglv!&QDpq{+H=V5g|YTanj z`yc7z?RA1PDI?cUU`nSa-vX8lO$=U6Ve-#re`-L4?l)Y~F818^`$)n87w34o;x|cU z8nxI}GB106=+HT7_TVgev#bG4tAA^qd#6%Wb zy;tg!(Egb_4i%w=aN!};>DS?;q+jJID ze|GN(-JLV=eadZmPnFBhC^(8ktU%3JgWMjnJlMdRc<=4-!`76;59*|#-=@Lqc^x-E z&lA7Q7`fmTG=TI05kbcA7c+gka#uTbb&sy(>aM<}i+X6eC>!_3k&+D5;aiXvRJPbJ z!%U9XYZ{0p3tQ2f=LT$7uFAS?TKd%%nz{^pf3RHKfhlP2|X}Mm|VQLcp zIvoP!t$3s5JCtjKQsz>9kIRTo=9jptF!ZIikz_n|V}OI+nhZTZK9DMVdsh4?Arb_) z3TkWygfW7#?+vbH=iwMy-U;hId5Vr4Jb^p`Ij;yo?Pi>%D^`KR_YUCei2oc^)1GZhAcpx_+h2pTaOMBT)2{nehe zz}~%#9A}%nI$1!i`LA(tZg|rNB@PcT&|p%Scdux<+Vuw#F)SF9dj{{p!2kj8Z0CA& zd(f#@i-6x&p+@DSOs4xbRs>RbpH!2`1X))NsVwvpw?^uI2O^-I0~r0YRTJ8yqdT`%b} z)HY1}c(|~&tds1dg8ns}I9x+)D~J4aG&&zfCr%*9^?-axj&dj9m~gWM&FA*&!B!Ws zqVHEGm!(f{=;WL|ID9}8mt%5cSpLZ%tyLkmq7>k4lxR!r!?o9#Xm#p6MP^z&qrBZJ4R)k`ob!Nx1vI zMQNID3%u0BgKP;tclFv!p1jL}&^KybN10h^IFzL%r+aWE`59Zf1`B7yxEg~v+iahI zd|SKD_ujWh3Dot_*6Z}}cjOTWNmphD1s!xMw)?K6vm0uFc&ee&28#C zKR_kEQmW8o;GJ^@1iy}gGt9@kHvVhu?-^!~;} z|Iidvs%=o@A8)R|yo4A2b!D)m-&rstv?MO6$`OY-q5GWM$2DZQNykFgwOUVcQ76ji{ygqimQw7yv zx-d&(zITNOZg+p+_$-0$_Oo$7a8qFtS8V=i;jgDjH4!eTVzq^Z9n4K4F-_gzGnwD0 zuLJ3`MqEc*G+{KL^rX{>APt3~E{9hmehSmNa38F>-<==fAW*_^ zJ*}k6-eieReH_!!5oP@=U}K=kON>izc)!v5r#}J9g&=qWsLt;R z6!}xRnvX{1#uV{?$s2A6q1ZOXz_#PX_Ix;?)t|s%W`L2csHxxbTXcWROdM%Nafas~ z`d~9Xr~!PyU73_5VrFC3$7k1Xhb}nF=spDWt%70vGo5Cs0KaF(S0WsA>Aj+Xo5v_O zB{(q}$i04nEHGp;l~@OdN`pCGdeXJ;O9oEOZnAv;e)C44C1^i;vYfJB%~(rs@mURb#?R00cp7)U)l5YzTY|PAA7d4K9~M}!0xES) z73dmOW(nt1Sh&VXfTSRX+NMW77(X$m?hg_pd?E{l>kIOb`dF>#TV$izV`7#mh~rr_ zs^H15;9Umx#wm{@-|%*7y0WUg`mRRWU~TyTv^38Y<;X#SOcQf2IkT?>)HXYLtJ;^F9NST>tS;&g@0ldZ&zzDxDD&L@EWu!|TNi`JC5wjbe~%p-u&_Fzn`N?zxM+-eT-+0CyZ zGr^Jf(XA(A?=v&DlJSyzaX7w;G{b+Flh7^~0A@jQh{HK0;G6Eq z)L+t4=i648B2WlX3IR=R0Q#0~=Bp({Xih^y(oAVfH1QZotObnt)yuU_*UQ$GP>{|i z>6SqNoNhHfFpM6|P%>H340afGqM!yzcH?p0m4lD6i==YD!5{wFt43j8t(+uM-aAU*4-YTb zf7+`vtbx0-a%&16}5-f`)c8ymHK@5&VPqlJ&~b#@Bj)*XstQfC)*?b%I82d zfgz2?!kmQq71>asFf$jBnX}qYryBT`0-YRl8y8^#3fSVq31wh|Z@u?!z8yU;cYAKV z4nky+llfRdlV5m{Z@9InDil>;DE@W<`Hg}=od@xqh7bwI#{=06UYq6+bKUp(-Etz( zk@4V1PZ3;kz_97&)R&LfH4ZWn6HUu8Em05C@p@XW)R|%PoY-0tm{Be1_B|N>FxthX z%vBIdN%|ml;N2{NUhAf_rdqbAyRoI$)I$K9<|a)1n*Q*t!y0K@Vf-(o2Jmq^JJFWM zF+#9TLsRmKzEf=c+k7@iz|d~>*M&SLI57$)Dpc-KOl9qj zVsOxgX@7SAz|%I?(%WaK#Z{NEq0#ypuh?J5?gS_h?s&lY`I7D1Tv2XOM+M5;Agp&| zL6wZUy9oj4X(r|>@0H!!NJX)U4SJ+JlL@!A7>uW5(Ff$*0Zk`!I9VA?Pct_fs*FJq z+SCh&BRDttGW`E^&q_5Z2|P4;8aM7(33L>R>IN$k63tZOyy7+$2@>#cGE#si9+;&6 zU`$Qkb>G677U?i3-JsWc z>{u!=RQNlA;=_mF19rU|ez#wB>)+C81&dx2Sznc9B(+Ho)f87q=ljti#MB&{Ph~kx zj)jmQB<;e>0wA&Z7DV##hJyeQ0{Y(@m)T?}Ar|o0p8^xL55{Ggu*L+LL%A7-fOCB9 zkZ{}9M?rP@H$)h?XlB_?;NLrZeLUo*{R}s#%YA3NC?-K1NMgNpY7vczWYaD<*W++bQW!W>2VUs15LJBW?IYgbhYrz#JN$xPmHYPH+gMTFY6q7nrVOX z*$0!UL!YM@*?M;SuC-3ZCthMf5S(XA@UfxW*kcKV7}i)zObkc~hO>^1u~^Kf;^M>z zWX}sia9r13WBt<1@!0VX`S8fN57Bg<`a;8PH76S`>K^sR}dYa4;9OH?TQx zE?>*WfFe5kNuv=-Sg?=$q3zSFn|g>rzof_a-g==I4H$96PiCR&MKkaxH41cMQjeC_ z<=KjPiajF)f@?G?oTBNvyps}GvAgw@^|YxAl;m#CvEpR8Pj@$};u!LN4bnEHUg+|pe;vF*O!OgFCrIog zTT;+7YKU(ovjjpA2_Jv_a=)~RvaOy(l!C+$4C0#$LR98HPh$oNU)qA8rM#DJ!L<1| z)UcB-q+}>!HUbL_DIZ=8Z~lIBw4HYnY=o6h?2x@0O|bchgD^KZIM^$9+#4G^W3r&` zWH4sVp$WMUMwpf>U~zB*Mm1P?sE&qCyI?Hk9TFD5rFgD8GHWlN@3oy}`|p01PT&wB z+$Crx7?%T}wK-mEtUhyMTOpFayYW$uXMb1jD2s>ipnC`1MY1`libRkp({^wYIwTOGI9a!k&#%-N%op}O5m&(NyA%ul zFlNr%fWcgnal%mIG!C){CZ&hpM$*E&A2x*~_nc(mw+_;pzk;Xr{)zDjS_8@+9O>COrqxqmK z){FOlfF;^EXTZf?j?a9v_n#j+5qK(vGpma>%Wua}5@ti@Xe?reY$)Cr0?J2J_Lqea zhbUy;L-D&N=|0pabj8sL=*CTFDoY-nCRi#4HQ!VO>4hQnTmL94_&48vsMb+IK?of$ zA^*TdUo`eJQQ>dipK4Y}!R?2e*>qjH+uM1^1bYh7P22usGhv>^j7<4x{?#LkPKxh7 zl1QG46Wo1;yC$zSv3{g{udZ7#LuZ$1CD1jorytY}Dm?{Va z=|_1>5X?2HwHLUvIy=%bky2dzBw`~sHm7b$NN9@-8wJvsdxR%QpZRP4s5;o$)wJ`g~#5jdj*iMu(x zHvhM)vG84`YcRWACn&{6<+Sf={_V8kF{MaT-sdnXJg;W0$Fi!_+;dL*!u0rse9HFy z`MKg>i$=+;PPP#m*!JQQHcK-L>J#CKB&E2(~Ut zdQQn=gNhV;NvKENezgEw#cv_s`s3c4@EZ?~?W%p#CN12f!eu-n5CJXGt8!yu(64-j za-94M+^VoFlhg@}89z$)aHVD7+Y5RDaKO$T*q6k>9R<6%2GjQr7djCQjmBkwS#81t zp!Ld~vah}XKtNwTc6`R(wS^T*S@n_Kbio&|&lartFqs*iC>(su2ml~>RhaNs00Fkt z;#b8fnKPD#Q8-c0(~BOvke7}xvZgw5I1P(E3ZZB+p4ipf{@ynmsvG8SSV17D${mj} zZfb#2?v#)=xBTat*0Ak7lUqrU)`wDC2FHX8M!azaqfGO#b~u6) z!71@njhr`jit3Cl(D#V%tH1Kx^X_pYr>Dm7^ zDR2V&-2v0J!MbHfMM*W0B@iD<%l6&PCx3&Z14=X%P;4*&tY^OQDdvMjA`wxk6kqp` zMW(=BGtY}3l9U42SNj(}RQIkDCbX!xVWz~S(Mec8*O3I=dSsVmiw>b4T z&1O-8!$+#f;;_S;bSBJDmuiXi>ER7l;3x{qa)sq!5W0 zImVcmqrDzG6xTd$j*EMxkFsi~0l&i(rToZabi3{@NQidCaWlK+;OpB*RaQA9Cwd4p zAXX&~Iv^sbnK&OS~B<8qGu znyx%1RXcy!=idrwJ8hyiXJFWy!9ET?8az@3J4dZ6T<)e$HIwRMG#}RUjO=7)hEJON zO}ne4X>pT5CyPkjKg9DBPw|e0A*D4#haM4-A;8I^{07rmwnp={K5J>WhxR_%XAmgJ zJnOhV{g+gFb^7P5EkxaxWaY`omc+QeS04WCT z*Eorh#8eAs=Su%QTmzPD;A_D_P6+yW*XE+v`i#~TmA}C>1X-Yc`2u9Igl0B3rb6Yn zeJL4=dd_VAG5k?QtgvE<)#snQaDdi7I4t*5mzKI#`3^!gi;h5o`b4ZZPOSL_-iZUX ztj!Qt0Ar|rO6?~gCTLGIZI&F?J=UH#{IJf>wA{Mm2C!X4FTWqKza6%opXQoNao`P2SP)JkhCMCLVj^!>+uQ z_$jeHiHLXiGxQOCs#&n%#cU*(v8y5z7P`f@y#Fj2BrWwkD-Zd@EbhVLN?^KSKKQZ@ zuL}2YILggQY|n=jrcG!Vz{8b#I(57j@wsDN!$4}4SUXFg3Kx^gX({mkQ=eOM+CFc3Yu1xjp zAA8jp`#6$rQSxrS7}DFYZc$h$QdCQ9nBmTmPKj2LxYVPpGumsLNuHhaPDMt$VW4*A zmG&$wepk#6^f4Djh{0+6=h;xFG*-+aI1T(sgf>l>mGFb;LiUB+;&!?aZ6HnN^R{sr zE#Qg(fiy8nM*9hS@;P4=!eKz>+rvfOTdkAwLSMPCA{u{qS2?3u6^_1}I{qj8;At2Z zq+wVZ@x7c(M4k*8K}}y%`-fO>>Xh})yT|Z&3mi(-g2AD)U1PG{D}CDUIa4bOZxra< zc~s1B=4kRYUkv@dHXzR{IXNR5?3G{Rka+Jpq2jA)62als4IPkP3CQ02JSd{dhM)b5 zIhk^%OGv!D5`!DSp}n>>Pd9GaO&;u%=ZTV&MSRfb!x%_bRYv=G0gz;tKK=y7rc8QL z)JJ2%TT;(jFSlIOfOjq2?T*ZTqPq>Z!B@$-m(DQlxRH;qNyS&w;t7dZZ`^aa)0S=8 zbmhfT0k!gTYWhL~y>`$2B3*u0RTM}c*m+lE)~98~q0;U-!9dc)fm0x^i6-G7A4gh` zQOY?66`et`+k!fCf&AiUGU)-CJ?)MQ^JkOhO0=Tl1gc7mPRm#3-H;zax1nF57d#4P zCU5PP7=jmJq1dU?ZaiDOfENY|pgo8td!2SGa*BL>$X~rDi|~n5Jcz!^oEk3=w#Hct zr2Y7jbYVHgyAjiC3x{g)yKaKU|E5o0e@_j|Fm?GOL6H0VyRQszSPVMJ1U=atFDURv!EWBOtTx|i~FOkNw zcLcz+)TSlzU(ITl{q_2y)=f@nlel(=z|W`uD~xRV zWU`H!LqC!LBX|w9fu@m4#DZY_(YZASUhVzLd)p^3bcWx~WSq~E57WL`<(PWvejST5 z6d>i+KMH9ViXA2BKXoFPb)Pkt$g}%ErFTuQ8N6oNTFl^KLD=Y2I%eh)mKi zn~Jo%?D4QDHOlsMn^u%iH!u>Sj~5%EYLS0+gglzQIQI)Pn!lU_oA5b%xc!-R+55EY z-LG*WQlLE-V%gga?LF$vidyvQLk5sn527~^>(18YB<`qm$q=$$9pH} zZ(2R+JXw?L@481bhIF8>du$`b?lu0Jw>*q5H|zvzBHEdwy?j4^_PWz~q60|$jP1-G zW`7Fg%tbSLEba$1{7Gz=zS=#_hl{~ERSlHtioZs@_maoKp^-A~3vyaq12!k6h8WAs zI_>jNBV~JJM1SXJ_-K1gL#wX{nnwVPv48R6FhOqjIAuC4h_$?79_sFSH%<)T^S!+Z zOz66z&ZV8)oB)8k!s%Bs?drRrY~~xW*i`dp?Y@9THzoPd8auJ}OWkU|yf7)`4z<|S z)s6Rpg#)5fF@28M1ex7GF1?E?eRT^4BJadPG5L~+7}4ar4r7Vdz+HA46ph9qzYN7h zwA_`2*HFUgqp0+W!6wA=^kB|c#5OqU(&-;c3&Bu05E@eOcKWU7qp;&!H^e=ex-H)F zm!Wsn#As~b&}0A;5FJ2`thmLeE8oY$sd~x^$`f&pEMlO9qQRI$S=YE8h^*wZ;unB% zxmOm%a>2Y=@yFb~?a9=~G=eGUnPE~6_!WS!1c=bSvG5^FJakX?Du@q zTdfl8-jXo@`0KcdEURi~W`4L{2vqUcJ}lD5f3H5n#Ss$XD1t(U-HJVoHlp2k{)2jQ zAx&u-i;Z2fJyMk%0%g=ui^>aj2dro(IZzP%T|ez!^9*9ftd_4H3w@W%@VZBtiZ(xT zBKm!WiVyYsO5g7!V>dpwg}04Khl9c#Kc~ zak(Rrr*NDxE#`TQ6_Nv?Y~u{S9#`MhYBOUc34vwea7^Qv5SCoI!@pNy0OE9iwpwoY zlRON9kU|E3GA?V7VYGU5c8rmzVP`9j3KkG3 zCF^eRcgOpsB8&cW>pw?R*XmcsP-PIT(yBzn+(r9g)P~Kgm!)0# zxrOS=)f4`*U!zSx%xYg3eEwtE;D=&BmfXgU_ZgnG<+nSXatud@H>lK^ci_p*#6ldv z6)%nW_zc^nV~PGN(ZIB3*xYR_;U-<5L)(qXt3Yux;RbEgAGBG@Ow=*Re=teYnhBl^ z->06;+RsS$lV<@Ott;@YSP4q}`VK|}7A_czCpO*4#Xb+1T=;qH!Qx{~_L7Z-xjeTS zpnEjP?)~l-bv=>1_v=Gm=;goCr;$piBw1dJqqo*qPq=E}(83#|4(;}kj8T(0B=$7Ow5HxyztkL~+g z1gywIKg*&gS{~oN-`UJDM~+}hxXry({%L=WY&di1D(5Z;RDG>3GVC_bN>3()(TG5j zzE%SfFR(PCDji}rf5A{=N785)>`gg z;4^ZBY4eL!U8!Gu5FEcEY~7-SD3~!a=PMEF64&0)Shm)4Go(-nd>-o*Kpa5LfXLSE zdcb4A8+P_H+w;4H=ZL9eMFdz>+MkgY#NxXdw$(^b46juoLPEbr-gF27yaLwY?97+C z#iCpQwkJ;^Lde(7kBoyulvB{QIw4w@W9}&R5mm=UvZ5)#1%bmvxI#vrEflse=efZ8>VASNr--6 z9`~RpkrhSSH&1VY>cn}{p{(4s{3L@qJfg^nqZAxA_m(;q$u&IO-w7;2WiN;Q2VA+y zG(m~L*|0m=n(}acP(R(OyFj0|&y25d&sMYpN`&F{b@nJP{6`i!y70%RhRK-{9>3TO zKs*b~CT`P`O8p9uK*Zntq6Zibm29sr-5`c$5*(cVPe_yxwSr|p`uy=47v3{5LUZKl zL|~Fz7%7xJPei|l6E~mQfU7Ss8Pd|C!zzfFpbcJ)sY)}=n33b`MuGGxA_VA|**v`` zX1k?z!wB_cG}=>z6fd_PZN*scHJABKC`c$4$!TpQz8Ml{NbP3=-VCj+9lft^RV4sb2} z+qX3w&kI|UlO!caCnre2GJlUXt@a^(e;HlhZm&ezdn&4IfR8cjG0Mqz5n|ySO+*s{liNf~-mR^SM^L!FpJN@Y{r6!kd)}cMN?0(%7 zwP>z*Fq!kRi0oc($DfS$wUUaR8L7gJX|<7xuQbZcx^JsmZhmZ*mOgmnK~8`ZzE7!e zCH$J&O_Gz}L0K93v_9Pe`Z40^yV+Z>CJ6?hky96EuQi@BdWj(quQy3Dk~^C_`KF!M z&+-KKW)dgWjek6FfW`V)UlD+YAvQYzhIFH?~5azv;$ zvza9p6ZMtN9h`jm9aMoS^>%{MoQ|qP8TC)Qbj=MSy#hEKApB*g4z!3YmVQ{+SF}C( zJ>0mbpc+jPipAC&_I?0#R5<39JR^}Mj9v15Gv$QG%J6JYVTwvSJi13T=5o*N`-^)Y zZZSiL%W+Htn8&NvmPNWPV4D>&9{2Z_fhTuLa=gtRnAD9K_?`xrU6eHJ>NEfYs8Lji z!lIsRm1L4w@d-^8&*Y!jJfKd5pYZ@jR`=$MH#+4d?HAwGuNkX?>~De z2f|QLRV-*)liNE=`}B8t+0=6ZLx#M_p#rO)uckO46J-&%r(-r_0#?Et_ zcv=f1kNy5-?s=%9O`($c?0f=C8o8v{?QX@C8Te~8E?r8TPEC`nOisJ`l-iP| zJ7JCH9krB=gQIwA>*ZReco(gTTHKZZ}T6>y8t5jyI|yPoP$j z@oqXBtFaUO%xHhJLlmMsUr3{D#q83vZP-+~3EeNo0OZpl5rNIy^d5_S%k>^k)vNas zzBqo^`_JF=fUM@&t}%c;+FB0KqY?Ba%t$C!`FVcyE2Fv3`^Y*$>*eL>Ej5R-xBJ)- zII++QRTL1))M6LJWj*6cUBL%y98VFTYKN_PGYZj6>s@(D6OvfZjRkMLumBG-av+yR zfllcBQfb2P5$TXYI<5!+fC7a59;Ul+<(6z*)UUoRXBw(`dmo7na9v(jMh&7u^a{+u zoPNz8`l705vF>d6so+D2g8~OIjz$g}^Z8c+1W3IzMzNzKe6?g{0q`+w6A{$TPGO_MNvFG4gr6490b19 zrqpBuEm6Ih;rCd;D5n0d;_vZg9Y?jzMJlQo+bAfePHk78IawSsHYX54c8vhi-Sb9YvPqp+Go~h?_ln%)&|>%ACu7|Hh*9KxOE8F5OWRIQ0|1a2gPMZ1pR8B zNlK`Jk@5{I(;tDs5t)tDsuW>=i^%<%$LIffadVN8N%X&271b#Gd(O%NiZzOhY|Kg2 z(8Z-b4mo9^U`+T=Uhkbs%4w!3oE_fLA3sH7 z4Y;0!lw>D`2CE^oC76*nbYpN%B*-a1Dc-jwU`|aIy*xWx_|)Wjw&AoFkPpVwikfR@ z_LE-ajD^1q?^Sz|ih~}B7)}=6C|a#ZIIiO!e?2BjC0ls9%yx~qh~!En%(d#`+}zt| zmMy)8mFY=RRn2AAVE|EwiE=oL&ZGNpoOH1U@Nu6&apxD_#}}R@+xG_8jY+$WNm;?a zInsLVNTWO}eK@Aj@cHA@GF7he8=DV^bE%uN=5I@c-`EprAUJs}4CKr{B`4TOW*gz| zIF&rG#!B*Ik@^iQFBfhIHi(l}ZT?%y`7?lUCQEgM>ppv;|6a$d8uOyB*`wuTl6$sR zR;%DT6tI!z6(w*pkH2BUeV2}%C6_?Oil5%0Sq>q$lcZIX#n8-Vimvu0@I0Q#w0PWb z`Mq#h?229!pLX324G3_7CA}*~qj8njtm_hPUrOCNSA^7i@U!FgCxy%&_a43Q^R&5R zCxk)?AzWliePU!gk&{pIyzc(xt?OsVl--_4e*qe^X%^m(j<&qdYR)*X=?I6DkIb$& z+88++bnWOJ_7NDFiSqq04|qEmWDKCIYzV)~`Ta)V?dDxH2nmqMwstj%hlINg73gev zSIb??z=sS+b0_(fifO${Pp#o=!*aPU}5wl_riIjP{!*5rO3T7I1r8@=cOWLiR@8SGQ1S_BR5=rd8WEXHWZX;c7A{ zpb=7AZr2sQqYwl4=gXQBv~s!s#_PSV4o04Qhw^ZS`yE5Ocv9QH>y7lsb0WHd>)$+hc zI(Y}X1yAkbN@1I~j^?yuv|3o;9oG+GJo}#mswt+t4}3^4HJJZ5X8Iqs6d4ttx#d@L zOeg)?dg}L0|E zh|I-vq8M4%&bhz#TG1CBT}?Arn@Fj>g`S4XN)lK zJMNU0=E{yosXZvU@|2%*fp_jIWS5sqS~^*2ZbmyuxGTOz$X{6ON}47H3u>m_WoP>X z1yL;J2#Da9d%<<*o^dj>_@9j?-hb+lcOT-)bE;hl`>Lx^^C(E9$e6?lW$yu88;0G# z{SfBAea&YseL}@bokxn7$z#C9}EgC}vhXn>UFXIi6KL zxbS>2jz(Uie^aeWW^`17${OvQtla;{j=efy-Yqng3X*jntoxHawrA2sapHHvnTq-I z@9&$vg#|!8C&2Q(WRSRnLJ(^5bT!bM@BR58Y`Y~o&0varQszl206;|@D5U+3ic>fL zyn|v77g^#zojuLJ-1`x+`A|SDgyP&RA~{ROl;_#*hkzR*KW{#skX_7YB1=lUVC;L% zK{z>{q(7kpijO8>Kqw#7&%>IVg5!23kK0ry(y~#;RAVdpY14%dIOS zUTVWqoXNzYmLcq5+2bYavNyToB7Ua1cWH?M4|pkA{5k1*D@H`RXiqx39TWJXDT{P9 zpY9-v3>FffoqDgqTT8!PP8O}usk{m>g!QwlGVLy2~wuzixV?iNu_WJW)BTlwt!kO-n+pY zwKW0fcGyJtGir6mtH56p5+C?6I_<+3;21NfU~a6qZ1L;a*cL#1QFXMkRb6OD_dBM66-I}Reo=$EzokoXT%kx4RGfAaE1OQ>HRYy2w+??*w{2EAS%ZJ<&@g3 zfiAb!shHGS`g`BfViqq5Zf)lRPE20+I|+d*NI62N4x9yAME&UHYs0g3O&{mwQ8{!G z!@sXNN$NEBE_u|Ia|nB{S|inD#o<5Lg&tjLFOzXVB>9?7epL*cNz@8A?2LHILT)k zLox~^7GYtzeiD-)ymvd};NK*GMOyJm@-}W=zbxV597LYWy*Ev$fo!BwC>j?IHdZw) z5?TZzAb|g*D=`)OYQv%DS|A*#?L4!)9He+i9-U1t$oRa#4^*@Q)FsL8Qwdp0(ax^5;p34B zJRO-~sx%AAcoZTZST$J(c?bx4S5%x=l$S`mMKTs931urSu!Hy1~SbE0-JYR6z+$=P9r{T0x zNWYdpRjDA}7f!+_=gK>}s;*se8zX#v6`4duWk-<+ZtJTn*JRDnNC3^V=qI2-{YDIL z*Ec->*b|W|>$B7R@2|LZI5AhwG}{I!q}&attc?a8!(+ke2o<)|6OwJC!@ehgxP6)%KpT*0fh<*Xf8)6PSeX?Uwmj#roIIWQjT5L6uz+XOHEiM z(4RYOr?f?yxMRGqOzE_*CcUPZ^FclRi+!L{9$nJ>XM4!|Xa3vYRlJAkIZp*pfMO9x zG6cy1oZ^w?J-H{K9c$g2&jA4-plFR4Q%=L1@qJIc@y1V6B=?Q4R3p}~=3%3UymkSh zJ2Qt46D0x?4m@}<K{4xEfup3R)ue_Ef7SSLFpwqY^#pf& znnnYcm2$&oY3bQ})i0Nt4Wz!A+*6w;1wSPo9R+V6ZFpcQWT($hQt-{+Em5-Ic4Cq} zm^uGdx5TZy=P@HMdqEnL)O7Da*=U0AS>^$WE?N0UuW?VChuT0d^+b3(T zB3^o)?m$Mxh#6qoA*p_DJSRhCT=2c(Kg~rCt($LBP=%L0Igf^%W~nGqcviAG>Xc!` znA7H#q%g1??g&;ux)wns=^se~eo0Y|E%Ly3FfLmM8u@Dim~aI6a}aEdG#@+ zc(a#N7R8Qa&&F%9jO(Baps_w0nL>qqdnJTo=CXmwec%D#rbIv6o_(ekSku;~9~O{3 zjE-_YE3egsv@1SZ(upFJB4v7j4X<21Qo8zn^~uxE-tCVo0Zl5EJCWs|aernM%;njq zdzeBtI1!1=_!ZrkX;HmznmZF;ek?Ef(!bx6hwA>0AI`OW$#V@rHQrc#^fDjl=kT4p zJ^!7-;_N(kx|RTnzPbpXRq%ym*@Uhh*n3{csEd+WM@}Xi@w|6_`bWC;Ehf>GToxUK zL_R5JOgMf1k(%u!Dli7#OG%U`QuD%#;Vg%K;%{>8Q6KkIvGG*={m(V0#yFvljxFyb zn+pWQVMvsa$fK;ED)vqJC5!9eXe3NDTEE1^Wj$UWREwQbvr7wlovf3(TVNB(;-*C2 zxG&M1B6=9XHG1d^cnpEdVric<2f=YTwZ9_vE=Gwen0B|DXs4MReagJgyJA^a=b_JJ zn=u~<-u=cx*KPXT4!l@W_KrylzfDAN(anYGBb9Ho$zu0Eet-b2U7jmk?r&1H$qT2{ zj&(&I0O&G7P_?~e9|wci@07A3WfKSV2E_{5on}Y69?g-0?K|$n>H{e%rsOA~t#cxQ zzbp}dd+EB|3A%Q}Ws8}H=(Yv~kpG%3UNfjT=s2Hv7G?eWap%3q&1wb0!a4~JsdIiW zn{1^q6qvl0`RlxSaxxAkE@D`p)yOzke3Re~|Dc$CoG0OU8&*|a{3Ex5=O1gYxgRF1 z(6)HNdnI&dG7V?OU=n1ZR@L8RCUGJV%o9GINi?&lKyZF>%IQi>c&hdQh2*kPfNL1E zQfB{t`}*oU-LoopST4CeYNOCiAEc^4Oq5y8S}9`TWIvf5aMoY$H!%PU@sRupitWnm z!fvSRcC1-}+Y2%T1LF>CzWCtF^dC;@Bb_BEapJ#|Ej|qnC?LeN`+ZNQUB$;H@L;!E z*3zY*Fijl4#QUJDv2j}H${Yr`ER8ucdha*AEzke_z<}!oC*@;@ml?5a^c1ZGyHtM~ zRWJWq6nhYP&1(YAYoS>Xv^mM+?=q-UGdd3&79=4js_XG_-~9qM7F&pqTo0I3d(KH& z-`Bc)*ermmHk^|V6t498cD(NBru@z&fEr)T(axGE;40N^;N8OM6yDS2yc|U_c68a< zW8tUkn_=(abQNu8!fBmba=l9ZHq{PKT74=BGWVD6O1aD@LP!UnXlmLVQgRL?+n$G=f= z^opLhmHhr|BJhwCtte+l$n@wlCd9L(NTi5s(e z9yg}=QAj6k_^Iz-(s~nM6VK|hvvg^{Y{WZ+-ucP~IPk`_I|Wra{zWgVxM%LV9=QbnN$Ops{*J zO>s9QX$Qj3+It~WAjcKY8eZkuNh;NYT=3K`t5DK z$BxDCdjJv`Xgt(U-wXzwhLyyCswmsP!zBM>oxU zJN>h0T)IJTtU(d}t)`U5ht21yZuWzZHDSPyR})gGfS%;6TlSXlf^c8tAwC2XgI-(5o- zS4#6}PS1^rY)#aY7bVb4S!)(9K=W_py|LRv@Cco|_hoXtQw|&}1HfWwJt!=C=VTWr zPX@qj7qX~D%BI0cqqzOTsAnmj$JP97t>&IqYPV3jd9Cw5qm@kIJ(t!UpL=*JOJk66HsB_zY8B z8Vc&>y*S`O8fBvz9Jzy9hVcI`3-`xFK)lWM@$gcu%Ub>iot^A47jYlnC2bU zKe(;IfmlSDwrPu`SU2uqvqhvVCL|IC%SQxRd6I0nnCU7xSK@LRfWeF1S-MxGSj@F+`8p0Ugr3%X*?+Z<)y;qlnz zJZL=C3>oKl>gKvGt=c$C^^HJe>-h>KeEVZYTWQ zQwB1Eq|RsCCf{+>pluUYW>2~b@9zT2Qg?<69?E4$uQhkS{`?Q;Z53<1m81KX;i+D$ z6rhzlcUv=@AU#c?fhIIy79bZ{m-Z9ev_qoC)l1DGNIh)u7Ezc7**v{En21y~^Gu}O zRY{LCC!)LL6TL@T(pHsL3R5Q=)HLdWXK*%%Nm8D!9>dh zE=s#VS6ob4iay|(1fYI#XI19iK{6#G{a_sfWR|bVzB+bdz~yX3vxbn6?9LO=&|`mm zAU28ytsw94a1rqE@TUlXDmy6>v@q=bYpdWZ1EfL=5KlW(D^T@&P~#FYGSSy;vN>NT zi2Rr#-}w{gDkY@($0mUG3cV5cmuoMxs2l;=<)Sb3)2br++nLWG;unIf$RHG|!nQqiJS2m`<0D>12orn!#tx^%;TRqIX=Zor)ff_p43qQ8dwIkte$tjUohZC zP_hULT>aOnJWabfAc=V9l{AMg`jV~_9fk;^N-9tuj548-mXKBZ#w)8hf}lmRqL|4o zy6o0_AIZddpO8R+SDvk!IQ$Zuxf42;m+bEkSa&)<3C}BXK@%(PTYH zMj>G@(NQoBMDJ%pc8;^V>jZpr-*-{h0ifqR=>2=y=iBx!7xJpgu<+f$~*% zW0K#-&%t=+nXvTTubXpMVM;g)KX7$$<5ZbkhR)xo_M)FWmwk1=FY9?qQ}U+VtIqIV z{)`#FfGm9(vFFm0OOyA+*4&u)L}9;FTG;`NRcCVbBUdu+ve(tZKkAyw&QP)_XoQcC z?Z@8~2w6E>AYxKn#z9Wh{HAtZNdd-#iOT-lO?CT~4GDb=IU)tDbc^WyR}F=9&vYOx z53Ra#6XBu{xV=s#BjUBujtR%{$+{}6D8#g@dgo9{2SRZaL!fd0&j)iK=9SBl4Z)|-T5+GT{;}a1>%U>D8i^fss zMQK~FOd0HYU#Ds@2nrbW%MtST+Nxe@reE$C0{XgNRhFs(_1$N*yQEAWF|B4QpizK! z1aAM8pE|Go&%fktg9RjdJOH~jiG{-&0B?)vbmRb5rJpQ@g4z}oTsVSx#8*qHaE=y!&RSjs<>zb=K1z5gLlBtIuyMQ$OyBf?}#fDf;uP zE%(_NAHI04hFTeT5UA!-$>UQ{D4Ey>pXZYyQw`Ur=Gjdw$iU@^-vQ<=W$U(lp^<&o>v`8>OMV`|Tf+&y2a?HRB*qG^L<|sgpX7JhMBqqfb_nkK z)87`SA=Z$pdaoDCIc^Qk7eZFW)1KKRHKyF;J-i|SYl%{$=(i)T^DpuR_K@+1z`vqM@@1b+!bLn^N1GdVapL4LQssHyXMg0cWk|=}{Yx89a;am^yB_%9iRr1PC8$y)ZNPh50CCi3K*UN+ zN?8-cKq?R7m!u8F7V!b0e^Cu4+-Vxli;Xihb9@!;Ki>r-YnL|?ws9U`$nZ6jcJP1s znX6s!mQpZDO+4*h#}BbhuYrDWyaaOfh~DSN)q4v#TAtyF>yS*n4PUGMX1kuPKx7$q zAp^yZDtmZuSWZUJ?gmIYH~7D3dRJm3N;bT!3x#9(6Wi>)duErz7-iLDeiR&&G7;?0 zSg=_4RlPL&CD|>X^PehQgM^r~6>cUTiLb(u{%%os8=&~ef(vNZ6u;QH-xV*;`s$(| z5eOh25b$n3PjO>em;YwGAcO)o*?g)*ZKKMpEF}*GFvu(eiL!f`sDbqi`KYIj7P#A0 z$u;F4$D}J)i`a*N@wj^#cr4*_e|)M=*3UL8n_Zr$EL1#w#MKL%xr4$t%p}~8u1axd zD1|6uZEURYUUnApwRlcu=pWIr$Q92yLlF^Jt``D%6--TaJEV*Ro<;6i0j_HVFyn;K z^CFRsSCGo$d*$iJiSp{eo5%xpR#wXA>H0E4ChvAw2Yyg<0vPPP`&iV>8&BvjA`ZO2 z{&ztc4bqs3KaIMqTP95NwN32F%~sZ7^h0@HP53@-iPMHzHte(jQ%+ETlKa<}xXMaGtVY%gHb5y&Pwc7&@S}%Vx zfHl>Ny=^s6N4Q$KSh(+nQgVaa&{V)XBB2DN0p?7h6^V**WJ^}U)G`uaYl=qZcWRCC zG21@_k5+_KxVl-7oCln1clQx$ynjmE&jNYZ?#|e}qP5CgPq<~CbR{Pc7H8}9Wr;0^bvJZ>iJ(KD?q%{RbjH{Ey#`k%RHdjvx=GmJM%s=DQ zF3RO;zpjRs@H;tZ(1D+DYHx5q17g0t*SpuJ_M0|fU}f^nH2*OaIDbp;d&9sr5wC|` z?oIg_^>_|7T6YgUzPOtl#sacc3KWu*YPP9NoqmxcgQ!@+N2vMOTr%0$t^(W165r|U z$Cw~Xt}mPnL?m{S11vtX*4bao1Daj8>D4}`V*tebc#a5f*+jj`5PAI}L)K>m^Y>P6 zCQ&ldcp&rC-_1+!aUj*}y!tSBx1404Q4S`>$alt6R3LEC&StqY_x}f`T&cJ?(0G`_z7K8cx5*(S z;TUf1=(|ESD>X@juO;sLYhIq$i@}Ta3P}EL5fJC)>tp-Je@>0E-`g?IfzXWwVkgN= z-$Is3nOMcw;!*zI>7QwfAO#|ZpSb4DjNq(V#R9K)`o^Y6PR0S2MgjDF*o%8;SX}WH zl}_z|PQHs9b4f?AJn}3_)H8}5*iW6@IgO$dDKV-d1Z-Sy>yGcZ^!lCC&^C%T$e>OX zz3ptu32g}0u8W#N=Px*OUOB z0;_+GIgt1BC@tITpElATFFvrHR#E5O>YcCQGL%hu+urGVFk}5mrZ9f8Sq~eL6hqVd zGoVKVm8PCJtu~?>nA9Uct^k9AFQXRyyqD<)Q?tm;hz+s3;0McHp%1|4X0M!5UKRX~MXT@Y;DwRiY<C{5^qYPpYO&qQATkh`T@t3din=iWxr>vl$H!MnE%Cv?#O+!uBPYl-1e`Wd81Dxz)rA*GNTZUAU9_(?dT|8%_%Zn){ z>Db%ed&o%qe&Dzmqlet!eHu;~lc1h<+anUTC`rugJ8g~)+1zzBX4Kza(<-CzB#8K- zjYx`FP=d^UcJo#xMEFk9J}pc5X+S$iLH2qH?=ithH`@b4he(0$qjq{*BZ_x%9IMA z3RL$Ym|!+4zON7?(Cy!%Zs4#cS~9gWVLuUid+NLJB#4jk(el-8E`LCB?R^RW-&##L zrRnz4k-uU+064GbWDwTfS!>I)sT3r1$m?T#nP2S-3gX_Gx)b2Vrtja5QLtej5VvhTV^)vIkr2tcr!ZKf!-*Hh4q}1_+BY8S^LGQ zyY2oW0PqKfC5+uR-<}mPHPX7jO!}-W5MyOyC1(q6#!kTz!L$)iy!Yje+`{Wd?Sr8* zVbu`p0SZ|J%(w`yd>Jg_c~f{E=2ayB6>lw|aSsKRwO7)-93pWkSVg5?umiP%e^V2Q zBg0AZ`I#xQK2u+I-Ee&O4+ew^a6NCzsvM@A=Bh!|9LMkuLGia|y${ABTMVbXk}w|+ z`qy0xbY1T}1K#!p`Zm4iI>hKOf}i`)bQ$WkWDTIczTTtAQy#PB#N zuspLjwPlJdi#GUmY2!FeZ>U-?2HD!lO5<*WZ|-+>BGa6HJqf#yv+QiLx-@S6uu3)Q zq=CGq&_jrsz%|o>V>td(Iv(aw2-vVpJ_?>#n2aE+qkK*9Wsm^CJozO(C>x0@5e+kl zG$<2}){0pgo3Og;bSyhL`)QY%|86k)-*jJW(KP3fbY^I8E4g;g`ASVf8O zab36NFx>qXc4eTk>%po4R2z#mY4n2hR zU1ToD{+Q%3Z{|rEY#*S-KmplPbiiJxA(gj=;6Zx;HG_#z*W3&ooqEWQsj^`C;_v;j z#nV!iwug0+Lgi}a)BMQk-8Cja=MzK8Gu~KXqTl)?srRz)>*(XXV>_+oUDfH>#}9{h zmSa$pMt*@yS5efeN*WT~a&v{`5X?!3F+X*p5f6X$xdO-1{W?W}dgr$6dpAJEaS_K!NlFe7n= zzNTK6B_05OmVq&_GETZk?|b|6D z9@_2mk9U_E+S2LdwP>aKGW&qQ%tY|jp^ZeOKJWs&Wh zt5A*5<1W9sP04BdisEQgqyW&B_Zi>+vrJ^Dzlv$<*?X>V#TbELUiCg`@lm7xdXnbr zgB5ziqknp-FoQ1)snju5rFptsY&d;dr*xE2hcBUBts753sbVVyYmM9S?P!m_>$wtS zY8sui4qp=%XWS$v4*yJvFwjy~85w@H{S8l3@}eN3-N95`U?JAKl*}?ZS8}ZU|0n$9`z_js_*6#2@5VB zX)L6By1@yznHU3@z-0DIrn>ZBZRqJcr~QL6p`Mnr)L%wI zLa`vej|Yv07c1sOd%X&KxUxW3-r`D!%q~67sO3Iw-f`r`v(D>c9@NLnV{f}WE}zp^ z;il`Vw!dcJmXNty-2LF3Tj^z3=1e3DuKGWhY9I4Wg#10yKd8cSh-~VcXeIEkgG{~9 ziBQG&%gI_r=f{7+Ki62Q_fX9mA?vyC@~hoJgo_9C+%_M${!tw~s|NmGiXI zMXKaF#i)rQKYZPkAPxo(!viO-0K)NQ-<4+Vzu*`GTDBh-uD!dhxgWQU0x`&JnvaYd zGPO|>+7y=A;1Y z%#qWk-Cu~;RFqj?{w&*dCPxwW1GzU0`Jol*S;@T6P{K?m&>e&fO5~hW71!lk__a+2 zWO~;=64!s3N5EBf_h3VZCgJ;SH(LRnzWQH>rDHKM4>fO=nfBj6@_DB$de z*_c%GwAb|@3jS7lpy|MuIIdXf_$#jZ07N2_9S$RdKmYLl=C{S+azTAOG5_Ou5>Lg=ClQbM5B0}rq(FzXTntgHBCgTpnvS*|$P!#{5NH;naV)t}< zoA|}A!2KbEZ;;w)7Q*FsT+wh2c4%}ll}o%&2$7Jo!@^LTk!rG(EijwR%LNecNn7m* zaN|NlVwIhH#N8o~r{Pg{eUg>&zXBzyg-I2G%)9lP%lGB|{UIP1SWrN$CpPSSv-X;) zXEEwSzi-ECwB~|p-M9}y5dgdl*zex$aT0)$KgcTh?)VY2W2x5Fy|6NE&x2Y_Dg|(>X9VC=71Xx(Swstgla|0>i z@o2OX-R=QdXRnK0ic+5~g?@oI^e!I$8{4YvCrq}xWrYWMrr_yE7s|lwD2CLzBCnpQ?s^0QgMd9p zHu|ft93PM{&AuUUEa0Pnr`r(F$NT5f&X<2*6FJzBn>}oYAgcQAj(7_iCX-^4mHlp4 zLu4^;AW!48`>dv8xR}Hju8OI@G-+650R<9MTQ5ux-%|Y}$J$W4$QRw8qX7cDCawDNf+mQJm&%JLxSccDS#q&t zWHfXiq^fZdfm~A^I|<)BPk>4$MJ!lAfRD`jEj z<0q>-Om-(Fdi-Ef~aM4;Pj-QL13ksiUe7NxsM<;7T5b*WZL1XyhS%DZ^? zAxUt;V{D&-cET2=ox@+x%kStCKrv+k1%U2Eckw+uU>Gm%jGnY|>Ivd zY~|$GEDTXr<$D=ZoSt&!w_a-OWof9Dw$;wD|L}SU$Je8VccSRafSKu3>X=EiZm`6Z z=etYBA-s*PEe&xd-%#_0j-@gbZArDkH+ME$7!1V@+yb- zS=Q}CMf5q!y7#g;8lZq+Vrn$?qcdIvD)HGn!IrJx1Hc>lkHcH|HJPRC$}Eba7bgzE z4blH*+*vM_6s;1tYvOi3_RD9o@VvV;EB)pW$!PkkJN~3;%Hz6w0rAk-Q8Rs!oVLT4 z<6{_)F~BTJ3^ppk;LM zOpnvfna&N1Kfma_63$Of{(qMguM&#=YRRikc)8hWf#>4L1`HnE{mN4XNy|2gE09(w z_OvZ~OX{1!Me{dh=13=qiRsfB6FgM?OMlukHl&=L;`c=lRaa8S*RQX&cQQkI$QMV( zEVh9#sCNSOR5{CUk zdTAWqJyM7)?~rA8jo$BawLG+0N~Zzu`!#q8jz!A8B(PbcN?A5J{W9LF*udHHzcDlJ zIgcG4CNT=qNX}yAd9hY4bdJ}ZGzOV$^`z0|Rjo&zMEc}C%W*!kj|ZvZhlA8{+D2T8 zztE8b*rGJ;f}(1AjbZU>6aYpb;e5PD-?HtT+#FzjRT;=&QmMtwUjgKj@%mbXM?7cOg*I#WN z%a`0^0~hv@fU~xrzF#j5cXd6;yH+j1=2~`~OxeZPgy4oh#o)Sj_p3PV?%L9MM_Z?4 z&WKfX?!yp4P?Y*(6ZIBbot3e3tK}$Oc~%(NMB2{fpr4NqGvoJ46x^w~q<3)jN04kp z929<>6f?EBb@y{9JU@^@U1seY(;^S{E8{0#98t|*N>)?}-{TkEiVs3MT8&3vTaP`~ zaqiaqB`W-8R~c-AJCmpUUU9$ufq<+j3O(gdviMzUhz`V~d1OE-D@T#EYTU%BJfMt$ zCD7gCT5Jp0T%QCRKR-tIeZWpm=V(eB?=irIxS-?ch&U^D)>zhmEdvw=vKTaq!uaRS zwqrqx{--aJ4K7fWS1@M871!}bRN3SPy?*p>lO$=W!Q9zs z^}6$Gwe074mZ!JDA_kw-rIOc4v$xRmw+rHapWXGy(gs1fiVzJK!!E;cwRiFl%Z@PJ zhaOe^yzF5P0ub4dy}6o>aqgl=r04hY8TY>=TiT#cs=hrF!4i)hUb`K+rHYu@K{Q4> zBtsSb)c2fqi}Lmj5@xHdRA~3_l~5tc-1^t-N1iMUR)DT{IvFg~Zn=~FyU0tk8P>nSx@&oj z3lA~Y|LSB;_epnwc~Asmp^+a*kz%bfAX`=H&~w?(amjJSlO|dF-|e5ll!k@|)Bik9 zg^k(646nXtJj7x*E>c9C!ycU7LD2m1zCPxq8(fO4vNlIj&f z#RMe}!nW90PB|}pm_afYR3*-dic7P^Dj?q8Hom7B*C0v#H|xe<=EfqImEb#kpCGPa z95UK0QJeL$1_MMEVZJL}WWU|n=2 zBpTyGU-(YNV}q87mMNaXHYYIqR|J5K#bNNfz<#B*%|KW;0@4sTl&y`CR9>42_Kl{q2fL18lI<;hSmOXtP_X>h&qnRsO6f0$;>#}$G(89U&E13*p@p4$exFqM>D73k- zwEzPX7-a zk=;K}^gMBEii9UNzkl-KAl2)n@r!THQ!@YUG=R?>YjIfo#cFS$n{lWj;O3HKvhO$d zmaSAt7Od5OtUED1J-wuaFLCDo!N54u)J}VJL~kf97RY2z81qS@ij24-E6w6w=|dXr z6gNOI3H0(c0lETzxQqGgdDSbvwL5~w+fd#Qjf53 zJ0TJQq*2TtVhF-|!(?55F!3lJNEAP{tute#(3^s_jS(sp1@f=;H9`XfwkpEK8OpCtJ9YU z-v5^(s?57)p*s^7s@X^ivqaPJ!j?6DJf#CKd$iuru2?izzr?Jl8Cu`Vly65U^VI5R zshUcJQ1hx^#m=YR97fCT#XTNyfylvbmcGs@yNJZ2;-QUmDbnRQI5rBXuKCH~;kcMe8wthT3n4xCtr)kZVi zEcocaek~*r;=Fh<({=QZkJj2k#F%lIHj?qCkFYd@280+1zwaG>w&(LGT#4ijk>ckU z0+^?zWm6)^XEPL1#5KX_vzs!r^&OUGCHJ=kkwOlY72?=)`$3WIUD3}=5H>iMLr{cY z2Wuk`h>`kPvUZ*!MB^ban}UK& z-}ScEyH5#0cR4dfazi47PNa5JQ8flveiF4_$x<5w_CkV=?9V^Uw(Hu~v#_*{ z2KXRHxs6efFT{XFNEh_aFZPT3y_5@67svMkZdcD_g-C(USNV#vD4h-?hjky$)-#19hXhCb1^BI&*R|m2cf;@^BK4G*m^OiiklH7;punJz7e983(~;g(0rZM z&W3)hG+^f9A%@R8l|xMk1?3O!Wsq!hWYta?0u%9l<_AQR4M+2Dd^>JPuZZ}e#kNt$qFo$9GhQ&V*^{Z0=lsX3St0wYzV^S_i+Z5Yj9YTqR* z4iJV4c_n5(O(teU(8gVl9P zFvZ(hP2J|L-YZ=u`he?F7#1%2a!0%L;q*`!3Y&0`EVf3U?9qh4OiyzAXPc(Oq_^rp z=ZrO$(6+Ik{$>cl^oSM!jj-OFWElNZ@OOV0FIFS- zAYLf4gL)S8)Tad2{Q3DcbU*{X+750h&AJhj@2!g8r1hmStjj0pWmY(`HMxyI~Ue0IOR&-30WGKDcUM>+TrQVT~(viLo zdPdQ$J^6f=!?0A{Tc~)|U|-;O&Gw5=9?$rMYU!x}l9w-svi)4bYf6&CN)2U_#Bcf+ z?q|!5-`#Z8wqgz^qJ!qL&CVXK!x#G*;^{2p`Y2iKFs~+|>CM!+bGV#3bJSsJ| zM6M_Ks|gpOt48fjRqg%XM0e=z%`YphF`OJpy-{3=J|;>Q&6={Y_*Md1Bv&DHhDo z5!>d5fMK6uAVJ!7zwsP9jARzp$Kfz@7rHdCnXi#nJ@NTzp(!ubyy!59I^aji>naYS z=aL_0+@Z47iN05Dsw`Gk9G;}lX-GUhD%5O5UP#vO9W0z*bn zz_cf>;3lwg=daB5&t~*l+HaREh&^O|^!%TT2oo3624>d44!Sf8x*?F%sY#?&mo_gE zAM8a^vwl8baXcMBU-%Vd1v;;k6WIBs9{qgg9$V+|T0{?;+jj~gc}X&-4s>^qsH?B} zq!Q7ix2w*+3soEcQiMR8*_ammGQwE|m6XDRGZb++p1UIx%NTab&mLe!O=8Ofz$=v< z3e$Z3I{VU|DScHW$!y;iq${K*WTcwS<+Nl@j19A7ux`rKRJ;1yX+nxY&OVzlKcKTM z4Nn(Cerx-e+hO|8s#D4J`u=Y*uO!L@zLufO*>d#xp?@9)lo=`s63~&qqv3^60x!7Y z!+UFX`4>L>Se#HC-9vB8Bq}bnvZ8oJ6E&uLjO^0}IlxE}D5sTDxRvC~{IIJr&I9#; z?Z^9DsWC@pIf80i#^R#y4ub;F-x&$%Hp61 z^MlLcv|B$Xeq>^w#q%^74}`1c5#hi5WVSbEab^F)_8TT+?W_8UddIN_oz7B`DZOA;02%e>m_~cqt>`R$@Fg3K` zmcX9faekRFsIQfEChS02ux5+H@vSfE8UnHk|HPX@?9>AxFf|~b`np?A zj(?!fgBWgif}#eZbE(!os7GK>M*1Zxf`Y>0tR){^Z>1Knp{TBYn;!o>l@=pg95~OX z!8Y%N7x})TK!xM0K}-Ye&e^pn1={2}KBDGH)`aq@Ko0&v8pb(A2cq8fm>H5n%Jmn1R8zUjt4`a(jRuD-l6x5yIZd0 zpZ^%T?=pE1=%Bn@buk(e#XZsW7xY>6E1ta~E3b{lZrF0sL9>wCp~5UT4GZ#}9mm}g zN5zB^j{O&MYSI_2Wv!k>O5>3|Vcq zq!m-rujs!Y*mr~WmKJ2tsSJ;CQ$&pP z`lI?)LS@0p@7{HZi*yq@|Gp*z;pI_If9EMRBe@@FE;9caO=&~==F&rYt@F(mW?hyQ z=y^ehzCXCQODa!_O~*f(7Ra)+Ass96&y${D$>Qw8=e2NSk(6wa$-i0r^fevY>lQ@VCkinsWHCn_aT(WAJSxOFrs(1;5$9a ziX3L?_E6y9BOaHnsE>QQQF(!S*x+3{1PXT<8EeDqSt>Tq4Hw~!Ru3T%@5%jO(&&BJ zpNYQyD|SD>nCWAg6|J$7{4^s929W&!s(SZ{FsmVrYGZXdwZnFMC44PakqrPVz+dsm zhGL;tC6!x`esx?#;<4P%C}QSzT$;fz@T6^9wy)p9Wr!OtRRx6+RM$d!(nnM7q@8;P zx=}!9Cp6g>UUKv`=~R)1fwW zBBBBNII+}CVzmw@)!#&$q++6*3nH@M z2nFfC)ZV`TYZ`Q@vV9+I)%gWpw(>OPCb)wXr(F@f_KSn^REN9sb^?7>%4+WSWI0{^ z3nBSiW9`fS=Im*`?O#uAL+9xU<8H0_ScNJ{Pe+Q{4IXA*4L@#sLMMa=Ynv80Te8)* zhr6DD;+k05!-EZrX2RXabvKRXDtK~V*>%yTrME^>g#mlSU||%>nu8p$QjB^5XEIi!6!pUggb69p|UiQY)8cQ8x*5XX)oC#AoxG-a!@e%2ers~YT~Q{(mRTd00XIB3p6qAAL|cD9UlSe) zNX{|7l&;xYal`9?P^Kw*8Vngh9Sye-lQT_GFfUW4(OR2eplrEZ>;}uKeiNxaSs1J z1xssI<`>}vF=cEAxAz}bZYJ~NdDM1}GTkY2<&^mX4{B!#eZGO`1aFY0mMzeDB z^32lg;p0xJ2k3#iwdTTFXh z=aG*05Q_QhENt(O7#Fk;zyHUQttW(6QuA}x0Y^cdJoc)FAfiK`+)sMG(A(cP+#NCf zUeEEX`;3D$b|~$4xr93x%;VfQGWHjq+GkIpd2=)IXVpAN4mVTB2%pE6^HxLcaZ=+e z>ecT;e7zLU0%DE6v}XT9pVeL5{vorq=ori;c}WK62wSsP3GLa$?pfWbte#Mv@Sa{I zv(BX)&Q3=!DIJ`P{`-+%r8lcA2&yL`h62R_&pBJr+o*#kJxS?Y-N3j(7yz=j5hK)R zuCl@)LY4AE@gk!`dh%Lxd;kPCR{rvv_wQjxui!mec*w-h!B*>2uMt~0dC@2V1;DVy z--jcCk)Ga$625MHEr;wH1a5%GoLHs)RKm1hxWx3T*1Mme<6rOqsp5 znmHera>1Vw`l93NuNtDT^NvD}mool!M+yfSQV!lhV)e)>3I#4CU$1hl3H)~u=yBc9 z%=_%!&d8^?hi=>mhiZcN8MxVp=QRr-!&n!mUtMhl3Y#of6DO>ZZLct>F%H@Mag-ye z%q|hkWWpO;xQ;vk{VF!E_wzU$-q+4On6*(mYi|uOgMRMz-kM4#dGw9ilA}{CYRcoK zgy(*Tn3>^;acr&ECl&-Aj)cFxt~2^iz0qWgm>OYbKaS-DN#}Z}eIL659J)}v z4@Fr$;$q}Yle60<21=DCx)6fa_t`KbxSV!{n_MJa)QiMp$%0`cD@`Rtv*Z{V2>yQ` zL6{C>HLsX*_1R^QwM^sy(VHX>6h&vRcxgkG?;m!as87Yo4U&cLB|^?m!_xwOUatpmdwu)khY#s?`I%bXXu(!5CDy%+r-+mM!N=EbVis&mjyg{ z$Y`i!)j7@@;M$O%9z50GesPz`>lZ^WUR=|1t+^d4&`kzFUA3L)yI&+d-r6?gGIp7jAFz zB*8m5$*@isk95D^^EN>;WREw(+^@8@E=fdpDT69PlN^lX!m~%3o+ip5Hb?{@jlMO8mIt+Bjpdwme}XMu+wsmC%!{kx zb{UTR6GC(iv-uJT>KpAH-~%&;PEHBeCFxpK>G}goU)@{G;v6ik!N@$X>tasarZyLK zw3^|&p~K(U7*M0%tbVTNDWY1Hj||iyJb18ob2Ly9XRZ7b*Va;=@s&l3eOjn1ii7ce z;PK<2lgiqQ**VGOX|aWcv#{=dS;2ojm5NFe{i%k`a5fGr`wnM5NTWi}_6XZ^i0l_f zryQhTgmPSoe<`7JBZz{Qw|JJl0jrn_X1S9;Ht^U=p#IcGdeePMKgYVdV{h z4R0_IJrmSywpip5=;5&~82(zU8reXmx;6~R$4>-k6K04KVX zEnOMYnF{NdTIT;J4`b_9k+WFeC=-G~Y2ZY<>R(IcSo?sl9)T z-REZD^-(insM-Eb$W*oRsF1$Zj!?MQI4_B;?1~}3aZkpy&G71Xk4rs|+JEnD@DS~< zJ}C$E3VuPl9W*dXV>?G1Q-a#;3%xN;Rb~bL!|4$H$GdNbUUc2Uf=fHC*wFC0u)5Ob z&ok(@GFHEq%VZjAdPDbA#jZ%0`9?9mn!to z`>{ljeS+Y7b`pDAmk)k1>6hocn`To6{I71EjQnV=e#B8zK)I~K`jL-M4HOh0ZBamo z0$JrrWFV79^y6B-`;chI81!4vfU@#cY-+SYc3@c*E$W7QD13{4eC+xWVU6mKA^8Z=&CH zW|Hf-5}w9uh&hD9>|S*(K9&b&s8R z-|#5dSeTaz+;*A=dK)$kL&wwo=Ie`C^lrZ1)@FPDJxx{eXaPwl`$CoyfhWQPTJ0@R zfpK){0Z3f*wgd3`Eb`(BB-5F(63=k}-OG?~$SdRb(kmCm{hYCeS{5qj*$C&2=!vUj z34APFx%qF4sikH2cU`1&Un?fAY+N_g`u_b{Q8T^o(9?_0UwK+nUB!+qkR83U z(w-37Q^I8_5q(_-2^C~4#;GgAuYC;Xzji6vy{t25oOWmVSxv|%z^%l=0e0(>318Tr zXF{PwYkc=v#cUX72&`kZ=!jKMgS;=8WT06L_>yk++QJSxsyN_?1i43$&8h*{B_2ZS zu~HIH=hvMlPqrI7mv8Ed|Goe|liN#VqqT{@jw}l|Yc;!VaQ@uJVwa)XpyWsLh@$jS z|Ak0tsOPid)5(oVNL^dgx`^H#T?oaxGA}9oFnGcA?MjM@L_q1O)Js^hHCz50Iy*dP@F=hP& zAEwKrx*}LyT+14EUX=9_kWLK7kY8k3*m7XbNiQEU9dn3r?C|ECU%7IAt(B|64tGny z@g><{*i{r*zlR_tj^=YPueCB7Q{?uaM&3U-4+$k(X0HDibg?{d?wcLx3+u5P%I2`z zusNmX#<7wQWxI9}RI%F-bX*O!isGBBU}bn#(cWr@W$TYnTDPDbda77+AD@7}oGChJ z)!$+m;+B~=l_jq&Y-&@03UjlCl_cZG2d8lPtc#yrNX?=Nf&l|&C|;VTETV^PLOpl3Rg6q7)lcM+ajnzNM5)YW`$f$_gnH9guNsROP7Ij?sZIXg%gbf4g~2xXcfj2k zqEz8aZ+$p*wB+}^K}W6G&!T5v)w>xk{+xtxBv@I&SU{MzLg7rwziv@bW0PeZhV?m$ zG!TQ!h-eHovdvJI^@-Ap30ei~66lVdjs(S+CUMJ|Osn5@$~>=($4&Ony5cshWJ*Pg z912A6fRtNvou%s$or|8iFYY$9;Fi|`yFNMxz zD$($>L2c9w(YMmh^asuBrmJr|0x0sV?}n$XmV5>xvVgSw^ceFuO1;YglUH<9<`rv{ zwXqiKJqCe}pZbdSHQB!q+|KH+%Xrdpu)1-Q-VyIVYr2Vyoz#2~ z8b)tCq%yFo!^~M}kh`HCuD_I=MO7(@5$?Y_h7`IOQZ#u9mz%}W<7gTzGeJpK-S+y0 z{WPV|jt_&)Y$-g~(>1uUFkmgG@J=I*{tn2%{8LmjiGw|C!<;)I_{V2F2;#wU*15-B z|GT?gm5N*e>m9l3389k^Y*SZy*6g0SECs;}%z!D_l|Q=G8A+v;Amq0D9)PKlPsU`u z$%~6KS^i)Y@W2?QR^%ZeDk37!NB$JbjQ8tnNe+MOJLuxY>eEawNNQkumOQqF90`6Y z4Eh=-kM*^Ly)ue}Qpi54233Q@oY<$JE#7Y(b7ci`)_}%|VKO8cxhaNolSZK6t&q$kn z1qQ6P_jiiR8Ab0D6A9V~K!yrn7QvYdo)5oSaeak%x`nZ@AwY93mTo3Pai$AMBzai@ zLdov(#Fu) zoBg?0^XS`_d%JU-F#6XPlfsHN3f}~)TQQobZGEvAKcD~YTeUjwg?I0U(F-}4+lE53 z7wlgzhOs(QGS^{lcRyOjlMb<($gQc77}RtW;bzfU+{=H*=?lXZ`XR7FeRz%0-LW{LMjtNyT6YlHbJBz<8LD&n_&UbMmINQ) zX!02;n>?kEyi>GgaSnTwwVbtLl@7ynA!9~BAi8bfcjUozabywo&>!S;Q{L)gUA4bT zybO^DRDi9N?(*DD+-=^Uj2_8`RkdS_1Hd-`M9YTy6%~;P`Vr7-R>Xi&X|DLBB_;=m zxD`k+R^w&U9ktk2o-P;^FAf2Nl5%qpCO$84vQasyFIP=`aJJ$v_3~@iX@(cN8R77J zj(;LV)Vjl&#j4aOef89vG7yZg;5j><<mJO79~yblOL zoGp(?q7PZ^8h&HGAwVg3B&rqKt~A(6k~(=5VKG_@e>1ki5AEnr><&=#=C_W`7bZiA z)^ZODDR^}vR0L1B(ncq`13?JS=O~j?ExazZB1cibi_#OOg`O7@bHTA3FEuDgYh}P~ zhrwi=Ehld1lN+aojW_ZW%tk}9xkRc)>Z`vv|_Po9-nUs~Q5&`EY{mHt(rX^4hNutRIo6 z)oVS`@o3G*%ux;(iynRcqWs<^$o;T9vn-v)>6AP_Fi?Qw*>_(Dc0#{>kT?Z4SS!jRQ3S6WP+yodNVjDhifmWlp4EvOoWZNC^z4lRL9@@?Io z-hDpTXm}V()nj2ox#A?)9>Fo9LPWhGoL8rL9=Mu!9$5+g&lNu$A#YMj$QGEUB9Blh z@o)A2=TYiXan+Y(C9i-mU^J_o6 zobO1L4W2ESOOF&h&w{-AfJL-_V;Rvax{D`F>>_S{{?^q8jCi+V%uhj_d0c5}Z7(83 zN+>v@XdZ_5fp3D1$+t84765OZ?9K(Rn$9j$rCuv;{ql!M;LjvxJ$o) zb$~#U{GSs2@79;l*X_J$Oe6C3U#jeQ0upex`k9oE`Uo&azJRLTagWWFsW2s3b!P`5 zYU__T#kT4@R8%0Cd;!WT36C4+Fl0!pfEc|O`|$4Xg|pQ6Bm!n6M6BeI|E(r-#W>!f zsW{@NA48p7i6XQU^Gk7A8X33yeVuihwNyP4*z$H9?+ z)3x}80(cpD{7dzlci{Ryns2HwS}a{usU%EEGA|_^qxGzm|AWXnFn@f^Ag(JTneCt9 zy%hBo4enwcACsQEk~ZB7t7TC!lyYmlnC18RUQUt-2S3eGWl{Bh;eC&#UaMCZ#em6o z)xQlFK5)5nLcqgG9x^_?-w3*O!+7c|sy^^}M~9lkyHR1W>Pmjb*f@2NfC7sZZtn^T z-R``#_)}}KnzUYAq@h%!_5liizV(Tr)cKmbBzit6_St<2x4v#zI@KjnA<|!m(I-;} zqaE;?bN^L?a$70smq_htfAAM&y3-PkYH;-UF)#%NX~)H-G`O9ro0Nd6&C64&*}o%g zs;2k%u}dGSwe|`okst&sA=619TX9CkZUrWaw}hwvLBK{m^}r z=IESO>61A|y3TORfiHF7w!JW_4T-?Jfq})Kso4sFXU5g*Jcal;I1mM-!qUfZN1MNE z%nmk`ry*^F`47>1#KiaGqgEU#EhA@7%y#5jVO**ORWu4#B-@;1DvqO`g4`S`{+52nHo@8j(+EeU&e7k26+-S*`d$_`&6 zFL0yVW&b|bT>R8vu{?tok01rcAoN-382O*>m-R}vSGiObt}~M-9dkjv#4%;UAhW!viu#t$(^O@v0T+@rViuxuJ@nEZ&&~ghfqbo$%lgb`YMk7R0ipBd|2eG$lZFh++V)|?zdhX~?G1wz1hB;EgRK7U|EA6i39 zZs>^PQ{%eRRnCWLL6d@+!=kg>%)v1pkCdkNGWsnC+-7 zX;cEBy_Z{`>WFS*nRK0yP(Bh;Qb8UtCOGvb;#J~kdgBovuNAVOIX;Lu&A zO#<2vkVh&ZIDCX1R#v=5@O?ekJWmYUCc|%UXau*GKWHuAV^BW%V>sx6tAJPTajU=a zySs>GPP5Wh*HC$4oo9xTBc2a|xQaEoA;6w$n+Igw)P{@jy1!SR=-81tThL#tqH>xq zeTqI2`_J~fHJ?uSZY-H!y@^+wq|>O=22t|n$4ivN(VF|!-jBO7C&}-0U|H|g?c=W> zhSR!H!dMev0E=4o;qCR-e~ZQ4dUDh0?1z4j07}gPOyKw36-GCf zb<&ftQBeM6xhZh^_&OQ@8`2RQj2z5ns5F8`(@rgU2RK0ZK_Q!(|m@26E_*{7~Zv<~Mww6t) zz&z2bpWQorpJGM@v|&IK(u45~?>I_X3mB{Jcv1vX`6Z!-jUM=I{a)@X_t`}HhCe!@ z4hS%*_(%+pEE25-m(CMw-SnwKFS|Ks|53A(mA8e(CMp}DCe$1zQl625X8kah}D2cW*K z7sovo)<|6o!4Nz6u;yr z_Oz>XN|F;f@>1segYggV!vI+ewqFAtmq)WYSq(4F9=)Tz=6-mWre^+#=|JW(No()w z*J?pfeL@uEs_7wCSYddgPNqI%)us<)Rd>vOd2)@Wp;nTVW9e9@{H~8WG^#;D>Sr1i z1jO=fq&U!VXe^s%3?x}%i1NQWUe^}6`18=c0c!~Yq^SF1%3}qj&o`6I2!Js^+#ax? zt`JGf9e9lEsc6N)P0r3y|E|yKzYpakZ>dhceybwWsPeZHf-5596^{7rx0yc+*tnAJTMXLC{`sV8GZ<-@{Ohf34u!0P%*p+pZ{P7sLivQ* zvnX{EN0RpQUmN*#BFyp%ZxsL~#Ctlp4C3K`vyA>y8V~~o7G&H%*p)fn^^;CKB=7E z{mlMi!Do|U@uECJ&+%9C3BIfe7deJVC6cg10zkqw_UvUGG;Pvkhbl72SX{RH`<|o;>zA;K0feb;*z=0KiVlz)BXMBJPbO^tz#|3 z0^qCWus+8RF|-iGks_{|x>-9RQJxGq$D%iR;>+ll@oTzbNBH6lJ*|5bADF1o+^5Dg zZvz0l5yP<83Z)(}VUg6JrDzg3!maom3k zn>H@y#cCLOs4tG%7jMOy{fal0KAG8=@Cfh86Ft1Ml^EBD*Z^qTE;8?VL6ct3yOwii zz#^&xGu7GFypv*X$EL%^Kmw%BtBla^8d*0Vp&4ixpxB5(bQzFMQ-sM_V@yf~62i`( zs903=q-N?iwK5+ykMC@bgcin$pwdK2;_J1?9Qd!jz6VLyj!&7_3EV8xHPQLaF&4~; zDt}(;)7!yJ3VU}8yqK(b@N{2j1nCJ&X99jkfF6cPS_1j z-NTn1so{{t0*8TpT!`wzDZHd<}ki$ zSvKWH59!p7ER6zrc#Sw2ZPHLyBS&Sr6yq-|oNN z#h4{zw}w=OUs{y{adA&+!XxtyPbT=)=4&UMtH;lfz^|0e^D~*MNv#5E?Tm8upLQib zG{m~@C^0-c-OJMeUkBW&CuByvn3KTG7BjK&Gd^A3)FBwgI_F9`{(($Mj&o>|zYK#x zNQ_HD^izoEUtUthHt}9(390#8H1Kxdr<|a`{$oQFGU9WeRw=y#96b!MN%h9#-fC(ge2|+-}`>iJ- z)BurN%ECbli+&M%r*^~6URQS#?6|g$khs8iRT#78 zB%>Vie(;~OHMd@q{zpA27)zex*3ch4 z<&R+^D2{c^Wjd_HM1y|D71L<1z&#mVbN_Wcg?R5!jQ{ynAv5B~MHOA%+*4VxSAWI*8d;q)f7KEgs&T`e>AS01g`{yUN}(y^8i>$r z&Oa2f3JQ7{0H+Vf;LG*-&In$EvL2feS0|-Go)o|2GzI`y8AH*sjfU^^?`FK*k>(ti zsM5425D?e$frpWQ+WIoOp=p=7iu;TO6L+;0PgPp`+W-nxkWKwVL*}~5Psvj| zrX<9bfgyd|r4T2%mnDWu%}3awJ6a<6VKBJmp&q-eloy<=J$eYI15cYwaw zvcp8^3eUN3N9am{8iC29a7n_}i#W470a~tEN20mU%J!?6VzhY^!}SeHC|sXbTliDh z+*X14;)QuDP2vw{_u#p>C1+`dtj5WZDK%5PG*k^Mrs|e-WG!ms5Ala!y9?r`Q+>J{ zwXx3RMlUS>9f3~A6V&%#-+Xgh{X0;IuIbdt(XeTO7#8O4HP?h-MU!^|`$nJtv{SC# zitz&|!8xe!3&K?=1qh(#k`bjzTr||3D<6xr&oQK~Bz9R=AM)MZ`S>lGUSj$t!=PE< zr3!%{jr5KQ7wV{&qZ%bT&UHg5_Q|Wv#cL@k?aWweqV7f}pr-o3+pxz$7JFAa`+EF~ zI-RZTg&tE-4pQDisW_iB%&Ti55w9UA)MsxoupTo+1KQPz{W62x4rL*>3!VF!`khG^< zPZ`(;G~l^%@Ewl|x6Ptm^h!PIyZYzU!LsJ4mkATeTL z!}`eX87K!1eB!)vIR`%=+LN9LxXI7V`dL-s!2Seln%lS8LP+RQlTTvnTkWHwjLw6D z@WDhbCU6bg!>-&&_0ViXnkejcVPtL_wWS(GB_`JR*J%3Gk7*>O?SZ!=+y@hNn6-L; zSe|96aH=Oyp}koJm@<`QdLK8;eNB`|a;*6o4FJBb%HD%r@%*i_T`VjF zmF4hFoId4iH)Fr9`Hx0%IVSeFy?=tlJe^rb=Q``*aZ^unZf&yPN$V3zG%GSBEh1-) zw+>UhE7qvoxWdIbNxPoE3R2dpw|*mJP)dOZ`zE^4V-VzsqdXD@#uDM$k`-{QkjSQ{ zqw1R`o{tMytPOP@l1Sga@J46yKYP-2;60US@QX3qY9!`7;opN~02^Us*h(TV9rNOq z*>oa$DQ0XB-mZ~{D6)}?)w#~}@f`ef&?Mx42uUE2#IRDqL}PJU0%UL&92>pRj(`1M z;%M`VRf`O{^P*g_;C65uiBA?$u2r6PeCZSzj0gaaiKuZrkgYHLPf;b0H+fv=dzLEg zcmB(;eKWm%R}GlsuAPYJ`4{xN@Bo&=xHl93z$BdrW<}pkNaa~>T=&rSu#XG~^{yw) zpwVyP2(}qdsP<71L52S%S}TgNq=3jZm@uO2HU;5B{wZX5;MWF1oXoP6a7C*&Ln3JE z6bm)^^AbH~y7BFTz|*bNX9?8 zAf*(XKcq~P<+IWxr%Dpfa76#q@)jxDMo%tOkQqo3HGg`;G%;P#OpkGsR>nGsJ|BY}mZGNg)?Uz5fvXVc;b_S*pGi23uFb zjV7#P3tgGu$E0Em_oeGLU&In0NK<;Q)2J|4SZPGRZtV!ix8*fvhd_->vN!tu>hczY znzub4XX*A_ISiaq@Y!tVxLK`eT6Mx%r64Z;k>R?-7QbRM*1O;8WxYmy{qysL7HWR;RX`OB z$iC}tz(go!)mHmT$F7y;`h?5m@MdCWU|_)HF|Ke*Gd_^I9I?fu-{M)$r8d)S(8!i_ z)vt1T0JBQeQ7iH>ogBwAV6}q)LiVatEU$SBK$57b|XOhX#SZ z8&{YLzo4DUPcDbYG|4&v0vu)y7@ohWbnMr_ih|2hv3}WjcW%8eQ@UpR)Cq@%;;jA- zQ!(HW(Qg9dDUx>|CP9{~GIw!F&J9n9H{COD2N&)8##g+&icK7=pX$gel(5t~@gZ^T zr4CMY%PHR)CCyfpyn02-f-Efaz(AU@g6@cDc6czCjqCF*`)?gDn)>p{SbEmV%?y3d z`6@mWy>?f9X&e&z@0MHubJvrz715>uXUCi4 zHEQEvfMo(FLOIJHhtGbG*FwpbE%DtuTF?&_DHHs+X0I-5B!>+4649ooLC3ooOTn|s z8~b8mt&mies^eq|o&YnaIRD@zzt60A-%FKVhL3&hoQ~ba^E_qS4BGB!(cDVwKa~z# zk>tmS(5H>M>pv_YYK7V-lys5oP)%%l?;7FXE_Z_knrJ7lLFIiz?{3@k_pD`^5&D?oA>_;6 zzQA{%S{+^=rIo+JtXF_959#^ugqS$Uc@gqaV3^7-7bg-%iKyuVsoT{0@3WefF-Xz^ zByyb$Og}Z$#z$g_3*|r37F#Kh^G0POOW3g{USKB%$1ike4c;y*_rMPt$QNq!k5}5a z?{(vj+P`UHC%ShY&lZHRC+#H?0wHE|!AAIa&`3i7khfQcaiJ6^Wtbss;Y2ty=F{&3 znUa*YrnbBb>ABXGvS9J06M}nhm=;1Z-zMAGhc36HFmSj7_gRnuC`Z19s60JV+dsS)h23sK;|iC=Q0fIBYz0n`zmD#AMntloY5w zX|QZ=TEVjai%w{Dc5S)}(rO^4@gOjRc#r~cuD5p@SERTbYsdejbE?V5T_U4QAKw4e zV9Qb1U!%j7UQwG|F^A@vv-9_9X-v9Idu?M(!u6}5E#_uc^&4zYlJ+}@a~Q0Gd4*L} z`ADujsX;pFIB!M+C~di~_+SDI2c?;;NQAPEr=jrBk|NXpnA@&YAhYIu|uX<8TBQK|;VnA=~vR1XrN< zX(cFo`}}z{_nQC+UZI4QykaxBt+n%?H|Dd*rU)#MF&QZ~jd*-*p$`{v{KPcc2QXF* zNQ(0?N0ceyzws4WZP7nZ^M^PaN|$0VV^N~09OL`#k*ZfO8+sxOIM>brV8z-WO-eGp z=xc}?(sKQ~3FLtN&(qH58l<3%Npkt^-gdWoOv-5LPv4#0%02#?AAKXqR!nLTeh(<< zXxhLYrVFE)HLfPl=vU)ZgZmDN;lF}jGOqc%Zs}{Fbd1grLBI8 ze_OQL)#^7RpX%RdGApT6Kmv_wJSIymnV<1f1B)xy4FD{(!jwwxMhFOY1-tsU*{@`= z1ASB24xEQkfcc+ssyJXKTb#^@2$a#(x09|Q(@NN9VzA)X<0=Sy zd3sEouC&wI=tmm>0^KTDiC~AVLY9l~X-H)*E4k zm%zqq(DlR;VW!Qc&X5y>I7j{~0(K!*lKMM+n|^lFFQ5W0&=81{&1!)*?j>*2`*O-X zZNnQp4&#u2>qaEc%;kKZxs+l8aFvm5oZIQ~-%Rl^&UA$?MKlV-571a{8>_{+f3ut) ztFH(CMMDZ8U&=g#u5N7xWs5vw_ZH`xG@y`+XBOPTl(ls0d*AM@pier{09fITPPG(% zQv_TUd63@Ka{i3bHZC(`^IMn%7Rpb(3lZ=7w-=L1B*Y@0Z^AB&A8U^dPLl!!DFNm0 z_%;{5324tT@wZdGe`dX7+i1RfW9WXHgEMcdNyzWTkHSXRG%vu*XY!Os%cE*EN&+DM z&p5N=S0BLaK%3$Od}e)})za8_k(B~QPBo0=a~;WtPchAb3 zHQpU->MlBB1F)WuO&C64begK--DmV_M6M?3>RGBI4SL_{d?_A9PFbS_Wj5z#}5W{xh#Fr}P>f)ksJ!e2b89?6<`4XOV zS!v^>fCe2|^Ki>pj6&hCxmY@D$uyi0ti?l-i4{|nN{~fKNQlu9r))s7iwQBG`-n|( z;3y`&^m1+Az4*A>Qxd<`ygR3#6D}bU#(N^Kpa!UBF_$L)MSs$ZhT>N^O*Lv=Ry>&!K5d%b)SU4 z32_xTS4{Y4;kkn6?QQ}|_>Ro}7S^e9p%>_T2bi}#n737Prgp%#=GdY@N{^@}vBuU0 z3V@E_qQ1afoi7Ib03f1NZ)Vfqx8Bc@1P=D4!Vc^9P!4aftsIq&DaMef!sI0mRSG@9 z0PIfx+1BuI{NGo*PdJCl_mh8XS$tfNrv^_h;i+tXm2Q@iJjy4esIYh{a-ao#t_8@P z*503B{#>r=$Ue)DlA*15p$ZyZ)!sS;N`#wJsbIR!G zru)X`OTXT^lZ%&V;4LLjKM9uNfTGwe(~{P(XN#EL;j%?(DBqPWGiR+z{-|+oH*hYv z$+3l3aEA|wfZ^G-s`_c3z?0P}PC1adlm6qTs}(3n&nyNPBYtb(`*Hy*dfAcD9R*CO>O?CNC#;!f;tU5M#t=r z&ilZbp13eZWauHXRo;5r4Y=*Ar$e|BTE2RphY|rwIj`%8p8w`RqJ6jF%Z{*j?eu2~ z@}k6Od-f3#nAL|8P81t{Mz%1wT}ZByY8mr3FG>vLS4xGnf<;r)B1Hr20c^@OB84JmD1UA?9)up{=VNf*Fbp(*fQLnS+RsOKi)SnsnnYm5Kxz!zk1e1} z!e4>!A?I)YKHIQLn_Q*W9ucn(wKnXqXjoWg|DI?Jn(0r4|k3p>>Y+RJnu;`t>O_XT`n6 z(41Du{Seu3rT0}{S>q)yW9WU9^Y@ZWodWlZ4jwI3XN=FoG0I0~DJPDXzArdEXEJRug!A z^J7>_f?FUjB`CSlA*(iAvA)}$ZOMC@j{Xx&H{g>6hqK9u%OfNLr_hl0{I_+|o4c)M zN2)sa^Va=HJZ6_4{lYh6a>Zk=N{C@2*}$R9MRc1O0Nt{Ho(s3<@uk-PdF!s51lRXg z!}v~Nd&}7#x&%||z#=)%JJ}(4F6J#DG*u37xgQUlO!28RYgQ#Pbhi@;8!8ThBI%Zv zdF#OPl)O}=RA(Ge#wvY>1E#qH4>24XkPaEna;x3tqNBwnv3uWO;La76yiJv}m_%y; ztueS~i}^>dyY!yy1NCgm=(vY@-~EGeHU$I(tXN&0T~42DvBzDfpEAmG;A*Qkf+Ct` zT}LVcGd=S_d{(msS_u5Yp;(kfSVfXz)EZhDre=v4AK8b|ii!+~Mw~8N+K?Z~j9iWm z@vk~d%ogMnh{Te=VMsc>d61+3Je{-Ykj~rEgO4 z=JVZleU9JCsc!sZ)&d{W;ymcxbNAF|V_!z-f<=yCZTTmKIz(Y3f!Lr+Q%qEsK}=x<-wb^ShhcTJt!BmZzIM+uy;lui`IHu$yDfmC{X1 z5|n*kQ~w*JcoVdC_`;D-iZsUFn*4VB;jpQe^`oh)ArJuIC#-$0k*>VzZ0|bLxeg7! z_od@-xBI8f4EWB)D+MIUrZNKS3aY?X3Dq2;^vF>@C?J{mOE}M$tEZ>j^53zCVff_L zn0Swn=jEB68?8zziNEKLu=OcIP%SFw>V$@IKLUW0&t$?l>U$1a^lo($24t|O&j3&4 zOVzHt{kCB+7WSJ5S>RpM51zdsxYem!adUG?xz0etU!Stm0t+0yEG6#p0g0*H_b+ey zW?op5iJ+$I!oUcb0D=fjLA8oU%3r=fQTHTlqz#a*`-7>PT{cSeh0DU8%RaseIX`=5^!atyRKsrabu6{c6B zS3HIWuj^M-l3(A&!2*zvU;cSpJ}s?KjxJPiMXT8m;9qX53AwE48~)DuaRTd}8|ulw zIPrF~&yZ&#SBz^3jR^sikH%=+z5GYkkp9sdJ1S5Cjz0&_7+v|B_$N#-QX_$?H>!;= zCP(S_vzQ3OCQyRt??<(${71&mrR{HE!%_ltvsScPlwy4=D@kyGaJH-YbW}TQLd%B<|{%yn~d`2qudIyk5>2yMeO_W9vxnx%eZbfzn+4 zNK#O{WW2>yU7c22AG-|=almZand3H!S`okvSBv%yj{pGdTJ-D$MCjBl$sf#f8nrs# z2xo>%4CDm@{Ud@x$OC`_K?L+jYNlp8M5a_hfb&-=+nUF7egEr4*!<+q=eSkU-A?R~ zA(QBDD{WBWbdNvGnAVs`XIRnYlaVp%n#@v(^t+k@CJqANISK$#L#Dw#Zsv~--=HTG z`p_kok~EjrN@lxH8ka{uIStAsQLWn-sANDr zx5~zCey`hQDAk#)V@gGi}h!V(7p6gQX$nXB)-`1Im^WIs;`ITA9y!%sM zJQyc}!e??hjr*4S zYFeyJ7x)f9sV3KM{x?YRkK@MDQj7Ic<$GZPaD9uHPwjriug9p!pVv`{fUl(3lrKHn z6)86NFA9kThis3mQ6j++yewmbfOPVY@HoR9150+1j2Uu)@Cr}{UiJ2QxK4tJndYpn!%6cS=;c<1|2 zv^j<@XWAVRt@BfHL`iA6L1w=8;UmWT?}fs2utA?RoC_8XR(_H)xm=bD1loT9=;w2G8x@=qo%8Or~c|PJa@x6ra+tnU92b=^l z)lW0Zs{pOWa_%}%3b#bi0m<9+KZ)atFI|3de3ntdFJ*=63)_ai+wmp}%R7qYJE}6Q z6ToNToPPXc)%}cXV^^b9wR{Gnv$d#Iwku-GmMu)ff4A&y^Qe!x&(P`gWTIbi7mG$= zD_ek>29Bz3ZZm*6M>Ev!%#>(Rye4$0!^YScsDD7iDAeXPvDkCcO!JSh_!Dd{(Qdz9 z8NZcj2*Rkf;cTanqx?W%EVtduw$kkKL{g`jClFFXq)rOYIdP$AuL2Z@C%{64mE?$0 zMl`^QWRtGC`yBZ{-GKbT@|hOz^$y@oOt-e5&)l=rYF-8?G-ZOZZ9+D&XiZvo57?<* z;~xEP|Ku6@JAmdnY2oaI{DBD$-=WvZ+rEF~OL9h1C@m@BftD4LMCAka8+%4=E1Gxu zYt?&TOagcC39eQCHsN6t;?!|I*AJ-@BGm6O{O=2ai5eJn#|r))(x)J<$P`aBUXiJo zB4Hi=`@5=c($s0<VZ=$wT?KlR(!DX+5j)- z->wN{@>BMrS+bi#V;RTyyX`T49Z!V0I=Y?1e0}p;=iVgY#PP^uu@LmIE{<&hIPwXK zFk{==Jy~zpy%E&O@;Qjx#~YFL!rkvC4`Rx-wkiLafhjE!KM77XqKNlHu)1=$;qM>5 zeiP&7UTZDraDe|<93pS9l%pT_luS$%Hfll!IXig*tYBp@TdQU2m5lKMGQS6&xlnX> z#lk}1I`UyS%0v*ICBnG~K%un!6&0B7Wp4HYUjNO6z-kfd4;1BGI-ZBHn_HxIzlOuh&niX?&Mx`3wS*66=~Dro2KFDWuaMCj`3caDR6mj;N67j5TSX;&)& zD3s*b%SxD;*551!n5Y#EDAK;@p1(p2z7{Isa}1?IrPZO5KpP>;JEOYgiG!OGB!sp` zmULT?)7Lt@u1aacnzdJ%wIC?KLVb0G|H;^I}R{73Nc%f~IPfPEzN#O&Q8 zTpP>yX6ZGmg9cc_XFe+k{A>HZ9i&xP%0(F-7^MA>jrj&@UbG(Nei^rHeO_9s@xTa>Tr81rA(w z`LxTj)zxxUr+NJsAV`N6hANyy0^6dEx9maxEqwnS6T4*C%*qq#ggiAstlY}@1q?2Xnn>(+hQa(|Uj;5FFAK_r=^*d~_VmNSvJL4D`}$&wjZOt=a`8TI8?(7y1E z4~X;(klHzsVSpRJ>L~4Wi(M;Y&ke@HE{VvjyO{8QF|NrK0;e5%;5gya&~m6Wwq$Y& zx-=YDYF5EKjql_Z`GPCt0H0F*T{xA2Vps-m*;D;}+VJUoK-EPBYFOu{f9QG+9?*Bt zI5f-5T+g{T52$04s@7yec_Vnpnx&q^%0}w=hIqhcqm`99qSthj@}TQkjmQ4pt1$g^ zTr=+B;yIbl=#>Xrb@d0ln-gTw*kXk7ksoGIC+n=ab;dkXlvilCJWJ%f969{Ufk;Vh zX{q*+q~bjj68g=_jefU1Nqg{-SPe`^fwL4#T~UgfZXNfD9-X$CNcm|0?c0y19{IwP`crw^CF+n{u4W-!fz z8}{&d6E;A3cpIrh?}fyrE52r?5X|-oGyItxzfF0_6e@WGLP`y+UAFf8ORc=W5hv&_ zOwRSxaS_>+4K=!n7lho!B94X-{ehw5ke2rbmVJcD5c_jtASO}tqOc>@GK&MG-B_pY zwZ*!{i(z7P;?ZFEO<#JwQmaa?0tO{Bx^^@m#v0OLSRz3Z#gIE}9%QRKy?^NvI1((y zi&Mt@OWhvu zv&d%RYY#ju3qtRspufxRHgny6i~k@)?WfH$hOZAm4?$sr3-$oOgWvYZ@sU^(0pNwu!)TK#5zClwX4_-#_V+){t?>G*ck|qh5NMh ze|~{6KT^%C-pKzVU2S8uHAbCqzqy9e?1!?J9`cv?qGR^C-q#4W!yv_Wr64xis3NuncAj_D zO--!tq(SUJz#Mv-ZHdxkiUBu=^U3dIVni{#Deo_nX4X66SU@bRQ`!&|YE!s5N;JI& zq_2f7rWhvXfAkQ56>$a{Rrx-rEzWghdN2QCnM54)XLBd7GbXKm{?F(AxI+>&B_E#e z(eg0Nb`#-)31odX5{IfxhhwX%017_Po2oq7}43?V)Dzu)+EFRrO#XbH2-Isk-o3Q*25~eENF476)T30U(lcj6HMKd;mx%drJRm3sb2DG9P1n(kdS=GLnq9?M`BH6GJME8^lvV5%V0Y8fH z-)`jLll`_^l@QS2N6fJ8w-{i@vEMAJ74i7>7A!Qlz4c={PGwxevVK?Z-Ou?iSVcqR zU(PLG#cX$7gthrL+HOT4;Ctvxy0cAs>l`wc>}K=0-|nR|^mgQ)Be;Ke}s%7e?wjjI<7?Q%F1|}4ssNhIe za3!^v+i_5>j+&d93DxKd$E;5B#4cLemCiMDCan#74R=WYqF2R}#X>}dACiNo$Fr^* z_l+MNUEy)}zuIy>9Q3{1AJ|cri|Dnpno+8M{A@~D%xXJ8#3Daw`&D(wmLBh! z1U^$qkfBcdWBFiM<{tgel0P-pJSe#74>CC9$G>n>#2kb>o91W!G{=tZjl_4~gY*GN z_ByUtp98Sgu0nW%#Qg1XPYD7GKB(fsq+*pXE=F}#dom$~y`VMArd6;4HbeRZF7BR? zzs!6>6m>^MP!y(&3fcjPB|wbSb>kFsIIJr?w@y4Dud$U zr!v3-0|v>G-;Opr-TwElZN0CcNEUy$(}kHNlkX~@PUi~c+xe6dD1V0Qu$2(iB-R+kl9(wd`lsQKdsE%F67SuDgeXxz zF79KQ|Bi@Qt!r}w+Sp`&67u?z;~JcfeB6!jw|m=ZOGCY$IWu-d$QfxNc4N7mid zT9l~xxL9zok&gfK%GwolXj6yt040$^Rg;yCNJ=);DHW~Ui}xydr*ODMpbnbs|9B$; zAsL+ccT?1b7AAUzxl8ne+PHatXGK2wRp{Je6G_2~5uO(Fdi($I{Ht+{eykB1;? zdIoA>bWr7|CZo+!EfUr4d2I@nm>Bf7`vc?}3}fj}0Y7hrzQenTP@o`gz7CM%bZl*0+m!nn8Hk$C@;vMOo10K-RQTrs?~Dv?)(x4XcW zx}LeG2fk|Vc0EcdtV64M8XE3j_ zBgl8BhrirzcL^>tcinvcXYqcVx3N5p2eH4k8dBLMbo*%=C&NaQVuMJ9o5m!6ME2WR z%+npKG=QQ!u(z*51+gO{%2_W`zU&W5pm+jIX?xdPikYe35D}wwC2)c&Zl;HmEQr8!=<5HGt?}k-(HpLEC?+XVc_b4@YVXP<$n}+ z@K~Z)+8;@+H*);V%*45k!zHM9-dxt;m^qFjkA zl^OF+5+r4Q^G~D!HPE%L5yYu}e@bXn?RTlmD4EOBraiHJe)r8V|9O~%!~gDdIQF?* ztukg=HWCiT7_wvs)l;$AEi81uN@&Xm=jG-6J>6GZ_*%p1ugkOnn!Ik;@W>n=CG>{G5=P`N_flMVH#fi8mJJ@RpJqhkVk~A;topeHH zwmZT1`5KsU#Je)s#JITOs=6knL>xb;Zi`Z9aw>dJsOBOgrzgBy50%R7IdY->uRMOx zaHgZ5ja;b>6qKeE6SkunZZ*9$t&^YB4hzrGjjd;>y@M2>pEOxX%+O?KzYSc$U_@Qr zG#cHq#XF!Zupy38o}g~svbI)Q>?%`mvbSXX_DtHU6R=tGmCU^i1yEkec6j}{x<1jN zfryw`tXERsm+3Z|q?99z?R%79v)BCx?4+---7W#~>oL`0>IXC0DVxqr$!-ctc2*@p z1j9_-oJaV>ovd3w@LLTJbREhHiRFodE-5Sfoud;kOhEqDW21cy zeP0Pi*wWE8@Q3L+M}yq>y%)8m!a?>dz1PbAXC?k`JW}~0sxmL<-2E^1zpmaMdwFhK zmSG)W=x`F-aFVv}j}^0G3D|G=fMcf5$)0Ka=Ji9Ohprd+W=iC3XIGgy zN#aMjZM8|@68Q;kS7H|h1@bU!#@g*@o?vHhwlRsv70o2_mlauY=r68Ts~<}j%;YGN zSVXqKShg@7Q1-EVxw*Nyi>axpqhtSC`7zv+=$bE%J8HnzI>6zI?stj8@!T;rToN^( z>nSH`N3uuw?4k{aS(7J)J#_u3SXwigS~ls|s_lpQLW6p;G1u(~6l#^hkEOz%ssDo2 zuYegV(e9MS+{F^Y&bK1`ZBLh}2qL$;W4$-4FDDWgZ0p@sC~5$DA$ML#UGHxQoqe7E z{ny@4Qeg}saFkj|$g61Z7F(LqXC!UfTW_#xn0XOM>|A=@n$%a7ezPJ#qVlFUv~D~9 zd9CUol0P}J4?8nL5esZ?$t|_4hnG3d(yan*(ViT_nqBDg_qIk1Xt{0s>2o0MEaIWe zJzuWZ$R)2*Y#tM7oDs`4j3sFv!2Zv1ZIj1x|m8*ZpsvZh2M&-jgC#(QBaWv1Rx4YqLrv7o9 zsj83lsJ_&zIT7)*+ZiE@hs=+}`CXUEsZ*g`Yv1jLVRMs@A9x&3)TI~-cDxCQC~g1# zAYmS>Y7v>?yEXb{U{cZXV6O1+?KB&D-e&Y>?`L*?P!>hHy(x+hOzL=q99${--;b0e zQpj_|lbBJOQE{g!n4@g#YSj+B`%!^6WbcSV+YlnWzksAje;da9atD&b!Cv#&S>mqrpw1+P?{JP26hA*AYN zTwQ4q8i~}7EqcEDiuX~rCK%JW(uK&swu#UC<&{BC={^LgZ0mVQlDq8)O}J*6e*gD`v?* zb)MSp!}UVS^@nczxxU2v<)CYSbyhH6m9nMe4vVEIRbWaQA$llI8T;YGt<0)X7Xn>x#kFG%=d1+hctJxo)PlQj`t~qt-JoiJVSM9 zgaZ&Kh^BJEqetRW2B|t#Z+X`NPrC_ecH~w)d*2>X^Shi~Pt|Ag-|lDP1pR%~JKB+d ziVEO6_}HG4`T2ppkCy$QuI|p*kzB(`PlDbi0Lr?&{(JTCVlUzjE9yQZOiip!$V2wB z-{b4pXo7`J3MDrP*ueIsz>kdDPzduWfo$I< z>|bo6Kczl+e@$Qm@u{Zvv-dsxclAws-i$S9))XC_0rZ8HB+8!7iqOpd1?2GEHnV*$ z%<3OIy{txXsB7;n9#NN>g$dOv@QX*J0rz21=PgJ9KY=Y8jPGPsm^<*_lj74XrNt{N zYx-Sg-dIgPg|>k7d79q0HQly>=fi5-=q=f~XHW%mDCUKDzr5j;7JAW?O=4l*F#g(? z?TU)P8vL-7bGxwZ<9jK6^%+v4{0VwfW<5e1Xjlf1zU=p4dvn*{BI4t_=S}!4F*C_R z0%bw*3(RIEHBHL*Y6SIS=jIgUi542)R~B;Kza`6lg$Qs*Q5}x15h*BIjgQS*<^A_m zi_OeLkBB_ZS&D76`sTftYa!E*Rz0`0Iq~5(vPmljW8nkMa1+Bsaicn{M;yL9WzWK< zi@oX=N1DMmuBM*Wqj_1J%CYNB$R6eB*;aj%k*MyFIFL&(S@5s}UMA=LpOfbItWAoh z+voPHsW{2MbX&U&g?ZPEM(mxOC}nZ5O%BEQ;oWE9j`84yR809*Hm-DX)$g0hNMtDbW&d;;s+zJ!AU3;laXh!t795^<|tr4ZJ9BA zSQ%2xLSrToN_0Fe{;Tp@2Yk{CmHf8)y-URIlq(sviz#22_ok{&L&OycQHHd}e`C|t zA{kV>-4015+j!g4-W-tn(Pdd};SfnBZ@cnQ;#q^m3?s3`r;^Zh`NiIbFZa?|^OusO zCVuMZr(9OL;q%pCACDD<4|c*vcz}$jp^Tw04osT|YwFWNl%#@TqN`}?zMsZ+`?0s~ z?yi>~KjpX%X1#!R^^8DRD5a_;YN*y4m_K0tIj?hoZ6dh+(F_eAx*3mH)lG*>FaG{! zaZ%%`Jzmvr`}>$zG)Azfw{h14@?0X~=E@3v65!psWTD*oJSRWcaNU~n$- z`gq9W*(%R%VdA7c6SU6L#N^!3T$rgcmSn+-Z1xh|x~=&E5m4A5I_M%qV+tQakryhN zF_ipB?v}Ub9 zm3ogiTb}dj&B(vd$rMdb2P*IZTa1&mD)$As*XcPQ61SljS1Kjt2MJAN@mq}10^FVJ ze<$Of3SH7S^1pZ?do$i!vlY~+`22~cjG8_*NevHolvR2%tOicfHZubosUM5G7~-+Q zYs$(C{41nZ2Ea(2?B^G8?#s(+9vS&w-rQai7d_!wIhB*u_kERxbFw~kd)pI0*~*Rc z10&|SCEbLQWTaovHx1YDi&zyz$TdxAj*rNCJ>V9Z9)v-4Z0t${KD2ldLX{ z+P;?}(fP?w*gF8c8f~t+D;KR>Mz+_AivePwY`<>F$=q3}p|Bxis$A95$NGndpj=wa zztQE|-iHCi6@cgaPB8jA(FTk>(SxJ>sh`ZPTiuyGJQvJci3dmp^=W476}9bGaolY( zxoE2FXh9~HfnNBS4PP>eShge;41vE4>V}ub*FyE}!A<@mw^sI~&=zGyzqcQav_|WD z9dMpN5W2P$1XPwx7|#q2C#&gp^}XqRX)lb=Wi*9$BI5#?=xF01oB2l1$!)_uZ`Y?2 zbOBTB;E_!~Z-Lsm4sdr{9r!YzrQ3UH*wNK`5vzZ&KC|p(4jUnp!38;R(a-Vu-KhI4OxlN!3hEa@OyosT&V`iQTOJ7X0 z7z*0^SHAQHWfe-BnkEq6a{4tTby&`3bwlXT8tb?O0gKTyqn!%rW6Udk z6hE0h7TD$6I7hz&Cfw_Y2K-bbdV!x!0Hdg%P-^TK%fq*#uA{5~fe0DAkyIy7SGyVq z09tEk(2&*mM-lG`%Fd5%KG4TW+<)i!{Lu7e%LS(9txieyHj4rA^c!i@ zH+|~qL|Mt}ar)2#>tSV%G?X`p#STEFF;DvpYusYpwT@e`JE38(%fBNde#n7xY>p79 z3G&xRK*R4^$H$}D&$0C_(acV)GiWmiwentBSm-XX>^B}<_sPpj&dJ%^h7DmY_(;Ua z<6f{UMLN930*44o-zKukk*_sTjOgr7j{8fPkGu4{U5X38K5tjFtCUPBrn&wOPe_6g z*BJ8Yor9Y{fK}@h=hmw7If(@t3p#mAEnomfVkA3!)2hq#qYb)8e~$#d+&@L>WLU}A3bJsW8EC%_F16_CPQ%Bm@+F$Z zT>DV(YC~>2f4X*hObSgkimLG~z!Ux=8~D9Mqj)%kPi`O#*q6yZ*yJT~J`^o&jw?)L zMKYCb^t`iyIYaimtNi(OcZ4at!&`zZSc%cNTI=(f&C9hct-=nYWH;)Y`_$bxpU1WP zZD{|+RS&~i%`d~)Bt&>E3vTQN6I^LWoRPxS^x!^`i2nXe@IR$(r5AY(^)f?xO7!%} zvB8JMU!I2rLK@pCw^t8(WQRgHtGIi5+|ztej|30J!Tx^_cj3`BxaG+iAerd1_WIHG+hvW&Uz1N`{~a z{h;$uXiik4m7!mbSxNrf_Zc`uq+X$=t)=zSofZTZD+^pM(S07$apL6#kbT@k|8{K$ zcRw_2g$er`x8~?r{O{RlLRd}70F(NZcN(sEo@}v|>GgRYN+C^XZ!opKAkpGc^ zgJEtt3h}V{6zS*4JfZJOG1q}6a%()t4-B^`SIqo^rkJs#C7wod4?k&Nc2qPiql#9% zzfz02f7G-nqK|7*DQ@T_b2sGe-(S|-4OJBJ#tRP%`#>iAHcVoF=ZGO723tpez6zu~ zdR)~^(P#{s+uPWsS!`;GR<7A{!;GWF7tKr77P?4%E8oq{?;5s;_9&2z%Bum07>rfqBgVhNVV zeG@fkDX}d|VT56i(m9wGx@p%_$w;Zc`{MY?z5*VtR=jCdAt@xYH5F;Jky8gs$<8M1 zcDg8g{&V}K`$iv*Qc`efq96)Lg8$oPnJuGBgO05= zvgL78NjkaPje>hVnlQ03pv=tN4ZB}7vE)46lt~*3igjC~)33OPq~Im4f8T&y3TQ)b z^I2e{s9{x$u4&*G^Nd&vTC-K)WLQLBWJ`%!(%IYo3r$})f!hcN9=U6hXAlf~*?=v~ z{V`X_SV?Ifn99#KjZFAxf8`4Ygk9URw>!(He|)-lY{%=Djo*{e^r9qF`)91d6-AlO zcl}eFB}Pmlh)>_{DOO8^>1wO?N*7Hu)rpL-Uj1$hj=bn+zXm`z&5j|59hPEE+2XL_ zPq|K!lU<%|LB5dDgeBRsS_hWay+t%gDwo5(U*lSlu>ra^LA?2|MLuo3r=*g=B-mI) z?u>-w)wunguXrJ1L{g*N;jYyOV6w^i@ZQig57P-;z-WxtOt{4yWIY8Ki&`?-+6Ce=l#*lkHlsUbgE*x~6lp2ycWGUCzI=-DuZYua7^ z+POt4dVMX6o(gtKhCS2!L@UfI4DsLNMC!bNPEkV?JW0jtPKVizC1eE!1;3UZZgEXd z|E^`@=(Oyu@dKytw3lV5Rg6^(N62S~YY*>Ity@w{w_XR3>3_3$Vu;|uU-^Ka2i?jyn#3;j zV<;#Ew3^IX=INAP{X%Y%>_y#5bDt1tLVppV3W<6X{7%*dlqz z>+*KGle8TvRX?pG6xS@pGW9;!w2SyZuGB&9c6#sR*w;uuY2~~_P*_&j{?k@#_!=zI z3%+P8Nu`xoDo;tEXF}JXu#LdTj=;dxw?x9lTBm1sY#TT#)tq{MbGPGbW~V7i;dV&RA^{vzt(l>*Sn(*GV2jz zq$Zb@x|tJZFNs~`^y$>Rjp;onmu*hUx!Kj;zucd{#boPBG0LEiU{fNztEfc71)>JP zp)z1sppl>?s+-cX>}o^;7o$-yHTU$|`I?@#dS3?Dw|$SE(uKM1GmmWBrGp329zJez z_|{Erz3ge*`&_hu-sIRdBEuNbO)~15R+89k(Xnw!LMCe&{;;`bo+HACd-N`s zN*w+{#h`l_`sMpl;Q0U``*fH%?hC3fmexL&VU{i_qt*6zk?hL)48tKHh?^ICzmI_p zI}LD}=T@eavtdc@F8e#9rzIjO(tu%M_ES=YD;6XQAwo&jrd4!W2O0QZKeDK0kB+gi zZS0b$AMKbaD6vuXkGZcS$%|mt&t&9dKUsRMvm>DXJCxIIBYXBAkAEM*K^{hosX+*> zGiiqP0wEs&l-ss{tV-p|Fwf5~FQ-sHRj&u%&yVEa+}fP9pMcie<{wKf{1ibSbASeo zKy-L{kHC)!0BdyA=xY^96WW=|uptJ%8$-O=`F{!SKMyX>>~nkhAh~7AJ|_!%bvdOD zLJS)LVuiTe)>AbK{|(7W=FJP5DjLhSL(3}D7L*%>G~}35`on!{ zrdvF}^5Y0wK%7{w1r;W5)zvGV=7sx{5u6&`_l~&RrWxj@N?V0?H8&=3CRDqA1l6i8 z%B#TVG=P{9q0@9~BNvxk!p(YA2_seHwmJWs>~{8#ZcnOihxMr%ENtnpT@;01DryAZ zJE%A+4~%XGhG?cIsEX5h&9nf(lrZSR31u;$Q%ojz{d(6T%NJ5j>S5KbX%uY z-ZK83i}H1Yt$W{Rl&%YRe5iFrn>W!m@)79y`N!2IoE$%tm^*CfO5#aA%Ec0%V>#kI ze_0Pz7LeHw8{pR*|N^Hh8G zkG4)4VB{F-r&i=}CXq)4?(US_-i5cZ)bpFqy4HQ(a+Eq@CTgO90L@6*B^?V)$8o8} zeoqUD-9>K}4LMsJi>W)xB}^ z*BPnN$+p<8;Pj1$jUhFVB@=@6O>r$>g6Q{CQOH+Daj@qV)WTQ(IjoYBG_ic*rW=_m z+^H@6_I)O>5TX#SqB(`BDWDcPqrkU{&zA|Us(%RgN=VgElQ~xT^MI$Z+j`(q3#n*o}t$x|ADaE5jfX!>Q zs$A`Lp%RzTnR~q4!`K&rAIcUfCcG_B$V+^e-6Vl6a$n^+u!#eTy9(0jBXs5`NlBS= z`G6Y)UHB!NUu=&*lp@JTGr$y(&%|G$lf?d3CC@MScW(-ACR%A91A;P55lq$8G-*O{ z7&1mB(5tl_|5fi(DCHun;;bhrrfai+p%B}L*Q?Lad1bP<(0HlTA~s_(aYW;j?z3fo zC^AfclKxmzuGWYz506C5o;KRpAa)dv5sXfPU}_qK5QorMVla=i)Sw^O0xf zGkdY-inpZTT)u~Y{VVD*-WcPeCn>Xy`QLXNP~FUKan0COyCD}dT+!nK1_T#LIFio08Y;u_qoxVsc75@?~gyA#~qDbV6A?heH*xcvF?NKQQ zA5@opdHFnSDm3Wrs$9+#I(%|9_ja@P&*hok(C9~HNwJBH$dOArrW5 z2EcfzT9aBu9u`7Uhw*Y8XzH#`LmPM~X5Y#66@@jzs z<0Pf4{f94lORU>BONUOU8c+kIUU+sf!^m7sTYD_;qDsTm6B!D}1Gk6VZn#8>0Q~}5 z?z!o3%L^zQ_C1>`CN->Z-H44Rw=uq>_%R^3 zL}!P{X5+s1#e-#|7=vN49K9YdeN#ObH^C3z_7I9>Db1+z(F#+p1!|vfTb&%oie%`2 zhlFyCM=mvR4Mi>@N2}S`Fj|y1;5(I?NeeYZjU<*~1ItRc53sM*|DE{;mxI>V3Nz0h z3v0frXWCgh`$7MVKmJ@f)^!%BnLP3*#V{#>ut)G+V(PT>P00ZGKcY)*X(+@hm7U*FQj_|_vHV(f#TJdG42 z_ElBvy?(ORrk%HH9$28lyDOnsLMQBw#tz{`Po zx2Z64kjKHsWyRzEdms5B4|IwmiIa|?c%`Gv*0lNB4gF5{fQL1**njPwc7wG7%H%)i zG__-#tegl!9n-VQ7JXzZsKOHEH0bSMovH+MJLw)#4PFKoQ%4v&R4_+ek_I&tZ^Nd* z@bq~zy|+aq6iJXw|Bp_Q&$E<|h8?=ijauvYawwi^I5I1_I&*Ag{^@M$EYM)1MqX~H zG#9iITB!^E1jFI@v+gDx*?r+>j81S6Cr0@2`biC0Q!48{^gEXIGJ6{?9vNbkp@+NE zS|~7Bg6zvHaIepmTYS}trGgo?lPkU{ppO&G>K16jBF+PPcsN*vKHR)y%x4MwIac~& zZ445sC)ekW%uooY;988gl8#FUWh**v;|HHMrpQ>z!q7L#;=-0h@|ThywLRWTsD;ej z$=El1)?fsR$tiW-^}*0jhUNf07Y3^}g?v(GBw_^9H-(qroHz6w_e>$hLUAk|3oK3Zj`MvHu@GZYG)>7Lu^ zjaYhx0dR9b(A|^&HMZ;JV91t9^+UppO{od$%Z*L|5-x}(#q*#f82uKV;AUyrKoEmC zB1X=!T}KP=l6KN%)kv?KSM2(Yr68PGF@@R22}^O$~vdt_3WHT3=k zJ5b{&o#iggh}{UpSvoi|b-bZ=;^3YKk>5Swz-=0mba}I{bmS2(0AZ|-&0eU-fI)vQ zO?Ebhh58UOL<;qj_9tybzX-(FX#K)S-Q%OV^Je4Q6uuEf6mK>h;FtV$~tE zHC`7yQ%p&Nez!$trjm#tE!9%-yX{z?&$P6ao3mP}4P4&t^uppg{+G6}VJ^%oz2|!! z(W!sXSkhHSaiYsH(Vnt@S^`ySP2K2SYU^Ii)^}$mGqZ3IYWZcGgMmPe1V`UL{2772 zpd)$-hs3gqOBs37`^YIDYm;+_CdLuBW*IY#-Zqg}fZux{t@v3Yx$@3ty{zV(r>b*A z4->ibE&(|wj~cOQPp#m10VYPnEDDrKnfv-~2Z@m2!>T>K>S z!SFcp>7MX5eqMsv3}kjk?K(`<;%Qe9KO#dBb+Z|V^6u@CcnD`m8r4)O!9HXu@)b3b;$twB?^n- zcejhq0lmke&t5FV5zChX)q4sKbw02{n|nB%aq~;!50Y*_K6*l810IIMArg)Zvg1#1c^w!c zDGMqnEQAymDrXMyM;Bza7}R9cn53Kd-;s`J*cF-x@rqw<|EfQT!=}h%QHgC>`#Ha* zYV4(sYrSny@jSD$_k*%F$b8K>Z^QS+U}x3ydN`23Rr4+4pz<@8RDEw&K&~Vzps>Cm z+SJc_r@68yFF;&K%)0F8uJy_1(IBWbMD0KwTkh>Kw*9A1O|?;`>Vb~ox61A8=#TP| zbPi)&xLSw(cW7?PKx#&t5JDh)H_Z3yr(#z7??GZGHlmw&j-k`4NpA4Yb_zX&GLu-?tNhFD;o>zDD~epwjDb(N z_&DEM#ZDdmr4!MY^m+(MB_jt_B?n(7k&Vtqo95HdzrYVqPo7`gNuE-E#J&C*%lbLw z)1D^skb^vfw!A!+#a`XIubaxTW+3ik`Ldh?J@)yt*Sx9gVYQDM}SBi9zYv` z;(-$Kp_~lPkr)t_kN*`TYNUU>c-(KXm-7YPKLlc6=}2HLmh!HkOTn0AS87OdOksJ- ze5!v|)MG!xCHSe+kn&^)LJ0$o0W=;~-+wiHRQZdeyPk-N>Zugy?Qx#8B5@MUA!A@y z=75f)*(fj%6~xfnGwk1yGK+`&iYjK|qApIIWsR0jcseXphfRz z>?T;K*P|DjD_hg1Hg;WLPgPoF6cdxFI7lR@{L7I#^g>X-QUAWRNGqyU8wEFGMiE-3 z3KD+ps7fNgeP6uazF{D()d*Y(O(U?-v#8x^@m_`;*9jf|l|6l%+v2!CH1#KZ-9Wh}p_uIw8Z%j%ka%1>|oxEPYjl!Sc)HQB- zh)-c@S`5 zq4ZM_=BVH7RL{|5`R3%!hWf+xMRba)k+36^!ZwOTFp;{(L|`510H5yH6KSb_K*9nS z4uL(6{d?&g>2$(;3;?`&K|Gon2jn7BAs-E@j;jfRc~n!2>%wWqF~_hJ9?51@xH*`g zUY&{rzxGrN?aAyEO;J|oi5mq!x zM23cF!(FNV>Vq-NaO0VZ3MpA|LYcLJDcah+zStPtjF1rsWU`ajuv4)6>Xk39@M_j| zZ+h{`+>h%5a>Zt-UR(XEC~e$(vE}}~)K~*EPM`DH&hfYNW(iN2oLlj<#OHl@c1_i%iKOxRKI^Ai z&w9|jXFSj5HU1&c8C2B_L;%fp>yn3HQ5bFz|MjyvZpyEr0Z>dy$^K4JB!K$i=pDi_ zL)g%BT{}9hkzgsbNz&Enh6pBC@(GHiF+z1Uz$}QgkV2d*69!@>lQ|h_Nic0#Gg|rG z5)pW+%Q^?rz4eAk-*F}@$bv|as~&DbE=+y-3L!Waagvlc-iZ?B z5J;+{6$l@M%i(No>E{;o(Ct95@_W|yVfr2>vasaHQ(UCfm04$kPGHj}|VFCYi zPKRt1EB!uKG}m>wyV?9(V~x%D8Eg3M-w|>JUf(dVB%F0mRHqg(M212F<=12&W3ins zlsKMy$q4iWoi;SO~PP{rd_H6=)&=C_*j+4Z^cs!&rdt=hUelHgK zX)6q2dP=L$AmFY%UA(4500Z{<0~*@ao4C?^0B9jtw>jVJ2TmCDPMp#r^YmLXU7QWdM6dILXq z-}|MV9V#)97`H|)=~|WE8ttau1-)yYi3$8BzrjTN9_+CrT5s#}w<~R~%Ve*LA>vn# z#3a-D;FYU_hR>La{LS=(@`gn^^`MKe?6aS>1n%gr{mbc$(P>fK%q7C|F$>m6SkV8d zRCPFhdodHOA_9=2kKf2cm>Y~~d0$LaIEWEZsPiGiyLVS#z6jAC1ixulmG$vDd-ceWVpViX5Vl^xz#rZ z*ggOBsWp9BJ5Rxm!^jij4tzYkK$mwI!CrK4Xm3zO`eYu2$!|Pikk~PNvVHYnI7Z}B zW8BmI#hTI3E_^4EZAB0(^wG$RsTTY9vA49}k9V3mncr^12dMt$E}+BXl1)JUnbRg{ z|DNTQO~?|C81;W)h_lSIt|3wg>4HY|h1g)dV0HMAYN15-y8-G1dMGc^7IqSRk&vDU z&Yyz@-|kAr&SoZ>0G|}3iVLea9m5N#HU8QW&OlKMq6}lwl=f$9c?FGaG0dVSn6y9=>^gY!(?iaAEHW zDiLaoXLq@mv!@+Xa7-NK&USB0gt*B&+gF-IdBnfW+1QT34n->pvNNiP2rOTntS{M$Ab#u7Qv2PEP;|r>f4q z$Idr4=EZXy+9Y4M_0AEy3=l|~@|k9gC196*B_W?YobxyD#PkK$z?33Gz|i7_=c#-m9Vgp$iCsHs+sr^+fhe{{%GBl6wIYh z*G_j?ulyOesj#64xG{!D1pqbZ0lCCYd%PYHG!B+9b=uX0>&33813TsX>T6uI=!)ao z!^hAL%6|mn`;&ufE6@1@q1Zk&H|r9&Fd1K{HnEiK99fH>9gd{EWM(G{00BeOa=?lU zA)I6|l4e^Lq!+YK7oyI+3kNl`F#p3cGM7k{FkWq%V;p$=dzLA$TFk4i9D!6+E>FZ8 z#s|K1V8dUUc9Bm0cB`&_yp=zy@SS=V8yQ#d9wqzu3I~ux_I4;NBw`-AO0kHC!G={9 zCM6pR1{<)QQwI5`>4HFIxm`YE?=W@!+Xm!|l(HQpi6v3;ds!q&_W>A-=9+a#Vg8{7 zS45`ZAF*Tp`0#F&Ch>lk@Eop%8GRyx9IBfj9_)jyZvPqOO<+!%a(>us1wh?){RT~q zRQfB89%dM`Q;b!ilh$sk;|kYdE)g&bkM4U*?+m|ESYwxvt?e;c*SFK{z zFX>8dmJ?aY`ucPEzKo0Pwfw-;y2Jh^j5T$=O`dJLKNl_hV|?(NjR{Zfq{IH~hiv)% zIX~u2*=|V!6Hpi0CSoB=*k;oG^T7o#VT2$|-6&*{0v2E+EA9MFZoeSnB>w01!yTP_ z<*EoSbn$ycOY7g9w!`O&?$b#M%VXo6T=GaQF2^e*yPk?oLfnLzK(UYNI!O6dkaa{> z(+Gtv5C|2SmgP4Kq;OlP3Ad8_vx;smaok8$i<=d}2^Dx$M=59}px4_-y^i(f0#!}? z`2*6A0m{1cfM4s;5J!+NGcmF7mXAh4DSE+fr;=OwngD8@okUZk1N^`^+q*cR_>Y0+ zi6EwJB$KV~eQbYU%(&3-JXsKsTWWt(o2QJnpYYumRHGHbUle#Cw?sei0Lr^B@zPz) zB@gMQGpjsOXGgZV+abt4%*p^6LplZ@QQ;bRFQ`fj4>6)!ZXr0MsS*fz(GLGZ4X~0_ zgs3xWGPp7a;FZ(PqE@ib+oDKG4~D28(v`kfCnY;7iq)&z!O#?Qk?N-m^SAx+&$zh` zNzAg3JVdO|8267Tfj%ea?$s6bI|{|(Q_hDd<1FzDi~G$=`n9`}Cka+wR(LUy+D;ZCcR=&_)zvS^N9cgP`>8}Meu^LD#|4( z2u!NV{v6^&{iFTa{h9hh&wN-|PT^-JUANRToCt(z%cg1_L-GcMSeDImiS1j2`#uB< zl(=M+g=x|Ihqcquf^Q)c^Afj|6FD#ibOe!CVL`1hy0wyO4sC7XRl(m#&>SlP&RqPG zYoYioumUy=EAZ_)X)~j(DA(=w`JkE6{@5T?U>BH(gN0>X1owcO#CvYgG9p$_9acDf z39ux8Xw;takB5?xY5;IHuRCzhQ>(nW$D;p8NC=1@B)36Eu;aucjX1OJMSt*C5a zRMx%RVXjn1v;6lZb6XZ%7OH7+PXNXet(D-WV?d9>e|5l0zeypCy{&54a9hJAkMtE- zV_f?}A#D6#*TBlfCs^>F+OgX7<4-zu_*{p#kpzNdGR4SZ&O(lK-cJU~f$Lg;K{yl)k%w zcOm9OMtZME|5v_-Vr5_5NvgnOu}DgO`g_BKEjjM^U0NC~pBPOCcDpm3uk8|Flh4@x ztH>7vc^rY58HHMf2LPNM;fPK*!_d}91`rYiG8?KTj0joVj`d>S-3$x`Z-1!yi-hzN zCVqmrDx-TS)|8yfDToEY<;zkz$ZmcK)Urzd_zi+H-bcZXgb=rWP=+FQJeaqFczv^eo zho?-m&S1cY&NU%SJ33?NHJM40hp1owb>wgOc-)B42Tbjp1vj;I6P%!8f36B9o_&}y zmJq$jKaHKKVKK>v6tbYO>I$YzNjIpD!lKuM3 zge4vf`7yT!m|q}6@J=AcK>+}GYOAVR465DRSIZc10K}z>n#_bn1J6{RybH)r)1Q$j zeL1J2#CO)qg70;xa;LY7(Pp|L7@p5SAQ>YgS^DdvYcruPU#6oj|MQ%_fOB$gT#ln| z9}{k-$-!vB+HD5>ODxq{KR4R`Fdvg_-Gd;;qa5MdNu~WcAu5w}Kd1?JtqB3O>{GCl zIX^QZwd8<6fx0#SIOB6l%GE(QPvXF5xuJsJd0^D7U<}D$#I5Ui9DkGpu9x1Q@M%jW z*EkzJPDmJb`;N`C^lvlQEQp1Sig272@CrE+%t+cL5IADzJ?JdMCpbr2RiFWE_l+Bu zM1A)Kb0v^8(tC0WA(~czTjt^PrKKg9iY*}_L0kZC#Jg{GC=5F+ozg~llrC}<4&1^K zj;4WmTf-8_*#PRs?svR|tPg&R@rCU~j`+~GoXRqEVGSi-?YAOgN)+}|4ZN2M+~*q; ze&1d^8Bm)M1@YGiB|10E@ULY#0`U?2DUT`FEiXsQhLqb<+7f99A`Se^?(6@9h3t#^ z8iC^e76k^sqX-74hjsVtS$}UK-1wsJOC5}cx;dI?{$7*z%+YNuIW9mI6oJ=hj=;FV zOdcY|Xz0MHC2G`ILi|AeFo57Iii-1#JL=D%Sk5RgwdsB_PaQnlWO2Tlx?&5KfA^u` z`}U}gqGaBb>cMJAhBxeV(4-WSshms!ynqUNZv?t1f+-zsCg>StX}1cQJKr zjGbL~hiU)fej0C0ofqF-LVC(@Y%XAHaZ$?YQ$E*1r6Mz03R9F!fE3vynx;$!P@whk*rope8(8vuTMb?So|P0y$!Z2*;Jv6&fl7%Exh z{YvlM*9@1Qb%V7}IoBCU^J-1(uht~&<}qVrTtZmp zpIRS^!+yQ<pE%>Pw?NQR$xrWk)0!nDe9-Y6_skWE%PvO4c)wj(5 zX`k!VHRV(<{&u|VsX>n913km9+SE|T4e4L`aE#k9JUy75hx9dSKyQy&KhrDEk7h%K znr3@+S@38B?|Q|$af!IDW)jx&<@s^S^uK-Kqw2l78g*Z7SB@AB0?y?smlQ$S{?^7 zVcS#BPxJ+T`t9?KhzB(RkAD@DvVs+1p0@o^|DTU*GBBSJM&Mtt~#-Wju+JRkV>7j&#yhYGz5r?-#d}a1G;*r%?j-O+M%#j%_-{B`c+4 z9Js9hm?whWA-a^Kt#{6TMP|%ATqN98r}*4uZP^lth`t=dj&FmSNTUs>pW%D+YwJo- zR~=ixEBn0zGGZS_votMss7F?(=&ZbNy;nxbM)TUo`K1#D9*u$aa^UDg5^A;z zN7)$Julwmfqf2ymFhKeBICv&X2A_5Kl@sX6U z5L2K4u$U#t8juxzF#&vU+OUmBPrxMRUc`(#?#z?w47#d>$RmHJv{x%n>9gz zL%zLa^=0Ljf6xyOyLmAGC|jT_)ftF<@O_@<=2q++k8T3ZAQDtxZ-$7WaXsRjn(_1VNzkyJMLOx^F0u> zuc+d*i-M)o2-6GK)hXhs%&T9|e+GRpBSA#T{|ad`sP3r&P`iF$)M5_BVx$qBg8a5J z%P*!zSa!d476@0%;^W9)4WM2tom(~DU$^FUS-D!TnrEVw)CS*dxg0OA2>}3`QS7!I z4m8HcZBs?qUlAE-FopAh1Yb}98c;Nj(^O3E<{@Q_OV=fG$VeIE1aJ)_?bMdd1wb5P ztJdFb+o|{i6;X>r*F;F)Z;u|}^BJT=wiFw2^Xw$hdURg(Sb{l0AXPcUjZvgU*s4!d z*UWJM^ROo=U$TL|8D{}lF+36+11#$K<#u@v!WxPI>U=P|Zn_wbu62)yRxgD%sJQxm zrse&zqCXHQHE5Hz782?X%iJ@C1ptI7;_4qI2V=`Y%BkZwvcUSyYrmDyQdJxXn-L!2S#aM-DE z9c1v!R}v8QgA5GdEP9u^RXKTu-M_4u zqBw;J@-iW>D@I3DQ`ZS{YP6%j%=XQo= z2i@x8L3QznLGCm|3fn>Hn99YZ&X$b)j9)NdS$chYyWx|}ZbS~c?f}AAeW_($Z z*2u)g`LX>za1JRq%F#@;n~3<3%sXt|7U#0RgIf1zYNR>Kos(RBLnUA}HQBN^&kLwvE%sd^*Q0OwuNDoh%>7sckW z3fpZdEz@y8T*-uz@;4Sq+MKOXukz&!2de`%2;5a@e9P~?IK6r9#VOjX|5)}549K#pl@eh` zq;xIm;8e(U@s@`j&L}uI!0;k#{>fN>Nn1L0)c*N~EIV@6Xti+lJ2O zWaFNl(lnUXp4|yd#Eocao>66|)sQ5$+U)HS2WS}#%Y405{~qO2yWzt4zXM!Fyq--yZvlaL&Kjf zWK;oil$7RoKYqB4ugwYNvov+z zzsWduFp;6nJwwz(wY&;5v_K8W(OU`b|E6s{J;y0YD34<7{%Y?( z#G^};Z}6fF@z;27LkY$%H(SB+AQ;gvO31TSZZSA}Vh~pO`_W_kA^R!7#dfltS0%^8 zRu>vLT^h#s7Qz%R5&fxg$!ecDW?OJQ+OZE7wsj(;7V|k1eLMi{vi&FlfBZHzAe;NO z%WUf%22Ku~DcWB3#tB`}%qh`YWAm#d&}4W0#ya>A5)+o_A38Owz+8{mNKt*ctIn(c zEiP7GO+_wArqpDs;LrT2qlwr*SWELax7urY0Py%fv=bB1a>Woqy{qwim_C*?or1@u zy3aX;61|a;AtcHKTqFqlaoN-2Dp;S|6mM=KS=G_0qaL=05*{BP zzwx+31dx-(DVL$N)$t&wOF@sdK~D}ZK805h91yNo*mwo=&qzppb?RwC!r>4w&~}KN zI4GNNVU}OLs0H6Sr(k|Y6 z9#8CS-gRaxO*?qGNvvtM>MkiH=c+2{it>H4Mjm>~Lc^4*rVM0a1dRGC>5zW$ zFY&UQSL1kE89Td;Y2ilAS4=1v4e5lyTc1B7(9(+FGg3-{Gd6$Sc4WQh0QZl?=$z;?TjYRh!xtB;aP{6VoW zJ~q(N*}Yww_D8Albv_ZcFY+_ynVKKK`%W`xwm!~uPU0g8dO^_!-q<{?2kZ}^_`?4q z-{X&I`=!V!!*Db8h|Rbf@r_7VSGN=W5@yktYJDfZM2!DmlEW3yHHNcHB0bE5{6L!Z z;yuD2p#@uBm~>4oFht57kc?{A0exBw8YR_YYcE7BHw(twjqw@cKWd4A1tW@8xyyj$ zBr&lWA3eK7nB0yCBzzhg@&LIR!H#-cMy#Ue<@0_KTMwraWh&{^mFK_q4BT77s053~%{ER!9aFG}<<~rGI zP<`eoiW@yTJS=wsM|nBXM1q5oZ>*1Wz>T~01q2^qt;a9JP{KJ_egQzc#YelReE+5{ zua{JSc0dokFp;H+No-D%xzw9e#{3DRmly4b>NFQMS4W8Xe5lw^bG4J#SQCvvH?%T^ znI>@i9IFLOhbIuJrec3@;LGWCR=r%)|GX(KHbg)|S^?X%-?z)C-~Z&(UmUeb{fplE zGJ(`vcXqHaZJ)qpRyeBeXl~p1*=#`srA36mt`jFA#`iq7`KSJ!m9#p4DxJgc7jpP% z{=E{mSE*_p*0Bb*8avc=c@57EJJV2Xd)(K2l&>7P-mQDJ6E@eE*8td=91+~M6cA58zKal zb>xS^=&iqD6z6euA=IBl{cmAGz&4;$=VNbYCY9vA@p71l-zzJZH^fAk(-8}6go$x` z$5K?256aEpgW}aO_Z!H>WP$8Q-zyR4K`W{@qV!&_T1hj7nG32z19| zVuBkrP)a5H;?2;_d+hwNBf~m4KwsCuOcP!{)dGDm3rSjR3IpfV==?kg7nhwpgy~0M zZkH{$W_`+Q8UU$i17;Ojvc~-eQ?j{LXb+%xK1TMeQ(t*(>`In<94o(dyR5*dJ>%rN zk;0u=MJ_O#dpagKHwIP#amgu`CmZu2e*4AS;G%Fp zFAdsH(W7qR+G=IlHcf8m(05hfh}=#R{_V6aFP|fmeKOF8WXe$S;YoLb>ZSuM(2aHZ zWoJL|`gVI@MOT+Y)kS%#);On{B9AoqGMoZJ01A4-1K~W(u03o$$qCgYYg=Gc2@=*mfBuXkbT({6x_~+& z#$QWGnF09i(PIe{*{5g*BSIiY-nA7Pd|oL{=aOnof$-9UFd!Y>3of>^|Nfu0w%zq1Hgt6JbQO4@xqW8pRwr8thoiQhzAz6PJSqwvd@l%NlPtIqe_{1S^R+WI^vp~G z$x?~l5JpPqZVWtoJW5&GyQ^*9*D>M&oi8nxo7kVe1V#ozHuw&nU;v6BG74nugH|9po7uo0F-=4Fjfq za-Ui-aWt$>LTLibP&uer17@02JG--ub9@Ad26-)(K7pjrfa4m;cNpQ-q7b&zoWI7p zjL>zh8O-NmDQXa*YqiyH1>fQyj*eAjcBHZ`jaZ=O`E`evDDgF3rxLsO@VD6Fo}Ez1 zLG93wV*`t|XCm$waKfse4jB5Ke48RSgU$hne|yC|;0hav!b94~Kg`%rcu4iH%Y{be zJ(sYU!5o!%bYkOTht*Vm%8&RKTST%FYy>H^w+6TV_$>3KApgv)S8Z*0q8-L5`sQM! z*W+5r)wyb*7pfbFL6)SgXeCJetbb(FbG;u53sni;{Iu(yqK4;u`|9zzcG3v|V< zHz#Eu8Qi8~yp{36%CJ_x7$53nt>rSh>M~w}R5Q?(l=C#DaX3 z4r?wq@~EZ0HGMFzipUjk#bQGQuoiA|`cdhr8%JGeOS4#CKED8LOmJd1E1`XF`YuzL z$Ee~Bn#Up*JQTNZ*iV`hAXVB(xAV7$yt3TTBgnyn%}@dU|)wrZK~JL@88<-#KWGWR}Mi-GO#4^Ll$+ts^Y324^SBb zR8+qhuHO6S(q#hk2GLf&UySmtrp#K_>x_&22uY^f=fqM5A+bPAepbelmTjYwduA)W zLp1?*nYOz+T&_9Xs%`sLnMioqZl`F;e2$xqQ`u)g3tc-QJKO*253Y`mi<6U=hdY$p z*X4hHUVfzN$><46N^&Y^jk#rdrc#d(bSWHw^KDR1c={f&;iaRa^PY%EMC*ezy*RtBCgYDKJ5zeSI{M^)V0x>+|Yxig1UNI$V6xTLT4RcovcX5#|Q&T z8vxWeWJo;nj-R42lft5_xd6opk2VIvTtc_#9C0tJ*O$KCE-o#b_4P7)6{ZjOqpW4R zy)UmvdEKmyl}0TDBXR}p?JlB2ETWB&O9L@%;giA5Hgs8w>5zN|b z@{ToXSk5%ie)nVsW;@J~G{_j|KGth06dG7&{00u&v`IA}a*4v_!>&-Jfw27X8Cww{ z5`%0i^ovVh^TMdQiwTOadT(dE)jHyLtpVZ-saR_xwa@JwIs6;WJL1LE*&aDG{g6jg zkR)u+8Ln7$v0>Qi9D!ZvA}tB{iJNALyFrM=!n_zzzCZAW{Y8f}e9qi)<8`gEL657$&b*O>c?xC*b3;8_><>-^#bUn#JlsYG zcrLC4(mimj1|zKl28kTcHJP1Vm&x0orN^mWbz%OV6_>{RgK~HjC{ zw)OjUq~1Tg&Eea6-M;4}RcMh+=2Xb{b%O5W`f$1N4hzsF==x{z`&bACgU&kmnb2zW)7f^Q{7 zmCzNYnE+1c<&~(i!*SYA9mGh}_Ix=W1u)-`i{QGM&Tm%%J&`tzcHhnSC%Wg+A*v-;TCd~;L>H>Icf zZ5>I2y=Fkx{B*OZ@YA+!Qy!LN+h5oW6``3;{nB1SwkSmO+Tr1V`deZRv)`P-F4MaV zDcj?2o>45M9|pAnldXG_s{R#eMv>ISn-j9_hY+5qH1Rw*7}jd$TV-9d9us}GpQ2ic zj#%q%RQ-BsBjVE1QSa~NeR_1--pXE^-MN%)3R@D>qm!89EO`ic@U>Ba(ujOOK%==5 zMjy`CQEEYe89zB5{IG$=$FjQepvQj&rvCNM12ciljtL`V^uo>nkE`vO`|;4>O5KIm z!-<<0yO_oK-)QB&aN3_Rh>PukvY^0Rlz34ZoK?WPNdTf^YT;HUo>At54*y-zwTFZ# z5w@;Ul$>0ygwW&aWq}q7E6PYaUEW;De*4ZOAi>nB%Cz$|p9>M&%|o+Kq;+s?8JT5U z)^Q7fA&ds9B`~a^r+Pi1*nfl`$I2CHeyH4DKT7;K=3RJSMn?O);bYv6^TyYVST6lk zuS|Stvc5qVZs?*mPTtVpo-K8yENF3fhLqJj_~7pi(hAAo zj74JP%22LkCInO~u=Hk9hTc2iFe&IzQEN%tR8;4wB#nhiL`sT|A^kN1D&gC-24Im* znaWi#5&d(&{s5KmW9qE$+Z#>B*J19$lWqk=V$ft1=DywKt4lDkoTV+_Wq5+<}5BMctE#12Rh#8<7e+~8j&YVsvKm?Nw zxdT;2W#%NQ7XS3f#{~1!T&=?#(ka$Mi;Z7uf$Epp>1TGUoobwIQ+d6c*$Ci_mhY>} zg`@2rh)?1QiD&Ht8Uzu(0?Tx$Erj2cY8JVxYftyH<>k6x%D z6gT!xAD?}?iW-L?63qPLkc^fQev#NFL~3Z9S|<5NsI`o8ReUUlosO^&-_6f7hrFPU zY7vd}S2aL8c~9n+`>C!8d(g@5u)v1l+id`Mt7=L(KH2YEnd&YaL#Q;T6;SpUIEIN3 z7lhmQ4Wyw)!~HknX~RkLiX)EwN&bRX2BYo( zXte8`uEW6LU`dVHE;pteL)GCZO4j}ozqCLf*wZ_&*UQ)I?`87}{pO&%|Nj71L8-ph zr{}WeHDV$%CgM`P!esJNY6WY!22x(w69#w@F)1_%rWGlNK*sWh_a zz{t?&pR4`C3wClStZJ{!G$_~wLY_$#AbX%*|1W;J{L`n_{`l?Y4=%}agDNq{Mm?ai znUhjjkf^GXsET0`6^IaoRaHExSFxIp7f@9pRYS~dqe!aiop&pZr8h1wymrwJmurV6 zYiACQedJW_*i`k%M0bIZhW$R~(WnX{aenokYwCnTHz5(@1JB)EHf|msYDB_pM4j@~Ol4>Ql@s*$;5Q7+@jh76F!AwL< z28IbB7;xJSKuFzEJDyL>U}($9ddmz~YM*~$=nF5!CnkWlFH@NQPaw3}4I4c*G4j9s z+195|uYc|B=1;EaMrwvih>Y=~U<)Xz!Z0aRSw$6URFy>`5U<9nihAjG074HjK~xAr z)`t7Eh)Cv_&s|?ScYXTnuf-Gfk+a9^XAX_MaI$)Q$|O;+(t9#hz^yhnuFev)eL8&b z&56j1-<#oogy|*DaTFD&>Y$=f6|!ShV(zaE<(ykzUk3o(<%f4H@?Bd=xLkBwwjBqc z^T@W&*+Fvv066EaUAvB*tEBu;2mmNHrk?0>6YWxhhg4iHDA-XH5P9Tl7BPVY#v1jy z_U=u5@xdj;U3=X!otFS0U0z?mIlprG*8CfnRxZsn?<{328%)fRi6XFw3&8?Q}&^YzmBQ1$4<=u4+Yo%!itG)ZpyU%iF@rURTby=tlB0KsfdX1LsvT#>@yTf8jaS_Z$X!4v$?pq zWQ+lb*>o=^l-%s*+U~XQyYpb%t=StK2cYvE5K$-r>TiCK%Skj=Z(UtfEv){6J%oC% ze%l8nfuPEyPMArF*bp~vE@T^xs8;zv)A@eWd41*^vkS}TZZ5rhb@kHB^5yAlWrI`+ z%t=(L*N8yG!P5vLoM5%oe8F0AB zt5FJx016I(LRq1fSX3q4ofV$Ef*q+s424kxntKkh5mM1uz0Vfc=VzA}Uc1DVq;_Iz z`02x=&z&4Td!#fuLT1zFR?&w`3lM;{i_>mtBd*o*9+>vT;Cmudq+a%H_&+5}W z83_QFB0D}5219GRrnpb*DJaOvuUU_FBod&+qzq!Es1&8M%Nti_hhIE-_dalMJFj|4 zS2k8IO|M+Mwe;@Q(9P0B)l?be0Wi}zYAIf;TdU=UW@DSQz zeQp~;LE0Z%Y9*M#_)9MQ3O@--aEhc-i_tAuHO3EPvY^~@R`FSFPs>D=4kckgsqg?I{uxz{s-J=2$K1Y zYjdPzjA@@K_xXfEv!nCbV|{eHg?Mj_DNen?L&cj)67(4Q`|VCo-(Fu|55iM>(A&Is zNl)$^fY24Ova%dBQ~Tovgb8-c(O6A`f<$5Z7wio}Ir5{uHZK(*f`9-UCyj-b^{aEa z1E6_be+c%6mt<=j>o?}suH9L9^U~_I*|qC)+1dsHp~$B+GGs_W%pgD+OdwFM&dJOs z1oDYPVGp+reWrYzS5OM2O%pyh|GO4VFeHu4uQctU;jzE@^3X3lXU3{w!M*A9EwTrD z3RMwx>&-BK_i=9lclQSm|Lsp!KKa!8*WPOU;F7GTrd~q(bU@qmCP3S>bp-|p4@sZk|4Q>-}AykE(j-^TfiQC$v8ng+K#? zY6zH;cr`;MGg<-q>;bHt%g0R3*#eNDUf`u0R;0D=QBGjqGyY{YS&lSj6e zXt;S$(Fa`6e?(RNqo*u2#0!Nu$Y?UNpmFWCI8RK}&c#cbWowOvcdo9SzqNAd=JLfE zx3b||8Hj8YCFK&BOj~_~!0mxt)UN8u%X>H%Txieh4Yfb2dFUU(8Nk+Hf44znNHQmj zO|F+me*F_eUwAP(G79w4WLMD;f=!p#qM_Fy6cJvH+8f4=mYGizUYGkg06n7Nh!6cnHHr?(FRrhLMeDk&j1ZvbN;Djr^y zM2&{#V0cvsv4yCpSMdlEKq{(2L^0bq3LX5}N@M=V7Z%>QXevqN(Ae9rE?`8R^ZN)nV&;hVEx_x_QZf?F_AMW2m2!N?qOgZviOvJ$jD6#pd_k(;l<%Ez8s&L0@{@l zJu&??EQr$O^{c=47c<{^^Z9@HrSX?fhjB}fzx{&k5^mBPw-(O*k6&B6cKfaW?za#A z>_<-iwa=Chj^goC0od#hhT+mjjwfdiHU8q#`d8n~uFY{Nro@ucmh-EvRjc7}RSgF? z6iQ?m9NK~*EDTi^gic}cEULImJ_zceUc@j7Ga_h`i1$AAYnNwM&fT(=`0Ds@_1NV2 z$IlEMKQQ#vL0j&Gz(~C;zjs5@%$BQp)!f~ZCLO%b0NF8sEVm2 zCX4~@)4>=n8uRn>q1Hcy{5#fvzv|4lC=uNo@_+c$#Gp9<0Em!fZgFw3ziR+s$7^ON z!BPu$-&{-!1`^6=1U^>BQWytDq@mT8pfmrwrn&mR88kM$-MfX)73Dn*sgolRajzVWSdjjzA!?yQ=! zrO39U{9UhTmj<;H2}&T%J!wcN3xcY$A_V)@gmhi#4-Tq95U)`9Fml+dXej5mR#Y^B zh_q%Fn$rt&KYTwLDi57HR6luO?B&xV&mA+B1gecIv*gqmrqC82I^*v?gMzBbK8vOk zy!UL(zFKs_R=Q6cRfWRVE8&-Z9gyKNe(v1)-~eb|=DPXUUG549?#CAUJ_v(8T4B;Z zoIPCs;!BmEIt`m^sQ0W)Ka4G7YRoQO{;h9KfAe)|WwsRCQnK{cwM+lg*Pr`Gf0Ydv zJ;A$-suI(c-~RU8U%Z#pEAVO}Ya-LUIsfjz_`SJT&!72Qzfe8V&H_FDSJUYau9t_t z^pWx>POg3Zo!0j*$V!vSF`4#Jci)%hd8+)cp#erg04bD7MWG;7Sg2P~hKl&0BgE`T zM8xLl0uhA(N)Q9(7=Vb%M!NXg#f2YVy#7b8mPTq*AAhEDXgr->G;u`KR>{SE#;p_->;hY+hdeSN36Pfnh4EWpV@y&ldl6O1i+qSo9`)bU z=wxOCbV~d~H!lN*C|B+euiQ*=-W9HWQ0*KORHd1!m-zU2?H6CD{>)jfCO}VT`nJo5 z#QEuOymsj~zumYsXUnCiQi3X!N<)=ffBahc(DZ_so(hQkuUy~Nuu6Vf^GH(!yX(S`8%IZKY42XkKb+mn4-bW18&@CgBj}h>!Rwe%x>LqU%7I+bIq0Y!am?erx zL^4TdmTvz3Usy7waycm_tnGH4yJMFW=Kk(+>CX>>$cu13aHsGA_B9Fsq7>QE;jw-% z2CJ(p&1N&#vQrIncEg{7hrrCvx!now5>XH%>fFt@NRfv1Jp2X+!~qC&J{J*x;lf4q zdwv86W~dCHZ~zMWh^UHlJ=+{9B$xLz#1XNwAz>!3#2s0lVE8kI5`Qo;fjI>G+s`q% z4?tm}66H;a4-xF&{2Kv~W+rJC9UQIx{ByORf7XuIfF6tUbgD;IF5bHEKYe5FFWxoA zl!mIg08t1BM?{ib{-3{DIW%_g=Uyt30K0@LfQ2_MpZm9e#Gp8ek$>|P6837y4pr0D zjrac5AKdP5I@C`GAXtyfODoN0qq_sR`#E6{ z@2)K=H~^hB5Yd+UpY1j%50nGY1>L-P1KVtf?llTfbZ7(=F6ixVsOSSO*j;*6{L_Yr z5axCnQe_h<5qS{;^5I+DCG0~KZEuZ;$*nc6fAvRKf9JdD+)7-pT4PAVM5cUCqOj!z8;$q= z`R^uUL!&RAEXw|N90iE7wdVPM^M`J3r8GWDP9u{aZwggaFXGjg$|WDii?3ez@wpo( ze(lr8e(h7qNSCAdn6!@oGF<-XiRA3T<`1r}fBkKDX_lfl-ZXW-6n4d#UQQj!rk?{HO-7~2Zztp6Pt$yy=`Y*qnoIQ|7P0>5kzbi<5 z=f~$R|JJvc-n?wADUa4kVTcTyU~q5{eOFaNnrUfrnB(Z7-b=w_LV&`S<0D`E_?7?9 z3OBQ;QnDJxz%v1&;z^v6S5>0QSUqdBF8+W2`G zJ(Ik2r19PJ>)&|S&#X|{aw&q~gDQf$-q2kha45PnK|}~dYJ|ZmN`R7OoCEtLj+alTogscU3Nbb$|O`F>JytJ2S*Ww zV0M4LO%Y+{OP8-KudI|xrOty}BJRN`-<|APr~0U~ch{BM4~u!CWk3T&)Mzx8mR6>w zCi=UQ>Z~Bm(*tM+uhn!u(t(#2&=-vMfuIq`M9$ilSX;1F+Uc zQM4tx@9r+{HO4%l8Guj@)e&l4T3VW&o$0#+VCogFCbE&i6m0+nyN&mL2LuWTp+ON~ z5Ru_r(=d-I<^}$FAw# zVnR^B>`g^bdw%fYk>UUHGo??STL0=>t=F!(M$-(%1m3P2fcqo|phOyKhLo68iJ>Y4 z3xTRjM9T;-w?;wuQY3=IQY6_ktw&(-&oKU|HAkPEjdj&Sjd)k&cHoJQt1tJi% znfX>49T^?{!pqg4JInPl&}-9wbAwp9Jbm%sedG3b-jd9hhikcpsZbnQOKga(v4+@$ z@n%GBr7?8&=z)LuOUaSZViwqL6FzL!vClnkt)2Tf-=K}mR7+4bs)pDJc~)X(VFSlP zUL}rW8{3U*ci#Qyzcc^ib0>b|XNOK42;1pdDggPRpFDFgIX%^Q^~&1U-p<~eCd;N0 zxJC z6!~1EF2e$01VH|hN81yDpsDwb)J#-IzWmYJ=U=c>b)eUszQ`y0f+*W)UjM@%UjC2Y z*_d7|*GjfhA%Ou|HcV_3abyiRSpQ6hm}Iq4e)h=Z|K{`2!I8rH?;Au=t$+3zW6k2f z{WIN2O|7I}3@HK3N=lyK2u$87Wdbi$s#ScJO@ICMrMIsg`}NNp`AZ+O<+zteSKB#( z;qp(PN}fN``0j;`KYb^=vB0H>lPE}cKI(>ZW1d2xX|8<)0tqWXs;YTAG$?mgyNd9L z#JT?6B6kXLE(kRCdm#neL{Y9*39Oaaj8^--8qCknU%7m_R4R%05=QqC142T<|Lz$7;~wLo(>L?7ky16Oec{FW7hj4`OaMKV_HWZ^_MLzI;)Q?r zjXSTNx7JohYKF*oCALvs@WVzqB5RmU7-_()tBulghe!YZ=c5DlaLV^^VFlZSps0TG zG)HFPU;mk`G)=vvUc(q4@yJ=nwgmiecb&L0t)+$ChLfeh%gn` zqk>&Ry#H{)kzTN+rMEXQ!+XEhL}bdJJU#T6Un)O$w9{MJkeWNnmXcbzP)R_orO6G@T)=#>u;`VdN` z(!GT}X_|J2|5Y_fl5MsB1_sIj=xWOlW6b&U7v|>XrlzL)*U$aCZ?2rX zkyJ{RdIcZ@j*MX@%f^xo);|*&;{QK;{}~|1b)5;rC)``1!$iy=5Cj2&IcHK5#Y~El zD9J&R)4twa+be7B_4~cMUVEL^-p{W$eCw4hOOCRFWh+Z06__b8i4;lXoO77LU~=eK zb?^Cp-0H?)0L*j`W~K)KA3-EI(_M9|y1MFw=Xs7BSHp_q;aqUT($-Jh&+VD|YX9#T z1l5bW&KLp+1UFpV_8%VV|A&`M&nUN~z*s~?5o94`6e2_t6C)y`5s1VBW2z++6-xWQ z@}vHBdoKNj`#SEp5)j1-;tbuktNLI>bxC{kzkP3T$IASRTZ-l(usZj4 z#zj|I4d*Gu#4&pMou}C7Pdwb*9D5Z$V^SpAoT#Y1+ zF~wpr48sZUa$KD#iq1albj+U#(ZB0Ij9-ak|DS3QR140l1i-AH6%(*;-x3%p6gL5d?_-br*S8E-J3wKla>~X!mjQm_iRg zV3xnc#yOhL?oJvB5s_F((fMq{jdRoJon43sF}Yw`tOZ2s%rtgMF1+5nd5fd^0D#td zysMs*2s86|OHhX}43$#FV$u0h*1K!BHP7>W-#_*3*4kpRI3c_6JZ~E1e>ndVfNB$f zh|A^j$jE48mjeJ^Ynq$G==i9+rK|J!j{6Sg0mO=&TL}Q7ph#?FG@{OI%Y(OP@4Gr7 zfX)Klzq-vhUp(@{+P&X?Eq`nvNC(REP!It%6B8+9MXZpRnUPqK2{G|I!f0U3zkOxf zuiwY5=~|gTm7DYaCtgFPmVe~k$zt9~1}1?!w}{7nyk+MXpIh-WcQ5qN-kSp(_pSK3 zdl%nxJu04I>3Jm$K+WM@mwDG-RCr@=?uT3B?ja`(K$)%B)fj7IbKYNi#u#EcUu$k6 z;wjIH7;|n@xkMxtrnJ^kYy`j}@Zy$6FA4x)-@bj-IGc!^%(wbmL@bp`j(k7CpGRxW z%%xH(j^ldM0GCuua2bM1a9b=ECy;+mJ0GA%oNoz06^KwQmW~}e25@7;EP-8i&ZHN& zmUkbsU+b(VY50^_VR2~kLp2nmRU2q-2(V;F1<7+Zs$$E~{9)xY&GAMbm6=cT`J zUuOA2m|1Z!oJa#W8)hE8F1+=U{7c*Nuk5xX1xkC!IP_EosD@fa|COx);blYM8wsvfJiND0)WQSC5pvjKA#^yQ$lO))VJe9N|zFx zngb9~7=~_em`ekoq6;0r7pa&FL1omJo927!2Pz_kLSg*00k^eN4T5UN`I!K?^AgA9 zjT<*S`sn)_yA}WpE@>ZgBkta*_`QSKgf-@zdDI~aSeq+@=G0x6XFqsjaK&PPnfLch zAjv?~($MJs@BQTP)2pJPoSzDa87(Mgg~Y@f+4+0&INFc%P;ulFlPiXIT-x#L4{~!@ zhw9e~5FUGN)6UO5&AukB_J8Bm(E~kK{OTi_i#lgT+q{?mzr2w&hwaUA zuDJbgpHhL>apzUFo_v=BENxrxn-BGW?&WBAkItq*1Q9?G5C|AS2ndK!h=F3TB!&=U zYb{vHq@y_Md2RF1_JbFHn$9}SH&)0r5vh#@Yy&#(+K>}1vOstTISR=VifDwrZ zo%q0&Xc26_l)me-_J4OjXM#FZzgB>-Z|&}FfAa&0jLw8&EoV}FZ|%$-Jbw8vKfLJP z>#M@h89w%N6e55)xMly2zkg=Dj6N}~}L`)oG{SJxq8IJhD z%r4AiR>s73=CtE;2=Va-)L#wt0NuWQM_*sx_%XoMx_&;NpTNU$ zrktMVopysR#CNQo2?;>;pVhg-r@q}7Qz#TBNc*a?>9cw0pN9#+I2iy94-b_}rL$>~ z%m{Q_hMRmT$KrYKME~z#mSC-&?+E}Rh)5iZSiPb%`|$PYcU^{>0cOGE$Dtzj%^mIE z{k0!;y|kVL{7ecFNsx&Yl1?IiVoGQ~gh+|*xDx#X+I%T}=gI~D?g7mBbp-1oKsdDh z(6-M!VaJMob6R5KSjj)y<7ZL{`-%tz z{8SJP=eB?Ld)NKW&$e8(tkw?#5v-{8Z2Ko49Qgbz<&8%;<2#CGGO1b+kWd6skfAy> zm%$Q1WEsVx?{T09HtZkX^_69hy=&P|z1tf&ia_5*h5sg5m}mrnoQ2 z!Gi~i#iH}zM?_4f?48H~CVY=vh2GKkPx}>{5ci+@^9gW;|0s$kSpGxB_w!W!alJTy zz7nT`h>joc?d|P_GoRww2Lga<4fUc{TZ#}}k@Ld3|GtB{!MryAaYc@DY|9ZZY;OLA z_jLZw2Q&9viJG0O=B#jj1OU;L$_KvplQ;j<-yL~omGV759V#Rb$tU)S1JXVzpOi<+ zBc+fSkbuzT00_=X-Q)_XyRT^fclTq)2U~N%XDuL(9_-or7mr81V?j%njc8PwlqRJF zf=u9r-jVOUx#oAjFtC0v!1>_mF(VLx&bzO>=%HI6SMpeSq&!p_nE|~_s?;;M?bF{I zJA)&8F!&Hn7I)RwWivMrnGnPMTLTxjKg000nx z`20F*M-#99XVMT*6W!wHKLX!(HEa~HC?Hl8s!mr5Y1pmMo!gKomu8YZHF!YX4^+{lj_L0jR<`f$rF`7R*#2+5Uss)c_*6oGgopSkDi1;2Jb1-cI2zX%W&jty@6 z)Dy+S{Xtt38BnCjbr(Ra6=N-Ff@~^(_;_i+S(d#+5v+JQBQE>t_l#~hAY&yRcwj{U zj96m~H)rz)j&J+a6W9O2&!rZ()mnph;@{@5?cd!uq<&oZ$sUyrt44~5zyKnQBm$N! zSiu-AA{dbv0o~|av8YhBW^;RvZurx$UG% zL=vwnM3hpDDW4ZMH+Es}?%&mQbX*)iv1af30M3(V!mph9k5lwkHN-Ur>#ph_$FY+R z!zt|o0GO%hAI`r7pu+x7z8l7vfq{VruSo0h(`12_9kXRD~!sS z`ZF;TDqsRq%t$~&M2>|$F8a3;59hKEUfcew_fnwi;Qc4o^||ez`R?ehBVk($8_|jt zGNV%hp+##*Vzi~v(Mvx3u0{9VF!N{Q+yx?tq?UDD{Mem`|M_K|VwW`;YYkFt_o8y`s4E<6WE%fDi>LQ3w#A1wuj;0ZXKmu?9gA zm>3WNSs=C$HfK!~9eUy?ed~6w{DlV=-FE|fDv7>k_PTcZU=g*bx#gGcD&4Un|H`(~ z>O*F%$f1W!wPgNoe$c#b63!+N(Hb+}(dFC)^J$`gaJ(R`qH!al<}(m53<6f{LJL6< z5gQq7N^wV1gV%=G)6=te?_S5VI@9^A<^WECU45Ag;>+c7xm;FCIkm31Cp;RoL z6StKM5F#=kqklq)tu2Iz;3n|5++8U<3cw=F%l2tG7n$d?rQ&a@%|CxTxrMOJ~gmr zPuS5+1~s!L(xfPnI-o@xlQkp7=1V%4e)vvgniVS4xeG)9=zR2+(bap)dwXHb>jKq-ZJS0ny}CsB?Ha_zb~SNtDv(N{#%qV5Ui2Ulg-B7yOQ#Q+^PJ z)xx5P2%T0+XW7^yLLLignz7#J8H9&s(Bq%C~9Z!{65QmIm@bSh2Xp<2kN3aZXO zbJ<^ELs1N*=ar*DlwNX{;TPx3rZ473X7C`h*4D{01WW zfsY`b_TuQmtsc#D%scWAAy{!7Yya9M*+*_j-MV6SmA)so3}c6S_I&e|qtCCE*kl&A z5fK?7Rtkxk6mi1;0U|_qKL$Y>cgsZpK@=nLU@rUUbqjv=e)Ls+p*fPp^H9pSL))<3x)fWOn9jE#gz6J{p?*`fB6i>LadAk zVvJS+#9(b^VSE1@J9eagaLxbo(;U?7^nwTi6zZ1$>)k+@|Is#1`@rb5z;1DZLVzG( z5fm~Z80WbthKz{`5iMF{ZJcUrib~~UFKrm!dhn8u-Lv%3+jKerm<2Ldb#NF{aO2Y8 zszv#?_Ky8%tJ&9wiYW9dCPJrySbKqYaS_oPYsu1VR3GLF%$n#l<^RfWSt(VX_e}sq zOr=s2`WRxZfT$(S$OO>fo8i#VP@#~o3dgIV`Gl8Mr}nzBUoMCr|FY`eCzyv$K$W_3 zT757xd!FY863=XQcRnWo0KiPgjvedk>sz#FQDax4TeGS)6ORr$9_svuh-mFGu@!OG z->G7hchGo# ztyhnJ|E;hk!^9d;v(`kKSP>DR8$v}0@o2I2mP_03yWYLI)`wnQG4wn^)i}T2Yd|D( z%cV_sU6KFsPHxMPu?PymIL3}xlUmqv{N;@*6I}U;50J|0Q8>dwvV2 z1JWcmDa{a|pdbK)yJHiwkVOWF85u2$B}5|_8-rTw#qEWW{LX)PdSKn&6(7I5?Z%aE z7c>7!RTx3wtJJ+$`Zru$czsvyKqmWOaO$fGEbs7bN?C0z|AeG10kd3F_S9 zC+T1~mIyOjW9RMt!CD)Jq3?OsSXQbxPO<9ZRsg6&YBf99y?f8-=vX%Ec}|!z&r1sz8jLaXBArA81Y3%2vBaIt*?X_fK6tHKkO7!Q zr7w&Z`))q4_nR*tdt)mxr5Cla02ow6ikK;}`A>wu$OJ%;c>Exq6rc%#7;8rJO^@B& z{%_ukn(J0}A|C$!oBO}^vX@CIN%a-i=IS&uoU2M_N^*=kb>YBUu4tAt16gMnfWiM1n*V8*8miHD{x8 zxqsD;;hl$6#k z51eVkkpj+9OHf2~{G~}s!0w))wJzDyGg2Cks(iLeX>&gY6dM`QDiHuQ?#4z$BCu!A zZl?gQtK#nJ^e$2|##BiYwcn_#gMnQ$$Md{dondz#CII6P8xY ziXc(%y>R*O_}VAuOfLbK5W9gQ`waz7-(s{?UfrpMOq!p6B~6`q!j9H)kNx8vr7L6UhO8~K8EQZ8bq}ay5tU6lCx#FI$zSO&J&&r>_uj9_EkZ^Wd0Z`@q z=ta%V|LQ&A9V>G`++JFD(2f-;^neisO&p87lK@m8634OjymRNv0{|cbPD)x!Ea;j5 zlMqfC2ocF-G84vEiJ$;TIi`*bHK!W8JVY#)OMQKP<9XvXM)2;Sod1t8CXVA%r~f*f znp(JBD5YH0-w6h0d${L$m;gZKRJso@pU>~zyB7c&$@~)l1aEO0`bvxyP4jsiuv9od zr~XiD{Z12LoOw}VDm)`bo%bAvhTYtxM~Ri)DeMA10v$S<03t8@7(i^mxea& zQ@)p8&`bbmM6qII56MkeSLm2Ogou2m&>sW{C9)=0YWnakZNKzxR8(J{ZUqQ?-rTzV zZ@$mOUOHd{O0g!VIVMJzfVi*?O`+^9Z*O}4jkR+E-3@K@V9)lydn#Piw)mdwTCZKM zQht4BZw}!W91Z6VKJ`}b+dD?~bz3W}xo_33fzA6D+h~hNK763rd81Yhp3cayiM>qbjZ(Q`ytt&qI-f(ei^@L3Kbe?Jbi7)^V zy(<>!OFN4j59MFjTHeuxh!FVZ9GMS3M?e%2Ys|T22}(qDdA}&7=3xSmXn%v?r0Cxb z(Lgb!h&r>>5&$&V3t@0@@X(>d)nN(BRncPTeyRqtRt#2Asr zvHuChTAM2(b9mDwnfKk0y6F<&6S2r_?bj9l0diga`@i$r;pbM{V%cxXFf$1-5Gxn) zt7N_}Fe5Tz#o`~}luE3N{%zTqT(RY6Zf*O;_kd#v)EWKvZ``}-e}5ZGajLzQV(YQi zq!eK#{h)+ygeb-cK=zRvbZ1lTrwb7Qr0b;($KT$rLhsPiZ(aUN4_x^xkJdqYnPUh5 zLNr=D{M6fp-r=A%i$q9NI6idv=~ZplTta?r-bx4{!cAe*V>b@`?T;X`sE8~m03kpT z0YNL`c~UIy{^Ij06)e2xx;iGVxT}Jx>8Ec6rAEK~Hi=N^iM8W%003}SK_Vn50;C8? zkOT?PqA(&^v?#HOBY;$Ewp=J3{{EYToA)jM_`QqoyMa{wjItV0)dwpIZ(Z(RyQJ{O zp8QMO3wwGjic0y;|8(Z}dkz8ttT8U=YV=xah1RMr8i`97=ArN-48v17EeHZ4RzP=V zksCP!*x}&8gWcWTzVBOWnR$AvsU9ODx?JMqrpIZt!Y4!#a}{Ep=Lvv__`bh)&)$)d zk*21m#>xP6M^<+>mAi*^I)zpQCk7((0nYk!LWiyjB64crcbWhVhDgH-JVYR3b43yH zF6+!ba%1X_l@w}#igIiAI6nY@Xv@*jm)7t3`YWURyMt^dXln)|O33;8GqJPz*T@8@ z7(v+4#m}@XBr;KCa;27^xvll*-<5ck)_xEoKsd7J=;r_ZZ8K6xwKu!yUlFTBd!Uej z;Din$&KHAQm#6N!tgb0eh&ZzQX!pw-gSM;+gM8P3N(I$+#uO`@c+Ar&YMuCNLO+>O z)&>9&bT%)%>*}r_u2+gB76SCM>HfEO^l#YHap%=_oN1Bt%`0-ZUs`%&w`xiuAR_?+ zFe?BHpiB%wSjy*j{@o8K^g3?8qP}Qb005glbR&8=^7U1aFH_os(@AU)0R=50gPR|0 z3B*`S3do|dmJrZdYYhgz_PyfKfo*^J#K49N2>#n*kYjc z($>n)8W~`8cXv-H(x3e{PfPeY({JYt=fD?W+Hi^=t<}DL`?|Zk8@dz#0P;O=NvjnB zD>5(RXBT8R-N~6=e-bU14) zJCVdhXlTdbb^qh*8~)d~3P<`f9j#vAkwwi)GkdJHR+^P&t&tV8VkTrJL;^w}#Hz{T zi7gY_C^loI=8xXd_KWYvq()oc!g5FYHvRdxi(P}M)@F(=0lK|wV#UsJh!XpMLR%_R zQ<(kWjTCBt+5$lV1QaVro>^NyKJ2AJGg3$|XbqzygfPYaetxKKuz#MI>Ey#t`;=J(%-ttlzRNQ6M_vMgq2 zvC0BLDrIx!9e?$`fz1cp0%|_MVrkpf^6%@?pXNyA4$Le zM$lx2a}vcs^RVvJ09b3r&3T=_aH8Jny-}%o%)e&BrtEw7-+z zZV=J;{dX)u8wjyt=eUgL=>Ab`$4c0qY5w3%nFp@ci&_9?)8EsfBK9p0=MFyo*8cDO zxY#$GYR)R(Ba2ALgp8!g4cT=geu)7&Df(Cbb-IU&AlfLl`BKZr?`-|KyDHW6I+#C5 zSnMC&{He!Bb{$PGXk`Ir#R80|SSchzB=;Zz00e8TDMgt_uMe(VQcoFJ0C8~3!QP*2 z^;5ngHnGhvX%9PEre0$d_xxlVFohj0UM5hPP^Em*b>Dw%Y)rls<%)5xSRT&hj`of0 z=~{5hWsC2-agukr;B8fo3C72$9cx&|CxubMURKR{1X@} zQrgE;sCG^j;1)pW21HvDj!96E013$?Gt1)03Tn;mO{KoE9e?wKzBRip{keNvu3nZH zq0CAv0IK?6Z&}-dU%RjP?#oA?-u_JDL|mR*JSAKOy7<>Pm@e)P^{kM$63kub^?xBk_W1M7FE7PK&kLe{JlFj>@q zgp{-$T)`L7s%WH;YR!PLgw%T73Y`g)Q*@>kB9@2pyTAP6 z*wMbQJ?k~4y#-A=6Qq}RuK3xzRp?J~$O3>6=ZXiPdTVT7cT^~s`$tQIqfxOWktq$1 zM)}gB_g-I_VSKtRAOb*U<)X|*3v%0!c&r7i2yht0W5up#SGV1|Ql)BlK@|YZK5%Ve z{Xui6pF1bvcbKAfnb@ zsnqyt9WkGd{3FS~#9Cw2MQs##01XQ(+zoSRXlP_)q^ifQR&UNrTo4I>wRZLDRlo8p z|F+>Dq;AV_N7fu3mY~r~IR#FkU!&E4=lR8=J&#*s^A^^axtr*TDAw9y2^FU9SebtG z#?_`@g+?r5yW#-*ov!$dg$Wxu50^_r$r9_B@j>=SB*-!^h)7 zIqYm*_JP|~IHiM-0AQ3a9)5b&*xqAaYuc5?h>1d<1d7K7%fmUpEju}FmwlbRY)Nrv z7b78~v4R3&b9Q9&!M-&}Skp`gR^qnii>z9tbzH98o&E-Sp1>u=$i%$P5M);yupxOK)Oa+$! z?BBnCY;4Rqt~NYkoNb)v34rs>AfkbR!D6u(1VIDW0syKh6)s;mwr@b@*(d;~{heU_ zISG_vt#zqXI`6+B^9mv|N6|kbfS6(#MEt9kWZ!>7`nF5KO=zF(8I9w`zAtas_sv&F z_jP-jl;7S27L+ALL_~^M5h-MajED@#LahrEx&MA^G9y2TXQA? z05&qaKL6~Ir{7MsH7jI={w(O*bAb{9(!zIHnY*rRYDFz#f0iVjb!m;Pqw%>ZWZb{dAM|7e2Ei3Z3 zEib&i*UP3r0G%g~AhH4L^3zzvgsshEJC1Ds?Dwww&mRri>o8oZ>1|~8;ZD)UjT;9B2HXtbStYm52b`ZG;PLz|5oG4! z;gNm&_5nb{_;BdH)8sE}7qDV0qwMF5%P}bs(D(eh)V=Shf#)7`QT|6a(>F4ONH1w^ z{WtIJ{GAV`@4O7SQiz)E=pPXfhj$;@@ISw?>CeBNKiU_zHEYi!K@XkYS9zp7RvMK? zRzw;}5hwR*L_lyB?Wfs1h!EPcvDUWy{JUCy>egCCsN*&PfP%Q^>n|U8{KsK)hFKAy zB37gnFe5V{5g~vTn>;@d<5GkR(oK)ujGl5oseONaZycRvK$CA5hc`MzHX1~_8%dE8 z>F#cj7HOm>A)`B`ltx0N1f;t=rIC(FOKtD-fBC#m+}m@X=bYGx7i=g9&n(O#;-g_=1P%-%lLTfXsoM5L){cRQ2~0)@#_a7JzF?x=c}i2W z!`Ho&8*ER;*b}bm%J$-JX?8!JvF*J}l{@pC!I$0LgcX@8cAe-Im$x!>GFa1!H0%jR zjJ48}$1McAiOE zH!$qEWywIK8*b&9jzJi5Ge!{dz`I)GLQ<-fW)#4pd)1{6)NDYVv;VJc;02*6e!D$B zbJQ3+-Yq_w=dw-}C7h3ON(%I|_D7t*Hlrnn>ePWkCN2)nM{b4LBrW{URNvd(-Jmua z8VUUUei!*SOnVmsU{T7i4W}m(?e5zw4mqpZq-%XAvqag04C5J&mMJD7dAOxd@dL2y zqK$Y_jA)^$3@N-*p{g?zD{Hp_2|{fMEam$sb2t4M`n2v4LE}ZBnX!fp_%a|my`96KEf^fQ>W;+ zexF9`caS=5On=yWmO@%r!3F_!8r#o@TURx>?|yM^Qz4r*iH!f`u{u%xQS=%uA9pBv z?>=jU+=d{cv?#8vUyrY)U;8omtVjMpg9Z{L_*-m-X06(d}*`dLr5AwA~U z(ppm^;vv$W=stHD;ejKKqaW(b>vVf_bJiV8$*FF=;nQt{2L|Ipp_z%q)|uyueuFfe z>p_rE<)Z@T&r&O`J31OJkF(p&VFM}eM%O%tpQqx$Kae*yg=`@)Q8ztZCmDDjxk)(H z+v^%GZgG1v+24JqhgqDJ^!R+Q%B;Si+|X+ ztv!E51@okY!{J&aS66eF1=;WZsVx6wc20Pryz%8-AQl~i?EbC!bHa_`XA%=JUk52X zfxg@>?#hbAo~rPL2`dJaU7?ZMGk_&vVR#gM!JoVdy)#Gmk@z(?=(75E+a9OXu|=yv z@h@EyVq;5{Y(;ucqOczf_Em4fNn-^ZGgYrf94?@SzwbtTMS?a;+?79NTVdiPwEy(k zlaf60%PW;2n>?n1Rz^`ICFbIRLA}eO@oDoc2G=#_Ic*3h5NtUOg$8qbh^y)`d5XCt z2!0_z!od5?wz>t!Qv0k7hb|pkUfC=xZ=QyeNOe$)!cn6ut15T^3W+b ze?#|?$TK}pFU7a$qMj_0uC^3t5K%2YHWlk$q8BE_Hma6JsxE3=>2;38eP+CsC+qbg zeFJN)e>P3@_L-k=8IfUutUo;VA$MZVov-8CeiqjsQNZ2yyCQ6fndXh1S@}EiR79x^ zy`P-Kf|61_QdeJAi7`x<&*$s?G|v#~=eXo?m2>?C+Ss3}t}r%p42sQf z-ThOA{gj$3ZMYpFs%66tT%_@QjV2tE_VGjAs=`4l!1*#h*pXP$?lph(*CaUdh*DokE1^VQF^_{fTy^Z!o zr<1O=S5&U8sZUX66b+%WE_OyB8A7$IJ621ymD|H_lcJ(1D=ipVVl7HKX2#IKsl+gm+lDCk{eu+GYxk71 z=UIAOTZ_#lFd%Z{uu?@ncpL8Hu5C90a z+c{K=>)+V0XBmS>m@6M^f`z3W};) zPy5{ucDkA3Gp12{enM2(ZDDmEbI+cMpg~@{jJc^-hX2R>nIKI59^Dvx4S9(k6TC|o zMYJaGzQFlRA2mgO6TA~iqU7`%pD{&_ck>RoopdVUg3jdj#4qTG=;p{C!x&!aW7zx- z-pMPuSvOoLtHGFO*qpq6VT;Iw%7k`wnRU5w2PAxs6qkz;Q zIIa7X3$=Trh{DpYb;U)sPoI4nQsTq`6=c-!kJ}OVh3~ges>Z?qOv|mTX|I@|p_+Ax zB~w>wN2)E4lt*U*8+dq%L zzV^hDyshActEjPWveKtK)BZ@qKBk;9J(|5__9r?MGql8IG5aJW=%_{Nak#yvBWIt? zGJU6+R30J{F-F_sw}}WWIIur0NcR%Y$*`uZc&xm5Hb0Kt5eTAVFhga=m($6XrG_>~ zhx8iTJ?;4$yAvW(`Bc_AY>d9)EvVq*j%L&N*yko)vYdUz2?WN*uM?1N(n?^~K!5+I z$jE2EsG!o9yhe1{?_3u5`m@0=uTk|4zfR3wL;iR)-|jeh1$QNd*qtB0cx0aj6x$Bqi^9K7M2O9VfXWxFE;gWkPuN zBJ`2n-P9eG8CcE`J?a3JT@Kz^D^aMf@jjjnpCgKUe!O(Kw+^7U#U|O4FguOf=~1dh ztv|U4O(A+HL|U*9hupRt?aBgUHw&VvD_j~@71kp*hOzDGZ}F<1IxkhVEK zTdkfjY`$e`g(9x0y6p)Oy9{e;s1eBJ#*4xfw2+%mdF=!xbw(J=Ko1J=H&?tSSfVzRD;;{v={#o@R`m8hu~1 z;mpH6!CLbCK`P3^&_HwrA!0v>#>oF8)#klb3<9fGEy6*RoZwGp7H$$eF{c3&H+grN zJPc=_T~;3SN!dLYCn{~)mcQxdXPh-`2mwX|b?xAP>?C+$W67ec=)mkUM3V4?I>52* zw^baz%4{d67*Ghm8-5EZ&#_^`Koeoe&QyXr_qj0Rpz&V%h9GYXc`Gr)TW-1GmU937 zSN=TS{fL;dG&j|i8hVx7q*wg}4a3$_?zqJ8Ls6i%WUa<=-LxXG!9m-~SqJs0?HOud z!8hpa)*3NsT90O`@dg9qS6VK<!dsT;?WCN~0TM9*?*(Oh1$7CIy~;+# z189GIyBV9G=Y%*n%%}XUHn5?owUnFf<~sjVXR?b15Z(?BgN`FqzfzmK{qjJ%Inr_% zeZv)c@88%EgJeN}$r>@peKS2)-0nIM_x3OCF+j3ROXIIHF*CD%xXEKMm_%=FiZ>P+ zO9n4=qt3sSD7^oZuA3GofF6*Afo7f3cKL3l>3X8Q<*II-^ZH3Kd86N#1TvCZg=NNK z4*C4(G!|BZ*oGMBX}7q$VfWAKJCOzZ`xZ@NchK!CX^qWH~NbW$b-lwR21{qw?- z_$}7zN3w)Vxi-dQb{T6BmZj3^zcP;JF+-cz(u&zi>X|2WbPP#!#Kc-v0*)epGJFEEL}w-mT>r)*A34cB zoAQs7PP~`bwBdejZ+ia<96zNlTc?J`@Ksk#;$>Z@65Ts$oBqAxs#E*A)=Gh%+76%N zMSf9H#XleT$z`eBzF@qA!xY29-T+)wmkLx`&foDf9bD~nhrkidq3WmsDb8)W+I>@+ z!*TcY@Dm))Z~vK%0aPgKE}r^kZ0W{q{kE0XH z3kY(ZN;yQDKrsJb4Y;mnC1xMH#mc_Phk+PYa-8lq;-WNo z^8S%By!g={?o?yM@7(z3?TohYE7UGF(B%Sso&AmN_Oi3Pq%kC~c2j0ANcdgiS`~VobaERq(;UAukiZ#rS)=~U30)ER4z36Cc zZ^P8Sm@f+l9F=48;2Af$J`N7TE4s{Ye|6pFfOH2w(i6eh3H1!Ah+34;Hk~Akr@q6CyxB6+Zxqp|C{0X_27{En$^9UeT=f{ zM|+1Vdl|jsXP<4}yO`aeg5TbBJWT#kKDZ{Em~oMNspDszU_=}+N>gjCUkRDi(ko+W zL5cExt|ba@d0aT1SPQuF((PaXSu@sMs7!c2x&=+9>h+GRSuo2vYtQ+M=Kc`w6*U-L z3(!0K^w#o7>p2|Mxt~|PUE^{t;3&^TgeHpy=f>jjzU@978OM=0@ZgRct&X z2g{#l8dOT?sw5P&pFY0sS9xIX8Wu}SxaUH`T0VG->0H&|6Hhqe_k~?ZAfJUWG8H{AUkovlZqJ2=``f@Y1s);6^yYHrQK6m6H@sda)q5*Ce+0xwe>0F6>p zW3MSz*B_N%KZ|dBnn1c`b3zEcN{RE?Lmkcv_tDZV(R?ZeWh#I6=nf zyPL=JP|}J{GF|;`x&_JN;g~$@k;3 z5@EklhpmP80hazRVW1{^6DhwARJBTB*Du4PV@YRY?;S28dL0icFBv@Rgfs)k2>uti zA3oC7+r^j#y^_3d8_T~NpRDdVO(|;)(&A07hQi?H%gfg_Ycsd`Qi<&-Dp`1>=RAdF z_O66edv|YA%;26&0{m-g_A|^MGsv-N7fUE^&+JfGy}BO(90$kHITozN`AX51VA`}YCNXgZ@g#d zv-=p24A2}NV!VcnPt$PZry-2Na4S#w($KYqrvJ$Q)BD|TQx5dd-En`;f@uQK-x|YT z8!3d1sQDgb+(?n8Fyl*TXaDcLQ3_e6tQJv&R`i0UZ^QXyb@amD8KPg3Vri1oEo zOJ~2@!Q|x$)In~429p>Sp5{}NTlH}E)x}+igDD2kl&i0R_paFZczWv|)evYOolw#@|+^2ul3>_rlpH@YJz5?P(y{ImarloyRRMGdrGopn#TmHvW5~ z`M`A{(A6Jf29PDdtk};lnhxOyVh$}?GV!Meo^V^h)tkiT^zjw2T<95!6%)U7>s1`X zspoz+&V<3sRy0Td5Jc4x;L*Qe;7pU6wm77%qUp;L#$c#mPiwcXjbnr!E#trkWx_{g zf+@0-wx&w;SwELQ63b%1jJRZP^{pQu_Eiy3Beyz*H4ahj~ttIXyy9`7pk>qKCk z^D0hNhnTB-sQ@@`TttT$&Da~RP|W~Y9X-sS%tZY3oPYx``0Eq>JZ&0BqUmLPlh31W zRudWKrZ@H$CuXfP&)XN5LO$t+gUi^w?}x`x|B&-Q^O4&GLKxp?!(4EoKnVyc zY!os+)=mw#6WxJ8F%*lnO~bxxN^?cW5%3OAe`SHa^ykYZJJpf&IR-lmJ0Z6ocO%-GBa_+6ba+fLwD;pXsxKWdkd1gwVSUGj2(9Y6-;yBdQ+>$U;xm&b)X9y} zAR&5Vx9T`zeau5!TJIe74-*H6VcD7zef6%kbyCM$Aq9^9?3$ozY5T1VmM&=uwM??L zYL(SK21tmmqsavC?KIx=5phR-=`GC)HY4x2qiLq?@gk-cG>>O`#!E>u&Avq?YEZ0^ zSA8}wr!b^h%QVAdA&s_oAwS;P4$yastxn46dM-X}etySJ^jUXH;|~ZUc5qO2R2I)D z#ab4Vy3sar9`PI5B*jLU!0eUL0>eQALL;cF)$+)iIQbasO31vof$xGin1}(rmEDns z*@8HsL7_5NgN+{@6BzNO9-6gzuI2~7y_XW#+kft%bWz!awjoQ^nN@I*^o$I7YQx>} z&(%e}FQ~AQ;^W1U*n(A`{1mnBkDP0Rv4=l30U|q?pt^H{34P%v}Jd z)ADXdkg}LTda=VD(KsO))hFtp%wOQq&ovmGm4u5Ewf|&q7ERWs@0d}f2;fqhu0c~I z0I*@k*{2w=oMj`1(g8t^UpJ-`M5T34fn(!zIAZJG*ObAWMV>)Hp!pWD(ZfGx zU>pVkd6tmxrTuDm89rt4yFU&4ZL#-TsG~{2e!$2`YeDB*-)v1EiQ>Aq5r8wEO=kYZ zZSBD$#{t8m8kD{Ej2$EPp^@B6NRdXw-AWxPrTe2P9Td-NgtwjZqTPAau&bZ!dpq?; zul5k`h}m6+?MU9a__eq;&5r?PdZ=`ZPz?0=vH#mQ)bET|i&d`L@?oE&)%UB4J{T2s z2sI^2wqzT0i-lv*Kw->~jsUB*h>194kZ?a&aM>PsXX;me-AC@E0=c zYT^3+OTYf2qQ35Tenj8q&a@Mf&z2IMULp$y#Z3XivcV`@!M@i-s(7o=wLBL`9&fQCV6|0?(p95hNfe;1i%QSzLE!RLN#}a_JwoeaF?*H02Ea zh+|3!hdco%Q;_Mz(>K=2bWbwo5BSim{_E&)f9U#b5PX?8`a``enAx7xaA*Vcixhu3 z_ylIhetIMDM=(BiauQ1H{)qdKd_Zew2yFqG_7Q9LDCUY(|aJTdEqY zDAcPTpA&*>-D4fA418Fm931K==jIwh)+MV_i7{Gf^KJkQ1cDfb3jtSMt+m~MW%F=% z+m^HecmBdb;3#sxu6=fL}TR@$XYN55gg2&8keEW4`LKZsv8un#jFZV!{?M46>wb&I`6aT zDJ~2fp25Ijy+qRvf>zvhQ_XU*X4K^}z&MCZ?09Ht;|I>oo$ZDPUOGOlHrHP9Qrx02 z1j9t7sOjWfV&|08F8T^JYFu0Vje`8&%0kX+43mTZF4rPz7%dVkB1gbDokCWauZhv< z*y`Oel$C^6uP!-A_eW4;J%gq<=wG)KX3sBtzW@b+FbCL+QY*L2)N(7CN|ph_L{CEY z;uDu)!XoHvTvF!eI<4lwKjnIFOrBQ%+g~M@_<(=!A3xfjoQ6k)wZL;#W13@87jk(J z*O#l1L>ifQe{x)HtT zJsn?E#bv#{ttO=NMgoREh)%*2j$!#A$If6J03d1m2M0ziUXC{8SU~$QhK)G0_67g8 zXv?8Xfmn_2(`W+tzF#o)0D)TVxRN4wkiD#QqKBBNK=q#z2q<~qt$N(A zVOX^O=LY(5-@o^_EN*aZCRn-_kCrJmCIKA- z$kt-xn_v#rA1q7@^k7+&_+K%dW8Br1_>kAKy@&@km(|+0$75ZEM&6|ON;lQg!-|iy}X2@x6?d`|v-|`Ww05r4_n)}L^ zB@Y9xo;Fo>HOkLJSKZj!9_40hYkPCLN?`F6w7)xP(mdJEKl%edu@0Fdae^qH^d~Fs z-{UWVBcWieuY<8P{h%l!_CvX)NlZfeyM&#ga)t1D4Pv(xDFwbZ{FIS5MS!> z@mm(k-Yw{?)ljvzQyL=z>)^(yDdHK%t%DBoKj0P)i{{n1Ig@I2FWWQyrQh-2w z#fv6ur{2O~)ih&BsI+TH6J4Um)k#VXF4(q`H4h6Ut-rNsSNebj2Ee=MNRNoqk5nT2 zyiRlE4NHqG8323;!DA%)A!A)kAKj8~;(Y$L63ADB82n%B%tX32S{J+gwdD!cBUF=) zEd!RLr;wumKpgRj{*5zuDsh|Q_$g@IKORT{xDEwh3iInLpDktP=#Hu4;wEOoWd*ff zh$bxB@6ZcC82t~V*;g;lON2rmCR%}5pD7!|*wEm2+bSh0Y08d+AQ3MlGBR7r=ha&@ z0qs<_bWb<8OnBy!78+!VE9-0lzj$1kpfVM&=X<(A3njZN1olCh*ZI|)>4*5&vh&MV zNAm{MjJzb*9X%1rAl*l4aHnyr{}q)(i9Wn!te0eAYp@Q~lf+=FV!?1r&?th7%( zrl%JxpM>&RGCsxe&DsLC*6_*zHI?BL zh-`Kcq!oTEZpZzHKHv|MEkAXj(#TOaIx1&^p2ak~PEns|j@Q>t4B7K$Q;1wG;g(S! zM9-7j^f2d}(9sBtBVHuSpXcB*vdjJ1su1ATBa*_88gZXtT)^feQ%BT^ULWq(uCAK1 zMDR#r|LJwaVUF&yNBoe}c{U3N!PwI;?&Fi__*vhVGnot}L%*m)`O0Sq11g?Uuvph? zi%%PbT~dOj8;U~Ha{GH3a34WX%tR0+Jc+VXrC44Vfv{+D_FwS1s~!pcZ6M3&N1q8n z>AQ#|5f$pqtI{O1%mXWD*{W_HW@3OkQX)vL3WQ?|_+fVU5D-~*sxJoyejIis1%MF? z&Spors)~NYJtN6Um_{~fj5%f`kh6Zc3$|{Iy!Pn zGag8}jzvCwF1Gf2fQ2at|`^LHo14pyg1JgyWD3OFi#;u-~!q-CLv!vYCzn7x@F~(vc z7f{r2-^}hK;};>jy}kU?;NW+Q>3XtMg9J?TgVCw@5HO310r2Q1f8-<==|Et?#H5}= zrAK|Qd^^5>go{^sMexfhp8AnwFb;nzA0cB^keVxxkw4#A@6I8udrq+dG=lk12FP9jx^$5&*B2t9;*sX= zsZszQ_Gng~V>I{hH?j|3$>=3`da-D4g)PL(%L9Si*(B@{R6!v`XG^ zMRt9?uf}#hLZ&kptBtlJ#B@dP#(-7`zvj#&h5`8#9P28I9>uMB9*0CluCGzdS_>3V zj1jBBJgJ{nsEX$n#@Cy^RS*B#0PTaWDB+BubnZxB#nUy5+Rpplpa|a@>L6E7_ZfP& zRJP{@44JJ)CNtPFFUVc&%q~{B)+kptmO$Xtd9BA(Gv{{@jMtD^{&-_)Sr=PBC1R0M zsu5J}{ELecwa@+m3C<^aW7d}A?JRNq5z}BdxBRltSU{dK59`Js06GlUzL34$wl+%U zxfxYJ!9@drp6z-wA|RTl;M4NuN7qwCFL8t_ouz^Yi^X+~Nel2=efX~`Qb)wh!`gZ( zXSI+cB}nb1{JGhlohGmSr~gjd`}>_yZK@`W z{dA(dk2@E2riH3FP(T5L`vBxlWMtlh(qy*QC>{sn*UmF!tu>y+LAo_#bheZSr+w+) zPRXA8FZX=}5n%&iF4Do)BnAOPow?~*ky3Ht0dyy8ZLOMYd>2ZXq4;!nk@!XEnnLKLP}xai z+E+dV7vgdKdt)0vIqFvUg3-Z@u$ds6@Z?U>6#5C!;%5{%;+U$ z8rBM2u`*cinZZF(eJCSdbWHeGyH=2v$v{Y8N5>CO|B7`cF*)&ne~tn=?ih2`ovVz# za~ROEb~1kzs1c_}(e*c5?|yWC(KK&kc+f}}3b(lrh<|izyAB$Q<}7r=%~2vUWF#8c zOpAFbkp_0aynQn;rue#{i3nsx)Xdt^^QW-#4f;khj*PUDY#r;u)KmjD28riO1CHw_ zpU8PLoj&7$DkKWYnq&tQ`i$MHe8CuW3_rSM^Hf(%+u&6IDbttIUuCrKc2&LBiw}%f(vO#nQ_tjWm zH$!f5cZXBYyOte`y7~?G77dwwnh6Kc=)MB31V*whs@iZC;eNxvGwpcZt{Mw>sN1-; zhF0FkMTsR9vhJLyFfhlg(3i=PUpEzhTZ)@$5mbIwDqcVHwIxd*!}UZH=t2DyLd5e< z)%5FbCkTw6dXzSC<$45M46h*{@(i}?F$Nx*fR8A02Klje<}}u@Rx5cNFZewB-fM0n(a&Kl1F``|YuFrCQr8%Z5j9Ac_zmTpL3>8{EGhB`m~ z5=zcK2sG&we9f~m5yRfao|rY|+iUT>{+;Dc2b&)bnkWsdE&K=gjQnrt=^9-ej9xVq zmo`sQhQ=tx(@3Cf*6FxP&S?_4s_S8tbSD3-imas^HF-#Zb5NRcyYXNT-z6_X`lmjY<>n;Q3WJ+61Q*ZGAbIzw0 z?hd$~^SFMypMip5o4E?D7Rv?QFz|CkK8H`?xcLCtNJU+rg|MDlTj;r>WXMmA+vrL6 zu>oGC6)6nJAy*(y9VB-U#Im9e!A(m0G)R^}AnJIP`WXWh;)jhfOvRY?+dQH^JXThb zt1L}Fx;5Xzgl2p@^~L@Sz4zYm-`%%o4(942@2|oKo)q#Ym z(w+#2WbxDMFsn!$oXUbQVAZb+^~&vkii;YXO)y0gg1Y+fFO!9J;x$MlSN5$LSD3MnMPHyWQ=l zRUv1xn~M-tDNSjJV#m>sd5aEOnRoJdonBb)x@B=-QQI?l+6#MD8DUU%>$plK&iTCi z!uo+_h2lgK%f+0l(2aiyP1U#Cya?oS!q?jFoC-9{97&4K4wtFW^$%qizETuxKIKCh z+h4>%qfq|xU^qN#+i^Y8>`k!#Ky)s*Z0fX*ai}o>PgqgR^Iziw&Jj6lX8{_E<@AT2 z?rx5Y7ZXw%sk4|X1Q(&hXgsMHmf|_p6BKn;J@TS2MI1n~5Pt7Dxo$RhaZeM{GQ*JZ z$Y1)-69j91*xMiB*6)NEk`}|8co6?I5Eg$;2mvxl{XyIEXwz=PH&B*}?yhOQZFR2x(0AcNfT>I>IpwZbK(7hvk? zRTm^n4s9bYLi=8-yc*V54ThD|oC0L4@wC6uX9|JM@r~i-aabAhWIK z$ff#s7&CoiLAD_~@?G3>Y0#i|3F$QWN&t}y=Q3Fk8M z5k2{8%nj_kjb>zXJgY8i=+0*=xBq3Po{doN>!5vAR0HsX)C~}(8AjY~;X5NQIoq6l znx8nhngBB5DeUz?rGXHCuda{}iyhWhg1US*%yc4E@7B5uIp@`1*=0)2=L7VnlZ2cZ zEmWtRWI@B9r1K|tlelxI+uz2vo%SHg{hXbt@cHbid>2P6+m=Uc7 zvpcEpH+u%Sv-~0GokAb@4^4cAdN3(`6@QnNnsH7kP4DQVOSvQ9tnX@^Ztc_4L2Yj* zUx6I*mj-pp3ww{810`+H+H~W=0#XjdzcAOa!<#>dkRr34W*US?D?!=Zx-FOrIO_b9 znQ<+1cx_KxIlLd4z44ReAf2g&JsMRn80C0(pdjKX($L{!3y^fuqUG=n?}_TQDY{2M z>l7X|uNrK_l(doU^w>A$C7ctyr3gl`hA+fjhm^P z*dI$oXp|Mm$+BY(!h^*wXErDA+MXc?7JLHFmaNy|zvZ5%$J-OCeoEEae|y?oap6nr z4B-7=;#F6q>|&Axkwbx0s_(gAjAIkDz;tE9bze-E7Ij+v-x$*wiEe(Q=jusdj)m{G_s?>DJ9-=2<4+-6RM64p?AI`OFJ%>0~rNQ!Yfv!@xJ>U!Ytu z>FG5WE>0A(eETcoJndSsyq8a*{BU%+j_TN(rGT_{9(YhJsQm6-1Wp?ogU)Cob-%j# z4*S7n|G`JFbvdNFO^FLtYEF_J7?oaMAGj~fl%p;ly$JO2P`_Wbm5_j6aImmo1awnl z$w^xm@;J@JIG3dZLTSU#Qj_?gA`0TYapEF(D2S86I!k)4$<9{ByI)jDD;gNc8L?4| z^HiHk-1?e^wj_HY5`o3bm@fwd0nL~ zV(L-_%LQ9tIaeV9E=nH|z#H8j`t0pr$q=h5wLb}@F@jHYT|*`|>YnxH*|BuGyq2!? zPS`|_-OnS3GMXMw2#13h%jYYv#UqN6h{J4+A38q6q+#a$_=_Jh=Zem{$4H32f0zypjxnRKa20KPpUJE#?=3cP zArF%#h+j2wr~aa&vx=w$k=9ahTJtLn(8XJa^r7wivM61Q14);M)UQZYkQ9z!n_fyG zy?{qQ188m?oLRrE0e>Pr3QGL_+Xhd|ThD%t4Fq$Y0HRdC7YEtBDKIn@PhZ%;=svUi z5cqU_Z?8^EP}p6~xEJB&B-~?7Si?zf_Es%RO4Fv{h|7-36m=N(>G&CZlVM(;yF3- z=`Kr9$V~x?S*zfppv_^q+2j}QPln#PWs6uq>8-1t*#WWOdVS?`D)09IQqikBJzn&{ zYh9V9`5ZO%X{E7n=H^+sCnXFfTii8uV)4OejP^fScr_g{)>0xSrBdCrv7>cDgI$%9 zqXLrN)?PQP0b^_ijAjU_)u&KFXN*K5Z;=K~vwuGMO+(QDBgEQm!h~1HPe})5PHUF= zN+AIOV0||K3yrjXxQ;SI@2!m6_K)MX1yzN6PBc*4`*%kcb*v8Ke850ns<%4E+L{pr zv$hFie{Q;*Ws0kV1H%L<4`3A{q1Qrad~~@^tT3g6n8SLooV<2m2|f{YHOo@gj^~Cz zf$^3~IGRqzQRAzKKNAL) z_|p5i3XacUaBf4={dVm+DQgz&^ZdZE{f}6$eeCzuKnnADpii0*izDXf&MFnL&~bOrt`+4KbRo9v%l;W(`2;$Uku`zqQ1#a~lFd0HtA{VAe;xxv(S_tJ8gnHT&B6Bj z310jC4Pw3Cu?`Use`Ro1=@7^!njwl!1QMsT?`Sx*$edela1QYIr>abq172T@T78Gm zQg}6xwiQ-3`}cX;7iaCbp!Pkp%wQAZ4b?|=afF;{7>Qtpe1E*;8L>&UT?T`n%&~K; z#qVE-3GMYjB1eh+smY7c=m^1DAQ6kQ)u@{;s=rW@t^V-P^W+6m!;B7u2WvoMH{&6> zL0-)ax=63@ditkg;Ez8t&4gmf-BIW($D%buT4Vk zgwMTKcS4}jT!3Iisv(-|L*9g9)QuEN4ngg_F(jveaSus zfop_bF0LU&zH9~)XZ1sqK#qs%=`;px_-53w9LO78$K8|j7I;~1Q$Wm4Y<{&eGqTI7 zRf5A*DXyOQN_7Mqizt?2nI|`+D%dQ%K9!`bIzn?8Ou>GY;tar-x;U}ERF8uCZr&L? zKk#`n!CW&Pl@5g{wqL%H9TWaV%p;J>w@vwW{hLaGK!&FAeS649R?umM z&r=T8U>wWWv9+mB@7LC*?w84Krj3lG<&IzZ{9Wwt_z>8GLLAw&wuY9((%xaD4hE)O zM@h`nh!twgyZ%J{tUy(ckPuNNE*efQlu)1CeWs8h6TSp-SE3hLi_{niJGskUnA3w+4qb6zV z;{V6L&E>VY{&z2VAvbR@ToKMOG{ez&7n*lnKYfqd+3A_6u70J}ga#Kj5IesmzqeRn zkknXQ3b%F$@mu2U)ltf<`%=L~xA7njAx>oWVeNqGpb6LK5u&Hr1zZ$SuzPQRL ztd)t#5x5t5S30{MT#x7@*y3c|rk>uldJ6f?UgHL(+w#pX>`noojkN4nHja!DV3kS! z#NNfNDNn}8PXGV^JeqUvt!fRq$YQiem}gc?=cp}rYin!uzUjZ-Hj+jIWj)Jyy)053 zjwwh$_jT{!_Sj};mi$T|IxaxryoxQ3EdMkl$2Q0W!*0Kjul2Rvjgm%F-?LZVd0Y<) znhSX>1+=dEMWL$7^e=vPO9k|*ZyzDQeynG#08OogBU!;v04v?c9gGk8;I!UkjtOIT zO3??M0hTlbvXtDbtN~G&C{w&RHJsHYx0ZH@%1RRNhp5&bTdd5VBR`jVLKxthqLLr} z9Oyl%lpsu^hywdj$KZjh8cL|amTq%I>bE);AOMe6(F#WKYgaG~i7J6j!7a-Ib1DjU z$`};(AmtYXF!-Qid4RO~zdKd%YR*}DeT?_JTpfMWgE$Bjd^nkK2lR(bIrR_Q9T{P; zLl;;7ODr&_ySN`NIj0gjy`zZD$U$Egg=Qoe{q%MVf3?O{xkbA{8UshIy&gfEj|g%s zEUGV_(LkrLI1vkob*`Xec=6p@Uom>nbCynzRpqSoWq^ztV1Y0jHAN^S9zCJTHokOZ8aBh;gvNU@6 zVGG}a;&^`o+cRh-{AY1NyPm%Ue`k{8N(-IVVBJK>d@5x;sx=VP1`AZi}-n~{`{n@(e-H-UYle^weT2eieP#8!-O9*R-aPCZNw zf;8;DU0l6s30#DFt#T#xD@pxW+wRo?etduwV16E(3tzvy=<$V^jRv;1hKR`s&ihLg~6ftmW9cG=)sxEw;^J(MRd8~@H=?M>?$clRqj zGq9V0blElHds3XEb5GKpHWm;;%o<}qTs2#vJ^VI|JaxtYP93DQBdv#LDnUn(?)**a z=|y{eylMcl8K(MWdij{RvcY_Ju$O+wSrs4nje(v+*UR!bQMPKOn3y$WKP(_w`MKS4 z*W-9+88~aVsy``bpx_}T-e)7F{TcV`X2JO4a7H$k>Qb~i*SsJ`c8dsrmXhA(GdqLx z6z^ksSHtX}lRh)?znf3F@575*ty*KWo=&`0A0O^AiJRjcy_*whR%=H4dBT$r**Zg7 z=+KT}V{xBnnULmReq#}N<~W0jubSQppI40@DD(y!Fz)-A&kT?CX}>k%Vdz(~9{6Wz zyqBD1csBI3+~nOv=4k-xI|U0jsEq!f;4!};P$74m(X9C^MaNtiBR*f^#14n$vDMnz zRYS77--eDXm3W9SN4V#wnb>2nT7zW?hMSmUGFw8-CXF9U%yY4_hP}Za_&vFA>8r(Q zr?W8rEJ&;opYl0Ro%wO5!y=>Jk6nnPe4h1kim?LmW9J#m*24VocZZVg41|On zLISry%r5lVhw;iJq0rltczHP~7V*0P%G}r7h2MOr6s6G04*w(Q`MGfM#i}h5{Xy}^ z_FGWaF?$LXLt-T)21_HkDL8&#k6y)gb!vS4 ihBCBv)8__?8cC&XLrk0D^;$L%D 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�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 diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj index 9df3ad5516..12505e73e4 100644 --- a/osu.iOS/osu.iOS.csproj +++ b/osu.iOS/osu.iOS.csproj @@ -10,25 +10,6 @@ osu.iOS - - - - - - - - - - - - - - - - - - - @@ -79,6 +60,28 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 23419a0ec3f15d821d33e041f536236951adebd3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jul 2019 18:06:36 +0900 Subject: [PATCH 1873/5608] Add drop shadow --- assets/lazer.png | Bin 77579 -> 191397 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/assets/lazer.png b/assets/lazer.png index 19b5fc2151e570bf321596998437072943422c26..1e40e844ccb4f6065bbdb28a591af35ed78ada35 100644 GIT binary patch literal 191397 zcmb@tbyS;A^9P#Xg;LyIN};%yQrwHXyF0}_ltOVRw0LoMD6T;Yw8bfIfl{QnTS9Wv ze&zlBao>CHA8*ddlYRE=&d$!x%zkEe6QiM~fQwCu4FCXel@w*Q001;(5ewS55qpt3mX7-z}42o@d;={G7Z(&jom%^YPLD z{b59o=4oU1TuWB|@3D|?VvG*n-X71nx&8e7xcvCJ+&%5Nc|}A-xOw=v`S>`IEjYab z+`KLQIo-UN{-Gdi>t*ff=;7_??neKcqNSC)kGB{jlGDGY;Og-&SvRl0#e@_Xx4)$a zH!l~@?x@Bb@dFP#7nTW&2|FLxhLYvjV&G5sFO;JTK1p5vhLPCuC{L8 z|Ma!_PhYwJ+V{6QxOyN*mbLYC^tH8-_jGrq|1<69j{lt(>HkXa@4hzwofnz^+Ls&2 z4EOKF{XdKSPZd&wei#2$UF6HZ%5Uq2)Ob&%YVU;7qySKMNt9%zbo`eNaxlYYY}SSl zN~H%}95|iCzq)Zygz5|Fuijb>c*c7A9^AVuEHn7xHGu3z2M0taL`QyAERe|Q#9pk8 zq-83dg$8Kb@hvtjnx?HT?)Z_}3u$L4@qLB9I0j?I^P>E*K;%O*l*x+dpBDhnza^yU z{-^xEs15`EhaUNVivN@9hyS71`=27$1?pN37!00C05< za71^Tt!O|=Z!L)Hje=Y9=U+AxuY{sw8{$f2Ys9(!Zq@ty0q{*(AoD$Q_PiIDW?CV$ zlsUUc^Ls}=p&J&(i{WIA-HZRb(VxK=`oh7r5kanVTX!q<5OqN^WedJ^s9Vxuc?iR^ zqo5ihnNW$eO>2&bdYDCPX4WR9TMj3f?M8{r( znK@Fb5d%ZiMw10H!-aNoa_CbA0)$C})&#gpghhp{@{idFiO?8ISCdYRU1Oq`Y7V`k z!>?X2K)nWEh)W<|C@srdtLSRC9OswEe~oV_ZYkE0Q*y*(wl!39R987QHq`tntIL=< zz0l%nJlih^*6%^|K_5gZ(YKLfhDXJ$vut~@?G8(0du}&~ea7FGan&aImuLDLnHQw; zAL9i56V{n_IZxfl4k}rC1|0;Ro*Bb~UpE;`P1w#OxHvgUCdfhZU(JFJrdk4CoqzHd zFsqEY(@S9{apqC+AgTrO5Lc2_{vCxiCPF5+1dn&k&C+^-$6b$~! zB(FOR8MOl#B#DxhELkrh+8)=tE(_T%p4omH($lpyrqI4UBpq6?)75Qx8v98wRmHXP zC5w>TT9@NJCS7RT)ur$nt2#4L=Jm8$ad-Q-hch})OP0jnuUj)dv%g%0UlE;K?&0&C z%Vo84fcam8jcIy(>A(|leZ7V!*neX9}=159fWR?T>^yk0=mZi9+bYdZAJsqCY zl^ENB>$OgqbGtF)VXKBuipZ7ZxyD#j% z*mcwmLIiD%fbPL#@eNO1D`wKLb#*Ik3~NnV-9olX$Fe_eC)scn%Gk^gJ`{iWdu#a1 zY)XUA}-^QtD@-;5#=;+8|9)TnqQ&Lh)3#S~YR6nObC|vlYx-Z13E_(ZO zE(Ch%tdGy_psd+IbB#7yB5?2K_9-C~v0?RMHd?^cbqwS2OcjSE*DKV5ciGI$P19F8 zbUSN@g`97qa0{yHI^WhAR&iD}+u|xeb!LCcJ{Nj9J6{FyKTp6-O-(h{(OoTO-Mjnn z(FAOFnRSV{|G9}xW=$`>NI)3MhU)f<+6@#HL+K$(tEv5aJ^q+?g5K^t%S=xTMwn^* z1EB`@u|0O%l9K*K`}+bP=+&X0OLA@(gK;v! zzs_`3e*0z~YTmWmDtgr6d|NqNb#v}NB@;=;t3fPRqN0ipt>NeE ztpnI(bf8G}OR#DI6xfk0|8YdV(Ytkr9H7aN)_EgKXmG)&Pkc`EEv_-8*TxRvU>ivU zkh8W8c6OBW-1k6R$6!W1R`zblx*>O}FuW~bY^3W6+3lytEQa^4W7Pqc3>MDVLKM3h zJmZ22peTn|3OiCP3q4QH)0)&6=ve%FSn}c^m4->O&4+VZovv*1MFJkJQo*Yp=e$0} zzB=&|mraKiI!?JQFe5`<5%=+rc{^gywhBtB^y}7!;wX@2ZhM+CxXjMZUgJ(#pppY@ z^#;^I1z(9<{NB|5Y^(Wwv2YXFp5^D_b=iE85;XM)AbO6d&mLur>~qIL@MgPx-gno} z(F7r^PcP?akCa|KF;9A6v1r9pGBZHR-<)HCZCUn(%q85+g1FWsJj!s=B9XY@&ae6^ zBQLkvm3=#7af0x? z2g4~@@Lgf9V8@*A}mTg*S=hCE#j8-h<$Na%uZHjYV1NX~5xa}m%&2q@?3;9_>U z)wQ()Uy*jW>l`(z`*?1!cTDo6iVpDGU@d;L?$BQ-;ovI~4_t2@uc4p6GSUx04YIE{N$ zS>8k7o2#Hu#O`KN&5tcKa_b6NMuzNT3+@-YdNTC$k5Hw1A)%P;zun|t3iALPR0n=D z7Zd}s!)7uhmfM?cwAbXIb?1z+s*2<8X#1WVMI+u+Uha_O|DwlU>fG+IN#Dlvvc@Xd zhv5pnEJNTpI{s5pGu6$S^-b_=I(d(k6jw6-SzEX6w-xAfuQHW*Hv}<^-qW`niPlS~ zD~Y@_#)BS$!LTwaHiAE>gVo5R8cUEkr=*mv;;TL02vZNbDjDMpz5xOtl_$ZXX>#_n^n66=+l7 zAl+}CI3egB%JW_7Elja83vuN+%?ue7YBWlhmT(p_|H66PV;0F*#novtuo{9^zVBtQ zN+)jV30rldYZIHB+|Fx^2c&g_oVwXu<*06JEaj`G)AHtO4KBa)PpIWVm%9RRo>o02 z3x?lTr;g~KjG~CS(#x+Q{Wu$n<$UDg84nT=s-`%8FP(~bKy-EmW%vycvvL>esu)Am zERooQF}Co4}sB zq{SM_I}h<@LIl;caNKNUyOV|9&gx6(J+ADzKk7UNgEmUYS~W_)hs}o9vtWej6Nl*^ z0)RtER(p|Oz~nPokiiC>{Cd#V3BT&Pf(H=jTEX527ETN)h`8OAR_X zGD)|Tw^E@BR`6OJYcOEB-tyTbtzJ)&_Snf(7CH?SD|6*!tFTCz_XOV}YCDdy(4FV1 zl~`j_R7$k?Y_T79%;M8W^e-6+>M{@kf6=Kl0I%zdSxZ@#kzi%ex>c?wi zo2TJdm~;Z4?n}tbKPhC-xyq9e6URrBk~FcAi)iZ`DJ5yFbSXl3e6Enx=j92!m-AjfA5DwUXDLYZ^sN5>c`L`SzBxLPVox|)9l zyY{=#RH#v7d7sB&)U{jm)o<-|pzHR0-fgwT_3+1F9MSfZ7)=(fFikf(wEK9Va9@(p z8zkGmF|{Nr5xjl;WI1obp8P#*yp2fBVY%9{G4u`Q@f;#)Cs(+syg1`piLNk?M7eE7 z=cLU3(p6--|It#Q;g2fN8he^q!+;wulpd~lAQYVZIDyl;cP^8j zXFxhAywKnm%14K;{CuyjdJot-5@>_rt>9D0_Iy=Z&CS{AliZAM@5O2Jxf?M~>IY2-1K2*+2I*PUdwEqIdz-z~D;P?3TSjGP8v;(@tOL zht%e^^N9Cq2X!?&%F9bzCpe2CkQ}k~eG~Gf*bYNGIU{UdKS$KF32KWL(fCjMxC=>A zQ!TZ%iC;P1jKGF-rkFX3ea90CqaBai-J#<&*EzxSG_d2xp0;PLWago-)cBHNPHW+} zd8(OrCrCud^x+o=eOm@lwoec(0>AY2GWUbGNTK#3zkqi|yLIdh$H6ahM(C1;t;6YM zkGt*@X`#oh5QdVHnn%ADTh+}E8+Wr8%j>y4>@9&?Y@ zEPkhhJa-Qrp^~>@8S`ws;-hkS48S)){&VQV@s!zE7v$CnK zEm?U-o4uMQTCW-pX2xNw6`~}jaDcg7)fCvLi8Fu=^&_RYkkUOwN5{!-b$BIto|1w} zn{{U2v%NgFFBBX+-+dk289Hz$k{5DyJ8`}}v1uMnMi8G8)E!n2?#fp~`R#K5H~<01 zK69c5Ivaoi>Va%oV$NrFu1*&NWTZ0u@!3_xM$J+)ZFSA@$J&{^#&y34`FTTjA>-Vh z>~)25afkZSFt)bCOY{SlFf((>^3{rgN_7iv9ml#?8`q+CLWgcJGe37jy%uN)-pT|b zL-=^d+zttw5peghCBb8e&#@TzG2w$4*ggi@>_ZPqVEOML{|}<+hwL1iJiRhTbrFA4 zHe}ThEq~GBTzeRDL7+gpSgBhz&~ddl^*%m0w9p2(@-prbueScTudy#QQ0;^m;8NCi zCH(qRIgaWMN#x~UC9Jru93BL-OH11Jy+yYz!MXUwUoT;6)^ zEze71KLFd3SB7D)y5)w%tLHZDLeih7g}Bh~bmDh_U!(<}OxJw%pQ3$i5!d$hvWzJM z9h);|+~9KVO>Lfn;5f(Iipeg+SEmJ?hvEm5!uDN;wKccv3HoNxU2{a}@yMdYI2^fM zg16Aox}7l4njd;&gJgdnT>Lfx2flC!*V&ugbceZWiq%)khXY3GsWc)-5wD=1w6rV#lQpOx)pMIKZ7HOWtyx)`C-ah()xZ{2OWZRa7*iDACdj4l zfaUHoy?m=}kH|(TQ3BV%0qj5N6AsbE;9a5cd50Qm1IunhDxx^T%jRUaFqC$(!vPJdu(#G&tSyu%S4+Sv zN)$^_<1Yc!Pnp0`b1Qo%jOb*CrVynnJtB39eU+Y3_^-}IcL~A6U+UYi7d!h&61O&0 zj%c#f{g4TKEGhy36H+=B$Zzi>lKW=P?VaExo#96`3rM&_Gu>c4ys1V7x`Qv#2S*5f zOxPw~GuN-V(@7H>NqP|qpiE-u1+`v9(=}i;qfXb^F0P^(L}vltGSn~UTXr5^A#uO! zV#})$vbvtDy(r~0u7LAg=&>>D2p=~!Yde-7SUSADiSi+o@*n&^9*JC`+P&29@bCrk z0fnZvjgEc1UyI$t6{~j_)Ri?5Igmj0NgdJD1YdvO(}zPSEogxJjokKWtJOQzWoJw* z5m@<{R~++#taxMPM?>pyOYu zL+)HB@x;Xpq?cV!S?LvmUuS0r1p;nk8hrto;km8Y#9lR27W>qMLV~Q?-1*92DbyRj zqYS2`+*ZqhA+qt#lO%*;n?+y0`ObYyX1p586n@@NT^yhfsThBpp$66IaXN&K`KAU+ z!fDiGVVxvaiy%;-ezo5A>It0;A&opAk>|JlR=Xq5M>{2ZgHZZAphL%QGwKJGpYIIb zbO6KO#XMA`0&=Ky1K3EDuH7LG1FOfd&7AC%Wp?`)Vu#$vq0jfvlgvX7XScQ&1k{e$ zfM$m%Iq0a}@qmvvNG1;W(hxiS3^H#g4;C96T7iIO5}2D6#F<9nXugd5w@qU{q!K!~ zK~KOup+GIWN|599V`PT&CmYBv>qX2Oz{mfp$TH5Lo!3CxCKD0bbqOAzt9 zUuATNt1m=J_w|+o7__+bBH|_b-2kxh*-f?uQUWU(Lavmm89WT`U^+&mK=9!k=-}*y zR>YW>fp&ud2Vd~<#$&%V@!Lt-)u4~71mc8LZ6ga+1W$*9Y@E z&s;_B<~55zFvoHA2~)oTA36@${dHsM>_sPF^hCjfi3zdZgIuhTqd zONpKSNYJdN0`;O3B;-ou?2|ILXlZ`iF0-p^0dIzGe@tk>+kpEy4hhdYAV8Gxp1Q~e zt=mD=JyPVdct1TN8oPcTJ9_Z#QO|s?4C1^G(|Ml5`1ULWPyA$py9f5;`vf>cw?NEH zQ9c%FBbEoavPeH_fm{noBK&*Hr5nS=`cMo2-n*J-TgC66(*`bVY>rcchBT#Bo@)@n zlRePyBMx4|+k2@+?w=N@(gE^AC!H~~hKekzG#TH<8+jfwO0L-f%rZJ)VyTx7pmJJTF(4~jK2Z@BvvHYE63an zyvuka5=>l4N=z)v-RZ4WMwCP+YPsHPs?N&FwO4`58L824UcKQ077uQ2KClKth>?d2 zZ4?$QBr{_GyN~n5)cfcQoml0-U&?O@G_;m#FB^!)vpp7GDbR>HuE7Gh#o#mV>w4g= z!a|P;W0-CC&_GGTe?6 z7|u|7lao)Z&_|BBsC3H#*kcC2=3K7rsIE|eq>M1CicDDEHuDsR4dvNoAn|LP41i4* zwi)@(ioYSWMMlA4!xUp`(@<<-T(vZOpsH+7=BPG#`6h;^Z%iX}w8%zp7u!nxY3h(d-TA!Jz zom}5(HftQ^tfU#tY|rRdd5`bpxYhen+0pb$JZeyYfcyd~pk6m%1b~&zn4gy*SL8r1 z@x+Kt!;FjS_S1s!eUeXkQc*)ZZ#k9=JRjZbp&6>IA0&0ftaa;AYk65C1LTrX@6 zPM??{4HhEiv(xQ|*gQ9EY#I4<^h2Jt^L1t3xibA8PNcSB3gQ<9~VFM8CnK72H{N2M64AP`Tf%@3c#Bo3@6Efr_3*sy~qYckuil z5)Lg8K44{__wl$qjrYlk#Oh6%wdnP3Aja3~H(cLja6r7UCkk#7&5QI1 zIA$s*^KiqQh98a;>nd&E>J;NQqm1gHn9W1hXa*CCL%GNpQv@8237{&_-A%;!?cF)I zS?EE`FywYQzIEFL(j!(WMq6~y1W-PyVo3D;*M*?s--lv^Y2kA#uKJ#jb<+9#oFc+J zXxZOb@~DyV$N*b7d!@daZop^{ZPW$WpeJLsP%*Sk%gvqd_l0?Uf98fe_a%3(ztY|W z)uLb?Tf?)Cg#K+cQGQ<3ck;Gthy0?-WLz*zOMUqEq2p;{2>MdzbnyB z`X8w*IR21uNd$M(HJNB=;NO486}}YRXxrpI5_Ra+TuNl9}m@4(L;@ z$LT`}wV&X|7MGad$xCQ=V6-E0Q2P!@=2OKBssV5v$xr|jp93pvg2Jd^AGxvaA3e93 z@xe@>^;xQTl6N+3t^NW&8pjQ8VoX-4{7^wauXQAdk}*<;fyoERx5QO9Aj(LlvV z%N3&vq6&i%z-2c)VVALRvCeDO7d98j?Z#^-$3E>tT8=8A;P}Ec+w6?n9%Ink-;* zYX05>G=f%sFxyz>fAZxGUYGM3&6Ct-_aKat87uyWGv+tOxA&IA*}n?)SohK;6bejd zvi)S21A#w!)_mnBuk74dUat~M5~~%-lbyw$LO12Zd=l+|JFiB1bwjl3FS59wg5X>^ zo!;G>bjR>>mcd8LC#U@MV6bqS5^imB+hiTN$!!f^`k^^`-Bc;`Z^9Xa|=jjI73<$5S_WwwyohWQw? z#oFUFNmM};mA+bpo=hobaRQ(Ut13!qWRwyO+h@sVcbzIPWaIWd;shS$jyN|z77u~E z!Q&|26GT~I1k3;mCa^A%F8Ft3O>cjCeChX;Hcp|o`)-f6EMD|i3cM4SvZ}_JstxYq%qWc9>wZUw!oBR2~``&YA5FF7d+Up2C{$j{CrrpYdgh@U4I;r zL-e?hnr?_99$^eaf&R+&{t5P?QT@?zej89jcgJ)1M*s~x7*HLfHXn|aRc5`1zfd5`-?Em6fQT{iB*-*LkHN-bVh zYTG{&ZFGEn_t4m0bm8*L)6iXSyqiEfqP@$Ru`ue=FtNLVyCXdUk=dg6K!<1Y0AcIf zhalO91O$?A7unH^T~8rTgi&N0&S{yhdbZldu3qfNj&On2&#G!a-d+lubFZ42(FzYw zRvzY)e(in}W?mrqnGE;`iey!v`0)c*&_FCR;QV|T5?$|w%%$w(0uub z_CmQG3$!dr&=1~t2s<3SI%qA_04X$(Xt|N$O6_~;|40CtCoA`f*BxhX%|_4ShF4>u zk`~$rPfYGKLw7sJ;d~-g;D3|@YNWhs!A|eqwMeaAt-_2^xn&^yY&hZ zuww=LiI1n(;1{PqiQK`^HL#xZ1nZ}mKrk_&^Tv37DZ1(J)GXw$7c52zvtddZYmFiU+6k|BTDlH_|rc<2wvpy4kBvMxqz1h|Jz+Jwfr#kpXpYHCC@W!qA z!N>5{rOii~$*E53uj2Kgevx73by4M4PJ_cA^9mjf>{Q9=_*0;T4~SP6b)dylAG^yj zL}yOeZDmv`QY}=-1M(KrJ$X>VozOBWfLa_akhbq?i$OojH9`LN+mK`MNlKhVd1d8G z%~J6&$s^x){Dgpi%uiJs7S-O2x5|EZb@UxJ9mg%=(civfO2r*}T(=W)H+Hu}xtBNo zWRQ4mTtv%d@b)vHKrh>}!8G13^40NrL(BS&TX<6bTvaj^3o*ZYO{8J}(7~%*xN(rm z78uj;>zyf2H|g8M47Cb*o$hl;e8&A`&9FcpvjOOQf;#CPezIb;Ql=s$v@nG3HRSA? zAi<3?oZ0SkI&(m<`8I36J|>jW6(5Q>mol6mZl1OqAMzz46p}HIGzNJc$ z_6}%pLM!gX@Fxe#i!M53x42%3BJ;USYGS`W2-kIP+(}Gi++MXJYLXg8_9 zWdB(}vseTV1Hw(YQsJ7mqG6a;)Ds!)=4oq8!@N~{v0nF^KQx>*r(aefu!HSi?$*oJ zEBXlYJ9oG8lSzo7L0&T~{US!6nzQX?kbP=v6+_G`u31hq087(#9Og4Gd*CyawEq&}I_R45$*`Q1;>rix}=ieC&Spy%dG-s>26E>%l)t62NhnV};amZ(ab$Q!a5tKb*`Y zcxn(8;}N+6pYtI%>?<@U&rEG@uw4rc+* zsVzEtt$RY7X|BrnRVrClYs9Cu7-0vjZW*`2XgkjjB`Pb)!*l9lcYN9GO?o?Jhp

grX5kAnI7=yXit`@W>Pbv5O3$W*%9No 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%0D!HvI2srO7R>s0u0X(o9pX;k-Xz_y?7-o4VgT%# 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.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 VCItYF2In1!ZDDF{Qek{8`d_IH0SW*B literal 77579 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±JV~w(ThIDK>wg};C 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 Date: Fri, 12 Jul 2019 18:24:49 +0900 Subject: [PATCH 1874/5608] Update android icon --- osu.Android/Resources/drawable/lazer.png | Bin 39498 -> 39318 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/osu.Android/Resources/drawable/lazer.png b/osu.Android/Resources/drawable/lazer.png index 075a8e7184ad508cedd8fe9ae549d8cea696b51a..fc7aa8a092cb616233bc83a3328413740bb57953 100644 GIT binary patch literal 39318 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 X{r?ZpP_kcw2Ot$CjR&O)ra}J$c_$^Y From 341f2462232a5ecb1acc9056bfe7c511cd98ad8b Mon Sep 17 00:00:00 2001 From: kakiremora <32620809+ticotaco72@users.noreply.github.com> Date: Fri, 12 Jul 2019 15:17:13 +0200 Subject: [PATCH 1875/5608] Fix README icon display on mobile (#5341) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 590442f01b..fdf5c85b20 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- +

# osu! From 3c665bfb2970378d565669eee8b6119efb76a52c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jul 2019 22:21:25 +0900 Subject: [PATCH 1876/5608] Revert breaking README change --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fdf5c85b20..52fc29cb98 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- +

# osu! From bbc3cbf5632fbe5fd8adffd0c9c29db639d4b7dc Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 12 Jul 2019 20:22:31 +0200 Subject: [PATCH 1877/5608] Restore deleted line --- osu.Game/Overlays/OSD/Toast.cs | 6 ++++-- osu.Game/Overlays/OSD/TrackedSettingToast.cs | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/OSD/Toast.cs b/osu.Game/Overlays/OSD/Toast.cs index 6572830d10..67c9b46c77 100644 --- a/osu.Game/Overlays/OSD/Toast.cs +++ b/osu.Game/Overlays/OSD/Toast.cs @@ -16,6 +16,8 @@ namespace osu.Game.Overlays.OSD private readonly Container content; protected override Container Content => content; + protected readonly OsuSpriteText ValueText; + protected Toast(string description, string value, string keybinding) { Anchor = Anchor.Centre; @@ -49,13 +51,13 @@ namespace osu.Game.Overlays.OSD Origin = Anchor.TopCentre, Text = description.ToUpperInvariant() }, - new OsuSpriteText + ValueText = new OsuSpriteText { Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), Padding = new MarginPadding { Left = 10, Right = 10 }, Name = "Value", Anchor = Anchor.Centre, - Origin = Anchor.BottomCentre, + Origin = Anchor.Centre, Text = value }, new OsuSpriteText diff --git a/osu.Game/Overlays/OSD/TrackedSettingToast.cs b/osu.Game/Overlays/OSD/TrackedSettingToast.cs index 454ba84d70..9812dcd797 100644 --- a/osu.Game/Overlays/OSD/TrackedSettingToast.cs +++ b/osu.Game/Overlays/OSD/TrackedSettingToast.cs @@ -62,6 +62,8 @@ namespace osu.Game.Overlays.OSD break; } + ValueText.Origin = optionCount > 0 ? Anchor.BottomCentre : Anchor.Centre; + for (int i = 0; i < optionCount; i++) { optionLights.Add(new OptionLight From 08014b1b99232e698e4118fe003661cdd7c6a560 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 13 Jul 2019 11:13:00 +0900 Subject: [PATCH 1878/5608] Fix logo masking not being applied correctly for showcase/win screens --- osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs | 2 +- osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs index d809dfc994..20928499bf 100644 --- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -10,7 +10,7 @@ namespace osu.Game.Tournament.Screens.Showcase [BackgroundDependencyLoader] private void load() { - AddInternal(new TournamentLogo()); + AddInternal(new TournamentLogo(false)); } } } diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs index efe4ee92fc..a0216c5db3 100644 --- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tournament.Screens.TeamWin RelativeSizeAxes = Axes.Both, Loop = true, }, - new TournamentLogo + new TournamentLogo(false) { Y = 40, }, From 0584ee9ce55c5a9e86940c66754f5722ba4d4cd3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 12:34:12 +0300 Subject: [PATCH 1879/5608] Basic implementation --- .../SongSelect/TestSceneUserTopScore.cs | 97 +++++++++++++++++++ .../Select/Details/UserTopScoreContainer.cs | 79 +++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs create mode 100644 osu.Game/Screens/Select/Details/UserTopScoreContainer.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs new file mode 100644 index 0000000000..f7cfd4156d --- /dev/null +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -0,0 +1,97 @@ +// 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.Screens.Select.Details; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +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.Users; + +namespace osu.Game.Tests.Visual.SongSelect +{ + public class TestSceneUserTopScore : OsuTestScene + { + private readonly UserTopScoreContainer topScoreContainer; + private readonly APILegacyUserTopScoreInfo[] scores; + + public TestSceneUserTopScore() + { + Add(new Container + { + Origin = Anchor.BottomCentre, + Anchor = Anchor.Centre, + AutoSizeAxes = Axes.Y, + Width = 500, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.DarkGreen, + }, + topScoreContainer = new UserTopScoreContainer + { + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + } + } + }); + + AddStep(@"Trigger visibility", topScoreContainer.ToggleVisibility); + AddStep(@"Add score", () => topScoreContainer.TopScore = scores[0]); + AddStep(@"Add another score", () => topScoreContainer.TopScore = scores[1]); + + scores = new APILegacyUserTopScoreInfo[] + { + new APILegacyUserTopScoreInfo + { + Position = 999, + Score = new APILegacyScoreInfo + { + Rank = ScoreRank.XH, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 1707827, + Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, + User = new User + { + Id = 6602580, + Username = @"waaiiru", + Country = new Country + { + FullName = @"Spain", + FlagName = @"ES", + }, + }, + } + }, + new APILegacyUserTopScoreInfo + { + Position = 110000, + Score = new APILegacyScoreInfo + { + Rank = ScoreRank.X, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 1707827, + User = new User + { + Id = 4608074, + Username = @"Skycries", + Country = new Country + { + FullName = @"Brazil", + FlagName = @"BR", + }, + }, + } + } + }; + } + } +} diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs new file mode 100644 index 0000000000..05d0930de5 --- /dev/null +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -0,0 +1,79 @@ +// 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.Online.API.Requests.Responses; +using osu.Game.Online.Leaderboards; + +namespace osu.Game.Screens.Select.Details +{ + public class UserTopScoreContainer : VisibilityContainer + { + private const int height = 150; + private const int duration = 300; + + private readonly Container contentContainer; + private readonly Container scoreContainer; + + public APILegacyUserTopScoreInfo TopScore + { + set + { + scoreContainer.Clear(); + scoreContainer.Add(new LeaderboardScore(value.Score, value.Position)); + } + } + + protected override bool StartHidden => true; + + public UserTopScoreContainer() + { + RelativeSizeAxes = Axes.X; + Height = height; + Anchor = Anchor.BottomCentre; + Origin = Anchor.BottomCentre; + Children = new Drawable[] + { + contentContainer = new Container + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Height = height, + RelativeSizeAxes = Axes.X, + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = @"your personal best".ToUpper(), + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), + }, + scoreContainer = new Container + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } + } + } + }; + } + + protected override void PopIn() + { + this.ResizeHeightTo(height, duration, Easing.OutQuint); + contentContainer.FadeIn(duration, Easing.OutQuint); + } + + protected override void PopOut() + { + this.ResizeHeightTo(0, duration, Easing.OutQuint); + contentContainer.FadeOut(duration, Easing.OutQuint); + } + } +} From d30ae24f581d14d2068fbec2acf69375f6ff620a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 12:40:54 +0300 Subject: [PATCH 1880/5608] Use Bindable for setting score --- .../SongSelect/TestSceneUserTopScore.cs | 5 +++-- .../Select/Details/UserTopScoreContainer.cs | 20 +++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs index f7cfd4156d..3fa85ffca6 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -43,8 +43,9 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddStep(@"Trigger visibility", topScoreContainer.ToggleVisibility); - AddStep(@"Add score", () => topScoreContainer.TopScore = scores[0]); - AddStep(@"Add another score", () => topScoreContainer.TopScore = scores[1]); + AddStep(@"Add score", () => topScoreContainer.TopScore.Value = scores[0]); + AddStep(@"Add another score", () => topScoreContainer.TopScore.Value = scores[1]); + AddStep(@"Add null score", () => topScoreContainer.TopScore.Value = null); scores = new APILegacyUserTopScoreInfo[] { diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 05d0930de5..21c16d1d74 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -18,14 +19,7 @@ namespace osu.Game.Screens.Select.Details private readonly Container contentContainer; private readonly Container scoreContainer; - public APILegacyUserTopScoreInfo TopScore - { - set - { - scoreContainer.Clear(); - scoreContainer.Add(new LeaderboardScore(value.Score, value.Position)); - } - } + public Bindable TopScore = new Bindable(); protected override bool StartHidden => true; @@ -62,6 +56,16 @@ namespace osu.Game.Screens.Select.Details } } }; + + TopScore.BindValueChanged((score) => onScoreChanged(score.NewValue)); + } + + private void onScoreChanged(APILegacyUserTopScoreInfo score) + { + scoreContainer.Clear(); + + if (score != null) + scoreContainer.Add(new LeaderboardScore(score.Score, score.Position)); } protected override void PopIn() From 922c3c89ae4eb9d89c6e5c90d7af0c2ae7222fd0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 12:47:35 +0300 Subject: [PATCH 1881/5608] Make leaderboard score use metric system --- .../SongSelect/TestSceneUserTopScore.cs | 26 +++++++++++++++++-- .../Online/Leaderboards/LeaderboardScore.cs | 12 ++++----- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs index 3fa85ffca6..1023294000 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -43,8 +43,9 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddStep(@"Trigger visibility", topScoreContainer.ToggleVisibility); - AddStep(@"Add score", () => topScoreContainer.TopScore.Value = scores[0]); - AddStep(@"Add another score", () => topScoreContainer.TopScore.Value = scores[1]); + AddStep(@"Add score(rank 999)", () => topScoreContainer.TopScore.Value = scores[0]); + AddStep(@"Add score(rank 110000)", () => topScoreContainer.TopScore.Value = scores[1]); + AddStep(@"Add score(rank 22333)", () => topScoreContainer.TopScore.Value = scores[2]); AddStep(@"Add null score", () => topScoreContainer.TopScore.Value = null); scores = new APILegacyUserTopScoreInfo[] @@ -91,6 +92,27 @@ namespace osu.Game.Tests.Visual.SongSelect }, }, } + }, + new APILegacyUserTopScoreInfo + { + Position = 22333, + Score = new APILegacyScoreInfo + { + Rank = ScoreRank.S, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 1707827, + User = new User + { + Id = 1541390, + Username = @"Toukai", + Country = new Country + { + FullName = @"Canada", + FlagName = @"CA", + }, + }, + } } }; } diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 9840b59805..713d4a25f7 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -20,23 +20,23 @@ using osu.Game.Scoring; using osu.Game.Users.Drawables; using osuTK; using osuTK.Graphics; +using Humanizer; namespace osu.Game.Online.Leaderboards { public class LeaderboardScore : OsuClickableContainer { - public readonly int RankPosition; - public const float HEIGHT = 60; private const float corner_radius = 5; private const float edge_margin = 5; private const float background_alpha = 0.25f; - private const float rank_width = 30; + private const float rank_width = 35; protected Container RankContainer { get; private set; } private readonly ScoreInfo score; + private readonly int rank; private Box background; private Container content; @@ -52,7 +52,7 @@ namespace osu.Game.Online.Leaderboards public LeaderboardScore(ScoreInfo score, int rank) { this.score = score; - RankPosition = rank; + this.rank = rank; RelativeSizeAxes = Axes.X; Height = HEIGHT; @@ -79,8 +79,8 @@ namespace osu.Game.Online.Leaderboards { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 22, italics: true), - Text = RankPosition.ToString(), + Font = OsuFont.GetFont(size: 20, italics: true), + Text = rank <= 999 ? rank.ToString() : rank.ToMetric(decimals: rank < 100000 ? 1 : 0), }, }, }, From d1409d4610bbcb4f58c6cc5fb0ee0ea8b8e6f37d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 13:33:47 +0300 Subject: [PATCH 1882/5608] Add top score section into beatmap detail area --- .../SongSelect/TestSceneBeatmapDetailArea.cs | 1 + osu.Game/Screens/Select/BeatmapDetailArea.cs | 68 +++++++++++-------- .../Select/Details/UserTopScoreContainer.cs | 3 +- 3 files changed, 42 insertions(+), 30 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index 7b97a27732..e9650343af 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -163,6 +163,7 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddStep("null beatmap", () => detailsArea.Beatmap = null); + AddStep("Toggle top score visibility", () => detailsArea.TopScore.ToggleVisibility()); } } } diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index b66a2ffe0f..678b18e8cf 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -5,19 +5,18 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; +using osu.Game.Screens.Select.Details; using osu.Game.Screens.Select.Leaderboards; namespace osu.Game.Screens.Select { public class BeatmapDetailArea : Container { - private const float details_padding = 10; - - private readonly Container content; - protected override Container Content => content; + private const float padding = 10; public readonly BeatmapDetails Details; public readonly BeatmapLeaderboard Leaderboard; + public readonly UserTopScoreContainer TopScore; private WorkingBeatmap beatmap; @@ -34,7 +33,7 @@ namespace osu.Game.Screens.Select public BeatmapDetailArea() { - AddRangeInternal(new Drawable[] + Children = new Drawable[] { new BeatmapDetailAreaTabControl { @@ -58,33 +57,44 @@ namespace osu.Game.Screens.Select } }, }, - content = new Container + new GridContainer { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT }, + Margin = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT }, + RowDimensions = new Dimension[] + { + new Dimension(GridSizeMode.Distributed), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + Details = new BeatmapDetails + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + Padding = new MarginPadding { Vertical = padding }, + }, + Leaderboard = new BeatmapLeaderboard + { + RelativeSizeAxes = Axes.Both, + } + } + } + }, + new Drawable[] + { + TopScore = new UserTopScoreContainer(), + } + }, }, - }); - - AddRange(new Drawable[] - { - Details = new BeatmapDetails - { - RelativeSizeAxes = Axes.X, - Alpha = 0, - Margin = new MarginPadding { Top = details_padding }, - }, - Leaderboard = new BeatmapLeaderboard - { - RelativeSizeAxes = Axes.Both, - } - }); - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - Details.Height = Math.Min(DrawHeight - details_padding * 3 - BeatmapDetailAreaTabControl.HEIGHT, 450); + }; } } } diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 21c16d1d74..2cc47a7483 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.Select.Details { public class UserTopScoreContainer : VisibilityContainer { - private const int height = 150; + private const int height = 110; private const int duration = 300; private readonly Container contentContainer; @@ -37,6 +37,7 @@ namespace osu.Game.Screens.Select.Details Origin = Anchor.BottomCentre, Height = height, RelativeSizeAxes = Axes.X, + Padding = new MarginPadding { Vertical = 10 }, Children = new Drawable[] { new OsuSpriteText From 963e025bb8882eb94884adbf40bb6b13cc0b298a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 14:03:14 +0300 Subject: [PATCH 1883/5608] Make it works and some layout adjustments --- .../SongSelect/TestSceneUserTopScore.cs | 8 +-- osu.Game/Screens/Select/BeatmapDetailArea.cs | 60 +++++++++++-------- .../Select/Details/UserTopScoreContainer.cs | 11 ++-- .../Select/Leaderboards/BeatmapLeaderboard.cs | 9 ++- 4 files changed, 53 insertions(+), 35 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs index 1023294000..b33dbddccb 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -43,10 +43,10 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddStep(@"Trigger visibility", topScoreContainer.ToggleVisibility); - AddStep(@"Add score(rank 999)", () => topScoreContainer.TopScore.Value = scores[0]); - AddStep(@"Add score(rank 110000)", () => topScoreContainer.TopScore.Value = scores[1]); - AddStep(@"Add score(rank 22333)", () => topScoreContainer.TopScore.Value = scores[2]); - AddStep(@"Add null score", () => topScoreContainer.TopScore.Value = null); + AddStep(@"Add score(rank 999)", () => topScoreContainer.Score.Value = scores[0]); + AddStep(@"Add score(rank 110000)", () => topScoreContainer.Score.Value = scores[1]); + AddStep(@"Add score(rank 22333)", () => topScoreContainer.Score.Value = scores[2]); + AddStep(@"Add null score", () => topScoreContainer.Score.Value = null); scores = new APILegacyUserTopScoreInfo[] { diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index 678b18e8cf..cac1281cc2 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -1,10 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Screens.Select.Details; using osu.Game.Screens.Select.Leaderboards; @@ -28,6 +28,7 @@ namespace osu.Game.Screens.Select beatmap = value; Leaderboard.Beatmap = beatmap?.BeatmapInfo; Details.Beatmap = beatmap?.BeatmapInfo; + TopScore.Hide(); } } @@ -57,43 +58,50 @@ namespace osu.Game.Screens.Select } }, }, - new GridContainer + new Container { + Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT, Bottom = padding }, RelativeSizeAxes = Axes.Both, - Margin = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT }, - RowDimensions = new Dimension[] + Child = new GridContainer { - new Dimension(GridSizeMode.Distributed), - new Dimension(GridSizeMode.AutoSize), - }, - Content = new[] - { - new Drawable[] + RelativeSizeAxes = Axes.Both, + RowDimensions = new Dimension[] { - new Container + new Dimension(GridSizeMode.Distributed), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new Drawable[] { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + new Container { - Details = new BeatmapDetails + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - Padding = new MarginPadding { Vertical = padding }, - }, - Leaderboard = new BeatmapLeaderboard - { - RelativeSizeAxes = Axes.Both, + Details = new BeatmapDetails + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + Padding = new MarginPadding { Top = padding }, + }, + Leaderboard = new BeatmapLeaderboard + { + RelativeSizeAxes = Axes.Both, + } } } + }, + new Drawable[] + { + TopScore = new UserTopScoreContainer + { + Score = { BindTarget = Leaderboard.TopScore } + } } }, - new Drawable[] - { - TopScore = new UserTopScoreContainer(), - } }, - }, + } }; } } diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 2cc47a7483..0bc30fae6b 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -13,13 +13,13 @@ namespace osu.Game.Screens.Select.Details { public class UserTopScoreContainer : VisibilityContainer { - private const int height = 110; + private const int height = 90; private const int duration = 300; private readonly Container contentContainer; private readonly Container scoreContainer; - public Bindable TopScore = new Bindable(); + public Bindable Score = new Bindable(); protected override bool StartHidden => true; @@ -37,13 +37,13 @@ namespace osu.Game.Screens.Select.Details Origin = Anchor.BottomCentre, Height = height, RelativeSizeAxes = Axes.X, - Padding = new MarginPadding { Vertical = 10 }, Children = new Drawable[] { new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Margin = new MarginPadding { Top = 5 }, Text = @"your personal best".ToUpper(), Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), }, @@ -58,7 +58,7 @@ namespace osu.Game.Screens.Select.Details } }; - TopScore.BindValueChanged((score) => onScoreChanged(score.NewValue)); + Score.BindValueChanged((score) => onScoreChanged(score.NewValue)); } private void onScoreChanged(APILegacyUserTopScoreInfo score) @@ -66,7 +66,10 @@ namespace osu.Game.Screens.Select.Details scoreContainer.Clear(); if (score != null) + { scoreContainer.Add(new LeaderboardScore(score.Score, score.Position)); + Show(); + } } protected override void PopIn() diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 0f6d4f3188..c41bf17685 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -9,6 +9,7 @@ using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -18,6 +19,8 @@ namespace osu.Game.Screens.Select.Leaderboards { public class BeatmapLeaderboard : Leaderboard { + public Bindable TopScore = new Bindable(); + public Action ScoreSelected; private BeatmapInfo beatmap; @@ -133,7 +136,11 @@ namespace osu.Game.Screens.Select.Leaderboards var req = new GetScoresRequest(Beatmap, ruleset.Value ?? Beatmap.Ruleset, Scope, requestMods); - req.Success += r => scoresCallback?.Invoke(r.Scores); + req.Success += r => + { + scoresCallback?.Invoke(r.Scores); + TopScore.Value = r.UserScore; + }; return req; } From ecf0e624849901aedcb2eac6008853773ef6aee8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 16:16:21 +0300 Subject: [PATCH 1884/5608] CI fixes --- .../SongSelect/TestSceneUserTopScore.cs | 19 +++++++++---------- osu.Game/Screens/Select/BeatmapDetailArea.cs | 3 +-- .../Select/Details/UserTopScoreContainer.cs | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs index b33dbddccb..1de8a5375e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -16,11 +16,10 @@ namespace osu.Game.Tests.Visual.SongSelect { public class TestSceneUserTopScore : OsuTestScene { - private readonly UserTopScoreContainer topScoreContainer; - private readonly APILegacyUserTopScoreInfo[] scores; - public TestSceneUserTopScore() { + UserTopScoreContainer topScoreContainer; + Add(new Container { Origin = Anchor.BottomCentre, @@ -42,13 +41,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - AddStep(@"Trigger visibility", topScoreContainer.ToggleVisibility); - AddStep(@"Add score(rank 999)", () => topScoreContainer.Score.Value = scores[0]); - AddStep(@"Add score(rank 110000)", () => topScoreContainer.Score.Value = scores[1]); - AddStep(@"Add score(rank 22333)", () => topScoreContainer.Score.Value = scores[2]); - AddStep(@"Add null score", () => topScoreContainer.Score.Value = null); - - scores = new APILegacyUserTopScoreInfo[] + APILegacyUserTopScoreInfo[] scores = new[] { new APILegacyUserTopScoreInfo { @@ -115,6 +108,12 @@ namespace osu.Game.Tests.Visual.SongSelect } } }; + + AddStep(@"Trigger visibility", topScoreContainer.ToggleVisibility); + AddStep(@"Add score(rank 999)", () => topScoreContainer.Score.Value = scores[0]); + AddStep(@"Add score(rank 110000)", () => topScoreContainer.Score.Value = scores[1]); + AddStep(@"Add score(rank 22333)", () => topScoreContainer.Score.Value = scores[2]); + AddStep(@"Add null score", () => topScoreContainer.Score.Value = null); } } } diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index cac1281cc2..6cd6372152 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -4,7 +4,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Screens.Select.Details; using osu.Game.Screens.Select.Leaderboards; @@ -65,7 +64,7 @@ namespace osu.Game.Screens.Select Child = new GridContainer { RelativeSizeAxes = Axes.Both, - RowDimensions = new Dimension[] + RowDimensions = new[] { new Dimension(GridSizeMode.Distributed), new Dimension(GridSizeMode.AutoSize), diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 0bc30fae6b..0300d14ac1 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -58,7 +58,7 @@ namespace osu.Game.Screens.Select.Details } }; - Score.BindValueChanged((score) => onScoreChanged(score.NewValue)); + Score.BindValueChanged(score => onScoreChanged(score.NewValue)); } private void onScoreChanged(APILegacyUserTopScoreInfo score) From 19680c8df8f7c883df97f600bde0e1f882687758 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 16:37:05 +0300 Subject: [PATCH 1885/5608] Minor adjustments --- osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs | 2 +- osu.Game/Screens/Select/Details/UserTopScoreContainer.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs index 1de8a5375e..5ddccb4c8e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - APILegacyUserTopScoreInfo[] scores = new[] + var scores = new APILegacyUserTopScoreInfo[] { new APILegacyUserTopScoreInfo { diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 0300d14ac1..e5e33a47d8 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -63,13 +63,14 @@ namespace osu.Game.Screens.Select.Details private void onScoreChanged(APILegacyUserTopScoreInfo score) { - scoreContainer.Clear(); - if (score != null) { + scoreContainer.Clear(); scoreContainer.Add(new LeaderboardScore(score.Score, score.Position)); Show(); } + else + Hide(); } protected override void PopIn() From a01e7260e06e7b23d6b40d7c54d56bee969eb2cc Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 16:49:46 +0300 Subject: [PATCH 1886/5608] Testcase fix --- osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs index 5ddccb4c8e..5f3e7d09dd 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - var scores = new APILegacyUserTopScoreInfo[] + var scores = new[] { new APILegacyUserTopScoreInfo { From b93b26a0366069000d99535a6f83f62e7e377726 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 19:38:46 +0300 Subject: [PATCH 1887/5608] Fix link formatting --- .../Profile/Sections/UnderscoredBeatmapLink.cs | 14 +++++++------- .../Profile/Sections/UnderscoredLinkContainer.cs | 9 +++++++++ .../Profile/Sections/UnderscoredUserLink.cs | 9 ++++----- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/UnderscoredBeatmapLink.cs b/osu.Game/Overlays/Profile/Sections/UnderscoredBeatmapLink.cs index 370d6d84ef..ddad99355c 100644 --- a/osu.Game/Overlays/Profile/Sections/UnderscoredBeatmapLink.cs +++ b/osu.Game/Overlays/Profile/Sections/UnderscoredBeatmapLink.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Game.Beatmaps; namespace osu.Game.Overlays.Profile.Sections @@ -15,15 +14,16 @@ namespace osu.Game.Overlays.Profile.Sections this.beatmap = beatmap; } - [BackgroundDependencyLoader(true)] - private void load(BeatmapSetOverlay beatmapSetOverlay) + protected override void LoadComplete() { + base.LoadComplete(); + ClickAction = () => { - if (beatmap.OnlineBeatmapID != null) - beatmapSetOverlay?.FetchAndShowBeatmap(beatmap.OnlineBeatmapID.Value); - else if (beatmap.BeatmapSet?.OnlineBeatmapSetID != null) - beatmapSetOverlay?.FetchAndShowBeatmapSet(beatmap.BeatmapSet.OnlineBeatmapSetID.Value); + var beatmapId = beatmap.OnlineBeatmapID; + + if (beatmapId.HasValue) + Game?.ShowBeatmap(beatmapId.Value); }; } } diff --git a/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs b/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs index 8daf0bd24d..09a23d2fe3 100644 --- a/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -17,6 +18,8 @@ namespace osu.Game.Overlays.Profile.Sections private readonly Container underscore; private readonly FillFlowContainer textContent; + protected OsuGame Game; + protected Action ClickAction; public IReadOnlyList Text @@ -59,6 +62,12 @@ namespace osu.Game.Overlays.Profile.Sections }; } + [BackgroundDependencyLoader(true)] + private void load(OsuGame game) + { + Game = game; + } + protected override bool OnHover(HoverEvent e) { underscore.FadeIn(duration, Easing.OutQuint); diff --git a/osu.Game/Overlays/Profile/Sections/UnderscoredUserLink.cs b/osu.Game/Overlays/Profile/Sections/UnderscoredUserLink.cs index f50bc7f7ba..9b3e8ccdf6 100644 --- a/osu.Game/Overlays/Profile/Sections/UnderscoredUserLink.cs +++ b/osu.Game/Overlays/Profile/Sections/UnderscoredUserLink.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; - namespace osu.Game.Overlays.Profile.Sections { public class UnderscoredUserLink : UnderscoredLinkContainer @@ -14,10 +12,11 @@ namespace osu.Game.Overlays.Profile.Sections this.userId = userId; } - [BackgroundDependencyLoader(true)] - private void load(UserProfileOverlay userProfileOverlay) + protected override void LoadComplete() { - ClickAction = () => userProfileOverlay?.ShowUser(userId); + base.LoadComplete(); + + ClickAction = () => Game?.ShowUser(userId); } } } From d093eb6660c7f04ff27c75dd587e08bb67bd48d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 15 Jul 2019 11:45:15 +0900 Subject: [PATCH 1888/5608] Mark sprite read-only --- osu.Game/Graphics/Backgrounds/Background.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index 526b3da8a6..436fcd0476 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.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.Allocation; @@ -16,7 +16,7 @@ namespace osu.Game.Graphics.Backgrounds ///

public class Background : CompositeDrawable { - public Sprite Sprite; + public readonly Sprite Sprite; private readonly string textureName; From 2186ffda555e610f799a3d2da0865ced1b3b949f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 15 Jul 2019 11:46:41 +0900 Subject: [PATCH 1889/5608] Avoid unnecessarily creating buffered container for zero-blur --- osu.Game/Graphics/Backgrounds/Background.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index 436fcd0476..0043aab7e2 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.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.Allocation; @@ -51,7 +51,7 @@ namespace osu.Game.Graphics.Backgrounds /// A to which further transforms can be added. public void BlurTo(Vector2 newBlurSigma, double duration = 0, Easing easing = Easing.None) { - if (bufferedContainer == null) + if (bufferedContainer == null && newBlurSigma != Vector2.Zero) { RemoveInternal(Sprite); From 12e7668afc3245b5395c976ff8e71cd9d5e7a3b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 15 Jul 2019 11:48:33 +0900 Subject: [PATCH 1890/5608] Fix potential cross-thread talk from bindable updates --- osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 08f1881038..5225740d0b 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.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; @@ -168,6 +168,12 @@ namespace osu.Game.Screens.Backgrounds private void load(OsuConfigManager config) { userBlurLevel = config.GetBindable(OsuSetting.BlurLevel); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + userBlurLevel.ValueChanged += _ => UpdateVisuals(); BlurAmount.ValueChanged += _ => UpdateVisuals(); } From d92f6c762ba88e6d4335134a9ec131c8c9c457e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 15 Jul 2019 11:53:16 +0900 Subject: [PATCH 1891/5608] Fix potential nullref --- 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 0043aab7e2..d13475189d 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -63,7 +63,7 @@ namespace osu.Game.Graphics.Backgrounds }); } - bufferedContainer.BlurTo(newBlurSigma, duration, easing); + bufferedContainer?.BlurTo(newBlurSigma, duration, easing); } } } From 27258e3a9b6b16d2ed845b9e65ab63515366a718 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 15 Jul 2019 14:38:05 +0900 Subject: [PATCH 1892/5608] Rename test scene to match class --- ...SceneUserTopScore.cs => TestSceneUserTopScoreContainer.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename osu.Game.Tests/Visual/SongSelect/{TestSceneUserTopScore.cs => TestSceneUserTopScoreContainer.cs} (97%) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs similarity index 97% rename from osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs rename to osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs index 5f3e7d09dd..38ebb58e76 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs @@ -14,9 +14,9 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.SongSelect { - public class TestSceneUserTopScore : OsuTestScene + public class TestSceneUserTopScoreContainer : OsuTestScene { - public TestSceneUserTopScore() + public TestSceneUserTopScoreContainer() { UserTopScoreContainer topScoreContainer; From 9c1badd2e3771a36c2eea89d090c0db873991f71 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 15 Jul 2019 15:42:54 +0900 Subject: [PATCH 1893/5608] Fix rulesets not matching in dictionary lookups due to missing GetHashCode implementation --- osu.Game/Rulesets/RulesetInfo.cs | 14 ++++++++++++++ osu.Game/Rulesets/RulesetStore.cs | 6 +++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index ca331ec339..8eb2abec79 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics.CodeAnalysis; using Newtonsoft.Json; namespace osu.Game.Rulesets @@ -23,6 +24,19 @@ namespace osu.Game.Rulesets public bool Equals(RulesetInfo other) => other != null && ID == other.ID && Available == other.Available && Name == other.Name && InstantiationInfo == other.InstantiationInfo; + [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")] + public override int GetHashCode() + { + unchecked + { + var hashCode = ID.HasValue ? ID.GetHashCode() : 0; + hashCode = (hashCode * 397) ^ (InstantiationInfo != null ? InstantiationInfo.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Name != null ? Name.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ Available.GetHashCode(); + return hashCode; + } + } + public override string ToString() => $"{Name} ({ShortName}) ID: {ID}"; } } diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index fd42f96c92..2d8c9f5b49 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets public RulesetStore(IDatabaseContextFactory factory) : base(factory) { - AddMissingRulesets(); + addMissingRulesets(); } /// @@ -52,13 +52,13 @@ namespace osu.Game.Rulesets /// /// All available rulesets. /// - public IEnumerable AvailableRulesets; + public IEnumerable AvailableRulesets { get; private set; } private static Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args) => loaded_assemblies.Keys.FirstOrDefault(a => a.FullName == args.Name); private const string ruleset_library_prefix = "osu.Game.Rulesets"; - protected void AddMissingRulesets() + private void addMissingRulesets() { using (var usage = ContextFactory.GetForWrite()) { From d0c8aaba4e1f6442e188f7042deb4d8a0a5b5b3f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 15 Jul 2019 15:50:50 +0900 Subject: [PATCH 1894/5608] Override basic equality function too --- osu.Game/Rulesets/RulesetInfo.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 8eb2abec79..d9cff86265 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -24,6 +24,8 @@ namespace osu.Game.Rulesets public bool Equals(RulesetInfo other) => other != null && ID == other.ID && Available == other.Available && Name == other.Name && InstantiationInfo == other.InstantiationInfo; + public override bool Equals(object obj) => obj is RulesetInfo rulesetInfo && Equals(rulesetInfo); + [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")] public override int GetHashCode() { From d4c1005c7e820bfa7d7cb1a5b1791e3ba1b0a5a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 15 Jul 2019 15:53:19 +0900 Subject: [PATCH 1895/5608] Fix incorrect comparison in line updating logic --- osu.Game/OsuGame.cs | 2 +- osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 361ff62155..2a484fc122 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -248,7 +248,7 @@ namespace osu.Game } // Use first beatmap available for current ruleset, else switch ruleset. - var first = databasedSet.Beatmaps.Find(b => b.Ruleset == Ruleset.Value) ?? databasedSet.Beatmaps.First(); + var first = databasedSet.Beatmaps.Find(b => b.Ruleset.Equals(Ruleset.Value)) ?? databasedSet.Beatmaps.First(); Ruleset.Value = first.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first); diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index f4272ab15c..bf0cd91321 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -73,7 +73,7 @@ namespace osu.Game.Overlays.Toolbar { foreach (var tabItem in TabContainer) { - if (tabItem.Value == Current.Value) + if (tabItem.Value.Equals(Current.Value)) { ModeButtonLine.MoveToX(tabItem.DrawPosition.X, !hasInitialPosition ? 0 : 200, Easing.OutQuint); break; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 0eeffda5eb..b3c3925a26 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -329,7 +329,7 @@ namespace osu.Game.Screens.Select if (this.IsCurrentScreen() && !Carousel.SelectBeatmap(e.NewValue?.BeatmapInfo, false)) // If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch - if (e.NewValue?.BeatmapInfo?.Ruleset != null && e.NewValue.BeatmapInfo.Ruleset != decoupledRuleset.Value) + if (e.NewValue?.BeatmapInfo?.Ruleset != null && !e.NewValue.BeatmapInfo.Ruleset.Equals(decoupledRuleset.Value)) { Ruleset.Value = e.NewValue.BeatmapInfo.Ruleset; Carousel.SelectBeatmap(e.NewValue.BeatmapInfo); From 7e367dc397e9ce17fe089b83df4b324689d5d756 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 15 Jul 2019 12:30:42 +0300 Subject: [PATCH 1896/5608] Push results screen when clicking on top score --- osu.Game/Screens/Select/Details/UserTopScoreContainer.cs | 9 ++++++++- osu.Game/Screens/Select/SongSelect.cs | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index e5e33a47d8..ba6751475e 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -8,6 +8,8 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; +using osu.Game.Scoring; +using System; namespace osu.Game.Screens.Select.Details { @@ -21,6 +23,8 @@ namespace osu.Game.Screens.Select.Details public Bindable Score = new Bindable(); + public Action ScoreSelected; + protected override bool StartHidden => true; public UserTopScoreContainer() @@ -66,7 +70,10 @@ namespace osu.Game.Screens.Select.Details if (score != null) { scoreContainer.Clear(); - scoreContainer.Add(new LeaderboardScore(score.Score, score.Position)); + scoreContainer.Add(new LeaderboardScore(score.Score, score.Position) + { + Action = () => ScoreSelected?.Invoke(score.Score) + }); Show(); } else diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index b3c3925a26..94b1fedeab 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -216,6 +216,7 @@ namespace osu.Game.Screens.Select } BeatmapDetails.Leaderboard.ScoreSelected += s => this.Push(new SoloResults(s)); + BeatmapDetails.TopScore.ScoreSelected += s => this.Push(new SoloResults(s)); } [BackgroundDependencyLoader(true)] From d62e42ba1459d5b32c3c721f9a322d9af7d7bb19 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 15 Jul 2019 13:09:21 +0300 Subject: [PATCH 1897/5608] Remove custom link container implementation --- .../Sections/BeatmapMetadataContainer.cs | 26 ++---- .../Historical/DrawableMostPlayedBeatmap.cs | 75 +++++++--------- .../Sections/Ranks/DrawableProfileScore.cs | 29 +++++- .../Sections/UnderscoredBeatmapLink.cs | 30 ------- .../Sections/UnderscoredLinkContainer.cs | 89 ------------------- .../Profile/Sections/UnderscoredUserLink.cs | 22 ----- 6 files changed, 67 insertions(+), 204 deletions(-) delete mode 100644 osu.Game/Overlays/Profile/Sections/UnderscoredBeatmapLink.cs delete mode 100644 osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs delete mode 100644 osu.Game/Overlays/Profile/Sections/UnderscoredUserLink.cs diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs index 16326900f1..597171cc7f 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs @@ -4,22 +4,19 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Localisation; using osu.Game.Beatmaps; -using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Profile.Sections { /// /// Display artist/title/mapper information, commonly used as the left portion of a profile or score display row (see ). /// - public class BeatmapMetadataContainer : OsuHoverContainer + public abstract class BeatmapMetadataContainer : OsuHoverContainer { private readonly BeatmapInfo beatmap; - public BeatmapMetadataContainer(BeatmapInfo beatmap) + protected BeatmapMetadataContainer(BeatmapInfo beatmap) { this.beatmap = beatmap; AutoSizeAxes = Axes.Both; @@ -40,23 +37,10 @@ namespace osu.Game.Overlays.Profile.Sections Child = new FillFlowContainer { AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - new OsuSpriteText - { - Text = new LocalisedString(( - $"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ", - $"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] ")), - Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold, italics: true) - }, - new OsuSpriteText - { - Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)), - Padding = new MarginPadding { Top = 3 }, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular, italics: true) - }, - }, + Children = CreateText(beatmap), }; } + + protected abstract Drawable[] CreateText(BeatmapInfo beatmap); } } diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs index 98872d6141..fc457676a8 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs @@ -19,13 +19,12 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { public class DrawableMostPlayedBeatmap : OsuHoverContainer { - private readonly OsuSpriteText mapperText; private readonly Box background; private const int cover_width = 100; private const int corner_radius = 10; private readonly SpriteIcon icon; private readonly OsuSpriteText playCountText; - private readonly UnderscoredUserLink mapper; + private readonly LinkFlowContainer mapper; protected override IEnumerable EffectTargets => new[] { background }; @@ -71,54 +70,24 @@ namespace osu.Game.Overlays.Profile.Sections.Historical Padding = new MarginPadding { Left = 15, Right = 20 }, Children = new Drawable[] { - new UnderscoredBeatmapLink(beatmap) + new MostPlayedBeatmapMetadataContainer(beatmap) { Anchor = Anchor.CentreLeft, Origin = Anchor.BottomLeft, Margin = new MarginPadding { Bottom = 2 }, - Text = new[] - { - new OsuSpriteText - { - Text = new LocalisedString(( - $"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ", - $"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] ")), - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold) - }, - new OsuSpriteText - { - Text = "by " + new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)), - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular) - }, - } }, - new FillFlowContainer + mapper = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: 15, weight: FontWeight.Regular)) { - AutoSizeAxes = Axes.Both, Anchor = Anchor.CentreLeft, Origin = Anchor.TopLeft, + AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Margin = new MarginPadding { Top = 2 }, - Children = new Drawable[] - { - mapperText = new OsuSpriteText - { - Text = "mapped by ", - Font = OsuFont.GetFont(size: 15, weight: FontWeight.Regular), - }, - mapper = new UnderscoredUserLink(beatmap.Metadata.Author.Id) - { - Text = new[] - { - new OsuSpriteText - { - Text = beatmap.Metadata.Author.Username, - Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), - } - } - }, - } - }, + }.With(d => + { + d.AddText("mapped by "); + d.AddUserLink(beatmap.Metadata.Author); + }), new FillFlowContainer { Anchor = Anchor.CentreRight, @@ -157,8 +126,32 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { IdleColour = colors.GreySeafoam; HoverColour = colors.GreySeafoamLight; - mapperText.Colour = mapper.Colour = colors.GreySeafoamLighter; + mapper.Colour = colors.GreySeafoamLighter; icon.Colour = playCountText.Colour = colors.Yellow; } + + private class MostPlayedBeatmapMetadataContainer : BeatmapMetadataContainer + { + public MostPlayedBeatmapMetadataContainer(BeatmapInfo beatmap) + : base(beatmap) + { + } + + protected override Drawable[] CreateText(BeatmapInfo beatmap) => new Drawable[] + { + new OsuSpriteText + { + Text = new LocalisedString(( + $"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ", + $"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] ")), + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold) + }, + new OsuSpriteText + { + Text = "by " + new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)), + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular) + }, + }; + } } } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index b77357edd8..e54ce44ca2 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -10,6 +10,8 @@ using osu.Game.Online.Leaderboards; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osu.Game.Scoring; +using osu.Game.Beatmaps; +using osu.Framework.Localisation; namespace osu.Game.Overlays.Profile.Sections.Ranks { @@ -51,7 +53,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks RightFlowContainer.Insert(1, text); - LeftFlowContainer.Add(new BeatmapMetadataContainer(Score.Beatmap)); + LeftFlowContainer.Add(new ProfileScoreBeatmapMetadataContainer(Score.Beatmap)); LeftFlowContainer.Add(new DrawableDate(Score.Date)); foreach (Mod mod in Score.Mods) @@ -64,5 +66,30 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Width = 60, FillMode = FillMode.Fit, }; + + private class ProfileScoreBeatmapMetadataContainer : BeatmapMetadataContainer + { + public ProfileScoreBeatmapMetadataContainer(BeatmapInfo beatmap) + : base(beatmap) + { + } + + protected override Drawable[] CreateText(BeatmapInfo beatmap) => new Drawable[] + { + new OsuSpriteText + { + Text = new LocalisedString(( + $"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ", + $"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] ")), + Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold, italics: true) + }, + new OsuSpriteText + { + Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)), + Padding = new MarginPadding { Top = 3 }, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular, italics: true) + }, + }; + } } } diff --git a/osu.Game/Overlays/Profile/Sections/UnderscoredBeatmapLink.cs b/osu.Game/Overlays/Profile/Sections/UnderscoredBeatmapLink.cs deleted file mode 100644 index ddad99355c..0000000000 --- a/osu.Game/Overlays/Profile/Sections/UnderscoredBeatmapLink.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Beatmaps; - -namespace osu.Game.Overlays.Profile.Sections -{ - public class UnderscoredBeatmapLink : UnderscoredLinkContainer - { - private readonly BeatmapInfo beatmap; - - public UnderscoredBeatmapLink(BeatmapInfo beatmap) - { - this.beatmap = beatmap; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - ClickAction = () => - { - var beatmapId = beatmap.OnlineBeatmapID; - - if (beatmapId.HasValue) - Game?.ShowBeatmap(beatmapId.Value); - }; - } - } -} diff --git a/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs b/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs deleted file mode 100644 index 09a23d2fe3..0000000000 --- a/osu.Game/Overlays/Profile/Sections/UnderscoredLinkContainer.cs +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; -using osu.Game.Graphics.Sprites; -using System; -using System.Collections.Generic; - -namespace osu.Game.Overlays.Profile.Sections -{ - public abstract class UnderscoredLinkContainer : Container - { - private const int duration = 200; - private readonly Container underscore; - private readonly FillFlowContainer textContent; - - protected OsuGame Game; - - protected Action ClickAction; - - public IReadOnlyList Text - { - get => textContent.Children; - set - { - textContent.Clear(); - textContent.AddRange(value); - } - } - - protected UnderscoredLinkContainer() - { - AutoSizeAxes = Axes.Both; - Child = new Container - { - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - underscore = new Container - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Height = 1, - Alpha = 0, - AlwaysPresent = true, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - } - }, - textContent = new FillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - }, - }, - }; - } - - [BackgroundDependencyLoader(true)] - private void load(OsuGame game) - { - Game = game; - } - - protected override bool OnHover(HoverEvent e) - { - underscore.FadeIn(duration, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - underscore.FadeOut(duration, Easing.OutQuint); - base.OnHoverLost(e); - } - - protected override bool OnClick(ClickEvent e) - { - ClickAction?.Invoke(); - return base.OnClick(e); - } - } -} diff --git a/osu.Game/Overlays/Profile/Sections/UnderscoredUserLink.cs b/osu.Game/Overlays/Profile/Sections/UnderscoredUserLink.cs deleted file mode 100644 index 9b3e8ccdf6..0000000000 --- a/osu.Game/Overlays/Profile/Sections/UnderscoredUserLink.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Overlays.Profile.Sections -{ - public class UnderscoredUserLink : UnderscoredLinkContainer - { - private readonly long userId; - - public UnderscoredUserLink(long userId) - { - this.userId = userId; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - ClickAction = () => Game?.ShowUser(userId); - } - } -} From 111541fe7add521e40a6e9d90cd92f16f449d050 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 15 Jul 2019 13:31:57 +0300 Subject: [PATCH 1898/5608] Use limit in requests --- osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs | 6 ++++-- .../Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs | 6 ++++-- .../Online/API/Requests/GetUserRecentActivitiesRequest.cs | 6 ++++-- osu.Game/Online/API/Requests/GetUserScoresRequest.cs | 6 ++++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs index 45d751f00e..57005181ca 100644 --- a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs @@ -11,17 +11,19 @@ namespace osu.Game.Online.API.Requests { private readonly long userId; private readonly int offset; + private readonly int limit; private readonly BeatmapSetType type; - public GetUserBeatmapsRequest(long userId, BeatmapSetType type, int offset = 0) + public GetUserBeatmapsRequest(long userId, BeatmapSetType type, int offset = 0, int limit = 6) { this.userId = userId; this.offset = offset; + this.limit = limit; this.type = type; } // ReSharper disable once ImpureMethodCallOnReadonlyValueField - protected override string Target => $@"users/{userId}/beatmapsets/{type.ToString().Underscore()}?offset={offset}"; + protected override string Target => $@"users/{userId}/beatmapsets/{type.ToString().Underscore()}?offset={offset}&limit={limit}"; } public enum BeatmapSetType diff --git a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs index 40e52bdaf6..fccb27a86c 100644 --- a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs @@ -10,13 +10,15 @@ namespace osu.Game.Online.API.Requests { private readonly long userId; private readonly int offset; + private readonly int limit; - public GetUserMostPlayedBeatmapsRequest(long userId, int offset = 0) + public GetUserMostPlayedBeatmapsRequest(long userId, int offset = 0, int limit = 5) { this.userId = userId; this.offset = offset; + this.limit = limit; } - protected override string Target => $@"users/{userId}/beatmapsets/most_played?offset={offset}"; + protected override string Target => $@"users/{userId}/beatmapsets/most_played?offset={offset}&limit={limit}"; } } diff --git a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs index 9f80180e70..d066636911 100644 --- a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs @@ -10,14 +10,16 @@ namespace osu.Game.Online.API.Requests { private readonly long userId; private readonly int offset; + private readonly int limit; - public GetUserRecentActivitiesRequest(long userId, int offset = 0) + public GetUserRecentActivitiesRequest(long userId, int offset = 0, int limit = 5) { this.userId = userId; this.offset = offset; + this.limit = limit; } - protected override string Target => $"users/{userId}/recent_activity?offset={offset}"; + protected override string Target => $"users/{userId}/recent_activity?offset={offset}&limit={limit}"; } public enum RecentActivityType diff --git a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs index 48a43bbbad..e81686b9fe 100644 --- a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs @@ -11,16 +11,18 @@ namespace osu.Game.Online.API.Requests private readonly long userId; private readonly ScoreType type; private readonly int offset; + private readonly int limit; - public GetUserScoresRequest(long userId, ScoreType type, int offset = 0) + public GetUserScoresRequest(long userId, ScoreType type, int offset = 0, int limit = 5) { this.userId = userId; this.type = type; this.offset = offset; + this.offset = limit; } // ReSharper disable once ImpureMethodCallOnReadonlyValueField - protected override string Target => $@"users/{userId}/scores/{type.ToString().ToLowerInvariant()}?offset={offset}"; + protected override string Target => $@"users/{userId}/scores/{type.ToString().ToLowerInvariant()}?offset={offset}&limit={limit}"; } public enum ScoreType From 9458bca58f954a6b80094b7940013b8dcdd5fc22 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 15 Jul 2019 13:37:25 +0300 Subject: [PATCH 1899/5608] Update usage of requests --- osu.Game/Online/API/Requests/GetUserScoresRequest.cs | 2 +- .../Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs | 2 +- .../Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs | 2 +- .../Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs | 2 +- .../Profile/Sections/Recent/PaginatedRecentActivityContainer.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs index e81686b9fe..0e2f7ec417 100644 --- a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs @@ -18,7 +18,7 @@ namespace osu.Game.Online.API.Requests this.userId = userId; this.type = type; this.offset = offset; - this.offset = limit; + this.limit = limit; } // ReSharper disable once ImpureMethodCallOnReadonlyValueField diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index b6b0e605d7..22f8e6c6b0 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps protected override void ShowMore() { - request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage); + request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage, ItemsPerPage); request.Success += sets => Schedule(() => { MoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0); diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index 6085b0bc05..92b0304a68 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical protected override void ShowMore() { - request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); + request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage, ItemsPerPage); request.Success += beatmaps => Schedule(() => { MoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0); diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index a149cfa12e..5bb362e21c 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks protected override void ShowMore() { - request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage); + request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage, ItemsPerPage); request.Success += scores => Schedule(() => { foreach (var s in scores) diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index b72aec7a44..215c96a423 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent protected override void ShowMore() { - request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); + request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage, ItemsPerPage); request.Success += activities => Schedule(() => { MoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0); From 83ffb1d5420e8f5f28316583a84e5f87a40d3cc7 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 15 Jul 2019 14:15:03 -0700 Subject: [PATCH 1900/5608] Remove unnecessary transforms on top score user section --- .../Overlays/BeatmapSet/Scores/TopScoreUserSection.cs | 4 ++-- osu.Game/Users/Drawables/UpdateableAvatar.cs | 8 +------- osu.Game/Users/Drawables/UpdateableFlag.cs | 8 +------- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index a15d3c5fd1..ffc39e5af2 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }, } }, - avatar = new UpdateableAvatar(hideImmediately: true) + avatar = new UpdateableAvatar { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -99,7 +99,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold) }, - flag = new UpdateableFlag(hideImmediately: true) + flag = new UpdateableFlag { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index a49f2d079b..795b90ba11 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -5,7 +5,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Transforms; namespace osu.Game.Users.Drawables { @@ -38,8 +37,6 @@ namespace osu.Game.Users.Drawables set => base.EdgeEffect = value; } - protected override bool TransformImmediately { get; } - /// /// Whether to show a default guest representation on null user (as opposed to nothing). /// @@ -50,14 +47,11 @@ namespace osu.Game.Users.Drawables /// public readonly BindableBool OpenOnClick = new BindableBool(true); - public UpdateableAvatar(User user = null, bool hideImmediately = false) + public UpdateableAvatar(User user = null) { - TransformImmediately = hideImmediately; User = user; } - protected override TransformSequence ApplyHideTransforms(Drawable drawable) => TransformImmediately ? drawable?.FadeOut() : base.ApplyHideTransforms(drawable); - protected override Drawable CreateDrawable(User user) { if (user == null && !ShowGuestOnNull) diff --git a/osu.Game/Users/Drawables/UpdateableFlag.cs b/osu.Game/Users/Drawables/UpdateableFlag.cs index 78d1a8de20..abc16b2390 100644 --- a/osu.Game/Users/Drawables/UpdateableFlag.cs +++ b/osu.Game/Users/Drawables/UpdateableFlag.cs @@ -3,7 +3,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Transforms; namespace osu.Game.Users.Drawables { @@ -15,21 +14,16 @@ namespace osu.Game.Users.Drawables set => Model = value; } - protected override bool TransformImmediately { get; } - /// /// Whether to show a place holder on null country. /// public bool ShowPlaceholderOnNull = true; - public UpdateableFlag(Country country = null, bool hideImmediately = false) + public UpdateableFlag(Country country = null) { - TransformImmediately = hideImmediately; Country = country; } - protected override TransformSequence ApplyHideTransforms(Drawable drawable) => TransformImmediately ? drawable?.FadeOut() : base.ApplyHideTransforms(drawable); - protected override Drawable CreateDrawable(Country country) { if (country == null && !ShowPlaceholderOnNull) From ed203cb0ffc3d22659e322976da02b2855864c68 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Jul 2019 13:45:59 +0900 Subject: [PATCH 1901/5608] Delay intial hitobject updates --- .../Objects/Drawables/DrawableOsuHitObject.cs | 3 ++ .../Objects/Drawables/DrawableHitObject.cs | 42 ++++++++++++++----- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index f372cb65ce..4533e08a2b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -29,6 +29,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ShakeDuration = 30, RelativeSizeAxes = Axes.Both }); + Alpha = 0; } @@ -38,6 +39,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void ClearInternal(bool disposeChildren = true) => shakeContainer.Clear(disposeChildren); protected override bool RemoveInternal(Drawable drawable) => shakeContainer.Remove(drawable); + protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; + protected sealed override void UpdateState(ArmedState state) { double transformTime = HitObject.StartTime - HitObject.TimePreempt; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 1f6ca4dd73..76233eabf2 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -179,6 +179,38 @@ namespace osu.Game.Rulesets.Objects.Drawables UpdateResult(false); } + private double? lifetimeStart; + + public override double LifetimeStart + { + get => lifetimeStart ?? (HitObject.StartTime - InitialLifetimeOffset); + set + { + base.LifetimeStart = value; + lifetimeStart = value; + } + } + + /// + /// A safe offset prior to the start time of at which this may begin displaying contents. + /// By default, s are assumed to display their contents within 10 seconds prior to the start time of . + /// + /// + /// This is only used as an optimisation to delay the initial update of this and may be tuned more aggressively if required. + /// A more accurate should be set inside for an state. + /// + protected virtual double InitialLifetimeOffset => 10000; + + /// + /// Will called at least once after the of this has been passed. + /// + internal void OnLifetimeEnd() + { + foreach (var nested in NestedHitObjects) + nested.OnLifetimeEnd(); + UpdateResult(false); + } + protected virtual void AddNested(DrawableHitObject h) { h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); @@ -223,16 +255,6 @@ namespace osu.Game.Rulesets.Objects.Drawables OnNewResult?.Invoke(this, Result); } - /// - /// Will called at least once after the of this has been passed. - /// - internal void OnLifetimeEnd() - { - foreach (var nested in NestedHitObjects) - nested.OnLifetimeEnd(); - UpdateResult(false); - } - /// /// Processes this , checking if a scoring result has occurred. /// From e789bb37c8a57aaca7bc67e7b8b3b4dc1bbebb3d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 16 Jul 2019 14:55:41 +0900 Subject: [PATCH 1902/5608] Ignore shift-delete in SearchTextBox --- .../Graphics/UserInterface/SearchTextBox.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index 7023711aaa..cd801a3fc9 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input; using osu.Framework.Input.Events; using osuTK; using osuTK.Input; @@ -15,6 +16,8 @@ namespace osu.Game.Graphics.UserInterface public override bool HandleLeftRightArrows => false; + private InputManager inputManager; + public SearchTextBox() { Height = 35; @@ -33,6 +36,21 @@ namespace osu.Game.Graphics.UserInterface PlaceholderText = "type to search"; } + protected override void LoadComplete() + { + inputManager = GetContainingInputManager(); + base.LoadComplete(); + } + + protected override bool HandleAction(PlatformAction action) + { + // Allow shift-delete to be handled locally + if (inputManager.CurrentState.Keyboard.ShiftPressed && action.ActionType == PlatformActionType.CharNext && action.ActionMethod == PlatformActionMethod.Delete) + return false; + + return base.HandleAction(action); + } + protected override bool OnKeyDown(KeyDownEvent e) { if (!e.ControlPressed && !e.ShiftPressed) From 7634e3cc813c43d317c518dda349878bd94b7013 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 Jul 2019 14:57:11 +0900 Subject: [PATCH 1903/5608] Fix song select iterating over all beatmaps in database unnnecessarily --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index b3c3925a26..260867b1ea 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -253,7 +253,7 @@ namespace osu.Game.Screens.Select Schedule(() => { // if we have no beatmaps but osu-stable is found, let's prompt the user to import. - if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable) + if (!beatmaps.GetAllUsableBeatmapSetsEnumerable().Any() && beatmaps.StableInstallationAvailable) dialogOverlay.Push(new ImportFromStablePopup(() => { Task.Run(beatmaps.ImportFromStableAsync).ContinueWith(_ => scores.ImportFromStableAsync(), TaskContinuationOptions.OnlyOnRanToCompletion); From b95a5983385a349174404d3f71957ec22462abc7 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 16 Jul 2019 15:12:01 +0900 Subject: [PATCH 1904/5608] don't check for shift --- osu.Game/Graphics/UserInterface/SearchTextBox.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index cd801a3fc9..c1020e6340 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -16,8 +16,6 @@ namespace osu.Game.Graphics.UserInterface public override bool HandleLeftRightArrows => false; - private InputManager inputManager; - public SearchTextBox() { Height = 35; @@ -36,16 +34,10 @@ namespace osu.Game.Graphics.UserInterface PlaceholderText = "type to search"; } - protected override void LoadComplete() - { - inputManager = GetContainingInputManager(); - base.LoadComplete(); - } - protected override bool HandleAction(PlatformAction action) { - // Allow shift-delete to be handled locally - if (inputManager.CurrentState.Keyboard.ShiftPressed && action.ActionType == PlatformActionType.CharNext && action.ActionMethod == PlatformActionMethod.Delete) + // Allow delete to be handled locally + if (action.ActionType == PlatformActionType.CharNext && action.ActionMethod == PlatformActionMethod.Delete) return false; return base.HandleAction(action); From b0415dc30abb7aec345c535988097be14446271b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Jul 2019 17:33:14 +0900 Subject: [PATCH 1905/5608] Remove cursortrail drawnode allocs --- .../UI/Cursor/CursorTrail.cs | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index b986076593..6a70728c50 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -162,7 +162,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly TrailPart[] parts = new TrailPart[max_sprites]; private Vector2 size; - private readonly VertexBatch vertexBatch = new QuadBatch(max_sprites, 1); + private readonly CustomBatch vertexBatch = new CustomBatch(max_sprites, 1); public TrailDrawNode(CursorTrail source) : base(source) @@ -197,20 +197,14 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor for (int i = 0; i < parts.Length; ++i) { Vector2 pos = parts[i].Position; - float localTime = parts[i].Time; + vertexBatch.DrawTime = parts[i].Time; DrawQuad( texture, new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y), DrawColourInfo.Colour, null, - v => vertexBatch.Add(new TexturedTrailVertex - { - Position = v.Position, - TexturePosition = v.TexturePosition, - Time = localTime + 1, - Colour = v.Colour, - })); + vertexBatch.AddAction); } shader.Unbind(); @@ -222,6 +216,27 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor vertexBatch.Dispose(); } + + private class CustomBatch : QuadBatch + { + public new readonly Action AddAction; + + public float DrawTime; + + public CustomBatch(int size, int maxBuffers) + : base(size, maxBuffers) + { + AddAction = add; + } + + private void add(TexturedVertex2D vertex) => Add(new TexturedTrailVertex + { + Position = vertex.Position, + TexturePosition = vertex.TexturePosition, + Time = DrawTime + 1, + Colour = vertex.Colour, + }); + } } [StructLayout(LayoutKind.Sequential)] From 62b867018d555d6c034ce00991768bb35bcc2338 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Jul 2019 17:50:03 +0900 Subject: [PATCH 1906/5608] Refactor a bit --- .../UI/Cursor/CursorTrail.cs | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 6a70728c50..05eb0ffdbf 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -162,7 +162,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly TrailPart[] parts = new TrailPart[max_sprites]; private Vector2 size; - private readonly CustomBatch vertexBatch = new CustomBatch(max_sprites, 1); + private readonly TrailBatch vertexBatch = new TrailBatch(max_sprites, 1); public TrailDrawNode(CursorTrail source) : base(source) @@ -196,9 +196,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor for (int i = 0; i < parts.Length; ++i) { - Vector2 pos = parts[i].Position; vertexBatch.DrawTime = parts[i].Time; + Vector2 pos = parts[i].Position; + DrawQuad( texture, new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y), @@ -217,25 +218,23 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor vertexBatch.Dispose(); } - private class CustomBatch : QuadBatch + // Todo: This shouldn't exist, but is currently used to reduce allocations by caching variable-capturing closures. + private class TrailBatch : QuadBatch { public new readonly Action AddAction; - public float DrawTime; - public CustomBatch(int size, int maxBuffers) + public TrailBatch(int size, int maxBuffers) : base(size, maxBuffers) { - AddAction = add; + AddAction = v => Add(new TexturedTrailVertex + { + Position = v.Position, + TexturePosition = v.TexturePosition, + Time = DrawTime + 1, + Colour = v.Colour, + }); } - - private void add(TexturedVertex2D vertex) => Add(new TexturedTrailVertex - { - Position = vertex.Position, - TexturePosition = vertex.TexturePosition, - Time = DrawTime + 1, - Colour = vertex.Colour, - }); } } From 7c5a227fc53c4e750e19ff630719e15101d22e4b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Jul 2019 14:46:25 +0900 Subject: [PATCH 1907/5608] Fix crashes when presenting replays --- osu.Game/Screens/Select/FooterButtonMods.cs | 16 ++++++++++------ osu.Game/Screens/Select/SongSelect.cs | 11 ++++++++--- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index c96c5022c0..fce4d1b2e2 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -9,18 +9,25 @@ using osu.Game.Rulesets.Mods; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osuTK; using osuTK.Input; namespace osu.Game.Screens.Select { - public class FooterButtonMods : FooterButton + public class FooterButtonMods : FooterButton, IHasCurrentValue> { - public FooterButtonMods(Bindable> mods) + public Bindable> Current { - FooterModDisplay modDisplay; + get => modDisplay.Current; + set => modDisplay.Current = value; + } + private readonly FooterModDisplay modDisplay; + + public FooterButtonMods() + { Add(new Container { Anchor = Anchor.CentreLeft, @@ -33,9 +40,6 @@ namespace osu.Game.Screens.Select AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Left = 70 } }); - - if (mods != null) - modDisplay.Current = mods; } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 260867b1ea..20dbcf2693 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -221,11 +221,9 @@ namespace osu.Game.Screens.Select [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { - mods.BindTo(Mods); - if (Footer != null) { - Footer.AddButton(new FooterButtonMods(mods), ModSelect); + Footer.AddButton(new FooterButtonMods { Current = mods }, ModSelect); Footer.AddButton(new FooterButtonRandom { Action = triggerRandom }); Footer.AddButton(new FooterButtonOptions(), BeatmapOptions); @@ -263,6 +261,13 @@ namespace osu.Game.Screens.Select } } + protected override void LoadComplete() + { + base.LoadComplete(); + + mods.BindTo(Mods); + } + private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) From a9286fee07fc2c814062586a49ee116fb719334b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Jul 2019 18:19:13 +0900 Subject: [PATCH 1908/5608] Recycle slider paths when the parenting slider dies --- .../Objects/Drawables/DrawableSlider.cs | 6 ++++++ .../Objects/Drawables/Pieces/SliderBody.cs | 19 ++++++++++++++++++- .../Objects/Drawables/DrawableHitObject.cs | 8 ++++---- osu.Game/Rulesets/UI/HitObjectContainer.cs | 10 ++++++++-- 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 05cb42d853..4d67c9ae34 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -156,6 +156,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } + public override void OnKilled() + { + base.OnKilled(); + Body.RecyclePath(); + } + protected override void SkinChanged(ISkinSource skin, bool allowFallback) { base.SkinChanged(skin, allowFallback); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 33b3667c4f..97c7c9cec5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -13,7 +13,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public const float DEFAULT_BORDER_SIZE = 1; - private readonly SliderPath path; + private SliderPath path; + protected Path Path => path; public float PathRadius @@ -77,6 +78,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces InternalChild = path = new SliderPath(); } + /// + /// Initialises a new , releasing all resources retained by the old one. + /// + public void RecyclePath() + { + InternalChild = path = new SliderPath + { + Position = path.Position, + PathRadius = path.PathRadius, + AccentColour = path.AccentColour, + BorderColour = path.BorderColour, + BorderSize = path.BorderSize, + Vertices = path.Vertices + }; + } + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => path.ReceivePositionalInputAt(screenSpacePos); /// diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 76233eabf2..e61fac679e 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -7,7 +7,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; -using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Game.Audio; using osu.Game.Graphics; @@ -202,12 +201,13 @@ namespace osu.Game.Rulesets.Objects.Drawables protected virtual double InitialLifetimeOffset => 10000; /// - /// Will called at least once after the of this has been passed. + /// Will be called at least once after this has become not alive. /// - internal void OnLifetimeEnd() + public virtual void OnKilled() { foreach (var nested in NestedHitObjects) - nested.OnLifetimeEnd(); + nested.OnKilled(); + UpdateResult(false); } diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index 2f3a384e95..aa942e70df 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -34,8 +34,14 @@ namespace osu.Game.Rulesets.UI protected override void OnChildLifetimeBoundaryCrossed(LifetimeBoundaryCrossedEvent e) { - if (e.Kind == LifetimeBoundaryKind.End && e.Direction == LifetimeBoundaryCrossingDirection.Forward && e.Child is DrawableHitObject hitObject) - hitObject.OnLifetimeEnd(); + if (!(e.Child is DrawableHitObject hitObject)) + return; + + if (e.Kind == LifetimeBoundaryKind.End && e.Direction == LifetimeBoundaryCrossingDirection.Forward + || e.Kind == LifetimeBoundaryKind.Start && e.Direction == LifetimeBoundaryCrossingDirection.Backward) + { + hitObject.OnKilled(); + } } } } From 66036508b607348d1f88daf0845bc5aeffbc2c71 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 Jul 2019 17:39:04 +0900 Subject: [PATCH 1909/5608] Fix potential crash when displaying leaderbaords --- osu.Game/Online/Leaderboards/Leaderboard.cs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 35f7ba1c1b..18c827707a 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -51,7 +51,6 @@ namespace osu.Game.Online.Leaderboards loading.Hide(); - // schedule because we may not be loaded yet (LoadComponentAsync complains). showScoresDelegate?.Cancel(); showScoresCancellationSource?.Cancel(); @@ -61,28 +60,22 @@ namespace osu.Game.Online.Leaderboards // ensure placeholder is hidden when displaying scores PlaceholderState = PlaceholderState.Successful; - scrollFlow = CreateScoreFlow(); - scrollFlow.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)); + var sf = CreateScoreFlow(); + sf.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)); - if (!IsLoaded) - showScoresDelegate = Schedule(showScores); - else - showScores(); - - void showScores() => LoadComponentAsync(scrollFlow, _ => + // schedule because we may not be loaded yet (LoadComponentAsync complains). + showScoresDelegate = Schedule(() => LoadComponentAsync(sf, _ => { - scrollContainer.Add(scrollFlow); + scrollContainer.Add(scrollFlow = sf); int i = 0; foreach (var s in scrollFlow.Children) - { using (s.BeginDelayedSequence(i++ * 50, true)) s.Show(); - } scrollContainer.ScrollTo(0f, false); - }, (showScoresCancellationSource = new CancellationTokenSource()).Token); + }, (showScoresCancellationSource = new CancellationTokenSource()).Token)); } } From cca472d412dd7d3f9983c9f06fe485eb49f22b99 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Jul 2019 19:19:45 +0900 Subject: [PATCH 1910/5608] Fix direct ruleset selector binding in ctor --- osu.Game/Overlays/Direct/DirectRulesetSelector.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/DirectRulesetSelector.cs b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs index fdab9f1b90..2c5ea85c5a 100644 --- a/osu.Game/Overlays/Direct/DirectRulesetSelector.cs +++ b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs @@ -26,8 +26,13 @@ namespace osu.Game.Overlays.Direct TabContainer.Masking = false; TabContainer.Spacing = new Vector2(10, 0); AutoSizeAxes = Axes.Both; + } - Current.DisabledChanged += value => SelectedTab.FadeColour(value ? Color4.DarkGray : Color4.White, 200, Easing.OutQuint); + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindDisabledChanged(value => SelectedTab.FadeColour(value ? Color4.DarkGray : Color4.White, 200, Easing.OutQuint)); } protected override TabItem CreateTabItem(RulesetInfo value) => new DirectRulesetTabItem(value); From 9f6ff63634b19d99010b282a66a8df760d113da9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Jul 2019 19:25:41 +0900 Subject: [PATCH 1911/5608] Fix judgement disposals causing huge LOH pressure --- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 9 ++++++++- osu.Game/Skinning/LocalSkinOverrideContainer.cs | 6 +++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 0cbe0cca85..9037faf606 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.UI; using System.Linq; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.UI.Cursor; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.UI { @@ -39,7 +40,13 @@ namespace osu.Game.Rulesets.Osu.UI RelativeSizeAxes = Axes.Both, Depth = 1, }, - HitObjectContainer, + // Todo: This should not exist, but currently helps to reduce LOH allocations due to unbinding skin source events on judgement disposal + // Todo: Remove when hitobjects are properly pooled + new LocalSkinOverrideContainer(null) + { + RelativeSizeAxes = Axes.Both, + Child = HitObjectContainer, + }, approachCircles = new ApproachCircleProxyContainer { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Skinning/LocalSkinOverrideContainer.cs b/osu.Game/Skinning/LocalSkinOverrideContainer.cs index 37f4cc28a2..7882e0f31b 100644 --- a/osu.Game/Skinning/LocalSkinOverrideContainer.cs +++ b/osu.Game/Skinning/LocalSkinOverrideContainer.cs @@ -34,7 +34,7 @@ namespace osu.Game.Skinning public Drawable GetDrawableComponent(string componentName) { Drawable sourceDrawable; - if (beatmapSkins.Value && (sourceDrawable = skin.GetDrawableComponent(componentName)) != null) + if (beatmapSkins.Value && (sourceDrawable = skin?.GetDrawableComponent(componentName)) != null) return sourceDrawable; return fallbackSource?.GetDrawableComponent(componentName); @@ -43,7 +43,7 @@ namespace osu.Game.Skinning public Texture GetTexture(string componentName) { Texture sourceTexture; - if (beatmapSkins.Value && (sourceTexture = skin.GetTexture(componentName)) != null) + if (beatmapSkins.Value && (sourceTexture = skin?.GetTexture(componentName)) != null) return sourceTexture; return fallbackSource.GetTexture(componentName); @@ -52,7 +52,7 @@ namespace osu.Game.Skinning public SampleChannel GetSample(string sampleName) { SampleChannel sourceChannel; - if (beatmapHitsounds.Value && (sourceChannel = skin.GetSample(sampleName)) != null) + if (beatmapHitsounds.Value && (sourceChannel = skin?.GetSample(sampleName)) != null) return sourceChannel; return fallbackSource?.GetSample(sampleName); From 883c090248b49ec98dd14746304bc2374ad7a4cc Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Wed, 17 Jul 2019 20:02:20 +0900 Subject: [PATCH 1912/5608] Fix disabled state potentially not being set --- osu.Game/Overlays/Direct/DirectRulesetSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/DirectRulesetSelector.cs b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs index 2c5ea85c5a..106aaa616b 100644 --- a/osu.Game/Overlays/Direct/DirectRulesetSelector.cs +++ b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Direct { base.LoadComplete(); - Current.BindDisabledChanged(value => SelectedTab.FadeColour(value ? Color4.DarkGray : Color4.White, 200, Easing.OutQuint)); + Current.BindDisabledChanged(value => SelectedTab.FadeColour(value ? Color4.DarkGray : Color4.White, 200, Easing.OutQuint), true); } protected override TabItem CreateTabItem(RulesetInfo value) => new DirectRulesetTabItem(value); From 42b1e1772fe591452e3e0778771e42dfbc0ef105 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 Jul 2019 22:07:11 +0900 Subject: [PATCH 1913/5608] 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 98f9bf1a42..31c1c29865 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 436ba90a88..f54a51d5db 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index c24349bcb5..eb6d3ead06 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From cc3492f8f29e7e192b5af10dca9479efb288b299 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jul 2019 00:01:38 +0900 Subject: [PATCH 1914/5608] 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 31c1c29865..9aa5e631ad 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f54a51d5db..86a68d2159 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index eb6d3ead06..712effcc39 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From f1423b8cb5717361443594e4311f00a1a6b34c90 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 Jul 2019 22:38:17 +0900 Subject: [PATCH 1915/5608] Add more brackets --- osu.Game/Rulesets/UI/HitObjectContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index aa942e70df..9485189433 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -37,8 +37,8 @@ namespace osu.Game.Rulesets.UI if (!(e.Child is DrawableHitObject hitObject)) return; - if (e.Kind == LifetimeBoundaryKind.End && e.Direction == LifetimeBoundaryCrossingDirection.Forward - || e.Kind == LifetimeBoundaryKind.Start && e.Direction == LifetimeBoundaryCrossingDirection.Backward) + if ((e.Kind == LifetimeBoundaryKind.End && e.Direction == LifetimeBoundaryCrossingDirection.Forward) + || (e.Kind == LifetimeBoundaryKind.Start && e.Direction == LifetimeBoundaryCrossingDirection.Backward)) { hitObject.OnKilled(); } From a6ddcd78d46a8fc38fa9ae8d37bfe724d58e7610 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jul 2019 01:08:12 +0900 Subject: [PATCH 1916/5608] Fix results screen not showing first tab correctly --- osu.Game/Screens/Ranking/Results.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index f53fb75e1a..cac26b3dbf 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -256,9 +256,12 @@ namespace osu.Game.Screens.Ranking } }; - foreach (var t in CreateResultPages()) - modeChangeButtons.AddItem(t); - modeChangeButtons.Current.Value = modeChangeButtons.Items.FirstOrDefault(); + var pages = CreateResultPages(); + + foreach (var p in pages) + modeChangeButtons.AddItem(p); + + modeChangeButtons.Current.Value = pages.FirstOrDefault(); modeChangeButtons.Current.BindValueChanged(page => { From 1ce2b2eaceabb32ef5c3f1953e6a4cce30387b9e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 18 Jul 2019 13:18:06 +0900 Subject: [PATCH 1917/5608] Set title as default grouping/sorting modes --- osu.Game/Screens/Select/FilterControl.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index bd0b0dd5cd..57fe15fd99 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -120,7 +120,8 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.X, Height = 24, Width = 0.5f, - AutoSort = true + AutoSort = true, + Current = { Value = GroupMode.Title } }, //spriteText = new OsuSpriteText //{ @@ -139,6 +140,7 @@ namespace osu.Game.Screens.Select Width = 0.5f, Height = 24, AutoSort = true, + Current = { Value = SortMode.Title } } } }, From f175f597e76bf717ac528ee25c98dd7cb12bc0ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jul 2019 14:05:57 +0900 Subject: [PATCH 1918/5608] Update follower count API source --- osu.Game/Overlays/Profile/Header/Components/AddFriendButton.cs | 2 +- osu.Game/Users/User.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/AddFriendButton.cs b/osu.Game/Overlays/Profile/Header/Components/AddFriendButton.cs index 2e4fd6fe3d..6e1b6e2c7d 100644 --- a/osu.Game/Overlays/Profile/Header/Components/AddFriendButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/AddFriendButton.cs @@ -53,6 +53,6 @@ namespace osu.Game.Overlays.Profile.Header.Components User.BindValueChanged(user => updateFollowers(user.NewValue), true); } - private void updateFollowers(User user) => followerText.Text = user?.FollowerCount?.Length > 0 ? user.FollowerCount[0].ToString("#,##0") : "0"; + private void updateFollowers(User user) => followerText.Text = user?.FollowerCount.ToString("#,##0"); } } diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index df41e194b0..34bd4bbaae 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -118,7 +118,7 @@ namespace osu.Game.Users public int PostCount; [JsonProperty(@"follower_count")] - public int[] FollowerCount; + public int FollowerCount; [JsonProperty] private string[] playstyle From ca72409dc269fe0ffd0a1045f17cdcec98e48ab2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 18 Jul 2019 20:16:10 +0900 Subject: [PATCH 1919/5608] More closely match osu-web styling --- .../Historical/DrawableMostPlayedBeatmap.cs | 147 +++++++++++------- 1 file changed, 87 insertions(+), 60 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs index fc457676a8..a6c41cde72 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs @@ -14,34 +14,45 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; using System.Collections.Generic; +using osu.Framework.Graphics.Cursor; namespace osu.Game.Overlays.Profile.Sections.Historical { public class DrawableMostPlayedBeatmap : OsuHoverContainer { - private readonly Box background; private const int cover_width = 100; private const int corner_radius = 10; - private readonly SpriteIcon icon; - private readonly OsuSpriteText playCountText; - private readonly LinkFlowContainer mapper; + + private readonly BeatmapInfo beatmap; + private readonly int playCount; + + private Box background; protected override IEnumerable EffectTargets => new[] { background }; public DrawableMostPlayedBeatmap(BeatmapInfo beatmap, int playCount) { + this.beatmap = beatmap; + this.playCount = playCount; Enabled.Value = true; //manually enabled, because we have no action RelativeSizeAxes = Axes.X; - Height = 60; + AutoSizeAxes = Axes.Y; + Masking = true; CornerRadius = corner_radius; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + IdleColour = colours.GreySeafoam; + HoverColour = colours.GreySeafoamLight; + Children = new Drawable[] { new UpdateableBeatmapSetCover { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, RelativeSizeAxes = Axes.Y, Width = cover_width, BeatmapSet = beatmap.BeatmapSet, @@ -49,69 +60,53 @@ namespace osu.Game.Overlays.Profile.Sections.Historical }, new Container { - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Left = cover_width - corner_radius }, Children = new Drawable[] { new Container { - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Masking = true, CornerRadius = corner_radius, Children = new Drawable[] { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, + background = new Box { RelativeSizeAxes = Axes.Both }, new Container { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = 15, Right = 20 }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding(10), Children = new Drawable[] { - new MostPlayedBeatmapMetadataContainer(beatmap) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.BottomLeft, - Margin = new MarginPadding { Bottom = 2 }, - }, - mapper = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: 15, weight: FontWeight.Regular)) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.TopLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Margin = new MarginPadding { Top = 2 }, - }.With(d => - { - d.AddText("mapped by "); - d.AddUserLink(beatmap.Metadata.Author); - }), new FillFlowContainer { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, + Direction = FillDirection.Vertical, Children = new Drawable[] { - icon = new SpriteIcon + new MostPlayedBeatmapMetadataContainer(beatmap), + new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular)) { - Icon = FontAwesome.Solid.CaretRight, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Size = new Vector2(20), - }, - playCountText = new OsuSpriteText + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Colour = colours.GreySeafoamLighter + }.With(d => { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Text = playCount.ToString(), - Font = OsuFont.GetFont(size: 30, weight: FontWeight.Regular, fixedWidth: true), - }, + d.AddText("mapped by "); + d.AddUserLink(beatmap.Metadata.Author); + }), } - } + }, + new PlayCountText(playCount) + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight + }, } }, } @@ -121,15 +116,6 @@ namespace osu.Game.Overlays.Profile.Sections.Historical }; } - [BackgroundDependencyLoader] - private void load(OsuColour colors) - { - IdleColour = colors.GreySeafoam; - HoverColour = colors.GreySeafoamLight; - mapper.Colour = colors.GreySeafoamLighter; - icon.Colour = playCountText.Colour = colors.Yellow; - } - private class MostPlayedBeatmapMetadataContainer : BeatmapMetadataContainer { public MostPlayedBeatmapMetadataContainer(BeatmapInfo beatmap) @@ -144,14 +130,55 @@ namespace osu.Game.Overlays.Profile.Sections.Historical Text = new LocalisedString(( $"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ", $"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] ")), - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold) + Font = OsuFont.GetFont(weight: FontWeight.Bold) }, new OsuSpriteText { Text = "by " + new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)), - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular) + Font = OsuFont.GetFont(weight: FontWeight.Regular) }, }; } + + private class PlayCountText : CompositeDrawable, IHasTooltip + { + public string TooltipText => "times played"; + + public PlayCountText(int playCount) + { + AutoSizeAxes = Axes.Both; + + InternalChild = new FillFlowContainer + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(5, 0), + Children = new Drawable[] + { + new SpriteIcon + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(12), + Icon = FontAwesome.Solid.Play, + }, + new OsuSpriteText + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Text = playCount.ToString(), + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular), + }, + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.Yellow; + } + } } } From f87e9b801716136e0ad43d124bc1b312b5b6212f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 18 Jul 2019 20:17:19 +0900 Subject: [PATCH 1920/5608] Remove unnecessary tooltip text --- osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs index 597171cc7f..13b547eed3 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs @@ -19,8 +19,8 @@ namespace osu.Game.Overlays.Profile.Sections protected BeatmapMetadataContainer(BeatmapInfo beatmap) { this.beatmap = beatmap; + AutoSizeAxes = Axes.Both; - TooltipText = $"{beatmap.Metadata.Artist} - {beatmap.Metadata.Title}"; } [BackgroundDependencyLoader(true)] From fa978a47b004085da22d0ebacb31e7df7c8d18d7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 18 Jul 2019 15:08:50 +0300 Subject: [PATCH 1921/5608] Fix loading animation is no longer present --- .../BeatmapSet/Scores/ScoresContainer.cs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 22d7ea9c97..0adaaa20b2 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -19,7 +19,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public class ScoresContainer : CompositeDrawable { private const int spacing = 15; - private const int fade_duration = 200; private readonly Box background; private readonly ScoreTable scoreTable; @@ -53,8 +52,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Schedule(() => { - loading = false; - topScoresContainer.Clear(); if (value?.Scores.Any() != true) @@ -128,13 +125,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores background.Colour = colours.Gray2; } - private bool loading - { - set => loadingAnimation.FadeTo(value ? 1 : 0, fade_duration); - } - private void getScores(BeatmapInfo beatmap) { + loadingAnimation.Show(); + getScoresRequest?.Cancel(); getScoresRequest = null; @@ -142,14 +136,17 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (beatmap?.OnlineBeatmapID.HasValue != true) { - loading = false; + loadingAnimation.Hide(); return; } getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); - getScoresRequest.Success += scores => Scores = scores; + getScoresRequest.Success += scores => + { + loadingAnimation.Hide(); + Scores = scores; + }; api.Queue(getScoresRequest); - loading = true; } } } From 00f1d1b53cc47c9be1743bf1b69d28b0c89ee659 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 19 Jul 2019 00:53:00 +0900 Subject: [PATCH 1922/5608] Reduce Triangle drawnode overhead by ~90% This was never batching, ever. Pointless memory overhead. --- osu.Game/Graphics/Backgrounds/Triangles.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 29113e0e2f..3502531d13 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -137,11 +137,13 @@ namespace osu.Game.Graphics.Backgrounds } } + protected int AimCount; + private void addTriangles(bool randomY) { - int aimTriangleCount = (int)(DrawWidth * DrawHeight * 0.002f / (triangleScale * triangleScale) * SpawnRatio); + AimCount = (int)(DrawWidth * DrawHeight * 0.002f / (triangleScale * triangleScale) * SpawnRatio); - for (int i = 0; i < aimTriangleCount - parts.Count; i++) + for (int i = 0; i < AimCount - parts.Count; i++) parts.Add(createTriangle(randomY)); } @@ -190,11 +192,12 @@ namespace osu.Game.Graphics.Backgrounds private readonly List parts = new List(); private Vector2 size; - private readonly LinearBatch vertexBatch = new LinearBatch(100 * 3, 10, PrimitiveType.Triangles); + private readonly LinearBatch vertexBatch; public TrianglesDrawNode(Triangles source) : base(source) { + vertexBatch = new LinearBatch(source.AimCount * 3, 2, PrimitiveType.Triangles); } public override void ApplyState() From a23bb3a6b32f48355dbb6f0b837d1835e4b0a14b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 19 Jul 2019 01:14:55 +0900 Subject: [PATCH 1923/5608] Account for headless nulls (but how?) --- osu.Game/Graphics/Backgrounds/Triangles.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 3502531d13..20e92cd2c6 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -249,7 +249,7 @@ namespace osu.Game.Graphics.Backgrounds { base.Dispose(isDisposing); - vertexBatch.Dispose(); + vertexBatch?.Dispose(); } } From 95f36c36c4d00dc53c8b27bd2bb44c167d21b739 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 19 Jul 2019 01:52:53 +0900 Subject: [PATCH 1924/5608] Late-initialize vertex batch for safety --- osu.Game/Graphics/Backgrounds/Triangles.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 20e92cd2c6..4f50abc985 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -192,12 +192,11 @@ namespace osu.Game.Graphics.Backgrounds private readonly List parts = new List(); private Vector2 size; - private readonly LinearBatch vertexBatch; + private LinearBatch vertexBatch; public TrianglesDrawNode(Triangles source) : base(source) { - vertexBatch = new LinearBatch(source.AimCount * 3, 2, PrimitiveType.Triangles); } public override void ApplyState() @@ -214,6 +213,9 @@ namespace osu.Game.Graphics.Backgrounds public override void Draw(Action vertexAction) { + if (vertexBatch == null && Source.AimCount > 0) + vertexBatch = new LinearBatch(Source.AimCount * 3, 2, PrimitiveType.Triangles); + base.Draw(vertexAction); shader.Bind(); From 024f136d820db7791324d988fc4e9d2a20e47676 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 19 Jul 2019 14:24:11 +0900 Subject: [PATCH 1925/5608] Reduce buffer count by one --- osu.Game/Graphics/Backgrounds/Triangles.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 4f50abc985..62151d066b 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -213,11 +213,14 @@ namespace osu.Game.Graphics.Backgrounds public override void Draw(Action vertexAction) { - if (vertexBatch == null && Source.AimCount > 0) - vertexBatch = new LinearBatch(Source.AimCount * 3, 2, PrimitiveType.Triangles); - base.Draw(vertexAction); + if (vertexBatch == null || vertexBatch.Size != Source.AimCount * 6) + { + vertexBatch?.Dispose(); + vertexBatch = new LinearBatch(Source.AimCount * 6, 1, PrimitiveType.Triangles); + } + shader.Bind(); Vector2 localInflationAmount = edge_smoothness * DrawInfo.MatrixInverse.ExtractScale().Xy; From 99ab77b926a5fb3e569e2955eb577e1a2211adfd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 19 Jul 2019 15:33:09 +0900 Subject: [PATCH 1926/5608] Add PaginatedWebRequest to handle request pagination --- .../API/Requests/GetUserBeatmapsRequest.cs | 11 +++---- .../GetUserMostPlayedBeatmapsRequest.cs | 9 ++---- .../GetUserRecentActivitiesRequest.cs | 9 ++---- .../API/Requests/GetUserScoresRequest.cs | 10 ++----- .../API/Requests/PaginatedAPIRequest.cs | 30 +++++++++++++++++++ 5 files changed, 43 insertions(+), 26 deletions(-) create mode 100644 osu.Game/Online/API/Requests/PaginatedAPIRequest.cs diff --git a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs index 57005181ca..978d0915fb 100644 --- a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs @@ -7,23 +7,20 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { - public class GetUserBeatmapsRequest : APIRequest> + public class GetUserBeatmapsRequest : PaginatedAPIRequest> { private readonly long userId; - private readonly int offset; - private readonly int limit; + private readonly BeatmapSetType type; public GetUserBeatmapsRequest(long userId, BeatmapSetType type, int offset = 0, int limit = 6) + : base(offset, limit) { this.userId = userId; - this.offset = offset; - this.limit = limit; this.type = type; } - // ReSharper disable once ImpureMethodCallOnReadonlyValueField - protected override string Target => $@"users/{userId}/beatmapsets/{type.ToString().Underscore()}?offset={offset}&limit={limit}"; + protected override string Target => $@"users/{userId}/beatmapsets/{type.ToString().Underscore()}"; } public enum BeatmapSetType diff --git a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs index fccb27a86c..a363d127d8 100644 --- a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs @@ -6,19 +6,16 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { - public class GetUserMostPlayedBeatmapsRequest : APIRequest> + public class GetUserMostPlayedBeatmapsRequest : PaginatedAPIRequest> { private readonly long userId; - private readonly int offset; - private readonly int limit; public GetUserMostPlayedBeatmapsRequest(long userId, int offset = 0, int limit = 5) + : base(offset, limit) { this.userId = userId; - this.offset = offset; - this.limit = limit; } - protected override string Target => $@"users/{userId}/beatmapsets/most_played?offset={offset}&limit={limit}"; + protected override string Target => $@"users/{userId}/beatmapsets/most_played"; } } diff --git a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs index d066636911..5675e877b5 100644 --- a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs @@ -6,20 +6,17 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { - public class GetUserRecentActivitiesRequest : APIRequest> + public class GetUserRecentActivitiesRequest : PaginatedAPIRequest> { private readonly long userId; - private readonly int offset; - private readonly int limit; public GetUserRecentActivitiesRequest(long userId, int offset = 0, int limit = 5) + : base(offset, limit) { this.userId = userId; - this.offset = offset; - this.limit = limit; } - protected override string Target => $"users/{userId}/recent_activity?offset={offset}&limit={limit}"; + protected override string Target => $"users/{userId}/recent_activity"; } public enum RecentActivityType diff --git a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs index 0e2f7ec417..03a11b68ac 100644 --- a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs @@ -6,23 +6,19 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { - public class GetUserScoresRequest : APIRequest> + public class GetUserScoresRequest : PaginatedAPIRequest> { private readonly long userId; private readonly ScoreType type; - private readonly int offset; - private readonly int limit; public GetUserScoresRequest(long userId, ScoreType type, int offset = 0, int limit = 5) + : base(offset, limit) { this.userId = userId; this.type = type; - this.offset = offset; - this.limit = limit; } - // ReSharper disable once ImpureMethodCallOnReadonlyValueField - protected override string Target => $@"users/{userId}/scores/{type.ToString().ToLowerInvariant()}?offset={offset}&limit={limit}"; + protected override string Target => $@"users/{userId}/scores/{type.ToString().ToLowerInvariant()}"; } public enum ScoreType diff --git a/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs new file mode 100644 index 0000000000..45360612bd --- /dev/null +++ b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Globalization; +using osu.Framework.IO.Network; + +namespace osu.Game.Online.API.Requests +{ + public abstract class PaginatedAPIRequest : APIRequest + { + private readonly int offset; + private readonly int limit; + + protected PaginatedAPIRequest(int offset, int limit) + { + this.offset = offset; + this.limit = limit; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + req.AddParameter("offset", offset.ToString(CultureInfo.InvariantCulture)); + req.AddParameter("limit", limit.ToString(CultureInfo.InvariantCulture)); + + return req; + } + } +} From 066bee35350fa0f094a1b08983d426ff5b178f18 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 19 Jul 2019 16:02:33 +0900 Subject: [PATCH 1927/5608] Simplify offset calculation --- .../Online/API/Requests/GetUserBeatmapsRequest.cs | 4 ++-- .../Requests/GetUserMostPlayedBeatmapsRequest.cs | 4 ++-- .../API/Requests/GetUserRecentActivitiesRequest.cs | 4 ++-- .../Online/API/Requests/GetUserScoresRequest.cs | 4 ++-- .../Online/API/Requests/PaginatedAPIRequest.cs | 14 +++++++------- .../Sections/Beatmaps/PaginatedBeatmapContainer.cs | 2 +- .../PaginatedMostPlayedBeatmapContainer.cs | 2 +- .../Sections/Ranks/PaginatedScoreContainer.cs | 2 +- .../Recent/PaginatedRecentActivityContainer.cs | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs index 978d0915fb..f3384163b8 100644 --- a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs @@ -13,8 +13,8 @@ namespace osu.Game.Online.API.Requests private readonly BeatmapSetType type; - public GetUserBeatmapsRequest(long userId, BeatmapSetType type, int offset = 0, int limit = 6) - : base(offset, limit) + public GetUserBeatmapsRequest(long userId, BeatmapSetType type, int page = 0, int itemsPerPage = 6) + : base(page, itemsPerPage) { this.userId = userId; this.type = type; diff --git a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs index a363d127d8..9f094e51c4 100644 --- a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs @@ -10,8 +10,8 @@ namespace osu.Game.Online.API.Requests { private readonly long userId; - public GetUserMostPlayedBeatmapsRequest(long userId, int offset = 0, int limit = 5) - : base(offset, limit) + public GetUserMostPlayedBeatmapsRequest(long userId, int page = 0, int itemsPerPage = 5) + : base(page, itemsPerPage) { this.userId = userId; } diff --git a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs index 5675e877b5..4908e5ecc2 100644 --- a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs @@ -10,8 +10,8 @@ namespace osu.Game.Online.API.Requests { private readonly long userId; - public GetUserRecentActivitiesRequest(long userId, int offset = 0, int limit = 5) - : base(offset, limit) + public GetUserRecentActivitiesRequest(long userId, int page = 0, int itemsPerPage = 5) + : base(page, itemsPerPage) { this.userId = userId; } diff --git a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs index 03a11b68ac..d41966fe1b 100644 --- a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs @@ -11,8 +11,8 @@ namespace osu.Game.Online.API.Requests private readonly long userId; private readonly ScoreType type; - public GetUserScoresRequest(long userId, ScoreType type, int offset = 0, int limit = 5) - : base(offset, limit) + public GetUserScoresRequest(long userId, ScoreType type, int page = 0, int itemsPerPage = 5) + : base(page, itemsPerPage) { this.userId = userId; this.type = type; diff --git a/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs index 45360612bd..52e12f04ee 100644 --- a/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs +++ b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs @@ -8,21 +8,21 @@ namespace osu.Game.Online.API.Requests { public abstract class PaginatedAPIRequest : APIRequest { - private readonly int offset; - private readonly int limit; + private readonly int page; + private readonly int itemsPerPage; - protected PaginatedAPIRequest(int offset, int limit) + protected PaginatedAPIRequest(int page, int itemsPerPage) { - this.offset = offset; - this.limit = limit; + this.page = page; + this.itemsPerPage = itemsPerPage; } protected override WebRequest CreateWebRequest() { var req = base.CreateWebRequest(); - req.AddParameter("offset", offset.ToString(CultureInfo.InvariantCulture)); - req.AddParameter("limit", limit.ToString(CultureInfo.InvariantCulture)); + req.AddParameter("offset", (page * itemsPerPage).ToString(CultureInfo.InvariantCulture)); + req.AddParameter("limit", itemsPerPage.ToString(CultureInfo.InvariantCulture)); return req; } diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 22f8e6c6b0..1b6c1c99a6 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps protected override void ShowMore() { - request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage, ItemsPerPage); + request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); request.Success += sets => Schedule(() => { MoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0); diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index 92b0304a68..9409cd9aeb 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical protected override void ShowMore() { - request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage, ItemsPerPage); + request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++, ItemsPerPage); request.Success += beatmaps => Schedule(() => { MoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0); diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 5bb362e21c..4a9ac6e5c7 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks protected override void ShowMore() { - request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage, ItemsPerPage); + request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); request.Success += scores => Schedule(() => { foreach (var s in scores) diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index 215c96a423..f2a778a874 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent protected override void ShowMore() { - request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage, ItemsPerPage); + request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++, ItemsPerPage); request.Success += activities => Schedule(() => { MoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0); From eebfdd88650446da481fdfceebbfdb0b1f17c8ec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 19 Jul 2019 23:43:25 +0900 Subject: [PATCH 1928/5608] 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 9aa5e631ad..b9451fc744 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 86a68d2159..d90b1d36e1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 712effcc39..fa2521a19e 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 5696d794235850fc37578ef475c4b91e2ec74d98 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 19 Jul 2019 23:47:48 +0900 Subject: [PATCH 1929/5608] Use TriangleBatch --- osu.Game/Graphics/Backgrounds/Triangles.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 62151d066b..a2d8f42fac 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -8,7 +8,6 @@ using osuTK.Graphics; using System; using osu.Framework.Graphics.Shaders; using osu.Framework.Graphics.Textures; -using osuTK.Graphics.ES30; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Primitives; using osu.Framework.Allocation; @@ -192,7 +191,7 @@ namespace osu.Game.Graphics.Backgrounds private readonly List parts = new List(); private Vector2 size; - private LinearBatch vertexBatch; + private TriangleBatch vertexBatch; public TrianglesDrawNode(Triangles source) : base(source) @@ -215,10 +214,10 @@ namespace osu.Game.Graphics.Backgrounds { base.Draw(vertexAction); - if (vertexBatch == null || vertexBatch.Size != Source.AimCount * 6) + if (vertexBatch == null || vertexBatch.Size != Source.AimCount) { vertexBatch?.Dispose(); - vertexBatch = new LinearBatch(Source.AimCount * 6, 1, PrimitiveType.Triangles); + vertexBatch = new TriangleBatch(Source.AimCount, 1); } shader.Bind(); From 2a94b68ecb4cebe004240b7f88a680b6ccd4f54b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 20 Jul 2019 22:50:17 +0900 Subject: [PATCH 1930/5608] Simplify logic --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 0adaaa20b2..a6cc2b0500 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -127,19 +127,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void getScores(BeatmapInfo beatmap) { - loadingAnimation.Show(); - getScoresRequest?.Cancel(); getScoresRequest = null; Scores = null; if (beatmap?.OnlineBeatmapID.HasValue != true) - { - loadingAnimation.Hide(); return; - } + loadingAnimation.Show(); getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); getScoresRequest.Success += scores => { From 4c592a5e65a11ad8a3b472f0ab6ba796e1196109 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 20 Jul 2019 22:50:35 +0900 Subject: [PATCH 1931/5608] Fix TriangleDrawNode crash when aimcount is zero --- osu.Game/Graphics/Backgrounds/Triangles.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index a2d8f42fac..79f227fafe 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -214,7 +214,7 @@ namespace osu.Game.Graphics.Backgrounds { base.Draw(vertexAction); - if (vertexBatch == null || vertexBatch.Size != Source.AimCount) + if (vertexBatch == null || vertexBatch.Size != Source.AimCount && Source.AimCount > 0) { vertexBatch?.Dispose(); vertexBatch = new TriangleBatch(Source.AimCount, 1); From 2926932a1acf5adc8da8125ba83b05a7960ebb60 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 20 Jul 2019 21:10:17 +0200 Subject: [PATCH 1932/5608] Add MusicControllerToast used to display current music playback status on OSD --- osu.Game/OsuGame.cs | 6 +-- osu.Game/Overlays/OSD/MusicControllerToast.cs | 13 ++++++ osu.Game/Overlays/OSD/OsdIconToast.cs | 45 ------------------- 3 files changed, 16 insertions(+), 48 deletions(-) create mode 100644 osu.Game/Overlays/OSD/MusicControllerToast.cs delete mode 100644 osu.Game/Overlays/OSD/OsdIconToast.cs diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index bae301a8a6..dde87cd2ed 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -726,21 +726,21 @@ namespace osu.Game if (!musicController.IsLoaded) return true; if (musicController.PlayTrack()) - osd.Display(new Overlays.OSD.OsdIconToast(musicController.IsPlaying ? "Play track" : "Pause track", musicController.IsPlaying ? FontAwesome.Solid.PlayCircle : FontAwesome.Solid.PauseCircle)); + osd.Display(new Overlays.OSD.MusicControllerToast(musicController.IsPlaying ? "Play track" : "Pause track")); return true; case GlobalAction.MusicNext: if (!musicController.IsLoaded) return true; if (musicController.NextTrack()) - osd.Display(new Overlays.OSD.OsdIconToast("Next track", FontAwesome.Solid.FastForward)); + osd.Display(new Overlays.OSD.MusicControllerToast("Next track")); return true; case GlobalAction.MusicPrev: if (!musicController.IsLoaded) return true; if (musicController.PreviousTrack()) - osd.Display(new Overlays.OSD.OsdIconToast("Previous track", FontAwesome.Solid.FastBackward)); + osd.Display(new Overlays.OSD.MusicControllerToast("Previous track")); return true; } diff --git a/osu.Game/Overlays/OSD/MusicControllerToast.cs b/osu.Game/Overlays/OSD/MusicControllerToast.cs new file mode 100644 index 0000000000..d9e0ad2c07 --- /dev/null +++ b/osu.Game/Overlays/OSD/MusicControllerToast.cs @@ -0,0 +1,13 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Overlays.OSD +{ + public class MusicControllerToast : Toast + { + public MusicControllerToast(string value) + : base("Music Playback", value, "") + { + } + } +} diff --git a/osu.Game/Overlays/OSD/OsdIconToast.cs b/osu.Game/Overlays/OSD/OsdIconToast.cs deleted file mode 100644 index 0e2bcd377f..0000000000 --- a/osu.Game/Overlays/OSD/OsdIconToast.cs +++ /dev/null @@ -1,45 +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.Sprites; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; - -namespace osu.Game.Overlays.OSD -{ - public class OsdIconToast : OsdToast - { - public OsdIconToast(string message, IconUsage icon) - { - Children = new Drawable[] - { - new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Direction = FillDirection.Vertical, - Spacing = new osuTK.Vector2(10), - Children = new Drawable[] - { - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.BottomCentre, - Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), - Text = message - }, - new SpriteIcon - { - Icon = icon, - Size = new osuTK.Vector2(45), - Anchor = Anchor.Centre, - Origin = Anchor.BottomCentre, - } - } - } - }; - } - } -} From 842417cf42480d7df01a50e23f6e016a720ca9a4 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 21 Jul 2019 03:07:27 +0300 Subject: [PATCH 1933/5608] Check if selected scope requires API --- osu.Game/Online/Leaderboards/Leaderboard.cs | 6 +++++- osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs | 2 ++ osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 18c827707a..5e3f57a19e 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -194,13 +194,17 @@ namespace osu.Game.Online.Leaderboards private APIRequest getScoresRequest; + protected abstract bool IsOnlineScope(); + public void APIStateChanged(IAPIProvider api, APIState state) { switch (state) { case APIState.Online: case APIState.Offline: - UpdateScores(); + if (IsOnlineScope()) + UpdateScores(); + break; } } diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index fff713f026..873765c17c 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -33,6 +33,8 @@ namespace osu.Game.Screens.Multi.Match.Components }, true); } + protected override bool IsOnlineScope() => true; + protected override APIRequest FetchScores(Action> scoresCallback) { if (roomId.Value == null) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 0f6d4f3188..3c857cc44a 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -79,6 +79,8 @@ namespace osu.Game.Screens.Select.Leaderboards }; } + protected override bool IsOnlineScope() => Scope != BeatmapLeaderboardScope.Local; + protected override APIRequest FetchScores(Action> scoresCallback) { if (Scope == BeatmapLeaderboardScope.Local) From e76b3e2b406d2e744b1794edbd1fe6cca17352d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 21 Jul 2019 10:42:40 +0900 Subject: [PATCH 1934/5608] User property instead of method --- osu.Game/Online/Leaderboards/Leaderboard.cs | 4 ++-- osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs | 2 +- osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 5e3f57a19e..98f15599fc 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -194,7 +194,7 @@ namespace osu.Game.Online.Leaderboards private APIRequest getScoresRequest; - protected abstract bool IsOnlineScope(); + protected abstract bool IsOnlineScope { get; } public void APIStateChanged(IAPIProvider api, APIState state) { @@ -202,7 +202,7 @@ namespace osu.Game.Online.Leaderboards { case APIState.Online: case APIState.Offline: - if (IsOnlineScope()) + if (IsOnlineScope) UpdateScores(); break; diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index 873765c17c..ae27e53813 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Multi.Match.Components }, true); } - protected override bool IsOnlineScope() => true; + protected override bool IsOnlineScope => true; protected override APIRequest FetchScores(Action> scoresCallback) { diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 3c857cc44a..cb45c00f66 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -79,7 +79,7 @@ namespace osu.Game.Screens.Select.Leaderboards }; } - protected override bool IsOnlineScope() => Scope != BeatmapLeaderboardScope.Local; + protected override bool IsOnlineScope => Scope != BeatmapLeaderboardScope.Local; protected override APIRequest FetchScores(Action> scoresCallback) { From ed0ef90613bf1038883c4368cb6702da211fe45f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 21 Jul 2019 12:14:55 +0300 Subject: [PATCH 1935/5608] Separate glowing sprite text into it's own class --- .../Graphics/Sprites/GlowingSpriteText.cs | 110 ++++++++++++++++++ .../Online/Leaderboards/LeaderboardScore.cs | 57 ++------- 2 files changed, 122 insertions(+), 45 deletions(-) create mode 100644 osu.Game/Graphics/Sprites/GlowingSpriteText.cs diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs new file mode 100644 index 0000000000..77187b9ff2 --- /dev/null +++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs @@ -0,0 +1,110 @@ +// 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.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Graphics.Sprites +{ + public class GlowingSpriteText : Container + { + private readonly BufferedContainer blurContainer; + private readonly OsuSpriteText spriteText, glowingText; + + private string text = string.Empty; + + public string Text + { + get => text; + set + { + text = value; + + spriteText.Text = text; + glowingText.Text = text; + } + } + + private FontUsage font = OsuFont.Default.With(fixedWidth: true); + + public FontUsage Font + { + get => font; + set + { + font = value.With(fixedWidth: true); + + spriteText.Font = font; + glowingText.Font = font; + } + } + + private Vector2 textSize; + + public Vector2 TextSize + { + get => textSize; + set + { + textSize = value; + + spriteText.Size = textSize; + glowingText.Size = textSize; + } + } + + public ColourInfo TextColour + { + get => spriteText.Colour; + set => spriteText.Colour = value; + } + + public ColourInfo GlowColour + { + get => glowingText.Colour; + set => glowingText.Colour = value; + } + + public GlowingSpriteText() + { + AutoSizeAxes = Axes.Both; + + Children = new Drawable[] + { + blurContainer = new BufferedContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + BlurSigma = new Vector2(4), + CacheDrawnFrameBuffer = true, + RelativeSizeAxes = Axes.Both, + Blending = BlendingMode.Additive, + Size = new Vector2(3f), + Children = new[] + { + glowingText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = font, + Text = text, + Shadow = false, + }, + }, + }, + spriteText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = font, + Text = text, + Shadow = false, + }, + }; + } + } +} diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 9840b59805..008f8208eb 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -187,7 +187,13 @@ namespace osu.Game.Online.Leaderboards Spacing = new Vector2(5f, 0f), Children = new Drawable[] { - scoreLabel = new GlowingSpriteText(score.TotalScore.ToString(@"N0"), OsuFont.Numeric.With(size: 23), Color4.White, OsuColour.FromHex(@"83ccfa")), + scoreLabel = new GlowingSpriteText + { + TextColour = Color4.White, + GlowColour = OsuColour.FromHex(@"83ccfa"), + Text = score.TotalScore.ToString(@"N0"), + Font = OsuFont.Numeric.With(size: 23), + }, RankContainer = new Container { Size = new Vector2(40f, 20f), @@ -275,49 +281,6 @@ namespace osu.Game.Online.Leaderboards base.OnHoverLost(e); } - private class GlowingSpriteText : Container - { - public GlowingSpriteText(string text, FontUsage font, Color4 textColour, Color4 glowColour) - { - AutoSizeAxes = Axes.Both; - - Children = new Drawable[] - { - new BufferedContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - BlurSigma = new Vector2(4), - CacheDrawnFrameBuffer = true, - RelativeSizeAxes = Axes.Both, - Blending = BlendingMode.Additive, - Size = new Vector2(3f), - Children = new[] - { - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = font.With(fixedWidth: true), - Text = text, - Colour = glowColour, - Shadow = false, - }, - }, - }, - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = font.With(fixedWidth: true), - Text = text, - Colour = textColour, - Shadow = false, - }, - }; - } - } - private class ScoreComponentLabel : Container, IHasTooltip { private const float icon_size = 20; @@ -367,10 +330,14 @@ namespace osu.Game.Online.Leaderboards }, }, }, - new GlowingSpriteText(statistic.Value, OsuFont.GetFont(size: 17, weight: FontWeight.Bold), Color4.White, OsuColour.FromHex(@"83ccfa")) + new GlowingSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, + TextColour = Color4.White, + GlowColour = OsuColour.FromHex(@"83ccfa"), + Text = statistic.Value, + Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold), }, }, }; From 9d7f6abbddb5354839d1afe45d706b806789abef Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 21 Jul 2019 12:18:31 +0300 Subject: [PATCH 1936/5608] Remove unnecessary field --- osu.Game/Graphics/Sprites/GlowingSpriteText.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs index 77187b9ff2..b075dc0476 100644 --- a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs @@ -12,7 +12,6 @@ namespace osu.Game.Graphics.Sprites { public class GlowingSpriteText : Container { - private readonly BufferedContainer blurContainer; private readonly OsuSpriteText spriteText, glowingText; private string text = string.Empty; @@ -75,7 +74,7 @@ namespace osu.Game.Graphics.Sprites Children = new Drawable[] { - blurContainer = new BufferedContainer + new BufferedContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 87fb22352c4fea9f2740021e8315f9331e263926 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 21 Jul 2019 12:28:55 +0300 Subject: [PATCH 1937/5608] glowingText -> blurredText --- osu.Game/Graphics/Sprites/GlowingSpriteText.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs index b075dc0476..7082e99600 100644 --- a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs @@ -12,7 +12,7 @@ namespace osu.Game.Graphics.Sprites { public class GlowingSpriteText : Container { - private readonly OsuSpriteText spriteText, glowingText; + private readonly OsuSpriteText spriteText, blurredText; private string text = string.Empty; @@ -85,7 +85,7 @@ namespace osu.Game.Graphics.Sprites Size = new Vector2(3f), Children = new[] { - glowingText = new OsuSpriteText + blurredText = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 57fc5cbda86e6c5ea6565227d66732d0cd8de506 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 21 Jul 2019 12:29:06 +0300 Subject: [PATCH 1938/5608] Fix CI issues --- osu.Game/Graphics/Sprites/GlowingSpriteText.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs index 7082e99600..abc81df7a7 100644 --- a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osuTK; -using osuTK.Graphics; namespace osu.Game.Graphics.Sprites { From affd0b28789b0339be71ee68e2265d5cae49f759 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 21 Jul 2019 12:34:52 +0300 Subject: [PATCH 1939/5608] Fix build issues --- osu.Game/Graphics/Sprites/GlowingSpriteText.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs index abc81df7a7..546b8cae58 100644 --- a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs @@ -23,7 +23,7 @@ namespace osu.Game.Graphics.Sprites text = value; spriteText.Text = text; - glowingText.Text = text; + blurredText.Text = text; } } @@ -37,7 +37,7 @@ namespace osu.Game.Graphics.Sprites font = value.With(fixedWidth: true); spriteText.Font = font; - glowingText.Font = font; + blurredText.Font = font; } } @@ -51,7 +51,7 @@ namespace osu.Game.Graphics.Sprites textSize = value; spriteText.Size = textSize; - glowingText.Size = textSize; + blurredText.Size = textSize; } } @@ -63,8 +63,8 @@ namespace osu.Game.Graphics.Sprites public ColourInfo GlowColour { - get => glowingText.Colour; - set => glowingText.Colour = value; + get => blurredText.Colour; + set => blurredText.Colour = value; } public GlowingSpriteText() From de8ac9a428b994691b2195ddf7cf3ab74b82e47a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 21 Jul 2019 21:41:07 +0300 Subject: [PATCH 1940/5608] Simple implementation --- osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs | 5 +++++ osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs | 4 ++++ osu.Game/Overlays/BeatmapSet/Header.cs | 2 ++ 3 files changed, 11 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs index ea3f0b61b9..df3a45d1cc 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs @@ -66,6 +66,11 @@ namespace osu.Game.Beatmaps /// public int FavouriteCount { get; set; } + /// + /// Whether this beatmap set has been favourited by the current user. + /// + public bool HasFavourited { get; set; } + /// /// The availability of this beatmap set. /// diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 200a705500..e5bfde8f8f 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -30,6 +30,9 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"preview_url")] private string preview { get; set; } + [JsonProperty(@"has_favourited")] + private bool hasFavourited { get; set; } + [JsonProperty(@"play_count")] private int playCount { get; set; } @@ -91,6 +94,7 @@ namespace osu.Game.Online.API.Requests.Responses Ranked = ranked, LastUpdated = lastUpdated, Availability = availability, + HasFavourited = hasFavourited, }, Beatmaps = beatmaps?.Select(b => b.ToBeatmap(rulesets)).ToList(), }; diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index b50eac2c1a..dd8a2f18c1 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -246,6 +246,8 @@ namespace osu.Game.Overlays.BeatmapSet onlineStatusPill.Status = setInfo.NewValue.OnlineInfo.Status; downloadButtonsContainer.FadeIn(transition_duration); + + favouriteButton.Favourited.Value = setInfo.NewValue.OnlineInfo.HasFavourited; favouriteButton.FadeIn(transition_duration); updateDownloadButtons(); From e50b70d6157266cb6448719b033aba2a15eb4401 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jul 2019 15:59:22 +0900 Subject: [PATCH 1941/5608] Centralise osu! circle radius specification --- .../Blueprints/HitCircles/Components/HitCirclePiece.cs | 2 +- .../Blueprints/Sliders/Components/SliderBodyPiece.cs | 3 +-- .../Objects/Drawables/DrawableSlider.cs | 2 +- .../Objects/Drawables/Pieces/CirclePiece.cs | 2 +- .../Objects/Drawables/Pieces/ExplodePiece.cs | 2 +- .../Objects/Drawables/Pieces/FlashPiece.cs | 4 ++-- .../Objects/Drawables/Pieces/RingPiece.cs | 4 ++-- .../Objects/Drawables/Pieces/SliderBall.cs | 10 ++++------ osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 2 +- 9 files changed, 14 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs index 7f6a60c400..fe11ead94d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components this.hitCircle = hitCircle; Origin = Anchor.Centre; - Size = new Vector2((float)OsuHitObject.OBJECT_RADIUS * 2); + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Scale = new Vector2(hitCircle.Scale); CornerRadius = Size.X / 2; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index 957550a051..f1f55731b6 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -24,7 +24,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components InternalChild = body = new ManualSliderBody { AccentColour = Color4.Transparent, - PathRadius = slider.Scale * 64 }; } @@ -34,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components body.BorderColour = colours.Yellow; PositionBindable.BindValueChanged(_ => updatePosition(), true); - ScaleBindable.BindValueChanged(scale => body.PathRadius = scale.NewValue * 64, true); + ScaleBindable.BindValueChanged(scale => body.PathRadius = scale.NewValue * OsuHitObject.OBJECT_RADIUS, true); } private void updatePosition() => Position = slider.StackedPosition; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 4d67c9ae34..56b5decd30 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { Body = new SnakingSliderBody(s) { - PathRadius = s.Scale * 64, + PathRadius = s.Scale * OsuHitObject.OBJECT_RADIUS, }, ticks = new Container { RelativeSizeAxes = Axes.Both }, repeatPoints = new Container { RelativeSizeAxes = Axes.Both }, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index 786cac7198..dc0b149140 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public CirclePiece() { - Size = new Vector2((float)OsuHitObject.OBJECT_RADIUS * 2); + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Masking = true; CornerRadius = Size.X / 2; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs index b960f40578..8ff16f8b84 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public ExplodePiece() { - Size = new Vector2(128); + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Anchor = Anchor.Centre; Origin = Anchor.Centre; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs index 8e5eb886aa..c22073f56c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.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; @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public FlashPiece() { - Size = new Vector2(128); + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Anchor = Anchor.Centre; Origin = Anchor.Centre; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs index 28180a7f71..af733f16e1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public RingPiece() { - Size = new Vector2(128); + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Anchor = Anchor.Centre; Origin = Anchor.Centre; @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces RelativeSizeAxes = Axes.Both } } - }); + }, confineMode: ConfineMode.NoScaling); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 7d1d77ae96..9ba8ad3474 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -17,8 +17,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class SliderBall : CircularContainer, ISliderProgress, IRequireHighFrequencyMousePosition { - private const float width = 128; - private Color4 accentColour = Color4.Black; public Func GetInitialHitAction; @@ -57,8 +55,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { Origin = Anchor.Centre, Anchor = Anchor.Centre, - Width = width, - Height = width, + Width = OsuHitObject.OBJECT_RADIUS * 2, + Height = OsuHitObject.OBJECT_RADIUS * 2, Alpha = 0, Child = new SkinnableDrawable("Play/osu/sliderfollowcircle", _ => new CircularContainer { @@ -84,8 +82,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Alpha = 1, Child = new Container { - Width = width, - Height = width, + Width = OsuHitObject.OBJECT_RADIUS * 2, + Height = OsuHitObject.OBJECT_RADIUS * 2, // TODO: support skin filename animation (sliderb0, sliderb1...) Child = new SkinnableDrawable("Play/osu/sliderb", _ => new CircularContainer { diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 364c182dd4..d1221fd2d3 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Objects { public abstract class OsuHitObject : HitObject, IHasComboInformation, IHasPosition { - public const double OBJECT_RADIUS = 64; + public const float OBJECT_RADIUS = 64; public double TimePreempt = 600; public double TimeFadeIn = 400; From 74c961bcffcf7030ccae4320e3fb951346a734d4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jul 2019 12:10:28 +0900 Subject: [PATCH 1942/5608] Add more flexible skin element confine modes --- .../Drawables/Connections/FollowPoint.cs | 2 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- .../Objects/Drawables/DrawableSliderTick.cs | 4 +- .../Objects/Drawables/Pieces/NumberPiece.cs | 2 +- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs | 2 +- .../Gameplay/TestSceneSkinReloadable.cs | 4 +- .../Rulesets/Judgements/DrawableJudgement.cs | 2 +- osu.Game/Skinning/SkinnableDrawable.cs | 44 +++++++++++++------ osu.Game/Skinning/SkinnableSprite.cs | 4 +- osu.Game/Skinning/SkinnableSpriteText.cs | 4 +- 10 files changed, 43 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index aacf3ee08d..a2a23e9ff7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections Anchor = Anchor.Centre, Alpha = 0.5f, } - }, restrictSize: false); + }, confineMode: ConfineMode.NoScaling); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index cce6dfe106..cf6f05a604 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { RelativeSizeAxes = Axes.Both, Icon = FontAwesome.Solid.ChevronRight - }, restrictSize: false) + }) }; } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index 72b648bfd0..01ef1eb3e0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) { - Size = new Vector2(16) * sliderTick.Scale; + Size = new Vector2(16 * sliderTick.Scale); Origin = Anchor.Centre; InternalChildren = new Drawable[] @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Colour = AccentColour, Alpha = 0.3f, } - }, restrictSize: false) + }) }; } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs index 84034d3ee9..e8dc63abca 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { Font = OsuFont.Numeric.With(size: 40), UseFullGlyphHeight = false, - }, restrictSize: false) + }, confineMode: ConfineMode.NoScaling) { Text = @"1" } diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index 27546fa424..b3492a2b31 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor }, }, } - }, restrictSize: false) + }) { Origin = Anchor.Centre, Anchor = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs index c7a0df6e9f..af03ddc65c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs @@ -92,8 +92,8 @@ namespace osu.Game.Tests.Visual.Gameplay public new Drawable Drawable => base.Drawable; public int SkinChangedCount { get; private set; } - public SkinConsumer(string name, Func defaultImplementation, Func allowFallback = null, bool restrictSize = true) - : base(name, defaultImplementation, allowFallback, restrictSize) + public SkinConsumer(string name, Func defaultImplementation, Func allowFallback = null) + : base(name, defaultImplementation, allowFallback) { } diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 2150726a42..61c2644c6f 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Judgements Font = OsuFont.Numeric.With(size: 12), Colour = judgementColour(Result.Type), Scale = new Vector2(0.85f, 1), - }, restrictSize: false) + }) }; } diff --git a/osu.Game/Skinning/SkinnableDrawable.cs b/osu.Game/Skinning/SkinnableDrawable.cs index 995cb15136..a30bdbd2dc 100644 --- a/osu.Game/Skinning/SkinnableDrawable.cs +++ b/osu.Game/Skinning/SkinnableDrawable.cs @@ -9,8 +9,8 @@ namespace osu.Game.Skinning { public class SkinnableDrawable : SkinnableDrawable { - public SkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, bool restrictSize = true) - : base(name, defaultImplementation, allowFallback, restrictSize) + public SkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + : base(name, defaultImplementation, allowFallback, confineMode) { } } @@ -29,7 +29,7 @@ namespace osu.Game.Skinning private readonly string componentName; - private readonly bool restrictSize; + private readonly ConfineMode confineMode; /// /// Create a new skinnable drawable. @@ -37,18 +37,18 @@ namespace osu.Game.Skinning /// The namespace-complete resource name for this skinnable element. /// A function to create the default skin implementation of this element. /// A conditional to decide whether to allow fallback to the default implementation if a skinned element is not present. - /// Whether a user-skin drawable should be limited to the size of our parent. - public SkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, bool restrictSize = true) - : this(name, allowFallback, restrictSize) + /// How (if at all) the should be resize to fit within our own bounds. + public SkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + : this(name, allowFallback, confineMode) { createDefault = defaultImplementation; } - protected SkinnableDrawable(string name, Func allowFallback = null, bool restrictSize = true) + protected SkinnableDrawable(string name, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) : base(allowFallback) { componentName = name; - this.restrictSize = restrictSize; + this.confineMode = confineMode; RelativeSizeAxes = Axes.Both; } @@ -58,7 +58,7 @@ namespace osu.Game.Skinning protected virtual T CreateDefault(string name) => createDefault(name); /// - /// Whether to apply size restrictions (specified via ) to the default implementation. + /// Whether to apply size restrictions (specified via ) to the default implementation. /// protected virtual bool ApplySizeRestrictionsToDefault => false; @@ -76,12 +76,18 @@ namespace osu.Game.Skinning if (Drawable != null) { - if (restrictSize && (!isDefault || ApplySizeRestrictionsToDefault)) + if (confineMode != ConfineMode.NoScaling && (!isDefault || ApplySizeRestrictionsToDefault)) { - Drawable.RelativeSizeAxes = Axes.Both; - Drawable.Size = Vector2.One; - Drawable.Scale = Vector2.One; - Drawable.FillMode = FillMode.Fit; + bool applyScaling = confineMode == ConfineMode.ScaleToFit || + (confineMode == ConfineMode.ScaleDownToFit && (Drawable.DrawSize.X > DrawSize.X || Drawable.DrawSize.Y > DrawSize.Y)); + + if (applyScaling) + { + Drawable.RelativeSizeAxes = Axes.Both; + Drawable.Size = Vector2.One; + Drawable.Scale = Vector2.One; + Drawable.FillMode = FillMode.Fit; + } } Drawable.Origin = Anchor.Centre; @@ -93,4 +99,14 @@ namespace osu.Game.Skinning ClearInternal(); } } + + public enum ConfineMode + { + /// + /// Don't apply any scaling. This allows the user element to be of any size, exceeding specified bounds. + /// + NoScaling, + ScaleDownToFit, + ScaleToFit, + } } diff --git a/osu.Game/Skinning/SkinnableSprite.cs b/osu.Game/Skinning/SkinnableSprite.cs index ceb1ed0f70..1716ec71de 100644 --- a/osu.Game/Skinning/SkinnableSprite.cs +++ b/osu.Game/Skinning/SkinnableSprite.cs @@ -18,8 +18,8 @@ namespace osu.Game.Skinning [Resolved] private TextureStore textures { get; set; } - public SkinnableSprite(string name, Func allowFallback = null, bool restrictSize = true) - : base(name, allowFallback, restrictSize) + public SkinnableSprite(string name, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + : base(name, allowFallback, confineMode) { } diff --git a/osu.Game/Skinning/SkinnableSpriteText.cs b/osu.Game/Skinning/SkinnableSpriteText.cs index 36e646d743..d12a6f74f7 100644 --- a/osu.Game/Skinning/SkinnableSpriteText.cs +++ b/osu.Game/Skinning/SkinnableSpriteText.cs @@ -8,8 +8,8 @@ namespace osu.Game.Skinning { public class SkinnableSpriteText : SkinnableDrawable, IHasText { - public SkinnableSpriteText(string name, Func defaultImplementation, Func allowFallback = null, bool restrictSize = true) - : base(name, defaultImplementation, allowFallback, restrictSize) + public SkinnableSpriteText(string name, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + : base(name, defaultImplementation, allowFallback, confineMode) { } From 9d091c96b81d2bf461890137cc32d87daa7b4972 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jul 2019 17:52:50 +0900 Subject: [PATCH 1943/5608] Use cache to ensure correct DrawSize when deciding scaling --- osu.Game/Skinning/SkinnableDrawable.cs | 32 +++++++++++++++++++------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/osu.Game/Skinning/SkinnableDrawable.cs b/osu.Game/Skinning/SkinnableDrawable.cs index a30bdbd2dc..5d1ca98bfd 100644 --- a/osu.Game/Skinning/SkinnableDrawable.cs +++ b/osu.Game/Skinning/SkinnableDrawable.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Caching; using osu.Framework.Graphics; using osuTK; @@ -55,6 +56,10 @@ namespace osu.Game.Skinning private readonly Func createDefault; + private readonly Cached scaling = new Cached(); + + private bool isDefault; + protected virtual T CreateDefault(string name) => createDefault(name); /// @@ -66,7 +71,7 @@ namespace osu.Game.Skinning { Drawable = skin.GetDrawableComponent(componentName); - bool isDefault = false; + isDefault = false; if (Drawable == null && allowFallback) { @@ -76,7 +81,23 @@ namespace osu.Game.Skinning if (Drawable != null) { - if (confineMode != ConfineMode.NoScaling && (!isDefault || ApplySizeRestrictionsToDefault)) + scaling.Invalidate(); + Drawable.Origin = Anchor.Centre; + Drawable.Anchor = Anchor.Centre; + + InternalChild = Drawable; + } + else + ClearInternal(); + } + + protected override void Update() + { + base.Update(); + + if (!scaling.IsValid) + { + if (Drawable != null && confineMode != ConfineMode.NoScaling && (!isDefault || ApplySizeRestrictionsToDefault)) { bool applyScaling = confineMode == ConfineMode.ScaleToFit || (confineMode == ConfineMode.ScaleDownToFit && (Drawable.DrawSize.X > DrawSize.X || Drawable.DrawSize.Y > DrawSize.Y)); @@ -90,13 +111,8 @@ namespace osu.Game.Skinning } } - Drawable.Origin = Anchor.Centre; - Drawable.Anchor = Anchor.Centre; - - InternalChild = Drawable; + scaling.Validate(); } - else - ClearInternal(); } } From eca63980d2ed7cda53a848af781eb495960a11c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jul 2019 17:53:01 +0900 Subject: [PATCH 1944/5608] Add comprehensive scaling mode tests --- .../Gameplay/TestSceneSkinReloadable.cs | 145 --------- .../Gameplay/TestSceneSkinnableDrawable.cs | 283 ++++++++++++++++++ 2 files changed, 283 insertions(+), 145 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs deleted file mode 100644 index af03ddc65c..0000000000 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using NUnit.Framework; -using osu.Framework.Audio.Sample; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Textures; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Skinning; -using osuTK.Graphics; - -namespace osu.Game.Tests.Visual.Gameplay -{ - public class TestSceneSkinReloadable : OsuTestScene - { - [Test] - public void TestInitialLoad() - { - var secondarySource = new SecondarySource(); - SkinConsumer consumer = null; - - AddStep("setup layout", () => - { - Child = new SkinSourceContainer - { - RelativeSizeAxes = Axes.Both, - Child = new LocalSkinOverrideContainer(secondarySource) - { - RelativeSizeAxes = Axes.Both, - Child = consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation"), source => true) - } - }; - }); - - AddAssert("consumer using override source", () => consumer.Drawable is SecondarySourceBox); - AddAssert("skinchanged only called once", () => consumer.SkinChangedCount == 1); - } - - [Test] - public void TestOverride() - { - var secondarySource = new SecondarySource(); - - SkinConsumer consumer = null; - Container target = null; - - AddStep("setup layout", () => - { - Child = new SkinSourceContainer - { - RelativeSizeAxes = Axes.Both, - Child = target = new LocalSkinOverrideContainer(secondarySource) - { - RelativeSizeAxes = Axes.Both, - } - }; - }); - - AddStep("add permissive", () => target.Add(consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation"), source => true))); - AddAssert("consumer using override source", () => consumer.Drawable is SecondarySourceBox); - AddAssert("skinchanged only called once", () => consumer.SkinChangedCount == 1); - } - - private class NamedBox : Container - { - public NamedBox(string name) - { - Children = new Drawable[] - { - new Box - { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, - }, - new OsuSpriteText - { - Font = OsuFont.Default.With(size: 40), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = name - } - }; - } - } - - private class SkinConsumer : SkinnableDrawable - { - public new Drawable Drawable => base.Drawable; - public int SkinChangedCount { get; private set; } - - public SkinConsumer(string name, Func defaultImplementation, Func allowFallback = null) - : base(name, defaultImplementation, allowFallback) - { - } - - protected override void SkinChanged(ISkinSource skin, bool allowFallback) - { - base.SkinChanged(skin, allowFallback); - SkinChangedCount++; - } - } - - private class BaseSourceBox : NamedBox - { - public BaseSourceBox() - : base("Base Source") - { - } - } - - private class SecondarySourceBox : NamedBox - { - public SecondarySourceBox() - : base("Secondary Source") - { - } - } - - private class SecondarySource : ISkin - { - public Drawable GetDrawableComponent(string componentName) => new SecondarySourceBox(); - - public Texture GetTexture(string componentName) => throw new NotImplementedException(); - - public SampleChannel GetSample(string sampleName) => throw new NotImplementedException(); - - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); - } - - private class SkinSourceContainer : Container, ISkin - { - public Drawable GetDrawableComponent(string componentName) => new BaseSourceBox(); - - public Texture GetTexture(string componentName) => throw new NotImplementedException(); - - public SampleChannel GetSample(string sampleName) => throw new NotImplementedException(); - - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); - } - } -} diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs new file mode 100644 index 0000000000..0b5978e3eb --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs @@ -0,0 +1,283 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Globalization; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Audio.Sample; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestSceneSkinnableDrawable : OsuTestScene + { + [Test] + public void TestConfineScaleDown() + { + FillFlowContainer fill = null; + + AddStep("setup layout larger source", () => + { + Child = new LocalSkinOverrideContainer(new SizedSource(50)) + { + RelativeSizeAxes = Axes.Both, + Child = fill = new FillFlowContainer + { + Size = new Vector2(30), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Spacing = new Vector2(10), + Children = new[] + { + new ExposedSkinnableDrawable("default", _ => new DefaultBox(), _ => true), + new ExposedSkinnableDrawable("available", _ => new DefaultBox(), _ => true), + new ExposedSkinnableDrawable("available", _ => new DefaultBox(), _ => true, ConfineMode.ScaleToFit), + new ExposedSkinnableDrawable("available", _ => new DefaultBox(), _ => true, ConfineMode.NoScaling) + } + }, + }; + }); + + AddAssert("check sizes", () => fill.Children.Select(c => c.Drawable.DrawWidth).SequenceEqual(new float[] { 30, 30, 30, 50 })); + AddStep("adjust scale", () => fill.Scale = new Vector2(2)); + AddAssert("check sizes unchanged by scale", () => fill.Children.Select(c => c.Drawable.DrawWidth).SequenceEqual(new float[] { 30, 30, 30, 50 })); + } + + [Test] + public void TestConfineScaleUp() + { + FillFlowContainer fill = null; + + AddStep("setup layout larger source", () => + { + Child = new LocalSkinOverrideContainer(new SizedSource(30)) + { + RelativeSizeAxes = Axes.Both, + Child = fill = new FillFlowContainer + { + Size = new Vector2(50), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Spacing = new Vector2(10), + Children = new[] + { + new ExposedSkinnableDrawable("default", _ => new DefaultBox(), _ => true), + new ExposedSkinnableDrawable("available", _ => new DefaultBox(), _ => true), + new ExposedSkinnableDrawable("available", _ => new DefaultBox(), _ => true, ConfineMode.ScaleToFit), + new ExposedSkinnableDrawable("available", _ => new DefaultBox(), _ => true, ConfineMode.NoScaling) + } + }, + }; + }); + + AddAssert("check sizes", () => fill.Children.Select(c => c.Drawable.DrawWidth).SequenceEqual(new float[] { 50, 30, 50, 30 })); + AddStep("adjust scale", () => fill.Scale = new Vector2(2)); + AddAssert("check sizes unchanged by scale", () => fill.Children.Select(c => c.Drawable.DrawWidth).SequenceEqual(new float[] { 50, 30, 50, 30 })); + } + + [Test] + public void TestInitialLoad() + { + var secondarySource = new SecondarySource(); + SkinConsumer consumer = null; + + AddStep("setup layout", () => + { + Child = new SkinSourceContainer + { + RelativeSizeAxes = Axes.Both, + Child = new LocalSkinOverrideContainer(secondarySource) + { + RelativeSizeAxes = Axes.Both, + Child = consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation"), source => true) + } + }; + }); + + AddAssert("consumer using override source", () => consumer.Drawable is SecondarySourceBox); + AddAssert("skinchanged only called once", () => consumer.SkinChangedCount == 1); + } + + [Test] + public void TestOverride() + { + var secondarySource = new SecondarySource(); + + SkinConsumer consumer = null; + Container target = null; + + AddStep("setup layout", () => + { + Child = new SkinSourceContainer + { + RelativeSizeAxes = Axes.Both, + Child = target = new LocalSkinOverrideContainer(secondarySource) + { + RelativeSizeAxes = Axes.Both, + } + }; + }); + + AddStep("add permissive", () => target.Add(consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation"), source => true))); + AddAssert("consumer using override source", () => consumer.Drawable is SecondarySourceBox); + AddAssert("skinchanged only called once", () => consumer.SkinChangedCount == 1); + } + + private class ExposedSkinnableDrawable : SkinnableDrawable + { + public new Drawable Drawable => base.Drawable; + + public ExposedSkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + : base(name, defaultImplementation, allowFallback, confineMode) + { + } + } + + private class DefaultBox : DrawWidthBox + { + public DefaultBox() + { + RelativeSizeAxes = Axes.Both; + } + } + + private class DrawWidthBox : Container + { + private readonly OsuSpriteText text; + + public DrawWidthBox() + { + Children = new Drawable[] + { + new Box + { + Colour = Color4.Gray, + RelativeSizeAxes = Axes.Both, + }, + text = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + text.Text = DrawWidth.ToString(CultureInfo.InvariantCulture); + } + } + + private class NamedBox : Container + { + public NamedBox(string name) + { + Children = new Drawable[] + { + new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + }, + new OsuSpriteText + { + Font = OsuFont.Default.With(size: 40), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = name + } + }; + } + } + + private class SkinConsumer : SkinnableDrawable + { + public new Drawable Drawable => base.Drawable; + public int SkinChangedCount { get; private set; } + + public SkinConsumer(string name, Func defaultImplementation, Func allowFallback = null) + : base(name, defaultImplementation, allowFallback) + { + } + + protected override void SkinChanged(ISkinSource skin, bool allowFallback) + { + base.SkinChanged(skin, allowFallback); + SkinChangedCount++; + } + } + + private class BaseSourceBox : NamedBox + { + public BaseSourceBox() + : base("Base Source") + { + } + } + + private class SecondarySourceBox : NamedBox + { + public SecondarySourceBox() + : base("Secondary Source") + { + } + } + + private class SizedSource : ISkin + { + private readonly float size; + + public SizedSource(float size) + { + this.size = size; + } + + public Drawable GetDrawableComponent(string componentName) => + componentName == "available" + ? new DrawWidthBox + { + Colour = Color4.Yellow, + Size = new Vector2(size) + } + : null; + + public Texture GetTexture(string componentName) => throw new NotImplementedException(); + + public SampleChannel GetSample(string sampleName) => throw new NotImplementedException(); + + public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); + } + + private class SecondarySource : ISkin + { + public Drawable GetDrawableComponent(string componentName) => new SecondarySourceBox(); + + public Texture GetTexture(string componentName) => throw new NotImplementedException(); + + public SampleChannel GetSample(string sampleName) => throw new NotImplementedException(); + + public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); + } + + private class SkinSourceContainer : Container, ISkin + { + public Drawable GetDrawableComponent(string componentName) => new BaseSourceBox(); + + public Texture GetTexture(string componentName) => throw new NotImplementedException(); + + public SampleChannel GetSample(string sampleName) => throw new NotImplementedException(); + + public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); + } + } +} From 36c557c752be5bdecb37b9e761c6ad4551e47c12 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jul 2019 18:39:33 +0900 Subject: [PATCH 1945/5608] Add null check and simplify scaling conditional logic via switch --- osu.Game/Skinning/SkinnableDrawable.cs | 33 ++++++++++++++++---------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/osu.Game/Skinning/SkinnableDrawable.cs b/osu.Game/Skinning/SkinnableDrawable.cs index 5d1ca98bfd..eb0508b568 100644 --- a/osu.Game/Skinning/SkinnableDrawable.cs +++ b/osu.Game/Skinning/SkinnableDrawable.cs @@ -84,7 +84,6 @@ namespace osu.Game.Skinning scaling.Invalidate(); Drawable.Origin = Anchor.Centre; Drawable.Anchor = Anchor.Centre; - InternalChild = Drawable; } else @@ -97,21 +96,31 @@ namespace osu.Game.Skinning if (!scaling.IsValid) { - if (Drawable != null && confineMode != ConfineMode.NoScaling && (!isDefault || ApplySizeRestrictionsToDefault)) + try { - bool applyScaling = confineMode == ConfineMode.ScaleToFit || - (confineMode == ConfineMode.ScaleDownToFit && (Drawable.DrawSize.X > DrawSize.X || Drawable.DrawSize.Y > DrawSize.Y)); + if (Drawable == null || (isDefault && !ApplySizeRestrictionsToDefault)) return; - if (applyScaling) + switch (confineMode) { - Drawable.RelativeSizeAxes = Axes.Both; - Drawable.Size = Vector2.One; - Drawable.Scale = Vector2.One; - Drawable.FillMode = FillMode.Fit; - } - } + case ConfineMode.NoScaling: + return; - scaling.Validate(); + case ConfineMode.ScaleDownToFit: + if (Drawable.DrawSize.X <= DrawSize.X && Drawable.DrawSize.Y <= DrawSize.Y) + return; + + break; + } + + Drawable.RelativeSizeAxes = Axes.Both; + Drawable.Size = Vector2.One; + Drawable.Scale = Vector2.One; + Drawable.FillMode = FillMode.Fit; + } + finally + { + scaling.Validate(); + } } } } From 8327452fe18b89b80fe374b6e873f97bacedc706 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 14:45:25 +0900 Subject: [PATCH 1946/5608] Make AccentColour a bindable --- .../Drawable/DrawableCatchHitObject.cs | 2 +- .../Objects/Drawable/DrawableDroplet.cs | 11 +---- .../Objects/Drawable/DrawableFruit.cs | 46 +++++++++---------- .../TestSceneHoldNoteSelectionBlueprint.cs | 2 +- .../TestSceneNotes.cs | 4 +- .../Objects/Drawables/DrawableHoldNote.cs | 26 ++++------- .../Objects/Drawables/DrawableHoldNoteTick.cs | 17 ++----- .../Objects/Drawables/DrawableNote.cs | 30 +++++------- osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/HitExplosion.cs | 2 +- .../Objects/Drawables/DrawableHitCircle.cs | 18 +++----- .../Objects/Drawables/DrawableOsuHitObject.cs | 4 +- .../Objects/Drawables/DrawableSlider.cs | 19 +++----- .../Objects/Drawables/DrawableSliderTick.cs | 3 +- .../Objects/Drawables/DrawableHitObject.cs | 5 +- 15 files changed, 75 insertions(+), 116 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 5785d9a9ca..2ccb01a3e3 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable base.SkinChanged(skin, allowFallback); if (HitObject is IHasComboInformation combo) - AccentColour = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; + AccentColour.Value = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; } protected override void UpdateState(ArmedState state) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs index 9cabdc3dd9..059310d671 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces; using osuTK; -using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawable { @@ -27,16 +26,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable private void load() { AddInternal(pulp = new Pulp { Size = Size }); - } - public override Color4 AccentColour - { - get => base.AccentColour; - set - { - base.AccentColour = value; - pulp.AccentColour = AccentColour; - } + AccentColour.BindValueChanged(colour => { pulp.AccentColour = colour.NewValue; }, true); } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 77407def54..ce2daebbf1 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable private void load() { // todo: this should come from the skin. - AccentColour = colourForRepresentation(HitObject.VisualRepresentation); + AccentColour.Value = colourForRepresentation(HitObject.VisualRepresentation); AddRangeInternal(new[] { @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Hollow = !HitObject.HyperDash, Type = EdgeEffectType.Glow, Radius = 4 * radius_adjust, - Colour = HitObject.HyperDash ? Color4.Red : AccentColour.Darken(1).Opacity(0.6f) + Colour = HitObject.HyperDash ? Color4.Red : AccentColour.Value.Darken(1).Opacity(0.6f) }, Size = new Vector2(Height), Anchor = Anchor.Centre, @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable new Box { AlwaysPresent = true, - Colour = AccentColour, + Colour = AccentColour.Value, Alpha = 0, RelativeSizeAxes = Axes.Both } @@ -115,32 +115,32 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(small_pulp), Y = -0.34f, }, new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(large_pulp_4), Position = positionAt(0, distance_from_centre_4), }, new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(large_pulp_4), Position = positionAt(90, distance_from_centre_4), }, new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(large_pulp_4), Position = positionAt(180, distance_from_centre_4), }, new Pulp { Size = new Vector2(large_pulp_4), - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Position = positionAt(270, distance_from_centre_4), }, } @@ -154,32 +154,32 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(small_pulp), Y = -0.3f, }, new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(large_pulp_4), Position = positionAt(45, distance_from_centre_4), }, new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(large_pulp_4), Position = positionAt(135, distance_from_centre_4), }, new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(large_pulp_4), Position = positionAt(225, distance_from_centre_4), }, new Pulp { Size = new Vector2(large_pulp_4), - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Position = positionAt(315, distance_from_centre_4), }, } @@ -193,26 +193,26 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(small_pulp), Y = -0.33f, }, new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(large_pulp_3), Position = positionAt(60, distance_from_centre_3), }, new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(large_pulp_3), Position = positionAt(180, distance_from_centre_3), }, new Pulp { Size = new Vector2(large_pulp_3), - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Position = positionAt(300, distance_from_centre_3), }, } @@ -226,26 +226,26 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(small_pulp), Y = -0.25f, }, new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(large_pulp_3), Position = positionAt(0, distance_from_centre_3), }, new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(large_pulp_3), Position = positionAt(120, distance_from_centre_3), }, new Pulp { Size = new Vector2(large_pulp_3), - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Position = positionAt(240, distance_from_centre_3), }, } @@ -259,13 +259,13 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(small_pulp), Y = -0.3f }, new Pulp { - AccentColour = AccentColour, + AccentColour = AccentColour.Value, Size = new Vector2(large_pulp_4 * 0.8f, large_pulp_4 * 2.5f), Y = 0.05f, }, diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs index 04c5724f93..622d840a0c 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Mania.Tests Child = drawableObject = new DrawableHoldNote(holdNote) { Height = 300, - AccentColour = OsuColour.Gray(0.3f) + AccentColour = { Value = OsuColour.Gray(0.3f) } } }; } diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index b2613a59d5..031abb08e2 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs @@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Mania.Tests AutoSizeAxes = Axes.Both, Child = new NoteContainer(direction, $"note {identifier}, scrolling {direction.ToString().ToLowerInvariant()}") { - Child = hitObject = new DrawableNote(note) { AccentColour = Color4.OrangeRed } + Child = hitObject = new DrawableNote(note) { AccentColour = { Value = Color4.OrangeRed } } } }; } @@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Mania.Tests Child = hitObject = new DrawableHoldNote(note) { RelativeSizeAxes = Axes.Both, - AccentColour = Color4.OrangeRed, + AccentColour = { Value = Color4.OrangeRed }, } } }; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 9368af987d..952c6e128e 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -6,7 +6,6 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; -using osuTK.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Scoring; @@ -36,11 +35,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// private bool hasBroken; - private readonly Container tickContainer; - public DrawableHoldNote(HoldNote hitObject) : base(hitObject) { + Container tickContainer; RelativeSizeAxes = Axes.X; AddRangeInternal(new Drawable[] @@ -74,6 +72,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables AddNested(Head); AddNested(Tail); + + AccentColour.BindValueChanged(colour => + { + bodyPiece.AccentColour = colour.NewValue; + Head.AccentColour.Value = colour.NewValue; + Tail.AccentColour.Value = colour.NewValue; + tickContainer.ForEach(t => t.AccentColour.Value = colour.NewValue); + }, true); } protected override void OnDirectionChanged(ValueChangedEvent e) @@ -83,20 +89,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables bodyPiece.Anchor = bodyPiece.Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; } - public override Color4 AccentColour - { - get => base.AccentColour; - set - { - base.AccentColour = value; - - bodyPiece.AccentColour = value; - Head.AccentColour = value; - Tail.AccentColour = value; - tickContainer.ForEach(t => t.AccentColour = value); - } - } - protected override void CheckForResult(bool userTriggered, double timeOffset) { if (Tail.AllJudged) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index 9a29273282..9b0322a6cd 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -3,7 +3,6 @@ using System; using osuTK; -using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -23,11 +22,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// public Func HoldStartTime; - private readonly Container glowContainer; - public DrawableHoldNoteTick(HoldNoteTick hitObject) : base(hitObject) { + Container glowContainer; + Anchor = Anchor.TopCentre; Origin = Anchor.TopCentre; @@ -53,23 +52,17 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } } }); - } - public override Color4 AccentColour - { - get => base.AccentColour; - set + AccentColour.BindValueChanged(colour => { - base.AccentColour = value; - glowContainer.EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, Radius = 2f, Roundness = 15f, - Colour = value.Opacity(0.3f) + Colour = colour.NewValue.Opacity(0.3f) }; - } + }, true); } protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index afd7777861..dccff7f6ac 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -3,7 +3,6 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; -using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Effects; using osu.Framework.Input.Bindings; @@ -30,6 +29,18 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Masking = true; AddInternal(headPiece = new NotePiece()); + + AccentColour.BindValueChanged(colour => + { + headPiece.AccentColour = colour.NewValue; + + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = colour.NewValue.Lighten(1f).Opacity(0.6f), + Radius = 10, + }; + }, true); } protected override void OnDirectionChanged(ValueChangedEvent e) @@ -39,23 +50,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables headPiece.Anchor = headPiece.Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; } - public override Color4 AccentColour - { - get => base.AccentColour; - set - { - base.AccentColour = value; - headPiece.AccentColour = AccentColour; - - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Colour = AccentColour.Lighten(1f).Opacity(0.6f), - Radius = 10, - }; - } - } - protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!userTriggered) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index c59bed4ea7..91dd236ab1 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Mania.UI /// The DrawableHitObject to add. public override void Add(DrawableHitObject hitObject) { - hitObject.AccentColour = AccentColour; + hitObject.AccentColour.Value = AccentColour; hitObject.OnNewResult += OnNewResult; HitObjectContainer.Add(hitObject); diff --git a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs index 0ec1fc38d2..48470add8b 100644 --- a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Mania.UI EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, - Colour = Interpolation.ValueAt(0.1f, judgedObject.AccentColour, Color4.White, 0, 1), + Colour = Interpolation.ValueAt(0.1f, judgedObject.AccentColour.Value, Color4.White, 0, 1), Radius = 100, }, Child = new Box diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index fef0bfdc2c..a83f1b5e56 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osuTK; using osu.Game.Rulesets.Scoring; -using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -98,19 +97,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindTo(HitObject.PositionBindable); stackHeightBindable.BindTo(HitObject.StackHeightBindable); scaleBindable.BindTo(HitObject.ScaleBindable); - } - public override Color4 AccentColour - { - get => base.AccentColour; - set + AccentColour.BindValueChanged(colour => { - base.AccentColour = value; - explode.Colour = AccentColour; - glow.Colour = AccentColour; - circle.Colour = AccentColour; - ApproachCircle.Colour = AccentColour; - } + explode.Colour = colour.NewValue; + glow.Colour = colour.NewValue; + circle.Colour = colour.NewValue; + ApproachCircle.Colour = colour.NewValue; + }, true); } protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 4533e08a2b..30cf09c9d7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.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; @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.SkinChanged(skin, allowFallback); if (HitObject is IHasComboInformation combo) - AccentColour = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; + AccentColour.Value = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; } protected virtual void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadeIn); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 4d67c9ae34..e06287f527 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -114,20 +114,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables pathBindable.BindTo(slider.PathBindable); pathBindable.BindValueChanged(_ => Body.Refresh()); - } - public override Color4 AccentColour - { - get => base.AccentColour; - set + AccentColour.BindValueChanged(colour => { - base.AccentColour = value; - Body.AccentColour = AccentColour; - Ball.AccentColour = AccentColour; + Body.AccentColour = colour.NewValue; + Ball.AccentColour = colour.NewValue; foreach (var drawableHitObject in NestedHitObjects) - drawableHitObject.AccentColour = AccentColour; - } + drawableHitObject.AccentColour.Value = colour.NewValue; + }, true); } public readonly Bindable Tracking = new Bindable(); @@ -167,9 +162,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.SkinChanged(skin, allowFallback); Body.BorderSize = skin.GetValue(s => s.SliderBorderSize) ?? SliderBody.DEFAULT_BORDER_SIZE; - Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? AccentColour; + Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? AccentColour.Value; Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Color4.White; - Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? AccentColour; + Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? AccentColour.Value; } protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index 72b648bfd0..ec294a1630 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -34,6 +34,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, CornerRadius = Size.X / 2, + Colour = AccentColour.Value, BorderThickness = 2, BorderColour = Color4.White, @@ -41,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Child = new Box { RelativeSizeAxes = Axes.Both, - Colour = AccentColour, + Colour = AccentColour.Value, Alpha = 0.3f, } }, restrictSize: false) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index e61fac679e..1fd6176f4f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -9,7 +9,6 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics.Primitives; using osu.Game.Audio; -using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; @@ -18,14 +17,14 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Objects.Drawables { - public abstract class DrawableHitObject : SkinReloadableDrawable, IHasAccentColour + public abstract class DrawableHitObject : SkinReloadableDrawable { public readonly HitObject HitObject; /// /// The colour used for various elements of this DrawableHitObject. /// - public virtual Color4 AccentColour { get; set; } = Color4.Gray; + public readonly Bindable AccentColour = new Bindable(Color4.Gray); // Todo: Rulesets should be overriding the resources instead, but we need to figure out where/when to apply overrides first protected virtual string SampleNamespace => null; From a631aac66435e3b6f0e2a3be851096a5c7ec74b4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 22 Jul 2019 15:01:01 +0900 Subject: [PATCH 1947/5608] Fix workingbeatmap's disposal potentially null-refing --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 37aa0024da..949a2aab6f 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -247,7 +247,7 @@ namespace osu.Game.Beatmaps // cancelling the beatmap load is safe for now since the retrieval is a synchronous // operation. if we add an async retrieval method this may need to be reconsidered. - beatmapCancellation.Cancel(); + beatmapCancellation?.Cancel(); total_count.Value--; } From 91f86adb66250b20062ebbe3fbe1d7aede2b1b2d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 15:05:56 +0900 Subject: [PATCH 1948/5608] Move DrawableHitObject state management to base class --- .../Drawable/DrawableCatchHitObject.cs | 10 --- .../Objects/Drawables/DrawableOsuHitObject.cs | 49 +---------- .../Objects/Drawables/DrawableHitObject.cs | 82 ++++++++++++++++--- 3 files changed, 75 insertions(+), 66 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 2ccb01a3e3..f5dd7cd255 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -3,12 +3,10 @@ using System; using osuTK; -using osuTK.Graphics; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; -using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.Objects.Drawable { @@ -60,14 +58,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable ApplyResult(r => r.Type = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss); } - protected override void SkinChanged(ISkinSource skin, bool allowFallback) - { - base.SkinChanged(skin, allowFallback); - - if (HitObject is IHasComboInformation combo) - AccentColour.Value = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; - } - protected override void UpdateState(ArmedState state) { using (BeginAbsoluteSequence(HitObject.StartTime - HitObject.TimePreempt)) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 30cf09c9d7..145be253bc 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -1,15 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Judgements; -using osu.Game.Rulesets.Scoring; -using osu.Game.Skinning; -using osuTK.Graphics; using osu.Game.Graphics.Containers; namespace osu.Game.Rulesets.Osu.Objects.Drawables @@ -39,49 +34,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void ClearInternal(bool disposeChildren = true) => shakeContainer.Clear(disposeChildren); protected override bool RemoveInternal(Drawable drawable) => shakeContainer.Remove(drawable); + protected override bool UseTransformStateManagement => true; + protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; - protected sealed override void UpdateState(ArmedState state) - { - double transformTime = HitObject.StartTime - HitObject.TimePreempt; - - base.ApplyTransformsAt(transformTime, true); - base.ClearTransformsAfter(transformTime, true); - - using (BeginAbsoluteSequence(transformTime, true)) - { - UpdatePreemptState(); - - var judgementOffset = Math.Min(HitObject.HitWindows.HalfWindowFor(HitResult.Miss), Result?.TimeOffset ?? 0); - - using (BeginDelayedSequence(HitObject.TimePreempt + judgementOffset, true)) - UpdateCurrentState(state); - } - } - - protected override void SkinChanged(ISkinSource skin, bool allowFallback) - { - base.SkinChanged(skin, allowFallback); - - if (HitObject is IHasComboInformation combo) - AccentColour.Value = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; - } - - protected virtual void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadeIn); - - protected virtual void UpdateCurrentState(ArmedState state) - { - } - - // Todo: At some point we need to move these to DrawableHitObject after ensuring that all other Rulesets apply - // transforms in the same way and don't rely on them not being cleared - public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null) - { - } - - public override void ApplyTransformsAt(double time, bool propagateChildren = false) - { - } + protected override void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadeIn); private OsuInputManager osuActionInputManager; internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 1fd6176f4f..06ea82746f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -79,10 +79,12 @@ namespace osu.Game.Rulesets.Objects.Drawables public override bool RemoveCompletedTransforms => false; protected override bool RequiresChildrenUpdate => true; - public override bool IsPresent => base.IsPresent || (State.Value == ArmedState.Idle && Clock?.CurrentTime >= LifetimeStart); + public override bool IsPresent => base.IsPresent || (state.Value == ArmedState.Idle && Clock?.CurrentTime >= LifetimeStart); public readonly Bindable State = new Bindable(); + private readonly Bindable state = new Bindable(); + protected DrawableHitObject(HitObject hitObject) { HitObject = hitObject; @@ -122,21 +124,81 @@ namespace osu.Game.Rulesets.Objects.Drawables { base.LoadComplete(); - State.ValueChanged += armed => + state.BindValueChanged(armed => { - UpdateState(armed.NewValue); + updateState(armed.NewValue); // apply any custom state overrides ApplyCustomUpdateState?.Invoke(this, armed.NewValue); if (armed.NewValue == ArmedState.Hit) PlaySamples(); - }; - - State.TriggerChange(); + }, true); } - protected abstract void UpdateState(ArmedState state); + protected virtual bool UseTransformStateManagement => false; + + private void updateState(ArmedState state) + { + if (UseTransformStateManagement) + { + double transformTime = HitObject.StartTime - InitialLifetimeOffset; + + base.ApplyTransformsAt(transformTime, true); + base.ClearTransformsAfter(transformTime, true); + + using (BeginAbsoluteSequence(transformTime, true)) + { + UpdatePreemptState(); + + var judgementOffset = Math.Min(HitObject.HitWindows?.HalfWindowFor(HitResult.Miss) ?? double.MaxValue, Result?.TimeOffset ?? 0); + + using (BeginDelayedSequence(InitialLifetimeOffset + judgementOffset, true)) + { + UpdateCurrentState(state); + State.Value = state; + } + } + } + else + { + State.Value = state; + } + + UpdateState(state); + } + + protected override void SkinChanged(ISkinSource skin, bool allowFallback) + { + base.SkinChanged(skin, allowFallback); + + if (HitObject is IHasComboInformation combo) + AccentColour.Value = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; + } + + protected virtual void UpdatePreemptState() + { + } + + protected virtual void UpdateCurrentState(ArmedState state) + { + } + + public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null) + { + if (!UseTransformStateManagement) + base.ClearTransformsAfter(time, propagateChildren, targetMember); + } + + public override void ApplyTransformsAt(double time, bool propagateChildren = false) + { + if (!UseTransformStateManagement) + base.ApplyTransformsAt(time, propagateChildren); + } + + protected virtual void UpdateState(ArmedState state) + { + } /// /// Bind to apply a custom state which can override the default implementation. @@ -163,7 +225,7 @@ namespace osu.Game.Rulesets.Objects.Drawables Result.TimeOffset = 0; Result.Type = HitResult.None; - State.Value = ArmedState.Idle; + state.Value = ArmedState.Idle; } } } @@ -243,11 +305,11 @@ namespace osu.Game.Rulesets.Objects.Drawables break; case HitResult.Miss: - State.Value = ArmedState.Miss; + state.Value = ArmedState.Miss; break; default: - State.Value = ArmedState.Hit; + state.Value = ArmedState.Hit; break; } From 6d889c8a37b3f83978fc5020c59857608ff5f5d2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 15:43:27 +0900 Subject: [PATCH 1949/5608] Revert unintended change --- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs index af733f16e1..575f2c92c5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.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; @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces RelativeSizeAxes = Axes.Both } } - }, confineMode: ConfineMode.NoScaling); + }); } } } From be170b412496834986c5d214dd4660b4d26115a2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 15:33:12 +0900 Subject: [PATCH 1950/5608] Naming and documentation improvements --- .../Objects/Drawables/DrawableHitCircle.cs | 6 +-- .../Objects/Drawables/DrawableOsuHitObject.cs | 2 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 4 +- .../Objects/Drawables/DrawableSlider.cs | 2 +- .../Objects/Drawables/DrawableSliderTick.cs | 4 +- .../Objects/Drawables/DrawableSpinner.cs | 6 +-- .../Objects/Drawables/DrawableHitObject.cs | 39 ++++++++++++------- 7 files changed, 37 insertions(+), 26 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index a83f1b5e56..d3d763daf3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -128,16 +128,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ApplyResult(r => r.Type = result); } - protected override void UpdatePreemptState() + protected override void UpdateInitialTransforms() { - base.UpdatePreemptState(); + base.UpdateInitialTransforms(); ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadeIn * 2, HitObject.TimePreempt)); ApproachCircle.ScaleTo(1.1f, HitObject.TimePreempt); ApproachCircle.Expire(true); } - protected override void UpdateCurrentState(ArmedState state) + protected override void UpdateStateTransforms(ArmedState state) { glow.FadeOut(400); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 145be253bc..8107d366b3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; - protected override void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadeIn); + protected override void UpdateInitialTransforms() => this.FadeIn(HitObject.TimeFadeIn); private OsuInputManager osuActionInputManager; internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index cce6dfe106..1e2c0ae59f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ApplyResult(r => r.Type = drawableSlider.Tracking.Value ? HitResult.Great : HitResult.Miss); } - protected override void UpdatePreemptState() + protected override void UpdateInitialTransforms() { animDuration = Math.Min(150, repeatPoint.SpanDuration / 2); @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ); } - protected override void UpdateCurrentState(ArmedState state) + protected override void UpdateStateTransforms(ArmedState state) { switch (state) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index e06287f527..d2089c05f3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -190,7 +190,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }); } - protected override void UpdateCurrentState(ArmedState state) + protected override void UpdateStateTransforms(ArmedState state) { Ball.FadeIn(); Ball.ScaleTo(HitObject.Scale); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index ec294a1630..3e128e9f15 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -55,13 +55,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ApplyResult(r => r.Type = Tracking ? HitResult.Great : HitResult.Miss); } - protected override void UpdatePreemptState() + protected override void UpdateInitialTransforms() { this.FadeOut().FadeIn(ANIM_DURATION); this.ScaleTo(0.5f).ScaleTo(1f, ANIM_DURATION * 4, Easing.OutElasticHalf); } - protected override void UpdateCurrentState(ArmedState state) + protected override void UpdateStateTransforms(ArmedState state) { switch (state) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 1794da54b7..a0bd301fdb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -196,9 +196,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables symbol.RotateTo(Disc.Rotation / 2, 500, Easing.OutQuint); } - protected override void UpdatePreemptState() + protected override void UpdateInitialTransforms() { - base.UpdatePreemptState(); + base.UpdateInitialTransforms(); circleContainer.ScaleTo(Spinner.Scale * 0.3f); circleContainer.ScaleTo(Spinner.Scale, HitObject.TimePreempt / 1.4f, Easing.OutQuint); @@ -213,7 +213,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables .ScaleTo(1, 500, Easing.OutQuint); } - protected override void UpdateCurrentState(ArmedState state) + protected override void UpdateStateTransforms(ArmedState state) { var sequence = this.Delay(Spinner.Duration).FadeOut(160); diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 06ea82746f..26d51e3809 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -118,8 +118,6 @@ namespace osu.Game.Rulesets.Objects.Drawables } } - protected override void ClearInternal(bool disposeChildren = true) => throw new InvalidOperationException($"Should never clear a {nameof(DrawableHitObject)}"); - protected override void LoadComplete() { base.LoadComplete(); @@ -136,8 +134,19 @@ namespace osu.Game.Rulesets.Objects.Drawables }, true); } + #region State / Transform Management + + /// + /// Enables automatic transform management of this hitobject. Implementation of transforms should be done in and only. Rewinding and removing previous states is done automatically. + /// + /// + /// Going forward, this is the preferred way of implementing s. Previous functionality + /// is offered as a compatibility layer until all rulesets have been migrated across. + /// protected virtual bool UseTransformStateManagement => false; + protected override void ClearInternal(bool disposeChildren = true) => throw new InvalidOperationException($"Should never clear a {nameof(DrawableHitObject)}"); + private void updateState(ArmedState state) { if (UseTransformStateManagement) @@ -149,13 +158,13 @@ namespace osu.Game.Rulesets.Objects.Drawables using (BeginAbsoluteSequence(transformTime, true)) { - UpdatePreemptState(); + UpdateInitialTransforms(); var judgementOffset = Math.Min(HitObject.HitWindows?.HalfWindowFor(HitResult.Miss) ?? double.MaxValue, Result?.TimeOffset ?? 0); using (BeginDelayedSequence(InitialLifetimeOffset + judgementOffset, true)) { - UpdateCurrentState(state); + UpdateStateTransforms(state); State.Value = state; } } @@ -168,19 +177,11 @@ namespace osu.Game.Rulesets.Objects.Drawables UpdateState(state); } - protected override void SkinChanged(ISkinSource skin, bool allowFallback) - { - base.SkinChanged(skin, allowFallback); - - if (HitObject is IHasComboInformation combo) - AccentColour.Value = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; - } - - protected virtual void UpdatePreemptState() + protected virtual void UpdateInitialTransforms() { } - protected virtual void UpdateCurrentState(ArmedState state) + protected virtual void UpdateStateTransforms(ArmedState state) { } @@ -200,6 +201,16 @@ namespace osu.Game.Rulesets.Objects.Drawables { } + #endregion + + protected override void SkinChanged(ISkinSource skin, bool allowFallback) + { + base.SkinChanged(skin, allowFallback); + + if (HitObject is IHasComboInformation combo) + AccentColour.Value = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; + } + /// /// Bind to apply a custom state which can override the default implementation. /// From c3b81bef4ab8e9160e73f0013067082d4239706f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 15:55:38 +0900 Subject: [PATCH 1951/5608] Flip default to the preferred method going forward --- .../Objects/Drawable/DrawableCatchHitObject.cs | 3 +++ .../Objects/Drawables/DrawableManiaHitObject.cs | 3 +++ .../Objects/Drawables/DrawableOsuHitObject.cs | 2 -- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs | 1 + .../Objects/Drawables/DrawableTaikoHitObject.cs | 2 ++ osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- 6 files changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index f5dd7cd255..a1279e8443 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -58,8 +58,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable ApplyResult(r => r.Type = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss); } + protected override bool UseTransformStateManagement => false; + protected override void UpdateState(ArmedState state) { + // TODO: update to use new state management. using (BeginAbsoluteSequence(HitObject.StartTime - HitObject.TimePreempt)) this.FadeIn(200); diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 0873f753be..db6b53e76d 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -58,8 +58,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables HitObject = hitObject; } + protected override bool UseTransformStateManagement => false; + protected override void UpdateState(ArmedState state) { + // TODO: update to use new state management. switch (state) { case ArmedState.Miss: diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 8107d366b3..579f16e0d4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -34,8 +34,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void ClearInternal(bool disposeChildren = true) => shakeContainer.Clear(disposeChildren); protected override bool RemoveInternal(Drawable drawable) => shakeContainer.Remove(drawable); - protected override bool UseTransformStateManagement => true; - protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; protected override void UpdateInitialTransforms() => this.FadeIn(HitObject.TimeFadeIn); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 4c8d5d5204..34ae7db984 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -94,6 +94,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void UpdateState(ArmedState state) { + // TODO: update to use new state management. var circlePiece = MainPiece as CirclePiece; circlePiece?.FlashBox.FinishTransforms(); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index bd45b52d7b..b46738c69a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -121,6 +121,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } + protected override bool UseTransformStateManagement => false; + // Normal and clap samples are handled by the drum protected override IEnumerable GetSamples() => HitObject.Samples.Where(s => s.Name != HitSampleInfo.HIT_NORMAL && s.Name != HitSampleInfo.HIT_CLAP); diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 26d51e3809..aef163cda7 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Going forward, this is the preferred way of implementing s. Previous functionality /// is offered as a compatibility layer until all rulesets have been migrated across. /// - protected virtual bool UseTransformStateManagement => false; + protected virtual bool UseTransformStateManagement => true; protected override void ClearInternal(bool disposeChildren = true) => throw new InvalidOperationException($"Should never clear a {nameof(DrawableHitObject)}"); From d4d286c9880a4ed3a08c9245e5f5491d87f5c9f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 16:08:38 +0900 Subject: [PATCH 1952/5608] Add full documentation --- .../Objects/Drawables/DrawableHitObject.cs | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index aef163cda7..d10f829dae 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -136,6 +136,11 @@ namespace osu.Game.Rulesets.Objects.Drawables #region State / Transform Management + /// + /// Bind to apply a custom state which can override the default implementation. + /// + public event Action ApplyCustomUpdateState; + /// /// Enables automatic transform management of this hitobject. Implementation of transforms should be done in and only. Rewinding and removing previous states is done automatically. /// @@ -177,26 +182,45 @@ namespace osu.Game.Rulesets.Objects.Drawables UpdateState(state); } + /// + /// Apply (generally fade-in) transforms. + /// The local drawable hierarchy is recursively delayed to for convenience. + /// + /// + /// This is called once before every . This is to ensure a good state in the case + /// the was negative and potentially altered the pre-hit transforms. + /// protected virtual void UpdateInitialTransforms() { } + /// + /// Apply transforms based on the current . Previous states are automatically cleared. + /// + /// The new armed state. protected virtual void UpdateStateTransforms(ArmedState state) { } public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null) { + // When we are using automatic state menement, parent calls to this should be blocked for safety. if (!UseTransformStateManagement) base.ClearTransformsAfter(time, propagateChildren, targetMember); } public override void ApplyTransformsAt(double time, bool propagateChildren = false) { + // When we are using automatic state menement, parent calls to this should be blocked for safety. if (!UseTransformStateManagement) base.ApplyTransformsAt(time, propagateChildren); } + /// + /// Legacy method to handle state changes. + /// Should generally not be used when is true; use instead. + /// + /// The new armed state. protected virtual void UpdateState(ArmedState state) { } @@ -211,11 +235,6 @@ namespace osu.Game.Rulesets.Objects.Drawables AccentColour.Value = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; } - /// - /// Bind to apply a custom state which can override the default implementation. - /// - public event Action ApplyCustomUpdateState; - /// /// Plays all the hit sounds for this . /// This is invoked automatically when this is hit. @@ -268,6 +287,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// /// This is only used as an optimisation to delay the initial update of this and may be tuned more aggressively if required. + /// It is indirectly used to decide the automatic transform offset provided to . /// A more accurate should be set inside for an state. /// protected virtual double InitialLifetimeOffset => 10000; From 07a0df7c4f8e12f6acd09f068c4d77a369165549 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 18:29:04 +0900 Subject: [PATCH 1953/5608] Fix bracket precedence --- osu.Game/Graphics/Backgrounds/Triangles.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 79f227fafe..2b68e8530d 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -214,7 +214,7 @@ namespace osu.Game.Graphics.Backgrounds { base.Draw(vertexAction); - if (vertexBatch == null || vertexBatch.Size != Source.AimCount && Source.AimCount > 0) + if (Source.AimCount > 0 && (vertexBatch == null || vertexBatch.Size != Source.AimCount)) { vertexBatch?.Dispose(); vertexBatch = new TriangleBatch(Source.AimCount, 1); From 3e95cb9145b935ce9eabcb2e91c092fa5053756a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 22 Jul 2019 14:35:18 +0300 Subject: [PATCH 1954/5608] Use bindable and disable button --- .../BeatmapSet/Buttons/FavouriteButton.cs | 16 ++++++++++++---- osu.Game/Overlays/BeatmapSet/Header.cs | 5 ++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 7207739646..5266623494 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osuTK; @@ -15,7 +16,8 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { public class FavouriteButton : HeaderButton { - public readonly Bindable Favourited = new Bindable(); + private readonly Bindable favourited = new Bindable(); + public readonly Bindable BeatmapSet = new Bindable(); [BackgroundDependencyLoader] private void load() @@ -54,7 +56,15 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, }); - Favourited.ValueChanged += favourited => + BeatmapSet.BindValueChanged(setInfo => + { + if (setInfo.NewValue?.OnlineInfo?.HasFavourited == null) + return; + + favourited.Value = setInfo.NewValue.OnlineInfo.HasFavourited; + }); + + favourited.ValueChanged += favourited => { if (favourited.NewValue) { @@ -67,8 +77,6 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons icon.Icon = FontAwesome.Regular.Heart; } }; - - Action = () => Favourited.Value = !Favourited.Value; } protected override void UpdateAfterChildren() diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index dd8a2f18c1..d5b6fbd8e6 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -161,7 +161,8 @@ namespace osu.Game.Overlays.BeatmapSet Margin = new MarginPadding { Top = 10 }, Children = new Drawable[] { - favouriteButton = new FavouriteButton(), + favouriteButton = new FavouriteButton + { BeatmapSet = { BindTarget = BeatmapSet } }, downloadButtonsContainer = new FillFlowContainer { RelativeSizeAxes = Axes.Both, @@ -246,8 +247,6 @@ namespace osu.Game.Overlays.BeatmapSet onlineStatusPill.Status = setInfo.NewValue.OnlineInfo.Status; downloadButtonsContainer.FadeIn(transition_duration); - - favouriteButton.Favourited.Value = setInfo.NewValue.OnlineInfo.HasFavourited; favouriteButton.FadeIn(transition_duration); updateDownloadButtons(); From 075ca3d8ea50df15918410798bed9aa2a9272df0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 22 Jul 2019 14:47:35 +0300 Subject: [PATCH 1955/5608] CI fix --- osu.Game/Overlays/BeatmapSet/Header.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index d5b6fbd8e6..260a989628 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -162,7 +162,9 @@ namespace osu.Game.Overlays.BeatmapSet Children = new Drawable[] { favouriteButton = new FavouriteButton - { BeatmapSet = { BindTarget = BeatmapSet } }, + { + BeatmapSet = { BindTarget = BeatmapSet } + }, downloadButtonsContainer = new FillFlowContainer { RelativeSizeAxes = Axes.Both, From cdf75b409854cbf941c7827906c9a805f851aaf5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 22:14:09 +0900 Subject: [PATCH 1956/5608] Public before private --- osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 5266623494..11f56bc163 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -16,9 +16,10 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { public class FavouriteButton : HeaderButton { - private readonly Bindable favourited = new Bindable(); public readonly Bindable BeatmapSet = new Bindable(); + private readonly Bindable favourited = new Bindable(); + [BackgroundDependencyLoader] private void load() { From 764513feea591b2d6e25e378e15913017d525b20 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 23:13:48 +0900 Subject: [PATCH 1957/5608] Fix code quality --- .../Select/Details/UserTopScoreContainer.cs | 46 ++++++++++--------- osu.Game/Screens/Select/SongSelect.cs | 6 ++- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index ba6751475e..cc2d2a3dae 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -31,30 +31,31 @@ namespace osu.Game.Screens.Select.Details { RelativeSizeAxes = Axes.X; Height = height; - Anchor = Anchor.BottomCentre; - Origin = Anchor.BottomCentre; + + Anchor = Anchor.BottomLeft; + Origin = Anchor.BottomLeft; + Children = new Drawable[] { contentContainer = new Container { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Height = height, - RelativeSizeAxes = Axes.X, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.Both, Children = new Drawable[] { new OsuSpriteText { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, Margin = new MarginPadding { Top = 5 }, Text = @"your personal best".ToUpper(), Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), }, scoreContainer = new Container { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, } @@ -62,22 +63,25 @@ namespace osu.Game.Screens.Select.Details } }; - Score.BindValueChanged(score => onScoreChanged(score.NewValue)); + Score.BindValueChanged(onScoreChanged); } - private void onScoreChanged(APILegacyUserTopScoreInfo score) + private void onScoreChanged(ValueChangedEvent score) { - if (score != null) + var newScore = score.NewValue; + + if (newScore == null) { - scoreContainer.Clear(); - scoreContainer.Add(new LeaderboardScore(score.Score, score.Position) - { - Action = () => ScoreSelected?.Invoke(score.Score) - }); - Show(); - } - else Hide(); + return; + } + + scoreContainer.Child = new LeaderboardScore(newScore.Score, newScore.Position) + { + Action = () => ScoreSelected?.Invoke(newScore.Score) + }; + + Show(); } protected override void PopIn() diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 209707d8fe..a3b87b5068 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -215,8 +215,10 @@ namespace osu.Game.Screens.Select }); } - BeatmapDetails.Leaderboard.ScoreSelected += s => this.Push(new SoloResults(s)); - BeatmapDetails.TopScore.ScoreSelected += s => this.Push(new SoloResults(s)); + void displayScore(ScoreInfo score) => this.Push(new SoloResults(score)); + + BeatmapDetails.Leaderboard.ScoreSelected += displayScore; + BeatmapDetails.TopScore.ScoreSelected += displayScore; } [BackgroundDependencyLoader(true)] From d83d93ee66fa26b2aabe1678d5c4704f1f74c0d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 23:21:07 +0900 Subject: [PATCH 1958/5608] Use asynchronous loading --- .../Select/Details/UserTopScoreContainer.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index cc2d2a3dae..1535aa3df1 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -10,6 +10,7 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Scoring; using System; +using System.Threading; namespace osu.Game.Screens.Select.Details { @@ -66,6 +67,8 @@ namespace osu.Game.Screens.Select.Details Score.BindValueChanged(onScoreChanged); } + private CancellationTokenSource loadScoreCancellation; + private void onScoreChanged(ValueChangedEvent score) { var newScore = score.NewValue; @@ -76,12 +79,17 @@ namespace osu.Game.Screens.Select.Details return; } - scoreContainer.Child = new LeaderboardScore(newScore.Score, newScore.Position) + scoreContainer.Clear(); + loadScoreCancellation?.Cancel(); + + LoadComponentAsync(new LeaderboardScore(newScore.Score, newScore.Position) { Action = () => ScoreSelected?.Invoke(newScore.Score) - }; - - Show(); + }, drawableScore => + { + scoreContainer.Child = drawableScore; + Show(); + }, (loadScoreCancellation = new CancellationTokenSource()).Token); } protected override void PopIn() From 95241165cce4724758f7267630b1755c748b1dbc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 23:26:11 +0900 Subject: [PATCH 1959/5608] Fix text alignment --- osu.Game/Screens/Select/Details/UserTopScoreContainer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 1535aa3df1..5a224756b9 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.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.Bindables; @@ -47,8 +47,8 @@ namespace osu.Game.Screens.Select.Details { new OsuSpriteText { - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Margin = new MarginPadding { Top = 5 }, Text = @"your personal best".ToUpper(), Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), From 5a6c8bfec9ff1563856ecd22936dc396e2360d90 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 23:28:17 +0900 Subject: [PATCH 1960/5608] Adjust transition to now show janky resize --- .../Select/Details/UserTopScoreContainer.cs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 5a224756b9..8e9df8bbb1 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.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.Bindables; @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Select.Details public class UserTopScoreContainer : VisibilityContainer { private const int height = 90; - private const int duration = 300; + private const int duration = 800; private readonly Container contentContainer; private readonly Container scoreContainer; @@ -92,16 +92,8 @@ namespace osu.Game.Screens.Select.Details }, (loadScoreCancellation = new CancellationTokenSource()).Token); } - protected override void PopIn() - { - this.ResizeHeightTo(height, duration, Easing.OutQuint); - contentContainer.FadeIn(duration, Easing.OutQuint); - } + protected override void PopIn() => this.ResizeHeightTo(height, duration / 4f, Easing.OutQuint).OnComplete(_ => contentContainer.FadeIn(duration, Easing.OutQuint)); - protected override void PopOut() - { - this.ResizeHeightTo(0, duration, Easing.OutQuint); - contentContainer.FadeOut(duration, Easing.OutQuint); - } + protected override void PopOut() => contentContainer.FadeOut(duration, Easing.OutQuint).OnComplete(_ => this.ResizeHeightTo(0)); } } From 2f111e6cf4ea5e56147a395c8bff06a3c7508b2c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 23:57:26 +0900 Subject: [PATCH 1961/5608] Fix incorrect corner radius --- .../Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs index a6c41cde72..0e9b534ca2 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical public class DrawableMostPlayedBeatmap : OsuHoverContainer { private const int cover_width = 100; - private const int corner_radius = 10; + private const int corner_radius = 6; private readonly BeatmapInfo beatmap; private readonly int playCount; From ee6fed5b33c219cada52a9628301d61767dabf57 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 22 Jul 2019 18:17:49 +0300 Subject: [PATCH 1962/5608] Use fixed height --- .../Sections/Historical/DrawableMostPlayedBeatmap.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs index 0e9b534ca2..0206c4e13b 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs @@ -22,6 +22,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { private const int cover_width = 100; private const int corner_radius = 6; + private const int height = 50; private readonly BeatmapInfo beatmap; private readonly int playCount; @@ -37,7 +38,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical Enabled.Value = true; //manually enabled, because we have no action RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; + Height = height; Masking = true; CornerRadius = corner_radius; @@ -60,15 +61,13 @@ namespace osu.Game.Overlays.Profile.Sections.Historical }, new Container { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Left = cover_width - corner_radius }, Children = new Drawable[] { new Container { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.Both, Masking = true, CornerRadius = corner_radius, Children = new Drawable[] @@ -76,8 +75,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical background = new Box { RelativeSizeAxes = Axes.Both }, new Container { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.Both, Padding = new MarginPadding(10), Children = new Drawable[] { From 94ed03548d7a401bc43be3b9ce602412efb6e662 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 22 Jul 2019 18:34:31 +0300 Subject: [PATCH 1963/5608] Hide top score at every leaderboard change --- osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index ee16123e20..f4a18e3b58 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -86,6 +86,8 @@ namespace osu.Game.Screens.Select.Leaderboards protected override APIRequest FetchScores(Action> scoresCallback) { + TopScore.Value = null; + if (Scope == BeatmapLeaderboardScope.Local) { var scores = scoreManager From 081355e3d158f74cc74ff061455e013ecb09406f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 22 Jul 2019 23:12:09 +0300 Subject: [PATCH 1964/5608] Use IHasText and simplify properties --- .../Graphics/Sprites/GlowingSpriteText.cs | 44 ++++--------------- 1 file changed, 8 insertions(+), 36 deletions(-) diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs index 546b8cae58..6c92d4cd06 100644 --- a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs @@ -9,50 +9,26 @@ using osuTK; namespace osu.Game.Graphics.Sprites { - public class GlowingSpriteText : Container + public class GlowingSpriteText : Container, IHasText { private readonly OsuSpriteText spriteText, blurredText; - private string text = string.Empty; - public string Text { - get => text; - set - { - text = value; - - spriteText.Text = text; - blurredText.Text = text; - } + get => spriteText.Text; + set => blurredText.Text = spriteText.Text = value; } - - private FontUsage font = OsuFont.Default.With(fixedWidth: true); - + public FontUsage Font { - get => font; - set - { - font = value.With(fixedWidth: true); - - spriteText.Font = font; - blurredText.Font = font; - } + get => spriteText.Font; + set => blurredText.Font = spriteText.Font = value.With(fixedWidth: true); } - private Vector2 textSize; - public Vector2 TextSize { - get => textSize; - set - { - textSize = value; - - spriteText.Size = textSize; - blurredText.Size = textSize; - } + get => spriteText.Size; + set => blurredText.Size = spriteText.Size = value; } public ColourInfo TextColour @@ -88,8 +64,6 @@ namespace osu.Game.Graphics.Sprites { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = font, - Text = text, Shadow = false, }, }, @@ -98,8 +72,6 @@ namespace osu.Game.Graphics.Sprites { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = font, - Text = text, Shadow = false, }, }; From 32e9547ce9d264b779f1d90b60bf765c1e41dd1c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 22 Jul 2019 23:16:54 +0300 Subject: [PATCH 1965/5608] Trim whitespace --- osu.Game/Graphics/Sprites/GlowingSpriteText.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs index 6c92d4cd06..74e387d60e 100644 --- a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs @@ -18,7 +18,7 @@ namespace osu.Game.Graphics.Sprites get => spriteText.Text; set => blurredText.Text = spriteText.Text = value; } - + public FontUsage Font { get => spriteText.Font; From ffcc1c62af5fcfed1d9ec7b3b322b4145d724d56 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 22 Jul 2019 23:22:39 +0300 Subject: [PATCH 1966/5608] simplify moving condition --- osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index bf0cd91321..927986159b 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -71,15 +71,7 @@ namespace osu.Game.Overlays.Toolbar // Scheduled to allow the flow layout to be computed before the line position is updated private void moveLineToCurrent() => ScheduleAfterChildren(() => { - foreach (var tabItem in TabContainer) - { - if (tabItem.Value.Equals(Current.Value)) - { - ModeButtonLine.MoveToX(tabItem.DrawPosition.X, !hasInitialPosition ? 0 : 200, Easing.OutQuint); - break; - } - } - + ModeButtonLine.MoveToX(SelectedTab.DrawPosition.X, !hasInitialPosition ? 0 : 200, Easing.OutQuint); hasInitialPosition = true; }); From 76b79f355443cba1b1f60fea02f24fae764e771d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 23 Jul 2019 01:14:45 +0300 Subject: [PATCH 1967/5608] Transform adjustments --- osu.Game/Screens/Select/Details/UserTopScoreContainer.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 8e9df8bbb1..c10f4d4fd4 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -42,7 +42,8 @@ namespace osu.Game.Screens.Select.Details { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + Height = height, Children = new Drawable[] { new OsuSpriteText @@ -94,6 +95,10 @@ namespace osu.Game.Screens.Select.Details protected override void PopIn() => this.ResizeHeightTo(height, duration / 4f, Easing.OutQuint).OnComplete(_ => contentContainer.FadeIn(duration, Easing.OutQuint)); - protected override void PopOut() => contentContainer.FadeOut(duration, Easing.OutQuint).OnComplete(_ => this.ResizeHeightTo(0)); + protected override void PopOut() + { + this.ResizeHeightTo(0); + contentContainer.FadeOut(duration / 4f, Easing.OutQuint); + } } } From d5ee4cbc9cc5d3bae002d6e6357296ebc9be5b1c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 Jul 2019 13:11:06 +0900 Subject: [PATCH 1968/5608] Move TouchDevice mod to new "system" category --- osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs | 2 ++ osu.Game/Rulesets/Mods/ModType.cs | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs index 571756d056..f0db548e74 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs @@ -11,6 +11,8 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Acronym => "TD"; public override double ScoreMultiplier => 1; + public override ModType Type => ModType.System; + public override bool Ranked => true; } } diff --git a/osu.Game/Rulesets/Mods/ModType.cs b/osu.Game/Rulesets/Mods/ModType.cs index cd649728cf..e3c82e42f5 100644 --- a/osu.Game/Rulesets/Mods/ModType.cs +++ b/osu.Game/Rulesets/Mods/ModType.cs @@ -9,6 +9,7 @@ namespace osu.Game.Rulesets.Mods DifficultyIncrease, Conversion, Automation, - Fun + Fun, + System } } From f8feac792c4cc1da31de38e2ebb4b48d74633439 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 Jul 2019 13:12:17 +0900 Subject: [PATCH 1969/5608] Return TouchDevice in GetAllMods response --- osu.Game.Rulesets.Osu/OsuRuleset.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index baa4aff413..8df0f77629 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -138,6 +138,12 @@ namespace osu.Game.Rulesets.Osu new MultiMod(new ModWindUp(), new ModWindDown()), }; + case ModType.System: + return new Mod[] + { + new OsuModTouchDevice(), + }; + default: return new Mod[] { }; } From e628e44d8e7a45ea961481dafe8c02a92b965209 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 23 Jul 2019 13:25:03 +0900 Subject: [PATCH 1970/5608] update comment --- 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 c1020e6340..a3fe9bb8f5 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -36,7 +36,7 @@ namespace osu.Game.Graphics.UserInterface protected override bool HandleAction(PlatformAction action) { - // Allow delete to be handled locally + // Shift-delete is unnecessary for search inputs, so its propagated up the input queue. if (action.ActionType == PlatformActionType.CharNext && action.ActionMethod == PlatformActionMethod.Delete) return false; From 292bd22f92656b972318ce766b4ff6d0440c92f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 Jul 2019 13:38:05 +0900 Subject: [PATCH 1971/5608] Allow multiple instances of osu! when running under debug --- osu.Desktop/Program.cs | 45 ++++++++++++++++++++++++------------------ osu.Game/OsuGame.cs | 3 ++- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index cb488fea52..141b2cdbbc 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -29,29 +29,36 @@ namespace osu.Desktop if (!host.IsPrimaryInstance) { - var importer = new ArchiveImportIPCChannel(host); - // Restore the cwd so relative paths given at the command line work correctly - Directory.SetCurrentDirectory(cwd); - - foreach (var file in args) + if (args.Length > 0 && args[0].Contains('.')) // easy way to check for a file import in args { - Console.WriteLine(@"Importing {0}", file); - if (!importer.ImportAsync(Path.GetFullPath(file)).Wait(3000)) - throw new TimeoutException(@"IPC took too long to send"); + var importer = new ArchiveImportIPCChannel(host); + // Restore the cwd so relative paths given at the command line work correctly + Directory.SetCurrentDirectory(cwd); + + foreach (var file in args) + { + Console.WriteLine(@"Importing {0}", file); + if (!importer.ImportAsync(Path.GetFullPath(file)).Wait(3000)) + throw new TimeoutException(@"IPC took too long to send"); + } + + return 0; } + + // we want to allow multiple instances to be started when in debug. + if (!DebugUtils.IsDebugBuild) + return 0; } - else - { - switch (args.FirstOrDefault() ?? string.Empty) - { - default: - host.Run(new OsuGameDesktop(args)); - break; - case "--tournament": - host.Run(new TournamentGame()); - break; - } + switch (args.FirstOrDefault() ?? string.Empty) + { + default: + host.Run(new OsuGameDesktop(args)); + break; + + case "--tournament": + host.Run(new TournamentGame()); + break; } return 0; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 2a484fc122..41b67f343a 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -20,6 +20,7 @@ using System.Threading; using System.Threading.Tasks; using osu.Framework.Audio; using osu.Framework.Bindables; +using osu.Framework.Development; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; @@ -153,7 +154,7 @@ namespace osu.Game { this.frameworkConfig = frameworkConfig; - if (!Host.IsPrimaryInstance) + if (!Host.IsPrimaryInstance && !DebugUtils.IsDebugBuild) { Logger.Log(@"osu! does not support multiple running instances.", LoggingTarget.Runtime, LogLevel.Error); Environment.Exit(0); From 776757545d15ae536f223afeb8e6ada4d8bab89b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 23 Jul 2019 15:17:02 +0900 Subject: [PATCH 1972/5608] Fix FTB causing flashlight to block vision correctly --- .../Vertices/PositionAndColourVertex.cs | 26 +++++++++++++++++++ osu.Game/Rulesets/Mods/ModFlashlight.cs | 12 ++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs diff --git a/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs b/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs new file mode 100644 index 0000000000..8714138322 --- /dev/null +++ b/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Runtime.InteropServices; +using osu.Framework.Graphics.OpenGL.Vertices; +using osuTK; +using osuTK.Graphics; +using osuTK.Graphics.ES30; + +namespace osu.Game.Graphics.OpenGL.Vertices +{ + [StructLayout(LayoutKind.Sequential)] + public struct PositionAndColourVertex : IEquatable, IVertex + { + [VertexMember(2, VertexAttribPointerType.Float)] + public Vector2 Position; + + [VertexMember(4, VertexAttribPointerType.Float)] + public Color4 Colour; + + public bool Equals(PositionAndColourVertex other) + => Position.Equals(other.Position) + && Colour.Equals(other.Colour); + } +} diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 405d21c711..cb0c2fafe5 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Batches; using osu.Framework.Graphics.OpenGL.Vertices; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Shaders; @@ -13,6 +14,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps.Timing; using osu.Game.Graphics; +using osu.Game.Graphics.OpenGL.Vertices; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; @@ -153,9 +155,17 @@ namespace osu.Game.Rulesets.Mods private Vector2 flashlightSize; private float flashlightDim; + private readonly VertexBatch quadBatch = new QuadBatch(1, 1); + private readonly Action addAction; + public FlashlightDrawNode(Flashlight source) : base(source) { + addAction = v => quadBatch.Add(new PositionAndColourVertex + { + Position = v.Position, + Colour = v.Colour + }); } public override void ApplyState() @@ -179,7 +189,7 @@ namespace osu.Game.Rulesets.Mods shader.GetUniform("flashlightSize").UpdateValue(ref flashlightSize); shader.GetUniform("flashlightDim").UpdateValue(ref flashlightDim); - DrawQuad(Texture.WhitePixel, screenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction); + DrawQuad(Texture.WhitePixel, screenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: addAction); shader.Unbind(); } From 4d8e2a78d119c79907da53197d9bd0abc5736889 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 23 Jul 2019 15:31:09 +0900 Subject: [PATCH 1973/5608] update with new framework changes and update comment --- osu.Game/Graphics/UserInterface/SearchTextBox.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index a3fe9bb8f5..4b49174e65 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -34,13 +34,14 @@ namespace osu.Game.Graphics.UserInterface PlaceholderText = "type to search"; } - protected override bool HandleAction(PlatformAction action) + public override bool OnPressed(PlatformAction action) { - // Shift-delete is unnecessary for search inputs, so its propagated up the input queue. + // Shift-delete, used in MacOS for character deletion, is unnecessary here as arrow keys are blocked by HandleLeftRightArrows + // Avoid handling it here to allow other components to potentially consume the shortcut if (action.ActionType == PlatformActionType.CharNext && action.ActionMethod == PlatformActionMethod.Delete) return false; - return base.HandleAction(action); + return base.OnPressed(action); } protected override bool OnKeyDown(KeyDownEvent e) From 5e72ed0d1276dd149d2d69dc6da90f308a047e96 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 23 Jul 2019 15:35:12 +0900 Subject: [PATCH 1974/5608] Fix potential nullref --- osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 927986159b..2c79f5bc0e 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -71,8 +71,11 @@ namespace osu.Game.Overlays.Toolbar // Scheduled to allow the flow layout to be computed before the line position is updated private void moveLineToCurrent() => ScheduleAfterChildren(() => { - ModeButtonLine.MoveToX(SelectedTab.DrawPosition.X, !hasInitialPosition ? 0 : 200, Easing.OutQuint); - hasInitialPosition = true; + if (SelectedTab != null) + { + ModeButtonLine.MoveToX(SelectedTab.DrawPosition.X, !hasInitialPosition ? 0 : 200, Easing.OutQuint); + hasInitialPosition = true; + } }); public override bool HandleNonPositionalInput => !Current.Disabled && base.HandleNonPositionalInput; From 704fe2d6554f5138d994d5528b10be3831cc4459 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 Jul 2019 16:01:05 +0900 Subject: [PATCH 1975/5608] Remove text shadow in chat --- osu.Game/Overlays/Chat/ChatLine.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index e29216dffd..2576b38ec8 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -85,6 +85,7 @@ namespace osu.Game.Overlays.Chat Drawable effectedUsername = username = new OsuSpriteText { + Shadow = false, Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length], Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true) }; @@ -133,6 +134,7 @@ namespace osu.Game.Overlays.Chat { timestamp = new OsuSpriteText { + Shadow = false, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(size: TextSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true) @@ -155,6 +157,8 @@ namespace osu.Game.Overlays.Chat { contentFlow = new LinkFlowContainer(t => { + t.Shadow = false; + if (Message.IsAction) { t.Font = OsuFont.GetFont(italics: true); From e81ef4bf339e59307f1cb47a12e9097e580afd47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 Jul 2019 16:44:19 +0900 Subject: [PATCH 1976/5608] Rewrite comment --- osu.Game/Graphics/UserInterface/SearchTextBox.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index 4b49174e65..c3efe2ed45 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -36,8 +36,9 @@ namespace osu.Game.Graphics.UserInterface public override bool OnPressed(PlatformAction action) { - // Shift-delete, used in MacOS for character deletion, is unnecessary here as arrow keys are blocked by HandleLeftRightArrows - // Avoid handling it here to allow other components to potentially consume the shortcut + // 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) + // 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 8220a513102a6128fc6e3c11383b365029b4aa4f Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 23 Jul 2019 17:59:50 +0900 Subject: [PATCH 1977/5608] Make backbutton handle global input last --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 669fd62e45..ff006efdd6 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Bindings; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Input.Bindings { @@ -55,8 +56,11 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { InputKey.Control, InputKey.Minus }, GlobalAction.DecreaseScrollSpeed), }; + /// + /// Make sure that the handles global input first, and that handles global input last. + /// protected override IEnumerable KeyBindingInputQueue => - handler == null ? base.KeyBindingInputQueue : base.KeyBindingInputQueue.Prepend(handler); + (handler == null ? base.KeyBindingInputQueue : base.KeyBindingInputQueue.Prepend(handler)).OrderBy(d => d is BackButton); } public enum GlobalAction From b1a9ce85e7fbaaac4ff9962cb71be382d4853a0f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 23 Jul 2019 20:30:47 +0900 Subject: [PATCH 1978/5608] Fix ticks being given an extra colour --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index ec294a1630..dafdcf3b82 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -34,11 +34,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, CornerRadius = Size.X / 2, - Colour = AccentColour.Value, - BorderThickness = 2, BorderColour = Color4.White, - Child = new Box { RelativeSizeAxes = Axes.Both, From 74b09c72fa044d9fc0f21f19f03da216df2bf291 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 23 Jul 2019 21:08:41 +0900 Subject: [PATCH 1979/5608] Refactor state updates to convert State into an IBindable --- .../Objects/Drawables/DrawableHitObject.cs | 46 +++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index d10f829dae..3253302c71 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -79,12 +79,12 @@ namespace osu.Game.Rulesets.Objects.Drawables public override bool RemoveCompletedTransforms => false; protected override bool RequiresChildrenUpdate => true; - public override bool IsPresent => base.IsPresent || (state.Value == ArmedState.Idle && Clock?.CurrentTime >= LifetimeStart); - - public readonly Bindable State = new Bindable(); + public override bool IsPresent => base.IsPresent || (State.Value == ArmedState.Idle && Clock?.CurrentTime >= LifetimeStart); private readonly Bindable state = new Bindable(); + public IBindable State => state; + protected DrawableHitObject(HitObject hitObject) { HitObject = hitObject; @@ -121,17 +121,7 @@ namespace osu.Game.Rulesets.Objects.Drawables protected override void LoadComplete() { base.LoadComplete(); - - state.BindValueChanged(armed => - { - updateState(armed.NewValue); - - // apply any custom state overrides - ApplyCustomUpdateState?.Invoke(this, armed.NewValue); - - if (armed.NewValue == ArmedState.Hit) - PlaySamples(); - }, true); + updateState(ArmedState.Idle, true); } #region State / Transform Management @@ -152,8 +142,17 @@ namespace osu.Game.Rulesets.Objects.Drawables protected override void ClearInternal(bool disposeChildren = true) => throw new InvalidOperationException($"Should never clear a {nameof(DrawableHitObject)}"); - private void updateState(ArmedState state) + private void updateState(ArmedState newState, bool force = false) { + if (State.Value == newState && !force) + return; + + // apply any custom state overrides + ApplyCustomUpdateState?.Invoke(this, newState); + + if (newState == ArmedState.Hit) + PlaySamples(); + if (UseTransformStateManagement) { double transformTime = HitObject.StartTime - InitialLifetimeOffset; @@ -169,17 +168,15 @@ namespace osu.Game.Rulesets.Objects.Drawables using (BeginDelayedSequence(InitialLifetimeOffset + judgementOffset, true)) { - UpdateStateTransforms(state); - State.Value = state; + UpdateStateTransforms(newState); + state.Value = newState; } } } else - { - State.Value = state; - } + state.Value = newState; - UpdateState(state); + UpdateState(newState); } /// @@ -255,7 +252,8 @@ namespace osu.Game.Rulesets.Objects.Drawables Result.TimeOffset = 0; Result.Type = HitResult.None; - state.Value = ArmedState.Idle; + + updateState(ArmedState.Idle); } } } @@ -336,11 +334,11 @@ namespace osu.Game.Rulesets.Objects.Drawables break; case HitResult.Miss: - state.Value = ArmedState.Miss; + updateState(ArmedState.Miss); break; default: - state.Value = ArmedState.Hit; + updateState(ArmedState.Hit); break; } From 4e7e2d1d5230b76bb25edfbceffb8b51c060f475 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 23 Jul 2019 21:15:55 +0900 Subject: [PATCH 1980/5608] Adjust comments --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 3253302c71..1d9d885527 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -180,7 +180,7 @@ namespace osu.Game.Rulesets.Objects.Drawables } /// - /// Apply (generally fade-in) transforms. + /// Apply (generally fade-in) transforms leading into the start time. /// The local drawable hierarchy is recursively delayed to for convenience. /// /// @@ -201,14 +201,14 @@ namespace osu.Game.Rulesets.Objects.Drawables public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null) { - // When we are using automatic state menement, parent calls to this should be blocked for safety. + // When we are using automatic state management, parent calls to this should be blocked for safety. if (!UseTransformStateManagement) base.ClearTransformsAfter(time, propagateChildren, targetMember); } public override void ApplyTransformsAt(double time, bool propagateChildren = false) { - // When we are using automatic state menement, parent calls to this should be blocked for safety. + // When we are using automatic state management, parent calls to this should be blocked for safety. if (!UseTransformStateManagement) base.ApplyTransformsAt(time, propagateChildren); } From 2610ee2abb4a63603e4afb1b7c9468a59d43fb1b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 Jul 2019 21:39:10 +0900 Subject: [PATCH 1981/5608] 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 b9451fc744..b24493665e 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index d90b1d36e1..c05cc6f9dd 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index fa2521a19e..3b18039600 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 38559685a96ec763291aff3bed423696462b69cf Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 24 Jul 2019 12:47:41 +0900 Subject: [PATCH 1982/5608] proxy backbutton instead --- osu.Game/OsuGame.cs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 2a484fc122..4c7fc688ab 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -394,6 +394,16 @@ namespace osu.Game AddRange(new Drawable[] { + backButton = new BackButton + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Action = () => + { + if ((screenStack.CurrentScreen as IOsuScreen)?.AllowBackButton == true) + screenStack.Exit(); + } + }, new VolumeControlReceptor { RelativeSizeAxes = Axes.Both, @@ -403,19 +413,10 @@ namespace osu.Game screenContainer = new ScalingContainer(ScalingMode.ExcludeOverlays) { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + Children = new[] { screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, - backButton = new BackButton - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Action = () => - { - if ((screenStack.CurrentScreen as IOsuScreen)?.AllowBackButton == true) - screenStack.Exit(); - } - }, + backButton.CreateProxy(), logoContainer = new Container { RelativeSizeAxes = Axes.Both }, } }, From da3dc610baf632279149814ac500f7d47883c4d3 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 24 Jul 2019 12:52:18 +0900 Subject: [PATCH 1983/5608] revert globalaction changes --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index ff006efdd6..669fd62e45 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -7,7 +7,6 @@ using System.Linq; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Bindings; -using osu.Game.Graphics.UserInterface; namespace osu.Game.Input.Bindings { @@ -56,11 +55,8 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { InputKey.Control, InputKey.Minus }, GlobalAction.DecreaseScrollSpeed), }; - /// - /// Make sure that the handles global input first, and that handles global input last. - /// protected override IEnumerable KeyBindingInputQueue => - (handler == null ? base.KeyBindingInputQueue : base.KeyBindingInputQueue.Prepend(handler)).OrderBy(d => d is BackButton); + handler == null ? base.KeyBindingInputQueue : base.KeyBindingInputQueue.Prepend(handler); } public enum GlobalAction From 136f3b8b6b1430605ebe10391d9f40503d505a52 Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Wed, 24 Jul 2019 20:49:35 +0800 Subject: [PATCH 1984/5608] Add iOS import osu! files --- osu.iOS/AppDelegate.cs | 19 ++++++++++++++++++- osu.iOS/Info.plist | 13 +++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs index 058e246ed8..93eca8caa1 100644 --- a/osu.iOS/AppDelegate.cs +++ b/osu.iOS/AppDelegate.cs @@ -1,15 +1,32 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Threading.Tasks; using Foundation; using osu.Framework.iOS; using osu.Game; +using UIKit; namespace osu.iOS { [Register("AppDelegate")] public class AppDelegate : GameAppDelegate { - protected override Framework.Game CreateGame() => new OsuGameIOS(); + private OsuGameIOS IOSGame; + + protected override Framework.Game CreateGame() + { + //Save OsuGameIOS for Import + IOSGame = new OsuGameIOS(); + return IOSGame; + } + + public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation) + { + //Open in Application + Task.Run(() => IOSGame.Import(url.Path)); + + return true; + } } } diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index d7992353cf..f6fc768632 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -40,5 +40,18 @@ XSAppIconAssets Assets.xcassets/AppIcon.appiconset + CFBundleDocumentTypes + + + LSHandlerRank + Owner + CFBundleTypeName + public.item + LSItemContentTypes + + public.item + + + From 433f192214da43c206a47296531cadb2c76910f1 Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Wed, 24 Jul 2019 21:51:01 +0800 Subject: [PATCH 1985/5608] Add iOS custom UTIs --- osu.iOS/Info.plist | 56 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index f6fc768632..0775d1522d 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -40,16 +40,68 @@ XSAppIconAssets Assets.xcassets/AppIcon.appiconset + UTExportedTypeDeclarations + + + UTTypeConformsTo + + + + UTTypeIdentifier + sh.ppy.osu.items + UTTypeTagSpecification + + + + UTTypeConformsTo + + sh.ppy.osu.items + + UTTypeIdentifier + sh.ppy.osu.osr + UTTypeTagSpecification + + public.filename-extension + osr + + + + UTTypeConformsTo + + sh.ppy.osu.items + + UTTypeIdentifier + sh.ppy.osu.osk + UTTypeTagSpecification + + public.filename-extension + osk + + + + UTTypeConformsTo + + sh.ppy.osu.items + + UTTypeIdentifier + sh.ppy.osu.osz + UTTypeTagSpecification + + public.filename-extension + osz + + + CFBundleDocumentTypes LSHandlerRank Owner CFBundleTypeName - public.item + Supported osu! files LSItemContentTypes - public.item + sh.ppy.osu.items From 78a8a6490e50a15eb8aad5f83675f1c741e6ea30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20H=C3=BCbner?= Date: Wed, 24 Jul 2019 17:17:29 +0200 Subject: [PATCH 1986/5608] close chat tabs with middle mouse button --- .../Overlays/Chat/Tabs/ChannelSelectorTabItem.cs | 3 +++ osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs index 7386bffb1a..f6533be551 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Online.Chat; @@ -39,5 +40,7 @@ namespace osu.Game.Overlays.Chat.Tabs Name = "+"; } } + + protected override bool OnMouseUp(MouseUpEvent e) => false; } } diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs index 7f820e4ff7..859ca30d7f 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs @@ -16,6 +16,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; using osuTK; using osuTK.Graphics; +using osuTK.Input; namespace osu.Game.Overlays.Chat.Tabs { @@ -138,6 +139,17 @@ namespace osu.Game.Overlays.Chat.Tabs updateState(); } + protected override bool OnMouseUp(MouseUpEvent e) + { + if (e.Button == MouseButton.Middle) + { + CloseButton.Action(); + return true; + } + + return false; + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { From bbcc8f072116e52e5105bc241166a4396d3b9af5 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 25 Jul 2019 11:11:20 +0900 Subject: [PATCH 1987/5608] Add new container level and unblock footer --- osu.Game/OsuGame.cs | 33 +++++++++++++++++++------------ osu.Game/Screens/Select/Footer.cs | 4 ++-- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 6fb76c640f..a248da4304 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -395,16 +395,6 @@ namespace osu.Game AddRange(new Drawable[] { - backButton = new BackButton - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Action = () => - { - if ((screenStack.CurrentScreen as IOsuScreen)?.AllowBackButton == true) - screenStack.Exit(); - } - }, new VolumeControlReceptor { RelativeSizeAxes = Axes.Both, @@ -416,9 +406,26 @@ namespace osu.Game RelativeSizeAxes = Axes.Both, Children = new[] { - screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, - backButton.CreateProxy(), - logoContainer = new Container { RelativeSizeAxes = Axes.Both }, + backButton = new BackButton + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Action = () => + { + if ((screenStack.CurrentScreen as IOsuScreen)?.AllowBackButton == true) + screenStack.Exit(); + } + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Children = new[] + { + screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, + backButton.CreateProxy(), + logoContainer = new Container { RelativeSizeAxes = Axes.Both }, + } + } } }, overlayContent = new Container { RelativeSizeAxes = Axes.Both }, diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index 0680711f1c..0043acb818 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -104,8 +104,8 @@ namespace osu.Game.Screens.Select updateModeLight(); } - protected override bool OnMouseDown(MouseDownEvent e) => true; + protected override bool OnMouseDown(MouseDownEvent e) => false; - protected override bool OnClick(ClickEvent e) => true; + protected override bool OnClick(ClickEvent e) => false; } } From c16af882993b86a0ef91d7813ba5c551dbced753 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 19 Jul 2019 11:47:27 +0900 Subject: [PATCH 1988/5608] Start exploding animation earlier (don't wait for flash) --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index d3d763daf3..001003155d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -169,6 +169,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables .FadeOut(100); explode.FadeIn(flash_in); + explodeContainer.ScaleTo(1.5f, 400, Easing.OutQuad); using (BeginDelayedSequence(flash_in, true)) { @@ -178,7 +179,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables number.FadeOut(); this.FadeOut(800); - explodeContainer.ScaleTo(1.5f, 400, Easing.OutQuad); } Expire(); From e63c97b306b712db8b2159d8bfd3acef76006e81 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 25 Jul 2019 11:20:24 +0900 Subject: [PATCH 1989/5608] remove unnecessary overrides --- osu.Game/Screens/Select/Footer.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index 0043acb818..a1384f19b4 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -103,9 +103,5 @@ namespace osu.Game.Screens.Select updateModeLight(); } - - protected override bool OnMouseDown(MouseDownEvent e) => false; - - protected override bool OnClick(ClickEvent e) => false; } } From 7275beaf1aedbcb55fce70deaab3f075762ea153 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 19 Jul 2019 18:38:24 +0900 Subject: [PATCH 1990/5608] Remove unnecessary type specification from SkinnableDrawable --- osu.Game/Skinning/SkinnableDrawable.cs | 22 ++++++---------------- osu.Game/Skinning/SkinnableSprite.cs | 5 +++-- osu.Game/Skinning/SkinnableSpriteText.cs | 2 +- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/osu.Game/Skinning/SkinnableDrawable.cs b/osu.Game/Skinning/SkinnableDrawable.cs index eb0508b568..0c635a3d2f 100644 --- a/osu.Game/Skinning/SkinnableDrawable.cs +++ b/osu.Game/Skinning/SkinnableDrawable.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; @@ -8,23 +8,13 @@ using osuTK; namespace osu.Game.Skinning { - public class SkinnableDrawable : SkinnableDrawable - { - public SkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) - : base(name, defaultImplementation, allowFallback, confineMode) - { - } - } - /// /// A drawable which can be skinned via an . /// - /// The type of drawable. - public class SkinnableDrawable : SkinReloadableDrawable - where T : Drawable + public class SkinnableDrawable : SkinReloadableDrawable { /// - /// The displayed component. May or may not be a type- member. + /// The displayed component. /// protected Drawable Drawable { get; private set; } @@ -39,7 +29,7 @@ namespace osu.Game.Skinning /// A function to create the default skin implementation of this element. /// A conditional to decide whether to allow fallback to the default implementation if a skinned element is not present. /// How (if at all) the should be resize to fit within our own bounds. - public SkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + public SkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) : this(name, allowFallback, confineMode) { createDefault = defaultImplementation; @@ -54,13 +44,13 @@ namespace osu.Game.Skinning RelativeSizeAxes = Axes.Both; } - private readonly Func createDefault; + private readonly Func createDefault; private readonly Cached scaling = new Cached(); private bool isDefault; - protected virtual T CreateDefault(string name) => createDefault(name); + protected virtual Drawable CreateDefault(string name) => createDefault(name); /// /// Whether to apply size restrictions (specified via ) to the default implementation. diff --git a/osu.Game/Skinning/SkinnableSprite.cs b/osu.Game/Skinning/SkinnableSprite.cs index 1716ec71de..07ba48d6ae 100644 --- a/osu.Game/Skinning/SkinnableSprite.cs +++ b/osu.Game/Skinning/SkinnableSprite.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; @@ -11,7 +12,7 @@ namespace osu.Game.Skinning /// /// A skinnable element which uses a stable sprite and can therefore share implementation logic. /// - public class SkinnableSprite : SkinnableDrawable + public class SkinnableSprite : SkinnableDrawable { protected override bool ApplySizeRestrictionsToDefault => true; @@ -23,6 +24,6 @@ namespace osu.Game.Skinning { } - protected override Sprite CreateDefault(string name) => new Sprite { Texture = textures.Get(name) }; + protected override Drawable CreateDefault(string name) => new Sprite { Texture = textures.Get(name) }; } } diff --git a/osu.Game/Skinning/SkinnableSpriteText.cs b/osu.Game/Skinning/SkinnableSpriteText.cs index d12a6f74f7..5af6df15e1 100644 --- a/osu.Game/Skinning/SkinnableSpriteText.cs +++ b/osu.Game/Skinning/SkinnableSpriteText.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Skinning { - public class SkinnableSpriteText : SkinnableDrawable, IHasText + public class SkinnableSpriteText : SkinnableDrawable, IHasText { public SkinnableSpriteText(string name, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) : base(name, defaultImplementation, allowFallback, confineMode) From c989185774497a13ef6cf977fb58052b56722ec3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Jul 2019 19:32:24 +0900 Subject: [PATCH 1991/5608] Fix incorrect approach circle scaling --- .../Objects/Drawables/DrawableHitCircle.cs | 2 +- .../Drawables/Pieces/ApproachCircle.cs | 22 ++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index d3d763daf3..9b8627d8f1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -133,7 +133,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.UpdateInitialTransforms(); ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadeIn * 2, HitObject.TimePreempt)); - ApproachCircle.ScaleTo(1.1f, HitObject.TimePreempt); + ApproachCircle.ScaleTo(1f, HitObject.TimePreempt); ApproachCircle.Expire(true); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs index 9981585f9e..5813197336 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; using osu.Game.Skinning; +using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { @@ -24,7 +25,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces [BackgroundDependencyLoader] private void load(TextureStore textures) { - Child = new SkinnableSprite("Play/osu/approachcircle"); + Child = new SkinnableApproachCircle(); + } + + private class SkinnableApproachCircle : SkinnableSprite + { + public SkinnableApproachCircle() + : base("Play/osu/approachcircle") + { + } + + protected override Drawable CreateDefault(string name) + { + var drawable = base.CreateDefault(name); + + // account for the sprite being used for the default approach circle being taken from stable, + // when hitcircles have 5px padding on each size. this should be removed if we update the sprite. + drawable.Scale = new Vector2(128 / 118f); + + return drawable; + } } } } From 6ef3c71e22c430039cdfab297a0095bfc48a20a6 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 25 Jul 2019 11:31:46 +0900 Subject: [PATCH 1992/5608] remove unused using --- osu.Game/Screens/Select/Footer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index a1384f19b4..71641cab5d 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -9,7 +9,6 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Select From 69844e6c24e973a74024be87ba654f16e9958221 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jul 2019 12:18:18 +0900 Subject: [PATCH 1993/5608] Fix beatmap present failing directly after an import --- osu.Game/Screens/Select/BeatmapCarousel.cs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 16354534f4..5069096a44 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -81,7 +81,8 @@ namespace osu.Game.Screens.Select itemsCache.Invalidate(); scrollPositionCache.Invalidate(); - Schedule(() => + // Run on late scheduler want to ensure this runs after all pending UpdateBeatmapSet / RemoveBeatmapSet operations are run. + SchedulerAfterChildren.Add(() => { BeatmapSetsChanged?.Invoke(); BeatmapSetsLoaded = true; @@ -129,19 +130,16 @@ namespace osu.Game.Screens.Select loadBeatmapSets(beatmaps.GetAllUsableBeatmapSetsEnumerable()); } - public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) + public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() => { - Schedule(() => - { - var existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID); + var existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID); - if (existingSet == null) - return; + if (existingSet == null) + return; - root.RemoveChild(existingSet); - itemsCache.Invalidate(); - }); - } + root.RemoveChild(existingSet); + itemsCache.Invalidate(); + }); public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() => { From 2b184658d1d81b7ae6f86cf5b38e963d2b53f2cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jul 2019 20:28:31 +0900 Subject: [PATCH 1994/5608] Adjust follow points by circle size --- .../Objects/Drawables/Connections/FollowPointRenderer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 7569626230..a269b87c75 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -97,13 +97,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections Position = pointStartPosition, Rotation = rotation, Alpha = 0, - Scale = new Vector2(1.5f), + Scale = new Vector2(1.5f * currHitObject.Scale), }); using (fp.BeginAbsoluteSequence(fadeInTime)) { fp.FadeIn(currHitObject.TimeFadeIn); - fp.ScaleTo(1, currHitObject.TimeFadeIn, Easing.Out); + fp.ScaleTo(currHitObject.Scale, currHitObject.TimeFadeIn, Easing.Out); fp.MoveTo(pointEndPosition, currHitObject.TimeFadeIn, Easing.Out); From 28653e871cad59e40d978a088717ee21f3e0614f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jul 2019 15:59:29 +0900 Subject: [PATCH 1995/5608] Give repeat points a size specification --- .../Objects/Drawables/DrawableRepeatPoint.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 2e6e7e03ac..543e5d20d5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables this.repeatPoint = repeatPoint; this.drawableSlider = drawableSlider; - Size = new Vector2(45 * repeatPoint.Scale); + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2 * repeatPoint.Scale); Blending = BlendingMode.Additive; Origin = Anchor.Centre; @@ -36,7 +36,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon { RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.Solid.ChevronRight + Icon = FontAwesome.Solid.ChevronRight, + Size = new Vector2(0.35f) }) }; } From 5a9d18380cc6844ecc462b727970deba05a2bfac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jul 2019 16:40:40 +0900 Subject: [PATCH 1996/5608] Use scale correctly in DrawableRepeatPoint --- .../Objects/Drawables/DrawableRepeatPoint.cs | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 543e5d20d5..d07b37488c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -3,6 +3,8 @@ using System; using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; @@ -20,28 +22,40 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private double animDuration; + private readonly SkinnableDrawable scaleContainer; + public DrawableRepeatPoint(RepeatPoint repeatPoint, DrawableSlider drawableSlider) : base(repeatPoint) { this.repeatPoint = repeatPoint; this.drawableSlider = drawableSlider; - Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2 * repeatPoint.Scale); + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Blending = BlendingMode.Additive; Origin = Anchor.Centre; - InternalChildren = new Drawable[] + InternalChild = scaleContainer = new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon { - new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon - { - RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.Solid.ChevronRight, - Size = new Vector2(0.35f) - }) + RelativeSizeAxes = Axes.Both, + Icon = FontAwesome.Solid.ChevronRight, + Size = new Vector2(0.35f) + }) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, }; } + private readonly IBindable scaleBindable = new Bindable(); + + [BackgroundDependencyLoader] + private void load() + { + scaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); + scaleBindable.BindTo(HitObject.ScaleBindable); + } + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (repeatPoint.StartTime <= Time.Current) From 2cb3619b548ead0a1422017d246840843dc8eafc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jul 2019 13:27:41 +0900 Subject: [PATCH 1997/5608] Allow scaling outside of defined area Caters to skins which show borders outside of the circle for repeats. --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index d07b37488c..f75b62eecf 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables RelativeSizeAxes = Axes.Both, Icon = FontAwesome.Solid.ChevronRight, Size = new Vector2(0.35f) - }) + }, confineMode: ConfineMode.NoScaling) { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 5e153a3dd39364ff742505f5322ef83900015de3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jul 2019 13:42:29 +0900 Subject: [PATCH 1998/5608] Use scale correctly in DrawableSliderTick --- .../Objects/Drawables/DrawableSliderTick.cs | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index c8062b67b5..653e73ac3f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osuTK; @@ -16,36 +18,49 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public const double ANIM_DURATION = 150; + private const float default_tick_size = 16; + public bool Tracking { get; set; } public override bool DisplayResult => false; + private readonly SkinnableDrawable scaleContainer; + public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) { - Size = new Vector2(16 * sliderTick.Scale); + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Origin = Anchor.Centre; - InternalChildren = new Drawable[] + InternalChild = scaleContainer = new SkinnableDrawable("Play/osu/sliderscorepoint", _ => new CircularContainer { - new SkinnableDrawable("Play/osu/sliderscorepoint", _ => new Container + Masking = true, + Origin = Anchor.Centre, + Size = new Vector2(default_tick_size), + BorderThickness = default_tick_size / 4, + BorderColour = Color4.White, + Child = new Box { - Masking = true, RelativeSizeAxes = Axes.Both, - Origin = Anchor.Centre, - CornerRadius = Size.X / 2, - BorderThickness = 2, - BorderColour = Color4.White, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = AccentColour.Value, - Alpha = 0.3f, - } - }) + Colour = AccentColour.Value, + Alpha = 0.3f, + } + }) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, }; } + private readonly IBindable scaleBindable = new Bindable(); + + [BackgroundDependencyLoader] + private void load() + { + scaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); + scaleBindable.BindTo(HitObject.ScaleBindable); + } + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (timeOffset >= 0) From a290437286e1c55e34efea34bc5b0327271c71a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 12:34:40 +0900 Subject: [PATCH 1999/5608] Fix skin changed events triggering after disposal --- osu.Game/Skinning/SkinReloadableDrawable.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index c09d5b1f92..440645bee7 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.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; @@ -36,12 +36,14 @@ namespace osu.Game.Skinning skin.SourceChanged += onChange; } - private void onChange() => SkinChanged(skin, allowDefaultFallback); + private void onChange() => + // schedule required to avoid calls after disposed. + Schedule(() => SkinChanged(skin, allowDefaultFallback)); protected override void LoadAsyncComplete() { base.LoadAsyncComplete(); - onChange(); + SkinChanged(skin, allowDefaultFallback); } /// From 9473f6d3e3b83970e4b785629f46080fa55cb440 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 19 Jul 2019 11:45:33 +0900 Subject: [PATCH 2000/5608] Fix incorrect ratios being applied to playfield / skin elements This now matches osu-stable 1:1. --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs | 3 +-- .../UI/OsuPlayfieldAdjustmentContainer.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 15 +++++++++++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index b3492a2b31..ea81527fa9 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -101,11 +101,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor }, }, } - }) + }, confineMode: ConfineMode.NoScaling) { Origin = Anchor.Centre, Anchor = Anchor.Centre, - RelativeSizeAxes = Axes.Both, } }; diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs index e28ff5f460..8b6b483618 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.UI Anchor = Anchor.Centre; Origin = Anchor.Centre; - Size = new Vector2(0.75f); + Size = new Vector2(0.8f); InternalChild = new Container { diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 513a024a36..7b6cd613ec 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -95,7 +95,6 @@ namespace osu.Game.Skinning public override Texture GetTexture(string componentName) { float ratio = 2; - var texture = Textures.Get($"{componentName}@2x"); if (texture == null) @@ -105,7 +104,19 @@ namespace osu.Game.Skinning } if (texture != null) - texture.ScaleAdjust = ratio / 0.72f; // brings sizing roughly in-line with stable + { + texture.ScaleAdjust = ratio; + + switch (componentName) + { + case "cursormiddle": + case "cursortrail": + case "cursor": + // apply inverse of adjustment in OsuPlayfieldAdjustmentContainer for non-gameplay-scale textures. + texture.ScaleAdjust *= 1.6f; + break; + } + } return texture; } From 46e17646acee682392c3b576b13aa97ca47b2978 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Jul 2019 18:49:52 +0900 Subject: [PATCH 2001/5608] Align slider path size with legacy skins --- .../Objects/Drawables/DrawableSlider.cs | 7 +++---- osu.Game/Skinning/LegacySkin.cs | 17 +++++++++++++++++ osu.Game/Skinning/SkinConfiguration.cs | 2 ++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 4a6bd45007..dc05f3de58 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -48,10 +48,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables InternalChildren = new Drawable[] { - Body = new SnakingSliderBody(s) - { - PathRadius = s.Scale * OsuHitObject.OBJECT_RADIUS, - }, + Body = new SnakingSliderBody(s), ticks = new Container { RelativeSizeAxes = Axes.Both }, repeatPoints = new Container { RelativeSizeAxes = Axes.Both }, Ball = new SliderBall(s, this) @@ -162,6 +159,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.SkinChanged(skin, allowFallback); Body.BorderSize = skin.GetValue(s => s.SliderBorderSize) ?? SliderBody.DEFAULT_BORDER_SIZE; + Body.PathRadius = slider.Scale * (skin.GetValue(s => s.SliderPathRadius) ?? OsuHitObject.OBJECT_RADIUS); + Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? AccentColour.Value; Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Color4.White; Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? AccentColour.Value; diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 7b6cd613ec..af9a24df42 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -24,6 +24,13 @@ namespace osu.Game.Skinning protected IResourceStore Samples; + /// + /// On osu-stable, hitcircles have 5 pixels of transparent padding on each side to allow for shadows etc. + /// Their hittable area is 128px, but the actual circle portion is 118px. + /// We must account for some gameplay elements such as slider bodies, where this padding is not present. + /// + private const float legacy_circle_radius = 64 - 5; + public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini") { @@ -41,6 +48,16 @@ namespace osu.Game.Skinning Samples = audioManager.GetSampleStore(storage); Textures = new TextureStore(new TextureLoaderStore(storage)); + + bool hasHitCircle = false; + + using (var testStream = storage.GetStream("hitcircle")) + hasHitCircle |= testStream != null; + + if (hasHitCircle) + { + Configuration.SliderPathRadius = legacy_circle_radius; + } } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index 043622f8ce..93b599f9f6 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -27,6 +27,8 @@ namespace osu.Game.Skinning public float? SliderBorderSize { get; set; } + public float? SliderPathRadius { get; set; } + public bool? CursorExpand { get; set; } = true; } } From 5e8867066c3e395c9b6b646fdd4d539cd09de635 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jul 2019 14:43:44 +0900 Subject: [PATCH 2002/5608] Correctly handling bindable scale changes --- .../Objects/Drawables/DrawableSlider.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index dc05f3de58..020a64a26b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); scaleBindable.BindValueChanged(scale => { - Body.PathRadius = scale.NewValue * 64; + updatePathRadius(); Ball.Scale = new Vector2(scale.NewValue); }); @@ -154,18 +154,23 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Body.RecyclePath(); } + private float sliderPathRadius; + protected override void SkinChanged(ISkinSource skin, bool allowFallback) { base.SkinChanged(skin, allowFallback); Body.BorderSize = skin.GetValue(s => s.SliderBorderSize) ?? SliderBody.DEFAULT_BORDER_SIZE; - Body.PathRadius = slider.Scale * (skin.GetValue(s => s.SliderPathRadius) ?? OsuHitObject.OBJECT_RADIUS); + sliderPathRadius = skin.GetValue(s => s.SliderPathRadius) ?? OsuHitObject.OBJECT_RADIUS; + updatePathRadius(); Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? AccentColour.Value; Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Color4.White; Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? AccentColour.Value; } + private void updatePathRadius() => Body.PathRadius = slider.Scale * sliderPathRadius; + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (userTriggered || Time.Current < slider.EndTime) From c4bed0e6d29944cb6045267a3a4fdd17cf40bf34 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 25 Jul 2019 15:31:21 +0900 Subject: [PATCH 2003/5608] Resize BeatmapCarousel, update carouselitem logic --- osu.Game/Screens/Select/BeatmapCarousel.cs | 21 +++++++++------- osu.Game/Screens/Select/FilterControl.cs | 6 ----- osu.Game/Screens/Select/SongSelect.cs | 28 +++++++++++++++------- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 16354534f4..938ae1c028 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -108,10 +108,12 @@ namespace osu.Game.Screens.Select root = new CarouselRoot(this); Child = new OsuContextMenuContainer { + Masking = false, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Child = scrollableContent = new Container { + Masking = false, RelativeSizeAxes = Axes.X, } }; @@ -424,7 +426,9 @@ namespace osu.Game.Screens.Select if (!scrollPositionCache.IsValid) updateScrollPosition(); - float drawHeight = DrawHeight; + // The draw positions of individual sets extend beyond the size of the carousel and into its parent + // As a result, this should use the Parent's draw height instead. + float drawHeight = Parent.DrawHeight; // Remove all items that should no longer be on-screen scrollableContent.RemoveAll(p => p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent); @@ -432,9 +436,9 @@ namespace osu.Game.Screens.Select // Find index range of all items that should be on-screen Trace.Assert(Items.Count == yPositions.Count); - int firstIndex = yPositions.BinarySearch(Current - DrawableCarouselItem.MAX_HEIGHT); + int firstIndex = yPositions.BinarySearch(Current - DrawableCarouselItem.MAX_HEIGHT - Parent.Padding.Top); if (firstIndex < 0) firstIndex = ~firstIndex; - int lastIndex = yPositions.BinarySearch(Current + drawHeight); + int lastIndex = yPositions.BinarySearch(Current + drawHeight + Parent.Padding.Bottom); if (lastIndex < 0) lastIndex = ~lastIndex; int notVisibleCount = 0; @@ -637,18 +641,19 @@ namespace osu.Game.Screens.Select /// the current scroll position. /// /// The item to be updated. - /// Half the draw height of the carousel container. - private void updateItem(DrawableCarouselItem p, float halfHeight) + /// Half the draw height of the carousel container's parent. + private void updateItem(DrawableCarouselItem p, float parentHalfHeight) { var height = p.IsPresent ? p.DrawHeight : 0; - float itemDrawY = p.Position.Y - Current + height / 2; - float dist = Math.Abs(1f - itemDrawY / halfHeight); + // The actual Y position of the item needs to be offset by any potential padding set by the container's parent. + float itemDrawY = p.Position.Y - Current + Parent.Padding.Top + height / 2; + float dist = Math.Abs(1f - itemDrawY / parentHalfHeight); // Setting the origin position serves as an additive position on top of potential // local transformation we may want to apply (e.g. when a item gets selected, we // may want to smoothly transform it leftwards.) - p.OriginPosition = new Vector2(-offsetX(dist, halfHeight), 0); + p.OriginPosition = new Vector2(-offsetX(dist, parentHalfHeight), 0); // We are applying a multiplicative alpha (which is internally done by nesting an // additional container and setting that container's alpha) such that we can diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 57fe15fd99..97ba1cce6b 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -187,11 +187,5 @@ namespace osu.Game.Screens.Select } private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria()); - - protected override bool OnMouseDown(MouseDownEvent e) => true; - - protected override bool OnMouseMove(MouseMoveEvent e) => true; - - protected override bool OnClick(ClickEvent e) => true; } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 20dbcf2693..011c62f0eb 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -45,6 +45,7 @@ namespace osu.Game.Screens.Select protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; + private const float filter_control_height = 100; public readonly FilterControl FilterControl; @@ -121,7 +122,7 @@ namespace osu.Game.Screens.Select Size = new Vector2(wedged_container_size.X, 1), Padding = new MarginPadding { - Bottom = 50, + Bottom = Footer.HEIGHT, Top = wedged_container_size.Y + left_area_padding, Left = left_area_padding, Right = left_area_padding * 2, @@ -147,20 +148,29 @@ namespace osu.Game.Screens.Select Width = 0.5f, Children = new Drawable[] { - Carousel = new BeatmapCarousel + new Container { - Masking = false, RelativeSizeAxes = Axes.Both, - Size = new Vector2(1 - wedged_container_size.X, 1), - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - SelectionChanged = updateSelectedBeatmap, - BeatmapSetsChanged = carouselBeatmapsLoaded, + Padding = new MarginPadding + { + Top = filter_control_height, + Bottom = Footer.HEIGHT + }, + Child = Carousel = new BeatmapCarousel + { + Masking = false, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(1 - wedged_container_size.X, 1), + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + SelectionChanged = updateSelectedBeatmap, + BeatmapSetsChanged = carouselBeatmapsLoaded, + }, }, FilterControl = new FilterControl { RelativeSizeAxes = Axes.X, - Height = 100, + Height = filter_control_height, FilterChanged = c => Carousel.Filter(c), Background = { Width = 2 }, Exit = () => From 58feba72a30824e7d5624dbf20bf6a0e2acc0666 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jul 2019 15:59:44 +0900 Subject: [PATCH 2004/5608] Fix scheduled events not running on previous drawables --- osu.Game/Skinning/SkinReloadableDrawable.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index 440645bee7..397c6656a5 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -38,7 +38,8 @@ namespace osu.Game.Skinning private void onChange() => // schedule required to avoid calls after disposed. - Schedule(() => SkinChanged(skin, allowDefaultFallback)); + // note that this has the side-effect of components only performance a skin change when they are alive. + Scheduler.AddOnce(() => SkinChanged(skin, allowDefaultFallback)); protected override void LoadAsyncComplete() { From eb6bda3f0853cf2fa3c11f3f0787e1c1ffeb06d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 19 Jul 2019 19:12:41 +0900 Subject: [PATCH 2005/5608] Cache DrawableHitObject for skinnables to access --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 1d9d885527..c1cb1a7a33 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -17,6 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Objects.Drawables { + [Cached(typeof(DrawableHitObject))] public abstract class DrawableHitObject : SkinReloadableDrawable { public readonly HitObject HitObject; From 859233526d4ad1f3173e0b6d4a5c33425cbfc45b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 Jul 2019 18:50:57 +0900 Subject: [PATCH 2006/5608] Move circle visual implementation to new class Allows for more precise skin control over state animations. --- .../Objects/Drawables/DrawableHitCircle.cs | 127 +++++++++--------- .../Objects/Drawables/DrawableOsuHitObject.cs | 2 +- .../Objects/Drawables/Pieces/CirclePiece.cs | 31 +---- .../Drawables/Pieces/MainCirclePiece.cs | 94 +++++++++++++ 4 files changed, 157 insertions(+), 97 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/MainCirclePiece.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 001003155d..897ab0a17b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -6,33 +6,29 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osuTK; using osu.Game.Rulesets.Scoring; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableHitCircle : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { public ApproachCircle ApproachCircle; - private readonly CirclePiece circle; - private readonly RingPiece ring; - private readonly FlashPiece flash; - private readonly ExplodePiece explode; - private readonly NumberPiece number; - private readonly GlowPiece glow; private readonly IBindable positionBindable = new Bindable(); private readonly IBindable stackHeightBindable = new Bindable(); private readonly IBindable scaleBindable = new Bindable(); - public OsuAction? HitAction => circle.HitAction; - - private readonly Container explodeContainer; + public OsuAction? HitAction => hitArea.HitAction; private readonly Container scaleContainer; + private readonly HitArea hitArea; + public DrawableHitCircle(HitCircle h) : base(h) { @@ -47,44 +43,30 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, Anchor = Anchor.Centre, - Child = explodeContainer = new Container + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Children = new Drawable[] + hitArea = new HitArea { - glow = new GlowPiece(), - circle = new CirclePiece + Hit = () => { - Hit = () => - { - if (AllJudged) - return false; + if (AllJudged) + return false; - UpdateResult(true); - return true; - }, + UpdateResult(true); + return true; }, - number = new NumberPiece - { - Text = (HitObject.IndexInCurrentCombo + 1).ToString(), - }, - ring = new RingPiece(), - flash = new FlashPiece(), - explode = new ExplodePiece(), - ApproachCircle = new ApproachCircle - { - Alpha = 0, - Scale = new Vector2(4), - } + }, + new SkinnableDrawable("Play/Osu/Objects/Drawables/MainCircle", _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)), + ApproachCircle = new ApproachCircle + { + Alpha = 0, + Scale = new Vector2(4), } } }, }; - //may not be so correct - Size = circle.DrawSize; + Size = hitArea.DrawSize; } [BackgroundDependencyLoader] @@ -98,13 +80,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables stackHeightBindable.BindTo(HitObject.StackHeightBindable); scaleBindable.BindTo(HitObject.ScaleBindable); - AccentColour.BindValueChanged(colour => - { - explode.Colour = colour.NewValue; - glow.Colour = colour.NewValue; - circle.Colour = colour.NewValue; - ApproachCircle.Colour = colour.NewValue; - }, true); + AccentColour.BindValueChanged(accent => ApproachCircle.Colour = accent.NewValue, true); } protected override void CheckForResult(bool userTriggered, double timeOffset) @@ -139,8 +115,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateStateTransforms(ArmedState state) { - glow.FadeOut(400); - switch (state) { case ArmedState.Idle: @@ -148,7 +122,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Expire(true); - circle.HitAction = null; + hitArea.HitAction = null; // override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early. LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.HalfWindowFor(HitResult.Miss); @@ -163,29 +137,50 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables case ArmedState.Hit: ApproachCircle.FadeOut(50); - const double flash_in = 40; - flash.FadeTo(0.8f, flash_in) - .Then() - .FadeOut(100); - - explode.FadeIn(flash_in); - explodeContainer.ScaleTo(1.5f, 400, Easing.OutQuad); - - using (BeginDelayedSequence(flash_in, true)) - { - //after the flash, we can hide some elements that were behind it - ring.FadeOut(); - circle.FadeOut(); - number.FadeOut(); - - this.FadeOut(800); - } - - Expire(); + // todo: temporary / arbitrary + this.Delay(800).Expire(); break; } } public Drawable ProxiedLayer => ApproachCircle; + + private class HitArea : Drawable, IKeyBindingHandler + { + // IsHovered is used + public override bool HandlePositionalInput => true; + + public Func Hit; + + public OsuAction? HitAction; + + public HitArea() + { + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); + + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + } + + public bool OnPressed(OsuAction action) + { + switch (action) + { + case OsuAction.LeftButton: + case OsuAction.RightButton: + if (IsHovered && (Hit?.Invoke() ?? false)) + { + HitAction = action; + return true; + } + + break; + } + + return false; + } + + public bool OnReleased(OsuAction action) => false; + } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 579f16e0d4..a89fb8b682 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index dc0b149140..acbf5ba9ae 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -1,24 +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; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Bindings; using osu.Game.Skinning; using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { - public class CirclePiece : Container, IKeyBindingHandler + public class CirclePiece : CompositeDrawable { - // IsHovered is used - public override bool HandlePositionalInput => true; - - public Func Hit; - - public OsuAction? HitAction; - public CirclePiece() { Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); @@ -30,25 +21,5 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces InternalChild = new SkinnableDrawable("Play/osu/hitcircle", _ => new DefaultCirclePiece()); } - - public bool OnPressed(OsuAction action) - { - switch (action) - { - case OsuAction.LeftButton: - case OsuAction.RightButton: - if (IsHovered && (Hit?.Invoke() ?? false)) - { - HitAction = action; - return true; - } - - break; - } - - return false; - } - - public bool OnReleased(OsuAction action) => false; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/MainCirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/MainCirclePiece.cs new file mode 100644 index 0000000000..944c93bb6d --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/MainCirclePiece.cs @@ -0,0 +1,94 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects.Drawables; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +{ + public class MainCirclePiece : CompositeDrawable + { + private readonly CirclePiece circle; + private readonly RingPiece ring; + private readonly FlashPiece flash; + private readonly ExplodePiece explode; + private readonly NumberPiece number; + private readonly GlowPiece glow; + + public MainCirclePiece(int index) + { + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); + + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + InternalChildren = new Drawable[] + { + glow = new GlowPiece(), + circle = new CirclePiece(), + number = new NumberPiece + { + Text = (index + 1).ToString(), + }, + ring = new RingPiece(), + flash = new FlashPiece(), + explode = new ExplodePiece(), + }; + } + + private readonly IBindable state = new Bindable(); + + private readonly Bindable accentColour = new Bindable(); + + [BackgroundDependencyLoader] + private void load(DrawableHitObject drawableObject) + { + state.BindTo(drawableObject.State); + state.BindValueChanged(updateState, true); + + accentColour.BindTo(drawableObject.AccentColour); + accentColour.BindValueChanged(colour => + { + explode.Colour = colour.NewValue; + glow.Colour = colour.NewValue; + circle.Colour = colour.NewValue; + }, true); + } + + private void updateState(ValueChangedEvent state) + { + glow.FadeOut(400); + + switch (state.NewValue) + { + case ArmedState.Hit: + const double flash_in = 40; + const double flash_out = 100; + + flash.FadeTo(0.8f, flash_in) + .Then() + .FadeOut(flash_out); + + explode.FadeIn(flash_in); + this.ScaleTo(1.5f, 400, Easing.OutQuad); + + using (BeginDelayedSequence(flash_in, true)) + { + //after the flash, we can hide some elements that were behind it + ring.FadeOut(); + circle.FadeOut(); + number.FadeOut(); + + this.FadeOut(800); + } + + break; + } + } + } +} From 38e21caa5a50296697d200138c492628b3c3ed15 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 12:34:54 +0900 Subject: [PATCH 2007/5608] Add legacy hitcircle --- osu.Game/Skinning/LegacySkin.cs | 75 ++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index af9a24df42..0a811a9514 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -6,15 +6,22 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; +using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Game.Database; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; using osuTK; +using osuTK.Graphics; namespace osu.Game.Skinning { @@ -36,6 +43,8 @@ namespace osu.Game.Skinning { } + private readonly bool hasHitCircle; + protected LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager, string filename) : base(skin) { @@ -49,8 +58,6 @@ namespace osu.Game.Skinning Samples = audioManager.GetSampleStore(storage); Textures = new TextureStore(new TextureLoaderStore(storage)); - bool hasHitCircle = false; - using (var testStream = storage.GetStream("hitcircle")) hasHitCircle |= testStream != null; @@ -71,6 +78,12 @@ namespace osu.Game.Skinning { switch (componentName) { + case "Play/Osu/Objects/Drawables/MainCircle": + if (!hasHitCircle) + return null; + + return new LegacyMainCirclePiece(); + case "Play/Miss": componentName = "hit0"; break; @@ -243,5 +256,63 @@ namespace osu.Game.Skinning return texture; } } + + public class LegacyMainCirclePiece : CompositeDrawable + { + public LegacyMainCirclePiece() + { + Size = new Vector2(128); + + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + } + + private readonly IBindable state = new Bindable(); + + private readonly Bindable accentColour = new Bindable(); + + [BackgroundDependencyLoader] + private void load(DrawableHitObject drawableObject, ISkinSource skin) + { + Sprite mainCircle; + + InternalChildren = new Drawable[] + { + mainCircle = new Sprite + { + Texture = skin.GetTexture("hitcircle"), + Colour = drawableObject.AccentColour.Value + }, + new SkinnableSpriteText("Play/osu/number-text", _ => new OsuSpriteText + { + Font = OsuFont.Numeric.With(size: 40), + UseFullGlyphHeight = false, + }, confineMode: ConfineMode.NoScaling) + { + Text = (((IHasComboInformation)drawableObject.HitObject).IndexInCurrentCombo + 1).ToString() + }, + new Sprite { Texture = skin.GetTexture("hitcircleoverlay") } + }; + + state.BindTo(drawableObject.State); + state.BindValueChanged(updateState, true); + + accentColour.BindTo(drawableObject.AccentColour); + accentColour.BindValueChanged(colour => mainCircle.Colour = colour.NewValue, true); + } + + private void updateState(ValueChangedEvent state) + { + const double legacy_fade_duration = 240; + + switch (state.NewValue) + { + case ArmedState.Hit: + this.FadeOut(legacy_fade_duration, Easing.Out); + this.ScaleTo(1.4f, legacy_fade_duration, Easing.Out); + break; + } + } + } } } From c1b01308579e057a9748df8f66583f5fe89b3cc4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jul 2019 16:17:02 +0900 Subject: [PATCH 2008/5608] Add legacy cursormiddle support --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs | 133 +++++++++++-------- osu.Game/Skinning/LegacySkin.cs | 39 ++++++ 2 files changed, 115 insertions(+), 57 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index ea81527fa9..37ac972f41 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { public class OsuCursor : SkinReloadableDrawable { + private const float size = 28; + private bool cursorExpand; private Bindable cursorScale; @@ -30,7 +32,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public OsuCursor() { Origin = Anchor.Centre; - Size = new Vector2(28); + + Size = new Vector2(size); } protected override void SkinChanged(ISkinSource skin, bool allowFallback) @@ -46,62 +49,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, Anchor = Anchor.Centre, - Child = scaleTarget = new SkinnableDrawable("cursor", _ => new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = Size.X / 6, - BorderColour = Color4.White, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Pink.Opacity(0.5f), - Radius = 5, - }, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true, - }, - new CircularContainer - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = Size.X / 3, - BorderColour = Color4.White.Opacity(0.5f), - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true, - }, - }, - }, - new CircularContainer - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.1f), - Masking = true, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.White, - }, - }, - }, - } - }, confineMode: ConfineMode.NoScaling) + Child = scaleTarget = new SkinnableDrawable("osu/Game/Rulesets/Osu/UI/Cursor/OsuCursor", _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling) { Origin = Anchor.Centre, Anchor = Anchor.Centre, @@ -144,5 +92,76 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor } public void Contract() => expandTarget.ScaleTo(released_scale, 100, Easing.OutQuad); + + private class DefaultCursor : CompositeDrawable + { + public DefaultCursor() + { + RelativeSizeAxes = Axes.Both; + + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + InternalChildren = new Drawable[] + { + new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = size / 6, + BorderColour = Color4.White, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Pink.Opacity(0.5f), + Radius = 5, + }, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true, + }, + new CircularContainer + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = size / 3, + BorderColour = Color4.White.Opacity(0.5f), + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true, + }, + }, + }, + new CircularContainer + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.1f), + Masking = true, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }, + }, + }, + } + } + }; + } + } } } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index af9a24df42..905541a592 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -6,9 +6,11 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; +using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; @@ -71,6 +73,12 @@ namespace osu.Game.Skinning { switch (componentName) { + case "osu/Game/Rulesets/Osu/UI/Cursor/OsuCursor": + if (GetTexture("cursor") != null) + return new LegacyCursor(); + + break; + case "Play/Miss": componentName = "hit0"; break; @@ -243,5 +251,36 @@ namespace osu.Game.Skinning return texture; } } + + public class LegacyCursor : CompositeDrawable + { + public LegacyCursor() + { + Size = new Vector2(50); + + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + } + + [BackgroundDependencyLoader] + private void load(ISkinSource skin) + { + InternalChildren = new Drawable[] + { + new Sprite + { + Texture = skin.GetTexture("cursormiddle"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new Sprite + { + Texture = skin.GetTexture("cursor"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + } + } } } From bfaf9d5f419aef2cd84031e0e0c00aeffc3acf5e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jul 2019 16:24:10 +0900 Subject: [PATCH 2009/5608] Remove unnecessary special cases --- osu.Game/Skinning/LegacySkin.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 905541a592..48888191e9 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -129,20 +129,8 @@ namespace osu.Game.Skinning } if (texture != null) - { texture.ScaleAdjust = ratio; - switch (componentName) - { - case "cursormiddle": - case "cursortrail": - case "cursor": - // apply inverse of adjustment in OsuPlayfieldAdjustmentContainer for non-gameplay-scale textures. - texture.ScaleAdjust *= 1.6f; - break; - } - } - return texture; } From 6cc6aff66e94de5d3a387639f0aeaac5230a02c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jul 2019 15:35:51 +0900 Subject: [PATCH 2010/5608] Fix slider ball sizing when legacy skin falls back to default --- .../Objects/Drawables/DrawableSlider.cs | 2 - .../Objects/Drawables/Pieces/SliderBall.cs | 130 ++++++++++-------- 2 files changed, 76 insertions(+), 56 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 020a64a26b..a0626707af 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -115,7 +115,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables AccentColour.BindValueChanged(colour => { Body.AccentColour = colour.NewValue; - Ball.AccentColour = colour.NewValue; foreach (var drawableHitObject in NestedHitObjects) drawableHitObject.AccentColour.Value = colour.NewValue; @@ -166,7 +165,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? AccentColour.Value; Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Color4.White; - Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? AccentColour.Value; } private void updatePathRadius() => Body.PathRadius = slider.Scale * sliderPathRadius; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 9ba8ad3474..119005eb40 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -3,11 +3,14 @@ using System; using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Framework.Input.Events; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osuTK.Graphics; using osu.Game.Skinning; @@ -17,88 +20,44 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class SliderBall : CircularContainer, ISliderProgress, IRequireHighFrequencyMousePosition { - private Color4 accentColour = Color4.Black; - public Func GetInitialHitAction; - /// - /// The colour that is used for the slider ball. - /// - public Color4 AccentColour - { - get => accentColour; - set - { - accentColour = value; - if (drawableBall != null) - drawableBall.Colour = value; - } - } - private readonly Slider slider; public readonly Drawable FollowCircle; - private Drawable drawableBall; private readonly DrawableSlider drawableSlider; public SliderBall(Slider slider, DrawableSlider drawableSlider = null) { this.drawableSlider = drawableSlider; this.slider = slider; - Masking = true; - AutoSizeAxes = Axes.Both; + Blending = BlendingMode.Additive; Origin = Anchor.Centre; + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); + Children = new[] { - FollowCircle = new Container + FollowCircle = new FollowCircleContainer { Origin = Anchor.Centre, Anchor = Anchor.Centre, - Width = OsuHitObject.OBJECT_RADIUS * 2, - Height = OsuHitObject.OBJECT_RADIUS * 2, + RelativeSizeAxes = Axes.Both, Alpha = 0, - Child = new SkinnableDrawable("Play/osu/sliderfollowcircle", _ => new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = 5, - BorderColour = Color4.Orange, - Blending = BlendingMode.Additive, - Child = new Box - { - Colour = Color4.Orange, - RelativeSizeAxes = Axes.Both, - Alpha = 0.2f, - } - }), + Child = new SkinnableDrawable("Play/osu/sliderfollowcircle", _ => new DefaultFollowCircle()), }, new CircularContainer { Masking = true, - AutoSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, Anchor = Anchor.Centre, Alpha = 1, Child = new Container { - Width = OsuHitObject.OBJECT_RADIUS * 2, - Height = OsuHitObject.OBJECT_RADIUS * 2, + RelativeSizeAxes = Axes.Both, // TODO: support skin filename animation (sliderb0, sliderb1...) - Child = new SkinnableDrawable("Play/osu/sliderb", _ => new CircularContainer - { - Masking = true, - RelativeSizeAxes = Axes.Both, - BorderThickness = 10, - BorderColour = Color4.White, - Alpha = 1, - Child = drawableBall = new Box - { - Colour = AccentColour, - RelativeSizeAxes = Axes.Both, - Alpha = 0.4f, - } - }), + Child = new SkinnableDrawable("Play/osu/sliderb", _ => new DefaultSliderBall()), } } }; @@ -191,7 +150,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces // in valid time range Time.Current >= slider.StartTime && Time.Current < slider.EndTime && // in valid position range - lastScreenSpaceMousePosition.HasValue && base.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value) && + lastScreenSpaceMousePosition.HasValue && FollowCircle.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value) && // valid action (actions?.Any(isValidTrackingAction) ?? false); } @@ -214,5 +173,68 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { Position = slider.CurvePositionAt(completionProgress); } + + private class FollowCircleContainer : Container + { + public override bool HandlePositionalInput => true; + } + + public class DefaultFollowCircle : CompositeDrawable + { + public DefaultFollowCircle() + { + RelativeSizeAxes = Axes.Both; + + InternalChild = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = 5, + BorderColour = Color4.Orange, + Blending = BlendingMode.Additive, + Child = new Box + { + Colour = Color4.Orange, + RelativeSizeAxes = Axes.Both, + Alpha = 0.2f, + } + }; + } + } + + public class DefaultSliderBall : CompositeDrawable + { + private readonly Bindable accentColour = new Bindable(); + + private Drawable drawableBall; + + [BackgroundDependencyLoader] + private void load(DrawableHitObject drawableObject, ISkinSource skin) + { + RelativeSizeAxes = Axes.Both; + + float radius = skin.GetValue(s => s.SliderPathRadius) ?? OsuHitObject.OBJECT_RADIUS; + + InternalChild = new CircularContainer + { + Masking = true, + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(radius / OsuHitObject.OBJECT_RADIUS), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + BorderThickness = 10, + BorderColour = Color4.White, + Alpha = 1, + Child = drawableBall = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.4f, + } + }; + + accentColour.BindTo(drawableObject.AccentColour); + accentColour.BindValueChanged(colour => drawableBall.Colour = colour.NewValue, true); + } + } } } From 7b82d184bd48dd3130552596ff1115a58986c651 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 25 Jul 2019 11:07:53 +0300 Subject: [PATCH 2011/5608] Add bindable boolean for break times --- osu.Game/Screens/Play/BreakOverlay.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index d390787090..0941b8a452 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -2,7 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -35,6 +37,11 @@ namespace osu.Game.Screens.Play public override bool RemoveCompletedTransforms => false; + /// + /// Whether we are currently in the break time range. + /// + public readonly BindableBool IsBreakTime = new BindableBool(); + private readonly Container remainingTimeAdjustmentBox; private readonly Container remainingTimeBox; private readonly RemainingTimeCounter remainingTimeCounter; @@ -109,6 +116,13 @@ namespace osu.Game.Screens.Play initializeBreaks(); } + protected override void Update() + { + base.Update(); + + IsBreakTime.Value = breaks.Where(b => b.HasEffect).Any(b => Clock.CurrentTime >= b.StartTime && Clock.CurrentTime <= b.EndTime); + } + private void initializeBreaks() { if (!IsLoaded) return; // we need a clock. From 0ea0a10ca45ee73e08efad09e55e98f17b1ee2da Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 25 Jul 2019 11:26:38 +0300 Subject: [PATCH 2012/5608] Expose as IBindable --- osu.Game/Screens/Play/BreakOverlay.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 0941b8a452..593b54afb8 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -41,6 +41,9 @@ namespace osu.Game.Screens.Play /// Whether we are currently in the break time range. /// public readonly BindableBool IsBreakTime = new BindableBool(); + public IBindable IsBreakTime => isBreakTime; + + private readonly BindableBool isBreakTime = new BindableBool(); private readonly Container remainingTimeAdjustmentBox; private readonly Container remainingTimeBox; From 69d2f57f4fadc108076365780f13b96b6e8e08cc Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 25 Jul 2019 11:27:01 +0300 Subject: [PATCH 2013/5608] Avoid using LINQ --- osu.Game/Screens/Play/BreakOverlay.cs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 593b54afb8..bebbbc5b68 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -123,7 +122,24 @@ namespace osu.Game.Screens.Play { base.Update(); - IsBreakTime.Value = breaks.Where(b => b.HasEffect).Any(b => Clock.CurrentTime >= b.StartTime && Clock.CurrentTime <= b.EndTime); + updateBreakTimeBindable(); + } + + private void updateBreakTimeBindable() + { + foreach (var b in breaks) + { + if (!b.HasEffect) + continue; + + if (Clock.CurrentTime >= b.StartTime && Clock.CurrentTime <= b.EndTime) + { + isBreakTime.Value = true; + return; + } + } + + isBreakTime.Value = false; } private void initializeBreaks() From 9bd66b6e7a777f9273efd5b6c7734db909c78b2f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 25 Jul 2019 11:27:32 +0300 Subject: [PATCH 2014/5608] Better xmldoc --- osu.Game/Screens/Play/BreakOverlay.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index bebbbc5b68..5958ca77d8 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -37,9 +37,8 @@ namespace osu.Game.Screens.Play public override bool RemoveCompletedTransforms => false; /// - /// Whether we are currently in the break time range. + /// Whether the gameplay is currently in a break. /// - public readonly BindableBool IsBreakTime = new BindableBool(); public IBindable IsBreakTime => isBreakTime; private readonly BindableBool isBreakTime = new BindableBool(); From 97eb5293a87102dbf918bd4b69ca0486937abd03 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 25 Jul 2019 17:32:21 +0900 Subject: [PATCH 2015/5608] Don't depend on parent sizing --- osu.Game/Screens/Select/BeatmapCarousel.cs | 28 +++++++++++----------- osu.Game/Screens/Select/FilterControl.cs | 1 - osu.Game/Screens/Select/Footer.cs | 4 ---- osu.Game/Screens/Select/SongSelect.cs | 21 ++++++++++------ 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 938ae1c028..e4b75a3540 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -426,19 +426,18 @@ namespace osu.Game.Screens.Select if (!scrollPositionCache.IsValid) updateScrollPosition(); - // The draw positions of individual sets extend beyond the size of the carousel and into its parent - // As a result, this should use the Parent's draw height instead. - float drawHeight = Parent.DrawHeight; + // The draw positions of individual sets extend beyond the size of the carousel and into the footer and header. + float visibleHeight = DrawHeight + SongSelect.FOOTER_HEIGHT + SongSelect.FILTER_CONTROL_HEIGHT; // Remove all items that should no longer be on-screen - scrollableContent.RemoveAll(p => p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent); + scrollableContent.RemoveAll(p => p.Y < Current - p.DrawHeight || p.Y > Current + visibleHeight || !p.IsPresent); // Find index range of all items that should be on-screen Trace.Assert(Items.Count == yPositions.Count); - int firstIndex = yPositions.BinarySearch(Current - DrawableCarouselItem.MAX_HEIGHT - Parent.Padding.Top); + int firstIndex = yPositions.BinarySearch(Current - DrawableCarouselItem.MAX_HEIGHT - SongSelect.FILTER_CONTROL_HEIGHT); if (firstIndex < 0) firstIndex = ~firstIndex; - int lastIndex = yPositions.BinarySearch(Current + drawHeight + Parent.Padding.Bottom); + int lastIndex = yPositions.BinarySearch(Current + visibleHeight + SongSelect.FOOTER_HEIGHT); if (lastIndex < 0) lastIndex = ~lastIndex; int notVisibleCount = 0; @@ -490,7 +489,7 @@ namespace osu.Game.Screens.Select // Update externally controlled state of currently visible items // (e.g. x-offset and opacity). - float halfHeight = drawHeight / 2; + float halfHeight = visibleHeight / 2; foreach (DrawableCarouselItem p in scrollableContent.Children) updateItem(p, halfHeight); } @@ -546,7 +545,8 @@ namespace osu.Game.Screens.Select yPositions.Clear(); - float currentY = DrawHeight / 2; + float visibleHeight = DrawHeight + SongSelect.FOOTER_HEIGHT + SongSelect.FILTER_CONTROL_HEIGHT; + float currentY = visibleHeight / 2; DrawableCarouselBeatmapSet lastSet = null; scrollTarget = null; @@ -600,7 +600,7 @@ namespace osu.Game.Screens.Select currentY += d.DrawHeight + 5; } - currentY += DrawHeight / 2; + currentY += visibleHeight / 2; scrollableContent.Height = currentY; if (BeatmapSetsLoaded && (selectedBeatmapSet == null || selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected)) @@ -641,19 +641,19 @@ namespace osu.Game.Screens.Select /// the current scroll position. /// /// The item to be updated. - /// Half the draw height of the carousel container's parent. - private void updateItem(DrawableCarouselItem p, float parentHalfHeight) + /// Half the draw height of the carousel container's parent. + private void updateItem(DrawableCarouselItem p, float halfHeight) { var height = p.IsPresent ? p.DrawHeight : 0; // The actual Y position of the item needs to be offset by any potential padding set by the container's parent. - float itemDrawY = p.Position.Y - Current + Parent.Padding.Top + height / 2; - float dist = Math.Abs(1f - itemDrawY / parentHalfHeight); + float itemDrawY = p.Position.Y + SongSelect.FILTER_CONTROL_HEIGHT - Current + height / 2; + float dist = Math.Abs(1f - itemDrawY / halfHeight); // Setting the origin position serves as an additive position on top of potential // local transformation we may want to apply (e.g. when a item gets selected, we // may want to smoothly transform it leftwards.) - p.OriginPosition = new Vector2(-offsetX(dist, parentHalfHeight), 0); + p.OriginPosition = new Vector2(-offsetX(dist, halfHeight), 0); // We are applying a multiplicative alpha (which is internally done by nesting an // additional container and setting that container's alpha) such that we can diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 97ba1cce6b..31b71a21c8 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -14,7 +14,6 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Select.Filter; using Container = osu.Framework.Graphics.Containers.Container; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; using osu.Game.Configuration; using osu.Game.Rulesets; diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index 0680711f1c..7db3d65a0b 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -62,10 +62,6 @@ namespace osu.Game.Screens.Select public Footer() { - RelativeSizeAxes = Axes.X; - Height = HEIGHT; - Anchor = Anchor.BottomCentre; - Origin = Anchor.BottomCentre; Children = new Drawable[] { new Box diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 011c62f0eb..e5576f78cf 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -43,9 +43,10 @@ namespace osu.Game.Screens.Select { private static readonly Vector2 wedged_container_size = new Vector2(0.5f, 245); + public const float FILTER_CONTROL_HEIGHT = 100; + public const float FOOTER_HEIGHT = 50; protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; - private const float filter_control_height = 100; public readonly FilterControl FilterControl; @@ -122,7 +123,7 @@ namespace osu.Game.Screens.Select Size = new Vector2(wedged_container_size.X, 1), Padding = new MarginPadding { - Bottom = Footer.HEIGHT, + Bottom = FOOTER_HEIGHT, Top = wedged_container_size.Y + left_area_padding, Left = left_area_padding, Right = left_area_padding * 2, @@ -153,8 +154,8 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { - Top = filter_control_height, - Bottom = Footer.HEIGHT + Top = FILTER_CONTROL_HEIGHT, + Bottom = FOOTER_HEIGHT }, Child = Carousel = new BeatmapCarousel { @@ -170,7 +171,7 @@ namespace osu.Game.Screens.Select FilterControl = new FilterControl { RelativeSizeAxes = Axes.X, - Height = filter_control_height, + Height = FILTER_CONTROL_HEIGHT, FilterChanged = c => Carousel.Filter(c), Background = { Width = 2 }, Exit = () => @@ -209,7 +210,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Bottom = Footer.HEIGHT }, + Margin = new MarginPadding { Bottom = FOOTER_HEIGHT }, Children = new Drawable[] { BeatmapOptions = new BeatmapOptionsOverlay(), @@ -221,7 +222,13 @@ namespace osu.Game.Screens.Select } } }, - Footer = new Footer() + Footer = new Footer + { + RelativeSizeAxes = Axes.X, + Height = FOOTER_HEIGHT, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + } }); } From a9f0dda9d7ec20b4a0492f670c02e03be26e4a1b Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 25 Jul 2019 17:36:13 +0900 Subject: [PATCH 2016/5608] Confine positional input --- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index e4b75a3540..b917fc4bb4 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -53,6 +53,8 @@ namespace osu.Game.Screens.Select public override bool HandleNonPositionalInput => AllowSelection; public override bool HandlePositionalInput => AllowSelection; + protected override bool ConfinePositionalInput => true; + /// /// Whether carousel items have completed asynchronously loaded. /// From 172a9ce33a29a5286d23f46fc0b752e795362e12 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 25 Jul 2019 11:40:45 +0300 Subject: [PATCH 2017/5608] Use a for loop instead of foreach avoid allocating an iterator --- osu.Game/Screens/Play/BreakOverlay.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 5958ca77d8..918bb1e5c9 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -126,12 +126,12 @@ namespace osu.Game.Screens.Play private void updateBreakTimeBindable() { - foreach (var b in breaks) + for (int i = 0; i < breaks.Count; i++) { - if (!b.HasEffect) + if (!breaks[i].HasEffect) continue; - if (Clock.CurrentTime >= b.StartTime && Clock.CurrentTime <= b.EndTime) + if (Clock.CurrentTime >= breaks[i].StartTime && Clock.CurrentTime <= breaks[i].EndTime) { isBreakTime.Value = true; return; From 5a55433d6c7e2b76e8b7ceabd732374e0573efc1 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 25 Jul 2019 11:53:32 +0300 Subject: [PATCH 2018/5608] Return if breaks are null Fixes a test --- osu.Game/Screens/Play/BreakOverlay.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 918bb1e5c9..8b9431a87c 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -126,6 +126,9 @@ namespace osu.Game.Screens.Play private void updateBreakTimeBindable() { + if (breaks == null) + return; + for (int i = 0; i < breaks.Count; i++) { if (!breaks[i].HasEffect) From d4f85af19c9745d49dadfbd77fe529c5248b6f83 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 25 Jul 2019 18:22:56 +0900 Subject: [PATCH 2019/5608] Force snaking slider paths to retain a fixed size --- .../Objects/Drawables/Pieces/SliderBody.cs | 17 +++++++++-------- .../Drawables/Pieces/SnakingSliderBody.cs | 19 ++++++++++++++++++- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 97c7c9cec5..6bc19ee3b5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Lines; @@ -75,22 +76,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces protected SliderBody() { - InternalChild = path = new SliderPath(); + RecyclePath(); } /// /// Initialises a new , releasing all resources retained by the old one. /// - public void RecyclePath() + public virtual void RecyclePath() { InternalChild = path = new SliderPath { - Position = path.Position, - PathRadius = path.PathRadius, - AccentColour = path.AccentColour, - BorderColour = path.BorderColour, - BorderSize = path.BorderSize, - Vertices = path.Vertices + Position = path?.Position ?? Vector2.Zero, + PathRadius = path?.PathRadius ?? 10, + AccentColour = path?.AccentColour ?? Color4.White, + BorderColour = path?.BorderColour ?? Color4.White, + BorderSize = path?.BorderSize ?? DEFAULT_BORDER_SIZE, + Vertices = path?.Vertices ?? Array.Empty() }; } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index 73b184bffe..a3d3893c8b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Types; using osuTK; @@ -78,9 +79,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces slider.Path.GetPathToProgress(CurrentCurve, 0, 1); SetVertices(CurrentCurve); - // The body is sized to the full path size to avoid excessive autosize computations + // Force the body to be the final path size to avoid excessive autosize computations + Path.AutoSizeAxes = Axes.Both; Size = Path.Size; + updatePathSize(); + snakedPosition = Path.PositionInBoundingBox(Vector2.Zero); snakedPathOffset = Path.PositionInBoundingBox(Path.Vertices[0]); @@ -93,6 +97,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces setRange(lastSnakedStart, lastSnakedEnd); } + public override void RecyclePath() + { + base.RecyclePath(); + updatePathSize(); + } + + private void updatePathSize() + { + // Force the path to its final size to avoid excessive framebuffer resizes + Path.AutoSizeAxes = Axes.None; + Path.Size = Size; + } + private void setRange(double p0, double p1) { if (p0 > p1) From cdda264c491c4cef4b122ece777e04413e57cbc5 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 25 Jul 2019 12:28:21 +0300 Subject: [PATCH 2020/5608] Use global index and move it to find if break time Avoid using iterations --- osu.Game/Screens/Play/BreakOverlay.cs | 38 ++++++++++++++++++--------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 8b9431a87c..0470cdb0d5 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -30,6 +31,8 @@ namespace osu.Game.Screens.Play set { breaks = value; + currentBreakIndex = 0; + initializeBreaks(); } } @@ -41,6 +44,7 @@ namespace osu.Game.Screens.Play /// public IBindable IsBreakTime => isBreakTime; + private int currentBreakIndex; private readonly BindableBool isBreakTime = new BindableBool(); private readonly Container remainingTimeAdjustmentBox; @@ -126,22 +130,30 @@ namespace osu.Game.Screens.Play private void updateBreakTimeBindable() { - if (breaks == null) - return; - - for (int i = 0; i < breaks.Count; i++) + if (breaks == null || !breaks.Any()) { - if (!breaks[i].HasEffect) - continue; - - if (Clock.CurrentTime >= breaks[i].StartTime && Clock.CurrentTime <= breaks[i].EndTime) - { - isBreakTime.Value = true; - return; - } + isBreakTime.Value = false; + return; } - isBreakTime.Value = false; + int indexDirection = Clock.CurrentTime < breaks[currentBreakIndex].StartTime ? -1 : (Clock.CurrentTime > breaks[currentBreakIndex].EndTime ? 1 : 0); + + while (Clock.CurrentTime < breaks[currentBreakIndex].StartTime || Clock.CurrentTime > breaks[currentBreakIndex].EndTime) + { + currentBreakIndex += indexDirection; + + if (currentBreakIndex < 0 || currentBreakIndex >= breaks.Count) + break; + } + + if (currentBreakIndex < 0 || currentBreakIndex >= breaks.Count) + { + isBreakTime.Value = false; + currentBreakIndex = 0; + return; + } + + isBreakTime.Value = true; } private void initializeBreaks() From 5e5101280054709321e3f528312605be91843b28 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Thu, 25 Jul 2019 22:54:05 +0930 Subject: [PATCH 2021/5608] Rewrite updateBreakTimeBindable --- .../Visual/Gameplay/TestSceneBreakOverlay.cs | 26 ++++++++++++++++- osu.Game/Screens/Play/BreakOverlay.cs | 29 +++++++------------ 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs index 3cd1b8307a..ffa822d175 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs @@ -1,8 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using NUnit.Framework; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps.Timing; using osu.Game.Screens.Play; @@ -11,11 +16,30 @@ namespace osu.Game.Tests.Visual.Gameplay [TestFixture] public class TestSceneBreakOverlay : OsuTestScene { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(BreakOverlay), + }; + private readonly BreakOverlay breakOverlay; + private readonly IBindable isBreakTimeBindable = new BindableBool(); public TestSceneBreakOverlay() { - Child = breakOverlay = new BreakOverlay(true); + SpriteText breakTimeText; + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + breakTimeText = new SpriteText(), + breakOverlay = new BreakOverlay(true) + } + }; + + isBreakTimeBindable.BindTo(breakOverlay.IsBreakTime); + isBreakTimeBindable.BindValueChanged(e => breakTimeText.Text = $"IsBreakTime: {e.NewValue}", true); AddStep("2s break", () => startBreak(2000)); AddStep("5s break", () => startBreak(5000)); diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 0470cdb0d5..aceacdbab1 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Play set { breaks = value; - currentBreakIndex = 0; + nearestBreakIndex = 0; initializeBreaks(); } @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Play ///
public IBindable IsBreakTime => isBreakTime; - private int currentBreakIndex; + private int nearestBreakIndex; private readonly BindableBool isBreakTime = new BindableBool(); private readonly Container remainingTimeAdjustmentBox; @@ -136,24 +136,17 @@ namespace osu.Game.Screens.Play return; } - int indexDirection = Clock.CurrentTime < breaks[currentBreakIndex].StartTime ? -1 : (Clock.CurrentTime > breaks[currentBreakIndex].EndTime ? 1 : 0); + while (nearestBreakIndex < breaks.Count - 1 && Clock.CurrentTime > breaks[nearestBreakIndex].EndTime) + nearestBreakIndex++; - while (Clock.CurrentTime < breaks[currentBreakIndex].StartTime || Clock.CurrentTime > breaks[currentBreakIndex].EndTime) - { - currentBreakIndex += indexDirection; + while (nearestBreakIndex > 0 && Clock.CurrentTime < breaks[nearestBreakIndex].StartTime) + nearestBreakIndex--; - if (currentBreakIndex < 0 || currentBreakIndex >= breaks.Count) - break; - } - - if (currentBreakIndex < 0 || currentBreakIndex >= breaks.Count) - { - isBreakTime.Value = false; - currentBreakIndex = 0; - return; - } - - isBreakTime.Value = true; + // This ensures that IsBreakTime is generally consistent with the overlay's transforms during a break. + // If the overlay never shows (break.HasEffect is false), IsBreakTime should be false. + // We also assume that the overlay's fade out transform is "not break time". + var nearestBreak = breaks[nearestBreakIndex]; + isBreakTime.Value = nearestBreak.HasEffect && Clock.CurrentTime >= nearestBreak.StartTime && Clock.CurrentTime <= nearestBreak.EndTime - fade_duration; } private void initializeBreaks() From 1d6c321e14ff3c820ae2f3578f62e239cacbdd18 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 26 Jul 2019 08:34:18 +0930 Subject: [PATCH 2022/5608] Ensure we don't ping-pong nearestBreakIndex between breaks --- osu.Game/Screens/Play/BreakOverlay.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index aceacdbab1..50b2c97f59 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -136,11 +136,16 @@ namespace osu.Game.Screens.Play return; } - while (nearestBreakIndex < breaks.Count - 1 && Clock.CurrentTime > breaks[nearestBreakIndex].EndTime) - nearestBreakIndex++; - - while (nearestBreakIndex > 0 && Clock.CurrentTime < breaks[nearestBreakIndex].StartTime) - nearestBreakIndex--; + if (Clock.CurrentTime > breaks[nearestBreakIndex].EndTime) + { + while (nearestBreakIndex < breaks.Count - 1 && Clock.CurrentTime > breaks[nearestBreakIndex].EndTime) + nearestBreakIndex++; + } + else + { + while (nearestBreakIndex > 0 && Clock.CurrentTime < breaks[nearestBreakIndex].StartTime) + nearestBreakIndex--; + } // This ensures that IsBreakTime is generally consistent with the overlay's transforms during a break. // If the overlay never shows (break.HasEffect is false), IsBreakTime should be false. From a08d54eb06b2b2686152b9b04729ba3aabe65fdb Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 26 Jul 2019 03:11:59 +0300 Subject: [PATCH 2023/5608] Remove unnecessary checks --- osu.Game/Screens/Play/BreakOverlay.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 50b2c97f59..aceacdbab1 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -136,16 +136,11 @@ namespace osu.Game.Screens.Play return; } - if (Clock.CurrentTime > breaks[nearestBreakIndex].EndTime) - { - while (nearestBreakIndex < breaks.Count - 1 && Clock.CurrentTime > breaks[nearestBreakIndex].EndTime) - nearestBreakIndex++; - } - else - { - while (nearestBreakIndex > 0 && Clock.CurrentTime < breaks[nearestBreakIndex].StartTime) - nearestBreakIndex--; - } + while (nearestBreakIndex < breaks.Count - 1 && Clock.CurrentTime > breaks[nearestBreakIndex].EndTime) + nearestBreakIndex++; + + while (nearestBreakIndex > 0 && Clock.CurrentTime < breaks[nearestBreakIndex].StartTime) + nearestBreakIndex--; // This ensures that IsBreakTime is generally consistent with the overlay's transforms during a break. // If the overlay never shows (break.HasEffect is false), IsBreakTime should be false. From b4c93b1777646c59507bed626c0c79d2e5f4f82b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 26 Jul 2019 05:11:01 +0300 Subject: [PATCH 2024/5608] Use lookup direction than 2 while loops --- osu.Game/Screens/Play/BreakOverlay.cs | 31 +++++++++++++++++++-------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index aceacdbab1..9091e54159 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -31,7 +31,9 @@ namespace osu.Game.Screens.Play set { breaks = value; - nearestBreakIndex = 0; + + // reset index in case the new breaks list is smaller than last one + currentBreakIndex = 0; initializeBreaks(); } @@ -44,7 +46,7 @@ namespace osu.Game.Screens.Play ///
public IBindable IsBreakTime => isBreakTime; - private int nearestBreakIndex; + private int currentBreakIndex; private readonly BindableBool isBreakTime = new BindableBool(); private readonly Container remainingTimeAdjustmentBox; @@ -133,20 +135,31 @@ namespace osu.Game.Screens.Play if (breaks == null || !breaks.Any()) { isBreakTime.Value = false; + currentBreakIndex = 0; return; } - while (nearestBreakIndex < breaks.Count - 1 && Clock.CurrentTime > breaks[nearestBreakIndex].EndTime) - nearestBreakIndex++; + var lastIndex = currentBreakIndex; + var lookupDirection = Clock.CurrentTime > breaks[lastIndex].EndTime ? 1 : (Clock.CurrentTime < breaks[lastIndex].StartTime ? -1 : 0); - while (nearestBreakIndex > 0 && Clock.CurrentTime < breaks[nearestBreakIndex].StartTime) - nearestBreakIndex--; + while (Clock.CurrentTime < breaks[currentBreakIndex].StartTime || Clock.CurrentTime > breaks[currentBreakIndex].EndTime) + { + currentBreakIndex += lookupDirection; + + // restore index if out of bounds + if (currentBreakIndex < 0 || currentBreakIndex >= breaks.Count) + { + isBreakTime.Value = false; + currentBreakIndex = lastIndex; + return; + } + } // This ensures that IsBreakTime is generally consistent with the overlay's transforms during a break. - // If the overlay never shows (break.HasEffect is false), IsBreakTime should be false. + // If the current break doesn't have effects, IsBreakTime should be false. // We also assume that the overlay's fade out transform is "not break time". - var nearestBreak = breaks[nearestBreakIndex]; - isBreakTime.Value = nearestBreak.HasEffect && Clock.CurrentTime >= nearestBreak.StartTime && Clock.CurrentTime <= nearestBreak.EndTime - fade_duration; + var currentBreak = breaks[currentBreakIndex]; + isBreakTime.Value = currentBreak.HasEffect && Clock.CurrentTime <= currentBreak.EndTime - fade_duration; } private void initializeBreaks() From 44895c4b69743042b1cb0e70e6a8231ce7bc44c7 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 26 Jul 2019 05:41:10 +0300 Subject: [PATCH 2025/5608] Use IReadOnlyList for break periods list --- osu.Game/Screens/Play/BreakOverlay.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index d390787090..2b401778a6 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -19,11 +19,11 @@ namespace osu.Game.Screens.Play private const float remaining_time_container_max_size = 0.3f; private const int vertical_margin = 25; - private List breaks; - private readonly Container fadeContainer; - public List Breaks + private IReadOnlyList breaks; + + public IReadOnlyList Breaks { get => breaks; set From c89830f3d89cd1bd2baa0e1731d8f67bf1147b94 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 26 Jul 2019 13:07:28 +0900 Subject: [PATCH 2026/5608] move constants, combine local vars into properties --- osu.Game/Screens/Select/BeatmapCarousel.cs | 22 ++++++++++++---------- osu.Game/Screens/Select/FilterControl.cs | 2 ++ osu.Game/Screens/Select/Footer.cs | 4 ++++ osu.Game/Screens/Select/SongSelect.cs | 22 +++++++--------------- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index b917fc4bb4..44aebf73c9 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -26,6 +26,9 @@ namespace osu.Game.Screens.Select { public class BeatmapCarousel : OsuScrollContainer { + private const float bleed_top = FilterControl.HEIGHT; + private const float bleed_bottom = Footer.HEIGHT; + /// /// Triggered when the loaded change and are completely loaded. /// @@ -110,12 +113,10 @@ namespace osu.Game.Screens.Select root = new CarouselRoot(this); Child = new OsuContextMenuContainer { - Masking = false, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Child = scrollableContent = new Container { - Masking = false, RelativeSizeAxes = Axes.X, } }; @@ -342,6 +343,12 @@ namespace osu.Game.Screens.Select public bool AllowSelection = true; + /// + /// The total bounds of what is displayable in the beatmap carousel. + /// + /// + private float visibleHeight => DrawHeight + bleed_bottom + bleed_top; + public void FlushPendingFilterOperations() { if (PendingFilter?.Completed == false) @@ -428,18 +435,15 @@ namespace osu.Game.Screens.Select if (!scrollPositionCache.IsValid) updateScrollPosition(); - // The draw positions of individual sets extend beyond the size of the carousel and into the footer and header. - float visibleHeight = DrawHeight + SongSelect.FOOTER_HEIGHT + SongSelect.FILTER_CONTROL_HEIGHT; - // Remove all items that should no longer be on-screen scrollableContent.RemoveAll(p => p.Y < Current - p.DrawHeight || p.Y > Current + visibleHeight || !p.IsPresent); // Find index range of all items that should be on-screen Trace.Assert(Items.Count == yPositions.Count); - int firstIndex = yPositions.BinarySearch(Current - DrawableCarouselItem.MAX_HEIGHT - SongSelect.FILTER_CONTROL_HEIGHT); + int firstIndex = yPositions.BinarySearch(Current - DrawableCarouselItem.MAX_HEIGHT - bleed_top); if (firstIndex < 0) firstIndex = ~firstIndex; - int lastIndex = yPositions.BinarySearch(Current + visibleHeight + SongSelect.FOOTER_HEIGHT); + int lastIndex = yPositions.BinarySearch(Current + visibleHeight + bleed_bottom); if (lastIndex < 0) lastIndex = ~lastIndex; int notVisibleCount = 0; @@ -547,7 +551,6 @@ namespace osu.Game.Screens.Select yPositions.Clear(); - float visibleHeight = DrawHeight + SongSelect.FOOTER_HEIGHT + SongSelect.FILTER_CONTROL_HEIGHT; float currentY = visibleHeight / 2; DrawableCarouselBeatmapSet lastSet = null; @@ -648,8 +651,7 @@ namespace osu.Game.Screens.Select { var height = p.IsPresent ? p.DrawHeight : 0; - // The actual Y position of the item needs to be offset by any potential padding set by the container's parent. - float itemDrawY = p.Position.Y + SongSelect.FILTER_CONTROL_HEIGHT - Current + height / 2; + float itemDrawY = p.Position.Y + bleed_top - Current + height / 2; float dist = Math.Abs(1f - itemDrawY / halfHeight); // Setting the origin position serves as an additive position on top of potential diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 31b71a21c8..84e8e90f54 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -21,6 +21,8 @@ namespace osu.Game.Screens.Select { public class FilterControl : Container { + public const float HEIGHT = 100; + public Action FilterChanged; private readonly OsuTabControl sortTabs; diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index 7db3d65a0b..0680711f1c 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -62,6 +62,10 @@ namespace osu.Game.Screens.Select public Footer() { + RelativeSizeAxes = Axes.X; + Height = HEIGHT; + Anchor = Anchor.BottomCentre; + Origin = Anchor.BottomCentre; Children = new Drawable[] { new Box diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index e5576f78cf..73848cc740 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -42,9 +42,7 @@ namespace osu.Game.Screens.Select public abstract class SongSelect : OsuScreen, IKeyBindingHandler { private static readonly Vector2 wedged_container_size = new Vector2(0.5f, 245); - - public const float FILTER_CONTROL_HEIGHT = 100; - public const float FOOTER_HEIGHT = 50; + protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; @@ -123,7 +121,7 @@ namespace osu.Game.Screens.Select Size = new Vector2(wedged_container_size.X, 1), Padding = new MarginPadding { - Bottom = FOOTER_HEIGHT, + Bottom = Footer.HEIGHT, Top = wedged_container_size.Y + left_area_padding, Left = left_area_padding, Right = left_area_padding * 2, @@ -154,8 +152,8 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { - Top = FILTER_CONTROL_HEIGHT, - Bottom = FOOTER_HEIGHT + Top = FilterControl.HEIGHT, + Bottom = Footer.HEIGHT }, Child = Carousel = new BeatmapCarousel { @@ -171,7 +169,7 @@ namespace osu.Game.Screens.Select FilterControl = new FilterControl { RelativeSizeAxes = Axes.X, - Height = FILTER_CONTROL_HEIGHT, + Height = FilterControl.HEIGHT, FilterChanged = c => Carousel.Filter(c), Background = { Width = 2 }, Exit = () => @@ -210,7 +208,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Bottom = FOOTER_HEIGHT }, + Margin = new MarginPadding { Bottom = Footer.HEIGHT }, Children = new Drawable[] { BeatmapOptions = new BeatmapOptionsOverlay(), @@ -222,13 +220,7 @@ namespace osu.Game.Screens.Select } } }, - Footer = new Footer - { - RelativeSizeAxes = Axes.X, - Height = FOOTER_HEIGHT, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - } + Footer = new Footer() }); } From 7ec6ac7b0eb15e88ed18e13889a57ca917e63738 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jul 2019 13:15:36 +0900 Subject: [PATCH 2027/5608] Remove unnecessary override --- osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs index f6533be551..7386bffb1a 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Online.Chat; @@ -40,7 +39,5 @@ namespace osu.Game.Overlays.Chat.Tabs Name = "+"; } } - - protected override bool OnMouseUp(MouseUpEvent e) => false; } } From 56b27db7a412a30547f9f9530fa4ccfee5864e25 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jul 2019 13:17:21 +0900 Subject: [PATCH 2028/5608] Use "Click" instead of "Action" --- osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs index 859ca30d7f..2a3dd55c71 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs @@ -141,13 +141,15 @@ namespace osu.Game.Overlays.Chat.Tabs protected override bool OnMouseUp(MouseUpEvent e) { - if (e.Button == MouseButton.Middle) + switch (e.Button) { - CloseButton.Action(); - return true; - } + case MouseButton.Middle: + CloseButton.Click(); + return true; - return false; + default: + return false; + } } [BackgroundDependencyLoader] From 8a54dab5d0e28d4aaa372c1f62a8a655629c5a4e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jul 2019 13:27:37 +0900 Subject: [PATCH 2029/5608] Tidy up code --- osu.iOS/AppDelegate.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs index 93eca8caa1..9ef21e014c 100644 --- a/osu.iOS/AppDelegate.cs +++ b/osu.iOS/AppDelegate.cs @@ -12,20 +12,13 @@ namespace osu.iOS [Register("AppDelegate")] public class AppDelegate : GameAppDelegate { - private OsuGameIOS IOSGame; + private OsuGameIOS game; - protected override Framework.Game CreateGame() - { - //Save OsuGameIOS for Import - IOSGame = new OsuGameIOS(); - return IOSGame; - } + protected override Framework.Game CreateGame() => game = new OsuGameIOS(); public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation) { - //Open in Application - Task.Run(() => IOSGame.Import(url.Path)); - + Task.Run(() => game.Import(url.Path)); return true; } } From 53ecb2ae82acf42a4e36ff5283de641aa6442ed6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jul 2019 13:48:29 +0900 Subject: [PATCH 2030/5608] Reduce notification span during beatmap imports --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- osu.Game/OsuGame.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 65efcaa949..166ba5111c 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -386,7 +386,7 @@ namespace osu.Game.Beatmaps beatmap.OnlineBeatmapID = res.OnlineBeatmapID; }; - req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap}", e); }; + req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); }; // intentionally blocking to limit web request concurrency req.Perform(api); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 41b67f343a..ceaf0c3d5e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -589,7 +589,7 @@ namespace osu.Game { int recentLogCount = 0; - const double debounce = 5000; + const double debounce = 60000; Logger.NewEntry += entry => { From 91fa8a6552c4591ad78b891be086159aa556baf6 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 26 Jul 2019 08:09:18 +0300 Subject: [PATCH 2031/5608] Simplify null and any check --- osu.Game/Screens/Play/BreakOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 9091e54159..86a991c02e 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -132,7 +132,7 @@ namespace osu.Game.Screens.Play private void updateBreakTimeBindable() { - if (breaks == null || !breaks.Any()) + if (breaks?.Any() != true) { isBreakTime.Value = false; currentBreakIndex = 0; From 806d41daf499df87917abaf0c3dd8772ee557e75 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 26 Jul 2019 08:11:13 +0300 Subject: [PATCH 2032/5608] Add function to reset break index --- osu.Game/Screens/Play/BreakOverlay.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 86a991c02e..99361a5bd7 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Play breaks = value; // reset index in case the new breaks list is smaller than last one - currentBreakIndex = 0; + resetBreakIndex(); initializeBreaks(); } @@ -130,12 +130,17 @@ namespace osu.Game.Screens.Play updateBreakTimeBindable(); } + private void resetBreakIndex() + { + isBreakTime.Value = false; + currentBreakIndex = 0; + } + private void updateBreakTimeBindable() { if (breaks?.Any() != true) { - isBreakTime.Value = false; - currentBreakIndex = 0; + resetBreakIndex(); return; } From 3fa6804501a0d417feb4a876160fc83731101140 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 26 Jul 2019 08:12:32 +0300 Subject: [PATCH 2033/5608] Use better loops for moving index Easy to read, suggested by peppy --- osu.Game/Screens/Play/BreakOverlay.cs | 31 +++++++++++++++++---------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 99361a5bd7..f3decb38fb 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -144,19 +144,28 @@ namespace osu.Game.Screens.Play return; } - var lastIndex = currentBreakIndex; - var lookupDirection = Clock.CurrentTime > breaks[lastIndex].EndTime ? 1 : (Clock.CurrentTime < breaks[lastIndex].StartTime ? -1 : 0); + var time = Clock.CurrentTime; - while (Clock.CurrentTime < breaks[currentBreakIndex].StartTime || Clock.CurrentTime > breaks[currentBreakIndex].EndTime) + if (time > breaks[currentBreakIndex].EndTime) { - currentBreakIndex += lookupDirection; - - // restore index if out of bounds - if (currentBreakIndex < 0 || currentBreakIndex >= breaks.Count) + for (int i = currentBreakIndex; i < breaks.Count; i++) { - isBreakTime.Value = false; - currentBreakIndex = lastIndex; - return; + if (time <= breaks[i].EndTime) + { + currentBreakIndex = i; + break; + } + } + } + else if (time < breaks[currentBreakIndex].StartTime) + { + for (int i = currentBreakIndex; i >= 0; i--) + { + if (time >= breaks[i].StartTime) + { + currentBreakIndex = i; + break; + } } } @@ -164,7 +173,7 @@ namespace osu.Game.Screens.Play // If the current break doesn't have effects, IsBreakTime should be false. // We also assume that the overlay's fade out transform is "not break time". var currentBreak = breaks[currentBreakIndex]; - isBreakTime.Value = currentBreak.HasEffect && Clock.CurrentTime <= currentBreak.EndTime - fade_duration; + isBreakTime.Value = currentBreak.HasEffect && time >= currentBreak.StartTime && time <= currentBreak.EndTime - fade_duration; } private void initializeBreaks() From 6fac716ec704f1c07436d57a2979e95f0b504966 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 26 Jul 2019 08:15:46 +0300 Subject: [PATCH 2034/5608] Use container instead of fill flow --- .../Visual/Gameplay/TestSceneBreakOverlay.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs index ffa822d175..85f69bf058 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs @@ -27,13 +27,17 @@ namespace osu.Game.Tests.Visual.Gameplay public TestSceneBreakOverlay() { SpriteText breakTimeText; - Child = new FillFlowContainer + Child = new Container { RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, Children = new Drawable[] { - breakTimeText = new SpriteText(), + breakTimeText = new SpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Bottom = 35 }, + }, breakOverlay = new BreakOverlay(true) } }; From 3b0a48274380ef9616dcc029c0e217f62b477f98 Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 25 Jul 2019 23:10:00 -0700 Subject: [PATCH 2035/5608] Fix font weight of leaderboard mod filter --- osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index 8134cfb42d..d158186899 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -64,7 +64,7 @@ namespace osu.Game.Graphics.UserInterface Direction = FillDirection.Horizontal, Children = new Drawable[] { - text = new OsuSpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) }, + text = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) }, icon = new SpriteIcon { Size = new Vector2(14), @@ -84,7 +84,11 @@ namespace osu.Game.Graphics.UserInterface } }; - Current.ValueChanged += selected => { icon.Icon = selected.NewValue ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.Circle; }; + Current.ValueChanged += selected => + { + icon.Icon = selected.NewValue ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.Circle; + text.Font = text.Font.With(weight: selected.NewValue ? FontWeight.Bold : FontWeight.Medium); + }; } [BackgroundDependencyLoader] From 6765e9f7fa6a6d0dbfb75aa2e012ac18eef3e99c Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 26 Jul 2019 15:13:10 +0900 Subject: [PATCH 2036/5608] Combine into properties and update for framework changes --- osu.Game/Screens/Select/BeatmapCarousel.cs | 32 ++++++++++++++-------- osu.Game/Screens/Select/SongSelect.cs | 2 +- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 44aebf73c9..c8746579b5 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -56,8 +56,6 @@ namespace osu.Game.Screens.Select public override bool HandleNonPositionalInput => AllowSelection; public override bool HandlePositionalInput => AllowSelection; - protected override bool ConfinePositionalInput => true; - /// /// Whether carousel items have completed asynchronously loaded. /// @@ -344,11 +342,24 @@ namespace osu.Game.Screens.Select public bool AllowSelection = true; /// - /// The total bounds of what is displayable in the beatmap carousel. - /// + /// The total height of the displayable portion of the Beatmap Carousel. + /// + /// This is different from , since + /// the beatmap carousel bleeds into the and the + /// /// private float visibleHeight => DrawHeight + bleed_bottom + bleed_top; + /// + /// The position of the lower visible bound with respect to the current scroll position. + /// + private float visibleBottomBound => Current + DrawHeight + bleed_bottom; + + /// + /// The position of the upper visible bound with respect to the current scroll position. + /// + private float visibleUpperBound => Current - bleed_top; + public void FlushPendingFilterOperations() { if (PendingFilter?.Completed == false) @@ -425,6 +436,8 @@ namespace osu.Game.Screens.Select return true; } + protected override bool ReceiveSubTreePositionalInputAt(Vector2 screenSpacePos) => ReceivePositionalInputAt(screenSpacePos); + protected override void Update() { base.Update(); @@ -436,14 +449,14 @@ namespace osu.Game.Screens.Select updateScrollPosition(); // Remove all items that should no longer be on-screen - scrollableContent.RemoveAll(p => p.Y < Current - p.DrawHeight || p.Y > Current + visibleHeight || !p.IsPresent); + scrollableContent.RemoveAll(p => p.Y < visibleUpperBound - p.DrawHeight || p.Y > visibleBottomBound || !p.IsPresent); // Find index range of all items that should be on-screen Trace.Assert(Items.Count == yPositions.Count); - int firstIndex = yPositions.BinarySearch(Current - DrawableCarouselItem.MAX_HEIGHT - bleed_top); + int firstIndex = yPositions.BinarySearch(visibleUpperBound - DrawableCarouselItem.MAX_HEIGHT); if (firstIndex < 0) firstIndex = ~firstIndex; - int lastIndex = yPositions.BinarySearch(Current + visibleHeight + bleed_bottom); + int lastIndex = yPositions.BinarySearch(visibleBottomBound); if (lastIndex < 0) lastIndex = ~lastIndex; int notVisibleCount = 0; @@ -584,7 +597,6 @@ namespace osu.Game.Screens.Select float? setY = null; if (!d.IsLoaded || beatmap.Alpha == 0) // can't use IsPresent due to DrawableCarouselItem override. - // ReSharper disable once PossibleNullReferenceException (resharper broken?) setY = lastSet.Y + lastSet.DrawHeight + 5; if (d.IsLoaded) @@ -649,9 +661,7 @@ namespace osu.Game.Screens.Select /// Half the draw height of the carousel container's parent. private void updateItem(DrawableCarouselItem p, float halfHeight) { - var height = p.IsPresent ? p.DrawHeight : 0; - - float itemDrawY = p.Position.Y + bleed_top - Current + height / 2; + float itemDrawY = p.Position.Y - visibleUpperBound + p.DrawHeight / 2; float dist = Math.Abs(1f - itemDrawY / halfHeight); // Setting the origin position serves as an additive position on top of potential diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 73848cc740..7dd934f91a 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Select public abstract class SongSelect : OsuScreen, IKeyBindingHandler { private static readonly Vector2 wedged_container_size = new Vector2(0.5f, 245); - + protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; From 5a94a223147b4e774452154b41ed2c4794d30615 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 26 Jul 2019 09:17:39 +0300 Subject: [PATCH 2037/5608] Add a quick check if we're not in a break with current index --- osu.Game/Screens/Play/BreakOverlay.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index f3decb38fb..8f07b90b30 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -146,6 +146,16 @@ namespace osu.Game.Screens.Play var time = Clock.CurrentTime; + if (currentBreakIndex < breaks.Count - 1) + { + // Quick check if we're not in a break with our current index. + if (time > breaks[currentBreakIndex].EndTime && time < breaks[currentBreakIndex + 1].StartTime) + { + isBreakTime.Value = false; + return; + } + } + if (time > breaks[currentBreakIndex].EndTime) { for (int i = currentBreakIndex; i < breaks.Count; i++) From 0b6cfec21cd0463617158abddc1c65f67c73cc75 Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 25 Jul 2019 23:20:56 -0700 Subject: [PATCH 2038/5608] Hide leaderboard mod filter when on details tab --- osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index f66cd2b29a..f632a7f979 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -28,6 +28,8 @@ namespace osu.Game.Screens.Select private void invokeOnFilter() { OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value); + + modsCheckbox.FadeTo(tabs.Current.Value == BeatmapDetailTab.Details ? 0 : 1, 200, Easing.OutQuint); } [BackgroundDependencyLoader] From 0f6c6c7de0b981ab517e35b3f1a1f2c9aae31315 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 26 Jul 2019 15:22:29 +0900 Subject: [PATCH 2039/5608] consolidate halfheight as well --- osu.Game/Screens/Select/BeatmapCarousel.cs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index c8746579b5..cbe54cce1a 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -342,13 +342,13 @@ namespace osu.Game.Screens.Select public bool AllowSelection = true; /// - /// The total height of the displayable portion of the Beatmap Carousel. + /// Half the height of the visible content. /// - /// This is different from , since + /// This is different from the height of , since /// the beatmap carousel bleeds into the and the /// /// - private float visibleHeight => DrawHeight + bleed_bottom + bleed_top; + private float visibleHalfHeight => (DrawHeight + bleed_bottom + bleed_top) / 2; /// /// The position of the lower visible bound with respect to the current scroll position. @@ -508,9 +508,8 @@ namespace osu.Game.Screens.Select // Update externally controlled state of currently visible items // (e.g. x-offset and opacity). - float halfHeight = visibleHeight / 2; foreach (DrawableCarouselItem p in scrollableContent.Children) - updateItem(p, halfHeight); + updateItem(p); } protected override void Dispose(bool isDisposing) @@ -564,7 +563,7 @@ namespace osu.Game.Screens.Select yPositions.Clear(); - float currentY = visibleHeight / 2; + float currentY = visibleHalfHeight; DrawableCarouselBeatmapSet lastSet = null; scrollTarget = null; @@ -617,7 +616,7 @@ namespace osu.Game.Screens.Select currentY += d.DrawHeight + 5; } - currentY += visibleHeight / 2; + currentY += visibleHalfHeight; scrollableContent.Height = currentY; if (BeatmapSetsLoaded && (selectedBeatmapSet == null || selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected)) @@ -658,16 +657,15 @@ namespace osu.Game.Screens.Select /// the current scroll position. /// /// The item to be updated. - /// Half the draw height of the carousel container's parent. - private void updateItem(DrawableCarouselItem p, float halfHeight) + private void updateItem(DrawableCarouselItem p) { float itemDrawY = p.Position.Y - visibleUpperBound + p.DrawHeight / 2; - float dist = Math.Abs(1f - itemDrawY / halfHeight); + float dist = Math.Abs(1f - itemDrawY / visibleHalfHeight); // Setting the origin position serves as an additive position on top of potential // local transformation we may want to apply (e.g. when a item gets selected, we // may want to smoothly transform it leftwards.) - p.OriginPosition = new Vector2(-offsetX(dist, halfHeight), 0); + p.OriginPosition = new Vector2(-offsetX(dist, visibleHalfHeight), 0); // We are applying a multiplicative alpha (which is internally done by nesting an // additional container and setting that container's alpha) such that we can From 4c9e8527d86b57c65774b89c7db6ae552c9ae64b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 26 Jul 2019 09:24:53 +0300 Subject: [PATCH 2040/5608] Modify global index directly in the for loop Moves the global index to a near break if not in a break yet --- osu.Game/Screens/Play/BreakOverlay.cs | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 8f07b90b30..005cdd36d7 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -158,25 +158,15 @@ namespace osu.Game.Screens.Play if (time > breaks[currentBreakIndex].EndTime) { - for (int i = currentBreakIndex; i < breaks.Count; i++) - { - if (time <= breaks[i].EndTime) - { - currentBreakIndex = i; + for (; currentBreakIndex < breaks.Count; currentBreakIndex++) + if (time <= breaks[currentBreakIndex].EndTime) break; - } - } } else if (time < breaks[currentBreakIndex].StartTime) { - for (int i = currentBreakIndex; i >= 0; i--) - { - if (time >= breaks[i].StartTime) - { - currentBreakIndex = i; + for (; currentBreakIndex >= 0; currentBreakIndex--) + if (time >= breaks[currentBreakIndex].StartTime) break; - } - } } // This ensures that IsBreakTime is generally consistent with the overlay's transforms during a break. From 7fa419a38b0e47e9fb85b946e1a32042cb07f033 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jul 2019 15:49:21 +0900 Subject: [PATCH 2041/5608] Fix file layout order --- .../Select/BeatmapDetailAreaTabControl.cs | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index f632a7f979..ea466c2370 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -25,24 +25,6 @@ namespace osu.Game.Screens.Select private Bindable selectedTab; - private void invokeOnFilter() - { - OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value); - - modsCheckbox.FadeTo(tabs.Current.Value == BeatmapDetailTab.Details ? 0 : 1, 200, Easing.OutQuint); - } - - [BackgroundDependencyLoader] - private void load(OsuColour colour, OsuConfigManager config) - { - modsCheckbox.AccentColour = tabs.AccentColour = colour.YellowLight; - - selectedTab = config.GetBindable(OsuSetting.BeatmapDetailTab); - - tabs.Current.BindTo(selectedTab); - tabs.Current.TriggerChange(); - } - public BeatmapDetailAreaTabControl() { Height = HEIGHT; @@ -74,6 +56,24 @@ namespace osu.Game.Screens.Select tabs.Current.ValueChanged += _ => invokeOnFilter(); modsCheckbox.Current.ValueChanged += _ => invokeOnFilter(); } + + [BackgroundDependencyLoader] + private void load(OsuColour colour, OsuConfigManager config) + { + modsCheckbox.AccentColour = tabs.AccentColour = colour.YellowLight; + + selectedTab = config.GetBindable(OsuSetting.BeatmapDetailTab); + + tabs.Current.BindTo(selectedTab); + tabs.Current.TriggerChange(); + } + + private void invokeOnFilter() + { + OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value); + + modsCheckbox.FadeTo(tabs.Current.Value == BeatmapDetailTab.Details ? 0 : 1, 200, Easing.OutQuint); + } } public enum BeatmapDetailTab From 4d49aad1538c5de6b245d1a1eb72a39b9f847059 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jul 2019 15:51:51 +0900 Subject: [PATCH 2042/5608] Start not visible --- osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index ea466c2370..7f82d3cc12 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -50,6 +50,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Text = @"Mods", + Alpha = 0, }, }; From 9d080ec249bbb2237cd649ca168ad25f16ede974 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jul 2019 17:18:56 +0900 Subject: [PATCH 2043/5608] 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 b24493665e..385d630823 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@
- + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index c05cc6f9dd..71de5ac17f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 3b18039600..95ae4021e8 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 9ef858806b9d8cde669446abb7695efa042b9993 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jul 2019 17:48:19 +0900 Subject: [PATCH 2044/5608] Fix existing usage of Path --- osu.Game/Graphics/UserInterface/LineGraph.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs index 757a9a349c..714e953816 100644 --- a/osu.Game/Graphics/UserInterface/LineGraph.cs +++ b/osu.Game/Graphics/UserInterface/LineGraph.cs @@ -76,7 +76,12 @@ namespace osu.Game.Graphics.UserInterface { Masking = true, RelativeSizeAxes = Axes.Both, - Child = path = new SmoothPath { RelativeSizeAxes = Axes.Both, PathRadius = 1 } + Child = path = new SmoothPath + { + AutoSizeAxes = Axes.None, + RelativeSizeAxes = Axes.Both, + PathRadius = 1 + } }); } From 5317a8fa0f3cf0e537aacf3be0cde9c0c79bed08 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jul 2019 17:50:49 +0900 Subject: [PATCH 2045/5608] Update framework again --- 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 385d630823..0dd3c98116 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@
- + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 71de5ac17f..9f405d1099 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 95ae4021e8..4e8ce18c6f 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 6e09d857fd3d2ed0b18737e6565836fb6ea5bdf7 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 26 Jul 2019 19:00:07 +0900 Subject: [PATCH 2046/5608] Fix ValueChanged events being called out of order --- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 5606328575..5c98c72b75 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -53,7 +53,13 @@ namespace osu.Game.Graphics.Containers samplePopIn = audio.Samples.Get(@"UI/overlay-pop-in"); samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out"); + } + protected override void LoadComplete() + { + base.LoadComplete(); + + // This must be added after the base LoadComplete. The overlay may need to be hidden immediately if its disabled. State.ValueChanged += onStateChanged; } From 1b0f7b0459c28ff4684b580e2104b69978ddea58 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 26 Jul 2019 19:05:55 +0900 Subject: [PATCH 2047/5608] more detailed explanation --- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 5c98c72b75..158f96b46b 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -59,7 +59,8 @@ namespace osu.Game.Graphics.Containers { base.LoadComplete(); - // This must be added after the base LoadComplete. The overlay may need to be hidden immediately if its disabled. + // This must be added after the base LoadComplete. The overlay may need to be hidden immediately if its disabled, + // but the overlay doesn't get shown until after the stateChanged function from VisibilityContainer gets called. State.ValueChanged += onStateChanged; } From 699e366306c20050c91c5f639439a1a1afbeaaea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jul 2019 20:29:57 +0900 Subject: [PATCH 2048/5608] 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 0dd3c98116..6744590f0d 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@
- + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 9f405d1099..0b2baa982b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 4e8ce18c6f..55d1afa645 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From ba4045a761e790097d5015d6dd174bf4fdc8ba3a Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 27 Jul 2019 00:22:40 +0300 Subject: [PATCH 2049/5608] Fix transforming mods not working properly Hidden, Grow, Deflate, etc.. --- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 1d9d885527..181ae37a8b 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -147,12 +147,6 @@ namespace osu.Game.Rulesets.Objects.Drawables if (State.Value == newState && !force) return; - // apply any custom state overrides - ApplyCustomUpdateState?.Invoke(this, newState); - - if (newState == ArmedState.Hit) - PlaySamples(); - if (UseTransformStateManagement) { double transformTime = HitObject.StartTime - InitialLifetimeOffset; @@ -177,6 +171,12 @@ namespace osu.Game.Rulesets.Objects.Drawables state.Value = newState; UpdateState(newState); + + // apply any custom state overrides + ApplyCustomUpdateState?.Invoke(this, newState); + + if (newState == ArmedState.Hit) + PlaySamples(); } /// From 3571cb96b0b923405beeccfd4f306f55f3be7b6a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 27 Jul 2019 12:56:55 +0900 Subject: [PATCH 2050/5608] Fix broken merge --- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 40079f01e4..cf88b697d9 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -434,7 +434,7 @@ namespace osu.Game.Screens.Select return true; } - protected override bool ReceiveSubTreePositionalInputAt(Vector2 screenSpacePos) => ReceivePositionalInputAt(screenSpacePos); + protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos) => ReceivePositionalInputAt(screenSpacePos); protected override void Update() { From 56dbd94d167d76ca82ba64afa5ae1859880ce4d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 27 Jul 2019 19:46:46 +0900 Subject: [PATCH 2051/5608] Adjust tournament map pool layout to allow for larger pools --- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 46d4cfa98c..d32c0d6156 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -47,8 +47,8 @@ namespace osu.Game.Tournament.Screens.MapPool mapFlows = new FillFlowContainer> { Y = 100, - Spacing = new Vector2(10, 20), - Padding = new MarginPadding(50), + Spacing = new Vector2(10, 10), + Padding = new MarginPadding(25), Direction = FillDirection.Vertical, RelativeSizeAxes = Axes.Both, }, @@ -218,7 +218,7 @@ namespace osu.Game.Tournament.Screens.MapPool { mapFlows.Add(currentFlow = new FillFlowContainer { - Spacing = new Vector2(10, 20), + Spacing = new Vector2(10, 5), Direction = FillDirection.Full, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y From 46f17885c6378aaaeb19e7cd0043629cefa494ff Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 27 Jul 2019 15:51:14 +0300 Subject: [PATCH 2052/5608] Rewrite break overlay test --- .../Visual/Gameplay/TestSceneBreakOverlay.cs | 180 +++++++++++------- 1 file changed, 107 insertions(+), 73 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs index 85f69bf058..bbebd62b26 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs @@ -3,11 +3,10 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; -using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; +using osu.Framework.Timing; using osu.Game.Beatmaps.Timing; using osu.Game.Screens.Play; @@ -21,96 +20,131 @@ namespace osu.Game.Tests.Visual.Gameplay typeof(BreakOverlay), }; - private readonly BreakOverlay breakOverlay; - private readonly IBindable isBreakTimeBindable = new BindableBool(); + private readonly BreakOverlay breakOverlay, manualBreakOverlay; + private readonly ManualClock manualClock = new ManualClock(); + + private readonly IReadOnlyList testBreaks = new List + { + new BreakPeriod + { + StartTime = 1000, + EndTime = 5000, + }, + new BreakPeriod + { + StartTime = 6000, + EndTime = 13500, + }, + }; public TestSceneBreakOverlay() { - SpriteText breakTimeText; - Child = new Container + Add(breakOverlay = new BreakOverlay(true)); + Add(manualBreakOverlay = new BreakOverlay(true) { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - breakTimeText = new SpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Margin = new MarginPadding { Bottom = 35 }, - }, - breakOverlay = new BreakOverlay(true) - } - }; - - isBreakTimeBindable.BindTo(breakOverlay.IsBreakTime); - isBreakTimeBindable.BindValueChanged(e => breakTimeText.Text = $"IsBreakTime: {e.NewValue}", true); - - AddStep("2s break", () => startBreak(2000)); - AddStep("5s break", () => startBreak(5000)); - AddStep("10s break", () => startBreak(10000)); - AddStep("15s break", () => startBreak(15000)); - AddStep("2s, 2s", startMultipleBreaks); - AddStep("0.5s, 0.7s, 1s, 2s", startAnotherMultipleBreaks); + Alpha = 0, + Clock = new FramedClock(manualClock), + }); } - private void startBreak(double duration) + [Test] + public void TestShowBreaks() { - breakOverlay.Breaks = new List + loadClockStep(false); + + addShowBreakStep(2); + addShowBreakStep(5); + addShowBreakStep(15); + } + + [Test] + public void TestNoEffectsBreak() + { + var shortBreak = new BreakPeriod { EndTime = 500 }; + + loadClockStep(true); + AddStep("start short break", () => manualBreakOverlay.Breaks = new[] { shortBreak }); + + seekBreakStep("seek back to 0", 0, false); + addBreakSeeks(shortBreak, false); + } + + [Test] + public void TestMultipleBreaks() + { + loadClockStep(true); + AddStep("start multiple breaks", () => manualBreakOverlay.Breaks = testBreaks); + + seekBreakStep("seek back to 0", 0, false); + foreach (var b in testBreaks) + addBreakSeeks(b, false); + } + + [Test] + public void TestRewindBreaks() + { + loadClockStep(true); + AddStep("start multiple breaks in rewind", () => manualBreakOverlay.Breaks = testBreaks); + + seekBreakStep("seek back to 0", 0, false); + foreach (var b in testBreaks.Reverse()) + addBreakSeeks(b, true); + } + + [Test] + public void TestSkipBreaks() + { + loadClockStep(true); + AddStep("start multiple breaks with skipping", () => manualBreakOverlay.Breaks = testBreaks); + + var b = testBreaks.Last(); + seekBreakStep("seek back to 0", 0, false); + addBreakSeeks(b, false); + } + + private void addShowBreakStep(double seconds) + { + AddStep($"show '{seconds}s' break", () => breakOverlay.Breaks = new List { new BreakPeriod { StartTime = Clock.CurrentTime, - EndTime = Clock.CurrentTime + duration, + EndTime = Clock.CurrentTime + seconds * 1000, } - }; + }); } - private void startMultipleBreaks() + private void loadClockStep(bool loadManual) { - double currentTime = Clock.CurrentTime; - - breakOverlay.Breaks = new List + AddStep($"load {(loadManual ? "manual" : "normal")} clock", () => { - new BreakPeriod - { - StartTime = currentTime, - EndTime = currentTime + 2000, - }, - new BreakPeriod - { - StartTime = currentTime + 4000, - EndTime = currentTime + 6000, - } - }; + breakOverlay.FadeTo(loadManual ? 0 : 1); + manualBreakOverlay.FadeTo(loadManual ? 1 : 0); + }); } - private void startAnotherMultipleBreaks() + private void addBreakSeeks(BreakPeriod b, bool isReversed) { - double currentTime = Clock.CurrentTime; - - breakOverlay.Breaks = new List + if (isReversed) { - new BreakPeriod // Duration is less than 650 - too short to appear - { - StartTime = currentTime, - EndTime = currentTime + 500, - }, - new BreakPeriod - { - StartTime = currentTime + 1500, - EndTime = currentTime + 2200, - }, - new BreakPeriod - { - StartTime = currentTime + 3200, - EndTime = currentTime + 4200, - }, - new BreakPeriod - { - StartTime = currentTime + 5200, - EndTime = currentTime + 7200, - } - }; + seekBreakStep("seek to break after end", b.EndTime + 500, false); + seekBreakStep("seek to break end", b.EndTime, false); + seekBreakStep("seek to break middle", b.StartTime + b.Duration / 2, b.HasEffect); + seekBreakStep("seek to break start", b.StartTime, b.HasEffect); + } + else + { + seekBreakStep("seek to break start", b.StartTime, b.HasEffect); + seekBreakStep("seek to break middle", b.StartTime + b.Duration / 2, b.HasEffect); + seekBreakStep("seek to break end", b.EndTime, false); + seekBreakStep("seek to break after end", b.EndTime + 500, false); + } + } + + private void seekBreakStep(string seekStepDescription, double time, bool onBreak) + { + AddStep(seekStepDescription, () => manualClock.CurrentTime = time); + AddAssert($"is{(!onBreak ? " not " : " ")}break time", () => manualBreakOverlay.IsBreakTime.Value == onBreak); } } } From 6c580ac9d5c4456bc91a1f8a51f4d92457167669 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 27 Jul 2019 15:52:01 +0300 Subject: [PATCH 2053/5608] Use while loops instead --- osu.Game/Screens/Play/BreakOverlay.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index f96c176104..532109d14b 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -158,15 +158,13 @@ namespace osu.Game.Screens.Play if (time > breaks[currentBreakIndex].EndTime) { - for (; currentBreakIndex < breaks.Count; currentBreakIndex++) - if (time <= breaks[currentBreakIndex].EndTime) - break; + while (time > breaks[currentBreakIndex].EndTime && currentBreakIndex < breaks.Count - 1) + currentBreakIndex++; } else if (time < breaks[currentBreakIndex].StartTime) { - for (; currentBreakIndex >= 0; currentBreakIndex--) - if (time >= breaks[currentBreakIndex].StartTime) - break; + while (time < breaks[currentBreakIndex].StartTime && currentBreakIndex > 0) + currentBreakIndex--; } // This ensures that IsBreakTime is generally consistent with the overlay's transforms during a break. From 95b568eb4646c45b2169899d599114f86c350865 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 27 Jul 2019 15:52:30 +0300 Subject: [PATCH 2054/5608] Remove unnecessary condition --- osu.Game/Screens/Play/BreakOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 532109d14b..7e87c44259 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -161,7 +161,7 @@ namespace osu.Game.Screens.Play while (time > breaks[currentBreakIndex].EndTime && currentBreakIndex < breaks.Count - 1) currentBreakIndex++; } - else if (time < breaks[currentBreakIndex].StartTime) + else { while (time < breaks[currentBreakIndex].StartTime && currentBreakIndex > 0) currentBreakIndex--; From edf6453e04dfe28e092ceebe3f058e573f374ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20H=C3=BCbner?= Date: Sat, 27 Jul 2019 18:56:37 +0200 Subject: [PATCH 2055/5608] truncate long usernames in private chat --- osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs index 9e87bae864..4f93beee17 100644 --- a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs @@ -65,6 +65,12 @@ namespace osu.Game.Overlays.Chat.Tabs Text.X = ChatOverlay.TAB_AREA_HEIGHT; TextBold.X = ChatOverlay.TAB_AREA_HEIGHT; + + Text.Width = 100f; + TextBold.Width = 100f; + + Text.Truncate = true; + TextBold.Truncate = true; } protected override bool ShowCloseOnHover => false; From 4d49b38277ec35df3723eac519e6cba80f681e1a Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 28 Jul 2019 05:21:27 +0300 Subject: [PATCH 2056/5608] Add a function for loading a list of breaks --- .../Visual/Gameplay/TestSceneBreakOverlay.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs index bbebd62b26..c238f42b60 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs @@ -63,9 +63,8 @@ namespace osu.Game.Tests.Visual.Gameplay var shortBreak = new BreakPeriod { EndTime = 500 }; loadClockStep(true); - AddStep("start short break", () => manualBreakOverlay.Breaks = new[] { shortBreak }); + loadBreaksStep("short break", new[] { shortBreak }); - seekBreakStep("seek back to 0", 0, false); addBreakSeeks(shortBreak, false); } @@ -73,9 +72,8 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestMultipleBreaks() { loadClockStep(true); - AddStep("start multiple breaks", () => manualBreakOverlay.Breaks = testBreaks); + loadBreaksStep("multiple breaks", testBreaks); - seekBreakStep("seek back to 0", 0, false); foreach (var b in testBreaks) addBreakSeeks(b, false); } @@ -84,9 +82,8 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestRewindBreaks() { loadClockStep(true); - AddStep("start multiple breaks in rewind", () => manualBreakOverlay.Breaks = testBreaks); + loadBreaksStep("multiple breaks", testBreaks); - seekBreakStep("seek back to 0", 0, false); foreach (var b in testBreaks.Reverse()) addBreakSeeks(b, true); } @@ -95,10 +92,9 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestSkipBreaks() { loadClockStep(true); - AddStep("start multiple breaks with skipping", () => manualBreakOverlay.Breaks = testBreaks); + loadBreaksStep("multiple breaks", testBreaks); var b = testBreaks.Last(); - seekBreakStep("seek back to 0", 0, false); addBreakSeeks(b, false); } @@ -123,6 +119,12 @@ namespace osu.Game.Tests.Visual.Gameplay }); } + private void loadBreaksStep(string breakDescription, IReadOnlyList breaks) + { + AddStep($"load {breakDescription}", () => manualBreakOverlay.Breaks = breaks); + seekBreakStep("seek back to 0", 0, false); + } + private void addBreakSeeks(BreakPeriod b, bool isReversed) { if (isReversed) From 4143bafd67ac14e61b98855797a96bec2fac4647 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 28 Jul 2019 05:22:09 +0300 Subject: [PATCH 2057/5608] More simplifies --- osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs index c238f42b60..d2db92c855 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.Gameplay }; private readonly BreakOverlay breakOverlay, manualBreakOverlay; - private readonly ManualClock manualClock = new ManualClock(); + private readonly ManualClock manualClock; private readonly IReadOnlyList testBreaks = new List { @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Gameplay Add(manualBreakOverlay = new BreakOverlay(true) { Alpha = 0, - Clock = new FramedClock(manualClock), + Clock = new FramedClock(manualClock = new ManualClock()), }); } @@ -94,8 +94,7 @@ namespace osu.Game.Tests.Visual.Gameplay loadClockStep(true); loadBreaksStep("multiple breaks", testBreaks); - var b = testBreaks.Last(); - addBreakSeeks(b, false); + addBreakSeeks(testBreaks.Last(), false); } private void addShowBreakStep(double seconds) From bd2fce4bb7997dde45486bd0ff2cbecbcdce6826 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Sun, 28 Jul 2019 13:45:54 +0900 Subject: [PATCH 2058/5608] don't use extra container --- osu.Game/OsuGame.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e71344738b..e5099f3c2f 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -416,16 +416,9 @@ namespace osu.Game screenStack.Exit(); } }, - new Container - { - RelativeSizeAxes = Axes.Both, - Children = new[] - { - screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, - backButton.CreateProxy(), - logoContainer = new Container { RelativeSizeAxes = Axes.Both }, - } - } + screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, + backButton.CreateProxy(), + logoContainer = new Container { RelativeSizeAxes = Axes.Both }, } }, overlayContent = new Container { RelativeSizeAxes = Axes.Both }, From 1dd3a6630082b0e0b88b43be089f471b54d19aec Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 28 Jul 2019 09:16:19 +0300 Subject: [PATCH 2059/5608] Remove unnecessary index resets --- osu.Game/Screens/Play/BreakOverlay.cs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 7e87c44259..726c825c84 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -33,7 +33,8 @@ namespace osu.Game.Screens.Play breaks = value; // reset index in case the new breaks list is smaller than last one - resetBreakIndex(); + isBreakTime.Value = false; + currentBreakIndex = 0; initializeBreaks(); } @@ -126,23 +127,13 @@ namespace osu.Game.Screens.Play protected override void Update() { base.Update(); - updateBreakTimeBindable(); } - private void resetBreakIndex() - { - isBreakTime.Value = false; - currentBreakIndex = 0; - } - private void updateBreakTimeBindable() { if (breaks?.Any() != true) - { - resetBreakIndex(); return; - } var time = Clock.CurrentTime; From 5bf0277fd401b5d668bd8939ba7a41264a1ca6c9 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 28 Jul 2019 09:17:13 +0300 Subject: [PATCH 2060/5608] Remove unnecessary quick check Not saving for anything --- osu.Game/Screens/Play/BreakOverlay.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 726c825c84..e3e4014eb3 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -137,16 +137,6 @@ namespace osu.Game.Screens.Play var time = Clock.CurrentTime; - if (currentBreakIndex < breaks.Count - 1) - { - // Quick check if we're not in a break with our current index. - if (time > breaks[currentBreakIndex].EndTime && time < breaks[currentBreakIndex + 1].StartTime) - { - isBreakTime.Value = false; - return; - } - } - if (time > breaks[currentBreakIndex].EndTime) { while (time > breaks[currentBreakIndex].EndTime && currentBreakIndex < breaks.Count - 1) From 37c32659429787f33f3a78005142d5803feb1ac8 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 28 Jul 2019 09:21:54 +0300 Subject: [PATCH 2061/5608] Manually call the update function on retrieving IsBreakTime value --- .../Visual/Gameplay/TestSceneBreakOverlay.cs | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs index d2db92c855..890c575eb6 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; -using osu.Framework.Graphics; +using osu.Framework.Bindables; using osu.Framework.Timing; using osu.Game.Beatmaps.Timing; using osu.Game.Screens.Play; @@ -20,8 +20,9 @@ namespace osu.Game.Tests.Visual.Gameplay typeof(BreakOverlay), }; - private readonly BreakOverlay breakOverlay, manualBreakOverlay; private readonly ManualClock manualClock; + private readonly BreakOverlay breakOverlay; + private readonly TestBreakOverlay manualBreakOverlay; private readonly IReadOnlyList testBreaks = new List { @@ -40,7 +41,7 @@ namespace osu.Game.Tests.Visual.Gameplay public TestSceneBreakOverlay() { Add(breakOverlay = new BreakOverlay(true)); - Add(manualBreakOverlay = new BreakOverlay(true) + Add(manualBreakOverlay = new TestBreakOverlay(true) { Alpha = 0, Clock = new FramedClock(manualClock = new ManualClock()), @@ -147,5 +148,24 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep(seekStepDescription, () => manualClock.CurrentTime = time); AddAssert($"is{(!onBreak ? " not " : " ")}break time", () => manualBreakOverlay.IsBreakTime.Value == onBreak); } + + private class TestBreakOverlay : BreakOverlay + { + public new IBindable IsBreakTime + { + get + { + // Manually call the update function as it might take up to 2 frames for an automatic update to happen + Update(); + + return base.IsBreakTime; + } + } + + public TestBreakOverlay(bool letterboxing) + : base(letterboxing) + { + } + } } } From c9e45f8cdc2e5b26e6d099e21bf2e7d731fa2dab Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 28 Jul 2019 09:27:02 +0300 Subject: [PATCH 2062/5608] Assign clocks instead of creating 2 separate overlays --- .../Visual/Gameplay/TestSceneBreakOverlay.cs | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs index 890c575eb6..eaae647dbc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs @@ -20,9 +20,7 @@ namespace osu.Game.Tests.Visual.Gameplay typeof(BreakOverlay), }; - private readonly ManualClock manualClock; - private readonly BreakOverlay breakOverlay; - private readonly TestBreakOverlay manualBreakOverlay; + private readonly TestBreakOverlay breakOverlay; private readonly IReadOnlyList testBreaks = new List { @@ -40,12 +38,7 @@ namespace osu.Game.Tests.Visual.Gameplay public TestSceneBreakOverlay() { - Add(breakOverlay = new BreakOverlay(true)); - Add(manualBreakOverlay = new TestBreakOverlay(true) - { - Alpha = 0, - Clock = new FramedClock(manualClock = new ManualClock()), - }); + Add(breakOverlay = new TestBreakOverlay(true)); } [Test] @@ -112,16 +105,12 @@ namespace osu.Game.Tests.Visual.Gameplay private void loadClockStep(bool loadManual) { - AddStep($"load {(loadManual ? "manual" : "normal")} clock", () => - { - breakOverlay.FadeTo(loadManual ? 0 : 1); - manualBreakOverlay.FadeTo(loadManual ? 1 : 0); - }); + AddStep($"load {(loadManual ? "manual" : "normal")} clock", () => breakOverlay.SwitchClock(loadManual)); } private void loadBreaksStep(string breakDescription, IReadOnlyList breaks) { - AddStep($"load {breakDescription}", () => manualBreakOverlay.Breaks = breaks); + AddStep($"load {breakDescription}", () => breakOverlay.Breaks = breaks); seekBreakStep("seek back to 0", 0, false); } @@ -145,12 +134,22 @@ namespace osu.Game.Tests.Visual.Gameplay private void seekBreakStep(string seekStepDescription, double time, bool onBreak) { - AddStep(seekStepDescription, () => manualClock.CurrentTime = time); - AddAssert($"is{(!onBreak ? " not " : " ")}break time", () => manualBreakOverlay.IsBreakTime.Value == onBreak); + AddStep(seekStepDescription, () => breakOverlay.ManualClockTime = time); + AddAssert($"is{(!onBreak ? " not " : " ")}break time", () => breakOverlay.IsBreakTime.Value == onBreak); } private class TestBreakOverlay : BreakOverlay { + private readonly FramedClock framedManualClock; + private readonly ManualClock manualClock; + private IFrameBasedClock normalClock; + + public double ManualClockTime + { + get => manualClock.CurrentTime; + set => manualClock.CurrentTime = value; + } + public new IBindable IsBreakTime { get @@ -165,6 +164,15 @@ namespace osu.Game.Tests.Visual.Gameplay public TestBreakOverlay(bool letterboxing) : base(letterboxing) { + framedManualClock = new FramedClock(manualClock = new ManualClock()); + } + + public void SwitchClock(bool setManual) => Clock = setManual ? framedManualClock : normalClock; + + protected override void LoadComplete() + { + base.LoadComplete(); + normalClock = Clock; } } } From c6d4ce0f8a8bb0787744bc2d337231f8bcdb3f9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20H=C3=BCbner?= Date: Sun, 28 Jul 2019 12:14:06 +0200 Subject: [PATCH 2063/5608] revert truncation in derived class --- osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs index 4f93beee17..9e87bae864 100644 --- a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs @@ -65,12 +65,6 @@ namespace osu.Game.Overlays.Chat.Tabs Text.X = ChatOverlay.TAB_AREA_HEIGHT; TextBold.X = ChatOverlay.TAB_AREA_HEIGHT; - - Text.Width = 100f; - TextBold.Width = 100f; - - Text.Truncate = true; - TextBold.Truncate = true; } protected override bool ShowCloseOnHover => false; From df8d4d896639867418b5ad5199170a1931e6cdfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20H=C3=BCbner?= Date: Sun, 28 Jul 2019 12:16:32 +0200 Subject: [PATCH 2064/5608] add truncation to base class --- osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs | 2 ++ osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs index 2a3dd55c71..7007b0183d 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs @@ -102,6 +102,8 @@ namespace osu.Game.Overlays.Chat.Tabs Anchor = Anchor.CentreLeft, Text = value.ToString(), Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold) + Width = 115f, + Truncate = true, }, CloseButton = new TabCloseButton { diff --git a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs index 9e87bae864..194e62e52a 100644 --- a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs @@ -65,6 +65,8 @@ namespace osu.Game.Overlays.Chat.Tabs Text.X = ChatOverlay.TAB_AREA_HEIGHT; TextBold.X = ChatOverlay.TAB_AREA_HEIGHT; + + Text.Width = 100f; } protected override bool ShowCloseOnHover => false; From f7b9ddb48ce4dffa56129344a1591e623e502597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20H=C3=BCbner?= Date: Sun, 28 Jul 2019 12:40:21 +0200 Subject: [PATCH 2065/5608] combine Text and TextBold --- .../Chat/Tabs/ChannelSelectorTabItem.cs | 3 ++- osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs | 23 +++++++------------ .../Chat/Tabs/PrivateChannelTabItem.cs | 1 - 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs index 7386bffb1a..ba4f046b66 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs @@ -13,6 +13,8 @@ namespace osu.Game.Overlays.Chat.Tabs public override bool IsSwitchable => false; + protected override bool IsBoldWhenActive => false; + public ChannelSelectorTabItem() : base(new ChannelSelectorTabChannel()) { @@ -22,7 +24,6 @@ namespace osu.Game.Overlays.Chat.Tabs Icon.Alpha = 0; Text.Font = Text.Font.With(size: 45); - TextBold.Font = Text.Font.With(size: 45); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs index 7007b0183d..ea7875ac63 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs @@ -29,7 +29,6 @@ namespace osu.Game.Overlays.Chat.Tabs public override bool IsRemovable => !Pinned; protected readonly SpriteText Text; - protected readonly SpriteText TextBold; protected readonly ClickableContainer CloseButton; private readonly Box box; private readonly Box highlightBox; @@ -92,16 +91,7 @@ namespace osu.Game.Overlays.Chat.Tabs Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, Text = value.ToString(), - Font = OsuFont.GetFont(size: 18) - }, - TextBold = new OsuSpriteText - { - Alpha = 0, - Margin = new MarginPadding(5), - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - Text = value.ToString(), - Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold) + Font = OsuFont.GetFont(size: 18), Width = 115f, Truncate = true, }, @@ -125,6 +115,8 @@ namespace osu.Game.Overlays.Chat.Tabs protected virtual bool ShowCloseOnHover => true; + protected virtual bool IsBoldWhenActive => true; + protected override bool OnHover(HoverEvent e) { if (IsRemovable && ShowCloseOnHover) @@ -205,8 +197,10 @@ namespace osu.Game.Overlays.Chat.Tabs box.FadeColour(BackgroundActive, TRANSITION_LENGTH, Easing.OutQuint); highlightBox.FadeIn(TRANSITION_LENGTH, Easing.OutQuint); - Text.FadeOut(TRANSITION_LENGTH, Easing.OutQuint); - TextBold.FadeIn(TRANSITION_LENGTH, Easing.OutQuint); + if (IsBoldWhenActive) + { + Text.Font = Text.Font.With(weight: FontWeight.Bold); + } } protected virtual void FadeInactive() @@ -218,8 +212,7 @@ namespace osu.Game.Overlays.Chat.Tabs box.FadeColour(BackgroundInactive, TRANSITION_LENGTH, Easing.OutQuint); highlightBox.FadeOut(TRANSITION_LENGTH, Easing.OutQuint); - Text.FadeIn(TRANSITION_LENGTH, Easing.OutQuint); - TextBold.FadeOut(TRANSITION_LENGTH, Easing.OutQuint); + Text.Font = Text.Font.With(weight: FontWeight.Medium); } protected override void OnActivated() => updateState(); diff --git a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs index 194e62e52a..97f695c73a 100644 --- a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs @@ -64,7 +64,6 @@ namespace osu.Game.Overlays.Chat.Tabs avatar.OnLoadComplete += d => d.FadeInFromZero(300, Easing.OutQuint); Text.X = ChatOverlay.TAB_AREA_HEIGHT; - TextBold.X = ChatOverlay.TAB_AREA_HEIGHT; Text.Width = 100f; } From 088c04a20fa32b8c42ab7bf4ecac1acb363c0d81 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 28 Jul 2019 15:32:29 +0900 Subject: [PATCH 2066/5608] Revert "Fix BackButton handling escape before all other elements (#5440)" This reverts commit 17a6563f4c5d0c7e3a4dfac5469c65866de311aa. --- osu.Game/OsuGame.cs | 5 ++--- osu.Game/Screens/Select/Footer.cs | 5 +++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e5099f3c2f..ceaf0c3d5e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -404,8 +404,9 @@ namespace osu.Game screenContainer = new ScalingContainer(ScalingMode.ExcludeOverlays) { RelativeSizeAxes = Axes.Both, - Children = new[] + Children = new Drawable[] { + screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, backButton = new BackButton { Anchor = Anchor.BottomLeft, @@ -416,8 +417,6 @@ namespace osu.Game screenStack.Exit(); } }, - screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, - backButton.CreateProxy(), logoContainer = new Container { RelativeSizeAxes = Axes.Both }, } }, diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index 71641cab5d..0680711f1c 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -9,6 +9,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Select @@ -102,5 +103,9 @@ namespace osu.Game.Screens.Select updateModeLight(); } + + protected override bool OnMouseDown(MouseDownEvent e) => true; + + protected override bool OnClick(ClickEvent e) => true; } } From 07f905d21c7944d1969b3435fedc703746c8d98a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jul 2019 01:00:41 +0900 Subject: [PATCH 2067/5608] Tidy up code and fix explode animations not playing correctly --- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 89 ++++++++++------------ 1 file changed, 40 insertions(+), 49 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index 102275043c..18267a2e0e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -1,95 +1,86 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; using System.Linq; -using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using OpenTK; +using osuTK; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModSpinIn : Mod, IApplicableToDrawableHitObjects + public class OsuModSpinIn : Mod, IApplicableToDrawableHitObjects, IReadFromConfig { public override string Name => "Spin In"; - public override string ShortenedName => "SI"; - public override FontAwesome Icon => FontAwesome.fa_rotate_right; + public override string Acronym => "SI"; + public override IconUsage Icon => FontAwesome.Solid.Undo; public override ModType Type => ModType.Fun; public override string Description => "Circles spin in. No approach circles."; public override double ScoreMultiplier => 1; public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden) }; private const int rotate_offset = 360; - private const float rotate_starting_width = 2.0f; + private const float rotate_starting_width = 2; + private Bindable increaseFirstObjectVisibility = new Bindable(); + + public void ReadFromConfig(OsuConfigManager config) + { + increaseFirstObjectVisibility = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility); + } public void ApplyToDrawableHitObjects(IEnumerable drawables) { - foreach (var drawable in drawables) + foreach (var drawable in drawables.Skip(increaseFirstObjectVisibility.Value ? 1 : 0)) { - // Need to add custom update in order to disable fade - drawable.ApplyCustomUpdateState += ApplyZoomState; + switch (drawable) + { + case DrawableSpinner _: + continue; + + default: + drawable.ApplyCustomUpdateState += applyZoomState; + break; + } } } - protected void ApplyZoomState(DrawableHitObject drawable, ArmedState state) + private void applyZoomState(DrawableHitObject drawable, ArmedState state) { - if (!(drawable is DrawableOsuHitObject)) return; - if (state != ArmedState.Idle) return; - var h = (OsuHitObject)drawable.HitObject; - var appearTime = h.StartTime - h.TimePreempt + 1; - var moveDuration = h.TimePreempt - 1; - switch (drawable) { case DrawableHitCircle circle: - // Disable Fade - circle.Transforms - .Where(t => t.TargetMember == "Alpha") - .ForEach(t => circle.RemoveTransform(t)); - - using (circle.BeginAbsoluteSequence(appearTime, true)) - { - var origScale = drawable.Scale; - var origRotate = circle.Rotation; - - circle - .RotateTo(origRotate+rotate_offset) - .RotateTo(origRotate, moveDuration, Easing.InOutSine) - .ScaleTo(origScale * new Vector2(rotate_starting_width, 0)) - .ScaleTo(origScale, moveDuration, Easing.InOutSine) - .FadeTo(1); - } - - using (circle.ApproachCircle.BeginAbsoluteSequence(appearTime, true)) + using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) { circle.ApproachCircle.Hide(); + + circle.RotateTo(rotate_offset).Then().RotateTo(0, h.TimePreempt, Easing.InOutSine); + circle.ScaleTo(new Vector2(rotate_starting_width, 0)).Then().ScaleTo(1, h.TimePreempt, Easing.InOutSine); + + // bypass fade in. + if (state == ArmedState.Idle) + circle.FadeIn(); } break; case DrawableSlider slider: - // Disable fade - slider.Transforms - .Where(t => t.TargetMember == "Alpha") - .ForEach(t => slider.RemoveTransform(t)); - - using (slider.BeginAbsoluteSequence(appearTime, true)) + using (slider.BeginAbsoluteSequence(h.StartTime - h.TimePreempt)) { - var origScale = slider.Scale; + slider.ScaleTo(0).Then().ScaleTo(1, h.TimePreempt, Easing.InOutSine); - slider - .ScaleTo(0) - .ScaleTo(origScale, moveDuration, Easing.InOutSine) - .FadeTo(1); + // bypass fade in. + if (state == ArmedState.Idle) + slider.FadeIn(); } break; From 3e74079d0278a3876b41497acb4206b2d312fa06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jul 2019 01:15:54 +0900 Subject: [PATCH 2068/5608] Add incompatibility with scale tween mods --- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 4 +++- osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index 18267a2e0e..62b5ecfd58 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -24,7 +24,9 @@ namespace osu.Game.Rulesets.Osu.Mods public override ModType Type => ModType.Fun; public override string Description => "Circles spin in. No approach circles."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden) }; + + // todo: this mod should be able to be compatible with hidden with a bit of further implementation. + public override Type[] IncompatibleMods => new[] { typeof(OsuModeObjectScaleTween), typeof(OsuModHidden) }; private const int rotate_offset = 360; private const float rotate_starting_width = 2; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs b/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs index ad6a15718a..e926ade41b 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; @@ -28,6 +29,8 @@ namespace osu.Game.Rulesets.Osu.Mods private Bindable increaseFirstObjectVisibility = new Bindable(); + public override Type[] IncompatibleMods => new[] { typeof(OsuModSpinIn) }; + public void ReadFromConfig(OsuConfigManager config) { increaseFirstObjectVisibility = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility); @@ -64,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Mods case DrawableSlider _: case DrawableHitCircle _: { - using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt)) drawable.ScaleTo(StartScale).Then().ScaleTo(EndScale, h.TimePreempt, Easing.OutSine); break; } @@ -75,7 +78,7 @@ namespace osu.Game.Rulesets.Osu.Mods { case DrawableHitCircle circle: // we don't want to see the approach circle - using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt)) circle.ApproachCircle.Hide(); break; } From de8f5028714007f6b0051793f60436555c29cb40 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jul 2019 02:46:33 +0900 Subject: [PATCH 2069/5608] Add test --- osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index 4d3992ce13..9196513a55 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Online private TestChatOverlay chatOverlay; private ChannelManager channelManager; - private readonly Channel channel1 = new Channel(new User()) { Name = "test1" }; + private readonly Channel channel1 = new Channel(new User()) { Name = "test really long username" }; private readonly Channel channel2 = new Channel(new User()) { Name = "test2" }; [SetUp] From 663f34d3d8643221feee276eb6923cc95a5b90a2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jul 2019 02:47:26 +0900 Subject: [PATCH 2070/5608] Remove width specifications --- .../Overlays/Chat/Tabs/ChannelSelectorTabItem.cs | 1 + osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs | 12 ++++++++++-- osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs | 6 ++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs index ba4f046b66..d5d9a6c2ce 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs @@ -24,6 +24,7 @@ namespace osu.Game.Overlays.Chat.Tabs Icon.Alpha = 0; Text.Font = Text.Font.With(size: 45); + Text.Truncate = false; } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs index ea7875ac63..3de321e127 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs @@ -87,12 +87,16 @@ namespace osu.Game.Overlays.Chat.Tabs }, Text = new OsuSpriteText { - Margin = new MarginPadding(5), Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, Text = value.ToString(), Font = OsuFont.GetFont(size: 18), - Width = 115f, + Padding = new MarginPadding(5) + { + Left = LeftTextPadding, + Right = RightTextPadding, + }, + RelativeSizeAxes = Axes.X, Truncate = true, }, CloseButton = new TabCloseButton @@ -111,6 +115,10 @@ namespace osu.Game.Overlays.Chat.Tabs }; } + protected virtual float LeftTextPadding => 5; + + protected virtual float RightTextPadding => IsRemovable ? 40 : 5; + protected virtual IconUsage DisplayIcon => FontAwesome.Solid.Hashtag; protected virtual bool ShowCloseOnHover => true; diff --git a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs index 97f695c73a..1413b8fe78 100644 --- a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs @@ -62,12 +62,10 @@ namespace osu.Game.Overlays.Chat.Tabs }); avatar.OnLoadComplete += d => d.FadeInFromZero(300, Easing.OutQuint); - - Text.X = ChatOverlay.TAB_AREA_HEIGHT; - - Text.Width = 100f; } + protected override float LeftTextPadding => base.LeftTextPadding + ChatOverlay.TAB_AREA_HEIGHT; + protected override bool ShowCloseOnHover => false; protected override void FadeActive() From 316b11d08b0647041c08aa5e839cb5adf1ccc11b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20H=C3=BCbner?= Date: Sun, 28 Jul 2019 20:36:21 +0200 Subject: [PATCH 2071/5608] use single line if-statement --- osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs index 3de321e127..266e68f17e 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs @@ -205,10 +205,7 @@ namespace osu.Game.Overlays.Chat.Tabs box.FadeColour(BackgroundActive, TRANSITION_LENGTH, Easing.OutQuint); highlightBox.FadeIn(TRANSITION_LENGTH, Easing.OutQuint); - if (IsBoldWhenActive) - { - Text.Font = Text.Font.With(weight: FontWeight.Bold); - } + if (IsBoldWhenActive) Text.Font = Text.Font.With(weight: FontWeight.Bold); } protected virtual void FadeInactive() From f4effd12c301ecece374df443cc08bd0e2bf2958 Mon Sep 17 00:00:00 2001 From: jorolf Date: Sun, 28 Jul 2019 21:04:55 +0200 Subject: [PATCH 2072/5608] make legacy skins animatable --- osu.Game/Skinning/LegacySkin.cs | 38 +++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 513a024a36..24c6c9e4ec 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; +using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; @@ -52,22 +53,29 @@ namespace osu.Game.Skinning public override Drawable GetDrawableComponent(string componentName) { + bool animatable = false; + (bool looping, double frametime) animationData = (false, 1000 / 60d); + switch (componentName) { case "Play/Miss": componentName = "hit0"; + animatable = true; break; case "Play/Meh": componentName = "hit50"; + animatable = true; break; case "Play/Good": componentName = "hit100"; + animatable = true; break; case "Play/Great": componentName = "hit300"; + animatable = true; break; case "Play/osu/number-text": @@ -81,15 +89,31 @@ namespace osu.Game.Skinning }; } - // temporary allowance is given for skins the fact that stable handles non-animatable items such as hitcircles (incorrectly) - // by (incorrectly) displaying the first frame of animation rather than the non-animated version. - // users have used this to "hide" certain elements like hit300. - var texture = GetTexture($"{componentName}-0") ?? GetTexture(componentName); + var texture = GetTexture($"{componentName}-0"); - if (texture == null) - return null; + if (texture != null && animatable) + { + var animation = new TextureAnimation { DefaultFrameLength = animationData.frametime }; - return new Sprite { Texture = texture }; + for (int i = 1; texture != null; i++) + { + animation.AddFrame(texture); + texture = GetTexture($"{componentName}-{i}"); + } + + animation.Repeat = animationData.looping; + + return animation; + } + else + { + texture = GetTexture(componentName); + + if (texture == null) + return null; + + return new Sprite { Texture = texture }; + } } public override Texture GetTexture(string componentName) From 26fc782de9cb40dc36960b6c7764fa0c024a83ce Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 29 Jul 2019 10:33:34 +0900 Subject: [PATCH 2073/5608] Don't exit if screenstack is null --- osu.Game/Screens/Multi/Multiplayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 9ffd620e55..90806bab6e 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -212,7 +212,7 @@ namespace osu.Game.Screens.Multi public override bool OnExiting(IScreen next) { - if (!(screenStack.CurrentScreen is LoungeSubScreen)) + if (screenStack.CurrentScreen != null && !(screenStack.CurrentScreen is LoungeSubScreen)) { screenStack.Exit(); return true; From 4b5fb84888dd7afed64bdafc497031675182489d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 29 Jul 2019 11:02:44 +0900 Subject: [PATCH 2074/5608] Rewrite comment --- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 158f96b46b..c33e980a9a 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -59,8 +59,8 @@ namespace osu.Game.Graphics.Containers { base.LoadComplete(); - // This must be added after the base LoadComplete. The overlay may need to be hidden immediately if its disabled, - // but the overlay doesn't get shown until after the stateChanged function from VisibilityContainer gets called. + // This must be added after the base LoadComplete, since onStateChanged contains logic that + // must be run after other state change logic has been completed. State.ValueChanged += onStateChanged; } From 2e242075b486692326ad6efe0fc7e7ed97750e60 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 29 Jul 2019 14:30:46 +0900 Subject: [PATCH 2075/5608] Remove and re-add backbutton instead and add tests --- .../Visual/Menus/TestSceneExitingScreens.cs | 152 ++++++++++++++++++ .../Input/Bindings/GlobalActionContainer.cs | 29 +++- osu.Game/OsuGame.cs | 33 ++-- 3 files changed, 196 insertions(+), 18 deletions(-) create mode 100644 osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs diff --git a/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs b/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs new file mode 100644 index 0000000000..fafaa3a397 --- /dev/null +++ b/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs @@ -0,0 +1,152 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Platform; +using osu.Framework.Screens; +using osu.Framework.Testing; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Mods; +using osu.Game.Screens.Menu; +using osu.Game.Screens.Select; +using osuTK.Graphics; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.Menus +{ + public class TestSceneExitingScreens : ManualInputManagerTestScene + { + private readonly TestOsuGame osuGame = new TestOsuGame(); + + [BackgroundDependencyLoader] + private void load(GameHost gameHost) + { + osuGame.SetHost(gameHost); + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + osuGame + }; + } + + [SetUpSteps] + public void SetUpSteps() + { + AddUntilStep("wait for load", () => osuGame.IsLoaded); + AddUntilStep("wait for main menu", () => + { + var current = osuGame.ScreenStack?.CurrentScreen; + + switch (current) + { + case null: + case Intro _: + case Disclaimer _: + return false; + + case MainMenu _: + return true; + + default: + current.Exit(); + return false; + } + }); + } + + [Test] + public void TestExitingSongSelectWithEscape() + { + TestSongSelect songSelect = null; + + AddStep("Push songselect", () => osuGame.ScreenStack.Push(songSelect = new TestSongSelect())); + AddUntilStep("Wait for song select", () => songSelect.IsCurrentScreen()); + AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show()); + AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); + AddStep("Press escape", () => pressAndRelease(Key.Escape)); + AddAssert("Overlay was hidden", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden); + exitViaEscapeAndConfirm(); + } + + [Test] + public void TestExitingSongSelectWithClick() + { + TestSongSelect songSelect = null; + + AddStep("Push songselect", () => osuGame.ScreenStack.Push(songSelect = new TestSongSelect())); + AddUntilStep("Wait for song select", () => songSelect.IsCurrentScreen()); + AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show()); + AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); + AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(osuGame.BackButton)); + + // BackButton handles hover using its child button, so this checks whether or not any of BackButton's children are hovered. + AddUntilStep("Back button is hovered", () => InputManager.HoveredDrawables.Any(d => d.Parent == osuGame.BackButton)); + + AddStep("Click back button", () => InputManager.Click(MouseButton.Left)); + AddAssert("Overlay was hidden", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden); + exitViaBackButtonAndConfirm(); + } + + [Test] + public void TestExitMultiWithEscape() + { + Screens.Multi.Multiplayer multiplayer = null; + + AddStep("Push songselect", () => osuGame.ScreenStack.Push(multiplayer = new Screens.Multi.Multiplayer())); + AddUntilStep("Wait for song select", () => multiplayer.IsCurrentScreen()); + exitViaEscapeAndConfirm(); + } + + [Test] + public void TestExitMultiWithBackButton() + { + Screens.Multi.Multiplayer multiplayer = null; + + AddStep("Push songselect", () => osuGame.ScreenStack.Push(multiplayer = new Screens.Multi.Multiplayer())); + AddUntilStep("Wait for song select", () => multiplayer.IsCurrentScreen()); + + exitViaBackButtonAndConfirm(); + } + + private void exitViaEscapeAndConfirm() + { + AddStep("Press escape", () => pressAndRelease(Key.Escape)); + AddUntilStep("Wait for main menu", () => osuGame.ScreenStack.CurrentScreen is MainMenu); + } + + private void exitViaBackButtonAndConfirm() + { + AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(osuGame.BackButton)); + AddStep("Click back button", () => InputManager.Click(MouseButton.Left)); + AddUntilStep("Wait for main menu", () => osuGame.ScreenStack.CurrentScreen is MainMenu); + } + + private void pressAndRelease(Key key) + { + InputManager.PressKey(key); + InputManager.ReleaseKey(key); + } + + private class TestOsuGame : OsuGame + { + public new ScreenStack ScreenStack => base.ScreenStack; + + public new BackButton BackButton => base.BackButton; + } + + private class TestSongSelect : PlaySongSelect + { + public ModSelectOverlay ModSelectOverlay => ModSelect; + } + } +} diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 669fd62e45..373333696a 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Bindings; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Input.Bindings { @@ -55,8 +56,32 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { InputKey.Control, InputKey.Minus }, GlobalAction.DecreaseScrollSpeed), }; - protected override IEnumerable KeyBindingInputQueue => - handler == null ? base.KeyBindingInputQueue : base.KeyBindingInputQueue.Prepend(handler); + protected override IEnumerable KeyBindingInputQueue + { + get + { + var queue = base.KeyBindingInputQueue.ToList(); + + if (handler != null) + yield return handler; + + BackButton backButton = null; + + foreach (var drawable in queue) + { + if (drawable is BackButton button) + { + backButton = button; + continue; + } + + yield return drawable; + } + + if (backButton != null) + yield return backButton; + } + } } public enum GlobalAction diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ceaf0c3d5e..64958c9a09 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -81,10 +81,11 @@ namespace osu.Game public readonly Bindable OverlayActivationMode = new Bindable(); - private OsuScreenStack screenStack; + protected OsuScreenStack ScreenStack; + protected BackButton BackButton; + private VolumeOverlay volume; private OsuLogo osuLogo; - private BackButton backButton; private MainMenu menuScreen; private Intro introScreen; @@ -325,7 +326,7 @@ namespace osu.Game performFromMainMenuTask?.Cancel(); // if the current screen does not allow screen changing, give the user an option to try again later. - if (!bypassScreenAllowChecks && (screenStack.CurrentScreen as IOsuScreen)?.AllowExternalScreenChange == false) + if (!bypassScreenAllowChecks && (ScreenStack.CurrentScreen as IOsuScreen)?.AllowExternalScreenChange == false) { notifications.Post(new SimpleNotification { @@ -343,7 +344,7 @@ namespace osu.Game CloseAllOverlays(false); // we may already be at the target screen type. - if (targetScreen != null && screenStack.CurrentScreen?.GetType() == targetScreen) + if (targetScreen != null && ScreenStack.CurrentScreen?.GetType() == targetScreen) { action(); return; @@ -406,15 +407,15 @@ namespace osu.Game RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, - backButton = new BackButton + ScreenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, + BackButton = new BackButton { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Action = () => { - if ((screenStack.CurrentScreen as IOsuScreen)?.AllowBackButton == true) - screenStack.Exit(); + if ((ScreenStack.CurrentScreen as IOsuScreen)?.AllowBackButton == true) + ScreenStack.Exit(); } }, logoContainer = new Container { RelativeSizeAxes = Axes.Both }, @@ -427,15 +428,15 @@ namespace osu.Game idleTracker }); - screenStack.ScreenPushed += screenPushed; - screenStack.ScreenExited += screenExited; + ScreenStack.ScreenPushed += screenPushed; + ScreenStack.ScreenExited += screenExited; loadComponentSingleFile(osuLogo, logo => { logoContainer.Add(logo); // Loader has to be created after the logo has finished loading as Loader performs logo transformations on entering. - screenStack.Push(new Loader + ScreenStack.Push(new Loader { RelativeSizeAxes = Axes.Both }); @@ -755,13 +756,13 @@ namespace osu.Game protected override bool OnExiting() { - if (screenStack.CurrentScreen is Loader) + if (ScreenStack.CurrentScreen is Loader) return false; if (introScreen == null) return true; - if (!introScreen.DidLoadMenu || !(screenStack.CurrentScreen is Intro)) + if (!introScreen.DidLoadMenu || !(ScreenStack.CurrentScreen is Intro)) { Scheduler.Add(introScreen.MakeCurrent); return true; @@ -789,7 +790,7 @@ namespace osu.Game screenContainer.Padding = new MarginPadding { Top = ToolbarOffset }; overlayContent.Padding = new MarginPadding { Top = ToolbarOffset }; - MenuCursorContainer.CanShowCursor = (screenStack.CurrentScreen as IOsuScreen)?.CursorVisible ?? false; + MenuCursorContainer.CanShowCursor = (ScreenStack.CurrentScreen as IOsuScreen)?.CursorVisible ?? false; } protected virtual void ScreenChanged(IScreen current, IScreen newScreen) @@ -815,9 +816,9 @@ namespace osu.Game Toolbar.Show(); if (newOsuScreen.AllowBackButton) - backButton.Show(); + BackButton.Show(); else - backButton.Hide(); + BackButton.Hide(); } } From c14c3ba8ec28f4e927b7865de73cff615f9b942e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jul 2019 16:55:19 +0900 Subject: [PATCH 2076/5608] Move database isolation logic to OsuTestScene for easier reuse --- .../Background/TestSceneUserDimContainer.cs | 17 ++------------ .../SongSelect/TestScenePlaySongSelect.cs | 23 ++----------------- osu.Game/Tests/Visual/OsuTestScene.cs | 15 ++++++++++++ 3 files changed, 19 insertions(+), 36 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index dc4ceed59e..f114559114 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -17,7 +17,6 @@ using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Configuration; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -51,26 +50,14 @@ namespace osu.Game.Tests.Visual.Background private DummySongSelect songSelect; private TestPlayerLoader playerLoader; private TestPlayer player; - private DatabaseContextFactory factory; private BeatmapManager manager; private RulesetStore rulesets; [BackgroundDependencyLoader] private void load(GameHost host, AudioManager audio) { - factory = new DatabaseContextFactory(LocalStorage); - factory.ResetDatabase(); - - using (var usage = factory.Get()) - usage.Migrate(); - - factory.ResetDatabase(); - - using (var usage = factory.Get()) - usage.Migrate(); - - Dependencies.Cache(rulesets = new RulesetStore(factory)); - Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, audio, host, Beatmap.Default)); + Dependencies.Cache(rulesets = new RulesetStore(ContextFactory)); + Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default)); Dependencies.Cache(new OsuConfigManager(LocalStorage)); manager.Import(TestResources.GetTestBeatmapForImport()).Wait(); diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index f3255814f2..680250a226 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -15,7 +15,6 @@ using osu.Framework.MathUtils; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Beatmaps; -using osu.Game.Database; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; @@ -35,7 +34,6 @@ namespace osu.Game.Tests.Visual.SongSelect private RulesetStore rulesets; private WorkingBeatmap defaultBeatmap; - private DatabaseContextFactory factory; public override IReadOnlyList RequiredTypes => new[] { @@ -74,28 +72,11 @@ namespace osu.Game.Tests.Visual.SongSelect private TestSongSelect songSelect; - protected override void Dispose(bool isDisposing) - { - factory.ResetDatabase(); - base.Dispose(isDisposing); - } - [BackgroundDependencyLoader] private void load(GameHost host, AudioManager audio) { - factory = new DatabaseContextFactory(LocalStorage); - factory.ResetDatabase(); - - using (var usage = factory.Get()) - usage.Migrate(); - - factory.ResetDatabase(); - - using (var usage = factory.Get()) - usage.Migrate(); - - Dependencies.Cache(rulesets = new RulesetStore(factory)); - Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, audio, host, defaultBeatmap = Beatmap.Default)); + Dependencies.Cache(rulesets = new RulesetStore(ContextFactory)); + Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, defaultBeatmap = Beatmap.Default)); Beatmap.SetDefault(); } diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 9b3c15aa91..27d72f3950 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -15,6 +15,7 @@ using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Database; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Tests.Beatmaps; @@ -43,6 +44,9 @@ namespace osu.Game.Tests.Visual private readonly Lazy localStorage; protected Storage LocalStorage => localStorage.Value; + private readonly Lazy contextFactory; + protected DatabaseContextFactory ContextFactory => contextFactory.Value; + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { // This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures @@ -59,6 +63,14 @@ namespace osu.Game.Tests.Visual protected OsuTestScene() { localStorage = new Lazy(() => new NativeStorage($"{GetType().Name}-{Guid.NewGuid()}")); + contextFactory = new Lazy(() => + { + var factory = new DatabaseContextFactory(LocalStorage); + factory.ResetDatabase(); + using (var usage = factory.Get()) + usage.Migrate(); + return factory; + }); } [Resolved] @@ -85,6 +97,9 @@ namespace osu.Game.Tests.Visual if (beatmap?.Value.TrackLoaded == true) beatmap.Value.Track.Stop(); + if (contextFactory.IsValueCreated) + contextFactory.Value.ResetDatabase(); + if (localStorage.IsValueCreated) { try From cb17007fa740c67e665dbc0cd447412e5e81b78b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jul 2019 16:55:39 +0900 Subject: [PATCH 2077/5608] Fix zero-length hash models incorrectly creating a unique hash --- osu.Game/Database/ArchiveModelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index ed65bdc069..efb76deff8 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -253,7 +253,7 @@ namespace osu.Game.Database using (Stream s = reader.GetStream(file)) s.CopyTo(hashable); - return hashable.ComputeSHA2Hash(); + return hashable.Length > 0 ? hashable.ComputeSHA2Hash() : null; } /// From 8742ed8a9cc5768c89f9b3d2230c0f3ca74abd1c Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 29 Jul 2019 17:23:45 +0900 Subject: [PATCH 2078/5608] Fix step names --- .../Visual/Menus/TestSceneExitingScreens.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs b/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs index fafaa3a397..377d7b60fb 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.Menus AddUntilStep("wait for load", () => osuGame.IsLoaded); AddUntilStep("wait for main menu", () => { - var current = osuGame.ScreenStack?.CurrentScreen; + var current = osuGame.ScreenStack.CurrentScreen; switch (current) { @@ -69,7 +69,7 @@ namespace osu.Game.Tests.Visual.Menus { TestSongSelect songSelect = null; - AddStep("Push songselect", () => osuGame.ScreenStack.Push(songSelect = new TestSongSelect())); + AddStep("Push song select", () => osuGame.ScreenStack.Push(songSelect = new TestSongSelect())); AddUntilStep("Wait for song select", () => songSelect.IsCurrentScreen()); AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show()); AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); @@ -83,7 +83,7 @@ namespace osu.Game.Tests.Visual.Menus { TestSongSelect songSelect = null; - AddStep("Push songselect", () => osuGame.ScreenStack.Push(songSelect = new TestSongSelect())); + AddStep("Push song select", () => osuGame.ScreenStack.Push(songSelect = new TestSongSelect())); AddUntilStep("Wait for song select", () => songSelect.IsCurrentScreen()); AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show()); AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); @@ -102,8 +102,8 @@ namespace osu.Game.Tests.Visual.Menus { Screens.Multi.Multiplayer multiplayer = null; - AddStep("Push songselect", () => osuGame.ScreenStack.Push(multiplayer = new Screens.Multi.Multiplayer())); - AddUntilStep("Wait for song select", () => multiplayer.IsCurrentScreen()); + AddStep("Push multiplayer", () => osuGame.ScreenStack.Push(multiplayer = new Screens.Multi.Multiplayer())); + AddUntilStep("Wait for multiplayer", () => multiplayer.IsCurrentScreen()); exitViaEscapeAndConfirm(); } @@ -112,8 +112,8 @@ namespace osu.Game.Tests.Visual.Menus { Screens.Multi.Multiplayer multiplayer = null; - AddStep("Push songselect", () => osuGame.ScreenStack.Push(multiplayer = new Screens.Multi.Multiplayer())); - AddUntilStep("Wait for song select", () => multiplayer.IsCurrentScreen()); + AddStep("Push multiplayer", () => osuGame.ScreenStack.Push(multiplayer = new Screens.Multi.Multiplayer())); + AddUntilStep("Wait for multiplayer", () => multiplayer.IsCurrentScreen()); exitViaBackButtonAndConfirm(); } From c514cbe2b78c9c4846b125d8b9f48924b1e7f176 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jul 2019 19:29:06 +0900 Subject: [PATCH 2079/5608] Add basic skinning test --- .../default-skin/approachcircle@2x.png | Bin 0 -> 18164 bytes .../Resources/default-skin/hit300k@2x.png | Bin 0 -> 29098 bytes .../Resources/default-skin/hitcircle@2x.png | Bin 0 -> 7768 bytes .../default-skin/hitcircleoverlay@2x.png | Bin 0 -> 45901 bytes .../Resources/metrics-skin/hitcircle@2x.png | Bin 0 -> 13140 bytes .../metrics-skin/hitcircleoverlay@2x.png | Bin 0 -> 38217 bytes .../special-skin/approachcircle@2x.png | Bin 0 -> 31796 bytes .../Resources/special-skin/hitcircle@2x.png | Bin 0 -> 263521 bytes .../special-skin/hitcircleoverlay@2x.png | Bin 0 -> 262013 bytes .../SkinnableTestScene.cs | 66 ++++++++++++++++++ .../TestSceneHitCircle.cs | 44 ++++++------ osu.Game/Skinning/SkinManager.cs | 6 +- .../Tests/Visual}/OsuGridTestScene.cs | 2 +- osu.iOS.props | 2 +- 14 files changed, 92 insertions(+), 28 deletions(-) create mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/approachcircle@2x.png create mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300k@2x.png create mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hitcircle@2x.png create mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hitcircleoverlay@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hitcircle@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hitcircleoverlay@2x.png create mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/special-skin/approachcircle@2x.png create mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hitcircle@2x.png create mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hitcircleoverlay@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs rename {osu.Game.Tests/Visual/UserInterface => osu.Game/Tests/Visual}/OsuGridTestScene.cs (97%) diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/approachcircle@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/approachcircle@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..db2f4a5730b80c3488c618fe825e322742e4007c GIT binary patch literal 18164 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
xUBq)wpYuSo%L4;iD|W&d3&2irtb$J#-rmG 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 tq+89yAYBs>kLVeUC5rTls%z@vF}1DU#4;$aN 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 R|M{Pbx-w?>O~E?q{{RqUO*sGn literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hitcircleoverlay@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hitcircleoverlay@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4233d9bb6e6aa88c7da5c1998439789cc5f9c7b2 GIT binary patch literal 38217 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/approachcircle@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/approachcircle@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..5d28b3f7cb5b7d682686c9a93a994ae506f68f2f GIT binary patch literal 31796 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hitcircle@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hitcircle@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..b4eb5221ffd0c2791d079ebfc6bafcf0ac7a31ba GIT binary patch literal 263521 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

ga#N){uvTxT7 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. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.IO; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.IO.Stores; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public abstract class SkinnableTestScene : OsuGridTestScene + { + private static Skin getSkinFromResources(SkinManager skins, string name) + { + using (var storage = new DllResourceStore("osu.Game.Rulesets.Osu.Tests.dll")) + { + var tempName = Path.GetTempFileName(); + + File.Delete(tempName); + Directory.CreateDirectory(tempName); + + var files = storage.GetAvailableResources().Where(f => f.StartsWith($"Resources/{name}")); + + foreach (var file in files) + using (var stream = storage.GetStream(file)) + using (var newFile = File.Create(Path.Combine(tempName, Path.GetFileName(file)))) + stream.CopyTo(newFile); + + return skins.GetSkin(skins.Import(tempName).Result); + } + } + + private Skin metricsSkin; + private Skin defaultSkin; + private Skin specialSkin; + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + var skins = new SkinManager(LocalStorage, ContextFactory, null, audio); + + metricsSkin = getSkinFromResources(skins, "metrics_skin"); + defaultSkin = getSkinFromResources(skins, "default_skin"); + specialSkin = getSkinFromResources(skins, "special_skin"); + } + + public void SetContents(Func creationFunction) + { + Cell(0).Child = new LocalSkinOverrideContainer(null) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); + Cell(1).Child = new LocalSkinOverrideContainer(metricsSkin) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); + Cell(2).Child = new LocalSkinOverrideContainer(defaultSkin) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); + Cell(3).Child = new LocalSkinOverrideContainer(specialSkin) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); + } + + protected SkinnableTestScene() + : base(2, 2) + { + } + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs index d44a0cd841..8692744c0d 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs @@ -7,7 +7,6 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Tests.Visual; using osuTK; using System.Collections.Generic; using System; @@ -19,37 +18,32 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneHitCircle : OsuTestScene + public class TestSceneHitCircle : SkinnableTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(DrawableHitCircle) }; - private readonly Container content; - protected override Container Content => content; - private int depthIndex; public TestSceneHitCircle() { - base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 })); - - AddStep("Miss Big Single", () => testSingle(2)); - AddStep("Miss Medium Single", () => testSingle(5)); - AddStep("Miss Small Single", () => testSingle(7)); - AddStep("Hit Big Single", () => testSingle(2, true)); - AddStep("Hit Medium Single", () => testSingle(5, true)); - AddStep("Hit Small Single", () => testSingle(7, true)); - AddStep("Miss Big Stream", () => testStream(2)); - AddStep("Miss Medium Stream", () => testStream(5)); - AddStep("Miss Small Stream", () => testStream(7)); - AddStep("Hit Big Stream", () => testStream(2, true)); - AddStep("Hit Medium Stream", () => testStream(5, true)); - AddStep("Hit Small Stream", () => testStream(7, true)); + AddStep("Miss Big Single", () => SetContents(() => testSingle(2))); + AddStep("Miss Medium Single", () => SetContents(() => testSingle(5))); + AddStep("Miss Small Single", () => SetContents(() => testSingle(7))); + AddStep("Hit Big Single", () => SetContents(() => testSingle(2, true))); + AddStep("Hit Medium Single", () => SetContents(() => testSingle(5, true))); + AddStep("Hit Small Single", () => SetContents(() => testSingle(7, true))); + AddStep("Miss Big Stream", () => SetContents(() => testStream(2))); + AddStep("Miss Medium Stream", () => SetContents(() => testStream(5))); + AddStep("Miss Small Stream", () => SetContents(() => testStream(7))); + AddStep("Hit Big Stream", () => SetContents(() => testStream(2, true))); + AddStep("Hit Medium Stream", () => SetContents(() => testStream(5, true))); + AddStep("Hit Small Stream", () => SetContents(() => testStream(7, true))); } - private void testSingle(float circleSize, bool auto = false, double timeOffset = 0, Vector2? positionOffset = null) + private Drawable testSingle(float circleSize, bool auto = false, double timeOffset = 0, Vector2? positionOffset = null) { positionOffset = positionOffset ?? Vector2.Zero; @@ -70,18 +64,22 @@ namespace osu.Game.Rulesets.Osu.Tests foreach (var mod in Mods.Value.OfType()) mod.ApplyToDrawableHitObjects(new[] { drawable }); - Add(drawable); + return drawable; } - private void testStream(float circleSize, bool auto = false) + private Drawable testStream(float circleSize, bool auto = false) { + var container = new Container { RelativeSizeAxes = Axes.Both }; + Vector2 pos = new Vector2(-250, 0); for (int i = 0; i <= 1000; i += 100) { - testSingle(circleSize, auto, i, pos); + container.Add(testSingle(circleSize, auto, i, pos)); pos.X += 50; } + + return container; } protected class TestDrawableHitCircle : DrawableHitCircle diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 70abfac501..19997e8844 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -45,7 +45,7 @@ namespace osu.Game.Skinning CurrentSkinInfo.Value = SkinInfo.Default; }; - CurrentSkinInfo.ValueChanged += skin => CurrentSkin.Value = getSkin(skin.NewValue); + CurrentSkinInfo.ValueChanged += skin => CurrentSkin.Value = GetSkin(skin.NewValue); CurrentSkin.ValueChanged += skin => { if (skin.NewValue.SkinInfo != CurrentSkinInfo.Value) @@ -80,7 +80,7 @@ namespace osu.Game.Skinning { await base.Populate(model, archive, cancellationToken); - Skin reference = getSkin(model); + Skin reference = GetSkin(model); if (!string.IsNullOrEmpty(reference.Configuration.SkinInfo.Name)) { @@ -99,7 +99,7 @@ namespace osu.Game.Skinning ///

0xJlZ?;ZV^q_mZ9Q!A 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hitcircleoverlay@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hitcircleoverlay@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..69b601e006d36419bf3392ec832097b3035b8676 GIT binary patch literal 262013 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

/// The skin to lookup. /// A instance correlating to the provided . - private Skin getSkin(SkinInfo skinInfo) + public Skin GetSkin(SkinInfo skinInfo) { if (skinInfo == SkinInfo.Default) return new DefaultSkin(); diff --git a/osu.Game.Tests/Visual/UserInterface/OsuGridTestScene.cs b/osu.Game/Tests/Visual/OsuGridTestScene.cs similarity index 97% rename from osu.Game.Tests/Visual/UserInterface/OsuGridTestScene.cs rename to osu.Game/Tests/Visual/OsuGridTestScene.cs index 096ac951de..c09f4d6218 100644 --- a/osu.Game.Tests/Visual/UserInterface/OsuGridTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGridTestScene.cs @@ -5,7 +5,7 @@ using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -namespace osu.Game.Tests.Visual.UserInterface +namespace osu.Game.Tests.Visual { /// /// An abstract test case which exposes small cells arranged in a grid. diff --git a/osu.iOS.props b/osu.iOS.props index 55d1afa645..e87e759492 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -35,7 +35,7 @@ prompt 4 - iPhone Distribution + iPhone Developer true true Entitlements.plist From 466297df552500a5d789aa8e846469474332b729 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jul 2019 17:05:13 +0900 Subject: [PATCH 2080/5608] Fix shaking test --- osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs | 12 +++++++----- osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs | 15 +++++++-------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs index 8692744c0d..84a7bfc53e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs @@ -55,11 +55,7 @@ namespace osu.Game.Rulesets.Osu.Tests circle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize }); - var drawable = new TestDrawableHitCircle(circle, auto) - { - Anchor = Anchor.Centre, - Depth = depthIndex++ - }; + var drawable = CreateDrawableHitCircle(circle, auto); foreach (var mod in Mods.Value.OfType()) mod.ApplyToDrawableHitObjects(new[] { drawable }); @@ -67,6 +63,12 @@ namespace osu.Game.Rulesets.Osu.Tests return drawable; } + protected virtual TestDrawableHitCircle CreateDrawableHitCircle(HitCircle circle, bool auto) => new TestDrawableHitCircle(circle, auto) + { + Anchor = Anchor.Centre, + Depth = depthIndex++ + }; + private Drawable testStream(float circleSize, bool auto = false) { var container = new Container { RelativeSizeAxes = Axes.Both }; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs index 3d8afd66f4..84a73c7cfc 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs @@ -1,23 +1,22 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics; using osu.Framework.MathUtils; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Tests { public class TestSceneShaking : TestSceneHitCircle { - public override void Add(Drawable drawable) + protected override TestDrawableHitCircle CreateDrawableHitCircle(HitCircle circle, bool auto) { - base.Add(drawable); + var drawableHitObject = base.CreateDrawableHitCircle(circle, auto); - if (drawable is TestDrawableHitCircle hitObject) - { - Scheduler.AddDelayed(() => hitObject.TriggerJudgement(), - hitObject.HitObject.StartTime - (hitObject.HitObject.HitWindows.HalfWindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current); - } + Scheduler.AddDelayed(() => drawableHitObject.TriggerJudgement(), + drawableHitObject.HitObject.StartTime - (drawableHitObject.HitObject.HitWindows.HalfWindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current); + + return drawableHitObject; } } } From e579bce18afab63f9c8e63a0bd32418a12378b9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jul 2019 18:14:06 +0900 Subject: [PATCH 2081/5608] Don't report delta patch failures to sentry --- osu.Desktop/Updater/SquirrelUpdateManager.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index 78a1e680ec..fa41c061b5 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -27,6 +27,8 @@ namespace osu.Desktop.Updater public Task PrepareUpdateAsync() => UpdateManager.RestartAppWhenExited(); + private static readonly Logger logger = Logger.GetLogger("updater"); + [BackgroundDependencyLoader] private void load(NotificationOverlay notification, OsuGameBase game) { @@ -77,7 +79,7 @@ namespace osu.Desktop.Updater { if (useDeltaPatching) { - Logger.Error(e, @"delta patching failed!"); + logger.Add(@"delta patching failed; will attempt full download!"); //could fail if deltas are unavailable for full update path (https://github.com/Squirrel/Squirrel.Windows/issues/959) //try again without deltas. @@ -163,16 +165,11 @@ namespace osu.Desktop.Updater { public LogLevel Level { get; set; } = LogLevel.Info; - private Logger logger; - public void Write(string message, LogLevel logLevel) { if (logLevel < Level) return; - if (logger == null) - logger = Logger.GetLogger("updater"); - logger.Add(message); } From 98813222afbeadbf823af00724fa23a4a9a55bbd Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Mon, 29 Jul 2019 18:35:22 +0900 Subject: [PATCH 2082/5608] Adjust comment --- osu.Game/Skinning/SkinReloadableDrawable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index 397c6656a5..4bbdeafba5 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -38,7 +38,7 @@ namespace osu.Game.Skinning private void onChange() => // schedule required to avoid calls after disposed. - // note that this has the side-effect of components only performance a skin change when they are alive. + // note that this has the side-effect of components only performing a skin change when they are alive. Scheduler.AddOnce(() => SkinChanged(skin, allowDefaultFallback)); protected override void LoadAsyncComplete() From ac01e9fbebbe271c368361aa31e29193e4140e1a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jul 2019 18:36:07 +0900 Subject: [PATCH 2083/5608] Fix legacy scores with no online ID being imported with a non-null ID --- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 0fdbd56c92..2e4b4b3a9a 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -80,6 +80,9 @@ namespace osu.Game.Scoring.Legacy else if (version >= 20121008) scoreInfo.OnlineScoreID = sr.ReadInt32(); + if (scoreInfo.OnlineScoreID <= 0) + scoreInfo.OnlineScoreID = null; + if (compressedReplay?.Length > 0) { using (var replayInStream = new MemoryStream(compressedReplay)) From 396892da1aa4bd2aeff96155d477189db3b1cb26 Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Mon, 29 Jul 2019 18:43:05 +0900 Subject: [PATCH 2084/5608] Describe how the ratio came to be --- osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs index 8b6b483618..f7888f8022 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs @@ -18,6 +18,7 @@ namespace osu.Game.Rulesets.Osu.UI Anchor = Anchor.Centre; Origin = Anchor.Centre; + // Calculated from osu!stable as 512 (default gamefield size) / 640 (default window size) Size = new Vector2(0.8f); InternalChild = new Container From e8c039bb8a7d6fb5babe3628f1fd898402194969 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 29 Jul 2019 18:45:16 +0900 Subject: [PATCH 2085/5608] Use a receptor model instead --- .../UserInterface/TestSceneBackButton.cs | 4 +- osu.Game/Graphics/UserInterface/BackButton.cs | 38 +++++++++++-------- .../Input/Bindings/GlobalActionContainer.cs | 29 +------------- osu.Game/OsuGame.cs | 5 ++- 4 files changed, 32 insertions(+), 44 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs index 38a9af05d8..05d14abe30 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs @@ -22,6 +22,7 @@ namespace osu.Game.Tests.Visual.UserInterface public TestSceneBackButton() { BackButton button; + BackButton.BackButtonReceptor receptor = new BackButton.BackButtonReceptor(); Child = new Container { @@ -31,12 +32,13 @@ namespace osu.Game.Tests.Visual.UserInterface Masking = true, Children = new Drawable[] { + receptor, new Box { RelativeSizeAxes = Axes.Both, Colour = Color4.SlateGray }, - button = new BackButton + button = new BackButton(receptor) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 48bf0848ae..fe82a5d8e2 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -10,14 +10,16 @@ using osu.Game.Input.Bindings; namespace osu.Game.Graphics.UserInterface { - public class BackButton : VisibilityContainer, IKeyBindingHandler + public class BackButton : VisibilityContainer { public Action Action; private readonly TwoLayerButton button; - public BackButton() + public BackButton(BackButtonReceptor receptor) { + receptor.OnBackPressed += () => Action.Invoke(); + Size = TwoLayerButton.SIZE_EXTENDED; Child = button = new TwoLayerButton @@ -37,19 +39,6 @@ namespace osu.Game.Graphics.UserInterface button.HoverColour = colours.PinkDark; } - public bool OnPressed(GlobalAction action) - { - if (action == GlobalAction.Back) - { - Action?.Invoke(); - return true; - } - - return false; - } - - public bool OnReleased(GlobalAction action) => action == GlobalAction.Back; - protected override void PopIn() { button.MoveToX(0, 400, Easing.OutQuint); @@ -61,5 +50,24 @@ namespace osu.Game.Graphics.UserInterface button.MoveToX(-TwoLayerButton.SIZE_EXTENDED.X / 2, 400, Easing.OutQuint); button.FadeOut(400, Easing.OutQuint); } + + public class BackButtonReceptor : Drawable, IKeyBindingHandler + { + public Action OnBackPressed; + + public bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.Back: + OnBackPressed.Invoke(); + return true; + } + + return false; + } + + public bool OnReleased(GlobalAction action) => action == GlobalAction.Back; + } } } diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 373333696a..669fd62e45 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -7,7 +7,6 @@ using System.Linq; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Bindings; -using osu.Game.Graphics.UserInterface; namespace osu.Game.Input.Bindings { @@ -56,32 +55,8 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { InputKey.Control, InputKey.Minus }, GlobalAction.DecreaseScrollSpeed), }; - protected override IEnumerable KeyBindingInputQueue - { - get - { - var queue = base.KeyBindingInputQueue.ToList(); - - if (handler != null) - yield return handler; - - BackButton backButton = null; - - foreach (var drawable in queue) - { - if (drawable is BackButton button) - { - backButton = button; - continue; - } - - yield return drawable; - } - - if (backButton != null) - yield return backButton; - } - } + protected override IEnumerable KeyBindingInputQueue => + handler == null ? base.KeyBindingInputQueue : base.KeyBindingInputQueue.Prepend(handler); } public enum GlobalAction diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 64958c9a09..3018cea276 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -84,6 +84,8 @@ namespace osu.Game protected OsuScreenStack ScreenStack; protected BackButton BackButton; + private BackButton.BackButtonReceptor backButtonReceptor; + private VolumeOverlay volume; private OsuLogo osuLogo; @@ -407,8 +409,9 @@ namespace osu.Game RelativeSizeAxes = Axes.Both, Children = new Drawable[] { + backButtonReceptor = new BackButton.BackButtonReceptor(), ScreenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, - BackButton = new BackButton + BackButton = new BackButton(backButtonReceptor) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, From 0635680db52db1d6063c09dbdf88fa459a07b64f Mon Sep 17 00:00:00 2001 From: jorolf Date: Mon, 29 Jul 2019 11:49:59 +0200 Subject: [PATCH 2086/5608] fix some code quality --- osu.Game/Skinning/LegacySkin.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 24c6c9e4ec..c9c64c96f2 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -54,28 +54,33 @@ namespace osu.Game.Skinning public override Drawable GetDrawableComponent(string componentName) { bool animatable = false; - (bool looping, double frametime) animationData = (false, 1000 / 60d); + bool looping = true; + const double frametime = 1000 / 60d; switch (componentName) { case "Play/Miss": componentName = "hit0"; animatable = true; + looping = false; break; case "Play/Meh": componentName = "hit50"; animatable = true; + looping = false; break; case "Play/Good": componentName = "hit100"; animatable = true; + looping = false; break; case "Play/Great": componentName = "hit300"; animatable = true; + looping = false; break; case "Play/osu/number-text": @@ -93,7 +98,7 @@ namespace osu.Game.Skinning if (texture != null && animatable) { - var animation = new TextureAnimation { DefaultFrameLength = animationData.frametime }; + var animation = new TextureAnimation { DefaultFrameLength = frametime }; for (int i = 1; texture != null; i++) { @@ -101,7 +106,9 @@ namespace osu.Game.Skinning texture = GetTexture($"{componentName}-{i}"); } - animation.Repeat = animationData.looping; + // This comment can be removed once we have components which are looping + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + animation.Repeat = looping; return animation; } @@ -109,10 +116,7 @@ namespace osu.Game.Skinning { texture = GetTexture(componentName); - if (texture == null) - return null; - - return new Sprite { Texture = texture }; + return texture == null ? null : new Sprite { Texture = texture }; } } From c01461b9511c553c8e0c5b54e63f538cd739f78d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 29 Jul 2019 19:12:41 +0900 Subject: [PATCH 2087/5608] Recalculate path size when path radius changes --- .../Objects/Drawables/Pieces/SliderBody.cs | 2 +- .../Objects/Drawables/Pieces/SnakingSliderBody.cs | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 6bc19ee3b5..24a437c20e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces protected Path Path => path; - public float PathRadius + public virtual float PathRadius { get => path.PathRadius; set => path.PathRadius = value; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index a3d3893c8b..0590ca1d96 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -24,6 +24,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public double? SnakedStart { get; private set; } public double? SnakedEnd { get; private set; } + public override float PathRadius + { + get => base.PathRadius; + set + { + if (base.PathRadius == value) + return; + + base.PathRadius = value; + + Refresh(); + } + } + public override Vector2 PathOffset => snakedPathOffset; /// From b4bcdb1c7013f2013c147a794111d2d96c0dc384 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jul 2019 19:44:58 +0900 Subject: [PATCH 2088/5608] 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 6744590f0d..2c5e54d4f5 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0b2baa982b..472f6e9d65 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 55d1afa645..0a19eac2b5 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From f21a2f7e5e4ced31256d8bdd0ef9d64b24426e15 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jul 2019 21:49:12 +0900 Subject: [PATCH 2089/5608] Fix version overlay displaying briefly before it should --- osu.Desktop/OsuGameDesktop.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 18f0cd1f80..cd39ca0699 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.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; @@ -52,11 +52,7 @@ namespace osu.Desktop if (!noVersionOverlay) { - LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, v => - { - Add(v); - v.Show(); - }); + LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, Add); if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows) Add(new SquirrelUpdateManager()); From ece5a9622e53160e337b699c3d7cd2c164c29cb5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 06:31:45 +0900 Subject: [PATCH 2090/5608] Fix scores without an online ID not always presenting correctly --- osu.Game/OsuGame.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 9358a412d9..e71dd67bf2 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -265,7 +265,16 @@ namespace osu.Game { // The given ScoreInfo may have missing properties if it was retrieved from online data. Re-retrieve it from the database // to ensure all the required data for presenting a replay are present. - var databasedScoreInfo = ScoreManager.Query(s => s.OnlineScoreID == score.OnlineScoreID); + var databasedScoreInfo = score.OnlineScoreID != null + ? ScoreManager.Query(s => s.OnlineScoreID == score.OnlineScoreID) + : ScoreManager.Query(s => s.Hash == score.Hash); + + if (databasedScoreInfo == null) + { + Logger.Log("The requested score could not be found locally.", LoggingTarget.Information); + return; + } + var databasedScore = ScoreManager.GetScore(databasedScoreInfo); if (databasedScore.Replay == null) From cec26a270ecf65453e808f5c6b5d5634c5e59ade Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 07:03:59 +0900 Subject: [PATCH 2091/5608] Fix using right mouse button to drag at song select seeking incorrectly with many beatmaps loaded Closes #5195 --- .../Graphics/Containers/OsuScrollContainer.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuScrollContainer.cs b/osu.Game/Graphics/Containers/OsuScrollContainer.cs index 53092ddc9e..8fc8dec9fd 100644 --- a/osu.Game/Graphics/Containers/OsuScrollContainer.cs +++ b/osu.Game/Graphics/Containers/OsuScrollContainer.cs @@ -27,11 +27,12 @@ namespace osu.Game.Graphics.Containers private bool shouldPerformRightMouseScroll(MouseButtonEvent e) => RightMouseScrollbar && e.Button == MouseButton.Right; - private void scrollToRelative(float value) => ScrollTo(Clamp((value - Scrollbar.DrawSize[ScrollDim] / 2) / Scrollbar.Size[ScrollDim]), true, DistanceDecayOnRightMouseScrollbar); + private void scrollFromMouseEvent(MouseEvent e) => + ScrollTo(Clamp(ToLocalSpace(e.ScreenSpaceMousePosition)[ScrollDim] / DrawSize[ScrollDim]) * Content.DrawSize[ScrollDim], true, DistanceDecayOnRightMouseScrollbar); - private bool mouseScrollBarDragging; + private bool rightMouseDragging; - protected override bool IsDragging => base.IsDragging || mouseScrollBarDragging; + protected override bool IsDragging => base.IsDragging || rightMouseDragging; public OsuScrollContainer(Direction scrollDirection = Direction.Vertical) : base(scrollDirection) @@ -42,7 +43,7 @@ namespace osu.Game.Graphics.Containers { if (shouldPerformRightMouseScroll(e)) { - scrollToRelative(e.MousePosition[ScrollDim]); + scrollFromMouseEvent(e); return true; } @@ -51,9 +52,9 @@ namespace osu.Game.Graphics.Containers protected override bool OnDrag(DragEvent e) { - if (mouseScrollBarDragging) + if (rightMouseDragging) { - scrollToRelative(e.MousePosition[ScrollDim]); + scrollFromMouseEvent(e); return true; } @@ -64,7 +65,7 @@ namespace osu.Game.Graphics.Containers { if (shouldPerformRightMouseScroll(e)) { - mouseScrollBarDragging = true; + rightMouseDragging = true; return true; } @@ -73,9 +74,9 @@ namespace osu.Game.Graphics.Containers protected override bool OnDragEnd(DragEndEvent e) { - if (mouseScrollBarDragging) + if (rightMouseDragging) { - mouseScrollBarDragging = false; + rightMouseDragging = false; return true; } From 62f69581652254283a82b75d4e16382b2aa40bde Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 07:23:25 +0900 Subject: [PATCH 2092/5608] Fix tournament tests not running --- .../TestSceneDrawableTournamentMatch.cs | 3 +- osu.Game.Tournament.Tests/LadderTestScene.cs | 5 ++-- .../Screens/TestSceneGameplayScreen.cs | 3 +- .../Screens/TestSceneScheduleScreen.cs | 3 +- .../Screens/TestSceneShowcaseScreen.cs | 3 +- .../TestSceneTournamentSceneManager.cs | 3 +- .../TournamentTestScene.cs | 28 +++++++++++++++++++ 7 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 osu.Game.Tournament.Tests/TournamentTestScene.cs diff --git a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs index f329623703..e65b708fea 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs @@ -5,14 +5,13 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Ladder.Components; namespace osu.Game.Tournament.Tests.Components { - public class TestSceneDrawableTournamentMatch : OsuTestScene + public class TestSceneDrawableTournamentMatch : TournamentTestScene { public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tournament.Tests/LadderTestScene.cs b/osu.Game.Tournament.Tests/LadderTestScene.cs index b49341d0d1..dae0721023 100644 --- a/osu.Game.Tournament.Tests/LadderTestScene.cs +++ b/osu.Game.Tournament.Tests/LadderTestScene.cs @@ -1,13 +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 NUnit.Framework; using osu.Framework.Allocation; -using osu.Game.Tests.Visual; using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Tests { - public abstract class LadderTestScene : OsuTestScene + [TestFixture] + public abstract class LadderTestScene : TournamentTestScene { [Resolved] protected LadderInfo Ladder { get; private set; } diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs index 201736f38a..9de00818a5 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs @@ -2,13 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; using osu.Game.Tournament.Screens.Gameplay; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneGameplayScreen : OsuTestScene + public class TestSceneGameplayScreen : TournamentTestScene { [Cached] private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay(); diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs index f3e65919eb..2277302e98 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs @@ -2,12 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Game.Tests.Visual; using osu.Game.Tournament.Screens.Schedule; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneScheduleScreen : OsuTestScene + public class TestSceneScheduleScreen : TournamentTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs index edf1477b06..8c43e25416 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs @@ -2,12 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Game.Tests.Visual; using osu.Game.Tournament.Screens.Showcase; namespace osu.Game.Tournament.Tests.Screens { - public class TestSceneShowcaseScreen : OsuTestScene + public class TestSceneShowcaseScreen : TournamentTestScene { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs b/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs index 378614343a..4d134ce4af 100644 --- a/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs @@ -3,11 +3,10 @@ using osu.Framework.Allocation; using osu.Framework.Platform; -using osu.Game.Tests.Visual; namespace osu.Game.Tournament.Tests { - public class TestSceneTournamentSceneManager : OsuTestScene + public class TestSceneTournamentSceneManager : TournamentTestScene { [BackgroundDependencyLoader] private void load(Storage storage) diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs new file mode 100644 index 0000000000..18ac3230da --- /dev/null +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -0,0 +1,28 @@ +// 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.Testing; +using osu.Game.Tests.Visual; + +namespace osu.Game.Tournament.Tests +{ + public abstract class TournamentTestScene : OsuTestScene + { + protected override ITestSceneTestRunner CreateRunner() => new TournamentTestSceneTestRunner(); + + public class TournamentTestSceneTestRunner : TournamentGameBase, ITestSceneTestRunner + { + private TestSceneTestRunner.TestRunner runner; + + protected override void LoadAsyncComplete() + { + // this has to be run here rather than LoadComplete because + // TestScene.cs is checking the IsLoaded state (on another thread) and expects + // the runner to be loaded at that point. + Add(runner = new TestSceneTestRunner.TestRunner()); + } + + public void RunTestBlocking(TestScene test) => runner.RunTestBlocking(test); + } + } +} From 1d1372d639066b0086f50750e08dbda679727bbb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 07:42:19 +0900 Subject: [PATCH 2093/5608] Remove forceful resizing --- osu.Game.Tournament/TournamentGameBase.cs | 70 ++++++++++++++++------- 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 06fb52da77..dbfa70704b 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -9,15 +9,20 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Input; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Game.Beatmaps; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; +using osuTK.Graphics; using osuTK.Input; namespace osu.Game.Tournament @@ -35,6 +40,8 @@ namespace osu.Game.Tournament private Bindable windowSize; private FileBasedIPC ipc; + private Drawable heightWarning; + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { return dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); @@ -53,6 +60,12 @@ namespace osu.Game.Tournament this.storage = storage; windowSize = frameworkConfig.GetBindable(FrameworkSetting.WindowedSize); + windowSize.BindValueChanged(size => ScheduleAfterChildren(() => + { + var minWidth = (int)(size.NewValue.Height / 9f * 16 + 400); + + heightWarning.Alpha = size.NewValue.Width < minWidth ? 1 : 0; + }), true); readBracket(); @@ -61,16 +74,43 @@ namespace osu.Game.Tournament dependencies.CacheAs(ipc = new FileBasedIPC()); Add(ipc); - Add(new OsuButton + AddRange(new[] { - Text = "Save Changes", - Width = 140, - Height = 50, - Depth = float.MinValue, - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Padding = new MarginPadding(10), - Action = SaveChanges, + new OsuButton + { + Text = "Save Changes", + Width = 140, + Height = 50, + Depth = float.MinValue, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Padding = new MarginPadding(10), + Action = SaveChanges, + }, + heightWarning = new Container + { + Masking = true, + CornerRadius = 5, + Depth = float.MinValue, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + Colour = Color4.Red, + RelativeSizeAxes = Axes.Both, + }, + new SpriteText + { + Text = "Please make the window wider", + Font = OsuFont.Default.With(weight: "bold"), + Colour = Color4.White, + Padding = new MarginPadding(20) + } + } + }, }); } @@ -195,18 +235,6 @@ namespace osu.Game.Tournament base.LoadComplete(); } - protected override void Update() - { - base.Update(); - var minWidth = (int)(windowSize.Value.Height / 9f * 16 + 400); - - if (windowSize.Value.Width < minWidth) - { - // todo: can be removed after ppy/osu-framework#1975 - windowSize.Value = Host.Window.ClientSize = new Size(minWidth, windowSize.Value.Height); - } - } - protected virtual void SaveChanges() { foreach (var r in ladder.Rounds) From 6d1203a5993a0faec79e1ba4076522e11acc9cba Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 30 Jul 2019 12:00:04 +0900 Subject: [PATCH 2094/5608] Move screen pushes into function, rename receptor --- .../Visual/Menus/TestSceneExitingScreens.cs | 27 +++++++++---------- .../UserInterface/TestSceneBackButton.cs | 2 +- osu.Game/Graphics/UserInterface/BackButton.cs | 6 ++--- osu.Game/OsuGame.cs | 7 +++-- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs b/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs index 377d7b60fb..4780111e66 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.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.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -43,7 +44,7 @@ namespace osu.Game.Tests.Visual.Menus public void SetUpSteps() { AddUntilStep("wait for load", () => osuGame.IsLoaded); - AddUntilStep("wait for main menu", () => + AddUntilStep("exit to main menu", () => { var current = osuGame.ScreenStack.CurrentScreen; @@ -69,8 +70,7 @@ namespace osu.Game.Tests.Visual.Menus { TestSongSelect songSelect = null; - AddStep("Push song select", () => osuGame.ScreenStack.Push(songSelect = new TestSongSelect())); - AddUntilStep("Wait for song select", () => songSelect.IsCurrentScreen()); + pushAndConfirm(() => songSelect = new TestSongSelect(), "song select"); AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show()); AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); AddStep("Press escape", () => pressAndRelease(Key.Escape)); @@ -83,8 +83,7 @@ namespace osu.Game.Tests.Visual.Menus { TestSongSelect songSelect = null; - AddStep("Push song select", () => osuGame.ScreenStack.Push(songSelect = new TestSongSelect())); - AddUntilStep("Wait for song select", () => songSelect.IsCurrentScreen()); + pushAndConfirm(() => songSelect = new TestSongSelect(), "song select"); AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show()); AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(osuGame.BackButton)); @@ -100,24 +99,24 @@ namespace osu.Game.Tests.Visual.Menus [Test] public void TestExitMultiWithEscape() { - Screens.Multi.Multiplayer multiplayer = null; - - AddStep("Push multiplayer", () => osuGame.ScreenStack.Push(multiplayer = new Screens.Multi.Multiplayer())); - AddUntilStep("Wait for multiplayer", () => multiplayer.IsCurrentScreen()); + pushAndConfirm(() => new Screens.Multi.Multiplayer(), "multiplayer"); exitViaEscapeAndConfirm(); } [Test] public void TestExitMultiWithBackButton() { - Screens.Multi.Multiplayer multiplayer = null; - - AddStep("Push multiplayer", () => osuGame.ScreenStack.Push(multiplayer = new Screens.Multi.Multiplayer())); - AddUntilStep("Wait for multiplayer", () => multiplayer.IsCurrentScreen()); - + pushAndConfirm(() => new Screens.Multi.Multiplayer(), "multiplayer"); exitViaBackButtonAndConfirm(); } + private void pushAndConfirm(Func newScreen, string screenName) + { + Screen screen = null; + AddStep($"Push new {screenName}", () => osuGame.ScreenStack.Push(screen = newScreen())); + AddUntilStep($"Wait for new {screenName}", () => screen.IsCurrentScreen()); + } + private void exitViaEscapeAndConfirm() { AddStep("Press escape", () => pressAndRelease(Key.Escape)); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs index 05d14abe30..b7d7053dcd 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.UserInterface public TestSceneBackButton() { BackButton button; - BackButton.BackButtonReceptor receptor = new BackButton.BackButtonReceptor(); + BackButton.Receptor receptor = new BackButton.Receptor(); Child = new Container { diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index fe82a5d8e2..9808eda4df 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -16,9 +16,9 @@ namespace osu.Game.Graphics.UserInterface private readonly TwoLayerButton button; - public BackButton(BackButtonReceptor receptor) + public BackButton(Receptor receptor) { - receptor.OnBackPressed += () => Action.Invoke(); + receptor.OnBackPressed = () => Action.Invoke(); Size = TwoLayerButton.SIZE_EXTENDED; @@ -51,7 +51,7 @@ namespace osu.Game.Graphics.UserInterface button.FadeOut(400, Easing.OutQuint); } - public class BackButtonReceptor : Drawable, IKeyBindingHandler + public class Receptor : Drawable, IKeyBindingHandler { public Action OnBackPressed; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 3018cea276..a889af94eb 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -84,8 +84,6 @@ namespace osu.Game protected OsuScreenStack ScreenStack; protected BackButton BackButton; - private BackButton.BackButtonReceptor backButtonReceptor; - private VolumeOverlay volume; private OsuLogo osuLogo; @@ -393,6 +391,7 @@ namespace osu.Game ScoreManager.PresentImport = items => PresentScore(items.First()); Container logoContainer; + BackButton.Receptor receptor; dependencies.CacheAs(idleTracker = new GameIdleTracker(6000)); @@ -409,9 +408,9 @@ namespace osu.Game RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - backButtonReceptor = new BackButton.BackButtonReceptor(), + receptor = new BackButton.Receptor(), ScreenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, - BackButton = new BackButton(backButtonReceptor) + BackButton = new BackButton(receptor) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, From 9e809a2342797ca55fbee818da5a7f98809b9cc1 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 30 Jul 2019 12:05:29 +0900 Subject: [PATCH 2095/5608] fix merge --- osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs b/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs index 4780111e66..f89e67db74 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs @@ -51,7 +51,7 @@ namespace osu.Game.Tests.Visual.Menus switch (current) { case null: - case Intro _: + case IntroScreen _: case Disclaimer _: return false; From 82fcb88f5c7e7cc5584ba3ffcb57ddca78d43bbd Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 30 Jul 2019 12:11:08 +0900 Subject: [PATCH 2096/5608] update names --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 4223184a68..77f16549fe 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -765,7 +765,7 @@ namespace osu.Game if (introScreen == null) return true; - if (!introScreen.DidLoadMenu || !(screenStack.CurrentScreen is IntroScreen)) + if (!introScreen.DidLoadMenu || !(ScreenStack.CurrentScreen is IntroScreen)) { Scheduler.Add(introScreen.MakeCurrent); return true; From a16c0f2aa0b3ac2962d8921d8145334d69e00a84 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 12:44:08 +0900 Subject: [PATCH 2097/5608] Don't report stable storage msising to sentry --- osu.Desktop/OsuGameDesktop.cs | 4 ++-- osu.Game/Utils/RavenLogger.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 18f0cd1f80..4d68148a36 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -38,9 +38,9 @@ namespace osu.Desktop if (Host is DesktopGameHost desktopHost) return new StableStorage(desktopHost); } - catch (Exception e) + catch (Exception) { - Logger.Error(e, "Error while searching for stable install"); + Logger.Log("Could not find a stable install", LoggingTarget.Runtime, LogLevel.Important); } return null; diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/RavenLogger.cs index 7f4faa60ae..0a6f40a0a6 100644 --- a/osu.Game/Utils/RavenLogger.cs +++ b/osu.Game/Utils/RavenLogger.cs @@ -54,7 +54,7 @@ namespace osu.Game.Utils } lastException = exception; - queuePendingTask(raven.CaptureAsync(new SentryEvent(exception))); + queuePendingTask(raven.CaptureAsync(new SentryEvent(exception) { Message = entry.Message })); } else raven.AddTrail(new Breadcrumb(entry.Target.ToString(), BreadcrumbType.Navigation) { Message = entry.Message }); From 370a81d78a9963e3c2109cfe73b7a954fdf3b818 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 13:30:26 +0900 Subject: [PATCH 2098/5608] Don't forward timeout exceptions to sentry --- osu.Game/Utils/RavenLogger.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/RavenLogger.cs index 7f4faa60ae..80786d2c72 100644 --- a/osu.Game/Utils/RavenLogger.cs +++ b/osu.Game/Utils/RavenLogger.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Net; using System.Threading.Tasks; using osu.Framework.Logging; using SharpRaven; @@ -46,6 +47,16 @@ namespace osu.Game.Utils return; } + if (exception is WebException we) + { + switch (we.Status) + { + // more statuses may need to be blocked as we come across them. + case WebExceptionStatus.Timeout: + return; + } + } + // since we let unhandled exceptions go ignored at times, we want to ensure they don't get submitted on subsequent reports. if (lastException != null && lastException.Message == exception.Message && exception.StackTrace.StartsWith(lastException.StackTrace)) From 6f91a21f00d9f4acce39109953c8f384b2d60da9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 13:31:57 +0900 Subject: [PATCH 2099/5608] Use switch --- osu.Game/Utils/RavenLogger.cs | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/RavenLogger.cs index 80786d2c72..2a396d35cf 100644 --- a/osu.Game/Utils/RavenLogger.cs +++ b/osu.Game/Utils/RavenLogger.cs @@ -37,24 +37,27 @@ namespace osu.Game.Utils if (exception != null) { - if (exception is IOException ioe) + switch (exception) { - // disk full exceptions, see https://stackoverflow.com/a/9294382 - const int hr_error_handle_disk_full = unchecked((int)0x80070027); - const int hr_error_disk_full = unchecked((int)0x80070070); + case IOException ioe: + // disk full exceptions, see https://stackoverflow.com/a/9294382 + const int hr_error_handle_disk_full = unchecked((int)0x80070027); + const int hr_error_disk_full = unchecked((int)0x80070070); - if (ioe.HResult == hr_error_handle_disk_full || ioe.HResult == hr_error_disk_full) - return; - } - - if (exception is WebException we) - { - switch (we.Status) - { - // more statuses may need to be blocked as we come across them. - case WebExceptionStatus.Timeout: + if (ioe.HResult == hr_error_handle_disk_full || ioe.HResult == hr_error_disk_full) return; - } + + break; + + case WebException we: + switch (we.Status) + { + // more statuses may need to be blocked as we come across them. + case WebExceptionStatus.Timeout: + return; + } + + break; } // since we let unhandled exceptions go ignored at times, we want to ensure they don't get submitted on subsequent reports. From 195609816674f0428a281d12e4c0757cba08169a Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 30 Jul 2019 13:58:08 +0900 Subject: [PATCH 2100/5608] Add a fallback for humanizer localization failure --- osu.Game/Graphics/DrawableDate.cs | 4 +-- .../BeatmapSet/Scores/TopScoreUserSection.cs | 4 +-- osu.Game/Utils/HumanizerUtils.cs | 36 +++++++++++++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Utils/HumanizerUtils.cs diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 125c994c92..533f02af7b 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -2,11 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System; -using Humanizer; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.Sprites; +using osu.Game.Utils; namespace osu.Game.Graphics { @@ -71,7 +71,7 @@ namespace osu.Game.Graphics Scheduler.AddDelayed(updateTimeWithReschedule, timeUntilNextUpdate); } - protected virtual string Format() => Date.Humanize(); + protected virtual string Format() => HumanizerUtils.Humanize(Date); private void updateTime() => Text = Format(); diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index ffc39e5af2..38a909411a 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.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 Humanizer; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -14,6 +13,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Online.Leaderboards; using osu.Game.Scoring; using osu.Game.Users.Drawables; +using osu.Game.Utils; using osuTK; using osuTK.Graphics; @@ -132,7 +132,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { avatar.User = value.User; flag.Country = value.User.Country; - date.Text = $@"achieved {value.Date.Humanize()}"; + date.Text = $@"achieved {HumanizerUtils.Humanize(value.Date)}"; usernameText.Clear(); usernameText.AddUserLink(value.User); diff --git a/osu.Game/Utils/HumanizerUtils.cs b/osu.Game/Utils/HumanizerUtils.cs new file mode 100644 index 0000000000..398c76a09f --- /dev/null +++ b/osu.Game/Utils/HumanizerUtils.cs @@ -0,0 +1,36 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Globalization; +using Humanizer; + +namespace osu.Game.Utils +{ + public static class HumanizerUtils + { + /// + /// Humanizes a string using the system culture, then falls back if one cannot be found. + /// + /// A localization lookup failure will throw an exception of type + /// + /// + /// The time to humanize. + /// A humanized string of the given time. + public static string Humanize(DateTimeOffset dateTimeOffset) + { + string offset; + + try + { + offset = dateTimeOffset.Humanize(); + } + catch (ArgumentException) + { + offset = dateTimeOffset.Humanize(culture: new CultureInfo("en-US")); + } + + return offset; + } + } +} From 20b611486350e69582f7a5a126463f4ad1e78db7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 17:52:06 +0900 Subject: [PATCH 2101/5608] Reduce method complexity --- osu.Game/Utils/RavenLogger.cs | 54 +++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/RavenLogger.cs index 2a396d35cf..6aaf55e045 100644 --- a/osu.Game/Utils/RavenLogger.cs +++ b/osu.Game/Utils/RavenLogger.cs @@ -37,35 +37,13 @@ namespace osu.Game.Utils if (exception != null) { - switch (exception) - { - case IOException ioe: - // disk full exceptions, see https://stackoverflow.com/a/9294382 - const int hr_error_handle_disk_full = unchecked((int)0x80070027); - const int hr_error_disk_full = unchecked((int)0x80070070); - - if (ioe.HResult == hr_error_handle_disk_full || ioe.HResult == hr_error_disk_full) - return; - - break; - - case WebException we: - switch (we.Status) - { - // more statuses may need to be blocked as we come across them. - case WebExceptionStatus.Timeout: - return; - } - - break; - } + if (!shouldSubmitException(exception)) + return; // since we let unhandled exceptions go ignored at times, we want to ensure they don't get submitted on subsequent reports. if (lastException != null && lastException.Message == exception.Message && exception.StackTrace.StartsWith(lastException.StackTrace)) - { return; - } lastException = exception; queuePendingTask(raven.CaptureAsync(new SentryEvent(exception))); @@ -75,6 +53,34 @@ namespace osu.Game.Utils }; } + private bool shouldSubmitException(Exception exception) + { + switch (exception) + { + case IOException ioe: + // disk full exceptions, see https://stackoverflow.com/a/9294382 + const int hr_error_handle_disk_full = unchecked((int)0x80070027); + const int hr_error_disk_full = unchecked((int)0x80070070); + + if (ioe.HResult == hr_error_handle_disk_full || ioe.HResult == hr_error_disk_full) + return false; + + break; + + case WebException we: + switch (we.Status) + { + // more statuses may need to be blocked as we come across them. + case WebExceptionStatus.Timeout: + return false; + } + + break; + } + + return true; + } + private void queuePendingTask(Task task) { lock (tasks) tasks.Add(task); From 98bb6da9756940cf7ae89ec02ad11c880271087e Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 30 Jul 2019 18:16:17 +0900 Subject: [PATCH 2102/5608] rename test scene and create a new game each test --- ...creens.cs => TestSceneScreenNavigation.cs} | 40 +++++++------------ 1 file changed, 14 insertions(+), 26 deletions(-) rename osu.Game.Tests/Visual/Menus/{TestSceneExitingScreens.cs => TestSceneScreenNavigation.cs} (81%) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs similarity index 81% rename from osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs rename to osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index f89e67db74..e77a7a83c3 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneExitingScreens.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -20,49 +20,37 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Menus { - public class TestSceneExitingScreens : ManualInputManagerTestScene + public class TestSceneScreenNavigation : ManualInputManagerTestScene { - private readonly TestOsuGame osuGame = new TestOsuGame(); + private GameHost gameHost; + private TestOsuGame osuGame; [BackgroundDependencyLoader] private void load(GameHost gameHost) { - osuGame.SetHost(gameHost); + this.gameHost = gameHost; - Children = new Drawable[] + Child = new Box { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - osuGame + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, }; } [SetUpSteps] public void SetUpSteps() { - AddUntilStep("wait for load", () => osuGame.IsLoaded); - AddUntilStep("exit to main menu", () => + AddStep("Create new game instance", () => { - var current = osuGame.ScreenStack.CurrentScreen; + if (osuGame != null) + Remove(osuGame); - switch (current) - { - case null: - case IntroScreen _: - case Disclaimer _: - return false; + osuGame = new TestOsuGame(); + osuGame.SetHost(gameHost); - case MainMenu _: - return true; - - default: - current.Exit(); - return false; - } + Add(osuGame); }); + AddUntilStep("wait for load and menu is current", () => osuGame.IsLoaded && osuGame.ScreenStack.CurrentScreen is MainMenu); } [Test] From 0291a708d45f38c6ae85dc45fe8c9055ed12ceed Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 30 Jul 2019 18:18:03 +0900 Subject: [PATCH 2103/5608] fix step name and rename test --- osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index e77a7a83c3..ca94f2b636 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -50,11 +50,11 @@ namespace osu.Game.Tests.Visual.Menus Add(osuGame); }); - AddUntilStep("wait for load and menu is current", () => osuGame.IsLoaded && osuGame.ScreenStack.CurrentScreen is MainMenu); + AddUntilStep("Wait for main menu", () => osuGame.IsLoaded && osuGame.ScreenStack.CurrentScreen is MainMenu); } [Test] - public void TestExitingSongSelectWithEscape() + public void TestExitSongSelectWithEscape() { TestSongSelect songSelect = null; @@ -67,7 +67,7 @@ namespace osu.Game.Tests.Visual.Menus } [Test] - public void TestExitingSongSelectWithClick() + public void TestExitSongSelectWithClick() { TestSongSelect songSelect = null; From e8e5b2742d545d1344769afe965073aaeae00e3f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 18:31:57 +0900 Subject: [PATCH 2104/5608] Fix manual clock usage --- .../Visual/Gameplay/TestSceneBreakOverlay.cs | 65 +++++++++---------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs index eaae647dbc..ed5861b47d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; -using osu.Framework.Bindables; using osu.Framework.Timing; using osu.Game.Beatmaps.Timing; using osu.Game.Screens.Play; @@ -44,7 +43,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestShowBreaks() { - loadClockStep(false); + setClock(false); addShowBreakStep(2); addShowBreakStep(5); @@ -56,7 +55,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var shortBreak = new BreakPeriod { EndTime = 500 }; - loadClockStep(true); + setClock(true); loadBreaksStep("short break", new[] { shortBreak }); addBreakSeeks(shortBreak, false); @@ -65,7 +64,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestMultipleBreaks() { - loadClockStep(true); + setClock(true); loadBreaksStep("multiple breaks", testBreaks); foreach (var b in testBreaks) @@ -75,7 +74,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestRewindBreaks() { - loadClockStep(true); + setClock(true); loadBreaksStep("multiple breaks", testBreaks); foreach (var b in testBreaks.Reverse()) @@ -85,7 +84,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestSkipBreaks() { - loadClockStep(true); + setClock(true); loadBreaksStep("multiple breaks", testBreaks); addBreakSeeks(testBreaks.Last(), false); @@ -103,46 +102,50 @@ namespace osu.Game.Tests.Visual.Gameplay }); } - private void loadClockStep(bool loadManual) + private void setClock(bool useManual) { - AddStep($"load {(loadManual ? "manual" : "normal")} clock", () => breakOverlay.SwitchClock(loadManual)); + AddStep($"set {(useManual ? "manual" : "realtime")} clock", () => breakOverlay.SwitchClock(useManual)); } private void loadBreaksStep(string breakDescription, IReadOnlyList breaks) { AddStep($"load {breakDescription}", () => breakOverlay.Breaks = breaks); - seekBreakStep("seek back to 0", 0, false); + seekAndAssertBreak("seek back to 0", 0, false); } private void addBreakSeeks(BreakPeriod b, bool isReversed) { if (isReversed) { - seekBreakStep("seek to break after end", b.EndTime + 500, false); - seekBreakStep("seek to break end", b.EndTime, false); - seekBreakStep("seek to break middle", b.StartTime + b.Duration / 2, b.HasEffect); - seekBreakStep("seek to break start", b.StartTime, b.HasEffect); + seekAndAssertBreak("seek to break after end", b.EndTime + 500, false); + seekAndAssertBreak("seek to break end", b.EndTime, false); + seekAndAssertBreak("seek to break middle", b.StartTime + b.Duration / 2, b.HasEffect); + seekAndAssertBreak("seek to break start", b.StartTime, b.HasEffect); } else { - seekBreakStep("seek to break start", b.StartTime, b.HasEffect); - seekBreakStep("seek to break middle", b.StartTime + b.Duration / 2, b.HasEffect); - seekBreakStep("seek to break end", b.EndTime, false); - seekBreakStep("seek to break after end", b.EndTime + 500, false); + seekAndAssertBreak("seek to break start", b.StartTime, b.HasEffect); + seekAndAssertBreak("seek to break middle", b.StartTime + b.Duration / 2, b.HasEffect); + seekAndAssertBreak("seek to break end", b.EndTime, false); + seekAndAssertBreak("seek to break after end", b.EndTime + 500, false); } } - private void seekBreakStep(string seekStepDescription, double time, bool onBreak) + private void seekAndAssertBreak(string seekStepDescription, double time, bool shouldBeBreak) { AddStep(seekStepDescription, () => breakOverlay.ManualClockTime = time); - AddAssert($"is{(!onBreak ? " not " : " ")}break time", () => breakOverlay.IsBreakTime.Value == onBreak); + AddAssert($"is{(!shouldBeBreak ? " not" : string.Empty)} break time", () => + { + breakOverlay.ProgressTime(); + return breakOverlay.IsBreakTime.Value == shouldBeBreak; + }); } private class TestBreakOverlay : BreakOverlay { private readonly FramedClock framedManualClock; private readonly ManualClock manualClock; - private IFrameBasedClock normalClock; + private IFrameBasedClock originalClock; public double ManualClockTime { @@ -150,29 +153,25 @@ namespace osu.Game.Tests.Visual.Gameplay set => manualClock.CurrentTime = value; } - public new IBindable IsBreakTime - { - get - { - // Manually call the update function as it might take up to 2 frames for an automatic update to happen - Update(); - - return base.IsBreakTime; - } - } - public TestBreakOverlay(bool letterboxing) : base(letterboxing) { framedManualClock = new FramedClock(manualClock = new ManualClock()); + ProcessCustomClock = false; } - public void SwitchClock(bool setManual) => Clock = setManual ? framedManualClock : normalClock; + public void ProgressTime() + { + framedManualClock.ProcessFrame(); + Update(); + } + + public void SwitchClock(bool setManual) => Clock = setManual ? framedManualClock : originalClock; protected override void LoadComplete() { base.LoadComplete(); - normalClock = Clock; + originalClock = Clock; } } } From eaaef61bc2ba264d1faf63ce16c69e292389f876 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 18:59:17 +0900 Subject: [PATCH 2105/5608] Revert unintended change --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 897dc36dea..0a19eac2b5 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -35,7 +35,7 @@ prompt 4 - iPhone Developer + iPhone Distribution true true Entitlements.plist From 1222536f7ac5380b1d217b5f7d69c77bf9e7a1fb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 30 Jul 2019 19:10:21 +0900 Subject: [PATCH 2106/5608] Rename resource string --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index 37ac972f41..eb1977a13d 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, Anchor = Anchor.Centre, - Child = scaleTarget = new SkinnableDrawable("osu/Game/Rulesets/Osu/UI/Cursor/OsuCursor", _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling) + Child = scaleTarget = new SkinnableDrawable("Play/osu/cursor", _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling) { Origin = Anchor.Centre, Anchor = Anchor.Centre, diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 48888191e9..a567f85a02 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -73,7 +73,7 @@ namespace osu.Game.Skinning { switch (componentName) { - case "osu/Game/Rulesets/Osu/UI/Cursor/OsuCursor": + case "Play/osu/cursor": if (GetTexture("cursor") != null) return new LegacyCursor(); From de20d026727094eef78e75d36c239cd4ddb1fff6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 19:11:54 +0900 Subject: [PATCH 2107/5608] Make special skin more generic --- .../special-skin/approachcircle@2x.png | Bin 31796 -> 26840 bytes .../Resources/special-skin/hitcircle@2x.png | Bin 263521 -> 245645 bytes .../special-skin/hitcircleoverlay@2x.png | Bin 262013 -> 247101 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/approachcircle@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/approachcircle@2x.png index 5d28b3f7cb5b7d682686c9a93a994ae506f68f2f..0a6ec6535c3b20c63fa9e47fa03beac92c64bee9 100755 GIT binary patch delta 24199 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 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hitcircle@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hitcircle@2x.png index b4eb5221ffd0c2791d079ebfc6bafcf0ac7a31ba..919d8f405ca7f40c921e71b91e7a81655db1f94b 100755 GIT binary patch delta 17705 zcma&NX*`tQA3uD}HG>&s-$Fu$Y#|ZZCP|ho*|!jdtd*2?t|19!Nwy-iNY=4rDa#Cr zWEtO-Jtk{qnXzwU=0Cstestfj`@#KSo?P=f*E#2Nea`!{yx-?{GEWMFt2zn>M&5oF z1A8W^A$eB&l$xgc8EtJP$A65tFET(?WL;j<9+6=n$}sZ z2LUXP0$56DXC;cv5Fo!!7E@krnXS}pz=-rF=?w-5vcOzI&nz>+YW!1CF z|IhX1NZp4kbN}x@$&(h>yl)2I4GHzjkqU>4G)_jqjbMAL0bMKXXo zeJTEV9yjl3R7}jp#^7J~hPE9KVV}a58qO^t1}i7HT;*`gr=#a!cb6JI52K1)8;>3`3R6}9lpW&cKmHe2-V4c91z^AZ@YyTf(?rHsVW^6DlX=h%xE-_+Hi{1^0P808uE4)eA|mOL#5(BQZ?V+FWH zhCEqtZfa>F6usdUqjK3g3se0}01FQXr~wTOJso^J6=XnL&8<(vz;M?(wPv>M*|9Y? zBRoDsUvMajERjd6TZmOJ7O_L~ETccBmLUELq&z(@7l(F|!`{}JAlmvB;NC@A&=?~)o@mc*E&=X(vnA2-Ku{+4Cepe*vqZ0k^5G4DSRI1 zDOs~h?`_js7qj?q%=P``!Lfvw#ieNOi-}SlX=Crc6_v*&RqzwNjLFBP zBM+Rfv)F1YX*{>KWvT2$EB3lY$Y3^#^P278zB1<;7z1w>=ue2t!Dg&M1D8w zU6P5TAg{&o!KUB17Ked;>MZ(tKeRi@y6r8Ec$SvNVl%9_9c<7N)VM=10^BcL>1E}N zk}+xUMUoj@WS@I9j+e+6Ocx##xV~wuO}2uqA0{)7mb3Z?Rg92e1{Xn%IZu1o=Sp?X zB(j{L;eXhH;M6eCB+u-29#nMhLgxPRSM%8a;MF7VTto9C^$rRg_M^y+i@HVOrpyLW% zmi=y8r}qmM(*HUJxJ5={5#kR2Z5v{te;wXgj1TzS2G@cb7ryLZ+TtD8 z*U^KG!7?~L-ckR4IUom#`do+Kkt~^@U|IuO4AWgS>Q1T*z1{FB)x=EjmJDzy;p^li)vI6Y=BQ4|f zz0G|&nH&#d|`#!^9~boNQF>ce>!XV3YXahYM>E4_mP;m)L za~jb%b~}sFYb_DqjcM&;IGNicbge8YB^>`^R6dm?D#T6wO?z?tBYdE(s~o~zu{V+*jt zZ+}$S!vnUrkcse!{BKh4708?JI;6ty6IExHdl-}NjEc%Ig0TwX1&qWdryjP>Nh16n z4$<%&$ed5(Jxzo9wkwvbU=ZzdSND_IG*zW5F-CzZbX>%G?s#2Vy}<7luL6MzVY#D| zCkD0_Ydr&h)xYZCPe6F)oPZ2lED?-0+SMc*SU=*oLBsrRSI)tVv>rS8Z=d^QxF(c!UbT=@qZo# z_Q`(r*Tb?eKYAW2N($`cOE!9~E2aC2Q}$V8#x z$fynbW9Fd0%daAS?Ju{)-Mo7<9!y{W_GRz*a0Y3NF0!%GqTx

bF2s0)VHd_aN%?wwRSD#3e> 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 delta 35772 zcmZU4cRbba|NiS72ZxM9?mZfsH}{lgp};pF;dytD@1k(Az4Stu|i45 zrj)H?@A18Tet-VXqaKe#bYAy;KgadFuIr9IX809>dFPKn`er8tA`6PJ(^m%MmELQ+veR`H@jwFL4GG9}oT;&eg@isS#iA)!1{uKH4(3w5J> z=0=GCf01==loald>dO5nG!d}n+Pzu`iV)P%R5$az3G}`&T7~OA>msf2SRjLj&*b$4W6`NI-=NN{`Oe1K97M={s+?wW z(Du(VQGxuhq_X=?0HfW4d|7 z?|pfB`(dxwdH=6lN)-E9k&wmKjc5W(|A#_B&Tm^^=xL8_QQn@{Y63k6j%`1|5!eY) z@Ly-RX-%0xcC4J@_x1b(U$Sg$Q>9WqU|P}`6?&>~c3&j(+{>h^)qu|B#DMlLo9Z(3)Mgrk=Ee`S z4}}!|CS+HtjO4K`q_Cm(9ftSW`Yu#eS+3t~kY(vRr28pIacn&!RBrB(9;)OZjMl z)ur4KUXILpg2*Y@s#T1&2}<*6@+sFvG>RgNM%eo7kB~HoL3LD`zzTw3x-TVV$<%sH zVofRVS*apk_q_9>@z1k!_avg{C9|?;|LXh-WK*VQtq{qwb&MpGXJ=nUMP>~QBEo49 zj+%H!{4b5lC-$%trT>3o73is3dfQtc3oA-jQJ5Es$EZsgzSr&&dpX`ntO66H`T?K_2g;c+T2IJpArj2eW=-a)n znAaW$xk>o-+Xp4nCAeR?BuEdDMUeKKqadKAq}0suaAzAU6Cnb!$)C3hI3?vWi5FRM zD@xum=Mz`4T^hM`UIc1XLi+H$D`c&(+Ti&pO1Rak?Z(r?j0kG?cR7#r*)5=$45!<< z(1EuN9heBRBBZ#PTL<;!(L%ij$nK6qt*Hx0---1|^y?y8r4DVooEQq9z87{{kT~&C z9D5wxx#vqzWsDmTv{`R-wX^cKsZeFyF~@mWJWRccI^FR@W7WTT9h}U%jCBO3L^Sy( z)E`#-gBZ~$Dv^x%@K*0h+H}eG`5Gujw2UD}t%xM~lT?!Hc*(v@2%|m7Nga_GD7UPy`F|RB> zHOqaS{;#$3bF!7T9Xr^zmFtMcrGS@EGJm*M7=ADu;W$NZla?mj2zeqaX8DzR1wIJJ z6O5n8bT|gxT;@)7-ef}@i$N75XI_5Ejk7c6v13B8ys+b;G1EB$A2^!Kk2YDY-{E3N z{(et#FYYNdkKR?0Gw|%mQKW{1U8dTgg5Ijn>{@pu5*mZ$%?YX%Wjk3({D}NS2;vXJ z=!!s)xqq(N&7<^)d;9~^Nif8hB=^!K9SOa0N&nq>AR}QrBYtYH`hhkS`8;RnrYSX^ z$C0Lu#!(kBr7RS@od!LEUXQt7rV6tDCr)u7l_MojKjYN*Rggkg#GFqk(WD)FHcGM! zd$z!Zc|f|@9{X8>E`oD5)1z0!fo}5b9ZC@=hDZEidhs~@c+GatOxQIeDpxoE4{#^iMWopQJPhttqwE7AsczMwE9E!n4;`&nD6w4Q${WY3PR(T<>NX7 zHuhvX{v74vZY8Ds*Za9`MoEq=KY2HNE#RVl!f>trEz;le#kCt{?c7BB@7^y-Xr8xw_H+iD3RFd~~ShNJ_+Q6^8Nz4ty zY>0f`AUeUbsUwS;_!p`N7v^>!ODsk}^7##jNkDj}n8Sfk8+@LV`{ODRS>HNE%D``_cbSP;iP7L=Hw(5k z%XAp2yNzb1`f|0R+tMhui;oaf#?D(Z-nR1<}uae3DJQRn4rnnn`;KEsE3?@#v*- zpyNBm36g~`KhbJPd;q8Od2jC{x=n(nO@b?ysNOQU-7sF>($b({S-g#(@$ zUkj$?W1P|pTtNPtjz6CJ8|=jpZjT{)5!E|F8$fG6f`D!QbO41}@+of#}8POXs7f_1R7I`g6YRJc99Yeuz>mFz#L zoMaM$LB`{Pr&Llt0v{#EP7S!U5aHazSpZvD}$<G*OMn7oPWdtp1e|OI=xQF953z{gdfJ)ek=X0FbL_7J_rH;uSkR6!m86t&{Mw~wRAr#B*A?{f%PjByl8`bN8mcpME)Tb$mx(;P%eIl4Ai zX^!&5Dtqh|uot=|H<}QRQN|+Dtag6^{5W9bM!9k&Zp_ zDe5Cfe*^8SPsba48BgcR&IQ*cL625QeAhPITHj~5GwrZ_*}XC>>Cp2|tb6W};#U5( zlm$|`^*!7AhfZ$({tbf<>h8r%57oNCDae-8q4R#dT0H5JR2pcE#?-Mc{hVd_Da-Q6 z{DzOL;d{Lup37b@Fd;Y{jd&ctOZv><73qry`o2u@Dt~-z{^jajm~wxfi*BEm1WTFQ z-k;i6(KOZsKdOP&5XmnY8$4QZ{otDRY|v#-r?x5=&0{m1F#uPXvhw1~9$6JQ(Hlhp*R zv{K(=6SrAq5nqXWlJP4S2gQKbGn?1LCQHpZ`vCGtZnv7i_r0Xzk+12W4QX zdxu9JN<99?EZ-vD<%o%(pE?M0QRrPpDtAUzENWPsU$KZMz@t|nrzw&$%(UUxquRHa zg5-th+Oc(Rqc=eFs<3Gq*_jGuRJ>k(%W8CN?7m#a*L1hhp;$u}bk0!HGk^S=Wy6kT zXV8);1*DyTYd!LMSx{`0xAvP4Eik#A0J;>lI%dC_7o^nCdgBQ~Kq2DQIf$O+bUB&O zBSS-2VYWwtj?4A_$MSn0%I}pRw8Py-$Ew6Y(q9&$HXp!yvGn|qo+BZZk3HnWrl+U5 z4%9Jf*l>&%(;JtPXSygz;zbwMVN8Nyg?s= zR)2q~@opIRuqJ_GAVC)@N>21Y$Q`2=CUcYur*|qVS@ahFdJk$Qvqo4m`RYhVgPjC6 z3;^yeC2@ujKAI3d-Uv=DCO_B=G6{AKha@;F2)brhvL5ypbJ+9%FjEV=dC4$;1CY?7 zbg=4XS+aEnsq99Xvto=xefhnSTDKd?U+CKGq9h}_(4A_!G{!8gcclT|IyL@)?Mfb# zPgcrl=p66nz2};I`8dcC$_EAQHmzS4wMg}&{hI@d%x8~J_=O7&{We&OQ9`_t2AWlaa93KO$%fIdiHGjl=4TrU)`v#A z#X2HRi6)nsf*sNe+|p+{!ATgLJ1v?o#@w1qKWc6DAV(YNC&(WU1=rzG6K9Z6s`sX{ zIK1;1DNNCfNc$rPfbkP=@3BQvMV;#2T;3+Y4V$1DoM1JVbgK47t^O1QuicrI4>bI0 zVA$2m7LDaD<=C|YC_qR^=xBAdQjUwE2}~wY#A%RsSLN-_#W=jay%#{mqg#xEbkLpG zZq<-+2sNqp5)NkusH`vRjSH;%CXofwX3@ev8(8(xqv1EBzvisVo(j6CYu)J9$jA*h zQ0hVNv$$6`YEV7=o|{-HoPPy_x-Wq>>e&HP!>z5-565P8XQ7@rC`dK_6)xF{Ux7W- z3x}+pByTJCtta4K-_SOq@)lMomwJU7k+_ERWBbMF=1zg&`)~nHJ+u4%*V2@@-;rqs z=u_YmwzswxvIEw1X4|7VGcH}abZ^um^2-}CkbZwUCmuP+y5ht782sNRwH&K$E*z-SY&&~y7av7hMef*iD zq*}B~aYr`k)>#-*dx?$5y|%}iOl}W%cG4)z%TECmQFDXdJh-~1#(Z>Sq@-?i`J+9y zMn1-^Z(VP4J6eLyg^MU1<|+O5&*Pcbl9 z#*8ly*}Gx-PG8nZlV5nG=v_KkBEu1VZnhCIkU!uilK;A7Pxy>p(#wS&wx7Kh+vDVm z5}Cc|Q+Xxm+9VWa10=9?p?v6#Nwca~dqv;H!xw*SLOT*Q_j*gCsMwj>UzTIU;sVCxeLUM${&>e*T zFgp^P2O{~>*AYf>M;r*Khq<+iWOJw&A4+i)Cy^b}GlDAcmgg?S-tO zlB|{=i=k@=G1IW+$%qiEdh}s^_)fN)^~Xmp4uOG9zdn{*Cmty7JTBG!_nLThiV@6O zb)($8JUk3pDuIealasvO4c4#{54ADN7oGU2T-Feb0GdBUGCWH)<#29SMljAlC?C0| z?@#9;i-e4Zy?g5opj{avk{hKeil9^~=#>-^yf%;s)9_nj!(Ws45f1n7W83?y-kv6U zrk5|)auHn=VodAAx~-DY5%x%a)F8Cw$`OIWI`kNE-ii9Q>a(PtJWZHv)TUvn$POEp zMN3@JA-;T0;S)N`9&nll5^uEmTgNa^oRPeGv`%mj(cKz!mAU8cUU9TLn_UsOH(z+u z-`^kR1lj#dKBhQcr;uv-Zf9i|))rw4h`F6+-qbHmklLcxr)4PMW{8F7LU zIvywgS;m-;EexYB@-^5NhlqwAO%>+&2BLz3p@{I=^G$q6o^9b*<}dyW?wNKFM~LFN z4#YD4L$e|%pyUFV%mR_vTw%Hp0=%u{et&d}@Ob=6nZ><^@=4szP_?D@6-{$;;g-;v{&p)V2&hSvENF#jnoQ<+T1A@i3{LzC3O$6sPlD zK4t*m6|m@&lUDZMdV4(gEiXaHFpCbb1+%_37%gM5{3vxqwu$0p2;##!6#M;W9>KSL zkh(Mwk7q7;6Xze$yL*aBEgpCA7vxRj`dLj~kXijrJ|ss#9~ovb)7@2tBL zkKv=Ki|x!EQ1;!NJ{^b#O5DCWwU`DQWoaXtw4of;pMHoLjx8hvNzyr-Q+PgMbCxRJ zT*Nf@_E9Ee<`Z`s0ZH(qOta))nmmLEoodq(ba}!NA$;g_&E#0unvtU6``))mZa3j% zb2I;sW0q?8{38c< zGm{m40sQUn?%Y+)N1`izoMWa7yYy`mmtMsjt`d3W;Ps5j`vC{5#8FVl!JP3!es-wE zc46~;yuZAm4Jc$QfvOAJ`$w&h2Yy7+8QDkkgDoai~P{+twcOe17ba@1=%15DXIR4KYFV}xJ7T|CdiLN z^P`N3EQvP=VRrF2GZBgsSIX4Hc+cK66H0BAh7eK)aW@{Y{wVcK9GE6wtETBST9nq< zln(v`2aOH?g$-}bPdqgUO_&DQ_y$ryt_!JC_h3Fre zG$2%gCrn*n>YEh3_+QMz&7r_vc&4?&NXJtiIR*=E=VZVo<;WD_q3buGoKcR)Jd z@>QY#llQk9D{cp}gF{vl2ZuZ{P-tlQZ@huj^n`5V4#TiKXskN%VJ2N+80Jze+(Nf= z5rxmPeMz93Gp3otlhBBqvC(TX(ee;f6s(q15CMZ^*I{my%P+x8UP&w@(FE&?xV)qT zupG-VhXNypA`?dALyt4^%rJ@dMM(hNw0ssyeTwMW2-dFXlKvAkX(!o?{wS32snL~2 z0i-K7909%gcDHA2775dc-MlJE{`fJjW)YHNCIk@fT}QYh5iEbdD>_mNa2Y)5&K%t5 zjFQY7m>)VpWz(_n!F2m|+rXM8z>@w18~~uyyHqc{NOAwtDfiyeHrzfHVDPDx6_1UT zUu|IJPh$T~woH;Y{iZ>A(-k>8nBzdXhDtmj1skGuV64MME4bI!W+g8)%LK?k|I{yK zt!`zmo7CH)=|$;-vqYBX6nBMlU>jt6y*Z zP&w*{X9SIUfPtW~h_DpF19|~TnG=Nb#WKG02_eh3G#mq;BOwzlluLR6K!=)Wrl(fz z5_e@YI5nO#c(dOgS4%HQ!r?cOu6dbW|K&eg+*Evs$AxvY+Qo@7Lq$}3uz*xQ_pQ@X zQ_tc=@Yo42Bq1{Ndkg*g^pWr3;YFO9hzyWc9)p2&j|?C0*VrEKk>+;q)w<12iEokF zu5KaJ{-d0hKLdtOB9S=#jFC6%V69vH*^_@`3Mv4cg8ASDMnE8pZz|G%d|gOus+8!` zy5AkI?0jH|Xcqft3!m9AFGvVx2pGGU#T$?7)WPdrd$`VnOgfb#Rm!i8P@4mjB?}gL zS2IqkJq#m23GwH%3Wn@kH4DuTpf4~G&uBb< zB+Ze;L{RFpJtH-@i}9-diX=>Dd*4gi8On+pX&#N$lG1=0k^(_d(5WottR#C#oLpO#cGW?GLaxS2(}! zQL1Ek;C|)I=4lP>PYQke2iNeihlhpu3jaN+*jVE3)4)zt4)0=w8iKpdj0rh|E)qCZ zVg{?z zZSQvc?_W7+Oa}#r?#Em1H?LRNSi8%@8IRqB$z$Jb@FEDiw#eMO-42Q<SX%b_a#fG6O*{Jgt^SG4}Gs2<(K6k^tb!lay zy8Ups(jMDBGgEN*H^sIV-XEQOVBHcFm8 z0BZZ}j6a#=o@jvqwFol^X*`d^FjGJws?JegGS|~S@RlC1(4cjTi;&IsSP_2Bl3CIG zAf}EC_p)WWt8Qgk=cMJnz8$1ivPqL@ z3`uYki?4~uRaLMOT^Xn|&CPAEyj}Vr3X4Ih;Ye=ao(UnbP&G0j)#k|>$rzD@BlAkw zDO)xF$K9G6Gtr!K3n!T=rvj4hE0_@r(mSU0rr0$2cA6TVkhhu-w?+@$n|Ehc0Ggth z+@|11A#GERe9;7jSec6KyF9kS{gHr!Vwr8B>ld%eC6Zb$$KwiFUhu%@SYm+bl(6I7s|{5pnz&-`tffNP%h$x`jgyM)D0R zlmz*gd_s!k>rKlihudo(ayjw`|CqR05>~c%WA_FcRznvTtH8RaUaO^<8d;|SGIZ24 z)1rDf3c%$sjHJOk+DJC`3uh^tqNi~JJbH^rn_^}kZWR7Si>%(WonDHTtb_AO$Km!^ zw*PKS3q}Cs`uwKf5vZ08pmEw}2d;mWJ5k(t^x$&| z5Tt=>K0}_hh5;vz><_N+KT5>JbA-QaE+dFvwBDo8Yav%@;uS*VWAc06*W;{SJW#nL z6*4Ii#j=hb;x1W3DD;1qe#(b_(?k1VgFGWZ!(xu#QeIa?XzBGx>la#-J`Tg!bKOzO ziI3HqkL4uwUM#Xe%0K!*&rYKWuSA#=N^#J^H{dehJrz_!XfZ<*u+z)lqk9_zhMcxR zyMMzM{&`7GS5UN|gA^{Tbhg4kex3x?V;`K0(mrSeo;y3M)BGX4kU)DX!;z(LVB&$K zUr^L0(}8Gx3Wco@gs(fjqvg*e06`M^rlNoU0|<@(YCdE{GX;xX+hJ#Z{|+B_U!+EY z&R(AD_nRWkWos^Dbljj%q6iY|zlQ?Gg|RDnm1jgul^M;iMYGA#4&v~X8V(%`6iSbe zlExOV>qCBHd42yvN2MxT{yX$7v$zP@6pHQAisl;)p406>WV+E->*i(iB%2{f3v$7r zawo}#JW4+O@X7O6{x8CSfLla&@KSf{E8h0YUL_CN;cbP^5!Z(3;;{kLa<}g?YR7M5 zFY)^=dbOXI1k6>`M8BLgFoK>)cyC{VG@@yIVKY5a4Z&ChV znd4RVleT0&nA<$vCc#XJ@$DXkqgJPPnH4}1A_ zmy_x^Q7R-H&5!-FZ5f5);{fB&R?{p^lNzGPPrD>-l5&>YL>qSFX8o|bzA@pJ=J zI!7vd8;qYKVsvzM=-T?tFY{2@sX*BS<$~X|@oE;q+97;cP)x6g$e{VbDEHU2J7K9U za`K6@cy&GX2bc63zozCh;jej7!928cnmKhhttna75q=u)s7zV$)#xTOe^ykE|M9s@ zn`ZwkTH(#3aQl_zWw-s4sWoWh+to!*PEPpi?Xec&`4rp>FeZBf;srpTJ|cj+lZ@_@ z&Er5g+RMp8=O1yc^mPR3ikv&pZP=M$t5EHGl+$NQfjt93*l_jV@>Kne0-{g=V}NSM z2s0206UX`rp>3rK#*({HCS5fA^t#1qCG)M3ImCB(y?c~J_SgcqQ6NfH!YXNc2NHCb z#n{7lb)ivN3(5t~P&!Wi4l^~VLXEPK7O6&_4D(t$0$OpS=k%4s^*&YG(cxhiFm(E7 zZHPziOHRW8rTwd$4D$Ec-&#%xY9XK9+5F9;WP=J?nkYpc?aytN-hau_Pya&A=~$f! z0XgP(YccZyKC6K08BBK|uZjTk=uR_y8%)U6f}gSZiBj!!P{*j@uZ9`_ByGEJ`yoIG zjx5)*p;|RJ>E=*I1;`RV$_P=&pVH_KGC}Vk)7vSyjCs*qpj4yEW^6mruQB#w3yC|@-)Lmqy0(ZP7Ye+xk z<#(N*z_Rg$xO1H872=P-FY46;D32G@L%gv><@VH0>_w6MF=>6>s!m-RzkuaSGyZ0X zOs@x47G*XSPdK8f7^n?BhNLnXs8_I~^5G~gt{hq{;ZbyJ%1;9uS;U+wdhxK2_TT`! ze*mA*&mVl(XGUgboCj*%BAsdzH?Es{U&U@8FWMe2{3DZN6L2)AvQ$3_WFvPBo%Zzy zSiU$;Ds{FXkKVEl5|jk-!~&Nt;fS?a78*=%{gF!jMUI{qm1>b?7s!WH>rfQcufZ`o>^_XoelVu@p`Yq{lo3a zC+4;=+G_Hir>5;hUxk`2?NN#2WY=Q$*Z%3gQ#2cYa$M4l_z<~%l+OhytYI3XB+Tb9 zUiuKABQfX$gHk>U+bPB?Z#H%hrN%;Ya`HFIes*jh>crzb)AjFny;frBXH~aSfxHm( z9nbBM;+0A}PN(rS1H2}z``1~Idph8DtSvB6onWs`Ox26 z?Ie76R(^G!3>X10069QX{C@FB-rrp%Cc8v{H#hp<`K}|@oxZ+g9gK-gn5E#Y7d#An z@~k_OG|vZ;PPbbcpfu2mX?j$7-#TRJ+Ga92aW~a8R|(RHqQI8lv)E*(LC)wacceL@ zJSewarqd zrun0QxYZ#O20%eq`zPxZ5`GHjjIxoFy^ZW42e%biGHd=Buu!ZbvBTm;=i4jOP(ajVn zw-hXDzG{Fh(HklobOnA|o9o@N_Tm<-CqC|QMr&Bh0eN_9*(nS{0a^C4?^oDr+t!6G zXYJ?!Y+mo?BI#yEMh5+8?FFu{^}?$u1;uo2Mn#`(j|;Pd7M96mf694Yz>|-eUG6Mg zvMI=hDUVX_MSenN=r9@F+JlH1u1a>hYNW%2X>5p{Xh7W7j;+E!sZczeBbC zmTWxdRKJfHC;bOowE1#M-%u&+?$_9NXLhADvxCBp^60wL zdU<`2`}_T*g>B|_2fRop&Mz6d z(8ci}*u1i(WE=RrV;LA3pMiK&@m>4VDUS}pKo1S^RlLxeNQ2CLw&CQ{v->4)R7YqJ z#3#GTeXUI5yvk=$-+v!c)~KByD0uMf{);t$t}ADKh14;C0q!+dv-%I;vqg)MxzS%n zS_Dt}>tU}XyL??!TR>(GEg@i}ez=-vjdU#v*sR&1ElL?qNg6~ zeu^KAH%&X%^gV7p+~1}?3{u5t%$?s@cxYtXnDWg#>#xP$smR=2nB|wqZrNqrI3B3NYNxABeX~)Xw54?A40L(N;t=rAS?{EnwCkk5< zAN*fq*aUt(;36_j(=$hLx6X_?&ZNt=hNH!2HP>tYd;XQu!H3aeJGNc>r}$0!)_(&N z-nUnmp6s1?fImq@*?m-WH*th>zm6Kdr&NrL2hSzfR-&z@dWD&wKYkOpYr2frzwR0H z2?SZ+B6zxpY5DfQG!gJcD)X=t-l=@?BPdZ^S%IBSpYWoMb~ejnZTJ**=;Hw?`=%mI z(VrIIzg-R};^xvUqDfzp4XSOLy~F+8-D52Nw9V=G5erQ2fhLhtnT;mO$S zI^^+UodC_0f-;K)9R=AT$lZ8e(kUhn(;RTHlFVcALK zZ<58BB#v-(@6c8jmv^y2FrRm`sHa(){pqqQ?!&Fc7omQW8e?gkm1Va>E~2HCC!&Kr*?Fdb1$J zo+5;WD7XYIm#qEyFBu{UJ1wcjx85L~aWCz$_kqp45tMB=;I0MQQ>Q}TUsb4Q{RnvO zK9Cl78F^K>fUvd?ctR*nC>ZM?eE1IWCre!@ICq=KTa7%1Gw!Tw1WU2z$Z{VPA>T#g z;-W>Khwy=p&3VQ6kHh1s#u7EDW%`^bNdOM(K&4A|vd4Oqd~FLL$A;Sz>SqwWk(HaM1Ue}>eW22nNxh3jsmdj7S+cLZ4z{5{)#f%+Sd!Q zRCZGRwae+#@;})>;iXuOJ`dMN(aVb?39k8CUsTs!5o^D*fw{bH{K2IUjU=fxRUPK} z{h+aB@20DR_6||D65M zzvUUuC3Ff$2pH;b@jGeR$L%Tc;kr=|dqL;pCOwu+vz8I?uo_E^`#aJr$mn6i59uaU z4LQ!^0GK@qfsY=)G|GnWk0_NMq@6z=G_#c-HQd;kHzkABH_!UMmkHZip!|a8L z)0OfnDhxpNlwR;|NC1}0R4HH2fqdTbq3X3GGX6pylCOaT?^y-|wo9u0dwi|Hn?wNE zS{g>;yU=3DN3g2r`RWDr=Y)MO_G*X0N&Wq8n+f&FK%Ad?Rdiolm3c&?{i@QyB$ zS;I2#n?!A0o!j3-dR>vhXSZE1?rX4UVZ!-=6?jF-Fy=}gu*`J8TT5xcBqq6A*w-Gf zQTt|t4rZFN_(_HtNX|~~cvf?~Y~kg9yN`DnyF8~P`89Dm%;ENPUp$w90Kle&X9#%s zQH}tNJKol$|H2S=bdX5Bbx3i-ro$!?ihC($dF$X}3L5M1)~14UadENS$x8M_g;zI> zo!|-P4F~Tadu&&yV?4MzFgG=+j~Sl9mw4 z3a1m{nzIwSPE2O$`&fQ3UfB3Dh<*EKB1k1WNUlW5W=tv_1z_BM~5 zO{4A8*8($Hqo6<~zc_aJWf^-6Zl5)R8${)cx4*EoV$?Y2F2VzcLivdi&~Gr6&2R7T zrZ49_;1IST1y?+HSd6p`J{+%!-+x;doF)M!ZjfT1V!$P?1o;?G1jZ^;{yk1a`v+RR z;0$YxymMV?8(vfcO8rXFXo2jXW)kxdR%tQg!Fw5SMu%6{);a?`=Gn^*VN8s7Or=(@ zo?PN#dgftYN;BT}?RxPmfy>(*8-ZBB<~x07o&QgorEsq;VjZKVU3 zU@qb(aK%cViwbBtBA<_))@)09Ds0$m(|<2=*Od6*FoTB9MKmE&PeX$RX6|Zm9FArt z-C&U7Znn%t%~Y>m{ehlQd9gyMM2|Re&lKwZd~D>YGO0JzA=U z9Cn{O0`%CbhdeO4MVdWL<~d$854u>zTealwgnkFAS&aGkWG)hQfd!8gx$6rt-8lnF z$K@+@g;W%*e^lpCfNPyN{f@<8qk`e@kpF-F#+3L@v@%oW63qCC+3xnJED3G*z$8x% z38?9Bz|9E!y>B-sXDT`M*aK!}%1e$W+|OU5df59o$ugZ9?}EjY>>|E@+Mn4Ep*Rcp zW$Z<8v5&ru&^T;$Dp+m5rRvXq+LG20`&DWFg!$U{%yv=6L{A^!ExkV~d)GO#{m6mM z4&W;#j%fH3C`We(t$g1yf>EWCr>7+N`>!|W{p;Soy>r$5)E-a4YrFwfJVqc40|=1U zwRAp`eb5(TD%uQX=h?eXsm*qOca$ZlSLxt_Ti<@HB1Mw^F{Q^Iwc0Nw#FvO#w~IA% z)OVs@O0BTzZ$fXt6-l6!dvcxn(yl;5_^~*<1luGnl|HAxz7=CBxqE$(%1&1L$7n)W z&%Of>pNZ*L`%7)C5s}|jfi}qmd=|4~j`H8MWTw_Ds0t*ys(N=-CG%XU=>$xrN=cJJ4n|G z)66Q>id~bBp(t?C&8)Q%LUIub9$Elz9N z)tC~QF>d1PaQk;5xb(`9gJ;tEPApoVfcy5ugz#GE-ow6%YeDiC1}&!GzOv6uJz89||u z!?wytwl6<5+*@b{wdxMO4;!kd7Q%z|^%z|M&Yn}fmYwu0d1gdPk6J=4oB>Z>s6 zlZ5wgU!M9WWFGMOORLkwAM1@ykSe*6CnURmxw#10-ypSe>cTq38t*+UxU2W9_;*qL zT8kwmFdG4{4?~-gntFjc&B`q6;oGG{nI?UYUa%)gnmHoZz;&nTSFgA|ch{V(N(a@1 zAZfF=@;>^Atbg#oe^q`>2EzH8Xyd1`rnaokl?4tfppl`W7W~oEjoCB09IQyA?keo8 zlGpL6c-RsZ=0s4(eAbCam+@VeYB$(~8VTfE!}~55muaZ8)Gc;}5^zj9@t=X_m0s{( z?ApU#oit=W4WGWLNd?KOde|}9$=IAO%=;%#umDvbe1G;E{RchdyS0E|D0xq^2m-f4 zj9CPA;uE{zSA*9+`c{conV`t8%*WQ#WKF~{-{taEOu^L(oX(nHo2W{uC6l)PfFlTW zaNAlSqFNU|+$H^_FM@Zf=pN}J06DIIagkM>(n#<)@-d|G9N3Nd!{n1bi*WVfg9b@0 za8)krh^AFTC%8W(7308;3f7K)<5!%+d^XH(`P4B` zW^Es%9iqUxBTwPQq;y@f;*2j=Lt<%5r!_MD#{aLYGmnR=egF8GF&Mi=2|%CxwNJ0P!`xZbn~A-LYU2abI1$8W(+9NUyO3rpY>VuoXoW?V@i$=$6lvv;@ftX z*Nne+@Fhb_35Rr7ow3wSF?}#~y7B2|rpl)H0MEnb$&iAM*c7up$V+g(*-~SspyJnG`pmT-McHh-8#^dd7>~Q_waOfk4MnG zdz@IA&McdwG+4+!*4W|h**W_kc@C*a_w=d9T~`E0?-wzpxrDoAZAMSDkGQwWwaCSp z7pB8ClvM_b&$8^uF6gMBSN@t@tg6(kZp336d_Eg>em&h?_uTVbeK||~)DN5qu8#kC zc!K^ra(K_V^Utd8J+S;zKH=0gA$uCJ?MS?cT@v{F)C_TXuLigHN5$B-Y#`shB9h7}h|-a`u-FPjhZ~Pv z+07IE&fR6s`@y8j9?Qmh3!ce>7a`$Pjbm8JwZENY&G$cNdDC19(_HjZ$$rF&PPA0l zaeB!`)~QNP;oOurGi^@fNV zQdaWD$6NGezBqk>sqBK`)2r#N%PLu~3^zrC?O~~*$vv$%+NhmEWw9cAp1!bG6gZXd zx;yKFuVh8}2k%~k`HCl(Zz`L9@pA2d2rz|O&oxp3R( zt8vt0PO=5aDn~_Co#Da4D9IQzr6*jM*5299e#WviWCCf%^TbRN@S zHOVta4{lqnv!8pXk>_?`$kjmGKwC;2HmE`WI#4$39!?8M8;kcv?&Bi}CrzVbV~@-( zb>^OuAfLaUD?<2k@U_Jh~1U6)gaQSidWv<{`eVe7g$UlWBO=JY0F;Vw?R*)}>s zxwkxCT8uv~3s9vBYjfSh2ft1$vP6DYBjj_uFob5Qic!I^J&Y@*tt8RUHcho_gkb5)$%z(RtqIM2&z^DS_%@d zh*Xqbs~k7vD3;Y6velNu3VhjDX0(vbgV-~k?ibJe-fl994VJMKk}4ESHJivj3eA+D zMp`U8BhjxNp4ph&Z*voS=+N_U5KZfv{+Sd%a%n+@{m7+eH1(*d2BLlV61WkML?f3l znnBb-ZG;bnE+hH#>6_4+e3UzLXDLA7oo}{b?86U6ESReYy=rX17Nt_=vuo8NVeSLL zK`fF-sv)>&d^FG#arM)AcQ06~FjXzS)%K}Xxw`McvOsBMH_=`Ge#c5f!FN05`N3m3 zi2Z52a6YQe^z54JQKP>84T>{(=iK9|*G$h4jS+xGT)A?^3Vcwl2+}dF$-Rt##E@aj z@@~tkD?#LhnV4^_???_c>DhS6LO^!jDJLE= zj&$&DHP|U`T4?{~1)^`=J66mMw{ai(*I3%Ah^#%MFd`hiZ1}@WQ%?#(eM3S7Hk*Ws z-RdQa^Uv^W+YKsx862F0MD;2pYbN)eJdmVn#ZF2;8k54Fg_z38a^uC&J{-M-X)^LC z+YgHJae&zv^|!M?PT$2E_E~^&qpY^vx;a;T*W*rfe{heBY$?Kp+-7#T_=z`f_)+TT zjZojKSCa#Bk5zXKq7fm&rWzPn(nBD*c`n0ZZBVEd>9oG*xd|a9XgK};981{i&Z??o zA1h;Dhz=g5yWWd%+^lsTRR%vA$dsPn^>81ryXjh0nfeXFU9dQFjc>?LHp)!IG7|{V zjlAwpW*#7k$j`=d1y;R2#k&QPa~s>>kY|4=3D&pYsQMyrXEDu2$W%~ST6CU%NnC%)PED`kB`&k)4Yydh5 zG@&~g|0A2WyLftgzk=oFJZumT30>RwErzo4mW?mhmaUgGq}+sxze8Vj_L^GT`g(2O zWks1#tx+BE7I-}%qkzvDG#|cv(Q1pQeK9M~9+fT3)UNQcaGnTM_%3s&<@xwR`}X#B z_`!4Dz=L;QVZP6a=<_f*uA-}ECm#^WgUbga!`Ja~4zOuISwm#*GxoCWCdxMuc!gVH z4-rLoTRyXt?^A6J04c7Dz(Gbv#z`<}epl(9dPx5OnatijT8rK_E}ru6@=`0GtS5ijYNQt<&7cm?ShIK#C>^keO+kag7(f<~&8f`zU7~wK zaxjnr6*5>C%skblI0;GkQa#MXH8S<<1fz;37Jp$=E}wJ&+@s}g5Sa(f)=VO>2pr8ChET4_{h!I1%-sD`h^g=?zh*`6-U8R3?=)3@7rN~?MpT*$U0;vV7cs5HcB}ym5HSqnlbK) z!XSrQnq#eW7c0;192LQ(m?`urZnm{W*SvUPZLWcwZl?l*r)l99&>&I(hH}c(;^$^( zDnd{#y4WGN(Z)%@S1)yZUefgP6^I2ek46}INa$Z}-Udx&G|{yXZ21bv1ljX1C;HuM zGUW)*R9iz3g)p#LC=tzdv<~qsuG?mAw6Bcl*8J5x>`I+{PCiC^S^yM*9rkF=z0l6% z&3sgF;R*+kNzcaTu0K?Xe-^axBoKiTjjkj@bW^V~gjZ=Qa|Xi@sRb>rl>G4pFt4GL zQEvAFk*C79&!)LtQ`^4*T~Dw)dzu>5eZWlUVu%OzBTmZg<^su>bL9v62B)HN_!!|4 z2jng7%y?ogfLn`627+XBU{dvy1DRUPPzAj{3oy(&qo^j7X~Q^iNm*)vC2}o_Mqj*M%$-g@q6ABR z|7fl1Wv=qdPugFt)wF#Iv17;2wQWa!nM*H{YOT%xK`mJa(VOq&8~W|#>CQE{{`*CB zsbuRz_+l;2lhAEUfoA+=bwP>J5&vDk%DQ`4>Uun8YN}jWQDpbyZaRygu+Z27J%RoE zZ-O3d4fYSt_N6y+1R*|)iouU8yhr+v*wz1lN@fbDLhG*}V`L*>MV|X?3Gqf}%$P&- zplyOlIqv!OH^9w_;sk zs@B~cgu$#ef-Rqyn+Io&z!sv30{I5oPkKmC3ZtG#>kzJ6WQX?3awdw4$7H@Q{EmKw zUD`**5bEgM;3C>;TF8@P1uHyoV1mI+SXW&=1vYgv169M6Z~^b|6>`ubN;-X0sBtM%kV88jb~f&0Qi>sZi3gEMKk zYp^qjT1C>d7-hMKJj}7i6EpQSSXHW-VWj|^OFej91{V2JfQo=|H$MX`+v{pMTc92S z59-+{&Lf3C0?e0QChj|HK%d=LV>^7h7Q`9vC`VfcxmpFP))X>Rlg$k_M@F(j=SFJU zP-rNA^S67lbIx`Lcv=IGPE^_7WF zNO<_)jrjmjd$6?1W$`j_X8^H=Rr~fiz^cGUUYN?C|6Mh({xof+Vqm4tZq%}p>eaZl zeGtc5&->{|?5@(>wm-MF(E2M`MGttX7Dux0e);l*<2Wfl5Zb)( z6f4MwGcxFtD6|NEa-yB@!thIQX&{;4;b~?f?WedGyH}9C({P6 zV$kyj@B0*|^^+Zqg(V`Y>WP+;i>~K}8>QcqXExM~%vl*PjYOv=gKG{TL<3%5Uw#_- z`t`|Zt!Ho79`>ErpU3ShX2#(+!h)EBYJ9flicJ3CQUvq9{eSC*0=bZAjG(hal?#^)@%h2FS_Y>&h=U4K zqxVcr2Vzn~hva-xY<&}railufk+(c^SKGJuw9AjRlgA1M+oSTvjt~N=014Y}<TA(j%R#~$S0Kd4^1CJ-A)R=QTf~7y28EtNd9zn;1CZ;)w9GP5_EObAm zh~zhpro9hOB^=}sROe%3ptHbKwLDiPf%SG08p@z7CE&GGXLR8q!n+Sey6Ye1Sa%~= zdmJnPo>1dJ1S@a}35ib&odE z-6zllDmWl%1SSdFr5@4W4mZ;a>cb8&A&$zXrk1Im;^uFgiB~th{O$9`= z!;pUW6<-i&uP4JPVi`)6r1pq!C$#mfe01D$X-^EbVXXSGuVrsAG*Lll(hl~gC7Rn} z{$0TvQ?) z1vM%7TX&saa@5}F*Uq&;R}Ap_Od?P{d(U@TzxF3$VsOa|5fQuOBqjbysNygAsory! zmiFVQz_4{1De}qCC0%+m1DXz;rqZGQNI9bhP&|;Vbh$J(rv^@s|Jb2yKLl|*`p!HB z%|5k`vd#=qZe1V4<=?{WMjn^-sQ4uivOeZ#sRt|ylfd*C4T>{9P=E2yWEZ;`0QpRPki!_zOhsPd^-1X8kbKc0V~T6{kZ~Zn9{H@O&xLEUa7^PHH#IQV_<{ogqz+bgu#~IP?@_bhhb1xn zm+U)Y`m6)vJs9F{Z7@P!7;gxy-h3~S_r&g{&ja5*3wg%8lvSD*fc8||P`EU+xhqNJ z!Dpt|Qh!n8E3TKXE8q!l{-$5Qz)W)aL5*XEJrJtWV?RLH#OLAd{X+TJF}t3Xq1Uf5 z8mg+{V*1AN)ff1BJ(M2|dvGaT?Hq?=(Hm1?ETyJ7}SYcwYdMD_sL*mZ6w|OE_a*t90g76a}(m9&! z7@#cfuZBI;qA$pW4lOiPIarc*3&K;{S*t+V!035wNqs?PthsbSD8~&y^Ou6L7sTK@ z#9|ryuHQ^m(BVoPw)i3S*hDzq39v(NHKOT! z1tQ(D%+BBnp6X4IJ#Bhq3&q^CQFi!*0Y0V<5VZx_>LZf^e~e9#0UzW*7qYo znz1`f&g9sVifH~t8Hj0yw_}4*6Lk5c#YH)@_nKeREHOj&V$Sl-jC<3%3)h=3%SIwd z(PtMN;)zsFJZF}a4mY2;Rl@v1XtgO z_z2+;I75HY)(@PH?I5D|eZ9@A?`Zlr0lkMF2w)mUpQq~}YQcetH!(p9ayNf7H<4b( z?f2vHf$G4wdjBgjg#zc{K!GBMp|)O=+!}GweY| zVsN?RY4n=&YX;3K@tK^W>11YdH0K)v4{%22E5g>wXv+5{Um!QZt7D}+xjE_q}Gq=Mw z^?YY;eCMA~F(;^TKBGuqs_=9$sx*0P1Ga#?5GrNkAzY6MUcP5rHU%*hZe{&IP5Bspn>o8N6x0v>#Vn(e2|)4 zikjqK2Y1OD6bAMtwA11M9Znq0bon+v%I!F!GGlg{8C!}VM9G*I#g7dK^J8!beD@Gn zh7*3L^g?6(-*hu*6uP!~J63UQyn896PvpD^5-2c&Hg1lN?_8(+{CFQK9J5O8zAukY zTr&MGtIs7bm=Fo!{#r9-9UY~)(n3K{sA%NBC@UHs_>6k`^v;7uLjW`xWQriqk(TIp z()lv19W$3V)MeGw)deb^KFtAQMwW{WM61I8(6U6ous?0Plsq%`Fw^L>cWK&oKNSI8 zsKG(q#VuJZP%>W+t~);>8p9^emoK05va}c4aFIuS zi3torxkV)p!pFI_GwN5tJvA~qS_a7VhT=pMCq{=23vGT3#WNAf|*krJxK{0 zN4Hkp0NF7J8Kd`B-`qnSCoDP%HUHd9!WjbMsIhSl_NMeJ&6^*+ zm4PbRZ{$lka)5Fx@xr@E zKYC2gsu{~^WdPaXuOlit z;Og99em?3+D=f^y#{seot9$3olE4N3gGs9wRiLiu5zVqB7-ys~NI=B^VejHnh-H_9 z%(4`nrkD2Zkk&BtAEIeK3>;iJ zuI_C1pz%!sm<7!2 z?CjCNI=nA-=b@LHa{T9gHh6mI=Yw<4mNHUvWgm2WK|BCafD!1*QWYGsEdV0HdpUpO zNFs4Z3l#hl*)#U2sUETzRuW#V7xuM`Nh4DiInT4zMHFg09*vk8m>amswRJ(cEo6Q8 z(wruFlH*)n2)g_pwiaDGwza3Y=JlM|6>@^txB3AJygJGu%Rlrvb&}@iI`tff!>A(8 zXH_@qsS4n#LJ}#z5QIT)zmQ29i)1N+qn2b71lm6VgKPs5p%h@4y@J;u&2#kp(;>BL z55J{0X)fU+x6e>I^zigl`mSOeA$%Jub{wdnx?bpbIs$CgWO?POLeA&D0^r+24sr49 z!mpi=F(8DxGRv{7ZWyu2Osy?F%l%tcx@a!u*x{iFR>s{fnvdg}OIN%p@Z7(WzsJfd zLlLX@t^Vmc>ae1tFJXS?WsF=>e**lK3s@hDE{3;@XD*2B>k-ZusZ2cZ_UW^)c~N5nrS zv?|eM#V3$(SS5>z#uR`tdKKs<3akL=X~`yzT~0b_g3*&=Dpd6DNHt3;k}|!33uCll zm{(9D&Nz@iH;18p;T&?~v+2&;XWoYiG~QZvSldnyAIBkO_7$TvlLuvz104b$K}GG2 z8#idl{r7BHo{fjA;87+uX$F!>zEmJH1aE-LdmlKeZrOg9jh^03bfN6f1>A(>Zh(te zj{TFkh8OOL6+wbNS3PoUdgp5hh;9i@%Bnevf_f61x@lPr;c&9pvmicMxPCq?SO<*+ zKi?_92h;t4l95P^s8pd$GIB&#$AXWbGIMeofunU_RSTDkrFHHf5iQg8GLxwskqDRY zgm&>{YQKg3A3hg!Y@qo4j`;)?5RSGesa2>pj7G+BXbP!&$g!F!LGj0;pt=HgFl2W8 zw6o<~GkIE;0(-MjgfO9(_jR+!phKyBLbrUc{mSP#%Uwu|#m_k5?FUB;{V3LEG?WI}C6mCxFti21d0x07_+iD`4Jyx9@xb?lJ%Izvlt0Wh9O<7l~3=Q6a*K z-V(<}SWFQ^^_Mk7Alnd@R%}U(CRlxxyr-ZyaHC_O<&`e(5`EasL5bfURUE}0Q)UJa zOY@rXJ68tFm1tf~ubu5?>h?|e&!=uH+m`DaWeZBXH%^&y=VWKc(VRkKRB{h>HEip* z1RVA}g;a&HW|_h16VZ2eHAHkZdsSp1CiJT)SYJ!8Vq6-r#TG=)2$ATio1;?TXmq;>t%2J4UX!isD{Kw4C z+j2_Jrtn24m4)B9gU{t9;lmDpso)=Kg+TF9>AX3G9C$;>S$qZ>TPGI1Df8%!=Fz$^ z%2rU>z?(Sg=ZQ0Y9?|2IKEI#_RI#x(=pck{&%JmEnZ%i`yuxu!n6wZY@b2HTLRu8Z zmV~!otLSwQuX6PsqVreEPXUi!1^_E*l!YPh7o$b9^=W?w-*HaCkug5yb5Tm%-!A>M z)RjMhh7(C3N><234J+k$XFff6ns%z=suFRp^CZOy@?s{r4xHK`|G~Z9Il}om7VEH| zH$1^S!0+SAObz9#TFI?DnPFY)ugYgbAk+CsB_&XY$dm;XorK!Q`Gsq0<({LeBwnNC zaNp*vagklv zc#QqP6%ix}6yl4L1WQi@Y#Dc8fsW_(&-#ND{KQQxyXh1?@?iyo+<9;M91cX3~66Av_FY{2z2R6>`K*2q~#42y2c*HfB zt$!h~kgb?`b<1ysSP_mM97``QUixnK@q3w==HQQ=lJX{6BKgwy;o7Tlir4Io=Iw9m zU=14lFUOeebr0V;ezJb@Z7`|P7*b8!^RFIKw<@S=aNatQp>tXY>uB-6)8Egu0|EL( z*ti>nHkKHP#1ce63O%cfRf9r%?969H@!XkDaQG&`y@0GAJQ2~hABGtat2hd85+d@b zsOqhSk%EDcW|;b-dP1oQ!sm1{3Be$5_#VRTsm|Q_u&Y-kUP>g2KUzfCoU=r5k5BiR zl5lBJBtXNtlJ(b8z^=uVH`0yxkkCK#-!sDKgL1|0pctT8Wn}x60bU5epB|K*jpp&K zIdAk;D1?R3379)V7q(`1DLJgP|Hif1FHis7+MgZBcBaCbg_uOHEjScnf#cHX`EXS; z+}dQt!KH$hnmy~`RKWIH61`j?c$3m2Ow%z$V(LP-*DI~ce3i;r;0%#6$u&UnR!PL! z`fSecW(IdaS4QLB9t87}7OEn^C4$?fZGz-8lPm&*u?Crs+j1WF6q$0H8c0oNvnV}1 zTWXdxo$J;_2M{QI-8Bp(aW<5qc^!6H3+%sQ2H7IcC_JuBp_ehK|#?(n>dp#wG3 z^`GD1a&J027-O^ju0RrsZbEHl1dvKXFKE=6r|@duuzi~5WV5F@^$1&-2o5g-`3LO< zq+#C+dg#?9!7<~n-T_`;Y%N)B=iNp&Ng?Bd`oGVfgvyL{k4Uq$w-L9|b zW0|xxI7}>Xn}H%YRgj~@;jZK(aO+&!JJp%zeZNgm?b{FRj~%^xmWSyvPP90+KHKji zA4A!II~cB)Xd&5ZkOod;mo{f1gXH5xf`R@(ut|3v9NiLFRu;U76j!(zP6`2Wz*PlF zX)J|LXqNZbm50T-ts(Ee?t2(1ke`iTB-=EE3AA%76k46X=Hgm+WSX)Pm6zQ;5<4-2 zN5iy1&Q}DG^trI5cf2|O!V+4UMwxcpxyRwp?I9biA0SPEKDo(nrh6%mN}g$@of0&c zi73fG!C`f$GnM@3b2G(V^&63-ulUju;(m8 z3YG#xEm&I}O9_urz%q{=g;x~Up@;M_0DZbGNw$y+h&b*atL? z%l+<3=N4u(SxA8504p&GiW1+bI}6m~U}2n+QVU+h(BM7yE;%-`XuQ+;9Lbv=3i zjV^Qj;nNJU&S(-6lPg#yb}9GAZtV&A6f-k~W?pQW0Z^rZ6fmwwzM@~R(LhpP{@uN7 z6X~K8G_`=Y`}1*bUft2H%j3ZeWRPP{Ee!=jsJB4lj=iQ*nyD{>VK1b$nNKH&t!(X- zZBf?vGXxu4e*nELVsBa(pjQY6V^>4NUuYLl@ zOui!;k;*A5eE-hvUD~*a{U>l@7z>8qe@_;wVkCR4)qXmb>@(9wqxdr01CDOHiTl`@@RQuRS; zEhQQNYMr{GNnQC@IE7x8#&6!& z-{+f3k2DuV?rZt`rmkXO3>$ZNbwgF=v+ z?(Swsh(Kw_*jU>)p-l*obXa@eWA11L^0%qJfNc?^PoP5?2JkVI{$@$*bED9`4h1IX zEw?OPckX>oHoSDoq?1a^xIrn4lZjl~Ck5K2kRNpzbzK)^?@MuD?HURaIYoWHojhCc znn}d9+(rMZ=G0n>nAZC|I-#QcQwe8yI!YKqidwo+VY>h5JU6fZW7~Vw*nXiEoBPga zdZKFs*0Z!kdjw`@RDZgx;!ZlIQ{iCv=TCH?AU*l(%IpMnoVtw)QU0BVf`XvPp3Too zC*QYTvyR(7Ga=ry9BdVAjz`#7qT)pkAnZ0*O?ns+3kmuMKI)-PBD9uK*bcgRNoF-s z8$UEUI*SlKR>_=jwewTO$h8qrR=GJ@257VpOG=NI>a{@M?;0eRCR8Zf2hqA?G=7B^ zXO#3Y;PD9*nP)R~aBG!goommQn2a6Qu|%q!g)P0c*h4}q{Qc6d@9(ZI=xU!WZr`}6 zaWjrJCLh8*3yLm^JAMf3;OexsS0w6aTiicQj%OV$5~2ZPuKcS`Pj{xD%P|Iy(LnEP zPwHCt%9h#ejI}%(H$jD@mSd-fx~b_hkudQW5{!Ax@Fzx2bqo8Pyty!rQ*W^%0t4?R zt{u;pmO9H2rXfIt-V^McEP7IfoZ0}pLZPks-m1*9+H+LQhL|g>YUOb@;C$l!R8DP` z89uJFpn;p8pZB7`B4~sJc!L)G%>!s1ia}AF&qUe9u;oQ5T=b$X(;q%`2wP+1EU|&P zguts7*h2b~_l^}z%&lE15j0;V=kFrW|MKlkV-G3f3Nd6nUf2(Y#;-%@Q02c46|j~@ z^B`9m87Q+J1s^4J#JrsB+HJ%%KZG^Rm~!g?>me9uW*kmC-p!O+RgAGWh-ar!sl2wY-Yfu#le^?mIUo52#_JRDhApxI|BEuQlhtB z*pGXNZthD@kP)-_$aEmv&vmqR*y}|Os9Lt*o>$+#cPd#w?Ee$%%iF;-s=S$<2 zPDgPjiQN&70??E(!{#5I{3NJ;0LF80_lc;OD|QX`#pMqet|503P-oC-93~#m`(zUs z{CC~S;LlO|5E@D|UDlzT)(k~Io;kkh3>~g3w6-YV&#wuz%lAL3C}voZp$oGd&C@mI zUfT{`fU~ci_WJvgs5|4-*)V{pIPt8chohO3O)JS^?TIzh#}3X9&KVs*6uTH#9SyL7 z?`2bW69NxO2K$Ks+v5ZD2E+lvcX#Tnn7$}XM@jbb@KE$XN0lv~7+l-L`|y*`p33Kn z%IBAqXN`pT==@*}2m!Bvqy8g2xD6T&2c?<%QFI*Yp!XvUZ=ZFJWZ^hE9Rtp>7)7GE^r9g@rrO3Mlh)4eigID1&q@y}e}ljnqspLz`$>L26N8jkBE zRCI=_w@voaPDFdL@DMx3ftA;A#DLNb#4ziy!sfQ1|3Ir1SNg*W_yST82s{1*fku&= zf>Owag=tUKQd6n|d}L6}2XW9{S_yJWle*b+%iTE-B!8kJZyTbuYN*7x|rb43rLhM+owOTspYi69y|k0_*PntlLjD%uVv`z+Kw#1Ly~4!45#n{Xkp;Bf#jI|77LW*ZsM)XNsai zgE2@z=QfgdHjvIhDEP@?XE`0-4-Uw6;|^@c;3^+?3o+#n={!9&=#-H&Idhjzv*kV% z7>ZLOSc}SV_tsctw!@C50ZJo+fC6vfq^_x0fusRcB!R+s#J*w3P5C}esMJ_1;P{MR zGK&7B(q)+O0VAg%I`{@tNFa2&UjJ=A0BF9eGzk5tPf0g`5CRR1q$1`-yqN_yUmK%? zFHVl|v1Q|~c-_F6KXljD0u!W?b{g&dj^Y~KvLL_O3(`RpoXZga^Ra#fXss2fQQxJh zyNacJBYp>TeV!`O#x z=u`iSm2J9RalWqV3ygUJ#+u8+&NLC6fz%$(aAO=SNf1*&MBq-lb?BF=*G#D=#*{tpiR@-N1H=3Iy7|o z%d9`6#9pa*#WMFNLE6kyfb$f=W5JOSeL)heXAdR0V1EJ;l)znGV5Q1|pluB5;DdA5 zDF6Y6oi`c;y3&T6+IW!xxr?g%jpLr7#<&IJafP5=G~az;3OJDWgT3OucI<1i-*gi>EYTUeHPA10+_DodaxFHrUh+7Yqcq^Sy> zsj+(hvW-FL1CeGcngwZLCCtT0U_KGV%QmmdLOO#?APT>!wlSf(jGf-~*j~0NwCsrC zKKFe^VwHv}CI`bW^}|8-+fhyrw)-3?Mm`#x)uDu;%a8-y0=t}tQzJ3C>?H%irFFm( zIsPSAqBM*MS{dNM!MGG#m{SOTLm*|o0b?rsG~B##P-8C0L18F{90*_@z&u5W9Kfnq zAjuWOZ6;1ZLCv{hg0y1p;ylto z(f$j8K3D#`?Vu1%Z^s@R4d`fiqAPbllG2AqwUMEt!~=}}T$f*ma7nhc#MZ)`O1POV zXlH;A@CS*cqOPvadK}ts?*WnW1vV{y7?z=Ibkv$ID6L+`>o8Y143={$N=+8ihve9> z4_<|f0glisg!WvDF#h5+9|Nkg}{EHPTR*Z0Ut_@FQFfvwYPR2dp`$L~DDX$dYxJ;yXz&#DkLGCc@&YZ zzk=vWCG>_(M1^#xgHkP&xG`N3LZcJ=4pTn;n^R+N^5iK@|9gBeyx^-{G^@`eJO1bg zP_gG~S||og$QTH~n@HbTs34%SrJ?D7Fqma~i+D&}?jgemg~0&(`;*5sEBKYlRfPwT zee>}8L{-9z12#qGujn(|9yzQ01bEaivggP4@noF>uKU_N>Lr&&4qz$Y-Obd6j^8!U zhf)PdH{maslC!^E-eT||ZB8b*y#ewxsls0Ec^{^&9`1beRwBM2dy{f$jpV`;s(l*{ zsFN@nC>RRB6Trm!R?)n(^@G+b0obJ^EJzj9|HiJronl)t!#g??gEMQvhgvumuS1_f zhAH6Yif2X|`)up2SgHd+Gl%W};g(n7r~zd{90xo58z@0-<)J%uG(ciEh)7_Hkm`_m zzMk;HVT5RQC$_K+P?cBr^f>*^DUyPm!t$ejXO$0fms@*C`?dv}dy+Pae~_lU+gCv1 zrFEG=A?%#eTzZz7mHqD-5tDa6Tt5DryZX`$bN+omQ9rXhE1km$yvRwsR)J)MqS2k> z88Lpj32i59qD~T7x&1q5MR z-|vF`E71R+UW?@kd&w*J)IuX-n4kKBnT&V~VUW}mB=>|kQOraa+49}HmwT@!02rWA zqoJQsVe?!TrnL<1MdFw4%r+1;}}WedDMBP-1{6N~}>F(DI*fY*OFh7n-5z9(=#gQZs)W8;Mi?@wqKWjz6o z6fVusEyb58wP^z;vD~e2XdY_oH!eV`P zy_O4U`JGKfRUKh@$g#w8&qNOPcGMZDS`hHNz)}^ZNYT?>^N`p4NK88)Un52 zA9gD6A!|XIVocW)0MH`F&weWmMjyg-5|4k^JvaK|6fkyHUw!j>%wY99KbLW*;On54 zL)>QJb;05l?ZsKUP;YS(W-M2Y7#Q7%VO8k8fjFAa`R=_M`g7u9BLRKpn*YQr|Eg1* zFHFq@@#-u@12ksbEG-9yaX3tOTAq21N=GxO!N4_Un93&5o+$SIGo{Y*k%|BO6J?Ge z%b7i)xPrHQ>{7QtNs|3<+yrE*@M-Q$K<}0|+h`M%NuUw_@@3{++oWf)uAMnk`%W3O&_`#?=@38n>*LAIk~%FQB@{5-_P-gN0DE6L@~@f_r0 zN52b4Rn$1*%DWii1RGS?Zs@*Eo)Vd5yR2oU^pbtJ|KdwYeE6R~uNAl?xwHzkO?aAU z0Ve2Pegdc|7_y5IP=5`*1YDcnl`Caq?ltFY0!m)1wxe(Ou!$cXZc8IBel{VLXnU&J zLV0lLx4v1YRp`&V_ZkBhk}@^rv;g6MBygqf3LX#nwO>F0Mo`HzM+m2x9dygG3U9!Z z6eeWn`QN~mZ~>JC;S6B zY$|TrH>7|70@5Ow<;u=Lw*Z+LZIcHY*Qtka^3xQkTCbU-)GC{#Dh>rqZYz_NuZG zn&EE8#^s%tni#!bKR!<6!EhT%VD?otv_y~mC%2C)TS=z3=Uzm!PZtbgl4FH=(QrXW zp)Tb(H$SgNt18&R1i>cYKtWUhJhS^|?pn&0e89IXNE4J@f0bSmNp6=Fj&#B2ODCQE zqJc6MV_-~V;55KrX;V{X0%1IH9yEO*w?WB2-tS(Rm=IQhBLiGJFjh}As#ij%1RG|l zOnq|IAst2!{b#j}j4dva>!0E$p7W$c8g=xy@EfjR@xQ7$wJgi?4a9#?BPYQH4i-N- zrK{aEuT<#Lcbyv$+j`d6qR^Su>u@t?)kK zip9F4@)!z7dZj2)x-TV?!MQKSUzmj{OYWR({%(Rzf)*+-a~2fcr5H=hboNoD6glWx zy8_%0GO&*z3O~p8z#nXwcHo7DxxE7^EtbRbeOBt9XXh`)1pJ(4i?RASjB$;*^JsZF z@Q!a*k+%49GVJYOsDzXVn0xu7bH*ScCxbjIA3|yHN5Kx7G!qCEo#DlIe?QKk;ens5 zQc3T2$fCbuDcdJHzK7Z^H$QvdBz|Vk%xNZr64Q@D4JIaiegr@s|G(MonSc!Y`U;#V0ia%kZ!xu+NS>*Pv}c@C z_dd?C+8Gp*!&w=-fK#YQunY0N`$Kjl2HCSO%$LC?fv{fzdp7b(I&%6pZxSI>RPsPX z;QO}<*w=EH_O7FyRlr|>k>4Rd?EX=6a%iFKfICXdsmr0;?3Q(&ZRmmfNg?T|^HPo^ zB+EcDVB>3b8AcaRf{`v3Y>EbLQ@&54#ZKWDKV41*%T@p!^)Mm>jNfvs=AqxYBscn9 zgk^(`cqYo!!}gNsotMLKdl%0Lr%;oE*e4F-G+Sbj?u&TG^MQ})_wITw%(APLD+-O} zey#3rQpi^tB)H7RgwgWII;donq86W$&~w8sU8*1-va!ypWwu*urGad|UMI4D9jK^l zzoX=H1VcX&a^LXaMTN{q7x&ZHmatF3y@zO2M6Hy`AP4*d)C*q#%5t`X`dx|gidZMJ6lJ=R7C%g377V9PK zUCTtHbnL@&U&yAd{IPH5Ft4CmiEsTJjzMyJR=*PIY%W$lX87V~ za8!9|7|#C|q&8xY!)t1vbK!5d2wf%nP^70 zHnO#Ot$X&T6l>i0feiW`e9?Q2RZ<}ObDQ?7*NSd2>~WsNB*U*aw9pdLOjo_>$y z;)^bkS8VrUxO?)%Po7=nCrV{}8g;tLp`{saGtqowtf|Wix46Z6hp7E?^Ki#iI{%sr zxdd5h>0}hsay1I!p;{l@h&|>$ywBQ$yXr>>59SxFlqM1y^v;2`j}-Pq*&!#^v3ADM zg?=zLKjiWu%x%-i8guW@Kg11fYB0J^jtKu=)3oEdMNt|y8Wxa<}^A8 zLIj4b4TWbn_P~~U-=$t!&e3XbzvIZ=%WtmPqR#^DLQGW30dH@;7La6_L|F12XbLFD z2W593if}t77$K;kad6FQER2cv({4d#6?zQuBZ;i6H5bmjQTLZy2*_-Y^{~M{Ry(q? zy!D|0zr|$ev?cnh^Y{%H9(c`Ea%geru+Z2h(6zM92GzW!GOFvlcHMyZv2V(zs4>Y@P(8oGj+C z#Qe41cDcFQLv*j2n7u8-F1TERcd_A{)#}f8QtfO2oq8I_srSA~=7q`gs;12rCMY)wD>+(y~K z!G=oxU|;Ywnyxw63da%NRlR4L(x6IT+JNrG{K~T_#KyGVnDO6u`j_nm?UJqN;mAISMG{r++nSc`$&US$OsoPh-m@ceVRs`RprH?B^<)i< z)V1_=bd8KuWwkZ63^g8ey<4&fbr^Rp4BosrD=3ZTl1u*(SzqK zGXL*KKUi)byRLOr>zc2wznZSDu8x|np1!u4k%5kunvwQZe|^1c*RSjAXxN5t&E08meFLHmsjATqGr(B;Q^&f zuU>X#olB0I#)?)yT12W2Yl`Wx_THrGJnXe^rZW6_3c0e!LW-nMP7Ts~Q=~(@R+05k zz|GxxsdMsN{xSYexD8=&*5O-;{W6XZf!R-X( zc@o)ca7Y8jpezx}In1GtAq#H)Yr$ubJB^d4_GDg)!wNXf!lo#fRA6YoTzSkkC+850 zZ1$PCeYs;Azn#&hdw2iFR=EZrgtip``-;Sd!J;(tZO#)zEGXgUESz78efE2Vv!;?;1Q)cR0Xl#RRbu+`tvhtf>_Z{pb66A(a=FxYzV zJn5|n_L5dT{UUikq;u)e0xKm@Bu^BMSHBZd4XH9obgyGxpIWN~(IdFD5}zk!3q-nC z6lbYM;qRbq>!(N6qNcQ0Yr9FD939KGq6ru9{bBTH#HPki2Hr2s{}pT$r0_Z+?$)1U zDIYw#9`z-0~FTopp@&|yzboY4@2?QH+zxy3Xe_&#G8-*K{u0Tvij=U z7Zo?8^60OcO`y`zt1t2I!y3lQqRV!zj|sE&JvbGx7+fgjP9SMp)cn#|6hki*6@G5Pg{#r6hhs&(C&BvaW+t*4jbY$C(yz^xn5{I z)sQ;1RYjdV*#mSV6yoi+iV;aq&C6sLaygIQtRSTHTo=avl4azEdZ{`abjh&r!h5ko zQ-^lZ@iO0QNnffJ`7Bd!lv^E(SB(ZWcBGF8w5oZ>B$*_&;nil8HXNEkh%%z^LRz}H zJxe^)b8F8bN!I$G+5?&K5Lj+7Uh5r|s7K%%do>pS10Y+iADYP1IA)GTa2ie@C6PV_ zL{lD}{So#F&lvQMh!=m-ZC)zdZk4zpCcrQiycdk$4Wl|o)3hpMS$wz)?YI(M7-y1Y zMUR9?2#l-3T!VHU&iGht6(=``k{U^=eQ4o4I?v2)n=?4}SXQ}NgA+6`+=xdA-)+Z# zMfMFD$ml#b6L5^Pxotj2j87y!yjv8i@RBStf-vXSnhTc*M_m^hV9$Mbcs!aEUW)$m z(eznrAx2XET^>VBo?3#xadnrkG6rLyt`JUYd^q!9Uu28-h^uFWPz%i4=Gg|9GxwES zDr#ws> zvyBd&H4M>#rk47Fm0KK0&JzA2w8nBGBE1L-+wO6zcx1&`y>>m-w_*%4^57=hK7TSB>GtYsCTFMo+n3A*`3M(^ ziQIFi7@jkzU$;gnAk4C9dgpP3Pn3D8QBOK3_wMkeYdntYa`*MM3!?8^%mJ4;*YRDY z4e2emj%(hC8k*s#sYM;0!fW5g<1vl@cqCz09r7R-H~7m%ElLGrFjodQHOpGPy^y%> zcT4lzT{EAp6HUBY4=(l=Hui9bO;qlQ$$cr>B8hQVP)1Gdv>FWu%RzD)=rN1t4Kc!!~RS+XNoJwnxC-QdT@sRMtJ zrdc-ewT-4Fu}|y452?j}8I?Slk9#>fN!YqP{>iH!#>xky9An|FLnzBd*3n8xK@U~2 z5Ld8IjCi{sZbjR!_97$HdwkY<)(i|4Ho0urr^io8#V+yvj=1Bc{LoyR+#P zy=`Jg%dd)L1-tzUw5YG6YNY0hMzf{k$MA|H4>nk$)ef!jD2iXLQ_B{T^`&opY!KO#^{y>P@-7u}JK?usJkZ4pgn;~f z_%cg;Sp?yaVtpszm^!3a+M9Jrw_>ALZ=m5+;!G-=ainzT#hE%4+X(T?mJY&u$%Ylm zuKBXw6uHj3f>^l)joSy7(E7t2be}~#UwjJ7%YAvjJsZ!{B4*62(g{aocM!YviE&K%_&qc z%v>jX;ft!rW=?&a*1uqWg225E%jM|rRb+$I*Dhk@!1*`{q=|Gj41b?jW`vZW-^v3{?az8Y3IWs*FV_D?_k zi`$Iev8LV#U|y~U6(o7G#Ou)-W(gtqN}*4|kd?-o%o-iJ___5?5hsU!6{3b6x~zZ$ z6f8~(3t@{JDYXpDt$8F2lU&0%KH_;n`#VLAu48o=*CN+&LEtZ0`;^V}+?{?nf%AOd zzuqQ?p=h5Y_t3=~J^%%9r@~Uo9LK*BuU(KfJKg{?nVKT@+n*{Y;7)u+UAo}8ZYhnAJjN2> zYN4-R9HhAZQ(mz8O?A->&MklAROPnVAt3EZ%5MXHZVkOiY}|sRKV4Sh){(s__6UvvjbU^gK5zSJ&DtM~u)LsA!G`7#B_glivd9qoOZ8^B_xl9xdi2G@6`z`| z6e|u`XvL%uX7smm8QI?3I@Ml#+}}?Y-%dn{&@JNLs@M^S4DK1P0F-!bj>9T2(B5~9j*Jzx zWIiYOI6&)fm+kT~K^5Vx1{>edZd=mpgYV^$V&RqTopLX{9vR)6_->+p#xRGwXRIYx z_V%PRZ{E^(W?4n#`cz4x}tjU~!8EsLi&td%QR7&(0qCx)+iw#(;Q*^|YPVrkVq-)oD zt`Aha?J~&4OPTpDh^nN%AEGyJw9})Kh6$+elAay{o@&tI0-8}XNk;xIVs{DT-B-S< z_UF;l{%|Y33m|9qJ`#}4XvFUmgpbdS9i#cd_=zu3IAKK#{!j`2=HbU( z|AIEpwp*xt&o@3{UG4nGB39(<1z|(B44`0DhSU5$jmm!jl^zp}C^dDm{5=spTEYP_%*+~};Ge<<%XW(BkM<;IavOQC{>oyRj%z7?Dm6uPa8>*dX}dADaI4mo{ULHta+Tuwqc$D8N9~lJDg> zoa`G=xnSYo(XjiF)Iq8zMxMwxHL3nP$2YJteG!@>Z?jMVL#t%aj7q)m;kgD8 znO___o8`K<1uAF%y6j|NFS{UxH$KZQIXQ{^Jc1Sb8;aBYL$SuY?5|l`%Yuo_T>7>q zT4lh`#6p~2=juo?7(sObow7zhT)LS-B)m>JTE@~!mXhZ^u1%yY78XE~jG#zW#5P?2 z)z@B?3WL9>`p`ZIdWOEveS$5n*bo3h5udOd^u39Z>R{TdcMb|h__1lA^sWcOrJbiWt(mvHi3 z7Z=3}hU2>udzYuDZKm@)4BEGQ_yuMxPsw50L}msrBzRnuD)hD=8TPl(@-dW9p@&j0iLeviZQUcK7y zU<}Pi9&#rfs3Ar`4TPzd!h(+4$^@yP2jtlaygVnnH2czcsyAh3WE*-?9LAkaN6Xb? z7-NyY88>oCY-DfiNCr^RK`+VNTOG?sDnYFFIIeKz3`d1jmb-8tno352mTsO(Pq?{@ zTEplN1D9@#=J@*)k9gE25?xtTZ_ysP3Dj?Mk%3Qx>7MF%fb@|Q>K=(ZdU6x;N4{TO zH<4_RsYFv!1TCuu0INa}cAtyB{z-0OP)!rl?aypIzF|wn3SwA&iI@D&N(EWZXlX;v zTkY`wdeELM`0YU&HW{w}W%bQ^^V6%QOJz72&Z?xSpabj~)^h!I4JXE$1*>S;?8if1 zzdB3Lzg>I%fT8Sj6ZolzQ7ZpF!5!kqlD&yok4tVA6>^eGzV zX~|fjfHLnGMdD8&Ka|lvqex|l<}@(g1wJ5>PV{jk;AE)YHR#^~!PW=TVIc`l?-{0V zzww;m4O=w@1q2}_TWja%+W#RBjM6%)W*#p=EFN-#A?b~LMQhdJyOz53OG0O-jdyHR zE4cvnbK7+GuRGM|B@GADHx)ayptA4Q>blp)8RtK{%GHngeX)qEwSpA7Ndq&sR_9CZ z(oKTmEbk(&yOx~3|50j9oOkp{6ih^ZfPI{zVLSRu>;&W$m;1_LuOFslVE*XH7%2Yr zJ8$jm6&r&sefvGSu{?O&CSdum5O%TeBVkMEclMeAqOqb=yK=2-kSmGgAy|0Y;z|X% z2}mq)yq<;#u~qCVo9)UhQUQd&$?e>vZF7LlVBD|J;7dl>A1%m50Z%mO6{wx#Q|X2= zew0aTcBM?qxL&N|A?>_eI`L?;ad5?8&V{ehVg^wE<-p&eA@W+Sau}U4y>(oE(^X(R zA^$h7=k)5Ve5D?2c5cjgXAyq>G&_G3J@pv1tBQ2|Rvsqxke-^o1Q=|Qtg1ky9ZQ(j zDeDWb7Bw0Uv-W@5X7TUD!uOtzeA>!6ZSBua+uINiD~_#23_NS1DFqR^roz2nsOBt` zxo`_5!x~|(H@6za0f$3$=6&>c`EZor7Rh1(BpGgb8I;wn>uCXBvc7VdcWV-o%8wyY z^T`H7`iSCvUZXN6f7WWm|++HRCI_A?y_aC=^M?Q&|`5AApB(XL%} zIkeUmWWa%(3&V!?@Uv^U?0Ih?Ou)bG!3cSj&8p5q1MlBQ6Dbq>v6GckK11XiDKt(n zF3nG?SeKpuL`c?Z_(KeCrSJi_%c0sc45QAii6n?=T&RmYDEZ}MJQ4#pz1eV!QwioX zrv%w-dl?L9-kWG?q#C!}=yAB|zatT%~m8#Q{%iCdcU<4v40xQ zzjPnqxlce{@`nap2ID=WlKsNyF@YRaSULoRhq6x*$}{j~?|F4Ab3OxnO6l z_Vo2>Ad`*uO&u>4f_9|l|D zVU7+gU10_?d_&%X)V6D)-8Qw~<<#S`Uvt;;{C%%{T{^qWQ6-r8sgM5Ky9pT1F8T-( zU3+%WXT45;=nv<(=BOdx5AxWT7ZZh}s2*rKdS#*y*N`WeFiDM?HXHx$Q{F`3v0pxF z_6gp2#+-}QSw76W^K|^k#OplMBW&Y>#?4nW%3nxE1a5`%8q|?qR&NAUuY%l{%aPCK zGD`>!@ebEFLl;Oiu^*QF_W`r-Trt@bGd{Tq@A;dX9EcVP@6!~<#CTXOpmrSQY12(5 zg4j!|Wf}C^QBXnmJCIhwqP`At-u~<@2ZnT9KaebUW}!WWbvxFtY1Fw&wkJ+3xE+Hj zyS3FNILU9x*$0A&T&(Ue{`+Q)qOKD>hR4e_^ zlnyGf%~K>x6M5+>X{lQ~6a!9npMcF|@Om3@%s5j!| zDWo}u+*I80Xj~o;EUOH=qv}nGg=I`lY(af0nlOmicH@)a{NDPuOvU<|aT*+>F1y5< zB%KYI`Xg9T?yF>t(Y0vlUx$3+^W-*$&&++aeH(CKp`}SM!A7+CM#+yE^K+WlT#)U7 z3MKSbXJHanV0#MT z*x7%}dN|Lx_Vp9ihEbbdAX}q! zEY?Th-lIU^Bw67Pt8R$XPGj+zprCdhufb z5ToL<;&yJc^WiNY*)8ilNB@+ZaWTacjH@o6GuAz0QMM{Goi@&sG|WXx zDwnhJaUa@?3e`BmIr$lAT#DnSz`ko8?#$%^=n8C3o)nYQ)R@d^l{~)_1R=J^dY zo#ClEYsp3%Hw3u?Tf$Flinc-3*29aB1Z_hb^u-+zSFA#*roiqMERXQ1RKup6VQ({a zVNI*kiJBZ@aZzUwC=c`#%f*~VI-_G3l>GXb_Y5s>JUmb=(Yxfe6JpvdG_G0{6?Nlr z!jy9?BG-{E#R%K6;PX{-Jj=Tvin~N($`9nKChb5gMSzBk()asXx^jUk)}bo7L1j&J z&c?qou97nO09XAAKFYDdLGuFpO!(3quzF~G??h2hFrz5X;)-Q@e!;HG<&8gw1~n}9 zmI)nu;&-8>il!@G@*(~#&I)h8%|CT6_zF)l$;R9m(X)$x1X{i@DWt_oQYJr0c>V(f zZa?w_Zq)Ab4cn14)v6{gWQn47)rwrba4w%j>yJkM1Eeay;Llz*8-Q3reQw?Fd&_|Jz)fLP^zChs3>W#%CtpP zh?yN;-(O8hIWt_u&zyv@?p6!I&qU zE=@arz zXdpWVM-dfnLlmX4WQL3t=hbWJdNIku8-n&pNjZC8KQoSR8LX1(fAlpr2>>W+}J}(K*g1>j+3C`CM%TUy6-VK<-vkq|T|~fZ8^aNkU4a)mx`O zCQt`9by?o=DuYH}<~f_|bfK$q?m}7(swTnHDtjCAIqt<&AbGe~=2s7B`gk|olNn@} zoDeALAV2$CZB_2^oVtg#r21c zM=0^B%2n@b9(a=i@6)Tdp5@N1<2{c@ko-2ms&!DW>aOn;5V}=&5ls2j5l z{#MS}QIO43x;&--OQ+eZg|ge=QJd$uMg?$yj!P+70_>uFEW7VoJ9#y2LYpJm8uYox zGg@MbHxFRccI*NQkQMAzV<5A&bB*Q8zW56KvheBtw*Pa9@nD=cM^Cp#>2Sh-W!Fw1BT%lv4%UU5PNXd=14A*D^% zPYX1Snew3oB4^p=dbn05T2H%;KeaaOt!9VZ(5gNm^I;zZAkLvd^PsZIXse|O)kmJi zNmyc(%kL^vqV5Y{4M-De=C=*nhQtXdQ#>BAt1vmRy59=899JZ{Owr`+JR4)AhlvV# zRt3;&@9LfqHD^~_2rqsAn{X8H~Z1v~i2~PNtblXRIMr#Wa z#L6tqTe9n~%(c3N!YJR^XK;fU{Dorob_))Cn;}KX`c4{`g=M#mrIRPhV`1uZEbv87 zlW&Uq)<8?nrm=xoABf$B49vgFeC}zpn9Vii=MU1yylA9)an};|jfSL~{(Nrg<@y3* z^MUGokUW0bhkP5j_`VHNK=s$ZTAK_&o@%5k5a=1M658C_jz3ArqqbPIx-YQE_WT9n z5k2$wT-8*+MCAJB&@m~_UkAeg{R~q5Z#QC35x?!a2U2@z5KhRv)wkNfFT2M^f{!QP z=jqyi#`gz0sVogzD#Ue-Zt{E-yMpumNHM&f$KmQqvq3?-EgdSj-?xKKpnj~cbNLA8cW zW;+BVabCQq#KyBK^5Da@`DF0{<(B)u-95$Xi#A(N-Hn5G864XCzO`Osk?pTGp4W13 z`aIJpcN)UOBPnjg2LT8I^NzKU{pq`g4w_aiCH>HSvKAl8jux)$Pk-FN#ZUDXx|i}T z@ob!PGF~H>-PMZ=1*?~g)HfJqPg{a?@$LIuGG>Vpf91Jy^`@xe?p@~LTKL3eM|QEG zs@dyHHe;bQO6CIOuw$qP`p>TgVzM^c5SI0aVGyFXFwuSvV37z2VwGJ8Dy(ajGTVP{ z+;*Esm1DnPAAujIdi0i<>4pf8G;M0KAdEcjl{RGmfw+g^fDp<1$Aj3R3C?py^U4p5 z8#<)Snd6$homQlXm+9!$KYk*1p>ops99MGq4(W;$EC$F1gU=5ZK8iM%3t6!*a(}6 z(km5Fx&K27s{v`OSFU)m^4Mz>=X+9abh`Uacsl-Z1B8tWe%OAuymV;KHTMRWnL@l} zx8Y&tb>8>W?mK^&-D=7#3tZ8&=QO?Q+Lok5j{v~MnyKTEH%6U_gM3nHTt4R`fp-o} zd#tA$Vl5Vsl1nleoelP{7GU;3;bM2Sd3d};9tiiIi(R$!J4{JQd1!reEbGlT31IUMPd z8S;SpK>UP+NAf#3EV}R7hElW6O}$9j0SfUlc30CPQF32d4^Y+) z2^^Q*AV$2>bUX!h3E5FQ)^hnVy!dKjVrb@f<>EH6)_Es{gg&Rzjd`6ux{NlfOj_k& z+MtrIA$uy3bp@{Whp=+8BM@&%5?3w91>Uq$;8s@=uQ8m;mG# zS6BEdRO&D3bzl9t(W@k!^=p@=z@B?3-!1sS$s4RC`?}2l@AZ*c-m*K7bgbA z7=$0_OjB>&MQFhhj{hQeVdCajcztTzy8r%zmNKn%s8~*i4p38>O*zK~dA2rq@EA z4b|r{GbgirCmDLILQQO?&|h2fvhQpU+D!AWvU;v`?3gl}cRoA|N~1CzUvV1xUvZVR zCx)t1^in^9ymMWPfcw6b9<(n~VwudE#uPLz->k=cgX1xCgK9Zyv(dUa<-VUPU+|>X zd9lu52oEPDu%!^Q#3f%u?jiQGD4%P7MUyg0@@t5+4d>DlRAN?A|76g_zUo|$FX16G z%jF2zcAH$zC;jjBzr>JRm~tgP&5TLVp9welajw2V{xK_|l$71Xj=e`gOBGa{sNqCy z@Faj_0EA^j>{%nt84Ik~Z1**RU5#mfPif{_Wabs%9_wz~5D8|T%q-P_P$O*K=`(0>FJ^vRO;5HU2vS;<*7_}^dkOnEkCgdl);YsPbyqGf34K8(+=%#{kPq03kFxFq zERjDgcD!lGIcSo`PAsH3uf**Ed$D;HGR+Fb_jeis>Y$UtEr#kx`x?LfXbPPIY+b`I zhQcBQBDeGxr6HOUu$^7D;;)m|pV=BM?=9u-0z5?vDm>7~zrx4uRBrTFK>pcI8k${( z4Q)knrIq}767U{uVxrHz35SBfmV3ZQ31-noMhL$0z9Egb_3^8(@Ktloum7$_*Mg;%kJAy!d?-NKngl?qDC_2ljYOpw%agOBygd5FYKkHpW}UM_gGkwsTy^FAqimX7J#?rH4V z1XrIc67e8Ozdf7c_LppYXY@g%ckkW#-Q9E|j>l2$hD6<@UQV zk1*NqsIe~>JSa()<}BYUDRG|jmHq|G_$ZK~pf2?i!&08SFvhR^W)A4%W3yM=s~j7~ z-zyRU#0oY|SlWNrI&@(tlfwc%9SS}Smr}`56?^8g8UpNf^K$^GIt$M{2kQ}JpAA0G zzvIw6Qpj4e@+sT9%ro4~$&WuA$IO@Z{?)sD#1GfN969xokKlPmut}x}ByXINDpq9! zKMWG^$S+d)Q+$lu5Za!=Df914wH_1s!6Zf{TJ?V~F~TiFK^{W#B?`c?#2{UZKQbeg z6AFab*N>L~{$I@c;oj!reG|4Rp_bj!gXI$eB?|aK)+8$W3!ce()ac#}RkhvoESXN2 zV2J?`e_c1q0VYk(qeoXFt-(sv#D^maPl?LCCGVDKa=-y8b zCtHVtPRzE$MS${F%M_ww&8TL_0AC+><u=t|iF(hOYOl z35{j^6j}hJ;4Tz2BcaMm5x~ALUXeUV5LRY&V0#LkwrCvs!^-62MiqwYC;A$n3(tD| z{*RORsb*;pd|STaH$tydLQdzre3vXY+by#h2UpjrQ9>!Z6QUzI@=Sje#jyP!nqc?h zVX4@DD4nG{AK()hbN>wrU+|xF=4Im~6>~xhhXSj7uo=MAT|4avX~WdB!`H1I6^afG zX&!&!OAocF(W$N-)KNW%mh5d5&CLH)$BxQeJx)>hr)`&x*S=}Ku28hV*{#I+JDJU@ zeK6)fs&T;tD$nfl-FFljhZDZznCOZox@pj=aXXICo)I8CMVB5`l%4RCN#=4UZNvEfz$n`b8k~;7h1>qxWrx%7v zE_u74^aZNV16oGPVQUzEyrFo`GaRpQ_R*~dfO^le9UEJfyA+|rwrJ<$u4Z?2YADy@ z)oNMLJ>NK{sPtXy=qjkQ{ue37=bwm5<1|<05W~psvHA|oD#JBqybCI>;BBWSUc;lL z&2G34flpFW#F#?I*_ah&hF|E%(L=8^bi(k0k2-^bEL(^vhNsbE&LHYDOH>w=tIh(H zR~p>!yz$hjo5d}nx%V4GWVR~Igc4Ht8}K29{U zzbZR_$9NGp_Y@D%fiJ<6#MfE>Sw;Tnt?nmCD_wfPwampTA>poao6hWF`KTuMCbm{b zC{*ewNX|UZNS^H9g&q4W>j*162Ee;zw!pM+LK|@V^OFI^q7jgX_L!s+)e3#N@hvFN z^Xe?BgAg-4{t(dMF9dr=A*)Sv0DO) zYU^%f)`4e#yGd-OmOqt#!>wP=vhD}U*Z(hd`;ignT0-Y;oJChq)38H+|3>8&32 zN7idFdXds4DS@rVXTa_z(h}>yOglChZ?Fs-sLXJ+YzhthFk)NXG^0NMd$4q6vEZ~x z??$|&KJqXhV>t;hj3!OMB{$+}d-^S({uT@v9`W>6?QRa5jIaki2cBqlrHb|qvc~6F zBs@@2dM$ov_!HezF!I9G*$K0(@uF!@#$##33KjgUkfwMMG@1;=MMpdh4*jB$hK%Nq z?ogJd7I}iE=3+vSGU4O>kKWOAGUK3Q33bB*%G=9xBS4EqA%A=`^)1m(T;|-HagDy@)-YJ-=2iP-g=_KwMnnGl zRVS9W(4Ug`z=r?mRn=T7)=$A(BEM=>(Cw9-31?;t2j=YNMsK%8J)hXkxl104z2#i zN)Svu!r5-tKs5;Dy%ooA7itk<{Pis+(F!k^n4mu^L< zTKn(iQeBdEH^`MqGrtJnHdvYCsWO8jVcw+Udu(|Q9Ny6w?|2M8kG-sR>M*CHWFpdW zG6@<27eYSPJzns6xSQGz8MzBUwdCqUPx2n}a^T%YPP-GW{a7uQa@jZd)A6BSMFhye z^P!tCNtx$bAb&qHqkX&^pNc2Dl}Nd7ywB|V9o%PzNiA7>nX>~ z+(%ZNm52Pd`N`)J<7u6Ik@6e)w;FxdVb9yKg<_NA)r!Cw(K4LpD>4w5Mw8JFsgh}V z)Ci`u_)cLucI&dJ8N?fB3{aWen$EYtn2^}yzC-v%z=+ek)WZp^rc6Cnx?tlS6+LuZCaglTEBPkxE$VDD}ObMBJ@IKF$74|IAXUt1Z z{gV_nK5FsyZ0IDQdrwlI=5?@qL6vmOuz&asu#6Tb=<$xtK;hR zg*R5=7!sPyrF-qi{8#cjLOBTfUk#teA6oGo1l(H#gb)1BAp7@0w#HT+?o~4T#RHgLMgm-_H3sHXlh;eCaa8`-3&%J-ayJ0Z5 ziliM>goFamCU?s|?xy-mo2knM))ghe1_jRG%$Rz>NY1HaPaj)e)?N}gsCC?DyZ=5Y zx1W8V{3V&4=VZo23{GR6tN=z@F#t;-w5F+asy;KA;`6Kts5CymdiY?x&LY$Rb-%d3 z^Ue*G4Mf)6!*HgL-*;U0zW6P5Th~D>pcO74nlR*-wDd!nXP)?5g(a<{eIXY{#EZG0^T6iEYDo};rkL?$*4WxR% zhWEh@tv+>qpOH3T9AAG%XEk`_w-VLV1WG)$U4Lc}j=G)u{;=tLE6u21rhkvPY^ngh zZ0U{VlLO`7)`AzBG1xwwnCgQT#yK%B9ldZvryqIzpzPT?z;p(tBTMGq-ev+-NA|I|L|^j<=h6*1tW-+RJre0J({D~eWZrgr2v`x=Hr0t)AE;< zOrQ9ek#N~jl(xY5J-?2rspz9-jj#)@*G9Qg(y>q8;0AJWkF-MAv{V#7;f^ZAwaDam zq|lC#%WSH^qk;+keF|dQ^}VPCkZD9)sy_Y5?YJUZb-nE4YIyM-UOdT}KAhhrfr}iE zPrM@(kW180M-0gG&FGaXYXUiwjWQAMd5hApPssVrGSh?t6+*84i!c_gWra^TnfH5) zJO4aYhc5_H24_z=l58F^NaX_PZSKJx$@neMcxAmUb0VyGr=P=Iof{kJRxI{&2V%bs zy~A{BH}uTqh;JandaDj4+!-^9Qw7E@>lV< zeZLd0mnZM2-b0~8oyRFn4{~6y9n`ig!G%|W%#zYO>QU;7G0Bn>RQ4HA>&iT7X>aUL z{);GzvS5R8$L=oBmbCvo4CEa#oi>}o}P@MnKn&G0{X(y#iKGel#HGrJO&O&r`96<9@cDWNp!$KvG^ta)fz@f9H-I#y+_@y_PQEH~ z`I6)T4zSi@Mhv=26mQ2u>rKAHs;5 zseau@`z}dYUbX_vBd49bZz{Jp7|Hcb?TlnmnjI|O@c-mb6?{3c+s_c2Cf z4y%0^x3DFiTQbU_qUFH{ux~Tldh%eIYZD1rp*pAnO!Xb`Ki9|iMhKSFdy}jol6b8Y z(cb06x~CPkFnVlriusjKe&Wh?V8t@P14K&*9t$;~)Ma;o_Zb&sdNkJ^^}H4Z##&@v!1=>b?U z@~JY6z56IdR>)Q?mf!TEeTS$O{>}0n()K@(thBZ1jr;)Kiz3@>S1ffpG0A?olPan) zHr@z7c~=R++}}!u&JiZohjK^i^?RDv+#o(S}kb_dwK@d3YAp9 z%c9rPoM#ZxKt->rA(CZGVu!;lOIcHm=>fuxY!xAxgdutkm%_FYpEgJT zsdA&OpE_CP*>ijQvem9!S>=_AxJmB$TL0vyJ5OuJLyuFa zEoY7@HFD~-xcl|%mjEIkv0aG{eR|&bWVVdVOBf%P!ZQZE+SIF~$M!sWyQ2OXAIaDZ zy?g@V`%c4g=Xaz21rTDt@x+|6bNT8fUv!<*F7RiH1}@ug%RBjdEvS9?bv+c036&yHJNE@uWq@#)GR z%H8h}8%bhmxZU!^xbPHivf&c6x`Bc5VT4`%twz~W=ltYc5!{jSHzwNjNS5e9I5LepG)QNKzT~gK|*&+ z(um@M`V|YK#5kZ&r-8kwO2W1#uKGNpYi+V&Bz7_T7eCUZaPQGPu9~S~5dhuYicj}u;3_TZZ}d`woiUzhDE6)Z_OKnV{qCbaFBQtkhsmhv6L{gl z8MJXa@vms{)g>(k7Wdk3rSld};0@d!l2?Wdh37Y|a{YkB*>PfsoX`}8x7GRAt~8_EJn$uJ{j;3fDq@AnnG znuid)rT})6fJ%SEhWEPvbPZXc8>sO;KwX)Zbn?9eYh?a;lG%@Kmmntssr``fHt*gZ zMCya+{C{6V9@r_IrQeTB>aB#eH!S0Zm|sI(xL37#kKLnnM}Am) z0f0JBz`}r(CGx-1U*>Q(W)Ug>eMGpcsCv*!N2l4B>?8CF_M+JKP1NWX5cz*WNy8hs ze8Hn`@dd#=8@~bCxf5&;ZDg_QYujNQZ{d#-et%!LSX}=aO6na$B5(j_>9?^mvAqww zMi%S;fa3hWA`jp$uBxxk;+JOnVI7kn)`tKq ztV}go2qTLXx9mg2coUKQ5w7>*4ibf5P$OOF-t)9uo-x|9(AOXh;eIUMPbKdBjJ?gW zynh=J{{SNRv2Hnnav=x0^R$?Lr7gV=yWa~)@V`am{|*UlX!Uaf5Oeo8B>7?e2mlNh zftldFv)*UKK8%7q0!LeF3ia)}oiEpL9zs4(2?)|NYXiaZ+| z7-gPj$sI~lJMRAo2Xm% zuSftcqwAL%#}NuZNc>#94;z5|u)YKU>cW8#z9--df&bmH#jL|46p#Oe8&P%^7Z$9v z5WuLlwS<{XP+|$G7pT!b!+8MDkXK;d!(;FGbDS{5CZ~i^(i`!O=sVH*@9O@GS%2|8 z-tpbu_73lR{67EHgc0A|{U1>=&)29s_BNxFb@pZTYr6MhVb{7OKde6ifO6~azt<;D zNl1|L2A(5}dIL3-k5OO#X;!A>v=9Dy*}dA0VrRcGF5>1zFc07rc@MyEtf{R1wqP+2 zz+Ct_#=VEtCc6*27SB+)bOpKjUw@(O{!QGh&!xmKaruet!+4urSLBEFDF86qFm1o4 zRv`2QN<_eJtPLo#26O>8=;U==3F>MJfe#BALX=peT;uHP?u#w!1wQfbp*Y_LY1wGa z2lUVFSexYAa4vs{^(p{{A$bAAlJ|NnFJLz{9A|Df{{>18-9#?rIW(*6yML(rYM#{# z4N9=yNVyvDUH$tgnR@}v>g*Fg)u$h`@+qso>BtZ3UjU#kFA#Yo zl)=A(uKh(+PW?;wT5Lw9KKH)1Pk+N(eIFZ101Txef&ZG1SfbD;y?<@TJb_RMtjFLY z>R&#KLW4JOLs$L5EKLl`V5GE!?0sb2e@3qUkH{0dOFFBcB7Q09ORPR@VDbaZEdODt z|6S`7vC6e@JGA_%>b6+5o8KiC+xENXtj_-+ZW{5ksIu=QswFspD~f4iFb<#ePf_0G z4kEgZqP&V5IAvwKv46Q0YGeCJt$u8OLtrBdfFVYFe>+8fNKZ=@_KC;#Lt*gCWA`EJ zZ({H!3J*@;>frsv;a1EU_{mmF=siTFzlq%Z%Q({C$65Q7o1e1oeb(MckP-oZo!j1U z*bD*yb>4u#om)bpr#yq0Fjx_d)%nk(+<-sy^;ma&KME79f`4wUs^?Z3KH03I(JcLa zL~?(K^lcpJEw)dU<)$os&gz%C`kT(```9c3U`Tlbwm(D+QUXx&nk{}=?>q_#jw3-h z*=^4wF$nADLoa0`AhfRGxQ2&_+_#X6f34fTi<>&l=0zwe%qe-Tmh_t{)=yz0CINGZ zB?U{8gti@9?0>acZ`;u$@=yt8O-_%y$$7T}%NE3gC{+m}T z1T(>QOb~246a(wawot(Y!A98GW6F=BVxt4yYyQBSoqxDt%dvb0k#)H3pL=XSmJsvF z{-Qe{e}IyWTD*swhV4#w>>-Zup=+P&htCnaB%#+A+iyAI8#bc=7<>yK?oUGqQu`_5 z$Bx-z39#F^sk8RrhSb^w8wXLSV2gzez8KihUF)6jN9M)62S~fqRt;&{b{k^sliqjf zZFzv3z<6({dqOcv8Q?Q-~e?XCMfnRxR8(nB*H<#XsZ4;B2 zyYCNA_UF%!jYNbx^47e!l=%KS+>Y&UI&5|UFn>%E7TEh^#3gY&B@C%06o`UOE<8_vJ0waf!w%yl^tWrsZ@*LW-rRSG|0Vp7v2%{? zZ-07hH32Y8QwaQR=qL4Z=6$i_^lZo0;dX4l4>@w=tm-6U0A&JD@>{9@+;?tU3R_hG z43h|fF9@Xs_P@99eX0F$9V7ju<(&sJoS>+mG=sTAB-Q53A?Qc13bpbHsguvgA zeJ=D0e2<{Sg4eu{iZzM-)G<4UzGJ1NOMelx)NSv3U-+Kbf9N}hEsrJuqnK0(Vj@6d zJt^sjSpHH^pp-y0o`CZy{7arJqVA z*rZ-T$!n?qQbO`Z`~;c+%P}Y_DfOg3FHVm={mPvvR>a1 zK@)&-OyU*T`$G}%zpsYyx$TnuQq+*F&pHpa>NTWK9cxIS2|zt^UV$Ae$rbqT%?ZMg rZ3>Q;B6luBwrdDqvY-2p4L$h(o(IA$jV9zn00000NkvXXu0mjf$;^e3 delta 34252 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 Date: Tue, 30 Jul 2019 19:28:02 +0900 Subject: [PATCH 2108/5608] Add maximum height to skin dropdown --- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 5d7542ca2b..35be930a2e 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -107,6 +107,8 @@ namespace osu.Game.Overlays.Settings.Sections private class SkinDropdownControl : DropdownControl { protected override string GenerateItemText(SkinInfo item) => item.ToString(); + + protected override DropdownMenu CreateMenu() => base.CreateMenu().With(m => m.MaxHeight = 200); } } } From e6e315e07bd952625a01bdd9c1578224d41d3dd0 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 30 Jul 2019 13:29:41 +0300 Subject: [PATCH 2109/5608] Expose current break index --- .../Visual/Gameplay/TestSceneBreakOverlay.cs | 2 ++ osu.Game/Screens/Play/BreakOverlay.cs | 17 +++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs index ed5861b47d..bb89c85e93 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs @@ -147,6 +147,8 @@ namespace osu.Game.Tests.Visual.Gameplay private readonly ManualClock manualClock; private IFrameBasedClock originalClock; + public new int CurrentBreakIndex => base.CurrentBreakIndex; + public double ManualClockTime { get => manualClock.CurrentTime; diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index e3e4014eb3..93267e5f2a 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Play // reset index in case the new breaks list is smaller than last one isBreakTime.Value = false; - currentBreakIndex = 0; + CurrentBreakIndex = 0; initializeBreaks(); } @@ -47,7 +47,8 @@ namespace osu.Game.Screens.Play ///

public IBindable IsBreakTime => isBreakTime; - private int currentBreakIndex; + protected int CurrentBreakIndex; + private readonly BindableBool isBreakTime = new BindableBool(); private readonly Container remainingTimeAdjustmentBox; @@ -137,21 +138,21 @@ namespace osu.Game.Screens.Play var time = Clock.CurrentTime; - if (time > breaks[currentBreakIndex].EndTime) + if (time > breaks[CurrentBreakIndex].EndTime) { - while (time > breaks[currentBreakIndex].EndTime && currentBreakIndex < breaks.Count - 1) - currentBreakIndex++; + while (time > breaks[CurrentBreakIndex].EndTime && CurrentBreakIndex < breaks.Count - 1) + CurrentBreakIndex++; } else { - while (time < breaks[currentBreakIndex].StartTime && currentBreakIndex > 0) - currentBreakIndex--; + while (time < breaks[CurrentBreakIndex].StartTime && CurrentBreakIndex > 0) + CurrentBreakIndex--; } // This ensures that IsBreakTime is generally consistent with the overlay's transforms during a break. // If the current break doesn't have effects, IsBreakTime should be false. // We also assume that the overlay's fade out transform is "not break time". - var currentBreak = breaks[currentBreakIndex]; + var currentBreak = breaks[CurrentBreakIndex]; isBreakTime.Value = currentBreak.HasEffect && time >= currentBreak.StartTime && time <= currentBreak.EndTime - fade_duration; } From f2ab259c21aefc7900f983b1cffc087229f0a349 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 30 Jul 2019 13:30:26 +0300 Subject: [PATCH 2110/5608] Add an assert if current break index has skipped a break --- osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs index bb89c85e93..879e15c548 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs @@ -87,7 +87,12 @@ namespace osu.Game.Tests.Visual.Gameplay setClock(true); loadBreaksStep("multiple breaks", testBreaks); - addBreakSeeks(testBreaks.Last(), false); + seekAndAssertBreak("seek to break start", testBreaks[1].StartTime, true); + AddAssert("is skipped to break #2", () => breakOverlay.CurrentBreakIndex == 1); + + seekAndAssertBreak("seek to break middle", testBreaks[1].StartTime + testBreaks[1].Duration / 2, true); + seekAndAssertBreak("seek to break end", testBreaks[1].EndTime, false); + seekAndAssertBreak("seek to break after end", testBreaks[1].EndTime + 500, false); } private void addShowBreakStep(double seconds) From 333049e71220dedc33bda9ec84e02b6a506fd38e Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Tue, 30 Jul 2019 19:32:53 +0800 Subject: [PATCH 2111/5608] Fix ITMS-90737 --- osu.iOS/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index 0775d1522d..4fbc67e27b 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -14,6 +14,8 @@ 0.1.0 LSRequiresIPhoneOS + LSSupportsOpeningDocumentsInPlace + MinimumOSVersion 10.0 UIDeviceFamily From 6ded53b3a91285e8f968c2a1772af347e16841f9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 21:53:28 +0900 Subject: [PATCH 2112/5608] Reorder class --- .../SkinnableTestScene.cs | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs b/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs index ba31f15b3c..a2c058193b 100644 --- a/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs +++ b/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs @@ -16,30 +16,15 @@ namespace osu.Game.Rulesets.Osu.Tests { public abstract class SkinnableTestScene : OsuGridTestScene { - private static Skin getSkinFromResources(SkinManager skins, string name) - { - using (var storage = new DllResourceStore("osu.Game.Rulesets.Osu.Tests.dll")) - { - var tempName = Path.GetTempFileName(); - - File.Delete(tempName); - Directory.CreateDirectory(tempName); - - var files = storage.GetAvailableResources().Where(f => f.StartsWith($"Resources/{name}")); - - foreach (var file in files) - using (var stream = storage.GetStream(file)) - using (var newFile = File.Create(Path.Combine(tempName, Path.GetFileName(file)))) - stream.CopyTo(newFile); - - return skins.GetSkin(skins.Import(tempName).Result); - } - } - private Skin metricsSkin; private Skin defaultSkin; private Skin specialSkin; + protected SkinnableTestScene() + : base(2, 2) + { + } + [BackgroundDependencyLoader] private void load(AudioManager audio) { @@ -58,9 +43,24 @@ namespace osu.Game.Rulesets.Osu.Tests Cell(3).Child = new LocalSkinOverrideContainer(specialSkin) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); } - protected SkinnableTestScene() - : base(2, 2) + private static Skin getSkinFromResources(SkinManager skins, string name) { + using (var storage = new DllResourceStore("osu.Game.Rulesets.Osu.Tests.dll")) + { + var tempName = Path.GetTempFileName(); + + File.Delete(tempName); + Directory.CreateDirectory(tempName); + + var files = storage.GetAvailableResources().Where(f => f.StartsWith($"Resources/{name}")); + + foreach (var file in files) + using (var stream = storage.GetStream(file)) + using (var newFile = File.Create(Path.Combine(tempName, Path.GetFileName(file)))) + stream.CopyTo(newFile); + + return skins.GetSkin(skins.Import(tempName).Result); + } } } } From e849e68e9984741b2dbe59a17e7445f123b61fac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 22:24:03 +0900 Subject: [PATCH 2113/5608] 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 2c5e54d4f5..e64102c401 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 472f6e9d65..1f91ce1cd8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 0a19eac2b5..66f398a927 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 307a6c10953eb0cd8c830694b2c0a3d8654b08ab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 22:38:29 +0900 Subject: [PATCH 2114/5608] Remove DefaultCirclePiece --- .../Objects/Drawables/Pieces/CirclePiece.cs | 24 +++++++++++-- .../Drawables/Pieces/DefaultCirclePiece.cs | 35 ------------------- osu.Game/Skinning/LegacySkin.cs | 6 ++-- 3 files changed, 25 insertions(+), 40 deletions(-) delete mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index acbf5ba9ae..c92937ef09 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -1,9 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Skinning; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces @@ -18,8 +20,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Anchor = Anchor.Centre; Origin = Anchor.Centre; + } - InternalChild = new SkinnableDrawable("Play/osu/hitcircle", _ => new DefaultCirclePiece()); + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + InternalChildren = new Drawable[] + { + new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Texture = textures.Get(@"Play/osu/disc"), + }, + new TrianglesPiece + { + RelativeSizeAxes = Axes.Both, + Blending = BlendingMode.Additive, + Alpha = 0.5f, + } + }; } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs deleted file mode 100644 index 047ff943ff..0000000000 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; - -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces -{ - public class DefaultCirclePiece : Container - { - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - RelativeSizeAxes = Axes.Both; - Children = new Drawable[] - { - new Sprite - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Texture = textures.Get(@"Play/osu/disc"), - }, - new TrianglesPiece - { - RelativeSizeAxes = Axes.Both, - Blending = BlendingMode.Additive, - Alpha = 0.5f, - } - }; - } - } -} diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 0a811a9514..dffcd00cc3 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -274,11 +274,11 @@ namespace osu.Game.Skinning [BackgroundDependencyLoader] private void load(DrawableHitObject drawableObject, ISkinSource skin) { - Sprite mainCircle; + Sprite hitCircleSprite; InternalChildren = new Drawable[] { - mainCircle = new Sprite + hitCircleSprite = new Sprite { Texture = skin.GetTexture("hitcircle"), Colour = drawableObject.AccentColour.Value @@ -298,7 +298,7 @@ namespace osu.Game.Skinning state.BindValueChanged(updateState, true); accentColour.BindTo(drawableObject.AccentColour); - accentColour.BindValueChanged(colour => mainCircle.Colour = colour.NewValue, true); + accentColour.BindValueChanged(colour => hitCircleSprite.Colour = colour.NewValue, true); } private void updateState(ValueChangedEvent state) From e6bd02d2767f6b7dbb265542dbf2d2369b15e9fb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 22:41:20 +0900 Subject: [PATCH 2115/5608] Simplify namespace definition --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index df944fd9a6..ca124e9214 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return true; }, }, - new SkinnableDrawable("Play/Osu/Objects/Drawables/MainCircle", _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)), + new SkinnableDrawable("Play/osu/hitcircle", _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)), ApproachCircle = new ApproachCircle { Alpha = 0, diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index dffcd00cc3..fff7fd082e 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -78,7 +78,7 @@ namespace osu.Game.Skinning { switch (componentName) { - case "Play/Osu/Objects/Drawables/MainCircle": + case "Play/osu/hitcircle": if (!hasHitCircle) return null; From fb1f77bd0490ebaf7c921654d3b67792b47ea6d2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 23:06:18 +0900 Subject: [PATCH 2116/5608] Move implementation and colour logic to legacy implementation --- .../Objects/Drawables/Pieces/SliderBall.cs | 13 +++---------- osu.Game/Skinning/LegacySkin.cs | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 119005eb40..8b72b23ca3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -4,7 +4,6 @@ using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -57,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { RelativeSizeAxes = Axes.Both, // TODO: support skin filename animation (sliderb0, sliderb1...) - Child = new SkinnableDrawable("Play/osu/sliderb", _ => new DefaultSliderBall()), + Child = new SkinnableDrawable("Play/osu/sliderball", _ => new DefaultSliderBall()), } } }; @@ -204,10 +203,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public class DefaultSliderBall : CompositeDrawable { - private readonly Bindable accentColour = new Bindable(); - - private Drawable drawableBall; - [BackgroundDependencyLoader] private void load(DrawableHitObject drawableObject, ISkinSource skin) { @@ -225,15 +220,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces BorderThickness = 10, BorderColour = Color4.White, Alpha = 1, - Child = drawableBall = new Box + Child = new Box { RelativeSizeAxes = Axes.Both, + Colour = Color4.White, Alpha = 0.4f, } }; - - accentColour.BindTo(drawableObject.AccentColour); - accentColour.BindValueChanged(colour => drawableBall.Colour = colour.NewValue, true); } } } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index af9a24df42..84fa5ff97b 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; +using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; @@ -15,6 +16,7 @@ using osu.Framework.IO.Stores; using osu.Game.Database; using osu.Game.Graphics.Sprites; using osuTK; +using osuTK.Graphics; namespace osu.Game.Skinning { @@ -71,6 +73,12 @@ namespace osu.Game.Skinning { switch (componentName) { + case "Play/osu/sliderball": + if (GetTexture("sliderb") != null) + return new LegacySliderBall(); + + break; + case "Play/Miss": componentName = "hit0"; break; @@ -109,6 +117,16 @@ namespace osu.Game.Skinning return new Sprite { Texture = texture }; } + public class LegacySliderBall : Sprite + { + [BackgroundDependencyLoader] + private void load(ISkinSource skin) + { + Texture = skin.GetTexture("sliderb"); + Colour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Color4.White; + } + } + public override Texture GetTexture(string componentName) { float ratio = 2; From 6d279dba5ce40957bb8df20845c2409203f02d24 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 23:07:41 +0900 Subject: [PATCH 2117/5608] Fix centering being incorrect for some skins --- osu.Game/Skinning/LegacySkin.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index fff7fd082e..c381c6293b 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -281,7 +281,9 @@ namespace osu.Game.Skinning hitCircleSprite = new Sprite { Texture = skin.GetTexture("hitcircle"), - Colour = drawableObject.AccentColour.Value + Colour = drawableObject.AccentColour.Value, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, }, new SkinnableSpriteText("Play/osu/number-text", _ => new OsuSpriteText { @@ -291,7 +293,12 @@ namespace osu.Game.Skinning { Text = (((IHasComboInformation)drawableObject.HitObject).IndexInCurrentCombo + 1).ToString() }, - new Sprite { Texture = skin.GetTexture("hitcircleoverlay") } + new Sprite + { + Texture = skin.GetTexture("hitcircleoverlay"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } }; state.BindTo(drawableObject.State); From d12de7dbfa0127ffac637e9736a54fc496d29bd9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 23:20:35 +0900 Subject: [PATCH 2118/5608] Add temporary scale hack to make cursors correct size --- osu.Game/Skinning/LegacySkin.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index a567f85a02..bd08de03d5 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -255,13 +255,13 @@ namespace osu.Game.Skinning { InternalChildren = new Drawable[] { - new Sprite + new NonPlayfieldSprite { Texture = skin.GetTexture("cursormiddle"), Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - new Sprite + new NonPlayfieldSprite { Texture = skin.GetTexture("cursor"), Anchor = Anchor.Centre, @@ -270,5 +270,18 @@ namespace osu.Game.Skinning }; } } + + private class NonPlayfieldSprite : Sprite + { + public override Texture Texture + { + get => base.Texture; + set + { + value.ScaleAdjust *= 2f; + base.Texture = value; + } + } + } } } From 21a8f566c3b34b78bbfd3be635a06ea5d169d93f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 23:24:28 +0900 Subject: [PATCH 2119/5608] Trim whitespace --- osu.Game/Skinning/LegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index f01dc7f8dd..b6d9b014fd 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -87,7 +87,7 @@ namespace osu.Game.Skinning case "Play/osu/hitcircle": if (hasHitCircle) return new LegacyMainCirclePiece(); - + return null; case "Play/Miss": From 4c6cccb3a338294dd20b69615cddeb82ba77301b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 23:31:21 +0900 Subject: [PATCH 2120/5608] Update settings in line with framework changes --- .../Settings/Sections/Debug/GeneralSettings.cs | 5 ----- .../Debug/{GCSettings.cs => MemorySettings.cs} | 12 ++++++------ osu.Game/Overlays/Settings/Sections/DebugSection.cs | 2 +- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- 4 files changed, 8 insertions(+), 13 deletions(-) rename osu.Game/Overlays/Settings/Sections/Debug/{GCSettings.cs => MemorySettings.cs} (63%) diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs index f063898a9f..7eec971b62 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs @@ -27,11 +27,6 @@ namespace osu.Game.Overlays.Settings.Sections.Debug Bindable = frameworkConfig.GetBindable(FrameworkSetting.PerformanceLogging) }, new SettingsCheckbox - { - LabelText = "Bypass caching (slow)", - Bindable = config.GetBindable(DebugSetting.BypassCaching) - }, - new SettingsCheckbox { LabelText = "Bypass front-to-back render pass", Bindable = config.GetBindable(DebugSetting.BypassFrontToBackPass) diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/MemorySettings.cs similarity index 63% rename from osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs rename to osu.Game/Overlays/Settings/Sections/Debug/MemorySettings.cs index 6897b42f4f..db64c9a8ac 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/MemorySettings.cs @@ -1,26 +1,26 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Framework.Platform; namespace osu.Game.Overlays.Settings.Sections.Debug { - public class GCSettings : SettingsSubsection + public class MemorySettings : SettingsSubsection { - protected override string Header => "Garbage Collector"; + protected override string Header => "Memory"; [BackgroundDependencyLoader] - private void load(FrameworkDebugConfigManager config) + private void load(FrameworkDebugConfigManager config, GameHost host) { Children = new Drawable[] { new SettingsButton { - Text = "Force garbage collection", - Action = GC.Collect + Text = "Clear all caches", + Action = host.Collect }, }; } diff --git a/osu.Game/Overlays/Settings/Sections/DebugSection.cs b/osu.Game/Overlays/Settings/Sections/DebugSection.cs index 0149cab802..f62de0b243 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSection.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSection.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Settings.Sections Children = new Drawable[] { new GeneralSettings(), - new GCSettings(), + new MemorySettings(), }; } } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 2551ffe2fc..a9e4eaa9b3 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -141,6 +141,7 @@ namespace osu.Game.Screens.Select private readonly RulesetInfo ruleset; public BufferedWedgeInfo(WorkingBeatmap beatmap, RulesetInfo userRuleset) + : base(pixelSnapping: true) { this.beatmap = beatmap; ruleset = userRuleset ?? beatmap.BeatmapInfo.Ruleset; @@ -152,7 +153,6 @@ namespace osu.Game.Screens.Select var beatmapInfo = beatmap.BeatmapInfo; var metadata = beatmapInfo.Metadata ?? beatmap.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); - PixelSnapping = true; CacheDrawnFrameBuffer = true; RelativeSizeAxes = Axes.Both; From f6b6fa963393ed2e3130a96e737b33605fc91fcd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 23:44:47 +0900 Subject: [PATCH 2121/5608] Add disappeared null check --- osu.Game/Skinning/LegacySkin.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index d6709df646..906a81a007 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -365,7 +365,8 @@ namespace osu.Game.Skinning get => base.Texture; set { - value.ScaleAdjust *= 2f; + if (value != null) + value.ScaleAdjust *= 2f; base.Texture = value; } } From 9335ebeb5592d10a820bdcb5b3edc719294f7593 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jul 2019 23:45:55 +0900 Subject: [PATCH 2122/5608] Fix missing anchor/origin specification --- osu.Game/Skinning/LegacySkin.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 906a81a007..19f04c9b7a 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -291,6 +291,8 @@ namespace osu.Game.Skinning new NonPlayfieldSprite { Texture = skin.GetTexture("cursor"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, } }; } From 5aece2d5f2c718be42c1b5805e37efa381f18e0d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 31 Jul 2019 16:03:05 +0900 Subject: [PATCH 2123/5608] fix tests --- .../Visual/Menus/TestSceneScreenNavigation.cs | 23 ++++++++++++++++--- osu.Game/OsuGame.cs | 7 +++--- osu.Game/Screens/Menu/ButtonSystem.cs | 2 +- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index ca94f2b636..de6daf9618 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -13,8 +13,10 @@ using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods; +using osu.Game.Screens; using osu.Game.Screens.Menu; using osu.Game.Screens.Select; +using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -25,6 +27,8 @@ namespace osu.Game.Tests.Visual.Menus private GameHost gameHost; private TestOsuGame osuGame; + private Vector2 backButtonPosition => osuGame.ToScreenSpace(new Vector2(0, osuGame.LayoutRectangle.Bottom)); + [BackgroundDependencyLoader] private void load(GameHost gameHost) { @@ -50,7 +54,8 @@ namespace osu.Game.Tests.Visual.Menus Add(osuGame); }); - AddUntilStep("Wait for main menu", () => osuGame.IsLoaded && osuGame.ScreenStack.CurrentScreen is MainMenu); + AddUntilStep("Wait for load", () => osuGame.IsLoaded); + AddUntilStep("Wait for main menu", () => osuGame.ScreenStack.CurrentScreen is MainMenu); } [Test] @@ -80,7 +85,7 @@ namespace osu.Game.Tests.Visual.Menus AddUntilStep("Back button is hovered", () => InputManager.HoveredDrawables.Any(d => d.Parent == osuGame.BackButton)); AddStep("Click back button", () => InputManager.Click(MouseButton.Left)); - AddAssert("Overlay was hidden", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden); + AddUntilStep("Overlay was hidden", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden); exitViaBackButtonAndConfirm(); } @@ -102,7 +107,7 @@ namespace osu.Game.Tests.Visual.Menus { Screen screen = null; AddStep($"Push new {screenName}", () => osuGame.ScreenStack.Push(screen = newScreen())); - AddUntilStep($"Wait for new {screenName}", () => screen.IsCurrentScreen()); + AddUntilStep($"Wait for new {screenName}", () => osuGame.ScreenStack.CurrentScreen == screen); } private void exitViaEscapeAndConfirm() @@ -129,11 +134,23 @@ namespace osu.Game.Tests.Visual.Menus public new ScreenStack ScreenStack => base.ScreenStack; public new BackButton BackButton => base.BackButton; + + protected override Loader CreateLoader() => new TestLoader(); } private class TestSongSelect : PlaySongSelect { public ModSelectOverlay ModSelectOverlay => ModSelect; } + + private class TestLoader : Loader + { + protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler(); + + private class TestShaderPrecompiler : ShaderPrecompiler + { + protected override bool AllLoaded => true; + } + } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 77f16549fe..6d85623eb9 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -105,6 +105,8 @@ namespace osu.Game private readonly List visibleBlockingOverlays = new List(); + protected virtual Loader CreateLoader() => new Loader(); + public OsuGame(string[] args = null) { this.args = args; @@ -439,10 +441,7 @@ namespace osu.Game logoContainer.Add(logo); // Loader has to be created after the logo has finished loading as Loader performs logo transformations on entering. - ScreenStack.Push(new Loader - { - RelativeSizeAxes = Axes.Both - }); + ScreenStack.Push(CreateLoader().With(l => l.RelativeSizeAxes = Axes.Both)); }); loadComponentSingleFile(Toolbar = new Toolbar diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 1a3e1213b4..e9eab12557 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -316,7 +316,7 @@ namespace osu.Game.Screens.Menu logoDelayedAction = Scheduler.AddDelayed(() => { if (impact) - logo.Impact(); + logo?.Impact(); game?.Toolbar.Show(); }, 200); From 6bfac9f8e42546565c34151b0d30d0c5b501bd74 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 31 Jul 2019 17:50:13 +0900 Subject: [PATCH 2124/5608] Remove protected ctor --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 47ce28db4c..b3d7bfb91f 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -217,10 +217,6 @@ namespace osu.Game.Rulesets.Scoring private double baseScore; private double bonusScore; - protected ScoreProcessor() - { - } - public ScoreProcessor(DrawableRuleset drawableRuleset) { Debug.Assert(base_portion + combo_portion == 1.0); From e57663b39cdf2ba57984f54c6dd54a751ac225e7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 31 Jul 2019 17:55:22 +0900 Subject: [PATCH 2125/5608] Apply mod score multipliers --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index b3d7bfb91f..2e863f7edb 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -217,6 +217,8 @@ namespace osu.Game.Rulesets.Scoring private double baseScore; private double bonusScore; + private double scoreMultiplier = 1; + public ScoreProcessor(DrawableRuleset drawableRuleset) { Debug.Assert(base_portion + combo_portion == 1.0); @@ -235,6 +237,15 @@ namespace osu.Game.Rulesets.Scoring } Mode.ValueChanged += _ => updateScore(); + Mods.ValueChanged += mods => + { + scoreMultiplier = 1; + + foreach (var m in mods.NewValue) + scoreMultiplier *= m.ScoreMultiplier; + + updateScore(); + }; } ///
@@ -384,7 +395,7 @@ namespace osu.Game.Rulesets.Scoring if (rollingMaxBaseScore != 0) Accuracy.Value = baseScore / rollingMaxBaseScore; - TotalScore.Value = getScore(Mode.Value); + TotalScore.Value = getScore(Mode.Value) * scoreMultiplier; } private double getScore(ScoringMode mode) From 980686f6bff6a0bc3f7da03d7826e3a7b46806d7 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 31 Jul 2019 19:30:35 +0900 Subject: [PATCH 2126/5608] get tests running again --- .../Visual/Menus/TestSceneScreenNavigation.cs | 34 ++++++++++++++----- osu.Game/OsuGame.cs | 2 +- osu.Game/Screens/Menu/ButtonSystem.cs | 2 +- osu.Game/Screens/Multi/Multiplayer.cs | 4 ++- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index de6daf9618..b4c7716e37 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -5,17 +5,23 @@ using System; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods; +using osu.Game.Rulesets; using osu.Game.Screens; using osu.Game.Screens.Menu; using osu.Game.Screens.Select; +using osu.Game.Tests.Resources; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -27,7 +33,7 @@ namespace osu.Game.Tests.Visual.Menus private GameHost gameHost; private TestOsuGame osuGame; - private Vector2 backButtonPosition => osuGame.ToScreenSpace(new Vector2(0, osuGame.LayoutRectangle.Bottom)); + private Vector2 backButtonPosition => osuGame.ToScreenSpace(new Vector2(25, osuGame.LayoutRectangle.Bottom - 25)); [BackgroundDependencyLoader] private void load(GameHost gameHost) @@ -55,7 +61,8 @@ namespace osu.Game.Tests.Visual.Menus Add(osuGame); }); AddUntilStep("Wait for load", () => osuGame.IsLoaded); - AddUntilStep("Wait for main menu", () => osuGame.ScreenStack.CurrentScreen is MainMenu); + AddUntilStep("Wait for intro", () => osuGame.ScreenStack.CurrentScreen is IntroScreen); + AddUntilStep("Wait for main menu", () => osuGame.ScreenStack.CurrentScreen is MainMenu menu && menu.IsLoaded); } [Test] @@ -79,7 +86,7 @@ namespace osu.Game.Tests.Visual.Menus pushAndConfirm(() => songSelect = new TestSongSelect(), "song select"); AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show()); AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); - AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(osuGame.BackButton)); + AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(backButtonPosition)); // BackButton handles hover using its child button, so this checks whether or not any of BackButton's children are hovered. AddUntilStep("Back button is hovered", () => InputManager.HoveredDrawables.Any(d => d.Parent == osuGame.BackButton)); @@ -92,22 +99,28 @@ namespace osu.Game.Tests.Visual.Menus [Test] public void TestExitMultiWithEscape() { - pushAndConfirm(() => new Screens.Multi.Multiplayer(), "multiplayer"); + pushAndConfirm(() => new TestMultiplayer(), "multiplayer"); exitViaEscapeAndConfirm(); } [Test] public void TestExitMultiWithBackButton() { - pushAndConfirm(() => new Screens.Multi.Multiplayer(), "multiplayer"); + pushAndConfirm(() => new TestMultiplayer(), "multiplayer"); exitViaBackButtonAndConfirm(); } private void pushAndConfirm(Func newScreen, string screenName) { Screen screen = null; - AddStep($"Push new {screenName}", () => osuGame.ScreenStack.Push(screen = newScreen())); - AddUntilStep($"Wait for new {screenName}", () => osuGame.ScreenStack.CurrentScreen == screen); + AddStep($"Push new {screenName}", () => + { + if (screenName == "song select") + Logger.Log("fuck"); + + osuGame.ScreenStack.Push(screen = newScreen()); + }); + AddUntilStep($"Wait for new {screenName}", () => osuGame.ScreenStack.CurrentScreen == screen && screen.IsLoaded); } private void exitViaEscapeAndConfirm() @@ -118,7 +131,7 @@ namespace osu.Game.Tests.Visual.Menus private void exitViaBackButtonAndConfirm() { - AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(osuGame.BackButton)); + AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(backButtonPosition)); AddStep("Click back button", () => InputManager.Click(MouseButton.Left)); AddUntilStep("Wait for main menu", () => osuGame.ScreenStack.CurrentScreen is MainMenu); } @@ -143,6 +156,11 @@ namespace osu.Game.Tests.Visual.Menus public ModSelectOverlay ModSelectOverlay => ModSelect; } + private class TestMultiplayer : Screens.Multi.Multiplayer + { + protected override bool RequireOnline => false; + } + private class TestLoader : Loader { protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler(); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 38b9526364..9fa1eb8aa7 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -317,7 +317,7 @@ namespace osu.Game private void currentTrackCompleted() { - if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled) + if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled && musicController.IsLoaded) musicController.NextTrack(); } diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index e9eab12557..1a3e1213b4 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -316,7 +316,7 @@ namespace osu.Game.Screens.Menu logoDelayedAction = Scheduler.AddDelayed(() => { if (impact) - logo?.Impact(); + logo.Impact(); game?.Toolbar.Show(); }, 200); diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 90806bab6e..3d9997e236 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -34,6 +34,8 @@ namespace osu.Game.Screens.Multi public override bool DisallowExternalBeatmapRulesetChanges => true; + protected virtual bool RequireOnline => true; + private readonly MultiplayerWaveContainer waves; private readonly OsuButton createButton; @@ -166,7 +168,7 @@ namespace osu.Game.Screens.Multi public void APIStateChanged(IAPIProvider api, APIState state) { - if (state != APIState.Online) + if (RequireOnline && state != APIState.Online) forcefullyExit(); } From 351b6e6259769bd98384142ebf9f6d1713a80760 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 31 Jul 2019 19:47:41 +0900 Subject: [PATCH 2127/5608] Add new options test --- .../Visual/Menus/TestSceneScreenNavigation.cs | 23 ++++++++++++++----- osu.Game/OsuGame.cs | 15 ++++++------ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index b4c7716e37..f71e8dc2ce 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -5,7 +5,6 @@ using System; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Audio; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -13,15 +12,12 @@ using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Testing; -using osu.Game.Beatmaps; -using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; using osu.Game.Overlays.Mods; -using osu.Game.Rulesets; using osu.Game.Screens; using osu.Game.Screens.Menu; using osu.Game.Screens.Select; -using osu.Game.Tests.Resources; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -35,6 +31,8 @@ namespace osu.Game.Tests.Visual.Menus private Vector2 backButtonPosition => osuGame.ToScreenSpace(new Vector2(25, osuGame.LayoutRectangle.Bottom - 25)); + private Vector2 optionsButtonPosition => osuGame.ToScreenSpace(new Vector2(25, 25)); + [BackgroundDependencyLoader] private void load(GameHost gameHost) { @@ -110,6 +108,17 @@ namespace osu.Game.Tests.Visual.Menus exitViaBackButtonAndConfirm(); } + [Test] + public void TestOpenOptionsAndExitWithEscape() + { + AddStep("Enter menu", () => pressAndRelease(Key.Enter)); + AddStep("Move mouse to options overlay", () => InputManager.MoveMouseTo(optionsButtonPosition)); + AddStep("Click options overlay", () => InputManager.Click(MouseButton.Left)); + AddAssert("Options overlay was opened", () => osuGame.Settings.State.Value == Visibility.Visible); + AddStep("Hide options overlay using escape", () => pressAndRelease(Key.Escape)); + AddAssert("Options overlay was closed", () => osuGame.Settings.State.Value == Visibility.Hidden); + } + private void pushAndConfirm(Func newScreen, string screenName) { Screen screen = null; @@ -117,7 +126,7 @@ namespace osu.Game.Tests.Visual.Menus { if (screenName == "song select") Logger.Log("fuck"); - + osuGame.ScreenStack.Push(screen = newScreen()); }); AddUntilStep($"Wait for new {screenName}", () => osuGame.ScreenStack.CurrentScreen == screen && screen.IsLoaded); @@ -148,6 +157,8 @@ namespace osu.Game.Tests.Visual.Menus public new BackButton BackButton => base.BackButton; + public new SettingsPanel Settings => base.Settings; + protected override Loader CreateLoader() => new TestLoader(); } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 9fa1eb8aa7..e7c0d01f31 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -82,8 +82,11 @@ namespace osu.Game public readonly Bindable OverlayActivationMode = new Bindable(); protected OsuScreenStack ScreenStack; + protected BackButton BackButton; + protected SettingsPanel Settings; + private VolumeOverlay volume; private OsuLogo osuLogo; @@ -97,8 +100,6 @@ namespace osu.Game private readonly string[] args; - private SettingsPanel settings; - private readonly List overlays = new List(); private readonly List toolbarElements = new List(); @@ -483,7 +484,7 @@ namespace osu.Game loadComponentSingleFile(social = new SocialOverlay(), overlayContent.Add, true); loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal, true); loadComponentSingleFile(chatOverlay = new ChatOverlay(), overlayContent.Add, true); - loadComponentSingleFile(settings = new SettingsOverlay { GetToolbarHeight = () => ToolbarOffset }, leftFloatingOverlayContent.Add, true); + loadComponentSingleFile(Settings = new SettingsOverlay { GetToolbarHeight = () => ToolbarOffset }, leftFloatingOverlayContent.Add, true); var changelogOverlay = loadComponentSingleFile(new ChangelogOverlay(), overlayContent.Add, true); loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true); @@ -514,7 +515,7 @@ namespace osu.Game Add(externalLinkOpener = new ExternalLinkOpener()); - var singleDisplaySideOverlays = new OverlayContainer[] { settings, notifications }; + var singleDisplaySideOverlays = new OverlayContainer[] { Settings, notifications }; overlays.AddRange(singleDisplaySideOverlays); foreach (var overlay in singleDisplaySideOverlays) @@ -567,7 +568,7 @@ namespace osu.Game { float offset = 0; - if (settings.State.Value == Visibility.Visible) + if (Settings.State.Value == Visibility.Visible) offset += ToolbarButton.WIDTH / 2; if (notifications.State.Value == Visibility.Visible) offset -= ToolbarButton.WIDTH / 2; @@ -575,7 +576,7 @@ namespace osu.Game screenContainer.MoveToX(offset, SettingsPanel.TRANSITION_LENGTH, Easing.OutQuint); } - settings.State.ValueChanged += _ => updateScreenOffset(); + Settings.State.ValueChanged += _ => updateScreenOffset(); notifications.State.ValueChanged += _ => updateScreenOffset(); } @@ -720,7 +721,7 @@ namespace osu.Game return true; case GlobalAction.ToggleSettings: - settings.ToggleVisibility(); + Settings.ToggleVisibility(); return true; case GlobalAction.ToggleDirect: From 3af1aaeabe8571674c01f721e01dd0628b89edbe Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 31 Jul 2019 15:19:02 +0300 Subject: [PATCH 2128/5608] Unsubscribe from Completed event on old beatmap --- osu.Game/OsuGame.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e71dd67bf2..431e6c91f9 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -307,8 +307,11 @@ namespace osu.Game if (nextBeatmap?.Track != null) nextBeatmap.Track.Completed += currentTrackCompleted; - beatmap.OldValue?.Dispose(); + var oldBeatmap = beatmap.OldValue; + if (oldBeatmap?.Track != null) + oldBeatmap.Track.Completed -= currentTrackCompleted; + oldBeatmap?.Dispose(); nextBeatmap?.LoadBeatmapAsync(); } From 0f1dd8a46e4d5e43e0c1e138886d790a84539cea Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Wed, 31 Jul 2019 21:44:57 +0800 Subject: [PATCH 2129/5608] Undo #5533 for causing crashes --- osu.iOS/Info.plist | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index 4fbc67e27b..0775d1522d 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -14,8 +14,6 @@ 0.1.0 LSRequiresIPhoneOS - LSSupportsOpeningDocumentsInPlace - MinimumOSVersion 10.0 UIDeviceFamily From 958e3fb68bffcd8bbad6f178c585f13bf849faa2 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 31 Jul 2019 22:42:23 +0300 Subject: [PATCH 2130/5608] Add a property for acquiring online API access --- osu.Game/Tests/Visual/OsuTestScene.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 27d72f3950..dd68ed93e6 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -16,6 +16,7 @@ using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Database; +using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Tests.Beatmaps; @@ -47,6 +48,12 @@ namespace osu.Game.Tests.Visual private readonly Lazy contextFactory; protected DatabaseContextFactory ContextFactory => contextFactory.Value; + /// + /// Whether this test scene requires API access + /// Setting this will cache an actual . + /// + protected virtual bool RequiresAPIAccess => false; + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { // This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures @@ -57,7 +64,17 @@ namespace osu.Game.Tests.Visual Default = working }; - return Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + + if (!RequiresAPIAccess) + { + var dummyAPI = new DummyAPIAccess(); + + Dependencies.CacheAs(dummyAPI); + Add(dummyAPI); + } + + return Dependencies; } protected OsuTestScene() From 034345f1bd5dd28dcd9f5b91bdaca3a6fead35d2 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 31 Jul 2019 22:43:05 +0300 Subject: [PATCH 2131/5608] Resolve API for dummy-caching tests --- osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs | 7 +------ .../Online/TestSceneAccountCreationOverlay.cs | 14 ++++++++------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs index f2718b8e80..13116de320 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs @@ -10,14 +10,9 @@ namespace osu.Game.Tests.Visual.Menus { public class TestSceneDisclaimer : ScreenTestScene { - [Cached(typeof(IAPIProvider))] - private readonly DummyAPIAccess api = new DummyAPIAccess(); - [BackgroundDependencyLoader] - private void load() + private void load(IAPIProvider api) { - Add(api); - AddStep("load disclaimer", () => LoadScreen(new Disclaimer())); AddStep("toggle support", () => diff --git a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs index 35449f5687..66ab1fe18a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs @@ -25,17 +25,14 @@ namespace osu.Game.Tests.Visual.Online typeof(AccountCreationScreen), }; - [Cached(typeof(IAPIProvider))] - private DummyAPIAccess api = new DummyAPIAccess(); + private readonly Container userPanelArea; public TestSceneAccountCreationOverlay() { - Container userPanelArea; AccountCreationOverlay accountCreation; Children = new Drawable[] { - api, accountCreation = new AccountCreationOverlay(), userPanelArea = new Container { @@ -46,11 +43,16 @@ namespace osu.Game.Tests.Visual.Online }, }; + AddStep("show", () => accountCreation.Show()); + } + + [BackgroundDependencyLoader] + private void load(IAPIProvider api) + { api.Logout(); api.LocalUser.BindValueChanged(user => { userPanelArea.Child = new UserPanel(user.NewValue) { Width = 200 }; }, true); - AddStep("show", () => accountCreation.Show()); - AddStep("logout", () => api.Logout()); + AddStep("logout", api.Logout); } } } From 849ed0c69df35d11c0b2c6e133e943143bb19e01 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 31 Jul 2019 22:44:44 +0300 Subject: [PATCH 2132/5608] Acquire api access for online tests --- .../Multiplayer/TestSceneMatchLeaderboard.cs | 7 +++---- .../Visual/Multiplayer/TestSceneMultiScreen.cs | 2 ++ .../Visual/Online/TestSceneBeatmapSetOverlay.cs | 2 ++ .../Visual/Online/TestSceneChangelogOverlay.cs | 2 ++ .../Visual/Online/TestSceneDirectOverlay.cs | 2 ++ .../Visual/Online/TestSceneHistoricalSection.cs | 17 +++++++++-------- .../Visual/Online/TestSceneSocialOverlay.cs | 2 ++ .../Visual/Online/TestSceneUserProfileHeader.cs | 2 ++ .../Online/TestSceneUserProfileOverlay.cs | 2 ++ .../Visual/Online/TestSceneUserRanks.cs | 2 ++ ...estSceneUpdateableBeatmapBackgroundSprite.cs | 2 ++ 11 files changed, 30 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs index fa3c392b2e..723e5fc03d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs @@ -14,6 +14,8 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMatchLeaderboard : MultiplayerTestScene { + protected override bool RequiresAPIAccess => true; + public TestSceneMatchLeaderboard() { Room.RoomID.Value = 3; @@ -27,11 +29,8 @@ namespace osu.Game.Tests.Visual.Multiplayer }); } - [Resolved] - private IAPIProvider api { get; set; } - [BackgroundDependencyLoader] - private void load() + private void load(IAPIProvider api) { var req = new GetRoomScoresRequest(); req.Success += v => { }; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs index 069e133c2b..b646433846 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs @@ -12,6 +12,8 @@ namespace osu.Game.Tests.Visual.Multiplayer [TestFixture] public class TestSceneMultiScreen : ScreenTestScene { + protected override bool RequiresAPIAccess => true; + public override IReadOnlyList RequiredTypes => new[] { typeof(Screens.Multi.Multiplayer), diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index daee419b52..edb232359f 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -42,6 +42,8 @@ namespace osu.Game.Tests.Visual.Online typeof(BeatmapAvailability), }; + protected override bool RequiresAPIAccess => true; + private RulesetInfo taikoRuleset; private RulesetInfo maniaRuleset; diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index cf8bac7642..324291c9d7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -27,6 +27,8 @@ namespace osu.Game.Tests.Visual.Online typeof(Comments), }; + protected override bool RequiresAPIAccess => true; + protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs index 75c2a2a6a1..14ae975806 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs @@ -13,6 +13,8 @@ namespace osu.Game.Tests.Visual.Online { private DirectOverlay direct; + protected override bool RequiresAPIAccess => true; + protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs index 838347800f..c98f98c23d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs @@ -17,14 +17,15 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneHistoricalSection : OsuTestScene { - public override IReadOnlyList RequiredTypes => - new[] - { - typeof(HistoricalSection), - typeof(PaginatedMostPlayedBeatmapContainer), - typeof(DrawableMostPlayedBeatmap), - typeof(DrawableProfileRow) - }; + protected override bool RequiresAPIAccess => true; + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HistoricalSection), + typeof(PaginatedMostPlayedBeatmapContainer), + typeof(DrawableMostPlayedBeatmap), + typeof(DrawableProfileRow) + }; public TestSceneHistoricalSection() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs index 5cb96c7ed2..806b36e855 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs @@ -13,6 +13,8 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneSocialOverlay : OsuTestScene { + protected override bool RequiresAPIAccess => true; + public override IReadOnlyList RequiredTypes => new[] { typeof(UserPanel), diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index 2285c9b799..555d5334d8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -17,6 +17,8 @@ namespace osu.Game.Tests.Visual.Online { public class TestSceneUserProfileHeader : OsuTestScene { + protected override bool RequiresAPIAccess => true; + public override IReadOnlyList RequiredTypes => new[] { typeof(ProfileHeader), diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index c2376aa153..39ba0ea3da 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -19,6 +19,8 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneUserProfileOverlay : OsuTestScene { + protected override bool RequiresAPIAccess => true; + private readonly TestUserProfileOverlay profile; [Resolved] diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs index 9f0a8c769a..d777f9766a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs @@ -18,6 +18,8 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneUserRanks : OsuTestScene { + protected override bool RequiresAPIAccess => true; + public override IReadOnlyList RequiredTypes => new[] { typeof(DrawableProfileScore), typeof(RanksSection) }; public TestSceneUserRanks() diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs index 9cdfcb6cc4..fdc50be3fa 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs @@ -20,6 +20,8 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneUpdateableBeatmapBackgroundSprite : OsuTestScene { + protected override bool RequiresAPIAccess => true; + private BeatmapSetInfo testBeatmap; private IAPIProvider api; private RulesetStore rulesets; From 7b95741dab566f5ef85ae01d1b169dbd3e9f18a0 Mon Sep 17 00:00:00 2001 From: jorolf Date: Wed, 31 Jul 2019 21:55:56 +0200 Subject: [PATCH 2133/5608] fix crash and add some tests - still missing special skin textures --- .../Resources/default-skin/hit0@2x.png | Bin 0 -> 16112 bytes .../Resources/default-skin/hit100@2x.png | Bin 0 -> 31228 bytes .../Resources/default-skin/hit100k@2x.png | Bin 0 -> 21318 bytes .../Resources/default-skin/hit300@2x.png | Bin 0 -> 36873 bytes .../Resources/default-skin/hit300g@2x.png | Bin 0 -> 39840 bytes .../Resources/default-skin/hit50@2x.png | Bin 0 -> 26015 bytes .../Resources/metrics-skin/hit0@2x.PNG | Bin 0 -> 9492 bytes .../Resources/metrics-skin/hit100@2x.PNG | Bin 0 -> 8371 bytes .../Resources/metrics-skin/hit300@2x.PNG | Bin 0 -> 9589 bytes .../Resources/metrics-skin/hit50@2x.PNG | Bin 0 -> 9299 bytes .../TestSceneDrawableJudgement.cs | 39 ++++++++++++++++++ osu.Game/Skinning/LegacySkin.cs | 2 +- 12 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit0@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit100@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit100k@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300g@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit50@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit0@2x.PNG create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit100@2x.PNG create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit300@2x.PNG create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit50@2x.PNG create mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit0@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit0@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bdb2bcbc41085fef9d4bd351bdeae81f0da331f4 GIT binary patch literal 16112 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit100@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit100@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7db8eb312403e739d8dc61b280f930443ad0d81c GIT binary patch literal 31228 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2c7c07852ff6e84edc2164b4487aaaa6cb4d8fe4 GIT binary patch literal 36873 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%0DE1j{G{fQ$Fey0U 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300g@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300g@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1ce746e3a494f4446cc451f5924240f4c8eecb4b GIT binary patch literal 39840 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%0DP1I3KX^ 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 eY4UfV&i_BJT8gC9ZPy+E0000_|)(jNwS@P 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit50@2x.PNG b/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit50@2x.PNG new file mode 100644 index 0000000000000000000000000000000000000000..f64feded0cc2fc38672c081da38fe214d2546df3 GIT binary patch literal 9299 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. 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.Extensions; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestSceneDrawableJudgement : SkinnableTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(DrawableJudgement), + typeof(DrawableOsuJudgement) + }; + + public TestSceneDrawableJudgement() + { + foreach (HitResult result in Enum.GetValues(typeof(HitResult))) + { + JudgementResult judgement = new JudgementResult(null) + { + Type = result, + }; + + AddStep("Show " + result.GetDescription(), () => SetContents(() => new DrawableOsuJudgement(judgement, null) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + })); + } + } + } +} diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 5357a75e00..3426ddaf16 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -140,7 +140,7 @@ namespace osu.Game.Skinning if (texture != null && animatable) { - var animation = new TextureAnimation { DefaultFrameLength = frametime }; + var animation = new TextureAnimation { DefaultFrameLength = frametime, AutoSizeAxes = Axes.None }; for (int i = 1; texture != null; i++) { From 852079d43852a255b7d238f1691c3214d5221830 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 1 Aug 2019 01:35:42 +0300 Subject: [PATCH 2134/5608] Remove redundant ScreenshotManager.Update override --- osu.Game/Graphics/ScreenshotManager.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 5ad5e5569a..524a4742c0 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -92,7 +92,8 @@ namespace osu.Game.Graphics using (var image = await host.TakeScreenshotAsync()) { - Interlocked.Decrement(ref screenShotTasks); + if (Interlocked.Decrement(ref screenShotTasks) == 0 && cursorVisibility.Value == false) + cursorVisibility.Value = true; var fileName = getFileName(); if (fileName == null) return; @@ -125,14 +126,6 @@ namespace osu.Game.Graphics } }); - protected override void Update() - { - base.Update(); - - if (cursorVisibility.Value == false && Interlocked.CompareExchange(ref screenShotTasks, 0, 0) == 0) - cursorVisibility.Value = true; - } - private string getFileName() { var dt = DateTime.Now; From 8a64ab03847c9ebdb7c2d9d5081e306410f9ee1b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Aug 2019 12:35:17 +0900 Subject: [PATCH 2135/5608] Remove generics from IApplicableToBeatmap --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 3 +-- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 3 +-- .../Mods/ManiaModMirror.cs | 4 +-- .../Mods/ManiaModRandom.cs | 4 +-- osu.Game.Rulesets.Osu/OsuRuleset.cs | 3 +-- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 3 +-- .../Rulesets/Mods/IApplicableToBeatmap.cs | 13 ++++------ osu.Game/Rulesets/Mods/ModTimeRamp.cs | 26 +++++++------------ osu.Game/Rulesets/Mods/ModWindDown.cs | 6 ++--- osu.Game/Rulesets/Mods/ModWindUp.cs | 6 ++--- osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 +- 11 files changed, 28 insertions(+), 45 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index ea9f225cc1..6f1a7873ec 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -11,7 +11,6 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; @@ -108,7 +107,7 @@ namespace osu.Game.Rulesets.Catch case ModType.Fun: return new Mod[] { - new MultiMod(new ModWindUp(), new ModWindDown()) + new MultiMod(new ModWindUp(), new ModWindDown()) }; default: diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index d83033f9c6..8966b5058f 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Game.Graphics; -using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; @@ -154,7 +153,7 @@ namespace osu.Game.Rulesets.Mania case ModType.Fun: return new Mod[] { - new MultiMod(new ModWindUp(), new ModWindDown()) + new MultiMod(new ModWindUp(), new ModWindDown()) }; default: diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs index 17f4098420..485595cea9 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Mania.Beatmaps; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModMirror : Mod, IApplicableToBeatmap + public class ManiaModMirror : Mod, IApplicableToBeatmap { public override string Name => "Mirror"; public override string Acronym => "MR"; @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Mods public override double ScoreMultiplier => 1; public override bool Ranked => true; - public void ApplyToBeatmap(Beatmap beatmap) + public void ApplyToBeatmap(IBeatmap beatmap) { var availableColumns = ((ManiaBeatmap)beatmap).TotalColumns; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs index ba16140644..9275371a61 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModRandom : Mod, IApplicableToBeatmap + public class ManiaModRandom : Mod, IApplicableToBeatmap { public override string Name => "Random"; public override string Acronym => "RD"; @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.Mods public override string Description => @"Shuffle around the keys!"; public override double ScoreMultiplier => 1; - public void ApplyToBeatmap(Beatmap beatmap) + public void ApplyToBeatmap(IBeatmap beatmap) { var availableColumns = ((ManiaBeatmap)beatmap).TotalColumns; var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => RNG.Next()).ToList(); diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 7f45fbe1dd..d50d4f401c 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -14,7 +14,6 @@ using osu.Game.Overlays.Settings; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; @@ -136,7 +135,7 @@ namespace osu.Game.Rulesets.Osu new OsuModWiggle(), new OsuModSpinIn(), new MultiMod(new OsuModGrow(), new OsuModDeflate()), - new MultiMod(new ModWindUp(), new ModWindDown()), + new MultiMod(new ModWindUp(), new ModWindDown()), }; case ModType.System: diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index a67004e9c7..83356b77c2 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Replays.Types; -using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Difficulty; @@ -107,7 +106,7 @@ namespace osu.Game.Rulesets.Taiko case ModType.Fun: return new Mod[] { - new MultiMod(new ModWindUp(), new ModWindDown()) + new MultiMod(new ModWindUp(), new ModWindDown()) }; default: diff --git a/osu.Game/Rulesets/Mods/IApplicableToBeatmap.cs b/osu.Game/Rulesets/Mods/IApplicableToBeatmap.cs index a634976b3c..cff669bf53 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToBeatmap.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToBeatmap.cs @@ -2,21 +2,18 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; -using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mods { /// - /// Interface for a that applies changes to a - /// after conversion and post-processing has completed. + /// Interface for a that applies changes to a after conversion and post-processing has completed. /// - public interface IApplicableToBeatmap : IApplicableMod - where TObject : HitObject + public interface IApplicableToBeatmap : IApplicableMod { /// - /// Applies this to a . + /// Applies this to an . /// - /// The to apply to. - void ApplyToBeatmap(Beatmap beatmap); + /// The to apply to. + void ApplyToBeatmap(IBeatmap beatmap); } } diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index a5f96087c0..9edf57ad00 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -13,27 +13,21 @@ using osuTK; namespace osu.Game.Rulesets.Mods { - public abstract class ModTimeRamp : Mod + public abstract class ModTimeRamp : Mod, IUpdatableByPlayfield, IApplicableToClock, IApplicableToBeatmap { - public override Type[] IncompatibleMods => new[] { typeof(ModTimeAdjust) }; - - protected abstract double FinalRateAdjustment { get; } - } - - public abstract class ModTimeRamp : ModTimeRamp, IUpdatableByPlayfield, IApplicableToClock, IApplicableToBeatmap - where T : HitObject - { - private double finalRateTime; - - private double beginRampTime; - - private IAdjustableClock clock; - /// /// The point in the beatmap at which the final ramping rate should be reached. /// private const double final_rate_progress = 0.75f; + public override Type[] IncompatibleMods => new[] { typeof(ModTimeAdjust) }; + + protected abstract double FinalRateAdjustment { get; } + + private double finalRateTime; + private double beginRampTime; + private IAdjustableClock clock; + public virtual void ApplyToClock(IAdjustableClock clock) { this.clock = clock; @@ -44,7 +38,7 @@ namespace osu.Game.Rulesets.Mods applyAdjustment(1); } - public virtual void ApplyToBeatmap(Beatmap beatmap) + public virtual void ApplyToBeatmap(IBeatmap beatmap) { HitObject lastObject = beatmap.HitObjects.LastOrDefault(); diff --git a/osu.Game/Rulesets/Mods/ModWindDown.cs b/osu.Game/Rulesets/Mods/ModWindDown.cs index 5d71c8950b..b2e3abb59d 100644 --- a/osu.Game/Rulesets/Mods/ModWindDown.cs +++ b/osu.Game/Rulesets/Mods/ModWindDown.cs @@ -4,12 +4,10 @@ using System; using System.Linq; using osu.Framework.Graphics.Sprites; -using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mods { - public class ModWindDown : ModTimeRamp - where T : HitObject + public class ModWindDown : ModTimeRamp { public override string Name => "Wind Down"; public override string Acronym => "WD"; @@ -19,6 +17,6 @@ namespace osu.Game.Rulesets.Mods protected override double FinalRateAdjustment => -0.25; - public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindUp)).ToArray(); + public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindUp)).ToArray(); } } diff --git a/osu.Game/Rulesets/Mods/ModWindUp.cs b/osu.Game/Rulesets/Mods/ModWindUp.cs index aae85cec19..8df35a1de2 100644 --- a/osu.Game/Rulesets/Mods/ModWindUp.cs +++ b/osu.Game/Rulesets/Mods/ModWindUp.cs @@ -4,12 +4,10 @@ using System; using System.Linq; using osu.Framework.Graphics.Sprites; -using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mods { - public class ModWindUp : ModTimeRamp - where T : HitObject + public class ModWindUp : ModTimeRamp { public override string Name => "Wind Up"; public override string Acronym => "WU"; @@ -19,6 +17,6 @@ namespace osu.Game.Rulesets.Mods protected override double FinalRateAdjustment => 0.5; - public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindDown)).ToArray(); + public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindDown)).ToArray(); } } diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 52fba9cab3..faa6b98c86 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -278,7 +278,7 @@ namespace osu.Game.Rulesets.UI if (mods == null) return; - foreach (var mod in mods.OfType>()) + foreach (var mod in mods.OfType()) mod.ApplyToBeatmap(Beatmap); } From bc80fa11bbeee2b39174ec1b68132cc3a6468bfe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Aug 2019 12:41:46 +0900 Subject: [PATCH 2136/5608] Mode IApplicableToBeatmap application to WorkingBeatmap --- osu.Game/Beatmaps/WorkingBeatmap.cs | 3 +++ osu.Game/Rulesets/UI/DrawableRuleset.cs | 15 --------------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 949a2aab6f..baf921ddfc 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -141,6 +141,9 @@ namespace osu.Game.Beatmaps processor?.PostProcess(); + foreach (var mod in mods.OfType()) + mod.ApplyToBeatmap(Beatmap); + return converted; } diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index faa6b98c86..ac81fdc719 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -109,8 +109,6 @@ namespace osu.Game.Rulesets.UI Beatmap = (Beatmap)workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo, mods); - applyBeatmapMods(mods); - KeyBindingInputManager = CreateInputManager(); playfield = new Lazy(CreatePlayfield); @@ -269,19 +267,6 @@ namespace osu.Game.Rulesets.UI public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(this); - /// - /// Applies the active mods to the Beatmap. - /// - /// - private void applyBeatmapMods(IReadOnlyList mods) - { - if (mods == null) - return; - - foreach (var mod in mods.OfType()) - mod.ApplyToBeatmap(Beatmap); - } - /// /// Applies the active mods to this DrawableRuleset. /// From 0108700793069bd524b390e50e44ea7b00869247 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 31 Jul 2019 19:48:50 +0900 Subject: [PATCH 2137/5608] Make beatmap conversion test use WorkingBeatmap --- .../ManiaBeatmapConversionTest.cs | 39 ++++++++-- osu.Game/Beatmaps/WorkingBeatmap.cs | 10 ++- .../Tests/Beatmaps/BeatmapConversionTest.cs | 72 ++++++++++++++----- 3 files changed, 94 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index 6b95975059..51c7ba029a 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -35,11 +35,37 @@ namespace osu.Game.Rulesets.Mania.Tests }; } - protected override ManiaConvertMapping CreateConvertMapping() => new ManiaConvertMapping(Converter); + private readonly Dictionary rngSnapshots = new Dictionary(); + + protected override void OnConversionGenerated(HitObject original, IEnumerable result, IBeatmapConverter beatmapConverter) + { + base.OnConversionGenerated(original, result, beatmapConverter); + + rngSnapshots[original] = new RngSnapshot(beatmapConverter); + } + + protected override ManiaConvertMapping CreateConvertMapping(HitObject source) => new ManiaConvertMapping(rngSnapshots[source]); protected override Ruleset CreateRuleset() => new ManiaRuleset(); } + public class RngSnapshot + { + public readonly uint RandomW; + public readonly uint RandomX; + public readonly uint RandomY; + public readonly uint RandomZ; + + public RngSnapshot(IBeatmapConverter converter) + { + var maniaConverter = (ManiaBeatmapConverter)converter; + RandomW = maniaConverter.Random.W; + RandomX = maniaConverter.Random.X; + RandomY = maniaConverter.Random.Y; + RandomZ = maniaConverter.Random.Z; + } + } + public class ManiaConvertMapping : ConvertMapping, IEquatable { public uint RandomW; @@ -51,13 +77,12 @@ namespace osu.Game.Rulesets.Mania.Tests { } - public ManiaConvertMapping(IBeatmapConverter converter) + public ManiaConvertMapping(RngSnapshot snapshot) { - var maniaConverter = (ManiaBeatmapConverter)converter; - RandomW = maniaConverter.Random.W; - RandomX = maniaConverter.Random.X; - RandomY = maniaConverter.Random.Y; - RandomZ = maniaConverter.Random.Z; + RandomW = snapshot.RandomW; + RandomX = snapshot.RandomX; + RandomY = snapshot.RandomY; + RandomZ = snapshot.RandomZ; } public bool Equals(ManiaConvertMapping other) => other != null && RandomW == other.RandomW && RandomX == other.RandomX && RandomY == other.RandomY && RandomZ == other.RandomZ; diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index baf921ddfc..6b3a21a2c1 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -89,6 +89,14 @@ namespace osu.Game.Beatmaps return path; } + /// + /// Creates a to convert a for a specified . + /// + /// The to be converted. + /// The for which should be converted. + /// The applicable . + protected virtual IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) => ruleset.CreateBeatmapConverter(beatmap); + /// /// Constructs a playable from using the applicable converters for a specific . /// @@ -104,7 +112,7 @@ namespace osu.Game.Beatmaps { var rulesetInstance = ruleset.CreateInstance(); - IBeatmapConverter converter = rulesetInstance.CreateBeatmapConverter(Beatmap); + IBeatmapConverter converter = CreateBeatmapConverter(Beatmap, rulesetInstance); // Check if the beatmap can be converted if (!converter.CanConvert) diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 6a5e17eb38..1f2d457624 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -4,13 +4,16 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Reflection; using Newtonsoft.Json; using NUnit.Framework; -using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Audio.Track; +using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; namespace osu.Game.Tests.Beatmaps @@ -25,8 +28,6 @@ namespace osu.Game.Tests.Beatmaps protected abstract string ResourceAssembly { get; } - protected IBeatmapConverter Converter { get; private set; } - protected void Test(string name) { var ourResult = convert(name); @@ -98,26 +99,33 @@ namespace osu.Game.Tests.Beatmaps var rulesetInstance = CreateRuleset(); beatmap.BeatmapInfo.Ruleset = beatmap.BeatmapInfo.RulesetID == rulesetInstance.RulesetInfo.ID ? rulesetInstance.RulesetInfo : new RulesetInfo(); - Converter = rulesetInstance.CreateBeatmapConverter(beatmap); + var converterResult = new Dictionary>(); - var result = new ConvertResult(); - - Converter.ObjectConverted += (orig, converted) => + var working = new ConversionWorkingBeatmap(beatmap) { - converted.ForEach(h => h.ApplyDefaults(beatmap.ControlPointInfo, beatmap.BeatmapInfo.BaseDifficulty)); - - var mapping = CreateConvertMapping(); - mapping.StartTime = orig.StartTime; - - foreach (var obj in converted) - mapping.Objects.AddRange(CreateConvertValue(obj)); - result.Mappings.Add(mapping); + ConversionGenerated = (o, r, c) => + { + converterResult[o] = r; + OnConversionGenerated(o, r, c); + } }; - IBeatmap convertedBeatmap = Converter.Convert(); - rulesetInstance.CreateBeatmapProcessor(convertedBeatmap)?.PostProcess(); + working.GetPlayableBeatmap(rulesetInstance.RulesetInfo, Array.Empty()); - return result; + return new ConvertResult + { + Mappings = converterResult.Select(r => + { + var mapping = CreateConvertMapping(r.Key); + mapping.StartTime = r.Key.StartTime; + mapping.Objects.AddRange(r.Value.SelectMany(CreateConvertValue)); + return mapping; + }).ToList() + }; + } + + protected virtual void OnConversionGenerated(HitObject original, IEnumerable result, IBeatmapConverter beatmapConverter) + { } private ConvertResult read(string name) @@ -154,7 +162,7 @@ namespace osu.Game.Tests.Beatmaps /// This should be used to validate the integrity of the conversion process after a conversion has occurred. /// /// - protected virtual TConvertMapping CreateConvertMapping() => new TConvertMapping(); + protected virtual TConvertMapping CreateConvertMapping(HitObject source) => new TConvertMapping(); /// public ResumeOverlay ResumeOverlay { get; protected set; } + /// + /// Returns first available provided by a . + /// + [CanBeNull] + public HitWindows FirstAvailableHitWindows + { + get + { + foreach (var h in Objects) + { + if (h.HitWindows != null) + return h.HitWindows; + + foreach (var n in h.NestedHitObjects) + if (n.HitWindows != null) + return n.HitWindows; + } + + return null; + } + } + protected virtual ResumeOverlay CreateResumeOverlay() => null; /// diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index eac45f9214..eee7235a6e 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -259,9 +258,7 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20, Right = 10 }, }; - protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay( - scoreProcessor, - drawableRuleset.Objects.Concat(drawableRuleset.Objects.SelectMany(h => h.NestedHitObjects)).FirstOrDefault(h => h.HitWindows != null)?.HitWindows); + protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset.FirstAvailableHitWindows); protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); From d1cdf49dd51a6d5b66f006abb2afc5417e04c3e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 14:21:54 +0900 Subject: [PATCH 2748/5608] Revert SkinnableSprite lookups to old behaviour --- osu.Game.Rulesets.Catch/CatchSkinComponent.cs | 2 +- osu.Game.Rulesets.Catch/CatchSkinComponents.cs | 1 - osu.Game.Rulesets.Catch/UI/CatcherSprite.cs | 2 +- .../Objects/Drawables/Pieces/ApproachCircle.cs | 2 +- osu.Game/Skinning/SkinnableSprite.cs | 16 ++++++++++++++-- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchSkinComponent.cs b/osu.Game.Rulesets.Catch/CatchSkinComponent.cs index 0a3e43dcfc..8bf53e53e3 100644 --- a/osu.Game.Rulesets.Catch/CatchSkinComponent.cs +++ b/osu.Game.Rulesets.Catch/CatchSkinComponent.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Catch { } - protected override string RulesetPrefix => CatchRuleset.SHORT_NAME; + protected override string RulesetPrefix => "catch"; // todo: use CatchRuleset.SHORT_NAME; protected override string ComponentName => Component.ToString().ToLower(); } diff --git a/osu.Game.Rulesets.Catch/CatchSkinComponents.cs b/osu.Game.Rulesets.Catch/CatchSkinComponents.cs index c03fe42af7..7e482d4045 100644 --- a/osu.Game.Rulesets.Catch/CatchSkinComponents.cs +++ b/osu.Game.Rulesets.Catch/CatchSkinComponents.cs @@ -5,6 +5,5 @@ namespace osu.Game.Rulesets.Catch { public enum CatchSkinComponents { - Catcher } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherSprite.cs b/osu.Game.Rulesets.Catch/UI/CatcherSprite.cs index 1c2fe3517a..e3c6c93d01 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherSprite.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherSprite.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.UI [BackgroundDependencyLoader] private void load() { - InternalChild = new SkinnableSprite(new CatchSkinComponent(CatchSkinComponents.Catcher)) + InternalChild = new SkinnableSprite("Gameplay/catch/fruit-catcher-idle") { RelativeSizeAxes = Axes.Both, Anchor = Anchor.TopCentre, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs index c17c276205..1b474f265c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private class SkinnableApproachCircle : SkinnableSprite { public SkinnableApproachCircle() - : base(new OsuSkinComponent(OsuSkinComponents.ApproachCircle)) + : base("Gameplay/osu/approachcircle") { } diff --git a/osu.Game/Skinning/SkinnableSprite.cs b/osu.Game/Skinning/SkinnableSprite.cs index 0081aef520..4b78493e97 100644 --- a/osu.Game/Skinning/SkinnableSprite.cs +++ b/osu.Game/Skinning/SkinnableSprite.cs @@ -19,11 +19,23 @@ namespace osu.Game.Skinning [Resolved] private TextureStore textures { get; set; } - public SkinnableSprite(ISkinComponent component, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) - : base(component, allowFallback, confineMode) + public SkinnableSprite(string textureName, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + : base(new SpriteComponent(textureName), allowFallback, confineMode) { } protected override Drawable CreateDefault(ISkinComponent component) => new Sprite { Texture = textures.Get(component.LookupName) }; + + private class SpriteComponent : ISkinComponent + { + private readonly string textureName; + + public SpriteComponent(string textureName) + { + this.textureName = textureName; + } + + public string LookupName => textureName; + } } } From bebc3309ced768307cac8398cebf804055dbf79c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 17:57:34 +0900 Subject: [PATCH 2749/5608] Refactor skin configuration to be infinitely extensible --- .../TestSceneCatcher.cs | 4 +- .../TestSceneSkinFallbacks.cs | 2 + .../Objects/Drawables/DrawableSlider.cs | 9 ++-- .../Objects/Drawables/Pieces/SliderBall.cs | 3 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../Skinning/LegacySliderBall.cs | 2 +- ...acySkin.cs => OsuLegacySkinTransformer.cs} | 51 +++++++++--------- .../Skinning/OsuSkinColour.cs | 12 +++++ .../Skinning/OsuSkinConfiguration.cs | 14 +++++ osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs | 3 +- .../Gameplay/TestSceneSkinnableDrawable.cs | 10 ++-- .../Objects/Drawables/DrawableHitObject.cs | 6 ++- osu.Game/Screens/Menu/LogoVisualisation.cs | 2 +- osu.Game/Screens/Menu/MenuSideFlashes.cs | 2 +- osu.Game/Skinning/DefaultSkin.cs | 5 +- osu.Game/Skinning/DefaultSkinConfiguration.cs | 4 -- osu.Game/Skinning/GameplaySkinComponent.cs | 2 +- osu.Game/Skinning/GlobalSkinColour.cs | 10 ++++ osu.Game/Skinning/GlobalSkinConfiguration.cs | 10 ++++ osu.Game/Skinning/ISkin.cs | 4 +- osu.Game/Skinning/LegacySkin.cs | 43 +++++++++++++++ osu.Game/Skinning/LegacySkinDecoder.cs | 54 +++++++------------ osu.Game/Skinning/Skin.cs | 8 +-- osu.Game/Skinning/SkinConfigManager.cs | 16 ++++++ osu.Game/Skinning/SkinConfiguration.cs | 10 +--- osu.Game/Skinning/SkinCustomColourLookup.cs | 15 ++++++ osu.Game/Skinning/SkinManager.cs | 4 +- osu.Game/Skinning/SkinProvidingContainer.cs | 14 +++-- 28 files changed, 214 insertions(+), 107 deletions(-) rename osu.Game.Rulesets.Osu/Skinning/{OsuLegacySkin.cs => OsuLegacySkinTransformer.cs} (70%) create mode 100644 osu.Game.Rulesets.Osu/Skinning/OsuSkinColour.cs create mode 100644 osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs create mode 100644 osu.Game/Skinning/GlobalSkinColour.cs create mode 100644 osu.Game/Skinning/GlobalSkinConfiguration.cs create mode 100644 osu.Game/Skinning/SkinConfigManager.cs create mode 100644 osu.Game/Skinning/SkinCustomColourLookup.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index c89cd95f36..6a4294a178 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -14,6 +14,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osuTK.Graphics; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics.Textures; using osu.Game.Audio; @@ -99,8 +100,7 @@ namespace osu.Game.Rulesets.Catch.Tests public Texture GetTexture(string componentName) => throw new NotImplementedException(); - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => - throw new NotImplementedException(); + public IBindable GetConfig(TLookup lookup) => throw new NotImplementedException(); } } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index fe73e7c861..02c65db6ad 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; @@ -135,6 +136,7 @@ namespace osu.Game.Rulesets.Osu.Tests public SampleChannel GetSample(ISampleInfo sampleInfo) => null; public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => default; + public IBindable GetConfig(TLookup lookup) => null; public event Action SourceChanged; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 1749ea1f60..00c953c393 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -12,6 +12,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Configuration; +using osu.Game.Rulesets.Osu.Skinning; using osu.Game.Rulesets.Scoring; using osuTK.Graphics; using osu.Game.Skinning; @@ -166,12 +167,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.SkinChanged(skin, allowFallback); - Body.BorderSize = skin.GetValue(s => s.SliderBorderSize) ?? SliderBody.DEFAULT_BORDER_SIZE; - sliderPathRadius = skin.GetValue(s => s.SliderPathRadius) ?? OsuHitObject.OBJECT_RADIUS; + Body.BorderSize = skin.GetConfig(OsuSkinConfiguration.SliderBorderSize)?.Value ?? SliderBody.DEFAULT_BORDER_SIZE; + sliderPathRadius = skin.GetConfig(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS; updatePathRadius(); - Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? AccentColour.Value; - Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Color4.White; + Body.AccentColour = skin.GetConfig(OsuSkinColour.SliderTrackOverride)?.Value ?? AccentColour.Value; + Body.BorderColour = skin.GetConfig(OsuSkinColour.SliderBorder)?.Value ?? Color4.White; } private void updatePathRadius() => Body.PathRadius = slider.Scale * sliderPathRadius; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 7c871c6ccd..ef7b077480 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -11,6 +11,7 @@ using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Skinning; using osuTK.Graphics; using osu.Game.Skinning; using osuTK; @@ -218,7 +219,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { RelativeSizeAxes = Axes.Both; - float radius = skin.GetValue(s => s.SliderPathRadius) ?? OsuHitObject.OBJECT_RADIUS; + float radius = skin.GetConfig(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS; InternalChild = new CircularContainer { diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 27899ab56e..ceb9ed9343 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu public override RulesetSettingsSubsection CreateSettings() => new OsuSettingsSubsection(this); - public override ISkin CreateLegacySkinProvider(ISkinSource source) => new OsuLegacySkin(source); + public override ISkin CreateLegacySkinProvider(ISkinSource source) => new OsuLegacySkinTransformer(source); public override int? LegacyID => 0; diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs index ec838c596d..81c02199d0 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Skinning [BackgroundDependencyLoader] private void load(ISkinSource skin, DrawableHitObject drawableObject) { - animationContent.Colour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Color4.White; + animationContent.Colour = skin.GetConfig(OsuSkinColour.SliderBall)?.Value ?? Color4.White; InternalChildren = new[] { diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs similarity index 70% rename from osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs rename to osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index e3e302b81c..284259705a 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -3,21 +3,19 @@ using System; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Game.Audio; using osu.Game.Skinning; using osuTK; -using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning { - public class OsuLegacySkin : ISkin + public class OsuLegacySkinTransformer : ISkin { private readonly ISkin source; - private Lazy configuration; - private Lazy hasHitCircle; /// @@ -27,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Skinning /// private const float legacy_circle_radius = 64 - 5; - public OsuLegacySkin(ISkinSource source) + public OsuLegacySkinTransformer(ISkinSource source) { this.source = source; @@ -37,21 +35,6 @@ namespace osu.Game.Rulesets.Osu.Skinning private void sourceChanged() { - // these need to be lazy in order to ensure they aren't called before the dependencies have been loaded into our source. - configuration = new Lazy(() => - { - var config = new SkinConfiguration(); - if (hasHitCircle.Value) - config.SliderPathRadius = legacy_circle_radius; - - // defaults should only be applied for non-beatmap skins (which are parsed via this constructor). - config.CustomColours["SliderBall"] = - source.GetValue(s => s.CustomColours.TryGetValue("SliderBall", out var val) ? val : (Color4?)null) - ?? new Color4(2, 170, 255, 255); - - return config; - }); - hasHitCircle = new Lazy(() => source.GetTexture("hitcircle") != null); } @@ -96,8 +79,8 @@ namespace osu.Game.Rulesets.Osu.Skinning return null; case OsuSkinComponents.HitCircleText: - string font = GetValue(config => config.HitCircleFont); - var overlap = GetValue(config => config.HitCircleOverlap); + var font = GetConfig(OsuSkinConfiguration.HitCircleFont)?.Value ?? "default"; + var overlap = GetConfig(OsuSkinConfiguration.HitCircleOverlap)?.Value ?? 0; return !hasFont(font) ? null @@ -116,13 +99,27 @@ namespace osu.Game.Rulesets.Osu.Skinning public SampleChannel GetSample(ISampleInfo sample) => source.GetSample(sample); - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration + public IBindable GetConfig(TLookup lookup) { - TValue val; - if (configuration.Value is TConfiguration conf && (val = query.Invoke(conf)) != null) - return val; + switch (lookup) + { + case OsuSkinColour colour: + return source.GetConfig(new SkinCustomColourLookup(colour)); - return source.GetValue(query); + case OsuSkinConfiguration osuLookup: + switch (osuLookup) + { + case OsuSkinConfiguration.SliderPathRadius: + if (hasHitCircle.Value) + return new BindableFloat(legacy_circle_radius) as Bindable; + + break; + } + + break; + } + + return source.GetConfig(lookup); } private bool hasFont(string fontName) => source.GetTexture($"{fontName}-0") != null; diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuSkinColour.cs b/osu.Game.Rulesets.Osu/Skinning/OsuSkinColour.cs new file mode 100644 index 0000000000..4e6d3ef0e4 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/OsuSkinColour.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Osu.Skinning +{ + public enum OsuSkinColour + { + SliderTrackOverride, + SliderBorder, + SliderBall + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs new file mode 100644 index 0000000000..a6b87150ae --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.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. + +namespace osu.Game.Rulesets.Osu.Skinning +{ + public enum OsuSkinConfiguration + { + HitCircleFont, + HitCircleOverlap, + SliderBorderSize, + SliderPathRadius, + CursorExpand, + } +} diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index 869c27dcac..ac641ecfbc 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Rulesets.Osu.Skinning; using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -38,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor protected override void SkinChanged(ISkinSource skin, bool allowFallback) { - cursorExpand = skin.GetValue(s => s.CursorExpand ?? true); + cursorExpand = skin.GetConfig(OsuSkinConfiguration.CursorExpand)?.Value ?? true; } [BackgroundDependencyLoader] diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs index ee5552c6e0..91ee16cab7 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs @@ -6,6 +6,7 @@ using System.Globalization; using System.Linq; using NUnit.Framework; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -137,7 +138,8 @@ namespace osu.Game.Tests.Visual.Gameplay { public new Drawable Drawable => base.Drawable; - public ExposedSkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + public ExposedSkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, + ConfineMode confineMode = ConfineMode.ScaleDownToFit) : base(new TestSkinComponent(name), defaultImplementation, allowFallback, confineMode) { } @@ -256,7 +258,7 @@ namespace osu.Game.Tests.Visual.Gameplay public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException(); - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); + public IBindable GetConfig(TLookup lookup) => throw new NotImplementedException(); } private class SecondarySource : ISkin @@ -267,7 +269,7 @@ namespace osu.Game.Tests.Visual.Gameplay public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException(); - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); + public IBindable GetConfig(TLookup lookup) => throw new NotImplementedException(); } private class SkinSourceContainer : Container, ISkin @@ -278,7 +280,7 @@ namespace osu.Game.Tests.Visual.Gameplay public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException(); - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); + public IBindable GetConfig(TLookup lookup) => throw new NotImplementedException(); } private class TestSkinComponent : ISkinComponent diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 1a224b2cea..a6d0aad880 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -241,7 +241,11 @@ namespace osu.Game.Rulesets.Objects.Drawables base.SkinChanged(skin, allowFallback); if (HitObject is IHasComboInformation combo) - AccentColour.Value = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; + { + var comboColours = skin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value; + + AccentColour.Value = comboColours?.Count > 0 ? comboColours[combo.ComboIndex % comboColours.Count] : Color4.White; + } } /// diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 6984959e9c..59ab6ad265 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -122,7 +122,7 @@ namespace osu.Game.Screens.Menu Color4 defaultColour = Color4.White.Opacity(0.2f); if (user.Value?.IsSupporter ?? false) - AccentColour = skin.Value.GetValue(s => s.CustomColours.ContainsKey("MenuGlow") ? s.CustomColours["MenuGlow"] : (Color4?)null) ?? defaultColour; + AccentColour = skin.Value.GetConfig(GlobalSkinColour.MenuGlow)?.Value ?? defaultColour; else AccentColour = defaultColour; } diff --git a/osu.Game/Screens/Menu/MenuSideFlashes.cs b/osu.Game/Screens/Menu/MenuSideFlashes.cs index 393964561c..55a6a33e89 100644 --- a/osu.Game/Screens/Menu/MenuSideFlashes.cs +++ b/osu.Game/Screens/Menu/MenuSideFlashes.cs @@ -112,7 +112,7 @@ namespace osu.Game.Screens.Menu Color4 baseColour = colours.Blue; if (user.Value?.IsSupporter ?? false) - baseColour = skin.Value.GetValue(s => s.CustomColours.ContainsKey("MenuGlow") ? s.CustomColours["MenuGlow"] : (Color4?)null) ?? baseColour; + baseColour = skin.Value.GetConfig(GlobalSkinColour.MenuGlow)?.Value ?? baseColour; // linear colour looks better in this case, so let's use it for now. Color4 gradientDark = baseColour.Opacity(0).ToLinear(); diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs index 9eda5d597a..4dee70a47f 100644 --- a/osu.Game/Skinning/DefaultSkin.cs +++ b/osu.Game/Skinning/DefaultSkin.cs @@ -1,7 +1,8 @@ -// 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.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Game.Audio; @@ -21,5 +22,7 @@ namespace osu.Game.Skinning public override Texture GetTexture(string componentName) => null; public override SampleChannel GetSample(ISampleInfo sampleInfo) => null; + + public override IBindable GetConfig(TLookup lookup) => null; } } diff --git a/osu.Game/Skinning/DefaultSkinConfiguration.cs b/osu.Game/Skinning/DefaultSkinConfiguration.cs index 722b35f102..f52fac6077 100644 --- a/osu.Game/Skinning/DefaultSkinConfiguration.cs +++ b/osu.Game/Skinning/DefaultSkinConfiguration.cs @@ -12,8 +12,6 @@ namespace osu.Game.Skinning { public DefaultSkinConfiguration() { - HitCircleFont = "default"; - ComboColours.AddRange(new[] { new Color4(17, 136, 170, 255), @@ -21,8 +19,6 @@ namespace osu.Game.Skinning new Color4(204, 102, 0, 255), new Color4(121, 9, 13, 255) }); - - CursorExpand = true; } } } diff --git a/osu.Game/Skinning/GameplaySkinComponent.cs b/osu.Game/Skinning/GameplaySkinComponent.cs index 8695b3d720..2aa380fa90 100644 --- a/osu.Game/Skinning/GameplaySkinComponent.cs +++ b/osu.Game/Skinning/GameplaySkinComponent.cs @@ -5,7 +5,7 @@ using System.Linq; namespace osu.Game.Skinning { - public class GameplaySkinComponent : ISkinComponent where T : struct + public class GameplaySkinComponent : ISkinComponent { public readonly T Component; diff --git a/osu.Game/Skinning/GlobalSkinColour.cs b/osu.Game/Skinning/GlobalSkinColour.cs new file mode 100644 index 0000000000..d039be98ce --- /dev/null +++ b/osu.Game/Skinning/GlobalSkinColour.cs @@ -0,0 +1,10 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Skinning +{ + public enum GlobalSkinColour + { + MenuGlow + } +} diff --git a/osu.Game/Skinning/GlobalSkinConfiguration.cs b/osu.Game/Skinning/GlobalSkinConfiguration.cs new file mode 100644 index 0000000000..66dc9a9395 --- /dev/null +++ b/osu.Game/Skinning/GlobalSkinConfiguration.cs @@ -0,0 +1,10 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Skinning +{ + public enum GlobalSkinConfiguration + { + ComboColours + } +} diff --git a/osu.Game/Skinning/ISkin.cs b/osu.Game/Skinning/ISkin.cs index bc1ae634c9..841ff3d357 100644 --- a/osu.Game/Skinning/ISkin.cs +++ b/osu.Game/Skinning/ISkin.cs @@ -1,8 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Game.Audio; @@ -20,6 +20,6 @@ namespace osu.Game.Skinning SampleChannel GetSample(ISampleInfo sampleInfo); - TValue GetValue(Func query) where TConfiguration : SkinConfiguration; + IBindable GetConfig(TLookup lookup); } } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 535471f455..53f7c54003 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -1,10 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using System.IO; using System.Linq; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; @@ -48,6 +50,47 @@ namespace osu.Game.Skinning Samples?.Dispose(); } + public override IBindable GetConfig(TLookup lookup) + { + switch (lookup) + { + case GlobalSkinConfiguration global: + switch (global) + { + case GlobalSkinConfiguration.ComboColours: + return new Bindable>(Configuration.ComboColours) as IBindable; + } + + break; + + case GlobalSkinColour colour: + return getCustomColour(colour.ToString()) as IBindable; + + case SkinCustomColourLookup customColour: + return getCustomColour(customColour.Lookup.ToString()) as IBindable; + + default: + try + { + if (Configuration.ConfigDictionary.TryGetValue(lookup.ToString(), out var val)) + { + var bindable = new Bindable(); + bindable.Parse(val); + return bindable; + } + } + catch + { + } + + break; + } + + return null; + } + + private IBindable getCustomColour(string lookup) => Configuration.CustomColours.TryGetValue(lookup, out var col) ? new Bindable(col) : null; + public override Drawable GetDrawableComponent(ISkinComponent component) { switch (component) diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 0160755eed..1912c4cd05 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -14,47 +14,31 @@ namespace osu.Game.Skinning protected override void ParseLine(DefaultSkinConfiguration skin, Section section, string line) { - line = StripComments(line); - - var pair = SplitKeyVal(line); - - switch (section) + if (section != Section.Colours) { - case Section.General: - switch (pair.Key) - { - case @"Name": - skin.SkinInfo.Name = pair.Value; - break; + line = StripComments(line); - case @"Author": - skin.SkinInfo.Creator = pair.Value; - break; + var pair = SplitKeyVal(line); - case @"CursorExpand": - skin.CursorExpand = pair.Value != "0"; - break; + switch (section) + { + case Section.General: + switch (pair.Key) + { + case @"Name": + skin.SkinInfo.Name = pair.Value; + return; - case @"SliderBorderSize": - skin.SliderBorderSize = Parsing.ParseFloat(pair.Value); - break; - } + case @"Author": + skin.SkinInfo.Creator = pair.Value; + return; + } - break; + break; + } - case Section.Fonts: - switch (pair.Key) - { - case "HitCirclePrefix": - skin.HitCircleFont = pair.Value; - break; - - case "HitCircleOverlap": - skin.HitCircleOverlap = int.Parse(pair.Value); - break; - } - - break; + if (!string.IsNullOrEmpty(pair.Key)) + skin.ConfigDictionary[$"{section}/{pair.Key}"] = pair.Value; } base.ParseLine(skin, section, line); diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 299f257e57..fa4aebd8a5 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -1,8 +1,9 @@ -// 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; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Game.Audio; @@ -13,7 +14,7 @@ namespace osu.Game.Skinning { public readonly SkinInfo SkinInfo; - public virtual SkinConfiguration Configuration { get; protected set; } + public SkinConfiguration Configuration { get; protected set; } public abstract Drawable GetDrawableComponent(ISkinComponent componentName); @@ -21,8 +22,7 @@ namespace osu.Game.Skinning public abstract Texture GetTexture(string componentName); - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration - => Configuration is TConfiguration conf ? query.Invoke(conf) : default; + public abstract IBindable GetConfig(TLookup lookup); protected Skin(SkinInfo skin) { diff --git a/osu.Game/Skinning/SkinConfigManager.cs b/osu.Game/Skinning/SkinConfigManager.cs new file mode 100644 index 0000000000..896444d1d2 --- /dev/null +++ b/osu.Game/Skinning/SkinConfigManager.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Configuration; + +namespace osu.Game.Skinning +{ + public class SkinConfigManager : ConfigManager where T : struct + { + protected override void PerformLoad() + { + } + + protected override bool PerformSave() => false; + } +} diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index d585c58ef1..54aac86e3c 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -18,14 +18,6 @@ namespace osu.Game.Skinning public Dictionary CustomColours { get; set; } = new Dictionary(); - public string HitCircleFont { get; set; } - - public int HitCircleOverlap { get; set; } - - public float? SliderBorderSize { get; set; } - - public float? SliderPathRadius { get; set; } - - public bool? CursorExpand { get; set; } + public readonly Dictionary ConfigDictionary = new Dictionary(); } } diff --git a/osu.Game/Skinning/SkinCustomColourLookup.cs b/osu.Game/Skinning/SkinCustomColourLookup.cs new file mode 100644 index 0000000000..b8e5ac9b53 --- /dev/null +++ b/osu.Game/Skinning/SkinCustomColourLookup.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. + +namespace osu.Game.Skinning +{ + public class SkinCustomColourLookup + { + public readonly object Lookup; + + public SkinCustomColourLookup(object lookup) + { + Lookup = lookup; + } + } +} diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index a55a128dff..aa3b3981c2 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.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; @@ -131,6 +131,6 @@ namespace osu.Game.Skinning public SampleChannel GetSample(ISampleInfo sampleInfo) => CurrentSkin.Value.GetSample(sampleInfo); - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => CurrentSkin.Value.GetValue(query); + public IBindable GetConfig(TLookup lookup) => CurrentSkin.Value.GetConfig(lookup); } } diff --git a/osu.Game/Skinning/SkinProvidingContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs index 85a80655ea..ef7f5f381b 100644 --- a/osu.Game/Skinning/SkinProvidingContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; @@ -64,13 +65,16 @@ namespace osu.Game.Skinning return fallbackSource?.GetSample(sampleInfo); } - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration + public IBindable GetConfig(TLookup lookup) { - TValue val; - if (AllowConfigurationLookup && skin != null && (val = skin.GetValue(query)) != null) - return val; + if (AllowConfigurationLookup && skin != null) + { + var bindable = skin.GetConfig(lookup); + if (bindable != null) + return bindable; + } - return fallbackSource == null ? default : fallbackSource.GetValue(query); + return fallbackSource?.GetConfig(lookup); } protected virtual void TriggerSourceChanged() => SourceChanged?.Invoke(); From 097012dc95c05e829864d451b35be143844cdc7e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 18:05:16 +0900 Subject: [PATCH 2750/5608] Move slider ball colouring to DefaultLegacySkin for now --- osu.Game/Skinning/DefaultLegacySkin.cs | 2 ++ osu.Game/Skinning/LegacySkin.cs | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index b35c9c7b97..98f158c725 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -3,6 +3,7 @@ using osu.Framework.Audio; using osu.Framework.IO.Stores; +using osuTK.Graphics; namespace osu.Game.Skinning { @@ -11,6 +12,7 @@ namespace osu.Game.Skinning public DefaultLegacySkin(IResourceStore storage, AudioManager audioManager) : base(Info, storage, audioManager, string.Empty) { + Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); } public static SkinInfo Info { get; } = new SkinInfo diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 53f7c54003..5f0afae075 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -25,8 +25,6 @@ namespace osu.Game.Skinning public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini") { - // defaults should only be applied for non-beatmap skins (which are parsed via this constructor). - if (!Configuration.CustomColours.ContainsKey("SliderBall")) Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); } protected LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager, string filename) From 352fd3efdaa1fcddd2a19bc87287134b02ebed97 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2019 09:18:24 +0000 Subject: [PATCH 2751/5608] Bump ppy.osu.Game.Resources from 2019.903.0 to 2019.903.1 Bumps [ppy.osu.Game.Resources](https://github.com/ppy/osu-resources) from 2019.903.0 to 2019.903.1. - [Release notes](https://github.com/ppy/osu-resources/releases) - [Commits](https://github.com/ppy/osu-resources/compare/2019.903.0...2019.903.1) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 743508baf8..96706f2bdc 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -60,7 +60,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 03207dfdf7..ca69bb2295 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index ec76ceaf95..86a2a40940 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -117,7 +117,7 @@ - + From 2f74ef513140bfcd0e8b69c16a4d0731f87b5790 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 18:21:57 +0900 Subject: [PATCH 2752/5608] Add test for changing of a source --- .../Gameplay/TestSceneSkinnableDrawable.cs | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs index ee5552c6e0..80015099cf 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs @@ -5,6 +5,7 @@ using System; using System.Globalization; using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -133,6 +134,48 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("skinchanged only called once", () => consumer.SkinChangedCount == 1); } + [Test] + public void TestSwitchOff() + { + SkinConsumer consumer = null; + SwitchableSkinProvidingContainer target = null; + + AddStep("setup layout", () => + { + Child = new SkinSourceContainer + { + RelativeSizeAxes = Axes.Both, + Child = target = new SwitchableSkinProvidingContainer(new SecondarySource()) + { + RelativeSizeAxes = Axes.Both, + } + }; + }); + + AddStep("add permissive", () => target.Add(consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation"), source => true))); + AddAssert("consumer using override source", () => consumer.Drawable is SecondarySourceBox); + AddStep("disable", () => target.Disable()); + AddAssert("consumer using base source", () => consumer.Drawable is BaseSourceBox); + } + + private class SwitchableSkinProvidingContainer : SkinProvidingContainer + { + private bool allow = true; + + protected override bool AllowDrawableLookup(ISkinComponent component) => allow; + + public void Disable() + { + allow = false; + TriggerSourceChanged(); + } + + public SwitchableSkinProvidingContainer(ISkin skin) + : base(skin) + { + } + } + private class ExposedSkinnableDrawable : SkinnableDrawable { public new Drawable Drawable => base.Drawable; @@ -270,7 +313,8 @@ namespace osu.Game.Tests.Visual.Gameplay public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); } - private class SkinSourceContainer : Container, ISkin + [Cached(typeof(ISkinSource))] + private class SkinSourceContainer : Container, ISkinSource { public Drawable GetDrawableComponent(ISkinComponent componentName) => new BaseSourceBox(); @@ -279,6 +323,8 @@ namespace osu.Game.Tests.Visual.Gameplay public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException(); public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); + + public event Action SourceChanged; } private class TestSkinComponent : ISkinComponent From 002de80c30b2f65eb842e8089382ac74cf2e1964 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 18:30:22 +0900 Subject: [PATCH 2753/5608] Add xmldoc to ISkin --- osu.Game/Skinning/ISkin.cs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/osu.Game/Skinning/ISkin.cs b/osu.Game/Skinning/ISkin.cs index 841ff3d357..cb2a379b8e 100644 --- a/osu.Game/Skinning/ISkin.cs +++ b/osu.Game/Skinning/ISkin.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 JetBrains.Annotations; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -14,12 +15,36 @@ namespace osu.Game.Skinning /// public interface ISkin { + /// + /// Retrieve a component implementation. + /// + /// The requested component. + /// A drawable representation for the requested component, or null if unavailable. + [CanBeNull] Drawable GetDrawableComponent(ISkinComponent component); + /// + /// Retrieve a . + /// + /// The requested texture. + /// A matching texture, or null if unavailable. + [CanBeNull] Texture GetTexture(string componentName); + /// + /// Retrieve a . + /// + /// The requested sample. + /// A matching sample channel, or null if unavailable. + [CanBeNull] SampleChannel GetSample(ISampleInfo sampleInfo); + /// + /// Retrieve a configuration value. + /// + /// The requested configuration value. + /// A matching value boxed in an , or null if unavailable. + [CanBeNull] IBindable GetConfig(TLookup lookup); } } From f58ca823986f79491946fd4fe3394ec9fbd4afa1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 18:56:01 +0900 Subject: [PATCH 2754/5608] Don't include section for now --- osu.Game/Skinning/LegacySkinDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 1912c4cd05..e97664e75e 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -38,7 +38,7 @@ namespace osu.Game.Skinning } if (!string.IsNullOrEmpty(pair.Key)) - skin.ConfigDictionary[$"{section}/{pair.Key}"] = pair.Value; + skin.ConfigDictionary[pair.Key] = pair.Value; } base.ParseLine(skin, section, line); From 343af28ed578cc247ba842c9983d72e4dce138a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 18:59:11 +0900 Subject: [PATCH 2755/5608] Add extra legacy skin parsing tests --- osu.Game.Tests/Resources/skin.ini | 1 + osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/osu.Game.Tests/Resources/skin.ini b/osu.Game.Tests/Resources/skin.ini index 0e5737b4ea..7f7f0b32a6 100644 --- a/osu.Game.Tests/Resources/skin.ini +++ b/osu.Game.Tests/Resources/skin.ini @@ -1,5 +1,6 @@ [General] Name: test skin +TestLookup: TestValue [Colours] Combo1 : 142,199,255 diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 24ef9e4535..8bd846518b 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -41,5 +41,20 @@ namespace osu.Game.Tests.Skins Assert.AreEqual(expectedColors[i], comboColors[i]); } } + + [Test] + public void TestDecodeGeneral() + { + var decoder = new LegacySkinDecoder(); + + using (var resStream = TestResources.OpenResource("skin.ini")) + using (var stream = new StreamReader(resStream)) + { + var config = decoder.Decode(stream); + + Assert.AreEqual("test skin", config.SkinInfo.Name); + Assert.AreEqual("TestValue", config.ConfigDictionary["TestLookup"]); + } + } } } From 299d528654f823689e14ffc6fb56c9f2db55ae5f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 19:20:23 +0900 Subject: [PATCH 2756/5608] Simplify implementation --- osu.Game/Graphics/UserInterface/HoverClickSounds.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index e64b9259f1..38e6a82bab 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -36,11 +36,9 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnMouseUp(MouseUpEvent e) { - bool shouldPlayEffect = buttons.Contains(e.Button); - // examine the button pressed first for short-circuiting - // in most usages it is more likely that another button was pressed than that the cursor left the drawable bounds - if (shouldPlayEffect && Contains(e.ScreenSpaceMousePosition)) + if (buttons.Contains(e.Button) && Contains(e.ScreenSpaceMousePosition)) sampleClick?.Play(); + return base.OnMouseUp(e); } From e98059267d4348a92e4d16fe6b75d9ebe45e3912 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 19:21:24 +0900 Subject: [PATCH 2757/5608] Improve xmldoc --- osu.Game/Graphics/UserInterface/HoverClickSounds.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index 38e6a82bab..1fb73efa65 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -21,12 +21,12 @@ namespace osu.Game.Graphics.UserInterface private readonly MouseButton[] buttons; /// - /// Creates an instance that adds sounds on hover and on click for any of the buttons specified. + /// a container which plays sounds on hover and click for any specified s. /// /// Set of click samples to play. /// /// Array of button codes which should trigger the click sound. - /// If this optional parameter is omitted or set to null, the click sound will only be added on left click. + /// If this optional parameter is omitted or set to null, the click sound will only be played on left click. /// public HoverClickSounds(HoverSampleSet sampleSet = HoverSampleSet.Normal, MouseButton[] buttons = null) : base(sampleSet) From 4b2cb8854e06735d859568ba1b22e4ceb3a71541 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 19:28:10 +0900 Subject: [PATCH 2758/5608] Fix storyboard samples not stopping on exit --- osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs index b04f1d4518..f3f8308964 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs @@ -64,5 +64,11 @@ namespace osu.Game.Storyboards.Drawables LifetimeEnd = sampleInfo.StartTime; } } + + protected override void Dispose(bool isDisposing) + { + channel?.Stop(); + base.Dispose(isDisposing); + } } } From f8c1afa539e47e6ea8ee5bef22f3c4df35a4a053 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 20:17:39 +0900 Subject: [PATCH 2759/5608] Fix two more cases of judgements appearing on hit error display when they shouldn't --- osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs | 3 +++ osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs | 2 ++ 2 files changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs index 63713541b4..5bd480c0ff 100644 --- a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs @@ -5,6 +5,7 @@ using System; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; namespace osu.Game.Rulesets.Osu.Objects @@ -28,5 +29,7 @@ namespace osu.Game.Rulesets.Osu.Objects } public override Judgement CreateJudgement() => new OsuJudgement(); + + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index 4f2af64161..c53a88337e 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -23,5 +23,7 @@ namespace osu.Game.Rulesets.Osu.Objects } public override Judgement CreateJudgement() => new OsuSliderTailJudgement(); + + protected override HitWindows CreateHitWindows() => null; } } From a8f16503e2faa8dcfe98d1f28297e32149f2cd01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 3 Sep 2019 23:18:39 +0200 Subject: [PATCH 2760/5608] Add backslash escaping to new link format For users to be able to add square brackets inside of links using the new format, the regular expression used for parsing those links contained a balancing group, which can be used for matching pairs of tokens (in this case, opening and closing brackets, in that order). However, this means that users could not post links with unmatched brackets inside of them (ie. ones that contain single brackets, or a closing bracket and then an opening one). Allow for escaping opening and closing brackets using the backslash character. The change substitutes this old fragment of the regex in the display text group: [^\[\]]* // any character other than closing/opening bracket for this one: (((?<=\\)[\[\]])|[^\[\]])* The second pattern in the alternative remains the same; the first one performs the escaping, as follows: ( (?<=\\) // positive lookbehind expression: // this match will succeed, if the next expression // is preceded by a single backslash [\[\]] // either an opening or closing brace ) Since the entire display group is matched, unfortunately the lookbehind expression does not actually strip the backslashes, so they are manually stripped in handleMatches. As demonstrated in the unit tests attached, this also allows balanced brackets to be mixed with escaped ones. --- osu.Game.Tests/Chat/MessageFormatterTests.cs | 36 +++++++++++++++++++ .../Visual/Online/TestSceneChatLink.cs | 1 + osu.Game/Online/Chat/MessageFormatter.cs | 11 ++++-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs index 0d6ed67767..1de6280531 100644 --- a/osu.Game.Tests/Chat/MessageFormatterTests.cs +++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs @@ -131,6 +131,42 @@ namespace osu.Game.Tests.Chat Assert.AreEqual(11, result.Links[0].Length); } + [Test] + public void TestNewFormatLinkWithEscapedBrackets() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [https://osu.ppy.sh nasty link with escaped brackets: \\] and \\[]" }); + + Assert.AreEqual("This is a nasty link with escaped brackets: ] and [", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(41, result.Links[0].Length); + } + + [Test] + public void TestNewFormatLinkWithBackslashesInside() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [https://osu.ppy.sh link \\ with \\ backslashes \\]" }); + + Assert.AreEqual("This is a link \\ with \\ backslashes \\", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(27, result.Links[0].Length); + } + + [Test] + public void TestNewFormatLinkWithEscapedAndBalancedBrackets() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [https://osu.ppy.sh [link [with \\] too many brackets \\[ ]]]" }); + + Assert.AreEqual("This is a [link [with ] too many brackets [ ]]", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(36, result.Links[0].Length); + } + [Test] public void TestMarkdownFormatLink() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs index c18e0e3064..056ccafe79 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs @@ -127,6 +127,7 @@ namespace osu.Game.Tests.Visual.Online addMessageWithChecks("is now playing [https://osu.ppy.sh/b/252238 IMAGE -MATERIAL- ]", 1, true, expectedActions: LinkAction.OpenBeatmap); addMessageWithChecks("Let's (try)[https://osu.ppy.sh/home] [https://osu.ppy.sh/b/252238 multiple links] https://osu.ppy.sh/home", 3, expectedActions: new[] { LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External }); + addMessageWithChecks("[https://osu.ppy.sh/home New link format with escaped [and \\[ paired] braces]", expectedActions: LinkAction.External); // note that there's 0 links here (they get removed if a channel is not found) addMessageWithChecks("#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present)."); addMessageWithChecks("I am important!", 0, false, true); diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index db26945ef3..a9fffc196c 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text.RegularExpressions; namespace osu.Game.Online.Chat @@ -16,7 +17,7 @@ namespace osu.Game.Online.Chat private static readonly Regex old_link_regex = new Regex(@"\(([^\)]*)\)\[([a-z]+://[^ ]+)\]"); // [https://osu.ppy.sh/b/1234 Beatmap [Hard] (poop)] -> Beatmap [hard] (poop) (https://osu.ppy.sh/b/1234) - private static readonly Regex new_link_regex = new Regex(@"\[([a-z]+://[^ ]+) ([^\[\]]*(((?\[)[^\[\]]*)+((?\])[^\[\]]*)+)*(?(open)(?!)))\]"); + private static readonly Regex new_link_regex = new Regex(@"\[([a-z]+://[^ ]+) ((((?<=\\)[\[\]])|[^\[\]])*(((?\[)(((?<=\\)[\[\]])|[^\[\]])*)+((?\])(((?<=\\)[\[\]])|[^\[\]])*)+)*(?(open)(?!)))\]"); // [test](https://osu.ppy.sh/b/1234) -> test (https://osu.ppy.sh/b/1234) aka correct markdown format private static readonly Regex markdown_link_regex = new Regex(@"\[([^\]]*)\]\(([a-z]+://[^ ]+)\)"); @@ -48,7 +49,7 @@ namespace osu.Game.Online.Chat // Unicode emojis private static readonly Regex emoji_regex = new Regex(@"(\uD83D[\uDC00-\uDE4F])"); - private static void handleMatches(Regex regex, string display, string link, MessageFormatterResult result, int startIndex = 0, LinkAction? linkActionOverride = null) + private static void handleMatches(Regex regex, string display, string link, MessageFormatterResult result, int startIndex = 0, LinkAction? linkActionOverride = null, char[] escapeChars = null) { int captureOffset = 0; @@ -68,6 +69,10 @@ namespace osu.Game.Online.Chat if (displayText.Length == 0 || linkText.Length == 0) continue; + // Remove backslash escapes in front of the characters provided in escapeChars + if (escapeChars != null) + displayText = escapeChars.Aggregate(displayText, (current, c) => current.Replace($"\\{c}", c.ToString())); + // Check for encapsulated links if (result.Links.Find(l => (l.Index <= index && l.Index + l.Length >= index + m.Length) || (index <= l.Index && index + m.Length >= l.Index + l.Length)) == null) { @@ -183,7 +188,7 @@ namespace osu.Game.Online.Chat var result = new MessageFormatterResult(toFormat); // handle the [link display] format - handleMatches(new_link_regex, "{2}", "{1}", result, startIndex); + handleMatches(new_link_regex, "{2}", "{1}", result, startIndex, escapeChars: new[] { '[', ']' }); // handle the standard markdown []() format handleMatches(markdown_link_regex, "{1}", "{2}", result, startIndex); From 24d4f0372c851280eb017553101712ad86731133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 3 Sep 2019 23:56:07 +0200 Subject: [PATCH 2761/5608] Refactor link parsing regexes to use named groups For the sake of readability, consistency and to make further changes easier, introduce named groups (?) and (?) to all link parsing regexes which have parts containing the desired link text and (optionally) URL. The introduction of the named groups additionally simplifies handleMatches() and makes all calls to it consistent. --- osu.Game/Online/Chat/MessageFormatter.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index a9fffc196c..23b5cdc0a6 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -11,16 +11,16 @@ namespace osu.Game.Online.Chat public static class MessageFormatter { // [[Performance Points]] -> wiki:Performance Points (https://osu.ppy.sh/wiki/Performance_Points) - private static readonly Regex wiki_regex = new Regex(@"\[\[([^\]]+)\]\]"); + private static readonly Regex wiki_regex = new Regex(@"\[\[(?[^\]]+)\]\]"); // (test)[https://osu.ppy.sh/b/1234] -> test (https://osu.ppy.sh/b/1234) - private static readonly Regex old_link_regex = new Regex(@"\(([^\)]*)\)\[([a-z]+://[^ ]+)\]"); + private static readonly Regex old_link_regex = new Regex(@"\((?[^\)]*)\)\[(?[a-z]+://[^ ]+)\]"); // [https://osu.ppy.sh/b/1234 Beatmap [Hard] (poop)] -> Beatmap [hard] (poop) (https://osu.ppy.sh/b/1234) - private static readonly Regex new_link_regex = new Regex(@"\[([a-z]+://[^ ]+) ((((?<=\\)[\[\]])|[^\[\]])*(((?\[)(((?<=\\)[\[\]])|[^\[\]])*)+((?\])(((?<=\\)[\[\]])|[^\[\]])*)+)*(?(open)(?!)))\]"); + private static readonly Regex new_link_regex = new Regex(@"\[(?[a-z]+://[^ ]+) (?(((?<=\\)[\[\]])|[^\[\]])*(((?\[)(((?<=\\)[\[\]])|[^\[\]])*)+((?\])(((?<=\\)[\[\]])|[^\[\]])*)+)*(?(open)(?!)))\]"); // [test](https://osu.ppy.sh/b/1234) -> test (https://osu.ppy.sh/b/1234) aka correct markdown format - private static readonly Regex markdown_link_regex = new Regex(@"\[([^\]]*)\]\(([a-z]+://[^ ]+)\)"); + private static readonly Regex markdown_link_regex = new Regex(@"\[(?[^\]]*)\]\((?[a-z]+://[^ ]+)\)"); // advanced, RFC-compatible regular expression that matches any possible URL, *but* allows certain invalid characters that are widely used // This is in the format (, [optional]): @@ -59,13 +59,13 @@ namespace osu.Game.Online.Chat var displayText = string.Format(display, m.Groups[0], - m.Groups.Count > 1 ? m.Groups[1].Value : "", - m.Groups.Count > 2 ? m.Groups[2].Value : "").Trim(); + m.Groups["text"].Value, + m.Groups["url"].Value).Trim(); var linkText = string.Format(link, m.Groups[0], - m.Groups.Count > 1 ? m.Groups[1].Value : "", - m.Groups.Count > 2 ? m.Groups[2].Value : "").Trim(); + m.Groups["text"].Value, + m.Groups["url"].Value).Trim(); if (displayText.Length == 0 || linkText.Length == 0) continue; @@ -188,7 +188,7 @@ namespace osu.Game.Online.Chat var result = new MessageFormatterResult(toFormat); // handle the [link display] format - handleMatches(new_link_regex, "{2}", "{1}", result, startIndex, escapeChars: new[] { '[', ']' }); + handleMatches(new_link_regex, "{1}", "{2}", result, startIndex, escapeChars: new[] { '[', ']' }); // handle the standard markdown []() format handleMatches(markdown_link_regex, "{1}", "{2}", result, startIndex); From f04add6d9edda7bbdf080adc7e6959ee16e6f222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 4 Sep 2019 00:01:26 +0200 Subject: [PATCH 2762/5608] Add bracket handling to Markdown link format Allow users to put both balanced brackets, as well as unbalanced escaped ones, in Markdown link text. The implementation is the exact same as in the case of new format links. For completion's sake, tests also included. --- osu.Game.Tests/Chat/MessageFormatterTests.cs | 47 +++++++++++++++++++ .../Visual/Online/TestSceneChatLink.cs | 1 + osu.Game/Online/Chat/MessageFormatter.cs | 4 +- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs index 1de6280531..198267d78a 100644 --- a/osu.Game.Tests/Chat/MessageFormatterTests.cs +++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs @@ -179,6 +179,53 @@ namespace osu.Game.Tests.Chat Assert.AreEqual(11, result.Links[0].Length); } + [Test] + public void TestMarkdownFormatLinkWithBalancedBrackets() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [tricky [one]](https://osu.ppy.sh)!" }); + + Assert.AreEqual("This is a tricky [one]!", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(12, result.Links[0].Length); + } + + [Test] + public void TestMarkdownFormatLinkWithEscapedBrackets() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is [another loose bracket \\]](https://osu.ppy.sh)." }); + + Assert.AreEqual("This is another loose bracket ].", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(8, result.Links[0].Index); + Assert.AreEqual(23, result.Links[0].Length); + } + + [Test] + public void TestMarkdownFormatWithBackslashes() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This link [should end with a backslash \\](https://osu.ppy.sh)." }); + Assert.AreEqual("This link should end with a backslash \\.", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(29, result.Links[0].Length); + } + + [Test] + public void TestMarkdownFormatLinkWithEscapedAndBalancedBrackets() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [\\]super\\[\\[ tricky [one]](https://osu.ppy.sh)!" }); + + Assert.AreEqual("This is a ]super[[ tricky [one]!", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(21, result.Links[0].Length); + } + [Test] public void TestChannelLink() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs index 056ccafe79..61c7d3f5b6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs @@ -128,6 +128,7 @@ namespace osu.Game.Tests.Visual.Online addMessageWithChecks("Let's (try)[https://osu.ppy.sh/home] [https://osu.ppy.sh/b/252238 multiple links] https://osu.ppy.sh/home", 3, expectedActions: new[] { LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External }); addMessageWithChecks("[https://osu.ppy.sh/home New link format with escaped [and \\[ paired] braces]", expectedActions: LinkAction.External); + addMessageWithChecks("[Markdown link format with escaped [and \\[ paired] braces](https://osu.ppy.sh/home)", expectedActions: LinkAction.External); // note that there's 0 links here (they get removed if a channel is not found) addMessageWithChecks("#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present)."); addMessageWithChecks("I am important!", 0, false, true); diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 23b5cdc0a6..e40bb05381 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -20,7 +20,7 @@ namespace osu.Game.Online.Chat private static readonly Regex new_link_regex = new Regex(@"\[(?[a-z]+://[^ ]+) (?(((?<=\\)[\[\]])|[^\[\]])*(((?\[)(((?<=\\)[\[\]])|[^\[\]])*)+((?\])(((?<=\\)[\[\]])|[^\[\]])*)+)*(?(open)(?!)))\]"); // [test](https://osu.ppy.sh/b/1234) -> test (https://osu.ppy.sh/b/1234) aka correct markdown format - private static readonly Regex markdown_link_regex = new Regex(@"\[(?[^\]]*)\]\((?[a-z]+://[^ ]+)\)"); + private static readonly Regex markdown_link_regex = new Regex(@"\[(?(((?<=\\)[\[\]])|[^\[\]])*(((?\[)(((?<=\\)[\[\]])|[^\[\]])*)+((?\])(((?<=\\)[\[\]])|[^\[\]])*)+)*(?(open)(?!)))\]\((?[a-z]+://[^ ]+)\)"); // advanced, RFC-compatible regular expression that matches any possible URL, *but* allows certain invalid characters that are widely used // This is in the format (, [optional]): @@ -191,7 +191,7 @@ namespace osu.Game.Online.Chat handleMatches(new_link_regex, "{1}", "{2}", result, startIndex, escapeChars: new[] { '[', ']' }); // handle the standard markdown []() format - handleMatches(markdown_link_regex, "{1}", "{2}", result, startIndex); + handleMatches(markdown_link_regex, "{1}", "{2}", result, startIndex, escapeChars: new[] { '[', ']' }); // handle the ()[] link format handleMatches(old_link_regex, "{1}", "{2}", result, startIndex); From 08350a1acaf4c3bb70176e384c845fc83735d497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 4 Sep 2019 00:17:52 +0200 Subject: [PATCH 2763/5608] Add parenthesis handling to old link format Allow users to put both balanced round parentheses, as well as unbalanced escaped ones, in old style link text. The implementation is the same as for Markdown and new style links, except for swapping all instances of \[\] to \(\) for obvious reasons (different type of parenthesis requiring escaping). Tests also included. --- osu.Game.Tests/Chat/MessageFormatterTests.cs | 47 +++++++++++++++++++ .../Visual/Online/TestSceneChatLink.cs | 5 +- osu.Game/Online/Chat/MessageFormatter.cs | 4 +- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs index 198267d78a..9b4a90e9a9 100644 --- a/osu.Game.Tests/Chat/MessageFormatterTests.cs +++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs @@ -119,6 +119,53 @@ namespace osu.Game.Tests.Chat Assert.AreEqual(11, result.Links[0].Length); } + [Test] + public void TestOldFormatLinkWithBalancedBrackets() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a (tricky (one))[https://osu.ppy.sh]!" }); + + Assert.AreEqual("This is a tricky (one)!", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(12, result.Links[0].Length); + } + + [Test] + public void TestOldFormatLinkWithEscapedBrackets() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is (another loose bracket \\))[https://osu.ppy.sh]." }); + + Assert.AreEqual("This is another loose bracket ).", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(8, result.Links[0].Index); + Assert.AreEqual(23, result.Links[0].Length); + } + + [Test] + public void TestOldFormatWithBackslashes() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This link (should end with a backslash \\)[https://osu.ppy.sh]." }); + Assert.AreEqual("This link should end with a backslash \\.", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(29, result.Links[0].Length); + } + + [Test] + public void TestOldFormatLinkWithEscapedAndBalancedBrackets() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a (\\)super\\(\\( tricky (one))[https://osu.ppy.sh]!" }); + + Assert.AreEqual("This is a )super(( tricky (one)!", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(21, result.Links[0].Length); + } + [Test] public void TestNewFormatLink() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs index 61c7d3f5b6..a1c77e2db0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs @@ -127,8 +127,9 @@ namespace osu.Game.Tests.Visual.Online addMessageWithChecks("is now playing [https://osu.ppy.sh/b/252238 IMAGE -MATERIAL- ]", 1, true, expectedActions: LinkAction.OpenBeatmap); addMessageWithChecks("Let's (try)[https://osu.ppy.sh/home] [https://osu.ppy.sh/b/252238 multiple links] https://osu.ppy.sh/home", 3, expectedActions: new[] { LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External }); - addMessageWithChecks("[https://osu.ppy.sh/home New link format with escaped [and \\[ paired] braces]", expectedActions: LinkAction.External); - addMessageWithChecks("[Markdown link format with escaped [and \\[ paired] braces](https://osu.ppy.sh/home)", expectedActions: LinkAction.External); + addMessageWithChecks("[https://osu.ppy.sh/home New link format with escaped [and \\[ paired] braces]", 1, expectedActions: LinkAction.External); + addMessageWithChecks("[Markdown link format with escaped [and \\[ paired] braces](https://osu.ppy.sh/home)", 1, expectedActions: LinkAction.External); + addMessageWithChecks("(Old link format with escaped (and \\( paired) parentheses)[https://osu.ppy.sh/home] and [[also a rogue wiki link]]", 2, expectedActions: new[] { LinkAction.External, LinkAction.External }); // note that there's 0 links here (they get removed if a channel is not found) addMessageWithChecks("#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present)."); addMessageWithChecks("I am important!", 0, false, true); diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index e40bb05381..24d17612ee 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -14,7 +14,7 @@ namespace osu.Game.Online.Chat private static readonly Regex wiki_regex = new Regex(@"\[\[(?[^\]]+)\]\]"); // (test)[https://osu.ppy.sh/b/1234] -> test (https://osu.ppy.sh/b/1234) - private static readonly Regex old_link_regex = new Regex(@"\((?[^\)]*)\)\[(?[a-z]+://[^ ]+)\]"); + private static readonly Regex old_link_regex = new Regex(@"\((?(((?<=\\)[\(\)])|[^\(\)])*(((?\()(((?<=\\)[\(\)])|[^\(\)])*)+((?\))(((?<=\\)[\(\)])|[^\(\)])*)+)*(?(open)(?!)))\)\[(?[a-z]+://[^ ]+)\]"); // [https://osu.ppy.sh/b/1234 Beatmap [Hard] (poop)] -> Beatmap [hard] (poop) (https://osu.ppy.sh/b/1234) private static readonly Regex new_link_regex = new Regex(@"\[(?[a-z]+://[^ ]+) (?(((?<=\\)[\[\]])|[^\[\]])*(((?\[)(((?<=\\)[\[\]])|[^\[\]])*)+((?\])(((?<=\\)[\[\]])|[^\[\]])*)+)*(?(open)(?!)))\]"); @@ -194,7 +194,7 @@ namespace osu.Game.Online.Chat handleMatches(markdown_link_regex, "{1}", "{2}", result, startIndex, escapeChars: new[] { '[', ']' }); // handle the ()[] link format - handleMatches(old_link_regex, "{1}", "{2}", result, startIndex); + handleMatches(old_link_regex, "{1}", "{2}", result, startIndex, escapeChars: new[] { '(', ')' }); // handle wiki links handleMatches(wiki_regex, "{1}", "https://osu.ppy.sh/wiki/{1}", result, startIndex); From 9ec16bc2b260fd35a7d0b2722432cb5636c6f4f2 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 3 Sep 2019 16:56:45 -0700 Subject: [PATCH 2764/5608] Add test for initial button hover --- .../Gameplay/TestSceneGameplayMenuOverlay.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs index 0d8a84fa51..ef7345bda7 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs @@ -63,6 +63,7 @@ namespace osu.Game.Tests.Visual.Gameplay testKeyDownWrapping(); testHideResets(); + testInitialButtonHover(); testMouseSelectionAfterKeySelection(); testKeySelectionAfterMouseSelection(); @@ -159,6 +160,25 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("Overlay state is reset", () => !failOverlay.Buttons.Any(b => b.Selected.Value)); } + /// + /// Tests that entering menu with cursor initially on button selects it. + /// + private void testInitialButtonHover() + { + AddStep("Show overlay", () => pauseOverlay.Show()); + + var firstButton = pauseOverlay.Buttons.First(); + + AddStep("Hover first button", () => InputManager.MoveMouseTo(firstButton)); + + AddStep("Hide overlay", () => pauseOverlay.Hide()); + AddStep("Show overlay", () => pauseOverlay.Show()); + + AddAssert("First button selected", () => firstButton.Selected.Value); + + AddStep("Hide overlay", () => pauseOverlay.Hide()); + } + /// /// Tests that hovering a button that was previously selected with the keyboard correctly selects the new button and deselects the previous button. /// From 5c10a228771ba0f3bb5459ff80b5d6f74a8e586f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 10:34:56 +0900 Subject: [PATCH 2765/5608] Update tests to use [Test] attributes --- .../Gameplay/TestSceneGameplayMenuOverlay.cs | 57 +++++++++---------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs index ef7345bda7..8b2fbe8aae 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs @@ -3,8 +3,8 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; +using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -16,7 +16,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - [Description("player pause/fail screens")] + [System.ComponentModel.Description("player pause/fail screens")] public class TestSceneGameplayMenuOverlay : ManualInputManagerTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(FailOverlay), typeof(PauseOverlay) }; @@ -55,29 +55,13 @@ namespace osu.Game.Tests.Visual.Gameplay retryCount++; pauseOverlay.Retries = failOverlay.Retries = retryCount; }); - - testEnterWithoutSelection(); - testKeyUpFromInitial(); - testKeyDownFromInitial(); - testKeyUpWrapping(); - testKeyDownWrapping(); - - testHideResets(); - testInitialButtonHover(); - - testMouseSelectionAfterKeySelection(); - testKeySelectionAfterMouseSelection(); - - testMouseDeselectionResets(); - - testClickSelection(); - testEnterKeySelection(); } /// /// Tests that pressing enter after an overlay shows doesn't trigger an event because a selection hasn't occurred. /// - private void testEnterWithoutSelection() + [Test] + public void TestEnterWithoutSelection() { AddStep("Show overlay", () => pauseOverlay.Show()); @@ -90,7 +74,8 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// Tests that pressing the up arrow from the initial state selects the last button. /// - private void testKeyUpFromInitial() + [Test] + public void TestKeyUpFromInitial() { AddStep("Show overlay", () => pauseOverlay.Show()); @@ -103,7 +88,8 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// Tests that pressing the down arrow from the initial state selects the first button. /// - private void testKeyDownFromInitial() + [Test] + public void TestKeyDownFromInitial() { AddStep("Show overlay", () => pauseOverlay.Show()); @@ -116,7 +102,8 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// Tests that pressing the up arrow repeatedly causes the selected button to wrap correctly. /// - private void testKeyUpWrapping() + [Test] + public void TestKeyUpWrapping() { AddStep("Show overlay", () => failOverlay.Show()); @@ -133,7 +120,8 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// Tests that pressing the down arrow repeatedly causes the selected button to wrap correctly. /// - private void testKeyDownWrapping() + [Test] + public void TestKeyDownWrapping() { AddStep("Show overlay", () => failOverlay.Show()); @@ -150,7 +138,8 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// Test that hiding the overlay after hovering a button will reset the overlay to the initial state with no buttons selected. /// - private void testHideResets() + [Test] + public void TestHideResets() { AddStep("Show overlay", () => failOverlay.Show()); @@ -163,7 +152,8 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// Tests that entering menu with cursor initially on button selects it. /// - private void testInitialButtonHover() + [Test] + public void TestInitialButtonHover() { AddStep("Show overlay", () => pauseOverlay.Show()); @@ -182,7 +172,8 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// Tests that hovering a button that was previously selected with the keyboard correctly selects the new button and deselects the previous button. /// - private void testMouseSelectionAfterKeySelection() + [Test] + public void TestMouseSelectionAfterKeySelection() { AddStep("Show overlay", () => pauseOverlay.Show()); @@ -199,7 +190,8 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// Tests that pressing a key after selecting a button with a hover event correctly selects a new button and deselects the previous button. /// - private void testKeySelectionAfterMouseSelection() + [Test] + public void TestKeySelectionAfterMouseSelection() { AddStep("Show overlay", () => { @@ -220,7 +212,8 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// Tests that deselecting with the mouse by losing hover will reset the overlay to the initial state. /// - private void testMouseDeselectionResets() + [Test] + public void TestMouseDeselectionResets() { AddStep("Show overlay", () => pauseOverlay.Show()); @@ -237,7 +230,8 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// Tests that clicking on a button correctly causes a click event for that button. /// - private void testClickSelection() + [Test] + public void TestClickSelection() { AddStep("Show overlay", () => pauseOverlay.Show()); @@ -260,7 +254,8 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// Tests that pressing the enter key with a button selected correctly causes a click event for that button. /// - private void testEnterKeySelection() + [Test] + public void TestEnterKeySelection() { AddStep("Show overlay", () => pauseOverlay.Show()); From 40c61894effd9afcc1dc2db5393f4b37058c1076 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 10:44:24 +0900 Subject: [PATCH 2766/5608] Update some case sensitive resources lookups in-line with resources --- osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs | 2 +- osu.Game.Rulesets.Taiko/UI/InputDrum.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index c89cd95f36..e96c7d8f92 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Catch.Tests { switch (component.LookupName) { - case "Gameplay/Catch/fruit-catcher-idle": + case "Gameplay/catch/fruit-catcher-idle": return new CatcherCustomSkin(); } diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index 9766da9a24..5234ae1f69 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -132,10 +132,10 @@ namespace osu.Game.Rulesets.Taiko.UI [BackgroundDependencyLoader] private void load(TextureStore textures, OsuColour colours) { - rim.Texture = textures.Get(@"Gameplay/Taiko/taiko-drum-outer"); - rimHit.Texture = textures.Get(@"Gameplay/Taiko/taiko-drum-outer-hit"); - centre.Texture = textures.Get(@"Gameplay/Taiko/taiko-drum-inner"); - centreHit.Texture = textures.Get(@"Gameplay/Taiko/taiko-drum-inner-hit"); + rim.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer"); + rimHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer-hit"); + centre.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner"); + centreHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner-hit"); rimHit.Colour = colours.Blue; centreHit.Colour = colours.Pink; From 7cbcc7b9069178bc07c38bdf8802fbf3eaf7333b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 11:36:09 +0900 Subject: [PATCH 2767/5608] Further test refactors --- .../Gameplay/TestSceneGameplayMenuOverlay.cs | 121 ++++++++---------- 1 file changed, 54 insertions(+), 67 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs index 8b2fbe8aae..cc275009ba 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Logging; +using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; using osu.Game.Screens.Play; using osuTK; @@ -29,32 +30,43 @@ namespace osu.Game.Tests.Visual.Gameplay [BackgroundDependencyLoader] private void load(OsuGameBase game) { - Child = globalActionContainer = new GlobalActionContainer(game) - { - Children = new Drawable[] - { - pauseOverlay = new PauseOverlay - { - OnResume = () => Logger.Log(@"Resume"), - OnRetry = () => Logger.Log(@"Retry"), - OnQuit = () => Logger.Log(@"Quit"), - }, - failOverlay = new FailOverlay + Child = globalActionContainer = new GlobalActionContainer(game); + } - { - OnRetry = () => Logger.Log(@"Retry"), - OnQuit = () => Logger.Log(@"Quit"), - } + [SetUp] + public void SetUp() => Schedule(() => + { + globalActionContainer.Children = new Drawable[] + { + pauseOverlay = new PauseOverlay + { + OnResume = () => Logger.Log(@"Resume"), + OnRetry = () => Logger.Log(@"Retry"), + OnQuit = () => Logger.Log(@"Quit"), + }, + failOverlay = new FailOverlay + + { + OnRetry = () => Logger.Log(@"Retry"), + OnQuit = () => Logger.Log(@"Quit"), } }; + InputManager.MoveMouseTo(Vector2.Zero); + }); + + [Test] + public void TestAdjustRetryCount() + { + showOverlay(); + var retryCount = 0; - AddStep("Add retry", () => + AddRepeatStep("Add retry", () => { retryCount++; pauseOverlay.Retries = failOverlay.Retries = retryCount; - }); + }, 10); } /// @@ -63,12 +75,10 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestEnterWithoutSelection() { - AddStep("Show overlay", () => pauseOverlay.Show()); + showOverlay(); AddStep("Press select", () => press(GlobalAction.Select)); AddAssert("Overlay still open", () => pauseOverlay.State.Value == Visibility.Visible); - - AddStep("Hide overlay", () => pauseOverlay.Hide()); } /// @@ -77,12 +87,10 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestKeyUpFromInitial() { - AddStep("Show overlay", () => pauseOverlay.Show()); + showOverlay(); AddStep("Up arrow", () => press(Key.Up)); AddAssert("Last button selected", () => pauseOverlay.Buttons.Last().Selected.Value); - - AddStep("Hide overlay", () => pauseOverlay.Hide()); } /// @@ -91,12 +99,10 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestKeyDownFromInitial() { - AddStep("Show overlay", () => pauseOverlay.Show()); + showOverlay(); AddStep("Down arrow", () => press(Key.Down)); - AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected.Value); - - AddStep("Hide overlay", () => pauseOverlay.Hide()); + AddAssert("First button selected", () => getButton(0).Selected.Value); } /// @@ -113,8 +119,6 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value); AddStep("Up arrow", () => press(Key.Up)); AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value); - - AddStep("Hide overlay", () => failOverlay.Hide()); } /// @@ -131,8 +135,6 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value); AddStep("Down arrow", () => press(Key.Down)); AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value); - - AddStep("Hide overlay", () => failOverlay.Hide()); } /// @@ -155,18 +157,14 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestInitialButtonHover() { - AddStep("Show overlay", () => pauseOverlay.Show()); + showOverlay(); - var firstButton = pauseOverlay.Buttons.First(); - - AddStep("Hover first button", () => InputManager.MoveMouseTo(firstButton)); + AddStep("Hover first button", () => InputManager.MoveMouseTo(getButton(0))); AddStep("Hide overlay", () => pauseOverlay.Hide()); - AddStep("Show overlay", () => pauseOverlay.Show()); + showOverlay(); - AddAssert("First button selected", () => firstButton.Selected.Value); - - AddStep("Hide overlay", () => pauseOverlay.Hide()); + AddAssert("First button selected", () => getButton(0).Selected.Value); } /// @@ -175,16 +173,12 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestMouseSelectionAfterKeySelection() { - AddStep("Show overlay", () => pauseOverlay.Show()); - - var secondButton = pauseOverlay.Buttons.Skip(1).First(); + showOverlay(); AddStep("Down arrow", () => press(Key.Down)); - AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton)); - AddAssert("First button not selected", () => !pauseOverlay.Buttons.First().Selected.Value); - AddAssert("Second button selected", () => secondButton.Selected.Value); - - AddStep("Hide overlay", () => pauseOverlay.Hide()); + AddStep("Hover second button", () => InputManager.MoveMouseTo(getButton(1))); + AddAssert("First button not selected", () => !getButton(0).Selected.Value); + AddAssert("Second button selected", () => getButton(1).Selected.Value); } /// @@ -196,17 +190,12 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("Show overlay", () => { pauseOverlay.Show(); - InputManager.MoveMouseTo(Vector2.Zero); }); - var secondButton = pauseOverlay.Buttons.Skip(1).First(); - - AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton)); + AddStep("Hover second button", () => InputManager.MoveMouseTo(getButton(1))); AddStep("Up arrow", () => press(Key.Up)); - AddAssert("Second button not selected", () => !secondButton.Selected.Value); - AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected.Value); - - AddStep("Hide overlay", () => pauseOverlay.Hide()); + AddAssert("Second button not selected", () => !getButton(1).Selected.Value); + AddAssert("First button selected", () => getButton(0).Selected.Value); } /// @@ -215,16 +204,12 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestMouseDeselectionResets() { - AddStep("Show overlay", () => pauseOverlay.Show()); + showOverlay(); - var secondButton = pauseOverlay.Buttons.Skip(1).First(); - - AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton)); + AddStep("Hover second button", () => InputManager.MoveMouseTo(getButton(1))); AddStep("Unhover second button", () => InputManager.MoveMouseTo(Vector2.Zero)); AddStep("Down arrow", () => press(Key.Down)); - AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected.Value); // Initial state condition - - AddStep("Hide overlay", () => pauseOverlay.Hide()); + AddAssert("First button selected", () => getButton(0).Selected.Value); // Initial state condition } /// @@ -233,9 +218,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestClickSelection() { - AddStep("Show overlay", () => pauseOverlay.Show()); - - var retryButton = pauseOverlay.Buttons.Skip(1).First(); + showOverlay(); bool triggered = false; AddStep("Click retry button", () => @@ -243,7 +226,7 @@ namespace osu.Game.Tests.Visual.Gameplay var lastAction = pauseOverlay.OnRetry; pauseOverlay.OnRetry = () => triggered = true; - retryButton.Click(); + getButton(1).Click(); pauseOverlay.OnRetry = lastAction; }); @@ -257,7 +240,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestEnterKeySelection() { - AddStep("Show overlay", () => pauseOverlay.Show()); + showOverlay(); AddStep("Select second button", () => { @@ -287,6 +270,10 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("Overlay is closed", () => pauseOverlay.State.Value == Visibility.Hidden); } + private void showOverlay() => AddStep("Show overlay", () => pauseOverlay.Show()); + + private DialogButton getButton(int index) => pauseOverlay.Buttons.Skip(index).First(); + private void press(Key key) { InputManager.PressKey(key); From 4c563232d627b17a6f1c31350b156673c7befb7d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 11:37:02 +0900 Subject: [PATCH 2768/5608] HoverClickSounds should handle click event instead of MouseUp --- osu.Game/Graphics/UserInterface/HoverClickSounds.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index 1fb73efa65..4f678b7218 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -34,12 +34,12 @@ namespace osu.Game.Graphics.UserInterface this.buttons = buttons ?? new[] { MouseButton.Left }; } - protected override bool OnMouseUp(MouseUpEvent e) + protected override bool OnClick(ClickEvent e) { if (buttons.Contains(e.Button) && Contains(e.ScreenSpaceMousePosition)) sampleClick?.Play(); - return base.OnMouseUp(e); + return base.OnClick(e); } [BackgroundDependencyLoader] From 5efd455ce4821e48919eb462531325db12d54f65 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 4 Sep 2019 12:47:10 +0900 Subject: [PATCH 2769/5608] Fix taiko sample namespace --- .../Objects/Drawables/DrawableTaikoHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 5424ccb4de..423f65b2d3 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables // Normal and clap samples are handled by the drum protected override IEnumerable GetSamples() => HitObject.Samples.Where(s => s.Name != HitSampleInfo.HIT_NORMAL && s.Name != HitSampleInfo.HIT_CLAP); - protected override string SampleNamespace => "Taiko"; + protected override string SampleNamespace => "taiko"; protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(); From 024aa4dd7b3ea19e04cd59cf8e66a26f74a62cc2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 4 Sep 2019 13:05:05 +0900 Subject: [PATCH 2770/5608] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 96706f2bdc..90d1854c39 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -60,7 +60,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ca69bb2295..7d106f0484 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 86a2a40940..8390a2229b 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -117,7 +117,7 @@ - + From 9edfe6800f7a7157b3a0b8902a2a9ad57b599814 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2019 04:20:46 +0000 Subject: [PATCH 2771/5608] Bump ppy.osu.Game.Resources from 2019.903.1 to 2019.904.0 Bumps [ppy.osu.Game.Resources](https://github.com/ppy/osu-resources) from 2019.903.1 to 2019.904.0. - [Release notes](https://github.com/ppy/osu-resources/releases) - [Commits](https://github.com/ppy/osu-resources/compare/2019.903.1...2019.904.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 96706f2bdc..90d1854c39 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -60,7 +60,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ca69bb2295..7d106f0484 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 86a2a40940..8390a2229b 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -117,7 +117,7 @@ - + From 04c2c33c64bbc908324510672c822681bf40667b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 13:29:55 +0900 Subject: [PATCH 2772/5608] Allow LegacySkin to be constructed with all nulls --- osu.Game/Skinning/LegacySkin.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 5f0afae075..7bdb980eaf 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -30,14 +30,14 @@ namespace osu.Game.Skinning protected LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager, string filename) : base(skin) { - Stream stream = storage.GetStream(filename); + Stream stream = storage?.GetStream(filename); if (stream != null) using (StreamReader reader = new StreamReader(stream)) Configuration = new LegacySkinDecoder().Decode(reader); else Configuration = new DefaultSkinConfiguration(); - Samples = audioManager.GetSampleStore(storage); + Samples = audioManager?.GetSampleStore(storage); Textures = new TextureStore(new TextureLoaderStore(storage)); } @@ -72,6 +72,10 @@ namespace osu.Game.Skinning { if (Configuration.ConfigDictionary.TryGetValue(lookup.ToString(), out var val)) { + // special case for handling skins which use 1 or 0 to signify a boolean state. + if (typeof(TValue) == typeof(bool)) + val = val == "1" ? "true" : "false"; + var bindable = new Bindable(); bindable.Parse(val); return bindable; From f655cd451681e8fc64e0f6c8faebcdc1c0ab08ea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 13:30:46 +0900 Subject: [PATCH 2773/5608] Fix parsing of null configuration elements --- osu.Game/Skinning/LegacySkin.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 7bdb980eaf..94e2a49908 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -77,7 +77,8 @@ namespace osu.Game.Skinning val = val == "1" ? "true" : "false"; var bindable = new Bindable(); - bindable.Parse(val); + if (val != null) + bindable.Parse(val); return bindable; } } From fb3d050209bb8b72c02435d5225b8f7318afd98f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 13:36:50 +0900 Subject: [PATCH 2774/5608] Add comprehensive configuration lookup tests --- .../Skins/SkinConfigurationLookupTest.cs | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 osu.Game.Tests/Skins/SkinConfigurationLookupTest.cs diff --git a/osu.Game.Tests/Skins/SkinConfigurationLookupTest.cs b/osu.Game.Tests/Skins/SkinConfigurationLookupTest.cs new file mode 100644 index 0000000000..1344d20d9f --- /dev/null +++ b/osu.Game.Tests/Skins/SkinConfigurationLookupTest.cs @@ -0,0 +1,137 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Textures; +using osu.Game.Audio; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; +using osuTK.Graphics; + +namespace osu.Game.Tests.Skins +{ + [TestFixture] + public class TestSceneSkinConfigurationLookup : OsuTestScene + { + private LegacySkin source1; + private LegacySkin source2; + private SkinRequester requester; + + [SetUp] + public void SetUp() => Schedule(() => + { + Add(new SkinProvidingContainer(source1 = new SkinSource()) + .WithChild(new SkinProvidingContainer(source2 = new SkinSource()) + .WithChild(requester = new SkinRequester()))); + }); + + [Test] + public void TestBasicLookup() + { + AddStep("Add config values", () => + { + source1.Configuration.ConfigDictionary["Lookup"] = "source1"; + source2.Configuration.ConfigDictionary["Lookup"] = "source2"; + }); + + AddAssert("Check lookup finds source2", () => requester.GetConfig("Lookup")?.Value == "source2"); + } + + [Test] + public void TestParsingLookup() + { + AddStep("Add config values", () => + { + source1.Configuration.ConfigDictionary["FloatTest"] = "1.1"; + source2.Configuration.ConfigDictionary["BoolTest"] = "1"; + }); + + AddAssert("Check float parse lookup", () => requester.GetConfig("FloatTest")?.Value == 1.1f); + AddAssert("Check bool parse lookup", () => requester.GetConfig("BoolTest")?.Value == true); + } + + [Test] + public void TestEnumLookup() + { + AddStep("Add config values", () => { source1.Configuration.ConfigDictionary["Test"] = "Test2"; }); + + AddAssert("Check float parse lookup", () => requester.GetConfig(LookupType.Test)?.Value == ValueType.Test2); + } + + [Test] + public void TestLookupFailure() + { + AddAssert("Check lookup failure", () => requester.GetConfig("Lookup") == null); + } + + [Test] + public void TestLookupNull() + { + AddStep("Add config values", () => { source1.Configuration.ConfigDictionary["Lookup"] = null; }); + + AddAssert("Check lookup null", () => + { + var bindable = requester.GetConfig("Lookup"); + return bindable != null && bindable.Value == null; + }); + } + + [Test] + public void TestColourLookup() + { + AddStep("Add config colour", () => { source1.Configuration.CustomColours["Lookup"] = Color4.Red; }); + AddAssert("Check colour lookup", () => requester.GetConfig(new SkinCustomColourLookup("Lookup"))?.Value == Color4.Red); + } + + [Test] + public void TestGlobalLookup() + { + AddAssert("Check combo colours", () => requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.Count > 0); + } + + public enum LookupType + { + Test + } + + public enum ValueType + { + Test1, + Test2, + Test3 + } + + public class SkinSource : LegacySkin + { + public SkinSource() + : base(new SkinInfo(), null, null, string.Empty) + { + } + } + + public class SkinRequester : Drawable, ISkin + { + private ISkinSource skin; + + [BackgroundDependencyLoader] + private void load(ISkinSource skin) + { + this.skin = skin; + } + + public Drawable GetDrawableComponent(ISkinComponent component) => skin.GetDrawableComponent(component); + + public Texture GetTexture(string componentName) => skin.GetTexture(componentName); + + public SampleChannel GetSample(ISampleInfo sampleInfo) => skin.GetSample(sampleInfo); + + public IBindable GetConfig(TLookup lookup) => skin.GetConfig(lookup); + } + } +} From 8d48cc3533ef470fba9045e8206763caac0a7820 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 13:40:36 +0900 Subject: [PATCH 2775/5608] Fix filename --- ...igurationLookupTest.cs => TestSceneSkinConfigurationLookup.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Tests/Skins/{SkinConfigurationLookupTest.cs => TestSceneSkinConfigurationLookup.cs} (100%) diff --git a/osu.Game.Tests/Skins/SkinConfigurationLookupTest.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs similarity index 100% rename from osu.Game.Tests/Skins/SkinConfigurationLookupTest.cs rename to osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs From 69b9d70a35c2c1f42214d16f083b6e73f43ddc4c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 15:56:18 +0900 Subject: [PATCH 2776/5608] Add minimal configuration to support nuget package creation --- osu.Game/osu.Game.csproj | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 7d106f0484..3147ca749f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -6,6 +6,17 @@ AnyCPU true + + osu! + ppy.osu.Game + ppy Pty Ltd + https://github.com/ppy/osu/blob/master/LICENCE.md + https://github.com/ppy/osu + https://github.com/ppy/osu + Automated release. + Copyright (c) 2019 ppy Pty Ltd + osu game + @@ -15,7 +26,7 @@ - + From 8ea82123e4afc36ac897735d24743a17b259d25b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 15:59:09 +0900 Subject: [PATCH 2777/5608] Fix nullref on test disposal --- osu.Game/Skinning/LegacySkin.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 94e2a49908..cd2ad2d61c 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; @@ -18,8 +19,10 @@ namespace osu.Game.Skinning { public class LegacySkin : Skin { + [CanBeNull] protected TextureStore Textures; + [CanBeNull] protected IResourceStore Samples; public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) @@ -37,8 +40,11 @@ namespace osu.Game.Skinning else Configuration = new DefaultSkinConfiguration(); - Samples = audioManager?.GetSampleStore(storage); - Textures = new TextureStore(new TextureLoaderStore(storage)); + if (storage != null) + { + Samples = audioManager?.GetSampleStore(storage); + Textures = new TextureStore(new TextureLoaderStore(storage)); + } } protected override void Dispose(bool isDisposing) @@ -125,12 +131,12 @@ namespace osu.Game.Skinning componentName = getFallbackName(componentName); float ratio = 2; - var texture = Textures.Get($"{componentName}@2x"); + var texture = Textures?.Get($"{componentName}@2x"); if (texture == null) { ratio = 1; - texture = Textures.Get(componentName); + texture = Textures?.Get(componentName); } if (texture != null) @@ -143,7 +149,7 @@ namespace osu.Game.Skinning { foreach (var lookup in sampleInfo.LookupNames) { - var sample = Samples.Get(getFallbackName(lookup)); + var sample = Samples?.Get(getFallbackName(lookup)); if (sample != null) return sample; @@ -151,7 +157,7 @@ namespace osu.Game.Skinning if (sampleInfo is HitSampleInfo hsi) // Try fallback to non-bank samples. - return Samples.Get(hsi.Name); + return Samples?.Get(hsi.Name); return null; } From 07f662071d5c7dc31424e692fb9e438587cff662 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 4 Sep 2019 18:14:55 +0900 Subject: [PATCH 2778/5608] Remove judgementOccurred --- .../Objects/Drawables/DrawableHitObject.cs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 1a224b2cea..f7efa625a5 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -76,8 +76,6 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public JudgementResult Result { get; private set; } - private bool judgementOccurred; - public override bool RemoveWhenNotAlive => false; public override bool RemoveCompletedTransforms => false; protected override bool RequiresChildrenUpdate => true; @@ -342,8 +340,6 @@ namespace osu.Game.Rulesets.Objects.Drawables if (!Result.HasResult) throw new InvalidOperationException($"{GetType().ReadableName()} applied a {nameof(JudgementResult)} but did not update {nameof(JudgementResult.Type)}."); - judgementOccurred = true; - // Ensure that the judgement is given a valid time offset, because this may not get set by the caller var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; Result.TimeOffset = Time.Current - endTime; @@ -376,21 +372,13 @@ namespace osu.Game.Rulesets.Objects.Drawables if (Time.Elapsed < 0) return false; - judgementOccurred = false; - - if (AllJudged) + if (Judged) return false; - foreach (var d in NestedHitObjects) - judgementOccurred |= d.UpdateResult(userTriggered); - - if (judgementOccurred || Judged) - return judgementOccurred; - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; CheckForResult(userTriggered, Time.Current - endTime); - return judgementOccurred; + return Judged; } /// From a87a1e60314352fc3bd241935d5116f9e07cc075 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 4 Sep 2019 19:38:12 +0900 Subject: [PATCH 2779/5608] Don't redraw certain buffered containers on scale change --- osu.Game/Graphics/Backgrounds/Background.cs | 3 ++- osu.Game/Overlays/NowPlayingOverlay.cs | 5 ++++- osu.Game/Screens/Play/SquareGraph.cs | 1 + osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 ++ .../Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs | 1 + 5 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index d13475189d..0f923c3a28 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -57,8 +57,9 @@ namespace osu.Game.Graphics.Backgrounds AddInternal(bufferedContainer = new BufferedContainer { - CacheDrawnFrameBuffer = true, RelativeSizeAxes = Axes.Both, + CacheDrawnFrameBuffer = true, + RedrawOnScale = false, Child = Sprite }); } diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index a3243a655e..c8361c6114 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -346,10 +346,13 @@ namespace osu.Game.Overlays public Background(WorkingBeatmap beatmap = null) { this.beatmap = beatmap; - CacheDrawnFrameBuffer = true; + Depth = float.MaxValue; RelativeSizeAxes = Axes.Both; + CacheDrawnFrameBuffer = true; + RedrawOnScale = false; + Children = new Drawable[] { sprite = new Sprite diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 9c56725c4e..05f6128ac2 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -103,6 +103,7 @@ namespace osu.Game.Screens.Play var newColumns = new BufferedContainer { CacheDrawnFrameBuffer = true, + RedrawOnScale = false, RelativeSizeAxes = Axes.Both, }; diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 5f6307e3b4..65ecd7b812 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -154,6 +154,8 @@ namespace osu.Game.Screens.Select var metadata = beatmapInfo.Metadata ?? beatmap.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); CacheDrawnFrameBuffer = true; + RedrawOnScale = false; + RelativeSizeAxes = Axes.Both; titleBinding = localisation.GetLocalisedString(new LocalisedString((metadata.TitleUnicode, metadata.Title))); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 97b6a78804..699e01bca7 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -146,6 +146,7 @@ namespace osu.Game.Screens.Select.Carousel public PanelBackground(WorkingBeatmap working) { CacheDrawnFrameBuffer = true; + RedrawOnScale = false; Children = new Drawable[] { From b80a8296cd591db9dd34b8746fdbb85570694be2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 20:27:27 +0900 Subject: [PATCH 2780/5608] Fix unavailable rulesets crashing at song select --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 2 +- osu.Game/Rulesets/RulesetInfo.cs | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 81f517dd86..8014631eca 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -84,7 +84,7 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, // the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment) - Icon = ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle } + Icon = ruleset?.CreateInstance()?.CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle } } }; } diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index d9cff86265..c982ef7be1 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using JetBrains.Annotations; using Newtonsoft.Json; namespace osu.Game.Rulesets @@ -20,7 +21,13 @@ namespace osu.Game.Rulesets [JsonIgnore] public bool Available { get; set; } - public virtual Ruleset CreateInstance() => (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo), this); + [CanBeNull] + public virtual Ruleset CreateInstance() + { + if (!Available) return null; + + return (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo), this); + } public bool Equals(RulesetInfo other) => other != null && ID == other.ID && Available == other.Available && Name == other.Name && InstantiationInfo == other.InstantiationInfo; From c59a2bf9bb6bce70906c6fd3b3e99417ff314249 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 20:28:04 +0900 Subject: [PATCH 2781/5608] Fix tests crashing if a ruleset doesn't provide a NoFail mod --- osu.Game/Tests/Visual/PlayerTestScene.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/PlayerTestScene.cs b/osu.Game/Tests/Visual/PlayerTestScene.cs index ccd996098c..2c5a51ca02 100644 --- a/osu.Game/Tests/Visual/PlayerTestScene.cs +++ b/osu.Game/Tests/Visual/PlayerTestScene.cs @@ -50,7 +50,11 @@ namespace osu.Game.Tests.Visual Beatmap.Value = CreateWorkingBeatmap(beatmap); if (!AllowFail) - Mods.Value = new[] { ruleset.GetAllMods().First(m => m is ModNoFail) }; + { + var noFailMod = ruleset.GetAllMods().FirstOrDefault(m => m is ModNoFail); + if (noFailMod != null) + Mods.Value = new[] { noFailMod }; + } if (Autoplay) { From 6197c7fd31d3edcbae5a07c1b06d7157b3eb25b6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 20:28:21 +0900 Subject: [PATCH 2782/5608] Add automatic resource mapping for rulesets to their own dll --- osu.Game/Rulesets/Ruleset.cs | 3 +++ osu.Game/Rulesets/UI/DrawableRuleset.cs | 20 ++++++++++++++++++++ osu.Game/Skinning/SkinnableSound.cs | 14 ++++++++------ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index b63292757d..197c089f71 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; +using osu.Framework.IO.Stores; using osu.Game.Beatmaps; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Edit; @@ -83,6 +84,8 @@ namespace osu.Game.Rulesets public virtual Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.Solid.QuestionCircle }; + public virtual IResourceStore CreateReourceStore() => new NamespacedResourceStore(new DllResourceStore(GetType().Assembly.Location), @"Resources"); + public abstract string Description { get; } public virtual RulesetSettingsSubsection CreateSettings() => null; diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index a32407d180..562b2c4667 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -14,10 +14,14 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using JetBrains.Annotations; +using osu.Framework.Audio; +using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Textures; using osu.Framework.Input; using osu.Framework.Input.Events; +using osu.Framework.IO.Stores; using osu.Game.Configuration; using osu.Game.Graphics.Cursor; using osu.Game.Input.Handlers; @@ -51,6 +55,10 @@ namespace osu.Game.Rulesets.UI private readonly Lazy playfield; + private TextureStore textureStore; + + private ISampleStore sampleStore; + /// /// The playfield. /// @@ -142,6 +150,18 @@ namespace osu.Game.Rulesets.UI { var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + var resources = Ruleset.CreateReourceStore(); + + if (resources != null) + { + textureStore = new TextureStore(new TextureLoaderStore(new NamespacedResourceStore(resources, "Textures"))); + textureStore.AddStore(dependencies.Get()); + dependencies.Cache(textureStore); + + sampleStore = dependencies.Get().GetSampleStore(new NamespacedResourceStore(resources, "Samples")); + dependencies.CacheAs(sampleStore); + } + onScreenDisplay = dependencies.Get(); Config = dependencies.Get().GetConfigFor(Ruleset); diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 3d0219ed93..bdf8be773b 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -6,6 +6,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Audio; @@ -20,7 +21,7 @@ namespace osu.Game.Skinning private SampleChannel[] channels; - private AudioManager audio; + private ISampleStore samples; public SkinnableSound(IEnumerable hitSamples) { @@ -33,9 +34,9 @@ namespace osu.Game.Skinning } [BackgroundDependencyLoader] - private void load(AudioManager audio) + private void load(ISampleStore samples) { - this.audio = audio; + this.samples = samples; } private bool looping; @@ -81,7 +82,7 @@ namespace osu.Game.Skinning if (ch == null && allowFallback) foreach (var lookup in s.LookupNames) - if ((ch = audio.Samples.Get($"Gameplay/{lookup}")) != null) + if ((ch = samples.Get($"Gameplay/{lookup}")) != null) break; if (ch != null) @@ -102,8 +103,9 @@ namespace osu.Game.Skinning { base.Dispose(isDisposing); - foreach (var c in channels) - c.Dispose(); + if (channels != null) + foreach (var c in channels) + c.Dispose(); } } } From 8e8f33ec7b5fb0a24f279692c76ba3d214997bc2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 21:35:59 +0900 Subject: [PATCH 2783/5608] Remove null hinting for now --- osu.Game/Rulesets/RulesetInfo.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index c982ef7be1..6a69fd8dd0 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -3,7 +3,6 @@ using System; using System.Diagnostics.CodeAnalysis; -using JetBrains.Annotations; using Newtonsoft.Json; namespace osu.Game.Rulesets @@ -21,7 +20,6 @@ namespace osu.Game.Rulesets [JsonIgnore] public bool Available { get; set; } - [CanBeNull] public virtual Ruleset CreateInstance() { if (!Available) return null; From f9fa5988e69a679a7a344baa0a1855703d7f7caf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Sep 2019 23:16:56 +0900 Subject: [PATCH 2784/5608] Add basic nuget deploy support --- appveyor.yml | 2 -- appveyor_deploy.yml | 10 ++++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 appveyor_deploy.yml diff --git a/appveyor.yml b/appveyor.yml index 4dcaa7b45e..be1727e7d7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,7 +2,5 @@ clone_depth: 1 version: '{branch}-{build}' image: Previous Visual Studio 2017 test: off -install: - - cmd: git submodule update --init --recursive --depth=5 build_script: - cmd: PowerShell -Version 2.0 .\build.ps1 diff --git a/appveyor_deploy.yml b/appveyor_deploy.yml new file mode 100644 index 0000000000..d36298175b --- /dev/null +++ b/appveyor_deploy.yml @@ -0,0 +1,10 @@ +clone_depth: 1 +version: '{build}' +image: Previous Visual Studio 2017 +test: off +skip_non_tags: true +build_script: + - cmd: PowerShell -Version 2.0 .\build.ps1 +deploy: + - provider: Environment + name: nuget From 50de4d1a3a4569da2532c52b3b74371f28f46ae7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Sep 2019 01:11:53 +0900 Subject: [PATCH 2785/5608] Remove PrivateAssets changes for now --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3147ca749f..f2a605e7a7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + From afac512a1bfd09d115fc60b9dcfc5d8c0b7e776e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Sep 2019 02:12:17 +0900 Subject: [PATCH 2786/5608] Fix databased config save performance Adds proper save debounce logic. Closes #5991. --- .../Configuration/DatabasedConfigManager.cs | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs index d5cdd7e4bc..6aa89cdd69 100644 --- a/osu.Game/Configuration/DatabasedConfigManager.cs +++ b/osu.Game/Configuration/DatabasedConfigManager.cs @@ -16,11 +16,11 @@ namespace osu.Game.Configuration private readonly int? variant; - private readonly List databasedSettings; + private List databasedSettings; private readonly RulesetInfo ruleset; - private readonly bool legacySettingsExist; + private bool legacySettingsExist; protected DatabasedConfigManager(SettingsStore settings, RulesetInfo ruleset = null, int? variant = null) { @@ -28,21 +28,34 @@ namespace osu.Game.Configuration this.ruleset = ruleset; this.variant = variant; - databasedSettings = settings.Query(ruleset?.ID, variant); - legacySettingsExist = databasedSettings.Any(s => int.TryParse(s.Key, out var _)); + Load(); InitialiseDefaults(); } protected override void PerformLoad() { + databasedSettings = settings.Query(ruleset?.ID, variant); + legacySettingsExist = databasedSettings.Any(s => int.TryParse(s.Key, out var _)); } protected override bool PerformSave() { + lock (dirtySettings) + { + if (dirtySettings.Count > 0) + { + foreach (var setting in dirtySettings) + settings.Update(setting); + dirtySettings.Clear(); + } + } + return true; } + private readonly List dirtySettings = new List(); + protected override void AddBindable(T lookup, Bindable bindable) { base.AddBindable(lookup, bindable); @@ -80,7 +93,9 @@ namespace osu.Game.Configuration bindable.ValueChanged += b => { setting.Value = b.NewValue; - settings.Update(setting); + lock (dirtySettings) + if (!dirtySettings.Contains(setting)) + dirtySettings.Add(setting); }; } } From a1c580f27ecae7f58bc6fbf6b58de8b6cef9b885 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 5 Sep 2019 05:56:21 +0300 Subject: [PATCH 2787/5608] Create "none selected" placeholder state --- osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs | 1 + osu.Game/Online/Leaderboards/Leaderboard.cs | 4 ++++ osu.Game/Online/Leaderboards/PlaceholderState.cs | 1 + .../Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 8 +++++++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs index 8e358a77db..186f27a8b2 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs @@ -42,6 +42,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter)); AddStep(@"Not logged in", () => leaderboard.SetRetrievalState(PlaceholderState.NotLoggedIn)); AddStep(@"Unavailable", () => leaderboard.SetRetrievalState(PlaceholderState.Unavailable)); + AddStep(@"None selected", () => leaderboard.SetRetrievalState(PlaceholderState.NoneSelected)); foreach (BeatmapSetOnlineStatus status in Enum.GetValues(typeof(BeatmapSetOnlineStatus))) AddStep($"{status} beatmap", () => showBeatmapWithStatus(status)); } diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 98f15599fc..147556b78b 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -133,6 +133,10 @@ namespace osu.Game.Online.Leaderboards }); break; + case PlaceholderState.NoneSelected: + replacePlaceholder(new MessagePlaceholder(@"Please select a beatmap!")); + break; + case PlaceholderState.Unavailable: replacePlaceholder(new MessagePlaceholder(@"Leaderboards are not available for this beatmap!")); break; diff --git a/osu.Game/Online/Leaderboards/PlaceholderState.cs b/osu.Game/Online/Leaderboards/PlaceholderState.cs index 930e1df484..297241fa73 100644 --- a/osu.Game/Online/Leaderboards/PlaceholderState.cs +++ b/osu.Game/Online/Leaderboards/PlaceholderState.cs @@ -9,6 +9,7 @@ namespace osu.Game.Online.Leaderboards Retrieving, NetworkFailure, Unavailable, + NoneSelected, NoScores, NotLoggedIn, NotSupporter, diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index cb45c00f66..33f040755e 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -83,6 +83,12 @@ namespace osu.Game.Screens.Select.Leaderboards protected override APIRequest FetchScores(Action> scoresCallback) { + if (Beatmap == null) + { + PlaceholderState = PlaceholderState.NoneSelected; + return null; + } + if (Scope == BeatmapLeaderboardScope.Local) { var scores = scoreManager @@ -113,7 +119,7 @@ namespace osu.Game.Screens.Select.Leaderboards return null; } - if (Beatmap?.OnlineBeatmapID == null || Beatmap?.Status <= BeatmapSetOnlineStatus.Pending) + if (Beatmap.OnlineBeatmapID == null || Beatmap?.Status <= BeatmapSetOnlineStatus.Pending) { PlaceholderState = PlaceholderState.Unavailable; return null; From 1b0123a60cb22e89f009b2befbc024960dee706f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 5 Sep 2019 05:56:52 +0300 Subject: [PATCH 2788/5608] Set beatmap of leaderboard to null if NoBeatmapsAvailable is selected --- osu.Game/Screens/Select/BeatmapDetailArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index b66a2ffe0f..bf8fc8cf07 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -27,8 +27,8 @@ namespace osu.Game.Screens.Select set { beatmap = value; - Leaderboard.Beatmap = beatmap?.BeatmapInfo; Details.Beatmap = beatmap?.BeatmapInfo; + Leaderboard.Beatmap = beatmap is NoBeatmapsAvailableWorkingBeatmap ? null : beatmap?.BeatmapInfo; } } From d40129aabe9a8947add0a28b6a51fa85b7017365 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Sep 2019 13:36:37 +0900 Subject: [PATCH 2789/5608] Remove unnecessary count check --- osu.Game/Configuration/DatabasedConfigManager.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs index 6aa89cdd69..0046f4fa7f 100644 --- a/osu.Game/Configuration/DatabasedConfigManager.cs +++ b/osu.Game/Configuration/DatabasedConfigManager.cs @@ -43,12 +43,9 @@ namespace osu.Game.Configuration { lock (dirtySettings) { - if (dirtySettings.Count > 0) - { - foreach (var setting in dirtySettings) - settings.Update(setting); - dirtySettings.Clear(); - } + foreach (var setting in dirtySettings) + settings.Update(setting); + dirtySettings.Clear(); } return true; From 070a005294668614deaf2779450eed7b1e90051e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Sep 2019 13:37:11 +0900 Subject: [PATCH 2790/5608] Add braces to lock() Personal preference, I want to be sure that everything is wrapped correctly. --- osu.Game/Configuration/DatabasedConfigManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs index 0046f4fa7f..02382cfd2b 100644 --- a/osu.Game/Configuration/DatabasedConfigManager.cs +++ b/osu.Game/Configuration/DatabasedConfigManager.cs @@ -90,9 +90,12 @@ namespace osu.Game.Configuration bindable.ValueChanged += b => { setting.Value = b.NewValue; + lock (dirtySettings) + { if (!dirtySettings.Contains(setting)) dirtySettings.Add(setting); + } }; } } From 2e6af84ca839d5e22f6fdab8fe790c0fd80894c4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Sep 2019 14:39:02 +0900 Subject: [PATCH 2791/5608] Don't redraw leaderboard scores --- osu.Game/Graphics/Sprites/GlowingSpriteText.cs | 9 ++++++++- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs index 24816deeb5..892b27da75 100644 --- a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs @@ -12,6 +12,7 @@ namespace osu.Game.Graphics.Sprites public class GlowingSpriteText : Container, IHasText { private readonly OsuSpriteText spriteText, blurredText; + private readonly BufferedContainer buffer; public string Text { @@ -43,13 +44,19 @@ namespace osu.Game.Graphics.Sprites set => blurredText.Colour = value; } + public bool RedrawOnScale + { + get => buffer.RedrawOnScale; + set => buffer.RedrawOnScale = value; + } + public GlowingSpriteText() { AutoSizeAxes = Axes.Both; Children = new Drawable[] { - new BufferedContainer + buffer = new BufferedContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 008f8208eb..e29748060e 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -193,6 +193,7 @@ namespace osu.Game.Online.Leaderboards GlowColour = OsuColour.FromHex(@"83ccfa"), Text = score.TotalScore.ToString(@"N0"), Font = OsuFont.Numeric.With(size: 23), + RedrawOnScale = false, }, RankContainer = new Container { @@ -338,6 +339,7 @@ namespace osu.Game.Online.Leaderboards GlowColour = OsuColour.FromHex(@"83ccfa"), Text = statistic.Value, Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold), + RedrawOnScale = false }, }, }; From 99579255ade422b7985b80c2dce5034735d8038c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Sep 2019 14:41:02 +0900 Subject: [PATCH 2792/5608] Force glowing sprite text to never redraw --- osu.Game/Graphics/Sprites/GlowingSpriteText.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs index 892b27da75..12688da9df 100644 --- a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs @@ -12,7 +12,6 @@ namespace osu.Game.Graphics.Sprites public class GlowingSpriteText : Container, IHasText { private readonly OsuSpriteText spriteText, blurredText; - private readonly BufferedContainer buffer; public string Text { @@ -44,24 +43,19 @@ namespace osu.Game.Graphics.Sprites set => blurredText.Colour = value; } - public bool RedrawOnScale - { - get => buffer.RedrawOnScale; - set => buffer.RedrawOnScale = value; - } - public GlowingSpriteText() { AutoSizeAxes = Axes.Both; Children = new Drawable[] { - buffer = new BufferedContainer + new BufferedContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, BlurSigma = new Vector2(4), CacheDrawnFrameBuffer = true, + RedrawOnScale = false, RelativeSizeAxes = Axes.Both, Blending = BlendingParameters.Additive, Size = new Vector2(3f), From a1d7291ffa8623eeb91bebb947bba1423e0ee1ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Sep 2019 16:31:10 +0900 Subject: [PATCH 2793/5608] Fix pause menu keyboard navigation being affected by initial cursor hover --- .../Visual/Gameplay/TestSceneGameplayMenuOverlay.cs | 9 +++++++-- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs index cc275009ba..c1635ffc83 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs @@ -17,7 +17,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - [System.ComponentModel.Description("player pause/fail screens")] + [Description("player pause/fail screens")] public class TestSceneGameplayMenuOverlay : ManualInputManagerTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(FailOverlay), typeof(PauseOverlay) }; @@ -152,7 +152,8 @@ namespace osu.Game.Tests.Visual.Gameplay } /// - /// Tests that entering menu with cursor initially on button selects it. + /// Tests that entering menu with cursor initially on button doesn't selects it immediately. + /// This is to allow for stable keyboard navigation. /// [Test] public void TestInitialButtonHover() @@ -164,6 +165,10 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("Hide overlay", () => pauseOverlay.Hide()); showOverlay(); + AddAssert("First button not selected", () => !getButton(0).Selected.Value); + + AddStep("Move slightly", () => InputManager.MoveMouseTo(InputManager.CurrentState.Mouse.Position + new Vector2(1))); + AddAssert("First button selected", () => getButton(0).Selected.Value); } diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index f93d5d8b02..c5202fa792 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -304,6 +304,9 @@ namespace osu.Game.Screens.Play private class Button : DialogButton { + // required to ensure keyboard navigation always starts from an extremity (unless the cursor is moved) + protected override bool OnHover(HoverEvent e) => true; + protected override bool OnMouseMove(MouseMoveEvent e) { Selected.Value = true; From 55c6feab6408d37f69c26706eb981906d5e61bc9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Sep 2019 16:33:14 +0900 Subject: [PATCH 2794/5608] 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 90d1854c39..adc340a734 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -61,6 +61,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 7d106f0484..cb30eee33a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 8390a2229b..88d181454f 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From 174f8ddb31b75b9a4e925c05871ea22f37a97fe0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Sep 2019 16:37:47 +0900 Subject: [PATCH 2795/5608] Remove incorrect usages --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index e29748060e..008f8208eb 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -193,7 +193,6 @@ namespace osu.Game.Online.Leaderboards GlowColour = OsuColour.FromHex(@"83ccfa"), Text = score.TotalScore.ToString(@"N0"), Font = OsuFont.Numeric.With(size: 23), - RedrawOnScale = false, }, RankContainer = new Container { @@ -339,7 +338,6 @@ namespace osu.Game.Online.Leaderboards GlowColour = OsuColour.FromHex(@"83ccfa"), Text = statistic.Value, Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold), - RedrawOnScale = false }, }, }; From bda21998c4de0a87d57ed019a6c77b0c86925223 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Sep 2019 16:39:58 +0900 Subject: [PATCH 2796/5608] Add helper method to make direct casts be used --- .../Skinning/OsuLegacySkinTransformer.cs | 2 +- .../Skins/TestSceneSkinConfigurationLookup.cs | 19 +++++++++++++++++++ osu.Game/Skinning/LegacySkin.cs | 6 +++--- osu.Game/Skinning/SkinUtils.cs | 18 ++++++++++++++++++ 4 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Skinning/SkinUtils.cs diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 284259705a..5957b81d7e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Osu.Skinning { case OsuSkinConfiguration.SliderPathRadius: if (hasHitCircle.Value) - return new BindableFloat(legacy_circle_radius) as Bindable; + return SkinUtils.As(new BindableFloat(legacy_circle_radius)); break; } diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index 1344d20d9f..71df038311 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -95,6 +95,25 @@ namespace osu.Game.Tests.Skins AddAssert("Check combo colours", () => requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.Count > 0); } + [Test] + public void TestWrongColourType() + { + AddStep("Add config colour", () => { source1.Configuration.CustomColours["Lookup"] = Color4.Red; }); + + AddAssert("perform incorrect lookup", () => + { + try + { + requester.GetConfig(new SkinCustomColourLookup("Lookup")); + return false; + } + catch + { + return true; + } + }); + } + public enum LookupType { Test diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index cd2ad2d61c..0b1076be01 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -62,16 +62,16 @@ namespace osu.Game.Skinning switch (global) { case GlobalSkinConfiguration.ComboColours: - return new Bindable>(Configuration.ComboColours) as IBindable; + return SkinUtils.As(new Bindable>(Configuration.ComboColours)); } break; case GlobalSkinColour colour: - return getCustomColour(colour.ToString()) as IBindable; + return SkinUtils.As(getCustomColour(colour.ToString())); case SkinCustomColourLookup customColour: - return getCustomColour(customColour.Lookup.ToString()) as IBindable; + return SkinUtils.As(getCustomColour(customColour.Lookup.ToString())); default: try diff --git a/osu.Game/Skinning/SkinUtils.cs b/osu.Game/Skinning/SkinUtils.cs new file mode 100644 index 0000000000..18059bc4bf --- /dev/null +++ b/osu.Game/Skinning/SkinUtils.cs @@ -0,0 +1,18 @@ +using osu.Framework.Bindables; + +namespace osu.Game.Skinning +{ + /// + /// Contains helper methods to assist in implementing s. + /// + public static class SkinUtils + { + /// + /// Converts an to a . Used for returning configuration values of specific types. + /// + /// The value. + /// The type of value , and the type of the resulting bindable. + /// The resulting bindable. + public static Bindable As(object value) => (Bindable)value; + } +} From 696802e6743088e1d450ad822f940afe348c4f1e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Sep 2019 16:52:53 +0900 Subject: [PATCH 2797/5608] Don't use in music player for now --- osu.Game/Overlays/NowPlayingOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index c8361c6114..cf42c8005a 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -351,7 +351,6 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both; CacheDrawnFrameBuffer = true; - RedrawOnScale = false; Children = new Drawable[] { From 8e204ba2e90182dd3f691d94fa58ac526b91232e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Sep 2019 16:55:24 +0900 Subject: [PATCH 2798/5608] Refactor tests --- .../Skins/TestSceneSkinConfigurationLookup.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index 71df038311..bbcc4140a9 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -44,24 +44,24 @@ namespace osu.Game.Tests.Skins } [Test] - public void TestParsingLookup() + public void TestFloatLookup() { - AddStep("Add config values", () => - { - source1.Configuration.ConfigDictionary["FloatTest"] = "1.1"; - source2.Configuration.ConfigDictionary["BoolTest"] = "1"; - }); - + AddStep("Add config values", () => source1.Configuration.ConfigDictionary["FloatTest"] = "1.1"); AddAssert("Check float parse lookup", () => requester.GetConfig("FloatTest")?.Value == 1.1f); + } + + [Test] + public void TestBoolLookup() + { + AddStep("Add config values", () => source1.Configuration.ConfigDictionary["BoolTest"] = "1"); AddAssert("Check bool parse lookup", () => requester.GetConfig("BoolTest")?.Value == true); } [Test] public void TestEnumLookup() { - AddStep("Add config values", () => { source1.Configuration.ConfigDictionary["Test"] = "Test2"; }); - - AddAssert("Check float parse lookup", () => requester.GetConfig(LookupType.Test)?.Value == ValueType.Test2); + AddStep("Add config values", () => source1.Configuration.ConfigDictionary["Test"] = "Test2"); + AddAssert("Check enum parse lookup", () => requester.GetConfig(LookupType.Test)?.Value == ValueType.Test2); } [Test] @@ -73,7 +73,7 @@ namespace osu.Game.Tests.Skins [Test] public void TestLookupNull() { - AddStep("Add config values", () => { source1.Configuration.ConfigDictionary["Lookup"] = null; }); + AddStep("Add config values", () => source1.Configuration.ConfigDictionary["Lookup"] = null); AddAssert("Check lookup null", () => { @@ -85,7 +85,7 @@ namespace osu.Game.Tests.Skins [Test] public void TestColourLookup() { - AddStep("Add config colour", () => { source1.Configuration.CustomColours["Lookup"] = Color4.Red; }); + AddStep("Add config colour", () => source1.Configuration.CustomColours["Lookup"] = Color4.Red); AddAssert("Check colour lookup", () => requester.GetConfig(new SkinCustomColourLookup("Lookup"))?.Value == Color4.Red); } @@ -98,7 +98,7 @@ namespace osu.Game.Tests.Skins [Test] public void TestWrongColourType() { - AddStep("Add config colour", () => { source1.Configuration.CustomColours["Lookup"] = Color4.Red; }); + AddStep("Add config colour", () => source1.Configuration.CustomColours["Lookup"] = Color4.Red); AddAssert("perform incorrect lookup", () => { From 90985b6af65a6008b55fd968d523e7c9ebc40d05 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Sep 2019 17:00:43 +0900 Subject: [PATCH 2799/5608] Add missing license header --- osu.Game/Skinning/SkinUtils.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Skinning/SkinUtils.cs b/osu.Game/Skinning/SkinUtils.cs index 18059bc4bf..e3bc5e28b8 100644 --- a/osu.Game/Skinning/SkinUtils.cs +++ b/osu.Game/Skinning/SkinUtils.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Framework.Bindables; namespace osu.Game.Skinning From 0a6c42972c8896ef0943133b93661895cb129841 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Sep 2019 23:01:35 +0900 Subject: [PATCH 2800/5608] Add back missing sample fallback to default skin --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 8 ++- osu.Game/Rulesets/UI/FallbackSampleStore.cs | 64 +++++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Rulesets/UI/FallbackSampleStore.cs diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 562b2c4667..2a8f64c42e 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.UI private TextureStore textureStore; - private ISampleStore sampleStore; + private ISampleStore localSampleStore; /// /// The playfield. @@ -158,8 +158,8 @@ namespace osu.Game.Rulesets.UI textureStore.AddStore(dependencies.Get()); dependencies.Cache(textureStore); - sampleStore = dependencies.Get().GetSampleStore(new NamespacedResourceStore(resources, "Samples")); - dependencies.CacheAs(sampleStore); + localSampleStore = dependencies.Get().GetSampleStore(new NamespacedResourceStore(resources, "Samples")); + dependencies.CacheAs(new FallbackSampleStore(localSampleStore, dependencies.Get())); } onScreenDisplay = dependencies.Get(); @@ -334,6 +334,8 @@ namespace osu.Game.Rulesets.UI { base.Dispose(isDisposing); + localSampleStore?.Dispose(); + if (Config != null) { onScreenDisplay?.StopTracking(this, Config); diff --git a/osu.Game/Rulesets/UI/FallbackSampleStore.cs b/osu.Game/Rulesets/UI/FallbackSampleStore.cs new file mode 100644 index 0000000000..64e273b72e --- /dev/null +++ b/osu.Game/Rulesets/UI/FallbackSampleStore.cs @@ -0,0 +1,64 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Audio.Track; +using osu.Framework.Bindables; + +namespace osu.Game.Rulesets.UI +{ + public class FallbackSampleStore : ISampleStore + { + private readonly ISampleStore primary; + private readonly ISampleStore secondary; + + public FallbackSampleStore(ISampleStore primary, ISampleStore secondary) + { + this.primary = primary; + this.secondary = secondary; + } + + public void Dispose() + { + primary.Dispose(); + secondary.Dispose(); + } + + public SampleChannel Get(string name) => primary.Get(name) ?? secondary.Get(name); + + public Task GetAsync(string name) => primary.GetAsync(name) ?? secondary.GetAsync(name); + + public Stream GetStream(string name) => primary.GetStream(name) ?? secondary.GetStream(name); + + public IEnumerable GetAvailableResources() => primary.GetAvailableResources().Concat(secondary.GetAvailableResources()); + + public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) + { + primary.AddAdjustment(type, adjustBindable); + secondary.AddAdjustment(type, adjustBindable); + } + + public void RemoveAdjustment(AdjustableProperty type, BindableDouble adjustBindable) + { + primary.RemoveAdjustment(type, adjustBindable); + primary.RemoveAdjustment(type, adjustBindable); + } + + public BindableDouble Volume => primary.Volume; + + public BindableDouble Balance => primary.Balance; + + public BindableDouble Frequency => primary.Frequency; + + public int PlaybackConcurrency + { + get => primary.PlaybackConcurrency; + set => primary.PlaybackConcurrency = value; + } + } +} From 60c2d113b80eed1630d0ccdc951a3b1fa954b9e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Sep 2019 23:07:03 +0900 Subject: [PATCH 2801/5608] Fix typo --- osu.Game/Rulesets/UI/FallbackSampleStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/FallbackSampleStore.cs b/osu.Game/Rulesets/UI/FallbackSampleStore.cs index 64e273b72e..cdefae458a 100644 --- a/osu.Game/Rulesets/UI/FallbackSampleStore.cs +++ b/osu.Game/Rulesets/UI/FallbackSampleStore.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.UI public void RemoveAdjustment(AdjustableProperty type, BindableDouble adjustBindable) { primary.RemoveAdjustment(type, adjustBindable); - primary.RemoveAdjustment(type, adjustBindable); + secondary.RemoveAdjustment(type, adjustBindable); } public BindableDouble Volume => primary.Volume; From a0aeccf2322d06c782c9fc15d5eda86d1b15df6b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Sep 2019 23:24:13 +0900 Subject: [PATCH 2802/5608] Fix fallback to default combo colours not working --- osu.Game/Skinning/DefaultSkin.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs index 4dee70a47f..c0d6bb34e0 100644 --- a/osu.Game/Skinning/DefaultSkin.cs +++ b/osu.Game/Skinning/DefaultSkin.cs @@ -1,11 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Game.Audio; +using osuTK.Graphics; namespace osu.Game.Skinning { @@ -23,6 +25,21 @@ namespace osu.Game.Skinning public override SampleChannel GetSample(ISampleInfo sampleInfo) => null; - public override IBindable GetConfig(TLookup lookup) => null; + public override IBindable GetConfig(TLookup lookup) + { + switch (lookup) + { + case GlobalSkinConfiguration global: + switch (global) + { + case GlobalSkinConfiguration.ComboColours: + return SkinUtils.As(new Bindable>(Configuration.ComboColours)); + } + + break; + } + + return null; + } } } From dafe9da851437098d15f6104ce720d7eba2fc351 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 00:22:35 +0900 Subject: [PATCH 2803/5608] Dispose config managers ahead of time to avoid database errors --- osu.Game/Rulesets/RulesetConfigCache.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index 8c9e3c94e2..abaf7a96f2 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -36,5 +36,13 @@ namespace osu.Game.Rulesets return configCache.GetOrAdd(ruleset.RulesetInfo.ID.Value, _ => ruleset.CreateConfig(settingsStore)); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + foreach (var c in configCache.Values) + (c as IDisposable)?.Dispose(); + } } } From 5b094f8e1de30a7473e9b29c9b7933696f77c226 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 01:13:58 +0900 Subject: [PATCH 2804/5608] Actually register the RulesetConfigCache as a component --- osu.Game/OsuGameBase.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index de8f316b06..d6b8ad3e67 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -207,6 +207,7 @@ namespace osu.Game FileStore.Cleanup(); AddInternal(API); + AddInternal(RulesetConfigCache); GlobalActionContainer globalBinding; From d6cdde552daa84e04a76e6bf1c1d61872002c0bb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 01:14:37 +0900 Subject: [PATCH 2805/5608] Add comment explaining dispose logic --- osu.Game/Rulesets/RulesetConfigCache.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index abaf7a96f2..cdcd2666cf 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -41,6 +41,7 @@ namespace osu.Game.Rulesets { base.Dispose(isDisposing); + // ensures any potential database operations are finalised before game destruction. foreach (var c in configCache.Values) (c as IDisposable)?.Dispose(); } From 50985d1b1d952b7d922c0a4ccd3936218061cc26 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 10:43:19 +0900 Subject: [PATCH 2806/5608] Fix disposal logic --- osu.Game/Rulesets/UI/FallbackSampleStore.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/UI/FallbackSampleStore.cs b/osu.Game/Rulesets/UI/FallbackSampleStore.cs index cdefae458a..f9e1c85e38 100644 --- a/osu.Game/Rulesets/UI/FallbackSampleStore.cs +++ b/osu.Game/Rulesets/UI/FallbackSampleStore.cs @@ -23,12 +23,6 @@ namespace osu.Game.Rulesets.UI this.secondary = secondary; } - public void Dispose() - { - primary.Dispose(); - secondary.Dispose(); - } - public SampleChannel Get(string name) => primary.Get(name) ?? secondary.Get(name); public Task GetAsync(string name) => primary.GetAsync(name) ?? secondary.GetAsync(name); @@ -58,7 +52,15 @@ namespace osu.Game.Rulesets.UI public int PlaybackConcurrency { get => primary.PlaybackConcurrency; - set => primary.PlaybackConcurrency = value; + set + { + primary.PlaybackConcurrency = value; + secondary.PlaybackConcurrency = value; + } + } + + public void Dispose() + { } } } From 43aed7fea7c1be8da0e906f5f18d6dafc17f6716 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 6 Sep 2019 02:58:58 +0000 Subject: [PATCH 2807/5608] Bump Humanizer from 2.6.2 to 2.7.2 Bumps [Humanizer](https://github.com/Humanizr/Humanizer) from 2.6.2 to 2.7.2. - [Release notes](https://github.com/Humanizr/Humanizer/releases) - [Changelog](https://github.com/Humanizr/Humanizer/blob/master/release_notes.md) - [Commits](https://github.com/Humanizr/Humanizer/compare/v2.6.2...v2.7.2) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8e4ce03e1a..5f2aad24dc 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 88d181454f..5027a4ef8c 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -113,7 +113,7 @@ - + From 7d1f5310d20a866a9b8c9283eb3a2a1bc6903840 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 12:03:29 +0900 Subject: [PATCH 2808/5608] Don't implement anything --- osu.Game/Rulesets/UI/FallbackSampleStore.cs | 30 +++++++-------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/osu.Game/Rulesets/UI/FallbackSampleStore.cs b/osu.Game/Rulesets/UI/FallbackSampleStore.cs index f9e1c85e38..f1df8bf359 100644 --- a/osu.Game/Rulesets/UI/FallbackSampleStore.cs +++ b/osu.Game/Rulesets/UI/FallbackSampleStore.cs @@ -1,9 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Threading.Tasks; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -29,34 +29,22 @@ namespace osu.Game.Rulesets.UI public Stream GetStream(string name) => primary.GetStream(name) ?? secondary.GetStream(name); - public IEnumerable GetAvailableResources() => primary.GetAvailableResources().Concat(secondary.GetAvailableResources()); + public IEnumerable GetAvailableResources() => throw new NotImplementedException(); - public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) - { - primary.AddAdjustment(type, adjustBindable); - secondary.AddAdjustment(type, adjustBindable); - } + public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => throw new NotImplementedException(); - public void RemoveAdjustment(AdjustableProperty type, BindableDouble adjustBindable) - { - primary.RemoveAdjustment(type, adjustBindable); - secondary.RemoveAdjustment(type, adjustBindable); - } + public void RemoveAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => throw new NotImplementedException(); - public BindableDouble Volume => primary.Volume; + public BindableDouble Volume => throw new NotImplementedException(); - public BindableDouble Balance => primary.Balance; + public BindableDouble Balance => throw new NotImplementedException(); - public BindableDouble Frequency => primary.Frequency; + public BindableDouble Frequency => throw new NotImplementedException(); public int PlaybackConcurrency { - get => primary.PlaybackConcurrency; - set - { - primary.PlaybackConcurrency = value; - secondary.PlaybackConcurrency = value; - } + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); } public void Dispose() From bf6f803e691edbc776896433beb8f8c4f0f2f3ea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 12:12:27 +0900 Subject: [PATCH 2809/5608] Nest temporary class --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 49 +++++++++++++++++++ osu.Game/Rulesets/UI/FallbackSampleStore.cs | 54 --------------------- 2 files changed, 49 insertions(+), 54 deletions(-) delete mode 100644 osu.Game/Rulesets/UI/FallbackSampleStore.cs diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 2a8f64c42e..a34bb6e8ea 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -11,10 +11,13 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; +using System.Threading.Tasks; using JetBrains.Annotations; using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics.Cursor; @@ -465,4 +468,50 @@ namespace osu.Game.Rulesets.UI { } } + + /// + /// A sample store which adds a fallback source. + /// + /// + /// This is a temporary implementation to workaround ISampleStore limitations. + /// + public class FallbackSampleStore : ISampleStore + { + private readonly ISampleStore primary; + private readonly ISampleStore secondary; + + public FallbackSampleStore(ISampleStore primary, ISampleStore secondary) + { + this.primary = primary; + this.secondary = secondary; + } + + public SampleChannel Get(string name) => primary.Get(name) ?? secondary.Get(name); + + public Task GetAsync(string name) => primary.GetAsync(name) ?? secondary.GetAsync(name); + + public Stream GetStream(string name) => primary.GetStream(name) ?? secondary.GetStream(name); + + public IEnumerable GetAvailableResources() => throw new NotImplementedException(); + + public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => throw new NotImplementedException(); + + public void RemoveAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => throw new NotImplementedException(); + + public BindableDouble Volume => throw new NotImplementedException(); + + public BindableDouble Balance => throw new NotImplementedException(); + + public BindableDouble Frequency => throw new NotImplementedException(); + + public int PlaybackConcurrency + { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } + + public void Dispose() + { + } + } } diff --git a/osu.Game/Rulesets/UI/FallbackSampleStore.cs b/osu.Game/Rulesets/UI/FallbackSampleStore.cs deleted file mode 100644 index f1df8bf359..0000000000 --- a/osu.Game/Rulesets/UI/FallbackSampleStore.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; -using osu.Framework.Audio.Track; -using osu.Framework.Bindables; - -namespace osu.Game.Rulesets.UI -{ - public class FallbackSampleStore : ISampleStore - { - private readonly ISampleStore primary; - private readonly ISampleStore secondary; - - public FallbackSampleStore(ISampleStore primary, ISampleStore secondary) - { - this.primary = primary; - this.secondary = secondary; - } - - public SampleChannel Get(string name) => primary.Get(name) ?? secondary.Get(name); - - public Task GetAsync(string name) => primary.GetAsync(name) ?? secondary.GetAsync(name); - - public Stream GetStream(string name) => primary.GetStream(name) ?? secondary.GetStream(name); - - public IEnumerable GetAvailableResources() => throw new NotImplementedException(); - - public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => throw new NotImplementedException(); - - public void RemoveAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => throw new NotImplementedException(); - - public BindableDouble Volume => throw new NotImplementedException(); - - public BindableDouble Balance => throw new NotImplementedException(); - - public BindableDouble Frequency => throw new NotImplementedException(); - - public int PlaybackConcurrency - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - - public void Dispose() - { - } - } -} From f4f95197616cce29716fb31f1f36d3cb03bde0b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 12:16:20 +0900 Subject: [PATCH 2810/5608] Add todo comment --- osu.Game/Skinning/DefaultSkin.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs index c0d6bb34e0..529c1afca5 100644 --- a/osu.Game/Skinning/DefaultSkin.cs +++ b/osu.Game/Skinning/DefaultSkin.cs @@ -29,6 +29,8 @@ namespace osu.Game.Skinning { switch (lookup) { + // todo: this code is pulled from LegacySkin and should not exist. + // will likely change based on how databased storage of skin configuration goes. case GlobalSkinConfiguration global: switch (global) { From f925e781a9ac8a1a770d0e2fc09d0b421b54af47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 15:24:00 +0900 Subject: [PATCH 2811/5608] Refactor HitWindows for legibility --- .../Objects/CatchHitObject.cs | 1 + .../{Objects => Scoring}/CatchHitWindows.cs | 3 +- .../Scoring/CatchScoreProcessor.cs | 1 - .../Difficulty/ManiaDifficultyCalculator.cs | 6 +- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 2 +- .../Objects/HoldNoteTick.cs | 2 +- .../Objects/ManiaHitObject.cs | 2 + .../Objects/ManiaHitWindows.cs | 35 ----- .../Scoring/ManiaHitWindows.cs | 11 ++ .../Scoring/ManiaScoreProcessor.cs | 1 - .../TestSceneShaking.cs | 2 +- .../Difficulty/OsuDifficultyCalculator.cs | 5 +- .../Objects/Drawables/DrawableHitCircle.cs | 6 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- .../Objects/Drawables/DrawableSliderTick.cs | 2 +- .../Objects/Drawables/DrawableSpinner.cs | 2 +- osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 2 + .../Objects/OsuHitWindows.cs | 29 ---- osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 1 + .../Objects/SliderTailCircle.cs | 1 + osu.Game.Rulesets.Osu/Objects/SliderTick.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 2 +- .../Replays/OsuAutoGenerator.cs | 20 +-- .../Scoring/OsuHitWindows.cs | 20 +++ .../TestSceneTaikoPlayfield.cs | 2 +- .../Difficulty/TaikoDifficultyCalculator.cs | 5 +- .../Objects/Drawables/DrawableHit.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 2 +- .../Objects/DrumRollTick.cs | 2 +- .../Objects/StrongHitObject.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/Swell.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/SwellTick.cs | 2 +- .../Objects/TaikoHitObject.cs | 2 + .../Objects/TaikoHitWindows.cs | 41 ------ .../Scoring/TaikoHitWindows.cs | 19 +++ .../Scoring/TaikoScoreProcessor.cs | 1 - .../Beatmaps/Formats/OsuJsonDecoderTest.cs | 2 +- .../Gameplay/TestSceneBarHitErrorMeter.cs | 20 +-- .../Objects/Drawables/DrawableHitObject.cs | 2 +- osu.Game/Rulesets/Objects/HitObject.cs | 1 + .../Objects/Legacy/Mania/ConvertHit.cs | 1 + .../Objects/Legacy/Mania/ConvertHold.cs | 1 + .../Objects/Legacy/Mania/ConvertSlider.cs | 1 + .../Objects/Legacy/Mania/ConvertSpinner.cs | 1 + .../Rulesets/Objects/Legacy/Osu/ConvertHit.cs | 1 + .../Objects/Legacy/Osu/ConvertSlider.cs | 1 + .../Objects/Legacy/Osu/ConvertSpinner.cs | 1 + .../Objects/Legacy/Taiko/ConvertHit.cs | 2 + .../Objects/Legacy/Taiko/ConvertSlider.cs | 2 + .../Objects/Legacy/Taiko/ConvertSpinner.cs | 1 + osu.Game/Rulesets/Scoring/HitResult.cs | 4 + .../{Objects => Scoring}/HitWindows.cs | 131 +++++++++++++----- osu.Game/Scoring/ScoreInfo.cs | 2 +- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 1 - .../HUD/HitErrorMeters/BarHitErrorMeter.cs | 3 +- .../Play/HUD/HitErrorMeters/HitErrorMeter.cs | 2 +- 57 files changed, 225 insertions(+), 199 deletions(-) rename osu.Game.Rulesets.Catch/{Objects => Scoring}/CatchHitWindows.cs (87%) delete mode 100644 osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs create mode 100644 osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs delete mode 100644 osu.Game.Rulesets.Osu/Objects/OsuHitWindows.cs create mode 100644 osu.Game.Rulesets.Osu/Scoring/OsuHitWindows.cs delete mode 100644 osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs create mode 100644 osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs rename osu.Game/Rulesets/{Objects => Scoring}/HitWindows.cs (56%) diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index 19a1b59752..a25d9cb67e 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -6,6 +6,7 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Objects { diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitWindows.cs b/osu.Game.Rulesets.Catch/Scoring/CatchHitWindows.cs similarity index 87% rename from osu.Game.Rulesets.Catch/Objects/CatchHitWindows.cs rename to osu.Game.Rulesets.Catch/Scoring/CatchHitWindows.cs index 837662f5fe..ff793a372e 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitWindows.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchHitWindows.cs @@ -1,10 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; -namespace osu.Game.Rulesets.Catch.Objects +namespace osu.Game.Rulesets.Catch.Scoring { public class CatchHitWindows : HitWindows { diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 99b22b2d56..18785d65ea 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -4,7 +4,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index d945abdb04..37cba1fd3c 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -11,9 +11,9 @@ using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Difficulty.Preprocessing; using osu.Game.Rulesets.Mania.Difficulty.Skills; using osu.Game.Rulesets.Mania.Mods; -using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Difficulty { @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty StarRating = difficultyValue(skills) * star_scaling_factor, Mods = mods, // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future - GreatHitWindow = (int)(hitWindows.Great / 2) / clockRate, + GreatHitWindow = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate, Skills = skills }; } diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index d28d04b3c1..0c82cf7bbc 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -5,8 +5,8 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Objects { diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs index 6bb21633b6..d0125f8793 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs @@ -3,7 +3,7 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; -using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Objects { diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs index 70720a926b..995e1516cb 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs @@ -3,7 +3,9 @@ using osu.Framework.Bindables; using osu.Game.Rulesets.Mania.Objects.Types; +using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Objects { diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs deleted file mode 100644 index 5f2ceab48b..0000000000 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Rulesets.Mania.Objects -{ - public class ManiaHitWindows : HitWindows - { - private static readonly IReadOnlyDictionary base_ranges = new Dictionary - { - { HitResult.Perfect, (44.8, 38.8, 27.8) }, - { HitResult.Great, (128, 98, 68) }, - { HitResult.Good, (194, 164, 134) }, - { HitResult.Ok, (254, 224, 194) }, - { HitResult.Meh, (302, 272, 242) }, - { HitResult.Miss, (376, 346, 316) }, - }; - - public override bool IsHitResultAllowed(HitResult result) => true; - - public override void SetDifficulty(double difficulty) - { - Perfect = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Perfect]); - Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]); - Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]); - Ok = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Ok]); - Meh = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Meh]); - Miss = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Miss]); - } - } -} diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs new file mode 100644 index 0000000000..549f0f9214 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs @@ -0,0 +1,11 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Mania.Scoring +{ + public class ManiaHitWindows : HitWindows + { + } +} diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 5caf08fb1e..49894a644c 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -4,7 +4,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs index 585fdb9cb4..863d0eda09 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Tests Debug.Assert(drawableHitObject.HitObject.HitWindows != null); - double delay = drawableHitObject.HitObject.StartTime - (drawableHitObject.HitObject.HitWindows.HalfWindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current; + double delay = drawableHitObject.HitObject.StartTime - (drawableHitObject.HitObject.HitWindows.WindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current; Scheduler.AddDelayed(() => drawableHitObject.TriggerJudgement(), delay); return drawableHitObject; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 61e9f60cdd..b0d261a1cc 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -9,11 +9,12 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; using osu.Game.Rulesets.Osu.Difficulty.Skills; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Scoring; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Difficulty { @@ -39,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); // Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be removed in the future - double hitWindowGreat = (int)(hitWindows.Great / 2) / clockRate; + double hitWindowGreat = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate; double preempt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate; int maxCombo = beatmap.HitObjects.Count; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 3decc4e51f..985dcbca86 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -10,8 +10,8 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; -using osuTK; using osu.Game.Rulesets.Scoring; +using osuTK; using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables @@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (result == HitResult.None) { - Shake(Math.Abs(timeOffset) - HitObject.HitWindows.HalfWindowFor(HitResult.Miss)); + Shake(Math.Abs(timeOffset) - HitObject.HitWindows.WindowFor(HitResult.Miss)); return; } @@ -134,7 +134,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables hitArea.HitAction = null; // override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early. - LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.HalfWindowFor(HitResult.Miss); + LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.WindowFor(HitResult.Miss); break; case ArmedState.Miss: diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 50187781f6..00a943a67f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -9,8 +9,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; -using osuTK; using osu.Game.Rulesets.Scoring; +using osuTK; using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index c5fa5f0af5..ba931976a8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -8,9 +8,9 @@ using osu.Game.Rulesets.Objects.Drawables; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects.Drawables { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index a0bd301fdb..49aaa2aaea 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -13,8 +13,8 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; -using osu.Game.Screens.Ranking; using osu.Game.Rulesets.Scoring; +using osu.Game.Screens.Ranking; namespace osu.Game.Rulesets.Osu.Objects.Drawables { diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index b52bfcd181..2cf877b000 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -7,6 +7,8 @@ using osu.Game.Rulesets.Objects; using osuTK; using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Osu.Scoring; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects { diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitWindows.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitWindows.cs deleted file mode 100644 index add8fd53c7..0000000000 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitWindows.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Rulesets.Osu.Objects -{ - public class OsuHitWindows : HitWindows - { - private static readonly IReadOnlyDictionary base_ranges = new Dictionary - { - { HitResult.Great, (160, 100, 40) }, - { HitResult.Good, (280, 200, 120) }, - { HitResult.Meh, (400, 300, 200) }, - { HitResult.Miss, (400, 400, 400) }, - }; - - public override void SetDifficulty(double difficulty) - { - Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]); - Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]); - Meh = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Meh]); - Miss = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Miss]); - } - } -} diff --git a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs index 5bd480c0ff..a794e57c9e 100644 --- a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs @@ -5,8 +5,8 @@ using System; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects { diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 93231844bb..2805494021 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects { diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index c53a88337e..7e540a577b 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -5,6 +5,7 @@ using osu.Framework.Bindables; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects { diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs index 60e9084ed3..af7cf5b144 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs @@ -4,8 +4,8 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects { diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index 69c779a182..2e7b763966 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -6,8 +6,8 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects { diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index e5fa571d4d..24320b6579 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -10,9 +10,9 @@ using System.Diagnostics; using System.Linq; using osu.Framework.Graphics; using osu.Game.Replays; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Replays @@ -118,29 +118,29 @@ namespace osu.Game.Rulesets.Osu.Replays Debug.Assert(hitWindows != null); // Make the cursor stay at a hitObject as long as possible (mainly for autopilot). - if (h.StartTime - hitWindows.HalfWindowFor(HitResult.Miss) > endTime + hitWindows.HalfWindowFor(HitResult.Meh) + 50) + if (h.StartTime - hitWindows.WindowFor(HitResult.Miss) > endTime + hitWindows.WindowFor(HitResult.Meh) + 50) { if (!(prev is Spinner) && h.StartTime - endTime < 1000) - AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); + AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.WindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); if (!(h is Spinner)) - AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.HalfWindowFor(HitResult.Miss), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); + AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.WindowFor(HitResult.Miss), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); } - else if (h.StartTime - hitWindows.HalfWindowFor(HitResult.Meh) > endTime + hitWindows.HalfWindowFor(HitResult.Meh) + 50) + else if (h.StartTime - hitWindows.WindowFor(HitResult.Meh) > endTime + hitWindows.WindowFor(HitResult.Meh) + 50) { if (!(prev is Spinner) && h.StartTime - endTime < 1000) - AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); + AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.WindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); if (!(h is Spinner)) - AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.HalfWindowFor(HitResult.Meh), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); + AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.WindowFor(HitResult.Meh), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); } - else if (h.StartTime - hitWindows.HalfWindowFor(HitResult.Good) > endTime + hitWindows.HalfWindowFor(HitResult.Good) + 50) + else if (h.StartTime - hitWindows.WindowFor(HitResult.Good) > endTime + hitWindows.WindowFor(HitResult.Good) + 50) { if (!(prev is Spinner) && h.StartTime - endTime < 1000) - AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.HalfWindowFor(HitResult.Good), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); + AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.WindowFor(HitResult.Good), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); if (!(h is Spinner)) - AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.HalfWindowFor(HitResult.Good), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); + AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.WindowFor(HitResult.Good), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); } } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuHitWindows.cs b/osu.Game.Rulesets.Osu/Scoring/OsuHitWindows.cs new file mode 100644 index 0000000000..8f258c9e3d --- /dev/null +++ b/osu.Game.Rulesets.Osu/Scoring/OsuHitWindows.cs @@ -0,0 +1,20 @@ +// 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.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Osu.Scoring +{ + public class OsuHitWindows : HitWindows + { + private static readonly DifficultyRange[] osu_ranges = + { + new DifficultyRange(HitResult.Great, 80, 50, 20), + new DifficultyRange(HitResult.Good, 140, 100, 60), + new DifficultyRange(HitResult.Meh, 200, 150, 100), + new DifficultyRange(HitResult.Miss, 200, 200, 200), + }; + + protected override DifficultyRange[] GetRanges() => osu_ranges; + } +} diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index 6fd16c213b..3aa461e779 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -14,13 +14,13 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.UI; using osu.Game.Tests.Visual; using osuTK; -using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Tests { diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index fc93bccb94..32d49ea39c 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -8,11 +8,12 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing; using osu.Game.Rulesets.Taiko.Difficulty.Skills; using osu.Game.Rulesets.Taiko.Mods; using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Scoring; namespace osu.Game.Rulesets.Taiko.Difficulty { @@ -38,7 +39,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty StarRating = skills.Single().DifficultyValue() * star_scaling_factor, Mods = mods, // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future - GreatHitWindow = (int)(hitWindows.Great / 2) / clockRate, + GreatHitWindow = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate, MaxCombo = beatmap.HitObjects.Count(h => h is Hit), Skills = skills }; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 0942b37f58..676ecd5a0b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables validActionPressed = false; UnproxyContent(); - this.Delay(HitObject.HitWindows.HalfWindowFor(HitResult.Miss)).Expire(); + this.Delay(HitObject.HitWindows.WindowFor(HitResult.Miss)).Expire(); break; case ArmedState.Miss: diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 3ed52f21f0..4e02c76a8b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -6,7 +6,7 @@ using System; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index 39e2b45e24..c466ca7c8a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects diff --git a/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs index 830e640242..d660149528 100644 --- a/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index e7812841bf..f96c033dce 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -4,7 +4,7 @@ using System; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects diff --git a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs index 049fa7de5f..68212e8f12 100644 --- a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index 3592d73004..6f4fbd0651 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -4,7 +4,9 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; +using osu.Game.Rulesets.Taiko.Scoring; namespace osu.Game.Rulesets.Taiko.Objects { diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs deleted file mode 100644 index f232919cbf..0000000000 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Rulesets.Taiko.Objects -{ - public class TaikoHitWindows : HitWindows - { - private static readonly IReadOnlyDictionary base_ranges = new Dictionary - { - { HitResult.Great, (100, 70, 40) }, - { HitResult.Good, (240, 160, 100) }, - { HitResult.Miss, (270, 190, 140) }, - }; - - public override bool IsHitResultAllowed(HitResult result) - { - switch (result) - { - case HitResult.Great: - case HitResult.Good: - case HitResult.Miss: - return true; - - default: - return false; - } - } - - public override void SetDifficulty(double difficulty) - { - Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]); - Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]); - Miss = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Miss]); - } - } -} diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs new file mode 100644 index 0000000000..77d59f9638 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Taiko.Scoring +{ + public class TaikoHitWindows : HitWindows + { + private static readonly DifficultyRange[] taiko_ranges = + { + new DifficultyRange(HitResult.Great, 50, 35, 20), + new DifficultyRange(HitResult.Good, 120, 80, 50), + new DifficultyRange(HitResult.Miss, 135, 95, 70), + }; + + protected override DifficultyRange[] GetRanges() => taiko_ranges; + } +} diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 68ddf2db19..75a27ff639 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -3,7 +3,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs index a725c58462..4859abbb8e 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs @@ -9,8 +9,8 @@ using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.IO.Serialization; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; using osu.Game.Tests.Resources; using osuTK; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs index e9c15dab9b..a934d22b5d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs @@ -3,18 +3,18 @@ using NUnit.Framework; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Taiko.Objects; -using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Catch.Objects; using System; using System.Collections.Generic; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Scoring; using osu.Framework.MathUtils; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Game.Rulesets.Catch.Scoring; +using osu.Game.Rulesets.Mania.Scoring; +using osu.Game.Rulesets.Osu.Scoring; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Scoring; using osu.Game.Screens.Play.HUD.HitErrorMeters; namespace osu.Game.Tests.Visual.Gameplay @@ -36,8 +36,8 @@ namespace osu.Game.Tests.Visual.Gameplay AddRepeatStep("New random judgement", () => newJudgement(), 40); - AddRepeatStep("New max negative", () => newJudgement(-hitWindows.HalfWindowFor(HitResult.Meh)), 20); - AddRepeatStep("New max positive", () => newJudgement(hitWindows.HalfWindowFor(HitResult.Meh)), 20); + AddRepeatStep("New max negative", () => newJudgement(-hitWindows.WindowFor(HitResult.Meh)), 20); + AddRepeatStep("New max positive", () => newJudgement(hitWindows.WindowFor(HitResult.Meh)), 20); AddStep("New fixed judgement (50ms)", () => newJudgement(50)); } @@ -85,9 +85,9 @@ namespace osu.Game.Tests.Visual.Gameplay AutoSizeAxes = Axes.Both, Children = new[] { - new SpriteText { Text = $@"Great: {hitWindows?.Great}" }, - new SpriteText { Text = $@"Good: {hitWindows?.Good}" }, - new SpriteText { Text = $@"Meh: {hitWindows?.Meh}" }, + new SpriteText { Text = $@"Great: {hitWindows?.WindowFor(HitResult.Great)}" }, + new SpriteText { Text = $@"Good: {hitWindows?.WindowFor(HitResult.Good)}" }, + new SpriteText { Text = $@"Meh: {hitWindows?.WindowFor(HitResult.Meh)}" }, } }); diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index a6d0aad880..5dfab5ef77 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -164,7 +164,7 @@ namespace osu.Game.Rulesets.Objects.Drawables { UpdateInitialTransforms(); - var judgementOffset = Math.Min(HitObject.HitWindows?.HalfWindowFor(HitResult.Miss) ?? double.MaxValue, Result?.TimeOffset ?? 0); + var judgementOffset = Math.Min(HitObject.HitWindows?.WindowFor(HitResult.Miss) ?? double.MaxValue, Result?.TimeOffset ?? 0); using (BeginDelayedSequence(InitialLifetimeOffset + judgementOffset, true)) { diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 5e029139d9..96297ab44f 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -9,6 +9,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Objects { diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs index 06fde576d2..609bdd571a 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Objects.Legacy.Mania { diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs index 096c07f7d2..350ee3185d 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Objects.Legacy.Mania { diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs index 226d91bb86..e372fbd273 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Objects.Legacy.Mania { diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs index eb20fa67f1..067377d300 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Objects.Legacy.Mania { diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs index 84b66a4c26..c9851a0074 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; using osuTK; namespace osu.Game.Rulesets.Objects.Legacy.Osu diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs index c850feb189..1c1180702b 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; using osuTK; namespace osu.Game.Rulesets.Objects.Legacy.Osu diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs index e5a8884aa2..bc94ea1803 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; using osuTK; namespace osu.Game.Rulesets.Objects.Legacy.Osu diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs index 5cecc2a59f..709345170f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Rulesets.Scoring; + namespace osu.Game.Rulesets.Objects.Legacy.Taiko { /// diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs index 5cedc6e2e5..c173b3e11a 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Rulesets.Scoring; + namespace osu.Game.Rulesets.Objects.Legacy.Taiko { /// diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs index ca9fdd53ed..9a35ad2776 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Objects.Legacy.Taiko { diff --git a/osu.Game/Rulesets/Scoring/HitResult.cs b/osu.Game/Rulesets/Scoring/HitResult.cs index 2376f12e9e..7ba88d3df8 100644 --- a/osu.Game/Rulesets/Scoring/HitResult.cs +++ b/osu.Game/Rulesets/Scoring/HitResult.cs @@ -16,6 +16,10 @@ namespace osu.Game.Rulesets.Scoring /// /// Indicates that the object has been judged as a miss. /// + /// + /// This miss window should determine how early a hit can be before it is considered for judgement (as opposed to being ignored as + /// "too far in the future). It should also define when a forced miss should be triggered (as a result of no user input in time). + /// [Description(@"Miss")] Miss, diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Scoring/HitWindows.cs similarity index 56% rename from osu.Game/Rulesets/Objects/HitWindows.cs rename to osu.Game/Rulesets/Scoring/HitWindows.cs index e88af67c7c..beba62044a 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Scoring/HitWindows.cs @@ -4,51 +4,61 @@ using System; using System.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Objects; -namespace osu.Game.Rulesets.Objects +namespace osu.Game.Rulesets.Scoring { + /// + /// A structure containing timing data for hit window based gameplay. + /// public class HitWindows { - private static readonly IReadOnlyDictionary base_ranges = new Dictionary + private static readonly DifficultyRange[] base_ranges = { - { HitResult.Perfect, (44.8, 38.8, 27.8) }, - { HitResult.Great, (128, 98, 68) }, - { HitResult.Good, (194, 164, 134) }, - { HitResult.Ok, (254, 224, 194) }, - { HitResult.Meh, (302, 272, 242) }, - { HitResult.Miss, (376, 346, 316) }, + new DifficultyRange(HitResult.Perfect, 22.4D, 19.4D, 13.9D), + new DifficultyRange(HitResult.Great, 64, 49, 34), + new DifficultyRange(HitResult.Good, 97, 82, 67), + new DifficultyRange(HitResult.Ok, 127, 112, 97), + new DifficultyRange(HitResult.Meh, 151, 136, 121), + new DifficultyRange(HitResult.Miss, 188, 173, 158), }; /// /// Hit window for a result. /// - public double Perfect { get; protected set; } + private double perfect; /// /// Hit window for a result. /// - public double Great { get; protected set; } + /// + /// Note that this value includes both the early and late region. + /// + private double great; /// /// Hit window for a result. /// - public double Good { get; protected set; } + private double good; /// /// Hit window for an result. /// - public double Ok { get; protected set; } + private double ok; /// /// Hit window for a result. /// - public double Meh { get; protected set; } + private double meh; /// /// Hit window for a result. /// - public double Miss { get; protected set; } + /// + /// This miss window should determine how early a hit can be before it is considered for judgement (as opposed to being ignored as + /// "too far in the future). It should also define when a forced miss should be triggered (as a result of no user input in time). + /// + private double miss; /// /// Retrieves the with the largest hit window that produces a successful hit. @@ -66,15 +76,15 @@ namespace osu.Game.Rulesets.Objects } /// - /// Retrieves a mapping of s to their half window timing for all allowed s. + /// Retrieves a mapping of s to their timing windows for all allowed s. /// /// - public IEnumerable<(HitResult result, double length)> GetAllAvailableHalfWindows() + public IEnumerable<(HitResult result, double length)> GetAllAvailableWindows() { for (var result = HitResult.Meh; result <= HitResult.Perfect; ++result) { if (IsHitResultAllowed(result)) - yield return (result, HalfWindowFor(result)); + yield return (result, WindowFor(result)); } } @@ -100,14 +110,39 @@ namespace osu.Game.Rulesets.Objects /// Sets hit windows with values that correspond to a difficulty parameter. /// /// The parameter. - public virtual void SetDifficulty(double difficulty) + public void SetDifficulty(double difficulty) { - Perfect = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Perfect]); - Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]); - Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]); - Ok = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Ok]); - Meh = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Meh]); - Miss = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Miss]); + foreach (var range in GetRanges()) + { + var value = BeatmapDifficulty.DifficultyRange(difficulty, (range.Min, range.Average, range.Max)); + + switch (range.Result) + { + case HitResult.Miss: + miss = value; + break; + + case HitResult.Meh: + meh = value; + break; + + case HitResult.Ok: + ok = value; + break; + + case HitResult.Good: + good = value; + break; + + case HitResult.Great: + great = value; + break; + + case HitResult.Perfect: + perfect = value; + break; + } + } } /// @@ -121,7 +156,7 @@ namespace osu.Game.Rulesets.Objects for (var result = HitResult.Perfect; result >= HitResult.Miss; --result) { - if (IsHitResultAllowed(result) && timeOffset <= HalfWindowFor(result)) + if (IsHitResultAllowed(result) && timeOffset <= WindowFor(result)) return result; } @@ -129,32 +164,32 @@ namespace osu.Game.Rulesets.Objects } /// - /// Retrieves half the hit window for a . - /// This is useful if the hit window for one half of the hittable range of a is required. + /// Retrieves the hit window for a . + /// This is the number of +/- milliseconds allowed for the requested result (so the actual hittable range is double this). /// /// The expected . /// One half of the hit window for . - public double HalfWindowFor(HitResult result) + public double WindowFor(HitResult result) { switch (result) { case HitResult.Perfect: - return Perfect / 2; + return perfect; case HitResult.Great: - return Great / 2; + return great; case HitResult.Good: - return Good / 2; + return good; case HitResult.Ok: - return Ok / 2; + return ok; case HitResult.Meh: - return Meh / 2; + return meh; case HitResult.Miss: - return Miss / 2; + return miss; default: throw new ArgumentException(nameof(result)); @@ -167,6 +202,30 @@ namespace osu.Game.Rulesets.Objects /// /// The time offset. /// Whether the can be hit at any point in the future from this time offset. - public bool CanBeHit(double timeOffset) => timeOffset <= HalfWindowFor(LowestSuccessfulHitResult()); + public bool CanBeHit(double timeOffset) => timeOffset <= WindowFor(LowestSuccessfulHitResult()); + + /// + /// Retrieve a valid list of s representing hit windows. + /// Defaults are provided but can be overridden to customise for a ruleset. + /// + protected virtual DifficultyRange[] GetRanges() => base_ranges; + } + + public struct DifficultyRange + { + public readonly HitResult Result; + + public double Min; + public double Average; + public double Max; + + public DifficultyRange(HitResult result, double min, double average, double max) + { + Result = result; + + Min = min; + Average = average; + Max = max; + } } } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 266725a739..d3c37bd4f4 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -11,8 +11,8 @@ using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; -using osu.Game.Users; using osu.Game.Rulesets.Scoring; +using osu.Game.Users; namespace osu.Game.Scoring { diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index adda94d629..920d11c910 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play.HUD.HitErrorMeters; diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 594dd64e52..03a0f23fb6 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osuTK; using osuTK.Graphics; @@ -146,7 +145,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters private void createColourBars(OsuColour colours) { - var windows = HitWindows.GetAllAvailableHalfWindows().ToArray(); + var windows = HitWindows.GetAllAvailableWindows().ToArray(); maxHitWindow = windows.First().length; diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs index da1d9fff0d..dee25048ed 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs @@ -3,7 +3,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Screens.Play.HUD.HitErrorMeters { From 6cdc87bd29cfade223c0fe44fe7c0808a8634c80 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 15:37:20 +0900 Subject: [PATCH 2812/5608] Fix allowed results omissions --- osu.Game.Rulesets.Osu/Scoring/OsuHitWindows.cs | 14 ++++++++++++++ osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs | 13 +++++++++++++ 2 files changed, 27 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuHitWindows.cs b/osu.Game.Rulesets.Osu/Scoring/OsuHitWindows.cs index 8f258c9e3d..a6491bb3f3 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuHitWindows.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuHitWindows.cs @@ -15,6 +15,20 @@ namespace osu.Game.Rulesets.Osu.Scoring new DifficultyRange(HitResult.Miss, 200, 200, 200), }; + public override bool IsHitResultAllowed(HitResult result) + { + switch (result) + { + case HitResult.Great: + case HitResult.Good: + case HitResult.Meh: + case HitResult.Miss: + return true; + } + + return false; + } + protected override DifficultyRange[] GetRanges() => osu_ranges; } } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs index 77d59f9638..9d273392ff 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs @@ -14,6 +14,19 @@ namespace osu.Game.Rulesets.Taiko.Scoring new DifficultyRange(HitResult.Miss, 135, 95, 70), }; + public override bool IsHitResultAllowed(HitResult result) + { + switch (result) + { + case HitResult.Great: + case HitResult.Good: + case HitResult.Miss: + return true; + } + + return false; + } + protected override DifficultyRange[] GetRanges() => taiko_ranges; } } From 4031f51745ae15add836cbeb2d5c9b6116ac37d7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 15:37:30 +0900 Subject: [PATCH 2813/5608] More permissive IsHitResultAllow by default --- osu.Game/Rulesets/Scoring/HitWindows.cs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/HitWindows.cs b/osu.Game/Rulesets/Scoring/HitWindows.cs index beba62044a..6d8107cf9c 100644 --- a/osu.Game/Rulesets/Scoring/HitWindows.cs +++ b/osu.Game/Rulesets/Scoring/HitWindows.cs @@ -93,18 +93,7 @@ namespace osu.Game.Rulesets.Scoring /// /// The result type to check. /// Whether the can be achieved. - public virtual bool IsHitResultAllowed(HitResult result) - { - switch (result) - { - case HitResult.Perfect: - case HitResult.Ok: - return false; - - default: - return true; - } - } + public virtual bool IsHitResultAllowed(HitResult result) => true; /// /// Sets hit windows with values that correspond to a difficulty parameter. From 985375d1c64daec3290130d80957ea980ee8b836 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 15:47:01 +0900 Subject: [PATCH 2814/5608] Remove private field xmldoc --- osu.Game/Rulesets/Scoring/HitWindows.cs | 30 ------------------------- 1 file changed, 30 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/HitWindows.cs b/osu.Game/Rulesets/Scoring/HitWindows.cs index 6d8107cf9c..efc4cd9f5c 100644 --- a/osu.Game/Rulesets/Scoring/HitWindows.cs +++ b/osu.Game/Rulesets/Scoring/HitWindows.cs @@ -23,41 +23,11 @@ namespace osu.Game.Rulesets.Scoring new DifficultyRange(HitResult.Miss, 188, 173, 158), }; - /// - /// Hit window for a result. - /// private double perfect; - - /// - /// Hit window for a result. - /// - /// - /// Note that this value includes both the early and late region. - /// private double great; - - /// - /// Hit window for a result. - /// private double good; - - /// - /// Hit window for an result. - /// private double ok; - - /// - /// Hit window for a result. - /// private double meh; - - /// - /// Hit window for a result. - /// - /// - /// This miss window should determine how early a hit can be before it is considered for judgement (as opposed to being ignored as - /// "too far in the future). It should also define when a forced miss should be triggered (as a result of no user input in time). - /// private double miss; /// From b89fb5cdf7ca5e5b1ac8932ed6b3e79fb7a8bedd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 16:51:30 +0900 Subject: [PATCH 2815/5608] Fix failing test --- .../Visual/Gameplay/TestSceneFailJudgement.cs | 10 +--------- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 9 +++++++-- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index bb0901524f..d57ec44f39 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -26,15 +26,7 @@ namespace osu.Game.Tests.Visual.Gameplay { AddUntilStep("wait for fail", () => Player.HasFailed); AddUntilStep("wait for multiple judged objects", () => ((FailPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.Count(h => h.AllJudged) > 1); - AddAssert("total judgements == 1", () => - { - int count = 0; - - foreach (var stat in (HitResult[])Enum.GetValues(typeof(HitResult))) - count += ((FailPlayer)Player).ScoreProcessor.GetStatistic(stat); - - return count == 1; - }); + AddAssert("total judgements == 1", () => ((FailPlayer)Player).ScoreProcessor.JudgedHits == 1); } private class FailPlayer : ReplayPlayer diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 9f2c79df33..e4f20c27b4 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -92,6 +92,11 @@ namespace osu.Game.Rulesets.Scoring /// public virtual bool HasCompleted => false; + /// + /// The total number of judged s at the current point in time. + /// + public int JudgedHits { get; protected set; } + /// /// Whether this ScoreProcessor has already triggered the failed state. /// @@ -142,6 +147,8 @@ namespace osu.Game.Rulesets.Scoring Rank.Value = ScoreRank.X; HighestCombo.Value = 0; + JudgedHits = 0; + HasFailed = false; } @@ -208,7 +215,6 @@ namespace osu.Game.Rulesets.Scoring public sealed override bool HasCompleted => JudgedHits == MaxHits; protected int MaxHits { get; private set; } - protected int JudgedHits { get; private set; } private double maxHighestCombo; @@ -441,7 +447,6 @@ namespace osu.Game.Rulesets.Scoring base.Reset(storeResults); - JudgedHits = 0; baseScore = 0; rollingMaxBaseScore = 0; bonusScore = 0; From 88d0756107f6e2c0a1955f64a68de6553d680631 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 17:17:30 +0900 Subject: [PATCH 2816/5608] Allow global actions to propagate through pause screen --- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index c5202fa792..f54d638584 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -313,5 +313,22 @@ namespace osu.Game.Screens.Play return base.OnMouseMove(e); } } + + [Resolved] + private GlobalActionContainer globalAction { get; set; } + + protected override bool Handle(UIEvent e) + { + switch (e) + { + case ScrollEvent _: + if (ReceivePositionalInputAt(e.ScreenSpaceMousePosition)) + return globalAction.TriggerEvent(e); + + break; + } + + return base.Handle(e); + } } } From 95baae5088de6333deebece25b66c42869793a7a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 18:27:54 +0900 Subject: [PATCH 2817/5608] Fix dragging from inside to outside an overlay incorrectly hiding --- .../Containers/OsuFocusedOverlayContainer.cs | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 9c948d6f90..a4121acfca 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -62,21 +62,31 @@ namespace osu.Game.Graphics.Containers protected override bool OnClick(ClickEvent e) { - closeIfOutside(e); + if (!base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)) + Hide(); return base.OnClick(e); } - protected override bool OnDragEnd(DragEndEvent e) - { - closeIfOutside(e); - return base.OnDragEnd(e); - } + private bool closeOnDragEnd; - private void closeIfOutside(MouseEvent e) + protected override bool OnDragStart(DragStartEvent e) { if (!base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)) + closeOnDragEnd = true; + + return base.OnDragStart(e); + } + + protected override bool OnDragEnd(DragEndEvent e) + { + if (closeOnDragEnd) + { Hide(); + closeOnDragEnd = false; + } + + return base.OnDragEnd(e); } public virtual bool OnPressed(GlobalAction action) From 374479f837b3e56e527b6682d9d7234f78ea4adf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 19:00:49 +0900 Subject: [PATCH 2818/5608] Add truncatino of long usernames in chat --- .../Online/TestSceneChatLineTruncation.cs | 108 ++++++++++++++++++ osu.Game/Overlays/Chat/ChatLine.cs | 10 +- 2 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs new file mode 100644 index 0000000000..888e55ab0a --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs @@ -0,0 +1,108 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Containers; +using osu.Game.Online.Chat; +using osu.Game.Overlays.Chat; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + [TestFixture] + public class TestSceneChatLineTruncation : OsuTestScene + { + private readonly TestChatLineContainer textContainer; + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ChatLine), + typeof(Message), + typeof(LinkFlowContainer), + typeof(MessageFormatter) + }; + + public TestSceneChatLineTruncation() + { + Add(textContainer = new TestChatLineContainer + { + Padding = new MarginPadding { Left = 20, Right = 20 }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + }); + } + + [BackgroundDependencyLoader] + private void load() + { + testFormatting(); + } + + private void clear() => AddStep("clear messages", textContainer.Clear); + + private void addMessageWithChecks(string text, bool isAction = false, bool isImportant = false, string username = null) + { + int index = textContainer.Count + 1; + var newLine = new ChatLine(new DummyMessage(text, isAction, isImportant, index, username)); + textContainer.Add(newLine); + } + + private void testFormatting() + { + for (int a = 0; a < 25; a++) + addMessageWithChecks($"Wide {a} character username.", username: new string('w', a)); + addMessageWithChecks("Short name with spaces.", username: "sho rt name"); + addMessageWithChecks("Long name with spaces.", username: "long name with s p a c e s"); + } + + private class DummyMessage : Message + { + private static long messageCounter; + + internal static readonly User TEST_SENDER_BACKGROUND = new User + { + Username = @"i-am-important", + Id = 42, + Colour = "#250cc9", + }; + + internal static readonly User TEST_SENDER = new User + { + Username = @"Somebody", + Id = 1, + }; + + public new DateTimeOffset Timestamp = DateTimeOffset.Now; + + public DummyMessage(string text, bool isAction = false, bool isImportant = false, int number = 0, string username = null) + : base(messageCounter++) + { + Content = text; + IsAction = isAction; + Sender = new User + { + Username = username ?? $"user {number}", + Id = number, + Colour = isImportant ? "#250cc9" : null, + }; + } + } + + private class TestChatLineContainer : FillFlowContainer + { + protected override int Compare(Drawable x, Drawable y) + { + var xC = (ChatLine)x; + var yC = (ChatLine)y; + + return xC.Message.CompareTo(yC.Message); + } + } + } +} diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 2576b38ec8..a07b6472a3 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -31,6 +31,8 @@ namespace osu.Game.Overlays.Chat protected virtual float MessagePadding => default_message_padding; + private const float timestamp_padding = 70; + private const float default_horizontal_padding = 15; protected virtual float HorizontalPadding => default_horizontal_padding; @@ -87,7 +89,10 @@ namespace osu.Game.Overlays.Chat { Shadow = false, Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length], - Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true) + Truncate = true, + EllipsisString = ".. :", + Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true), + RelativeSizeAxes = Axes.Both, }; if (hasBackground) @@ -141,7 +146,8 @@ namespace osu.Game.Overlays.Chat }, new MessageSender(message.Sender) { - AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = timestamp_padding }, + RelativeSizeAxes = Axes.Both, Origin = Anchor.TopRight, Anchor = Anchor.TopRight, Child = effectedUsername, From c6b8f2db77313f29bdfa106a042a9ba211b009fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 19:05:50 +0900 Subject: [PATCH 2819/5608] Update historic licence header --- osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs | 4 ++-- osu.Game/Overlays/Chat/ChatLine.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs index 888e55ab0a..4773e84a5e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/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; using System.Collections.Generic; diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index a07b6472a3..d812e007a0 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Chat protected virtual float MessagePadding => default_message_padding; - private const float timestamp_padding = 70; + private const float timestamp_padding = 70; private const float default_horizontal_padding = 15; From 3227dc87fbac1c47fb505c4e66a66ac80a935678 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 6 Sep 2019 22:56:46 +0300 Subject: [PATCH 2820/5608] Don't use CancelDelayedTasks to avoid cancelling unwanted tasks --- osu.Game/Overlays/SocialOverlay.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index bf306f9569..1912a2c3e0 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -17,6 +17,7 @@ using osu.Game.Overlays.Social; using osu.Game.Users; using System; using System.Threading; +using osu.Framework.Threading; namespace osu.Game.Overlays { @@ -77,12 +78,12 @@ namespace osu.Game.Overlays currentQuery.BindTo(Filter.Search.Current); currentQuery.ValueChanged += query => { - Scheduler.CancelDelayedTasks(); + queryChangedDebounce?.Cancel(); if (string.IsNullOrEmpty(query.NewValue)) queueUpdate(); else - Scheduler.AddDelayed(updateSearch, 500); + queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); }; } @@ -90,13 +91,15 @@ namespace osu.Game.Overlays private readonly Bindable currentQuery = new Bindable(); + private ScheduledDelegate queryChangedDebounce; + private void queueUpdate() => Scheduler.AddOnce(updateSearch); private CancellationTokenSource loadCancellation; private void updateSearch() { - Scheduler.CancelDelayedTasks(); + queryChangedDebounce?.Cancel(); if (!IsLoaded) return; @@ -169,6 +172,9 @@ namespace osu.Game.Overlays LoadComponentAsync(newPanels, f => { + if (panels != null) + ScrollFlow.Remove(panels); + loading.Hide(); ScrollFlow.Add(panels = newPanels); }, loadCancellation.Token); From 7f2d14416a16d7b849e7c9be682bd4f84493c024 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 7 Sep 2019 14:44:44 +0900 Subject: [PATCH 2821/5608] Reset DrawableHitObject lifetimes on state change --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index db87d4b4f2..e3390c8cf0 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -153,6 +153,9 @@ namespace osu.Game.Rulesets.Objects.Drawables if (UseTransformStateManagement) { + lifetimeStart = null; + LifetimeEnd = double.MaxValue; + double transformTime = HitObject.StartTime - InitialLifetimeOffset; base.ApplyTransformsAt(transformTime, true); From 55b2bc1ed5b4466ef0a21cf3faadacb76b6dc951 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 7 Sep 2019 18:03:04 +0300 Subject: [PATCH 2822/5608] Set Health default value to 1 --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index e4f20c27b4..f350eef146 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Scoring /// /// The current health. /// - public readonly BindableDouble Health = new BindableDouble { MinValue = 0, MaxValue = 1 }; + public readonly BindableDouble Health = new BindableDouble(1) { MinValue = 0, MaxValue = 1 }; /// /// The current combo. From c397ab62821a91ccca252b2e627f90f9c89bdc1e Mon Sep 17 00:00:00 2001 From: miterosan Date: Sat, 7 Sep 2019 17:04:13 +0200 Subject: [PATCH 2823/5608] Fix Android Builds. --- osu.Android.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index adc340a734..03c6889a69 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -14,7 +14,7 @@ v9.0 false - + True portable False @@ -30,12 +30,12 @@ armeabi-v7a;x86;arm64-v8a true - + false None True prompt - true + true false SdkOnly False From fdd36874371909a1dd4391dbf828bb015cf441cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 8 Sep 2019 00:09:24 +0900 Subject: [PATCH 2824/5608] Fix catcher additive sprites staying on screen during rewind --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index ceda643335..592a45c865 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.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; @@ -197,6 +197,7 @@ namespace osu.Game.Rulesets.Catch.UI additive.Anchor = Anchor; additive.OriginPosition = additive.OriginPosition + new Vector2(DrawWidth / 2, 0); // also temporary to align sprite correctly. + additive.LifetimeStart = Clock.CurrentTime; additive.Position = Position; additive.Scale = Scale; additive.Colour = HyperDashing ? Color4.Red : Color4.White; From ec7a50b75f946453c76d351e181162136a7d88b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 8 Sep 2019 00:10:31 +0900 Subject: [PATCH 2825/5608] Fix already caught osu!catch objects not correctly disappearing --- .../Objects/Drawable/DrawableCatchHitObject.cs | 4 ++++ osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 13 ++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 00734810b3..ce90319846 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -50,6 +50,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable public Func CheckPosition; + public bool IsOnPlate; + + public override bool RemoveWhenNotAlive => IsOnPlate; + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (CheckPosition == null) return; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 592a45c865..330f6e6b24 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -69,6 +69,7 @@ namespace osu.Game.Rulesets.Catch.UI caughtFruit.RelativePositionAxes = Axes.None; caughtFruit.Position = new Vector2(MovableCatcher.ToLocalSpace(fruit.ScreenSpaceDrawQuad.Centre).X - MovableCatcher.DrawSize.X / 2, 0); + caughtFruit.IsOnPlate = true; caughtFruit.Anchor = Anchor.TopCentre; caughtFruit.Origin = Anchor.Centre; @@ -384,6 +385,12 @@ namespace osu.Game.Rulesets.Catch.UI X = hyperDashTargetPosition; SetHyperDashState(); } + + if (Clock.ElapsedFrameTime < 0) + { + AdditiveTarget.RemoveAll(d => Clock.CurrentTime < d.LifetimeStart); + caughtFruit.RemoveAll(d => d.HitObject.StartTime > Clock.CurrentTime); + } } /// @@ -407,7 +414,7 @@ namespace osu.Game.Rulesets.Catch.UI f.MoveToY(f.Y + 75, 750, Easing.InSine); f.FadeOut(750); - f.Expire(); + f.Expire(true); } } @@ -437,11 +444,11 @@ namespace osu.Game.Rulesets.Catch.UI ExplodingFruitTarget.Add(fruit); } + fruit.ClearTransforms(); fruit.MoveToY(fruit.Y - 50, 250, Easing.OutSine).Then().MoveToY(fruit.Y + 50, 500, Easing.InSine); fruit.MoveToX(fruit.X + originalX * 6, 1000); fruit.FadeOut(750); - - fruit.Expire(); + fruit.Expire(true); } } } From be803fa9217d3cc5ecc808d32a0c603e7278ad5b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 7 Sep 2019 18:15:49 +0300 Subject: [PATCH 2826/5608] Reset score processor before starting the simulation --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index f350eef146..4ca9ddd183 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -269,6 +269,8 @@ namespace osu.Game.Rulesets.Scoring /// The to simulate. protected virtual void SimulateAutoplay(Beatmap beatmap) { + Reset(false); + foreach (var obj in beatmap.HitObjects) simulate(obj); From 6581e51d6af714cae1763a1f28d79013f9756a25 Mon Sep 17 00:00:00 2001 From: miterosan Date: Sat, 7 Sep 2019 18:03:33 +0200 Subject: [PATCH 2827/5608] Add a default for the configuration into the android props. This allows building even if no configuration is specified. --- osu.Android.props | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Android.props b/osu.Android.props index 03c6889a69..4962064853 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -1,5 +1,6 @@ + Debug bin\$(Configuration) 4 2.0 From 3435e2a8d3f2e7ab5ef9c3cf0090c72dbe0d0f21 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Sun, 8 Sep 2019 13:36:58 +0800 Subject: [PATCH 2828/5608] open login on enter main menu --- osu.Game/Screens/Menu/MainMenu.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 499b5089f6..160ff95632 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -11,6 +11,7 @@ using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Charts; @@ -44,6 +45,12 @@ namespace osu.Game.Screens.Menu [Resolved(canBeNull: true)] private MusicController music { get; set; } + [Resolved(canBeNull: true)] + private LoginOverlay login { get; set; } + + [Resolved] + private IAPIProvider api { get; set; } + private BackgroundScreenDefault background; protected override BackgroundScreen CreateBackground() => background; @@ -128,6 +135,9 @@ namespace osu.Game.Screens.Menu track.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * track.Length); track.Start(); } + + if (api?.State == APIState.Offline) + login?.ToggleVisibility(); } Beatmap.ValueChanged += beatmap_ValueChanged; From a67a2899a9d763b94f8b3e689fbeb6a5bc323cde Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Sun, 8 Sep 2019 16:18:15 +0800 Subject: [PATCH 2829/5608] move api state check to it's own clause --- osu.Game/Screens/Menu/MainMenu.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 160ff95632..10b2f827af 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -135,11 +135,11 @@ namespace osu.Game.Screens.Menu track.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * track.Length); track.Start(); } - - if (api?.State == APIState.Offline) - login?.ToggleVisibility(); } + if (last is IntroScreen && api?.State == APIState.Offline) + login?.ToggleVisibility(); + Beatmap.ValueChanged += beatmap_ValueChanged; } From 3d8b27abfaa698c7ff8e4ba2b07a3dbb48f7a798 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 8 Sep 2019 16:13:36 +0300 Subject: [PATCH 2830/5608] RotationAbsolute -> BidirectionalRotation --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 5 +++-- .../Objects/Drawables/Pieces/SpinnerDisc.cs | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs index 3ed3f3e981..5d7acb77bb 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Tests if (auto && !userTriggered && Time.Current > Spinner.StartTime + Spinner.Duration / 2 && Progress < 1) { // force completion only once to not break human interaction - Disc.RotationAbsolute = Spinner.SpinsRequired * 360; + Disc.BidirectionalRotation = Spinner.SpinsRequired * 360; auto = false; } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 49aaa2aaea..c7bcf2526a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.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.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -136,7 +137,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindTo(HitObject.PositionBindable); } - public float Progress => MathHelper.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); + public float Progress => MathHelper.Clamp(Disc.BidirectionalRotation / 360 / Spinner.SpinsRequired, 0, 1); protected override void CheckForResult(bool userTriggered, double timeOffset) { @@ -188,7 +189,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circle.Rotation = Disc.Rotation; Ticks.Rotation = Disc.Rotation; - spmCounter.SetRotation(Disc.RotationAbsolute); + spmCounter.SetRotation(Disc.BidirectionalRotation); float relativeCircleScale = Spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight; Disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index 448a2eada7..b9d5674b34 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -82,11 +82,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private float lastAngle; private float currentRotation; - public float RotationAbsolute; + public float BidirectionalRotation; private int completeTick; - private bool updateCompleteTick() => completeTick != (completeTick = (int)(RotationAbsolute / 360)); + private bool updateCompleteTick() => completeTick != (completeTick = (int)(BidirectionalRotation / 360)); private bool rotationTransferred; protected override void Update() @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces lastAngle -= 360; currentRotation += thisAngle - lastAngle; - RotationAbsolute += Math.Abs(thisAngle - lastAngle); + BidirectionalRotation += Math.Abs(thisAngle - lastAngle) * Math.Sign(Time.Current - lastTime); } lastAngle = thisAngle; From f5f2713a17c62037786bb0010b2fd3cd480cd97c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 8 Sep 2019 16:14:14 +0300 Subject: [PATCH 2831/5608] Account angle change negatively on rewind --- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index b9d5674b34..5b2b3bcd42 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -85,8 +85,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public float BidirectionalRotation; private int completeTick; + private double lastTime; private bool updateCompleteTick() => completeTick != (completeTick = (int)(BidirectionalRotation / 360)); + private bool rotationTransferred; protected override void Update() @@ -112,6 +114,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces currentRotation += thisAngle - lastAngle; BidirectionalRotation += Math.Abs(thisAngle - lastAngle) * Math.Sign(Time.Current - lastTime); + lastTime = Time.Current; } lastAngle = thisAngle; From d790656b7ed9feee90fd419c56e85797aa3f9e3a Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 8 Sep 2019 15:33:16 +0200 Subject: [PATCH 2832/5608] Revert shortening the condition --- osu.Android.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 4962064853..a84b877a98 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -15,7 +15,7 @@ v9.0 false - + True portable False @@ -31,7 +31,7 @@ armeabi-v7a;x86;arm64-v8a true - + false None True From 8862cdab9c719a093d47c49dd9be546fc655f8eb Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 8 Sep 2019 15:33:51 +0200 Subject: [PATCH 2833/5608] Also set the default for Platform --- osu.Android.props | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Android.props b/osu.Android.props index a84b877a98..896b10133d 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -1,6 +1,7 @@ Debug + AnyCPU bin\$(Configuration) 4 2.0 From 9951011e6c5d469f149ee9b0d08405f0afb6a250 Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 8 Sep 2019 16:27:25 +0200 Subject: [PATCH 2834/5608] Remove not needed androidnativelibrary itemgroup --- osu.Android.props | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index adc340a734..51bfdca064 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -49,7 +49,6 @@ osu.licenseheader - From 9defcb0e9945785dc4edf44a444a6015f78517f6 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 8 Sep 2019 21:37:50 +0300 Subject: [PATCH 2835/5608] Remove redundant using directive --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index c7bcf2526a..a8dc275fb5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.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.Graphics; using osu.Framework.Graphics.Containers; From be4f0cc2dd19c8adfced41dd82731c22a951a523 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Mon, 9 Sep 2019 06:14:49 +0800 Subject: [PATCH 2836/5608] remove null conditional --- osu.Game/Screens/Menu/MainMenu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 10b2f827af..276c653345 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -137,7 +137,7 @@ namespace osu.Game.Screens.Menu } } - if (last is IntroScreen && api?.State == APIState.Offline) + if (last is IntroScreen && api.State == APIState.Offline) login?.ToggleVisibility(); Beatmap.ValueChanged += beatmap_ValueChanged; From 55cc3de57e3346419b3eaf05403a0d2e7ea01e3b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Sep 2019 11:59:58 +0900 Subject: [PATCH 2837/5608] Always specify a configuration --- fastlane/Fastfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index f6eb95ca3d..dd35fa0b46 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -6,9 +6,7 @@ desc 'Deploy to play store' # update csproj version update_version(options) - build( - build_configuration: 'Release', - ) + build() client = HTTPClient.new changelog = client.get_content 'https://gist.githubusercontent.com/peppy/ab89c29dcc0dce95f39eb218e8fad197/raw' @@ -22,6 +20,7 @@ desc 'Deploy to play store' ) souyuz( + build_configuration: 'Release', solution_path: 'osu.Android.sln', platform: "android", ) From eeebd517f3e5cafc0245e60668407d1bb131f5e5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Sep 2019 12:08:59 +0900 Subject: [PATCH 2838/5608] Use MaxWidth specification --- osu.Game/Overlays/Chat/ChatLine.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index d812e007a0..4c37d626c0 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Chat protected virtual float MessagePadding => default_message_padding; - private const float timestamp_padding = 70; + private const float timestamp_padding = 65; private const float default_horizontal_padding = 15; @@ -92,7 +92,9 @@ namespace osu.Game.Overlays.Chat Truncate = true, EllipsisString = ".. :", Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true), - RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + MaxWidth = default_message_padding - timestamp_padding }; if (hasBackground) From 04a4f9c9a347f45549233517479a35bf4f864f85 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Mon, 9 Sep 2019 11:26:51 +0800 Subject: [PATCH 2839/5608] use IsLoggedIn and remove useless clause --- osu.Game/Screens/Menu/MainMenu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 276c653345..79a3993874 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -137,7 +137,7 @@ namespace osu.Game.Screens.Menu } } - if (last is IntroScreen && api.State == APIState.Offline) + if (!api.IsLoggedIn) login?.ToggleVisibility(); Beatmap.ValueChanged += beatmap_ValueChanged; From 7adfae37843adc5a225244bb76a7b433a8c9db7a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 12:35:15 +0900 Subject: [PATCH 2840/5608] Reorder CursorTrail members --- .../UI/Cursor/CursorTrail.cs | 51 ++++++++----------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 05eb0ffdbf..a50c3a2fea 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -22,28 +22,14 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { internal class CursorTrail : Drawable, IRequireHighFrequencyMousePosition { - private int currentIndex; - - private IShader shader; - private Texture texture; - - private Vector2 size => texture.Size * Scale; - - private double timeOffset; - - private float time; - - public override bool IsPresent => true; - private const int max_sprites = 2048; private readonly TrailPart[] parts = new TrailPart[max_sprites]; - - private Vector2? lastPosition; - - private readonly InputResampler resampler = new InputResampler(); - - protected override DrawNode CreateDrawNode() => new TrailDrawNode(this); + private int currentIndex; + private IShader shader; + private Texture texture; + private double timeOffset; + private float time; public CursorTrail() { @@ -60,8 +46,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor } } - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; - [BackgroundDependencyLoader] private void load(ShaderManager shaders, TextureStore textures) { @@ -76,6 +60,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor resetTime(); } + public override bool IsPresent => true; + protected override void Update() { base.Update(); @@ -101,6 +87,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor timeOffset = Time.Current; } + private Vector2 size => texture.Size * Scale; + + private Vector2? lastPosition; + private readonly InputResampler resampler = new InputResampler(); + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + protected override bool OnMouseMove(MouseMoveEvent e) { Vector2 pos = e.ScreenSpaceMousePosition; @@ -127,21 +120,19 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor for (float d = interval; d < distance; d += interval) { lastPosition = pos1 + direction * d; - addPosition(lastPosition.Value); + + parts[currentIndex].Position = lastPosition.Value; + parts[currentIndex].Time = time; + ++parts[currentIndex].InvalidationID; + + currentIndex = (currentIndex + 1) % max_sprites; } } return base.OnMouseMove(e); } - private void addPosition(Vector2 pos) - { - parts[currentIndex].Position = pos; - parts[currentIndex].Time = time; - ++parts[currentIndex].InvalidationID; - - currentIndex = (currentIndex + 1) % max_sprites; - } + protected override DrawNode CreateDrawNode() => new TrailDrawNode(this); private struct TrailPart { From af09ed1b7fe648930f4bc084e2dd00b7307cf1e1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 12:48:34 +0900 Subject: [PATCH 2841/5608] Make cursor test scene more automated --- .../TestSceneGameplayCursor.cs | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs index ebb6cd3a5a..f4bc172d9c 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs @@ -6,7 +6,9 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Testing.Input; using osu.Game.Rulesets.Osu.UI.Cursor; +using osuTK; namespace osu.Game.Rulesets.Osu.Tests { @@ -18,11 +20,35 @@ namespace osu.Game.Rulesets.Osu.Tests [BackgroundDependencyLoader] private void load() { - SetContents(() => new OsuCursorContainer + SetContents(() => new MovingCursorInputManager { - RelativeSizeAxes = Axes.Both, - Masking = true, + Child = new OsuCursorContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + } }); } + + private class MovingCursorInputManager : ManualInputManager + { + public MovingCursorInputManager() + { + UseParentInput = false; + } + + protected override void Update() + { + base.Update(); + + const double spin_duration = 5000; + double currentTime = Time.Current; + + double angle = (currentTime % spin_duration) / spin_duration * 2 * Math.PI; + Vector2 rPos = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); + + MoveMouseTo(ToScreenSpace(DrawSize / 2 + DrawSize / 3 * rPos)); + } + } } } From 74440dcfdcc35fa847ecafe1d577f618a7d2b34b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 13:01:40 +0900 Subject: [PATCH 2842/5608] Make the cursors click every so often --- .../TestSceneGameplayCursor.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs index f4bc172d9c..f50b935477 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Tests { SetContents(() => new MovingCursorInputManager { - Child = new OsuCursorContainer + Child = new ClickingCursorContainer { RelativeSizeAxes = Axes.Both, Masking = true, @@ -30,6 +30,21 @@ namespace osu.Game.Rulesets.Osu.Tests }); } + private class ClickingCursorContainer : OsuCursorContainer + { + protected override void Update() + { + base.Update(); + + double currentTime = Time.Current; + + if (((int)(currentTime / 1000)) % 2 == 0) + OnPressed(OsuAction.LeftButton); + else + OnReleased(OsuAction.LeftButton); + } + } + private class MovingCursorInputManager : ManualInputManager { public MovingCursorInputManager() From 07fce8397bdd3bb4cae902a65196ad5cd01301fb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Sep 2019 14:24:17 +0900 Subject: [PATCH 2843/5608] Move reset call to ctor --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 4ca9ddd183..18c2a2ca01 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -233,6 +233,8 @@ namespace osu.Game.Rulesets.Scoring drawableRuleset.OnRevertResult += revertResult; ApplyBeatmap(drawableRuleset.Beatmap); + + Reset(false); SimulateAutoplay(drawableRuleset.Beatmap); Reset(true); @@ -269,8 +271,6 @@ namespace osu.Game.Rulesets.Scoring /// The to simulate. protected virtual void SimulateAutoplay(Beatmap beatmap) { - Reset(false); - foreach (var obj in beatmap.HitObjects) simulate(obj); From c2353cbdfa7193941784799fd8d9bd473d542c27 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Mon, 9 Sep 2019 13:30:48 +0800 Subject: [PATCH 2844/5608] move logic to logo action --- osu.Game/Screens/Menu/MainMenu.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 79a3993874..e85d59fc72 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -39,6 +39,8 @@ namespace osu.Game.Screens.Menu private ButtonSystem buttons; + private bool loginPrompted = false; + [Resolved] private GameHost host { get; set; } @@ -137,9 +139,6 @@ namespace osu.Game.Screens.Menu } } - if (!api.IsLoggedIn) - login?.ToggleVisibility(); - Beatmap.ValueChanged += beatmap_ValueChanged; } @@ -152,6 +151,16 @@ namespace osu.Game.Screens.Menu logo.FadeColour(Color4.White, 100, Easing.OutQuint); logo.FadeIn(100, Easing.OutQuint); + logo.Action += () => + { + if (!api.IsLoggedIn && !loginPrompted) + login?.ToggleVisibility(); + + loginPrompted = true; + + return true; + }; + if (resuming) { buttons.State = ButtonSystemState.TopLevel; From ff49c4ae98622e5a05d8d8e3b122a674d1b28ccb Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Mon, 9 Sep 2019 13:50:14 +0800 Subject: [PATCH 2845/5608] remove redundancies --- osu.Game/Screens/Menu/MainMenu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index e85d59fc72..4c3566b3e9 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.Menu private ButtonSystem buttons; - private bool loginPrompted = false; + private bool loginPrompted; [Resolved] private GameHost host { get; set; } From 5b692915be98de0c3d17399f96b2dddcb4b472bf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 17:03:14 +0900 Subject: [PATCH 2846/5608] Add required type --- osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs index f50b935477..aa170eae1e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs @@ -15,7 +15,11 @@ namespace osu.Game.Rulesets.Osu.Tests [TestFixture] public class TestSceneGameplayCursor : SkinnableTestScene { - public override IReadOnlyList RequiredTypes => new[] { typeof(CursorTrail) }; + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuCursorContainer), + typeof(CursorTrail) + }; [BackgroundDependencyLoader] private void load() From 81bb8d9bc4d2f606bc2f4b4211a33b0a0345c906 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 17:05:03 +0900 Subject: [PATCH 2847/5608] Make SkinnabbleTestScene use stored classic skin --- .../default-skin/approachcircle@2x.png | Bin 18164 -> 0 bytes .../Resources/default-skin/cursor@2x.png | Bin 28063 -> 0 bytes .../Resources/default-skin/cursormiddle@2x.png | Bin 7676 -> 0 bytes .../Resources/default-skin/hit0@2x.png | Bin 16112 -> 0 bytes .../Resources/default-skin/hit100@2x.png | Bin 31228 -> 0 bytes .../Resources/default-skin/hit100k@2x.png | Bin 21318 -> 0 bytes .../Resources/default-skin/hit300@2x.png | Bin 36873 -> 0 bytes .../Resources/default-skin/hit300g@2x.png | Bin 39840 -> 0 bytes .../Resources/default-skin/hit300k@2x.png | Bin 29098 -> 0 bytes .../Resources/default-skin/hit50@2x.png | Bin 26015 -> 0 bytes .../Resources/default-skin/hitcircle@2x.png | Bin 7768 -> 0 bytes .../default-skin/hitcircleoverlay@2x.png | Bin 45901 -> 0 bytes .../Resources/default-skin/sliderb-nd@2x.png | Bin 14258 -> 0 bytes .../Resources/default-skin/sliderb-spec@2x.png | Bin 13141 -> 0 bytes .../Resources/default-skin/sliderb0@2x.png | Bin 17053 -> 0 bytes .../Resources/default-skin/sliderb1@2x.png | Bin 17792 -> 0 bytes .../Resources/default-skin/sliderb2@2x.png | Bin 18268 -> 0 bytes .../Resources/default-skin/sliderb3@2x.png | Bin 18182 -> 0 bytes .../Resources/default-skin/sliderb4@2x.png | Bin 18062 -> 0 bytes .../Resources/default-skin/sliderb5@2x.png | Bin 16895 -> 0 bytes .../Resources/default-skin/sliderb6@2x.png | Bin 16702 -> 0 bytes .../Resources/default-skin/sliderb7@2x.png | Bin 17139 -> 0 bytes .../Resources/default-skin/sliderb8@2x.png | Bin 17084 -> 0 bytes .../Resources/default-skin/sliderb9@2x.png | Bin 17067 -> 0 bytes .../SkinnableTestScene.cs | 4 ++-- 25 files changed, 2 insertions(+), 2 deletions(-) delete mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/approachcircle@2x.png delete mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/cursor@2x.png delete mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/cursormiddle@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit0@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit100@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit100k@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300g@2x.png delete mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300k@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit50@2x.png delete mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hitcircle@2x.png delete mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hitcircleoverlay@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb-nd@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb-spec@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb0@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb1@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb2@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb3@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb4@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb5@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb6@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb7@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb8@2x.png delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb9@2x.png diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/approachcircle@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/approachcircle@2x.png deleted file mode 100755 index db2f4a5730b80c3488c618fe825e322742e4007c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18164 zcmXV1Wmp_tv&1#HyF+jbuEE{i-3jiR;O;CA!QBZi+29Ze9-PJ9W%0XtzxxZGXJ=;T z^y$-8)zurLrXq`mLW}|h1%)OrC#3=T`vL_84TXdN`413J(gX#CB4sZrsU|NeNvY=U zVq@=Q4Fx5KmY?aPg}X#BvN`F*-fEmlZGF_+4qwXFE0;l!GI0*0sK01U(8wnRPaPYL zq(l4BV!-YrHgmBa5)%F?G%~fq2N^89jLBiry9XhL$5)jN3Lnv%poapVgN^4YBB+nh zR50e~wNTz(s7<_k+8n+``^B zBCFol-7Bu`>4MMk1?($;zw8DotWdR#t-OYPc8o&Mc7_E64V^#JCn17?_b&n9V`0T*ze2~6TTq32sXlgjZRJ{CEooI& zHuJXYqf*>E`F02ySlhsK&zyWrbuaEw;fFxbh6o<#_)q2wG0_yhR-(7Id5fuAvvU}q@FSzwHk z(VM>#?uPA|p?!p*GeiB0Uj5TV4Ut$JhaX{OK;9MI2u}AWk1Ng^tfU#PFl^cuPu5pT zBn)*b;!*^ANrYq~E7T@RpHTvouhidtKN2Z~g(u@0px1>d6uDOtuVCVv4R=i zklsE7Ly5(PNK)doBL9FBlYsdwr>9s+OG=+d{{eFtiCYT371FtH^^Q&j!ZK@LeNoxKWmKC%gPiJgkdSHyOQm~?WahAs4 zbg9_%=4|(5_e}Sw>r{m@VhxchWG!Sb?zXS~1y9LOGKuuIj07J?(hTWzX_lDyC?AXp zKDtm|(Dlm&R|S^6xIKzKBEuJd`wnCHwWLwwy9_8CSOiR`R-TdJRN^#j(zrg_&y6=cB4S^DZE_Pa;~G*t5t9Xe&r*XEMGC=EcYSZ?Zsj5t-Ljzb-*6s z9?Tx`p60mZhj8;zBr7YuP6hN6mnuM0GyxB(-VX&642HK^Evii6^AzdD{Xb`)doKJW4#&Jel^Se-3A| zX6I*bmvHUR=Y<;tz7PGmo*(~H{YS8lr(Su^dkNo8*RF6TcwEcIpR*-Pdy;LxG%->o zG*Qd8U!`FxzCPtVaJ{YTcNfO3oIgviRxe7gO0Rs7^Q+qH-c!Pp4_Y(=OPFUE8Nxck zT%=57QzXfU)enV)RmAYbtUL~%x?Gfa?m0}Hj2r`h!Px@2#y%}OyZ^@J_2N+GtK&T5 z4*N~|8_uTt_tWpD{i%J48-ttAsId_M=>qAJp+>r2T!Zd)*13Bg%t1A9HFY}cIuvze zwJo(LwHM1Dm*JLc+m0F^*B9qA9Sto5ekD2_*tU2fuabpOou&OXt31bmt&eI<6+Kuk1{Tt z-hd51wVyBJwG@w@d45vfi>Y#i_;Uvb~A-iEMFwe4D;~p24>9fl3xil9Qgbs!o2VYI)jg zu^ly6$5-FL_i%v{N)kc9d6-T3Rf2eWL0Wve4FkK@Ml;Z!^l@A>e!fDg>NYKz>M;EX zJ%vi}H1f{8d$|UTrgxc=`|=vunys*^3A{_*#W4FpQdw77W`(G{hvI4`Z^3zrNwz4J z8EQ2=I~NSsy^WG>q&4|u-tXAo4pa1247P=sOvv03#sUTc@B**Y-0CTIc1;u8XK@Te zKewNZKKht{=?+hPQ@WE&C_5?p<#+DKq{=*>OlJzKkN%F+!i8|*4=-VI`Gza8h}-P8)=?iTR! zaLKk@E@16o1+upP@OKi?s@Lml4YV>m{IQ5)BkeX+b0)vauDhapzW#ZIYMoOHPh+7^ zGvpvM|DtBD#%0lW>C?sR-!}WD+bgN#{+ZkQa786Dqt|$z{p8 z=i|;%O#D_dTcX;p`u4Wiv}Kt;qCb)w%mFsnMXf9Az;iI36qzpiSYE1ip|u$^WR;r7z;^xigF=}eg_oeDVEnc6&zJv{Ek33&}4D z`F++8o`y)i^3`wT`Lw(*z8JP6;vhzSx%nd2ndWscwBFOr{h+fsvcVo)bXj!$efZZ( zp>psSa(7Zeo>T6%n~%pcy;$d?EvD`veqsjTtfvllrGQ#c%voC6PVmlB0h_PjlhUn| zP4S`bkg1OdU+~*6mxBH~rD5g7KFt2C*WTN*m5H#1Q&TUM2vw25{8xXQE^xw1uB3~; zOZVnbA4%?5NK%OD-OpXgk&&&W2iq1~+jl6~teY1s^cgcKC}Br=sn1%z&}aFGd3X!U z?=5FvN*>BJK75qMY%D4sCawjwjS#{OrOHwFd5@W5$Ivxcd@fP{ETvw8O;;o?^_fva zs#HFMjk5Q__-)fRYk6{`*W-MxyZv1B;3hl2+vE6U>M{R7V45+_ZFe-Ku&Txv$!g1& zxpPq9VQcfce-27v-JW3T9b3j2{xfCww;tItKeXJ@?4HJCz4P-4D!*Y^3}Ln2pyzuY zq(bcqmHcCDb__sTTG|1Eu32m?D%#3gTU(R) zDqi%(+uNJ0-XJ?Wd*Q5Ot=OYAE^KIMNC=%mwCC~9cgfsC4Bi=mmyVG4H*LfAFUC!Q zkJlNhVz0M3`YkqOl!!-Av8NNqA6jXm(I0$AG=L){<`hTWqpZXL=}V#Wj*^uGzKy^2 z=D#8tKA$c|L_{!1oZ9H?>w5*!W+zi7=e%uQcEKW|v#fV|92B3ewojWjSqvGq#z~{% zv+&DN<*A6D53L~6mKwxoe*`654vx&xcVHSK6$B08>EdpLyuaoX^L+_)NFe4Bq-tBG zY)bm2TI#|2O=Ub9M^6%k6U zEg^^f>(gB!8WES(+Q3)Xb`94WShees29%6T&OzSj-LGyt!(MjlU3c1ECyTwIS3W0% zHrn4)zilC=yv^}_Spy$cs+Wj%J)d`n?839&nT}DcR_g#qpj4yTES-sx4uW5R@1hy_J@eS&KyU>JrissQC|&$e?d z{{Hq#VwV2o6^4LTZzH@RI!ruciQdx!S8T`u@Th-s}+=k@wVZ$Jo_<#4>nZcy}r#jPd*Jd6Su>2u2%)z0aO;2}cH12-DIrnzGlj%lyUW*?7xlbH=HLK9jX0s98{FSe>MSAqX=)!NOpSU-J^LXcn+0?S|ff%Gl6$s39Z<8s8L zvM~N1T1;*)Q7Vo*|8n(bseD?bQON6E+?YaHFs?5%DCir)cj=r14l$El##VB@zX3(f z?YBfC)n;<-k6it~B>>WnOZE9l;fC?NR6B-L9%Hxo{dM+i=VeFOe<#S&76mWOE(4ybV8`X4z zyCInF;-P`kRNopyxgzn@K{VzUZ!oL5#23V>DPW{u#qiuBB9QSoN2`FvNt>sQV(A zdR39|nWM}d$P&B;4+=wqFNkdOX1?}>W8QT-DD)X|MP_ozMOk`H?&ddp(OG*MYuL<0 zm%c#PuetO+?!%Q{Q4mJP$Ma;eyyCGSu6az0j3fiLGPB3^=vtf@S3^^wQP9f550xaTn%#LVJG&ibeDVlZcG9WzelmrICGlCR3FJ*D@eMF ze^~At0H(cAKmK$fbO`C>Vb-~EHs_u$S?}^nLzCrdt-K_wA=sa~Nygju)!FS{KZJ4O za}FowPe%9=^}q@+Y_a+Mccw&kQ*ouaT4i2=C~ZPV+g8}*h=ddh;NW3~6Z-<4xw2^C zz3t-!%+{$_pyINxErsoi=&?Ga^^Q<5#3&oUsE>~Y_pc9>&ejCKzdrbk-%nkC`dB*S zuXX>~xZ7JK?USKf%qM~j;}0&2Sv}O-gh@Uy4QAJdOky_|x=o8_u71bz+vEHBO_n2X z-vUuOnzyges|sw&sD(3FjsxBp3IpAFGsL8cKer|}JxZ{gCN<}4vz&?@I1FlsDVF&q z<09@vuMiO;;Ft;?4m6toI_5-t$F;nzn^`2eLWd;L)hJEUXsukC<_%4Cv>Y>=HgFZ~ z<3S|Jm&*5@B(c8mC-OV~pqu^Q+>KkCsyWV`2Ch6?)x*|AQ60JlUYz82tiCG%&qe$z z{XnfSc=-novi4}<5_daq5`oek-dWro`?8dKyn;)OY$N!&a^>#WrnT5g1H_a@TGgR% zn}F8v!{41&fozr%DcBD1iE6R1_EOFm@nJEAG;;y*H!e}&o8mg%PiGLk(~pc!HTXNP}6=IW3T(SDQJ?JnmmIh`{tE!gG*tDOEAvZT6<-m>h9iMx*^ZP=o#FAcin_D~u;wgebhu zM$C=c-4j1o58=ge7Eduaf}~oT5V(q0_`GQ7(iYXqOfozKL);9bQK1uot<92U{{ZVce3C4<#q~HrxaD>{`T;`>B#Qw{fOUSbT z)61?LbLtR5+P`|GC|7|7U;!qJoM%`#&>P2)+ILo|Mu8J^3MXR3D`sb8yNuei?ntKj zTsDj{{h67SJdQI zN~<_@snKAR*xFux)j0Ytkm^liJ`_9s0GE@JS(=jROm~LlqH6?g%H4^|>?9SXLAlW1 z_j^zZ?n)#zS%b~N%Gs_q9h9my1onY_pL1$=5j4pN86X$jr2!-auHpTz*=>QwGN2N_$ zqFHFS;*HGy;>YghxA)Ke&Zxh)DDR>4vodssds-=li)<$RtmD7;T^mwiC!+WPI`TUQ zIT&t^Ej;B{uLv5_@$WLw_e#n5OMSFn1|SSzDq3xbeg8xFI}Pg${+vaM$~Ye-)klWm zA66=!^~rx5B((!FJIFevA^=Cc%Y_At_&OURdne56<8rx}+W^HO+k$tr0J7lmG*N4k zWMeD=m!2ybpaa2u%&KJl+^yB66{Bc^_INJ z%K##Dc+<@EOw&<7#Z$%fjVgUy#=|tb8D~s!3QmdmR9k{?8C#p>I8KMBX3i%;+mgs+ zu+fSWb(^ksl$$g3VFTbhc3!jl$lph~G#p-8}e4b)nUB5&_# zdT!!U#-Vz<^NMPfn@CheYvN!Q;*pr5_AI1dzHU6Z1LHY$3Hl`@MZIi0mG?+}MY@xh zCqd&;!ssF#gBYA+bGkz7JgWRen%ywsD!d5DVn~*I($c!HR9UejA%ikR5Y!*rCD39r zr@XS_OkhdT-Z3H-1lgUmP!E%Lbgm{HRPpUA;nHN_eOn&-G-(A67Z^Ypb#h&8O;55A}aFgzeXqGvV zhe$iKZC*u;?xdkLhzEVnfo#*!yIC^@b=cMnW+7qt2G{#R$ z#YRIzlO~N60TGcwJPZsK_8m%(1rNzn`9l3N9U?}n9o`;fT zWc%T(-M&A#jX>bz%LbiVJvVlcJ1EkVIK~ZF=xf>&)1xLT)5QQ^ml`MFabEF6p`bcDDk)m7C=7mL zCcT`+rDFf}4czUkh`&L3QU)*)#G-b=H&a5F-1rH(qzln)#dWN{y;YDs-bYip2-{LT z0FRMfLTmrfgQ((xr_E<1DZ&;9r)^)f9!<-{#ANV7p$npfMWjdtoHXuRDh4&A=$gDO zQd*%`oEc|ZI4b%jo#yhdUfyZy^CoeZqy^k)dS18vnoIxO7AI1Syp8)?W(PYCYbP*+ zH1X5vzWCa$WFQ)@)aTy%O)5mRt(B~w%WmaMujTpv$nZ@BwSX~AWrw+&BmW-mS|(QH zd#|X$#7LVAp9T0GQJ){3E|Z3=pLyza;t}gs~5-X-4E7-0$&wHr)z{Zx78T5BqmSv=RR2~7~;#b z4|hNb?bm<8{&{cI{w2Rw1Z!2>Nb5O^4~FrhZl4qK?aepI$Pb-qm(HDoa)8@)sg>y8 z33^voNf>9#>SqzRouaBh)|^lFse$OMY}G-+NQK;A);ewo(@0TdeG@B)2jj*fvvxYL z`;O&E8s3L%^rWNk&Q_>;+qx64UI;+GKRx;L)EHnh?wXg#D8xB0 z%c{te2PYaeJL!1$SEZ;doM-(Q(K;%%TSY(ez;t)UinJ)<66`Akf4H)!zZzcQ$MikO z_j$|8&1KefEKu2BEgZlyqW};e38!cz#fFA*QGO7tqMmGty|}+YG#+UA|#vw{x$2c|~TYh_jo-yD^FHvAkBvN!%u^;T0G1DeWm+ zDftm40u5OAnLC9S;N;#Kk^*ukP_m~z)R?{=UrkOb>2vHH@q=tuAiPUB6{?v?2JqXT zx{MqT85%3JCy8#ali+t2=MIK2_Sxbb9xiU){oRu3rUX=WXKYLyGKf+Be!fbRy;i4g zrL0_o>h(eN>9C}Dd_vG~S-mw0u=wbWV|T1;j_I1#2N9smLk<+@dj_p`SD2>5fHo zo>l*{1s5EVW#@)eL0SwCKk=IUGA4#3fQW=?4GXaQE+@?@8=(yNhcuU`4)$;Jq_vtH5 z|Btd60P847Mk_>x=H6C7M7l=b*kungoNuPjvNhl}o5Sw~|BTXKc3<7Fb&Mwo&ue-D zHH#F{G*Ce=yIQj*P~Z|_r}9K$rySqg^}AG^ElNGq^CApR)FrbGd;!a6_9c{_N;+Y( zgi{X}`eTHMOV7O7&IH)!0{YO(Ym4lqUo65i8cE~dLX&fS+G_9PXE3;TGa`8D0W(dO zvdhsr^)yYz^uk1l^qkm+#!`gY6G`LJ(!MF@gjfcPHM$q{n)NKCdOv?G=_1jj8q>Z|Y5Lx2!Z9(z zSWGi*ba~Z~j(zcD$oHHLf{XTNp}+%;aSUu{_hFhQCfs}8%KYMxf`RNBqoD4kZ z_H>AlePd9XOW-l5(kQqCH*e4}F;Z}Xq`PkR;%&T+=R2pgIQr^4L(yK{?|)#Ll#_XW zO+e6 zr22n^DI2-Y7xa4ix?X;fv+z=hi?^ii!T!2OH;k5ZYTk+5NzQ z7jEfyVCpu6SBNb$eExjYsnwMWr70#oAOlIpW#tC|$ADFy-+s0amQ3IH?&>4GFr&>) zM7(25bMtYoMj@AVY`mD&DObuXqVF)Wm){()~!dT72NfaSndWh>OVIeIy2e1V(o`9=vg$J|H+Yspi3Yg4vfS+Gx zdB~Soi7b+=a^}W}X2#0B1Hh#Kq{Vq*ub?an<9AZmE_id^JSsDCPCqcOighUtS!YuW z+7*(G$kf!-7x4Y6i_Z>)sivnnvg&loSPY35zu^gr=CC4wjjYLP3|pXCwzQk=JI~j$ z;8<~AI0$ww)fxK00X=^(`a*QHbkdfgR{mEcnxP_L#yNe_ zzxRv@HLRmZex=y~(s~q+Lo)rjv&ilw>gCu-tH85dcqSwEtU4Gz{eA9f)U} zm(%`jW_#XEaOjP>6i_-ODHC!S)|h{s9+kphJ(M8PbgqOvTLflNg0%0I5_MIW4A==T zVbCXgFy^R=LB03K(r7zdkbEMOHEm8H{1maXRP7iSTAET62^T_Oj%xJ%9ugS+=KY&G z{i^S%kf*^SC%q3F&jJ(x{-5dKt)F2-dJN%9td0M@)JH@ZHc4Mj+2PlT^mNuz4<{0% z>>?^;)k-Jy!gTIN5i-{jZP*wswTX<^28NR zpk1WfV6uRUimJ*@_jFWISlu)QmkikoPN@OsI@vmavO~cX{^A>wDwBTgsQ}4FKtX8} zq-WcPA@*|l5H2!M#(X0DT^I5~`$)JACcRIZn$<`rQ%go3$_r{cU@q)}@Me9XcT~-9 zCrb^5@%{1Z3wpLN3a_|d38}Z_{6uA%!d+%ww=zCSO$Tg!MeN!(-KWh<4sTE|8O}C| z8S^OLv2n!#o~(646{}#$vA_(~e#y}ME<)ybGCkB1Z(tgGSqyXect8v)-|@daq{^-m zyg+V;R6IAy0fX>g#qCw)q?jxDS9~}HQ2PJq0FnCv$`SupOY&9oy-7js14-&q47{%$ zG_F>o$yCE`!Xq>J^KFhxFI#SbjL52-Edn$XcKMr-24H)*rkCisS2fW`7;7xo;VTT0 z+dn3}bAh_NgEI_Vi6M|aywH^?V^_zQi$Y9TE0V*bwO})GYd`rq4@aMKi-J zQj=yb6E8eLx|^Qgam(hPuz_)hV)uV7VM)DbX0+xBOas+fZlgLp&w7wQLcnD^ZUAe4 zr=QpQr$9P2ND*yX5h+P_-?5>0F|p;O+LulOVL~Q}ychocS69~*DqT=L(jWn}Y@KP3 zZ&S+U+#Q^e0gzma4_eaMgCIT&Hqk<7>q17b{6| z4*=;tl|pKK`*woYBxO&)G{P9DJba%Q%jiH*(VB7<%`0CdvO9~^I4#h!8*{kGFXJ?4>n zDJ}T^MM55urQtNLa6opxz44!!)O)P;-N>7RxG~av)F7{yFEIZu7^HCxuM%jg^Xpn^ zbL1Oo!3A;uxl0J&g!DU@s2M>b=Gu_6(S*bwDTKrh{5$v4d1gZqOEhhcEg}3MO=C9h zFp@}BZ$T1E4jpE)sE%iE@+}JiY`7UUna(J1|9hX4Zs`whOr1A1DC6>f0Tzal{maun zoX!d~DqmHk4MfQ7dlLT0xsE7H|1%*_Ql)%%9#TlfW2qV;a?q=s`m-2q`&Z zvQUY{$kT4Rz^f7la}GM)1uZM=)tGlIO+v_xxL-@DD6viWkBK(lmPszx=N-dtv=`WFj_A8z%^H~a4dpLq z0p*oB0fQbM)&rvPd$ah4od;LSs($KZDLBGkBvI>_CR$I}$c2N&4vP>flKc@azB;fN z<@@7D$Zl9*VgjSIm(&q~k@8AzJOq$(j1&P?V`IJYd#;H>ru-~X51Sm-v;(@|tzd(j z;7$#)+;GZJHMTpn&MhUP9YdW!({S4rwl(1(*Qclcf8j=lUVd_*6_!{RbXx%^6n3~f zszAOLlMV*7IIG8e#ezJ2ue&2?RK6FV>sZWEB=awVa5P(TU{@Idb)s4vZfqmb-~ZMg zNEtda)d4+a!WuAdH^SL2gFH>xmy;yS6aDXN5TONDfp%q(!}-_CHvO7K70{vVN|qfS_-#>ly`!=$B!Dy@;kJ2INCI6d3B2F}*J`KnTC~CIPVk z32v@kg=VEAVdpzvDV2=3aYdGLZ>ZRd|U?M zlk(zQXYHHlKF7C<5F1*5Go!Kg7Q%~o$gPqTOs}hQXnT@usvy^GAX!~D$)$PvBxbkU zY_kCSANO;`QVI?Ve6*e-A;6Sy0I=_wC>H$}Ef+Y4`AVw7)N4;f407CH!wMDKSQ9b( z+0s{~-+sYbCK|^}4Vz7CT4e+rkW*C^7D~z;5?{rSY4QnN65bArfAa?nKi=ha!plQf z{f~e`P8Fd$N&ica&&38>daYC$K!e=eVnfbXR3Ly9qyfzr8rE}13+b5tNYb?qY&tbZ4QkgPa<>1f-`^tcbx_a8tS{>Hz0 zaY1n-2_$?=%&Ee%!1jImIbQ|;|4KUyQeMD$Cqqu`Pq1-mz*u@WCfJsXX9=?Fb&yD~ z4SddM5DmCLwN#F&Dg2if2+$*Dx@8J@G@z#6tR+&Jo`6*S@b)-8DVN5-Z)Det5ZC&L zZ)G?}Oroe39Co5OLSZt53j}cik7ltq*lcDXHhp}!t-};`5Aiv+NmI^uYD|=`lj4-F z8XqwZh<*qVRR>@Pf5qXL&vy$XDX0m@fKL?Fgu{*ty;LjTjSqi6u4%BrVJlTI?Q!25 zca7}!meToUY{9JKp$R8JmCR{9o=$JKS|GH?9~b;<-Dk6Rqv?+#^*Lvt8)T;9z%8$i zGy-QfrY!hxqq#q!jGX7~cj{z9IMOiV8lAeXEO)CHQPdEDg08^~OcRznh;c1C+O_JU z7%2JDaS2471~u(gRR( z2Zg@dF))#T$$H$y%{Sj6mTjDZsYPR2qc!adWJ;q<_hT7?ocKt}SQTj`)>er237Oh$ zJrXVc*LcYIf;YGI*tguyJdY;T$m4U@G9>l_h|#|?_5Chx?d!J?oPCsnDg%lS@ox=C zgA~w;-Sq}-$JynzggF4tzw%&>@OB*j9teOimJg2BGQU+X=8FF#^}$G1&A@XD&FhoJ zy4=u^s;lmB40&InMq7Vx8y%yz#Q%H9Xw*2NxU{>Q=6 zyK6sJKKACTeWEP>Pgw}Tajmwyg!D2Bs1%yaKr~ZCI3v&d`5-bQXy!PszW?p13{-xg zB77w^ww8LW^37itQeyv7W0p?6Coy`V*OJD)QxWAvp%A2AdJjle-dRdWyBBa~cI0eU zFA9Yo8e>IMz+@Mzm+1TOS~t0ZfEZU|yLiKLzART10n+IQ%>;n54#2hMfrFbp_RD@as0U)zcuv1;D9=Dr+LR1Cz(z`F4=KZ@Hzr!ADLQ3joTxhZ|4%(BA zCR`$bVzWZEFm+l!8yHC^+$(zp8O-5xS?^k~>#oS?9yS%+I0`s&_O+U!leC|ArYL)9TMu8of^x?_gOX+sbr4=zj{G z5N_>Q*jDcT6a2xA>&XmQWN8X<jLOzwMm(|~NRSu$9HN!93Kok~EbAd5e62&0 ziVVGEki>6mYCeb2)B^TQz;yQh=>3g5e|;nEE7SxVSh?+`8Cyy2%s9{%uFmN4PfS5W zWb|mB>rFMih7jx75cJnXlfS)?9hn_V zuGM!ki?e&N!BlKMU;NUg^o7yFZmUz_(aiNa^U%rY?pT`X_W6X~ zLFr!ZrFVGPJ9tFQmTyB!q?tu_NF1FThgaMzqCDo%?A?_w~sJv|AL^L z%NyeE7xB{Rd$p~5iPYW9#_ui_-cCdD0^Ug~410MF!|`~Z{<}^7rW@Bwf(yAZTzo+K zJ|03T+Qhrw1*IBOWhXO#pRaYcka|*iH%A){hDRMr`>eT*pr|Z@2h!8x_mFQ$fd9Y6 z1L|;6`O^-NnU8nZP!@yM!*`?>3bv<~j&AJutV{2;Fw2p|pvaf_IcO#3Te==Ozqs4_ zz`F_vgocJHcGePBI*!yA26t-Klm+%kB%xTam5FeqFbjst3+}kP#C^el?*N!D&V>A6*%Y< zbYnp+CBAgJz12Cwa#i#xZ+?%uWA5kp`pvU&u}l&0j!DmS#Ag3&;)_#FiOc^!LJ<;J z4M~z9iASO7`-{zYe1@Id{Sd}Vwqdu>nSe6s0cCITQBlZL8K2#tvr?#1HrL*G%aov_ zQpfjJ#)NA*U-^dtRQ8@rPj&Sfd`uo0g5q-_P++MwZhBC!Kk zg>2xx=jG`o#FBqk3Wa@1{L6Kr(qY8ZODhH9CeoeHf;f8f;*@{J^L;N}`t*Y+YA#K- zI&0B27DNdtU;BYHTl7Ngxxe*23pu>Srf;{M_$s(_Qv#VYa;wgFv zGV#f~vjQ}}i!-qyISU+{7(?kH0E^XHBK=9Ygl3BaOQ|t75Nbv9nt6N1VBvU$(-zX>R0&mo(7Fc-f_4>w4$+NSD9PeY9A82{e&OpqZkM&lG725y6uXhp7w=ubd@O+^;YI-I(yuZ9fn0w zABU0ta?&-Q=sj12tBj>jhbQoHB;hiZvsa;Mk_Ix<`|<$to|gwhj#lr~IQ25*hbRx% zdXRPwJ`!A75Ja{0r|s>6P?E%7P)>SDov;FG0$ukLE0YfLg<&VfOq9u^I^)q7Y=q21 zRPspKsDhOasK$&I42CH8oyAwGg5-128awuvh9kcOjJJad0?q}NJu@?+e-Nd$-Qq4D zo))ktF?PHu=X~niBqUTF7Ty8xzchduyN`F9w?Gi_EhhkHB&j-+)dHqn%^o51S>q3m z`@_}wi`2ml?|E%xc7W!oD4bC}&D2QSpTW|cxgVp|W%I4UY4?57@7xRGJ%yhn^_Q%m zmd}P&Lyj08G)SXdiPM93edGmQ_P%h2Qy6_Y0)x|#nF2j89Mc2^`oLPa|6tj+us4Cs zqXvjq3ppnk(Lcjn6`owpszPQl8{t!=y-`vU)B;j$7l3%t`c)~vb9mDH9>Gbg>k(L> z+|jrm53tO7XYeA9W<3oQjU-fly`rlKU9)njqe-jcj9|nm_3xYe)8(74)@9ekUV0Cg z?z10}gYu&t`Pb>LJ-boQ=E5O2sW2LBh&H#hh1B(p=#B>zwCI4TnQkVGEo_sJoCEdA zGjAga@5mz9U%XZ@MeFqedl|Y0iiRo(nez4=yn672R|S`_sp01Qt_)Y{w+h##t@?Zd zlF943LN*Tmd^M`mG{FP;Ce$Geg9_8AnQrkOr9LcXPumNEUdL-{^y1Noa!;$vitqF$ z7M%bQpcyk!65O!S){sqG}Bz4!#(BQ zF13)lA9`-4o_h;3d^JXMcpTqg-3to)kj6Y`O4FD z!)GFmTAAQdL-dqM0{@gP@80De<*W0c=AG!6m#j5i+Zioa$Vx8F0xK+;rMIa=&nG+Y z@v(i5W!S>(QLdV;#cN3$msEXP1B zczTu?&;ilaehAtdmuME7BF1`Ta@UKZe`>%{;s0!tWf8z;{5KB`I-H`)U41g|VI!b{ z<|J+j+3l4-p1wImZ)!MgLzhX~-_kgwP~uKOq+E&Q#t^@oOrQ3^X9{BfO2cMcbUnJa zPPm<|wAIM3g-^F>imUdBh$y9OA2Dq8y}vzI$jCiG4|>S4R|8Tv)Q+xd`(u-TtOt`e zBZ7U$V_0xkhr1u$lV4lDK&UERemb>KMEic5M(i!`->-7=?7a=Qz(E3eQ;Q)0U|x~) zauwn9p1}$L`Vty+Oz`>Mc<^D5@;O8!b?*p$roPfDfQ6X@Y%75x^X_@F2mqse)ZtH~VHdKcz=tu4vSMOYkitsH7{
xUBq)wpYuSo%L4;iD|W&d3&2irtb$J#-rmG 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 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/cursormiddle@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/cursormiddle@2x.png deleted file mode 100755 index ebf59c18ba9f62390f49be4bed696a997a51f05c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7676 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 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit100@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit100@2x.png deleted file mode 100644 index 7db8eb312403e739d8dc61b280f930443ad0d81c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31228 zcmV(-K-|BHP)4Tx07wm;mUmPX*B8g%%xo{TU6vwc>AklFq%OTkl_mFQv@x1^BM1TV}0C2duqR=S6Xn?LjUp6xrb&~O43j*Nv zEr418u3H3zGns$s|L;SQD-ufpfWpxLJ03rmi*g~#S@{x?OrJ!Vo{}kJ7$ajbnjp%m zGEV!%=70KpVow?KvV}a4moSaFCQKV= zXBIPnpP$8-NG!rR+)R#`$7JVZi#Wn10DSspSrkx`)s~4C+0n+?(b2-z5-tDd^^cpM zz5W?wz5V3zGUCskL5!X++LzcbT23thtSPiMTfS&1I{|204}j|3FPi>70OSh+Xzlyz zdl<5LNtZ}OE>>3g`T3RtKG#xK(9i3CI(+v0d-&=+OWAp!Ysd8Ar*foO5~i%E+?=c& zshF87;&Ay)i~kOm zCIB-Z!^JGdti+UJsxgN!t(Y#%b<8kk67vyD#cE*9urAm@Y#cTXn~yERR$}Y1E!Yd# zo7hq8Ya9;8z!~A3Z~?e@Tn26#t`xT$*Ni)h>&K1Yrto;Y8r}@=h7ZGY@Dh9xekcA2 z{tSKqKZ<`tAQQ9+wgf*y0zpVvOQ<9qCY&Y=5XJ~ILHOG0j2XwBQ%7jM`P2tv~{#P+6CGu9Y;5!2hua>CG_v;z4S?CC1rc%807-x z8s$^ULkxsr$OvR)G0GUn7`GVjR5Vq*RQM{JRGL%DRgX~5SKp(4L49HleU9rK?wsN|$L8GCfHh1tA~lw29MI^|n9|hJ z^w$(=?$kW5IibbS^3=-Es?a*EHLgw5cGnhYS7@Kne#%s4dNH$@Rm?8tq>hG8fR0pW zzfP~tjINRHeBHIW&AJctNO~;2RJ{tlPQ6KeZT(RF<@$~KcMXUJEQ54|9R}S7(}qTd zv4$HA+YFx=sTu_uEj4O1x^GN1_Ap*-Tx)#81ZToB$u!w*a?KPrbudjgtugI0gUuYx z1ZKO<`pvQC&gMe%TJu2*iiMX&o<*a@uqDGX#B!}=o8@yWeX9hktybMuAFUm%v#jf^ z@7XBX1lg>$>9G0T*3_13TVs2}j%w#;x5}>F?uEUXJ>Pzh{cQ)DL#V?BhfaqNj!uqZ z$0o;dCw-@6r(I5iEIKQkRm!^LjCJ;QUgdn!`K^nii^S!a%Wtk0u9>cfU7yS~n#-SC zH+RHM*Nx-0-)+d9>7MMq&wa>4$AjZh>+#4_&y(j_?>XjW;+5fb#Ot}YwYS*2#e16V z!d}5X>x20C`xN{1`YQR(_pSDQ=%?$K=GW*q>F?mb%>QfvHXt})YrtTjW*|4PA#gIt zDQHDdS1=_wD!4lMQHW`XIHV&K4h;(37J7f4!93x-wlEMD7`83!LAX));_x3Ma1r4V zH4%>^Z6cRPc1O{olA;bry^i*dE{nc5-*~=serJq)Okzw!%yg_zYWi`#ol25V;v^kU#wN!mA5MPH z3FFjqrcwe^cBM>m+1wr6XFN|{1#g`1#xLiOrMjh-r#?w@OWT$Wgg6&&5F%x&L(6hXP*!%2{VOVIa)adIsGCtQITk9vCHD^izmgw;`&@D zcVTY3gpU49^+=7S>!rha?s+wNZ}MaEj~6Hw2n%|am@e70WNfM5(r=exmT{MLF4tMU zX8G_6uNC`OLMu~NcCOM}Rk&(&wg2ivYe;J{*Zj2BdTsgISLt?eJQu}$~QLORDCnMIdyYynPb_W zEx0YhEw{FMY&}%2SiZD;WLxOA)(U1tamB0cN!u@1+E?z~LE0hRF;o>&)xJ}I=a!xC ztJAA*)_B)6@6y<{Y1i~_-tK`to_m`1YVIxB`);3L-|hYW`&(-bYby`n4&)tpTo+T< z{VnU;hI;k-lKKw^g$IWYMIP#EaB65ctZ}%k5pI+=jvq-pa_u{x@7kLzn)Wv{noEv? zqtc^Kzfb=D*0JDYoyS?nn|?6(VOI;SrMMMpUD7()mfkkh9^c-7BIrbChiga6kCs0k zJgIZC=9KcOveTr~g{NoFEIl)IR&;jaT-v#j&ZN$J=i|=b=!)p-y%2oi(nY_E=exbS z&s=i5bn>#xz3Ke>~2=f&N;yEFGz-^boBexUH6@}b7V+Mi8+ZXR+R zIyLMw-18{v(Y+Dw$g^K^e|bMz_?Y^*a!h-y;fd{&ljDBl*PbqTI{HlXY-Xb9SH)j< zJvV;-!*8Cy^-RW1j=m7TnEk!1@*s91?cyKAMSV=jms8V)f zM-|I)NoCL}Eh$O{B^iuFEe1(#1T2vR36KOH@aAo^-}T)5eqZ07d*{BHhncs4G~|Bo z%sKZg-Ti(2ZT&fkmIPbicgp%P23Z?7`4Ce|7{X^V)wpfcQ zy;N-ORqgJgvv+NsXVXi?T+Xt%yI6|rhl?|#CwOt1Niy8incWV8$#7avEA#jsniHJf ze`E}&*BRDt;`;n`V7&`CKjjCcSvbA-Nb$rT9)$IF!)cj0-Exg^I1&qpu4n&9}~ZAHr-yrDq{<0QM{=* zRqR#{g42A2bsA3Z3F`#TdEop~z^pLHZTt*EU{(NR1l}y1*5ROZ%NQXeavF(BcO_+( z9vO*NL`1#`L|z7w{?5qsdOBsKdGAv3+9B>Bc&3RW!;%T#`b+Ss@lRHEAcBQrP}$|^ z7Q@PF0JU0l`0eFfQ3q95`BxOJqBff6_YTJb46;>R9!Wr%Xfk7DVwo^SlAw=GNzdaF z$~2tT>+xWKNxK~fPQRZA)}lzz3hO~|UW)hXzHns@y1gFhZl) z<+@SI6djIHv0KU*r;7Pf#uyguQlTJIyrozv&yP*0n<120SPx?KleF6xi>p=J>_X82 z)>UBaR3-TJF|4hCccJ3B$8mi)YolJVGinBm&9YN$jaG|Rz*-iYWzrx^Wfpq3vTeon zVd;h$VHSzg(tjdF67d(sW;IL70)kOWN-z?OL?iN+s9|@CP+AblCig_xG;t_7kvm5s zj?4^4m6EeCO%n!8SIyF2c#2}Fs??V#gr!pSxYrt=2b`Py9#jXwR4-bUA!o1W#x2p| zTnEM)$Drtryyi|hDta)t=O*WFoMnm;k~2$C%7##q`BW5V%4rReVYZmV;GTukwtE=O zZT}{>9r;!>qgR1-Kb-wN_?pEW+HX*8MB6p0!fDy{@!9La9-LL+?2h_Vu#RB$L%g4BjYe+#dj6okKW>KCe#0*#ySk7*1gnR^c23%rqPDj)1ccoC<(m(Hb_20oP6L z@0Rn$67TG1h|KuUjy-KhZC~+yy>w(om_?wOz8VshBE6zntAfNO2&PwbL0%KW>2YoZ z^6EtcNjXAl?l&8hB6ScpDEc68f-n)ag%t685MgL8W$95A?}KR0>4$=e4)@JZGr?gn zb&HMK*;=Jy%o2%N3#1M~d_&Wys`OBD+GrCgSp!l1Q5B>m!YDZ>r1e0Q2U<9aR3Q-PsOZ;`c8E-g zq{4TJ5hRd;qbzuBD)BssV-y53EO`!5jJP>M)G9F>P|rvT8e~El73DyNSmgdLaBDIx z6dm48aAzSf4f|A)d!1oTp5n^1B4)xxoUzWe6F6 zr)Uqe_8%bZazAMrPLX>(fj5nZ+3V{v!ZeZi;jFaG9Vw;AGy`N}5s^rPAe4+mi3G<) zU1?cCN=hKtBCZ1B#7`BZl}N%W8el>Y5(k-}D)tjaW`>i+S&(;O+@XA5`B-r-IBXV4 z)9_{3k|}hynx*3+jNK_3wYg%qwhd887{WwDHd+D4r~&6S5+g(hrU9yWr>u>F8L*0q z5t6bBagCsc#O%C}iqb5C{)-BKM)a-`oJDPruIXDtAT%y#38d1e+_>gBgi;RL9G$V$ z+!|{KiR2(t$@Vj4IHyga%p?82NXr~c%|fP7wUTdLZl+)fWC*n&R6=!zl!OrCr9c!!)kg|jN0_M6-{NAC zZZ*;j_uW!~mjm$vy1@PwB;VsaC(#&_B#hqRStS#P9pY|yw=PhxB|7!m{8dbXvc6Ny z0nZ3^Br%K{POmx!KXIlwd-V{9L{p)%r4{CXW(4aqQc_|Qh874$ zkT7@v!Atl9?E+z?CqC*oib_w0Xaav9({cx*qu()D2Nz9vaS=_iUYr4{)#5G$fzV?9 z6b{UpY(rp-4zU`Kcach$@dU~26_`N6A97S7{xaaies{nFa7$FYaH^6=cmn9!1#H4+ z`>G{S-ZTmL0oDX(6v@YE3vS5hD16RT4#JnQp>W_rK=v`UfVlw1fFJx}aY9!$ntmQQ z`HeezlW`ecD;L1!8M0YpAg+KJK15qS5lBsKd$=h)uG7BLK8;`oJ_Ya~kfJz;1WDrn zvzvQY|n#E7(`J4iK^MrU#6b_`9frZri40> z3Dj_xi^K$Y`0K(ZJTy!rF@ci5l)sxYfW$#(zU4J_gE){2!5A@G7H~o^z=+_78F83-*pP%BPL%xo%IYSsd| zKhP~&wIxiU+=kQ@Gbk~;aHd0fRyHMm%4-Rq@Y;_24kiIO8E32+D&S1bm)g^Ex%NMB zR`-}4nC<*Un+g+U0Hfy$?OO(%!q+JJ0V`$nc}P2#gC*e9RGKykZ&ouXog+ycUQoGU zf+QuMs+@>WfllQ-(gW$>JHo9b##|^c7X~1pibQB&0*OR=vYf{R1K|ha#!^H=5`i_| z8Hz-iV4nm5czex3ApB7}LWdO)mJr0fG2^Iy2e>8aZb!YlP&tAJ4+_$m!Kf~N_ngiF z*STPTeCKg8&6+?aR};ttGWbGq)jkXiFbXX|z7RswIz#kLB;$}F;A#uvn1f)s9&x{l z{|`^^gh(JD{Gek3;TkwYjfumc42X$a+6XM^Ep2Dm!t>Ap1n&esKF>OsYHO8G9#SR%Qpdo;XW4~tL2EtT;og{-m6XYT z?5IanSH2B)L&nLqV<{bHq3?Y0`NFU_~+pI>S(KL;MP>JWg{j!XcFb1pg% zB-&MztFD&8{1{+X*1(m-_9Z5;9n^T3 zVYEq|_89^vt}5UZW}XAr5IAE9gnKf5CC(Jr>~(u*Hg`AP-0OGmEX#7a*YCYy2E_OY zj(UwobFEQpTxhlCURa!8dXC=X26?~?BjByVt)qYwdH_!QA0yppv_&+b7$k5MrE1DnLy4W`>+k4vcE65y)CjMdGK2IXpsk(FZ@GBoLT|1)|M{iGl~1-8+FwWn5^*SDj!-^~ zU`ITeTS!fqpw3aFKt?h^8QKgY*@j5kTyIiMXpMw$VDKx!naw_hl5If;76uq_RAF>A zU2P9eFwM1adQ|2H;kR8FM?8J281(XOt4C^imUx9MXY1~73KTK z{X%XWSt|r1kkekWL-i{#L2|22m_Ri}!8Ii%h_QlAR4NrNnwSt{)v3LV>o+8)l5#W$ zk|mNLBJv2vxVmxWPa#F#*6;U|w%#lK`WINnZyFUFv{ms7OY_U0gSl*A2!Di4gq6fW zUxjN0NuNO=HSk_UsP6_t$n16+h0zXUHWM_5mM{@^ixz~@Z{g$DEPyDi|7adfu)wth zvcT^JVAH|9aCP&_+acn2NX(XDdZ6)^;vMrJnxGi^y{nl(hjwLb=Jetj#PF=srYOM;|~tIhj4lc0?{i>_ep`$P|I; zETMp0ktid~Z|`p3zp=gk*4@tTo2<*jt#2zHUHovdT-C;V_4M1jKUX}t^;5-MtM%kv zXYTz!XrOHvZ<}&=Fg#ag5rDKt}Cuw{y>xjVs@}+ueDqwU;O!ZGX7<_V!;c z7OKnMI(Cv^ehWB12AmR(X<=^R_g9uq{N`M1{>$KZ2mEfs|J&f!q3s>d)QMoFQ3oQY zPtm87Spd5}_<}G#!;l#z1vo0tW+&#xxU*8JxBn$>eQ|6;@$}IocO4zx?R-&eprk z$MnI)zgE1r{ey=xczWyle?PhVOU2Wjj}{-_{+W0Y)9J;fg{7xgmrj0)8*~9m+P4yL z;w%78VK+>nvCAMMeTV_E8Py&pE1l>e&XWFMzmw!}*ZFMCfIIbM9)}SeX>^dKh0UxV zT}erVWPNi_QYIo9+xV!^3Gu@$s7+0UBqc#2i1glQK?c~|-gw(iXXopzfYR~=58OC0hB5aGFz*_;=g@S**T55$m_VXPL|=sRUFpH@~^p>pW;4-@Ej~#Rr%EI>PI~E|0Gq zJN-fDsp4bXKUF-v`_cHey|DN@cb>fKm(dC^LKRp`U`_2TytXs2!whwV-T=n0_I7c< z5|Y!`lSH47k?9M#&L1qD<8Y3~1D+5DhgELMG&;wmlBdQd(JuXh?eL>laUn8r#E5E% z@4SUZ7={}SpRXoE*pXBcqA!#j1j8h00ssrWA*yu!@;fja_DRg|Uiuq{)#pg}(f2fF ziP=Rc5}hr|#na*d5YBvj|44^08St~yfh+?i)#ZoiJg1NXO`@yd(=iZ4XbkQR!gr2_ zf%|KEgtUiY>?#tngb^ylS4bSi;)P2ue<#cx=7EIqean9*6!wuSe~gzD6z^U5!Q!Xa ze^gC~S#tF|`h&sh*;9A?64_`HA;+|uVG9}?xUq@r_+jlkHL+!dpBG{`L z{EPL+3pLOA^2ND3Pv8BEBAlkl8`bZc#lX$^4-ql$N1R zc^@QJ+SvYQu54a<7oEpHol)_ZRvs&EmH~2Jlws#d?*-Bzx$d|QR~x9J-ZertoD2j0 zVsJKnDH9}LdKyS_zzmOx9wK0Cpb;D&2=56@K7u%eD=`81X6jgF>HOMD-;+(DzjERq z9$TwTU^v>97V(Eye;oV!-b5t3TkpDXX;iuM)ZM>iw~>0u4t5H|Vc=k--DL>}QXxf#fULdvO3570s012`!|>f@mW`WJp8;LXoT`e%qlPE2OR3pu#cC?$FQ*P#1`-E?m6) z^80r>+wUZF%<=Er#QFN5bI50>3hIm7&^a?9gJR|gThPWS=bp6J3LPJC1 zW1Ikn6%fA!6D&a_1HNrF=ocU%?G)AV6b+-(2!kOhWrkw$l}qQp19#zDWrFWr`kTc= z&9|rQUc z;uahbz!#hjQ&e$T$_$$_2zZ!`BR!r90o;Sr9wYcTO+3-0s3So~P?~{pExbiNkXOZJ zr|Zt4_8J-?23+PZZ(MpeHr=1;5Bm3;hn@sIC%2POuo$&@WK1;`s$N&3(VhnIRgw0o zZvc|8)lSBE!T_yc{pcV^fFRMEz_t@65l8^8dW?S{X&?->fu5q#xMO_jTam)=^n2~( z+XIa)47oOJ zqiO(~%rR)uS#A-CxPuVLS|Rlnl%I#EF(aJgji)%?#Dwb?HH#RyFi3395xwv`lSya= z&Jf_Jd2#(B>T~-83Byx1x0j4?<&q*VU)gmCBB58-& zX@)o&f+3u4c$R@w0|f2+kXzWy%#LF)$uNTOrNac_L&rtBd+++@)%RPj67qI*7R~!O zNdjFPe5v@k&7UYXwl?0$SOacV$5A3)$qoSwK`X_`bHrysJEno5zc9Uno52X-)#KaH z2hv|NPU5R+w`mG09@#9N{9 z&=hqdmS?rXhiK9#G$R>Uy_P4C4n^_(iC%sMiqfP%)$%O|dgvozV(Pvd4qI5AHNe*!z<6 zaCJEv8ck>~TA{~zL|=hk2n?~Yz40cQK;QZIF8|HqwPb)?Q4qoZ(gvkr6>`puLKku$ zb%`If0TYxk^w3^pm`C&#czhC%nBn6|8_dB>sqd2_D?uU}A-PQ{U_kGfm&S&WRJttAALlHHg>+0d$ywOTyQuOg}PwkN$CF z%@JEoBN$zeU%9Z`>)eBR`;MHao~j#74hT9(rp7Ya@s+twt2i$GOwKAzNVsm(qK)U|ZI-90 zaHGUAJ6L3XIsGFpj^|Z_e5cY|=l*PbuZeW|>g9KxJ$2W|c#K5Uod{;YjZ%~A&W}V45!@)v*an86 zY<0HYcA_}#$TK6$1|k}zYLK9ep>}Z2L0U&R>1$&4r`L*Cq+y1AQEa*9!Q_@xi4J^P9!AcDLT{046v<%11{( zVxfcu28fs_2qeyGJA{TuduMm+jd=SWK2yI3t@p!xI>|d-=dwNL`fxdwtoz?z`@TIU z5VqCD)pcQA24-QGh=1bJe^rQ+8%ef-Z9$*()TJwH-$tVo`&A;e9M3Ywtrl@uwkzHv zOy4?8;L0Kjzs;DE>S7F!gOG#D-_r;OJ#_gI`UlrMnwy*dbbqV=c2(dz=D+Kj=dZyH zfKfw*TLdOh$9f z=mEQtWP>ZIO)HBlS5B{Ohw!<`R^HCb3GVaaXR|AvC3a$TYzz%>6x`Lcqt3 zWn!AXcj>>StpBZW6#vZ0JN^v?#0VPrKqJKHyD{tJqNfan7*Vv2n2#1Pt76de(e{5~ zXM!Xna&iU;X8!J+Y0y7Pev@sBnDc4)dsX!#swpfOeRn8KH7|5#ecY95$` zCX%{lHo;lrMoaQ2HA!W3qP-fg=h%?h@2>azx!&&<|LDr!C_LXxf}nx{)B@OrVG5Za zG3(KsUh6e7(9Fr`Y6b(&loUz~B?nCm;`BaMF^yuR8jUcTqi^u7UuWuXVATJ^`|?Z-FeziYyu=XwsH;Jc zCSbTo^yn9n{#W?9k>R8)u8WNm%O_trwR-v`-xW6pYe1hKo@@*IYh^iH+}v9Kdh!kp zZrj0lv|*YJ=>h|;wgJ^b-(5_GCFYwX^T@!`J))i}N@Chec>;$EYB4W1-p7kV49fsN zW0hfT`<^91M@`gS^(#Ac{0t*LO45e>sjGjx_|Xd=2(EsTAgh~87;G>>&V$NE-@xDY z6VzsQ`dvIMF@x(VrKM!jxCk5p6F~TA1Cb~))7Z$(XoCR)Sb{bYKK;__(uwD}w1>P7 z)5badmLW##5()(J++us_lF_Cg+4ylDgXWOF5~A0h4`K$Nl?1@8VmACmt|??|3-W`bOHu1l)dM>hVau-g|GmM#fH zCVt_vDjt+`b$q=6v%n0ezRd5yk+?c;vaev;*x8`}rdc$ZAt*C|V+5PyOU^Z~(--U@ z^g1v^GLMX)FoBaj+VM9p6wK6mB#7Q?*WMHY4Oo1#+;`zAXBlEK!b%ot$=!Unq{ShRDDQopyas`ZSawee-MrYeEVyw%cnk185_inFyf4A2;3oM}xWC8|yg9+63YW=hfO_O=`Mi}&C;bOf< zj~_rg!3ad??W>F$p^bBa#g$+J-1Hm}5O!u-gNB0oi|ys7{m6d8VaaGhH9$5KkdA{l z+;Q(=uivu!8jNukOOaWm86F@kdEE9HxFzfS{`Q-LL=WixJ2{aSoG;?@8 zIUZ`h83MW6&g9Bq&^rwSjKf4yN0}V<%pyKqU?$x|zaM$!eGx6`^QHFEmHX~`;6)_IM$L7xZey}@ zoU?a1N&5+z36u~nE~X8s3PlTqM$k0M{RF}c9`O5&?3~w8&e>kZJM`sdqow1Td6Kb& zYnGO@dL@WL!k7?8yt74r;Ka3-S;khH-B^9InVril6R_$^(mu&XC1BU$(7T83|(w- z5d4{7qO5>%8dmN}@dk))HJh!qg}L?xe#ayv&&NqwND%&M>4edg{@ojGym=P`*?mm+Luy2M+34JNRr8+eOKJV&XY z;CO=l11Gy{7O@INbe2UNX5ScrqZXkQA{Ht6L8#{_Gt8z5rz}3c^D_a?>e9*=Xc%W# z0dLHjL|RtInqd@Y%2q;dQr;GgzyuqjTd+tM=i8wbo`TT!6X>)=&IFq8CBl7g`#+BI z34gzj{P2FI$x<=|Z`fIuF@iaEyPZ3H`5p7`;cw1oI^TRRrZ)o)a0~Rqf-aN{>kBRh&oFhW!sLtL(?08 zNi=G-xohpZ@U)QyX$mr5%oMiA2(GB?<`k|~?{eg6dS9Imvg>a)8L6XO!~%T;y5lug z8>n`eKKTEdpOYzm;47!YPprS#DR(DVPyZSdD}KGzntv%F!Nwlh^$7p@Og(PPPdm#p z!_K&qoR*u+%QGg^2*klVYJ^d9r@Q@-6>+ZdwMl}=M<$s3yJSqo(bO*&OuWC?s5dXc z^xFuFm_?T0&x9b6NHj{(N-zSs_$~sXva_@pCKXKe^OTo~arSJvxek-_{f#$5Ad8qs z{l(#M;MO~60oKx;FaYLKF^|jiUhXmC``!cdIT+4dhmvuTU-R=~b@_ySAg53=ozkhJ zNi$GJz?hgnGzD;0g9$JLd9T=Z<^-uM>+Wem^6GMXQA)!DBOg&UvNEo3tz=;gwJmg}xRd2A^YOS-z1k;Pd7rB+o zo<8U6T))Zrk=EP!hQhl$XCY{qAWfj+R)o!a?sRug`_99yKh59Cx07r0&xg-*c>@^! zS7QpyTyt)%R;l9>4n~lP$8g3OIE6J$DfO9*l5kNnrM4pT?9R6qULo@saP)kfq%*^0 zc!=!>^@a0;TVsvjnygivBYoPs8GBaPPjGXZ++n6&AcK@72I`b5fv74Q@?{KrR~>SCN-TgSYgii2slfaA1j1K6Clnp(hPyohNlt8 zgIvTp8n~ESm~VdtIPZ5n>bqDB;5aD@D^?D;|eaH0#F=P<6#YLwI_`kwKs7h zn1D}wM*h)(g$W|;*-F1gX&wxzyzCQ?h^QS9d8z}~`N?_~G>;-0vq6}_eO4+-8la72 zTjpzTjN3Mz`6oSlq5toYk{hh`*TDNz#|&^5&}bLp$P592uySouCsHFhv6wf+V#RpR zlXyXDS39g$@rsP_Z1I<<%T4aRhW)&K!qfjivMr-xs+MD^NN z*q;Kr46gkI*UEI$4XiJSd5-CCy;!TBR>K$NdX+WIBi9|R18}L7+oi-X0{}MEBNd1< z6+mSwDZ(5Ibx83p;&j^*L=_9;7=fyJBoo+4)-2MCfOd!|TIwpIf)S`poh4@Ou~HAW zzJV28!0YMX5`~A))3ay0zr{6Fhc^Ux@ro%aM~>nIe*7(Ch%1jINnO1zEow!h zam~PYyg%x)Tn+gYj7NNqzm{b=60GN3em+l|FeUYmbrSTm!wAkT4`z@dh{q}B@U)!d z8uL$WFq=mSKF045EGM2S zI9ymHg>=+`S>Mgc2x!x8clQp38v2IAX}cvt*LHRmry3zeQD0@0Id_<6Jx9R^X7(6Z zdxEn&uekFJ9%49nlfA9lbjz1e;c1C(7u#Zxu&VfW1Q_}YcHWR4l{R}YqJphJ>qCSLB;8BV79)l6McC|Seq(B=y$luvK4$Ig3 z!{V9l@A@edTU!@}k;|xeh7r62+i2`eNsN%-9tG^+75IeJ(CLIH91D!C$n>A_bgZ=3 zPw4L4!-r~k86eu%c4pj*iCV5`GT`jCU5hcWc2FU~2oN;*cZB(g*v3??;2vG>#*&z! zKXg+Hmm{ySJ{gd(cvge(*ShNmAr+ElU=;`$V!{|SbTEJngBDQ}WXX3>U2ge3HA2z~ zN(F7z#0<=83WgZllQ6=ljw|kj6}Z3gX8s<;0MkUc|N41MBU1~H5x78W+SqA+J>C1RK0Yb>ypqygGO zsfX5x1zuJC4DX7J+mpnEiG~RVP%C(3hEQF?kVp(&sLovoIj-l)Z(fh*p2g{IIK(@?&M>pE(%k&Z=6NIi1p5dk`aMpurCoK#ICtG;Ee+52 z&{No?Z<0JmXJh5;?bG@+?vXb?y^RpKB!BP73+r9@D_!X zOoM0=hYfE!j8J@@j%T~S6K^t-d?^z#H?qwUXBud1TBhxh^6&Is?EV9h1flSLI#;X2 zi;=cnttW`_u)17(|ABFbx!dn)5=r=W#N&(!h{P=Lj44E~{r2#Cqhf6sG|M zngm>Aw0HK}XPA48!g}byN%(*s2-8VhV?iI>2llE~1NO6#C&x^AomI>|`Uq)JWCa}g za%cghc`Eh~a{#6@FpWgDsK?>vTx1rapgIkZcE;nutOYr9DxCeQiW-#*JJ-OsTy*z^bk8`@c|i5P5b z-ePXRkY1bnhUvw1*G&5?dQj@z^BeaKlQ2rIE6ycgp{0o5K_fgzcGLCX={3pcf|b%j z1epREF_OHkH1J$OL&z9tzBlrBHlO`@q@4Wg{gl=Q;r3_mpq3#NLGU0DCW!gM)ZL8% zh1aE4M#2Vy^&Gmhk4vt&;smw{aFQe6v2IRlp8m#-^$}97_Wp(@;8(OSxTc{!s?hF$ zF(o}mC7vT`SGll1O|Un<&s&kQW^m0=X4taa`UTEwVJ^A0BrkyocXTRQO2ZCx(eFUy z6dv0hkq>i6lO#;<`YiUz^4r^zs2~8RBm*QSNVC?cCn{0`OcEn8fh*?4Op`Glrip{x z_K3hLd*pkbQ`+kvH0a<4Q75VAwGt4RIb?zquSLI#-!cFmTxcT^MG9}1aU>#gX8W1C zeJV79=D6iqH;?H${Sg>6`A&L< zZ-Q@Wgdv^f)QKD_g>4od#o_h!j|BpcO$5#ZbLvETCiEiYMCwdmKaW&KTp*kIF`~8S%+$1BaZvZOW+2zti1U`D+^s2&!7eP3y5^^dwL39F)XhF0VrWAelvY zc?^}XP50`G$uY&uVfP?WYm7lzaG)1BwVDN2>P(CyUckL|8>eHz72miTNWp*{un{Gx zCa93PeLtDO$m2Tgo+1orpYR;5V#XWKGM%nr1RqW_!}#T-Dqsp9!x*e7SrqRtKEyH^ z&qCoffLjI`UF_cm>aou-DVmtZ7ip+JkPxe{kv2{v7ld70U_er^_h|s| zBUPnusgQ*P-X?Y7jYzZQ&;Ir$av*6QJ>UPL18a2#`naPev{=(&`K6~RkDRyp(NPYD zM6J|xon|Jm&em6^c4*v5T+DI+F4rMVxha9Ag}w|BDgZNz3Wx_oaKz7Eg>nUse0FhU z6WVTB2H;Z8O9U5D5jIQ`gldb3E#aka;yBMCZCHndHEzr%A5I@uS}b~; z|8z|+s_i!=r1qroxLtiQ(dzh|h{{%l(Re8lw6Mc`F~yY)Eg*mjf%7$(qt7+{YKR7D z88}LK5=ZVKmyVQI6gK{o%lDj*>F4=6J3 z`Moim))*L}4T(M&079eQ!eia-8&t57`*GM=Rxo-NPDB71i6alSL#3?M>mi`mhF_ko z$kBg;I0Q>Ddp;}pa@)_1bLudt=H>Yq^glPgo5jc8&+A`IGltjsZ9})c?h#gE56^)D z0Z%{!GDITONi%S9o0Fo&JRg)(UN|^wBcG$Jvj?c!&bFH~c zAi)fSnE8f}s{9!S6UYFGINW4hf#Esf2o=sZ5>p_RQ_`Y@GVGZ7#j#nkzaFCeup_E8 z{uA&CBb|{1N9rv5_|?A8aOX3hC_u*yZ~G!(RJ+mE>34z;2MR(!hN$vPO^_I!oB~IF zlNg`T%xWVs!r%o8m@3OE9yO7nLQa#H3UVYBot!7cQS;kDHM27u+jBDWy*ef%q)#S) z9|IW28@w|gv1|6sQX}WLGBf1guhm(?x2$~DWtNcRHl;F!XB9$v@8EjPHp=vGuS@*j zdUe8NU@$Q;feq~8{Y)H6|9FqH1QLS;h>U5?nZL7A=0!MmFv5j>{RDG~th_iR?SIa% zV1&ubKHvY&w0`&@wZ#&z@slAg{c(p7Kk%q7K*}ospGZT2$G_uy%3U#G7VMY_6J+5J+fIpIw{clWT8Z=MHsy z6&MfuIG0sU`Uv%gGt5Nh9<$59x(77@%}LESo#S*U!R&Xu$GZvs>2HpD{c!6&@hTJf z?=&NSs2Q|L!ZR?=NGoA{dEn`F%?Ps)DEBOmf|1 zR#Vpa`J8sE5#Ge?GKDZs`Ufe${Qf~gCB1R{zY;UG-$(Gav!*eTU_4#G(}~yifb_a& z1R5*=&x9`y5^@sK2;nu>fDYt;D+0^~pJ@;qx_h+`IOk zY~Wf~`T6Ymbt%k}XNTU;^*Ho}>pb`q$q2`lVAsLl-lJ)0w0HA>i!7D&VoX1_?~?ko(|5mG*V9#- zzMj+v3dZC}D|pS?SMJ$^0j9dtiGpFJP+?m_qVf0rk<5#q097)91rmb^5K>$#v?mB}tKyRgIOK4FitQ zo&zAwD9YypUf~u^h<%WJ*f8H7ktikez}_?ym`fh`%S2%wmg4tEOA^lXakQ`Yzcu~6 z*VAeCw@jXxlqc~p*FB%JcP5`(Sm)DlDkO3VDKA{uX{O*0XPgjiCm|@vw?HN=4&OUZrdyw zCt=}f;*d;|SMSc>WM-m%jH)qMPijZBXs*j19ZeViYS%jK`JdBK@|b?7N2pLwNI9(@t1~Da`}XRqbNT$&W9i00Hn$#&KYIM}oPVVe`k0CAmo$v)3)>qQJ{^ zknbIIzWEv)lgdNK1GUC=Po|FW3XjA;fzus~(k@1_#`HLjaKcOszq4Qp z$!(^RaXGHa@lIpGmPY7PTc>dxV;yu(q(!aWKE}lj_b+~(p*&uZU*m7922+?vIy;~x zLpZW&3yLIu<4cqF!s|H&(JV^x@9A^CcKjjY^_Y^v#6237{Kte`g8-Zkz+5wmbe5b` z1{0CU0B*~b`Upx(rE6vYnLx&vs?_+>awla^h}l>3kzQRJuEhnbO(aVJMj#$D2w?|yx&}wR7O)(q;-F+|*rW}#2J#rr9P9d;r;FJY#W^n{O+%RP{d<4ToueL}0vW(V zWT+-nyi*DmqaDIzAe12}O0VbAxUpUK1T zO*y}O&i6c92mfl$$fz=dW{wZ4z>{DUPBoz2R~bJsyNq8)2)GZn43naMWy)49OaK5c zXGugsRCqp@J5%OS!tws(Wnfy3xr<~IL439`!jS6}=cU8MF&u+JW62DPNUJl+Jn~F} z{CFjQjlV6?TgAixX>`-kPMN^YQ|d6M(OV^m$RoHd0){ROzQUIhK~9G;!{nWIj7U4% zU|?UE2NH=5>_J;_NF2_aRVzS`tU@KBIG@&4H4@WESQ3ff(Kt+LV-tDOBtS0H3ZLw& zqi=a{I!*tEE>r)J?h!N?$-JiDIV{ioP6ZS2!T6Ge!;s$6e}dI(>z(Q@Jn4|>6U@#P zk2%Aq)r+n}F=e$cPbDv#W2>42wGx=FWdv}n?>n2T z0KM)~W(EOMD>#~)82||dvLuLnju~NN9E{sHh$N$CmKpN>^zQwQZ-{SMCWVEwLO}8$ zoiWMA#4bZfAc-ivmPj(AKvP^N>6p)XebPjLJdQd^z_SdIpH0pehfe09w3^F-0)9G% zu$)YRhb&_GxSD)(?R73IF->O3WY4F%k~zrn+WLDW#!u(8Sb}iM@R%#(=ZVoFT0Thm zFqa_uLV3Y1>v#ic+^)H8o&1vy>0wZG8B3_KcW~h3n(V3E>nYjhDX9e}T0yhOfG|xW zwSt;JB!z@5SvuvCU%7N+wCz3u@kwTej4sdlNQ9Ye`Vwj%#j+wwbtFG8Wy$YZ;+H@& zW27^hDG17MQ0s_I&Q^IZ%@Y4KkzRX!VUYR<%r6GU0NmLzeWpal3L?+1?y`f|<_};aL zSUQD0Qb?(@eDJpk*8D7&SshPWf)Qfr8#jAT^+nQ;VHQSLpdQjGaq-;*XIhB2ihyt} zsXb=ko5b|2tP$G4#g}g~P0bhAL{j5BS9*v`s#fYT>T$T`K`!U9J$gw{=lidV^Mv4$ zMKFN2p%MYwat2)>C^3L$LU@jbt?^o;Nh3%E(xNF7M85VMbUHp)$1Xq6&Kz_y*E`56 z0ZMg`AtKpL?FMXII3WzTHFC3(%qV`7z6;43--p@F&BOq?9{HRJ^x*SeN4Z*;@Ht{R zogQm1#Tr6R;oQ$y2j??^Kb3o?euoue;jo^>OPyV|M`l+$gtQMhft~YUyc)FvU^r%Y z*CmyK;$84Fstty{*pcN-?Y_wSIDhhFe>5HQ#nWN{;56Emy3-uhm^G(qY)9EXf?FQA zGt_K3LioB&$u3OOB4q~VD1jIyL`G232uP-3bG-iMT6C5rbkULtJ`>+T=Ndl#6t#-a z-v)&^l$J3N7K9=*NEqo^#eK6d1Jc&Eo;`dg5mhX>6YqBWoilvHK-Qn;uY`I~`3K*7 zAqd?yN}J;egRU-!P=qP!Z2rxeS#LO5uA8UT$oVHmITKS^VT70{Z@q)*qrSYncNX61 zBR!koAU*T_QKQrAo#Hv2@ibuP^-DUL)*LilbheTHCj=8 zu5iKY>2iehb(eIPDFxIB&J#}aXsh_i^3p1?r2SZxvd9!GP>6)*`_J%Klw@X@z0QQO z|NKC#ml~@wpXGbjpm*bn7`5SCjZN-o4Hnue+0`Z8r?KKUt3<5Bf|2Pd+CY^SA73Gw8ceF&iP?=jm8!FTA2w)24M9q45$i zxv!wm8?Zn^8cfS^M(zyt1Rn@lPD1#)Nt3Q}0!b>6A<|@dkus$B=0a2MOEAJXcU3yq zVX9)g%-7>?MVNP%( z7=T@v)1KCti{o!A&EBAY!-HwLqs-1bU!hvT2;dLLKw4PM1qBp>tiTuxOSr&99#sxN zrv3=+>n>>)DFxE}>1t?&iCLuQD6P;YXF#Nw3ZnrYmhc>RYin39!KcGJ(ga%Rv5+u*1PMPK z2$k5U8b%KI=%)dff?zo3weYhs3eOV5_M=fN=I|Wv!yLsNJ6_&th7Y&Ck-wQ3EnlYan66i@M>^;JL8H-f(>|19>`CFm z0`6zgWvA22WWZhrzki*4GOYW{Q#+l(RKskWXJCyr-rR^}6bzkVlNqM35lHdd`-Ef6 z3#TwDEZCeSdfzwFKX3y=7Y;TmfbCyk?yCNAs9sI)nSSzEBP5T}PI!zCa-E6~vG=-7 zb=qDeIG7@CT#J*&pl`qe*dPqRwWfk0@EpA?B3|feGMF-fW$lop|HNd<#A1ip?M|09 z8J6;HmN29ekS$)_<~42UN||o)x_L_?E8)rr^i{BIwh&H&pUcQgN)*~}RK6`Ic z{`7TTx}DAbVn-WZ3}ztTIM*t*ZT2_lx%$S%h(|goAM?*gE;F4IbK-*C-M*WbU<9Rq z+O}2(;NBi=!Uxgs{Z8+>op9webYLhnfPWx1lKTJ@#m6dzCby)c>LT;Xk{SL0pBjsfoxtz)Q zopXOa;N0y5BLtihJ2z!$V5$IPf>T(%7Jko|i^25bhf?R=58BM~2I7(N5&!J<51Mmd zkrDVT+SIce-^GZN=5JsoUF$J=jLK3c(2L_QA(QJ7_ z`?^dy+He7B;9OO;LOs^+cQ1l^NDn0m3=v4Aae5F)xLe#j{P2_sWIr*!WBxzEe!jOb zMu^TN9Y7mD2mnGTApCL(VqrBj4>UDr2}K5>taw+cxwX4>k7d7i;d}X;%a}c92AHl( zwfOjUs&{*CQ7M^s^mGty?;1kcZ7;-*m@xdO$7Sr#XTl7L_|xxPhdSEt&+}bTT;00* zP?Gd&09O8tqtG2XhBICJ8+c`Sgh2tr6boD18~2+>79d_9H5qYg|A3M6%LGhrD#XZ_ zeK_2yN5PghDk0j{w#HM`-PcjJ9O|$y3Ek^1r8uLc4IEadArXdZg*rh!Ze}5Zlo+8E zKwLs31oXVfP}<}TK>U5w^xlOZj91q;*Wb9GDA=#JV3lMJ&osi`H6H}wC^gxzo<5B)%d+7zr4+fyD&f$L zOG!=OdaSz6LCW}E!nlB$)1%`?-Pm5g zhXr>T8CC+8K@6Zeh=a0mJ;qcl!xZ8k6;^^S^4)!A`GLj%oWC}WM>fGSQ+O|Hgvt2@ z0_oNUFU3Y4DTvUmePc@_w>5$ZVz+yDJ%t%ccD-+ZndiXy@dNWqW#saw>rgKqYQ7D- z{x6En*5&m}UynJ2whM*^*3n90fOJmR!kHL_!WR9;Z|xi0Re#8894qCvSzKI#5p)la zf*Gg-?HS_<>|j%e5o~LPU<-rsa%_-!SV2Pix=W5AIgrLKpv0K$!VEjX3?fDINY9bx z5f~av5eJ;y0u}dStNnQqa((mYV3aLaPZ!_2^uzIRef!G&G>{T-j{(p^tN6NM0GS~Z zOi0Zoh~rJ$JKLupZoRws_V#~99ui-c{`u^^=_7aEYnVkpALTC2Ej|Zh1ru;%2kplJ z0$>Ku)W>H#Cznq=%M_cw-=(nZNnZQQkVGa7mznd?_Fso~-y#dY}!|451x%=jYmA@S9)V{#X1xJpV~uWR_H?hnn9A)Bg=WFE+NW-peVp zL1J=YOE3$g_k`1T#_xu}c&PbyZXGXud}nMH%`H9)1{fc4e`=$LOSA&Cj|`Lv>>mIV zAlp%P=whjKAnl29aePOWCP{4GvP9?rnQMk79YyCbY!E6L_at6=_;G#ne-a>;VP58) zuMM)xon<2q4Yu+~CQ_6AqMI@J!uwOqAVOmk>`r^G{TcK8*w#;ZI##N)_;@yv=qsGP zboJ7M)J-A?!uOn*fc<;9-sx=Jb#>#)8!SX^^6q&%$(aE%;Y~9|zL(!=K*%5Q^MX)= z=a`IhmCGQ0zVaNVk=NtjaRy`CD~qdt;CD}k%{|HQ+VXuiU59l2eak-*uFuWw&68_a zUU_H?=a?ZfBdGm=e^jho;2q!9BvN1;H$B(;T{Pd%5XW2FT3tEyy9zG6RyYXD&2Qo0$#$+(uh;%AlN^kp4TKHy6I#mWHyt`1fFSd3zu>w)?2~}=H+4DsDG{# zL*x~itxwvoK?c|j_nBIu2Xc}(LC=C-qu3J+iBe%}+*k^&1Cl@G_aEK*-;0g%qL;@? z@1Fk)#a}t`596Elt*fWjE?;;f8~f==QX_aQ6HByu>FV13uUvfjemco*ndb*q{x07r znXe_fM4Z<$f%l)>{=cKFmBnR-i_2gFZiEH^?+|_^uGIwOJbpgfAr|SSg}M398+H4O zoBxzgUX2-ip6kGh6hv5P-bmOG`07g+Ui`Yv?JWn|G?M~Wuf2DE?Zt<-c*l4BMuBnM z^yKzW#U}`=KLjo$ZZ$LlZ5JDxBm6w;2^@fHG=oi?-KJmS_Tfpa-_oQcCf*(btp{=9 zFV}>DUSp!XOyF^|37~?Zm|P<>xb=^dZwPQl^f;i_<4{B4PbLnaKAxiIz~_){aeHnD ziXL@9%?+^=Gb9O9>^7>^tL^#4PjByTed9+qe!Teb>W?40zTe*dq4-9v^8C(cmNs`b zmY6EZY`A8h@Pq~%OzjCFH9=y6TugrCIbVx5iEw}V+4aAV&HNR#!Tjgu=NG@oQ!PUJ z0%88Z;7-aJftNtMvr-5;bPyXcrcQkJv zEj}DKkk)gZUS|&Na0esXU3cs0_0tB1z96%I*WzEhp$_t%HmKIN&YU>=37R?v2cfTV z_(%=+Y1y|;spWuetcGl06Tx;1c#Iez8eO4(@Gm)^i`wr0b1h{1pC9?xrFb*qxng#h z-W!)sp>iBbYfgK|k+VJUMOu-R^K&MWJJaN8d1;pxN0gnK*J1gNG%JaL+prRnR^WRO zR_PN96N71dudUe`zqEUD`Q-1g5X;t+5b_^%o;t7|uXa;r__4DeEB?~TV==}+xF0)s zc3LulyT*SIqWE9#{GAyln9bED@|d>a)Ajkm3&qcE{;%=D(&Eae5ej=uz|FA4@~q~JD@+i{y!dAPAdO!Qjr<{n-f1-{P3y&b1&{nI5QKxbN++H ze}DQTAy96_OC*4M+F*Y14`|r2OV|dj;N;Mx9qKtk8@Pe{key%W=qT?(7t?0ZBZ+bl z4CXnVZka|fvX9N2Av#x%fTXxa(n_WN$24&VMLRIzyPvMZv9H-1g}ftHi2Mw%wiq?U z$PN5LJAjbrC=&sPHfY3zjK$(4A(2;yTiA^)B7;<;^se|n#A_7OH64&9lCsz#hGnfi z-~Rp0?Tv5y7%KU#bMHHLJ^erv;JfKmdN?*=2!}ytH!?qWwgSI|>1JANFMeuqerfD2 z8leqJju=sfKzoQr|9Yq)?XhqL)qMUHyO5Fb{iL2hY|uu@tEz-0(`roDNQLN>%rB>>^S zL+NSbYa1Fs;0!g7o7ttvQ#;Bss6J%l(9`Us7V6S5g(mfwXayNTHOsx|Tq-S5!N1;W zw4T?4^t0w^aEA8L) z*|n5iUq<6SzkAV1w*RWP$i2cJ3%WTNx?9Q!5}w64D@@6pB(>VW4d=pyC+s<5dk(J6 z5$}?R(m!lL^Yy?E9>RpE99JxGE<(q72w@hb$rwvKYxCVaT47?d2d4rRA?~|MU@Scza*dRLjJ{DDtORS%?{0l^t+CHjR?$0Aq9r zH@8C>2bvl$OR>vpdvW#~VWhU(XHVYwE0{=se5;uLR$*YuB>Lou<&!W%>g=oW5U{|Z z$Eean__B$#9p#e#!C-iaLA2EFYi0HpStoE2G&)Wuw>-ffEl{#&5?6T+a zfO?f-9+8Jb^mrU3m|FA`C_ocqdueg`GmGuz->{DVD4%2?etSu|8|%} zFz6rMaq6xots^jOE2ONy@G#>LxT*-UicSIOVF9hsW6*Sqc1~jlY6D^6n?uu0GeVjK z{kh^ou|~&K!s|hZnnZ3wo?`!<5=l*BB-ft(p|v^k13StFS*0O$Od7O;3@0;8rslcM zrRI?8Q9JQ+*owrtg;wbC{sMKfb0t#^dW<*+v4~_D0n=_z!`=_#X+_M8GNi-=Yj z0q1DDJ-_t1)uj_3vl-MlUri0DDXQs5$jcw$+4{F*IAPe-KM+O_>fap{y*+I}KNW!5 z!?Q7nmbJkn*ENfT_m*{*7hnS2lszmBO(T#!Hi?2j$J#*E#Va?Tz{kjWxaJp3#u+*& zoshu@vYx6r##;yU4Qinc@FMVyX4_X_iWTghHs;Zwx{X%oGshe?t6k@!T%1{Sir)|y zt|z-6MfHx8cl_(~<*4EEGSoEE z_780U(T5ksF_WYvb(ex3`c>iw(<0O=QkDg|TyfZix5~*z7)OAyiyjl8d$`N{ZQ61dZBWKCPA9`< z`hK**v&Fe_C;4Er$Z~Fq5vWY@A&y64K&`<7t5?Zz0Y>Q4N2t;vjcwmy0;O&h2`=%b z#k4H^CK61R<`5)iDCsYxN%`c7#IMp1kS27S4~ntZfNNJlF3R)85}l08m0g0eco}oe zWe7vPhK&W%S&N6|%3*>;AUa&i;;z$o|HApTmsHnpl^`87do74W$sFSmc${Pc>!Fzd zL3m&)RMB3eT^f_lagvhU$J8tOEQk)SjLCP%g+(RkU%@a43YO}{a|BZ0fC?TA*D6gr z*PlIg=SMGGer2@1v-K{S!PO%6k8|8a%U$PFLt6BNg(kopQWMAowC5hIvO zS`F0SMPFR77$u6Ual53zGD%Gk5>oE0@l9vc!}~3>UbOky2}Ny)>Zq zAKCZ^VYB-l^NoK$F##4IgCyV;Ls z4yk}vY{Wy;Enx)RQ*An=x=xX#sNEif*1&FW=-G+*50H&EsNk7Nn?f8~qa!>3B#1qR z*D&53@cz1reAD6b~k= zEJ`#8f&g<82W$Wo{Dp!X4lb3L7q6`CGRE*;iR2Tz|0==;94ok0Dcqy<2OQ`!;l29! z=@V!E4Rulj1aVL=I>^Itg~|lX#0r~Pzd8iXU|~1}9At^5EMx@C2sMN#M0*1%e}P-r zI0+|@!{b+!Cr_OH|LTp#mCc>4chWC;(7uVI;2&K2>xGfFw<7)a?$3t?$Wt$I0Q}oC zC+_@}c^echW*swZ+bIM^tt(+^)RbDE7v4)GvQT#d*7X902S(37eB$}hq=HRw@h?KdxWg8Qz{l%A_`=1$Q zy;r2Zbvy_5C{-}>P?H2t&Obf9diIx@tVhz?z~ zITm)hoqIPnuYAi+XXkC!-x+GoxH6vRMttbbyb?a+?K1t>Q)2ylm8o=xOY*vQD$;vz|>2L=WhxRv;)5U0Znh^7-#! z;`V=S1&*7Tc>Zg5pS|ZF(|Ca-3WpGkJJBqtV>kA@T?nDY0d6pPaF!Hjpy#K`$3V*C z!2C?{p~@o#q3kfjda+!?t5kz=T;HX^NHnuK=2@k!-y&Yc^@(Do1{e-zE*9W+V>K3N zte9+1J)DI8(B{tiJ6N9N;S7&V@c=u($PljLcF@|MFZBPgaD9KJp#Fg0WfHk^yq8+K64I0yKwODC-ftfPj^fYxSY zaY)pp>o5)G8!&}%3NJ5nu8z;e{9w>KeR=)jw`vyVdU|#h3J#Q{%XRo;s0^mqo&8(`ApFMf@NsN^k9pyQQQVP}?I2!62#3ZPTq&*3-Qfv$# zE*>6c#F+2nWc@JA@GHd^2*6usAMS0cgm`QugFb52bNw_o%hnsf@hf9(q zSiH|Q$7rt8?cTAqv;Hs|;w{9u9@};xg!&>H;4_O0E6>igTCY%+{VCwf17L|D662?V zGTn#v34}c{fguL%!8T?>3r*;tlH(|70^BZr`aMf*Sh8K4pJE0zLkotW109SnOi2?8 zYg&UTx1aF4p8<^j$aZJ<8+yIYgVga@iA_B=Tg~~;quGCti9}x#J~9}?S(OQ5z%RkA zkV}lNI~WbMj|qhHR0urX;%gjd%B=m*1^v7_6Il6M(nqipdIh`NPS^zsZx&bWth%Wf zLKZ(H2fchco^F~)Gopxa)BP6V&Wsd}#%qJd!m+w8V_kHl63Nx7b&KK$rH_IAYCi*_ zPe?;GIudLLJUYvUSTh3+WK@`%x61(98_LhnX?lhX{v`$RZlrVk)qcFYSfl@-d92}Z z0UfMMb(`%_>E?%EqJskw!O&pSFpeq%H5KPP#|Sys)(Il4AdxFAh?mgjGcTPfsvmci zhfZ(jZo;qcB%osjQ*aqGRPd<@HH7<_8oEYAYKH-%=NDQFFEJUN(LPsWNP%Q9Jn(7W z$8Ip4G|o|@ETyCGj3A5#;~$y`yWk)(0pHO{-ld=BNV*;4d0fZ^-ZK@+CU(y%6Ph;} zeWyo9TcGuLXUMq@vWMJ{HDbYg1>4Hi<6?yf;e_c%E$X?mx_s*L>hkD!z)6ECrVkRU z^Z+o<1M3-zQg+$U0Vj*XZ`7-e^;Wa_@?2x#Jb1cDUeTVsNxs5q;9Ph$gex-z&te%G z-@zSR@1e0Ucb$zk8Z5#DgNPhC37q?x;4v~jXGM;fZb~DhGAfntFFsT~5z_T+^;B`8 zhFQci;T3G|5>sP@bWIE1g6NPs*srMJ5*Jg+xrXMD3DP?IAUe}4*&DhYQKss2RG<@S zQfvtg1i~ajM}-q1pz6^C;HFp&dr@tW%%b;U7M+{UxHw1V(brotN@3AH~$Oc|E; zSL1#p;pBVZP4Q+t4m|xJ(>hSxqBoEJUkK%^do?kLLgp$wkJBM zX(J7g2{BHHg$zNUo*&HaxmEz>cofA)>t!4*QKz`*h z@_xK{qJS9~2T?1mfw4365I2cLYg6CQ3~B-!5t!68I^&~0YAA^hspj~Dwsr+uyA16{ zU4sdDKUNl_C|-$yE14jYu*nGg;K*9f#i?ZYQG|!{4yK+q@Ni7{6^MSswc#M8V+3e{ z9BejZM0LUh5(k||9xtK!WCGKYqwBa(@1r+zl__MbPXxS}Nilx||4|4Y1Q#B^7=1&k zs1YPs2SS7R;j&-|R=LirT5DOT_}%xw?Xp1GI0>hX3QXiVq8)Qv7X1Wk>Dj!2OY<&V z*m}LdYXkTO0V{1z+fU3sH9=+qy_VTk`WP8m_;HxPs@^msSm-(aVRMhNTT*)zqz~~{ zU`#h9c9d{p2E#8Hy$ynrm>{5#n%Lh+CpVd^BQ=F3&1V3?5vqZN2xbs@cno4l9os!7 zVu0iU9l;@^isc0Y5?f3YRvNxUQ(vKe5c<9(l4J%OX_gs~nB2YqLnQMd6A2@i)Vaba zZNyIDuB$jmsEU?IVhMCU3#Q+9r!9#TA#OsEHOqQsJl7iWJpexvXLknWU zVE*U{l6abZdXAKxVr!hA>u4%k5KUkl)x=iLE@K7NGsQDewoFfllIwN;ouOUir8;fW zzy{lFnW6PUH@VNXV zoo<>Daw$)6@rbLEq}Xp7WD{Gv4RLNOarl?ksE0_<;k!XpA`WXn9;D@FM+v?kyKDYzopM?tS&e@n|o4$MH9U>(BP!5*!HFr{W6mn*o1 z5m5874J*VEj35vom8?@}HEI$>xbsPi<@|<>q7B$dBN2mcLYW{%mQEyM_8vSI2s#)! z)Ai4NhL?&>4B>V9JNHnR)NeQp2EeW(HE~m=-ESZuD9LT1Sfe>KLFvdfDj{h)B@e`d zq-wvR!gvFW&*szik)U^AV|P;EWXL7pjm_A2kl++v8C{0Ya8le}(yT;-Mq5JQ zgx>5$B`eI(^bO!7kSmDaWmuYMw-KYoPQLF&NVOg?JO2ZO+<3rj&pTv6=Ms3wHi>d2 zZ(1W{$x21AxRX{u+KhwS?xCTauA`>d)g}%@bBV?Vv0$&M1^|Ig5NKZ_^$++UlB3i} zLq@FWw}rr{BaypEl)15Y$jylRVGgMYvRN>(8ST3~ksUQT+kNL;e_ot6ld{Bwj?N&W zx@rf;O6mmcZDLw9Y1kS8dJf>!F-@8feIE+0a1QSn&uYMCkemA~*Nj^Vnk4KYGy>&f zmbkD$>U;3M>H%hOaREo=OM(WQz&DEdx2$N&^AUuxIVKD>fuStoHuVP%V}cB$707Tx zI@s0ERGv-aDa9pB!mI_W#T*R5=qF08TXc~6^;r3X@C@Lq>6?aG)Zzvvx>uSCumr~X z|6ktu?z9aZLhQEp}gb1@eE9prfn2Twez!k@Qv%Fg{JGIS%Rc? z68Bu6bNxS6ABZxfi5qJKa4zvg*iAJJEw57+M+)nSc#vuy8RA*_bUHq1>C3s^lh2X~ zh)z= zbHMx4y5a>@orDiwHk(|f`Mlg0pdVD%0%UO`zGu>J5(AuEgJEw~bP?xJc|A(#Y98s; zznyCC#S2~y+o~qu2h_p#yzU#U#NIwuHcNq5(w71r(@`w})q>LU8sk~QxagIwYj}@- zNdPN`>a)Ww6J{CDCRXBi4U-9h42O(+FCn;@;Yl54Ilqfc7n)C7sLA+2_j9bjIGcUg z=fDzg#=hBz4;k2JfB@KQfT2FCSwNqlWvFc;aGouad{H7^^OKrOUqf@rIHIuCnbY_0 zw1nYF>y=o|d45_%PL04k9D&JGQ9$HC7tgYr`Z$Ak*5ocp8()#jtZM5xmLI%rLv_z-v-O!Sh5DgY#YS)>vCO z)nt+rOA~Qgm-VC-yIB;J6E!;+!KzwMKLCdaS~zJc|LWmn)70-I_PhiH^5+@w?AUlc zqp`Xf^j4hQw=GO21Tv}(OB}}KnAi5q)b_T=nb9s?8<{H@(9^t874Y~(LHxVfon}Y7 z9{CF)vH-aDEu`SS7>2Oa;^rPEslJIUQ5X;gaYLA^^@A;PK3eF^_;PNsmn9JpB74MI z?A-4+I`50sIC&<9zNHvL4MDui%;nX>$#r=xQ*ma*4dEoMkChEmh5V&l^N7&CILU7; zOezF2strqAHf|Ax$wV3fL+7*M|9E_-;vqQC6M6F#jiEU4gLd_b>E@AtHJ%zvTi}b6 z>)EviCGn(ffjdhJ9n#O%LMP4Mkn@6flN6*+jTJ*0XG;{GrKX0T31_Y`cEcGR8s9zQ zY>}U9k`Z;B3MbF3!{kDU8AK8hpO~s+F><_`^LZ6ff6mD_7 z=e{waM}c##$-ue2KIdRIA^3bqtTj&ZD`hrM{R!gi1UM&*;Uqm`9mC1B#(GGcI~CHFf;oGEALs>vR46Ep)Ce#A)5xjvEp4Tx07wm;mUmPX*B8g%%xo{TU6vwc>AklFq%OTkl_mFQv@x1^BM1TV}0C2duqR=S6Xn?LjUp6xrb&~O43j*Nv zEr418u3H3zGns$s|L;SQD-ufpfWpxLJ03rmi*g~#S@{x?OrJ!Vo{}kJ7$ajbnjp%m zGEV!%=70KpVow?KvV}a4moSaFCQKV= zXBIPnpP$8-NG!rR+)R#`$7JVZi#Wn10DSspSrkx`)s~4C+0n+?(b2-z5-tDd^^cpM zz5W?wz5V3zGUCskL5!X++LzcbT23thtSPiMTfS&1I{|204}j|3FPi>70OSh+Xzlyz zdl<5LNtZ}OE>>3g`T3RtKG#xK(9i3CI(+v0d-&=+OWAp!Ysd8Ar*foO5~i%E+?=c& zshF87;&Ay)i~kOm zCIB-Z!^JGdti+UJsxgN!t(Y#%b<8kk67vyD#cE*9urAm@Y#cTXn~yERR$}Y1E!Yd# zo7hq8Ya9;8z!~A3Z~?e@Tn26#t`xT$*Ni)h>&K1Yrto;Y8r}@=h7ZGY@Dh9xekcA2 z{tSKqKZ<`tAQQ9+wgf*y0zpVvOQ<9qCY&Y=5XJ~ILHOG0j2XwBQ%7jM`P2tv~{#P+6CGu9Y;5!2hua>CG_v;z4S?CC1rc%807-x z8s$^ULkxsr$OvR)G0GUn7`GVjR5Vq*RQM{JRGL%DRgX~5SKp(4L49HleU9rK?wsN|$L8GCfHh1tA~lw29MI^|n9|hJ z^w$(=?$kW5IibbS^3=-Es?a*EHLgw5cGnhYS7@Kne#%s4dNH$@Rm?8tq>hG8fR0pW zzfP~tjINRHeBHIW&AJctNO~;2RJ{tlPQ6KeZT(RF<@$~KcMXUJEQ54|9R}S7(}qTd zv4$HA+YFx=sTu_uEj4O1x^GN1_Ap*-Tx)#81ZToB$u!w*a?KPrbudjgtugI0gUuYx z1ZKO<`pvQC&gMe%TJu2*iiMX&o<*a@uqDGX#B!}=o8@yWeX9hktybMuAFUm%v#jf^ z@7XBX1lg>$>9G0T*3_13TVs2}j%w#;x5}>F?uEUXJ>Pzh{cQ)DL#V?BhfaqNj!uqZ z$0o;dCw-@6r(I5iEIKQkRm!^LjCJ;QUgdn!`K^nii^S!a%Wtk0u9>cfU7yS~n#-SC zH+RHM*Nx-0-)+d9>7MMq&wa>4$AjZh>+#4_&y(j_?>XjW;+5fb#Ot}YwYS*2#e16V z!d}5X>x20C`xN{1`YQR(_pSDQ=%?$K=GW*q>F?mb%>QfvHXt})YrtTjW*|4PA#gIt zDQHDdS1=_wD!4lMQHW`XIHV&K4h;(37J7f4!93x-wlEMD7`83!LAX));_x3Ma1r4V zH4%>^Z6cRPc1O{olA;bry^i*dE{nc5-*~=serJq)Okzw!%yg_zYWi`#ol25V;v^kU#wN!mA5MPH z3FFjqrcwe^cBM>m+1wr6XFN|{1#g`1#xLiOrMjh-r#?w@OWT$Wgg6&&5F%x&L(6hXP*!%2{VOVIa)adIsGCtQITk9vCHD^izmgw;`&@D zcVTY3gpU49^+=7S>!rha?s+wNZ}MaEj~6Hw2n%|am@e70WNfM5(r=exmT{MLF4tMU zX8G_6uNC`OLMu~NcCOM}Rk&(&wg2ivYe;J{*Zj2BdTsgISLt?eJQu}$~QLORDCnMIdyYynPb_W zEx0YhEw{FMY&}%2SiZD;WLxOA)(U1tamB0cN!u@1+E?z~LE0hRF;o>&)xJ}I=a!xC ztJAA*)_B)6@6y<{Y1i~_-tK`to_m`1YVIxB`);3L-|hYW`&(-bYby`n4&)tpTo+T< z{VnU;hI;k-lKKw^g$IWYMIP#EaB65ctZ}%k5pI+=jvq-pa_u{x@7kLzn)Wv{noEv? zqtc^Kzfb=D*0JDYoyS?nn|?6(VOI;SrMMMpUD7()mfkkh9^c-7BIrbChiga6kCs0k zJgIZC=9KcOveTr~g{NoFEIl)IR&;jaT-v#j&ZN$J=i|=b=!)p-y%2oi(nY_E=exbS z&s=i5bn>#xz3Ke>~2=f&N;yEFGz-^boBexUH6@}b7V+Mi8+ZXR+R zIyLMw-18{v(Y+Dw$g^K^e|bMz_?Y^*a!h-y;fd{&ljDBl*PbqTI{HlXY-Xb9SH)j< zJvV;-!*8Cy^-RW1j=m7TnEk!snup96b+UQzl&~ zWdXS7E8b6(Cl);W$~A>Y$|K{VNBQPU@>nVL`JzJKX`}e60Xo4=P@8~0Q68%OL9w@7$&o-VsShgnNpD5?5 zI~v6K8tSnH;NK4DuX>=H0AHAJ>-i#gCa?mUUyC+F5WPY6+~McFIm$(C#ni$}XU;mws!HO9HRqzh5>dfF6v&J(<*hne1!h zbXOXHua@rUYPnkUTf=RTUF>xlz>V_4$cA785d16Uj{tsUl%PKhr+kCZ9kS*hc| ze$@h(xHQ-7CY^21Gi< z#wz`?nl$qEWi{QhUjglv_GpRA%nkv1iR-ZJj+U`UWqG(-ZjAP-dv!Q0+rtFCUrr6> z^d{g>)_(qck-M$PJqJ30SVWmxgGCQ+)9*q9+@^RAfP;HW*={R_+hwcWD*Ie(T!-ya zR>pR}9U%7GOMu!hD>Q&U&r9jn`%!Cvy#i0Y66T;Bl+GC3ZfTABxV`U}1HkPL1%6Zx zhc<#ySsISY0U$49?+piK1%TIv)R}8*m>gcpxuM*BJ7C{(cr_1bf_Q$?UrMGBsYx)! zil(U;h0pE(Dw^L}o+1so_o3E<ev7bH)NRACM*vDchnjZr(Kq9{kUJgzPVZ3RmAWi9-Yz~^xxxp=oA2aUUzX z6X1-UT$Z3Fr7@?i%Nh~4RQ0eyfC;Q+jkZDZ&F^a#-%HiU*~adqMGm)p>wDk%p53-`jMeeP+4 zT%$6;?oi0#pi>3|8tkBpO+)PW$};YLb%$8*4K9@%!*<;XFpZ} zM<~phBS0?(c&Y>$UtqJJd~+ z@AjbdW@%T=HaJpIHE5{>Z4vi?Fr{o(lJ>?TQ$?hD@UvNN&||ho84j+jaR+d>$`j%b zI`y~|&4*y5SRQp(0THnX*f0xVLzM2Iw7ZCF5NwkH$~bNat4ODjkO>#IPOeIuEXF;z z0g?=cW&+p(Jy2u=Ft}m^E}#wpy9+0@`xF)=TU4}#gz9P6Zin*MBJY=_vRY8r%3h`2 z*{bAijT~}bh|*7Jnw6OWT5dK3fl2UuLH1+EP(}{EI0m>=UTB}J{p7Irlh+W92N0`W z)&XGvryR7`0A`myMap+bcb9ZSDcU7X8^D?t+~gBbs9}=%`HkyIVl<7LbNRi zzE7Vhw;ejXq4g~x8f`TDaL{rKWuq!VJ&3RjT?gX8Zy26p5XU39aE7=LsP>~25*b#d z9(e>uLYxkq-=z`3sU5Vi(GrBR5VS4SRxS#sW+U)&vz%TV$QWeUL*Q+oQ$zSPGi6E7 zTia8hr|FUl0NZ%T(=0%o>W(iwY~OOTvpN7h)VA!F7uv}@ZD_YbIz5!P_GlY!#-DNb zDaP9elvPG_R`5KH>im&nPJp(>ShEXUF(+)K%WXB@E+EH5#1`7^)y^q~GK^6>WD7_2 z=?9m(Ylu`8p-_P2w2_)E*ATFV5VT7=ZCa&-pjRBX{NP~wuPz0g7F=cna1I0;0d`BG5!MDH0WHUbtMLlML&{R&o&mZR zBm>Ra1my9=)P^G$&LqHNYErdqTyS$+1xv8u=9Y?#qyXUI0s6!NG_n!fiIbijZ5If4 z5y2stUEDImFXs+UmOfheL(CgoYP}fq`SV#T@}}kjiRQ!vqM-G=4Ujj>T4x_(b*l0+ zL=^VBdu0WJ9dzMR`b7IiMdYYn(pW`^{)e)u{0u1Uh^q?$MiQYChq%@hA}HSaP<~1u zOB+g4r^Z*3F!n@Bw8^9PzqWcn9w{Q05Bi7qy>RvU?`yT}lNHgG<|F~IBwUlDL33a4 z@Tg^}xT0<6;AV_O~MFS9g2rwGa z07`$kyY%_9r|$nWZW1taU?&QC$Z(&b*)l@w0A+5aj;&9%8Ql!kp+24&&)G9T`^;g} z#{v0DxkmF}uACeoF9GUKcZ;D6y#(M6mgsX;dJvP9&?rA6!0ylzReUO;0Ysv=suEwc;0j!QmM#-TdFbrn1qk)nTw|R8 zO(KZx^9;NnuS2K8^dfVv$dENeWPq&bQ}IC@(+`f8$aI-jw#-b=QXgCFU|%>)4mTWw z!wL*6hz-{(c|ff8ivq4Ff|o{g_AUA?XN!gvbi9)-D#FGY2Pdf-tpZKCmwNsF$pra_ zw|)}jqu)1;X??9>nx;GbOg>Gz(@y_a&VHu%yX7-`ANjsZFI;@;+?m(>3Je9;qh!GO z&=&4LU^1mUI6yyIryFosdw>Lnvuh!vE4FQfsX&Kk^vw>VR?zOcTuUfgXIUgbk}!N} zL)dngVGh791M*;nDMglD+N{G3R}kqg!6-(tNA!(V69#ODH$wookF0&7*h;}B6^ZI_ zV+7ctw2aF)mX{S|!nel?R2>uBhy;6S|6uQ5GyKCV-&y{xlRu5iCImUEnRk!9kF_kG z#`dIX-lse52=Q|KK6&u#0$uhF4!(!Mx9bwiw#R ziru2}RG@uu0ZJ>jU*x(t=4KN(D9eoHMu=*f4@AWe4PXG+ot1v+yCSfPxaLBNpb&9i zFTo}$fd`B#zAGoHSdo=l7XOvs zr@$B;J*I*@53u)5llSwWHScvF2Y9W{IKgI|W*#ryO}9?PTdPPtgz2b9We=5@&KtB5 zW^{hc6t)?@j##N%8c${&&36K{k778rU+0wNW-?%!aagr$$EEZXfanmWO~!TEhr#fO z+4j+zg#igy2qu8@44?&D&Kttna&Eh64 zqYp{9N}2}H`-C-SUQNz6xlC1e(~L_~z0%zTIsLQ~xQOn`P+b-FxNSBYF5+DD7qA`uqxJBn?%7LW(@#cqRWt z?Ohn^2GflIxmBg3+)S!tiRRqJYF!Vwihi~>X^2NNsz6JgALVkI(>ZKbSLjrGOpXi~ z9xV~3#gK_5m8xiUXkDY#y@TzC66Bva{Wr_^ZM^Sj>Mz+xfRHN{C`EAGfAH%0^3fYV z|MirzbN`vwJj0-E47AS|0X^;+czSaqFdE2PO%teeXPD-_?gU+uS`N!A*y*3~@VWy- zNgQ=lku44?w&+ACq5~ApyPfJ1}+9NSvU*^ZGFX5#1ptU)40SOcnc*g z>Q>kvu*g)PFGSOu>;`d>-}PUnCS5ghNQB667?We^HWMPQK;8?J;0chIAPQ;%)&w}+ z+7z0x6_(sQ2Xum*l~16h zmrIZxRu1^-GL7tlQ5zsem7~W*SeVk0+}si3W&u~8NStfLymDuyLlFmawj>(_Mk0hO8d;04wz}F z%a*j9k=u1p2waJ>WNkHYxI2kk^SFy2!4r@KdLG~eH*LcTbb^huHpKDncW*18%;Qxk z1KjvUv#21W&Wv3(I6qSW(&y#2El~n(UK0owXKc%?^;9XVd)#DcI55@>oEB92+7dJh z?nRq2XL51-kNdR_==PQvYPqn6DqoiyNgMI)_^r-x$<3KI&O0>;sudQ%yw^@((=B1r zFWufBHG;`ve1(+qVh8jz%Gx}%^*`6WzeZM+zS8CmOK&C1CeW5(28Nj;0f3^Lg6Bez zYtuvhY_!>pg$;H~< zC)m34O3w8@sukhVAMXW*venQDbbzeL4sQ1TJJ;V)!+d(@@tG8C2Ii!F)FkPmxy*(# zMl)94H|>D|Q=!hHEoHV z{x}yJi8eLH43PDcvjed20POEv|K4#x8-fia`tY|^g_-VW>Wx$$orrd1W0fx^M-oe)cc+o))duS%yY5sDm;WJ*^ z`gx_;mXx{;f16|_vuLnUDm+n@tF92DfrY zz$I#c9nYg$g6DnOx}|R33wXM<@2yz?w8DF5CYLC9w7toLS>~8{PaReyIkU;p^`%0$ zwkAz$6t=y(NWwrc36LO5&}n8ynu%Cr=T8&lDR9BL#?lqan%o!Zguf|7Lo&ZK0dn|6 zdegL`TygK9&PEtu3wVg}OlRIUE$f+AldE+vfMq_3JG{T^6sN>EF2}5dAnTqOJ>0Nf zlSnc{HaU6>bo9yoO8y{saI>x6`{PWME1v6)du<^}yH!5N%GJMO1xpkDVONj(lPTrX ze9}x+zbH+>?r+@NkV3;Zz8uCbN@NqP41oNYH6k4y)}0QG*w9Y9a9<$Yh@B- z?Ly<2-V)w1TgiJ8#& zbP9GCx+*3nA6bkA0FAMZNRAX_fk&)feH5VI z&C{gOB6}usZk}XpD}z<_W(+cKdowFNCR~lgm}bQ6*h~W6+&$2i?^t8jUh|cZO0`^q zJtmrAoKufYpUKT3qWu-56Wd^(-0(3G&ChDnQ{}7)nhRd@IN4hvs@M^X@K+Yfp!+f1df{d z!e_xJA@$&mLF1c56~vUw>GUj|#f(eO5Y-9xu^HEJQK*QKqCfi0Y$Tb7x!sYe^3+08 zvdD&_;keDAX69wos8uA>q*u}^?Mel+B#@V{+nTqpFzKN!$YDIuNM82!*|FEex_geE zBr)%>;1)Cs>%CVPh~!ITYTZ-MAXdGf<=9!Ug)g3GYO{9K&V~>!e~n`*`OFyM6HAnP zm%pgj?V1Yq?FK$RoK-a`1)HVwe$jG1OFSr(6GT-*{*F$Jc*u zJQJtSD`(!l*;K?Vr_~m4flsid+n5|!is)+LBoxj8QpHmgDrXaR*4%PEdN%mo+*wdf z7P#q-g4;5Ipiz?=A!}T3{1MhBpmFb$n{#!<37`$FX@ac#Z09xQZ#?k7lq>x&S8_H( zr#tOR*P4nY(ARoIU80mWttg%PMa0X}YDZY@6YP|K{n8u9@ug9MYpkT%9CHwnbjRIA z8;%|dHcf-K(QABe8s^Qo7p=0t3>oKxxWG)5+IvL30vs+PP@7xTl!5LlZWF#!I={HW+s4$ z#1f48IO(71G@s|Q@S8S<#rIQsW;`pB?&R&JEj_YkX(x@+mUguSfMGcA)8sSn(|_Jx6!tj3MRAYI zBmDDe0-Uz~>DKmsYH0Fx%q}<6SkP!kEF+J2v&IDi-_%&2fa~4@Uz#)p=vVz;24#%Y ztFf?6Gh6WHlcqa*N2_W0MPuRsycwtIHlB?`V+o?6M0&a--AH44KmWW&C-+FFS@K9b zQpr+kPtyvXZpI024*!_1kJT>YO-&QzdD?}#W@tv$6iR&}w)iT(Dmn>R>4YE0AVoEHhdbq&!#}8C8aCn! zigB`mM7lnUCpa1*Bd5&IR5W2{8j*Ihu|$ZBo8`@W!)FTFMA9ehcv`a>|6J@pHMzBR zgn&cqZd@lN>*Y2tck6m`u^T!)PBV|_bg$`!tQhW>fumCiBlTmAN<_dALAW2^h83I_ zkS2*Dh<+2Y;3WKLd5I%XH&3>{aO0`+_h0<)IR(x4?o4S^&bl(eA)YW5B;i?Z?*1UwZ#rt8Ot>L!T zPCQA9fE@d|2~|aSif#|*^NmWCv0*)Q{(3#kU_5CuDcs8dbS>Xae(GWm<*j9~c9`0a zjNLx*S(3g6sD9I#vG5zG;aIJ8->GxeQ?O@DU8x$C_bva_IMtb_<8%}3$n_sw{oCbJ zH~#5tz^}mF*80}xPM$dZRJ7*+SgwXp$gnQ9Te0JiKHrn(+%ZJ=nZ}_t=c(WMTJo;| z(6tHEY^$!2{U4<3-+elD?Tu(_LGn z?_Jl40H07I|BYOYT576q2@j1TAJ5nkcg72j9+c}h;*%xcv-yMLhf(h-z@})AAN~f~ z8Qv(rvGcJS{)KB-#_?Ve%l&d*4u_8zN_dE5xwx^u`Ki+<&VGt}4i6e2Ykc{!@5}Mf zZp5c2R(NOH1MQgg$h=6csallipVrgX$i!Hq|g-~#P2N>hrE7KI;2(Az6jFGZ_y!w&~{leD~@G1qrE zaC+Ng@k;r@6Mw0ZNyIm9a`mEgY#9FrSJOlZvJA$~5=~dD63AHWh&mWg=@d=2t}EBv z9d>eZG44tVvJwV$fwbLhErUB9vQ~D7hvfs$y`}W~{Wp@@`1nl^5Q;AhKq>lZkE9;d z!{t0xYW@_#c{E7)r5clLCfjt^w6iwWY;r*wYhB3_WC}R)*JlY;xb&GdwEBt2{_)d) zwQO?0afD3{GJLqFAe(BK^qcyGfAhZS&Un-EEPA@gZyNJGk*Q|*rfpdapO8gq@@@*V zDQCPWf0o!McW*owRI}7wdWL2Sojfs7+tVlpoJ8TI$q0b^9HJiznRDKe8B{~;bSl&rBkiM)9v696K+lw6 z<|YfQy~sTi_}H5ym;r*!0w7TXq9mfvpMUYPR(a3XkCyMIU(WFQg*%8IarK=wrWH_x zf8-K=`ea_owbT14m>DiPJ<^PjQ_#IPPBuVeC5_T;n511kjnTuPJ^r*Tu+@q zTnoHk<%@%B?5B<8+jH~g9s_Oia&wAq-N}JbaYM{*X4hwG3>75NF9;K^roTQM963JH z=?4J$FPwZIJ^`(y6tJ*s(8*6eO9-=6nQt?fXmFFLjdB?(fX)UKIcIF|@(RC9-v$$# z`t)gnn!rx;%ZBhYr}1l+mzJKV`~*~7#|3psD1g@KCWPe*^>#C%I&houcL+BkNUo@XP8LDfJ%27&kdQ9H++9!>(TNT0a*aEN%>?RP(^Rb1l_Jq zrO8GSc^NZJC1 zpCHF^RKd+%v~CX>s?)(tnD@Ew)uqdfdsiGy_30Ci8)7vJt6R|9oW}Db*rW1v@As=6 zoSq>_hl zKrc#Y)^DDpyXArI8_N4m{YL~-N%L~uS`nXa@8gUTfeLVid=U^IA>O`pEOzSGBHiSqmhGaE5KLLK+WjOB)e}+BX@7emX z@{#R-gznlduRZ%f1U%;V;Bdc=(OvS?eDCIaNTrltz3~xmTW3$5J2<&{a+mUXma?Cb z<@K2suhC?g>g!Pwz-x)OD%Svd>EV@cGCG$v$P4GhNDckN7?Nu&P2GqPQq}E5Caf~1 z20jixVcIAXgB<^oBM(eL9Nv_HG?1Lga-{vu&VOiiqpf4cpP<;vB|tNs4r z0Kh#eLa_Zx9Vpa~!pO-G!?#EU-(6FDpR5wbawlDyb`xM1H@-kPCpo*d(8MxLN)Sd0 zr`yjNHaYqcz8L=@4s~u)eH`sxStc!4TY+Xa0bKZ7p)^y#tpwx23UO3OXtM!Cc=_4( zZR+#JI8pU*&ENgp)&HS9e&fT19UN{!s-c@d^BnB6A4IeNH&6aM<6!1JDnG*gI*0%N z!nMCwuHCq{!MA<-_np4~OXMop^+o33y82xVX9Q(8+u`_&0o>IZq`esI%l&6-zTKte zSyg&m8aqHK%s85Y1>~Fcn>Es3pV6X;3%^HV8;Q5o%^Cqz6QDTQ_2qSJfw`55bRuj5 z*#zDA7R+2`{iEs#C4*o>P^T!2ScdU=a(lQVtiSU{ZuYc;PXe<2s~|h4lxA;#w_IZa zW_K^na9L;BQV#xeTkqwYLAgMZp|yu__Yc>zML$7*`?;MbP7e7x@QKY+m)QKk=4$C? zLF!T1<2NE}kpqER#wNI?*}R{Y%_m876O@`+LuSh88{z~6OTJN;6AZ68&-K_Gb@d+` zK5b1Q$K}D#LYsjlM+jE2lwpszEwqJAz~@6I`1Ag89~H?m$i2bGmOvxGhDqP7c-n>= zQ@VzaI1^`CS@z?9!#ca>Jb9nbZfjCRzh~=5h@TBQY94vp4NT3qu6=tw?eG&j|E&Dl z&f}*^r?a(wqHJxR^h>UwUC&N6p)vjPkOJvrO7q|*-L$7h3@8Qv(m%cp7FYyRLLr_> zFPXJd9^jK?N9MZSbNJvmP2ZrmROqn`+DyDp!d?8#C*ISI495{}YRz)$Y|td)tZ(x! z2r6ewTym`@01m$(l}{pU@cuYp^_#}hH}6XM(v^!7?)AyrP>xiz{>*qiI{I^;nD#WD z_tAv(Q_7U`#^pDaH!c4MY`k4ApSbbS69@jT)UJ(4?1cFgR}<4CC>Utmfz;#&Rf#k~KZ4md z6VP$^HficL+|7TEWJ7RU-Xi~_DM`p6w1m|Nx`fc*C*IfEVh7>t!--$qW%KYZhe(R& z?_w-2zz=l4PKsenG1BzTv?KK>M?5p+G_)gq|K5M<-=$Wa^3M_F*LJSnf9Ay5XGsZq zLAr{b++8t=+X7|C9SJlwak{Q33wuwLjB%YD-Qchd|& zwWFySPQPei&oha$G5$Ie-NLxw71#-a#E8Ue>Uv8XZM!(_CII`s(m(G6UFU0G6Abj2VHhTM)(EPdHbWoJs6vHy8V#FCV+{ zK??2EqxB4;g*)#}VFaNz%DY%@{FAHS%)P~z`!!a;umX}G2Z0lOxmLB-SWU3A5eVEP ztAC2?Pme(qB#pm5HC>b<_OSh^u>IZ zkk-+LqkGtVLW6ykBwD{2_Y|iI{E0E~BT9nnU4Wu1VnieGe%@3X;;9|NK0>6wzTuX8KY8Qh z<)3W-(j<{?r?b1dyms;A*6GhLFD>67q;wwxT)VvyTan!q#zF0G;WxRt32;JXsHRa= zt8ghH;ye>?2!X$551FuzRPOTqNIp2&Fh_v)*-F_R?Gl(#Jz|=Vl=B&AWItec>OnK4 zD{CdS8_6B-O!4#D`yPCbLh+Gn&oY^yW?GiM78qq^i%E*F|E2AJP$&O?2<>;8U2;Hh zw_Nnm8~?mK(|fx7SFib*^7Tuv2YRdRv|un#@TR}Psg^RrkRgBJ)>Ua% zwY>L`3o&Zj&~BA~$VA02ZU1kR+<$xTH_Jmy4^d$2mb@O|>LYN$|+4F6~dcGfP;GK5&U}Jsbxl>!GpW)380j5ssG|_bsTZCCxjCpCE)qB$m zlOPLja(4F95n{4mY-#z+qy?w~YddmZyyuxXsqXZWBP5SsY*!|2D%7Sl0XmY6-%!Sk zc<5^Za9@|NkPj*t-1i|vkJJVHjtv55hf<>4v-71kn%ZC>kYLxoM~K=G?^>_dYj5vf zf9ub__%n#PH#2;BD^dF8`tVBm#p{0`PX2JspRnU;${_F*pea`;z|q$VqM<0s*g(Jv zt?fF&7KTsnK3+b%_gh?_$)JqCSGG6Swl1CCI`u_TP_%dvzrOA0qJz@O)S0SuM~H0d zN8%8PLq6n=S!bCt$S<(MAlP2!delUkRWg{iNmr2NXz6B+dVsu7`Aucs%mD52f&@S{ zACA~_G~7pIv+M;o4*_A+hX6ei79e*z+!fFi(AV)_B%=y6ZlwdFyDiw}ud!a;`_7#E zG{E$3?B4jskM8{A@;#$JUoQ5aL8<#Cl)BG5;c>|4h5Nj|VxI?vtgc`SXTUfGI7GM4 z4drv~sfnzG`?E-f&+Z4fsa&yhdI-4JSiHEzYd`kA9*QUB+q^8W!K=Fmole(PLiivX zELhZSKXuJPM3k*>^P1&m!%dClb&^EISeA|n6Ekq0Ly(>4_5{HdhFe#_ z^6h1_HUMi@fqsm@7r6NY{#NMBc_WW4<0jOFqYn|OBd%`!^gL5-hb$)Y_^vtn2E=5C z{cz0DtdPSIg3VGUW2%+FZ2%X z!xOM=%T`IQ6v`Ch!s`{>s;{IC)2f>C@6qoH?r+1n39iqX^w`^6+t}Gy-?~m3l+^}a zztY}jr_8DAH?H2lv$s>%J$b?JY392Bz?=vxH&ZpIKS$#&&TMNQ(>xkwa&T<}a>!+py_T;07mec%^q%eAAfPDrl6!dI+@NOdhS=fA)b7 zUwQHQD+h+uA(w%;~K&SIBOYz+1#{hdV$MyN*TG?WlgetiOa;&(;>?7Ar!R zE2zJB@FX1k+k}~#^|kfE#@fc=`r6iBr|#3LqFEH6X5C~tVotlmZkcZ~mfz93+`q(B z>h(8l?`^+sV|DWqTKAV$mX_sk5s=QJxjYz-s>baOlc~3WC+IjECWfPKBU-*9VW0`v zI&o{V0|4&o2f?t>+_LPMYvRONLknB)BwWOA1qXp@^|M za%hW0G%}o4s^67CEo{9A2sD~1{^e}Mb{joFrLXow_H*=U%-57QU!ZU8-+%i4PjdfT zT)f<0cgbi|NujH+osvuvOuz*=01wdf4S`YlyH|e}@&7TNhjC5XMUIWtjk3PJIRM;R zCZCduWwGI5*M7G0-Om2*hR?rs?c2&vo&C?t=MVp|e01l-e0%a^UEYy;&}*r?ytlHl zvb(;rvA4Cp>FcmdhrNTUC%t}2YS*?iwkJ@S>;hB!jU*R42?sG(KeM&5^*a#0_Vo}@v29<6g6C<14j+Q5`18t16?M$z(UZ`J6V7?# ziXQIxClao)bP;G7$5aePDiv_=368&CniXWw^; zbZLlsIM^+#yo9T`mhgQv0Y7$TAKEXQ8z=tB_RjSYAbxi<(M4_+_L(KY+&vs^ml0vCq=1o*aM}qX!%{J{CKAo0==k7nq!XK-0fW-c|ysH=;|eOyLwYV8`SM5|VyFJ#lID z02g18X465K21lP~_39mHYkxF4TTU_-TSW~R4%cGw4lsH>v^jDbP)SrW8YUX=zdW&Z z`g2#WKmQ4c5c|ieEu@edY0&CM!&4{DGWRK{YVFbA$Gv`aXoWIX8JfuP(NmN`N~_Y= zrXg6lk)1b&JMzFS$Wp4o(bCb;jx@=(V{szpgrV@cg{hIqhyVDAdetHf4-a#8>&-ls zjG0FOZho&{`Ub8?D$u5ZSw+XF1&PTL8)XB68f5WLlmiK^?iG!_g3h`gU^}4|3mSWf z?L)fX=OD?0BqhyEaVD3kLbf%eBWa_Q4d{q@am&eV4iSKX=u5f$zLSciTV@7>(G_~Ovkyn|BX~%$} ze%01}aCp$A?bbRzyz(vhBv%@(d3Ea+XXA`FAuiKLd&}_ZPw_iL{^~#fb9wM=^+Fj_ zfgM*uhKOMnC4_+X)d!4GS5#n9VVOy4CMVhaH2pM(L%`LSAnd9iB9+M0atO=%ZjT%I z>Z}Ykts+DK>t}{h@u}s|5>z5^195C^wMzj>Ik(#=p%Xo5_@O^}D>;gx^AynFM#Ot$=T?d@{8vOyKg zUd!L`JK}V1)PbAFXy zhnJUahiZU_78$Txa9nUR3{G|Y>YcBKxSG70idm(B^~xbi--vxy4!LXqxF`dyw^EeGrm|MSW}UX4T445*#bSuU%4ngth-haQh%Ls&wwLQyGbxzF)y zl@e%riiz8#Yw}}z2w11#@NeZ_lh5KV;-ypoQN zTm4)bb2GDUYznl?vj>%i+C%6#f~ysv9hfP`&?;iiik)R8>oEdn9utlhobz0Y??>u7 zX60%EZljR-rTA^Qd6}5&sJQ!XP5_)k1}Pl?TcU;oa|dmDHJXE;8%M0Fd60$x_GuW) zfZb!*)>mZH5)TJU_1P}ZS6Iol+pSPh`lZ@xB^?^Rx`7Y5hV|4 z4jC^GzDQ{2BNQIc2IpnJo$j>tyPZp3@XD~dO~X9W&ga_t$MxHLzseNm z^|H=5-9CEnzy&ToZgQKVJGc2V%}f7`=&N8?@#!c8W^w7b3lZgk?$Du?+kDT`Kg+N( zZ<-mP)6+oq)lINDDq$cP0>BUpu-iQW2b>BXVi+)c0B`^pVSBH?;PUck4IlAJ&qk8~ zoAzcoGq_T&aou0tg1%Gh=7bHiG~~5ZdVt+$c8)37GNMBt0d{+jO6;z7SDv)|zp?wv z{3e)kx9+rc3)nnZ8GZ`V6v*bYbT@(3FXLrCasQe9kMWH8a%S9ohuf2qBbkX&i8(F=Y!?l z`epm=H2NQBrge%C*(ZCK&(e+%&XE1&*}uy$?t|51gJIaaHa@^U zxOYT=Tl}hVJN?<|w6C|j9s1}Nl2alIHb;y>eCE5=W011TFvv)y71}Ow%?_>1Dk)I2 z4X%#Y{}OEF;XL3E)X;){&^lXQXWKyaK@mUR(082S)LCcURw}q0jYQ~kqtjd;$K^Xh zkCgL(9QmEDn*S-Z$}f`eWIC40^$_Epuch2-12U&LLk=6kYwmmC7cXA^qg6QR+n+r6 zHO9FgU}wtv(XN}vHwj3B(yac?fF{Z$j_%tt-?sK%-j;mt?FF6-^~6|gFLhR)1xy-s zm1IauwagBH50Q*r6*84#t`(GBw`6=>)woSgJTqCwKNENQ(TUd)lAK-5g>k>`sqT7A zxvrGvSys*wH4g=sTNNW|#@m(92+vLCU{l0ARs~6fjQrj~9WJ-8l@lE%13X)ctH*lo zaG46aqP5C|i#sLOn5ARrINU%%*+602xOn*se`)Vv|2r~Yl^^>?CpVm9j!BMu`qJ!& zS0>rKw1nnj|IC&5mCx*bq?|c*_8*I|*!^20ow_|--%)9AxKXB^5xuw*SM6->jy7{S6Pk@oxyQKvOqB9^POV2@@zi z#-y#?RYp0?I~;DI4_!kSdRsZ{f4sbL_zQOe^rF%?!JmJgjiKp34`TCKQ?#VN>6^}l za-OJl{Jja!aqiVb`F#?`m&_YS@u>9xVK z;cMNzkYbB6WD!G*5wZTqkI%+e?b2KTH=MGc<)h&erxmXK*ROf}wl(Rj=gsU7Uj1ve zZ(m>AeEhX%U;E1fO`hy<83M4}+}`1y(MD@8Mm8(#rRu`Xg(;)$!Gq<82ItFp*m=s) z%}(lOc~71-BTqbU;#dU!O@h~cMOso&MEs+p7j4A!>n@$|Y**mM2HFKl#EzD+?U|bOur_AkP!Z@d z3_ren^%aRSq6=v)UwYw7j{x-R90uL)km+W1_t__Q{$2%{cecKKX6wxVLD?AC2&zL$ zFGntQ#fEvd0qX;+C}X?qQSGr=WS5cB>!{*+lbSJB;8klJ&&Mp?WhTl`K;xK>1yZ=) zuf(|G!E^yQ0E!dAC?&4fy4uyDg$wq`X*mF5eWuzjz z{9=OKQnUA}4F$W7!B!deu=%0_{r#JN##sg$XGJ8|UHq); zu}MThR9JD-CR_ztPA4-sx-MB(ZswVdBZ0QzEHlaOK$1iuhF;oFKC#)#ea`!9HbX_HhK*OH92CspAThOS`o1b&6K%1lJQdegXGm z4Y6&auS%dHbnObyQ$Qzf(55iYQkipz?`@j+2D9%wb%5rEb(iW8ZE*C^fwhzUPSc{h zjTn2{pHDfHL=*&0A!%1|T@j;!(1`LlWY^V)gsB@8T|}uMQwZsWWEio%X|&9Y6+o2w z5?pSy_r7U17}}ldJXFIp{hi0QfhhKK2F&LizWyt(J@eWRQ??x@f_4O({P$?Ii0u(O zaQU_ZqTAsW3+8}~n!*${vx-%0KUkGs8D!SnRO_A%`pVt`&R8icE&A%#$EybJ=L61B z&+RrlU^<6or?Xa;kSf`%dxe#LiO@nWb5#S0zVVz$RBeNh^IP zayGzrdh{G)sBNxOb!&2${%Mt$W)7J^0BAV+kk;Pmu<*hRn%vu~05g+R*Yw~9IJhOE zu>Gjo=>|lcA;J~ygp>276AB!<5AFb*!*t>5&Gn7Pw|8&69e z!1F=nY6xF#!dAcq+KYgdtBFKHiu2%jicVu_YV<*N>O&BB%ebcO>Rd}50y)UdmN-lxU3QNXAqnzrx3ohqjW zt~WTXEH}GOpe{oNMEZz%RdaNfc9yg2TsXU7F4wQB`q`hHbEo1^cZW?rXQ=NUn;YG* zu*Pi4ptTL)%bX16Hyr)Qh`{>sPQMq$R2tNdd*Zaa4C7*hVi&O8JtKGb-SL9E#SESO zf1hq4lr)f=Q~2!P>lmCy;(j0dfBOT-?JY_p4S=ChjE8yX*q9;H;E?*Y4N7>_c znT3^@a}UrTV#&_cHNWas*z4w`(is{+8!2!ImHQQFKko-|0az}U&9n!Mxz^#p!+M(i zF8wY^$o+uaLK@Js(%;L`f({^+vxz7NSMXK%0FVX&lEg6q+%*p@%g;YZ*A=5klhe+Hbx?KNqNf6M?oe(b2i_v4kKr0 zNiFq-F#&V2MK1Tb3oZG9FP2ql26^+L;rs;?)wkv`xW8#`F83(#^q}A)34SDHdq3(9|?_50Gk*7c10B3-9YMv zOvX;OJlki>;jy!Z1S%IF*0J)a@4CDbBkl)?T|dz;$MEw*qsNG7g=7lznm1onKsO72 z9O#Bg;2*^uYunRRw)qt{#eSsw<}zMquZ_WmkX?Yl+Xb-ml~>~e^icLVTM7p%nT-*adUqX{}ANxK#YnJOPQS|T3WA7p3+w8r%KgIR%ohV-p zJKfGX(~^=vbM{v)N6*#cmbXm_uqd#tBpZbiA;D*hQ|oujwYD29QrXMloLsJWw-JQh z$6jXFV=8(pX!5fgGTg}5Wy`cXZQOM4rUCd35$=@yLA6H!tC$|b!2`Bj$BvQUVim6x z*Vf~_(i+oj_}0B*6O>x ze%HB~m&b;BlT22 z-EQQIwmO(_5X diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300@2x.png deleted file mode 100644 index 2c7c07852ff6e84edc2164b4487aaaa6cb4d8fe4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36873 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%0DE1j{G{fQ$Fey0U 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 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300g@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/hit300g@2x.png deleted file mode 100644 index 1ce746e3a494f4446cc451f5924240f4c8eecb4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39840 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%0DP1I3KX^ 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 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb-spec@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb-spec@2x.png deleted file mode 100644 index 76fd9ab16807c2ef61dd2aa0db47c78262db03b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13141 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 O@*I3?M71L9&Hn(Rv4%VV diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb1@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb1@2x.png deleted file mode 100644 index e99f076947aa7ca1614fe825839dd3d7b8dcc303..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17792 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 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb2@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb2@2x.png deleted file mode 100644 index cd36a0ae169e1d876012402b2b7aa34a13a179d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18268 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 SqgKcO0000l1{&5@md}*`-!Dp9 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 Y0Z!VEjc(%0RR91007*qoM6N<$f_m)to&W#< diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb4@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb4@2x.png deleted file mode 100644 index a5b19887d64f0040da387029545dea15d85669c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18062 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 Hu0mjf{m45K diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb5@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb5@2x.png deleted file mode 100644 index 4bb01f0e88229c6433c6363d7f7c725776372683..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16895 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

{E0 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 E0O3MVi~s-t diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb6@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb6@2x.png deleted file mode 100644 index 859e0aa4c1f0d548eda3fe4c6c02f7fc4af1831f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16702 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 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb8@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb8@2x.png deleted file mode 100644 index fcdf4ed4a4a76808dbfe41e54a45d4433dc1320b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17084 zcmYLx1z1#V)a@aq8G2|2k&uusX+dcOq-*FJx)HsSl8@ z`}+U)KKFTs88|bXc+ZZt_g-sapK3lKCZHpLAc$B+Sy2bP?)>|~!v)WNld6>91>arS z$P0o9DgOOnKskAEuPni5 zN;?1hmz$Rlf<+hQXk+WCVETVw`K(a3t~N~Y*;24e_`h8$T6)_;g8Tx)5BUE*SOg>_ zh55mQP|_?Ad-pIYi;Xl3;oaYI>IayY^M0PSqGewt>^zg2%msN*MBp`5X1th zD9S(cpWn?7$fKNUIveX~`ul0LpQMQO2WHE=7?#V>FMq;0$=;2}sk^>$k={g+HGnhhNLY=2VOf1avub7g$zz|%`oxv|sfE`1QmzC)mWnXj*hDxfF ztr5vfg||K1Gc`3>p)Ci5@GiPkC0r5)PkLn4(66HL>Q#Dy+&Rd>^M-lSt9)_!9^152!|{QXJGGfd9WMVu_d^+lYj zSgbc+;0s*ChkX6B8~#!^BSlK_bdVed)bGJS#2^mqy!gYtIv^CvOR_cBz;OriAL1&L zVl?u~ z)K0f9FrZY55buItGLXqyC3KkR>NZ%f_9yD7sNg^0>U+wm_-_1tsycgGG%2&_3q!2g z?kva2Qh63wsJ|3R3|_9NizLBL7}lNH-{bFoMv%&g@7*#5?Fd-a8RBAgnZ<}l==@QM z7N+XH=Ec3uEO2sQJsO6=O({N-1 z*Xil++G{jZx)UYoKl;K(lX<|@O$9RK?AH2MisK(WStv;V;_ zCg?v1`dXSESZ_3e`i6cixU{Rm-JRC@4%vY%vkivut~%u1^3;Z?=$oN z8AVB!J>{gg9CG^{F6;o?nQt0?N{2OD{p!W_MK%M;od3&}%KcI*}}#(WodF;@T<|)e`9&JhBiG zpFiKn=8vwqxw#SKu}}Nq+LSmP8acf$j&fJvst(Y?{dELMbi~8pv)W;lsG50=*x|f$ z4Hx5iHZxcaL&e}%unBGRRX)?kf)^B!fWy@Hh7H8KtZq=TETQX3v{nrEaEPBvQL1U|kk_adj5KA;=D{H_AbHNKaq?zKDp(_x;n=OkR@&a|f*1 zXFi7kxrVH_;qX))~%6kc8%Pk)7x;z%uA^!x}L_>*x)4hs$$`*|&YawR) z?KmfE(_AQ2R;ZteLC8*hO>w~fS8psVzVAKHaQbGzVn>h|lel{*Z5Q>2uQ?(WkplXb zg4vi-V>7&_E&OxYg`Kv;nVur!!UZr^VH`&<>ZXqACSH9smqXL0(2yK)%voVVozlC< zi9>^m;kmAD_-MD4Q4Vr^`Apk@A6;P}^k!h7>b^8OPO56KPY&8ONDLlb?a`R~BfigV z*4hqJ7p%58LjSQrf1NZQpDCLDO!7^fwCI6fl9PqxD6@%L_|Dl%G{iL6jf4XSJOWmy zn96pt*S>!rw^lM!``zPKH8r&{k!*G9_`dqx*3E(n39=Gdvbk0-dkIL26k5eYY>Y-W zab>kMQKK_l51kY09=;@HHeVn+e`(0W&fnkSAbkJ%)xkhLM&;-lxKm8`@wz40(;TyA zwy&?opD=6qPPOhVwx)S9_|ZZiu_0*{)p>?yG|hY|(xoP2lx=%;cA(2cJzSz+acq_~e7yIFRGM-m+H0XB=u{%+j1IA81HEbWjGioX zbJ9cwS-O-3eT5y^_RpI2yd*yITYEj4|1e9DmCRY30nJ7p`{N1o^K{`*URbuw^9wG% ztZkCqk^Z^e6MH8AA7Q)t6;y}V`V@$@&B&BXjIOB(qP%IFNH1H<1#8<}Ed8eXW9UD% z{@HE&d>{RycLRRik@(aVQ%=OV5knWp+t;|Y0XNU9+xOaxNTOHSE2i3}oSJTSKi^?q zEY#vSyFOjX!t8Q}_;X<0O*GR%BvSI&NVnrZQwXftD~~YytjtWA z-@ffVqPe?o4-XHUX?P4%{GPuDuIUT;N5TY2p&geIqGsIh=$0Nv92az_P(K>+YY_tr zH+U)A`b7`1Sj>ygTS^7xmhy6^P7Ksc+!nC18*4|$t+7SdQ@h-elkFg2C27^=RiYdq z(P52on44J~Zl2r1x_Ifr9zaU#fwTWPmQd@31{+uhrgJrn`Lb)!irTSY5-= z(|M+fd9p51;L}}b_EMMbp%)P`22WUDG1?ad*p(&UP8nD%CF&S65#gS8o^Ry7z?#)e zr4_PEI120tdBDpnJ?Gl|KrDBJbm{r&lEvDQ#LV>cJfbP5w+TWzk$gYttr?MD(2-go zua!u!wTAu^XTAAg(fQ(Y^%pzKF{Oj(W2Mb^PozC z7XXJ|;6jQ$=q^0ZPNTGOqm77i4~d=nL=3K+QUKDS>V8s zOW53!cz}XIdv*yO6JYOrE>1thNnTt`7Mj0SXTRhij}@bNV9xN>-fYO(!t?uk?W||d zo_(CIGHH%wO1@L6zfA`g=!Z-5l0JX!MX-zl*RBfJt{UFYMvclwY0n8}dzq|rzY#(E z8!dEVonZ2Y`AW{%%wDti!uJ6CV00RQxT`Ix)i=*6mBKa)Ltdm!IW6@ZT`iK`eVk_x zEs)TPxh}p=)0A}72A(-)V7cU4XUIgMLaga1#LTAKI&Ho1nr@P)m`^Pk zISKaK{Fd6}!u#>h%6-lfA+C~*;In+V^?zBNSGHaO0q68f?S7q3073R7!qHTqx=0WJ z_vJxmR@SMu_4IWS=S}Qti^0ZNp~chdH*cTf`4{YCK>IKS+_LVkquiU`dJGFW{`yfi zV$j!gHb;9UC8gyS4ZkIynb&eG{1tU|2UF$c*8cLXiU$*Y^vjZSiV%i;UHL#+s)&^2cDAo$cDKt8$pqn zqO*@Ic+83PV%5lId&7=E5psn#3I)@29i87PXsYFnf?&JXYU-ukS4d9`PSH7x~p z9L;_I{^M3tzFOldWSyZLWnWD|L5SyQo`i_xHwy|Vk64Lw_dV}JJVY922|D;%lT_-z zE=_QbL1mKx=AAFD3uuKMQW_jWJ1+iIF!OM6wW{nQG2{C%!&!t6rEcF3tj_8DCa9RE zt%BU|LwHYnCsf_RscNU|Jdp{>TDiSB-8SQ!=`pW4trr>F@DXjw1kgN}Z8qz_Z_iz$#xe!#$4@tu^F93TDf}B1!!VLc&&CYBm3+Valyo zHCI<*i0!(QE3iLRtvV0B>AYHhfCX|ke%WN}uw6rkxXXOwRvWhO&TL(Ts;cTub7N!U zch}~KITUWg98oyS4h8m4uC&2MzxhVTz&Uyxj31_uJ3Iz0IZB0(xJ!so@f(vq4YqGG zW(Hwhpl0TB2J{eq6LnxXZ!NW--UX&}z2keSZD0t)ro^@+F7a+)Qwf}x{Du!@!S~#^ z-{^h5S8lRslFF8|zvmihH_tb@N*WkK zAWesEB74~bneL^DJ^vZx&bGF;aPgJY)Kp@-hI2Q*tl^)&?S-!eZB>&MaHfs5wGWgX z9UWzJM>1WF!Zy$8l2&g}O~$AHTs?3hk_O|4y7H7Iv19vRDAW=xLNFq4hgfWpC3j>a z%SCkIA=p&r-?7XAb(y+%jb;nkYpSRWK8x=05O&qG#3|UEac4LU5X}C*nl#4_!J)_9 zTZ&TY@l#TA@?UnFS6+Ov5xh=ba+O^>4y?%$vLF2$j)|_X_e@#Xy=j`+o(ha?Vx#y^ zsZA2IE^)F%Dw!2iOr)~ULd1y8$R)8MJ9pAiqWGyp6t8K`myT1M6^NzRc%L$Eqz zso0X|Ft3L;WnrBmj|E5{S-$(r*E5Vi={6Z=CA>DidbBU;?)p9i@lAc(SPjoe9?y|M zIp9PNn`TD8I3q#Xs|DiNspCBc zVtuMv&Ju6367PYv!L)n%_j584qLtgRvBVHxBqn#fMvic7Y|&ZU9O~xVx@XvkU642M zlCllnT9DaJ+m`myCd_^cZ_g`pnGJiG$_>QzLr5gzp8BD9Bb*qz7v=klkeWxFGwzp{ zXzqxCj?P5GlVqmT^?S7j<^k*C%?r<~dVY$RE|+%?ah7o7BP>9c#yEa&2^JR{y8f&z zzK%KT3jMfWEPnDnx6gw)rl@7vwfWufdYe;!0xiW6!7PX@J$t_G`#!CvXm!IW_SmKL ziOu`m+!2xn!f84D0+M-}rVNm~4#NEE#Yscq6k+&(aeY=Fj{K#lYi5G>L0z^#M30On zqV?>U-1?|)mbS%N8_oii2oHKJ(lZQP*SaoAc9`JM!@ZDR_gIVVq_PPP)&dGv*zmeJ zKqqC%^|Yj{An?z}kI+dRclGaGckw+R$^7gQvMvt>&>{@gxnPGB`;(b#{E%wTaPH!| zaa12c?&fbduv|e?FtA|LLNr^Q_)m`QsafzrpS`z4EifID=7pt)YWi^Tq%`rQ%h#~O z-4>5kn|y9KPG|wrCdP}J0JF;xLUI?6j3vb;tCy1E$e(pt)rHP%SN)!m(m*~-Uo?V_K2puSm=Z3Sa=7X zC&TFn&bZvKb`8IL+n1Pc<4y#sp_Nj2^vN1N?!8yiA)g@ z`n+}FBt`<9MG4=hmMu>7B%rOnBppteT8J|8!UX2SI;p zVxa*PASs*Nny9S6t-$3eX?z8%Pu)EK_Fns4oO~T#F}1l+X4GKEEJjyE432bl`ot-= z{A`WU96%2^`ItNDT)MacQUzpxGE)Y6tLLf1(=!h}o*+XDJ58%WUj0k5CXF&>Tr_%?G(JLE3;8<`|9c4Xnn(5y|V^bagF8E;y6k1N^xz-vLh zQq=R4(}i^$n_*xueF7x-C8g45AdI3~dKq!SaD$)5X&{Y##v-HxU{H~87B+QuiWbxA ziM^$Eiy1^$f%k+;hkrq*tjUtdNZVt41aR|2rT5R4h|rQevfn6l@H@iCy1W=pWyX$V z9rUNSyhr~mwKt1xc9Aej{uL~noD=K#EX$~WJpBakJYluPu+AYZaH=fD>75V{Y5;Q9 zBbA2QlQ+*vm9*2R4AJ{IG^XyBqhUVnOOuVX5=N$$Z_-&y{(31W^HN$Ih2njPngMk% z=asG(HqJ_!wBOz$8^VTn>?oBp?uWa0%#v$ip)PXsYxd-%YqLd>E7C`JE`5UltAr9C z!K|bD{O;ofPEkT+*t3pr4mrQ!b>$wFeB~qz11=llu7#jU3Gf2w;dB?Pq`lmj=r*@+ zm{V=Y@DO&u2RHr9sW*m9=hgjm&|tJIs%WZ5i7p_LR;Rrf%HHcw?|DnsjN;cy2mbxd zi`Q+oCFEIeXb`1yL4~lfc-3$CSj}o6`9S4O+Pby<*VhQJUVLLm2zl5)w+Dgi>$+#Q zCVcjD#GPc{R@0K~I%m2{Ij#&m#6G#gpZKTQ36Z*+2_B>njIg6Ijore7!GIeN^L_O} z0F6cPK??=$^y-0n!@};jyoc&s8srKx>*9RIynvAmjZ3i~~1-GwOTax_?vT)>~ z=pGEdtct_PP)1Rd;RApb!4hqeR6Ml5i|8eVM0%o04dPVdC#p|uk(I*Z<5n2?->onp zfM@AqVf6)@0Y;QcyywDOACE?l(Dbv*9YGeQKB6M4Boqo?L>0b-6%khAVN6l&IYSFv z9;ny?1yY4CGz6-*+*UroR|D`pAlhIg1hnZqCt6I1Ae9KA=UBC7eb(odhA) z2)}EKzDcCk&;4M{mM^IfFBa@;GZJ#%TWn2CpGcNSdc=Fq7H4I9dvmQePqb5O*|S3u z-IF83&B17>5JTNFjnze_JYvZ8n2<2VDThB*lktJ{o364s+drfT8;SuB{1INXaa9Mv z!3k;eM3oD>Os-AFRoS(6hDKmj(qQCmV5m^1oT2e?R6z8e{=#wA^8 zWCZ$b5)4T{U2rou&mHX=T0bbJ*;&#;JGh}XukMp+hxyP^qjme+)U~Lop~idxvWr{~VSA^~*?&J@vFfu?6dO~30RWSs*l!efdPQ~H z{STP&^BW$(>$}#oES9ULx^hM~1i`|kBFFU!${IyxS4zsmV2W1UyLaL^He_b0^rcPV5 zj&Tj`6HrZn1hJ@(<=ngwRNCI7(OaXUx@F#!r(227VFfL0tyZ-MV+?pSrBCcP9*-+( zW2X%Y7wdH;F+N1o40zma+;K0Z&%>=Gf3re(55WxIY>aeDT-A!<56R0H(TE03(yz?X&D^(pP0{V+-ja8|6#3UcB zaUW#%`{W9~I;thY+$I|b{+h02hRq9RPNKQFYQm0BU=RsRA)Qs9MO!11jW|q+hG!Wh?_#;giK);G`&rB_;Pw`YxD1yyy;M9pWJr$7glR z&?L^}h7EH&Bd9~S?t7USU8H@@-65r~5gAR25ha=wgvIj|J{;*2Sdp;8jk$93y_CQ4 zx{|e+10GAl2I3v*@Az=u8Bw!E_L2!`;&B-(X~bK8z(AFm7-}b5YjU}~NuPG2*7r#a zBBB-S^<=31*Z&$1)i9~y%8gP|P!5G*ZsvJuj^8i;;|LSMuj z^@RzJJS7N69t3u5tcHS8k3=3;IhS*9f|Bx?*cl#WfM2qcrG#>ZPXdp}CjR8A5~zCU zI7<);Ul0m-PSlyJEd-!QKNSb|Py)Ds}qlwX~~%90BK069llDt-HTKSRjw>r*^L zG(JLjP<|r~M!`koZxsQ-N|r zE%c#EG#Q7QEU0*(lCIc@hldpM*(?Zht^7ju#3XdYiU0f7YW0E=79Qf*c!I0yA?>{{;awX9v$&9QDV7=+@5lyukP!OE7bnXpbZ_WSTqZ`@ z)$XZttMR&rl#V1Uu7{VL&8V82}1T}SMUh*T0IFi@LuMg6sb#7dM?oJIXC10D`_hDoj&cb{Xy!6f^LvF=C zDt@q~s#m@m^ZMJ(YnKrNVt@Wro@}OQME--eDS6cokud_|=rLwCl?$=jdY&g3ESdOD z6!9YTN3zK{(+(_KbV%(1$r6VhN8D%H>F-4JVg^=;bSLtBrg}*r{hAqPx!j?RdkKWE zEiJtsa~I+LA>vPbqL@w*8yQSFtH|m>l&-O)MR?`{Ip|4uI^n|T#@pGhP%*St*?(7YN@U1ea83qkNmRT|GYKeR)a#V=t3i5 zb6|e6(Cs=~i%`V-;Kub*LrscSy7AUGHj&MAGYd*O}|^5Ry|=43BvuXmr~{D%(2|rlh3( zrvYOjau7{FLh*qx-_o*ujg>3xMNq6u%okx?TI)BQs)msr4Opq3^v zG|G&KD`LQM?x!zV34HU#fbf|~jgrW@WlL{9$9%V6Afs1MV7E%9ElXsu7ej4AU4A`} zvm&##nGmuBdaA#p!r{Y1dFOLMerYQ9LWlTL?dpMg44^uKT zY30g3>6dy2m(jLT5lwg(6a4@kpT}lwC1wS8>#sQOP#7yqkQvb zb#%N*8h1oj1)^hIp)PPbbX}#Xnz$hTigxtZ{^|93V4a}VQ2SOo=tS|~Qt>k-4~QUz zmVPCiCB8R^C>lvB9XZVc!2TGMRu=@fbaF)=74FSYp5b;dN1z|U<$2WmpuuR?JInAn z>Pc^rrqqX3*qu<8-$99QgVQ*FH=c~ZxpjvnpHOJl^DwK2j0kjb#no%17PF^mI!4FD z03-|l5~eAX8Q^N^GiUZPMjEEA?iDScx$dHY$*nSxWFv@Q&-19%IgfS#Q_jLgU;b5m z!NS_%RQI3y5PGsZLjC-Vv;I;qSgu6|AQ~cEKQK8I<&4vr$jgX&w*8$p#fgD)=(*Ko z=5u1YF5kAOsSF>pCMPO3a{N~U(-skWI43bY!}Ph0wQe29`c*}ompQ6ZC5)J?B$3}0 z7p(MI^ebs9`55-;lrtv0?>ear48gbi;qT~b5B#OBmi$(fa zH0Q3|EWiYtvyj}~V$p<&1wSu={tJPA@qV~+Dt25EYO%@LphW`t?+X9KCu4}HZOr0B z%dBqNiV$9?00+835f@_q?Oq>M#MuF>lahXs*k^S|(87-ab>JWTgoirf?1i?ZDt7HlB!0p4%w& zVmvN|lSF{S2wBe>cLWI684|%flmoAF)Y+ZEe?;?Qw%d*5%==4y(yGE>G?-V3$hs5y zHlfaHkBc3G30Tc)Hq|Bu((j8nPm7b)$yz5AxAt6ufzQ%6)>`OIuT@?Cpv@tiFgH8c zDj_yTJQUXLwt%jBO~r}%*xAZHsd;b6A+9K0u>Yd0z2}v(jTU;wE>YIj$oySj-BwrW zNT}91M*^{&BIy`Sl|dyhnKeKP#S4Ld9pKhjaBJy_A&EDfLvd*6QbjPka;Cm-uCg-F zBrL{0KVT!fZ-;#NrP`w7v`8i3R6Q!BC?b2@c^vL{zly#0J07$MqIqA9pA>t+``PvY{dzQA*abk?$&E1 z;4nJG%9eLXkjKhBe|{Y%iq-Bs zQ(Xm^I%WFHjzxTGaBC1=N;y@>MV`Lj^)O}t72Lr&CNso#JdxP~229~GG@NnW!}XOI zCSG7nLF|Hi(!T$RaA5Ty1X#MVo8DKQG+w1%O9q3+SRL%pK>m$h-mAmSHg@nqHuC-b*}8Y1M!GN|KuRcg5RUuv^|bU270e@8FuReau0sFLS(M{wMCra8zg`Lmoaj!)nM_dv~=T0k@cWN^g~CikyK0!4U1I`s~#IJ^rY)G z^o^FLzbBB+UQtRzo3fc_SkWt*lu7E$qdjb?*7A`!1Ig`O5b4r_RgY?sJmc6@ zgkLGkaZ;8`xc}%H;2_#L*2(N4RkY|iPHEV$mDn}8|61jt%`Poysf&VLz za|<=!7|Y+^|D_%^x%d;wfA$&t+qM?maEjL)P7r0a#eLtduAWa(YI{;kmbYA7-%MSa z;KFQC(!wU!+-erY>SvsBp0P!oY}x7xY~&x}6ep(^meprMz z{BWMK9R@GSPfF#7b};k5#-*}tDJW@c>ShT<8SCj?vaap|6zJO5DYX25stF z4NrmWno1WC)y}llm12qpp9cPG>wMcewYLpg z{q1}VByMAk^*K>``&o!z=U`W}qCwMUiTtF}@J_(SD;)DHFXE(e&esT&dt*0NAWiQ{ z@;}Q}XNb}krjza;vI}*#OBg{WP-&nIHNrU|_iqroCsew41E0VgZk_d|e(^!Jda5!T zrc9yRF2Iudgp-5cfw8FOa^yN%iZs6#@Ey;xcwwaO!J{1}qOY|B zM|R>eR-Qainc!E_e$1Ap;~))~lW6m6mS1NV7Z<6l zI``iN6s;=ahVDah_t)r9dU{lPl(yw;Dtt|Q#s(%Pm$EL;3xS6_O_h&Dd`9}Pkq^=h zm;WHKOCX*FK2Z1FrfFS_80qyu9-1Y_`7{wZwn_hH_!BpC6u3VxJ(yjHCtK2>Czk2VSH(u|LYmIs)#WeH$ zP(_a&A3C9T^%z~9*@aR#*IYF2snFdWKAZ#jDf~0?%jVHF)qJahO1t&fduo{|65I&A zk?;RbWII@v#H6Hc2O^pY8+jO#zr_mhv6#`P*P5JM zlz7-oq}Z6mTl%7R3#4hto_xB!x$LX`k%kGaM2u$s+_6##&2hi~EXy!+J)TX4E?b!` zQjX=RiGjiCTI|Oae2jLhzBtCWPk;9T!`4U-;7O=+j4SewV_UvhuC0~GNXen${KCH) zMPpve9e0?f$f{kg`833OBu8YSoyZV^3dc@Q*6@R8+>ZXg{F4OW(j?KYm~}1jHd&@<4-a z;-yf(9Wc4vQ7Uzlz3;DSavvg_A-Q@Oh31&dB?@@I(656QUP=OaVY=sk0kLL&WgUd= zot4fIOHRr_S(EH&fqt$yK|SsCPf8F9TZj8Dhy)C9PO8~(Q(FbF3~7UFk${Z{$dzL! zdrOy2e9K}SU7t>ugI>w8{P%igU&{fXb3|HySh`HGzuKbNHGi3&>z7k%FLcs-j{p*h zf?G))eHC&w%B)EkST!#k<2b**kp&gR=Rz@XA|FrYot?45y6Atp!v#6+e5wBmu7^9$ z^8&O|eLk2uPVSI^!dCGQ^aBr3{DWLGl`T~Qi%oU={Jw9aoAE{Sw?#`; zF1EBmBVfl9ax4&t;+@McE_cl&t`kfP|Ds(MGC?xed!@{lo3R@oGxG^}VW8P7g{+|0 zzF}t=KXMfadBMEugU~&dHUYXsXqWDrPGe$6{=UMOe z-ii#@2bUCa_IMLjGV2WY!97ryiWT-W-xcEkeaAe7ZL7_Y$5;Q+qem{_G72TTAN@`_ zFRw7DS!N)K4%s@rl;=J!mS2b$5Ir3cTlsEwnwH}q2b$&>sE1ynP%SM1$|UJ2r!e~~ zWz*HuOOWYqtJ~TFy`o!|7>{u>0a5tt=8>MG(Q1Ov8$Mmib%07|{?rYKV|?JU>`yJ* zJ=H-&a*a>_)cosxHG{&%nv?R+`st;`zfotweywB#}Ko->Gm; zO`Pac+R95Y?SFU__0H*vN?_JG>k1DlBv&A?dO3P?eW@bFR7ex6SbA}NQ}bMA<(e_O z=l8dJrpx}TiThx|^26l13V+ghrLvg~!P`H!wapg^MWyK>6LIF|tXNYTdm**%a%X$C0^>X7zSv|36pHFkb5^!b0nyznSc<7r zhLS*|qNXOqZy<>=j5XMsHg~F+(HsT zGFb1J7Mu)etz%+DAa{uD=#yp9+qafBY~-y~b#)%Mz-{)=f5kt*Y{Q_2egJ>Jkb&V{ z)dO>?kq7{zmAU!4dEeF^K*+2I!yI=&o_ltjN)UI=ddC;L8&Y?1KRbGC-A}Msq*>E;fUZb5^ zvDa@(T-0ss_F#b7@A12FoG`f`Qk^Te73;%UHQQgu_W#QLEXguA_5}!(=D7@WvAlDt z?RlvptH2geMBJ0aIKeAsZ={bcvtIpP`Ax9@5A49Ao`*x7UH8)l2Mc+uIw@{M12Bq0 z8a~sO+J>>WYQOpc)Vb1!MVd>EX_W!l1~wjo3Uc2Bq&YvVt|SG0O$9s_D@y1F2P(r1 zHQafFc9%_x*~aLyZ&=^&X6w9M+UElt*yfp;nUKGO9EDQ2W+~5hQlBjX!NC>alF9m0!B_J#YF2mLxfBB@koMMn83!9UNJHOhQtl~+1qcANb~6k zqL@JDzeBCFa)qk>FDX{L;jpzR)l|kqyJ8XBW>^lKpkdn-j4EO z&p-f#d0?@=jGx+d!8bmZQeGUvqxi3IlTd1KM)fYU9JaHlpZr5 zJ~QJTV>HUh+S+B-x(-s z+u-#KgO}9htno!L33U+b4I$Y&Dz4H%dD5+6Y0O^(i}e%Vu;-Vb?rT%0!N*eutr2%f z&9_f4qlJZquY9*AN-oDOgt~ z&tUm)NR?@;rxB=+Mw*(M5}gR&-Fv01p33Gp3V0)?DVIl_ajb}612J&N`)FrA+DR%{ zGdr%!u*=4E!T?$SEM5QWWPwbvuA8I6TQ-1KFC*Q>r35Gmq}yx;Q^yY17Z1xVz0MEU zhrvyBdtX&0U8!J_sm$h@!RGkq-vQhSUzzYwM+uxTTJxk-*Sh#HHiRvjzi#NzQY&2e zF0t9gNa8>voIH@G6(}x9mzYEv-805x+~}Ytv-ND*$MAt!TVq>w_1*@^0nGT=m_Q0} z!A>4~o2AUgUTNG^{=?V%NiRR^ixGI*!XHV|JI_j|oOZ{_-&aYLopk5CV2Ue(SgUOl zo^Kro9@(Y#GWsnFuu&2u;(?=l0wgk%Lyf{i^3Z>tCtyWR|Z#5B25l+egtasV1h08%rbl&(peG6@Sw!*DZg>=JKx=_>KV6PPPKs}lj z@qH)iU5S^=&s)}nI=?A8pDgxV&XWHc3a?QPY~&K$)bYI4<>eQWg~uOQ)Th3G(Cq-! zi?Phi%u(-F)A}hVv-@$sm;rkk?MCqP>VL?>=UC99JRVtNMc@V1rw^Ng`(mf2CTUtD z(lZm+`hV{*`^oMe(8P$h1FFsKpP`kgRdGP`xG@4@*MtRjhFTxWxCx#q2|wTkH`#om zGvxLTAPQ~(qG0Zn)AK2-x~miPg6l%o{-(Kw#hA7#2S(Q|nS#_DiwkdME76^KEElil z5h&+HB*qU*#o#v3Rxz7K2dq3lJ%}b@q$5urFavd3+Mhpv!VM!Tew5ZVYd2XFugzTGq8BB$4~D{wYE435{y&Zz-mD6>Omf= zd4a~LYC3uk%$b+YgGYfk`a)-f2pbY8rV2yUpcako=9RpFz=#K3%eme;dXi{w&?z7x$hpxF<|h%3jId`@qgfUVYp-AygHWzp(P9(KF`Im zrP-M^-~C_J!c?}k3{ZP%XRdpyq^G-(bNOFb1Ou!uiReOfm&kksmn?)r|SxP8B{bTJ^C4)KKWHLhmLJO8(yN zC2Wln*sw~7G7q`-F+=4S(Szc-&2Qf|N7!*f9dOT?MRQ&9ht~s7ZZ7w0#>%`Fo82q` zJ?0+5#y_qB-QK@jSIPT%zF@~)t+w=f*IMx-7_ZYq>GBbh=zZJej{(BuvEpQ}IOE7c zm@X-zVVt3=%>m*j=h}tcPoJ&oK*T$opwN;!$l%!=nEwu1ETR+&t{jnzKuFe1J#DJ6 zKvywepr}g$V^-*00WPK<0u_=((8-R( zh+RXzb;I0rpj5$W$mPO{Z-B=Y2-s{uO$3K{I3n}D>l5axWr-W?xeHbEv;5+Q+>?tq zeg4g&qWh9(%!7DU*vRer;mkz16d;G2>m&zOnIJ{7ANsj!X;X552BHdOpWh9jd@}$3 z<8=Y_g$$7?9MF%zr_S}QmBSm|-DolHJfnX3-diYCi?d|n+grwlUt_a%)=FuEz1bsn zjzAT12+9ZVim|pk`c#2{c1}!&{nJL9vJ((P+JR`Zj;|flZLS`)WHJw++7y`1G{bwB zrpEad7X2A?>Dppa|F-2-|pHN6@!3fYy?QfABs3}0Uh%b zkOAx;@YU8!4R|y_KeoKNbGMmRr+aH$@)Of|TZ=VHbj^O&KtJ>q7nQj(fc~pM=;=Kb z)^Ha0NEmhEW23h-dc?>D>XkOKI&89c>}enN0DMe+NNYSYq{+&)^`AIe!e5KcbxIVe z?_Av}-<$O~i6J{}P8>KFRxluy=Pm4(jyq5SVdr(xl1=6NFdPUj=E~4y$WtOUwxFm@ z1aud-|6m7KgYwP!Sjb`e1UEv2t1EYeSLT%=nis!};d40Kw=^y z(S0JWTA62xp)Mr)$2a7PS5s#PtIpFk7NkI|;5hSIJx`o$y4s9Tw^SWNk#fhkz0rG1 z=aC9AGC6Df-IGTF0j*rGl>bZDiCS%0tG6AN{Q9ffydwv&y<(yNh@iitk;jVjR9+bl zLzPud&9ou6FtUAxUPeG1qhMEenDPIbCqZFV2QT9!FadRXon9FRY8$Ac`NC3D$qQiJ z7|^P?runDffN0KdKoBOKlGArcq57fZZWStsLVb=!BjQw7@uM@Cj~6!j5j{?%Q?fC7 zNlY*L10>D2pbC4cfHiwEm_REOQ^fg9n^G0;l?FQnKxR_^D>fCv_z{AKxGThqauyoc zf;E?=Ptu8rd%3YFY5Rhq6Bv2`ob21~ya3iBOpz6XUKGVoISPr2=@=QQe6U9lz=gEP6aq_navZf6w#l2P8C~(eHx4jkb%hMpe>A65 z3IKXr-ar<>HUP6V6|z?@i!I|%?_Gu^!9cOh&DeA`ZV%^uG*V)@`@>fNSJB6Z`E5K+}iVd zKoAlQ=woES4a0N@-ad8modN3H+0xU1^Ytt(>jY_#5hRjUg~D81corx>Rwe3A%Ii_$ zkR7NgUIBfw+hV|GK5zBUpm8Oduz}SuFsp$x{_Zw|APmcY-wQBg3FY2;Zk1#)VeNp$ zP==9RzmR>VrzdjR`7eNu%Jo`cbx|2_yw;hojL%z^%_Av2X+{l}BuF|YPha~zVIphjXWCDY5LWETZn@UW~9WX}b8TJIf-+|uza|_ad+IM*f+}ge? j6LJXI52N~Y71H#p;9VF6dJ=p`1Ed1JRH9k|8UB9&92svR diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb9@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb9@2x.png deleted file mode 100644 index c990cf0fe6784265e2419070a27459fa6f7b2fa0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17067 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, "Resources/metrics_skin"), audio, true); - defaultSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore(dllStore, "Resources/default_skin"), audio, false); + defaultSkin = skinManager.GetSkin(DefaultLegacySkin.Info); specialSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore(dllStore, "Resources/special_skin"), audio, true); } From 55afcc1e04ef4d48569cf7247195a32a15d0ec72 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 17:53:51 +0900 Subject: [PATCH 2848/5608] Add skin component for the legacy cursor trail --- osu.Game.Rulesets.Osu/OsuSkinComponents.cs | 1 + .../Skinning/LegacyCursorTrail.cs | 24 +++++++++++++++++++ .../Skinning/OsuLegacySkinTransformer.cs | 6 +++++ .../UI/Cursor/CursorTrail.cs | 22 +++++++++++++---- .../UI/Cursor/OsuCursorContainer.cs | 20 ++++++++++++---- 5 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs diff --git a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs index 5971f053c2..8dd48eace0 100644 --- a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs +++ b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs @@ -8,6 +8,7 @@ namespace osu.Game.Rulesets.Osu HitCircle, FollowPoint, Cursor, + CursorTrail, SliderScorePoint, ApproachCircle, ReverseArrow, diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs new file mode 100644 index 0000000000..74746faa44 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs @@ -0,0 +1,24 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Osu.UI.Cursor; +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Osu.Skinning +{ + public class LegacyCursorTrail : CursorTrail + { + public LegacyCursorTrail() + { + Blending = BlendingParameters.Additive; + } + + [BackgroundDependencyLoader] + private void load(ISkinSource skin) + { + Texture = skin.GetTexture("cursortrail"); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 5957b81d7e..b5475f50ef 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -78,6 +78,12 @@ namespace osu.Game.Rulesets.Osu.Skinning return null; + case OsuSkinComponents.CursorTrail: + if (source.GetTexture("cursortrail") != null) + return new LegacyCursorTrail(); + + return null; + case OsuSkinComponents.HitCircleText: var font = GetConfig(OsuSkinConfiguration.HitCircleFont)?.Value ?? "default"; var overlap = GetConfig(OsuSkinConfiguration.HitCircleOverlap)?.Value ?? 0; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index a50c3a2fea..acb7fb8251 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -20,14 +20,28 @@ using osuTK.Graphics.ES30; namespace osu.Game.Rulesets.Osu.UI.Cursor { - internal class CursorTrail : Drawable, IRequireHighFrequencyMousePosition + public class CursorTrail : Drawable, IRequireHighFrequencyMousePosition { private const int max_sprites = 2048; + private Texture texture = Texture.WhitePixel; + + public Texture Texture + { + get => texture; + set + { + if (texture == value) + return; + + texture = value; + Invalidate(Invalidation.DrawNode); + } + } + private readonly TrailPart[] parts = new TrailPart[max_sprites]; private int currentIndex; private IShader shader; - private Texture texture; private double timeOffset; private float time; @@ -47,11 +61,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor } [BackgroundDependencyLoader] - private void load(ShaderManager shaders, TextureStore textures) + private void load(ShaderManager shaders) { shader = shaders.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE); - texture = textures.Get(@"Cursor/cursortrail"); - Scale = new Vector2(1 / texture.ScaleAdjust); } protected override void LoadComplete() diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 893c7875fa..5d68d200ff 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -6,9 +6,12 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Textures; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.UI; +using osu.Game.Skinning; +using osuTK; namespace osu.Game.Rulesets.Osu.UI.Cursor { @@ -22,17 +25,14 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly Bindable showTrail = new Bindable(true); - private readonly CursorTrail cursorTrail; + private readonly Drawable cursorTrail; public OsuCursorContainer() { InternalChild = fadeContainer = new Container { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - cursorTrail = new CursorTrail { Depth = 1 } - } + Child = cursorTrail = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.CursorTrail), _ => new DefaultCursorTrail()) }; } @@ -98,5 +98,15 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint); ActiveCursor.ScaleTo(0.8f, 450, Easing.OutQuint); } + + private class DefaultCursorTrail : CursorTrail + { + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Texture = textures.Get(@"Cursor/cursortrail"); + Scale = new Vector2(1 / Texture.ScaleAdjust); + } + } } } From 2d636ce1472a9e19fa15698a012ac1b60b775f59 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Sep 2019 17:54:53 +0900 Subject: [PATCH 2849/5608] 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 896b10133d..f76297c197 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5f2aad24dc..791d2fe285 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 5027a4ef8c..0560c45edf 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From 195f101799d4ef63af86fdda28df71b6a5d7b52d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 19:00:42 +0900 Subject: [PATCH 2850/5608] Move complex property below ctor --- .../UI/Cursor/CursorTrail.cs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index acb7fb8251..8164816f9f 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -24,21 +24,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { private const int max_sprites = 2048; - private Texture texture = Texture.WhitePixel; - - public Texture Texture - { - get => texture; - set - { - if (texture == value) - return; - - texture = value; - Invalidate(Invalidation.DrawNode); - } - } - private readonly TrailPart[] parts = new TrailPart[max_sprites]; private int currentIndex; private IShader shader; @@ -72,6 +57,21 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor resetTime(); } + private Texture texture = Texture.WhitePixel; + + public Texture Texture + { + get => texture; + set + { + if (texture == value) + return; + + texture = value; + Invalidate(Invalidation.DrawNode); + } + } + public override bool IsPresent => true; protected override void Update() From 1d225ba81e627128d14e16eb2aef9c34304d6f3d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 19:02:10 +0900 Subject: [PATCH 2851/5608] Add FadeDuration to control cursor trail fade --- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 8164816f9f..91bc3278bf 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -72,6 +72,11 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor } } + ///

+ /// The amount of time to fade the cursor trail pieces. + /// + protected virtual double FadeDuration => 300; + public override bool IsPresent => true; protected override void Update() @@ -82,7 +87,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor const int fade_clock_reset_threshold = 1000000; - time = (float)(Time.Current - timeOffset) / 300f; + time = (float)((Time.Current - timeOffset) / FadeDuration); if (time > fade_clock_reset_threshold) resetTime(); } From 3b1b7910bbf50447b82b8d5ba7bce555255ad0a1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 19:22:27 +0900 Subject: [PATCH 2852/5608] Add toggle for cursor trail interpolation --- .../UI/Cursor/CursorTrail.cs | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 91bc3278bf..0998b5d604 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -106,6 +106,11 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private Vector2 size => texture.Size * Scale; + /// + /// Whether to interpolate mouse movements and add trail pieces at intermediate points. + /// + protected virtual bool InterpolateMovements => true; + private Vector2? lastPosition; private readonly InputResampler resampler = new InputResampler(); @@ -126,29 +131,41 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { Trace.Assert(lastPosition.HasValue); - // ReSharper disable once PossibleInvalidOperationException - Vector2 pos1 = lastPosition.Value; - Vector2 diff = pos2 - pos1; - float distance = diff.Length; - Vector2 direction = diff / distance; - - float interval = size.X / 2 * 0.9f; - - for (float d = interval; d < distance; d += interval) + if (InterpolateMovements) { - lastPosition = pos1 + direction * d; + // ReSharper disable once PossibleInvalidOperationException + Vector2 pos1 = lastPosition.Value; + Vector2 diff = pos2 - pos1; + float distance = diff.Length; + Vector2 direction = diff / distance; - parts[currentIndex].Position = lastPosition.Value; - parts[currentIndex].Time = time; - ++parts[currentIndex].InvalidationID; + float interval = size.X / 2 * 0.9f; - currentIndex = (currentIndex + 1) % max_sprites; + for (float d = interval; d < distance; d += interval) + { + lastPosition = pos1 + direction * d; + addPart(lastPosition.Value); + } + } + else + { + lastPosition = pos2; + addPart(lastPosition.Value); } } return base.OnMouseMove(e); } + private void addPart(Vector2 screenSpacePosition) + { + parts[currentIndex].Position = screenSpacePosition; + parts[currentIndex].Time = time; + ++parts[currentIndex].InvalidationID; + + currentIndex = (currentIndex + 1) % max_sprites; + } + protected override DrawNode CreateDrawNode() => new TrailDrawNode(this); private struct TrailPart From 292d50aacfed96eb19e83b6775515ef74b933c74 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 19:22:44 +0900 Subject: [PATCH 2853/5608] Don't confine the cursor trail --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 5d68d200ff..a944ff88c6 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor InternalChild = fadeContainer = new Container { RelativeSizeAxes = Axes.Both, - Child = cursorTrail = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.CursorTrail), _ => new DefaultCursorTrail()) + Child = cursorTrail = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.CursorTrail), _ => new DefaultCursorTrail(), confineMode: ConfineMode.NoScaling) }; } From a200485fbd0db1b2a4b429bb15620c8174cc4a9f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 19:23:02 +0900 Subject: [PATCH 2854/5608] Implement disjoint (old style) cursor trails --- .../Skinning/LegacyCursorTrail.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs index 74746faa44..d2018ea720 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Skinning; @@ -10,6 +11,11 @@ namespace osu.Game.Rulesets.Osu.Skinning { public class LegacyCursorTrail : CursorTrail { + private const double disjoint_trail_time_separation = 1000 / 60.0; + + private bool disjointTrail; + private double lastTrailTime; + public LegacyCursorTrail() { Blending = BlendingParameters.Additive; @@ -19,6 +25,31 @@ namespace osu.Game.Rulesets.Osu.Skinning private void load(ISkinSource skin) { Texture = skin.GetTexture("cursortrail"); + disjointTrail = skin.GetTexture("cursormiddle") == null; + + if (disjointTrail && Texture != null) + { + // stable "magic ratio". see OsuPlayfieldAdjustmentContainer for full explanation. + Texture.ScaleAdjust *= 1.6f; + } + } + + protected override double FadeDuration => disjointTrail ? 150 : 500; + + protected override bool InterpolateMovements => !disjointTrail; + + protected override bool OnMouseMove(MouseMoveEvent e) + { + if (!disjointTrail) + return base.OnMouseMove(e); + + if (Time.Current - lastTrailTime >= disjoint_trail_time_separation) + { + lastTrailTime = Time.Current; + return base.OnMouseMove(e); + } + + return false; } } } From e3b972187e7bfa966b0efc1d29adabcdb9875088 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 19:30:31 +0900 Subject: [PATCH 2855/5608] Fix incorrect cursor trail size + scale --- .../UI/Cursor/CursorTrail.cs | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 0998b5d604..7975982aec 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -5,6 +5,7 @@ using System; using System.Diagnostics; using System.Runtime.InteropServices; using osu.Framework.Allocation; +using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Batches; using osu.Framework.Graphics.OpenGL.Vertices; @@ -72,6 +73,20 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor } } + private readonly Cached partSizeCache = new Cached(); + + private Vector2 partSize => partSizeCache.IsValid + ? partSizeCache.Value + : (partSizeCache.Value = new Vector2(Texture.DisplayWidth, Texture.DisplayHeight) * DrawInfo.Matrix.ExtractScale().Xy); + + public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) + { + if ((invalidation & (Invalidation.DrawInfo | Invalidation.RequiredParentSizeToFit | Invalidation.Presence)) > 0) + partSizeCache.Invalidate(); + + return base.Invalidate(invalidation, source, shallPropagate); + } + /// /// The amount of time to fade the cursor trail pieces. /// @@ -104,8 +119,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor timeOffset = Time.Current; } - private Vector2 size => texture.Size * Scale; - /// /// Whether to interpolate mouse movements and add trail pieces at intermediate points. /// @@ -139,7 +152,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor float distance = diff.Length; Vector2 direction = diff / distance; - float interval = size.X / 2 * 0.9f; + float interval = partSize.X / 2 * 0.9f; for (float d = interval; d < distance; d += interval) { @@ -202,7 +215,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor shader = Source.shader; texture = Source.texture; - size = Source.size; + size = Source.partSize; time = Source.time; for (int i = 0; i < Source.parts.Length; ++i) From 0790e9e377582117b70688865efa2abcfba2859b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2019 11:35:26 +0000 Subject: [PATCH 2856/5608] Bump ppy.osu.Framework.iOS from 2019.905.0 to 2019.909.0 Bumps [ppy.osu.Framework.iOS](https://github.com/ppy/osu-framework) from 2019.905.0 to 2019.909.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.905.0...2019.909.0) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 5027a4ef8c..5645862bf7 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -119,7 +119,7 @@ - + From 7a7c3d21a1a158691daaf39005268e5acdd3b26d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2019 11:36:58 +0000 Subject: [PATCH 2857/5608] Bump ppy.osu.Framework from 2019.905.0 to 2019.909.0 Bumps [ppy.osu.Framework](https://github.com/ppy/osu-framework) from 2019.905.0 to 2019.909.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.905.0...2019.909.0) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5f2aad24dc..791d2fe285 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 5027a4ef8c..77756dfd87 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,7 +118,7 @@ - + From 3b4750ab9e54033fed4a358041e9b15124feb643 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2019 11:37:09 +0000 Subject: [PATCH 2858/5608] Bump ppy.osu.Framework.Android from 2019.905.0 to 2019.909.0 Bumps [ppy.osu.Framework.Android](https://github.com/ppy/osu-framework) from 2019.905.0 to 2019.909.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.905.0...2019.909.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index 896b10133d..f76297c197 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + From c4aee11fe08c60db192388be63cad4287cb70f65 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 9 Sep 2019 15:35:18 +0300 Subject: [PATCH 2859/5608] Revert renaming changes --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 4 ++-- .../Objects/Drawables/Pieces/SpinnerDisc.cs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs index 5d7acb77bb..3ed3f3e981 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Tests if (auto && !userTriggered && Time.Current > Spinner.StartTime + Spinner.Duration / 2 && Progress < 1) { // force completion only once to not break human interaction - Disc.BidirectionalRotation = Spinner.SpinsRequired * 360; + Disc.RotationAbsolute = Spinner.SpinsRequired * 360; auto = false; } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index a8dc275fb5..49aaa2aaea 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindTo(HitObject.PositionBindable); } - public float Progress => MathHelper.Clamp(Disc.BidirectionalRotation / 360 / Spinner.SpinsRequired, 0, 1); + public float Progress => MathHelper.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); protected override void CheckForResult(bool userTriggered, double timeOffset) { @@ -188,7 +188,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circle.Rotation = Disc.Rotation; Ticks.Rotation = Disc.Rotation; - spmCounter.SetRotation(Disc.BidirectionalRotation); + spmCounter.SetRotation(Disc.RotationAbsolute); float relativeCircleScale = Spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight; Disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index 5b2b3bcd42..2ae420a5e2 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -82,12 +82,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private float lastAngle; private float currentRotation; - public float BidirectionalRotation; + public float RotationAbsolute; private int completeTick; private double lastTime; - private bool updateCompleteTick() => completeTick != (completeTick = (int)(BidirectionalRotation / 360)); + private bool updateCompleteTick() => completeTick != (completeTick = (int)(RotationAbsolute / 360)); private bool rotationTransferred; @@ -113,8 +113,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces lastAngle -= 360; currentRotation += thisAngle - lastAngle; - BidirectionalRotation += Math.Abs(thisAngle - lastAngle) * Math.Sign(Time.Current - lastTime); lastTime = Time.Current; + RotationAbsolute += Math.Abs(thisAngle - lastAngle) * Math.Sign(Clock.ElapsedFrameTime); } lastAngle = thisAngle; From aec04dcf904cc1a8ba2f80b6298f82ef3e419b57 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 9 Sep 2019 15:36:20 +0300 Subject: [PATCH 2860/5608] Use Clock.ElapsedFrameTime instead --- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index 2ae420a5e2..c45e98cc76 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -85,8 +85,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public float RotationAbsolute; private int completeTick; - private double lastTime; - private bool updateCompleteTick() => completeTick != (completeTick = (int)(RotationAbsolute / 360)); private bool rotationTransferred; @@ -113,7 +111,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces lastAngle -= 360; currentRotation += thisAngle - lastAngle; - lastTime = Time.Current; RotationAbsolute += Math.Abs(thisAngle - lastAngle) * Math.Sign(Clock.ElapsedFrameTime); } From 0ec642d8261d347ab5b4520f44259747185fb400 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Sep 2019 01:06:37 +0900 Subject: [PATCH 2861/5608] Show instead of toggle --- osu.Game/Screens/Menu/MainMenu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 4c3566b3e9..65df98551d 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -154,7 +154,7 @@ namespace osu.Game.Screens.Menu logo.Action += () => { if (!api.IsLoggedIn && !loginPrompted) - login?.ToggleVisibility(); + login?.Show(); loginPrompted = true; From f398f134e171e8284c6b8b3f5b66b10df813ffbe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Sep 2019 01:12:30 +0900 Subject: [PATCH 2862/5608] Remove unnecessary bool storage Also delay show slightly for better user experience. --- osu.Game/Screens/Menu/MainMenu.cs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 65df98551d..978a1bffcd 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -39,8 +39,6 @@ namespace osu.Game.Screens.Menu private ButtonSystem buttons; - private bool loginPrompted; - [Resolved] private GameHost host { get; set; } @@ -151,16 +149,6 @@ namespace osu.Game.Screens.Menu logo.FadeColour(Color4.White, 100, Easing.OutQuint); logo.FadeIn(100, Easing.OutQuint); - logo.Action += () => - { - if (!api.IsLoggedIn && !loginPrompted) - login?.Show(); - - loginPrompted = true; - - return true; - }; - if (resuming) { buttons.State = ButtonSystemState.TopLevel; @@ -170,6 +158,14 @@ namespace osu.Game.Screens.Menu sideFlashes.Delay(FADE_IN_DURATION).FadeIn(64, Easing.InQuint); } + else if (!api.IsLoggedIn) + { + logo.Action += () => + { + Scheduler.AddDelayed(() => login?.Show(), 500); + return true; + }; + } } protected override void LogoSuspending(OsuLogo logo) From 7eb20da820128defcfd3c9a3738f5ee5b3f3b861 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Sep 2019 01:17:58 +0900 Subject: [PATCH 2863/5608] Add back local bool (required due to action limitations) --- osu.Game/Screens/Menu/MainMenu.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 978a1bffcd..18a3de7f37 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -140,6 +140,8 @@ namespace osu.Game.Screens.Menu Beatmap.ValueChanged += beatmap_ValueChanged; } + private bool loginDisplayed = false; + protected override void LogoArriving(OsuLogo logo, bool resuming) { base.LogoArriving(logo, resuming); @@ -160,11 +162,18 @@ namespace osu.Game.Screens.Menu } else if (!api.IsLoggedIn) { - logo.Action += () => + logo.Action += displayLogin; + } + + bool displayLogin() + { + if (!loginDisplayed) { Scheduler.AddDelayed(() => login?.Show(), 500); - return true; - }; + loginDisplayed = true; + } + + return true; } } From 98e384129c578742fb88408d7b00c2a69cd223a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Sep 2019 01:34:48 +0900 Subject: [PATCH 2864/5608] Remove redundant initialisation --- osu.Game/Screens/Menu/MainMenu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 18a3de7f37..a006877082 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -140,7 +140,7 @@ namespace osu.Game.Screens.Menu Beatmap.ValueChanged += beatmap_ValueChanged; } - private bool loginDisplayed = false; + private bool loginDisplayed; protected override void LogoArriving(OsuLogo logo, bool resuming) { From 22fabef344c41920820a662bfc37009675c12207 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 9 Sep 2019 19:52:31 +0300 Subject: [PATCH 2865/5608] Use TestWorkingBeatmap in BeatmapDetailsArea tests --- .../SongSelect/TestSceneBeatmapDetailArea.cs | 80 +++++++++---------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index 7b97a27732..ed9e01a67e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Screens.Select; +using osu.Game.Tests.Beatmaps; using osuTK; namespace osu.Game.Tests.Visual.SongSelect @@ -30,45 +31,44 @@ namespace osu.Game.Tests.Visual.SongSelect Size = new Vector2(550f, 450f), }); - AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("all metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap + { + BeatmapInfo = { - BeatmapSetInfo = + BeatmapSet = new BeatmapSetInfo { Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } }, - BeatmapInfo = + Version = "All Metrics", + Metadata = new BeatmapMetadata { - Version = "All Metrics", - Metadata = new BeatmapMetadata - { - Source = "osu!lazer", - Tags = "this beatmap has all the metrics", - }, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 7, - DrainRate = 1, - OverallDifficulty = 5.7f, - ApproachRate = 3.5f, - }, - StarDifficulty = 5.3f, - Metrics = new BeatmapMetrics - { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, - } + Source = "osu!lazer", + Tags = "this beatmap has all the metrics", + }, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 7, + DrainRate = 1, + OverallDifficulty = 5.7f, + ApproachRate = 3.5f, + }, + StarDifficulty = 5.3f, + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + }, } - ); + })); - AddStep("all except source", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("all except source", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { - BeatmapSetInfo = - { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } - }, BeatmapInfo = { + BeatmapSet = new BeatmapSetInfo + { + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + }, Version = "All Metrics", Metadata = new BeatmapMetadata { @@ -88,16 +88,16 @@ namespace osu.Game.Tests.Visual.SongSelect Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, } - }); + })); - AddStep("ratings", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("ratings", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { - BeatmapSetInfo = - { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } - }, BeatmapInfo = { + BeatmapSet = new BeatmapSetInfo + { + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + }, Version = "Only Ratings", Metadata = new BeatmapMetadata { @@ -113,9 +113,9 @@ namespace osu.Game.Tests.Visual.SongSelect }, StarDifficulty = 4.8f } - }); + })); - AddStep("fails+retries", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("fails+retries", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { BeatmapInfo = { @@ -139,9 +139,9 @@ namespace osu.Game.Tests.Visual.SongSelect Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, } - }); + })); - AddStep("null metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("null metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { BeatmapInfo = { @@ -160,7 +160,7 @@ namespace osu.Game.Tests.Visual.SongSelect }, StarDifficulty = 1.97f, } - }); + })); AddStep("null beatmap", () => detailsArea.Beatmap = null); } From b77550625c86360b5c98618eb61dec642c4824dd Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 9 Sep 2019 20:04:04 +0300 Subject: [PATCH 2866/5608] Check if DummyWorkingBeatmap is selected instead --- osu.Game/Screens/Select/BeatmapDetailArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index bf8fc8cf07..5348de68d6 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Select { beatmap = value; Details.Beatmap = beatmap?.BeatmapInfo; - Leaderboard.Beatmap = beatmap is NoBeatmapsAvailableWorkingBeatmap ? null : beatmap?.BeatmapInfo; + Leaderboard.Beatmap = beatmap is DummyWorkingBeatmap ? null : beatmap?.BeatmapInfo; } } From 65869c7ebba728b9727d53fcf39caf11c68c9d67 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 10 Sep 2019 04:04:37 +0300 Subject: [PATCH 2867/5608] Refactor LeaderboardScopeSelector for more extensibility --- .../UserInterface/GradientLineTabControl.cs | 129 ++++++++++++++++++ .../BeatmapSet/LeaderboardScopeSelector.cs | 93 +------------ 2 files changed, 131 insertions(+), 91 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/GradientLineTabControl.cs diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs new file mode 100644 index 0000000000..f4c43b0222 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -0,0 +1,129 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osuTK; +using osu.Framework.Graphics.Shapes; +using osuTK.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Input.Events; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; + +namespace osu.Game.Graphics.UserInterface +{ + public class GradientLineTabControl : PageTabControl + { + protected override Dropdown CreateDropdown() => null; + + protected override TabItem CreateTabItem(TModel value) => new ScopeSelectorTabItem(value); + + protected Color4 LineColour + { + get => line.MainColour.Value; + set => line.MainColour.Value = value; + } + + private readonly GradientLine line; + + public GradientLineTabControl() + { + RelativeSizeAxes = Axes.X; + + AddInternal(line = new GradientLine + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + }); + } + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20, 0), + }; + + private class ScopeSelectorTabItem : PageTabItem + { + public ScopeSelectorTabItem(TModel value) + : base(value) + { + Text.Font = OsuFont.GetFont(size: 16); + } + + protected override bool OnHover(HoverEvent e) + { + Text.FadeColour(AccentColour); + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + Text.FadeColour(Color4.White); + } + } + + private class GradientLine : GridContainer + { + public readonly Bindable MainColour = new Bindable(); + + private readonly Box left; + private readonly Box middle; + private readonly Box right; + + public GradientLine() + { + RelativeSizeAxes = Axes.X; + Size = new Vector2(0.8f, 1.5f); + + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(mode: GridSizeMode.Relative, size: 0.4f), + new Dimension(), + }; + + Content = new[] + { + new Drawable[] + { + left = new Box + { + RelativeSizeAxes = Axes.Both, + }, + middle = new Box + { + RelativeSizeAxes = Axes.Both, + }, + right = new Box + { + RelativeSizeAxes = Axes.Both, + }, + } + }; + } + + protected override void LoadComplete() + { + MainColour.BindValueChanged(onColourChanged, true); + base.LoadComplete(); + } + + private void onColourChanged(ValueChangedEvent colour) + { + left.Colour = ColourInfo.GradientHorizontal(colour.NewValue.Opacity(0), colour.NewValue); + middle.Colour = colour.NewValue; + right.Colour = ColourInfo.GradientHorizontal(colour.NewValue, colour.NewValue.Opacity(0)); + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index dcd58db427..bdcd5c21b9 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -1,119 +1,30 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics.UserInterface; using osu.Game.Screens.Select.Leaderboards; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osuTK; using osu.Game.Graphics.UserInterface; -using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Framework.Allocation; using osuTK.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Input.Events; namespace osu.Game.Overlays.BeatmapSet { - public class LeaderboardScopeSelector : PageTabControl + public class LeaderboardScopeSelector : GradientLineTabControl { protected override bool AddEnumEntriesAutomatically => false; - protected override Dropdown CreateDropdown() => null; - - protected override TabItem CreateTabItem(BeatmapLeaderboardScope value) => new ScopeSelectorTabItem(value); - public LeaderboardScopeSelector() { - RelativeSizeAxes = Axes.X; - AddItem(BeatmapLeaderboardScope.Global); AddItem(BeatmapLeaderboardScope.Country); AddItem(BeatmapLeaderboardScope.Friend); - - AddInternal(new GradientLine - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - }); } [BackgroundDependencyLoader] private void load(OsuColour colours) { AccentColour = colours.Blue; - } - - protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(20, 0), - }; - - private class ScopeSelectorTabItem : PageTabItem - { - public ScopeSelectorTabItem(BeatmapLeaderboardScope value) - : base(value) - { - Text.Font = OsuFont.GetFont(size: 16); - } - - protected override bool OnHover(HoverEvent e) - { - Text.FadeColour(AccentColour); - - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - - Text.FadeColour(Color4.White); - } - } - - private class GradientLine : GridContainer - { - public GradientLine() - { - RelativeSizeAxes = Axes.X; - Size = new Vector2(0.8f, 1.5f); - - ColumnDimensions = new[] - { - new Dimension(), - new Dimension(mode: GridSizeMode.Relative, size: 0.4f), - new Dimension(), - }; - - Content = new[] - { - new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4.Transparent, Color4.Gray), - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Gray, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4.Gray, Color4.Transparent), - }, - } - }; - } + LineColour = Color4.Gray; } } } From 03bd7ca8e72a88d2551887b742281374bec2ee14 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 10 Sep 2019 04:20:32 +0300 Subject: [PATCH 2868/5608] Implement RankingsScopeSelector --- .../Online/TestSceneRankingsScopeSelector.cs | 53 +++++++++++++++++++ .../UserInterface/GradientLineTabControl.cs | 26 --------- .../BeatmapSet/LeaderboardScopeSelector.cs | 28 ++++++++++ osu.Game/Overlays/RankingsScopeSelector.cs | 26 +++++++++ 4 files changed, 107 insertions(+), 26 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs create mode 100644 osu.Game/Overlays/RankingsScopeSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs new file mode 100644 index 0000000000..1488addb09 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs @@ -0,0 +1,53 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Bindables; +using osu.Game.Overlays; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Framework.Extensions.Color4Extensions; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsScopeSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RankingsScopeSelector), + }; + + private readonly Box background; + + public TestSceneRankingsScopeSelector() + { + Bindable scope = new Bindable(); + + Add(background = new Box + { + RelativeSizeAxes = Axes.Both + }); + + Add(new RankingsScopeSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = scope } + }); + + AddStep(@"Select country", () => scope.Value = RankingsScope.Country); + AddStep(@"Select performance", () => scope.Value = RankingsScope.Performance); + AddStep(@"Select score", () => scope.Value = RankingsScope.Score); + AddStep(@"Select spotlights", () => scope.Value = RankingsScope.Spotlights); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.Yellow.Opacity(50); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs index f4c43b0222..7cd8d2c5bd 100644 --- a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -8,7 +8,6 @@ using osuTK; using osu.Framework.Graphics.Shapes; using osuTK.Graphics; using osu.Framework.Graphics.Colour; -using osu.Framework.Input.Events; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -18,8 +17,6 @@ namespace osu.Game.Graphics.UserInterface { protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(TModel value) => new ScopeSelectorTabItem(value); - protected Color4 LineColour { get => line.MainColour.Value; @@ -49,29 +46,6 @@ namespace osu.Game.Graphics.UserInterface Spacing = new Vector2(20, 0), }; - private class ScopeSelectorTabItem : PageTabItem - { - public ScopeSelectorTabItem(TModel value) - : base(value) - { - Text.Font = OsuFont.GetFont(size: 16); - } - - protected override bool OnHover(HoverEvent e) - { - Text.FadeColour(AccentColour); - - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - - Text.FadeColour(Color4.White); - } - } - private class GradientLine : GridContainer { public readonly Bindable MainColour = new Bindable(); diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index bdcd5c21b9..e2a725ec46 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -6,6 +6,9 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Graphics; using osu.Framework.Allocation; using osuTK.Graphics; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Framework.Graphics; namespace osu.Game.Overlays.BeatmapSet { @@ -13,6 +16,8 @@ namespace osu.Game.Overlays.BeatmapSet { protected override bool AddEnumEntriesAutomatically => false; + protected override TabItem CreateTabItem(BeatmapLeaderboardScope value) => new ScopeSelectorTabItem(value); + public LeaderboardScopeSelector() { AddItem(BeatmapLeaderboardScope.Global); @@ -26,5 +31,28 @@ namespace osu.Game.Overlays.BeatmapSet AccentColour = colours.Blue; LineColour = Color4.Gray; } + + private class ScopeSelectorTabItem : PageTabItem + { + public ScopeSelectorTabItem(BeatmapLeaderboardScope value) + : base(value) + { + Text.Font = OsuFont.GetFont(size: 16); + } + + protected override bool OnHover(HoverEvent e) + { + Text.FadeColour(AccentColour); + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + Text.FadeColour(Color4.White); + } + } } } diff --git a/osu.Game/Overlays/RankingsScopeSelector.cs b/osu.Game/Overlays/RankingsScopeSelector.cs new file mode 100644 index 0000000000..5935876ec9 --- /dev/null +++ b/osu.Game/Overlays/RankingsScopeSelector.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Graphics.UserInterface; +using osu.Framework.Allocation; +using osuTK.Graphics; + +namespace osu.Game.Overlays +{ + public class RankingsScopeSelector : GradientLineTabControl + { + [BackgroundDependencyLoader] + private void load() + { + AccentColour = LineColour = Color4.Black; + } + } + + public enum RankingsScope + { + Performance, + Spotlights, + Score, + Country + } +} From f505a3ff1d48efea15967e3c322f6203fb8bf1cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Sep 2019 11:44:11 +0900 Subject: [PATCH 2869/5608] Mark AutoGeneration tests as headless --- osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs index 20ac5eaa39..f260357df5 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs @@ -3,6 +3,7 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Testing; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Replays; @@ -12,6 +13,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests { [TestFixture] + [HeadlessTest] public class TestSceneAutoGeneration : OsuTestScene { [Test] From af3bb5a2cdf7084cc14a988a0610e636438ad4fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Sep 2019 13:29:50 +0900 Subject: [PATCH 2870/5608] Centralise and share bar line generation code between rulesets --- .../TestSceneStage.cs | 4 +- osu.Game.Rulesets.Mania/Objects/BarLine.cs | 21 ------- .../Objects/Drawables/DrawableBarLine.cs | 9 ++- .../UI/DrawableManiaRuleset.cs | 33 +---------- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 1 + osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 1 + osu.Game.Rulesets.Taiko/Objects/BarLine.cs | 9 --- .../Objects/Drawables/DrawableBarLine.cs | 3 +- .../Objects/Drawables/DrawableBarLineMajor.cs | 1 + .../UI/DrawableTaikoRuleset.cs | 47 +-------------- osu.Game/Rulesets/Objects/BarLine.cs | 16 +++++ osu.Game/Rulesets/Objects/BarLineGenerator.cs | 58 +++++++++++++++++++ 12 files changed, 89 insertions(+), 114 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Objects/BarLine.cs delete mode 100644 osu.Game.Rulesets.Taiko/Objects/BarLine.cs create mode 100644 osu.Game/Rulesets/Objects/BarLine.cs create mode 100644 osu.Game/Rulesets/Objects/BarLineGenerator.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs index 395e6daf0a..e7fd601abe 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Tests.Visual; using osuTK; @@ -114,8 +115,7 @@ namespace osu.Game.Rulesets.Mania.Tests var obj = new BarLine { StartTime = Time.Current + 2000, - ControlPoint = new TimingControlPoint(), - BeatIndex = major ? 0 : 1 + Major = major, }; obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); diff --git a/osu.Game.Rulesets.Mania/Objects/BarLine.cs b/osu.Game.Rulesets.Mania/Objects/BarLine.cs deleted file mode 100644 index 4c644a8f09..0000000000 --- a/osu.Game.Rulesets.Mania/Objects/BarLine.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Beatmaps.ControlPoints; - -namespace osu.Game.Rulesets.Mania.Objects -{ - public class BarLine : ManiaHitObject - { - /// - /// The control point which this bar line is part of. - /// - public TimingControlPoint ControlPoint; - - /// - /// The index of the beat which this bar line represents within the control point. - /// This is a "major" bar line if % == 0. - /// - public int BeatIndex; - } -} diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index e9c352c97e..862af8d15b 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -4,6 +4,7 @@ using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osuTK.Graphics; @@ -13,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// Visualises a . Although this derives DrawableManiaHitObject, /// this does not handle input/sound like a normal hit object. ///
- public class DrawableBarLine : DrawableManiaHitObject + public class DrawableBarLine : DrawableHitObject { /// /// Height of major bar line triangles. @@ -40,9 +41,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Colour = new Color4(255, 204, 33, 255), }); - bool isMajor = barLine.BeatIndex % (int)barLine.ControlPoint.TimeSignature == 0; - - if (isMajor) + if (barLine.Major) { AddInternal(new EquilateralTriangle { @@ -65,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }); } - if (!isMajor && barLine.BeatIndex % 2 == 1) + if (!barLine.Major) Alpha = 0.2f; } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index f26526fe70..29863fba2e 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -2,14 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Input; -using osu.Framework.MathUtils; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Input.Handlers; using osu.Game.Replays; using osu.Game.Rulesets.Mania.Beatmaps; @@ -19,8 +16,8 @@ using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; @@ -45,33 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI public DrawableManiaRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { - // Generate the bar lines - double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; - - var timingPoints = Beatmap.ControlPointInfo.TimingPoints; - var barLines = new List(); - - for (int i = 0; i < timingPoints.Count; i++) - { - TimingControlPoint point = timingPoints[i]; - - // Stop on the beat before the next timing point, or if there is no next timing point stop slightly past the last object - double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - point.BeatLength : lastObjectTime + point.BeatLength * (int)point.TimeSignature; - - int index = 0; - - for (double t = timingPoints[i].Time; Precision.DefinitelyBigger(endTime, t); t += point.BeatLength, index++) - { - barLines.Add(new BarLine - { - StartTime = t, - ControlPoint = point, - BeatIndex = index - }); - } - } - - BarLines = barLines; + BarLines = new BarLineGenerator(Beatmap).BarLines; } [BackgroundDependencyLoader] diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 5ab07416a6..12faa499ad 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using osuTK; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index a28de7ea58..98a4b7d0b6 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; diff --git a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs deleted file mode 100644 index a07012fd71..0000000000 --- a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Rulesets.Taiko.Objects -{ - public class BarLine : TaikoHitObject - { - } -} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index bf89f7e15b..1a5a797f28 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; using osuTK; using osu.Game.Rulesets.Objects.Drawables; @@ -11,7 +12,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// A line that scrolls alongside hit objects in the playfield and visualises control points. /// - public class DrawableBarLine : DrawableHitObject + public class DrawableBarLine : DrawableHitObject { /// /// The width of the line tracker. diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs index 4d3a1a3f8a..f5b75a781b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index b03bea578e..5caa9e4626 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -5,19 +5,18 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Taiko.Replays; -using System.Linq; using osu.Framework.Input; using osu.Game.Configuration; using osu.Game.Input.Handlers; using osu.Game.Replays; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI @@ -38,49 +37,7 @@ namespace osu.Game.Rulesets.Taiko.UI [BackgroundDependencyLoader] private void load() { - loadBarLines(); - } - - private void loadBarLines() - { - TaikoHitObject lastObject = Beatmap.HitObjects[Beatmap.HitObjects.Count - 1]; - double lastHitTime = 1 + ((lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime); - - var timingPoints = Beatmap.ControlPointInfo.TimingPoints.ToList(); - - if (timingPoints.Count == 0) - return; - - int currentIndex = 0; - int currentBeat = 0; - double time = timingPoints[currentIndex].Time; - - while (time <= lastHitTime) - { - int nextIndex = currentIndex + 1; - - if (nextIndex < timingPoints.Count && time > timingPoints[nextIndex].Time) - { - currentIndex = nextIndex; - time = timingPoints[currentIndex].Time; - currentBeat = 0; - } - - var currentPoint = timingPoints[currentIndex]; - - var barLine = new BarLine - { - StartTime = time, - }; - - barLine.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty); - - bool isMajor = currentBeat % (int)currentPoint.TimeSignature == 0; - Playfield.Add(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine)); - - time += currentPoint.BeatLength * (int)currentPoint.TimeSignature; - currentBeat++; - } + new BarLineGenerator(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar.Major ? new DrawableBarLineMajor(bar) : new DrawableBarLine(bar))); } public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); diff --git a/osu.Game/Rulesets/Objects/BarLine.cs b/osu.Game/Rulesets/Objects/BarLine.cs new file mode 100644 index 0000000000..a5c716e127 --- /dev/null +++ b/osu.Game/Rulesets/Objects/BarLine.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Objects +{ + /// + /// A hit object representing the end of a bar. + /// + public class BarLine : HitObject + { + /// + /// Whether this barline is a prominent beat (based on time signature of beatmap). + /// + public bool Major; + } +} diff --git a/osu.Game/Rulesets/Objects/BarLineGenerator.cs b/osu.Game/Rulesets/Objects/BarLineGenerator.cs new file mode 100644 index 0000000000..ce571d7b17 --- /dev/null +++ b/osu.Game/Rulesets/Objects/BarLineGenerator.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 System.Collections.Generic; +using System.Linq; +using osu.Framework.MathUtils; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Rulesets.Objects +{ + public class BarLineGenerator + { + /// + /// The generated bar lines. + /// + public readonly List BarLines = new List(); + + /// + /// Constructs and generates bar lines for provided beatmap. + /// + /// The beatmap to generate bar lines for. + public BarLineGenerator(IBeatmap beatmap) + { + if (beatmap.HitObjects.Count == 0) + return; + + HitObject lastObject = beatmap.HitObjects.Last(); + double lastHitTime = 1 + ((lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime); + + var timingPoints = beatmap.ControlPointInfo.TimingPoints; + + if (timingPoints.Count == 0) + return; + + for (int i = 0; i < timingPoints.Count; i++) + { + TimingControlPoint currentTimingPoint = timingPoints[i]; + int currentBeat = 0; + + // Stop on the beat before the next timing point, or if there is no next timing point stop slightly past the last object + double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - currentTimingPoint.BeatLength : lastHitTime + currentTimingPoint.BeatLength * (int)currentTimingPoint.TimeSignature; + + double barLength = currentTimingPoint.BeatLength * (int)currentTimingPoint.TimeSignature; + + for (double t = currentTimingPoint.Time; Precision.DefinitelyBigger(endTime, t); t += barLength, currentBeat++) + { + BarLines.Add(new BarLine + { + StartTime = t, + Major = currentBeat % (int)currentTimingPoint.TimeSignature == 0 + }); + } + } + } + } +} From ef90914f581311f17bc689dea4cf83b7f96e01de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Sep 2019 15:27:40 +0900 Subject: [PATCH 2871/5608] Fix mania notes test scene not visually displaying --- osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index 031abb08e2..8dae5e6d84 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.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; @@ -11,6 +11,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; @@ -40,6 +41,7 @@ namespace osu.Game.Rulesets.Mania.Tests { Child = new FillFlowContainer { + Clock = new FramedClock(new ManualClock()), Anchor = Anchor.Centre, Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, @@ -62,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Tests private Drawable createNoteDisplay(ScrollingDirection direction, int identifier, out DrawableNote hitObject) { - var note = new Note { StartTime = 999999999 }; + var note = new Note { StartTime = 0 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new ScrollingTestContainer(direction) @@ -77,7 +79,7 @@ namespace osu.Game.Rulesets.Mania.Tests private Drawable createHoldNoteDisplay(ScrollingDirection direction, int identifier, out DrawableHoldNote hitObject) { - var note = new HoldNote { StartTime = 999999999, Duration = 5000 }; + var note = new HoldNote { StartTime = 0, Duration = 5000 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new ScrollingTestContainer(direction) @@ -133,7 +135,7 @@ namespace osu.Game.Rulesets.Mania.Tests Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Both, Width = 1.25f, - Colour = Color4.Black.Opacity(0.5f) + Colour = Color4.Green.Opacity(0.5f) }, content = new Container { RelativeSizeAxes = Axes.Both } } From 01fd08cba92f1e7c96878147259b1c2b6411abab Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Sep 2019 17:11:16 +0900 Subject: [PATCH 2872/5608] Fix broken positioning of effected usernames --- osu.Game/Overlays/Chat/ChatLine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 4c37d626c0..d125da8e92 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -148,8 +148,8 @@ namespace osu.Game.Overlays.Chat }, new MessageSender(message.Sender) { + AutoSizeAxes = Axes.Both, Padding = new MarginPadding { Left = timestamp_padding }, - RelativeSizeAxes = Axes.Both, Origin = Anchor.TopRight, Anchor = Anchor.TopRight, Child = effectedUsername, From 717a287d692e207e08231eec334f29076ad82b0c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Sep 2019 17:11:26 +0900 Subject: [PATCH 2873/5608] Use real ellipsis character --- osu.Game/Overlays/Chat/ChatLine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index d125da8e92..7596231a3d 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -90,7 +90,7 @@ namespace osu.Game.Overlays.Chat Shadow = false, Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length], Truncate = true, - EllipsisString = ".. :", + EllipsisString = "… :", Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, From 36d3736e1dde496c2a1446f31a176dcf7d5a90f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Sep 2019 18:06:24 +0900 Subject: [PATCH 2874/5608] Fix hitcircle font prefix not being read for legacy skins --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs | 2 +- osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 5957b81d7e..6b6a08ed21 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Skinning return null; case OsuSkinComponents.HitCircleText: - var font = GetConfig(OsuSkinConfiguration.HitCircleFont)?.Value ?? "default"; + var font = GetConfig(OsuSkinConfiguration.HitCirclePrefix)?.Value ?? "default"; var overlap = GetConfig(OsuSkinConfiguration.HitCircleOverlap)?.Value ?? 0; return !hasFont(font) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs index a6b87150ae..e7b686d27d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs @@ -5,7 +5,7 @@ namespace osu.Game.Rulesets.Osu.Skinning { public enum OsuSkinConfiguration { - HitCircleFont, + HitCirclePrefix, HitCircleOverlap, SliderBorderSize, SliderPathRadius, From 1969c5b89bccc3788a295d14ecc8e83412b58da7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 10 Sep 2019 16:36:05 +0300 Subject: [PATCH 2875/5608] Apply suggetsted changes --- .../Online/TestSceneRankingsScopeSelector.cs | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs index 1488addb09..93a00e1d06 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs @@ -9,7 +9,6 @@ using osu.Game.Overlays; using osu.Framework.Graphics.Shapes; using osu.Framework.Allocation; using osu.Game.Graphics; -using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Tests.Visual.Online { @@ -24,18 +23,20 @@ namespace osu.Game.Tests.Visual.Online public TestSceneRankingsScopeSelector() { - Bindable scope = new Bindable(); + var scope = new Bindable(); - Add(background = new Box + AddRange(new Drawable[] { - RelativeSizeAxes = Axes.Both - }); - - Add(new RankingsScopeSelector - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Current = { BindTarget = scope } + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new RankingsScopeSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = scope } + } }); AddStep(@"Select country", () => scope.Value = RankingsScope.Country); @@ -47,7 +48,7 @@ namespace osu.Game.Tests.Visual.Online [BackgroundDependencyLoader] private void load(OsuColour colours) { - background.Colour = colours.Yellow.Opacity(50); + background.Colour = colours.GreySeafoam; } } } From e682ca4fd9a17cf90ac083ec5ff8faf317606b59 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 12:51:54 +0900 Subject: [PATCH 2876/5608] Adjust osu!mania scroll speed defaults to be more sane --- .../Configuration/ManiaRulesetConfigManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs index b591f9da22..f5412dcfc5 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.Configuration { base.InitialiseDefaults(); - Set(ManiaRulesetSetting.ScrollTime, 2250.0, 50.0, 10000.0, 50.0); + Set(ManiaRulesetSetting.ScrollTime, 1500.0, 50.0, 5000.0, 50.0); Set(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down); } From 70d39e9be47d7fae0250c0acc3c9fdf27e0f8ced Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Sep 2019 13:28:36 +0900 Subject: [PATCH 2877/5608] Always apply stable's magic ratio --- osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs index d2018ea720..1885c76fcc 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Skinning Texture = skin.GetTexture("cursortrail"); disjointTrail = skin.GetTexture("cursormiddle") == null; - if (disjointTrail && Texture != null) + if (Texture != null) { // stable "magic ratio". see OsuPlayfieldAdjustmentContainer for full explanation. Texture.ScaleAdjust *= 1.6f; From 6c00d3936ae556af3184f587fffdf85afab58b61 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Sep 2019 13:28:46 +0900 Subject: [PATCH 2878/5608] Reduce interval between cursor trail parts --- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 7975982aec..b32dfd483f 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -152,7 +152,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor float distance = diff.Length; Vector2 direction = diff / distance; - float interval = partSize.X / 2 * 0.9f; + float interval = partSize.X / 2.5f; for (float d = interval; d < distance; d += interval) { From 562280ced02ed9c570a7b56a8a6e4cd9dbd95507 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Sep 2019 13:30:07 +0900 Subject: [PATCH 2879/5608] Add cursor trail test scene --- .../TestSceneCursorTrail.cs | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs new file mode 100644 index 0000000000..dae75e5a9d --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs @@ -0,0 +1,120 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Textures; +using osu.Framework.Testing.Input; +using osu.Game.Audio; +using osu.Game.Rulesets.Osu.Skinning; +using osu.Game.Rulesets.Osu.UI.Cursor; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestSceneCursorTrail : OsuTestScene + { + [Test] + public void TestSmoothCursorTrail() + { + createTest(() => new CursorTrail()); + } + + [Test] + public void TestLegacySmoothCursorTrail() + { + createTest(() => new LegacySkinContainer(false) + { + Child = new LegacyCursorTrail() + }); + } + + [Test] + public void TestLegacyDisjointCursorTrail() + { + createTest(() => new LegacySkinContainer(true) + { + Child = new LegacyCursorTrail() + }); + } + + private void createTest(Func createContent) => AddStep("create trail", () => + { + Clear(); + + Add(new Container + { + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.8f), + Child = new MovingCursorInputManager { Child = createContent?.Invoke() } + }); + }); + + [Cached(typeof(ISkinSource))] + private class LegacySkinContainer : Container, ISkinSource + { + private readonly bool disjoint; + + public LegacySkinContainer(bool disjoint) + { + this.disjoint = disjoint; + + RelativeSizeAxes = Axes.Both; + } + + public Drawable GetDrawableComponent(ISkinComponent component) => throw new NotImplementedException(); + + public Texture GetTexture(string componentName) + { + switch (componentName) + { + case "cursortrail": + var tex = new Texture(Texture.WhitePixel.TextureGL); + + if (disjoint) + tex.ScaleAdjust = 1 / 25f; + return tex; + + case "cursormiddle": + return disjoint ? null : Texture.WhitePixel; + } + + return null; + } + + public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException(); + + public IBindable GetConfig(TLookup lookup) => throw new NotImplementedException(); + + public event Action SourceChanged; + } + + private class MovingCursorInputManager : ManualInputManager + { + public MovingCursorInputManager() + { + UseParentInput = false; + } + + protected override void Update() + { + base.Update(); + + const double spin_duration = 1000; + double currentTime = Time.Current; + + double angle = (currentTime % spin_duration) / spin_duration * 2 * Math.PI; + Vector2 rPos = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); + + MoveMouseTo(ToScreenSpace(DrawSize / 2 + DrawSize / 3 * rPos)); + } + } + } +} From 6760e239a119b74661a9efc0b6bce63615d6fdcd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 13:39:21 +0900 Subject: [PATCH 2880/5608] Fix osu! hitcircle font textures being incorrectly sized --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs | 6 +++--- osu.Game/Skinning/LegacySpriteText.cs | 7 +------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 6b6a08ed21..c978d95302 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -86,9 +86,9 @@ namespace osu.Game.Rulesets.Osu.Skinning ? null : new LegacySpriteText(source, font) { - // Spacing value was reverse-engineered from the ratio of the rendered sprite size in the visual inspector vs the actual texture size - Scale = new Vector2(0.96f), - Spacing = new Vector2(-overlap * 0.89f, 0) + // stable applies a blanket 0.8x scale to hitcircle fonts + Scale = new Vector2(0.8f), + Spacing = new Vector2(-overlap, 0) }; } diff --git a/osu.Game/Skinning/LegacySpriteText.cs b/osu.Game/Skinning/LegacySpriteText.cs index dbcec019d6..773a9dc5c6 100644 --- a/osu.Game/Skinning/LegacySpriteText.cs +++ b/osu.Game/Skinning/LegacySpriteText.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using osu.Framework.Graphics.Sprites; using osu.Framework.Text; -using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Skinning @@ -18,7 +17,7 @@ namespace osu.Game.Skinning Shadow = false; UseFullGlyphHeight = false; - Font = new FontUsage(font, OsuFont.DEFAULT_FONT_SIZE); + Font = new FontUsage(font, 1); glyphStore = new LegacyGlyphStore(skin); } @@ -37,10 +36,6 @@ namespace osu.Game.Skinning { var texture = skin.GetTexture($"{fontName}-{character}"); - if (texture != null) - // Approximate value that brings character sizing roughly in-line with stable - texture.ScaleAdjust *= 18; - if (texture == null) return null; From e408efff4984be7d737c86a76221d9c5771c229d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Sep 2019 13:40:53 +0900 Subject: [PATCH 2881/5608] Add scaling to the test --- osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs index dae75e5a9d..685a51d208 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs @@ -24,7 +24,15 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestSmoothCursorTrail() { - createTest(() => new CursorTrail()); + Container scalingContainer = null; + + createTest(() => scalingContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Child = new CursorTrail() + }); + + AddStep("set large scale", () => scalingContainer.Scale = new Vector2(10)); } [Test] From 96efc91b51a9b46a0045d246e7c2cc26e86fc6b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 14:57:42 +0900 Subject: [PATCH 2882/5608] Fix follow points not displaying on some skins --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 82181945a4..479c250eab 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -45,6 +45,9 @@ namespace osu.Game.Rulesets.Osu.Skinning switch (osuComponent.Component) { + case OsuSkinComponents.FollowPoint: + return this.GetAnimation(component.LookupName, true, false); + case OsuSkinComponents.SliderFollowCircle: return this.GetAnimation("sliderfollowcircle", true, true); From 95828b07efecaf83ef25127043f71ebb77e6c92f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 11 Sep 2019 10:40:58 +0300 Subject: [PATCH 2883/5608] Implement HeaderFlag component for rankings overlay --- .../Online/TestSceneRankingsHeaderFlag.cs | 55 +++++++++++++++ osu.Game/Overlays/Rankings/HeaderFlag.cs | 68 +++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs create mode 100644 osu.Game/Overlays/Rankings/HeaderFlag.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs new file mode 100644 index 0000000000..d31e3011b8 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs @@ -0,0 +1,55 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Overlays.Rankings; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsHeaderFlag : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HeaderFlag), + }; + + public TestSceneRankingsHeaderFlag() + { + HeaderFlag flag; + SpriteText text; + + AddRange(new Drawable[] + { + flag = new HeaderFlag + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(30, 20), + Country = new Country + { + FlagName = "BY", + FullName = "Belarus" + } + }, + text = new SpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Invoked", + Font = OsuFont.GetFont(size: 30), + Alpha = 0, + } + }); + + flag.Action += () => text.FadeIn().Then().FadeOut(1000, Easing.OutQuint); + + AddStep("Trigger click", () => flag.Click()); + } + } +} diff --git a/osu.Game/Overlays/Rankings/HeaderFlag.cs b/osu.Game/Overlays/Rankings/HeaderFlag.cs new file mode 100644 index 0000000000..5b00e3e487 --- /dev/null +++ b/osu.Game/Overlays/Rankings/HeaderFlag.cs @@ -0,0 +1,68 @@ +// 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.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Users.Drawables; +using osuTK.Graphics; +using osuTK; +using osu.Framework.Input.Events; +using osu.Framework.Extensions.Color4Extensions; +using System; + +namespace osu.Game.Overlays.Rankings +{ + public class HeaderFlag : UpdateableFlag + { + private const int duration = 200; + + public Action Action; + + private readonly Container hoverContainer; + + public HeaderFlag() + { + AddInternal(hoverContainer = new Container + { + Alpha = 0, + Depth = -1, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(15), + Icon = FontAwesome.Solid.Times, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(100), + } + } + }); + } + + protected override bool OnHover(HoverEvent e) + { + hoverContainer.FadeIn(duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + hoverContainer.FadeOut(duration, Easing.OutQuint); + } + + protected override bool OnClick(ClickEvent e) + { + Action?.Invoke(); + return base.OnClick(e); + } + } +} From d610c903716356593f9b774c5e768412583e13c5 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 11 Sep 2019 10:43:51 +0300 Subject: [PATCH 2884/5608] Add more tests --- .../Online/TestSceneRankingsHeaderFlag.cs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs index d31e3011b8..c9531e1016 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs @@ -24,6 +24,18 @@ namespace osu.Game.Tests.Visual.Online HeaderFlag flag; SpriteText text; + var countryA = new Country + { + FlagName = "BY", + FullName = "Belarus" + }; + + var countryB = new Country + { + FlagName = "US", + FullName = "United States" + }; + AddRange(new Drawable[] { flag = new HeaderFlag @@ -31,11 +43,7 @@ namespace osu.Game.Tests.Visual.Online Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(30, 20), - Country = new Country - { - FlagName = "BY", - FullName = "Belarus" - } + Country = countryA, }, text = new SpriteText { @@ -50,6 +58,8 @@ namespace osu.Game.Tests.Visual.Online flag.Action += () => text.FadeIn().Then().FadeOut(1000, Easing.OutQuint); AddStep("Trigger click", () => flag.Click()); + AddStep("Change to country 2", () => flag.Country = countryB); + AddStep("Change to country 1", () => flag.Country = countryA); } } } From 1d1da1bc13c7f1c613aa8bba35c8f5b90a819b15 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 11 Sep 2019 11:26:09 +0300 Subject: [PATCH 2885/5608] Visual improvements --- osu.Game/Overlays/Rankings/HeaderFlag.cs | 34 +++++++++--------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/osu.Game/Overlays/Rankings/HeaderFlag.cs b/osu.Game/Overlays/Rankings/HeaderFlag.cs index 5b00e3e487..8bd4bdf13f 100644 --- a/osu.Game/Overlays/Rankings/HeaderFlag.cs +++ b/osu.Game/Overlays/Rankings/HeaderFlag.cs @@ -20,49 +20,39 @@ namespace osu.Game.Overlays.Rankings public Action Action; - private readonly Container hoverContainer; + private readonly SpriteIcon hoverIcon; public HeaderFlag() { - AddInternal(hoverContainer = new Container + AddInternal(hoverIcon = new SpriteIcon { - Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Depth = -1, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(15), - Icon = FontAwesome.Solid.Times, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(100), - } - } + Alpha = 0, + Size = new Vector2(10), + Icon = FontAwesome.Solid.Times, }); } protected override bool OnHover(HoverEvent e) { - hoverContainer.FadeIn(duration, Easing.OutQuint); + hoverIcon.FadeIn(duration, Easing.OutQuint); + this.FadeColour(Color4.Gray, duration, Easing.OutQuint); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - hoverContainer.FadeOut(duration, Easing.OutQuint); + hoverIcon.FadeOut(duration, Easing.OutQuint); + this.FadeColour(Color4.White, duration, Easing.OutQuint); } protected override bool OnClick(ClickEvent e) { Action?.Invoke(); - return base.OnClick(e); + return true; } } } From 825a34ecd3180d421aa6f6f8827df3a8269f5f70 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 17:34:03 +0900 Subject: [PATCH 2886/5608] Early return to avoid other potential fail cases --- .../Containers/OsuFocusedOverlayContainer.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 5c2efbc354..08164dbf3e 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.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.Allocation; @@ -106,26 +106,26 @@ namespace osu.Game.Graphics.Containers protected override void UpdateState(ValueChangedEvent state) { - base.UpdateState(state); - switch (state.NewValue) { case Visibility.Visible: - if (OverlayActivationMode.Value != OverlayActivation.Disabled) + if (OverlayActivationMode.Value == OverlayActivation.Disabled) { - if (PlaySamplesOnStateChange) samplePopIn?.Play(); - if (BlockScreenWideMouse && DimMainContent) osuGame?.AddBlockingOverlay(this); + State.Value = Visibility.Hidden; + return; } - else - Hide(); + if (PlaySamplesOnStateChange) samplePopIn?.Play(); + if (BlockScreenWideMouse && DimMainContent) game?.AddBlockingOverlay(this); break; case Visibility.Hidden: if (PlaySamplesOnStateChange) samplePopOut?.Play(); - if (BlockScreenWideMouse) osuGame?.RemoveBlockingOverlay(this); + if (BlockScreenWideMouse) game?.RemoveBlockingOverlay(this); break; } + + base.UpdateState(state); } protected override void PopOut() From 2c09efa23b577bc5e15c3a4efea6558a490f7d62 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 17:34:28 +0900 Subject: [PATCH 2887/5608] Handle changes to OverlayActivationMode --- .../Containers/OsuFocusedOverlayContainer.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 08164dbf3e..0ce095d44f 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.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.Allocation; @@ -32,7 +32,7 @@ namespace osu.Game.Graphics.Containers protected virtual bool DimMainContent => true; [Resolved(CanBeNull = true)] - private OsuGame osuGame { get; set; } + private OsuGame game { get; set; } [Resolved] private PreviewTrackManager previewTrackManager { get; set; } @@ -42,8 +42,14 @@ namespace osu.Game.Graphics.Containers [BackgroundDependencyLoader(true)] private void load(AudioManager audio) { - if (osuGame != null) - OverlayActivationMode.BindTo(osuGame.OverlayActivationMode); + OverlayActivationMode.ValueChanged += mode => + { + if (mode.NewValue == OverlayActivation.Disabled) + State.Value = Visibility.Hidden; + }; + + if (game != null) + OverlayActivationMode.BindTo(game.OverlayActivationMode); samplePopIn = audio.Samples.Get(@"UI/overlay-pop-in"); samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out"); @@ -137,7 +143,7 @@ namespace osu.Game.Graphics.Containers protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - osuGame?.RemoveBlockingOverlay(this); + game?.RemoveBlockingOverlay(this); } } } From 660c678cdcbe74b8a6b6fe55555a60b2b778f820 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 11 Sep 2019 11:40:51 +0300 Subject: [PATCH 2888/5608] Remove unused using directives --- osu.Game/Overlays/Rankings/HeaderFlag.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/Rankings/HeaderFlag.cs b/osu.Game/Overlays/Rankings/HeaderFlag.cs index 8bd4bdf13f..6f641c74a5 100644 --- a/osu.Game/Overlays/Rankings/HeaderFlag.cs +++ b/osu.Game/Overlays/Rankings/HeaderFlag.cs @@ -2,14 +2,11 @@ // 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.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Users.Drawables; using osuTK.Graphics; using osuTK; using osu.Framework.Input.Events; -using osu.Framework.Extensions.Color4Extensions; using System; namespace osu.Game.Overlays.Rankings From 41ad44791bfc2918af739f05273e244e180b7f20 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 11 Sep 2019 11:58:18 +0300 Subject: [PATCH 2889/5608] Move RankingsScopeSelector to another namespace --- osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs | 2 +- osu.Game/Overlays/{ => Rankings}/RankingsScopeSelector.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename osu.Game/Overlays/{ => Rankings}/RankingsScopeSelector.cs (94%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs index 93a00e1d06..2081a6c0cb 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs @@ -5,10 +5,10 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Bindables; -using osu.Game.Overlays; using osu.Framework.Graphics.Shapes; using osu.Framework.Allocation; using osu.Game.Graphics; +using osu.Game.Overlays.Rankings; namespace osu.Game.Tests.Visual.Online { diff --git a/osu.Game/Overlays/RankingsScopeSelector.cs b/osu.Game/Overlays/Rankings/RankingsScopeSelector.cs similarity index 94% rename from osu.Game/Overlays/RankingsScopeSelector.cs rename to osu.Game/Overlays/Rankings/RankingsScopeSelector.cs index 5935876ec9..2095bcc61c 100644 --- a/osu.Game/Overlays/RankingsScopeSelector.cs +++ b/osu.Game/Overlays/Rankings/RankingsScopeSelector.cs @@ -5,7 +5,7 @@ using osu.Game.Graphics.UserInterface; using osu.Framework.Allocation; using osuTK.Graphics; -namespace osu.Game.Overlays +namespace osu.Game.Overlays.Rankings { public class RankingsScopeSelector : GradientLineTabControl { From da6ba20fc80a7cb25badd75fcc0dfd23a2b4f0bb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:15:03 +0900 Subject: [PATCH 2890/5608] Reduce glow on notes --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 2cd81104a3..5aeaba717c 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.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.Diagnostics; @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, - Colour = colour.NewValue.Lighten(1f).Opacity(0.6f), + Colour = colour.NewValue.Lighten(1f).Opacity(0.2f), Radius = 10, }; }, true); From 44d90a4e860fecb7891d295fe929fdc8dbc8d6f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:16:14 +0900 Subject: [PATCH 2891/5608] Increase note height --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs | 4 +++- .../Objects/Drawables/Pieces/NotePiece.cs | 7 +++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 5aeaba717c..31221c05ee 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.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.Diagnostics; @@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// public class DrawableNote : DrawableManiaHitObject, IKeyBindingHandler { + public const float CORNER_RADIUS = NotePiece.NOTE_HEIGHT / 2; + private readonly NotePiece headPiece; public DrawableNote(Note hitObject) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index bb33693783..4521af7dfb 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -18,8 +18,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces /// internal class NotePiece : Container, IHasAccentColour { - public const float NOTE_HEIGHT = 10; - private const float head_colour_height = 6; + public const float NOTE_HEIGHT = 12; private readonly IBindable direction = new Bindable(); @@ -39,8 +38,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces colouredBox = new Box { RelativeSizeAxes = Axes.X, - Height = head_colour_height, - Alpha = 0.2f + Height = NOTE_HEIGHT / 2, + Alpha = 0.1f } }; } From 8f6bc6fd5c8171152f308c937c2e3dff48894b97 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:12:43 +0900 Subject: [PATCH 2892/5608] Make osu!mania hit explosions more explodey --- .../TestSceneHitExplosion.cs | 84 ++++++++++++ osu.Game.Rulesets.Mania/UI/Column.cs | 9 +- osu.Game.Rulesets.Mania/UI/HitExplosion.cs | 123 +++++++++++++----- 3 files changed, 183 insertions(+), 33 deletions(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs new file mode 100644 index 0000000000..12159ca239 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs @@ -0,0 +1,84 @@ +// 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 NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Tests.Visual; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [TestFixture] + public class TestSceneHitExplosion : OsuTestScene + { + private ScrollingTestContainer scrolling; + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(DrawableNote), + typeof(DrawableManiaHitObject), + }; + + protected override void LoadComplete() + { + base.LoadComplete(); + + Child = scrolling = new ScrollingTestContainer(ScrollingDirection.Down) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.Y, + Y = -0.25f, + Size = new Vector2(Column.COLUMN_WIDTH, NotePiece.NOTE_HEIGHT), + }; + + int runcount = 0; + + AddRepeatStep("explode", () => + { + runcount++; + + if (runcount % 15 > 12) + return; + + scrolling.AddRange(new Drawable[] + { + new HitExplosion((runcount / 15) % 2 == 0 ? new Color4(94, 0, 57, 255) : new Color4(6, 84, 0, 255), runcount % 6 != 0) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }); + }, 100); + } + + private class TestNote : DrawableNote + { + protected override void CheckForResult(bool userTriggered, double timeOffset) + { + if (!userTriggered) + { + // force success + ApplyResult(r => r.Type = HitResult.Great); + } + else + base.CheckForResult(userTriggered, timeOffset); + } + + public TestNote(Note hitObject) + : base(hitObject) + { + AccentColour.Value = Color4.Pink; + } + } + } +} diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 91dd236ab1..fa14a0a293 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.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; @@ -90,6 +90,8 @@ namespace osu.Game.Rulesets.Mania.UI Bottom = dir.NewValue == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, }; + explosionContainer.Y = dir.NewValue == ScrollingDirection.Down ? -NotePiece.NOTE_HEIGHT : 0; + keyArea.Anchor = keyArea.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; }, true); } @@ -163,9 +165,10 @@ namespace osu.Game.Rulesets.Mania.UI if (!result.IsHit || !judgedObject.DisplayResult || !DisplayJudgements.Value) return; - explosionContainer.Add(new HitExplosion(judgedObject) + explosionContainer.Add(new HitExplosion(judgedObject.AccentColour.Value, judgedObject is DrawableHoldNoteTick) { - Anchor = Direction.Value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre + Anchor = Direction.Value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre, + Origin = Direction.Value == ScrollingDirection.Up ? Anchor.BottomCentre : Anchor.TopCentre, }); } diff --git a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs index 48470add8b..21726206f1 100644 --- a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs @@ -1,16 +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 osuTK.Graphics; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; -using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; -using osu.Game.Rulesets.Objects.Drawables; using osuTK; +using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.UI { @@ -18,51 +16,116 @@ namespace osu.Game.Rulesets.Mania.UI { public override bool RemoveWhenNotAlive => true; - private readonly CircularContainer circle; + private readonly CircularContainer largeFaint; + private readonly CircularContainer mainGlow1; + private readonly CircularContainer mainGlow2; + private readonly CircularContainer mainGlow3; - public HitExplosion(DrawableHitObject judgedObject) + public HitExplosion(Color4 objectColour, bool isSmall = false) { - bool isTick = judgedObject is DrawableHoldNoteTick; - - Origin = Anchor.Centre; - RelativeSizeAxes = Axes.X; - Y = NotePiece.NOTE_HEIGHT / 2; Height = NotePiece.NOTE_HEIGHT; // scale roughly in-line with visual appearance of notes - Scale = new Vector2(isTick ? 0.4f : 0.8f); + Scale = new Vector2(1f, 0.6f); - InternalChild = circle = new CircularContainer + if (isSmall) + Scale *= 0.5f; + + const float angle_variangle = 15; // should be less than 45 + + const float roundness = 80; + + const float opacity = 1; + + const float initial_height = 10; + + var colour = Interpolation.ValueAt(0.4f, objectColour, Color4.White, 0, 1); + + InternalChildren = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - // we want our size to be very small so the glow dominates it. - Size = new Vector2(0.1f), - EdgeEffect = new EdgeEffectParameters + largeFaint = new CircularContainer { - Type = EdgeEffectType.Glow, - Colour = Interpolation.ValueAt(0.1f, judgedObject.AccentColour.Value, Color4.White, 0, 1), - Radius = 100, - }, - Child = new Box - { - Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - AlwaysPresent = true + Masking = true, + // we want our size to be very small so the glow dominates it. + Size = new Vector2(0.8f), + Blending = BlendingParameters.Additive, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = Interpolation.ValueAt(0.1f, objectColour, Color4.White, 0, 1).Opacity(0.3f), + Roundness = 160, + Radius = 200, + }, + }, + mainGlow1 = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + Blending = BlendingParameters.Additive, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = Interpolation.ValueAt(0.6f, objectColour, Color4.White, 0, 1), + Roundness = 20, + Radius = 50, + }, + }, + mainGlow2 = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + Size = new Vector2(0.01f, initial_height), + Blending = BlendingParameters.Additive, + Rotation = RNG.NextSingle(-angle_variangle, angle_variangle), + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = colour, + Roundness = roundness, + Radius = 40, + }, + }, + mainGlow3 = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + Size = new Vector2(0.01f, initial_height), + Blending = BlendingParameters.Additive, + Rotation = RNG.NextSingle(-angle_variangle, angle_variangle), + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = colour, + Roundness = roundness, + Radius = 40, + }, } }; } protected override void LoadComplete() { + const double duration = 200; + base.LoadComplete(); - circle.ResizeTo(circle.Size * new Vector2(4, 20), 1000, Easing.OutQuint); - this.FadeIn(16).Then().FadeOut(500, Easing.OutQuint); + largeFaint + .ResizeTo(largeFaint.Size * new Vector2(5, 1), duration, Easing.OutQuint) + .FadeOut(duration * 2); + mainGlow1.ScaleTo(1.4f, duration, Easing.OutQuint); + + this.FadeOut(duration, Easing.Out); Expire(true); } } From 6bfdadb22fb1dcaaf172e5694a955c812c4bd030 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:20:41 +0900 Subject: [PATCH 2893/5608] Increase column width --- osu.Game.Rulesets.Mania/UI/Column.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 91dd236ab1..0caee025b6 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -11,6 +11,8 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; using osuTK; @@ -19,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.UI { public class Column : ScrollingPlayfield, IKeyBindingHandler, IHasAccentColour { - private const float column_width = 45; + public const float COLUMN_WIDTH = 80; private const float special_column_width = 70; /// @@ -41,10 +43,7 @@ namespace osu.Game.Rulesets.Mania.UI Index = index; RelativeSizeAxes = Axes.Y; - Width = column_width; - - Masking = true; - CornerRadius = 5; + Width = COLUMN_WIDTH; background = new ColumnBackground { RelativeSizeAxes = Axes.Both }; @@ -67,7 +66,7 @@ namespace osu.Game.Rulesets.Mania.UI explosionContainer = new Container { Name = "Hit explosions", - RelativeSizeAxes = Axes.Both + RelativeSizeAxes = Axes.Both, } } }, @@ -108,7 +107,7 @@ namespace osu.Game.Rulesets.Mania.UI isSpecial = value; - Width = isSpecial ? special_column_width : column_width; + Width = isSpecial ? special_column_width : COLUMN_WIDTH; } } From c7186efd5339a954eaf67682c01fb184e669b455 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:21:29 +0900 Subject: [PATCH 2894/5608] Reduce opacity of judgement area --- osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index a0d713067d..386bcbb724 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osuTK.Graphics; @@ -17,7 +18,6 @@ namespace osu.Game.Rulesets.Mania.UI.Components { public class ColumnHitObjectArea : CompositeDrawable, IHasAccentColour { - private const float hit_target_height = 10; private const float hit_target_bar_height = 2; private readonly IBindable direction = new Bindable(); @@ -32,7 +32,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components hitTargetBar = new Box { RelativeSizeAxes = Axes.X, - Height = hit_target_height, + Height = NotePiece.NOTE_HEIGHT, + Alpha = 0.6f, Colour = Color4.Black }, hitTargetLine = new Container From b9e71d26b285922d7c0d0a7e3f2d0bcc60628220 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:21:39 +0900 Subject: [PATCH 2895/5608] Dim column backgrounds further --- osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index 5ee78aa496..57241da564 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -35,7 +35,6 @@ namespace osu.Game.Rulesets.Mania.UI.Components { Name = "Background", RelativeSizeAxes = Axes.Both, - Alpha = 0.3f }, backgroundOverlay = new Box { @@ -82,7 +81,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components if (!IsLoaded) return; - background.Colour = AccentColour; + background.Colour = AccentColour.Darken(5); var brightPoint = AccentColour.Opacity(0.6f); var dimPoint = AccentColour.Opacity(0); From 06618b6d02e7f358d1929cf5bf19b1e6f22c269a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:45:47 +0900 Subject: [PATCH 2896/5608] Fix osu!mania minor barline alpha not being respected --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index 862af8d15b..be21610525 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -68,6 +68,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Alpha = 0.2f; } + protected override void UpdateInitialTransforms() + { + } + protected override void UpdateStateTransforms(ArmedState state) { } From 039b5ec958fcac03296e31791721b2e786c17de7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:47:25 +0900 Subject: [PATCH 2897/5608] 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 f76297c197..45c162a30e 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 791d2fe285..df8b11e653 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 0560c45edf..7c31744a14 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From be66c0e9127982166e393e697daa9d4c2d5db938 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 19:06:31 +0900 Subject: [PATCH 2898/5608] Fix potential of toggle between load and LoadComplete --- .../Graphics/Containers/OsuFocusedOverlayContainer.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 0ce095d44f..a1df973b60 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -41,6 +41,12 @@ namespace osu.Game.Graphics.Containers [BackgroundDependencyLoader(true)] private void load(AudioManager audio) + { + samplePopIn = audio.Samples.Get(@"UI/overlay-pop-in"); + samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out"); + } + + protected override void LoadComplete() { OverlayActivationMode.ValueChanged += mode => { @@ -51,8 +57,7 @@ namespace osu.Game.Graphics.Containers if (game != null) OverlayActivationMode.BindTo(game.OverlayActivationMode); - samplePopIn = audio.Samples.Get(@"UI/overlay-pop-in"); - samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out"); + base.LoadComplete(); } /// From 55a071e8ba9bfe68ba237daa81a1024a43366d92 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 19:12:55 +0900 Subject: [PATCH 2899/5608] Use BindValueChanged --- .../Graphics/Containers/OsuFocusedOverlayContainer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index a1df973b60..2e8910213b 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -48,14 +48,14 @@ namespace osu.Game.Graphics.Containers protected override void LoadComplete() { - OverlayActivationMode.ValueChanged += mode => + if (game != null) + OverlayActivationMode.BindTo(game.OverlayActivationMode); + + OverlayActivationMode.BindValueChanged(mode => { if (mode.NewValue == OverlayActivation.Disabled) State.Value = Visibility.Hidden; - }; - - if (game != null) - OverlayActivationMode.BindTo(game.OverlayActivationMode); + }, true); base.LoadComplete(); } From dbfbd1262fd1caffd5d657d1bbf6ef24d2b66997 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 11 Sep 2019 23:39:22 +0300 Subject: [PATCH 2900/5608] Implement HeaderTitle component for RankingsOverlay --- .../Online/TestSceneRankingsHeaderTitle.cs | 60 ++++++++++ osu.Game/Overlays/Rankings/HeaderTitle.cs | 105 ++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs create mode 100644 osu.Game/Overlays/Rankings/HeaderTitle.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs new file mode 100644 index 0000000000..0f16b2592f --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs @@ -0,0 +1,60 @@ +// 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.Bindables; +using osu.Framework.Graphics; +using osu.Game.Overlays.Rankings; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsHeaderTitle : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HeaderFlag), + typeof(HeaderTitle), + }; + + public TestSceneRankingsHeaderTitle() + { + var countryBindable = new Bindable(); + var scope = new Bindable(); + + Add(new HeaderTitle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Country = { BindTarget = countryBindable }, + Scope = { BindTarget = scope }, + }); + + var countryA = new Country + { + FlagName = "BY", + FullName = "Belarus" + }; + + var countryB = new Country + { + FlagName = "US", + FullName = "United States" + }; + + AddStep("Set country", () => countryBindable.Value = countryA); + AddAssert("Check scope is Performance", () => scope.Value == RankingsScope.Performance); + AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); + AddAssert("Check country is Null", () => countryBindable.Value == null); + + AddStep("Set country 1", () => countryBindable.Value = countryA); + AddStep("Set country 2", () => countryBindable.Value = countryB); + AddStep("Set null country", () => countryBindable.Value = null); + AddStep("Set scope to Performance", () => scope.Value = RankingsScope.Performance); + AddStep("Set scope to Spotlights", () => scope.Value = RankingsScope.Spotlights); + AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); + AddStep("Set scope to Country", () => scope.Value = RankingsScope.Country); + } + } +} diff --git a/osu.Game/Overlays/Rankings/HeaderTitle.cs b/osu.Game/Overlays/Rankings/HeaderTitle.cs new file mode 100644 index 0000000000..3f1feb10b8 --- /dev/null +++ b/osu.Game/Overlays/Rankings/HeaderTitle.cs @@ -0,0 +1,105 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Users; +using osu.Framework.Graphics; +using osuTK; +using osu.Game.Graphics; +using osu.Framework.Allocation; + +namespace osu.Game.Overlays.Rankings +{ + public class HeaderTitle : CompositeDrawable + { + private const int spacing = 10; + private const int flag_margin = 5; + private const int text_size = 40; + + public readonly Bindable Scope = new Bindable(); + public readonly Bindable Country = new Bindable(); + + private readonly SpriteText scopeText; + private readonly Container flagPlaceholder; + private readonly HeaderFlag flag; + + public HeaderTitle() + { + AutoSizeAxes = Axes.Both; + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(spacing, 0), + Children = new Drawable[] + { + flagPlaceholder = new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Bottom = flag_margin }, + Child = flag = new HeaderFlag + { + Size = new Vector2(30, 20), + }, + }, + scopeText = new SpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Light) + }, + new SpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Light), + Text = @"Ranking" + } + } + }; + + flag.Action += () => Country.Value = null; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + scopeText.Colour = colours.Lime; + } + + protected override void LoadComplete() + { + Scope.BindValueChanged(scope => onScopeChanged(scope.NewValue), true); + Country.BindValueChanged(onCountryChanged, true); + base.LoadComplete(); + } + + private void onScopeChanged(RankingsScope scope) + { + scopeText.Text = scope.ToString(); + + if (scope != RankingsScope.Performance) + Country.Value = null; + } + + private void onCountryChanged(ValueChangedEvent country) + { + if (country.NewValue == null) + { + flagPlaceholder.Hide(); + return; + } + + Scope.Value = RankingsScope.Performance; + + if (country.OldValue == null) + flagPlaceholder.Show(); + + flag.Country = country.NewValue; + } + } +} From e0bf579b18eaddd62a85c9333a2375403b2d2e14 Mon Sep 17 00:00:00 2001 From: Joehu Date: Wed, 11 Sep 2019 15:35:47 -0700 Subject: [PATCH 2901/5608] Properly fix dialog overlay playing double samples on show/hide --- .../Containers/OsuFocusedOverlayContainer.cs | 6 ++---- osu.Game/Overlays/Dialog/PopupDialog.cs | 20 +------------------ osu.Game/Overlays/DialogOverlay.cs | 16 +++++++++++++-- 3 files changed, 17 insertions(+), 25 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 2e8910213b..b117d71006 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -21,8 +21,6 @@ namespace osu.Game.Graphics.Containers private SampleChannel samplePopIn; private SampleChannel samplePopOut; - protected virtual bool PlaySamplesOnStateChange => true; - protected override bool BlockNonPositionalInput => true; /// @@ -126,12 +124,12 @@ namespace osu.Game.Graphics.Containers return; } - if (PlaySamplesOnStateChange) samplePopIn?.Play(); + samplePopIn?.Play(); if (BlockScreenWideMouse && DimMainContent) game?.AddBlockingOverlay(this); break; case Visibility.Hidden: - if (PlaySamplesOnStateChange) samplePopOut?.Play(); + samplePopOut?.Play(); if (BlockScreenWideMouse) game?.RemoveBlockingOverlay(this); break; } diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index 1022edfe81..5c0ddb47b1 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -13,20 +13,17 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; -using osu.Game.Input.Bindings; using osuTK; using osuTK.Graphics; using osuTK.Input; namespace osu.Game.Overlays.Dialog { - public class PopupDialog : OsuFocusedOverlayContainer + public class PopupDialog : VisibilityContainer { public static readonly float ENTER_DURATION = 500; public static readonly float EXIT_DURATION = 200; - protected override bool BlockPositionalInput => false; - private readonly Vector2 ringSize = new Vector2(100f); private readonly Vector2 ringMinifiedSize = new Vector2(20f); private readonly Vector2 buttonsEnterSpacing = new Vector2(0f, 50f); @@ -202,18 +199,6 @@ namespace osu.Game.Overlays.Dialog }; } - public override bool OnPressed(GlobalAction action) - { - switch (action) - { - case GlobalAction.Select: - Buttons.OfType().FirstOrDefault()?.Click(); - return true; - } - - return base.OnPressed(action); - } - protected override bool OnKeyDown(KeyDownEvent e) { if (e.Repeat) return false; @@ -238,8 +223,6 @@ namespace osu.Game.Overlays.Dialog protected override void PopIn() { - base.PopIn(); - actionInvoked = false; // Reset various animations but only if the dialog animation fully completed @@ -263,7 +246,6 @@ namespace osu.Game.Overlays.Dialog // This is presumed to always be a sane default "cancel" action. buttonsContainer.Last().Click(); - base.PopOut(); content.FadeOut(EXIT_DURATION, Easing.InSine); } diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index aaae7bcf5c..0d3c96c984 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -5,6 +5,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Dialog; using osu.Game.Graphics.Containers; +using osu.Game.Input.Bindings; +using System.Linq; namespace osu.Game.Overlays { @@ -41,8 +43,6 @@ namespace osu.Game.Overlays Show(); } - protected override bool PlaySamplesOnStateChange => false; - protected override bool BlockNonPositionalInput => true; private void onDialogOnStateChanged(VisibilityContainer dialog, Visibility v) @@ -74,5 +74,17 @@ namespace osu.Game.Overlays this.FadeOut(PopupDialog.EXIT_DURATION, Easing.InSine); } + + public override bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.Select: + currentDialog.Buttons.OfType().FirstOrDefault()?.Click(); + return true; + } + + return base.OnPressed(action); + } } } From 77ac186cf803e02861197032cfda700383933667 Mon Sep 17 00:00:00 2001 From: Joehu Date: Wed, 11 Sep 2019 16:08:01 -0700 Subject: [PATCH 2902/5608] Add spacing to mod icons on leaderboards --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 1 + osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 1 + .../Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 008f8208eb..0b84cfc28a 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -215,6 +215,7 @@ namespace osu.Game.Online.Leaderboards Origin = Anchor.BottomRight, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, + Spacing = new Vector2(1), ChildrenEnumerable = score.Mods.Select(mod => new ModIcon(mod) { Scale = new Vector2(0.375f) }) }, }, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 347522fb48..58f5f02956 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -171,6 +171,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, + Spacing = new Vector2(1), ChildrenEnumerable = score.Mods.Select(m => new ModIcon(m) { AutoSizeAxes = Axes.Both, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index 6761d0f710..b9664d7c2f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -172,7 +172,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores : this(new FillFlowContainer { AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal + Direction = FillDirection.Horizontal, + Spacing = new Vector2(1), }) { } From c3c2efe35ca966df9cbde9925417fedbe0000637 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 05:03:59 +0300 Subject: [PATCH 2903/5608] Add ability to override text in PageTabItem --- osu.Game/Graphics/UserInterface/PageTabControl.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/PageTabControl.cs b/osu.Game/Graphics/UserInterface/PageTabControl.cs index a0d3745180..ddcb626701 100644 --- a/osu.Game/Graphics/UserInterface/PageTabControl.cs +++ b/osu.Game/Graphics/UserInterface/PageTabControl.cs @@ -63,7 +63,7 @@ namespace osu.Game.Graphics.UserInterface Margin = new MarginPadding { Top = 8, Bottom = 8 }, Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, - Text = (value as Enum)?.GetDescription() ?? value.ToString(), + Text = CreateText(), Font = OsuFont.GetFont(size: 14) }, box = new Box @@ -81,6 +81,8 @@ namespace osu.Game.Graphics.UserInterface Active.BindValueChanged(active => Text.Font = Text.Font.With(Typeface.Exo, weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium), true); } + protected virtual string CreateText() => (Value as Enum)?.GetDescription() ?? Value.ToString(); + protected override bool OnHover(HoverEvent e) { if (!Active.Value) From 581508b8e75f51560398b06095d27e860afd89c1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 05:06:51 +0300 Subject: [PATCH 2904/5608] Implement RankingsRulesetSelector --- .../TestSceneRankingsRulesetSelector.cs | 42 ++++++++++++++ .../Rankings/RankingsRulesetSelector.cs | 56 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs create mode 100644 osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs new file mode 100644 index 0000000000..8ad10c6a63 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs @@ -0,0 +1,42 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Game.Overlays.Rankings; +using osu.Framework.Graphics; +using osu.Game.Rulesets; +using osu.Framework.Bindables; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Taiko; +using osu.Game.Rulesets.Catch; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsRulesetSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RankingsRulesetSelector), + }; + + public TestSceneRankingsRulesetSelector() + { + RankingsRulesetSelector selector; + var current = new Bindable(); + + Add(selector = new RankingsRulesetSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = current } + }); + + AddStep("Select osu!", () => current.Value = new OsuRuleset().RulesetInfo); + AddStep("Select mania", () => current.Value = new ManiaRuleset().RulesetInfo); + AddStep("Select taiko", () => current.Value = new TaikoRuleset().RulesetInfo); + AddStep("Select catch", () => current.Value = new CatchRuleset().RulesetInfo); + } + } +} diff --git a/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs b/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs new file mode 100644 index 0000000000..f1666507d1 --- /dev/null +++ b/osu.Game/Overlays/Rankings/RankingsRulesetSelector.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.UserInterface; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets; +using osuTK; +using System.Linq; + +namespace osu.Game.Overlays.Rankings +{ + public class RankingsRulesetSelector : PageTabControl + { + protected override TabItem CreateTabItem(RulesetInfo value) => new RankingsTabItem(value); + + protected override Dropdown CreateDropdown() => null; + + public RankingsRulesetSelector() + { + AutoSizeAxes = Axes.X; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, RulesetStore Rulesets) + { + foreach (var r in Rulesets.AvailableRulesets) + AddItem(r); + + AccentColour = colours.Lime; + + SelectTab(TabContainer.FirstOrDefault()); + } + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20, 0), + }; + + private class RankingsTabItem : PageTabItem + { + public RankingsTabItem(RulesetInfo value) + : base(value) + { + } + + protected override string CreateText() => $"{Value.Name}"; + } + } +} From 4bfb681db6f816fd623e0ef407e86c41980c1c5a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 05:16:56 +0300 Subject: [PATCH 2905/5608] CI fixes --- .../Visual/Online/TestSceneRankingsRulesetSelector.cs | 3 +-- osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs index 8ad10c6a63..84515bd3a4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs @@ -23,10 +23,9 @@ namespace osu.Game.Tests.Visual.Online public TestSceneRankingsRulesetSelector() { - RankingsRulesetSelector selector; var current = new Bindable(); - Add(selector = new RankingsRulesetSelector + Add(new RankingsRulesetSelector { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs b/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs index f1666507d1..3d25e3995a 100644 --- a/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs +++ b/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs @@ -25,9 +25,9 @@ namespace osu.Game.Overlays.Rankings } [BackgroundDependencyLoader] - private void load(OsuColour colours, RulesetStore Rulesets) + private void load(OsuColour colours, RulesetStore rulesets) { - foreach (var r in Rulesets.AvailableRulesets) + foreach (var r in rulesets.AvailableRulesets) AddItem(r); AccentColour = colours.Lime; From b657e31f93b2b9fce626d0f151f6d36a565fd809 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 05:26:10 +0300 Subject: [PATCH 2906/5608] Merge dependent changes --- .../Online/TestSceneRankingsHeaderFlag.cs | 65 +++++++++++ .../Online/TestSceneRankingsHeaderTitle.cs | 60 ++++++++++ .../TestSceneRankingsRulesetSelector.cs | 41 +++++++ .../Online/TestSceneRankingsScopeSelector.cs | 54 +++++++++ .../UserInterface/GradientLineTabControl.cs | 103 +++++++++++++++++ .../Graphics/UserInterface/PageTabControl.cs | 4 +- .../BeatmapSet/LeaderboardScopeSelector.cs | 69 +----------- osu.Game/Overlays/Rankings/HeaderFlag.cs | 55 +++++++++ osu.Game/Overlays/Rankings/HeaderTitle.cs | 105 ++++++++++++++++++ .../Rankings/RankingsRulesetSelector.cs | 56 ++++++++++ .../Rankings/RankingsScopeSelector.cs | 26 +++++ 11 files changed, 572 insertions(+), 66 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs create mode 100644 osu.Game/Graphics/UserInterface/GradientLineTabControl.cs create mode 100644 osu.Game/Overlays/Rankings/HeaderFlag.cs create mode 100644 osu.Game/Overlays/Rankings/HeaderTitle.cs create mode 100644 osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs create mode 100644 osu.Game/Overlays/Rankings/RankingsScopeSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs new file mode 100644 index 0000000000..c9531e1016 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs @@ -0,0 +1,65 @@ +// 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; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Overlays.Rankings; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsHeaderFlag : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HeaderFlag), + }; + + public TestSceneRankingsHeaderFlag() + { + HeaderFlag flag; + SpriteText text; + + var countryA = new Country + { + FlagName = "BY", + FullName = "Belarus" + }; + + var countryB = new Country + { + FlagName = "US", + FullName = "United States" + }; + + AddRange(new Drawable[] + { + flag = new HeaderFlag + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(30, 20), + Country = countryA, + }, + text = new SpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Invoked", + Font = OsuFont.GetFont(size: 30), + Alpha = 0, + } + }); + + flag.Action += () => text.FadeIn().Then().FadeOut(1000, Easing.OutQuint); + + AddStep("Trigger click", () => flag.Click()); + AddStep("Change to country 2", () => flag.Country = countryB); + AddStep("Change to country 1", () => flag.Country = countryA); + } + } +} diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs new file mode 100644 index 0000000000..0f16b2592f --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs @@ -0,0 +1,60 @@ +// 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.Bindables; +using osu.Framework.Graphics; +using osu.Game.Overlays.Rankings; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsHeaderTitle : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HeaderFlag), + typeof(HeaderTitle), + }; + + public TestSceneRankingsHeaderTitle() + { + var countryBindable = new Bindable(); + var scope = new Bindable(); + + Add(new HeaderTitle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Country = { BindTarget = countryBindable }, + Scope = { BindTarget = scope }, + }); + + var countryA = new Country + { + FlagName = "BY", + FullName = "Belarus" + }; + + var countryB = new Country + { + FlagName = "US", + FullName = "United States" + }; + + AddStep("Set country", () => countryBindable.Value = countryA); + AddAssert("Check scope is Performance", () => scope.Value == RankingsScope.Performance); + AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); + AddAssert("Check country is Null", () => countryBindable.Value == null); + + AddStep("Set country 1", () => countryBindable.Value = countryA); + AddStep("Set country 2", () => countryBindable.Value = countryB); + AddStep("Set null country", () => countryBindable.Value = null); + AddStep("Set scope to Performance", () => scope.Value = RankingsScope.Performance); + AddStep("Set scope to Spotlights", () => scope.Value = RankingsScope.Spotlights); + AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); + AddStep("Set scope to Country", () => scope.Value = RankingsScope.Country); + } + } +} diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs new file mode 100644 index 0000000000..84515bd3a4 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs @@ -0,0 +1,41 @@ +// 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.Game.Overlays.Rankings; +using osu.Framework.Graphics; +using osu.Game.Rulesets; +using osu.Framework.Bindables; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Taiko; +using osu.Game.Rulesets.Catch; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsRulesetSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RankingsRulesetSelector), + }; + + public TestSceneRankingsRulesetSelector() + { + var current = new Bindable(); + + Add(new RankingsRulesetSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = current } + }); + + AddStep("Select osu!", () => current.Value = new OsuRuleset().RulesetInfo); + AddStep("Select mania", () => current.Value = new ManiaRuleset().RulesetInfo); + AddStep("Select taiko", () => current.Value = new TaikoRuleset().RulesetInfo); + AddStep("Select catch", () => current.Value = new CatchRuleset().RulesetInfo); + } + } +} diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs new file mode 100644 index 0000000000..2081a6c0cb --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs @@ -0,0 +1,54 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Overlays.Rankings; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsScopeSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RankingsScopeSelector), + }; + + private readonly Box background; + + public TestSceneRankingsScopeSelector() + { + var scope = new Bindable(); + + AddRange(new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new RankingsScopeSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = scope } + } + }); + + AddStep(@"Select country", () => scope.Value = RankingsScope.Country); + AddStep(@"Select performance", () => scope.Value = RankingsScope.Performance); + AddStep(@"Select score", () => scope.Value = RankingsScope.Score); + AddStep(@"Select spotlights", () => scope.Value = RankingsScope.Spotlights); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.GreySeafoam; + } + } +} diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs new file mode 100644 index 0000000000..7cd8d2c5bd --- /dev/null +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -0,0 +1,103 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osuTK; +using osu.Framework.Graphics.Shapes; +using osuTK.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; + +namespace osu.Game.Graphics.UserInterface +{ + public class GradientLineTabControl : PageTabControl + { + protected override Dropdown CreateDropdown() => null; + + protected Color4 LineColour + { + get => line.MainColour.Value; + set => line.MainColour.Value = value; + } + + private readonly GradientLine line; + + public GradientLineTabControl() + { + RelativeSizeAxes = Axes.X; + + AddInternal(line = new GradientLine + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + }); + } + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20, 0), + }; + + private class GradientLine : GridContainer + { + public readonly Bindable MainColour = new Bindable(); + + private readonly Box left; + private readonly Box middle; + private readonly Box right; + + public GradientLine() + { + RelativeSizeAxes = Axes.X; + Size = new Vector2(0.8f, 1.5f); + + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(mode: GridSizeMode.Relative, size: 0.4f), + new Dimension(), + }; + + Content = new[] + { + new Drawable[] + { + left = new Box + { + RelativeSizeAxes = Axes.Both, + }, + middle = new Box + { + RelativeSizeAxes = Axes.Both, + }, + right = new Box + { + RelativeSizeAxes = Axes.Both, + }, + } + }; + } + + protected override void LoadComplete() + { + MainColour.BindValueChanged(onColourChanged, true); + base.LoadComplete(); + } + + private void onColourChanged(ValueChangedEvent colour) + { + left.Colour = ColourInfo.GradientHorizontal(colour.NewValue.Opacity(0), colour.NewValue); + middle.Colour = colour.NewValue; + right.Colour = ColourInfo.GradientHorizontal(colour.NewValue, colour.NewValue.Opacity(0)); + } + } + } +} diff --git a/osu.Game/Graphics/UserInterface/PageTabControl.cs b/osu.Game/Graphics/UserInterface/PageTabControl.cs index a0d3745180..ddcb626701 100644 --- a/osu.Game/Graphics/UserInterface/PageTabControl.cs +++ b/osu.Game/Graphics/UserInterface/PageTabControl.cs @@ -63,7 +63,7 @@ namespace osu.Game.Graphics.UserInterface Margin = new MarginPadding { Top = 8, Bottom = 8 }, Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, - Text = (value as Enum)?.GetDescription() ?? value.ToString(), + Text = CreateText(), Font = OsuFont.GetFont(size: 14) }, box = new Box @@ -81,6 +81,8 @@ namespace osu.Game.Graphics.UserInterface Active.BindValueChanged(active => Text.Font = Text.Font.With(Typeface.Exo, weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium), true); } + protected virtual string CreateText() => (Value as Enum)?.GetDescription() ?? Value.ToString(); + protected override bool OnHover(HoverEvent e) { if (!Active.Value) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index dcd58db427..e2a725ec46 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -1,60 +1,37 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics.UserInterface; using osu.Game.Screens.Select.Leaderboards; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osuTK; using osu.Game.Graphics.UserInterface; -using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Framework.Allocation; using osuTK.Graphics; -using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; +using osu.Framework.Graphics; namespace osu.Game.Overlays.BeatmapSet { - public class LeaderboardScopeSelector : PageTabControl + public class LeaderboardScopeSelector : GradientLineTabControl { protected override bool AddEnumEntriesAutomatically => false; - protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(BeatmapLeaderboardScope value) => new ScopeSelectorTabItem(value); public LeaderboardScopeSelector() { - RelativeSizeAxes = Axes.X; - AddItem(BeatmapLeaderboardScope.Global); AddItem(BeatmapLeaderboardScope.Country); AddItem(BeatmapLeaderboardScope.Friend); - - AddInternal(new GradientLine - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - }); } [BackgroundDependencyLoader] private void load(OsuColour colours) { AccentColour = colours.Blue; + LineColour = Color4.Gray; } - protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(20, 0), - }; - private class ScopeSelectorTabItem : PageTabItem { public ScopeSelectorTabItem(BeatmapLeaderboardScope value) @@ -77,43 +54,5 @@ namespace osu.Game.Overlays.BeatmapSet Text.FadeColour(Color4.White); } } - - private class GradientLine : GridContainer - { - public GradientLine() - { - RelativeSizeAxes = Axes.X; - Size = new Vector2(0.8f, 1.5f); - - ColumnDimensions = new[] - { - new Dimension(), - new Dimension(mode: GridSizeMode.Relative, size: 0.4f), - new Dimension(), - }; - - Content = new[] - { - new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4.Transparent, Color4.Gray), - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Gray, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4.Gray, Color4.Transparent), - }, - } - }; - } - } } } diff --git a/osu.Game/Overlays/Rankings/HeaderFlag.cs b/osu.Game/Overlays/Rankings/HeaderFlag.cs new file mode 100644 index 0000000000..6f641c74a5 --- /dev/null +++ b/osu.Game/Overlays/Rankings/HeaderFlag.cs @@ -0,0 +1,55 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Users.Drawables; +using osuTK.Graphics; +using osuTK; +using osu.Framework.Input.Events; +using System; + +namespace osu.Game.Overlays.Rankings +{ + public class HeaderFlag : UpdateableFlag + { + private const int duration = 200; + + public Action Action; + + private readonly SpriteIcon hoverIcon; + + public HeaderFlag() + { + AddInternal(hoverIcon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Depth = -1, + Alpha = 0, + Size = new Vector2(10), + Icon = FontAwesome.Solid.Times, + }); + } + + protected override bool OnHover(HoverEvent e) + { + hoverIcon.FadeIn(duration, Easing.OutQuint); + this.FadeColour(Color4.Gray, duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + hoverIcon.FadeOut(duration, Easing.OutQuint); + this.FadeColour(Color4.White, duration, Easing.OutQuint); + } + + protected override bool OnClick(ClickEvent e) + { + Action?.Invoke(); + return true; + } + } +} diff --git a/osu.Game/Overlays/Rankings/HeaderTitle.cs b/osu.Game/Overlays/Rankings/HeaderTitle.cs new file mode 100644 index 0000000000..3f1feb10b8 --- /dev/null +++ b/osu.Game/Overlays/Rankings/HeaderTitle.cs @@ -0,0 +1,105 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Users; +using osu.Framework.Graphics; +using osuTK; +using osu.Game.Graphics; +using osu.Framework.Allocation; + +namespace osu.Game.Overlays.Rankings +{ + public class HeaderTitle : CompositeDrawable + { + private const int spacing = 10; + private const int flag_margin = 5; + private const int text_size = 40; + + public readonly Bindable Scope = new Bindable(); + public readonly Bindable Country = new Bindable(); + + private readonly SpriteText scopeText; + private readonly Container flagPlaceholder; + private readonly HeaderFlag flag; + + public HeaderTitle() + { + AutoSizeAxes = Axes.Both; + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(spacing, 0), + Children = new Drawable[] + { + flagPlaceholder = new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Bottom = flag_margin }, + Child = flag = new HeaderFlag + { + Size = new Vector2(30, 20), + }, + }, + scopeText = new SpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Light) + }, + new SpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Light), + Text = @"Ranking" + } + } + }; + + flag.Action += () => Country.Value = null; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + scopeText.Colour = colours.Lime; + } + + protected override void LoadComplete() + { + Scope.BindValueChanged(scope => onScopeChanged(scope.NewValue), true); + Country.BindValueChanged(onCountryChanged, true); + base.LoadComplete(); + } + + private void onScopeChanged(RankingsScope scope) + { + scopeText.Text = scope.ToString(); + + if (scope != RankingsScope.Performance) + Country.Value = null; + } + + private void onCountryChanged(ValueChangedEvent country) + { + if (country.NewValue == null) + { + flagPlaceholder.Hide(); + return; + } + + Scope.Value = RankingsScope.Performance; + + if (country.OldValue == null) + flagPlaceholder.Show(); + + flag.Country = country.NewValue; + } + } +} diff --git a/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs b/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs new file mode 100644 index 0000000000..3d25e3995a --- /dev/null +++ b/osu.Game/Overlays/Rankings/RankingsRulesetSelector.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.UserInterface; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets; +using osuTK; +using System.Linq; + +namespace osu.Game.Overlays.Rankings +{ + public class RankingsRulesetSelector : PageTabControl + { + protected override TabItem CreateTabItem(RulesetInfo value) => new RankingsTabItem(value); + + protected override Dropdown CreateDropdown() => null; + + public RankingsRulesetSelector() + { + AutoSizeAxes = Axes.X; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, RulesetStore rulesets) + { + foreach (var r in rulesets.AvailableRulesets) + AddItem(r); + + AccentColour = colours.Lime; + + SelectTab(TabContainer.FirstOrDefault()); + } + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20, 0), + }; + + private class RankingsTabItem : PageTabItem + { + public RankingsTabItem(RulesetInfo value) + : base(value) + { + } + + protected override string CreateText() => $"{Value.Name}"; + } + } +} diff --git a/osu.Game/Overlays/Rankings/RankingsScopeSelector.cs b/osu.Game/Overlays/Rankings/RankingsScopeSelector.cs new file mode 100644 index 0000000000..2095bcc61c --- /dev/null +++ b/osu.Game/Overlays/Rankings/RankingsScopeSelector.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Graphics.UserInterface; +using osu.Framework.Allocation; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Rankings +{ + public class RankingsScopeSelector : GradientLineTabControl + { + [BackgroundDependencyLoader] + private void load() + { + AccentColour = LineColour = Color4.Black; + } + } + + public enum RankingsScope + { + Performance, + Spotlights, + Score, + Country + } +} From 0c6c8fdcd0e97e74979ae9d248241050f0bf5149 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 05:53:18 +0300 Subject: [PATCH 2907/5608] Implement RankingsHeader component --- .../Visual/Online/TestSceneRankingsHeader.cs | 52 ++++++++++++ osu.Game/Overlays/Rankings/RankingsHeader.cs | 84 +++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs create mode 100644 osu.Game/Overlays/Rankings/RankingsHeader.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs new file mode 100644 index 0000000000..81534e7d44 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs @@ -0,0 +1,52 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Overlays.Rankings; +using osu.Game.Rulesets; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsHeader : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HeaderFlag), + typeof(HeaderTitle), + typeof(RankingsRulesetSelector), + typeof(RankingsScopeSelector), + typeof(RankingsHeader), + }; + + public TestSceneRankingsHeader() + { + var countryBindable = new Bindable(); + var ruleset = new Bindable(); + var scope = new Bindable(); + + Add(new RankingsHeader + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scope = { BindTarget = scope }, + Country = { BindTarget = countryBindable }, + Ruleset = { BindTarget = ruleset }, + }); + + var country = new Country + { + FlagName = "BY", + FullName = "Belarus" + }; + + AddStep("Set country", () => countryBindable.Value = country); + AddAssert("Check scope is Performance", () => scope.Value == RankingsScope.Performance); + AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); + AddAssert("Check country is Null", () => countryBindable.Value == null); + } + } +} diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs new file mode 100644 index 0000000000..7fdc2ab9c8 --- /dev/null +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -0,0 +1,84 @@ +// 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.Containers; +using osu.Framework.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Framework.Bindables; +using osu.Game.Rulesets; +using osu.Game.Users; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; + +namespace osu.Game.Overlays.Rankings +{ + public class RankingsHeader : CompositeDrawable + { + private const int content_height = 250; + + public readonly Bindable Scope = new Bindable(); + public readonly Bindable Ruleset = new Bindable(); + public readonly Bindable Country = new Bindable(); + + public RankingsHeader() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + AddInternal(new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new RankingsRulesetSelector + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Current = { BindTarget = Ruleset } + }, + new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Height = content_height, + Children = new Drawable[] + { + new HeaderBackground(), + new RankingsScopeSelector + { + Margin = new MarginPadding { Top = 10 }, + Current = { BindTarget = Scope } + }, + new HeaderTitle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scope = { BindTarget = Scope }, + Country = { BindTarget = Country }, + } + } + } + } + }); + } + + public class HeaderBackground : Sprite + { + public HeaderBackground() + { + RelativeSizeAxes = Axes.Both; + FillMode = FillMode.Fill; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Texture = textures.Get(@"Headers/rankings"); + } + } + } +} From acdd26422dc4c006f88b2eb0028113622b23a4ad Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 06:36:17 +0300 Subject: [PATCH 2908/5608] Implement Spotlights logic --- .../Visual/Online/TestSceneRankingsHeader.cs | 18 +++++ osu.Game/Overlays/Rankings/RankingsHeader.cs | 74 +++++++++++++++++-- osu.Game/Overlays/Rankings/Spotlight.cs | 18 +++++ 3 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Overlays/Rankings/Spotlight.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs index 81534e7d44..e8ed94b59c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs @@ -35,6 +35,24 @@ namespace osu.Game.Tests.Visual.Online Scope = { BindTarget = scope }, Country = { BindTarget = countryBindable }, Ruleset = { BindTarget = ruleset }, + Spotlights = new[] + { + new Spotlight + { + Id = 1, + Text = "Spotlight 1" + }, + new Spotlight + { + Id = 2, + Text = "Spotlight 2" + }, + new Spotlight + { + Id = 3, + Text = "Spotlight 4" + } + } }); var country = new Country diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs index 7fdc2ab9c8..6d55e92502 100644 --- a/osu.Game/Overlays/Rankings/RankingsHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -4,23 +4,38 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Allocation; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; using osu.Framework.Bindables; using osu.Game.Rulesets; using osu.Game.Users; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osuTK; +using osu.Game.Graphics.UserInterface; +using System.Collections.Generic; namespace osu.Game.Overlays.Rankings { public class RankingsHeader : CompositeDrawable { private const int content_height = 250; + private const int dropdown_height = 50; + private const int spacing = 20; + private const int title_offset = 30; + private const int duration = 200; + + public IEnumerable Spotlights + { + get => dropdown.Items; + set => dropdown.Items = value; + } public readonly Bindable Scope = new Bindable(); public readonly Bindable Ruleset = new Bindable(); public readonly Bindable Country = new Bindable(); + public readonly Bindable Spotlight = new Bindable(); + + private readonly Container dropdownPlaceholder; + private readonly OsuDropdown dropdown; public RankingsHeader() { @@ -47,29 +62,72 @@ namespace osu.Game.Overlays.Rankings Height = content_height, Children = new Drawable[] { - new HeaderBackground(), + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = new HeaderBackground(), + }, new RankingsScopeSelector { Margin = new MarginPadding { Top = 10 }, Current = { BindTarget = Scope } }, - new HeaderTitle + new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Scope = { BindTarget = Scope }, - Country = { BindTarget = Country }, - } + Y = title_offset, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, spacing), + Children = new Drawable[] + { + new HeaderTitle + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Scope = { BindTarget = Scope }, + Country = { BindTarget = Country }, + }, + dropdownPlaceholder = new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Height = dropdown_height, + Width = 0.8f, + AlwaysPresent = true, + Child = dropdown = new OsuDropdown + { + RelativeSizeAxes = Axes.X, + Current = { BindTarget = Spotlight }, + } + } + } + }, } } } }); } - public class HeaderBackground : Sprite + protected override void LoadComplete() + { + Scope.BindValueChanged(scope => onScopeChanged(scope.NewValue), true); + base.LoadComplete(); + } + + private void onScopeChanged(RankingsScope scope) => + dropdownPlaceholder.FadeTo(scope == RankingsScope.Spotlights ? 1 : 0, duration, Easing.OutQuint); + + private class HeaderBackground : Sprite { public HeaderBackground() { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; RelativeSizeAxes = Axes.Both; FillMode = FillMode.Fill; } diff --git a/osu.Game/Overlays/Rankings/Spotlight.cs b/osu.Game/Overlays/Rankings/Spotlight.cs new file mode 100644 index 0000000000..e956b4f449 --- /dev/null +++ b/osu.Game/Overlays/Rankings/Spotlight.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 Newtonsoft.Json; + +namespace osu.Game.Overlays.Rankings +{ + public class Spotlight + { + [JsonProperty("id")] + public int Id; + + [JsonProperty("text")] + public string Text; + + public override string ToString() => Text; + } +} From b1c0b080ecced55aecae5aa4f28078418d8ecbd7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Sep 2019 13:52:27 +0900 Subject: [PATCH 2909/5608] Fix bad hit explosion anchoring --- osu.Game.Rulesets.Mania/UI/Column.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index fa14a0a293..8021660f77 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -11,6 +11,8 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; using osuTK; @@ -90,7 +92,11 @@ namespace osu.Game.Rulesets.Mania.UI Bottom = dir.NewValue == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, }; - explosionContainer.Y = dir.NewValue == ScrollingDirection.Down ? -NotePiece.NOTE_HEIGHT : 0; + explosionContainer.Padding = new MarginPadding + { + Top = dir.NewValue == ScrollingDirection.Up ? NotePiece.NOTE_HEIGHT / 2 : 0, + Bottom = dir.NewValue == ScrollingDirection.Down ? NotePiece.NOTE_HEIGHT / 2 : 0 + }; keyArea.Anchor = keyArea.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; }, true); @@ -168,7 +174,7 @@ namespace osu.Game.Rulesets.Mania.UI explosionContainer.Add(new HitExplosion(judgedObject.AccentColour.Value, judgedObject is DrawableHoldNoteTick) { Anchor = Direction.Value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre, - Origin = Direction.Value == ScrollingDirection.Up ? Anchor.BottomCentre : Anchor.TopCentre, + Origin = Anchor.Centre }); } From bbf80f63aa920b3a86b51142cd2b54d782fe5182 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Sep 2019 13:53:05 +0900 Subject: [PATCH 2910/5608] Publicly expose column width constant --- osu.Game.Rulesets.Mania/UI/Column.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 8021660f77..910342a3b0 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.UI { public class Column : ScrollingPlayfield, IKeyBindingHandler, IHasAccentColour { - private const float column_width = 45; + public const float COLUMN_WIDTH = 45; private const float special_column_width = 70; /// @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.UI Index = index; RelativeSizeAxes = Axes.Y; - Width = column_width; + Width = COLUMN_WIDTH; Masking = true; CornerRadius = 5; @@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Mania.UI isSpecial = value; - Width = isSpecial ? special_column_width : column_width; + Width = isSpecial ? special_column_width : COLUMN_WIDTH; } } From f9c969788a758f913001047dca99aff00a853de8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 13:56:23 +0900 Subject: [PATCH 2911/5608] Fix keys not reaching full brightness as soon as they should --- osu.Game/Screens/Play/KeyCounter.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 88a62ac8d4..ad5fcfcf24 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -130,15 +130,17 @@ namespace osu.Game.Screens.Play private void updateGlowSprite(bool show) { + double remainingFadeTime = FadeTime * (1 - glowSprite.Alpha); + if (show) { - glowSprite.FadeIn(FadeTime); - textLayer.FadeColour(KeyDownTextColor, FadeTime); + glowSprite.FadeIn(remainingFadeTime); + textLayer.FadeColour(KeyDownTextColor, remainingFadeTime); } else { - glowSprite.FadeOut(FadeTime); - textLayer.FadeColour(KeyUpTextColor, FadeTime); + glowSprite.FadeOut(remainingFadeTime); + textLayer.FadeColour(KeyUpTextColor, remainingFadeTime); } } From b941f12688eb2bb309e8d37cd3fc5f29beb582a1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Sep 2019 14:09:21 +0900 Subject: [PATCH 2912/5608] Cleanup --- .../TestSceneHitExplosion.cs | 22 ------------------- osu.Game.Rulesets.Mania/UI/HitExplosion.cs | 8 ++----- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs index 12159ca239..26a1b1b1ec 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs @@ -5,11 +5,9 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics; -using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Tests.Visual; using osuTK; @@ -60,25 +58,5 @@ namespace osu.Game.Rulesets.Mania.Tests }); }, 100); } - - private class TestNote : DrawableNote - { - protected override void CheckForResult(bool userTriggered, double timeOffset) - { - if (!userTriggered) - { - // force success - ApplyResult(r => r.Type = HitResult.Great); - } - else - base.CheckForResult(userTriggered, timeOffset); - } - - public TestNote(Note hitObject) - : base(hitObject) - { - AccentColour.Value = Color4.Pink; - } - } } } diff --git a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs index 21726206f1..ccbff226a9 100644 --- a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs @@ -18,8 +18,6 @@ namespace osu.Game.Rulesets.Mania.UI private readonly CircularContainer largeFaint; private readonly CircularContainer mainGlow1; - private readonly CircularContainer mainGlow2; - private readonly CircularContainer mainGlow3; public HitExplosion(Color4 objectColour, bool isSmall = false) { @@ -36,8 +34,6 @@ namespace osu.Game.Rulesets.Mania.UI const float roundness = 80; - const float opacity = 1; - const float initial_height = 10; var colour = Interpolation.ValueAt(0.4f, objectColour, Color4.White, 0, 1); @@ -76,7 +72,7 @@ namespace osu.Game.Rulesets.Mania.UI Radius = 50, }, }, - mainGlow2 = new CircularContainer + new CircularContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -93,7 +89,7 @@ namespace osu.Game.Rulesets.Mania.UI Radius = 40, }, }, - mainGlow3 = new CircularContainer + new CircularContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 158737e001e46bdfd4f8ed85a48ab53ba81f70a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 14:27:29 +0900 Subject: [PATCH 2913/5608] Remove FadeTime customisation Also adjusts fade transitions to feel better, especially in fast forward scenarios. --- .../Visual/Gameplay/TestSceneKeyCounter.cs | 1 - osu.Game/Screens/Play/HUDOverlay.cs | 1 - osu.Game/Screens/Play/KeyCounter.cs | 14 +++++------ osu.Game/Screens/Play/KeyCounterDisplay.cs | 25 ++----------------- 4 files changed, 9 insertions(+), 32 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 18088a9a5b..4643b82792 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -44,7 +44,6 @@ namespace osu.Game.Tests.Visual.Gameplay Key key = (Key)((int)Key.A + RNG.Next(26)); kc.Add(new KeyCounterKeyboard(key)); }); - AddSliderStep("Fade time", 0, 200, 50, v => kc.FadeTime = v); Key testKey = ((KeyCounterKeyboard)kc.Children.First()).Key; double time1 = 0; diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index eee7235a6e..0f9edf5606 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -231,7 +231,6 @@ namespace osu.Game.Screens.Play protected virtual KeyCounterDisplay CreateKeyCounter() => new KeyCounterDisplay { - FadeTime = 50, Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Margin = new MarginPadding(10), diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index ad5fcfcf24..1930369299 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -65,7 +65,7 @@ namespace osu.Game.Screens.Play //further: change default values here and in KeyCounterCollection if needed, instead of passing them in every constructor public Color4 KeyDownTextColor { get; set; } = Color4.DarkGray; public Color4 KeyUpTextColor { get; set; } = Color4.White; - public int FadeTime { get; set; } + public double FadeTime { get; set; } protected KeyCounter(string name) { @@ -130,17 +130,17 @@ namespace osu.Game.Screens.Play private void updateGlowSprite(bool show) { - double remainingFadeTime = FadeTime * (1 - glowSprite.Alpha); - if (show) { - glowSprite.FadeIn(remainingFadeTime); - textLayer.FadeColour(KeyDownTextColor, remainingFadeTime); + double remainingFadeTime = FadeTime * (1 - glowSprite.Alpha); + glowSprite.FadeIn(remainingFadeTime, Easing.OutQuint); + textLayer.FadeColour(KeyDownTextColor, remainingFadeTime, Easing.OutQuint); } else { - glowSprite.FadeOut(remainingFadeTime); - textLayer.FadeColour(KeyUpTextColor, remainingFadeTime); + double remainingFadeTime = 8 * FadeTime * glowSprite.Alpha; + glowSprite.FadeOut(remainingFadeTime, Easing.OutQuint); + textLayer.FadeColour(KeyUpTextColor, remainingFadeTime, Easing.OutQuint); } } diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index d5967f5899..6b8fa5c75b 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -17,6 +17,7 @@ namespace osu.Game.Screens.Play public class KeyCounterDisplay : FillFlowContainer { private const int duration = 100; + private const double key_fade_time = 80; public readonly Bindable Visible = new Bindable(true); private readonly Bindable configVisibility = new Bindable(); @@ -33,17 +34,11 @@ namespace osu.Game.Screens.Play base.Add(key); key.IsCounting = IsCounting; - key.FadeTime = FadeTime; + key.FadeTime = key_fade_time; key.KeyDownTextColor = KeyDownTextColor; key.KeyUpTextColor = KeyUpTextColor; } - public void ResetCount() - { - foreach (var counter in Children) - counter.ResetCount(); - } - [BackgroundDependencyLoader] private void load(OsuConfigManager config) { @@ -68,22 +63,6 @@ namespace osu.Game.Screens.Play } } - private int fadeTime; - - public int FadeTime - { - get => fadeTime; - set - { - if (value != fadeTime) - { - fadeTime = value; - foreach (var child in Children) - child.FadeTime = value; - } - } - } - private Color4 keyDownTextColor = Color4.DarkGray; public Color4 KeyDownTextColor From cb0cf6e2c5e14e37d37716a79cec9b02b89d2aae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 14:27:52 +0900 Subject: [PATCH 2914/5608] Remove reset functions --- osu.Game/Screens/Play/KeyCounter.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 1930369299..ad0858184e 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -144,12 +144,6 @@ namespace osu.Game.Screens.Play } } - public void ResetCount() - { - CountPresses = 0; - states.Clear(); - } - protected override void Update() { base.Update(); From 0cdf125c1e8f64fc5397fc1701e42cb21d1adaf2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 15:41:53 +0900 Subject: [PATCH 2915/5608] Handle key counter rewinding in a better way Use ElapsedFrameTime rather than storing state data --- .../Visual/Gameplay/TestSceneKeyCounter.cs | 40 ++------------- osu.Game/Rulesets/UI/RulesetInputManager.cs | 4 +- osu.Game/Screens/Play/KeyCounter.cs | 49 ++++++------------- osu.Game/Screens/Play/KeyCounterAction.cs | 22 ++++++--- osu.Game/Screens/Play/KeyCounterDisplay.cs | 5 -- osu.Game/Screens/Play/KeyCounterKeyboard.cs | 7 ++- osu.Game/Screens/Play/KeyCounterMouse.cs | 7 ++- 7 files changed, 50 insertions(+), 84 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 4643b82792..6783a36ac3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -7,7 +7,6 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.MathUtils; -using osu.Framework.Timing; using osu.Game.Screens.Play; using osuTK.Input; @@ -25,14 +24,15 @@ namespace osu.Game.Tests.Visual.Gameplay public TestSceneKeyCounter() { - KeyCounterKeyboard rewindTestKeyCounterKeyboard; + KeyCounterKeyboard testCounter; + KeyCounterDisplay kc = new KeyCounterDisplay { Origin = Anchor.Centre, Anchor = Anchor.Centre, Children = new KeyCounter[] { - rewindTestKeyCounterKeyboard = new KeyCounterKeyboard(Key.X), + testCounter = new KeyCounterKeyboard(Key.X), new KeyCounterKeyboard(Key.X), new KeyCounterMouse(MouseButton.Left), new KeyCounterMouse(MouseButton.Right), @@ -54,7 +54,7 @@ namespace osu.Game.Tests.Visual.Gameplay InputManager.ReleaseKey(testKey); }); - AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 1); + AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 1); AddStep($"Press {testKey} key", () => { @@ -63,39 +63,9 @@ namespace osu.Game.Tests.Visual.Gameplay time1 = Clock.CurrentTime; }); - AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 2); - - IFrameBasedClock oldClock = null; - - AddStep($"Rewind {testKey} counter once", () => - { - oldClock = rewindTestKeyCounterKeyboard.Clock; - rewindTestKeyCounterKeyboard.Clock = new FramedOffsetClock(new FixedClock(time1 - 10)); - }); - - AddAssert($"Check {testKey} counter after rewind", () => rewindTestKeyCounterKeyboard.CountPresses == 1); - - AddStep($"Rewind {testKey} counter to zero", () => rewindTestKeyCounterKeyboard.Clock = new FramedOffsetClock(new FixedClock(0))); - - AddAssert($"Check {testKey} counter after rewind", () => rewindTestKeyCounterKeyboard.CountPresses == 0); - - AddStep("Restore clock", () => rewindTestKeyCounterKeyboard.Clock = oldClock); + AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 2); Add(kc); } - - private class FixedClock : IClock - { - private readonly double time; - - public FixedClock(double time) - { - this.time = time; - } - - public double CurrentTime => time; - public double Rate => 1; - public bool IsRunning => false; - } } } diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index e25c3bd0e7..98e27240d3 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -137,9 +137,9 @@ namespace osu.Game.Rulesets.UI { } - public bool OnPressed(T action) => Target.Children.OfType>().Any(c => c.OnPressed(action)); + public bool OnPressed(T action) => Target.Children.OfType>().Any(c => c.OnPressed(action, Clock.ElapsedFrameTime > 0)); - public bool OnReleased(T action) => Target.Children.OfType>().Any(c => c.OnReleased(action)); + public bool OnReleased(T action) => Target.Children.OfType>().Any(c => c.OnReleased(action, Clock.ElapsedFrameTime > 0)); } #endregion diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index ad0858184e..1daf89d8f9 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -22,9 +20,6 @@ namespace osu.Game.Screens.Play private Container textLayer; private SpriteText countSpriteText; - private readonly List states = new List(); - private KeyCounterState currentState; - public bool IsCounting { get; set; } = true; private int countPresses; @@ -52,16 +47,26 @@ namespace osu.Game.Screens.Play { isLit = value; updateGlowSprite(value); - - if (value && IsCounting) - { - CountPresses++; - saveState(); - } } } } + public void Increment() + { + if (!IsCounting) + return; + + CountPresses++; + } + + public void Decrement() + { + if (!IsCounting) + return; + + CountPresses--; + } + //further: change default values here and in KeyCounterCollection if needed, instead of passing them in every constructor public Color4 KeyDownTextColor { get; set; } = Color4.DarkGray; public Color4 KeyUpTextColor { get; set; } = Color4.White; @@ -143,27 +148,5 @@ namespace osu.Game.Screens.Play textLayer.FadeColour(KeyUpTextColor, remainingFadeTime, Easing.OutQuint); } } - - protected override void Update() - { - base.Update(); - - if (currentState?.Time > Clock.CurrentTime) - restoreStateTo(Clock.CurrentTime); - } - - private void saveState() - { - if (currentState == null || currentState.Time < Clock.CurrentTime) - states.Add(currentState = new KeyCounterState(Clock.CurrentTime, CountPresses)); - } - - private void restoreStateTo(double time) - { - states.RemoveAll(state => state.Time > time); - - currentState = states.LastOrDefault(); - CountPresses = currentState?.Count ?? 0; - } } } diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterAction.cs index 8deac653ad..f60ad7aa5a 100644 --- a/osu.Game/Screens/Play/KeyCounterAction.cs +++ b/osu.Game/Screens/Play/KeyCounterAction.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Input.Bindings; - namespace osu.Game.Screens.Play { - public class KeyCounterAction : KeyCounter, IKeyBindingHandler + public class KeyCounterAction : KeyCounter where T : struct { public T Action { get; } @@ -16,15 +14,25 @@ namespace osu.Game.Screens.Play Action = action; } - public bool OnPressed(T action) + public bool OnPressed(T action, bool forwards) { - if (action.Equals(Action)) IsLit = true; + if (!action.Equals(Action)) + return false; + + IsLit = true; + if (forwards) + Increment(); return false; } - public bool OnReleased(T action) + public bool OnReleased(T action, bool forwards) { - if (action.Equals(Action)) IsLit = false; + if (!action.Equals(Action)) + return false; + + IsLit = false; + if (!forwards) + Decrement(); return false; } } diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index 6b8fa5c75b..1edb95ca46 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -102,11 +102,6 @@ namespace osu.Game.Screens.Play private Receptor receptor; - public Receptor GetReceptor() - { - return receptor ?? (receptor = new Receptor(this)); - } - public void SetReceptor(Receptor receptor) { if (this.receptor != null) diff --git a/osu.Game/Screens/Play/KeyCounterKeyboard.cs b/osu.Game/Screens/Play/KeyCounterKeyboard.cs index d9b6dca79d..29188b6b59 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboard.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboard.cs @@ -18,7 +18,12 @@ namespace osu.Game.Screens.Play protected override bool OnKeyDown(KeyDownEvent e) { - if (e.Key == Key) IsLit = true; + if (e.Key == Key) + { + IsLit = true; + Increment(); + } + return base.OnKeyDown(e); } diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouse.cs index 95fa58e5c0..828441de6e 100644 --- a/osu.Game/Screens/Play/KeyCounterMouse.cs +++ b/osu.Game/Screens/Play/KeyCounterMouse.cs @@ -36,7 +36,12 @@ namespace osu.Game.Screens.Play protected override bool OnMouseDown(MouseDownEvent e) { - if (e.Button == Button) IsLit = true; + if (e.Button == Button) + { + IsLit = true; + Increment(); + } + return base.OnMouseDown(e); } From 831d04f339402020b0467bd38a7b940ab8031638 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 15:48:07 +0900 Subject: [PATCH 2916/5608] Don't use gameplay clock in KeyCounter --- osu.Game/Screens/Play/KeyCounter.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 1daf89d8f9..f4109a63d0 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -78,11 +78,8 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader(true)] - private void load(TextureStore textures, GameplayClock clock) + private void load(TextureStore textures) { - if (clock != null) - Clock = clock; - Children = new Drawable[] { buttonSprite = new Sprite From 09a0c9f4d2fa8224651ff91d05881fe31f118ac1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 18:10:50 +0900 Subject: [PATCH 2917/5608] Add key counter rewind tests --- osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs | 9 ++++++++- .../Visual/Gameplay/TestSceneGameplayRewinding.cs | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index 452ac859de..e2b620ea98 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -21,7 +21,12 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void AddCheckSteps() { AddUntilStep("score above zero", () => ((ScoreAccessiblePlayer)Player).ScoreProcessor.TotalScore.Value > 0); - AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 0)); + AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 5)); + AddStep("rewind", () => + { + ((ScoreAccessiblePlayer)Player).GameplayClockContainer.Seek(0); + }); + AddUntilStep("key counter counted no", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); } private class ScoreAccessiblePlayer : TestPlayer @@ -29,6 +34,8 @@ namespace osu.Game.Tests.Visual.Gameplay public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new HUDOverlay HUDOverlay => base.HUDOverlay; + public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; + public ScoreAccessiblePlayer() : base(false, false) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index 237fee1594..ffc025a942 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -14,6 +14,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using osuTK; @@ -47,9 +48,11 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for track to start running", () => track.IsRunning); addSeekStep(3000); AddAssert("all judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged)); + AddUntilStep("key counter counted keys", () => player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses >= 7)); AddStep("clear results", () => player.AppliedResults.Clear()); addSeekStep(0); AddAssert("none judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => !h.Judged)); + AddUntilStep("key counters reset", () => player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); AddAssert("no results triggered", () => player.AppliedResults.Count == 0); } @@ -90,6 +93,10 @@ namespace osu.Game.Tests.Visual.Gameplay { public readonly List AppliedResults = new List(); + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + + public new HUDOverlay HUDOverlay => base.HUDOverlay; + public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; public new DrawableRuleset DrawableRuleset => base.DrawableRuleset; From acdfeef1dc44fcacad192926163e71ced4adc1e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 18:33:46 +0900 Subject: [PATCH 2918/5608] Improve how osu!catch stores and replays key actions --- .../Replays/CatchAutoGenerator.cs | 29 ++++++++++------ .../Replays/CatchFramedReplayInputHandler.cs | 15 ++------- .../Replays/CatchReplayFrame.cs | 33 ++++++++++++++++--- .../Replays/ManiaReplayFrame.cs | 2 +- .../Replays/OsuReplayFrame.cs | 8 ++--- .../Replays/TaikoReplayFrame.cs | 10 +++--- .../Replays/Types/IConvertibleReplayFrame.cs | 5 +-- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 15 ++++++--- 8 files changed, 74 insertions(+), 43 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 8dd00756f2..4ea1f22006 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -27,6 +27,8 @@ namespace osu.Game.Rulesets.Catch.Replays protected Replay Replay; + private CatchReplayFrame currentFrame; + public override Replay Generate() { // todo: add support for HT DT @@ -36,7 +38,7 @@ namespace osu.Game.Rulesets.Catch.Replays double lastTime = 0; // Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled - Replay.Frames.Add(new CatchReplayFrame(-100000, lastPosition)); + addFrame(-100000, lastPosition); void moveToNext(CatchHitObject h) { @@ -58,18 +60,18 @@ namespace osu.Game.Rulesets.Catch.Replays { //we are already in the correct range. lastTime = h.StartTime; - Replay.Frames.Add(new CatchReplayFrame(h.StartTime, lastPosition)); + addFrame(h.StartTime, lastPosition); return; } if (impossibleJump) { - Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); + addFrame(h.StartTime, h.X); } else if (h.HyperDash) { - Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable, lastPosition)); - Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); + addFrame(h.StartTime - timeAvailable, lastPosition); + addFrame(h.StartTime, h.X); } else if (dashRequired) { @@ -81,16 +83,16 @@ namespace osu.Game.Rulesets.Catch.Replays float midPosition = (float)Interpolation.Lerp(lastPosition, h.X, (float)timeAtDashSpeed / timeAvailable); //dash movement - Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable + 1, lastPosition, true)); - Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable + timeAtDashSpeed, midPosition)); - Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); + addFrame(h.StartTime - timeAvailable + 1, lastPosition, true); + addFrame(h.StartTime - timeAvailable + timeAtDashSpeed, midPosition); + addFrame(h.StartTime, h.X); } else { double timeBefore = positionChange / movement_speed; - Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeBefore, lastPosition)); - Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); + addFrame(h.StartTime - timeBefore, lastPosition); + addFrame(h.StartTime, h.X); } lastTime = h.StartTime; @@ -122,5 +124,12 @@ namespace osu.Game.Rulesets.Catch.Replays return Replay; } + + private void addFrame(double time, float? position = null, bool dashing = false) + { + var last = currentFrame; + currentFrame = new CatchReplayFrame(time, position, dashing, last); + Replay.Frames.Add(currentFrame); + } } } diff --git a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs index 103aa6c3f1..22532bc9ec 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using osu.Framework.Input.StateChanges; using osu.Framework.MathUtils; using osu.Game.Replays; @@ -17,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Replays { } - protected override bool IsImportant(CatchReplayFrame frame) => frame.Position > 0; + protected override bool IsImportant(CatchReplayFrame frame) => frame.Actions.Any(); protected float? Position { @@ -38,21 +39,11 @@ namespace osu.Game.Rulesets.Catch.Replays { if (!Position.HasValue) return new List(); - var actions = new List(); - - if (CurrentFrame.Dashing) - actions.Add(CatchAction.Dash); - - if (Position.Value > CurrentFrame.Position) - actions.Add(CatchAction.MoveRight); - else if (Position.Value < CurrentFrame.Position) - actions.Add(CatchAction.MoveLeft); - return new List { new CatchReplayState { - PressedActions = actions, + PressedActions = CurrentFrame?.Actions ?? new List(), CatcherX = Position.Value }, }; diff --git a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs index 1e88b35c3b..19637f321b 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.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.Game.Beatmaps; using osu.Game.Replays.Legacy; using osu.Game.Rulesets.Catch.UI; @@ -11,6 +12,8 @@ namespace osu.Game.Rulesets.Catch.Replays { public class CatchReplayFrame : ReplayFrame, IConvertibleReplayFrame { + public List Actions = new List(); + public float Position; public bool Dashing; @@ -18,17 +21,39 @@ namespace osu.Game.Rulesets.Catch.Replays { } - public CatchReplayFrame(double time, float? position = null, bool dashing = false) + public CatchReplayFrame(double time, float? position = null, bool dashing = false, CatchReplayFrame lastFrame = null) : base(time) { Position = position ?? -1; Dashing = dashing; + + if (Dashing) + Actions.Add(CatchAction.Dash); + + if (lastFrame != null) + { + if (Position > lastFrame.Position) + Actions.Add(CatchAction.MoveRight); + else if (Position < lastFrame.Position) + Actions.Add(CatchAction.MoveLeft); + } } - public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap) + public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) { - Position = legacyFrame.Position.X / CatchPlayfield.BASE_WIDTH; - Dashing = legacyFrame.ButtonState == ReplayButtonState.Left1; + Position = currentFrame.Position.X / CatchPlayfield.BASE_WIDTH; + Dashing = currentFrame.ButtonState == ReplayButtonState.Left1; + + if (Dashing) + Actions.Add(CatchAction.Dash); + + if (lastFrame != null) + { + if (currentFrame.Position.X > lastFrame.Position.X) + Actions.Add(CatchAction.MoveRight); + else if (currentFrame.Position.X < lastFrame.Position.X) + Actions.Add(CatchAction.MoveLeft); + } } } } diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index f7277d3669..b2901f46c0 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Mania.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap) + public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) { // We don't need to fully convert, just create the converter var converter = new ManiaBeatmapConverter(beatmap); diff --git a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs index 4d90fcadd5..441b69ef2d 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs @@ -26,11 +26,11 @@ namespace osu.Game.Rulesets.Osu.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap) + public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) { - Position = legacyFrame.Position; - if (legacyFrame.MouseLeft) Actions.Add(OsuAction.LeftButton); - if (legacyFrame.MouseRight) Actions.Add(OsuAction.RightButton); + Position = currentFrame.Position; + if (currentFrame.MouseLeft) Actions.Add(OsuAction.LeftButton); + if (currentFrame.MouseRight) Actions.Add(OsuAction.RightButton); } } } diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs index 5203415e90..6e43892777 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs @@ -23,12 +23,12 @@ namespace osu.Game.Rulesets.Taiko.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap) + public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) { - if (legacyFrame.MouseRight1) Actions.Add(TaikoAction.LeftRim); - if (legacyFrame.MouseRight2) Actions.Add(TaikoAction.RightRim); - if (legacyFrame.MouseLeft1) Actions.Add(TaikoAction.LeftCentre); - if (legacyFrame.MouseLeft2) Actions.Add(TaikoAction.RightCentre); + if (currentFrame.MouseRight1) Actions.Add(TaikoAction.LeftRim); + if (currentFrame.MouseRight2) Actions.Add(TaikoAction.RightRim); + if (currentFrame.MouseLeft1) Actions.Add(TaikoAction.LeftCentre); + if (currentFrame.MouseLeft2) Actions.Add(TaikoAction.RightCentre); } } } diff --git a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs index 7ecdc0715b..8fcdec6630 100644 --- a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs @@ -14,8 +14,9 @@ namespace osu.Game.Rulesets.Replays.Types /// /// Populates this using values from a . /// - /// The to extract values from. + /// The to extract values from. /// The beatmap. - void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap); + /// The last , used to fill in missing delta information. May be null. + void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null); } } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 2e4b4b3a9a..5a90daa045 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -218,6 +218,7 @@ namespace osu.Game.Scoring.Legacy private void readLegacyReplay(Replay replay, StreamReader reader) { float lastTime = 0; + LegacyReplayFrame currentFrame = null; foreach (var l in reader.ReadToEnd().Split(',')) { @@ -240,23 +241,27 @@ namespace osu.Game.Scoring.Legacy if (diff < 0) continue; - replay.Frames.Add(convertFrame(new LegacyReplayFrame(lastTime, + var lastFrame = currentFrame; + + currentFrame = new LegacyReplayFrame(lastTime, Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE), Parsing.ParseFloat(split[2], Parsing.MAX_COORDINATE_VALUE), - (ReplayButtonState)Parsing.ParseInt(split[3])))); + (ReplayButtonState)Parsing.ParseInt(split[3])); + + replay.Frames.Add(convertFrame(currentFrame, lastFrame)); } } - private ReplayFrame convertFrame(LegacyReplayFrame legacyFrame) + private ReplayFrame convertFrame(LegacyReplayFrame currentFrame, LegacyReplayFrame lastFrame) { var convertible = currentRuleset.CreateConvertibleReplayFrame(); if (convertible == null) throw new InvalidOperationException($"Legacy replay cannot be converted for the ruleset: {currentRuleset.Description}"); - convertible.ConvertFrom(legacyFrame, currentBeatmap); + convertible.ConvertFrom(currentFrame, currentBeatmap, lastFrame); var frame = (ReplayFrame)convertible; - frame.Time = legacyFrame.Time; + frame.Time = currentFrame.Time; return frame; } From 68feedbd159b677879e77260b7f2b1f40e789185 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 18:46:42 +0900 Subject: [PATCH 2919/5608] Fix unreported CI issue --- osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 6783a36ac3..ad747e88e1 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -46,7 +46,6 @@ namespace osu.Game.Tests.Visual.Gameplay }); Key testKey = ((KeyCounterKeyboard)kc.Children.First()).Key; - double time1 = 0; AddStep($"Press {testKey} key", () => { @@ -60,7 +59,6 @@ namespace osu.Game.Tests.Visual.Gameplay { InputManager.PressKey(testKey); InputManager.ReleaseKey(testKey); - time1 = Clock.CurrentTime; }); AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 2); From f21e47d6d2a513451dff67eeaa0bf1f78426f69a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 19:29:08 +0900 Subject: [PATCH 2920/5608] Move expire to DrawableHitObject --- .../Drawable/DrawableCatchHitObject.cs | 4 +-- .../Drawables/DrawableManiaHitObject.cs | 4 +-- .../Objects/Drawables/DrawableHitCircle.cs | 26 +++++++++++++++---- .../Objects/Drawables/DrawableOsuHitObject.cs | 8 ++++++ .../Objects/Drawables/DrawableSlider.cs | 4 +-- .../Objects/Drawables/DrawableSpinner.cs | 6 ----- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 8 +----- .../Objects/Drawables/DrawableDrumRoll.cs | 2 +- .../Objects/Drawables/DrawableDrumRollTick.cs | 2 +- .../Objects/Drawables/DrawableHit.cs | 8 ++---- .../Objects/Drawables/DrawableSwell.cs | 2 -- .../Objects/Drawables/DrawableHitObject.cs | 5 +++- 12 files changed, 43 insertions(+), 36 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 00734810b3..51deae6e85 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -71,11 +71,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable switch (state) { case ArmedState.Miss: - this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out).Expire(); + this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out); break; case ArmedState.Hit: - this.FadeOut().Expire(); + this.FadeOut(); break; } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index e5b114ca81..5bfa07bd14 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -51,11 +51,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables switch (state) { case ArmedState.Miss: - this.FadeOut(150, Easing.In).Expire(); + this.FadeOut(150, Easing.In); break; case ArmedState.Hit: - this.FadeOut(150, Easing.OutQuint).Expire(); + this.FadeOut(150, Easing.OutQuint); break; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 985dcbca86..85fd68efdd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -86,6 +86,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables AccentColour.BindValueChanged(accent => ApproachCircle.Colour = accent.NewValue, true); } + public override double LifetimeStart + { + get => base.LifetimeStart; + set + { + base.LifetimeStart = value; + ApproachCircle.LifetimeStart = value; + } + } + + public override double LifetimeEnd + { + get => base.LifetimeEnd; + set + { + base.LifetimeEnd = value; + ApproachCircle.LifetimeEnd = value; + } + } + protected override void CheckForResult(bool userTriggered, double timeOffset) { Debug.Assert(HitObject.HitWindows != null); @@ -132,22 +152,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Expire(true); hitArea.HitAction = null; - - // override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early. - LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.WindowFor(HitResult.Miss); break; case ArmedState.Miss: ApproachCircle.FadeOut(50); this.FadeOut(100); - Expire(); break; case ArmedState.Hit: ApproachCircle.FadeOut(50); // todo: temporary / arbitrary - this.Delay(800).Expire(); + this.Delay(800).FadeOut(); break; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index fcd42314fc..8a7e5117f9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -41,6 +41,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength); + protected override void LoadComplete() + { + base.LoadComplete(); + + // Manually set to reduce the number of future alive objects to a bare minimum. + LifetimeStart = HitObject.StartTime - HitObject.TimePreempt; + } + protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(HitObject, judgement); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 00c953c393..65f1d5e15f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -219,10 +219,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables break; } - this.FadeOut(fade_out_time, Easing.OutQuint).Expire(); + this.FadeOut(fade_out_time, Easing.OutQuint); } - - Expire(true); } public Drawable ProxiedLayer => HeadCircle.ApproachCircle; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 49aaa2aaea..b1185ddba8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -219,10 +219,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables switch (state) { - case ArmedState.Idle: - Expire(true); - break; - case ArmedState.Hit: sequence.ScaleTo(Scale * 1.2f, 320, Easing.Out); break; @@ -231,8 +227,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables sequence.ScaleTo(Scale * 0.8f, 320, Easing.In); break; } - - Expire(); } } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index ea7eee8bb8..df12ebc514 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -70,13 +70,7 @@ namespace osu.Game.Rulesets.Osu.UI base.Add(h); } - private void addApproachCircleProxy(Drawable d) - { - var proxy = d.CreateProxy(); - proxy.LifetimeStart = d.LifetimeStart; - proxy.LifetimeEnd = d.LifetimeEnd; - approachCircles.Add(proxy); - } + private void addApproachCircleProxy(Drawable d) => approachCircles.Add(d.CreateProxy()); public override void PostProcess() { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index f4407a7b54..8e16a21199 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { case ArmedState.Hit: case ArmedState.Miss: - this.Delay(HitObject.Duration).FadeOut(100).Expire(); + this.Delay(HitObject.Duration).FadeOut(100); break; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index cef9a53deb..25b6141a0e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (state) { case ArmedState.Hit: - this.ScaleTo(0, 100, Easing.OutQuint).Expire(); + this.ScaleTo(0, 100, Easing.OutQuint); break; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 676ecd5a0b..4b25ff0ecc 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -105,12 +105,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables validActionPressed = false; UnproxyContent(); - this.Delay(HitObject.HitWindows.WindowFor(HitResult.Miss)).Expire(); break; case ArmedState.Miss: - this.FadeOut(100) - .Expire(); + this.FadeOut(100); break; case ArmedState.Hit: @@ -129,9 +127,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables .Then() .MoveToY(gravity_travel_height * 2, gravity_time * 2, Easing.In); - this.FadeOut(800) - .Expire(); - + this.FadeOut(800); break; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 094ad1230f..07af7fe7e0 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -208,8 +208,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { this.FadeOut(transition_duration, Easing.Out); bodyContainer.ScaleTo(1.4f, transition_duration); - - Expire(); } break; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index e3390c8cf0..90c49a0144 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -153,7 +153,6 @@ namespace osu.Game.Rulesets.Objects.Drawables if (UseTransformStateManagement) { - lifetimeStart = null; LifetimeEnd = double.MaxValue; double transformTime = HitObject.StartTime - InitialLifetimeOffset; @@ -173,6 +172,9 @@ namespace osu.Game.Rulesets.Objects.Drawables state.Value = newState; } } + + if (state.Value != ArmedState.Idle && LifetimeEnd == double.MaxValue) + Expire(); } else state.Value = newState; @@ -203,6 +205,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Apply transforms based on the current . Previous states are automatically cleared. + /// In the case of a non-idle , and if was not set during this call, will be invoked. /// /// The new armed state. protected virtual void UpdateStateTransforms(ArmedState state) From b81b162ee12a96b0668222ee57ac477567851a0a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 19:30:27 +0900 Subject: [PATCH 2921/5608] Update InitialLifetimeOffset comment --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 90c49a0144..00b57f7249 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -314,7 +314,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// This is only used as an optimisation to delay the initial update of this and may be tuned more aggressively if required. /// It is indirectly used to decide the automatic transform offset provided to . - /// A more accurate should be set inside for an state. + /// A more accurate should be set for further optimisation (in , for example). /// protected virtual double InitialLifetimeOffset => 10000; From cafb5105bc4b4997bc0c75259c9c1ce587d0c768 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 16:44:15 +0300 Subject: [PATCH 2922/5608] Rename HeaderFlag to DismissableFlag --- ...aderFlag.cs => TestSceneRankingsDismissableFlag.cs} | 10 +++++----- .../Rankings/{HeaderFlag.cs => DismissableFlag.cs} | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) rename osu.Game.Tests/Visual/Online/{TestSceneRankingsHeaderFlag.cs => TestSceneRankingsDismissableFlag.cs} (88%) rename osu.Game/Overlays/Rankings/{HeaderFlag.cs => DismissableFlag.cs} (94%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs similarity index 88% rename from osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs rename to osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs index c9531e1016..db6afa9bf3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs @@ -12,16 +12,16 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { - public class TestSceneRankingsHeaderFlag : OsuTestScene + public class TestSceneRankingsDismissableFlag : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { - typeof(HeaderFlag), + typeof(DismissableFlag), }; - public TestSceneRankingsHeaderFlag() + public TestSceneRankingsDismissableFlag() { - HeaderFlag flag; + DismissableFlag flag; SpriteText text; var countryA = new Country @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Online AddRange(new Drawable[] { - flag = new HeaderFlag + flag = new DismissableFlag { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Rankings/HeaderFlag.cs b/osu.Game/Overlays/Rankings/DismissableFlag.cs similarity index 94% rename from osu.Game/Overlays/Rankings/HeaderFlag.cs rename to osu.Game/Overlays/Rankings/DismissableFlag.cs index 6f641c74a5..7a55b0bba6 100644 --- a/osu.Game/Overlays/Rankings/HeaderFlag.cs +++ b/osu.Game/Overlays/Rankings/DismissableFlag.cs @@ -11,7 +11,7 @@ using System; namespace osu.Game.Overlays.Rankings { - public class HeaderFlag : UpdateableFlag + public class DismissableFlag : UpdateableFlag { private const int duration = 200; @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Rankings private readonly SpriteIcon hoverIcon; - public HeaderFlag() + public DismissableFlag() { AddInternal(hoverIcon = new SpriteIcon { From b17d097a39d7edd1d15f6d2744029d47c7f2b08d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 17:17:57 +0300 Subject: [PATCH 2923/5608] Simplify colour usage in GradientLine --- .../UserInterface/GradientLineTabControl.cs | 38 +++++-------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs index 7cd8d2c5bd..3523876fca 100644 --- a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -8,7 +8,6 @@ using osuTK; using osu.Framework.Graphics.Shapes; using osuTK.Graphics; using osu.Framework.Graphics.Colour; -using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Graphics.UserInterface @@ -19,8 +18,8 @@ namespace osu.Game.Graphics.UserInterface protected Color4 LineColour { - get => line.MainColour.Value; - set => line.MainColour.Value = value; + get => line.Colour; + set => line.Colour = value; } private readonly GradientLine line; @@ -48,12 +47,6 @@ namespace osu.Game.Graphics.UserInterface private class GradientLine : GridContainer { - public readonly Bindable MainColour = new Bindable(); - - private readonly Box left; - private readonly Box middle; - private readonly Box right; - public GradientLine() { RelativeSizeAxes = Axes.X; @@ -70,34 +63,23 @@ namespace osu.Game.Graphics.UserInterface { new Drawable[] { - left = new Box + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(Color4.White.Opacity(0), Color4.White) + }, + new Box { RelativeSizeAxes = Axes.Both, }, - middle = new Box - { - RelativeSizeAxes = Axes.Both, - }, - right = new Box + new Box { RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(Color4.White, Color4.White.Opacity(0)) }, } }; } - - protected override void LoadComplete() - { - MainColour.BindValueChanged(onColourChanged, true); - base.LoadComplete(); - } - - private void onColourChanged(ValueChangedEvent colour) - { - left.Colour = ColourInfo.GradientHorizontal(colour.NewValue.Opacity(0), colour.NewValue); - middle.Colour = colour.NewValue; - right.Colour = ColourInfo.GradientHorizontal(colour.NewValue, colour.NewValue.Opacity(0)); - } } } } From 7ee01ee3233a5a3d7eee3b1f41a018d923567e35 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 18:11:48 +0300 Subject: [PATCH 2924/5608] Use assignment instead of binding --- osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs index 2081a6c0cb..178016c648 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs @@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Online { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Current = { BindTarget = scope } + Current = scope } }); From 99fc13b4d85a17e4dcf5c65012c857892674e36c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 19:34:58 +0300 Subject: [PATCH 2925/5608] Update usage of the DismissableFlag --- osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs | 2 +- osu.Game/Overlays/Rankings/HeaderTitle.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs index 0f16b2592f..849ca2defc 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Online { public override IReadOnlyList RequiredTypes => new[] { - typeof(HeaderFlag), + typeof(DismissableFlag), typeof(HeaderTitle), }; diff --git a/osu.Game/Overlays/Rankings/HeaderTitle.cs b/osu.Game/Overlays/Rankings/HeaderTitle.cs index 3f1feb10b8..a00c6c6dcd 100644 --- a/osu.Game/Overlays/Rankings/HeaderTitle.cs +++ b/osu.Game/Overlays/Rankings/HeaderTitle.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Rankings private readonly SpriteText scopeText; private readonly Container flagPlaceholder; - private readonly HeaderFlag flag; + private readonly DismissableFlag flag; public HeaderTitle() { @@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Rankings Origin = Anchor.BottomLeft, AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Bottom = flag_margin }, - Child = flag = new HeaderFlag + Child = flag = new DismissableFlag { Size = new Vector2(30, 20), }, From 2a8fa2f5936543aa1c77baed96836a26d9c8ef98 Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 12 Sep 2019 14:01:12 -0700 Subject: [PATCH 2926/5608] Refactor modsContainer on profile scores --- .../Sections/Ranks/DrawableProfileScore.cs | 9 ++++---- .../Sections/Ranks/ScoreModsContainer.cs | 21 ------------------- 2 files changed, 5 insertions(+), 25 deletions(-) delete mode 100644 osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index e54ce44ca2..6362d3dfb0 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -12,12 +12,13 @@ using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Beatmaps; using osu.Framework.Localisation; +using osu.Framework.Graphics.Containers; namespace osu.Game.Overlays.Profile.Sections.Ranks { public abstract class DrawableProfileScore : DrawableProfileRow { - private readonly ScoreModsContainer modsContainer; + private readonly FillFlowContainer modsContainer; protected readonly ScoreInfo Score; protected DrawableProfileScore(ScoreInfo score) @@ -28,12 +29,12 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Height = 60; Children = new Drawable[] { - modsContainer = new ScoreModsContainer + modsContainer = new FillFlowContainer { - AutoSizeAxes = Axes.Y, + AutoSizeAxes = Axes.Both, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Width = 60, + Spacing = new Vector2(1), Margin = new MarginPadding { Right = 160 } } }; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs deleted file mode 100644 index 1ce04effa8..0000000000 --- a/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osuTK; -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.UI; -using System.Collections.Generic; -using System.Linq; - -namespace osu.Game.Overlays.Profile.Sections.Ranks -{ - public class ScoreModsContainer : FlowContainer - { - protected override IEnumerable ComputeLayoutPositions() - { - int count = FlowingChildren.Count(); - for (int i = 0; i < count; i++) - yield return new Vector2(DrawWidth * i * (count == 1 ? 0 : 1f / (count - 1)), 0); - } - } -} From b917f29cfe6cccf9158332edc694572cbb7c302b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 13:59:06 +0900 Subject: [PATCH 2927/5608] Make GradientLineTabControl abstract --- osu.Game/Graphics/UserInterface/GradientLineTabControl.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs index 3523876fca..a9bbda4194 100644 --- a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -12,10 +12,8 @@ using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Graphics.UserInterface { - public class GradientLineTabControl : PageTabControl + public abstract class GradientLineTabControl : PageTabControl { - protected override Dropdown CreateDropdown() => null; - protected Color4 LineColour { get => line.Colour; @@ -24,7 +22,7 @@ namespace osu.Game.Graphics.UserInterface private readonly GradientLine line; - public GradientLineTabControl() + protected GradientLineTabControl() { RelativeSizeAxes = Axes.X; @@ -35,6 +33,8 @@ namespace osu.Game.Graphics.UserInterface }); } + protected override Dropdown CreateDropdown() => null; + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer { Anchor = Anchor.BottomCentre, From 0e679fb468a4ee27dc0b57bd6aefbcfbce67ccfc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 14:06:19 +0900 Subject: [PATCH 2928/5608] Use colour constant rather than opacity helper function --- osu.Game/Graphics/UserInterface/GradientLineTabControl.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs index a9bbda4194..4fd4a2adbd 100644 --- a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -8,7 +8,6 @@ using osuTK; using osu.Framework.Graphics.Shapes; using osuTK.Graphics; using osu.Framework.Graphics.Colour; -using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Graphics.UserInterface { @@ -66,7 +65,7 @@ namespace osu.Game.Graphics.UserInterface new Box { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4.White.Opacity(0), Color4.White) + Colour = ColourInfo.GradientHorizontal(Color4.Transparent, Color4.White) }, new Box { @@ -75,7 +74,7 @@ namespace osu.Game.Graphics.UserInterface new Box { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4.White, Color4.White.Opacity(0)) + Colour = ColourInfo.GradientHorizontal(Color4.White, Color4.Transparent) }, } }; From 44947aa9edece7d0c140aa8660aa6c342a28b54f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 15:27:29 +0900 Subject: [PATCH 2929/5608] Make PopupDialog abstract --- .../UserInterface/TestSceneDialogOverlay.cs | 8 +++++-- .../UserInterface/TestScenePopupDialog.cs | 23 ++++++++++++------- osu.Game/Overlays/Dialog/PopupDialog.cs | 2 +- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs index a6ff3462d4..cc4a57fb83 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.UserInterface Add(overlay = new DialogOverlay()); - AddStep("dialog #1", () => overlay.Push(new PopupDialog + AddStep("dialog #1", () => overlay.Push(new TestPopupDialog { Icon = FontAwesome.Regular.TrashAlt, HeaderText = @"Confirm deletion of", @@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual.UserInterface }, })); - AddStep("dialog #2", () => overlay.Push(new PopupDialog + AddStep("dialog #2", () => overlay.Push(new TestPopupDialog { Icon = FontAwesome.Solid.Cog, HeaderText = @"What do you want to do with", @@ -71,5 +71,9 @@ namespace osu.Game.Tests.Visual.UserInterface }, })); } + + private class TestPopupDialog : PopupDialog + { + } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs index 9ddd8f4038..3d39bb7003 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs @@ -13,13 +13,22 @@ namespace osu.Game.Tests.Visual.UserInterface { public TestScenePopupDialog() { - var popup = new PopupDialog + Add(new TestPopupDialog { RelativeSizeAxes = Axes.Both, State = { Value = Framework.Graphics.Containers.Visibility.Visible }, - Icon = FontAwesome.Solid.AssistiveListeningSystems, - HeaderText = @"This is a test popup", - BodyText = "I can say lots of stuff and even wrap my words!", + }); + } + + private class TestPopupDialog : PopupDialog + { + public TestPopupDialog() + { + Icon = FontAwesome.Solid.AssistiveListeningSystems; + + HeaderText = @"This is a test popup"; + BodyText = "I can say lots of stuff and even wrap my words!"; + Buttons = new PopupDialogButton[] { new PopupDialogCancelButton @@ -30,10 +39,8 @@ namespace osu.Game.Tests.Visual.UserInterface { Text = @"You're a fake!", }, - } - }; - - Add(popup); + }; + } } } } diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index 5c0ddb47b1..37674a5dcb 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -19,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Overlays.Dialog { - public class PopupDialog : VisibilityContainer + public abstract class PopupDialog : VisibilityContainer { public static readonly float ENTER_DURATION = 500; public static readonly float EXIT_DURATION = 200; From dc8c7a50414caa25b9304f7cc99a1a9d45ebea44 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 15:27:42 +0900 Subject: [PATCH 2930/5608] Add null check for safety --- osu.Game/Overlays/DialogOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index 0d3c96c984..6aaeff8554 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -80,7 +80,7 @@ namespace osu.Game.Overlays switch (action) { case GlobalAction.Select: - currentDialog.Buttons.OfType().FirstOrDefault()?.Click(); + currentDialog?.Buttons.OfType().FirstOrDefault()?.Click(); return true; } From c66e96370531ae6baf9c1779cbfa20eecb045ba4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 15:42:36 +0900 Subject: [PATCH 2931/5608] Make constructor private --- osu.Game/Overlays/Dialog/PopupDialog.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index 37674a5dcb..cff887865a 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -87,7 +87,7 @@ namespace osu.Game.Overlays.Dialog } } - public PopupDialog() + protected PopupDialog() { RelativeSizeAxes = Axes.Both; From cf2f841b4d00da43aa1c4dd496d34df0a80a0746 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Sep 2019 15:41:53 +0900 Subject: [PATCH 2932/5608] Fix player not correctly exiting after an unpause --- .../Visual/Gameplay/TestScenePause.cs | 10 ++++++++++ osu.Game/Screens/Play/Player.cs | 19 +++++++++++-------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 5808a78056..50583e43c4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -160,6 +160,15 @@ namespace osu.Game.Tests.Visual.Gameplay exitAndConfirm(); } + [Test] + public void TestRestartAfterResume() + { + pauseAndConfirm(); + resumeAndConfirm(); + restart(); + confirmExited(); + } + private void pauseAndConfirm() { pause(); @@ -198,6 +207,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("player exited", () => !Player.IsCurrentScreen()); } + private void restart() => AddStep("restart", () => Player.Restart()); private void pause() => AddStep("pause", () => Player.Pause()); private void resume() => AddStep("resume", () => Player.Resume()); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 3f1603eabe..3fd0f0260c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -502,15 +502,18 @@ namespace osu.Game.Screens.Play return true; } - if (pauseCooldownActive && !GameplayClockContainer.IsPaused.Value) - // still want to block if we are within the cooldown period and not already paused. - return true; - - if (HasFailed && ValidForResume && !FailOverlay.IsPresent) - // ValidForResume is false when restarting + // ValidForResume is false when restarting + if (ValidForResume) { - failAnimation.FinishTransforms(true); - return true; + if (pauseCooldownActive && !GameplayClockContainer.IsPaused.Value) + // still want to block if we are within the cooldown period and not already paused. + return true; + + if (HasFailed && !FailOverlay.IsPresent) + { + failAnimation.FinishTransforms(true); + return true; + } } GameplayClockContainer.ResetLocalAdjustments(); From 7818ecd71c1eab60b1c0f7f17b4dcc79f5357ad9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 16:03:44 +0900 Subject: [PATCH 2933/5608] Forward ValueChangedEvent instead --- osu.Game/Overlays/Rankings/HeaderTitle.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Rankings/HeaderTitle.cs b/osu.Game/Overlays/Rankings/HeaderTitle.cs index a00c6c6dcd..ed9dc99a79 100644 --- a/osu.Game/Overlays/Rankings/HeaderTitle.cs +++ b/osu.Game/Overlays/Rankings/HeaderTitle.cs @@ -73,16 +73,16 @@ namespace osu.Game.Overlays.Rankings protected override void LoadComplete() { - Scope.BindValueChanged(scope => onScopeChanged(scope.NewValue), true); + Scope.BindValueChanged(onScopeChanged, true); Country.BindValueChanged(onCountryChanged, true); base.LoadComplete(); } - private void onScopeChanged(RankingsScope scope) + private void onScopeChanged(ValueChangedEvent scope) { - scopeText.Text = scope.ToString(); + scopeText.Text = scope.NewValue.ToString(); - if (scope != RankingsScope.Performance) + if (scope.NewValue != RankingsScope.Performance) Country.Value = null; } From 78e7be919f7dc05f40b806a07d2e8847cb2275f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 16:25:25 +0900 Subject: [PATCH 2934/5608] Remove unnecessary container --- osu.Game/Overlays/Rankings/HeaderTitle.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Rankings/HeaderTitle.cs b/osu.Game/Overlays/Rankings/HeaderTitle.cs index ed9dc99a79..efaf4225d5 100644 --- a/osu.Game/Overlays/Rankings/HeaderTitle.cs +++ b/osu.Game/Overlays/Rankings/HeaderTitle.cs @@ -22,7 +22,6 @@ namespace osu.Game.Overlays.Rankings public readonly Bindable Country = new Bindable(); private readonly SpriteText scopeText; - private readonly Container flagPlaceholder; private readonly DismissableFlag flag; public HeaderTitle() @@ -35,16 +34,12 @@ namespace osu.Game.Overlays.Rankings Spacing = new Vector2(spacing, 0), Children = new Drawable[] { - flagPlaceholder = new Container + flag = new DismissableFlag { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Bottom = flag_margin }, - Child = flag = new DismissableFlag - { - Size = new Vector2(30, 20), - }, + Size = new Vector2(30, 20), }, scopeText = new SpriteText { @@ -90,15 +85,13 @@ namespace osu.Game.Overlays.Rankings { if (country.NewValue == null) { - flagPlaceholder.Hide(); + flag.Hide(); return; } Scope.Value = RankingsScope.Performance; - if (country.OldValue == null) - flagPlaceholder.Show(); - + flag.Show(); flag.Country = country.NewValue; } } From 51f17ccb1b8caec176e2b712066cd76caf453c98 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 13 Sep 2019 10:48:02 +0300 Subject: [PATCH 2935/5608] Remove test duplicate --- .../Online/TestSceneRankingsHeaderFlag.cs | 65 ------------------- 1 file changed, 65 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs deleted file mode 100644 index 17f6f8417b..0000000000 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osu.Game.Overlays.Rankings; -using osu.Game.Users; -using osuTK; - -namespace osu.Game.Tests.Visual.Online -{ - public class TestSceneRankingsHeaderFlag : OsuTestScene - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(DismissableFlag), - }; - - public TestSceneRankingsHeaderFlag() - { - DismissableFlag flag; - SpriteText text; - - var countryA = new Country - { - FlagName = "BY", - FullName = "Belarus" - }; - - var countryB = new Country - { - FlagName = "US", - FullName = "United States" - }; - - AddRange(new Drawable[] - { - flag = new DismissableFlag - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(30, 20), - Country = countryA, - }, - text = new SpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = "Invoked", - Font = OsuFont.GetFont(size: 30), - Alpha = 0, - } - }); - - flag.Action += () => text.FadeIn().Then().FadeOut(1000, Easing.OutQuint); - - AddStep("Trigger click", () => flag.Click()); - AddStep("Change to country 2", () => flag.Country = countryB); - AddStep("Change to country 1", () => flag.Country = countryA); - } - } -} From c9ae4336f944b779becfcf7f880cef8293a19815 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 13 Sep 2019 10:50:26 +0300 Subject: [PATCH 2936/5608] Fix RankingsScope test --- osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs index fef9c3a7b1..3693d6b5b4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs @@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Online { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Current = { BindTarget = scope } + Current = scope, } }); From 6867b3c23214a8a6f47d547cf6377cdf4d13919b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 13 Sep 2019 10:56:21 +0300 Subject: [PATCH 2937/5608] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 45c162a30e..4167d07698 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,7 +62,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index df8b11e653..5703293caf 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -25,7 +25,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 7c31744a14..683dccf3ae 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -117,7 +117,7 @@ - + From 9a9654dbd1021614d95969231a4d09523699b663 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 13 Sep 2019 10:59:09 +0300 Subject: [PATCH 2938/5608] Fix the Test Scene --- osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs index e8ed94b59c..0ceb5f21d3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tests.Visual.Online { public override IReadOnlyList RequiredTypes => new[] { - typeof(HeaderFlag), + typeof(DismissableFlag), typeof(HeaderTitle), typeof(RankingsRulesetSelector), typeof(RankingsScopeSelector), @@ -50,7 +50,7 @@ namespace osu.Game.Tests.Visual.Online new Spotlight { Id = 3, - Text = "Spotlight 4" + Text = "Spotlight 3" } } }); From 7cb79dd7605f37e9c5fdd67ec98cda660e4a46b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 17:15:33 +0900 Subject: [PATCH 2939/5608] Fix incorrect DI usage of IAPIProvider in many tests --- .../Visual/Menus/TestSceneDisclaimer.cs | 11 ++++---- .../Multiplayer/TestSceneMatchLeaderboard.cs | 2 +- .../Multiplayer/TestSceneMultiScreen.cs | 2 +- .../Online/TestSceneAccountCreationOverlay.cs | 14 +++++++---- .../Online/TestSceneBeatmapSetOverlay.cs | 2 +- .../Online/TestSceneChangelogOverlay.cs | 2 +- .../Visual/Online/TestSceneDirectOverlay.cs | 2 +- .../Online/TestSceneHistoricalSection.cs | 2 +- .../Visual/Online/TestSceneSocialOverlay.cs | 2 +- .../Online/TestSceneUserProfileHeader.cs | 2 +- .../Online/TestSceneUserProfileOverlay.cs | 2 +- .../Visual/Online/TestSceneUserRanks.cs | 2 +- ...tSceneUpdateableBeatmapBackgroundSprite.cs | 3 +-- osu.Game/Tests/Visual/OsuTestScene.cs | 25 ++++++++++++++----- 14 files changed, 44 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs index 13116de320..681bf1b40b 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Game.Online.API; using osu.Game.Screens.Menu; using osu.Game.Users; @@ -11,17 +10,17 @@ namespace osu.Game.Tests.Visual.Menus public class TestSceneDisclaimer : ScreenTestScene { [BackgroundDependencyLoader] - private void load(IAPIProvider api) + private void load() { AddStep("load disclaimer", () => LoadScreen(new Disclaimer())); AddStep("toggle support", () => { - api.LocalUser.Value = new User + API.LocalUser.Value = new User { - Username = api.LocalUser.Value.Username, - Id = api.LocalUser.Value.Id, - IsSupporter = !api.LocalUser.Value.IsSupporter, + Username = API.LocalUser.Value.Username, + Id = API.LocalUser.Value.Id, + IsSupporter = !API.LocalUser.Value.IsSupporter, }; }); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs index 723e5fc03d..7ba1782a28 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMatchLeaderboard : MultiplayerTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; public TestSceneMatchLeaderboard() { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs index b646433846..dfe61a4dda 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs @@ -12,7 +12,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [TestFixture] public class TestSceneMultiScreen : ScreenTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs index 66ab1fe18a..31eab7f74e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs @@ -4,9 +4,9 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Overlays.AccountCreation; using osu.Game.Users; @@ -27,6 +27,8 @@ namespace osu.Game.Tests.Visual.Online private readonly Container userPanelArea; + private Bindable localUser; + public TestSceneAccountCreationOverlay() { AccountCreationOverlay accountCreation; @@ -47,12 +49,14 @@ namespace osu.Game.Tests.Visual.Online } [BackgroundDependencyLoader] - private void load(IAPIProvider api) + private void load() { - api.Logout(); - api.LocalUser.BindValueChanged(user => { userPanelArea.Child = new UserPanel(user.NewValue) { Width = 200 }; }, true); + API.Logout(); - AddStep("logout", api.Logout); + localUser = API.LocalUser.GetBoundCopy(); + localUser.BindValueChanged(user => { userPanelArea.Child = new UserPanel(user.NewValue) { Width = 200 }; }, true); + + AddStep("logout", API.Logout); } } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 5068064a1f..9f03d947b9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Online typeof(BeatmapAvailability), }; - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; private RulesetInfo taikoRuleset; private RulesetInfo maniaRuleset; diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 324291c9d7..f555c276f4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.Online typeof(Comments), }; - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; protected override void LoadComplete() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs index 14ae975806..d9873ea243 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual.Online { private DirectOverlay direct; - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; protected override void LoadComplete() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs index c98f98c23d..d3b037f499 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneHistoricalSection : OsuTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs index 806b36e855..dbd7544b38 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneSocialOverlay : OsuTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index 555d5334d8..63b8acb234 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.Online { public class TestSceneUserProfileHeader : OsuTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index 42c8ffbf0a..93e6607ac5 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneUserProfileOverlay : OsuTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; private readonly TestUserProfileOverlay profile; diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs index d777f9766a..2951f6b63e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneUserRanks : OsuTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; public override IReadOnlyList RequiredTypes => new[] { typeof(DrawableProfileScore), typeof(RanksSection) }; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs index fdc50be3fa..d3359fd824 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneUpdateableBeatmapBackgroundSprite : OsuTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; private BeatmapSetInfo testBeatmap; private IAPIProvider api; @@ -32,7 +32,6 @@ namespace osu.Game.Tests.Visual.UserInterface [BackgroundDependencyLoader] private void load(OsuGameBase osu, IAPIProvider api, RulesetStore rulesets) { - this.api = api; this.rulesets = rulesets; testBeatmap = ImportBeatmapTest.LoadOszIntoOsu(osu).Result; diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index dd68ed93e6..5a7fbd31e2 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -46,13 +46,27 @@ namespace osu.Game.Tests.Visual protected Storage LocalStorage => localStorage.Value; private readonly Lazy contextFactory; + + protected IAPIProvider API + { + get + { + if (UseOnlineAPI) + throw new Exception("Using the OsuTestScene dummy API is not supported when UseOnlineAPI is true"); + + return dummyAPI; + } + } + + private DummyAPIAccess dummyAPI; + protected DatabaseContextFactory ContextFactory => contextFactory.Value; /// - /// Whether this test scene requires API access - /// Setting this will cache an actual . + /// Whether this test scene requires real-world API access. + /// If true, this will bypass the local and use the provided one. /// - protected virtual bool RequiresAPIAccess => false; + protected virtual bool UseOnlineAPI => false; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { @@ -66,10 +80,9 @@ namespace osu.Game.Tests.Visual Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - if (!RequiresAPIAccess) + if (!UseOnlineAPI) { - var dummyAPI = new DummyAPIAccess(); - + dummyAPI = new DummyAPIAccess(); Dependencies.CacheAs(dummyAPI); Add(dummyAPI); } From 0cc21c9c747979052603576c25be1ec0bd502034 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 17:21:47 +0900 Subject: [PATCH 2940/5608] Fix changelog overlay potentially adding children after disposal --- osu.Game/Overlays/ChangelogOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 7755c8a6a6..dfe3669813 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -170,7 +170,7 @@ namespace osu.Game.Overlays var tcs = new TaskCompletionSource(); var req = new GetChangelogRequest(); - req.Success += res => + req.Success += res => Schedule(() => { // remap streams to builds to ensure model equality res.Builds.ForEach(b => b.UpdateStream = res.Streams.Find(s => s.Id == b.UpdateStream.Id)); @@ -182,7 +182,7 @@ namespace osu.Game.Overlays header.Streams.Populate(res.Streams); tcs.SetResult(true); - }; + }); req.Failure += _ => initialFetchTask = null; req.Perform(API); From d681f43e29c2c45fa50c762c47955668e9872e21 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2019 08:38:02 +0000 Subject: [PATCH 2941/5608] Bump ppy.osu.Game.Resources from 2019.904.0 to 2019.913.0 Bumps [ppy.osu.Game.Resources](https://github.com/ppy/osu-resources) from 2019.904.0 to 2019.913.0. - [Release notes](https://github.com/ppy/osu-resources/releases) - [Commits](https://github.com/ppy/osu-resources/compare/2019.904.0...2019.913.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 45c162a30e..4167d07698 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,7 +62,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index df8b11e653..5703293caf 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -25,7 +25,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 7c31744a14..683dccf3ae 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -117,7 +117,7 @@ - + From a7c59098ce51be6eb3828d9029f57bfe51e02688 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 17:38:04 +0900 Subject: [PATCH 2942/5608] Fix missing assignment --- .../UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs index d3359fd824..198cc70e01 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs @@ -32,6 +32,7 @@ namespace osu.Game.Tests.Visual.UserInterface [BackgroundDependencyLoader] private void load(OsuGameBase osu, IAPIProvider api, RulesetStore rulesets) { + this.api = api; this.rulesets = rulesets; testBeatmap = ImportBeatmapTest.LoadOszIntoOsu(osu).Result; From 1e4f3507ed9c0529eda45ab530fe2430aa85cf07 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 18:07:52 +0900 Subject: [PATCH 2943/5608] Fix layout not matching web --- osu.Game/Overlays/Rankings/RankingsHeader.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs index 6d55e92502..18a0599036 100644 --- a/osu.Game/Overlays/Rankings/RankingsHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -20,7 +20,6 @@ namespace osu.Game.Overlays.Rankings private const int content_height = 250; private const int dropdown_height = 50; private const int spacing = 20; - private const int title_offset = 30; private const int duration = 200; public IEnumerable Spotlights @@ -68,27 +67,25 @@ namespace osu.Game.Overlays.Rankings Masking = true, Child = new HeaderBackground(), }, - new RankingsScopeSelector - { - Margin = new MarginPadding { Top = 10 }, - Current = { BindTarget = Scope } - }, new FillFlowContainer { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Y = title_offset, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Direction = FillDirection.Vertical, Spacing = new Vector2(0, spacing), Children = new Drawable[] { + new RankingsScopeSelector + { + Margin = new MarginPadding { Top = 10 }, + Current = { BindTarget = Scope } + }, new HeaderTitle { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Scope = { BindTarget = Scope }, + Margin = new MarginPadding { Top = 10 }, Country = { BindTarget = Country }, }, dropdownPlaceholder = new Container From 031f0ee1e7251308e1830ad86dcca94f69ee7656 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 18:09:15 +0900 Subject: [PATCH 2944/5608] Consume ValueChanged and inline some pointless constants --- osu.Game/Overlays/Rankings/RankingsHeader.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs index 18a0599036..4e502fb7fe 100644 --- a/osu.Game/Overlays/Rankings/RankingsHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -19,8 +19,6 @@ namespace osu.Game.Overlays.Rankings { private const int content_height = 250; private const int dropdown_height = 50; - private const int spacing = 20; - private const int duration = 200; public IEnumerable Spotlights { @@ -72,7 +70,7 @@ namespace osu.Game.Overlays.Rankings AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Direction = FillDirection.Vertical, - Spacing = new Vector2(0, spacing), + Spacing = new Vector2(0, 20), Children = new Drawable[] { new RankingsScopeSelector @@ -112,12 +110,12 @@ namespace osu.Game.Overlays.Rankings protected override void LoadComplete() { - Scope.BindValueChanged(scope => onScopeChanged(scope.NewValue), true); + Scope.BindValueChanged(onScopeChanged, true); base.LoadComplete(); } - private void onScopeChanged(RankingsScope scope) => - dropdownPlaceholder.FadeTo(scope == RankingsScope.Spotlights ? 1 : 0, duration, Easing.OutQuint); + private void onScopeChanged(ValueChangedEvent scope) => + dropdownPlaceholder.FadeTo(scope.NewValue == RankingsScope.Spotlights ? 1 : 0, 200, Easing.OutQuint); private class HeaderBackground : Sprite { From 614e68cdf960cd15667f4b2597012320239750a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 18:10:52 +0900 Subject: [PATCH 2945/5608] Remove redundant BindTarget usage --- osu.Game/Overlays/Rankings/RankingsHeader.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs index 4e502fb7fe..fbf3097f4f 100644 --- a/osu.Game/Overlays/Rankings/RankingsHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -49,7 +49,7 @@ namespace osu.Game.Overlays.Rankings { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Current = { BindTarget = Ruleset } + Current = Ruleset }, new Container { @@ -76,14 +76,14 @@ namespace osu.Game.Overlays.Rankings new RankingsScopeSelector { Margin = new MarginPadding { Top = 10 }, - Current = { BindTarget = Scope } + Current = Scope }, new HeaderTitle { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Scope = { BindTarget = Scope }, Margin = new MarginPadding { Top = 10 }, + Scope = { BindTarget = Scope }, Country = { BindTarget = Country }, }, dropdownPlaceholder = new Container @@ -97,7 +97,7 @@ namespace osu.Game.Overlays.Rankings Child = dropdown = new OsuDropdown { RelativeSizeAxes = Axes.X, - Current = { BindTarget = Spotlight }, + Current = Spotlight, } } } From 5c2c055614d943f1cc46d8b8f1faf8f0bb17daa9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Sep 2019 18:49:21 +0900 Subject: [PATCH 2946/5608] Set lifetime on initial state update --- .../Objects/Drawables/DrawableHitCircle.cs | 2 ++ .../Objects/Drawables/DrawableOsuHitObject.cs | 13 +++++++++---- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 ++ .../Objects/Drawables/DrawableSlider.cs | 2 ++ .../Objects/Drawables/DrawableSliderTick.cs | 2 ++ .../Objects/Drawables/DrawableSpinner.cs | 2 ++ 6 files changed, 19 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 85fd68efdd..83646c561d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -142,6 +142,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateStateTransforms(ArmedState state) { + base.UpdateStateTransforms(state); + Debug.Assert(HitObject.HitWindows != null); switch (state) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 8a7e5117f9..c46343c73c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -41,12 +41,17 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength); - protected override void LoadComplete() + protected override void UpdateStateTransforms(ArmedState state) { - base.LoadComplete(); + base.UpdateStateTransforms(state); - // Manually set to reduce the number of future alive objects to a bare minimum. - LifetimeStart = HitObject.StartTime - HitObject.TimePreempt; + switch (state) + { + case ArmedState.Idle: + // Manually set to reduce the number of future alive objects to a bare minimum. + LifetimeStart = HitObject.StartTime - HitObject.TimePreempt; + break; + } } protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(HitObject, judgement); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 00a943a67f..84d2a4af9b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -74,6 +74,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateStateTransforms(ArmedState state) { + base.UpdateStateTransforms(state); + switch (state) { case ArmedState.Idle: diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 65f1d5e15f..08b43b0345 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -202,6 +202,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateStateTransforms(ArmedState state) { + base.UpdateStateTransforms(state); + Ball.FadeIn(); Ball.ScaleTo(HitObject.Scale); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index ba931976a8..9d4d9958a1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -75,6 +75,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateStateTransforms(ArmedState state) { + base.UpdateStateTransforms(state); + switch (state) { case ArmedState.Idle: diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index b1185ddba8..d1b9ee6cb4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -215,6 +215,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateStateTransforms(ArmedState state) { + base.UpdateStateTransforms(state); + var sequence = this.Delay(Spinner.Duration).FadeOut(160); switch (state) From a6420def9909b6e375c57f6f43e1b9f05edb401f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 19:29:49 +0900 Subject: [PATCH 2947/5608] Make hyperdash test automatic --- osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs index a603d96201..7b8c699f2c 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs @@ -16,6 +16,8 @@ namespace osu.Game.Rulesets.Catch.Tests { } + protected override bool Autoplay => true; + [Test] public void TestHyperDash() { From c13950fbbf801d92a8c62aa4075ef51e2dadc323 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 13 Sep 2019 13:43:21 +0300 Subject: [PATCH 2948/5608] Remove custom db additions --- osu.Game/Migrations/20171019041408_InitialCreate.cs | 1 - osu.Game/Migrations/20181007180454_StandardizePaths.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game/Migrations/20171019041408_InitialCreate.cs b/osu.Game/Migrations/20171019041408_InitialCreate.cs index 3349998873..9b6881f98c 100644 --- a/osu.Game/Migrations/20171019041408_InitialCreate.cs +++ b/osu.Game/Migrations/20171019041408_InitialCreate.cs @@ -35,7 +35,6 @@ namespace osu.Game.Migrations AudioFile = table.Column(type: "TEXT", nullable: true), Author = table.Column(type: "TEXT", nullable: true), BackgroundFile = table.Column(type: "TEXT", nullable: true), - VideoFile = table.Column(type: "TEXT", nullable: true), PreviewTime = table.Column(type: "INTEGER", nullable: false), Source = table.Column(type: "TEXT", nullable: true), Tags = table.Column(type: "TEXT", nullable: true), diff --git a/osu.Game/Migrations/20181007180454_StandardizePaths.cs b/osu.Game/Migrations/20181007180454_StandardizePaths.cs index c106b839e2..274b8030a9 100644 --- a/osu.Game/Migrations/20181007180454_StandardizePaths.cs +++ b/osu.Game/Migrations/20181007180454_StandardizePaths.cs @@ -15,7 +15,6 @@ namespace osu.Game.Migrations migrationBuilder.Sql($"UPDATE `BeatmapInfo` SET `Path` = REPLACE(`Path`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `BeatmapMetadata` SET `AudioFile` = REPLACE(`AudioFile`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `BeatmapMetadata` SET `BackgroundFile` = REPLACE(`BackgroundFile`, '{windowsStyle}', '{standardized}')"); - migrationBuilder.Sql($"UPDATE `BeatmapMetadata` SET `VideoFile` = REPLACE(`VideoFile`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `BeatmapSetFileInfo` SET `Filename` = REPLACE(`Filename`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `SkinFileInfo` SET `Filename` = REPLACE(`Filename`, '{windowsStyle}', '{standardized}')"); } From 9e742839ac360f81f45c3db28c7587b1d4cd4002 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 13 Sep 2019 13:57:55 +0300 Subject: [PATCH 2949/5608] Use correct database migration --- ...20190913104727_AddBeatmapVideo.Designer.cs | 506 ++++++++++++++++++ .../20190913104727_AddBeatmapVideo.cs | 22 + .../Migrations/OsuDbContextModelSnapshot.cs | 4 +- 3 files changed, 531 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Migrations/20190913104727_AddBeatmapVideo.Designer.cs create mode 100644 osu.Game/Migrations/20190913104727_AddBeatmapVideo.cs diff --git a/osu.Game/Migrations/20190913104727_AddBeatmapVideo.Designer.cs b/osu.Game/Migrations/20190913104727_AddBeatmapVideo.Designer.cs new file mode 100644 index 0000000000..826233a2b0 --- /dev/null +++ b/osu.Game/Migrations/20190913104727_AddBeatmapVideo.Designer.cs @@ -0,0 +1,506 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using osu.Game.Database; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20190913104727_AddBeatmapVideo")] + partial class AddBeatmapVideo + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("ApproachRate"); + + b.Property("CircleSize"); + + b.Property("DrainRate"); + + b.Property("OverallDifficulty"); + + b.Property("SliderMultiplier"); + + b.Property("SliderTickRate"); + + b.HasKey("ID"); + + b.ToTable("BeatmapDifficulty"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("AudioLeadIn"); + + b.Property("BPM"); + + b.Property("BaseDifficultyID"); + + b.Property("BeatDivisor"); + + b.Property("BeatmapSetInfoID"); + + b.Property("Countdown"); + + b.Property("DistanceSpacing"); + + b.Property("GridSize"); + + b.Property("Hash"); + + b.Property("Hidden"); + + b.Property("Length"); + + b.Property("LetterboxInBreaks"); + + b.Property("MD5Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapID"); + + b.Property("Path"); + + b.Property("RulesetID"); + + b.Property("SpecialStyle"); + + b.Property("StackLeniency"); + + b.Property("StarDifficulty"); + + b.Property("Status"); + + b.Property("StoredBookmarks"); + + b.Property("TimelineZoom"); + + b.Property("Version"); + + b.Property("WidescreenStoryboard"); + + b.HasKey("ID"); + + b.HasIndex("BaseDifficultyID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("Hash"); + + b.HasIndex("MD5Hash"); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("BeatmapInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Artist"); + + b.Property("ArtistUnicode"); + + b.Property("AudioFile"); + + b.Property("AuthorString") + .HasColumnName("Author"); + + b.Property("BackgroundFile"); + + b.Property("PreviewTime"); + + b.Property("Source"); + + b.Property("Tags"); + + b.Property("Title"); + + b.Property("TitleUnicode"); + + b.Property("VideoFile"); + + b.HasKey("ID"); + + b.ToTable("BeatmapMetadata"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("BeatmapSetInfoID"); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.HasKey("ID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("FileInfoID"); + + b.ToTable("BeatmapSetFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("DateAdded"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapSetID"); + + b.Property("Protected"); + + b.Property("Status"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapSetID") + .IsUnique(); + + b.ToTable("BeatmapSetInfo"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Key") + .HasColumnName("Key"); + + b.Property("RulesetID"); + + b.Property("SkinInfoID"); + + b.Property("StringValue") + .HasColumnName("Value"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("SkinInfoID"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("osu.Game.IO.FileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Hash"); + + b.Property("ReferenceCount"); + + b.HasKey("ID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("ReferenceCount"); + + b.ToTable("FileInfo"); + }); + + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntAction") + .HasColumnName("Action"); + + b.Property("KeysString") + .HasColumnName("Keys"); + + b.Property("RulesetID"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("IntAction"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("KeyBinding"); + }); + + modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Available"); + + b.Property("InstantiationInfo"); + + b.Property("Name"); + + b.Property("ShortName"); + + b.HasKey("ID"); + + b.HasIndex("Available"); + + b.HasIndex("ShortName") + .IsUnique(); + + b.ToTable("RulesetInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("ScoreInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("ScoreInfoID"); + + b.ToTable("ScoreFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Accuracy") + .HasColumnType("DECIMAL(1,4)"); + + b.Property("BeatmapInfoID"); + + b.Property("Combo"); + + b.Property("Date"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MaxCombo"); + + b.Property("ModsJson") + .HasColumnName("Mods"); + + b.Property("OnlineScoreID"); + + b.Property("PP"); + + b.Property("Rank"); + + b.Property("RulesetID"); + + b.Property("StatisticsJson") + .HasColumnName("Statistics"); + + b.Property("TotalScore"); + + b.Property("UserID") + .HasColumnName("UserID"); + + b.Property("UserString") + .HasColumnName("User"); + + b.HasKey("ID"); + + b.HasIndex("BeatmapInfoID"); + + b.HasIndex("OnlineScoreID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("ScoreInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("SkinInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("SkinInfoID"); + + b.ToTable("SkinFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Creator"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("Name"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.ToTable("SkinInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") + .WithMany() + .HasForeignKey("BaseDifficultyID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") + .WithMany("Beatmaps") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("Beatmaps") + .HasForeignKey("MetadataID"); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") + .WithMany("Files") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("BeatmapSets") + .HasForeignKey("MetadataID"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Settings") + .HasForeignKey("SkinInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Scoring.ScoreInfo") + .WithMany("Files") + .HasForeignKey("ScoreInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap") + .WithMany("Scores") + .HasForeignKey("BeatmapInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Files") + .HasForeignKey("SkinInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/osu.Game/Migrations/20190913104727_AddBeatmapVideo.cs b/osu.Game/Migrations/20190913104727_AddBeatmapVideo.cs new file mode 100644 index 0000000000..9ed0943acd --- /dev/null +++ b/osu.Game/Migrations/20190913104727_AddBeatmapVideo.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace osu.Game.Migrations +{ + public partial class AddBeatmapVideo : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "VideoFile", + table: "BeatmapMetadata", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "VideoFile", + table: "BeatmapMetadata"); + } + } +} diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 761dca2801..a6d9d1f3cb 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace osu.Game.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.4-servicing-10062"); + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => { @@ -139,6 +139,8 @@ namespace osu.Game.Migrations b.Property("TitleUnicode"); + b.Property("VideoFile"); + b.HasKey("ID"); b.ToTable("BeatmapMetadata"); From 744085fa549766b74d2bcb9f78e8a841225fe936 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 20:25:08 +0900 Subject: [PATCH 2950/5608] Fix exploding fruit not getting correct lifetime --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 330f6e6b24..40d2f64f6a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -74,6 +74,7 @@ namespace osu.Game.Rulesets.Catch.UI caughtFruit.Anchor = Anchor.TopCentre; caughtFruit.Origin = Anchor.Centre; caughtFruit.Scale *= 0.7f; + caughtFruit.LifetimeStart = caughtFruit.HitObject.StartTime; caughtFruit.LifetimeEnd = double.MaxValue; MovableCatcher.Add(caughtFruit); @@ -414,7 +415,10 @@ namespace osu.Game.Rulesets.Catch.UI f.MoveToY(f.Y + 75, 750, Easing.InSine); f.FadeOut(750); - f.Expire(true); + + // todo: this shouldn't exist once DrawableHitObject's ClearTransformsAfter overrides are repaired. + f.LifetimeStart = Time.Current; + f.Expire(); } } @@ -448,7 +452,10 @@ namespace osu.Game.Rulesets.Catch.UI fruit.MoveToY(fruit.Y - 50, 250, Easing.OutSine).Then().MoveToY(fruit.Y + 50, 500, Easing.InSine); fruit.MoveToX(fruit.X + originalX * 6, 1000); fruit.FadeOut(750); - fruit.Expire(true); + + // todo: this shouldn't exist once DrawableHitObject's ClearTransformsAfter overrides are repaired. + fruit.LifetimeStart = Time.Current; + fruit.Expire(); } } } From d385c35955aa89f604c606e8d7051761d5808374 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 21:55:45 +0900 Subject: [PATCH 2951/5608] Apply suggestions from code review Co-Authored-By: Salman Ahmed --- osu.Game/Tests/Visual/OsuTestScene.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 5a7fbd31e2..b382fdb3c0 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual get { if (UseOnlineAPI) - throw new Exception("Using the OsuTestScene dummy API is not supported when UseOnlineAPI is true"); + throw new Exception($"Using the {nameof(OsuTestScene)} dummy API is not supported when {nameof(UseOnlineAPI)} is true"); return dummyAPI; } @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual /// /// Whether this test scene requires real-world API access. - /// If true, this will bypass the local and use the provided one. + /// If true, this will bypass the local and use the provided one. /// protected virtual bool UseOnlineAPI => false; From 2379b665e3e81cee3eb91bef8bcebc1a0a66c61b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 22:15:11 +0900 Subject: [PATCH 2952/5608] Use InvalidOperationException --- osu.Game/Tests/Visual/OsuTestScene.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index b382fdb3c0..2b8baab57c 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual get { if (UseOnlineAPI) - throw new Exception($"Using the {nameof(OsuTestScene)} dummy API is not supported when {nameof(UseOnlineAPI)} is true"); + throw new InvalidOperationException($"Using the {nameof(OsuTestScene)} dummy API is not supported when {nameof(UseOnlineAPI)} is true"); return dummyAPI; } From 82561aa44a30dd0986e79b402168c709218a6527 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 22:44:40 +0900 Subject: [PATCH 2953/5608] Fix catcher additive sprite rewinding and remove unnecessary update code --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 40d2f64f6a..56c8b33e02 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.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; @@ -199,7 +199,6 @@ namespace osu.Game.Rulesets.Catch.UI additive.Anchor = Anchor; additive.OriginPosition = additive.OriginPosition + new Vector2(DrawWidth / 2, 0); // also temporary to align sprite correctly. - additive.LifetimeStart = Clock.CurrentTime; additive.Position = Position; additive.Scale = Scale; additive.Colour = HyperDashing ? Color4.Red : Color4.White; @@ -208,7 +207,8 @@ namespace osu.Game.Rulesets.Catch.UI AdditiveTarget.Add(additive); - additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint).Expire(); + additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint); + additive.Expire(true); Scheduler.AddDelayed(beginTrail, HyperDashing ? 25 : 50); } @@ -303,6 +303,7 @@ namespace osu.Game.Rulesets.Catch.UI { this.FadeColour(Color4.White, hyper_dash_transition_length, Easing.OutQuint); this.FadeTo(1, hyper_dash_transition_length, Easing.OutQuint); + Trail &= Dashing; } } else @@ -386,12 +387,6 @@ namespace osu.Game.Rulesets.Catch.UI X = hyperDashTargetPosition; SetHyperDashState(); } - - if (Clock.ElapsedFrameTime < 0) - { - AdditiveTarget.RemoveAll(d => Clock.CurrentTime < d.LifetimeStart); - caughtFruit.RemoveAll(d => d.HitObject.StartTime > Clock.CurrentTime); - } } /// From 624e5644a4f582d66df2b9ecdc7c2216f5a29394 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 23:05:47 +0900 Subject: [PATCH 2954/5608] Change osu!catch key trigger to occur on frame before positional change --- .../Replays/CatchReplayFrame.cs | 15 ++++++++------- .../Replays/ManiaReplayFrame.cs | 2 +- osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs | 2 +- .../Replays/TaikoReplayFrame.cs | 2 +- .../Replays/Types/IConvertibleReplayFrame.cs | 4 ++-- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 12 +++++------- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs index 19637f321b..b41a5e0612 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs @@ -33,13 +33,13 @@ namespace osu.Game.Rulesets.Catch.Replays if (lastFrame != null) { if (Position > lastFrame.Position) - Actions.Add(CatchAction.MoveRight); + lastFrame.Actions.Add(CatchAction.MoveRight); else if (Position < lastFrame.Position) - Actions.Add(CatchAction.MoveLeft); + lastFrame.Actions.Add(CatchAction.MoveLeft); } } - public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) + public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) { Position = currentFrame.Position.X / CatchPlayfield.BASE_WIDTH; Dashing = currentFrame.ButtonState == ReplayButtonState.Left1; @@ -47,11 +47,12 @@ namespace osu.Game.Rulesets.Catch.Replays if (Dashing) Actions.Add(CatchAction.Dash); - if (lastFrame != null) + // this probably needs some cross-checking with osu-stable to ensure it is actually correct. + if (lastFrame is CatchReplayFrame lastCatchFrame) { - if (currentFrame.Position.X > lastFrame.Position.X) - Actions.Add(CatchAction.MoveRight); - else if (currentFrame.Position.X < lastFrame.Position.X) + if (Position > lastCatchFrame.Position) + lastCatchFrame.Actions.Add(CatchAction.MoveRight); + else if (Position < lastCatchFrame.Position) Actions.Add(CatchAction.MoveLeft); } } diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index b2901f46c0..70ba5cd938 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Mania.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) + public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) { // We don't need to fully convert, just create the converter var converter = new ManiaBeatmapConverter(beatmap); diff --git a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs index 441b69ef2d..e6c6db5e61 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) + public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) { Position = currentFrame.Position; if (currentFrame.MouseLeft) Actions.Add(OsuAction.LeftButton); diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs index 6e43892777..c5ebefc397 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) + public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) { if (currentFrame.MouseRight1) Actions.Add(TaikoAction.LeftRim); if (currentFrame.MouseRight2) Actions.Add(TaikoAction.RightRim); diff --git a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs index 8fcdec6630..c2947c0aca 100644 --- a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Replays.Types /// /// The to extract values from. /// The beatmap. - /// The last , used to fill in missing delta information. May be null. - void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null); + /// The last post-conversion , used to fill in missing delta information. May be null. + void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null); } } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 5a90daa045..2cdd0c4b5e 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -218,7 +218,7 @@ namespace osu.Game.Scoring.Legacy private void readLegacyReplay(Replay replay, StreamReader reader) { float lastTime = 0; - LegacyReplayFrame currentFrame = null; + ReplayFrame currentFrame = null; foreach (var l in reader.ReadToEnd().Split(',')) { @@ -241,18 +241,16 @@ namespace osu.Game.Scoring.Legacy if (diff < 0) continue; - var lastFrame = currentFrame; - - currentFrame = new LegacyReplayFrame(lastTime, + currentFrame = convertFrame(new LegacyReplayFrame(lastTime, Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE), Parsing.ParseFloat(split[2], Parsing.MAX_COORDINATE_VALUE), - (ReplayButtonState)Parsing.ParseInt(split[3])); + (ReplayButtonState)Parsing.ParseInt(split[3])), currentFrame); - replay.Frames.Add(convertFrame(currentFrame, lastFrame)); + replay.Frames.Add(currentFrame); } } - private ReplayFrame convertFrame(LegacyReplayFrame currentFrame, LegacyReplayFrame lastFrame) + private ReplayFrame convertFrame(LegacyReplayFrame currentFrame, ReplayFrame lastFrame) { var convertible = currentRuleset.CreateConvertibleReplayFrame(); if (convertible == null) From 65aa7b20169e6a92444713fa010ce65582a591c1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 14 Sep 2019 00:07:06 +0900 Subject: [PATCH 2955/5608] Recreate beatmap video on each consumption Should not be shared over multiple usages --- osu.Game/Beatmaps/WorkingBeatmap.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index bf3fa90d7b..3fc33e9f52 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -44,7 +44,6 @@ namespace osu.Game.Beatmaps track = new RecyclableLazy(() => GetTrack() ?? GetVirtualTrack()); background = new RecyclableLazy(GetBackground, BackgroundStillValid); - video = new RecyclableLazy(GetVideo); waveform = new RecyclableLazy(GetWaveform); storyboard = new RecyclableLazy(GetStoryboard); skin = new RecyclableLazy(GetSkin); @@ -188,11 +187,9 @@ namespace osu.Game.Beatmaps protected abstract Texture GetBackground(); private readonly RecyclableLazy background; - public bool VideoLoaded => video.IsResultAvailable; - public VideoSprite Video => video.Value; + public VideoSprite Video => GetVideo(); protected abstract VideoSprite GetVideo(); - private readonly RecyclableLazy video; public bool TrackLoaded => track.IsResultAvailable; public Track Track => track.Value; From 9a94405b3a195d18ddcfaf2e1a01a683bff7bd52 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 14 Sep 2019 06:05:09 +0300 Subject: [PATCH 2956/5608] Fix video playback is stretched on client resize --- osu.Game/Screens/Play/DimmableVideo.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index 3e6b95d2cc..4981c3457f 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -59,8 +59,12 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both; Masking = true; - AddInternal(video); video.RelativeSizeAxes = Axes.Both; + video.FillMode = FillMode.Fill; + video.Anchor = Anchor.Centre; + video.Origin = Anchor.Centre; + + AddInternal(video); } [BackgroundDependencyLoader] From 8ad782a82d71b03d6f17bec85b35bbacf6e30102 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 14 Sep 2019 06:16:25 +0300 Subject: [PATCH 2957/5608] Fix RankingsHeader dropdown can be clickable when not visible --- osu.Game/Overlays/Rankings/RankingsHeader.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs index fbf3097f4f..13c1f0fe40 100644 --- a/osu.Game/Overlays/Rankings/RankingsHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -31,7 +31,6 @@ namespace osu.Game.Overlays.Rankings public readonly Bindable Country = new Bindable(); public readonly Bindable Spotlight = new Bindable(); - private readonly Container dropdownPlaceholder; private readonly OsuDropdown dropdown; public RankingsHeader() @@ -86,14 +85,13 @@ namespace osu.Game.Overlays.Rankings Scope = { BindTarget = Scope }, Country = { BindTarget = Country }, }, - dropdownPlaceholder = new Container + new Container { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, Height = dropdown_height, Width = 0.8f, - AlwaysPresent = true, Child = dropdown = new OsuDropdown { RelativeSizeAxes = Axes.X, @@ -115,7 +113,7 @@ namespace osu.Game.Overlays.Rankings } private void onScopeChanged(ValueChangedEvent scope) => - dropdownPlaceholder.FadeTo(scope.NewValue == RankingsScope.Spotlights ? 1 : 0, 200, Easing.OutQuint); + dropdown.FadeTo(scope.NewValue == RankingsScope.Spotlights ? 1 : 0, 200, Easing.OutQuint); private class HeaderBackground : Sprite { From a36c80868247ff5a7fe1c180378e34e95732a905 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 14 Sep 2019 06:28:59 +0300 Subject: [PATCH 2958/5608] Use Fit FillFode --- osu.Game/Screens/Play/DimmableVideo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index 4981c3457f..628871b164 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -60,7 +60,7 @@ namespace osu.Game.Screens.Play Masking = true; video.RelativeSizeAxes = Axes.Both; - video.FillMode = FillMode.Fill; + video.FillMode = FillMode.Fit; video.Anchor = Anchor.Centre; video.Origin = Anchor.Centre; From 9febeb1f3def1c30e07c825785f5c2557bbdcb26 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 14 Sep 2019 06:32:00 +0300 Subject: [PATCH 2959/5608] Add black background --- osu.Game/Screens/Play/DimmableVideo.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index 628871b164..4d6c10d69d 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -4,8 +4,10 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Video; using osu.Game.Graphics.Containers; +using osuTK.Graphics; namespace osu.Game.Screens.Play { @@ -64,7 +66,15 @@ namespace osu.Game.Screens.Play video.Anchor = Anchor.Centre; video.Origin = Anchor.Centre; - AddInternal(video); + AddRangeInternal(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + video, + }); } [BackgroundDependencyLoader] From 2783ae62ef7b409b5b6a5d9f4f3867d1553d2bf6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 14 Sep 2019 06:34:57 +0300 Subject: [PATCH 2960/5608] Remove useless container --- osu.Game/Overlays/Rankings/RankingsHeader.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs index 13c1f0fe40..6aa3e75df9 100644 --- a/osu.Game/Overlays/Rankings/RankingsHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -18,7 +18,6 @@ namespace osu.Game.Overlays.Rankings public class RankingsHeader : CompositeDrawable { private const int content_height = 250; - private const int dropdown_height = 50; public IEnumerable Spotlights { @@ -85,18 +84,13 @@ namespace osu.Game.Overlays.Rankings Scope = { BindTarget = Scope }, Country = { BindTarget = Country }, }, - new Container + dropdown = new OsuDropdown { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, - Height = dropdown_height, Width = 0.8f, - Child = dropdown = new OsuDropdown - { - RelativeSizeAxes = Axes.X, - Current = Spotlight, - } + Current = Spotlight, } } }, From 8456861b8d58f5b4bb7695d81aaee02a952717d8 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 14 Sep 2019 17:08:56 +0300 Subject: [PATCH 2961/5608] Wait for cursor hiding using ManualResetEventSlim --- osu.Game/Graphics/ScreenshotManager.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index f532302de2..02d928ec66 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -83,11 +83,19 @@ namespace osu.Game.Graphics const int frames_to_wait = 3; int framesWaited = 0; - ScheduledDelegate waitDelegate = host.DrawThread.Scheduler.AddDelayed(() => framesWaited++, 0, true); - while (framesWaited < frames_to_wait) - Thread.Sleep(10); - waitDelegate.Cancel(); + using (var framesWaitedEvent = new ManualResetEventSlim(false)) + { + ScheduledDelegate waitDelegate = host.DrawThread.Scheduler.AddDelayed(() => + { + if (framesWaited++ < frames_to_wait) + // ReSharper disable once AccessToDisposedClosure + framesWaitedEvent.Set(); + }, 10, true); + + framesWaitedEvent.Wait(); + waitDelegate.Cancel(); + } } using (var image = await host.TakeScreenshotAsync()) From 7b1ff38df7652b3eee6c159f50125f7809cefb4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 9 Sep 2019 23:41:51 +0200 Subject: [PATCH 2962/5608] Implement line-buffered reader Add a line-buffered reader decorator operating on StreamReader instances. The decorator has two main operations - PeekLine(), which allows to see the next line in the stream without consuming it, ReadLine(), which consumes and returns the next line in the stream, and ReadToEnd() which reads all the remaining text in the stream (including the unconsumed peeked line). Peeking line-per-line uses an internal queue of lines that have been read ahead from the underlying stream. The addition of the line-buffered reader is a workaround solution to a problem with decoding. At current selecting a decoder works by irreversibly reading the first line from the stream and looking for a magic string that indicates the type of decoder to use. It might however be possible for a file to be valid in format, just missing a header. In such a case a lack of a line-buffered reader makes it impossible to reparse the content of that first line. Introducing it will however allow to peek the first line for magic first. - If magic is found in the first line, GetDecoder() will peek it and use it to return the correct Decoder instance. Note that in the case of JsonBeatmapDecoder the magic is the opening JSON object brace, and therefore must not be consumed. - If magic is not found, the fallback decoder will be able to consume it using ReadLine() in Decode(). This commit additionally contains basic unit tests for the reader. Suggested-by: Aergwyn --- .../Beatmaps/IO/LineBufferedReaderTest.cs | 133 ++++++++++++++++++ osu.Game/IO/LineBufferedReader.cs | 70 +++++++++ 2 files changed, 203 insertions(+) create mode 100644 osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs create mode 100644 osu.Game/IO/LineBufferedReader.cs diff --git a/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs new file mode 100644 index 0000000000..b582ca0a6f --- /dev/null +++ b/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs @@ -0,0 +1,133 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.IO; +using System.Text; +using NUnit.Framework; +using osu.Game.IO; + +namespace osu.Game.Tests.Beatmaps.IO +{ + [TestFixture] + public class LineBufferedReaderTest + { + [Test] + public void TestReadLineByLine() + { + const string contents = @"line 1 +line 2 +line 3"; + + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(contents))) + using (var bufferedReader = new LineBufferedReader(stream)) + { + Assert.AreEqual("line 1", bufferedReader.ReadLine()); + Assert.AreEqual("line 2", bufferedReader.ReadLine()); + Assert.AreEqual("line 3", bufferedReader.ReadLine()); + Assert.IsNull(bufferedReader.ReadLine()); + } + } + + [Test] + public void TestPeekLineOnce() + { + const string contents = @"line 1 +peek this +line 3"; + + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(contents))) + using (var bufferedReader = new LineBufferedReader(stream)) + { + Assert.AreEqual("line 1", bufferedReader.ReadLine()); + Assert.AreEqual("peek this", bufferedReader.PeekLine()); + Assert.AreEqual("peek this", bufferedReader.ReadLine()); + Assert.AreEqual("line 3", bufferedReader.ReadLine()); + Assert.IsNull(bufferedReader.ReadLine()); + } + } + + [Test] + public void TestPeekLineMultipleTimes() + { + const string contents = @"peek this once +line 2 +peek this a lot"; + + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(contents))) + using (var bufferedReader = new LineBufferedReader(stream)) + { + Assert.AreEqual("peek this once", bufferedReader.PeekLine()); + Assert.AreEqual("peek this once", bufferedReader.ReadLine()); + Assert.AreEqual("line 2", bufferedReader.ReadLine()); + Assert.AreEqual("peek this a lot", bufferedReader.PeekLine()); + Assert.AreEqual("peek this a lot", bufferedReader.PeekLine()); + Assert.AreEqual("peek this a lot", bufferedReader.PeekLine()); + Assert.AreEqual("peek this a lot", bufferedReader.ReadLine()); + Assert.IsNull(bufferedReader.ReadLine()); + } + } + + [Test] + public void TestPeekLineAtEndOfStream() + { + const string contents = @"first line +second line"; + + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(contents))) + using (var bufferedReader = new LineBufferedReader(stream)) + { + Assert.AreEqual("first line", bufferedReader.ReadLine()); + Assert.AreEqual("second line", bufferedReader.ReadLine()); + Assert.IsNull(bufferedReader.PeekLine()); + Assert.IsNull(bufferedReader.ReadLine()); + Assert.IsNull(bufferedReader.PeekLine()); + } + } + + [Test] + public void TestPeekReadLineOnEmptyStream() + { + using (var stream = new MemoryStream()) + using (var bufferedReader = new LineBufferedReader(stream)) + { + Assert.IsNull(bufferedReader.PeekLine()); + Assert.IsNull(bufferedReader.ReadLine()); + Assert.IsNull(bufferedReader.ReadLine()); + Assert.IsNull(bufferedReader.PeekLine()); + } + } + + [Test] + public void TestReadToEndNoPeeks() + { + const string contents = @"first line +second line"; + + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(contents))) + using (var bufferedReader = new LineBufferedReader(stream)) + { + Assert.AreEqual(contents, bufferedReader.ReadToEnd()); + } + } + + [Test] + public void TestReadToEndAfterReadsAndPeeks() + { + const string contents = @"this line is gone +this one shouldn't be +these ones +definitely not"; + + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(contents))) + using (var bufferedReader = new LineBufferedReader(stream)) + { + Assert.AreEqual("this line is gone", bufferedReader.ReadLine()); + Assert.AreEqual("this one shouldn't be", bufferedReader.PeekLine()); + const string ending = @"this one shouldn't be +these ones +definitely not"; + Assert.AreEqual(ending, bufferedReader.ReadToEnd()); + } + } + } +} diff --git a/osu.Game/IO/LineBufferedReader.cs b/osu.Game/IO/LineBufferedReader.cs new file mode 100644 index 0000000000..66dee1181f --- /dev/null +++ b/osu.Game/IO/LineBufferedReader.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; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace osu.Game.IO +{ + /// + /// A -like decorator (with more limited API) for s + /// that allows lines to be peeked without consuming. + /// + public class LineBufferedReader : IDisposable + { + private readonly StreamReader streamReader; + private readonly Queue lineBuffer; + + public LineBufferedReader(Stream stream) + { + streamReader = new StreamReader(stream); + lineBuffer = new Queue(); + } + + /// + /// Reads the next line from the stream without consuming it. + /// + public string PeekLine() + { + if (lineBuffer.Count > 0) + return lineBuffer.Peek(); + + var line = streamReader.ReadLine(); + if (line != null) + lineBuffer.Enqueue(line); + return line; + } + + /// + /// Reads the next line from the stream and consumes it. + /// + public string ReadLine() => lineBuffer.Count > 0 ? lineBuffer.Dequeue() : streamReader.ReadLine(); + + /// + /// Reads the stream to its end and returns the text read. + /// This includes any peeked but unconsumed lines. + /// + public string ReadToEnd() + { + var remainingText = streamReader.ReadToEnd(); + if (lineBuffer.Count == 0) + return remainingText; + + var builder = new StringBuilder(); + + // this might not be completely correct due to varying platform line endings + while (lineBuffer.Count > 0) + builder.AppendLine(lineBuffer.Dequeue()); + builder.Append(remainingText); + + return builder.ToString(); + } + + public void Dispose() + { + streamReader?.Dispose(); + } + } +} From 11eda44d3451c889469af4e8e30d522b04d2dd15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 10 Sep 2019 00:43:30 +0200 Subject: [PATCH 2963/5608] Migrate decoding to line-buffered reader Migrate all usages of StreamReader in the context of decoding beatmaps, storyboards or skins to the new LineBufferedReader. --- osu.Game.Rulesets.Osu.Tests/StackingTest.cs | 3 +- .../Formats/LegacyBeatmapDecoderTest.cs | 42 +++++++++---------- .../Beatmaps/Formats/LegacyDecoderTest.cs | 4 +- .../Formats/LegacyStoryboardDecoderTest.cs | 6 +-- .../Beatmaps/Formats/OsuJsonDecoderTest.cs | 5 ++- .../Beatmaps/IO/OszArchiveReaderTest.cs | 3 +- osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 6 +-- osu.Game.Tests/WaveformTestBeatmap.cs | 3 +- osu.Game/Beatmaps/BeatmapManager.cs | 5 ++- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 8 ++-- osu.Game/Beatmaps/Formats/Decoder.cs | 9 ++-- .../Beatmaps/Formats/JsonBeatmapDecoder.cs | 7 +--- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 3 +- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 4 +- .../Formats/LegacyStoryboardDecoder.cs | 3 +- osu.Game/Skinning/LegacySkin.cs | 3 +- .../Tests/Beatmaps/BeatmapConversionTest.cs | 3 +- .../Beatmaps/DifficultyCalculatorTest.cs | 3 +- osu.Game/Tests/Beatmaps/TestBeatmap.cs | 3 +- 19 files changed, 64 insertions(+), 59 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/StackingTest.cs b/osu.Game.Rulesets.Osu.Tests/StackingTest.cs index e8b99e86f9..871afdb09d 100644 --- a/osu.Game.Rulesets.Osu.Tests/StackingTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/StackingTest.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Text; using NUnit.Framework; using osu.Game.Beatmaps; +using osu.Game.IO; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Tests.Beatmaps; @@ -21,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Tests public void TestStacking() { using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(beatmap_data))) - using (var reader = new StreamReader(stream)) + using (var reader = new LineBufferedReader(stream)) { var beatmap = Decoder.GetDecoder(reader).Decode(reader); var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Array.Empty()); diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 535320530d..6a77c6ca96 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.IO; using NUnit.Framework; using osuTK; using osuTK.Graphics; @@ -13,6 +12,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Timing; +using osu.Game.IO; using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; @@ -30,13 +30,9 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapVersion() { using (var resStream = TestResources.OpenResource("beatmap-version.osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var decoder = Decoder.GetDecoder(stream); - - stream.BaseStream.Position = 0; - stream.DiscardBufferedData(); - var working = new TestWorkingBeatmap(decoder.Decode(stream)); Assert.AreEqual(6, working.BeatmapInfo.BeatmapVersion); @@ -51,7 +47,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var beatmap = decoder.Decode(stream); var beatmapInfo = beatmap.BeatmapInfo; @@ -75,7 +71,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder(); using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var beatmapInfo = decoder.Decode(stream).BeatmapInfo; @@ -101,7 +97,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder(); using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var beatmap = decoder.Decode(stream); var beatmapInfo = beatmap.BeatmapInfo; @@ -126,7 +122,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder(); using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var difficulty = decoder.Decode(stream).BeatmapInfo.BaseDifficulty; @@ -145,7 +141,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var beatmap = decoder.Decode(stream); var metadata = beatmap.Metadata; @@ -164,7 +160,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var beatmap = decoder.Decode(stream); var controlPoints = beatmap.ControlPointInfo; @@ -239,7 +235,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; using (var resStream = TestResources.OpenResource("overlapping-control-points.osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var controlPoints = decoder.Decode(stream).ControlPointInfo; @@ -271,7 +267,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacySkinDecoder(); using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var comboColors = decoder.Decode(stream).ComboColours; @@ -297,7 +293,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder(); using (var resStream = TestResources.OpenResource("hitobject-combo-offset.osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var beatmap = decoder.Decode(stream); @@ -320,7 +316,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder(); using (var resStream = TestResources.OpenResource("hitobject-combo-offset.osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var beatmap = decoder.Decode(stream); @@ -343,7 +339,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var hitObjects = decoder.Decode(stream).HitObjects; @@ -371,7 +367,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; using (var resStream = TestResources.OpenResource("controlpoint-custom-samplebank.osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var hitObjects = decoder.Decode(stream).HitObjects; @@ -393,7 +389,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; using (var resStream = TestResources.OpenResource("hitobject-custom-samplebank.osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var hitObjects = decoder.Decode(stream).HitObjects; @@ -411,7 +407,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; using (var resStream = TestResources.OpenResource("hitobject-file-samples.osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var hitObjects = decoder.Decode(stream).HitObjects; @@ -431,7 +427,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; using (var resStream = TestResources.OpenResource("slider-samples.osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var hitObjects = decoder.Decode(stream).HitObjects; @@ -475,7 +471,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; using (var resStream = TestResources.OpenResource("hitobject-no-addition-bank.osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var hitObjects = decoder.Decode(stream).HitObjects; @@ -489,7 +485,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; using (var badResStream = TestResources.OpenResource("invalid-events.osu")) - using (var badStream = new StreamReader(badResStream)) + using (var badStream = new LineBufferedReader(badResStream)) { Assert.DoesNotThrow(() => decoder.Decode(badStream)); } diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs index b4d219456c..335a6aeeb0 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs @@ -2,9 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.IO; using NUnit.Framework; using osu.Game.Beatmaps.Formats; +using osu.Game.IO; using osu.Game.Tests.Resources; namespace osu.Game.Tests.Beatmaps.Formats @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LineLoggingDecoder(14); using (var resStream = TestResources.OpenResource("comments.osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { decoder.Decode(stream); diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index 953763c95d..66d53d7e7b 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.IO; using System.Linq; using NUnit.Framework; using osuTK; using osu.Framework.Graphics; using osu.Game.Beatmaps.Formats; +using osu.Game.IO; using osu.Game.Storyboards; using osu.Game.Tests.Resources; @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyStoryboardDecoder(); using (var resStream = TestResources.OpenResource("Himeringo - Yotsuya-san ni Yoroshiku (RLC) [Winber1's Extreme].osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var storyboard = decoder.Decode(stream); @@ -94,7 +94,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decoder = new LegacyStoryboardDecoder(); using (var resStream = TestResources.OpenResource("variable-with-suffix.osb")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var storyboard = decoder.Decode(stream); diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs index 4859abbb8e..63346b8c9d 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; +using osu.Game.IO; using osu.Game.IO.Serialization; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; @@ -148,13 +149,13 @@ namespace osu.Game.Tests.Beatmaps.Formats private Beatmap decode(string filename, out Beatmap jsonDecoded) { using (var stream = TestResources.OpenResource(filename)) - using (var sr = new StreamReader(stream)) + using (var sr = new LineBufferedReader(stream)) { var legacyDecoded = new LegacyBeatmapDecoder { ApplyOffsets = false }.Decode(sr); using (var ms = new MemoryStream()) using (var sw = new StreamWriter(ms)) - using (var sr2 = new StreamReader(ms)) + using (var sr2 = new LineBufferedReader(ms)) { sw.Write(legacyDecoded.Serialize()); sw.Flush(); diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs index 37e0565df0..022b2c1a59 100644 --- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Tests.Resources; using osu.Game.Beatmaps.Formats; +using osu.Game.IO; using osu.Game.IO.Archives; namespace osu.Game.Tests.Beatmaps.IO @@ -50,7 +51,7 @@ namespace osu.Game.Tests.Beatmaps.IO Beatmap beatmap; - using (var stream = new StreamReader(reader.GetStream("Soleily - Renatus (Deif) [Platter].osu"))) + using (var stream = new LineBufferedReader(reader.GetStream("Soleily - Renatus (Deif) [Platter].osu"))) beatmap = Decoder.GetDecoder(stream).Decode(stream); var meta = beatmap.Metadata; diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 8bd846518b..0d96dd08da 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -2,8 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.IO; using NUnit.Framework; +using osu.Game.IO; using osu.Game.Skinning; using osu.Game.Tests.Resources; using osuTK.Graphics; @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Skins var decoder = new LegacySkinDecoder(); using (var resStream = TestResources.OpenResource(hasColours ? "skin.ini" : "skin-empty.ini")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var comboColors = decoder.Decode(stream).ComboColours; @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Skins var decoder = new LegacySkinDecoder(); using (var resStream = TestResources.OpenResource("skin.ini")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var config = decoder.Decode(stream); diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index db9576b5fa..0d16a78f75 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Video; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; +using osu.Game.IO; using osu.Game.IO.Archives; using osu.Game.Tests.Resources; @@ -56,7 +57,7 @@ namespace osu.Game.Tests private Beatmap createTestBeatmap() { using (var beatmapStream = getBeatmapStream()) - using (var beatmapReader = new StreamReader(beatmapStream)) + using (var beatmapReader = new LineBufferedReader(beatmapStream)) return Decoder.GetDecoder(beatmapReader).Decode(beatmapReader); } } diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b9ed3664ef..372eec50fd 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -20,6 +20,7 @@ using osu.Framework.Platform; using osu.Framework.Threading; using osu.Game.Beatmaps.Formats; using osu.Game.Database; +using osu.Game.IO; using osu.Game.IO.Archives; using osu.Game.Online.API; using osu.Game.Online.API.Requests; @@ -264,7 +265,7 @@ namespace osu.Game.Beatmaps } Beatmap beatmap; - using (var stream = new StreamReader(reader.GetStream(mapName))) + using (var stream = new LineBufferedReader(reader.GetStream(mapName))) beatmap = Decoder.GetDecoder(stream).Decode(stream); return new BeatmapSetInfo @@ -287,7 +288,7 @@ namespace osu.Game.Beatmaps { using (var raw = reader.GetStream(name)) using (var ms = new MemoryStream()) //we need a memory stream so we can seek - using (var sr = new StreamReader(ms)) + using (var sr = new LineBufferedReader(ms)) { raw.CopyTo(ms); ms.Position = 0; diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 1d00c94ef2..b879b92f01 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.IO; using System.Linq; using osu.Framework.Audio; using osu.Framework.Audio.Track; @@ -11,6 +10,7 @@ using osu.Framework.Graphics.Video; using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Game.Beatmaps.Formats; +using osu.Game.IO; using osu.Game.Skinning; using osu.Game.Storyboards; @@ -33,7 +33,7 @@ namespace osu.Game.Beatmaps { try { - using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path)))) + using (var stream = new LineBufferedReader(store.GetStream(getPathForFile(BeatmapInfo.Path)))) return Decoder.GetDecoder(stream).Decode(stream); } catch @@ -127,7 +127,7 @@ namespace osu.Game.Beatmaps try { - using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path)))) + using (var stream = new LineBufferedReader(store.GetStream(getPathForFile(BeatmapInfo.Path)))) { var decoder = Decoder.GetDecoder(stream); @@ -136,7 +136,7 @@ namespace osu.Game.Beatmaps storyboard = decoder.Decode(stream); else { - using (var secondaryStream = new StreamReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile)))) + using (var secondaryStream = new LineBufferedReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile)))) storyboard = decoder.Decode(stream, secondaryStream); } } diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs index 953e50eadc..0f1b617809 100644 --- a/osu.Game/Beatmaps/Formats/Decoder.cs +++ b/osu.Game/Beatmaps/Formats/Decoder.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using osu.Game.IO; namespace osu.Game.Beatmaps.Formats { @@ -13,15 +14,15 @@ namespace osu.Game.Beatmaps.Formats { protected virtual TOutput CreateTemplateObject() => new TOutput(); - public TOutput Decode(StreamReader primaryStream, params StreamReader[] otherStreams) + public TOutput Decode(LineBufferedReader primaryStream, params LineBufferedReader[] otherStreams) { var output = CreateTemplateObject(); - foreach (StreamReader stream in otherStreams.Prepend(primaryStream)) + foreach (LineBufferedReader stream in otherStreams.Prepend(primaryStream)) ParseStreamInto(stream, output); return output; } - protected abstract void ParseStreamInto(StreamReader stream, TOutput output); + protected abstract void ParseStreamInto(LineBufferedReader stream, TOutput output); } public abstract class Decoder @@ -39,7 +40,7 @@ namespace osu.Game.Beatmaps.Formats /// Retrieves a to parse a . /// /// A stream pointing to the . - public static Decoder GetDecoder(StreamReader stream) + public static Decoder GetDecoder(LineBufferedReader stream) where T : new() { if (stream == null) diff --git a/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs index d8482b200f..988968fa42 100644 --- a/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs @@ -1,7 +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.IO; +using osu.Game.IO; using osu.Game.IO.Serialization; namespace osu.Game.Beatmaps.Formats @@ -13,11 +13,8 @@ namespace osu.Game.Beatmaps.Formats AddDecoder("{", m => new JsonBeatmapDecoder()); } - protected override void ParseStreamInto(StreamReader stream, Beatmap output) + protected override void ParseStreamInto(LineBufferedReader stream, Beatmap output) { - stream.BaseStream.Position = 0; - stream.DiscardBufferedData(); - stream.ReadToEnd().DeserializeInto(output); foreach (var hitObject in output.HitObjects) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 0532790f0a..6e34fd8e90 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -8,6 +8,7 @@ using osu.Framework.IO.File; using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.IO; namespace osu.Game.Beatmaps.Formats { @@ -41,7 +42,7 @@ namespace osu.Game.Beatmaps.Formats offset = FormatVersion < 5 ? 24 : 0; } - protected override void ParseStreamInto(StreamReader stream, Beatmap beatmap) + protected override void ParseStreamInto(LineBufferedReader stream, Beatmap beatmap) { this.beatmap = beatmap; this.beatmap.BeatmapInfo.BeatmapVersion = FormatVersion; diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 9a8197ad82..83d20da458 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; -using System.IO; using osu.Framework.Logging; using osu.Game.Audio; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.IO; using osuTK.Graphics; namespace osu.Game.Beatmaps.Formats @@ -21,7 +21,7 @@ namespace osu.Game.Beatmaps.Formats FormatVersion = version; } - protected override void ParseStreamInto(StreamReader stream, T output) + protected override void ParseStreamInto(LineBufferedReader stream, T output) { Section section = Section.None; diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 14c6ea5c8e..a8f8dbf69d 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -10,6 +10,7 @@ using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.IO.File; +using osu.Game.IO; using osu.Game.Storyboards; namespace osu.Game.Beatmaps.Formats @@ -35,7 +36,7 @@ namespace osu.Game.Beatmaps.Formats AddDecoder(@"[Events]", m => new LegacyStoryboardDecoder()); } - protected override void ParseStreamInto(StreamReader stream, Storyboard storyboard) + protected override void ParseStreamInto(LineBufferedReader stream, Storyboard storyboard) { this.storyboard = storyboard; base.ParseStreamInto(stream, storyboard); diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 0b1076be01..fea15458e4 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Game.Audio; +using osu.Game.IO; using osu.Game.Rulesets.Scoring; using osuTK.Graphics; @@ -35,7 +36,7 @@ namespace osu.Game.Skinning { Stream stream = storage?.GetStream(filename); if (stream != null) - using (StreamReader reader = new StreamReader(stream)) + using (LineBufferedReader reader = new LineBufferedReader(stream)) Configuration = new LegacySkinDecoder().Decode(reader); else Configuration = new DefaultSkinConfiguration(); diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 3fc9662b17..e99b5fc5fb 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Video; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; +using osu.Game.IO; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; @@ -142,7 +143,7 @@ namespace osu.Game.Tests.Beatmaps private IBeatmap getBeatmap(string name) { using (var resStream = openResource($"{resource_namespace}.{name}.osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var decoder = Decoder.GetDecoder(stream); ((LegacyBeatmapDecoder)decoder).ApplyOffsets = false; diff --git a/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs index 108fa8ff71..748a52d1c5 100644 --- a/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs +++ b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs @@ -7,6 +7,7 @@ using System.Reflection; using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; +using osu.Game.IO; using osu.Game.Rulesets; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; @@ -26,7 +27,7 @@ namespace osu.Game.Tests.Beatmaps private WorkingBeatmap getBeatmap(string name) { using (var resStream = openResource($"{resource_namespace}.{name}.osu")) - using (var stream = new StreamReader(resStream)) + using (var stream = new LineBufferedReader(resStream)) { var decoder = Decoder.GetDecoder(stream); ((LegacyBeatmapDecoder)decoder).ApplyOffsets = false; diff --git a/osu.Game/Tests/Beatmaps/TestBeatmap.cs b/osu.Game/Tests/Beatmaps/TestBeatmap.cs index b77a8508ad..d6f92ba086 100644 --- a/osu.Game/Tests/Beatmaps/TestBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestBeatmap.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Text; using osu.Game.Beatmaps; +using osu.Game.IO; using osu.Game.Rulesets; using Decoder = osu.Game.Beatmaps.Formats.Decoder; @@ -39,7 +40,7 @@ namespace osu.Game.Tests.Beatmaps private static Beatmap createTestBeatmap() { using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(test_beatmap_data))) - using (var reader = new StreamReader(stream)) + using (var reader = new LineBufferedReader(stream)) return Decoder.GetDecoder(reader).Decode(reader); } From 86588778b170b363b2e7156a9ffa08ba32e15f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 10 Sep 2019 22:06:10 +0200 Subject: [PATCH 2964/5608] Implement fallback decoder registration After the preparatory introduction of LineBufferedReader, it is now possible to introduce registration of fallback decoders that won't drop input supplied in the first line of the file. A fallback decoder is used when the magic in the first line of the file does not match any of the other known decoders. In such a case, the fallback decoder is constructed and provided a LineBufferedReader instance. The process of matching magic only peeks the first non-empty line, so it is available for re-reading in Decode() using ReadLine(). There can be only one fallback decoder per type; a second attempt of registering a fallback will result in an exception to avoid bugs. To address the issue of parsing failing on badly or non-headered files, set the legacy decoders for Beatmaps and Storyboards as the fallbacks. Due to non-trivial logic, several new, passing unit tests with possible edge cases also included. --- .../Formats/LegacyBeatmapDecoderTest.cs | 101 ++++++++++++++++++ .../Beatmaps/IO/ImportBeatmapTest.cs | 2 +- osu.Game.Tests/Resources/corrupted-header.osu | 5 + .../empty-line-instead-of-header.osu | 5 + .../Resources/empty-lines-at-start.osu | 8 ++ osu.Game.Tests/Resources/missing-header.osu | 4 + .../Resources/no-empty-line-after-header.osu | 4 + osu.Game.Tests/osu.Game.Tests.csproj | 7 ++ osu.Game/Beatmaps/Formats/Decoder.cs | 41 +++++-- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 1 + .../Formats/LegacyStoryboardDecoder.cs | 1 + osu.Game/IO/LineBufferedReader.cs | 2 + 12 files changed, 172 insertions(+), 9 deletions(-) create mode 100644 osu.Game.Tests/Resources/corrupted-header.osu create mode 100644 osu.Game.Tests/Resources/empty-line-instead-of-header.osu create mode 100644 osu.Game.Tests/Resources/empty-lines-at-start.osu create mode 100644 osu.Game.Tests/Resources/missing-header.osu create mode 100644 osu.Game.Tests/Resources/no-empty-line-after-header.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 6a77c6ca96..f6c0dbbecf 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.IO; using NUnit.Framework; using osuTK; using osuTK.Graphics; @@ -490,5 +491,105 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.DoesNotThrow(() => decoder.Decode(badStream)); } } + + [Test] + public void TestFallbackDecoderForCorruptedHeader() + { + Decoder decoder = null; + Beatmap beatmap = null; + + using (var resStream = TestResources.OpenResource("corrupted-header.osu")) + using (var stream = new LineBufferedReader(resStream)) + { + Assert.DoesNotThrow(() => decoder = Decoder.GetDecoder(stream)); + Assert.IsInstanceOf(decoder); + Assert.DoesNotThrow(() => beatmap = decoder.Decode(stream)); + Assert.IsNotNull(beatmap); + Assert.AreEqual("Beatmap with corrupted header", beatmap.Metadata.Title); + Assert.AreEqual("Evil Hacker", beatmap.Metadata.AuthorString); + } + } + + [Test] + public void TestFallbackDecoderForMissingHeader() + { + Decoder decoder = null; + Beatmap beatmap = null; + + using (var resStream = TestResources.OpenResource("missing-header.osu")) + using (var stream = new LineBufferedReader(resStream)) + { + Assert.DoesNotThrow(() => decoder = Decoder.GetDecoder(stream)); + Assert.IsInstanceOf(decoder); + Assert.DoesNotThrow(() => beatmap = decoder.Decode(stream)); + Assert.IsNotNull(beatmap); + Assert.AreEqual("Beatmap with no header", beatmap.Metadata.Title); + Assert.AreEqual("Incredibly Evil Hacker", beatmap.Metadata.AuthorString); + } + } + + [Test] + public void TestDecodeFileWithEmptyLinesAtStart() + { + Decoder decoder = null; + Beatmap beatmap = null; + + using (var resStream = TestResources.OpenResource("empty-lines-at-start.osu")) + using (var stream = new LineBufferedReader(resStream)) + { + Assert.DoesNotThrow(() => decoder = Decoder.GetDecoder(stream)); + Assert.IsInstanceOf(decoder); + Assert.DoesNotThrow(() => beatmap = decoder.Decode(stream)); + Assert.IsNotNull(beatmap); + Assert.AreEqual("Empty lines at start", beatmap.Metadata.Title); + Assert.AreEqual("Edge Case Hunter", beatmap.Metadata.AuthorString); + } + } + + [Test] + public void TestDecodeFileWithEmptyLinesAndNoHeader() + { + Decoder decoder = null; + Beatmap beatmap = null; + + using (var resStream = TestResources.OpenResource("empty-line-instead-of-header.osu")) + using (var stream = new LineBufferedReader(resStream)) + { + Assert.DoesNotThrow(() => decoder = Decoder.GetDecoder(stream)); + Assert.IsInstanceOf(decoder); + Assert.DoesNotThrow(() => beatmap = decoder.Decode(stream)); + Assert.IsNotNull(beatmap); + Assert.AreEqual("The dog ate the file header", beatmap.Metadata.Title); + Assert.AreEqual("Why does this keep happening", beatmap.Metadata.AuthorString); + } + } + + [Test] + public void TestDecodeFileWithContentImmediatelyAfterHeader() + { + Decoder decoder = null; + Beatmap beatmap = null; + + using (var resStream = TestResources.OpenResource("no-empty-line-after-header.osu")) + using (var stream = new LineBufferedReader(resStream)) + { + Assert.DoesNotThrow(() => decoder = Decoder.GetDecoder(stream)); + Assert.IsInstanceOf(decoder); + Assert.DoesNotThrow(() => beatmap = decoder.Decode(stream)); + Assert.IsNotNull(beatmap); + Assert.AreEqual("No empty line delimiting header from contents", beatmap.Metadata.Title); + Assert.AreEqual("Edge Case Hunter", beatmap.Metadata.AuthorString); + } + } + + [Test] + public void TestDecodeEmptyFile() + { + using (var resStream = new MemoryStream()) + using (var stream = new LineBufferedReader(resStream)) + { + Assert.Throws(() => Decoder.GetDecoder(stream)); + } + } } } diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index ad0ed00989..0686073292 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -126,7 +126,7 @@ namespace osu.Game.Tests.Beatmaps.IO var breakTemp = TestResources.GetTestBeatmapForImport(); - MemoryStream brokenOsu = new MemoryStream(new byte[] { 1, 3, 3, 7 }); + MemoryStream brokenOsu = new MemoryStream(); MemoryStream brokenOsz = new MemoryStream(File.ReadAllBytes(breakTemp)); File.Delete(breakTemp); diff --git a/osu.Game.Tests/Resources/corrupted-header.osu b/osu.Game.Tests/Resources/corrupted-header.osu new file mode 100644 index 0000000000..92701a4a7d --- /dev/null +++ b/osu.Game.Tests/Resources/corrupted-header.osu @@ -0,0 +1,5 @@ +ow computerosu file format v14 + +[Metadata] +Title: Beatmap with corrupted header +Creator: Evil Hacker diff --git a/osu.Game.Tests/Resources/empty-line-instead-of-header.osu b/osu.Game.Tests/Resources/empty-line-instead-of-header.osu new file mode 100644 index 0000000000..91ecf8d84a --- /dev/null +++ b/osu.Game.Tests/Resources/empty-line-instead-of-header.osu @@ -0,0 +1,5 @@ + + +[Metadata] +Title: The dog ate the file header +Creator: Why does this keep happening \ No newline at end of file diff --git a/osu.Game.Tests/Resources/empty-lines-at-start.osu b/osu.Game.Tests/Resources/empty-lines-at-start.osu new file mode 100644 index 0000000000..cb3b1761a2 --- /dev/null +++ b/osu.Game.Tests/Resources/empty-lines-at-start.osu @@ -0,0 +1,8 @@ + + + +osu file format v14 + +[Metadata] +Title: Empty lines at start +Creator: Edge Case Hunter \ No newline at end of file diff --git a/osu.Game.Tests/Resources/missing-header.osu b/osu.Game.Tests/Resources/missing-header.osu new file mode 100644 index 0000000000..95fac0d79b --- /dev/null +++ b/osu.Game.Tests/Resources/missing-header.osu @@ -0,0 +1,4 @@ +[Metadata] + +Title: Beatmap with no header +Creator: Incredibly Evil Hacker diff --git a/osu.Game.Tests/Resources/no-empty-line-after-header.osu b/osu.Game.Tests/Resources/no-empty-line-after-header.osu new file mode 100644 index 0000000000..9db2b7c01c --- /dev/null +++ b/osu.Game.Tests/Resources/no-empty-line-after-header.osu @@ -0,0 +1,4 @@ +osu file format v14 +[Metadata] +Title: No empty line delimiting header from contents +Creator: Edge Case Hunter \ No newline at end of file diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 84f67c9319..9dc3e85e1b 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -1,5 +1,12 @@  + + + + + + + diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs index 0f1b617809..4a539cc33f 100644 --- a/osu.Game/Beatmaps/Formats/Decoder.cs +++ b/osu.Game/Beatmaps/Formats/Decoder.cs @@ -28,6 +28,7 @@ namespace osu.Game.Beatmaps.Formats public abstract class Decoder { private static readonly Dictionary>> decoders = new Dictionary>>(); + private static readonly Dictionary> fallback_decoders = new Dictionary>(); static Decoder() { @@ -49,21 +50,31 @@ namespace osu.Game.Beatmaps.Formats if (!decoders.TryGetValue(typeof(T), out var typedDecoders)) throw new IOException(@"Unknown decoder type"); - string line; + // start off with the first line of the file + string line = stream.PeekLine()?.Trim(); - do + while (line != null && line.Length == 0) { - line = stream.ReadLine()?.Trim(); - } while (line != null && line.Length == 0); + // consume the previously peeked empty line and advance to the next one + stream.ReadLine(); + line = stream.PeekLine()?.Trim(); + } if (line == null) - throw new IOException(@"Unknown file format (null)"); + throw new IOException("Unknown file format (null)"); var decoder = typedDecoders.Select(d => line.StartsWith(d.Key, StringComparison.InvariantCulture) ? d.Value : null).FirstOrDefault(); - if (decoder == null) - throw new IOException($@"Unknown file format ({line})"); - return (Decoder)decoder.Invoke(line); + // it's important the magic does NOT get consumed here, since sometimes it's part of the structure + // (see JsonBeatmapDecoder - the magic string is the opening brace) + // decoder implementations should therefore not die on receiving their own magic + if (decoder != null) + return (Decoder)decoder.Invoke(line); + + if (!fallback_decoders.TryGetValue(typeof(T), out var fallbackDecoder)) + throw new IOException($"Unknown file format ({line})"); + + return (Decoder)fallbackDecoder.Invoke(); } /// @@ -78,5 +89,19 @@ namespace osu.Game.Beatmaps.Formats typedDecoders[magic] = constructor; } + + /// + /// Registers a fallback decoder instantiation function. + /// The fallback will be returned if the first line of the decoded stream does not match any known magic. + /// + /// Type of object being decoded. + /// A function that constructs the fallback. + protected static void SetFallbackDecoder(Func constructor) + { + if (fallback_decoders.ContainsKey(typeof(T))) + throw new InvalidOperationException($"A fallback decoder was already added for type {typeof(T)}."); + + fallback_decoders[typeof(T)] = constructor; + } } } diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 6e34fd8e90..786b7611b5 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -26,6 +26,7 @@ namespace osu.Game.Beatmaps.Formats public static void Register() { AddDecoder(@"osu file format v", m => new LegacyBeatmapDecoder(Parsing.ParseInt(m.Split('v').Last()))); + SetFallbackDecoder(() => new LegacyBeatmapDecoder()); } /// diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index a8f8dbf69d..5dbd67d304 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -34,6 +34,7 @@ namespace osu.Game.Beatmaps.Formats // note that this isn't completely correct AddDecoder(@"osu file format v", m => new LegacyStoryboardDecoder()); AddDecoder(@"[Events]", m => new LegacyStoryboardDecoder()); + SetFallbackDecoder(() => new LegacyStoryboardDecoder()); } protected override void ParseStreamInto(LineBufferedReader stream, Storyboard storyboard) diff --git a/osu.Game/IO/LineBufferedReader.cs b/osu.Game/IO/LineBufferedReader.cs index 66dee1181f..aab761afd8 100644 --- a/osu.Game/IO/LineBufferedReader.cs +++ b/osu.Game/IO/LineBufferedReader.cs @@ -25,6 +25,7 @@ namespace osu.Game.IO /// /// Reads the next line from the stream without consuming it. + /// Subsequent calls to without a will return the same string. /// public string PeekLine() { @@ -39,6 +40,7 @@ namespace osu.Game.IO /// /// Reads the next line from the stream and consumes it. + /// If a line was peeked, that same line will then be consumed and returned. /// public string ReadLine() => lineBuffer.Count > 0 ? lineBuffer.Dequeue() : streamReader.ReadLine(); From 29fcab65f9a2e553dd9c9cd550173612f1b74303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 10 Sep 2019 22:40:52 +0200 Subject: [PATCH 2965/5608] Remove superfluous csproj entries --- osu.Game.Tests/osu.Game.Tests.csproj | 7 ------- 1 file changed, 7 deletions(-) diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 9dc3e85e1b..84f67c9319 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -1,12 +1,5 @@  - - - - - - - From dd9f620c2364e35c1f1185f2f4b5a43893b5874f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 10 Sep 2019 22:45:34 +0200 Subject: [PATCH 2966/5608] Fix misleading xmldoc --- osu.Game/Beatmaps/Formats/Decoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs index 4a539cc33f..045eb2d14d 100644 --- a/osu.Game/Beatmaps/Formats/Decoder.cs +++ b/osu.Game/Beatmaps/Formats/Decoder.cs @@ -92,7 +92,7 @@ namespace osu.Game.Beatmaps.Formats /// /// Registers a fallback decoder instantiation function. - /// The fallback will be returned if the first line of the decoded stream does not match any known magic. + /// The fallback will be returned if the first non-empty line of the decoded stream does not match any known magic. /// /// Type of object being decoded. /// A function that constructs the fallback. From babd34470ea38ca7b38cc80fbbb6a00f8ed7bfaf Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 15 Sep 2019 02:33:21 +0300 Subject: [PATCH 2967/5608] Fix DrawableFlag returns empty texture if there's no flag avaliable for needed country --- osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs | 7 +++++++ osu.Game/Users/Drawables/DrawableFlag.cs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs index 0ceb5f21d3..c0da605cdb 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs @@ -61,10 +61,17 @@ namespace osu.Game.Tests.Visual.Online FullName = "Belarus" }; + var unknownCountry = new Country + { + FlagName = "CK", + FullName = "Cook Islands" + }; + AddStep("Set country", () => countryBindable.Value = country); AddAssert("Check scope is Performance", () => scope.Value == RankingsScope.Performance); AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); AddAssert("Check country is Null", () => countryBindable.Value == null); + AddStep("Set country with no flag", () => countryBindable.Value = unknownCountry); } } } diff --git a/osu.Game/Users/Drawables/DrawableFlag.cs b/osu.Game/Users/Drawables/DrawableFlag.cs index 368354e48e..fab561c1af 100644 --- a/osu.Game/Users/Drawables/DrawableFlag.cs +++ b/osu.Game/Users/Drawables/DrawableFlag.cs @@ -26,7 +26,7 @@ namespace osu.Game.Users.Drawables if (ts == null) throw new ArgumentNullException(nameof(ts)); - Texture = ts.Get($@"Flags/{country?.FlagName ?? @"__"}"); + Texture = ts.Get($@"Flags/{country?.FlagName ?? @"__"}") ?? ts.Get($@"Flags/__"); } } } From 96453d8197be660721540348198819d551bf04ef Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 15 Sep 2019 02:46:28 +0300 Subject: [PATCH 2968/5608] Remove redundant string interpolation --- osu.Game/Users/Drawables/DrawableFlag.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Users/Drawables/DrawableFlag.cs b/osu.Game/Users/Drawables/DrawableFlag.cs index fab561c1af..1d648e46b6 100644 --- a/osu.Game/Users/Drawables/DrawableFlag.cs +++ b/osu.Game/Users/Drawables/DrawableFlag.cs @@ -26,7 +26,7 @@ namespace osu.Game.Users.Drawables if (ts == null) throw new ArgumentNullException(nameof(ts)); - Texture = ts.Get($@"Flags/{country?.FlagName ?? @"__"}") ?? ts.Get($@"Flags/__"); + Texture = ts.Get($@"Flags/{country?.FlagName ?? @"__"}") ?? ts.Get(@"Flags/__"); } } } From 78931c8e23f304e0b39387b6d8d355ff64c01555 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sun, 15 Sep 2019 15:59:46 +0200 Subject: [PATCH 2969/5608] Implement notification when user has track or master volume muted This took around under a hour to implement, it has the same behavior and content from osu!stable. A notification will show up when the user has either its master or track volume set to the minimum, clicking it will set it to the default values. --- osu.Game/Screens/Play/PlayerLoader.cs | 46 ++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 5396321160..b8d5fc7bda 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -19,6 +20,8 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Input; +using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Menu; using osu.Game.Screens.Play.HUD; @@ -54,6 +57,8 @@ namespace osu.Game.Screens.Play private InputManager inputManager; + private NotificationOverlay notificationOverlay; + private IdleTracker idleTracker; public PlayerLoader(Func createPlayer) @@ -68,7 +73,7 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load() + private void load(AudioManager audioManager, NotificationOverlay notificationOverlay) { InternalChild = (content = new LogoTrackingContainer { @@ -101,6 +106,10 @@ namespace osu.Game.Screens.Play }); loadNewPlayer(); + + this.notificationOverlay = notificationOverlay; + + checkVolume(audioManager); } private void playerLoaded(Player player) => info.Loading = false; @@ -145,6 +154,12 @@ namespace osu.Game.Screens.Play content.FadeOut(250); } + private void checkVolume(AudioManager audio) + { + if (audio.Volume.Value <= audio.Volume.MinValue || audio.VolumeTrack.Value <= audio.VolumeTrack.MinValue) + notificationOverlay.Post(new MutedNotification()); + } + public override void OnEntering(IScreen last) { base.OnEntering(last); @@ -473,5 +488,34 @@ namespace osu.Game.Screens.Play Loading = true; } } + + private class MutedNotification : SimpleNotification + { + public MutedNotification() + { + this.Text = "Your music volume is set to 0%! Click here to restore it."; + } + + public override bool IsImportant => true; + + public override bool RequestsFocus => true; + + [BackgroundDependencyLoader] + private void load(OsuColour colours, AudioManager audioManager, NotificationOverlay notificationOverlay) + { + Icon = FontAwesome.Solid.VolumeMute; + IconBackgound.Colour = colours.RedDark; + + Activated = delegate + { + notificationOverlay.Hide(); + + audioManager.Volume.SetDefault(); + audioManager.VolumeTrack.SetDefault(); + + return true; + }; + } + } } } From 4a10e6c44e767012cc93266b5c0a9041e6a8cf82 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sun, 15 Sep 2019 16:11:45 +0200 Subject: [PATCH 2970/5608] Use ResolvedAttribute for NotificationOverlay --- osu.Game/Screens/Play/PlayerLoader.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index b8d5fc7bda..aaf750b9f7 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -57,7 +57,8 @@ namespace osu.Game.Screens.Play private InputManager inputManager; - private NotificationOverlay notificationOverlay; + [Resolved] + private NotificationOverlay notificationOverlay { get; set; } private IdleTracker idleTracker; @@ -107,8 +108,6 @@ namespace osu.Game.Screens.Play loadNewPlayer(); - this.notificationOverlay = notificationOverlay; - checkVolume(audioManager); } From 72af640df7316e646fe0c80ffcf2b9fa7b73f2d3 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sun, 15 Sep 2019 16:31:40 +0200 Subject: [PATCH 2971/5608] Expose VolumeOverlay as available dependencies --- osu.Game/OsuGame.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 8fa8ffaf9b..b07cd84bc3 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -485,7 +485,8 @@ namespace osu.Game toolbarElements.Add(d); }); - loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add); + dependencies.Cache(loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add)); + loadComponentSingleFile(new OnScreenDisplay(), Add, true); loadComponentSingleFile(musicController = new MusicController(), Add, true); From 0afb5c5bb05f4a9b9e54f43b6d97f4b166a10b3d Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sun, 15 Sep 2019 16:31:57 +0200 Subject: [PATCH 2972/5608] Expose muted state from VolumeOverlay --- osu.Game/Overlays/VolumeOverlay.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index e6204a3179..ff3cbcd575 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -32,6 +32,12 @@ namespace osu.Game.Overlays private readonly BindableDouble muteAdjustment = new BindableDouble(); + public bool IsMuted + { + get => muteButton.Current.Value; + set => muteButton.Current.Value = value; + } + [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colours) { From 00e46fdefed6be79e6542464342a0e8a345c32e0 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sun, 15 Sep 2019 16:32:23 +0200 Subject: [PATCH 2973/5608] Add check if game is muted by MuteButton --- osu.Game/Screens/Play/PlayerLoader.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index aaf750b9f7..a00f005827 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -57,10 +58,13 @@ namespace osu.Game.Screens.Play private InputManager inputManager; + private IdleTracker idleTracker; + [Resolved] private NotificationOverlay notificationOverlay { get; set; } - private IdleTracker idleTracker; + [Resolved] + private VolumeOverlay volumeOverlay { get; set; } public PlayerLoader(Func createPlayer) { @@ -155,7 +159,7 @@ namespace osu.Game.Screens.Play private void checkVolume(AudioManager audio) { - if (audio.Volume.Value <= audio.Volume.MinValue || audio.VolumeTrack.Value <= audio.VolumeTrack.MinValue) + if (volumeOverlay.IsMuted || audio.Volume.Value <= audio.Volume.MinValue || audio.VolumeTrack.Value <= audio.VolumeTrack.MinValue) notificationOverlay.Post(new MutedNotification()); } @@ -500,7 +504,7 @@ namespace osu.Game.Screens.Play public override bool RequestsFocus => true; [BackgroundDependencyLoader] - private void load(OsuColour colours, AudioManager audioManager, NotificationOverlay notificationOverlay) + private void load(OsuColour colours, AudioManager audioManager, NotificationOverlay notificationOverlay, VolumeOverlay volumeOverlay) { Icon = FontAwesome.Solid.VolumeMute; IconBackgound.Colour = colours.RedDark; @@ -509,6 +513,7 @@ namespace osu.Game.Screens.Play { notificationOverlay.Hide(); + volumeOverlay.IsMuted = false; audioManager.Volume.SetDefault(); audioManager.VolumeTrack.SetDefault(); From 811a08d18ff2736b52382b95ba48b80544ff27f0 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sun, 15 Sep 2019 16:50:01 +0200 Subject: [PATCH 2974/5608] Use Bindable instead of bool --- osu.Game/Overlays/VolumeOverlay.cs | 6 +----- osu.Game/Screens/Play/PlayerLoader.cs | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index ff3cbcd575..0c08e0eb6e 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -32,11 +32,7 @@ namespace osu.Game.Overlays private readonly BindableDouble muteAdjustment = new BindableDouble(); - public bool IsMuted - { - get => muteButton.Current.Value; - set => muteButton.Current.Value = value; - } + public Bindable IsMuted => muteButton.Current; [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colours) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index a00f005827..baeec27412 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -159,7 +159,7 @@ namespace osu.Game.Screens.Play private void checkVolume(AudioManager audio) { - if (volumeOverlay.IsMuted || audio.Volume.Value <= audio.Volume.MinValue || audio.VolumeTrack.Value <= audio.VolumeTrack.MinValue) + if (volumeOverlay.IsMuted.Value || audio.Volume.Value <= audio.Volume.MinValue || audio.VolumeTrack.Value <= audio.VolumeTrack.MinValue) notificationOverlay.Post(new MutedNotification()); } @@ -513,7 +513,7 @@ namespace osu.Game.Screens.Play { notificationOverlay.Hide(); - volumeOverlay.IsMuted = false; + volumeOverlay.IsMuted.Value = false; audioManager.Volume.SetDefault(); audioManager.VolumeTrack.SetDefault(); From 08ab4e508f07b774f83c35063cb7d5216aecb421 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sun, 15 Sep 2019 17:15:52 +0200 Subject: [PATCH 2975/5608] Use loadComponentSingleFile for caching --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b07cd84bc3..d539fe0f50 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -485,7 +485,7 @@ namespace osu.Game toolbarElements.Add(d); }); - dependencies.Cache(loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add)); + loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add, true); loadComponentSingleFile(new OnScreenDisplay(), Add, true); From ec788ac09d8ac8343e374187725fbb8a7c4cef24 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sun, 15 Sep 2019 17:20:07 +0200 Subject: [PATCH 2976/5608] Make notification only show up once per session --- osu.Game/Screens/Play/PlayerLoader.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index baeec27412..3bce6fa1ed 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -66,6 +66,8 @@ namespace osu.Game.Screens.Play [Resolved] private VolumeOverlay volumeOverlay { get; set; } + private bool muteWarningShownOnce = false; + public PlayerLoader(Func createPlayer) { this.createPlayer = createPlayer; @@ -159,8 +161,12 @@ namespace osu.Game.Screens.Play private void checkVolume(AudioManager audio) { - if (volumeOverlay.IsMuted.Value || audio.Volume.Value <= audio.Volume.MinValue || audio.VolumeTrack.Value <= audio.VolumeTrack.MinValue) + //Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. + if (!muteWarningShownOnce && (volumeOverlay.IsMuted.Value || audio.Volume.Value <= audio.Volume.MinValue || audio.VolumeTrack.Value <= audio.VolumeTrack.MinValue)) + { notificationOverlay.Post(new MutedNotification()); + muteWarningShownOnce = true; + } } public override void OnEntering(IScreen last) From 2381b4c00365e8d59003b9fc235f25e953618cb7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Sep 2019 00:20:56 +0900 Subject: [PATCH 2977/5608] Move video behind storyboard --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 5c7ac9e762..309f4837e5 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -143,8 +143,8 @@ namespace osu.Game.Screens.Play private void addUnderlayComponents(Container target) { - target.Add(DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both }); target.Add(DimmableVideo = new DimmableVideo(Beatmap.Value.Video) { RelativeSizeAxes = Axes.Both }); + target.Add(DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both }); } private void addGameplayComponents(Container target, WorkingBeatmap working) From e3884658af0be36a364e8637b70fea1f2b20ff08 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sun, 15 Sep 2019 17:36:53 +0200 Subject: [PATCH 2978/5608] Resolve code inspection errors --- osu.Game/Screens/Play/PlayerLoader.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 3bce6fa1ed..d78f36f6de 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -66,7 +65,7 @@ namespace osu.Game.Screens.Play [Resolved] private VolumeOverlay volumeOverlay { get; set; } - private bool muteWarningShownOnce = false; + private bool muteWarningShownOnce; public PlayerLoader(Func createPlayer) { @@ -500,10 +499,7 @@ namespace osu.Game.Screens.Play private class MutedNotification : SimpleNotification { - public MutedNotification() - { - this.Text = "Your music volume is set to 0%! Click here to restore it."; - } + public MutedNotification() => Text = "Your music volume is set to 0%! Click here to restore it."; public override bool IsImportant => true; From ecce12981e7bea177c784912d6adc360805be57e Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sun, 15 Sep 2019 17:47:44 +0200 Subject: [PATCH 2979/5608] Use block body for constructor to fix remaining code inspection issue --- osu.Game/Screens/Play/PlayerLoader.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index d78f36f6de..df55b738e1 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -499,7 +499,10 @@ namespace osu.Game.Screens.Play private class MutedNotification : SimpleNotification { - public MutedNotification() => Text = "Your music volume is set to 0%! Click here to restore it."; + public MutedNotification() + { + Text = "Your music volume is set to 0%! Click here to restore it."; + } public override bool IsImportant => true; From 43760bdfcdfffd6301a4cba30c2d86c131b8a2c2 Mon Sep 17 00:00:00 2001 From: HoLLy-HaCKeR Date: Sun, 15 Sep 2019 18:29:14 +0200 Subject: [PATCH 2980/5608] Specify Rider analysis rules explicitly --- osu.Android.sln.DotSettings | 21 ++++++++++++++++++++- osu.iOS.sln.DotSettings | 22 +++++++++++++++++++++- osu.sln.DotSettings | 12 ++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/osu.Android.sln.DotSettings b/osu.Android.sln.DotSettings index 3f5bd9d34d..5a97fc7518 100644 --- a/osu.Android.sln.DotSettings +++ b/osu.Android.sln.DotSettings @@ -1,4 +1,4 @@ - + True True True @@ -167,6 +167,14 @@ WARNING <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> Code Cleanup (peppy) + Required + Required + Required + Explicit + ExpressionBody + ExpressionBody + True + NEXT_LINE True True True @@ -176,12 +184,22 @@ True True NEXT_LINE + 1 + 1 + NEXT_LINE + MULTILINE NEXT_LINE + 1 + 1 True + NEXT_LINE NEVER NEVER + True False + True NEVER + False False True False @@ -189,6 +207,7 @@ True True False + False CHOP_IF_LONG True 200 diff --git a/osu.iOS.sln.DotSettings b/osu.iOS.sln.DotSettings index 3b2b851d45..752b817910 100644 --- a/osu.iOS.sln.DotSettings +++ b/osu.iOS.sln.DotSettings @@ -1,4 +1,4 @@ - + True True True @@ -165,8 +165,17 @@ HINT HINT WARNING + WARNING <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> Code Cleanup (peppy) + Required + Required + Required + Explicit + ExpressionBody + ExpressionBody + True + NEXT_LINE True True True @@ -176,12 +185,22 @@ True True NEXT_LINE + 1 + 1 + NEXT_LINE + MULTILINE NEXT_LINE + 1 + 1 True + NEXT_LINE NEVER NEVER + True False + True NEVER + False False True False @@ -189,6 +208,7 @@ True True False + False CHOP_IF_LONG True 200 diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index c3e274569d..ed162eed6e 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -218,9 +218,14 @@ WARNING <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> Code Cleanup (peppy) + Required + Required + Required + Explicit ExpressionBody ExpressionBody True + NEXT_LINE True True True @@ -232,14 +237,20 @@ NEXT_LINE 1 1 + NEXT_LINE + MULTILINE NEXT_LINE 1 1 True + NEXT_LINE NEVER NEVER + True False + True NEVER + False False True False @@ -247,6 +258,7 @@ True True False + False CHOP_IF_LONG True 200 From a407e267a238575d1418a94f3d912479a84f0bca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Sep 2019 22:55:25 +0200 Subject: [PATCH 2981/5608] Fix PF/SD legacy mod conversion Upon investigating an user report in #6091 that indicated that viewing replays using the Perfect mod would also display the Sudden Death mod icon despite Perfect being the more restrictive of the two, it turned out that the logic of importing legacy scores was missing that corner case. A similar case of Double Time/Nightcore mutual exclusion was handled, but PF/SD was missed. Add analogous handling of PF/SD legacy mods for all four rulesets, and additionally cover a tiny fraction of all cases with unit tests. The most problematic cases (NC+HD and PF+SD) are covered in all four basic rulesets. --- .../CatchLegacyModConversionTest.cs | 29 +++++++++++++++ osu.Game.Rulesets.Catch/CatchRuleset.cs | 11 +++--- .../ManiaLegacyModConversionTest.cs | 30 ++++++++++++++++ osu.Game.Rulesets.Mania/ManiaRuleset.cs | 11 +++--- .../OsuLegacyModConversionTest.cs | 30 ++++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 11 +++--- .../TaikoLegacyModConversionTest.cs | 29 +++++++++++++++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 11 +++--- .../Tests/Beatmaps/LegacyModConversionTest.cs | 35 +++++++++++++++++++ 9 files changed, 173 insertions(+), 24 deletions(-) create mode 100644 osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs create mode 100644 osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs create mode 100644 osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs create mode 100644 osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs create mode 100644 osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs diff --git a/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs new file mode 100644 index 0000000000..04e6dea376 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Catch.Mods; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Catch.Tests +{ + [TestFixture] + public class CatchLegacyModConversionTest : LegacyModConversionTest + { + [TestCase(LegacyMods.Easy, new[] { typeof(CatchModEasy) })] + [TestCase(LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(CatchModHardRock), typeof(CatchModDoubleTime) })] + [TestCase(LegacyMods.DoubleTime, new[] { typeof(CatchModDoubleTime) })] + [TestCase(LegacyMods.Nightcore, new[] { typeof(CatchModNightcore) })] + [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(CatchModNightcore) })] + [TestCase(LegacyMods.Flashlight | LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(CatchModFlashlight), typeof(CatchModNightcore) })] + [TestCase(LegacyMods.Perfect, new[] { typeof(CatchModPerfect) })] + [TestCase(LegacyMods.SuddenDeath, new[] { typeof(CatchModSuddenDeath) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(CatchModPerfect) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath | LegacyMods.DoubleTime, new[] { typeof(CatchModDoubleTime), typeof(CatchModPerfect) })] + public new void Test(LegacyMods legacyMods, Type[] expectedMods) => base.Test(legacyMods, expectedMods); + + protected override Ruleset CreateRuleset() => new CatchRuleset(); + } +} diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 5428b4eeb8..71d68ace94 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -46,6 +46,11 @@ namespace osu.Game.Rulesets.Catch else if (mods.HasFlag(LegacyMods.DoubleTime)) yield return new CatchModDoubleTime(); + if (mods.HasFlag(LegacyMods.Perfect)) + yield return new CatchModPerfect(); + else if (mods.HasFlag(LegacyMods.SuddenDeath)) + yield return new CatchModSuddenDeath(); + if (mods.HasFlag(LegacyMods.Autoplay)) yield return new CatchModAutoplay(); @@ -67,14 +72,8 @@ namespace osu.Game.Rulesets.Catch if (mods.HasFlag(LegacyMods.NoFail)) yield return new CatchModNoFail(); - if (mods.HasFlag(LegacyMods.Perfect)) - yield return new CatchModPerfect(); - if (mods.HasFlag(LegacyMods.Relax)) yield return new CatchModRelax(); - - if (mods.HasFlag(LegacyMods.SuddenDeath)) - yield return new CatchModSuddenDeath(); } public override IEnumerable GetModsFor(ModType type) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs new file mode 100644 index 0000000000..957743c5f1 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [TestFixture] + public class ManiaLegacyModConversionTest : LegacyModConversionTest + { + [TestCase(LegacyMods.Easy, new[] { typeof(ManiaModEasy) })] + [TestCase(LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(ManiaModHardRock), typeof(ManiaModDoubleTime) })] + [TestCase(LegacyMods.DoubleTime, new[] { typeof(ManiaModDoubleTime) })] + [TestCase(LegacyMods.Nightcore, new[] { typeof(ManiaModNightcore) })] + [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(ManiaModNightcore) })] + [TestCase(LegacyMods.Flashlight | LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(ManiaModFlashlight), typeof(ManiaModNightcore) })] + [TestCase(LegacyMods.Perfect, new[] { typeof(ManiaModPerfect) })] + [TestCase(LegacyMods.SuddenDeath, new[] { typeof(ManiaModSuddenDeath) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(ManiaModPerfect) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath | LegacyMods.DoubleTime, new[] { typeof(ManiaModDoubleTime), typeof(ManiaModPerfect) })] + [TestCase(LegacyMods.Random | LegacyMods.SuddenDeath, new[] { typeof(ManiaModRandom), typeof(ManiaModSuddenDeath) })] + public new void Test(LegacyMods legacyMods, Type[] expectedMods) => base.Test(legacyMods, expectedMods); + + protected override Ruleset CreateRuleset() => new ManiaRuleset(); + } +} diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 0c4e7d4858..c74a292331 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -46,6 +46,11 @@ namespace osu.Game.Rulesets.Mania else if (mods.HasFlag(LegacyMods.DoubleTime)) yield return new ManiaModDoubleTime(); + if (mods.HasFlag(LegacyMods.Perfect)) + yield return new ManiaModPerfect(); + else if (mods.HasFlag(LegacyMods.SuddenDeath)) + yield return new ManiaModSuddenDeath(); + if (mods.HasFlag(LegacyMods.Autoplay)) yield return new ManiaModAutoplay(); @@ -97,14 +102,8 @@ namespace osu.Game.Rulesets.Mania if (mods.HasFlag(LegacyMods.NoFail)) yield return new ManiaModNoFail(); - if (mods.HasFlag(LegacyMods.Perfect)) - yield return new ManiaModPerfect(); - if (mods.HasFlag(LegacyMods.Random)) yield return new ManiaModRandom(); - - if (mods.HasFlag(LegacyMods.SuddenDeath)) - yield return new ManiaModSuddenDeath(); } public override IEnumerable GetModsFor(ModType type) diff --git a/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs new file mode 100644 index 0000000000..495f2738b5 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Osu.Tests +{ + [TestFixture] + public class OsuLegacyModConversionTest : LegacyModConversionTest + { + [TestCase(LegacyMods.Easy, new[] { typeof(OsuModEasy) })] + [TestCase(LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(OsuModHardRock), typeof(OsuModDoubleTime) })] + [TestCase(LegacyMods.DoubleTime, new[] { typeof(OsuModDoubleTime) })] + [TestCase(LegacyMods.Nightcore, new[] { typeof(OsuModNightcore) })] + [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(OsuModNightcore) })] + [TestCase(LegacyMods.Flashlight | LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(OsuModFlashlight), typeof(OsuModFlashlight) })] + [TestCase(LegacyMods.Perfect, new[] { typeof(OsuModPerfect) })] + [TestCase(LegacyMods.SuddenDeath, new[] { typeof(OsuModSuddenDeath) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(OsuModPerfect) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath | LegacyMods.DoubleTime, new[] { typeof(OsuModDoubleTime), typeof(OsuModPerfect) })] + [TestCase(LegacyMods.SpunOut | LegacyMods.Easy, new[] { typeof(OsuModSpunOut), typeof(OsuModEasy) })] + public new void Test(LegacyMods legacyMods, Type[] expectedMods) => base.Test(legacyMods, expectedMods); + + protected override Ruleset CreateRuleset() => new OsuRuleset(); + } +} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index ceb9ed9343..df2ae81a5a 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -52,6 +52,11 @@ namespace osu.Game.Rulesets.Osu else if (mods.HasFlag(LegacyMods.DoubleTime)) yield return new OsuModDoubleTime(); + if (mods.HasFlag(LegacyMods.Perfect)) + yield return new OsuModPerfect(); + else if (mods.HasFlag(LegacyMods.SuddenDeath)) + yield return new OsuModSuddenDeath(); + if (mods.HasFlag(LegacyMods.Autopilot)) yield return new OsuModAutopilot(); @@ -76,18 +81,12 @@ namespace osu.Game.Rulesets.Osu if (mods.HasFlag(LegacyMods.NoFail)) yield return new OsuModNoFail(); - if (mods.HasFlag(LegacyMods.Perfect)) - yield return new OsuModPerfect(); - if (mods.HasFlag(LegacyMods.Relax)) yield return new OsuModRelax(); if (mods.HasFlag(LegacyMods.SpunOut)) yield return new OsuModSpunOut(); - if (mods.HasFlag(LegacyMods.SuddenDeath)) - yield return new OsuModSuddenDeath(); - if (mods.HasFlag(LegacyMods.Target)) yield return new OsuModTarget(); diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs new file mode 100644 index 0000000000..a59544386b --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Taiko.Mods; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + [TestFixture] + public class TaikoLegacyModConversionTest : LegacyModConversionTest + { + [TestCase(LegacyMods.Easy, new[] { typeof(TaikoModEasy) })] + [TestCase(LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(TaikoModHardRock), typeof(TaikoModDoubleTime) })] + [TestCase(LegacyMods.DoubleTime, new[] { typeof(TaikoModDoubleTime) })] + [TestCase(LegacyMods.Nightcore, new[] { typeof(TaikoModNightcore) })] + [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(TaikoModNightcore) })] + [TestCase(LegacyMods.Flashlight | LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(TaikoModFlashlight), typeof(TaikoModNightcore) })] + [TestCase(LegacyMods.Perfect, new[] { typeof(TaikoModPerfect) })] + [TestCase(LegacyMods.SuddenDeath, new[] { typeof(TaikoModSuddenDeath) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(TaikoModPerfect) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath | LegacyMods.DoubleTime, new[] { typeof(TaikoModDoubleTime), typeof(TaikoModPerfect) })] + public new void Test(LegacyMods legacyMods, Type[] expectedMods) => base.Test(legacyMods, expectedMods); + + protected override Ruleset CreateRuleset() => new TaikoRuleset(); + } +} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 7fdb823388..b2655f592c 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -45,6 +45,11 @@ namespace osu.Game.Rulesets.Taiko else if (mods.HasFlag(LegacyMods.DoubleTime)) yield return new TaikoModDoubleTime(); + if (mods.HasFlag(LegacyMods.Perfect)) + yield return new TaikoModPerfect(); + else if (mods.HasFlag(LegacyMods.SuddenDeath)) + yield return new TaikoModSuddenDeath(); + if (mods.HasFlag(LegacyMods.Autoplay)) yield return new TaikoModAutoplay(); @@ -66,14 +71,8 @@ namespace osu.Game.Rulesets.Taiko if (mods.HasFlag(LegacyMods.NoFail)) yield return new TaikoModNoFail(); - if (mods.HasFlag(LegacyMods.Perfect)) - yield return new TaikoModPerfect(); - if (mods.HasFlag(LegacyMods.Relax)) yield return new TaikoModRelax(); - - if (mods.HasFlag(LegacyMods.SuddenDeath)) - yield return new TaikoModSuddenDeath(); } public override IEnumerable GetModsFor(ModType type) diff --git a/osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs b/osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs new file mode 100644 index 0000000000..e9251f8011 --- /dev/null +++ b/osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using NUnit.Framework; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets; + +namespace osu.Game.Tests.Beatmaps +{ + /// + /// Base class for tests of converting enumeration flags to ruleset mod instances. + /// + public abstract class LegacyModConversionTest + { + /// + /// Creates the whose legacy mod conversion is to be tested. + /// + /// + protected abstract Ruleset CreateRuleset(); + + protected void Test(LegacyMods legacyMods, Type[] expectedMods) + { + var ruleset = CreateRuleset(); + var mods = ruleset.ConvertLegacyMods(legacyMods).ToList(); + Assert.AreEqual(expectedMods.Length, mods.Count); + + foreach (var modType in expectedMods) + { + Assert.IsNotNull(mods.SingleOrDefault(mod => mod.GetType() == modType)); + } + } + } +} From 220fdd0a044105e268cccfe9c113c1dce6fcf668 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Mon, 16 Sep 2019 06:56:52 +0200 Subject: [PATCH 2982/5608] Make muteWarningShownOnce static ... so it will actually get an instance per osu session. --- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index df55b738e1..dbb6c47943 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -65,7 +65,7 @@ namespace osu.Game.Screens.Play [Resolved] private VolumeOverlay volumeOverlay { get; set; } - private bool muteWarningShownOnce; + private static bool muteWarningShownOnce; public PlayerLoader(Func createPlayer) { From 78b6062100d83db9f6bc5c35f99a62c4038527d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Sep 2019 17:54:12 +0900 Subject: [PATCH 2983/5608] Update fastlane version --- Gemfile.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index f7c19064b4..ac46fddb41 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,9 +1,9 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.0) - addressable (2.6.0) - public_suffix (>= 2.0.2, < 4.0) + CFPropertyList (3.0.1) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) atomos (0.1.3) babosa (1.0.2) claide (1.0.3) @@ -26,8 +26,8 @@ GEM http-cookie (~> 1.0.0) faraday_middleware (0.13.1) faraday (>= 0.7.4, < 1.0) - fastimage (2.1.5) - fastlane (2.129.0) + fastimage (2.1.7) + fastlane (2.131.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.3, < 3.0.0) babosa (>= 1.0.2, < 2.0.0) @@ -77,9 +77,9 @@ GEM representable (~> 3.0) retriable (>= 2.0, < 4.0) signet (~> 0.9) - google-cloud-core (1.3.0) + google-cloud-core (1.3.1) google-cloud-env (~> 1.0) - google-cloud-env (1.2.0) + google-cloud-env (1.2.1) faraday (~> 0.11) google-cloud-storage (1.16.0) digest-crc (~> 0.4) @@ -100,9 +100,9 @@ GEM json (2.2.0) jwt (2.1.0) memoist (0.16.0) - mime-types (3.2.2) + mime-types (3.3) mime-types-data (~> 3.2015) - mime-types-data (3.2019.0331) + mime-types-data (3.2019.0904) mini_magick (4.9.5) mini_portile2 (2.4.0) multi_json (1.13.1) @@ -121,14 +121,14 @@ GEM uber (< 0.2.0) retriable (3.1.2) rouge (2.0.7) - rubyzip (1.2.3) + rubyzip (1.2.4) security (0.1.3) signet (0.11.0) addressable (~> 2.3) faraday (~> 0.9) jwt (>= 1.5, < 3.0) multi_json (~> 1.10) - simctl (1.6.5) + simctl (1.6.6) CFPropertyList naturally slack-notifier (2.3.2) From 7bc4b4f98164bfa0d052c51b4540cb76afe10dc9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Sep 2019 18:08:11 +0900 Subject: [PATCH 2984/5608] Explicitly specify solution in beta lane --- fastlane/Fastfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index dd35fa0b46..e4a6bc4585 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -3,6 +3,9 @@ update_fastlane platform :android do desc 'Deploy to play store' lane :beta do |options| + + options[:solution_path] = 'osu.Android.sln' + # update csproj version update_version(options) From efedfefe635e63c8cad19c73ff56e29482741be9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Sep 2019 15:54:11 +0900 Subject: [PATCH 2985/5608] Fix disclaimer potentially pushing a null screen --- osu.Game/Screens/Menu/Disclaimer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index 073ab639e3..17f999d519 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -173,7 +173,11 @@ namespace osu.Game.Screens.Menu .Then(5500) .FadeOut(250) .ScaleTo(0.9f, 250, Easing.InQuint) - .Finally(d => this.Push(nextScreen)); + .Finally(d => + { + if (nextScreen != null) + this.Push(nextScreen); + }); } } } From f0bcb2b9337a94fa429b9aa609c5444f95dbab34 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Sep 2019 16:12:18 +0900 Subject: [PATCH 2986/5608] Debounce user-requested replay seeks --- osu.Game/Screens/Play/SongProgressBar.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index dd7b5826d5..33c7595b37 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.MathUtils; +using osu.Framework.Threading; namespace osu.Game.Screens.Play { @@ -121,6 +122,12 @@ namespace osu.Game.Screens.Play handleBase.X = newX; } - protected override void OnUserChange(double value) => OnSeek?.Invoke(value); + private ScheduledDelegate scheduledSeek; + + protected override void OnUserChange(double value) + { + scheduledSeek?.Cancel(); + scheduledSeek = Schedule(() => OnSeek?.Invoke(value)); + } } } From 9543c277845bfeb1d1eaa282700c863a50ec0c21 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Sep 2019 19:10:41 +0900 Subject: [PATCH 2987/5608] Add full upload support --- fastlane/Fastfile | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index e4a6bc4585..906d284bc9 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -4,16 +4,21 @@ platform :android do desc 'Deploy to play store' lane :beta do |options| - options[:solution_path] = 'osu.Android.sln' - # update csproj version - update_version(options) + update_version( + solution_path: 'osu.Android.sln', + version: options[:version], + build: options[:build], + ) build() - client = HTTPClient.new - changelog = client.get_content 'https://gist.githubusercontent.com/peppy/ab89c29dcc0dce95f39eb218e8fad197/raw' - changelog.gsub!('$BUILD_ID', options[:build]) + supply( + apk: './osu.Android/bin/Release/sh.ppy.osulazer-Signed.apk', + package_name: 'sh.ppy.osulazer', + track: 'alpha', # upload to alpha, we can promote it later + json_key: options[:json_key], + ) end desc 'Compile the project' From 77947e83097164eb73adc4b380fd2b80fcf643e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Sep 2019 22:33:27 +0900 Subject: [PATCH 2988/5608] Fix rewind tests failing --- .../Replays/CatchAutoGenerator.cs | 1 + .../Replays/ManiaAutoGenerator.cs | 1 + .../Visual/Gameplay/TestSceneAutoplay.cs | 19 ++++++++++++++----- osu.Game/Screens/Play/GameplayClock.cs | 2 ++ osu.Game/Tests/Visual/OsuTestScene.cs | 4 ++-- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 4ea1f22006..7f972a25ae 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -39,6 +39,7 @@ namespace osu.Game.Rulesets.Catch.Replays // Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled addFrame(-100000, lastPosition); + addFrame(0, lastPosition); void moveToNext(CatchHitObject h) { diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 7b8bbc2095..5d333e2047 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -49,6 +49,7 @@ namespace osu.Game.Rulesets.Mania.Replays { // Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled Replay.Frames.Add(new ManiaReplayFrame(-100000, 0)); + Replay.Frames.Add(new ManiaReplayFrame(0, 0)); var pointGroups = generateActionPoints().GroupBy(a => a.Time).OrderBy(g => g.First().Time); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index e2b620ea98..883aa9fc36 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Linq; +using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; @@ -12,6 +13,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Description("Player instantiated with an autoplay mod.")] public class TestSceneAutoplay : AllPlayersTestScene { + private ClockBackedTestWorkingBeatmap.TrackVirtualManual track; + protected override Player CreatePlayer(Ruleset ruleset) { Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); @@ -22,11 +25,17 @@ namespace osu.Game.Tests.Visual.Gameplay { AddUntilStep("score above zero", () => ((ScoreAccessiblePlayer)Player).ScoreProcessor.TotalScore.Value > 0); AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 5)); - AddStep("rewind", () => - { - ((ScoreAccessiblePlayer)Player).GameplayClockContainer.Seek(0); - }); - AddUntilStep("key counter counted no", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); + AddStep("rewind", () => track.Seek(-10000)); + AddUntilStep("key counter reset", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); + } + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) + { + var working = base.CreateWorkingBeatmap(beatmap); + + track = (ClockBackedTestWorkingBeatmap.TrackVirtualManual)working.Track; + + return working; } private class ScoreAccessiblePlayer : TestPlayer diff --git a/osu.Game/Screens/Play/GameplayClock.cs b/osu.Game/Screens/Play/GameplayClock.cs index b1948d02d5..379c4c89ed 100644 --- a/osu.Game/Screens/Play/GameplayClock.cs +++ b/osu.Game/Screens/Play/GameplayClock.cs @@ -42,5 +42,7 @@ namespace osu.Game.Screens.Play public double FramesPerSecond => underlyingClock.FramesPerSecond; public FrameTimeInfo TimeInfo => underlyingClock.TimeInfo; + + public IClock Source => underlyingClock; } } diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 2b8baab57c..32a32cfa43 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.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; @@ -239,7 +239,7 @@ namespace osu.Game.Tests.Visual public override bool Seek(double seek) { - offset = MathHelper.Clamp(seek, 0, Length); + offset = Math.Min(seek, Length); lastReferenceTime = null; return offset == seek; From 057c4aa795657654822ce73c086352e75a9677f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Sep 2019 22:42:20 +0900 Subject: [PATCH 2989/5608] Remove unused using statement --- osu.Game/Tests/Visual/OsuTestScene.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 32a32cfa43..2bc9273f69 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -20,7 +20,6 @@ using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Tests.Beatmaps; -using osuTK; namespace osu.Game.Tests.Visual { From 3ab352ffe51b0a37fef9af64569b91c9bbc0d2b0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Sep 2019 23:08:37 +0900 Subject: [PATCH 2990/5608] Randomise beatmap playback order on startup Closes #6135. --- osu.Game/Overlays/Music/PlaylistList.cs | 18 ++++++++++-------- osu.Game/Overlays/MusicController.cs | 21 +++++++++++---------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 539601c359..6ad0aa23ec 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -44,6 +45,8 @@ namespace osu.Game.Overlays.Music private class ItemsScrollContainer : OsuScrollContainer { + private BindableList beatmaps; + public Action Selected; public Action OrderChanged; @@ -73,20 +76,19 @@ namespace osu.Game.Overlays.Music } [BackgroundDependencyLoader] - private void load(BeatmapManager beatmaps, IBindable beatmap) + private void load(MusicController musicController, IBindable beatmap) { - beatmaps.GetAllUsableBeatmapSets().ForEach(addBeatmapSet); - beatmaps.ItemAdded += addBeatmapSet; - beatmaps.ItemRemoved += removeBeatmapSet; + beatmaps = musicController.BeatmapSets.GetBoundCopy(); + + beatmaps.ItemsAdded += i => i.ForEach(addBeatmapSet); + beatmaps.ItemsRemoved += i => i.ForEach(removeBeatmapSet); + beatmaps.ForEach(addBeatmapSet); beatmapBacking.BindTo(beatmap); beatmapBacking.ValueChanged += _ => updateSelectedSet(); } - private void addBeatmapSet(BeatmapSetInfo obj) => Schedule(() => - { - items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }); - }); + private void addBeatmapSet(BeatmapSetInfo obj) => Schedule(() => { items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }); }); private void removeBeatmapSet(BeatmapSetInfo obj) => Schedule(() => { diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 6ad147735b..92246dfc62 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; +using osu.Framework.MathUtils; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Input.Bindings; @@ -24,7 +25,7 @@ namespace osu.Game.Overlays [Resolved] private BeatmapManager beatmaps { get; set; } - private List beatmapSets; + public readonly BindableList BeatmapSets = new BindableList(); public bool IsUserPaused { get; private set; } @@ -46,7 +47,7 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load() { - beatmapSets = beatmaps.GetAllUsableBeatmapSets(); + BeatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next())); beatmaps.ItemAdded += handleBeatmapAdded; beatmaps.ItemRemoved += handleBeatmapRemoved; } @@ -65,8 +66,8 @@ namespace osu.Game.Overlays /// The new position. public void ChangeBeatmapSetPosition(BeatmapSetInfo beatmapSetInfo, int index) { - beatmapSets.Remove(beatmapSetInfo); - beatmapSets.Insert(index, beatmapSetInfo); + BeatmapSets.Remove(beatmapSetInfo); + BeatmapSets.Insert(index, beatmapSetInfo); } /// @@ -75,10 +76,10 @@ namespace osu.Game.Overlays public bool IsPlaying => beatmap.Value.Track.IsRunning; private void handleBeatmapAdded(BeatmapSetInfo set) => - Schedule(() => beatmapSets.Add(set)); + Schedule(() => BeatmapSets.Add(set)); private void handleBeatmapRemoved(BeatmapSetInfo set) => - Schedule(() => beatmapSets.RemoveAll(s => s.ID == set.ID)); + Schedule(() => BeatmapSets.RemoveAll(s => s.ID == set.ID)); private ScheduledDelegate seekDelegate; @@ -140,7 +141,7 @@ namespace osu.Game.Overlays { queuedDirection = TrackChangeDirection.Prev; - var playable = beatmapSets.TakeWhile(i => i.ID != current.BeatmapSetInfo.ID).LastOrDefault() ?? beatmapSets.LastOrDefault(); + var playable = BeatmapSets.TakeWhile(i => i.ID != current.BeatmapSetInfo.ID).LastOrDefault() ?? BeatmapSets.LastOrDefault(); if (playable != null) { @@ -165,7 +166,7 @@ namespace osu.Game.Overlays if (!instant) queuedDirection = TrackChangeDirection.Next; - var playable = beatmapSets.SkipWhile(i => i.ID != current.BeatmapSetInfo.ID).Skip(1).FirstOrDefault() ?? beatmapSets.FirstOrDefault(); + var playable = BeatmapSets.SkipWhile(i => i.ID != current.BeatmapSetInfo.ID).Skip(1).FirstOrDefault() ?? BeatmapSets.FirstOrDefault(); if (playable != null) { @@ -200,8 +201,8 @@ namespace osu.Game.Overlays else { //figure out the best direction based on order in playlist. - var last = beatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); - var next = beatmap.NewValue == null ? -1 : beatmapSets.TakeWhile(b => b.ID != beatmap.NewValue.BeatmapSetInfo?.ID).Count(); + var last = BeatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); + var next = beatmap.NewValue == null ? -1 : BeatmapSets.TakeWhile(b => b.ID != beatmap.NewValue.BeatmapSetInfo?.ID).Count(); direction = last > next ? TrackChangeDirection.Prev : TrackChangeDirection.Next; } From b5b29a21e783b93d21ea955d473fce33d59c8d47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 02:15:18 +0900 Subject: [PATCH 2991/5608] Move menu cursor rotation to more appropriate settings section --- .../Overlays/Settings/Sections/Graphics/DetailSettings.cs | 5 ----- .../{MainMenuSettings.cs => UserInterfaceSettings.cs} | 7 ++++++- osu.Game/Overlays/Settings/Sections/GraphicsSection.cs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) rename osu.Game/Overlays/Settings/Sections/Graphics/{MainMenuSettings.cs => UserInterfaceSettings.cs} (71%) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index 56e56f6ca8..9be34c3073 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -26,11 +26,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics LabelText = "Video", Bindable = config.GetBindable(OsuSetting.ShowVideoBackground) }, - new SettingsCheckbox - { - LabelText = "Rotate cursor when dragging", - Bindable = config.GetBindable(OsuSetting.CursorRotation) - }, new SettingsEnumDropdown { LabelText = "Screenshot format", diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs similarity index 71% rename from osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs rename to osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs index 92f64d0e14..dd822fedb6 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs @@ -6,7 +6,7 @@ using osu.Game.Configuration; namespace osu.Game.Overlays.Settings.Sections.Graphics { - public class MainMenuSettings : SettingsSubsection + public class UserInterfaceSettings : SettingsSubsection { protected override string Header => "User Interface"; @@ -15,6 +15,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { Children = new[] { + new SettingsCheckbox + { + LabelText = "Rotate cursor when dragging", + Bindable = config.GetBindable(OsuSetting.CursorRotation) + }, new SettingsCheckbox { LabelText = "Parallax", diff --git a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs index 3d6086d3ea..89caa3dc8f 100644 --- a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Settings.Sections new RendererSettings(), new LayoutSettings(), new DetailSettings(), - new MainMenuSettings(), + new UserInterfaceSettings(), }; } } From 63cc8d4f90b29a165f43eb704cc9c0a057766a5f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 02:16:57 +0900 Subject: [PATCH 2992/5608] Add hit lighting setting --- osu.Game/Configuration/OsuConfigManager.cs | 5 ++++- .../Overlays/Settings/Sections/Graphics/DetailSettings.cs | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index e26021d930..4cbf2b4d94 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -81,6 +81,8 @@ namespace osu.Game.Configuration Set(OsuSetting.DimLevel, 0.3, 0, 1, 0.01); Set(OsuSetting.BlurLevel, 0, 0, 1, 0.01); + Set(OsuSetting.HitLighting, true); + Set(OsuSetting.ShowInterface, true); Set(OsuSetting.ShowHealthDisplayWhenCantFail, true); Set(OsuSetting.KeyOverlay, false); @@ -180,6 +182,7 @@ namespace osu.Game.Configuration ScalingSizeX, ScalingSizeY, UIScale, - IntroSequence + IntroSequence, + HitLighting } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index 56e56f6ca8..5189d573cc 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -27,6 +27,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Bindable = config.GetBindable(OsuSetting.ShowVideoBackground) }, new SettingsCheckbox + { + LabelText = "Hit Lighting", + Bindable = config.GetBindable(OsuSetting.HitLighting) + }, + new SettingsCheckbox { LabelText = "Rotate cursor when dragging", Bindable = config.GetBindable(OsuSetting.CursorRotation) From ba76f09c99df0c59c37c85c32ccbdc24875a9d30 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 02:49:54 +0900 Subject: [PATCH 2993/5608] Add initial implementation of hit lighting Requires a supporting skin, like osu!classic for now. --- .../Objects/Drawables/DrawableOsuJudgement.cs | 44 +++++++++++++++++++ .../Rulesets/Judgements/DrawableJudgement.cs | 8 +++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index 938a2293ba..022e9ea12b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -1,22 +1,66 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Configuration; using osuTK; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Scoring; +using osu.Game.Skinning; +using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableOsuJudgement : DrawableJudgement { + private SkinnableSprite lighting; + private Bindable lightingColour; + public DrawableOsuJudgement(JudgementResult result, DrawableHitObject judgedObject) : base(result, judgedObject) { } + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + if (config.Get(OsuSetting.HitLighting) && Result.Type != HitResult.Miss) + { + AddInternal(lighting = new SkinnableSprite("lighting") + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Blending = BlendingParameters.Additive, + Depth = float.MaxValue + }); + + if (JudgedObject != null) + { + lightingColour = JudgedObject.AccentColour.GetBoundCopy(); + lightingColour.BindValueChanged(colour => lighting.Colour = colour.NewValue, true); + } + else + { + lighting.Colour = Color4.White; + } + } + } + + protected override double FadeOutDelay => lighting == null ? base.FadeOutDelay : 1400; + protected override void ApplyHitAnimations() { + if (lighting != null) + { + JudgementBody.Delay(FadeInDuration).FadeOut(400); + + lighting.ScaleTo(0.8f).ScaleTo(1.2f, 600, Easing.Out); + lighting.FadeIn(200).Then().Delay(200).FadeOut(1000); + } + JudgementText?.TransformSpacingTo(new Vector2(14, 0), 1800, Easing.OutQuint); base.ApplyHitAnimations(); } diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 4f8cb7660b..4c503ea59c 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -34,10 +34,14 @@ namespace osu.Game.Rulesets.Judgements /// /// Duration of initial fade in. - /// Default fade out will start immediately after this duration. /// protected virtual double FadeInDuration => 100; + /// + /// Duration to wait until fade out begins. Defaults to . + /// + protected virtual double FadeOutDelay => FadeInDuration; + /// /// Creates a drawable which visualises a . /// @@ -76,7 +80,7 @@ namespace osu.Game.Rulesets.Judgements JudgementBody.ScaleTo(0.9f); JudgementBody.ScaleTo(1, 500, Easing.OutElastic); - this.Delay(FadeInDuration).FadeOut(400); + this.Delay(FadeOutDelay).FadeOut(400); } protected override void LoadComplete() From 26eca5b1f425403df404da0ab4b4157e9f5fce52 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 02:56:03 +0900 Subject: [PATCH 2994/5608] Fix judgement sizes not matching skins stable --- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 2 +- osu.Game/Rulesets/Judgements/DrawableJudgement.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index df12ebc514..d1757de445 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Osu.UI { Origin = Anchor.Centre, Position = ((OsuHitObject)judgedObject.HitObject).StackedEndPosition, - Scale = new Vector2(((OsuHitObject)judgedObject.HitObject).Scale * 1.65f) + Scale = new Vector2(((OsuHitObject)judgedObject.HitObject).Scale) }; judgementLayer.Add(explosion); diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 4f8cb7660b..061c8cb3e1 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Judgements /// public class DrawableJudgement : CompositeDrawable { - private const float judgement_size = 80; + private const float judgement_size = 128; private OsuColour colours; @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Judgements Child = new SkinnableDrawable(new GameplaySkinComponent(Result.Type), _ => JudgementText = new OsuSpriteText { Text = Result.Type.GetDescription().ToUpperInvariant(), - Font = OsuFont.Numeric.With(size: 12), + Font = OsuFont.Numeric.With(size: 20), Colour = judgementColour(Result.Type), Scale = new Vector2(0.85f, 1), }) From adc2dfa6c6ffecf27ae299d0cecd1e2844d380f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 03:00:17 +0900 Subject: [PATCH 2995/5608] Fix HitCircleLongCombo test stacking off-screen --- osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs index 399cf22599..95c2810e94 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs @@ -29,7 +29,8 @@ namespace osu.Game.Rulesets.Osu.Tests }; for (int i = 0; i < 512; i++) - beatmap.HitObjects.Add(new HitCircle { Position = new Vector2(256, 192), StartTime = i * 100 }); + if (i % 32 < 20) + beatmap.HitObjects.Add(new HitCircle { Position = new Vector2(256, 192), StartTime = i * 100 }); return beatmap; } From 7e791f7cd78e2fed4e67f91a739e8a6411da891a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 13:14:33 +0900 Subject: [PATCH 2996/5608] Expose as IBindableList --- osu.Game/Overlays/MusicController.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 92246dfc62..db94b0278f 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -25,7 +25,9 @@ namespace osu.Game.Overlays [Resolved] private BeatmapManager beatmaps { get; set; } - public readonly BindableList BeatmapSets = new BindableList(); + public IBindableList BeatmapSets => beatmapSets; + + private readonly BindableList beatmapSets = new BindableList(); public bool IsUserPaused { get; private set; } @@ -47,7 +49,7 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load() { - BeatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next())); + beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next())); beatmaps.ItemAdded += handleBeatmapAdded; beatmaps.ItemRemoved += handleBeatmapRemoved; } @@ -66,8 +68,8 @@ namespace osu.Game.Overlays /// The new position. public void ChangeBeatmapSetPosition(BeatmapSetInfo beatmapSetInfo, int index) { - BeatmapSets.Remove(beatmapSetInfo); - BeatmapSets.Insert(index, beatmapSetInfo); + beatmapSets.Remove(beatmapSetInfo); + beatmapSets.Insert(index, beatmapSetInfo); } /// @@ -76,10 +78,10 @@ namespace osu.Game.Overlays public bool IsPlaying => beatmap.Value.Track.IsRunning; private void handleBeatmapAdded(BeatmapSetInfo set) => - Schedule(() => BeatmapSets.Add(set)); + Schedule(() => beatmapSets.Add(set)); private void handleBeatmapRemoved(BeatmapSetInfo set) => - Schedule(() => BeatmapSets.RemoveAll(s => s.ID == set.ID)); + Schedule(() => beatmapSets.RemoveAll(s => s.ID == set.ID)); private ScheduledDelegate seekDelegate; From 91bdece9af42fe2848d9fef7b56432cdaaee279c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 13:15:39 +0900 Subject: [PATCH 2997/5608] Localise OrderChanged handling and fix callbacks The dragged item's position now only updates after the drag finishes. Local handling changes were required to ignore the bindable remove/add events that are fired as a result. --- osu.Game/Overlays/Music/PlaylistList.cs | 42 +++++++++++++++++----- osu.Game/Overlays/Music/PlaylistOverlay.cs | 8 ----- osu.Game/Overlays/NowPlayingOverlay.cs | 1 - 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 6ad0aa23ec..636945edd2 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -19,7 +19,6 @@ namespace osu.Game.Overlays.Music public class PlaylistList : CompositeDrawable { public Action Selected; - public Action OrderChanged; private readonly ItemsScrollContainer items; @@ -29,7 +28,6 @@ namespace osu.Game.Overlays.Music { RelativeSizeAxes = Axes.Both, Selected = set => Selected?.Invoke(set), - OrderChanged = (s, i) => OrderChanged?.Invoke(s, i) }; } @@ -45,16 +43,17 @@ namespace osu.Game.Overlays.Music private class ItemsScrollContainer : OsuScrollContainer { - private BindableList beatmaps; + private IBindableList beatmaps; public Action Selected; - public Action OrderChanged; private readonly SearchContainer search; private readonly FillFlowContainer items; private readonly IBindable beatmapBacking = new Bindable(); + private MusicController musicController; + public ItemsScrollContainer() { Children = new Drawable[] @@ -78,6 +77,8 @@ namespace osu.Game.Overlays.Music [BackgroundDependencyLoader] private void load(MusicController musicController, IBindable beatmap) { + this.musicController = musicController; + beatmaps = musicController.BeatmapSets.GetBoundCopy(); beatmaps.ItemsAdded += i => i.ForEach(addBeatmapSet); @@ -88,10 +89,21 @@ namespace osu.Game.Overlays.Music beatmapBacking.ValueChanged += _ => updateSelectedSet(); } - private void addBeatmapSet(BeatmapSetInfo obj) => Schedule(() => { items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }); }); + private void addBeatmapSet(BeatmapSetInfo obj) => Schedule(() => + { + if (obj == draggedItem?.BeatmapSetInfo) + { + draggedItem = null; + return; + } + + items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }); + }); private void removeBeatmapSet(BeatmapSetInfo obj) => Schedule(() => { + if (obj == draggedItem?.BeatmapSetInfo) return; + var itemToRemove = items.FirstOrDefault(i => i.BeatmapSetInfo.ID == obj.ID); if (itemToRemove != null) items.Remove(itemToRemove); @@ -114,6 +126,8 @@ namespace osu.Game.Overlays.Music private Vector2 nativeDragPosition; private PlaylistItem draggedItem; + private int? dragDestination; + protected override bool OnDragStart(DragStartEvent e) { nativeDragPosition = e.ScreenSpaceMousePosition; @@ -133,10 +147,20 @@ namespace osu.Game.Overlays.Music protected override bool OnDragEnd(DragEndEvent e) { nativeDragPosition = e.ScreenSpaceMousePosition; - var handled = draggedItem != null || base.OnDragEnd(e); - draggedItem = null; - return handled; + if (draggedItem != null) + { + if (dragDestination != null) + { + // draggedItem is nulled when the BindableList's add event is received so we can quietly ignore the callbacks. + musicController.ChangeBeatmapSetPosition(draggedItem.BeatmapSetInfo, dragDestination.Value); + dragDestination = null; + } + + return true; + } + + return base.OnDragEnd(e); } protected override void Update() @@ -212,7 +236,7 @@ namespace osu.Game.Overlays.Music } items.SetLayoutPosition(draggedItem, dstIndex); - OrderChanged?.Invoke(draggedItem.BeatmapSetInfo, dstIndex); + dragDestination = dstIndex; } private class ItemSearchContainer : FillFlowContainer, IHasFilterableChildren diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index ec3d708645..ae81a6c117 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.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.Bindables; @@ -22,12 +21,6 @@ namespace osu.Game.Overlays.Music private const float transition_duration = 600; private const float playlist_height = 510; - /// - /// Invoked when the order of an item in the list has changed. - /// The second parameter indicates the new index of the item. - /// - public Action OrderChanged; - private readonly Bindable beatmap = new Bindable(); private BeatmapManager beatmaps; @@ -65,7 +58,6 @@ namespace osu.Game.Overlays.Music RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = 95, Bottom = 10, Right = 10 }, Selected = itemSelected, - OrderChanged = (s, i) => OrderChanged?.Invoke(s, i) }, filter = new FilterControl { diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index cf42c8005a..6b79f2af07 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -81,7 +81,6 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.X, Y = player_height + 10, - OrderChanged = musicController.ChangeBeatmapSetPosition }, playerContainer = new Container { From 2db1e236a7180174ffa78318e29d92c0e9b6842f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 14:08:09 +0900 Subject: [PATCH 2998/5608] Fix frame count dependent tests regressing --- .../TestSceneAutoGeneration.cs | 101 ++++++++++-------- 1 file changed, 54 insertions(+), 47 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs index f260357df5..8206e33c7c 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs @@ -16,6 +16,11 @@ namespace osu.Game.Rulesets.Mania.Tests [HeadlessTest] public class TestSceneAutoGeneration : OsuTestScene { + /// + /// The number of frames which are generated at the start of a replay regardless of hitobject content. + /// + private const int frame_offset = 2; + [Test] public void TestSingleNote() { @@ -28,11 +33,11 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 3, "Replay must have 3 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect hit time"); - Assert.AreEqual(1000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[2].Time, "Incorrect release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Special1), "Special1 has not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[2], ManiaAction.Special1), "Special1 has not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 2, "Replay must have 3 frames"); + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect hit time"); + Assert.AreEqual(1000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 1].Time, "Incorrect release time"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Special1), "Special1 has not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Special1), "Special1 has not been released"); } [Test] @@ -49,11 +54,11 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 3, "Replay must have 3 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect hit time"); - Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[2].Time, "Incorrect release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Special1), "Special1 has not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[2], ManiaAction.Special1), "Special1 has not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 2, "Replay must have 3 frames"); + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect hit time"); + Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 1].Time, "Incorrect release time"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Special1), "Special1 has not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Special1), "Special1 has not been released"); } [Test] @@ -69,11 +74,11 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 3, "Replay must have 3 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect hit time"); - Assert.AreEqual(1000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[2].Time, "Incorrect release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[2], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 2, "Replay must have 3 frames"); + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect hit time"); + Assert.AreEqual(1000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 1].Time, "Incorrect release time"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been released"); } [Test] @@ -91,11 +96,13 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 3, "Replay must have 3 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect hit time"); - Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[2].Time, "Incorrect release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[2], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 2, "Replay must have 3 frames"); + + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect hit time"); + Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 1].Time, "Incorrect release time"); + + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been released"); } [Test] @@ -112,15 +119,15 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 5, "Replay must have 5 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect first note hit time"); - Assert.AreEqual(1000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[2].Time, "Incorrect first note release time"); - Assert.AreEqual(2000, generated.Frames[3].Time, "Incorrect second note hit time"); - Assert.AreEqual(2000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[4].Time, "Incorrect second note release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Key1), "Key1 has not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[2], ManiaAction.Key1), "Key1 has not been released"); - Assert.IsTrue(checkContains(generated.Frames[3], ManiaAction.Key2), "Key2 has not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[4], ManiaAction.Key2), "Key2 has not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 4, "Replay must have 4 generated frames"); + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect first note hit time"); + Assert.AreEqual(1000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 1].Time, "Incorrect first note release time"); + Assert.AreEqual(2000, generated.Frames[frame_offset + 2].Time, "Incorrect second note hit time"); + Assert.AreEqual(2000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 3].Time, "Incorrect second note release time"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Key1), "Key1 has not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Key1), "Key1 has not been released"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset + 2], ManiaAction.Key2), "Key2 has not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 3], ManiaAction.Key2), "Key2 has not been released"); } [Test] @@ -139,16 +146,16 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 5, "Replay must have 5 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect first note hit time"); - Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[3].Time, "Incorrect first note release time"); - Assert.AreEqual(2000, generated.Frames[2].Time, "Incorrect second note hit time"); - Assert.AreEqual(4000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[4].Time, "Incorrect second note release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Key1), "Key1 has not been pressed"); - Assert.IsTrue(checkContains(generated.Frames[2], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[3], ManiaAction.Key1), "Key1 has not been released"); - Assert.IsTrue(checkContains(generated.Frames[3], ManiaAction.Key2), "Key2 has been released"); - Assert.IsFalse(checkContains(generated.Frames[4], ManiaAction.Key2), "Key2 has not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 4, "Replay must have 4 generated frames"); + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect first note hit time"); + Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 2].Time, "Incorrect first note release time"); + Assert.AreEqual(2000, generated.Frames[frame_offset + 1].Time, "Incorrect second note hit time"); + Assert.AreEqual(4000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 3].Time, "Incorrect second note release time"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Key1), "Key1 has not been pressed"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 2], ManiaAction.Key1), "Key1 has not been released"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset + 2], ManiaAction.Key2), "Key2 has been released"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 3], ManiaAction.Key2), "Key2 has not been released"); } [Test] @@ -166,14 +173,14 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 4, "Replay must have 4 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect first note hit time"); - Assert.AreEqual(3000, generated.Frames[2].Time, "Incorrect second note press time + first note release time"); - Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[3].Time, "Incorrect second note release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Key1), "Key1 has not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[2], ManiaAction.Key1), "Key1 has not been released"); - Assert.IsTrue(checkContains(generated.Frames[2], ManiaAction.Key2), "Key2 has not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[3], ManiaAction.Key2), "Key2 has not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 3, "Replay must have 3 generated frames"); + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect first note hit time"); + Assert.AreEqual(3000, generated.Frames[frame_offset + 1].Time, "Incorrect second note press time + first note release time"); + Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 2].Time, "Incorrect second note release time"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Key1), "Key1 has not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Key1), "Key1 has not been released"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Key2), "Key2 has not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 2], ManiaAction.Key2), "Key2 has not been released"); } private bool checkContains(ReplayFrame frame, params ManiaAction[] actions) => actions.All(action => ((ManiaReplayFrame)frame).Actions.Contains(action)); From 2046f64b22b31c753390da30bc71d33b59381c96 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 16:07:02 +0900 Subject: [PATCH 2999/5608] Revert clamping logic --- osu.Game/Tests/Visual/OsuTestScene.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 2bc9273f69..8e98d51962 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -20,6 +20,7 @@ using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Tests.Beatmaps; +using osuTK; namespace osu.Game.Tests.Visual { @@ -238,7 +239,7 @@ namespace osu.Game.Tests.Visual public override bool Seek(double seek) { - offset = Math.Min(seek, Length); + offset = MathHelper.Clamp(seek, 0, Length); lastReferenceTime = null; return offset == seek; From 381daffe527afef49687cbd1aed9ba026f718ef2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 16:07:29 +0900 Subject: [PATCH 3000/5608] Generate better temporary frames to support framed handling flaws --- osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs | 8 ++++---- osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs | 2 +- osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs | 8 ++++---- osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs | 3 ++- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 7f972a25ae..6c8515eb90 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -37,10 +37,6 @@ namespace osu.Game.Rulesets.Catch.Replays float lastPosition = 0.5f; double lastTime = 0; - // Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled - addFrame(-100000, lastPosition); - addFrame(0, lastPosition); - void moveToNext(CatchHitObject h) { float positionChange = Math.Abs(lastPosition - h.X); @@ -128,6 +124,10 @@ namespace osu.Game.Rulesets.Catch.Replays private void addFrame(double time, float? position = null, bool dashing = false) { + // todo: can be removed once FramedReplayInputHandler correctly handles rewinding before first frame. + if (Replay.Frames.Count == 0) + Replay.Frames.Add(new CatchReplayFrame(time - 1, position, false, null)); + var last = currentFrame; currentFrame = new CatchReplayFrame(time, position, dashing, last); Replay.Frames.Add(currentFrame); diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs index 8206e33c7c..a5248c7712 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.Tests /// /// The number of frames which are generated at the start of a replay regardless of hitobject content. /// - private const int frame_offset = 2; + private const int frame_offset = 1; [Test] public void TestSingleNote() diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 5d333e2047..2b336ca16d 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -47,10 +47,6 @@ namespace osu.Game.Rulesets.Mania.Replays public override Replay Generate() { - // Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled - Replay.Frames.Add(new ManiaReplayFrame(-100000, 0)); - Replay.Frames.Add(new ManiaReplayFrame(0, 0)); - var pointGroups = generateActionPoints().GroupBy(a => a.Time).OrderBy(g => g.First().Time); var actions = new List(); @@ -71,6 +67,10 @@ namespace osu.Game.Rulesets.Mania.Replays } } + // todo: can be removed once FramedReplayInputHandler correctly handles rewinding before first frame. + if (Replay.Frames.Count == 0) + Replay.Frames.Add(new ManiaReplayFrame(group.First().Time - 1)); + Replay.Frames.Add(new ManiaReplayFrame(group.First().Time, actions.ToArray())); } diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index 70ba5cd938..72c7eb60e0 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -21,7 +21,8 @@ namespace osu.Game.Rulesets.Mania.Replays public ManiaReplayFrame(double time, params ManiaAction[] actions) : base(time) { - Actions.AddRange(actions); + if (actions.Length > 0) + Actions.AddRange(actions); } public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) From e17cd9e964e5eaeded62b3b2a4584a813bec5470 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 16:14:31 +0900 Subject: [PATCH 3001/5608] Reduce length of tests --- osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index 883aa9fc36..f94071a7a9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void AddCheckSteps() { AddUntilStep("score above zero", () => ((ScoreAccessiblePlayer)Player).ScoreProcessor.TotalScore.Value > 0); - AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 5)); + AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2)); AddStep("rewind", () => track.Seek(-10000)); AddUntilStep("key counter reset", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); } From 61b396f235bedbd8306a26f84cbf5472df9f92d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 17:09:43 +0900 Subject: [PATCH 3002/5608] Remove redundant length check --- osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index 72c7eb60e0..70ba5cd938 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -21,8 +21,7 @@ namespace osu.Game.Rulesets.Mania.Replays public ManiaReplayFrame(double time, params ManiaAction[] actions) : base(time) { - if (actions.Length > 0) - Actions.AddRange(actions); + Actions.AddRange(actions); } public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) From cfdac956c2b28acd95829b6cac682d803e9fea67 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 20:04:49 +0900 Subject: [PATCH 3003/5608] Fix issues with colour and skin application --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 23 +++++++++++-------- .../Objects/Drawables/DrawableHitCircle.cs | 8 +++---- .../Objects/Drawables/DrawableSlider.cs | 4 ++-- .../Objects/Drawables/DrawableHitObject.cs | 15 +++++++++++- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 7c75bd608e..10a6334479 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -5,12 +5,12 @@ using System; using System.Linq; using osu.Framework.Bindables; using System.Collections.Generic; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods { @@ -22,7 +22,8 @@ namespace osu.Game.Rulesets.Osu.Mods public override ModType Type => ModType.Fun; public override string Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModeObjectScaleTween) }; + + public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModSpinIn) }; private Bindable increaseFirstObjectVisibility = new Bindable(); public void ReadFromConfig(OsuConfigManager config) @@ -38,26 +39,28 @@ namespace osu.Game.Rulesets.Osu.Mods protected void ApplyTraceableState(DrawableHitObject drawable, ArmedState state) { - if (!(drawable is DrawableOsuHitObject d)) + if (!(drawable is DrawableOsuHitObject drawableOsu)) return; - var h = d.HitObject; + var h = drawableOsu.HitObject; switch (drawable) { case DrawableHitCircle circle: // we only want to see the approach circle using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) - { - circle.ApproachCircle.Show(); - } + circle.CirclePiece.Hide(); break; case DrawableSlider slider: - ApplyTraceableState(slider.HeadCircle, state); - slider.Body.AccentColour = Color4.Transparent; - slider.Body.BorderColour = slider.HeadCircle.AccentColour.Value; + slider.AccentColour.BindValueChanged(_ => + { + //will trigger on skin change. + slider.Body.AccentColour = slider.AccentColour.Value.Opacity(0); + slider.Body.BorderColour = slider.AccentColour.Value; + }, true); + break; case DrawableSpinner spinner: diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 83646c561d..c90f230f93 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableHitCircle : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { - public ApproachCircle ApproachCircle; + public ApproachCircle ApproachCircle { get; } private readonly IBindable positionBindable = new Bindable(); private readonly IBindable stackHeightBindable = new Bindable(); @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly HitArea hitArea; - private readonly SkinnableDrawable mainContent; + public SkinnableDrawable CirclePiece { get; } public DrawableHitCircle(HitCircle h) : base(h) @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return true; }, }, - mainContent = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.HitCircle), _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)), + CirclePiece = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.HitCircle), _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)), ApproachCircle = new ApproachCircle { Alpha = 0, @@ -133,7 +133,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.UpdateInitialTransforms(); - mainContent.FadeInFromZero(HitObject.TimeFadeIn); + CirclePiece.FadeInFromZero(HitObject.TimeFadeIn); ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadeIn * 2, HitObject.TimePreempt)); ApproachCircle.ScaleTo(1f, HitObject.TimePreempt); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 08b43b0345..643a0f7336 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -163,9 +163,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private float sliderPathRadius; - protected override void SkinChanged(ISkinSource skin, bool allowFallback) + protected override void ApplySkin(ISkinSource skin, bool allowFallback) { - base.SkinChanged(skin, allowFallback); + base.ApplySkin(skin, allowFallback); Body.BorderSize = skin.GetConfig(OsuSkinConfiguration.SliderBorderSize)?.Value ?? SliderBody.DEFAULT_BORDER_SIZE; sliderPathRadius = skin.GetConfig(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 00b57f7249..9a7f1e8522 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -240,7 +240,7 @@ namespace osu.Game.Rulesets.Objects.Drawables #endregion - protected override void SkinChanged(ISkinSource skin, bool allowFallback) + protected sealed override void SkinChanged(ISkinSource skin, bool allowFallback) { base.SkinChanged(skin, allowFallback); @@ -250,6 +250,19 @@ namespace osu.Game.Rulesets.Objects.Drawables AccentColour.Value = comboColours?.Count > 0 ? comboColours[combo.ComboIndex % comboColours.Count] : Color4.White; } + + ApplySkin(skin, allowFallback); + + updateState(State.Value, true); + } + + /// + /// Called when a change is made to the skin. + /// + /// The new skin. + /// Whether fallback to default skin should be allowed if the custom skin is missing this resource. + protected virtual void ApplySkin(ISkinSource skin, bool allowFallback) + { } /// From aa1a6256431f0e6ac5a6cd793d3d57112e346faf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 20:07:44 +0900 Subject: [PATCH 3004/5608] Add back incompatibility marker --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 3 +-- osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 10a6334479..7e20feba02 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModSpinIn) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModSpinIn), typeof(OsuModeObjectScaleTween) }; private Bindable increaseFirstObjectVisibility = new Bindable(); public void ReadFromConfig(OsuConfigManager config) @@ -65,7 +65,6 @@ namespace osu.Game.Rulesets.Osu.Mods case DrawableSpinner spinner: spinner.Disc.Hide(); - //spinner.Ticks.Hide(); // do they contribute to the theme? debatable spinner.Background.Hide(); break; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs b/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs index e926ade41b..923278f484 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.Mods private Bindable increaseFirstObjectVisibility = new Bindable(); - public override Type[] IncompatibleMods => new[] { typeof(OsuModSpinIn) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModSpinIn), typeof(OsuModTraceable) }; public void ReadFromConfig(OsuConfigManager config) { From 5901a915e7850fb064cde851cbb5d5a4d8af193b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 20:19:57 +0900 Subject: [PATCH 3005/5608] Always update drawable hitobject state on skin change --- .../Objects/Drawables/DrawableSlider.cs | 4 ++-- .../Objects/Drawables/DrawableHitObject.cs | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 08b43b0345..643a0f7336 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -163,9 +163,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private float sliderPathRadius; - protected override void SkinChanged(ISkinSource skin, bool allowFallback) + protected override void ApplySkin(ISkinSource skin, bool allowFallback) { - base.SkinChanged(skin, allowFallback); + base.ApplySkin(skin, allowFallback); Body.BorderSize = skin.GetConfig(OsuSkinConfiguration.SliderBorderSize)?.Value ?? SliderBody.DEFAULT_BORDER_SIZE; sliderPathRadius = skin.GetConfig(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 00b57f7249..9a7f1e8522 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -240,7 +240,7 @@ namespace osu.Game.Rulesets.Objects.Drawables #endregion - protected override void SkinChanged(ISkinSource skin, bool allowFallback) + protected sealed override void SkinChanged(ISkinSource skin, bool allowFallback) { base.SkinChanged(skin, allowFallback); @@ -250,6 +250,19 @@ namespace osu.Game.Rulesets.Objects.Drawables AccentColour.Value = comboColours?.Count > 0 ? comboColours[combo.ComboIndex % comboColours.Count] : Color4.White; } + + ApplySkin(skin, allowFallback); + + updateState(State.Value, true); + } + + /// + /// Called when a change is made to the skin. + /// + /// The new skin. + /// Whether fallback to default skin should be allowed if the custom skin is missing this resource. + protected virtual void ApplySkin(ISkinSource skin, bool allowFallback) + { } /// From 646a64792a8a7be0f00b202b545cd4421d6ffce1 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2019 14:36:31 +0000 Subject: [PATCH 3006/5608] Bump ppy.osu.Framework.Android from 2019.911.0 to 2019.918.0 Bumps [ppy.osu.Framework.Android](https://github.com/ppy/osu-framework) from 2019.911.0 to 2019.918.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.911.0...2019.918.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index 4167d07698..85e8cb9ceb 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + From 1d7377df65c29f90712bb9a97630acd05b9bab3a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2019 14:51:01 +0000 Subject: [PATCH 3007/5608] Bump ppy.osu.Framework from 2019.911.0 to 2019.918.0 Bumps [ppy.osu.Framework](https://github.com/ppy/osu-framework) from 2019.911.0 to 2019.918.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.911.0...2019.918.0) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5703293caf..a733a0e7f9 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 683dccf3ae..f70853d70b 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,7 +118,7 @@ - + From 5dc5181c9014f8f75ab32b6b17d16de5092e3e2c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2019 15:27:39 +0000 Subject: [PATCH 3008/5608] Bump ppy.osu.Framework.iOS from 2019.911.0 to 2019.918.0 Bumps [ppy.osu.Framework.iOS](https://github.com/ppy/osu-framework) from 2019.911.0 to 2019.918.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.911.0...2019.918.0) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index f70853d70b..4bfa1ebcd0 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -119,7 +119,7 @@ - + From 1150e9fdfbc14254816c5f26b978d6104decf147 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 01:45:42 +0900 Subject: [PATCH 3009/5608] Bring other mods up-to-date --- osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs | 1 + osu.Game/Rulesets/Mods/ModAutoplay.cs | 2 ++ osu.Game/Rulesets/Mods/ModBlockFail.cs | 2 ++ 3 files changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs index ca72f18e9c..65d7acc911 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs @@ -25,6 +25,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) }; public bool AllowFail => false; + public bool RestartOnFail => false; private OsuInputManager inputManager; diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index f0dffa60ce..070a10b1c8 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -26,8 +26,10 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.Automation; public override string Description => "Watch a perfect automated play through the song."; public override double ScoreMultiplier => 1; + public bool AllowFail => false; public bool RestartOnFail => false; + public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) }; public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index 26efc3932d..55c074bde2 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -16,6 +16,8 @@ namespace osu.Game.Rulesets.Mods /// public bool AllowFail => false; + public virtual bool RestartOnFail => false; + public void ReadFromConfig(OsuConfigManager config) { showHealthBar = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail); From 2fcc8c2d720d60bbd6431e720628f056f41594a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 01:45:59 +0900 Subject: [PATCH 3010/5608] Simplify implementation, play fail animation during restart --- osu.Game/Screens/Play/Player.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index ca17e8a7bc..dac5561a45 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -360,7 +360,9 @@ namespace osu.Game.Screens.Play private bool onFail() { - if (Mods.Value.OfType().Any(m => !m.AllowFail)) + var failOverrideMods = Mods.Value.OfType(); + + if (failOverrideMods.Any(m => !m.AllowFail)) return false; HasFailed = true; @@ -371,13 +373,10 @@ namespace osu.Game.Screens.Play if (PauseOverlay.State.Value == Visibility.Visible) PauseOverlay.Hide(); - if (Beatmap.Value.Mods.Value.OfType().Any(m => m.RestartOnFail)) - { - Restart(); - return true; - } - failAnimation.Start(); + if (failOverrideMods.Any(m => m.RestartOnFail)) + Restart(); + return true; } From 2296ea75d7e64183b6b625810da21c3ef5b46458 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 02:03:30 +0900 Subject: [PATCH 3011/5608] Add reference to xmldoc Co-Authored-By: Salman Ahmed --- osu.Game/Rulesets/Mods/IApplicableFailOverride.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs b/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs index ae5903f085..120bfc9a23 100644 --- a/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs +++ b/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mods bool AllowFail { get; } /// - /// Whether we want to restart on fail. Only used if AllowFail is true. + /// Whether we want to restart on fail. Only used if is true. /// bool RestartOnFail { get; } } From 92556db9cd8bae5df028a295338d8ad1065e2a55 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 02:37:35 +0900 Subject: [PATCH 3012/5608] Add query-based filter modes to song select search field --- osu.Game/Beatmaps/BeatmapManager.cs | 1 + .../Select/Carousel/CarouselBeatmap.cs | 24 +++- osu.Game/Screens/Select/FilterControl.cs | 118 ++++++++++++++++-- osu.Game/Screens/Select/FilterCriteria.cs | 33 ++++- 4 files changed, 163 insertions(+), 13 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b9ed3664ef..02d7b2d98f 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -301,6 +301,7 @@ namespace osu.Game.Beatmaps var ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID); beatmap.BeatmapInfo.Ruleset = ruleset; + // TODO: this should be done in a better place once we actually need to dynamically update it. beatmap.BeatmapInfo.StarDifficulty = ruleset?.CreateInstance().CreateDifficultyCalculator(new DummyConversionBeatmap(beatmap)).Calculate().StarRating ?? 0; beatmap.BeatmapInfo.Length = calculateLength(beatmap); diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 712ab7b571..60e556a261 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -24,12 +24,26 @@ namespace osu.Game.Screens.Select.Carousel { base.Filter(criteria); - bool match = criteria.Ruleset == null || Beatmap.RulesetID == criteria.Ruleset.ID || (Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps); + bool match = + criteria.Ruleset == null || + Beatmap.RulesetID == criteria.Ruleset.ID || + (Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps); - 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 &= 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.BeatDivisor.HasValue || criteria.BeatDivisor == Beatmap.BeatDivisor; + match &= !criteria.OnlineStatus.HasValue || criteria.OnlineStatus == Beatmap.Status; + + if (match) + 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; Filtered.Value = !match; } diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index ed74b01fc9..01e7ed9383 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -16,6 +16,8 @@ using Container = osu.Framework.Graphics.Containers.Container; using osu.Framework.Graphics.Shapes; using osu.Game.Configuration; using osu.Game.Rulesets; +using System.Text.RegularExpressions; +using osu.Game.Beatmaps; namespace osu.Game.Screens.Select { @@ -33,14 +35,24 @@ namespace osu.Game.Screens.Select private Bindable groupMode; - public FilterCriteria CreateCriteria() => new FilterCriteria + public FilterCriteria CreateCriteria() { - Group = groupMode.Value, - Sort = sortMode.Value, - SearchText = searchTextBox.Text, - AllowConvertedBeatmaps = showConverted.Value, - Ruleset = ruleset.Value - }; + var query = searchTextBox.Text; + + var criteria = new FilterCriteria + { + Group = groupMode.Value, + Sort = sortMode.Value, + AllowConvertedBeatmaps = showConverted.Value, + Ruleset = ruleset.Value + }; + + applyQueries(criteria, ref query); + + criteria.SearchText = query; + + return criteria; + } public Action Exit; @@ -169,5 +181,97 @@ namespace osu.Game.Screens.Select } private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria()); + + private static readonly Regex query_syntax_regex = new Regex( + @"\b(?stars|ar|dr|cs|divisor|length|objects|bpm|status)(?[:><]+)(?\S*)", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + + private void applyQueries(FilterCriteria criteria, ref string query) + { + foreach (Match match in query_syntax_regex.Matches(query)) + { + var key = match.Groups["key"].Value.ToLower(); + var op = match.Groups["op"].Value; + var value = match.Groups["value"].Value; + + switch (key) + { + case "stars" when double.TryParse(value, out var stars): + updateCriteriaRange(ref criteria.StarDifficulty, op, stars, 0.5); + break; + + case "ar" when double.TryParse(value, out var ar): + updateCriteriaRange(ref criteria.ApproachRate, op, ar, 0.3); + break; + + case "dr" when double.TryParse(value, out var dr): + updateCriteriaRange(ref criteria.DrainRate, op, dr, 0.3); + break; + + case "cs" when double.TryParse(value, out var cs): + updateCriteriaRange(ref criteria.CircleSize, op, cs, 0.3); + break; + + case "bpm" when double.TryParse(value, out var bpm): + updateCriteriaRange(ref criteria.BPM, op, bpm, 0.3); + break; + + case "length" when double.TryParse(value.TrimEnd('m', 's', 'h'), out var length): + var scale = + value.EndsWith("ms") ? 1 : + value.EndsWith("s") ? 1000 : + value.EndsWith("m") ? 60000 : + value.EndsWith("h") ? 3600000 : 1000; + + updateCriteriaRange(ref criteria.Length, op, length * scale, scale / 2.0); + break; + + case "divisor" when op == ":" && int.TryParse(value, out var divisor): + criteria.BeatDivisor = divisor; + break; + + case "status" when op == ":" && Enum.TryParse(value, ignoreCase: true, out var statusValue): + criteria.OnlineStatus = statusValue; + break; + } + + query = query.Remove(match.Index, match.Length); + } + } + + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double equalityToleration = 0) + { + switch (op) + { + default: + return; + + case ":": + range.IsInclusive = true; + range.Min = value - equalityToleration; + range.Max = value + equalityToleration; + break; + + case ">": + range.IsInclusive = false; + range.Min = value; + break; + + case ">:": + range.IsInclusive = true; + range.Min = value; + break; + + case "<": + range.IsInclusive = false; + range.Max = value; + break; + + case "<:": + range.IsInclusive = true; + range.Max = value; + break; + } + } } } diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 140010ff54..84d63c16e0 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Screens.Select.Filter; @@ -13,6 +14,17 @@ namespace osu.Game.Screens.Select public GroupMode Group; public SortMode Sort; + public OptionalRange StarDifficulty; + public OptionalRange ApproachRate; + public OptionalRange DrainRate; + public OptionalRange CircleSize; + public OptionalRange Length; + public OptionalRange BPM; + + public int? BeatDivisor; + + public BeatmapSetOnlineStatus? OnlineStatus; + public string[] SearchTerms = Array.Empty(); public RulesetInfo Ruleset; @@ -26,8 +38,27 @@ namespace osu.Game.Screens.Select set { searchText = value; - SearchTerms = searchText.Split(',', ' ', '!').Where(s => !string.IsNullOrEmpty(s)).ToArray(); + SearchTerms = searchText.Split(new[] { ',', ' ', '!' }, StringSplitOptions.RemoveEmptyEntries).ToArray(); } } + + public struct OptionalRange : IEquatable + { + public bool IsInRange(double value) + { + if (Min.HasValue && (IsInclusive ? value < Min.Value : value <= Min.Value)) + return false; + if (Max.HasValue && (IsInclusive ? value > Max.Value : value >= Max.Value)) + return false; + + return true; + } + + public double? Min; + public double? Max; + public bool IsInclusive; + + public bool Equals(OptionalRange range) => Min == range.Min && Max == range.Max; + } } } From ecd721e8c5be287068bc1f51d2f85b4a44c225b3 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 18 Sep 2019 22:49:28 +0300 Subject: [PATCH 3013/5608] Add bypass fail property to Player --- osu.Game/Screens/Play/Player.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 309f4837e5..fbaab61b42 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -86,6 +86,11 @@ namespace osu.Game.Screens.Play [Cached(Type = typeof(IBindable>))] protected new readonly Bindable> Mods = new Bindable>(Array.Empty()); + /// + /// Whether to block the player from failing. + /// + protected virtual bool BypassFail => false; + private readonly bool allowPause; private readonly bool showResults; @@ -360,7 +365,7 @@ namespace osu.Game.Screens.Play private bool onFail() { - if (Mods.Value.OfType().Any(m => !m.AllowFail)) + if (Mods.Value.OfType().Any(m => !m.AllowFail) || BypassFail) return false; HasFailed = true; From 775b90e06643da66c6ebc72218e2163bbf15c8de Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 18 Sep 2019 22:49:48 +0300 Subject: [PATCH 3014/5608] Bypass fail on replays --- osu.Game/Screens/Play/ReplayPlayer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index a9c0ee3a15..da9f558c16 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -9,6 +9,9 @@ namespace osu.Game.Screens.Play { private readonly Score score; + // Block replays from failing. (see https://github.com/ppy/osu/issues/6108) + protected override bool BypassFail => true; + public ReplayPlayer(Score score, bool allowPause = true, bool showResults = true) : base(allowPause, showResults) { From 871adb16e0ba068e305ca79e342623bfff2b6e34 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 18 Sep 2019 22:51:03 +0300 Subject: [PATCH 3015/5608] Add asserts for fail bypassing --- osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs index 3fbce9d43c..d89304cf44 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs @@ -26,12 +26,14 @@ namespace osu.Game.Tests.Visual.Gameplay { AddUntilStep("score above zero", () => ((ScoreAccessibleReplayPlayer)Player).ScoreProcessor.TotalScore.Value > 0); AddUntilStep("key counter counted keys", () => ((ScoreAccessibleReplayPlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 0)); + AddAssert("cannot fail", () => ((ScoreAccessibleReplayPlayer)Player).BypassFail); } private class ScoreAccessibleReplayPlayer : ReplayPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new HUDOverlay HUDOverlay => base.HUDOverlay; + public new bool BypassFail => base.BypassFail; protected override bool PauseOnFocusLost => false; From ea6318ed73c22607c2aace18d7fa9cc7a659ebd1 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 18 Sep 2019 23:17:24 +0300 Subject: [PATCH 3016/5608] Fix failing test --- .../Visual/Gameplay/TestSceneFailJudgement.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index d57ec44f39..e6d302a5ca 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -17,9 +17,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Player CreatePlayer(Ruleset ruleset) { Mods.Value = Array.Empty(); - - var beatmap = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Array.Empty()); - return new FailPlayer(ruleset.GetAutoplayMod().CreateReplayScore(beatmap)); + return new FailPlayer(); } protected override void AddCheckSteps() @@ -29,16 +27,12 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("total judgements == 1", () => ((FailPlayer)Player).ScoreProcessor.JudgedHits == 1); } - private class FailPlayer : ReplayPlayer + private class FailPlayer : TestPlayer { - public new DrawableRuleset DrawableRuleset => base.DrawableRuleset; - public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; - protected override bool PauseOnFocusLost => false; - - public FailPlayer(Score score) - : base(score, false, false) + public FailPlayer() + : base(false, false) { } From 3efcf0493c45c95b5a648bbcce99ab4af831ac7d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 18 Sep 2019 23:28:48 +0300 Subject: [PATCH 3017/5608] Remove redundant using directive --- osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index e6d302a5ca..cca6301b02 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -6,8 +6,6 @@ using System.Linq; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; -using osu.Game.Scoring; using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay From c3221e1a3623d3c0cc5134aef738fbed3acbd24a Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Wed, 18 Sep 2019 23:27:26 +0200 Subject: [PATCH 3018/5608] Prepare classes for player loader test scene --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 90 +++++++++++++++++-- osu.Game/Screens/Play/PlayerLoader.cs | 16 +++- 2 files changed, 96 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index ab519360ac..dc099b14b9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -3,14 +3,20 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; using osu.Framework.Screens; +using osu.Game.Graphics.Containers; +using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; @@ -24,19 +30,35 @@ namespace osu.Game.Tests.Visual.Gameplay public class TestScenePlayerLoader : ManualInputManagerTestScene { private TestPlayerLoader loader; - private OsuScreenStack stack; + private TestPlayerLoaderContainer container; + private TestPlayer player; + + [Resolved] + private AudioManager audioManager { get; set; } [SetUp] public void Setup() => Schedule(() => { - InputManager.Child = stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }; + ResetPlayer(false); Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); }); + /// + /// Sets the input manager child to a new test player loader container instance. + /// + /// If the test player should behave like the production one. + public void ResetPlayer(bool interactive) + { + player = new TestPlayer(interactive, interactive); + loader = new TestPlayerLoader(() => player); + container = new TestPlayerLoaderContainer(loader); + InputManager.Child = container; + } + [Test] public void TestBlockLoadViaMouseMovement() { - AddStep("load dummy beatmap", () => stack.Push(loader = new TestPlayerLoader(() => new TestPlayer(false, false)))); + AddStep("load dummy beatmap", () => ResetPlayer(false)); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddRepeatStep("move mouse", () => InputManager.MoveMouseTo(loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft + (loader.VisualSettings.ScreenSpaceDrawQuad.BottomRight - loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft) * RNG.NextSingle()), 20); AddAssert("loader still active", () => loader.IsCurrentScreen()); @@ -49,13 +71,13 @@ namespace osu.Game.Tests.Visual.Gameplay Player player = null; SlowLoadPlayer slowPlayer = null; - AddStep("load dummy beatmap", () => stack.Push(loader = new TestPlayerLoader(() => player = new TestPlayer(false, false)))); + AddStep("load dummy beatmap", () => ResetPlayer(false)); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); AddUntilStep("wait for player to be current", () => player.IsCurrentScreen()); AddStep("load slow dummy beatmap", () => { - stack.Push(loader = new TestPlayerLoader(() => slowPlayer = new SlowLoadPlayer(false, false))); + InputManager.Children = container = new TestPlayerLoaderContainer(loader = new TestPlayerLoader(() => slowPlayer = new SlowLoadPlayer(false, false))); Scheduler.AddDelayed(() => slowPlayer.AllowLoad.Set(), 5000); }); @@ -65,7 +87,6 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestModReinstantiation() { - TestPlayer player = null; TestMod gameMod = null; TestMod playerMod1 = null; TestMod playerMod2 = null; @@ -73,7 +94,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("load player", () => { Mods.Value = new[] { gameMod = new TestMod() }; - stack.Push(loader = new TestPlayerLoader(() => player = new TestPlayer())); + ResetPlayer(true); }); AddUntilStep("wait for loader to become current", () => loader.IsCurrentScreen()); @@ -97,6 +118,61 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("player mods applied", () => playerMod2.Applied); } + [Test] + public void TestMutedNotification() + { + AddStep("set master volume to 0%", () => audioManager.Volume.Value = 0); + AddStep("reset notification lock", () => PlayerLoader.ResetNotificationLock()); + //AddStep("reset notification overlay", () => notificationOverlay); + AddStep("load player", () => ResetPlayer(false)); + AddUntilStep("wait for player", () => player.IsLoaded); + + AddAssert("check for notification", () => container.NotificationOverlay.UnreadCount.Value == 1); + AddAssert("click notification", () => + { + var scrollContainer = container.NotificationOverlay.Children.Last() as OsuScrollContainer; + var flowContainer = scrollContainer.Children.First() as FillFlowContainer; + return flowContainer.Children.First().First().Click(); + }); + AddAssert("check master volume", () => audioManager.Volume.IsDefault); + + AddStep("restart player", () => + { + var lastPlayer = player; + player = null; + lastPlayer.Restart(); + }); + } + + private class TestPlayerLoaderContainer : Container + { + private TestPlayerLoader loader; + + [Cached] + public NotificationOverlay NotificationOverlay { get; } = new NotificationOverlay + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }; + + [Cached] + public VolumeOverlay VolumeOverlay { get; } = new VolumeOverlay + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }; + + public TestPlayerLoaderContainer(TestPlayerLoader testPlayerLoader) + { + Children = new Drawable[] + { + loader = testPlayerLoader, + NotificationOverlay, + VolumeOverlay + }; + } + } + private class TestPlayerLoader : PlayerLoader { public new VisualSettings VisualSettings => base.VisualSettings; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index dbb6c47943..8f2435d2f7 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -65,6 +65,9 @@ namespace osu.Game.Screens.Play [Resolved] private VolumeOverlay volumeOverlay { get; set; } + [Resolved] + private AudioManager audioManager { get; set; } + private static bool muteWarningShownOnce; public PlayerLoader(Func createPlayer) @@ -79,7 +82,7 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load(AudioManager audioManager, NotificationOverlay notificationOverlay) + private void load() { InternalChild = (content = new LogoTrackingContainer { @@ -112,8 +115,6 @@ namespace osu.Game.Screens.Play }); loadNewPlayer(); - - checkVolume(audioManager); } private void playerLoaded(Player player) => info.Loading = false; @@ -212,6 +213,7 @@ namespace osu.Game.Screens.Play { inputManager = GetContainingInputManager(); base.LoadComplete(); + checkVolume(audioManager); } private ScheduledDelegate pushDebounce; @@ -526,5 +528,13 @@ namespace osu.Game.Screens.Play }; } } + + /// + /// Sets to , reserved for testing. + /// + public static void ResetNotificationLock() + { + muteWarningShownOnce = false; + } } } From 44412f9ddb0407318c7b9603484f806ef717266e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 19 Sep 2019 03:35:56 +0300 Subject: [PATCH 3019/5608] Fix local sorting calls an online request --- osu.Game/Overlays/SocialOverlay.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 1912a2c3e0..7fd9ef153e 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -70,7 +70,7 @@ namespace osu.Game.Overlays Header.Tabs.Current.ValueChanged += _ => queueUpdate(); - Filter.Tabs.Current.ValueChanged += _ => queueUpdate(); + Filter.Tabs.Current.ValueChanged += _ => onFilterUpdate(); Filter.DisplayStyleControl.DisplayStyle.ValueChanged += style => recreatePanels(style.NewValue); Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => updateUsers(Users); @@ -180,6 +180,17 @@ namespace osu.Game.Overlays }, loadCancellation.Token); } + private void onFilterUpdate() + { + if (Users == null || Filter.Tabs.Current.Value == SocialSortCriteria.Rank) + { + queueUpdate(); + return; + } + + updateUsers(Users); + } + private void updateUsers(IEnumerable newUsers) { var sortDirection = Filter.DisplayStyleControl.Dropdown.Current.Value; From 647433a8d1c21187d86f656571d0abe8b5a0423f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 19 Sep 2019 04:09:14 +0300 Subject: [PATCH 3020/5608] Don't trigger request if there are no avaliable users --- osu.Game/Overlays/SocialOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 7fd9ef153e..a77172c90c 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -182,7 +182,7 @@ namespace osu.Game.Overlays private void onFilterUpdate() { - if (Users == null || Filter.Tabs.Current.Value == SocialSortCriteria.Rank) + if (Filter.Tabs.Current.Value == SocialSortCriteria.Rank) { queueUpdate(); return; From 3fa1b53b2ae3d670bc7f1f2a6f8b55cb57659b93 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 12:39:15 +0900 Subject: [PATCH 3021/5608] Add back combo colours for osu!classic --- osu.Game/Skinning/DefaultLegacySkin.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index 98f158c725..4b6eea6b6e 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -13,6 +13,13 @@ namespace osu.Game.Skinning : base(Info, storage, audioManager, string.Empty) { Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); + Configuration.ComboColours.AddRange(new[] + { + new Color4(255, 192, 0, 255), + new Color4(0, 202, 0, 255), + new Color4(18, 124, 255, 255), + new Color4(242, 24, 57, 255), + }); } public static SkinInfo Info { get; } = new SkinInfo From e5509cd3908175a866809317576b0d896b53afe8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 13:19:48 +0900 Subject: [PATCH 3022/5608] Rename test --- ...stSceneLeaderboard.cs => TestSceneBeatmapLeaderboard.cs} | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) rename osu.Game.Tests/Visual/SongSelect/{TestSceneLeaderboard.cs => TestSceneBeatmapLeaderboard.cs} (98%) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs similarity index 98% rename from osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs rename to osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 186f27a8b2..cb4cd63266 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.Leaderboards; @@ -14,8 +13,7 @@ using osuTK; namespace osu.Game.Tests.Visual.SongSelect { - [Description("PlaySongSelect leaderboard")] - public class TestSceneLeaderboard : OsuTestScene + public class TestSceneBeatmapLeaderboard : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -26,7 +24,7 @@ namespace osu.Game.Tests.Visual.SongSelect private readonly FailableLeaderboard leaderboard; - public TestSceneLeaderboard() + public TestSceneBeatmapLeaderboard() { Add(leaderboard = new FailableLeaderboard { From 0644443979bde65a602504c34eeecbbfcff332f9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 13:51:50 +0900 Subject: [PATCH 3023/5608] Use resolved attribute for music controller --- osu.Game/Overlays/Music/PlaylistList.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 636945edd2..cd9c91f3af 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -43,8 +43,6 @@ namespace osu.Game.Overlays.Music private class ItemsScrollContainer : OsuScrollContainer { - private IBindableList beatmaps; - public Action Selected; private readonly SearchContainer search; @@ -52,7 +50,10 @@ namespace osu.Game.Overlays.Music private readonly IBindable beatmapBacking = new Bindable(); - private MusicController musicController; + private IBindableList beatmaps; + + [Resolved] + private MusicController musicController { get; set; } public ItemsScrollContainer() { @@ -75,12 +76,9 @@ namespace osu.Game.Overlays.Music } [BackgroundDependencyLoader] - private void load(MusicController musicController, IBindable beatmap) + private void load(IBindable beatmap) { - this.musicController = musicController; - beatmaps = musicController.BeatmapSets.GetBoundCopy(); - beatmaps.ItemsAdded += i => i.ForEach(addBeatmapSet); beatmaps.ItemsRemoved += i => i.ForEach(removeBeatmapSet); beatmaps.ForEach(addBeatmapSet); From 4b97327b37ad910b93bb3a835a19201369dc6730 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 13:53:52 +0900 Subject: [PATCH 3024/5608] Cleanup draggedItem usages and make them more safe --- osu.Game/Overlays/Music/PlaylistList.cs | 50 ++++++++++++------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index cd9c91f3af..5b528c5ab2 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -87,25 +87,24 @@ namespace osu.Game.Overlays.Music beatmapBacking.ValueChanged += _ => updateSelectedSet(); } - private void addBeatmapSet(BeatmapSetInfo obj) => Schedule(() => - { - if (obj == draggedItem?.BeatmapSetInfo) - { - draggedItem = null; - return; - } - - items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }); - }); - - private void removeBeatmapSet(BeatmapSetInfo obj) => Schedule(() => + private void addBeatmapSet(BeatmapSetInfo obj) { if (obj == draggedItem?.BeatmapSetInfo) return; - var itemToRemove = items.FirstOrDefault(i => i.BeatmapSetInfo.ID == obj.ID); - if (itemToRemove != null) - items.Remove(itemToRemove); - }); + Schedule(() => items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) })); + } + + private void removeBeatmapSet(BeatmapSetInfo obj) + { + if (obj == draggedItem?.BeatmapSetInfo) return; + + Schedule(() => + { + var itemToRemove = items.FirstOrDefault(i => i.BeatmapSetInfo.ID == obj.ID); + if (itemToRemove != null) + items.Remove(itemToRemove); + }); + } private void updateSelectedSet() { @@ -146,19 +145,16 @@ namespace osu.Game.Overlays.Music { nativeDragPosition = e.ScreenSpaceMousePosition; - if (draggedItem != null) - { - if (dragDestination != null) - { - // draggedItem is nulled when the BindableList's add event is received so we can quietly ignore the callbacks. - musicController.ChangeBeatmapSetPosition(draggedItem.BeatmapSetInfo, dragDestination.Value); - dragDestination = null; - } + if (draggedItem == null) + return base.OnDragEnd(e); - return true; - } + if (dragDestination != null) + musicController.ChangeBeatmapSetPosition(draggedItem.BeatmapSetInfo, dragDestination.Value); - return base.OnDragEnd(e); + draggedItem = null; + dragDestination = null; + + return true; } protected override void Update() From 9de0bcae1eef5ff0beaa2fb70f26d66a62cb725e Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 19 Sep 2019 07:58:54 +0300 Subject: [PATCH 3025/5608] Check for blocking fail mods by default --- osu.Game/Screens/Play/Player.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fbaab61b42..e8134253f5 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -87,9 +87,11 @@ namespace osu.Game.Screens.Play protected new readonly Bindable> Mods = new Bindable>(Array.Empty()); /// - /// Whether to block the player from failing. + /// Whether failing should be allowed. + /// + /// By default, this checks whether any selected mod disallows failing. /// - protected virtual bool BypassFail => false; + protected virtual bool AllowFail => !Mods.Value.OfType().Any(m => !m.AllowFail); private readonly bool allowPause; private readonly bool showResults; @@ -365,7 +367,7 @@ namespace osu.Game.Screens.Play private bool onFail() { - if (Mods.Value.OfType().Any(m => !m.AllowFail) || BypassFail) + if (!AllowFail) return false; HasFailed = true; From e793854735a812acb0d4e01ddbff87c5d20922d3 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 19 Sep 2019 08:00:41 +0300 Subject: [PATCH 3026/5608] Invert BypassFail usage --- osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs | 4 ++-- osu.Game/Screens/Play/ReplayPlayer.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs index d89304cf44..36335bc54a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs @@ -26,14 +26,14 @@ namespace osu.Game.Tests.Visual.Gameplay { AddUntilStep("score above zero", () => ((ScoreAccessibleReplayPlayer)Player).ScoreProcessor.TotalScore.Value > 0); AddUntilStep("key counter counted keys", () => ((ScoreAccessibleReplayPlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 0)); - AddAssert("cannot fail", () => ((ScoreAccessibleReplayPlayer)Player).BypassFail); + AddAssert("cannot fail", () => !((ScoreAccessibleReplayPlayer)Player).AllowFail); } private class ScoreAccessibleReplayPlayer : ReplayPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new HUDOverlay HUDOverlay => base.HUDOverlay; - public new bool BypassFail => base.BypassFail; + public new bool AllowFail => base.AllowFail; protected override bool PauseOnFocusLost => false; diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index da9f558c16..b040549efc 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -9,8 +9,8 @@ namespace osu.Game.Screens.Play { private readonly Score score; - // Block replays from failing. (see https://github.com/ppy/osu/issues/6108) - protected override bool BypassFail => true; + // Disallow replays from failing. (see https://github.com/ppy/osu/issues/6108) + protected override bool AllowFail => false; public ReplayPlayer(Score score, bool allowPause = true, bool showResults = true) : base(allowPause, showResults) From 177a789d792b55d69a232c56d82a2813ea6f0159 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 14:04:51 +0900 Subject: [PATCH 3027/5608] Add setting to adjust hold-to-confirm activation time --- osu.Game/Configuration/OsuConfigManager.cs | 5 ++++- .../Containers/HoldToConfirmContainer.cs | 18 ++++++++---------- osu.Game/Overlays/HoldToConfirmOverlay.cs | 2 +- .../Sections/Graphics/UserInterfaceSettings.cs | 15 ++++++++++++++- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index e26021d930..62590a0a8f 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -112,6 +112,8 @@ namespace osu.Game.Configuration Set(OsuSetting.UIScale, 1f, 0.8f, 1.6f, 0.01f); + Set(OsuSetting.UIHoldActivationDelay, 200, 0, 500); + Set(OsuSetting.IntroSequence, IntroSequence.Triangles); } @@ -180,6 +182,7 @@ namespace osu.Game.Configuration ScalingSizeX, ScalingSizeY, UIScale, - IntroSequence + IntroSequence, + UIHoldActivationDelay } } diff --git a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs index 773265d19b..a345fb554f 100644 --- a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs +++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs @@ -2,9 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Configuration; namespace osu.Game.Graphics.Containers { @@ -12,11 +14,8 @@ namespace osu.Game.Graphics.Containers { public Action Action; - private const int default_activation_delay = 200; private const int fadeout_delay = 200; - private readonly double activationDelay; - private bool fired; private bool confirming; @@ -27,13 +26,12 @@ namespace osu.Game.Graphics.Containers public Bindable Progress = new BindableDouble(); - /// - /// Create a new instance. - /// - /// The time requried before an action is confirmed. - protected HoldToConfirmContainer(double activationDelay = default_activation_delay) + private Bindable holdActivationDelay; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) { - this.activationDelay = activationDelay; + holdActivationDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); } protected void BeginConfirm() @@ -42,7 +40,7 @@ namespace osu.Game.Graphics.Containers confirming = true; - this.TransformBindableTo(Progress, 1, activationDelay * (1 - Progress.Value), Easing.Out).OnComplete(_ => Confirm()); + this.TransformBindableTo(Progress, 1, holdActivationDelay.Value * (1 - Progress.Value), Easing.Out).OnComplete(_ => Confirm()); } protected virtual void Confirm() diff --git a/osu.Game/Overlays/HoldToConfirmOverlay.cs b/osu.Game/Overlays/HoldToConfirmOverlay.cs index fdc6f096bc..eb325d8dd3 100644 --- a/osu.Game/Overlays/HoldToConfirmOverlay.cs +++ b/osu.Game/Overlays/HoldToConfirmOverlay.cs @@ -51,7 +51,7 @@ namespace osu.Game.Overlays protected override void Dispose(bool isDisposing) { - audio.Tracks.RemoveAdjustment(AdjustableProperty.Volume, audioVolume); + audio?.Tracks.RemoveAdjustment(AdjustableProperty.Volume, audioVolume); base.Dispose(isDisposing); } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs index dd822fedb6..a6956b7d9a 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs @@ -2,7 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings.Sections.Graphics { @@ -13,7 +15,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - Children = new[] + Children = new Drawable[] { new SettingsCheckbox { @@ -25,7 +27,18 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics LabelText = "Parallax", Bindable = config.GetBindable(OsuSetting.MenuParallax) }, + new SettingsSlider + { + LabelText = "Hold-to-confirm activation time", + Bindable = config.GetBindable(OsuSetting.UIHoldActivationDelay), + KeyboardStep = 50 + }, }; } + + private class TimeSlider : OsuSliderBar + { + public override string TooltipText => Current.Value.ToString("N0") + "ms"; + } } } From 762adb783ae359a5d3f1d5bebeabd1ec3ef79be8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 14:15:06 +0900 Subject: [PATCH 3028/5608] Fix duplicate invocation of updateState on load complete --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 9a7f1e8522..b94de0df89 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -253,7 +253,8 @@ namespace osu.Game.Rulesets.Objects.Drawables ApplySkin(skin, allowFallback); - updateState(State.Value, true); + if (IsLoaded) + updateState(State.Value, true); } /// From a7b6895d4c9c79119922792b6d688faa48ee2166 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 14:26:15 +0900 Subject: [PATCH 3029/5608] Revert changes to BeatmapDetailArea --- .../SongSelect/TestSceneBeatmapDetailArea.cs | 1 - osu.Game/Screens/Select/BeatmapDetailArea.cs | 77 ++++++++----------- osu.Game/Screens/Select/SongSelect.cs | 1 - 3 files changed, 30 insertions(+), 49 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index ee47888d99..ed9e01a67e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -163,7 +163,6 @@ namespace osu.Game.Tests.Visual.SongSelect })); AddStep("null beatmap", () => detailsArea.Beatmap = null); - AddStep("Toggle top score visibility", () => detailsArea.TopScore.ToggleVisibility()); } } } diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index 648dae68bc..5348de68d6 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -1,21 +1,23 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; -using osu.Game.Screens.Select.Details; using osu.Game.Screens.Select.Leaderboards; namespace osu.Game.Screens.Select { public class BeatmapDetailArea : Container { - private const float padding = 10; + private const float details_padding = 10; + + private readonly Container content; + protected override Container Content => content; public readonly BeatmapDetails Details; public readonly BeatmapLeaderboard Leaderboard; - public readonly UserTopScoreContainer TopScore; private WorkingBeatmap beatmap; @@ -27,13 +29,12 @@ namespace osu.Game.Screens.Select beatmap = value; Details.Beatmap = beatmap?.BeatmapInfo; Leaderboard.Beatmap = beatmap is DummyWorkingBeatmap ? null : beatmap?.BeatmapInfo; - TopScore.Hide(); } } public BeatmapDetailArea() { - Children = new Drawable[] + AddRangeInternal(new Drawable[] { new BeatmapDetailAreaTabControl { @@ -57,51 +58,33 @@ namespace osu.Game.Screens.Select } }, }, - new Container + content = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT }, + }, + }); + + AddRange(new Drawable[] + { + Details = new BeatmapDetails + { + RelativeSizeAxes = Axes.X, + Alpha = 0, + Margin = new MarginPadding { Top = details_padding }, + }, + Leaderboard = new BeatmapLeaderboard { - Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT, Bottom = padding }, RelativeSizeAxes = Axes.Both, - Child = new GridContainer - { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.Distributed), - new Dimension(GridSizeMode.AutoSize), - }, - Content = new[] - { - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - Details = new BeatmapDetails - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - Padding = new MarginPadding { Top = padding }, - }, - Leaderboard = new BeatmapLeaderboard - { - RelativeSizeAxes = Axes.Both, - } - } - } - }, - new Drawable[] - { - TopScore = new UserTopScoreContainer - { - Score = { BindTarget = Leaderboard.TopScore } - } - } - }, - }, } - }; + }); + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + Details.Height = Math.Min(DrawHeight - details_padding * 3 - BeatmapDetailAreaTabControl.HEIGHT, 450); } } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 173442384e..7f9804c6a3 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -226,7 +226,6 @@ namespace osu.Game.Screens.Select void displayScore(ScoreInfo score) => this.Push(new SoloResults(score)); BeatmapDetails.Leaderboard.ScoreSelected += displayScore; - BeatmapDetails.TopScore.ScoreSelected += displayScore; } [BackgroundDependencyLoader(true)] From da4d83063e73c4cda5a705fa0500f4153388a029 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 19 Sep 2019 08:31:11 +0300 Subject: [PATCH 3030/5608] Simplify LINQ expression --- osu.Game/Screens/Play/Player.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index e8134253f5..30d6cfbf68 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -89,9 +89,9 @@ namespace osu.Game.Screens.Play /// /// Whether failing should be allowed. /// - /// By default, this checks whether any selected mod disallows failing. + /// By default, this checks whether all selected mods allow failing. /// - protected virtual bool AllowFail => !Mods.Value.OfType().Any(m => !m.AllowFail); + protected virtual bool AllowFail => Mods.Value.OfType().All(m => m.AllowFail); private readonly bool allowPause; private readonly bool showResults; From 4967ffd8e557291a261a6b678026a91a2901965f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 14:52:31 +0900 Subject: [PATCH 3031/5608] Move inside leaderboard --- osu.Game/Online/Leaderboards/Leaderboard.cs | 39 ++++++++++++++++--- .../Select/Leaderboards/BeatmapLeaderboard.cs | 12 ++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 147556b78b..d66a9a7535 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -35,6 +35,10 @@ namespace osu.Game.Online.Leaderboards private bool scoresLoadedOnce; + private readonly Container content; + + protected override Container Content => content; + private IEnumerable scores; public IEnumerable Scores @@ -60,13 +64,13 @@ namespace osu.Game.Online.Leaderboards // ensure placeholder is hidden when displaying scores PlaceholderState = PlaceholderState.Successful; - var sf = CreateScoreFlow(); - sf.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)); + var scoreFlow = CreateScoreFlow(); + scoreFlow.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)); // schedule because we may not be loaded yet (LoadComponentAsync complains). - showScoresDelegate = Schedule(() => LoadComponentAsync(sf, _ => + showScoresDelegate = Schedule(() => LoadComponentAsync(scoreFlow, _ => { - scrollContainer.Add(scrollFlow = sf); + scrollContainer.Add(scrollFlow = scoreFlow); int i = 0; @@ -164,10 +168,33 @@ namespace osu.Game.Online.Leaderboards { Children = new Drawable[] { - scrollContainer = new OsuScrollContainer + new GridContainer { RelativeSizeAxes = Axes.Both, - ScrollbarVisible = false, + RowDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new Drawable[] + { + scrollContainer = new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + ScrollbarVisible = false, + } + }, + new Drawable[] + { + content = new Container + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + }, + } + }, }, loading = new LoadingAnimation(), placeholderContainer = new Container diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 4e4def4911..0eef784279 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -80,6 +80,18 @@ namespace osu.Game.Screens.Select.Leaderboards if (filterMods) UpdateScores(); }; + + TopScore.BindValueChanged(newTopScore); + } + + private void newTopScore(ValueChangedEvent score) + { + Content.Clear(); + + if (score.NewValue != null) + { + + } } protected override bool IsOnlineScope => Scope != BeatmapLeaderboardScope.Local; From c76e27549a6db11e251376d5d15c2a3d710545b9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 14:56:52 +0900 Subject: [PATCH 3032/5608] Remove spacing --- osu.Game/Screens/Play/Player.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 30d6cfbf68..4b234ab296 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -88,7 +88,6 @@ namespace osu.Game.Screens.Play /// /// Whether failing should be allowed. - /// /// By default, this checks whether all selected mods allow failing. /// protected virtual bool AllowFail => Mods.Value.OfType().All(m => m.AllowFail); From 098e89cb66a2896d673c0cb924eecfc92147ff56 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:23:33 +0900 Subject: [PATCH 3033/5608] Improve state reset flow --- osu.Game/Online/Leaderboards/Leaderboard.cs | 13 ++++--- .../Select/Details/UserTopScoreContainer.cs | 22 ++++++------ .../Select/Leaderboards/BeatmapLeaderboard.cs | 36 ++++++++++++------- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index d66a9a7535..83de0635fb 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -120,9 +120,7 @@ namespace osu.Game.Online.Leaderboards { if (value != PlaceholderState.Successful) { - getScoresRequest?.Cancel(); - getScoresRequest = null; - Scores = null; + Reset(); } if (value == placeholderState) @@ -166,7 +164,7 @@ namespace osu.Game.Online.Leaderboards protected Leaderboard() { - Children = new Drawable[] + InternalChildren = new Drawable[] { new GridContainer { @@ -204,6 +202,13 @@ namespace osu.Game.Online.Leaderboards }; } + protected virtual void Reset() + { + getScoresRequest?.Cancel(); + getScoresRequest = null; + Scores = null; + } + private IAPIProvider api; private ScheduledDelegate pendingUpdateScores; diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index c10f4d4fd4..959fbb927a 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -17,9 +17,8 @@ namespace osu.Game.Screens.Select.Details public class UserTopScoreContainer : VisibilityContainer { private const int height = 90; - private const int duration = 800; + private const int duration = 500; - private readonly Container contentContainer; private readonly Container scoreContainer; public Bindable Score = new Bindable(); @@ -38,7 +37,7 @@ namespace osu.Game.Screens.Select.Details Children = new Drawable[] { - contentContainer = new Container + new Container { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -74,15 +73,12 @@ namespace osu.Game.Screens.Select.Details { var newScore = score.NewValue; - if (newScore == null) - { - Hide(); - return; - } - scoreContainer.Clear(); loadScoreCancellation?.Cancel(); + if (newScore == null) + return; + LoadComponentAsync(new LeaderboardScore(newScore.Score, newScore.Position) { Action = () => ScoreSelected?.Invoke(newScore.Score) @@ -93,12 +89,14 @@ namespace osu.Game.Screens.Select.Details }, (loadScoreCancellation = new CancellationTokenSource()).Token); } - protected override void PopIn() => this.ResizeHeightTo(height, duration / 4f, Easing.OutQuint).OnComplete(_ => contentContainer.FadeIn(duration, Easing.OutQuint)); + protected override void PopIn() + { + this.FadeIn(duration, Easing.OutQuint); + } protected override void PopOut() { - this.ResizeHeightTo(0); - contentContainer.FadeOut(duration / 4f, Easing.OutQuint); + this.FadeOut(duration, Easing.OutQuint); } } } diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 0eef784279..d038049504 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -14,13 +14,12 @@ using osu.Game.Online.Leaderboards; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; +using osu.Game.Screens.Select.Details; namespace osu.Game.Screens.Select.Leaderboards { public class BeatmapLeaderboard : Leaderboard { - public Bindable TopScore = new Bindable(); - public Action ScoreSelected; private BeatmapInfo beatmap; @@ -40,8 +39,25 @@ namespace osu.Game.Screens.Select.Leaderboards } } + public APILegacyUserTopScoreInfo TopScore + { + get => topScoreContainer.Score.Value; + set + { + if (value == null) + topScoreContainer.Hide(); + else + { + topScoreContainer.Show(); + topScoreContainer.Score.Value = value; + } + } + } + private bool filterMods; + private UserTopScoreContainer topScoreContainer; + /// /// Whether to apply the game's currently selected mods as a filter when retrieving scores. /// @@ -81,25 +97,19 @@ namespace osu.Game.Screens.Select.Leaderboards UpdateScores(); }; - TopScore.BindValueChanged(newTopScore); + Content.Add(topScoreContainer = new UserTopScoreContainer()); } - private void newTopScore(ValueChangedEvent score) + protected override void Reset() { - Content.Clear(); - - if (score.NewValue != null) - { - - } + base.Reset(); + TopScore = null; } protected override bool IsOnlineScope => Scope != BeatmapLeaderboardScope.Local; protected override APIRequest FetchScores(Action> scoresCallback) { - TopScore.Value = null; - if (Beatmap == null) { PlaceholderState = PlaceholderState.NoneSelected; @@ -161,7 +171,7 @@ namespace osu.Game.Screens.Select.Leaderboards req.Success += r => { scoresCallback?.Invoke(r.Scores); - TopScore.Value = r.UserScore; + TopScore = r.UserScore; }; return req; From 9b35de9ce17c1fbe85ccabbc4e58bba81bef805f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:23:37 +0900 Subject: [PATCH 3034/5608] Update tests --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index cb4cd63266..bbd874fcd7 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -5,8 +5,12 @@ using System; using System.Collections.Generic; 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.Details; using osu.Game.Screens.Select.Leaderboards; using osu.Game.Users; using osuTK; @@ -20,6 +24,8 @@ namespace osu.Game.Tests.Visual.SongSelect typeof(Placeholder), typeof(MessagePlaceholder), typeof(RetrievalFailurePlaceholder), + typeof(UserTopScoreContainer), + typeof(Leaderboard), }; private readonly FailableLeaderboard leaderboard; @@ -35,6 +41,7 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddStep(@"New Scores", newScores); + AddStep(@"Show personal best", showPersonalBest); AddStep(@"Empty Scores", () => leaderboard.SetRetrievalState(PlaceholderState.NoScores)); AddStep(@"Network failure", () => leaderboard.SetRetrievalState(PlaceholderState.NetworkFailure)); AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter)); @@ -45,6 +52,32 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep($"{status} beatmap", () => showBeatmapWithStatus(status)); } + private void showPersonalBest() + { + leaderboard.TopScore = new APILegacyUserTopScoreInfo + { + Position = 999, + Score = new APILegacyScoreInfo + { + Rank = ScoreRank.XH, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 1707827, + Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, + User = new User + { + Id = 6602580, + Username = @"waaiiru", + Country = new Country + { + FullName = @"Spain", + FlagName = @"ES", + }, + }, + } + }; + } + private void newScores() { var scores = new[] From 80f46e02d8578ed0c23db9bb68bd7806f637663c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 15:33:49 +0900 Subject: [PATCH 3035/5608] Add equals (=) query operator variants --- osu.Game/Screens/Select/FilterControl.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 01e7ed9383..b25e65092e 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -183,7 +183,7 @@ namespace osu.Game.Screens.Select private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria()); private static readonly Regex query_syntax_regex = new Regex( - @"\b(?stars|ar|dr|cs|divisor|length|objects|bpm|status)(?[:><]+)(?\S*)", + @"\b(?stars|ar|dr|cs|divisor|length|objects|bpm|status)(?[=:><]+)(?\S*)", RegexOptions.Compiled | RegexOptions.IgnoreCase); private void applyQueries(FilterCriteria criteria, ref string query) @@ -246,6 +246,7 @@ namespace osu.Game.Screens.Select default: return; + case "=": case ":": range.IsInclusive = true; range.Min = value - equalityToleration; @@ -257,6 +258,7 @@ namespace osu.Game.Screens.Select range.Min = value; break; + case ">=": case ">:": range.IsInclusive = true; range.Min = value; @@ -267,6 +269,7 @@ namespace osu.Game.Screens.Select range.Max = value; break; + case "<=": case "<:": range.IsInclusive = true; range.Max = value; From e0fd8609d1f96f5fd0169248a3e6b2d3611097f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:34:46 +0900 Subject: [PATCH 3036/5608] Fix margins and clean up implementation --- .../Select/Details/UserTopScoreContainer.cs | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 959fbb927a..9d03f8439a 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -16,7 +16,6 @@ namespace osu.Game.Screens.Select.Details { public class UserTopScoreContainer : VisibilityContainer { - private const int height = 90; private const int duration = 500; private readonly Container scoreContainer; @@ -30,33 +29,30 @@ namespace osu.Game.Screens.Select.Details public UserTopScoreContainer() { RelativeSizeAxes = Axes.X; - Height = height; + AutoSizeAxes = Axes.Y; - Anchor = Anchor.BottomLeft; - Origin = Anchor.BottomLeft; + Margin = new MarginPadding { Vertical = 5 }; Children = new Drawable[] { - new Container + new FillFlowContainer { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, - Height = height, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, Children = new Drawable[] { new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Margin = new MarginPadding { Top = 5 }, Text = @"your personal best".ToUpper(), Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), }, scoreContainer = new Container { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, } @@ -89,14 +85,8 @@ namespace osu.Game.Screens.Select.Details }, (loadScoreCancellation = new CancellationTokenSource()).Token); } - protected override void PopIn() - { - this.FadeIn(duration, Easing.OutQuint); - } + protected override void PopIn() => this.FadeIn(duration, Easing.OutQuint); - protected override void PopOut() - { - this.FadeOut(duration, Easing.OutQuint); - } + protected override void PopOut() => this.FadeOut(duration, Easing.OutQuint); } } From 2b6c9aeb266e4f352fddebabb066314527ff658e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:38:40 +0900 Subject: [PATCH 3037/5608] Move top score container to more local namespace --- .../Visual/SongSelect/TestSceneBeatmapLeaderboard.cs | 1 - .../Visual/SongSelect/TestSceneUserTopScoreContainer.cs | 2 +- osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 1 - .../{Details => Leaderboards}/UserTopScoreContainer.cs | 6 +++--- 4 files changed, 4 insertions(+), 6 deletions(-) rename osu.Game/Screens/Select/{Details => Leaderboards}/UserTopScoreContainer.cs (98%) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index bbd874fcd7..fb27ec7654 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -10,7 +10,6 @@ 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.Details; using osu.Game.Screens.Select.Leaderboards; using osu.Game.Users; using osuTK; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs index 38ebb58e76..7fac45e0f1 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Screens.Select.Details; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -10,6 +9,7 @@ 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; namespace osu.Game.Tests.Visual.SongSelect diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index d038049504..71aa8a8a31 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -14,7 +14,6 @@ using osu.Game.Online.Leaderboards; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; -using osu.Game.Screens.Select.Details; namespace osu.Game.Screens.Select.Leaderboards { diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs similarity index 98% rename from osu.Game/Screens/Select/Details/UserTopScoreContainer.cs rename to osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs index 9d03f8439a..301b3a6ae1 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Threading; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -9,10 +11,8 @@ using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Scoring; -using System; -using System.Threading; -namespace osu.Game.Screens.Select.Details +namespace osu.Game.Screens.Select.Leaderboards { public class UserTopScoreContainer : VisibilityContainer { From 033c68a428bc74c126466d8b39b0bb119e8611dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:44:00 +0900 Subject: [PATCH 3038/5608] Fade in score, not container --- osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs index 301b3a6ae1..c5872e271d 100644 --- a/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.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; @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Select.Leaderboards }, drawableScore => { scoreContainer.Child = drawableScore; - Show(); + drawableScore.FadeInFromZero(duration, Easing.OutQuint); }, (loadScoreCancellation = new CancellationTokenSource()).Token); } From 36d0695e5c243e2012b2f128364a52574665117b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:44:05 +0900 Subject: [PATCH 3039/5608] Add spacing --- osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs index c5872e271d..da8f676cd0 100644 --- a/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.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; @@ -11,6 +11,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Scoring; +using osuTK; namespace osu.Game.Screens.Select.Leaderboards { @@ -40,6 +41,7 @@ namespace osu.Game.Screens.Select.Leaderboards RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, + Spacing = new Vector2(5), Children = new Drawable[] { new OsuSpriteText From c1daa187fe2aa68426341c6786b18bbee4c621df Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 15:44:14 +0900 Subject: [PATCH 3040/5608] Reduce default tolerance --- osu.Game/Screens/Select/FilterControl.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index b25e65092e..4c91208aec 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -197,23 +197,23 @@ namespace osu.Game.Screens.Select switch (key) { case "stars" when double.TryParse(value, out var stars): - updateCriteriaRange(ref criteria.StarDifficulty, op, stars, 0.5); + updateCriteriaRange(ref criteria.StarDifficulty, op, stars); break; case "ar" when double.TryParse(value, out var ar): - updateCriteriaRange(ref criteria.ApproachRate, op, ar, 0.3); + updateCriteriaRange(ref criteria.ApproachRate, op, ar); break; case "dr" when double.TryParse(value, out var dr): - updateCriteriaRange(ref criteria.DrainRate, op, dr, 0.3); + updateCriteriaRange(ref criteria.DrainRate, op, dr); break; case "cs" when double.TryParse(value, out var cs): - updateCriteriaRange(ref criteria.CircleSize, op, cs, 0.3); + updateCriteriaRange(ref criteria.CircleSize, op, cs); break; case "bpm" when double.TryParse(value, out var bpm): - updateCriteriaRange(ref criteria.BPM, op, bpm, 0.3); + updateCriteriaRange(ref criteria.BPM, op, bpm); break; case "length" when double.TryParse(value.TrimEnd('m', 's', 'h'), out var length): @@ -239,7 +239,7 @@ namespace osu.Game.Screens.Select } } - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double equalityToleration = 0) + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05) { switch (op) { @@ -249,8 +249,8 @@ namespace osu.Game.Screens.Select case "=": case ":": range.IsInclusive = true; - range.Min = value - equalityToleration; - range.Max = value + equalityToleration; + range.Min = value - tolerance; + range.Max = value + tolerance; break; case ">": From 48ee95955b80ea7a385e55649fcd71e308d2b197 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:45:08 +0900 Subject: [PATCH 3041/5608] Remove unnecessary redirection --- osu.Game/Screens/Select/SongSelect.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 7f9804c6a3..fca801ce78 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -223,9 +223,7 @@ namespace osu.Game.Screens.Select }); } - void displayScore(ScoreInfo score) => this.Push(new SoloResults(score)); - - BeatmapDetails.Leaderboard.ScoreSelected += displayScore; + BeatmapDetails.Leaderboard.ScoreSelected += score => this.Push(new SoloResults(score)); } [BackgroundDependencyLoader(true)] From e2f7d4bc629defae3f03c64040be75857594c27f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:45:43 +0900 Subject: [PATCH 3042/5608] Remove unnecessary ToMetric avoidance --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index e21ad413b6..9387482f14 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -80,7 +80,7 @@ namespace osu.Game.Online.Leaderboards Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 20, italics: true), - Text = rank <= 999 ? rank.ToString() : rank.ToMetric(decimals: rank < 100000 ? 1 : 0), + Text = rank.ToMetric(decimals: rank < 100000 ? 1 : 0), }, }, }, From a214e7e72fbf131c001b07b1f9288764bd5cdf85 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 16:26:22 +0900 Subject: [PATCH 3043/5608] Add confirmation dialog when exiting game --- osu.Game/Screens/Menu/MainMenu.cs | 49 ++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index a006877082..9393f785cd 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -1,18 +1,22 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.API; using osu.Game.Overlays; +using osu.Game.Overlays.Dialog; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Charts; using osu.Game.Screens.Edit; @@ -51,16 +55,23 @@ namespace osu.Game.Screens.Menu [Resolved] private IAPIProvider api { get; set; } + [Resolved] + private DialogOverlay dialogOverlay { get; set; } + private BackgroundScreenDefault background; protected override BackgroundScreen CreateBackground() => background; + private Bindable holdDelay; + [BackgroundDependencyLoader(true)] - private void load(DirectOverlay direct, SettingsOverlay settings) + private void load(DirectOverlay direct, SettingsOverlay settings, OsuConfigManager config) { if (host.CanExit) AddInternal(new ExitConfirmOverlay { Action = this.Exit }); + holdDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); + AddRangeInternal(new Drawable[] { new ParallaxContainer @@ -141,6 +152,7 @@ namespace osu.Game.Screens.Menu } private bool loginDisplayed; + private bool exitConfirmed; protected override void LogoArriving(OsuLogo logo, bool resuming) { @@ -221,9 +233,44 @@ namespace osu.Game.Screens.Menu public override bool OnExiting(IScreen next) { + if (holdDelay.Value == 0 && !exitConfirmed) + { + dialogOverlay?.Push(new ConfirmExitDialog(() => + { + exitConfirmed = true; + this.Exit(); + })); + + return true; + } + buttons.State = ButtonSystemState.Exit; this.FadeOut(3000); return base.OnExiting(next); } + + public class ConfirmExitDialog : PopupDialog + { + public ConfirmExitDialog(Action confirm) + { + HeaderText = "Are you sure you want to exit?"; + BodyText = "Last chance to back out."; + + Icon = FontAwesome.Solid.ExclamationTriangle; + + Buttons = new PopupDialogButton[] + { + new PopupDialogOkButton + { + Text = @"Good bye", + Action = confirm + }, + new PopupDialogCancelButton + { + Text = @"Just a little more" + }, + }; + } + } } } From 929f05884b8bf5cd4ce70c9481ffabf0486174e8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 16:28:06 +0900 Subject: [PATCH 3044/5608] Always confirm exit when button is clicked --- osu.Game/Screens/Menu/MainMenu.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 9393f785cd..7645734859 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -85,7 +85,11 @@ namespace osu.Game.Screens.Menu OnEdit = delegate { this.Push(new Editor()); }, OnSolo = onSolo, OnMulti = delegate { this.Push(new Multiplayer()); }, - OnExit = this.Exit, + OnExit = delegate + { + exitConfirmed = true; + this.Exit(); + }, } } }, From 3c21b68b738af2d902341d934f4c34f920b5c5b8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 16:51:57 +0900 Subject: [PATCH 3045/5608] Make OptionalRange generic --- osu.Game/Screens/Select/FilterControl.cs | 27 ++++++++---- osu.Game/Screens/Select/FilterCriteria.cs | 51 ++++++++++++++++------- 2 files changed, 56 insertions(+), 22 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 4c91208aec..8fda6c6a97 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -196,19 +196,19 @@ namespace osu.Game.Screens.Select switch (key) { - case "stars" when double.TryParse(value, out var stars): + case "stars" when float.TryParse(value, out var stars): updateCriteriaRange(ref criteria.StarDifficulty, op, stars); break; - case "ar" when double.TryParse(value, out var ar): + case "ar" when float.TryParse(value, out var ar): updateCriteriaRange(ref criteria.ApproachRate, op, ar); break; - case "dr" when double.TryParse(value, out var dr): + case "dr" when float.TryParse(value, out var dr): updateCriteriaRange(ref criteria.DrainRate, op, dr); break; - case "cs" when double.TryParse(value, out var cs): + case "cs" when float.TryParse(value, out var cs): updateCriteriaRange(ref criteria.CircleSize, op, cs); break; @@ -239,7 +239,8 @@ namespace osu.Game.Screens.Select } } - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05) + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value, double tolerance = 0.05f) + where T : struct, IComparable { switch (op) { @@ -249,8 +250,20 @@ namespace osu.Game.Screens.Select case "=": case ":": range.IsInclusive = true; - range.Min = value - tolerance; - range.Max = value + tolerance; + + switch (value) + { + case float _: + range.Min = (T)(object)((float)(object)value - tolerance); + range.Max = (T)(object)((float)(object)value + tolerance); + break; + + case double _: + range.Min = (T)(object)((double)(object)value - tolerance); + range.Max = (T)(object)((double)(object)value + tolerance); + break; + } + break; case ">": diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 84d63c16e0..4867f27c0b 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -14,12 +14,12 @@ namespace osu.Game.Screens.Select public GroupMode Group; public SortMode Sort; - public OptionalRange StarDifficulty; - public OptionalRange ApproachRate; - public OptionalRange DrainRate; - public OptionalRange CircleSize; - public OptionalRange Length; - public OptionalRange BPM; + public OptionalRange StarDifficulty; + public OptionalRange ApproachRate; + public OptionalRange DrainRate; + public OptionalRange CircleSize; + public OptionalRange Length; + public OptionalRange BPM; public int? BeatDivisor; @@ -42,23 +42,44 @@ namespace osu.Game.Screens.Select } } - public struct OptionalRange : IEquatable + public struct OptionalRange : IEquatable> + where T : struct, IComparable { - public bool IsInRange(double value) + public bool IsInRange(T value) { - if (Min.HasValue && (IsInclusive ? value < Min.Value : value <= Min.Value)) - return false; - if (Max.HasValue && (IsInclusive ? value > Max.Value : value >= Max.Value)) - return false; + if (Min.HasValue) + { + int comparison = value.CompareTo(Min.Value); + + if (comparison < 0) + return false; + + if (!IsInclusive && comparison == 0) + return false; + } + + if (Max.HasValue) + { + int comparison = value.CompareTo(Max.Value); + + if (comparison > 0) + return false; + + if (!IsInclusive && comparison == 0) + return false; + } return true; } - public double? Min; - public double? Max; + public T? Min; + public T? Max; public bool IsInclusive; - public bool Equals(OptionalRange range) => Min == range.Min && Max == range.Max; + public bool Equals(OptionalRange other) + => Min.Equals(other.Min) + && Max.Equals(other.Max) + && IsInclusive.Equals(other.IsInclusive); } } } From 0915a94470bd67b3d1cdcabb21bd12c6d3e66373 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 16:53:27 +0900 Subject: [PATCH 3046/5608] Make BeatDivisor use OptionalRange --- osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs | 2 +- osu.Game/Screens/Select/FilterControl.cs | 4 ++-- osu.Game/Screens/Select/FilterCriteria.cs | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 60e556a261..7017310018 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Select.Carousel match &= criteria.Length.IsInRange(Beatmap.Length); match &= criteria.BPM.IsInRange(Beatmap.BPM); - match &= !criteria.BeatDivisor.HasValue || criteria.BeatDivisor == Beatmap.BeatDivisor; + match &= criteria.BeatDivisor.IsInRange(Beatmap.BeatDivisor); match &= !criteria.OnlineStatus.HasValue || criteria.OnlineStatus == Beatmap.Status; if (match) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 8fda6c6a97..829f16d622 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -226,8 +226,8 @@ namespace osu.Game.Screens.Select updateCriteriaRange(ref criteria.Length, op, length * scale, scale / 2.0); break; - case "divisor" when op == ":" && int.TryParse(value, out var divisor): - criteria.BeatDivisor = divisor; + case "divisor" when int.TryParse(value, out var divisor): + updateCriteriaRange(ref criteria.BeatDivisor, op, divisor); break; case "status" when op == ":" && Enum.TryParse(value, ignoreCase: true, out var statusValue): diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 4867f27c0b..4584c63c2e 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -20,8 +20,7 @@ namespace osu.Game.Screens.Select public OptionalRange CircleSize; public OptionalRange Length; public OptionalRange BPM; - - public int? BeatDivisor; + public OptionalRange BeatDivisor; public BeatmapSetOnlineStatus? OnlineStatus; From 167bb9fcc16751087fc687d3424e7ea7cfafa555 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:11:28 +0900 Subject: [PATCH 3047/5608] Fix ugly casts --- osu.Game/Screens/Select/FilterControl.cs | 46 +++++++++++++++--------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 829f16d622..6ada0e4980 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -239,8 +239,36 @@ namespace osu.Game.Screens.Select } } - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value, double tolerance = 0.05f) - where T : struct, IComparable + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, float value, float tolerance = 0.05f) + { + switch (op) + { + case "=": + case ":": + range.Min = value - tolerance; + range.Max = value + tolerance; + break; + } + + updateCriteriaRange(ref range, op, value); + } + + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05f) + { + switch (op) + { + case "=": + case ":": + range.Min = value - tolerance; + range.Max = value + tolerance; + break; + } + + updateCriteriaRange(ref range, op, value); + } + + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value) + where T : struct, IComparable { switch (op) { @@ -250,20 +278,6 @@ namespace osu.Game.Screens.Select case "=": case ":": range.IsInclusive = true; - - switch (value) - { - case float _: - range.Min = (T)(object)((float)(object)value - tolerance); - range.Max = (T)(object)((float)(object)value + tolerance); - break; - - case double _: - range.Min = (T)(object)((double)(object)value - tolerance); - range.Max = (T)(object)((double)(object)value + tolerance); - break; - } - break; case ">": From d7831d8f5d6cdced76b9ff070b1d0d55c932818b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:11:43 +0900 Subject: [PATCH 3048/5608] Use non-generic IComparable interface --- osu.Game/Screens/Select/FilterCriteria.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 4584c63c2e..ff55ef5b12 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.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.Rulesets; @@ -42,13 +43,13 @@ namespace osu.Game.Screens.Select } public struct OptionalRange : IEquatable> - where T : struct, IComparable + where T : struct, IComparable { public bool IsInRange(T value) { - if (Min.HasValue) + if (Min != null) { - int comparison = value.CompareTo(Min.Value); + int comparison = Comparer.Default.Compare(value, Min.Value); if (comparison < 0) return false; @@ -57,9 +58,9 @@ namespace osu.Game.Screens.Select return false; } - if (Max.HasValue) + if (Max != null) { - int comparison = value.CompareTo(Max.Value); + int comparison = Comparer.Default.Compare(value, Max.Value); if (comparison > 0) return false; From 7683f7ff23198fc782135b4959550abe13236c97 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:12:07 +0900 Subject: [PATCH 3049/5608] Make OnlineStatus use OptionalRange --- osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs | 2 +- osu.Game/Screens/Select/FilterControl.cs | 4 ++-- osu.Game/Screens/Select/FilterCriteria.cs | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 7017310018..9cc84c8bdd 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -37,7 +37,7 @@ namespace osu.Game.Screens.Select.Carousel match &= criteria.BPM.IsInRange(Beatmap.BPM); match &= criteria.BeatDivisor.IsInRange(Beatmap.BeatDivisor); - match &= !criteria.OnlineStatus.HasValue || criteria.OnlineStatus == Beatmap.Status; + match &= criteria.OnlineStatus.IsInRange(Beatmap.Status); if (match) foreach (var criteriaTerm in criteria.SearchTerms) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 6ada0e4980..f1c8bb3a4e 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -230,8 +230,8 @@ namespace osu.Game.Screens.Select updateCriteriaRange(ref criteria.BeatDivisor, op, divisor); break; - case "status" when op == ":" && Enum.TryParse(value, ignoreCase: true, out var statusValue): - criteria.OnlineStatus = statusValue; + case "status" when Enum.TryParse(value, true, out var statusValue): + updateCriteriaRange(ref criteria.OnlineStatus, op, statusValue); break; } diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index ff55ef5b12..674f64efb4 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -22,8 +22,7 @@ namespace osu.Game.Screens.Select public OptionalRange Length; public OptionalRange BPM; public OptionalRange BeatDivisor; - - public BeatmapSetOnlineStatus? OnlineStatus; + public OptionalRange OnlineStatus; public string[] SearchTerms = Array.Empty(); From e075dd7ea84258862fac010f95e4a56d62d6ea0c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:16:34 +0900 Subject: [PATCH 3050/5608] Fix equals operator not working --- osu.Game/Screens/Select/FilterControl.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index f1c8bb3a4e..cd958a9503 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -241,6 +241,8 @@ namespace osu.Game.Screens.Select private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, float value, float tolerance = 0.05f) { + updateCriteriaRange(ref range, op, value); + switch (op) { case "=": @@ -249,12 +251,12 @@ namespace osu.Game.Screens.Select range.Max = value + tolerance; break; } - - updateCriteriaRange(ref range, op, value); } - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05f) + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05) { + updateCriteriaRange(ref range, op, value); + switch (op) { case "=": @@ -263,8 +265,6 @@ namespace osu.Game.Screens.Select range.Max = value + tolerance; break; } - - updateCriteriaRange(ref range, op, value); } private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value) @@ -278,6 +278,8 @@ namespace osu.Game.Screens.Select case "=": case ":": range.IsInclusive = true; + range.Min = value; + range.Max = value; break; case ">": From 96ea507320f6b10a9b902f5c1cc6f2df17a9c07a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:21:22 +0900 Subject: [PATCH 3051/5608] Reorder comparison for readability --- osu.Game/Screens/Select/FilterCriteria.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 674f64efb4..a3fa1b10ca 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -53,7 +53,7 @@ namespace osu.Game.Screens.Select if (comparison < 0) return false; - if (!IsInclusive && comparison == 0) + if (comparison == 0 && !IsInclusive) return false; } @@ -64,7 +64,7 @@ namespace osu.Game.Screens.Select if (comparison > 0) return false; - if (!IsInclusive && comparison == 0) + if (comparison == 0 && !IsInclusive) return false; } From e6c36a8bc7974e5c2b3f31c7e41467bc53809d7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 17:27:54 +0900 Subject: [PATCH 3052/5608] Fix scaling mode being applied to judgements --- osu.Game/Rulesets/Judgements/DrawableJudgement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 061c8cb3e1..b77fc1cfb0 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Judgements Font = OsuFont.Numeric.With(size: 20), Colour = judgementColour(Result.Type), Scale = new Vector2(0.85f, 1), - }) + }, confineMode: ConfineMode.NoScaling) }; } From 5120d82ef84cba05df1b775cd1689b1e7d60a562 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:36:42 +0900 Subject: [PATCH 3053/5608] Fix crash with multiple range criterias --- osu.Game/Screens/Select/FilterControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index cd958a9503..e3c23f7e22 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -235,7 +235,7 @@ namespace osu.Game.Screens.Select break; } - query = query.Remove(match.Index, match.Length); + query = query.Replace(match.ToString(), ""); } } From fa54a0bfd3954576adc0a07fef7619d6d6050f3b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 17:40:46 +0900 Subject: [PATCH 3054/5608] Fix test failures --- osu.Game/Screens/Menu/MainMenu.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 7645734859..2d8c48873a 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Menu [Resolved] private IAPIProvider api { get; set; } - [Resolved] + [Resolved(canBeNull: true)] private DialogOverlay dialogOverlay { get; set; } private BackgroundScreenDefault background; @@ -237,9 +237,9 @@ namespace osu.Game.Screens.Menu public override bool OnExiting(IScreen next) { - if (holdDelay.Value == 0 && !exitConfirmed) + if (holdDelay.Value == 0 && !exitConfirmed && dialogOverlay != null) { - dialogOverlay?.Push(new ConfirmExitDialog(() => + dialogOverlay.Push(new ConfirmExitDialog(() => { exitConfirmed = true; this.Exit(); From da15b900f7d628f4790dfd263c045382cdcd4f51 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:44:24 +0900 Subject: [PATCH 3055/5608] Remove virtual member from ModBlockFail --- osu.Game/Rulesets/Mods/ModBlockFail.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index 55c074bde2..7d7ecfa416 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mods /// public bool AllowFail => false; - public virtual bool RestartOnFail => false; + public bool RestartOnFail => false; public void ReadFromConfig(OsuConfigManager config) { From 65276cd235a0026170d4e06b2faffc515b045c06 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:58:10 +0900 Subject: [PATCH 3056/5608] Remove whitespace --- osu.Game/Rulesets/Mods/ModBlockFail.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index 7d7ecfa416..957a8d3348 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -15,7 +15,6 @@ namespace osu.Game.Rulesets.Mods /// We never fail, 'yo. /// public bool AllowFail => false; - public bool RestartOnFail => false; public void ReadFromConfig(OsuConfigManager config) From bc9941a990ea7430f2f8f1d87714beb8517e1dab Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 18:00:11 +0900 Subject: [PATCH 3057/5608] Newline required when xmldocs are involved --- osu.Game/Rulesets/Mods/ModBlockFail.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index 957a8d3348..7d7ecfa416 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -15,6 +15,7 @@ namespace osu.Game.Rulesets.Mods /// We never fail, 'yo. /// public bool AllowFail => false; + public bool RestartOnFail => false; public void ReadFromConfig(OsuConfigManager config) From ddff9882cf25e447df3e5632b0bc65f65d125d73 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 17:35:45 +0900 Subject: [PATCH 3058/5608] Fix importing archives which are nested in a single folder within a zip --- .../Beatmaps/IO/ImportBeatmapTest.cs | 50 ++++++++++++++++++- osu.Game/Database/ArchiveModelManager.cs | 7 ++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index ad0ed00989..8b39946ab0 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -15,7 +15,10 @@ using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.IO; using osu.Game.Tests.Resources; +using SharpCompress.Archives; using SharpCompress.Archives.Zip; +using SharpCompress.Common; +using SharpCompress.Writers.Zip; namespace osu.Game.Tests.Beatmaps.IO { @@ -135,7 +138,7 @@ namespace osu.Game.Tests.Beatmaps.IO using (var zip = ZipArchive.Open(brokenOsz)) { zip.AddEntry("broken.osu", brokenOsu, false); - zip.SaveTo(outStream, SharpCompress.Common.CompressionType.Deflate); + zip.SaveTo(outStream, CompressionType.Deflate); } // this will trigger purging of the existing beatmap (online set id match) but should rollback due to broken osu. @@ -366,6 +369,51 @@ namespace osu.Game.Tests.Beatmaps.IO } } + [Test] + public async Task TestImportNestedStructure() + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportNestedStructure")) + { + try + { + var osu = loadOsu(host); + + var temp = TestResources.GetTestBeatmapForImport(); + + string extractedFolder = $"{temp}_extracted"; + string subfolder = Path.Combine(extractedFolder, "subfolder"); + + Directory.CreateDirectory(subfolder); + + try + { + using (var zip = ZipArchive.Open(temp)) + zip.WriteToDirectory(subfolder); + + using (var zip = ZipArchive.Create()) + { + zip.AddAllFromDirectory(extractedFolder); + zip.SaveTo(temp, new ZipWriterOptions(CompressionType.Deflate)); + } + + var imported = await osu.Dependencies.Get().Import(temp); + + ensureLoaded(osu); + + Assert.IsFalse(imported.Files.Any(f => f.Filename.Contains("subfolder")), "Files contain common subfolder"); + } + finally + { + Directory.Delete(extractedFolder, true); + } + } + finally + { + host.Exit(); + } + } + } + public static async Task LoadOszIntoOsu(OsuGameBase osu, string path = null) { var temp = path ?? TestResources.GetTestBeatmapForImport(); diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 52d3f013ce..6c79b0d472 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -11,6 +11,7 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using osu.Framework; using osu.Framework.Extensions; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.IO.File; using osu.Framework.Logging; using osu.Framework.Platform; @@ -481,12 +482,16 @@ namespace osu.Game.Database { var fileInfos = new List(); + string prefix = reader.Filenames.GetCommonPrefix(); + if (!(prefix.EndsWith("/") || prefix.EndsWith("\\"))) + prefix = string.Empty; + // import files to manager foreach (string file in reader.Filenames) using (Stream s = reader.GetStream(file)) fileInfos.Add(new TFileModel { - Filename = FileSafety.PathStandardise(file), + Filename = FileSafety.PathStandardise(file.Substring(prefix.Length)), FileInfo = files.Add(s) }); From cffee1fd5e39c0857d877793be0a5184bce5cc3b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 20:02:45 +0900 Subject: [PATCH 3059/5608] Fix imported beatmap paths not correctly matching files --- osu.Game/Beatmaps/BeatmapManager.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 02d7b2d98f..55b8b80e44 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -89,7 +89,7 @@ namespace osu.Game.Beatmaps protected override Task Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive, CancellationToken cancellationToken = default) { if (archive != null) - beatmapSet.Beatmaps = createBeatmapDifficulties(archive); + beatmapSet.Beatmaps = createBeatmapDifficulties(beatmapSet.Files); foreach (BeatmapInfo b in beatmapSet.Beatmaps) { @@ -279,13 +279,13 @@ namespace osu.Game.Beatmaps /// /// Create all required s for the provided archive. /// - private List createBeatmapDifficulties(ArchiveReader reader) + private List createBeatmapDifficulties(List files) { var beatmapInfos = new List(); - foreach (var name in reader.Filenames.Where(f => f.EndsWith(".osu"))) + foreach (var file in files.Where(f => f.Filename.EndsWith(".osu"))) { - using (var raw = reader.GetStream(name)) + using (var raw = Files.Store.GetStream(file.FileInfo.StoragePath)) using (var ms = new MemoryStream()) //we need a memory stream so we can seek using (var sr = new StreamReader(ms)) { @@ -295,7 +295,7 @@ namespace osu.Game.Beatmaps var decoder = Decoder.GetDecoder(sr); IBeatmap beatmap = decoder.Decode(sr); - beatmap.BeatmapInfo.Path = name; + beatmap.BeatmapInfo.Path = file.Filename; beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash(); beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash(); From 50d4206c4584950d20e8824585a613a5a6b5ada2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 20:17:58 +0900 Subject: [PATCH 3060/5608] Fix exit scenarios --- .../TestSceneHoldToConfirmOverlay.cs | 3 --- .../Containers/HoldToConfirmContainer.cs | 13 +++++++--- osu.Game/Overlays/DialogOverlay.cs | 26 +++++++++++-------- osu.Game/Screens/Menu/ExitConfirmOverlay.cs | 7 ++++- osu.Game/Screens/Menu/MainMenu.cs | 16 ++++++++---- 5 files changed, 41 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs index f787754aa4..d4143f3f8d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs @@ -61,10 +61,7 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestHoldToConfirmOverlay : ExitConfirmOverlay { - protected override bool AllowMultipleFires => true; - public void Begin() => BeginConfirm(); - public void Abort() => AbortConfirm(); } } } diff --git a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs index a345fb554f..5d549ba217 100644 --- a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs +++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs @@ -16,7 +16,11 @@ namespace osu.Game.Graphics.Containers private const int fadeout_delay = 200; - private bool fired; + /// + /// Whether currently in a fired state (and the confirm has been sent). + /// + public bool Fired { get; private set; } + private bool confirming; /// @@ -36,7 +40,7 @@ namespace osu.Game.Graphics.Containers protected void BeginConfirm() { - if (confirming || (!AllowMultipleFires && fired)) return; + if (confirming || (!AllowMultipleFires && Fired)) return; confirming = true; @@ -46,14 +50,15 @@ namespace osu.Game.Graphics.Containers protected virtual void Confirm() { Action?.Invoke(); - fired = true; + Fired = true; } protected void AbortConfirm() { - if (!AllowMultipleFires && fired) return; + if (!AllowMultipleFires && Fired) return; confirming = false; + Fired = false; this.TransformBindableTo(Progress, 0, fadeout_delay, Easing.Out); } diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index 6aaeff8554..59d748bc5d 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -13,7 +13,8 @@ namespace osu.Game.Overlays public class DialogOverlay : OsuFocusedOverlayContainer { private readonly Container dialogContainer; - private PopupDialog currentDialog; + + public PopupDialog CurrentDialog { get; private set; } public DialogOverlay() { @@ -31,15 +32,15 @@ namespace osu.Game.Overlays public void Push(PopupDialog dialog) { - if (dialog == currentDialog) return; + if (dialog == CurrentDialog) return; - currentDialog?.Hide(); - currentDialog = dialog; + CurrentDialog?.Hide(); + CurrentDialog = dialog; - dialogContainer.Add(currentDialog); + dialogContainer.Add(CurrentDialog); - currentDialog.Show(); - currentDialog.State.ValueChanged += state => onDialogOnStateChanged(dialog, state.NewValue); + CurrentDialog.Show(); + CurrentDialog.State.ValueChanged += state => onDialogOnStateChanged(dialog, state.NewValue); Show(); } @@ -52,8 +53,11 @@ namespace osu.Game.Overlays //handle the dialog being dismissed. dialog.Delay(PopupDialog.EXIT_DURATION).Expire(); - if (dialog == currentDialog) + if (dialog == CurrentDialog) + { Hide(); + CurrentDialog = null; + } } protected override void PopIn() @@ -66,9 +70,9 @@ namespace osu.Game.Overlays { base.PopOut(); - if (currentDialog?.State.Value == Visibility.Visible) + if (CurrentDialog?.State.Value == Visibility.Visible) { - currentDialog.Hide(); + CurrentDialog.Hide(); return; } @@ -80,7 +84,7 @@ namespace osu.Game.Overlays switch (action) { case GlobalAction.Select: - currentDialog?.Buttons.OfType().FirstOrDefault()?.Click(); + CurrentDialog?.Buttons.OfType().FirstOrDefault()?.Click(); return true; } diff --git a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs index 519834859d..aaa3a77e74 100644 --- a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs +++ b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs @@ -9,6 +9,10 @@ namespace osu.Game.Screens.Menu { public class ExitConfirmOverlay : HoldToConfirmOverlay, IKeyBindingHandler { + protected override bool AllowMultipleFires => true; + + public void Abort() => AbortConfirm(); + public bool OnPressed(GlobalAction action) { if (action == GlobalAction.Back) @@ -24,7 +28,8 @@ namespace osu.Game.Screens.Menu { if (action == GlobalAction.Back) { - AbortConfirm(); + if (!Fired) + AbortConfirm(); return true; } diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 2d8c48873a..23fb2d8e37 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -64,11 +64,13 @@ namespace osu.Game.Screens.Menu private Bindable holdDelay; + private ExitConfirmOverlay exitConfirmOverlay; + [BackgroundDependencyLoader(true)] private void load(DirectOverlay direct, SettingsOverlay settings, OsuConfigManager config) { if (host.CanExit) - AddInternal(new ExitConfirmOverlay { Action = this.Exit }); + AddInternal(exitConfirmOverlay = new ExitConfirmOverlay { Action = this.Exit }); holdDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); @@ -237,12 +239,15 @@ namespace osu.Game.Screens.Menu public override bool OnExiting(IScreen next) { - if (holdDelay.Value == 0 && !exitConfirmed && dialogOverlay != null) + if (holdDelay.Value == 0 && !exitConfirmed && dialogOverlay != null && !(dialogOverlay.CurrentDialog is ConfirmExitDialog)) { dialogOverlay.Push(new ConfirmExitDialog(() => { exitConfirmed = true; this.Exit(); + }, () => + { + exitConfirmOverlay.Abort(); })); return true; @@ -253,9 +258,9 @@ namespace osu.Game.Screens.Menu return base.OnExiting(next); } - public class ConfirmExitDialog : PopupDialog + private class ConfirmExitDialog : PopupDialog { - public ConfirmExitDialog(Action confirm) + public ConfirmExitDialog(Action confirm, Action cancel) { HeaderText = "Are you sure you want to exit?"; BodyText = "Last chance to back out."; @@ -271,7 +276,8 @@ namespace osu.Game.Screens.Menu }, new PopupDialogCancelButton { - Text = @"Just a little more" + Text = @"Just a little more", + Action = cancel }, }; } From 94d3bcc612b96c63814e6fb5523f3b794ee12877 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 20:47:33 +0900 Subject: [PATCH 3061/5608] Fix top score not being selectable --- osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 71aa8a8a31..337d46ecdd 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -96,7 +96,10 @@ namespace osu.Game.Screens.Select.Leaderboards UpdateScores(); }; - Content.Add(topScoreContainer = new UserTopScoreContainer()); + Content.Add(topScoreContainer = new UserTopScoreContainer + { + ScoreSelected = s => ScoreSelected?.Invoke(s) + }); } protected override void Reset() From 23c5cb6367e1cf976eaae4cec6f6662b48adc9e5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 22:35:14 +0900 Subject: [PATCH 3062/5608] Expand tests to cover new behaviour --- .../Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs index d4143f3f8d..feef1dae6b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs @@ -52,11 +52,18 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("start confirming", () => overlay.Begin()); AddStep("abort confirming", () => overlay.Abort()); + AddAssert("ensure not fired internally", () => !overlay.Fired); AddAssert("ensure aborted", () => !fired); AddStep("start confirming", () => overlay.Begin()); AddUntilStep("wait until confirmed", () => fired); + AddAssert("ensure fired internally", () => overlay.Fired); + + AddStep("abort after fire", () => overlay.Abort()); + AddAssert("ensure not fired internally", () => !overlay.Fired); + AddStep("start confirming", () => overlay.Begin()); + AddUntilStep("wait until fired again", () => overlay.Fired); } private class TestHoldToConfirmOverlay : ExitConfirmOverlay From 67796e098258dd194367aa2bf031c66064b205cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 22:46:21 +0900 Subject: [PATCH 3063/5608] Apply code styling suggestions --- osu.Game/Screens/Menu/MainMenu.cs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 23fb2d8e37..0274973161 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -87,11 +87,7 @@ namespace osu.Game.Screens.Menu OnEdit = delegate { this.Push(new Editor()); }, OnSolo = onSolo, OnMulti = delegate { this.Push(new Multiplayer()); }, - OnExit = delegate - { - exitConfirmed = true; - this.Exit(); - }, + OnExit = confirmAndExit, } } }, @@ -120,6 +116,12 @@ namespace osu.Game.Screens.Menu preloadSongSelect(); } + private void confirmAndExit() + { + exitConfirmed = true; + this.Exit(); + } + private void preloadSongSelect() { if (songSelect == null) @@ -241,15 +243,7 @@ namespace osu.Game.Screens.Menu { if (holdDelay.Value == 0 && !exitConfirmed && dialogOverlay != null && !(dialogOverlay.CurrentDialog is ConfirmExitDialog)) { - dialogOverlay.Push(new ConfirmExitDialog(() => - { - exitConfirmed = true; - this.Exit(); - }, () => - { - exitConfirmOverlay.Abort(); - })); - + dialogOverlay.Push(new ConfirmExitDialog(confirmAndExit, () => exitConfirmOverlay.Abort())); return true; } From 0cf4db899ff94292bac6945e8296c93931f64769 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 19 Sep 2019 17:03:52 +0300 Subject: [PATCH 3064/5608] Few cleanups --- .../Visual/Online/TestSceneLeaderboardModSelector.cs | 9 +++++---- .../Overlays/BeatmapSet/LeaderboardModSelector.cs | 11 ++++------- osu.Game/Rulesets/UI/ModIcon.cs | 4 ++-- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index eb7fe5591d..3a64ac79f6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -53,11 +53,12 @@ namespace osu.Game.Tests.Visual.Online }); }); - AddStep("osu mods", () => ruleset.Value = new OsuRuleset().RulesetInfo); - AddStep("mania mods", () => ruleset.Value = new ManiaRuleset().RulesetInfo); - AddStep("taiko mods", () => ruleset.Value = new TaikoRuleset().RulesetInfo); - AddStep("catch mods", () => ruleset.Value = new CatchRuleset().RulesetInfo); + AddStep("osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo); + AddStep("mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo); + AddStep("taiko ruleset", () => ruleset.Value = new TaikoRuleset().RulesetInfo); + AddStep("catch ruleset", () => ruleset.Value = new CatchRuleset().RulesetInfo); AddStep("Deselect all", () => modSelector.DeselectAll()); + AddStep("null ruleset", () => ruleset.Value = null); } } } diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 66d78f927a..d09464aba6 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -74,10 +74,10 @@ namespace osu.Game.Overlays.BeatmapSet else mods.Remove(mod); + SelectedMods.Value = mods; + if (!mods.Any() && !IsHovered) highlightAll(); - - SelectedMods.Value = mods; } protected override bool OnHover(HoverEvent e) @@ -116,6 +116,7 @@ namespace osu.Game.Overlays.BeatmapSet : base(mod) { Scale = new Vector2(mod_scale); + Highlighted.Value = true; Add(new HoverClickSounds()); } @@ -123,8 +124,6 @@ namespace osu.Game.Overlays.BeatmapSet { base.LoadComplete(); - Highlighted.Value = true; - Selected.BindValueChanged(selected => { updateState(); @@ -152,10 +151,8 @@ namespace osu.Game.Overlays.BeatmapSet private void updateState() => Highlighted.Value = IsHovered || Selected.Value; - protected override void OnHighlightedChange(ValueChangedEvent highlighted) - { + protected override void OnHighlightedChanged(ValueChangedEvent highlighted) => this.FadeColour(highlighted.NewValue ? Color4.White : Color4.Gray, duration, Easing.OutQuint); - } } private class NoMod : Mod diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index d3607757ab..b54ddf8f12 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -114,10 +114,10 @@ namespace osu.Game.Rulesets.UI protected override void LoadComplete() { base.LoadComplete(); - Highlighted.BindValueChanged(OnHighlightedChange); + Highlighted.BindValueChanged(OnHighlightedChanged, true); } - protected virtual void OnHighlightedChange(ValueChangedEvent highlighted) + protected virtual void OnHighlightedChanged(ValueChangedEvent highlighted) { background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour; } From f10b390ca0ccc1aa3cce2392cfbb58b1428bfc06 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2019 16:32:39 +0000 Subject: [PATCH 3065/5608] Bump Microsoft.NET.Test.Sdk from 16.2.0 to 16.3.0 Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 16.2.0 to 16.3.0. - [Release notes](https://github.com/microsoft/vstest/releases) - [Commits](https://github.com/microsoft/vstest/compare/v16.2.0...v16.3) Signed-off-by: dependabot-preview[bot] --- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index c527a81f51..36342024b0 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index af10d5e06e..09bf9241f2 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index c331c811d2..791043bcc6 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index d2a0a8fa6f..b0e0efdc68 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 84f67c9319..75e6354612 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -3,7 +3,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index bba3c92245..491cf54686 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -5,7 +5,7 @@ - + From 636582e089c12f3eb9b814e84c7f3b54cd370e0d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Sep 2019 02:22:49 +0900 Subject: [PATCH 3066/5608] Always show exit confirmation when closing via alt-f4 or window control --- osu.Game/Screens/Menu/MainMenu.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 0274973161..dd81569e26 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -69,11 +69,22 @@ namespace osu.Game.Screens.Menu [BackgroundDependencyLoader(true)] private void load(DirectOverlay direct, SettingsOverlay settings, OsuConfigManager config) { - if (host.CanExit) - AddInternal(exitConfirmOverlay = new ExitConfirmOverlay { Action = this.Exit }); - holdDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); + if (host.CanExit) + { + AddInternal(exitConfirmOverlay = new ExitConfirmOverlay + { + Action = () => + { + if (holdDelay.Value > 0) + confirmAndExit(); + else + this.Exit(); + } + }); + } + AddRangeInternal(new Drawable[] { new ParallaxContainer @@ -241,7 +252,7 @@ namespace osu.Game.Screens.Menu public override bool OnExiting(IScreen next) { - if (holdDelay.Value == 0 && !exitConfirmed && dialogOverlay != null && !(dialogOverlay.CurrentDialog is ConfirmExitDialog)) + if (!exitConfirmed && dialogOverlay != null && !(dialogOverlay.CurrentDialog is ConfirmExitDialog)) { dialogOverlay.Push(new ConfirmExitDialog(confirmAndExit, () => exitConfirmOverlay.Abort())); return true; From 573da7b1e78b44a91db02fecfd8830fdd362d5b5 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 19 Sep 2019 20:34:37 +0300 Subject: [PATCH 3067/5608] Implement ChangelogEntryType --- .../Online/API/Requests/Responses/APIChangelogEntry.cs | 8 +++++++- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs index 140e228acd..f949ab5da5 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs @@ -24,7 +24,7 @@ namespace osu.Game.Online.API.Requests.Responses public string Url { get; set; } [JsonProperty("type")] - public string Type { get; set; } + public ChangelogEntryType Type { get; set; } [JsonProperty("category")] public string Category { get; set; } @@ -44,4 +44,10 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("github_user")] public APIChangelogUser GithubUser { get; set; } } + + public enum ChangelogEntryType + { + Add, + Fix + } } diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 3d145af562..6b24f39d98 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -76,7 +76,7 @@ namespace osu.Game.Overlays.Changelog var entryColour = entry.Major ? colours.YellowLight : Color4.White; - title.AddIcon(FontAwesome.Solid.Check, t => + title.AddIcon(entry.Type == ChangelogEntryType.Fix ? FontAwesome.Solid.Check : FontAwesome.Solid.Plus, t => { t.Font = fontSmall; t.Colour = entryColour; From daa64f1be7c9de8643014ca9d1aacf610a7d4ac9 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 19 Sep 2019 20:53:06 +0300 Subject: [PATCH 3068/5608] Adjust icon padding --- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 6b24f39d98..6d7b36b832 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -80,7 +80,7 @@ namespace osu.Game.Overlays.Changelog { t.Font = fontSmall; t.Colour = entryColour; - t.Padding = new MarginPadding { Left = -17, Right = 5 }; + t.Padding = new MarginPadding { Left = -17, Top = 5 }; }); title.AddText(entry.Title, t => From 5663e3e6b3b682c8c78c74fd49ebdf1502c0157d Mon Sep 17 00:00:00 2001 From: Lucas A Date: Thu, 19 Sep 2019 20:08:14 +0200 Subject: [PATCH 3069/5608] Fix escaped html strings not being unescaped in changelog entries. --- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 3d145af562..f44faabe52 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK.Graphics; using osu.Framework.Allocation; +using System.Net; namespace osu.Game.Overlays.Changelog { @@ -149,7 +150,7 @@ namespace osu.Game.Overlays.Changelog }; // todo: use markdown parsing once API returns markdown - message.AddText(Regex.Replace(entry.MessageHtml, @"<(.|\n)*?>", string.Empty), t => + message.AddText(WebUtility.HtmlDecode(Regex.Replace(entry.MessageHtml, @"<(.|\n)*?>", string.Empty)), t => { t.Font = fontSmall; t.Colour = new Color4(235, 184, 254, 255); From f7f9c0f7e0cb93bbbc423fbb3065713271c7b4a3 Mon Sep 17 00:00:00 2001 From: Revel Date: Thu, 19 Sep 2019 15:47:32 -0400 Subject: [PATCH 3070/5608] Update BeatmapDetailAreaTabControl.cs --- osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index 7f82d3cc12..6caef8e2aa 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -49,7 +49,7 @@ namespace osu.Game.Screens.Select { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, - Text = @"Mods", + Text = @"Selected Mods", Alpha = 0, }, }; From 033ed2e1f56c670dc42926c26aa1e9209e8b3c4e Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 20 Sep 2019 00:10:28 +0300 Subject: [PATCH 3071/5608] Add setting to always tint slider ball --- .../Configuration/OsuRulesetConfigManager.cs | 2 ++ osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs index f76635a932..ab6e6bac6c 100644 --- a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs @@ -18,6 +18,7 @@ namespace osu.Game.Rulesets.Osu.Configuration base.InitialiseDefaults(); Set(OsuRulesetSetting.SnakingInSliders, true); Set(OsuRulesetSetting.SnakingOutSliders, true); + Set(OsuRulesetSetting.AlwaysTintSliderBall, true); Set(OsuRulesetSetting.ShowCursorTrail, true); } } @@ -26,6 +27,7 @@ namespace osu.Game.Rulesets.Osu.Configuration { SnakingInSliders, SnakingOutSliders, + AlwaysTintSliderBall, ShowCursorTrail } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs index 88adf72551..be86614b57 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs @@ -35,6 +35,11 @@ namespace osu.Game.Rulesets.Osu.UI Bindable = config.GetBindable(OsuRulesetSetting.SnakingOutSliders) }, new SettingsCheckbox + { + LabelText = "Always tint slider ball with combo colour", + Bindable = config.GetBindable(OsuRulesetSetting.AlwaysTintSliderBall) + }, + new SettingsCheckbox { LabelText = "Cursor trail", Bindable = config.GetBindable(OsuRulesetSetting.ShowCursorTrail) From 8fcfd823169948811ca4000afde188ededb2d043 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 20 Sep 2019 00:10:55 +0300 Subject: [PATCH 3072/5608] Add AllowSliderBallTint to skin configuration --- osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs index e7b686d27d..98219cafe8 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs @@ -9,6 +9,7 @@ namespace osu.Game.Rulesets.Osu.Skinning HitCircleOverlap, SliderBorderSize, SliderPathRadius, + AllowSliderBallTint, CursorExpand, } } From f6291170b197bb200b2b3c1cd66b65623263047c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 20 Sep 2019 00:11:37 +0300 Subject: [PATCH 3073/5608] Implement tinting slider ball with combo colour --- .../Objects/Drawables/DrawableSlider.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 643a0f7336..d894fe2a31 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -34,6 +34,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly IBindable scaleBindable = new Bindable(); private readonly IBindable pathBindable = new Bindable(); + private readonly Bindable alwaysTintSliderBall = new Bindable(true); + private bool allowSliderBallTint; + [Resolved(CanBeNull = true)] private OsuRulesetConfigManager config { get; set; } @@ -106,6 +109,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { config?.BindWith(OsuRulesetSetting.SnakingInSliders, Body.SnakingIn); config?.BindWith(OsuRulesetSetting.SnakingOutSliders, Body.SnakingOut); + config?.BindWith(OsuRulesetSetting.AlwaysTintSliderBall, alwaysTintSliderBall); positionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); scaleBindable.BindValueChanged(scale => @@ -120,9 +124,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables pathBindable.BindValueChanged(_ => Body.Refresh()); + alwaysTintSliderBall.BindValueChanged(_ => updateSliderBallTint()); + AccentColour.BindValueChanged(colour => { Body.AccentColour = colour.NewValue; + updateSliderBallTint(); foreach (var drawableHitObject in NestedHitObjects) drawableHitObject.AccentColour.Value = colour.NewValue; @@ -173,10 +180,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Body.AccentColour = skin.GetConfig(OsuSkinColour.SliderTrackOverride)?.Value ?? AccentColour.Value; Body.BorderColour = skin.GetConfig(OsuSkinColour.SliderBorder)?.Value ?? Color4.White; + + allowSliderBallTint = skin.GetConfig(OsuSkinConfiguration.AllowSliderBallTint)?.Value ?? false; + updateSliderBallTint(); } private void updatePathRadius() => Body.PathRadius = slider.Scale * sliderPathRadius; + private void updateSliderBallTint() => Ball.Colour = (alwaysTintSliderBall.Value | allowSliderBallTint) ? AccentColour.Value : Color4.White; + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (userTriggered || Time.Current < slider.EndTime) From 1b45014ff678ccd256a5a3c57885fbb58357e1f8 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 20 Sep 2019 00:25:16 +0300 Subject: [PATCH 3074/5608] Use logical-OR --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index d894fe2a31..36ac0be723 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -187,7 +187,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private void updatePathRadius() => Body.PathRadius = slider.Scale * sliderPathRadius; - private void updateSliderBallTint() => Ball.Colour = (alwaysTintSliderBall.Value | allowSliderBallTint) ? AccentColour.Value : Color4.White; + private void updateSliderBallTint() => Ball.Colour = (alwaysTintSliderBall.Value || allowSliderBallTint) ? AccentColour.Value : Color4.White; protected override void CheckForResult(bool userTriggered, double timeOffset) { From d0a4e1e3c2ff107327091d7ece191742f45e1429 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Sep 2019 15:00:27 +0900 Subject: [PATCH 3075/5608] Force a checksum check before skipping FileStore copy op --- osu.Game/IO/FileStore.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/IO/FileStore.cs b/osu.Game/IO/FileStore.cs index 370d6786f5..bf4e881ed0 100644 --- a/osu.Game/IO/FileStore.cs +++ b/osu.Game/IO/FileStore.cs @@ -50,7 +50,16 @@ namespace osu.Game.IO string path = info.StoragePath; // we may be re-adding a file to fix missing store entries. - if (!Storage.Exists(path)) + bool requiresCopy = !Storage.Exists(path); + + if (!requiresCopy) + { + // even if the file already exists, check the existing checksum for safety. + using (var stream = Storage.GetStream(path)) + requiresCopy |= stream.ComputeSHA2Hash() != hash; + } + + if (requiresCopy) { data.Seek(0, SeekOrigin.Begin); From f306fe27d82d790ec6df2764a04b6e7ab1903593 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Sep 2019 15:05:48 +0900 Subject: [PATCH 3076/5608] Add test to cover corruption case --- .../Beatmaps/IO/ImportBeatmapTest.cs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 8b39946ab0..385ab4064d 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -90,6 +90,48 @@ namespace osu.Game.Tests.Beatmaps.IO } } + [Test] + public async Task TestImportCorruptThenImport() + { + //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenImport")) + { + try + { + var osu = loadOsu(host); + + var imported = await LoadOszIntoOsu(osu); + + var firstFile = imported.Files.First(); + + var files = osu.Dependencies.Get(); + + long originalLength; + using (var stream = files.Storage.GetStream(firstFile.FileInfo.StoragePath)) + originalLength = stream.Length; + + using (var stream = files.Storage.GetStream(firstFile.FileInfo.StoragePath, FileAccess.Write, FileMode.Create)) + stream.WriteByte(0); + + var importedSecondTime = await LoadOszIntoOsu(osu); + + using (var stream = files.Storage.GetStream(firstFile.FileInfo.StoragePath)) + Assert.AreEqual(stream.Length, originalLength, "Corruption was not fixed on second import"); + + // check the newly "imported" beatmap is actually just the restored previous import. since it matches hash. + Assert.IsTrue(imported.ID == importedSecondTime.ID); + Assert.IsTrue(imported.Beatmaps.First().ID == importedSecondTime.Beatmaps.First().ID); + + checkBeatmapSetCount(osu, 1); + checkSingleReferencedFileCount(osu, 18); + } + finally + { + host.Exit(); + } + } + } + [Test] public async Task TestRollbackOnFailure() { From e0a97cfac533487450b8067656674858cef958a0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Sep 2019 18:35:15 +0900 Subject: [PATCH 3077/5608] Add a LabelledComponent base class --- .../TestSceneLabelledComponent.cs | 89 +++++++++++++ .../LabelledComponents/LabelledComponent.cs | 121 ++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs create mode 100644 osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs new file mode 100644 index 0000000000..73e0191adb --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs @@ -0,0 +1,89 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Sprites; +using osu.Game.Screens.Edit.Setup.Components.LabelledComponents; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneLabelledComponent : OsuTestScene + { + [TestCase(false)] + [TestCase(true)] + public void TestPadded(bool hasDescription) => createPaddedComponent(hasDescription); + + [TestCase(false)] + [TestCase(true)] + public void TestNonPadded(bool hasDescription) => createPaddedComponent(hasDescription, false); + + private void createPaddedComponent(bool hasDescription = false, bool padded = true) + { + AddStep("create component", () => + { + LabelledComponent component; + + Child = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 500, + AutoSizeAxes = Axes.Y, + Child = component = padded ? (LabelledComponent)new PaddedLabelledComponent() : new NonPaddedLabelledComponent(), + }; + + component.Label = "a sample component"; + component.Description = hasDescription ? "this text describes the component" : string.Empty; + }); + } + + private class PaddedLabelledComponent : LabelledComponent + { + public PaddedLabelledComponent() + : base(true) + { + } + + protected override Drawable CreateComponent() => new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = Color4.Red, + Text = @"(( Component ))" + }; + } + + private class NonPaddedLabelledComponent : LabelledComponent + { + public NonPaddedLabelledComponent() + : base(false) + { + } + + protected override Drawable CreateComponent() => new Container + { + RelativeSizeAxes = Axes.X, + Height = 40, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.SlateGray + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = Color4.Red, + Text = @"(( Component ))" + } + } + }; + } + } +} diff --git a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs new file mode 100644 index 0000000000..b4c91d6d57 --- /dev/null +++ b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs @@ -0,0 +1,121 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osuTK; + +namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents +{ + public abstract class LabelledComponent : CompositeDrawable + { + protected const float CONTENT_PADDING_VERTICAL = 10; + protected const float CONTENT_PADDING_HORIZONTAL = 15; + protected const float CORNER_RADIUS = 15; + + protected readonly Drawable Component; + + private readonly OsuTextFlowContainer labelText; + private readonly OsuTextFlowContainer descriptionText; + + protected LabelledComponent(bool padded) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + CornerRadius = CORNER_RADIUS; + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex("1c2125"), + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = padded + ? new MarginPadding { Horizontal = CONTENT_PADDING_HORIZONTAL, Vertical = CONTENT_PADDING_VERTICAL } + : new MarginPadding { Left = CONTENT_PADDING_HORIZONTAL }, + Spacing = new Vector2(0, 12), + Children = new Drawable[] + { + new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Content = new[] + { + new Drawable[] + { + labelText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Bold)) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 20 } + }, + new Container + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = Component = CreateComponent().With(d => + { + d.Anchor = Anchor.CentreRight; + d.Origin = Anchor.CentreRight; + }) + } + }, + }, + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } + }, + descriptionText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold, italics: true)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Bottom = padded ? 0 : CONTENT_PADDING_VERTICAL }, + Alpha = 0, + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour osuColour) + { + descriptionText.Colour = osuColour.Yellow; + } + + public string Label + { + set => labelText.Text = value; + } + + public string Description + { + set + { + descriptionText.Text = value; + + if (!string.IsNullOrEmpty(value)) + descriptionText.Show(); + else + descriptionText.Hide(); + } + } + + protected abstract Drawable CreateComponent(); + } +} From 523272edab145dbd08b40980ca71a9aba16fe9d6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Sep 2019 18:39:04 +0900 Subject: [PATCH 3078/5608] Add xmldocs --- .../LabelledComponents/LabelledComponent.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs index b4c91d6d57..19e9c329d6 100644 --- a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs +++ b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs @@ -17,11 +17,18 @@ namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents protected const float CONTENT_PADDING_HORIZONTAL = 15; protected const float CORNER_RADIUS = 15; + /// + /// The component that is being displayed. + /// protected readonly Drawable Component; private readonly OsuTextFlowContainer labelText; private readonly OsuTextFlowContainer descriptionText; + /// + /// Creates a new . + /// + /// Whether the component should be padded or should be expanded to the bounds of this . protected LabelledComponent(bool padded) { RelativeSizeAxes = Axes.X; @@ -116,6 +123,10 @@ namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents } } + /// + /// Creates the component that should be displayed. + /// + /// The component. protected abstract Drawable CreateComponent(); } } From 2bbf4ca4b59abf2a0e87b7c2481d922bacd773b5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Sep 2019 18:50:50 +0900 Subject: [PATCH 3079/5608] Update LabelledTextBox to use LabelledComponent --- .../UserInterface/TestSceneLabelledTextBox.cs | 32 ++++- .../LabelledComponents/LabelledTextBox.cs | 117 +++--------------- 2 files changed, 51 insertions(+), 98 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs index 395905a30d..f9a5369576 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs @@ -19,6 +19,36 @@ namespace osu.Game.Tests.Visual.UserInterface typeof(LabelledTextBox), }; + [TestCase(false)] + [TestCase(true)] + public void TestTextBox(bool hasDescription) => createTextBox(hasDescription); + + private void createTextBox(bool hasDescription = false) + { + AddStep("create component", () => + { + LabelledComponent component; + + Child = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 500, + AutoSizeAxes = Axes.Y, + Child = component = new LabelledTextBox + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Label = "Testing text", + PlaceholderText = "This is definitely working as intended", + } + }; + + component.Label = "a sample component"; + component.Description = hasDescription ? "this text describes the component" : string.Empty; + }); + } + [BackgroundDependencyLoader] private void load() { @@ -32,7 +62,7 @@ namespace osu.Game.Tests.Visual.UserInterface { Anchor = Anchor.Centre, Origin = Anchor.Centre, - LabelText = "Testing text", + Label = "Testing text", PlaceholderText = "This is definitely working as intended", } }; diff --git a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs index 1c53fc7088..992371fedf 100644 --- a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs +++ b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs @@ -3,127 +3,50 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osuTK.Graphics; namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents { - public class LabelledTextBox : CompositeDrawable + public class LabelledTextBox : LabelledComponent { - private const float label_container_width = 150; - private const float corner_radius = 15; - private const float default_height = 40; - private const float default_label_left_padding = 15; - private const float default_label_top_padding = 12; - private const float default_label_text_size = 16; - public event TextBox.OnCommitHandler OnCommit; + protected new OsuTextBox Component => (OsuTextBox)base.Component; + + public LabelledTextBox() + : base(false) + { + } + public bool ReadOnly { - get => textBox.ReadOnly; - set => textBox.ReadOnly = value; - } - - public string LabelText - { - get => label.Text; - set => label.Text = value; - } - - public float LabelTextSize - { - get => label.Font.Size; - set => label.Font = label.Font.With(size: value); + set => Component.ReadOnly = value; } public string PlaceholderText { - get => textBox.PlaceholderText; - set => textBox.PlaceholderText = value; + set => Component.PlaceholderText = value; } public string Text { - get => textBox.Text; - set => textBox.Text = value; - } - - public Color4 LabelTextColour - { - get => label.Colour; - set => label.Colour = value; - } - - private readonly OsuTextBox textBox; - private readonly OsuSpriteText label; - - public LabelledTextBox() - { - RelativeSizeAxes = Axes.X; - Height = default_height; - CornerRadius = corner_radius; - Masking = true; - - InternalChild = new Container - { - RelativeSizeAxes = Axes.Both, - CornerRadius = corner_radius, - Masking = true, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("1c2125"), - }, - new GridContainer - { - RelativeSizeAxes = Axes.X, - Height = default_height, - Content = new[] - { - new Drawable[] - { - label = new OsuSpriteText - { - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - Padding = new MarginPadding { Left = default_label_left_padding, Top = default_label_top_padding }, - Colour = Color4.White, - Font = OsuFont.GetFont(size: default_label_text_size, weight: FontWeight.Bold), - }, - textBox = new OsuTextBox - { - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - RelativeSizeAxes = Axes.Both, - Height = 1, - CornerRadius = corner_radius, - }, - }, - }, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.Absolute, label_container_width), - new Dimension() - } - } - } - }; - - textBox.OnCommit += OnCommit; + set => Component.Text = value; } [BackgroundDependencyLoader] private void load(OsuColour colours) { - textBox.BorderColour = colours.Blue; + Component.BorderColour = colours.Blue; } + + protected override Drawable CreateComponent() => new OsuTextBox + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + CornerRadius = CORNER_RADIUS, + }.With(t => t.OnCommit += (sender, newText) => OnCommit?.Invoke(sender, newText)); } } From dfc0928ebe1af4fcb5b1837835d0b7642205526f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Sep 2019 19:39:21 +0900 Subject: [PATCH 3080/5608] Fix scores importing with deleted beatmap sets --- osu.Game/Database/ArchiveModelManager.cs | 2 +- osu.Game/Scoring/Legacy/DatabasedLegacyScoreParser.cs | 2 +- osu.Game/Scoring/ScoreManager.cs | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 6c79b0d472..2e30a7da3e 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -590,7 +590,7 @@ namespace osu.Game.Database /// /// The existing model. /// The newly imported model. - /// Whether the existing model should be restored and used. Returning false will delete the existing a force a re-import. + /// Whether the existing model should be restored and used. Returning false will delete the existing and force a re-import. protected virtual bool CanUndelete(TModel existing, TModel import) => true; private DbSet queryModel() => ContextFactory.Get().Set(); diff --git a/osu.Game/Scoring/Legacy/DatabasedLegacyScoreParser.cs b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreParser.cs index 77edd24612..2115d784a0 100644 --- a/osu.Game/Scoring/Legacy/DatabasedLegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreParser.cs @@ -22,6 +22,6 @@ namespace osu.Game.Scoring.Legacy } protected override Ruleset GetRuleset(int rulesetId) => rulesets.GetRuleset(rulesetId).CreateInstance(); - protected override WorkingBeatmap GetBeatmap(string md5Hash) => beatmaps.GetWorkingBeatmap(beatmaps.QueryBeatmap(b => b.MD5Hash == md5Hash)); + protected override WorkingBeatmap GetBeatmap(string md5Hash) => beatmaps.GetWorkingBeatmap(beatmaps.QueryBeatmap(b => !b.BeatmapSet.DeletePending && b.MD5Hash == md5Hash)); } } diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 8475158c78..6da195cd7c 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -56,6 +56,8 @@ namespace osu.Game.Scoring } } + protected override bool CanUndelete(ScoreInfo existing, ScoreInfo import) => false; + protected override IEnumerable GetStableImportPaths(Storage stableStorage) => stableStorage.GetFiles(ImportFromStablePath).Where(p => HandledExtensions.Any(ext => Path.GetExtension(p)?.Equals(ext, StringComparison.InvariantCultureIgnoreCase) ?? false)); From ff2f3cde02c6c841ca10ea2367bf75a2b411c43d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Sep 2019 19:47:54 +0900 Subject: [PATCH 3081/5608] Add test --- osu.Game.Tests/Scores/IO/ImportScoreTest.cs | 41 +++++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs index 4babb07213..ef71a38028 100644 --- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs @@ -117,6 +117,43 @@ namespace osu.Game.Tests.Scores.IO } } + [Test] + public async Task TestImportWithDeletedBeatmapSet() + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWithDeletedBeatmapSet")) + { + try + { + var osu = await loadOsu(host); + + var toImport = new ScoreInfo + { + Hash = Guid.NewGuid().ToString(), + Statistics = new Dictionary + { + { HitResult.Perfect, 100 }, + { HitResult.Miss, 50 } + } + }; + + var imported = await loadIntoOsu(osu, toImport); + + var beatmapManager = osu.Dependencies.Get(); + var scoreManager = osu.Dependencies.Get(); + + beatmapManager.Delete(imported.Beatmap.BeatmapSet); + Assert.That(scoreManager.Query(s => s.ID == imported.ID).DeletePending, Is.EqualTo(true)); + + await scoreManager.Import(imported); + Assert.That(scoreManager.Query(s => s.ID == imported.ID).DeletePending, Is.EqualTo(true)); + } + finally + { + host.Exit(); + } + } + } + private async Task loadIntoOsu(OsuGameBase osu, ScoreInfo score) { var beatmapManager = osu.Dependencies.Get(); @@ -125,9 +162,7 @@ namespace osu.Game.Tests.Scores.IO score.Ruleset = new OsuRuleset().RulesetInfo; var scoreManager = osu.Dependencies.Get(); - await scoreManager.Import(score); - - return scoreManager.GetAllUsableScores().First(); + return await scoreManager.Import(score); } private async Task loadOsu(GameHost host) From c89c092b989bedb1bc49c65c144874b4cc48f89f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Sep 2019 19:55:59 +0900 Subject: [PATCH 3082/5608] Allow undeleting scores if their beatmap exists --- osu.Game/Scoring/ScoreManager.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 6da195cd7c..8475158c78 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -56,8 +56,6 @@ namespace osu.Game.Scoring } } - protected override bool CanUndelete(ScoreInfo existing, ScoreInfo import) => false; - protected override IEnumerable GetStableImportPaths(Storage stableStorage) => stableStorage.GetFiles(ImportFromStablePath).Where(p => HandledExtensions.Any(ext => Path.GetExtension(p)?.Equals(ext, StringComparison.InvariantCultureIgnoreCase) ?? false)); From 093ed8421e34d76255083fd4bba7890f4818fbfe Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 20 Sep 2019 15:08:00 +0300 Subject: [PATCH 3083/5608] Remove "allow slider ball tinting" ruleset setting --- .../Configuration/OsuRulesetConfigManager.cs | 2 -- .../Objects/Drawables/DrawableSlider.cs | 10 ++-------- osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs | 5 ----- 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs index ab6e6bac6c..f76635a932 100644 --- a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs @@ -18,7 +18,6 @@ namespace osu.Game.Rulesets.Osu.Configuration base.InitialiseDefaults(); Set(OsuRulesetSetting.SnakingInSliders, true); Set(OsuRulesetSetting.SnakingOutSliders, true); - Set(OsuRulesetSetting.AlwaysTintSliderBall, true); Set(OsuRulesetSetting.ShowCursorTrail, true); } } @@ -27,7 +26,6 @@ namespace osu.Game.Rulesets.Osu.Configuration { SnakingInSliders, SnakingOutSliders, - AlwaysTintSliderBall, ShowCursorTrail } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 36ac0be723..a0b60479ac 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -109,7 +109,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { config?.BindWith(OsuRulesetSetting.SnakingInSliders, Body.SnakingIn); config?.BindWith(OsuRulesetSetting.SnakingOutSliders, Body.SnakingOut); - config?.BindWith(OsuRulesetSetting.AlwaysTintSliderBall, alwaysTintSliderBall); positionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); scaleBindable.BindValueChanged(scale => @@ -124,12 +123,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables pathBindable.BindValueChanged(_ => Body.Refresh()); - alwaysTintSliderBall.BindValueChanged(_ => updateSliderBallTint()); - AccentColour.BindValueChanged(colour => { Body.AccentColour = colour.NewValue; - updateSliderBallTint(); foreach (var drawableHitObject in NestedHitObjects) drawableHitObject.AccentColour.Value = colour.NewValue; @@ -181,14 +177,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Body.AccentColour = skin.GetConfig(OsuSkinColour.SliderTrackOverride)?.Value ?? AccentColour.Value; Body.BorderColour = skin.GetConfig(OsuSkinColour.SliderBorder)?.Value ?? Color4.White; - allowSliderBallTint = skin.GetConfig(OsuSkinConfiguration.AllowSliderBallTint)?.Value ?? false; - updateSliderBallTint(); + bool allowBallTint = skin.GetConfig(OsuSkinConfiguration.AllowSliderBallTint)?.Value ?? false; + Ball.Colour = allowBallTint ? AccentColour.Value : Color4.White; } private void updatePathRadius() => Body.PathRadius = slider.Scale * sliderPathRadius; - private void updateSliderBallTint() => Ball.Colour = (alwaysTintSliderBall.Value || allowSliderBallTint) ? AccentColour.Value : Color4.White; - protected override void CheckForResult(bool userTriggered, double timeOffset) { if (userTriggered || Time.Current < slider.EndTime) diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs index be86614b57..88adf72551 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs @@ -35,11 +35,6 @@ namespace osu.Game.Rulesets.Osu.UI Bindable = config.GetBindable(OsuRulesetSetting.SnakingOutSliders) }, new SettingsCheckbox - { - LabelText = "Always tint slider ball with combo colour", - Bindable = config.GetBindable(OsuRulesetSetting.AlwaysTintSliderBall) - }, - new SettingsCheckbox { LabelText = "Cursor trail", Bindable = config.GetBindable(OsuRulesetSetting.ShowCursorTrail) From 57310c86c7ab8d57f1edad558f4f9fdc917595fb Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 20 Sep 2019 15:09:51 +0300 Subject: [PATCH 3084/5608] Remove unnecessary fields --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index a0b60479ac..9e8ad9851c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -34,9 +34,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly IBindable scaleBindable = new Bindable(); private readonly IBindable pathBindable = new Bindable(); - private readonly Bindable alwaysTintSliderBall = new Bindable(true); - private bool allowSliderBallTint; - [Resolved(CanBeNull = true)] private OsuRulesetConfigManager config { get; set; } From 8300e86f20815f9add57bdc4132437186af7346d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 20 Sep 2019 15:46:43 +0300 Subject: [PATCH 3085/5608] Specify model name on import notification messages --- osu.Game/Database/ArchiveModelManager.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 6c79b0d472..969673993b 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Humanizer; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using osu.Framework; @@ -110,7 +111,7 @@ namespace osu.Game.Database protected async Task Import(ProgressNotification notification, params string[] paths) { notification.Progress = 0; - notification.Text = "Import is initialising..."; + notification.Text = $"{HumanisedModelName.Humanize()}s import is initialising..."; int current = 0; @@ -146,7 +147,7 @@ namespace osu.Game.Database if (imported.Count == 0) { - notification.Text = "Import failed!"; + notification.Text = $"{HumanisedModelName.Humanize()}s import failed!"; notification.State = ProgressNotificationState.Cancelled; } else From 3be03a26c93257dcfa0858dfca872b635127194f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 20 Sep 2019 16:18:55 +0300 Subject: [PATCH 3086/5608] Pluralize instead of adding 's' --- osu.Game/Database/ArchiveModelManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 969673993b..dc17526201 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -111,7 +111,7 @@ namespace osu.Game.Database protected async Task Import(ProgressNotification notification, params string[] paths) { notification.Progress = 0; - notification.Text = $"{HumanisedModelName.Humanize()}s import is initialising..."; + notification.Text = $"{HumanisedModelName.Pluralize(paths.Length == 1)} import is initialising...".Humanize(); int current = 0; @@ -147,7 +147,7 @@ namespace osu.Game.Database if (imported.Count == 0) { - notification.Text = $"{HumanisedModelName.Humanize()}s import failed!"; + notification.Text = $"{HumanisedModelName.Pluralize(paths.Length == 1)} import failed!".Humanize(); notification.State = ProgressNotificationState.Cancelled; } else From 2d99d41a6dc1fb79173f91f5dcbb22514ab96d0b Mon Sep 17 00:00:00 2001 From: Vperus Date: Fri, 20 Sep 2019 18:17:35 +0300 Subject: [PATCH 3087/5608] Remove unused CORNER_RADIUS --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 31221c05ee..8f353ae138 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -18,8 +18,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// public class DrawableNote : DrawableManiaHitObject, IKeyBindingHandler { - public const float CORNER_RADIUS = NotePiece.NOTE_HEIGHT / 2; - private readonly NotePiece headPiece; public DrawableNote(Note hitObject) From ac8fe6045f2cba92ec1d3e819b0f6fa0b3c15164 Mon Sep 17 00:00:00 2001 From: Vperus Date: Fri, 20 Sep 2019 19:58:39 +0300 Subject: [PATCH 3088/5608] Fixed typo Changed CreateReourceStore() to CreateResourceStore() --- osu.Game/Rulesets/Ruleset.cs | 2 +- osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 197c089f71..dd1b3615c7 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -84,7 +84,7 @@ namespace osu.Game.Rulesets public virtual Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.Solid.QuestionCircle }; - public virtual IResourceStore CreateReourceStore() => new NamespacedResourceStore(new DllResourceStore(GetType().Assembly.Location), @"Resources"); + public virtual IResourceStore CreateResourceStore() => new NamespacedResourceStore(new DllResourceStore(GetType().Assembly.Location), @"Resources"); public abstract string Description { get; } diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index a34bb6e8ea..d68b0e94c5 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -153,7 +153,7 @@ namespace osu.Game.Rulesets.UI { var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - var resources = Ruleset.CreateReourceStore(); + var resources = Ruleset.CreateResourceStore(); if (resources != null) { From 92f9cf3e06e75eb67d0fa40498e2b436136b9e85 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 21 Sep 2019 02:08:19 +0900 Subject: [PATCH 3089/5608] 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 969eb205e0..c57fc342ba 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a733a0e7f9..a27a94b8f9 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 4bfa1ebcd0..a6516e6d1b 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From bbf3ac77f840a546fe500de6b2638540b674e3a8 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 20 Sep 2019 21:35:26 +0200 Subject: [PATCH 3090/5608] Add visual test for HTML string unescaping. --- .../Online/TestSceneChangelogOverlay.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index f555c276f4..658f678b10 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -68,6 +68,34 @@ namespace osu.Game.Tests.Visual.Online changelog.ShowListing(); changelog.Show(); }); + + AddStep(@"Ensure HTML string unescaping", () => + { + changelog.ShowBuild(new APIChangelogBuild + { + Version = "2019.920.0", + DisplayVersion = "2019.920.0", + UpdateStream = new APIUpdateStream + { + Name = "Test", + DisplayName = "Test" + }, + ChangelogEntries = new List + { + new APIChangelogEntry + { + Category = "Testing HTML strings unescaping", + Title = "Ensuring HTML strings are being unescaped", + MessageHtml = """"This text should appear triple-quoted""" >_<", + GithubUser = new APIChangelogUser + { + DisplayName = "Dummy", + OsuUsername = "Dummy", + } + }, + } + }); + }); } } } From e7118a9272600b7e4ac2ffddef8bbecab336d12d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 20 Sep 2019 23:47:21 +0300 Subject: [PATCH 3091/5608] Use System mod type for NoMod --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 2 +- osu.Game/Rulesets/Mods/ModType.cs | 3 +-- osu.Game/Rulesets/UI/ModIcon.cs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index d09464aba6..4b6fd5bfc2 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -165,7 +165,7 @@ namespace osu.Game.Overlays.BeatmapSet public override IconUsage Icon => FontAwesome.Solid.Ban; - public override ModType Type => ModType.Custom; + public override ModType Type => ModType.System; } } } diff --git a/osu.Game/Rulesets/Mods/ModType.cs b/osu.Game/Rulesets/Mods/ModType.cs index 1cdc4415ac..e3c82e42f5 100644 --- a/osu.Game/Rulesets/Mods/ModType.cs +++ b/osu.Game/Rulesets/Mods/ModType.cs @@ -10,7 +10,6 @@ namespace osu.Game.Rulesets.Mods Conversion, Automation, Fun, - System, - Custom + System } } diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index b54ddf8f12..19211e0c80 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.UI highlightedColour = colours.PinkLight; break; - case ModType.Custom: + case ModType.System: backgroundColour = colours.Gray6; highlightedColour = colours.Gray7; modIcon.Colour = colours.Yellow; From befdd140f462c80d6aa2027b22f77310ecd45ed5 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 20 Sep 2019 23:50:19 +0300 Subject: [PATCH 3092/5608] Reverse padding changes --- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 6d7b36b832..6b24f39d98 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -80,7 +80,7 @@ namespace osu.Game.Overlays.Changelog { t.Font = fontSmall; t.Colour = entryColour; - t.Padding = new MarginPadding { Left = -17, Top = 5 }; + t.Padding = new MarginPadding { Left = -17, Right = 5 }; }); title.AddText(entry.Title, t => From c99b48f9342189ba0290702893fbdcc1a7b72f2f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 21 Sep 2019 23:30:54 +0900 Subject: [PATCH 3093/5608] Bring up-to-date and use IApplicableFailOverride --- osu.Game/Rulesets/Mods/ModEasy.cs | 40 +++++++++++++++++++------------ 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index 4365ed256f..a55ebc51d6 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -2,16 +2,17 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModEasy : Mod, IApplicableToDifficulty, IApplicableToScoreProcessor + public abstract class ModEasy : Mod, IApplicableToDifficulty, IApplicableFailOverride, IApplicableToScoreProcessor { - private int lives; public override string Name => "Easy"; public override string Acronym => "EZ"; public override IconUsage Icon => OsuIcon.ModEasy; @@ -20,6 +21,10 @@ namespace osu.Game.Rulesets.Mods public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) }; + private int retries = 2; + + private BindableNumber health; + public void ApplyToDifficulty(BeatmapDifficulty difficulty) { const float ratio = 0.5f; @@ -29,21 +34,26 @@ namespace osu.Game.Rulesets.Mods difficulty.OverallDifficulty *= ratio; } + public bool AllowFail + { + get + { + if (retries == 0) return true; + + health.Value = health.MaxValue; + retries--; + + return false; + } + } + + public bool RestartOnFail => false; + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { - //Note : The lives has to be instaciated here in order to prevent the values from different plays to interfear - //with each other / not reseting after a restart , as this method is called once a play starts (to my knowlegde). - //This will be better implemented with a List once I know how to reliably get the game time and update it. - //If you know any information about that, please contact me because I didn't find a sollution to that. - lives = 2; - scoreProcessor.Health.ValueChanged += valueChanged => - { - if (scoreProcessor.Health.Value == scoreProcessor.Health.MinValue && lives > 0) - { - lives--; - scoreProcessor.Health.Value = scoreProcessor.Health.MaxValue; - } - }; + health = scoreProcessor.Health.GetBoundCopy(); } + + public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; } } From 24cc8ce0b7c53f5d4a30b3865c363dcc82483816 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 22 Sep 2019 00:59:01 +0900 Subject: [PATCH 3094/5608] Fix deleting null beatmap set --- osu.Game.Tests/Scores/IO/ImportScoreTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs index ef71a38028..b784cc4682 100644 --- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs @@ -141,7 +141,7 @@ namespace osu.Game.Tests.Scores.IO var beatmapManager = osu.Dependencies.Get(); var scoreManager = osu.Dependencies.Get(); - beatmapManager.Delete(imported.Beatmap.BeatmapSet); + beatmapManager.Delete(beatmapManager.QueryBeatmapSet(s => s.Beatmaps.Any(b => b.ID == imported.Beatmap.ID))); Assert.That(scoreManager.Query(s => s.ID == imported.ID).DeletePending, Is.EqualTo(true)); await scoreManager.Import(imported); From 08440ce5fd404f03763de43f95012a8dca64dafa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 22 Sep 2019 00:59:40 +0900 Subject: [PATCH 3095/5608] Adjust test to assert that the import failed --- osu.Game.Tests/Scores/IO/ImportScoreTest.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs index b784cc4682..89b5db9e1b 100644 --- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs @@ -144,8 +144,8 @@ namespace osu.Game.Tests.Scores.IO beatmapManager.Delete(beatmapManager.QueryBeatmapSet(s => s.Beatmaps.Any(b => b.ID == imported.Beatmap.ID))); Assert.That(scoreManager.Query(s => s.ID == imported.ID).DeletePending, Is.EqualTo(true)); - await scoreManager.Import(imported); - Assert.That(scoreManager.Query(s => s.ID == imported.ID).DeletePending, Is.EqualTo(true)); + var secondImport = await loadIntoOsu(osu, imported); + Assert.That(secondImport, Is.Null); } finally { @@ -158,11 +158,16 @@ namespace osu.Game.Tests.Scores.IO { var beatmapManager = osu.Dependencies.Get(); - score.Beatmap = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First(); - score.Ruleset = new OsuRuleset().RulesetInfo; + if (score.Beatmap == null) + score.Beatmap = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First(); + + if (score.Ruleset == null) + score.Ruleset = new OsuRuleset().RulesetInfo; var scoreManager = osu.Dependencies.Get(); - return await scoreManager.Import(score); + await scoreManager.Import(score); + + return scoreManager.GetAllUsableScores().FirstOrDefault(); } private async Task loadOsu(GameHost host) From 6bb0f3eb4149a3649c62543b16d765abcfa4f990 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 21 Sep 2019 20:04:12 +0300 Subject: [PATCH 3096/5608] Move humanizing to the model name instead --- osu.Game/Database/ArchiveModelManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index dc17526201..36084fefeb 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -111,7 +111,7 @@ namespace osu.Game.Database protected async Task Import(ProgressNotification notification, params string[] paths) { notification.Progress = 0; - notification.Text = $"{HumanisedModelName.Pluralize(paths.Length == 1)} import is initialising...".Humanize(); + notification.Text = $"{HumanisedModelName.Humanize().Pluralize(paths.Length == 1)} import is initialising..."; int current = 0; @@ -147,7 +147,7 @@ namespace osu.Game.Database if (imported.Count == 0) { - notification.Text = $"{HumanisedModelName.Pluralize(paths.Length == 1)} import failed!".Humanize(); + notification.Text = $"{HumanisedModelName.Humanize().Pluralize(paths.Length == 1)} import failed!"; notification.State = ProgressNotificationState.Cancelled; } else From 9be8bdef521d1a90f1e8462835bb308865994fab Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 21 Sep 2019 21:00:24 +0300 Subject: [PATCH 3097/5608] Remove pluralize and use title letter casing --- osu.Game/Database/ArchiveModelManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 36084fefeb..703cc53318 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -111,7 +111,7 @@ namespace osu.Game.Database protected async Task Import(ProgressNotification notification, params string[] paths) { notification.Progress = 0; - notification.Text = $"{HumanisedModelName.Humanize().Pluralize(paths.Length == 1)} import is initialising..."; + notification.Text = $"{HumanisedModelName.Humanize(LetterCasing.Title)} import is initialising..."; int current = 0; @@ -147,7 +147,7 @@ namespace osu.Game.Database if (imported.Count == 0) { - notification.Text = $"{HumanisedModelName.Humanize().Pluralize(paths.Length == 1)} import failed!"; + notification.Text = $"{HumanisedModelName.Humanize(LetterCasing.Title)} import failed!"; notification.State = ProgressNotificationState.Cancelled; } else From 33c51d5178fc5191d143fd77407042e5dc6b6687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 20 Sep 2019 20:55:30 +0200 Subject: [PATCH 3098/5608] Extract parsing filter queries to class For the sake of testability without having to spin up visual tests, extract methods related to parsing filter queries from FilterControl to a static FilterQueryParser class. --- osu.Game/Screens/Select/FilterControl.cs | 131 +----------------- osu.Game/Screens/Select/FilterQueryParser.cs | 138 +++++++++++++++++++ 2 files changed, 139 insertions(+), 130 deletions(-) create mode 100644 osu.Game/Screens/Select/FilterQueryParser.cs diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index e3c23f7e22..91f1ca0307 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -16,8 +16,6 @@ using Container = osu.Framework.Graphics.Containers.Container; using osu.Framework.Graphics.Shapes; using osu.Game.Configuration; using osu.Game.Rulesets; -using System.Text.RegularExpressions; -using osu.Game.Beatmaps; namespace osu.Game.Screens.Select { @@ -47,10 +45,7 @@ namespace osu.Game.Screens.Select Ruleset = ruleset.Value }; - applyQueries(criteria, ref query); - - criteria.SearchText = query; - + FilterQueryParser.ApplyQueries(criteria, query); return criteria; } @@ -181,129 +176,5 @@ namespace osu.Game.Screens.Select } private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria()); - - private static readonly Regex query_syntax_regex = new Regex( - @"\b(?stars|ar|dr|cs|divisor|length|objects|bpm|status)(?[=:><]+)(?\S*)", - RegexOptions.Compiled | RegexOptions.IgnoreCase); - - private void applyQueries(FilterCriteria criteria, ref string query) - { - foreach (Match match in query_syntax_regex.Matches(query)) - { - var key = match.Groups["key"].Value.ToLower(); - var op = match.Groups["op"].Value; - var value = match.Groups["value"].Value; - - switch (key) - { - case "stars" when float.TryParse(value, out var stars): - updateCriteriaRange(ref criteria.StarDifficulty, op, stars); - break; - - case "ar" when float.TryParse(value, out var ar): - updateCriteriaRange(ref criteria.ApproachRate, op, ar); - break; - - case "dr" when float.TryParse(value, out var dr): - updateCriteriaRange(ref criteria.DrainRate, op, dr); - break; - - case "cs" when float.TryParse(value, out var cs): - updateCriteriaRange(ref criteria.CircleSize, op, cs); - break; - - case "bpm" when double.TryParse(value, out var bpm): - updateCriteriaRange(ref criteria.BPM, op, bpm); - break; - - case "length" when double.TryParse(value.TrimEnd('m', 's', 'h'), out var length): - var scale = - value.EndsWith("ms") ? 1 : - value.EndsWith("s") ? 1000 : - value.EndsWith("m") ? 60000 : - value.EndsWith("h") ? 3600000 : 1000; - - updateCriteriaRange(ref criteria.Length, op, length * scale, scale / 2.0); - break; - - case "divisor" when int.TryParse(value, out var divisor): - updateCriteriaRange(ref criteria.BeatDivisor, op, divisor); - break; - - case "status" when Enum.TryParse(value, true, out var statusValue): - updateCriteriaRange(ref criteria.OnlineStatus, op, statusValue); - break; - } - - query = query.Replace(match.ToString(), ""); - } - } - - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, float value, float tolerance = 0.05f) - { - updateCriteriaRange(ref range, op, value); - - switch (op) - { - case "=": - case ":": - range.Min = value - tolerance; - range.Max = value + tolerance; - break; - } - } - - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05) - { - updateCriteriaRange(ref range, op, value); - - switch (op) - { - case "=": - case ":": - range.Min = value - tolerance; - range.Max = value + tolerance; - break; - } - } - - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value) - where T : struct, IComparable - { - switch (op) - { - default: - return; - - case "=": - case ":": - range.IsInclusive = true; - range.Min = value; - range.Max = value; - break; - - case ">": - range.IsInclusive = false; - range.Min = value; - break; - - case ">=": - case ">:": - range.IsInclusive = true; - range.Min = value; - break; - - case "<": - range.IsInclusive = false; - range.Max = value; - break; - - case "<=": - case "<:": - range.IsInclusive = true; - range.Max = value; - break; - } - } } } diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs new file mode 100644 index 0000000000..4e2b591fc9 --- /dev/null +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -0,0 +1,138 @@ +// 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.Text.RegularExpressions; +using osu.Game.Beatmaps; + +namespace osu.Game.Screens.Select +{ + internal static class FilterQueryParser + { + private static readonly Regex query_syntax_regex = new Regex( + @"\b(?stars|ar|dr|cs|divisor|length|objects|bpm|status)(?[=:><]+)(?\S*)", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + + internal static void ApplyQueries(FilterCriteria criteria, string query) + { + foreach (Match match in query_syntax_regex.Matches(query)) + { + var key = match.Groups["key"].Value.ToLower(); + var op = match.Groups["op"].Value; + var value = match.Groups["value"].Value; + + switch (key) + { + case "stars" when float.TryParse(value, out var stars): + updateCriteriaRange(ref criteria.StarDifficulty, op, stars); + break; + + case "ar" when float.TryParse(value, out var ar): + updateCriteriaRange(ref criteria.ApproachRate, op, ar); + break; + + case "dr" when float.TryParse(value, out var dr): + updateCriteriaRange(ref criteria.DrainRate, op, dr); + break; + + case "cs" when float.TryParse(value, out var cs): + updateCriteriaRange(ref criteria.CircleSize, op, cs); + break; + + case "bpm" when double.TryParse(value, out var bpm): + updateCriteriaRange(ref criteria.BPM, op, bpm); + break; + + case "length" when double.TryParse(value.TrimEnd('m', 's', 'h'), out var length): + var scale = + value.EndsWith("ms") ? 1 : + value.EndsWith("s") ? 1000 : + value.EndsWith("m") ? 60000 : + value.EndsWith("h") ? 3600000 : 1000; + + updateCriteriaRange(ref criteria.Length, op, length * scale, scale / 2.0); + break; + + case "divisor" when int.TryParse(value, out var divisor): + updateCriteriaRange(ref criteria.BeatDivisor, op, divisor); + break; + + case "status" when Enum.TryParse(value, true, out var statusValue): + updateCriteriaRange(ref criteria.OnlineStatus, op, statusValue); + break; + } + + query = query.Replace(match.ToString(), ""); + } + + criteria.SearchText = query; + } + + private static void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, float value, float tolerance = 0.05f) + { + updateCriteriaRange(ref range, op, value); + + switch (op) + { + case "=": + case ":": + range.Min = value - tolerance; + range.Max = value + tolerance; + break; + } + } + + private static void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05) + { + updateCriteriaRange(ref range, op, value); + + switch (op) + { + case "=": + case ":": + range.Min = value - tolerance; + range.Max = value + tolerance; + break; + } + } + + private static void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value) + where T : struct, IComparable + { + switch (op) + { + default: + return; + + case "=": + case ":": + range.IsInclusive = true; + range.Min = value; + range.Max = value; + break; + + case ">": + range.IsInclusive = false; + range.Min = value; + break; + + case ">=": + case ">:": + range.IsInclusive = true; + range.Min = value; + break; + + case "<": + range.IsInclusive = false; + range.Max = value; + break; + + case "<=": + case "<:": + range.IsInclusive = true; + range.Max = value; + break; + } + } + } +} From dddd94684bd233e1377211d086e0f47c736fb934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 20 Sep 2019 21:34:38 +0200 Subject: [PATCH 3099/5608] Split out lower and upper interval inclusivity A single IsInclusive field causes unexpected issues when trying to formulate a half-open interval query. Split out IsInclusive into two fields, Is{Lower,Upper}Inclusive and update usages accordingly. --- osu.Game/Screens/Select/FilterCriteria.cs | 10 ++++++---- osu.Game/Screens/Select/FilterQueryParser.cs | 10 +++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index a3fa1b10ca..97a7f12724 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -53,7 +53,7 @@ namespace osu.Game.Screens.Select if (comparison < 0) return false; - if (comparison == 0 && !IsInclusive) + if (comparison == 0 && !IsLowerInclusive) return false; } @@ -64,7 +64,7 @@ namespace osu.Game.Screens.Select if (comparison > 0) return false; - if (comparison == 0 && !IsInclusive) + if (comparison == 0 && !IsUpperInclusive) return false; } @@ -73,12 +73,14 @@ namespace osu.Game.Screens.Select public T? Min; public T? Max; - public bool IsInclusive; + public bool IsLowerInclusive; + public bool IsUpperInclusive; public bool Equals(OptionalRange other) => Min.Equals(other.Min) && Max.Equals(other.Max) - && IsInclusive.Equals(other.IsInclusive); + && IsLowerInclusive.Equals(other.IsLowerInclusive) + && IsUpperInclusive.Equals(other.IsUpperInclusive); } } } diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 4e2b591fc9..800f1afd03 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -106,30 +106,30 @@ namespace osu.Game.Screens.Select case "=": case ":": - range.IsInclusive = true; + range.IsLowerInclusive = range.IsUpperInclusive = true; range.Min = value; range.Max = value; break; case ">": - range.IsInclusive = false; + range.IsLowerInclusive = false; range.Min = value; break; case ">=": case ">:": - range.IsInclusive = true; + range.IsLowerInclusive = true; range.Min = value; break; case "<": - range.IsInclusive = false; + range.IsUpperInclusive = false; range.Max = value; break; case "<=": case "<:": - range.IsInclusive = true; + range.IsUpperInclusive = true; range.Max = value; break; } From f5f5094611257f50fc778becf402105868e9757f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 20 Sep 2019 22:10:46 +0200 Subject: [PATCH 3100/5608] Take culture into account when parsing filters Culture was not taken into account when parsing filters, which meant that in cultures that use the comma (,) as a decimal delimiter, it would conflict with the comma used to delimit search criteria. To remove any ambiguity, introduce local helper functions that allow the decimal point to be utilised, using the invariant culture. This also matches stable behaviour. The decision to not reuse osu.Game.Beatmaps.Formats.Parsing was deliberate due to differing semantics (it's not really sane to throw exceptions on receiving user-facing input). --- osu.Game/Screens/Select/FilterQueryParser.cs | 24 ++++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 800f1afd03..d6d19c8650 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Globalization; using System.Text.RegularExpressions; using osu.Game.Beatmaps; @@ -23,27 +24,27 @@ namespace osu.Game.Screens.Select switch (key) { - case "stars" when float.TryParse(value, out var stars): + case "stars" when parseFloatWithPoint(value, out var stars): updateCriteriaRange(ref criteria.StarDifficulty, op, stars); break; - case "ar" when float.TryParse(value, out var ar): + case "ar" when parseFloatWithPoint(value, out var ar): updateCriteriaRange(ref criteria.ApproachRate, op, ar); break; - case "dr" when float.TryParse(value, out var dr): + case "dr" when parseFloatWithPoint(value, out var dr): updateCriteriaRange(ref criteria.DrainRate, op, dr); break; - case "cs" when float.TryParse(value, out var cs): + case "cs" when parseFloatWithPoint(value, out var cs): updateCriteriaRange(ref criteria.CircleSize, op, cs); break; - case "bpm" when double.TryParse(value, out var bpm): + case "bpm" when parseDoubleWithPoint(value, out var bpm): updateCriteriaRange(ref criteria.BPM, op, bpm); break; - case "length" when double.TryParse(value.TrimEnd('m', 's', 'h'), out var length): + case "length" when parseDoubleWithPoint(value.TrimEnd('m', 's', 'h'), out var length): var scale = value.EndsWith("ms") ? 1 : value.EndsWith("s") ? 1000 : @@ -53,7 +54,7 @@ namespace osu.Game.Screens.Select updateCriteriaRange(ref criteria.Length, op, length * scale, scale / 2.0); break; - case "divisor" when int.TryParse(value, out var divisor): + case "divisor" when parseInt(value, out var divisor): updateCriteriaRange(ref criteria.BeatDivisor, op, divisor); break; @@ -68,6 +69,15 @@ namespace osu.Game.Screens.Select criteria.SearchText = query; } + private static bool parseFloatWithPoint(string value, out float result) => + float.TryParse(value, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result); + + private static bool parseDoubleWithPoint(string value, out double result) => + double.TryParse(value, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result); + + private static bool parseInt(string value, out int result) => + int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out result); + private static void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, float value, float tolerance = 0.05f) { updateCriteriaRange(ref range, op, value); From d11d932a8747273f56f4128dbcf8b31bd6a329c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 20 Sep 2019 22:19:45 +0200 Subject: [PATCH 3101/5608] Add filter parsing tests Introduce unit tests covering parsing for the originally introduced filtering features. The introduced improvements (lower and upper interval and decimal point support) also tested. --- .../Filtering/FilterQueryParserTest.cs | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs new file mode 100644 index 0000000000..f98ad1fc43 --- /dev/null +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -0,0 +1,129 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Screens.Select; + +namespace osu.Game.Tests.NonVisual.Filtering +{ + [TestFixture] + public class FilterQueryParserTest + { + [Test] + public void TestApplyQueriesBareWords() + { + const string query = "looking for a beatmap"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual("looking for a beatmap", filterCriteria.SearchText); + Assert.AreEqual(4, filterCriteria.SearchTerms.Length); + } + + [Test] + public void TestApplyStarQueries() + { + const string query = "stars<4 easy"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual("easy", filterCriteria.SearchText.Trim()); + Assert.AreEqual(1, filterCriteria.SearchTerms.Length); + Assert.AreEqual(4.0f, filterCriteria.StarDifficulty.Max); + Assert.IsFalse(filterCriteria.StarDifficulty.IsUpperInclusive); + Assert.IsNull(filterCriteria.StarDifficulty.Min); + } + + [Test] + public void TestApplyApproachRateQueries() + { + const string query = "ar>=9 difficult"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual("difficult", filterCriteria.SearchText.Trim()); + Assert.AreEqual(1, filterCriteria.SearchTerms.Length); + Assert.AreEqual(9.0f, filterCriteria.ApproachRate.Min); + Assert.IsTrue(filterCriteria.ApproachRate.IsLowerInclusive); + Assert.IsNull(filterCriteria.ApproachRate.Max); + } + + [Test] + public void TestApplyDrainRateQueries() + { + const string query = "dr>2 quite specific dr<:6"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual("quite specific", filterCriteria.SearchText.Trim()); + Assert.AreEqual(2, filterCriteria.SearchTerms.Length); + Assert.AreEqual(2.0f, filterCriteria.DrainRate.Min); + Assert.IsFalse(filterCriteria.DrainRate.IsLowerInclusive); + Assert.AreEqual(6.0f, filterCriteria.DrainRate.Max); + Assert.IsTrue(filterCriteria.DrainRate.IsUpperInclusive); + } + + [Test] + public void TestApplyBPMQueries() + { + const string query = "bpm>:200 gotta go fast"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual("gotta go fast", filterCriteria.SearchText.Trim()); + Assert.AreEqual(3, filterCriteria.SearchTerms.Length); + Assert.AreEqual(200d, filterCriteria.BPM.Min); + Assert.IsTrue(filterCriteria.BPM.IsLowerInclusive); + Assert.IsNull(filterCriteria.BPM.Max); + } + + private static object[] lengthQueryExamples = + { + new object[] { "6ms", TimeSpan.FromMilliseconds(6), TimeSpan.FromMilliseconds(1) }, + new object[] { "23s", TimeSpan.FromSeconds(23), TimeSpan.FromSeconds(1) }, + new object[] { "9m", TimeSpan.FromMinutes(9), TimeSpan.FromMinutes(1) }, + new object[] { "0.25h", TimeSpan.FromHours(0.25), TimeSpan.FromHours(1) }, + new object[] { "70", TimeSpan.FromSeconds(70), TimeSpan.FromSeconds(1) }, + }; + + [Test] + [TestCaseSource(nameof(lengthQueryExamples))] + public void TestApplyLengthQueries(string lengthQuery, TimeSpan expectedLength, TimeSpan scale) + { + string query = $"length={lengthQuery} time"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual("time", filterCriteria.SearchText.Trim()); + Assert.AreEqual(1, filterCriteria.SearchTerms.Length); + Assert.AreEqual(expectedLength.TotalMilliseconds - scale.TotalMilliseconds / 2.0, filterCriteria.Length.Min); + Assert.IsTrue(filterCriteria.Length.IsLowerInclusive); + Assert.AreEqual(expectedLength.TotalMilliseconds + scale.TotalMilliseconds / 2.0, filterCriteria.Length.Max); + Assert.IsTrue(filterCriteria.Length.IsUpperInclusive); + } + + [Test] + public void TestApplyDivisorQueries() + { + const string query = "that's a time signature alright! divisor:12"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual("that's a time signature alright!", filterCriteria.SearchText.Trim()); + Assert.AreEqual(5, filterCriteria.SearchTerms.Length); + Assert.AreEqual(12, filterCriteria.BeatDivisor.Min); + Assert.IsTrue(filterCriteria.BeatDivisor.IsLowerInclusive); + Assert.AreEqual(12, filterCriteria.BeatDivisor.Max); + Assert.IsTrue(filterCriteria.BeatDivisor.IsUpperInclusive); + } + + [Test] + public void TestApplyStatusQueries() + { + const string query = "I want the pp status=ranked"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual("I want the pp", filterCriteria.SearchText.Trim()); + Assert.AreEqual(4, filterCriteria.SearchTerms.Length); + Assert.AreEqual(BeatmapSetOnlineStatus.Ranked, filterCriteria.OnlineStatus.Min); + Assert.IsTrue(filterCriteria.OnlineStatus.IsLowerInclusive); + Assert.AreEqual(BeatmapSetOnlineStatus.Ranked, filterCriteria.OnlineStatus.Max); + Assert.IsTrue(filterCriteria.OnlineStatus.IsUpperInclusive); + } + } +} From 41569fd2b63f82aa5a19f4f026120d0d2f2717ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 20 Sep 2019 22:48:30 +0200 Subject: [PATCH 3102/5608] Add filter evaluating unit tests Introduce unit tests covering the actual evaluation of filters for beatmaps. Partially covers most scenarios. --- .../NonVisual/Filtering/FilterMatchingTest.cs | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs new file mode 100644 index 0000000000..24e735310d --- /dev/null +++ b/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs @@ -0,0 +1,136 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Screens.Select; +using osu.Game.Screens.Select.Carousel; + +namespace osu.Game.Tests.NonVisual.Filtering +{ + [TestFixture] + public class FilterMatchingTest + { + private readonly BeatmapInfo exampleBeatmapInfo = new BeatmapInfo + { + Ruleset = new RulesetInfo { ID = 5 }, + StarDifficulty = 4.0d, + BaseDifficulty = new BeatmapDifficulty + { + ApproachRate = 5.0f, + DrainRate = 3.0f, + CircleSize = 2.0f, + }, + Metadata = new BeatmapMetadata + { + Artist = "The Artist", + ArtistUnicode = "The Artist", + Title = "Title goes here", + TitleUnicode = "Title goes here", + AuthorString = "Author", + Source = "unit tests", + Tags = "look for tags too", + }, + Version = "version as well", + Length = 2500, + BPM = 160, + BeatDivisor = 12, + Status = BeatmapSetOnlineStatus.Loved + }; + + [Test] + public void TestCriteriaMatchingNoRuleset() + { + var criteria = new FilterCriteria(); + var carouselItem = new CarouselBeatmap(exampleBeatmapInfo); + carouselItem.Filter(criteria); + Assert.IsFalse(carouselItem.Filtered.Value); + } + + [Test] + public void TestCriteriaMatchingSpecificRuleset() + { + var criteria = new FilterCriteria + { + Ruleset = new RulesetInfo { ID = 6 } + }; + var carouselItem = new CarouselBeatmap(exampleBeatmapInfo); + carouselItem.Filter(criteria); + Assert.IsTrue(carouselItem.Filtered.Value); + } + + [Test] + public void TestCriteriaMatchingConvertedBeatmaps() + { + var criteria = new FilterCriteria + { + Ruleset = new RulesetInfo { ID = 6 }, + AllowConvertedBeatmaps = true + }; + var carouselItem = new CarouselBeatmap(exampleBeatmapInfo); + carouselItem.Filter(criteria); + Assert.IsFalse(carouselItem.Filtered.Value); + } + + [Test] + [TestCase(true)] + [TestCase(false)] + public void TestCriteriaMatchingRangeMin(bool inclusive) + { + var criteria = new FilterCriteria + { + Ruleset = new RulesetInfo { ID = 6 }, + AllowConvertedBeatmaps = true, + ApproachRate = new FilterCriteria.OptionalRange + { + IsLowerInclusive = inclusive, + Min = 5.0f + } + }; + var carouselItem = new CarouselBeatmap(exampleBeatmapInfo); + carouselItem.Filter(criteria); + Assert.AreEqual(!inclusive, carouselItem.Filtered.Value); + } + + [Test] + [TestCase(true)] + [TestCase(false)] + public void TestCriteriaMatchingRangeMax(bool inclusive) + { + var criteria = new FilterCriteria + { + Ruleset = new RulesetInfo { ID = 6 }, + AllowConvertedBeatmaps = true, + BPM = new FilterCriteria.OptionalRange + { + IsUpperInclusive = inclusive, + Max = 160d + } + }; + var carouselItem = new CarouselBeatmap(exampleBeatmapInfo); + carouselItem.Filter(criteria); + Assert.AreEqual(!inclusive, carouselItem.Filtered.Value); + } + + [Test] + [TestCase("artist", false)] + [TestCase("artist title author", false)] + [TestCase("an artist", true)] + [TestCase("tags too", false)] + [TestCase("version", false)] + [TestCase("an auteur", true)] + public void TestCriteriaMatchingTerms(string terms, bool filtered) + { + var criteria = new FilterCriteria + { + Ruleset = new RulesetInfo { ID = 6 }, + AllowConvertedBeatmaps = true, + SearchText = terms + }; + var carouselItem = new CarouselBeatmap(exampleBeatmapInfo); + carouselItem.Filter(criteria); + Assert.AreEqual(filtered, carouselItem.Filtered.Value); + } + } +} From 51509f6be03523771e61269311086d6fdb49c7ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 20 Sep 2019 23:06:20 +0200 Subject: [PATCH 3103/5608] Add filter steps to carousel visual test Just a couple of steps for added coverage in visual tests. Very on-the-surface, the unit tests are supposed to cover the gory details. --- .../Visual/SongSelect/TestSceneBeatmapCarousel.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 6669ec7da3..71399106f4 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -242,6 +242,21 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); AddAssert("Selection is non-null", () => currentSelection != null); + + setSelected(1, 3); + AddStep("Apply a range filter", () => carousel.Filter(new FilterCriteria + { + SearchText = "#3", + StarDifficulty = new FilterCriteria.OptionalRange + { + Min = 2, + Max = 5.5, + IsLowerInclusive = true + } + }, false)); + checkSelected(3, 2); + + AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); } /// From b262ba13cd5d2ea1c9a908bd542f7c28758299fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 21 Sep 2019 23:16:23 +0200 Subject: [PATCH 3104/5608] Add creator= and artist= filters To match stable, add creator= and artist= filters to the beatmap carousel on song select screen. Contrary to stable, this implementation supports phrase queries with spaces within using double quotes. The quote handling is not entirely correct (can't nest), but quotes should rarely happen within names, and it is an edge case of an edge case - leaving best-effort as is. Test coverage also included. --- .../NonVisual/Filtering/FilterMatchingTest.cs | 71 ++++++++++++++++++- .../Filtering/FilterQueryParserTest.cs | 44 ++++++++++++ .../Select/Carousel/CarouselBeatmap.cs | 4 ++ osu.Game/Screens/Select/FilterCriteria.cs | 21 ++++++ osu.Game/Screens/Select/FilterQueryParser.cs | 21 +++++- 5 files changed, 157 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs index 24e735310d..30686cb947 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs @@ -12,7 +12,7 @@ namespace osu.Game.Tests.NonVisual.Filtering [TestFixture] public class FilterMatchingTest { - private readonly BeatmapInfo exampleBeatmapInfo = new BeatmapInfo + private BeatmapInfo getExampleBeatmap() => new BeatmapInfo { Ruleset = new RulesetInfo { ID = 5 }, StarDifficulty = 4.0d, @@ -25,10 +25,10 @@ namespace osu.Game.Tests.NonVisual.Filtering Metadata = new BeatmapMetadata { Artist = "The Artist", - ArtistUnicode = "The Artist", + ArtistUnicode = "check unicode too", Title = "Title goes here", TitleUnicode = "Title goes here", - AuthorString = "Author", + AuthorString = "The Author", Source = "unit tests", Tags = "look for tags too", }, @@ -42,6 +42,7 @@ namespace osu.Game.Tests.NonVisual.Filtering [Test] public void TestCriteriaMatchingNoRuleset() { + var exampleBeatmapInfo = getExampleBeatmap(); var criteria = new FilterCriteria(); var carouselItem = new CarouselBeatmap(exampleBeatmapInfo); carouselItem.Filter(criteria); @@ -51,6 +52,7 @@ namespace osu.Game.Tests.NonVisual.Filtering [Test] public void TestCriteriaMatchingSpecificRuleset() { + var exampleBeatmapInfo = getExampleBeatmap(); var criteria = new FilterCriteria { Ruleset = new RulesetInfo { ID = 6 } @@ -63,6 +65,7 @@ namespace osu.Game.Tests.NonVisual.Filtering [Test] public void TestCriteriaMatchingConvertedBeatmaps() { + var exampleBeatmapInfo = getExampleBeatmap(); var criteria = new FilterCriteria { Ruleset = new RulesetInfo { ID = 6 }, @@ -78,6 +81,7 @@ namespace osu.Game.Tests.NonVisual.Filtering [TestCase(false)] public void TestCriteriaMatchingRangeMin(bool inclusive) { + var exampleBeatmapInfo = getExampleBeatmap(); var criteria = new FilterCriteria { Ruleset = new RulesetInfo { ID = 6 }, @@ -98,6 +102,7 @@ namespace osu.Game.Tests.NonVisual.Filtering [TestCase(false)] public void TestCriteriaMatchingRangeMax(bool inclusive) { + var exampleBeatmapInfo = getExampleBeatmap(); var criteria = new FilterCriteria { Ruleset = new RulesetInfo { ID = 6 }, @@ -122,6 +127,7 @@ namespace osu.Game.Tests.NonVisual.Filtering [TestCase("an auteur", true)] public void TestCriteriaMatchingTerms(string terms, bool filtered) { + var exampleBeatmapInfo = getExampleBeatmap(); var criteria = new FilterCriteria { Ruleset = new RulesetInfo { ID = 6 }, @@ -132,5 +138,64 @@ namespace osu.Game.Tests.NonVisual.Filtering carouselItem.Filter(criteria); Assert.AreEqual(filtered, carouselItem.Filtered.Value); } + + [Test] + [TestCase("", false)] + [TestCase("The", false)] + [TestCase("THE", false)] + [TestCase("author", false)] + [TestCase("the author", false)] + [TestCase("the author AND then something else", true)] + [TestCase("unknown", true)] + public void TestCriteriaMatchingCreator(string creatorName, bool filtered) + { + var exampleBeatmapInfo = getExampleBeatmap(); + var criteria = new FilterCriteria + { + Creator = new FilterCriteria.OptionalTextFilter { SearchTerm = creatorName } + }; + var carouselItem = new CarouselBeatmap(exampleBeatmapInfo); + carouselItem.Filter(criteria); + Assert.AreEqual(filtered, carouselItem.Filtered.Value); + } + + [Test] + [TestCase("", false)] + [TestCase("The", false)] + [TestCase("THE", false)] + [TestCase("artist", false)] + [TestCase("the artist", false)] + [TestCase("the artist AND then something else", true)] + [TestCase("unicode too", false)] + [TestCase("unknown", true)] + public void TestCriteriaMatchingArtist(string artistName, bool filtered) + { + var exampleBeatmapInfo = getExampleBeatmap(); + var criteria = new FilterCriteria + { + Artist = new FilterCriteria.OptionalTextFilter { SearchTerm = artistName } + }; + var carouselItem = new CarouselBeatmap(exampleBeatmapInfo); + carouselItem.Filter(criteria); + Assert.AreEqual(filtered, carouselItem.Filtered.Value); + } + + [Test] + [TestCase("", false)] + [TestCase("artist", false)] + [TestCase("unknown", true)] + public void TestCriteriaMatchingArtistWithNullUnicodeName(string artistName, bool filtered) + { + var exampleBeatmapInfo = getExampleBeatmap(); + exampleBeatmapInfo.Metadata.ArtistUnicode = null; + + var criteria = new FilterCriteria + { + Artist = new FilterCriteria.OptionalTextFilter { SearchTerm = artistName } + }; + var carouselItem = new CarouselBeatmap(exampleBeatmapInfo); + carouselItem.Filter(criteria); + Assert.AreEqual(filtered, carouselItem.Filtered.Value); + } } } diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index f98ad1fc43..daab690a84 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -125,5 +125,49 @@ namespace osu.Game.Tests.NonVisual.Filtering Assert.AreEqual(BeatmapSetOnlineStatus.Ranked, filterCriteria.OnlineStatus.Max); Assert.IsTrue(filterCriteria.OnlineStatus.IsUpperInclusive); } + + [Test] + public void TestApplyCreatorQueries() + { + const string query = "beatmap specifically by creator=my_fav"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual("beatmap specifically by", filterCriteria.SearchText.Trim()); + Assert.AreEqual(3, filterCriteria.SearchTerms.Length); + Assert.AreEqual("my_fav", filterCriteria.Creator.SearchTerm); + } + + [Test] + public void TestApplyArtistQueries() + { + const string query = "find me songs by artist=singer please"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual("find me songs by please", filterCriteria.SearchText.Trim()); + Assert.AreEqual(5, filterCriteria.SearchTerms.Length); + Assert.AreEqual("singer", filterCriteria.Artist.SearchTerm); + } + + [Test] + public void TestApplyArtistQueriesWithSpaces() + { + const string query = "really like artist=\"name with space\" yes"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual("really like yes", filterCriteria.SearchText.Trim()); + Assert.AreEqual(3, filterCriteria.SearchTerms.Length); + Assert.AreEqual("name with space", filterCriteria.Artist.SearchTerm); + } + + [Test] + public void TestApplyArtistQueriesOneDoubleQuote() + { + const string query = "weird artist=double\"quote"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual("weird", filterCriteria.SearchText.Trim()); + Assert.AreEqual(1, filterCriteria.SearchTerms.Length); + Assert.AreEqual("double\"quote", filterCriteria.Artist.SearchTerm); + } } } diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 9cc84c8bdd..6c3c9d20f3 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -39,6 +39,10 @@ namespace osu.Game.Screens.Select.Carousel match &= criteria.BeatDivisor.IsInRange(Beatmap.BeatDivisor); match &= criteria.OnlineStatus.IsInRange(Beatmap.Status); + match &= criteria.Creator.Matches(Beatmap.Metadata.AuthorString); + match &= criteria.Artist.Matches(Beatmap.Metadata.Artist) || + criteria.Artist.Matches(Beatmap.Metadata.ArtistUnicode); + if (match) foreach (var criteriaTerm in criteria.SearchTerms) match &= diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 97a7f12724..c2cbac905e 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -23,6 +23,8 @@ namespace osu.Game.Screens.Select public OptionalRange BPM; public OptionalRange BeatDivisor; public OptionalRange OnlineStatus; + public OptionalTextFilter Creator; + public OptionalTextFilter Artist; public string[] SearchTerms = Array.Empty(); @@ -82,5 +84,24 @@ namespace osu.Game.Screens.Select && IsLowerInclusive.Equals(other.IsLowerInclusive) && IsUpperInclusive.Equals(other.IsUpperInclusive); } + + public struct OptionalTextFilter : IEquatable + { + public bool Matches(string value) + { + if (string.IsNullOrEmpty(SearchTerm)) + return true; + + // search term is guaranteed to be non-empty, so if the string we're comparing is empty, it's not matching + if (string.IsNullOrEmpty(value)) + return false; + + return value.IndexOf(SearchTerm, StringComparison.InvariantCultureIgnoreCase) >= 0; + } + + public string SearchTerm; + + public bool Equals(OptionalTextFilter other) => SearchTerm?.Equals(other.SearchTerm) ?? true; + } } } diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index d6d19c8650..b9281c5d6f 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -11,7 +11,7 @@ namespace osu.Game.Screens.Select internal static class FilterQueryParser { private static readonly Regex query_syntax_regex = new Regex( - @"\b(?stars|ar|dr|cs|divisor|length|objects|bpm|status)(?[=:><]+)(?\S*)", + @"\b(?stars|ar|dr|cs|divisor|length|objects|bpm|status|creator|artist)(?[=:><]+)(?("".*"")|(\S*))", RegexOptions.Compiled | RegexOptions.IgnoreCase); internal static void ApplyQueries(FilterCriteria criteria, string query) @@ -61,6 +61,14 @@ namespace osu.Game.Screens.Select case "status" when Enum.TryParse(value, true, out var statusValue): updateCriteriaRange(ref criteria.OnlineStatus, op, statusValue); break; + + case "creator": + updateCriteriaText(ref criteria.Creator, op, value); + break; + + case "artist": + updateCriteriaText(ref criteria.Artist, op, value); + break; } query = query.Replace(match.ToString(), ""); @@ -78,6 +86,17 @@ namespace osu.Game.Screens.Select private static bool parseInt(string value, out int result) => int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out result); + private static void updateCriteriaText(ref FilterCriteria.OptionalTextFilter textFilter, string op, string value) + { + switch (op) + { + case "=": + case ":": + textFilter.SearchTerm = value.Trim('"'); + break; + } + } + private static void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, float value, float tolerance = 0.05f) { updateCriteriaRange(ref range, op, value); From 70842f71f4b54484ea1ef22c19379950c2a01a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 22 Sep 2019 00:11:13 +0200 Subject: [PATCH 3105/5608] Fix floating point handling in filter intervals Due to floating-point rounding and representation errors, filters could wrongly display results incongruous with the wedge display text (ie. a beatmap with the BPM of 139.99999 would be displayed as having 140 BPM and also pass the bpm<140 filter). Apply tolerance when parsing floating-point constraints. The tolerance chosen is half of what the UI displays for the particular values (so for example half of 0.1 for AR/DR/CS, 0.01 for stars, etc.) Tests updated accordingly. --- .../Filtering/FilterQueryParserTest.cs | 35 ++++++++---- osu.Game/Screens/Select/FilterQueryParser.cs | 56 ++++++++++++++++--- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index daab690a84..9869ddde41 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -21,6 +21,16 @@ namespace osu.Game.Tests.NonVisual.Filtering Assert.AreEqual(4, filterCriteria.SearchTerms.Length); } + /* + * The following tests have been written a bit strangely (they don't check exact + * bound equality with what the filter says). + * This is to account for floating-point arithmetic issues. + * For example, specifying a bpm<140 filter would previously match beatmaps with BPM + * of 139.99999, which would be displayed in the UI as 140. + * Due to this the tests check the last tick inside the range and the first tick + * outside of the range. + */ + [Test] public void TestApplyStarQueries() { @@ -29,8 +39,9 @@ namespace osu.Game.Tests.NonVisual.Filtering FilterQueryParser.ApplyQueries(filterCriteria, query); Assert.AreEqual("easy", filterCriteria.SearchText.Trim()); Assert.AreEqual(1, filterCriteria.SearchTerms.Length); - Assert.AreEqual(4.0f, filterCriteria.StarDifficulty.Max); - Assert.IsFalse(filterCriteria.StarDifficulty.IsUpperInclusive); + Assert.IsNotNull(filterCriteria.StarDifficulty.Max); + Assert.Greater(filterCriteria.StarDifficulty.Max, 3.99d); + Assert.Less(filterCriteria.StarDifficulty.Max, 4.00d); Assert.IsNull(filterCriteria.StarDifficulty.Min); } @@ -42,8 +53,9 @@ namespace osu.Game.Tests.NonVisual.Filtering FilterQueryParser.ApplyQueries(filterCriteria, query); Assert.AreEqual("difficult", filterCriteria.SearchText.Trim()); Assert.AreEqual(1, filterCriteria.SearchTerms.Length); - Assert.AreEqual(9.0f, filterCriteria.ApproachRate.Min); - Assert.IsTrue(filterCriteria.ApproachRate.IsLowerInclusive); + Assert.IsNotNull(filterCriteria.ApproachRate.Min); + Assert.Greater(filterCriteria.ApproachRate.Min, 8.9f); + Assert.Less(filterCriteria.ApproachRate.Min, 9.0f); Assert.IsNull(filterCriteria.ApproachRate.Max); } @@ -55,10 +67,10 @@ namespace osu.Game.Tests.NonVisual.Filtering FilterQueryParser.ApplyQueries(filterCriteria, query); Assert.AreEqual("quite specific", filterCriteria.SearchText.Trim()); Assert.AreEqual(2, filterCriteria.SearchTerms.Length); - Assert.AreEqual(2.0f, filterCriteria.DrainRate.Min); - Assert.IsFalse(filterCriteria.DrainRate.IsLowerInclusive); - Assert.AreEqual(6.0f, filterCriteria.DrainRate.Max); - Assert.IsTrue(filterCriteria.DrainRate.IsUpperInclusive); + Assert.Greater(filterCriteria.DrainRate.Min, 2.0f); + Assert.Less(filterCriteria.DrainRate.Min, 2.1f); + Assert.Greater(filterCriteria.DrainRate.Max, 6.0f); + Assert.Less(filterCriteria.DrainRate.Min, 6.1f); } [Test] @@ -69,8 +81,9 @@ namespace osu.Game.Tests.NonVisual.Filtering FilterQueryParser.ApplyQueries(filterCriteria, query); Assert.AreEqual("gotta go fast", filterCriteria.SearchText.Trim()); Assert.AreEqual(3, filterCriteria.SearchTerms.Length); - Assert.AreEqual(200d, filterCriteria.BPM.Min); - Assert.IsTrue(filterCriteria.BPM.IsLowerInclusive); + Assert.IsNotNull(filterCriteria.BPM.Min); + Assert.Greater(filterCriteria.BPM.Min, 199.99d); + Assert.Less(filterCriteria.BPM.Min, 200.00d); Assert.IsNull(filterCriteria.BPM.Max); } @@ -93,9 +106,7 @@ namespace osu.Game.Tests.NonVisual.Filtering Assert.AreEqual("time", filterCriteria.SearchText.Trim()); Assert.AreEqual(1, filterCriteria.SearchTerms.Length); Assert.AreEqual(expectedLength.TotalMilliseconds - scale.TotalMilliseconds / 2.0, filterCriteria.Length.Min); - Assert.IsTrue(filterCriteria.Length.IsLowerInclusive); Assert.AreEqual(expectedLength.TotalMilliseconds + scale.TotalMilliseconds / 2.0, filterCriteria.Length.Max); - Assert.IsTrue(filterCriteria.Length.IsUpperInclusive); } [Test] diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index b9281c5d6f..3ee704201e 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -25,23 +25,23 @@ namespace osu.Game.Screens.Select switch (key) { case "stars" when parseFloatWithPoint(value, out var stars): - updateCriteriaRange(ref criteria.StarDifficulty, op, stars); + updateCriteriaRange(ref criteria.StarDifficulty, op, stars, 0.01f / 2); break; case "ar" when parseFloatWithPoint(value, out var ar): - updateCriteriaRange(ref criteria.ApproachRate, op, ar); + updateCriteriaRange(ref criteria.ApproachRate, op, ar, 0.1f / 2); break; case "dr" when parseFloatWithPoint(value, out var dr): - updateCriteriaRange(ref criteria.DrainRate, op, dr); + updateCriteriaRange(ref criteria.DrainRate, op, dr, 0.1f / 2); break; case "cs" when parseFloatWithPoint(value, out var cs): - updateCriteriaRange(ref criteria.CircleSize, op, cs); + updateCriteriaRange(ref criteria.CircleSize, op, cs, 0.1f / 2); break; case "bpm" when parseDoubleWithPoint(value, out var bpm): - updateCriteriaRange(ref criteria.BPM, op, bpm); + updateCriteriaRange(ref criteria.BPM, op, bpm, 0.01d / 2); break; case "length" when parseDoubleWithPoint(value.TrimEnd('m', 's', 'h'), out var length): @@ -99,29 +99,67 @@ namespace osu.Game.Screens.Select private static void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, float value, float tolerance = 0.05f) { - updateCriteriaRange(ref range, op, value); - switch (op) { + default: + return; + case "=": case ":": range.Min = value - tolerance; range.Max = value + tolerance; break; + + case ">": + range.Min = value + tolerance; + break; + + case ">=": + case ">:": + range.Min = value - tolerance; + break; + + case "<": + range.Max = value - tolerance; + break; + + case "<=": + case "<:": + range.Max = value + tolerance; + break; } } private static void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05) { - updateCriteriaRange(ref range, op, value); - switch (op) { + default: + return; + case "=": case ":": range.Min = value - tolerance; range.Max = value + tolerance; break; + + case ">": + range.Min = value + tolerance; + break; + + case ">=": + case ">:": + range.Min = value - tolerance; + break; + + case "<": + range.Max = value - tolerance; + break; + + case "<=": + case "<:": + range.Max = value + tolerance; + break; } } From fc1d49631a934437b24ccab3014aa31f2c06f579 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Sep 2019 20:30:58 +0900 Subject: [PATCH 3106/5608] Allow top-level menu key pressed to progress the osu! logo --- osu.Game/Screens/Menu/Button.cs | 7 ++++--- osu.Game/Screens/Menu/ButtonSystem.cs | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index 1bf25a2504..ffeadb96c7 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -31,6 +31,8 @@ namespace osu.Game.Screens.Menu { public event Action StateChanged; + public readonly Key TriggerKey; + private readonly Container iconText; private readonly Container box; private readonly Box boxHoverLayer; @@ -43,7 +45,6 @@ namespace osu.Game.Screens.Menu public ButtonSystemState VisibleState = ButtonSystemState.TopLevel; private readonly Action clickAction; - private readonly Key triggerKey; private SampleChannel sampleClick; private SampleChannel sampleHover; @@ -53,7 +54,7 @@ namespace osu.Game.Screens.Menu { this.sampleName = sampleName; this.clickAction = clickAction; - this.triggerKey = triggerKey; + TriggerKey = triggerKey; AutoSizeAxes = Axes.Both; Alpha = 0; @@ -210,7 +211,7 @@ namespace osu.Game.Screens.Menu if (e.Repeat || e.ControlPressed || e.ShiftPressed || e.AltPressed) return false; - if (triggerKey == e.Key && triggerKey != Key.Unknown) + if (TriggerKey == e.Key && TriggerKey != Key.Unknown) { trigger(); return true; diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 1a3e1213b4..0dee478a4c 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -14,6 +14,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Threading; @@ -180,6 +181,20 @@ namespace osu.Game.Screens.Menu State = ButtonSystemState.Initial; } + protected override bool OnKeyDown(KeyDownEvent e) + { + if (State == ButtonSystemState.Initial) + { + if (buttonsTopLevel.Any(b => e.PressedKeys.Contains(b.TriggerKey))) + { + logo.Click(); + return true; + } + } + + return base.OnKeyDown(e); + } + public bool OnPressed(GlobalAction action) { switch (action) From e5b14ce74de34d23ce42913a3c24152d75022866 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Sep 2019 21:42:32 +0900 Subject: [PATCH 3107/5608] Add null check for safety Co-Authored-By: Salman Ahmed --- osu.Game/Screens/Menu/ButtonSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 0dee478a4c..7ac6b5c696 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -187,7 +187,7 @@ namespace osu.Game.Screens.Menu { if (buttonsTopLevel.Any(b => e.PressedKeys.Contains(b.TriggerKey))) { - logo.Click(); + logo?.Click(); return true; } } From 3b52e7c72408555fbf6d42d988033ef30bac7f0e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Sep 2019 02:10:04 +0900 Subject: [PATCH 3108/5608] Add boilerplate logic --- .../Screens/TestSceneSetupScreen.cs | 17 +++++++++++++++++ osu.Game.Tournament/Screens/SetupScreen.cs | 9 +++++++++ osu.Game.Tournament/TournamentSceneManager.cs | 2 ++ 3 files changed, 28 insertions(+) create mode 100644 osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs create mode 100644 osu.Game.Tournament/Screens/SetupScreen.cs diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs new file mode 100644 index 0000000000..650b4c5412 --- /dev/null +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Game.Tournament.Screens; + +namespace osu.Game.Tournament.Tests.Screens +{ + public class TestSceneSetupScreen : TournamentTestScene + { + [BackgroundDependencyLoader] + private void load() + { + Add(new SetupScreen()); + } + } +} diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs new file mode 100644 index 0000000000..a5e0e5927a --- /dev/null +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -0,0 +1,9 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Tournament.Screens +{ + public class SetupScreen : TournamentScreen + { + } +} diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 4c255be463..b1384023d3 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -106,6 +106,8 @@ namespace osu.Game.Tournament Direction = FillDirection.Vertical, Children = new Drawable[] { + new OsuButton { RelativeSizeAxes = Axes.X, Text = "Setup", Action = () => SetScreen(typeof(SetupScreen)) }, + new Container { RelativeSizeAxes = Axes.X, Height = 50 }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Team Editor", Action = () => SetScreen(typeof(TeamEditorScreen)) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Rounds Editor", Action = () => SetScreen(typeof(RoundEditorScreen)) }, new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) }, From 47a89231ad3da90ca774fb524a75cd61c68a4bbd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Sep 2019 04:15:02 +0900 Subject: [PATCH 3109/5608] Read from (and allow reloading) IPC source --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 186 +++++++++++---------- osu.Game.Tournament/Screens/SetupScreen.cs | 15 ++ 2 files changed, 117 insertions(+), 84 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 4fd858bd12..e05d96e098 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Platform.Windows; +using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; using osu.Game.Online.API; @@ -26,103 +27,120 @@ namespace osu.Game.Tournament.IPC [Resolved] protected RulesetStore Rulesets { get; private set; } + [Resolved] + private GameHost host { get; set; } + + [Resolved] + private LadderInfo ladder { get; set; } + private int lastBeatmapId; + private ScheduledDelegate scheduled; + + public Storage Storage { get; private set; } [BackgroundDependencyLoader] - private void load(LadderInfo ladder, GameHost host) + private void load() { - StableStorage stable; + LocateStableStorage(); + } + + public Storage LocateStableStorage() + { + scheduled?.Cancel(); + + Storage = null; try { - stable = new StableStorage(host as DesktopGameHost); + Storage = new StableStorage(host as DesktopGameHost); + + const string file_ipc_filename = "ipc.txt"; + const string file_ipc_state_filename = "ipc-state.txt"; + const string file_ipc_scores_filename = "ipc-scores.txt"; + const string file_ipc_channel_filename = "ipc-channel.txt"; + + if (Storage.Exists(file_ipc_filename)) + scheduled = Scheduler.AddDelayed(delegate + { + try + { + using (var stream = Storage.GetStream(file_ipc_filename)) + using (var sr = new StreamReader(stream)) + { + var beatmapId = int.Parse(sr.ReadLine()); + var mods = int.Parse(sr.ReadLine()); + + if (lastBeatmapId != beatmapId) + { + lastBeatmapId = beatmapId; + + var existing = ladder.CurrentMatch.Value?.Round.Value?.Beatmaps.FirstOrDefault(b => b.ID == beatmapId && b.BeatmapInfo != null); + + if (existing != null) + Beatmap.Value = existing.BeatmapInfo; + else + { + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); + req.Success += b => Beatmap.Value = b.ToBeatmap(Rulesets); + API.Queue(req); + } + } + + Mods.Value = (LegacyMods)mods; + } + } + catch + { + // file might be in use. + } + + try + { + using (var stream = Storage.GetStream(file_ipc_channel_filename)) + using (var sr = new StreamReader(stream)) + { + ChatChannel.Value = sr.ReadLine(); + } + } + catch (Exception) + { + // file might be in use. + } + + try + { + using (var stream = Storage.GetStream(file_ipc_state_filename)) + using (var sr = new StreamReader(stream)) + { + State.Value = (TourneyState)Enum.Parse(typeof(TourneyState), sr.ReadLine()); + } + } + catch (Exception) + { + // file might be in use. + } + + try + { + using (var stream = Storage.GetStream(file_ipc_scores_filename)) + using (var sr = new StreamReader(stream)) + { + Score1.Value = int.Parse(sr.ReadLine()); + Score2.Value = int.Parse(sr.ReadLine()); + } + } + catch (Exception) + { + // file might be in use. + } + }, 250, true); } catch (Exception e) { Logger.Error(e, "Stable installation could not be found; disabling file based IPC"); - return; } - const string file_ipc_filename = "ipc.txt"; - const string file_ipc_state_filename = "ipc-state.txt"; - const string file_ipc_scores_filename = "ipc-scores.txt"; - const string file_ipc_channel_filename = "ipc-channel.txt"; - - if (stable.Exists(file_ipc_filename)) - Scheduler.AddDelayed(delegate - { - try - { - using (var stream = stable.GetStream(file_ipc_filename)) - using (var sr = new StreamReader(stream)) - { - var beatmapId = int.Parse(sr.ReadLine()); - var mods = int.Parse(sr.ReadLine()); - - if (lastBeatmapId != beatmapId) - { - lastBeatmapId = beatmapId; - - var existing = ladder.CurrentMatch.Value?.Round.Value?.Beatmaps.FirstOrDefault(b => b.ID == beatmapId && b.BeatmapInfo != null); - - if (existing != null) - Beatmap.Value = existing.BeatmapInfo; - else - { - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId }); - req.Success += b => Beatmap.Value = b.ToBeatmap(Rulesets); - API.Queue(req); - } - } - - Mods.Value = (LegacyMods)mods; - } - } - catch - { - // file might be in use. - } - - try - { - using (var stream = stable.GetStream(file_ipc_channel_filename)) - using (var sr = new StreamReader(stream)) - { - ChatChannel.Value = sr.ReadLine(); - } - } - catch (Exception) - { - // file might be in use. - } - - try - { - using (var stream = stable.GetStream(file_ipc_state_filename)) - using (var sr = new StreamReader(stream)) - { - State.Value = (TourneyState)Enum.Parse(typeof(TourneyState), sr.ReadLine()); - } - } - catch (Exception) - { - // file might be in use. - } - - try - { - using (var stream = stable.GetStream(file_ipc_scores_filename)) - using (var sr = new StreamReader(stream)) - { - Score1.Value = int.Parse(sr.ReadLine()); - Score2.Value = int.Parse(sr.ReadLine()); - } - } - catch (Exception) - { - // file might be in use. - } - }, 250, true); + return Storage; } /// diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index a5e0e5927a..b75b0056ce 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -1,9 +1,24 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; +using osu.Framework.Graphics.Sprites; +using osu.Game.Tournament.IPC; + namespace osu.Game.Tournament.Screens { public class SetupScreen : TournamentScreen { + [Resolved] + private MatchIPCInfo ipc { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + AddInternal(new SpriteText + { + Text = (ipc as FileBasedIPC)?.Storage.GetFullPath(string.Empty) + }); + } } } From 96c0c80dc58622af64cba3b020b2434b60132bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 22 Sep 2019 21:20:50 +0200 Subject: [PATCH 3110/5608] Factor out methods in FilterQueryParser Factor FilterQueryParser.ApplyQueries into shorter methods to reduce method complexity. --- osu.Game/Screens/Select/FilterQueryParser.cs | 102 ++++++++++--------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 3ee704201e..ffe1258168 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -22,54 +22,7 @@ namespace osu.Game.Screens.Select var op = match.Groups["op"].Value; var value = match.Groups["value"].Value; - switch (key) - { - case "stars" when parseFloatWithPoint(value, out var stars): - updateCriteriaRange(ref criteria.StarDifficulty, op, stars, 0.01f / 2); - break; - - case "ar" when parseFloatWithPoint(value, out var ar): - updateCriteriaRange(ref criteria.ApproachRate, op, ar, 0.1f / 2); - break; - - case "dr" when parseFloatWithPoint(value, out var dr): - updateCriteriaRange(ref criteria.DrainRate, op, dr, 0.1f / 2); - break; - - case "cs" when parseFloatWithPoint(value, out var cs): - updateCriteriaRange(ref criteria.CircleSize, op, cs, 0.1f / 2); - break; - - case "bpm" when parseDoubleWithPoint(value, out var bpm): - updateCriteriaRange(ref criteria.BPM, op, bpm, 0.01d / 2); - break; - - case "length" when parseDoubleWithPoint(value.TrimEnd('m', 's', 'h'), out var length): - var scale = - value.EndsWith("ms") ? 1 : - value.EndsWith("s") ? 1000 : - value.EndsWith("m") ? 60000 : - value.EndsWith("h") ? 3600000 : 1000; - - updateCriteriaRange(ref criteria.Length, op, length * scale, scale / 2.0); - break; - - case "divisor" when parseInt(value, out var divisor): - updateCriteriaRange(ref criteria.BeatDivisor, op, divisor); - break; - - case "status" when Enum.TryParse(value, true, out var statusValue): - updateCriteriaRange(ref criteria.OnlineStatus, op, statusValue); - break; - - case "creator": - updateCriteriaText(ref criteria.Creator, op, value); - break; - - case "artist": - updateCriteriaText(ref criteria.Artist, op, value); - break; - } + parseKeywordCriteria(criteria, key, value, op); query = query.Replace(match.ToString(), ""); } @@ -77,6 +30,59 @@ namespace osu.Game.Screens.Select criteria.SearchText = query; } + private static void parseKeywordCriteria(FilterCriteria criteria, string key, string value, string op) + { + switch (key) + { + case "stars" when parseFloatWithPoint(value, out var stars): + updateCriteriaRange(ref criteria.StarDifficulty, op, stars, 0.01f / 2); + break; + + case "ar" when parseFloatWithPoint(value, out var ar): + updateCriteriaRange(ref criteria.ApproachRate, op, ar, 0.1f / 2); + break; + + case "dr" when parseFloatWithPoint(value, out var dr): + updateCriteriaRange(ref criteria.DrainRate, op, dr, 0.1f / 2); + break; + + case "cs" when parseFloatWithPoint(value, out var cs): + updateCriteriaRange(ref criteria.CircleSize, op, cs, 0.1f / 2); + break; + + case "bpm" when parseDoubleWithPoint(value, out var bpm): + updateCriteriaRange(ref criteria.BPM, op, bpm, 0.01d / 2); + break; + + case "length" when parseDoubleWithPoint(value.TrimEnd('m', 's', 'h'), out var length): + var scale = getLengthScale(value); + updateCriteriaRange(ref criteria.Length, op, length * scale, scale / 2.0); + break; + + case "divisor" when parseInt(value, out var divisor): + updateCriteriaRange(ref criteria.BeatDivisor, op, divisor); + break; + + case "status" when Enum.TryParse(value, true, out var statusValue): + updateCriteriaRange(ref criteria.OnlineStatus, op, statusValue); + break; + + case "creator": + updateCriteriaText(ref criteria.Creator, op, value); + break; + + case "artist": + updateCriteriaText(ref criteria.Artist, op, value); + break; + } + } + + private static int getLengthScale(string value) => + value.EndsWith("ms") ? 1 : + value.EndsWith("s") ? 1000 : + value.EndsWith("m") ? 60000 : + value.EndsWith("h") ? 3600000 : 1000; + private static bool parseFloatWithPoint(string value, out float result) => float.TryParse(value, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result); From e07aa94fc8701f0a2807ef04cbca20d26f75566c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Sep 2019 04:22:50 +0900 Subject: [PATCH 3111/5608] Allow reloading ipc source --- osu.Game.Tournament/Screens/SetupScreen.cs | 84 ++++++++++++++++++++-- 1 file changed, 80 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index b75b0056ce..992762431e 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -1,9 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; -using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Edit.Setup.Components.LabelledComponents; using osu.Game.Tournament.IPC; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Tournament.Screens { @@ -15,10 +22,79 @@ namespace osu.Game.Tournament.Screens [BackgroundDependencyLoader] private void load() { - AddInternal(new SpriteText + reload(); + } + + private void reload() + { + var fileBasedIpc = ipc as FileBasedIPC; + + InternalChildren = new Drawable[] { - Text = (ipc as FileBasedIPC)?.Storage.GetFullPath(string.Empty) - }); + new ActionableInfo + { + Label = "Current IPC source", + ButtonText = "Refresh", + Action = () => + { + fileBasedIpc?.LocateStableStorage(); + reload(); + }, + Value = fileBasedIpc?.Storage?.GetFullPath(string.Empty) ?? "Not found", + Failing = fileBasedIpc?.Storage == null, + Description = "The osu!stable installation which is currently being used as a data source. If a source is not found, make sure you have created an empty ipc.txt in your stable cutting-edge installation, and that it is registered as the default osu! install." + } + }; + } + + private class ActionableInfo : LabelledComponent + { + private OsuButton button; + + public ActionableInfo() + : base(true) + { + } + + public string ButtonText + { + set => button.Text = value; + } + + public string Value + { + set => valueText.Text = value; + } + + public bool Failing + { + set => valueText.Colour = value ? Color4.Red : Color4.White; + } + + public Action Action; + + private OsuSpriteText valueText; + + protected override Drawable CreateComponent() => new Container + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Children = new Drawable[] + { + valueText = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + button = new TriangleButton + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Size = new Vector2(100, 30), + Action = () => Action?.Invoke() + }, + } + }; } } } From b41ac543c5a4a4d31e783a4c802f80d25871a427 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Sep 2019 04:45:23 +0900 Subject: [PATCH 3112/5608] Allow changing logged in user --- osu.Game.Tournament/Screens/SetupScreen.cs | 44 ++++++++++++++++++- osu.Game.Tournament/TournamentSceneManager.cs | 1 + .../Sections/General/LoginSettings.cs | 4 +- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 992762431e..8ccb469b13 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -7,6 +7,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Overlays; using osu.Game.Screens.Edit.Setup.Components.LabelledComponents; using osu.Game.Tournament.IPC; using osuTK; @@ -16,12 +18,29 @@ namespace osu.Game.Tournament.Screens { public class SetupScreen : TournamentScreen { + private FillFlowContainer fillFlow; + + private LoginOverlay loginOverlay; + [Resolved] private MatchIPCInfo ipc { get; set; } + [Resolved] + private IAPIProvider api { get; set; } + [BackgroundDependencyLoader] private void load() { + InternalChild = fillFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = new MarginPadding(10), + Spacing = new Vector2(10), + }; + + api.LocalUser.BindValueChanged(_ => Schedule(reload)); reload(); } @@ -29,7 +48,7 @@ namespace osu.Game.Tournament.Screens { var fileBasedIpc = ipc as FileBasedIPC; - InternalChildren = new Drawable[] + fillFlow.Children = new Drawable[] { new ActionableInfo { @@ -43,6 +62,29 @@ namespace osu.Game.Tournament.Screens Value = fileBasedIpc?.Storage?.GetFullPath(string.Empty) ?? "Not found", Failing = fileBasedIpc?.Storage == null, Description = "The osu!stable installation which is currently being used as a data source. If a source is not found, make sure you have created an empty ipc.txt in your stable cutting-edge installation, and that it is registered as the default osu! install." + }, + new ActionableInfo + { + Label = "Current User", + ButtonText = "Change Login", + Action = () => + { + api.Logout(); + + if (loginOverlay == null) + { + AddInternal(loginOverlay = new LoginOverlay() + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }); + } + + loginOverlay.State.Value = Visibility.Visible; + }, + Value = api?.LocalUser.Value.Username, + Failing = api?.IsLoggedIn != true, + Description = "In order to access the API and display metadata, a login is required." } }; } diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index b1384023d3..58c6e3fee6 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -69,6 +69,7 @@ namespace osu.Game.Tournament RelativeSizeAxes = Axes.Both, Children = new Drawable[] { + new SetupScreen(), new ScheduleScreen(), new LadderScreen(), new LadderEditorScreen(), diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 66fec1ecf9..b02b1a5489 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.Settings.Sections.General api?.Register(this); } - public void APIStateChanged(IAPIProvider api, APIState state) + public void APIStateChanged(IAPIProvider api, APIState state) => Schedule(() => { form = null; @@ -184,7 +184,7 @@ namespace osu.Game.Overlays.Settings.Sections.General } if (form != null) GetContainingInputManager()?.ChangeFocus(form); - } + }); public override bool AcceptsFocus => true; From 4b7a42119119bbfdb03f7a458572a938714fdd30 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Sep 2019 04:47:51 +0900 Subject: [PATCH 3113/5608] Set setup screen as default when opening --- osu.Game.Tournament/TournamentSceneManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 58c6e3fee6..02ee1c8603 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -130,7 +130,7 @@ namespace osu.Game.Tournament }, }; - SetScreen(typeof(ScheduleScreen)); + SetScreen(typeof(SetupScreen)); } public void SetScreen(Type screenType) From bafb429e9b6ae8ddaf120089f0bf6e845d7c3fc2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Sep 2019 04:49:21 +0900 Subject: [PATCH 3114/5608] Don't show video background --- osu.Game.Tournament/Screens/SetupScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 8ccb469b13..1cb4917790 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens { - public class SetupScreen : TournamentScreen + public class SetupScreen : TournamentScreen, IProvideVideo { private FillFlowContainer fillFlow; @@ -73,7 +73,7 @@ namespace osu.Game.Tournament.Screens if (loginOverlay == null) { - AddInternal(loginOverlay = new LoginOverlay() + AddInternal(loginOverlay = new LoginOverlay { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, From c92545e294d61ad151aac2197d1bb0882bf8d73d Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Mon, 23 Sep 2019 01:41:59 +0200 Subject: [PATCH 3115/5608] Update osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs Co-Authored-By: Salman Ahmed --- osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index dc099b14b9..36c8ecf020 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual.Gameplay /// Sets the input manager child to a new test player loader container instance. /// /// If the test player should behave like the production one. - public void ResetPlayer(bool interactive) + private void resetPlayer(bool interactive) { player = new TestPlayer(interactive, interactive); loader = new TestPlayerLoader(() => player); From e3e245ab20456afd2cf5a4b700a103c73ff9b79f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 23 Sep 2019 08:15:27 +0300 Subject: [PATCH 3116/5608] Introduce SessionStatics --- osu.Game/Configuration/SessionStatics.cs | 21 +++++++++++++++++++++ osu.Game/OsuGameBase.cs | 1 + 2 files changed, 22 insertions(+) create mode 100644 osu.Game/Configuration/SessionStatics.cs diff --git a/osu.Game/Configuration/SessionStatics.cs b/osu.Game/Configuration/SessionStatics.cs new file mode 100644 index 0000000000..9afb1bda36 --- /dev/null +++ b/osu.Game/Configuration/SessionStatics.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Configuration; + +namespace osu.Game.Configuration +{ + public class SessionStatics : ConfigManager + { + // This is an in-memory store. + protected override void PerformLoad() + { + } + + protected override bool PerformSave() => true; + } + + public enum Statics + { + } +} diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index d6b8ad3e67..b79de0aa94 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -189,6 +189,7 @@ namespace osu.Game dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); dependencies.Cache(RulesetConfigCache = new RulesetConfigCache(SettingsStore)); + dependencies.Cache(new SessionStatics()); dependencies.Cache(new OsuColour()); fileImporters.Add(BeatmapManager); From 5024770544999feda8849f7463102b1db5fe2283 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Mon, 23 Sep 2019 20:52:44 +0800 Subject: [PATCH 3117/5608] move common logic to IntroScreen --- osu.Game/Screens/Menu/IntroCircles.cs | 74 ++++++----------------- osu.Game/Screens/Menu/IntroScreen.cs | 80 +++++++++++++++++++++++-- osu.Game/Screens/Menu/IntroTriangles.cs | 65 ++++---------------- 3 files changed, 104 insertions(+), 115 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroCircles.cs b/osu.Game/Screens/Menu/IntroCircles.cs index c069f82134..d5d7f5cb7a 100644 --- a/osu.Game/Screens/Menu/IntroCircles.cs +++ b/osu.Game/Screens/Menu/IntroCircles.cs @@ -2,86 +2,46 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Audio.Sample; -using osu.Framework.Audio.Track; -using osu.Framework.Bindables; +using osu.Framework.Audio; using osu.Framework.Screens; using osu.Framework.Graphics; -using osu.Framework.MathUtils; -using osu.Game.Beatmaps; -using osu.Game.Configuration; -using osu.Game.IO.Archives; namespace osu.Game.Screens.Menu { public class IntroCircles : IntroScreen { - private const string menu_music_beatmap_hash = "3c8b1fcc9434dbb29e2fb613d3b9eada9d7bb6c125ceb32396c3b53437280c83"; + protected override string BeatmapHash => "3c8b1fcc9434dbb29e2fb613d3b9eada9d7bb6c125ceb32396c3b53437280c83"; - private SampleChannel welcome; - - private Bindable menuMusic; - - private Track track; - - private WorkingBeatmap introBeatmap; - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game, ISampleStore samples) - { - menuMusic = config.GetBindable(OsuSetting.MenuMusic); - - BeatmapSetInfo setInfo = null; - - if (!menuMusic.Value) - { - var sets = beatmaps.GetAllUsableBeatmapSets(); - if (sets.Count > 0) - setInfo = beatmaps.QueryBeatmapSet(s => s.ID == sets[RNG.Next(0, sets.Count - 1)].ID); - } - - if (setInfo == null) - { - setInfo = beatmaps.QueryBeatmapSet(b => b.Hash == menu_music_beatmap_hash); - - if (setInfo == null) - { - // we need to import the default menu background beatmap - setInfo = beatmaps.Import(new ZipArchiveReader(game.Resources.GetStream(@"Tracks/circles.osz"), "circles.osz")).Result; - - setInfo.Protected = true; - beatmaps.Update(setInfo); - } - } - - introBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); - track = introBeatmap.Track; - - if (config.Get(OsuSetting.MenuVoice)) - welcome = samples.Get(@"welcome"); - } + protected override string BeatmapFile => "circles.osz"; private const double delay_step_one = 2300; private const double delay_step_two = 600; + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + if (MenuVoice.Value) + SetWelcome(); + } + protected override void LogoArriving(OsuLogo logo, bool resuming) { base.LogoArriving(logo, resuming); if (!resuming) { - Beatmap.Value = introBeatmap; - introBeatmap = null; + Beatmap.Value = IntroBeatmap; + IntroBeatmap = null; - welcome?.Play(); + Welcome?.Play(); Scheduler.AddDelayed(delegate { // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Menu. - if (menuMusic.Value) + if (MenuMusic.Value) { - track.Restart(); - track = null; + Track.Restart(); + Track = null; } PrepareMenuLoad(); @@ -97,7 +57,7 @@ namespace osu.Game.Screens.Menu public override void OnSuspending(IScreen next) { - track = null; + Track = null; this.FadeOut(300); base.OnSuspending(next); diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 4d0f7ff87a..651fa7583d 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -4,12 +4,19 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.MathUtils; using osu.Framework.Screens; +using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.IO.Archives; using osu.Game.Screens.Backgrounds; +using osu.Game.Skinning; +using osu.Game.Online.API; +using osu.Game.Users; using osuTK; using osuTK.Graphics; @@ -17,6 +24,10 @@ namespace osu.Game.Screens.Menu { public abstract class IntroScreen : StartupScreen { + protected abstract string BeatmapHash { get; } + + protected abstract string BeatmapFile { get; } + private readonly BindableDouble exitingVolumeFade = new BindableDouble(1); public const int EXIT_DELAY = 3000; @@ -24,24 +35,83 @@ namespace osu.Game.Screens.Menu [Resolved] private AudioManager audio { get; set; } + protected SampleChannel Welcome; + private SampleChannel seeya; - private Bindable menuVoice; + protected Bindable MenuVoice; + + protected Bindable MenuMusic; + + protected Track Track; + + protected WorkingBeatmap IntroBeatmap; private LeasedBindable beatmap; public new Bindable Beatmap => beatmap; + protected Bindable User; + + protected Bindable Skin; + protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack(); [BackgroundDependencyLoader] - private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game) + private void load(OsuConfigManager config, IAPIProvider api, SkinManager skinManager, BeatmapManager beatmaps, Framework.Game game) { // prevent user from changing beatmap while the intro is still runnning. beatmap = base.Beatmap.BeginLease(false); - menuVoice = config.GetBindable(OsuSetting.MenuVoice); - seeya = audio.Samples.Get(@"seeya"); + MenuVoice = config.GetBindable(OsuSetting.MenuVoice); + MenuMusic = config.GetBindable(OsuSetting.MenuMusic); + + User = api.LocalUser.GetBoundCopy(); + Skin = skinManager.CurrentSkin.GetBoundCopy(); + + Skin.BindValueChanged(_ => updateSeeya(), true); + + BeatmapSetInfo setInfo = null; + + if (!MenuMusic.Value) + { + var sets = beatmaps.GetAllUsableBeatmapSets(); + if (sets.Count > 0) + setInfo = beatmaps.QueryBeatmapSet(s => s.ID == sets[RNG.Next(0, sets.Count - 1)].ID); + } + + if (setInfo == null) + { + setInfo = beatmaps.QueryBeatmapSet(b => b.Hash == BeatmapHash); + + if (setInfo == null) + { + // we need to import the default menu background beatmap + setInfo = beatmaps.Import(new ZipArchiveReader(game.Resources.GetStream($"Tracks/{BeatmapFile}"), BeatmapFile)).Result; + + setInfo.Protected = true; + beatmaps.Update(setInfo); + } + } + + IntroBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); + Track = IntroBeatmap.Track; + } + + private void updateSeeya() + { + if (User.Value?.IsSupporter ?? false) + seeya = Skin.Value.GetSample(new SampleInfo("seeya")) ?? audio.Samples.Get(@"seeya"); + else + seeya = audio.Samples.Get(@"seeya"); + } + + protected void SetWelcome() + { + if (User.Value?.IsSupporter ?? false) + Welcome = Skin.Value.GetSample(new SampleInfo("welcome")) ?? audio.Samples.Get(@"welcome"); + else + Welcome = audio.Samples.Get(@"welcome"); } /// @@ -61,7 +131,7 @@ namespace osu.Game.Screens.Menu double fadeOutTime = EXIT_DELAY; //we also handle the exit transition. - if (menuVoice.Value) + if (MenuVoice.Value) seeya.Play(); else fadeOutTime = 500; diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index db970dd76e..77700900a8 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -6,9 +6,6 @@ using System.Collections.Generic; using System.IO; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Audio.Sample; -using osu.Framework.Audio.Track; -using osu.Framework.Bindables; using osu.Framework.Screens; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -17,12 +14,9 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Video; using osu.Framework.MathUtils; using osu.Framework.Timing; -using osu.Game.Beatmaps; -using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.IO.Archives; using osu.Game.Rulesets; using osu.Game.Screens.Backgrounds; using osuTK; @@ -32,9 +26,9 @@ namespace osu.Game.Screens.Menu { public class IntroTriangles : IntroScreen { - private const string menu_music_beatmap_hash = "a1556d0801b3a6b175dda32ef546f0ec812b400499f575c44fccbe9c67f9b1e5"; + protected override string BeatmapHash => "a1556d0801b3a6b175dda32ef546f0ec812b400499f575c44fccbe9c67f9b1e5"; - private SampleChannel welcome; + protected override string BeatmapFile => "triangles.osz"; protected override BackgroundScreen CreateBackground() => background = new BackgroundScreenDefault(false) { @@ -44,48 +38,13 @@ namespace osu.Game.Screens.Menu [Resolved] private AudioManager audio { get; set; } - private Bindable menuMusic; - private Track track; - private WorkingBeatmap introBeatmap; - private BackgroundScreenDefault background; [BackgroundDependencyLoader] - private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game) + private void load(AudioManager audio) { - menuMusic = config.GetBindable(OsuSetting.MenuMusic); - - BeatmapSetInfo setInfo = null; - - if (!menuMusic.Value) - { - var sets = beatmaps.GetAllUsableBeatmapSets(); - if (sets.Count > 0) - setInfo = beatmaps.QueryBeatmapSet(s => s.ID == sets[RNG.Next(0, sets.Count - 1)].ID); - } - - if (setInfo == null) - { - setInfo = beatmaps.QueryBeatmapSet(b => b.Hash == menu_music_beatmap_hash); - - if (setInfo == null) - { - // we need to import the default menu background beatmap - setInfo = beatmaps.Import(new ZipArchiveReader(game.Resources.GetStream(@"Tracks/triangles.osz"), "triangles.osz")).Result; - - setInfo.Protected = true; - beatmaps.Update(setInfo); - } - } - - introBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); - - track = introBeatmap.Track; - track.Reset(); - - if (config.Get(OsuSetting.MenuVoice) && !menuMusic.Value) - // triangles has welcome sound included in the track. only play this if the user doesn't want menu music. - welcome = audio.Samples.Get(@"welcome"); + if (MenuVoice.Value && !MenuMusic.Value) + SetWelcome(); } protected override void LogoArriving(OsuLogo logo, bool resuming) @@ -96,24 +55,24 @@ namespace osu.Game.Screens.Menu if (!resuming) { - Beatmap.Value = introBeatmap; - introBeatmap = null; + Beatmap.Value = IntroBeatmap; + IntroBeatmap = null; PrepareMenuLoad(); LoadComponentAsync(new TrianglesIntroSequence(logo, background) { RelativeSizeAxes = Axes.Both, - Clock = new FramedClock(menuMusic.Value ? track : null), + Clock = new FramedClock(MenuMusic.Value ? Track : null), LoadMenu = LoadMenu }, t => { AddInternal(t); - welcome?.Play(); + Welcome?.Play(); // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Menu. - if (menuMusic.Value) - track.Start(); + if (MenuMusic.Value) + Track.Start(); }); } } @@ -126,7 +85,7 @@ namespace osu.Game.Screens.Menu public override void OnSuspending(IScreen next) { - track = null; + Track = null; base.OnSuspending(next); } From ffbab2535856f37dacdb6f49f494aa1ed20f3ccf Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 23 Sep 2019 16:12:43 +0300 Subject: [PATCH 3118/5608] Fix incorrect icon margin in ChangelogOverlay --- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 11dc2049fd..05bf56bc33 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -15,6 +15,7 @@ using osu.Game.Users; using osuTK.Graphics; using osu.Framework.Allocation; using System.Net; +using osuTK; namespace osu.Game.Overlays.Changelog { @@ -67,21 +68,31 @@ namespace osu.Game.Overlays.Changelog foreach (APIChangelogEntry entry in categoryEntries) { - LinkFlowContainer title = new LinkFlowContainer + LinkFlowContainer title; + + Container titleContainer = new Container { - Direction = FillDirection.Full, - RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, Margin = new MarginPadding { Vertical = 5 }, + Child = title = new LinkFlowContainer + { + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } }; var entryColour = entry.Major ? colours.YellowLight : Color4.White; - title.AddIcon(entry.Type == ChangelogEntryType.Fix ? FontAwesome.Solid.Check : FontAwesome.Solid.Plus, t => + titleContainer.Add(new SpriteIcon { - t.Font = fontSmall; - t.Colour = entryColour; - t.Padding = new MarginPadding { Left = -17, Right = 5 }; + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreRight, + Size = new Vector2(fontSmall.Size), + Icon = entry.Type == ChangelogEntryType.Fix ? FontAwesome.Solid.Check : FontAwesome.Solid.Plus, + Colour = entryColour, + Margin = new MarginPadding { Right = 5 }, }); title.AddText(entry.Title, t => @@ -139,7 +150,7 @@ namespace osu.Game.Overlays.Changelog t.Colour = entryColour; }); - ChangelogEntries.Add(title); + ChangelogEntries.Add(titleContainer); if (!string.IsNullOrEmpty(entry.MessageHtml)) { From 5c4dfe0809c6865adf8f8daec0756935200f1ee0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 23 Sep 2019 17:05:19 +0300 Subject: [PATCH 3119/5608] Apply suggested change --- osu.Game/Overlays/Changelog/ChangelogBuild.cs | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 05bf56bc33..bce1be5941 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -68,6 +68,8 @@ namespace osu.Game.Overlays.Changelog foreach (APIChangelogEntry entry in categoryEntries) { + var entryColour = entry.Major ? colours.YellowLight : Color4.White; + LinkFlowContainer title; Container titleContainer = new Container @@ -75,26 +77,26 @@ namespace osu.Game.Overlays.Changelog AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Margin = new MarginPadding { Vertical = 5 }, - Child = title = new LinkFlowContainer + Children = new Drawable[] { - Direction = FillDirection.Full, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, + new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreRight, + Size = new Vector2(fontSmall.Size), + Icon = entry.Type == ChangelogEntryType.Fix ? FontAwesome.Solid.Check : FontAwesome.Solid.Plus, + Colour = entryColour, + Margin = new MarginPadding { Right = 5 }, + }, + title = new LinkFlowContainer + { + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } } }; - var entryColour = entry.Major ? colours.YellowLight : Color4.White; - - titleContainer.Add(new SpriteIcon - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreRight, - Size = new Vector2(fontSmall.Size), - Icon = entry.Type == ChangelogEntryType.Fix ? FontAwesome.Solid.Check : FontAwesome.Solid.Plus, - Colour = entryColour, - Margin = new MarginPadding { Right = 5 }, - }); - title.AddText(entry.Title, t => { t.Font = fontLarge; From 8df77ffe924a36c750cc1a3d30216e038b57d06c Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Mon, 23 Sep 2019 16:48:30 +0200 Subject: [PATCH 3120/5608] Revert test scene changes --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 90 ++----------------- 1 file changed, 7 insertions(+), 83 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index dc099b14b9..ab519360ac 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -3,20 +3,14 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Threading; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; using osu.Framework.Screens; -using osu.Game.Graphics.Containers; -using osu.Game.Overlays; -using osu.Game.Overlays.Notifications; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; @@ -30,35 +24,19 @@ namespace osu.Game.Tests.Visual.Gameplay public class TestScenePlayerLoader : ManualInputManagerTestScene { private TestPlayerLoader loader; - private TestPlayerLoaderContainer container; - private TestPlayer player; - - [Resolved] - private AudioManager audioManager { get; set; } + private OsuScreenStack stack; [SetUp] public void Setup() => Schedule(() => { - ResetPlayer(false); + InputManager.Child = stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }; Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); }); - /// - /// Sets the input manager child to a new test player loader container instance. - /// - /// If the test player should behave like the production one. - public void ResetPlayer(bool interactive) - { - player = new TestPlayer(interactive, interactive); - loader = new TestPlayerLoader(() => player); - container = new TestPlayerLoaderContainer(loader); - InputManager.Child = container; - } - [Test] public void TestBlockLoadViaMouseMovement() { - AddStep("load dummy beatmap", () => ResetPlayer(false)); + AddStep("load dummy beatmap", () => stack.Push(loader = new TestPlayerLoader(() => new TestPlayer(false, false)))); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddRepeatStep("move mouse", () => InputManager.MoveMouseTo(loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft + (loader.VisualSettings.ScreenSpaceDrawQuad.BottomRight - loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft) * RNG.NextSingle()), 20); AddAssert("loader still active", () => loader.IsCurrentScreen()); @@ -71,13 +49,13 @@ namespace osu.Game.Tests.Visual.Gameplay Player player = null; SlowLoadPlayer slowPlayer = null; - AddStep("load dummy beatmap", () => ResetPlayer(false)); + AddStep("load dummy beatmap", () => stack.Push(loader = new TestPlayerLoader(() => player = new TestPlayer(false, false)))); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); AddUntilStep("wait for player to be current", () => player.IsCurrentScreen()); AddStep("load slow dummy beatmap", () => { - InputManager.Children = container = new TestPlayerLoaderContainer(loader = new TestPlayerLoader(() => slowPlayer = new SlowLoadPlayer(false, false))); + stack.Push(loader = new TestPlayerLoader(() => slowPlayer = new SlowLoadPlayer(false, false))); Scheduler.AddDelayed(() => slowPlayer.AllowLoad.Set(), 5000); }); @@ -87,6 +65,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestModReinstantiation() { + TestPlayer player = null; TestMod gameMod = null; TestMod playerMod1 = null; TestMod playerMod2 = null; @@ -94,7 +73,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("load player", () => { Mods.Value = new[] { gameMod = new TestMod() }; - ResetPlayer(true); + stack.Push(loader = new TestPlayerLoader(() => player = new TestPlayer())); }); AddUntilStep("wait for loader to become current", () => loader.IsCurrentScreen()); @@ -118,61 +97,6 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("player mods applied", () => playerMod2.Applied); } - [Test] - public void TestMutedNotification() - { - AddStep("set master volume to 0%", () => audioManager.Volume.Value = 0); - AddStep("reset notification lock", () => PlayerLoader.ResetNotificationLock()); - //AddStep("reset notification overlay", () => notificationOverlay); - AddStep("load player", () => ResetPlayer(false)); - AddUntilStep("wait for player", () => player.IsLoaded); - - AddAssert("check for notification", () => container.NotificationOverlay.UnreadCount.Value == 1); - AddAssert("click notification", () => - { - var scrollContainer = container.NotificationOverlay.Children.Last() as OsuScrollContainer; - var flowContainer = scrollContainer.Children.First() as FillFlowContainer; - return flowContainer.Children.First().First().Click(); - }); - AddAssert("check master volume", () => audioManager.Volume.IsDefault); - - AddStep("restart player", () => - { - var lastPlayer = player; - player = null; - lastPlayer.Restart(); - }); - } - - private class TestPlayerLoaderContainer : Container - { - private TestPlayerLoader loader; - - [Cached] - public NotificationOverlay NotificationOverlay { get; } = new NotificationOverlay - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - }; - - [Cached] - public VolumeOverlay VolumeOverlay { get; } = new VolumeOverlay - { - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - }; - - public TestPlayerLoaderContainer(TestPlayerLoader testPlayerLoader) - { - Children = new Drawable[] - { - loader = testPlayerLoader, - NotificationOverlay, - VolumeOverlay - }; - } - } - private class TestPlayerLoader : PlayerLoader { public new VisualSettings VisualSettings => base.VisualSettings; From 53603b559176e4ddbc62e5e3e9d54f67785b2d62 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2019 20:15:51 +0000 Subject: [PATCH 3121/5608] Bump System.ComponentModel.Annotations from 4.5.0 to 4.6.0 Bumps [System.ComponentModel.Annotations](https://github.com/dotnet/corefx) from 4.5.0 to 4.6.0. - [Release notes](https://github.com/dotnet/corefx/releases) - [Commits](https://github.com/dotnet/corefx/commits) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a27a94b8f9..a699217503 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -30,6 +30,6 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index a6516e6d1b..7803ea1e49 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -123,7 +123,7 @@ - + From 78ce62b187798d8e194c0c89ea6ee3a29154bc3b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2019 20:29:36 +0000 Subject: [PATCH 3122/5608] Bump System.IO.Packaging from 4.5.0 to 4.6.0 Bumps [System.IO.Packaging](https://github.com/dotnet/corefx) from 4.5.0 to 4.6.0. - [Release notes](https://github.com/dotnet/corefx/releases) - [Commits](https://github.com/dotnet/corefx/commits) Signed-off-by: dependabot-preview[bot] --- osu.Desktop/osu.Desktop.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 538aaf2d7a..03b002add7 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -26,7 +26,7 @@ - + From 50dcb70342c22f97398e9c45b2f7c8576f52807d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2019 21:04:20 +0000 Subject: [PATCH 3123/5608] Bump Microsoft.Win32.Registry from 4.5.0 to 4.6.0 Bumps [Microsoft.Win32.Registry](https://github.com/dotnet/corefx) from 4.5.0 to 4.6.0. - [Release notes](https://github.com/dotnet/corefx/releases) - [Commits](https://github.com/dotnet/corefx/commits) Signed-off-by: dependabot-preview[bot] --- osu.Desktop/osu.Desktop.csproj | 2 +- osu.Game.Tournament/osu.Game.Tournament.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 538aaf2d7a..9e8bb431c0 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -23,7 +23,7 @@ - + diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index 4790fcbcde..bddaff0a80 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -11,6 +11,6 @@ - + \ No newline at end of file From ec78889e94178357e1d18303ca0f7164f5e31955 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Tue, 24 Sep 2019 08:14:20 +0800 Subject: [PATCH 3124/5608] remove unused dependencies --- osu.Game/Screens/Menu/IntroCircles.cs | 3 +-- osu.Game/Screens/Menu/IntroTriangles.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroCircles.cs b/osu.Game/Screens/Menu/IntroCircles.cs index d5d7f5cb7a..a861d54663 100644 --- a/osu.Game/Screens/Menu/IntroCircles.cs +++ b/osu.Game/Screens/Menu/IntroCircles.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Audio; using osu.Framework.Screens; using osu.Framework.Graphics; @@ -18,7 +17,7 @@ namespace osu.Game.Screens.Menu private const double delay_step_two = 600; [BackgroundDependencyLoader] - private void load(AudioManager audio) + private void load() { if (MenuVoice.Value) SetWelcome(); diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index 77700900a8..5b49a81a5a 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Menu private BackgroundScreenDefault background; [BackgroundDependencyLoader] - private void load(AudioManager audio) + private void load() { if (MenuVoice.Value && !MenuMusic.Value) SetWelcome(); From 143d7ab640b588569e5dc31bd0d87f79b8a78401 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 24 Sep 2019 04:53:26 +0300 Subject: [PATCH 3125/5608] Add test scene for spinner rotation --- .../TestSceneSpinnerRotation.cs | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs new file mode 100644 index 0000000000..e9fa8e46ed --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -0,0 +1,104 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Logging; +using osu.Framework.MathUtils; +using osu.Framework.Testing; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Screens.Play; +using osu.Game.Tests.Visual; +using osuTK; +using System.Collections.Generic; +using System.Linq; +using static osu.Game.Tests.Visual.OsuTestScene.ClockBackedTestWorkingBeatmap; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestSceneSpinnerRotation : TestSceneOsuPlayer + { + [Resolved] + private AudioManager audioManager { get; set; } + + private TrackVirtualManual track; + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) + { + var working = new ClockBackedTestWorkingBeatmap(beatmap, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + track = (TrackVirtualManual)working.Track; + return working; + } + + private DrawableSpinner drawableSpinner; + + [SetUpSteps] + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)((TestPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.First()); + + // wait for frame stable clock time to hit 0 (for some reason, executing a seek while current time is below 0 doesn't seek successfully) + addSeekStep(0); + } + + [Test] + public void TestSpinnerRewindingRotation() + { + addSeekStep(5000); + AddAssert("is rotation absolute not almost 0", () => !Precision.AlmostEquals(drawableSpinner.Disc.RotationAbsolute, 0, 100)); + + addSeekStep(0); + AddAssert("is rotation absolute almost 0", () => Precision.AlmostEquals(drawableSpinner.Disc.RotationAbsolute, 0, 100)); + } + + [Test] + public void TestSpinnerMiddleRewindingRotation() + { + double estimatedRotation = 0; + + addSeekStep(5000); + AddStep("retrieve rotation", () => estimatedRotation = drawableSpinner.Disc.RotationAbsolute); + + addSeekStep(2500); + addSeekStep(5000); + AddAssert("is rotation absolute almost same", () => Precision.AlmostEquals(drawableSpinner.Disc.RotationAbsolute, estimatedRotation, 100)); + } + + private void addSeekStep(double time) + { + AddStep($"seek to {time}", () => track.Seek(time)); + + AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, ((TestPlayer)Player).DrawableRuleset.FrameStableClock.CurrentTime, 100)); + } + + protected override Player CreatePlayer(Ruleset ruleset) + { + Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); + return new TestPlayer(); + } + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap + { + HitObjects = new List + { + new Spinner + { + Position = new Vector2(256, 192), + EndTime = 5000, + }, + // placeholder object to avoid hitting the results screen + new HitObject + { + StartTime = 99999, + } + } + }; + } +} From ba679684be0aab707d545b111973253d5926f647 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 24 Sep 2019 04:59:57 +0300 Subject: [PATCH 3126/5608] Trim whitespaces --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index e9fa8e46ed..4b98e84866 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -83,7 +83,7 @@ namespace osu.Game.Rulesets.Osu.Tests Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); return new TestPlayer(); } - + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap { HitObjects = new List From 18fd7aa8055a406ceecd242a359a2ec6072dee10 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 24 Sep 2019 05:10:06 +0300 Subject: [PATCH 3127/5608] Remove redundant using directive --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index 4b98e84866..7e792f0b40 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -4,7 +4,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Logging; using osu.Framework.MathUtils; using osu.Framework.Testing; using osu.Framework.Timing; From 267e12ce3c0d88cab712d562a1c3f27dd6321fe3 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 24 Sep 2019 05:45:47 +0300 Subject: [PATCH 3128/5608] Add sample usage to the session statics --- osu.Game/Configuration/SessionStatics.cs | 1 + osu.Game/Screens/Menu/MainMenu.cs | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Configuration/SessionStatics.cs b/osu.Game/Configuration/SessionStatics.cs index 9afb1bda36..0c1ea1e568 100644 --- a/osu.Game/Configuration/SessionStatics.cs +++ b/osu.Game/Configuration/SessionStatics.cs @@ -17,5 +17,6 @@ namespace osu.Game.Configuration public enum Statics { + LoginOverlayDisplayed, } } diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index dd81569e26..1834221d35 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -52,6 +52,9 @@ namespace osu.Game.Screens.Menu [Resolved(canBeNull: true)] private LoginOverlay login { get; set; } + [Resolved] + private SessionStatics statics { get; set; } + [Resolved] private IAPIProvider api { get; set; } @@ -170,7 +173,6 @@ namespace osu.Game.Screens.Menu Beatmap.ValueChanged += beatmap_ValueChanged; } - private bool loginDisplayed; private bool exitConfirmed; protected override void LogoArriving(OsuLogo logo, bool resuming) @@ -198,10 +200,12 @@ namespace osu.Game.Screens.Menu bool displayLogin() { - if (!loginDisplayed) + var loginDisplayed = statics.GetBindable(Statics.LoginOverlayDisplayed); + + if (!loginDisplayed.Value) { Scheduler.AddDelayed(() => login?.Show(), 500); - loginDisplayed = true; + loginDisplayed.Value = true; } return true; From 4555ecc5e05d4c053e8a7822ca736c4328481e75 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 24 Sep 2019 15:09:08 +0900 Subject: [PATCH 3129/5608] Check for exact key --- osu.Game/Screens/Menu/ButtonSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 7ac6b5c696..ed8e4c70f9 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -185,7 +185,7 @@ namespace osu.Game.Screens.Menu { if (State == ButtonSystemState.Initial) { - if (buttonsTopLevel.Any(b => e.PressedKeys.Contains(b.TriggerKey))) + if (buttonsTopLevel.Any(b => e.Key == b.TriggerKey)) { logo?.Click(); return true; From 6e619fbd71ad8b5654e60ed7850b05ee0865f1a1 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2019 06:35:04 +0000 Subject: [PATCH 3130/5608] Bump ppy.osu.Framework from 2019.921.0 to 2019.924.0 Bumps [ppy.osu.Framework](https://github.com/ppy/osu-framework) from 2019.921.0 to 2019.924.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.921.0...2019.924.0) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a699217503..83632f3d41 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 7803ea1e49..29a12f3707 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,7 +118,7 @@ - + From 50efb4414f87a78b3fda6595056b6851389740f7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2019 06:35:31 +0000 Subject: [PATCH 3131/5608] Bump ppy.osu.Framework.Android from 2019.921.0 to 2019.924.0 Bumps [ppy.osu.Framework.Android](https://github.com/ppy/osu-framework) from 2019.921.0 to 2019.924.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.921.0...2019.924.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index c57fc342ba..46fd5424df 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ - + From 60c9519095313948a05c27ca04aece93a9f2d7fe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Sep 2019 16:21:37 +0900 Subject: [PATCH 3132/5608] Add proper signing and github release support --- fastlane/Fastfile | 48 +++++++++++++++++++++++++++++++++++++++++----- fastlane/README.md | 5 +++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 906d284bc9..7adf42a1eb 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -4,14 +4,12 @@ platform :android do desc 'Deploy to play store' lane :beta do |options| - # update csproj version update_version( - solution_path: 'osu.Android.sln', version: options[:version], build: options[:build], ) - build() + build(options) supply( apk: './osu.Android/bin/Release/sh.ppy.osulazer-Signed.apk', @@ -21,8 +19,35 @@ desc 'Deploy to play store' ) end + desc 'Deploy to github release' + lane :build_github do |options| + + update_version( + version: options[:version], + build: options[:build], + ) + + build(options) + + client = HTTPClient.new + changelog = client.get_content 'https://gist.githubusercontent.com/peppy/aaa2ec1a323554b619671cac6dbbb776/raw' + changelog.gsub!('$BUILD_ID', options[:build]) + + set_github_release( + repository_name: "ppy/osu", + api_token: ENV["GITHUB_TOKEN"], + name: options[:build], + tag_name: options[:build], + is_draft: true, + description: changelog, + commitish: "master", + upload_assets: ["osu.Android/bin/Release/sh.ppy.osulazer.apk"] + ) + + end + desc 'Compile the project' - lane :build do + lane :build do |options| nuget_restore( project_path: 'osu.Android.sln' ) @@ -31,11 +56,24 @@ desc 'Deploy to play store' build_configuration: 'Release', solution_path: 'osu.Android.sln', platform: "android", + output_path: "osu.Android/bin/Release/", + keystore_path: options[:keystore_path], + keystore_alias: options[:keystore_alias], + keystore_password: ENV["KEYSTORE_PASSWORD"] ) end lane :update_version do |options| - app_version(options) + + split = options[:build].split('.') + split[1] = split[1].to_s.rjust(4, '0') + android_build = split.join('') + + app_version( + solution_path: 'osu.Android.sln', + version: options[:version], + build: android_build, + ) end end diff --git a/fastlane/README.md b/fastlane/README.md index 6145620870..a400ed9516 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -21,6 +21,11 @@ or alternatively using `brew cask install fastlane` fastlane android beta ``` Deploy to play store +### android build_github +``` +fastlane android build_github +``` +Deploy to github release ### android build ``` fastlane android build From 1860c2f9cea07e13cbf8c81c4d23ba45f2732266 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Sep 2019 16:22:30 +0900 Subject: [PATCH 3133/5608] 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 c57fc342ba..46fd5424df 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a699217503..83632f3d41 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 7803ea1e49..30f1da362d 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From d08fc563707f1bfe010bc889cbb51ae824583da0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Sep 2019 16:33:48 +0900 Subject: [PATCH 3134/5608] Add apk download link in README --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 56491a4be4..aefeb2e96e 100644 --- a/README.md +++ b/README.md @@ -31,12 +31,10 @@ If you are not interested in developing the game, you can still consume our [bin **Latest build:** -| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) | -| ------------- | ------------- | +| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) | [iOS(iOS 10+)](https://testflight.apple.com/join/2tLcjWlF) | [Android (5+)](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) +| ------------- | ------------- | ------------- | ------------- | - **Linux** users are recommended to self-compile until we have official deployment in place. -- **iOS** users can join the [TestFlight beta program](https://testflight.apple.com/join/2tLcjWlF) (note that due to high demand this is regularly full). -- **Android** users can self-compile, and expect a public beta soon. If your platform is not listed above, there is still a chance you can manually build it by following the instructions below. From 315dcc81583ad8da74fb0ded9e8d64b7b5f22b4a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Sep 2019 16:42:05 +0900 Subject: [PATCH 3135/5608] Update fastlane --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index ac46fddb41..7df9c46482 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,7 +5,7 @@ GEM addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) atomos (0.1.3) - babosa (1.0.2) + babosa (1.0.3) claide (1.0.3) colored (1.2) colored2 (3.1.2) From 75cceb9e303568ab94b2ce416ac4791044010ac4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 24 Sep 2019 16:47:34 +0900 Subject: [PATCH 3136/5608] Fix LifetimeChanged being invoked before lifetime is set --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index b94de0df89..8d8f8a419f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -316,8 +316,8 @@ namespace osu.Game.Rulesets.Objects.Drawables get => lifetimeStart ?? (HitObject.StartTime - InitialLifetimeOffset); set { - base.LifetimeStart = value; lifetimeStart = value; + base.LifetimeStart = value; } } From af0c15a93c171c3559b6fafb344ac3376b7eb986 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 24 Sep 2019 16:48:39 +0900 Subject: [PATCH 3137/5608] Fix initial hitobject states not being recomputed correctly --- osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index bd1f496dfa..e00597dd56 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -77,6 +77,9 @@ namespace osu.Game.Rulesets.UI.Scrolling if (!initialStateCache.IsValid) { + foreach (var cached in hitObjectInitialStateCache.Values) + cached.Invalidate(); + switch (direction.Value) { case ScrollingDirection.Up: From 4abe0473b9093c8d6dd4f9d6e28364c7e34e3f89 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 24 Sep 2019 16:49:42 +0900 Subject: [PATCH 3138/5608] Fix relative beat length not considering slider multiplier --- .../TestSceneDrawableScrollingRuleset.cs | 16 ++++++++++++++++ .../UI/Scrolling/DrawableScrollingRuleset.cs | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index 60ace8ea69..86f7896457 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -115,6 +116,19 @@ namespace osu.Game.Tests.Visual.Gameplay assertPosition(4, 1f); } + [Test] + public void TestSliderMultiplierDoesnotAffectRelativeBeatLength() + { + var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range }); + beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2; + + createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); + AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 5000); + + for (int i = 0; i < 5; i++) + assertPosition(i, i / 5f); + } + private void assertPosition(int index, float relativeY) => AddAssert($"hitobject {index} at {relativeY}", () => Precision.AlmostEquals(drawableRuleset.Playfield.AllHitObjects.ElementAt(index).DrawPosition.Y, drawableRuleset.Playfield.HitObjectContainer.DrawHeight * relativeY)); @@ -193,6 +207,8 @@ namespace osu.Game.Tests.Visual.Gameplay protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping; + public new Bindable TimeRange => base.TimeRange; + public TestDrawableScrollingRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 64e491858b..3d56543bab 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -131,7 +131,7 @@ namespace osu.Game.Rulesets.UI.Scrolling if (duration > maxDuration) { maxDuration = duration; - baseBeatLength = timingPoints[i].BeatLength; + baseBeatLength = timingPoints[i].BeatLength / Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier; } } } From c6fe8587e3c6c023db6fe81f77a75ee4de33a612 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Sep 2019 17:45:45 +0900 Subject: [PATCH 3139/5608] Read build from VersionCode --- osu.Android/OsuGameAndroid.cs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/osu.Android/OsuGameAndroid.cs b/osu.Android/OsuGameAndroid.cs index d9bdd9c0c2..aca36b59aa 100644 --- a/osu.Android/OsuGameAndroid.cs +++ b/osu.Android/OsuGameAndroid.cs @@ -9,6 +9,23 @@ namespace osu.Android { public class OsuGameAndroid : OsuGame { - public override Version AssemblyVersion => new Version(Application.Context.ApplicationContext.PackageManager.GetPackageInfo(Application.Context.ApplicationContext.PackageName, 0).VersionName); + public override Version AssemblyVersion + { + get + { + string versionName = Application.Context.ApplicationContext.PackageManager.GetPackageInfo(Application.Context.ApplicationContext.PackageName, 0).VersionCode.ToString(); + + try + { + // undo play store version garbling + return new Version(int.Parse(versionName.Substring(0, 4)), int.Parse(versionName.Substring(4, 4)), int.Parse(versionName.Substring(8, 1))); + } + catch + { + } + + return new Version(versionName); + } + } } -} +} \ No newline at end of file From 1c474de0ed8cd3a9cf778340bba142efcf4780e1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Sep 2019 18:03:01 +0900 Subject: [PATCH 3140/5608] Move post-update notification logic to UpdateManager base class --- osu.Desktop/OsuGameDesktop.cs | 1 + osu.Desktop/Overlays/VersionManager.cs | 55 +-------------- osu.Desktop/Updater/SquirrelUpdateManager.cs | 2 +- .../Updater/SimpleUpdateManager.cs | 18 +++-- osu.Game/Updater/UpdateManager.cs | 67 +++++++++++++++++++ 5 files changed, 78 insertions(+), 65 deletions(-) rename {osu.Desktop => osu.Game}/Updater/SimpleUpdateManager.cs (87%) create mode 100644 osu.Game/Updater/UpdateManager.cs diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 761f52f961..7725ee6451 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -17,6 +17,7 @@ using osu.Framework.Logging; using osu.Framework.Platform.Windows; using osu.Framework.Screens; using osu.Game.Screens.Menu; +using osu.Game.Updater; namespace osu.Desktop { diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 51e801c185..6eed46867a 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -8,11 +8,8 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game; -using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Overlays; -using osu.Game.Overlays.Notifications; using osuTK; using osuTK.Graphics; @@ -20,17 +17,9 @@ namespace osu.Desktop.Overlays { public class VersionManager : OverlayContainer { - private OsuConfigManager config; - private OsuGameBase game; - private NotificationOverlay notificationOverlay; - [BackgroundDependencyLoader] - private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config) + private void load(OsuColour colours, TextureStore textures, OsuGameBase game) { - notificationOverlay = notification; - this.config = config; - this.game = game; - AutoSizeAxes = Axes.Both; Anchor = Anchor.BottomCentre; Origin = Anchor.BottomCentre; @@ -85,48 +74,6 @@ namespace osu.Desktop.Overlays }; } - protected override void LoadComplete() - { - base.LoadComplete(); - - var version = game.Version; - var lastVersion = config.Get(OsuSetting.Version); - - if (game.IsDeployedBuild && version != lastVersion) - { - config.Set(OsuSetting.Version, version); - - // only show a notification if we've previously saved a version to the config file (ie. not the first run). - if (!string.IsNullOrEmpty(lastVersion)) - notificationOverlay.Post(new UpdateCompleteNotification(version)); - } - } - - private class UpdateCompleteNotification : SimpleNotification - { - private readonly string version; - - public UpdateCompleteNotification(string version) - { - this.version = version; - Text = $"You are now running osu!lazer {version}.\nClick to see what's new!"; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours, ChangelogOverlay changelog, NotificationOverlay notificationOverlay) - { - Icon = FontAwesome.Solid.CheckSquare; - IconBackgound.Colour = colours.BlueDark; - - Activated = delegate - { - notificationOverlay.Hide(); - changelog.ShowBuild(OsuGameBase.CLIENT_STREAM_NAME, version); - return true; - }; - } - } - protected override void PopIn() { this.FadeIn(1400, Easing.OutQuint); diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index fa41c061b5..60b47a8b3a 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -20,7 +20,7 @@ using LogLevel = Splat.LogLevel; namespace osu.Desktop.Updater { - public class SquirrelUpdateManager : Component + public class SquirrelUpdateManager : osu.Game.Updater.UpdateManager { private UpdateManager updateManager; private NotificationOverlay notificationOverlay; diff --git a/osu.Desktop/Updater/SimpleUpdateManager.cs b/osu.Game/Updater/SimpleUpdateManager.cs similarity index 87% rename from osu.Desktop/Updater/SimpleUpdateManager.cs rename to osu.Game/Updater/SimpleUpdateManager.cs index 5184791de1..eec27d3325 100644 --- a/osu.Desktop/Updater/SimpleUpdateManager.cs +++ b/osu.Game/Updater/SimpleUpdateManager.cs @@ -6,31 +6,25 @@ using System.Threading.Tasks; using Newtonsoft.Json; using osu.Framework; using osu.Framework.Allocation; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.IO.Network; using osu.Framework.Platform; -using osu.Game; -using osu.Game.Overlays; using osu.Game.Overlays.Notifications; -namespace osu.Desktop.Updater +namespace osu.Game.Updater { /// /// An update manager that shows notifications if a newer release is detected. /// Installation is left up to the user. /// - internal class SimpleUpdateManager : CompositeDrawable + public class SimpleUpdateManager : UpdateManager { - private NotificationOverlay notificationOverlay; private string version; private GameHost host; [BackgroundDependencyLoader] - private void load(NotificationOverlay notification, OsuGameBase game, GameHost host) + private void load(OsuGameBase game, GameHost host) { - notificationOverlay = notification; - this.host = host; version = game.Version; @@ -50,7 +44,7 @@ namespace osu.Desktop.Updater if (latest.TagName != version) { - notificationOverlay.Post(new SimpleNotification + Notifications.Post(new SimpleNotification { Text = $"A newer release of osu! has been found ({version} → {latest.TagName}).\n\n" + "Click here to download the new version, which can be installed over the top of your existing installation", @@ -82,6 +76,10 @@ namespace osu.Desktop.Updater case RuntimeInfo.Platform.MacOsx: bestAsset = release.Assets?.Find(f => f.Name.EndsWith(".app.zip")); break; + + case RuntimeInfo.Platform.Android: + bestAsset = release.Assets?.Find(f => f.Name.EndsWith(".apk")); + break; } return bestAsset?.BrowserDownloadUrl ?? release.HtmlUrl; diff --git a/osu.Game/Updater/UpdateManager.cs b/osu.Game/Updater/UpdateManager.cs new file mode 100644 index 0000000000..cfca7dc858 --- /dev/null +++ b/osu.Game/Updater/UpdateManager.cs @@ -0,0 +1,67 @@ +// 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.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; +using osu.Game.Graphics; +using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; + +namespace osu.Game.Updater +{ + public abstract class UpdateManager : CompositeDrawable + { + [Resolved] + private OsuConfigManager config { get; set; } + + [Resolved] + private OsuGameBase game { get; set; } + + [Resolved] + protected NotificationOverlay Notifications { get; set; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + var version = game.Version; + var lastVersion = config.Get(OsuSetting.Version); + + if (game.IsDeployedBuild && version != lastVersion) + { + config.Set(OsuSetting.Version, version); + + // only show a notification if we've previously saved a version to the config file (ie. not the first run). + if (!string.IsNullOrEmpty(lastVersion)) + Notifications.Post(new UpdateCompleteNotification(version)); + } + } + + private class UpdateCompleteNotification : SimpleNotification + { + private readonly string version; + + public UpdateCompleteNotification(string version) + { + this.version = version; + Text = $"You are now running osu!lazer {version}.\nClick to see what's new!"; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, ChangelogOverlay changelog, NotificationOverlay notificationOverlay) + { + Icon = FontAwesome.Solid.CheckSquare; + IconBackgound.Colour = colours.BlueDark; + + Activated = delegate + { + notificationOverlay.Hide(); + changelog.ShowBuild(OsuGameBase.CLIENT_STREAM_NAME, version); + return true; + }; + } + } + } +} From 07ec163daa856235a5046d2428b2a924c41478bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Sep 2019 18:12:04 +0900 Subject: [PATCH 3141/5608] Fix version fallback logic --- osu.Android/OsuGameAndroid.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Android/OsuGameAndroid.cs b/osu.Android/OsuGameAndroid.cs index aca36b59aa..a91c010809 100644 --- a/osu.Android/OsuGameAndroid.cs +++ b/osu.Android/OsuGameAndroid.cs @@ -4,6 +4,7 @@ using System; using Android.App; using osu.Game; +using osu.Game.Updater; namespace osu.Android { @@ -13,10 +14,11 @@ namespace osu.Android { get { - string versionName = Application.Context.ApplicationContext.PackageManager.GetPackageInfo(Application.Context.ApplicationContext.PackageName, 0).VersionCode.ToString(); + var packageInfo = Application.Context.ApplicationContext.PackageManager.GetPackageInfo(Application.Context.ApplicationContext.PackageName, 0); try { + string versionName = packageInfo.VersionCode.ToString(); // undo play store version garbling return new Version(int.Parse(versionName.Substring(0, 4)), int.Parse(versionName.Substring(4, 4)), int.Parse(versionName.Substring(8, 1))); } @@ -24,8 +26,15 @@ namespace osu.Android { } - return new Version(versionName); + return new Version(packageInfo.VersionName); } } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Add(new SimpleUpdateManager()); + } } } \ No newline at end of file From 84d9f98ff1cfde97c4d51b264f11d7d226f243ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Sep 2019 18:15:57 +0900 Subject: [PATCH 3142/5608] fixup! Move post-update notification logic to UpdateManager base class --- osu.Game/Updater/UpdateManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Updater/UpdateManager.cs b/osu.Game/Updater/UpdateManager.cs index cfca7dc858..e256cdbe45 100644 --- a/osu.Game/Updater/UpdateManager.cs +++ b/osu.Game/Updater/UpdateManager.cs @@ -20,7 +20,7 @@ namespace osu.Game.Updater private OsuGameBase game { get; set; } [Resolved] - protected NotificationOverlay Notifications { get; set; } + protected NotificationOverlay Notifications { get; private set; } protected override void LoadComplete() { From df692b091c415ee0c9090d00698130368023626b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 24 Sep 2019 18:22:02 +0900 Subject: [PATCH 3143/5608] Make LabelledComponent generic --- .../UserInterface/TestSceneLabelledComponent.cs | 8 ++++---- osu.Game.Tournament/Screens/SetupScreen.cs | 2 +- .../LabelledComponents/LabelledComponent.cs | 11 ++++++----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs index 73e0191adb..a762d561c2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("create component", () => { - LabelledComponent component; + LabelledComponent component; Child = new Container { @@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual.UserInterface Origin = Anchor.Centre, Width = 500, AutoSizeAxes = Axes.Y, - Child = component = padded ? (LabelledComponent)new PaddedLabelledComponent() : new NonPaddedLabelledComponent(), + Child = component = padded ? (LabelledComponent)new PaddedLabelledComponent() : new NonPaddedLabelledComponent(), }; component.Label = "a sample component"; @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private class PaddedLabelledComponent : LabelledComponent + private class PaddedLabelledComponent : LabelledComponent { public PaddedLabelledComponent() : base(true) @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.UserInterface }; } - private class NonPaddedLabelledComponent : LabelledComponent + private class NonPaddedLabelledComponent : LabelledComponent { public NonPaddedLabelledComponent() : base(false) diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 1cb4917790..7a44e7a0e1 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -89,7 +89,7 @@ namespace osu.Game.Tournament.Screens }; } - private class ActionableInfo : LabelledComponent + private class ActionableInfo : LabelledComponent { private OsuButton button; diff --git a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs index 19e9c329d6..770065cb0e 100644 --- a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs +++ b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs @@ -11,7 +11,8 @@ using osuTK; namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents { - public abstract class LabelledComponent : CompositeDrawable + public abstract class LabelledComponent : CompositeDrawable + where T : Drawable { protected const float CONTENT_PADDING_VERTICAL = 10; protected const float CONTENT_PADDING_HORIZONTAL = 15; @@ -20,15 +21,15 @@ namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents /// /// The component that is being displayed. /// - protected readonly Drawable Component; + protected readonly T Component; private readonly OsuTextFlowContainer labelText; private readonly OsuTextFlowContainer descriptionText; /// - /// Creates a new . + /// Creates a new . /// - /// Whether the component should be padded or should be expanded to the bounds of this . + /// Whether the component should be padded or should be expanded to the bounds of this . protected LabelledComponent(bool padded) { RelativeSizeAxes = Axes.X; @@ -127,6 +128,6 @@ namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents /// Creates the component that should be displayed. /// /// The component. - protected abstract Drawable CreateComponent(); + protected abstract T CreateComponent(); } } From 6b702eb6de7820dcb4245db7f0fa737731bdf3f9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 24 Sep 2019 18:25:17 +0900 Subject: [PATCH 3144/5608] Update with generic labelledcomponent --- .../Visual/UserInterface/TestSceneLabelledTextBox.cs | 3 ++- .../Setup/Components/LabelledComponents/LabelledTextBox.cs | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs index f9a5369576..5c5b1262a6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Edit.Setup.Components.LabelledComponents; namespace osu.Game.Tests.Visual.UserInterface @@ -27,7 +28,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("create component", () => { - LabelledComponent component; + LabelledComponent component; Child = new Container { diff --git a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs index 992371fedf..67bacea9f8 100644 --- a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs +++ b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs @@ -9,12 +9,10 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents { - public class LabelledTextBox : LabelledComponent + public class LabelledTextBox : LabelledComponent { public event TextBox.OnCommitHandler OnCommit; - protected new OsuTextBox Component => (OsuTextBox)base.Component; - public LabelledTextBox() : base(false) { @@ -41,7 +39,7 @@ namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents Component.BorderColour = colours.Blue; } - protected override Drawable CreateComponent() => new OsuTextBox + protected override OsuTextBox CreateComponent() => new OsuTextBox { Anchor = Anchor.Centre, Origin = Anchor.Centre, From c226d52b53acbdb84003a736f81488b688b2f01a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Sep 2019 18:34:54 +0900 Subject: [PATCH 3145/5608] Don't automatic download for now --- osu.Game/Updater/SimpleUpdateManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Updater/SimpleUpdateManager.cs b/osu.Game/Updater/SimpleUpdateManager.cs index eec27d3325..4789ac94d2 100644 --- a/osu.Game/Updater/SimpleUpdateManager.cs +++ b/osu.Game/Updater/SimpleUpdateManager.cs @@ -78,7 +78,8 @@ namespace osu.Game.Updater break; case RuntimeInfo.Platform.Android: - bestAsset = release.Assets?.Find(f => f.Name.EndsWith(".apk")); + // on our testing device this causes the download to magically disappear. + //bestAsset = release.Assets?.Find(f => f.Name.EndsWith(".apk")); break; } From 42b60417639455df5bb6d53000f011ce86e38ee3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Sep 2019 18:03:01 +0900 Subject: [PATCH 3146/5608] Move post-update notification logic to UpdateManager base class --- osu.Desktop/OsuGameDesktop.cs | 1 + osu.Desktop/Overlays/VersionManager.cs | 55 +-------------- osu.Desktop/Updater/SquirrelUpdateManager.cs | 2 +- .../Updater/SimpleUpdateManager.cs | 18 +++-- osu.Game/Updater/UpdateManager.cs | 67 +++++++++++++++++++ 5 files changed, 78 insertions(+), 65 deletions(-) rename {osu.Desktop => osu.Game}/Updater/SimpleUpdateManager.cs (87%) create mode 100644 osu.Game/Updater/UpdateManager.cs diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 761f52f961..7725ee6451 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -17,6 +17,7 @@ using osu.Framework.Logging; using osu.Framework.Platform.Windows; using osu.Framework.Screens; using osu.Game.Screens.Menu; +using osu.Game.Updater; namespace osu.Desktop { diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 51e801c185..6eed46867a 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -8,11 +8,8 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game; -using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Overlays; -using osu.Game.Overlays.Notifications; using osuTK; using osuTK.Graphics; @@ -20,17 +17,9 @@ namespace osu.Desktop.Overlays { public class VersionManager : OverlayContainer { - private OsuConfigManager config; - private OsuGameBase game; - private NotificationOverlay notificationOverlay; - [BackgroundDependencyLoader] - private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config) + private void load(OsuColour colours, TextureStore textures, OsuGameBase game) { - notificationOverlay = notification; - this.config = config; - this.game = game; - AutoSizeAxes = Axes.Both; Anchor = Anchor.BottomCentre; Origin = Anchor.BottomCentre; @@ -85,48 +74,6 @@ namespace osu.Desktop.Overlays }; } - protected override void LoadComplete() - { - base.LoadComplete(); - - var version = game.Version; - var lastVersion = config.Get(OsuSetting.Version); - - if (game.IsDeployedBuild && version != lastVersion) - { - config.Set(OsuSetting.Version, version); - - // only show a notification if we've previously saved a version to the config file (ie. not the first run). - if (!string.IsNullOrEmpty(lastVersion)) - notificationOverlay.Post(new UpdateCompleteNotification(version)); - } - } - - private class UpdateCompleteNotification : SimpleNotification - { - private readonly string version; - - public UpdateCompleteNotification(string version) - { - this.version = version; - Text = $"You are now running osu!lazer {version}.\nClick to see what's new!"; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours, ChangelogOverlay changelog, NotificationOverlay notificationOverlay) - { - Icon = FontAwesome.Solid.CheckSquare; - IconBackgound.Colour = colours.BlueDark; - - Activated = delegate - { - notificationOverlay.Hide(); - changelog.ShowBuild(OsuGameBase.CLIENT_STREAM_NAME, version); - return true; - }; - } - } - protected override void PopIn() { this.FadeIn(1400, Easing.OutQuint); diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index fa41c061b5..60b47a8b3a 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -20,7 +20,7 @@ using LogLevel = Splat.LogLevel; namespace osu.Desktop.Updater { - public class SquirrelUpdateManager : Component + public class SquirrelUpdateManager : osu.Game.Updater.UpdateManager { private UpdateManager updateManager; private NotificationOverlay notificationOverlay; diff --git a/osu.Desktop/Updater/SimpleUpdateManager.cs b/osu.Game/Updater/SimpleUpdateManager.cs similarity index 87% rename from osu.Desktop/Updater/SimpleUpdateManager.cs rename to osu.Game/Updater/SimpleUpdateManager.cs index 5184791de1..eec27d3325 100644 --- a/osu.Desktop/Updater/SimpleUpdateManager.cs +++ b/osu.Game/Updater/SimpleUpdateManager.cs @@ -6,31 +6,25 @@ using System.Threading.Tasks; using Newtonsoft.Json; using osu.Framework; using osu.Framework.Allocation; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.IO.Network; using osu.Framework.Platform; -using osu.Game; -using osu.Game.Overlays; using osu.Game.Overlays.Notifications; -namespace osu.Desktop.Updater +namespace osu.Game.Updater { /// /// An update manager that shows notifications if a newer release is detected. /// Installation is left up to the user. /// - internal class SimpleUpdateManager : CompositeDrawable + public class SimpleUpdateManager : UpdateManager { - private NotificationOverlay notificationOverlay; private string version; private GameHost host; [BackgroundDependencyLoader] - private void load(NotificationOverlay notification, OsuGameBase game, GameHost host) + private void load(OsuGameBase game, GameHost host) { - notificationOverlay = notification; - this.host = host; version = game.Version; @@ -50,7 +44,7 @@ namespace osu.Desktop.Updater if (latest.TagName != version) { - notificationOverlay.Post(new SimpleNotification + Notifications.Post(new SimpleNotification { Text = $"A newer release of osu! has been found ({version} → {latest.TagName}).\n\n" + "Click here to download the new version, which can be installed over the top of your existing installation", @@ -82,6 +76,10 @@ namespace osu.Desktop.Updater case RuntimeInfo.Platform.MacOsx: bestAsset = release.Assets?.Find(f => f.Name.EndsWith(".app.zip")); break; + + case RuntimeInfo.Platform.Android: + bestAsset = release.Assets?.Find(f => f.Name.EndsWith(".apk")); + break; } return bestAsset?.BrowserDownloadUrl ?? release.HtmlUrl; diff --git a/osu.Game/Updater/UpdateManager.cs b/osu.Game/Updater/UpdateManager.cs new file mode 100644 index 0000000000..e256cdbe45 --- /dev/null +++ b/osu.Game/Updater/UpdateManager.cs @@ -0,0 +1,67 @@ +// 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.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; +using osu.Game.Graphics; +using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; + +namespace osu.Game.Updater +{ + public abstract class UpdateManager : CompositeDrawable + { + [Resolved] + private OsuConfigManager config { get; set; } + + [Resolved] + private OsuGameBase game { get; set; } + + [Resolved] + protected NotificationOverlay Notifications { get; private set; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + var version = game.Version; + var lastVersion = config.Get(OsuSetting.Version); + + if (game.IsDeployedBuild && version != lastVersion) + { + config.Set(OsuSetting.Version, version); + + // only show a notification if we've previously saved a version to the config file (ie. not the first run). + if (!string.IsNullOrEmpty(lastVersion)) + Notifications.Post(new UpdateCompleteNotification(version)); + } + } + + private class UpdateCompleteNotification : SimpleNotification + { + private readonly string version; + + public UpdateCompleteNotification(string version) + { + this.version = version; + Text = $"You are now running osu!lazer {version}.\nClick to see what's new!"; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, ChangelogOverlay changelog, NotificationOverlay notificationOverlay) + { + Icon = FontAwesome.Solid.CheckSquare; + IconBackgound.Colour = colours.BlueDark; + + Activated = delegate + { + notificationOverlay.Hide(); + changelog.ShowBuild(OsuGameBase.CLIENT_STREAM_NAME, version); + return true; + }; + } + } + } +} From 028c958431728deb42811a92a3993f2382ee49a6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Sep 2019 19:19:43 +0900 Subject: [PATCH 3147/5608] Initial implementation of a switch button --- .../UserInterface/TestSceneSwitchButton.cs | 20 +++ .../Graphics/UserInterface/SwitchButton.cs | 117 ++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs create mode 100644 osu.Game/Graphics/UserInterface/SwitchButton.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs new file mode 100644 index 0000000000..8fe381f141 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs @@ -0,0 +1,20 @@ +// 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.Graphics.UserInterface; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneSwitchButton : OsuTestScene + { + public TestSceneSwitchButton() + { + Child = new SwitchButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + } + } +} diff --git a/osu.Game/Graphics/UserInterface/SwitchButton.cs b/osu.Game/Graphics/UserInterface/SwitchButton.cs new file mode 100644 index 0000000000..21712051ef --- /dev/null +++ b/osu.Game/Graphics/UserInterface/SwitchButton.cs @@ -0,0 +1,117 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Graphics.UserInterface +{ + public class SwitchButton : Checkbox + { + private const float border_thickness = 4.5f; + private const float padding = 1.25f; + + private readonly Box fill; + private readonly Container switchContainer; + private readonly Drawable switchCircle; + private readonly CircularBorderContainer circularContainer; + + private Color4 enabledColour; + private Color4 disabledColour; + + public SwitchButton() + { + Size = new Vector2(45, 20); + + InternalChild = circularContainer = new CircularBorderContainer + { + RelativeSizeAxes = Axes.Both, + BorderColour = Color4.White, + BorderThickness = border_thickness, + Masking = true, + Children = new Drawable[] + { + fill = new Box + { + RelativeSizeAxes = Axes.Both, + AlwaysPresent = true, + Alpha = 0 + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(border_thickness + padding), + Child = switchContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Child = switchCircle = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + Masking = true, + Child = new Box { RelativeSizeAxes = Axes.Both } + } + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + enabledColour = colours.BlueDark; + disabledColour = colours.Gray3; + + switchContainer.Colour = enabledColour; + fill.Colour = disabledColour; + + updateBorder(); + } + + protected override void OnUserChange(bool value) + { + base.OnUserChange(value); + + if (value) + switchCircle.MoveToX(switchContainer.DrawWidth - switchCircle.DrawWidth, 200, Easing.OutQuint); + else + switchCircle.MoveToX(0, 200, Easing.OutQuint); + + fill.FadeTo(value ? 1 : 0, 250, Easing.OutQuint); + + updateBorder(); + } + + protected override bool OnHover(HoverEvent e) + { + updateBorder(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateBorder(); + base.OnHoverLost(e); + } + + private void updateBorder() + { + circularContainer.TransformBorderTo((Current.Value ? enabledColour : disabledColour).Lighten(IsHovered ? 0.3f : 0)); + } + + private class CircularBorderContainer : CircularContainer + { + public void TransformBorderTo(SRGBColour colour) + => this.TransformTo(nameof(BorderColour), colour, 250, Easing.OutQuint); + } + } +} From b8d147a3b41586c2e10556145a04aea69193e57a Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Tue, 24 Sep 2019 17:42:06 +0800 Subject: [PATCH 3148/5608] introduce main menu background modes --- osu.Game/Configuration/BackgroundMode.cs | 12 +++++++ osu.Game/Configuration/OsuConfigManager.cs | 5 ++- .../Graphics/Backgrounds/BeatmapBackground.cs | 28 ++++++++++++++++ .../Sections/Audio/MainMenuSettings.cs | 6 ++++ .../Backgrounds/BackgroundScreenBeatmap.cs | 17 ---------- .../Backgrounds/BackgroundScreenDefault.cs | 33 +++++++++++++++++-- 6 files changed, 80 insertions(+), 21 deletions(-) create mode 100644 osu.Game/Configuration/BackgroundMode.cs create mode 100644 osu.Game/Graphics/Backgrounds/BeatmapBackground.cs diff --git a/osu.Game/Configuration/BackgroundMode.cs b/osu.Game/Configuration/BackgroundMode.cs new file mode 100644 index 0000000000..21554891ca --- /dev/null +++ b/osu.Game/Configuration/BackgroundMode.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Configuration +{ + public enum BackgroundMode + { + Default, + Seasonal, + Beatmap + } +} diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 64b1f2d7bc..9b964e8893 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -117,6 +117,8 @@ namespace osu.Game.Configuration Set(OsuSetting.UIHoldActivationDelay, 200, 0, 500); Set(OsuSetting.IntroSequence, IntroSequence.Triangles); + + Set(OsuSetting.BackgroundMode, BackgroundMode.Default); } public OsuConfigManager(Storage storage) @@ -186,6 +188,7 @@ namespace osu.Game.Configuration UIScale, IntroSequence, UIHoldActivationDelay, - HitLighting + HitLighting, + BackgroundMode } } diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs new file mode 100644 index 0000000000..40c6dae43c --- /dev/null +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs @@ -0,0 +1,28 @@ +// 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.Textures; +using osu.Game.Beatmaps; + +namespace osu.Game.Graphics.Backgrounds +{ + public class BeatmapBackground : Background + { + public readonly WorkingBeatmap Beatmap; + + private readonly string fallbackTextureName; + + public BeatmapBackground(WorkingBeatmap beatmap, string fallbackTextureName = @"Backgrounds/bg1") + { + Beatmap = beatmap; + this.fallbackTextureName = fallbackTextureName; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Sprite.Texture = Beatmap?.Background ?? textures.Get(fallbackTextureName); + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs index 5ccdc952ba..76a6aafe45 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs @@ -34,6 +34,12 @@ namespace osu.Game.Overlays.Settings.Sections.Audio Bindable = config.GetBindable(OsuSetting.IntroSequence), Items = Enum.GetValues(typeof(IntroSequence)).Cast() }, + new SettingsDropdown + { + LabelText = "Background", + Bindable = config.GetBindable(OsuSetting.BackgroundMode), + Items = Enum.GetValues(typeof(BackgroundMode)).Cast() + } }; } } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 2730b0b90d..3de0ab191c 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -6,7 +6,6 @@ using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics.Backgrounds; @@ -107,22 +106,6 @@ namespace osu.Game.Screens.Backgrounds return base.Equals(other) && beatmap == otherBeatmapBackground.Beatmap; } - protected class BeatmapBackground : Background - { - public readonly WorkingBeatmap Beatmap; - - public BeatmapBackground(WorkingBeatmap beatmap) - { - Beatmap = beatmap; - } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - Sprite.Texture = Beatmap?.Background ?? textures.Get(@"Backgrounds/bg1"); - } - } - public class DimmableBackground : UserDimContainer { /// diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 2d7fe6a6a3..a8ba17ef49 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -6,6 +6,8 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.MathUtils; using osu.Framework.Threading; +using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Graphics.Backgrounds; using osu.Game.Online.API; using osu.Game.Skinning; @@ -24,6 +26,10 @@ namespace osu.Game.Screens.Backgrounds private Bindable user; private Bindable skin; + private Bindable mode; + + [Resolved] + private IBindable beatmap { get; set; } public BackgroundScreenDefault(bool animateOnEnter = true) : base(animateOnEnter) @@ -31,13 +37,15 @@ namespace osu.Game.Screens.Backgrounds } [BackgroundDependencyLoader] - private void load(IAPIProvider api, SkinManager skinManager) + private void load(IAPIProvider api, SkinManager skinManager, OsuConfigManager config) { user = api.LocalUser.GetBoundCopy(); skin = skinManager.CurrentSkin.GetBoundCopy(); + mode = config.GetBindable(OsuSetting.BackgroundMode); user.ValueChanged += _ => Next(); skin.ValueChanged += _ => Next(); + mode.ValueChanged += _ => Next(); currentDisplay = RNG.Next(0, background_count); @@ -66,9 +74,28 @@ namespace osu.Game.Screens.Backgrounds Background newBackground; if (user.Value?.IsSupporter ?? false) - newBackground = new SkinnedBackground(skin.Value, backgroundName); + { + switch (mode.Value) + { + case BackgroundMode.Beatmap: + newBackground = new BeatmapBackground(beatmap.Value, backgroundName); + break; + + default: + newBackground = new SkinnedBackground(skin.Value, backgroundName); + break; + } + } else - newBackground = new Background(backgroundName); + { + switch (mode.Value) + { + case BackgroundMode.Seasonal: + default: + newBackground = new Background(backgroundName); + break; + } + } newBackground.Depth = currentDisplay; From f493f1c71d2bee7242b6a4d552bc1ce0f3f05df7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Sep 2019 19:00:26 +0900 Subject: [PATCH 3149/5608] Move new components to v2 namespace --- .../Visual/UserInterface/TestSceneLabelledComponent.cs | 2 +- .../Visual/UserInterface/TestSceneLabelledTextBox.cs | 2 +- osu.Game.Tournament/Screens/SetupScreen.cs | 2 +- .../UserInterfaceV2}/LabelledComponent.cs | 3 +-- .../UserInterfaceV2}/LabelledTextBox.cs | 3 +-- 5 files changed, 5 insertions(+), 7 deletions(-) rename osu.Game/{Screens/Edit/Setup/Components/LabelledComponents => Graphics/UserInterfaceV2}/LabelledComponent.cs (98%) rename osu.Game/{Screens/Edit/Setup/Components/LabelledComponents => Graphics/UserInterfaceV2}/LabelledTextBox.cs (93%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs index a762d561c2..700adad9cb 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Sprites; -using osu.Game.Screens.Edit.Setup.Components.LabelledComponents; +using osu.Game.Graphics.UserInterfaceV2; using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs index 5c5b1262a6..53a2bfabbc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs @@ -8,7 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.UserInterface; -using osu.Game.Screens.Edit.Setup.Components.LabelledComponents; +using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Tests.Visual.UserInterface { diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 7a44e7a0e1..091a837745 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -7,9 +7,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.API; using osu.Game.Overlays; -using osu.Game.Screens.Edit.Setup.Components.LabelledComponents; using osu.Game.Tournament.IPC; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs similarity index 98% rename from osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs rename to osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs index 770065cb0e..2e659825b7 100644 --- a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledComponent.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs @@ -5,11 +5,10 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osuTK; -namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents +namespace osu.Game.Graphics.UserInterfaceV2 { public abstract class LabelledComponent : CompositeDrawable where T : Drawable diff --git a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs similarity index 93% rename from osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs rename to osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs index 67bacea9f8..50d2a14482 100644 --- a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs @@ -4,10 +4,9 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; -using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents +namespace osu.Game.Graphics.UserInterfaceV2 { public class LabelledTextBox : LabelledComponent { From afa043aa7de522e6436276d2c000f9820800b970 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Tue, 24 Sep 2019 18:17:27 +0800 Subject: [PATCH 3150/5608] always use default samples --- osu.Game/Screens/Menu/IntroCircles.cs | 5 +++-- osu.Game/Screens/Menu/IntroScreen.cs | 30 ++----------------------- osu.Game/Screens/Menu/IntroTriangles.cs | 4 ++-- 3 files changed, 7 insertions(+), 32 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroCircles.cs b/osu.Game/Screens/Menu/IntroCircles.cs index a861d54663..6c643860a0 100644 --- a/osu.Game/Screens/Menu/IntroCircles.cs +++ b/osu.Game/Screens/Menu/IntroCircles.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Screens; using osu.Framework.Graphics; @@ -17,10 +18,10 @@ namespace osu.Game.Screens.Menu private const double delay_step_two = 600; [BackgroundDependencyLoader] - private void load() + private void load(AudioManager audio) { if (MenuVoice.Value) - SetWelcome(); + Welcome = audio.Samples.Get(@"welcome"); } protected override void LogoArriving(OsuLogo logo, bool resuming) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 651fa7583d..c81fef6436 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -9,14 +9,11 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.MathUtils; using osu.Framework.Screens; -using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.IO.Archives; using osu.Game.Screens.Backgrounds; using osu.Game.Skinning; -using osu.Game.Online.API; -using osu.Game.Users; using osuTK; using osuTK.Graphics; @@ -51,14 +48,10 @@ namespace osu.Game.Screens.Menu public new Bindable Beatmap => beatmap; - protected Bindable User; - - protected Bindable Skin; - protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack(); [BackgroundDependencyLoader] - private void load(OsuConfigManager config, IAPIProvider api, SkinManager skinManager, BeatmapManager beatmaps, Framework.Game game) + private void load(OsuConfigManager config, SkinManager skinManager, BeatmapManager beatmaps, Framework.Game game) { // prevent user from changing beatmap while the intro is still runnning. beatmap = base.Beatmap.BeginLease(false); @@ -66,10 +59,7 @@ namespace osu.Game.Screens.Menu MenuVoice = config.GetBindable(OsuSetting.MenuVoice); MenuMusic = config.GetBindable(OsuSetting.MenuMusic); - User = api.LocalUser.GetBoundCopy(); - Skin = skinManager.CurrentSkin.GetBoundCopy(); - - Skin.BindValueChanged(_ => updateSeeya(), true); + seeya = audio.Samples.Get(@"seeya"); BeatmapSetInfo setInfo = null; @@ -98,22 +88,6 @@ namespace osu.Game.Screens.Menu Track = IntroBeatmap.Track; } - private void updateSeeya() - { - if (User.Value?.IsSupporter ?? false) - seeya = Skin.Value.GetSample(new SampleInfo("seeya")) ?? audio.Samples.Get(@"seeya"); - else - seeya = audio.Samples.Get(@"seeya"); - } - - protected void SetWelcome() - { - if (User.Value?.IsSupporter ?? false) - Welcome = Skin.Value.GetSample(new SampleInfo("welcome")) ?? audio.Samples.Get(@"welcome"); - else - Welcome = audio.Samples.Get(@"welcome"); - } - /// /// Whether we have loaded the menu previously. /// diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index 5b49a81a5a..590069ab43 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -41,10 +41,10 @@ namespace osu.Game.Screens.Menu private BackgroundScreenDefault background; [BackgroundDependencyLoader] - private void load() + private void load(AudioManager audio) { if (MenuVoice.Value && !MenuMusic.Value) - SetWelcome(); + Welcome = audio.Samples.Get(@"welcome"); } protected override void LogoArriving(OsuLogo logo, bool resuming) From e78f134b90792a65e0b8e7d59236c32ea415f156 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Sep 2019 19:35:42 +0900 Subject: [PATCH 3151/5608] Mark configuration lookup test headless --- osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index bbcc4140a9..578030748b 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -9,6 +9,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; +using osu.Framework.Testing; using osu.Game.Audio; using osu.Game.Skinning; using osu.Game.Tests.Visual; @@ -17,6 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Skins { [TestFixture] + [HeadlessTest] public class TestSceneSkinConfigurationLookup : OsuTestScene { private LegacySkin source1; From 03947e5b8532b21f52dcc73f755b2d31c64c000b Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Tue, 24 Sep 2019 19:49:46 +0800 Subject: [PATCH 3152/5608] change background for ScalingContainer --- osu.Game/Graphics/Containers/ScalingContainer.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 8f07c3a656..84053ee5d9 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; +using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Screens; using osu.Game.Screens.Backgrounds; @@ -154,6 +155,15 @@ namespace osu.Game.Graphics.Containers private class ScalingBackgroundScreen : BackgroundScreenDefault { + private Bindable beatmap; + + [BackgroundDependencyLoader] + private void load(IBindable beatmap) + { + this.beatmap = (Bindable)beatmap; + this.beatmap.ValueChanged += _ => Next(); + } + public override void OnEntering(IScreen last) { this.FadeInFromZero(4000, Easing.OutQuint); From 0bc59e17dc30cfd240407cc3d9fc4928c55b6daa Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Tue, 24 Sep 2019 21:56:32 +0800 Subject: [PATCH 3153/5608] remove Seasonal and apply suggestions --- osu.Game/Configuration/BackgroundMode.cs | 1 - osu.Game/Graphics/Containers/ScalingContainer.cs | 4 +--- .../Screens/Backgrounds/BackgroundScreenDefault.cs | 10 +--------- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/osu.Game/Configuration/BackgroundMode.cs b/osu.Game/Configuration/BackgroundMode.cs index 21554891ca..50d54f1eb2 100644 --- a/osu.Game/Configuration/BackgroundMode.cs +++ b/osu.Game/Configuration/BackgroundMode.cs @@ -6,7 +6,6 @@ namespace osu.Game.Configuration public enum BackgroundMode { Default, - Seasonal, Beatmap } } diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 84053ee5d9..1701223f44 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -155,13 +155,11 @@ namespace osu.Game.Graphics.Containers private class ScalingBackgroundScreen : BackgroundScreenDefault { - private Bindable beatmap; [BackgroundDependencyLoader] private void load(IBindable beatmap) { - this.beatmap = (Bindable)beatmap; - this.beatmap.ValueChanged += _ => Next(); + beatmap.ValueChanged += _ => Next(); } public override void OnEntering(IScreen last) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index a8ba17ef49..93590b0543 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -87,15 +87,7 @@ namespace osu.Game.Screens.Backgrounds } } else - { - switch (mode.Value) - { - case BackgroundMode.Seasonal: - default: - newBackground = new Background(backgroundName); - break; - } - } + newBackground = new Background(backgroundName); newBackground.Depth = currentDisplay; From 851e42a444d642ed08e3505f5314398db8401a67 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Tue, 24 Sep 2019 22:57:29 +0800 Subject: [PATCH 3154/5608] avoid memory leak --- osu.Game/Graphics/Containers/ScalingContainer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 1701223f44..023d295b08 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -155,11 +155,13 @@ namespace osu.Game.Graphics.Containers private class ScalingBackgroundScreen : BackgroundScreenDefault { + private IBindable beatmap; [BackgroundDependencyLoader] private void load(IBindable beatmap) { - beatmap.ValueChanged += _ => Next(); + this.beatmap = beatmap.GetBoundCopy(); + this.beatmap.ValueChanged += _ => Next(); } public override void OnEntering(IScreen last) From 4a59e3351edb6f5b9eb12c398e43bbe1c43be3a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Sep 2019 02:42:12 +0900 Subject: [PATCH 3155/5608] Update beatmap carousel tests code style Also fixes one issue I spotted in BeatmapCarousel related to incorrectly holding a selection after new sets are loaded. --- .../SongSelect/TestSceneBeatmapCarousel.cs | 98 +++++++++++-------- osu.Game/Screens/Select/BeatmapCarousel.cs | 3 + 2 files changed, 62 insertions(+), 39 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 71399106f4..16e873a84c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.SongSelect private readonly Stack selectedSets = new Stack(); private readonly HashSet eagerSelectedIDs = new HashSet(); - private BeatmapInfo currentSelection; + private BeatmapInfo currentSelection => carousel.SelectedBeatmap; private const int set_count = 5; @@ -56,37 +56,26 @@ namespace osu.Game.Tests.Visual.SongSelect { RelativeSizeAxes = Axes.Both, }); - - List beatmapSets = new List(); - - for (int i = 1; i <= set_count; i++) - beatmapSets.Add(createTestBeatmapSet(i)); - - carousel.SelectionChanged = s => currentSelection = s; - - loadBeatmaps(beatmapSets); - - testTraversal(); - testFiltering(); - testRandom(); - testAddRemove(); - testSorting(); - - testRemoveAll(); - testEmptyTraversal(); - testHiding(); - testSelectingFilteredRuleset(); - testCarouselRootIsRandom(); } - private void loadBeatmaps(List beatmapSets) + private void loadBeatmaps(List beatmapSets = null) { + if (beatmapSets == null) + { + beatmapSets = new List(); + + for (int i = 1; i <= set_count; i++) + beatmapSets.Add(createTestBeatmapSet(i)); + } + bool changed = false; AddStep($"Load {beatmapSets.Count} Beatmaps", () => { + carousel.Filter(new FilterCriteria()); carousel.BeatmapSetsChanged = () => changed = true; carousel.BeatmapSets = beatmapSets; }); + AddUntilStep("Wait for load", () => changed); } @@ -173,8 +162,11 @@ namespace osu.Game.Tests.Visual.SongSelect /// /// Test keyboard traversal /// - private void testTraversal() + [Test] + public void TestTraversal() { + loadBeatmaps(); + advanceSelection(direction: 1, diff: false); checkSelected(1, 1); @@ -199,8 +191,11 @@ namespace osu.Game.Tests.Visual.SongSelect /// /// Test filtering /// - private void testFiltering() + [Test] + public void TestFiltering() { + loadBeatmaps(); + // basic filtering setSelected(1, 1); @@ -262,8 +257,11 @@ namespace osu.Game.Tests.Visual.SongSelect /// /// Test random non-repeating algorithm /// - private void testRandom() + [Test] + public void TestRandom() { + loadBeatmaps(); + setSelected(1, 1); nextRandom(); @@ -299,8 +297,11 @@ namespace osu.Game.Tests.Visual.SongSelect /// /// Test adding and removing beatmap sets /// - private void testAddRemove() + [Test] + public void TestAddRemove() { + loadBeatmaps(); + AddStep("Add new set", () => carousel.UpdateBeatmapSet(createTestBeatmapSet(set_count + 1))); AddStep("Add new set", () => carousel.UpdateBeatmapSet(createTestBeatmapSet(set_count + 2))); @@ -322,16 +323,22 @@ namespace osu.Game.Tests.Visual.SongSelect /// /// Test sorting /// - private void testSorting() + [Test] + public void TestSorting() { + loadBeatmaps(); + AddStep("Sort by author", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Author }, false)); AddAssert("Check zzzzz is at bottom", () => carousel.BeatmapSets.Last().Metadata.AuthorString == "zzzzz"); AddStep("Sort by artist", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Artist }, false)); AddAssert($"Check #{set_count} is at bottom", () => carousel.BeatmapSets.Last().Metadata.Title.EndsWith($"#{set_count}!")); } - private void testRemoveAll() + [Test] + public void TestRemoveAll() { + loadBeatmaps(); + setSelected(2, 1); AddAssert("Selection is non-null", () => currentSelection != null); @@ -353,8 +360,11 @@ namespace osu.Game.Tests.Visual.SongSelect checkNoSelection(); } - private void testEmptyTraversal() + [Test] + public void TestEmptyTraversal() { + loadBeatmaps(new List()); + advanceSelection(direction: 1, diff: false); checkNoSelection(); @@ -368,11 +378,18 @@ namespace osu.Game.Tests.Visual.SongSelect checkNoSelection(); } - private void testHiding() + [Test] + public void TestHiding() { - var hidingSet = createTestBeatmapSet(1); - hidingSet.Beatmaps[1].Hidden = true; - AddStep("Add set with diff 2 hidden", () => carousel.UpdateBeatmapSet(hidingSet)); + BeatmapSetInfo hidingSet = null; + + AddStep("Add set with diff 2 hidden", () => + { + hidingSet = createTestBeatmapSet(1); + hidingSet.Beatmaps[1].Hidden = true; + carousel.UpdateBeatmapSet(hidingSet); + }); + setSelected(1, 1); checkVisibleItemCount(true, 2); @@ -402,7 +419,8 @@ namespace osu.Game.Tests.Visual.SongSelect } } - private void testSelectingFilteredRuleset() + [Test] + public void TestSelectingFilteredRuleset() { var testMixed = createTestBeatmapSet(set_count + 1); AddStep("add mixed ruleset beatmapset", () => @@ -437,14 +455,16 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("remove single ruleset set", () => carousel.RemoveBeatmapSet(testSingle)); } - private void testCarouselRootIsRandom() + [Test] + public void TestCarouselRootIsRandom() { - List beatmapSets = new List(); + List manySets = new List(); for (int i = 1; i <= 50; i++) - beatmapSets.Add(createTestBeatmapSet(i)); + manySets.Add(createTestBeatmapSet(i)); + + loadBeatmaps(manySets); - loadBeatmaps(beatmapSets); advanceSelection(direction: 1, diff: false); checkNonmatchingFilter(); checkNonmatchingFilter(); diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 23c581c6f9..c3436ffd45 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -82,6 +82,9 @@ namespace osu.Game.Screens.Select var _ = newRoot.Drawables; root = newRoot; + if (selectedBeatmapSet != null && !beatmapSets.Contains(selectedBeatmapSet.BeatmapSet)) + selectedBeatmapSet = null; + scrollableContent.Clear(false); itemsCache.Invalidate(); scrollPositionCache.Invalidate(); From 56b460365b7cd5b96ba03ba7ca118fb8db6bb9dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 24 Sep 2019 20:34:09 +0200 Subject: [PATCH 3156/5608] Add bar line anchoring checks in mania test stage Add steps checking bar line anchoring in the mania Stage visual test to reproduce the regression in #6215 and prevent it from happening in the future. --- osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs index e7fd601abe..56401dd082 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs @@ -67,6 +67,8 @@ namespace osu.Game.Rulesets.Mania.Tests AddAssert("check note anchors", () => notesInStageAreAnchored(stages[0], Anchor.TopCentre)); AddAssert("check note anchors", () => notesInStageAreAnchored(stages[1], Anchor.BottomCentre)); + AddAssert("check bar anchors", () => barsInStageAreAnchored(stages[0], Anchor.TopCentre)); + AddAssert("check bar anchors", () => barsInStageAreAnchored(stages[1], Anchor.BottomCentre)); AddStep("flip direction", () => { @@ -76,10 +78,14 @@ namespace osu.Game.Rulesets.Mania.Tests AddAssert("check note anchors", () => notesInStageAreAnchored(stages[0], Anchor.BottomCentre)); AddAssert("check note anchors", () => notesInStageAreAnchored(stages[1], Anchor.TopCentre)); + AddAssert("check bar anchors", () => barsInStageAreAnchored(stages[0], Anchor.BottomCentre)); + AddAssert("check bar anchors", () => barsInStageAreAnchored(stages[1], Anchor.TopCentre)); } private bool notesInStageAreAnchored(ManiaStage stage, Anchor anchor) => stage.Columns.SelectMany(c => c.AllHitObjects).All(o => o.Anchor == anchor); + private bool barsInStageAreAnchored(ManiaStage stage, Anchor anchor) => stage.AllHitObjects.Where(obj => obj is DrawableBarLine).All(o => o.Anchor == anchor); + private void createNote() { foreach (var stage in stages) From 09864d7f0edb3a6164d2d384acc977c2e8795ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 24 Sep 2019 21:42:40 +0200 Subject: [PATCH 3157/5608] Add bar line visual check in taiko playfield test Add a step checking alignment of a centre and a bar line in taiko playfield. Purely visual test without asserts. --- osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index 3aa461e779..cbbf5b0c09 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -53,6 +53,11 @@ namespace osu.Game.Rulesets.Taiko.Tests AddStep("Strong Rim", () => addRimHit(true)); AddStep("Add bar line", () => addBarLine(false)); AddStep("Add major bar line", () => addBarLine(true)); + AddStep("Add centre w/ bar line", () => + { + addCentreHit(false); + addBarLine(true); + }); AddStep("Height test 1", () => changePlayfieldSize(1)); AddStep("Height test 2", () => changePlayfieldSize(2)); AddStep("Height test 3", () => changePlayfieldSize(3)); From d013b73d33082c3f1471bc922c4d77147122c81d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 25 Sep 2019 01:25:05 +0300 Subject: [PATCH 3158/5608] Move in-memory logic to a base class --- .../Configuration/InMemoryConfigManager.cs | 22 +++++++++++++++++++ osu.Game/Configuration/SessionStatics.cs | 10 +++------ 2 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 osu.Game/Configuration/InMemoryConfigManager.cs diff --git a/osu.Game/Configuration/InMemoryConfigManager.cs b/osu.Game/Configuration/InMemoryConfigManager.cs new file mode 100644 index 0000000000..b0dc6b0e9c --- /dev/null +++ b/osu.Game/Configuration/InMemoryConfigManager.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Configuration; + +namespace osu.Game.Configuration +{ + public class InMemoryConfigManager : ConfigManager + where T : struct + { + public InMemoryConfigManager() + { + InitialiseDefaults(); + } + + protected override void PerformLoad() + { + } + + protected override bool PerformSave() => true; + } +} diff --git a/osu.Game/Configuration/SessionStatics.cs b/osu.Game/Configuration/SessionStatics.cs index 0c1ea1e568..b4b5e914bb 100644 --- a/osu.Game/Configuration/SessionStatics.cs +++ b/osu.Game/Configuration/SessionStatics.cs @@ -1,18 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; - namespace osu.Game.Configuration { - public class SessionStatics : ConfigManager + public class SessionStatics : InMemoryConfigManager { - // This is an in-memory store. - protected override void PerformLoad() + protected override void InitialiseDefaults() { + Set(Statics.LoginOverlayDisplayed, false); } - - protected override bool PerformSave() => true; } public enum Statics From cde7f49db1b37d3325b64f0ceddd312476e3f2c8 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 25 Sep 2019 01:26:02 +0300 Subject: [PATCH 3159/5608] Use direct get and set instead --- osu.Game/Screens/Menu/MainMenu.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 1834221d35..98ceb315a2 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -200,12 +200,10 @@ namespace osu.Game.Screens.Menu bool displayLogin() { - var loginDisplayed = statics.GetBindable(Statics.LoginOverlayDisplayed); - - if (!loginDisplayed.Value) + if (!statics.Get(Statics.LoginOverlayDisplayed)) { Scheduler.AddDelayed(() => login?.Show(), 500); - loginDisplayed.Value = true; + statics.Set(Statics.LoginOverlayDisplayed, true); } return true; From 9323df26a1cafa6fa90e316bfa659fcb5584fa13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 24 Sep 2019 23:03:55 +0200 Subject: [PATCH 3160/5608] Decouple bar line hitobjects from generator Introduce an IBarLine interface, which together with generic constraints helps decouple BarLineGenerator from the actual hitobject types it creates. Thanks to this, all rulesets that want bar lines can provide an implementation of IBarLine that also derives from the base hitobject class. This allows DrawableBarLines in taiko and mania to be migrated back to DrawableTaikoHitObject and DrawableManiaHitObject base classes respectively. This in turn resolves #6215 without code duplication, since the missing anchoring application is now done in mania's DrawableBarLine through deriving from DrawableManiaHitObject. --- osu.Game.Rulesets.Mania/Objects/BarLine.cs | 12 ++++++++++ .../Objects/Drawables/DrawableBarLine.cs | 3 +-- .../UI/DrawableManiaRuleset.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 1 - osu.Game.Rulesets.Taiko/Objects/BarLine.cs | 12 ++++++++++ .../UI/DrawableTaikoRuleset.cs | 2 +- osu.Game/Rulesets/Objects/BarLine.cs | 16 -------------- osu.Game/Rulesets/Objects/BarLineGenerator.cs | 7 +++--- osu.Game/Rulesets/Objects/IBarLine.cs | 22 +++++++++++++++++++ 9 files changed, 53 insertions(+), 24 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Objects/BarLine.cs create mode 100644 osu.Game.Rulesets.Taiko/Objects/BarLine.cs delete mode 100644 osu.Game/Rulesets/Objects/BarLine.cs create mode 100644 osu.Game/Rulesets/Objects/IBarLine.cs diff --git a/osu.Game.Rulesets.Mania/Objects/BarLine.cs b/osu.Game.Rulesets.Mania/Objects/BarLine.cs new file mode 100644 index 0000000000..0981b028b2 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Objects/BarLine.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Mania.Objects +{ + public class BarLine : ManiaHitObject, IBarLine + { + public bool Major { get; set; } + } +} diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index be21610525..56bc797c7f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -4,7 +4,6 @@ using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osuTK.Graphics; @@ -14,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// Visualises a . Although this derives DrawableManiaHitObject, /// this does not handle input/sound like a normal hit object. /// - public class DrawableBarLine : DrawableHitObject + public class DrawableBarLine : DrawableManiaHitObject { /// /// Height of major bar line triangles. diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 29863fba2e..d371c1f7a8 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI public DrawableManiaRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { - BarLines = new BarLineGenerator(Beatmap).BarLines; + BarLines = new BarLineGenerator(Beatmap).BarLines; } [BackgroundDependencyLoader] diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 12faa499ad..5ab07416a6 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -8,7 +8,6 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using osuTK; diff --git a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs new file mode 100644 index 0000000000..2afbbc737c --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Taiko.Objects +{ + public class BarLine : TaikoHitObject, IBarLine + { + public bool Major { get; set; } + } +} diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index 5caa9e4626..fc109bf6a6 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Taiko.UI [BackgroundDependencyLoader] private void load() { - new BarLineGenerator(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar.Major ? new DrawableBarLineMajor(bar) : new DrawableBarLine(bar))); + new BarLineGenerator(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar.Major ? new DrawableBarLineMajor(bar) : new DrawableBarLine(bar))); } public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); diff --git a/osu.Game/Rulesets/Objects/BarLine.cs b/osu.Game/Rulesets/Objects/BarLine.cs deleted file mode 100644 index a5c716e127..0000000000 --- a/osu.Game/Rulesets/Objects/BarLine.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Rulesets.Objects -{ - /// - /// A hit object representing the end of a bar. - /// - public class BarLine : HitObject - { - /// - /// Whether this barline is a prominent beat (based on time signature of beatmap). - /// - public bool Major; - } -} diff --git a/osu.Game/Rulesets/Objects/BarLineGenerator.cs b/osu.Game/Rulesets/Objects/BarLineGenerator.cs index ce571d7b17..4f9395435e 100644 --- a/osu.Game/Rulesets/Objects/BarLineGenerator.cs +++ b/osu.Game/Rulesets/Objects/BarLineGenerator.cs @@ -10,12 +10,13 @@ using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects { - public class BarLineGenerator + public class BarLineGenerator + where TBarLine : class, IBarLine, new() { /// /// The generated bar lines. /// - public readonly List BarLines = new List(); + public readonly List BarLines = new List(); /// /// Constructs and generates bar lines for provided beatmap. @@ -46,7 +47,7 @@ namespace osu.Game.Rulesets.Objects for (double t = currentTimingPoint.Time; Precision.DefinitelyBigger(endTime, t); t += barLength, currentBeat++) { - BarLines.Add(new BarLine + BarLines.Add(new TBarLine { StartTime = t, Major = currentBeat % (int)currentTimingPoint.TimeSignature == 0 diff --git a/osu.Game/Rulesets/Objects/IBarLine.cs b/osu.Game/Rulesets/Objects/IBarLine.cs new file mode 100644 index 0000000000..14df80e3b9 --- /dev/null +++ b/osu.Game/Rulesets/Objects/IBarLine.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Objects +{ + /// + /// Interface for bar line hitobjects. + /// Used to decouple bar line generation from ruleset-specific rendering/drawing hierarchies. + /// + public interface IBarLine + { + /// + /// The time position of the bar. + /// + double StartTime { set; } + + /// + /// Whether this bar line is a prominent beat (based on time signature of beatmap). + /// + bool Major { set; } + } +} From 7fab1a4337c4db0094e4179fb34037984f1d322b Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 24 Sep 2019 16:06:33 -0700 Subject: [PATCH 3161/5608] Truncate long metadata on beatmap info wedge --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 22 +++++++++++++++------ osu.Game/Screens/Select/SongSelect.cs | 2 +- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 65ecd7b812..6c3eed8610 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -31,7 +31,9 @@ namespace osu.Game.Screens.Select { public class BeatmapInfoWedge : OverlayContainer { - private static readonly Vector2 wedged_container_shear = new Vector2(0.15f, 0); + private const float shear_width = 36.75f; + + private static readonly Vector2 wedged_container_shear = new Vector2(shear_width / SongSelect.wedged_container_size.Y, 0); private readonly IBindable ruleset = new Bindable(); @@ -200,14 +202,17 @@ namespace osu.Game.Screens.Select Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, Direction = FillDirection.Vertical, - Margin = new MarginPadding { Top = 10, Left = 25, Right = 10, Bottom = 20 }, - AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 10, Left = 25, Right = shear_width * 2.5f, Bottom = 20 }, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, Children = new Drawable[] { VersionLabel = new OsuSpriteText { Text = beatmapInfo.Version, Font = OsuFont.GetFont(size: 24, italics: true), + RelativeSizeAxes = Axes.X, + Truncate = true, }, } }, @@ -217,7 +222,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Direction = FillDirection.Vertical, - Margin = new MarginPadding { Top = 14, Left = 10, Right = 18, Bottom = 20 }, + Padding = new MarginPadding { Top = 14, Left = 10, Right = shear_width / 2, Bottom = 20 }, AutoSizeAxes = Axes.Both, Children = new Drawable[] { @@ -236,17 +241,22 @@ namespace osu.Game.Screens.Select Origin = Anchor.TopLeft, Y = -22, Direction = FillDirection.Vertical, - Margin = new MarginPadding { Top = 15, Left = 25, Right = 10, Bottom = 20 }, - AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 15, Left = 25, Right = shear_width, Bottom = 20 }, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, Children = new Drawable[] { TitleLabel = new OsuSpriteText { Font = OsuFont.GetFont(size: 28, italics: true), + RelativeSizeAxes = Axes.X, + Truncate = true, }, ArtistLabel = new OsuSpriteText { Font = OsuFont.GetFont(size: 17, italics: true), + RelativeSizeAxes = Axes.X, + Truncate = true, }, MapperContainer = new FillFlowContainer { diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index fca801ce78..6c0d8a0f36 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Select { public abstract class SongSelect : OsuScreen, IKeyBindingHandler { - private static readonly Vector2 wedged_container_size = new Vector2(0.5f, 245); + public static readonly Vector2 wedged_container_size = new Vector2(0.5f, 245); protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; From 8efab559c8d65138c2a38097970797957f396233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 25 Sep 2019 01:13:42 +0200 Subject: [PATCH 3162/5608] Remove unused using directives --- osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs | 1 - osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 1 - .../Objects/Drawables/DrawableBarLineMajor.cs | 1 - 3 files changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs index 56401dd082..d5fd2808b8 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs @@ -15,7 +15,6 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Tests.Visual; using osuTK; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 98a4b7d0b6..a28de7ea58 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -12,7 +12,6 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs index f5b75a781b..4d3a1a3f8a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK; using osu.Framework.Graphics.Shapes; -using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { From 8efba255c383acd4114b1625939eaf745bb59cbd Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 24 Sep 2019 16:21:08 -0700 Subject: [PATCH 3163/5608] Add truncation test --- .../SongSelect/TestSceneBeatmapInfoWedge.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index 932e114580..cda6bedf5d 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -127,6 +127,12 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("check no info labels", () => !infoWedge.Info.InfoLabelContainer.Children.Any()); } + [Test] + public void testTruncation() + { + selectBeatmap(createLongMetadata()); + } + private void selectBeatmap([CanBeNull] IBeatmap b) { BeatmapInfoWedge.BufferedWedgeInfo infoBefore = null; @@ -166,6 +172,25 @@ namespace osu.Game.Tests.Visual.SongSelect }; } + private IBeatmap createLongMetadata() + { + return new Beatmap + { + BeatmapInfo = new BeatmapInfo + { + Metadata = new BeatmapMetadata + { + AuthorString = $"WWWWWWWWWWWWWWW", + Artist = $"Verrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrry long Artist", + Source = $"Verrrrry long Source", + Title = $"Verrrrry long Title" + }, + Version = $"Verrrrrrrrrrrrrrrrrrrrrrrrrrrrry long Version", + Status = BeatmapSetOnlineStatus.Graveyard, + }, + }; + } + private class TestBeatmapInfoWedge : BeatmapInfoWedge { public new BufferedWedgeInfo Info => base.Info; From cc6030ca14d3f6377c657afeb44faa96bca3bbd2 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 24 Sep 2019 16:23:36 -0700 Subject: [PATCH 3164/5608] Update beatmap info wedge tests --- .../Visual/SongSelect/TestSceneBeatmapInfoWedge.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index cda6bedf5d..017e9c527b 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -75,7 +75,6 @@ namespace osu.Game.Tests.Visual.SongSelect testBeatmapLabels(instance); - // TODO: adjust cases once more info is shown for other gamemodes switch (instance) { case OsuRuleset _: @@ -99,8 +98,6 @@ namespace osu.Game.Tests.Visual.SongSelect break; } } - - testNullBeatmap(); } private void testBeatmapLabels(Ruleset ruleset) @@ -117,7 +114,8 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("check info labels count", () => infoWedge.Info.InfoLabelContainer.Children.Count == expectedCount); } - private void testNullBeatmap() + [Test] + public void testNullBeatmap() { selectBeatmap(null); AddAssert("check empty version", () => string.IsNullOrEmpty(infoWedge.Info.VersionLabel.Text)); From 9861b214407a5e4861722b2cfb876bd524db76de Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 24 Sep 2019 16:28:40 -0700 Subject: [PATCH 3165/5608] Remove unnecessary padding/margin --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 6c3eed8610..33060e0735 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -202,7 +202,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, Direction = FillDirection.Vertical, - Padding = new MarginPadding { Top = 10, Left = 25, Right = shear_width * 2.5f, Bottom = 20 }, + Padding = new MarginPadding { Top = 10, Left = 25, Right = shear_width * 2.5f }, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Children = new Drawable[] @@ -222,7 +222,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Direction = FillDirection.Vertical, - Padding = new MarginPadding { Top = 14, Left = 10, Right = shear_width / 2, Bottom = 20 }, + Padding = new MarginPadding { Top = 14, Right = shear_width / 2 }, AutoSizeAxes = Axes.Both, Children = new Drawable[] { @@ -239,9 +239,9 @@ namespace osu.Game.Screens.Select Name = "Centre-aligned metadata", Anchor = Anchor.CentreLeft, Origin = Anchor.TopLeft, - Y = -22, + Y = -7, Direction = FillDirection.Vertical, - Padding = new MarginPadding { Top = 15, Left = 25, Right = shear_width, Bottom = 20 }, + Padding = new MarginPadding { Left = 25, Right = shear_width }, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Children = new Drawable[] From 102dbd85bdd4fd4f4589314e3164512502860b51 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 24 Sep 2019 16:48:22 -0700 Subject: [PATCH 3166/5608] Fix CI errors --- .../Visual/SongSelect/TestSceneBeatmapInfoWedge.cs | 14 +++++++------- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index 017e9c527b..f49d7a14a6 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -115,7 +115,7 @@ namespace osu.Game.Tests.Visual.SongSelect } [Test] - public void testNullBeatmap() + public void TestNullBeatmap() { selectBeatmap(null); AddAssert("check empty version", () => string.IsNullOrEmpty(infoWedge.Info.VersionLabel.Text)); @@ -126,7 +126,7 @@ namespace osu.Game.Tests.Visual.SongSelect } [Test] - public void testTruncation() + public void TestTruncation() { selectBeatmap(createLongMetadata()); } @@ -178,12 +178,12 @@ namespace osu.Game.Tests.Visual.SongSelect { Metadata = new BeatmapMetadata { - AuthorString = $"WWWWWWWWWWWWWWW", - Artist = $"Verrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrry long Artist", - Source = $"Verrrrry long Source", - Title = $"Verrrrry long Title" + AuthorString = "WWWWWWWWWWWWWWW", + Artist = "Verrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrry long Artist", + Source = "Verrrrry long Source", + Title = "Verrrrry long Title" }, - Version = $"Verrrrrrrrrrrrrrrrrrrrrrrrrrrrry long Version", + Version = "Verrrrrrrrrrrrrrrrrrrrrrrrrrrrry long Version", Status = BeatmapSetOnlineStatus.Graveyard, }, }; diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 33060e0735..8b360d4a86 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Select { private const float shear_width = 36.75f; - private static readonly Vector2 wedged_container_shear = new Vector2(shear_width / SongSelect.wedged_container_size.Y, 0); + private static readonly Vector2 wedged_container_shear = new Vector2(shear_width / SongSelect.WEDGED_CONTAINER_SIZE.Y, 0); private readonly IBindable ruleset = new Bindable(); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 6c0d8a0f36..653f62dd15 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Select { public abstract class SongSelect : OsuScreen, IKeyBindingHandler { - public static readonly Vector2 wedged_container_size = new Vector2(0.5f, 245); + public static readonly Vector2 WEDGED_CONTAINER_SIZE = new Vector2(0.5f, 245); protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; @@ -109,7 +109,7 @@ namespace osu.Game.Screens.Select { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Right = -150 }, - Size = new Vector2(wedged_container_size.X, 1), + Size = new Vector2(WEDGED_CONTAINER_SIZE.X, 1), } } }, @@ -118,11 +118,11 @@ namespace osu.Game.Screens.Select Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, - Size = new Vector2(wedged_container_size.X, 1), + Size = new Vector2(WEDGED_CONTAINER_SIZE.X, 1), Padding = new MarginPadding { Bottom = Footer.HEIGHT, - Top = wedged_container_size.Y + left_area_padding, + Top = WEDGED_CONTAINER_SIZE.Y + left_area_padding, Left = left_area_padding, Right = left_area_padding * 2, }, @@ -158,7 +158,7 @@ namespace osu.Game.Screens.Select Child = Carousel = new BeatmapCarousel { RelativeSizeAxes = Axes.Both, - Size = new Vector2(1 - wedged_container_size.X, 1), + Size = new Vector2(1 - WEDGED_CONTAINER_SIZE.X, 1), Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, SelectionChanged = updateSelectedBeatmap, @@ -182,7 +182,7 @@ namespace osu.Game.Screens.Select }, beatmapInfoWedge = new BeatmapInfoWedge { - Size = wedged_container_size, + Size = WEDGED_CONTAINER_SIZE, RelativeSizeAxes = Axes.X, Margin = new MarginPadding { From 2089f6fc42ed65d088712553def79a8078716b8b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Sep 2019 14:28:35 +0900 Subject: [PATCH 3167/5608] Fix potential test fail case --- .../Visual/SongSelect/TestSceneBeatmapCarousel.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 16e873a84c..f12a613bf1 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -381,14 +381,10 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestHiding() { - BeatmapSetInfo hidingSet = null; + BeatmapSetInfo hidingSet = createTestBeatmapSet(1); + hidingSet.Beatmaps[1].Hidden = true; - AddStep("Add set with diff 2 hidden", () => - { - hidingSet = createTestBeatmapSet(1); - hidingSet.Beatmaps[1].Hidden = true; - carousel.UpdateBeatmapSet(hidingSet); - }); + loadBeatmaps(new List { hidingSet }); setSelected(1, 1); From c83db94eb7ccbe458da15d6f1d7563e14af0cfba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Sep 2019 15:00:08 +0900 Subject: [PATCH 3168/5608] Use isolated storage/api --- .../Visual/Menus/TestSceneScreenNavigation.cs | 25 +++++++--------- osu.Game/Online/API/APIRequest.cs | 5 +++- osu.Game/OsuGameBase.cs | 29 ++++++++++++------- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index 515f4cdce6..ee160e6a15 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -28,7 +28,7 @@ namespace osu.Game.Tests.Visual.Menus { private const float click_padding = 25; - private GameHost gameHost; + private GameHost host; private TestOsuGame osuGame; private Vector2 backButtonPosition => osuGame.ToScreenSpace(new Vector2(click_padding, osuGame.LayoutRectangle.Bottom - click_padding)); @@ -36,9 +36,9 @@ namespace osu.Game.Tests.Visual.Menus private Vector2 optionsButtonPosition => osuGame.ToScreenSpace(new Vector2(click_padding, click_padding)); [BackgroundDependencyLoader] - private void load(GameHost gameHost) + private void load(GameHost host) { - this.gameHost = gameHost; + this.host = host; Child = new Box { @@ -58,8 +58,8 @@ namespace osu.Game.Tests.Visual.Menus osuGame.Dispose(); } - osuGame = new TestOsuGame(); - osuGame.SetHost(gameHost); + osuGame = new TestOsuGame(LocalStorage, API); + osuGame.SetHost(host); Add(osuGame); }); @@ -163,19 +163,16 @@ namespace osu.Game.Tests.Visual.Menus protected override Loader CreateLoader() => new TestLoader(); - private DependencyContainer dependencies; - - private DummyAPIAccess dummyAPI; - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => - dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + public TestOsuGame(Storage storage, IAPIProvider api) + { + Storage = storage; + API = api; + } protected override void LoadComplete() { base.LoadComplete(); - dependencies.CacheAs(dummyAPI = new DummyAPIAccess()); - - dummyAPI.Login("Rhythm Champion", "osu!"); + API.Login("Rhythm Champion", "osu!"); } } diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index e8eff5a3a9..4f613d5c3c 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -64,7 +64,10 @@ namespace osu.Game.Online.API public void Perform(IAPIProvider api) { if (!(api is APIAccess apiAccess)) - throw new NotSupportedException($"A {nameof(APIAccess)} is required to perform requests."); + { + Fail(new NotSupportedException($"A {nameof(APIAccess)} is required to perform requests.")); + return; + } API = apiAccess; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index d6b8ad3e67..9d1eff4819 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -65,7 +65,7 @@ namespace osu.Game protected RulesetConfigCache RulesetConfigCache; - protected APIAccess API; + protected IAPIProvider API; protected MenuCursorContainer MenuCursorContainer; @@ -73,6 +73,8 @@ namespace osu.Game protected override Container Content => content; + protected Storage Storage { get; set; } + private Bindable beatmap; // cached via load() method [Cached] @@ -123,7 +125,7 @@ namespace osu.Game { Resources.AddStore(new DllResourceStore(@"osu.Game.Resources.dll")); - dependencies.Cache(contextFactory = new DatabaseContextFactory(Host.Storage)); + dependencies.Cache(contextFactory = new DatabaseContextFactory(Storage)); var largeStore = new LargeTextureStore(Host.CreateTextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures"))); largeStore.AddStore(Host.CreateTextureLoaderStore(new OnlineStore())); @@ -158,21 +160,21 @@ namespace osu.Game runMigrations(); - dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio, new NamespacedResourceStore(Resources, "Skins/Legacy"))); + dependencies.Cache(SkinManager = new SkinManager(Storage, contextFactory, Host, Audio, new NamespacedResourceStore(Resources, "Skins/Legacy"))); dependencies.CacheAs(SkinManager); - API = new APIAccess(LocalConfig); + if (API == null) API = new APIAccess(LocalConfig); - dependencies.CacheAs(API); + dependencies.CacheAs(API); var defaultBeatmap = new DummyWorkingBeatmap(Audio, Textures); dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); - dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); + dependencies.Cache(FileStore = new FileStore(contextFactory, Storage)); // ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup() - dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Host.Storage, API, contextFactory, Host)); - dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap)); + dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, API, contextFactory, Host)); + dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap)); // this should likely be moved to ArchiveModelManager when another case appers where it is necessary // to have inter-dependent model managers. this could be obtained with an IHasForeign interface to @@ -206,7 +208,8 @@ namespace osu.Game FileStore.Cleanup(); - AddInternal(API); + if (API is APIAccess apiAcces) + AddInternal(apiAcces); AddInternal(RulesetConfigCache); GlobalActionContainer globalBinding; @@ -266,9 +269,13 @@ namespace osu.Game public override void SetHost(GameHost host) { - if (LocalConfig == null) - LocalConfig = new OsuConfigManager(host.Storage); base.SetHost(host); + + if (Storage == null) + Storage = host.Storage; + + if (LocalConfig == null) + LocalConfig = new OsuConfigManager(Storage); } private readonly List fileImporters = new List(); From 8fd1a45a4278389c8b3fdc8e76209218cb4804d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Sep 2019 15:29:02 +0900 Subject: [PATCH 3169/5608] Change intro displayed for tests As the triangles intro relies on the audio track's clock advancing, we can't use it just yet (CI server has no audio device). This is a temporary workaround for that shortcoming. --- osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index ee160e6a15..17535cae98 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Testing; +using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Overlays; @@ -21,6 +22,7 @@ using osu.Game.Screens.Select; using osuTK; using osuTK.Graphics; using osuTK.Input; +using IntroSequence = osu.Game.Configuration.IntroSequence; namespace osu.Game.Tests.Visual.Menus { @@ -61,6 +63,10 @@ namespace osu.Game.Tests.Visual.Menus osuGame = new TestOsuGame(LocalStorage, API); osuGame.SetHost(host); + // todo: this can be removed once we can run audio trakcs without a device present + // see https://github.com/ppy/osu/issues/1302 + osuGame.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles); + Add(osuGame); }); AddUntilStep("Wait for load", () => osuGame.IsLoaded); @@ -161,6 +167,8 @@ namespace osu.Game.Tests.Visual.Menus public new SettingsPanel Settings => base.Settings; + public new OsuConfigManager LocalConfig => base.LocalConfig; + protected override Loader CreateLoader() => new TestLoader(); public TestOsuGame(Storage storage, IAPIProvider api) From 74b2e99247ab38d210d76aac8050aac8533057f6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Sep 2019 16:25:15 +0900 Subject: [PATCH 3170/5608] Fix invalid cursor trail parts being drawn --- .../UI/Cursor/CursorTrail.cs | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index b32dfd483f..80291c002e 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -40,9 +40,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor for (int i = 0; i < max_sprites; i++) { - // InvalidationID 1 forces an update of each part of the cursor trail the first time ApplyState is run on the draw node - // This is to prevent garbage data from being sent to the vertex shader, resulting in visual issues on some platforms - parts[i].InvalidationID = 1; + // -1 signals that the part is unusable, and should not be drawn + parts[i].InvalidationID = -1; } } @@ -112,7 +111,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor for (int i = 0; i < parts.Length; ++i) { parts[i].Time -= time; - ++parts[i].InvalidationID; + + if (parts[i].InvalidationID != -1) + ++parts[i].InvalidationID; } time = 0; @@ -205,8 +206,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public TrailDrawNode(CursorTrail source) : base(source) { - for (int i = 0; i < max_sprites; i++) - parts[i].InvalidationID = 0; } public override void ApplyState() @@ -218,11 +217,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor size = Source.partSize; time = Source.time; - for (int i = 0; i < Source.parts.Length; ++i) - { - if (Source.parts[i].InvalidationID > parts[i].InvalidationID) - parts[i] = Source.parts[i]; - } + Source.parts.CopyTo(parts, 0); } public override void Draw(Action vertexAction) @@ -234,6 +229,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor for (int i = 0; i < parts.Length; ++i) { + if (parts[i].InvalidationID == -1) + continue; + vertexBatch.DrawTime = parts[i].Time; Vector2 pos = parts[i].Position; From 261ba5c80ac4b82d5d73ce02c9609fe8bc829783 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Sep 2019 17:42:27 +0900 Subject: [PATCH 3171/5608] Fix button not transforming correctly in some cases --- .../UserInterface/TestSceneSwitchButton.cs | 30 +++++++++++++++++-- .../Graphics/UserInterface/SwitchButton.cs | 19 ++++++------ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs index 8fe381f141..bf9071b812 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs @@ -1,20 +1,44 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using NUnit.Framework; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; +using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneSwitchButton : OsuTestScene + public class TestSceneSwitchButton : ManualInputManagerTestScene { - public TestSceneSwitchButton() + private SwitchButton switchButton; + + [SetUp] + public void Setup() => Schedule(() => { - Child = new SwitchButton + Child = switchButton = new SwitchButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, }; + }); + + [Test] + public void TestChangeThroughInput() + { + AddStep("move to switch button", () => InputManager.MoveMouseTo(switchButton)); + AddStep("click on", () => InputManager.Click(MouseButton.Left)); + AddStep("click off", () => InputManager.Click(MouseButton.Left)); + } + + [Test] + public void TestChangeThroughBindable() + { + BindableBool bindable = null; + + AddStep("bind bindable", () => switchButton.Current.BindTo(bindable = new BindableBool())); + AddStep("toggle bindable", () => bindable.Toggle()); + AddStep("toggle bindable", () => bindable.Toggle()); } } } diff --git a/osu.Game/Graphics/UserInterface/SwitchButton.cs b/osu.Game/Graphics/UserInterface/SwitchButton.cs index 21712051ef..9964af91d5 100644 --- a/osu.Game/Graphics/UserInterface/SwitchButton.cs +++ b/osu.Game/Graphics/UserInterface/SwitchButton.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -73,20 +74,20 @@ namespace osu.Game.Graphics.UserInterface switchContainer.Colour = enabledColour; fill.Colour = disabledColour; - - updateBorder(); } - protected override void OnUserChange(bool value) + protected override void LoadComplete() { - base.OnUserChange(value); + base.LoadComplete(); - if (value) - switchCircle.MoveToX(switchContainer.DrawWidth - switchCircle.DrawWidth, 200, Easing.OutQuint); - else - switchCircle.MoveToX(0, 200, Easing.OutQuint); + Current.BindValueChanged(updateState, true); + FinishTransforms(true); + } - fill.FadeTo(value ? 1 : 0, 250, Easing.OutQuint); + private void updateState(ValueChangedEvent state) + { + switchCircle.MoveToX(state.NewValue ? switchContainer.DrawWidth - switchCircle.DrawWidth : 0, 200, Easing.OutQuint); + fill.FadeTo(state.NewValue ? 1 : 0, 250, Easing.OutQuint); updateBorder(); } From c9e39c124e5817bce9909acc8e057606701ea0ce Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Sep 2019 17:42:35 +0900 Subject: [PATCH 3172/5608] Add a labelled switch button --- .../TestSceneLabelledSwitchButton.cs | 50 +++++++++++++++++++ .../LabelledSwitchButton.cs | 17 +++++++ 2 files changed, 67 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs create mode 100644 osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledSwitchButton.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs new file mode 100644 index 0000000000..dbce08c898 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs @@ -0,0 +1,50 @@ +// 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 NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Edit.Setup.Components.LabelledComponents; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneLabelledSwitchButton : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(LabelledSwitchButton), + typeof(SwitchButton) + }; + + [TestCase(false)] + [TestCase(true)] + public void TestSwitchButton(bool hasDescription) => createSwitchButton(hasDescription); + + private void createSwitchButton(bool hasDescription = false) + { + AddStep("create component", () => + { + LabelledSwitchButton component; + + Child = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 500, + AutoSizeAxes = Axes.Y, + Child = component = new LabelledSwitchButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + + component.Label = "a sample component"; + component.Description = hasDescription ? "this text describes the component" : string.Empty; + }); + } + } +} diff --git a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledSwitchButton.cs b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledSwitchButton.cs new file mode 100644 index 0000000000..54f6184578 --- /dev/null +++ b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledSwitchButton.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents +{ + public class LabelledSwitchButton : LabelledComponent + { + public LabelledSwitchButton() + : base(true) + { + } + + protected override SwitchButton CreateComponent() => new SwitchButton(); + } +} From 9f77a1ef35c081db6812bbd40e38185101ae4fcc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Sep 2019 17:53:08 +0900 Subject: [PATCH 3173/5608] Adjust namespaces --- .../Visual/UserInterface/TestSceneLabelledSwitchButton.cs | 3 +-- osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs | 2 +- osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs | 4 +--- .../{UserInterface => UserInterfaceV2}/SwitchButton.cs | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) rename osu.Game/Graphics/{UserInterface => UserInterfaceV2}/SwitchButton.cs (98%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs index dbce08c898..6ca4d9fa4c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs @@ -6,8 +6,7 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics.UserInterface; -using osu.Game.Screens.Edit.Setup.Components.LabelledComponents; +using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Tests.Visual.UserInterface { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs index bf9071b812..4a104b4a41 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs @@ -4,7 +4,7 @@ using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs index 54f6184578..c973f1d13e 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs @@ -1,9 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Graphics.UserInterface; - -namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents +namespace osu.Game.Graphics.UserInterfaceV2 { public class LabelledSwitchButton : LabelledComponent { diff --git a/osu.Game/Graphics/UserInterface/SwitchButton.cs b/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs similarity index 98% rename from osu.Game/Graphics/UserInterface/SwitchButton.cs rename to osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs index 9964af91d5..a7fd25b554 100644 --- a/osu.Game/Graphics/UserInterface/SwitchButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs @@ -13,7 +13,7 @@ using osu.Framework.Input.Events; using osuTK; using osuTK.Graphics; -namespace osu.Game.Graphics.UserInterface +namespace osu.Game.Graphics.UserInterfaceV2 { public class SwitchButton : Checkbox { From f11156c2dc644e34f68c883b2b7d9bdf3a63c380 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Sep 2019 19:24:05 +0900 Subject: [PATCH 3174/5608] Fix tests not working correctly --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 107 +++++++++++++++--- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- 2 files changed, 93 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index ab519360ac..eb54eca0cb 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -7,10 +7,15 @@ using System.Linq; using System.Threading; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; using osu.Framework.Screens; +using osu.Game.Graphics.Containers; +using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; @@ -18,25 +23,41 @@ using osu.Game.Scoring; using osu.Game.Screens; using osu.Game.Screens.Play; using osu.Game.Screens.Play.PlayerSettings; +using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { public class TestScenePlayerLoader : ManualInputManagerTestScene { private TestPlayerLoader loader; - private OsuScreenStack stack; + private TestPlayerLoaderContainer container; + private TestPlayer player; - [SetUp] - public void Setup() => Schedule(() => + [Resolved] + private AudioManager audioManager { get; set; } + + /// + /// Sets the input manager child to a new test player loader container instance. + /// + /// If the test player should behave like the production one. + /// An action to run before player load but after bindable leases are returned. + public void ResetPlayer(bool interactive, Action beforeLoadAction = null) { - InputManager.Child = stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }; + audioManager.Volume.SetDefault(); + + InputManager.Clear(); + + beforeLoadAction?.Invoke(); Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); - }); + + InputManager.Child = container = new TestPlayerLoaderContainer( + loader = new TestPlayerLoader(() => player = new TestPlayer(interactive, interactive))); + } [Test] public void TestBlockLoadViaMouseMovement() { - AddStep("load dummy beatmap", () => stack.Push(loader = new TestPlayerLoader(() => new TestPlayer(false, false)))); + AddStep("load dummy beatmap", () => ResetPlayer(false)); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddRepeatStep("move mouse", () => InputManager.MoveMouseTo(loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft + (loader.VisualSettings.ScreenSpaceDrawQuad.BottomRight - loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft) * RNG.NextSingle()), 20); AddAssert("loader still active", () => loader.IsCurrentScreen()); @@ -46,16 +67,17 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestLoadContinuation() { - Player player = null; SlowLoadPlayer slowPlayer = null; - AddStep("load dummy beatmap", () => stack.Push(loader = new TestPlayerLoader(() => player = new TestPlayer(false, false)))); + AddStep("load dummy beatmap", () => ResetPlayer(false)); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); AddUntilStep("wait for player to be current", () => player.IsCurrentScreen()); AddStep("load slow dummy beatmap", () => { - stack.Push(loader = new TestPlayerLoader(() => slowPlayer = new SlowLoadPlayer(false, false))); + InputManager.Child = container = new TestPlayerLoaderContainer( + loader = new TestPlayerLoader(() => slowPlayer = new SlowLoadPlayer(false, false))); + Scheduler.AddDelayed(() => slowPlayer.AllowLoad.Set(), 5000); }); @@ -65,16 +87,11 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestModReinstantiation() { - TestPlayer player = null; TestMod gameMod = null; TestMod playerMod1 = null; TestMod playerMod2 = null; - AddStep("load player", () => - { - Mods.Value = new[] { gameMod = new TestMod() }; - stack.Push(loader = new TestPlayerLoader(() => player = new TestPlayer())); - }); + AddStep("load player", () => { ResetPlayer(true, () => Mods.Value = new[] { gameMod = new TestMod() }); }); AddUntilStep("wait for loader to become current", () => loader.IsCurrentScreen()); AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); @@ -97,6 +114,66 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("player mods applied", () => playerMod2.Applied); } + [Test] + public void TestMutedNotification() + { + AddStep("reset notification", PlayerLoader.ResetNotificationLock); + + AddStep("load player", () => ResetPlayer(false, () => audioManager.Volume.Value = 0)); + AddUntilStep("wait for player", () => player.IsLoaded); + + AddAssert("check for notification", () => container.NotificationOverlay.UnreadCount.Value == 1); + AddStep("click notification", () => + { + var scrollContainer = (OsuScrollContainer)container.NotificationOverlay.Children.Last(); + var flowContainer = scrollContainer.Children.OfType>().First(); + var notification = flowContainer.First(); + + InputManager.MoveMouseTo(notification); + InputManager.Click(MouseButton.Left); + }); + AddAssert("check master volume", () => audioManager.Volume.IsDefault); + + AddStep("restart player", () => + { + var lastPlayer = player; + player = null; + lastPlayer.Restart(); + }); + } + + private class TestPlayerLoaderContainer : Container + { + [Cached] + public readonly NotificationOverlay NotificationOverlay; + + [Cached] + public readonly VolumeOverlay VolumeOverlay; + + public TestPlayerLoaderContainer(IScreen screen) + { + RelativeSizeAxes = Axes.Both; + + InternalChildren = new Drawable[] + { + new OsuScreenStack(screen) + { + RelativeSizeAxes = Axes.Both, + }, + NotificationOverlay = new NotificationOverlay + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }, + VolumeOverlay = new VolumeOverlay + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + } + }; + } + } + private class TestPlayerLoader : PlayerLoader { public new VisualSettings VisualSettings => base.VisualSettings; diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 8f2435d2f7..053e11104f 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -530,7 +530,7 @@ namespace osu.Game.Screens.Play } /// - /// Sets to , reserved for testing. + /// Sets to false, reserved for testing. /// public static void ResetNotificationLock() { From ccb56234877e204009e97e58de868b6a8710b155 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Sep 2019 20:03:03 +0900 Subject: [PATCH 3175/5608] Fix test name --- .../Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index 86f7896457..c3b61fa420 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -117,7 +117,7 @@ namespace osu.Game.Tests.Visual.Gameplay } [Test] - public void TestSliderMultiplierDoesnotAffectRelativeBeatLength() + public void TestSliderMultiplierDoesNotAffectRelativeBeatLength() { var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range }); beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2; From 244627ff10cb1b517634a0278fa26eb27a000d3c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Sep 2019 20:12:01 +0900 Subject: [PATCH 3176/5608] Add comment + test for slider multiplier --- .../Gameplay/TestSceneDrawableScrollingRuleset.cs | 13 +++++++++++++ .../UI/Scrolling/DrawableScrollingRuleset.cs | 2 ++ 2 files changed, 15 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index c3b61fa420..dcab964d6d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -129,6 +129,19 @@ namespace osu.Game.Tests.Visual.Gameplay assertPosition(i, i / 5f); } + [Test] + public void TestSliderMultiplierAffectsNonRelativeBeatLength() + { + var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range }); + beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2; + + createTest(beatmap); + AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 2000); + + assertPosition(0, 0); + assertPosition(1, 1); + } + private void assertPosition(int index, float relativeY) => AddAssert($"hitobject {index} at {relativeY}", () => Precision.AlmostEquals(drawableRuleset.Playfield.AllHitObjects.ElementAt(index).DrawPosition.Y, drawableRuleset.Playfield.HitObjectContainer.DrawHeight * relativeY)); diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 3d56543bab..f178c01fd6 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -131,6 +131,8 @@ namespace osu.Game.Rulesets.UI.Scrolling if (duration > maxDuration) { maxDuration = duration; + // The slider multiplier is post-multiplied to determine the final velocity, but for relative scale beat lengths + // the multiplier should not affect the effective timing point (the longest in the beatmap), so it is factored out here baseBeatLength = timingPoints[i].BeatLength / Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier; } } From 8844d567cb1220dfe1b261ff30108dea5ae1c527 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 25 Sep 2019 15:56:47 +0300 Subject: [PATCH 3177/5608] Use bindable setting instead --- osu.Game/Screens/Menu/MainMenu.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 98ceb315a2..004bba20d4 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -52,9 +52,6 @@ namespace osu.Game.Screens.Menu [Resolved(canBeNull: true)] private LoginOverlay login { get; set; } - [Resolved] - private SessionStatics statics { get; set; } - [Resolved] private IAPIProvider api { get; set; } @@ -66,13 +63,15 @@ namespace osu.Game.Screens.Menu protected override BackgroundScreen CreateBackground() => background; private Bindable holdDelay; + private Bindable loginDisplayed; private ExitConfirmOverlay exitConfirmOverlay; [BackgroundDependencyLoader(true)] - private void load(DirectOverlay direct, SettingsOverlay settings, OsuConfigManager config) + private void load(DirectOverlay direct, SettingsOverlay settings, OsuConfigManager config, SessionStatics statics) { holdDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); + loginDisplayed = statics.GetBindable(Statics.LoginOverlayDisplayed); if (host.CanExit) { @@ -200,10 +199,10 @@ namespace osu.Game.Screens.Menu bool displayLogin() { - if (!statics.Get(Statics.LoginOverlayDisplayed)) + if (!loginDisplayed.Value) { Scheduler.AddDelayed(() => login?.Show(), 500); - statics.Set(Statics.LoginOverlayDisplayed, true); + loginDisplayed.Value = true; } return true; From 42fd323020f3df9f16be166a91935e6ffb046302 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Sep 2019 22:13:49 +0900 Subject: [PATCH 3178/5608] Move protected method --- 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 aaaa320093..3a7e53905c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -106,8 +106,6 @@ namespace osu.Game private readonly List visibleBlockingOverlays = new List(); - protected virtual Loader CreateLoader() => new Loader(); - public OsuGame(string[] args = null) { this.args = args; @@ -322,6 +320,8 @@ namespace osu.Game }, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true); } + protected virtual Loader CreateLoader() => new Loader(); + #region Beatmap progression private void beatmapChanged(ValueChangedEvent beatmap) From 45f833ceea17628cc54856bb9aa58916e0dc6589 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Sep 2019 22:14:42 +0900 Subject: [PATCH 3179/5608] Add invocation null checks for safety --- osu.Game/Graphics/UserInterface/BackButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 5fa634425b..62c33b9a39 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -18,7 +18,7 @@ namespace osu.Game.Graphics.UserInterface public BackButton(Receptor receptor) { - receptor.OnBackPressed = () => Action.Invoke(); + receptor.OnBackPressed = () => Action?.Invoke(); Size = TwoLayerButton.SIZE_EXTENDED; @@ -60,7 +60,7 @@ namespace osu.Game.Graphics.UserInterface switch (action) { case GlobalAction.Back: - OnBackPressed.Invoke(); + OnBackPressed?.Invoke(); return true; } From 911094e79049a244a68912c01e717015689c8ff0 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 26 Sep 2019 01:42:56 +0300 Subject: [PATCH 3180/5608] Replace menu button text with "press for menu" on 0ms activation delay --- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 91c14591b1..6b2bbc13b7 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.MathUtils; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -45,7 +46,6 @@ namespace osu.Game.Screens.Play.HUD { text = new OsuSpriteText { - Text = "hold for menu", Font = OsuFont.GetFont(weight: FontWeight.Bold), Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft @@ -60,6 +60,14 @@ namespace osu.Game.Screens.Play.HUD AutoSizeAxes = Axes.Both; } + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + text.Text = config.Get(OsuSetting.UIHoldActivationDelay) > 0 + ? "hold for menu" + : "press for menu"; + } + protected override void LoadComplete() { text.FadeInFromZero(500, Easing.OutQuint).Delay(1500).FadeOut(500, Easing.OutQuint); From 186ea9821708da3260601fc9f6c9ba08ad4e49be Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 26 Sep 2019 02:23:18 +0300 Subject: [PATCH 3181/5608] Wait for track to start running instead --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index 7e792f0b40..cd46bc63a9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -41,10 +41,8 @@ namespace osu.Game.Rulesets.Osu.Tests { base.SetUpSteps(); + AddUntilStep("wait for track to start running", () => track.IsRunning); AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)((TestPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.First()); - - // wait for frame stable clock time to hit 0 (for some reason, executing a seek while current time is below 0 doesn't seek successfully) - addSeekStep(0); } [Test] From d773f0cce18b7bad01bebd4f593504ae670658cb Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 26 Sep 2019 04:38:20 +0300 Subject: [PATCH 3182/5608] Override autoplay bool instead of adding it --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index cd46bc63a9..4eb4c21c90 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -27,6 +27,8 @@ namespace osu.Game.Rulesets.Osu.Tests private TrackVirtualManual track; + protected override bool Autoplay => true; + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) { var working = new ClockBackedTestWorkingBeatmap(beatmap, new FramedClock(new ManualClock { Rate = 1 }), audioManager); @@ -75,12 +77,6 @@ namespace osu.Game.Rulesets.Osu.Tests AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, ((TestPlayer)Player).DrawableRuleset.FrameStableClock.CurrentTime, 100)); } - protected override Player CreatePlayer(Ruleset ruleset) - { - Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); - return new TestPlayer(); - } - protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap { HitObjects = new List From c57868795e08063241810b497ccc072d78972513 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 26 Sep 2019 04:38:57 +0300 Subject: [PATCH 3183/5608] Remove redundant using directive --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index 4eb4c21c90..cded7f0e95 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -11,7 +11,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Screens.Play; using osu.Game.Tests.Visual; using osuTK; using System.Collections.Generic; From bbf0544a8d0f476eb969aec5852042b286730e94 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Sep 2019 16:55:08 +0900 Subject: [PATCH 3184/5608] Add bindables for IHasComboInformation properties --- .../Objects/CatchHitObject.cs | 25 +++++++++++++-- osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 32 ++++++++++++++++--- .../Objects/Types/IHasComboInformation.cs | 8 +++++ 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index a25d9cb67e..77d7de989a 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Catch.Beatmaps; @@ -37,9 +38,21 @@ namespace osu.Game.Rulesets.Catch.Objects public int ComboOffset { get; set; } - public int IndexInCurrentCombo { get; set; } + public Bindable IndexInCurrentComboBindable { get; } = new Bindable(); - public int ComboIndex { get; set; } + public int IndexInCurrentCombo + { + get => IndexInCurrentComboBindable.Value; + set => IndexInCurrentComboBindable.Value = value; + } + + public Bindable ComboIndexBindable { get; } = new Bindable(); + + public int ComboIndex + { + get => ComboIndexBindable.Value; + set => ComboIndexBindable.Value = value; + } /// /// Difference between the distance to the next object @@ -48,10 +61,16 @@ namespace osu.Game.Rulesets.Catch.Objects /// public float DistanceToHyperDash { get; set; } + public Bindable LastInComboBindable { get; } = new Bindable(); + /// /// The next fruit starts a new combo. Used for explodey. /// - public virtual bool LastInCombo { get; set; } + public virtual bool LastInCombo + { + get => LastInComboBindable.Value; + set => LastInComboBindable.Value = value; + } public float Scale { get; set; } = 1; diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 2cf877b000..80e013fe68 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -58,13 +58,37 @@ namespace osu.Game.Rulesets.Osu.Objects public virtual bool NewCombo { get; set; } - public int ComboOffset { get; set; } + public readonly Bindable ComboOffsetBindable = new Bindable(); - public virtual int IndexInCurrentCombo { get; set; } + public int ComboOffset + { + get => ComboOffsetBindable.Value; + set => ComboOffsetBindable.Value = value; + } - public virtual int ComboIndex { get; set; } + public Bindable IndexInCurrentComboBindable { get; } = new Bindable(); - public bool LastInCombo { get; set; } + public virtual int IndexInCurrentCombo + { + get => IndexInCurrentComboBindable.Value; + set => IndexInCurrentComboBindable.Value = value; + } + + public Bindable ComboIndexBindable { get; } = new Bindable(); + + public virtual int ComboIndex + { + get => ComboIndexBindable.Value; + set => ComboIndexBindable.Value = value; + } + + public Bindable LastInComboBindable { get; } = new Bindable(); + + public bool LastInCombo + { + get => LastInComboBindable.Value; + set => LastInComboBindable.Value = value; + } protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { diff --git a/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs b/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs index e07da93a3a..4e3de04278 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; + namespace osu.Game.Rulesets.Objects.Types { /// @@ -8,16 +10,22 @@ namespace osu.Game.Rulesets.Objects.Types /// public interface IHasComboInformation : IHasCombo { + Bindable IndexInCurrentComboBindable { get; } + /// /// The offset of this hitobject in the current combo. /// int IndexInCurrentCombo { get; set; } + Bindable ComboIndexBindable { get; } + /// /// The offset of this combo in relation to the beatmap. /// int ComboIndex { get; set; } + Bindable LastInComboBindable { get; } + /// /// Whether this is the last object in the current combo. /// From 3155a9050119ecb1edf3aad8fa6518fe2cd104fa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Sep 2019 16:57:58 +0900 Subject: [PATCH 3185/5608] Use bindables for displayed circle piece numbers --- .../Objects/Drawables/DrawableHitCircle.cs | 2 +- .../Objects/Drawables/Pieces/MainCirclePiece.cs | 16 +++++++++------- .../Skinning/LegacyMainCirclePiece.cs | 16 +++++++++------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index c90f230f93..bb227d76df 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return true; }, }, - CirclePiece = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.HitCircle), _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)), + CirclePiece = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.HitCircle), _ => new MainCirclePiece()), ApproachCircle = new ApproachCircle { Alpha = 0, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/MainCirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/MainCirclePiece.cs index 944c93bb6d..e364c96426 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/MainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/MainCirclePiece.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private readonly NumberPiece number; private readonly GlowPiece glow; - public MainCirclePiece(int index) + public MainCirclePiece() { Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); @@ -31,10 +31,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { glow = new GlowPiece(), circle = new CirclePiece(), - number = new NumberPiece - { - Text = (index + 1).ToString(), - }, + number = new NumberPiece(), ring = new RingPiece(), flash = new FlashPiece(), explode = new ExplodePiece(), @@ -42,12 +39,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } private readonly IBindable state = new Bindable(); - - private readonly Bindable accentColour = new Bindable(); + private readonly IBindable accentColour = new Bindable(); + private readonly IBindable indexInCurrentCombo = new Bindable(); [BackgroundDependencyLoader] private void load(DrawableHitObject drawableObject) { + OsuHitObject osuObject = (OsuHitObject)drawableObject.HitObject; + state.BindTo(drawableObject.State); state.BindValueChanged(updateState, true); @@ -58,6 +57,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces glow.Colour = colour.NewValue; circle.Colour = colour.NewValue; }, true); + + indexInCurrentCombo.BindTo(osuObject.IndexInCurrentComboBindable); + indexInCurrentCombo.BindValueChanged(index => number.Text = (index.NewValue + 1).ToString(), true); } private void updateState(ValueChangedEvent state) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs index 83d507f64b..93ae0371df 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Skinning; using osuTK; @@ -25,13 +24,16 @@ namespace osu.Game.Rulesets.Osu.Skinning } private readonly IBindable state = new Bindable(); - private readonly Bindable accentColour = new Bindable(); + private readonly IBindable indexInCurrentCombo = new Bindable(); [BackgroundDependencyLoader] private void load(DrawableHitObject drawableObject, ISkinSource skin) { + OsuHitObject osuObject = (OsuHitObject)drawableObject.HitObject; + Sprite hitCircleSprite; + SkinnableSpriteText hitCircleText; InternalChildren = new Drawable[] { @@ -42,14 +44,11 @@ namespace osu.Game.Rulesets.Osu.Skinning Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - new SkinnableSpriteText(new OsuSkinComponent(OsuSkinComponents.HitCircleText), _ => new OsuSpriteText + hitCircleText = new SkinnableSpriteText(new OsuSkinComponent(OsuSkinComponents.HitCircleText), _ => new OsuSpriteText { Font = OsuFont.Numeric.With(size: 40), UseFullGlyphHeight = false, - }, confineMode: ConfineMode.NoScaling) - { - Text = (((IHasComboInformation)drawableObject.HitObject).IndexInCurrentCombo + 1).ToString() - }, + }, confineMode: ConfineMode.NoScaling), new Sprite { Texture = skin.GetTexture("hitcircleoverlay"), @@ -63,6 +62,9 @@ namespace osu.Game.Rulesets.Osu.Skinning accentColour.BindTo(drawableObject.AccentColour); accentColour.BindValueChanged(colour => hitCircleSprite.Colour = colour.NewValue, true); + + indexInCurrentCombo.BindTo(osuObject.IndexInCurrentComboBindable); + indexInCurrentCombo.BindValueChanged(index => hitCircleText.Text = (index.NewValue + 1).ToString(), true); } private void updateState(ValueChangedEvent state) From 706e884cc05cdd04cb4e56cb3e1f0c9f583e1d0e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Sep 2019 17:04:38 +0900 Subject: [PATCH 3186/5608] Update accent colour on combo index change --- .../Objects/Drawables/DrawableHitObject.cs | 25 ++++++++++++++----- osu.Game/Skinning/SkinReloadableDrawable.cs | 20 +++++++++------ 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 8d8f8a419f..f8bc74b2a6 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -76,6 +76,8 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public JudgementResult Result { get; private set; } + private Bindable comboIndexBindable; + public override bool RemoveWhenNotAlive => false; public override bool RemoveCompletedTransforms => false; protected override bool RequiresChildrenUpdate => true; @@ -122,6 +124,13 @@ namespace osu.Game.Rulesets.Objects.Drawables protected override void LoadComplete() { base.LoadComplete(); + + if (HitObject is IHasComboInformation combo) + { + comboIndexBindable = combo.ComboIndexBindable.GetBoundCopy(); + comboIndexBindable.BindValueChanged(_ => updateAccentColour()); + } + updateState(ArmedState.Idle, true); } @@ -244,12 +253,7 @@ namespace osu.Game.Rulesets.Objects.Drawables { base.SkinChanged(skin, allowFallback); - if (HitObject is IHasComboInformation combo) - { - var comboColours = skin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value; - - AccentColour.Value = comboColours?.Count > 0 ? comboColours[combo.ComboIndex % comboColours.Count] : Color4.White; - } + updateAccentColour(); ApplySkin(skin, allowFallback); @@ -257,6 +261,15 @@ namespace osu.Game.Rulesets.Objects.Drawables updateState(State.Value, true); } + private void updateAccentColour() + { + if (HitObject is IHasComboInformation combo) + { + var comboColours = CurrentSkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value; + AccentColour.Value = comboColours?.Count > 0 ? comboColours[combo.ComboIndex % comboColours.Count] : Color4.White; + } + } + /// /// Called when a change is made to the skin. /// diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index 4bbdeafba5..6d0b22dd51 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -12,13 +12,17 @@ namespace osu.Game.Skinning /// public abstract class SkinReloadableDrawable : CompositeDrawable { + /// + /// The current skin source. + /// + protected ISkinSource CurrentSkin { get; private set; } + private readonly Func allowFallback; - private ISkinSource skin; /// /// Whether fallback to default skin should be allowed if the custom skin is missing this resource. /// - private bool allowDefaultFallback => allowFallback == null || allowFallback.Invoke(skin); + private bool allowDefaultFallback => allowFallback == null || allowFallback.Invoke(CurrentSkin); /// /// Create a new @@ -32,19 +36,19 @@ namespace osu.Game.Skinning [BackgroundDependencyLoader] private void load(ISkinSource source) { - skin = source; - skin.SourceChanged += onChange; + CurrentSkin = source; + CurrentSkin.SourceChanged += onChange; } private void onChange() => // schedule required to avoid calls after disposed. // note that this has the side-effect of components only performing a skin change when they are alive. - Scheduler.AddOnce(() => SkinChanged(skin, allowDefaultFallback)); + Scheduler.AddOnce(() => SkinChanged(CurrentSkin, allowDefaultFallback)); protected override void LoadAsyncComplete() { base.LoadAsyncComplete(); - SkinChanged(skin, allowDefaultFallback); + SkinChanged(CurrentSkin, allowDefaultFallback); } /// @@ -60,8 +64,8 @@ namespace osu.Game.Skinning { base.Dispose(isDisposing); - if (skin != null) - skin.SourceChanged -= onChange; + if (CurrentSkin != null) + CurrentSkin.SourceChanged -= onChange; } } } From ea76dd6a9e1adde6941005ffb6114bcceced2a52 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Sep 2019 17:18:16 +0900 Subject: [PATCH 3187/5608] Add test scene for hitcircles and combo changes --- .../TestSceneHitCircleComboChange.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs new file mode 100644 index 0000000000..5695462859 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Rulesets.Osu.Objects; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestSceneHitCircleComboChange : TestSceneHitCircle + { + private readonly Bindable comboIndex = new Bindable(); + + protected override void LoadComplete() + { + base.LoadComplete(); + Scheduler.AddDelayed(() => comboIndex.Value++, 250, true); + } + + protected override TestDrawableHitCircle CreateDrawableHitCircle(HitCircle circle, bool auto) + { + circle.ComboIndexBindable.BindTo(comboIndex); + circle.IndexInCurrentComboBindable.BindTo(comboIndex); + return base.CreateDrawableHitCircle(circle, auto); + } + } +} From 45f2bcc440c4aea51f0905b4da7f1128dcc415f3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Sep 2019 17:39:19 +0900 Subject: [PATCH 3188/5608] Fix combo bindings not being bound to nested hitobjects --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 26 ------------------------- osu.Game/Beatmaps/BeatmapProcessor.cs | 20 ------------------- osu.Game/Rulesets/Objects/HitObject.cs | 10 ++++++++++ 3 files changed, 10 insertions(+), 46 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 2805494021..d8514092bc 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -33,28 +33,6 @@ namespace osu.Game.Rulesets.Osu.Objects public Vector2 StackedPositionAt(double t) => StackedPosition + this.CurvePositionAt(t); - public override int ComboIndex - { - get => base.ComboIndex; - set - { - base.ComboIndex = value; - foreach (var n in NestedHitObjects.OfType()) - n.ComboIndex = value; - } - } - - public override int IndexInCurrentCombo - { - get => base.IndexInCurrentCombo; - set - { - base.IndexInCurrentCombo = value; - foreach (var n in NestedHitObjects.OfType()) - n.IndexInCurrentCombo = value; - } - } - public readonly Bindable PathBindable = new Bindable(); public SliderPath Path @@ -192,8 +170,6 @@ namespace osu.Game.Rulesets.Osu.Objects Position = Position, Samples = getNodeSamples(0), SampleControlPoint = SampleControlPoint, - IndexInCurrentCombo = IndexInCurrentCombo, - ComboIndex = ComboIndex, }); break; @@ -205,8 +181,6 @@ namespace osu.Game.Rulesets.Osu.Objects { StartTime = e.Time, Position = EndPosition, - IndexInCurrentCombo = IndexInCurrentCombo, - ComboIndex = ComboIndex, }); break; diff --git a/osu.Game/Beatmaps/BeatmapProcessor.cs b/osu.Game/Beatmaps/BeatmapProcessor.cs index 7a612893c9..250cc49ad4 100644 --- a/osu.Game/Beatmaps/BeatmapProcessor.cs +++ b/osu.Game/Beatmaps/BeatmapProcessor.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Beatmaps @@ -45,25 +44,6 @@ namespace osu.Game.Beatmaps public virtual void PostProcess() { - void updateNestedCombo(HitObject obj, int comboIndex, int indexInCurrentCombo) - { - if (obj is IHasComboInformation objectComboInfo) - { - objectComboInfo.ComboIndex = comboIndex; - objectComboInfo.IndexInCurrentCombo = indexInCurrentCombo; - foreach (var nestedObject in obj.NestedHitObjects) - updateNestedCombo(nestedObject, comboIndex, indexInCurrentCombo); - } - } - - foreach (var hitObject in Beatmap.HitObjects) - { - if (hitObject is IHasComboInformation objectComboInfo) - { - foreach (var nested in hitObject.NestedHitObjects) - updateNestedCombo(nested, objectComboInfo.ComboIndex, objectComboInfo.IndexInCurrentCombo); - } - } } } } diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 96297ab44f..6c5627c5d2 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using JetBrains.Annotations; using Newtonsoft.Json; using osu.Game.Audio; @@ -82,6 +83,15 @@ namespace osu.Game.Rulesets.Objects CreateNestedHitObjects(); + if (this is IHasComboInformation hasCombo) + { + foreach (var n in NestedHitObjects.OfType()) + { + n.ComboIndexBindable.BindTo(hasCombo.ComboIndexBindable); + n.IndexInCurrentComboBindable.BindTo(hasCombo.IndexInCurrentComboBindable); + } + } + nestedHitObjects.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime)); foreach (var h in nestedHitObjects) From e4e66344322dc9733b61e464712541c4ac1b51fe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Sep 2019 17:39:26 +0900 Subject: [PATCH 3189/5608] Add slider combo change test --- .../TestSceneSlider.cs | 12 ++++---- .../TestSceneSliderComboChange.cs | 28 +++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 29c71a8903..6a4201f84d 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -297,11 +297,7 @@ namespace osu.Game.Rulesets.Osu.Tests slider.ApplyDefaults(cpi, new BeatmapDifficulty { CircleSize = circleSize, SliderTickRate = 3 }); - var drawable = new DrawableSlider(slider) - { - Anchor = Anchor.Centre, - Depth = depthIndex++ - }; + var drawable = CreateDrawableSlider(slider); foreach (var mod in Mods.Value.OfType()) mod.ApplyToDrawableHitObjects(new[] { drawable }); @@ -311,6 +307,12 @@ namespace osu.Game.Rulesets.Osu.Tests return drawable; } + protected virtual DrawableSlider CreateDrawableSlider(Slider slider) => new DrawableSlider(slider) + { + Anchor = Anchor.Centre, + Depth = depthIndex++ + }; + private float judgementOffsetDirection = 1; private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs new file mode 100644 index 0000000000..13ced3019e --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs @@ -0,0 +1,28 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestSceneSliderComboChange : TestSceneSlider + { + private readonly Bindable comboIndex = new Bindable(); + + protected override void LoadComplete() + { + base.LoadComplete(); + Scheduler.AddDelayed(() => comboIndex.Value++, 250, true); + } + + protected override DrawableSlider CreateDrawableSlider(Slider slider) + { + slider.ComboIndexBindable.BindTo(comboIndex); + slider.IndexInCurrentComboBindable.BindTo(comboIndex); + + return base.CreateDrawableSlider(slider); + } + } +} From 9a31ccd2e34bc56960e714db87bda72c5fb6282a Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Thu, 26 Sep 2019 14:05:43 +0200 Subject: [PATCH 3190/5608] Add missing test cases for master, track and mute button This also modifies the reset player method to make it possible to set something before the player is loaded but after the container has loaded. --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index eb54eca0cb..e1a2cdcca3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -41,7 +41,8 @@ namespace osu.Game.Tests.Visual.Gameplay /// /// If the test player should behave like the production one. /// An action to run before player load but after bindable leases are returned. - public void ResetPlayer(bool interactive, Action beforeLoadAction = null) + /// An action to run after container load. + public void ResetPlayer(bool interactive, Action beforeLoadAction = null, Action afterLoadAction = null) { audioManager.Volume.SetDefault(); @@ -51,7 +52,11 @@ namespace osu.Game.Tests.Visual.Gameplay Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); InputManager.Child = container = new TestPlayerLoaderContainer( - loader = new TestPlayerLoader(() => player = new TestPlayer(interactive, interactive))); + loader = new TestPlayerLoader(() => + { + afterLoadAction?.Invoke(); + return player = new TestPlayer(interactive, interactive); + })); } [Test] @@ -115,11 +120,26 @@ namespace osu.Game.Tests.Visual.Gameplay } [Test] - public void TestMutedNotification() - { - AddStep("reset notification", PlayerLoader.ResetNotificationLock); + public void TestMutedNotificationMasterVolume() => addVolumeSteps("master volume", () => audioManager.Volume.Value = 0, null, () => audioManager.Volume.IsDefault); - AddStep("load player", () => ResetPlayer(false, () => audioManager.Volume.Value = 0)); + [Test] + public void TestMutedNotificationTrackVolume() => addVolumeSteps("music volume", () => audioManager.Volume.Value = 0, null, () => audioManager.Volume.IsDefault); + + [Test] + public void TestMutedNotificationMuteButton() => addVolumeSteps("mute button", null, () => container.VolumeOverlay.IsMuted.Value = true, () => !container.VolumeOverlay.IsMuted.Value); + + /// + /// Created for avoiding copy pasting code for the same steps. + /// + /// What part of the volume system is checked + /// The action to be invoked to set the volume before loading + /// The action to be invoked to set the volume after loading + /// The function to be invoked and checked + private void addVolumeSteps(string volumeName, Action beforeLoad, Action afterLoad, Func assert) + { + AddStep("reset notification lock", PlayerLoader.ResetNotificationLock); + + AddStep("load player", () => ResetPlayer(false, beforeLoad, afterLoad)); AddUntilStep("wait for player", () => player.IsLoaded); AddAssert("check for notification", () => container.NotificationOverlay.UnreadCount.Value == 1); @@ -132,14 +152,8 @@ namespace osu.Game.Tests.Visual.Gameplay InputManager.MoveMouseTo(notification); InputManager.Click(MouseButton.Left); }); - AddAssert("check master volume", () => audioManager.Volume.IsDefault); - AddStep("restart player", () => - { - var lastPlayer = player; - player = null; - lastPlayer.Restart(); - }); + AddAssert("check " + volumeName, assert); } private class TestPlayerLoaderContainer : Container From 7904f77cd5cd716c6547b3ee8a7dea2bd79ce5df Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 27 Sep 2019 02:59:42 +0300 Subject: [PATCH 3191/5608] Bind event to activation delay change --- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 6b2bbc13b7..9c1435ef3d 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -63,9 +63,13 @@ namespace osu.Game.Screens.Play.HUD [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - text.Text = config.Get(OsuSetting.UIHoldActivationDelay) > 0 - ? "hold for menu" - : "press for menu"; + var activationDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay).GetBoundCopy(); + activationDelay.BindValueChanged(v => + { + text.Text = v.NewValue > 0 + ? "hold for menu" + : "press for menu"; + }, true); } protected override void LoadComplete() From 2670a23e6f313875aeb0301d7cd6fc67b7c253ea Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 27 Sep 2019 08:15:24 +0300 Subject: [PATCH 3192/5608] Assign to field and move to load complete --- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 9c1435ef3d..2dc50326a8 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -60,21 +60,23 @@ namespace osu.Game.Screens.Play.HUD AutoSizeAxes = Axes.Both; } - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) + [Resolved] + private OsuConfigManager config { get; set; } + + private Bindable activationDelay; + + protected override void LoadComplete() { - var activationDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay).GetBoundCopy(); + activationDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); activationDelay.BindValueChanged(v => { text.Text = v.NewValue > 0 ? "hold for menu" : "press for menu"; }, true); - } - protected override void LoadComplete() - { text.FadeInFromZero(500, Easing.OutQuint).Delay(1500).FadeOut(500, Easing.OutQuint); + base.LoadComplete(); } From b50ef8ffa4855cecb9ae195accd455669b279feb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 27 Sep 2019 13:15:33 +0800 Subject: [PATCH 3193/5608] Allow null NotificationManager --- osu.Game/Screens/Play/PlayerLoader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 053e11104f..6cde7522d4 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Play private IdleTracker idleTracker; - [Resolved] + [Resolved(CanBeNull = true)] private NotificationOverlay notificationOverlay { get; set; } [Resolved] @@ -164,7 +164,7 @@ namespace osu.Game.Screens.Play //Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. if (!muteWarningShownOnce && (volumeOverlay.IsMuted.Value || audio.Volume.Value <= audio.Volume.MinValue || audio.VolumeTrack.Value <= audio.VolumeTrack.MinValue)) { - notificationOverlay.Post(new MutedNotification()); + notificationOverlay?.Post(new MutedNotification()); muteWarningShownOnce = true; } } From f4f5a7e9c8be2b2d0f48a9b5be9a8761d4b856b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 27 Sep 2019 13:20:17 +0800 Subject: [PATCH 3194/5608] Fix test regressions --- osu.Game/Screens/Play/PlayerLoader.cs | 32 +++++++++++++++------------ 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 6cde7522d4..157ff8fcd4 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -59,17 +59,6 @@ namespace osu.Game.Screens.Play private IdleTracker idleTracker; - [Resolved(CanBeNull = true)] - private NotificationOverlay notificationOverlay { get; set; } - - [Resolved] - private VolumeOverlay volumeOverlay { get; set; } - - [Resolved] - private AudioManager audioManager { get; set; } - - private static bool muteWarningShownOnce; - public PlayerLoader(Func createPlayer) { this.createPlayer = createPlayer; @@ -159,10 +148,24 @@ namespace osu.Game.Screens.Play content.FadeOut(250); } - private void checkVolume(AudioManager audio) + [Resolved(CanBeNull = true)] + private NotificationOverlay notificationOverlay { get; set; } + + [Resolved(CanBeNull = true)] + private VolumeOverlay volumeOverlay { get; set; } + + [Resolved] + private AudioManager audioManager { get; set; } + + private static bool muteWarningShownOnce; + + private void checkVolume() { + if (muteWarningShownOnce) + return; + //Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. - if (!muteWarningShownOnce && (volumeOverlay.IsMuted.Value || audio.Volume.Value <= audio.Volume.MinValue || audio.VolumeTrack.Value <= audio.VolumeTrack.MinValue)) + if (volumeOverlay?.IsMuted.Value == true || audioManager.Volume.Value <= audioManager.Volume.MinValue || audioManager.VolumeTrack.Value <= audioManager.VolumeTrack.MinValue) { notificationOverlay?.Post(new MutedNotification()); muteWarningShownOnce = true; @@ -213,7 +216,8 @@ namespace osu.Game.Screens.Play { inputManager = GetContainingInputManager(); base.LoadComplete(); - checkVolume(audioManager); + + checkVolume(); } private ScheduledDelegate pushDebounce; From 67bed57cbdf3f0921a6a721c74cc28317afc74c7 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 27 Sep 2019 08:46:49 +0300 Subject: [PATCH 3195/5608] Bind value changed event of cursor trail appearence outside BDL https://github.com/ppy/osu/pull/6270#discussion_r328899728 --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index a944ff88c6..6dbdf0114d 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -40,6 +40,11 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private void load(OsuRulesetConfigManager config) { config?.BindWith(OsuRulesetSetting.ShowCursorTrail, showTrail); + } + + protected override void LoadComplete() + { + base.LoadComplete(); showTrail.BindValueChanged(v => cursorTrail.FadeTo(v.NewValue ? 1 : 0, 200), true); } From 94eacbca5dde273bec3a0f2073af9e0ce5cb3097 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 27 Sep 2019 09:22:25 +0300 Subject: [PATCH 3196/5608] Fix Bot users have all the profile sections in ProfileOverlay --- osu.Game/Overlays/UserProfileOverlay.cs | 5 ++++- osu.Game/Users/User.cs | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index b924b3302f..bc16711ea8 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -44,7 +44,7 @@ namespace osu.Game.Overlays Clear(); lastSection = null; - sections = new ProfileSection[] + sections = !user.IsBot ? new ProfileSection[] { //new AboutSection(), new RecentSection(), @@ -53,6 +53,9 @@ namespace osu.Game.Overlays new HistoricalSection(), new BeatmapsSection(), new KudosuSection() + } : new ProfileSection[] + { + //new AboutSection(), }; tabs = new ProfileTabControl diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 9986f70557..1cb395fd75 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -78,6 +78,9 @@ namespace osu.Game.Users [JsonProperty(@"is_bng")] public bool IsBNG; + [JsonProperty(@"is_bot")] + public bool IsBot; + [JsonProperty(@"is_active")] public bool Active; From 475455d7cd5f02275ceeed31e34baf63a9bc465a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 27 Sep 2019 09:32:46 +0300 Subject: [PATCH 3197/5608] Add missing line breaks --- osu.Game/Overlays/UserProfileOverlay.cs | 28 +++++++++++++------------ 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index bc16711ea8..57b9b6c965 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -44,19 +44,21 @@ namespace osu.Game.Overlays Clear(); lastSection = null; - sections = !user.IsBot ? new ProfileSection[] - { - //new AboutSection(), - new RecentSection(), - new RanksSection(), - //new MedalsSection(), - new HistoricalSection(), - new BeatmapsSection(), - new KudosuSection() - } : new ProfileSection[] - { - //new AboutSection(), - }; + sections = !user.IsBot ? + new ProfileSection[] + { + //new AboutSection(), + new RecentSection(), + new RanksSection(), + //new MedalsSection(), + new HistoricalSection(), + new BeatmapsSection(), + new KudosuSection() + } : + new ProfileSection[] + { + //new AboutSection(), + }; tabs = new ProfileTabControl { From 4908cb826b78d964025708865cc695adb7202a4e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 27 Sep 2019 09:46:11 +0300 Subject: [PATCH 3198/5608] Fix line breaks --- osu.Game/Overlays/UserProfileOverlay.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 57b9b6c965..468eb22b01 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -44,8 +44,8 @@ namespace osu.Game.Overlays Clear(); lastSection = null; - sections = !user.IsBot ? - new ProfileSection[] + sections = !user.IsBot + ? new ProfileSection[] { //new AboutSection(), new RecentSection(), @@ -54,8 +54,8 @@ namespace osu.Game.Overlays new HistoricalSection(), new BeatmapsSection(), new KudosuSection() - } : - new ProfileSection[] + } + : new ProfileSection[] { //new AboutSection(), }; From 06c32d52dca8e465d34546af08505f234f7183a5 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Fri, 27 Sep 2019 09:19:39 +0200 Subject: [PATCH 3199/5608] Change wrong volume bindable used in test --- osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index e1a2cdcca3..6866fd4c62 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -123,7 +123,7 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestMutedNotificationMasterVolume() => addVolumeSteps("master volume", () => audioManager.Volume.Value = 0, null, () => audioManager.Volume.IsDefault); [Test] - public void TestMutedNotificationTrackVolume() => addVolumeSteps("music volume", () => audioManager.Volume.Value = 0, null, () => audioManager.Volume.IsDefault); + public void TestMutedNotificationTrackVolume() => addVolumeSteps("music volume", () => audioManager.VolumeTrack.Value = 0, null, () => audioManager.VolumeTrack.IsDefault); [Test] public void TestMutedNotificationMuteButton() => addVolumeSteps("mute button", null, () => container.VolumeOverlay.IsMuted.Value = true, () => !container.VolumeOverlay.IsMuted.Value); From f64fe22f3669cd2117a295d490ecd6a9f14b8f0e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 27 Sep 2019 18:00:24 +0900 Subject: [PATCH 3200/5608] Remove bindables from osu! selection blueprints --- .../HitCircles/Components/HitCirclePiece.cs | 10 +++++++--- .../Edit/Blueprints/HitObjectPiece.cs | 19 ++----------------- .../Edit/Blueprints/SliderPiece.cs | 17 +++-------------- .../Components/PathControlPointVisualiser.cs | 9 ++------- .../Sliders/Components/SliderBodyPiece.cs | 6 +++--- .../Sliders/Components/SliderCirclePiece.cs | 12 ------------ .../Spinners/Components/SpinnerPiece.cs | 12 +++++++----- 7 files changed, 24 insertions(+), 61 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs index fe11ead94d..99928cdad9 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs @@ -31,10 +31,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components private void load(OsuColour colours) { Colour = colours.Yellow; + } - PositionBindable.BindValueChanged(_ => UpdatePosition(), true); - StackHeightBindable.BindValueChanged(_ => UpdatePosition()); - ScaleBindable.BindValueChanged(scale => Scale = new Vector2(scale.NewValue), true); + protected override void Update() + { + base.Update(); + + UpdatePosition(); + Scale = new Vector2(hitCircle.Scale); } protected virtual void UpdatePosition() => Position = hitCircle.StackedPosition; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs index 315a5a2b9d..3d7d609c6b 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs @@ -1,11 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu.Objects; -using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints { @@ -14,23 +11,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints /// public abstract class HitObjectPiece : CompositeDrawable { - protected readonly IBindable PositionBindable = new Bindable(); - protected readonly IBindable StackHeightBindable = new Bindable(); - protected readonly IBindable ScaleBindable = new Bindable(); - - private readonly OsuHitObject hitObject; + protected readonly OsuHitObject HitObject; protected HitObjectPiece(OsuHitObject hitObject) { - this.hitObject = hitObject; - } - - [BackgroundDependencyLoader] - private void load() - { - PositionBindable.BindTo(hitObject.PositionBindable); - StackHeightBindable.BindTo(hitObject.StackHeightBindable); - ScaleBindable.BindTo(hitObject.ScaleBindable); + HitObject = hitObject; } } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs index 8fd1d6d6f9..e0fcf8a000 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs @@ -1,32 +1,21 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Edit.Blueprints { /// - /// A piece of a blueprint which responds to changes in the state of a . + /// A piece of a blueprint which responds to changes in the state of a . /// public abstract class SliderPiece : HitObjectPiece { - protected readonly IBindable PathBindable = new Bindable(); - - private readonly Slider slider; + protected readonly Slider Slider; protected SliderPiece(Slider slider) : base(slider) { - this.slider = slider; - } - - [BackgroundDependencyLoader] - private void load() - { - PathBindable.BindTo(slider.PathBindable); + Slider = slider; } } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index df846b5d5b..3d8e014551 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu.Objects; @@ -22,14 +21,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components InternalChild = pieces = new Container { RelativeSizeAxes = Axes.Both }; } - [BackgroundDependencyLoader] - private void load() + protected override void Update() { - PathBindable.BindValueChanged(_ => updatePathControlPoints(), true); - } + base.Update(); - private void updatePathControlPoints() - { while (slider.Path.ControlPoints.Length > pieces.Count) pieces.Add(new PathControlPointPiece(slider, pieces.Count)); while (slider.Path.ControlPoints.Length < pieces.Count) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index f1f55731b6..aea17a4b8f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -31,9 +31,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private void load(OsuColour colours) { body.BorderColour = colours.Yellow; - - PositionBindable.BindValueChanged(_ => updatePosition(), true); - ScaleBindable.BindValueChanged(scale => body.PathRadius = scale.NewValue * OsuHitObject.OBJECT_RADIUS, true); } private void updatePosition() => Position = slider.StackedPosition; @@ -42,6 +39,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { base.Update(); + Position = slider.StackedPosition; + body.PathRadius = HitObject.Scale * OsuHitObject.OBJECT_RADIUS; + var vertices = new List(); slider.Path.GetPathToProgress(vertices, 0, 1); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs index 2ecfea2e3e..ec3a1d0034 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs @@ -1,9 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; @@ -11,8 +8,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public class SliderCirclePiece : HitCirclePiece { - private readonly IBindable pathBindable = new Bindable(); - private readonly Slider slider; private readonly SliderPosition position; @@ -23,13 +18,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components this.position = position; } - [BackgroundDependencyLoader] - private void load() - { - pathBindable.BindTo(slider.PathBindable); - pathBindable.BindValueChanged(_ => UpdatePosition(), true); - } - protected override void UpdatePosition() { switch (position) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs index ae94848c81..e2084bbb7c 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs @@ -52,13 +52,15 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components private void load(OsuColour colours) { Colour = colours.Yellow; - - PositionBindable.BindValueChanged(_ => updatePosition(), true); - StackHeightBindable.BindValueChanged(_ => updatePosition()); - ScaleBindable.BindValueChanged(scale => ring.Scale = new Vector2(scale.NewValue), true); } - private void updatePosition() => Position = spinner.Position; + protected override void Update() + { + base.Update(); + + Position = spinner.Position; + ring.Scale = new Vector2(spinner.Scale); + } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => circle.ReceivePositionalInputAt(screenSpacePos); } From 4fc37d11376980b2fc34c616b247e8fbaca8b640 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 27 Sep 2019 18:01:55 +0900 Subject: [PATCH 3201/5608] Remove SliderPiece + HitObjectPiece --- .../HitCircles/Components/HitCirclePiece.cs | 4 ++-- .../Edit/Blueprints/HitObjectPiece.cs | 21 ------------------- .../Edit/Blueprints/SliderPiece.cs | 21 ------------------- .../Components/PathControlPointVisualiser.cs | 3 +-- .../Sliders/Components/SliderBodyPiece.cs | 6 +++--- .../Spinners/Components/SpinnerPiece.cs | 3 +-- 6 files changed, 7 insertions(+), 51 deletions(-) delete mode 100644 osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs delete mode 100644 osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs index 99928cdad9..5e46b3ace4 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; @@ -10,12 +11,11 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components { - public class HitCirclePiece : HitObjectPiece + public class HitCirclePiece : CompositeDrawable { private readonly HitCircle hitCircle; public HitCirclePiece(HitCircle hitCircle) - : base(hitCircle) { this.hitCircle = hitCircle; Origin = Anchor.Centre; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs deleted file mode 100644 index 3d7d609c6b..0000000000 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Osu.Objects; - -namespace osu.Game.Rulesets.Osu.Edit.Blueprints -{ - /// - /// A piece of a blueprint which responds to changes in the state of a . - /// - public abstract class HitObjectPiece : CompositeDrawable - { - protected readonly OsuHitObject HitObject; - - protected HitObjectPiece(OsuHitObject hitObject) - { - HitObject = hitObject; - } - } -} diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs deleted file mode 100644 index e0fcf8a000..0000000000 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Rulesets.Osu.Objects; - -namespace osu.Game.Rulesets.Osu.Edit.Blueprints -{ - /// - /// A piece of a blueprint which responds to changes in the state of a . - /// - public abstract class SliderPiece : HitObjectPiece - { - protected readonly Slider Slider; - - protected SliderPiece(Slider slider) - : base(slider) - { - Slider = slider; - } - } -} diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 3d8e014551..24fcc460d1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -7,14 +7,13 @@ using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { - public class PathControlPointVisualiser : SliderPiece + public class PathControlPointVisualiser : CompositeDrawable { private readonly Slider slider; private readonly Container pieces; public PathControlPointVisualiser(Slider slider) - : base(slider) { this.slider = slider; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index aea17a4b8f..239feee431 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; @@ -11,13 +12,12 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { - public class SliderBodyPiece : SliderPiece + public class SliderBodyPiece : CompositeDrawable { private readonly Slider slider; private readonly ManualSliderBody body; public SliderBodyPiece(Slider slider) - : base(slider) { this.slider = slider; @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components base.Update(); Position = slider.StackedPosition; - body.PathRadius = HitObject.Scale * OsuHitObject.OBJECT_RADIUS; + body.PathRadius = slider.Scale * OsuHitObject.OBJECT_RADIUS; var vertices = new List(); slider.Path.GetPathToProgress(vertices, 0, 1); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs index e2084bbb7c..5dab501a24 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs @@ -12,14 +12,13 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components { - public class SpinnerPiece : HitObjectPiece + public class SpinnerPiece : CompositeDrawable { private readonly Spinner spinner; private readonly CircularContainer circle; private readonly RingPiece ring; public SpinnerPiece(Spinner spinner) - : base(spinner) { this.spinner = spinner; From bddaead72e5b650b4e2e0205572b3ac232c865bf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 27 Sep 2019 18:45:22 +0900 Subject: [PATCH 3202/5608] Make hitobject pieces able to update dynamically --- .../Edit/Blueprints/BlueprintPiece.cs | 25 +++++++++++++ .../HitCircles/Components/HitCirclePiece.cs | 18 +++------- .../HitCircles/HitCirclePlacementBlueprint.cs | 11 +++++- .../HitCircles/HitCircleSelectionBlueprint.cs | 13 +++++-- .../Edit/Blueprints/OsuSelectionBlueprint.cs | 7 ++-- .../Components/PathControlPointPiece.cs | 2 +- .../Sliders/Components/SliderBodyPiece.cs | 21 ++++------- .../Sliders/Components/SliderCirclePiece.cs | 35 ------------------- .../Sliders/SliderCircleSelectionBlueprint.cs | 21 ++++++++--- .../Sliders/SliderPlacementBlueprint.cs | 15 ++++++-- .../Sliders/SliderSelectionBlueprint.cs | 16 ++++++--- .../Spinners/Components/SpinnerPiece.cs | 16 +++------ .../Spinners/SpinnerPlacementBlueprint.cs | 9 ++++- .../Spinners/SpinnerSelectionBlueprint.cs | 11 ++++-- 14 files changed, 125 insertions(+), 95 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs delete mode 100644 osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs new file mode 100644 index 0000000000..95e926fdfa --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.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 osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Osu.Objects; + +namespace osu.Game.Rulesets.Osu.Edit.Blueprints +{ + /// + /// A piece of a selection or placement blueprint which visualises an . + /// + /// The type of which this visualises. + public abstract class BlueprintPiece : CompositeDrawable + where T : OsuHitObject + { + /// + /// Updates this using the properties of a . + /// + /// The to reference properties from. + public virtual void UpdateFrom(T hitObject) + { + Position = hitObject.Position; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs index 5e46b3ace4..2b6b93a590 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs @@ -3,7 +3,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; @@ -11,17 +10,13 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components { - public class HitCirclePiece : CompositeDrawable + public class HitCirclePiece : BlueprintPiece { - private readonly HitCircle hitCircle; - - public HitCirclePiece(HitCircle hitCircle) + public HitCirclePiece() { - this.hitCircle = hitCircle; Origin = Anchor.Centre; Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); - Scale = new Vector2(hitCircle.Scale); CornerRadius = Size.X / 2; InternalChild = new RingPiece(); @@ -33,14 +28,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components Colour = colours.Yellow; } - protected override void Update() + public override void UpdateFrom(HitCircle hitObject) { - base.Update(); + base.UpdateFrom(hitObject); - UpdatePosition(); - Scale = new Vector2(hitCircle.Scale); + Scale = new Vector2(hitObject.Scale); } - - protected virtual void UpdatePosition() => Position = hitCircle.StackedPosition; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs index a4050f0c31..cccef52737 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs @@ -13,10 +13,12 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles { public new HitCircle HitObject => (HitCircle)base.HitObject; + private readonly HitCirclePiece circlePiece; + public HitCirclePlacementBlueprint() : base(new HitCircle()) { - InternalChild = new HitCirclePiece(HitObject); + InternalChild = circlePiece = new HitCirclePiece(); } protected override void LoadComplete() @@ -27,6 +29,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles HitObject.Position = Parent?.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position) ?? Vector2.Zero; } + protected override void Update() + { + base.Update(); + + circlePiece.UpdateFrom(HitObject); + } + protected override bool OnClick(ClickEvent e) { HitObject.StartTime = EditorClock.CurrentTime; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs index 83787e2219..430d4a0222 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs @@ -7,12 +7,21 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles { - public class HitCircleSelectionBlueprint : OsuSelectionBlueprint + public class HitCircleSelectionBlueprint : OsuSelectionBlueprint { + private readonly HitCirclePiece circlePiece; + public HitCircleSelectionBlueprint(DrawableHitCircle hitCircle) : base(hitCircle) { - InternalChild = new HitCirclePiece((HitCircle)hitCircle.HitObject); + InternalChild = circlePiece = new HitCirclePiece(); + } + + protected override void Update() + { + base.Update(); + + circlePiece.UpdateFrom(HitObject); } } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs index dd524252f3..2e4b990db8 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs @@ -7,11 +7,12 @@ using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Edit.Blueprints { - public class OsuSelectionBlueprint : SelectionBlueprint + public abstract class OsuSelectionBlueprint : SelectionBlueprint + where T : OsuHitObject { - protected OsuHitObject OsuObject => (OsuHitObject)HitObject.HitObject; + protected new T HitObject => (T)base.HitObject.HitObject; - public OsuSelectionBlueprint(DrawableHitObject hitObject) + protected OsuSelectionBlueprint(DrawableHitObject hitObject) : base(hitObject) { } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index e257369ad9..3aec7c2872 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { - public class PathControlPointPiece : CompositeDrawable + public class PathControlPointPiece : BlueprintPiece { private readonly Slider slider; private readonly int index; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index 239feee431..d28cf7b492 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; @@ -12,18 +11,15 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { - public class SliderBodyPiece : CompositeDrawable + public class SliderBodyPiece : BlueprintPiece { - private readonly Slider slider; private readonly ManualSliderBody body; - public SliderBodyPiece(Slider slider) + public SliderBodyPiece() { - this.slider = slider; - InternalChild = body = new ManualSliderBody { - AccentColour = Color4.Transparent, + AccentColour = Color4.Transparent }; } @@ -33,17 +29,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components body.BorderColour = colours.Yellow; } - private void updatePosition() => Position = slider.StackedPosition; - - protected override void Update() + public override void UpdateFrom(Slider hitObject) { - base.Update(); + base.UpdateFrom(hitObject); - Position = slider.StackedPosition; - body.PathRadius = slider.Scale * OsuHitObject.OBJECT_RADIUS; + body.PathRadius = hitObject.Scale * OsuHitObject.OBJECT_RADIUS; var vertices = new List(); - slider.Path.GetPathToProgress(vertices, 0, 1); + hitObject.Path.GetPathToProgress(vertices, 0, 1); body.SetVertices(vertices); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs deleted file mode 100644 index ec3a1d0034..0000000000 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; -using osu.Game.Rulesets.Osu.Objects; - -namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components -{ - public class SliderCirclePiece : HitCirclePiece - { - private readonly Slider slider; - private readonly SliderPosition position; - - public SliderCirclePiece(Slider slider, SliderPosition position) - : base(slider.HeadCircle) - { - this.slider = slider; - this.position = position; - } - - protected override void UpdatePosition() - { - switch (position) - { - case SliderPosition.Start: - Position = slider.StackedPosition + slider.Path.PositionAt(0); - break; - - case SliderPosition.End: - Position = slider.StackedPosition + slider.Path.PositionAt(1); - break; - } - } - } -} diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs index c9f005495c..8f9a9c3a64 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs @@ -1,22 +1,33 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; +using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { - public class SliderCircleSelectionBlueprint : OsuSelectionBlueprint + public class SliderCircleSelectionBlueprint : OsuSelectionBlueprint { - public SliderCircleSelectionBlueprint(DrawableOsuHitObject hitObject, Slider slider, SliderPosition position) - : base(hitObject) + private readonly SliderPosition position; + private readonly HitCirclePiece circlePiece; + + public SliderCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position) + : base(slider) { - InternalChild = new SliderCirclePiece(slider, position); + this.position = position; + InternalChild = circlePiece = new HitCirclePiece(); Select(); } + protected override void Update() + { + base.Update(); + + circlePiece.UpdateFrom(position == SliderPosition.Start ? HitObject.HeadCircle : HitObject.TailCircle); + } + // Todo: This is temporary, since the slider circle masks don't do anything special yet. In the future they will handle input. public override bool HandlePositionalInput => false; } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 55de626d7d..4c281a0e7d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -11,6 +11,7 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osuTK; using osuTK.Input; @@ -21,6 +22,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { public new Objects.Slider HitObject => (Objects.Slider)base.HitObject; + private SliderBodyPiece bodyPiece; + private HitCirclePiece headCirclePiece; + private HitCirclePiece tailCirclePiece; + private readonly List segments = new List(); private Vector2 cursor; @@ -38,9 +43,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { InternalChildren = new Drawable[] { - new SliderBodyPiece(HitObject), - new SliderCirclePiece(HitObject, SliderPosition.Start), - new SliderCirclePiece(HitObject, SliderPosition.End), + bodyPiece = new SliderBodyPiece(), + headCirclePiece = new HitCirclePiece(), + tailCirclePiece = new HitCirclePiece(), new PathControlPointVisualiser(HitObject), }; @@ -130,6 +135,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { var newControlPoints = segments.SelectMany(s => s.ControlPoints).Concat(cursor.Yield()).ToArray(); HitObject.Path = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints); + + bodyPiece.UpdateFrom(HitObject); + headCirclePiece.UpdateFrom(HitObject.HeadCircle); + tailCirclePiece.UpdateFrom(HitObject.TailCircle); } private void setState(PlacementState newState) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index fb8c081ff7..bc760c9456 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -9,8 +9,9 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { - public class SliderSelectionBlueprint : OsuSelectionBlueprint + public class SliderSelectionBlueprint : OsuSelectionBlueprint { + private readonly SliderBodyPiece bodyPiece; private readonly SliderCircleSelectionBlueprint headBlueprint; public SliderSelectionBlueprint(DrawableSlider slider) @@ -20,13 +21,20 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders InternalChildren = new Drawable[] { - new SliderBodyPiece(sliderObject), - headBlueprint = new SliderCircleSelectionBlueprint(slider.HeadCircle, sliderObject, SliderPosition.Start), - new SliderCircleSelectionBlueprint(slider.TailCircle, sliderObject, SliderPosition.End), + bodyPiece = new SliderBodyPiece(), + headBlueprint = new SliderCircleSelectionBlueprint(slider, SliderPosition.Start), + new SliderCircleSelectionBlueprint(slider, SliderPosition.End), new PathControlPointVisualiser(sliderObject), }; } + protected override void Update() + { + base.Update(); + + bodyPiece.UpdateFrom(HitObject); + } + public override Vector2 SelectionPoint => headBlueprint.SelectionPoint; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs index 5dab501a24..65c8720031 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs @@ -12,16 +12,13 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components { - public class SpinnerPiece : CompositeDrawable + public class SpinnerPiece : BlueprintPiece { - private readonly Spinner spinner; private readonly CircularContainer circle; private readonly RingPiece ring; - public SpinnerPiece(Spinner spinner) + public SpinnerPiece() { - this.spinner = spinner; - Origin = Anchor.Centre; RelativeSizeAxes = Axes.Both; @@ -43,8 +40,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components Origin = Anchor.Centre } }; - - ring.Scale = new Vector2(spinner.Scale); } [BackgroundDependencyLoader] @@ -53,12 +48,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components Colour = colours.Yellow; } - protected override void Update() + public override void UpdateFrom(Spinner hitObject) { - base.Update(); + base.UpdateFrom(hitObject); - Position = spinner.Position; - ring.Scale = new Vector2(spinner.Scale); + ring.Scale = new Vector2(hitObject.Scale); } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => circle.ReceivePositionalInputAt(screenSpacePos); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs index 03d761c67f..8d9dea736b 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs @@ -21,7 +21,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners public SpinnerPlacementBlueprint() : base(new Spinner { Position = OsuPlayfield.BASE_SIZE / 2 }) { - InternalChild = piece = new SpinnerPiece(HitObject) { Alpha = 0.5f }; + InternalChild = piece = new SpinnerPiece { Alpha = 0.5f }; + } + + protected override void Update() + { + base.Update(); + + piece.UpdateFrom(HitObject); } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs index 25cef3b251..f05d4f8435 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs @@ -8,14 +8,21 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners { - public class SpinnerSelectionBlueprint : OsuSelectionBlueprint + public class SpinnerSelectionBlueprint : OsuSelectionBlueprint { private readonly SpinnerPiece piece; public SpinnerSelectionBlueprint(DrawableSpinner spinner) : base(spinner) { - InternalChild = piece = new SpinnerPiece((Spinner)spinner.HitObject); + InternalChild = piece = new SpinnerPiece(); + } + + protected override void Update() + { + base.Update(); + + piece.UpdateFrom(HitObject); } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => piece.ReceivePositionalInputAt(screenSpacePos); From 2a395956aa4278f7eca532049c88947599f8171e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 27 Sep 2019 19:00:17 +0300 Subject: [PATCH 3203/5608] 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 3204/5608] 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 3af7c910fb311ac4319e9b2eb218926e6b52c04a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 27 Sep 2019 19:09:07 +0000 Subject: [PATCH 3205/5608] Bump Humanizer from 2.7.2 to 2.7.9 Bumps [Humanizer](https://github.com/Humanizr/Humanizer) from 2.7.2 to 2.7.9. - [Release notes](https://github.com/Humanizr/Humanizer/releases) - [Changelog](https://github.com/Humanizr/Humanizer/blob/master/release_notes.md) - [Commits](https://github.com/Humanizr/Humanizer/compare/v2.7.2...v2.7.9) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 83632f3d41..8fd5f1c3cd 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 30f1da362d..521552bd4b 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -113,7 +113,7 @@ - + From fb9f21237ebb66b2e0631975d12d65b4f877c8e7 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 28 Sep 2019 04:18:16 +0300 Subject: [PATCH 3206/5608] Reset track adjustments on resuming from another screen --- osu.Game/Overlays/MusicController.cs | 6 +++--- osu.Game/Screens/Select/SongSelect.cs | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index db94b0278f..172ae4e5cb 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -57,7 +57,7 @@ namespace osu.Game.Overlays protected override void LoadComplete() { beatmap.BindValueChanged(beatmapChanged, true); - mods.BindValueChanged(_ => updateAudioAdjustments(), true); + mods.BindValueChanged(_ => ResetTrackAdjustments(), true); base.LoadComplete(); } @@ -213,12 +213,12 @@ namespace osu.Game.Overlays current = beatmap.NewValue; TrackChanged?.Invoke(current, direction); - updateAudioAdjustments(); + ResetTrackAdjustments(); queuedDirection = null; } - private void updateAudioAdjustments() + public void ResetTrackAdjustments() { var track = current?.Track; if (track == null) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index fca801ce78..d40dd9414a 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -490,6 +490,7 @@ namespace osu.Game.Screens.Select BeatmapDetails.Leaderboard.RefreshScores(); Beatmap.Value.Track.Looping = true; + music?.ResetTrackAdjustments(); if (Beatmap != null && !Beatmap.Value.BeatmapSetInfo.DeletePending) { From 2487d4f0f208524b433dff5dd6395b61268498a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 28 Sep 2019 11:58:27 +0200 Subject: [PATCH 3207/5608] Migrate beatmap carousel test to AddUntilStep Due to non-deterministic test failures in TestSceneBeatmapCarousel, migrate the checkSelected helper step from AddAssert to AddUntilStep. This adds more leniency for performance-related issues while still checking the desired behaviour. --- osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index f12a613bf1..51dc11ebf8 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -83,7 +83,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("ensure prev random fetch worked", () => selectedSets.Peek() == carousel.SelectedBeatmapSet); private void checkSelected(int set, int? diff = null) => - AddAssert($"selected is set{set}{(diff.HasValue ? $" diff{diff.Value}" : "")}", () => + AddUntilStep($"selected is set{set}{(diff.HasValue ? $" diff{diff.Value}" : "")}", () => { if (diff != null) return carousel.SelectedBeatmap == carousel.BeatmapSets.Skip(set - 1).First().Beatmaps.Skip(diff.Value - 1).First(); From a45f8c968b4669ca345089670455ce740afeb7a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 28 Sep 2019 20:21:51 +0800 Subject: [PATCH 3208/5608] Rename and add simple xmldoc --- osu.Game/Configuration/SessionStatics.cs | 9 ++++++--- osu.Game/Screens/Menu/MainMenu.cs | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Configuration/SessionStatics.cs b/osu.Game/Configuration/SessionStatics.cs index b4b5e914bb..818a95c0be 100644 --- a/osu.Game/Configuration/SessionStatics.cs +++ b/osu.Game/Configuration/SessionStatics.cs @@ -3,15 +3,18 @@ namespace osu.Game.Configuration { - public class SessionStatics : InMemoryConfigManager + /// + /// Stores global per-session statics. These will not be stored after exiting the game. + /// + public class SessionStatics : InMemoryConfigManager { protected override void InitialiseDefaults() { - Set(Statics.LoginOverlayDisplayed, false); + Set(Static.LoginOverlayDisplayed, false); } } - public enum Statics + public enum Static { LoginOverlayDisplayed, } diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 004bba20d4..16e9d67cc3 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -71,7 +71,7 @@ namespace osu.Game.Screens.Menu private void load(DirectOverlay direct, SettingsOverlay settings, OsuConfigManager config, SessionStatics statics) { holdDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); - loginDisplayed = statics.GetBindable(Statics.LoginOverlayDisplayed); + loginDisplayed = statics.GetBindable(Static.LoginOverlayDisplayed); if (host.CanExit) { From 52b044b7f60b055df4baccedbc902eb7142788eb Mon Sep 17 00:00:00 2001 From: V1ntagezTV Date: Sun, 29 Sep 2019 00:10:17 +0500 Subject: [PATCH 3209/5608] Add random intro! --- osu.Game/Configuration/IntroSequence.cs | 3 ++- osu.Game/Screens/Loader.cs | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game/Configuration/IntroSequence.cs b/osu.Game/Configuration/IntroSequence.cs index 1eb953be36..1ee7da8bac 100644 --- a/osu.Game/Configuration/IntroSequence.cs +++ b/osu.Game/Configuration/IntroSequence.cs @@ -6,6 +6,7 @@ namespace osu.Game.Configuration public enum IntroSequence { Circles, - Triangles + Triangles, + Random } } diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index 850349272e..7d2ad0e0ad 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -12,6 +13,7 @@ using osu.Framework.Screens; using osu.Game.Configuration; using IntroSequence = osu.Game.Configuration.IntroSequence; + namespace osu.Game.Screens { public class Loader : StartupScreen @@ -58,9 +60,16 @@ namespace osu.Game.Screens } private IntroScreen getIntroSequence() - { + {//вот именно что не показывает ни всплывающих подсказок нихера + Random random = new Random(); switch (introSequence) { + case IntroSequence.Random: + if (random.Next(2) == 0) + return new IntroCircles(); + else + return new IntroTriangles(); + case IntroSequence.Circles: return new IntroCircles(); From 1babd139bc066c1d49e48fa4cf3575784d010eaf Mon Sep 17 00:00:00 2001 From: V1ntagezTV Date: Sun, 29 Sep 2019 00:22:23 +0500 Subject: [PATCH 3210/5608] remove needless blank --- osu.Game/Screens/Loader.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index 7d2ad0e0ad..c17463388a 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -13,7 +13,6 @@ using osu.Framework.Screens; using osu.Game.Configuration; using IntroSequence = osu.Game.Configuration.IntroSequence; - namespace osu.Game.Screens { public class Loader : StartupScreen From 2681e2064ae40da81da7ac1b2962481556025d10 Mon Sep 17 00:00:00 2001 From: V1ntagezTV Date: Sun, 29 Sep 2019 00:34:09 +0500 Subject: [PATCH 3211/5608] remove comment --- osu.Game/Screens/Loader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index c17463388a..75ed74978f 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens } private IntroScreen getIntroSequence() - {//вот именно что не показывает ни всплывающих подсказок нихера + { Random random = new Random(); switch (introSequence) { From 9f1c3787333dbaa7957992e0248e317f46c2797c Mon Sep 17 00:00:00 2001 From: V1ntagezTV Date: Sun, 29 Sep 2019 00:35:47 +0500 Subject: [PATCH 3212/5608] moved into the switch case --- osu.Game/Screens/Loader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index 75ed74978f..fb49c8a574 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -60,10 +60,10 @@ namespace osu.Game.Screens private IntroScreen getIntroSequence() { - Random random = new Random(); switch (introSequence) { case IntroSequence.Random: + var random = new Random(); if (random.Next(2) == 0) return new IntroCircles(); else From 740efa57477f75da8078fb0d86e73bc603e7bb64 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 29 Sep 2019 12:13:41 +0800 Subject: [PATCH 3213/5608] Handle potential null case --- osu.Game/Overlays/MusicController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 172ae4e5cb..49d16a4f3e 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays /// /// Returns whether the current beatmap track is playing. /// - public bool IsPlaying => beatmap.Value.Track.IsRunning; + public bool IsPlaying => beatmap.Value?.Track.IsRunning ?? false; private void handleBeatmapAdded(BeatmapSetInfo set) => Schedule(() => beatmapSets.Add(set)); From 539f3329cef87bf1024b569a6ae77e033316e15e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 29 Sep 2019 12:23:18 +0800 Subject: [PATCH 3214/5608] Rename method to match new behaviour --- .../SongSelect/TestSceneBeatmapCarousel.cs | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 51dc11ebf8..90c6c9065c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -82,7 +82,7 @@ namespace osu.Game.Tests.Visual.SongSelect private void ensureRandomFetchSuccess() => AddAssert("ensure prev random fetch worked", () => selectedSets.Peek() == carousel.SelectedBeatmapSet); - private void checkSelected(int set, int? diff = null) => + private void waitForSelection(int set, int? diff = null) => AddUntilStep($"selected is set{set}{(diff.HasValue ? $" diff{diff.Value}" : "")}", () => { if (diff != null) @@ -168,24 +168,24 @@ namespace osu.Game.Tests.Visual.SongSelect loadBeatmaps(); advanceSelection(direction: 1, diff: false); - checkSelected(1, 1); + waitForSelection(1, 1); advanceSelection(direction: 1, diff: true); - checkSelected(1, 2); + waitForSelection(1, 2); advanceSelection(direction: -1, diff: false); - checkSelected(set_count, 1); + waitForSelection(set_count, 1); advanceSelection(direction: -1, diff: true); - checkSelected(set_count - 1, 3); + waitForSelection(set_count - 1, 3); advanceSelection(diff: false); advanceSelection(diff: false); - checkSelected(1, 2); + waitForSelection(1, 2); advanceSelection(direction: -1, diff: true); advanceSelection(direction: -1, diff: true); - checkSelected(set_count, 3); + waitForSelection(set_count, 3); } /// @@ -203,10 +203,10 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("Filter", () => carousel.Filter(new FilterCriteria { SearchText = "set #3!" }, false)); checkVisibleItemCount(diff: false, count: 1); checkVisibleItemCount(diff: true, count: 3); - checkSelected(3, 1); + waitForSelection(3, 1); advanceSelection(diff: true, count: 4); - checkSelected(3, 2); + waitForSelection(3, 2); AddStep("Un-filter (debounce)", () => carousel.Filter(new FilterCriteria())); AddUntilStep("Wait for debounce", () => !carousel.PendingFilterTask); @@ -217,10 +217,10 @@ namespace osu.Game.Tests.Visual.SongSelect setSelected(1, 2); AddStep("Filter some difficulties", () => carousel.Filter(new FilterCriteria { SearchText = "Normal" }, false)); - checkSelected(1, 1); + waitForSelection(1, 1); AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); - checkSelected(1, 1); + waitForSelection(1, 1); AddStep("Filter all", () => carousel.Filter(new FilterCriteria { SearchText = "Dingo" }, false)); @@ -249,7 +249,7 @@ namespace osu.Game.Tests.Visual.SongSelect IsLowerInclusive = true } }, false)); - checkSelected(3, 2); + waitForSelection(3, 2); AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); } @@ -317,7 +317,7 @@ namespace osu.Game.Tests.Visual.SongSelect checkVisibleItemCount(false, set_count); - checkSelected(set_count); + waitForSelection(set_count); } /// @@ -343,11 +343,11 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("Selection is non-null", () => currentSelection != null); AddStep("Remove selected", () => carousel.RemoveBeatmapSet(carousel.SelectedBeatmapSet)); - checkSelected(2); + waitForSelection(2); AddStep("Remove first", () => carousel.RemoveBeatmapSet(carousel.BeatmapSets.First())); AddStep("Remove first", () => carousel.RemoveBeatmapSet(carousel.BeatmapSets.First())); - checkSelected(1); + waitForSelection(1); AddUntilStep("Remove all", () => { @@ -390,17 +390,17 @@ namespace osu.Game.Tests.Visual.SongSelect checkVisibleItemCount(true, 2); advanceSelection(true); - checkSelected(1, 3); + waitForSelection(1, 3); setHidden(3); - checkSelected(1, 1); + waitForSelection(1, 1); setHidden(2, false); advanceSelection(true); - checkSelected(1, 2); + waitForSelection(1, 2); setHidden(1); - checkSelected(1, 2); + waitForSelection(1, 2); setHidden(2); checkNoSelection(); From ce62f3c75b8e2e896053bbf61291bb31404c2775 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 29 Sep 2019 14:35:35 +0800 Subject: [PATCH 3215/5608] Simplify and future-proof random retrieval method Will support future added intros without further code changes. Also uses RNG instead of `new Random`. --- osu.Game/Screens/Loader.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index fb49c8a574..41ee01be20 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shaders; +using osu.Framework.MathUtils; using osu.Game.Screens.Menu; using osuTK; using osu.Framework.Screens; @@ -60,15 +60,11 @@ namespace osu.Game.Screens private IntroScreen getIntroSequence() { + if (introSequence == IntroSequence.Random) + introSequence = (IntroSequence)RNG.Next(0, (int)IntroSequence.Random); + switch (introSequence) { - case IntroSequence.Random: - var random = new Random(); - if (random.Next(2) == 0) - return new IntroCircles(); - else - return new IntroTriangles(); - case IntroSequence.Circles: return new IntroCircles(); From 97a0e0097f6e5f4fe7de2b5d4000e5c48df9cd5a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 29 Sep 2019 14:56:33 +0300 Subject: [PATCH 3216/5608] Add testing --- .../Visual/Online/TestSceneUserProfileOverlay.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index 93e6607ac5..c0457ba0ff 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -106,6 +106,14 @@ namespace osu.Game.Tests.Visual.Online Country = new Country { FullName = @"Japan", FlagName = @"JP" }, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg" }, api.IsLoggedIn)); + AddStep("Show bancho", () => profile.ShowUser(new User + { + Username = @"BanchoBot", + Id = 3, + IsBot = true, + Country = new Country { FullName = @"Saint Helena", FlagName = @"SH" }, + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c4.jpg" + }, api.IsLoggedIn)); AddStep("Hide", profile.Hide); AddStep("Show without reload", profile.Show); From 883ee9851af74ae0695e9731df269685f9a7ad70 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 29 Sep 2019 15:02:33 +0300 Subject: [PATCH 3217/5608] 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 3218/5608] 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 f24ac04bebbcbbc0ca5d0679172d3fbe6efd6854 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 29 Sep 2019 15:18:29 +0300 Subject: [PATCH 3219/5608] Add suggested blank line for consistency --- osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index c0457ba0ff..98da63508b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -106,6 +106,7 @@ namespace osu.Game.Tests.Visual.Online Country = new Country { FullName = @"Japan", FlagName = @"JP" }, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg" }, api.IsLoggedIn)); + AddStep("Show bancho", () => profile.ShowUser(new User { Username = @"BanchoBot", From febe0175cd6f6c3b594e2cf2b8dd2e1b1c59f0e0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 29 Sep 2019 15:27:29 +0300 Subject: [PATCH 3220/5608] 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 9f498d29908a94f2a70a7e3d390a4202d9a5bdec Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 29 Sep 2019 19:25:44 +0200 Subject: [PATCH 3221/5608] Log the exception that caused to loading of rulesets to fail. --- osu.Game/Rulesets/RulesetStore.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 2d8c9f5b49..a94b0e0c06 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -135,9 +135,9 @@ namespace osu.Game.Rulesets foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) loadRulesetFromFile(file); } - catch + catch(Exception e) { - Logger.Log($"Could not load rulesets from directory {Environment.CurrentDirectory}"); + Logger.Error(e, $"Could not load rulesets from directory {Environment.CurrentDirectory}"); } } From 42d1379848fa03611cda80eb2336838ddf3165d3 Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 29 Sep 2019 20:40:10 +0200 Subject: [PATCH 3222/5608] Load the rulesets lasily --- osu.Game/Rulesets/RulesetStore.cs | 95 ++++++++++++++++--------------- 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 2d8c9f5b49..6392f982fb 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -16,17 +16,11 @@ namespace osu.Game.Rulesets /// public class RulesetStore : DatabaseBackedStore { - private static readonly Dictionary loaded_assemblies = new Dictionary(); + private static readonly Lazy> loaded_assemblies = new Lazy>(() => loadRulesets()); static RulesetStore() { AppDomain.CurrentDomain.AssemblyResolve += currentDomain_AssemblyResolve; - - // On android in release configuration assemblies are loaded from the apk directly into memory. - // We cannot read assemblies from cwd, so should check loaded assemblies instead. - loadFromAppDomain(); - - loadFromDisk(); } public RulesetStore(IDatabaseContextFactory factory) @@ -54,7 +48,7 @@ namespace osu.Game.Rulesets /// public IEnumerable AvailableRulesets { get; private set; } - private static Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args) => loaded_assemblies.Keys.FirstOrDefault(a => a.FullName == args.Name); + private static Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args) => loaded_assemblies.Value.Keys.FirstOrDefault(a => a.FullName == args.Name); private const string ruleset_library_prefix = "osu.Game.Rulesets"; @@ -64,7 +58,7 @@ namespace osu.Game.Rulesets { var context = usage.Context; - var instances = loaded_assemblies.Values.Select(r => (Ruleset)Activator.CreateInstance(r, (RulesetInfo)null)).ToList(); + var instances = loaded_assemblies.Value.Values.Select(r => (Ruleset)Activator.CreateInstance(r, (RulesetInfo)null)).ToList(); //add all legacy modes in correct order foreach (var r in instances.Where(r => r.LegacyID != null).OrderBy(r => r.LegacyID)) @@ -113,8 +107,39 @@ namespace osu.Game.Rulesets } } - private static void loadFromAppDomain() + /// + /// Loads the rulesets that are in the current appdomain an in the current directory. + /// + /// The rulesets that were loaded. + private static Dictionary loadRulesets() { + var rulesets = new Dictionary(); + + foreach (var rulesetAssembly in getRulesetAssemblies()) + { + try + { + rulesets[rulesetAssembly] = rulesetAssembly.GetTypes().First(t => t.IsPublic && t.IsSubclassOf(typeof(Ruleset))); + } + catch (Exception e) + { + Logger.Error(e, $"Failed to add ruleset {rulesetAssembly}"); + } + } + + return rulesets; + } + + /// + /// Scans the current appdomain and current directory for ruleset assemblies. + /// Rulesets that were found in the current directory are automaticly loaded. + /// + /// The ruleset assemblies that were found in the current appdomain or in the current directory. + private static IEnumerable getRulesetAssemblies() + { + var rulesetAssemblies = new HashSet(); + + // load from appdomain foreach (var ruleset in AppDomain.CurrentDomain.GetAssemblies()) { string rulesetName = ruleset.GetName().Name; @@ -122,55 +147,33 @@ namespace osu.Game.Rulesets if (!rulesetName.StartsWith(ruleset_library_prefix, StringComparison.InvariantCultureIgnoreCase) || ruleset.GetName().Name.Contains("Tests")) continue; - addRuleset(ruleset); + rulesetAssemblies.Add(ruleset); } - } - private static void loadFromDisk() - { + // load from current directory try { string[] files = Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll"); foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) - loadRulesetFromFile(file); + { + try + { + rulesetAssemblies.Add(Assembly.LoadFrom(file)); + } + catch (Exception e) + { + Logger.Error(e, $"Failed to load ruleset assembly {Path.GetFileNameWithoutExtension(file)}"); + return null; + } + } } catch { Logger.Log($"Could not load rulesets from directory {Environment.CurrentDirectory}"); } - } - private static void loadRulesetFromFile(string file) - { - var filename = Path.GetFileNameWithoutExtension(file); - - if (loaded_assemblies.Values.Any(t => t.Namespace == filename)) - return; - - try - { - addRuleset(Assembly.LoadFrom(file)); - } - catch (Exception e) - { - Logger.Error(e, $"Failed to load ruleset {filename}"); - } - } - - private static void addRuleset(Assembly assembly) - { - if (loaded_assemblies.ContainsKey(assembly)) - return; - - try - { - loaded_assemblies[assembly] = assembly.GetTypes().First(t => t.IsPublic && t.IsSubclassOf(typeof(Ruleset))); - } - catch (Exception e) - { - Logger.Error(e, $"Failed to add ruleset {assembly}"); - } + return rulesetAssemblies; } } } From 351e89bf182faaaa342c2b0c78f63a10500af18d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 30 Sep 2019 22:03:56 +0900 Subject: [PATCH 3223/5608] 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 46fd5424df..51245351b6 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8fd5f1c3cd..8cbc8b0af3 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 521552bd4b..a15cae55c4 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From 04ac414249a30de3ea34a734a2c0e08183a27af7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Oct 2019 13:48:56 +0900 Subject: [PATCH 3224/5608] Fix memory leaks due to audio track recycle order --- osu.Game/Beatmaps/BindableBeatmap.cs | 23 ----------------------- osu.Game/OsuGameBase.cs | 6 ++++++ osu.Game/Tests/Visual/OsuTestScene.cs | 9 ++++++--- 3 files changed, 12 insertions(+), 26 deletions(-) diff --git a/osu.Game/Beatmaps/BindableBeatmap.cs b/osu.Game/Beatmaps/BindableBeatmap.cs index af627cc6a9..39c633e282 100644 --- a/osu.Game/Beatmaps/BindableBeatmap.cs +++ b/osu.Game/Beatmaps/BindableBeatmap.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.Diagnostics; using osu.Framework.Bindables; namespace osu.Game.Beatmaps @@ -12,31 +11,9 @@ namespace osu.Game.Beatmaps /// public abstract class BindableBeatmap : NonNullableBindable { - private WorkingBeatmap lastBeatmap; - protected BindableBeatmap(WorkingBeatmap defaultValue) : base(defaultValue) { - BindValueChanged(b => updateAudioTrack(b.NewValue), true); - } - - private void updateAudioTrack(WorkingBeatmap beatmap) - { - var trackLoaded = lastBeatmap?.TrackLoaded ?? false; - - // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo) - if (!trackLoaded || lastBeatmap?.Track != beatmap.Track) - { - if (trackLoaded) - { - Debug.Assert(lastBeatmap != null); - Debug.Assert(lastBeatmap.Track != null); - - lastBeatmap.RecycleTrack(); - } - } - - lastBeatmap = beatmap; } } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 59a5e38b2c..a9a9693c76 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -203,6 +203,12 @@ namespace osu.Game Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8)); beatmap = new OsuBindableBeatmap(defaultBeatmap); + beatmap.BindValueChanged(b => ScheduleAfterChildren(() => + { + // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo) + if (b.OldValue?.TrackLoaded == true && b.OldValue?.Track != b.NewValue?.Track) + b.OldValue.RecycleTrack(); + })); dependencies.CacheAs>(beatmap); dependencies.CacheAs(beatmap); diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 8e98d51962..cf128e058f 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -73,10 +73,13 @@ namespace osu.Game.Tests.Visual // This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures var working = new DummyWorkingBeatmap(parent.Get(), parent.Get()); - beatmap = new OsuTestBeatmap(working) + beatmap = new OsuTestBeatmap(working) { Default = working }; + beatmap.BindValueChanged(b => ScheduleAfterChildren(() => { - Default = working - }; + // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo) + if (b.OldValue?.TrackLoaded == true && b.OldValue?.Track != b.NewValue?.Track) + b.OldValue.RecycleTrack(); + })); Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); From ce609302edd25e0a59a36d64d81b2bfc36c2b344 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Oct 2019 15:41:01 +0900 Subject: [PATCH 3225/5608] Fix CI error --- osu.Game/Rulesets/RulesetStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index a94b0e0c06..47aad43966 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -135,7 +135,7 @@ namespace osu.Game.Rulesets foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) loadRulesetFromFile(file); } - catch(Exception e) + catch (Exception e) { Logger.Error(e, $"Could not load rulesets from directory {Environment.CurrentDirectory}"); } From cc533e8fe471c69bb0db52915a803ee1f7ad2a2f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Oct 2019 17:24:47 +0900 Subject: [PATCH 3226/5608] Remove BindableBeatmap --- osu.Game/Beatmaps/BindableBeatmap.cs | 19 ------------------- osu.Game/OsuGameBase.cs | 10 +--------- osu.Game/Tests/Visual/OsuTestScene.cs | 14 +++----------- 3 files changed, 4 insertions(+), 39 deletions(-) delete mode 100644 osu.Game/Beatmaps/BindableBeatmap.cs diff --git a/osu.Game/Beatmaps/BindableBeatmap.cs b/osu.Game/Beatmaps/BindableBeatmap.cs deleted file mode 100644 index 39c633e282..0000000000 --- a/osu.Game/Beatmaps/BindableBeatmap.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Bindables; - -namespace osu.Game.Beatmaps -{ - /// - /// A for the beatmap. - /// This should be used sparingly in-favour of . - /// - public abstract class BindableBeatmap : NonNullableBindable - { - protected BindableBeatmap(WorkingBeatmap defaultValue) - : base(defaultValue) - { - } - } -} diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index a9a9693c76..8578517a17 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -202,7 +202,7 @@ namespace osu.Game // this adds a global reduction of track volume for the time being. Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8)); - beatmap = new OsuBindableBeatmap(defaultBeatmap); + beatmap = new NonNullableBindable(defaultBeatmap); beatmap.BindValueChanged(b => ScheduleAfterChildren(() => { // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo) @@ -298,14 +298,6 @@ namespace osu.Game public string[] HandledExtensions => fileImporters.SelectMany(i => i.HandledExtensions).ToArray(); - private class OsuBindableBeatmap : BindableBeatmap - { - public OsuBindableBeatmap(WorkingBeatmap defaultValue) - : base(defaultValue) - { - } - } - private class OsuUserInputManager : UserInputManager { protected override MouseButtonEventManager CreateButtonManagerFor(MouseButton button) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index cf128e058f..96b39b303e 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -28,9 +28,9 @@ namespace osu.Game.Tests.Visual { [Cached(typeof(Bindable))] [Cached(typeof(IBindable))] - private OsuTestBeatmap beatmap; + private NonNullableBindable beatmap; - protected BindableBeatmap Beatmap => beatmap; + protected Bindable Beatmap => beatmap; [Cached] [Cached(typeof(IBindable))] @@ -73,7 +73,7 @@ namespace osu.Game.Tests.Visual // This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures var working = new DummyWorkingBeatmap(parent.Get(), parent.Get()); - beatmap = new OsuTestBeatmap(working) { Default = working }; + beatmap = new NonNullableBindable(working) { Default = working }; beatmap.BindValueChanged(b => ScheduleAfterChildren(() => { // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo) @@ -320,13 +320,5 @@ namespace osu.Game.Tests.Visual public void RunTestBlocking(TestScene test) => runner.RunTestBlocking(test); } - - private class OsuTestBeatmap : BindableBeatmap - { - public OsuTestBeatmap(WorkingBeatmap defaultValue) - : base(defaultValue) - { - } - } } } From a310c4b65f220afef633a4dc6ff9d8c58c89f0d2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Oct 2019 19:32:47 +0900 Subject: [PATCH 3227/5608] Make selection blueprints a bit more testable --- .../TestSceneHoldNoteSelectionBlueprint.cs | 4 ++- .../TestSceneNoteSelectionBlueprint.cs | 8 +++--- .../TestSceneSpinnerSelectionBlueprint.cs | 9 ++++--- .../Visual/SelectionBlueprintTestScene.cs | 26 +++++-------------- 4 files changed, 20 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs index 622d840a0c..5507ca2ba0 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs @@ -39,6 +39,8 @@ namespace osu.Game.Rulesets.Mania.Tests AccentColour = { Value = OsuColour.Gray(0.3f) } } }; + + AddBlueprint(new HoldNoteSelectionBlueprint(drawableObject)); } protected override void Update() @@ -52,6 +54,6 @@ namespace osu.Game.Rulesets.Mania.Tests } } - protected override SelectionBlueprint CreateBlueprint() => new HoldNoteSelectionBlueprint(drawableObject); + protected override SelectionBlueprint CreateBlueprint() => new HoldNoteSelectionBlueprint(null); } } diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNoteSelectionBlueprint.cs index 6bb344f977..c0482e2150 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNoteSelectionBlueprint.cs @@ -17,8 +17,6 @@ namespace osu.Game.Rulesets.Mania.Tests { public class TestSceneNoteSelectionBlueprint : ManiaSelectionBlueprintTestScene { - private readonly DrawableNote drawableObject; - protected override Container Content => content ?? base.Content; private readonly Container content; @@ -27,6 +25,8 @@ namespace osu.Game.Rulesets.Mania.Tests var note = new Note { Column = 0 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + DrawableNote drawableObject; + base.Content.Child = content = new ScrollingTestContainer(ScrollingDirection.Down) { Anchor = Anchor.Centre, @@ -34,8 +34,10 @@ namespace osu.Game.Rulesets.Mania.Tests Size = new Vector2(50, 20), Child = drawableObject = new DrawableNote(note) }; + + AddBlueprint(new NoteSelectionBlueprint(drawableObject)); } - protected override SelectionBlueprint CreateBlueprint() => new NoteSelectionBlueprint(drawableObject); + protected override SelectionBlueprint CreateBlueprint() => new NoteSelectionBlueprint(null); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerSelectionBlueprint.cs index c5cea76b14..1c195311a4 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerSelectionBlueprint.cs @@ -25,8 +25,6 @@ namespace osu.Game.Rulesets.Osu.Tests typeof(SpinnerPiece) }; - private readonly DrawableSpinner drawableSpinner; - public TestSceneSpinnerSelectionBlueprint() { var spinner = new Spinner @@ -35,16 +33,21 @@ namespace osu.Game.Rulesets.Osu.Tests StartTime = -1000, EndTime = 2000 }; + spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 }); + DrawableSpinner drawableSpinner; + Add(new Container { RelativeSizeAxes = Axes.Both, Size = new Vector2(0.5f), Child = drawableSpinner = new DrawableSpinner(spinner) }); + + AddBlueprint(new SpinnerSelectionBlueprint(drawableSpinner) { Size = new Vector2(0.5f) }); } - protected override SelectionBlueprint CreateBlueprint() => new SpinnerSelectionBlueprint(drawableSpinner) { Size = new Vector2(0.5f) }; + protected override SelectionBlueprint CreateBlueprint() => new SpinnerSelectionBlueprint(null) { Size = new Vector2(0.5f) }; } } diff --git a/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs index df3af2cc43..55dda03b16 100644 --- a/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs +++ b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs @@ -1,10 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Rulesets.Edit; @@ -12,8 +10,6 @@ namespace osu.Game.Tests.Visual { public abstract class SelectionBlueprintTestScene : OsuTestScene { - private SelectionBlueprint blueprint; - protected override Container Content => content ?? base.Content; private readonly Container content; @@ -26,23 +22,13 @@ namespace osu.Game.Tests.Visual }); } - [BackgroundDependencyLoader] - private void load() + protected void AddBlueprint(SelectionBlueprint blueprint) { - blueprint = CreateBlueprint(); - blueprint.Depth = float.MinValue; - blueprint.SelectionRequested += (_, __) => blueprint.Select(); - - Add(blueprint); - - AddStep("Select", () => blueprint.Select()); - AddStep("Deselect", () => blueprint.Deselect()); - } - - protected override bool OnClick(ClickEvent e) - { - blueprint.Deselect(); - return true; + Add(blueprint.With(d => + { + d.Depth = float.MinValue; + d.Select(); + })); } protected abstract SelectionBlueprint CreateBlueprint(); From ba5c9547e14a74af6cee3cbfd61a9066bb944734 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Oct 2019 19:33:08 +0900 Subject: [PATCH 3228/5608] Add more tests for hitcircle selection blueprint --- .../TestSceneHitCircleSelectionBlueprint.cs | 45 +++++++++++++++++-- .../HitCircles/HitCircleSelectionBlueprint.cs | 6 +-- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs index 32043bf5d7..7278d923c1 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs @@ -1,10 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; +using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Tests.Visual; @@ -14,16 +16,53 @@ namespace osu.Game.Rulesets.Osu.Tests { public class TestSceneHitCircleSelectionBlueprint : SelectionBlueprintTestScene { - private readonly DrawableHitCircle drawableObject; + private HitCircle hitCircle; + private DrawableHitCircle drawableObject; + private TestBlueprint blueprint; - public TestSceneHitCircleSelectionBlueprint() + [SetUp] + public void Setup() => Schedule(() => { - var hitCircle = new HitCircle { Position = new Vector2(256, 192) }; + Clear(); + + hitCircle = new HitCircle { Position = new Vector2(256, 192) }; hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 }); Add(drawableObject = new DrawableHitCircle(hitCircle)); + AddBlueprint(blueprint = new TestBlueprint(drawableObject)); + }); + + [Test] + public void TestInitialState() + { + AddAssert("blueprint positioned over hitobject", () => blueprint.CirclePiece.Position == hitCircle.Position); + } + + [Test] + public void TestMoveHitObject() + { + AddStep("move hitobject", () => hitCircle.Position = new Vector2(300, 225)); + AddAssert("blueprint positioned over hitobject", () => blueprint.CirclePiece.Position == hitCircle.Position); + } + + [Test] + public void TestMoveAfterApplyingDefaults() + { + AddStep("apply defaults", () => hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 })); + AddStep("move hitobject", () => hitCircle.Position = new Vector2(300, 225)); + AddAssert("blueprint positioned over hitobject", () => blueprint.CirclePiece.Position == hitCircle.Position); } protected override SelectionBlueprint CreateBlueprint() => new HitCircleSelectionBlueprint(drawableObject); + + private class TestBlueprint : HitCircleSelectionBlueprint + { + public new HitCirclePiece CirclePiece => base.CirclePiece; + + public TestBlueprint(DrawableHitCircle hitCircle) + : base(hitCircle) + { + } + } } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs index 430d4a0222..a191dba8ff 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs @@ -9,19 +9,19 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles { public class HitCircleSelectionBlueprint : OsuSelectionBlueprint { - private readonly HitCirclePiece circlePiece; + protected readonly HitCirclePiece CirclePiece; public HitCircleSelectionBlueprint(DrawableHitCircle hitCircle) : base(hitCircle) { - InternalChild = circlePiece = new HitCirclePiece(); + InternalChild = CirclePiece = new HitCirclePiece(); } protected override void Update() { base.Update(); - circlePiece.UpdateFrom(HitObject); + CirclePiece.UpdateFrom(HitObject); } } } From 90ad1c5166fdc4dd116ff89554a585c28853774b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Oct 2019 19:33:24 +0900 Subject: [PATCH 3229/5608] Add more tests for slider selection blueprint --- .../TestSceneSliderSelectionBlueprint.cs | 79 ++++++++++++++++++- .../Sliders/SliderCircleSelectionBlueprint.cs | 7 +- .../Sliders/SliderSelectionBlueprint.cs | 17 ++-- 3 files changed, 90 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs index 8cf5a2f33e..61c8316ed9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs @@ -3,11 +3,14 @@ using System; using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Objects; @@ -29,11 +32,16 @@ namespace osu.Game.Rulesets.Osu.Tests typeof(PathControlPointPiece) }; - private readonly DrawableSlider drawableObject; + private Slider slider; + private DrawableSlider drawableObject; + private TestSliderBlueprint blueprint; - public TestSceneSliderSelectionBlueprint() + [SetUp] + public void Setup() => Schedule(() => { - var slider = new Slider + Clear(); + + slider = new Slider { Position = new Vector2(256, 192), Path = new SliderPath(PathType.Bezier, new[] @@ -47,8 +55,73 @@ namespace osu.Game.Rulesets.Osu.Tests slider.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 }); Add(drawableObject = new DrawableSlider(slider)); + AddBlueprint(blueprint = new TestSliderBlueprint(drawableObject)); + }); + + [Test] + public void TestInitialState() + { + checkPositions(); + } + + [Test] + public void TestMoveHitObject() + { + moveHitObject(); + checkPositions(); + } + + [Test] + public void TestMoveAfterApplyingDefaults() + { + AddStep("apply defaults", () => slider.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 })); + moveHitObject(); + checkPositions(); + } + + private void moveHitObject() + { + AddStep("move hitobject", () => + { + slider.Position = new Vector2(300, 225); + }); + } + + private void checkPositions() + { + AddAssert("body positioned correctly", () => blueprint.BodyPiece.Position == slider.Position); + + AddAssert("head positioned correctly", + () => Precision.AlmostEquals(blueprint.HeadBlueprint.CirclePiece.ScreenSpaceDrawQuad.Centre, drawableObject.HeadCircle.ScreenSpaceDrawQuad.Centre)); + + AddAssert("tail positioned correctly", + () => Precision.AlmostEquals(blueprint.TailBlueprint.CirclePiece.ScreenSpaceDrawQuad.Centre, drawableObject.TailCircle.ScreenSpaceDrawQuad.Centre)); } protected override SelectionBlueprint CreateBlueprint() => new SliderSelectionBlueprint(drawableObject); + + private class TestSliderBlueprint : SliderSelectionBlueprint + { + public new SliderBodyPiece BodyPiece => base.BodyPiece; + public new TestSliderCircleBlueprint HeadBlueprint => (TestSliderCircleBlueprint)base.HeadBlueprint; + public new TestSliderCircleBlueprint TailBlueprint => (TestSliderCircleBlueprint)base.TailBlueprint; + + public TestSliderBlueprint(DrawableSlider slider) + : base(slider) + { + } + + protected override SliderCircleSelectionBlueprint CreateCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position) => new TestSliderCircleBlueprint(slider, position); + } + + private class TestSliderCircleBlueprint : SliderCircleSelectionBlueprint + { + public new HitCirclePiece CirclePiece => base.CirclePiece; + + public TestSliderCircleBlueprint(DrawableSlider slider, SliderPosition position) + : base(slider, position) + { + } + } } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs index 8f9a9c3a64..f09279ed73 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs @@ -9,14 +9,15 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { public class SliderCircleSelectionBlueprint : OsuSelectionBlueprint { + protected readonly HitCirclePiece CirclePiece; + private readonly SliderPosition position; - private readonly HitCirclePiece circlePiece; public SliderCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position) : base(slider) { this.position = position; - InternalChild = circlePiece = new HitCirclePiece(); + InternalChild = CirclePiece = new HitCirclePiece(); Select(); } @@ -25,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { base.Update(); - circlePiece.UpdateFrom(position == SliderPosition.Start ? HitObject.HeadCircle : HitObject.TailCircle); + CirclePiece.UpdateFrom(position == SliderPosition.Start ? HitObject.HeadCircle : HitObject.TailCircle); } // Todo: This is temporary, since the slider circle masks don't do anything special yet. In the future they will handle input. diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index bc760c9456..fdeffc6f8a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -11,8 +11,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { public class SliderSelectionBlueprint : OsuSelectionBlueprint { - private readonly SliderBodyPiece bodyPiece; - private readonly SliderCircleSelectionBlueprint headBlueprint; + protected readonly SliderBodyPiece BodyPiece; + protected readonly SliderCircleSelectionBlueprint HeadBlueprint; + protected readonly SliderCircleSelectionBlueprint TailBlueprint; public SliderSelectionBlueprint(DrawableSlider slider) : base(slider) @@ -21,9 +22,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders InternalChildren = new Drawable[] { - bodyPiece = new SliderBodyPiece(), - headBlueprint = new SliderCircleSelectionBlueprint(slider, SliderPosition.Start), - new SliderCircleSelectionBlueprint(slider, SliderPosition.End), + BodyPiece = new SliderBodyPiece(), + HeadBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.Start), + TailBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.End), new PathControlPointVisualiser(sliderObject), }; } @@ -32,9 +33,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { base.Update(); - bodyPiece.UpdateFrom(HitObject); + BodyPiece.UpdateFrom(HitObject); } - public override Vector2 SelectionPoint => headBlueprint.SelectionPoint; + public override Vector2 SelectionPoint => HeadBlueprint.SelectionPoint; + + protected virtual SliderCircleSelectionBlueprint CreateCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position) => new SliderCircleSelectionBlueprint(slider, position); } } From c5540048ab1608873b6377f2fa15bbd4b5b7ab01 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 1 Oct 2019 19:39:06 +0900 Subject: [PATCH 3230/5608] Fix tail circle not moving with slider position changes --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index d8514092bc..3ed1f2cdde 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -54,13 +54,13 @@ namespace osu.Game.Rulesets.Osu.Objects { base.Position = value; + endPositionCache.Invalidate(); + if (HeadCircle != null) HeadCircle.Position = value; if (TailCircle != null) TailCircle.Position = EndPosition; - - endPositionCache.Invalidate(); } } From ff477cd56c36eb99a8e238dd0de607fc5f3a6222 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 1 Oct 2019 14:12:03 +0300 Subject: [PATCH 3231/5608] 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 208b9a4eba5c5df080683456afae698feafe99c9 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Tue, 1 Oct 2019 20:47:53 +0700 Subject: [PATCH 3232/5608] Add new virtual float for username to timestamp padding --- .../Visual/Online/TestSceneStandAloneChatDisplay.cs | 12 ++++++++++++ osu.Game/Online/Chat/StandAloneChatDisplay.cs | 1 + osu.Game/Overlays/Chat/ChatLine.cs | 8 +++++--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs index 91006bc0d9..3c5641fcd6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs @@ -32,6 +32,12 @@ namespace osu.Game.Tests.Visual.Online Id = 4, }; + private readonly User longUsernameUser = new User + { + Username = "Very Long Long Username", + Id = 5, + }; + [Cached] private ChannelManager channelManager = new ChannelManager(); @@ -99,6 +105,12 @@ namespace osu.Game.Tests.Visual.Online Sender = admin, Content = "Okay okay, calm down guys. Let's do this!" })); + + AddStep("message from long username", () => testChannel.AddNewMessages(new Message(sequence++) + { + Sender = longUsernameUser, + Content = "Hi guys, my new username is lit!" + })); } } } diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 9dab2f2aba..00defd5f34 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -146,6 +146,7 @@ namespace osu.Game.Online.Chat protected override float HorizontalPadding => 10; protected override float MessagePadding => 120; + protected override float TimestampPadding => 130; public StandAloneMessage(Message message) : base(message) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 7596231a3d..1f5f5d3ff6 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -31,7 +31,9 @@ namespace osu.Game.Overlays.Chat protected virtual float MessagePadding => default_message_padding; - private const float timestamp_padding = 65; + private const float default_timestamp_padding = 65; + + protected virtual float TimestampPadding => default_timestamp_padding; private const float default_horizontal_padding = 15; @@ -94,7 +96,7 @@ namespace osu.Game.Overlays.Chat Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - MaxWidth = default_message_padding - timestamp_padding + MaxWidth = default_message_padding - TimestampPadding }; if (hasBackground) @@ -149,7 +151,7 @@ namespace osu.Game.Overlays.Chat new MessageSender(message.Sender) { AutoSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = timestamp_padding }, + Padding = new MarginPadding { Left = TimestampPadding }, Origin = Anchor.TopRight, Anchor = Anchor.TopRight, Child = effectedUsername, From 5f700f2ae9e57139cfa4aa0cb7e249363cc6d7e6 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 1 Oct 2019 08:26:34 -0700 Subject: [PATCH 3233/5608] Simplify exit logic of screens with textboxes using back button receptor --- .../Graphics/UserInterface/FocusedTextBox.cs | 16 +++++----------- osu.Game/Graphics/UserInterface/OsuTextBox.cs | 17 +---------------- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 4 ---- .../Chat/Selection/ChannelSelectionOverlay.cs | 1 - osu.Game/Overlays/ChatOverlay.cs | 1 - osu.Game/Overlays/Music/FilterControl.cs | 3 --- osu.Game/Overlays/Music/PlaylistOverlay.cs | 1 - .../SearchableList/SearchableListOverlay.cs | 2 -- osu.Game/Overlays/SettingsPanel.cs | 1 - .../Screens/Multi/Lounge/LoungeSubScreen.cs | 2 -- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 9 +-------- osu.Game/Screens/Select/FilterControl.cs | 8 +------- osu.Game/Screens/Select/SongSelect.cs | 5 ----- 13 files changed, 8 insertions(+), 62 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index f873db0dcb..62fbb3592c 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -2,22 +2,20 @@ // See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; -using System; using osu.Framework.Allocation; using osu.Framework.Input.Events; using osu.Framework.Platform; using osu.Game.Input.Bindings; using osuTK.Input; +using osu.Framework.Input.Bindings; namespace osu.Game.Graphics.UserInterface { /// /// A textbox which holds focus eagerly. /// - public class FocusedTextBox : OsuTextBox + public class FocusedTextBox : OsuTextBox, IKeyBindingHandler { - public Action Exit; - private bool focus; private bool allowImmediateFocus => host?.OnScreenKeyboardOverlapsGameWindow != true; @@ -68,7 +66,7 @@ namespace osu.Game.Graphics.UserInterface return base.OnKeyDown(e); } - public override bool OnPressed(GlobalAction action) + public bool OnPressed(GlobalAction action) { if (action == GlobalAction.Back) { @@ -79,14 +77,10 @@ namespace osu.Game.Graphics.UserInterface } } - return base.OnPressed(action); + return false; } - protected override void KillFocus() - { - base.KillFocus(); - Exit?.Invoke(); - } + public bool OnReleased(GlobalAction action) => false; public override bool RequestsFocus => HoldFocus; } diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index 89de91bc9b..1cac4d76ab 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -8,13 +8,11 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.Sprites; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; -using osu.Game.Input.Bindings; namespace osu.Game.Graphics.UserInterface { - public class OsuTextBox : TextBox, IKeyBindingHandler + public class OsuTextBox : TextBox { protected override float LeftRightPadding => 10; @@ -57,18 +55,5 @@ namespace osu.Game.Graphics.UserInterface } protected override Drawable GetDrawableCharacter(char c) => new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: CalculatedTextSize) }; - - public virtual bool OnPressed(GlobalAction action) - { - if (action == GlobalAction.Back) - { - KillFocus(); - return true; - } - - return false; - } - - public bool OnReleased(GlobalAction action) => false; } } diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 9dab2f2aba..b9edc36dfb 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -21,8 +21,6 @@ namespace osu.Game.Online.Chat { public readonly Bindable Channel = new Bindable(); - public Action Exit; - private readonly FocusedTextBox textbox; protected ChannelManager ChannelManager; @@ -66,8 +64,6 @@ namespace osu.Game.Online.Chat Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, }); - - textbox.Exit += () => Exit?.Invoke(); } Channel.BindValueChanged(channelChanged); diff --git a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs index e0ded11ec9..621728830a 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs @@ -119,7 +119,6 @@ namespace osu.Game.Overlays.Chat.Selection { RelativeSizeAxes = Axes.X, PlaceholderText = @"Search", - Exit = Hide, }, }, }, diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 6f848c7627..0cadbdfd31 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -138,7 +138,6 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Height = 1, PlaceholderText = "type your message", - Exit = Hide, OnCommit = postMessage, ReleaseFocusOnCommit = false, HoldFocus = true, diff --git a/osu.Game/Overlays/Music/FilterControl.cs b/osu.Game/Overlays/Music/FilterControl.cs index 99017579a2..278bb55170 100644 --- a/osu.Game/Overlays/Music/FilterControl.cs +++ b/osu.Game/Overlays/Music/FilterControl.cs @@ -31,7 +31,6 @@ namespace osu.Game.Overlays.Music { RelativeSizeAxes = Axes.X, Height = 40, - Exit = () => ExitRequested?.Invoke(), }, new CollectionsDropdown { @@ -47,8 +46,6 @@ namespace osu.Game.Overlays.Music private void current_ValueChanged(ValueChangedEvent e) => FilterChanged?.Invoke(e.NewValue); - public Action ExitRequested; - public Action FilterChanged; public class FilterTextBox : SearchTextBox diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index ae81a6c117..bb88960280 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -63,7 +63,6 @@ namespace osu.Game.Overlays.Music { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - ExitRequested = Hide, FilterChanged = search => list.Filter(search), Padding = new MarginPadding(10), }, diff --git a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs index 293ee4bcda..177f731f12 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs @@ -88,8 +88,6 @@ namespace osu.Game.Overlays.SearchableList }, }, }; - - Filter.Search.Exit = Hide; } protected override void Update() diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 9dd0def453..37e7b62483 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -91,7 +91,6 @@ namespace osu.Game.Overlays Top = 20, Bottom = 20 }, - Exit = Hide, }, Footer = CreateFooter() }, diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index 7f8e690516..0a48f761cf 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -69,8 +69,6 @@ namespace osu.Game.Screens.Multi.Lounge }, }, }; - - Filter.Search.Exit += this.Exit; } protected override void UpdateAfterChildren() diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index f3e10db444..c2bb7da6b5 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -62,7 +62,6 @@ namespace osu.Game.Screens.Multi.Match [BackgroundDependencyLoader] private void load() { - MatchChatDisplay chat; Components.Header header; Info info; GridContainer bottomRow; @@ -122,7 +121,7 @@ namespace osu.Game.Screens.Multi.Match Vertical = 10, }, RelativeSizeAxes = Axes.Both, - Child = chat = new MatchChatDisplay + Child = new MatchChatDisplay { RelativeSizeAxes = Axes.Both } @@ -159,12 +158,6 @@ namespace osu.Game.Screens.Multi.Match bottomRow.FadeTo(settingsDisplayed ? 0 : 1, fade_duration, Easing.OutQuint); }, true); - chat.Exit += () => - { - if (this.IsCurrentScreen()) - this.Exit(); - }; - beatmapManager.ItemAdded += beatmapAdded; } diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 91f1ca0307..8755c3fda6 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -49,8 +49,6 @@ namespace osu.Game.Screens.Select return criteria; } - public Action Exit; - private readonly SearchTextBox searchTextBox; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => @@ -75,11 +73,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.TopRight, Children = new Drawable[] { - searchTextBox = new SearchTextBox - { - RelativeSizeAxes = Axes.X, - Exit = () => Exit?.Invoke(), - }, + searchTextBox = new SearchTextBox { RelativeSizeAxes = Axes.X }, new Box { RelativeSizeAxes = Axes.X, diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index d40dd9414a..5ab49fa2b9 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -171,11 +171,6 @@ namespace osu.Game.Screens.Select Height = FilterControl.HEIGHT, FilterChanged = c => Carousel.Filter(c), Background = { Width = 2 }, - Exit = () => - { - if (this.IsCurrentScreen()) - this.Exit(); - }, }, } }, From ff6367fa4b113052fd835a05ff776049e3ca818f Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 1 Oct 2019 08:26:45 -0700 Subject: [PATCH 3234/5608] Make back button glow when pressing escape --- osu.Game/Graphics/UserInterface/BackButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 62c33b9a39..23565e8742 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -18,7 +18,7 @@ namespace osu.Game.Graphics.UserInterface public BackButton(Receptor receptor) { - receptor.OnBackPressed = () => Action?.Invoke(); + receptor.OnBackPressed = () => button.Click(); Size = TwoLayerButton.SIZE_EXTENDED; From e3502f52008e01e6de850ab7820332a9e6f2a694 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 1 Oct 2019 08:37:08 -0700 Subject: [PATCH 3235/5608] Fix typo on Key.Escape comment --- osu.Game/Graphics/UserInterface/FocusedTextBox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index 62fbb3592c..0b183c0ec9 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -61,7 +61,7 @@ namespace osu.Game.Graphics.UserInterface if (!HasFocus) return false; if (e.Key == Key.Escape) - return false; // disable the framework-level handling of escape key for confority (we use GlobalAction.Back). + return false; // disable the framework-level handling of escape key for conformity (we use GlobalAction.Back). return base.OnKeyDown(e); } From 2ac5e0bfa0b6961eb07e09f8995b5d041b449561 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Tue, 1 Oct 2019 17:39:01 +0200 Subject: [PATCH 3236/5608] Make use of SessionStatics --- osu.Game/Configuration/SessionStatics.cs | 2 ++ osu.Game/Screens/Play/PlayerLoader.cs | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Configuration/SessionStatics.cs b/osu.Game/Configuration/SessionStatics.cs index 818a95c0be..40b2adb867 100644 --- a/osu.Game/Configuration/SessionStatics.cs +++ b/osu.Game/Configuration/SessionStatics.cs @@ -11,11 +11,13 @@ namespace osu.Game.Configuration protected override void InitialiseDefaults() { Set(Static.LoginOverlayDisplayed, false); + Set(Static.MutedAudioNotificationShownOnce, false); } } public enum Static { LoginOverlayDisplayed, + MutedAudioNotificationShownOnce } } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 157ff8fcd4..635201879b 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -15,6 +16,7 @@ using osu.Framework.Localisation; using osu.Framework.Screens; using osu.Framework.Threading; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -71,8 +73,10 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load() + private void load(SessionStatics sessionStatics) { + muteWarningShownOnce = sessionStatics.GetBindable(Static.MutedAudioNotificationShownOnce); + InternalChild = (content = new LogoTrackingContainer { Anchor = Anchor.Centre, @@ -157,18 +161,18 @@ namespace osu.Game.Screens.Play [Resolved] private AudioManager audioManager { get; set; } - private static bool muteWarningShownOnce; + private Bindable muteWarningShownOnce; private void checkVolume() { - if (muteWarningShownOnce) + if (muteWarningShownOnce.Value) return; //Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. if (volumeOverlay?.IsMuted.Value == true || audioManager.Volume.Value <= audioManager.Volume.MinValue || audioManager.VolumeTrack.Value <= audioManager.VolumeTrack.MinValue) { notificationOverlay?.Post(new MutedNotification()); - muteWarningShownOnce = true; + muteWarningShownOnce.Value = true; } } From 5f399add82ece40b2f927982f0762d1d86369c04 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Tue, 1 Oct 2019 18:15:40 +0200 Subject: [PATCH 3237/5608] Resolve @iiSaLMaN 's suggested changes --- osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs | 6 +++++- osu.Game/Screens/Play/PlayerLoader.cs | 8 -------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 6866fd4c62..74ae641bfe 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; using osu.Framework.Screens; +using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; @@ -36,6 +37,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Resolved] private AudioManager audioManager { get; set; } + [Resolved] + private SessionStatics sessionStatics { get; set; } + /// /// Sets the input manager child to a new test player loader container instance. /// @@ -137,7 +141,7 @@ namespace osu.Game.Tests.Visual.Gameplay /// The function to be invoked and checked private void addVolumeSteps(string volumeName, Action beforeLoad, Action afterLoad, Func assert) { - AddStep("reset notification lock", PlayerLoader.ResetNotificationLock); + AddStep("reset notification lock", () => sessionStatics.GetBindable(Static.MutedAudioNotificationShownOnce).Value = false); AddStep("load player", () => ResetPlayer(false, beforeLoad, afterLoad)); AddUntilStep("wait for player", () => player.IsLoaded); diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 635201879b..7f8ef60a5d 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -536,13 +536,5 @@ namespace osu.Game.Screens.Play }; } } - - /// - /// Sets to false, reserved for testing. - /// - public static void ResetNotificationLock() - { - muteWarningShownOnce = false; - } } } From b6dd610af847b9d15c7a8fcb761110f7fd40c18f Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Tue, 1 Oct 2019 23:18:03 +0700 Subject: [PATCH 3238/5608] Apply reviews --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 2 +- osu.Game/Overlays/Chat/ChatLine.cs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 00defd5f34..6a94cec4fd 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -146,7 +146,7 @@ namespace osu.Game.Online.Chat protected override float HorizontalPadding => 10; protected override float MessagePadding => 120; - protected override float TimestampPadding => 130; + protected override float TimestampPadding => 50; public StandAloneMessage(Message message) : base(message) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 1f5f5d3ff6..db378bde73 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -96,7 +96,7 @@ namespace osu.Game.Overlays.Chat Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - MaxWidth = default_message_padding - TimestampPadding + MaxWidth = MessagePadding - TimestampPadding }; if (hasBackground) @@ -151,7 +151,6 @@ namespace osu.Game.Overlays.Chat new MessageSender(message.Sender) { AutoSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = TimestampPadding }, Origin = Anchor.TopRight, Anchor = Anchor.TopRight, Child = effectedUsername, From faf8fe132ecc0fc9971406d25a09109088fa4b32 Mon Sep 17 00:00:00 2001 From: HDragonHR Date: Wed, 2 Oct 2019 12:26:46 +0800 Subject: [PATCH 3239/5608] Change bindable int to float --- osu.Game/Configuration/OsuConfigManager.cs | 2 +- osu.Game/Graphics/Containers/HoldToConfirmContainer.cs | 4 ++-- .../Settings/Sections/Graphics/UserInterfaceSettings.cs | 6 +++--- osu.Game/Screens/Menu/MainMenu.cs | 4 ++-- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 64b1f2d7bc..c0ce08ba08 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -114,7 +114,7 @@ namespace osu.Game.Configuration Set(OsuSetting.UIScale, 1f, 0.8f, 1.6f, 0.01f); - Set(OsuSetting.UIHoldActivationDelay, 200, 0, 500); + Set(OsuSetting.UIHoldActivationDelay, 200f, 0f, 500f, 50f); Set(OsuSetting.IntroSequence, IntroSequence.Triangles); } diff --git a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs index 5d549ba217..fcf445a878 100644 --- a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs +++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs @@ -30,12 +30,12 @@ namespace osu.Game.Graphics.Containers public Bindable Progress = new BindableDouble(); - private Bindable holdActivationDelay; + private Bindable holdActivationDelay; [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - holdActivationDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); + holdActivationDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); } protected void BeginConfirm() diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs index a6956b7d9a..a8953ac3a2 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs @@ -27,16 +27,16 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics LabelText = "Parallax", Bindable = config.GetBindable(OsuSetting.MenuParallax) }, - new SettingsSlider + new SettingsSlider { LabelText = "Hold-to-confirm activation time", - Bindable = config.GetBindable(OsuSetting.UIHoldActivationDelay), + Bindable = config.GetBindable(OsuSetting.UIHoldActivationDelay), KeyboardStep = 50 }, }; } - private class TimeSlider : OsuSliderBar + private class TimeSlider : OsuSliderBar { public override string TooltipText => Current.Value.ToString("N0") + "ms"; } diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 16e9d67cc3..c195ed6cb6 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -62,7 +62,7 @@ namespace osu.Game.Screens.Menu protected override BackgroundScreen CreateBackground() => background; - private Bindable holdDelay; + private Bindable holdDelay; private Bindable loginDisplayed; private ExitConfirmOverlay exitConfirmOverlay; @@ -70,7 +70,7 @@ namespace osu.Game.Screens.Menu [BackgroundDependencyLoader(true)] private void load(DirectOverlay direct, SettingsOverlay settings, OsuConfigManager config, SessionStatics statics) { - holdDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); + holdDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); loginDisplayed = statics.GetBindable(Static.LoginOverlayDisplayed); if (host.CanExit) diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 2dc50326a8..a05937801c 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -63,11 +63,11 @@ namespace osu.Game.Screens.Play.HUD [Resolved] private OsuConfigManager config { get; set; } - private Bindable activationDelay; + private Bindable activationDelay; protected override void LoadComplete() { - activationDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); + activationDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); activationDelay.BindValueChanged(v => { text.Text = v.NewValue > 0 From dfaa9531f8f4fc6470a5a4bb60bea87fc44eed76 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 2 Oct 2019 18:48:50 +0900 Subject: [PATCH 3240/5608] Only lock the database for the duration of a deletion --- osu.Game/Database/ArchiveModelManager.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 17d1bd822e..2cc1e016d1 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -400,20 +400,17 @@ namespace osu.Game.Database int i = 0; - using (ContextFactory.GetForWrite()) + foreach (var b in items) { - foreach (var b in items) - { - if (notification.State == ProgressNotificationState.Cancelled) - // user requested abort - return; + if (notification.State == ProgressNotificationState.Cancelled) + // user requested abort + return; - notification.Text = $"Deleting {HumanisedModelName}s ({++i} of {items.Count})"; + notification.Text = $"Deleting {HumanisedModelName}s ({++i} of {items.Count})"; - Delete(b); + Delete(b); - notification.Progress = (float)i / items.Count; - } + notification.Progress = (float)i / items.Count; } notification.State = ProgressNotificationState.Completed; From 6929847b0870664c8f2568170cd08935cc876dd8 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Wed, 2 Oct 2019 17:22:34 +0200 Subject: [PATCH 3241/5608] Remove redundant override --- osu.Game/Screens/Play/PlayerLoader.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 7f8ef60a5d..cd4b331fce 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -516,8 +516,6 @@ namespace osu.Game.Screens.Play public override bool IsImportant => true; - public override bool RequestsFocus => true; - [BackgroundDependencyLoader] private void load(OsuColour colours, AudioManager audioManager, NotificationOverlay notificationOverlay, VolumeOverlay volumeOverlay) { From a69b9f1148bbee373e6243452291cbab0bab0e16 Mon Sep 17 00:00:00 2001 From: Joehu Date: Wed, 2 Oct 2019 11:16:31 -0700 Subject: [PATCH 3242/5608] Fix alt-f4 being blocked during gameplay --- osu.Game/Screens/Play/Player.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 44be73b089..91d34c8056 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -299,7 +299,10 @@ namespace osu.Game.Screens.Play { if (!this.IsCurrentScreen()) return; - this.Exit(); + if (canPause) + Pause(); + else + this.Exit(); } public void Restart() @@ -508,12 +511,6 @@ namespace osu.Game.Screens.Play return true; } - if (canPause) - { - Pause(); - return true; - } - // ValidForResume is false when restarting if (ValidForResume) { From 752dd26a4f5a73823a9acbcbc5b518f9a9b6f4bf Mon Sep 17 00:00:00 2001 From: Joehu Date: Wed, 2 Oct 2019 11:17:43 -0700 Subject: [PATCH 3243/5608] Fix alt-f4 being blocked in interface --- osu.Game/Screens/Menu/MainMenu.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index c195ed6cb6..df4803b2b6 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -81,8 +81,8 @@ namespace osu.Game.Screens.Menu { if (holdDelay.Value > 0) confirmAndExit(); - else - this.Exit(); + else if (!exitConfirmed && dialogOverlay != null && !(dialogOverlay.CurrentDialog is ConfirmExitDialog)) + dialogOverlay.Push(new ConfirmExitDialog(confirmAndExit, () => exitConfirmOverlay.Abort())); } }); } @@ -253,12 +253,6 @@ namespace osu.Game.Screens.Menu public override bool OnExiting(IScreen next) { - if (!exitConfirmed && dialogOverlay != null && !(dialogOverlay.CurrentDialog is ConfirmExitDialog)) - { - dialogOverlay.Push(new ConfirmExitDialog(confirmAndExit, () => exitConfirmOverlay.Abort())); - return true; - } - buttons.State = ButtonSystemState.Exit; this.FadeOut(3000); return base.OnExiting(next); From ff56453f1a259ed80d8ab6338ba4d8c9b93a27d3 Mon Sep 17 00:00:00 2001 From: Joehu Date: Wed, 2 Oct 2019 12:07:07 -0700 Subject: [PATCH 3244/5608] Fix test regressions --- osu.Game.Tests/Visual/Gameplay/TestScenePause.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 50583e43c4..c67001c3d8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -132,9 +132,7 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("exit", () => Player.Exit()); - confirmPaused(); - - exitAndConfirm(); + confirmExited(); } [Test] From 38fe519c91f9836f46b6a9347e4ceb97a96f0d67 Mon Sep 17 00:00:00 2001 From: Joehu Date: Wed, 2 Oct 2019 12:28:48 -0700 Subject: [PATCH 3245/5608] Remove unnecessary exitConfirmed condition check --- osu.Game/Screens/Menu/MainMenu.cs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index df4803b2b6..6deb29c2f2 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -80,9 +80,9 @@ namespace osu.Game.Screens.Menu Action = () => { if (holdDelay.Value > 0) - confirmAndExit(); - else if (!exitConfirmed && dialogOverlay != null && !(dialogOverlay.CurrentDialog is ConfirmExitDialog)) - dialogOverlay.Push(new ConfirmExitDialog(confirmAndExit, () => exitConfirmOverlay.Abort())); + this.Exit(); + else if (dialogOverlay != null && !(dialogOverlay.CurrentDialog is ConfirmExitDialog)) + dialogOverlay.Push(new ConfirmExitDialog(this.Exit, () => exitConfirmOverlay.Abort())); } }); } @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Menu OnEdit = delegate { this.Push(new Editor()); }, OnSolo = onSolo, OnMulti = delegate { this.Push(new Multiplayer()); }, - OnExit = confirmAndExit, + OnExit = this.Exit, } } }, @@ -129,12 +129,6 @@ namespace osu.Game.Screens.Menu preloadSongSelect(); } - private void confirmAndExit() - { - exitConfirmed = true; - this.Exit(); - } - private void preloadSongSelect() { if (songSelect == null) @@ -172,8 +166,6 @@ namespace osu.Game.Screens.Menu Beatmap.ValueChanged += beatmap_ValueChanged; } - private bool exitConfirmed; - protected override void LogoArriving(OsuLogo logo, bool resuming) { base.LogoArriving(logo, resuming); From 148089f160240fc408f5a68b72caa2b84dc8731e Mon Sep 17 00:00:00 2001 From: Joehu Date: Wed, 2 Oct 2019 16:08:19 -0700 Subject: [PATCH 3246/5608] Revert "Remove unnecessary exitConfirmed condition check" This reverts commit 38fe519c91f9836f46b6a9347e4ceb97a96f0d67. --- osu.Game/Screens/Menu/MainMenu.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 6deb29c2f2..df4803b2b6 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -80,9 +80,9 @@ namespace osu.Game.Screens.Menu Action = () => { if (holdDelay.Value > 0) - this.Exit(); - else if (dialogOverlay != null && !(dialogOverlay.CurrentDialog is ConfirmExitDialog)) - dialogOverlay.Push(new ConfirmExitDialog(this.Exit, () => exitConfirmOverlay.Abort())); + confirmAndExit(); + else if (!exitConfirmed && dialogOverlay != null && !(dialogOverlay.CurrentDialog is ConfirmExitDialog)) + dialogOverlay.Push(new ConfirmExitDialog(confirmAndExit, () => exitConfirmOverlay.Abort())); } }); } @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Menu OnEdit = delegate { this.Push(new Editor()); }, OnSolo = onSolo, OnMulti = delegate { this.Push(new Multiplayer()); }, - OnExit = this.Exit, + OnExit = confirmAndExit, } } }, @@ -129,6 +129,12 @@ namespace osu.Game.Screens.Menu preloadSongSelect(); } + private void confirmAndExit() + { + exitConfirmed = true; + this.Exit(); + } + private void preloadSongSelect() { if (songSelect == null) @@ -166,6 +172,8 @@ namespace osu.Game.Screens.Menu Beatmap.ValueChanged += beatmap_ValueChanged; } + private bool exitConfirmed; + protected override void LogoArriving(OsuLogo logo, bool resuming) { base.LogoArriving(logo, resuming); From 80177885213d56d52f2386dc885784c0549a0db6 Mon Sep 17 00:00:00 2001 From: Joehu Date: Wed, 2 Oct 2019 16:08:24 -0700 Subject: [PATCH 3247/5608] Revert "Fix alt-f4 being blocked in interface" This reverts commit 752dd26a4f5a73823a9acbcbc5b518f9a9b6f4bf. --- osu.Game/Screens/Menu/MainMenu.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index df4803b2b6..c195ed6cb6 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -81,8 +81,8 @@ namespace osu.Game.Screens.Menu { if (holdDelay.Value > 0) confirmAndExit(); - else if (!exitConfirmed && dialogOverlay != null && !(dialogOverlay.CurrentDialog is ConfirmExitDialog)) - dialogOverlay.Push(new ConfirmExitDialog(confirmAndExit, () => exitConfirmOverlay.Abort())); + else + this.Exit(); } }); } @@ -253,6 +253,12 @@ namespace osu.Game.Screens.Menu public override bool OnExiting(IScreen next) { + if (!exitConfirmed && dialogOverlay != null && !(dialogOverlay.CurrentDialog is ConfirmExitDialog)) + { + dialogOverlay.Push(new ConfirmExitDialog(confirmAndExit, () => exitConfirmOverlay.Abort())); + return true; + } + buttons.State = ButtonSystemState.Exit; this.FadeOut(3000); return base.OnExiting(next); From f8eb07b21116e9ae3f01eba30cd626e50f097a32 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 11:23:21 +0900 Subject: [PATCH 3248/5608] Only lock database for the duration of a model restoration --- osu.Game/Database/ArchiveModelManager.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 2cc1e016d1..b567f0c0e3 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -436,20 +436,17 @@ namespace osu.Game.Database int i = 0; - using (ContextFactory.GetForWrite()) + foreach (var item in items) { - foreach (var item in items) - { - if (notification.State == ProgressNotificationState.Cancelled) - // user requested abort - return; + if (notification.State == ProgressNotificationState.Cancelled) + // user requested abort + return; - notification.Text = $"Restoring ({++i} of {items.Count})"; + notification.Text = $"Restoring ({++i} of {items.Count})"; - Undelete(item); + Undelete(item); - notification.Progress = (float)i / items.Count; - } + notification.Progress = (float)i / items.Count; } notification.State = ProgressNotificationState.Completed; From 897b3233afdd196157db7891bc7ad05b8a173e0e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 14:23:48 +0900 Subject: [PATCH 3249/5608] Add start time tracking to EditorBeatmap --- osu.Game/Rulesets/Objects/HitObject.cs | 20 ++++++++++++++++- osu.Game/Screens/Edit/EditorBeatmap.cs | 31 +++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 6c5627c5d2..a99fac09cc 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using Newtonsoft.Json; +using osu.Framework.Bindables; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; @@ -27,10 +28,16 @@ namespace osu.Game.Rulesets.Objects /// private const double control_point_leniency = 1; + public readonly Bindable StartTimeBindable = new Bindable(); + /// /// The time at which the HitObject starts. /// - public virtual double StartTime { get; set; } + public virtual double StartTime + { + get => StartTimeBindable.Value; + set => StartTimeBindable.Value = value; + } private List samples; @@ -67,6 +74,17 @@ namespace osu.Game.Rulesets.Objects [JsonIgnore] public IReadOnlyList NestedHitObjects => nestedHitObjects; + public HitObject() + { + StartTimeBindable.ValueChanged += time => + { + double offset = time.NewValue - time.OldValue; + + foreach (var nested in NestedHitObjects) + nested.StartTime += offset; + }; + } + /// /// Applies default values to this HitObject. /// diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index f0b6c62154..22aa133de7 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Timing; @@ -15,12 +16,17 @@ namespace osu.Game.Screens.Edit { public event Action HitObjectAdded; public event Action HitObjectRemoved; + public event Action HitObjectChanged; + private readonly Dictionary> startTimeBindables = new Dictionary>(); private readonly Beatmap beatmap; public EditorBeatmap(Beatmap beatmap) { this.beatmap = beatmap; + + foreach (var obj in HitObjects) + trackStartTime(obj); } public BeatmapInfo BeatmapInfo @@ -37,7 +43,7 @@ namespace osu.Game.Screens.Edit public double TotalBreakTime => beatmap.TotalBreakTime; - IReadOnlyList IBeatmap.HitObjects => beatmap.HitObjects; + public IReadOnlyList HitObjects => beatmap.HitObjects; IReadOnlyList IBeatmap.HitObjects => beatmap.HitObjects; @@ -51,6 +57,8 @@ namespace osu.Game.Screens.Edit /// The to add. public void Add(T hitObject) { + trackStartTime(hitObject); + // Preserve existing sorting order in the beatmap var insertionIndex = beatmap.HitObjects.FindLastIndex(h => h.StartTime <= hitObject.StartTime); beatmap.HitObjects.Insert(insertionIndex + 1, hitObject); @@ -65,7 +73,28 @@ namespace osu.Game.Screens.Edit public void Remove(T hitObject) { if (beatmap.HitObjects.Remove(hitObject)) + { + var bindable = startTimeBindables[hitObject]; + bindable.UnbindAll(); + + startTimeBindables.Remove(hitObject); HitObjectRemoved?.Invoke(hitObject); + } + } + + private void trackStartTime(T hitObject) + { + startTimeBindables[hitObject] = hitObject.StartTimeBindable.GetBoundCopy(); + startTimeBindables[hitObject].ValueChanged += _ => + { + // For now we'll remove and re-add the hitobject. This is not optimal and can be improved if required. + beatmap.HitObjects.Remove(hitObject); + + var insertionIndex = beatmap.HitObjects.FindLastIndex(h => h.StartTime <= hitObject.StartTime); + beatmap.HitObjects.Insert(insertionIndex + 1, hitObject); + + HitObjectChanged?.Invoke(hitObject); + }; } /// From f2719afd0e7f7e445659e413e03edd32125db3f0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 14:27:40 +0900 Subject: [PATCH 3250/5608] Add tests for Editorbeatmap --- osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs | 154 +++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs diff --git a/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs b/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs new file mode 100644 index 0000000000..88c9f9cb6c --- /dev/null +++ b/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs @@ -0,0 +1,154 @@ +// 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 Microsoft.EntityFrameworkCore.Internal; +using NUnit.Framework; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Edit; + +namespace osu.Game.Tests.Beatmaps +{ + [TestFixture] + public class EditorBeatmapTest + { + /// + /// Tests that the addition event is correctly invoked after a hitobject is added. + /// + [Test] + public void TestHitObjectAddEvent() + { + var editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + + HitObject addedObject = null; + editorBeatmap.HitObjectAdded += h => addedObject = h; + + var hitCircle = new HitCircle(); + + editorBeatmap.Add(hitCircle); + Assert.That(addedObject, Is.EqualTo(hitCircle)); + } + + /// + /// Tests that the removal event is correctly invoked after a hitobject is removed. + /// + [Test] + public void HitObjectRemoveEvent() + { + var hitCircle = new HitCircle(); + var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); + + HitObject removedObject = null; + editorBeatmap.HitObjectRemoved += h => removedObject = h; + + editorBeatmap.Remove(hitCircle); + Assert.That(removedObject, Is.EqualTo(hitCircle)); + } + + /// + /// Tests that the changed event is correctly invoked after the start time of a hitobject is changed. + /// This tests for hitobjects which were already present before the editor beatmap was constructed. + /// + [Test] + public void TestInitialHitObjectStartTimeChangeEvent() + { + var hitCircle = new HitCircle(); + var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); + + HitObject changedObject = null; + editorBeatmap.HitObjectChanged += h => changedObject = h; + + hitCircle.StartTime = 1000; + Assert.That(changedObject, Is.EqualTo(hitCircle)); + } + + /// + /// Tests that the changed event is correctly invoked after the start time of a hitobject is changed. + /// This tests for hitobjects which were added to an existing editor beatmap. + /// + [Test] + public void TestAddedHitObjectStartTimeChangeEvent() + { + var editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + + HitObject changedObject = null; + editorBeatmap.HitObjectChanged += h => changedObject = h; + + var hitCircle = new HitCircle(); + + editorBeatmap.Add(hitCircle); + Assert.That(changedObject, Is.Null); + + hitCircle.StartTime = 1000; + Assert.That(changedObject, Is.EqualTo(hitCircle)); + } + + /// + /// Tests that the channged event is not invoked after a hitobject is removed from the beatmap/ + /// + [Test] + public void TestRemovedHitObjectStartTimeChangeEvent() + { + var hitCircle = new HitCircle(); + var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); + + HitObject changedObject = null; + editorBeatmap.HitObjectChanged += h => changedObject = h; + + editorBeatmap.Remove(hitCircle); + Assert.That(changedObject, Is.Null); + + hitCircle.StartTime = 1000; + Assert.That(changedObject, Is.Null); + } + + /// + /// Tests that an added hitobject is correctly inserted to preserve the sorting order of the beatmap. + /// + [Test] + public void TestAddHitObjectInMiddle() + { + var editorBeatmap = new EditorBeatmap(new OsuBeatmap + { + HitObjects = + { + new HitCircle(), + new HitCircle { StartTime = 1000 }, + new HitCircle { StartTime = 1000 }, + new HitCircle { StartTime = 2000 }, + } + }); + + var hitCircle = new HitCircle { StartTime = 1000 }; + editorBeatmap.Add(hitCircle); + Assert.That(editorBeatmap.HitObjects.Count(h => h == hitCircle), Is.EqualTo(1)); + Assert.That(editorBeatmap.HitObjects.IndexOf(hitCircle), Is.EqualTo(3)); + } + + /// + /// Tests that the beatmap remains correctly sorted after the start time of a hitobject is changed. + /// + [Test] + public void TestResortWhenStartTimeChanged() + { + var hitCircle = new HitCircle { StartTime = 1000 }; + var editorBeatmap = new EditorBeatmap(new OsuBeatmap + { + HitObjects = + { + new HitCircle(), + new HitCircle { StartTime = 1000 }, + new HitCircle { StartTime = 1000 }, + hitCircle, + new HitCircle { StartTime = 2000 }, + } + }); + + hitCircle.StartTime = 0; + Assert.That(editorBeatmap.HitObjects.Count(h => h == hitCircle), Is.EqualTo(1)); + Assert.That(editorBeatmap.HitObjects.IndexOf(hitCircle), Is.EqualTo(1)); + } + } +} From 3fb0b0b66833d107ef2e5e17f9930959deefeff2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 14:37:16 +0900 Subject: [PATCH 3251/5608] Rename to StartTimeChanged and add xmldocs --- osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs | 6 +++--- osu.Game/Screens/Edit/EditorBeatmap.cs | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs b/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs index 88c9f9cb6c..98e630abd2 100644 --- a/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Beatmaps var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); HitObject changedObject = null; - editorBeatmap.HitObjectChanged += h => changedObject = h; + editorBeatmap.StartTimeChanged += h => changedObject = h; hitCircle.StartTime = 1000; Assert.That(changedObject, Is.EqualTo(hitCircle)); @@ -74,7 +74,7 @@ namespace osu.Game.Tests.Beatmaps var editorBeatmap = new EditorBeatmap(new OsuBeatmap()); HitObject changedObject = null; - editorBeatmap.HitObjectChanged += h => changedObject = h; + editorBeatmap.StartTimeChanged += h => changedObject = h; var hitCircle = new HitCircle(); @@ -95,7 +95,7 @@ namespace osu.Game.Tests.Beatmaps var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); HitObject changedObject = null; - editorBeatmap.HitObjectChanged += h => changedObject = h; + editorBeatmap.StartTimeChanged += h => changedObject = h; editorBeatmap.Remove(hitCircle); Assert.That(changedObject, Is.Null); diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index 22aa133de7..c3a322ea36 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -14,9 +14,20 @@ namespace osu.Game.Screens.Edit public class EditorBeatmap : IEditorBeatmap where T : HitObject { + /// + /// Invoked when a is added to this . + /// public event Action HitObjectAdded; + + /// + /// Invoked when a is removed from this . + /// public event Action HitObjectRemoved; - public event Action HitObjectChanged; + + /// + /// Invoked when the start time of a in this was changed. + /// + public event Action StartTimeChanged; private readonly Dictionary> startTimeBindables = new Dictionary>(); private readonly Beatmap beatmap; @@ -93,7 +104,7 @@ namespace osu.Game.Screens.Edit var insertionIndex = beatmap.HitObjects.FindLastIndex(h => h.StartTime <= hitObject.StartTime); beatmap.HitObjects.Insert(insertionIndex + 1, hitObject); - HitObjectChanged?.Invoke(hitObject); + StartTimeChanged?.Invoke(hitObject); }; } From 2c13043c42b79fb166483862284fce652f3fb17f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 14:40:00 +0900 Subject: [PATCH 3252/5608] Hook up the event to HitObjectComposer --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index fc324d7021..a267d7c44d 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -132,6 +132,7 @@ namespace osu.Game.Rulesets.Edit editorBeatmap = new EditorBeatmap(playableBeatmap); editorBeatmap.HitObjectAdded += addHitObject; editorBeatmap.HitObjectRemoved += removeHitObject; + editorBeatmap.StartTimeChanged += updateHitObject; var dependencies = new DependencyContainer(parent); dependencies.CacheAs(editorBeatmap); @@ -162,12 +163,7 @@ namespace osu.Game.Rulesets.Edit }); } - private void addHitObject(HitObject hitObject) - { - beatmapProcessor?.PreProcess(); - hitObject.ApplyDefaults(playableBeatmap.ControlPointInfo, playableBeatmap.BeatmapInfo.BaseDifficulty); - beatmapProcessor?.PostProcess(); - } + private void addHitObject(HitObject hitObject) => updateHitObject(hitObject); private void removeHitObject(HitObject hitObject) { @@ -175,6 +171,13 @@ namespace osu.Game.Rulesets.Edit beatmapProcessor?.PostProcess(); } + private void updateHitObject(HitObject hitObject) + { + beatmapProcessor?.PreProcess(); + hitObject.ApplyDefaults(playableBeatmap.ControlPointInfo, playableBeatmap.BeatmapInfo.BaseDifficulty); + beatmapProcessor?.PostProcess(); + } + public override IEnumerable HitObjects => drawableRulesetWrapper.Playfield.AllHitObjects; public override bool CursorInPlacementArea => drawableRulesetWrapper.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); From b28689c774c8a0e4bc029eda00cb5a4083ad040e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 3 Oct 2019 15:00:47 +0800 Subject: [PATCH 3253/5608] Fix key counters appearing negative on intense beatmaps When `FrameStabilityContainer` decides it needs multiple updates on the same frame, it ends up with an elapsed time of zero. This was interacting badly with the condition used in `RulesetInputManager` to govern playback direction. I have changed this to use `Rate` as exposed by the frame stable clock. - Closes #6198. --- .../Rulesets/UI/FrameStabilityContainer.cs | 28 ++++++++++--------- osu.Game/Rulesets/UI/RulesetInputManager.cs | 4 +-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 05d3c02381..74d3439c59 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -47,6 +47,11 @@ namespace osu.Game.Rulesets.UI private IFrameBasedClock parentGameplayClock; + /// + /// The current direction of playback to be exposed to frame stable children. + /// + private int direction; + [BackgroundDependencyLoader(true)] private void load(GameplayClock clock) { @@ -111,16 +116,12 @@ namespace osu.Game.Rulesets.UI validState = true; - manualClock.Rate = parentGameplayClock.Rate; - manualClock.IsRunning = parentGameplayClock.IsRunning; - var newProposedTime = parentGameplayClock.CurrentTime; try { if (!FrameStablePlayback) { - manualClock.CurrentTime = newProposedTime; requireMoreUpdateLoops = false; return; } @@ -128,9 +129,9 @@ namespace osu.Game.Rulesets.UI { // On the first update, frame-stability seeking would result in unexpected/unwanted behaviour. // Instead we perform an initial seek to the proposed time. - manualClock.CurrentTime = newProposedTime; - // do a second process to clear out ElapsedTime + // process frame (in addition to finally clause) to clear out ElapsedTime + manualClock.CurrentTime = newProposedTime; framedClock.ProcessFrame(); firstConsumption = false; @@ -144,11 +145,7 @@ namespace osu.Game.Rulesets.UI : Math.Max(newProposedTime, manualClock.CurrentTime - sixty_frame_time); } - if (!isAttached) - { - manualClock.CurrentTime = newProposedTime; - } - else + if (isAttached) { double? newTime = ReplayInputHandler.SetFrameFromTime(newProposedTime); @@ -156,9 +153,7 @@ namespace osu.Game.Rulesets.UI { // we shouldn't execute for this time value. probably waiting on more replay data. validState = false; - requireMoreUpdateLoops = true; - manualClock.CurrentTime = newProposedTime; return; } @@ -169,6 +164,13 @@ namespace osu.Game.Rulesets.UI } finally { + if (newProposedTime != manualClock.CurrentTime) + direction = newProposedTime > manualClock.CurrentTime ? 1 : -1; + + manualClock.CurrentTime = newProposedTime; + manualClock.Rate = Math.Abs(parentGameplayClock.Rate) * direction; + manualClock.IsRunning = parentGameplayClock.IsRunning; + // The manual clock time has changed in the above code. The framed clock now needs to be updated // to ensure that the its time is valid for our children before input is processed framedClock.ProcessFrame(); diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 98e27240d3..5cc213be41 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -137,9 +137,9 @@ namespace osu.Game.Rulesets.UI { } - public bool OnPressed(T action) => Target.Children.OfType>().Any(c => c.OnPressed(action, Clock.ElapsedFrameTime > 0)); + public bool OnPressed(T action) => Target.Children.OfType>().Any(c => c.OnPressed(action, Clock.Rate >= 0)); - public bool OnReleased(T action) => Target.Children.OfType>().Any(c => c.OnReleased(action, Clock.ElapsedFrameTime > 0)); + public bool OnReleased(T action) => Target.Children.OfType>().Any(c => c.OnReleased(action, Clock.Rate >= 0)); } #endregion From 652acac87fa69d2debfd9ee18872e08379c4ad0e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 16:14:42 +0900 Subject: [PATCH 3254/5608] Move placement movement event to BlueprintContainer --- .../Blueprints/HoldNotePlacementBlueprint.cs | 11 ++++------ .../Blueprints/ManiaPlacementBlueprint.cs | 9 ++++---- .../HitCircles/HitCirclePlacementBlueprint.cs | 13 ++--------- .../Sliders/SliderPlacementBlueprint.cs | 20 +++++------------ .../Spinners/SpinnerPlacementBlueprint.cs | 5 +++++ osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 8 ++++++- .../Compose/Components/BlueprintContainer.cs | 22 ++++++++++++++++++- 7 files changed, 48 insertions(+), 40 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs index 26115311f7..bcbc1ee527 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Graphics; -using osu.Framework.Input.Events; using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; using osu.Game.Rulesets.Mania.Objects; using osuTK; @@ -49,13 +48,13 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints private double originalStartTime; - protected override bool OnMouseMove(MouseMoveEvent e) + public override void UpdatePosition(Vector2 screenSpacePosition) { - base.OnMouseMove(e); + base.UpdatePosition(screenSpacePosition); if (PlacementBegun) { - var endTime = TimeAt(e.ScreenSpaceMousePosition); + var endTime = TimeAt(screenSpacePosition); HitObject.StartTime = endTime < originalStartTime ? endTime : originalStartTime; HitObject.Duration = Math.Abs(endTime - originalStartTime); @@ -65,10 +64,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints headPiece.Width = tailPiece.Width = SnappedWidth; headPiece.X = tailPiece.X = SnappedMousePosition.X; - originalStartTime = HitObject.StartTime = TimeAt(e.ScreenSpaceMousePosition); + originalStartTime = HitObject.StartTime = TimeAt(screenSpacePosition); } - - return true; } } } diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index d3779e2e18..7ad38860dd 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -62,19 +62,18 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints return base.OnMouseUp(e); } - protected override bool OnMouseMove(MouseMoveEvent e) + public override void UpdatePosition(Vector2 screenSpacePosition) { if (!PlacementBegun) - Column = ColumnAt(e.ScreenSpaceMousePosition); + Column = ColumnAt(screenSpacePosition); - if (Column == null) return false; + if (Column == null) return; SnappedWidth = Column.DrawWidth; // Snap to the column var parentPos = Parent.ToLocalSpace(Column.ToScreenSpace(new Vector2(Column.DrawWidth / 2, 0))); - SnappedMousePosition = new Vector2(parentPos.X, e.MousePosition.Y); - return true; + SnappedMousePosition = new Vector2(parentPos.X, Parent.ToLocalSpace(screenSpacePosition).Y); } protected double TimeAt(Vector2 screenSpacePosition) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs index a4050f0c31..0f6bee19bb 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs @@ -19,14 +19,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles InternalChild = new HitCirclePiece(HitObject); } - protected override void LoadComplete() - { - base.LoadComplete(); - - // Fixes a 1-frame position discrepancy due to the first mouse move event happening in the next frame - HitObject.Position = Parent?.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position) ?? Vector2.Zero; - } - protected override bool OnClick(ClickEvent e) { HitObject.StartTime = EditorClock.CurrentTime; @@ -34,10 +26,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles return true; } - protected override bool OnMouseMove(MouseMoveEvent e) + public override void UpdatePosition(Vector2 screenSpacePosition) { - HitObject.Position = e.MousePosition; - return true; + HitObject.Position = ToLocalSpace(screenSpacePosition); } } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 55de626d7d..62c879b05e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -47,28 +47,18 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders setState(PlacementState.Initial); } - protected override void LoadComplete() - { - base.LoadComplete(); - - // Fixes a 1-frame position discrepancy due to the first mouse move event happening in the next frame - HitObject.Position = Parent?.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position) ?? Vector2.Zero; - } - - protected override bool OnMouseMove(MouseMoveEvent e) + public override void UpdatePosition(Vector2 screenSpacePosition) { switch (state) { case PlacementState.Initial: - HitObject.Position = e.MousePosition; - return true; + HitObject.Position = ToLocalSpace(screenSpacePosition); + break; case PlacementState.Body: - cursor = e.MousePosition - HitObject.Position; - return true; + cursor = ToLocalSpace(screenSpacePosition) - HitObject.Position; + break; } - - return false; } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs index 03d761c67f..730b8448de 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs @@ -7,6 +7,7 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; +using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners { @@ -43,5 +44,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners return true; } + + public override void UpdatePosition(Vector2 screenSpacePosition) + { + } } } diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 757c269358..290fd8d27d 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -108,6 +108,12 @@ namespace osu.Game.Rulesets.Edit placementHandler.EndPlacement(HitObject); } + /// + /// Updates the position of this to a new screen-space position. + /// + /// The screen-space position. + public abstract void UpdatePosition(Vector2 screenSpacePosition); + /// /// Invokes , /// refreshing and parameters for the . @@ -125,7 +131,7 @@ namespace osu.Game.Rulesets.Edit case ScrollEvent _: return false; - case MouseEvent _: + case MouseButtonEvent _: return true; default: diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 7d25fd5283..d96d88c2b9 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; +using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Rulesets.Edit; @@ -22,8 +23,8 @@ namespace osu.Game.Screens.Edit.Compose.Components private Container placementBlueprintContainer; private PlacementBlueprint currentPlacement; - private SelectionHandler selectionHandler; + private InputManager inputManager; private IEnumerable selections => selectionBlueprints.Children.Where(c => c.IsAlive); @@ -66,6 +67,8 @@ namespace osu.Game.Screens.Edit.Compose.Components beatmap.HitObjectAdded += addBlueprintFor; beatmap.HitObjectRemoved += removeBlueprintFor; + + inputManager = GetContainingInputManager(); } private HitObjectCompositionTool currentTool; @@ -136,6 +139,17 @@ namespace osu.Game.Screens.Edit.Compose.Components return true; } + protected override bool OnMouseMove(MouseMoveEvent e) + { + if (currentPlacement != null) + { + currentPlacement.UpdatePosition(e.ScreenSpaceMousePosition); + return true; + } + + return base.OnMouseMove(e); + } + protected override void Update() { base.Update(); @@ -158,8 +172,14 @@ namespace osu.Game.Screens.Edit.Compose.Components currentPlacement = null; var blueprint = CurrentTool?.CreatePlacementBlueprint(); + if (blueprint != null) + { placementBlueprintContainer.Child = currentPlacement = blueprint; + + // Fixes a 1-frame position discrepancy due to the first mouse move event happening in the next frame + blueprint.UpdatePosition(inputManager.CurrentState.Mouse.Position); + } } /// From f2ba87a1d2a2f66fa423a682a0eb2ef0f7edef9c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 16:28:56 +0900 Subject: [PATCH 3255/5608] Fix placement blueprint test scenes not working --- .../Visual/PlacementBlueprintTestScene.cs | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs index 2b177e264f..0688620b8e 100644 --- a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs +++ b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs @@ -4,6 +4,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input; +using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; @@ -18,16 +20,17 @@ namespace osu.Game.Tests.Visual protected Container HitObjectContainer; private PlacementBlueprint currentBlueprint; + private InputManager inputManager; + protected PlacementBlueprintTestScene() { - Add(HitObjectContainer = CreateHitObjectContainer()); + Add(HitObjectContainer = CreateHitObjectContainer().With(c => c.Clock = new FramedClock(new StopwatchClock()))); } [BackgroundDependencyLoader] private void load() { Beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize = 2; - Add(currentBlueprint = CreateBlueprint()); } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -38,6 +41,14 @@ namespace osu.Game.Tests.Visual return dependencies; } + protected override void LoadComplete() + { + base.LoadComplete(); + + inputManager = GetContainingInputManager(); + Add(currentBlueprint = CreateBlueprint()); + } + public void BeginPlacement(HitObject hitObject) { } @@ -54,10 +65,27 @@ namespace osu.Game.Tests.Visual { } - protected virtual Container CreateHitObjectContainer() => new Container { RelativeSizeAxes = Axes.Both }; + protected override bool OnMouseMove(MouseMoveEvent e) + { + currentBlueprint.UpdatePosition(e.ScreenSpaceMousePosition); + return true; + } + + public override void Add(Drawable drawable) + { + base.Add(drawable); + + if (drawable is PlacementBlueprint blueprint) + { + blueprint.Show(); + blueprint.UpdatePosition(inputManager.CurrentState.Mouse.Position); + } + } protected virtual void AddHitObject(DrawableHitObject hitObject) => HitObjectContainer.Add(hitObject); + protected virtual Container CreateHitObjectContainer() => new Container { RelativeSizeAxes = Axes.Both }; + protected abstract DrawableHitObject CreateHitObject(HitObject hitObject); protected abstract PlacementBlueprint CreateBlueprint(); } From e9c73ce30fae825f2ed79150f3b4a098d346eb6c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 3 Oct 2019 16:21:14 +0800 Subject: [PATCH 3256/5608] Fix random failures on BeatmapCarousel filter test The "un-filter" step causes a `SelectNextRandom` invocation. If this happens to select a difficulty in set 3 other than the previously buffered difficulty #2, the subsequent test would fail. I've split this test out to remove the random element, but added a new assert to ensure buffered (previously visited?) difficulty is re-selected on return to the same set. --- .../SongSelect/TestSceneBeatmapCarousel.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 90c6c9065c..6bdd94db21 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -239,6 +239,18 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("Selection is non-null", () => currentSelection != null); setSelected(1, 3); + } + + [Test] + public void TestFilterRange() + { + loadBeatmaps(); + + // buffer the selection + setSelected(3, 2); + + setSelected(1, 3); + AddStep("Apply a range filter", () => carousel.Filter(new FilterCriteria { SearchText = "#3", @@ -249,9 +261,9 @@ namespace osu.Game.Tests.Visual.SongSelect IsLowerInclusive = true } }, false)); - waitForSelection(3, 2); - AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); + // should reselect the buffered selection. + waitForSelection(3, 2); } /// From ee34c5ccb457e582868ced659a6d0f952cb98665 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 18:21:00 +0900 Subject: [PATCH 3257/5608] Add a flip step to mania placement test scenes --- .../ManiaPlacementBlueprintTestScene.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs index 4b3786c30a..afde1c9521 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs @@ -27,8 +27,13 @@ namespace osu.Game.Rulesets.Mania.Tests [Cached(typeof(IReadOnlyList))] private IReadOnlyList mods { get; set; } = Array.Empty(); + [Cached(typeof(IScrollingInfo))] + private IScrollingInfo scrollingInfo; + protected ManiaPlacementBlueprintTestScene() { + scrollingInfo = ((ScrollingTestContainer)HitObjectContainer).ScrollingInfo; + Add(column = new Column(0) { Anchor = Anchor.Centre, @@ -36,15 +41,8 @@ namespace osu.Game.Rulesets.Mania.Tests AccentColour = Color4.OrangeRed, Clock = new FramedClock(new StopwatchClock()), // No scroll }); - } - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - - dependencies.CacheAs(((ScrollingTestContainer)HitObjectContainer).ScrollingInfo); - - return dependencies; + AddStep("change direction", () => ((ScrollingTestContainer)HitObjectContainer).Flip()); } protected override Container CreateHitObjectContainer() => new ScrollingTestContainer(ScrollingDirection.Down) { RelativeSizeAxes = Axes.Both }; From 754fbc59e1a96f2dc7da030dce850a0cb5231e78 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 18:21:36 +0900 Subject: [PATCH 3258/5608] Fix note placement being offset --- .../Edit/Blueprints/ManiaPlacementBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index d3779e2e18..f7d21ddf55 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints // If we're scrolling downwards, a position of 0 is actually further away from the hit target // so we need to flip the vertical coordinate in the hitobject container's space - var hitObjectPos = Column.HitObjectContainer.ToLocalSpace(applyPositionOffset(screenSpacePosition, false)).Y; + var hitObjectPos = applyPositionOffset(Column.HitObjectContainer.ToLocalSpace(screenSpacePosition), false).Y; if (scrollingInfo.Direction.Value == ScrollingDirection.Down) hitObjectPos = hitObjectContainer.DrawHeight - hitObjectPos; From 0a409075be251fbc1acbebfdfa80f81204d8f0a6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 18:21:50 +0900 Subject: [PATCH 3259/5608] Fix note placement offset not working for down-scroll --- .../Blueprints/ManiaPlacementBlueprint.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index f7d21ddf55..83282f9990 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -111,8 +111,23 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints private Vector2 applyPositionOffset(Vector2 position, bool reverse) { - position.Y += (scrollingInfo.Direction.Value == ScrollingDirection.Up && !reverse ? -1 : 1) * NotePiece.NOTE_HEIGHT / 2; - return position; + float offset = 0; + + switch (scrollingInfo.Direction.Value) + { + case ScrollingDirection.Up: + offset = -NotePiece.NOTE_HEIGHT / 2; + break; + + case ScrollingDirection.Down: + offset = NotePiece.NOTE_HEIGHT / 2; + break; + } + + if (reverse) + offset = -offset; + + return new Vector2(position.X, position.Y + offset); } } } From 39369620fa530000cf22dc6b1643b932b738dda1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 18:22:06 +0900 Subject: [PATCH 3260/5608] Remove position offset from ColumnAt --- .../Edit/Blueprints/ManiaPlacementBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 83282f9990..a0feecee3b 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -107,7 +107,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints } protected Column ColumnAt(Vector2 screenSpacePosition) - => composer.ColumnAt(applyPositionOffset(screenSpacePosition, false)); + => composer.ColumnAt(screenSpacePosition); private Vector2 applyPositionOffset(Vector2 position, bool reverse) { From f1ff22cf8bc1612aef947df2bdafd4e0e0d2cafd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 18:23:13 +0900 Subject: [PATCH 3261/5608] Fix hold note blueprint placing in the wrong direction --- .../Edit/Blueprints/ManiaPlacementBlueprint.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index a0feecee3b..4a187b1942 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -103,6 +103,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints scrollingInfo.TimeRange.Value, Column.HitObjectContainer.DrawHeight); + if (scrollingInfo.Direction.Value == ScrollingDirection.Down) + pos = Column.HitObjectContainer.DrawHeight - pos; + return applyPositionOffset(Column.HitObjectContainer.ToSpaceOfOtherDrawable(new Vector2(0, pos), Parent), true).Y; } From 80585d446c108268e3261933caf9ef2f3d56f1c6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 18:27:39 +0900 Subject: [PATCH 3262/5608] Split applyPositionOffset into two methods and add xmldocs --- .../Blueprints/ManiaPlacementBlueprint.cs | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 4a187b1942..e83c85b40e 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints // If we're scrolling downwards, a position of 0 is actually further away from the hit target // so we need to flip the vertical coordinate in the hitobject container's space - var hitObjectPos = applyPositionOffset(Column.HitObjectContainer.ToLocalSpace(screenSpacePosition), false).Y; + var hitObjectPos = mouseToHitObjectPosition(Column.HitObjectContainer.ToLocalSpace(screenSpacePosition)).Y; if (scrollingInfo.Direction.Value == ScrollingDirection.Down) hitObjectPos = hitObjectContainer.DrawHeight - hitObjectPos; @@ -106,31 +106,55 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints if (scrollingInfo.Direction.Value == ScrollingDirection.Down) pos = Column.HitObjectContainer.DrawHeight - pos; - return applyPositionOffset(Column.HitObjectContainer.ToSpaceOfOtherDrawable(new Vector2(0, pos), Parent), true).Y; + return hitObjectToMousePosition(Column.HitObjectContainer.ToSpaceOfOtherDrawable(new Vector2(0, pos), Parent)).Y; } protected Column ColumnAt(Vector2 screenSpacePosition) => composer.ColumnAt(screenSpacePosition); - private Vector2 applyPositionOffset(Vector2 position, bool reverse) + /// + /// Converts a mouse position to a hitobject position. + /// + /// + /// Blueprints are centred on the mouse position, such that the hitobject position is anchored at the top or bottom of the blueprint depending on the scroll direction. + /// + /// The mouse position. + /// The resulting hitobject position, acnhored at the top or bottom of the blueprint depending on the scroll direction. + private Vector2 mouseToHitObjectPosition(Vector2 mousePosition) { - float offset = 0; - switch (scrollingInfo.Direction.Value) { case ScrollingDirection.Up: - offset = -NotePiece.NOTE_HEIGHT / 2; + mousePosition.Y -= NotePiece.NOTE_HEIGHT / 2; break; case ScrollingDirection.Down: - offset = NotePiece.NOTE_HEIGHT / 2; + mousePosition.Y += NotePiece.NOTE_HEIGHT / 2; break; } - if (reverse) - offset = -offset; + return mousePosition; + } - return new Vector2(position.X, position.Y + offset); + /// + /// Converts a hitobject position to a mouse position. + /// + /// The hitobject position. + /// The resulting mouse position, anchored at the centre of the hitobject. + private Vector2 hitObjectToMousePosition(Vector2 hitObjectPosition) + { + switch (scrollingInfo.Direction.Value) + { + case ScrollingDirection.Up: + hitObjectPosition.Y += NotePiece.NOTE_HEIGHT / 2; + break; + + case ScrollingDirection.Down: + hitObjectPosition.Y -= NotePiece.NOTE_HEIGHT / 2; + break; + } + + return hitObjectPosition; } } } From 2d0c52239893526a28be0e01eacf74b18bab0ee3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 18:43:46 +0900 Subject: [PATCH 3263/5608] Remove unused method --- .../TestSceneHoldNoteSelectionBlueprint.cs | 3 --- .../TestSceneNoteSelectionBlueprint.cs | 3 --- .../TestSceneHitCircleSelectionBlueprint.cs | 3 --- .../TestSceneSliderSelectionBlueprint.cs | 3 --- .../TestSceneSpinnerSelectionBlueprint.cs | 3 --- osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs | 2 -- 6 files changed, 17 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs index 5507ca2ba0..90394f3d1b 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; @@ -53,7 +52,5 @@ namespace osu.Game.Rulesets.Mania.Tests nested.Y = (float)(-finalPosition * content.DrawHeight); } } - - protected override SelectionBlueprint CreateBlueprint() => new HoldNoteSelectionBlueprint(null); } } diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNoteSelectionBlueprint.cs index c0482e2150..1514bdf0bd 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNoteSelectionBlueprint.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; @@ -37,7 +36,5 @@ namespace osu.Game.Rulesets.Mania.Tests AddBlueprint(new NoteSelectionBlueprint(drawableObject)); } - - protected override SelectionBlueprint CreateBlueprint() => new NoteSelectionBlueprint(null); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs index 7278d923c1..d4cdabdb07 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs @@ -4,7 +4,6 @@ using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; @@ -53,8 +52,6 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("blueprint positioned over hitobject", () => blueprint.CirclePiece.Position == hitCircle.Position); } - protected override SelectionBlueprint CreateBlueprint() => new HitCircleSelectionBlueprint(drawableObject); - private class TestBlueprint : HitCircleSelectionBlueprint { public new HitCirclePiece CirclePiece => base.CirclePiece; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs index 61c8316ed9..ec23ec31b2 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs @@ -7,7 +7,6 @@ using NUnit.Framework; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; @@ -98,8 +97,6 @@ namespace osu.Game.Rulesets.Osu.Tests () => Precision.AlmostEquals(blueprint.TailBlueprint.CirclePiece.ScreenSpaceDrawQuad.Centre, drawableObject.TailCircle.ScreenSpaceDrawQuad.Centre)); } - protected override SelectionBlueprint CreateBlueprint() => new SliderSelectionBlueprint(drawableObject); - private class TestSliderBlueprint : SliderSelectionBlueprint { public new SliderBodyPiece BodyPiece => base.BodyPiece; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerSelectionBlueprint.cs index 1c195311a4..d777ca3610 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerSelectionBlueprint.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners; using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components; using osu.Game.Rulesets.Osu.Objects; @@ -47,7 +46,5 @@ namespace osu.Game.Rulesets.Osu.Tests AddBlueprint(new SpinnerSelectionBlueprint(drawableSpinner) { Size = new Vector2(0.5f) }); } - - protected override SelectionBlueprint CreateBlueprint() => new SpinnerSelectionBlueprint(null) { Size = new Vector2(0.5f) }; } } diff --git a/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs index 55dda03b16..f53c12b047 100644 --- a/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs +++ b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs @@ -30,7 +30,5 @@ namespace osu.Game.Tests.Visual d.Select(); })); } - - protected abstract SelectionBlueprint CreateBlueprint(); } } From bcf0b2752e75f40b046e6447cbfce2b705dfb0ce Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 18:48:44 +0900 Subject: [PATCH 3264/5608] Fix possible MusicController nullref --- osu.Game/Overlays/MusicController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 49d16a4f3e..51afac4b8c 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays /// /// Returns whether the current beatmap track is playing. /// - public bool IsPlaying => beatmap.Value?.Track.IsRunning ?? false; + public bool IsPlaying => beatmap?.Value?.Track.IsRunning ?? false; private void handleBeatmapAdded(BeatmapSetInfo set) => Schedule(() => beatmapSets.Add(set)); From 662a1a9c2cb8af2b6e151a9b1bed43d32491ca3b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 18:55:53 +0900 Subject: [PATCH 3265/5608] Use current --- osu.Game/Overlays/MusicController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 51afac4b8c..f5c36a9cac 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays /// /// Returns whether the current beatmap track is playing. /// - public bool IsPlaying => beatmap?.Value?.Track.IsRunning ?? false; + public bool IsPlaying => current?.Track.IsRunning ?? false; private void handleBeatmapAdded(BeatmapSetInfo set) => Schedule(() => beatmapSets.Add(set)); From 6c878cb167544addc3a6af83efad12558a7b230d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 19:11:50 +0900 Subject: [PATCH 3266/5608] Prevent nullrefs --- osu.Game/Overlays/VolumeOverlay.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index 0c08e0eb6e..27e2eef200 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -32,7 +32,8 @@ namespace osu.Game.Overlays private readonly BindableDouble muteAdjustment = new BindableDouble(); - public Bindable IsMuted => muteButton.Current; + private readonly Bindable isMuted = new Bindable(); + public Bindable IsMuted => isMuted; [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colours) @@ -66,7 +67,8 @@ namespace osu.Game.Overlays volumeMeterMusic = new VolumeMeter("MUSIC", 125, colours.BlueDarker), muteButton = new MuteButton { - Margin = new MarginPadding { Top = 100 } + Margin = new MarginPadding { Top = 100 }, + Current = { BindTarget = isMuted } } } }, @@ -76,13 +78,13 @@ namespace osu.Game.Overlays volumeMeterEffect.Bindable.BindTo(audio.VolumeSample); volumeMeterMusic.Bindable.BindTo(audio.VolumeTrack); - muteButton.Current.ValueChanged += muted => + isMuted.BindValueChanged(muted => { if (muted.NewValue) audio.AddAdjustment(AdjustableProperty.Volume, muteAdjustment); else audio.RemoveAdjustment(AdjustableProperty.Volume, muteAdjustment); - }; + }); } protected override void LoadComplete() From 636913a4a6a62319f23f3b17f52552bfa3905409 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Oct 2019 19:16:31 +0900 Subject: [PATCH 3267/5608] Refactor PlayerLoader changes --- osu.Game/Screens/Play/PlayerLoader.cs | 63 ++++++++++++--------------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index cd4b331fce..87d902b547 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -58,9 +58,19 @@ namespace osu.Game.Screens.Play private Task loadTask; private InputManager inputManager; - private IdleTracker idleTracker; + [Resolved(CanBeNull = true)] + private NotificationOverlay notificationOverlay { get; set; } + + [Resolved(CanBeNull = true)] + private VolumeOverlay volumeOverlay { get; set; } + + [Resolved] + private AudioManager audioManager { get; set; } + + private Bindable muteWarningShownOnce; + public PlayerLoader(Func createPlayer) { this.createPlayer = createPlayer; @@ -110,7 +120,22 @@ namespace osu.Game.Screens.Play loadNewPlayer(); } - private void playerLoaded(Player player) => info.Loading = false; + protected override void LoadComplete() + { + base.LoadComplete(); + + inputManager = GetContainingInputManager(); + + if (!muteWarningShownOnce.Value) + { + //Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. + if (volumeOverlay?.IsMuted.Value == true || audioManager.Volume.Value <= audioManager.Volume.MinValue || audioManager.VolumeTrack.Value <= audioManager.VolumeTrack.MinValue) + { + notificationOverlay?.Post(new MutedNotification()); + muteWarningShownOnce.Value = true; + } + } + } public override void OnResuming(IScreen last) { @@ -134,7 +159,7 @@ namespace osu.Game.Screens.Play player.RestartCount = restartCount; player.RestartRequested = restartRequested; - loadTask = LoadComponentAsync(player, playerLoaded); + loadTask = LoadComponentAsync(player, _ => info.Loading = false); } private void contentIn() @@ -152,30 +177,6 @@ namespace osu.Game.Screens.Play content.FadeOut(250); } - [Resolved(CanBeNull = true)] - private NotificationOverlay notificationOverlay { get; set; } - - [Resolved(CanBeNull = true)] - private VolumeOverlay volumeOverlay { get; set; } - - [Resolved] - private AudioManager audioManager { get; set; } - - private Bindable muteWarningShownOnce; - - private void checkVolume() - { - if (muteWarningShownOnce.Value) - return; - - //Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. - if (volumeOverlay?.IsMuted.Value == true || audioManager.Volume.Value <= audioManager.Volume.MinValue || audioManager.VolumeTrack.Value <= audioManager.VolumeTrack.MinValue) - { - notificationOverlay?.Post(new MutedNotification()); - muteWarningShownOnce.Value = true; - } - } - public override void OnEntering(IScreen last) { base.OnEntering(last); @@ -216,14 +217,6 @@ namespace osu.Game.Screens.Play content.StopTracking(); } - protected override void LoadComplete() - { - inputManager = GetContainingInputManager(); - base.LoadComplete(); - - checkVolume(); - } - private ScheduledDelegate pushDebounce; protected VisualSettings VisualSettings; From d2c9a29c0d4bf8f805dbead933156a57ea466d75 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Oct 2019 10:45:18 +0800 Subject: [PATCH 3268/5608] Remove unnecessary local assign --- osu.Game/Screens/Select/SongSelect.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 5ab49fa2b9..e97fac96c5 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -66,11 +66,7 @@ namespace osu.Game.Screens.Select /// protected readonly Container FooterPanels; - protected override BackgroundScreen CreateBackground() - { - var background = new BackgroundScreenBeatmap(); - return background; - } + protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(); protected readonly BeatmapCarousel Carousel; private readonly BeatmapInfoWedge beatmapInfoWedge; From 925615320e4d8ae455738b5dc3fa1de8a170f71f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Oct 2019 10:46:48 +0800 Subject: [PATCH 3269/5608] Update lazer default combo colours to match stable --- osu.Game/Skinning/DefaultSkinConfiguration.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Skinning/DefaultSkinConfiguration.cs b/osu.Game/Skinning/DefaultSkinConfiguration.cs index f52fac6077..cd5975edac 100644 --- a/osu.Game/Skinning/DefaultSkinConfiguration.cs +++ b/osu.Game/Skinning/DefaultSkinConfiguration.cs @@ -14,10 +14,10 @@ namespace osu.Game.Skinning { ComboColours.AddRange(new[] { - new Color4(17, 136, 170, 255), - new Color4(102, 136, 0, 255), - new Color4(204, 102, 0, 255), - new Color4(121, 9, 13, 255) + new Color4(255, 192, 0, 255), + new Color4(0, 202, 0, 255), + new Color4(18, 124, 255, 255), + new Color4(242, 24, 57, 255), }); } } From 71985c7ef13913af2d3c6acf07c17ac4d11986c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Oct 2019 11:23:42 +0800 Subject: [PATCH 3270/5608] Update fail logic to match --- osu.Game/Screens/Play/Player.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 91d34c8056..5560baa7d1 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -299,6 +299,12 @@ namespace osu.Game.Screens.Play { if (!this.IsCurrentScreen()) return; + if (HasFailed && !FailOverlay.IsPresent) + { + failAnimation.FinishTransforms(true); + return; + } + if (canPause) Pause(); else @@ -517,12 +523,6 @@ namespace osu.Game.Screens.Play if (pauseCooldownActive && !GameplayClockContainer.IsPaused.Value) // still want to block if we are within the cooldown period and not already paused. return true; - - if (HasFailed && !FailOverlay.IsPresent) - { - failAnimation.FinishTransforms(true); - return true; - } } GameplayClockContainer.ResetLocalAdjustments(); From e646b2677ca0b07267690783cf8894676e437dc4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Oct 2019 11:25:23 +0800 Subject: [PATCH 3271/5608] Add test coverage --- osu.Game.Tests/Visual/Gameplay/TestScenePause.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index c67001c3d8..48159aa5e0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -127,6 +127,15 @@ namespace osu.Game.Tests.Visual.Gameplay exitAndConfirm(); } + [Test] + public void TestExitFromFailedGameplay() + { + AddUntilStep("wait for fail", () => Player.HasFailed); + AddStep("exit", () => Player.Exit()); + + confirmExited(); + } + [Test] public void TestExitFromGameplay() { From 47c1f36f9d91f54eb68b824badad248b69c169be Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Oct 2019 11:41:53 +0800 Subject: [PATCH 3272/5608] Add ValidForResume check --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 5560baa7d1..0b363eac4d 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -299,7 +299,7 @@ namespace osu.Game.Screens.Play { if (!this.IsCurrentScreen()) return; - if (HasFailed && !FailOverlay.IsPresent) + if (ValidForResume && HasFailed && !FailOverlay.IsPresent) { failAnimation.FinishTransforms(true); return; From 626f7388c8fdc8dd34935d2a8cf86cfaf702ac4a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Oct 2019 12:23:01 +0800 Subject: [PATCH 3273/5608] Add tests for quick retry and quick exit scenarios --- .../Visual/Gameplay/TestScenePause.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 48159aa5e0..2df22df659 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -136,6 +136,24 @@ namespace osu.Game.Tests.Visual.Gameplay confirmExited(); } + [Test] + public void TestQuickRetryFromFailedGameplay() + { + AddUntilStep("wait for fail", () => Player.HasFailed); + AddStep("quick retry", () => Player.GameplayClockContainer.OfType().First().Action?.Invoke()); + + confirmExited(); + } + + [Test] + public void TestQuickExitFromFailedGameplay() + { + AddUntilStep("wait for fail", () => Player.HasFailed); + AddStep("quick exit", () => Player.GameplayClockContainer.OfType().First().Action?.Invoke()); + + confirmExited(); + } + [Test] public void TestExitFromGameplay() { @@ -144,6 +162,14 @@ namespace osu.Game.Tests.Visual.Gameplay confirmExited(); } + [Test] + public void TestQuickExitFromGameplay() + { + AddStep("quick exit", () => Player.GameplayClockContainer.OfType().First().Action?.Invoke()); + + confirmExited(); + } + [Test] public void TestExitViaHoldToExit() { From ffde389641a15f0b0faceb8e1e900fa186509bda Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 4 Oct 2019 13:28:32 +0900 Subject: [PATCH 3274/5608] Add difficulty calculator beatmap decoder fallback --- .../Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs index 2c493254e0..238187bf8f 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs @@ -24,6 +24,7 @@ namespace osu.Game.Beatmaps.Formats public new static void Register() { AddDecoder(@"osu file format v", m => new LegacyDifficultyCalculatorBeatmapDecoder(int.Parse(m.Split('v').Last()))); + SetFallbackDecoder(() => new LegacyDifficultyCalculatorBeatmapDecoder()); } protected override TimingControlPoint CreateTimingControlPoint() From ddef7fa3ba67d47ff90d62446d7ed5bbf294c46d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Oct 2019 13:32:47 +0800 Subject: [PATCH 3275/5608] Repair behavioural change --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 74d3439c59..c6d812aee3 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -157,7 +157,7 @@ namespace osu.Game.Rulesets.UI return; } - manualClock.CurrentTime = newTime.Value; + newProposedTime = newTime.Value; } requireMoreUpdateLoops = manualClock.CurrentTime != parentGameplayClock.CurrentTime; From aeb62825cdb0c0727fca76b6ae21541133aeb1e8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Oct 2019 13:42:06 +0800 Subject: [PATCH 3276/5608] Move out requireMoreUpdateLoops for better consistency --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index c6d812aee3..e569bb8459 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -115,17 +115,16 @@ namespace osu.Game.Rulesets.UI setClock(); // LoadComplete may not be run yet, but we still want the clock. validState = true; + requireMoreUpdateLoops = false; var newProposedTime = parentGameplayClock.CurrentTime; try { if (!FrameStablePlayback) - { - requireMoreUpdateLoops = false; return; - } - else if (firstConsumption) + + if (firstConsumption) { // On the first update, frame-stability seeking would result in unexpected/unwanted behaviour. // Instead we perform an initial seek to the proposed time. @@ -159,8 +158,6 @@ namespace osu.Game.Rulesets.UI newProposedTime = newTime.Value; } - - requireMoreUpdateLoops = manualClock.CurrentTime != parentGameplayClock.CurrentTime; } finally { @@ -171,6 +168,8 @@ namespace osu.Game.Rulesets.UI manualClock.Rate = Math.Abs(parentGameplayClock.Rate) * direction; manualClock.IsRunning = parentGameplayClock.IsRunning; + requireMoreUpdateLoops |= manualClock.CurrentTime != parentGameplayClock.CurrentTime; + // The manual clock time has changed in the above code. The framed clock now needs to be updated // to ensure that the its time is valid for our children before input is processed framedClock.ProcessFrame(); From 7b414092afd261c953fd9f51f9bdf93632021523 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 4 Oct 2019 17:35:41 +0300 Subject: [PATCH 3277/5608] Implement beatmap ruleset selector --- .../BeatmapSet/BeatmapRulesetSelector.cs | 50 ++++++ .../BeatmapSet/BeatmapRulesetTabItem.cs | 148 ++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs create mode 100644 osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs new file mode 100644 index 0000000000..0847272e1f --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs @@ -0,0 +1,50 @@ +// 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.UserInterface; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osuTK; +using System.Linq; + +namespace osu.Game.Overlays.BeatmapSet +{ + public class BeatmapRulesetSelector : RulesetSelector + { + private BeatmapSetInfo beatmapSet; + + public BeatmapSetInfo BeatmapSet + { + get => beatmapSet; + set + { + if (value == beatmapSet) + return; + + beatmapSet = value; + + foreach (BeatmapRulesetTabItem tab in TabContainer.TabItems) + tab.SetBeatmaps(beatmapSet?.Beatmaps.FindAll(b => b.Ruleset.Equals(tab.Value))); + + var firstRuleset = beatmapSet?.Beatmaps.OrderBy(b => b.Ruleset.ID).FirstOrDefault()?.Ruleset; + SelectTab(TabContainer.TabItems.FirstOrDefault(t => t.Value.Equals(firstRuleset))); + } + } + + public BeatmapRulesetSelector() + { + AutoSizeAxes = Axes.Both; + TabContainer.Spacing = new Vector2(10, 0); + } + + protected override TabItem CreateTabItem(RulesetInfo value) => new BeatmapRulesetTabItem(value); + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + }; + } +} diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs new file mode 100644 index 0000000000..19c9af13d5 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.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 osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets; +using osuTK; +using osuTK.Graphics; +using System.Collections.Generic; +using System.Diagnostics; + +namespace osu.Game.Overlays.BeatmapSet +{ + public class BeatmapRulesetTabItem : TabItem + { + private readonly OsuSpriteText name, count; + private readonly Box bar; + + public override bool PropagatePositionalInputSubTree => Enabled.Value && !Active.Value && base.PropagatePositionalInputSubTree; + + public BeatmapRulesetTabItem(RulesetInfo value) + : base(value) + { + AutoSizeAxes = Axes.Both; + Masking = true; + + FillFlowContainer nameContainer; + + Children = new Drawable[] + { + nameContainer = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding { Bottom = 7.5f }, + Spacing = new Vector2(2.5f), + Children = new Drawable[] + { + name = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = value.Name, + Font = OsuFont.Default.With(size: 18), + }, + new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 4f, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0.5f), + }, + count = new OsuSpriteText + { + Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Horizontal = 5f }, + Font = OsuFont.Default.With(weight: FontWeight.SemiBold), + } + } + } + } + }, + bar = new Box + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + Height = 4f, + }, + new HoverClickSounds(), + }; + + Enabled.BindValueChanged(v => nameContainer.Alpha = v.NewValue ? 1f : 0.5f, true); + } + + [Resolved] + private OsuColour colour { get; set; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + count.Colour = colour.Gray9; + bar.Colour = colour.Blue; + + updateState(); + } + + public void SetBeatmaps(List beatmaps) + { + Trace.Assert(beatmaps?.TrueForAll(b => b.Ruleset.Equals(Value)) ?? true, "A beatmap has a ruleset not of this tab value"); + + count.Text = beatmaps?.Count.ToString(); + + var hasBeatmaps = (beatmaps?.Count ?? 0) > 0; + count.Alpha = hasBeatmaps ? 1f : 0f; + Enabled.Value = hasBeatmaps; + } + + private void updateState() + { + var isHoveredOrActive = IsHovered || Active.Value; + name.Colour = isHoveredOrActive ? colour.GrayE : colour.GrayC; + bar.MoveToY(isHoveredOrActive ? 0f : bar.Height, 120); + + name.Font = name.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Regular); + } + + #region Hovering and activation logic + + protected override void OnActivated() => updateState(); + + protected override void OnDeactivated() => updateState(); + + protected override bool OnHover(HoverEvent e) + { + updateState(); + return false; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateState(); + } + + #endregion + } +} From edddbdb7845a250002ee5dd111750b3290a29401 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 4 Oct 2019 17:37:09 +0300 Subject: [PATCH 3278/5608] Add tests for beatmap ruleset selector --- .../Online/TestSceneBeatmapRulesetSelector.cs | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs new file mode 100644 index 0000000000..1f8df438fb --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.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 NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Beatmaps; +using osu.Game.Overlays.BeatmapSet; +using osu.Game.Rulesets; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneBeatmapRulesetSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(BeatmapRulesetSelector), + typeof(BeatmapRulesetTabItem), + }; + + private readonly TestRulesetSelector selector; + + public TestSceneBeatmapRulesetSelector() + { + Add(selector = new TestRulesetSelector()); + } + + [Resolved] + private RulesetStore rulesets { get; set; } + + [Test] + public void TestMultipleRulesetsBeatmapSet() + { + var enabledRulesets = rulesets.AvailableRulesets.Skip(1).Take(2); + + AddStep("load multiple rulesets beatmapset", () => + { + selector.BeatmapSet = new BeatmapSetInfo + { + Beatmaps = enabledRulesets.Select(r => new BeatmapInfo { Ruleset = r }).ToList() + }; + }); + + var tabItems = selector.TabContainer.TabItems; + AddAssert("other rulesets disabled", () => tabItems.Except(tabItems.Where(t => enabledRulesets.Any(r => r.Equals(t.Value)))).All(t => !t.Enabled.Value)); + AddAssert("left-most ruleset selected", () => tabItems.First(t => t.Enabled.Value).Active.Value); + } + + [Test] + public void TestSingleRulesetBeatmapSet() + { + var enabledRuleset = rulesets.AvailableRulesets.Last(); + + AddStep("load single ruleset beatmapset", () => + { + selector.BeatmapSet = new BeatmapSetInfo + { + Beatmaps = new List + { + new BeatmapInfo + { + Ruleset = enabledRuleset + } + } + }; + }); + + AddAssert("single ruleset selected", () => selector.SelectedTab.Value.Equals(enabledRuleset)); + } + + [Test] + public void TestEmptyBeatmapSet() + { + AddStep("load empty beatmapset", () => selector.BeatmapSet = new BeatmapSetInfo + { + Beatmaps = new List() + }); + + AddAssert("no ruleset selected", () => selector.SelectedTab == null); + AddAssert("all rulesets disabled", () => selector.TabContainer.TabItems.All(t => !t.Enabled.Value)); + } + + [Test] + public void TestNullBeatmapSet() + { + AddStep("load null beatmapset", () => selector.BeatmapSet = null); + + AddAssert("no ruleset selected", () => selector.SelectedTab == null); + AddAssert("all rulesets disabled", () => selector.TabContainer.TabItems.All(t => !t.Enabled.Value)); + } + + private class TestRulesetSelector : BeatmapRulesetSelector + { + public new TabItem SelectedTab => base.SelectedTab; + + public new TabFillFlowContainer TabContainer => base.TabContainer; + } + } +} From 7d5f5d2fd9272e207bc26860e76f613ce01e38ec Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 4 Oct 2019 17:55:33 +0300 Subject: [PATCH 3279/5608] Add ruleset selector to the beatmap overlay header --- osu.Game/Overlays/BeatmapSet/Header.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 260a989628..0e3d29c25b 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -3,6 +3,7 @@ using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -16,6 +17,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online; using osu.Game.Overlays.BeatmapSet.Buttons; using osu.Game.Overlays.Direct; +using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; @@ -39,6 +41,7 @@ namespace osu.Game.Overlays.BeatmapSet public bool DownloadButtonsVisible => downloadButtonsContainer.Any(); + public readonly BeatmapRulesetSelector RulesetSelector; public readonly BeatmapPicker Picker; private readonly FavouriteButton favouriteButton; @@ -69,12 +72,17 @@ namespace osu.Game.Overlays.BeatmapSet { RelativeSizeAxes = Axes.X, Height = tabs_height, - Children = new[] + Children = new Drawable[] { tabsBg = new Box { RelativeSizeAxes = Axes.Both, }, + RulesetSelector = new BeatmapRulesetSelector + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + } }, }, new Container @@ -214,6 +222,13 @@ namespace osu.Game.Overlays.BeatmapSet }; } + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.CacheAs>(RulesetSelector.Current); + return dependencies; + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -223,7 +238,7 @@ namespace osu.Game.Overlays.BeatmapSet BeatmapSet.BindValueChanged(setInfo => { - Picker.BeatmapSet = author.BeatmapSet = beatmapAvailability.BeatmapSet = Details.BeatmapSet = setInfo.NewValue; + Picker.BeatmapSet = RulesetSelector.BeatmapSet = author.BeatmapSet = beatmapAvailability.BeatmapSet = Details.BeatmapSet = setInfo.NewValue; cover.BeatmapSet = setInfo.NewValue; if (setInfo.NewValue == null) From 555c82e9c9077f8e363aebb12e73ff07127aa97f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 4 Oct 2019 17:56:42 +0300 Subject: [PATCH 3280/5608] Filter beatmap difficulties by current ruleset --- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 28947b6f22..e7a3d15401 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -17,6 +17,7 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; @@ -27,10 +28,11 @@ namespace osu.Game.Overlays.BeatmapSet private const float tile_icon_padding = 7; private const float tile_spacing = 2; - private readonly DifficultiesContainer difficulties; private readonly OsuSpriteText version, starRating; private readonly Statistic plays, favourites; + public readonly DifficultiesContainer Difficulties; + public readonly Bindable Beatmap = new Bindable(); private BeatmapSetInfo beatmapSet; @@ -50,11 +52,11 @@ namespace osu.Game.Overlays.BeatmapSet private void updateDisplay() { - difficulties.Clear(); + Difficulties.Clear(); if (BeatmapSet != null) { - difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty).Select(b => new DifficultySelectorButton(b) + Difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.FindAll(b => b.Ruleset.Equals(ruleset.Value)).OrderBy(b => b.StarDifficulty).Select(b => new DifficultySelectorButton(b) { State = DifficultySelectorState.NotSelected, OnHovered = beatmap => @@ -68,7 +70,7 @@ namespace osu.Game.Overlays.BeatmapSet } starRating.FadeOut(100); - Beatmap.Value = BeatmapSet?.Beatmaps.FirstOrDefault(); + Beatmap.Value = Difficulties.FirstOrDefault()?.Beatmap; plays.Value = BeatmapSet?.OnlineInfo.PlayCount ?? 0; favourites.Value = BeatmapSet?.OnlineInfo.FavouriteCount ?? 0; @@ -89,7 +91,7 @@ namespace osu.Game.Overlays.BeatmapSet Direction = FillDirection.Vertical, Children = new Drawable[] { - difficulties = new DifficultiesContainer + Difficulties = new DifficultiesContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -147,6 +149,9 @@ namespace osu.Game.Overlays.BeatmapSet }; } + [Resolved] + private IBindable ruleset { get; set; } + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -158,6 +163,8 @@ namespace osu.Game.Overlays.BeatmapSet { base.LoadComplete(); + ruleset.ValueChanged += r => updateDisplay(); + // done here so everything can bind in intialization and get the first trigger Beatmap.TriggerChange(); } @@ -169,10 +176,10 @@ namespace osu.Game.Overlays.BeatmapSet private void updateDifficultyButtons() { - difficulties.Children.ToList().ForEach(diff => diff.State = diff.Beatmap == Beatmap.Value ? DifficultySelectorState.Selected : DifficultySelectorState.NotSelected); + Difficulties.Children.ToList().ForEach(diff => diff.State = diff.Beatmap == Beatmap.Value ? DifficultySelectorState.Selected : DifficultySelectorState.NotSelected); } - private class DifficultiesContainer : FillFlowContainer + public class DifficultiesContainer : FillFlowContainer { public Action OnLostHover; @@ -183,7 +190,7 @@ namespace osu.Game.Overlays.BeatmapSet } } - private class DifficultySelectorButton : OsuClickableContainer, IStateful + public class DifficultySelectorButton : OsuClickableContainer, IStateful { private const float transition_duration = 100; private const float size = 52; @@ -320,7 +327,7 @@ namespace osu.Game.Overlays.BeatmapSet } } - private enum DifficultySelectorState + public enum DifficultySelectorState { Selected, NotSelected, From 4f40a044258b392f8c0d42a672d5d492ab11779e Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 4 Oct 2019 17:57:39 +0300 Subject: [PATCH 3281/5608] Add tests ensuring correct behaviour with ruleset selection --- .../Online/TestSceneBeatmapSetOverlay.cs | 70 +++++++++++++++---- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 9f03d947b9..6c7a3e4108 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapSet; @@ -40,24 +41,19 @@ namespace osu.Game.Tests.Visual.Online typeof(PreviewButton), typeof(SuccessRate), typeof(BeatmapAvailability), + typeof(BeatmapRulesetSelector), + typeof(BeatmapRulesetTabItem), }; protected override bool UseOnlineAPI => true; - private RulesetInfo taikoRuleset; - private RulesetInfo maniaRuleset; - public TestSceneBeatmapSetOverlay() { Add(overlay = new TestBeatmapSetOverlay()); } - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) - { - taikoRuleset = rulesets.GetRuleset(1); - maniaRuleset = rulesets.GetRuleset(3); - } + [Resolved] + private RulesetStore rulesets { get; set; } [Test] public void TestLoading() @@ -111,7 +107,7 @@ namespace osu.Game.Tests.Visual.Online StarDifficulty = 9.99, Version = @"TEST", Length = 456000, - Ruleset = maniaRuleset, + Ruleset = rulesets.GetRuleset(3), BaseDifficulty = new BeatmapDifficulty { CircleSize = 1, @@ -189,7 +185,7 @@ namespace osu.Game.Tests.Visual.Online StarDifficulty = 5.67, Version = @"ANOTHER TEST", Length = 123000, - Ruleset = taikoRuleset, + Ruleset = rulesets.GetRuleset(1), BaseDifficulty = new BeatmapDifficulty { CircleSize = 9, @@ -217,6 +213,54 @@ namespace osu.Game.Tests.Visual.Online downloadAssert(false); } + [Test] + public void TestMultipleRulesets() + { + AddStep("show multiple rulesets beatmap", () => + { + var beatmaps = new List(); + + foreach (var ruleset in rulesets.AvailableRulesets.Skip(1)) + { + beatmaps.Add(new BeatmapInfo + { + Version = ruleset.Name, + Ruleset = ruleset, + BaseDifficulty = new BeatmapDifficulty(), + OnlineInfo = new BeatmapOnlineInfo(), + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + }, + }); + } + + overlay.ShowBeatmapSet(new BeatmapSetInfo + { + Metadata = new BeatmapMetadata + { + Title = @"multiple rulesets beatmap", + Artist = @"none", + Author = new User + { + Username = "BanchoBot", + Id = 3, + } + }, + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers(), + }, + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, + Beatmaps = beatmaps + }); + }); + + AddAssert("shown beatmaps of current ruleset", () => overlay.Header.Picker.Difficulties.All(b => b.Beatmap.Ruleset.Equals(overlay.Header.RulesetSelector.Current.Value))); + AddAssert("left-most beatmap selected", () => overlay.Header.Picker.Difficulties.First().State == BeatmapPicker.DifficultySelectorState.Selected); + } + [Test] public void TestHide() { @@ -281,12 +325,12 @@ namespace osu.Game.Tests.Visual.Online private void downloadAssert(bool shown) { - AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.DownloadButtonsVisible == shown); + AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.Header.DownloadButtonsVisible == shown); } private class TestBeatmapSetOverlay : BeatmapSetOverlay { - public bool DownloadButtonsVisible => Header.DownloadButtonsVisible; + public new Header Header => base.Header; } } } From 76c74719a44f2aa461cebf93cd2b71e476663632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 4 Oct 2019 17:00:51 +0200 Subject: [PATCH 3282/5608] Add test for fallback decoder overwrite LegacyDifficultyCalculatorBeatmapDecoder was registered as a fallback decoder in commit ffde389 for future use in the server-side difficulty calculation components. Due to the pre-existing fallback registrations this causes a runtime crash when the diffcalc components are started. Add a test reproducing this scenario to prevent the issue from resurfacing in the future. --- .../Formats/LegacyBeatmapDecoderTest.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index f6c0dbbecf..de516d3142 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -591,5 +591,27 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.Throws(() => Decoder.GetDecoder(stream)); } } + + [Test] + public void TestAllowFallbackDecoderOverwrite() + { + Decoder decoder = null; + + using (var resStream = TestResources.OpenResource("corrupted-header.osu")) + using (var stream = new LineBufferedReader(resStream)) + { + Assert.DoesNotThrow(() => decoder = Decoder.GetDecoder(stream)); + Assert.IsInstanceOf(decoder); + } + + Assert.DoesNotThrow(LegacyDifficultyCalculatorBeatmapDecoder.Register); + + using (var resStream = TestResources.OpenResource("corrupted-header.osu")) + using (var stream = new LineBufferedReader(resStream)) + { + Assert.DoesNotThrow(() => decoder = Decoder.GetDecoder(stream)); + Assert.IsInstanceOf(decoder); + } + } } } From 0c4f24825969c64775705b8feb9297af2f4fc9ac Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 4 Oct 2019 18:02:13 +0300 Subject: [PATCH 3283/5608] Fix CI issues --- osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs index 0847272e1f..1abe103fc8 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs @@ -25,7 +25,7 @@ namespace osu.Game.Overlays.BeatmapSet beatmapSet = value; - foreach (BeatmapRulesetTabItem tab in TabContainer.TabItems) + foreach (var tab in TabContainer.TabItems.OfType()) tab.SetBeatmaps(beatmapSet?.Beatmaps.FindAll(b => b.Ruleset.Equals(tab.Value))); var firstRuleset = beatmapSet?.Beatmaps.OrderBy(b => b.Ruleset.ID).FirstOrDefault()?.Ruleset; From 7c2c537bc9cca82740ea9df51f65c3f8047de372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 4 Oct 2019 17:23:33 +0200 Subject: [PATCH 3284/5608] Allow fallback decoder overwrite To fix the runtime crashes in difficulty calculation components, remove the check for pre-existing fallback registration along with the exception. The xmldoc for the registration function has been extended to make users aware of possible consequences of calling it. --- osu.Game/Beatmaps/Formats/Decoder.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs index 045eb2d14d..40c329eb7e 100644 --- a/osu.Game/Beatmaps/Formats/Decoder.cs +++ b/osu.Game/Beatmaps/Formats/Decoder.cs @@ -93,14 +93,12 @@ namespace osu.Game.Beatmaps.Formats /// /// Registers a fallback decoder instantiation function. /// The fallback will be returned if the first non-empty line of the decoded stream does not match any known magic. + /// Calling this method will overwrite any existing global fallback registration for type - use with caution. /// /// Type of object being decoded. /// A function that constructs the fallback. protected static void SetFallbackDecoder(Func constructor) { - if (fallback_decoders.ContainsKey(typeof(T))) - throw new InvalidOperationException($"A fallback decoder was already added for type {typeof(T)}."); - fallback_decoders[typeof(T)] = constructor; } } From 6985249d90e63e8e18ca92dd31c056eed82f35af Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 4 Oct 2019 21:18:03 +0300 Subject: [PATCH 3285/5608] Simplify properties --- osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs index 1abe103fc8..bfb188a83b 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs @@ -36,15 +36,15 @@ namespace osu.Game.Overlays.BeatmapSet public BeatmapRulesetSelector() { AutoSizeAxes = Axes.Both; - TabContainer.Spacing = new Vector2(10, 0); } protected override TabItem CreateTabItem(RulesetInfo value) => new BeatmapRulesetTabItem(value); protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer { - Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), }; } } From e7ba6ef5c43fcf1c55d93a86cb0773ea4d8070f2 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 4 Oct 2019 14:32:43 -0700 Subject: [PATCH 3286/5608] Fix keybinding order of beatmap options --- osu.Game/Screens/Select/PlaySongSelect.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 4df6e6a3f3..9368bac69f 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Select { ValidForResume = false; Edit(); - }, Key.Number3); + }, Key.Number4); } public override void OnResuming(IScreen last) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 452c63a18c..ee2e40dcd9 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -230,9 +230,9 @@ namespace osu.Game.Screens.Select Footer.AddButton(new FooterButtonRandom { Action = triggerRandom }); Footer.AddButton(new FooterButtonOptions(), BeatmapOptions); - BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo), Key.Number4, float.MaxValue); - BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, colours.Purple, null, Key.Number1); - BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.Solid.Eraser, colours.Purple, () => clearScores(Beatmap.Value.BeatmapInfo), Key.Number2); + BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo), Key.Number1, float.MaxValue); + BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, colours.Purple, null, Key.Number2); + BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.Solid.Eraser, colours.Purple, () => clearScores(Beatmap.Value.BeatmapInfo), Key.Number3); } if (this.beatmaps == null) From 5d460eaf6b8a9c05d54c61f2cd01cfddb2636386 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 4 Oct 2019 17:14:19 -0700 Subject: [PATCH 3287/5608] Remove depth specification and button order regression --- osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs | 5 ++--- osu.Game/Screens/Select/SongSelect.cs | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs index ede526f9da..b831ae274c 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs @@ -93,7 +93,7 @@ namespace osu.Game.Screens.Select.Options /// Lower depth to be put on the left, and higher to be put on the right. /// Notice this is different to ! /// - public void AddButton(string firstLine, string secondLine, IconUsage icon, Color4 colour, Action action, Key? hotkey = null, float depth = 0) + public void AddButton(string firstLine, string secondLine, IconUsage icon, Color4 colour, Action action, Key? hotkey = null) { var button = new BeatmapOptionsButton { @@ -101,7 +101,6 @@ namespace osu.Game.Screens.Select.Options SecondLineText = secondLine, Icon = icon, ButtonColour = colour, - Depth = depth, Action = () => { Hide(); @@ -110,7 +109,7 @@ namespace osu.Game.Screens.Select.Options HotKey = hotkey }; - buttonsContainer.Insert((int)depth, button); + buttonsContainer.Add(button); } } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index ee2e40dcd9..59a143728c 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -230,9 +230,9 @@ namespace osu.Game.Screens.Select Footer.AddButton(new FooterButtonRandom { Action = triggerRandom }); Footer.AddButton(new FooterButtonOptions(), BeatmapOptions); - BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo), Key.Number1, float.MaxValue); - BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, colours.Purple, null, Key.Number2); - BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.Solid.Eraser, colours.Purple, () => clearScores(Beatmap.Value.BeatmapInfo), Key.Number3); + BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, colours.Purple, null, Key.Number1); + BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.Solid.Eraser, colours.Purple, () => clearScores(Beatmap.Value.BeatmapInfo), Key.Number2); + BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo), Key.Number3); } if (this.beatmaps == null) From de658c932e6ef23ce6511d15cabf28b836f94416 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 4 Oct 2019 17:22:42 -0700 Subject: [PATCH 3288/5608] Fix test regression --- .../Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs index ecdc484887..f55c099d83 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs @@ -18,8 +18,8 @@ namespace osu.Game.Tests.Visual.SongSelect overlay.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, Color4.Purple, null, Key.Number1); overlay.AddButton(@"Clear", @"local scores", FontAwesome.Solid.Eraser, Color4.Purple, null, Key.Number2); - overlay.AddButton(@"Edit", @"Beatmap", FontAwesome.Solid.PencilAlt, Color4.Yellow, null, Key.Number3); - overlay.AddButton(@"Delete", @"Beatmap", FontAwesome.Solid.Trash, Color4.Pink, null, Key.Number4, float.MaxValue); + overlay.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, Color4.Pink, null, Key.Number3); + overlay.AddButton(@"Edit", @"beatmap", FontAwesome.Solid.PencilAlt, Color4.Yellow, null, Key.Number4); Add(overlay); From a71db11ea544cacf62fdd22da93a9f89a6523f5c Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 4 Oct 2019 18:38:44 -0700 Subject: [PATCH 3289/5608] Remove depth parameter description --- osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs index b831ae274c..c01970f536 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs @@ -89,10 +89,6 @@ namespace osu.Game.Screens.Select.Options /// Icon of the button. /// Hotkey of the button. /// Binding the button does. - /// - /// Lower depth to be put on the left, and higher to be put on the right. - /// Notice this is different to ! - /// public void AddButton(string firstLine, string secondLine, IconUsage icon, Color4 colour, Action action, Key? hotkey = null) { var button = new BeatmapOptionsButton From ba1a8547011d721f61ef1798b6dab6ed6d0e083e Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 5 Oct 2019 10:30:32 +0300 Subject: [PATCH 3290/5608] Use IEnumerable.Where<>() rather than List.FindAll() Saves a whole list allocation --- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index e7a3d15401..bffe779da1 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -56,7 +56,7 @@ namespace osu.Game.Overlays.BeatmapSet if (BeatmapSet != null) { - Difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.FindAll(b => b.Ruleset.Equals(ruleset.Value)).OrderBy(b => b.StarDifficulty).Select(b => new DifficultySelectorButton(b) + Difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.Where(b => b.Ruleset.Equals(ruleset.Value)).OrderBy(b => b.StarDifficulty).Select(b => new DifficultySelectorButton(b) { State = DifficultySelectorState.NotSelected, OnHovered = beatmap => From e257f4ca04481e6b43ef8ec52337c7c364218b56 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sat, 5 Oct 2019 10:31:44 -0700 Subject: [PATCH 3291/5608] Resume music to same position when exiting gameplay --- osu.Game/Screens/Select/SongSelect.cs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 59a143728c..d9ddfa2a94 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -413,7 +413,7 @@ namespace osu.Game.Screens.Select Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap, previous); if (this.IsCurrentScreen() && Beatmap.Value?.Track != previous?.Track) - ensurePlayingSelected(); + ensurePlayingSelected(true); if (beatmap != null) { @@ -585,18 +585,14 @@ namespace osu.Game.Screens.Select { Track track = Beatmap.Value.Track; - if (!track.IsRunning || restart) + if (!track.IsRunning) { track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - if (music != null) - { - // use the global music controller (when available) to cancel a potential local user paused state. - music.SeekTo(track.RestartPoint); - music.Play(); - } - else + if (restart) track.Restart(); + else + track.Start(); } } From bdea75b99584c2624cfc9acff6fc811f332ebc07 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 5 Oct 2019 23:53:05 +0300 Subject: [PATCH 3292/5608] Autoscroll playlist on song change --- osu.Game/Configuration/OsuConfigManager.cs | 5 +++- osu.Game/Overlays/Music/PlaylistList.cs | 11 +++++++- .../Sections/Audio/PlaylistSettings.cs | 27 +++++++++++++++++++ .../Settings/Sections/AudioSection.cs | 1 + 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Overlays/Settings/Sections/Audio/PlaylistSettings.cs diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index c0ce08ba08..75cc961a9e 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -117,6 +117,8 @@ namespace osu.Game.Configuration Set(OsuSetting.UIHoldActivationDelay, 200f, 0f, 500f, 50f); Set(OsuSetting.IntroSequence, IntroSequence.Triangles); + + Set(OsuSetting.FollowPlayback, true); } public OsuConfigManager(Storage storage) @@ -186,6 +188,7 @@ namespace osu.Game.Configuration UIScale, IntroSequence, UIHoldActivationDelay, - HitLighting + HitLighting, + FollowPlayback } } diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 5b528c5ab2..95b4a28125 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osuTK; @@ -52,6 +53,8 @@ namespace osu.Game.Overlays.Music private IBindableList beatmaps; + private IBindable followPlayback; + [Resolved] private MusicController musicController { get; set; } @@ -76,8 +79,10 @@ namespace osu.Game.Overlays.Music } [BackgroundDependencyLoader] - private void load(IBindable beatmap) + private void load(IBindable beatmap, OsuConfigManager configManager) { + followPlayback = configManager.GetBindable(OsuSetting.FollowPlayback); + beatmaps = musicController.BeatmapSets.GetBoundCopy(); beatmaps.ItemsAdded += i => i.ForEach(addBeatmapSet); beatmaps.ItemsRemoved += i => i.ForEach(removeBeatmapSet); @@ -109,7 +114,11 @@ namespace osu.Game.Overlays.Music private void updateSelectedSet() { foreach (PlaylistItem s in items.Children) + { s.Selected = s.BeatmapSetInfo.ID == beatmapBacking.Value.BeatmapSetInfo?.ID; + if (s.Selected && followPlayback.Value) + ScrollIntoView(s); + } } public string SearchTerm diff --git a/osu.Game/Overlays/Settings/Sections/Audio/PlaylistSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/PlaylistSettings.cs new file mode 100644 index 0000000000..5de99e24af --- /dev/null +++ b/osu.Game/Overlays/Settings/Sections/Audio/PlaylistSettings.cs @@ -0,0 +1,27 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Configuration; + +namespace osu.Game.Overlays.Settings.Sections.Audio +{ + public class PlaylistSettings : SettingsSubsection + { + protected override string Header => "Playlist"; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + Children = new Drawable[] + { + new SettingsCheckbox + { + LabelText = "Follow playback", + Bindable = config.GetBindable(OsuSetting.FollowPlayback) + } + }; + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index 772f5c2039..dd67493a75 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.cs @@ -20,6 +20,7 @@ namespace osu.Game.Overlays.Settings.Sections new VolumeSettings(), new OffsetSettings(), new MainMenuSettings(), + new PlaylistSettings() }; } } From eda4a27b45e66c8231c7aeea7c9c2915bbfca74b Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sun, 6 Oct 2019 15:06:25 +0300 Subject: [PATCH 3293/5608] Move FollowPlayback setting to User Interface subsection --- .../Sections/Audio/PlaylistSettings.cs | 27 ------------------- .../Settings/Sections/AudioSection.cs | 3 +-- .../Graphics/UserInterfaceSettings.cs | 5 ++++ 3 files changed, 6 insertions(+), 29 deletions(-) delete mode 100644 osu.Game/Overlays/Settings/Sections/Audio/PlaylistSettings.cs diff --git a/osu.Game/Overlays/Settings/Sections/Audio/PlaylistSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/PlaylistSettings.cs deleted file mode 100644 index 5de99e24af..0000000000 --- a/osu.Game/Overlays/Settings/Sections/Audio/PlaylistSettings.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Game.Configuration; - -namespace osu.Game.Overlays.Settings.Sections.Audio -{ - public class PlaylistSettings : SettingsSubsection - { - protected override string Header => "Playlist"; - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - Children = new Drawable[] - { - new SettingsCheckbox - { - LabelText = "Follow playback", - Bindable = config.GetBindable(OsuSetting.FollowPlayback) - } - }; - } - } -} diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index dd67493a75..7ca313a751 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.cs @@ -19,8 +19,7 @@ namespace osu.Game.Overlays.Settings.Sections new AudioDevicesSettings(), new VolumeSettings(), new OffsetSettings(), - new MainMenuSettings(), - new PlaylistSettings() + new MainMenuSettings() }; } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs index a8953ac3a2..2678d4c11a 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs @@ -17,6 +17,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { Children = new Drawable[] { + new SettingsCheckbox + { + LabelText = "Scroll playlist on song change", + Bindable = config.GetBindable(OsuSetting.FollowPlayback) + }, new SettingsCheckbox { LabelText = "Rotate cursor when dragging", From 38c1cee5fdbb913c771ddbf373ca3fea3d062235 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 6 Oct 2019 10:22:55 -0700 Subject: [PATCH 3294/5608] Fix tab controls overflowing --- .../Overlays/Chat/Tabs/ChannelTabControl.cs | 13 ++----------- osu.Game/Overlays/ChatOverlay.cs | 9 +++++++++ .../SearchableListFilterControl.cs | 10 +++++++++- .../Select/BeatmapDetailAreaTabControl.cs | 18 +++++++++++++++--- 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 612379d339..8b88d81b88 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -9,7 +9,6 @@ using osuTK; using System; using System.Linq; using osu.Framework.Bindables; -using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.Chat.Tabs { @@ -25,19 +24,11 @@ namespace osu.Game.Overlays.Chat.Tabs public ChannelTabControl() { - TabContainer.Margin = new MarginPadding { Left = 50 }; + Padding = new MarginPadding { Left = 50 }; + TabContainer.Spacing = new Vector2(-SHEAR_WIDTH, 0); TabContainer.Masking = false; - AddInternal(new SpriteIcon - { - Icon = FontAwesome.Solid.Comments, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(20), - Margin = new MarginPadding(10), - }); - AddTabItem(selectorTab = new ChannelSelectorTabItem()); ChannelSelectorActive.BindTo(selectorTab.Active); diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 0cadbdfd31..33bcc4c139 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -21,6 +21,7 @@ using osu.Game.Overlays.Chat; using osu.Game.Overlays.Chat.Selection; using osu.Game.Overlays.Chat.Tabs; using osuTK.Input; +using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays { @@ -156,6 +157,14 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, + new SpriteIcon + { + Icon = FontAwesome.Solid.Comments, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(20), + Margin = new MarginPadding(10), + }, ChannelTabControl = CreateChannelTabControl().With(d => { d.Anchor = Anchor.BottomLeft; diff --git a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs index a0c4e9a080..d72e99289e 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs @@ -18,6 +18,7 @@ namespace osu.Game.Overlays.SearchableList private const float padding = 10; private readonly Container filterContainer; + private readonly Container tabsContainer; private readonly Box tabStrip; public readonly SearchTextBox Search; @@ -85,9 +86,14 @@ namespace osu.Game.Overlays.SearchableList AutoSizeAxes = Axes.Y, Margin = new MarginPadding { Top = controls != null ? padding : 0 }, }, - Tabs = new PageTabControl + tabsContainer = new Container { RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = Tabs = new PageTabControl + { + RelativeSizeAxes = Axes.X, + }, }, new Box //keep the tab strip part of autosize, but don't put it in the flow container { @@ -127,6 +133,8 @@ namespace osu.Game.Overlays.SearchableList Height = filterContainer.Height; DisplayStyleControl.Margin = new MarginPadding { Top = filterContainer.Height - 35, Right = SearchableListOverlay.WIDTH_PADDING }; + + tabsContainer.Padding = new MarginPadding { Right = DisplayStyleControl.Width }; } private class FilterSearchTextBox : SearchTextBox diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index 6caef8e2aa..4ca629fee9 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -20,6 +20,7 @@ namespace osu.Game.Screens.Select public static readonly float HEIGHT = 24; private readonly OsuTabControlCheckbox modsCheckbox; private readonly OsuTabControl tabs; + private readonly Container tabsContainer; public Action OnFilter; //passed the selected tab and if mods is checked @@ -39,11 +40,15 @@ namespace osu.Game.Screens.Select Height = 1, Colour = Color4.White.Opacity(0.2f), }, - tabs = new OsuTabControl + tabsContainer = new Container { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, + Child = tabs = new OsuTabControl + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.Both, + }, }, modsCheckbox = new OsuTabControlCheckbox { @@ -69,6 +74,13 @@ namespace osu.Game.Screens.Select tabs.Current.TriggerChange(); } + protected override void Update() + { + base.Update(); + + tabsContainer.Padding = new MarginPadding { Right = modsCheckbox.Width }; + } + private void invokeOnFilter() { OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value); From 11d937beab1708fb1354994b017e08e98cb5cc78 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 6 Oct 2019 10:24:33 -0700 Subject: [PATCH 3295/5608] Fix beatmap detail area tab dropdown being blocked by content --- osu.Game/Screens/Select/BeatmapDetailArea.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index 5348de68d6..71733c9f06 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -36,6 +36,11 @@ namespace osu.Game.Screens.Select { AddRangeInternal(new Drawable[] { + content = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT }, + }, new BeatmapDetailAreaTabControl { RelativeSizeAxes = Axes.X, @@ -58,11 +63,6 @@ namespace osu.Game.Screens.Select } }, }, - content = new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT }, - }, }); AddRange(new Drawable[] From 62c4c1266ef8c1dc71324021bd4808abbb7b6205 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 7 Oct 2019 14:45:26 +0900 Subject: [PATCH 3296/5608] Move private functions to bottom --- .../SongSelect/TestSceneBeatmapCarousel.cs | 202 +++++++++--------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 6bdd94db21..527367fdb8 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -58,107 +58,6 @@ namespace osu.Game.Tests.Visual.SongSelect }); } - private void loadBeatmaps(List beatmapSets = null) - { - if (beatmapSets == null) - { - beatmapSets = new List(); - - for (int i = 1; i <= set_count; i++) - beatmapSets.Add(createTestBeatmapSet(i)); - } - - bool changed = false; - AddStep($"Load {beatmapSets.Count} Beatmaps", () => - { - carousel.Filter(new FilterCriteria()); - carousel.BeatmapSetsChanged = () => changed = true; - carousel.BeatmapSets = beatmapSets; - }); - - AddUntilStep("Wait for load", () => changed); - } - - private void ensureRandomFetchSuccess() => - AddAssert("ensure prev random fetch worked", () => selectedSets.Peek() == carousel.SelectedBeatmapSet); - - private void waitForSelection(int set, int? diff = null) => - AddUntilStep($"selected is set{set}{(diff.HasValue ? $" diff{diff.Value}" : "")}", () => - { - if (diff != null) - return carousel.SelectedBeatmap == carousel.BeatmapSets.Skip(set - 1).First().Beatmaps.Skip(diff.Value - 1).First(); - - return carousel.BeatmapSets.Skip(set - 1).First().Beatmaps.Contains(carousel.SelectedBeatmap); - }); - - private void setSelected(int set, int diff) => - AddStep($"select set{set} diff{diff}", () => - carousel.SelectBeatmap(carousel.BeatmapSets.Skip(set - 1).First().Beatmaps.Skip(diff - 1).First())); - - private void advanceSelection(bool diff, int direction = 1, int count = 1) - { - if (count == 1) - AddStep($"select {(direction > 0 ? "next" : "prev")} {(diff ? "diff" : "set")}", () => - carousel.SelectNext(direction, !diff)); - else - { - AddRepeatStep($"select {(direction > 0 ? "next" : "prev")} {(diff ? "diff" : "set")}", () => - carousel.SelectNext(direction, !diff), count); - } - } - - private void checkVisibleItemCount(bool diff, int count) => - AddAssert($"{count} {(diff ? "diffs" : "sets")} visible", () => - carousel.Items.Count(s => (diff ? s.Item is CarouselBeatmap : s.Item is CarouselBeatmapSet) && s.Item.Visible) == count); - - private void checkNoSelection() => AddAssert("Selection is null", () => currentSelection == null); - - private void nextRandom() => - AddStep("select random next", () => - { - carousel.RandomAlgorithm.Value = RandomSelectAlgorithm.RandomPermutation; - - if (!selectedSets.Any() && carousel.SelectedBeatmap != null) - selectedSets.Push(carousel.SelectedBeatmapSet); - - carousel.SelectNextRandom(); - selectedSets.Push(carousel.SelectedBeatmapSet); - }); - - private void ensureRandomDidntRepeat() => - AddAssert("ensure no repeats", () => selectedSets.Distinct().Count() == selectedSets.Count); - - private void prevRandom() => AddStep("select random last", () => - { - carousel.SelectPreviousRandom(); - selectedSets.Pop(); - }); - - private bool selectedBeatmapVisible() - { - var currentlySelected = carousel.Items.Find(s => s.Item is CarouselBeatmap && s.Item.State.Value == CarouselItemState.Selected); - if (currentlySelected == null) - return true; - - return currentlySelected.Item.Visible; - } - - private void checkInvisibleDifficultiesUnselectable() - { - nextRandom(); - AddAssert("Selection is visible", selectedBeatmapVisible); - } - - private void checkNonmatchingFilter() - { - AddStep("Toggle non-matching filter", () => - { - carousel.Filter(new FilterCriteria { SearchText = "Dingo" }, false); - carousel.Filter(new FilterCriteria(), false); - eagerSelectedIDs.Add(carousel.SelectedBeatmapSet.ID); - }); - } - /// /// Test keyboard traversal /// @@ -482,6 +381,107 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("Selection was random", () => eagerSelectedIDs.Count > 1); } + private void loadBeatmaps(List beatmapSets = null) + { + if (beatmapSets == null) + { + beatmapSets = new List(); + + for (int i = 1; i <= set_count; i++) + beatmapSets.Add(createTestBeatmapSet(i)); + } + + bool changed = false; + AddStep($"Load {beatmapSets.Count} Beatmaps", () => + { + carousel.Filter(new FilterCriteria()); + carousel.BeatmapSetsChanged = () => changed = true; + carousel.BeatmapSets = beatmapSets; + }); + + AddUntilStep("Wait for load", () => changed); + } + + private void ensureRandomFetchSuccess() => + AddAssert("ensure prev random fetch worked", () => selectedSets.Peek() == carousel.SelectedBeatmapSet); + + private void waitForSelection(int set, int? diff = null) => + AddUntilStep($"selected is set{set}{(diff.HasValue ? $" diff{diff.Value}" : "")}", () => + { + if (diff != null) + return carousel.SelectedBeatmap == carousel.BeatmapSets.Skip(set - 1).First().Beatmaps.Skip(diff.Value - 1).First(); + + return carousel.BeatmapSets.Skip(set - 1).First().Beatmaps.Contains(carousel.SelectedBeatmap); + }); + + private void setSelected(int set, int diff) => + AddStep($"select set{set} diff{diff}", () => + carousel.SelectBeatmap(carousel.BeatmapSets.Skip(set - 1).First().Beatmaps.Skip(diff - 1).First())); + + private void advanceSelection(bool diff, int direction = 1, int count = 1) + { + if (count == 1) + AddStep($"select {(direction > 0 ? "next" : "prev")} {(diff ? "diff" : "set")}", () => + carousel.SelectNext(direction, !diff)); + else + { + AddRepeatStep($"select {(direction > 0 ? "next" : "prev")} {(diff ? "diff" : "set")}", () => + carousel.SelectNext(direction, !diff), count); + } + } + + private void checkVisibleItemCount(bool diff, int count) => + AddAssert($"{count} {(diff ? "diffs" : "sets")} visible", () => + carousel.Items.Count(s => (diff ? s.Item is CarouselBeatmap : s.Item is CarouselBeatmapSet) && s.Item.Visible) == count); + + private void checkNoSelection() => AddAssert("Selection is null", () => currentSelection == null); + + private void nextRandom() => + AddStep("select random next", () => + { + carousel.RandomAlgorithm.Value = RandomSelectAlgorithm.RandomPermutation; + + if (!selectedSets.Any() && carousel.SelectedBeatmap != null) + selectedSets.Push(carousel.SelectedBeatmapSet); + + carousel.SelectNextRandom(); + selectedSets.Push(carousel.SelectedBeatmapSet); + }); + + private void ensureRandomDidntRepeat() => + AddAssert("ensure no repeats", () => selectedSets.Distinct().Count() == selectedSets.Count); + + private void prevRandom() => AddStep("select random last", () => + { + carousel.SelectPreviousRandom(); + selectedSets.Pop(); + }); + + private bool selectedBeatmapVisible() + { + var currentlySelected = carousel.Items.Find(s => s.Item is CarouselBeatmap && s.Item.State.Value == CarouselItemState.Selected); + if (currentlySelected == null) + return true; + + return currentlySelected.Item.Visible; + } + + private void checkInvisibleDifficultiesUnselectable() + { + nextRandom(); + AddAssert("Selection is visible", selectedBeatmapVisible); + } + + private void checkNonmatchingFilter() + { + AddStep("Toggle non-matching filter", () => + { + carousel.Filter(new FilterCriteria { SearchText = "Dingo" }, false); + carousel.Filter(new FilterCriteria(), false); + eagerSelectedIDs.Add(carousel.SelectedBeatmapSet.ID); + }); + } + private BeatmapSetInfo createTestBeatmapSet(int id) { return new BeatmapSetInfo From 46d6c5ec3b6832d353f033d9284d761f423943db Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 7 Oct 2019 15:13:58 +0900 Subject: [PATCH 3297/5608] Add failing test --- .../SongSelect/TestSceneBeatmapCarousel.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 527367fdb8..f87d6ebebb 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -245,6 +245,30 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert($"Check #{set_count} is at bottom", () => carousel.BeatmapSets.Last().Metadata.Title.EndsWith($"#{set_count}!")); } + [Test] + public void TestSortingWithFiltered() + { + List sets = new List(); + + for (int i = 0; i < 3; i++) + { + var set = createTestBeatmapSet(i); + set.Beatmaps[0].StarDifficulty = 3 - i; + set.Beatmaps[2].StarDifficulty = 6 + i; + sets.Add(set); + } + + loadBeatmaps(sets); + + AddStep("Filter to normal", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Difficulty, SearchText = "Normal" }, false)); + AddAssert("Check first set at end", () => carousel.BeatmapSets.First() == sets.Last()); + AddAssert("Check last set at start", () => carousel.BeatmapSets.Last() == sets.First()); + + AddStep("Filter to insane", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Difficulty, SearchText = "Insane" }, false)); + AddAssert("Check first set at start", () => carousel.BeatmapSets.First() == sets.First()); + AddAssert("Check last set at end", () => carousel.BeatmapSets.Last() == sets.Last()); + } + [Test] public void TestRemoveAll() { From f15953d65ce00c38a2544234c426c33f55429cb0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 7 Oct 2019 15:16:26 +0900 Subject: [PATCH 3298/5608] Fix carousel including filtered difficulties in sort comparisons --- .../Select/Carousel/CarouselBeatmapSet.cs | 23 ++++++++++++++++--- .../Screens/Select/Carousel/CarouselGroup.cs | 2 +- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 5a3996bb49..35816fe620 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -49,16 +49,33 @@ namespace osu.Game.Screens.Select.Carousel return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded); case SortMode.BPM: - return BeatmapSet.MaxBPM.CompareTo(otherSet.BeatmapSet.MaxBPM); + return compareUsingAggregateMax(otherSet, b => b.BPM); case SortMode.Length: - return BeatmapSet.MaxLength.CompareTo(otherSet.BeatmapSet.MaxLength); + return compareUsingAggregateMax(otherSet, b => b.Length); case SortMode.Difficulty: - return BeatmapSet.MaxStarDifficulty.CompareTo(otherSet.BeatmapSet.MaxStarDifficulty); + return compareUsingAggregateMax(otherSet, b => b.StarDifficulty); } } + /// + /// All beatmaps which are not filtered and valid for display. + /// + protected IEnumerable ValidBeatmaps => Beatmaps.Where(b => !b.Filtered.Value).Select(b => b.Beatmap); + + private int compareUsingAggregateMax(CarouselBeatmapSet other, Func func) + { + var ourBeatmaps = ValidBeatmaps.Any(); + var otherBeatmaps = other.ValidBeatmaps.Any(); + + if (!ourBeatmaps && !otherBeatmaps) return 0; + if (!ourBeatmaps) return -1; + if (!otherBeatmaps) return 1; + + return ValidBeatmaps.Max(func).CompareTo(other.ValidBeatmaps.Max(func)); + } + public override void Filter(FilterCriteria criteria) { base.Filter(criteria); diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs index 6ebd2d41cc..09b728abeb 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs @@ -83,8 +83,8 @@ namespace osu.Game.Screens.Select.Carousel var children = new List(InternalChildren); - children.Sort((x, y) => x.CompareTo(criteria, y)); children.ForEach(c => c.Filter(criteria)); + children.Sort((x, y) => x.CompareTo(criteria, y)); InternalChildren = children; } From e265beb289a3d1df5c5d0645526884e85c410ac9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 7 Oct 2019 18:49:59 +0900 Subject: [PATCH 3299/5608] Fix merge error --- .../Blueprints/HitCircles/HitCirclePlacementBlueprint.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs index 38584ce898..6c08990ad6 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs @@ -21,6 +21,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles InternalChild = circlePiece = new HitCirclePiece(); } + protected override void Update() + { + base.Update(); + + circlePiece.UpdateFrom(HitObject); + } + protected override bool OnClick(ClickEvent e) { HitObject.StartTime = EditorClock.CurrentTime; From 2d707b2b65bb4baa189e4cb68c3e9d3bbbfeff54 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 7 Oct 2019 15:36:23 +0300 Subject: [PATCH 3300/5608] Implement PostBeatmapFavouriteRequest --- .../Requests/PostBeatmapFavouriteRequest.cs | 36 +++++++++++++++++++ .../BeatmapSet/Buttons/FavouriteButton.cs | 24 ++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs diff --git a/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs b/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs new file mode 100644 index 0000000000..f3724230cb --- /dev/null +++ b/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs @@ -0,0 +1,36 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.IO.Network; +using System.Net.Http; + +namespace osu.Game.Online.API.Requests +{ + public class PostBeatmapFavouriteRequest : APIRequest + { + private readonly int id; + private readonly BeatmapFavouriteAction action; + + public PostBeatmapFavouriteRequest(int id, BeatmapFavouriteAction action) + { + this.id = id; + this.action = action; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Post; + req.AddParameter(@"action", action.ToString().ToLowerInvariant()); + return req; + } + + protected override string Target => $@"beatmapsets/{id}/favourites"; + } + + public enum BeatmapFavouriteAction + { + Favourite, + UnFavourite + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 11f56bc163..23325b8765 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -10,6 +10,9 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osuTK; namespace osu.Game.Overlays.BeatmapSet.Buttons @@ -20,8 +23,11 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private readonly Bindable favourited = new Bindable(); + private PostBeatmapFavouriteRequest request; + private DimmedLoadingLayer loading; + [BackgroundDependencyLoader] - private void load() + private void load(IAPIProvider api) { Container pink; SpriteIcon icon; @@ -55,6 +61,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons Size = new Vector2(18), Shadow = false, }, + loading = new DimmedLoadingLayer(), }); BeatmapSet.BindValueChanged(setInfo => @@ -67,6 +74,8 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons favourited.ValueChanged += favourited => { + loading.Hide(); + if (favourited.NewValue) { pink.FadeIn(200); @@ -78,6 +87,19 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons icon.Icon = FontAwesome.Regular.Heart; } }; + + Action = () => + { + if (loading.State.Value == Visibility.Visible) + return; + + loading.Show(); + + request?.Cancel(); + request = new PostBeatmapFavouriteRequest(BeatmapSet.Value?.OnlineBeatmapSetID ?? 0, favourited.Value ? BeatmapFavouriteAction.UnFavourite : BeatmapFavouriteAction.Favourite); + request.Success += () => favourited.Value = !favourited.Value; + api.Queue(request); + }; } protected override void UpdateAfterChildren() From a7dc9bb582682c0b87ea047f1da9aa6b40a45ea0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 7 Oct 2019 15:41:05 +0300 Subject: [PATCH 3301/5608] Add tooltip and remove pink layer --- .../BeatmapSet/Buttons/FavouriteButton.cs | 40 +++---------------- 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 23325b8765..fcea20ef11 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -5,11 +5,9 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; @@ -17,7 +15,7 @@ using osuTK; namespace osu.Game.Overlays.BeatmapSet.Buttons { - public class FavouriteButton : HeaderButton + public class FavouriteButton : HeaderButton, IHasTooltip { public readonly Bindable BeatmapSet = new Bindable(); @@ -26,33 +24,14 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private PostBeatmapFavouriteRequest request; private DimmedLoadingLayer loading; + public string TooltipText => (favourited.Value ? "Unfavourite" : "Favourite") + " this beatmapset"; + [BackgroundDependencyLoader] private void load(IAPIProvider api) { - Container pink; SpriteIcon icon; AddRange(new Drawable[] { - pink = new Container - { - RelativeSizeAxes = Axes.Both, - Alpha = 0f, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"9f015f"), - }, - new Triangles - { - RelativeSizeAxes = Axes.Both, - ColourLight = OsuColour.FromHex(@"cb2187"), - ColourDark = OsuColour.FromHex(@"9f015f"), - TriangleScale = 1.5f, - }, - }, - }, icon = new SpriteIcon { Anchor = Anchor.Centre, @@ -76,16 +55,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { loading.Hide(); - if (favourited.NewValue) - { - pink.FadeIn(200); - icon.Icon = FontAwesome.Solid.Heart; - } - else - { - pink.FadeOut(200); - icon.Icon = FontAwesome.Regular.Heart; - } + icon.Icon = favourited.NewValue ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart; }; Action = () => From 76db200bd3efd8f3f1a93820e852cbdb9e54fdc8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 7 Oct 2019 16:48:05 +0300 Subject: [PATCH 3302/5608] Implement GetCommentsRequest --- .../Online/API/Requests/GetCommentsRequest.cs | 53 ++++++++++++++++++ .../API/Requests/Responses/APIComments.cs | 36 ++++++++++++ .../Online/API/Requests/Responses/Comment.cs | 56 +++++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 osu.Game/Online/API/Requests/GetCommentsRequest.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APIComments.cs create mode 100644 osu.Game/Online/API/Requests/Responses/Comment.cs diff --git a/osu.Game/Online/API/Requests/GetCommentsRequest.cs b/osu.Game/Online/API/Requests/GetCommentsRequest.cs new file mode 100644 index 0000000000..279a1905da --- /dev/null +++ b/osu.Game/Online/API/Requests/GetCommentsRequest.cs @@ -0,0 +1,53 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.IO.Network; +using Humanizer; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Online.API.Requests +{ + public class GetCommentsRequest : APIRequest + { + private readonly long id; + private readonly int page; + private readonly CommentableType type; + private readonly SortCommentsBy sort; + + public GetCommentsRequest(CommentableType type, long id, SortCommentsBy sort = SortCommentsBy.New, int page = 1) + { + this.type = type; + this.sort = sort; + this.id = id; + this.page = page; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + req.AddParameter("commentable_type", type.ToString().Underscore().ToLowerInvariant()); + req.AddParameter("commentable_id", id.ToString()); + req.AddParameter("sort", sort.ToString()); + req.AddParameter("page", page.ToString()); + + return req; + } + + protected override string Target => "comments"; + } + + public enum CommentableType + { + Build, + Beatmapset, + NewsPost + } + + public enum SortCommentsBy + { + New, + Old, + Top + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIComments.cs b/osu.Game/Online/API/Requests/Responses/APIComments.cs new file mode 100644 index 0000000000..158430a5b6 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIComments.cs @@ -0,0 +1,36 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Newtonsoft.Json; +using osu.Game.Users; +using System.Collections.Generic; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIComments + { + [JsonProperty(@"comments")] + public List Comments { get; set; } + + [JsonProperty(@"has_more")] + public bool HasMore { get; set; } + + [JsonProperty(@"has_more_id")] + public long HasMoreId { get; set; } + + [JsonProperty(@"user_follow")] + public bool UserFollow { get; set; } + + [JsonProperty(@"included_comments")] + public List IncludedComments { get; set; } + + [JsonProperty(@"users")] + public List Users { get; set; } + + [JsonProperty(@"total")] + public int Total { get; set; } + + [JsonProperty(@"top_level_count")] + public int TopLevelCount { get; set; } + } +} diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs new file mode 100644 index 0000000000..e157a10f8a --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/Comment.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 Newtonsoft.Json; +using System; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class Comment + { + [JsonProperty(@"id")] + public long Id { get; set; } + + [JsonProperty(@"parent_id")] + public long ParentId { get; set; } + + [JsonProperty(@"user_id")] + public long UserId { get; set; } + + [JsonProperty(@"message")] + public string Message { get; set; } + + [JsonProperty(@"message_html")] + public string MessageHTML { get; set; } + + [JsonProperty(@"replies_count")] + public int RepliesCount { get; set; } + + [JsonProperty(@"votes_count")] + public int VotesCount { get; set; } + + [JsonProperty(@"commenatble_type")] + public string CommentableType { get; set; } + + [JsonProperty(@"commentable_id")] + public int CommentableId { get; set; } + + [JsonProperty(@"legacy_name")] + public string LegacyName { get; set; } + + [JsonProperty(@"created_at")] + public DateTimeOffset CreatedAt { get; set; } + + [JsonProperty(@"updated_at")] + public DateTimeOffset UpdatedAt { get; set; } + + [JsonProperty(@"deleted_at")] + public DateTimeOffset DeletedAt { get; set; } + + [JsonProperty(@"edited_at")] + public DateTimeOffset EditedAt { get; set; } + + [JsonProperty(@"edited_by_id")] + public long EditedById { get; set; } + } +} From 738580ec617a23789236575f2525606a6a4d227e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 7 Oct 2019 16:58:24 +0300 Subject: [PATCH 3303/5608] Add IsTopLevel property --- osu.Game/Online/API/Requests/Responses/Comment.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index e157a10f8a..6edf13d2da 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -11,8 +11,18 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"id")] public long Id { get; set; } + private long? parentId; + [JsonProperty(@"parent_id")] - public long ParentId { get; set; } + public long? ParentId + { + get => parentId; + set + { + parentId = value; + IsTopLevel = value != null; + } + } [JsonProperty(@"user_id")] public long UserId { get; set; } @@ -52,5 +62,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"edited_by_id")] public long EditedById { get; set; } + + public bool IsTopLevel { get; set; } } } From e772822bd5ee46afddc5bc14398e73f84ff84564 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 7 Oct 2019 17:49:20 +0300 Subject: [PATCH 3304/5608] Basic implementation --- .../Online/TestSceneCommentsContainer.cs | 29 +++++ osu.Game/Overlays/CommentsContainer.cs | 110 ++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs create mode 100644 osu.Game/Overlays/CommentsContainer.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs new file mode 100644 index 0000000000..c99062d59b --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -0,0 +1,29 @@ +// 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 NUnit.Framework; +using osu.Game.Overlays; +using osu.Game.Online.API.Requests; + +namespace osu.Game.Tests.Visual.Online +{ + [TestFixture] + public class TestSceneCommentsContainer : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(CommentsContainer), + }; + + public TestSceneCommentsContainer() + { + AddStep("Big Black comments", () => + { + Clear(); + Add(new CommentsContainer(CommentableType.Beatmapset, 41823)); + }); + } + } +} diff --git a/osu.Game/Overlays/CommentsContainer.cs b/osu.Game/Overlays/CommentsContainer.cs new file mode 100644 index 0000000000..8ed6fd0878 --- /dev/null +++ b/osu.Game/Overlays/CommentsContainer.cs @@ -0,0 +1,110 @@ +// 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.Containers; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Framework.Graphics; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Framework.Graphics.Sprites; +using osuTK; + +namespace osu.Game.Overlays +{ + public class CommentsContainer : CompositeDrawable + { + private readonly CommentableType type; + private readonly long id; + + public readonly Bindable Sort = new Bindable(); + + [Resolved] + private IAPIProvider api { get; set; } + + private readonly CommentsHeader header; + private readonly Box background; + + public CommentsContainer(CommentableType type, long id) + { + this.type = type; + this.id = id; + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + AddRangeInternal(new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + header = new CommentsHeader + { + Sort = { BindTarget = Sort } + } + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.Gray3; + } + + private class CommentsHeader : CompositeDrawable + { + private const int height = 40; + private const int spacing = 10; + private const int padding = 50; + + public readonly Bindable Sort = new Bindable(); + + private readonly Box background; + + public CommentsHeader() + { + RelativeSizeAxes = Axes.X; + Height = height; + AddRangeInternal(new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = padding }, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(spacing, 0), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Children = new Drawable[] + { + new SpriteText + { + Font = OsuFont.GetFont(size: 14), + Text = @"Sort by" + } + } + } + } + } + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.Gray4; + } + } + } +} From aa8df0fa20426b0beec6997a2f2a07895cdddbaf Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 7 Oct 2019 18:26:07 +0300 Subject: [PATCH 3305/5608] Hook up api and implement some visual comments representation --- .../Online/TestSceneCommentsContainer.cs | 15 +++- .../API/Requests/Responses/APIComments.cs | 2 +- .../Online/API/Requests/Responses/Comment.cs | 8 +- osu.Game/Overlays/CommentsContainer.cs | 84 ++++++++++++++++++- 4 files changed, 99 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index c99062d59b..bf4117189a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Game.Overlays; using osu.Game.Online.API.Requests; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics; namespace osu.Game.Tests.Visual.Online { @@ -17,12 +19,21 @@ namespace osu.Game.Tests.Visual.Online typeof(CommentsContainer), }; + protected override bool UseOnlineAPI => true; + public TestSceneCommentsContainer() { + BasicScrollContainer scrollFlow; + + Add(scrollFlow = new BasicScrollContainer + { + RelativeSizeAxes = Axes.Both, + }); + AddStep("Big Black comments", () => { - Clear(); - Add(new CommentsContainer(CommentableType.Beatmapset, 41823)); + scrollFlow.Clear(); + scrollFlow.Add(new CommentsContainer(CommentableType.Beatmapset, 41823)); }); } } diff --git a/osu.Game/Online/API/Requests/Responses/APIComments.cs b/osu.Game/Online/API/Requests/Responses/APIComments.cs index 158430a5b6..af7650e512 100644 --- a/osu.Game/Online/API/Requests/Responses/APIComments.cs +++ b/osu.Game/Online/API/Requests/Responses/APIComments.cs @@ -16,7 +16,7 @@ namespace osu.Game.Online.API.Requests.Responses public bool HasMore { get; set; } [JsonProperty(@"has_more_id")] - public long HasMoreId { get; set; } + public long? HasMoreId { get; set; } [JsonProperty(@"user_follow")] public bool UserFollow { get; set; } diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 6edf13d2da..df5c812fa0 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -52,16 +52,16 @@ namespace osu.Game.Online.API.Requests.Responses public DateTimeOffset CreatedAt { get; set; } [JsonProperty(@"updated_at")] - public DateTimeOffset UpdatedAt { get; set; } + public DateTimeOffset? UpdatedAt { get; set; } [JsonProperty(@"deleted_at")] - public DateTimeOffset DeletedAt { get; set; } + public DateTimeOffset? DeletedAt { get; set; } [JsonProperty(@"edited_at")] - public DateTimeOffset EditedAt { get; set; } + public DateTimeOffset? EditedAt { get; set; } [JsonProperty(@"edited_by_id")] - public long EditedById { get; set; } + public long? EditedById { get; set; } public bool IsTopLevel { get; set; } } diff --git a/osu.Game/Overlays/CommentsContainer.cs b/osu.Game/Overlays/CommentsContainer.cs index 8ed6fd0878..fce9b3f03b 100644 --- a/osu.Game/Overlays/CommentsContainer.cs +++ b/osu.Game/Overlays/CommentsContainer.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Framework.Graphics.Sprites; using osuTK; +using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays { @@ -24,8 +25,14 @@ namespace osu.Game.Overlays [Resolved] private IAPIProvider api { get; set; } + [Resolved] + private OsuColour colours { get; set; } + + private GetCommentsRequest request; + private readonly CommentsHeader header; private readonly Box background; + private readonly FillFlowContainer content; public CommentsContainer(CommentableType type, long id) { @@ -40,15 +47,86 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.Both, }, - header = new CommentsHeader + new FillFlowContainer { - Sort = { BindTarget = Sort } + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + header = new CommentsHeader + { + Sort = { BindTarget = Sort } + }, + content = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + } + } + } + }); + } + + protected override void LoadComplete() + { + Sort.BindValueChanged(onSortChanged, true); + base.LoadComplete(); + } + + private void onSortChanged(ValueChangedEvent sort) => getComments(); + + private void getComments() + { + request?.Cancel(); + request = new GetCommentsRequest(type, id, Sort.Value); + request.Success += onSuccess; + api.Queue(request); + } + + private void onSuccess(APIComments response) + { + content.Clear(); + + foreach (var c in response.Comments) + { + createDrawableComment(c); + } + } + + private void createDrawableComment(Comment comment) + { + content.Add(new Container + { + RelativeSizeAxes = Axes.X, + Height = 70, + Children = new Drawable[] + { + new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = comment.MessageHTML, + }, + new Container + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + Height = 1, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Gray1, + } + } } }); } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { background.Colour = colours.Gray3; } From cc6bf2f173b4d53c9fb568963c4685e133417254 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 7 Oct 2019 18:45:22 +0300 Subject: [PATCH 3306/5608] Add IsDeleted property --- .../Online/API/Requests/Responses/Comment.cs | 16 ++++++++++++++-- osu.Game/Overlays/CommentsContainer.cs | 6 +++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index df5c812fa0..e4b66ddeee 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -20,7 +20,7 @@ namespace osu.Game.Online.API.Requests.Responses set { parentId = value; - IsTopLevel = value != null; + IsTopLevel = value == null; } } @@ -54,8 +54,18 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"updated_at")] public DateTimeOffset? UpdatedAt { get; set; } + private DateTimeOffset? deletedAt; + [JsonProperty(@"deleted_at")] - public DateTimeOffset? DeletedAt { get; set; } + public DateTimeOffset? DeletedAt + { + get => deletedAt; + set + { + deletedAt = value; + IsDeleted = value != null; + } + } [JsonProperty(@"edited_at")] public DateTimeOffset? EditedAt { get; set; } @@ -64,5 +74,7 @@ namespace osu.Game.Online.API.Requests.Responses public long? EditedById { get; set; } public bool IsTopLevel { get; set; } + + public bool IsDeleted { get; set; } } } diff --git a/osu.Game/Overlays/CommentsContainer.cs b/osu.Game/Overlays/CommentsContainer.cs index fce9b3f03b..b22fefb3de 100644 --- a/osu.Game/Overlays/CommentsContainer.cs +++ b/osu.Game/Overlays/CommentsContainer.cs @@ -30,7 +30,6 @@ namespace osu.Game.Overlays private GetCommentsRequest request; - private readonly CommentsHeader header; private readonly Box background; private readonly FillFlowContainer content; @@ -54,7 +53,7 @@ namespace osu.Game.Overlays Direction = FillDirection.Vertical, Children = new Drawable[] { - header = new CommentsHeader + new CommentsHeader { Sort = { BindTarget = Sort } }, @@ -91,7 +90,8 @@ namespace osu.Game.Overlays foreach (var c in response.Comments) { - createDrawableComment(c); + if (!c.IsDeleted) + createDrawableComment(c); } } From e00992dfd8f18cc9e99724099e75eae42d0a1424 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Mon, 7 Oct 2019 19:44:22 +0300 Subject: [PATCH 3307/5608] Remove FollowPlayback setting --- osu.Game/Configuration/OsuConfigManager.cs | 5 +---- osu.Game/Overlays/Music/PlaylistList.cs | 9 ++------- .../Settings/Sections/Graphics/UserInterfaceSettings.cs | 5 ----- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 75cc961a9e..c0ce08ba08 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -117,8 +117,6 @@ namespace osu.Game.Configuration Set(OsuSetting.UIHoldActivationDelay, 200f, 0f, 500f, 50f); Set(OsuSetting.IntroSequence, IntroSequence.Triangles); - - Set(OsuSetting.FollowPlayback, true); } public OsuConfigManager(Storage storage) @@ -188,7 +186,6 @@ namespace osu.Game.Configuration UIScale, IntroSequence, UIHoldActivationDelay, - HitLighting, - FollowPlayback + HitLighting } } diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 95b4a28125..f497bd5b8d 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Game.Beatmaps; -using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osuTK; @@ -53,8 +52,6 @@ namespace osu.Game.Overlays.Music private IBindableList beatmaps; - private IBindable followPlayback; - [Resolved] private MusicController musicController { get; set; } @@ -79,10 +76,8 @@ namespace osu.Game.Overlays.Music } [BackgroundDependencyLoader] - private void load(IBindable beatmap, OsuConfigManager configManager) + private void load(IBindable beatmap) { - followPlayback = configManager.GetBindable(OsuSetting.FollowPlayback); - beatmaps = musicController.BeatmapSets.GetBoundCopy(); beatmaps.ItemsAdded += i => i.ForEach(addBeatmapSet); beatmaps.ItemsRemoved += i => i.ForEach(removeBeatmapSet); @@ -116,7 +111,7 @@ namespace osu.Game.Overlays.Music foreach (PlaylistItem s in items.Children) { s.Selected = s.BeatmapSetInfo.ID == beatmapBacking.Value.BeatmapSetInfo?.ID; - if (s.Selected && followPlayback.Value) + if (s.Selected) ScrollIntoView(s); } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs index 2678d4c11a..a8953ac3a2 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs @@ -17,11 +17,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { Children = new Drawable[] { - new SettingsCheckbox - { - LabelText = "Scroll playlist on song change", - Bindable = config.GetBindable(OsuSetting.FollowPlayback) - }, new SettingsCheckbox { LabelText = "Rotate cursor when dragging", From 8e6e90eaecf467b2764f3b2497acac12d4977c30 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 7 Oct 2019 16:11:40 -0700 Subject: [PATCH 3308/5608] Use fixed numbers for padding instead --- .../SearchableList/SearchableListFilterControl.cs | 6 ++---- .../Screens/Select/BeatmapDetailAreaTabControl.cs | 11 ++--------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs index d72e99289e..372da94b37 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs @@ -18,7 +18,6 @@ namespace osu.Game.Overlays.SearchableList private const float padding = 10; private readonly Container filterContainer; - private readonly Container tabsContainer; private readonly Box tabStrip; public readonly SearchTextBox Search; @@ -86,10 +85,11 @@ namespace osu.Game.Overlays.SearchableList AutoSizeAxes = Axes.Y, Margin = new MarginPadding { Top = controls != null ? padding : 0 }, }, - tabsContainer = new Container + new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Right = 225 }, Child = Tabs = new PageTabControl { RelativeSizeAxes = Axes.X, @@ -133,8 +133,6 @@ namespace osu.Game.Overlays.SearchableList Height = filterContainer.Height; DisplayStyleControl.Margin = new MarginPadding { Top = filterContainer.Height - 35, Right = SearchableListOverlay.WIDTH_PADDING }; - - tabsContainer.Padding = new MarginPadding { Right = DisplayStyleControl.Width }; } private class FilterSearchTextBox : SearchTextBox diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index 4ca629fee9..38b1c6411b 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -20,7 +20,6 @@ namespace osu.Game.Screens.Select public static readonly float HEIGHT = 24; private readonly OsuTabControlCheckbox modsCheckbox; private readonly OsuTabControl tabs; - private readonly Container tabsContainer; public Action OnFilter; //passed the selected tab and if mods is checked @@ -40,9 +39,10 @@ namespace osu.Game.Screens.Select Height = 1, Colour = Color4.White.Opacity(0.2f), }, - tabsContainer = new Container + new Container { RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 100 }, Child = tabs = new OsuTabControl { Anchor = Anchor.BottomLeft, @@ -74,13 +74,6 @@ namespace osu.Game.Screens.Select tabs.Current.TriggerChange(); } - protected override void Update() - { - base.Update(); - - tabsContainer.Padding = new MarginPadding { Right = modsCheckbox.Width }; - } - private void invokeOnFilter() { OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value); From 9fdbe583262411aa5f863aec924459420e373c26 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 7 Oct 2019 16:17:58 -0700 Subject: [PATCH 3309/5608] Fix dropdown header padding when selected mod filter is hidden --- osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index 38b1c6411b..bba72c7ee1 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -20,6 +20,7 @@ namespace osu.Game.Screens.Select public static readonly float HEIGHT = 24; private readonly OsuTabControlCheckbox modsCheckbox; private readonly OsuTabControl tabs; + private readonly Container tabsContainer; public Action OnFilter; //passed the selected tab and if mods is checked @@ -39,10 +40,9 @@ namespace osu.Game.Screens.Select Height = 1, Colour = Color4.White.Opacity(0.2f), }, - new Container + tabsContainer = new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 100 }, Child = tabs = new OsuTabControl { Anchor = Anchor.BottomLeft, @@ -79,6 +79,8 @@ namespace osu.Game.Screens.Select OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value); modsCheckbox.FadeTo(tabs.Current.Value == BeatmapDetailTab.Details ? 0 : 1, 200, Easing.OutQuint); + + tabsContainer.Padding = new MarginPadding { Right = tabs.Current.Value == BeatmapDetailTab.Details ? 0 : 100 }; } } From 3ec78388e896e6b5bf1fe1f2fa3869545c6759c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 11:02:54 +0900 Subject: [PATCH 3310/5608] Avoid excess background updates in playlist overlay --- osu.Game/Overlays/Music/PlaylistList.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 5b528c5ab2..e8c2537c43 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -84,7 +84,7 @@ namespace osu.Game.Overlays.Music beatmaps.ForEach(addBeatmapSet); beatmapBacking.BindTo(beatmap); - beatmapBacking.ValueChanged += _ => updateSelectedSet(); + beatmapBacking.ValueChanged += _ => Scheduler.AddOnce(updateSelectedSet); } private void addBeatmapSet(BeatmapSetInfo obj) From e7fc5e556c79f154b334545b2d367e712c0154e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 10:40:52 +0900 Subject: [PATCH 3311/5608] Fix song select not correctly playing tracks in some cases --- osu.Game/Screens/Select/SongSelect.cs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index d9ddfa2a94..04a686f481 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -412,9 +412,6 @@ namespace osu.Game.Screens.Select WorkingBeatmap previous = Beatmap.Value; Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap, previous); - if (this.IsCurrentScreen() && Beatmap.Value?.Track != previous?.Track) - ensurePlayingSelected(true); - if (beatmap != null) { if (beatmap.BeatmapSetInfoID == beatmapNoDebounce?.BeatmapSetInfoID) @@ -424,6 +421,9 @@ namespace osu.Game.Screens.Select } } + if (this.IsCurrentScreen()) + ensurePlayingSelected(); + UpdateBeatmap(Beatmap.Value); } } @@ -581,19 +581,14 @@ namespace osu.Game.Screens.Select beatmap.Track.Looping = true; } - private void ensurePlayingSelected(bool restart = false) + private void ensurePlayingSelected() { Track track = Beatmap.Value.Track; - if (!track.IsRunning) - { - track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; + track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - if (restart) - track.Restart(); - else - track.Start(); - } + if (!track.IsRunning) + track.Restart(); } private void onBeatmapSetAdded(BeatmapSetInfo s) => Carousel.UpdateBeatmapSet(s); From 3c0b1be7f48c32db7714b04ce6fda76ffeefdcb8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 11:52:16 +0900 Subject: [PATCH 3312/5608] Add xmldoc where applicable --- osu.Game/Screens/Menu/IntroScreen.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index c81fef6436..1052ebdd5b 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -21,8 +21,15 @@ namespace osu.Game.Screens.Menu { public abstract class IntroScreen : StartupScreen { + /// + /// A hash used to find the associated beatmap if already imported. + /// protected abstract string BeatmapHash { get; } + /// + /// A source file to use as an import source if the intro beatmap is not yet present. + /// Should be within the "Tracks" namespace of game resources. + /// protected abstract string BeatmapFile { get; } private readonly BindableDouble exitingVolumeFade = new BindableDouble(1); From c3d56088d87d8f12fe7abbe2912b8a6f89e73bc1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 11:54:39 +0900 Subject: [PATCH 3313/5608] Make constant private --- osu.Game/Screens/Menu/IntroScreen.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 1052ebdd5b..5d560c0c2a 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Menu private readonly BindableDouble exitingVolumeFade = new BindableDouble(1); - public const int EXIT_DELAY = 3000; + private const int exit_delay = 3000; [Resolved] private AudioManager audio { get; set; } @@ -110,7 +110,7 @@ namespace osu.Game.Screens.Menu { this.FadeIn(300); - double fadeOutTime = EXIT_DELAY; + double fadeOutTime = exit_delay; //we also handle the exit transition. if (MenuVoice.Value) seeya.Play(); @@ -151,8 +151,8 @@ namespace osu.Game.Screens.Menu .ScaleTo(1, initialMovementTime, Easing.OutQuint) .FadeIn(quick_appear, Easing.OutQuint) .Then() - .RotateTo(20, EXIT_DELAY * 1.5f) - .FadeOut(EXIT_DELAY); + .RotateTo(20, exit_delay * 1.5f) + .FadeOut(exit_delay); } } From 449e53ee6d5c57db401884b9924eb4d5158dda20 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 12:03:42 +0900 Subject: [PATCH 3314/5608] Centralise track handling --- osu.Game/Screens/Menu/IntroCircles.cs | 12 +----------- osu.Game/Screens/Menu/IntroScreen.cs | 18 +++++++++++++++++- osu.Game/Screens/Menu/IntroTriangles.cs | 13 +------------ 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroCircles.cs b/osu.Game/Screens/Menu/IntroCircles.cs index 6c643860a0..8f3b4f43c5 100644 --- a/osu.Game/Screens/Menu/IntroCircles.cs +++ b/osu.Game/Screens/Menu/IntroCircles.cs @@ -30,19 +30,11 @@ namespace osu.Game.Screens.Menu if (!resuming) { - Beatmap.Value = IntroBeatmap; - IntroBeatmap = null; - Welcome?.Play(); Scheduler.AddDelayed(delegate { - // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Menu. - if (MenuMusic.Value) - { - Track.Restart(); - Track = null; - } + StartTrack(); PrepareMenuLoad(); @@ -57,8 +49,6 @@ namespace osu.Game.Screens.Menu public override void OnSuspending(IScreen next) { - Track = null; - this.FadeOut(300); base.OnSuspending(next); } diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 5d560c0c2a..c00d105e12 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Menu protected Bindable MenuMusic; - protected Track Track; + protected Track Track { get; private set; } protected WorkingBeatmap IntroBeatmap; @@ -57,6 +57,13 @@ namespace osu.Game.Screens.Menu protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack(); + protected void StartTrack() + { + // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Menu. + if (MenuMusic.Value) + Track.Restart(); + } + [BackgroundDependencyLoader] private void load(OsuConfigManager config, SkinManager skinManager, BeatmapManager beatmaps, Framework.Game game) { @@ -136,6 +143,9 @@ namespace osu.Game.Screens.Menu if (!resuming) { + Beatmap.Value = IntroBeatmap; + IntroBeatmap = null; + logo.MoveTo(new Vector2(0.5f)); logo.ScaleTo(Vector2.One); logo.Hide(); @@ -156,6 +166,12 @@ namespace osu.Game.Screens.Menu } } + public override void OnSuspending(IScreen next) + { + base.OnSuspending(next); + Track = null; + } + private MainMenu mainMenu; protected void PrepareMenuLoad() diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index 590069ab43..08941eca37 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -55,9 +55,6 @@ namespace osu.Game.Screens.Menu if (!resuming) { - Beatmap.Value = IntroBeatmap; - IntroBeatmap = null; - PrepareMenuLoad(); LoadComponentAsync(new TrianglesIntroSequence(logo, background) @@ -70,9 +67,7 @@ namespace osu.Game.Screens.Menu AddInternal(t); Welcome?.Play(); - // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Menu. - if (MenuMusic.Value) - Track.Start(); + StartTrack(); }); } } @@ -83,12 +78,6 @@ namespace osu.Game.Screens.Menu background.FadeOut(100); } - public override void OnSuspending(IScreen next) - { - Track = null; - base.OnSuspending(next); - } - private class TrianglesIntroSequence : CompositeDrawable { private readonly OsuLogo logo; From a0bb19334219edf1f37282a95aa11893cb2fd954 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 12:04:13 +0900 Subject: [PATCH 3315/5608] Remove unnecessary beatmap storage --- osu.Game/Screens/Menu/IntroScreen.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index c00d105e12..ccb7b8ef3d 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -53,8 +53,6 @@ namespace osu.Game.Screens.Menu private LeasedBindable beatmap; - public new Bindable Beatmap => beatmap; - protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack(); protected void StartTrack() @@ -68,7 +66,7 @@ namespace osu.Game.Screens.Menu private void load(OsuConfigManager config, SkinManager skinManager, BeatmapManager beatmaps, Framework.Game game) { // prevent user from changing beatmap while the intro is still runnning. - beatmap = base.Beatmap.BeginLease(false); + beatmap = Beatmap.BeginLease(false); MenuVoice = config.GetBindable(OsuSetting.MenuVoice); MenuMusic = config.GetBindable(OsuSetting.MenuMusic); From 4ba2dccde30caac207687d4bff7bbb62a2d770cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 12:05:52 +0900 Subject: [PATCH 3316/5608] Reorder file contents --- osu.Game/Screens/Menu/IntroScreen.cs | 73 +++++++++++++--------------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index ccb7b8ef3d..c638d4f3c9 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -21,6 +21,11 @@ namespace osu.Game.Screens.Menu { public abstract class IntroScreen : StartupScreen { + /// + /// Whether we have loaded the menu previously. + /// + public bool DidLoadMenu { get; private set; } + /// /// A hash used to find the associated beatmap if already imported. /// @@ -32,35 +37,28 @@ namespace osu.Game.Screens.Menu /// protected abstract string BeatmapFile { get; } - private readonly BindableDouble exitingVolumeFade = new BindableDouble(1); - - private const int exit_delay = 3000; - - [Resolved] - private AudioManager audio { get; set; } - protected SampleChannel Welcome; - private SampleChannel seeya; - protected Bindable MenuVoice; protected Bindable MenuMusic; + protected WorkingBeatmap IntroBeatmap; + protected Track Track { get; private set; } - protected WorkingBeatmap IntroBeatmap; + private readonly BindableDouble exitingVolumeFade = new BindableDouble(1); + + private const int exit_delay = 3000; + + private SampleChannel seeya; private LeasedBindable beatmap; - protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack(); + private MainMenu mainMenu; - protected void StartTrack() - { - // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Menu. - if (MenuMusic.Value) - Track.Restart(); - } + [Resolved] + private AudioManager audio { get; set; } [BackgroundDependencyLoader] private void load(OsuConfigManager config, SkinManager skinManager, BeatmapManager beatmaps, Framework.Game game) @@ -100,16 +98,7 @@ namespace osu.Game.Screens.Menu Track = IntroBeatmap.Track; } - /// - /// Whether we have loaded the menu previously. - /// - public bool DidLoadMenu { get; private set; } - - public override bool OnExiting(IScreen next) - { - //cancel exiting if we haven't loaded the menu yet. - return !DidLoadMenu; - } + public override bool OnExiting(IScreen next) => !DidLoadMenu; public override void OnResuming(IScreen last) { @@ -131,6 +120,21 @@ namespace osu.Game.Screens.Menu base.OnResuming(last); } + public override void OnSuspending(IScreen next) + { + base.OnSuspending(next); + Track = null; + } + + protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack(); + + protected void StartTrack() + { + // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Menu. + if (MenuMusic.Value) + Track.Restart(); + } + protected override void LogoArriving(OsuLogo logo, bool resuming) { base.LogoArriving(logo, resuming); @@ -151,7 +155,7 @@ namespace osu.Game.Screens.Menu else { const int quick_appear = 350; - int initialMovementTime = logo.Alpha > 0.2f ? quick_appear : 0; + var initialMovementTime = logo.Alpha > 0.2f ? quick_appear : 0; logo.MoveTo(new Vector2(0.5f), initialMovementTime, Easing.OutQuint); @@ -164,18 +168,7 @@ namespace osu.Game.Screens.Menu } } - public override void OnSuspending(IScreen next) - { - base.OnSuspending(next); - Track = null; - } - - private MainMenu mainMenu; - - protected void PrepareMenuLoad() - { - LoadComponentAsync(mainMenu = new MainMenu()); - } + protected void PrepareMenuLoad() => LoadComponentAsync(mainMenu = new MainMenu()); protected void LoadMenu() { From b8b2ff2674001e9bc3334a7799a8931b5004e7d9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 12:07:59 +0900 Subject: [PATCH 3317/5608] Move welcome to local usages --- osu.Game/Screens/Menu/IntroCircles.cs | 7 +++++-- osu.Game/Screens/Menu/IntroScreen.cs | 2 -- osu.Game/Screens/Menu/IntroTriangles.cs | 7 +++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroCircles.cs b/osu.Game/Screens/Menu/IntroCircles.cs index 8f3b4f43c5..aa9cee969c 100644 --- a/osu.Game/Screens/Menu/IntroCircles.cs +++ b/osu.Game/Screens/Menu/IntroCircles.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Screens; using osu.Framework.Graphics; @@ -17,11 +18,13 @@ namespace osu.Game.Screens.Menu private const double delay_step_one = 2300; private const double delay_step_two = 600; + private SampleChannel welcome; + [BackgroundDependencyLoader] private void load(AudioManager audio) { if (MenuVoice.Value) - Welcome = audio.Samples.Get(@"welcome"); + welcome = audio.Samples.Get(@"welcome"); } protected override void LogoArriving(OsuLogo logo, bool resuming) @@ -30,7 +33,7 @@ namespace osu.Game.Screens.Menu if (!resuming) { - Welcome?.Play(); + welcome?.Play(); Scheduler.AddDelayed(delegate { diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index c638d4f3c9..0c192552eb 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -37,8 +37,6 @@ namespace osu.Game.Screens.Menu /// protected abstract string BeatmapFile { get; } - protected SampleChannel Welcome; - protected Bindable MenuVoice; protected Bindable MenuMusic; diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index 08941eca37..c86f1393a4 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Screens; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -40,11 +41,13 @@ namespace osu.Game.Screens.Menu private BackgroundScreenDefault background; + private SampleChannel welcome; + [BackgroundDependencyLoader] private void load(AudioManager audio) { if (MenuVoice.Value && !MenuMusic.Value) - Welcome = audio.Samples.Get(@"welcome"); + welcome = audio.Samples.Get(@"welcome"); } protected override void LogoArriving(OsuLogo logo, bool resuming) @@ -65,7 +68,7 @@ namespace osu.Game.Screens.Menu }, t => { AddInternal(t); - Welcome?.Play(); + welcome?.Play(); StartTrack(); }); From c280bee894df7e9c01c88332df579d2964f401e1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 12:08:47 +0900 Subject: [PATCH 3318/5608] Protect configuration bindables --- osu.Game/Screens/Menu/IntroScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 0c192552eb..feb472ba88 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -37,9 +37,9 @@ namespace osu.Game.Screens.Menu /// protected abstract string BeatmapFile { get; } - protected Bindable MenuVoice; + protected IBindable MenuVoice { get; private set; } - protected Bindable MenuMusic; + protected IBindable MenuMusic { get; private set; } protected WorkingBeatmap IntroBeatmap; From cbb120cd3874044673e3197a9fc78942433a3edd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 12:09:42 +0900 Subject: [PATCH 3319/5608] Switch beatmap to private --- osu.Game/Screens/Menu/IntroScreen.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index feb472ba88..f5ef839b06 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Menu protected IBindable MenuMusic { get; private set; } - protected WorkingBeatmap IntroBeatmap; + private WorkingBeatmap introBeatmap; protected Track Track { get; private set; } @@ -92,8 +92,8 @@ namespace osu.Game.Screens.Menu } } - IntroBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); - Track = IntroBeatmap.Track; + introBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); + Track = introBeatmap.Track; } public override bool OnExiting(IScreen next) => !DidLoadMenu; @@ -143,8 +143,8 @@ namespace osu.Game.Screens.Menu if (!resuming) { - Beatmap.Value = IntroBeatmap; - IntroBeatmap = null; + Beatmap.Value = introBeatmap; + introBeatmap = null; logo.MoveTo(new Vector2(0.5f)); logo.ScaleTo(Vector2.One); From 52770f803d8844c135c3cfb05a4abb1d119e087c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 12:14:53 +0900 Subject: [PATCH 3320/5608] Fix incorrect beatmap usage --- osu.Game/Screens/Menu/IntroScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index f5ef839b06..df83e98494 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -143,7 +143,7 @@ namespace osu.Game.Screens.Menu if (!resuming) { - Beatmap.Value = introBeatmap; + beatmap.Value = introBeatmap; introBeatmap = null; logo.MoveTo(new Vector2(0.5f)); From 5472029ffed6681a327eeacad42577da0306e0e6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 12:27:51 +0900 Subject: [PATCH 3321/5608] Fix editor defaulting to 0.5x playback speed --- osu.Game/Screens/Edit/Components/PlaybackControl.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 8d4ad0efa9..62d6c4648b 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; @@ -105,6 +106,8 @@ namespace osu.Game.Screens.Edit.Components TabContainer.Spacing = Vector2.Zero; tempo_values.ForEach(AddItem); + + Current.Value = tempo_values.Last(); } public class PlaybackTabItem : TabItem From 24269c0384f6ebaa5c09ce52c6a4d404bf23fb7e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 12:52:34 +0900 Subject: [PATCH 3322/5608] Fix skins not being displayed correctly in the editor --- osu.Game/Screens/Edit/Compose/ComposeScreen.cs | 13 ++++++++++++- osu.Game/Skinning/SkinProvidingContainer.cs | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index ec4dda5c23..bd7e8e44e5 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -11,6 +11,7 @@ using osu.Framework.Logging; using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Screens.Edit.Compose.Components.Timeline; +using osu.Game.Skinning; using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose @@ -115,7 +116,17 @@ namespace osu.Game.Screens.Edit.Compose return; } - composerContainer.Child = composer; + var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin); + + // the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation + // full access to all skin sources. + var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider)); + + // load the skinning hierarchy first. + // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. + composerContainer.Add( + beatmapSkinProvider.WithChild( + rulesetSkinProvider.WithChild(composer))); } } } diff --git a/osu.Game/Skinning/SkinProvidingContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs index ef7f5f381b..1c01bbf1ab 100644 --- a/osu.Game/Skinning/SkinProvidingContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -53,7 +53,7 @@ namespace osu.Game.Skinning if (AllowTextureLookup(componentName) && (sourceTexture = skin?.GetTexture(componentName)) != null) return sourceTexture; - return fallbackSource.GetTexture(componentName); + return fallbackSource?.GetTexture(componentName); } public SampleChannel GetSample(ISampleInfo sampleInfo) From 63bf8ff832ba04886bb2b60f83247f4b30e3073d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 14:23:13 +0900 Subject: [PATCH 3323/5608] Better signify under construction screens in editor --- .../Screens/Edit/Compose/ComposeScreen.cs | 41 ++-- osu.Game/Screens/Edit/Design/DesignScreen.cs | 41 +--- osu.Game/Screens/Edit/Editor.cs | 10 + osu.Game/Screens/Edit/Setup/SetupScreen.cs | 13 ++ osu.Game/Screens/Edit/Timing/SetupScreen.cs | 13 ++ osu.Game/Screens/ScreenWhiteBox.cs | 200 ++++++++++-------- 6 files changed, 169 insertions(+), 149 deletions(-) create mode 100644 osu.Game/Screens/Edit/Setup/SetupScreen.cs create mode 100644 osu.Game/Screens/Edit/Timing/SetupScreen.cs diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index bd7e8e44e5..2a99d81516 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Logging; -using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Screens.Edit.Compose.Components.Timeline; using osu.Game.Skinning; @@ -23,8 +22,6 @@ namespace osu.Game.Screens.Edit.Compose private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); - private HitObjectComposer composer; - [BackgroundDependencyLoader(true)] private void load([CanBeNull] BindableBeatDivisor beatDivisor) { @@ -107,26 +104,32 @@ namespace osu.Game.Screens.Edit.Compose return; } - composer = ruleset.CreateHitObjectComposer(); + var composer = ruleset.CreateHitObjectComposer(); - if (composer == null) + Drawable content; + + if (composer != null) { - Logger.Log($"Ruleset {ruleset.Description} doesn't support hitobject composition."); - // ExitRequested?.Invoke(); - return; + var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin); + + // the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation + // full access to all skin sources. + var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider)); + + // load the skinning hierarchy first. + // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. + content = beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(ruleset.CreateHitObjectComposer())); + } + else + { + content = new ScreenWhiteBox.UnderConstructionMessage($"{ruleset.Description}'s composer"); } - var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin); - - // the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation - // full access to all skin sources. - var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider)); - - // load the skinning hierarchy first. - // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. - composerContainer.Add( - beatmapSkinProvider.WithChild( - rulesetSkinProvider.WithChild(composer))); + LoadComponentAsync(content, _ => + { + composerContainer.Add(content); + content.FadeInFromZero(300, Easing.OutQuint); + }); } } } diff --git a/osu.Game/Screens/Edit/Design/DesignScreen.cs b/osu.Game/Screens/Edit/Design/DesignScreen.cs index 2a334e1b30..9f1fcf55b2 100644 --- a/osu.Game/Screens/Edit/Design/DesignScreen.cs +++ b/osu.Game/Screens/Edit/Design/DesignScreen.cs @@ -1,52 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics.Sprites; -using osuTK.Graphics; - namespace osu.Game.Screens.Edit.Design { public class DesignScreen : EditorScreen { public DesignScreen() { - Add(new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.35f - }, - new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.5f - }, - new Container - { - AutoSizeAxes = Axes.Both, - Padding = new MarginPadding(20), - Child = new OsuSpriteText { Text = "Design screen" } - } - } - } - } - }); + Child = new ScreenWhiteBox.UnderConstructionMessage("Design mode"); } } } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 8cc227d9be..9ebe3bc26a 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -26,6 +26,8 @@ using System.Collections.Generic; using osu.Framework; using osu.Framework.Input.Bindings; using osu.Game.Input.Bindings; +using osu.Game.Screens.Edit.Setup; +using osu.Game.Screens.Edit.Timing; using osu.Game.Users; namespace osu.Game.Screens.Edit @@ -258,6 +260,10 @@ namespace osu.Game.Screens.Edit switch (e.NewValue) { + case EditorScreenMode.SongSetup: + currentScreen = new SetupScreen(); + break; + case EditorScreenMode.Compose: currentScreen = new ComposeScreen(); break; @@ -266,6 +272,10 @@ namespace osu.Game.Screens.Edit currentScreen = new DesignScreen(); break; + case EditorScreenMode.Timing: + currentScreen = new TimingScreen(); + break; + default: currentScreen = new EditorScreen(); break; diff --git a/osu.Game/Screens/Edit/Setup/SetupScreen.cs b/osu.Game/Screens/Edit/Setup/SetupScreen.cs new file mode 100644 index 0000000000..758dbc6e16 --- /dev/null +++ b/osu.Game/Screens/Edit/Setup/SetupScreen.cs @@ -0,0 +1,13 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Screens.Edit.Setup +{ + public class SetupScreen : EditorScreen + { + public SetupScreen() + { + Child = new ScreenWhiteBox.UnderConstructionMessage("Setup mode"); + } + } +} diff --git a/osu.Game/Screens/Edit/Timing/SetupScreen.cs b/osu.Game/Screens/Edit/Timing/SetupScreen.cs new file mode 100644 index 0000000000..9ded4207e5 --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/SetupScreen.cs @@ -0,0 +1,13 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Screens.Edit.Timing +{ + public class TimingScreen : EditorScreen + { + public TimingScreen() + { + Child = new ScreenWhiteBox.UnderConstructionMessage("Timing mode"); + } + } +} diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index 6c5854d17e..e4971221c4 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -20,38 +20,17 @@ namespace osu.Game.Screens { public class ScreenWhiteBox : OsuScreen { + private readonly UnderConstructionMessage message; + private const double transition_time = 1000; protected virtual IEnumerable PossibleChildren => null; - private readonly FillFlowContainer textContainer; - private readonly Container boxContainer; - protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg2"); - public override void OnEntering(IScreen last) - { - base.OnEntering(last); - - Alpha = 0; - textContainer.Position = new Vector2(DrawSize.X / 16, 0); - - boxContainer.ScaleTo(0.2f); - boxContainer.RotateTo(-20); - - using (BeginDelayedSequence(300, true)) - { - boxContainer.ScaleTo(1, transition_time, Easing.OutElastic); - boxContainer.RotateTo(0, transition_time / 2, Easing.OutQuint); - - textContainer.MoveTo(Vector2.Zero, transition_time, Easing.OutExpo); - this.FadeIn(transition_time, Easing.OutExpo); - } - } - public override bool OnExiting(IScreen next) { - textContainer.MoveTo(new Vector2(DrawSize.X / 16, 0), transition_time, Easing.OutExpo); + message.TextContainer.MoveTo(new Vector2(DrawSize.X / 16, 0), transition_time, Easing.OutExpo); this.FadeOut(transition_time, Easing.OutExpo); return base.OnExiting(next); @@ -61,7 +40,7 @@ namespace osu.Game.Screens { base.OnSuspending(next); - textContainer.MoveTo(new Vector2(-(DrawSize.X / 16), 0), transition_time, Easing.OutExpo); + message.TextContainer.MoveTo(new Vector2(-(DrawSize.X / 16), 0), transition_time, Easing.OutExpo); this.FadeOut(transition_time, Easing.OutExpo); } @@ -69,7 +48,7 @@ namespace osu.Game.Screens { base.OnResuming(last); - textContainer.MoveTo(Vector2.Zero, transition_time, Easing.OutExpo); + message.TextContainer.MoveTo(Vector2.Zero, transition_time, Easing.OutExpo); this.FadeIn(transition_time, Easing.OutExpo); } @@ -79,65 +58,7 @@ namespace osu.Game.Screens InternalChildren = new Drawable[] { - boxContainer = new Container - { - Size = new Vector2(0.3f), - RelativeSizeAxes = Axes.Both, - CornerRadius = 20, - Masking = true, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - - Colour = getColourFor(GetType()), - Alpha = 0.2f, - Blending = BlendingParameters.Additive, - }, - textContainer = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new SpriteIcon - { - Icon = FontAwesome.Solid.UniversalAccess, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Size = new Vector2(50), - }, - new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = GetType().Name, - Colour = getColourFor(GetType()).Lighten(0.8f), - Font = OsuFont.GetFont(size: 50), - }, - new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = "is not yet ready for use!", - Font = OsuFont.GetFont(size: 20), - }, - new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = "please check back a bit later.", - Font = OsuFont.GetFont(size: 14), - }, - } - }, - } - }, + message = new UnderConstructionMessage(GetType().Name), childModeButtons = new FillFlowContainer { Direction = FillDirection.Vertical, @@ -155,24 +76,24 @@ namespace osu.Game.Screens childModeButtons.Add(new ChildModeButton { Text = $@"{t.Name}", - BackgroundColour = getColourFor(t), - HoverColour = getColourFor(t).Lighten(0.2f), + BackgroundColour = getColourFor(t.Name), + HoverColour = getColourFor(t.Name).Lighten(0.2f), Action = delegate { this.Push(Activator.CreateInstance(t) as Screen); } }); } } } - private Color4 getColourFor(Type type) + private static Color4 getColourFor(object type) { - int hash = type.Name.GetHashCode(); + int hash = type.GetHashCode(); byte r = (byte)MathHelper.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); byte g = (byte)MathHelper.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); byte b = (byte)MathHelper.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); return new Color4(r, g, b, 255); } - public class ChildModeButton : TwoLayerButton + private class ChildModeButton : TwoLayerButton { public ChildModeButton() { @@ -181,5 +102,104 @@ namespace osu.Game.Screens Origin = Anchor.BottomRight; } } + + public class UnderConstructionMessage : CompositeDrawable + { + public FillFlowContainer TextContainer { get; } + + private readonly Container boxContainer; + + public UnderConstructionMessage(string name) + { + RelativeSizeAxes = Axes.Both; + Size = new Vector2(0.3f); + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + var colour = getColourFor(name); + + InternalChildren = new Drawable[] + { + boxContainer = new Container + { + CornerRadius = 20, + Masking = true, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + + Colour = colour, + Alpha = 0.2f, + Blending = BlendingParameters.Additive, + }, + TextContainer = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new SpriteIcon + { + Icon = FontAwesome.Solid.UniversalAccess, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Size = new Vector2(50), + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = name, + Colour = colour.Lighten(0.8f), + Font = OsuFont.GetFont(size: 36), + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "is not yet ready for use!", + Font = OsuFont.GetFont(size: 20), + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "please check back a bit later.", + Font = OsuFont.GetFont(size: 14), + }, + } + }, + } + }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + TextContainer.Position = new Vector2(DrawSize.X / 16, 0); + + boxContainer.Hide(); + boxContainer.ScaleTo(0.2f); + boxContainer.RotateTo(-20); + + using (BeginDelayedSequence(300, true)) + { + boxContainer.ScaleTo(1, transition_time, Easing.OutElastic); + boxContainer.RotateTo(0, transition_time / 2, Easing.OutQuint); + + TextContainer.MoveTo(Vector2.Zero, transition_time, Easing.OutExpo); + boxContainer.FadeIn(transition_time, Easing.OutExpo); + } + } + } } } From 3e904b4838b9169b80b0f6fc2381f0de6a47a6cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 14:37:56 +0900 Subject: [PATCH 3324/5608] Fix naming of file --- osu.Game/Screens/Edit/Timing/{SetupScreen.cs => TimingScreen.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game/Screens/Edit/Timing/{SetupScreen.cs => TimingScreen.cs} (100%) diff --git a/osu.Game/Screens/Edit/Timing/SetupScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs similarity index 100% rename from osu.Game/Screens/Edit/Timing/SetupScreen.cs rename to osu.Game/Screens/Edit/Timing/TimingScreen.cs From 4e026b163ccd15556945a8d769cad3b5c0a8ac34 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 15:03:48 +0900 Subject: [PATCH 3325/5608] Don't resume playback when user has paused and track hasn't changed --- osu.Game/Screens/Select/SongSelect.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 04a686f481..6c5f64ed6c 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -581,14 +581,24 @@ namespace osu.Game.Screens.Select beatmap.Track.Looping = true; } + private readonly WeakReference lastTrack = new WeakReference(null); + + /// + /// Ensures some music is playing for the current track. + /// Will resume playback from a manual user pause if the track has changed. + /// private void ensurePlayingSelected() { Track track = Beatmap.Value.Track; + bool isNewTrack = !lastTrack.TryGetTarget(out var last) || last != track; + track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - if (!track.IsRunning) + if (!track.IsRunning && (music?.IsUserPaused != true || isNewTrack)) track.Restart(); + + lastTrack.SetTarget(track); } private void onBeatmapSetAdded(BeatmapSetInfo s) => Carousel.UpdateBeatmapSet(s); From f284d096b75fc63349f08fa0385ce8709e79f214 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 16:37:47 +0900 Subject: [PATCH 3326/5608] Fix ignored song select test --- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 263eada07c..be054495cc 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -128,12 +128,10 @@ namespace osu.Game.Tests.Visual.SongSelect } [Test] - [Ignore("needs fixing")] public void TestImportUnderDifferentRuleset() { createSongSelect(); - changeRuleset(2); - addRulesetImportStep(0); + addRulesetImportStep(2); AddUntilStep("no selection", () => songSelect.Carousel.SelectedBeatmap == null); } From 8ebccfe31fe098807ed355bf171c990557d6642f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 16:37:34 +0900 Subject: [PATCH 3327/5608] Add comprehensive audio state tests --- .../SongSelect/TestScenePlaySongSelect.cs | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 263eada07c..5584de5484 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -16,6 +16,7 @@ using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; @@ -34,6 +35,8 @@ namespace osu.Game.Tests.Visual.SongSelect private RulesetStore rulesets; + private MusicController music; + private WorkingBeatmap defaultBeatmap; public override IReadOnlyList RequiredTypes => new[] @@ -79,6 +82,11 @@ namespace osu.Game.Tests.Visual.SongSelect Dependencies.Cache(rulesets = new RulesetStore(ContextFactory)); Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, defaultBeatmap = Beatmap.Default)); + Dependencies.Cache(music = new MusicController()); + + // required to get bindables attached + Add(music); + Beatmap.SetDefault(); Dependencies.Cache(config = new OsuConfigManager(LocalStorage)); @@ -93,6 +101,57 @@ namespace osu.Game.Tests.Visual.SongSelect manager?.Delete(manager.GetAllUsableBeatmapSets()); }); + [Test] + public void TestAudioResuming() + { + createSongSelect(); + + addRulesetImportStep(0); + addRulesetImportStep(0); + + checkMusicPlaying(true); + AddStep("select first", () => songSelect.Carousel.SelectBeatmap(songSelect.Carousel.BeatmapSets.First().Beatmaps.First())); + checkMusicPlaying(true); + + AddStep("manual pause", () => music.TogglePause()); + checkMusicPlaying(false); + AddStep("select next difficulty", () => songSelect.Carousel.SelectNext(skipDifficulties: false)); + checkMusicPlaying(false); + + AddStep("select next set", () => songSelect.Carousel.SelectNext()); + checkMusicPlaying(true); + } + + [TestCase(false)] + [TestCase(true)] + public void TestAudioRemainsCorrectOnRulesetChange(bool rulesetsInSameBeatmap) + { + createSongSelect(); + + // start with non-osu! to avoid convert confusion + changeRuleset(1); + + if (rulesetsInSameBeatmap) + AddStep("import multi-ruleset map", () => + { + var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray(); + manager.Import(createTestBeatmapSet(0, usableRulesets)).Wait(); + }); + else + { + addRulesetImportStep(1); + addRulesetImportStep(0); + } + + checkMusicPlaying(true); + + AddStep("manual pause", () => music.TogglePause()); + checkMusicPlaying(false); + + changeRuleset(0); + checkMusicPlaying(!rulesetsInSameBeatmap); + } + [Test] public void TestDummy() { @@ -224,6 +283,9 @@ namespace osu.Game.Tests.Visual.SongSelect private static int importId; private int getImportId() => ++importId; + private void checkMusicPlaying(bool playing) => + AddUntilStep($"music {(playing ? "" : "not ")}playing", () => music.IsPlaying == playing); + private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => Mods.Value = mods); private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id)); From b09d9b7e1f761e9070c0f3aa3629928729c1c7a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 17:56:56 +0900 Subject: [PATCH 3328/5608] Add todo in slider tail to avoid confusion --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index 23c5494cf5..42bf5e4d21 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -40,6 +40,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindValueChanged(_ => updatePosition()); pathBindable.BindValueChanged(_ => updatePosition(), true); + + // TODO: This has no drawable content. Support for skins should be added. } protected override void CheckForResult(bool userTriggered, double timeOffset) From 4446a2972c7c36e48099b99fc597587156cf50c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Oct 2019 18:08:05 +0900 Subject: [PATCH 3329/5608] Move WaveContainer test out of editor namespace --- .../Visual/{Editor => UserInterface}/TestSceneWaveContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Tests/Visual/{Editor => UserInterface}/TestSceneWaveContainer.cs (97%) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneWaveContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs similarity index 97% rename from osu.Game.Tests/Visual/Editor/TestSceneWaveContainer.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs index de19727251..5b130b9224 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneWaveContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; -namespace osu.Game.Tests.Visual.Editor +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestSceneWaveContainer : OsuTestScene From 08d043f44715b02f1f65ecdc59fe21ce6190ec2a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 8 Oct 2019 18:57:03 +0900 Subject: [PATCH 3330/5608] Move selection relative to the hitobject start positions --- .../Blueprints/ManiaSelectionBlueprint.cs | 2 +- .../Edit/ManiaSelectionHandler.cs | 23 ++++---- .../Edit/OsuSelectionHandler.cs | 5 +- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 11 +++- .../Compose/Components/BlueprintContainer.cs | 9 +++- .../Compose/Components/SelectionDragEvent.cs | 53 +++++++++++++++++++ .../Compose/Components/SelectionHandler.cs | 2 +- 7 files changed, 87 insertions(+), 18 deletions(-) create mode 100644 osu.Game/Screens/Edit/Compose/Components/SelectionDragEvent.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index d3c12b1944..cc50459a0c 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints public Vector2 ScreenSpaceDragPosition { get; private set; } public Vector2 DragPosition { get; private set; } - protected new DrawableManiaHitObject HitObject => (DrawableManiaHitObject)base.HitObject; + public new DrawableManiaHitObject HitObject => (DrawableManiaHitObject)base.HitObject; protected IClock EditorClock { get; private set; } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 6f49c7f0c4..389837b059 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -3,7 +3,6 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; @@ -31,11 +30,14 @@ namespace osu.Game.Rulesets.Mania.Edit editorClock = clock; } - public override void HandleDrag(SelectionBlueprint blueprint, DragEvent dragEvent) + public override void HandleDrag(SelectionBlueprint blueprint, SelectionDragEvent dragEvent) { - adjustOrigins((ManiaSelectionBlueprint)blueprint); + var maniaBlueprint = (ManiaSelectionBlueprint)blueprint; + int lastColumn = maniaBlueprint.HitObject.HitObject.Column; + + adjustOrigins(maniaBlueprint); performDragMovement(dragEvent); - performColumnMovement(dragEvent); + performColumnMovement(lastColumn, dragEvent); base.HandleDrag(blueprint, dragEvent); } @@ -62,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Edit b.HitObject.Y += movementDelta; } - private void performDragMovement(DragEvent dragEvent) + private void performDragMovement(SelectionDragEvent dragEvent) { foreach (var b in SelectedBlueprints) { @@ -72,7 +74,7 @@ namespace osu.Game.Rulesets.Mania.Edit // Using the hitobject position is required since AdjustPosition can be invoked multiple times per frame // without the position having been updated by the parenting ScrollingHitObjectContainer - hitObject.Y += dragEvent.Delta.Y; + hitObject.Y += dragEvent.InstantDragDelta.Y; float targetPosition; @@ -94,14 +96,13 @@ namespace osu.Game.Rulesets.Mania.Edit } } - private void performColumnMovement(DragEvent dragEvent) + private void performColumnMovement(int lastColumn, SelectionDragEvent dragEvent) { - var lastColumn = composer.ColumnAt(dragEvent.ScreenSpaceLastMousePosition); - var currentColumn = composer.ColumnAt(dragEvent.ScreenSpaceMousePosition); - if (lastColumn == null || currentColumn == null) + var currentColumn = composer.ColumnAt(dragEvent.ScreenSpaceDragPosition); + if (currentColumn == null) return; - int columnDelta = currentColumn.Index - lastColumn.Index; + int columnDelta = currentColumn.Index - lastColumn; if (columnDelta == 0) return; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index 1ab1219ab0..4a0e88889b 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose.Components; @@ -11,7 +10,7 @@ namespace osu.Game.Rulesets.Osu.Edit { public class OsuSelectionHandler : SelectionHandler { - public override void HandleDrag(SelectionBlueprint blueprint, DragEvent dragEvent) + public override void HandleDrag(SelectionBlueprint blueprint, SelectionDragEvent dragEvent) { foreach (var h in SelectedHitObjects.OfType()) { @@ -21,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Edit continue; } - h.Position += dragEvent.Delta; + h.Position += dragEvent.InstantDragDelta; } base.HandleDrag(blueprint, dragEvent); diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 0f77b8d584..aa0dd1cc25 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -45,6 +45,11 @@ namespace osu.Game.Rulesets.Edit /// public readonly DrawableHitObject HitObject; + /// + /// The screen-space position of when a drag was started. + /// + public Vector2 ScreenSpaceDragStartPosition { get; private set; } + protected override bool ShouldBeAlive => (HitObject.IsAlive && HitObject.IsPresent) || State == SelectionState.Selected; public override bool HandlePositionalInput => ShouldBeAlive; public override bool RemoveWhenNotAlive => false; @@ -131,7 +136,11 @@ namespace osu.Game.Rulesets.Edit return base.OnClick(e); } - protected override bool OnDragStart(DragStartEvent e) => true; + protected override bool OnDragStart(DragStartEvent e) + { + ScreenSpaceDragStartPosition = HitObject.ToScreenSpace(HitObject.OriginPosition); + return true; + } protected override bool OnDrag(DragEvent e) { diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index d96d88c2b9..3286be4be6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -216,7 +216,14 @@ namespace osu.Game.Screens.Edit.Compose.Components private void onSelectionRequested(SelectionBlueprint blueprint, InputState state) => selectionHandler.HandleSelectionRequested(blueprint, state); - private void onDragRequested(SelectionBlueprint blueprint, DragEvent dragEvent) => selectionHandler.HandleDrag(blueprint, dragEvent); + private void onDragRequested(SelectionBlueprint blueprint, DragEvent dragEvent) + { + var dragPosition = blueprint.ScreenSpaceDragStartPosition + dragEvent.ScreenSpaceMousePosition - dragEvent.ScreenSpaceMouseDownPosition; + + // Todo: Snap dragPosition + + selectionHandler.HandleDrag(blueprint, new SelectionDragEvent(blueprint, blueprint.ScreenSpaceDragStartPosition, dragPosition)); + } protected override void Dispose(bool isDisposing) { diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionDragEvent.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionDragEvent.cs new file mode 100644 index 0000000000..8e00e8c30c --- /dev/null +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionDragEvent.cs @@ -0,0 +1,53 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Edit; +using osuTK; + +namespace osu.Game.Screens.Edit.Compose.Components +{ + /// + /// An event which occurs when a is dragged. + /// + public class SelectionDragEvent + { + /// + /// The dragged . + /// + public readonly SelectionBlueprint DraggedBlueprint; + + /// + /// The screen-space position of the hitobject at the start of the drag. + /// + public readonly Vector2 ScreenSpaceDragStartPosition; + + /// + /// The new screen-space position of the hitobject at the current drag point. + /// + public readonly Vector2 ScreenSpaceDragPosition; + + /// + /// The distance between and the hitobject's current position, in the coordinate-space of the hitobject's parent. + /// + /// + /// This does not use and does not represent the cumulative drag distance. + /// + public readonly Vector2 InstantDragDelta; + + public SelectionDragEvent(SelectionBlueprint blueprint, Vector2 screenSpaceDragStartPosition, Vector2 screenSpaceDragPosition) + { + DraggedBlueprint = blueprint; + ScreenSpaceDragStartPosition = screenSpaceDragStartPosition; + ScreenSpaceDragPosition = screenSpaceDragPosition; + + InstantDragDelta = toLocalSpace(ScreenSpaceDragPosition) - DraggedBlueprint.HitObject.Position; + } + + /// + /// Converts a screen-space position into the coordinate space of the hitobject's parents. + /// + /// The screen-space position. + /// The position in the coordinate space of the hitobject's parent. + private Vector2 toLocalSpace(Vector2 screenSpacePosition) => DraggedBlueprint.HitObject.Parent.ToLocalSpace(screenSpacePosition); + } +} diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 11e649168f..3fb06c8ee8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -69,7 +69,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// The that received the drag event. /// The drag event. - public virtual void HandleDrag(SelectionBlueprint blueprint, DragEvent dragEvent) + public virtual void HandleDrag(SelectionBlueprint blueprint, SelectionDragEvent dragEvent) { } From 8b661e624d25334b7c1b67db6b6c83c138a51ec1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 8 Oct 2019 19:08:23 +0900 Subject: [PATCH 3331/5608] Remove drag from class/method namings + refactor --- .../Edit/ManiaSelectionHandler.cs | 19 ++++--- .../Edit/OsuSelectionHandler.cs | 7 ++- .../Compose/Components/BlueprintContainer.cs | 2 +- .../Compose/Components/MoveSelectionEvent.cs | 53 +++++++++++++++++++ .../Compose/Components/SelectionDragEvent.cs | 53 ------------------- .../Compose/Components/SelectionHandler.cs | 7 ++- 6 files changed, 69 insertions(+), 72 deletions(-) create mode 100644 osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs delete mode 100644 osu.Game/Screens/Edit/Compose/Components/SelectionDragEvent.cs diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 389837b059..f576c43e52 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -4,7 +4,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Timing; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.UI; @@ -30,16 +29,16 @@ namespace osu.Game.Rulesets.Mania.Edit editorClock = clock; } - public override void HandleDrag(SelectionBlueprint blueprint, SelectionDragEvent dragEvent) + public override void HandleMovement(MoveSelectionEvent moveEvent) { - var maniaBlueprint = (ManiaSelectionBlueprint)blueprint; + var maniaBlueprint = (ManiaSelectionBlueprint)moveEvent.Blueprint; int lastColumn = maniaBlueprint.HitObject.HitObject.Column; adjustOrigins(maniaBlueprint); - performDragMovement(dragEvent); - performColumnMovement(lastColumn, dragEvent); + performDragMovement(moveEvent); + performColumnMovement(lastColumn, moveEvent); - base.HandleDrag(blueprint, dragEvent); + base.HandleMovement(moveEvent); } /// @@ -64,7 +63,7 @@ namespace osu.Game.Rulesets.Mania.Edit b.HitObject.Y += movementDelta; } - private void performDragMovement(SelectionDragEvent dragEvent) + private void performDragMovement(MoveSelectionEvent moveEvent) { foreach (var b in SelectedBlueprints) { @@ -74,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.Edit // Using the hitobject position is required since AdjustPosition can be invoked multiple times per frame // without the position having been updated by the parenting ScrollingHitObjectContainer - hitObject.Y += dragEvent.InstantDragDelta.Y; + hitObject.Y += moveEvent.InstantDelta.Y; float targetPosition; @@ -96,9 +95,9 @@ namespace osu.Game.Rulesets.Mania.Edit } } - private void performColumnMovement(int lastColumn, SelectionDragEvent dragEvent) + private void performColumnMovement(int lastColumn, MoveSelectionEvent moveEvent) { - var currentColumn = composer.ColumnAt(dragEvent.ScreenSpaceDragPosition); + var currentColumn = composer.ColumnAt(moveEvent.ScreenSpacePosition); if (currentColumn == null) return; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index 4a0e88889b..472267eb66 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose.Components; @@ -10,7 +9,7 @@ namespace osu.Game.Rulesets.Osu.Edit { public class OsuSelectionHandler : SelectionHandler { - public override void HandleDrag(SelectionBlueprint blueprint, SelectionDragEvent dragEvent) + public override void HandleMovement(MoveSelectionEvent moveEvent) { foreach (var h in SelectedHitObjects.OfType()) { @@ -20,10 +19,10 @@ namespace osu.Game.Rulesets.Osu.Edit continue; } - h.Position += dragEvent.InstantDragDelta; + h.Position += moveEvent.InstantDelta; } - base.HandleDrag(blueprint, dragEvent); + base.HandleMovement(moveEvent); } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 3286be4be6..593d70b24f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -222,7 +222,7 @@ namespace osu.Game.Screens.Edit.Compose.Components // Todo: Snap dragPosition - selectionHandler.HandleDrag(blueprint, new SelectionDragEvent(blueprint, blueprint.ScreenSpaceDragStartPosition, dragPosition)); + selectionHandler.HandleMovement(new MoveSelectionEvent(blueprint, blueprint.ScreenSpaceDragStartPosition, dragPosition)); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs b/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs new file mode 100644 index 0000000000..a75226d2bc --- /dev/null +++ b/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs @@ -0,0 +1,53 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Edit; +using osuTK; + +namespace osu.Game.Screens.Edit.Compose.Components +{ + /// + /// An event which occurs when a is moved. + /// + public class MoveSelectionEvent + { + /// + /// The that triggered this . + /// + public readonly SelectionBlueprint Blueprint; + + /// + /// The starting screen-space position of the hitobject. + /// + public readonly Vector2 ScreenSpaceStartPosition; + + /// + /// The expected screen-space position of the hitobject at the current cursor position. + /// + public readonly Vector2 ScreenSpacePosition; + + /// + /// The distance between and the hitobject's current position, in the coordinate-space of the hitobject's parent. + /// + /// + /// This does not use and does not represent the cumulative movement distance. + /// + public readonly Vector2 InstantDelta; + + public MoveSelectionEvent(SelectionBlueprint blueprint, Vector2 screenSpaceStartPosition, Vector2 screenSpacePosition) + { + Blueprint = blueprint; + ScreenSpaceStartPosition = screenSpaceStartPosition; + ScreenSpacePosition = screenSpacePosition; + + InstantDelta = toLocalSpace(ScreenSpacePosition) - Blueprint.HitObject.Position; + } + + /// + /// Converts a screen-space position into the coordinate space of the hitobject's parents. + /// + /// The screen-space position. + /// The position in the coordinate space of the hitobject's parent. + private Vector2 toLocalSpace(Vector2 screenSpacePosition) => Blueprint.HitObject.Parent.ToLocalSpace(screenSpacePosition); + } +} diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionDragEvent.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionDragEvent.cs deleted file mode 100644 index 8e00e8c30c..0000000000 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionDragEvent.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Rulesets.Edit; -using osuTK; - -namespace osu.Game.Screens.Edit.Compose.Components -{ - /// - /// An event which occurs when a is dragged. - /// - public class SelectionDragEvent - { - /// - /// The dragged . - /// - public readonly SelectionBlueprint DraggedBlueprint; - - /// - /// The screen-space position of the hitobject at the start of the drag. - /// - public readonly Vector2 ScreenSpaceDragStartPosition; - - /// - /// The new screen-space position of the hitobject at the current drag point. - /// - public readonly Vector2 ScreenSpaceDragPosition; - - /// - /// The distance between and the hitobject's current position, in the coordinate-space of the hitobject's parent. - /// - /// - /// This does not use and does not represent the cumulative drag distance. - /// - public readonly Vector2 InstantDragDelta; - - public SelectionDragEvent(SelectionBlueprint blueprint, Vector2 screenSpaceDragStartPosition, Vector2 screenSpaceDragPosition) - { - DraggedBlueprint = blueprint; - ScreenSpaceDragStartPosition = screenSpaceDragStartPosition; - ScreenSpaceDragPosition = screenSpaceDragPosition; - - InstantDragDelta = toLocalSpace(ScreenSpaceDragPosition) - DraggedBlueprint.HitObject.Position; - } - - /// - /// Converts a screen-space position into the coordinate space of the hitobject's parents. - /// - /// The screen-space position. - /// The position in the coordinate space of the hitobject's parent. - private Vector2 toLocalSpace(Vector2 screenSpacePosition) => DraggedBlueprint.HitObject.Parent.ToLocalSpace(screenSpacePosition); - } -} diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 3fb06c8ee8..c9e862d99e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -65,11 +65,10 @@ namespace osu.Game.Screens.Edit.Compose.Components #region User Input Handling /// - /// Handles the selected s being dragged. + /// Handles the selected s being moved. /// - /// The that received the drag event. - /// The drag event. - public virtual void HandleDrag(SelectionBlueprint blueprint, SelectionDragEvent dragEvent) + /// The move event. + public virtual void HandleMovement(MoveSelectionEvent moveEvent) { } From c1db11fa0612622cce5182a987847dc96701e66b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 8 Oct 2019 19:24:58 +0900 Subject: [PATCH 3332/5608] More removal of "drag" --- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 6 +++--- .../Screens/Edit/Compose/Components/BlueprintContainer.cs | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index aa0dd1cc25..838984b223 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -46,9 +46,9 @@ namespace osu.Game.Rulesets.Edit public readonly DrawableHitObject HitObject; /// - /// The screen-space position of when a drag was started. + /// The screen-space position of prior to handling a movement event. /// - public Vector2 ScreenSpaceDragStartPosition { get; private set; } + internal Vector2 ScreenSpaceMovementStartPosition { get; private set; } protected override bool ShouldBeAlive => (HitObject.IsAlive && HitObject.IsPresent) || State == SelectionState.Selected; public override bool HandlePositionalInput => ShouldBeAlive; @@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Edit protected override bool OnDragStart(DragStartEvent e) { - ScreenSpaceDragStartPosition = HitObject.ToScreenSpace(HitObject.OriginPosition); + ScreenSpaceMovementStartPosition = HitObject.ToScreenSpace(HitObject.OriginPosition); return true; } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 593d70b24f..2de5ecf633 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -218,11 +218,9 @@ namespace osu.Game.Screens.Edit.Compose.Components private void onDragRequested(SelectionBlueprint blueprint, DragEvent dragEvent) { - var dragPosition = blueprint.ScreenSpaceDragStartPosition + dragEvent.ScreenSpaceMousePosition - dragEvent.ScreenSpaceMouseDownPosition; + var movePosition = blueprint.ScreenSpaceMovementStartPosition + dragEvent.ScreenSpaceMousePosition - dragEvent.ScreenSpaceMouseDownPosition; - // Todo: Snap dragPosition - - selectionHandler.HandleMovement(new MoveSelectionEvent(blueprint, blueprint.ScreenSpaceDragStartPosition, dragPosition)); + selectionHandler.HandleMovement(new MoveSelectionEvent(blueprint, blueprint.ScreenSpaceMovementStartPosition, movePosition)); } protected override void Dispose(bool isDisposing) From 179656788dd87caae95c35c3e8e4b0372106bcbd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 8 Oct 2019 19:27:59 +0900 Subject: [PATCH 3333/5608] Remove unnecessary method --- .../Edit/Compose/Components/MoveSelectionEvent.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs b/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs index a75226d2bc..13945381bb 100644 --- a/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs +++ b/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs @@ -40,14 +40,7 @@ namespace osu.Game.Screens.Edit.Compose.Components ScreenSpaceStartPosition = screenSpaceStartPosition; ScreenSpacePosition = screenSpacePosition; - InstantDelta = toLocalSpace(ScreenSpacePosition) - Blueprint.HitObject.Position; + InstantDelta = Blueprint.HitObject.Parent.ToLocalSpace(ScreenSpacePosition) - Blueprint.HitObject.Position; } - - /// - /// Converts a screen-space position into the coordinate space of the hitobject's parents. - /// - /// The screen-space position. - /// The position in the coordinate space of the hitobject's parent. - private Vector2 toLocalSpace(Vector2 screenSpacePosition) => Blueprint.HitObject.Parent.ToLocalSpace(screenSpacePosition); } } From 4b1a40dabaebadb49d07cbc077d71709714fe6d8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 13:31:49 +0300 Subject: [PATCH 3334/5608] Implement temp fix to get the actual message --- osu.Game/Online/API/Requests/Responses/Comment.cs | 6 ++++++ osu.Game/Overlays/CommentsContainer.cs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index e4b66ddeee..ba71faa843 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -76,5 +76,11 @@ namespace osu.Game.Online.API.Requests.Responses public bool IsTopLevel { get; set; } public bool IsDeleted { get; set; } + + public string GetMessage() + { + //temporary fix until HTML parsing will be implemented + return MessageHTML.Remove(MessageHTML.LastIndexOf("

")).Substring(65); + } } } diff --git a/osu.Game/Overlays/CommentsContainer.cs b/osu.Game/Overlays/CommentsContainer.cs index b22fefb3de..1b4bbee6a1 100644 --- a/osu.Game/Overlays/CommentsContainer.cs +++ b/osu.Game/Overlays/CommentsContainer.cs @@ -107,7 +107,7 @@ namespace osu.Game.Overlays { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Text = comment.MessageHTML, + Text = comment.GetMessage(), }, new Container { From 59b2f028289521f6eef68456662ca9255913287d Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Tue, 8 Oct 2019 18:34:09 +0800 Subject: [PATCH 3335/5608] initial implementation of customizable mods --- osu.Game/Overlays/Mods/ModControlSection.cs | 56 ++++++++++++++++++++ osu.Game/Overlays/Mods/ModSelectOverlay.cs | 58 +++++++++++++++++++++ osu.Game/Rulesets/Mods/IModHasSettings.cs | 15 ++++++ osu.Game/Rulesets/Mods/Mod.cs | 2 +- 4 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Overlays/Mods/ModControlSection.cs create mode 100644 osu.Game/Rulesets/Mods/IModHasSettings.cs diff --git a/osu.Game/Overlays/Mods/ModControlSection.cs b/osu.Game/Overlays/Mods/ModControlSection.cs new file mode 100644 index 0000000000..df6f4d15b0 --- /dev/null +++ b/osu.Game/Overlays/Mods/ModControlSection.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.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Mods; +using osuTK; + +namespace osu.Game.Overlays.Mods +{ + public class ModControlSection : Container + { + protected FillFlowContainer FlowContent; + protected override Container Content => FlowContent; + + public readonly Mod Mod; + + public ModControlSection(Mod mod) + { + Mod = mod; + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + FlowContent = new FillFlowContainer + { + Margin = new MarginPadding { Top = 30 }, + Spacing = new Vector2(0, 5), + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + }; + + if (Mod is IModHasSettings modHasSettings) + AddRange(modHasSettings.CreateControls()); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AddRangeInternal(new Drawable[] + { + new OsuSpriteText + { + Text = Mod.Name, + Font = OsuFont.GetFont(weight: FontWeight.Bold), + Colour = colours.Yellow, + }, + FlowContent + }); + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 9ff320841a..5493080964 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -31,6 +31,7 @@ namespace osu.Game.Overlays.Mods public class ModSelectOverlay : WaveOverlayContainer { protected readonly TriangleButton DeselectAllButton; + protected readonly TriangleButton CustomizeButton; protected readonly TriangleButton CloseButton; protected readonly OsuSpriteText MultiplierLabel; @@ -42,6 +43,10 @@ namespace osu.Game.Overlays.Mods protected readonly FillFlowContainer ModSectionsContainer; + protected readonly FillFlowContainer ModSettingsContent; + + protected readonly Container ModSettingsContainer; + protected readonly Bindable> SelectedMods = new Bindable>(Array.Empty()); protected readonly IBindable Ruleset = new Bindable(); @@ -226,6 +231,16 @@ namespace osu.Game.Overlays.Mods Right = 20 } }, + CustomizeButton = new TriangleButton + { + Width = 180, + Text = "Customization", + Action = () => ModSettingsContainer.Alpha = ModSettingsContainer.Alpha == 1 ? 0 : 1, + Margin = new MarginPadding + { + Right = 20 + } + }, CloseButton = new TriangleButton { Width = 180, @@ -271,6 +286,36 @@ namespace osu.Game.Overlays.Mods }, }, }, + ModSettingsContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Width = 0.25f, + Alpha = 0, + X = -100, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = new Color4(0, 0, 0, 192) + }, + new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = ModSettingsContent = new FillFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(0f, 10f), + Padding = new MarginPadding(20), + } + } + } + } }; } @@ -284,10 +329,23 @@ namespace osu.Game.Overlays.Mods Ruleset.BindTo(ruleset); if (mods != null) SelectedMods.BindTo(mods); + SelectedMods.ValueChanged += updateModSettings; + sampleOn = audio.Samples.Get(@"UI/check-on"); sampleOff = audio.Samples.Get(@"UI/check-off"); } + private void updateModSettings(ValueChangedEvent> selectedMods) + { + var added = selectedMods.NewValue.Except(selectedMods.OldValue).FirstOrDefault(); + var removed = selectedMods.OldValue.Except(selectedMods.NewValue).FirstOrDefault(); + + if (added is IModHasSettings) + ModSettingsContent.Add(new ModControlSection(added)); + else if (removed is IModHasSettings) + ModSettingsContent.Remove(ModSettingsContent.Children.Where(section => section.Mod == removed).FirstOrDefault()); + } + public void DeselectAll() { foreach (var section in ModSectionsContainer.Children) diff --git a/osu.Game/Rulesets/Mods/IModHasSettings.cs b/osu.Game/Rulesets/Mods/IModHasSettings.cs new file mode 100644 index 0000000000..004279f71d --- /dev/null +++ b/osu.Game/Rulesets/Mods/IModHasSettings.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 osu.Framework.Graphics; + +namespace osu.Game.Rulesets.Mods +{ + /// + /// An interface for mods that allows user control over it's properties. + /// + public interface IModHasSettings + { + Drawable[] CreateControls(); + } +} diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 023d37497a..1c280c820d 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Mods /// /// Creates a copy of this initialised to a default state. /// - public virtual Mod CreateCopy() => (Mod)Activator.CreateInstance(GetType()); + public virtual Mod CreateCopy() => (Mod)MemberwiseClone(); public bool Equals(IMod other) => GetType() == other?.GetType(); } From 801b5b474e300343bafc0defc0a8818e3516919d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 13:45:13 +0300 Subject: [PATCH 3336/5608] Add a User property to the comment for easy access --- .../API/Requests/Responses/APIComments.cs | 20 ++++++++++++++++- .../Online/API/Requests/Responses/Comment.cs | 3 +++ osu.Game/Overlays/CommentsContainer.cs | 22 +++++++++++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIComments.cs b/osu.Game/Online/API/Requests/Responses/APIComments.cs index af7650e512..86bbf0358a 100644 --- a/osu.Game/Online/API/Requests/Responses/APIComments.cs +++ b/osu.Game/Online/API/Requests/Responses/APIComments.cs @@ -24,8 +24,26 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"included_comments")] public List IncludedComments { get; set; } + private List users; + [JsonProperty(@"users")] - public List Users { get; set; } + public List Users + { + get => users; + set + { + users = value; + + value.ForEach(u => + { + Comments.ForEach(c => + { + if (c.UserId == u.Id) + c.User = u; + }); + }); + } + } [JsonProperty(@"total")] public int Total { get; set; } diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index ba71faa843..46212dd50f 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; +using osu.Game.Users; using System; namespace osu.Game.Online.API.Requests.Responses @@ -27,6 +28,8 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"user_id")] public long UserId { get; set; } + public User User { get; set; } + [JsonProperty(@"message")] public string Message { get; set; } diff --git a/osu.Game/Overlays/CommentsContainer.cs b/osu.Game/Overlays/CommentsContainer.cs index 1b4bbee6a1..c871810d8a 100644 --- a/osu.Game/Overlays/CommentsContainer.cs +++ b/osu.Game/Overlays/CommentsContainer.cs @@ -103,11 +103,29 @@ namespace osu.Game.Overlays Height = 70, Children = new Drawable[] { - new SpriteText + new FillFlowContainer { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Text = comment.GetMessage(), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 3), + Children = new[] + { + new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = $"user: {comment.User.Username}", + }, + new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = $"message: {comment.GetMessage()}", + }, + } }, new Container { From 9375ef5eeae16c551b9e950becbb148a1a782dfd Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Tue, 8 Oct 2019 19:42:15 +0800 Subject: [PATCH 3337/5608] clear settings controls when changing rulesets --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 5493080964..a344bcc254 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -330,6 +330,7 @@ namespace osu.Game.Overlays.Mods if (mods != null) SelectedMods.BindTo(mods); SelectedMods.ValueChanged += updateModSettings; + Ruleset.ValueChanged += _ => ModSettingsContent.Clear(); sampleOn = audio.Samples.Get(@"UI/check-on"); sampleOff = audio.Samples.Get(@"UI/check-off"); From 1c89841949e025fe693aab73a97dd9a93c78b85b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 14:51:12 +0300 Subject: [PATCH 3338/5608] Move all the logic to it's own namespace --- .../Online/TestSceneCommentsContainer.cs | 2 +- .../{ => Comments}/CommentsContainer.cs | 67 +++---------- osu.Game/Overlays/Comments/DrawableComment.cs | 99 +++++++++++++++++++ 3 files changed, 116 insertions(+), 52 deletions(-) rename osu.Game/Overlays/{ => Comments}/CommentsContainer.cs (73%) create mode 100644 osu.Game/Overlays/Comments/DrawableComment.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index bf4117189a..e6f9582910 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -4,10 +4,10 @@ using System; using System.Collections.Generic; using NUnit.Framework; -using osu.Game.Overlays; using osu.Game.Online.API.Requests; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; +using osu.Game.Overlays.Comments; namespace osu.Game.Tests.Visual.Online { diff --git a/osu.Game/Overlays/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs similarity index 73% rename from osu.Game/Overlays/CommentsContainer.cs rename to osu.Game/Overlays/Comments/CommentsContainer.cs index c871810d8a..60b22428f0 100644 --- a/osu.Game/Overlays/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -13,7 +13,7 @@ using osu.Framework.Graphics.Sprites; using osuTK; using osu.Game.Online.API.Requests.Responses; -namespace osu.Game.Overlays +namespace osu.Game.Overlays.Comments { public class CommentsContainer : CompositeDrawable { @@ -90,59 +90,24 @@ namespace osu.Game.Overlays foreach (var c in response.Comments) { - if (!c.IsDeleted) - createDrawableComment(c); + if (!c.IsDeleted && c.IsTopLevel) + content.AddRange(new Drawable[] + { + new DrawableComment(c), + new Container + { + RelativeSizeAxes = Axes.X, + Height = 1, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Gray1, + } + } + }); } } - private void createDrawableComment(Comment comment) - { - content.Add(new Container - { - RelativeSizeAxes = Axes.X, - Height = 70, - Children = new Drawable[] - { - new FillFlowContainer - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 3), - Children = new[] - { - new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = $"user: {comment.User.Username}", - }, - new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = $"message: {comment.GetMessage()}", - }, - } - }, - new Container - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.X, - Height = 1, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Gray1, - } - } - } - }); - } - [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs new file mode 100644 index 0000000000..bbb804dc5b --- /dev/null +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -0,0 +1,99 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Framework.Graphics.Sprites; +using osuTK; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Users.Drawables; +using osu.Game.Graphics.Containers; +using osu.Game.Utils; + +namespace osu.Game.Overlays.Comments +{ + public class DrawableComment : CompositeDrawable + { + private const int avatar_size = 40; + private const int margin = 10; + + public DrawableComment(Comment comment) + { + LinkFlowContainer username; + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + InternalChild = new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding(margin), + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new Drawable[] + { + new UpdateableAvatar(comment.User) + { + Size = new Vector2(avatar_size), + Margin = new MarginPadding { Horizontal = margin }, + Masking = true, + CornerRadius = avatar_size / 2, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Spacing = new Vector2(0, 2), + Children = new Drawable[] + { + username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + }, + new TextFlowContainer(s => s.Font = OsuFont.GetFont(size: 18)) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Text = comment.GetMessage() + } + } + } + }, + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + }, + new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: 12), + Text = HumanizerUtils.Humanize(comment.CreatedAt) + } + } + } + }; + + username.AddUserLink(comment.User); + } + } +} From 2564214a72b70007368fa3c5763c407fab2192ac Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 15:01:18 +0300 Subject: [PATCH 3339/5608] Fix some padding issues with the big comments --- osu.Game/Overlays/Comments/DrawableComment.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index bbb804dc5b..6f3d92c7fd 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -54,21 +54,16 @@ namespace osu.Game.Overlays.Comments { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Top = margin / 2 }, Spacing = new Vector2(0, 2), Children = new Drawable[] { username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, }, - new TextFlowContainer(s => s.Font = OsuFont.GetFont(size: 18)) + new TextFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Text = comment.GetMessage() From 451a7342ce7459ae42562521e549af8e7e8a1d5b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 15:39:03 +0300 Subject: [PATCH 3340/5608] Parse child comments --- .../API/Requests/Responses/APIComments.cs | 22 +++- .../Online/API/Requests/Responses/Comment.cs | 3 + .../Overlays/Comments/CommentsContainer.cs | 4 +- osu.Game/Overlays/Comments/DrawableComment.cs | 106 +++++++++++------- 4 files changed, 92 insertions(+), 43 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIComments.cs b/osu.Game/Online/API/Requests/Responses/APIComments.cs index 86bbf0358a..9a12fb613e 100644 --- a/osu.Game/Online/API/Requests/Responses/APIComments.cs +++ b/osu.Game/Online/API/Requests/Responses/APIComments.cs @@ -9,8 +9,28 @@ namespace osu.Game.Online.API.Requests.Responses { public class APIComments { + private List comments; + [JsonProperty(@"comments")] - public List Comments { get; set; } + public List Comments + { + get => comments; + set + { + comments = value; + comments.ForEach(child => + { + if (child.ParentId != null) + { + comments.ForEach(parent => + { + if (parent.Id == child.ParentId) + parent.ChildComments.Add(child); + }); + } + }); + } + } [JsonProperty(@"has_more")] public bool HasMore { get; set; } diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 46212dd50f..cdc3c3204b 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -4,6 +4,7 @@ using Newtonsoft.Json; using osu.Game.Users; using System; +using System.Collections.Generic; namespace osu.Game.Online.API.Requests.Responses { @@ -25,6 +26,8 @@ namespace osu.Game.Online.API.Requests.Responses } } + public List ChildComments = new List(); + [JsonProperty(@"user_id")] public long UserId { get; set; } diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 60b22428f0..d02e74a5a4 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -17,6 +17,8 @@ namespace osu.Game.Overlays.Comments { public class CommentsContainer : CompositeDrawable { + private const float separator_height = 1.5f; + private readonly CommentableType type; private readonly long id; @@ -97,7 +99,7 @@ namespace osu.Game.Overlays.Comments new Container { RelativeSizeAxes = Axes.X, - Height = 1, + Height = separator_height, Child = new Box { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 6f3d92c7fd..53366be878 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -17,78 +17,102 @@ namespace osu.Game.Overlays.Comments { private const int avatar_size = 40; private const int margin = 10; + private const int child_margin = 20; public DrawableComment(Comment comment) { LinkFlowContainer username; + FillFlowContainer childCommentsContainer; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - InternalChild = new GridContainer + InternalChild = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Margin = new MarginPadding(margin), - ColumnDimensions = new[] + Direction = FillDirection.Vertical, + Children = new Drawable[] { - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize) - }, - Content = new[] - { - new Drawable[] + new GridContainer { - new UpdateableAvatar(comment.User) + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding(margin), + ColumnDimensions = new[] { - Size = new Vector2(avatar_size), - Margin = new MarginPadding { Horizontal = margin }, - Masking = true, - CornerRadius = avatar_size / 2, + new Dimension(GridSizeMode.AutoSize), + new Dimension(), }, - new FillFlowContainer + RowDimensions = new[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = margin / 2 }, - Spacing = new Vector2(0, 2), - Children = new Drawable[] + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new Drawable[] { - username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) + new UpdateableAvatar(comment.User) { - AutoSizeAxes = Axes.Both, + Size = new Vector2(avatar_size), + Margin = new MarginPadding { Horizontal = margin }, + Masking = true, + CornerRadius = avatar_size / 2, }, - new TextFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) + new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Text = comment.GetMessage() + Margin = new MarginPadding { Top = margin / 2 }, + Spacing = new Vector2(0, 2), + Children = new Drawable[] + { + username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) + { + AutoSizeAxes = Axes.Both, + }, + new TextFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Text = comment.GetMessage() + } + } + } + }, + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + }, + new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: 12), + Text = HumanizerUtils.Humanize(comment.CreatedAt) } } } }, - new Drawable[] + childCommentsContainer = new FillFlowContainer { - new Container - { - RelativeSizeAxes = Axes.Both, - }, - new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: 12), - Text = HumanizerUtils.Humanize(comment.CreatedAt) - } + Margin = new MarginPadding { Left = child_margin }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical } } }; username.AddUserLink(comment.User); + + comment.ChildComments.ForEach(c => + { + if (!c.IsDeleted) + childCommentsContainer.Add(new DrawableComment(c)); + }); } } } From 9c7e403cf8ca62b83ded5505c030b77f8ee0a81b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 16:00:34 +0300 Subject: [PATCH 3341/5608] Implement replies button --- osu.Game/Overlays/Comments/DrawableComment.cs | 98 +++++++++++++++++-- 1 file changed, 90 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 53366be878..9879995b00 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -10,6 +10,8 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Users.Drawables; using osu.Game.Graphics.Containers; using osu.Game.Utils; +using osu.Framework.Input.Events; +using System; namespace osu.Game.Overlays.Comments { @@ -18,11 +20,39 @@ namespace osu.Game.Overlays.Comments private const int avatar_size = 40; private const int margin = 10; private const int child_margin = 20; + private const int duration = 200; + + private bool childExpanded = true; + + public bool ChildExpanded + { + get => childExpanded; + set + { + if (childExpanded == value) + return; + + childExpanded = value; + + childCommentsVisibilityContainer.ClearTransforms(); + + if (childExpanded) + childCommentsVisibilityContainer.AutoSizeAxes = Axes.Y; + else + { + childCommentsVisibilityContainer.AutoSizeAxes = Axes.None; + childCommentsVisibilityContainer.ResizeHeightTo(0, duration, Easing.OutQuint); + } + } + } + + private readonly Container childCommentsVisibilityContainer; public DrawableComment(Comment comment) { LinkFlowContainer username; FillFlowContainer childCommentsContainer; + RepliesButton replies; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -86,22 +116,40 @@ namespace osu.Game.Overlays.Comments { RelativeSizeAxes = Axes.Both, }, - new SpriteText + new FillFlowContainer { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: 12), - Text = HumanizerUtils.Humanize(comment.CreatedAt) + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + Children = new Drawable[] + { + new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: 12), + Text = HumanizerUtils.Humanize(comment.CreatedAt) + }, + replies = new RepliesButton(comment.RepliesCount), + } } } } }, - childCommentsContainer = new FillFlowContainer + childCommentsVisibilityContainer = new Container { - Margin = new MarginPadding { Left = child_margin }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical + AutoSizeDuration = duration, + AutoSizeEasing = Easing.OutQuint, + Masking = true, + Child = childCommentsContainer = new FillFlowContainer + { + Margin = new MarginPadding { Left = child_margin }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical + } } } }; @@ -113,6 +161,40 @@ namespace osu.Game.Overlays.Comments if (!c.IsDeleted) childCommentsContainer.Add(new DrawableComment(c)); }); + + replies.Action += expanded => ChildExpanded = expanded; + } + + private class RepliesButton : Container + { + private readonly SpriteText text; + private bool expanded; + private readonly int count; + + public Action Action; + + public RepliesButton(int count) + { + this.count = count; + + AutoSizeAxes = Axes.Both; + Alpha = count == 0 ? 0 : 1; + Child = text = new SpriteText + { + Font = OsuFont.GetFont(size: 12), + Text = $@"[-] replies ({count})" + }; + + expanded = true; + } + + protected override bool OnClick(ClickEvent e) + { + text.Text = $@"{(expanded ? "[+]" : "[-]")} replies ({count})"; + expanded = !expanded; + Action?.Invoke(expanded); + return base.OnClick(e); + } } } } From 3f8fecbc5034d2b601ea6e6bc3643e25b8e13fc6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 16:04:52 +0300 Subject: [PATCH 3342/5608] Adjust spacing --- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 9879995b00..f3d8d2f577 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -120,7 +120,7 @@ namespace osu.Game.Overlays.Comments { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - Spacing = new Vector2(5, 0), + Spacing = new Vector2(10, 0), Children = new Drawable[] { new SpriteText From 000e4a563cf4389d9fc86683838ece2e8251230b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 19:09:02 +0300 Subject: [PATCH 3343/5608] Parse parent comments --- .../API/Requests/Responses/APIComments.cs | 3 ++ .../Online/API/Requests/Responses/Comment.cs | 2 + osu.Game/Overlays/Comments/DrawableComment.cs | 45 ++++++++++++++++++- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIComments.cs b/osu.Game/Online/API/Requests/Responses/APIComments.cs index 9a12fb613e..f454d4052f 100644 --- a/osu.Game/Online/API/Requests/Responses/APIComments.cs +++ b/osu.Game/Online/API/Requests/Responses/APIComments.cs @@ -25,7 +25,10 @@ namespace osu.Game.Online.API.Requests.Responses comments.ForEach(parent => { if (parent.Id == child.ParentId) + { parent.ChildComments.Add(child); + child.ParentComment = parent; + } }); } }); diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index cdc3c3204b..e5d3f14d27 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -28,6 +28,8 @@ namespace osu.Game.Online.API.Requests.Responses public List ChildComments = new List(); + public Comment ParentComment { get; set; } + [JsonProperty(@"user_id")] public long UserId { get; set; } diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index f3d8d2f577..dea14f22c8 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -12,6 +12,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Utils; using osu.Framework.Input.Events; using System; +using osu.Framework.Graphics.Cursor; namespace osu.Game.Overlays.Comments { @@ -97,9 +98,19 @@ namespace osu.Game.Overlays.Comments Spacing = new Vector2(0, 2), Children = new Drawable[] { - username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) + new FillFlowContainer { AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7, 0), + Children = new Drawable[] + { + username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) + { + AutoSizeAxes = Axes.Both, + }, + new ParentUsername(comment) + } }, new TextFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) { @@ -196,5 +207,37 @@ namespace osu.Game.Overlays.Comments return base.OnClick(e); } } + + private class ParentUsername : FillFlowContainer, IHasTooltip + { + private const int spacing = 3; + + public string TooltipText => comment.ParentComment?.GetMessage() ?? ""; + + private readonly Comment comment; + + public ParentUsername(Comment comment) + { + this.comment = comment; + + AutoSizeAxes = Axes.Both; + Direction = FillDirection.Horizontal; + Spacing = new Vector2(spacing, 0); + Alpha = comment.ParentId == null ? 0 : 1; + Children = new Drawable[] + { + new SpriteIcon + { + Icon = FontAwesome.Solid.Reply, + Size = new Vector2(14), + }, + new SpriteText + { + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), + Text = comment.ParentComment?.User?.Username + } + }; + } + } } } From 341702b91d084207316711e6f43e33afa3fadcc6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 19:18:46 +0300 Subject: [PATCH 3344/5608] Use Bindable for expansion logic --- osu.Game/Overlays/Comments/DrawableComment.cs | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index dea14f22c8..bf24cbb70d 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -11,8 +11,8 @@ using osu.Game.Users.Drawables; using osu.Game.Graphics.Containers; using osu.Game.Utils; using osu.Framework.Input.Events; -using System; using osu.Framework.Graphics.Cursor; +using osu.Framework.Bindables; namespace osu.Game.Overlays.Comments { @@ -23,29 +23,7 @@ namespace osu.Game.Overlays.Comments private const int child_margin = 20; private const int duration = 200; - private bool childExpanded = true; - - public bool ChildExpanded - { - get => childExpanded; - set - { - if (childExpanded == value) - return; - - childExpanded = value; - - childCommentsVisibilityContainer.ClearTransforms(); - - if (childExpanded) - childCommentsVisibilityContainer.AutoSizeAxes = Axes.Y; - else - { - childCommentsVisibilityContainer.AutoSizeAxes = Axes.None; - childCommentsVisibilityContainer.ResizeHeightTo(0, duration, Easing.OutQuint); - } - } - } + private readonly BindableBool childExpanded = new BindableBool(true); private readonly Container childCommentsVisibilityContainer; @@ -53,7 +31,6 @@ namespace osu.Game.Overlays.Comments { LinkFlowContainer username; FillFlowContainer childCommentsContainer; - RepliesButton replies; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -141,7 +118,8 @@ namespace osu.Game.Overlays.Comments Font = OsuFont.GetFont(size: 12), Text = HumanizerUtils.Humanize(comment.CreatedAt) }, - replies = new RepliesButton(comment.RepliesCount), + new RepliesButton(comment.RepliesCount) + { Expanded = { BindTarget = childExpanded } }, } } } @@ -172,17 +150,33 @@ namespace osu.Game.Overlays.Comments if (!c.IsDeleted) childCommentsContainer.Add(new DrawableComment(c)); }); + } - replies.Action += expanded => ChildExpanded = expanded; + protected override void LoadComplete() + { + childExpanded.BindValueChanged(onChildExpandedChanged, true); + base.LoadComplete(); + } + + private void onChildExpandedChanged(ValueChangedEvent expanded) + { + childCommentsVisibilityContainer.ClearTransforms(); + + if (expanded.NewValue) + childCommentsVisibilityContainer.AutoSizeAxes = Axes.Y; + else + { + childCommentsVisibilityContainer.AutoSizeAxes = Axes.None; + childCommentsVisibilityContainer.ResizeHeightTo(0, duration, Easing.OutQuint); + } } private class RepliesButton : Container { private readonly SpriteText text; - private bool expanded; private readonly int count; - public Action Action; + public readonly BindableBool Expanded = new BindableBool(true); public RepliesButton(int count) { @@ -193,17 +187,23 @@ namespace osu.Game.Overlays.Comments Child = text = new SpriteText { Font = OsuFont.GetFont(size: 12), - Text = $@"[-] replies ({count})" }; + } - expanded = true; + protected override void LoadComplete() + { + Expanded.BindValueChanged(onExpandedChanged, true); + base.LoadComplete(); + } + + private void onExpandedChanged(ValueChangedEvent expanded) + { + text.Text = $@"{(expanded.NewValue ? "[+]" : "[-]")} replies ({count})"; } protected override bool OnClick(ClickEvent e) { - text.Text = $@"{(expanded ? "[+]" : "[-]")} replies ({count})"; - expanded = !expanded; - Action?.Invoke(expanded); + Expanded.Value = !Expanded.Value; return base.OnClick(e); } } From 4230b00110768023bd1cf9d0e1fc098d5b273224 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 19:22:23 +0300 Subject: [PATCH 3345/5608] Rename APIComments to APICommentsController --- osu.Game/Online/API/Requests/GetCommentsRequest.cs | 2 +- .../Responses/{APIComments.cs => APICommentsController.cs} | 2 +- osu.Game/Overlays/Comments/CommentsContainer.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename osu.Game/Online/API/Requests/Responses/{APIComments.cs => APICommentsController.cs} (98%) diff --git a/osu.Game/Online/API/Requests/GetCommentsRequest.cs b/osu.Game/Online/API/Requests/GetCommentsRequest.cs index 279a1905da..5a2b61b4d0 100644 --- a/osu.Game/Online/API/Requests/GetCommentsRequest.cs +++ b/osu.Game/Online/API/Requests/GetCommentsRequest.cs @@ -7,7 +7,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { - public class GetCommentsRequest : APIRequest + public class GetCommentsRequest : APIRequest { private readonly long id; private readonly int page; diff --git a/osu.Game/Online/API/Requests/Responses/APIComments.cs b/osu.Game/Online/API/Requests/Responses/APICommentsController.cs similarity index 98% rename from osu.Game/Online/API/Requests/Responses/APIComments.cs rename to osu.Game/Online/API/Requests/Responses/APICommentsController.cs index f454d4052f..cf2e5e8a35 100644 --- a/osu.Game/Online/API/Requests/Responses/APIComments.cs +++ b/osu.Game/Online/API/Requests/Responses/APICommentsController.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; namespace osu.Game.Online.API.Requests.Responses { - public class APIComments + public class APICommentsController { private List comments; diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index d02e74a5a4..abbd2cdbde 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -86,7 +86,7 @@ namespace osu.Game.Overlays.Comments api.Queue(request); } - private void onSuccess(APIComments response) + private void onSuccess(APICommentsController response) { content.Clear(); From 35cfb16c8d21594237251fbf63d4fd69491efc3f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 19:56:43 +0300 Subject: [PATCH 3346/5608] Implement VotePill component --- osu.Game/Overlays/Comments/DrawableComment.cs | 55 +++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index bf24cbb70d..ce60d905ad 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -13,6 +13,8 @@ using osu.Game.Utils; using osu.Framework.Input.Events; using osu.Framework.Graphics.Cursor; using osu.Framework.Bindables; +using osu.Framework.Graphics.Shapes; +using osuTK.Graphics; namespace osu.Game.Overlays.Comments { @@ -60,12 +62,28 @@ namespace osu.Game.Overlays.Comments { new Drawable[] { - new UpdateableAvatar(comment.User) + new FillFlowContainer { - Size = new Vector2(avatar_size), + AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Horizontal = margin }, - Masking = true, - CornerRadius = avatar_size / 2, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + Children = new Drawable[] + { + new VotePill(comment.VotesCount) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new UpdateableAvatar(comment.User) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(avatar_size), + Masking = true, + CornerRadius = avatar_size / 2, + }, + } }, new FillFlowContainer { @@ -239,5 +257,34 @@ namespace osu.Game.Overlays.Comments }; } } + + private class VotePill : CircularContainer + { + private const int height = 20; + private const int margin = 10; + + public VotePill(int count) + { + AutoSizeAxes = Axes.X; + Height = height; + Masking = true; + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black + }, + new SpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Horizontal = margin }, + Font = OsuFont.GetFont(size: 14), + Text = $"+{count}" + } + }; + } + } } } From b6047e46135cd099a1d21ebcd492d38cac7f5a3b Mon Sep 17 00:00:00 2001 From: HoLLy-HaCKeR Date: Tue, 8 Oct 2019 19:39:54 +0200 Subject: [PATCH 3347/5608] Move OsuCursor resize logic to OsuCursorContainer --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs | 36 ++----------------- .../UI/Cursor/OsuCursorContainer.cs | 34 ++++++++++++++++-- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index 41a02deaca..0aa8661fd3 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -2,14 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps; -using osu.Game.Configuration; using osu.Game.Rulesets.Osu.Skinning; using osu.Game.Skinning; using osuTK; @@ -23,12 +20,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private bool cursorExpand; - private Bindable cursorScale; - private Bindable autoCursorScale; - private readonly IBindable beatmap = new Bindable(); - private Container expandTarget; - private Drawable scaleTarget; public OsuCursor() { @@ -43,43 +35,19 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor } [BackgroundDependencyLoader] - private void load(OsuConfigManager config, IBindable beatmap) + private void load() { InternalChild = expandTarget = new Container { RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, Anchor = Anchor.Centre, - Child = scaleTarget = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.Cursor), _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling) + Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.Cursor), _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling) { Origin = Anchor.Centre, Anchor = Anchor.Centre, } }; - - this.beatmap.BindTo(beatmap); - this.beatmap.ValueChanged += _ => calculateScale(); - - cursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); - cursorScale.ValueChanged += _ => calculateScale(); - - autoCursorScale = config.GetBindable(OsuSetting.AutoCursorSize); - autoCursorScale.ValueChanged += _ => calculateScale(); - - calculateScale(); - } - - private void calculateScale() - { - float scale = cursorScale.Value; - - if (autoCursorScale.Value && beatmap.Value != null) - { - // if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier. - scale *= 1f - 0.7f * (1f + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY; - } - - scaleTarget.Scale = new Vector2(scale); } private const float pressed_scale = 1.2f; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 6dbdf0114d..e24ab3a7cb 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -8,6 +8,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Bindings; +using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.UI; using osu.Game.Skinning; @@ -27,6 +29,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly Drawable cursorTrail; + private Bindable cursorScale; + private Bindable autoCursorScale; + private readonly IBindable beatmap = new Bindable(); + public OsuCursorContainer() { InternalChild = fadeContainer = new Container @@ -37,9 +43,33 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor } [BackgroundDependencyLoader(true)] - private void load(OsuRulesetConfigManager config) + private void load(OsuConfigManager config, OsuRulesetConfigManager rulesetConfig, IBindable beatmap) { - config?.BindWith(OsuRulesetSetting.ShowCursorTrail, showTrail); + rulesetConfig?.BindWith(OsuRulesetSetting.ShowCursorTrail, showTrail); + + this.beatmap.BindTo(beatmap); + this.beatmap.ValueChanged += _ => calculateScale(); + + cursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); + cursorScale.ValueChanged += _ => calculateScale(); + + autoCursorScale = config.GetBindable(OsuSetting.AutoCursorSize); + autoCursorScale.ValueChanged += _ => calculateScale(); + + calculateScale(); + } + + private void calculateScale() + { + float scale = cursorScale.Value; + + if (autoCursorScale.Value && beatmap.Value != null) + { + // if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier. + scale *= 1f - 0.7f * (1f + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY; + } + + ActiveCursor.Scale = new Vector2(scale); } protected override void LoadComplete() From 1c22fb485fa2cc8b75f230c5a5ddcd40fa090534 Mon Sep 17 00:00:00 2001 From: HoLLy-HaCKeR Date: Tue, 8 Oct 2019 19:40:46 +0200 Subject: [PATCH 3348/5608] Scale cursortrail along with cursor --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index e24ab3a7cb..371c2983fc 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor scale *= 1f - 0.7f * (1f + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY; } - ActiveCursor.Scale = new Vector2(scale); + ActiveCursor.Scale = cursorTrail.Scale = new Vector2(scale); } protected override void LoadComplete() From 9ab309fc0ef387e2226991c7f010e75f52fe1a19 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 20:44:01 +0300 Subject: [PATCH 3349/5608] Use bold font for replies button --- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index ce60d905ad..ce78dfec9f 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -204,7 +204,7 @@ namespace osu.Game.Overlays.Comments Alpha = count == 0 ? 0 : 1; Child = text = new SpriteText { - Font = OsuFont.GetFont(size: 12), + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), }; } From b9ad079bf8b077ae7a9aa53bdb2da1e6dcc0993e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 20:57:55 +0300 Subject: [PATCH 3350/5608] Move CommentsHeader to it's own file --- .../Online/TestSceneCommentsContainer.cs | 2 + .../Overlays/Comments/CommentsContainer.cs | 56 --------------- osu.Game/Overlays/Comments/CommentsHeader.cs | 69 +++++++++++++++++++ 3 files changed, 71 insertions(+), 56 deletions(-) create mode 100644 osu.Game/Overlays/Comments/CommentsHeader.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index e6f9582910..c8d16bdf21 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -17,6 +17,8 @@ namespace osu.Game.Tests.Visual.Online public override IReadOnlyList RequiredTypes => new[] { typeof(CommentsContainer), + typeof(CommentsHeader), + typeof(DrawableComment), }; protected override bool UseOnlineAPI => true; diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index abbd2cdbde..f8783952d1 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -9,8 +9,6 @@ using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; -using osu.Framework.Graphics.Sprites; -using osuTK; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Comments @@ -115,59 +113,5 @@ namespace osu.Game.Overlays.Comments { background.Colour = colours.Gray3; } - - private class CommentsHeader : CompositeDrawable - { - private const int height = 40; - private const int spacing = 10; - private const int padding = 50; - - public readonly Bindable Sort = new Bindable(); - - private readonly Box background; - - public CommentsHeader() - { - RelativeSizeAxes = Axes.X; - Height = height; - AddRangeInternal(new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = padding }, - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(spacing, 0), - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Children = new Drawable[] - { - new SpriteText - { - Font = OsuFont.GetFont(size: 14), - Text = @"Sort by" - } - } - } - } - } - }); - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = colours.Gray4; - } - } } } diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs new file mode 100644 index 0000000000..9ebd257a5d --- /dev/null +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -0,0 +1,69 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers; +using osu.Game.Online.API.Requests; +using osu.Framework.Graphics; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Framework.Graphics.Sprites; +using osuTK; + +namespace osu.Game.Overlays.Comments +{ + public class CommentsHeader : CompositeDrawable + { + private const int height = 40; + private const int spacing = 10; + private const int padding = 50; + + public readonly Bindable Sort = new Bindable(); + + private readonly Box background; + + public CommentsHeader() + { + RelativeSizeAxes = Axes.X; + Height = height; + AddRangeInternal(new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = padding }, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(spacing, 0), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Children = new Drawable[] + { + new SpriteText + { + Font = OsuFont.GetFont(size: 14), + Text = @"Sort by" + } + } + } + } + } + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.Gray4; + } + } +} From 574170124cff05070833415e324f77a2e5fe88ef Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 21:38:19 +0300 Subject: [PATCH 3351/5608] Implement HeaderButton component --- .../Online/TestSceneCommentsContainer.cs | 1 + osu.Game/Overlays/Comments/CommentsHeader.cs | 63 ++++++++++++++++- osu.Game/Overlays/Comments/HeaderButton.cs | 68 +++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Overlays/Comments/HeaderButton.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index c8d16bdf21..f5205552e0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -19,6 +19,7 @@ namespace osu.Game.Tests.Visual.Online typeof(CommentsContainer), typeof(CommentsHeader), typeof(DrawableComment), + typeof(HeaderButton), }; protected override bool UseOnlineAPI => true; diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index 9ebd257a5d..b9dee7935e 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Framework.Graphics.Sprites; using osuTK; +using osu.Framework.Input.Events; namespace osu.Game.Overlays.Comments { @@ -18,8 +19,10 @@ namespace osu.Game.Overlays.Comments private const int height = 40; private const int spacing = 10; private const int padding = 50; + private const int text_size = 14; public readonly Bindable Sort = new Bindable(); + public readonly BindableBool ShowDeleted = new BindableBool(); private readonly Box background; @@ -50,10 +53,16 @@ namespace osu.Game.Overlays.Comments { new SpriteText { - Font = OsuFont.GetFont(size: 14), + Font = OsuFont.GetFont(size: text_size), Text = @"Sort by" } } + }, + new ShowDeletedButton + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Checked = { BindTarget = ShowDeleted } } } } @@ -65,5 +74,57 @@ namespace osu.Game.Overlays.Comments { background.Colour = colours.Gray4; } + + private class ShowDeletedButton : HeaderButton + { + private const int spacing = 5; + + public readonly BindableBool Checked = new BindableBool(); + + private readonly SpriteIcon checkboxIcon; + + public ShowDeletedButton() + { + Add(new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(spacing, 0), + Children = new Drawable[] + { + checkboxIcon = new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(10), + }, + new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: text_size), + Text = @"Show deleted" + } + }, + }); + } + + protected override void LoadComplete() + { + Checked.BindValueChanged(onCheckedChanged, true); + base.LoadComplete(); + } + + private void onCheckedChanged(ValueChangedEvent isChecked) + { + checkboxIcon.Icon = isChecked.NewValue ? FontAwesome.Solid.CheckSquare : FontAwesome.Regular.Square; + } + + protected override bool OnClick(ClickEvent e) + { + Checked.Value = !Checked.Value; + return base.OnClick(e); + } + } } } diff --git a/osu.Game/Overlays/Comments/HeaderButton.cs b/osu.Game/Overlays/Comments/HeaderButton.cs new file mode 100644 index 0000000000..db8ea92a1a --- /dev/null +++ b/osu.Game/Overlays/Comments/HeaderButton.cs @@ -0,0 +1,68 @@ +// 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.Containers; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Overlays.Comments +{ + public class HeaderButton : Container + { + private const int height = 20; + private const int corner_radius = 3; + private const int margin = 10; + private const int duration = 200; + + protected override Container Content => content; + + private readonly Box background; + private readonly Container content; + + public HeaderButton() + { + AutoSizeAxes = Axes.X; + Height = height; + Masking = true; + CornerRadius = corner_radius; + AddRangeInternal(new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + }, + content = new Container + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Horizontal = margin } + }, + new HoverClickSounds(), + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.Gray6; + } + + protected override bool OnHover(HoverEvent e) + { + background.FadeIn(duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + background.FadeOut(duration, Easing.OutQuint); + } + } +} From 29b0eacc821b5091c0251d6066e2e52296d8c279 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 8 Oct 2019 22:46:42 +0300 Subject: [PATCH 3352/5608] Implement SortSelector component --- .../Online/TestSceneCommentsContainer.cs | 1 + .../Online/API/Requests/GetCommentsRequest.cs | 2 +- .../Online/API/Requests/Responses/Comment.cs | 2 +- .../Overlays/Comments/CommentsContainer.cs | 3 +- osu.Game/Overlays/Comments/CommentsHeader.cs | 8 ++ osu.Game/Overlays/Comments/DrawableComment.cs | 9 ++- osu.Game/Overlays/Comments/HeaderButton.cs | 8 +- osu.Game/Overlays/Comments/SortSelector.cs | 75 +++++++++++++++++++ 8 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 osu.Game/Overlays/Comments/SortSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index f5205552e0..7fbe9d7e8b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -20,6 +20,7 @@ namespace osu.Game.Tests.Visual.Online typeof(CommentsHeader), typeof(DrawableComment), typeof(HeaderButton), + typeof(SortSelector) }; protected override bool UseOnlineAPI => true; diff --git a/osu.Game/Online/API/Requests/GetCommentsRequest.cs b/osu.Game/Online/API/Requests/GetCommentsRequest.cs index 5a2b61b4d0..02a36f7aa2 100644 --- a/osu.Game/Online/API/Requests/GetCommentsRequest.cs +++ b/osu.Game/Online/API/Requests/GetCommentsRequest.cs @@ -28,7 +28,7 @@ namespace osu.Game.Online.API.Requests req.AddParameter("commentable_type", type.ToString().Underscore().ToLowerInvariant()); req.AddParameter("commentable_id", id.ToString()); - req.AddParameter("sort", sort.ToString()); + req.AddParameter("sort", sort.ToString().ToLowerInvariant()); req.AddParameter("page", page.ToString()); return req; diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index e5d3f14d27..30aca3c2ea 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -31,7 +31,7 @@ namespace osu.Game.Online.API.Requests.Responses public Comment ParentComment { get; set; } [JsonProperty(@"user_id")] - public long UserId { get; set; } + public long? UserId { get; set; } public User User { get; set; } diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index f8783952d1..5be1b6c1c4 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -79,6 +79,7 @@ namespace osu.Game.Overlays.Comments private void getComments() { request?.Cancel(); + content.Clear(); request = new GetCommentsRequest(type, id, Sort.Value); request.Success += onSuccess; api.Queue(request); @@ -86,8 +87,6 @@ namespace osu.Game.Overlays.Comments private void onSuccess(APICommentsController response) { - content.Clear(); - foreach (var c in response.Comments) { if (!c.IsDeleted && c.IsTopLevel) diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index b9dee7935e..90a6f44d6b 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -53,8 +53,16 @@ namespace osu.Game.Overlays.Comments { new SpriteText { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(size: text_size), Text = @"Sort by" + }, + new SortSelector + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Current = { BindTarget = Sort } } } }, diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index ce78dfec9f..41b30513a1 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -161,7 +161,14 @@ namespace osu.Game.Overlays.Comments } }; - username.AddUserLink(comment.User); + if (comment.UserId == null) + { + username.AddText(comment.LegacyName); + } + else + { + username.AddUserLink(comment.User); + } comment.ChildComments.ForEach(c => { diff --git a/osu.Game/Overlays/Comments/HeaderButton.cs b/osu.Game/Overlays/Comments/HeaderButton.cs index db8ea92a1a..e3729b3b05 100644 --- a/osu.Game/Overlays/Comments/HeaderButton.cs +++ b/osu.Game/Overlays/Comments/HeaderButton.cs @@ -55,14 +55,18 @@ namespace osu.Game.Overlays.Comments protected override bool OnHover(HoverEvent e) { - background.FadeIn(duration, Easing.OutQuint); + FadeInBackground(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - background.FadeOut(duration, Easing.OutQuint); + FadeOutBackground(); } + + public void FadeInBackground() => background.FadeIn(duration, Easing.OutQuint); + + public void FadeOutBackground() => background.FadeOut(duration, Easing.OutQuint); } } diff --git a/osu.Game/Overlays/Comments/SortSelector.cs b/osu.Game/Overlays/Comments/SortSelector.cs new file mode 100644 index 0000000000..4425145c3e --- /dev/null +++ b/osu.Game/Overlays/Comments/SortSelector.cs @@ -0,0 +1,75 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Online.API.Requests; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osuTK; +using osu.Game.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Framework.Bindables; + +namespace osu.Game.Overlays.Comments +{ + public class SortSelector : OsuTabControl + { + private const int spacing = 5; + + protected override Dropdown CreateDropdown() => null; + + protected override TabItem CreateTabItem(SortCommentsBy value) => new SortTabItem(value); + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(spacing, 0), + }; + + public SortSelector() + { + AutoSizeAxes = Axes.Both; + } + + private class SortTabItem : TabItem + { + private readonly TabContent content; + + public SortTabItem(SortCommentsBy value) + : base(value) + { + AutoSizeAxes = Axes.Both; + Child = content = new TabContent(value) + { Active = { BindTarget = Active } }; + } + + protected override void OnActivated() => content.FadeInBackground(); + + protected override void OnDeactivated() => content.FadeOutBackground(); + + private class TabContent : HeaderButton + { + private const int text_size = 14; + + public readonly BindableBool Active = new BindableBool(); + + public TabContent(SortCommentsBy value) + { + Add(new SpriteText + { + Font = OsuFont.GetFont(size: text_size), + Text = value.ToString() + }); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + if (!Active.Value) base.OnHoverLost(e); + } + } + } + } +} From 3dd2b18ff0d32cb717bddd6c982e42ca3a7a723f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Oct 2019 16:04:58 +0900 Subject: [PATCH 3353/5608] Make EditorScreen abstract --- osu.Game/Screens/Edit/Editor.cs | 6 +----- osu.Game/Screens/Edit/EditorScreen.cs | 15 +++++---------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 9ebe3bc26a..7f08c2f8b9 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -19,13 +19,13 @@ using osu.Framework.Timing; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Edit.Components; using osu.Game.Screens.Edit.Components.Menus; -using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Design; using osuTK.Input; using System.Collections.Generic; using osu.Framework; using osu.Framework.Input.Bindings; using osu.Game.Input.Bindings; +using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Setup; using osu.Game.Screens.Edit.Timing; using osu.Game.Users; @@ -275,10 +275,6 @@ namespace osu.Game.Screens.Edit case EditorScreenMode.Timing: currentScreen = new TimingScreen(); break; - - default: - currentScreen = new EditorScreen(); - break; } LoadComponentAsync(currentScreen, screenContainer.Add); diff --git a/osu.Game/Screens/Edit/EditorScreen.cs b/osu.Game/Screens/Edit/EditorScreen.cs index 045e5a1226..1b57c703ae 100644 --- a/osu.Game/Screens/Edit/EditorScreen.cs +++ b/osu.Game/Screens/Edit/EditorScreen.cs @@ -10,16 +10,17 @@ using osu.Game.Beatmaps; namespace osu.Game.Screens.Edit { /// - /// TODO: eventually make this inherit Screen and add a local scren stack inside the Editor. + /// TODO: eventually make this inherit Screen and add a local screen stack inside the Editor. /// - public class EditorScreen : Container + public abstract class EditorScreen : Container { - protected readonly IBindable Beatmap = new Bindable(); + [Resolved] + protected IBindable Beatmap { get; private set; } protected override Container Content => content; private readonly Container content; - public EditorScreen() + protected EditorScreen() { Anchor = Anchor.Centre; Origin = Anchor.Centre; @@ -28,12 +29,6 @@ namespace osu.Game.Screens.Edit InternalChild = content = new Container { RelativeSizeAxes = Axes.Both }; } - [BackgroundDependencyLoader] - private void load(IBindable beatmap) - { - Beatmap.BindTo(beatmap); - } - protected override void LoadComplete() { base.LoadComplete(); From f2adae8fd167195b667989d30d7bc99b09e12ba3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Oct 2019 16:05:38 +0900 Subject: [PATCH 3354/5608] Rename test case to better match underlying class --- ...{TestSceneEditorCompose.cs => TestSceneComposeScreen.cs} | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) rename osu.Game.Tests/Visual/Editor/{TestSceneEditorCompose.cs => TestSceneComposeScreen.cs} (72%) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorCompose.cs b/osu.Game.Tests/Visual/Editor/TestSceneComposeScreen.cs similarity index 72% rename from osu.Game.Tests/Visual/Editor/TestSceneEditorCompose.cs rename to osu.Game.Tests/Visual/Editor/TestSceneComposeScreen.cs index 608df1965e..9f16e1d781 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorCompose.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneComposeScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Rulesets.Osu; @@ -11,10 +9,8 @@ using osu.Game.Screens.Edit.Compose; namespace osu.Game.Tests.Visual.Editor { [TestFixture] - public class TestSceneEditorCompose : EditorClockTestScene + public class TestSceneComposeScreen : EditorClockTestScene { - public override IReadOnlyList RequiredTypes => new[] { typeof(ComposeScreen) }; - [BackgroundDependencyLoader] private void load() { From 2d8e5615e4970fc1f47a94ed2690d6f2c0cb8a99 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Oct 2019 16:05:55 +0900 Subject: [PATCH 3355/5608] Extract timeline and layout logic from ComposeScreen --- .../Screens/Edit/Compose/ComposeScreen.cs | 111 +----------------- .../Screens/Edit/EditorScreenWithTimeline.cs | 107 +++++++++++++++++ 2 files changed, 112 insertions(+), 106 deletions(-) create mode 100644 osu.Game/Screens/Edit/EditorScreenWithTimeline.cs diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 2a99d81516..1d93c6d4a4 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -1,112 +1,19 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using JetBrains.Annotations; -using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Logging; -using osu.Game.Screens.Edit.Compose.Components; -using osu.Game.Screens.Edit.Compose.Components.Timeline; using osu.Game.Skinning; -using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose { - public class ComposeScreen : EditorScreen + public class ComposeScreen : EditorScreenWithTimeline { - private const float vertical_margins = 10; - private const float horizontal_margins = 20; - - private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); - - [BackgroundDependencyLoader(true)] - private void load([CanBeNull] BindableBeatDivisor beatDivisor) + protected override Drawable CreateMainContent() { - if (beatDivisor != null) - this.beatDivisor.BindTo(beatDivisor); - - Container composerContainer; - - Children = new Drawable[] - { - new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - new Container - { - Name = "Timeline", - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(0.5f) - }, - new Container - { - Name = "Timeline content", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = horizontal_margins, Vertical = vertical_margins }, - Child = new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 5 }, - Child = new TimelineArea { RelativeSizeAxes = Axes.Both } - }, - new BeatDivisorControl(beatDivisor) { RelativeSizeAxes = Axes.Both } - }, - }, - ColumnDimensions = new[] - { - new Dimension(), - new Dimension(GridSizeMode.Absolute, 90), - } - }, - } - } - } - }, - new Drawable[] - { - composerContainer = new Container - { - Name = "Composer content", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = horizontal_margins, Vertical = vertical_margins }, - } - } - }, - RowDimensions = new[] { new Dimension(GridSizeMode.Absolute, 110) } - }, - }; - var ruleset = Beatmap.Value.BeatmapInfo.Ruleset?.CreateInstance(); - if (ruleset == null) - { - Logger.Log("Beatmap doesn't have a ruleset assigned."); - // ExitRequested?.Invoke(); - return; - } - - var composer = ruleset.CreateHitObjectComposer(); - - Drawable content; + var composer = ruleset?.CreateHitObjectComposer(); if (composer != null) { @@ -118,18 +25,10 @@ namespace osu.Game.Screens.Edit.Compose // load the skinning hierarchy first. // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. - content = beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(ruleset.CreateHitObjectComposer())); - } - else - { - content = new ScreenWhiteBox.UnderConstructionMessage($"{ruleset.Description}'s composer"); + return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(ruleset.CreateHitObjectComposer())); } - LoadComponentAsync(content, _ => - { - composerContainer.Add(content); - content.FadeInFromZero(300, Easing.OutQuint); - }); + return new ScreenWhiteBox.UnderConstructionMessage($"{ruleset.Description}'s composer"); } } } diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs new file mode 100644 index 0000000000..752356e8c4 --- /dev/null +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -0,0 +1,107 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using JetBrains.Annotations; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Screens.Edit.Compose.Components; +using osu.Game.Screens.Edit.Compose.Components.Timeline; +using osuTK.Graphics; + +namespace osu.Game.Screens.Edit +{ + public abstract class EditorScreenWithTimeline : EditorScreen + { + private const float vertical_margins = 10; + private const float horizontal_margins = 20; + + private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); + + [BackgroundDependencyLoader(true)] + private void load([CanBeNull] BindableBeatDivisor beatDivisor) + { + if (beatDivisor != null) + this.beatDivisor.BindTo(beatDivisor); + + Container mainContent; + + Children = new Drawable[] + { + new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + new Container + { + Name = "Timeline", + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0.5f) + }, + new Container + { + Name = "Timeline content", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = horizontal_margins, Vertical = vertical_margins }, + Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 5 }, + Child = CreateTimeline() + }, + new BeatDivisorControl(beatDivisor) { RelativeSizeAxes = Axes.Both } + }, + }, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.Absolute, 90), + } + }, + } + } + } + }, + new Drawable[] + { + mainContent = new Container + { + Name = "Main content", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = horizontal_margins, Vertical = vertical_margins }, + } + } + }, + RowDimensions = new[] { new Dimension(GridSizeMode.Absolute, 110) } + }, + }; + + LoadComponentAsync(CreateMainContent(), content => + { + mainContent.Add(content); + content.FadeInFromZero(300, Easing.OutQuint); + }); + } + + protected abstract Drawable CreateMainContent(); + + protected virtual Drawable CreateTimeline() => new TimelineArea { RelativeSizeAxes = Axes.Both }; + } +} From faef4d932d08cc7ef5fde89d88953b3c21cd7ac6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 9 Oct 2019 10:17:14 +0300 Subject: [PATCH 3356/5608] Improve message parsing --- osu.Game/Online/API/Requests/Responses/Comment.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 30aca3c2ea..fb0aad0e0b 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -87,8 +87,7 @@ namespace osu.Game.Online.API.Requests.Responses public string GetMessage() { - //temporary fix until HTML parsing will be implemented - return MessageHTML.Remove(MessageHTML.LastIndexOf("

")).Substring(65); + return MessageHTML.Replace("
", "").Replace("

", "").Replace("
", "").Replace("

", "").Replace("
", ""); } } } From 4462d454e87fba91a25b92b3bc4fef0a9ba6007c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 9 Oct 2019 10:34:17 +0300 Subject: [PATCH 3357/5608] Message padding improvements --- osu.Game/Overlays/Comments/CommentsContainer.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 5be1b6c1c4..b9effb39e8 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -16,6 +16,7 @@ namespace osu.Game.Overlays.Comments public class CommentsContainer : CompositeDrawable { private const float separator_height = 1.5f; + private const int padding = 40; private readonly CommentableType type; private readonly long id; @@ -92,7 +93,13 @@ namespace osu.Game.Overlays.Comments if (!c.IsDeleted && c.IsTopLevel) content.AddRange(new Drawable[] { - new DrawableComment(c), + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Right = padding }, + Child = new DrawableComment(c) + }, new Container { RelativeSizeAxes = Axes.X, From 0681bb9a2b27f063ae0153ca204b25a895334db1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Oct 2019 16:49:10 +0900 Subject: [PATCH 3358/5608] Fix potential nullref --- osu.Game/Screens/Edit/Compose/ComposeScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 1d93c6d4a4..2e9094ebe6 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Edit.Compose return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(ruleset.CreateHitObjectComposer())); } - return new ScreenWhiteBox.UnderConstructionMessage($"{ruleset.Description}'s composer"); + return new ScreenWhiteBox.UnderConstructionMessage(ruleset == null ? "This beatmap" : $"{ruleset.Description}'s composer"); } } } From 0a56b041fdf7116ceb72d8a7251383f912961f5f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 9 Oct 2019 11:07:56 +0300 Subject: [PATCH 3359/5608] Implement ShowChildsButton --- .../Online/TestSceneCommentsContainer.cs | 3 +- .../Online/API/Requests/Responses/Comment.cs | 2 +- .../Overlays/Comments/CommentsContainer.cs | 9 +-- osu.Game/Overlays/Comments/DrawableComment.cs | 72 ++++++++++++------- .../Overlays/Comments/ShowChildsButton.cs | 34 +++++++++ 5 files changed, 85 insertions(+), 35 deletions(-) create mode 100644 osu.Game/Overlays/Comments/ShowChildsButton.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index 7fbe9d7e8b..4187771963 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -20,7 +20,8 @@ namespace osu.Game.Tests.Visual.Online typeof(CommentsHeader), typeof(DrawableComment), typeof(HeaderButton), - typeof(SortSelector) + typeof(SortSelector), + typeof(ShowChildsButton) }; protected override bool UseOnlineAPI => true; diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index fb0aad0e0b..9a3dee30b4 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -87,7 +87,7 @@ namespace osu.Game.Online.API.Requests.Responses public string GetMessage() { - return MessageHTML.Replace("
", "").Replace("

", "").Replace("
", "").Replace("

", "").Replace("
", ""); + return MessageHTML.Replace("
", "").Replace("

", "").Replace("
", "").Replace("

", "").Replace("
", "").Replace(""", "\""); } } } diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index b9effb39e8..5be1b6c1c4 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -16,7 +16,6 @@ namespace osu.Game.Overlays.Comments public class CommentsContainer : CompositeDrawable { private const float separator_height = 1.5f; - private const int padding = 40; private readonly CommentableType type; private readonly long id; @@ -93,13 +92,7 @@ namespace osu.Game.Overlays.Comments if (!c.IsDeleted && c.IsTopLevel) content.AddRange(new Drawable[] { - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Right = padding }, - Child = new DrawableComment(c) - }, + new DrawableComment(c), new Container { RelativeSizeAxes = Axes.X, diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 41b30513a1..a66b8fcd44 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -10,11 +10,11 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Users.Drawables; using osu.Game.Graphics.Containers; using osu.Game.Utils; -using osu.Framework.Input.Events; using osu.Framework.Graphics.Cursor; using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; using osuTK.Graphics; +using System.Linq; namespace osu.Game.Overlays.Comments { @@ -23,6 +23,8 @@ namespace osu.Game.Overlays.Comments private const int avatar_size = 40; private const int margin = 10; private const int child_margin = 20; + private const int chevron_margin = 30; + private const int message_padding = 40; private const int duration = 200; private readonly BindableBool childExpanded = new BindableBool(true); @@ -93,25 +95,41 @@ namespace osu.Game.Overlays.Comments Spacing = new Vector2(0, 2), Children = new Drawable[] { - new FillFlowContainer + new Container { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7, 0), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Children = new Drawable[] { - username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) + new FillFlowContainer { AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7, 0), + Children = new Drawable[] + { + username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) + { + AutoSizeAxes = Axes.Both, + }, + new ParentUsername(comment) + } }, - new ParentUsername(comment) + new ChevronButton(comment) + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Margin = new MarginPadding { Right = chevron_margin }, + Expanded = { BindTarget = childExpanded } + } } }, new TextFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Text = comment.GetMessage() + Text = comment.GetMessage(), + Padding = new MarginPadding { Right = message_padding } } } } @@ -196,18 +214,34 @@ namespace osu.Game.Overlays.Comments } } - private class RepliesButton : Container + private class ChevronButton : ShowChildsButton + { + private readonly SpriteIcon icon; + + public ChevronButton(Comment comment) + { + Alpha = comment.IsTopLevel && comment.ChildComments.Any() ? 1 : 0; + Child = icon = new SpriteIcon + { + Size = new Vector2(12), + }; + } + + protected override void OnExpandedChanged(ValueChangedEvent expanded) + { + icon.Icon = expanded.NewValue ? FontAwesome.Solid.ChevronUp : FontAwesome.Solid.ChevronDown; + } + } + + private class RepliesButton : ShowChildsButton { private readonly SpriteText text; private readonly int count; - public readonly BindableBool Expanded = new BindableBool(true); - public RepliesButton(int count) { this.count = count; - AutoSizeAxes = Axes.Both; Alpha = count == 0 ? 0 : 1; Child = text = new SpriteText { @@ -215,22 +249,10 @@ namespace osu.Game.Overlays.Comments }; } - protected override void LoadComplete() - { - Expanded.BindValueChanged(onExpandedChanged, true); - base.LoadComplete(); - } - - private void onExpandedChanged(ValueChangedEvent expanded) + protected override void OnExpandedChanged(ValueChangedEvent expanded) { text.Text = $@"{(expanded.NewValue ? "[+]" : "[-]")} replies ({count})"; } - - protected override bool OnClick(ClickEvent e) - { - Expanded.Value = !Expanded.Value; - return base.OnClick(e); - } } private class ParentUsername : FillFlowContainer, IHasTooltip diff --git a/osu.Game/Overlays/Comments/ShowChildsButton.cs b/osu.Game/Overlays/Comments/ShowChildsButton.cs new file mode 100644 index 0000000000..81280a71b5 --- /dev/null +++ b/osu.Game/Overlays/Comments/ShowChildsButton.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.Graphics; +using osu.Game.Graphics.Containers; +using osu.Framework.Input.Events; +using osu.Framework.Bindables; + +namespace osu.Game.Overlays.Comments +{ + public abstract class ShowChildsButton : OsuHoverContainer + { + public readonly BindableBool Expanded = new BindableBool(true); + + public ShowChildsButton() + { + AutoSizeAxes = Axes.Both; + } + + protected override void LoadComplete() + { + Expanded.BindValueChanged(OnExpandedChanged, true); + base.LoadComplete(); + } + + protected abstract void OnExpandedChanged(ValueChangedEvent expanded); + + protected override bool OnClick(ClickEvent e) + { + Expanded.Value = !Expanded.Value; + return base.OnClick(e); + } + } +} From a0dfbfe1488e9cbb66ad068828fdbf88069b24ec Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 9 Oct 2019 11:18:26 +0300 Subject: [PATCH 3360/5608] Handle parent usernames for legacy comments --- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index a66b8fcd44..6215f5e108 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -281,7 +281,7 @@ namespace osu.Game.Overlays.Comments new SpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), - Text = comment.ParentComment?.User?.Username + Text = comment.ParentComment?.User?.Username ?? comment.ParentComment?.LegacyName } }; } From ad99a3236f052d2f2130a8c3559093f5c3c3699d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 9 Oct 2019 11:32:17 +0300 Subject: [PATCH 3361/5608] Handle edited comments --- .../Requests/Responses/APICommentsController.cs | 3 +++ osu.Game/Online/API/Requests/Responses/Comment.cs | 2 ++ osu.Game/Overlays/Comments/DrawableComment.cs | 14 +++++++++++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APICommentsController.cs b/osu.Game/Online/API/Requests/Responses/APICommentsController.cs index cf2e5e8a35..ca6062e371 100644 --- a/osu.Game/Online/API/Requests/Responses/APICommentsController.cs +++ b/osu.Game/Online/API/Requests/Responses/APICommentsController.cs @@ -63,6 +63,9 @@ namespace osu.Game.Online.API.Requests.Responses { if (c.UserId == u.Id) c.User = u; + + if (c.EditedById == u.Id) + c.EditedUser = u; }); }); } diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 9a3dee30b4..e420a585fe 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -81,6 +81,8 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"edited_by_id")] public long? EditedById { get; set; } + public User EditedUser { get; set; } + public bool IsTopLevel { get; set; } public bool IsDeleted { get; set; } diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 6215f5e108..92b59a985b 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -35,6 +35,7 @@ namespace osu.Game.Overlays.Comments { LinkFlowContainer username; FillFlowContainer childCommentsContainer; + FillFlowContainer info; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -140,7 +141,7 @@ namespace osu.Game.Overlays.Comments { RelativeSizeAxes = Axes.Both, }, - new FillFlowContainer + info = new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, @@ -188,6 +189,17 @@ namespace osu.Game.Overlays.Comments username.AddUserLink(comment.User); } + if (comment.EditedAt.HasValue) + { + info.Add(new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: 12), + Text = $@"edited {HumanizerUtils.Humanize(comment.EditedAt.Value)} by {comment.EditedUser.Username}" + }); + } + comment.ChildComments.ForEach(c => { if (!c.IsDeleted) From b2bd78308dc4473d89d89244b873e5bd97b9f54f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 9 Oct 2019 12:18:49 +0300 Subject: [PATCH 3362/5608] Handle deleted comments --- .../Online/API/Requests/Responses/Comment.cs | 2 +- .../Overlays/Comments/CommentsContainer.cs | 24 +-- osu.Game/Overlays/Comments/DrawableComment.cs | 150 +++++++++++------- 3 files changed, 98 insertions(+), 78 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index e420a585fe..76a322e5c9 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -89,7 +89,7 @@ namespace osu.Game.Online.API.Requests.Responses public string GetMessage() { - return MessageHTML.Replace("
", "").Replace("

", "").Replace("
", "").Replace("

", "").Replace("
", "").Replace(""", "\""); + return IsDeleted ? @"deleted" : MessageHTML.Replace("
", "").Replace("

", "").Replace("
", "").Replace("

", "").Replace("
", "").Replace(""", "\""); } } } diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 5be1b6c1c4..fb97f08a6e 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -15,12 +15,11 @@ namespace osu.Game.Overlays.Comments { public class CommentsContainer : CompositeDrawable { - private const float separator_height = 1.5f; - private readonly CommentableType type; private readonly long id; public readonly Bindable Sort = new Bindable(); + public readonly BindableBool ShowDeleted = new BindableBool(); [Resolved] private IAPIProvider api { get; set; } @@ -55,7 +54,8 @@ namespace osu.Game.Overlays.Comments { new CommentsHeader { - Sort = { BindTarget = Sort } + Sort = { BindTarget = Sort }, + ShowDeleted = { BindTarget = ShowDeleted } }, content = new FillFlowContainer { @@ -89,21 +89,9 @@ namespace osu.Game.Overlays.Comments { foreach (var c in response.Comments) { - if (!c.IsDeleted && c.IsTopLevel) - content.AddRange(new Drawable[] - { - new DrawableComment(c), - new Container - { - RelativeSizeAxes = Axes.X, - Height = separator_height, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Gray1, - } - } - }); + if (c.IsTopLevel) + content.Add(new DrawableComment(c) + { ShowDeleted = { BindTarget = ShowDeleted } }); } } diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 92b59a985b..4092cbb177 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -26,19 +26,29 @@ namespace osu.Game.Overlays.Comments private const int chevron_margin = 30; private const int message_padding = 40; private const int duration = 200; + private const float separator_height = 1.5f; + + public readonly BindableBool ShowDeleted = new BindableBool(); private readonly BindableBool childExpanded = new BindableBool(true); private readonly Container childCommentsVisibilityContainer; + private readonly Comment comment; public DrawableComment(Comment comment) { LinkFlowContainer username; FillFlowContainer childCommentsContainer; FillFlowContainer info; + TextFlowContainer message; + GridContainer content; + VotePill votePill; + + this.comment = comment; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + Masking = true; InternalChild = new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -46,7 +56,7 @@ namespace osu.Game.Overlays.Comments Direction = FillDirection.Vertical, Children = new Drawable[] { - new GridContainer + content = new GridContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -58,7 +68,6 @@ namespace osu.Game.Overlays.Comments }, RowDimensions = new[] { - new Dimension(GridSizeMode.AutoSize), new Dimension(GridSizeMode.AutoSize) }, Content = new[] @@ -73,10 +82,11 @@ namespace osu.Game.Overlays.Comments Spacing = new Vector2(5, 0), Children = new Drawable[] { - new VotePill(comment.VotesCount) + votePill = new VotePill(comment.VotesCount) { Anchor = Anchor.Centre, Origin = Anchor.Centre, + AlwaysPresent = true, }, new UpdateableAvatar(comment.User) { @@ -92,71 +102,53 @@ namespace osu.Game.Overlays.Comments { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = margin / 2 }, - Spacing = new Vector2(0, 2), + Spacing = new Vector2(0, 3), Children = new Drawable[] { - new Container + new FillFlowContainer { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7, 0), Children = new Drawable[] { - new FillFlowContainer + username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) { AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7, 0), - Children = new Drawable[] - { - username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) - { - AutoSizeAxes = Axes.Both, - }, - new ParentUsername(comment) - } }, - new ChevronButton(comment) + new ParentUsername(comment), + new SpriteText { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Margin = new MarginPadding { Right = chevron_margin }, - Expanded = { BindTarget = childExpanded } + Alpha = comment.IsDeleted? 1 : 0, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), + Text = @"deleted", } } }, - new TextFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) + message = new TextFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Text = comment.GetMessage(), Padding = new MarginPadding { Right = message_padding } - } - } - } - }, - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - }, - info = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: 12), - Text = HumanizerUtils.Humanize(comment.CreatedAt) }, - new RepliesButton(comment.RepliesCount) - { Expanded = { BindTarget = childExpanded } }, + info = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: 12), + Text = HumanizerUtils.Humanize(comment.CreatedAt) + }, + new RepliesButton(comment.RepliesCount) + { Expanded = { BindTarget = childExpanded } }, + } + } } } } @@ -181,13 +173,9 @@ namespace osu.Game.Overlays.Comments }; if (comment.UserId == null) - { username.AddText(comment.LegacyName); - } else - { username.AddUserLink(comment.User); - } if (comment.EditedAt.HasValue) { @@ -200,15 +188,45 @@ namespace osu.Game.Overlays.Comments }); } - comment.ChildComments.ForEach(c => + if (!comment.IsDeleted) + message.Text = comment.GetMessage(); + else { - if (!c.IsDeleted) - childCommentsContainer.Add(new DrawableComment(c)); - }); + content.FadeColour(OsuColour.Gray(0.5f)); + votePill.Hide(); + } + + if (comment.IsTopLevel) + { + AddInternal(new Container + { + RelativeSizeAxes = Axes.X, + Height = separator_height, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.1f) + } + }); + + if (comment.ChildComments.Any()) + { + AddInternal(new ChevronButton(comment) + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Margin = new MarginPadding { Right = chevron_margin, Top = margin }, + Expanded = { BindTarget = childExpanded } + }); + } + } + + comment.ChildComments.ForEach(c => childCommentsContainer.Add(new DrawableComment(c))); } protected override void LoadComplete() { + ShowDeleted.BindValueChanged(onShowDeletedChanged, true); childExpanded.BindValueChanged(onChildExpandedChanged, true); base.LoadComplete(); } @@ -226,6 +244,20 @@ namespace osu.Game.Overlays.Comments } } + private void onShowDeletedChanged(ValueChangedEvent show) + { + if (comment.IsDeleted) + { + if (show.NewValue) + AutoSizeAxes = Axes.Y; + else + { + AutoSizeAxes = Axes.None; + this.ResizeHeightTo(0); + } + } + } + private class ChevronButton : ShowChildsButton { private readonly SpriteIcon icon; From 93d2c3d7a1c43cb9871f1bcb779b51cddcc086e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Oct 2019 19:03:20 +0900 Subject: [PATCH 3363/5608] Warn on incorrect null usage --- osu.sln.DotSettings | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index ed162eed6e..ae08a1666f 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -17,7 +17,8 @@ WARNING WARNING HINT - HINT + + True HINT HINT WARNING @@ -738,6 +739,7 @@ See the LICENCE file in the repository root for full licence text. <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True True True From 51bf600ea7a830d736a748342bd987e6cc4dc878 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Oct 2019 19:08:31 +0900 Subject: [PATCH 3364/5608] Use empty hitwindows instead of null --- .../Objects/CatchHitObject.cs | 2 +- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 2 +- .../Objects/HoldNoteTick.cs | 2 +- osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- .../Objects/SliderTailCircle.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SliderTick.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 2 +- .../Objects/DrumRollTick.cs | 2 +- .../Objects/StrongHitObject.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/Swell.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/SwellTick.cs | 2 +- osu.Game/Rulesets/Objects/HitObject.cs | 6 +--- .../Objects/Legacy/Mania/ConvertHit.cs | 2 +- .../Objects/Legacy/Mania/ConvertHold.cs | 2 +- .../Objects/Legacy/Mania/ConvertSlider.cs | 2 +- .../Objects/Legacy/Mania/ConvertSpinner.cs | 2 +- .../Rulesets/Objects/Legacy/Osu/ConvertHit.cs | 2 +- .../Objects/Legacy/Osu/ConvertSlider.cs | 2 +- .../Objects/Legacy/Osu/ConvertSpinner.cs | 2 +- .../Objects/Legacy/Taiko/ConvertHit.cs | 2 +- .../Objects/Legacy/Taiko/ConvertSlider.cs | 2 +- .../Objects/Legacy/Taiko/ConvertSpinner.cs | 2 +- osu.Game/Rulesets/Scoring/HitWindows.cs | 35 +++++++++++++++++++ osu.Game/Rulesets/UI/DrawableRuleset.cs | 4 +-- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 2 +- 27 files changed, 62 insertions(+), 31 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index 77d7de989a..e4ad49ea50 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Catch.Objects Scale = 1.0f - 0.7f * (difficulty.CircleSize - 5) / 5; } - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } public enum FruitVisualRepresentation diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 0c82cf7bbc..bdba813eed 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -101,6 +101,6 @@ namespace osu.Game.Rulesets.Mania.Objects public override Judgement CreateJudgement() => new HoldNoteJudgement(); - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs index d0125f8793..ac6697a6dc 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs @@ -14,6 +14,6 @@ namespace osu.Game.Rulesets.Mania.Objects { public override Judgement CreateJudgement() => new HoldNoteTickJudgement(); - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs index a794e57c9e..a277517f9f 100644 --- a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs @@ -30,6 +30,6 @@ namespace osu.Game.Rulesets.Osu.Objects public override Judgement CreateJudgement() => new OsuJudgement(); - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 3ed1f2cdde..9bed123465 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -205,6 +205,6 @@ namespace osu.Game.Rulesets.Osu.Objects public override Judgement CreateJudgement() => new OsuJudgement(); - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index 7e540a577b..14c3369967 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -25,6 +25,6 @@ namespace osu.Game.Rulesets.Osu.Objects public override Judgement CreateJudgement() => new OsuSliderTailJudgement(); - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs index af7cf5b144..a49f4cef8b 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs @@ -32,6 +32,6 @@ namespace osu.Game.Rulesets.Osu.Objects public override Judgement CreateJudgement() => new OsuJudgement(); - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index 2e7b763966..2441a1449d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -33,6 +33,6 @@ namespace osu.Game.Rulesets.Osu.Objects public override Judgement CreateJudgement() => new OsuJudgement(); - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 4e02c76a8b..8956ca9c19 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -88,6 +88,6 @@ namespace osu.Game.Rulesets.Taiko.Objects public override Judgement CreateJudgement() => new TaikoDrumRollJudgement(); - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index c466ca7c8a..8a8be3e38d 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -27,6 +27,6 @@ namespace osu.Game.Rulesets.Taiko.Objects public override Judgement CreateJudgement() => new TaikoDrumRollTickJudgement(); - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs index d660149528..72a04698be 100644 --- a/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs @@ -11,6 +11,6 @@ namespace osu.Game.Rulesets.Taiko.Objects { public override Judgement CreateJudgement() => new TaikoStrongJudgement(); - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index f96c033dce..e60984596d 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -35,6 +35,6 @@ namespace osu.Game.Rulesets.Taiko.Objects public override Judgement CreateJudgement() => new TaikoSwellJudgement(); - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs index 68212e8f12..91f4d3dbe7 100644 --- a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs @@ -11,6 +11,6 @@ namespace osu.Game.Rulesets.Taiko.Objects { public override Judgement CreateJudgement() => new TaikoSwellTickJudgement(); - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index a99fac09cc..eb8652443f 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -66,7 +66,6 @@ namespace osu.Game.Rulesets.Objects /// /// The hit windows for this . /// - [CanBeNull] public HitWindows HitWindows { get; set; } private readonly List nestedHitObjects = new List(); @@ -113,10 +112,7 @@ namespace osu.Game.Rulesets.Objects nestedHitObjects.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime)); foreach (var h in nestedHitObjects) - { - h.HitWindows = HitWindows; h.ApplyDefaults(controlPointInfo, difficulty); - } } protected virtual void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) @@ -147,7 +143,7 @@ namespace osu.Game.Rulesets.Objects /// This will only be invoked if hasn't been set externally (e.g. from a . /// ///
- [CanBeNull] + [NotNull] protected virtual HitWindows CreateHitWindows() => new HitWindows(); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs index 609bdd571a..883ef55df0 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs @@ -13,6 +13,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania { public float X { get; set; } - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs index 350ee3185d..69e6f8379d 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs @@ -14,6 +14,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public double Duration => EndTime - StartTime; - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs index e372fbd273..4486c5d906 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs @@ -13,6 +13,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania { public float X { get; set; } - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs index 067377d300..c6d1f1922c 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs @@ -17,6 +17,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania public float X { get; set; } - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs index c9851a0074..e40b5b4505 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs @@ -22,6 +22,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public int ComboOffset { get; set; } - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs index 1c1180702b..a163329d47 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs @@ -22,6 +22,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public int ComboOffset { get; set; } - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs index bc94ea1803..5d96a61633 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public float Y => Position.Y; - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; public bool NewCombo { get; set; } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs index 709345170f..efb9810927 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs @@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko ///
internal sealed class ConvertHit : HitObject { - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs index c173b3e11a..b365fd34ae 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs @@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko ///
internal sealed class ConvertSlider : Legacy.ConvertSlider { - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs index 9a35ad2776..840ba51ac2 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs @@ -15,6 +15,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko public double Duration => EndTime - StartTime; - protected override HitWindows CreateHitWindows() => null; + protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Scoring/HitWindows.cs b/osu.Game/Rulesets/Scoring/HitWindows.cs index efc4cd9f5c..9e7e594104 100644 --- a/osu.Game/Rulesets/Scoring/HitWindows.cs +++ b/osu.Game/Rulesets/Scoring/HitWindows.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; @@ -30,6 +31,17 @@ namespace osu.Game.Rulesets.Scoring private double meh; private double miss; + /// + /// An empty with only and . + /// No time values are provided (meaning instantaneous hit or miss). + /// + public static HitWindows Empty => new EmptyHitWindows(); + + public HitWindows() + { + Debug.Assert(GetRanges().Length >= 1, $"{nameof(HitWindows)}"); + } + /// /// Retrieves the with the largest hit window that produces a successful hit. /// @@ -168,6 +180,29 @@ namespace osu.Game.Rulesets.Scoring /// Defaults are provided but can be overridden to customise for a ruleset. ///
protected virtual DifficultyRange[] GetRanges() => base_ranges; + + public class EmptyHitWindows : HitWindows + { + private static readonly DifficultyRange[] ranges = + { + new DifficultyRange(HitResult.Perfect, 0, 0, 0), + new DifficultyRange(HitResult.Miss, 0, 0, 0), + }; + + public override bool IsHitResultAllowed(HitResult result) + { + switch (result) + { + case HitResult.Great: + case HitResult.Miss: + return true; + } + + return false; + } + + protected override DifficultyRange[] GetRanges() => ranges; + } } public struct DifficultyRange diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index d68b0e94c5..d5b3df27df 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -426,11 +426,11 @@ namespace osu.Game.Rulesets.UI { foreach (var h in Objects) { - if (h.HitWindows != null) + if (h.HitWindows.WindowFor(HitResult.Miss) > 0) return h.HitWindows; foreach (var n in h.NestedHitObjects) - if (n.HitWindows != null) + if (h.HitWindows.WindowFor(HitResult.Miss) > 0) return n.HitWindows; } diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 920d11c910..54556f8648 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -48,7 +48,7 @@ namespace osu.Game.Screens.Play.HUD private void onNewJudgement(JudgementResult result) { - if (result.HitObject.HitWindows == null) + if (result.HitObject.HitWindows.WindowFor(HitResult.Miss) == 0) return; foreach (var c in Children) From ad6b8d3e04eccee5eaabf496b7b3df2d77c79659 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Oct 2019 19:08:55 +0900 Subject: [PATCH 3365/5608] Add result offset bounding to result itself, rather than just transforms --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index f8bc74b2a6..7f3bfd3b5c 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -173,7 +173,7 @@ namespace osu.Game.Rulesets.Objects.Drawables { UpdateInitialTransforms(); - var judgementOffset = Math.Min(HitObject.HitWindows?.WindowFor(HitResult.Miss) ?? double.MaxValue, Result?.TimeOffset ?? 0); + var judgementOffset = Result?.TimeOffset ?? 0; using (BeginDelayedSequence(InitialLifetimeOffset + judgementOffset, true)) { @@ -379,7 +379,8 @@ namespace osu.Game.Rulesets.Objects.Drawables // Ensure that the judgement is given a valid time offset, because this may not get set by the caller var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - Result.TimeOffset = Time.Current - endTime; + + Result.TimeOffset = Math.Min(HitObject.HitWindows.WindowFor(HitResult.Miss), Time.Current - endTime); switch (Result.Type) { From 9f2a64843291fbe2e8dae6f86f8004559b75991b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Oct 2019 19:23:37 +0900 Subject: [PATCH 3366/5608] Add full asserts --- osu.Game/Rulesets/Scoring/HitWindows.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/HitWindows.cs b/osu.Game/Rulesets/Scoring/HitWindows.cs index 9e7e594104..93e4dfc5fa 100644 --- a/osu.Game/Rulesets/Scoring/HitWindows.cs +++ b/osu.Game/Rulesets/Scoring/HitWindows.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; @@ -39,7 +40,8 @@ namespace osu.Game.Rulesets.Scoring public HitWindows() { - Debug.Assert(GetRanges().Length >= 1, $"{nameof(HitWindows)}"); + Debug.Assert(GetRanges().Any(r => r.Result == HitResult.Miss), $"{nameof(GetRanges)} should always contain {nameof(HitResult.Miss)}"); + Debug.Assert(GetRanges().Any(r => r.Result != HitResult.Miss), $"{nameof(GetRanges)} should always contain at least one result type other than {nameof(HitResult.Miss)}."); } /// From 7e3c97f4962e0503b16527d13cc2fb545a3dc659 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 9 Oct 2019 13:37:07 +0300 Subject: [PATCH 3367/5608] Implement DeletedChildsPlaceholder component --- .../Online/TestSceneCommentsContainer.cs | 6 ++ .../Online/API/Requests/Responses/Comment.cs | 18 +++++ osu.Game/Overlays/Comments/DrawableComment.cs | 66 +++++++++++++++++-- 3 files changed, 86 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index 4187771963..8a6ec81d8e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -40,6 +40,12 @@ namespace osu.Game.Tests.Visual.Online scrollFlow.Clear(); scrollFlow.Add(new CommentsContainer(CommentableType.Beatmapset, 41823)); }); + + AddStep("Airman comments", () => + { + scrollFlow.Clear(); + scrollFlow.Add(new CommentsContainer(CommentableType.Beatmapset, 24313)); + }); } } } diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 76a322e5c9..6fea994cb9 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -5,6 +5,7 @@ using Newtonsoft.Json; using osu.Game.Users; using System; using System.Collections.Generic; +using System.Linq; namespace osu.Game.Online.API.Requests.Responses { @@ -91,5 +92,22 @@ namespace osu.Game.Online.API.Requests.Responses { return IsDeleted ? @"deleted" : MessageHTML.Replace("
", "").Replace("

", "").Replace("
", "").Replace("

", "").Replace("
", "").Replace(""", "\""); } + + public int GetDeletedChildsCount() + { + int count = 0; + + if (ChildComments.Any()) + ChildComments.ForEach(child => + { + if (child.IsDeleted) + count++; + }); + + if (IsDeleted) + count++; + + return count; + } } } diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 4092cbb177..60cae8c62a 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -27,6 +27,7 @@ namespace osu.Game.Overlays.Comments private const int message_padding = 40; private const int duration = 200; private const float separator_height = 1.5f; + private const int deleted_placeholder_margin = 80; public readonly BindableBool ShowDeleted = new BindableBool(); @@ -161,12 +162,26 @@ namespace osu.Game.Overlays.Comments AutoSizeDuration = duration, AutoSizeEasing = Easing.OutQuint, Masking = true, - Child = childCommentsContainer = new FillFlowContainer + Child = new FillFlowContainer { - Margin = new MarginPadding { Left = child_margin }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + childCommentsContainer = new FillFlowContainer + { + Margin = new MarginPadding { Left = child_margin }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical + }, + new DeletedChildsPlaceholder(comment.GetDeletedChildsCount()) + { + Margin = new MarginPadding { Bottom = margin, Left = deleted_placeholder_margin }, + ShowDeleted = { BindTarget = ShowDeleted } + } + } } } } @@ -221,7 +236,8 @@ namespace osu.Game.Overlays.Comments } } - comment.ChildComments.ForEach(c => childCommentsContainer.Add(new DrawableComment(c))); + comment.ChildComments.ForEach(c => childCommentsContainer.Add(new DrawableComment(c) + { ShowDeleted = { BindTarget = ShowDeleted } })); } protected override void LoadComplete() @@ -258,6 +274,48 @@ namespace osu.Game.Overlays.Comments } } + private class DeletedChildsPlaceholder : FillFlowContainer + { + public readonly BindableBool ShowDeleted = new BindableBool(); + + private readonly bool canBeVisible; + + public DeletedChildsPlaceholder(int count) + { + canBeVisible = count != 0; + + AutoSizeAxes = Axes.Both; + Direction = FillDirection.Horizontal; + Spacing = new Vector2(3, 0); + Alpha = 0; + Children = new Drawable[] + { + new SpriteIcon + { + Icon = FontAwesome.Solid.Trash, + Size = new Vector2(14), + }, + new SpriteText + { + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), + Text = $@"{count} deleted comments" + } + }; + } + + protected override void LoadComplete() + { + ShowDeleted.BindValueChanged(onShowDeletedChanged, true); + base.LoadComplete(); + } + + private void onShowDeletedChanged(ValueChangedEvent showDeleted) + { + if (canBeVisible) + this.FadeTo(showDeleted.NewValue ? 0 : 1); + } + } + private class ChevronButton : ShowChildsButton { private readonly SpriteIcon icon; From e6f857d0d8db175f6cae7b70df070227fb474387 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Oct 2019 19:03:20 +0900 Subject: [PATCH 3368/5608] Revert "Warn on incorrect null usage" This reverts commit 93d2c3d7a1c43cb9871f1bcb779b51cddcc086e9. --- osu.sln.DotSettings | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index ae08a1666f..ed162eed6e 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -17,8 +17,7 @@ WARNING WARNING HINT - - True + HINT HINT HINT WARNING @@ -739,7 +738,6 @@ See the LICENCE file in the repository root for full licence text. <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - True True True From c9d5bea0f1bd1a8a01c4fe2f08242e8292dffe22 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 9 Oct 2019 13:45:14 +0300 Subject: [PATCH 3369/5608] Remove animations --- osu.Game/Overlays/Comments/DrawableComment.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 60cae8c62a..94ec7a861a 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -25,7 +25,6 @@ namespace osu.Game.Overlays.Comments private const int child_margin = 20; private const int chevron_margin = 30; private const int message_padding = 40; - private const int duration = 200; private const float separator_height = 1.5f; private const int deleted_placeholder_margin = 80; @@ -159,8 +158,6 @@ namespace osu.Game.Overlays.Comments { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - AutoSizeDuration = duration, - AutoSizeEasing = Easing.OutQuint, Masking = true, Child = new FillFlowContainer { @@ -249,14 +246,12 @@ namespace osu.Game.Overlays.Comments private void onChildExpandedChanged(ValueChangedEvent expanded) { - childCommentsVisibilityContainer.ClearTransforms(); - if (expanded.NewValue) childCommentsVisibilityContainer.AutoSizeAxes = Axes.Y; else { childCommentsVisibilityContainer.AutoSizeAxes = Axes.None; - childCommentsVisibilityContainer.ResizeHeightTo(0, duration, Easing.OutQuint); + childCommentsVisibilityContainer.ResizeHeightTo(0); } } From 4e273fc628d2bea152dc93f65e9cdbf144c9c610 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Oct 2019 19:50:05 +0900 Subject: [PATCH 3370/5608] Return correct allowed value for Perfect Co-Authored-By: Salman Ahmed --- osu.Game/Rulesets/Scoring/HitWindows.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/HitWindows.cs b/osu.Game/Rulesets/Scoring/HitWindows.cs index 93e4dfc5fa..39d67f1071 100644 --- a/osu.Game/Rulesets/Scoring/HitWindows.cs +++ b/osu.Game/Rulesets/Scoring/HitWindows.cs @@ -195,7 +195,7 @@ namespace osu.Game.Rulesets.Scoring { switch (result) { - case HitResult.Great: + case HitResult.Perfect: case HitResult.Miss: return true; } From 107d39c3e97edb17e56bc9377d7e6cf76574ed43 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 9 Oct 2019 14:10:05 +0300 Subject: [PATCH 3371/5608] Add DeletedChildsPlaceholder to the bottom of the comments container --- .../Online/TestSceneCommentsContainer.cs | 3 +- .../Online/API/Requests/Responses/Comment.cs | 3 - .../Overlays/Comments/CommentsContainer.cs | 13 +++++ .../Comments/DeletedChildsPlaceholder.cs | 58 +++++++++++++++++++ osu.Game/Overlays/Comments/DrawableComment.cs | 46 +-------------- 5 files changed, 75 insertions(+), 48 deletions(-) create mode 100644 osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index 8a6ec81d8e..342ba487f0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -21,7 +21,8 @@ namespace osu.Game.Tests.Visual.Online typeof(DrawableComment), typeof(HeaderButton), typeof(SortSelector), - typeof(ShowChildsButton) + typeof(ShowChildsButton), + typeof(DeletedChildsPlaceholder) }; protected override bool UseOnlineAPI => true; diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 6fea994cb9..2334c86519 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -104,9 +104,6 @@ namespace osu.Game.Online.API.Requests.Responses count++; }); - if (IsDeleted) - count++; - return count; } } diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index fb97f08a6e..bf68457988 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -93,6 +93,19 @@ namespace osu.Game.Overlays.Comments content.Add(new DrawableComment(c) { ShowDeleted = { BindTarget = ShowDeleted } }); } + + int deletedComments = 0; + + response.Comments.ForEach(comment => + { + if (comment.IsDeleted && comment.IsTopLevel) + deletedComments++; + }); + + content.Add(new DeletedChildsPlaceholder(deletedComments) + { + ShowDeleted = { BindTarget = ShowDeleted } + }); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs b/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs new file mode 100644 index 0000000000..d0e6c17ccb --- /dev/null +++ b/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.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.Containers; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Framework.Graphics.Sprites; +using osuTK; +using osu.Framework.Bindables; + +namespace osu.Game.Overlays.Comments +{ + public class DeletedChildsPlaceholder : FillFlowContainer + { + private const int deleted_placeholder_margin = 80; + private const int margin = 10; + + public readonly BindableBool ShowDeleted = new BindableBool(); + + private readonly bool canBeVisible; + + public DeletedChildsPlaceholder(int count) + { + canBeVisible = count != 0; + + AutoSizeAxes = Axes.Both; + Direction = FillDirection.Horizontal; + Spacing = new Vector2(3, 0); + Margin = new MarginPadding { Vertical = margin, Left = deleted_placeholder_margin }; + Alpha = 0; + Children = new Drawable[] + { + new SpriteIcon + { + Icon = FontAwesome.Solid.Trash, + Size = new Vector2(14), + }, + new SpriteText + { + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), + Text = $@"{count} deleted comments" + } + }; + } + + protected override void LoadComplete() + { + ShowDeleted.BindValueChanged(onShowDeletedChanged, true); + base.LoadComplete(); + } + + private void onShowDeletedChanged(ValueChangedEvent showDeleted) + { + if (canBeVisible) + this.FadeTo(showDeleted.NewValue ? 0 : 1); + } + } +} diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 94ec7a861a..4af2e07227 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -26,7 +26,6 @@ namespace osu.Game.Overlays.Comments private const int chevron_margin = 30; private const int message_padding = 40; private const float separator_height = 1.5f; - private const int deleted_placeholder_margin = 80; public readonly BindableBool ShowDeleted = new BindableBool(); @@ -175,7 +174,6 @@ namespace osu.Game.Overlays.Comments }, new DeletedChildsPlaceholder(comment.GetDeletedChildsCount()) { - Margin = new MarginPadding { Bottom = margin, Left = deleted_placeholder_margin }, ShowDeleted = { BindTarget = ShowDeleted } } } @@ -214,6 +212,8 @@ namespace osu.Game.Overlays.Comments { RelativeSizeAxes = Axes.X, Height = separator_height, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, Child = new Box { RelativeSizeAxes = Axes.Both, @@ -269,48 +269,6 @@ namespace osu.Game.Overlays.Comments } } - private class DeletedChildsPlaceholder : FillFlowContainer - { - public readonly BindableBool ShowDeleted = new BindableBool(); - - private readonly bool canBeVisible; - - public DeletedChildsPlaceholder(int count) - { - canBeVisible = count != 0; - - AutoSizeAxes = Axes.Both; - Direction = FillDirection.Horizontal; - Spacing = new Vector2(3, 0); - Alpha = 0; - Children = new Drawable[] - { - new SpriteIcon - { - Icon = FontAwesome.Solid.Trash, - Size = new Vector2(14), - }, - new SpriteText - { - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), - Text = $@"{count} deleted comments" - } - }; - } - - protected override void LoadComplete() - { - ShowDeleted.BindValueChanged(onShowDeletedChanged, true); - base.LoadComplete(); - } - - private void onShowDeletedChanged(ValueChangedEvent showDeleted) - { - if (canBeVisible) - this.FadeTo(showDeleted.NewValue ? 0 : 1); - } - } - private class ChevronButton : ShowChildsButton { private readonly SpriteIcon icon; From 281671a213f26a4d71bcc920205994b1f10c5db0 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 21:04:26 +0300 Subject: [PATCH 3372/5608] Remove default combo colours usage from skins --- osu.Game/Skinning/LegacySkin.cs | 2 +- osu.Game/Skinning/LegacySkinDecoder.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index fea15458e4..3f0d4ca0d6 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -39,7 +39,7 @@ namespace osu.Game.Skinning using (LineBufferedReader reader = new LineBufferedReader(stream)) Configuration = new LegacySkinDecoder().Decode(reader); else - Configuration = new DefaultSkinConfiguration(); + Configuration = new SkinConfiguration(); if (storage != null) { diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index e97664e75e..ada2e075a7 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -5,14 +5,14 @@ using osu.Game.Beatmaps.Formats; namespace osu.Game.Skinning { - public class LegacySkinDecoder : LegacyDecoder + public class LegacySkinDecoder : LegacyDecoder { public LegacySkinDecoder() : base(1) { } - protected override void ParseLine(DefaultSkinConfiguration skin, Section section, string line) + protected override void ParseLine(SkinConfiguration skin, Section section, string line) { if (section != Section.Colours) { From 5e3f0f6c95f88845946bae4f96879628e42d9be7 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 21:08:07 +0300 Subject: [PATCH 3373/5608] Return default combo colours if none provided --- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 9 --------- osu.Game/Skinning/LegacyBeatmapSkin.cs | 3 +++ osu.Game/Skinning/LegacySkin.cs | 12 +++++++++++- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 83d20da458..4899a53cf1 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -77,8 +77,6 @@ namespace osu.Game.Beatmaps.Formats return line; } - private bool hasComboColours; - private void handleColours(T output, string line) { var pair = SplitKeyVal(line); @@ -105,13 +103,6 @@ namespace osu.Game.Beatmaps.Formats { if (!(output is IHasComboColours tHasComboColours)) return; - if (!hasComboColours) - { - // remove default colours. - tHasComboColours.ComboColours.Clear(); - hasComboColours = true; - } - tHasComboColours.ComboColours.Add(colour); } else diff --git a/osu.Game/Skinning/LegacyBeatmapSkin.cs b/osu.Game/Skinning/LegacyBeatmapSkin.cs index 6770da3c66..c9dec8a55e 100644 --- a/osu.Game/Skinning/LegacyBeatmapSkin.cs +++ b/osu.Game/Skinning/LegacyBeatmapSkin.cs @@ -9,6 +9,9 @@ namespace osu.Game.Skinning { public class LegacyBeatmapSkin : LegacySkin { + // Null should be returned in the case of no colours provided to fallback into current skin's colours. + protected override bool AllowDefaultColoursFallback => false; + public LegacyBeatmapSkin(BeatmapInfo beatmap, IResourceStore storage, AudioManager audioManager) : base(createSkinInfo(beatmap), new LegacySkinResourceStore(beatmap.BeatmapSet, storage), audioManager, beatmap.Path) { diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 3f0d4ca0d6..bc12c00cd8 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -26,6 +26,11 @@ namespace osu.Game.Skinning [CanBeNull] protected IResourceStore Samples; + /// + /// Whether to allow default combo colours as fallback if none provided in this skin. + /// + protected virtual bool AllowDefaultColoursFallback => true; + public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini") { @@ -63,7 +68,12 @@ namespace osu.Game.Skinning switch (global) { case GlobalSkinConfiguration.ComboColours: - return SkinUtils.As(new Bindable>(Configuration.ComboColours)); + if (Configuration.ComboColours.Any()) + return SkinUtils.As(new Bindable>(Configuration.ComboColours)); + else if (AllowDefaultColoursFallback) + return SkinUtils.As(new Bindable>(new DefaultSkinConfiguration().ComboColours)); + + break; } break; From c2ada81c2313f77d5d7c19205da7dc92ee303e23 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 21:08:54 +0300 Subject: [PATCH 3374/5608] Add tests ensuring correct behaviour --- .../Skins/TestSceneSkinConfigurationLookup.cs | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index 578030748b..2ea66d8e41 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; @@ -21,8 +22,8 @@ namespace osu.Game.Tests.Skins [HeadlessTest] public class TestSceneSkinConfigurationLookup : OsuTestScene { - private LegacySkin source1; - private LegacySkin source2; + private SkinSource source1; + private SkinSource source2; private SkinRequester requester; [SetUp] @@ -116,6 +117,26 @@ namespace osu.Game.Tests.Skins }); } + [TestCase(false)] + [TestCase(true)] + public void TestEmptyComboColours(bool allowFallback) + { + AddStep("Add custom combo colours to fallback source", () => source1.Configuration.ComboColours = new List + { + new Color4(100, 150, 200, 255), + new Color4(55, 110, 166, 255), + new Color4(75, 125, 175, 255), + }); + AddStep("Clear combo colours from source", () => source2.Configuration.ComboColours.Clear()); + AddStep("Disable default fallback in source", () => source2.AllowColoursFallback = allowFallback); + + AddAssert($"Check retrieved combo colours from {(allowFallback ? "default skin" : "fallback source")}", () => + { + var expectedColours = allowFallback ? new DefaultSkinConfiguration().ComboColours : source1.Configuration.ComboColours; + return requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.SequenceEqual(expectedColours) ?? false; + }); + } + public enum LookupType { Test @@ -130,6 +151,9 @@ namespace osu.Game.Tests.Skins public class SkinSource : LegacySkin { + public bool AllowColoursFallback = true; + protected override bool AllowDefaultColoursFallback => AllowColoursFallback; + public SkinSource() : base(new SkinInfo(), null, null, string.Empty) { From 8d40c1b733d9b1800474c7b0d8dba4e36684080c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 21:15:30 +0300 Subject: [PATCH 3375/5608] Remove default combo colours on empty skin test Checked differently in TestSceneSkinConfigurationLookup.TestEmptyComboColours() --- osu.Game.Tests/Resources/skin-empty.ini | 2 -- osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 25 ++++++++----------- 2 files changed, 10 insertions(+), 17 deletions(-) delete mode 100644 osu.Game.Tests/Resources/skin-empty.ini diff --git a/osu.Game.Tests/Resources/skin-empty.ini b/osu.Game.Tests/Resources/skin-empty.ini deleted file mode 100644 index b6c319fe3c..0000000000 --- a/osu.Game.Tests/Resources/skin-empty.ini +++ /dev/null @@ -1,2 +0,0 @@ -[General] -Name: test skin \ No newline at end of file diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 0d96dd08da..76ce2331f5 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -13,28 +13,23 @@ namespace osu.Game.Tests.Skins [TestFixture] public class LegacySkinDecoderTest { - [TestCase(true)] - [TestCase(false)] - public void TestDecodeSkinColours(bool hasColours) + [Test] + public void TestDecodeSkinColours() { var decoder = new LegacySkinDecoder(); - using (var resStream = TestResources.OpenResource(hasColours ? "skin.ini" : "skin-empty.ini")) + using (var resStream = TestResources.OpenResource("skin.ini")) using (var stream = new LineBufferedReader(resStream)) { var comboColors = decoder.Decode(stream).ComboColours; - List expectedColors; - if (hasColours) - expectedColors = new List - { - new Color4(142, 199, 255, 255), - new Color4(255, 128, 128, 255), - new Color4(128, 255, 255, 255), - new Color4(100, 100, 100, 100), - }; - else - expectedColors = new DefaultSkin().Configuration.ComboColours; + List expectedColors = new List + { + new Color4(142, 199, 255, 255), + new Color4(255, 128, 128, 255), + new Color4(128, 255, 255, 255), + new Color4(100, 100, 100, 100), + }; Assert.AreEqual(expectedColors.Count, comboColors.Count); for (int i = 0; i < expectedColors.Count; i++) From 003af19e3f039985ec73565cee3d3ad7345e0e9b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 23:04:34 +0300 Subject: [PATCH 3376/5608] Introduce legacy skin configuration --- osu.Game/Skinning/LegacySkin.cs | 18 ++++++++++++++++-- osu.Game/Skinning/LegacySkinConfiguration.cs | 20 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Skinning/LegacySkinConfiguration.cs diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index fea15458e4..25703b30dc 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -26,6 +26,8 @@ namespace osu.Game.Skinning [CanBeNull] protected IResourceStore Samples; + protected new LegacySkinConfiguration Configuration => (LegacySkinConfiguration)base.Configuration; + public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini") { @@ -37,9 +39,9 @@ namespace osu.Game.Skinning Stream stream = storage?.GetStream(filename); if (stream != null) using (LineBufferedReader reader = new LineBufferedReader(stream)) - Configuration = new LegacySkinDecoder().Decode(reader); + base.Configuration = new LegacySkinDecoder().Decode(reader); else - Configuration = new DefaultSkinConfiguration(); + base.Configuration = new LegacySkinConfiguration { LegacyVersion = LegacySkinConfiguration.LATEST_VERSION }; if (storage != null) { @@ -71,6 +73,18 @@ namespace osu.Game.Skinning case GlobalSkinColour colour: return SkinUtils.As(getCustomColour(colour.ToString())); + case LegacySkinConfigurations legacy: + switch (legacy) + { + case LegacySkinConfigurations.Version: + if (Configuration.LegacyVersion.HasValue) + return SkinUtils.As(new BindableDouble(Configuration.LegacyVersion.Value)); + + break; + } + + break; + case SkinCustomColourLookup customColour: return SkinUtils.As(getCustomColour(customColour.Lookup.ToString())); diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs new file mode 100644 index 0000000000..022f613562 --- /dev/null +++ b/osu.Game/Skinning/LegacySkinConfiguration.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Skinning +{ + public class LegacySkinConfiguration : DefaultSkinConfiguration + { + public const double LATEST_VERSION = 2.5; + + /// + /// Legacy version of this skin. + /// + public double? LegacyVersion { get; internal set; } + } + + public enum LegacySkinConfigurations + { + Version, + } +} From 7f6541672c9c3d3e30673e47c7d7a1b0ab630f1b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 23:05:50 +0300 Subject: [PATCH 3377/5608] Parse legacy version of decoded skin to numerical --- osu.Game/Skinning/LegacySkinDecoder.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index e97664e75e..75cd0a666d 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -5,14 +5,14 @@ using osu.Game.Beatmaps.Formats; namespace osu.Game.Skinning { - public class LegacySkinDecoder : LegacyDecoder + public class LegacySkinDecoder : LegacyDecoder { public LegacySkinDecoder() : base(1) { } - protected override void ParseLine(DefaultSkinConfiguration skin, Section section, string line) + protected override void ParseLine(LegacySkinConfiguration skin, Section section, string line) { if (section != Section.Colours) { @@ -32,6 +32,14 @@ namespace osu.Game.Skinning case @"Author": skin.SkinInfo.Creator = pair.Value; return; + + case @"Version": + if (pair.Value == "latest" || pair.Value == "User") + skin.LegacyVersion = LegacySkinConfiguration.LATEST_VERSION; + else if (double.TryParse(pair.Value, out var version)) + skin.LegacyVersion = version; + + return; } break; From 01ac19fdbb96cea3f36da3ce4b5ed39d1994658a Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 23:06:32 +0300 Subject: [PATCH 3378/5608] Set legacy version of osu!classic skin to 2.0 --- osu.Game/Skinning/DefaultLegacySkin.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index 4b6eea6b6e..4c68ee938f 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -20,6 +20,8 @@ namespace osu.Game.Skinning new Color4(18, 124, 255, 255), new Color4(242, 24, 57, 255), }); + + Configuration.LegacyVersion = 2.0; } public static SkinInfo Info { get; } = new SkinInfo From d15db378ce2598a66f5bdad3958d964dbd1b869b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 23:06:53 +0300 Subject: [PATCH 3379/5608] Add tests for legacy skin decoding --- osu.Game.Tests/Resources/skin-20.ini | 2 ++ osu.Game.Tests/Resources/skin-latest.ini | 2 ++ osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 11 +++++++++++ 3 files changed, 15 insertions(+) create mode 100644 osu.Game.Tests/Resources/skin-20.ini create mode 100644 osu.Game.Tests/Resources/skin-latest.ini diff --git a/osu.Game.Tests/Resources/skin-20.ini b/osu.Game.Tests/Resources/skin-20.ini new file mode 100644 index 0000000000..947b56b2f9 --- /dev/null +++ b/osu.Game.Tests/Resources/skin-20.ini @@ -0,0 +1,2 @@ +[General] +Version: 2 \ No newline at end of file diff --git a/osu.Game.Tests/Resources/skin-latest.ini b/osu.Game.Tests/Resources/skin-latest.ini new file mode 100644 index 0000000000..32f500263f --- /dev/null +++ b/osu.Game.Tests/Resources/skin-latest.ini @@ -0,0 +1,2 @@ +[General] +Version: latest \ No newline at end of file diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 0d96dd08da..8c85074456 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -56,5 +56,16 @@ namespace osu.Game.Tests.Skins Assert.AreEqual("TestValue", config.ConfigDictionary["TestLookup"]); } } + + [TestCase("skin-20.ini", 2.0)] + [TestCase("skin-latest.ini", LegacySkinConfiguration.LATEST_VERSION)] + [TestCase("skin-empty.ini", null)] + public void TestDecodeVersion(string filename, double? expected) + { + var decoder = new LegacySkinDecoder(); + using (var resStream = TestResources.OpenResource(filename)) + using (var stream = new LineBufferedReader(resStream)) + Assert.AreEqual(expected, decoder.Decode(stream).LegacyVersion); + } } } From 2cf17e0bf38455d465d2f59e7c9552255dde2766 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 23:33:25 +0300 Subject: [PATCH 3380/5608] Use decimal data type instead --- osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 28 +++++++++++++++---- osu.Game/Skinning/DefaultLegacySkin.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 2 +- osu.Game/Skinning/LegacySkinConfiguration.cs | 4 +-- osu.Game/Skinning/LegacySkinDecoder.cs | 2 +- 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 8c85074456..4fee6942d0 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -57,15 +57,31 @@ namespace osu.Game.Tests.Skins } } - [TestCase("skin-20.ini", 2.0)] - [TestCase("skin-latest.ini", LegacySkinConfiguration.LATEST_VERSION)] - [TestCase("skin-empty.ini", null)] - public void TestDecodeVersion(string filename, double? expected) + [Test] + public void TestDecodeSpecifiedVersion() { var decoder = new LegacySkinDecoder(); - using (var resStream = TestResources.OpenResource(filename)) + using (var resStream = TestResources.OpenResource("skin-20.ini")) using (var stream = new LineBufferedReader(resStream)) - Assert.AreEqual(expected, decoder.Decode(stream).LegacyVersion); + Assert.AreEqual(2.0m, decoder.Decode(stream).LegacyVersion); + } + + [Test] + public void TestDecodeLatestVersion() + { + var decoder = new LegacySkinDecoder(); + using (var resStream = TestResources.OpenResource("skin-latest.ini")) + using (var stream = new LineBufferedReader(resStream)) + Assert.AreEqual(LegacySkinConfiguration.LATEST_VERSION, decoder.Decode(stream).LegacyVersion); + } + + [Test] + public void TestDecodeNoVersion() + { + var decoder = new LegacySkinDecoder(); + using (var resStream = TestResources.OpenResource("skin-empty.ini")) + using (var stream = new LineBufferedReader(resStream)) + Assert.IsNull(decoder.Decode(stream).LegacyVersion); } } } diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index 4c68ee938f..0caf2d19e9 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -21,7 +21,7 @@ namespace osu.Game.Skinning new Color4(242, 24, 57, 255), }); - Configuration.LegacyVersion = 2.0; + Configuration.LegacyVersion = 2.0m; } public static SkinInfo Info { get; } = new SkinInfo diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 25703b30dc..f6a366b21d 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -78,7 +78,7 @@ namespace osu.Game.Skinning { case LegacySkinConfigurations.Version: if (Configuration.LegacyVersion.HasValue) - return SkinUtils.As(new BindableDouble(Configuration.LegacyVersion.Value)); + return SkinUtils.As(new Bindable(Configuration.LegacyVersion.Value)); break; } diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs index 022f613562..051d10747b 100644 --- a/osu.Game/Skinning/LegacySkinConfiguration.cs +++ b/osu.Game/Skinning/LegacySkinConfiguration.cs @@ -5,12 +5,12 @@ namespace osu.Game.Skinning { public class LegacySkinConfiguration : DefaultSkinConfiguration { - public const double LATEST_VERSION = 2.5; + public const decimal LATEST_VERSION = 2.5m; /// /// Legacy version of this skin. /// - public double? LegacyVersion { get; internal set; } + public decimal? LegacyVersion { get; internal set; } } public enum LegacySkinConfigurations diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 75cd0a666d..ea087353a0 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -36,7 +36,7 @@ namespace osu.Game.Skinning case @"Version": if (pair.Value == "latest" || pair.Value == "User") skin.LegacyVersion = LegacySkinConfiguration.LATEST_VERSION; - else if (double.TryParse(pair.Value, out var version)) + else if (decimal.TryParse(pair.Value, out var version)) skin.LegacyVersion = version; return; From f74c79c2b85422fda49a147c2ee0d9441bbd49df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Oct 2019 11:58:43 +0900 Subject: [PATCH 3381/5608] Fix audio playback position being reset after resuming to song select --- .../Visual/Menus/TestSceneScreenNavigation.cs | 80 ++++++++++++++----- osu.Game/Screens/Select/SongSelect.cs | 12 ++- 2 files changed, 68 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index 17535cae98..124d3bb453 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -5,12 +5,15 @@ using System; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio.Track; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Testing; +using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; @@ -18,7 +21,9 @@ using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Screens; using osu.Game.Screens.Menu; +using osu.Game.Screens.Play; using osu.Game.Screens.Select; +using osu.Game.Tests.Beatmaps.IO; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -31,11 +36,11 @@ namespace osu.Game.Tests.Visual.Menus private const float click_padding = 25; private GameHost host; - private TestOsuGame osuGame; + private TestOsuGame game; - private Vector2 backButtonPosition => osuGame.ToScreenSpace(new Vector2(click_padding, osuGame.LayoutRectangle.Bottom - click_padding)); + private Vector2 backButtonPosition => game.ToScreenSpace(new Vector2(click_padding, game.LayoutRectangle.Bottom - click_padding)); - private Vector2 optionsButtonPosition => osuGame.ToScreenSpace(new Vector2(click_padding, click_padding)); + private Vector2 optionsButtonPosition => game.ToScreenSpace(new Vector2(click_padding, click_padding)); [BackgroundDependencyLoader] private void load(GameHost host) @@ -54,23 +59,23 @@ namespace osu.Game.Tests.Visual.Menus { AddStep("Create new game instance", () => { - if (osuGame != null) + if (game != null) { - Remove(osuGame); - osuGame.Dispose(); + Remove(game); + game.Dispose(); } - osuGame = new TestOsuGame(LocalStorage, API); - osuGame.SetHost(host); + game = new TestOsuGame(LocalStorage, API); + game.SetHost(host); // todo: this can be removed once we can run audio trakcs without a device present // see https://github.com/ppy/osu/issues/1302 - osuGame.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles); + game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles); - Add(osuGame); + Add(game); }); - AddUntilStep("Wait for load", () => osuGame.IsLoaded); - AddUntilStep("Wait for intro", () => osuGame.ScreenStack.CurrentScreen is IntroScreen); + AddUntilStep("Wait for load", () => game.IsLoaded); + AddUntilStep("Wait for intro", () => game.ScreenStack.CurrentScreen is IntroScreen); confirmAtMainMenu(); } @@ -82,11 +87,39 @@ namespace osu.Game.Tests.Visual.Menus pushAndConfirm(() => songSelect = new TestSongSelect()); AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show()); AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); - AddStep("Press escape", () => pressAndRelease(Key.Escape)); + pushEscape(); AddAssert("Overlay was hidden", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden); exitViaEscapeAndConfirm(); } + [Test] + public void TestSongContinuesAfterExitPlayer() + { + Player player = null; + + WorkingBeatmap beatmap() => game.Beatmap.Value; + Track track() => beatmap().Track; + + pushAndConfirm(() => new TestSongSelect()); + + AddStep("import beatmap", () => ImportBeatmapTest.LoadOszIntoOsu(game).Wait()); + + AddUntilStep("wait for selected", () => !(track() is TrackVirtual)); + + AddStep("press enter", () => pressAndRelease(Key.Enter)); + + AddUntilStep("wait for player", () => (player = game.ScreenStack.CurrentScreen as Player) != null); + AddUntilStep("wait for fail", () => player.HasFailed); + + AddUntilStep("wait for track stop", () => !track().IsRunning); + AddAssert("Ensure time before preview point", () => track().CurrentTime < beatmap().Metadata.PreviewTime); + + pushEscape(); + + AddUntilStep("wait for track playing", () => track().IsRunning); + AddAssert("Ensure time wasn't reset to preview point", () => track().CurrentTime < beatmap().Metadata.PreviewTime); + } + [Test] public void TestExitSongSelectWithClick() { @@ -98,7 +131,7 @@ namespace osu.Game.Tests.Visual.Menus AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(backButtonPosition)); // BackButton handles hover using its child button, so this checks whether or not any of BackButton's children are hovered. - AddUntilStep("Back button is hovered", () => InputManager.HoveredDrawables.Any(d => d.Parent == osuGame.BackButton)); + AddUntilStep("Back button is hovered", () => InputManager.HoveredDrawables.Any(d => d.Parent == game.BackButton)); AddStep("Click back button", () => InputManager.Click(MouseButton.Left)); AddUntilStep("Overlay was hidden", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden); @@ -122,25 +155,28 @@ namespace osu.Game.Tests.Visual.Menus [Test] public void TestOpenOptionsAndExitWithEscape() { - AddUntilStep("Wait for options to load", () => osuGame.Settings.IsLoaded); + AddUntilStep("Wait for options to load", () => game.Settings.IsLoaded); AddStep("Enter menu", () => pressAndRelease(Key.Enter)); AddStep("Move mouse to options overlay", () => InputManager.MoveMouseTo(optionsButtonPosition)); AddStep("Click options overlay", () => InputManager.Click(MouseButton.Left)); - AddAssert("Options overlay was opened", () => osuGame.Settings.State.Value == Visibility.Visible); + AddAssert("Options overlay was opened", () => game.Settings.State.Value == Visibility.Visible); AddStep("Hide options overlay using escape", () => pressAndRelease(Key.Escape)); - AddAssert("Options overlay was closed", () => osuGame.Settings.State.Value == Visibility.Hidden); + AddAssert("Options overlay was closed", () => game.Settings.State.Value == Visibility.Hidden); } private void pushAndConfirm(Func newScreen) { Screen screen = null; - AddStep("Push new screen", () => osuGame.ScreenStack.Push(screen = newScreen())); - AddUntilStep("Wait for new screen", () => osuGame.ScreenStack.CurrentScreen == screen && screen.IsLoaded); + AddStep("Push new screen", () => game.ScreenStack.Push(screen = newScreen())); + AddUntilStep("Wait for new screen", () => game.ScreenStack.CurrentScreen == screen && screen.IsLoaded); } + private void pushEscape() => + AddStep("Press escape", () => pressAndRelease(Key.Escape)); + private void exitViaEscapeAndConfirm() { - AddStep("Press escape", () => pressAndRelease(Key.Escape)); + pushEscape(); confirmAtMainMenu(); } @@ -151,7 +187,7 @@ namespace osu.Game.Tests.Visual.Menus confirmAtMainMenu(); } - private void confirmAtMainMenu() => AddUntilStep("Wait for main menu", () => osuGame.ScreenStack.CurrentScreen is MainMenu menu && menu.IsLoaded); + private void confirmAtMainMenu() => AddUntilStep("Wait for main menu", () => game.ScreenStack.CurrentScreen is MainMenu menu && menu.IsLoaded); private void pressAndRelease(Key key) { @@ -169,6 +205,8 @@ namespace osu.Game.Tests.Visual.Menus public new OsuConfigManager LocalConfig => base.LocalConfig; + public new Bindable Beatmap => base.Beatmap; + protected override Loader CreateLoader() => new TestLoader(); public TestOsuGame(Storage storage, IAPIProvider api) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 6c5f64ed6c..0025188ad4 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -490,7 +490,7 @@ namespace osu.Game.Screens.Select if (Beatmap != null && !Beatmap.Value.BeatmapSetInfo.DeletePending) { UpdateBeatmap(Beatmap.Value); - ensurePlayingSelected(); + ensurePlayingSelected(false); } base.OnResuming(last); @@ -587,7 +587,8 @@ namespace osu.Game.Screens.Select /// Ensures some music is playing for the current track. /// Will resume playback from a manual user pause if the track has changed. ///
- private void ensurePlayingSelected() + /// Whether to restart from the preview point, rather than resuming from previous location. + private void ensurePlayingSelected(bool fromPreviewPoint = true) { Track track = Beatmap.Value.Track; @@ -596,7 +597,12 @@ namespace osu.Game.Screens.Select track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; if (!track.IsRunning && (music?.IsUserPaused != true || isNewTrack)) - track.Restart(); + { + if (fromPreviewPoint) + track.Restart(); + else + track.Start(); + } lastTrack.SetTarget(track); } From e66f9adb8653a68b570d7fbee47f8854a7f61084 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Oct 2019 16:52:51 +0900 Subject: [PATCH 3382/5608] Fix user pause not being cancelled when playing audio --- osu.Game/Overlays/MusicController.cs | 45 ++++++++++++++++++--------- osu.Game/Screens/Select/SongSelect.cs | 7 +---- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index f5c36a9cac..2547d7515e 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -98,20 +98,13 @@ namespace osu.Game.Overlays /// /// Start playing the current track (if not already playing). /// - public void Play() - { - if (!IsPlaying) - TogglePause(); - } - - /// - /// Toggle pause / play. - /// /// Whether the operation was successful. - public bool TogglePause() + public bool Play(bool restart = false) { var track = current?.Track; + IsUserPaused = false; + if (track == null) { if (beatmap.Disabled) @@ -121,16 +114,40 @@ namespace osu.Game.Overlays return true; } + if (restart) + track.Restart(); + else if (!IsPlaying) + track.Start(); + + return true; + } + + /// + /// Stop playing the current track and pause at the current position. + /// + public void Stop() + { + var track = current?.Track; + if (track.IsRunning) { IsUserPaused = true; track.Stop(); } + } + + /// + /// Toggle pause / play. + /// + /// Whether the operation was successful. + public bool TogglePause() + { + var track = current?.Track; + + if (track?.IsRunning == true) + Stop(); else - { - track.Start(); - IsUserPaused = false; - } + Play(); return true; } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 0025188ad4..8187dd04d1 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -597,12 +597,7 @@ namespace osu.Game.Screens.Select track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; if (!track.IsRunning && (music?.IsUserPaused != true || isNewTrack)) - { - if (fromPreviewPoint) - track.Restart(); - else - track.Start(); - } + music?.Play(fromPreviewPoint); lastTrack.SetTarget(track); } From 65df7902f3f933baa68df1df3211f0077147b40f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 10 Oct 2019 08:15:47 +0000 Subject: [PATCH 3383/5608] Bump ppy.osu.Framework.NativeLibs from 2019.813.0 to 2019.1010.0 Bumps [ppy.osu.Framework.NativeLibs](https://github.com/ppy/osu-framework) from 2019.813.0 to 2019.1010.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.813.0...2019.1010.0) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index a15cae55c4..e59f613c98 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -124,6 +124,6 @@ - +
From efa5cedf4fef1c3393fdb6ef5926873072c8e6c5 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 10 Oct 2019 08:16:07 +0000 Subject: [PATCH 3384/5608] Bump ppy.osu.Framework.Android from 2019.930.0 to 2019.1010.0 Bumps [ppy.osu.Framework.Android](https://github.com/ppy/osu-framework) from 2019.930.0 to 2019.1010.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.930.0...2019.1010.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index 51245351b6..fa940a7c89 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ - + From bc4c1a237140da50f9958fcaf3ee7b0535e945db Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 10 Oct 2019 08:16:28 +0000 Subject: [PATCH 3385/5608] Bump ppy.osu.Framework from 2019.930.0 to 2019.1010.0 Bumps [ppy.osu.Framework](https://github.com/ppy/osu-framework) from 2019.930.0 to 2019.1010.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.930.0...2019.1010.0) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8cbc8b0af3..4e3130b64c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index a15cae55c4..8a9dc01f38 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,7 +118,7 @@ - + From e50d8419fda384b0f57a11e0bf4d838ab66d8783 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 10 Oct 2019 08:30:37 +0000 Subject: [PATCH 3386/5608] Bump ppy.osu.Framework.iOS from 2019.930.0 to 2019.1010.0 Bumps [ppy.osu.Framework.iOS](https://github.com/ppy/osu-framework) from 2019.930.0 to 2019.1010.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.930.0...2019.1010.0) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index a15cae55c4..7069960ce1 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -119,7 +119,7 @@ - + From 8df2e359c48d458cebaa3923e9d7342428259be2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Oct 2019 17:39:41 +0900 Subject: [PATCH 3387/5608] Fix tests on CI --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 4 ++-- osu.Game.Tests/Resources/TestResources.cs | 6 +++--- osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 6da8d8cb71..b24171a231 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -456,9 +456,9 @@ namespace osu.Game.Tests.Beatmaps.IO } } - public static async Task LoadOszIntoOsu(OsuGameBase osu, string path = null) + public static async Task LoadOszIntoOsu(OsuGameBase osu, string path = null, bool virtualTrack = false) { - var temp = path ?? TestResources.GetTestBeatmapForImport(); + var temp = path ?? TestResources.GetTestBeatmapForImport(virtualTrack); var manager = osu.Dependencies.Get(); diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index 9cb85a63bf..66084a3204 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -11,13 +11,13 @@ namespace osu.Game.Tests.Resources { public static Stream OpenResource(string name) => new DllResourceStore("osu.Game.Tests.dll").GetStream($"Resources/{name}"); - public static Stream GetTestBeatmapStream() => new DllResourceStore("osu.Game.Resources.dll").GetStream("Beatmaps/241526 Soleily - Renatus.osz"); + public static Stream GetTestBeatmapStream(bool virtualTrack = false) => new DllResourceStore("osu.Game.Resources.dll").GetStream($"Beatmaps/241526 Soleily - Renatus{(virtualTrack ? "_virtual" : "")}.osz"); - public static string GetTestBeatmapForImport() + public static string GetTestBeatmapForImport(bool virtualTrack = false) { var temp = Path.GetTempFileName() + ".osz"; - using (var stream = GetTestBeatmapStream()) + using (var stream = GetTestBeatmapStream(virtualTrack)) using (var newFile = File.Create(temp)) stream.CopyTo(newFile); diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index 124d3bb453..e74992e37a 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -102,9 +102,9 @@ namespace osu.Game.Tests.Visual.Menus pushAndConfirm(() => new TestSongSelect()); - AddStep("import beatmap", () => ImportBeatmapTest.LoadOszIntoOsu(game).Wait()); + AddStep("import beatmap", () => ImportBeatmapTest.LoadOszIntoOsu(game, virtualTrack: true).Wait()); - AddUntilStep("wait for selected", () => !(track() is TrackVirtual)); + AddUntilStep("wait for selected", () => !game.Beatmap.IsDefault); AddStep("press enter", () => pressAndRelease(Key.Enter)); From f6b78ad6617508f49654c86696585b934c83a8d2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 10 Oct 2019 11:43:45 +0300 Subject: [PATCH 3388/5608] Overall cleanups --- .../Online/API/Requests/GetCommentsRequest.cs | 8 +-- .../Overlays/Comments/CommentsContainer.cs | 4 +- osu.Game/Overlays/Comments/CommentsHeader.cs | 3 +- .../Comments/DeletedChildsPlaceholder.cs | 3 +- osu.Game/Overlays/Comments/DrawableComment.cs | 59 +++++++------------ osu.Game/Overlays/Comments/SortSelector.cs | 8 ++- 6 files changed, 35 insertions(+), 50 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetCommentsRequest.cs b/osu.Game/Online/API/Requests/GetCommentsRequest.cs index 02a36f7aa2..fb30130ee9 100644 --- a/osu.Game/Online/API/Requests/GetCommentsRequest.cs +++ b/osu.Game/Online/API/Requests/GetCommentsRequest.cs @@ -4,6 +4,7 @@ using osu.Framework.IO.Network; using Humanizer; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays.Comments; namespace osu.Game.Online.API.Requests { @@ -43,11 +44,4 @@ namespace osu.Game.Online.API.Requests Beatmapset, NewsPost } - - public enum SortCommentsBy - { - New, - Old, - Top - } } diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index bf68457988..314376f5ff 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -91,7 +91,9 @@ namespace osu.Game.Overlays.Comments { if (c.IsTopLevel) content.Add(new DrawableComment(c) - { ShowDeleted = { BindTarget = ShowDeleted } }); + { + ShowDeleted = { BindTarget = ShowDeleted } + }); } int deletedComments = 0; diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index 90a6f44d6b..6e9864f153 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -3,7 +3,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; -using osu.Game.Online.API.Requests; using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; @@ -62,7 +61,7 @@ namespace osu.Game.Overlays.Comments { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Current = { BindTarget = Sort } + Current = Sort } } }, diff --git a/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs b/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs index d0e6c17ccb..7aae42908e 100644 --- a/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs +++ b/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs @@ -7,6 +7,7 @@ using osu.Game.Graphics; using osu.Framework.Graphics.Sprites; using osuTK; using osu.Framework.Bindables; +using System.Linq; namespace osu.Game.Overlays.Comments { @@ -38,7 +39,7 @@ namespace osu.Game.Overlays.Comments new SpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), - Text = $@"{count} deleted comments" + Text = $@"{count} deleted comment{(count.ToString().ToCharArray().Last() == '1' ? "" : "s")}" } }; } diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 4af2e07227..fd7f874304 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Comments private readonly BindableBool childExpanded = new BindableBool(true); - private readonly Container childCommentsVisibilityContainer; + private readonly FillFlowContainer childCommentsVisibilityContainer; private readonly Comment comment; public DrawableComment(Comment comment) @@ -47,7 +47,6 @@ namespace osu.Game.Overlays.Comments RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Masking = true; InternalChild = new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -145,7 +144,9 @@ namespace osu.Game.Overlays.Comments Text = HumanizerUtils.Humanize(comment.CreatedAt) }, new RepliesButton(comment.RepliesCount) - { Expanded = { BindTarget = childExpanded } }, + { + Expanded = { BindTarget = childExpanded } + }, } } } @@ -153,29 +154,23 @@ namespace osu.Game.Overlays.Comments } } }, - childCommentsVisibilityContainer = new Container + childCommentsVisibilityContainer = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Masking = true, - Child = new FillFlowContainer + Direction = FillDirection.Vertical, + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] + childCommentsContainer = new FillFlowContainer { - childCommentsContainer = new FillFlowContainer - { - Margin = new MarginPadding { Left = child_margin }, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical - }, - new DeletedChildsPlaceholder(comment.GetDeletedChildsCount()) - { - ShowDeleted = { BindTarget = ShowDeleted } - } + Margin = new MarginPadding { Left = child_margin }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical + }, + new DeletedChildsPlaceholder(comment.GetDeletedChildsCount()) + { + ShowDeleted = { BindTarget = ShowDeleted } } } } @@ -234,7 +229,9 @@ namespace osu.Game.Overlays.Comments } comment.ChildComments.ForEach(c => childCommentsContainer.Add(new DrawableComment(c) - { ShowDeleted = { BindTarget = ShowDeleted } })); + { + ShowDeleted = { BindTarget = ShowDeleted } + })); } protected override void LoadComplete() @@ -246,27 +243,13 @@ namespace osu.Game.Overlays.Comments private void onChildExpandedChanged(ValueChangedEvent expanded) { - if (expanded.NewValue) - childCommentsVisibilityContainer.AutoSizeAxes = Axes.Y; - else - { - childCommentsVisibilityContainer.AutoSizeAxes = Axes.None; - childCommentsVisibilityContainer.ResizeHeightTo(0); - } + childCommentsVisibilityContainer.FadeTo(expanded.NewValue ? 1 : 0); } private void onShowDeletedChanged(ValueChangedEvent show) { if (comment.IsDeleted) - { - if (show.NewValue) - AutoSizeAxes = Axes.Y; - else - { - AutoSizeAxes = Axes.None; - this.ResizeHeightTo(0); - } - } + this.FadeTo(show.NewValue ? 1 : 0); } private class ChevronButton : ShowChildsButton diff --git a/osu.Game/Overlays/Comments/SortSelector.cs b/osu.Game/Overlays/Comments/SortSelector.cs index 4425145c3e..cb95a758ff 100644 --- a/osu.Game/Overlays/Comments/SortSelector.cs +++ b/osu.Game/Overlays/Comments/SortSelector.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Online.API.Requests; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; @@ -72,4 +71,11 @@ namespace osu.Game.Overlays.Comments } } } + + public enum SortCommentsBy + { + New, + Old, + Top + } } From 5d6648d9c95df7f5e05b5008e280f525410ccfe7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Oct 2019 17:45:38 +0900 Subject: [PATCH 3389/5608] Update 2.2 references --- .../CatchRuleset__Tests_.xml | 4 +-- .../ManiaRuleset__Tests_.xml | 4 +-- .../runConfigurations/OsuRuleset__Tests_.xml | 4 +-- .../TaikoRuleset__Tests_.xml | 4 +-- .../.idea/runConfigurations/Tournament.xml | 4 +-- .../.idea/runConfigurations/osu_.xml | 4 +-- .../.idea/runConfigurations/osu___Tests_.xml | 4 +-- .vscode/launch.json | 32 +++++++++---------- .vscode/tasks.json | 2 +- README.md | 4 +-- osu.Desktop/osu.Desktop.csproj | 2 +- .../.vscode/launch.json | 4 +-- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../.vscode/launch.json | 4 +-- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- .../.vscode/launch.json | 4 +-- .../osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../.vscode/launch.json | 4 +-- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- .../osu.Game.Tournament.Tests.csproj | 2 +- 21 files changed, 48 insertions(+), 48 deletions(-) diff --git a/.idea/.idea.osu/.idea/runConfigurations/CatchRuleset__Tests_.xml b/.idea/.idea.osu/.idea/runConfigurations/CatchRuleset__Tests_.xml index 6463dd6ea5..5372b6f28a 100644 --- a/.idea/.idea.osu/.idea/runConfigurations/CatchRuleset__Tests_.xml +++ b/.idea/.idea.osu/.idea/runConfigurations/CatchRuleset__Tests_.xml @@ -1,6 +1,6 @@ -
/// The snapped position. /// The time at the snapped position. - public double GetSnapTime(Vector2 snappedPosition) => startTime + (ToLocalSpace(snappedPosition) - startPosition).Length / Velocity; + public double GetSnapTime(Vector2 snappedPosition) => startTime + (ToLocalSpace(snappedPosition) - StartPosition).Length / Velocity; /// /// Retrieves the applicable colour for a beat index. From 8fb2628f9e07185dbdf1b3211a753839c3561ac1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Oct 2019 15:41:01 +0900 Subject: [PATCH 3418/5608] Improve xmldocs --- .../Edit/Compose/Components/BeatSnapGrid.cs | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs index d44d53dca7..175d61fd32 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs @@ -17,8 +17,14 @@ namespace osu.Game.Screens.Edit.Compose.Components { public abstract class BeatSnapGrid : CompositeDrawable { + /// + /// The velocity of the beatmap at the point of placement in pixels per millisecond. + /// protected double Velocity { get; private set; } + /// + /// The spacing between each tick of the beat snapping grid. + /// protected float DistanceSpacing { get; private set; } protected readonly Vector2 StartPosition; @@ -88,32 +94,32 @@ namespace osu.Game.Screens.Edit.Compose.Components } /// - /// Draws the grid. + /// Creates the content which visualises the grid ticks. /// protected abstract void CreateGrid(Vector2 startPosition); /// - /// Retrieves the velocity of gameplay at a time. + /// Retrieves the velocity of gameplay at a point in time in pixels per millisecond. /// /// The time to retrieve the velocity at. - /// The beatmap's at the requested time. - /// The beatmap's at the requested time. - /// The velocity in pixels per millisecond. + /// The beatmap's at the point in time. + /// The beatmap's at the point in time. + /// The velocity. protected abstract float GetVelocity(double time, ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty); /// - /// Snaps a position to this grid. + /// Snaps a screen-space position to this grid. /// /// The original screen-space position. - /// The snapped position. + /// The snapped screen-space position. public abstract Vector2 GetSnapPosition(Vector2 screenSpacePosition); /// - /// Retrieves the time at a snapped position. + /// Retrieves the time at a snapped screen-space position. /// - /// The snapped position. + /// The snapped screen-space position. /// The time at the snapped position. - public double GetSnapTime(Vector2 snappedPosition) => startTime + (ToLocalSpace(snappedPosition) - StartPosition).Length / Velocity; + public double GetSnapTime(Vector2 screenSpacePosition) => startTime + (ToLocalSpace(screenSpacePosition) - CentrePosition).Length / Velocity; /// /// Retrieves the applicable colour for a beat index. From 5f0cd356d764ffab48ab4396c18f4a017600e4f0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Oct 2019 15:41:21 +0900 Subject: [PATCH 3419/5608] Rename startPosition to centrePosition --- osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs | 4 ++-- .../Screens/Edit/Compose/Components/BeatSnapGrid.cs | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs index 6419b0c2e2..9f9b884cdd 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs @@ -133,8 +133,8 @@ namespace osu.Game.Tests.Visual.Editor public new float DistanceSpacing => base.DistanceSpacing; - public TestBeatSnapGrid(HitObject hitObject, Vector2 startPosition) - : base(hitObject, startPosition) + public TestBeatSnapGrid(HitObject hitObject, Vector2 centrePosition) + : base(hitObject, centrePosition) { } diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs index 175d61fd32..24926995e6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs @@ -27,7 +27,11 @@ namespace osu.Game.Screens.Edit.Compose.Components /// protected float DistanceSpacing { get; private set; } - protected readonly Vector2 StartPosition; + /// + /// The position which the grid is centred on. + /// The first beat snapping tick is located at + in the desired direction. + /// + protected readonly Vector2 CentrePosition; [Resolved] private IEditorBeatmap beatmap { get; set; } @@ -44,10 +48,10 @@ namespace osu.Game.Screens.Edit.Compose.Components private double startTime; private double beatLength; - protected BeatSnapGrid(HitObject hitObject, Vector2 startPosition) + protected BeatSnapGrid(HitObject hitObject, Vector2 centrePosition) { this.hitObject = hitObject; - this.StartPosition = startPosition; + this.CentrePosition = centrePosition; RelativeSizeAxes = Axes.Both; } From 9ecec806c2343d90c03eb48b71b264e1f82dba0e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Oct 2019 15:41:40 +0900 Subject: [PATCH 3420/5608] Rename grid creation method + parameter --- .../Visual/Editor/TestSceneBeatSnapGrid.cs | 20 +++++++++---------- .../Edit/Compose/Components/BeatSnapGrid.cs | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs index 9f9b884cdd..345fe245fe 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs @@ -138,63 +138,63 @@ namespace osu.Game.Tests.Visual.Editor { } - protected override void CreateGrid(Vector2 startPosition) + protected override void CreateContent(Vector2 centrePosition) { AddInternal(new Circle { Origin = Anchor.Centre, Size = new Vector2(5), - Position = startPosition + Position = centrePosition }); int beatIndex = 0; - for (float s = startPosition.X + DistanceSpacing; s <= DrawWidth; s += DistanceSpacing, beatIndex++) + for (float s = centrePosition.X + DistanceSpacing; s <= DrawWidth; s += DistanceSpacing, beatIndex++) { AddInternal(new Circle { Origin = Anchor.Centre, Size = new Vector2(5, 10), - Position = new Vector2(s, startPosition.Y), + Position = new Vector2(s, centrePosition.Y), Colour = GetColourForBeatIndex(beatIndex) }); } beatIndex = 0; - for (float s = startPosition.X - DistanceSpacing; s >= 0; s -= DistanceSpacing, beatIndex++) + for (float s = centrePosition.X - DistanceSpacing; s >= 0; s -= DistanceSpacing, beatIndex++) { AddInternal(new Circle { Origin = Anchor.Centre, Size = new Vector2(5, 10), - Position = new Vector2(s, startPosition.Y), + Position = new Vector2(s, centrePosition.Y), Colour = GetColourForBeatIndex(beatIndex) }); } beatIndex = 0; - for (float s = startPosition.Y + DistanceSpacing; s <= DrawHeight; s += DistanceSpacing, beatIndex++) + for (float s = centrePosition.Y + DistanceSpacing; s <= DrawHeight; s += DistanceSpacing, beatIndex++) { AddInternal(new Circle { Origin = Anchor.Centre, Size = new Vector2(10, 5), - Position = new Vector2(startPosition.X, s), + Position = new Vector2(centrePosition.X, s), Colour = GetColourForBeatIndex(beatIndex) }); } beatIndex = 0; - for (float s = startPosition.Y - DistanceSpacing; s >= 0; s -= DistanceSpacing, beatIndex++) + for (float s = centrePosition.Y - DistanceSpacing; s >= 0; s -= DistanceSpacing, beatIndex++) { AddInternal(new Circle { Origin = Anchor.Centre, Size = new Vector2(10, 5), - Position = new Vector2(startPosition.X, s), + Position = new Vector2(centrePosition.X, s), Colour = GetColourForBeatIndex(beatIndex) }); } diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs index 24926995e6..98ad0dd3e8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs @@ -92,7 +92,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (!gridCache.IsValid) { ClearInternal(); - CreateGrid(StartPosition); + CreateContent(CentrePosition); gridCache.Validate(); } } @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Creates the content which visualises the grid ticks. /// - protected abstract void CreateGrid(Vector2 startPosition); + protected abstract void CreateContent(Vector2 centrePosition); /// /// Retrieves the velocity of gameplay at a point in time in pixels per millisecond. From 050d86a741b5908d45ea588d7d25d3f8ae9c079b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Oct 2019 15:46:11 +0900 Subject: [PATCH 3421/5608] Always use the local coordinate space --- .../Visual/Editor/TestSceneBeatSnapGrid.cs | 8 ++++---- .../Edit/Compose/Components/BeatSnapGrid.cs | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs index 345fe245fe..d6ddd4cc86 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs @@ -101,12 +101,12 @@ namespace osu.Game.Tests.Visual.Editor { createGrid(); - Vector2 screenSpacePosition = Vector2.Zero; - AddStep("get first tick position", () => screenSpacePosition = grid.ToScreenSpace(grid_position + new Vector2((float)beat_length, 0))); - AddAssert("snap time is 1 beat away", () => Precision.AlmostEquals(beat_length, grid.GetSnapTime(screenSpacePosition), 0.01)); + Vector2 snapPosition = Vector2.Zero; + AddStep("get first tick position", () => snapPosition = grid_position + new Vector2((float)beat_length, 0)); + AddAssert("snap time is 1 beat away", () => Precision.AlmostEquals(beat_length, grid.GetSnapTime(snapPosition), 0.01)); createGrid(g => g.Velocity = 2, "with velocity = 2"); - AddAssert("snap time is now 0.5 beats away", () => Precision.AlmostEquals(beat_length / 2, grid.GetSnapTime(screenSpacePosition), 0.01)); + AddAssert("snap time is now 0.5 beats away", () => Precision.AlmostEquals(beat_length / 2, grid.GetSnapTime(snapPosition), 0.01)); } private void createGrid(Action func = null, string description = null) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs index 98ad0dd3e8..9040843144 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs @@ -112,18 +112,18 @@ namespace osu.Game.Screens.Edit.Compose.Components protected abstract float GetVelocity(double time, ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty); /// - /// Snaps a screen-space position to this grid. + /// Snaps a position to this grid. /// - /// The original screen-space position. - /// The snapped screen-space position. - public abstract Vector2 GetSnapPosition(Vector2 screenSpacePosition); + /// The original position in coordinate space local to this . + /// The snapped position in coordinate space local to this . + public abstract Vector2 GetSnapPosition(Vector2 position); /// - /// Retrieves the time at a snapped screen-space position. + /// Retrieves the time at a snapped position. /// - /// The snapped screen-space position. + /// The snapped position in coordinate space local to this . /// The time at the snapped position. - public double GetSnapTime(Vector2 screenSpacePosition) => startTime + (ToLocalSpace(screenSpacePosition) - CentrePosition).Length / Velocity; + public double GetSnapTime(Vector2 position) => startTime + (position - CentrePosition).Length / Velocity; /// /// Retrieves the applicable colour for a beat index. From 631f1555547581f0383a864e174683dc54ff9692 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Oct 2019 17:17:08 +0900 Subject: [PATCH 3422/5608] Add grid to make the test not appear empty --- osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs index d6ddd4cc86..073cec7315 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs @@ -32,6 +32,9 @@ namespace osu.Game.Tests.Visual.Editor public TestSceneBeatSnapGrid() { editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); + + createGrid(); } [SetUp] From 6301f837e0b17a8216f2af8a3ee55e064249b16d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Oct 2019 15:27:23 +0900 Subject: [PATCH 3423/5608] Initial implementation of osu! beat snapping grid --- .../TestSceneOsuBeatSnapGrid.cs | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs new file mode 100644 index 0000000000..9f0d59afab --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs @@ -0,0 +1,170 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Edit; +using osu.Game.Screens.Edit.Compose.Components; +using osu.Game.Tests.Visual; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestSceneOsuBeatSnapGrid : ManualInputManagerTestScene + { + private const double beat_length = 100; + private static readonly Vector2 grid_position = new Vector2(512, 384); + + [Cached(typeof(IEditorBeatmap))] + private readonly EditorBeatmap editorBeatmap; + + [Cached] + private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); + + private OsuBeatSnapGrid grid; + private Drawable cursor; + + public TestSceneOsuBeatSnapGrid() + { + editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + } + + [SetUp] + public void Setup() => Schedule(() => + { + Clear(); + + editorBeatmap.ControlPointInfo.TimingPoints.Clear(); + editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); + + beatDivisor.Value = 1; + }); + + protected override bool OnMouseMove(MouseMoveEvent e) + { + base.OnMouseMove(e); + + if (cursor != null) + cursor.Position = grid?.GetSnapPosition(grid.ToLocalSpace(e.ScreenSpaceMousePosition)) ?? e.ScreenSpaceMousePosition; + + return true; + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + [TestCase(4)] + [TestCase(6)] + [TestCase(8)] + [TestCase(12)] + [TestCase(16)] + public void TestBeatDivisor(int divisor) + { + AddStep($"set beat divisor = {divisor}", () => beatDivisor.Value = divisor); + createGrid(); + } + + private void createGrid() + { + AddStep("create grid", () => + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.SlateGray + }, + grid = new OsuBeatSnapGrid(new HitCircle { Position = grid_position }), + cursor = new Circle + { + Origin = Anchor.Centre, + Size = new Vector2(50), + Colour = Color4.Red + } + }; + }); + } + + private abstract class CircularBeatSnapGrid : BeatSnapGrid + { + protected override void CreateGrid(Vector2 startPosition) + { + float maxDistance = Math.Max( + Vector2.Distance(startPosition, Vector2.Zero), + Math.Max( + Vector2.Distance(startPosition, new Vector2(DrawWidth, 0)), + Math.Max( + Vector2.Distance(startPosition, new Vector2(0, DrawHeight)), + Vector2.Distance(startPosition, DrawSize)))); + + int requiredCircles = (int)(maxDistance / DistanceSpacing); + + for (int i = 0; i < requiredCircles; i++) + { + float radius = (i + 1) * DistanceSpacing * 2; + + AddInternal(new CircularProgress + { + Origin = Anchor.Centre, + Position = startPosition, + Current = { Value = 1 }, + Size = new Vector2(radius), + InnerRadius = 4 * 1f / radius, + Colour = GetColourForBeatIndex(i) + }); + } + } + + public override Vector2 GetSnapPosition(Vector2 position) + { + Vector2 direction = position - StartPosition; + float distance = direction.Length; + + float radius = DistanceSpacing; + int radialCount = Math.Max(1, (int)Math.Round(distance / radius)); + + if (radialCount <= 0) + return position; + + Vector2 normalisedDirection = direction * new Vector2(1f / distance); + + return StartPosition + normalisedDirection * radialCount * radius; + } + } + + private class OsuBeatSnapGrid : CircularBeatSnapGrid + { + /// + /// Scoring distance with a speed-adjusted beat length of 1 second. + /// + private const float base_scoring_distance = 100; + + public OsuBeatSnapGrid(OsuHitObject hitObject) + : base(hitObject, hitObject.StackedEndPosition) + { + } + + protected override float GetVelocity(double time, ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) + { + TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(time); + DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(time); + + double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier; + + return (float)(scoringDistance / timingPoint.BeatLength); + } + } + } +} From 4d32a8aa6b5cca76f5b993791ce4e536a4709836 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Oct 2019 17:11:37 +0900 Subject: [PATCH 3424/5608] More tests --- .../TestSceneOsuBeatSnapGrid.cs | 172 +++++++++++++++--- 1 file changed, 145 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs index 9f0d59afab..7baa2f0d72 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs @@ -5,9 +5,11 @@ using System; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Objects; @@ -32,12 +34,13 @@ namespace osu.Game.Rulesets.Osu.Tests [Cached] private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); - private OsuBeatSnapGrid grid; - private Drawable cursor; + private TestOsuBeatSnapGrid grid; public TestSceneOsuBeatSnapGrid() { editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + + createGrid(); } [SetUp] @@ -45,22 +48,14 @@ namespace osu.Game.Rulesets.Osu.Tests { Clear(); + editorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 1; + editorBeatmap.ControlPointInfo.DifficultyPoints.Clear(); editorBeatmap.ControlPointInfo.TimingPoints.Clear(); editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); beatDivisor.Value = 1; }); - protected override bool OnMouseMove(MouseMoveEvent e) - { - base.OnMouseMove(e); - - if (cursor != null) - cursor.Position = grid?.GetSnapPosition(grid.ToLocalSpace(e.ScreenSpaceMousePosition)) ?? e.ScreenSpaceMousePosition; - - return true; - } - [TestCase(1)] [TestCase(2)] [TestCase(3)] @@ -75,6 +70,80 @@ namespace osu.Game.Rulesets.Osu.Tests createGrid(); } + [TestCase(100, 100)] + [TestCase(200, 100)] + public void TestBeatLength(float beatLength, float expectedSpacing) + { + AddStep($"set beat length = {beatLength}", () => + { + editorBeatmap.ControlPointInfo.TimingPoints.Clear(); + editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beatLength }); + }); + + createGrid(); + AddAssert($"spacing = {expectedSpacing}", () => Precision.AlmostEquals(expectedSpacing, grid.DistanceSpacing)); + } + + [TestCase(0.5f, 50)] + [TestCase(1, 100)] + [TestCase(1.5f, 150)] + public void TestSpeedMultiplier(float multiplier, float expectedSpacing) + { + AddStep($"set speed multiplier = {multiplier}", () => + { + editorBeatmap.ControlPointInfo.DifficultyPoints.Clear(); + editorBeatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = multiplier }); + }); + + createGrid(); + AddAssert($"spacing = {expectedSpacing}", () => Precision.AlmostEquals(expectedSpacing, grid.DistanceSpacing)); + } + + [TestCase(0.5f, 50)] + [TestCase(1, 100)] + [TestCase(1.5f, 150)] + public void TestSliderMultiplier(float multiplier, float expectedSpacing) + { + AddStep($"set speed multiplier = {multiplier}", () => editorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = multiplier); + createGrid(); + AddAssert($"spacing = {expectedSpacing}", () => Precision.AlmostEquals(expectedSpacing, grid.DistanceSpacing)); + } + + [Test] + public void TestCursorInCentre() + { + createGrid(); + + AddStep("move mouse to centre", () => InputManager.MoveMouseTo(grid.ToScreenSpace(grid_position))); + assertSnappedDistance((float)beat_length); + } + + [Test] + public void TestCursorBeforeMovementPoint() + { + createGrid(); + + AddStep("move mouse to just before movement point", () => InputManager.MoveMouseTo(grid.ToScreenSpace(grid_position + new Vector2((float)beat_length, 0) * 1.49f))); + assertSnappedDistance((float)beat_length); + } + + [Test] + public void TestCursorAfterMovementPoint() + { + createGrid(); + + AddStep("move mouse to just after movement point", () => InputManager.MoveMouseTo(grid.ToScreenSpace(grid_position + new Vector2((float)beat_length, 0) * 1.51f))); + assertSnappedDistance((float)beat_length * 2); + } + + private void assertSnappedDistance(float expectedDistance) => AddAssert($"snap distance = {expectedDistance}", () => + { + Vector2 snappedPosition = grid.GetSnapPosition(grid.ToLocalSpace(InputManager.CurrentState.Mouse.Position)); + float distance = Vector2.Distance(snappedPosition, grid_position); + + return Precision.AlmostEquals(expectedDistance, distance); + }); + private void createGrid() { AddStep("create grid", () => @@ -86,28 +155,77 @@ namespace osu.Game.Rulesets.Osu.Tests RelativeSizeAxes = Axes.Both, Colour = Color4.SlateGray }, - grid = new OsuBeatSnapGrid(new HitCircle { Position = grid_position }), - cursor = new Circle - { - Origin = Anchor.Centre, - Size = new Vector2(50), - Colour = Color4.Red - } + grid = new TestOsuBeatSnapGrid(new HitCircle { Position = grid_position }), + new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnapPosition(grid.ToLocalSpace(v)) } }; }); } + private class SnappingCursorContainer : CompositeDrawable + { + public Func GetSnapPosition; + + private readonly Drawable cursor; + + public SnappingCursorContainer() + { + RelativeSizeAxes = Axes.Both; + + InternalChild = cursor = new Circle + { + Origin = Anchor.Centre, + Size = new Vector2(50), + Colour = Color4.Red + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + updatePosition(GetContainingInputManager().CurrentState.Mouse.Position); + } + + protected override bool OnMouseMove(MouseMoveEvent e) + { + base.OnMouseMove(e); + + updatePosition(e.ScreenSpaceMousePosition); + return true; + } + + private void updatePosition(Vector2 screenSpacePosition) + { + cursor.Position = GetSnapPosition.Invoke(screenSpacePosition); + } + } + + private class TestOsuBeatSnapGrid : OsuBeatSnapGrid + { + public new float DistanceSpacing => base.DistanceSpacing; + + public TestOsuBeatSnapGrid(OsuHitObject hitObject) + : base(hitObject) + { + } + } + private abstract class CircularBeatSnapGrid : BeatSnapGrid { - protected override void CreateGrid(Vector2 startPosition) + protected CircularBeatSnapGrid(HitObject hitObject, Vector2 centrePosition) + : base(hitObject, centrePosition) + { + } + + protected override void CreateContent(Vector2 centrePosition) { float maxDistance = Math.Max( - Vector2.Distance(startPosition, Vector2.Zero), + Vector2.Distance(centrePosition, Vector2.Zero), Math.Max( - Vector2.Distance(startPosition, new Vector2(DrawWidth, 0)), + Vector2.Distance(centrePosition, new Vector2(DrawWidth, 0)), Math.Max( - Vector2.Distance(startPosition, new Vector2(0, DrawHeight)), - Vector2.Distance(startPosition, DrawSize)))); + Vector2.Distance(centrePosition, new Vector2(0, DrawHeight)), + Vector2.Distance(centrePosition, DrawSize)))); int requiredCircles = (int)(maxDistance / DistanceSpacing); @@ -118,7 +236,7 @@ namespace osu.Game.Rulesets.Osu.Tests AddInternal(new CircularProgress { Origin = Anchor.Centre, - Position = startPosition, + Position = centrePosition, Current = { Value = 1 }, Size = new Vector2(radius), InnerRadius = 4 * 1f / radius, @@ -129,7 +247,7 @@ namespace osu.Game.Rulesets.Osu.Tests public override Vector2 GetSnapPosition(Vector2 position) { - Vector2 direction = position - StartPosition; + Vector2 direction = position - CentrePosition; float distance = direction.Length; float radius = DistanceSpacing; @@ -140,7 +258,7 @@ namespace osu.Game.Rulesets.Osu.Tests Vector2 normalisedDirection = direction * new Vector2(1f / distance); - return StartPosition + normalisedDirection * radialCount * radius; + return CentrePosition + normalisedDirection * radialCount * radius; } } From 45835f97a177597fb236793116382f5b8c7918ea Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Oct 2019 17:13:28 +0900 Subject: [PATCH 3425/5608] Split out grids into separate files --- .../TestSceneOsuBeatSnapGrid.cs | 80 +------------------ osu.Game.Rulesets.Osu/Edit/OsuBeatSnapGrid.cs | 33 ++++++++ .../Components/CircularBeatSnapGrid.cs | 63 +++++++++++++++ 3 files changed, 97 insertions(+), 79 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Edit/OsuBeatSnapGrid.cs create mode 100644 osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs index 7baa2f0d72..7399f12372 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs @@ -7,16 +7,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.MathUtils; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit; -using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Tests.Visual; using osuTK; using osuTK.Graphics; @@ -209,80 +206,5 @@ namespace osu.Game.Rulesets.Osu.Tests { } } - - private abstract class CircularBeatSnapGrid : BeatSnapGrid - { - protected CircularBeatSnapGrid(HitObject hitObject, Vector2 centrePosition) - : base(hitObject, centrePosition) - { - } - - protected override void CreateContent(Vector2 centrePosition) - { - float maxDistance = Math.Max( - Vector2.Distance(centrePosition, Vector2.Zero), - Math.Max( - Vector2.Distance(centrePosition, new Vector2(DrawWidth, 0)), - Math.Max( - Vector2.Distance(centrePosition, new Vector2(0, DrawHeight)), - Vector2.Distance(centrePosition, DrawSize)))); - - int requiredCircles = (int)(maxDistance / DistanceSpacing); - - for (int i = 0; i < requiredCircles; i++) - { - float radius = (i + 1) * DistanceSpacing * 2; - - AddInternal(new CircularProgress - { - Origin = Anchor.Centre, - Position = centrePosition, - Current = { Value = 1 }, - Size = new Vector2(radius), - InnerRadius = 4 * 1f / radius, - Colour = GetColourForBeatIndex(i) - }); - } - } - - public override Vector2 GetSnapPosition(Vector2 position) - { - Vector2 direction = position - CentrePosition; - float distance = direction.Length; - - float radius = DistanceSpacing; - int radialCount = Math.Max(1, (int)Math.Round(distance / radius)); - - if (radialCount <= 0) - return position; - - Vector2 normalisedDirection = direction * new Vector2(1f / distance); - - return CentrePosition + normalisedDirection * radialCount * radius; - } - } - - private class OsuBeatSnapGrid : CircularBeatSnapGrid - { - /// - /// Scoring distance with a speed-adjusted beat length of 1 second. - /// - private const float base_scoring_distance = 100; - - public OsuBeatSnapGrid(OsuHitObject hitObject) - : base(hitObject, hitObject.StackedEndPosition) - { - } - - protected override float GetVelocity(double time, ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) - { - TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(time); - DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(time); - - double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier; - - return (float)(scoringDistance / timingPoint.BeatLength); - } - } } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBeatSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuBeatSnapGrid.cs new file mode 100644 index 0000000000..d453e3d062 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/OsuBeatSnapGrid.cs @@ -0,0 +1,33 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Edit.Compose.Components; + +namespace osu.Game.Rulesets.Osu.Edit +{ + public class OsuBeatSnapGrid : CircularBeatSnapGrid + { + /// + /// Scoring distance with a speed-adjusted beat length of 1 second. + /// + private const float base_scoring_distance = 100; + + public OsuBeatSnapGrid(OsuHitObject hitObject) + : base(hitObject, hitObject.StackedEndPosition) + { + } + + protected override float GetVelocity(double time, ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) + { + TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(time); + DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(time); + + double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier; + + return (float)(scoringDistance / timingPoint.BeatLength); + } + } +} diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs new file mode 100644 index 0000000000..8492771808 --- /dev/null +++ b/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs @@ -0,0 +1,63 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Rulesets.Objects; +using osuTK; + +namespace osu.Game.Screens.Edit.Compose.Components +{ + public abstract class CircularBeatSnapGrid : BeatSnapGrid + { + protected CircularBeatSnapGrid(HitObject hitObject, Vector2 centrePosition) + : base(hitObject, centrePosition) + { + } + + protected override void CreateContent(Vector2 centrePosition) + { + float maxDistance = Math.Max( + Vector2.Distance(centrePosition, Vector2.Zero), + Math.Max( + Vector2.Distance(centrePosition, new Vector2(DrawWidth, 0)), + Math.Max( + Vector2.Distance(centrePosition, new Vector2(0, DrawHeight)), + Vector2.Distance(centrePosition, DrawSize)))); + + int requiredCircles = (int)(maxDistance / DistanceSpacing); + + for (int i = 0; i < requiredCircles; i++) + { + float radius = (i + 1) * DistanceSpacing * 2; + + AddInternal(new CircularProgress + { + Origin = Anchor.Centre, + Position = centrePosition, + Current = { Value = 1 }, + Size = new Vector2(radius), + InnerRadius = 4 * 1f / radius, + Colour = GetColourForBeatIndex(i) + }); + } + } + + public override Vector2 GetSnapPosition(Vector2 position) + { + Vector2 direction = position - CentrePosition; + float distance = direction.Length; + + float radius = DistanceSpacing; + int radialCount = Math.Max(1, (int)Math.Round(distance / radius)); + + if (radialCount <= 0) + return position; + + Vector2 normalisedDirection = direction * new Vector2(1f / distance); + + return CentrePosition + normalisedDirection * radialCount * radius; + } + } +} From 3008ade8a2b2182c1daf8a4afb52b1769eb5bb8e Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Fri, 11 Oct 2019 16:41:54 +0700 Subject: [PATCH 3426/5608] Using enum to determine the action --- osu.Game/Overlays/MusicController.cs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 9b54a6c9a6..12de2019cb 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -27,6 +27,8 @@ namespace osu.Game.Overlays public IBindableList BeatmapSets => beatmapSets; + private const double restart_cutoff_point = 5000; + private readonly BindableList beatmapSets = new BindableList(); public bool IsUserPaused { get; private set; } @@ -135,22 +137,26 @@ namespace osu.Game.Overlays return true; } + private PreviousButtonAction? prevAction; + /// - /// Play the previous track or restart the current track if it's current time below 5000ms + /// Play the previous track or restart the current track if it's current time below /// /// Whether the operation was successful. public bool PrevTrack() { var currentTrackPosition = current?.Track.CurrentTime; - if (currentTrackPosition >= 5000) + if (currentTrackPosition >= restart_cutoff_point) { SeekTo(0); + prevAction = PreviousButtonAction.Restart; return true; } queuedDirection = TrackChangeDirection.Prev; + prevAction = PreviousButtonAction.Previous; var playable = BeatmapSets.TakeWhile(i => i.ID != current.BeatmapSetInfo.ID).LastOrDefault() ?? BeatmapSets.LastOrDefault(); @@ -269,9 +275,8 @@ namespace osu.Game.Overlays return true; case GlobalAction.MusicPrev: - var shouldRestart = current?.Track.CurrentTime >= 5000; if (PrevTrack()) - onScreenDisplay?.Display(new MusicControllerToast(shouldRestart ? "Restart track" : "Previous track")); + onScreenDisplay?.Display(new MusicControllerToast(prevAction == PreviousButtonAction.Restart ? "Restart track" : "Previous track")); return true; } @@ -296,4 +301,11 @@ namespace osu.Game.Overlays Next, Prev } + + internal enum PreviousButtonAction + { + None, + Restart, + Previous + } } From de13320a2debb7c48d46691ea5a34a0b09d722a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 Oct 2019 18:46:05 +0900 Subject: [PATCH 3427/5608] Add initial table display --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 187 ++++++++++++++++--- 1 file changed, 160 insertions(+), 27 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index b723ffac9a..be7058ae08 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -1,12 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Globalization; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -15,6 +21,9 @@ namespace osu.Game.Screens.Edit.Timing { public class TimingScreen : EditorScreenWithTimeline { + [Cached] + private readonly Bindable controlPoint = new Bindable(); + protected override Drawable CreateMainContent() => new GridContainer { RelativeSizeAxes = Axes.Both, @@ -53,37 +62,13 @@ namespace osu.Game.Screens.Edit.Timing new OsuScrollContainer { RelativeSizeAxes = Axes.Both, - Child = new FillFlowContainer + Child = new ControlPointTable { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new ControlPointRow(), - new ControlPointRow(), - new ControlPointRow(), - new ControlPointRow(), - new ControlPointRow(), - new ControlPointRow(), - } - }, + ControlPoints = Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints + } } }; } - - private class ControlPointRow : CompositeDrawable - { - public ControlPointRow() - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - InternalChildren = new Drawable[] - { - new OsuSpriteText { Text = "sample row" }, - }; - } - } } public class ControlPointSettings : CompositeDrawable @@ -101,4 +86,152 @@ namespace osu.Game.Screens.Edit.Timing } } } + + public class ControlPointTable : TableContainer + { + private const float horizontal_inset = 20; + private const float row_height = 25; + private const int text_size = 14; + + private readonly FillFlowContainer backgroundFlow; + + [Resolved] + private Bindable controlPoint { get; set; } + + public ControlPointTable() + { + 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, + Padding = new MarginPadding { Horizontal = -horizontal_inset }, + Margin = new MarginPadding { Top = row_height } + }); + } + + public IReadOnlyList ControlPoints + { + set + { + Content = null; + backgroundFlow.Clear(); + + if (value?.Any() != true) + return; + + for (int i = 0; i < value.Count; i++) + { + var cp = value[i]; + backgroundFlow.Add(new RowBackground { Action = () => controlPoint.Value = cp }); + } + + Columns = createHeaders(); + Content = value.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); + } + } + + private TableColumn[] createHeaders() + { + var columns = new List + { + new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("offset", Anchor.Centre), + new TableColumn("BPM", Anchor.Centre), + new TableColumn("Meter", Anchor.Centre), + new TableColumn("Sample Set", Anchor.Centre), + new TableColumn("Volume", Anchor.Centre), + }; + + return columns.ToArray(); + } + + private Drawable[] createContent(int index, ControlPoint controlPoint) + { + return new Drawable[] + { + new OsuSpriteText + { + Text = $"#{index + 1}", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) + }, + new OsuSpriteText + { + Text = $"{controlPoint.Time}", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) + }, + new OsuSpriteText + { + Text = $"{(controlPoint as TimingControlPoint)?.BeatLength.ToString(CultureInfo.InvariantCulture) ?? "-"}", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) + }, + new OsuSpriteText + { + Text = $"{(controlPoint as TimingControlPoint)?.TimeSignature.ToString() ?? "-"}", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) + }, + }; + } + + protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty); + + private class HeaderText : OsuSpriteText + { + public HeaderText(string text) + { + Text = text.ToUpper(); + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black); + } + } + + public class RowBackground : OsuClickableContainer + { + private const int fade_duration = 100; + + private readonly Box hoveredBackground; + + public RowBackground() + { + RelativeSizeAxes = Axes.X; + Height = 25; + + AlwaysPresent = true; + + CornerRadius = 3; + Masking = true; + + Children = new Drawable[] + { + hoveredBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + hoveredBackground.Colour = colours.Blue; + } + + protected override bool OnHover(HoverEvent e) + { + hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); + base.OnHoverLost(e); + } + } + } } From 715fb88316bf4609a18a6cedaa9214a1454acb09 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Oct 2019 19:33:21 +0900 Subject: [PATCH 3428/5608] Fix build scripts not passing arguments to cake --- build.ps1 | 25 ++++++++++++++++++++++++- build.sh | 16 +++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/build.ps1 b/build.ps1 index 8eb37f2de6..2dbd10a150 100755 --- a/build.ps1 +++ b/build.ps1 @@ -1,4 +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 install Cake.Tool --global --version 0.35.0 dotnet cake ./build/build.cake --bootstrap -dotnet cake ./build/build.cake +dotnet cake ./build/build.cake $cakeArguments exit $LASTEXITCODE \ No newline at end of file diff --git a/build.sh b/build.sh index d20a9c12fa..ac6bd877a6 100755 --- a/build.sh +++ b/build.sh @@ -1,3 +1,17 @@ +echo "Installing Cake.Tool..." dotnet tool install Cake.Tool --global --version 0.35.0 + +# 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 \ No newline at end of file +dotnet cake ./build/build.cake "${CAKE_ARGUMENTS[@]}" \ No newline at end of file From 13924174c4950a173c575217484006046cfaccf4 Mon Sep 17 00:00:00 2001 From: HoLLy-HaCKeR Date: Sat, 12 Oct 2019 10:04:14 +0200 Subject: [PATCH 3429/5608] Fix PopIn and PopOut resetting cursor scale --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 371c2983fc..2b499064fb 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -31,6 +31,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private Bindable cursorScale; private Bindable autoCursorScale; + private float calculatedCursorScale; private readonly IBindable beatmap = new Bindable(); public OsuCursorContainer() @@ -69,6 +70,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor scale *= 1f - 0.7f * (1f + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY; } + calculatedCursorScale = scale; ActiveCursor.Scale = cursorTrail.Scale = new Vector2(scale); } @@ -125,13 +127,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor protected override void PopIn() { fadeContainer.FadeTo(1, 300, Easing.OutQuint); - ActiveCursor.ScaleTo(1, 400, Easing.OutQuint); + ActiveCursor.ScaleTo(calculatedCursorScale, 400, Easing.OutQuint); } protected override void PopOut() { fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint); - ActiveCursor.ScaleTo(0.8f, 450, Easing.OutQuint); + ActiveCursor.ScaleTo(calculatedCursorScale * 0.8f, 450, Easing.OutQuint); } private class DefaultCursorTrail : CursorTrail From fdc17d2adb07d81c22f7d1b6ad3c44f277917429 Mon Sep 17 00:00:00 2001 From: HoLLy-HaCKeR Date: Sat, 12 Oct 2019 11:51:14 +0200 Subject: [PATCH 3430/5608] Scale OsuResumeCursor with gameplay cursor --- .../UI/Cursor/OsuCursorContainer.cs | 13 ++++++++----- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 14 +++++++++++--- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 2b499064fb..8ea11d0a4b 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -29,9 +29,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly Drawable cursorTrail; + public IBindable CalculatedCursorScale => calculatedCursorScale; + private Bindable calculatedCursorScale; private Bindable cursorScale; private Bindable autoCursorScale; - private float calculatedCursorScale; private readonly IBindable beatmap = new Bindable(); public OsuCursorContainer() @@ -57,6 +58,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor autoCursorScale = config.GetBindable(OsuSetting.AutoCursorSize); autoCursorScale.ValueChanged += _ => calculateScale(); + calculatedCursorScale = new Bindable(); + calculatedCursorScale.ValueChanged += e => ActiveCursor.Scale = cursorTrail.Scale = new Vector2(e.NewValue); + calculateScale(); } @@ -70,8 +74,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor scale *= 1f - 0.7f * (1f + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY; } - calculatedCursorScale = scale; - ActiveCursor.Scale = cursorTrail.Scale = new Vector2(scale); + calculatedCursorScale.Value = scale; } protected override void LoadComplete() @@ -127,13 +130,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor protected override void PopIn() { fadeContainer.FadeTo(1, 300, Easing.OutQuint); - ActiveCursor.ScaleTo(calculatedCursorScale, 400, Easing.OutQuint); + ActiveCursor.ScaleTo(calculatedCursorScale.Value, 400, Easing.OutQuint); } protected override void PopOut() { fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint); - ActiveCursor.ScaleTo(calculatedCursorScale * 0.8f, 450, Easing.OutQuint); + ActiveCursor.ScaleTo(calculatedCursorScale.Value * 0.8f, 450, Easing.OutQuint); } private class DefaultCursorTrail : CursorTrail diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 9e5df0d6b1..9033817115 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -38,7 +38,13 @@ namespace osu.Game.Rulesets.Osu.UI clickToResumeCursor.ShowAt(GameplayCursor.ActiveCursor.Position); if (localCursorContainer == null) - Add(localCursorContainer = new OsuCursorContainer()); + { + var newContainer = new OsuCursorContainer(); + Add(localCursorContainer = newContainer); + + clickToResumeCursor.CursorScale = newContainer.CalculatedCursorScale.Value; + newContainer.CalculatedCursorScale.ValueChanged += e => clickToResumeCursor.CursorScale = e.NewValue; + } } public override void Hide() @@ -57,6 +63,8 @@ namespace osu.Game.Rulesets.Osu.UI public Action ResumeRequested; + public float CursorScale; + public OsuClickToResumeCursor() { RelativePositionAxes = Axes.Both; @@ -82,7 +90,7 @@ namespace osu.Game.Rulesets.Osu.UI case OsuAction.RightButton: if (!IsHovered) return false; - this.ScaleTo(new Vector2(2), TRANSITION_TIME, Easing.OutQuint); + this.ScaleTo(2 * CursorScale, TRANSITION_TIME, Easing.OutQuint); ResumeRequested?.Invoke(); return true; @@ -97,7 +105,7 @@ namespace osu.Game.Rulesets.Osu.UI { updateColour(); this.MoveTo(activeCursorPosition); - this.ScaleTo(new Vector2(4)).Then().ScaleTo(Vector2.One, 1000, Easing.OutQuint); + this.ScaleTo(4 * CursorScale).Then().ScaleTo(CursorScale, 1000, Easing.OutQuint); }); private void updateColour() From 7931510d7bda55dc3b54da6d411cd8c4711a7e4e Mon Sep 17 00:00:00 2001 From: HoLLy-HaCKeR Date: Sat, 12 Oct 2019 11:59:22 +0200 Subject: [PATCH 3431/5608] Ensure OsuResumeCursor can change scale when it is being shown --- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 9033817115..7221e09c35 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -43,7 +43,13 @@ namespace osu.Game.Rulesets.Osu.UI Add(localCursorContainer = newContainer); clickToResumeCursor.CursorScale = newContainer.CalculatedCursorScale.Value; - newContainer.CalculatedCursorScale.ValueChanged += e => clickToResumeCursor.CursorScale = e.NewValue; + clickToResumeCursor.Scale = new Vector2(newContainer.CalculatedCursorScale.Value); + + newContainer.CalculatedCursorScale.ValueChanged += e => + { + clickToResumeCursor.CursorScale = e.NewValue; + clickToResumeCursor.Scale = new Vector2(e.NewValue); + }; } } From f6b138fe6ed3aa230c1753b4ce0bb7bf576dcfef Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 12 Oct 2019 15:03:24 +0300 Subject: [PATCH 3432/5608] Remove useless ItemGroup --- osu.Game/osu.Game.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 4e6511385e..ab7c40116b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -32,7 +32,4 @@ - - - From 4d971e49ff050685a4498cc31b941fd426f41ef1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 13 Oct 2019 11:50:27 +0300 Subject: [PATCH 3433/5608] Colours update --- osu.Game/Overlays/Comments/CommentsContainer.cs | 2 +- osu.Game/Overlays/Comments/DrawableComment.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 265793226e..b66374cb69 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -113,7 +113,7 @@ namespace osu.Game.Overlays.Comments [BackgroundDependencyLoader] private void load() { - background.Colour = colours.Gray3; + background.Colour = colours.Gray2; } } } diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index fd7f874304..4617f6f86e 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -13,7 +13,6 @@ using osu.Game.Utils; using osu.Framework.Graphics.Cursor; using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; -using osuTK.Graphics; using System.Linq; namespace osu.Game.Overlays.Comments @@ -134,6 +133,7 @@ namespace osu.Game.Overlays.Comments AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(10, 0), + Colour = OsuColour.Gray(0.7f), Children = new Drawable[] { new SpriteText @@ -262,6 +262,7 @@ namespace osu.Game.Overlays.Comments Child = icon = new SpriteIcon { Size = new Vector2(12), + Colour = OsuColour.Gray(0.7f) }; } @@ -340,7 +341,7 @@ namespace osu.Game.Overlays.Comments new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4.Black + Colour = OsuColour.Gray(0.05f) }, new SpriteText { From 795ce8146895f435744a41e929a4621d0a212f16 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 13 Oct 2019 12:10:01 +0300 Subject: [PATCH 3434/5608] Use async loading for comment pages --- .../Overlays/Comments/CommentsContainer.cs | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index b66374cb69..3b997540c4 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -10,6 +10,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; +using System.Threading; namespace osu.Game.Overlays.Comments { @@ -28,6 +29,7 @@ namespace osu.Game.Overlays.Comments private OsuColour colours { get; set; } private GetCommentsRequest request; + private CancellationTokenSource loadCancellation; private readonly Box background; private readonly FillFlowContainer content; @@ -79,7 +81,7 @@ namespace osu.Game.Overlays.Comments private void getComments() { request?.Cancel(); - content.Clear(); + loadCancellation?.Cancel(); request = new GetCommentsRequest(type, id, Sort.Value); request.Success += onSuccess; api.Queue(request); @@ -87,27 +89,43 @@ namespace osu.Game.Overlays.Comments private void onSuccess(APICommentsController response) { + loadCancellation = new CancellationTokenSource(); + + FillFlowContainer page = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + }; + foreach (var c in response.Comments) { if (c.IsTopLevel) - content.Add(new DrawableComment(c) + page.Add(new DrawableComment(c) { ShowDeleted = { BindTarget = ShowDeleted } }); } - int deletedComments = 0; - - response.Comments.ForEach(comment => + LoadComponentAsync(page, loaded => { - if (comment.IsDeleted && comment.IsTopLevel) - deletedComments++; - }); + content.Clear(); - content.Add(new DeletedChildsPlaceholder(deletedComments) - { - ShowDeleted = { BindTarget = ShowDeleted } - }); + content.Add(loaded); + + int deletedComments = 0; + + response.Comments.ForEach(comment => + { + if (comment.IsDeleted && comment.IsTopLevel) + deletedComments++; + }); + + content.Add(new DeletedChildsPlaceholder(deletedComments) + { + ShowDeleted = { BindTarget = ShowDeleted } + }); + }, loadCancellation.Token); } [BackgroundDependencyLoader] From 60954f969d77f6350b0f63903cf2f5696046c248 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 13 Oct 2019 12:38:50 +0300 Subject: [PATCH 3435/5608] DeletedChildsPlaceholder refactor --- .../Overlays/Comments/CommentsContainer.cs | 33 ++++++++++++++++--- .../Comments/DeletedChildsPlaceholder.cs | 30 ++++++++++++----- osu.Game/Overlays/Comments/DrawableComment.cs | 5 ++- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 3b997540c4..1fca9ca5e5 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -33,6 +33,8 @@ namespace osu.Game.Overlays.Comments private readonly Box background; private readonly FillFlowContainer content; + private readonly FillFlowContainer footer; + private readonly DeletedChildsPlaceholder deletedChildsPlaceholder; public CommentsContainer(CommentableType type, long id) { @@ -64,6 +66,32 @@ namespace osu.Game.Overlays.Comments RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.2f) + }, + footer = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + deletedChildsPlaceholder = new DeletedChildsPlaceholder + { + ShowDeleted = { BindTarget = ShowDeleted } + } + } + } + } } } } @@ -121,10 +149,7 @@ namespace osu.Game.Overlays.Comments deletedComments++; }); - content.Add(new DeletedChildsPlaceholder(deletedComments) - { - ShowDeleted = { BindTarget = ShowDeleted } - }); + deletedChildsPlaceholder.DeletedCount.Value = deletedComments; }, loadCancellation.Token); } diff --git a/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs b/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs index 7aae42908e..b5dcf433f1 100644 --- a/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs +++ b/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs @@ -17,18 +17,18 @@ namespace osu.Game.Overlays.Comments private const int margin = 10; public readonly BindableBool ShowDeleted = new BindableBool(); + public readonly BindableInt DeletedCount = new BindableInt(); - private readonly bool canBeVisible; + private bool canBeShown; - public DeletedChildsPlaceholder(int count) + private readonly SpriteText countText; + + public DeletedChildsPlaceholder() { - canBeVisible = count != 0; - AutoSizeAxes = Axes.Both; Direction = FillDirection.Horizontal; Spacing = new Vector2(3, 0); Margin = new MarginPadding { Vertical = margin, Left = deleted_placeholder_margin }; - Alpha = 0; Children = new Drawable[] { new SpriteIcon @@ -36,24 +36,38 @@ namespace osu.Game.Overlays.Comments Icon = FontAwesome.Solid.Trash, Size = new Vector2(14), }, - new SpriteText + countText = new SpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), - Text = $@"{count} deleted comment{(count.ToString().ToCharArray().Last() == '1' ? "" : "s")}" } }; } protected override void LoadComplete() { + DeletedCount.BindValueChanged(onCountChanged, true); ShowDeleted.BindValueChanged(onShowDeletedChanged, true); base.LoadComplete(); } private void onShowDeletedChanged(ValueChangedEvent showDeleted) { - if (canBeVisible) + if (canBeShown) this.FadeTo(showDeleted.NewValue ? 0 : 1); } + + private void onCountChanged(ValueChangedEvent count) + { + canBeShown = count.NewValue != 0; + + if (!canBeShown) + { + Hide(); + return; + } + + countText.Text = $@"{count.NewValue} deleted comment{(count.NewValue.ToString().ToCharArray().Last() == '1' ? "" : "s")}"; + Show(); + } } } diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 4617f6f86e..8c356a6156 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -32,6 +32,7 @@ namespace osu.Game.Overlays.Comments private readonly FillFlowContainer childCommentsVisibilityContainer; private readonly Comment comment; + private readonly DeletedChildsPlaceholder deletedChildsPlaceholder; public DrawableComment(Comment comment) { @@ -168,7 +169,7 @@ namespace osu.Game.Overlays.Comments AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical }, - new DeletedChildsPlaceholder(comment.GetDeletedChildsCount()) + deletedChildsPlaceholder = new DeletedChildsPlaceholder { ShowDeleted = { BindTarget = ShowDeleted } } @@ -177,6 +178,8 @@ namespace osu.Game.Overlays.Comments } }; + deletedChildsPlaceholder.DeletedCount.Value = comment.GetDeletedChildsCount(); + if (comment.UserId == null) username.AddText(comment.LegacyName); else From a44cc2e70baf13f3f90c6635d23bb2645b06841f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 13 Oct 2019 14:43:30 +0300 Subject: [PATCH 3436/5608] Implement CommentsShowMoreButton --- .../Online/TestSceneCommentsContainer.cs | 6 ++ .../Visual/Online/TestSceneShowMoreButton.cs | 5 +- .../UserInterface}/ShowMoreButton.cs | 67 ++++++++++--------- .../Overlays/Comments/CommentsContainer.cs | 54 ++++++++++++--- .../Comments/CommentsShowMoreButton.cs | 32 +++++++++ .../Comments/DeletedChildsPlaceholder.cs | 8 ++- .../Profile/Sections/PaginatedContainer.cs | 4 +- .../Profile/Sections/ProfileShowMoreButton.cs | 20 ++++++ 8 files changed, 151 insertions(+), 45 deletions(-) rename osu.Game/{Overlays/Profile/Sections => Graphics/UserInterface}/ShowMoreButton.cs (77%) create mode 100644 osu.Game/Overlays/Comments/CommentsShowMoreButton.cs create mode 100644 osu.Game/Overlays/Profile/Sections/ProfileShowMoreButton.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index 342ba487f0..a283663a4a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -47,6 +47,12 @@ namespace osu.Game.Tests.Visual.Online scrollFlow.Clear(); scrollFlow.Add(new CommentsContainer(CommentableType.Beatmapset, 24313)); }); + + AddStep("lazer build comments", () => + { + scrollFlow.Clear(); + scrollFlow.Add(new CommentsContainer(CommentableType.Build, 4772)); + }); } } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs index bccb263600..8d4955abf0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs @@ -5,6 +5,7 @@ using osu.Game.Overlays.Profile.Sections; using System; using System.Collections.Generic; using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Tests.Visual.Online { @@ -17,11 +18,11 @@ namespace osu.Game.Tests.Visual.Online public TestSceneShowMoreButton() { - ShowMoreButton button = null; + ProfileShowMoreButton button = null; int fireCount = 0; - Add(button = new ShowMoreButton + Add(button = new ProfileShowMoreButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs similarity index 77% rename from osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs rename to osu.Game/Graphics/UserInterface/ShowMoreButton.cs index cf4e1c0dde..627ad995e8 100644 --- a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs +++ b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs @@ -1,30 +1,36 @@ -// 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.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; -using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osuTK; +using osuTK.Graphics; using System.Collections.Generic; -namespace osu.Game.Overlays.Profile.Sections +namespace osu.Game.Graphics.UserInterface { public class ShowMoreButton : OsuHoverContainer { private const float fade_duration = 200; - private readonly Box background; - private readonly LoadingAnimation loading; - private readonly FillFlowContainer content; + private Color4 chevronIconColour; - protected override IEnumerable EffectTargets => new[] { background }; + public Color4 ChevronIconColour + { + get => chevronIconColour; + set { chevronIconColour = leftChevron.AccentColour = rightChevron.AccentColour = value; } + } + + public string Text + { + get => text.Text; + set { text.Text = value; } + } private bool isLoading; @@ -33,26 +39,32 @@ namespace osu.Game.Overlays.Profile.Sections get => isLoading; set { - if (isLoading == value) - return; - isLoading = value; Enabled.Value = !isLoading; if (value) { - loading.FadeIn(fade_duration, Easing.OutQuint); + loading.Show(); content.FadeOut(fade_duration, Easing.OutQuint); } else { - loading.FadeOut(fade_duration, Easing.OutQuint); + loading.Hide(); content.FadeIn(fade_duration, Easing.OutQuint); } } } + private readonly Box background; + private readonly LoadingAnimation loading; + private readonly FillFlowContainer content; + private readonly ChevronIcon leftChevron; + private readonly ChevronIcon rightChevron; + private readonly SpriteText text; + + protected override IEnumerable EffectTargets => new[] { background }; + public ShowMoreButton() { AutoSizeAxes = Axes.Both; @@ -77,15 +89,15 @@ namespace osu.Game.Overlays.Profile.Sections Spacing = new Vector2(7), Children = new Drawable[] { - new ChevronIcon(), - new OsuSpriteText + leftChevron = new ChevronIcon(), + text = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), Text = "show more".ToUpper(), }, - new ChevronIcon(), + rightChevron = new ChevronIcon(), } }, loading = new LoadingAnimation @@ -99,13 +111,6 @@ namespace osu.Game.Overlays.Profile.Sections }; } - [BackgroundDependencyLoader] - private void load(OsuColour colors) - { - IdleColour = colors.GreySeafoamDark; - HoverColour = colors.GreySeafoam; - } - protected override bool OnClick(ClickEvent e) { if (!Enabled.Value) @@ -126,6 +131,14 @@ namespace osu.Game.Overlays.Profile.Sections { private const int icon_size = 8; + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set { accentColour = Colour = value; } + } + public ChevronIcon() { Anchor = Anchor.Centre; @@ -133,12 +146,6 @@ namespace osu.Game.Overlays.Profile.Sections Size = new Vector2(icon_size); Icon = FontAwesome.Solid.ChevronDown; } - - [BackgroundDependencyLoader] - private void load(OsuColour colors) - { - Colour = colors.Yellow; - } } } } diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 1fca9ca5e5..1111313d7f 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -16,6 +16,8 @@ namespace osu.Game.Overlays.Comments { public class CommentsContainer : CompositeDrawable { + private const int more_button_margin = 5; + private readonly CommentableType type; private readonly long id; @@ -30,11 +32,13 @@ namespace osu.Game.Overlays.Comments private GetCommentsRequest request; private CancellationTokenSource loadCancellation; + private int currentPage; + private int loadedTopLevelComments; private readonly Box background; private readonly FillFlowContainer content; - private readonly FillFlowContainer footer; private readonly DeletedChildsPlaceholder deletedChildsPlaceholder; + private readonly CommentsShowMoreButton moreButton; public CommentsContainer(CommentableType type, long id) { @@ -78,7 +82,7 @@ namespace osu.Game.Overlays.Comments RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.2f) }, - footer = new FillFlowContainer + new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -88,6 +92,18 @@ namespace osu.Game.Overlays.Comments deletedChildsPlaceholder = new DeletedChildsPlaceholder { ShowDeleted = { BindTarget = ShowDeleted } + }, + new Container + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Child = moreButton = new CommentsShowMoreButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding(more_button_margin), + Action = () => getComments(false), + } } } } @@ -106,16 +122,25 @@ namespace osu.Game.Overlays.Comments private void onSortChanged(ValueChangedEvent sort) => getComments(); - private void getComments() + private void getComments(bool initial = true) { + if (initial) + { + currentPage = 1; + loadedTopLevelComments = 0; + deletedChildsPlaceholder.DeletedCount.Value = 0; + moreButton.IsLoading = true; + content.Clear(); + } + request?.Cancel(); loadCancellation?.Cancel(); - request = new GetCommentsRequest(type, id, Sort.Value); - request.Success += onSuccess; + request = new GetCommentsRequest(type, id, Sort.Value, currentPage++); + request.Success += response => onSuccess(response, initial); api.Queue(request); } - private void onSuccess(APICommentsController response) + private void onSuccess(APICommentsController response, bool initial) { loadCancellation = new CancellationTokenSource(); @@ -137,8 +162,6 @@ namespace osu.Game.Overlays.Comments LoadComponentAsync(page, loaded => { - content.Clear(); - content.Add(loaded); int deletedComments = 0; @@ -149,7 +172,20 @@ namespace osu.Game.Overlays.Comments deletedComments++; }); - deletedChildsPlaceholder.DeletedCount.Value = deletedComments; + deletedChildsPlaceholder.DeletedCount.Value = initial ? deletedComments : deletedChildsPlaceholder.DeletedCount.Value + deletedComments; + + if (response.HasMore) + { + response.Comments.ForEach(comment => + { + if (comment.IsTopLevel) + loadedTopLevelComments++; + }); + moreButton.Current.Value = response.TopLevelCount - loadedTopLevelComments; + moreButton.IsLoading = false; + } + moreButton.FadeTo(response.HasMore ? 1 : 0); + }, loadCancellation.Token); } diff --git a/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs b/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs new file mode 100644 index 0000000000..b0174e7b1a --- /dev/null +++ b/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs @@ -0,0 +1,32 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Overlays.Comments +{ + public class CommentsShowMoreButton : ShowMoreButton + { + public readonly BindableInt Current = new BindableInt(); + + public CommentsShowMoreButton() + { + IdleColour = OsuColour.Gray(0.3f); + HoverColour = OsuColour.Gray(0.4f); + ChevronIconColour = OsuColour.Gray(0.5f); + } + + protected override void LoadComplete() + { + Current.BindValueChanged(onCurrentChanged, true); + base.LoadComplete(); + } + + private void onCurrentChanged(ValueChangedEvent count) + { + Text = $@"Show More ({count.NewValue})".ToUpper(); + } + } +} diff --git a/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs b/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs index b5dcf433f1..d626c13afd 100644 --- a/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs +++ b/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs @@ -7,7 +7,6 @@ using osu.Game.Graphics; using osu.Framework.Graphics.Sprites; using osuTK; using osu.Framework.Bindables; -using System.Linq; namespace osu.Game.Overlays.Comments { @@ -66,7 +65,12 @@ namespace osu.Game.Overlays.Comments return; } - countText.Text = $@"{count.NewValue} deleted comment{(count.NewValue.ToString().ToCharArray().Last() == '1' ? "" : "s")}"; + string str = $@"{count.NewValue} deleted comment"; + + if (!(count.NewValue.ToString().EndsWith("1") && !count.NewValue.ToString().EndsWith("11"))) + str += "s"; + + countText.Text = str; Show(); } } diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index bb221bd43a..dc1a847b14 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Profile.Sections { public abstract class PaginatedContainer : FillFlowContainer { - private readonly ShowMoreButton moreButton; + private readonly ProfileShowMoreButton moreButton; private readonly OsuSpriteText missingText; private APIRequest> retrievalRequest; private CancellationTokenSource loadCancellation; @@ -56,7 +56,7 @@ namespace osu.Game.Overlays.Profile.Sections RelativeSizeAxes = Axes.X, Spacing = new Vector2(0, 2), }, - moreButton = new ShowMoreButton + moreButton = new ProfileShowMoreButton { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.Game/Overlays/Profile/Sections/ProfileShowMoreButton.cs b/osu.Game/Overlays/Profile/Sections/ProfileShowMoreButton.cs new file mode 100644 index 0000000000..28486cc743 --- /dev/null +++ b/osu.Game/Overlays/Profile/Sections/ProfileShowMoreButton.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Overlays.Profile.Sections +{ + public class ProfileShowMoreButton : ShowMoreButton + { + [BackgroundDependencyLoader] + private void load(OsuColour colors) + { + IdleColour = colors.GreySeafoamDark; + HoverColour = colors.GreySeafoam; + ChevronIconColour = colors.Yellow; + } + } +} From 328b4d6863a3002b396b65bbcdde32d0a95568ff Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 13 Oct 2019 16:22:10 +0300 Subject: [PATCH 3437/5608] Cancel request on dispose --- osu.Game/Overlays/Comments/CommentsContainer.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 1111313d7f..4c27c498c3 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -194,5 +194,12 @@ namespace osu.Game.Overlays.Comments { background.Colour = colours.Gray2; } + + protected override void Dispose(bool isDisposing) + { + request?.Cancel(); + loadCancellation?.Cancel(); + base.Dispose(isDisposing); + } } } From ae2fe62fd9ed27d1ef5bdd60927795b9d509ca97 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Oct 2019 17:13:36 +0900 Subject: [PATCH 3438/5608] Use BindValueChanged --- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 7221e09c35..1ee2a04a3b 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.UI.Cursor; -using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using osuTK; using osuTK.Graphics; @@ -20,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.UI { private OsuClickToResumeCursor clickToResumeCursor; - private GameplayCursorContainer localCursorContainer; + private OsuCursorContainer localCursorContainer; public override CursorContainer LocalCursor => State.Value == Visibility.Visible ? localCursorContainer : null; @@ -39,17 +38,13 @@ namespace osu.Game.Rulesets.Osu.UI if (localCursorContainer == null) { - var newContainer = new OsuCursorContainer(); - Add(localCursorContainer = newContainer); + Add(localCursorContainer = new OsuCursorContainer()); - clickToResumeCursor.CursorScale = newContainer.CalculatedCursorScale.Value; - clickToResumeCursor.Scale = new Vector2(newContainer.CalculatedCursorScale.Value); - - newContainer.CalculatedCursorScale.ValueChanged += e => + localCursorContainer.CalculatedCursorScale.BindValueChanged(scale => { - clickToResumeCursor.CursorScale = e.NewValue; - clickToResumeCursor.Scale = new Vector2(e.NewValue); - }; + clickToResumeCursor.CursorScale = scale.NewValue; + clickToResumeCursor.Scale = new Vector2(scale.NewValue); + }, true); } } From 9372526d3af9f42da19442ed21baca4c692a358d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Oct 2019 20:08:05 +0900 Subject: [PATCH 3439/5608] Don't automatically return to gameplay from map pool if no picks are made Closes #6491. --- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index d32c0d6156..ec55bb5b54 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -196,7 +196,7 @@ namespace osu.Game.Tournament.Screens.MapPool setNextMode(); - if (pickType == ChoiceType.Pick) + if (pickType == ChoiceType.Pick && currentMatch.Value.PicksBans.Any(i => i.Type == ChoiceType.Pick)) { scheduledChange?.Cancel(); scheduledChange = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(GameplayScreen)); }, 10000); From e191c2c50e5652d32f04b7fccb7a7a57ed5c2e9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Oct 2019 21:32:16 +0900 Subject: [PATCH 3440/5608] Tidy up constants and method naming --- osu.Game/Overlays/Comments/CommentsHeader.cs | 16 +++++++--------- osu.Game/Overlays/Comments/HeaderButton.cs | 19 ++++++++----------- osu.Game/Overlays/Comments/SortSelector.cs | 4 ++-- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index 2bd2bf21a6..1df347eb82 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -15,10 +15,7 @@ namespace osu.Game.Overlays.Comments { public class CommentsHeader : CompositeDrawable { - private const int height = 40; - private const int spacing = 10; - private const int padding = 50; - private const int text_size = 14; + private const int font_size = 14; public readonly Bindable Sort = new Bindable(); public readonly BindableBool ShowDeleted = new BindableBool(); @@ -28,7 +25,8 @@ namespace osu.Game.Overlays.Comments public CommentsHeader() { RelativeSizeAxes = Axes.X; - Height = height; + Height = 40; + AddRangeInternal(new Drawable[] { background = new Box @@ -38,14 +36,14 @@ namespace osu.Game.Overlays.Comments new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = padding }, + Padding = new MarginPadding { Horizontal = 50 }, Children = new Drawable[] { new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - Spacing = new Vector2(spacing, 0), + Spacing = new Vector2(10, 0), Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Children = new Drawable[] @@ -54,7 +52,7 @@ namespace osu.Game.Overlays.Comments { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: text_size), + Font = OsuFont.GetFont(size: font_size), Text = @"Sort by" }, new SortSelector @@ -107,7 +105,7 @@ namespace osu.Game.Overlays.Comments { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: text_size), + Font = OsuFont.GetFont(size: font_size), Text = @"Show deleted" } }, diff --git a/osu.Game/Overlays/Comments/HeaderButton.cs b/osu.Game/Overlays/Comments/HeaderButton.cs index 231a364759..8789cf5830 100644 --- a/osu.Game/Overlays/Comments/HeaderButton.cs +++ b/osu.Game/Overlays/Comments/HeaderButton.cs @@ -13,10 +13,7 @@ namespace osu.Game.Overlays.Comments { public class HeaderButton : Container { - private const int height = 20; - private const int corner_radius = 3; - private const int margin = 10; - private const int duration = 200; + private const int transition_duration = 200; protected override Container Content => content; @@ -26,9 +23,9 @@ namespace osu.Game.Overlays.Comments public HeaderButton() { AutoSizeAxes = Axes.X; - Height = height; + Height = 20; Masking = true; - CornerRadius = corner_radius; + CornerRadius = 3; AddRangeInternal(new Drawable[] { background = new Box @@ -41,7 +38,7 @@ namespace osu.Game.Overlays.Comments AutoSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding { Horizontal = margin } + Margin = new MarginPadding { Horizontal = 10 } }, new HoverClickSounds(), }); @@ -55,18 +52,18 @@ namespace osu.Game.Overlays.Comments protected override bool OnHover(HoverEvent e) { - FadeInBackground(); + ShowBackground(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - FadeOutBackground(); + HideBackground(); } - protected void FadeInBackground() => background.FadeIn(duration, Easing.OutQuint); + protected void ShowBackground() => background.FadeIn(transition_duration, Easing.OutQuint); - protected void FadeOutBackground() => background.FadeOut(duration, Easing.OutQuint); + protected void HideBackground() => background.FadeOut(transition_duration, Easing.OutQuint); } } diff --git a/osu.Game/Overlays/Comments/SortSelector.cs b/osu.Game/Overlays/Comments/SortSelector.cs index 100ae83291..90e7defb9a 100644 --- a/osu.Game/Overlays/Comments/SortSelector.cs +++ b/osu.Game/Overlays/Comments/SortSelector.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays.Comments public void Activate() { - FadeInBackground(); + ShowBackground(); text.Font = text.Font.With(weight: FontWeight.Bold); text.Colour = colours.BlueLighter; } @@ -83,7 +83,7 @@ namespace osu.Game.Overlays.Comments public void Deactivate() { if (!IsHovered) - FadeOutBackground(); + HideBackground(); text.Font = text.Font.With(weight: FontWeight.Medium); text.Colour = Color4.White; From 89f270a19a32df0696cbd244eb9e39d826220f4b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Oct 2019 21:32:41 +0900 Subject: [PATCH 3441/5608] SortSelector -> SortTabControl --- osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs | 2 +- osu.Game/Overlays/Comments/CommentsHeader.cs | 2 +- .../Overlays/Comments/{SortSelector.cs => SortTabControl.cs} | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game/Overlays/Comments/{SortSelector.cs => SortTabControl.cs} (96%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs index 949dbbe5c4..bc3e0eff1a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.Online { typeof(CommentsHeader), typeof(HeaderButton), - typeof(SortSelector), + typeof(SortTabControl), }; private readonly Bindable sort = new Bindable(); diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index 1df347eb82..81be16967f 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -55,7 +55,7 @@ namespace osu.Game.Overlays.Comments Font = OsuFont.GetFont(size: font_size), Text = @"Sort by" }, - new SortSelector + new SortTabControl { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game/Overlays/Comments/SortSelector.cs b/osu.Game/Overlays/Comments/SortTabControl.cs similarity index 96% rename from osu.Game/Overlays/Comments/SortSelector.cs rename to osu.Game/Overlays/Comments/SortTabControl.cs index 90e7defb9a..8dc1f14c3d 100644 --- a/osu.Game/Overlays/Comments/SortSelector.cs +++ b/osu.Game/Overlays/Comments/SortTabControl.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Comments { - public class SortSelector : OsuTabControl + public class SortTabControl : OsuTabControl { private const int spacing = 5; @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Comments Spacing = new Vector2(spacing, 0), }; - public SortSelector() + public SortTabControl() { AutoSizeAxes = Axes.Both; } From 4822496c130880a5f3c20e847942cbab870849a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Oct 2019 21:34:16 +0900 Subject: [PATCH 3442/5608] Fix more naming --- osu.Game/Overlays/Comments/SortTabControl.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Comments/SortTabControl.cs b/osu.Game/Overlays/Comments/SortTabControl.cs index 8dc1f14c3d..3f1b5c54bd 100644 --- a/osu.Game/Overlays/Comments/SortTabControl.cs +++ b/osu.Game/Overlays/Comments/SortTabControl.cs @@ -37,23 +37,23 @@ namespace osu.Game.Overlays.Comments private class SortTabItem : TabItem { - private readonly TabContent content; + private readonly TabButton button; public SortTabItem(CommentsSortCriteria value) : base(value) { AutoSizeAxes = Axes.Both; - Child = content = new TabContent(value) + Child = button = new TabButton(value) { Active = { BindTarget = Active } }; } - protected override void OnActivated() => content.Activate(); + protected override void OnActivated() => button.Activate(); - protected override void OnDeactivated() => content.Deactivate(); + protected override void OnDeactivated() => button.Deactivate(); - private class TabContent : HeaderButton + private class TabButton : HeaderButton { private const int text_size = 14; @@ -64,7 +64,7 @@ namespace osu.Game.Overlays.Comments private readonly SpriteText text; - public TabContent(CommentsSortCriteria value) + public TabButton(CommentsSortCriteria value) { Add(text = new SpriteText { From 779445755034234c0c986dd8f874b0b2162ea35e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Oct 2019 21:34:43 +0900 Subject: [PATCH 3443/5608] Remove more constants --- osu.Game/Overlays/Comments/SortTabControl.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Comments/SortTabControl.cs b/osu.Game/Overlays/Comments/SortTabControl.cs index 3f1b5c54bd..596822a86c 100644 --- a/osu.Game/Overlays/Comments/SortTabControl.cs +++ b/osu.Game/Overlays/Comments/SortTabControl.cs @@ -17,8 +17,6 @@ namespace osu.Game.Overlays.Comments { public class SortTabControl : OsuTabControl { - private const int spacing = 5; - protected override Dropdown CreateDropdown() => null; protected override TabItem CreateTabItem(CommentsSortCriteria value) => new SortTabItem(value); @@ -27,7 +25,7 @@ namespace osu.Game.Overlays.Comments { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - Spacing = new Vector2(spacing, 0), + Spacing = new Vector2(5, 0), }; public SortTabControl() @@ -55,8 +53,6 @@ namespace osu.Game.Overlays.Comments private class TabButton : HeaderButton { - private const int text_size = 14; - public readonly BindableBool Active = new BindableBool(); [Resolved] @@ -68,7 +64,7 @@ namespace osu.Game.Overlays.Comments { Add(text = new SpriteText { - Font = OsuFont.GetFont(size: text_size), + Font = OsuFont.GetFont(size: 14), Text = value.ToString() }); } From 4e6ab1dad397f0151861f3fc39bed5c3c9f0617f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Oct 2019 21:42:07 +0900 Subject: [PATCH 3444/5608] Tidy up state management via bindable usage --- osu.Game/Overlays/Comments/SortTabControl.cs | 51 +++++++++++--------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/osu.Game/Overlays/Comments/SortTabControl.cs b/osu.Game/Overlays/Comments/SortTabControl.cs index 596822a86c..f5423e692f 100644 --- a/osu.Game/Overlays/Comments/SortTabControl.cs +++ b/osu.Game/Overlays/Comments/SortTabControl.cs @@ -35,21 +35,20 @@ namespace osu.Game.Overlays.Comments private class SortTabItem : TabItem { - private readonly TabButton button; - public SortTabItem(CommentsSortCriteria value) : base(value) { AutoSizeAxes = Axes.Both; - Child = button = new TabButton(value) - { - Active = { BindTarget = Active } - }; + Child = new TabButton(value) { Active = { BindTarget = Active } }; } - protected override void OnActivated() => button.Activate(); + protected override void OnActivated() + { + } - protected override void OnDeactivated() => button.Deactivate(); + protected override void OnDeactivated() + { + } private class TabButton : HeaderButton { @@ -69,25 +68,33 @@ namespace osu.Game.Overlays.Comments }); } - public void Activate() + protected override void LoadComplete() { - ShowBackground(); - text.Font = text.Font.With(weight: FontWeight.Bold); - text.Colour = colours.BlueLighter; + base.LoadComplete(); + + Active.BindValueChanged(active => + { + updateBackgroundState(); + + text.Font = text.Font.With(weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium); + text.Colour = active.NewValue ? colours.BlueLighter : Color4.White; + }, true); } - public void Deactivate() + protected override bool OnHover(HoverEvent e) { - if (!IsHovered) + updateBackgroundState(); + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) => updateBackgroundState(); + + private void updateBackgroundState() + { + if (Active.Value || IsHovered) + ShowBackground(); + else HideBackground(); - - text.Font = text.Font.With(weight: FontWeight.Medium); - text.Colour = Color4.White; - } - - protected override void OnHoverLost(HoverLostEvent e) - { - if (!Active.Value) base.OnHoverLost(e); } } } From b7ddf160b46d874e20c928aae44595daccfe692a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Oct 2019 21:48:12 +0900 Subject: [PATCH 3445/5608] OnClick should actually handle the event --- osu.Game/Overlays/Comments/CommentsHeader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index 81be16967f..1797a36b71 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -126,7 +126,7 @@ namespace osu.Game.Overlays.Comments protected override bool OnClick(ClickEvent e) { Checked.Value = !Checked.Value; - return base.OnClick(e); + return true; } } } From f0e970034950ff034e380be1ecf34947abf806fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Oct 2019 21:49:02 +0900 Subject: [PATCH 3446/5608] Inline delegate event --- osu.Game/Overlays/Comments/CommentsHeader.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index 1797a36b71..66fe7ff3fa 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -114,15 +114,10 @@ namespace osu.Game.Overlays.Comments protected override void LoadComplete() { - Checked.BindValueChanged(onCheckedChanged, true); + Checked.BindValueChanged(isChecked => checkboxIcon.Icon = isChecked.NewValue ? FontAwesome.Solid.CheckSquare : FontAwesome.Regular.Square, true); base.LoadComplete(); } - private void onCheckedChanged(ValueChangedEvent isChecked) - { - checkboxIcon.Icon = isChecked.NewValue ? FontAwesome.Solid.CheckSquare : FontAwesome.Regular.Square; - } - protected override bool OnClick(ClickEvent e) { Checked.Value = !Checked.Value; From 7cd3f5656d4c7b482fb995ce9ce4489db0a20d3d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 14 Oct 2019 16:43:43 +0300 Subject: [PATCH 3447/5608] Cleanups --- .../Online/TestSceneCommentsContainer.cs | 2 +- .../Online/API/Requests/Responses/Comment.cs | 6 ++++- .../Overlays/Comments/CommentsContainer.cs | 4 +-- .../Comments/DeletedChildsPlaceholder.cs | 5 +--- osu.Game/Overlays/Comments/DrawableComment.cs | 27 +++++++------------ .../Overlays/Comments/ShowChildsButton.cs | 2 +- 6 files changed, 18 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index a283663a4a..5e4aa27fae 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.Online typeof(CommentsHeader), typeof(DrawableComment), typeof(HeaderButton), - typeof(SortSelector), + typeof(SortTabControl), typeof(ShowChildsButton), typeof(DeletedChildsPlaceholder) }; diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 2334c86519..d0f7e4fac5 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -6,6 +6,7 @@ using osu.Game.Users; using System; using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; namespace osu.Game.Online.API.Requests.Responses { @@ -90,7 +91,10 @@ namespace osu.Game.Online.API.Requests.Responses public string GetMessage() { - return IsDeleted ? @"deleted" : MessageHTML.Replace("
", "").Replace("

", "").Replace("
", "").Replace("

", "").Replace("
", "").Replace(""", "\""); + if (IsDeleted) + return @"deleted"; + + return Regex.Replace(MessageHTML, @"\<.*?\>", ""); } public int GetDeletedChildsCount() diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 4c27c498c3..8680234d4b 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -16,8 +16,6 @@ namespace osu.Game.Overlays.Comments { public class CommentsContainer : CompositeDrawable { - private const int more_button_margin = 5; - private readonly CommentableType type; private readonly long id; @@ -101,7 +99,7 @@ namespace osu.Game.Overlays.Comments { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding(more_button_margin), + Margin = new MarginPadding(5), Action = () => getComments(false), } } diff --git a/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs b/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs index d626c13afd..058f8cc750 100644 --- a/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs +++ b/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs @@ -12,9 +12,6 @@ namespace osu.Game.Overlays.Comments { public class DeletedChildsPlaceholder : FillFlowContainer { - private const int deleted_placeholder_margin = 80; - private const int margin = 10; - public readonly BindableBool ShowDeleted = new BindableBool(); public readonly BindableInt DeletedCount = new BindableInt(); @@ -27,7 +24,7 @@ namespace osu.Game.Overlays.Comments AutoSizeAxes = Axes.Both; Direction = FillDirection.Horizontal; Spacing = new Vector2(3, 0); - Margin = new MarginPadding { Vertical = margin, Left = deleted_placeholder_margin }; + Margin = new MarginPadding { Vertical = 10, Left = 80 }; Children = new Drawable[] { new SpriteIcon diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 8c356a6156..756eb8caf9 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -21,18 +21,14 @@ namespace osu.Game.Overlays.Comments { private const int avatar_size = 40; private const int margin = 10; - private const int child_margin = 20; - private const int chevron_margin = 30; - private const int message_padding = 40; - private const float separator_height = 1.5f; public readonly BindableBool ShowDeleted = new BindableBool(); private readonly BindableBool childExpanded = new BindableBool(true); private readonly FillFlowContainer childCommentsVisibilityContainer; - private readonly Comment comment; private readonly DeletedChildsPlaceholder deletedChildsPlaceholder; + private readonly Comment comment; public DrawableComment(Comment comment) { @@ -127,7 +123,7 @@ namespace osu.Game.Overlays.Comments { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Right = message_padding } + Padding = new MarginPadding { Right = 40 } }, info = new FillFlowContainer { @@ -164,7 +160,7 @@ namespace osu.Game.Overlays.Comments { childCommentsContainer = new FillFlowContainer { - Margin = new MarginPadding { Left = child_margin }, + Margin = new MarginPadding { Left = 20 }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical @@ -180,10 +176,10 @@ namespace osu.Game.Overlays.Comments deletedChildsPlaceholder.DeletedCount.Value = comment.GetDeletedChildsCount(); - if (comment.UserId == null) - username.AddText(comment.LegacyName); - else + if (comment.UserId.HasValue) username.AddUserLink(comment.User); + else + username.AddText(comment.LegacyName); if (comment.EditedAt.HasValue) { @@ -209,7 +205,7 @@ namespace osu.Game.Overlays.Comments AddInternal(new Container { RelativeSizeAxes = Axes.X, - Height = separator_height, + Height = 1.5f, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, Child = new Box @@ -225,7 +221,7 @@ namespace osu.Game.Overlays.Comments { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - Margin = new MarginPadding { Right = chevron_margin, Top = margin }, + Margin = new MarginPadding { Right = 30, Top = margin }, Expanded = { BindTarget = childExpanded } }); } @@ -240,15 +236,10 @@ namespace osu.Game.Overlays.Comments protected override void LoadComplete() { ShowDeleted.BindValueChanged(onShowDeletedChanged, true); - childExpanded.BindValueChanged(onChildExpandedChanged, true); + childExpanded.BindValueChanged(expanded => childCommentsVisibilityContainer.FadeTo(expanded.NewValue ? 1 : 0), true); base.LoadComplete(); } - private void onChildExpandedChanged(ValueChangedEvent expanded) - { - childCommentsVisibilityContainer.FadeTo(expanded.NewValue ? 1 : 0); - } - private void onShowDeletedChanged(ValueChangedEvent show) { if (comment.IsDeleted) diff --git a/osu.Game/Overlays/Comments/ShowChildsButton.cs b/osu.Game/Overlays/Comments/ShowChildsButton.cs index 81280a71b5..b29e316e80 100644 --- a/osu.Game/Overlays/Comments/ShowChildsButton.cs +++ b/osu.Game/Overlays/Comments/ShowChildsButton.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.Comments protected override bool OnClick(ClickEvent e) { Expanded.Value = !Expanded.Value; - return base.OnClick(e); + return true; } } } From a81d5cd81968fc113f924552c87f728da17d0ef6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 14 Oct 2019 16:56:07 +0300 Subject: [PATCH 3448/5608] Handle links in message --- osu.Game/Overlays/Comments/DrawableComment.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 756eb8caf9..c492e48acf 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -14,6 +14,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; using System.Linq; +using osu.Game.Online.Chat; namespace osu.Game.Overlays.Comments { @@ -35,7 +36,7 @@ namespace osu.Game.Overlays.Comments LinkFlowContainer username; FillFlowContainer childCommentsContainer; FillFlowContainer info; - TextFlowContainer message; + LinkFlowContainer message; GridContainer content; VotePill votePill; @@ -119,7 +120,7 @@ namespace osu.Game.Overlays.Comments } } }, - message = new TextFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) + message = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -193,7 +194,10 @@ namespace osu.Game.Overlays.Comments } if (!comment.IsDeleted) - message.Text = comment.GetMessage(); + { + var formattedSource = MessageFormatter.FormatText(comment.GetMessage()); + message.AddLinks(formattedSource.Text, formattedSource.Links); + } else { content.FadeColour(OsuColour.Gray(0.5f)); From a4ffd4798dfc76b516f4da2cb8b2f8f58a5f858f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 14 Oct 2019 17:02:48 +0300 Subject: [PATCH 3449/5608] Fix escaped html strings not being unescaped --- osu.Game/Online/API/Requests/Responses/Comment.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index d0f7e4fac5..5e67bff859 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -6,6 +6,7 @@ using osu.Game.Users; using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Text.RegularExpressions; namespace osu.Game.Online.API.Requests.Responses @@ -94,7 +95,7 @@ namespace osu.Game.Online.API.Requests.Responses if (IsDeleted) return @"deleted"; - return Regex.Replace(MessageHTML, @"\<.*?\>", ""); + return WebUtility.HtmlDecode(Regex.Replace(MessageHTML, @"<(.|\n)*?>", string.Empty)); } public int GetDeletedChildsCount() From b53fb0d228ba112044285ca31272432a53938a43 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 14 Oct 2019 17:07:50 +0300 Subject: [PATCH 3450/5608] Remove empty line --- osu.Game/Overlays/Comments/CommentsContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 8680234d4b..a5e921e2c0 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -183,7 +183,6 @@ namespace osu.Game.Overlays.Comments moreButton.IsLoading = false; } moreButton.FadeTo(response.HasMore ? 1 : 0); - }, loadCancellation.Token); } From 139170cdc859f2689e99b0a940f8334b2b46fa19 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 14 Oct 2019 17:26:12 +0300 Subject: [PATCH 3451/5608] Fix incorrect padding for nested comments --- osu.Game/Overlays/Comments/DrawableComment.cs | 169 +++++++++--------- 1 file changed, 87 insertions(+), 82 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index c492e48acf..e5258ef3cc 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -51,100 +51,105 @@ namespace osu.Game.Overlays.Comments Direction = FillDirection.Vertical, Children = new Drawable[] { - content = new GridContainer + new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Margin = new MarginPadding(margin), - ColumnDimensions = new[] + Padding = new MarginPadding(margin), + Child = content = new GridContainer { - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize) - }, - Content = new[] - { - new Drawable[] + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + ColumnDimensions = new[] { - new FillFlowContainer + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new Drawable[] { - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Horizontal = margin }, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5, 0), - Children = new Drawable[] + new FillFlowContainer { - votePill = new VotePill(comment.VotesCount) + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Horizontal = margin }, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AlwaysPresent = true, - }, - new UpdateableAvatar(comment.User) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(avatar_size), - Masking = true, - CornerRadius = avatar_size / 2, - }, - } - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(0, 3), - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7, 0), - Children = new Drawable[] + votePill = new VotePill(comment.VotesCount) { - username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AlwaysPresent = true, + }, + new UpdateableAvatar(comment.User) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(avatar_size), + Masking = true, + CornerRadius = avatar_size / 2, + }, + } + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(0, 3), + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7, 0), + Children = new Drawable[] { - AutoSizeAxes = Axes.Both, - }, - new ParentUsername(comment), - new SpriteText - { - Alpha = comment.IsDeleted? 1 : 0, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), - Text = @"deleted", + username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) + { + AutoSizeAxes = Axes.Both, + }, + new ParentUsername(comment), + new SpriteText + { + Alpha = comment.IsDeleted? 1 : 0, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), + Text = @"deleted", + } } - } - }, - message = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Right = 40 } - }, - info = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Colour = OsuColour.Gray(0.7f), - Children = new Drawable[] + }, + message = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) { - new SpriteText + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Right = 40 } + }, + info = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Colour = OsuColour.Gray(0.7f), + Children = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: 12), - Text = HumanizerUtils.Humanize(comment.CreatedAt) - }, - new RepliesButton(comment.RepliesCount) - { - Expanded = { BindTarget = childExpanded } - }, + new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: 12), + Text = HumanizerUtils.Humanize(comment.CreatedAt) + }, + new RepliesButton(comment.RepliesCount) + { + Expanded = { BindTarget = childExpanded } + }, + } } } } @@ -161,7 +166,7 @@ namespace osu.Game.Overlays.Comments { childCommentsContainer = new FillFlowContainer { - Margin = new MarginPadding { Left = 20 }, + Padding = new MarginPadding { Left = 20 }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical From d4843285dbf091b6756b71e86599a94ffb8bbde0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 14 Oct 2019 17:33:14 +0300 Subject: [PATCH 3452/5608] CI fixes --- osu.Game/Graphics/UserInterface/ShowMoreButton.cs | 6 +++--- osu.Game/Online/API/Requests/Responses/Comment.cs | 4 ++-- osu.Game/Overlays/Comments/CommentsContainer.cs | 1 + osu.Game/Overlays/Comments/DrawableComment.cs | 15 +++++---------- osu.Game/Overlays/Comments/ShowChildsButton.cs | 2 +- 5 files changed, 12 insertions(+), 16 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs index 627ad995e8..8b2eb31d96 100644 --- a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs +++ b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs @@ -23,13 +23,13 @@ namespace osu.Game.Graphics.UserInterface public Color4 ChevronIconColour { get => chevronIconColour; - set { chevronIconColour = leftChevron.AccentColour = rightChevron.AccentColour = value; } + set => chevronIconColour = leftChevron.AccentColour = rightChevron.AccentColour = value; } public string Text { get => text.Text; - set { text.Text = value; } + set => text.Text = value; } private bool isLoading; @@ -136,7 +136,7 @@ namespace osu.Game.Graphics.UserInterface public Color4 AccentColour { get => accentColour; - set { accentColour = Colour = value; } + set => accentColour = Colour = value; } public ChevronIcon() diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 5e67bff859..6243ea4fb6 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -42,7 +42,7 @@ namespace osu.Game.Online.API.Requests.Responses public string Message { get; set; } [JsonProperty(@"message_html")] - public string MessageHTML { get; set; } + public string MessageHtml { get; set; } [JsonProperty(@"replies_count")] public int RepliesCount { get; set; } @@ -95,7 +95,7 @@ namespace osu.Game.Online.API.Requests.Responses if (IsDeleted) return @"deleted"; - return WebUtility.HtmlDecode(Regex.Replace(MessageHTML, @"<(.|\n)*?>", string.Empty)); + return WebUtility.HtmlDecode(Regex.Replace(MessageHtml, @"<(.|\n)*?>", string.Empty)); } public int GetDeletedChildsCount() diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index a5e921e2c0..6c674678df 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -182,6 +182,7 @@ namespace osu.Game.Overlays.Comments moreButton.Current.Value = response.TopLevelCount - loadedTopLevelComments; moreButton.IsLoading = false; } + moreButton.FadeTo(response.HasMore ? 1 : 0); }, loadCancellation.Token); } diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index e5258ef3cc..38e45949e1 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -28,13 +28,13 @@ namespace osu.Game.Overlays.Comments private readonly BindableBool childExpanded = new BindableBool(true); private readonly FillFlowContainer childCommentsVisibilityContainer; - private readonly DeletedChildsPlaceholder deletedChildsPlaceholder; private readonly Comment comment; public DrawableComment(Comment comment) { LinkFlowContainer username; FillFlowContainer childCommentsContainer; + DeletedChildsPlaceholder deletedChildsPlaceholder; FillFlowContainer info; LinkFlowContainer message; GridContainer content; @@ -93,7 +93,7 @@ namespace osu.Game.Overlays.Comments Origin = Anchor.Centre, Size = new Vector2(avatar_size), Masking = true, - CornerRadius = avatar_size / 2, + CornerRadius = avatar_size / 2f, }, } }, @@ -118,7 +118,7 @@ namespace osu.Game.Overlays.Comments new ParentUsername(comment), new SpriteText { - Alpha = comment.IsDeleted? 1 : 0, + Alpha = comment.IsDeleted ? 1 : 0, Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), Text = @"deleted", } @@ -299,8 +299,6 @@ namespace osu.Game.Overlays.Comments private class ParentUsername : FillFlowContainer, IHasTooltip { - private const int spacing = 3; - public string TooltipText => comment.ParentComment?.GetMessage() ?? ""; private readonly Comment comment; @@ -311,7 +309,7 @@ namespace osu.Game.Overlays.Comments AutoSizeAxes = Axes.Both; Direction = FillDirection.Horizontal; - Spacing = new Vector2(spacing, 0); + Spacing = new Vector2(3, 0); Alpha = comment.ParentId == null ? 0 : 1; Children = new Drawable[] { @@ -331,13 +329,10 @@ namespace osu.Game.Overlays.Comments private class VotePill : CircularContainer { - private const int height = 20; - private const int margin = 10; - public VotePill(int count) { AutoSizeAxes = Axes.X; - Height = height; + Height = 20; Masking = true; Children = new Drawable[] { diff --git a/osu.Game/Overlays/Comments/ShowChildsButton.cs b/osu.Game/Overlays/Comments/ShowChildsButton.cs index b29e316e80..464c0a1503 100644 --- a/osu.Game/Overlays/Comments/ShowChildsButton.cs +++ b/osu.Game/Overlays/Comments/ShowChildsButton.cs @@ -12,7 +12,7 @@ namespace osu.Game.Overlays.Comments { public readonly BindableBool Expanded = new BindableBool(true); - public ShowChildsButton() + protected ShowChildsButton() { AutoSizeAxes = Axes.Both; } From 6da1b4d0120317643473c61c4e9e9ce6f34f6784 Mon Sep 17 00:00:00 2001 From: miterosan Date: Mon, 14 Oct 2019 21:46:01 +0200 Subject: [PATCH 3453/5608] Fix incorrect current directory that accours on some devices on android. --- osu.Android/OsuGameActivity.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index 762a9c418d..41531617af 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.cs @@ -16,6 +16,11 @@ namespace osu.Android protected override void OnCreate(Bundle savedInstanceState) { + // The default current directory on android is '/'. + // On some devices '/' maps to the app data directory. On others it maps to the root of the internal storage. + // In order to have a consitend current directory on all devices the full path of the app data directory is set as the current directory. + System.Environment.CurrentDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); + base.OnCreate(savedInstanceState); Window.AddFlags(WindowManagerFlags.Fullscreen); From b1f7a673e719ede09fd76bd4e2da36658aaa53bc Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 00:10:02 +0300 Subject: [PATCH 3454/5608] Simplify chevron icon coloring --- osu.Game/Graphics/UserInterface/ShowMoreButton.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs index 8b2eb31d96..854b7abce1 100644 --- a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs +++ b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs @@ -23,7 +23,7 @@ namespace osu.Game.Graphics.UserInterface public Color4 ChevronIconColour { get => chevronIconColour; - set => chevronIconColour = leftChevron.AccentColour = rightChevron.AccentColour = value; + set => chevronIconColour = leftChevron.Colour = rightChevron.Colour = value; } public string Text @@ -131,14 +131,6 @@ namespace osu.Game.Graphics.UserInterface { private const int icon_size = 8; - private Color4 accentColour; - - public Color4 AccentColour - { - get => accentColour; - set => accentColour = Colour = value; - } - public ChevronIcon() { Anchor = Anchor.Centre; From 0676c880b53a612093ef2f0fb8f46c03246f355d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 00:26:31 +0300 Subject: [PATCH 3455/5608] Simplify IsTopLevel and IsDeleted properties --- .../Online/API/Requests/Responses/Comment.cs | 30 ++++--------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 6243ea4fb6..5accd7fd5b 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -16,20 +16,10 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"id")] public long Id { get; set; } - private long? parentId; - [JsonProperty(@"parent_id")] - public long? ParentId - { - get => parentId; - set - { - parentId = value; - IsTopLevel = value == null; - } - } + public long? ParentId { get; set; } - public List ChildComments = new List(); + public readonly List ChildComments = new List(); public Comment ParentComment { get; set; } @@ -65,18 +55,8 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"updated_at")] public DateTimeOffset? UpdatedAt { get; set; } - private DateTimeOffset? deletedAt; - [JsonProperty(@"deleted_at")] - public DateTimeOffset? DeletedAt - { - get => deletedAt; - set - { - deletedAt = value; - IsDeleted = value != null; - } - } + public DateTimeOffset? DeletedAt { get; set; } [JsonProperty(@"edited_at")] public DateTimeOffset? EditedAt { get; set; } @@ -86,9 +66,9 @@ namespace osu.Game.Online.API.Requests.Responses public User EditedUser { get; set; } - public bool IsTopLevel { get; set; } + public bool IsTopLevel => !ParentId.HasValue; - public bool IsDeleted { get; set; } + public bool IsDeleted => DeletedAt.HasValue; public string GetMessage() { From 09621f066e8fc1ac9b93e755c1fc94b416b8148e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 00:32:21 +0300 Subject: [PATCH 3456/5608] Childs -> Children --- .../Online/TestSceneCommentsContainer.cs | 4 ++-- .../Online/API/Requests/Responses/Comment.cs | 2 +- .../Overlays/Comments/CommentsContainer.cs | 8 ++++---- ...holder.cs => DeletedChildrenPlaceholder.cs} | 4 ++-- osu.Game/Overlays/Comments/DrawableComment.cs | 18 +++++++++--------- ...owChildsButton.cs => ShowChildrenButton.cs} | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) rename osu.Game/Overlays/Comments/{DeletedChildsPlaceholder.cs => DeletedChildrenPlaceholder.cs} (95%) rename osu.Game/Overlays/Comments/{ShowChildsButton.cs => ShowChildrenButton.cs} (89%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index 5e4aa27fae..436e80d6f5 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -21,8 +21,8 @@ namespace osu.Game.Tests.Visual.Online typeof(DrawableComment), typeof(HeaderButton), typeof(SortTabControl), - typeof(ShowChildsButton), - typeof(DeletedChildsPlaceholder) + typeof(ShowChildrenButton), + typeof(DeletedChildrenPlaceholder) }; protected override bool UseOnlineAPI => true; diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 5accd7fd5b..9e8f0cada2 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -78,7 +78,7 @@ namespace osu.Game.Online.API.Requests.Responses return WebUtility.HtmlDecode(Regex.Replace(MessageHtml, @"<(.|\n)*?>", string.Empty)); } - public int GetDeletedChildsCount() + public int GetDeletedChildrenCount() { int count = 0; diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 6c674678df..48b3952093 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.Comments private readonly Box background; private readonly FillFlowContainer content; - private readonly DeletedChildsPlaceholder deletedChildsPlaceholder; + private readonly DeletedChildrenPlaceholder deletedChildrenPlaceholder; private readonly CommentsShowMoreButton moreButton; public CommentsContainer(CommentableType type, long id) @@ -87,7 +87,7 @@ namespace osu.Game.Overlays.Comments Direction = FillDirection.Vertical, Children = new Drawable[] { - deletedChildsPlaceholder = new DeletedChildsPlaceholder + deletedChildrenPlaceholder = new DeletedChildrenPlaceholder { ShowDeleted = { BindTarget = ShowDeleted } }, @@ -126,7 +126,7 @@ namespace osu.Game.Overlays.Comments { currentPage = 1; loadedTopLevelComments = 0; - deletedChildsPlaceholder.DeletedCount.Value = 0; + deletedChildrenPlaceholder.DeletedCount.Value = 0; moreButton.IsLoading = true; content.Clear(); } @@ -170,7 +170,7 @@ namespace osu.Game.Overlays.Comments deletedComments++; }); - deletedChildsPlaceholder.DeletedCount.Value = initial ? deletedComments : deletedChildsPlaceholder.DeletedCount.Value + deletedComments; + deletedChildrenPlaceholder.DeletedCount.Value = initial ? deletedComments : deletedChildrenPlaceholder.DeletedCount.Value + deletedComments; if (response.HasMore) { diff --git a/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs b/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs similarity index 95% rename from osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs rename to osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs index 058f8cc750..f537141d7f 100644 --- a/osu.Game/Overlays/Comments/DeletedChildsPlaceholder.cs +++ b/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs @@ -10,7 +10,7 @@ using osu.Framework.Bindables; namespace osu.Game.Overlays.Comments { - public class DeletedChildsPlaceholder : FillFlowContainer + public class DeletedChildrenPlaceholder : FillFlowContainer { public readonly BindableBool ShowDeleted = new BindableBool(); public readonly BindableInt DeletedCount = new BindableInt(); @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Comments private readonly SpriteText countText; - public DeletedChildsPlaceholder() + public DeletedChildrenPlaceholder() { AutoSizeAxes = Axes.Both; Direction = FillDirection.Horizontal; diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 38e45949e1..81a6c6a743 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Comments public readonly BindableBool ShowDeleted = new BindableBool(); - private readonly BindableBool childExpanded = new BindableBool(true); + private readonly BindableBool childrenExpanded = new BindableBool(true); private readonly FillFlowContainer childCommentsVisibilityContainer; private readonly Comment comment; @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Comments { LinkFlowContainer username; FillFlowContainer childCommentsContainer; - DeletedChildsPlaceholder deletedChildsPlaceholder; + DeletedChildrenPlaceholder deletedChildrenPlaceholder; FillFlowContainer info; LinkFlowContainer message; GridContainer content; @@ -147,7 +147,7 @@ namespace osu.Game.Overlays.Comments }, new RepliesButton(comment.RepliesCount) { - Expanded = { BindTarget = childExpanded } + Expanded = { BindTarget = childrenExpanded } }, } } @@ -171,7 +171,7 @@ namespace osu.Game.Overlays.Comments AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical }, - deletedChildsPlaceholder = new DeletedChildsPlaceholder + deletedChildrenPlaceholder = new DeletedChildrenPlaceholder { ShowDeleted = { BindTarget = ShowDeleted } } @@ -180,7 +180,7 @@ namespace osu.Game.Overlays.Comments } }; - deletedChildsPlaceholder.DeletedCount.Value = comment.GetDeletedChildsCount(); + deletedChildrenPlaceholder.DeletedCount.Value = comment.GetDeletedChildrenCount(); if (comment.UserId.HasValue) username.AddUserLink(comment.User); @@ -231,7 +231,7 @@ namespace osu.Game.Overlays.Comments Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Margin = new MarginPadding { Right = 30, Top = margin }, - Expanded = { BindTarget = childExpanded } + Expanded = { BindTarget = childrenExpanded } }); } } @@ -245,7 +245,7 @@ namespace osu.Game.Overlays.Comments protected override void LoadComplete() { ShowDeleted.BindValueChanged(onShowDeletedChanged, true); - childExpanded.BindValueChanged(expanded => childCommentsVisibilityContainer.FadeTo(expanded.NewValue ? 1 : 0), true); + childrenExpanded.BindValueChanged(expanded => childCommentsVisibilityContainer.FadeTo(expanded.NewValue ? 1 : 0), true); base.LoadComplete(); } @@ -255,7 +255,7 @@ namespace osu.Game.Overlays.Comments this.FadeTo(show.NewValue ? 1 : 0); } - private class ChevronButton : ShowChildsButton + private class ChevronButton : ShowChildrenButton { private readonly SpriteIcon icon; @@ -275,7 +275,7 @@ namespace osu.Game.Overlays.Comments } } - private class RepliesButton : ShowChildsButton + private class RepliesButton : ShowChildrenButton { private readonly SpriteText text; private readonly int count; diff --git a/osu.Game/Overlays/Comments/ShowChildsButton.cs b/osu.Game/Overlays/Comments/ShowChildrenButton.cs similarity index 89% rename from osu.Game/Overlays/Comments/ShowChildsButton.cs rename to osu.Game/Overlays/Comments/ShowChildrenButton.cs index 464c0a1503..be04b6e5de 100644 --- a/osu.Game/Overlays/Comments/ShowChildsButton.cs +++ b/osu.Game/Overlays/Comments/ShowChildrenButton.cs @@ -8,11 +8,11 @@ using osu.Framework.Bindables; namespace osu.Game.Overlays.Comments { - public abstract class ShowChildsButton : OsuHoverContainer + public abstract class ShowChildrenButton : OsuHoverContainer { public readonly BindableBool Expanded = new BindableBool(true); - protected ShowChildsButton() + protected ShowChildrenButton() { AutoSizeAxes = Axes.Both; } From b84c9dfd84f206d3766b950803116fd687c61c7d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 00:35:44 +0300 Subject: [PATCH 3457/5608] Use Humanizer.ToQuantity instead of manual parsing --- osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs b/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs index f537141d7f..21cf01f993 100644 --- a/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs +++ b/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs @@ -7,6 +7,7 @@ using osu.Game.Graphics; using osu.Framework.Graphics.Sprites; using osuTK; using osu.Framework.Bindables; +using Humanizer; namespace osu.Game.Overlays.Comments { @@ -62,12 +63,7 @@ namespace osu.Game.Overlays.Comments return; } - string str = $@"{count.NewValue} deleted comment"; - - if (!(count.NewValue.ToString().EndsWith("1") && !count.NewValue.ToString().EndsWith("11"))) - str += "s"; - - countText.Text = str; + countText.Text = @"deleted comment".ToQuantity(count.NewValue); Show(); } } From 0fd6b0c8524912ec9cc4b98cae03434a9db1154c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 00:55:33 +0300 Subject: [PATCH 3458/5608] Use linq expression to count deleted comments --- osu.Game/Online/API/Requests/Responses/Comment.cs | 14 +------------- osu.Game/Overlays/Comments/CommentsContainer.cs | 9 ++------- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- 3 files changed, 4 insertions(+), 21 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 9e8f0cada2..046de194db 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -78,18 +78,6 @@ namespace osu.Game.Online.API.Requests.Responses return WebUtility.HtmlDecode(Regex.Replace(MessageHtml, @"<(.|\n)*?>", string.Empty)); } - public int GetDeletedChildrenCount() - { - int count = 0; - - if (ChildComments.Any()) - ChildComments.ForEach(child => - { - if (child.IsDeleted) - count++; - }); - - return count; - } + public int GetDeletedChildrenCount => ChildComments.Select(c => c.IsDeleted).Where(c => c).Count(); } } diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 48b3952093..318422bedb 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; using System.Threading; +using System.Linq; namespace osu.Game.Overlays.Comments { @@ -162,13 +163,7 @@ namespace osu.Game.Overlays.Comments { content.Add(loaded); - int deletedComments = 0; - - response.Comments.ForEach(comment => - { - if (comment.IsDeleted && comment.IsTopLevel) - deletedComments++; - }); + int deletedComments = response.Comments.Select(c => c.IsDeleted && c.IsTopLevel).Where(c => c).Count(); deletedChildrenPlaceholder.DeletedCount.Value = initial ? deletedComments : deletedChildrenPlaceholder.DeletedCount.Value + deletedComments; diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 81a6c6a743..13c67b9f5b 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -180,7 +180,7 @@ namespace osu.Game.Overlays.Comments } }; - deletedChildrenPlaceholder.DeletedCount.Value = comment.GetDeletedChildrenCount(); + deletedChildrenPlaceholder.DeletedCount.Value = comment.GetDeletedChildrenCount; if (comment.UserId.HasValue) username.AddUserLink(comment.User); From 42a06a54ffb3779c7079e0b8cbd934e7d204fe77 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 01:08:23 +0300 Subject: [PATCH 3459/5608] Don't use ProfileShowMoreButton in the test scene to avoid confusion --- .../Visual/Online/TestSceneShowMoreButton.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs index 8d4955abf0..b9fbbfef6b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Overlays.Profile.Sections; using System; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; +using osu.Framework.Allocation; +using osu.Game.Graphics; namespace osu.Game.Tests.Visual.Online { @@ -18,11 +19,11 @@ namespace osu.Game.Tests.Visual.Online public TestSceneShowMoreButton() { - ProfileShowMoreButton button = null; + TestButton button = null; int fireCount = 0; - Add(button = new ProfileShowMoreButton + Add(button = new TestButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -52,5 +53,16 @@ namespace osu.Game.Tests.Visual.Online AddAssert("action fired twice", () => fireCount == 2); AddAssert("is in loading state", () => button.IsLoading); } + + private class TestButton : ShowMoreButton + { + [BackgroundDependencyLoader] + private void load(OsuColour colors) + { + IdleColour = colors.YellowDark; + HoverColour = colors.Yellow; + ChevronIconColour = colors.Red; + } + } } } From ad32d663652c2432a4f31bb73dc3b555a1e743c4 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 01:10:23 +0300 Subject: [PATCH 3460/5608] CI fix --- osu.Game/Online/API/Requests/Responses/Comment.cs | 2 +- osu.Game/Overlays/Comments/CommentsContainer.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 046de194db..9d011c49c1 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -78,6 +78,6 @@ namespace osu.Game.Online.API.Requests.Responses return WebUtility.HtmlDecode(Regex.Replace(MessageHtml, @"<(.|\n)*?>", string.Empty)); } - public int GetDeletedChildrenCount => ChildComments.Select(c => c.IsDeleted).Where(c => c).Count(); + public int GetDeletedChildrenCount => ChildComments.Select(c => c.IsDeleted).Count(c => c); } } diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 318422bedb..49c479f6e5 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -163,7 +163,7 @@ namespace osu.Game.Overlays.Comments { content.Add(loaded); - int deletedComments = response.Comments.Select(c => c.IsDeleted && c.IsTopLevel).Where(c => c).Count(); + int deletedComments = response.Comments.Select(c => c.IsDeleted && c.IsTopLevel).Count(c => c); deletedChildrenPlaceholder.DeletedCount.Value = initial ? deletedComments : deletedChildrenPlaceholder.DeletedCount.Value + deletedComments; From ccc753a3151b1f8066e5015527d0bba6f448687a Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 14 Oct 2019 16:27:59 -0700 Subject: [PATCH 3461/5608] Make OverlayContainers with no blocking input VisibilityContainers --- osu.Game/OsuGame.cs | 2 +- osu.Game/Overlays/Toolbar/Toolbar.cs | 4 +--- osu.Game/Overlays/VolumeOverlay.cs | 4 +--- osu.Game/Screens/Play/ResumeOverlay.cs | 4 +--- osu.Game/Screens/Play/SkipOverlay.cs | 3 +-- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 4 +--- 6 files changed, 6 insertions(+), 15 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 5742d423bb..4dcc181bea 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -102,7 +102,7 @@ namespace osu.Game private readonly List overlays = new List(); - private readonly List toolbarElements = new List(); + private readonly List toolbarElements = new List(); private readonly List visibleBlockingOverlays = new List(); diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 19038c3981..b044bc4de0 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -16,7 +16,7 @@ using osu.Game.Rulesets; namespace osu.Game.Overlays.Toolbar { - public class Toolbar : OverlayContainer + public class Toolbar : VisibilityContainer { public const float HEIGHT = 40; public const float TOOLTIP_HEIGHT = 30; @@ -26,8 +26,6 @@ namespace osu.Game.Overlays.Toolbar private ToolbarUserButton userButton; private ToolbarRulesetSelector rulesetSelector; - protected override bool BlockPositionalInput => false; - private const double transition_time = 500; private const float alpha_hovering = 0.8f; diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index 27e2eef200..ca7665eba5 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public class VolumeOverlay : OverlayContainer + public class VolumeOverlay : VisibilityContainer { private const float offset = 10; @@ -28,8 +28,6 @@ namespace osu.Game.Overlays private VolumeMeter volumeMeterMusic; private MuteButton muteButton; - protected override bool BlockPositionalInput => false; - private readonly BindableDouble muteAdjustment = new BindableDouble(); private readonly Bindable isMuted = new Bindable(); diff --git a/osu.Game/Screens/Play/ResumeOverlay.cs b/osu.Game/Screens/Play/ResumeOverlay.cs index 2ef76069c2..641d5358ba 100644 --- a/osu.Game/Screens/Play/ResumeOverlay.cs +++ b/osu.Game/Screens/Play/ResumeOverlay.cs @@ -16,7 +16,7 @@ namespace osu.Game.Screens.Play /// /// An overlay which can be used to require further user actions before gameplay is resumed. /// - public abstract class ResumeOverlay : OverlayContainer + public abstract class ResumeOverlay : VisibilityContainer { public CursorContainer GameplayCursor { get; set; } @@ -29,8 +29,6 @@ namespace osu.Game.Screens.Play protected const float TRANSITION_TIME = 500; - protected override bool BlockPositionalInput => false; - protected abstract string Message { get; } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index d6c2b59d98..31cdff5fb9 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -23,7 +23,7 @@ using osu.Game.Input.Bindings; namespace osu.Game.Screens.Play { - public class SkipOverlay : OverlayContainer, IKeyBindingHandler + public class SkipOverlay : VisibilityContainer, IKeyBindingHandler { private readonly double startTime; @@ -36,7 +36,6 @@ namespace osu.Game.Screens.Play private double displayTime; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; - protected override bool BlockPositionalInput => false; /// /// Displays a skip overlay, giving the user the ability to skip forward. diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 8b360d4a86..d54c13c7db 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -29,7 +29,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Screens.Select { - public class BeatmapInfoWedge : OverlayContainer + public class BeatmapInfoWedge : VisibilityContainer { private const float shear_width = 36.75f; @@ -62,8 +62,6 @@ namespace osu.Game.Screens.Select ruleset.ValueChanged += _ => updateDisplay(); } - protected override bool BlockPositionalInput => false; - protected override void PopIn() { this.MoveToX(0, 800, Easing.OutQuint); From f4924dc3cf876999b027c0bc0e9a89e203999e1b Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 14 Oct 2019 16:37:54 -0700 Subject: [PATCH 3462/5608] Fix volume scrolling when hovering VersionManager --- osu.Desktop/Overlays/VersionManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 6eed46867a..8c759f8487 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Desktop.Overlays { - public class VersionManager : OverlayContainer + public class VersionManager : VisibilityContainer { [BackgroundDependencyLoader] private void load(OsuColour colours, TextureStore textures, OsuGameBase game) From efc201ec852561e3ab31491c4e171d9767a93665 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 14 Oct 2019 16:40:53 -0700 Subject: [PATCH 3463/5608] Make PlaylistOverlay a VisibilityContainer --- osu.Game/Overlays/Music/PlaylistOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index bb88960280..b89a577282 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Music { - public class PlaylistOverlay : OverlayContainer + public class PlaylistOverlay : VisibilityContainer { private const float transition_duration = 600; private const float playlist_height = 510; From 12cd57744b87d559679e179f5f366ab1e64f6238 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 Oct 2019 16:14:06 +0900 Subject: [PATCH 3464/5608] Make RulestStore initialise at construction time --- .../Background/TestSceneUserDimContainer.cs | 6 ++ .../SongSelect/TestScenePlaySongSelect.cs | 6 ++ osu.Game/OsuGameBase.cs | 6 ++ osu.Game/Rulesets/RulesetStore.cs | 57 +++++++++++-------- 4 files changed, 52 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index 3061a3a542..f858174ff2 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -285,6 +285,12 @@ namespace osu.Game.Tests.Visual.Background }); } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + rulesets?.Dispose(); + } + private class DummySongSelect : PlaySongSelect { protected override BackgroundScreen CreateBackground() diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index a7020b6534..efe7fee5e4 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -349,5 +349,11 @@ namespace osu.Game.Tests.Visual.SongSelect DateAdded = DateTimeOffset.UtcNow, }; } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + rulesets?.Dispose(); + } } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 8578517a17..194a439b06 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -298,6 +298,12 @@ namespace osu.Game public string[] HandledExtensions => fileImporters.SelectMany(i => i.HandledExtensions).ToArray(); + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + RulesetStore?.Dispose(); + } + private class OsuUserInputManager : UserInputManager { protected override MouseButtonEventManager CreateButtonManagerFor(MouseButton button) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 47aad43966..1df8568ee1 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -14,25 +14,22 @@ namespace osu.Game.Rulesets /// /// Todo: All of this needs to be moved to a RulesetStore. /// - public class RulesetStore : DatabaseBackedStore + public class RulesetStore : DatabaseBackedStore, IDisposable { - private static readonly Dictionary loaded_assemblies = new Dictionary(); + private const string ruleset_library_prefix = "osu.Game.Rulesets"; - static RulesetStore() - { - AppDomain.CurrentDomain.AssemblyResolve += currentDomain_AssemblyResolve; - - // On android in release configuration assemblies are loaded from the apk directly into memory. - // We cannot read assemblies from cwd, so should check loaded assemblies instead. - loadFromAppDomain(); - - loadFromDisk(); - } + private readonly Dictionary loadedAssemblies = new Dictionary(); public RulesetStore(IDatabaseContextFactory factory) : base(factory) { + // On android in release configuration assemblies are loaded from the apk directly into memory. + // We cannot read assemblies from cwd, so should check loaded assemblies instead. + loadFromAppDomain(); + loadFromDisk(); addMissingRulesets(); + + AppDomain.CurrentDomain.AssemblyResolve += resolveRulesetAssembly; } /// @@ -54,9 +51,7 @@ namespace osu.Game.Rulesets /// public IEnumerable AvailableRulesets { get; private set; } - private static Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args) => loaded_assemblies.Keys.FirstOrDefault(a => a.FullName == args.Name); - - private const string ruleset_library_prefix = "osu.Game.Rulesets"; + private Assembly resolveRulesetAssembly(object sender, ResolveEventArgs args) => loadedAssemblies.Keys.FirstOrDefault(a => a.FullName == args.Name); private void addMissingRulesets() { @@ -64,7 +59,7 @@ namespace osu.Game.Rulesets { var context = usage.Context; - var instances = loaded_assemblies.Values.Select(r => (Ruleset)Activator.CreateInstance(r, (RulesetInfo)null)).ToList(); + var instances = loadedAssemblies.Values.Select(r => (Ruleset)Activator.CreateInstance(r, (RulesetInfo)null)).ToList(); //add all legacy modes in correct order foreach (var r in instances.Where(r => r.LegacyID != null).OrderBy(r => r.LegacyID)) @@ -113,7 +108,7 @@ namespace osu.Game.Rulesets } } - private static void loadFromAppDomain() + private void loadFromAppDomain() { foreach (var ruleset in AppDomain.CurrentDomain.GetAssemblies()) { @@ -126,7 +121,7 @@ namespace osu.Game.Rulesets } } - private static void loadFromDisk() + private void loadFromDisk() { try { @@ -141,11 +136,11 @@ namespace osu.Game.Rulesets } } - private static void loadRulesetFromFile(string file) + private void loadRulesetFromFile(string file) { var filename = Path.GetFileNameWithoutExtension(file); - if (loaded_assemblies.Values.Any(t => t.Namespace == filename)) + if (loadedAssemblies.Values.Any(t => t.Namespace == filename)) return; try @@ -158,19 +153,35 @@ namespace osu.Game.Rulesets } } - private static void addRuleset(Assembly assembly) + private void addRuleset(Assembly assembly) { - if (loaded_assemblies.ContainsKey(assembly)) + if (loadedAssemblies.ContainsKey(assembly)) return; try { - loaded_assemblies[assembly] = assembly.GetTypes().First(t => t.IsPublic && t.IsSubclassOf(typeof(Ruleset))); + loadedAssemblies[assembly] = assembly.GetTypes().First(t => t.IsPublic && t.IsSubclassOf(typeof(Ruleset))); } catch (Exception e) { Logger.Error(e, $"Failed to add ruleset {assembly}"); } } + + ~RulesetStore() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + AppDomain.CurrentDomain.AssemblyResolve -= resolveRulesetAssembly; + } } } From 96c6aeefe92a864ecd783f253506b899a6a18741 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 15 Oct 2019 16:16:33 +0900 Subject: [PATCH 3465/5608] Remove out-of-date todo --- osu.Game/Rulesets/RulesetStore.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 1df8568ee1..0e6e0b8676 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -11,9 +11,6 @@ using osu.Game.Database; namespace osu.Game.Rulesets { - /// - /// Todo: All of this needs to be moved to a RulesetStore. - /// public class RulesetStore : DatabaseBackedStore, IDisposable { private const string ruleset_library_prefix = "osu.Game.Rulesets"; From 3c714dc01307216b23250329c5bc3bf0560138fe Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 11:20:06 +0300 Subject: [PATCH 3466/5608] APICommentsController -> CommentBundle --- osu.Game/Online/API/Requests/GetCommentsRequest.cs | 2 +- .../Responses/{APICommentsController.cs => CommentBundle.cs} | 2 +- osu.Game/Overlays/Comments/CommentsContainer.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename osu.Game/Online/API/Requests/Responses/{APICommentsController.cs => CommentBundle.cs} (98%) diff --git a/osu.Game/Online/API/Requests/GetCommentsRequest.cs b/osu.Game/Online/API/Requests/GetCommentsRequest.cs index 834a5106a0..7763501860 100644 --- a/osu.Game/Online/API/Requests/GetCommentsRequest.cs +++ b/osu.Game/Online/API/Requests/GetCommentsRequest.cs @@ -8,7 +8,7 @@ using osu.Game.Overlays.Comments; namespace osu.Game.Online.API.Requests { - public class GetCommentsRequest : APIRequest + public class GetCommentsRequest : APIRequest { private readonly long id; private readonly int page; diff --git a/osu.Game/Online/API/Requests/Responses/APICommentsController.cs b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs similarity index 98% rename from osu.Game/Online/API/Requests/Responses/APICommentsController.cs rename to osu.Game/Online/API/Requests/Responses/CommentBundle.cs index ca6062e371..7063581605 100644 --- a/osu.Game/Online/API/Requests/Responses/APICommentsController.cs +++ b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; namespace osu.Game.Online.API.Requests.Responses { - public class APICommentsController + public class CommentBundle { private List comments; diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 49c479f6e5..62f0ce947b 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -139,7 +139,7 @@ namespace osu.Game.Overlays.Comments api.Queue(request); } - private void onSuccess(APICommentsController response, bool initial) + private void onSuccess(CommentBundle response, bool initial) { loadCancellation = new CancellationTokenSource(); From eb5dad08aa6a8560d544358776c8e6ab3e18e2ea Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 11:25:58 +0300 Subject: [PATCH 3467/5608] Remove initial filed --- .../Online/API/Requests/Responses/Comment.cs | 2 +- .../Overlays/Comments/CommentsContainer.cs | 36 ++++++++++--------- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 9d011c49c1..68a4c28726 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -78,6 +78,6 @@ namespace osu.Game.Online.API.Requests.Responses return WebUtility.HtmlDecode(Regex.Replace(MessageHtml, @"<(.|\n)*?>", string.Empty)); } - public int GetDeletedChildrenCount => ChildComments.Select(c => c.IsDeleted).Count(c => c); + public int DeletedChildrenCount => ChildComments.Count(c => c.IsDeleted); } } diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 62f0ce947b..824d9822be 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -101,7 +101,7 @@ namespace osu.Game.Overlays.Comments Anchor = Anchor.Centre, Origin = Anchor.Centre, Margin = new MarginPadding(5), - Action = () => getComments(false), + Action = getComments } } } @@ -119,27 +119,31 @@ namespace osu.Game.Overlays.Comments base.LoadComplete(); } - private void onSortChanged(ValueChangedEvent sort) => getComments(); - - private void getComments(bool initial = true) + private void onSortChanged(ValueChangedEvent sort) { - if (initial) - { - currentPage = 1; - loadedTopLevelComments = 0; - deletedChildrenPlaceholder.DeletedCount.Value = 0; - moreButton.IsLoading = true; - content.Clear(); - } + clearComments(); + getComments(); + } + private void getComments() + { request?.Cancel(); loadCancellation?.Cancel(); request = new GetCommentsRequest(type, id, Sort.Value, currentPage++); - request.Success += response => onSuccess(response, initial); + request.Success += response => onSuccess(response); api.Queue(request); } - private void onSuccess(CommentBundle response, bool initial) + private void clearComments() + { + currentPage = 1; + loadedTopLevelComments = 0; + deletedChildrenPlaceholder.DeletedCount.Value = 0; + moreButton.IsLoading = true; + content.Clear(); + } + + private void onSuccess(CommentBundle response) { loadCancellation = new CancellationTokenSource(); @@ -163,9 +167,7 @@ namespace osu.Game.Overlays.Comments { content.Add(loaded); - int deletedComments = response.Comments.Select(c => c.IsDeleted && c.IsTopLevel).Count(c => c); - - deletedChildrenPlaceholder.DeletedCount.Value = initial ? deletedComments : deletedChildrenPlaceholder.DeletedCount.Value + deletedComments; + deletedChildrenPlaceholder.DeletedCount.Value += response.Comments.Count(c => c.IsDeleted && c.IsTopLevel); if (response.HasMore) { diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 13c67b9f5b..b22bd6d426 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -180,7 +180,7 @@ namespace osu.Game.Overlays.Comments } }; - deletedChildrenPlaceholder.DeletedCount.Value = comment.GetDeletedChildrenCount; + deletedChildrenPlaceholder.DeletedCount.Value = comment.DeletedChildrenCount; if (comment.UserId.HasValue) username.AddUserLink(comment.User); From b2885e7b139b8def41fc532181d2d19f4a871fc3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 11:26:58 +0300 Subject: [PATCH 3468/5608] Move load() under the ctor --- osu.Game/Overlays/Comments/CommentsContainer.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 824d9822be..bd1a8562d3 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -113,6 +113,12 @@ namespace osu.Game.Overlays.Comments }); } + [BackgroundDependencyLoader] + private void load() + { + background.Colour = colours.Gray2; + } + protected override void LoadComplete() { Sort.BindValueChanged(onSortChanged, true); @@ -184,12 +190,6 @@ namespace osu.Game.Overlays.Comments }, loadCancellation.Token); } - [BackgroundDependencyLoader] - private void load() - { - background.Colour = colours.Gray2; - } - protected override void Dispose(bool isDisposing) { request?.Cancel(); From 213f00556d30b3f4bededf2c57832bb6e5182802 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 11:30:50 +0300 Subject: [PATCH 3469/5608] Remove onShowDeletedChanged function --- osu.Game/Overlays/Comments/DrawableComment.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index b22bd6d426..59d3d08122 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -244,17 +244,15 @@ namespace osu.Game.Overlays.Comments protected override void LoadComplete() { - ShowDeleted.BindValueChanged(onShowDeletedChanged, true); + ShowDeleted.BindValueChanged(show => + { + if (comment.IsDeleted) + this.FadeTo(show.NewValue ? 1 : 0); + }, true); childrenExpanded.BindValueChanged(expanded => childCommentsVisibilityContainer.FadeTo(expanded.NewValue ? 1 : 0), true); base.LoadComplete(); } - private void onShowDeletedChanged(ValueChangedEvent show) - { - if (comment.IsDeleted) - this.FadeTo(show.NewValue ? 1 : 0); - } - private class ChevronButton : ShowChildrenButton { private readonly SpriteIcon icon; From 96e31b9cca2b62147354b6608c11857280a7cade Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 12:07:01 +0300 Subject: [PATCH 3470/5608] Add support for deleted comments with message --- .../Online/API/Requests/Responses/Comment.cs | 8 ++----- osu.Game/Overlays/Comments/DrawableComment.cs | 23 +++++++++++++------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 68a4c28726..29abaa74e5 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -70,13 +70,9 @@ namespace osu.Game.Online.API.Requests.Responses public bool IsDeleted => DeletedAt.HasValue; - public string GetMessage() - { - if (IsDeleted) - return @"deleted"; + public bool HasMessage => !string.IsNullOrEmpty(MessageHtml); - return WebUtility.HtmlDecode(Regex.Replace(MessageHtml, @"<(.|\n)*?>", string.Empty)); - } + public string GetMessage => HasMessage ? WebUtility.HtmlDecode(Regex.Replace(MessageHtml, @"<(.|\n)*?>", string.Empty)) : string.Empty; public int DeletedChildrenCount => ChildComments.Count(c => c.IsDeleted); } diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 59d3d08122..89abda92cf 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -198,12 +198,13 @@ namespace osu.Game.Overlays.Comments }); } - if (!comment.IsDeleted) + if (comment.HasMessage) { - var formattedSource = MessageFormatter.FormatText(comment.GetMessage()); + var formattedSource = MessageFormatter.FormatText(comment.GetMessage); message.AddLinks(formattedSource.Text, formattedSource.Links); } - else + + if (comment.IsDeleted) { content.FadeColour(OsuColour.Gray(0.5f)); votePill.Hide(); @@ -297,13 +298,13 @@ namespace osu.Game.Overlays.Comments private class ParentUsername : FillFlowContainer, IHasTooltip { - public string TooltipText => comment.ParentComment?.GetMessage() ?? ""; + public string TooltipText => getParentMessage(); - private readonly Comment comment; + private readonly Comment parentComment; public ParentUsername(Comment comment) { - this.comment = comment; + parentComment = comment.ParentComment; AutoSizeAxes = Axes.Both; Direction = FillDirection.Horizontal; @@ -319,10 +320,18 @@ namespace osu.Game.Overlays.Comments new SpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), - Text = comment.ParentComment?.User?.Username ?? comment.ParentComment?.LegacyName + Text = parentComment?.User?.Username ?? parentComment?.LegacyName } }; } + + private string getParentMessage() + { + if (parentComment == null) + return string.Empty; + + return parentComment.HasMessage ? parentComment.GetMessage : parentComment.IsDeleted ? @"deleted" : string.Empty; + } } private class VotePill : CircularContainer From d321794ef5b0fefbb2330a3f9e35ef42457e0299 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 12:26:16 +0300 Subject: [PATCH 3471/5608] Make loadedTopLevelComments a local filed --- osu.Game/Overlays/Comments/CommentsContainer.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index bd1a8562d3..6ac31b258f 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -12,6 +12,7 @@ using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; using System.Threading; using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Overlays.Comments { @@ -32,7 +33,6 @@ namespace osu.Game.Overlays.Comments private GetCommentsRequest request; private CancellationTokenSource loadCancellation; private int currentPage; - private int loadedTopLevelComments; private readonly Box background; private readonly FillFlowContainer content; @@ -143,7 +143,6 @@ namespace osu.Game.Overlays.Comments private void clearComments() { currentPage = 1; - loadedTopLevelComments = 0; deletedChildrenPlaceholder.DeletedCount.Value = 0; moreButton.IsLoading = true; content.Clear(); @@ -177,11 +176,9 @@ namespace osu.Game.Overlays.Comments if (response.HasMore) { - response.Comments.ForEach(comment => - { - if (comment.IsTopLevel) - loadedTopLevelComments++; - }); + int loadedTopLevelComments = 0; + content.Children.OfType().ForEach(p => loadedTopLevelComments += p.Children.OfType().Count()); + moreButton.Current.Value = response.TopLevelCount - loadedTopLevelComments; moreButton.IsLoading = false; } From 7ba15df0c07f193016e3e4f0a71c00ccd7b99c15 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 12:27:32 +0300 Subject: [PATCH 3472/5608] Convert to method group --- osu.Game/Overlays/Comments/CommentsContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 6ac31b258f..abc1b7233d 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -136,7 +136,7 @@ namespace osu.Game.Overlays.Comments request?.Cancel(); loadCancellation?.Cancel(); request = new GetCommentsRequest(type, id, Sort.Value, currentPage++); - request.Success += response => onSuccess(response); + request.Success += onSuccess; api.Queue(request); } From 2543de22bd4f2bf5c8fe95f46944419312cb9361 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 15 Oct 2019 12:47:35 +0300 Subject: [PATCH 3473/5608] Simplify DeletedChildrenPlaceholder behavior --- .../Comments/DeletedChildrenPlaceholder.cs | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs b/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs index 21cf01f993..e849691597 100644 --- a/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs +++ b/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs @@ -16,8 +16,6 @@ namespace osu.Game.Overlays.Comments public readonly BindableBool ShowDeleted = new BindableBool(); public readonly BindableInt DeletedCount = new BindableInt(); - private bool canBeShown; - private readonly SpriteText countText; public DeletedChildrenPlaceholder() @@ -42,29 +40,22 @@ namespace osu.Game.Overlays.Comments protected override void LoadComplete() { - DeletedCount.BindValueChanged(onCountChanged, true); - ShowDeleted.BindValueChanged(onShowDeletedChanged, true); + DeletedCount.BindValueChanged(_ => updateDisplay(), true); + ShowDeleted.BindValueChanged(_ => updateDisplay(), true); base.LoadComplete(); } - private void onShowDeletedChanged(ValueChangedEvent showDeleted) + private void updateDisplay() { - if (canBeShown) - this.FadeTo(showDeleted.NewValue ? 0 : 1); - } - - private void onCountChanged(ValueChangedEvent count) - { - canBeShown = count.NewValue != 0; - - if (!canBeShown) + if (DeletedCount.Value != 0) + { + countText.Text = @"deleted comment".ToQuantity(DeletedCount.Value); + this.FadeTo(ShowDeleted.Value ? 0 : 1); + } + else { Hide(); - return; } - - countText.Text = @"deleted comment".ToQuantity(count.NewValue); - Show(); } } } From 8c671d7fde49cd038378105e029be1fa37113c79 Mon Sep 17 00:00:00 2001 From: HoLLy Date: Tue, 15 Oct 2019 20:12:08 +0200 Subject: [PATCH 3474/5608] Rename cursorScale and calculatedCursorScale --- .../UI/Cursor/OsuCursorContainer.cs | 20 +++++++++---------- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 8ea11d0a4b..52e2e493d5 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -29,9 +29,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly Drawable cursorTrail; - public IBindable CalculatedCursorScale => calculatedCursorScale; - private Bindable calculatedCursorScale; + public IBindable CursorScale => cursorScale; private Bindable cursorScale; + private Bindable userCursorScale; private Bindable autoCursorScale; private readonly IBindable beatmap = new Bindable(); @@ -52,21 +52,21 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor this.beatmap.BindTo(beatmap); this.beatmap.ValueChanged += _ => calculateScale(); - cursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); - cursorScale.ValueChanged += _ => calculateScale(); + userCursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); + userCursorScale.ValueChanged += _ => calculateScale(); autoCursorScale = config.GetBindable(OsuSetting.AutoCursorSize); autoCursorScale.ValueChanged += _ => calculateScale(); - calculatedCursorScale = new Bindable(); - calculatedCursorScale.ValueChanged += e => ActiveCursor.Scale = cursorTrail.Scale = new Vector2(e.NewValue); + cursorScale = new Bindable(); + cursorScale.ValueChanged += e => ActiveCursor.Scale = cursorTrail.Scale = new Vector2(e.NewValue); calculateScale(); } private void calculateScale() { - float scale = cursorScale.Value; + float scale = userCursorScale.Value; if (autoCursorScale.Value && beatmap.Value != null) { @@ -74,7 +74,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor scale *= 1f - 0.7f * (1f + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY; } - calculatedCursorScale.Value = scale; + cursorScale.Value = scale; } protected override void LoadComplete() @@ -130,13 +130,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor protected override void PopIn() { fadeContainer.FadeTo(1, 300, Easing.OutQuint); - ActiveCursor.ScaleTo(calculatedCursorScale.Value, 400, Easing.OutQuint); + ActiveCursor.ScaleTo(cursorScale.Value, 400, Easing.OutQuint); } protected override void PopOut() { fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint); - ActiveCursor.ScaleTo(calculatedCursorScale.Value * 0.8f, 450, Easing.OutQuint); + ActiveCursor.ScaleTo(cursorScale.Value * 0.8f, 450, Easing.OutQuint); } private class DefaultCursorTrail : CursorTrail diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 1ee2a04a3b..64821ac24f 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.UI { Add(localCursorContainer = new OsuCursorContainer()); - localCursorContainer.CalculatedCursorScale.BindValueChanged(scale => + localCursorContainer.CursorScale.BindValueChanged(scale => { clickToResumeCursor.CursorScale = scale.NewValue; clickToResumeCursor.Scale = new Vector2(scale.NewValue); From 60133ba0c3fa62ef7f7cc6f8f14ea47f886b2015 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 15 Oct 2019 23:33:50 +0300 Subject: [PATCH 3475/5608] Propagate BeatmapSetInfo to tab items with bindable --- .../BeatmapSet/BeatmapRulesetSelector.cs | 22 +++++++--------- .../BeatmapSet/BeatmapRulesetTabItem.cs | 26 +++++++++---------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs index bfb188a83b..a0bedc848e 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; @@ -13,23 +14,17 @@ namespace osu.Game.Overlays.BeatmapSet { public class BeatmapRulesetSelector : RulesetSelector { - private BeatmapSetInfo beatmapSet; + private readonly Bindable beatmapSet = new Bindable(); public BeatmapSetInfo BeatmapSet { - get => beatmapSet; + get => beatmapSet.Value; set { - if (value == beatmapSet) - return; + // propagate value to tab items first to enable only available rulesets. + beatmapSet.Value = value; - beatmapSet = value; - - foreach (var tab in TabContainer.TabItems.OfType()) - tab.SetBeatmaps(beatmapSet?.Beatmaps.FindAll(b => b.Ruleset.Equals(tab.Value))); - - var firstRuleset = beatmapSet?.Beatmaps.OrderBy(b => b.Ruleset.ID).FirstOrDefault()?.Ruleset; - SelectTab(TabContainer.TabItems.FirstOrDefault(t => t.Value.Equals(firstRuleset))); + SelectTab(TabContainer.TabItems.FirstOrDefault(t => t.Enabled.Value)); } } @@ -38,7 +33,10 @@ namespace osu.Game.Overlays.BeatmapSet AutoSizeAxes = Axes.Both; } - protected override TabItem CreateTabItem(RulesetInfo value) => new BeatmapRulesetTabItem(value); + protected override TabItem CreateTabItem(RulesetInfo value) => new BeatmapRulesetTabItem(value) + { + BeatmapSet = { BindTarget = beatmapSet } + }; protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer { diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs index 19c9af13d5..5227bec92a 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -15,8 +16,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; -using System.Collections.Generic; -using System.Diagnostics; +using System.Linq; namespace osu.Game.Overlays.BeatmapSet { @@ -25,6 +25,8 @@ namespace osu.Game.Overlays.BeatmapSet private readonly OsuSpriteText name, count; private readonly Box bar; + public readonly Bindable BeatmapSet = new Bindable(); + public override bool PropagatePositionalInputSubTree => Enabled.Value && !Active.Value && base.PropagatePositionalInputSubTree; public BeatmapRulesetTabItem(RulesetInfo value) @@ -90,6 +92,15 @@ namespace osu.Game.Overlays.BeatmapSet new HoverClickSounds(), }; + BeatmapSet.BindValueChanged(setInfo => + { + var beatmapsCount = setInfo.NewValue?.Beatmaps.Count(b => b.Ruleset.Equals(Value)) ?? 0; + count.Text = beatmapsCount.ToString(); + + count.Alpha = beatmapsCount > 0 ? 1f : 0f; + Enabled.Value = beatmapsCount > 0; + }, true); + Enabled.BindValueChanged(v => nameContainer.Alpha = v.NewValue ? 1f : 0.5f, true); } @@ -106,17 +117,6 @@ namespace osu.Game.Overlays.BeatmapSet updateState(); } - public void SetBeatmaps(List beatmaps) - { - Trace.Assert(beatmaps?.TrueForAll(b => b.Ruleset.Equals(Value)) ?? true, "A beatmap has a ruleset not of this tab value"); - - count.Text = beatmaps?.Count.ToString(); - - var hasBeatmaps = (beatmaps?.Count ?? 0) > 0; - count.Alpha = hasBeatmaps ? 1f : 0f; - Enabled.Value = hasBeatmaps; - } - private void updateState() { var isHoveredOrActive = IsHovered || Active.Value; From 14c72f85fa56387b3932908c616c0de68e3aee36 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 15 Oct 2019 23:40:48 +0300 Subject: [PATCH 3476/5608] Fix incorrect beatmap set info equality check on non-online set info --- osu.Game/Beatmaps/BeatmapSetInfo.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 03bc7c7312..90346a8c8b 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -63,6 +63,12 @@ namespace osu.Game.Beatmaps public bool Protected { get; set; } - public bool Equals(BeatmapSetInfo other) => OnlineBeatmapSetID == other?.OnlineBeatmapSetID; + public bool Equals(BeatmapSetInfo other) + { + if (!OnlineBeatmapSetID.HasValue || !(other?.OnlineBeatmapSetID.HasValue ?? false)) + return ReferenceEquals(this, other); + + return OnlineBeatmapSetID == other.OnlineBeatmapSetID; + } } } From 13e11992296cbacadebe87ae239f84f201739f41 Mon Sep 17 00:00:00 2001 From: HoLLy Date: Tue, 15 Oct 2019 22:44:04 +0200 Subject: [PATCH 3477/5608] Move click to resume cursor scaling responsibility to container --- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 25 ++++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 64821ac24f..908ad1ce49 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Osu.UI { public class OsuResumeOverlay : ResumeOverlay { + private Container cursorScaleContainer; private OsuClickToResumeCursor clickToResumeCursor; private OsuCursorContainer localCursorContainer; @@ -28,23 +29,24 @@ namespace osu.Game.Rulesets.Osu.UI [BackgroundDependencyLoader] private void load() { - Add(clickToResumeCursor = new OsuClickToResumeCursor { ResumeRequested = Resume }); + Add(cursorScaleContainer = new Container + { + RelativePositionAxes = Axes.Both, + Child = clickToResumeCursor = new OsuClickToResumeCursor { ResumeRequested = Resume } + }); } public override void Show() { base.Show(); - clickToResumeCursor.ShowAt(GameplayCursor.ActiveCursor.Position); + cursorScaleContainer.MoveTo(GameplayCursor.ActiveCursor.Position); + clickToResumeCursor.Appear(); if (localCursorContainer == null) { Add(localCursorContainer = new OsuCursorContainer()); - localCursorContainer.CursorScale.BindValueChanged(scale => - { - clickToResumeCursor.CursorScale = scale.NewValue; - clickToResumeCursor.Scale = new Vector2(scale.NewValue); - }, true); + localCursorContainer.CursorScale.BindValueChanged(scale => cursorScaleContainer.Scale = new Vector2(scale.NewValue), true); } } @@ -64,8 +66,6 @@ namespace osu.Game.Rulesets.Osu.UI public Action ResumeRequested; - public float CursorScale; - public OsuClickToResumeCursor() { RelativePositionAxes = Axes.Both; @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Osu.UI case OsuAction.RightButton: if (!IsHovered) return false; - this.ScaleTo(2 * CursorScale, TRANSITION_TIME, Easing.OutQuint); + this.ScaleTo(2, TRANSITION_TIME, Easing.OutQuint); ResumeRequested?.Invoke(); return true; @@ -102,11 +102,10 @@ namespace osu.Game.Rulesets.Osu.UI public bool OnReleased(OsuAction action) => false; - public void ShowAt(Vector2 activeCursorPosition) => Schedule(() => + public void Appear() => Schedule(() => { updateColour(); - this.MoveTo(activeCursorPosition); - this.ScaleTo(4 * CursorScale).Then().ScaleTo(CursorScale, 1000, Easing.OutQuint); + this.ScaleTo(4).Then().ScaleTo(1, 1000, Easing.OutQuint); }); private void updateColour() From 649951198e800e23b46292f389f1271d899086f6 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 15 Oct 2019 14:47:48 -0700 Subject: [PATCH 3478/5608] Make most textbox carets movable --- osu.Game/Graphics/UserInterface/SearchTextBox.cs | 2 -- osu.Game/Screens/Select/FilterControl.cs | 9 +++++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index c3efe2ed45..e2b0e1b425 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -14,8 +14,6 @@ namespace osu.Game.Graphics.UserInterface { protected virtual bool AllowCommit => false; - public override bool HandleLeftRightArrows => false; - public SearchTextBox() { Height = 35; diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 8755c3fda6..2c878f8d90 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -49,7 +49,7 @@ namespace osu.Game.Screens.Select return criteria; } - private readonly SearchTextBox searchTextBox; + private readonly SongSelectTextBox searchTextBox; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) || groupTabs.ReceivePositionalInputAt(screenSpacePos) || sortTabs.ReceivePositionalInputAt(screenSpacePos); @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.TopRight, Children = new Drawable[] { - searchTextBox = new SearchTextBox { RelativeSizeAxes = Axes.X }, + searchTextBox = new SongSelectTextBox { RelativeSizeAxes = Axes.X }, new Box { RelativeSizeAxes = Axes.X, @@ -170,5 +170,10 @@ namespace osu.Game.Screens.Select } private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria()); + + private class SongSelectTextBox : SearchTextBox + { + public override bool HandleLeftRightArrows => false; + } } } From 350d139cbf22fef749454d867b3b716f8e947bf4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 15:54:00 +0900 Subject: [PATCH 3479/5608] Make chevron icon colour protected --- osu.Game/Graphics/UserInterface/ShowMoreButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs index 854b7abce1..5296b9dd7f 100644 --- a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs +++ b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs @@ -20,7 +20,7 @@ namespace osu.Game.Graphics.UserInterface private Color4 chevronIconColour; - public Color4 ChevronIconColour + protected Color4 ChevronIconColour { get => chevronIconColour; set => chevronIconColour = leftChevron.Colour = rightChevron.Colour = value; From 736a36a326700ab325db2f3938025f9cf76a1490 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Wed, 16 Oct 2019 14:30:09 +0700 Subject: [PATCH 3480/5608] Fix failed testcase --- .../Visual/UserInterface/TestSceneNowPlayingOverlay.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index 33706d2e0f..4c76a04bdb 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -49,9 +49,10 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep(@"Call PrevTrack", () => musicController.PrevTrack()); AddAssert(@"Check if it restarted", () => currentTrack == Beatmap.Value); - AddStep(@"Seek track to 1 second", () => musicController.SeekTo(1000)); + AddStep(@"Seek track to 2 second", () => musicController.SeekTo(2000)); AddStep(@"Call PrevTrack", () => musicController.PrevTrack()); - AddAssert(@"Check if it changed to prev track'", () => currentTrack != Beatmap.Value); + // If the track isn't changing, check the current track's time instead + AddAssert(@"Check if it changed to prev track'", () => currentTrack != Beatmap.Value || currentTrack.Track.CurrentTime < 2000); } } } From 5ac5e34f8585fc0910ef4d6cf81307ca90e51b47 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 19:32:45 +0900 Subject: [PATCH 3481/5608] Use a cleaner distance function --- .../Edit/Compose/Components/CircularBeatSnapGrid.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs index 8492771808..bf363aeb37 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs @@ -18,13 +18,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void CreateContent(Vector2 centrePosition) { - float maxDistance = Math.Max( - Vector2.Distance(centrePosition, Vector2.Zero), - Math.Max( - Vector2.Distance(centrePosition, new Vector2(DrawWidth, 0)), - Math.Max( - Vector2.Distance(centrePosition, new Vector2(0, DrawHeight)), - Vector2.Distance(centrePosition, DrawSize)))); + float dx = Math.Max(centrePosition.X, DrawWidth - centrePosition.X); + float dy = Math.Max(centrePosition.Y, DrawHeight - centrePosition.Y); + float maxDistance = new Vector2(dx, dy).Length; int requiredCircles = (int)(maxDistance / DistanceSpacing); From 2d4b7dc361ca061fd74cef1654ab86875c58d518 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 19:33:18 +0900 Subject: [PATCH 3482/5608] Remove redundant code --- .../Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs index bf363aeb37..09679f0553 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs @@ -48,11 +48,7 @@ namespace osu.Game.Screens.Edit.Compose.Components float radius = DistanceSpacing; int radialCount = Math.Max(1, (int)Math.Round(distance / radius)); - if (radialCount <= 0) - return position; - Vector2 normalisedDirection = direction * new Vector2(1f / distance); - return CentrePosition + normalisedDirection * radialCount * radius; } } From b6b8098b989383b0402e2efe48476048f9b05f3f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 19:44:53 +0900 Subject: [PATCH 3483/5608] Add an arbitrary offset to prevent div-by-0 --- .../Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs index 09679f0553..5e378f8393 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs @@ -43,6 +43,10 @@ namespace osu.Game.Screens.Edit.Compose.Components public override Vector2 GetSnapPosition(Vector2 position) { Vector2 direction = position - CentrePosition; + + if (direction == Vector2.Zero) + direction = new Vector2(0.001f, 0.001f); + float distance = direction.Length; float radius = DistanceSpacing; From 2dac3a6efe89934faa8cc354e5581a83bd182bd3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 16 Oct 2019 13:58:29 +0300 Subject: [PATCH 3484/5608] Handle hitting the maximum allowed number of favourited beatmaps --- .../BeatmapSet/Buttons/FavouriteButton.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index fcea20ef11..e2bc1ee008 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -11,6 +11,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Overlays.Notifications; using osuTK; namespace osu.Game.Overlays.BeatmapSet.Buttons @@ -26,8 +27,8 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons public string TooltipText => (favourited.Value ? "Unfavourite" : "Favourite") + " this beatmapset"; - [BackgroundDependencyLoader] - private void load(IAPIProvider api) + [BackgroundDependencyLoader(true)] + private void load(IAPIProvider api, NotificationOverlay notifications) { SpriteIcon icon; AddRange(new Drawable[] @@ -68,6 +69,18 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons request?.Cancel(); request = new PostBeatmapFavouriteRequest(BeatmapSet.Value?.OnlineBeatmapSetID ?? 0, favourited.Value ? BeatmapFavouriteAction.UnFavourite : BeatmapFavouriteAction.Favourite); request.Success += () => favourited.Value = !favourited.Value; + request.Failure += exception => + { + if (exception.Message == "UnprocessableEntity") + { + notifications.Post(new SimpleNotification + { + Text = @"You have too many favourited beatmaps! Please unfavourite some before trying again.", + Icon = FontAwesome.Solid.Times, + }); + loading.Hide(); + } + }; api.Queue(request); }; } From 79b2c7b480f34c2d122f69aed9a69ae413bf7108 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 20:04:15 +0900 Subject: [PATCH 3485/5608] Make BeginPlacement() set the hitobject start time --- .../Edit/Blueprints/ManiaPlacementBlueprint.cs | 4 +--- .../Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs | 1 - .../Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs | 2 -- .../Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs | 2 -- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 4 +++- 5 files changed, 4 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 3142f22fcd..b28d8bb0e6 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -49,10 +49,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints if (Column == null) return base.OnMouseDown(e); - HitObject.StartTime = TimeAt(e.ScreenSpaceMousePosition); HitObject.Column = Column.Index; - - BeginPlacement(); + BeginPlacement(TimeAt(e.ScreenSpaceMousePosition)); return true; } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs index 6c08990ad6..bb47c7e464 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs @@ -30,7 +30,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles protected override bool OnClick(ClickEvent e) { - HitObject.StartTime = EditorClock.CurrentTime; EndPlacement(); return true; } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index fc074ef8af..2fb18bf8ba 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -104,8 +104,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private void beginCurve() { BeginPlacement(); - - HitObject.StartTime = EditorClock.CurrentTime; setState(PlacementState.Body); } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs index 8319f49cbc..5525b8936e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs @@ -41,8 +41,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners } else { - HitObject.StartTime = EditorClock.CurrentTime; - isPlacingEnd = true; piece.FadeTo(1f, 150, Easing.OutQuint); diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 290fd8d27d..07283d2245 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -91,8 +91,10 @@ namespace osu.Game.Rulesets.Edit /// /// Signals that the placement of has started. /// - protected void BeginPlacement() + /// The start time of at the placement point. If null, the current clock time is used. + protected void BeginPlacement(double? startTime = null) { + HitObject.StartTime = startTime ?? EditorClock.CurrentTime; placementHandler.BeginPlacement(HitObject); PlacementBegun = true; } From 4ac2e1c58ee1aab9bbac8cb62dc717a8e03f5d3a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 21:41:18 +0900 Subject: [PATCH 3486/5608] Move load() to below ctor() --- .../Objects/Drawables/DrawableSlider.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 9e8ad9851c..09157d4fdc 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -94,13 +94,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - protected override void UpdateInitialTransforms() - { - base.UpdateInitialTransforms(); - - Body.FadeInFromZero(HitObject.TimeFadeIn); - } - [BackgroundDependencyLoader] private void load() { @@ -129,6 +122,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, true); } + protected override void UpdateInitialTransforms() + { + base.UpdateInitialTransforms(); + + Body.FadeInFromZero(HitObject.TimeFadeIn); + } + public readonly Bindable Tracking = new Bindable(); protected override void Update() From 8d7453c251b68243ed6a082f815a1d2133e71aa4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 22:10:50 +0900 Subject: [PATCH 3487/5608] Rework construction of nested hitobjects --- .../Objects/Drawables/DrawableSlider.cs | 124 +++++++++++------- .../Objects/Drawables/DrawableHitObject.cs | 44 +++++-- 2 files changed, 111 insertions(+), 57 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 09157d4fdc..21411259ae 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -5,7 +5,6 @@ using osuTK; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; -using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -21,15 +20,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSlider : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { - private readonly Slider slider; - private readonly List components = new List(); - - public readonly DrawableHitCircle HeadCircle; - public readonly DrawableSliderTail TailCircle; + public DrawableSliderHead HeadCircle { get; private set; } + public DrawableSliderTail TailCircle { get; private set; } public readonly SnakingSliderBody Body; public readonly SliderBall Ball; + private readonly Container headContainer; + private readonly Container tailContainer; + private readonly Container tickContainer; + private readonly Container repeatContainer; + + private readonly Slider slider; + private readonly IBindable positionBindable = new Bindable(); private readonly IBindable scaleBindable = new Bindable(); private readonly IBindable pathBindable = new Bindable(); @@ -44,14 +47,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Position = s.StackedPosition; - Container ticks; - Container repeatPoints; - InternalChildren = new Drawable[] { Body = new SnakingSliderBody(s), - ticks = new Container { RelativeSizeAxes = Axes.Both }, - repeatPoints = new Container { RelativeSizeAxes = Axes.Both }, + tickContainer = new Container { RelativeSizeAxes = Axes.Both }, + repeatContainer = new Container { RelativeSizeAxes = Axes.Both }, Ball = new SliderBall(s, this) { GetInitialHitAction = () => HeadCircle.HitAction, @@ -60,38 +60,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables AlwaysPresent = true, Alpha = 0 }, - HeadCircle = new DrawableSliderHead(s, s.HeadCircle) - { - OnShake = Shake - }, - TailCircle = new DrawableSliderTail(s, s.TailCircle) + headContainer = new Container { RelativeSizeAxes = Axes.Both }, + tailContainer = new Container { RelativeSizeAxes = Axes.Both }, }; - - components.Add(Body); - components.Add(Ball); - - AddNested(HeadCircle); - - AddNested(TailCircle); - components.Add(TailCircle); - - foreach (var tick in s.NestedHitObjects.OfType()) - { - var drawableTick = new DrawableSliderTick(tick) { Position = tick.Position - s.Position }; - - ticks.Add(drawableTick); - components.Add(drawableTick); - AddNested(drawableTick); - } - - foreach (var repeatPoint in s.NestedHitObjects.OfType()) - { - var drawableRepeatPoint = new DrawableRepeatPoint(repeatPoint, this) { Position = repeatPoint.Position - s.Position }; - - repeatPoints.Add(drawableRepeatPoint); - components.Add(drawableRepeatPoint); - AddNested(drawableRepeatPoint); - } } [BackgroundDependencyLoader] @@ -122,6 +93,60 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, true); } + protected override void AddNested(DrawableHitObject h) + { + base.AddNested(h); + + switch (h) + { + case DrawableSliderHead head: + headContainer.Child = HeadCircle = head; + break; + + case DrawableSliderTail tail: + tailContainer.Child = TailCircle = tail; + break; + + case DrawableSliderTick tick: + tickContainer.Add(tick); + break; + + case DrawableRepeatPoint repeat: + repeatContainer.Add(repeat); + break; + } + } + + protected override void ClearNested() + { + base.ClearNested(); + + headContainer.Clear(); + tailContainer.Clear(); + repeatContainer.Clear(); + tickContainer.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case SliderTailCircle tail: + return new DrawableSliderTail(slider, tail); + + case HitCircle head: + return new DrawableSliderHead(slider, head) { OnShake = Shake }; + + case SliderTick tick: + return new DrawableSliderTick(tick) { Position = tick.Position - slider.Position }; + + case RepeatPoint repeat: + return new DrawableRepeatPoint(repeat, this) { Position = repeat.Position - slider.Position }; + } + + return base.CreateNested(hitObject); + } + protected override void UpdateInitialTransforms() { base.UpdateInitialTransforms(); @@ -139,9 +164,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); - foreach (var c in components.OfType()) c.UpdateProgress(completionProgress); - foreach (var c in components.OfType()) c.UpdateSnakingPosition(slider.Path.PositionAt(Body.SnakedStart ?? 0), slider.Path.PositionAt(Body.SnakedEnd ?? 0)); - foreach (var t in components.OfType()) t.Tracking = Ball.Tracking; + Ball.UpdateProgress(completionProgress); + Body.UpdateProgress(completionProgress); + + foreach (DrawableHitObject hitObject in NestedHitObjects) + { + if (hitObject is ITrackSnaking s) s.UpdateSnakingPosition(slider.Path.PositionAt(Body.SnakedStart ?? 0), slider.Path.PositionAt(Body.SnakedEnd ?? 0)); + if (hitObject is IRequireTracking t) t.Tracking = Ball.Tracking; + } Size = Body.Size; OriginPosition = Body.PathOffset; @@ -187,7 +217,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ApplyResult(r => { - var judgementsCount = NestedHitObjects.Count(); + var judgementsCount = NestedHitObjects.Count; var judgementsHit = NestedHitObjects.Count(h => h.IsHit); var hitFraction = (double)judgementsHit / judgementsCount; @@ -228,7 +258,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - public Drawable ProxiedLayer => HeadCircle.ApproachCircle; + public Drawable ProxiedLayer => new Container(); // Todo: public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Body.ReceivePositionalInputAt(screenSpacePos); } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 7f3bfd3b5c..6bc2ccb889 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Objects.Drawables protected virtual IEnumerable GetSamples() => HitObject.Samples; private readonly Lazy> nestedHitObjects = new Lazy>(); - public IEnumerable NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : Enumerable.Empty(); + public IReadOnlyList NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : (IReadOnlyList)Array.Empty(); /// /// Invoked when a has been applied by this or a nested . @@ -125,6 +125,8 @@ namespace osu.Game.Rulesets.Objects.Drawables { base.LoadComplete(); + Apply(HitObject); + if (HitObject is IHasComboInformation combo) { comboIndexBindable = combo.ComboIndexBindable.GetBoundCopy(); @@ -134,6 +136,37 @@ namespace osu.Game.Rulesets.Objects.Drawables updateState(ArmedState.Idle, true); } + protected void Apply(HitObject hitObject) + { + if (nestedHitObjects.IsValueCreated) + { + nestedHitObjects.Value.Clear(); + ClearNested(); + } + + foreach (var h in hitObject.NestedHitObjects) + { + var drawableNested = CreateNested(h) ?? throw new InvalidOperationException($"{nameof(CreateNested)} returned null for {h.GetType().ReadableName()}."); + + drawableNested.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); + drawableNested.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); + drawableNested.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); + + nestedHitObjects.Value.Add(drawableNested); + AddNested(drawableNested); + } + } + + protected virtual void AddNested(DrawableHitObject h) + { + } + + protected virtual void ClearNested() + { + } + + protected virtual DrawableHitObject CreateNested(HitObject hitObject) => null; + #region State / Transform Management /// @@ -356,15 +389,6 @@ namespace osu.Game.Rulesets.Objects.Drawables UpdateResult(false); } - protected virtual void AddNested(DrawableHitObject h) - { - h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); - h.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); - h.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); - - nestedHitObjects.Value.Add(h); - } - /// /// Applies the of this , notifying responders such as /// the of the . From 326abc1a55be865f4facf10766f5fe89a6a6864b Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Wed, 16 Oct 2019 20:11:25 +0700 Subject: [PATCH 3488/5608] Apply reviews --- osu.Game/Overlays/MusicController.cs | 30 ++++++++++++++++------------ 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 12de2019cb..812c4778dd 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -137,26 +137,21 @@ namespace osu.Game.Overlays return true; } - private PreviousButtonAction? prevAction; - /// /// Play the previous track or restart the current track if it's current time below /// /// Whether the operation was successful. - public bool PrevTrack() + public PreviousButtonAction PrevTrack() { var currentTrackPosition = current?.Track.CurrentTime; if (currentTrackPosition >= restart_cutoff_point) { SeekTo(0); - prevAction = PreviousButtonAction.Restart; - - return true; + return PreviousButtonAction.Restart; } queuedDirection = TrackChangeDirection.Prev; - prevAction = PreviousButtonAction.Previous; var playable = BeatmapSets.TakeWhile(i => i.ID != current.BeatmapSetInfo.ID).LastOrDefault() ?? BeatmapSets.LastOrDefault(); @@ -166,10 +161,10 @@ namespace osu.Game.Overlays working.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); beatmap.Value.Track.Restart(); - return true; + return PreviousButtonAction.Previous; } - return false; + return PreviousButtonAction.None; } /// @@ -275,10 +270,19 @@ namespace osu.Game.Overlays return true; case GlobalAction.MusicPrev: - if (PrevTrack()) - onScreenDisplay?.Display(new MusicControllerToast(prevAction == PreviousButtonAction.Restart ? "Restart track" : "Previous track")); + switch (PrevTrack()) + { + case PreviousButtonAction.Restart: + onScreenDisplay?.Display(new MusicControllerToast("Restart track")); + return true; - return true; + case PreviousButtonAction.Previous: + onScreenDisplay?.Display(new MusicControllerToast("Previous track")); + return true; + + default: + return false; + } } return false; @@ -302,7 +306,7 @@ namespace osu.Game.Overlays Prev } - internal enum PreviousButtonAction + public enum PreviousButtonAction { None, Restart, From 405ab07800b204b9cf3b882dfc978378eee1f72c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 17 Oct 2019 01:18:29 +0300 Subject: [PATCH 3489/5608] Check equality by ID -> OnlineBeatmapSetID -> Hash -> ReferenceEquals --- osu.Game/Beatmaps/BeatmapSetInfo.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 90346a8c8b..a8b83dca38 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -65,10 +65,19 @@ namespace osu.Game.Beatmaps public bool Equals(BeatmapSetInfo other) { - if (!OnlineBeatmapSetID.HasValue || !(other?.OnlineBeatmapSetID.HasValue ?? false)) - return ReferenceEquals(this, other); + if (other == null) + return false; - return OnlineBeatmapSetID == other.OnlineBeatmapSetID; + if (ID != 0 && other.ID != 0) + return ID == other.ID; + + if (OnlineBeatmapSetID.HasValue && other.OnlineBeatmapSetID.HasValue) + return OnlineBeatmapSetID == other.OnlineBeatmapSetID; + + if (!string.IsNullOrEmpty(Hash) && !string.IsNullOrEmpty(other.Hash)) + return Hash == other.Hash; + + return ReferenceEquals(this, other); } } } From 40fc655b50244d0b0d588abb1b97f3ae9cbde831 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 17 Oct 2019 01:19:50 +0300 Subject: [PATCH 3490/5608] Add equality check test to ensure correct values --- .../NonVisual/BeatmapSetInfoEqualityTest.cs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs diff --git a/osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs b/osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs new file mode 100644 index 0000000000..42a3b4cf43 --- /dev/null +++ b/osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs @@ -0,0 +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 NUnit.Framework; +using osu.Game.Beatmaps; + +namespace osu.Game.Tests.NonVisual +{ + [TestFixture] + public class BeatmapSetInfoEqualityTest + { + [Test] + public void TestOnlineWithOnline() + { + var ourInfo = new BeatmapSetInfo { OnlineBeatmapSetID = 123 }; + var otherInfo = new BeatmapSetInfo { OnlineBeatmapSetID = 123 }; + + Assert.AreEqual(ourInfo, otherInfo); + } + + [Test] + public void TestDatabasedWithDatabased() + { + var ourInfo = new BeatmapSetInfo { ID = 123 }; + var otherInfo = new BeatmapSetInfo { ID = 123 }; + + Assert.AreEqual(ourInfo, otherInfo); + } + + [Test] + public void TestDatabasedWithOnline() + { + var ourInfo = new BeatmapSetInfo { ID = 123, OnlineBeatmapSetID = 12 }; + var otherInfo = new BeatmapSetInfo { OnlineBeatmapSetID = 12 }; + + Assert.AreEqual(ourInfo, otherInfo); + } + + [Test] + public void TestCheckNullID() + { + var ourInfo = new BeatmapSetInfo { Status = BeatmapSetOnlineStatus.Loved }; + var otherInfo = new BeatmapSetInfo { Status = BeatmapSetOnlineStatus.Approved }; + + Assert.AreNotEqual(ourInfo, otherInfo); + } + } +} From 9b9138253c13ba60fbb16f1735b1749722e7324a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 11:27:23 +0900 Subject: [PATCH 3491/5608] Remove finalizer --- osu.Game/Rulesets/RulesetStore.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 0e6e0b8676..23988ff0ff 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -165,11 +165,6 @@ namespace osu.Game.Rulesets } } - ~RulesetStore() - { - Dispose(false); - } - public void Dispose() { Dispose(true); From d49ef6a36bac0a60364f42a3ff7daab2c72e0fc0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 11:57:00 +0900 Subject: [PATCH 3492/5608] Make taiko use the new nested hitobject structure --- .../Objects/Drawables/DrawableDrumRoll.cs | 69 ++++++++++++++----- .../Objects/Drawables/DrawableSwell.cs | 56 +++++++++++---- .../Drawables/DrawableTaikoHitObject.cs | 39 ++++++++--- 3 files changed, 124 insertions(+), 40 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 8e16a21199..d98043b1b7 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -28,31 +29,18 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// private int rollingHits; + private readonly Container tickContainer; + + private Color4 colourIdle; + private Color4 colourEngaged; + public DrawableDrumRoll(DrumRoll drumRoll) : base(drumRoll) { RelativeSizeAxes = Axes.Y; - - Container tickContainer; MainPiece.Add(tickContainer = new Container { RelativeSizeAxes = Axes.Both }); - - foreach (var tick in drumRoll.NestedHitObjects.OfType()) - { - var newTick = new DrawableDrumRollTick(tick); - newTick.OnNewResult += onNewTickResult; - - AddNested(newTick); - tickContainer.Add(newTick); - } } - protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece(); - - public override bool OnPressed(TaikoAction action) => false; - - private Color4 colourIdle; - private Color4 colourEngaged; - [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -60,8 +48,51 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables colourEngaged = colours.YellowDarker; } - private void onNewTickResult(DrawableHitObject obj, JudgementResult result) + protected override void LoadComplete() { + base.LoadComplete(); + + OnNewResult += onNewResult; + } + + protected override void AddNested(DrawableHitObject h) + { + base.AddNested(h); + + switch (h) + { + case DrawableDrumRollTick tick: + tickContainer.Add(tick); + break; + } + } + + protected override void ClearNested() + { + base.ClearNested(); + tickContainer.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case DrumRollTick tick: + return new DrawableDrumRollTick(tick); + } + + return base.CreateNested(hitObject); + } + + protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece(); + + public override bool OnPressed(TaikoAction action) => false; + + private void onNewResult(DrawableHitObject obj, JudgementResult result) + { + if (!(obj is DrawableDrumRollTick)) + return; + if (result.Type > HitResult.Miss) rollingHits++; else diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 07af7fe7e0..164944f00a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -14,6 +13,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -30,8 +30,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// private const double ring_appear_offset = 100; - private readonly List ticks = new List(); - + private readonly Container ticks; private readonly Container bodyContainer; private readonly CircularContainer targetRing; private readonly CircularContainer expandingRing; @@ -108,16 +107,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } }); + AddInternal(ticks = new Container { RelativeSizeAxes = Axes.Both }); + MainPiece.Add(symbol = new SwellSymbolPiece()); - - foreach (var tick in HitObject.NestedHitObjects.OfType()) - { - var vis = new DrawableSwellTick(tick); - - ticks.Add(vis); - AddInternal(vis); - AddNested(vis); - } } [BackgroundDependencyLoader] @@ -136,11 +128,49 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Width *= Parent.RelativeChildSize.X; } + protected override void AddNested(DrawableHitObject h) + { + base.AddNested(h); + + switch (h) + { + case DrawableSwellTick tick: + ticks.Add(tick); + break; + } + } + + protected override void ClearNested() + { + base.ClearNested(); + ticks.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case SwellTick tick: + return new DrawableSwellTick(tick); + } + + return base.CreateNested(hitObject); + } + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (userTriggered) { - var nextTick = ticks.Find(j => !j.IsHit); + DrawableSwellTick nextTick = null; + + foreach (var t in ticks) + { + if (!t.IsHit) + { + nextTick = t; + break; + } + } nextTick?.TriggerResult(HitResult.Great); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 423f65b2d3..b89cd7c09f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -11,6 +11,7 @@ using osu.Game.Audio; using System.Collections.Generic; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { @@ -109,11 +110,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); - protected readonly Vector2 BaseSize; + public new TaikoHitType HitObject; + protected readonly Vector2 BaseSize; protected readonly TaikoPiece MainPiece; - public new TaikoHitType HitObject; + private readonly Container strongHitContainer; protected DrawableTaikoHitObject(TaikoHitType hitObject) : base(hitObject) @@ -129,17 +131,38 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Content.Add(MainPiece = CreateMainPiece()); MainPiece.KiaiMode = HitObject.Kiai; - var strongObject = HitObject.NestedHitObjects.OfType().FirstOrDefault(); + AddInternal(strongHitContainer = new Container()); + } - if (strongObject != null) + protected override void AddNested(DrawableHitObject h) + { + base.AddNested(h); + + switch (h) { - var strongHit = CreateStrongHit(strongObject); - - AddNested(strongHit); - AddInternal(strongHit); + case DrawableStrongNestedHit strong: + strongHitContainer.Add(strong); + break; } } + protected override void ClearNested() + { + base.ClearNested(); + strongHitContainer.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case StrongHitObject strong: + return CreateStrongHit(strong); + } + + return base.CreateNested(hitObject); + } + // Normal and clap samples are handled by the drum protected override IEnumerable GetSamples() => HitObject.Samples.Where(s => s.Name != HitSampleInfo.HIT_NORMAL && s.Name != HitSampleInfo.HIT_CLAP); From 1a0dfcdd4601ec2eff43eebf4ebee20e14570405 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 12:37:09 +0900 Subject: [PATCH 3493/5608] Make catch use the new nested hitobject structure --- .../Objects/Drawable/DrawableBananaShower.cs | 27 +++++++++++++---- .../Objects/Drawable/DrawableJuiceStream.cs | 30 +++++++++++++------ 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index 42646851d7..57ffd23e85 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -2,35 +2,50 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Catch.Objects.Drawable { public class DrawableBananaShower : DrawableCatchHitObject { + private readonly Func> createDrawableRepresentation; private readonly Container bananaContainer; public DrawableBananaShower(BananaShower s, Func> createDrawableRepresentation = null) : base(s) { + this.createDrawableRepresentation = createDrawableRepresentation; RelativeSizeAxes = Axes.X; Origin = Anchor.BottomLeft; X = 0; AddInternal(bananaContainer = new Container { RelativeSizeAxes = Axes.Both }); - - foreach (var b in s.NestedHitObjects.Cast()) - AddNested(createDrawableRepresentation?.Invoke(b)); } protected override void AddNested(DrawableHitObject h) { - ((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; - bananaContainer.Add(h); base.AddNested(h); + bananaContainer.Add(h); + } + + protected override void ClearNested() + { + base.ClearNested(); + bananaContainer.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case Banana banana: + return createDrawableRepresentation?.Invoke(banana)?.With(o => ((DrawableCatchHitObject)o).CheckPosition = p => CheckPosition?.Invoke(p) ?? false); + } + + return base.CreateNested(hitObject); } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index 9e5e9f6a04..1bbb7b08a5 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -2,38 +2,50 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Catch.Objects.Drawable { public class DrawableJuiceStream : DrawableCatchHitObject { + private readonly Func> createDrawableRepresentation; private readonly Container dropletContainer; public DrawableJuiceStream(JuiceStream s, Func> createDrawableRepresentation = null) : base(s) { + this.createDrawableRepresentation = createDrawableRepresentation; RelativeSizeAxes = Axes.Both; Origin = Anchor.BottomLeft; X = 0; AddInternal(dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }); - - foreach (var o in s.NestedHitObjects.Cast()) - AddNested(createDrawableRepresentation?.Invoke(o)); } protected override void AddNested(DrawableHitObject h) { - var catchObject = (DrawableCatchHitObject)h; - - catchObject.CheckPosition = o => CheckPosition?.Invoke(o) ?? false; - - dropletContainer.Add(h); base.AddNested(h); + dropletContainer.Add(h); + } + + protected override void ClearNested() + { + base.ClearNested(); + dropletContainer.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case CatchHitObject catchObject: + return createDrawableRepresentation?.Invoke(catchObject)?.With(o => ((DrawableCatchHitObject)o).CheckPosition = p => CheckPosition?.Invoke(p) ?? false); + } + + return base.CreateNested(hitObject); } } } From 8a284bacba34ed8a4a5759e89a237df19fea4087 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 12:37:20 +0900 Subject: [PATCH 3494/5608] Make mania use the new nested hitobject structure --- .../Objects/Drawables/DrawableHoldNote.cs | 106 ++++++++++++------ 1 file changed, 70 insertions(+), 36 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index c5c157608f..78969b7361 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -2,13 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System.Diagnostics; -using System.Linq; using osu.Framework.Bindables; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; @@ -22,8 +21,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { public override bool DisplayResult => false; - public readonly DrawableNote Head; - public readonly DrawableNote Tail; + private readonly Container headContainer; + private readonly Container tailContainer; + private readonly Container tickContainer; + + public DrawableNote Head { get; private set; } + public DrawableNote Tail { get; private set; } private readonly BodyPiece bodyPiece; @@ -40,50 +43,81 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public DrawableHoldNote(HoldNote hitObject) : base(hitObject) { - Container tickContainer; RelativeSizeAxes = Axes.X; AddRangeInternal(new Drawable[] { - bodyPiece = new BodyPiece - { - RelativeSizeAxes = Axes.X, - }, - tickContainer = new Container - { - RelativeSizeAxes = Axes.Both, - ChildrenEnumerable = HitObject.NestedHitObjects.OfType().Select(tick => new DrawableHoldNoteTick(tick) - { - HoldStartTime = () => holdStartTime - }) - }, - Head = new DrawableHeadNote(this) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - }, - Tail = new DrawableTailNote(this) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - } + bodyPiece = new BodyPiece { RelativeSizeAxes = Axes.X }, + tickContainer = new Container { RelativeSizeAxes = Axes.Both }, + headContainer = new Container { RelativeSizeAxes = Axes.Both }, + tailContainer = new Container { RelativeSizeAxes = Axes.Both }, }); - foreach (var tick in tickContainer) - AddNested(tick); - - AddNested(Head); - AddNested(Tail); - AccentColour.BindValueChanged(colour => { bodyPiece.AccentColour = colour.NewValue; - Head.AccentColour.Value = colour.NewValue; - Tail.AccentColour.Value = colour.NewValue; - tickContainer.ForEach(t => t.AccentColour.Value = colour.NewValue); }, true); } + protected override void AddNested(DrawableHitObject h) + { + base.AddNested(h); + + switch (h) + { + case DrawableHeadNote head: + headContainer.Child = head; + break; + + case DrawableTailNote tail: + tailContainer.Child = tail; + break; + + case DrawableHoldNoteTick tick: + tickContainer.Add(tick); + break; + } + } + + protected override void ClearNested() + { + base.ClearNested(); + headContainer.Clear(); + tailContainer.Clear(); + tickContainer.Clear(); + } + + protected override DrawableHitObject CreateNested(HitObject hitObject) + { + switch (hitObject) + { + case TailNote _: + return Tail = new DrawableTailNote(this) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AccentColour = { BindTarget = AccentColour } + }; + + case Note _: + return Head = new DrawableHeadNote(this) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AccentColour = { BindTarget = AccentColour } + }; + + case HoldNoteTick tick: + return new DrawableHoldNoteTick(tick) + { + HoldStartTime = () => holdStartTime, + AccentColour = { BindTarget = AccentColour } + }; + } + + return base.CreateNested(hitObject); + } + protected override void OnDirectionChanged(ValueChangedEvent e) { base.OnDirectionChanged(e); From 3a1acf7b0aab924aa9b48ef341ea2518d9ec3b92 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 12:50:22 +0900 Subject: [PATCH 3495/5608] Fix slider approach circle proxies --- .../Objects/Drawables/DrawableSlider.cs | 2 +- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 21411259ae..6ab14cb036 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -258,7 +258,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - public Drawable ProxiedLayer => new Container(); // Todo: + public Drawable ProxiedLayer => HeadCircle.ProxiedLayer; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Body.ReceivePositionalInputAt(screenSpacePos); } diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index d1757de445..69e53d6eea 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -57,21 +57,15 @@ namespace osu.Game.Rulesets.Osu.UI public override void Add(DrawableHitObject h) { h.OnNewResult += onNewResult; - - if (h is IDrawableHitObjectWithProxiedApproach c) + h.OnLoadComplete += d => { - var original = c.ProxiedLayer; - - // Hitobjects only have lifetimes set on LoadComplete. For nested hitobjects (e.g. SliderHeads), this only happens when the parenting slider becomes visible. - // This delegation is required to make sure that the approach circles for those not-yet-loaded objects aren't added prematurely. - original.OnLoadComplete += addApproachCircleProxy; - } + if (d is IDrawableHitObjectWithProxiedApproach c) + approachCircles.Add(c.ProxiedLayer.CreateProxy()); + }; base.Add(h); } - private void addApproachCircleProxy(Drawable d) => approachCircles.Add(d.CreateProxy()); - public override void PostProcess() { connectionLayer.HitObjects = HitObjectContainer.Objects.Select(d => d.HitObject).OfType(); From d8f3678c3cadbdc02adf3db8d79796b39c646b4c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 12:53:54 +0900 Subject: [PATCH 3496/5608] Rename parameter --- .../Objects/Drawable/DrawableBananaShower.cs | 6 +++--- .../Objects/Drawable/DrawableJuiceStream.cs | 6 +++--- .../Objects/Drawables/DrawableHoldNote.cs | 6 +++--- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 6 +++--- .../Objects/Drawables/DrawableDrumRoll.cs | 6 +++--- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs | 6 +++--- .../Objects/Drawables/DrawableTaikoHitObject.cs | 6 +++--- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index 57ffd23e85..f46abea68f 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -25,10 +25,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable AddInternal(bananaContainer = new Container { RelativeSizeAxes = Axes.Both }); } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); - bananaContainer.Add(h); + base.AddNested(hitObject); + bananaContainer.Add(hitObject); } protected override void ClearNested() diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index 1bbb7b08a5..7af3f49267 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -25,10 +25,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable AddInternal(dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }); } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); - dropletContainer.Add(h); + base.AddNested(hitObject); + dropletContainer.Add(hitObject); } protected override void ClearNested() diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 78969b7361..2d4f90876e 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -59,11 +59,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }, true); } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); + base.AddNested(hitObject); - switch (h) + switch (hitObject) { case DrawableHeadNote head: headContainer.Child = head; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 6ab14cb036..b937fd346f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -93,11 +93,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, true); } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); + base.AddNested(hitObject); - switch (h) + switch (hitObject) { case DrawableSliderHead head: headContainer.Child = HeadCircle = head; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index d98043b1b7..b212c81020 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -55,11 +55,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables OnNewResult += onNewResult; } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); + base.AddNested(hitObject); - switch (h) + switch (hitObject) { case DrawableDrumRollTick tick: tickContainer.Add(tick); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 164944f00a..162c8f4810 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -128,11 +128,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Width *= Parent.RelativeChildSize.X; } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); + base.AddNested(hitObject); - switch (h) + switch (hitObject) { case DrawableSwellTick tick: ticks.Add(tick); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index b89cd7c09f..ddc29f1de6 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -134,11 +134,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables AddInternal(strongHitContainer = new Container()); } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject hitObject) { - base.AddNested(h); + base.AddNested(hitObject); - switch (h) + switch (hitObject) { case DrawableStrongNestedHit strong: strongHitContainer.Add(strong); diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 6bc2ccb889..424776f61b 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -157,7 +157,7 @@ namespace osu.Game.Rulesets.Objects.Drawables } } - protected virtual void AddNested(DrawableHitObject h) + protected virtual void AddNested(DrawableHitObject hitObject) { } From f429a8f7c272b4849898cec0716257ec50c70d2c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 13:52:21 +0900 Subject: [PATCH 3497/5608] Add back/obsolete old AddNested() method --- .../Objects/Drawable/DrawableBananaShower.cs | 12 ++--- .../Objects/Drawable/DrawableJuiceStream.cs | 12 ++--- .../Objects/Drawables/DrawableHoldNote.cs | 12 ++--- .../Objects/Drawables/DrawableSlider.cs | 12 ++--- .../Objects/Drawables/DrawableDrumRoll.cs | 12 ++--- .../Objects/Drawables/DrawableSwell.cs | 12 ++--- .../Drawables/DrawableTaikoHitObject.cs | 12 ++--- .../Objects/Drawables/DrawableHitObject.cs | 44 ++++++++++++++++--- 8 files changed, 80 insertions(+), 48 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index f46abea68f..ea415e18fa 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -25,19 +25,19 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable AddInternal(bananaContainer = new Container { RelativeSizeAxes = Axes.Both }); } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); bananaContainer.Add(hitObject); } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); bananaContainer.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable return createDrawableRepresentation?.Invoke(banana)?.With(o => ((DrawableCatchHitObject)o).CheckPosition = p => CheckPosition?.Invoke(p) ?? false); } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index 7af3f49267..a24821b3ce 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -25,19 +25,19 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable AddInternal(dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }); } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); dropletContainer.Add(hitObject); } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); dropletContainer.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable return createDrawableRepresentation?.Invoke(catchObject)?.With(o => ((DrawableCatchHitObject)o).CheckPosition = p => CheckPosition?.Invoke(p) ?? false); } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 2d4f90876e..78d49c217e 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -59,9 +59,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }, true); } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); switch (hitObject) { @@ -79,15 +79,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); headContainer.Clear(); tailContainer.Clear(); tickContainer.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -115,7 +115,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }; } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } protected override void OnDirectionChanged(ValueChangedEvent e) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index b937fd346f..f057c67efe 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -93,9 +93,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, true); } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); switch (hitObject) { @@ -117,9 +117,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); headContainer.Clear(); tailContainer.Clear(); @@ -127,7 +127,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables tickContainer.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -144,7 +144,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return new DrawableRepeatPoint(repeat, this) { Position = repeat.Position - slider.Position }; } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } protected override void UpdateInitialTransforms() diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index b212c81020..cc0d6829ba 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -55,9 +55,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables OnNewResult += onNewResult; } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); switch (hitObject) { @@ -67,13 +67,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); tickContainer.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return new DrawableDrumRollTick(tick); } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece(); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 162c8f4810..9c9dfc5f9e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -128,9 +128,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Width *= Parent.RelativeChildSize.X; } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); switch (hitObject) { @@ -140,13 +140,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); ticks.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -154,7 +154,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return new DrawableSwellTick(tick); } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index ddc29f1de6..0db6498c12 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -134,9 +134,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables AddInternal(strongHitContainer = new Container()); } - protected override void AddNested(DrawableHitObject hitObject) + protected override void AddNestedHitObject(DrawableHitObject hitObject) { - base.AddNested(hitObject); + base.AddNestedHitObject(hitObject); switch (hitObject) { @@ -146,13 +146,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override void ClearNested() + protected override void ClearNestedHitObjects() { - base.ClearNested(); + base.ClearNestedHitObjects(); strongHitContainer.Clear(); } - protected override DrawableHitObject CreateNested(HitObject hitObject) + protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) { switch (hitObject) { @@ -160,7 +160,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return CreateStrongHit(strong); } - return base.CreateNested(hitObject); + return base.CreateNestedHitObject(hitObject); } // Normal and clap samples are handled by the drum diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 424776f61b..99b0c07570 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; @@ -138,34 +139,65 @@ namespace osu.Game.Rulesets.Objects.Drawables protected void Apply(HitObject hitObject) { +#pragma warning disable 618 // can be removed 20200417 + if (GetType().GetMethod(nameof(AddNested), BindingFlags.NonPublic | BindingFlags.Instance)?.DeclaringType != typeof(DrawableHitObject)) + return; +#pragma warning restore 618 + if (nestedHitObjects.IsValueCreated) { nestedHitObjects.Value.Clear(); - ClearNested(); + ClearNestedHitObjects(); } foreach (var h in hitObject.NestedHitObjects) { - var drawableNested = CreateNested(h) ?? throw new InvalidOperationException($"{nameof(CreateNested)} returned null for {h.GetType().ReadableName()}."); + var drawableNested = CreateNestedHitObject(h) ?? throw new InvalidOperationException($"{nameof(CreateNestedHitObject)} returned null for {h.GetType().ReadableName()}."); drawableNested.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); drawableNested.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); drawableNested.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); nestedHitObjects.Value.Add(drawableNested); - AddNested(drawableNested); + AddNestedHitObject(drawableNested); } } - protected virtual void AddNested(DrawableHitObject hitObject) + /// + /// Invoked by the base to add nested s to the hierarchy. + /// + /// The to be added. + protected virtual void AddNestedHitObject(DrawableHitObject hitObject) { } - protected virtual void ClearNested() + /// + /// Adds a nested . This should not be used except for legacy nested usages. + /// + /// + [Obsolete("Use AddNestedHitObject() / ClearNestedHitObjects() / CreateNestedHitObject() instead.")] // can be removed 20200417 + protected virtual void AddNested(DrawableHitObject h) + { + h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); + h.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); + h.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); + + nestedHitObjects.Value.Add(h); + } + + /// + /// Invoked by the base to remove all previously-added nested s. + /// + protected virtual void ClearNestedHitObjects() { } - protected virtual DrawableHitObject CreateNested(HitObject hitObject) => null; + /// + /// Creates the drawable representation for a nested . + /// + /// The . + /// The drawable representation for . + protected virtual DrawableHitObject CreateNestedHitObject(HitObject hitObject) => null; #region State / Transform Management From bc41eb176ee6ad63a153d7ba82e1a8a17d13c0c0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 14:02:23 +0900 Subject: [PATCH 3498/5608] Clean up head/tail setting in various DHOs --- .../Objects/Drawables/DrawableHoldNote.cs | 10 +++++----- .../Objects/Drawables/DrawableSlider.cs | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 78d49c217e..87b9633c80 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -21,13 +21,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { public override bool DisplayResult => false; + public DrawableNote Head => headContainer.Child; + public DrawableNote Tail => tailContainer.Child; + private readonly Container headContainer; private readonly Container tailContainer; private readonly Container tickContainer; - public DrawableNote Head { get; private set; } - public DrawableNote Tail { get; private set; } - private readonly BodyPiece bodyPiece; /// @@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables switch (hitObject) { case TailNote _: - return Tail = new DrawableTailNote(this) + return new DrawableTailNote(this) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -100,7 +100,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }; case Note _: - return Head = new DrawableHeadNote(this) + return new DrawableHeadNote(this) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index f057c67efe..6d45bb9ac4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -20,8 +20,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSlider : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { - public DrawableSliderHead HeadCircle { get; private set; } - public DrawableSliderTail TailCircle { get; private set; } + public DrawableSliderHead HeadCircle => headContainer.Child; + public DrawableSliderTail TailCircle => tailContainer.Child; public readonly SnakingSliderBody Body; public readonly SliderBall Ball; @@ -100,11 +100,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables switch (hitObject) { case DrawableSliderHead head: - headContainer.Child = HeadCircle = head; + headContainer.Child = head; break; case DrawableSliderTail tail: - tailContainer.Child = TailCircle = tail; + tailContainer.Child = tail; break; case DrawableSliderTick tick: From f92331531c6e183a4644a423d20b6e9df17df2cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 17 Oct 2019 15:32:02 +0900 Subject: [PATCH 3499/5608] Rename grid to DistanceSnap to be more in line with its purpose --- ...SnapGrid.cs => TestSceneOsuDistanceSnapGrid.cs} | 12 ++++++------ .../{OsuBeatSnapGrid.cs => OsuDistanceSnapGrid.cs} | 4 ++-- ...eatSnapGrid.cs => TestSceneDistanceSnapGrid.cs} | 14 +++++++------- ...BeatSnapGrid.cs => CircularDistanceSnapGrid.cs} | 4 ++-- .../{BeatSnapGrid.cs => DistanceSnapGrid.cs} | 13 ++++++++----- 5 files changed, 25 insertions(+), 22 deletions(-) rename osu.Game.Rulesets.Osu.Tests/{TestSceneOsuBeatSnapGrid.cs => TestSceneOsuDistanceSnapGrid.cs} (94%) rename osu.Game.Rulesets.Osu/Edit/{OsuBeatSnapGrid.cs => OsuDistanceSnapGrid.cs} (90%) rename osu.Game.Tests/Visual/Editor/{TestSceneBeatSnapGrid.cs => TestSceneDistanceSnapGrid.cs} (93%) rename osu.Game/Screens/Edit/Compose/Components/{CircularBeatSnapGrid.cs => CircularDistanceSnapGrid.cs} (92%) rename osu.Game/Screens/Edit/Compose/Components/{BeatSnapGrid.cs => DistanceSnapGrid.cs} (92%) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs similarity index 94% rename from osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs rename to osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index 7399f12372..da7708081b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -20,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneOsuBeatSnapGrid : ManualInputManagerTestScene + public class TestSceneOsuDistanceSnapGrid : ManualInputManagerTestScene { private const double beat_length = 100; private static readonly Vector2 grid_position = new Vector2(512, 384); @@ -31,9 +31,9 @@ namespace osu.Game.Rulesets.Osu.Tests [Cached] private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); - private TestOsuBeatSnapGrid grid; + private TestOsuDistanceSnapGrid grid; - public TestSceneOsuBeatSnapGrid() + public TestSceneOsuDistanceSnapGrid() { editorBeatmap = new EditorBeatmap(new OsuBeatmap()); @@ -152,7 +152,7 @@ namespace osu.Game.Rulesets.Osu.Tests RelativeSizeAxes = Axes.Both, Colour = Color4.SlateGray }, - grid = new TestOsuBeatSnapGrid(new HitCircle { Position = grid_position }), + grid = new TestOsuDistanceSnapGrid(new HitCircle { Position = grid_position }), new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnapPosition(grid.ToLocalSpace(v)) } }; }); @@ -197,11 +197,11 @@ namespace osu.Game.Rulesets.Osu.Tests } } - private class TestOsuBeatSnapGrid : OsuBeatSnapGrid + private class TestOsuDistanceSnapGrid : OsuDistanceSnapGrid { public new float DistanceSpacing => base.DistanceSpacing; - public TestOsuBeatSnapGrid(OsuHitObject hitObject) + public TestOsuDistanceSnapGrid(OsuHitObject hitObject) : base(hitObject) { } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBeatSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs similarity index 90% rename from osu.Game.Rulesets.Osu/Edit/OsuBeatSnapGrid.cs rename to osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs index d453e3d062..558993f8b2 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs @@ -8,14 +8,14 @@ using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Osu.Edit { - public class OsuBeatSnapGrid : CircularBeatSnapGrid + public class OsuDistanceSnapGrid : CircularDistanceSnapGrid { /// /// Scoring distance with a speed-adjusted beat length of 1 second. /// private const float base_scoring_distance = 100; - public OsuBeatSnapGrid(OsuHitObject hitObject) + public OsuDistanceSnapGrid(OsuHitObject hitObject) : base(hitObject, hitObject.StackedEndPosition) { } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs similarity index 93% rename from osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs rename to osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index 073cec7315..a9e5930478 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneBeatSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Editor { - public class TestSceneBeatSnapGrid : EditorClockTestScene + public class TestSceneDistanceSnapGrid : EditorClockTestScene { private const double beat_length = 100; private static readonly Vector2 grid_position = new Vector2(512, 384); @@ -27,9 +27,9 @@ namespace osu.Game.Tests.Visual.Editor [Cached(typeof(IEditorBeatmap))] private readonly EditorBeatmap editorBeatmap; - private TestBeatSnapGrid grid; + private TestDistanceSnapGrid grid; - public TestSceneBeatSnapGrid() + public TestSceneDistanceSnapGrid() { editorBeatmap = new EditorBeatmap(new OsuBeatmap()); editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); @@ -112,7 +112,7 @@ namespace osu.Game.Tests.Visual.Editor AddAssert("snap time is now 0.5 beats away", () => Precision.AlmostEquals(beat_length / 2, grid.GetSnapTime(snapPosition), 0.01)); } - private void createGrid(Action func = null, string description = null) + private void createGrid(Action func = null, string description = null) { AddStep($"create grid {description ?? string.Empty}", () => { @@ -123,20 +123,20 @@ namespace osu.Game.Tests.Visual.Editor RelativeSizeAxes = Axes.Both, Colour = Color4.SlateGray }, - grid = new TestBeatSnapGrid(new HitObject(), grid_position) + grid = new TestDistanceSnapGrid(new HitObject(), grid_position) }; func?.Invoke(grid); }); } - private class TestBeatSnapGrid : BeatSnapGrid + private class TestDistanceSnapGrid : DistanceSnapGrid { public new float Velocity = 1; public new float DistanceSpacing => base.DistanceSpacing; - public TestBeatSnapGrid(HitObject hitObject, Vector2 centrePosition) + public TestDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) : base(hitObject, centrePosition) { } diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs similarity index 92% rename from osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs rename to osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 5e378f8393..3cbf926d4f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularBeatSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -9,9 +9,9 @@ using osuTK; namespace osu.Game.Screens.Edit.Compose.Components { - public abstract class CircularBeatSnapGrid : BeatSnapGrid + public abstract class CircularDistanceSnapGrid : DistanceSnapGrid { - protected CircularBeatSnapGrid(HitObject hitObject, Vector2 centrePosition) + protected CircularDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) : base(hitObject, centrePosition) { } diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs similarity index 92% rename from osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs rename to osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 9040843144..299e78b7c0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -15,7 +15,10 @@ using osuTK; namespace osu.Game.Screens.Edit.Compose.Components { - public abstract class BeatSnapGrid : CompositeDrawable + /// + /// A grid which takes user input and returns a quantized ("snapped") position and time. + /// + public abstract class DistanceSnapGrid : CompositeDrawable { /// /// The velocity of the beatmap at the point of placement in pixels per millisecond. @@ -48,7 +51,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private double startTime; private double beatLength; - protected BeatSnapGrid(HitObject hitObject, Vector2 centrePosition) + protected DistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) { this.hitObject = hitObject; this.CentrePosition = centrePosition; @@ -114,14 +117,14 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Snaps a position to this grid. /// - /// The original position in coordinate space local to this . - /// The snapped position in coordinate space local to this . + /// The original position in coordinate space local to this . + /// The snapped position in coordinate space local to this . public abstract Vector2 GetSnapPosition(Vector2 position); /// /// Retrieves the time at a snapped position. /// - /// The snapped position in coordinate space local to this . + /// The snapped position in coordinate space local to this . /// The time at the snapped position. public double GetSnapTime(Vector2 position) => startTime + (position - CentrePosition).Length / Velocity; From 510ce9345f79b3deee4f6ed1fc72e46ebed0ed0e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 16:14:28 +0900 Subject: [PATCH 3500/5608] Fix potential blueprint nullrefs with the new structure --- .../Blueprints/HoldNoteSelectionBlueprint.cs | 32 +++++++++++-------- .../Compose/Components/BlueprintContainer.cs | 18 ++++++++--- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs index d64c5dbc6a..3169a8c036 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs @@ -20,30 +20,36 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints private readonly IBindable direction = new Bindable(); - private readonly BodyPiece body; + [Resolved] + private OsuColour colours { get; set; } public HoldNoteSelectionBlueprint(DrawableHoldNote hold) : base(hold) { - InternalChildren = new Drawable[] - { - new HoldNoteNoteSelectionBlueprint(hold.Head), - new HoldNoteNoteSelectionBlueprint(hold.Tail), - body = new BodyPiece - { - AccentColour = Color4.Transparent - }, - }; } [BackgroundDependencyLoader] - private void load(OsuColour colours, IScrollingInfo scrollingInfo) + private void load(IScrollingInfo scrollingInfo) { - body.BorderColour = colours.Yellow; - direction.BindTo(scrollingInfo.Direction); } + protected override void LoadComplete() + { + base.LoadComplete(); + + InternalChildren = new Drawable[] + { + new HoldNoteNoteSelectionBlueprint(HitObject.Head), + new HoldNoteNoteSelectionBlueprint(HitObject.Tail), + new BodyPiece + { + AccentColour = Color4.Transparent, + BorderColour = colours.Yellow + }, + }; + } + protected override void Update() { base.Update(); diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 2de5ecf633..cb3d3b71fc 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -123,12 +123,20 @@ namespace osu.Game.Screens.Edit.Compose.Components if (blueprint == null) return; - blueprint.Selected += onBlueprintSelected; - blueprint.Deselected += onBlueprintDeselected; - blueprint.SelectionRequested += onSelectionRequested; - blueprint.DragRequested += onDragRequested; + if (hitObject.IsLoaded) + addBlueprint(); + else + hitObject.OnLoadComplete += _ => addBlueprint(); - selectionBlueprints.Add(blueprint); + void addBlueprint() + { + blueprint.Selected += onBlueprintSelected; + blueprint.Deselected += onBlueprintDeselected; + blueprint.SelectionRequested += onSelectionRequested; + blueprint.DragRequested += onDragRequested; + + selectionBlueprints.Add(blueprint); + } } private void removeBlueprintFor(DrawableHitObject hitObject) => removeBlueprintFor(hitObject.HitObject); From f3ed71d3361bd1eb81e23432e457f93c54caa3db Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 17 Oct 2019 16:36:47 +0900 Subject: [PATCH 3501/5608] Move scoring distance constant to a central/shared location --- osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs | 7 +------ osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 8 ++++++++ osu.Game.Rulesets.Osu/Objects/Slider.cs | 7 +------ 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs index 558993f8b2..f701712739 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs @@ -10,11 +10,6 @@ namespace osu.Game.Rulesets.Osu.Edit { public class OsuDistanceSnapGrid : CircularDistanceSnapGrid { - /// - /// Scoring distance with a speed-adjusted beat length of 1 second. - /// - private const float base_scoring_distance = 100; - public OsuDistanceSnapGrid(OsuHitObject hitObject) : base(hitObject, hitObject.StackedEndPosition) { @@ -25,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Edit TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(time); DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(time); - double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier; + double scoringDistance = OsuHitObject.BASE_SCORING_DISTANCE * difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier; return (float)(scoringDistance / timingPoint.BeatLength); } diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 80e013fe68..b506c1f918 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -14,8 +14,16 @@ namespace osu.Game.Rulesets.Osu.Objects { public abstract class OsuHitObject : HitObject, IHasComboInformation, IHasPosition { + /// + /// The radius of hit objects (ie. the radius of a ). + /// public const float OBJECT_RADIUS = 64; + /// + /// Scoring distance with a speed-adjusted beat length of 1 second (ie. the speed slider balls move through their track). + /// + internal const float BASE_SCORING_DISTANCE = 100; + public double TimePreempt = 600; public double TimeFadeIn = 400; diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 9bed123465..d98d72331a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -19,11 +19,6 @@ namespace osu.Game.Rulesets.Osu.Objects { public class Slider : OsuHitObject, IHasCurve { - /// - /// Scoring distance with a speed-adjusted beat length of 1 second. - /// - private const float base_scoring_distance = 100; - public double EndTime => StartTime + this.SpanCount() * Path.Distance / Velocity; public double Duration => EndTime - StartTime; @@ -123,7 +118,7 @@ namespace osu.Game.Rulesets.Osu.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(StartTime); - double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier; + double scoringDistance = BASE_SCORING_DISTANCE * difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier; Velocity = scoringDistance / timingPoint.BeatLength; TickDistance = scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier; From c4cc960e1564944a18964c606b2b64b8f4d927de Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 17 Oct 2019 18:00:15 +0900 Subject: [PATCH 3502/5608] Fix mania hitobject selections not moving correctly --- .../Edit/ManiaSelectionHandler.cs | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index f576c43e52..2fba0639da 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -65,24 +65,27 @@ namespace osu.Game.Rulesets.Mania.Edit private void performDragMovement(MoveSelectionEvent moveEvent) { + float delta = moveEvent.InstantDelta.Y; + + // When scrolling downwards the anchor position is at the bottom of the screen, however the movement event assumes the anchor is at the top of the screen. + // This causes the delta to assume a positive hitobject position, and which can be corrected for by subtracting the parent height. + if (scrollingInfo.Direction.Value == ScrollingDirection.Down) + delta -= moveEvent.Blueprint.HitObject.Parent.DrawHeight; + foreach (var b in SelectedBlueprints) { var hitObject = b.HitObject; - var objectParent = (HitObjectContainer)hitObject.Parent; - // Using the hitobject position is required since AdjustPosition can be invoked multiple times per frame - // without the position having been updated by the parenting ScrollingHitObjectContainer - hitObject.Y += moveEvent.InstantDelta.Y; + // StartTime could be used to adjust the position if only one movement event was received per frame. + // However this is not the case and ScrollingHitObjectContainer performs movement in UpdateAfterChildren() so the position must also be updated to be valid for further movement events + hitObject.Y += delta; - float targetPosition; + float targetPosition = hitObject.Position.Y; - // If we're scrolling downwards, a position of 0 is actually further away from the hit target - // so we need to flip the vertical coordinate in the hitobject container's space + // The scrolling algorithm always assumes an anchor at the top of the screen, so the position must be flipped when scrolling downwards to reflect a top anchor if (scrollingInfo.Direction.Value == ScrollingDirection.Down) - targetPosition = -hitObject.Position.Y; - else - targetPosition = hitObject.Position.Y; + targetPosition = -targetPosition; objectParent.Remove(hitObject); From 38dcd42d0891fd3c2961277a32661ab7f4d2a974 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 17 Oct 2019 12:35:12 +0300 Subject: [PATCH 3503/5608] Parse voted comments --- .../Online/API/Requests/Responses/Comment.cs | 2 ++ .../API/Requests/Responses/CommentBundle.cs | 20 ++++++++++++++++ osu.Game/Overlays/Comments/DrawableComment.cs | 24 ++++++++++++++----- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 29abaa74e5..5510e9afff 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -72,6 +72,8 @@ namespace osu.Game.Online.API.Requests.Responses public bool HasMessage => !string.IsNullOrEmpty(MessageHtml); + public bool IsVoted { get; set; } + public string GetMessage => HasMessage ? WebUtility.HtmlDecode(Regex.Replace(MessageHtml, @"<(.|\n)*?>", string.Empty)) : string.Empty; public int DeletedChildrenCount => ChildComments.Count(c => c.IsDeleted); diff --git a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs index 7063581605..f910c738ac 100644 --- a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs +++ b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs @@ -47,6 +47,26 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"included_comments")] public List IncludedComments { get; set; } + private List userVotes; + + [JsonProperty(@"user_votes")] + public List UserVotes + { + get => userVotes; + set + { + userVotes = value; + value.ForEach(v => + { + Comments.ForEach(c => + { + if (v == c.Id) + c.IsVoted = true; + }); + }); + } + } + private List users; [JsonProperty(@"users")] diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 89abda92cf..3e9c6a5eca 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -15,6 +15,8 @@ using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; using System.Linq; using osu.Game.Online.Chat; +using osu.Framework.Allocation; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Comments { @@ -81,7 +83,7 @@ namespace osu.Game.Overlays.Comments Spacing = new Vector2(5, 0), Children = new Drawable[] { - votePill = new VotePill(comment.VotesCount) + votePill = new VotePill(comment) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -336,28 +338,38 @@ namespace osu.Game.Overlays.Comments private class VotePill : CircularContainer { - public VotePill(int count) + private readonly Box background; + private readonly Comment comment; + + public VotePill(Comment comment) { + this.comment = comment; + AutoSizeAxes = Axes.X; Height = 20; Masking = true; Children = new Drawable[] { - new Box + background = new Box { RelativeSizeAxes = Axes.Both, - Colour = OsuColour.Gray(0.05f) }, - new SpriteText + new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, Margin = new MarginPadding { Horizontal = margin }, Font = OsuFont.GetFont(size: 14), - Text = $"+{count}" + Text = $"+{comment.VotesCount}" } }; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = comment.IsVoted ? colours.GreenLight : OsuColour.Gray(0.05f); + } } } } From 1f28c00594daa535678f651a5d16501347653648 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 17 Oct 2019 13:10:28 +0300 Subject: [PATCH 3504/5608] UI implementation --- osu.Game/Overlays/Comments/DrawableComment.cs | 68 +++++++++++++++++-- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 3e9c6a5eca..d1cae6592a 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -17,6 +17,10 @@ using System.Linq; using osu.Game.Online.Chat; using osu.Framework.Allocation; using osu.Game.Graphics.Sprites; +using osuTK.Graphics; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Comments { @@ -57,7 +61,7 @@ namespace osu.Game.Overlays.Comments { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding(margin), + Padding = new MarginPadding(margin) { Left = margin + 5 }, Child = content = new GridContainer { RelativeSizeAxes = Axes.X, @@ -336,10 +340,15 @@ namespace osu.Game.Overlays.Comments } } - private class VotePill : CircularContainer + private class VotePill : Container, IHasAccentColour { + public Color4 AccentColour { get; set; } + private readonly Box background; + private readonly Box hoverLayer; private readonly Comment comment; + private readonly CircularContainer borderContainer; + private readonly SpriteText sideNumber; public VotePill(Comment comment) { @@ -347,12 +356,24 @@ namespace osu.Game.Overlays.Comments AutoSizeAxes = Axes.X; Height = 20; - Masking = true; Children = new Drawable[] { - background = new Box + borderContainer = new CircularContainer { RelativeSizeAxes = Axes.Both, + Masking = true, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + hoverLayer = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0 + } + } }, new OsuSpriteText { @@ -361,14 +382,49 @@ namespace osu.Game.Overlays.Comments Margin = new MarginPadding { Horizontal = margin }, Font = OsuFont.GetFont(size: 14), Text = $"+{comment.VotesCount}" - } + }, + sideNumber = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreRight, + Text = "+1", + Font = OsuFont.GetFont(size: 14), + Margin = new MarginPadding { Right = 3 }, + Alpha = 0, + }, + new HoverClickSounds(), }; } [BackgroundDependencyLoader] private void load(OsuColour colours) { - background.Colour = comment.IsVoted ? colours.GreenLight : OsuColour.Gray(0.05f); + AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; + background.Colour = comment.IsVoted ? AccentColour : OsuColour.Gray(0.05f); + hoverLayer.Colour = Color4.Black.Opacity(0.5f); + } + + protected override bool OnHover(HoverEvent e) + { + if (comment.IsVoted) + hoverLayer.Show(); + else + sideNumber.Show(); + + borderContainer.BorderThickness = 3; + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + if (comment.IsVoted) + hoverLayer.Hide(); + else + sideNumber.Hide(); + + borderContainer.BorderThickness = 0; } } } From d3a8dfd5ff6287ba616b31030a9e5c643cffb5ad Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 17 Oct 2019 13:57:17 +0300 Subject: [PATCH 3505/5608] Implement LoadingButton component --- .../Graphics/UserInterface/LoadingButton.cs | 96 +++++++++++++ .../Graphics/UserInterface/ShowMoreButton.cs | 129 ++++++------------ 2 files changed, 135 insertions(+), 90 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/LoadingButton.cs diff --git a/osu.Game/Graphics/UserInterface/LoadingButton.cs b/osu.Game/Graphics/UserInterface/LoadingButton.cs new file mode 100644 index 0000000000..1557a90c4a --- /dev/null +++ b/osu.Game/Graphics/UserInterface/LoadingButton.cs @@ -0,0 +1,96 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Containers; +using osuTK; + +namespace osu.Game.Graphics.UserInterface +{ + public abstract class LoadingButton : OsuHoverContainer + { + private const float fade_duration = 200; + + private bool isLoading; + + public bool IsLoading + { + get => isLoading; + set + { + isLoading = value; + + Enabled.Value = !isLoading; + + if (value) + { + loading.Show(); + content.FadeOut(fade_duration, Easing.OutQuint); + OnLoadingStart(); + } + else + { + loading.Hide(); + content.FadeIn(fade_duration, Easing.OutQuint); + OnLoadingFinished(); + } + } + } + + public Vector2 LoadingAnimationSize + { + get => loading.Size; + set => loading.Size = value; + } + + private readonly Container background; + private readonly LoadingAnimation loading; + private readonly Drawable content; + + public LoadingButton() + { + Child = background = CreateBackground(); + + background.AddRange(new Drawable[] + { + content = CreateContent(), + loading = new LoadingAnimation + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(12) + } + }); + } + + protected override bool OnClick(ClickEvent e) + { + if (!Enabled.Value) + return false; + + try + { + return base.OnClick(e); + } + finally + { + // run afterwards as this will disable this button. + IsLoading = true; + } + } + + protected virtual void OnLoadingStart() + { + } + + protected virtual void OnLoadingFinished() + { + } + + protected abstract Container CreateBackground(); + + protected abstract Drawable CreateContent(); + } +} diff --git a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs index 5296b9dd7f..b6b87c43f2 100644 --- a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs +++ b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs @@ -5,8 +5,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; @@ -14,10 +12,8 @@ using System.Collections.Generic; namespace osu.Game.Graphics.UserInterface { - public class ShowMoreButton : OsuHoverContainer + public class ShowMoreButton : LoadingButton { - private const float fade_duration = 200; - private Color4 chevronIconColour; protected Color4 ChevronIconColour @@ -32,100 +28,53 @@ namespace osu.Game.Graphics.UserInterface set => text.Text = value; } - private bool isLoading; - - public bool IsLoading - { - get => isLoading; - set - { - isLoading = value; - - Enabled.Value = !isLoading; - - if (value) - { - loading.Show(); - content.FadeOut(fade_duration, Easing.OutQuint); - } - else - { - loading.Hide(); - content.FadeIn(fade_duration, Easing.OutQuint); - } - } - } - - private readonly Box background; - private readonly LoadingAnimation loading; - private readonly FillFlowContainer content; - private readonly ChevronIcon leftChevron; - private readonly ChevronIcon rightChevron; - private readonly SpriteText text; - protected override IEnumerable EffectTargets => new[] { background }; + private ChevronIcon leftChevron; + private ChevronIcon rightChevron; + private SpriteText text; + private Box background; + public ShowMoreButton() { AutoSizeAxes = Axes.Both; + AddInternal(new CircularContainer + { + Masking = true, + Size = new Vector2(140, 30) + }); + } + + protected override Container CreateBackground() => new CircularContainer + { + Masking = true, + Size = new Vector2(140, 30), + Child = background = new Box + { + RelativeSizeAxes = Axes.Both, + } + }; + + protected override Drawable CreateContent() => new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7), Children = new Drawable[] { - new CircularContainer + leftChevron = new ChevronIcon(), + text = new OsuSpriteText { - Masking = true, - Size = new Vector2(140, 30), - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - content = new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7), - Children = new Drawable[] - { - leftChevron = new ChevronIcon(), - text = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), - Text = "show more".ToUpper(), - }, - rightChevron = new ChevronIcon(), - } - }, - loading = new LoadingAnimation - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(12) - }, - } - } - }; - } - - protected override bool OnClick(ClickEvent e) - { - if (!Enabled.Value) - return false; - - try - { - return base.OnClick(e); + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Text = "show more".ToUpper(), + }, + rightChevron = new ChevronIcon(), } - finally - { - // run afterwards as this will disable this button. - IsLoading = true; - } - } + }; private class ChevronIcon : SpriteIcon { From a437ff74ccf17f9e5bd3d42af78f053a62495e6c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 17 Oct 2019 14:18:31 +0300 Subject: [PATCH 3506/5608] Move VotePill to it's own file --- .../Online/TestSceneCommentsContainer.cs | 3 +- .../Graphics/UserInterface/ShowMoreButton.cs | 5 - osu.Game/Overlays/Comments/DrawableComment.cs | 94 ------------ osu.Game/Overlays/Comments/VotePill.cs | 135 ++++++++++++++++++ 4 files changed, 137 insertions(+), 100 deletions(-) create mode 100644 osu.Game/Overlays/Comments/VotePill.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index 436e80d6f5..86bd0ddd11 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -22,7 +22,8 @@ namespace osu.Game.Tests.Visual.Online typeof(HeaderButton), typeof(SortTabControl), typeof(ShowChildrenButton), - typeof(DeletedChildrenPlaceholder) + typeof(DeletedChildrenPlaceholder), + typeof(VotePill) }; protected override bool UseOnlineAPI => true; diff --git a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs index b6b87c43f2..31e9af55c4 100644 --- a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs +++ b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs @@ -38,11 +38,6 @@ namespace osu.Game.Graphics.UserInterface public ShowMoreButton() { AutoSizeAxes = Axes.Both; - AddInternal(new CircularContainer - { - Masking = true, - Size = new Vector2(140, 30) - }); } protected override Container CreateBackground() => new CircularContainer diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index d1cae6592a..bc53af09d3 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -15,12 +15,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; using System.Linq; using osu.Game.Online.Chat; -using osu.Framework.Allocation; -using osu.Game.Graphics.Sprites; -using osuTK.Graphics; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Input.Events; -using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Comments { @@ -339,93 +333,5 @@ namespace osu.Game.Overlays.Comments return parentComment.HasMessage ? parentComment.GetMessage : parentComment.IsDeleted ? @"deleted" : string.Empty; } } - - private class VotePill : Container, IHasAccentColour - { - public Color4 AccentColour { get; set; } - - private readonly Box background; - private readonly Box hoverLayer; - private readonly Comment comment; - private readonly CircularContainer borderContainer; - private readonly SpriteText sideNumber; - - public VotePill(Comment comment) - { - this.comment = comment; - - AutoSizeAxes = Axes.X; - Height = 20; - Children = new Drawable[] - { - borderContainer = new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both - }, - hoverLayer = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0 - } - } - }, - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Margin = new MarginPadding { Horizontal = margin }, - Font = OsuFont.GetFont(size: 14), - Text = $"+{comment.VotesCount}" - }, - sideNumber = new SpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreRight, - Text = "+1", - Font = OsuFont.GetFont(size: 14), - Margin = new MarginPadding { Right = 3 }, - Alpha = 0, - }, - new HoverClickSounds(), - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; - background.Colour = comment.IsVoted ? AccentColour : OsuColour.Gray(0.05f); - hoverLayer.Colour = Color4.Black.Opacity(0.5f); - } - - protected override bool OnHover(HoverEvent e) - { - if (comment.IsVoted) - hoverLayer.Show(); - else - sideNumber.Show(); - - borderContainer.BorderThickness = 3; - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - - if (comment.IsVoted) - hoverLayer.Hide(); - else - sideNumber.Hide(); - - borderContainer.BorderThickness = 0; - } - } } } diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs new file mode 100644 index 0000000000..79b7310c28 --- /dev/null +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -0,0 +1,135 @@ +// 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.Containers; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Online.API.Requests.Responses; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Allocation; +using osu.Game.Graphics.Sprites; +using osuTK.Graphics; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; +using System.Collections.Generic; +using osuTK; + +namespace osu.Game.Overlays.Comments +{ + public class VotePill : LoadingButton, IHasAccentColour + { + public Color4 AccentColour { get; set; } + + protected override IEnumerable EffectTargets => null; + + private readonly Comment comment; + private Box background; + private Box hoverLayer; + private CircularContainer borderContainer; + private SpriteText sideNumber; + private OsuSpriteText votesCounter; + + public VotePill(Comment comment) + { + this.comment = comment; + votesCounter.Text = $"+{comment.VotesCount}"; + + AutoSizeAxes = Axes.X; + Height = 20; + LoadingAnimationSize = new Vector2(10); + + Action = () => + { + + }; + } + + protected override Container CreateBackground() => new Container + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] + { + borderContainer = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + hoverLayer = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0 + } + } + }, + sideNumber = new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreRight, + Text = "+1", + Font = OsuFont.GetFont(size: 14), + Margin = new MarginPadding { Right = 3 }, + Alpha = 0, + }, + }, + }; + + protected override Drawable CreateContent() => votesCounter = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Horizontal = 10 }, + Font = OsuFont.GetFont(size: 14), + AlwaysPresent = true, + }; + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; + background.Colour = comment.IsVoted ? AccentColour : OsuColour.Gray(0.05f); + hoverLayer.Colour = Color4.Black.Opacity(0.5f); + } + + protected override void OnLoadingStart() + { + sideNumber.Hide(); + borderContainer.BorderThickness = 0; + } + + protected override bool OnHover(HoverEvent e) + { + if (comment.IsVoted) + hoverLayer.Show(); + + if (!IsLoading) + { + borderContainer.BorderThickness = 3; + + if (!comment.IsVoted) + sideNumber.Show(); + } + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + if (comment.IsVoted) + hoverLayer.Hide(); + else + sideNumber.Hide(); + + borderContainer.BorderThickness = 0; + } + } +} From 42cd4107a0396d8dd06e2acba1ca4ba659f2dd62 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 17 Oct 2019 15:04:30 +0300 Subject: [PATCH 3507/5608] Implement CommentVoteRequest and adjust UI --- .../Online/API/Requests/CommentVoteRequest.cs | 36 +++++++ osu.Game/Overlays/Comments/VotePill.cs | 96 ++++++++++++++----- 2 files changed, 106 insertions(+), 26 deletions(-) create mode 100644 osu.Game/Online/API/Requests/CommentVoteRequest.cs diff --git a/osu.Game/Online/API/Requests/CommentVoteRequest.cs b/osu.Game/Online/API/Requests/CommentVoteRequest.cs new file mode 100644 index 0000000000..06a3b1126e --- /dev/null +++ b/osu.Game/Online/API/Requests/CommentVoteRequest.cs @@ -0,0 +1,36 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.IO.Network; +using osu.Game.Online.API.Requests.Responses; +using System.Net.Http; + +namespace osu.Game.Online.API.Requests +{ + public class CommentVoteRequest : APIRequest + { + private readonly long id; + private readonly CommentVoteAction action; + + public CommentVoteRequest(long id, CommentVoteAction action) + { + this.id = id; + this.action = action; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = action == CommentVoteAction.Vote ? HttpMethod.Post : HttpMethod.Delete; + return req; + } + + protected override string Target => $@"comments/{id}/vote"; + } + + public enum CommentVoteAction + { + Vote, + UnVote + } +} diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 79b7310c28..cd50546b45 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -15,6 +15,10 @@ using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; using System.Collections.Generic; using osuTK; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Framework.Bindables; +using System.Linq; namespace osu.Game.Overlays.Comments { @@ -24,26 +28,57 @@ namespace osu.Game.Overlays.Comments protected override IEnumerable EffectTargets => null; + [Resolved] + private IAPIProvider api { get; set; } + private readonly Comment comment; private Box background; private Box hoverLayer; private CircularContainer borderContainer; private SpriteText sideNumber; private OsuSpriteText votesCounter; + private CommentVoteRequest request; + + private readonly BindableBool isVoted = new BindableBool(); public VotePill(Comment comment) { this.comment = comment; - votesCounter.Text = $"+{comment.VotesCount}"; + setCount(comment.VotesCount); + + Action = onAction; AutoSizeAxes = Axes.X; Height = 20; LoadingAnimationSize = new Vector2(10); + } - Action = () => - { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; + hoverLayer.Colour = Color4.Black.Opacity(0.5f); + } - }; + protected override void LoadComplete() + { + base.LoadComplete(); + isVoted.Value = comment.IsVoted; + isVoted.BindValueChanged(voted => background.Colour = voted.NewValue ? AccentColour : OsuColour.Gray(0.05f), true); + } + + private void onAction() + { + request = new CommentVoteRequest(comment.Id, isVoted.Value ? CommentVoteAction.UnVote : CommentVoteAction.Vote); + request.Success += onSuccess; + api.Queue(request); + } + + private void onSuccess(CommentBundle response) + { + isVoted.Value = !isVoted.Value; + setCount(response.Comments.First().VotesCount); + IsLoading = false; } protected override Container CreateBackground() => new Container @@ -90,46 +125,55 @@ namespace osu.Game.Overlays.Comments AlwaysPresent = true, }; - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; - background.Colour = comment.IsVoted ? AccentColour : OsuColour.Gray(0.05f); - hoverLayer.Colour = Color4.Black.Opacity(0.5f); - } + protected override void OnLoadingStart() => onHoverLostAction(); - protected override void OnLoadingStart() + protected override void OnLoadingFinished() { - sideNumber.Hide(); - borderContainer.BorderThickness = 0; + if (IsHovered) + onHoverAction(); } protected override bool OnHover(HoverEvent e) { - if (comment.IsVoted) - hoverLayer.Show(); - - if (!IsLoading) - { - borderContainer.BorderThickness = 3; - - if (!comment.IsVoted) - sideNumber.Show(); - } - + onHoverAction(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { + onHoverLostAction(); base.OnHoverLost(e); + } - if (comment.IsVoted) + private void onHoverLostAction() + { + if (isVoted.Value) hoverLayer.Hide(); else sideNumber.Hide(); borderContainer.BorderThickness = 0; } + + private void onHoverAction() + { + if (!IsLoading) + { + borderContainer.BorderThickness = 3; + + if (!isVoted.Value) + sideNumber.Show(); + else + hoverLayer.Show(); + } + } + + private void setCount(int count) => votesCounter.Text = $"+{count}"; + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + request?.Cancel(); + } } } From 6b196a6ce7548b180afebed93adfaf0d5062ef55 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 17 Oct 2019 15:24:51 +0300 Subject: [PATCH 3508/5608] CI fixes --- osu.Game/Graphics/UserInterface/LoadingButton.cs | 7 ++++--- osu.Game/Overlays/Comments/DrawableComment.cs | 10 ++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/LoadingButton.cs b/osu.Game/Graphics/UserInterface/LoadingButton.cs index 1557a90c4a..46a4c70666 100644 --- a/osu.Game/Graphics/UserInterface/LoadingButton.cs +++ b/osu.Game/Graphics/UserInterface/LoadingButton.cs @@ -45,15 +45,16 @@ namespace osu.Game.Graphics.UserInterface set => loading.Size = value; } - private readonly Container background; private readonly LoadingAnimation loading; private readonly Drawable content; - public LoadingButton() + protected LoadingButton() { + Container background; + Child = background = CreateBackground(); - background.AddRange(new Drawable[] + background.AddRange(new[] { content = CreateContent(), loading = new LoadingAnimation diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index bc53af09d3..b376900b18 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -81,11 +81,17 @@ namespace osu.Game.Overlays.Comments Spacing = new Vector2(5, 0), Children = new Drawable[] { - votePill = new VotePill(comment) + new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, - AlwaysPresent = true, + Width = 40, + AutoSizeAxes = Axes.Y, + Child = votePill = new VotePill(comment) + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + } }, new UpdateableAvatar(comment.User) { From a858e713f88e7f009c8a2269a72d41d432357eda Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 17 Oct 2019 15:40:09 +0300 Subject: [PATCH 3509/5608] Fix multiple spaces --- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index b376900b18..3fb9867f0e 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -87,7 +87,7 @@ namespace osu.Game.Overlays.Comments Origin = Anchor.Centre, Width = 40, AutoSizeAxes = Axes.Y, - Child = votePill = new VotePill(comment) + Child = votePill = new VotePill(comment) { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, From 9ee63a8c1abb260ccd196662c9e1e9705bb9f086 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 17 Oct 2019 16:28:32 +0300 Subject: [PATCH 3510/5608] Apply suggested changes --- osu.Game/Online/API/Requests/Responses/CommentBundle.cs | 6 +----- osu.Game/Overlays/Comments/VotePill.cs | 8 ++++---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs index f910c738ac..7db3126ade 100644 --- a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs +++ b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs @@ -47,15 +47,11 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"included_comments")] public List IncludedComments { get; set; } - private List userVotes; - [JsonProperty(@"user_votes")] - public List UserVotes + private List userVotes { - get => userVotes; set { - userVotes = value; value.ForEach(v => { Comments.ForEach(c => diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index cd50546b45..d8288c8ec4 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -40,11 +40,11 @@ namespace osu.Game.Overlays.Comments private CommentVoteRequest request; private readonly BindableBool isVoted = new BindableBool(); + private readonly BindableInt votesCount = new BindableInt(); public VotePill(Comment comment) { this.comment = comment; - setCount(comment.VotesCount); Action = onAction; @@ -64,7 +64,9 @@ namespace osu.Game.Overlays.Comments { base.LoadComplete(); isVoted.Value = comment.IsVoted; + votesCount.Value = comment.VotesCount; isVoted.BindValueChanged(voted => background.Colour = voted.NewValue ? AccentColour : OsuColour.Gray(0.05f), true); + votesCount.BindValueChanged(count => votesCounter.Text = $"+{count.NewValue}", true); } private void onAction() @@ -77,7 +79,7 @@ namespace osu.Game.Overlays.Comments private void onSuccess(CommentBundle response) { isVoted.Value = !isVoted.Value; - setCount(response.Comments.First().VotesCount); + votesCount.Value = response.Comments.Single().VotesCount; IsLoading = false; } @@ -168,8 +170,6 @@ namespace osu.Game.Overlays.Comments } } - private void setCount(int count) => votesCounter.Text = $"+{count}"; - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From 22511e41e29ab2bea9b01f678296f91224d7d3c8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 17 Oct 2019 23:20:01 +0300 Subject: [PATCH 3511/5608] Use received data to set isVoted bindable --- osu.Game/Overlays/Comments/VotePill.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index d8288c8ec4..d1a78cb368 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -78,8 +78,9 @@ namespace osu.Game.Overlays.Comments private void onSuccess(CommentBundle response) { - isVoted.Value = !isVoted.Value; - votesCount.Value = response.Comments.Single().VotesCount; + var receivedComment = response.Comments.Single(); + isVoted.Value = receivedComment.IsVoted; + votesCount.Value = receivedComment.VotesCount; IsLoading = false; } From e5b50b5e1fda974c7e47ec5be852ff0ec98bcf63 Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 17 Oct 2019 13:54:36 -0700 Subject: [PATCH 3512/5608] Fix slider bar regression when using arrows --- osu.Game/Graphics/UserInterface/FixedSearchTextBox.cs | 10 ++++++++++ osu.Game/Overlays/SettingsPanel.cs | 4 ++-- osu.Game/Screens/Select/FilterControl.cs | 9 ++------- 3 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/FixedSearchTextBox.cs diff --git a/osu.Game/Graphics/UserInterface/FixedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/FixedSearchTextBox.cs new file mode 100644 index 0000000000..0654746a6e --- /dev/null +++ b/osu.Game/Graphics/UserInterface/FixedSearchTextBox.cs @@ -0,0 +1,10 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Graphics.UserInterface +{ + public class FixedSearchTextBox : SearchTextBox + { + public override bool HandleLeftRightArrows => false; + } +} diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 37e7b62483..119b9a2b8c 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -37,7 +37,7 @@ namespace osu.Game.Overlays protected SettingsSectionsContainer SectionsContainer; - private SearchTextBox searchTextBox; + private FixedSearchTextBox searchTextBox; /// /// Provide a source for the toolbar height. @@ -80,7 +80,7 @@ namespace osu.Game.Overlays Masking = true, RelativeSizeAxes = Axes.Both, ExpandableHeader = CreateHeader(), - FixedHeader = searchTextBox = new SearchTextBox + FixedHeader = searchTextBox = new FixedSearchTextBox { RelativeSizeAxes = Axes.X, Origin = Anchor.TopCentre, diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 2c878f8d90..7aca11da2f 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -49,7 +49,7 @@ namespace osu.Game.Screens.Select return criteria; } - private readonly SongSelectTextBox searchTextBox; + private readonly FixedSearchTextBox searchTextBox; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) || groupTabs.ReceivePositionalInputAt(screenSpacePos) || sortTabs.ReceivePositionalInputAt(screenSpacePos); @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.TopRight, Children = new Drawable[] { - searchTextBox = new SongSelectTextBox { RelativeSizeAxes = Axes.X }, + searchTextBox = new FixedSearchTextBox { RelativeSizeAxes = Axes.X }, new Box { RelativeSizeAxes = Axes.X, @@ -170,10 +170,5 @@ namespace osu.Game.Screens.Select } private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria()); - - private class SongSelectTextBox : SearchTextBox - { - public override bool HandleLeftRightArrows => false; - } } } From 9daafb46365b369b9a656c52127f89d1e15a0baa Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 18 Oct 2019 03:06:01 +0300 Subject: [PATCH 3513/5608] Simplify hover/unhover logic --- osu.Game/Overlays/Comments/VotePill.cs | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index d1a78cb368..5eade6fc46 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -128,7 +128,7 @@ namespace osu.Game.Overlays.Comments AlwaysPresent = true, }; - protected override void OnLoadingStart() => onHoverLostAction(); + protected override void OnLoadingStart() => updateDisplay(); protected override void OnLoadingFinished() { @@ -144,31 +144,27 @@ namespace osu.Game.Overlays.Comments protected override void OnHoverLost(HoverLostEvent e) { - onHoverLostAction(); + updateDisplay(); base.OnHoverLost(e); } - private void onHoverLostAction() + private void updateDisplay() { if (isVoted.Value) - hoverLayer.Hide(); - else + { + hoverLayer.FadeTo(IsHovered ? 1 : 0); sideNumber.Hide(); + } + else + sideNumber.FadeTo(IsHovered ? 1 : 0); - borderContainer.BorderThickness = 0; + borderContainer.BorderThickness = IsHovered ? 3 : 0; } private void onHoverAction() { if (!IsLoading) - { - borderContainer.BorderThickness = 3; - - if (!isVoted.Value) - sideNumber.Show(); - else - hoverLayer.Show(); - } + updateDisplay(); } protected override void Dispose(bool isDisposing) From 5ccdd2b203512f9a6cb00947546b5474bfcd46a2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 20:05:25 +0900 Subject: [PATCH 3514/5608] Mask the osu! beatsnap grid --- osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs index f701712739..bc0f76f000 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs @@ -13,6 +13,7 @@ namespace osu.Game.Rulesets.Osu.Edit public OsuDistanceSnapGrid(OsuHitObject hitObject) : base(hitObject, hitObject.StackedEndPosition) { + Masking = true; } protected override float GetVelocity(double time, ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) From bc76a9cb8c4c80e352152d86fb9abf80f3eff284 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 20:07:11 +0900 Subject: [PATCH 3515/5608] Expose selection changed event from BlueprintContainer --- .../Compose/Components/BlueprintContainer.cs | 16 ++++++++++------ .../Edit/Compose/Components/SelectionHandler.cs | 4 ++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index cb3d3b71fc..ef1eb09e7c 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -19,15 +20,14 @@ namespace osu.Game.Screens.Edit.Compose.Components { public class BlueprintContainer : CompositeDrawable { - private SelectionBlueprintContainer selectionBlueprints; + public event Action> SelectionChanged; + private SelectionBlueprintContainer selectionBlueprints; private Container placementBlueprintContainer; private PlacementBlueprint currentPlacement; private SelectionHandler selectionHandler; private InputManager inputManager; - private IEnumerable selections => selectionBlueprints.Children.Where(c => c.IsAlive); - [Resolved] private HitObjectComposer composer { get; set; } @@ -196,9 +196,9 @@ namespace osu.Game.Screens.Edit.Compose.Components /// The rectangle to perform a selection on in screen-space coordinates. private void select(RectangleF rect) { - foreach (var blueprint in selections.ToList()) + foreach (var blueprint in selectionBlueprints) { - if (blueprint.IsPresent && rect.Contains(blueprint.SelectionPoint)) + if (blueprint.IsAlive && blueprint.IsPresent && rect.Contains(blueprint.SelectionPoint)) blueprint.Select(); else blueprint.Deselect(); @@ -208,18 +208,22 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Deselects all selected s. /// - private void deselectAll() => selections.ToList().ForEach(m => m.Deselect()); + private void deselectAll() => selectionHandler.SelectedBlueprints.ToList().ForEach(m => m.Deselect()); private void onBlueprintSelected(SelectionBlueprint blueprint) { selectionHandler.HandleSelected(blueprint); selectionBlueprints.ChangeChildDepth(blueprint, 1); + + SelectionChanged?.Invoke(selectionHandler.SelectedHitObjects); } private void onBlueprintDeselected(SelectionBlueprint blueprint) { selectionHandler.HandleDeselected(blueprint); selectionBlueprints.ChangeChildDepth(blueprint, 0); + + SelectionChanged?.Invoke(selectionHandler.SelectedHitObjects); } private void onSelectionRequested(SelectionBlueprint blueprint, InputState state) => selectionHandler.HandleSelectionRequested(blueprint, state); diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index c9e862d99e..f1467ff2c6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -26,10 +26,10 @@ namespace osu.Game.Screens.Edit.Compose.Components { public const float BORDER_RADIUS = 2; - protected IEnumerable SelectedBlueprints => selectedBlueprints; + public IEnumerable SelectedBlueprints => selectedBlueprints; private readonly List selectedBlueprints; - protected IEnumerable SelectedHitObjects => selectedBlueprints.Select(b => b.HitObject.HitObject); + public IEnumerable SelectedHitObjects => selectedBlueprints.Select(b => b.HitObject.HitObject); private Drawable outline; From d3e38f5e5aeeeb7c88ca2e7c5ff507c8dd82ba02 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 20:10:03 +0900 Subject: [PATCH 3516/5608] Make the editor beatmap protected --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 25 ++++++++++----------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index a267d7c44d..bf31b76dc4 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -30,12 +30,11 @@ namespace osu.Game.Rulesets.Edit where TObject : HitObject { protected IRulesetConfigManager Config { get; private set; } - + protected EditorBeatmap EditorBeatmap { get; private set; } protected readonly Ruleset Ruleset; private IWorkingBeatmap workingBeatmap; private Beatmap playableBeatmap; - private EditorBeatmap editorBeatmap; private IBeatmapProcessor beatmapProcessor; private DrawableEditRulesetWrapper drawableRulesetWrapper; @@ -129,14 +128,14 @@ namespace osu.Game.Rulesets.Edit beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap); - editorBeatmap = new EditorBeatmap(playableBeatmap); - editorBeatmap.HitObjectAdded += addHitObject; - editorBeatmap.HitObjectRemoved += removeHitObject; - editorBeatmap.StartTimeChanged += updateHitObject; + EditorBeatmap = new EditorBeatmap(playableBeatmap); + EditorBeatmap.HitObjectAdded += addHitObject; + EditorBeatmap.HitObjectRemoved += removeHitObject; + EditorBeatmap.StartTimeChanged += updateHitObject; var dependencies = new DependencyContainer(parent); - dependencies.CacheAs(editorBeatmap); - dependencies.CacheAs>(editorBeatmap); + dependencies.CacheAs(EditorBeatmap); + dependencies.CacheAs>(EditorBeatmap); Config = dependencies.Get().GetConfigFor(Ruleset); @@ -189,18 +188,18 @@ namespace osu.Game.Rulesets.Edit { } - public void EndPlacement(HitObject hitObject) => editorBeatmap.Add(hitObject); + public void EndPlacement(HitObject hitObject) => EditorBeatmap.Add(hitObject); - public void Delete(HitObject hitObject) => editorBeatmap.Remove(hitObject); + public void Delete(HitObject hitObject) => EditorBeatmap.Remove(hitObject); protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - if (editorBeatmap != null) + if (EditorBeatmap != null) { - editorBeatmap.HitObjectAdded -= addHitObject; - editorBeatmap.HitObjectRemoved -= removeHitObject; + EditorBeatmap.HitObjectAdded -= addHitObject; + EditorBeatmap.HitObjectRemoved -= removeHitObject; } } } From c4704f6a2993fc01aaf5e875f6d951cb6edaa210 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 20:20:07 +0900 Subject: [PATCH 3517/5608] Add beat snap grid to the composer --- .../Edit/OsuHitObjectComposer.cs | 28 ++++++++ osu.Game/Rulesets/Edit/HitObjectComposer.cs | 70 +++++++++++++++++-- 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 1c040e9dee..a5590a999d 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -2,10 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders; @@ -52,5 +54,31 @@ namespace osu.Game.Rulesets.Osu.Edit return base.CreateBlueprintFor(hitObject); } + + protected override DistanceSnapGrid CreateDistanceSnapGrid(IEnumerable selectedHitObjects) + { + var objects = selectedHitObjects.ToList(); + + if (objects.Count == 0) + { + var lastObject = EditorBeatmap.HitObjects.LastOrDefault(h => h.StartTime < EditorClock.CurrentTime); + + if (lastObject == null) + return null; + + return new OsuDistanceSnapGrid(lastObject); + } + else + { + double minTime = objects.Min(h => h.StartTime); + + var lastObject = EditorBeatmap.HitObjects.LastOrDefault(h => h.StartTime < minTime); + + if (lastObject == null) + return null; + + return new OsuDistanceSnapGrid(lastObject); + } + } } } diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index bf31b76dc4..49ecea5fd0 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -33,12 +34,17 @@ namespace osu.Game.Rulesets.Edit protected EditorBeatmap EditorBeatmap { get; private set; } protected readonly Ruleset Ruleset; + [Resolved] + protected IFrameBasedClock EditorClock { get; private set; } + private IWorkingBeatmap workingBeatmap; private Beatmap playableBeatmap; private IBeatmapProcessor beatmapProcessor; private DrawableEditRulesetWrapper drawableRulesetWrapper; private BlueprintContainer blueprintContainer; + private Container distanceSnapGridContainer; + private DistanceSnapGrid distanceSnapGrid; private readonly List layerContainers = new List(); private InputManager inputManager; @@ -65,11 +71,13 @@ namespace osu.Game.Rulesets.Edit return; } - var layerBelowRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer(); - layerBelowRuleset.Child = new EditorPlayfieldBorder { RelativeSizeAxes = Axes.Both }; + var layerBelowRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChildren(new Drawable[] + { + distanceSnapGridContainer = new Container { RelativeSizeAxes = Axes.Both }, + new EditorPlayfieldBorder { RelativeSizeAxes = Axes.Both } + }); - var layerAboveRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer(); - layerAboveRuleset.Child = blueprintContainer = new BlueprintContainer(); + var layerAboveRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChild(blueprintContainer = new BlueprintContainer()); layerContainers.Add(layerBelowRuleset); layerContainers.Add(layerAboveRuleset); @@ -112,11 +120,13 @@ namespace osu.Game.Rulesets.Edit }; toolboxCollection.Items = - CompositionTools.Select(t => new RadioButton(t.Name, () => blueprintContainer.CurrentTool = t)) - .Prepend(new RadioButton("Select", () => blueprintContainer.CurrentTool = null)) + CompositionTools.Select(t => new RadioButton(t.Name, () => selectTool(t))) + .Prepend(new RadioButton("Select", () => selectTool(null))) .ToList(); toolboxCollection.Items[0].Select(); + + blueprintContainer.SelectionChanged += selectionChanged; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -149,6 +159,14 @@ namespace osu.Game.Rulesets.Edit inputManager = GetContainingInputManager(); } + protected override void Update() + { + base.Update(); + + if (EditorClock.ElapsedFrameTime != 0 && blueprintContainer.CurrentTool != null) + showGridFor(Enumerable.Empty()); + } + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); @@ -162,6 +180,38 @@ namespace osu.Game.Rulesets.Edit }); } + private void selectionChanged(IEnumerable selectedHitObjects) + { + var hitObjects = selectedHitObjects.ToArray(); + + if (!hitObjects.Any()) + distanceSnapGridContainer.Hide(); + else + showGridFor(hitObjects); + } + + private void selectTool(HitObjectCompositionTool tool) + { + blueprintContainer.CurrentTool = tool; + + if (tool == null) + distanceSnapGridContainer.Hide(); + else + showGridFor(Enumerable.Empty()); + } + + private void showGridFor(IEnumerable selectedHitObjects) + { + distanceSnapGridContainer.Clear(); + distanceSnapGrid = CreateDistanceSnapGrid(selectedHitObjects); + + if (distanceSnapGrid != null) + { + distanceSnapGridContainer.Child = distanceSnapGrid; + distanceSnapGridContainer.Show(); + } + } + private void addHitObject(HitObject hitObject) => updateHitObject(hitObject); private void removeHitObject(HitObject hitObject) @@ -232,5 +282,13 @@ namespace osu.Game.Rulesets.Edit /// Creates a which outlines s and handles movement of selections. /// public virtual SelectionHandler CreateSelectionHandler() => new SelectionHandler(); + + /// + /// Creates the applicable for a selection. + /// + /// The selection. + /// The for . + [CanBeNull] + protected virtual DistanceSnapGrid CreateDistanceSnapGrid([NotNull] IEnumerable selectedHitObjects) => null; } } From 1dc7c59853ae8fc5bc22c44bdb9fcc97a15b087d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 20:34:02 +0900 Subject: [PATCH 3518/5608] Implement selection position snapping --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 4 ++++ .../Screens/Edit/Compose/Components/BlueprintContainer.cs | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 49ecea5fd0..3f46a6deaa 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -242,6 +242,8 @@ namespace osu.Game.Rulesets.Edit public void Delete(HitObject hitObject) => EditorBeatmap.Remove(hitObject); + public override Vector2 GetSnappedPosition(Vector2 position) => beatSnapGrid?.GetSnapPosition(position) ?? position; + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -290,5 +292,7 @@ namespace osu.Game.Rulesets.Edit /// The for . [CanBeNull] protected virtual DistanceSnapGrid CreateDistanceSnapGrid([NotNull] IEnumerable selectedHitObjects) => null; + + public abstract Vector2 GetSnappedPosition(Vector2 position); } } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index ef1eb09e7c..295b21a99e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -230,9 +230,13 @@ namespace osu.Game.Screens.Edit.Compose.Components private void onDragRequested(SelectionBlueprint blueprint, DragEvent dragEvent) { - var movePosition = blueprint.ScreenSpaceMovementStartPosition + dragEvent.ScreenSpaceMousePosition - dragEvent.ScreenSpaceMouseDownPosition; + HitObject draggedObject = blueprint.HitObject.HitObject; - selectionHandler.HandleMovement(new MoveSelectionEvent(blueprint, blueprint.ScreenSpaceMovementStartPosition, movePosition)); + Vector2 movePosition = blueprint.ScreenSpaceMovementStartPosition + dragEvent.ScreenSpaceMousePosition - dragEvent.ScreenSpaceMouseDownPosition; + Vector2 snappedPosition = composer.GetSnappedPosition(ToLocalSpace(movePosition)); + + // Move the hitobjects + selectionHandler.HandleMovement(new MoveSelectionEvent(blueprint, blueprint.ScreenSpaceMovementStartPosition, ToScreenSpace(snappedPosition))); } protected override void Dispose(bool isDisposing) From ba4402207adaa23d1954e91ce381e7516428f2d5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 16 Oct 2019 20:34:16 +0900 Subject: [PATCH 3519/5608] Implement selection time snapping --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 4 ++++ .../Screens/Edit/Compose/Components/BlueprintContainer.cs | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 3f46a6deaa..0b2a9cd0fb 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -244,6 +244,8 @@ namespace osu.Game.Rulesets.Edit public override Vector2 GetSnappedPosition(Vector2 position) => beatSnapGrid?.GetSnapPosition(position) ?? position; + public override double GetSnappedTime(double startTime, Vector2 position) => beatSnapGrid?.GetSnapTime(position) ?? startTime; + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -294,5 +296,7 @@ namespace osu.Game.Rulesets.Edit protected virtual DistanceSnapGrid CreateDistanceSnapGrid([NotNull] IEnumerable selectedHitObjects) => null; public abstract Vector2 GetSnappedPosition(Vector2 position); + + public abstract double GetSnappedTime(double startTime, Vector2 screenSpacePosition); } } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 295b21a99e..5d7f9ab788 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; +using osuTK; namespace osu.Game.Screens.Edit.Compose.Components { @@ -237,6 +238,11 @@ namespace osu.Game.Screens.Edit.Compose.Components // Move the hitobjects selectionHandler.HandleMovement(new MoveSelectionEvent(blueprint, blueprint.ScreenSpaceMovementStartPosition, ToScreenSpace(snappedPosition))); + + // Apply the start time at the newly snapped-to position + double offset = composer.GetSnappedTime(draggedObject.StartTime, snappedPosition) - draggedObject.StartTime; + foreach (HitObject obj in selectionHandler.SelectedHitObjects) + obj.StartTime += offset; } protected override void Dispose(bool isDisposing) From b047e05d8618dab7e47c8d03c4af151ca53b1d8e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 Oct 2019 13:18:16 +0900 Subject: [PATCH 3520/5608] Fix bad variable names --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 0b2a9cd0fb..c0c4cccca3 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -242,9 +242,9 @@ namespace osu.Game.Rulesets.Edit public void Delete(HitObject hitObject) => EditorBeatmap.Remove(hitObject); - public override Vector2 GetSnappedPosition(Vector2 position) => beatSnapGrid?.GetSnapPosition(position) ?? position; + public override Vector2 GetSnappedPosition(Vector2 position) => distanceSnapGrid?.GetSnapPosition(position) ?? position; - public override double GetSnappedTime(double startTime, Vector2 position) => beatSnapGrid?.GetSnapTime(position) ?? startTime; + public override double GetSnappedTime(double startTime, Vector2 position) => distanceSnapGrid?.GetSnapTime(position) ?? startTime; protected override void Dispose(bool isDisposing) { From 9a896d52bf795b77159474deae5d7aa42cc4fa3e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 Oct 2019 13:18:41 +0900 Subject: [PATCH 3521/5608] Fix nested hitobjects not updating --- .../Objects/Drawables/DrawableHitObject.cs | 17 +++++++++++++++-- osu.Game/Rulesets/Objects/HitObject.cs | 8 ++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 99b0c07570..0a8648516e 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -77,6 +77,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public JudgementResult Result { get; private set; } + private Bindable startTimeBindable; private Bindable comboIndexBindable; public override bool RemoveWhenNotAlive => false; @@ -126,7 +127,10 @@ namespace osu.Game.Rulesets.Objects.Drawables { base.LoadComplete(); - Apply(HitObject); + HitObject.DefaultsApplied += onDefaultsApplied; + + startTimeBindable = HitObject.StartTimeBindable.GetBoundCopy(); + startTimeBindable.BindValueChanged(_ => updateState(ArmedState.Idle, true)); if (HitObject is IHasComboInformation combo) { @@ -135,9 +139,12 @@ namespace osu.Game.Rulesets.Objects.Drawables } updateState(ArmedState.Idle, true); + onDefaultsApplied(); } - protected void Apply(HitObject hitObject) + private void onDefaultsApplied() => apply(HitObject); + + private void apply(HitObject hitObject) { #pragma warning disable 618 // can be removed 20200417 if (GetType().GetMethod(nameof(AddNested), BindingFlags.NonPublic | BindingFlags.Instance)?.DeclaringType != typeof(DrawableHitObject)) @@ -493,6 +500,12 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// The that provides the scoring information. protected virtual JudgementResult CreateResult(Judgement judgement) => new JudgementResult(HitObject, judgement); + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + HitObject.DefaultsApplied -= onDefaultsApplied; + } } public abstract class DrawableHitObject : DrawableHitObject diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index eb8652443f..6211fe50e6 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; @@ -28,6 +29,11 @@ namespace osu.Game.Rulesets.Objects /// private const double control_point_leniency = 1; + /// + /// Invoked after has completed on this . + /// + public event Action DefaultsApplied; + public readonly Bindable StartTimeBindable = new Bindable(); /// @@ -113,6 +119,8 @@ namespace osu.Game.Rulesets.Objects foreach (var h in nestedHitObjects) h.ApplyDefaults(controlPointInfo, difficulty); + + DefaultsApplied?.Invoke(); } protected virtual void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) From cb301a46612839070fcc0bd531939eae4be05458 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 Oct 2019 13:18:57 +0900 Subject: [PATCH 3522/5608] Improve performance of intra-frame updates/deletions --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 22 ++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index c0c4cccca3..a5b7991a52 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Logging; +using osu.Framework.Threading; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets.Configuration; @@ -23,6 +24,7 @@ using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Components.RadioButtons; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Compose.Components; +using osuTK; namespace osu.Game.Rulesets.Edit { @@ -212,19 +214,21 @@ namespace osu.Game.Rulesets.Edit } } + private ScheduledDelegate scheduledUpdate; + private void addHitObject(HitObject hitObject) => updateHitObject(hitObject); - private void removeHitObject(HitObject hitObject) - { - beatmapProcessor?.PreProcess(); - beatmapProcessor?.PostProcess(); - } + private void removeHitObject(HitObject hitObject) => updateHitObject(null); - private void updateHitObject(HitObject hitObject) + private void updateHitObject([CanBeNull] HitObject hitObject) { - beatmapProcessor?.PreProcess(); - hitObject.ApplyDefaults(playableBeatmap.ControlPointInfo, playableBeatmap.BeatmapInfo.BaseDifficulty); - beatmapProcessor?.PostProcess(); + scheduledUpdate?.Cancel(); + scheduledUpdate = Schedule(() => + { + beatmapProcessor?.PreProcess(); + hitObject?.ApplyDefaults(playableBeatmap.ControlPointInfo, playableBeatmap.BeatmapInfo.BaseDifficulty); + beatmapProcessor?.PostProcess(); + }); } public override IEnumerable HitObjects => drawableRulesetWrapper.Playfield.AllHitObjects; From 5d3d25d3b69060342deb8ba58dfe192735c809a7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 Oct 2019 13:24:25 +0900 Subject: [PATCH 3523/5608] Make method private for now --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 99b0c07570..18d45f3724 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Objects.Drawables { base.LoadComplete(); - Apply(HitObject); + apply(HitObject); if (HitObject is IHasComboInformation combo) { @@ -137,7 +137,7 @@ namespace osu.Game.Rulesets.Objects.Drawables updateState(ArmedState.Idle, true); } - protected void Apply(HitObject hitObject) + private void apply(HitObject hitObject) { #pragma warning disable 618 // can be removed 20200417 if (GetType().GetMethod(nameof(AddNested), BindingFlags.NonPublic | BindingFlags.Instance)?.DeclaringType != typeof(DrawableHitObject)) From 463079e1480d7fa17c779ad16a33b710f84fc46c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 Oct 2019 13:48:59 +0900 Subject: [PATCH 3524/5608] Implement placement snapping --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 1 + .../Screens/Edit/Compose/Components/BlueprintContainer.cs | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index a5b7991a52..a51728ba88 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -240,6 +240,7 @@ namespace osu.Game.Rulesets.Edit public void BeginPlacement(HitObject hitObject) { + hitObject.StartTime = GetSnappedTime(hitObject.StartTime, inputManager.CurrentState.Mouse.Position); } public void EndPlacement(HitObject hitObject) => EditorBeatmap.Add(hitObject); diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 5d7f9ab788..3bb4266563 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -152,7 +152,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { if (currentPlacement != null) { - currentPlacement.UpdatePosition(e.ScreenSpaceMousePosition); + updatePlacementPosition(e.ScreenSpaceMousePosition); return true; } @@ -187,10 +187,12 @@ namespace osu.Game.Screens.Edit.Compose.Components placementBlueprintContainer.Child = currentPlacement = blueprint; // Fixes a 1-frame position discrepancy due to the first mouse move event happening in the next frame - blueprint.UpdatePosition(inputManager.CurrentState.Mouse.Position); + updatePlacementPosition(inputManager.CurrentState.Mouse.Position); } } + private void updatePlacementPosition(Vector2 screenSpacePosition) => currentPlacement.UpdatePosition(ToScreenSpace(composer.GetSnappedPosition(ToLocalSpace(screenSpacePosition)))); + /// /// Select all masks in a given rectangle selection area. /// From b30c84778f5ae5655decbb91ee6f79977dc0aaba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 Oct 2019 16:13:01 +0900 Subject: [PATCH 3525/5608] Update WaveContainer to support framework changes --- osu.Game/Graphics/Containers/WaveContainer.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/WaveContainer.cs b/osu.Game/Graphics/Containers/WaveContainer.cs index c01674f5b4..8b87ddaa20 100644 --- a/osu.Game/Graphics/Containers/WaveContainer.cs +++ b/osu.Game/Graphics/Containers/WaveContainer.cs @@ -159,8 +159,15 @@ namespace osu.Game.Graphics.Containers Height = Parent.Parent.DrawSize.Y * 1.5f; } - protected override void PopIn() => this.MoveToY(FinalPosition, APPEAR_DURATION, easing_show); - protected override void PopOut() => this.MoveToY(Parent.Parent.DrawSize.Y, DISAPPEAR_DURATION, easing_hide); + protected override void PopIn() => Schedule(() => this.MoveToY(FinalPosition, APPEAR_DURATION, easing_show)); + + protected override void PopOut() + { + double duration = IsLoaded ? DISAPPEAR_DURATION : 0; + + // scheduling is required as parent may not be present at the time this is called. + Schedule(() => this.MoveToY(Parent.Parent.DrawSize.Y, duration, easing_hide)); + } } } } From 6b0976ff1e2e1d13747f0e6a06114ff52b056b26 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Oct 2019 15:07:06 +0900 Subject: [PATCH 3526/5608] Remove a weird unicode charcter from file --- osu.Game/Overlays/AccountCreation/ScreenWarning.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index be417f4aac..f91d2e3323 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -121,7 +121,7 @@ namespace osu.Game.Overlays.AccountCreation multiAccountExplanationText.AddText("? osu! has a policy of "); multiAccountExplanationText.AddText("one account per person!", cp => cp.Colour = colours.Yellow); multiAccountExplanationText.AddText(" Please be aware that creating more than one account per person may result in "); - multiAccountExplanationText.AddText("permanent deactivation of accounts", cp => cp.Colour = colours.Yellow); + multiAccountExplanationText.AddText("permanent deactivation of accounts", cp => cp.Colour = colours.Yellow); multiAccountExplanationText.AddText("."); furtherAssistance.AddText("Need further assistance? Contact us via our "); From 89f50b26f72f56f932df01a99f94f93de621da8e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 Oct 2019 17:32:11 +0900 Subject: [PATCH 3527/5608] Fix hitobject combo colour potentially not getting adjusted --- .../TestSceneHitObjectAccentColour.cs | 143 ++++++++++++++++++ .../Objects/Drawables/DrawableHitObject.cs | 2 +- 2 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs new file mode 100644 index 0000000000..6d7159a825 --- /dev/null +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs @@ -0,0 +1,143 @@ +// 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 NUnit.Framework; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Textures; +using osu.Framework.Testing; +using osu.Game.Audio; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; +using osuTK.Graphics; + +namespace osu.Game.Tests.Gameplay +{ + [HeadlessTest] + public class TestSceneHitObjectAccentColour : OsuTestScene + { + private Container skinContainer; + + [SetUp] + public void Setup() => Schedule(() => Child = skinContainer = new SkinProvidingContainer(new TestSkin())); + + [Test] + public void TestChangeComboIndexBeforeLoad() + { + TestDrawableHitObject hitObject = null; + + AddStep("set combo and add hitobject", () => + { + hitObject = new TestDrawableHitObject(); + hitObject.HitObject.ComboIndex = 1; + + skinContainer.Add(hitObject); + }); + + AddAssert("combo colour is green", () => hitObject.AccentColour.Value == Color4.Green); + } + + [Test] + public void TestChangeComboIndexDuringLoad() + { + TestDrawableHitObject hitObject = null; + + AddStep("add hitobject and set combo", () => + { + skinContainer.Add(hitObject = new TestDrawableHitObject()); + hitObject.HitObject.ComboIndex = 1; + }); + + AddAssert("combo colour is green", () => hitObject.AccentColour.Value == Color4.Green); + } + + [Test] + public void TestChangeComboIndexAfterLoad() + { + TestDrawableHitObject hitObject = null; + + AddStep("add hitobject", () => skinContainer.Add(hitObject = new TestDrawableHitObject())); + AddAssert("combo colour is red", () => hitObject.AccentColour.Value == Color4.Red); + + AddStep("change combo", () => hitObject.HitObject.ComboIndex = 1); + AddAssert("combo colour is green", () => hitObject.AccentColour.Value == Color4.Green); + } + + private class TestDrawableHitObject : DrawableHitObject + { + public TestDrawableHitObject() + : base(new TestHitObjectWithCombo()) + { + } + } + + private class TestHitObjectWithCombo : HitObject, IHasComboInformation + { + public bool NewCombo { get; } = false; + public int ComboOffset { get; } = 0; + + public Bindable IndexInCurrentComboBindable { get; } = new Bindable(); + + public int IndexInCurrentCombo + { + get => IndexInCurrentComboBindable.Value; + set => IndexInCurrentComboBindable.Value = value; + } + + public Bindable ComboIndexBindable { get; } = new Bindable(); + + public int ComboIndex + { + get => ComboIndexBindable.Value; + set => ComboIndexBindable.Value = value; + } + + public Bindable LastInComboBindable { get; } = new Bindable(); + + public bool LastInCombo + { + get => LastInComboBindable.Value; + set => LastInComboBindable.Value = value; + } + } + + private class TestSkin : ISkin + { + public readonly List ComboColours = new List + { + Color4.Red, + Color4.Green + }; + + public Drawable GetDrawableComponent(ISkinComponent component) => throw new NotImplementedException(); + + public Texture GetTexture(string componentName) => throw new NotImplementedException(); + + public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException(); + + public IBindable GetConfig(TLookup lookup) + { + switch (lookup) + { + case GlobalSkinConfiguration global: + switch (global) + { + case GlobalSkinConfiguration.ComboColours: + return SkinUtils.As(new Bindable>(ComboColours)); + } + + break; + } + + throw new NotImplementedException(); + } + } + } +} diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 7f3bfd3b5c..0948452ceb 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -128,7 +128,7 @@ namespace osu.Game.Rulesets.Objects.Drawables if (HitObject is IHasComboInformation combo) { comboIndexBindable = combo.ComboIndexBindable.GetBoundCopy(); - comboIndexBindable.BindValueChanged(_ => updateAccentColour()); + comboIndexBindable.BindValueChanged(_ => updateAccentColour(), true); } updateState(ArmedState.Idle, true); From 31313ec9e134f0a26f7847267126d89175d6817f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 Oct 2019 17:56:31 +0900 Subject: [PATCH 3528/5608] Fix potential nullref --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index a51728ba88..1ec36a59a8 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -240,7 +240,8 @@ namespace osu.Game.Rulesets.Edit public void BeginPlacement(HitObject hitObject) { - hitObject.StartTime = GetSnappedTime(hitObject.StartTime, inputManager.CurrentState.Mouse.Position); + if (distanceSnapGrid != null) + hitObject.StartTime = GetSnappedTime(hitObject.StartTime, distanceSnapGrid.ToLocalSpace(inputManager.CurrentState.Mouse.Position)); } public void EndPlacement(HitObject hitObject) => EditorBeatmap.Add(hitObject); From 71d45d41d1f85125dfae1171e3b5a2f954f4053d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 Oct 2019 17:46:39 +0900 Subject: [PATCH 3529/5608] Add basic visualisation of different control point types --- .../ControlPoints/ControlPointInfo.cs | 6 + osu.Game/Screens/Edit/Timing/TimingScreen.cs | 133 +++++++++++++----- 2 files changed, 105 insertions(+), 34 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 855084ad02..68eb0ec6d1 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -36,6 +36,12 @@ namespace osu.Game.Beatmaps.ControlPoints [JsonProperty] public SortedList EffectPoints { get; private set; } = new SortedList(Comparer.Default); + public IReadOnlyList AllControlPoints => + TimingPoints + .Concat((IEnumerable)DifficultyPoints) + .Concat(SamplePoints) + .Concat(EffectPoints).ToArray(); + /// /// Finds the difficulty control point that is active at . /// diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index be7058ae08..97ec03e6dd 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -2,13 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Globalization; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Beatmaps; @@ -16,6 +16,7 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osuTK; namespace osu.Game.Screens.Edit.Timing { @@ -64,7 +65,7 @@ namespace osu.Game.Screens.Edit.Timing RelativeSizeAxes = Axes.Both, Child = new ControlPointTable { - ControlPoints = Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints + ControlPoints = Beatmap.Value.Beatmap.ControlPointInfo.AllControlPoints } } }; @@ -115,7 +116,7 @@ namespace osu.Game.Screens.Edit.Timing }); } - public IReadOnlyList ControlPoints + public IEnumerable ControlPoints { set { @@ -125,14 +126,15 @@ namespace osu.Game.Screens.Edit.Timing if (value?.Any() != true) return; - for (int i = 0; i < value.Count; i++) + var grouped = value.GroupBy(cp => cp.Time, cp => cp); + + foreach (var group in grouped) { - var cp = value[i]; - backgroundFlow.Add(new RowBackground { Action = () => controlPoint.Value = cp }); + backgroundFlow.Add(new RowBackground { Action = () => controlPoint.Value = group.First() }); } Columns = createHeaders(); - Content = value.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); + Content = grouped.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); } } @@ -141,41 +143,104 @@ namespace osu.Game.Screens.Edit.Timing var columns = new List { new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("offset", Anchor.Centre), - new TableColumn("BPM", Anchor.Centre), - new TableColumn("Meter", Anchor.Centre), - new TableColumn("Sample Set", Anchor.Centre), - new TableColumn("Volume", Anchor.Centre), + new TableColumn("time", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Attributes", Anchor.Centre), }; return columns.ToArray(); } - private Drawable[] createContent(int index, ControlPoint controlPoint) + private Drawable[] createContent(int index, IGrouping controlPoints) => new Drawable[] { - return new Drawable[] + new OsuSpriteText { - new OsuSpriteText + Text = $"#{index + 1}", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), + Margin = new MarginPadding(10) + }, + new OsuSpriteText + { + Text = $"{controlPoints.Key:n0}ms", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + ChildrenEnumerable = controlPoints.Select(createAttribute).Where(c => c != null), + Padding = new MarginPadding(10), + Spacing = new Vector2(10) + }, + }; + + private Drawable createAttribute(ControlPoint controlPoint) + { + if (controlPoint.AutoGenerated) + return null; + + switch (controlPoint) + { + case TimingControlPoint timing: + return new RowAttribute("timing", $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); + + case DifficultyControlPoint difficulty: + + return new RowAttribute("difficulty", $"{difficulty.SpeedMultiplier:n2}x"); + + case EffectControlPoint effect: + return new RowAttribute("effect", $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); + + case SampleControlPoint sample: + return new RowAttribute("sample", $"{sample.SampleBank} {sample.SampleVolume}%"); + } + + return null; + } + + private class RowAttribute : CompositeDrawable, IHasTooltip + { + private readonly string header; + private readonly string content; + + public RowAttribute(string header, string content) + { + this.header = header; + this.content = content; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AutoSizeAxes = Axes.X; + + Height = 20; + + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + + Masking = true; + CornerRadius = 5; + + InternalChildren = new Drawable[] { - Text = $"#{index + 1}", - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) - }, - new OsuSpriteText - { - Text = $"{controlPoint.Time}", - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) - }, - new OsuSpriteText - { - Text = $"{(controlPoint as TimingControlPoint)?.BeatLength.ToString(CultureInfo.InvariantCulture) ?? "-"}", - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) - }, - new OsuSpriteText - { - Text = $"{(controlPoint as TimingControlPoint)?.TimeSignature.ToString() ?? "-"}", - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) - }, - }; + new Box + { + Colour = colours.Yellow, + RelativeSizeAxes = Axes.Both, + }, + new OsuSpriteText + { + Padding = new MarginPadding(2), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.Default.With(weight: FontWeight.SemiBold, size: 12), + Text = header, + Colour = colours.Gray3 + }, + }; + } + + public string TooltipText => content; } protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty); From ffec960b77960b855f9e8b63fc2a9b4e90814d2a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 Oct 2019 17:59:54 +0900 Subject: [PATCH 3530/5608] Split out classes --- .../Screens/Edit/Timing/ControlPointTable.cs | 186 +++++++++++++++ osu.Game/Screens/Edit/Timing/RowAttribute.cs | 59 +++++ osu.Game/Screens/Edit/Timing/TimingScreen.cs | 219 ------------------ 3 files changed, 245 insertions(+), 219 deletions(-) create mode 100644 osu.Game/Screens/Edit/Timing/ControlPointTable.cs create mode 100644 osu.Game/Screens/Edit/Timing/RowAttribute.cs diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs new file mode 100644 index 0000000000..1ff88fb5b4 --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -0,0 +1,186 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osuTK; + +namespace osu.Game.Screens.Edit.Timing +{ + public class ControlPointTable : TableContainer + { + private const float horizontal_inset = 20; + private const float row_height = 25; + private const int text_size = 14; + + private readonly FillFlowContainer backgroundFlow; + + [Resolved] + private Bindable controlPoint { get; set; } + + public ControlPointTable() + { + 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, + Padding = new MarginPadding { Horizontal = -horizontal_inset }, + Margin = new MarginPadding { Top = row_height } + }); + } + + public IEnumerable ControlPoints + { + set + { + Content = null; + backgroundFlow.Clear(); + + if (value?.Any() != true) + return; + + var grouped = value.GroupBy(cp => cp.Time, cp => cp); + + foreach (var group in grouped) + { + backgroundFlow.Add(new RowBackground { Action = () => controlPoint.Value = group.First() }); + } + + Columns = createHeaders(); + Content = grouped.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); + } + } + + private TableColumn[] createHeaders() + { + var columns = new List + { + new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("time", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Attributes", Anchor.Centre), + }; + + return columns.ToArray(); + } + + private Drawable[] createContent(int index, IGrouping controlPoints) => new Drawable[] + { + new OsuSpriteText + { + Text = $"#{index + 1}", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), + Margin = new MarginPadding(10) + }, + new OsuSpriteText + { + Text = $"{controlPoints.Key:n0}ms", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + ChildrenEnumerable = controlPoints.Select(createAttribute).Where(c => c != null), + Padding = new MarginPadding(10), + Spacing = new Vector2(10) + }, + }; + + private Drawable createAttribute(ControlPoint controlPoint) + { + if (controlPoint.AutoGenerated) + return null; + + switch (controlPoint) + { + case TimingControlPoint timing: + return new RowAttribute("timing", $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); + + case DifficultyControlPoint difficulty: + + return new RowAttribute("difficulty", $"{difficulty.SpeedMultiplier:n2}x"); + + case EffectControlPoint effect: + return new RowAttribute("effect", $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); + + case SampleControlPoint sample: + return new RowAttribute("sample", $"{sample.SampleBank} {sample.SampleVolume}%"); + } + + return null; + } + + protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty); + + private class HeaderText : OsuSpriteText + { + public HeaderText(string text) + { + Text = text.ToUpper(); + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black); + } + } + + public class RowBackground : OsuClickableContainer + { + private const int fade_duration = 100; + + private readonly Box hoveredBackground; + + public RowBackground() + { + RelativeSizeAxes = Axes.X; + Height = 25; + + AlwaysPresent = true; + + CornerRadius = 3; + Masking = true; + + Children = new Drawable[] + { + hoveredBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + hoveredBackground.Colour = colours.Blue; + } + + protected override bool OnHover(HoverEvent e) + { + hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); + base.OnHoverLost(e); + } + } + } +} diff --git a/osu.Game/Screens/Edit/Timing/RowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttribute.cs new file mode 100644 index 0000000000..8716382142 --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/RowAttribute.cs @@ -0,0 +1,59 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Screens.Edit.Timing +{ + public class RowAttribute : CompositeDrawable, IHasTooltip + { + private readonly string header; + private readonly string content; + + public RowAttribute(string header, string content) + { + this.header = header; + this.content = content; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AutoSizeAxes = Axes.X; + + Height = 20; + + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + + Masking = true; + CornerRadius = 5; + + InternalChildren = new Drawable[] + { + new Box + { + Colour = colours.Yellow, + RelativeSizeAxes = Axes.Both, + }, + new OsuSpriteText + { + Padding = new MarginPadding(2), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.Default.With(weight: FontWeight.SemiBold, size: 12), + Text = header, + Colour = colours.Gray3 + }, + }; + } + + public string TooltipText => content; + } +} diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 97ec03e6dd..3dda57becc 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -1,22 +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 System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osuTK; namespace osu.Game.Screens.Edit.Timing { @@ -87,216 +80,4 @@ namespace osu.Game.Screens.Edit.Timing } } } - - public class ControlPointTable : TableContainer - { - private const float horizontal_inset = 20; - private const float row_height = 25; - private const int text_size = 14; - - private readonly FillFlowContainer backgroundFlow; - - [Resolved] - private Bindable controlPoint { get; set; } - - public ControlPointTable() - { - 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, - Padding = new MarginPadding { Horizontal = -horizontal_inset }, - Margin = new MarginPadding { Top = row_height } - }); - } - - public IEnumerable ControlPoints - { - set - { - Content = null; - backgroundFlow.Clear(); - - if (value?.Any() != true) - return; - - var grouped = value.GroupBy(cp => cp.Time, cp => cp); - - foreach (var group in grouped) - { - backgroundFlow.Add(new RowBackground { Action = () => controlPoint.Value = group.First() }); - } - - Columns = createHeaders(); - Content = grouped.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); - } - } - - private TableColumn[] createHeaders() - { - var columns = new List - { - new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("time", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("Attributes", Anchor.Centre), - }; - - return columns.ToArray(); - } - - private Drawable[] createContent(int index, IGrouping controlPoints) => new Drawable[] - { - new OsuSpriteText - { - Text = $"#{index + 1}", - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), - Margin = new MarginPadding(10) - }, - new OsuSpriteText - { - Text = $"{controlPoints.Key:n0}ms", - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - ChildrenEnumerable = controlPoints.Select(createAttribute).Where(c => c != null), - Padding = new MarginPadding(10), - Spacing = new Vector2(10) - }, - }; - - private Drawable createAttribute(ControlPoint controlPoint) - { - if (controlPoint.AutoGenerated) - return null; - - switch (controlPoint) - { - case TimingControlPoint timing: - return new RowAttribute("timing", $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); - - case DifficultyControlPoint difficulty: - - return new RowAttribute("difficulty", $"{difficulty.SpeedMultiplier:n2}x"); - - case EffectControlPoint effect: - return new RowAttribute("effect", $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); - - case SampleControlPoint sample: - return new RowAttribute("sample", $"{sample.SampleBank} {sample.SampleVolume}%"); - } - - return null; - } - - private class RowAttribute : CompositeDrawable, IHasTooltip - { - private readonly string header; - private readonly string content; - - public RowAttribute(string header, string content) - { - this.header = header; - this.content = content; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - AutoSizeAxes = Axes.X; - - Height = 20; - - Anchor = Anchor.CentreLeft; - Origin = Anchor.CentreLeft; - - Masking = true; - CornerRadius = 5; - - InternalChildren = new Drawable[] - { - new Box - { - Colour = colours.Yellow, - RelativeSizeAxes = Axes.Both, - }, - new OsuSpriteText - { - Padding = new MarginPadding(2), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.Default.With(weight: FontWeight.SemiBold, size: 12), - Text = header, - Colour = colours.Gray3 - }, - }; - } - - public string TooltipText => content; - } - - protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty); - - private class HeaderText : OsuSpriteText - { - public HeaderText(string text) - { - Text = text.ToUpper(); - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black); - } - } - - public class RowBackground : OsuClickableContainer - { - private const int fade_duration = 100; - - private readonly Box hoveredBackground; - - public RowBackground() - { - RelativeSizeAxes = Axes.X; - Height = 25; - - AlwaysPresent = true; - - CornerRadius = 3; - Masking = true; - - Children = new Drawable[] - { - hoveredBackground = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - }, - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - hoveredBackground.Colour = colours.Blue; - } - - protected override bool OnHover(HoverEvent e) - { - hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); - base.OnHoverLost(e); - } - } - } } From 07286c0cfc106dfd49fb8370bfe5490ed2bb597f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 Oct 2019 18:21:53 +0900 Subject: [PATCH 3531/5608] Fix editor's clock not being processed unless composer is loaded --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 3 ++- osu.Game/Screens/Edit/Editor.cs | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index a267d7c44d..038d6a320a 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -57,7 +57,8 @@ namespace osu.Game.Rulesets.Edit { drawableRulesetWrapper = new DrawableEditRulesetWrapper(CreateDrawableRuleset(Ruleset, workingBeatmap, Array.Empty())) { - Clock = framedClock + Clock = framedClock, + ProcessCustomClock = false }; } catch (Exception e) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 7f08c2f8b9..35408e4003 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -173,6 +173,12 @@ namespace osu.Game.Screens.Edit bottomBackground.Colour = colours.Gray2; } + protected override void Update() + { + base.Update(); + clock.ProcessFrame(); + } + protected override bool OnKeyDown(KeyDownEvent e) { switch (e.Key) From 5dd5a070e073779743e8b2862ef9b9dd18aa8598 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 Oct 2019 18:44:58 +0900 Subject: [PATCH 3532/5608] Show placement grid from hitobjects at the current time --- osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index a5590a999d..fcf2772219 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Osu.Edit if (objects.Count == 0) { - var lastObject = EditorBeatmap.HitObjects.LastOrDefault(h => h.StartTime < EditorClock.CurrentTime); + var lastObject = EditorBeatmap.HitObjects.LastOrDefault(h => h.StartTime <= EditorClock.CurrentTime); if (lastObject == null) return null; From 190a83da6ec098031c5a879976d28eb585a8a726 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 Oct 2019 19:04:08 +0900 Subject: [PATCH 3533/5608] Refresh the grid after a placement --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 1ec36a59a8..c769ccae41 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -244,7 +244,11 @@ namespace osu.Game.Rulesets.Edit hitObject.StartTime = GetSnappedTime(hitObject.StartTime, distanceSnapGrid.ToLocalSpace(inputManager.CurrentState.Mouse.Position)); } - public void EndPlacement(HitObject hitObject) => EditorBeatmap.Add(hitObject); + public void EndPlacement(HitObject hitObject) + { + EditorBeatmap.Add(hitObject); + showGridFor(Enumerable.Empty()); + } public void Delete(HitObject hitObject) => EditorBeatmap.Remove(hitObject); From ca957f0994cd8e459231ecde6085d939eca2d094 Mon Sep 17 00:00:00 2001 From: HoLLy Date: Sat, 19 Oct 2019 11:52:07 +0200 Subject: [PATCH 3534/5608] Hide gameplay cursor when resume overlay is shown --- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 908ad1ce49..3d3e0fe49a 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -39,6 +39,7 @@ namespace osu.Game.Rulesets.Osu.UI public override void Show() { base.Show(); + GameplayCursor.ActiveCursor.Hide(); cursorScaleContainer.MoveTo(GameplayCursor.ActiveCursor.Position); clickToResumeCursor.Appear(); @@ -54,6 +55,7 @@ namespace osu.Game.Rulesets.Osu.UI { localCursorContainer?.Expire(); localCursorContainer = null; + GameplayCursor.ActiveCursor.Show(); base.Hide(); } From 68837d47df136a9ac8a9b1af9fb68bc62b2576ce Mon Sep 17 00:00:00 2001 From: HoLLy Date: Sat, 19 Oct 2019 12:15:31 +0200 Subject: [PATCH 3535/5608] Use local bindable instead of using BindValueChanged of external one --- .../UI/Cursor/OsuCursorContainer.cs | 13 ++++++------- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 8 ++++++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 52e2e493d5..6433ced624 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -29,8 +29,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly Drawable cursorTrail; - public IBindable CursorScale => cursorScale; - private Bindable cursorScale; + public Bindable CursorScale; private Bindable userCursorScale; private Bindable autoCursorScale; private readonly IBindable beatmap = new Bindable(); @@ -58,8 +57,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor autoCursorScale = config.GetBindable(OsuSetting.AutoCursorSize); autoCursorScale.ValueChanged += _ => calculateScale(); - cursorScale = new Bindable(); - cursorScale.ValueChanged += e => ActiveCursor.Scale = cursorTrail.Scale = new Vector2(e.NewValue); + CursorScale = new Bindable(); + CursorScale.ValueChanged += e => ActiveCursor.Scale = cursorTrail.Scale = new Vector2(e.NewValue); calculateScale(); } @@ -74,7 +73,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor scale *= 1f - 0.7f * (1f + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY; } - cursorScale.Value = scale; + CursorScale.Value = scale; } protected override void LoadComplete() @@ -130,13 +129,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor protected override void PopIn() { fadeContainer.FadeTo(1, 300, Easing.OutQuint); - ActiveCursor.ScaleTo(cursorScale.Value, 400, Easing.OutQuint); + ActiveCursor.ScaleTo(CursorScale.Value, 400, Easing.OutQuint); } protected override void PopOut() { fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint); - ActiveCursor.ScaleTo(cursorScale.Value * 0.8f, 450, Easing.OutQuint); + ActiveCursor.ScaleTo(CursorScale.Value * 0.8f, 450, Easing.OutQuint); } private class DefaultCursorTrail : CursorTrail diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 3d3e0fe49a..8347d255fa 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -1,8 +1,9 @@ -// 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; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -21,6 +22,7 @@ namespace osu.Game.Rulesets.Osu.UI private OsuClickToResumeCursor clickToResumeCursor; private OsuCursorContainer localCursorContainer; + private Bindable localCursorScale; public override CursorContainer LocalCursor => State.Value == Visibility.Visible ? localCursorContainer : null; @@ -47,7 +49,9 @@ namespace osu.Game.Rulesets.Osu.UI { Add(localCursorContainer = new OsuCursorContainer()); - localCursorContainer.CursorScale.BindValueChanged(scale => cursorScaleContainer.Scale = new Vector2(scale.NewValue), true); + localCursorScale = new Bindable(); + localCursorScale.BindTo(localCursorContainer.CursorScale); + localCursorScale.BindValueChanged(scale => cursorScaleContainer.Scale = new Vector2(scale.NewValue), true); } } From 7dc65ec9645e71bd790f5e157bf757ebfd6748c4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 20 Oct 2019 23:32:49 +0900 Subject: [PATCH 3536/5608] Add missing required types --- osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs index be84ae2cf9..54dcdc8da5 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Rulesets.Osu; @@ -11,6 +13,12 @@ namespace osu.Game.Tests.Visual.Editor [TestFixture] public class TestSceneTimingScreen : EditorClockTestScene { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ControlPointTable), + typeof(RowAttribute) + }; + [BackgroundDependencyLoader] private void load() { From 0fbba9a5e5c875f63a1e4afc7181aa4ee41895cf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 20 Oct 2019 23:42:13 +0900 Subject: [PATCH 3537/5608] Split out more classes --- .../Visual/Editor/TestSceneTimingScreen.cs | 1 + .../Edit/Timing/ControlPointSettings.cs | 26 +++++++++++++++++++ osu.Game/Screens/Edit/Timing/TimingScreen.cs | 15 ----------- 3 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 osu.Game/Screens/Edit/Timing/ControlPointSettings.cs diff --git a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs index 54dcdc8da5..3e227169e0 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs @@ -16,6 +16,7 @@ namespace osu.Game.Tests.Visual.Editor public override IReadOnlyList RequiredTypes => new[] { typeof(ControlPointTable), + typeof(ControlPointSettings), typeof(RowAttribute) }; diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs new file mode 100644 index 0000000000..2feced9738 --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; + +namespace osu.Game.Screens.Edit.Timing +{ + public class ControlPointSettings : CompositeDrawable + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + RelativeSizeAxes = Axes.Both; + + InternalChild = new Box + { + Colour = colours.Gray3, + RelativeSizeAxes = Axes.Both, + }; + } + } +} diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 3dda57becc..9cbba6b155 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -64,20 +64,5 @@ namespace osu.Game.Screens.Edit.Timing }; } } - - public class ControlPointSettings : CompositeDrawable - { - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - RelativeSizeAxes = Axes.Both; - - InternalChild = new Box - { - Colour = colours.Gray3, - RelativeSizeAxes = Axes.Both, - }; - } - } } } From 80bf68c1081ed4dc90f1cc5c99c7810e8e34e597 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Oct 2019 00:06:38 +0900 Subject: [PATCH 3538/5608] Add control sections and hook up bindable control groups --- .../Edit/Timing/ControlPointSettings.cs | 130 +++++++++++++++++- .../Screens/Edit/Timing/ControlPointTable.cs | 4 +- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 3 +- 3 files changed, 131 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index 2feced9738..dc4fb2a338 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -1,11 +1,20 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Edit.Timing { @@ -16,11 +25,126 @@ namespace osu.Game.Screens.Edit.Timing { RelativeSizeAxes = Axes.Both; - InternalChild = new Box + InternalChildren = new Drawable[] { - Colour = colours.Gray3, - RelativeSizeAxes = Axes.Both, + new Box + { + Colour = colours.Gray3, + RelativeSizeAxes = Axes.Both, + }, + new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(30), + Children = createSections() + }, + } }; } + + private IReadOnlyList createSections() => new Drawable[] + { + new TimingSection(), + new DifficultySection(), + new SampleSection(), + new EffectSection(), + }; + + private class TimingSection : Section + { + } + + private class DifficultySection : Section + { + } + + private class SampleSection : Section + { + } + + private class EffectSection : Section + { + } + + private class Section : Container + where T : ControlPoint + { + private const float header_height = 20; + + protected override Container Content { get; } + + [Resolved] + private Bindable> selectedPoints { get; set; } + + protected Section() + { + RelativeSizeAxes = Axes.X; + AutoSizeDuration = 200; + AutoSizeEasing = Easing.OutQuint; + AutoSizeAxes = Axes.Y; + + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + Colour = Color4.Gray, + RelativeSizeAxes = Axes.Both, + }, + new Container + { + RelativeSizeAxes = Axes.X, + Height = header_height, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = typeof(T).Name.Replace(typeof(ControlPoint).Name, string.Empty) + }, + } + }, + Content = new Container() + { + Y = header_height, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Box + { + Colour = Color4.DarkGray, + RelativeSizeAxes = Axes.X, + Height = 100, + }, + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + selectedPoints.BindValueChanged(points => + { + var matching = points.NewValue?.OfType().Where(p => !p.AutoGenerated).FirstOrDefault(); + + if (matching != null) + { + Content.BypassAutoSizeAxes = Axes.None; + } + else + { + Content.BypassAutoSizeAxes = Axes.Y; + } + }, true); + } + } } } diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 1ff88fb5b4..5032e71fe8 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Edit.Timing private readonly FillFlowContainer backgroundFlow; [Resolved] - private Bindable controlPoint { get; set; } + private Bindable> selectedPoints { get; set; } public ControlPointTable() { @@ -60,7 +60,7 @@ namespace osu.Game.Screens.Edit.Timing foreach (var group in grouped) { - backgroundFlow.Add(new RowBackground { Action = () => controlPoint.Value = group.First() }); + backgroundFlow.Add(new RowBackground { Action = () => selectedPoints.Value = group }); } Columns = createHeaders(); diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 9cbba6b155..5da5d3f785 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.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.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -16,7 +17,7 @@ namespace osu.Game.Screens.Edit.Timing public class TimingScreen : EditorScreenWithTimeline { [Cached] - private readonly Bindable controlPoint = new Bindable(); + private Bindable> selectedPoints = new Bindable>(); protected override Drawable CreateMainContent() => new GridContainer { From aa910fb51970a77c3bfaa8db12d2b3028380ad80 Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 20 Oct 2019 21:11:16 +0200 Subject: [PATCH 3539/5608] Revert "Load the rulesets lasily" This reverts commit 42d1379848fa03611cda80eb2336838ddf3165d3. --- osu.Game/Rulesets/RulesetStore.cs | 95 +++++++++++++++---------------- 1 file changed, 46 insertions(+), 49 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 97a90bf824..47aad43966 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -16,11 +16,17 @@ namespace osu.Game.Rulesets /// public class RulesetStore : DatabaseBackedStore { - private static readonly Lazy> loaded_assemblies = new Lazy>(() => loadRulesets()); + private static readonly Dictionary loaded_assemblies = new Dictionary(); static RulesetStore() { AppDomain.CurrentDomain.AssemblyResolve += currentDomain_AssemblyResolve; + + // On android in release configuration assemblies are loaded from the apk directly into memory. + // We cannot read assemblies from cwd, so should check loaded assemblies instead. + loadFromAppDomain(); + + loadFromDisk(); } public RulesetStore(IDatabaseContextFactory factory) @@ -48,7 +54,7 @@ namespace osu.Game.Rulesets /// public IEnumerable AvailableRulesets { get; private set; } - private static Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args) => loaded_assemblies.Value.Keys.FirstOrDefault(a => a.FullName == args.Name); + private static Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args) => loaded_assemblies.Keys.FirstOrDefault(a => a.FullName == args.Name); private const string ruleset_library_prefix = "osu.Game.Rulesets"; @@ -58,7 +64,7 @@ namespace osu.Game.Rulesets { var context = usage.Context; - var instances = loaded_assemblies.Value.Values.Select(r => (Ruleset)Activator.CreateInstance(r, (RulesetInfo)null)).ToList(); + var instances = loaded_assemblies.Values.Select(r => (Ruleset)Activator.CreateInstance(r, (RulesetInfo)null)).ToList(); //add all legacy modes in correct order foreach (var r in instances.Where(r => r.LegacyID != null).OrderBy(r => r.LegacyID)) @@ -107,39 +113,8 @@ namespace osu.Game.Rulesets } } - /// - /// Loads the rulesets that are in the current appdomain an in the current directory. - /// - /// The rulesets that were loaded. - private static Dictionary loadRulesets() + private static void loadFromAppDomain() { - var rulesets = new Dictionary(); - - foreach (var rulesetAssembly in getRulesetAssemblies()) - { - try - { - rulesets[rulesetAssembly] = rulesetAssembly.GetTypes().First(t => t.IsPublic && t.IsSubclassOf(typeof(Ruleset))); - } - catch (Exception e) - { - Logger.Error(e, $"Failed to add ruleset {rulesetAssembly}"); - } - } - - return rulesets; - } - - /// - /// Scans the current appdomain and current directory for ruleset assemblies. - /// Rulesets that were found in the current directory are automaticly loaded. - /// - /// The ruleset assemblies that were found in the current appdomain or in the current directory. - private static IEnumerable getRulesetAssemblies() - { - var rulesetAssemblies = new HashSet(); - - // load from appdomain foreach (var ruleset in AppDomain.CurrentDomain.GetAssemblies()) { string rulesetName = ruleset.GetName().Name; @@ -147,33 +122,55 @@ namespace osu.Game.Rulesets if (!rulesetName.StartsWith(ruleset_library_prefix, StringComparison.InvariantCultureIgnoreCase) || ruleset.GetName().Name.Contains("Tests")) continue; - rulesetAssemblies.Add(ruleset); + addRuleset(ruleset); } + } - // load from current directory + private static void loadFromDisk() + { try { string[] files = Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll"); foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests"))) - { - try - { - rulesetAssemblies.Add(Assembly.LoadFrom(file)); - } - catch (Exception e) - { - Logger.Error(e, $"Failed to load ruleset assembly {Path.GetFileNameWithoutExtension(file)}"); - return null; - } - } + loadRulesetFromFile(file); } catch (Exception e) { Logger.Error(e, $"Could not load rulesets from directory {Environment.CurrentDirectory}"); } + } - return rulesetAssemblies; + private static void loadRulesetFromFile(string file) + { + var filename = Path.GetFileNameWithoutExtension(file); + + if (loaded_assemblies.Values.Any(t => t.Namespace == filename)) + return; + + try + { + addRuleset(Assembly.LoadFrom(file)); + } + catch (Exception e) + { + Logger.Error(e, $"Failed to load ruleset {filename}"); + } + } + + private static void addRuleset(Assembly assembly) + { + if (loaded_assemblies.ContainsKey(assembly)) + return; + + try + { + loaded_assemblies[assembly] = assembly.GetTypes().First(t => t.IsPublic && t.IsSubclassOf(typeof(Ruleset))); + } + catch (Exception e) + { + Logger.Error(e, $"Failed to add ruleset {assembly}"); + } } } } From 6e32557be3d36f8c867e95d1f7527fcc2bbb95ca Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 20 Oct 2019 22:29:29 +0200 Subject: [PATCH 3540/5608] Fix spelling error --- osu.Android/OsuGameActivity.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index 41531617af..2e5fa59d20 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.cs @@ -18,7 +18,7 @@ namespace osu.Android { // The default current directory on android is '/'. // On some devices '/' maps to the app data directory. On others it maps to the root of the internal storage. - // In order to have a consitend current directory on all devices the full path of the app data directory is set as the current directory. + // In order to have a consistent current directory on all devices the full path of the app data directory is set as the current directory. System.Environment.CurrentDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); base.OnCreate(savedInstanceState); From dc222b5e4d00b3eac3d6e46405731e2b1050642b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 21 Oct 2019 13:52:02 +0900 Subject: [PATCH 3541/5608] Add common path for duplicated code --- .../Objects/Drawables/DrawableHitObject.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 156d4178e2..b472c880c0 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -154,11 +154,7 @@ namespace osu.Game.Rulesets.Objects.Drawables { var drawableNested = CreateNestedHitObject(h) ?? throw new InvalidOperationException($"{nameof(CreateNestedHitObject)} returned null for {h.GetType().ReadableName()}."); - drawableNested.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); - drawableNested.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); - drawableNested.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); - - nestedHitObjects.Value.Add(drawableNested); + addNested(drawableNested); AddNestedHitObject(drawableNested); } } @@ -176,14 +172,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// [Obsolete("Use AddNestedHitObject() / ClearNestedHitObjects() / CreateNestedHitObject() instead.")] // can be removed 20200417 - protected virtual void AddNested(DrawableHitObject h) - { - h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); - h.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); - h.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); - - nestedHitObjects.Value.Add(h); - } + protected virtual void AddNested(DrawableHitObject h) => addNested(h); /// /// Invoked by the base to remove all previously-added nested s. @@ -199,6 +188,17 @@ namespace osu.Game.Rulesets.Objects.Drawables /// The drawable representation for . protected virtual DrawableHitObject CreateNestedHitObject(HitObject hitObject) => null; + private void addNested(DrawableHitObject hitObject) + { + // Todo: Exists for legacy purposes, can be removed 20200417 + + hitObject.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); + hitObject.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); + hitObject.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); + + nestedHitObjects.Value.Add(hitObject); + } + #region State / Transform Management /// From 74b6e691d82631c6f2ad8edc73db42d2490c748f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 21 Oct 2019 14:01:52 +0900 Subject: [PATCH 3542/5608] Remove unnecessary schedule --- .../Compose/Components/BlueprintContainer.cs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index cb3d3b71fc..2de5ecf633 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -123,20 +123,12 @@ namespace osu.Game.Screens.Edit.Compose.Components if (blueprint == null) return; - if (hitObject.IsLoaded) - addBlueprint(); - else - hitObject.OnLoadComplete += _ => addBlueprint(); + blueprint.Selected += onBlueprintSelected; + blueprint.Deselected += onBlueprintDeselected; + blueprint.SelectionRequested += onSelectionRequested; + blueprint.DragRequested += onDragRequested; - void addBlueprint() - { - blueprint.Selected += onBlueprintSelected; - blueprint.Deselected += onBlueprintDeselected; - blueprint.SelectionRequested += onSelectionRequested; - blueprint.DragRequested += onDragRequested; - - selectionBlueprints.Add(blueprint); - } + selectionBlueprints.Add(blueprint); } private void removeBlueprintFor(DrawableHitObject hitObject) => removeBlueprintFor(hitObject.HitObject); From fc7e4680a763d6cfeb1a615919be6b29400de3df Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 21 Oct 2019 14:08:28 +0900 Subject: [PATCH 3543/5608] Split on multiple lines --- .../Screens/Edit/Compose/Components/BlueprintContainer.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 3bb4266563..039e324e4b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -191,7 +191,13 @@ namespace osu.Game.Screens.Edit.Compose.Components } } - private void updatePlacementPosition(Vector2 screenSpacePosition) => currentPlacement.UpdatePosition(ToScreenSpace(composer.GetSnappedPosition(ToLocalSpace(screenSpacePosition)))); + private void updatePlacementPosition(Vector2 screenSpacePosition) + { + Vector2 snappedGridPosition = composer.GetSnappedPosition(ToLocalSpace(screenSpacePosition)); + Vector2 snappedScreenSpacePosition = ToScreenSpace(snappedGridPosition); + + currentPlacement.UpdatePosition(snappedScreenSpacePosition); + } /// /// Select all masks in a given rectangle selection area. From 96649e0a6a8d803cfdb68bce00f403ceaf59b83d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 21 Oct 2019 15:03:49 +0900 Subject: [PATCH 3544/5608] Fix selection blueprints not respecting stacking --- .../TestSceneHitCircleSelectionBlueprint.cs | 7 +++++++ osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs index d4cdabdb07..cf24306623 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs @@ -52,6 +52,13 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("blueprint positioned over hitobject", () => blueprint.CirclePiece.Position == hitCircle.Position); } + [Test] + public void TestStackedHitObject() + { + AddStep("set stacking", () => hitCircle.StackHeight = 5); + AddAssert("blueprint positioned over hitobject", () => blueprint.CirclePiece.Position == hitCircle.StackedPosition); + } + private class TestBlueprint : HitCircleSelectionBlueprint { public new HitCirclePiece CirclePiece => base.CirclePiece; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs index 95e926fdfa..b9c77d3f56 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints /// The to reference properties from. public virtual void UpdateFrom(T hitObject) { - Position = hitObject.Position; + Position = hitObject.StackedPosition; } } } From 5f8d46f66628e9499ea424f811178e57de7406aa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 21 Oct 2019 16:15:41 +0900 Subject: [PATCH 3545/5608] Fix sliders not moving with stacking change --- osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs | 15 +++++++++++++++ .../TestSceneSliderSelectionBlueprint.cs | 9 ++++++++- .../Objects/Drawables/DrawableSlider.cs | 3 +++ osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 10 ++++++++++ osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 ++ 5 files changed, 38 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 6a4201f84d..4893ebfdd4 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -111,6 +111,21 @@ namespace osu.Game.Rulesets.Osu.Tests AddStep("Distance Overflow 1 Repeat", () => SetContents(() => testDistanceOverflow(1))); } + [Test] + public void TestChangeStackHeight() + { + DrawableSlider slider = null; + + AddStep("create slider", () => + { + slider = (DrawableSlider)createSlider(repeats: 1); + Add(slider); + }); + + AddStep("change stack height", () => slider.HitObject.StackHeight = 10); + AddAssert("body positioned correctly", () => slider.Position == slider.HitObject.StackedPosition); + } + private Drawable testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats); private Drawable testSimpleBigLargeStackOffset(int repeats = 0) => createSlider(2, repeats: repeats, stackHeight: 10); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs index ec23ec31b2..5df0b70f12 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs @@ -78,6 +78,13 @@ namespace osu.Game.Rulesets.Osu.Tests checkPositions(); } + [Test] + public void TestStackedHitObject() + { + AddStep("set stacking", () => slider.StackHeight = 5); + checkPositions(); + } + private void moveHitObject() { AddStep("move hitobject", () => @@ -88,7 +95,7 @@ namespace osu.Game.Rulesets.Osu.Tests private void checkPositions() { - AddAssert("body positioned correctly", () => blueprint.BodyPiece.Position == slider.Position); + AddAssert("body positioned correctly", () => blueprint.BodyPiece.Position == slider.StackedPosition); AddAssert("head positioned correctly", () => Precision.AlmostEquals(blueprint.HeadBlueprint.CirclePiece.ScreenSpaceDrawQuad.Centre, drawableObject.HeadCircle.ScreenSpaceDrawQuad.Centre)); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 9e8ad9851c..c0b0db0e99 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -31,6 +31,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public readonly SliderBall Ball; private readonly IBindable positionBindable = new Bindable(); + private readonly IBindable stackHeightBindable = new Bindable(); private readonly IBindable scaleBindable = new Bindable(); private readonly IBindable pathBindable = new Bindable(); @@ -108,6 +109,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables config?.BindWith(OsuRulesetSetting.SnakingOutSliders, Body.SnakingOut); positionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); + stackHeightBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); scaleBindable.BindValueChanged(scale => { updatePathRadius(); @@ -115,6 +117,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }); positionBindable.BindTo(HitObject.PositionBindable); + stackHeightBindable.BindTo(HitObject.StackHeightBindable); scaleBindable.BindTo(HitObject.ScaleBindable); pathBindable.BindTo(slider.PathBindable); diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index b506c1f918..0ba712a83f 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; @@ -98,6 +99,15 @@ namespace osu.Game.Rulesets.Osu.Objects set => LastInComboBindable.Value = value; } + protected OsuHitObject() + { + StackHeightBindable.BindValueChanged(height => + { + foreach (var nested in NestedHitObjects.OfType()) + nested.StackHeight = height.NewValue; + }); + } + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index d98d72331a..010bf072e8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -163,6 +163,7 @@ namespace osu.Game.Rulesets.Osu.Objects { StartTime = e.Time, Position = Position, + StackHeight = StackHeight, Samples = getNodeSamples(0), SampleControlPoint = SampleControlPoint, }); @@ -176,6 +177,7 @@ namespace osu.Game.Rulesets.Osu.Objects { StartTime = e.Time, Position = EndPosition, + StackHeight = StackHeight }); break; From 38c2c328ff8586d85c03e389747cdac9f5a43f1d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 21 Oct 2019 17:04:56 +0900 Subject: [PATCH 3546/5608] Rename HitObject -> DrawableObject in selection blueprints --- .../Blueprints/HoldNoteSelectionBlueprint.cs | 16 ++++++++-------- .../Edit/Blueprints/ManiaSelectionBlueprint.cs | 16 ++++++++-------- .../Edit/Blueprints/NoteSelectionBlueprint.cs | 2 +- .../Edit/ManiaSelectionHandler.cs | 14 +++++++------- .../Edit/Masks/ManiaSelectionBlueprint.cs | 4 ++-- .../TestSceneHitCircleSelectionBlueprint.cs | 4 ++-- .../HitCircles/HitCircleSelectionBlueprint.cs | 4 ++-- .../Edit/Blueprints/OsuSelectionBlueprint.cs | 6 +++--- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 18 +++++++++--------- .../Compose/Components/BlueprintContainer.cs | 4 ++-- .../Compose/Components/MoveSelectionEvent.cs | 2 +- .../Compose/Components/SelectionHandler.cs | 4 ++-- 12 files changed, 47 insertions(+), 47 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs index 3169a8c036..3a9eb1f043 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { public class HoldNoteSelectionBlueprint : ManiaSelectionBlueprint { - public new DrawableHoldNote HitObject => (DrawableHoldNote)base.HitObject; + public new DrawableHoldNote DrawableObject => (DrawableHoldNote)base.DrawableObject; private readonly IBindable direction = new Bindable(); @@ -40,8 +40,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints InternalChildren = new Drawable[] { - new HoldNoteNoteSelectionBlueprint(HitObject.Head), - new HoldNoteNoteSelectionBlueprint(HitObject.Tail), + new HoldNoteNoteSelectionBlueprint(DrawableObject.Head), + new HoldNoteNoteSelectionBlueprint(DrawableObject.Tail), new BodyPiece { AccentColour = Color4.Transparent, @@ -54,13 +54,13 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); - Size = HitObject.DrawSize + new Vector2(0, HitObject.Tail.DrawHeight); + Size = DrawableObject.DrawSize + new Vector2(0, DrawableObject.Tail.DrawHeight); // This is a side-effect of not matching the hitobject's anchors/origins, which is kinda hard to do // When scrolling upwards our origin is already at the top of the head note (which is the intended location), // but when scrolling downwards our origin is at the _bottom_ of the tail note (where we need to be at the _top_ of the tail note) if (direction.Value == ScrollingDirection.Down) - Y -= HitObject.Tail.DrawHeight; + Y -= DrawableObject.Tail.DrawHeight; } public override Quad SelectionQuad => ScreenSpaceDrawQuad; @@ -77,10 +77,10 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); - Anchor = HitObject.Anchor; - Origin = HitObject.Origin; + Anchor = DrawableObject.Anchor; + Origin = DrawableObject.Origin; - Position = HitObject.DrawPosition; + Position = DrawableObject.DrawPosition; } // Todo: This is temporary, since the note masks don't do anything special yet. In the future they will handle input. diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index cc50459a0c..3bd7fb2d49 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints public Vector2 ScreenSpaceDragPosition { get; private set; } public Vector2 DragPosition { get; private set; } - public new DrawableManiaHitObject HitObject => (DrawableManiaHitObject)base.HitObject; + public new DrawableManiaHitObject DrawableObject => (DrawableManiaHitObject)base.DrawableObject; protected IClock EditorClock { get; private set; } @@ -28,8 +28,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints [Resolved] private IManiaHitObjectComposer composer { get; set; } - public ManiaSelectionBlueprint(DrawableHitObject hitObject) - : base(hitObject) + public ManiaSelectionBlueprint(DrawableHitObject drawableObject) + : base(drawableObject) { RelativeSizeAxes = Axes.None; } @@ -44,13 +44,13 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); - Position = Parent.ToLocalSpace(HitObject.ToScreenSpace(Vector2.Zero)); + Position = Parent.ToLocalSpace(DrawableObject.ToScreenSpace(Vector2.Zero)); } protected override bool OnMouseDown(MouseDownEvent e) { ScreenSpaceDragPosition = e.ScreenSpaceMousePosition; - DragPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); + DragPosition = DrawableObject.ToLocalSpace(e.ScreenSpaceMousePosition); return base.OnMouseDown(e); } @@ -60,20 +60,20 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints var result = base.OnDrag(e); ScreenSpaceDragPosition = e.ScreenSpaceMousePosition; - DragPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); + DragPosition = DrawableObject.ToLocalSpace(e.ScreenSpaceMousePosition); return result; } public override void Show() { - HitObject.AlwaysAlive = true; + DrawableObject.AlwaysAlive = true; base.Show(); } public override void Hide() { - HitObject.AlwaysAlive = false; + DrawableObject.AlwaysAlive = false; base.Hide(); } } diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs index d345b14e84..b83c4aa9aa 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); - Size = HitObject.DrawSize; + Size = DrawableObject.DrawSize; } } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 2fba0639da..732231b0d9 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Mania.Edit public override void HandleMovement(MoveSelectionEvent moveEvent) { var maniaBlueprint = (ManiaSelectionBlueprint)moveEvent.Blueprint; - int lastColumn = maniaBlueprint.HitObject.HitObject.Column; + int lastColumn = maniaBlueprint.DrawableObject.HitObject.Column; adjustOrigins(maniaBlueprint); performDragMovement(moveEvent); @@ -48,19 +48,19 @@ namespace osu.Game.Rulesets.Mania.Edit /// The that received the drag event. private void adjustOrigins(ManiaSelectionBlueprint reference) { - var referenceParent = (HitObjectContainer)reference.HitObject.Parent; + var referenceParent = (HitObjectContainer)reference.DrawableObject.Parent; - float offsetFromReferenceOrigin = reference.DragPosition.Y - reference.HitObject.OriginPosition.Y; + float offsetFromReferenceOrigin = reference.DragPosition.Y - reference.DrawableObject.OriginPosition.Y; float targetPosition = referenceParent.ToLocalSpace(reference.ScreenSpaceDragPosition).Y - offsetFromReferenceOrigin; // Flip the vertical coordinate space when scrolling downwards if (scrollingInfo.Direction.Value == ScrollingDirection.Down) targetPosition = targetPosition - referenceParent.DrawHeight; - float movementDelta = targetPosition - reference.HitObject.Position.Y; + float movementDelta = targetPosition - reference.DrawableObject.Position.Y; foreach (var b in SelectedBlueprints.OfType()) - b.HitObject.Y += movementDelta; + b.DrawableObject.Y += movementDelta; } private void performDragMovement(MoveSelectionEvent moveEvent) @@ -70,11 +70,11 @@ namespace osu.Game.Rulesets.Mania.Edit // When scrolling downwards the anchor position is at the bottom of the screen, however the movement event assumes the anchor is at the top of the screen. // This causes the delta to assume a positive hitobject position, and which can be corrected for by subtracting the parent height. if (scrollingInfo.Direction.Value == ScrollingDirection.Down) - delta -= moveEvent.Blueprint.HitObject.Parent.DrawHeight; + delta -= moveEvent.Blueprint.DrawableObject.Parent.DrawHeight; foreach (var b in SelectedBlueprints) { - var hitObject = b.HitObject; + var hitObject = b.DrawableObject; var objectParent = (HitObjectContainer)hitObject.Parent; // StartTime could be used to adjust the position if only one movement event was received per frame. diff --git a/osu.Game.Rulesets.Mania/Edit/Masks/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Masks/ManiaSelectionBlueprint.cs index 30b0f09a94..ff8882124f 100644 --- a/osu.Game.Rulesets.Mania/Edit/Masks/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Masks/ManiaSelectionBlueprint.cs @@ -9,8 +9,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Masks { public abstract class ManiaSelectionBlueprint : SelectionBlueprint { - protected ManiaSelectionBlueprint(DrawableHitObject hitObject) - : base(hitObject) + protected ManiaSelectionBlueprint(DrawableHitObject drawableObject) + : base(drawableObject) { RelativeSizeAxes = Axes.None; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs index cf24306623..0ecce42e88 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleSelectionBlueprint.cs @@ -63,8 +63,8 @@ namespace osu.Game.Rulesets.Osu.Tests { public new HitCirclePiece CirclePiece => base.CirclePiece; - public TestBlueprint(DrawableHitCircle hitCircle) - : base(hitCircle) + public TestBlueprint(DrawableHitCircle drawableCircle) + : base(drawableCircle) { } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs index a191dba8ff..37e15664b3 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs @@ -11,8 +11,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles { protected readonly HitCirclePiece CirclePiece; - public HitCircleSelectionBlueprint(DrawableHitCircle hitCircle) - : base(hitCircle) + public HitCircleSelectionBlueprint(DrawableHitCircle drawableCircle) + : base(drawableCircle) { InternalChild = CirclePiece = new HitCirclePiece(); } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs index 2e4b990db8..a864257274 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs @@ -10,10 +10,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints public abstract class OsuSelectionBlueprint : SelectionBlueprint where T : OsuHitObject { - protected new T HitObject => (T)base.HitObject.HitObject; + protected T HitObject => (T)DrawableObject.HitObject; - protected OsuSelectionBlueprint(DrawableHitObject hitObject) - : base(hitObject) + protected OsuSelectionBlueprint(DrawableHitObject drawableObject) + : base(drawableObject) { } } diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 838984b223..3076ad081a 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -43,20 +43,20 @@ namespace osu.Game.Rulesets.Edit /// /// The which this applies to. /// - public readonly DrawableHitObject HitObject; + public readonly DrawableHitObject DrawableObject; /// - /// The screen-space position of prior to handling a movement event. + /// The screen-space position of prior to handling a movement event. /// internal Vector2 ScreenSpaceMovementStartPosition { get; private set; } - protected override bool ShouldBeAlive => (HitObject.IsAlive && HitObject.IsPresent) || State == SelectionState.Selected; + protected override bool ShouldBeAlive => (DrawableObject.IsAlive && DrawableObject.IsPresent) || State == SelectionState.Selected; public override bool HandlePositionalInput => ShouldBeAlive; public override bool RemoveWhenNotAlive => false; - protected SelectionBlueprint(DrawableHitObject hitObject) + protected SelectionBlueprint(DrawableHitObject drawableObject) { - HitObject = hitObject; + DrawableObject = drawableObject; RelativeSizeAxes = Axes.Both; @@ -107,7 +107,7 @@ namespace osu.Game.Rulesets.Edit public bool IsSelected => State == SelectionState.Selected; - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => HitObject.ReceivePositionalInputAt(screenSpacePos); + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => DrawableObject.ReceivePositionalInputAt(screenSpacePos); private bool selectionRequested; @@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Edit protected override bool OnDragStart(DragStartEvent e) { - ScreenSpaceMovementStartPosition = HitObject.ToScreenSpace(HitObject.OriginPosition); + ScreenSpaceMovementStartPosition = DrawableObject.ToScreenSpace(DrawableObject.OriginPosition); return true; } @@ -151,11 +151,11 @@ namespace osu.Game.Rulesets.Edit /// /// The screen-space point that causes this to be selected. /// - public virtual Vector2 SelectionPoint => HitObject.ScreenSpaceDrawQuad.Centre; + public virtual Vector2 SelectionPoint => DrawableObject.ScreenSpaceDrawQuad.Centre; /// /// The screen-space quad that outlines this for selections. /// - public virtual Quad SelectionQuad => HitObject.ScreenSpaceDrawQuad; + public virtual Quad SelectionQuad => DrawableObject.ScreenSpaceDrawQuad; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 2de5ecf633..5bc5dc8e42 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -101,7 +101,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private void removeBlueprintFor(HitObject hitObject) { - var blueprint = selectionBlueprints.Single(m => m.HitObject.HitObject == hitObject); + var blueprint = selectionBlueprints.Single(m => m.DrawableObject.HitObject == hitObject); if (blueprint == null) return; @@ -252,7 +252,7 @@ namespace osu.Game.Screens.Edit.Compose.Components return d; // Put earlier hitobjects towards the end of the list, so they handle input first - int i = y.HitObject.HitObject.StartTime.CompareTo(x.HitObject.HitObject.StartTime); + int i = y.DrawableObject.HitObject.StartTime.CompareTo(x.DrawableObject.HitObject.StartTime); return i == 0 ? CompareReverseChildID(x, y) : i; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs b/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs index 13945381bb..fe0a47aec8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs +++ b/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs @@ -40,7 +40,7 @@ namespace osu.Game.Screens.Edit.Compose.Components ScreenSpaceStartPosition = screenSpaceStartPosition; ScreenSpacePosition = screenSpacePosition; - InstantDelta = Blueprint.HitObject.Parent.ToLocalSpace(ScreenSpacePosition) - Blueprint.HitObject.Position; + InstantDelta = Blueprint.DrawableObject.Parent.ToLocalSpace(ScreenSpacePosition) - Blueprint.DrawableObject.Position; } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index c9e862d99e..9cbc1f6977 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Edit.Compose.Components protected IEnumerable SelectedBlueprints => selectedBlueprints; private readonly List selectedBlueprints; - protected IEnumerable SelectedHitObjects => selectedBlueprints.Select(b => b.HitObject.HitObject); + protected IEnumerable SelectedHitObjects => selectedBlueprints.Select(b => b.DrawableObject.HitObject); private Drawable outline; @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { case Key.Delete: foreach (var h in selectedBlueprints.ToList()) - placementHandler.Delete(h.HitObject.HitObject); + placementHandler.Delete(h.DrawableObject.HitObject); return true; } From c34d3362df6b7142e555dd869e8d458a7256b3a1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 21 Oct 2019 17:14:08 +0900 Subject: [PATCH 3547/5608] Fix hit circles selection area being too large --- .../HitCircles/HitCircleSelectionBlueprint.cs | 8 ++++++++ .../Objects/Drawables/DrawableHitCircle.cs | 18 ++++++++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs index 37e15664b3..093bae854e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs @@ -1,14 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics.Primitives; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; +using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles { public class HitCircleSelectionBlueprint : OsuSelectionBlueprint { + protected new DrawableHitCircle DrawableObject => (DrawableHitCircle)base.DrawableObject; + protected readonly HitCirclePiece CirclePiece; public HitCircleSelectionBlueprint(DrawableHitCircle drawableCircle) @@ -23,5 +27,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles CirclePiece.UpdateFrom(HitObject); } + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => DrawableObject.HitArea.ReceivePositionalInputAt(screenSpacePos); + + public override Quad SelectionQuad => DrawableObject.HitArea.ScreenSpaceDrawQuad; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index bb227d76df..f74f2d7bc5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -24,14 +24,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly IBindable stackHeightBindable = new Bindable(); private readonly IBindable scaleBindable = new Bindable(); - public OsuAction? HitAction => hitArea.HitAction; + public OsuAction? HitAction => HitArea.HitAction; + public readonly HitReceptor HitArea; + public readonly SkinnableDrawable CirclePiece; private readonly Container scaleContainer; - private readonly HitArea hitArea; - - public SkinnableDrawable CirclePiece { get; } - public DrawableHitCircle(HitCircle h) : base(h) { @@ -48,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Anchor = Anchor.Centre, Children = new Drawable[] { - hitArea = new HitArea + HitArea = new HitReceptor { Hit = () => { @@ -69,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, }; - Size = hitArea.DrawSize; + Size = HitArea.DrawSize; } [BackgroundDependencyLoader] @@ -153,7 +151,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Expire(true); - hitArea.HitAction = null; + HitArea.HitAction = null; break; case ArmedState.Miss: @@ -172,7 +170,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public Drawable ProxiedLayer => ApproachCircle; - private class HitArea : Drawable, IKeyBindingHandler + public class HitReceptor : Drawable, IKeyBindingHandler { // IsHovered is used public override bool HandlePositionalInput => true; @@ -181,7 +179,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public OsuAction? HitAction; - public HitArea() + public HitReceptor() { Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); From c8f4e8b52c3ba46d973cbed4875966fba6c68dc9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Oct 2019 17:24:32 +0900 Subject: [PATCH 3548/5608] 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 85766665a9..c5714caf4c 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ab7c40116b..64172a0954 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 925a217a13..5d384888d2 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From 9f004186d57e39f7d99f875c1ffa0bdfe39cce08 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Oct 2019 17:56:39 +0900 Subject: [PATCH 3549/5608] Ensure DrawableHitObject's HitObject is not null --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index b472c880c0..f305daf128 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; @@ -89,9 +90,9 @@ namespace osu.Game.Rulesets.Objects.Drawables public IBindable State => state; - protected DrawableHitObject(HitObject hitObject) + protected DrawableHitObject([NotNull] HitObject hitObject) { - HitObject = hitObject; + HitObject = hitObject ?? throw new ArgumentNullException(nameof(hitObject)); } [BackgroundDependencyLoader] From 1bf5f9313fc178a2dc78aa49e111ea0143e663fb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Oct 2019 18:10:00 +0900 Subject: [PATCH 3550/5608] Fix failing test --- osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index cbbf5b0c09..eaa8ca7ebb 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -239,7 +239,7 @@ namespace osu.Game.Rulesets.Taiko.Tests private class TestStrongNestedHit : DrawableStrongNestedHit { public TestStrongNestedHit(DrawableHitObject mainObject) - : base(null, mainObject) + : base(new StrongHitObject { StartTime = mainObject.HitObject.StartTime }, mainObject) { } From 0bf35faae8f5cede5647fbd3139a959c01ab4d04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Oct 2019 19:25:46 +0900 Subject: [PATCH 3551/5608] Update incorrect reference --- osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 99a045e509..4001a0f33a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -231,7 +231,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private void onDragRequested(SelectionBlueprint blueprint, DragEvent dragEvent) { - HitObject draggedObject = blueprint.HitObject.HitObject; + HitObject draggedObject = blueprint.DrawableObject.HitObject; Vector2 movePosition = blueprint.ScreenSpaceMovementStartPosition + dragEvent.ScreenSpaceMousePosition - dragEvent.ScreenSpaceMouseDownPosition; Vector2 snappedPosition = composer.GetSnappedPosition(ToLocalSpace(movePosition)); From 75f444e4311203c4901ef9d6ef2a4ed18e06d047 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 22 Oct 2019 00:44:58 +0300 Subject: [PATCH 3552/5608] Basic implementation --- osu.Game/Overlays/Chat/DrawableChannel.cs | 49 ++++++++++++++++++----- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index f831266b1b..34de149bc3 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -12,6 +12,8 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; using osu.Game.Online.Chat; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Overlays.Chat { @@ -74,17 +76,40 @@ namespace osu.Game.Overlays.Chat protected virtual ChatLine CreateChatLine(Message m) => new ChatLine(m); + protected virtual Drawable CreateDaySeparator(DateTimeOffset time) => new Container + { + Margin = new MarginPadding { Vertical = 5 }, + RelativeSizeAxes = Axes.X, + Height = 2, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + } + }; + private void newMessagesArrived(IEnumerable newMessages) { // Add up to last Channel.MAX_HISTORY messages var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MaxHistory)); - ChatLineFlow.AddRange(displayMessages.Select(CreateChatLine)); + var existingChatLines = getChatLines(); - if (scroll.IsScrolledToEnd(10) || !ChatLineFlow.Children.Any() || newMessages.Any(m => m is LocalMessage)) + Message lastMessage = existingChatLines.Any() ? existingChatLines.First().Message : null; + + displayMessages.ForEach(m => + { + if (lastMessage == null || lastMessage.Timestamp.ToLocalTime().Date != m.Timestamp.ToLocalTime().Date) + ChatLineFlow.Add(CreateDaySeparator(m.Timestamp)); + + ChatLineFlow.Add(CreateChatLine(m)); + lastMessage = m; + }); + + if (scroll.IsScrolledToEnd(10) || !existingChatLines.Any() || newMessages.Any(m => m is LocalMessage)) scrollToEnd(); - var staleMessages = ChatLineFlow.Children.Where(c => c.LifetimeEnd == double.MaxValue).ToArray(); + var staleMessages = existingChatLines.Where(c => c.LifetimeEnd == double.MaxValue).ToArray(); int count = staleMessages.Length - Channel.MaxHistory; for (int i = 0; i < count; i++) @@ -98,7 +123,7 @@ namespace osu.Game.Overlays.Chat private void pendingMessageResolved(Message existing, Message updated) { - var found = ChatLineFlow.Children.LastOrDefault(c => c.Message == existing); + var found = getChatLines().LastOrDefault(c => c.Message == existing); if (found != null) { @@ -112,19 +137,25 @@ namespace osu.Game.Overlays.Chat private void messageRemoved(Message removed) { - ChatLineFlow.Children.FirstOrDefault(c => c.Message == removed)?.FadeColour(Color4.Red, 400).FadeOut(600).Expire(); + getChatLines().FirstOrDefault(c => c.Message == removed)?.FadeColour(Color4.Red, 400).FadeOut(600).Expire(); } + private IEnumerable getChatLines() => ChatLineFlow.Children.OfType(); + private void scrollToEnd() => ScheduleAfterChildren(() => scroll.ScrollToEnd()); - protected class ChatLineContainer : FillFlowContainer + protected class ChatLineContainer : FillFlowContainer { protected override int Compare(Drawable x, Drawable y) { - var xC = (ChatLine)x; - var yC = (ChatLine)y; + if (x is ChatLine && y is ChatLine) + { + var xC = (ChatLine)x; + var yC = (ChatLine)y; - return xC.Message.CompareTo(yC.Message); + return xC.Message.CompareTo(yC.Message); + } + return base.Compare(x, y); } } } From d19041fa5353d007b01f1610a46a244e820e60b6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 22 Oct 2019 01:30:37 +0300 Subject: [PATCH 3553/5608] Implement DaySeparator class --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 8 ++ osu.Game/Overlays/Chat/DrawableChannel.cs | 84 ++++++++++++++++--- 2 files changed, 81 insertions(+), 11 deletions(-) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 8f39fb9006..a17b6ea170 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -124,6 +124,14 @@ namespace osu.Game.Online.Chat protected override ChatLine CreateChatLine(Message m) => CreateChatLineAction(m); + protected override DaySeparator CreateDaySeparator(DateTimeOffset time) => new DaySeparator(time) + { + Colour = Color4.White, + TextSize = 14, + LineHeight = 1, + Margin = new MarginPadding { Horizontal = 10 } + }; + public StandAloneDrawableChannel(Channel channel) : base(channel) { diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 34de149bc3..850c7146da 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -14,6 +14,9 @@ using osu.Game.Graphics.Cursor; using osu.Game.Online.Chat; using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Game.Graphics; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.Chat { @@ -23,6 +26,9 @@ namespace osu.Game.Overlays.Chat protected ChatLineContainer ChatLineFlow; private OsuScrollContainer scroll; + [Resolved] + private OsuColour colours { get; set; } + public DrawableChannel(Channel channel) { Channel = channel; @@ -76,16 +82,9 @@ namespace osu.Game.Overlays.Chat protected virtual ChatLine CreateChatLine(Message m) => new ChatLine(m); - protected virtual Drawable CreateDaySeparator(DateTimeOffset time) => new Container + protected virtual DaySeparator CreateDaySeparator(DateTimeOffset time) => new DaySeparator(time) { - Margin = new MarginPadding { Vertical = 5 }, - RelativeSizeAxes = Axes.X, - Height = 2, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - } + Colour = colours.ChatBlue.Lighten(0.7f) }; private void newMessagesArrived(IEnumerable newMessages) @@ -95,11 +94,11 @@ namespace osu.Game.Overlays.Chat var existingChatLines = getChatLines(); - Message lastMessage = existingChatLines.Any() ? existingChatLines.First().Message : null; + Message lastMessage = existingChatLines.Any() ? existingChatLines.Last().Message : null; displayMessages.ForEach(m => { - if (lastMessage == null || lastMessage.Timestamp.ToLocalTime().Date != m.Timestamp.ToLocalTime().Date) + if (lastMessage == null || lastMessage.Timestamp.ToLocalTime().Day != m.Timestamp.ToLocalTime().Day) ChatLineFlow.Add(CreateDaySeparator(m.Timestamp)); ChatLineFlow.Add(CreateChatLine(m)); @@ -158,5 +157,68 @@ namespace osu.Game.Overlays.Chat return base.Compare(x, y); } } + + protected class DaySeparator : GridContainer + { + public float TextSize + { + get => text.Font.Size; + set => text.Font = text.Font.With(size: value); + } + + private float lineHeight = 2; + + public float LineHeight + { + get => LineHeight; + set { lineHeight = leftBox.Height = rightBox.Height = value; } + } + + private readonly SpriteText text; + private readonly Box leftBox; + private readonly Box rightBox; + + public DaySeparator(DateTimeOffset time) + { + Margin = new MarginPadding { Vertical = 10 }; + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + }; + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + }; + Content = new[] + { + new Drawable[] + { + leftBox = new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Height = lineHeight, + }, + text = new SpriteText + { + Margin = new MarginPadding { Horizontal = 10 }, + Text = time.ToLocalTime().ToString("dd MMM yyyy"), + }, + rightBox = new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Height = lineHeight, + }, + } + }; + } + } } } From a3ab6d33c14ad83cd44edd4f5eeb35ee097a580e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 22 Oct 2019 01:37:30 +0300 Subject: [PATCH 3554/5608] Add test --- .../Visual/Online/TestSceneStandAloneChatDisplay.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs index 3c5641fcd6..39c2fbfcc9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Game.Online.Chat; using osu.Game.Users; using osuTK; +using System; namespace osu.Game.Tests.Visual.Online { @@ -111,6 +112,13 @@ namespace osu.Game.Tests.Visual.Online Sender = longUsernameUser, Content = "Hi guys, my new username is lit!" })); + + AddStep("message with new date", () => testChannel.AddNewMessages(new Message(sequence++) + { + Sender = longUsernameUser, + Content = "Message from the future!", + Timestamp = DateTimeOffset.Now + })); } } } From bb7af1e39cf88a7dd9120251237af29fff60bdab Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 22 Oct 2019 01:45:04 +0300 Subject: [PATCH 3555/5608] Fix some margin/padding issues --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 3 +- osu.Game/Overlays/Chat/DrawableChannel.cs | 71 ++++++++++--------- 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index a17b6ea170..5b1d25b0d9 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -129,7 +129,8 @@ namespace osu.Game.Online.Chat Colour = Color4.White, TextSize = 14, LineHeight = 1, - Margin = new MarginPadding { Horizontal = 10 } + Padding = new MarginPadding { Horizontal = 10 }, + Margin = new MarginPadding { Vertical = 5 }, }; public StandAloneDrawableChannel(Channel channel) diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 850c7146da..b26f974ec9 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -84,7 +84,8 @@ namespace osu.Game.Overlays.Chat protected virtual DaySeparator CreateDaySeparator(DateTimeOffset time) => new DaySeparator(time) { - Colour = colours.ChatBlue.Lighten(0.7f) + Margin = new MarginPadding { Vertical = 10 }, + Colour = colours.ChatBlue.Lighten(0.7f), }; private void newMessagesArrived(IEnumerable newMessages) @@ -158,7 +159,7 @@ namespace osu.Game.Overlays.Chat } } - protected class DaySeparator : GridContainer + protected class DaySeparator : Container { public float TextSize { @@ -180,42 +181,46 @@ namespace osu.Game.Overlays.Chat public DaySeparator(DateTimeOffset time) { - Margin = new MarginPadding { Vertical = 10 }; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - ColumnDimensions = new[] + Child = new GridContainer { - new Dimension(), - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - }; - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - }; - Content = new[] - { - new Drawable[] + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + ColumnDimensions = new[] { - leftBox = new Box + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, - Height = lineHeight, - }, - text = new SpriteText - { - Margin = new MarginPadding { Horizontal = 10 }, - Text = time.ToLocalTime().ToString("dd MMM yyyy"), - }, - rightBox = new Box - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, - Height = lineHeight, - }, + leftBox = new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Height = lineHeight, + }, + text = new SpriteText + { + Margin = new MarginPadding { Horizontal = 10 }, + Text = time.ToLocalTime().ToString("dd MMM yyyy"), + }, + rightBox = new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Height = lineHeight, + }, + } } }; } From 2896ed90e24cf774a573301c86798b2e3ba881c2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 22 Oct 2019 01:55:26 +0300 Subject: [PATCH 3556/5608] Fix incorrect date comparison --- osu.Game/Overlays/Chat/DrawableChannel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index b26f974ec9..ece5beb7f8 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -99,7 +99,7 @@ namespace osu.Game.Overlays.Chat displayMessages.ForEach(m => { - if (lastMessage == null || lastMessage.Timestamp.ToLocalTime().Day != m.Timestamp.ToLocalTime().Day) + if (lastMessage == null || lastMessage.Timestamp.ToLocalTime().Date != m.Timestamp.ToLocalTime().Date) ChatLineFlow.Add(CreateDaySeparator(m.Timestamp)); ChatLineFlow.Add(CreateChatLine(m)); From f7924d3bad6ce574c1967ba5a956915f8e9be56e Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 21 Oct 2019 16:00:09 -0700 Subject: [PATCH 3557/5608] Rename "FixedSearchTextBox" to "SeekLimitedSearchTextBox" --- .../{FixedSearchTextBox.cs => SeekLimitedSearchTextBox.cs} | 2 +- osu.Game/Overlays/SettingsPanel.cs | 4 ++-- osu.Game/Screens/Select/FilterControl.cs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename osu.Game/Graphics/UserInterface/{FixedSearchTextBox.cs => SeekLimitedSearchTextBox.cs} (82%) diff --git a/osu.Game/Graphics/UserInterface/FixedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs similarity index 82% rename from osu.Game/Graphics/UserInterface/FixedSearchTextBox.cs rename to osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs index 0654746a6e..6cd14c3263 100644 --- a/osu.Game/Graphics/UserInterface/FixedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs @@ -3,7 +3,7 @@ namespace osu.Game.Graphics.UserInterface { - public class FixedSearchTextBox : SearchTextBox + public class SeekLimitedSearchTextBox : SearchTextBox { public override bool HandleLeftRightArrows => false; } diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 119b9a2b8c..d028664fe0 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -37,7 +37,7 @@ namespace osu.Game.Overlays protected SettingsSectionsContainer SectionsContainer; - private FixedSearchTextBox searchTextBox; + private SeekLimitedSearchTextBox searchTextBox; /// /// Provide a source for the toolbar height. @@ -80,7 +80,7 @@ namespace osu.Game.Overlays Masking = true, RelativeSizeAxes = Axes.Both, ExpandableHeader = CreateHeader(), - FixedHeader = searchTextBox = new FixedSearchTextBox + FixedHeader = searchTextBox = new SeekLimitedSearchTextBox { RelativeSizeAxes = Axes.X, Origin = Anchor.TopCentre, diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 7aca11da2f..5b81303788 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -49,7 +49,7 @@ namespace osu.Game.Screens.Select return criteria; } - private readonly FixedSearchTextBox searchTextBox; + private readonly SeekLimitedSearchTextBox searchTextBox; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) || groupTabs.ReceivePositionalInputAt(screenSpacePos) || sortTabs.ReceivePositionalInputAt(screenSpacePos); @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.TopRight, Children = new Drawable[] { - searchTextBox = new FixedSearchTextBox { RelativeSizeAxes = Axes.X }, + searchTextBox = new SeekLimitedSearchTextBox { RelativeSizeAxes = Axes.X }, new Box { RelativeSizeAxes = Axes.X, From e9ae838f465bbf719a07623818e26e5b7bf5329b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 22 Oct 2019 02:16:52 +0300 Subject: [PATCH 3558/5608] CI fixes --- osu.Game/Overlays/Chat/DrawableChannel.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index ece5beb7f8..3dd9f755d1 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -155,6 +155,7 @@ namespace osu.Game.Overlays.Chat return xC.Message.CompareTo(yC.Message); } + return base.Compare(x, y); } } @@ -171,7 +172,7 @@ namespace osu.Game.Overlays.Chat public float LineHeight { - get => LineHeight; + get => lineHeight; set { lineHeight = leftBox.Height = rightBox.Height = value; } } @@ -193,11 +194,8 @@ namespace osu.Game.Overlays.Chat new Dimension(GridSizeMode.AutoSize), new Dimension(), }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - }, - Content = new[] + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize), }, + Content = new[] { new Drawable[] { From b1eac6b400dd5bfb5ad4948e588b616a46a23f46 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 22 Oct 2019 03:11:19 +0300 Subject: [PATCH 3559/5608] Apply suggested changes --- osu.Game/Overlays/Chat/DrawableChannel.cs | 32 ++++++----------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 3dd9f755d1..cfa56b5136 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Chat public class DrawableChannel : Container { public readonly Channel Channel; - protected ChatLineContainer ChatLineFlow; + protected FillFlowContainer ChatLineFlow; private OsuScrollContainer scroll; [Resolved] @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Chat // Some chat lines have effects that slightly protrude to the bottom, // which we do not want to mask away, hence the padding. Padding = new MarginPadding { Bottom = 5 }, - Child = ChatLineFlow = new ChatLineContainer + Child = ChatLineFlow = new FillFlowContainer { Padding = new MarginPadding { Left = 20, Right = 20 }, RelativeSizeAxes = Axes.X, @@ -93,9 +93,9 @@ namespace osu.Game.Overlays.Chat // Add up to last Channel.MAX_HISTORY messages var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MaxHistory)); - var existingChatLines = getChatLines(); + var existingChatLines = getChatLines; - Message lastMessage = existingChatLines.Any() ? existingChatLines.Last().Message : null; + Message lastMessage = existingChatLines.LastOrDefault()?.Message; displayMessages.ForEach(m => { @@ -123,7 +123,7 @@ namespace osu.Game.Overlays.Chat private void pendingMessageResolved(Message existing, Message updated) { - var found = getChatLines().LastOrDefault(c => c.Message == existing); + var found = getChatLines.LastOrDefault(c => c.Message == existing); if (found != null) { @@ -137,29 +137,13 @@ namespace osu.Game.Overlays.Chat private void messageRemoved(Message removed) { - getChatLines().FirstOrDefault(c => c.Message == removed)?.FadeColour(Color4.Red, 400).FadeOut(600).Expire(); + getChatLines.FirstOrDefault(c => c.Message == removed)?.FadeColour(Color4.Red, 400).FadeOut(600).Expire(); } - private IEnumerable getChatLines() => ChatLineFlow.Children.OfType(); + private IEnumerable getChatLines => ChatLineFlow.Children.OfType(); private void scrollToEnd() => ScheduleAfterChildren(() => scroll.ScrollToEnd()); - protected class ChatLineContainer : FillFlowContainer - { - protected override int Compare(Drawable x, Drawable y) - { - if (x is ChatLine && y is ChatLine) - { - var xC = (ChatLine)x; - var yC = (ChatLine)y; - - return xC.Message.CompareTo(yC.Message); - } - - return base.Compare(x, y); - } - } - protected class DaySeparator : Container { public float TextSize @@ -173,7 +157,7 @@ namespace osu.Game.Overlays.Chat public float LineHeight { get => lineHeight; - set { lineHeight = leftBox.Height = rightBox.Height = value; } + set => lineHeight = leftBox.Height = rightBox.Height = value; } private readonly SpriteText text; From 09b2f11bd5c4ee7fd6ebf2320e0d107c53ac6f82 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 22 Oct 2019 03:14:20 +0300 Subject: [PATCH 3560/5608] Remove unused variable --- osu.Game/Overlays/Chat/DrawableChannel.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index cfa56b5136..85de23caaa 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -93,9 +93,7 @@ namespace osu.Game.Overlays.Chat // Add up to last Channel.MAX_HISTORY messages var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MaxHistory)); - var existingChatLines = getChatLines; - - Message lastMessage = existingChatLines.LastOrDefault()?.Message; + Message lastMessage = getChatLines.LastOrDefault()?.Message; displayMessages.ForEach(m => { @@ -106,10 +104,10 @@ namespace osu.Game.Overlays.Chat lastMessage = m; }); - if (scroll.IsScrolledToEnd(10) || !existingChatLines.Any() || newMessages.Any(m => m is LocalMessage)) + if (scroll.IsScrolledToEnd(10) || !getChatLines.Any() || newMessages.Any(m => m is LocalMessage)) scrollToEnd(); - var staleMessages = existingChatLines.Where(c => c.LifetimeEnd == double.MaxValue).ToArray(); + var staleMessages = getChatLines.Where(c => c.LifetimeEnd == double.MaxValue).ToArray(); int count = staleMessages.Length - Channel.MaxHistory; for (int i = 0; i < count; i++) From 5d0d83b6bf8b6a8546e8df4b0313199f439ca138 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Oct 2019 15:04:10 +0900 Subject: [PATCH 3561/5608] Add basic xmldoc --- osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs index 6cd14c3263..6a9e8a5b8c 100644 --- a/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs @@ -3,6 +3,9 @@ namespace osu.Game.Graphics.UserInterface { + /// + /// A which does not handle left/right arrow keys for seeking. + /// public class SeekLimitedSearchTextBox : SearchTextBox { public override bool HandleLeftRightArrows => false; From 81e8b678d342c8a9f9f646974a9659790573cdea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Oct 2019 20:17:19 +0900 Subject: [PATCH 3562/5608] Update editor time when a new timing point is selected --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 5da5d3f785..ed045aca86 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -2,11 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; @@ -19,6 +21,9 @@ namespace osu.Game.Screens.Edit.Timing [Cached] private Bindable> selectedPoints = new Bindable>(); + [Resolved] + private IAdjustableClock clock { get; set; } + protected override Drawable CreateMainContent() => new GridContainer { RelativeSizeAxes = Axes.Both, @@ -37,6 +42,13 @@ namespace osu.Game.Screens.Edit.Timing } }; + protected override void LoadComplete() + { + base.LoadComplete(); + + selectedPoints.BindValueChanged(selected => { clock.Seek(selected.NewValue.First().Time); }); + } + public class ControlPointList : CompositeDrawable { [Resolved] From 4883844c4c390aa515fef26d4b730c8992d6fe57 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Oct 2019 20:57:56 +0900 Subject: [PATCH 3563/5608] Add basic information display for all types of control points --- .../Edit/Timing/ControlPointSettings.cs | 136 +++++++++++++++--- 1 file changed, 114 insertions(+), 22 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index dc4fb2a338..1ab22679d9 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -14,7 +14,6 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.Edit.Timing { @@ -40,7 +39,7 @@ namespace osu.Game.Screens.Edit.Timing RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, - Spacing = new Vector2(30), + Spacing = new Vector2(2), Children = createSections() }, } @@ -57,31 +56,123 @@ namespace osu.Game.Screens.Edit.Timing private class TimingSection : Section { + private OsuSpriteText bpm; + private OsuSpriteText timeSignature; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + bpm = new OsuSpriteText(), + timeSignature = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => + { + bpm.Text = $"BPM: {point.NewValue?.BeatLength}"; + timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; + }); + } } private class DifficultySection : Section { + private OsuSpriteText multiplier; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + multiplier = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier}"; }); + } } private class SampleSection : Section { + private OsuSpriteText bank; + private OsuSpriteText volume; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + bank = new OsuSpriteText(), + volume = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => + { + bank.Text = $"Bank: {point.NewValue?.SampleBank}"; + volume.Text = $"Volume: {point.NewValue?.SampleVolume}"; + }); + } } private class EffectSection : Section { + private OsuSpriteText kiai; + private OsuSpriteText omitBarLine; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + kiai = new OsuSpriteText(), + omitBarLine = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => + { + kiai.Text = $"Kiai: {point.NewValue?.KiaiMode}"; + omitBarLine.Text = $"Skip Bar Line: {point.NewValue?.OmitFirstBarLine}"; + }); + } } - private class Section : Container + private class Section : CompositeDrawable where T : ControlPoint { - private const float header_height = 20; + private OsuCheckbox checkbox; + private Container content; - protected override Container Content { get; } + protected FillFlowContainer Flow { get; private set; } + + protected Bindable ControlPoint { get; } = new Bindable(); + + private const float header_height = 20; [Resolved] private Bindable> selectedPoints { get; set; } - protected Section() + [BackgroundDependencyLoader] + private void load(OsuColour colours) { RelativeSizeAxes = Axes.X; AutoSizeDuration = 200; @@ -94,7 +185,7 @@ namespace osu.Game.Screens.Edit.Timing { new Box { - Colour = Color4.Gray, + Colour = colours.Gray1, RelativeSizeAxes = Axes.Both, }, new Container @@ -103,13 +194,13 @@ namespace osu.Game.Screens.Edit.Timing Height = header_height, Children = new Drawable[] { - new OsuSpriteText + checkbox = new OsuCheckbox { - Text = typeof(T).Name.Replace(typeof(ControlPoint).Name, string.Empty) - }, + LabelText = typeof(T).Name.Replace(typeof(ControlPoint).Name, string.Empty) + } } }, - Content = new Container() + content = new Container { Y = header_height, RelativeSizeAxes = Axes.X, @@ -118,9 +209,15 @@ namespace osu.Game.Screens.Edit.Timing { new Box { - Colour = Color4.DarkGray, + Colour = colours.Gray2, + RelativeSizeAxes = Axes.Both, + }, + Flow = new FillFlowContainer + { + Padding = new MarginPadding(10), RelativeSizeAxes = Axes.X, - Height = 100, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, }, } } @@ -133,17 +230,12 @@ namespace osu.Game.Screens.Edit.Timing selectedPoints.BindValueChanged(points => { - var matching = points.NewValue?.OfType().Where(p => !p.AutoGenerated).FirstOrDefault(); + ControlPoint.Value = points.NewValue?.OfType().Where(p => !p.AutoGenerated).FirstOrDefault(); - if (matching != null) - { - Content.BypassAutoSizeAxes = Axes.None; - } - else - { - Content.BypassAutoSizeAxes = Axes.Y; - } + checkbox.Current.Value = ControlPoint.Value != null; }, true); + + checkbox.Current.BindValueChanged(selected => { content.BypassAutoSizeAxes = selected.NewValue ? Axes.None : Axes.Y; }, true); } } } From 5e22eed131ca60093f816fa8a50a06a4536f8b85 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Oct 2019 21:50:21 +0900 Subject: [PATCH 3564/5608] Add add/remove buttons --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 53 +++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index ed045aca86..b6bd9ae61d 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -13,6 +14,8 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osuTK; namespace osu.Game.Screens.Edit.Timing { @@ -51,9 +54,14 @@ namespace osu.Game.Screens.Edit.Timing public class ControlPointList : CompositeDrawable { + private OsuButton deleteButton; + [Resolved] protected IBindable Beatmap { get; private set; } + [Resolved] + private Bindable> selectedPoints { get; set; } + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -73,9 +81,52 @@ namespace osu.Game.Screens.Edit.Timing { ControlPoints = Beatmap.Value.Beatmap.ControlPointInfo.AllControlPoints } - } + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding(10), + Spacing = new Vector2(5), + Children = new Drawable[] + { + deleteButton = new OsuButton + { + Text = "-", + Size = new Vector2(30, 30), + Action = delete, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + }, + new OsuButton + { + Text = "+", + Action = addNew, + Size = new Vector2(30, 30), + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + }, + } + }, }; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + selectedPoints.BindValueChanged(selected => { deleteButton.Enabled.Value = selected.NewValue != null; }, true); + } + + private void delete() + { + } + + private void addNew() + { + } } } } From 0ba287a7fd31bcb39256722bbc42585fbad77b6d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Oct 2019 00:14:22 +0900 Subject: [PATCH 3565/5608] Rename variable --- osu.Game/Overlays/Chat/DrawableChannel.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 85de23caaa..20e82cea95 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -93,7 +93,7 @@ namespace osu.Game.Overlays.Chat // Add up to last Channel.MAX_HISTORY messages var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MaxHistory)); - Message lastMessage = getChatLines.LastOrDefault()?.Message; + Message lastMessage = chatLines.LastOrDefault()?.Message; displayMessages.ForEach(m => { @@ -104,10 +104,10 @@ namespace osu.Game.Overlays.Chat lastMessage = m; }); - if (scroll.IsScrolledToEnd(10) || !getChatLines.Any() || newMessages.Any(m => m is LocalMessage)) + if (scroll.IsScrolledToEnd(10) || !chatLines.Any() || newMessages.Any(m => m is LocalMessage)) scrollToEnd(); - var staleMessages = getChatLines.Where(c => c.LifetimeEnd == double.MaxValue).ToArray(); + var staleMessages = chatLines.Where(c => c.LifetimeEnd == double.MaxValue).ToArray(); int count = staleMessages.Length - Channel.MaxHistory; for (int i = 0; i < count; i++) @@ -121,7 +121,7 @@ namespace osu.Game.Overlays.Chat private void pendingMessageResolved(Message existing, Message updated) { - var found = getChatLines.LastOrDefault(c => c.Message == existing); + var found = chatLines.LastOrDefault(c => c.Message == existing); if (found != null) { @@ -135,10 +135,10 @@ namespace osu.Game.Overlays.Chat private void messageRemoved(Message removed) { - getChatLines.FirstOrDefault(c => c.Message == removed)?.FadeColour(Color4.Red, 400).FadeOut(600).Expire(); + chatLines.FirstOrDefault(c => c.Message == removed)?.FadeColour(Color4.Red, 400).FadeOut(600).Expire(); } - private IEnumerable getChatLines => ChatLineFlow.Children.OfType(); + private IEnumerable chatLines => ChatLineFlow.Children.OfType(); private void scrollToEnd() => ScheduleAfterChildren(() => scroll.ScrollToEnd()); From 3b4823abe7c687bbab7eba9a6af9675fdb9f2786 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Oct 2019 00:16:17 +0900 Subject: [PATCH 3566/5608] Use foreach --- osu.Game/Overlays/Chat/DrawableChannel.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 20e82cea95..f40f53852a 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -95,14 +95,14 @@ namespace osu.Game.Overlays.Chat Message lastMessage = chatLines.LastOrDefault()?.Message; - displayMessages.ForEach(m => + foreach (var message in displayMessages) { - if (lastMessage == null || lastMessage.Timestamp.ToLocalTime().Date != m.Timestamp.ToLocalTime().Date) - ChatLineFlow.Add(CreateDaySeparator(m.Timestamp)); + if (lastMessage == null || lastMessage.Timestamp.ToLocalTime().Date != message.Timestamp.ToLocalTime().Date) + ChatLineFlow.Add(CreateDaySeparator(message.Timestamp)); - ChatLineFlow.Add(CreateChatLine(m)); - lastMessage = m; - }); + ChatLineFlow.Add(CreateChatLine(message)); + lastMessage = message; + } if (scroll.IsScrolledToEnd(10) || !chatLines.Any() || newMessages.Any(m => m is LocalMessage)) scrollToEnd(); From e9aa7f32186a806a549968d6920e7ea871d5f0d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Oct 2019 00:24:08 +0900 Subject: [PATCH 3567/5608] Subclass and use yellow for stand-alone chat display --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 27 +++++++++++++------ osu.Game/Overlays/Chat/DrawableChannel.cs | 1 - 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 5b1d25b0d9..5ae453ceeb 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Chat; using osuTK.Graphics; @@ -124,14 +125,7 @@ namespace osu.Game.Online.Chat protected override ChatLine CreateChatLine(Message m) => CreateChatLineAction(m); - protected override DaySeparator CreateDaySeparator(DateTimeOffset time) => new DaySeparator(time) - { - Colour = Color4.White, - TextSize = 14, - LineHeight = 1, - Padding = new MarginPadding { Horizontal = 10 }, - Margin = new MarginPadding { Vertical = 5 }, - }; + protected override DaySeparator CreateDaySeparator(DateTimeOffset time) => new CustomDaySeparator(time); public StandAloneDrawableChannel(Channel channel) : base(channel) @@ -143,6 +137,23 @@ namespace osu.Game.Online.Chat { ChatLineFlow.Padding = new MarginPadding { Horizontal = 0 }; } + + private class CustomDaySeparator : DaySeparator + { + public CustomDaySeparator(DateTimeOffset time) : base(time) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.Yellow; + TextSize = 14; + LineHeight = 1; + Padding = new MarginPadding { Horizontal = 10 }; + Margin = new MarginPadding { Vertical = 5 }; + } + } } protected class StandAloneMessage : ChatLine diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index f40f53852a..6cdbfabe0f 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -13,7 +13,6 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; using osu.Game.Online.Chat; using osu.Framework.Graphics.Shapes; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Sprites; From c3375071adbc1cbc9557789ca0ef6e1ae96b854c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Oct 2019 00:26:47 +0900 Subject: [PATCH 3568/5608] Fix formatting issue --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 5ae453ceeb..21d0bcc4bf 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -140,7 +140,8 @@ namespace osu.Game.Online.Chat private class CustomDaySeparator : DaySeparator { - public CustomDaySeparator(DateTimeOffset time) : base(time) + public CustomDaySeparator(DateTimeOffset time) + : base(time) { } From 8154cc1b1654b6766266b5c65ec4adb3c4ceaee5 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 22 Oct 2019 14:40:56 -0700 Subject: [PATCH 3569/5608] Fix registration textboxes always focusing after pressing escape --- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index e136fc1403..66ced88875 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -138,18 +138,12 @@ namespace osu.Game.Overlays.AccountCreation passwordTextBox.Current.ValueChanged += password => { characterCheckText.ForEach(s => s.Colour = password.NewValue.Length == 0 ? Color4.White : Interpolation.ValueAt(password.NewValue.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In)); }; } - protected override void Update() - { - base.Update(); - - if (host?.OnScreenKeyboardOverlapsGameWindow != true && !textboxes.Any(t => t.HasFocus)) - focusNextTextbox(); - } - public override void OnEntering(IScreen last) { base.OnEntering(last); processingOverlay.Hide(); + + focusNextTextbox(); } private void performRegistration() From c06f142433d547abe9d96bf082df5c36e8c8400b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Oct 2019 11:22:55 +0900 Subject: [PATCH 3570/5608] Fix some spacing and references --- osu.Game/Screens/Edit/Timing/ControlPointSettings.cs | 2 -- osu.Game/Screens/Edit/Timing/ControlPointTable.cs | 2 +- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index 1ab22679d9..0974745294 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -13,7 +13,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osuTK; namespace osu.Game.Screens.Edit.Timing { @@ -39,7 +38,6 @@ namespace osu.Game.Screens.Edit.Timing RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, - Spacing = new Vector2(2), Children = createSections() }, } diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 5032e71fe8..777d34e75b 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit.Timing var columns = new List { new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("time", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Time", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Attributes", Anchor.Centre), }; diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index b6bd9ae61d..bd0a75f0b0 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; From 7b7a87afa8369fcb659e18e5ae67f5c4f92bbce8 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 22 Oct 2019 19:51:29 -0700 Subject: [PATCH 3571/5608] Put back mobile conditional --- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 66ced88875..6de14c51ee 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -143,7 +143,8 @@ namespace osu.Game.Overlays.AccountCreation base.OnEntering(last); processingOverlay.Hide(); - focusNextTextbox(); + if (host?.OnScreenKeyboardOverlapsGameWindow != true) + focusNextTextbox(); } private void performRegistration() From 851773a84228c8a45cb7853ea46dd4d77c23c1b3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 Oct 2019 14:04:06 +0900 Subject: [PATCH 3572/5608] Apply adjustments for framework changes --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 2 +- osu.Game/Overlays/Settings/SettingsSlider.cs | 4 ++-- osu.Game/Screens/Edit/BindableBeatDivisor.cs | 2 +- osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 5c706781e6..11aba80d76 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -17,7 +17,7 @@ using osu.Framework.Input.Events; namespace osu.Game.Graphics.UserInterface { public class OsuSliderBar : SliderBar, IHasTooltip, IHasAccentColour - where T : struct, IEquatable, IComparable, IConvertible + where T : struct, IEquatable, IComparable, IConvertible { /// /// Maximum number of decimal digits to be displayed in the tooltip. diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index fd96ea972a..20e08c0cd8 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -8,12 +8,12 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { public class SettingsSlider : SettingsSlider> - where T : struct, IEquatable, IComparable, IConvertible + where T : struct, IEquatable, IComparable, IConvertible { } public class SettingsSlider : SettingsItem - where T : struct, IEquatable, IComparable, IConvertible + where T : struct, IEquatable, IComparable, IConvertible where U : OsuSliderBar, new() { protected override Drawable CreateControl() => new U diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index 2aeb1ef04b..a724f354e7 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -10,7 +10,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit { - public class BindableBeatDivisor : BindableNumber + public class BindableBeatDivisor : BindableInt { public static readonly int[] VALID_DIVISORS = { 1, 2, 3, 4, 6, 8, 12, 16 }; diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs index 28fe1f35ca..c8e281195a 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Play.PlayerSettings { public class PlayerSliderBar : SettingsSlider - where T : struct, IEquatable, IComparable, IConvertible + where T : struct, IEquatable, IComparable, IConvertible { public OsuSliderBar Bar => (OsuSliderBar)Control; From e836364add4c833aa9bbc8841ddefe415a6fd137 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Oct 2019 15:13:52 +0900 Subject: [PATCH 3573/5608] 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 c5714caf4c..43c1302e54 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 64172a0954..e898a001de 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 5d384888d2..656c60543e 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From 54f23cbd0da2a062f375dcfd1696bf0427718822 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 Oct 2019 15:49:36 +0900 Subject: [PATCH 3574/5608] Update stacking test case values --- .../old-stacking-expected-conversion.json | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/old-stacking-expected-conversion.json b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/old-stacking-expected-conversion.json index b994cbd85a..004e7940d1 100644 --- a/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/old-stacking-expected-conversion.json +++ b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/old-stacking-expected-conversion.json @@ -143,14 +143,14 @@ "Objects": [{ "StartTime": 34989, "EndTime": 34989, - "X": 163, - "Y": 138 + "X": 156.597382, + "Y": 131.597382 }, { "StartTime": 35018, "EndTime": 35018, - "X": 188, - "Y": 138 + "X": 181.597382, + "Y": 131.597382 } ] }, @@ -159,14 +159,14 @@ "Objects": [{ "StartTime": 35106, "EndTime": 35106, - "X": 163, - "Y": 138 + "X": 159.798691, + "Y": 134.798691 }, { "StartTime": 35135, "EndTime": 35135, - "X": 188, - "Y": 138 + "X": 184.798691, + "Y": 134.798691 } ] }, @@ -191,20 +191,20 @@ "Objects": [{ "StartTime": 35695, "EndTime": 35695, - "X": 166, - "Y": 76 + "X": 162.798691, + "Y": 72.79869 }, { "StartTime": 35871, "EndTime": 35871, - "X": 240.99855, - "Y": 75.53417 + "X": 237.797241, + "Y": 72.33286 }, { "StartTime": 36011, "EndTime": 36011, - "X": 315.9971, - "Y": 75.0683441 + "X": 312.795776, + "Y": 71.8670349 } ] }, @@ -235,20 +235,20 @@ "Objects": [{ "StartTime": 36518, "EndTime": 36518, - "X": 166, - "Y": 76 + "X": 169.201309, + "Y": 79.20131 }, { "StartTime": 36694, "EndTime": 36694, - "X": 240.99855, - "Y": 75.53417 + "X": 244.19986, + "Y": 78.73548 }, { "StartTime": 36834, "EndTime": 36834, - "X": 315.9971, - "Y": 75.0683441 + "X": 319.198425, + "Y": 78.26965 } ] }, @@ -257,20 +257,20 @@ "Objects": [{ "StartTime": 36929, "EndTime": 36929, - "X": 315, - "Y": 75 + "X": 324.603943, + "Y": 84.6039352 }, { "StartTime": 37105, "EndTime": 37105, - "X": 240.001526, - "Y": 75.47769 + "X": 249.605469, + "Y": 85.08163 }, { "StartTime": 37245, "EndTime": 37245, - "X": 165.003052, - "Y": 75.95539 + "X": 174.607, + "Y": 85.5593262 } ] } From b903edca4581574a30eb4760eeb908df64a9317f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 Oct 2019 16:03:16 +0900 Subject: [PATCH 3575/5608] Don't snap slider control point placement --- .../Blueprints/Sliders/SliderPlacementBlueprint.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 2fb18bf8ba..2fe294a7e0 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -6,6 +6,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; +using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; @@ -28,6 +29,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private readonly List segments = new List(); private Vector2 cursor; + private InputManager inputManager; private PlacementState state; @@ -52,6 +54,12 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders setState(PlacementState.Initial); } + protected override void LoadComplete() + { + base.LoadComplete(); + inputManager = GetContainingInputManager(); + } + public override void UpdatePosition(Vector2 screenSpacePosition) { switch (state) @@ -61,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders break; case PlacementState.Body: - cursor = ToLocalSpace(screenSpacePosition) - HitObject.Position; + cursor = ToLocalSpace(inputManager.CurrentState.Mouse.Position) - HitObject.Position; break; } } From 64682611bbd547336f61e3fe7bd42594e802c7bd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 Oct 2019 16:39:14 +0900 Subject: [PATCH 3576/5608] Fix distance snapping grid not updating on scroll --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 51155ce3fd..5b8f6663e7 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -162,12 +162,17 @@ namespace osu.Game.Rulesets.Edit inputManager = GetContainingInputManager(); } + private double lastGridUpdateTime; + protected override void Update() { base.Update(); - if (EditorClock.ElapsedFrameTime != 0 && blueprintContainer.CurrentTool != null) + if (EditorClock.CurrentTime != lastGridUpdateTime && blueprintContainer.CurrentTool != null) + { showGridFor(Enumerable.Empty()); + lastGridUpdateTime = EditorClock.CurrentTime; + } } protected override void UpdateAfterChildren() @@ -212,6 +217,8 @@ namespace osu.Game.Rulesets.Edit { distanceSnapGridContainer.Child = distanceSnapGrid; distanceSnapGridContainer.Show(); + + lastGridUpdateTime = EditorClock.CurrentTime; } } From 97383b4a37aeac057ab11b4baeb7176356e01d05 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 Oct 2019 16:58:56 +0900 Subject: [PATCH 3577/5608] Show centre point of distance snap grid --- .../TestSceneOsuDistanceSnapGrid.cs | 7 +++++++ .../Components/CircularDistanceSnapGrid.cs | 17 +++++++++++++++++ .../Edit/Compose/Components/DistanceSnapGrid.cs | 10 +++++----- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index da7708081b..6b8daa531f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -14,6 +15,7 @@ using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit; +using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Tests.Visual; using osuTK; using osuTK.Graphics; @@ -25,6 +27,11 @@ namespace osu.Game.Rulesets.Osu.Tests private const double beat_length = 100; private static readonly Vector2 grid_position = new Vector2(512, 384); + public override IReadOnlyList RequiredTypes => new[] + { + typeof(CircularDistanceSnapGrid) + }; + [Cached(typeof(IEditorBeatmap))] private readonly EditorBeatmap editorBeatmap; diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 3cbf926d4f..17b2eedb6e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Game.Rulesets.Objects; using osuTK; @@ -18,6 +19,22 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void CreateContent(Vector2 centrePosition) { + AddInternal(new Box + { + Origin = Anchor.Centre, + Position = centrePosition, + Width = 2, + Height = Math.Min(10, DistanceSpacing * 2), + }); + + AddInternal(new Box + { + Origin = Anchor.Centre, + Position = centrePosition, + Width = Math.Min(10, DistanceSpacing * 2), + Height = 2, + }); + float dx = Math.Max(centrePosition.X, DrawWidth - centrePosition.X); float dy = Math.Max(centrePosition.Y, DrawHeight - centrePosition.Y); float maxDistance = new Vector2(dx, dy).Length; diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 299e78b7c0..096ff0a6dd 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -36,15 +36,15 @@ namespace osu.Game.Screens.Edit.Compose.Components /// protected readonly Vector2 CentrePosition; + [Resolved] + protected OsuColour Colours { get; private set; } + [Resolved] private IEditorBeatmap beatmap { get; set; } [Resolved] private BindableBeatDivisor beatDivisor { get; set; } - [Resolved] - private OsuColour colours { get; set; } - private readonly Cached gridCache = new Cached(); private readonly HitObject hitObject; @@ -136,7 +136,7 @@ namespace osu.Game.Screens.Edit.Compose.Components protected ColourInfo GetColourForBeatIndex(int index) { int beat = (index + 1) % beatDivisor.Value; - ColourInfo colour = colours.Gray5; + ColourInfo colour = Colours.Gray5; for (int i = 0; i < BindableBeatDivisor.VALID_DIVISORS.Length; i++) { @@ -144,7 +144,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if ((beat * divisor) % beatDivisor.Value == 0) { - colour = BindableBeatDivisor.GetColourFor(divisor, colours); + colour = BindableBeatDivisor.GetColourFor(divisor, Colours); break; } } From c9fec50f6321017afe59b832e8ff7783e120b161 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 Oct 2019 17:00:13 +0900 Subject: [PATCH 3578/5608] Remove unnecessary whitespace --- .../Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 17b2eedb6e..8188197022 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -38,7 +38,6 @@ namespace osu.Game.Screens.Edit.Compose.Components float dx = Math.Max(centrePosition.X, DrawWidth - centrePosition.X); float dy = Math.Max(centrePosition.Y, DrawHeight - centrePosition.Y); float maxDistance = new Vector2(dx, dy).Length; - int requiredCircles = (int)(maxDistance / DistanceSpacing); for (int i = 0; i < requiredCircles; i++) From 2c9b11cdfd2b898f271147e27ae5395d926687d8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 Oct 2019 17:49:21 +0900 Subject: [PATCH 3579/5608] Move variable outside of if block --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 5b8f6663e7..7e7c260360 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -217,9 +217,9 @@ namespace osu.Game.Rulesets.Edit { distanceSnapGridContainer.Child = distanceSnapGrid; distanceSnapGridContainer.Show(); - - lastGridUpdateTime = EditorClock.CurrentTime; } + + lastGridUpdateTime = EditorClock.CurrentTime; } private ScheduledDelegate scheduledUpdate; From c03fa01fd9194f66b2e8c9733546aafddabdcb5c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 Oct 2019 17:51:16 +0900 Subject: [PATCH 3580/5608] Remove unnecessary set --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 7e7c260360..6396301add 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -169,10 +169,7 @@ namespace osu.Game.Rulesets.Edit base.Update(); if (EditorClock.CurrentTime != lastGridUpdateTime && blueprintContainer.CurrentTool != null) - { showGridFor(Enumerable.Empty()); - lastGridUpdateTime = EditorClock.CurrentTime; - } } protected override void UpdateAfterChildren() From f61d7e4fbec3dd022eaec9593cbdfcfc9b2df510 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Oct 2019 17:56:09 +0900 Subject: [PATCH 3581/5608] Add smoothing and tidy code a touch --- .../Components/CircularDistanceSnapGrid.cs | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 8188197022..a644e51c13 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -19,20 +19,27 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void CreateContent(Vector2 centrePosition) { - AddInternal(new Box - { - Origin = Anchor.Centre, - Position = centrePosition, - Width = 2, - Height = Math.Min(10, DistanceSpacing * 2), - }); + const float crosshair_thickness = 1; + const float crosshair_max_size = 10; - AddInternal(new Box + AddRangeInternal(new[] { - Origin = Anchor.Centre, - Position = centrePosition, - Width = Math.Min(10, DistanceSpacing * 2), - Height = 2, + new Box + { + Origin = Anchor.Centre, + Position = centrePosition, + Width = crosshair_thickness, + EdgeSmoothness = new Vector2(1), + Height = Math.Min(crosshair_max_size, DistanceSpacing * 2), + }, + new Box + { + Origin = Anchor.Centre, + Position = centrePosition, + EdgeSmoothness = new Vector2(1), + Width = Math.Min(crosshair_max_size, DistanceSpacing * 2), + Height = crosshair_thickness, + } }); float dx = Math.Max(centrePosition.X, DrawWidth - centrePosition.X); From 436941cda34b7f6dcbd9ca95a872056bc94e24a9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 Oct 2019 17:58:44 +0900 Subject: [PATCH 3582/5608] Add comment --- .../Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 2fe294a7e0..b7b8d0af88 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -69,6 +69,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders break; case PlacementState.Body: + // The given screen-space position may have been externally snapped, but the unsnapped position from the input manager + // is used instead since snapping control points doesn't make much sense cursor = ToLocalSpace(inputManager.CurrentState.Mouse.Position) - HitObject.Position; break; } From cef2318cf55861fc1c54ce14d868b28457372e90 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 Oct 2019 18:37:57 +0900 Subject: [PATCH 3583/5608] Move drag box drag handling to BlueprintContainer --- .../Compose/Components/BlueprintContainer.cs | 28 ++++++++++++++++--- .../Edit/Compose/Components/DragBox.cs | 21 +------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 4001a0f33a..c390ffe3f2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -23,6 +23,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { public event Action> SelectionChanged; + private DragBox dragBox; private SelectionBlueprintContainer selectionBlueprints; private Container placementBlueprintContainer; private PlacementBlueprint currentPlacement; @@ -46,12 +47,9 @@ namespace osu.Game.Screens.Edit.Compose.Components selectionHandler = composer.CreateSelectionHandler(); selectionHandler.DeselectAll = deselectAll; - var dragBox = new DragBox(select); - dragBox.DragEnd += () => selectionHandler.UpdateVisibility(); - InternalChildren = new[] { - dragBox, + dragBox = new DragBox(select), selectionHandler, selectionBlueprints = new SelectionBlueprintContainer { RelativeSizeAxes = Axes.Both }, placementBlueprintContainer = new Container { RelativeSizeAxes = Axes.Both }, @@ -229,6 +227,28 @@ namespace osu.Game.Screens.Edit.Compose.Components private void onSelectionRequested(SelectionBlueprint blueprint, InputState state) => selectionHandler.HandleSelectionRequested(blueprint, state); + protected override bool OnDragStart(DragStartEvent e) + { + if (!selectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) + dragBox.FadeIn(250, Easing.OutQuint); + + return true; + } + + protected override bool OnDrag(DragEvent e) + { + dragBox.UpdateDrag(e); + return true; + } + + protected override bool OnDragEnd(DragEndEvent e) + { + dragBox.FadeOut(250, Easing.OutQuint); + selectionHandler.UpdateVisibility(); + + return true; + } + private void onDragRequested(SelectionBlueprint blueprint, DragEvent dragEvent) { HitObject draggedObject = blueprint.DrawableObject.HitObject; diff --git a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs index 143615148a..7d892aa889 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs @@ -19,11 +19,6 @@ namespace osu.Game.Screens.Edit.Compose.Components { private readonly Action performSelection; - /// - /// Invoked when the drag selection has finished. - /// - public event Action DragEnd; - private Drawable box; /// @@ -55,13 +50,7 @@ namespace osu.Game.Screens.Edit.Compose.Components }; } - protected override bool OnDragStart(DragStartEvent e) - { - this.FadeIn(250, Easing.OutQuint); - return true; - } - - protected override bool OnDrag(DragEvent e) + public void UpdateDrag(DragEvent e) { var dragPosition = e.ScreenSpaceMousePosition; var dragStartPosition = e.ScreenSpaceMouseDownPosition; @@ -78,14 +67,6 @@ namespace osu.Game.Screens.Edit.Compose.Components box.Size = bottomRight - topLeft; performSelection?.Invoke(dragRectangle); - return true; - } - - protected override bool OnDragEnd(DragEndEvent e) - { - this.FadeOut(250, Easing.OutQuint); - DragEnd?.Invoke(); - return true; } } } From b310fd9d44503c7f889efc8357b76bb885a03367 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 23 Oct 2019 13:39:42 +0300 Subject: [PATCH 3584/5608] Adjust naming inside the LoadingButton --- .../Graphics/UserInterface/LoadingButton.cs | 18 +++++++++--------- .../Graphics/UserInterface/ShowMoreButton.cs | 4 ++-- osu.Game/Overlays/Comments/VotePill.cs | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/LoadingButton.cs b/osu.Game/Graphics/UserInterface/LoadingButton.cs index 46a4c70666..c177431c78 100644 --- a/osu.Game/Graphics/UserInterface/LoadingButton.cs +++ b/osu.Game/Graphics/UserInterface/LoadingButton.cs @@ -27,13 +27,13 @@ namespace osu.Game.Graphics.UserInterface if (value) { loading.Show(); - content.FadeOut(fade_duration, Easing.OutQuint); + text.FadeOut(fade_duration, Easing.OutQuint); OnLoadingStart(); } else { loading.Hide(); - content.FadeIn(fade_duration, Easing.OutQuint); + text.FadeIn(fade_duration, Easing.OutQuint); OnLoadingFinished(); } } @@ -46,17 +46,17 @@ namespace osu.Game.Graphics.UserInterface } private readonly LoadingAnimation loading; - private readonly Drawable content; + private readonly Drawable text; protected LoadingButton() { - Container background; + Container content; - Child = background = CreateBackground(); + Child = content = CreateContent(); - background.AddRange(new[] + content.AddRange(new[] { - content = CreateContent(), + text = CreateText(), loading = new LoadingAnimation { Anchor = Anchor.Centre, @@ -90,8 +90,8 @@ namespace osu.Game.Graphics.UserInterface { } - protected abstract Container CreateBackground(); + protected abstract Container CreateContent(); - protected abstract Drawable CreateContent(); + protected abstract Drawable CreateText(); } } diff --git a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs index 31e9af55c4..407e102ca5 100644 --- a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs +++ b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs @@ -40,7 +40,7 @@ namespace osu.Game.Graphics.UserInterface AutoSizeAxes = Axes.Both; } - protected override Container CreateBackground() => new CircularContainer + protected override Container CreateContent() => new CircularContainer { Masking = true, Size = new Vector2(140, 30), @@ -50,7 +50,7 @@ namespace osu.Game.Graphics.UserInterface } }; - protected override Drawable CreateContent() => new FillFlowContainer + protected override Drawable CreateText() => new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 5eade6fc46..532fd8d905 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -84,7 +84,7 @@ namespace osu.Game.Overlays.Comments IsLoading = false; } - protected override Container CreateBackground() => new Container + protected override Container CreateContent() => new Container { RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, @@ -119,7 +119,7 @@ namespace osu.Game.Overlays.Comments }, }; - protected override Drawable CreateContent() => votesCounter = new OsuSpriteText + protected override Drawable CreateText() => votesCounter = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, From c6d4fc8b2438af9786bf628ca4a7be712f13ff55 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Thu, 24 Oct 2019 08:00:45 +0700 Subject: [PATCH 3585/5608] Apply review --- osu.Game/Overlays/MusicController.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index cc74f234a0..45f08b2a25 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -289,15 +289,14 @@ namespace osu.Game.Overlays { case PreviousButtonAction.Restart: onScreenDisplay?.Display(new MusicControllerToast("Restart track")); - return true; + break; case PreviousButtonAction.Previous: onScreenDisplay?.Display(new MusicControllerToast("Previous track")); - return true; - - default: - return false; + break; } + + return true; } return false; From d22e12d1046a167c547d313bf703e309ef71e583 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Thu, 24 Oct 2019 10:28:23 +0700 Subject: [PATCH 3586/5608] Update doc --- osu.Game/Overlays/MusicController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 45f08b2a25..b2b0a0afd9 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -155,7 +155,7 @@ namespace osu.Game.Overlays /// /// Play the previous track or restart the current track if it's current time below /// - /// Whether the operation was successful. + /// The that indicate the decided action public PreviousButtonAction PrevTrack() { var currentTrackPosition = current?.Track.CurrentTime; From 967551fec06cc152085116e1510ddc91e98aa799 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Oct 2019 13:10:17 +0900 Subject: [PATCH 3587/5608] Renames and xmldoc --- .../TestSceneNowPlayingOverlay.cs | 4 ++-- osu.Game/Overlays/MusicController.cs | 21 +++++++++++-------- osu.Game/Overlays/NowPlayingOverlay.cs | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index 4c76a04bdb..f12e647b4e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -46,11 +46,11 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddStep(@"Seek track to 6 second", () => musicController.SeekTo(6000)); - AddStep(@"Call PrevTrack", () => musicController.PrevTrack()); + AddStep(@"Call PrevTrack", () => musicController.PreviousTrack()); AddAssert(@"Check if it restarted", () => currentTrack == Beatmap.Value); AddStep(@"Seek track to 2 second", () => musicController.SeekTo(2000)); - AddStep(@"Call PrevTrack", () => musicController.PrevTrack()); + AddStep(@"Call PrevTrack", () => musicController.PreviousTrack()); // If the track isn't changing, check the current track's time instead AddAssert(@"Check if it changed to prev track'", () => currentTrack != Beatmap.Value || currentTrack.Track.CurrentTime < 2000); } diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index b2b0a0afd9..bb246763c7 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -27,6 +27,9 @@ namespace osu.Game.Overlays public IBindableList BeatmapSets => beatmapSets; + /// + /// Point in time after which the current track will be restarted on triggering a "previous track" action. + /// private const double restart_cutoff_point = 5000; private readonly BindableList beatmapSets = new BindableList(); @@ -155,15 +158,15 @@ namespace osu.Game.Overlays /// /// Play the previous track or restart the current track if it's current time below /// - /// The that indicate the decided action - public PreviousButtonAction PrevTrack() + /// The that indicate the decided action + public PreviousTrackResult PreviousTrack() { var currentTrackPosition = current?.Track.CurrentTime; if (currentTrackPosition >= restart_cutoff_point) { SeekTo(0); - return PreviousButtonAction.Restart; + return PreviousTrackResult.Restart; } queuedDirection = TrackChangeDirection.Prev; @@ -176,10 +179,10 @@ namespace osu.Game.Overlays working.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); beatmap.Value.Track.Restart(); - return PreviousButtonAction.Previous; + return PreviousTrackResult.Previous; } - return PreviousButtonAction.None; + return PreviousTrackResult.None; } /// @@ -285,13 +288,13 @@ namespace osu.Game.Overlays return true; case GlobalAction.MusicPrev: - switch (PrevTrack()) + switch (PreviousTrack()) { - case PreviousButtonAction.Restart: + case PreviousTrackResult.Restart: onScreenDisplay?.Display(new MusicControllerToast("Restart track")); break; - case PreviousButtonAction.Previous: + case PreviousTrackResult.Previous: onScreenDisplay?.Display(new MusicControllerToast("Previous track")); break; } @@ -320,7 +323,7 @@ namespace osu.Game.Overlays Prev } - public enum PreviousButtonAction + public enum PreviousTrackResult { None, Restart, diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 6b79f2af07..c1c871aade 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -137,7 +137,7 @@ namespace osu.Game.Overlays { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Action = () => musicController.PrevTrack(), + Action = () => musicController.PreviousTrack(), Icon = FontAwesome.Solid.StepBackward, }, playButton = new MusicIconButton From 42e33dde0c718188afcaa41cbdf4bd8d731fac9a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Oct 2019 13:18:31 +0900 Subject: [PATCH 3588/5608] Make tests actually test --- .../Visual/UserInterface/TestSceneNowPlayingOverlay.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index f12e647b4e..16f788a9fc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -46,13 +46,11 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddStep(@"Seek track to 6 second", () => musicController.SeekTo(6000)); - AddStep(@"Call PrevTrack", () => musicController.PreviousTrack()); - AddAssert(@"Check if it restarted", () => currentTrack == Beatmap.Value); + AddAssert(@"Check action is restart track", () => musicController.PreviousTrack() == PreviousTrackResult.Restart); + AddAssert(@"Check track didn't change", () => currentTrack == Beatmap.Value); AddStep(@"Seek track to 2 second", () => musicController.SeekTo(2000)); - AddStep(@"Call PrevTrack", () => musicController.PreviousTrack()); - // If the track isn't changing, check the current track's time instead - AddAssert(@"Check if it changed to prev track'", () => currentTrack != Beatmap.Value || currentTrack.Track.CurrentTime < 2000); + AddAssert(@"Check action is previous track", () => musicController.PreviousTrack() == PreviousTrackResult.Previous); } } } From f32b84d07d98b29371f02fa54dc9ff7d6949e922 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Oct 2019 14:05:56 +0900 Subject: [PATCH 3589/5608] Fix tests not working on CI (where no beatmaps were present) --- .../TestSceneNowPlayingOverlay.cs | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index 16f788a9fc..1a824cf226 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -4,9 +4,9 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Overlays; +using osu.Game.Rulesets.Osu; namespace osu.Game.Tests.Visual.UserInterface { @@ -16,24 +16,31 @@ namespace osu.Game.Tests.Visual.UserInterface [Cached] private MusicController musicController = new MusicController(); - private WorkingBeatmap currentTrack; + private WorkingBeatmap currentBeatmap; - public TestSceneNowPlayingOverlay() + private NowPlayingOverlay nowPlayingOverlay; + + [BackgroundDependencyLoader] + private void load() { - Clock = new FramedClock(); + Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); - var np = new NowPlayingOverlay + nowPlayingOverlay = new NowPlayingOverlay { Origin = Anchor.Centre, Anchor = Anchor.Centre }; Add(musicController); - Add(np); + Add(nowPlayingOverlay); + } - AddStep(@"show", () => np.Show()); + [Test] + public void TestShowHideDisable() + { + AddStep(@"show", () => nowPlayingOverlay.Show()); AddToggleStep(@"toggle beatmap lock", state => Beatmap.Disabled = state); - AddStep(@"hide", () => np.Hide()); + AddStep(@"hide", () => nowPlayingOverlay.Hide()); } [Test] @@ -42,15 +49,16 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep(@"Play track", () => { musicController.NextTrack(); - currentTrack = Beatmap.Value; + currentBeatmap = Beatmap.Value; }); AddStep(@"Seek track to 6 second", () => musicController.SeekTo(6000)); + AddUntilStep(@"Wait for current time to update", () => currentBeatmap.Track.CurrentTime > 5000); AddAssert(@"Check action is restart track", () => musicController.PreviousTrack() == PreviousTrackResult.Restart); - AddAssert(@"Check track didn't change", () => currentTrack == Beatmap.Value); + AddAssert(@"Check track didn't change", () => currentBeatmap == Beatmap.Value); AddStep(@"Seek track to 2 second", () => musicController.SeekTo(2000)); - AddAssert(@"Check action is previous track", () => musicController.PreviousTrack() == PreviousTrackResult.Previous); + AddAssert(@"Check action is not restart", () => musicController.PreviousTrack() != PreviousTrackResult.Restart); } } } From 7f64012cfc022c82fd12605dd65ea06a02112c16 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Oct 2019 14:35:45 +0900 Subject: [PATCH 3590/5608] Remove seek --- .../Visual/UserInterface/TestSceneNowPlayingOverlay.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index 1a824cf226..4626b9d70f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -56,8 +56,6 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep(@"Wait for current time to update", () => currentBeatmap.Track.CurrentTime > 5000); AddAssert(@"Check action is restart track", () => musicController.PreviousTrack() == PreviousTrackResult.Restart); AddAssert(@"Check track didn't change", () => currentBeatmap == Beatmap.Value); - - AddStep(@"Seek track to 2 second", () => musicController.SeekTo(2000)); AddAssert(@"Check action is not restart", () => musicController.PreviousTrack() != PreviousTrackResult.Restart); } } From 714c89faa49272b4b5bbb0c275a842e05ddc85c9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 Oct 2019 18:58:15 +0900 Subject: [PATCH 3591/5608] Move selection drag events to BlueprintContainer --- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 22 ------- .../Compose/Components/BlueprintContainer.cs | 64 ++++++++++++------- 2 files changed, 42 insertions(+), 44 deletions(-) diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 3076ad081a..8a6e8f6128 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -35,21 +35,11 @@ namespace osu.Game.Rulesets.Edit /// public event Action SelectionRequested; - /// - /// Invoked when this has requested drag. - /// - public event Action DragRequested; - /// /// The which this applies to. /// public readonly DrawableHitObject DrawableObject; - /// - /// The screen-space position of prior to handling a movement event. - /// - internal Vector2 ScreenSpaceMovementStartPosition { get; private set; } - protected override bool ShouldBeAlive => (DrawableObject.IsAlive && DrawableObject.IsPresent) || State == SelectionState.Selected; public override bool HandlePositionalInput => ShouldBeAlive; public override bool RemoveWhenNotAlive => false; @@ -136,18 +126,6 @@ namespace osu.Game.Rulesets.Edit return base.OnClick(e); } - protected override bool OnDragStart(DragStartEvent e) - { - ScreenSpaceMovementStartPosition = DrawableObject.ToScreenSpace(DrawableObject.OriginPosition); - return true; - } - - protected override bool OnDrag(DragEvent e) - { - DragRequested?.Invoke(this, e); - return true; - } - /// /// The screen-space point that causes this to be selected. /// diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index c390ffe3f2..2f401ede38 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -109,7 +110,6 @@ namespace osu.Game.Screens.Edit.Compose.Components blueprint.Selected -= onBlueprintSelected; blueprint.Deselected -= onBlueprintDeselected; blueprint.SelectionRequested -= onSelectionRequested; - blueprint.DragRequested -= onDragRequested; selectionBlueprints.Remove(blueprint); } @@ -125,7 +125,6 @@ namespace osu.Game.Screens.Edit.Compose.Components blueprint.Selected += onBlueprintSelected; blueprint.Deselected += onBlueprintDeselected; blueprint.SelectionRequested += onSelectionRequested; - blueprint.DragRequested += onDragRequested; selectionBlueprints.Add(blueprint); } @@ -227,9 +226,18 @@ namespace osu.Game.Screens.Edit.Compose.Components private void onSelectionRequested(SelectionBlueprint blueprint, InputState state) => selectionHandler.HandleSelectionRequested(blueprint, state); + private Vector2? screenSpaceMovementStartPosition; + private SelectionBlueprint movementBlueprint; + protected override bool OnDragStart(DragStartEvent e) { - if (!selectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) + if (selectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) + { + // The earliest hitobject is used for drag-movement/snapping + movementBlueprint = selectionHandler.SelectedBlueprints.OrderBy(b => b.DrawableObject.HitObject.StartTime).First(); + screenSpaceMovementStartPosition = movementBlueprint.DrawableObject.ToScreenSpace(movementBlueprint.DrawableObject.OriginPosition); + } + else dragBox.FadeIn(250, Easing.OutQuint); return true; @@ -237,34 +245,46 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnDrag(DragEvent e) { - dragBox.UpdateDrag(e); + if (movementBlueprint != null) + { + Debug.Assert(screenSpaceMovementStartPosition != null); + + Vector2 startPosition = screenSpaceMovementStartPosition.Value; + HitObject draggedObject = movementBlueprint.DrawableObject.HitObject; + + Vector2 movePosition = startPosition + e.ScreenSpaceMousePosition - e.ScreenSpaceMouseDownPosition; + Vector2 snappedPosition = composer.GetSnappedPosition(ToLocalSpace(movePosition)); + + // Move the hitobjects + selectionHandler.HandleMovement(new MoveSelectionEvent(movementBlueprint, startPosition, ToScreenSpace(snappedPosition))); + + // Apply the start time at the newly snapped-to position + double offset = composer.GetSnappedTime(draggedObject.StartTime, snappedPosition) - draggedObject.StartTime; + foreach (HitObject obj in selectionHandler.SelectedHitObjects) + obj.StartTime += offset; + } + else + dragBox.UpdateDrag(e); + return true; } protected override bool OnDragEnd(DragEndEvent e) { - dragBox.FadeOut(250, Easing.OutQuint); - selectionHandler.UpdateVisibility(); + if (movementBlueprint != null) + { + screenSpaceMovementStartPosition = null; + movementBlueprint = null; + } + else + { + dragBox.FadeOut(250, Easing.OutQuint); + selectionHandler.UpdateVisibility(); + } return true; } - private void onDragRequested(SelectionBlueprint blueprint, DragEvent dragEvent) - { - HitObject draggedObject = blueprint.DrawableObject.HitObject; - - Vector2 movePosition = blueprint.ScreenSpaceMovementStartPosition + dragEvent.ScreenSpaceMousePosition - dragEvent.ScreenSpaceMouseDownPosition; - Vector2 snappedPosition = composer.GetSnappedPosition(ToLocalSpace(movePosition)); - - // Move the hitobjects - selectionHandler.HandleMovement(new MoveSelectionEvent(blueprint, blueprint.ScreenSpaceMovementStartPosition, ToScreenSpace(snappedPosition))); - - // Apply the start time at the newly snapped-to position - double offset = composer.GetSnappedTime(draggedObject.StartTime, snappedPosition) - draggedObject.StartTime; - foreach (HitObject obj in selectionHandler.SelectedHitObjects) - obj.StartTime += offset; - } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From e04c77178cfa94d7e89a6e0527b749114c4a41ba Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Oct 2019 14:58:02 +0900 Subject: [PATCH 3592/5608] Move selection events to BlueprintContainer --- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 35 ------------------- .../Compose/Components/BlueprintContainer.cs | 21 +++++++++-- 2 files changed, 19 insertions(+), 37 deletions(-) diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 8a6e8f6128..44f38acfd4 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -6,8 +6,6 @@ using osu.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; -using osu.Framework.Input.Events; -using osu.Framework.Input.States; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Objects.Drawables; using osuTK; @@ -29,12 +27,6 @@ namespace osu.Game.Rulesets.Edit /// public event Action Deselected; - /// - /// Invoked when this has requested selection. - /// Will fire even if already selected. Does not actually perform selection. - /// - public event Action SelectionRequested; - /// /// The which this applies to. /// @@ -99,33 +91,6 @@ namespace osu.Game.Rulesets.Edit public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => DrawableObject.ReceivePositionalInputAt(screenSpacePos); - private bool selectionRequested; - - protected override bool OnMouseDown(MouseDownEvent e) - { - selectionRequested = false; - - if (State == SelectionState.NotSelected) - { - SelectionRequested?.Invoke(this, e.CurrentState); - selectionRequested = true; - } - - return IsSelected; - } - - protected override bool OnClick(ClickEvent e) - { - if (State == SelectionState.Selected && !selectionRequested) - { - selectionRequested = true; - SelectionRequested?.Invoke(this, e.CurrentState); - return true; - } - - return base.OnClick(e); - } - /// /// The screen-space point that causes this to be selected. /// diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 2f401ede38..089f1bde9c 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -109,7 +109,6 @@ namespace osu.Game.Screens.Edit.Compose.Components blueprint.Selected -= onBlueprintSelected; blueprint.Deselected -= onBlueprintDeselected; - blueprint.SelectionRequested -= onSelectionRequested; selectionBlueprints.Remove(blueprint); } @@ -124,15 +123,31 @@ namespace osu.Game.Screens.Edit.Compose.Components blueprint.Selected += onBlueprintSelected; blueprint.Deselected += onBlueprintDeselected; - blueprint.SelectionRequested += onSelectionRequested; selectionBlueprints.Add(blueprint); } private void removeBlueprintFor(DrawableHitObject hitObject) => removeBlueprintFor(hitObject.HitObject); + protected override bool OnMouseDown(MouseDownEvent e) + { + foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) + { + if (blueprint.IsHovered) + { + selectionHandler.HandleSelectionRequested(blueprint, e.CurrentState); + break; + } + } + + return true; + } + protected override bool OnClick(ClickEvent e) { + if (selectionBlueprints.AliveBlueprints.Any(b => b.IsHovered)) + return true; + deselectAll(); return true; } @@ -298,6 +313,8 @@ namespace osu.Game.Screens.Edit.Compose.Components private class SelectionBlueprintContainer : Container { + public IEnumerable AliveBlueprints => AliveInternalChildren.Cast(); + protected override int Compare(Drawable x, Drawable y) { if (!(x is SelectionBlueprint xBlueprint) || !(y is SelectionBlueprint yBlueprint)) From f128e99fb2a0e16043730d05164620aeeab362e1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Oct 2019 15:07:04 +0900 Subject: [PATCH 3593/5608] Remove unused methods --- .../Screens/Edit/Compose/Components/BlueprintContainer.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 089f1bde9c..a2893c735e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Input; using osu.Framework.Input.Events; -using osu.Framework.Input.States; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Objects; @@ -127,8 +126,6 @@ namespace osu.Game.Screens.Edit.Compose.Components selectionBlueprints.Add(blueprint); } - private void removeBlueprintFor(DrawableHitObject hitObject) => removeBlueprintFor(hitObject.HitObject); - protected override bool OnMouseDown(MouseDownEvent e) { foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) @@ -239,8 +236,6 @@ namespace osu.Game.Screens.Edit.Compose.Components SelectionChanged?.Invoke(selectionHandler.SelectedHitObjects); } - private void onSelectionRequested(SelectionBlueprint blueprint, InputState state) => selectionHandler.HandleSelectionRequested(blueprint, state); - private Vector2? screenSpaceMovementStartPosition; private SelectionBlueprint movementBlueprint; From a07e5a269b4d5b6dd0b23432779026e82847d371 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Oct 2019 15:11:54 +0900 Subject: [PATCH 3594/5608] Extract drag events into multiple methods --- .../Compose/Components/BlueprintContainer.cs | 109 ++++++++++++------ 1 file changed, 72 insertions(+), 37 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index a2893c735e..e442e1b0b2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -160,6 +160,33 @@ namespace osu.Game.Screens.Edit.Compose.Components return base.OnMouseMove(e); } + protected override bool OnDragStart(DragStartEvent e) + { + if (!beginSelectionMovement()) + dragBox.FadeIn(250, Easing.OutQuint); + + return true; + } + + protected override bool OnDrag(DragEvent e) + { + if (!moveCurrentSelection(e)) + dragBox.UpdateDrag(e); + + return true; + } + + protected override bool OnDragEnd(DragEndEvent e) + { + if (!finishSelectionMovement()) + { + dragBox.FadeOut(250, Easing.OutQuint); + selectionHandler.UpdateVisibility(); + } + + return true; + } + protected override void Update() { base.Update(); @@ -239,58 +266,66 @@ namespace osu.Game.Screens.Edit.Compose.Components private Vector2? screenSpaceMovementStartPosition; private SelectionBlueprint movementBlueprint; - protected override bool OnDragStart(DragStartEvent e) + /// + /// Attempts to begin the movement of any selected blueprints. + /// + /// Whether movement began. + private bool beginSelectionMovement() { - if (selectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) - { - // The earliest hitobject is used for drag-movement/snapping - movementBlueprint = selectionHandler.SelectedBlueprints.OrderBy(b => b.DrawableObject.HitObject.StartTime).First(); - screenSpaceMovementStartPosition = movementBlueprint.DrawableObject.ToScreenSpace(movementBlueprint.DrawableObject.OriginPosition); - } - else - dragBox.FadeIn(250, Easing.OutQuint); + Debug.Assert(movementBlueprint == null); + + // Any selected blueprints can begin the movement of the group, however only the earliest hitobject is used for movement + if (!selectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) + return false; + + // Movement is tracked from the blueprint of the earliest hitobject, since it only makes sense to distance snap from that hitobject + movementBlueprint = selectionHandler.SelectedBlueprints.OrderBy(b => b.DrawableObject.HitObject.StartTime).First(); + screenSpaceMovementStartPosition = movementBlueprint.DrawableObject.ToScreenSpace(movementBlueprint.DrawableObject.OriginPosition); return true; } - protected override bool OnDrag(DragEvent e) + /// + /// Moves the current selected blueprints. + /// + /// The defining the movement event. + /// Whether a movement was active. + private bool moveCurrentSelection(DragEvent e) { - if (movementBlueprint != null) - { - Debug.Assert(screenSpaceMovementStartPosition != null); + if (movementBlueprint == null) + return false; - Vector2 startPosition = screenSpaceMovementStartPosition.Value; - HitObject draggedObject = movementBlueprint.DrawableObject.HitObject; + Debug.Assert(screenSpaceMovementStartPosition != null); - Vector2 movePosition = startPosition + e.ScreenSpaceMousePosition - e.ScreenSpaceMouseDownPosition; - Vector2 snappedPosition = composer.GetSnappedPosition(ToLocalSpace(movePosition)); + Vector2 startPosition = screenSpaceMovementStartPosition.Value; + HitObject draggedObject = movementBlueprint.DrawableObject.HitObject; - // Move the hitobjects - selectionHandler.HandleMovement(new MoveSelectionEvent(movementBlueprint, startPosition, ToScreenSpace(snappedPosition))); + // The final movement position, relative to screenSpaceMovementStartPosition + Vector2 movePosition = startPosition + e.ScreenSpaceMousePosition - e.ScreenSpaceMouseDownPosition; + Vector2 snappedPosition = composer.GetSnappedPosition(ToLocalSpace(movePosition)); - // Apply the start time at the newly snapped-to position - double offset = composer.GetSnappedTime(draggedObject.StartTime, snappedPosition) - draggedObject.StartTime; - foreach (HitObject obj in selectionHandler.SelectedHitObjects) - obj.StartTime += offset; - } - else - dragBox.UpdateDrag(e); + // Move the hitobjects + selectionHandler.HandleMovement(new MoveSelectionEvent(movementBlueprint, startPosition, ToScreenSpace(snappedPosition))); + + // Apply the start time at the newly snapped-to position + double offset = composer.GetSnappedTime(draggedObject.StartTime, snappedPosition) - draggedObject.StartTime; + foreach (HitObject obj in selectionHandler.SelectedHitObjects) + obj.StartTime += offset; return true; } - protected override bool OnDragEnd(DragEndEvent e) + /// + /// Finishes the current movement of selected blueprints. + /// + /// Whether a movement was active. + private bool finishSelectionMovement() { - if (movementBlueprint != null) - { - screenSpaceMovementStartPosition = null; - movementBlueprint = null; - } - else - { - dragBox.FadeOut(250, Easing.OutQuint); - selectionHandler.UpdateVisibility(); - } + if (movementBlueprint == null) + return false; + + screenSpaceMovementStartPosition = null; + movementBlueprint = null; return true; } From 8e4a21bee756c610c61e4be2d1737b6d5d2aa7f7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Oct 2019 15:58:22 +0900 Subject: [PATCH 3595/5608] Separate out mouse down/click/up handling --- .../Compose/Components/BlueprintContainer.cs | 61 ++++++++++++++++--- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index e442e1b0b2..123fdc78e6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Input; using osu.Framework.Input.Events; +using osu.Framework.Input.States; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Objects; @@ -128,27 +129,27 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnMouseDown(MouseDownEvent e) { - foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) - { - if (blueprint.IsHovered) - { - selectionHandler.HandleSelectionRequested(blueprint, e.CurrentState); - break; - } - } - + beginClickSelection(e); return true; } protected override bool OnClick(ClickEvent e) { - if (selectionBlueprints.AliveBlueprints.Any(b => b.IsHovered)) + // clickSelectionBegan will be true if a mouse down occurred on the blueprint but the click event was received outside of the blueprint + // otherwise, deselection should only occur if the click event did not occur on top of a selected blueprint + if (clickSelectionBegan || selectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) return true; deselectAll(); return true; } + protected override bool OnMouseUp(MouseUpEvent e) + { + endClickSelection(); + return true; + } + protected override bool OnMouseMove(MouseMoveEvent e) { if (currentPlacement != null) @@ -227,6 +228,40 @@ namespace osu.Game.Screens.Edit.Compose.Components currentPlacement.UpdatePosition(snappedScreenSpacePosition); } + #region Selection + + /// + /// Whether a blueprint was selected by a previous click event. + /// + private bool clickSelectionBegan; + + /// + /// Attempts to select any hovered blueprints. + /// + /// The input event that triggered this selection. + private void beginClickSelection(UIEvent e) + { + Debug.Assert(!clickSelectionBegan); + + foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) + { + if (blueprint.IsHovered) + { + selectionHandler.HandleSelectionRequested(blueprint, e.CurrentState); + clickSelectionBegan = true; + break; + } + } + } + + /// + /// Finishes the current blueprint selection. + /// + private void endClickSelection() + { + clickSelectionBegan = false; + } + /// /// Select all masks in a given rectangle selection area. /// @@ -263,6 +298,10 @@ namespace osu.Game.Screens.Edit.Compose.Components SelectionChanged?.Invoke(selectionHandler.SelectedHitObjects); } + #endregion + + #region Selection Movement + private Vector2? screenSpaceMovementStartPosition; private SelectionBlueprint movementBlueprint; @@ -330,6 +369,8 @@ namespace osu.Game.Screens.Edit.Compose.Components return true; } + #endregion + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From 45bd91f63fd10fd9c617fb6082f64166f90db160 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Oct 2019 16:14:29 +0900 Subject: [PATCH 3596/5608] Add special cases for click-selection --- .../Compose/Components/BlueprintContainer.cs | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 123fdc78e6..8d87af6931 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Input; using osu.Framework.Input.Events; -using osu.Framework.Input.States; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Objects; @@ -135,9 +134,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnClick(ClickEvent e) { - // clickSelectionBegan will be true if a mouse down occurred on the blueprint but the click event was received outside of the blueprint - // otherwise, deselection should only occur if the click event did not occur on top of a selected blueprint - if (clickSelectionBegan || selectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) + // Deselection should only occur if no selected blueprints are hovered + // A special case for when a blueprint was selected via this click is added since OnClick() may occur outside the hitobject and should not trigger deselection + if (endClickSelection() || selectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) return true; deselectAll(); @@ -146,7 +145,8 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnMouseUp(MouseUpEvent e) { - endClickSelection(); + // Special case for when a drag happened instead of a click + Schedule(() => endClickSelection()); return true; } @@ -257,9 +257,14 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Finishes the current blueprint selection. /// - private void endClickSelection() + /// Whether a click selection was active. + private bool endClickSelection() { + if (!clickSelectionBegan) + return false; + clickSelectionBegan = false; + return true; } /// @@ -313,8 +318,9 @@ namespace osu.Game.Screens.Edit.Compose.Components { Debug.Assert(movementBlueprint == null); - // Any selected blueprints can begin the movement of the group, however only the earliest hitobject is used for movement - if (!selectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) + // Any selected blueprint that is hovered can begin the movement of the group, however only the earliest hitobject is used for movement + // A special case is added for when a click selection occurred before the drag + if (!clickSelectionBegan && !selectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) return false; // Movement is tracked from the blueprint of the earliest hitobject, since it only makes sense to distance snap from that hitobject From fb88001c0ed0476c767bab32182bd8eac3f7018c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Oct 2019 16:17:48 +0900 Subject: [PATCH 3597/5608] Reorder blueprint addition/removal + add regions --- .../Compose/Components/BlueprintContainer.cs | 82 ++++++++++--------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 8d87af6931..d3cd0b1d65 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -89,43 +89,6 @@ namespace osu.Game.Screens.Edit.Compose.Components } } - private void addBlueprintFor(HitObject hitObject) - { - var drawable = composer.HitObjects.FirstOrDefault(d => d.HitObject == hitObject); - if (drawable == null) - return; - - addBlueprintFor(drawable); - } - - private void removeBlueprintFor(HitObject hitObject) - { - var blueprint = selectionBlueprints.Single(m => m.DrawableObject.HitObject == hitObject); - if (blueprint == null) - return; - - blueprint.Deselect(); - - blueprint.Selected -= onBlueprintSelected; - blueprint.Deselected -= onBlueprintDeselected; - - selectionBlueprints.Remove(blueprint); - } - - private void addBlueprintFor(DrawableHitObject hitObject) - { - refreshTool(); - - var blueprint = composer.CreateBlueprintFor(hitObject); - if (blueprint == null) - return; - - blueprint.Selected += onBlueprintSelected; - blueprint.Deselected += onBlueprintDeselected; - - selectionBlueprints.Add(blueprint); - } - protected override bool OnMouseDown(MouseDownEvent e) { beginClickSelection(e); @@ -201,6 +164,49 @@ namespace osu.Game.Screens.Edit.Compose.Components } } + #region Blueprint Addition/Removal + + private void addBlueprintFor(HitObject hitObject) + { + var drawable = composer.HitObjects.FirstOrDefault(d => d.HitObject == hitObject); + if (drawable == null) + return; + + addBlueprintFor(drawable); + } + + private void removeBlueprintFor(HitObject hitObject) + { + var blueprint = selectionBlueprints.Single(m => m.DrawableObject.HitObject == hitObject); + if (blueprint == null) + return; + + blueprint.Deselect(); + + blueprint.Selected -= onBlueprintSelected; + blueprint.Deselected -= onBlueprintDeselected; + + selectionBlueprints.Remove(blueprint); + } + + private void addBlueprintFor(DrawableHitObject hitObject) + { + refreshTool(); + + var blueprint = composer.CreateBlueprintFor(hitObject); + if (blueprint == null) + return; + + blueprint.Selected += onBlueprintSelected; + blueprint.Deselected += onBlueprintDeselected; + + selectionBlueprints.Add(blueprint); + } + + #endregion + + #region Placement + /// /// Refreshes the current placement tool. /// @@ -228,6 +234,8 @@ namespace osu.Game.Screens.Edit.Compose.Components currentPlacement.UpdatePosition(snappedScreenSpacePosition); } + #endregion + #region Selection /// From 7a71352684566cfa1649753181981160a9b203d4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Oct 2019 17:22:14 +0900 Subject: [PATCH 3598/5608] Fix drag box being positioned incorrectly for 1 frame --- osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs | 3 +++ osu.Game/Screens/Edit/Compose/Components/DragBox.cs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index d3cd0b1d65..30f0f94128 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -127,7 +127,10 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnDragStart(DragStartEvent e) { if (!beginSelectionMovement()) + { + dragBox.UpdateDrag(e); dragBox.FadeIn(250, Easing.OutQuint); + } return true; } diff --git a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs index 7d892aa889..2a510e74fd 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens.Edit.Compose.Components }; } - public void UpdateDrag(DragEvent e) + public void UpdateDrag(MouseButtonEvent e) { var dragPosition = e.ScreenSpaceMousePosition; var dragStartPosition = e.ScreenSpaceMouseDownPosition; From f45f17339c9d6c4d4c7d61020cbcfdd8ad090ac3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Oct 2019 18:09:20 +0900 Subject: [PATCH 3599/5608] Implement slider path distance snapping --- .../Blueprints/Sliders/SliderPlacementBlueprint.cs | 11 +++++++++-- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 4 ++++ .../Edit/Compose/Components/DistanceSnapGrid.cs | 7 +++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index b7b8d0af88..e1478a062c 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -33,6 +33,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private PlacementState state; + [Resolved] + private HitObjectComposer composer { get; set; } + public SliderPlacementBlueprint() : base(new Objects.Slider()) { @@ -131,8 +134,12 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private void updateSlider() { - var newControlPoints = segments.SelectMany(s => s.ControlPoints).Concat(cursor.Yield()).ToArray(); - HitObject.Path = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints); + Vector2[] newControlPoints = segments.SelectMany(s => s.ControlPoints).Concat(cursor.Yield()).ToArray(); + + var unsnappedPath = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints); + var snappedDistance = composer.GetSnappedDistance((float)unsnappedPath.Distance); + + HitObject.Path = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints, snappedDistance); bodyPiece.UpdateFrom(HitObject); headCirclePiece.UpdateFrom(HitObject.HeadCircle); diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 6396301add..f9d2734e80 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -261,6 +261,8 @@ namespace osu.Game.Rulesets.Edit public override double GetSnappedTime(double startTime, Vector2 position) => distanceSnapGrid?.GetSnapTime(position) ?? startTime; + public override float GetSnappedDistance(float distance) => distanceSnapGrid?.GetSnapDistance(distance) ?? distance; + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -313,5 +315,7 @@ namespace osu.Game.Rulesets.Edit public abstract Vector2 GetSnappedPosition(Vector2 position); public abstract double GetSnappedTime(double startTime, Vector2 screenSpacePosition); + + public abstract float GetSnappedDistance(float distance); } } diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 096ff0a6dd..3bedff79f5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -128,6 +128,13 @@ namespace osu.Game.Screens.Edit.Compose.Components /// The time at the snapped position. public double GetSnapTime(Vector2 position) => startTime + (position - CentrePosition).Length / Velocity; + /// + /// Snaps a distance by the snap distance of this grid. + /// + /// The distance to snap. + /// The snapped distance. + public float GetSnapDistance(float distance) => (int)(distance / DistanceSpacing) * DistanceSpacing; + /// /// Retrieves the applicable colour for a beat index. /// From d83b9ef0e4078688dd1b27cb243b4c147144de96 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Oct 2019 18:17:54 +0900 Subject: [PATCH 3600/5608] Rename grid snapping methods --- osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs | 4 ++-- osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs | 6 +++--- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 6 +++--- .../Edit/Compose/Components/CircularDistanceSnapGrid.cs | 2 +- .../Screens/Edit/Compose/Components/DistanceSnapGrid.cs | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index 6b8daa531f..fddbcea374 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -142,7 +142,7 @@ namespace osu.Game.Rulesets.Osu.Tests private void assertSnappedDistance(float expectedDistance) => AddAssert($"snap distance = {expectedDistance}", () => { - Vector2 snappedPosition = grid.GetSnapPosition(grid.ToLocalSpace(InputManager.CurrentState.Mouse.Position)); + Vector2 snappedPosition = grid.GetSnappedPosition(grid.ToLocalSpace(InputManager.CurrentState.Mouse.Position)); float distance = Vector2.Distance(snappedPosition, grid_position); return Precision.AlmostEquals(expectedDistance, distance); @@ -160,7 +160,7 @@ namespace osu.Game.Rulesets.Osu.Tests Colour = Color4.SlateGray }, grid = new TestOsuDistanceSnapGrid(new HitCircle { Position = grid_position }), - new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnapPosition(grid.ToLocalSpace(v)) } + new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)) } }; }); } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index a9e5930478..54d910fdcf 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -106,10 +106,10 @@ namespace osu.Game.Tests.Visual.Editor Vector2 snapPosition = Vector2.Zero; AddStep("get first tick position", () => snapPosition = grid_position + new Vector2((float)beat_length, 0)); - AddAssert("snap time is 1 beat away", () => Precision.AlmostEquals(beat_length, grid.GetSnapTime(snapPosition), 0.01)); + AddAssert("snap time is 1 beat away", () => Precision.AlmostEquals(beat_length, grid.GetSnappedTime(snapPosition), 0.01)); createGrid(g => g.Velocity = 2, "with velocity = 2"); - AddAssert("snap time is now 0.5 beats away", () => Precision.AlmostEquals(beat_length / 2, grid.GetSnapTime(snapPosition), 0.01)); + AddAssert("snap time is now 0.5 beats away", () => Precision.AlmostEquals(beat_length / 2, grid.GetSnappedTime(snapPosition), 0.01)); } private void createGrid(Action func = null, string description = null) @@ -206,7 +206,7 @@ namespace osu.Game.Tests.Visual.Editor protected override float GetVelocity(double time, ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) => Velocity; - public override Vector2 GetSnapPosition(Vector2 screenSpacePosition) + public override Vector2 GetSnappedPosition(Vector2 screenSpacePosition) => Vector2.Zero; } } diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index f9d2734e80..3c24c3dd1f 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -257,11 +257,11 @@ namespace osu.Game.Rulesets.Edit public void Delete(HitObject hitObject) => EditorBeatmap.Remove(hitObject); - public override Vector2 GetSnappedPosition(Vector2 position) => distanceSnapGrid?.GetSnapPosition(position) ?? position; + public override Vector2 GetSnappedPosition(Vector2 position) => distanceSnapGrid?.GetSnappedPosition(position) ?? position; - public override double GetSnappedTime(double startTime, Vector2 position) => distanceSnapGrid?.GetSnapTime(position) ?? startTime; + public override double GetSnappedTime(double startTime, Vector2 position) => distanceSnapGrid?.GetSnappedTime(position) ?? startTime; - public override float GetSnappedDistance(float distance) => distanceSnapGrid?.GetSnapDistance(distance) ?? distance; + public override float GetSnappedDistance(float distance) => distanceSnapGrid?.GetSnappedDistance(distance) ?? distance; protected override void Dispose(bool isDisposing) { diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index a644e51c13..381ae9f927 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -63,7 +63,7 @@ namespace osu.Game.Screens.Edit.Compose.Components } } - public override Vector2 GetSnapPosition(Vector2 position) + public override Vector2 GetSnappedPosition(Vector2 position) { Vector2 direction = position - CentrePosition; diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 3bedff79f5..50c69ae561 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -119,21 +119,21 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// The original position in coordinate space local to this . /// The snapped position in coordinate space local to this . - public abstract Vector2 GetSnapPosition(Vector2 position); + public abstract Vector2 GetSnappedPosition(Vector2 position); /// /// Retrieves the time at a snapped position. /// /// The snapped position in coordinate space local to this . /// The time at the snapped position. - public double GetSnapTime(Vector2 position) => startTime + (position - CentrePosition).Length / Velocity; + public double GetSnappedTime(Vector2 position) => startTime + (position - CentrePosition).Length / Velocity; /// /// Snaps a distance by the snap distance of this grid. /// /// The distance to snap. /// The snapped distance. - public float GetSnapDistance(float distance) => (int)(distance / DistanceSpacing) * DistanceSpacing; + public float GetSnappedDistance(float distance) => (int)(distance / DistanceSpacing) * DistanceSpacing; /// /// Retrieves the applicable colour for a beat index. From a969914d6ed0be5aadee0d3c40e43d0e640a5319 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Oct 2019 18:24:22 +0900 Subject: [PATCH 3601/5608] Mention coordinate space --- osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 50c69ae561..250a0abef5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -131,7 +131,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Snaps a distance by the snap distance of this grid. /// - /// The distance to snap. + /// The distance to snap in coordinate space local to this . /// The snapped distance. public float GetSnappedDistance(float distance) => (int)(distance / DistanceSpacing) * DistanceSpacing; From 0af5706db6f02c68a15302cf3b9fc0cf9b3a25a2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Oct 2019 19:02:59 +0900 Subject: [PATCH 3602/5608] Snap path during control point movement --- .../Sliders/Components/PathControlPointPiece.cs | 6 ++++-- .../Components/PathControlPointVisualiser.cs | 6 +++++- .../Sliders/SliderPlacementBlueprint.cs | 2 +- .../Sliders/SliderSelectionBlueprint.cs | 17 ++++++++++++++++- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 3aec7c2872..7afb8fcf49 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -8,7 +9,6 @@ using osu.Framework.Graphics.Lines; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osuTK; @@ -16,6 +16,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public class PathControlPointPiece : BlueprintPiece { + public Action ControlPointsChanged; + private readonly Slider slider; private readonly int index; @@ -96,7 +98,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components if (isSegmentSeparatorWithPrevious) newControlPoints[index - 1] = newControlPoints[index]; - slider.Path = new SliderPath(slider.Path.Type, newControlPoints); + ControlPointsChanged?.Invoke(newControlPoints); return true; } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 24fcc460d1..0385824b27 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -1,14 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu.Objects; +using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public class PathControlPointVisualiser : CompositeDrawable { + public Action ControlPointsChanged; + private readonly Slider slider; private readonly Container pieces; @@ -25,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components base.Update(); while (slider.Path.ControlPoints.Length > pieces.Count) - pieces.Add(new PathControlPointPiece(slider, pieces.Count)); + pieces.Add(new PathControlPointPiece(slider, pieces.Count) { ControlPointsChanged = c => ControlPointsChanged?.Invoke(c) }); while (slider.Path.ControlPoints.Length < pieces.Count) pieces.Remove(pieces[pieces.Count - 1]); } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index e1478a062c..761c2961ea 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders bodyPiece = new SliderBodyPiece(), headCirclePiece = new HitCirclePiece(), tailCirclePiece = new HitCirclePiece(), - new PathControlPointVisualiser(HitObject), + new PathControlPointVisualiser(HitObject) { ControlPointsChanged = _ => updateSlider() }, }; setState(PlacementState.Initial); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index fdeffc6f8a..a62c3cbb9f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -1,7 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -15,6 +19,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders protected readonly SliderCircleSelectionBlueprint HeadBlueprint; protected readonly SliderCircleSelectionBlueprint TailBlueprint; + [Resolved] + private HitObjectComposer composer { get; set; } + public SliderSelectionBlueprint(DrawableSlider slider) : base(slider) { @@ -25,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders BodyPiece = new SliderBodyPiece(), HeadBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.Start), TailBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.End), - new PathControlPointVisualiser(sliderObject), + new PathControlPointVisualiser(sliderObject) { ControlPointsChanged = onNewControlPoints }, }; } @@ -36,6 +43,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders BodyPiece.UpdateFrom(HitObject); } + private void onNewControlPoints(Vector2[] controlPoints) + { + var unsnappedPath = new SliderPath(controlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, controlPoints); + var snappedDistance = composer.GetSnappedDistance((float)unsnappedPath.Distance); + + HitObject.Path = new SliderPath(unsnappedPath.Type, controlPoints, snappedDistance); + } + public override Vector2 SelectionPoint => HeadBlueprint.SelectionPoint; protected virtual SliderCircleSelectionBlueprint CreateCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position) => new SliderCircleSelectionBlueprint(slider, position); From b7af4acdbf21bd3c3e521b1b12abb63d53341ea6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Oct 2019 19:04:00 +0900 Subject: [PATCH 3603/5608] Allow not having a composer --- .../Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs | 4 ++-- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 761c2961ea..400a1fea14 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private PlacementState state; - [Resolved] + [Resolved(CanBeNull = true)] private HitObjectComposer composer { get; set; } public SliderPlacementBlueprint() @@ -137,7 +137,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders Vector2[] newControlPoints = segments.SelectMany(s => s.ControlPoints).Concat(cursor.Yield()).ToArray(); var unsnappedPath = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints); - var snappedDistance = composer.GetSnappedDistance((float)unsnappedPath.Distance); + var snappedDistance = composer?.GetSnappedDistance((float)unsnappedPath.Distance) ?? (float)unsnappedPath.Distance; HitObject.Path = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints, snappedDistance); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index a62c3cbb9f..a90ed677ff 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders protected readonly SliderCircleSelectionBlueprint HeadBlueprint; protected readonly SliderCircleSelectionBlueprint TailBlueprint; - [Resolved] + [Resolved(CanBeNull = true)] private HitObjectComposer composer { get; set; } public SliderSelectionBlueprint(DrawableSlider slider) @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private void onNewControlPoints(Vector2[] controlPoints) { var unsnappedPath = new SliderPath(controlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, controlPoints); - var snappedDistance = composer.GetSnappedDistance((float)unsnappedPath.Distance); + var snappedDistance = composer?.GetSnappedDistance((float)unsnappedPath.Distance) ?? (float)unsnappedPath.Distance; HitObject.Path = new SliderPath(unsnappedPath.Type, controlPoints, snappedDistance); } From a6458fdeab45510f6cf92956cfbd038237009bb6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Oct 2019 19:04:24 +0900 Subject: [PATCH 3604/5608] Re-use slider type --- .../Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 400a1fea14..02923203b1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -139,7 +139,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders var unsnappedPath = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints); var snappedDistance = composer?.GetSnappedDistance((float)unsnappedPath.Distance) ?? (float)unsnappedPath.Distance; - HitObject.Path = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints, snappedDistance); + HitObject.Path = new SliderPath(unsnappedPath.Type, newControlPoints, snappedDistance); bodyPiece.UpdateFrom(HitObject); headCirclePiece.UpdateFrom(HitObject.HeadCircle); From a89ea78a7a54caa26d2882f12cdb7e086e4f937f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 22 Oct 2019 00:34:33 +0200 Subject: [PATCH 3605/5608] Add extended testing for Markdown links While reviewing #6542 it became apparent that there was another Markdown link format variant, used in comments that came from the web API, called the "inline link" style. It allows to specify the tooltip title within the actual URL portion, as such: [link text](https://osu.ppy.sh "tooltip text") Add tests with a couple of easy and trickier examples of such a format. Moreover, add a new edge case of a Markdown link with a link inside the display text, which during tests was detected to be problematic. --- osu.Game.Tests/Chat/MessageFormatterTests.cs | 48 ++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs index 9b4a90e9a9..1cbd083f0d 100644 --- a/osu.Game.Tests/Chat/MessageFormatterTests.cs +++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs @@ -273,6 +273,54 @@ namespace osu.Game.Tests.Chat Assert.AreEqual(21, result.Links[0].Length); } + [Test] + public void TestMarkdownFormatLinkWithInlineTitle() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "I haven't seen [this link format](https://osu.ppy.sh \"osu!\") before..." }); + + Assert.AreEqual("I haven't seen this link format before...", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(15, result.Links[0].Index); + Assert.AreEqual(16, result.Links[0].Length); + } + + [Test] + public void TestMarkdownFormatLinkWithInlineTitleAndEscapedQuotes() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "I haven't seen [this link format](https://osu.ppy.sh \"inner quote \\\" just to confuse \") before..." }); + + Assert.AreEqual("I haven't seen this link format before...", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(15, result.Links[0].Index); + Assert.AreEqual(16, result.Links[0].Length); + } + + [Test] + public void TestMarkdownFormatLinkWithUrlInTextAndInlineTitle() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "I haven't seen [https://osu.ppy.sh](https://osu.ppy.sh \"https://osu.ppy.sh\") before..." }); + + Assert.AreEqual("I haven't seen https://osu.ppy.sh before...", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(15, result.Links[0].Index); + Assert.AreEqual(18, result.Links[0].Length); + } + + [Test] + public void TestMarkdownFormatLinkWithMisleadingUrlInText() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "I haven't seen [https://google.com](https://osu.ppy.sh) before..." }); + + Assert.AreEqual("I haven't seen https://google.com before...", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(15, result.Links[0].Index); + Assert.AreEqual(18, result.Links[0].Length); + } + [Test] public void TestChannelLink() { From 24b71605227c247a37937dacafeaf2d600007760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 22 Oct 2019 00:40:58 +0200 Subject: [PATCH 3606/5608] Add support for parsing Markdown inline links Extend the Markdown parsing regex to allow parsing so-called inline links. Within the parenthesis () part of the Markdown URL syntax, introduce a new capturing group: ( \s+ // whitespace between actual URL and inline title (? // start of "title" named group "" // opening double quote (doubled inside @ string) ( [^""] // any character but a double quote | // or (?<=\\) // the next character should be preceded by a \ "" // a double quote )* // zero or more times "" // closing double quote ) )? // the whole group is optional This allows for parsing the inline links as-provided by web. Correctness is displayed by the passing tests. --- osu.Game/Online/Chat/MessageFormatter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 24d17612ee..749d24ee75 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -20,7 +20,7 @@ namespace osu.Game.Online.Chat private static readonly Regex new_link_regex = new Regex(@"\[(?<url>[a-z]+://[^ ]+) (?<text>(((?<=\\)[\[\]])|[^\[\]])*(((?<open>\[)(((?<=\\)[\[\]])|[^\[\]])*)+((?<close-open>\])(((?<=\\)[\[\]])|[^\[\]])*)+)*(?(open)(?!)))\]"); // [test](https://osu.ppy.sh/b/1234) -> test (https://osu.ppy.sh/b/1234) aka correct markdown format - private static readonly Regex markdown_link_regex = new Regex(@"\[(?<text>(((?<=\\)[\[\]])|[^\[\]])*(((?<open>\[)(((?<=\\)[\[\]])|[^\[\]])*)+((?<close-open>\])(((?<=\\)[\[\]])|[^\[\]])*)+)*(?(open)(?!)))\]\((?<url>[a-z]+://[^ ]+)\)"); + private static readonly Regex markdown_link_regex = new Regex(@"\[(?<text>(((?<=\\)[\[\]])|[^\[\]])*(((?<open>\[)(((?<=\\)[\[\]])|[^\[\]])*)+((?<close-open>\])(((?<=\\)[\[\]])|[^\[\]])*)+)*(?(open)(?!)))\]\((?<url>[a-z]+://[^ ]+)(\s+(?<title>""([^""]|(?<=\\)"")*""))?\)"); // advanced, RFC-compatible regular expression that matches any possible URL, *but* allows certain invalid characters that are widely used // This is in the format (<required>, [optional]): From cbd99cc767085bf79f17682e2ffe2845330d39f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= <dach.bartlomiej@gmail.com> Date: Tue, 22 Oct 2019 01:01:37 +0200 Subject: [PATCH 3607/5608] Resolve link-in-link edge case Testing with #6542 surfaced a crash scenario, caused by formatted links that had URLs in the display text, for example [mean example - https://osu.ppy.sh](https://osu.ppy.sh) In that case the outer Markdown link would get picked up once, and then reduced to the link text when looking for other links, leading to it being picked up again the second time when the raw link is found. Add a check in the raw link parsing path that ensures that the found URL is not a part of a bigger, pre-existing link. --- osu.Game.Tests/Chat/MessageFormatterTests.cs | 12 ++++++++++++ osu.Game/Online/Chat/MessageFormatter.cs | 18 +++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs index 1cbd083f0d..7988c6b96d 100644 --- a/osu.Game.Tests/Chat/MessageFormatterTests.cs +++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs @@ -309,6 +309,18 @@ namespace osu.Game.Tests.Chat Assert.AreEqual(18, result.Links[0].Length); } + [Test] + public void TestMarkdownFormatLinkWithUrlAndTextInTitle() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "I haven't seen [oh no, text here! https://osu.ppy.sh](https://osu.ppy.sh) before..." }); + + Assert.AreEqual("I haven't seen oh no, text here! https://osu.ppy.sh before...", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(15, result.Links[0].Index); + Assert.AreEqual(36, result.Links[0].Length); + } + [Test] public void TestMarkdownFormatLinkWithMisleadingUrlInText() { diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 749d24ee75..d77920c97d 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -95,11 +95,17 @@ namespace osu.Game.Online.Chat foreach (Match m in regex.Matches(result.Text, startIndex)) { var index = m.Index; - var link = m.Groups["link"].Value; - var indexLength = link.Length; + var linkText = m.Groups["link"].Value; + var indexLength = linkText.Length; - var details = getLinkDetails(link); - result.Links.Add(new Link(link, index, indexLength, details.Action, details.Argument)); + var details = getLinkDetails(linkText); + var link = new Link(linkText, index, indexLength, details.Action, details.Argument); + + // sometimes an already-processed formatted link can reduce to a simple URL, too + // (example: [mean example - https://osu.ppy.sh](https://osu.ppy.sh)) + // therefore we need to check if any of the pre-existing links contains the raw one we found + if (result.Links.All(existingLink => !existingLink.Contains(link))) + result.Links.Add(link); } } @@ -292,6 +298,8 @@ namespace osu.Game.Online.Chat Argument = argument; } + public bool Contains(Link otherLink) => otherLink.Index >= Index && otherLink.Index + otherLink.Length <= Index + Length; + public int CompareTo(Link otherLink) => Index > otherLink.Index ? 1 : -1; } } From 85769982a01fb95da961bb5d2c23abfaa8669380 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski <megaman9919@gmail.com> Date: Thu, 24 Oct 2019 17:49:34 +0300 Subject: [PATCH 3608/5608] Refactor LoadingButton --- .../Graphics/UserInterface/LoadingButton.cs | 26 +++------- .../Graphics/UserInterface/ShowMoreButton.cs | 49 +++++++++++-------- osu.Game/Overlays/Comments/VotePill.cs | 29 ++++++----- 3 files changed, 54 insertions(+), 50 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/LoadingButton.cs b/osu.Game/Graphics/UserInterface/LoadingButton.cs index c177431c78..49ec18ce8e 100644 --- a/osu.Game/Graphics/UserInterface/LoadingButton.cs +++ b/osu.Game/Graphics/UserInterface/LoadingButton.cs @@ -2,7 +2,6 @@ // 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.Events; using osu.Game.Graphics.Containers; using osuTK; @@ -11,8 +10,6 @@ namespace osu.Game.Graphics.UserInterface { public abstract class LoadingButton : OsuHoverContainer { - private const float fade_duration = 200; - private bool isLoading; public bool IsLoading @@ -27,14 +24,12 @@ namespace osu.Game.Graphics.UserInterface if (value) { loading.Show(); - text.FadeOut(fade_duration, Easing.OutQuint); - OnLoadingStart(); + OnLoadStarted(); } else { loading.Hide(); - text.FadeIn(fade_duration, Easing.OutQuint); - OnLoadingFinished(); + OnLoadFinished(); } } } @@ -46,17 +41,12 @@ namespace osu.Game.Graphics.UserInterface } private readonly LoadingAnimation loading; - private readonly Drawable text; protected LoadingButton() { - Container content; - - Child = content = CreateContent(); - - content.AddRange(new[] + AddRange(new[] { - text = CreateText(), + CreateContent(), loading = new LoadingAnimation { Anchor = Anchor.Centre, @@ -82,16 +72,14 @@ namespace osu.Game.Graphics.UserInterface } } - protected virtual void OnLoadingStart() + protected virtual void OnLoadStarted() { } - protected virtual void OnLoadingFinished() + protected virtual void OnLoadFinished() { } - protected abstract Container CreateContent(); - - protected abstract Drawable CreateText(); + protected abstract Drawable CreateContent(); } } diff --git a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs index 407e102ca5..4931a6aed6 100644 --- a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs +++ b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs @@ -14,6 +14,8 @@ namespace osu.Game.Graphics.UserInterface { public class ShowMoreButton : LoadingButton { + private const int duration = 200; + private Color4 chevronIconColour; protected Color4 ChevronIconColour @@ -34,43 +36,50 @@ namespace osu.Game.Graphics.UserInterface private ChevronIcon rightChevron; private SpriteText text; private Box background; + private FillFlowContainer textContainer; public ShowMoreButton() { AutoSizeAxes = Axes.Both; } - protected override Container CreateContent() => new CircularContainer + protected override Drawable CreateContent() => new CircularContainer { Masking = true, Size = new Vector2(140, 30), - Child = background = new Box - { - RelativeSizeAxes = Axes.Both, - } - }; - - protected override Drawable CreateText() => new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7), Children = new Drawable[] { - leftChevron = new ChevronIcon(), - text = new OsuSpriteText + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + textContainer = new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), - Text = "show more".ToUpper(), - }, - rightChevron = new ChevronIcon(), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7), + Children = new Drawable[] + { + leftChevron = new ChevronIcon(), + text = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Text = "show more".ToUpper(), + }, + rightChevron = new ChevronIcon(), + } + } } }; + protected override void OnLoadStarted() => textContainer.FadeOut(duration, Easing.OutQuint); + + protected override void OnLoadFinished() => textContainer.FadeIn(duration, Easing.OutQuint); + private class ChevronIcon : SpriteIcon { private const int icon_size = 8; diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 532fd8d905..e8d9013fd9 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -24,6 +24,8 @@ namespace osu.Game.Overlays.Comments { public class VotePill : LoadingButton, IHasAccentColour { + private const int duration = 200; + public Color4 AccentColour { get; set; } protected override IEnumerable<Drawable> EffectTargets => null; @@ -84,7 +86,7 @@ namespace osu.Game.Overlays.Comments IsLoading = false; } - protected override Container CreateContent() => new Container + protected override Drawable CreateContent() => new Container { RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, @@ -116,22 +118,27 @@ namespace osu.Game.Overlays.Comments Margin = new MarginPadding { Right = 3 }, Alpha = 0, }, + votesCounter = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Horizontal = 10 }, + Font = OsuFont.GetFont(size: 14), + AlwaysPresent = true, + } }, }; - protected override Drawable CreateText() => votesCounter = new OsuSpriteText + protected override void OnLoadStarted() { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Margin = new MarginPadding { Horizontal = 10 }, - Font = OsuFont.GetFont(size: 14), - AlwaysPresent = true, - }; + votesCounter.FadeOut(duration, Easing.OutQuint); + updateDisplay(); + } - protected override void OnLoadingStart() => updateDisplay(); - - protected override void OnLoadingFinished() + protected override void OnLoadFinished() { + votesCounter.FadeIn(duration, Easing.OutQuint); + if (IsHovered) onHoverAction(); } From 661dfbefaf55e0c9b238d86274e792ed06b3df61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= <dach.bartlomiej@gmail.com> Date: Fri, 25 Oct 2019 00:20:44 +0200 Subject: [PATCH 3609/5608] Change containment check to overlap Due to scenarios wherein a formatted link ended up as part of a larger raw link after parsing, change the containment check to an overlap check and add appropriate tests for these edge cases. --- osu.Game.Tests/Chat/MessageFormatterTests.cs | 30 ++++++++++++++++++++ osu.Game/Online/Chat/MessageFormatter.cs | 4 +-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs index 7988c6b96d..fbb0416c45 100644 --- a/osu.Game.Tests/Chat/MessageFormatterTests.cs +++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs @@ -333,6 +333,36 @@ namespace osu.Game.Tests.Chat Assert.AreEqual(18, result.Links[0].Length); } + [Test] + public void TestMarkdownFormatLinkThatContractsIntoLargerLink() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "super broken https://[osu.ppy](https://reddit.com).sh/" }); + + Assert.AreEqual("super broken https://osu.ppy.sh/", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://reddit.com", result.Links[0].Url); + Assert.AreEqual(21, result.Links[0].Index); + Assert.AreEqual(7, result.Links[0].Length); + } + + [Test] + public void TestMarkdownFormatLinkDirectlyNextToRawLink() + { + // the raw link has a port at the end of it, so that the raw link regex terminates at the port and doesn't consume display text from the formatted one + Message result = MessageFormatter.FormatMessage(new Message { Content = "https://localhost:8080[https://osu.ppy.sh](https://osu.ppy.sh) should be two links" }); + + Assert.AreEqual("https://localhost:8080https://osu.ppy.sh should be two links", result.DisplayContent); + Assert.AreEqual(2, result.Links.Count); + + Assert.AreEqual("https://localhost:8080", result.Links[0].Url); + Assert.AreEqual(0, result.Links[0].Index); + Assert.AreEqual(22, result.Links[0].Length); + + Assert.AreEqual("https://osu.ppy.sh", result.Links[1].Url); + Assert.AreEqual(22, result.Links[1].Index); + Assert.AreEqual(18, result.Links[1].Length); + } + [Test] public void TestChannelLink() { diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index d77920c97d..3ffff281f8 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -104,7 +104,7 @@ namespace osu.Game.Online.Chat // sometimes an already-processed formatted link can reduce to a simple URL, too // (example: [mean example - https://osu.ppy.sh](https://osu.ppy.sh)) // therefore we need to check if any of the pre-existing links contains the raw one we found - if (result.Links.All(existingLink => !existingLink.Contains(link))) + if (result.Links.All(existingLink => !existingLink.Overlaps(link))) result.Links.Add(link); } } @@ -298,7 +298,7 @@ namespace osu.Game.Online.Chat Argument = argument; } - public bool Contains(Link otherLink) => otherLink.Index >= Index && otherLink.Index + otherLink.Length <= Index + Length; + public bool Overlaps(Link otherLink) => Index < otherLink.Index + otherLink.Length && otherLink.Index < Index + Length; public int CompareTo(Link otherLink) => Index > otherLink.Index ? 1 : -1; } From 07f7944fc61f2fb907385cf4e9de4b2b7e575482 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Fri, 25 Oct 2019 12:22:19 +0900 Subject: [PATCH 3610/5608] Fix DateTime display sizing on results screen --- .../Screens/Ranking/Pages/ScoreResultsPage.cs | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs index 7c35742ff6..af47003682 100644 --- a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs +++ b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs @@ -253,9 +253,7 @@ namespace osu.Game.Screens.Ranking.Pages { this.date = date; - AutoSizeAxes = Axes.Y; - - Width = 140; + AutoSizeAxes = Axes.Both; Masking = true; CornerRadius = 5; @@ -271,22 +269,26 @@ namespace osu.Game.Screens.Ranking.Pages RelativeSizeAxes = Axes.Both, Colour = colours.Gray6, }, - new OsuSpriteText + new FillFlowContainer { - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - Text = date.ToShortDateString(), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, Padding = new MarginPadding { Horizontal = 10, Vertical = 5 }, - Colour = Color4.White, + Spacing = new Vector2(5), + Children = new[] + { + new OsuSpriteText + { + Text = date.ToShortDateString(), + Colour = Color4.White, + }, + new OsuSpriteText + { + Text = date.ToShortTimeString(), + Colour = Color4.White, + } + } }, - new OsuSpriteText - { - Origin = Anchor.CentreRight, - Anchor = Anchor.CentreRight, - Text = date.ToShortTimeString(), - Padding = new MarginPadding { Horizontal = 10, Vertical = 5 }, - Colour = Color4.White, - } }; } } From e5b5d286fd4aa21cc077bbc99a9892fe0d2deec1 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Fri, 25 Oct 2019 12:48:34 +0900 Subject: [PATCH 3611/5608] Increase spacing to closer match the design --- osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs index af47003682..56ae069a26 100644 --- a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs +++ b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs @@ -274,7 +274,7 @@ namespace osu.Game.Screens.Ranking.Pages AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Padding = new MarginPadding { Horizontal = 10, Vertical = 5 }, - Spacing = new Vector2(5), + Spacing = new Vector2(10), Children = new[] { new OsuSpriteText From 607b4d874a262185d105b6fcb0588498e121de46 Mon Sep 17 00:00:00 2001 From: smoogipoo <smoogipoo@smgi.me> Date: Fri, 25 Oct 2019 12:34:49 +0900 Subject: [PATCH 3612/5608] Refactor flow of snapping through HitObjectComposer --- .../TestSceneOsuDistanceSnapGrid.cs | 7 +- .../Sliders/SliderPlacementBlueprint.cs | 2 +- .../Sliders/SliderSelectionBlueprint.cs | 2 +- .../Edit/OsuDistanceSnapGrid.cs | 12 --- .../Editor/TestSceneDistanceSnapGrid.cs | 34 ++++---- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 87 +++++++++++++++++-- .../Compose/Components/BlueprintContainer.cs | 8 +- .../Components/CircularDistanceSnapGrid.cs | 11 ++- .../Compose/Components/DistanceSnapGrid.cs | 54 +++--------- 9 files changed, 128 insertions(+), 89 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index fddbcea374..7b28cc9c50 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -142,10 +142,9 @@ namespace osu.Game.Rulesets.Osu.Tests private void assertSnappedDistance(float expectedDistance) => AddAssert($"snap distance = {expectedDistance}", () => { - Vector2 snappedPosition = grid.GetSnappedPosition(grid.ToLocalSpace(InputManager.CurrentState.Mouse.Position)); - float distance = Vector2.Distance(snappedPosition, grid_position); + Vector2 snappedPosition = grid.GetSnappedPosition(grid.ToLocalSpace(InputManager.CurrentState.Mouse.Position)).position; - return Precision.AlmostEquals(expectedDistance, distance); + return Precision.AlmostEquals(expectedDistance, Vector2.Distance(snappedPosition, grid_position)); }); private void createGrid() @@ -160,7 +159,7 @@ namespace osu.Game.Rulesets.Osu.Tests Colour = Color4.SlateGray }, grid = new TestOsuDistanceSnapGrid(new HitCircle { Position = grid_position }), - new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)) } + new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position } }; }); } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 02923203b1..6f5309c2c2 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -137,7 +137,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders Vector2[] newControlPoints = segments.SelectMany(s => s.ControlPoints).Concat(cursor.Yield()).ToArray(); var unsnappedPath = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints); - var snappedDistance = composer?.GetSnappedDistance((float)unsnappedPath.Distance) ?? (float)unsnappedPath.Distance; + var snappedDistance = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)unsnappedPath.Distance) ?? (float)unsnappedPath.Distance; HitObject.Path = new SliderPath(unsnappedPath.Type, newControlPoints, snappedDistance); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index a90ed677ff..9ee456e791 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private void onNewControlPoints(Vector2[] controlPoints) { var unsnappedPath = new SliderPath(controlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, controlPoints); - var snappedDistance = composer?.GetSnappedDistance((float)unsnappedPath.Distance) ?? (float)unsnappedPath.Distance; + var snappedDistance = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)unsnappedPath.Distance) ?? (float)unsnappedPath.Distance; HitObject.Path = new SliderPath(unsnappedPath.Type, controlPoints, snappedDistance); } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs index bc0f76f000..79cd51a7f4 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose.Components; @@ -15,15 +13,5 @@ namespace osu.Game.Rulesets.Osu.Edit { Masking = true; } - - protected override float GetVelocity(double time, ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) - { - TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(time); - DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(time); - - double scoringDistance = OsuHitObject.BASE_SCORING_DISTANCE * difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier; - - return (float)(scoringDistance / timingPoint.BeatLength); - } } } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index 54d910fdcf..a67ba4d9e4 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -7,7 +7,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Beatmaps; @@ -93,23 +92,27 @@ namespace osu.Game.Tests.Visual.Editor [TestCase(2)] public void TestGridVelocity(float velocity) { - createGrid(g => g.Velocity = velocity); + // Todo: - float expectedDistance = (float)beat_length * velocity; - AddAssert($"spacing is {expectedDistance}", () => Precision.AlmostEquals(grid.DistanceSpacing, expectedDistance)); + // createGrid(g => g.Velocity = velocity); + // + // float expectedDistance = (float)beat_length * velocity; + // AddAssert($"spacing is {expectedDistance}", () => Precision.AlmostEquals(grid.DistanceSpacing, expectedDistance)); } [Test] public void TestGetSnappedTime() { - createGrid(); + //Todo: - Vector2 snapPosition = Vector2.Zero; - AddStep("get first tick position", () => snapPosition = grid_position + new Vector2((float)beat_length, 0)); - AddAssert("snap time is 1 beat away", () => Precision.AlmostEquals(beat_length, grid.GetSnappedTime(snapPosition), 0.01)); - - createGrid(g => g.Velocity = 2, "with velocity = 2"); - AddAssert("snap time is now 0.5 beats away", () => Precision.AlmostEquals(beat_length / 2, grid.GetSnappedTime(snapPosition), 0.01)); + // createGrid(); + // + // Vector2 snapPosition = Vector2.Zero; + // AddStep("get first tick position", () => snapPosition = grid_position + new Vector2((float)beat_length, 0)); + // AddAssert("snap time is 1 beat away", () => Precision.AlmostEquals(beat_length, grid.GetSnappedPosition(snapPosition).time, 0.01)); + // + // createGrid(g => g.Velocity = 2, "with velocity = 2"); + // AddAssert("snap time is now 0.5 beats away", () => Precision.AlmostEquals(beat_length / 2, grid.GetSnappedPosition(snapPosition).time, 0.01)); } private void createGrid(Action<TestDistanceSnapGrid> func = null, string description = null) @@ -132,8 +135,6 @@ namespace osu.Game.Tests.Visual.Editor private class TestDistanceSnapGrid : DistanceSnapGrid { - public new float Velocity = 1; - public new float DistanceSpacing => base.DistanceSpacing; public TestDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) @@ -203,11 +204,8 @@ namespace osu.Game.Tests.Visual.Editor } } - protected override float GetVelocity(double time, ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) - => Velocity; - - public override Vector2 GetSnappedPosition(Vector2 screenSpacePosition) - => Vector2.Zero; + public override (Vector2 position, double time) GetSnappedPosition(Vector2 screenSpacePosition) + => (Vector2.Zero, 0); } } } diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 3c24c3dd1f..beb0d38216 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -14,6 +14,7 @@ using osu.Framework.Logging; using osu.Framework.Threading; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Mods; @@ -39,6 +40,9 @@ namespace osu.Game.Rulesets.Edit [Resolved] protected IFrameBasedClock EditorClock { get; private set; } + [Resolved] + private BindableBeatDivisor beatDivisor { get; set; } + private IWorkingBeatmap workingBeatmap; private Beatmap<TObject> playableBeatmap; private IBeatmapProcessor beatmapProcessor; @@ -246,7 +250,7 @@ namespace osu.Game.Rulesets.Edit public void BeginPlacement(HitObject hitObject) { if (distanceSnapGrid != null) - hitObject.StartTime = GetSnappedTime(hitObject.StartTime, distanceSnapGrid.ToLocalSpace(inputManager.CurrentState.Mouse.Position)); + hitObject.StartTime = GetSnappedPosition(distanceSnapGrid.ToLocalSpace(inputManager.CurrentState.Mouse.Position), hitObject.StartTime).time; } public void EndPlacement(HitObject hitObject) @@ -257,11 +261,45 @@ namespace osu.Game.Rulesets.Edit public void Delete(HitObject hitObject) => EditorBeatmap.Remove(hitObject); - public override Vector2 GetSnappedPosition(Vector2 position) => distanceSnapGrid?.GetSnappedPosition(position) ?? position; + public override (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time) => distanceSnapGrid?.GetSnappedPosition(position) ?? (position, time); - public override double GetSnappedTime(double startTime, Vector2 position) => distanceSnapGrid?.GetSnappedTime(position) ?? startTime; + public override float GetBeatSnapDistanceAt(double referenceTime) + { + DifficultyControlPoint difficultyPoint = EditorBeatmap.ControlPointInfo.DifficultyPointAt(referenceTime); + return (float)(100 * EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier / beatDivisor.Value); + } - public override float GetSnappedDistance(float distance) => distanceSnapGrid?.GetSnappedDistance(distance) ?? distance; + public override float DurationToDistance(double referenceTime, double duration) + { + double beatLength = EditorBeatmap.ControlPointInfo.TimingPointAt(referenceTime).BeatLength / beatDivisor.Value; + return (float)(duration / beatLength * GetBeatSnapDistanceAt(referenceTime)); + } + + public override double DistanceToDuration(double referenceTime, float distance) + { + double beatLength = EditorBeatmap.ControlPointInfo.TimingPointAt(referenceTime).BeatLength / beatDivisor.Value; + return distance / GetBeatSnapDistanceAt(referenceTime) * beatLength; + } + + public override double GetSnappedDurationFromDistance(double referenceTime, float distance) + => beatSnap(referenceTime, DistanceToDuration(referenceTime, distance)); + + public override float GetSnappedDistanceFromDistance(double referenceTime, float distance) + => DurationToDistance(referenceTime, beatSnap(referenceTime, DistanceToDuration(referenceTime, distance))); + + /// <summary> + /// Snaps a duration to the closest beat of a timing point applicable at the reference time. + /// </summary> + /// <param name="referenceTime">The time of the timing point which <paramref name="duration"/> resides in.</param> + /// <param name="duration">The duration to snap.</param> + /// <returns>A value that represents <paramref name="duration"/> snapped to the closest beat of the timing point.</returns> + private double beatSnap(double referenceTime, double duration) + { + double beatLength = EditorBeatmap.ControlPointInfo.TimingPointAt(referenceTime).BeatLength / beatDivisor.Value; + + // A 1ms offset prevents rounding errors due to minute variations in duration + return (int)((duration + 1) / beatLength) * beatLength; + } protected override void Dispose(bool isDisposing) { @@ -312,10 +350,45 @@ namespace osu.Game.Rulesets.Edit [CanBeNull] protected virtual DistanceSnapGrid CreateDistanceSnapGrid([NotNull] IEnumerable<HitObject> selectedHitObjects) => null; - public abstract Vector2 GetSnappedPosition(Vector2 position); + public abstract (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time); - public abstract double GetSnappedTime(double startTime, Vector2 screenSpacePosition); + /// <summary> + /// Retrieves the distance between two points within a timing point that are one beat length apart. + /// </summary> + /// <param name="referenceTime">The time of the timing point.</param> + /// <returns>The distance between two points residing in the timing point that are one beat length apart.</returns> + public abstract float GetBeatSnapDistanceAt(double referenceTime); - public abstract float GetSnappedDistance(float distance); + /// <summary> + /// Converts a duration to a distance. + /// </summary> + /// <param name="referenceTime">The time of the timing point which <paramref name="duration"/> resides in.</param> + /// <param name="duration">The duration to convert.</param> + /// <returns>A value that represents <paramref name="duration"/> as a distance in the timing point.</returns> + public abstract float DurationToDistance(double referenceTime, double duration); + + /// <summary> + /// Converts a distance to a duration. + /// </summary> + /// <param name="referenceTime">The time of the timing point which <paramref name="distance"/> resides in.</param> + /// <param name="distance">The distance to convert.</param> + /// <returns>A value that represents <paramref name="distance"/> as a duration in the timing point.</returns> + public abstract double DistanceToDuration(double referenceTime, float distance); + + /// <summary> + /// Converts a distance to a snapped duration. + /// </summary> + /// <param name="referenceTime">The time of the timing point which <paramref name="distance"/> resides in.</param> + /// <param name="distance">The distance to convert.</param> + /// <returns>A value that represents <paramref name="distance"/> as a duration snapped to the closest beat of the timing point.</returns> + public abstract double GetSnappedDurationFromDistance(double referenceTime, float distance); + + /// <summary> + /// Converts an unsnapped distance to a snapped distance. + /// </summary> + /// <param name="referenceTime">The time of the timing point which <paramref name="distance"/> resides in.</param> + /// <param name="distance">The distance to convert.</param> + /// <returns>A value that represents <paramref name="distance"/> snapped to the closest beat of the timing point.</returns> + public abstract float GetSnappedDistanceFromDistance(double referenceTime, float distance); } } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 4001a0f33a..1bfd4c454b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -185,7 +185,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private void updatePlacementPosition(Vector2 screenSpacePosition) { - Vector2 snappedGridPosition = composer.GetSnappedPosition(ToLocalSpace(screenSpacePosition)); + Vector2 snappedGridPosition = composer.GetSnappedPosition(ToLocalSpace(screenSpacePosition), 0).position; Vector2 snappedScreenSpacePosition = ToScreenSpace(snappedGridPosition); currentPlacement.UpdatePosition(snappedScreenSpacePosition); @@ -232,15 +232,15 @@ namespace osu.Game.Screens.Edit.Compose.Components private void onDragRequested(SelectionBlueprint blueprint, DragEvent dragEvent) { HitObject draggedObject = blueprint.DrawableObject.HitObject; - Vector2 movePosition = blueprint.ScreenSpaceMovementStartPosition + dragEvent.ScreenSpaceMousePosition - dragEvent.ScreenSpaceMouseDownPosition; - Vector2 snappedPosition = composer.GetSnappedPosition(ToLocalSpace(movePosition)); + + (Vector2 snappedPosition, double snappedTime) = composer.GetSnappedPosition(ToLocalSpace(movePosition), draggedObject.StartTime); // Move the hitobjects selectionHandler.HandleMovement(new MoveSelectionEvent(blueprint, blueprint.ScreenSpaceMovementStartPosition, ToScreenSpace(snappedPosition))); // Apply the start time at the newly snapped-to position - double offset = composer.GetSnappedTime(draggedObject.StartTime, snappedPosition) - draggedObject.StartTime; + double offset = snappedTime - draggedObject.StartTime; foreach (HitObject obj in selectionHandler.SelectedHitObjects) obj.StartTime += offset; } diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 381ae9f927..7e9e6e2290 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -2,9 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osuTK; @@ -12,6 +14,9 @@ namespace osu.Game.Screens.Edit.Compose.Components { public abstract class CircularDistanceSnapGrid : DistanceSnapGrid { + [Resolved] + private HitObjectComposer composer { get; set; } + protected CircularDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) : base(hitObject, centrePosition) { @@ -63,7 +68,7 @@ namespace osu.Game.Screens.Edit.Compose.Components } } - public override Vector2 GetSnappedPosition(Vector2 position) + public override (Vector2 position, double time) GetSnappedPosition(Vector2 position) { Vector2 direction = position - CentrePosition; @@ -76,7 +81,9 @@ namespace osu.Game.Screens.Edit.Compose.Components int radialCount = Math.Max(1, (int)Math.Round(distance / radius)); Vector2 normalisedDirection = direction * new Vector2(1f / distance); - return CentrePosition + normalisedDirection * radialCount * radius; + Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; + + return (snappedPosition, StartTime + composer.GetSnappedDurationFromDistance(StartTime, (snappedPosition - CentrePosition).Length)); } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 250a0abef5..9eaccc5ac3 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -6,9 +6,8 @@ using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osuTK; @@ -20,16 +19,16 @@ namespace osu.Game.Screens.Edit.Compose.Components /// </summary> public abstract class DistanceSnapGrid : CompositeDrawable { - /// <summary> - /// The velocity of the beatmap at the point of placement in pixels per millisecond. - /// </summary> - protected double Velocity { get; private set; } - /// <summary> /// The spacing between each tick of the beat snapping grid. /// </summary> protected float DistanceSpacing { get; private set; } + /// <summary> + /// The snapping time at <see cref="CentrePosition"/>. + /// </summary> + protected double StartTime { get; private set; } + /// <summary> /// The position which the grid is centred on. /// The first beat snapping tick is located at <see cref="CentrePosition"/> + <see cref="DistanceSpacing"/> in the desired direction. @@ -45,25 +44,24 @@ namespace osu.Game.Screens.Edit.Compose.Components [Resolved] private BindableBeatDivisor beatDivisor { get; set; } + [Resolved] + private HitObjectComposer composer { get; set; } + private readonly Cached gridCache = new Cached(); private readonly HitObject hitObject; - private double startTime; - private double beatLength; - protected DistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) { this.hitObject = hitObject; - this.CentrePosition = centrePosition; + CentrePosition = centrePosition; RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] private void load() { - startTime = (hitObject as IHasEndTime)?.EndTime ?? hitObject.StartTime; - beatLength = beatmap.ControlPointInfo.TimingPointAt(startTime).BeatLength; + StartTime = (hitObject as IHasEndTime)?.EndTime ?? hitObject.StartTime; } protected override void LoadComplete() @@ -75,8 +73,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private void updateSpacing() { - Velocity = GetVelocity(startTime, beatmap.ControlPointInfo, beatmap.BeatmapInfo.BaseDifficulty); - DistanceSpacing = (float)(beatLength / beatDivisor.Value * Velocity); + DistanceSpacing = composer.GetBeatSnapDistanceAt(StartTime); gridCache.Invalidate(); } @@ -105,35 +102,12 @@ namespace osu.Game.Screens.Edit.Compose.Components /// </summary> protected abstract void CreateContent(Vector2 centrePosition); - /// <summary> - /// Retrieves the velocity of gameplay at a point in time in pixels per millisecond. - /// </summary> - /// <param name="time">The time to retrieve the velocity at.</param> - /// <param name="controlPointInfo">The beatmap's <see cref="ControlPointInfo"/> at the point in time.</param> - /// <param name="difficulty">The beatmap's <see cref="BeatmapDifficulty"/> at the point in time.</param> - /// <returns>The velocity.</returns> - protected abstract float GetVelocity(double time, ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty); - /// <summary> /// Snaps a position to this grid. /// </summary> /// <param name="position">The original position in coordinate space local to this <see cref="DistanceSnapGrid"/>.</param> - /// <returns>The snapped position in coordinate space local to this <see cref="DistanceSnapGrid"/>.</returns> - public abstract Vector2 GetSnappedPosition(Vector2 position); - - /// <summary> - /// Retrieves the time at a snapped position. - /// </summary> - /// <param name="position">The snapped position in coordinate space local to this <see cref="DistanceSnapGrid"/>.</param> - /// <returns>The time at the snapped position.</returns> - public double GetSnappedTime(Vector2 position) => startTime + (position - CentrePosition).Length / Velocity; - - /// <summary> - /// Snaps a distance by the snap distance of this grid. - /// </summary> - /// <param name="distance">The distance to snap in coordinate space local to this <see cref="DistanceSnapGrid"/>.</param> - /// <returns>The snapped distance.</returns> - public float GetSnappedDistance(float distance) => (int)(distance / DistanceSpacing) * DistanceSpacing; + /// <returns>A tuple containing the snapped position in coordinate space local to this <see cref="DistanceSnapGrid"/> and the respective time value.</returns> + public abstract (Vector2 position, double time) GetSnappedPosition(Vector2 position); /// <summary> /// Retrieves the applicable colour for a beat index. From 4ca6a5a0cc4fb841c35171dde5affcef9c0786fa Mon Sep 17 00:00:00 2001 From: smoogipoo <smoogipoo@smgi.me> Date: Fri, 25 Oct 2019 16:50:21 +0900 Subject: [PATCH 3613/5608] Interface the distance snap provider --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 37 +------------- .../Rulesets/Edit/IDistanceSnapProvider.cs | 51 +++++++++++++++++++ .../Compose/Components/DistanceSnapGrid.cs | 4 +- 3 files changed, 55 insertions(+), 37 deletions(-) create mode 100644 osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index beb0d38216..5922bfba78 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -314,7 +314,8 @@ namespace osu.Game.Rulesets.Edit } [Cached(typeof(HitObjectComposer))] - public abstract class HitObjectComposer : CompositeDrawable + [Cached(typeof(IDistanceSnapProvider))] + public abstract class HitObjectComposer : CompositeDrawable, IDistanceSnapProvider { internal HitObjectComposer() { @@ -351,44 +352,10 @@ namespace osu.Game.Rulesets.Edit protected virtual DistanceSnapGrid CreateDistanceSnapGrid([NotNull] IEnumerable<HitObject> selectedHitObjects) => null; public abstract (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time); - - /// <summary> - /// Retrieves the distance between two points within a timing point that are one beat length apart. - /// </summary> - /// <param name="referenceTime">The time of the timing point.</param> - /// <returns>The distance between two points residing in the timing point that are one beat length apart.</returns> public abstract float GetBeatSnapDistanceAt(double referenceTime); - - /// <summary> - /// Converts a duration to a distance. - /// </summary> - /// <param name="referenceTime">The time of the timing point which <paramref name="duration"/> resides in.</param> - /// <param name="duration">The duration to convert.</param> - /// <returns>A value that represents <paramref name="duration"/> as a distance in the timing point.</returns> public abstract float DurationToDistance(double referenceTime, double duration); - - /// <summary> - /// Converts a distance to a duration. - /// </summary> - /// <param name="referenceTime">The time of the timing point which <paramref name="distance"/> resides in.</param> - /// <param name="distance">The distance to convert.</param> - /// <returns>A value that represents <paramref name="distance"/> as a duration in the timing point.</returns> public abstract double DistanceToDuration(double referenceTime, float distance); - - /// <summary> - /// Converts a distance to a snapped duration. - /// </summary> - /// <param name="referenceTime">The time of the timing point which <paramref name="distance"/> resides in.</param> - /// <param name="distance">The distance to convert.</param> - /// <returns>A value that represents <paramref name="distance"/> as a duration snapped to the closest beat of the timing point.</returns> public abstract double GetSnappedDurationFromDistance(double referenceTime, float distance); - - /// <summary> - /// Converts an unsnapped distance to a snapped distance. - /// </summary> - /// <param name="referenceTime">The time of the timing point which <paramref name="distance"/> resides in.</param> - /// <param name="distance">The distance to convert.</param> - /// <returns>A value that represents <paramref name="distance"/> snapped to the closest beat of the timing point.</returns> public abstract float GetSnappedDistanceFromDistance(double referenceTime, float distance); } } diff --git a/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs b/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs new file mode 100644 index 0000000000..c6e61f68da --- /dev/null +++ b/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs @@ -0,0 +1,51 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osuTK; + +namespace osu.Game.Rulesets.Edit +{ + public interface IDistanceSnapProvider + { + (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time); + + /// <summary> + /// Retrieves the distance between two points within a timing point that are one beat length apart. + /// </summary> + /// <param name="referenceTime">The time of the timing point.</param> + /// <returns>The distance between two points residing in the timing point that are one beat length apart.</returns> + float GetBeatSnapDistanceAt(double referenceTime); + + /// <summary> + /// Converts a duration to a distance. + /// </summary> + /// <param name="referenceTime">The time of the timing point which <paramref name="duration"/> resides in.</param> + /// <param name="duration">The duration to convert.</param> + /// <returns>A value that represents <paramref name="duration"/> as a distance in the timing point.</returns> + float DurationToDistance(double referenceTime, double duration); + + /// <summary> + /// Converts a distance to a duration. + /// </summary> + /// <param name="referenceTime">The time of the timing point which <paramref name="distance"/> resides in.</param> + /// <param name="distance">The distance to convert.</param> + /// <returns>A value that represents <paramref name="distance"/> as a duration in the timing point.</returns> + double DistanceToDuration(double referenceTime, float distance); + + /// <summary> + /// Converts a distance to a snapped duration. + /// </summary> + /// <param name="referenceTime">The time of the timing point which <paramref name="distance"/> resides in.</param> + /// <param name="distance">The distance to convert.</param> + /// <returns>A value that represents <paramref name="distance"/> as a duration snapped to the closest beat of the timing point.</returns> + double GetSnappedDurationFromDistance(double referenceTime, float distance); + + /// <summary> + /// Converts an unsnapped distance to a snapped distance. + /// </summary> + /// <param name="referenceTime">The time of the timing point which <paramref name="distance"/> resides in.</param> + /// <param name="distance">The distance to convert.</param> + /// <returns>A value that represents <paramref name="distance"/> snapped to the closest beat of the timing point.</returns> + float GetSnappedDistanceFromDistance(double referenceTime, float distance); + } +} diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 9eaccc5ac3..d6ee6063ef 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -45,7 +45,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private BindableBeatDivisor beatDivisor { get; set; } [Resolved] - private HitObjectComposer composer { get; set; } + private IDistanceSnapProvider snapProvider { get; set; } private readonly Cached gridCache = new Cached(); private readonly HitObject hitObject; @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private void updateSpacing() { - DistanceSpacing = composer.GetBeatSnapDistanceAt(StartTime); + DistanceSpacing = snapProvider.GetBeatSnapDistanceAt(StartTime); gridCache.Invalidate(); } From ae011e8ee82db586ae808a0b8c10d6d44242f77e Mon Sep 17 00:00:00 2001 From: smoogipoo <smoogipoo@smgi.me> Date: Fri, 25 Oct 2019 17:25:46 +0900 Subject: [PATCH 3614/5608] Fix distance snap grid test scenes --- .../TestSceneOsuDistanceSnapGrid.cs | 99 +++++---------- .../Editor/TestSceneDistanceSnapGrid.cs | 117 +++++------------- .../Components/CircularDistanceSnapGrid.cs | 7 +- .../Compose/Components/DistanceSnapGrid.cs | 8 +- 4 files changed, 63 insertions(+), 168 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index 7b28cc9c50..b6907cf7c0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.MathUtils; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Objects; @@ -38,26 +39,34 @@ namespace osu.Game.Rulesets.Osu.Tests [Cached] private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); - private TestOsuDistanceSnapGrid grid; + [Cached(typeof(IDistanceSnapProvider))] + private readonly SnapProvider snapProvider = new SnapProvider(); + + private readonly TestOsuDistanceSnapGrid grid; public TestSceneOsuDistanceSnapGrid() { editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap()); - createGrid(); + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.SlateGray + }, + grid = new TestOsuDistanceSnapGrid(new HitCircle { Position = grid_position }), + new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position } + }; } [SetUp] public void Setup() => Schedule(() => { - Clear(); - editorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 1; editorBeatmap.ControlPointInfo.DifficultyPoints.Clear(); editorBeatmap.ControlPointInfo.TimingPoints.Clear(); editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); - - beatDivisor.Value = 1; }); [TestCase(1)] @@ -71,53 +80,11 @@ namespace osu.Game.Rulesets.Osu.Tests public void TestBeatDivisor(int divisor) { AddStep($"set beat divisor = {divisor}", () => beatDivisor.Value = divisor); - createGrid(); - } - - [TestCase(100, 100)] - [TestCase(200, 100)] - public void TestBeatLength(float beatLength, float expectedSpacing) - { - AddStep($"set beat length = {beatLength}", () => - { - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beatLength }); - }); - - createGrid(); - AddAssert($"spacing = {expectedSpacing}", () => Precision.AlmostEquals(expectedSpacing, grid.DistanceSpacing)); - } - - [TestCase(0.5f, 50)] - [TestCase(1, 100)] - [TestCase(1.5f, 150)] - public void TestSpeedMultiplier(float multiplier, float expectedSpacing) - { - AddStep($"set speed multiplier = {multiplier}", () => - { - editorBeatmap.ControlPointInfo.DifficultyPoints.Clear(); - editorBeatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = multiplier }); - }); - - createGrid(); - AddAssert($"spacing = {expectedSpacing}", () => Precision.AlmostEquals(expectedSpacing, grid.DistanceSpacing)); - } - - [TestCase(0.5f, 50)] - [TestCase(1, 100)] - [TestCase(1.5f, 150)] - public void TestSliderMultiplier(float multiplier, float expectedSpacing) - { - AddStep($"set speed multiplier = {multiplier}", () => editorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = multiplier); - createGrid(); - AddAssert($"spacing = {expectedSpacing}", () => Precision.AlmostEquals(expectedSpacing, grid.DistanceSpacing)); } [Test] public void TestCursorInCentre() { - createGrid(); - AddStep("move mouse to centre", () => InputManager.MoveMouseTo(grid.ToScreenSpace(grid_position))); assertSnappedDistance((float)beat_length); } @@ -125,8 +92,6 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestCursorBeforeMovementPoint() { - createGrid(); - AddStep("move mouse to just before movement point", () => InputManager.MoveMouseTo(grid.ToScreenSpace(grid_position + new Vector2((float)beat_length, 0) * 1.49f))); assertSnappedDistance((float)beat_length); } @@ -134,8 +99,6 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestCursorAfterMovementPoint() { - createGrid(); - AddStep("move mouse to just after movement point", () => InputManager.MoveMouseTo(grid.ToScreenSpace(grid_position + new Vector2((float)beat_length, 0) * 1.51f))); assertSnappedDistance((float)beat_length * 2); } @@ -147,23 +110,6 @@ namespace osu.Game.Rulesets.Osu.Tests return Precision.AlmostEquals(expectedDistance, Vector2.Distance(snappedPosition, grid_position)); }); - private void createGrid() - { - AddStep("create grid", () => - { - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.SlateGray - }, - grid = new TestOsuDistanceSnapGrid(new HitCircle { Position = grid_position }), - new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position } - }; - }); - } - private class SnappingCursorContainer : CompositeDrawable { public Func<Vector2, Vector2> GetSnapPosition; @@ -212,5 +158,20 @@ namespace osu.Game.Rulesets.Osu.Tests { } } + + private class SnapProvider : IDistanceSnapProvider + { + public (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time) => (position, time); + + public float GetBeatSnapDistanceAt(double referenceTime) => (float)beat_length; + + public float DurationToDistance(double referenceTime, double duration) => 0; + + public double DistanceToDuration(double referenceTime, float distance) => 0; + + public double GetSnappedDurationFromDistance(double referenceTime, float distance) => 0; + + public float GetSnappedDistanceFromDistance(double referenceTime, float distance) => 0; + } } } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index a67ba4d9e4..558e1106a7 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -1,13 +1,12 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Framework.MathUtils; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Objects; @@ -26,27 +25,25 @@ namespace osu.Game.Tests.Visual.Editor [Cached(typeof(IEditorBeatmap))] private readonly EditorBeatmap<OsuHitObject> editorBeatmap; - private TestDistanceSnapGrid grid; + [Cached(typeof(IDistanceSnapProvider))] + private readonly SnapProvider snapProvider = new SnapProvider(); public TestSceneDistanceSnapGrid() { editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap()); editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); - createGrid(); + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.SlateGray + }, + new TestDistanceSnapGrid(new HitObject(), grid_position) + }; } - [SetUp] - public void Setup() => Schedule(() => - { - Clear(); - - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); - - BeatDivisor.Value = 1; - }); - [TestCase(1)] [TestCase(2)] [TestCase(3)] @@ -55,82 +52,9 @@ namespace osu.Game.Tests.Visual.Editor [TestCase(8)] [TestCase(12)] [TestCase(16)] - public void TestInitialBeatDivisor(int divisor) + public void TestBeatDivisor(int divisor) { AddStep($"set beat divisor = {divisor}", () => BeatDivisor.Value = divisor); - createGrid(); - - float expectedDistance = (float)beat_length / divisor; - AddAssert($"spacing is {expectedDistance}", () => Precision.AlmostEquals(grid.DistanceSpacing, expectedDistance)); - } - - [Test] - public void TestChangeBeatDivisor() - { - createGrid(); - AddStep("set beat divisor = 2", () => BeatDivisor.Value = 2); - - const float expected_distance = (float)beat_length / 2; - AddAssert($"spacing is {expected_distance}", () => Precision.AlmostEquals(grid.DistanceSpacing, expected_distance)); - } - - [TestCase(100)] - [TestCase(200)] - public void TestBeatLength(double beatLength) - { - AddStep($"set beat length = {beatLength}", () => - { - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beatLength }); - }); - - createGrid(); - AddAssert($"spacing is {beatLength}", () => Precision.AlmostEquals(grid.DistanceSpacing, beatLength)); - } - - [TestCase(1)] - [TestCase(2)] - public void TestGridVelocity(float velocity) - { - // Todo: - - // createGrid(g => g.Velocity = velocity); - // - // float expectedDistance = (float)beat_length * velocity; - // AddAssert($"spacing is {expectedDistance}", () => Precision.AlmostEquals(grid.DistanceSpacing, expectedDistance)); - } - - [Test] - public void TestGetSnappedTime() - { - //Todo: - - // createGrid(); - // - // Vector2 snapPosition = Vector2.Zero; - // AddStep("get first tick position", () => snapPosition = grid_position + new Vector2((float)beat_length, 0)); - // AddAssert("snap time is 1 beat away", () => Precision.AlmostEquals(beat_length, grid.GetSnappedPosition(snapPosition).time, 0.01)); - // - // createGrid(g => g.Velocity = 2, "with velocity = 2"); - // AddAssert("snap time is now 0.5 beats away", () => Precision.AlmostEquals(beat_length / 2, grid.GetSnappedPosition(snapPosition).time, 0.01)); - } - - private void createGrid(Action<TestDistanceSnapGrid> func = null, string description = null) - { - AddStep($"create grid {description ?? string.Empty}", () => - { - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.SlateGray - }, - grid = new TestDistanceSnapGrid(new HitObject(), grid_position) - }; - - func?.Invoke(grid); - }); } private class TestDistanceSnapGrid : DistanceSnapGrid @@ -207,5 +131,20 @@ namespace osu.Game.Tests.Visual.Editor public override (Vector2 position, double time) GetSnappedPosition(Vector2 screenSpacePosition) => (Vector2.Zero, 0); } + + private class SnapProvider : IDistanceSnapProvider + { + public (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time) => (position, time); + + public float GetBeatSnapDistanceAt(double referenceTime) => 10; + + public float DurationToDistance(double referenceTime, double duration) => 0; + + public double DistanceToDuration(double referenceTime, float distance) => 0; + + public double GetSnappedDurationFromDistance(double referenceTime, float distance) => 0; + + public float GetSnappedDistanceFromDistance(double referenceTime, float distance) => 0; + } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 7e9e6e2290..f45115e1e4 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -2,11 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osuTK; @@ -14,9 +12,6 @@ namespace osu.Game.Screens.Edit.Compose.Components { public abstract class CircularDistanceSnapGrid : DistanceSnapGrid { - [Resolved] - private HitObjectComposer composer { get; set; } - protected CircularDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) : base(hitObject, centrePosition) { @@ -83,7 +78,7 @@ namespace osu.Game.Screens.Edit.Compose.Components Vector2 normalisedDirection = direction * new Vector2(1f / distance); Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; - return (snappedPosition, StartTime + composer.GetSnappedDurationFromDistance(StartTime, (snappedPosition - CentrePosition).Length)); + return (snappedPosition, StartTime + SnapProvider.GetSnappedDurationFromDistance(StartTime, (snappedPosition - CentrePosition).Length)); } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index d6ee6063ef..193474093f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -38,15 +38,15 @@ namespace osu.Game.Screens.Edit.Compose.Components [Resolved] protected OsuColour Colours { get; private set; } + [Resolved] + protected IDistanceSnapProvider SnapProvider { get; private set; } + [Resolved] private IEditorBeatmap beatmap { get; set; } [Resolved] private BindableBeatDivisor beatDivisor { get; set; } - [Resolved] - private IDistanceSnapProvider snapProvider { get; set; } - private readonly Cached gridCache = new Cached(); private readonly HitObject hitObject; @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private void updateSpacing() { - DistanceSpacing = snapProvider.GetBeatSnapDistanceAt(StartTime); + DistanceSpacing = SnapProvider.GetBeatSnapDistanceAt(StartTime); gridCache.Invalidate(); } From ccc45dea206a183a127f9ad41116c27774183ff1 Mon Sep 17 00:00:00 2001 From: smoogipoo <smoogipoo@smgi.me> Date: Fri, 25 Oct 2019 18:19:26 +0900 Subject: [PATCH 3615/5608] Add hitobject composer snapping test --- ...tSceneHitObjectComposerDistanceSnapping.cs | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs diff --git a/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs b/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs new file mode 100644 index 0000000000..e6b0cf992a --- /dev/null +++ b/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs @@ -0,0 +1,195 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Testing; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Edit; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Edit; +using osu.Game.Tests.Visual; + +namespace osu.Game.Tests.Editor +{ + [HeadlessTest] + public class TestSceneHitObjectComposerDistanceSnapping : EditorClockTestScene + { + private TestHitObjectComposer composer; + + [SetUp] + public void Setup() => Schedule(() => + { + Child = composer = new TestHitObjectComposer(); + + BeatDivisor.Value = 1; + + composer.EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 1; + composer.EditorBeatmap.ControlPointInfo.DifficultyPoints.Clear(); + composer.EditorBeatmap.ControlPointInfo.TimingPoints.Clear(); + + composer.EditorBeatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = 1 }); + composer.EditorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = 1000 }); + }); + + [TestCase(1)] + [TestCase(2)] + public void TestSliderMultiplier(float multiplier) + { + AddStep($"set multiplier = {multiplier}", () => composer.EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = multiplier); + + assertSnapDistance(100 * multiplier); + } + + [TestCase(1)] + [TestCase(2)] + public void TestSpeedMultiplier(float multiplier) + { + AddStep($"set multiplier = {multiplier}", () => + { + composer.EditorBeatmap.ControlPointInfo.DifficultyPoints.Clear(); + composer.EditorBeatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = multiplier }); + }); + + assertSnapDistance(100 * multiplier); + } + + [TestCase(1)] + [TestCase(2)] + public void TestBeatDivisor(int divisor) + { + AddStep($"set divisor = {divisor}", () => BeatDivisor.Value = divisor); + + assertSnapDistance(100f / divisor); + } + + [Test] + public void TestConvertDurationToDistance() + { + assertDurationToDistance(500, 50); + assertDurationToDistance(1000, 100); + + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2); + + assertDurationToDistance(500, 100); + assertDurationToDistance(1000, 200); + + AddStep("set beat length = 500", () => + { + composer.EditorBeatmap.ControlPointInfo.TimingPoints.Clear(); + composer.EditorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = 500 }); + }); + + assertDurationToDistance(500, 200); + assertDurationToDistance(1000, 400); + } + + [Test] + public void TestConvertDistanceToDuration() + { + assertDistanceToDuration(50, 500); + assertDistanceToDuration(100, 1000); + + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2); + + assertDistanceToDuration(100, 500); + assertDistanceToDuration(200, 1000); + + AddStep("set beat length = 500", () => + { + composer.EditorBeatmap.ControlPointInfo.TimingPoints.Clear(); + composer.EditorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = 500 }); + }); + + assertDistanceToDuration(200, 500); + assertDistanceToDuration(400, 1000); + } + + [Test] + public void TestGetSnappedDurationFromDistance() + { + assertSnappedDuration(50, 0); + assertSnappedDuration(100, 1000); + assertSnappedDuration(150, 1000); + assertSnappedDuration(200, 2000); + assertSnappedDuration(250, 2000); + + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2); + + assertSnappedDuration(50, 0); + assertSnappedDuration(100, 0); + assertSnappedDuration(150, 0); + assertSnappedDuration(200, 1000); + assertSnappedDuration(250, 1000); + + AddStep("set beat length = 500", () => + { + composer.EditorBeatmap.ControlPointInfo.TimingPoints.Clear(); + composer.EditorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = 500 }); + }); + + assertSnappedDuration(50, 0); + assertSnappedDuration(100, 0); + assertSnappedDuration(150, 0); + assertSnappedDuration(200, 500); + assertSnappedDuration(250, 500); + assertSnappedDuration(400, 1000); + } + + [Test] + public void GetSnappedDistanceFromDistance() + { + assertSnappedDistance(50, 0); + assertSnappedDistance(100, 100); + assertSnappedDistance(150, 100); + assertSnappedDistance(200, 200); + assertSnappedDistance(250, 200); + + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2); + + assertSnappedDistance(50, 0); + assertSnappedDistance(100, 0); + assertSnappedDistance(150, 0); + assertSnappedDistance(200, 200); + assertSnappedDistance(250, 200); + + AddStep("set beat length = 500", () => + { + composer.EditorBeatmap.ControlPointInfo.TimingPoints.Clear(); + composer.EditorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = 500 }); + }); + + assertSnappedDistance(50, 0); + assertSnappedDistance(100, 0); + assertSnappedDistance(150, 0); + assertSnappedDistance(200, 200); + assertSnappedDistance(250, 200); + assertSnappedDistance(400, 400); + } + + private void assertSnapDistance(float expectedDistance) + => AddAssert($"distance is {expectedDistance}", () => composer.GetBeatSnapDistanceAt(0) == expectedDistance); + + private void assertDurationToDistance(double duration, float expectedDistance) + => AddAssert($"duration = {duration} -> distance = {expectedDistance}", () => composer.DurationToDistance(0, duration) == expectedDistance); + + private void assertDistanceToDuration(float distance, double expectedDuration) + => AddAssert($"distance = {distance} -> duration = {expectedDuration}", () => composer.DistanceToDuration(0, distance) == expectedDuration); + + private void assertSnappedDuration(float distance, double expectedDuration) + => AddAssert($"distance = {distance} -> duration = {expectedDuration} (snapped)", () => composer.GetSnappedDurationFromDistance(0, distance) == expectedDuration); + + private void assertSnappedDistance(float distance, float expectedDistance) + => AddAssert($"distance = {distance} -> distance = {expectedDistance} (snapped)", () => composer.GetSnappedDistanceFromDistance(0, distance) == expectedDistance); + + private class TestHitObjectComposer : OsuHitObjectComposer + { + public new EditorBeatmap<OsuHitObject> EditorBeatmap => base.EditorBeatmap; + + public TestHitObjectComposer() + : base(new OsuRuleset()) + { + } + } + } +} From da6ee05dd689646d5c4831d9c1d7cc149754d184 Mon Sep 17 00:00:00 2001 From: smoogipoo <smoogipoo@smgi.me> Date: Fri, 25 Oct 2019 18:37:44 +0900 Subject: [PATCH 3616/5608] Fix not being able to drag non-snaked sliders --- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index fdeffc6f8a..ae0492ac3e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -38,6 +38,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders public override Vector2 SelectionPoint => HeadBlueprint.SelectionPoint; + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => BodyPiece.ReceivePositionalInputAt(screenSpacePos); + protected virtual SliderCircleSelectionBlueprint CreateCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position) => new SliderCircleSelectionBlueprint(slider, position); } } From a9ec6b256266f6c2c1c579ac61bac1d72ada66ca Mon Sep 17 00:00:00 2001 From: smoogipoo <smoogipoo@smgi.me> Date: Fri, 25 Oct 2019 19:00:10 +0900 Subject: [PATCH 3617/5608] Fix testcase failure --- osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs b/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs index 0ea73fb3de..b7c7028b52 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Editor { [TestFixture] - public class TestSceneHitObjectComposer : OsuTestScene + public class TestSceneHitObjectComposer : EditorClockTestScene { public override IReadOnlyList<Type> RequiredTypes => new[] { From e38b7cb169767b0d637cfcb166ed919161aa3087 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Fri, 25 Oct 2019 17:00:56 +0900 Subject: [PATCH 3618/5608] Replace local Equatable implementations with abstract EquivalentTo --- osu.Game/Beatmaps/ControlPoints/ControlPoint.cs | 12 +++++++++--- .../Beatmaps/ControlPoints/DifficultyControlPoint.cs | 8 +++----- .../Beatmaps/ControlPoints/EffectControlPoint.cs | 10 ++++------ .../Beatmaps/ControlPoints/SampleControlPoint.cs | 9 ++++----- .../Beatmaps/ControlPoints/TimingControlPoint.cs | 9 ++++----- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 8 ++++---- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index abe7e5e803..0081fab46a 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -5,7 +5,7 @@ using System; namespace osu.Game.Beatmaps.ControlPoints { - public class ControlPoint : IComparable<ControlPoint>, IEquatable<ControlPoint> + public abstract class ControlPoint : IComparable<ControlPoint>, IEquatable<ControlPoint> { /// <summary> /// The time at which the control point takes effect. @@ -19,7 +19,13 @@ namespace osu.Game.Beatmaps.ControlPoints public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); - public bool Equals(ControlPoint other) - => Time.Equals(other?.Time); + /// <summary> + /// Whether this control point is equivalent to another, ignoring time. + /// </summary> + /// <param name="other">Another control point to compare with.</param> + /// <returns>Whether equivalent.</returns> + public abstract bool EquivalentTo(ControlPoint other); + + public bool Equals(ControlPoint other) => Time.Equals(other?.Time) && EquivalentTo(other); } } diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index a3e3121575..42651fd0ca 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -1,12 +1,11 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osuTK; namespace osu.Game.Beatmaps.ControlPoints { - public class DifficultyControlPoint : ControlPoint, IEquatable<DifficultyControlPoint> + public class DifficultyControlPoint : ControlPoint { /// <summary> /// The speed multiplier at this control point. @@ -19,8 +18,7 @@ namespace osu.Game.Beatmaps.ControlPoints private double speedMultiplier = 1; - public bool Equals(DifficultyControlPoint other) - => base.Equals(other) - && SpeedMultiplier.Equals(other?.SpeedMultiplier); + public override bool EquivalentTo(ControlPoint other) => + other is DifficultyControlPoint otherTyped && otherTyped.SpeedMultiplier.Equals(speedMultiplier); } } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 354d86dc13..928f2a51ad 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; - namespace osu.Game.Beatmaps.ControlPoints { - public class EffectControlPoint : ControlPoint, IEquatable<EffectControlPoint> + public class EffectControlPoint : ControlPoint { /// <summary> /// Whether this control point enables Kiai mode. @@ -17,8 +15,8 @@ namespace osu.Game.Beatmaps.ControlPoints /// </summary> public bool OmitFirstBarLine; - public bool Equals(EffectControlPoint other) - => base.Equals(other) - && KiaiMode == other?.KiaiMode && OmitFirstBarLine == other.OmitFirstBarLine; + public override bool EquivalentTo(ControlPoint other) => + other is EffectControlPoint otherTyped && + KiaiMode == otherTyped.KiaiMode && OmitFirstBarLine == otherTyped.OmitFirstBarLine; } } diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 7bc7a9056d..35eefebca4 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -1,12 +1,11 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Game.Audio; namespace osu.Game.Beatmaps.ControlPoints { - public class SampleControlPoint : ControlPoint, IEquatable<SampleControlPoint> + public class SampleControlPoint : ControlPoint { public const string DEFAULT_BANK = "normal"; @@ -45,8 +44,8 @@ namespace osu.Game.Beatmaps.ControlPoints return newSampleInfo; } - public bool Equals(SampleControlPoint other) - => base.Equals(other) - && string.Equals(SampleBank, other?.SampleBank) && SampleVolume == other?.SampleVolume; + public override bool EquivalentTo(ControlPoint other) => + other is SampleControlPoint otherTyped && + string.Equals(SampleBank, otherTyped?.SampleBank) && SampleVolume == otherTyped?.SampleVolume; } } diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index ccb8a92b3a..03b188929b 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -1,13 +1,12 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osuTK; using osu.Game.Beatmaps.Timing; namespace osu.Game.Beatmaps.ControlPoints { - public class TimingControlPoint : ControlPoint, IEquatable<TimingControlPoint> + public class TimingControlPoint : ControlPoint { /// <summary> /// The time signature at this control point. @@ -27,8 +26,8 @@ namespace osu.Game.Beatmaps.ControlPoints private double beatLength = DEFAULT_BEAT_LENGTH; - public bool Equals(TimingControlPoint other) - => base.Equals(other) - && TimeSignature == other?.TimeSignature && beatLength.Equals(other.beatLength); + public override bool EquivalentTo(ControlPoint other) => + other is TimingControlPoint otherTyped + && TimeSignature == otherTyped?.TimeSignature && beatLength.Equals(otherTyped.beatLength); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 83d20da458..26f7209be6 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -189,7 +189,7 @@ namespace osu.Game.Beatmaps.Formats Foreground = 3 } - internal class LegacySampleControlPoint : SampleControlPoint, IEquatable<LegacySampleControlPoint> + internal class LegacySampleControlPoint : SampleControlPoint { public int CustomSampleBank; @@ -203,9 +203,9 @@ namespace osu.Game.Beatmaps.Formats return baseInfo; } - public bool Equals(LegacySampleControlPoint other) - => base.Equals(other) - && CustomSampleBank == other?.CustomSampleBank; + public override bool EquivalentTo(ControlPoint other) => + base.EquivalentTo(other) + && CustomSampleBank == ((LegacySampleControlPoint)other).CustomSampleBank; } } } From 94ffe03e6e71701e723db6196532dde41fd1c254 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Fri, 25 Oct 2019 16:19:06 +0900 Subject: [PATCH 3619/5608] Group timing points --- .../TestSceneDrawableHitObjects.cs | 2 +- .../TestSceneOsuDistanceSnapGrid.cs | 13 +- .../TestSceneSlider.cs | 2 +- .../TestSceneSliderInput.cs | 6 +- .../TestSceneTaikoPlayfield.cs | 6 +- .../Audio/DrumSampleMapping.cs | 7 +- .../Editor/TestSceneDistanceSnapGrid.cs | 10 +- .../Editor/TestSceneEditorSeekSnapping.cs | 20 ++- .../TestSceneDrawableScrollingRuleset.cs | 34 ++--- .../TestSceneBeatSyncedContainer.cs | 4 +- .../Beatmaps/ControlPoints/ControlPoint.cs | 6 +- .../ControlPoints/ControlPointGroup.cs | 48 +++++++ .../ControlPoints/ControlPointInfo.cs | 130 ++++++++++++++++-- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 92 ++----------- .../Containers/BeatSyncedContainer.cs | 2 - osu.Game/Screens/Edit/EditorClock.cs | 5 +- 16 files changed, 233 insertions(+), 154 deletions(-) create mode 100644 osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs index 7a9b61c60c..0369b6db4e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Catch.Tests private void load() { var controlPointInfo = new ControlPointInfo(); - controlPointInfo.TimingPoints.Add(new TimingControlPoint()); + controlPointInfo.Add(0, new TimingControlPoint()); WorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap { diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index 6b8daa531f..b66123e628 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -53,9 +53,8 @@ namespace osu.Game.Rulesets.Osu.Tests Clear(); editorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 1; - editorBeatmap.ControlPointInfo.DifficultyPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); beatDivisor.Value = 1; }); @@ -80,8 +79,8 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep($"set beat length = {beatLength}", () => { - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beatLength }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beatLength }); }); createGrid(); @@ -95,8 +94,8 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep($"set speed multiplier = {multiplier}", () => { - editorBeatmap.ControlPointInfo.DifficultyPoints.Clear(); - editorBeatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = multiplier }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = multiplier }); }); createGrid(); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 4893ebfdd4..a955911bd5 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -308,7 +308,7 @@ namespace osu.Game.Rulesets.Osu.Tests private Drawable createDrawable(Slider slider, float circleSize, double speedMultiplier) { var cpi = new ControlPointInfo(); - cpi.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = speedMultiplier }); + cpi.Add(0, new DifficultyControlPoint { SpeedMultiplier = speedMultiplier }); slider.ApplyDefaults(cpi, new BeatmapDifficulty { CircleSize = circleSize, SliderTickRate = 3 }); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index 2eb783233a..5f75cbabec 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -313,10 +313,6 @@ namespace osu.Game.Rulesets.Osu.Tests }, 25), } }, - ControlPointInfo = - { - DifficultyPoints = { new DifficultyControlPoint { SpeedMultiplier = 0.1f } } - }, BeatmapInfo = { BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 }, @@ -324,6 +320,8 @@ namespace osu.Game.Rulesets.Osu.Tests }, }); + Beatmap.Value.Beatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = 0.1f }); + var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }); p.OnLoadComplete += _ => diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index eaa8ca7ebb..8522a42739 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Taiko.Tests AddStep("Reset height", () => changePlayfieldSize(6)); var controlPointInfo = new ControlPointInfo(); - controlPointInfo.TimingPoints.Add(new TimingControlPoint()); + controlPointInfo.Add(0, new TimingControlPoint()); WorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap { @@ -142,7 +142,7 @@ namespace osu.Game.Rulesets.Taiko.Tests HitResult hitResult = RNG.Next(2) == 0 ? HitResult.Good : HitResult.Great; var cpi = new ControlPointInfo(); - cpi.EffectPoints.Add(new EffectControlPoint { KiaiMode = kiai }); + cpi.Add(0, new EffectControlPoint { KiaiMode = kiai }); Hit hit = new Hit(); hit.ApplyDefaults(cpi, new BeatmapDifficulty()); @@ -157,7 +157,7 @@ namespace osu.Game.Rulesets.Taiko.Tests HitResult hitResult = RNG.Next(2) == 0 ? HitResult.Good : HitResult.Great; var cpi = new ControlPointInfo(); - cpi.EffectPoints.Add(new EffectControlPoint { KiaiMode = kiai }); + cpi.Add(0, new EffectControlPoint { KiaiMode = kiai }); Hit hit = new Hit(); hit.ApplyDefaults(cpi, new BeatmapDifficulty()); diff --git a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs index ad2596931d..aaf113f216 100644 --- a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs +++ b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs @@ -19,12 +19,7 @@ namespace osu.Game.Rulesets.Taiko.Audio { this.controlPoints = controlPoints; - IEnumerable<SampleControlPoint> samplePoints; - if (controlPoints.SamplePoints.Count == 0) - // Get the default sample point - samplePoints = new[] { controlPoints.SamplePointAt(double.MinValue) }; - else - samplePoints = controlPoints.SamplePoints; + IEnumerable<SampleControlPoint> samplePoints = controlPoints.SamplePoints.Count == 0 ? new[] { controlPoints.SamplePointAt(double.MinValue) } : controlPoints.SamplePoints; foreach (var s in samplePoints) { diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index a9e5930478..07646fdb78 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Editor public TestSceneDistanceSnapGrid() { editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap()); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); createGrid(); } @@ -42,8 +42,8 @@ namespace osu.Game.Tests.Visual.Editor { Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); BeatDivisor.Value = 1; }); @@ -81,8 +81,8 @@ namespace osu.Game.Tests.Visual.Editor { AddStep($"set beat length = {beatLength}", () => { - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beatLength }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beatLength }); }); createGrid(); diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs index b997d6aaeb..3118e0cabe 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs @@ -28,18 +28,7 @@ namespace osu.Game.Tests.Visual.Editor { var testBeatmap = new Beatmap { - ControlPointInfo = new ControlPointInfo - { - TimingPoints = - { - new TimingControlPoint { Time = 0, BeatLength = 200 }, - new TimingControlPoint { Time = 100, BeatLength = 400 }, - new TimingControlPoint { Time = 175, BeatLength = 800 }, - new TimingControlPoint { Time = 350, BeatLength = 200 }, - new TimingControlPoint { Time = 450, BeatLength = 100 }, - new TimingControlPoint { Time = 500, BeatLength = 307.69230769230802 } - } - }, + ControlPointInfo = new ControlPointInfo(), HitObjects = { new HitCircle { StartTime = 0 }, @@ -47,6 +36,13 @@ namespace osu.Game.Tests.Visual.Editor } }; + testBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 200 }); + testBeatmap.ControlPointInfo.Add(100, new TimingControlPoint { BeatLength = 400 }); + testBeatmap.ControlPointInfo.Add(175, new TimingControlPoint { BeatLength = 800 }); + testBeatmap.ControlPointInfo.Add(350, new TimingControlPoint { BeatLength = 200 }); + testBeatmap.ControlPointInfo.Add(450, new TimingControlPoint { BeatLength = 100 }); + testBeatmap.ControlPointInfo.Add(500, new TimingControlPoint { BeatLength = 307.69230769230802 }); + Beatmap.Value = CreateWorkingBeatmap(testBeatmap); Child = new TimingPointVisualiser(testBeatmap, 5000) { Clock = Clock }; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index dcab964d6d..684e79b3f5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -47,7 +47,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestRelativeBeatLengthScaleSingleTimingPoint() { - var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range / 2 }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range / 2 }); createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); @@ -61,10 +62,10 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestRelativeBeatLengthScaleTimingPointBeyondEndDoesNotBecomeDominant() { - var beatmap = createBeatmap( - new TimingControlPoint { BeatLength = time_range / 2 }, - new TimingControlPoint { Time = 12000, BeatLength = time_range }, - new TimingControlPoint { Time = 100000, BeatLength = time_range }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range / 2 }); + beatmap.ControlPointInfo.Add(12000, new TimingControlPoint { BeatLength = time_range }); + beatmap.ControlPointInfo.Add(100000, new TimingControlPoint { BeatLength = time_range }); createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); @@ -75,9 +76,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestRelativeBeatLengthScaleFromSecondTimingPoint() { - var beatmap = createBeatmap( - new TimingControlPoint { BeatLength = time_range }, - new TimingControlPoint { Time = 3 * time_range, BeatLength = time_range / 2 }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); + beatmap.ControlPointInfo.Add(3 * time_range, new TimingControlPoint { BeatLength = time_range / 2 }); createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); @@ -97,9 +98,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestNonRelativeScale() { - var beatmap = createBeatmap( - new TimingControlPoint { BeatLength = time_range }, - new TimingControlPoint { Time = 3 * time_range, BeatLength = time_range / 2 }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); + beatmap.ControlPointInfo.Add(3 * time_range, new TimingControlPoint { BeatLength = time_range / 2 }); createTest(beatmap); @@ -119,7 +120,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestSliderMultiplierDoesNotAffectRelativeBeatLength() { - var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2; createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); @@ -132,7 +134,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestSliderMultiplierAffectsNonRelativeBeatLength() { - var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2; createTest(beatmap); @@ -154,14 +157,11 @@ namespace osu.Game.Tests.Visual.Gameplay /// Creates an <see cref="IBeatmap"/>, containing 10 hitobjects and user-provided timing points. /// The hitobjects are spaced <see cref="time_range"/> milliseconds apart. /// </summary> - /// <param name="timingControlPoints">The timing points to add to the beatmap.</param> /// <returns>The <see cref="IBeatmap"/>.</returns> - private IBeatmap createBeatmap(params TimingControlPoint[] timingControlPoints) + private IBeatmap createBeatmap() { var beatmap = new Beatmap<HitObject> { BeatmapInfo = { Ruleset = new OsuRuleset().RulesetInfo } }; - beatmap.ControlPointInfo.TimingPoints.AddRange(timingControlPoints); - for (int i = 0; i < 10; i++) beatmap.HitObjects.Add(new HitObject { StartTime = i * time_range }); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index d84ffa0d93..b6df559686 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Internal; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Track; @@ -10,7 +11,6 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Lists; using osu.Framework.Timing; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; @@ -153,7 +153,7 @@ namespace osu.Game.Tests.Visual.UserInterface }; } - private SortedList<TimingControlPoint> timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints; + private IReadOnlyList<TimingControlPoint> timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints; private TimingControlPoint getNextTimingPoint(TimingControlPoint current) { diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 0081fab46a..6288c1460f 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -10,13 +10,17 @@ namespace osu.Game.Beatmaps.ControlPoints /// <summary> /// The time at which the control point takes effect. /// </summary> - public double Time; + public double Time => controlPointGroup?.Time ?? 0; /// <summary> /// Whether this timing point was generated internally, as opposed to parsed from the underlying beatmap. /// </summary> internal bool AutoGenerated; + private ControlPointGroup controlPointGroup; + + public void AttachGroup(ControlPointGroup pointGroup) => this.controlPointGroup = pointGroup; + public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); /// <summary> diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs new file mode 100644 index 0000000000..c4b990675e --- /dev/null +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs @@ -0,0 +1,48 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace osu.Game.Beatmaps.ControlPoints +{ + public class ControlPointGroup : IComparable<ControlPointGroup> + { + public event Action<ControlPoint> ItemAdded; + public event Action<ControlPoint> ItemRemoved; + + /// <summary> + /// The time at which the control point takes effect. + /// </summary> + public double Time { get; } + + public IReadOnlyList<ControlPoint> ControlPoints => controlPoints; + + private readonly List<ControlPoint> controlPoints = new List<ControlPoint>(); + + public ControlPointGroup(double time) + { + Time = time; + } + + public int CompareTo(ControlPointGroup other) => Time.CompareTo(other.Time); + + public void Add(ControlPoint point) + { + point.AttachGroup(this); + + foreach (var existing in controlPoints.Where(p => p.GetType() == point.GetType()).ToArray()) + Remove(existing); + + controlPoints.Add(point); + ItemAdded?.Invoke(point); + } + + public void Remove(ControlPoint point) + { + controlPoints.Remove(point); + ItemRemoved?.Invoke(point); + } + } +} diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 68eb0ec6d1..2175eccaa2 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -12,35 +12,50 @@ namespace osu.Game.Beatmaps.ControlPoints [Serializable] public class ControlPointInfo { + /// <summary> + /// Control point groups. + /// </summary> + [JsonProperty] + public IReadOnlyList<ControlPointGroup> Groups => groups; + + private readonly SortedList<ControlPointGroup> groups = new SortedList<ControlPointGroup>(Comparer<ControlPointGroup>.Default); + /// <summary> /// All timing points. /// </summary> [JsonProperty] - public SortedList<TimingControlPoint> TimingPoints { get; private set; } = new SortedList<TimingControlPoint>(Comparer<TimingControlPoint>.Default); + public IReadOnlyList<TimingControlPoint> TimingPoints => timingPoints; + + private readonly SortedList<TimingControlPoint> timingPoints = new SortedList<TimingControlPoint>(Comparer<TimingControlPoint>.Default); /// <summary> /// All difficulty points. /// </summary> [JsonProperty] - public SortedList<DifficultyControlPoint> DifficultyPoints { get; private set; } = new SortedList<DifficultyControlPoint>(Comparer<DifficultyControlPoint>.Default); + public IReadOnlyList<DifficultyControlPoint> DifficultyPoints => difficultyPoints; + + private readonly SortedList<DifficultyControlPoint> difficultyPoints = new SortedList<DifficultyControlPoint>(Comparer<DifficultyControlPoint>.Default); /// <summary> /// All sound points. /// </summary> [JsonProperty] - public SortedList<SampleControlPoint> SamplePoints { get; private set; } = new SortedList<SampleControlPoint>(Comparer<SampleControlPoint>.Default); + public IReadOnlyList<SampleControlPoint> SamplePoints => samplePoints; + + private readonly SortedList<SampleControlPoint> samplePoints = new SortedList<SampleControlPoint>(Comparer<SampleControlPoint>.Default); /// <summary> /// All effect points. /// </summary> [JsonProperty] - public SortedList<EffectControlPoint> EffectPoints { get; private set; } = new SortedList<EffectControlPoint>(Comparer<EffectControlPoint>.Default); + public IReadOnlyList<EffectControlPoint> EffectPoints => effectPoints; - public IReadOnlyList<ControlPoint> AllControlPoints => - TimingPoints - .Concat((IEnumerable<ControlPoint>)DifficultyPoints) - .Concat(SamplePoints) - .Concat(EffectPoints).ToArray(); + private readonly SortedList<EffectControlPoint> effectPoints = new SortedList<EffectControlPoint>(Comparer<EffectControlPoint>.Default); + + /// <summary> + /// All control points, of all types. + /// </summary> + public IEnumerable<ControlPoint> AllControlPoints => Groups.SelectMany(g => g.ControlPoints); /// <summary> /// Finds the difficulty control point that is active at <paramref name="time"/>. @@ -70,6 +85,28 @@ namespace osu.Game.Beatmaps.ControlPoints /// <returns>The timing control point.</returns> public TimingControlPoint TimingPointAt(double time) => binarySearch(TimingPoints, time, TimingPoints.Count > 0 ? TimingPoints[0] : null); + /// <summary> + /// Finds the closest <see cref="ControlPoint"/> of the same type as <see cref="referencePoint"/> that is active at <paramref name="time"/>. + /// </summary> + /// <param name="time">The time to find the timing control point at.</param> + /// <param name="referencePoint">A reference point to infer type.</param> + /// <returns>The timing control point.</returns> + public ControlPoint SimilarPointAt(double time, ControlPoint referencePoint) + { + switch (referencePoint) + { + case TimingControlPoint _: return TimingPointAt(time); + + case EffectControlPoint _: return EffectPointAt(time); + + case SampleControlPoint _: return SamplePointAt(time); + + case DifficultyControlPoint _: return DifficultyPointAt(time); + } + + return null; + } + /// <summary> /// Finds the maximum BPM represented by any timing control point. /// </summary> @@ -98,7 +135,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// <param name="time">The time to find the control point at.</param> /// <param name="prePoint">The control point to use when <paramref name="time"/> is before any control points. If null, a new control point will be constructed.</param> /// <returns>The active control point at <paramref name="time"/>.</returns> - private T binarySearch<T>(SortedList<T> list, double time, T prePoint = null) + private T binarySearch<T>(IReadOnlyList<T> list, double time, T prePoint = null) where T : ControlPoint, new() { if (list == null) @@ -131,5 +168,78 @@ namespace osu.Game.Beatmaps.ControlPoints // l will be the first control point with Time > time, but we want the one before it return list[l - 1]; } + + public void Add(double time, ControlPoint newPoint, bool force = false) + { + if (!force && SimilarPointAt(time, newPoint)?.EquivalentTo(newPoint) == true) + return; + + GroupAt(time, true).Add(newPoint); + } + + public ControlPointGroup GroupAt(double time, bool createIfNotExisting) + { + var existing = Groups.FirstOrDefault(g => g.Time == time); + + if (existing != null) + return existing; + + if (createIfNotExisting) + { + var newGroup = new ControlPointGroup(time); + newGroup.ItemAdded += groupItemAdded; + newGroup.ItemRemoved += groupItemRemoved; + groups.Add(newGroup); + return newGroup; + } + + return null; + } + + private void groupItemRemoved(ControlPoint obj) + { + switch (obj) + { + case TimingControlPoint typed: + timingPoints.Remove(typed); + break; + + case EffectControlPoint typed: + effectPoints.Remove(typed); + break; + + case SampleControlPoint typed: + samplePoints.Remove(typed); + break; + + case DifficultyControlPoint typed: + difficultyPoints.Remove(typed); + break; + } + } + + private void groupItemAdded(ControlPoint obj) + { + switch (obj) + { + case TimingControlPoint typed: + timingPoints.Add(typed); + break; + + case EffectControlPoint typed: + effectPoints.Add(typed); + break; + + case SampleControlPoint typed: + samplePoints.Add(typed); + break; + + case DifficultyControlPoint typed: + difficultyPoints.Add(typed); + break; + } + } + + public void Clear() => groups.Clear(); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 786b7611b5..61f70a8c27 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -369,31 +369,29 @@ namespace osu.Game.Beatmaps.Formats if (timingChange) { var controlPoint = CreateTimingControlPoint(); - controlPoint.Time = time; controlPoint.BeatLength = beatLength; controlPoint.TimeSignature = timeSignature; - handleTimingControlPoint(controlPoint); + beatmap.ControlPointInfo.Add(time, controlPoint); + } + else + { + beatmap.ControlPointInfo.Add(time, new DifficultyControlPoint + { + SpeedMultiplier = speedMultiplier, + AutoGenerated = timingChange + }); } - handleDifficultyControlPoint(new DifficultyControlPoint + beatmap.ControlPointInfo.Add(time, new EffectControlPoint { - Time = time, - SpeedMultiplier = speedMultiplier, - AutoGenerated = timingChange - }); - - handleEffectControlPoint(new EffectControlPoint - { - Time = time, KiaiMode = kiaiMode, OmitFirstBarLine = omitFirstBarSignature, AutoGenerated = timingChange }); - handleSampleControlPoint(new LegacySampleControlPoint + beatmap.ControlPointInfo.Add(time, new LegacySampleControlPoint { - Time = time, SampleBank = stringSampleSet, SampleVolume = sampleVolume, CustomSampleBank = customSampleBank, @@ -401,74 +399,6 @@ namespace osu.Game.Beatmaps.Formats }); } - private void handleTimingControlPoint(TimingControlPoint newPoint) - { - var existing = beatmap.ControlPointInfo.TimingPointAt(newPoint.Time); - - if (existing.Time == newPoint.Time) - { - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - - beatmap.ControlPointInfo.TimingPoints.Remove(existing); - } - - beatmap.ControlPointInfo.TimingPoints.Add(newPoint); - } - - private void handleDifficultyControlPoint(DifficultyControlPoint newPoint) - { - var existing = beatmap.ControlPointInfo.DifficultyPointAt(newPoint.Time); - - if (existing.Time == newPoint.Time) - { - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - - beatmap.ControlPointInfo.DifficultyPoints.Remove(existing); - } - - beatmap.ControlPointInfo.DifficultyPoints.Add(newPoint); - } - - private void handleEffectControlPoint(EffectControlPoint newPoint) - { - var existing = beatmap.ControlPointInfo.EffectPointAt(newPoint.Time); - - if (existing.Time == newPoint.Time) - { - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - - beatmap.ControlPointInfo.EffectPoints.Remove(existing); - } - - beatmap.ControlPointInfo.EffectPoints.Add(newPoint); - } - - private void handleSampleControlPoint(SampleControlPoint newPoint) - { - var existing = beatmap.ControlPointInfo.SamplePointAt(newPoint.Time); - - if (existing.Time == newPoint.Time) - { - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - - beatmap.ControlPointInfo.SamplePoints.Remove(existing); - } - - beatmap.ControlPointInfo.SamplePoints.Add(newPoint); - } - private void handleHitObject(string line) { // If the ruleset wasn't specified, assume the osu!standard ruleset. diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 370d044ba4..2832a70518 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -105,12 +105,10 @@ namespace osu.Game.Graphics.Containers { BeatLength = default_beat_length, AutoGenerated = true, - Time = 0 }; defaultEffect = new EffectControlPoint { - Time = 0, AutoGenerated = true, KiaiMode = false, OmitFirstBarLine = false diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 24fb561f04..1cfb123f25 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Beatmaps; @@ -57,7 +58,7 @@ namespace osu.Game.Screens.Edit // Depending on beatSnapLength, we may snap to a beat that is beyond timingPoint's end time, but we want to instead snap to // the next timing point's start time - var nextTimingPoint = ControlPointInfo.TimingPoints.Find(t => t.Time > timingPoint.Time); + var nextTimingPoint = ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time); if (position > nextTimingPoint?.Time) position = nextTimingPoint.Time; @@ -124,7 +125,7 @@ namespace osu.Game.Screens.Edit if (seekTime < timingPoint.Time && timingPoint != ControlPointInfo.TimingPoints.First()) seekTime = timingPoint.Time; - var nextTimingPoint = ControlPointInfo.TimingPoints.Find(t => t.Time > timingPoint.Time); + var nextTimingPoint = ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time); if (seekTime > nextTimingPoint?.Time) seekTime = nextTimingPoint.Time; From da6769f0fcd9966a24624ec97451a16dd01fc187 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Fri, 25 Oct 2019 17:00:23 +0900 Subject: [PATCH 3620/5608] Remove necessity of AutoGenerated flag --- .../Formats/LegacyBeatmapDecoderTest.cs | 10 +-- .../Beatmaps/ControlPoints/ControlPoint.cs | 7 +-- .../ControlPoints/ControlPointInfo.cs | 2 +- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 63 ++++++++++++++----- .../Containers/BeatSyncedContainer.cs | 2 - .../Edit/Timing/ControlPointSettings.cs | 2 +- .../Screens/Edit/Timing/ControlPointTable.cs | 3 - 7 files changed, 56 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index de516d3142..c50250159e 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -167,9 +167,9 @@ namespace osu.Game.Tests.Beatmaps.Formats var controlPoints = beatmap.ControlPointInfo; Assert.AreEqual(4, controlPoints.TimingPoints.Count); - Assert.AreEqual(42, controlPoints.DifficultyPoints.Count); - Assert.AreEqual(42, controlPoints.SamplePoints.Count); - Assert.AreEqual(42, controlPoints.EffectPoints.Count); + Assert.AreEqual(5, controlPoints.DifficultyPoints.Count); + Assert.AreEqual(34, controlPoints.SamplePoints.Count); + Assert.AreEqual(8, controlPoints.EffectPoints.Count); var timingPoint = controlPoints.TimingPointAt(0); Assert.AreEqual(956, timingPoint.Time); @@ -191,7 +191,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(48428); - Assert.AreEqual(48428, difficultyPoint.Time); + Assert.AreEqual(0, difficultyPoint.Time); Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(116999); @@ -224,7 +224,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.IsFalse(effectPoint.OmitFirstBarLine); effectPoint = controlPoints.EffectPointAt(119637); - Assert.AreEqual(119637, effectPoint.Time); + Assert.AreEqual(95901, effectPoint.Time); Assert.IsFalse(effectPoint.KiaiMode); Assert.IsFalse(effectPoint.OmitFirstBarLine); } diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 6288c1460f..0861e00d8d 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -12,11 +12,6 @@ namespace osu.Game.Beatmaps.ControlPoints /// </summary> public double Time => controlPointGroup?.Time ?? 0; - /// <summary> - /// Whether this timing point was generated internally, as opposed to parsed from the underlying beatmap. - /// </summary> - internal bool AutoGenerated; - private ControlPointGroup controlPointGroup; public void AttachGroup(ControlPointGroup pointGroup) => this.controlPointGroup = pointGroup; diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 2175eccaa2..7e9c8844f0 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -177,7 +177,7 @@ namespace osu.Game.Beatmaps.ControlPoints GroupAt(time, true).Add(newPoint); } - public ControlPointGroup GroupAt(double time, bool createIfNotExisting) + public ControlPointGroup GroupAt(double time, bool createIfNotExisting = false) { var existing = Groups.FirstOrDefault(g => g.Time == time); diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 61f70a8c27..5589aecc19 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.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.IO; using System.Linq; using osu.Framework.IO.File; @@ -50,6 +51,8 @@ namespace osu.Game.Beatmaps.Formats base.ParseStreamInto(stream, beatmap); + flushPendingPoints(); + // Objects may be out of order *only* if a user has manually edited an .osu file. // Unfortunately there are ranked maps in this state (example: https://osu.ppy.sh/s/594828). // OrderBy is used to guarantee that the parsing order of hitobjects with equal start times is maintained (stably-sorted) @@ -369,34 +372,64 @@ namespace osu.Game.Beatmaps.Formats if (timingChange) { var controlPoint = CreateTimingControlPoint(); + controlPoint.BeatLength = beatLength; controlPoint.TimeSignature = timeSignature; - beatmap.ControlPointInfo.Add(time, controlPoint); - } - else - { - beatmap.ControlPointInfo.Add(time, new DifficultyControlPoint - { - SpeedMultiplier = speedMultiplier, - AutoGenerated = timingChange - }); + addControlPoint(time, controlPoint, true); } - beatmap.ControlPointInfo.Add(time, new EffectControlPoint + addControlPoint(time, new DifficultyControlPoint + { + SpeedMultiplier = speedMultiplier, + }, timingChange); + + addControlPoint(time, new EffectControlPoint { KiaiMode = kiaiMode, OmitFirstBarLine = omitFirstBarSignature, - AutoGenerated = timingChange - }); + }, timingChange); - beatmap.ControlPointInfo.Add(time, new LegacySampleControlPoint + addControlPoint(time, new LegacySampleControlPoint { SampleBank = stringSampleSet, SampleVolume = sampleVolume, CustomSampleBank = customSampleBank, - AutoGenerated = timingChange - }); + }, timingChange); + + // To handle the scenario where a non-timing line shares the same time value as a subsequent timing line but + // appears earlier in the file, we buffer non-timing control points and rewrite them *after* control points from the timing line + // with the same time value (allowing them to overwrite as necessary). + // + // The expected outcome is that we prefer the non-timing line's adjustments over the timing line's adjustments when time is equal. + if (timingChange) + flushPendingPoints(); + } + + private readonly List<ControlPoint> pendingControlPoints = new List<ControlPoint>(); + private double pendingControlPointsTime; + + private void addControlPoint(double time, ControlPoint point, bool timingChange) + { + if (timingChange) + { + beatmap.ControlPointInfo.Add(time, point); + return; + } + + if (time != pendingControlPointsTime) + flushPendingPoints(); + + pendingControlPoints.Add(point); + pendingControlPointsTime = time; + } + + private void flushPendingPoints() + { + foreach (var p in pendingControlPoints) + beatmap.ControlPointInfo.Add(pendingControlPointsTime, p); + + pendingControlPoints.Clear(); } private void handleHitObject(string line) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 2832a70518..2e76ab964f 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -104,12 +104,10 @@ namespace osu.Game.Graphics.Containers defaultTiming = new TimingControlPoint { BeatLength = default_beat_length, - AutoGenerated = true, }; defaultEffect = new EffectControlPoint { - AutoGenerated = true, KiaiMode = false, OmitFirstBarLine = false }; diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index 0974745294..ce72d7c191 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -228,7 +228,7 @@ namespace osu.Game.Screens.Edit.Timing selectedPoints.BindValueChanged(points => { - ControlPoint.Value = points.NewValue?.OfType<T>().Where(p => !p.AutoGenerated).FirstOrDefault(); + ControlPoint.Value = points.NewValue?.OfType<T>().FirstOrDefault(); checkbox.Current.Value = ControlPoint.Value != null; }, true); diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 777d34e75b..597200e54c 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -105,9 +105,6 @@ namespace osu.Game.Screens.Edit.Timing private Drawable createAttribute(ControlPoint controlPoint) { - if (controlPoint.AutoGenerated) - return null; - switch (controlPoint) { case TimingControlPoint timing: From e2f2638212524bfa0d95971af8b0a458c404006e Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Fri, 25 Oct 2019 17:00:56 +0900 Subject: [PATCH 3621/5608] Replace local Equatable implementations with abstract EquivalentTo --- osu.Game/Beatmaps/ControlPoints/ControlPoint.cs | 12 +++++++++--- .../Beatmaps/ControlPoints/DifficultyControlPoint.cs | 8 +++----- .../Beatmaps/ControlPoints/EffectControlPoint.cs | 10 ++++------ .../Beatmaps/ControlPoints/SampleControlPoint.cs | 9 ++++----- .../Beatmaps/ControlPoints/TimingControlPoint.cs | 9 ++++----- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 8 ++++---- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index abe7e5e803..0081fab46a 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -5,7 +5,7 @@ using System; namespace osu.Game.Beatmaps.ControlPoints { - public class ControlPoint : IComparable<ControlPoint>, IEquatable<ControlPoint> + public abstract class ControlPoint : IComparable<ControlPoint>, IEquatable<ControlPoint> { /// <summary> /// The time at which the control point takes effect. @@ -19,7 +19,13 @@ namespace osu.Game.Beatmaps.ControlPoints public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); - public bool Equals(ControlPoint other) - => Time.Equals(other?.Time); + /// <summary> + /// Whether this control point is equivalent to another, ignoring time. + /// </summary> + /// <param name="other">Another control point to compare with.</param> + /// <returns>Whether equivalent.</returns> + public abstract bool EquivalentTo(ControlPoint other); + + public bool Equals(ControlPoint other) => Time.Equals(other?.Time) && EquivalentTo(other); } } diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index a3e3121575..42651fd0ca 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -1,12 +1,11 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osuTK; namespace osu.Game.Beatmaps.ControlPoints { - public class DifficultyControlPoint : ControlPoint, IEquatable<DifficultyControlPoint> + public class DifficultyControlPoint : ControlPoint { /// <summary> /// The speed multiplier at this control point. @@ -19,8 +18,7 @@ namespace osu.Game.Beatmaps.ControlPoints private double speedMultiplier = 1; - public bool Equals(DifficultyControlPoint other) - => base.Equals(other) - && SpeedMultiplier.Equals(other?.SpeedMultiplier); + public override bool EquivalentTo(ControlPoint other) => + other is DifficultyControlPoint otherTyped && otherTyped.SpeedMultiplier.Equals(speedMultiplier); } } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 354d86dc13..928f2a51ad 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; - namespace osu.Game.Beatmaps.ControlPoints { - public class EffectControlPoint : ControlPoint, IEquatable<EffectControlPoint> + public class EffectControlPoint : ControlPoint { /// <summary> /// Whether this control point enables Kiai mode. @@ -17,8 +15,8 @@ namespace osu.Game.Beatmaps.ControlPoints /// </summary> public bool OmitFirstBarLine; - public bool Equals(EffectControlPoint other) - => base.Equals(other) - && KiaiMode == other?.KiaiMode && OmitFirstBarLine == other.OmitFirstBarLine; + public override bool EquivalentTo(ControlPoint other) => + other is EffectControlPoint otherTyped && + KiaiMode == otherTyped.KiaiMode && OmitFirstBarLine == otherTyped.OmitFirstBarLine; } } diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 7bc7a9056d..35eefebca4 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -1,12 +1,11 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Game.Audio; namespace osu.Game.Beatmaps.ControlPoints { - public class SampleControlPoint : ControlPoint, IEquatable<SampleControlPoint> + public class SampleControlPoint : ControlPoint { public const string DEFAULT_BANK = "normal"; @@ -45,8 +44,8 @@ namespace osu.Game.Beatmaps.ControlPoints return newSampleInfo; } - public bool Equals(SampleControlPoint other) - => base.Equals(other) - && string.Equals(SampleBank, other?.SampleBank) && SampleVolume == other?.SampleVolume; + public override bool EquivalentTo(ControlPoint other) => + other is SampleControlPoint otherTyped && + string.Equals(SampleBank, otherTyped?.SampleBank) && SampleVolume == otherTyped?.SampleVolume; } } diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index ccb8a92b3a..03b188929b 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -1,13 +1,12 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osuTK; using osu.Game.Beatmaps.Timing; namespace osu.Game.Beatmaps.ControlPoints { - public class TimingControlPoint : ControlPoint, IEquatable<TimingControlPoint> + public class TimingControlPoint : ControlPoint { /// <summary> /// The time signature at this control point. @@ -27,8 +26,8 @@ namespace osu.Game.Beatmaps.ControlPoints private double beatLength = DEFAULT_BEAT_LENGTH; - public bool Equals(TimingControlPoint other) - => base.Equals(other) - && TimeSignature == other?.TimeSignature && beatLength.Equals(other.beatLength); + public override bool EquivalentTo(ControlPoint other) => + other is TimingControlPoint otherTyped + && TimeSignature == otherTyped?.TimeSignature && beatLength.Equals(otherTyped.beatLength); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 83d20da458..26f7209be6 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -189,7 +189,7 @@ namespace osu.Game.Beatmaps.Formats Foreground = 3 } - internal class LegacySampleControlPoint : SampleControlPoint, IEquatable<LegacySampleControlPoint> + internal class LegacySampleControlPoint : SampleControlPoint { public int CustomSampleBank; @@ -203,9 +203,9 @@ namespace osu.Game.Beatmaps.Formats return baseInfo; } - public bool Equals(LegacySampleControlPoint other) - => base.Equals(other) - && CustomSampleBank == other?.CustomSampleBank; + public override bool EquivalentTo(ControlPoint other) => + base.EquivalentTo(other) + && CustomSampleBank == ((LegacySampleControlPoint)other).CustomSampleBank; } } } From e987db37ec9c8cf86936359259ca93875951506d Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Fri, 25 Oct 2019 19:48:01 +0900 Subject: [PATCH 3622/5608] Add grouping of ControlPoints --- .../TestSceneDrawableHitObjects.cs | 2 +- .../TestSceneOsuDistanceSnapGrid.cs | 13 +- .../TestSceneSlider.cs | 2 +- .../TestSceneSliderInput.cs | 6 +- .../TestSceneTaikoPlayfield.cs | 6 +- .../Audio/DrumSampleMapping.cs | 7 +- .../Editor/TestSceneDistanceSnapGrid.cs | 10 +- .../Editor/TestSceneEditorSeekSnapping.cs | 20 ++- .../TestSceneDrawableScrollingRuleset.cs | 34 ++--- .../TestSceneBeatSyncedContainer.cs | 4 +- .../Beatmaps/ControlPoints/ControlPoint.cs | 6 +- .../ControlPoints/ControlPointGroup.cs | 48 +++++++ .../ControlPoints/ControlPointInfo.cs | 126 +++++++++++++++++- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 92 ++----------- .../Containers/BeatSyncedContainer.cs | 2 - osu.Game/Screens/Edit/EditorClock.cs | 5 +- 16 files changed, 234 insertions(+), 149 deletions(-) create mode 100644 osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs index 7a9b61c60c..0369b6db4e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Catch.Tests private void load() { var controlPointInfo = new ControlPointInfo(); - controlPointInfo.TimingPoints.Add(new TimingControlPoint()); + controlPointInfo.Add(0, new TimingControlPoint()); WorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap { diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index 6b8daa531f..b66123e628 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -53,9 +53,8 @@ namespace osu.Game.Rulesets.Osu.Tests Clear(); editorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 1; - editorBeatmap.ControlPointInfo.DifficultyPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); beatDivisor.Value = 1; }); @@ -80,8 +79,8 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep($"set beat length = {beatLength}", () => { - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beatLength }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beatLength }); }); createGrid(); @@ -95,8 +94,8 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep($"set speed multiplier = {multiplier}", () => { - editorBeatmap.ControlPointInfo.DifficultyPoints.Clear(); - editorBeatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = multiplier }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = multiplier }); }); createGrid(); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 4893ebfdd4..a955911bd5 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -308,7 +308,7 @@ namespace osu.Game.Rulesets.Osu.Tests private Drawable createDrawable(Slider slider, float circleSize, double speedMultiplier) { var cpi = new ControlPointInfo(); - cpi.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = speedMultiplier }); + cpi.Add(0, new DifficultyControlPoint { SpeedMultiplier = speedMultiplier }); slider.ApplyDefaults(cpi, new BeatmapDifficulty { CircleSize = circleSize, SliderTickRate = 3 }); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index 2eb783233a..5f75cbabec 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -313,10 +313,6 @@ namespace osu.Game.Rulesets.Osu.Tests }, 25), } }, - ControlPointInfo = - { - DifficultyPoints = { new DifficultyControlPoint { SpeedMultiplier = 0.1f } } - }, BeatmapInfo = { BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 }, @@ -324,6 +320,8 @@ namespace osu.Game.Rulesets.Osu.Tests }, }); + Beatmap.Value.Beatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = 0.1f }); + var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }); p.OnLoadComplete += _ => diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index eaa8ca7ebb..8522a42739 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Taiko.Tests AddStep("Reset height", () => changePlayfieldSize(6)); var controlPointInfo = new ControlPointInfo(); - controlPointInfo.TimingPoints.Add(new TimingControlPoint()); + controlPointInfo.Add(0, new TimingControlPoint()); WorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap { @@ -142,7 +142,7 @@ namespace osu.Game.Rulesets.Taiko.Tests HitResult hitResult = RNG.Next(2) == 0 ? HitResult.Good : HitResult.Great; var cpi = new ControlPointInfo(); - cpi.EffectPoints.Add(new EffectControlPoint { KiaiMode = kiai }); + cpi.Add(0, new EffectControlPoint { KiaiMode = kiai }); Hit hit = new Hit(); hit.ApplyDefaults(cpi, new BeatmapDifficulty()); @@ -157,7 +157,7 @@ namespace osu.Game.Rulesets.Taiko.Tests HitResult hitResult = RNG.Next(2) == 0 ? HitResult.Good : HitResult.Great; var cpi = new ControlPointInfo(); - cpi.EffectPoints.Add(new EffectControlPoint { KiaiMode = kiai }); + cpi.Add(0, new EffectControlPoint { KiaiMode = kiai }); Hit hit = new Hit(); hit.ApplyDefaults(cpi, new BeatmapDifficulty()); diff --git a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs index ad2596931d..aaf113f216 100644 --- a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs +++ b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs @@ -19,12 +19,7 @@ namespace osu.Game.Rulesets.Taiko.Audio { this.controlPoints = controlPoints; - IEnumerable<SampleControlPoint> samplePoints; - if (controlPoints.SamplePoints.Count == 0) - // Get the default sample point - samplePoints = new[] { controlPoints.SamplePointAt(double.MinValue) }; - else - samplePoints = controlPoints.SamplePoints; + IEnumerable<SampleControlPoint> samplePoints = controlPoints.SamplePoints.Count == 0 ? new[] { controlPoints.SamplePointAt(double.MinValue) } : controlPoints.SamplePoints; foreach (var s in samplePoints) { diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index a9e5930478..07646fdb78 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Editor public TestSceneDistanceSnapGrid() { editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap()); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); createGrid(); } @@ -42,8 +42,8 @@ namespace osu.Game.Tests.Visual.Editor { Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); BeatDivisor.Value = 1; }); @@ -81,8 +81,8 @@ namespace osu.Game.Tests.Visual.Editor { AddStep($"set beat length = {beatLength}", () => { - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beatLength }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beatLength }); }); createGrid(); diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs index b997d6aaeb..3118e0cabe 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs @@ -28,18 +28,7 @@ namespace osu.Game.Tests.Visual.Editor { var testBeatmap = new Beatmap { - ControlPointInfo = new ControlPointInfo - { - TimingPoints = - { - new TimingControlPoint { Time = 0, BeatLength = 200 }, - new TimingControlPoint { Time = 100, BeatLength = 400 }, - new TimingControlPoint { Time = 175, BeatLength = 800 }, - new TimingControlPoint { Time = 350, BeatLength = 200 }, - new TimingControlPoint { Time = 450, BeatLength = 100 }, - new TimingControlPoint { Time = 500, BeatLength = 307.69230769230802 } - } - }, + ControlPointInfo = new ControlPointInfo(), HitObjects = { new HitCircle { StartTime = 0 }, @@ -47,6 +36,13 @@ namespace osu.Game.Tests.Visual.Editor } }; + testBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 200 }); + testBeatmap.ControlPointInfo.Add(100, new TimingControlPoint { BeatLength = 400 }); + testBeatmap.ControlPointInfo.Add(175, new TimingControlPoint { BeatLength = 800 }); + testBeatmap.ControlPointInfo.Add(350, new TimingControlPoint { BeatLength = 200 }); + testBeatmap.ControlPointInfo.Add(450, new TimingControlPoint { BeatLength = 100 }); + testBeatmap.ControlPointInfo.Add(500, new TimingControlPoint { BeatLength = 307.69230769230802 }); + Beatmap.Value = CreateWorkingBeatmap(testBeatmap); Child = new TimingPointVisualiser(testBeatmap, 5000) { Clock = Clock }; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index dcab964d6d..684e79b3f5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -47,7 +47,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestRelativeBeatLengthScaleSingleTimingPoint() { - var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range / 2 }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range / 2 }); createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); @@ -61,10 +62,10 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestRelativeBeatLengthScaleTimingPointBeyondEndDoesNotBecomeDominant() { - var beatmap = createBeatmap( - new TimingControlPoint { BeatLength = time_range / 2 }, - new TimingControlPoint { Time = 12000, BeatLength = time_range }, - new TimingControlPoint { Time = 100000, BeatLength = time_range }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range / 2 }); + beatmap.ControlPointInfo.Add(12000, new TimingControlPoint { BeatLength = time_range }); + beatmap.ControlPointInfo.Add(100000, new TimingControlPoint { BeatLength = time_range }); createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); @@ -75,9 +76,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestRelativeBeatLengthScaleFromSecondTimingPoint() { - var beatmap = createBeatmap( - new TimingControlPoint { BeatLength = time_range }, - new TimingControlPoint { Time = 3 * time_range, BeatLength = time_range / 2 }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); + beatmap.ControlPointInfo.Add(3 * time_range, new TimingControlPoint { BeatLength = time_range / 2 }); createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); @@ -97,9 +98,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestNonRelativeScale() { - var beatmap = createBeatmap( - new TimingControlPoint { BeatLength = time_range }, - new TimingControlPoint { Time = 3 * time_range, BeatLength = time_range / 2 }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); + beatmap.ControlPointInfo.Add(3 * time_range, new TimingControlPoint { BeatLength = time_range / 2 }); createTest(beatmap); @@ -119,7 +120,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestSliderMultiplierDoesNotAffectRelativeBeatLength() { - var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2; createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); @@ -132,7 +134,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestSliderMultiplierAffectsNonRelativeBeatLength() { - var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2; createTest(beatmap); @@ -154,14 +157,11 @@ namespace osu.Game.Tests.Visual.Gameplay /// Creates an <see cref="IBeatmap"/>, containing 10 hitobjects and user-provided timing points. /// The hitobjects are spaced <see cref="time_range"/> milliseconds apart. /// </summary> - /// <param name="timingControlPoints">The timing points to add to the beatmap.</param> /// <returns>The <see cref="IBeatmap"/>.</returns> - private IBeatmap createBeatmap(params TimingControlPoint[] timingControlPoints) + private IBeatmap createBeatmap() { var beatmap = new Beatmap<HitObject> { BeatmapInfo = { Ruleset = new OsuRuleset().RulesetInfo } }; - beatmap.ControlPointInfo.TimingPoints.AddRange(timingControlPoints); - for (int i = 0; i < 10; i++) beatmap.HitObjects.Add(new HitObject { StartTime = i * time_range }); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index d84ffa0d93..b6df559686 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Internal; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Track; @@ -10,7 +11,6 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Lists; using osu.Framework.Timing; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; @@ -153,7 +153,7 @@ namespace osu.Game.Tests.Visual.UserInterface }; } - private SortedList<TimingControlPoint> timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints; + private IReadOnlyList<TimingControlPoint> timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints; private TimingControlPoint getNextTimingPoint(TimingControlPoint current) { diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 0081fab46a..6288c1460f 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -10,13 +10,17 @@ namespace osu.Game.Beatmaps.ControlPoints /// <summary> /// The time at which the control point takes effect. /// </summary> - public double Time; + public double Time => controlPointGroup?.Time ?? 0; /// <summary> /// Whether this timing point was generated internally, as opposed to parsed from the underlying beatmap. /// </summary> internal bool AutoGenerated; + private ControlPointGroup controlPointGroup; + + public void AttachGroup(ControlPointGroup pointGroup) => this.controlPointGroup = pointGroup; + public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); /// <summary> diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs new file mode 100644 index 0000000000..c4b990675e --- /dev/null +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs @@ -0,0 +1,48 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace osu.Game.Beatmaps.ControlPoints +{ + public class ControlPointGroup : IComparable<ControlPointGroup> + { + public event Action<ControlPoint> ItemAdded; + public event Action<ControlPoint> ItemRemoved; + + /// <summary> + /// The time at which the control point takes effect. + /// </summary> + public double Time { get; } + + public IReadOnlyList<ControlPoint> ControlPoints => controlPoints; + + private readonly List<ControlPoint> controlPoints = new List<ControlPoint>(); + + public ControlPointGroup(double time) + { + Time = time; + } + + public int CompareTo(ControlPointGroup other) => Time.CompareTo(other.Time); + + public void Add(ControlPoint point) + { + point.AttachGroup(this); + + foreach (var existing in controlPoints.Where(p => p.GetType() == point.GetType()).ToArray()) + Remove(existing); + + controlPoints.Add(point); + ItemAdded?.Invoke(point); + } + + public void Remove(ControlPoint point) + { + controlPoints.Remove(point); + ItemRemoved?.Invoke(point); + } + } +} diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 855084ad02..6a760343c3 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -12,29 +12,50 @@ namespace osu.Game.Beatmaps.ControlPoints [Serializable] public class ControlPointInfo { + /// <summary> + /// Control point groups. + /// </summary> + [JsonProperty] + public IReadOnlyList<ControlPointGroup> Groups => groups; + + private readonly SortedList<ControlPointGroup> groups = new SortedList<ControlPointGroup>(Comparer<ControlPointGroup>.Default); + /// <summary> /// All timing points. /// </summary> [JsonProperty] - public SortedList<TimingControlPoint> TimingPoints { get; private set; } = new SortedList<TimingControlPoint>(Comparer<TimingControlPoint>.Default); + public IReadOnlyList<TimingControlPoint> TimingPoints => timingPoints; + + private readonly SortedList<TimingControlPoint> timingPoints = new SortedList<TimingControlPoint>(Comparer<TimingControlPoint>.Default); /// <summary> /// All difficulty points. /// </summary> [JsonProperty] - public SortedList<DifficultyControlPoint> DifficultyPoints { get; private set; } = new SortedList<DifficultyControlPoint>(Comparer<DifficultyControlPoint>.Default); + public IReadOnlyList<DifficultyControlPoint> DifficultyPoints => difficultyPoints; + + private readonly SortedList<DifficultyControlPoint> difficultyPoints = new SortedList<DifficultyControlPoint>(Comparer<DifficultyControlPoint>.Default); /// <summary> /// All sound points. /// </summary> [JsonProperty] - public SortedList<SampleControlPoint> SamplePoints { get; private set; } = new SortedList<SampleControlPoint>(Comparer<SampleControlPoint>.Default); + public IReadOnlyList<SampleControlPoint> SamplePoints => samplePoints; + + private readonly SortedList<SampleControlPoint> samplePoints = new SortedList<SampleControlPoint>(Comparer<SampleControlPoint>.Default); /// <summary> /// All effect points. /// </summary> [JsonProperty] - public SortedList<EffectControlPoint> EffectPoints { get; private set; } = new SortedList<EffectControlPoint>(Comparer<EffectControlPoint>.Default); + public IReadOnlyList<EffectControlPoint> EffectPoints => effectPoints; + + private readonly SortedList<EffectControlPoint> effectPoints = new SortedList<EffectControlPoint>(Comparer<EffectControlPoint>.Default); + + /// <summary> + /// All control points, of all types. + /// </summary> + public IEnumerable<ControlPoint> AllControlPoints => Groups.SelectMany(g => g.ControlPoints).ToArray(); /// <summary> /// Finds the difficulty control point that is active at <paramref name="time"/>. @@ -64,6 +85,28 @@ namespace osu.Game.Beatmaps.ControlPoints /// <returns>The timing control point.</returns> public TimingControlPoint TimingPointAt(double time) => binarySearch(TimingPoints, time, TimingPoints.Count > 0 ? TimingPoints[0] : null); + /// <summary> + /// Finds the closest <see cref="ControlPoint"/> of the same type as <see cref="referencePoint"/> that is active at <paramref name="time"/>. + /// </summary> + /// <param name="time">The time to find the timing control point at.</param> + /// <param name="referencePoint">A reference point to infer type.</param> + /// <returns>The timing control point.</returns> + public ControlPoint SimilarPointAt(double time, ControlPoint referencePoint) + { + switch (referencePoint) + { + case TimingControlPoint _: return TimingPointAt(time); + + case EffectControlPoint _: return EffectPointAt(time); + + case SampleControlPoint _: return SamplePointAt(time); + + case DifficultyControlPoint _: return DifficultyPointAt(time); + } + + return null; + } + /// <summary> /// Finds the maximum BPM represented by any timing control point. /// </summary> @@ -92,7 +135,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// <param name="time">The time to find the control point at.</param> /// <param name="prePoint">The control point to use when <paramref name="time"/> is before any control points. If null, a new control point will be constructed.</param> /// <returns>The active control point at <paramref name="time"/>.</returns> - private T binarySearch<T>(SortedList<T> list, double time, T prePoint = null) + private T binarySearch<T>(IReadOnlyList<T> list, double time, T prePoint = null) where T : ControlPoint, new() { if (list == null) @@ -125,5 +168,78 @@ namespace osu.Game.Beatmaps.ControlPoints // l will be the first control point with Time > time, but we want the one before it return list[l - 1]; } + + public void Add(double time, ControlPoint newPoint, bool force = false) + { + if (!force && SimilarPointAt(time, newPoint)?.EquivalentTo(newPoint) == true) + return; + + GroupAt(time, true).Add(newPoint); + } + + public ControlPointGroup GroupAt(double time, bool createIfNotExisting) + { + var existing = Groups.FirstOrDefault(g => g.Time == time); + + if (existing != null) + return existing; + + if (createIfNotExisting) + { + var newGroup = new ControlPointGroup(time); + newGroup.ItemAdded += groupItemAdded; + newGroup.ItemRemoved += groupItemRemoved; + groups.Add(newGroup); + return newGroup; + } + + return null; + } + + private void groupItemRemoved(ControlPoint obj) + { + switch (obj) + { + case TimingControlPoint typed: + timingPoints.Remove(typed); + break; + + case EffectControlPoint typed: + effectPoints.Remove(typed); + break; + + case SampleControlPoint typed: + samplePoints.Remove(typed); + break; + + case DifficultyControlPoint typed: + difficultyPoints.Remove(typed); + break; + } + } + + private void groupItemAdded(ControlPoint obj) + { + switch (obj) + { + case TimingControlPoint typed: + timingPoints.Add(typed); + break; + + case EffectControlPoint typed: + effectPoints.Add(typed); + break; + + case SampleControlPoint typed: + samplePoints.Add(typed); + break; + + case DifficultyControlPoint typed: + difficultyPoints.Add(typed); + break; + } + } + + public void Clear() => groups.Clear(); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 786b7611b5..61f70a8c27 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -369,31 +369,29 @@ namespace osu.Game.Beatmaps.Formats if (timingChange) { var controlPoint = CreateTimingControlPoint(); - controlPoint.Time = time; controlPoint.BeatLength = beatLength; controlPoint.TimeSignature = timeSignature; - handleTimingControlPoint(controlPoint); + beatmap.ControlPointInfo.Add(time, controlPoint); + } + else + { + beatmap.ControlPointInfo.Add(time, new DifficultyControlPoint + { + SpeedMultiplier = speedMultiplier, + AutoGenerated = timingChange + }); } - handleDifficultyControlPoint(new DifficultyControlPoint + beatmap.ControlPointInfo.Add(time, new EffectControlPoint { - Time = time, - SpeedMultiplier = speedMultiplier, - AutoGenerated = timingChange - }); - - handleEffectControlPoint(new EffectControlPoint - { - Time = time, KiaiMode = kiaiMode, OmitFirstBarLine = omitFirstBarSignature, AutoGenerated = timingChange }); - handleSampleControlPoint(new LegacySampleControlPoint + beatmap.ControlPointInfo.Add(time, new LegacySampleControlPoint { - Time = time, SampleBank = stringSampleSet, SampleVolume = sampleVolume, CustomSampleBank = customSampleBank, @@ -401,74 +399,6 @@ namespace osu.Game.Beatmaps.Formats }); } - private void handleTimingControlPoint(TimingControlPoint newPoint) - { - var existing = beatmap.ControlPointInfo.TimingPointAt(newPoint.Time); - - if (existing.Time == newPoint.Time) - { - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - - beatmap.ControlPointInfo.TimingPoints.Remove(existing); - } - - beatmap.ControlPointInfo.TimingPoints.Add(newPoint); - } - - private void handleDifficultyControlPoint(DifficultyControlPoint newPoint) - { - var existing = beatmap.ControlPointInfo.DifficultyPointAt(newPoint.Time); - - if (existing.Time == newPoint.Time) - { - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - - beatmap.ControlPointInfo.DifficultyPoints.Remove(existing); - } - - beatmap.ControlPointInfo.DifficultyPoints.Add(newPoint); - } - - private void handleEffectControlPoint(EffectControlPoint newPoint) - { - var existing = beatmap.ControlPointInfo.EffectPointAt(newPoint.Time); - - if (existing.Time == newPoint.Time) - { - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - - beatmap.ControlPointInfo.EffectPoints.Remove(existing); - } - - beatmap.ControlPointInfo.EffectPoints.Add(newPoint); - } - - private void handleSampleControlPoint(SampleControlPoint newPoint) - { - var existing = beatmap.ControlPointInfo.SamplePointAt(newPoint.Time); - - if (existing.Time == newPoint.Time) - { - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - - beatmap.ControlPointInfo.SamplePoints.Remove(existing); - } - - beatmap.ControlPointInfo.SamplePoints.Add(newPoint); - } - private void handleHitObject(string line) { // If the ruleset wasn't specified, assume the osu!standard ruleset. diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 370d044ba4..2832a70518 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -105,12 +105,10 @@ namespace osu.Game.Graphics.Containers { BeatLength = default_beat_length, AutoGenerated = true, - Time = 0 }; defaultEffect = new EffectControlPoint { - Time = 0, AutoGenerated = true, KiaiMode = false, OmitFirstBarLine = false diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 24fb561f04..1cfb123f25 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Beatmaps; @@ -57,7 +58,7 @@ namespace osu.Game.Screens.Edit // Depending on beatSnapLength, we may snap to a beat that is beyond timingPoint's end time, but we want to instead snap to // the next timing point's start time - var nextTimingPoint = ControlPointInfo.TimingPoints.Find(t => t.Time > timingPoint.Time); + var nextTimingPoint = ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time); if (position > nextTimingPoint?.Time) position = nextTimingPoint.Time; @@ -124,7 +125,7 @@ namespace osu.Game.Screens.Edit if (seekTime < timingPoint.Time && timingPoint != ControlPointInfo.TimingPoints.First()) seekTime = timingPoint.Time; - var nextTimingPoint = ControlPointInfo.TimingPoints.Find(t => t.Time > timingPoint.Time); + var nextTimingPoint = ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time); if (seekTime > nextTimingPoint?.Time) seekTime = nextTimingPoint.Time; From 8baf569f5976680d4e730a84a144e8bd53466579 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Fri, 25 Oct 2019 19:58:42 +0900 Subject: [PATCH 3623/5608] Remove necessity of AutoGenerated flag --- .../Formats/LegacyBeatmapDecoderTest.cs | 10 +-- .../Beatmaps/ControlPoints/ControlPoint.cs | 7 +-- .../ControlPoints/ControlPointInfo.cs | 2 +- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 63 ++++++++++++++----- .../Containers/BeatSyncedContainer.cs | 2 - 5 files changed, 55 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index de516d3142..c50250159e 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -167,9 +167,9 @@ namespace osu.Game.Tests.Beatmaps.Formats var controlPoints = beatmap.ControlPointInfo; Assert.AreEqual(4, controlPoints.TimingPoints.Count); - Assert.AreEqual(42, controlPoints.DifficultyPoints.Count); - Assert.AreEqual(42, controlPoints.SamplePoints.Count); - Assert.AreEqual(42, controlPoints.EffectPoints.Count); + Assert.AreEqual(5, controlPoints.DifficultyPoints.Count); + Assert.AreEqual(34, controlPoints.SamplePoints.Count); + Assert.AreEqual(8, controlPoints.EffectPoints.Count); var timingPoint = controlPoints.TimingPointAt(0); Assert.AreEqual(956, timingPoint.Time); @@ -191,7 +191,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(48428); - Assert.AreEqual(48428, difficultyPoint.Time); + Assert.AreEqual(0, difficultyPoint.Time); Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(116999); @@ -224,7 +224,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.IsFalse(effectPoint.OmitFirstBarLine); effectPoint = controlPoints.EffectPointAt(119637); - Assert.AreEqual(119637, effectPoint.Time); + Assert.AreEqual(95901, effectPoint.Time); Assert.IsFalse(effectPoint.KiaiMode); Assert.IsFalse(effectPoint.OmitFirstBarLine); } diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 6288c1460f..0861e00d8d 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -12,11 +12,6 @@ namespace osu.Game.Beatmaps.ControlPoints /// </summary> public double Time => controlPointGroup?.Time ?? 0; - /// <summary> - /// Whether this timing point was generated internally, as opposed to parsed from the underlying beatmap. - /// </summary> - internal bool AutoGenerated; - private ControlPointGroup controlPointGroup; public void AttachGroup(ControlPointGroup pointGroup) => this.controlPointGroup = pointGroup; diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 6a760343c3..b7bb993fc0 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -177,7 +177,7 @@ namespace osu.Game.Beatmaps.ControlPoints GroupAt(time, true).Add(newPoint); } - public ControlPointGroup GroupAt(double time, bool createIfNotExisting) + public ControlPointGroup GroupAt(double time, bool createIfNotExisting = false) { var existing = Groups.FirstOrDefault(g => g.Time == time); diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 61f70a8c27..5589aecc19 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.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.IO; using System.Linq; using osu.Framework.IO.File; @@ -50,6 +51,8 @@ namespace osu.Game.Beatmaps.Formats base.ParseStreamInto(stream, beatmap); + flushPendingPoints(); + // Objects may be out of order *only* if a user has manually edited an .osu file. // Unfortunately there are ranked maps in this state (example: https://osu.ppy.sh/s/594828). // OrderBy is used to guarantee that the parsing order of hitobjects with equal start times is maintained (stably-sorted) @@ -369,34 +372,64 @@ namespace osu.Game.Beatmaps.Formats if (timingChange) { var controlPoint = CreateTimingControlPoint(); + controlPoint.BeatLength = beatLength; controlPoint.TimeSignature = timeSignature; - beatmap.ControlPointInfo.Add(time, controlPoint); - } - else - { - beatmap.ControlPointInfo.Add(time, new DifficultyControlPoint - { - SpeedMultiplier = speedMultiplier, - AutoGenerated = timingChange - }); + addControlPoint(time, controlPoint, true); } - beatmap.ControlPointInfo.Add(time, new EffectControlPoint + addControlPoint(time, new DifficultyControlPoint + { + SpeedMultiplier = speedMultiplier, + }, timingChange); + + addControlPoint(time, new EffectControlPoint { KiaiMode = kiaiMode, OmitFirstBarLine = omitFirstBarSignature, - AutoGenerated = timingChange - }); + }, timingChange); - beatmap.ControlPointInfo.Add(time, new LegacySampleControlPoint + addControlPoint(time, new LegacySampleControlPoint { SampleBank = stringSampleSet, SampleVolume = sampleVolume, CustomSampleBank = customSampleBank, - AutoGenerated = timingChange - }); + }, timingChange); + + // To handle the scenario where a non-timing line shares the same time value as a subsequent timing line but + // appears earlier in the file, we buffer non-timing control points and rewrite them *after* control points from the timing line + // with the same time value (allowing them to overwrite as necessary). + // + // The expected outcome is that we prefer the non-timing line's adjustments over the timing line's adjustments when time is equal. + if (timingChange) + flushPendingPoints(); + } + + private readonly List<ControlPoint> pendingControlPoints = new List<ControlPoint>(); + private double pendingControlPointsTime; + + private void addControlPoint(double time, ControlPoint point, bool timingChange) + { + if (timingChange) + { + beatmap.ControlPointInfo.Add(time, point); + return; + } + + if (time != pendingControlPointsTime) + flushPendingPoints(); + + pendingControlPoints.Add(point); + pendingControlPointsTime = time; + } + + private void flushPendingPoints() + { + foreach (var p in pendingControlPoints) + beatmap.ControlPointInfo.Add(pendingControlPointsTime, p); + + pendingControlPoints.Clear(); } private void handleHitObject(string line) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 2832a70518..2e76ab964f 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -104,12 +104,10 @@ namespace osu.Game.Graphics.Containers defaultTiming = new TimingControlPoint { BeatLength = default_beat_length, - AutoGenerated = true, }; defaultEffect = new EffectControlPoint { - AutoGenerated = true, KiaiMode = false, OmitFirstBarLine = false }; From e39016bf011d0cf43d3132b798cc5240645dc640 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Fri, 25 Oct 2019 20:04:27 +0900 Subject: [PATCH 3624/5608] Fix known non-nulls --- osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs | 2 +- osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 35eefebca4..07f5aa6c90 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -46,6 +46,6 @@ namespace osu.Game.Beatmaps.ControlPoints public override bool EquivalentTo(ControlPoint other) => other is SampleControlPoint otherTyped && - string.Equals(SampleBank, otherTyped?.SampleBank) && SampleVolume == otherTyped?.SampleVolume; + string.Equals(SampleBank, otherTyped.SampleBank) && SampleVolume == otherTyped.SampleVolume; } } diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index 03b188929b..f8c84c79dd 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -28,6 +28,6 @@ namespace osu.Game.Beatmaps.ControlPoints public override bool EquivalentTo(ControlPoint other) => other is TimingControlPoint otherTyped - && TimeSignature == otherTyped?.TimeSignature && beatLength.Equals(otherTyped.beatLength); + && TimeSignature == otherTyped.TimeSignature && beatLength.Equals(otherTyped.beatLength); } } From b8efc59cdcd2be6d4ca8cbe9466221c61b70672c Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Fri, 25 Oct 2019 20:13:22 +0900 Subject: [PATCH 3625/5608] Update UI components to use new grouping --- .../Edit/Timing/ControlPointSettings.cs | 4 ++-- .../Screens/Edit/Timing/ControlPointTable.cs | 18 ++++++++---------- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 10 ++++------ 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index ce72d7c191..470750b860 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -167,7 +167,7 @@ namespace osu.Game.Screens.Edit.Timing private const float header_height = 20; [Resolved] - private Bindable<IEnumerable<ControlPoint>> selectedPoints { get; set; } + private Bindable<ControlPointGroup> selectedPoints { get; set; } [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -228,7 +228,7 @@ namespace osu.Game.Screens.Edit.Timing selectedPoints.BindValueChanged(points => { - ControlPoint.Value = points.NewValue?.OfType<T>().FirstOrDefault(); + ControlPoint.Value = points.NewValue?.ControlPoints.OfType<T>().FirstOrDefault(); checkbox.Current.Value = ControlPoint.Value != null; }, true); diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 597200e54c..aca74d4a20 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Edit.Timing private readonly FillFlowContainer backgroundFlow; [Resolved] - private Bindable<IEnumerable<ControlPoint>> selectedPoints { get; set; } + private Bindable<ControlPointGroup> selectedGroup { get; set; } public ControlPointTable() { @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Edit.Timing }); } - public IEnumerable<ControlPoint> ControlPoints + public IEnumerable<ControlPointGroup> ControlGroups { set { @@ -56,15 +56,13 @@ namespace osu.Game.Screens.Edit.Timing if (value?.Any() != true) return; - var grouped = value.GroupBy(cp => cp.Time, cp => cp); - - foreach (var group in grouped) + foreach (var group in value) { - backgroundFlow.Add(new RowBackground { Action = () => selectedPoints.Value = group }); + backgroundFlow.Add(new RowBackground { Action = () => selectedGroup.Value = group }); } Columns = createHeaders(); - Content = grouped.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); + Content = value.Select((g, i) => createContent(i, g)).ToArray().ToRectangular(); } } @@ -80,7 +78,7 @@ namespace osu.Game.Screens.Edit.Timing return columns.ToArray(); } - private Drawable[] createContent(int index, IGrouping<double, ControlPoint> controlPoints) => new Drawable[] + private Drawable[] createContent(int index, ControlPointGroup group) => new Drawable[] { new OsuSpriteText { @@ -90,14 +88,14 @@ namespace osu.Game.Screens.Edit.Timing }, new OsuSpriteText { - Text = $"{controlPoints.Key:n0}ms", + Text = $"{group.Time:n0}ms", Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, new FillFlowContainer { RelativeSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - ChildrenEnumerable = controlPoints.Select(createAttribute).Where(c => c != null), + ChildrenEnumerable = group.ControlPoints.Select(createAttribute).Where(c => c != null), Padding = new MarginPadding(10), Spacing = new Vector2(10) }, diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index bd0a75f0b0..a9fd038829 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -21,7 +19,7 @@ namespace osu.Game.Screens.Edit.Timing public class TimingScreen : EditorScreenWithTimeline { [Cached] - private Bindable<IEnumerable<ControlPoint>> selectedPoints = new Bindable<IEnumerable<ControlPoint>>(); + private Bindable<ControlPointGroup> selectedPoints = new Bindable<ControlPointGroup>(); [Resolved] private IAdjustableClock clock { get; set; } @@ -48,7 +46,7 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - selectedPoints.BindValueChanged(selected => { clock.Seek(selected.NewValue.First().Time); }); + selectedPoints.BindValueChanged(selected => { clock.Seek(selected.NewValue.Time); }); } public class ControlPointList : CompositeDrawable @@ -59,7 +57,7 @@ namespace osu.Game.Screens.Edit.Timing protected IBindable<WorkingBeatmap> Beatmap { get; private set; } [Resolved] - private Bindable<IEnumerable<ControlPoint>> selectedPoints { get; set; } + private Bindable<ControlPointGroup> selectedPoints { get; set; } [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -78,7 +76,7 @@ namespace osu.Game.Screens.Edit.Timing RelativeSizeAxes = Axes.Both, Child = new ControlPointTable { - ControlPoints = Beatmap.Value.Beatmap.ControlPointInfo.AllControlPoints + ControlGroups = Beatmap.Value.Beatmap.ControlPointInfo.Groups } }, new FillFlowContainer From c031aeb14c95431f9f7cc5e875b4a22248e0070f Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sat, 26 Oct 2019 00:06:05 +0900 Subject: [PATCH 3626/5608] Fix inspection --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 61f70a8c27..b5f763fc8d 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -379,7 +379,7 @@ namespace osu.Game.Beatmaps.Formats beatmap.ControlPointInfo.Add(time, new DifficultyControlPoint { SpeedMultiplier = speedMultiplier, - AutoGenerated = timingChange + AutoGenerated = false }); } From d25f7f4c275997c168659ce9f0143eb830531083 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sat, 26 Oct 2019 01:19:23 +0900 Subject: [PATCH 3627/5608] Correctly clear other lists --- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 6a760343c3..8f7777daff 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -240,6 +240,13 @@ namespace osu.Game.Beatmaps.ControlPoints } } - public void Clear() => groups.Clear(); + public void Clear() + { + groups.Clear(); + timingPoints.Clear(); + difficultyPoints.Clear(); + samplePoints.Clear(); + effectPoints.Clear(); + } } } From b0e21c2749d24d58de0b4c92569244bdeed77460 Mon Sep 17 00:00:00 2001 From: nwabear <iambeardaniel@gmail.com> Date: Fri, 25 Oct 2019 14:57:49 -0500 Subject: [PATCH 3628/5608] Fixed Issue #6442 --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 7 +++++++ osu.Game/Screens/Play/Player.cs | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index d5b3df27df..d37f053486 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -239,6 +239,11 @@ namespace osu.Game.Rulesets.UI continueResume(); } + public override void CancelResume() + { + ResumeOverlay.Hide(); + } + /// <summary> /// Creates and adds the visual representation of a <see cref="TObject"/> to this <see cref="DrawableRuleset{TObject}"/>. /// </summary> @@ -453,6 +458,8 @@ namespace osu.Game.Rulesets.UI /// <param name="continueResume">The action to run when resuming is to be completed.</param> public abstract void RequestResume(Action continueResume); + public abstract void CancelResume(); + /// <summary> /// Create a <see cref="ScoreProcessor"/> for the associated ruleset and link with this /// <see cref="DrawableRuleset"/>. diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0b363eac4d..7eccde4555 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -443,6 +443,11 @@ namespace osu.Game.Screens.Play { if (!canPause) return; + if (IsResuming) + { + DrawableRuleset.CancelResume(); + } + IsResuming = false; GameplayClockContainer.Stop(); PauseOverlay.Show(); From f8354eefc4e058b98fc9d834bc0be2bc441db1e4 Mon Sep 17 00:00:00 2001 From: nwabear <iambeardaniel@gmail.com> Date: Fri, 25 Oct 2019 16:49:18 -0500 Subject: [PATCH 3629/5608] Added null check in the CancelResume method --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index d37f053486..d3e1118625 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -241,7 +241,7 @@ namespace osu.Game.Rulesets.UI public override void CancelResume() { - ResumeOverlay.Hide(); + ResumeOverlay?.Hide(); } /// <summary> From 7100319858fd510e07eff7538c45d321ffd8ec99 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sat, 26 Oct 2019 08:31:41 +0900 Subject: [PATCH 3630/5608] Fix incorrect control point retrieval in non-lookup cases --- .../ControlPoints/ControlPointInfo.cs | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 8f7777daff..0122ee5cdc 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -62,28 +62,28 @@ namespace osu.Game.Beatmaps.ControlPoints /// </summary> /// <param name="time">The time to find the difficulty control point at.</param> /// <returns>The difficulty control point.</returns> - public DifficultyControlPoint DifficultyPointAt(double time) => binarySearch(DifficultyPoints, time); + public DifficultyControlPoint DifficultyPointAt(double time) => binarySearchWithFallback(DifficultyPoints, time); /// <summary> /// Finds the effect control point that is active at <paramref name="time"/>. /// </summary> /// <param name="time">The time to find the effect control point at.</param> /// <returns>The effect control point.</returns> - public EffectControlPoint EffectPointAt(double time) => binarySearch(EffectPoints, time); + public EffectControlPoint EffectPointAt(double time) => binarySearchWithFallback(EffectPoints, time); /// <summary> /// Finds the sound control point that is active at <paramref name="time"/>. /// </summary> /// <param name="time">The time to find the sound control point at.</param> /// <returns>The sound control point.</returns> - public SampleControlPoint SamplePointAt(double time) => binarySearch(SamplePoints, time, SamplePoints.Count > 0 ? SamplePoints[0] : null); + public SampleControlPoint SamplePointAt(double time) => binarySearchWithFallback(SamplePoints, time, SamplePoints.Count > 0 ? SamplePoints[0] : null); /// <summary> /// Finds the timing control point that is active at <paramref name="time"/>. /// </summary> /// <param name="time">The time to find the timing control point at.</param> /// <returns>The timing control point.</returns> - public TimingControlPoint TimingPointAt(double time) => binarySearch(TimingPoints, time, TimingPoints.Count > 0 ? TimingPoints[0] : null); + public TimingControlPoint TimingPointAt(double time) => binarySearchWithFallback(TimingPoints, time, TimingPoints.Count > 0 ? TimingPoints[0] : null); /// <summary> /// Finds the closest <see cref="ControlPoint"/> of the same type as <see cref="referencePoint"/> that is active at <paramref name="time"/>. @@ -95,13 +95,13 @@ namespace osu.Game.Beatmaps.ControlPoints { switch (referencePoint) { - case TimingControlPoint _: return TimingPointAt(time); + case TimingControlPoint _: return binarySearch(TimingPoints, time); - case EffectControlPoint _: return EffectPointAt(time); + case EffectControlPoint _: return binarySearch(EffectPoints, time); - case SampleControlPoint _: return SamplePointAt(time); + case SampleControlPoint _: return binarySearch(SamplePoints, time); - case DifficultyControlPoint _: return DifficultyPointAt(time); + case DifficultyControlPoint _: return binarySearch(DifficultyPoints, time); } return null; @@ -130,22 +130,35 @@ namespace osu.Game.Beatmaps.ControlPoints /// <summary> /// Binary searches one of the control point lists to find the active control point at <paramref name="time"/>. + /// Includes logic for returning a specific point when no matching point is found. /// </summary> /// <param name="list">The list to search.</param> /// <param name="time">The time to find the control point at.</param> /// <param name="prePoint">The control point to use when <paramref name="time"/> is before any control points. If null, a new control point will be constructed.</param> - /// <returns>The active control point at <paramref name="time"/>.</returns> - private T binarySearch<T>(IReadOnlyList<T> list, double time, T prePoint = null) + /// <returns>The active control point at <paramref name="time"/>, or a fallback <see cref="ControlPoint"/> if none found.</returns> + private T binarySearchWithFallback<T>(IReadOnlyList<T> list, double time, T prePoint = null) where T : ControlPoint, new() + { + return binarySearch(list, time) ?? prePoint ?? new T(); + } + + /// <summary> + /// Binary searches one of the control point lists to find the active control point at <paramref name="time"/>. + /// </summary> + /// <param name="list">The list to search.</param> + /// <param name="time">The time to find the control point at.</param> + /// <returns>The active control point at <paramref name="time"/>.</returns> + private T binarySearch<T>(IReadOnlyList<T> list, double time) + where T : ControlPoint { if (list == null) throw new ArgumentNullException(nameof(list)); if (list.Count == 0) - return new T(); + return null; if (time < list[0].Time) - return prePoint ?? new T(); + return null; if (time >= list[list.Count - 1].Time) return list[list.Count - 1]; From a724909c251b3175dd33db24904dca582043a00e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= <dach.bartlomiej@gmail.com> Date: Sat, 26 Oct 2019 01:43:33 +0200 Subject: [PATCH 3631/5608] Add temporary mobile report issue template Due to an overwhelming amount of mobile reports that are not actively being worked on (neither by the core team, due to more pressing priorities, nor by external contributors) and take up considerable time to manage, add an issue template that aims to enforce a temporary moratorium on accepting mobile issues. --- .github/ISSUE_TEMPLATE/mobile-issues.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/mobile-issues.md diff --git a/.github/ISSUE_TEMPLATE/mobile-issues.md b/.github/ISSUE_TEMPLATE/mobile-issues.md new file mode 100644 index 0000000000..f41562f532 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/mobile-issues.md @@ -0,0 +1,7 @@ +--- +name: Mobile Report +about: ⚠ Due to current development priorities we are currently not accepting mobile reports. +--- + +⚠ **PLEASE READ** ⚠: Due to prioritising finishing the client for desktop first we are not accepting reports related to mobile platforms for the time being. +Please check back in the future when the focus of development shifts towards mobile! From dca8de5e6be35d875fc7f33780a68560a768c807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= <dach.bartlomiej@gmail.com> Date: Sat, 26 Oct 2019 02:06:39 +0200 Subject: [PATCH 3632/5608] Rephrase template description --- .github/ISSUE_TEMPLATE/mobile-issues.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/mobile-issues.md b/.github/ISSUE_TEMPLATE/mobile-issues.md index f41562f532..6938f18097 100644 --- a/.github/ISSUE_TEMPLATE/mobile-issues.md +++ b/.github/ISSUE_TEMPLATE/mobile-issues.md @@ -1,6 +1,6 @@ --- name: Mobile Report -about: ⚠ Due to current development priorities we are currently not accepting mobile reports. +about: ⚠ Due to current development priorities we are not accepting mobile reports at this time. --- ⚠ **PLEASE READ** ⚠: Due to prioritising finishing the client for desktop first we are not accepting reports related to mobile platforms for the time being. From d6a49b9e93eecd41c6c6e4fc91b599b93050b6bf Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sat, 26 Oct 2019 10:25:13 +0900 Subject: [PATCH 3633/5608] Add back autogeneration rules Will be removed in https://github.com/ppy/osu/pull/6604 --- .../Beatmaps/ControlPoints/ControlPointGroup.cs | 13 +++++++++++-- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 3 --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 12 +++++------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs index c4b990675e..8b71fc1897 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs @@ -30,10 +30,19 @@ namespace osu.Game.Beatmaps.ControlPoints public void Add(ControlPoint point) { - point.AttachGroup(this); + var existing = controlPoints.FirstOrDefault(p => p.GetType() == point.GetType()); + + if (existing != null) + { + // autogenerated points should not replace non-autogenerated. + // this allows for incorrectly ordered timing points to still be correctly handled. + if (point.AutoGenerated && !existing.AutoGenerated) + return; - foreach (var existing in controlPoints.Where(p => p.GetType() == point.GetType()).ToArray()) Remove(existing); + } + + point.AttachGroup(this); controlPoints.Add(point); ItemAdded?.Invoke(point); diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 0122ee5cdc..d6db4c8d10 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -184,9 +184,6 @@ namespace osu.Game.Beatmaps.ControlPoints public void Add(double time, ControlPoint newPoint, bool force = false) { - if (!force && SimilarPointAt(time, newPoint)?.EquivalentTo(newPoint) == true) - return; - GroupAt(time, true).Add(newPoint); } diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index b5f763fc8d..24422199e5 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -374,14 +374,12 @@ namespace osu.Game.Beatmaps.Formats beatmap.ControlPointInfo.Add(time, controlPoint); } - else + + beatmap.ControlPointInfo.Add(time, new DifficultyControlPoint { - beatmap.ControlPointInfo.Add(time, new DifficultyControlPoint - { - SpeedMultiplier = speedMultiplier, - AutoGenerated = false - }); - } + SpeedMultiplier = speedMultiplier, + AutoGenerated = timingChange + }); beatmap.ControlPointInfo.Add(time, new EffectControlPoint { From 8ccff0e9cf6e42f21a23b324bc12cc6bea4105fd Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sat, 26 Oct 2019 11:20:07 +0900 Subject: [PATCH 3634/5608] temp --- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 6 +++--- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index c50250159e..7317771bac 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -167,9 +167,9 @@ namespace osu.Game.Tests.Beatmaps.Formats var controlPoints = beatmap.ControlPointInfo; Assert.AreEqual(4, controlPoints.TimingPoints.Count); - Assert.AreEqual(5, controlPoints.DifficultyPoints.Count); + Assert.AreEqual(6, controlPoints.DifficultyPoints.Count); Assert.AreEqual(34, controlPoints.SamplePoints.Count); - Assert.AreEqual(8, controlPoints.EffectPoints.Count); + Assert.AreEqual(9, controlPoints.EffectPoints.Count); var timingPoint = controlPoints.TimingPointAt(0); Assert.AreEqual(956, timingPoint.Time); @@ -191,7 +191,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(48428); - Assert.AreEqual(0, difficultyPoint.Time); + Assert.AreEqual(956, difficultyPoint.Time); Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(116999); diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 24e3c3d8ca..f8c6d3aa3b 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -95,13 +95,13 @@ namespace osu.Game.Beatmaps.ControlPoints { switch (referencePoint) { - case TimingControlPoint _: return TimingPointAt(time); + case TimingControlPoint _: return binarySearch(TimingPoints, time); - case EffectControlPoint _: return EffectPointAt(time); + case EffectControlPoint _: return binarySearch(EffectPoints, time); - case SampleControlPoint _: return SamplePointAt(time); + case SampleControlPoint _: return binarySearch(SamplePoints, time); - case DifficultyControlPoint _: return DifficultyPointAt(time); + case DifficultyControlPoint _: return binarySearch(DifficultyPoints, time); } return null; From 4290a71f442902dfb21248aa5e214d73b07f99d3 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sat, 26 Oct 2019 11:38:05 +0900 Subject: [PATCH 3635/5608] Add special case for timing points Timing points can't fallback to defaults and must be added at least once. --- .../ControlPoints/ControlPointInfo.cs | 57 +++++++++++-------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 24e3c3d8ca..3927f46530 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -85,28 +85,6 @@ namespace osu.Game.Beatmaps.ControlPoints /// <returns>The timing control point.</returns> public TimingControlPoint TimingPointAt(double time) => binarySearchWithFallback(TimingPoints, time, TimingPoints.Count > 0 ? TimingPoints[0] : null); - /// <summary> - /// Finds the closest <see cref="ControlPoint"/> of the same type as <see cref="referencePoint"/> that is active at <paramref name="time"/>. - /// </summary> - /// <param name="time">The time to find the timing control point at.</param> - /// <param name="referencePoint">A reference point to infer type.</param> - /// <returns>The timing control point.</returns> - public ControlPoint SimilarPointAt(double time, ControlPoint referencePoint) - { - switch (referencePoint) - { - case TimingControlPoint _: return TimingPointAt(time); - - case EffectControlPoint _: return EffectPointAt(time); - - case SampleControlPoint _: return SamplePointAt(time); - - case DifficultyControlPoint _: return DifficultyPointAt(time); - } - - return null; - } - /// <summary> /// Finds the maximum BPM represented by any timing control point. /// </summary> @@ -184,7 +162,7 @@ namespace osu.Game.Beatmaps.ControlPoints public void Add(double time, ControlPoint newPoint, bool force = false) { - if (!force && SimilarPointAt(time, newPoint)?.EquivalentTo(newPoint) == true) + if (!force && checkAlreadyExisting(time, newPoint)) return; GroupAt(time, true).Add(newPoint); @@ -209,6 +187,39 @@ namespace osu.Game.Beatmaps.ControlPoints return null; } + /// <summary> + /// Check whether <see cref="newPoint"/> should be added. + /// </summary> + /// <param name="time">The time to find the timing control point at.</param> + /// <param name="newPoint">A point to be added.</param> + /// <returns>Whether the new point should be added.</returns> + private bool checkAlreadyExisting(double time, ControlPoint newPoint) + { + ControlPoint existing = null; + + switch (newPoint) + { + case TimingControlPoint _: + // Timing points are a special case and need to be added regardless of fallback availability. + existing = binarySearch(TimingPoints, time); + break; + + case EffectControlPoint _: + existing = EffectPointAt(time); + break; + + case SampleControlPoint _: + existing = SamplePointAt(time); + break; + + case DifficultyControlPoint _: + existing = DifficultyPointAt(time); + break; + } + + return existing?.EquivalentTo(newPoint) == true; + } + private void groupItemRemoved(ControlPoint obj) { switch (obj) From 654890776d31d75a5bcab4761341752890b39908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= <dach.bartlomiej@gmail.com> Date: Sat, 26 Oct 2019 14:56:29 +0200 Subject: [PATCH 3636/5608] Add exemption for potential code contributors Add an exemption clause allowing potential code contributors to submit issues if they state they would like to work on them, and note that mobile-related pull requests are still accepted. Suggested-by: Dean Herbert <pe@ppy.sh> --- .github/ISSUE_TEMPLATE/mobile-issues.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/mobile-issues.md b/.github/ISSUE_TEMPLATE/mobile-issues.md index 6938f18097..f171e80b8b 100644 --- a/.github/ISSUE_TEMPLATE/mobile-issues.md +++ b/.github/ISSUE_TEMPLATE/mobile-issues.md @@ -1,7 +1,8 @@ --- name: Mobile Report -about: ⚠ Due to current development priorities we are not accepting mobile reports at this time. +about: ⚠ Due to current development priorities we are not accepting mobile reports at this time (unless you're willing to fix them yourself!) --- -⚠ **PLEASE READ** ⚠: Due to prioritising finishing the client for desktop first we are not accepting reports related to mobile platforms for the time being. -Please check back in the future when the focus of development shifts towards mobile! +⚠ **PLEASE READ** ⚠: Due to prioritising finishing the client for desktop first we are not accepting reports related to mobile platforms for the time being, unless you're willing to fix them. +If you'd like to report a problem or suggest a feature and then work on it, feel free to open an issue and highlight that you'd like to address it yourself in the issue body; mobile pull requests are also welcome. +Otherwise, please check back in the future when the focus of development shifts towards mobile! From 9e2e87c8d13cf147b720825a5ff266c024cabf72 Mon Sep 17 00:00:00 2001 From: nwabear <iambeardaniel@gmail.com> Date: Sat, 26 Oct 2019 14:29:52 -0500 Subject: [PATCH 3637/5608] added visual tests added small commenting added xmldoc for CancelResume(); --- .../Visual/Gameplay/TestScenePause.cs | 18 ++++++++++++++++++ osu.Game/Rulesets/UI/DrawableRuleset.cs | 5 +++++ 2 files changed, 23 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 2df22df659..64022b2410 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -69,6 +69,24 @@ namespace osu.Game.Tests.Visual.Gameplay confirmClockRunning(true); } + [Test] + public void TestPauseWithResumeOverlay() + { + AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre)); + AddUntilStep("wait for hitobjects", () => Player.ScoreProcessor.Health.Value < 1); + + pauseAndConfirm(); + + resume(); + confirmClockRunning(false); + confirmPauseOverlayShown(false); + + pauseAndConfirm(); + + AddUntilStep("resume overlay is not active", () => Player.DrawableRuleset.ResumeOverlay.State.Value == Visibility.Hidden); + confirmPaused(); + } + [Test] public void TestResumeWithResumeOverlaySkipped() { diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index d3e1118625..44e2e60be7 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -239,8 +239,10 @@ namespace osu.Game.Rulesets.UI continueResume(); } + public override void CancelResume() { + // called if the user pauses while the resume overlay is open ResumeOverlay?.Hide(); } @@ -458,6 +460,9 @@ namespace osu.Game.Rulesets.UI /// <param name="continueResume">The action to run when resuming is to be completed.</param> public abstract void RequestResume(Action continueResume); + /// <summary> + /// Invoked when the user requests to pause while the resume overlay is active. + /// </summary> public abstract void CancelResume(); /// <summary> From e35931fdfc7b6c94d401ab0076ce3e80f2edffcd Mon Sep 17 00:00:00 2001 From: nwabear <iambeardaniel@gmail.com> Date: Sat, 26 Oct 2019 14:33:59 -0500 Subject: [PATCH 3638/5608] removed blank line --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 44e2e60be7..e005eea831 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -239,7 +239,6 @@ namespace osu.Game.Rulesets.UI continueResume(); } - public override void CancelResume() { // called if the user pauses while the resume overlay is open From 814b520e5e7bc41a99adbc927b7021f4c6741a6d Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sun, 27 Oct 2019 11:35:45 +0900 Subject: [PATCH 3639/5608] Avoid potential mis-cast in comparison --- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 26f7209be6..a5a4380d4a 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -204,8 +204,8 @@ namespace osu.Game.Beatmaps.Formats } public override bool EquivalentTo(ControlPoint other) => - base.EquivalentTo(other) - && CustomSampleBank == ((LegacySampleControlPoint)other).CustomSampleBank; + base.EquivalentTo(other) && other is LegacySampleControlPoint otherTyped && + CustomSampleBank == otherTyped.CustomSampleBank; } } } From 93b003eb5adf1fdb2c31a6e6af2809e2fc9e315a Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sun, 27 Oct 2019 13:31:23 +0900 Subject: [PATCH 3640/5608] Add selected row state --- .../Screens/Edit/Timing/ControlPointTable.cs | 54 +++++++++++++++++-- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index aca74d4a20..df1f6daf4e 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -15,6 +15,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Edit.Timing { @@ -58,7 +59,7 @@ namespace osu.Game.Screens.Edit.Timing foreach (var group in value) { - backgroundFlow.Add(new RowBackground { Action = () => selectedGroup.Value = group }); + backgroundFlow.Add(new RowBackground(group)); } Columns = createHeaders(); @@ -135,12 +136,17 @@ namespace osu.Game.Screens.Edit.Timing public class RowBackground : OsuClickableContainer { + private readonly ControlPointGroup controlGroup; private const int fade_duration = 100; private readonly Box hoveredBackground; - public RowBackground() + [Resolved] + private Bindable<ControlPointGroup> selectedGroup { get; set; } + + public RowBackground(ControlPointGroup controlGroup) { + this.controlGroup = controlGroup; RelativeSizeAxes = Axes.X; Height = 25; @@ -157,25 +163,63 @@ namespace osu.Game.Screens.Edit.Timing Alpha = 0, }, }; + + Action = () => selectedGroup.Value = controlGroup; } + private Color4 colourHover; + private Color4 colourSelected; + [BackgroundDependencyLoader] private void load(OsuColour colours) { - hoveredBackground.Colour = colours.Blue; + hoveredBackground.Colour = colourHover = colours.BlueDarker; + colourSelected = colours.YellowDarker; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + selectedGroup.BindValueChanged(group => { Selected = controlGroup == group.NewValue; }); + } + + private bool selected; + + protected bool Selected + { + get => selected; + set + { + if (value == selected) + return; + + selected = value; + updateState(); + } } protected override bool OnHover(HoverEvent e) { - hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); + updateState(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); + updateState(); base.OnHoverLost(e); } + + private void updateState() + { + hoveredBackground.FadeColour(selected ? colourSelected : colourHover, 450, Easing.OutQuint); + + if (selected || IsHovered) + hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); + else + hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); + } } } } From de69665a4652f2f0595bb612c3c53570348522df Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sun, 27 Oct 2019 14:17:59 +0900 Subject: [PATCH 3641/5608] Reduce horizontal spacing of attributes --- osu.Game/Screens/Edit/Timing/ControlPointTable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index df1f6daf4e..8d5774cd09 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -98,7 +98,7 @@ namespace osu.Game.Screens.Edit.Timing Direction = FillDirection.Horizontal, ChildrenEnumerable = group.ControlPoints.Select(createAttribute).Where(c => c != null), Padding = new MarginPadding(10), - Spacing = new Vector2(10) + Spacing = new Vector2(2) }, }; From 0fba272e78dc1501847d8a97c8a38a69e126b695 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sun, 27 Oct 2019 15:19:36 +0900 Subject: [PATCH 3642/5608] Add the ability to add new ControlPoint types to existing groups --- .../Visual/Editor/TestSceneTimingScreen.cs | 5 + .../ControlPoints/ControlPointGroup.cs | 6 +- .../Edit/Timing/ControlPointSettings.cs | 190 ------------------ .../Screens/Edit/Timing/ControlPointTable.cs | 64 ++++-- .../Screens/Edit/Timing/DifficultySection.cs | 37 ++++ osu.Game/Screens/Edit/Timing/EffectSection.cs | 44 ++++ osu.Game/Screens/Edit/Timing/SampleSection.cs | 44 ++++ osu.Game/Screens/Edit/Timing/Section.cs | 126 ++++++++++++ osu.Game/Screens/Edit/Timing/TimingSection.cs | 44 ++++ 9 files changed, 346 insertions(+), 214 deletions(-) create mode 100644 osu.Game/Screens/Edit/Timing/DifficultySection.cs create mode 100644 osu.Game/Screens/Edit/Timing/EffectSection.cs create mode 100644 osu.Game/Screens/Edit/Timing/SampleSection.cs create mode 100644 osu.Game/Screens/Edit/Timing/Section.cs create mode 100644 osu.Game/Screens/Edit/Timing/TimingSection.cs diff --git a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs index 3e227169e0..121853d8d0 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs @@ -17,6 +17,11 @@ namespace osu.Game.Tests.Visual.Editor { typeof(ControlPointTable), typeof(ControlPointSettings), + typeof(Section<>), + typeof(TimingSection), + typeof(EffectSection), + typeof(SampleSection), + typeof(DifficultySection), typeof(RowAttribute) }; diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs index d57baf25be..cb73ce884e 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs @@ -2,8 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; +using osu.Framework.Bindables; namespace osu.Game.Beatmaps.ControlPoints { @@ -17,9 +17,9 @@ namespace osu.Game.Beatmaps.ControlPoints /// </summary> public double Time { get; } - public IReadOnlyList<ControlPoint> ControlPoints => controlPoints; + public IBindableList<ControlPoint> ControlPoints => controlPoints; - private readonly List<ControlPoint> controlPoints = new List<ControlPoint>(); + private readonly BindableList<ControlPoint> controlPoints = new BindableList<ControlPoint>(); public ControlPointGroup(double time) { diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index 470750b860..e1182d9fa4 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -2,17 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Edit.Timing { @@ -51,190 +46,5 @@ namespace osu.Game.Screens.Edit.Timing new SampleSection(), new EffectSection(), }; - - private class TimingSection : Section<TimingControlPoint> - { - private OsuSpriteText bpm; - private OsuSpriteText timeSignature; - - [BackgroundDependencyLoader] - private void load() - { - Flow.AddRange(new[] - { - bpm = new OsuSpriteText(), - timeSignature = new OsuSpriteText(), - }); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => - { - bpm.Text = $"BPM: {point.NewValue?.BeatLength}"; - timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; - }); - } - } - - private class DifficultySection : Section<DifficultyControlPoint> - { - private OsuSpriteText multiplier; - - [BackgroundDependencyLoader] - private void load() - { - Flow.AddRange(new[] - { - multiplier = new OsuSpriteText(), - }); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier}"; }); - } - } - - private class SampleSection : Section<SampleControlPoint> - { - private OsuSpriteText bank; - private OsuSpriteText volume; - - [BackgroundDependencyLoader] - private void load() - { - Flow.AddRange(new[] - { - bank = new OsuSpriteText(), - volume = new OsuSpriteText(), - }); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => - { - bank.Text = $"Bank: {point.NewValue?.SampleBank}"; - volume.Text = $"Volume: {point.NewValue?.SampleVolume}"; - }); - } - } - - private class EffectSection : Section<EffectControlPoint> - { - private OsuSpriteText kiai; - private OsuSpriteText omitBarLine; - - [BackgroundDependencyLoader] - private void load() - { - Flow.AddRange(new[] - { - kiai = new OsuSpriteText(), - omitBarLine = new OsuSpriteText(), - }); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => - { - kiai.Text = $"Kiai: {point.NewValue?.KiaiMode}"; - omitBarLine.Text = $"Skip Bar Line: {point.NewValue?.OmitFirstBarLine}"; - }); - } - } - - private class Section<T> : CompositeDrawable - where T : ControlPoint - { - private OsuCheckbox checkbox; - private Container content; - - protected FillFlowContainer Flow { get; private set; } - - protected Bindable<T> ControlPoint { get; } = new Bindable<T>(); - - private const float header_height = 20; - - [Resolved] - private Bindable<ControlPointGroup> selectedPoints { get; set; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - RelativeSizeAxes = Axes.X; - AutoSizeDuration = 200; - AutoSizeEasing = Easing.OutQuint; - AutoSizeAxes = Axes.Y; - - Masking = true; - - InternalChildren = new Drawable[] - { - new Box - { - Colour = colours.Gray1, - RelativeSizeAxes = Axes.Both, - }, - new Container - { - RelativeSizeAxes = Axes.X, - Height = header_height, - Children = new Drawable[] - { - checkbox = new OsuCheckbox - { - LabelText = typeof(T).Name.Replace(typeof(ControlPoint).Name, string.Empty) - } - } - }, - content = new Container - { - Y = header_height, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - new Box - { - Colour = colours.Gray2, - RelativeSizeAxes = Axes.Both, - }, - Flow = new FillFlowContainer - { - Padding = new MarginPadding(10), - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - }, - } - } - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - selectedPoints.BindValueChanged(points => - { - ControlPoint.Value = points.NewValue?.ControlPoints.OfType<T>().FirstOrDefault(); - - checkbox.Current.Value = ControlPoint.Value != null; - }, true); - - checkbox.Current.BindValueChanged(selected => { content.BypassAutoSizeAxes = selected.NewValue ? Axes.None : Axes.Y; }, true); - } - } } } diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 8d5774cd09..9c11443199 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -92,35 +92,57 @@ namespace osu.Game.Screens.Edit.Timing Text = $"{group.Time:n0}ms", Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - ChildrenEnumerable = group.ControlPoints.Select(createAttribute).Where(c => c != null), - Padding = new MarginPadding(10), - Spacing = new Vector2(2) - }, + new ControlGroupAttributes(group), }; - private Drawable createAttribute(ControlPoint controlPoint) + private class ControlGroupAttributes : CompositeDrawable { - switch (controlPoint) + private readonly IBindableList<ControlPoint> controlPoints; + + private readonly FillFlowContainer fill; + + public ControlGroupAttributes(ControlPointGroup group) { - case TimingControlPoint timing: - return new RowAttribute("timing", $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); + InternalChild = fill = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Padding = new MarginPadding(10), + Spacing = new Vector2(2) + }; - case DifficultyControlPoint difficulty: + controlPoints = group.ControlPoints.GetBoundCopy(); + controlPoints.ItemsAdded += _ => createChildren(); + controlPoints.ItemsRemoved += _ => createChildren(); - return new RowAttribute("difficulty", $"{difficulty.SpeedMultiplier:n2}x"); - - case EffectControlPoint effect: - return new RowAttribute("effect", $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); - - case SampleControlPoint sample: - return new RowAttribute("sample", $"{sample.SampleBank} {sample.SampleVolume}%"); + createChildren(); } - return null; + private void createChildren() + { + fill.ChildrenEnumerable = controlPoints.Select(createAttribute).Where(c => c != null); + } + + private Drawable createAttribute(ControlPoint controlPoint) + { + switch (controlPoint) + { + case TimingControlPoint timing: + return new RowAttribute("timing", $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); + + case DifficultyControlPoint difficulty: + + return new RowAttribute("difficulty", $"{difficulty.SpeedMultiplier:n2}x"); + + case EffectControlPoint effect: + return new RowAttribute("effect", $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); + + case SampleControlPoint sample: + return new RowAttribute("sample", $"{sample.SampleBank} {sample.SampleVolume}%"); + } + + return null; + } } protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty); diff --git a/osu.Game/Screens/Edit/Timing/DifficultySection.cs b/osu.Game/Screens/Edit/Timing/DifficultySection.cs new file mode 100644 index 0000000000..150c11f5ee --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/DifficultySection.cs @@ -0,0 +1,37 @@ +using osu.Framework.Allocation; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Screens.Edit.Timing +{ + internal class DifficultySection : Section<DifficultyControlPoint> + { + private OsuSpriteText multiplier; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + multiplier = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier}"; }); + } + + protected override DifficultyControlPoint CreatePoint() + { + var reference = Beatmap.Value.Beatmap.ControlPointInfo.DifficultyPointAt(SelectedGroup.Value.Time); + + return new DifficultyControlPoint + { + SpeedMultiplier = reference.SpeedMultiplier, + }; + } + } +} diff --git a/osu.Game/Screens/Edit/Timing/EffectSection.cs b/osu.Game/Screens/Edit/Timing/EffectSection.cs new file mode 100644 index 0000000000..ff8817147a --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/EffectSection.cs @@ -0,0 +1,44 @@ +using osu.Framework.Allocation; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Screens.Edit.Timing +{ + internal class EffectSection : Section<EffectControlPoint> + { + private OsuSpriteText kiai; + private OsuSpriteText omitBarLine; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + kiai = new OsuSpriteText(), + omitBarLine = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => + { + kiai.Text = $"Kiai: {point.NewValue?.KiaiMode}"; + omitBarLine.Text = $"Skip Bar Line: {point.NewValue?.OmitFirstBarLine}"; + }); + } + + protected override EffectControlPoint CreatePoint() + { + var reference = Beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(SelectedGroup.Value.Time); + + return new EffectControlPoint + { + KiaiMode = reference.KiaiMode, + OmitFirstBarLine = reference.OmitFirstBarLine + }; + } + } +} diff --git a/osu.Game/Screens/Edit/Timing/SampleSection.cs b/osu.Game/Screens/Edit/Timing/SampleSection.cs new file mode 100644 index 0000000000..0d6bc74057 --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/SampleSection.cs @@ -0,0 +1,44 @@ +using osu.Framework.Allocation; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Screens.Edit.Timing +{ + internal class SampleSection : Section<SampleControlPoint> + { + private OsuSpriteText bank; + private OsuSpriteText volume; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + bank = new OsuSpriteText(), + volume = new OsuSpriteText(), + }); + } + + protected override SampleControlPoint CreatePoint() + { + var reference = Beatmap.Value.Beatmap.ControlPointInfo.SamplePointAt(SelectedGroup.Value.Time); + + return new SampleControlPoint + { + SampleBank = reference.SampleBank, + SampleVolume = reference.SampleVolume, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => + { + bank.Text = $"Bank: {point.NewValue?.SampleBank}"; + volume.Text = $"Volume: {point.NewValue?.SampleVolume}"; + }); + } + } +} \ No newline at end of file diff --git a/osu.Game/Screens/Edit/Timing/Section.cs b/osu.Game/Screens/Edit/Timing/Section.cs new file mode 100644 index 0000000000..c6140ff497 --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/Section.cs @@ -0,0 +1,126 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Screens.Edit.Timing +{ + internal abstract class Section<T> : CompositeDrawable + where T : ControlPoint + { + private OsuCheckbox checkbox; + private Container content; + + protected FillFlowContainer Flow { get; private set; } + + protected Bindable<T> ControlPoint { get; } = new Bindable<T>(); + + private const float header_height = 20; + + [Resolved] + protected IBindable<WorkingBeatmap> Beatmap { get; private set; } + + [Resolved] + protected Bindable<ControlPointGroup> SelectedGroup { get; private set; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + RelativeSizeAxes = Axes.X; + AutoSizeDuration = 200; + AutoSizeEasing = Easing.OutQuint; + AutoSizeAxes = Axes.Y; + + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + Colour = colours.Gray1, + RelativeSizeAxes = Axes.Both, + }, + new Container + { + RelativeSizeAxes = Axes.X, + Height = header_height, + Children = new Drawable[] + { + checkbox = new OsuCheckbox + { + LabelText = typeof(T).Name.Replace(typeof(ControlPoint).Name, string.Empty) + } + } + }, + content = new Container + { + Y = header_height, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Box + { + Colour = colours.Gray2, + RelativeSizeAxes = Axes.Both, + }, + Flow = new FillFlowContainer + { + Padding = new MarginPadding(10), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + }, + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + checkbox.Current.BindValueChanged(selected => + { + if (selected.NewValue) + { + if (SelectedGroup.Value == null) + { + checkbox.Current.Value = false; + return; + } + + if (ControlPoint.Value == null) + SelectedGroup.Value.Add(ControlPoint.Value = CreatePoint()); + } + else + { + if (ControlPoint.Value != null) + { + SelectedGroup.Value.Remove(ControlPoint.Value); + ControlPoint.Value = null; + } + } + + content.BypassAutoSizeAxes = selected.NewValue ? Axes.None : Axes.Y; + }, true); + + SelectedGroup.BindValueChanged(points => + { + ControlPoint.Value = points.NewValue?.ControlPoints.OfType<T>().FirstOrDefault(); + checkbox.Current.Value = ControlPoint.Value != null; + }, true); + } + + protected abstract T CreatePoint(); + } +} diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs new file mode 100644 index 0000000000..dcbb6f8bbf --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -0,0 +1,44 @@ +using osu.Framework.Allocation; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Screens.Edit.Timing +{ + internal class TimingSection : Section<TimingControlPoint> + { + private OsuSpriteText bpm; + private OsuSpriteText timeSignature; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + bpm = new OsuSpriteText(), + timeSignature = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => + { + bpm.Text = $"BPM: {point.NewValue?.BeatLength}"; + timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; + }); + } + + protected override TimingControlPoint CreatePoint() + { + var reference = Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(SelectedGroup.Value.Time); + + return new TimingControlPoint + { + BeatLength = reference.BeatLength, + TimeSignature = reference.TimeSignature + }; + } + } +} From 73369ae6130680101aeaf6216307b13e9b76f564 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sun, 27 Oct 2019 16:13:24 +0900 Subject: [PATCH 3643/5608] Add the ability to add/remove groups --- .../ControlPoints/ControlPointInfo.cs | 19 +++++++++++-- .../Screens/Edit/Timing/ControlPointTable.cs | 2 +- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 27 ++++++++++++++----- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index e165adedea..4f83e14eaf 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; +using osu.Framework.Bindables; using osu.Framework.Lists; namespace osu.Game.Beatmaps.ControlPoints @@ -16,9 +17,9 @@ namespace osu.Game.Beatmaps.ControlPoints /// Control point groups. /// </summary> [JsonProperty] - public IReadOnlyList<ControlPointGroup> Groups => groups; + public IBindableList<ControlPointGroup> Groups => groups; - private readonly SortedList<ControlPointGroup> groups = new SortedList<ControlPointGroup>(Comparer<ControlPointGroup>.Default); + private readonly BindableList<ControlPointGroup> groups = new BindableList<ControlPointGroup>(); /// <summary> /// All timing points. @@ -294,5 +295,19 @@ namespace osu.Game.Beatmaps.ControlPoints samplePoints.Clear(); effectPoints.Clear(); } + + public ControlPointGroup CreateGroup(double time) + { + var newGroup = new ControlPointGroup(time); + + int i = groups.BinarySearch(newGroup); + if (i < 0) i = ~i; + + groups.Insert(i, newGroup); + + return newGroup; + } + + public void RemoveGroup(ControlPointGroup group) => groups.Remove(group); } } diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 9c11443199..729e631d87 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -203,7 +203,7 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - selectedGroup.BindValueChanged(group => { Selected = controlGroup == group.NewValue; }); + selectedGroup.BindValueChanged(group => { Selected = controlGroup == group.NewValue; }, true); } private bool selected; diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index a9fd038829..2b1c8f8497 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -52,12 +52,18 @@ namespace osu.Game.Screens.Edit.Timing public class ControlPointList : CompositeDrawable { private OsuButton deleteButton; + private ControlPointTable table; + + private IBindableList<ControlPointGroup> controlGroups; + + [Resolved] + protected IFrameBasedClock EditorClock { get; private set; } [Resolved] protected IBindable<WorkingBeatmap> Beatmap { get; private set; } [Resolved] - private Bindable<ControlPointGroup> selectedPoints { get; set; } + private Bindable<ControlPointGroup> selectedGroup { get; set; } [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -74,10 +80,7 @@ namespace osu.Game.Screens.Edit.Timing new OsuScrollContainer { RelativeSizeAxes = Axes.Both, - Child = new ControlPointTable - { - ControlGroups = Beatmap.Value.Beatmap.ControlPointInfo.Groups - } + Child = table = new ControlPointTable(), }, new FillFlowContainer { @@ -114,15 +117,27 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - selectedPoints.BindValueChanged(selected => { deleteButton.Enabled.Value = selected.NewValue != null; }, true); + selectedGroup.BindValueChanged(selected => { deleteButton.Enabled.Value = selected.NewValue != null; }, true); + + controlGroups = Beatmap.Value.Beatmap.ControlPointInfo.Groups.GetBoundCopy(); + controlGroups.ItemsAdded += _ => createContent(); + controlGroups.ItemsRemoved += _ => createContent(); + createContent(); } + private void createContent() => table.ControlGroups = controlGroups; + private void delete() { + if (selectedGroup.Value == null) + return; + + Beatmap.Value.Beatmap.ControlPointInfo.RemoveGroup(selectedGroup.Value); } private void addNew() { + selectedGroup.Value = Beatmap.Value.Beatmap.ControlPointInfo.CreateGroup(EditorClock.CurrentTime); } } } From 81b5d7b79fd668463a7d1c616a66da5a77ec4dee Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sun, 27 Oct 2019 16:30:05 +0900 Subject: [PATCH 3644/5608] Select another group after deleting selected --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 2b1c8f8497..2e9164c60f 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -57,7 +58,7 @@ namespace osu.Game.Screens.Edit.Timing private IBindableList<ControlPointGroup> controlGroups; [Resolved] - protected IFrameBasedClock EditorClock { get; private set; } + private IFrameBasedClock clock { get; set; } [Resolved] protected IBindable<WorkingBeatmap> Beatmap { get; private set; } @@ -133,11 +134,13 @@ namespace osu.Game.Screens.Edit.Timing return; Beatmap.Value.Beatmap.ControlPointInfo.RemoveGroup(selectedGroup.Value); + + selectedGroup.Value = Beatmap.Value.Beatmap.ControlPointInfo.Groups.FirstOrDefault(g => g.Time >= clock.CurrentTime); } private void addNew() { - selectedGroup.Value = Beatmap.Value.Beatmap.ControlPointInfo.CreateGroup(EditorClock.CurrentTime); + selectedGroup.Value = Beatmap.Value.Beatmap.ControlPointInfo.CreateGroup(clock.CurrentTime); } } } From 0179586f7811a1d71209d61cb676a0dd856cb7d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sun, 27 Oct 2019 16:31:23 +0900 Subject: [PATCH 3645/5608] Disallow inserting a group if one already exists with the current time value --- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 4f83e14eaf..6418ef984b 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -301,9 +301,11 @@ namespace osu.Game.Beatmaps.ControlPoints var newGroup = new ControlPointGroup(time); int i = groups.BinarySearch(newGroup); - if (i < 0) i = ~i; - groups.Insert(i, newGroup); + if (i > 0) + return groups[i]; + + groups.Insert(~i, newGroup); return newGroup; } From 022cc139528eb581029d7dcf0a7935ef34d0350a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= <dach.bartlomiej@gmail.com> Date: Sun, 27 Oct 2019 22:55:46 +0100 Subject: [PATCH 3646/5608] Add beatmap carousel item sorting stability test Add visual test to ensure sorting stability when sorting criteria are applied in the beatmap carousel. --- .../SongSelect/TestSceneBeatmapCarousel.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index f87d6ebebb..8b82567a8d 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -245,6 +245,28 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert($"Check #{set_count} is at bottom", () => carousel.BeatmapSets.Last().Metadata.Title.EndsWith($"#{set_count}!")); } + [Test] + public void TestSortingStability() + { + var sets = new List<BeatmapSetInfo>(); + + for (int i = 0; i < 20; i++) + { + var set = createTestBeatmapSet(i); + set.Metadata.Artist = "same artist"; + set.Metadata.Title = "same title"; + sets.Add(set); + } + + loadBeatmaps(sets); + + AddStep("Sort by artist", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Artist }, false)); + AddAssert("Items remain in original order", () => carousel.BeatmapSets.Select((set, index) => set.ID == index).All(b => b)); + + AddStep("Sort by title", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Title }, false)); + AddAssert("Items remain in original order", () => carousel.BeatmapSets.Select((set, index) => set.ID == index).All(b => b)); + } + [Test] public void TestSortingWithFiltered() { From c8d3dd0e5a62e126eb9e2d7701aec7e731a5effb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= <dach.bartlomiej@gmail.com> Date: Sun, 27 Oct 2019 23:14:14 +0100 Subject: [PATCH 3647/5608] Make carousel item sorting stable Migrate beatmap carousel item sorting from List<T>.Sort() to IEnumerable<T>.OrderBy(), as the second variant is documented to be a stable sorting algorithm. This allows for eliminating unnecessary movement of carousel items occurring whenever any set of items is tied when changing sorting criteria. --- .../Screens/Select/Carousel/CarouselGroup.cs | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs index 09b728abeb..b32561eb88 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs @@ -1,7 +1,9 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; +using System.Linq; namespace osu.Game.Screens.Select.Carousel { @@ -81,12 +83,9 @@ namespace osu.Game.Screens.Select.Carousel { base.Filter(criteria); - var children = new List<CarouselItem>(InternalChildren); - - children.ForEach(c => c.Filter(criteria)); - children.Sort((x, y) => x.CompareTo(criteria, y)); - - InternalChildren = children; + InternalChildren.ForEach(c => c.Filter(criteria)); + // IEnumerable<T>.OrderBy() is used instead of List<T>.Sort() to ensure sorting stability + InternalChildren = InternalChildren.OrderBy(c => c, new CriteriaComparer(criteria)).ToList(); } protected virtual void ChildItemStateChanged(CarouselItem item, CarouselItemState value) @@ -104,5 +103,23 @@ namespace osu.Game.Screens.Select.Carousel State.Value = CarouselItemState.Selected; } } + + private class CriteriaComparer : IComparer<CarouselItem> + { + private readonly FilterCriteria criteria; + + public CriteriaComparer(FilterCriteria criteria) + { + this.criteria = criteria; + } + + public int Compare(CarouselItem x, CarouselItem y) + { + if (x != null && y != null) + return x.CompareTo(criteria, y); + + throw new ArgumentNullException(); + } + } } } From 29e20bc8d2796d8ac5cb3f8a53dc684ec67263d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 10:45:11 +0900 Subject: [PATCH 3648/5608] Add xmldoc and combine GroupAt / CreateGroup --- .../ControlPoints/ControlPointInfo.cs | 174 ++++++++---------- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 2 +- 2 files changed, 79 insertions(+), 97 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 6418ef984b..c3e2b469ae 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -14,7 +14,7 @@ namespace osu.Game.Beatmaps.ControlPoints public class ControlPointInfo { /// <summary> - /// Control point groups. + /// All control points grouped by time. /// </summary> [JsonProperty] public IBindableList<ControlPointGroup> Groups => groups; @@ -86,28 +86,6 @@ namespace osu.Game.Beatmaps.ControlPoints /// <returns>The timing control point.</returns> public TimingControlPoint TimingPointAt(double time) => binarySearchWithFallback(TimingPoints, time, TimingPoints.Count > 0 ? TimingPoints[0] : null); - /// <summary> - /// Finds the closest <see cref="ControlPoint"/> of the same type as <see cref="referencePoint"/> that is active at <paramref name="time"/>. - /// </summary> - /// <param name="time">The time to find the timing control point at.</param> - /// <param name="referencePoint">A reference point to infer type.</param> - /// <returns>The timing control point.</returns> - public ControlPoint SimilarPointAt(double time, ControlPoint referencePoint) - { - switch (referencePoint) - { - case TimingControlPoint _: return binarySearch(TimingPoints, time); - - case EffectControlPoint _: return binarySearch(EffectPoints, time); - - case SampleControlPoint _: return binarySearch(SamplePoints, time); - - case DifficultyControlPoint _: return binarySearch(DifficultyPoints, time); - } - - return null; - } - /// <summary> /// Finds the maximum BPM represented by any timing control point. /// </summary> @@ -129,6 +107,62 @@ namespace osu.Game.Beatmaps.ControlPoints public double BPMMode => 60000 / (TimingPoints.GroupBy(c => c.BeatLength).OrderByDescending(grp => grp.Count()).FirstOrDefault()?.FirstOrDefault() ?? new TimingControlPoint()).BeatLength; + /// <summary> + /// Remove all <see cref="ControlPointGroup"/>s and return to a pristine state. + /// </summary> + public void Clear() + { + groups.Clear(); + timingPoints.Clear(); + difficultyPoints.Clear(); + samplePoints.Clear(); + effectPoints.Clear(); + } + + /// <summary> + /// Add a new <see cref="ControlPoint"/>. Note that the provided control point may not be added if the correct state is already present at the provided time. + /// </summary> + /// <param name="time">The time at which the control point should be added.</param> + /// <param name="controlPoint">The control point to add.</param> + /// <returns>Whether the control point was added.</returns> + public bool Add(double time, ControlPoint controlPoint) + { + if (checkAlreadyExisting(time, controlPoint)) + return false; + + GroupAt(time, true).Add(controlPoint); + return true; + } + + public ControlPointGroup GroupAt(double time, bool addIfNotExisting = false) + { + var newGroup = new ControlPointGroup(time); + + int i = groups.BinarySearch(newGroup); + + if (i >= 0) + return groups[i]; + + if (addIfNotExisting) + { + newGroup.ItemAdded += groupItemAdded; + newGroup.ItemRemoved += groupItemRemoved; + + groups.Insert(~i, newGroup); + return newGroup; + } + + return null; + } + + public void RemoveGroup(ControlPointGroup group) + { + group.ItemAdded -= groupItemAdded; + group.ItemRemoved -= groupItemRemoved; + + groups.Remove(group); + } + /// <summary> /// Binary searches one of the control point lists to find the active control point at <paramref name="time"/>. /// Includes logic for returning a specific point when no matching point is found. @@ -183,33 +217,6 @@ namespace osu.Game.Beatmaps.ControlPoints return list[l - 1]; } - public void Add(double time, ControlPoint newPoint, bool force = false) - { - if (!force && checkAlreadyExisting(time, newPoint)) - return; - - GroupAt(time, true).Add(newPoint); - } - - public ControlPointGroup GroupAt(double time, bool createIfNotExisting = false) - { - var existing = Groups.FirstOrDefault(g => g.Time == time); - - if (existing != null) - return existing; - - if (createIfNotExisting) - { - var newGroup = new ControlPointGroup(time); - newGroup.ItemAdded += groupItemAdded; - newGroup.ItemRemoved += groupItemRemoved; - groups.Add(newGroup); - return newGroup; - } - - return null; - } - /// <summary> /// Check whether <see cref="newPoint"/> should be added. /// </summary> @@ -243,31 +250,9 @@ namespace osu.Game.Beatmaps.ControlPoints return existing?.EquivalentTo(newPoint) == true; } - private void groupItemRemoved(ControlPoint obj) + private void groupItemAdded(ControlPoint controlPoint) { - switch (obj) - { - case TimingControlPoint typed: - timingPoints.Remove(typed); - break; - - case EffectControlPoint typed: - effectPoints.Remove(typed); - break; - - case SampleControlPoint typed: - samplePoints.Remove(typed); - break; - - case DifficultyControlPoint typed: - difficultyPoints.Remove(typed); - break; - } - } - - private void groupItemAdded(ControlPoint obj) - { - switch (obj) + switch (controlPoint) { case TimingControlPoint typed: timingPoints.Add(typed); @@ -287,29 +272,26 @@ namespace osu.Game.Beatmaps.ControlPoints } } - public void Clear() + private void groupItemRemoved(ControlPoint controlPoint) { - groups.Clear(); - timingPoints.Clear(); - difficultyPoints.Clear(); - samplePoints.Clear(); - effectPoints.Clear(); + switch (controlPoint) + { + case TimingControlPoint typed: + timingPoints.Remove(typed); + break; + + case EffectControlPoint typed: + effectPoints.Remove(typed); + break; + + case SampleControlPoint typed: + samplePoints.Remove(typed); + break; + + case DifficultyControlPoint typed: + difficultyPoints.Remove(typed); + break; + } } - - public ControlPointGroup CreateGroup(double time) - { - var newGroup = new ControlPointGroup(time); - - int i = groups.BinarySearch(newGroup); - - if (i > 0) - return groups[i]; - - groups.Insert(~i, newGroup); - - return newGroup; - } - - public void RemoveGroup(ControlPointGroup group) => groups.Remove(group); } } diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 2e9164c60f..6ae01e056f 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -140,7 +140,7 @@ namespace osu.Game.Screens.Edit.Timing private void addNew() { - selectedGroup.Value = Beatmap.Value.Beatmap.ControlPointInfo.CreateGroup(clock.CurrentTime); + selectedGroup.Value = Beatmap.Value.Beatmap.ControlPointInfo.GroupAt(clock.CurrentTime, true); } } } From cd4b7c04e9a18668680016c9b45ee1d4c3f1976d Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 11:34:41 +0900 Subject: [PATCH 3649/5608] Add test coverage --- .../NonVisual/ControlPointInfoTest.cs | 227 ++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 osu.Game.Tests/NonVisual/ControlPointInfoTest.cs diff --git a/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs new file mode 100644 index 0000000000..a51b90851c --- /dev/null +++ b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs @@ -0,0 +1,227 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Game.Beatmaps.ControlPoints; + +namespace osu.Game.Tests.NonVisual +{ + [TestFixture] + public class ControlPointInfoTest + { + [Test] + public void TestAdd() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new TimingControlPoint()); + cpi.Add(1000, new TimingControlPoint { BeatLength = 500 }); + + Assert.That(cpi.Groups.Count, Is.EqualTo(2)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(2)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(2)); + } + + [Test] + public void TestAddRedundantTiming() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new TimingControlPoint()); // is *not* redundant, special exception for first timing point. + cpi.Add(1000, new TimingControlPoint()); // is redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); + } + + [Test] + public void TestAddRedundantDifficulty() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new DifficultyControlPoint()); // is redundant + cpi.Add(1000, new DifficultyControlPoint()); // is redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(0)); + + cpi.Add(1000, new DifficultyControlPoint { SpeedMultiplier = 2 }); // is not redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); + } + + [Test] + public void TestAddRedundantSample() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new SampleControlPoint()); // is redundant + cpi.Add(1000, new SampleControlPoint()); // is redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(0)); + + cpi.Add(1000, new SampleControlPoint { SampleVolume = 50 }); // is not redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.SamplePoints.Count, Is.EqualTo(1)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); + } + + [Test] + public void TestAddRedundantEffect() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new EffectControlPoint()); // is redundant + cpi.Add(1000, new EffectControlPoint()); // is redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(0)); + + cpi.Add(1000, new EffectControlPoint { KiaiMode = true }); // is not redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.EffectPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); + } + + [Test] + public void TestAddGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + var group2 = cpi.GroupAt(1000, true); + + Assert.That(group, Is.EqualTo(group2)); + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + } + + [Test] + public void TestGroupAtLookupOnly() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(5000, true); + Assert.That(group, Is.Not.Null); + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.GroupAt(1000), Is.Null); + Assert.That(cpi.GroupAt(5000), Is.Not.Null); + } + + [Test] + public void TestAddRemoveGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + + cpi.RemoveGroup(group); + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + } + + [Test] + public void TestAddControlPointToGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + + // usually redundant, but adding to group forces it to be added + group.Add(new DifficultyControlPoint()); + + Assert.That(group.ControlPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(1)); + } + + [Test] + public void TestAddDuplicateControlPointToGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + + group.Add(new DifficultyControlPoint()); + group.Add(new DifficultyControlPoint { SpeedMultiplier = 2 }); + + Assert.That(group.ControlPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.DifficultyPoints.First().SpeedMultiplier, Is.EqualTo(2)); + } + + [Test] + public void TestRemoveControlPointFromGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + + var difficultyPoint = new DifficultyControlPoint(); + + group.Add(difficultyPoint); + group.Remove(difficultyPoint); + + Assert.That(group.ControlPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count, Is.EqualTo(0)); + } + + [Test] + public void TestOrdering() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new TimingControlPoint()); + cpi.Add(1000, new TimingControlPoint { BeatLength = 500 }); + cpi.Add(10000, new TimingControlPoint { BeatLength = 200 }); + cpi.Add(5000, new TimingControlPoint { BeatLength = 100 }); + cpi.Add(3000, new DifficultyControlPoint { SpeedMultiplier = 2 }); + cpi.GroupAt(7000, true).Add(new DifficultyControlPoint { SpeedMultiplier = 4 }); + cpi.GroupAt(1000).Add(new SampleControlPoint { SampleVolume = 0 }); + cpi.GroupAt(8000, true).Add(new EffectControlPoint { KiaiMode = true }); + + Assert.That(cpi.AllControlPoints.Count, Is.EqualTo(8)); + + Assert.That(cpi.Groups, Is.Ordered.Ascending.By(nameof(ControlPointGroup.Time))); + + Assert.That(cpi.AllControlPoints, Is.Ordered.Ascending.By(nameof(ControlPoint.Time))); + Assert.That(cpi.TimingPoints, Is.Ordered.Ascending.By(nameof(ControlPoint.Time))); + } + + [Test] + public void TestClear() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new TimingControlPoint()); + cpi.Add(1000, new TimingControlPoint { BeatLength = 500 }); + cpi.Add(10000, new TimingControlPoint { BeatLength = 200 }); + cpi.Add(5000, new TimingControlPoint { BeatLength = 100 }); + cpi.Add(3000, new DifficultyControlPoint { SpeedMultiplier = 2 }); + cpi.GroupAt(7000, true).Add(new DifficultyControlPoint { SpeedMultiplier = 4 }); + cpi.GroupAt(1000).Add(new SampleControlPoint { SampleVolume = 0 }); + cpi.GroupAt(8000, true).Add(new EffectControlPoint { KiaiMode = true }); + + cpi.Clear(); + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count, Is.EqualTo(0)); + } + } +} From 10033239c7c38781455d25d9189c80abc28123fd Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 11:39:17 +0900 Subject: [PATCH 3650/5608] Allow binding to ControlPointGroup's ControlPoints --- osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs index d57baf25be..cb73ce884e 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs @@ -2,8 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; +using osu.Framework.Bindables; namespace osu.Game.Beatmaps.ControlPoints { @@ -17,9 +17,9 @@ namespace osu.Game.Beatmaps.ControlPoints /// </summary> public double Time { get; } - public IReadOnlyList<ControlPoint> ControlPoints => controlPoints; + public IBindableList<ControlPoint> ControlPoints => controlPoints; - private readonly List<ControlPoint> controlPoints = new List<ControlPoint>(); + private readonly BindableList<ControlPoint> controlPoints = new BindableList<ControlPoint>(); public ControlPointGroup(double time) { From 59d983b66ebb540b45ebe0c07f9fe7ccc8213da8 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 11:39:53 +0900 Subject: [PATCH 3651/5608] Allow binding to ControlPointInfo's Groups --- .../ControlPoints/ControlPointInfo.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 3927f46530..4218f9f66f 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; +using osu.Framework.Bindables; using osu.Framework.Lists; namespace osu.Game.Beatmaps.ControlPoints @@ -16,9 +17,9 @@ namespace osu.Game.Beatmaps.ControlPoints /// Control point groups. /// </summary> [JsonProperty] - public IReadOnlyList<ControlPointGroup> Groups => groups; + public IBindableList<ControlPointGroup> Groups => groups; - private readonly SortedList<ControlPointGroup> groups = new SortedList<ControlPointGroup>(Comparer<ControlPointGroup>.Default); + private readonly BindableList<ControlPointGroup> groups = new BindableList<ControlPointGroup>(); /// <summary> /// All timing points. @@ -272,5 +273,19 @@ namespace osu.Game.Beatmaps.ControlPoints samplePoints.Clear(); effectPoints.Clear(); } + + public ControlPointGroup CreateGroup(double time) + { + var newGroup = new ControlPointGroup(time); + + int i = groups.BinarySearch(newGroup); + if (i < 0) i = ~i; + + groups.Insert(i, newGroup); + + return newGroup; + } + + public void RemoveGroup(ControlPointGroup group) => groups.Remove(group); } } From 2a6b3fd67c2905540de016ae7f18ecf52bc3cc07 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Sun, 27 Oct 2019 16:31:23 +0900 Subject: [PATCH 3652/5608] Disallow inserting a group if one already exists with the current time value --- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 4218f9f66f..d9e92f1264 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -279,9 +279,11 @@ namespace osu.Game.Beatmaps.ControlPoints var newGroup = new ControlPointGroup(time); int i = groups.BinarySearch(newGroup); - if (i < 0) i = ~i; - groups.Insert(i, newGroup); + if (i > 0) + return groups[i]; + + groups.Insert(~i, newGroup); return newGroup; } From 45da22afe903a5d625f7b581354d751109a70f81 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 11:40:33 +0900 Subject: [PATCH 3653/5608] Add xmldoc and combine GroupAt / CreateGroup --- .../ControlPoints/ControlPointInfo.cs | 152 +++++++++--------- 1 file changed, 78 insertions(+), 74 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index d9e92f1264..c3e2b469ae 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -14,7 +14,7 @@ namespace osu.Game.Beatmaps.ControlPoints public class ControlPointInfo { /// <summary> - /// Control point groups. + /// All control points grouped by time. /// </summary> [JsonProperty] public IBindableList<ControlPointGroup> Groups => groups; @@ -107,6 +107,62 @@ namespace osu.Game.Beatmaps.ControlPoints public double BPMMode => 60000 / (TimingPoints.GroupBy(c => c.BeatLength).OrderByDescending(grp => grp.Count()).FirstOrDefault()?.FirstOrDefault() ?? new TimingControlPoint()).BeatLength; + /// <summary> + /// Remove all <see cref="ControlPointGroup"/>s and return to a pristine state. + /// </summary> + public void Clear() + { + groups.Clear(); + timingPoints.Clear(); + difficultyPoints.Clear(); + samplePoints.Clear(); + effectPoints.Clear(); + } + + /// <summary> + /// Add a new <see cref="ControlPoint"/>. Note that the provided control point may not be added if the correct state is already present at the provided time. + /// </summary> + /// <param name="time">The time at which the control point should be added.</param> + /// <param name="controlPoint">The control point to add.</param> + /// <returns>Whether the control point was added.</returns> + public bool Add(double time, ControlPoint controlPoint) + { + if (checkAlreadyExisting(time, controlPoint)) + return false; + + GroupAt(time, true).Add(controlPoint); + return true; + } + + public ControlPointGroup GroupAt(double time, bool addIfNotExisting = false) + { + var newGroup = new ControlPointGroup(time); + + int i = groups.BinarySearch(newGroup); + + if (i >= 0) + return groups[i]; + + if (addIfNotExisting) + { + newGroup.ItemAdded += groupItemAdded; + newGroup.ItemRemoved += groupItemRemoved; + + groups.Insert(~i, newGroup); + return newGroup; + } + + return null; + } + + public void RemoveGroup(ControlPointGroup group) + { + group.ItemAdded -= groupItemAdded; + group.ItemRemoved -= groupItemRemoved; + + groups.Remove(group); + } + /// <summary> /// Binary searches one of the control point lists to find the active control point at <paramref name="time"/>. /// Includes logic for returning a specific point when no matching point is found. @@ -161,33 +217,6 @@ namespace osu.Game.Beatmaps.ControlPoints return list[l - 1]; } - public void Add(double time, ControlPoint newPoint, bool force = false) - { - if (!force && checkAlreadyExisting(time, newPoint)) - return; - - GroupAt(time, true).Add(newPoint); - } - - public ControlPointGroup GroupAt(double time, bool createIfNotExisting = false) - { - var existing = Groups.FirstOrDefault(g => g.Time == time); - - if (existing != null) - return existing; - - if (createIfNotExisting) - { - var newGroup = new ControlPointGroup(time); - newGroup.ItemAdded += groupItemAdded; - newGroup.ItemRemoved += groupItemRemoved; - groups.Add(newGroup); - return newGroup; - } - - return null; - } - /// <summary> /// Check whether <see cref="newPoint"/> should be added. /// </summary> @@ -221,31 +250,9 @@ namespace osu.Game.Beatmaps.ControlPoints return existing?.EquivalentTo(newPoint) == true; } - private void groupItemRemoved(ControlPoint obj) + private void groupItemAdded(ControlPoint controlPoint) { - switch (obj) - { - case TimingControlPoint typed: - timingPoints.Remove(typed); - break; - - case EffectControlPoint typed: - effectPoints.Remove(typed); - break; - - case SampleControlPoint typed: - samplePoints.Remove(typed); - break; - - case DifficultyControlPoint typed: - difficultyPoints.Remove(typed); - break; - } - } - - private void groupItemAdded(ControlPoint obj) - { - switch (obj) + switch (controlPoint) { case TimingControlPoint typed: timingPoints.Add(typed); @@ -265,29 +272,26 @@ namespace osu.Game.Beatmaps.ControlPoints } } - public void Clear() + private void groupItemRemoved(ControlPoint controlPoint) { - groups.Clear(); - timingPoints.Clear(); - difficultyPoints.Clear(); - samplePoints.Clear(); - effectPoints.Clear(); + switch (controlPoint) + { + case TimingControlPoint typed: + timingPoints.Remove(typed); + break; + + case EffectControlPoint typed: + effectPoints.Remove(typed); + break; + + case SampleControlPoint typed: + samplePoints.Remove(typed); + break; + + case DifficultyControlPoint typed: + difficultyPoints.Remove(typed); + break; + } } - - public ControlPointGroup CreateGroup(double time) - { - var newGroup = new ControlPointGroup(time); - - int i = groups.BinarySearch(newGroup); - - if (i > 0) - return groups[i]; - - groups.Insert(~i, newGroup); - - return newGroup; - } - - public void RemoveGroup(ControlPointGroup group) => groups.Remove(group); } } From 4e80eda6daf5b0294c20768f7071e83d1c73a62f Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 11:34:41 +0900 Subject: [PATCH 3654/5608] Add test coverage --- .../NonVisual/ControlPointInfoTest.cs | 227 ++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 osu.Game.Tests/NonVisual/ControlPointInfoTest.cs diff --git a/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs new file mode 100644 index 0000000000..a51b90851c --- /dev/null +++ b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs @@ -0,0 +1,227 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Game.Beatmaps.ControlPoints; + +namespace osu.Game.Tests.NonVisual +{ + [TestFixture] + public class ControlPointInfoTest + { + [Test] + public void TestAdd() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new TimingControlPoint()); + cpi.Add(1000, new TimingControlPoint { BeatLength = 500 }); + + Assert.That(cpi.Groups.Count, Is.EqualTo(2)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(2)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(2)); + } + + [Test] + public void TestAddRedundantTiming() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new TimingControlPoint()); // is *not* redundant, special exception for first timing point. + cpi.Add(1000, new TimingControlPoint()); // is redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); + } + + [Test] + public void TestAddRedundantDifficulty() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new DifficultyControlPoint()); // is redundant + cpi.Add(1000, new DifficultyControlPoint()); // is redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(0)); + + cpi.Add(1000, new DifficultyControlPoint { SpeedMultiplier = 2 }); // is not redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); + } + + [Test] + public void TestAddRedundantSample() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new SampleControlPoint()); // is redundant + cpi.Add(1000, new SampleControlPoint()); // is redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(0)); + + cpi.Add(1000, new SampleControlPoint { SampleVolume = 50 }); // is not redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.SamplePoints.Count, Is.EqualTo(1)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); + } + + [Test] + public void TestAddRedundantEffect() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new EffectControlPoint()); // is redundant + cpi.Add(1000, new EffectControlPoint()); // is redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(0)); + + cpi.Add(1000, new EffectControlPoint { KiaiMode = true }); // is not redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.EffectPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); + } + + [Test] + public void TestAddGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + var group2 = cpi.GroupAt(1000, true); + + Assert.That(group, Is.EqualTo(group2)); + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + } + + [Test] + public void TestGroupAtLookupOnly() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(5000, true); + Assert.That(group, Is.Not.Null); + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.GroupAt(1000), Is.Null); + Assert.That(cpi.GroupAt(5000), Is.Not.Null); + } + + [Test] + public void TestAddRemoveGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + + cpi.RemoveGroup(group); + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + } + + [Test] + public void TestAddControlPointToGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + + // usually redundant, but adding to group forces it to be added + group.Add(new DifficultyControlPoint()); + + Assert.That(group.ControlPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(1)); + } + + [Test] + public void TestAddDuplicateControlPointToGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + + group.Add(new DifficultyControlPoint()); + group.Add(new DifficultyControlPoint { SpeedMultiplier = 2 }); + + Assert.That(group.ControlPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.DifficultyPoints.First().SpeedMultiplier, Is.EqualTo(2)); + } + + [Test] + public void TestRemoveControlPointFromGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + + var difficultyPoint = new DifficultyControlPoint(); + + group.Add(difficultyPoint); + group.Remove(difficultyPoint); + + Assert.That(group.ControlPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count, Is.EqualTo(0)); + } + + [Test] + public void TestOrdering() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new TimingControlPoint()); + cpi.Add(1000, new TimingControlPoint { BeatLength = 500 }); + cpi.Add(10000, new TimingControlPoint { BeatLength = 200 }); + cpi.Add(5000, new TimingControlPoint { BeatLength = 100 }); + cpi.Add(3000, new DifficultyControlPoint { SpeedMultiplier = 2 }); + cpi.GroupAt(7000, true).Add(new DifficultyControlPoint { SpeedMultiplier = 4 }); + cpi.GroupAt(1000).Add(new SampleControlPoint { SampleVolume = 0 }); + cpi.GroupAt(8000, true).Add(new EffectControlPoint { KiaiMode = true }); + + Assert.That(cpi.AllControlPoints.Count, Is.EqualTo(8)); + + Assert.That(cpi.Groups, Is.Ordered.Ascending.By(nameof(ControlPointGroup.Time))); + + Assert.That(cpi.AllControlPoints, Is.Ordered.Ascending.By(nameof(ControlPoint.Time))); + Assert.That(cpi.TimingPoints, Is.Ordered.Ascending.By(nameof(ControlPoint.Time))); + } + + [Test] + public void TestClear() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new TimingControlPoint()); + cpi.Add(1000, new TimingControlPoint { BeatLength = 500 }); + cpi.Add(10000, new TimingControlPoint { BeatLength = 200 }); + cpi.Add(5000, new TimingControlPoint { BeatLength = 100 }); + cpi.Add(3000, new DifficultyControlPoint { SpeedMultiplier = 2 }); + cpi.GroupAt(7000, true).Add(new DifficultyControlPoint { SpeedMultiplier = 4 }); + cpi.GroupAt(1000).Add(new SampleControlPoint { SampleVolume = 0 }); + cpi.GroupAt(8000, true).Add(new EffectControlPoint { KiaiMode = true }); + + cpi.Clear(); + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count, Is.EqualTo(0)); + } + } +} From 66b00044483f1aa1429401f59c768ce28ab1839d Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 12:02:58 +0900 Subject: [PATCH 3655/5608] Remove unused logger provider class --- osu.Game/Database/OsuDbContext.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index ea3318598f..2ae07b3cf8 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -166,19 +166,6 @@ namespace osu.Game.Database // no-op. called by tooling. } - private class OsuDbLoggerProvider : ILoggerProvider - { - #region Disposal - - public void Dispose() - { - } - - #endregion - - public ILogger CreateLogger(string categoryName) => new OsuDbLogger(); - } - private class OsuDbLogger : ILogger { public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) From 43ad4a3a3c978b4305a48576ec3769f91d7f929e Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 12:31:38 +0900 Subject: [PATCH 3656/5608] Tidy up string output --- osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs | 5 +++++ osu.Game/Screens/Edit/Timing/DifficultySection.cs | 2 +- osu.Game/Screens/Edit/Timing/EffectSection.cs | 4 ++-- osu.Game/Screens/Edit/Timing/SampleSection.cs | 4 ++-- osu.Game/Screens/Edit/Timing/TimingSection.cs | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index f8c84c79dd..e3451892bf 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -24,6 +24,11 @@ namespace osu.Game.Beatmaps.ControlPoints set => beatLength = MathHelper.Clamp(value, 6, 60000); } + /// <summary> + /// The BPM at this control point. + /// </summary> + public double BPM => 60000 / BeatLength; + private double beatLength = DEFAULT_BEAT_LENGTH; public override bool EquivalentTo(ControlPoint other) => diff --git a/osu.Game/Screens/Edit/Timing/DifficultySection.cs b/osu.Game/Screens/Edit/Timing/DifficultySection.cs index 150c11f5ee..df61300451 100644 --- a/osu.Game/Screens/Edit/Timing/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Timing/DifficultySection.cs @@ -21,7 +21,7 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier}"; }); + ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier::0.##}x"; }); } protected override DifficultyControlPoint CreatePoint() diff --git a/osu.Game/Screens/Edit/Timing/EffectSection.cs b/osu.Game/Screens/Edit/Timing/EffectSection.cs index ff8817147a..57bee44177 100644 --- a/osu.Game/Screens/Edit/Timing/EffectSection.cs +++ b/osu.Game/Screens/Edit/Timing/EffectSection.cs @@ -25,8 +25,8 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.BindValueChanged(point => { - kiai.Text = $"Kiai: {point.NewValue?.KiaiMode}"; - omitBarLine.Text = $"Skip Bar Line: {point.NewValue?.OmitFirstBarLine}"; + kiai.Text = $"Kiai: {(point.NewValue?.KiaiMode == true ? "on" : "off")}"; + omitBarLine.Text = $"Skip Bar Line: {(point.NewValue?.OmitFirstBarLine == true ? "on" : "off")}"; }); } diff --git a/osu.Game/Screens/Edit/Timing/SampleSection.cs b/osu.Game/Screens/Edit/Timing/SampleSection.cs index 0d6bc74057..d623ad08ae 100644 --- a/osu.Game/Screens/Edit/Timing/SampleSection.cs +++ b/osu.Game/Screens/Edit/Timing/SampleSection.cs @@ -37,8 +37,8 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.BindValueChanged(point => { bank.Text = $"Bank: {point.NewValue?.SampleBank}"; - volume.Text = $"Volume: {point.NewValue?.SampleVolume}"; + volume.Text = $"Volume: {point.NewValue?.SampleVolume}%"; }); } } -} \ No newline at end of file +} diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs index dcbb6f8bbf..4f2cf82a65 100644 --- a/osu.Game/Screens/Edit/Timing/TimingSection.cs +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.BindValueChanged(point => { - bpm.Text = $"BPM: {point.NewValue?.BeatLength}"; + bpm.Text = $"BPM: {point.NewValue?.BPM:0.##}"; timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; }); } From ee5591d7d502244c61ca8cb2ee515eccc9403086 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 12:42:17 +0900 Subject: [PATCH 3657/5608] Add missing license headers --- osu.Game/Screens/Edit/Timing/DifficultySection.cs | 3 +++ osu.Game/Screens/Edit/Timing/EffectSection.cs | 3 +++ osu.Game/Screens/Edit/Timing/SampleSection.cs | 3 +++ osu.Game/Screens/Edit/Timing/TimingSection.cs | 3 +++ 4 files changed, 12 insertions(+) diff --git a/osu.Game/Screens/Edit/Timing/DifficultySection.cs b/osu.Game/Screens/Edit/Timing/DifficultySection.cs index df61300451..bd363c3158 100644 --- a/osu.Game/Screens/Edit/Timing/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Timing/DifficultySection.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Framework.Allocation; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Screens/Edit/Timing/EffectSection.cs b/osu.Game/Screens/Edit/Timing/EffectSection.cs index 57bee44177..bafdfd0b0d 100644 --- a/osu.Game/Screens/Edit/Timing/EffectSection.cs +++ b/osu.Game/Screens/Edit/Timing/EffectSection.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Framework.Allocation; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Screens/Edit/Timing/SampleSection.cs b/osu.Game/Screens/Edit/Timing/SampleSection.cs index d623ad08ae..0477ad4e78 100644 --- a/osu.Game/Screens/Edit/Timing/SampleSection.cs +++ b/osu.Game/Screens/Edit/Timing/SampleSection.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Framework.Allocation; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs index 4f2cf82a65..8609da4c4d 100644 --- a/osu.Game/Screens/Edit/Timing/TimingSection.cs +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Framework.Allocation; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; From 9acdcc912924ecc83df4bddd80ff59347cdfef94 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 14:44:45 +0900 Subject: [PATCH 3658/5608] Make all control point attributes bindable Properties are left intact for compatibility reasons. --- .../ControlPoints/DifficultyControlPoint.cs | 19 +++++++---- .../ControlPoints/EffectControlPoint.cs | 26 +++++++++++++-- .../ControlPoints/SampleControlPoint.cs | 27 ++++++++++++++-- .../ControlPoints/TimingControlPoint.cs | 32 ++++++++++++++----- ...egacyDifficultyCalculatorBeatmapDecoder.cs | 6 +++- 5 files changed, 90 insertions(+), 20 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 42651fd0ca..7726eb0245 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -1,24 +1,31 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; +using osu.Framework.Bindables; namespace osu.Game.Beatmaps.ControlPoints { public class DifficultyControlPoint : ControlPoint { + /// <summary> + /// The speed multiplier at this control point. + /// </summary> + public readonly BindableDouble SpeedMultiplierBindable = new BindableDouble(1) + { + MinValue = 0.1, + MaxValue = 10 + }; + /// <summary> /// The speed multiplier at this control point. /// </summary> public double SpeedMultiplier { - get => speedMultiplier; - set => speedMultiplier = MathHelper.Clamp(value, 0.1, 10); + get => SpeedMultiplierBindable.Value; + set => SpeedMultiplierBindable.Value = value; } - private double speedMultiplier = 1; - public override bool EquivalentTo(ControlPoint other) => - other is DifficultyControlPoint otherTyped && otherTyped.SpeedMultiplier.Equals(speedMultiplier); + other is DifficultyControlPoint otherTyped && otherTyped.SpeedMultiplier.Equals(SpeedMultiplier); } } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 928f2a51ad..369b93ff3d 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -1,19 +1,39 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; + namespace osu.Game.Beatmaps.ControlPoints { public class EffectControlPoint : ControlPoint { /// <summary> - /// Whether this control point enables Kiai mode. + /// Whether the first bar line of this control point is ignored. /// </summary> - public bool KiaiMode; + public readonly BindableBool OmitFirstBarLineBindable = new BindableBool(); /// <summary> /// Whether the first bar line of this control point is ignored. /// </summary> - public bool OmitFirstBarLine; + public bool OmitFirstBarLine + { + get => OmitFirstBarLineBindable.Value; + set => OmitFirstBarLineBindable.Value = value; + } + + /// <summary> + /// Whether this control point enables Kiai mode. + /// </summary> + public readonly BindableBool KiaiModeBindable = new BindableBool(); + + /// <summary> + /// Whether this control point enables Kiai mode. + /// </summary> + public bool KiaiMode + { + get => KiaiModeBindable.Value; + set => KiaiModeBindable.Value = value; + } public override bool EquivalentTo(ControlPoint other) => other is EffectControlPoint otherTyped && diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 07f5aa6c90..37607c716e 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Game.Audio; namespace osu.Game.Beatmaps.ControlPoints @@ -12,12 +13,34 @@ namespace osu.Game.Beatmaps.ControlPoints /// <summary> /// The default sample bank at this control point. /// </summary> - public string SampleBank = DEFAULT_BANK; + public readonly Bindable<string> SampleBankBindable = new Bindable<string>(DEFAULT_BANK); + + /// <summary> + /// The speed multiplier at this control point. + /// </summary> + public string SampleBank + { + get => SampleBankBindable.Value; + set => SampleBankBindable.Value = value; + } + + /// <summary> + /// The default sample bank at this control point. + /// </summary> + public readonly BindableInt SampleVolumeBindable = new BindableInt(100) + { + MinValue = 0, + MaxValue = 100 + }; /// <summary> /// The default sample volume at this control point. /// </summary> - public int SampleVolume = 100; + public int SampleVolume + { + get => SampleVolumeBindable.Value; + set => SampleVolumeBindable.Value = value; + } /// <summary> /// Create a SampleInfo based on the sample settings in this control point. diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index f8c84c79dd..d25d08c5bd 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; +using osu.Framework.Bindables; using osu.Game.Beatmaps.Timing; namespace osu.Game.Beatmaps.ControlPoints @@ -11,23 +11,39 @@ namespace osu.Game.Beatmaps.ControlPoints /// <summary> /// The time signature at this control point. /// </summary> - public TimeSignatures TimeSignature = TimeSignatures.SimpleQuadruple; + public readonly Bindable<TimeSignatures> TimeSignatureBindable = new Bindable<TimeSignatures>(TimeSignatures.SimpleQuadruple); + + /// <summary> + /// The time signature at this control point. + /// </summary> + public TimeSignatures TimeSignature + { + get => TimeSignatureBindable.Value; + set => TimeSignatureBindable.Value = value; + } public const double DEFAULT_BEAT_LENGTH = 1000; /// <summary> /// The beat length at this control point. /// </summary> - public virtual double BeatLength + public readonly BindableDouble BeatLengthBindable = new BindableDouble(DEFAULT_BEAT_LENGTH) { - get => beatLength; - set => beatLength = MathHelper.Clamp(value, 6, 60000); - } + MinValue = 6, + MaxValue = 60000 + }; - private double beatLength = DEFAULT_BEAT_LENGTH; + /// <summary> + /// The beat length at this control point. + /// </summary> + public double BeatLength + { + get => BeatLengthBindable.Value; + set => BeatLengthBindable.Value = value; + } public override bool EquivalentTo(ControlPoint other) => other is TimingControlPoint otherTyped - && TimeSignature == otherTyped.TimeSignature && beatLength.Equals(otherTyped.beatLength); + && TimeSignature == otherTyped.TimeSignature && BeatLength.Equals(otherTyped.BeatLength); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs index 238187bf8f..a16d391b99 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs @@ -32,7 +32,11 @@ namespace osu.Game.Beatmaps.Formats private class LegacyDifficultyCalculatorControlPoint : TimingControlPoint { - public override double BeatLength { get; set; } = DEFAULT_BEAT_LENGTH; + public LegacyDifficultyCalculatorControlPoint() + { + BeatLengthBindable.MinValue = double.MinValue; + BeatLengthBindable.MaxValue = double.MaxValue; + } } } } From d33b31f0c5100850be2ae873ca46ab4fdb71fffd Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 15:33:08 +0900 Subject: [PATCH 3659/5608] Expose Current bindable in LabelledComponents Adds a `LabelledDrawable` class for usages where bindables are not present. --- .../TestSceneLabelledComponent.cs | 14 +- .../UserInterface/TestSceneLabelledTextBox.cs | 3 +- osu.Game.Tournament/Screens/SetupScreen.cs | 2 +- .../UserInterfaceV2/LabelledComponent.cs | 124 ++-------------- .../UserInterfaceV2/LabelledDrawable.cs | 132 ++++++++++++++++++ .../UserInterfaceV2/LabelledSwitchButton.cs | 2 +- .../UserInterfaceV2/LabelledTextBox.cs | 2 +- 7 files changed, 151 insertions(+), 128 deletions(-) create mode 100644 osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs index 700adad9cb..8179f92ffc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLabelledComponent : OsuTestScene + public class TestSceneLabelledDrawable : OsuTestScene { [TestCase(false)] [TestCase(true)] @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("create component", () => { - LabelledComponent<Drawable> component; + LabelledDrawable<Drawable> component; Child = new Container { @@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual.UserInterface Origin = Anchor.Centre, Width = 500, AutoSizeAxes = Axes.Y, - Child = component = padded ? (LabelledComponent<Drawable>)new PaddedLabelledComponent() : new NonPaddedLabelledComponent(), + Child = component = padded ? (LabelledDrawable<Drawable>)new PaddedLabelledDrawable() : new NonPaddedLabelledDrawable(), }; component.Label = "a sample component"; @@ -41,9 +41,9 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private class PaddedLabelledComponent : LabelledComponent<Drawable> + private class PaddedLabelledDrawable : LabelledDrawable<Drawable> { - public PaddedLabelledComponent() + public PaddedLabelledDrawable() : base(true) { } @@ -57,9 +57,9 @@ namespace osu.Game.Tests.Visual.UserInterface }; } - private class NonPaddedLabelledComponent : LabelledComponent<Drawable> + private class NonPaddedLabelledDrawable : LabelledDrawable<Drawable> { - public NonPaddedLabelledComponent() + public NonPaddedLabelledDrawable() : base(false) { } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs index 53a2bfabbc..8208b55952 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs @@ -7,7 +7,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Tests.Visual.UserInterface @@ -28,7 +27,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("create component", () => { - LabelledComponent<OsuTextBox> component; + LabelledTextBox component; Child = new Container { diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 091a837745..a67daa2756 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -89,7 +89,7 @@ namespace osu.Game.Tournament.Screens }; } - private class ActionableInfo : LabelledComponent<Drawable> + private class ActionableInfo : LabelledDrawable<Drawable> { private OsuButton button; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs index 2e659825b7..1819b36667 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs @@ -1,132 +1,24 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics.Containers; -using osuTK; +using osu.Framework.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public abstract class LabelledComponent<T> : CompositeDrawable - where T : Drawable + public abstract class LabelledComponent<T, U> : LabelledDrawable<T>, IHasCurrentValue<U> + where T : Drawable, IHasCurrentValue<U> { - protected const float CONTENT_PADDING_VERTICAL = 10; - protected const float CONTENT_PADDING_HORIZONTAL = 15; - protected const float CORNER_RADIUS = 15; - - /// <summary> - /// The component that is being displayed. - /// </summary> - protected readonly T Component; - - private readonly OsuTextFlowContainer labelText; - private readonly OsuTextFlowContainer descriptionText; - - /// <summary> - /// Creates a new <see cref="LabelledComponent{T}"/>. - /// </summary> - /// <param name="padded">Whether the component should be padded or should be expanded to the bounds of this <see cref="LabelledComponent{T}"/>.</param> protected LabelledComponent(bool padded) + : base(padded) { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - CornerRadius = CORNER_RADIUS; - Masking = true; - - InternalChildren = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("1c2125"), - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Padding = padded - ? new MarginPadding { Horizontal = CONTENT_PADDING_HORIZONTAL, Vertical = CONTENT_PADDING_VERTICAL } - : new MarginPadding { Left = CONTENT_PADDING_HORIZONTAL }, - Spacing = new Vector2(0, 12), - Children = new Drawable[] - { - new GridContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Content = new[] - { - new Drawable[] - { - labelText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Bold)) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 20 } - }, - new Container - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = Component = CreateComponent().With(d => - { - d.Anchor = Anchor.CentreRight; - d.Origin = Anchor.CentreRight; - }) - } - }, - }, - RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, - ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } - }, - descriptionText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold, italics: true)) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Bottom = padded ? 0 : CONTENT_PADDING_VERTICAL }, - Alpha = 0, - } - } - } - }; } - [BackgroundDependencyLoader] - private void load(OsuColour osuColour) + public Bindable<U> Current { - descriptionText.Colour = osuColour.Yellow; + get => Component.Current; + set => Component.Current = value; } - - public string Label - { - set => labelText.Text = value; - } - - public string Description - { - set - { - descriptionText.Text = value; - - if (!string.IsNullOrEmpty(value)) - descriptionText.Show(); - else - descriptionText.Hide(); - } - } - - /// <summary> - /// Creates the component that should be displayed. - /// </summary> - /// <returns>The component.</returns> - protected abstract T CreateComponent(); } } diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs new file mode 100644 index 0000000000..f44bd72aee --- /dev/null +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs @@ -0,0 +1,132 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Containers; +using osuTK; + +namespace osu.Game.Graphics.UserInterfaceV2 +{ + public abstract class LabelledDrawable<T> : CompositeDrawable + where T : Drawable + { + protected const float CONTENT_PADDING_VERTICAL = 10; + protected const float CONTENT_PADDING_HORIZONTAL = 15; + protected const float CORNER_RADIUS = 15; + + /// <summary> + /// The component that is being displayed. + /// </summary> + protected readonly T Component; + + private readonly OsuTextFlowContainer labelText; + private readonly OsuTextFlowContainer descriptionText; + + /// <summary> + /// Creates a new <see cref="LabelledComponent{T, U}"/>. + /// </summary> + /// <param name="padded">Whether the component should be padded or should be expanded to the bounds of this <see cref="LabelledComponent{T, U}"/>.</param> + protected LabelledDrawable(bool padded) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + CornerRadius = CORNER_RADIUS; + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex("1c2125"), + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = padded + ? new MarginPadding { Horizontal = CONTENT_PADDING_HORIZONTAL, Vertical = CONTENT_PADDING_VERTICAL } + : new MarginPadding { Left = CONTENT_PADDING_HORIZONTAL }, + Spacing = new Vector2(0, 12), + Children = new Drawable[] + { + new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Content = new[] + { + new Drawable[] + { + labelText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Bold)) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 20 } + }, + new Container + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = Component = CreateComponent().With(d => + { + d.Anchor = Anchor.CentreRight; + d.Origin = Anchor.CentreRight; + }) + } + }, + }, + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } + }, + descriptionText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold, italics: true)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Bottom = padded ? 0 : CONTENT_PADDING_VERTICAL }, + Alpha = 0, + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour osuColour) + { + descriptionText.Colour = osuColour.Yellow; + } + + public string Label + { + set => labelText.Text = value; + } + + public string Description + { + set + { + descriptionText.Text = value; + + if (!string.IsNullOrEmpty(value)) + descriptionText.Show(); + else + descriptionText.Hide(); + } + } + + /// <summary> + /// Creates the component that should be displayed. + /// </summary> + /// <returns>The component.</returns> + protected abstract T CreateComponent(); + } +} diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs index c973f1d13e..c374d80830 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs @@ -3,7 +3,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { - public class LabelledSwitchButton : LabelledComponent<SwitchButton> + public class LabelledSwitchButton : LabelledComponent<SwitchButton, bool> { public LabelledSwitchButton() : base(true) diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs index 50d2a14482..2cbe095d0b 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public class LabelledTextBox : LabelledComponent<OsuTextBox> + public class LabelledTextBox : LabelledComponent<OsuTextBox, string> { public event TextBox.OnCommitHandler OnCommit; From 0a11cbf656aef28930ad01e1306ed907958d1832 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 16:20:33 +0900 Subject: [PATCH 3660/5608] Make OsuButton correctly block hover events --- osu.Game/Graphics/UserInterface/OsuButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index c1810800a0..4124d2ad58 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -59,7 +59,7 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(HoverEvent e) { hover.FadeIn(200); - return base.OnHover(e); + return true; } protected override void OnHoverLost(HoverLostEvent e) From 9c3e54909ca56882d230d4b4ebbd39d36fda96bb Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 16:20:54 +0900 Subject: [PATCH 3661/5608] Ensure tooltips of RowAttributes are up-to-date --- osu.Game/Screens/Edit/Timing/ControlPointTable.cs | 8 ++++---- osu.Game/Screens/Edit/Timing/RowAttribute.cs | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 729e631d87..96e3ab48f2 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -128,17 +128,17 @@ namespace osu.Game.Screens.Edit.Timing switch (controlPoint) { case TimingControlPoint timing: - return new RowAttribute("timing", $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); + return new RowAttribute("timing", () => $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); case DifficultyControlPoint difficulty: - return new RowAttribute("difficulty", $"{difficulty.SpeedMultiplier:n2}x"); + return new RowAttribute("difficulty", () => $"{difficulty.SpeedMultiplier:n2}x"); case EffectControlPoint effect: - return new RowAttribute("effect", $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); + return new RowAttribute("effect", () => $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); case SampleControlPoint sample: - return new RowAttribute("sample", $"{sample.SampleBank} {sample.SampleVolume}%"); + return new RowAttribute("sample", () => $"{sample.SampleBank} {sample.SampleVolume}%"); } return null; diff --git a/osu.Game/Screens/Edit/Timing/RowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttribute.cs index 8716382142..be8f693683 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttribute.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttribute.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -14,9 +15,9 @@ namespace osu.Game.Screens.Edit.Timing public class RowAttribute : CompositeDrawable, IHasTooltip { private readonly string header; - private readonly string content; + private readonly Func<string> content; - public RowAttribute(string header, string content) + public RowAttribute(string header, Func<string> content) { this.header = header; this.content = content; @@ -54,6 +55,6 @@ namespace osu.Game.Screens.Edit.Timing }; } - public string TooltipText => content; + public string TooltipText => content(); } } From f761eddec754ef130297d12b4e383e9988d55de2 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 16:21:14 +0900 Subject: [PATCH 3662/5608] Add default bindable values --- osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs | 2 ++ osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs | 5 +++-- osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 7726eb0245..8b21098a51 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -12,6 +12,8 @@ namespace osu.Game.Beatmaps.ControlPoints /// </summary> public readonly BindableDouble SpeedMultiplierBindable = new BindableDouble(1) { + Precision = 0.1, + Default = 1, MinValue = 0.1, MaxValue = 10 }; diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 37607c716e..42865c686c 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -13,7 +13,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// <summary> /// The default sample bank at this control point. /// </summary> - public readonly Bindable<string> SampleBankBindable = new Bindable<string>(DEFAULT_BANK); + public readonly Bindable<string> SampleBankBindable = new Bindable<string>(DEFAULT_BANK) { Default = DEFAULT_BANK }; /// <summary> /// The speed multiplier at this control point. @@ -30,7 +30,8 @@ namespace osu.Game.Beatmaps.ControlPoints public readonly BindableInt SampleVolumeBindable = new BindableInt(100) { MinValue = 0, - MaxValue = 100 + MaxValue = 100, + Default = 100 }; /// <summary> diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index fb548e60aa..51b3377394 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// <summary> /// The time signature at this control point. /// </summary> - public readonly Bindable<TimeSignatures> TimeSignatureBindable = new Bindable<TimeSignatures>(TimeSignatures.SimpleQuadruple); + public readonly Bindable<TimeSignatures> TimeSignatureBindable = new Bindable<TimeSignatures>(TimeSignatures.SimpleQuadruple) { Default = TimeSignatures.SimpleQuadruple }; /// <summary> /// The time signature at this control point. @@ -29,6 +29,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// </summary> public readonly BindableDouble BeatLengthBindable = new BindableDouble(DEFAULT_BEAT_LENGTH) { + Default = DEFAULT_BEAT_LENGTH, MinValue = 6, MaxValue = 60000 }; From 522572eacefefa13ae0f4524402984ce141932f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 16:21:31 +0900 Subject: [PATCH 3663/5608] Add ability to adjust all control point attributes --- .../Screens/Edit/Timing/DifficultySection.cs | 20 +++++-- osu.Game/Screens/Edit/Timing/EffectSection.cs | 17 +++--- osu.Game/Screens/Edit/Timing/SampleSection.cs | 28 ++++++--- osu.Game/Screens/Edit/Timing/TimingSection.cs | 59 ++++++++++++++++--- 4 files changed, 97 insertions(+), 27 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/DifficultySection.cs b/osu.Game/Screens/Edit/Timing/DifficultySection.cs index bd363c3158..d3e1b2a84f 100644 --- a/osu.Game/Screens/Edit/Timing/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Timing/DifficultySection.cs @@ -2,21 +2,27 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Edit.Timing { internal class DifficultySection : Section<DifficultyControlPoint> { - private OsuSpriteText multiplier; + private SettingsSlider<double> multiplier; [BackgroundDependencyLoader] private void load() { Flow.AddRange(new[] { - multiplier = new OsuSpriteText(), + multiplier = new SettingsSlider<double> + { + LabelText = "Speed Multiplier", + Bindable = new DifficultyControlPoint().SpeedMultiplierBindable, + RelativeSizeAxes = Axes.X, + } }); } @@ -24,7 +30,13 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier::0.##}x"; }); + ControlPoint.BindValueChanged(point => + { + if (point.NewValue != null) + { + multiplier.Bindable = point.NewValue.SpeedMultiplierBindable; + } + }, true); } protected override DifficultyControlPoint CreatePoint() diff --git a/osu.Game/Screens/Edit/Timing/EffectSection.cs b/osu.Game/Screens/Edit/Timing/EffectSection.cs index bafdfd0b0d..fcd733cf00 100644 --- a/osu.Game/Screens/Edit/Timing/EffectSection.cs +++ b/osu.Game/Screens/Edit/Timing/EffectSection.cs @@ -3,22 +3,22 @@ using osu.Framework.Allocation; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Screens.Edit.Timing { internal class EffectSection : Section<EffectControlPoint> { - private OsuSpriteText kiai; - private OsuSpriteText omitBarLine; + private LabelledSwitchButton kiai; + private LabelledSwitchButton omitBarLine; [BackgroundDependencyLoader] private void load() { Flow.AddRange(new[] { - kiai = new OsuSpriteText(), - omitBarLine = new OsuSpriteText(), + kiai = new LabelledSwitchButton { Label = "Kiai Time" }, + omitBarLine = new LabelledSwitchButton { Label = "Skip Bar Line" }, }); } @@ -28,8 +28,11 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.BindValueChanged(point => { - kiai.Text = $"Kiai: {(point.NewValue?.KiaiMode == true ? "on" : "off")}"; - omitBarLine.Text = $"Skip Bar Line: {(point.NewValue?.OmitFirstBarLine == true ? "on" : "off")}"; + if (point.NewValue != null) + { + kiai.Current = point.NewValue.KiaiModeBindable; + omitBarLine.Current = point.NewValue.OmitFirstBarLineBindable; + } }); } diff --git a/osu.Game/Screens/Edit/Timing/SampleSection.cs b/osu.Game/Screens/Edit/Timing/SampleSection.cs index 0477ad4e78..816f90d19e 100644 --- a/osu.Game/Screens/Edit/Timing/SampleSection.cs +++ b/osu.Game/Screens/Edit/Timing/SampleSection.cs @@ -2,23 +2,32 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Edit.Timing { internal class SampleSection : Section<SampleControlPoint> { - private OsuSpriteText bank; - private OsuSpriteText volume; + private LabelledTextBox bank; + private SettingsSlider<int> volume; [BackgroundDependencyLoader] private void load() { - Flow.AddRange(new[] + Flow.AddRange(new Drawable[] { - bank = new OsuSpriteText(), - volume = new OsuSpriteText(), + bank = new LabelledTextBox + { + Label = "Bank Name", + }, + volume = new SettingsSlider<int> + { + Bindable = new SampleControlPoint().SampleVolumeBindable, + LabelText = "Volume", + } }); } @@ -39,8 +48,11 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.BindValueChanged(point => { - bank.Text = $"Bank: {point.NewValue?.SampleBank}"; - volume.Text = $"Volume: {point.NewValue?.SampleVolume}%"; + if (point.NewValue != null) + { + bank.Current = point.NewValue.SampleBankBindable; + volume.Bindable = point.NewValue.SampleVolumeBindable; + } }); } } diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs index 8609da4c4d..9aecbe9160 100644 --- a/osu.Game/Screens/Edit/Timing/TimingSection.cs +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -2,23 +2,33 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Graphics.Sprites; +using osu.Game.Beatmaps.Timing; +using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Edit.Timing { internal class TimingSection : Section<TimingControlPoint> { - private OsuSpriteText bpm; - private OsuSpriteText timeSignature; + private SettingsSlider<double> bpm; + private SettingsEnumDropdown<TimeSignatures> timeSignature; [BackgroundDependencyLoader] private void load() { - Flow.AddRange(new[] + Flow.AddRange(new Drawable[] { - bpm = new OsuSpriteText(), - timeSignature = new OsuSpriteText(), + bpm = new BPMSlider + { + Bindable = new TimingControlPoint().BeatLengthBindable, + LabelText = "BPM", + }, + timeSignature = new SettingsEnumDropdown<TimeSignatures> + { + LabelText = "Time Signature" + }, }); } @@ -28,8 +38,11 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.BindValueChanged(point => { - bpm.Text = $"BPM: {point.NewValue?.BPM:0.##}"; - timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; + if (point.NewValue != null) + { + bpm.Bindable = point.NewValue.BeatLengthBindable; + timeSignature.Bindable = point.NewValue.TimeSignatureBindable; + } }); } @@ -43,5 +56,35 @@ namespace osu.Game.Screens.Edit.Timing TimeSignature = reference.TimeSignature }; } + + private class BPMSlider : SettingsSlider<double> + { + private readonly BindableDouble beatLengthBindable = new BindableDouble(); + + private BindableDouble bpmBindable; + + public override Bindable<double> Bindable + { + get => base.Bindable; + set + { + // incoming will be beatlength + + beatLengthBindable.UnbindBindings(); + beatLengthBindable.BindTo(value); + + base.Bindable = bpmBindable = new BindableDouble(beatLengthToBpm(beatLengthBindable.Value)) + { + MinValue = beatLengthToBpm(beatLengthBindable.MaxValue), + MaxValue = beatLengthToBpm(beatLengthBindable.MinValue), + Default = beatLengthToBpm(beatLengthBindable.Default), + }; + + bpmBindable.BindValueChanged(bpm => beatLengthBindable.Value = beatLengthToBpm(bpm.NewValue)); + } + } + + private double beatLengthToBpm(double beatLength) => 60000 / beatLength; + } } } From 8f87957c7089fb731aa28063486b356ee031cb75 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 14:44:45 +0900 Subject: [PATCH 3664/5608] Make all control point attributes bindable Properties are left intact for compatibility reasons. --- .../ControlPoints/DifficultyControlPoint.cs | 19 +++++++---- .../ControlPoints/EffectControlPoint.cs | 26 +++++++++++++-- .../ControlPoints/SampleControlPoint.cs | 27 ++++++++++++++-- .../ControlPoints/TimingControlPoint.cs | 32 ++++++++++++++----- ...egacyDifficultyCalculatorBeatmapDecoder.cs | 6 +++- 5 files changed, 90 insertions(+), 20 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 42651fd0ca..7726eb0245 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -1,24 +1,31 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; +using osu.Framework.Bindables; namespace osu.Game.Beatmaps.ControlPoints { public class DifficultyControlPoint : ControlPoint { + /// <summary> + /// The speed multiplier at this control point. + /// </summary> + public readonly BindableDouble SpeedMultiplierBindable = new BindableDouble(1) + { + MinValue = 0.1, + MaxValue = 10 + }; + /// <summary> /// The speed multiplier at this control point. /// </summary> public double SpeedMultiplier { - get => speedMultiplier; - set => speedMultiplier = MathHelper.Clamp(value, 0.1, 10); + get => SpeedMultiplierBindable.Value; + set => SpeedMultiplierBindable.Value = value; } - private double speedMultiplier = 1; - public override bool EquivalentTo(ControlPoint other) => - other is DifficultyControlPoint otherTyped && otherTyped.SpeedMultiplier.Equals(speedMultiplier); + other is DifficultyControlPoint otherTyped && otherTyped.SpeedMultiplier.Equals(SpeedMultiplier); } } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 928f2a51ad..369b93ff3d 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -1,19 +1,39 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; + namespace osu.Game.Beatmaps.ControlPoints { public class EffectControlPoint : ControlPoint { /// <summary> - /// Whether this control point enables Kiai mode. + /// Whether the first bar line of this control point is ignored. /// </summary> - public bool KiaiMode; + public readonly BindableBool OmitFirstBarLineBindable = new BindableBool(); /// <summary> /// Whether the first bar line of this control point is ignored. /// </summary> - public bool OmitFirstBarLine; + public bool OmitFirstBarLine + { + get => OmitFirstBarLineBindable.Value; + set => OmitFirstBarLineBindable.Value = value; + } + + /// <summary> + /// Whether this control point enables Kiai mode. + /// </summary> + public readonly BindableBool KiaiModeBindable = new BindableBool(); + + /// <summary> + /// Whether this control point enables Kiai mode. + /// </summary> + public bool KiaiMode + { + get => KiaiModeBindable.Value; + set => KiaiModeBindable.Value = value; + } public override bool EquivalentTo(ControlPoint other) => other is EffectControlPoint otherTyped && diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 07f5aa6c90..37607c716e 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Game.Audio; namespace osu.Game.Beatmaps.ControlPoints @@ -12,12 +13,34 @@ namespace osu.Game.Beatmaps.ControlPoints /// <summary> /// The default sample bank at this control point. /// </summary> - public string SampleBank = DEFAULT_BANK; + public readonly Bindable<string> SampleBankBindable = new Bindable<string>(DEFAULT_BANK); + + /// <summary> + /// The speed multiplier at this control point. + /// </summary> + public string SampleBank + { + get => SampleBankBindable.Value; + set => SampleBankBindable.Value = value; + } + + /// <summary> + /// The default sample bank at this control point. + /// </summary> + public readonly BindableInt SampleVolumeBindable = new BindableInt(100) + { + MinValue = 0, + MaxValue = 100 + }; /// <summary> /// The default sample volume at this control point. /// </summary> - public int SampleVolume = 100; + public int SampleVolume + { + get => SampleVolumeBindable.Value; + set => SampleVolumeBindable.Value = value; + } /// <summary> /// Create a SampleInfo based on the sample settings in this control point. diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index f8c84c79dd..d25d08c5bd 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; +using osu.Framework.Bindables; using osu.Game.Beatmaps.Timing; namespace osu.Game.Beatmaps.ControlPoints @@ -11,23 +11,39 @@ namespace osu.Game.Beatmaps.ControlPoints /// <summary> /// The time signature at this control point. /// </summary> - public TimeSignatures TimeSignature = TimeSignatures.SimpleQuadruple; + public readonly Bindable<TimeSignatures> TimeSignatureBindable = new Bindable<TimeSignatures>(TimeSignatures.SimpleQuadruple); + + /// <summary> + /// The time signature at this control point. + /// </summary> + public TimeSignatures TimeSignature + { + get => TimeSignatureBindable.Value; + set => TimeSignatureBindable.Value = value; + } public const double DEFAULT_BEAT_LENGTH = 1000; /// <summary> /// The beat length at this control point. /// </summary> - public virtual double BeatLength + public readonly BindableDouble BeatLengthBindable = new BindableDouble(DEFAULT_BEAT_LENGTH) { - get => beatLength; - set => beatLength = MathHelper.Clamp(value, 6, 60000); - } + MinValue = 6, + MaxValue = 60000 + }; - private double beatLength = DEFAULT_BEAT_LENGTH; + /// <summary> + /// The beat length at this control point. + /// </summary> + public double BeatLength + { + get => BeatLengthBindable.Value; + set => BeatLengthBindable.Value = value; + } public override bool EquivalentTo(ControlPoint other) => other is TimingControlPoint otherTyped - && TimeSignature == otherTyped.TimeSignature && beatLength.Equals(otherTyped.beatLength); + && TimeSignature == otherTyped.TimeSignature && BeatLength.Equals(otherTyped.BeatLength); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs index 238187bf8f..a16d391b99 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs @@ -32,7 +32,11 @@ namespace osu.Game.Beatmaps.Formats private class LegacyDifficultyCalculatorControlPoint : TimingControlPoint { - public override double BeatLength { get; set; } = DEFAULT_BEAT_LENGTH; + public LegacyDifficultyCalculatorControlPoint() + { + BeatLengthBindable.MinValue = double.MinValue; + BeatLengthBindable.MaxValue = double.MaxValue; + } } } } From 090881cf6f742637e7b2546fab04853bd3df048b Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 16:21:14 +0900 Subject: [PATCH 3665/5608] Add default bindable values --- osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs | 2 ++ osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs | 5 +++-- osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 7726eb0245..8b21098a51 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -12,6 +12,8 @@ namespace osu.Game.Beatmaps.ControlPoints /// </summary> public readonly BindableDouble SpeedMultiplierBindable = new BindableDouble(1) { + Precision = 0.1, + Default = 1, MinValue = 0.1, MaxValue = 10 }; diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 37607c716e..42865c686c 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -13,7 +13,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// <summary> /// The default sample bank at this control point. /// </summary> - public readonly Bindable<string> SampleBankBindable = new Bindable<string>(DEFAULT_BANK); + public readonly Bindable<string> SampleBankBindable = new Bindable<string>(DEFAULT_BANK) { Default = DEFAULT_BANK }; /// <summary> /// The speed multiplier at this control point. @@ -30,7 +30,8 @@ namespace osu.Game.Beatmaps.ControlPoints public readonly BindableInt SampleVolumeBindable = new BindableInt(100) { MinValue = 0, - MaxValue = 100 + MaxValue = 100, + Default = 100 }; /// <summary> diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index d25d08c5bd..c00b04b660 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// <summary> /// The time signature at this control point. /// </summary> - public readonly Bindable<TimeSignatures> TimeSignatureBindable = new Bindable<TimeSignatures>(TimeSignatures.SimpleQuadruple); + public readonly Bindable<TimeSignatures> TimeSignatureBindable = new Bindable<TimeSignatures>(TimeSignatures.SimpleQuadruple) { Default = TimeSignatures.SimpleQuadruple }; /// <summary> /// The time signature at this control point. @@ -29,6 +29,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// </summary> public readonly BindableDouble BeatLengthBindable = new BindableDouble(DEFAULT_BEAT_LENGTH) { + Default = DEFAULT_BEAT_LENGTH, MinValue = 6, MaxValue = 60000 }; From 6980f488dcab3baed2acf980471a512e6e07c448 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 16:20:33 +0900 Subject: [PATCH 3666/5608] Make OsuButton correctly block hover events --- osu.Game/Graphics/UserInterface/OsuButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index c1810800a0..4124d2ad58 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -59,7 +59,7 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(HoverEvent e) { hover.FadeIn(200); - return base.OnHover(e); + return true; } protected override void OnHoverLost(HoverLostEvent e) From 08040adfad386e5e0f7a916f86f0d35ec971a0ae Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 15:33:08 +0900 Subject: [PATCH 3667/5608] Expose Current bindable in LabelledComponents Adds a `LabelledDrawable` class for usages where bindables are not present. --- .../TestSceneLabelledComponent.cs | 14 +- .../UserInterface/TestSceneLabelledTextBox.cs | 3 +- osu.Game.Tournament/Screens/SetupScreen.cs | 2 +- .../UserInterfaceV2/LabelledComponent.cs | 124 ++-------------- .../UserInterfaceV2/LabelledDrawable.cs | 132 ++++++++++++++++++ .../UserInterfaceV2/LabelledSwitchButton.cs | 2 +- .../UserInterfaceV2/LabelledTextBox.cs | 2 +- 7 files changed, 151 insertions(+), 128 deletions(-) create mode 100644 osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs index 700adad9cb..8179f92ffc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLabelledComponent : OsuTestScene + public class TestSceneLabelledDrawable : OsuTestScene { [TestCase(false)] [TestCase(true)] @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("create component", () => { - LabelledComponent<Drawable> component; + LabelledDrawable<Drawable> component; Child = new Container { @@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual.UserInterface Origin = Anchor.Centre, Width = 500, AutoSizeAxes = Axes.Y, - Child = component = padded ? (LabelledComponent<Drawable>)new PaddedLabelledComponent() : new NonPaddedLabelledComponent(), + Child = component = padded ? (LabelledDrawable<Drawable>)new PaddedLabelledDrawable() : new NonPaddedLabelledDrawable(), }; component.Label = "a sample component"; @@ -41,9 +41,9 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private class PaddedLabelledComponent : LabelledComponent<Drawable> + private class PaddedLabelledDrawable : LabelledDrawable<Drawable> { - public PaddedLabelledComponent() + public PaddedLabelledDrawable() : base(true) { } @@ -57,9 +57,9 @@ namespace osu.Game.Tests.Visual.UserInterface }; } - private class NonPaddedLabelledComponent : LabelledComponent<Drawable> + private class NonPaddedLabelledDrawable : LabelledDrawable<Drawable> { - public NonPaddedLabelledComponent() + public NonPaddedLabelledDrawable() : base(false) { } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs index 53a2bfabbc..8208b55952 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs @@ -7,7 +7,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Tests.Visual.UserInterface @@ -28,7 +27,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("create component", () => { - LabelledComponent<OsuTextBox> component; + LabelledTextBox component; Child = new Container { diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 091a837745..a67daa2756 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -89,7 +89,7 @@ namespace osu.Game.Tournament.Screens }; } - private class ActionableInfo : LabelledComponent<Drawable> + private class ActionableInfo : LabelledDrawable<Drawable> { private OsuButton button; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs index 2e659825b7..1819b36667 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs @@ -1,132 +1,24 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics.Containers; -using osuTK; +using osu.Framework.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public abstract class LabelledComponent<T> : CompositeDrawable - where T : Drawable + public abstract class LabelledComponent<T, U> : LabelledDrawable<T>, IHasCurrentValue<U> + where T : Drawable, IHasCurrentValue<U> { - protected const float CONTENT_PADDING_VERTICAL = 10; - protected const float CONTENT_PADDING_HORIZONTAL = 15; - protected const float CORNER_RADIUS = 15; - - /// <summary> - /// The component that is being displayed. - /// </summary> - protected readonly T Component; - - private readonly OsuTextFlowContainer labelText; - private readonly OsuTextFlowContainer descriptionText; - - /// <summary> - /// Creates a new <see cref="LabelledComponent{T}"/>. - /// </summary> - /// <param name="padded">Whether the component should be padded or should be expanded to the bounds of this <see cref="LabelledComponent{T}"/>.</param> protected LabelledComponent(bool padded) + : base(padded) { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - CornerRadius = CORNER_RADIUS; - Masking = true; - - InternalChildren = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("1c2125"), - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Padding = padded - ? new MarginPadding { Horizontal = CONTENT_PADDING_HORIZONTAL, Vertical = CONTENT_PADDING_VERTICAL } - : new MarginPadding { Left = CONTENT_PADDING_HORIZONTAL }, - Spacing = new Vector2(0, 12), - Children = new Drawable[] - { - new GridContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Content = new[] - { - new Drawable[] - { - labelText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Bold)) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 20 } - }, - new Container - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = Component = CreateComponent().With(d => - { - d.Anchor = Anchor.CentreRight; - d.Origin = Anchor.CentreRight; - }) - } - }, - }, - RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, - ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } - }, - descriptionText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold, italics: true)) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Bottom = padded ? 0 : CONTENT_PADDING_VERTICAL }, - Alpha = 0, - } - } - } - }; } - [BackgroundDependencyLoader] - private void load(OsuColour osuColour) + public Bindable<U> Current { - descriptionText.Colour = osuColour.Yellow; + get => Component.Current; + set => Component.Current = value; } - - public string Label - { - set => labelText.Text = value; - } - - public string Description - { - set - { - descriptionText.Text = value; - - if (!string.IsNullOrEmpty(value)) - descriptionText.Show(); - else - descriptionText.Hide(); - } - } - - /// <summary> - /// Creates the component that should be displayed. - /// </summary> - /// <returns>The component.</returns> - protected abstract T CreateComponent(); } } diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs new file mode 100644 index 0000000000..f44bd72aee --- /dev/null +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs @@ -0,0 +1,132 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Containers; +using osuTK; + +namespace osu.Game.Graphics.UserInterfaceV2 +{ + public abstract class LabelledDrawable<T> : CompositeDrawable + where T : Drawable + { + protected const float CONTENT_PADDING_VERTICAL = 10; + protected const float CONTENT_PADDING_HORIZONTAL = 15; + protected const float CORNER_RADIUS = 15; + + /// <summary> + /// The component that is being displayed. + /// </summary> + protected readonly T Component; + + private readonly OsuTextFlowContainer labelText; + private readonly OsuTextFlowContainer descriptionText; + + /// <summary> + /// Creates a new <see cref="LabelledComponent{T, U}"/>. + /// </summary> + /// <param name="padded">Whether the component should be padded or should be expanded to the bounds of this <see cref="LabelledComponent{T, U}"/>.</param> + protected LabelledDrawable(bool padded) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + CornerRadius = CORNER_RADIUS; + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex("1c2125"), + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = padded + ? new MarginPadding { Horizontal = CONTENT_PADDING_HORIZONTAL, Vertical = CONTENT_PADDING_VERTICAL } + : new MarginPadding { Left = CONTENT_PADDING_HORIZONTAL }, + Spacing = new Vector2(0, 12), + Children = new Drawable[] + { + new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Content = new[] + { + new Drawable[] + { + labelText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Bold)) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 20 } + }, + new Container + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = Component = CreateComponent().With(d => + { + d.Anchor = Anchor.CentreRight; + d.Origin = Anchor.CentreRight; + }) + } + }, + }, + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } + }, + descriptionText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold, italics: true)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Bottom = padded ? 0 : CONTENT_PADDING_VERTICAL }, + Alpha = 0, + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour osuColour) + { + descriptionText.Colour = osuColour.Yellow; + } + + public string Label + { + set => labelText.Text = value; + } + + public string Description + { + set + { + descriptionText.Text = value; + + if (!string.IsNullOrEmpty(value)) + descriptionText.Show(); + else + descriptionText.Hide(); + } + } + + /// <summary> + /// Creates the component that should be displayed. + /// </summary> + /// <returns>The component.</returns> + protected abstract T CreateComponent(); + } +} diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs index c973f1d13e..c374d80830 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs @@ -3,7 +3,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { - public class LabelledSwitchButton : LabelledComponent<SwitchButton> + public class LabelledSwitchButton : LabelledComponent<SwitchButton, bool> { public LabelledSwitchButton() : base(true) diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs index 50d2a14482..2cbe095d0b 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public class LabelledTextBox : LabelledComponent<OsuTextBox> + public class LabelledTextBox : LabelledComponent<OsuTextBox, string> { public event TextBox.OnCommitHandler OnCommit; From cf3ed42bfc9e299c599e4215ab72ea2df69f7940 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 17:41:42 +0900 Subject: [PATCH 3668/5608] Fix download tracking components getting stuck on import failures --- osu.Game/Database/ArchiveModelManager.cs | 4 +++- osu.Game/Database/DownloadableArchiveModelManager.cs | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index b567f0c0e3..9fed8e03ac 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -108,7 +108,7 @@ namespace osu.Game.Database return Import(notification, paths); } - protected async Task Import(ProgressNotification notification, params string[] paths) + protected async Task<IEnumerable<TModel>> Import(ProgressNotification notification, params string[] paths) { notification.Progress = 0; notification.Text = $"{HumanisedModelName.Humanize(LetterCasing.Title)} import is initialising..."; @@ -168,6 +168,8 @@ namespace osu.Game.Database notification.State = ProgressNotificationState.Completed; } + + return imported; } /// <summary> diff --git a/osu.Game/Database/DownloadableArchiveModelManager.cs b/osu.Game/Database/DownloadableArchiveModelManager.cs index 78c0837ce9..e3c6ad25e6 100644 --- a/osu.Game/Database/DownloadableArchiveModelManager.cs +++ b/osu.Game/Database/DownloadableArchiveModelManager.cs @@ -76,7 +76,12 @@ namespace osu.Game.Database Task.Factory.StartNew(async () => { // This gets scheduled back to the update thread, but we want the import to run in the background. - await Import(notification, filename); + var imported = await Import(notification, filename); + + // for now a failed import will be marked as a failed download for simplicity. + if (!imported.Any()) + DownloadFailed?.Invoke(request); + currentDownloads.Remove(request); }, TaskCreationOptions.LongRunning); }; From 16e33e8bc7d5661cf945bfc495780063ddd1b4ea Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 18:34:58 +0900 Subject: [PATCH 3669/5608] Fix song progress not displaying correctly --- osu.Game/Screens/Play/SongProgress.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 6642efdf8b..3df06ebfa8 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -106,6 +106,8 @@ namespace osu.Game.Screens.Play protected override void LoadComplete() { + base.LoadComplete(); + Show(); replayLoaded.ValueChanged += loaded => AllowSeeking = loaded.NewValue; From 46b44f4f99e08c0d5685ba3bddb239d4860bfb04 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 18:37:58 +0900 Subject: [PATCH 3670/5608] Fix PlayerSettingsOverlay being shown by default --- .../Visual/Gameplay/TestSceneReplaySettingsOverlay.cs | 2 ++ osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplaySettingsOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplaySettingsOverlay.cs index 944480243d..cdfb3beb19 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplaySettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplaySettingsOverlay.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.PlayerSettings; @@ -20,6 +21,7 @@ namespace osu.Game.Tests.Visual.Gameplay { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, + State = { Value = Visibility.Visible } }); Add(container = new ExampleContainer()); diff --git a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs index b2c3952f38..d201b5d30e 100644 --- a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs +++ b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs @@ -45,8 +45,6 @@ namespace osu.Game.Screens.Play.HUD VisualSettings = new VisualSettings { Expanded = false } } }; - - Show(); } protected override void PopIn() => this.FadeIn(fade_duration); From 1a4817879e57800bf1ab7f829c5ca2c7d5b28623 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Mon, 28 Oct 2019 19:10:39 +0900 Subject: [PATCH 3671/5608] Fix precision changes in legacy control point types --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 8 ++++++++ .../Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs | 6 +++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 786b7611b5..c5b9ddc23b 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -376,7 +376,7 @@ namespace osu.Game.Beatmaps.Formats handleTimingControlPoint(controlPoint); } - handleDifficultyControlPoint(new DifficultyControlPoint + handleDifficultyControlPoint(new LegacyDifficultyControlPoint { Time = time, SpeedMultiplier = speedMultiplier, diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index a5a4380d4a..49457833f2 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -189,6 +189,14 @@ namespace osu.Game.Beatmaps.Formats Foreground = 3 } + internal class LegacyDifficultyControlPoint : DifficultyControlPoint + { + public LegacyDifficultyControlPoint() + { + SpeedMultiplierBindable.Precision = Double.Epsilon; + } + } + internal class LegacySampleControlPoint : SampleControlPoint { public int CustomSampleBank; diff --git a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs index a16d391b99..527f520172 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs @@ -28,11 +28,11 @@ namespace osu.Game.Beatmaps.Formats } protected override TimingControlPoint CreateTimingControlPoint() - => new LegacyDifficultyCalculatorControlPoint(); + => new LegacyDifficultyCalculatorTimingControlPoint(); - private class LegacyDifficultyCalculatorControlPoint : TimingControlPoint + private class LegacyDifficultyCalculatorTimingControlPoint : TimingControlPoint { - public LegacyDifficultyCalculatorControlPoint() + public LegacyDifficultyCalculatorTimingControlPoint() { BeatLengthBindable.MinValue = double.MinValue; BeatLengthBindable.MaxValue = double.MaxValue; From c181edaedfc59cd9f3cfc74f7f817059b8051dd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= <dach.bartlomiej@gmail.com> Date: Mon, 28 Oct 2019 15:07:36 +0100 Subject: [PATCH 3672/5608] Replace manual comparer implementation Replace manually-implemented CriteriaComparer with a call to Comparer<T>.Create() to decrease verbosity. --- .../Screens/Select/Carousel/CarouselGroup.cs | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs index b32561eb88..aa48d1a04e 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.Linq; @@ -85,7 +84,8 @@ namespace osu.Game.Screens.Select.Carousel InternalChildren.ForEach(c => c.Filter(criteria)); // IEnumerable<T>.OrderBy() is used instead of List<T>.Sort() to ensure sorting stability - InternalChildren = InternalChildren.OrderBy(c => c, new CriteriaComparer(criteria)).ToList(); + var criteriaComparer = Comparer<CarouselItem>.Create((x, y) => x.CompareTo(criteria, y)); + InternalChildren = InternalChildren.OrderBy(c => c, criteriaComparer).ToList(); } protected virtual void ChildItemStateChanged(CarouselItem item, CarouselItemState value) @@ -103,23 +103,5 @@ namespace osu.Game.Screens.Select.Carousel State.Value = CarouselItemState.Selected; } } - - private class CriteriaComparer : IComparer<CarouselItem> - { - private readonly FilterCriteria criteria; - - public CriteriaComparer(FilterCriteria criteria) - { - this.criteria = criteria; - } - - public int Compare(CarouselItem x, CarouselItem y) - { - if (x != null && y != null) - return x.CompareTo(criteria, y); - - throw new ArgumentNullException(); - } - } } } From a4a57eec544d7d66774364304f17cb629bfd4834 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Tue, 29 Oct 2019 01:09:49 +0900 Subject: [PATCH 3673/5608] Fix game-wide performance drop when triangles intro is used --- osu.Game/Screens/Menu/IntroSequence.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Menu/IntroSequence.cs b/osu.Game/Screens/Menu/IntroSequence.cs index 093d01f12d..e2dd14b18c 100644 --- a/osu.Game/Screens/Menu/IntroSequence.cs +++ b/osu.Game/Screens/Menu/IntroSequence.cs @@ -42,6 +42,7 @@ namespace osu.Game.Screens.Menu public IntroSequence() { RelativeSizeAxes = Axes.Both; + Alpha = 0; } [BackgroundDependencyLoader] From ecf14bc7b9721850744884822232af96db104038 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Tue, 29 Oct 2019 01:21:17 +0900 Subject: [PATCH 3674/5608] Rename class to match --- ...TestSceneLabelledComponent.cs => TestSceneLabelledDrawable.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{TestSceneLabelledComponent.cs => TestSceneLabelledDrawable.cs} (100%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDrawable.cs similarity index 100% rename from osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDrawable.cs From d1c6e3f62064305fbeb4d53bb627571bd8650ec6 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Tue, 29 Oct 2019 14:32:38 +0900 Subject: [PATCH 3675/5608] Add test for scroll to end when max history is exceeded --- .../Online/TestSceneStandAloneChatDisplay.cs | 37 +++++++++++++++++-- osu.Game/Online/Chat/Channel.cs | 8 ++-- osu.Game/Overlays/Chat/DrawableChannel.cs | 4 +- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs index 39c2fbfcc9..d973799405 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs @@ -7,6 +7,9 @@ using osu.Game.Online.Chat; using osu.Game.Users; using osuTK; using System; +using System.Linq; +using osu.Framework.Graphics.Containers; +using osu.Game.Overlays.Chat; namespace osu.Game.Tests.Visual.Online { @@ -42,14 +45,14 @@ namespace osu.Game.Tests.Visual.Online [Cached] private ChannelManager channelManager = new ChannelManager(); - private readonly StandAloneChatDisplay chatDisplay; - private readonly StandAloneChatDisplay chatDisplay2; + private readonly TestStandAloneChatDisplay chatDisplay; + private readonly TestStandAloneChatDisplay chatDisplay2; public TestSceneStandAloneChatDisplay() { Add(channelManager); - Add(chatDisplay = new StandAloneChatDisplay + Add(chatDisplay = new TestStandAloneChatDisplay { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -57,7 +60,7 @@ namespace osu.Game.Tests.Visual.Online Size = new Vector2(400, 80) }); - Add(chatDisplay2 = new StandAloneChatDisplay(true) + Add(chatDisplay2 = new TestStandAloneChatDisplay(true) { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, @@ -119,6 +122,32 @@ namespace osu.Game.Tests.Visual.Online Content = "Message from the future!", Timestamp = DateTimeOffset.Now })); + + AddUntilStep("ensure still scrolled to bottom", () => chatDisplay.ScrolledToBottom); + + const int messages_per_call = 10; + AddRepeatStep("add many messages", () => + { + for (int i = 0; i < messages_per_call; i++) + testChannel.AddNewMessages(new Message(sequence++) + { + Sender = longUsernameUser, + Content = "Many messages! " + Guid.NewGuid(), + Timestamp = DateTimeOffset.Now + }); + }, Channel.MAX_HISTORY / messages_per_call + 5); + + AddUntilStep("ensure still scrolled to bottom", () => chatDisplay.ScrolledToBottom); + } + + private class TestStandAloneChatDisplay : StandAloneChatDisplay + { + public TestStandAloneChatDisplay(bool textbox = false) + : base(textbox) + { + } + + public bool ScrolledToBottom => ((ScrollContainer<Drawable>)((Container)InternalChildren.OfType<DrawableChannel>().First().Child).Child).IsScrolledToEnd(1); } } } diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 9ec39c5cb1..451174a73c 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -14,7 +14,7 @@ namespace osu.Game.Online.Chat { public class Channel { - public readonly int MaxHistory = 300; + public const int MAX_HISTORY = 300; /// <summary> /// Contains every joined user except the current logged in user. Currently only returned for PM channels. @@ -80,8 +80,6 @@ namespace osu.Game.Online.Chat /// </summary> public Bindable<bool> Joined = new Bindable<bool>(); - public const int MAX_HISTORY = 300; - [JsonConstructor] public Channel() { @@ -162,8 +160,8 @@ namespace osu.Game.Online.Chat { // never purge local echos int messageCount = Messages.Count - pendingMessages.Count; - if (messageCount > MaxHistory) - Messages.RemoveRange(0, messageCount - MaxHistory); + if (messageCount > MAX_HISTORY) + Messages.RemoveRange(0, messageCount - MAX_HISTORY); } } } diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 6cdbfabe0f..4ddaf4d5ae 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.Chat scrollToEnd(); var staleMessages = chatLines.Where(c => c.LifetimeEnd == double.MaxValue).ToArray(); - int count = staleMessages.Length - Channel.MaxHistory; + int count = staleMessages.Length - Channel.MAX_HISTORY; for (int i = 0; i < count; i++) { From 09a6d1184a42ce86f5c61d1cf2464425b1c0a7ad Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Tue, 29 Oct 2019 14:33:05 +0900 Subject: [PATCH 3676/5608] Tidy up order of scroll changes --- osu.Game/Overlays/Chat/DrawableChannel.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 4ddaf4d5ae..9301daa9ff 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -89,8 +89,10 @@ namespace osu.Game.Overlays.Chat private void newMessagesArrived(IEnumerable<Message> newMessages) { + bool shouldScrollToEnd = scroll.IsScrolledToEnd(10) || !chatLines.Any() || newMessages.Any(m => m is LocalMessage); + // Add up to last Channel.MAX_HISTORY messages - var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MaxHistory)); + var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MAX_HISTORY)); Message lastMessage = chatLines.LastOrDefault()?.Message; @@ -103,19 +105,18 @@ namespace osu.Game.Overlays.Chat lastMessage = message; } - if (scroll.IsScrolledToEnd(10) || !chatLines.Any() || newMessages.Any(m => m is LocalMessage)) - scrollToEnd(); - var staleMessages = chatLines.Where(c => c.LifetimeEnd == double.MaxValue).ToArray(); int count = staleMessages.Length - Channel.MAX_HISTORY; for (int i = 0; i < count; i++) { var d = staleMessages[i]; - if (!scroll.IsScrolledToEnd(10)) - scroll.OffsetScrollPosition(-d.DrawHeight); + scroll.OffsetScrollPosition(-d.DrawHeight); d.Expire(); } + + if (shouldScrollToEnd) + scrollToEnd(); } private void pendingMessageResolved(Message existing, Message updated) From b06e70e546ca0a2d82ecfbce85f977a2a200fb28 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Tue, 29 Oct 2019 15:27:08 +0900 Subject: [PATCH 3677/5608] Add failing test showing issue with day separator logic --- .../Online/TestSceneStandAloneChatDisplay.cs | 20 ++++++++++++++++++- osu.Game/Overlays/Chat/DrawableChannel.cs | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs index d973799405..01400bf1d9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs @@ -9,6 +9,7 @@ using osuTK; using System; using System.Linq; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Containers; using osu.Game.Overlays.Chat; namespace osu.Game.Tests.Visual.Online @@ -137,6 +138,17 @@ namespace osu.Game.Tests.Visual.Online }); }, Channel.MAX_HISTORY / messages_per_call + 5); + AddAssert("Ensure no adjacent day separators", () => + { + var indices = chatDisplay.FillFlow.OfType<DrawableChannel.DaySeparator>().Select(ds => chatDisplay.FillFlow.IndexOf(ds)); + + foreach (var i in indices) + if (i < chatDisplay.FillFlow.Count && chatDisplay.FillFlow[i + 1] is DrawableChannel.DaySeparator) + return false; + + return true; + }); + AddUntilStep("ensure still scrolled to bottom", () => chatDisplay.ScrolledToBottom); } @@ -147,7 +159,13 @@ namespace osu.Game.Tests.Visual.Online { } - public bool ScrolledToBottom => ((ScrollContainer<Drawable>)((Container)InternalChildren.OfType<DrawableChannel>().First().Child).Child).IsScrolledToEnd(1); + protected DrawableChannel DrawableChannel => InternalChildren.OfType<DrawableChannel>().First(); + + protected OsuScrollContainer ScrollContainer => (OsuScrollContainer)((Container)DrawableChannel.Child).Child; + + public FillFlowContainer FillFlow => (FillFlowContainer)ScrollContainer.Child; + + public bool ScrolledToBottom => ScrollContainer.IsScrolledToEnd(1); } } } diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 9301daa9ff..636fafb5f2 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -142,7 +142,7 @@ namespace osu.Game.Overlays.Chat private void scrollToEnd() => ScheduleAfterChildren(() => scroll.ScrollToEnd()); - protected class DaySeparator : Container + public class DaySeparator : Container { public float TextSize { From 54befb6f8fdbdfe36e9f299b3df54782ff08cf7f Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Tue, 29 Oct 2019 15:45:41 +0900 Subject: [PATCH 3678/5608] Remove adjacent day separators --- osu.Game/Overlays/Chat/DrawableChannel.cs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 636fafb5f2..427bd8dcde 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -108,11 +108,25 @@ namespace osu.Game.Overlays.Chat var staleMessages = chatLines.Where(c => c.LifetimeEnd == double.MaxValue).ToArray(); int count = staleMessages.Length - Channel.MAX_HISTORY; - for (int i = 0; i < count; i++) + if (count > 0) { - var d = staleMessages[i]; - scroll.OffsetScrollPosition(-d.DrawHeight); - d.Expire(); + void expireAndAdjustScroll(Drawable d) + { + scroll.OffsetScrollPosition(-d.DrawHeight); + d.Expire(); + } + + for (int i = 0; i < count; i++) + expireAndAdjustScroll(staleMessages[i]); + + // remove all adjacent day separators after stale message removal + for (int i = 0; i < ChatLineFlow.Count - 1; i++) + { + if (!(ChatLineFlow[i] is DaySeparator)) break; + if (!(ChatLineFlow[i + 1] is DaySeparator)) break; + + expireAndAdjustScroll(ChatLineFlow[i]); + } } if (shouldScrollToEnd) From 8e1faf6ff1810b828bad316475ff5a9d2bed88dc Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Tue, 29 Oct 2019 17:03:52 +0900 Subject: [PATCH 3679/5608] Fix loader animation tests failing occasionally --- .../Visual/Menus/TestSceneLoaderAnimation.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs index 000832b784..61fed3013e 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs @@ -33,23 +33,15 @@ namespace osu.Game.Tests.Visual.Menus [Test] public void TestInstantLoad() { - bool logoVisible = false; + // visual only, very impossible to test this using asserts. - AddStep("begin loading", () => + AddStep("load immediately", () => { loader = new TestLoader(); loader.AllowLoad.Set(); LoadScreen(loader); }); - - AddUntilStep("loaded", () => - { - logoVisible = loader.Logo?.Alpha > 0; - return loader.Logo != null && loader.ScreenLoaded; - }); - - AddAssert("logo was not visible", () => !logoVisible); } [Test] @@ -58,7 +50,7 @@ namespace osu.Game.Tests.Visual.Menus AddStep("begin loading", () => LoadScreen(loader = new TestLoader())); AddUntilStep("wait for logo visible", () => loader.Logo?.Alpha > 0); AddStep("finish loading", () => loader.AllowLoad.Set()); - AddAssert("loaded", () => loader.Logo != null && loader.ScreenLoaded); + AddUntilStep("loaded", () => loader.Logo != null && loader.ScreenLoaded); AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0); } From 7c6ccce3ba1b271309185d5587a76924f95d82b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Tue, 29 Oct 2019 18:02:30 +0900 Subject: [PATCH 3680/5608] Add tests covering precision case --- .../Formats/LegacyBeatmapDecoderTest.cs | 17 +++++++++++++++++ .../controlpoint-difficulty-multiplier.osu | 8 ++++++++ 2 files changed, 25 insertions(+) create mode 100644 osu.Game.Tests/Resources/controlpoint-difficulty-multiplier.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index de516d3142..8545072199 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -362,6 +362,23 @@ namespace osu.Game.Tests.Beatmaps.Formats } } + [Test] + public void TestDecodeControlPointDifficultyChange() + { + var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + + using (var resStream = TestResources.OpenResource("controlpoint-difficulty-multiplier.osu")) + using (var stream = new LineBufferedReader(resStream)) + { + var controlPointInfo = decoder.Decode(stream).ControlPointInfo; + + Assert.That(controlPointInfo.DifficultyPointAt(5).SpeedMultiplier, Is.EqualTo(1)); + Assert.That(controlPointInfo.DifficultyPointAt(1000).SpeedMultiplier, Is.EqualTo(10)); + Assert.That(controlPointInfo.DifficultyPointAt(2000).SpeedMultiplier, Is.EqualTo(1.8518518518518519d)); + Assert.That(controlPointInfo.DifficultyPointAt(3000).SpeedMultiplier, Is.EqualTo(0.5)); + } + } + [Test] public void TestDecodeControlPointCustomSampleBank() { diff --git a/osu.Game.Tests/Resources/controlpoint-difficulty-multiplier.osu b/osu.Game.Tests/Resources/controlpoint-difficulty-multiplier.osu new file mode 100644 index 0000000000..5f06fc33c8 --- /dev/null +++ b/osu.Game.Tests/Resources/controlpoint-difficulty-multiplier.osu @@ -0,0 +1,8 @@ +osu file format v7 + +[TimingPoints] +0,100,4,2,0,100,1,0 +12,500,4,2,0,100,1,0 +1000,-10,4,2,0,100,0,0 +2000,-54,4,2,0,100,0,0 +3000,-200,4,2,0,100,0,0 From 97c1a6e86bfdfe65e18d0d52f53fb6e585f9edda Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Tue, 29 Oct 2019 18:05:32 +0900 Subject: [PATCH 3681/5608] 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 43c1302e54..8b31be3f12 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ </ItemGroup> <ItemGroup> <PackageReference Include="ppy.osu.Game.Resources" Version="2019.1010.0" /> - <PackageReference Include="ppy.osu.Framework.Android" Version="2019.1023.0" /> + <PackageReference Include="ppy.osu.Framework.Android" Version="2019.1029.0" /> </ItemGroup> </Project> diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e898a001de..0cb09d9b14 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2019.1010.0" /> - <PackageReference Include="ppy.osu.Framework" Version="2019.1023.0" /> + <PackageReference Include="ppy.osu.Framework" Version="2019.1029.0" /> <PackageReference Include="SharpCompress" Version="0.24.0" /> <PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="SharpRaven" Version="2.4.0" /> diff --git a/osu.iOS.props b/osu.iOS.props index 656c60543e..719aced705 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.1" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.1" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2019.1010.0" /> - <PackageReference Include="ppy.osu.Framework" Version="2019.1023.0" /> - <PackageReference Include="ppy.osu.Framework.iOS" Version="2019.1023.0" /> + <PackageReference Include="ppy.osu.Framework" Version="2019.1029.0" /> + <PackageReference Include="ppy.osu.Framework.iOS" Version="2019.1029.0" /> <PackageReference Include="SharpCompress" Version="0.24.0" /> <PackageReference Include="NUnit" Version="3.11.0" /> <PackageReference Include="SharpRaven" Version="2.4.0" /> From e9cb3337b31e39372f3905405366d45d3372bded Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Tue, 29 Oct 2019 22:31:27 +0900 Subject: [PATCH 3682/5608] Fix 1x1 white pixel appearing in the centre of hitcircles on default skin --- .../Objects/Drawables/Pieces/NumberPiece.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs index 62c4ba5ee3..7c94568835 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Game.Graphics.Sprites; using osuTK.Graphics; -using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Skinning; @@ -30,17 +29,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Children = new Drawable[] { - new CircularContainer + new Container { Masking = true, - Origin = Anchor.Centre, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, Radius = 60, Colour = Color4.White.Opacity(0.5f), }, - Child = new Box() }, number = new SkinnableSpriteText(new OsuSkinComponent(OsuSkinComponents.HitCircleText), _ => new OsuSpriteText { From 5c2917d3030e872a656deda7a4f44e8a218ec6d7 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya <gsculerlor@hotmail.com> Date: Wed, 30 Oct 2019 00:50:04 +0700 Subject: [PATCH 3683/5608] Place sign in button inside ShakeContainer --- .../Sections/General/LoginSettings.cs | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index b02b1a5489..a8bbccb168 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -200,6 +200,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { private TextBox username; private TextBox password; + private ShakeContainer shakeSignIn; private IAPIProvider api; public Action RequestHide; @@ -208,6 +209,8 @@ namespace osu.Game.Overlays.Settings.Sections.General { if (!string.IsNullOrEmpty(username.Text) && !string.IsNullOrEmpty(password.Text)) api.Login(username.Text, password.Text); + else + shakeSignIn.Shake(); } [BackgroundDependencyLoader(permitNulls: true)] @@ -244,10 +247,23 @@ namespace osu.Game.Overlays.Settings.Sections.General LabelText = "Stay signed in", Bindable = config.GetBindable<bool>(OsuSetting.SavePassword), }, - new SettingsButton + new Container { - Text = "Sign in", - Action = performLogin + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + shakeSignIn = new ShakeContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = new SettingsButton + { + Text = "Sign in", + Action = performLogin + }, + } + } }, new SettingsButton { From e287dae64b59aa1cf6f67f2485f7541b98a8cc44 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski <megaman9919@gmail.com> Date: Tue, 29 Oct 2019 21:25:48 +0300 Subject: [PATCH 3684/5608] Fix VotePill can be activated by the comment sender --- osu.Game/Overlays/Comments/VotePill.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index e8d9013fd9..b2c8c52bf3 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -43,6 +43,7 @@ namespace osu.Game.Overlays.Comments private readonly BindableBool isVoted = new BindableBool(); private readonly BindableInt votesCount = new BindableInt(); + private bool disabled; public VotePill(Comment comment) { @@ -69,6 +70,8 @@ namespace osu.Game.Overlays.Comments votesCount.Value = comment.VotesCount; isVoted.BindValueChanged(voted => background.Colour = voted.NewValue ? AccentColour : OsuColour.Gray(0.05f), true); votesCount.BindValueChanged(count => votesCounter.Text = $"+{count.NewValue}", true); + + api.LocalUser.BindValueChanged(user => disabled = user.NewValue?.Id == comment.UserId ? true : false, true); } private void onAction() @@ -145,16 +148,30 @@ namespace osu.Game.Overlays.Comments protected override bool OnHover(HoverEvent e) { + if (disabled) + return false; + onHoverAction(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { + if (disabled) + return; + updateDisplay(); base.OnHoverLost(e); } + protected override bool OnClick(ClickEvent e) + { + if (disabled) + return false; + + return base.OnClick(e); + } + private void updateDisplay() { if (isVoted.Value) From 30d9b21b86264bbc8cfae70f7ac65ae390ea250e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski <megaman9919@gmail.com> Date: Tue, 29 Oct 2019 21:57:20 +0300 Subject: [PATCH 3685/5608] Condition simplification --- osu.Game/Overlays/Comments/VotePill.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index b2c8c52bf3..32fbe55fb5 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -71,7 +71,7 @@ namespace osu.Game.Overlays.Comments isVoted.BindValueChanged(voted => background.Colour = voted.NewValue ? AccentColour : OsuColour.Gray(0.05f), true); votesCount.BindValueChanged(count => votesCounter.Text = $"+{count.NewValue}", true); - api.LocalUser.BindValueChanged(user => disabled = user.NewValue?.Id == comment.UserId ? true : false, true); + api.LocalUser.BindValueChanged(user => disabled = user.NewValue?.Id == comment.UserId, true); } private void onAction() From 092d16bb6465a2555654f991d492098a0355d7c6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski <megaman9919@gmail.com> Date: Tue, 29 Oct 2019 23:43:16 +0300 Subject: [PATCH 3686/5608] Dont use binding to set disabled value --- osu.Game/Overlays/Comments/VotePill.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 32fbe55fb5..a895ad2bcf 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -61,6 +61,8 @@ namespace osu.Game.Overlays.Comments { AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; hoverLayer.Colour = Color4.Black.Opacity(0.5f); + + disabled = api.LocalUser.Value.Id == comment.UserId; } protected override void LoadComplete() @@ -70,8 +72,6 @@ namespace osu.Game.Overlays.Comments votesCount.Value = comment.VotesCount; isVoted.BindValueChanged(voted => background.Colour = voted.NewValue ? AccentColour : OsuColour.Gray(0.05f), true); votesCount.BindValueChanged(count => votesCounter.Text = $"+{count.NewValue}", true); - - api.LocalUser.BindValueChanged(user => disabled = user.NewValue?.Id == comment.UserId, true); } private void onAction() From 1502a6c631920debf7bcdbda293326bb9be300e1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski <megaman9919@gmail.com> Date: Wed, 30 Oct 2019 03:09:14 +0300 Subject: [PATCH 3687/5608] Cleanups --- osu.Game/Overlays/Comments/VotePill.cs | 37 +++++++++----------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index a895ad2bcf..5d0431314b 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -43,14 +43,11 @@ namespace osu.Game.Overlays.Comments private readonly BindableBool isVoted = new BindableBool(); private readonly BindableInt votesCount = new BindableInt(); - private bool disabled; public VotePill(Comment comment) { this.comment = comment; - Action = onAction; - AutoSizeAxes = Axes.X; Height = 20; LoadingAnimationSize = new Vector2(10); @@ -62,7 +59,8 @@ namespace osu.Game.Overlays.Comments AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; hoverLayer.Colour = Color4.Black.Opacity(0.5f); - disabled = api.LocalUser.Value.Id == comment.UserId; + if (api.LocalUser.Value.Id != comment.UserId) + Action = onAction; } protected override void LoadComplete() @@ -148,41 +146,30 @@ namespace osu.Game.Overlays.Comments protected override bool OnHover(HoverEvent e) { - if (disabled) - return false; - onHoverAction(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - if (disabled) - return; - updateDisplay(); base.OnHoverLost(e); } - protected override bool OnClick(ClickEvent e) - { - if (disabled) - return false; - - return base.OnClick(e); - } - private void updateDisplay() { - if (isVoted.Value) + if (Action != null) { - hoverLayer.FadeTo(IsHovered ? 1 : 0); - sideNumber.Hide(); - } - else - sideNumber.FadeTo(IsHovered ? 1 : 0); + if (isVoted.Value) + { + hoverLayer.FadeTo(IsHovered ? 1 : 0); + sideNumber.Hide(); + } + else + sideNumber.FadeTo(IsHovered ? 1 : 0); - borderContainer.BorderThickness = IsHovered ? 3 : 0; + borderContainer.BorderThickness = IsHovered ? 3 : 0; + } } private void onHoverAction() From 2c31492bbe57f2ae9cca0b77f6a6f7cc0e967971 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski <megaman9919@gmail.com> Date: Wed, 30 Oct 2019 03:27:06 +0300 Subject: [PATCH 3688/5608] Fix comment can be voted if user is null --- osu.Game/Overlays/Comments/VotePill.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 5d0431314b..9a10e4a2c1 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Comments AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; hoverLayer.Colour = Color4.Black.Opacity(0.5f); - if (api.LocalUser.Value.Id != comment.UserId) + if ((api.LocalUser.Value?.Id ?? comment.UserId) != comment.UserId) Action = onAction; } From f1a2643c401b83ee8ec952b76dacf896910990d1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski <megaman9919@gmail.com> Date: Wed, 30 Oct 2019 03:45:05 +0300 Subject: [PATCH 3689/5608] Add test scene --- .../Visual/Online/TestSceneVotePill.cs | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneVotePill.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs new file mode 100644 index 0000000000..8ddb16d8ca --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -0,0 +1,59 @@ +// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Overlays.Comments; +using osu.Framework.Allocation; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Tests.Visual.Online +{ + [TestFixture] + public class TestSceneVotePill : OsuTestScene + { + public override IReadOnlyList<Type> RequiredTypes => new[] + { + typeof(VotePill) + }; + + private VotePill votePill; + + [BackgroundDependencyLoader] + private void load() + { + var userComment = new Comment + { + IsVoted = false, + UserId = API.LocalUser.Value?.Id, + VotesCount = 10, + }; + + var randomComment = new Comment + { + IsVoted = false, + UserId = 455454, + VotesCount = 2, + }; + + AddStep("Random comment", () => addVotePill(randomComment)); + AddStep("Click", () => votePill.Click()); + AddAssert("Loading", () => votePill.IsLoading == true); + AddStep("User comment", () => addVotePill(userComment)); + AddStep("Click", () => votePill.Click()); + AddAssert("Not loading", () => votePill.IsLoading == false); + } + + private void addVotePill(Comment comment) + { + Clear(); + Add(votePill = new VotePill(comment) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + } + } +} From 7f755fe726085b1e42afa8430f9f07429aa02545 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski <megaman9919@gmail.com> Date: Wed, 30 Oct 2019 03:47:17 +0300 Subject: [PATCH 3690/5608] Add more tests --- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index 8ddb16d8ca..76bf825541 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -44,6 +44,9 @@ namespace osu.Game.Tests.Visual.Online AddStep("User comment", () => addVotePill(userComment)); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => votePill.IsLoading == false); + AddStep("Log out", API.Logout); + AddStep("Click", () => votePill.Click()); + AddAssert("Not loading", () => votePill.IsLoading == false); } private void addVotePill(Comment comment) From 8ad5ccda68e679acae583b636cd125ac9b74674e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski <megaman9919@gmail.com> Date: Wed, 30 Oct 2019 04:16:14 +0300 Subject: [PATCH 3691/5608] Test steps rearrangement and condition fix --- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 13 ++++++++----- osu.Game/Overlays/Comments/VotePill.cs | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index 76bf825541..47cb806fb8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -27,24 +27,27 @@ namespace osu.Game.Tests.Visual.Online var userComment = new Comment { IsVoted = false, - UserId = API.LocalUser.Value?.Id, + UserId = API.LocalUser.Value.Id, VotesCount = 10, }; var randomComment = new Comment { IsVoted = false, - UserId = 455454, + UserId = 4444, VotesCount = 2, }; + AddStep("User comment", () => addVotePill(userComment)); + AddStep("Click", () => votePill.Click()); + AddAssert("Not loading", () => votePill.IsLoading == false); + AddStep("Random comment", () => addVotePill(randomComment)); AddStep("Click", () => votePill.Click()); AddAssert("Loading", () => votePill.IsLoading == true); - AddStep("User comment", () => addVotePill(userComment)); - AddStep("Click", () => votePill.Click()); - AddAssert("Not loading", () => votePill.IsLoading == false); + AddStep("Log out", API.Logout); + AddStep("Random comment", () => addVotePill(randomComment)); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => votePill.IsLoading == false); } diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 9a10e4a2c1..54eba63095 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Comments AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; hoverLayer.Colour = Color4.Black.Opacity(0.5f); - if ((api.LocalUser.Value?.Id ?? comment.UserId) != comment.UserId) + if (api.LocalUser.Value.Id != comment.UserId && api.LocalUser.Value.Id != 1) Action = onAction; } From 759395bcb5802f76dfea0db38be65f27561da27f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski <megaman9919@gmail.com> Date: Wed, 30 Oct 2019 04:31:09 +0300 Subject: [PATCH 3692/5608] CI fix --- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index 47cb806fb8..7ccb025b47 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -40,16 +40,16 @@ namespace osu.Game.Tests.Visual.Online AddStep("User comment", () => addVotePill(userComment)); AddStep("Click", () => votePill.Click()); - AddAssert("Not loading", () => votePill.IsLoading == false); + AddAssert("Not loading", () => !votePill.IsLoading); AddStep("Random comment", () => addVotePill(randomComment)); AddStep("Click", () => votePill.Click()); - AddAssert("Loading", () => votePill.IsLoading == true); + AddAssert("Loading", () => votePill.IsLoading); AddStep("Log out", API.Logout); AddStep("Random comment", () => addVotePill(randomComment)); AddStep("Click", () => votePill.Click()); - AddAssert("Not loading", () => votePill.IsLoading == false); + AddAssert("Not loading", () => !votePill.IsLoading); } private void addVotePill(Comment comment) From 95ff48c123cc19c7388c1140f2dc93513898244d Mon Sep 17 00:00:00 2001 From: smoogipoo <smoogipoo@smgi.me> Date: Wed, 30 Oct 2019 14:38:06 +0900 Subject: [PATCH 3693/5608] Don't log cancelled join requests --- osu.Game/Screens/Multi/RoomManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 6f473aaafa..8ceff7edef 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -98,7 +98,8 @@ namespace osu.Game.Screens.Multi currentJoinRoomRequest.Failure += exception => { - Logger.Log($"Failed to join room: {exception}", level: LogLevel.Important); + if (!(exception is OperationCanceledException)) + Logger.Log($"Failed to join room: {exception}", level: LogLevel.Important); onError?.Invoke(exception.ToString()); }; From b6457f0ce957342b9d76c2f36b37f85bccf640ea Mon Sep 17 00:00:00 2001 From: smoogipoo <smoogipoo@smgi.me> Date: Wed, 30 Oct 2019 14:41:54 +0900 Subject: [PATCH 3694/5608] Cancel room joins on part --- osu.Game/Screens/Multi/RoomManager.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 8ceff7edef..cdaba85b9e 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -87,9 +87,8 @@ namespace osu.Game.Screens.Multi public void JoinRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null) { currentJoinRoomRequest?.Cancel(); - currentJoinRoomRequest = null; - currentJoinRoomRequest = new JoinRoomRequest(room, api.LocalUser.Value); + currentJoinRoomRequest.Success += () => { joinedRoom = room; @@ -108,6 +107,8 @@ namespace osu.Game.Screens.Multi public void PartRoom() { + currentJoinRoomRequest?.Cancel(); + if (joinedRoom == null) return; From f56d9fe50cf2933a1fd94afc90df7082ebaff331 Mon Sep 17 00:00:00 2001 From: smoogipoo <smoogipoo@smgi.me> Date: Wed, 30 Oct 2019 14:42:14 +0900 Subject: [PATCH 3695/5608] Forcefully part room when multiplayer exits --- osu.Game/Screens/Multi/Multiplayer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 90806bab6e..5945e9de13 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -212,6 +212,8 @@ namespace osu.Game.Screens.Multi public override bool OnExiting(IScreen next) { + roomManager.PartRoom(); + if (screenStack.CurrentScreen != null && !(screenStack.CurrentScreen is LoungeSubScreen)) { screenStack.Exit(); From ced6042b3e977dcfcd18ca1e77872e061e0a8811 Mon Sep 17 00:00:00 2001 From: Dan Balasescu <smoogipoo@smgi.me> Date: Wed, 30 Oct 2019 15:51:09 +0900 Subject: [PATCH 3696/5608] Use internal type name --- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 49457833f2..2b914669cb 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -193,7 +193,7 @@ namespace osu.Game.Beatmaps.Formats { public LegacyDifficultyControlPoint() { - SpeedMultiplierBindable.Precision = Double.Epsilon; + SpeedMultiplierBindable.Precision = double.Epsilon; } } From 45af7969434d6216f71dc8da59759c3e33626986 Mon Sep 17 00:00:00 2001 From: smoogipoo <smoogipoo@smgi.me> Date: Wed, 30 Oct 2019 17:05:15 +0900 Subject: [PATCH 3697/5608] Remove usages of EF internals --- .../UserInterface/TestSceneBeatSyncedContainer.cs | 4 ++-- osu.Game/Screens/Edit/EditorClock.cs | 13 +++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index b6df559686..ed44d82bce 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Internal; +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Track; @@ -153,7 +153,7 @@ namespace osu.Game.Tests.Visual.UserInterface }; } - private IReadOnlyList<TimingControlPoint> timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints; + private List<TimingControlPoint> timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints.ToList(); private TimingControlPoint getNextTimingPoint(TimingControlPoint current) { diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 1cfb123f25..f674a62a3a 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -3,7 +3,6 @@ using System; using System.Linq; -using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Beatmaps; @@ -88,7 +87,17 @@ namespace osu.Game.Screens.Edit if (direction < 0 && timingPoint.Time == CurrentTime) { // When going backwards and we're at the boundary of two timing points, we compute the seek distance with the timing point which we are seeking into - int activeIndex = ControlPointInfo.TimingPoints.IndexOf(timingPoint); + int activeIndex = -1; + + for (int i = 0; i < ControlPointInfo.TimingPoints.Count; i++) + { + if (ControlPointInfo.TimingPoints[i] == timingPoint) + { + activeIndex = i; + break; + } + } + while (activeIndex > 0 && CurrentTime == timingPoint.Time) timingPoint = ControlPointInfo.TimingPoints[--activeIndex]; } From cf2d885099a0b92257adabf8bee9d130d8450d7d Mon Sep 17 00:00:00 2001 From: smoogipoo <smoogipoo@smgi.me> Date: Wed, 30 Oct 2019 18:02:18 +0900 Subject: [PATCH 3698/5608] Fix control points being flushed too late --- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 15 +++++++++++++++ .../timingpoint-speedmultiplier-reset.osu | 5 +++++ osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 6 +++--- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 osu.Game.Tests/Resources/timingpoint-speedmultiplier-reset.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index a6b0dedf56..2ecc516919 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -262,6 +262,21 @@ namespace osu.Game.Tests.Beatmaps.Formats } } + [Test] + public void TestTimingPointResetsSpeedMultiplier() + { + var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + + using (var resStream = TestResources.OpenResource("timingpoint-speedmultiplier-reset.osu")) + using (var stream = new LineBufferedReader(resStream)) + { + var controlPoints = decoder.Decode(stream).ControlPointInfo; + + Assert.That(controlPoints.DifficultyPointAt(0).SpeedMultiplier, Is.EqualTo(0.5).Within(0.1)); + Assert.That(controlPoints.DifficultyPointAt(2000).SpeedMultiplier, Is.EqualTo(1).Within(0.1)); + } + } + [Test] public void TestDecodeBeatmapColours() { diff --git a/osu.Game.Tests/Resources/timingpoint-speedmultiplier-reset.osu b/osu.Game.Tests/Resources/timingpoint-speedmultiplier-reset.osu new file mode 100644 index 0000000000..4512903c68 --- /dev/null +++ b/osu.Game.Tests/Resources/timingpoint-speedmultiplier-reset.osu @@ -0,0 +1,5 @@ +osu file format v14 + +[TimingPoints] +0,-200,4,1,0,100,0,0 +2000,100,1,1,0,100,1,0 diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index a6b60bd7a0..aeb5df46f8 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -411,15 +411,15 @@ namespace osu.Game.Beatmaps.Formats private void addControlPoint(double time, ControlPoint point, bool timingChange) { + if (time != pendingControlPointsTime) + flushPendingPoints(); + if (timingChange) { beatmap.ControlPointInfo.Add(time, point); return; } - if (time != pendingControlPointsTime) - flushPendingPoints(); - pendingControlPoints.Add(point); pendingControlPointsTime = time; } From 5899bbd8a63d8a4035c180f0c507fc7b3676cda3 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Wed, 30 Oct 2019 18:44:07 +0900 Subject: [PATCH 3699/5608] Fix merge regressions --- osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 6 +++--- osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index cf084e838e..2ecc516919 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -167,9 +167,9 @@ namespace osu.Game.Tests.Beatmaps.Formats var controlPoints = beatmap.ControlPointInfo; Assert.AreEqual(4, controlPoints.TimingPoints.Count); - Assert.AreEqual(6, controlPoints.DifficultyPoints.Count); + Assert.AreEqual(5, controlPoints.DifficultyPoints.Count); Assert.AreEqual(34, controlPoints.SamplePoints.Count); - Assert.AreEqual(9, controlPoints.EffectPoints.Count); + Assert.AreEqual(8, controlPoints.EffectPoints.Count); var timingPoint = controlPoints.TimingPointAt(0); Assert.AreEqual(956, timingPoint.Time); @@ -191,7 +191,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(48428); - Assert.AreEqual(956, difficultyPoint.Time); + Assert.AreEqual(0, difficultyPoint.Time); Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(116999); diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index d9328d1636..51b3377394 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -34,6 +34,7 @@ namespace osu.Game.Beatmaps.ControlPoints MaxValue = 60000 }; + /// <summary> /// The beat length at this control point. /// </summary> public double BeatLength From 7f2916454d934e57622c28c71ccaa57d538aeebf Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Wed, 30 Oct 2019 19:09:46 +0900 Subject: [PATCH 3700/5608] Simplify EditorClock.Seek method --- osu.Game/Screens/Edit/EditorClock.cs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index f674a62a3a..bd2db4ae2b 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -85,22 +85,8 @@ namespace osu.Game.Screens.Edit var timingPoint = ControlPointInfo.TimingPointAt(CurrentTime); if (direction < 0 && timingPoint.Time == CurrentTime) - { // When going backwards and we're at the boundary of two timing points, we compute the seek distance with the timing point which we are seeking into - int activeIndex = -1; - - for (int i = 0; i < ControlPointInfo.TimingPoints.Count; i++) - { - if (ControlPointInfo.TimingPoints[i] == timingPoint) - { - activeIndex = i; - break; - } - } - - while (activeIndex > 0 && CurrentTime == timingPoint.Time) - timingPoint = ControlPointInfo.TimingPoints[--activeIndex]; - } + timingPoint = ControlPointInfo.TimingPointAt(CurrentTime - 1); double seekAmount = timingPoint.BeatLength / beatDivisor.Value * amount; double seekTime = CurrentTime + seekAmount * direction; From 35be8f9dfbab66ba527631ba2b100f1c9c48f35f Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Wed, 30 Oct 2019 19:33:54 +0900 Subject: [PATCH 3701/5608] Share framework file-exclusion function --- osu.Game/IO/Archives/ZipArchiveReader.cs | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/osu.Game/IO/Archives/ZipArchiveReader.cs b/osu.Game/IO/Archives/ZipArchiveReader.cs index 9033e7529d..35f38ea7e8 100644 --- a/osu.Game/IO/Archives/ZipArchiveReader.cs +++ b/osu.Game/IO/Archives/ZipArchiveReader.cs @@ -1,30 +1,16 @@ // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.IO; using System.Linq; +using osu.Framework.IO.Stores; using SharpCompress.Archives.Zip; -using SharpCompress.Common; namespace osu.Game.IO.Archives { public sealed class ZipArchiveReader : ArchiveReader { - /// <summary> - /// List of substrings that indicate a file should be ignored during the import process - /// (usually due to representing no useful data and being autogenerated by the OS). - /// </summary> - private static readonly string[] filename_ignore_list = - { - // Mac-specific - "__MACOSX", - ".DS_Store", - // Windows-specific - "Thumbs.db" - }; - private readonly Stream archiveStream; private readonly ZipArchive archive; @@ -58,9 +44,7 @@ namespace osu.Game.IO.Archives archiveStream.Dispose(); } - private static bool canBeIgnored(IEntry entry) => filename_ignore_list.Any(ignoredName => entry.Key.IndexOf(ignoredName, StringComparison.OrdinalIgnoreCase) >= 0); - - public override IEnumerable<string> Filenames => archive.Entries.Where(e => !canBeIgnored(e)).Select(e => e.Key).ToArray(); + public override IEnumerable<string> Filenames => archive.Entries.Select(e => e.Key).ExcludeSystemFileNames(); public override Stream GetUnderlyingStream() => archiveStream; } From 8fbe76b574471e3f2decbcf49bde704fd202c5eb Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan <huoyaoyuan@hotmail.com> Date: Wed, 30 Oct 2019 21:06:55 +0800 Subject: [PATCH 3702/5608] Use slnf for filtering platform. --- osu.Android.sln | 126 ------ osu.Android.sln.DotSettings | 834 ----------------------------------- osu.Android.slnf | 19 + osu.Desktop.slnf | 20 + osu.iOS.sln | 187 -------- osu.iOS.sln.DotSettings | 836 ------------------------------------ osu.iOS.slnf | 18 + osu.sln | 318 +++++++++++++- 8 files changed, 371 insertions(+), 1987 deletions(-) delete mode 100644 osu.Android.sln delete mode 100644 osu.Android.sln.DotSettings create mode 100644 osu.Android.slnf create mode 100644 osu.Desktop.slnf delete mode 100644 osu.iOS.sln delete mode 100644 osu.iOS.sln.DotSettings create mode 100644 osu.iOS.slnf diff --git a/osu.Android.sln b/osu.Android.sln deleted file mode 100644 index ebf2c55cb4..0000000000 --- a/osu.Android.sln +++ /dev/null @@ -1,126 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28516.95 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game", "osu.Game\osu.Game.csproj", "{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Osu", "osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj", "{C92A607B-1FDD-4954-9F92-03FF547D9080}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Catch", "osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj", "{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Taiko", "osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj", "{F167E17A-7DE6-4AF5-B920-A5112296C695}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Mania", "osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj", "{48F4582B-7687-4621-9CBE-5C24197CB536}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Android", "osu.Android\osu.Android.csproj", "{D1D5F9A8-B40B-40E6-B02F-482D03346D3D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch.Tests.Android", "osu.Game.Rulesets.Catch.Tests.Android\osu.Game.Rulesets.Catch.Tests.Android.csproj", "{C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania.Tests.Android", "osu.Game.Rulesets.Mania.Tests.Android\osu.Game.Rulesets.Mania.Tests.Android.csproj", "{531F1092-DB27-445D-AA33-2A77C7187C99}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests.Android", "osu.Game.Rulesets.Osu.Tests.Android\osu.Game.Rulesets.Osu.Tests.Android.csproj", "{90CAB706-39CB-4B93-9629-3218A6FF8E9B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tests.Android", "osu.Game.Rulesets.Taiko.Tests.Android\osu.Game.Rulesets.Taiko.Tests.Android.csproj", "{3701A0A1-8476-42C6-B5C4-D24129B4A484}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tests.Android", "osu.Game.Tests.Android\osu.Game.Tests.Android.csproj", "{5CC222DC-5716-4499-B897-DCBDDA4A5CF9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.Build.0 = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.Build.0 = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.Build.0 = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.Build.0 = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.Build.0 = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.ActiveCfg = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.Build.0 = Release|Any CPU - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.Build.0 = Release|Any CPU - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.Deploy.0 = Release|Any CPU - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.Build.0 = Release|Any CPU - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.Deploy.0 = Release|Any CPU - {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.Build.0 = Debug|Any CPU - {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.ActiveCfg = Release|Any CPU - {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.Build.0 = Release|Any CPU - {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.Deploy.0 = Release|Any CPU - {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.Build.0 = Release|Any CPU - {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.Deploy.0 = Release|Any CPU - {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.Build.0 = Release|Any CPU - {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.Deploy.0 = Release|Any CPU - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.Build.0 = Release|Any CPU - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.Deploy.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {671B0BEC-2403-45B0-9357-2C97CC517668} - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - Policies = $0 - $0.TextStylePolicy = $1 - $1.EolMarker = Windows - $1.inheritsSet = VisualStudio - $1.inheritsScope = text/plain - $1.scope = text/x-csharp - $0.CSharpFormattingPolicy = $2 - $2.IndentSwitchSection = True - $2.NewLinesForBracesInProperties = True - $2.NewLinesForBracesInAccessors = True - $2.NewLinesForBracesInAnonymousMethods = True - $2.NewLinesForBracesInControlBlocks = True - $2.NewLinesForBracesInAnonymousTypes = True - $2.NewLinesForBracesInObjectCollectionArrayInitializers = True - $2.NewLinesForBracesInLambdaExpressionBody = True - $2.NewLineForElse = True - $2.NewLineForCatch = True - $2.NewLineForFinally = True - $2.NewLineForMembersInObjectInit = True - $2.NewLineForMembersInAnonymousTypes = True - $2.NewLineForClausesInQuery = True - $2.SpacingAfterMethodDeclarationName = False - $2.SpaceAfterMethodCallName = False - $2.SpaceBeforeOpenSquareBracket = False - $2.inheritsSet = Mono - $2.inheritsScope = text/x-csharp - $2.scope = text/x-csharp - EndGlobalSection -EndGlobal diff --git a/osu.Android.sln.DotSettings b/osu.Android.sln.DotSettings deleted file mode 100644 index 5a97fc7518..0000000000 --- a/osu.Android.sln.DotSettings +++ /dev/null @@ -1,834 +0,0 @@ -<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> - <s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Efnt/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Emp3/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Epng/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ewav/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=2A66DD92_002DADB1_002D4994_002D89E2_002DC94E04ACDA0D_002Fd_003AMigrations/@EntryIndexedValue">ExplicitlyExcluded</s:String> - <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=D9A367C9_002D4C1A_002D489F_002D9B05_002DA0CEA2B53B58/@EntryIndexedValue">ExplicitlyExcluded</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/AnalysisEnabled/@EntryValue">SOLUTION</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeAccessorOwnerBody/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeModifiersOrder/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeRedundantParentheses/@EntryIndexedValue"></s:String> - <s:Boolean x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeRedundantParentheses/@EntryIndexRemoved">True</s:Boolean> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTypeMemberModifiers/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTypeModifiers/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AssignedValueIsNeverUsed/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AssignNullToNotNullAttribute/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AutoPropertyCanBeMadeGetOnly_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AutoPropertyCanBeMadeGetOnly_002ELocal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CanBeReplacedWithTryCastAndCheckForNull/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CheckForReferenceEqualityInstead_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CheckForReferenceEqualityInstead_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassNeverInstantiated_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassNeverInstantiated_002ELocal/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassWithVirtualMembersNeverInherited_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CollectionNeverQueried_002EGlobal/@EntryIndexedValue">SUGGESTION</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CollectionNeverQueried_002ELocal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CompareOfFloatsByEqualityOperator/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertClosureToMethodGroup/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfDoToWhile/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfStatementToConditionalTernaryExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfStatementToNullCoalescingExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfToOrExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertNullableToShortForm/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertPropertyToExpressionBody/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToAutoProperty/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToConstant_002ELocal/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToLambdaExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToLocalFunction/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToStaticClass/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=DoubleNegationOperator/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EmptyGeneralCatchClause/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EventNeverSubscribedTo_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EventNeverSubscribedTo_002ELocal/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=FieldCanBeMadeReadOnly_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=FieldCanBeMadeReadOnly_002ELocal/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ForCanBeConvertedToForeach/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ImpureMethodCallOnReadonlyValueField/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InconsistentNaming/@EntryIndexedValue">ERROR</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InheritdocConsiderUsage/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InlineOutVariableDeclaration/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InvertIf/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InvokeAsExtensionMethod/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=JoinDeclarationAndInitializer/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=JoinNullCheckWithUsage/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MemberCanBeMadeStatic_002ELocal/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MemberCanBePrivate_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MemberCanBePrivate_002ELocal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MemberCanBeProtected_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MergeCastWithTypeCheck/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MergeConditionalExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MergeSequentialChecks/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MethodSupportsCancellation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MoreSpecificForeachVariableTypeAvailable/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=NestedStringInterpolation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=NotAccessedField_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ParameterHidesMember/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ParameterOnlyUsedForPreconditionCheck_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ParameterOnlyUsedForPreconditionCheck_002ELocal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=PossibleMultipleEnumeration/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=PrivateVariableCanBeMadeReadonly/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=PublicConstructorInAbstractClass/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantArrayCreationExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantAttributeParentheses/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantAttributeUsageProperty/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantCaseLabel/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantCommaInAttributeList/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantCommaInEnumDeclaration/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantCommaInInitializer/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantEmptyObjectCreationArgumentList/@EntryIndexedValue">WARNING</s:String> - - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantExplicitParamsArrayCreation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantImmediateDelegateInvocation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantLambdaSignatureParentheses/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantUsingDirective/@EntryIndexedValue">ERROR</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantStringInterpolation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantVerbatimPrefix/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantVerbatimStringPrefix/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RemoveRedundantOrStatement_002EFalse/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RemoveRedundantOrStatement_002ETrue/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RemoveToList_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RemoveToList_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithFirstOrDefault_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithFirstOrDefault_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithFirstOrDefault_002E3/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithFirstOrDefault_002E4/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithLastOrDefault_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithLastOrDefault_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithLastOrDefault_002E3/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithLastOrDefault_002E4/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002E3/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EAny_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EAny_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ECount_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ECount_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EFirst_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EFirst_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EFirstOrDefault_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EFirstOrDefault_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ELast_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ELast_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ELastOrDefault_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ELastOrDefault_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ELongCount/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ESingle_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ESingle_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ESingleOrDefault_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ESingleOrDefault_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EWhere/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSimpleAssignment_002EFalse/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSimpleAssignment_002ETrue/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleAssignment_002EFalse/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleAssignment_002ETrue/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToAny/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToCount/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToFirst/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToFirstOrDefault/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToLast/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToLastOrDefault/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToSingle/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToSingleOrDefault/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleOrDefault_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleOrDefault_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleOrDefault_002E3/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleOrDefault_002E4/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FBuiltInTypes/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SwitchStatementMissingSomeCases/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=TooWideLocalVariableScope/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=TryCastAlwaysSucceeds/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnassignedField_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnnecessaryWhitespace/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedAutoPropertyAccessor_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMemberHierarchy_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMemberInSuper_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMember_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMember_002ELocal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMethodReturnValue_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMethodReturnValue_002ELocal/@EntryIndexedValue">HINT</s:String> - - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedParameter_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseCollectionCountProperty/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseFormatSpecifierInFormatString/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseFormatSpecifierInInterpolation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseNameofExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseNullPropagation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseObjectOrCollectionInitializer/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UsePatternMatching/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseStringInterpolation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=VariableCanBeMadeConst/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=VirtualMemberCallInConstructor/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=VirtualMemberNeverOverridden_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=VirtualMemberNeverOverridden_002ELocal/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=Code_0020Cleanup_0020_0028peppy_0029/@EntryIndexedValue"><?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile></s:String> - <s:String x:Key="/Default/CodeStyle/CodeCleanup/RecentlyUsedProfile/@EntryValue">Code Cleanup (peppy)</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_INTERNAL_MODIFIER/@EntryValue">Explicit</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/LOCAL_FUNCTION_BODY/@EntryValue">ExpressionBody</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/METHOD_OR_OPERATOR_BODY/@EntryValue">ExpressionBody</s:String> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/USE_HEURISTICS_FOR_BODY_STYLE/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ACCESSOR_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_LINQ_QUERY/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_FOR_STMT/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_PARAMETER/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTIPLE_DECLARATION/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTLINE_TYPE_PARAMETER_CONSTRAINS/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTLINE_TYPE_PARAMETER_LIST/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String> - <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BEFORE_BLOCK_STATEMENTS/@EntryValue">1</s:Int64> - <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BEFORE_CASE/@EntryValue">1</s:Int64> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">NEXT_LINE</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">MULTILINE</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">NEXT_LINE</s:String> - <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64> - <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/LINE_FEED_AT_FILE_END/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OTHER_BRACES/@EntryValue">NEXT_LINE</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CATCH_ON_NEW_LINE/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CONSTRUCTOR_INITIALIZER_ON_SAME_LINE/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ELSE_ON_NEW_LINE/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AROUND_MULTIPLICATIVE_OP/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_SIZEOF_PARENTHESES/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_TYPEOF_PARENTHESES/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHING_EMPTY_BRACES/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/STICK_COMMENT/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_DECLARATION_LPAR/@EntryValue">False</s:Boolean> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARRAY_INITIALIZER_STYLE/@EntryValue">CHOP_IF_LONG</s:String> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_BINARY_OPSIGN/@EntryValue">True</s:Boolean> - <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">200</s:Int64> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_OBJECT_AND_COLLECTION_INITIALIZER_STYLE/@EntryValue">CHOP_IF_LONG</s:String> - <s:Boolean x:Key="/Default/CodeStyle/EncapsulateField/MakeFieldPrivate/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/EncapsulateField/UseAutoProperty/@EntryValue">False</s:Boolean> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AABB/@EntryIndexedValue">AABB</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=API/@EntryIndexedValue">API</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BPM/@EntryIndexedValue">BPM</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GC/@EntryIndexedValue">GC</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GL/@EntryIndexedValue">GL</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GLSL/@EntryIndexedValue">GLSL</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HID/@EntryIndexedValue">HID</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HUD/@EntryIndexedValue">HUD</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IPC/@EntryIndexedValue">IPC</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LTRB/@EntryIndexedValue">LTRB</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MD/@EntryIndexedValue">MD5</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NS/@EntryIndexedValue">NS</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OS/@EntryIndexedValue">OS</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RGB/@EntryIndexedValue">RGB</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RNG/@EntryIndexedValue">RNG</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SHA/@EntryIndexedValue">SHA</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SRGB/@EntryIndexedValue">SRGB</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TK/@EntryIndexedValue">TK</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SS/@EntryIndexedValue">SS</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PP/@EntryIndexedValue">PP</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GMT/@EntryIndexedValue">GMT</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=QAT/@EntryIndexedValue">QAT</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BNG/@EntryIndexedValue">BNG</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UI/@EntryIndexedValue">UI</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=EnumMember/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeStyle/CSharpFileLayoutPatterns/Pattern/@EntryValue"><?xml version="1.0" encoding="utf-16"?> -<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> - <TypePattern DisplayName="COM interfaces or structs"> - <TypePattern.Match> - <Or> - <And> - <Kind Is="Interface" /> - <Or> - <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> - <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> - </Or> - </And> - <Kind Is="Struct" /> - </Or> - </TypePattern.Match> - </TypePattern> - <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> - <TypePattern.Match> - <And> - <Kind Is="Class" /> - <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> - </And> - </TypePattern.Match> - <Entry DisplayName="Setup/Teardown Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <Or> - <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="All other members" /> - <Entry Priority="100" DisplayName="Test Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <HasAttribute Name="NUnit.Framework.TestAttribute" /> - </And> - </Entry.Match> - <Entry.SortBy> - <Name /> - </Entry.SortBy> - </Entry> - </TypePattern> - <TypePattern DisplayName="Default Pattern"> - <Group DisplayName="Fields/Properties"> - <Group DisplayName="Public Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Public Properties"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Internal Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Internal Properties"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Protected Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Protected Properties"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Private Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Private Properties"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Constructor/Destructor"> - <Entry DisplayName="Ctor"> - <Entry.Match> - <Kind Is="Constructor" /> - </Entry.Match> - </Entry> - <Region Name="Disposal"> - <Entry DisplayName="Dtor"> - <Entry.Match> - <Kind Is="Destructor" /> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose()"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose(true)"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Virtual /> - <Override /> - </Or> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - </Region> - </Group> - <Group DisplayName="Methods"> - <Group DisplayName="Public"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Internal"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Protected"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Private"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - </Group> - </TypePattern> -</Patterns></s:String> - <s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. -See the LICENCE file in the repository root for full licence text. -</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=EnumMember/@EntryIndexedValue"><Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=LocalConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=LocalFunctions/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="_" Suffix="" Style="aaBb" /></Policy></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypeParameters/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=9d1af99b_002Dbefe_002D48a4_002D9eb3_002D661384e29869/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=9ffbe43b_002Dc610_002D411b_002D9839_002D1416a146d9b0/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a4c2df6c_002Db202_002D48d5_002Db077_002De678cb548c25/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=fd562728_002Dc23d_002D417f_002Da19f_002D9d854247fbea/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCLASS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCONSTRUCTOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FGLOBAL_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLABEL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLOCAL_005FCONSTRUCTOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLOCAL_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FOBJECT_005FPROPERTY_005FOF_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FPARAMETER/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FCLASS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM_005FMEMBER/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FINTERFACE/@EntryIndexedValue"><Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMIXED_005FENUM/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FEXPORTED/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FLOCAL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FTYPE_005FALIAS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FTYPE_005FPARAMETER/@EntryIndexedValue"><Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FHTML_005FCONTROL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FNAME/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FPREFIX/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=NAMESPACE_005FALIAS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FRESOURCE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Description/@EntryValue">o!f – Object Initializer: Anchor&Origin</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Field/=anchor/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Field/=anchor/Expression/@EntryValue">constant("Centre")</s:String> - <s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Field/=anchor/Order/@EntryValue">0</s:Int64> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Shortcut/@EntryValue">ofao</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Text/@EntryValue">Anchor = Anchor.$anchor$, -Origin = Anchor.$anchor$,</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Description/@EntryValue">o!f – InternalChildren = []</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Shortcut/@EntryValue">ofic</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Text/@EntryValue">InternalChildren = new Drawable[] -{ - $END$ -};</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Description/@EntryValue">o!f – new GridContainer { .. }</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Shortcut/@EntryValue">ofgc</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Text/@EntryValue">new GridContainer -{ - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { $END$ }, - new Drawable[] { } - } -};</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Description/@EntryValue">o!f – new FillFlowContainer { .. }</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Shortcut/@EntryValue">offf</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Text/@EntryValue">new FillFlowContainer -{ - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - $END$ - } -},</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Description/@EntryValue">o!f – new Container { .. }</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Shortcut/@EntryValue">ofcont</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Text/@EntryValue">new Container -{ - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - $END$ - } -},</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Description/@EntryValue">o!f – BackgroundDependencyLoader load()</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Shortcut/@EntryValue">ofbdl</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Text/@EntryValue">[BackgroundDependencyLoader] -private void load() -{ - $END$ -}</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Description/@EntryValue">o!f – new Box { .. }</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Shortcut/@EntryValue">ofbox</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Text/@EntryValue">new Box -{ - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, -},</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Description/@EntryValue">o!f – Children = []</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Shortcut/@EntryValue">ofc</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Text/@EntryValue">Children = new Drawable[] -{ - $END$ -};</s:String> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Beatmap/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=beatmaps/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=beatmap_0027s/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=bindable/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Catmull/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Drawables/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=gameplay/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=hitobjects/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=keymods/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Kiai/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Leaderboard/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Leaderboards/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Playfield/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=resampler/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=ruleset/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=rulesets/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Taiko/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Unranked/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> diff --git a/osu.Android.slnf b/osu.Android.slnf new file mode 100644 index 0000000000..7d90f97eb9 --- /dev/null +++ b/osu.Android.slnf @@ -0,0 +1,19 @@ +{ + "solution": { + "path": "osu.sln", + "projects": [ + "osu.Android\\osu.Android.csproj", + "osu.Game.Rulesets.Catch.Tests.Android\\osu.Game.Rulesets.Catch.Tests.Android.csproj", + "osu.Game.Rulesets.Catch\\osu.Game.Rulesets.Catch.csproj", + "osu.Game.Rulesets.Mania.Tests.Android\\osu.Game.Rulesets.Mania.Tests.Android.csproj", + "osu.Game.Rulesets.Mania\\osu.Game.Rulesets.Mania.csproj", + "osu.Game.Rulesets.Osu.Tests.Android\\osu.Game.Rulesets.Osu.Tests.Android.csproj", + "osu.Game.Rulesets.Osu\\osu.Game.Rulesets.Osu.csproj", + "osu.Game.Rulesets.Taiko.Tests.Android\\osu.Game.Rulesets.Taiko.Tests.Android.csproj", + "osu.Game.Rulesets.Taiko\\osu.Game.Rulesets.Taiko.csproj", + "osu.Game.Tests.Android\\osu.Game.Tests.Android.csproj", + "osu.Game.Tests\\osu.Game.Tests.csproj", + "osu.Game\\osu.Game.csproj" + ] + } +} \ No newline at end of file diff --git a/osu.Desktop.slnf b/osu.Desktop.slnf new file mode 100644 index 0000000000..e6b6446f72 --- /dev/null +++ b/osu.Desktop.slnf @@ -0,0 +1,20 @@ +{ + "solution": { + "path": "osu.sln", + "projects": [ + "osu.Desktop\\osu.Desktop.csproj", + "osu.Game.Rulesets.Catch.Tests\\osu.Game.Rulesets.Catch.Tests.csproj", + "osu.Game.Rulesets.Catch\\osu.Game.Rulesets.Catch.csproj", + "osu.Game.Rulesets.Mania.Tests\\osu.Game.Rulesets.Mania.Tests.csproj", + "osu.Game.Rulesets.Mania\\osu.Game.Rulesets.Mania.csproj", + "osu.Game.Rulesets.Osu.Tests\\osu.Game.Rulesets.Osu.Tests.csproj", + "osu.Game.Rulesets.Osu\\osu.Game.Rulesets.Osu.csproj", + "osu.Game.Rulesets.Taiko.Tests\\osu.Game.Rulesets.Taiko.Tests.csproj", + "osu.Game.Rulesets.Taiko\\osu.Game.Rulesets.Taiko.csproj", + "osu.Game.Tests\\osu.Game.Tests.csproj", + "osu.Game.Tournament.Tests\\osu.Game.Tournament.Tests.csproj", + "osu.Game.Tournament\\osu.Game.Tournament.csproj", + "osu.Game\\osu.Game.csproj" + ] + } +} \ No newline at end of file diff --git a/osu.iOS.sln b/osu.iOS.sln deleted file mode 100644 index 21d02d33ab..0000000000 --- a/osu.iOS.sln +++ /dev/null @@ -1,187 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2006 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game", "osu.Game\osu.Game.csproj", "{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu", "osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj", "{C92A607B-1FDD-4954-9F92-03FF547D9080}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch", "osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj", "{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko", "osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj", "{F167E17A-7DE6-4AF5-B920-A5112296C695}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania", "osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj", "{48F4582B-7687-4621-9CBE-5C24197CB536}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.iOS", "osu.iOS\osu.iOS.csproj", "{3F082D0B-A964-43D7-BDF7-C256D76A50D0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tests.iOS", "osu.Game.Tests.iOS\osu.Game.Tests.iOS.csproj", "{65FF8E19-6934-469B-B690-23C6D6E56A17}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tests.iOS", "osu.Game.Rulesets.Taiko.Tests.iOS\osu.Game.Rulesets.Taiko.Tests.iOS.csproj", "{7E408809-66AC-49D1-AF4D-98834F9B979A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests.iOS", "osu.Game.Rulesets.Osu.Tests.iOS\osu.Game.Rulesets.Osu.Tests.iOS.csproj", "{6653CA6F-DB06-4604-A3FD-762E25C2AF96}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania.Tests.iOS", "osu.Game.Rulesets.Mania.Tests.iOS\osu.Game.Rulesets.Mania.Tests.iOS.csproj", "{39FD990E-B6CE-4B2A-999F-BC008CF2C64C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch.Tests.iOS", "osu.Game.Rulesets.Catch.Tests.iOS\osu.Game.Rulesets.Catch.Tests.iOS.csproj", "{4004C7B7-1A62-43F1-9DF2-52450FA67E70}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - Debug|iPhoneSimulator = Debug|iPhoneSimulator - Release|iPhone = Release|iPhone - Release|iPhoneSimulator = Release|iPhoneSimulator - Debug|iPhone = Debug|iPhone - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.Build.0 = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhone.ActiveCfg = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhone.Build.0 = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhone.Build.0 = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.Build.0 = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|iPhone.ActiveCfg = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|iPhone.Build.0 = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|iPhone.Build.0 = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.Build.0 = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhone.ActiveCfg = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhone.Build.0 = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhone.Build.0 = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.Build.0 = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhone.ActiveCfg = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhone.Build.0 = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhone.Build.0 = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.Build.0 = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhone.ActiveCfg = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhone.Build.0 = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhone.Build.0 = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.Build.0 = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.ActiveCfg = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.Build.0 = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhone.ActiveCfg = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhone.Build.0 = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhone.Build.0 = Debug|Any CPU - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|Any CPU.ActiveCfg = Release|iPhone - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhone.ActiveCfg = Release|iPhone - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhone.Build.0 = Release|iPhone - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhone.ActiveCfg = Debug|iPhone - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhone.Build.0 = Debug|iPhone - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|Any CPU.ActiveCfg = Release|iPhone - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhone.ActiveCfg = Release|iPhone - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhone.Build.0 = Release|iPhone - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhone.ActiveCfg = Debug|iPhone - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhone.Build.0 = Debug|iPhone - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|Any CPU.ActiveCfg = Release|iPhone - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhone.ActiveCfg = Release|iPhone - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhone.Build.0 = Release|iPhone - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhone.ActiveCfg = Debug|iPhone - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhone.Build.0 = Debug|iPhone - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|Any CPU.ActiveCfg = Release|iPhone - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhone.ActiveCfg = Release|iPhone - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhone.Build.0 = Release|iPhone - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhone.ActiveCfg = Debug|iPhone - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhone.Build.0 = Debug|iPhone - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|Any CPU.ActiveCfg = Release|iPhone - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhone.ActiveCfg = Release|iPhone - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhone.Build.0 = Release|iPhone - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhone.ActiveCfg = Debug|iPhone - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhone.Build.0 = Debug|iPhone - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|Any CPU.ActiveCfg = Release|iPhone - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhone.ActiveCfg = Release|iPhone - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhone.Build.0 = Release|iPhone - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhone.ActiveCfg = Debug|iPhone - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhone.Build.0 = Debug|iPhone - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {671B0BEC-2403-45B0-9357-2C97CC517668} - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - Policies = $0 - $0.TextStylePolicy = $1 - $1.EolMarker = Windows - $1.scope = text/x-csharp - $1.FileWidth = 80 - $1.TabsToSpaces = True - $0.CSharpFormattingPolicy = $2 - $2.scope = text/x-csharp - EndGlobalSection -EndGlobal diff --git a/osu.iOS.sln.DotSettings b/osu.iOS.sln.DotSettings deleted file mode 100644 index 752b817910..0000000000 --- a/osu.iOS.sln.DotSettings +++ /dev/null @@ -1,836 +0,0 @@ -<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> - <s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Efnt/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Emp3/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Epng/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ewav/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=2A66DD92_002DADB1_002D4994_002D89E2_002DC94E04ACDA0D_002Fd_003AMigrations/@EntryIndexedValue">ExplicitlyExcluded</s:String> - <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=D9A367C9_002D4C1A_002D489F_002D9B05_002DA0CEA2B53B58/@EntryIndexedValue">ExplicitlyExcluded</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/AnalysisEnabled/@EntryValue">SOLUTION</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeAccessorOwnerBody/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeModifiersOrder/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeRedundantParentheses/@EntryIndexedValue"></s:String> - <s:Boolean x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeRedundantParentheses/@EntryIndexRemoved">True</s:Boolean> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTypeMemberModifiers/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTypeModifiers/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AssignedValueIsNeverUsed/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AssignNullToNotNullAttribute/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AutoPropertyCanBeMadeGetOnly_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AutoPropertyCanBeMadeGetOnly_002ELocal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CanBeReplacedWithTryCastAndCheckForNull/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CheckForReferenceEqualityInstead_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CheckForReferenceEqualityInstead_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassNeverInstantiated_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassNeverInstantiated_002ELocal/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassWithVirtualMembersNeverInherited_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CollectionNeverQueried_002EGlobal/@EntryIndexedValue">SUGGESTION</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CollectionNeverQueried_002ELocal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CompareOfFloatsByEqualityOperator/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertClosureToMethodGroup/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfDoToWhile/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfStatementToConditionalTernaryExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfStatementToNullCoalescingExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertIfToOrExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertNullableToShortForm/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertPropertyToExpressionBody/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToAutoProperty/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToConstant_002ELocal/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToLambdaExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToLocalFunction/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToStaticClass/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=DoubleNegationOperator/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EmptyGeneralCatchClause/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EventNeverSubscribedTo_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EventNeverSubscribedTo_002ELocal/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=FieldCanBeMadeReadOnly_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=FieldCanBeMadeReadOnly_002ELocal/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ForCanBeConvertedToForeach/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ImpureMethodCallOnReadonlyValueField/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InconsistentNaming/@EntryIndexedValue">ERROR</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InheritdocConsiderUsage/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InlineOutVariableDeclaration/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InvertIf/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InvokeAsExtensionMethod/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=JoinDeclarationAndInitializer/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=JoinNullCheckWithUsage/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MemberCanBeMadeStatic_002ELocal/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MemberCanBePrivate_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MemberCanBePrivate_002ELocal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MemberCanBeProtected_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MergeCastWithTypeCheck/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MergeConditionalExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MergeSequentialChecks/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MethodSupportsCancellation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MoreSpecificForeachVariableTypeAvailable/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=NestedStringInterpolation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=NotAccessedField_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ParameterHidesMember/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ParameterOnlyUsedForPreconditionCheck_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ParameterOnlyUsedForPreconditionCheck_002ELocal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=PossibleMultipleEnumeration/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=PrivateVariableCanBeMadeReadonly/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=PublicConstructorInAbstractClass/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantArrayCreationExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantAttributeParentheses/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantAttributeUsageProperty/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantCaseLabel/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantCommaInAttributeList/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantCommaInEnumDeclaration/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantCommaInInitializer/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantEmptyObjectCreationArgumentList/@EntryIndexedValue">WARNING</s:String> - - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantExplicitParamsArrayCreation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantImmediateDelegateInvocation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantLambdaSignatureParentheses/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantUsingDirective/@EntryIndexedValue">ERROR</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantStringInterpolation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantVerbatimPrefix/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantVerbatimStringPrefix/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RemoveRedundantOrStatement_002EFalse/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RemoveRedundantOrStatement_002ETrue/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RemoveToList_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RemoveToList_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithFirstOrDefault_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithFirstOrDefault_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithFirstOrDefault_002E3/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithFirstOrDefault_002E4/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithLastOrDefault_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithLastOrDefault_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithLastOrDefault_002E3/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithLastOrDefault_002E4/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002E3/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EAny_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EAny_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ECount_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ECount_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EFirst_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EFirst_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EFirstOrDefault_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EFirstOrDefault_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ELast_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ELast_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ELastOrDefault_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ELastOrDefault_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ELongCount/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ESingle_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ESingle_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ESingleOrDefault_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002ESingleOrDefault_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithOfType_002EWhere/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSimpleAssignment_002EFalse/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSimpleAssignment_002ETrue/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleAssignment_002EFalse/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleAssignment_002ETrue/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToAny/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToCount/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToFirst/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToFirstOrDefault/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToLast/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToLastOrDefault/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToSingle/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToSingleOrDefault/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleOrDefault_002E1/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleOrDefault_002E2/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleOrDefault_002E3/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleOrDefault_002E4/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FBuiltInTypes/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SwitchStatementMissingSomeCases/@EntryIndexedValue">DO_NOT_SHOW</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=TooWideLocalVariableScope/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=TryCastAlwaysSucceeds/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnassignedField_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnnecessaryWhitespace/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedAutoPropertyAccessor_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMemberHierarchy_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMemberInSuper_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMember_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMember_002ELocal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMethodReturnValue_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedMethodReturnValue_002ELocal/@EntryIndexedValue">HINT</s:String> - - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UnusedParameter_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseCollectionCountProperty/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseFormatSpecifierInFormatString/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseFormatSpecifierInInterpolation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseNameofExpression/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseNullPropagation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseObjectOrCollectionInitializer/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UsePatternMatching/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=UseStringInterpolation/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=VariableCanBeMadeConst/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=VirtualMemberCallInConstructor/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=VirtualMemberNeverOverridden_002EGlobal/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=VirtualMemberNeverOverridden_002ELocal/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=WrongIndentSize/@EntryIndexedValue">WARNING</s:String> - <s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=Code_0020Cleanup_0020_0028peppy_0029/@EntryIndexedValue"><?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile></s:String> - <s:String x:Key="/Default/CodeStyle/CodeCleanup/RecentlyUsedProfile/@EntryValue">Code Cleanup (peppy)</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_INTERNAL_MODIFIER/@EntryValue">Explicit</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/LOCAL_FUNCTION_BODY/@EntryValue">ExpressionBody</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/METHOD_OR_OPERATOR_BODY/@EntryValue">ExpressionBody</s:String> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/USE_HEURISTICS_FOR_BODY_STYLE/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ACCESSOR_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_LINQ_QUERY/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_FOR_STMT/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_PARAMETER/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTIPLE_DECLARATION/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTLINE_TYPE_PARAMETER_CONSTRAINS/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTLINE_TYPE_PARAMETER_LIST/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String> - <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BEFORE_BLOCK_STATEMENTS/@EntryValue">1</s:Int64> - <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BEFORE_CASE/@EntryValue">1</s:Int64> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">NEXT_LINE</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">MULTILINE</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">NEXT_LINE</s:String> - <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64> - <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/LINE_FEED_AT_FILE_END/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OTHER_BRACES/@EntryValue">NEXT_LINE</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CATCH_ON_NEW_LINE/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CONSTRUCTOR_INITIALIZER_ON_SAME_LINE/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ELSE_ON_NEW_LINE/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AROUND_MULTIPLICATIVE_OP/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_SIZEOF_PARENTHESES/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_TYPEOF_PARENTHESES/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHING_EMPTY_BRACES/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/STICK_COMMENT/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_DECLARATION_LPAR/@EntryValue">False</s:Boolean> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARRAY_INITIALIZER_STYLE/@EntryValue">CHOP_IF_LONG</s:String> - <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_BINARY_OPSIGN/@EntryValue">True</s:Boolean> - <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">200</s:Int64> - <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_OBJECT_AND_COLLECTION_INITIALIZER_STYLE/@EntryValue">CHOP_IF_LONG</s:String> - <s:Boolean x:Key="/Default/CodeStyle/EncapsulateField/MakeFieldPrivate/@EntryValue">False</s:Boolean> - <s:Boolean x:Key="/Default/CodeStyle/EncapsulateField/UseAutoProperty/@EntryValue">False</s:Boolean> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AABB/@EntryIndexedValue">AABB</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=API/@EntryIndexedValue">API</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BPM/@EntryIndexedValue">BPM</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GC/@EntryIndexedValue">GC</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GL/@EntryIndexedValue">GL</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GLSL/@EntryIndexedValue">GLSL</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HID/@EntryIndexedValue">HID</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HUD/@EntryIndexedValue">HUD</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IPC/@EntryIndexedValue">IPC</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LTRB/@EntryIndexedValue">LTRB</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MD/@EntryIndexedValue">MD5</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NS/@EntryIndexedValue">NS</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OS/@EntryIndexedValue">OS</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RGB/@EntryIndexedValue">RGB</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RNG/@EntryIndexedValue">RNG</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SHA/@EntryIndexedValue">SHA</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SRGB/@EntryIndexedValue">SRGB</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TK/@EntryIndexedValue">TK</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SS/@EntryIndexedValue">SS</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PP/@EntryIndexedValue">PP</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GMT/@EntryIndexedValue">GMT</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=QAT/@EntryIndexedValue">QAT</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BNG/@EntryIndexedValue">BNG</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UI/@EntryIndexedValue">UI</s:String> - <s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpNaming/ApplyAutoDetectedRules/@EntryValue">False</s:Boolean> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=EnumMember/@EntryIndexedValue">HINT</s:String> - <s:String x:Key="/Default/CodeStyle/CSharpFileLayoutPatterns/Pattern/@EntryValue"><?xml version="1.0" encoding="utf-16"?> -<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> - <TypePattern DisplayName="COM interfaces or structs"> - <TypePattern.Match> - <Or> - <And> - <Kind Is="Interface" /> - <Or> - <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> - <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> - </Or> - </And> - <Kind Is="Struct" /> - </Or> - </TypePattern.Match> - </TypePattern> - <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> - <TypePattern.Match> - <And> - <Kind Is="Class" /> - <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> - </And> - </TypePattern.Match> - <Entry DisplayName="Setup/Teardown Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <Or> - <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="All other members" /> - <Entry Priority="100" DisplayName="Test Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <HasAttribute Name="NUnit.Framework.TestAttribute" /> - </And> - </Entry.Match> - <Entry.SortBy> - <Name /> - </Entry.SortBy> - </Entry> - </TypePattern> - <TypePattern DisplayName="Default Pattern"> - <Group DisplayName="Fields/Properties"> - <Group DisplayName="Public Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Public Properties"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Internal Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Internal Properties"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Protected Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Protected Properties"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Private Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Private Properties"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Constructor/Destructor"> - <Entry DisplayName="Ctor"> - <Entry.Match> - <Kind Is="Constructor" /> - </Entry.Match> - </Entry> - <Region Name="Disposal"> - <Entry DisplayName="Dtor"> - <Entry.Match> - <Kind Is="Destructor" /> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose()"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose(true)"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Virtual /> - <Override /> - </Or> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - </Region> - </Group> - <Group DisplayName="Methods"> - <Group DisplayName="Public"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Internal"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Protected"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Private"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - </Group> - </TypePattern> -</Patterns></s:String> - <s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. -See the LICENCE file in the repository root for full licence text. -</s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=EnumMember/@EntryIndexedValue"><Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=LocalConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=LocalFunctions/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="_" Suffix="" Style="aaBb" /></Policy></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypeParameters/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=9d1af99b_002Dbefe_002D48a4_002D9eb3_002D661384e29869/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=9ffbe43b_002Dc610_002D411b_002D9839_002D1416a146d9b0/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a4c2df6c_002Db202_002D48d5_002Db077_002De678cb548c25/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=fd562728_002Dc23d_002D417f_002Da19f_002D9d854247fbea/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCLASS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCONSTRUCTOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FGLOBAL_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLABEL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLOCAL_005FCONSTRUCTOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLOCAL_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FOBJECT_005FPROPERTY_005FOF_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FPARAMETER/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FCLASS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM_005FMEMBER/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FINTERFACE/@EntryIndexedValue"><Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMIXED_005FENUM/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FEXPORTED/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FLOCAL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FTYPE_005FALIAS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FTYPE_005FPARAMETER/@EntryIndexedValue"><Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FHTML_005FCONTROL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FNAME/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FPREFIX/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=NAMESPACE_005FALIAS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FRESOURCE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Description/@EntryValue">o!f – Object Initializer: Anchor&Origin</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Field/=anchor/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Field/=anchor/Expression/@EntryValue">constant("Centre")</s:String> - <s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Field/=anchor/Order/@EntryValue">0</s:Int64> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Shortcut/@EntryValue">ofao</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=28A2A5FC43E07C488A4BC7430879479E/Text/@EntryValue">Anchor = Anchor.$anchor$, -Origin = Anchor.$anchor$,</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Description/@EntryValue">o!f – InternalChildren = []</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Shortcut/@EntryValue">ofic</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2A3ECBA387AF6D468F6ABDA35DED325A/Text/@EntryValue">InternalChildren = new Drawable[] -{ - $END$ -};</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Description/@EntryValue">o!f – new GridContainer { .. }</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Shortcut/@EntryValue">ofgc</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=62B70E4DCA5E284A9E383E16C13789C1/Text/@EntryValue">new GridContainer -{ - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { $END$ }, - new Drawable[] { } - } -};</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Description/@EntryValue">o!f – new FillFlowContainer { .. }</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Shortcut/@EntryValue">offf</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=72BD3C3DCA42C84DA1E71F1D05A903C4/Text/@EntryValue">new FillFlowContainer -{ - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - $END$ - } -},</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Description/@EntryValue">o!f – new Container { .. }</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Shortcut/@EntryValue">ofcont</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=750A3C67E083484FAEEA0ED2382181CC/Text/@EntryValue">new Container -{ - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - $END$ - } -},</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Description/@EntryValue">o!f – BackgroundDependencyLoader load()</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Shortcut/@EntryValue">ofbdl</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=78D9C2B1742FD449BD69CD18437E0C07/Text/@EntryValue">[BackgroundDependencyLoader] -private void load() -{ - $END$ -}</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Description/@EntryValue">o!f – new Box { .. }</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Shortcut/@EntryValue">ofbox</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=CC879477D8841A4CBD724C2DCD249435/Text/@EntryValue">new Box -{ - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, -},</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/@KeyIndexDefined">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Applicability/=Live/@EntryIndexedValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Description/@EntryValue">o!f – Children = []</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Reformat/@EntryValue">True</s:Boolean> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Shortcut/@EntryValue">ofc</s:String> - <s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/ShortenQualifiedReferences/@EntryValue">True</s:Boolean> - <s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=F5B3CB743153774F99FB9FCA0FC744EE/Text/@EntryValue">Children = new Drawable[] -{ - $END$ -};</s:String> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Beatmap/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=beatmaps/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=beatmap_0027s/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=bindable/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Catmull/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Drawables/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=gameplay/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=hitobjects/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=keymods/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Kiai/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Leaderboard/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Leaderboards/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Playfield/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=resampler/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=ruleset/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=rulesets/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Taiko/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=Unranked/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> diff --git a/osu.iOS.slnf b/osu.iOS.slnf new file mode 100644 index 0000000000..33a1497a54 --- /dev/null +++ b/osu.iOS.slnf @@ -0,0 +1,18 @@ +{ + "solution": { + "path": "osu.sln", + "projects": [ + "osu.Game.Rulesets.Catch.Tests.iOS\\osu.Game.Rulesets.Catch.Tests.iOS.csproj", + "osu.Game.Rulesets.Catch\\osu.Game.Rulesets.Catch.csproj", + "osu.Game.Rulesets.Mania.Tests.iOS\\osu.Game.Rulesets.Mania.Tests.iOS.csproj", + "osu.Game.Rulesets.Mania\\osu.Game.Rulesets.Mania.csproj", + "osu.Game.Rulesets.Osu.Tests.iOS\\osu.Game.Rulesets.Osu.Tests.iOS.csproj", + "osu.Game.Rulesets.Osu\\osu.Game.Rulesets.Osu.csproj", + "osu.Game.Rulesets.Taiko.Tests.iOS\\osu.Game.Rulesets.Taiko.Tests.iOS.csproj", + "osu.Game.Rulesets.Taiko\\osu.Game.Rulesets.Taiko.csproj", + "osu.Game.Tests.iOS\\osu.Game.Tests.iOS.csproj", + "osu.Game.Tests\\osu.Game.Tests.csproj", + "osu.Game\\osu.Game.csproj" + ] + } +} \ No newline at end of file diff --git a/osu.sln b/osu.sln index 688339fab5..12ea89aaad 100644 --- a/osu.sln +++ b/osu.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2006 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29424.173 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game", "osu.Game\osu.Game.csproj", "{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}" EndProject @@ -25,68 +25,378 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Taiko.Tes EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Osu.Tests", "osu.Game.Rulesets.Osu.Tests\osu.Game.Rulesets.Osu.Tests.csproj", "{6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament", "osu.Game.Tournament\osu.Game.Tournament.csproj", "{5672CA4D-1B37-425B-A118-A8DA26E78938}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Tournament", "osu.Game.Tournament\osu.Game.Tournament.csproj", "{5672CA4D-1B37-425B-A118-A8DA26E78938}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament.Tests", "osu.Game.Tournament.Tests\osu.Game.Tournament.Tests.csproj", "{5789E78D-38F9-4072-AB7B-978F34B2C17F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Tournament.Tests", "osu.Game.Tournament.Tests\osu.Game.Tournament.Tests.csproj", "{5789E78D-38F9-4072-AB7B-978F34B2C17F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.iOS", "osu.iOS\osu.iOS.csproj", "{3F082D0B-A964-43D7-BDF7-C256D76A50D0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tests.iOS", "osu.Game.Tests.iOS\osu.Game.Tests.iOS.csproj", "{65FF8E19-6934-469B-B690-23C6D6E56A17}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tests.iOS", "osu.Game.Rulesets.Taiko.Tests.iOS\osu.Game.Rulesets.Taiko.Tests.iOS.csproj", "{7E408809-66AC-49D1-AF4D-98834F9B979A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests.iOS", "osu.Game.Rulesets.Osu.Tests.iOS\osu.Game.Rulesets.Osu.Tests.iOS.csproj", "{6653CA6F-DB06-4604-A3FD-762E25C2AF96}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania.Tests.iOS", "osu.Game.Rulesets.Mania.Tests.iOS\osu.Game.Rulesets.Mania.Tests.iOS.csproj", "{39FD990E-B6CE-4B2A-999F-BC008CF2C64C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch.Tests.iOS", "osu.Game.Rulesets.Catch.Tests.iOS\osu.Game.Rulesets.Catch.Tests.iOS.csproj", "{4004C7B7-1A62-43F1-9DF2-52450FA67E70}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Android", "osu.Android\osu.Android.csproj", "{D1D5F9A8-B40B-40E6-B02F-482D03346D3D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch.Tests.Android", "osu.Game.Rulesets.Catch.Tests.Android\osu.Game.Rulesets.Catch.Tests.Android.csproj", "{C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania.Tests.Android", "osu.Game.Rulesets.Mania.Tests.Android\osu.Game.Rulesets.Mania.Tests.Android.csproj", "{531F1092-DB27-445D-AA33-2A77C7187C99}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests.Android", "osu.Game.Rulesets.Osu.Tests.Android\osu.Game.Rulesets.Osu.Tests.Android.csproj", "{90CAB706-39CB-4B93-9629-3218A6FF8E9B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tests.Android", "osu.Game.Rulesets.Taiko.Tests.Android\osu.Game.Rulesets.Taiko.Tests.Android.csproj", "{3701A0A1-8476-42C6-B5C4-D24129B4A484}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tests.Android", "osu.Game.Tests.Android\osu.Game.Tests.Android.csproj", "{5CC222DC-5716-4499-B897-DCBDDA4A5CF9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{10DF8F12-50FD-45D8-8A38-17BA764BF54D}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + osu.Android.props = osu.Android.props + osu.Game.props = osu.Game.props + osu.iOS.props = osu.iOS.props + osu.sln.DotSettings = osu.sln.DotSettings + osu.TestProject.props = osu.TestProject.props + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|iPhone = Debug|iPhone + Debug|iPhoneSimulator = Debug|iPhoneSimulator Release|Any CPU = Release|Any CPU + Release|iPhone = Release|iPhone + Release|iPhoneSimulator = Release|iPhoneSimulator EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhone.Build.0 = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.Build.0 = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhone.ActiveCfg = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhone.Build.0 = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhone.Build.0 = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.ActiveCfg = Release|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.Build.0 = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhone.ActiveCfg = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhone.Build.0 = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhone.Build.0 = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.ActiveCfg = Release|Any CPU {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.Build.0 = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhone.ActiveCfg = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhone.Build.0 = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhone.Build.0 = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.ActiveCfg = Release|Any CPU {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.Build.0 = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhone.ActiveCfg = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhone.Build.0 = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhone.Build.0 = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.ActiveCfg = Release|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.Build.0 = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhone.ActiveCfg = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhone.Build.0 = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|iPhone.Build.0 = Debug|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|Any CPU.ActiveCfg = Release|Any CPU {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|Any CPU.Build.0 = Release|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|iPhone.ActiveCfg = Release|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|iPhone.Build.0 = Release|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|Any CPU.Build.0 = Debug|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|iPhone.Build.0 = Debug|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|Any CPU.ActiveCfg = Release|Any CPU {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|Any CPU.Build.0 = Release|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|iPhone.ActiveCfg = Release|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|iPhone.Build.0 = Release|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|iPhone.Build.0 = Debug|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|Any CPU.ActiveCfg = Release|Any CPU {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|Any CPU.Build.0 = Release|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|iPhone.ActiveCfg = Release|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|iPhone.Build.0 = Release|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|iPhone.Build.0 = Debug|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|Any CPU.ActiveCfg = Release|Any CPU {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|Any CPU.Build.0 = Release|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|iPhone.ActiveCfg = Release|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|iPhone.Build.0 = Release|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|iPhone.Build.0 = Debug|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|Any CPU.ActiveCfg = Release|Any CPU {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|Any CPU.Build.0 = Release|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|iPhone.ActiveCfg = Release|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|iPhone.Build.0 = Release|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|iPhone.Build.0 = Debug|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|Any CPU.ActiveCfg = Release|Any CPU {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|Any CPU.Build.0 = Release|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|iPhone.ActiveCfg = Release|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|iPhone.Build.0 = Release|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|iPhone.Build.0 = Debug|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|Any CPU.ActiveCfg = Release|Any CPU {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|Any CPU.Build.0 = Release|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|iPhone.ActiveCfg = Release|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|iPhone.Build.0 = Release|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|iPhone.Build.0 = Debug|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.ActiveCfg = Release|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.Build.0 = Release|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|iPhone.ActiveCfg = Release|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|iPhone.Build.0 = Release|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhone.ActiveCfg = Debug|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhone.Build.0 = Debug|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|Any CPU.ActiveCfg = Release|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhone.ActiveCfg = Release|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhone.Build.0 = Release|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhone.ActiveCfg = Debug|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhone.Build.0 = Debug|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|Any CPU.ActiveCfg = Release|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhone.ActiveCfg = Release|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhone.Build.0 = Release|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhone.ActiveCfg = Debug|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhone.Build.0 = Debug|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|Any CPU.ActiveCfg = Release|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhone.ActiveCfg = Release|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhone.Build.0 = Release|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhone.ActiveCfg = Debug|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhone.Build.0 = Debug|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|Any CPU.ActiveCfg = Release|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhone.ActiveCfg = Release|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhone.Build.0 = Release|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhone.ActiveCfg = Debug|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhone.Build.0 = Debug|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|Any CPU.ActiveCfg = Release|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhone.ActiveCfg = Release|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhone.Build.0 = Release|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhone.ActiveCfg = Debug|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhone.Build.0 = Debug|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|Any CPU.ActiveCfg = Release|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhone.ActiveCfg = Release|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhone.Build.0 = Release|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|iPhone.Build.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.Build.0 = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.Deploy.0 = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|iPhone.ActiveCfg = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|iPhone.Build.0 = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|iPhone.Deploy.0 = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|iPhone.Build.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.Build.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.Deploy.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|iPhone.ActiveCfg = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|iPhone.Build.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|iPhone.Deploy.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.Build.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|iPhone.Build.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.ActiveCfg = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.Build.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.Deploy.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|iPhone.ActiveCfg = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|iPhone.Build.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|iPhone.Deploy.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|iPhone.Build.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.Build.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.Deploy.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|iPhone.ActiveCfg = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|iPhone.Build.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|iPhone.Deploy.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|iPhone.Build.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.Build.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.Deploy.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|iPhone.ActiveCfg = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|iPhone.Build.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|iPhone.Deploy.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|iPhone.Build.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.Build.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.Deploy.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhone.ActiveCfg = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhone.Build.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhone.Deploy.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 93fae7ad4d257e91c53ecbd9d0bb8a106111fcd4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan <huoyaoyuan@hotmail.com> Date: Wed, 30 Oct 2019 21:46:30 +0800 Subject: [PATCH 3703/5608] Remove meanless properties. --- .../osu.Game.Rulesets.Catch.Tests.iOS.csproj | 2 -- .../osu.Game.Rulesets.Mania.Tests.iOS.csproj | 2 -- .../osu.Game.Rulesets.Osu.Tests.iOS.csproj | 2 -- .../osu.Game.Rulesets.Taiko.Tests.iOS.csproj | 2 -- osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj | 2 -- osu.Game/osu.Game.csproj | 3 --- osu.TestProject.props | 3 --- osu.iOS/osu.iOS.csproj | 2 -- 8 files changed, 18 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj index 7990c35e09..708779986c 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> -<Import Project="..\packages\NUnit.3.11.0\build\NUnit.props" Condition="Exists('..\packages\NUnit.3.11.0\build\NUnit.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform> @@ -33,5 +32,4 @@ </ProjectReference> </ItemGroup> <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" /> - <Import Project="..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets')" /> </Project> \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj index 58c2e2aa5a..52e558931b 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> -<Import Project="..\packages\NUnit.3.11.0\build\NUnit.props" Condition="Exists('..\packages\NUnit.3.11.0\build\NUnit.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform> @@ -33,5 +32,4 @@ </ProjectReference> </ItemGroup> <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" /> - <Import Project="..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets')" /> </Project> \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj index c7787bd162..cacd035078 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> -<Import Project="..\packages\NUnit.3.11.0\build\NUnit.props" Condition="Exists('..\packages\NUnit.3.11.0\build\NUnit.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform> @@ -33,5 +32,4 @@ </ProjectReference> </ItemGroup> <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" /> - <Import Project="..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets')" /> </Project> \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj index 3e46bb89af..c20bd4fe02 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> -<Import Project="..\packages\NUnit.3.11.0\build\NUnit.props" Condition="Exists('..\packages\NUnit.3.11.0\build\NUnit.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform> @@ -33,5 +32,4 @@ </ProjectReference> </ItemGroup> <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" /> - <Import Project="..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets')" /> </Project> \ No newline at end of file diff --git a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj index 5c0713b895..583d188295 100644 --- a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj +++ b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="..\packages\NUnit.3.11.0\build\NUnit.props" Condition="Exists('..\packages\NUnit.3.11.0\build\NUnit.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform> @@ -48,5 +47,4 @@ <PackageReference Include="DeepEqual" Version="2.0.0" /> </ItemGroup> <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" /> - <Import Project="..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets')" /> </Project> \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0cb09d9b14..53678b96c7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -17,9 +17,6 @@ <copyright>Copyright (c) 2019 ppy Pty Ltd</copyright> <PackageTags>osu game</PackageTags> </PropertyGroup> - <ItemGroup Label="Service"> - <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> - </ItemGroup> <ItemGroup Label="Package References"> <PackageReference Include="Humanizer" Version="2.7.9" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" /> diff --git a/osu.TestProject.props b/osu.TestProject.props index a5c70f4edc..79f1cf49d1 100644 --- a/osu.TestProject.props +++ b/osu.TestProject.props @@ -3,9 +3,6 @@ <PropertyGroup> <StartupObject>osu.Game.Tests.VisualTestRunner</StartupObject> </PropertyGroup> - <ItemGroup Label="Service"> - <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> - </ItemGroup> <ItemGroup Label="Project References"> <ProjectReference Include="..\osu.Game\osu.Game.csproj" /> </ItemGroup> diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj index 19d1acf014..49d45e9031 100644 --- a/osu.iOS/osu.iOS.csproj +++ b/osu.iOS/osu.iOS.csproj @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="..\packages\NUnit.3.11.0\build\NUnit.props" Condition="Exists('..\packages\NUnit.3.11.0\build\NUnit.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform> @@ -77,5 +76,4 @@ <ImageAsset Include="Assets.xcassets\AppIcon.appiconset\iPhoneSpotlight3x.png" /> </ItemGroup> <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" /> - <Import Project="..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets')" /> </Project> \ No newline at end of file From 31595159beed1e0476c48ccf5b33ed3e222915ab Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan <huoyaoyuan@hotmail.com> Date: Wed, 30 Oct 2019 21:54:14 +0800 Subject: [PATCH 3704/5608] Normalize .props --- osu.Game.props => Directory.Build.props | 6 +++--- osu.Desktop/osu.Desktop.csproj | 1 - osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj | 1 - osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 1 - osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 1 - osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj | 1 - osu.Game.Tournament/osu.Game.Tournament.csproj | 1 - osu.Game/osu.Game.csproj | 1 - osu.TestProject.props | 5 ++--- 9 files changed, 5 insertions(+), 13 deletions(-) rename osu.Game.props => Directory.Build.props (79%) diff --git a/osu.Game.props b/Directory.Build.props similarity index 79% rename from osu.Game.props rename to Directory.Build.props index 1a3c0aec3e..4f7ad880b5 100644 --- a/osu.Game.props +++ b/Directory.Build.props @@ -1,13 +1,13 @@ <!-- Contains required properties for osu!framework projects. --> <Project> <PropertyGroup Label="C#"> - <LangVersion>7.2</LangVersion> + <LangVersion>7.3</LangVersion> </PropertyGroup> <PropertyGroup> - <ApplicationManifest>..\app.manifest</ApplicationManifest> + <ApplicationManifest>$(MSBuildThisFileDirectory)app.manifest</ApplicationManifest> </PropertyGroup> <ItemGroup Label="License"> - <None Include="..\osu.licenseheader"> + <None Include="$(MSBuildThisFileDirectory)osu.licenseheader"> <Link>osu.licenseheader</Link> </None> </ItemGroup> diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 2d1282634f..84881ce1d3 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -1,5 +1,4 @@ <Project Sdk="Microsoft.NET.Sdk"> - <Import Project="..\osu.Game.props" /> <PropertyGroup Label="Project"> <TargetFramework>netcoreapp3.0</TargetFramework> <OutputType>WinExe</OutputType> diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 883cac67d1..53d8651476 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -1,5 +1,4 @@ <Project Sdk="Microsoft.NET.Sdk"> - <Import Project="..\osu.Game.props" /> <PropertyGroup Label="Project"> <TargetFramework>netstandard2.0</TargetFramework> <OutputType>Library</OutputType> diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index a086da0565..061cced227 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -1,5 +1,4 @@ <Project Sdk="Microsoft.NET.Sdk"> - <Import Project="..\osu.Game.props" /> <PropertyGroup Label="Project"> <TargetFramework>netstandard2.0</TargetFramework> <OutputType>Library</OutputType> diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index b0ca314551..afd5e1f753 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -1,5 +1,4 @@ <Project Sdk="Microsoft.NET.Sdk"> - <Import Project="..\osu.Game.props" /> <PropertyGroup Label="Project"> <TargetFramework>netstandard2.0</TargetFramework> <OutputType>Library</OutputType> diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 656ebcc7c2..482f459564 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -1,5 +1,4 @@ <Project Sdk="Microsoft.NET.Sdk"> - <Import Project="..\osu.Game.props" /> <PropertyGroup Label="Project"> <TargetFramework>netstandard2.0</TargetFramework> <OutputType>Library</OutputType> diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index bddaff0a80..7e1f0eb2b3 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -1,5 +1,4 @@ <Project Sdk="Microsoft.NET.Sdk"> - <Import Project="..\osu.Game.props" /> <PropertyGroup Label="Project"> <TargetFramework>netstandard2.0</TargetFramework> <OutputType>Library</OutputType> diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 53678b96c7..717e3e7de8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -1,5 +1,4 @@ <Project Sdk="Microsoft.NET.Sdk"> - <Import Project="..\osu.Game.props" /> <PropertyGroup Label="Project"> <TargetFramework>netstandard2.0</TargetFramework> <OutputType>Library</OutputType> diff --git a/osu.TestProject.props b/osu.TestProject.props index 79f1cf49d1..7e87bc5414 100644 --- a/osu.TestProject.props +++ b/osu.TestProject.props @@ -1,13 +1,12 @@ <Project> - <Import Project="osu.Game.props" /> <PropertyGroup> <StartupObject>osu.Game.Tests.VisualTestRunner</StartupObject> </PropertyGroup> <ItemGroup Label="Project References"> - <ProjectReference Include="..\osu.Game\osu.Game.csproj" /> + <ProjectReference Include="$(MSBuildThisFileDirectory)osu.Game\osu.Game.csproj" /> </ItemGroup> <ItemGroup> - <Compile Include="..\osu.Game\Tests\VisualTestRunner.cs"> + <Compile Include="$(MSBuildThisFileDirectory)osu.Game\Tests\VisualTestRunner.cs"> <Link>VisualTestRunner.cs</Link> </Compile> </ItemGroup> From 990227827731a203e5091844f7993a077b91bd6e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan <huoyaoyuan@hotmail.com> Date: Wed, 30 Oct 2019 22:28:10 +0800 Subject: [PATCH 3705/5608] Merge props orthogonally. --- osu.Android.props | 27 ++++-------- osu.iOS.props | 105 ++++++++++++++-------------------------------- 2 files changed, 41 insertions(+), 91 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 8b31be3f12..26a80660ca 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -1,13 +1,10 @@ <Project> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> +<PropertyGroup> <OutputPath>bin\$(Configuration)</OutputPath> <WarningLevel>4</WarningLevel> <SchemaVersion>2.0</SchemaVersion> <BundleAssemblies>false</BundleAssemblies> <AotAssemblies>false</AotAssemblies> - <LangVersion>default</LangVersion> <OutputType>Library</OutputType> <FileAlignment>512</FileAlignment> <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies> @@ -15,37 +12,31 @@ <AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType> <TargetFrameworkVersion>v9.0</TargetFrameworkVersion> <AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis> + <AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent> + <MandroidI18n>cjk,mideast,other,rare,west</MandroidI18n> + <AndroidLinkMode>SdkOnly</AndroidLinkMode> + <ErrorReport>prompt</ErrorReport> </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <PropertyGroup Condition="'$(Configuration)' == 'Debug'"> <DebugSymbols>True</DebugSymbols> <DebugType>portable</DebugType> <Optimize>False</Optimize> <DefineConstants>DEBUG;TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> <EnableLLVM>false</EnableLLVM> <AndroidManagedSymbols>false</AndroidManagedSymbols> - <AndroidLinkMode>SdkOnly</AndroidLinkMode> <AndroidUseSharedRuntime>true</AndroidUseSharedRuntime> <EmbedAssembliesIntoApk>false</EmbedAssembliesIntoApk> - <MandroidI18n>cjk,mideast,other,rare,west</MandroidI18n> - <AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent> - <AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <PropertyGroup Condition="'$(Configuration)' == 'Release'"> <DebugSymbols>false</DebugSymbols> <DebugType>None</DebugType> <Optimize>True</Optimize> - <ErrorReport>prompt</ErrorReport> <EnableLLVM>true</EnableLLVM> <AndroidManagedSymbols>false</AndroidManagedSymbols> - <AndroidLinkMode>SdkOnly</AndroidLinkMode> <AndroidUseSharedRuntime>False</AndroidUseSharedRuntime> <EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk> - <MandroidI18n>cjk,mideast,other,rare,west</MandroidI18n> - <AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent> - <AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis> - <AllowUnsafeBlocks>true</AllowUnsafeBlocks> </PropertyGroup> <ItemGroup> <None Include="$(MSBuildThisFileDirectory)\osu.licenseheader"> diff --git a/osu.iOS.props b/osu.iOS.props index 719aced705..8079022ca0 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -5,91 +5,50 @@ <RestoreProjectStyle>PackageReference</RestoreProjectStyle> <DefaultMtouchExtraArgs>--nolinkaway</DefaultMtouchExtraArgs> <DefaultMtouchGccFlags>-lstdc++ -lbz2 -framework AudioToolbox -framework AVFoundation -framework CoreMedia -framework VideoToolbox -framework SystemConfiguration -framework CFNetwork -framework Accelerate</DefaultMtouchGccFlags> + <OutputPath>bin\$(Platform)\$(Configuration)</OutputPath> + <MtouchI18n>cjk,mideast,other,rare,west</MtouchI18n> + <OptimizePNGs>false</OptimizePNGs> + <MtouchExtraArgs>$(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)"</MtouchExtraArgs> + <MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler> + <MtouchVerbosity></MtouchVerbosity> + <CodesignKey>iPhone Developer</CodesignKey> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)' == 'Debug'"> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <DefineConstants>DEBUG;ENABLE_TEST_CLOUD;</DefineConstants> + <MtouchDebug>true</MtouchDebug> + <MtouchNoSymbolStrip>true</MtouchNoSymbolStrip> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)' == 'Release'"> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + </PropertyGroup> + <PropertyGroup Condition="'$(Platform)' == 'iPhoneSimulator'"> + <MtouchArch>x86_64</MtouchArch> + <MtouchLink>None</MtouchLink> + </PropertyGroup> + <PropertyGroup Condition="'$(Platform)' == 'iPhone'"> + <MtouchFloat32>true</MtouchFloat32> + <MtouchLink>SdkOnly</MtouchLink> + <MtouchArch>ARM64</MtouchArch> + <CodesignEntitlements>Entitlements.plist</CodesignEntitlements> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' "> - <DebugSymbols>true</DebugSymbols> - <DebugType>full</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\iPhoneSimulator\Debug</OutputPath> - <DefineConstants>DEBUG;ENABLE_TEST_CLOUD;</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <CodesignKey>iPhone Developer</CodesignKey> - <MtouchDebug>true</MtouchDebug> - <MtouchNoSymbolStrip>true</MtouchNoSymbolStrip> <MtouchFastDev>true</MtouchFastDev> <IOSDebuggerPort>25823</IOSDebuggerPort> - <MtouchLink>None</MtouchLink> - <MtouchArch>x86_64</MtouchArch> - <MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler> <DeviceSpecificBuild>false</DeviceSpecificBuild> - <MtouchVerbosity></MtouchVerbosity> - <LangVersion>Default</LangVersion> - <MtouchExtraArgs>$(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)"</MtouchExtraArgs> - <OptimizePNGs>false</OptimizePNGs> - <MtouchI18n>cjk,mideast,other,rare,west</MtouchI18n> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' "> - <DebugType>pdbonly</DebugType> - <Optimize>true</Optimize> - <OutputPath>bin\iPhone\Release</OutputPath> - <DefineConstants></DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <CodesignKey>iPhone Distribution</CodesignKey> - <MtouchUseLlvm>true</MtouchUseLlvm> - <MtouchFloat32>true</MtouchFloat32> - <CodesignEntitlements>Entitlements.plist</CodesignEntitlements> - <MtouchLink>SdkOnly</MtouchLink> - <MtouchArch>ARM64</MtouchArch> - <MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler> - <MtouchVerbosity></MtouchVerbosity> - <LangVersion>Default</LangVersion> - <MtouchExtraArgs>$(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)"</MtouchExtraArgs> - <OptimizePNGs>false</OptimizePNGs> - <MtouchI18n>cjk,mideast,other,rare,west</MtouchI18n> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' "> - <DebugType>pdbonly</DebugType> - <Optimize>true</Optimize> - <OutputPath>bin\iPhoneSimulator\Release</OutputPath> - <DefineConstants></DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <CodesignKey>iPhone Developer</CodesignKey> <MtouchNoSymbolStrip>true</MtouchNoSymbolStrip> - <MtouchLink>None</MtouchLink> - <MtouchArch>x86_64</MtouchArch> - <MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler> - <MtouchVerbosity></MtouchVerbosity> - <LangVersion>Default</LangVersion> - <MtouchExtraArgs>$(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)"</MtouchExtraArgs> - <OptimizePNGs>false</OptimizePNGs> - <MtouchI18n>cjk,mideast,other,rare,west</MtouchI18n> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' "> - <DebugSymbols>true</DebugSymbols> - <DebugType>full</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\iPhone\Debug</OutputPath> - <DefineConstants>DEBUG;ENABLE_TEST_CLOUD;</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <CodesignKey>iPhone Developer</CodesignKey> <DeviceSpecificBuild>true</DeviceSpecificBuild> - <MtouchDebug>true</MtouchDebug> - <MtouchNoSymbolStrip>true</MtouchNoSymbolStrip> - <MtouchFloat32>true</MtouchFloat32> - <CodesignEntitlements>Entitlements.plist</CodesignEntitlements> <IOSDebuggerPort>28126</IOSDebuggerPort> - <MtouchLink>SdkOnly</MtouchLink> - <MtouchArch>ARM64</MtouchArch> - <MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler> - <MtouchVerbosity></MtouchVerbosity> - <LangVersion>Default</LangVersion> - <MtouchExtraArgs>$(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)"</MtouchExtraArgs> - <OptimizePNGs>false</OptimizePNGs> - <MtouchI18n>cjk,mideast,other,rare,west</MtouchI18n> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' "> + <MtouchUseLlvm>true</MtouchUseLlvm> </PropertyGroup> <ItemGroup> <NativeReference Include="$(OutputPath)\libbass.a;$(OutputPath)\libbass_fx.a"> From 47e3498b7149920e3b32367289cd96424cca2806 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan <huoyaoyuan@hotmail.com> Date: Wed, 30 Oct 2019 22:42:25 +0800 Subject: [PATCH 3706/5608] Use cake as local tool and builds for slnf. --- .config/dotnet-tools.json | 12 ++++++++++++ build.ps1 | 2 +- build.sh | 2 +- build/Desktop.proj | 17 +++++++++++++++++ build/build.cake | 7 ++++--- global.json | 5 +++++ osu.sln | 1 + 7 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 .config/dotnet-tools.json create mode 100644 build/Desktop.proj create mode 100644 global.json diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000000..1b70c949eb --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "cake.tool": { + "version": "0.35.0", + "commands": [ + "dotnet-cake" + ] + } + } +} \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index 2dbd10a150..4b3b1f717a 100755 --- a/build.ps1 +++ b/build.ps1 @@ -21,7 +21,7 @@ if ($DryRun) { $cakeArguments += "-dryrun" } if ($Experimental) { $cakeArguments += "-experimental" } $cakeArguments += $ScriptArgs -dotnet tool install Cake.Tool --global --version 0.35.0 +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 index ac6bd877a6..2c22f08574 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,5 @@ echo "Installing Cake.Tool..." -dotnet tool install Cake.Tool --global --version 0.35.0 +dotnet tool restore # Parse arguments. CAKE_ARGUMENTS=() diff --git a/build/Desktop.proj b/build/Desktop.proj new file mode 100644 index 0000000000..b1c6b065e8 --- /dev/null +++ b/build/Desktop.proj @@ -0,0 +1,17 @@ +<Project Sdk="Microsoft.Build.Traversal"> + <ItemGroup> + <ProjectReference Include="..\osu.Desktop\osu.Desktop.csproj" /> + <ProjectReference Include="..\osu.Game.Rulesets.Catch.Tests\osu.Game.Rulesets.Catch.Tests.csproj" /> + <ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" /> + <ProjectReference Include="..\osu.Game.Rulesets.Mania.Tests\osu.Game.Rulesets.Mania.Tests.csproj" /> + <ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" /> + <ProjectReference Include="..\osu.Game.Rulesets.Osu.Tests\osu.Game.Rulesets.Osu.Tests.csproj" /> + <ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" /> + <ProjectReference Include="..\osu.Game.Rulesets.Taiko.Tests\osu.Game.Rulesets.Taiko.Tests.csproj" /> + <ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" /> + <ProjectReference Include="..\osu.Game.Tests\osu.Game.Tests.csproj" /> + <ProjectReference Include="..\osu.Game.Tournament.Tests\osu.Game.Tournament.Tests.csproj" /> + <ProjectReference Include="..\osu.Game.Tournament\osu.Game.Tournament.csproj" /> + <ProjectReference Include="..\osu.Game\osu.Game.csproj" /> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/build/build.cake b/build/build.cake index cfdfebee61..389ff4829d 100644 --- a/build/build.cake +++ b/build/build.cake @@ -11,7 +11,8 @@ var target = Argument("target", "Build"); var configuration = Argument("configuration", "Release"); var rootDirectory = new DirectoryPath(".."); -var solution = rootDirectory.CombineWithFilePath("osu.sln"); +var desktopBuilds = rootDirectory.CombineWithFilePath("build/Desktop.proj"); +var desktopSlnf = rootDirectory.CombineWithFilePath("osu.Desktop.slnf"); /////////////////////////////////////////////////////////////////////////////// // TASKS @@ -19,7 +20,7 @@ var solution = rootDirectory.CombineWithFilePath("osu.sln"); Task("Compile") .Does(() => { - DotNetCoreBuild(solution.FullPath, new DotNetCoreBuildSettings { + DotNetCoreBuild(desktopBuilds.FullPath, new DotNetCoreBuildSettings { Configuration = configuration, }); }); @@ -41,7 +42,7 @@ Task("InspectCode") .WithCriteria(IsRunningOnWindows()) .IsDependentOn("Compile") .Does(() => { - InspectCode(solution, new InspectCodeSettings { + InspectCode(desktopSlnf, new InspectCodeSettings { CachesHome = "inspectcode", OutputFile = "inspectcodereport.xml", }); diff --git a/global.json b/global.json new file mode 100644 index 0000000000..d8b8d14c36 --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "msbuild-sdks": { + "Microsoft.Build.Traversal": "2.0.19" + } +} \ No newline at end of file diff --git a/osu.sln b/osu.sln index 12ea89aaad..1baf62da15 100644 --- a/osu.sln +++ b/osu.sln @@ -56,6 +56,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{10DF8F12-50FD-45D8-8A38-17BA764BF54D}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig + global.json = global.json osu.Android.props = osu.Android.props osu.Game.props = osu.Game.props osu.iOS.props = osu.iOS.props From bcf8e3a9d473856d20d7c25141da7c4754d18a1d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan <huoyaoyuan@hotmail.com> Date: Wed, 30 Oct 2019 22:56:33 +0800 Subject: [PATCH 3707/5608] Remove redundant properties from desktop projects. While OutputType=Library maybe doubtful, PlatformTarget=AnyCPU should be clearly the default. --- Directory.Build.props | 12 ++++++++++-- osu.Desktop/osu.Desktop.csproj | 3 +-- .../osu.Game.Rulesets.Catch.csproj | 1 - .../osu.Game.Rulesets.Mania.csproj | 1 - osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 1 - .../osu.Game.Rulesets.Taiko.csproj | 1 - osu.Game.Tournament/osu.Game.Tournament.csproj | 1 - osu.Game/osu.Game.csproj | 8 -------- osu.sln | 2 +- 9 files changed, 12 insertions(+), 18 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 4f7ad880b5..76f1ccc0ca 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -15,10 +15,18 @@ <EmbeddedResource Include="Resources\**\*.*" /> </ItemGroup> <PropertyGroup Label="Project"> - <Company>ppy Pty Ltd</Company> - <Copyright>Copyright (c) 2019 ppy Pty Ltd</Copyright> <!-- DeepEqual is not netstandard-compatible. This is fine since we run tests with .NET Framework anyway. This is required due to https://github.com/NuGet/Home/issues/5740 --> <NoWarn>NU1701</NoWarn> </PropertyGroup> + <PropertyGroup Label="Nuget"> + <Authors>ppy Pty Ltd</Authors> + <PackageLicenseUrl>https://github.com/ppy/osu/blob/master/LICENCE.md</PackageLicenseUrl> + <PackageProjectUrl>https://github.com/ppy/osu</PackageProjectUrl> + <RepositoryUrl>https://github.com/ppy/osu</RepositoryUrl> + <PackageReleaseNotes>Automated release.</PackageReleaseNotes> + <Company>ppy Pty Ltd</Company> + <Copyright>Copyright (c) 2019 ppy Pty Ltd</Copyright> + <PackageTags>osu game</PackageTags> + </PropertyGroup> </Project> \ No newline at end of file diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 84881ce1d3..453cf6f94d 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -2,7 +2,6 @@ <PropertyGroup Label="Project"> <TargetFramework>netcoreapp3.0</TargetFramework> <OutputType>WinExe</OutputType> - <PlatformTarget>AnyCPU</PlatformTarget> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> <Description>click the circles. to the beat.</Description> <AssemblyName>osu!</AssemblyName> @@ -22,13 +21,13 @@ <ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" /> <ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" /> <ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" /> - <PackageReference Include="Microsoft.Win32.Registry" Version="4.6.0" /> </ItemGroup> <ItemGroup Label="Package References"> <PackageReference Include="System.IO.Packaging" Version="4.6.0" /> <PackageReference Include="ppy.squirrel.windows" Version="1.9.0.4" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.6" /> + <PackageReference Include="Microsoft.Win32.Registry" Version="4.6.0" /> </ItemGroup> <ItemGroup Label="Resources"> <EmbeddedResource Include="lazer.ico" /> diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 53d8651476..f24cf1def9 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -2,7 +2,6 @@ <PropertyGroup Label="Project"> <TargetFramework>netstandard2.0</TargetFramework> <OutputType>Library</OutputType> - <PlatformTarget>AnyCPU</PlatformTarget> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> <Description>catch the fruit. to the beat.</Description> </PropertyGroup> diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 061cced227..0af200d19b 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -2,7 +2,6 @@ <PropertyGroup Label="Project"> <TargetFramework>netstandard2.0</TargetFramework> <OutputType>Library</OutputType> - <PlatformTarget>AnyCPU</PlatformTarget> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> <Description>smash the keys. to the beat.</Description> </PropertyGroup> diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index afd5e1f753..fb3fe8808d 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -2,7 +2,6 @@ <PropertyGroup Label="Project"> <TargetFramework>netstandard2.0</TargetFramework> <OutputType>Library</OutputType> - <PlatformTarget>AnyCPU</PlatformTarget> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> <Description>click the circles. to the beat.</Description> </PropertyGroup> diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 482f459564..0a2b189c3a 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -2,7 +2,6 @@ <PropertyGroup Label="Project"> <TargetFramework>netstandard2.0</TargetFramework> <OutputType>Library</OutputType> - <PlatformTarget>AnyCPU</PlatformTarget> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> <Description>bash the drum. to the beat.</Description> </PropertyGroup> diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index 7e1f0eb2b3..f5306facaf 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -2,7 +2,6 @@ <PropertyGroup Label="Project"> <TargetFramework>netstandard2.0</TargetFramework> <OutputType>Library</OutputType> - <PlatformTarget>AnyCPU</PlatformTarget> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> <Description>tools for tournaments.</Description> </PropertyGroup> diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 717e3e7de8..fce50c43d2 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -2,19 +2,11 @@ <PropertyGroup Label="Project"> <TargetFramework>netstandard2.0</TargetFramework> <OutputType>Library</OutputType> - <PlatformTarget>AnyCPU</PlatformTarget> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> </PropertyGroup> <PropertyGroup Label="Nuget"> <Title>osu! ppy.osu.Game - ppy Pty Ltd - https://github.com/ppy/osu/blob/master/LICENCE.md - https://github.com/ppy/osu - https://github.com/ppy/osu - Automated release. - Copyright (c) 2019 ppy Pty Ltd - osu game diff --git a/osu.sln b/osu.sln index 1baf62da15..1f4faae6b9 100644 --- a/osu.sln +++ b/osu.sln @@ -56,9 +56,9 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{10DF8F12-50FD-45D8-8A38-17BA764BF54D}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig + Directory.Build.props = Directory.Build.props global.json = global.json osu.Android.props = osu.Android.props - osu.Game.props = osu.Game.props osu.iOS.props = osu.iOS.props osu.sln.DotSettings = osu.sln.DotSettings osu.TestProject.props = osu.TestProject.props From 847cf8639fa87e505f47154134c0f8f7b1751cfa Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 22:58:23 +0800 Subject: [PATCH 3708/5608] Move to VS2019 stable for CI. --- appveyor.yml | 2 +- appveyor_deploy.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index f59c0b162d..f911d67c6e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ clone_depth: 1 version: '{branch}-{build}' -image: Visual Studio 2019 Preview +image: Visual Studio 2019 test: off build_script: - cmd: PowerShell -Version 2.0 .\build.ps1 diff --git a/appveyor_deploy.yml b/appveyor_deploy.yml index 13635b943c..fb7825b31d 100644 --- a/appveyor_deploy.yml +++ b/appveyor_deploy.yml @@ -1,6 +1,6 @@ clone_depth: 1 version: '{build}' -image: Visual Studio 2019 Preview +image: Visual Studio 2019 test: off skip_non_tags: true build_script: From c95052b10fc6f4707bebf3587e23ee938d10fb60 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 23:03:02 +0800 Subject: [PATCH 3709/5608] Resolve package downgrade and VS claims for iOS. --- osu.iOS.props | 12 +------ osu.iOS/osu.iOS.csproj | 80 +++++++++++++++++++++++++++++++----------- 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/osu.iOS.props b/osu.iOS.props index 8079022ca0..55f1317a58 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -12,6 +12,7 @@ NSUrlSessionHandler iPhone Developer + true true @@ -68,21 +69,10 @@ - - - - - - - - - - - diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj index 49d45e9031..378ac231c2 100644 --- a/osu.iOS/osu.iOS.csproj +++ b/osu.iOS/osu.iOS.csproj @@ -54,26 +54,66 @@ - - - - - - - - - - - - - - - - - - - - + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + \ No newline at end of file From e57e9a3817094fb8788f1f5a29af0fb6b483e8d3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 23:07:22 +0800 Subject: [PATCH 3710/5608] Update VSCode restore instructions. Use slnf when dotnet.exe knows it. --- .vscode/tasks.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 70e620bca2..04ff7c1bea 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -100,7 +100,7 @@ "command": "dotnet", "args": [ "restore", - "osu.sln" + "build/Desktop.proj" ], "problemMatcher": [] } From 3ad0369d7b77b6890ecfc69e32aef219aff8d138 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 23:09:08 +0800 Subject: [PATCH 3711/5608] Resolve new diagnostics in C# 7.3 --- osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs | 2 +- osu.Game/Updater/SimpleUpdateManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 3a14b6d9c2..fbf0435953 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -195,7 +195,7 @@ namespace osu.Game.Tournament.Screens.Drawings } } - writeOp = writeOp?.ContinueWith(t => { writeAction(); }) ?? Task.Run((Action)writeAction); + writeOp = writeOp?.ContinueWith(t => { writeAction(); }) ?? Task.Run(writeAction); } private void reloadTeams() diff --git a/osu.Game/Updater/SimpleUpdateManager.cs b/osu.Game/Updater/SimpleUpdateManager.cs index 4789ac94d2..f76cba7f41 100644 --- a/osu.Game/Updater/SimpleUpdateManager.cs +++ b/osu.Game/Updater/SimpleUpdateManager.cs @@ -29,7 +29,7 @@ namespace osu.Game.Updater version = game.Version; if (game.IsDeployedBuild) - Schedule(() => Task.Run(() => checkForUpdateAsync())); + Schedule(() => Task.Run(checkForUpdateAsync)); } private async void checkForUpdateAsync() From b0414c105f966f255fe25d4cbd18116b050b1ef6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 23:16:57 +0800 Subject: [PATCH 3712/5608] Copy parts of DotSettings from framework. --- osu.sln.DotSettings | 830 ++++++++++++++++++++++---------------------- 1 file changed, 421 insertions(+), 409 deletions(-) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index ed162eed6e..0a65fad9df 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -125,6 +125,7 @@ WARNING WARNING WARNING + WARNING WARNING WARNING ERROR @@ -201,6 +202,7 @@ HINT HINT + HINT WARNING WARNING WARNING @@ -271,10 +273,13 @@ GC GL GLSL + 2D + 3D HID HUD ID IL + IOS IP IPC JIT @@ -286,399 +291,400 @@ RGB RNG SHA + RGB SRGB TK - SS - PP - GMT - QAT - BNG + SS + PP + GMT + QAT + BNG UI False HINT <?xml version="1.0" encoding="utf-16"?> <Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> - <TypePattern DisplayName="COM interfaces or structs"> - <TypePattern.Match> - <Or> - <And> - <Kind Is="Interface" /> - <Or> - <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> - <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> - </Or> - </And> - <Kind Is="Struct" /> - </Or> - </TypePattern.Match> - </TypePattern> - <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> - <TypePattern.Match> - <And> - <Kind Is="Class" /> - <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> - </And> - </TypePattern.Match> - <Entry DisplayName="Setup/Teardown Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <Or> - <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="All other members" /> - <Entry Priority="100" DisplayName="Test Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <HasAttribute Name="NUnit.Framework.TestAttribute" /> - </And> - </Entry.Match> - <Entry.SortBy> - <Name /> - </Entry.SortBy> - </Entry> - </TypePattern> - <TypePattern DisplayName="Default Pattern"> - <Group DisplayName="Fields/Properties"> - <Group DisplayName="Public Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Public Properties"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Internal Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Internal Properties"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Protected Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Protected Properties"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Private Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Private Properties"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Constructor/Destructor"> - <Entry DisplayName="Ctor"> - <Entry.Match> - <Kind Is="Constructor" /> - </Entry.Match> - </Entry> - <Region Name="Disposal"> - <Entry DisplayName="Dtor"> - <Entry.Match> - <Kind Is="Destructor" /> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose()"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose(true)"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Virtual /> - <Override /> - </Or> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - </Region> - </Group> - <Group DisplayName="Methods"> - <Group DisplayName="Public"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Internal"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Protected"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Private"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - </Group> - </TypePattern> + <TypePattern DisplayName="COM interfaces or structs"> + <TypePattern.Match> + <Or> + <And> + <Kind Is="Interface" /> + <Or> + <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> + <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> + </Or> + </And> + <Kind Is="Struct" /> + </Or> + </TypePattern.Match> + </TypePattern> + <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> + <TypePattern.Match> + <And> + <Kind Is="Class" /> + <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> + </And> + </TypePattern.Match> + <Entry DisplayName="Setup/Teardown Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <Or> + <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="All other members" /> + <Entry Priority="100" DisplayName="Test Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <HasAttribute Name="NUnit.Framework.TestAttribute" /> + </And> + </Entry.Match> + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + </TypePattern> + <TypePattern DisplayName="Default Pattern"> + <Group DisplayName="Fields/Properties"> + <Group DisplayName="Public Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Public Properties"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Internal Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Internal Properties"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Protected Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Protected Properties"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Private Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Private Properties"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Constructor/Destructor"> + <Entry DisplayName="Ctor"> + <Entry.Match> + <Kind Is="Constructor" /> + </Entry.Match> + </Entry> + <Region Name="Disposal"> + <Entry DisplayName="Dtor"> + <Entry.Match> + <Kind Is="Destructor" /> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose()"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose(true)"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Virtual /> + <Override /> + </Or> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + </Region> + </Group> + <Group DisplayName="Methods"> + <Group DisplayName="Public"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Internal"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Protected"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Private"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + </Group> + </TypePattern> </Patterns> Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. See the LICENCE file in the repository root for full licence text. @@ -738,6 +744,7 @@ See the LICENCE file in the repository root for full licence text. <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True True True @@ -773,7 +780,7 @@ Origin = Anchor.$anchor$, True InternalChildren = new Drawable[] { - $END$ + $END$ }; True True @@ -786,12 +793,12 @@ Origin = Anchor.$anchor$, True new GridContainer { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { $END$ }, - new Drawable[] { } - } + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { $END$ }, + new Drawable[] { } + } }; True True @@ -804,12 +811,12 @@ Origin = Anchor.$anchor$, True new FillFlowContainer { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - $END$ - } + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + $END$ + } }, True True @@ -822,11 +829,11 @@ Origin = Anchor.$anchor$, True new Container { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - $END$ - } + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + $END$ + } }, True True @@ -840,7 +847,7 @@ Origin = Anchor.$anchor$, [BackgroundDependencyLoader] private void load() { - $END$ + $END$ } True True @@ -853,8 +860,8 @@ private void load() True new Box { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, }, True True @@ -867,8 +874,9 @@ private void load() True Children = new Drawable[] { - $END$ + $END$ }; + True True True True @@ -886,4 +894,8 @@ private void load() True True True - True + True + True + True + True + True From 9d4f80c2a236ecb35f1b0e02fed21494bddddb0a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 23:37:58 +0800 Subject: [PATCH 3713/5608] Add icon and use licence expression for NuGet. Unlike framework, if other components are packed, they are likely to use different icons. --- Directory.Build.props | 2 +- assets/lazer-nuget.png | Bin 0 -> 12471 bytes osu.Game/osu.Game.csproj | 7 +++++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 assets/lazer-nuget.png diff --git a/Directory.Build.props b/Directory.Build.props index 76f1ccc0ca..b4baa2833e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -21,7 +21,7 @@ ppy Pty Ltd - https://github.com/ppy/osu/blob/master/LICENCE.md + MIT https://github.com/ppy/osu https://github.com/ppy/osu Automated release. diff --git a/assets/lazer-nuget.png b/assets/lazer-nuget.png new file mode 100644 index 0000000000000000000000000000000000000000..c2a587fdc26734c1f263023d7eefa8fd644e978b GIT binary patch literal 12471 zcmV;oFi6jdP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>DFic5AK~#8N?R^P! z9MzfbU%jdq?UF59-Yp#4csI83g0TS;2ulJ9i-8c52?L73WuK|*|u4&VzdG7zO`$yGORZk5DgJb+YUxU}{9jj?tE$^>zdpyB(I_=kW-NSt4 zbF`Gp<%*|LsV?4V=ih_8za^fCH%Fq;EjxB>-*nFM^FB{e3PO^nX6;X+yc+zX>-OrL&HO-;>LJs!_|W_r2Ut1}-2 zJMe4#-CwwvOb`lC3xA6?^>i!}d-cfCqi?phwLUO&_N*qZOksynz7Y7L2!J5{`|rPB zIdROm3o0rrzsn|j0h{s?u{X{1PO~DONV20XI9Wh{+*{UfoKZh=c#@k0RFyL+`;6emK7;~`*tY)^OhAD({ZnSWY&{k4a94?5tWfx!j$?xaJjuBh<7 z|IYiDOl)YlgBf2dGz~sJ7leix-H&mG{&_nkx3y4e+d)b(^CE#M>Hq6y?ZdlG3C$V|DzxdZ{i z=HZgo(`~JXzEeAD#DiRWQi4Q~_C!Pb(_QyetXz5ZFFCFIzUFfIa%#PyG1S&g`n$VH zU$>u4eqScW<8ex*@+%RTuWG*pVgZgljIHBPkGDFe7aSLO7f&Sbau$TzFjwRe1l${+ z)78;=U-_`=@AI`zxJx+E0^nNx)N?gU&pPYQKsb1rsIl{%@UPGm1a7Z4S~4C;Gl66A zn6YIKFw#o<&0v8v{>ngS=Af7XYmwJo@G0JfY!OyW<^U&@sk0MuBbG@;6CXaa`h{;? z_KnM$x%Py)gcB(M?zdllee#)$7C!0mdmC&`zCjQ~^7Pg&(${=W6t!nuEEcoXYBLgv zL>4nuzzvvPfnB>ft$-P@2|5!Z3+Rj^rb&J|=g2gi1;>qrFyuMuV~W;6(c+yk4)+a4YSX zaAXBcaIrh^Up|{$lZR)RZD$RPL=P z#mq0KgvHIH7aZh4>!Z)Cr}!Gye9qT_a5!wKabOO#Kc7|uh!LzH8Epoxg?J#JRZ)ci z?Z`T{P1O1QesY~Tj6lQoN5;1Br=rcH! z15z--a9jh{BM=CP_RKobW)Rb+k!l>8J1xRvXxTg4liX0dW0dPI` zz{9n3=gxUr^SLW+na^4ieezR^JjsMm(mP392@qKZd$~-y892wzj|*n`k83GRHwpm8 z<2+nLWw=$5*TC_eot@Ox)kQr$J#5)CLSYrZNa!zbBmL3O1TA{UJIshMT{DuyPRfL4G3R=<)ec~S z^v^0_raj(l#z0ej92A-XM%uL_8Eyr{1j6(?5L7_lafs4V2n+=g%sTYL9=Z@oK( zYX*dO1JQ^U4hDUfeeJS;*LUPq%wh~Pl&cTY}>b4&u>WX{jOqu=%-Wm{B zFc1RZ-o3f;`an2%x#ge+M)(eOQexF7+vY%1x~ORU(}+1Af0NPO11TE7?{&U39Dgf zFyCyY`UQ3YuA7z!vrjuSwClyh8cNrd#@BqZcFN-OmVVAPg%i|3e=UIL!t*cqv3S6v zGM}{pu|V?e#$M(FcD_3wpj~D_+szEfrTzT@u4~n2wQiuazZVQ8SV8c{}6sl)@j z+Q=18`DRa_aSLzdPKolMKLX%-^{MA4hs(n^TiOxU{`9tklz1yU;_r`-G(%bvRTu^m z(0o<+0M!B&8~Ejd2nv~obXtv3V*t0hyPX0)-#6C1{lQY+Dw?3h3IOiZGjHy^|Ksxe zO0%MVn0`#%LeLk_)=Utu7-FgCKmbq%OZ(B!Toz02!*QyM7%1q^ZRQIwo5ofeH3r(c ziH=5Ta>Jy5;4NIdDCsL!09@}qL#_gB#R#ChxRscMwO=$Q#m*4BN8t}m! z{N!ufj0$UjcxDso6si^AxZU_`U;*uR(m(ipxF7k{GGBqUa#~>B#QlD_m*_}@tw5D= zRRhPOB37s>ulxaT6=emA5dhb!`yOm4DGgqnrTw@(0>3vom$jI`r=nOZU={-WjRJ-Z zWN~WJ!F)WZ!W;l61=#~8s5mKo@FrV%XFY~UR87|iTwk}G3w8yB(4KS`4D_{jMLRyvn76^b@$nv3(<7MEQ4_WaC28RxI z5!Gkjg6{=eTk4L}8MEhnhqvql78?{weeJ19Do0P-6B#2&_zKPcxm_?nx$iI~H#Sjn{r*hZ+$?5A zd%`8T1^6?pM8ka(ZyuR&sEa%<*O=9-o;jVj9P_mh0dQToe8t7?5?@JH@W&laZD|qd zU$FpTotn^G0OR`W3UZyF<(v853mO83U@`qL2Qu9qBR!hPl&+YFp)_?+O$DB|ZemxU z3P2~HA5YQr$x|-ptw9k0&xnyDzbZzhRIocpZ|5krpO)8YAO#Ikiy8f~0=bwEzij23 z(Ql`H7s`XeeTK01u{5|3rlqX6E8^i0T!?uw3m`Kl@OAzRI~;MtsQ|eC@c;g!tRxhi z$2~Br48Z*NBq+7{fKgFAz{p|(LMs#_1R!oM0YICWmZlcu_pn}$`VJzIz~?I&01YH)2r?{O?Z$xY2f<;uJTj23d+ z7oNKU?-DrTty2MT*VNR^5wA3@2DzrR~WBV_XC2d+-Db?O0?@5SwSwmu5BS;mck+#lS436 zhP(J4T^f_s_8g``lJ_aJ5JG^u96_L@AxdgH2Z8{Ezzhxsy)O5;{1-ZwgWwtDJ%FK& z8ac9b*ZOTcyrqF*eKG(H{j%AK-tr>p#+p3n9HL_U$_F6$TWX1!&{~O?JTvOaJ!2Fz zr#$nti;oomLD~`|4-jFc zF-(Jl3u0}=dPO~td?b#SDE-O#lYFu&60dF*tDocr-$(Gr=aR;LpPD<2 zN(M#>8){QCmMy5=uw@f2kkh0%vH-XK-+vk9^?8S7nSUl~dhcP1bw_$1U_g?=Z~*=s z0$?_A5C9yP9$P{FzgtG$Z_Fmw)ZwI;`$=a)>RuKq6#UJRuJ_FG6ufo;l`+vgE9-Gl~3H&!zA$zLF6T1D-K#fiNF$ zcq#i?f2NEmBhSqG43iB=?bq0%xW-j;V3wjZGc~pUNbjR?&!piQp)rjLKOZ7TEs-v`E*x9EroAhM!uP&MLSmTGOR$L+U0^eHnoVPAr$E@)*`cI1B~m7dT~7eE!$yar+wTWrg61*^Dh_vO&`VFe&Yla za8FsR;lo6g)vRh8qz`pw(m^vY0f+k=4wPU-FfV@{S%84QWRzY0FP3C8kZW3$@W))- zvqw|OMblXey*VS^J^Rk)|Z4v3+30G-zf|LY(4ptJ-e|9Bl#IhZQ{; z5MHP0sNQP$es!i$EJ-Ck-+2BjFMpi~0J}K%$m|S&x7pOB@x}@xm-a(jARHx2SdKVI z$6b99LCWX~4XB z9Gs;@p8S-euWY8+hr1}bW;dl@LLtryt8< ze!HS`+La}#3>bvu_SS4IWI(!88=ILnDzzBw_uRGICIi7Gm}GGjNBJ7Lmo-r6n`ctR zkItt6XCV6cY9TT0IP=sSC>;mjx)0>1>>fazAjd=Lz&WEmb`NxsWxQefpgD*NFIDmjzm2rGXMf!cm3 zi}@fWn5hZ?3ij!G#(&F#ZDcRlF9bpYf?=3?3Bi9#71q8%{d{-4FZkq+p zU0YS1SArY~0C(O(b-9?NH6L7MmPSO}a2lgoHb`TBq1DoI%s5wRNoK^2i5p$Nm-J@# z(Yeef1c8Yo2Awbvb=gb`U$sE2_1g#NCK+a^CWV***I^|D zh`Yo@6hWK5=Lm2;2ZFhJEa1oja5LGX6S$^Tu5N=q0iGG$IP!8^SPgU-PzOzt%}40y zJ#SL{*^Q*NbdeTGW>U5sbkJEaJu^pgIF$Vl2fG%M(HG7HK-VptE7!9IIfdTd zBT}L)csZ|@4_qwZ!ceDGz{Z+_Prs;09qpmcmp4$yZ(kO9fAW>>q#=Flj9KUJ=o7~$ zo;uS^TVX0cfq-dv9ad0{Cm?ie8Iv7dUD?v4z>xr?l4;9@`GxNkH=7@+gPbO*11tdFfV(CW z&1Zp|c8{pAb{`xYB-=ZU4F%k%6sJeA_4}ynsZZ$GuU??YUp}HVR@_p<367ZceMiYv zaeQ`7no~-vSOOLYu}l`wJ(Gqa_{)InEG$5}GfMGo2PpRG9*TajQ;biIY`4&6YijhQ8K^}c}kc-aIC zNmc-+;Cnq;GKRij7P9Fc4qR(|zD3UX@auFOQo5CTaoF-M?b*zt*!raT|aPe+dn zXPSi-b!MRek{v84e17O_bI4uI{etkLVA(mo4tm)q-2=E@q=^!|?VVI7zEGA*B!s0( zbw|Zmf~UT+uPag@hSSZ<*I-RyxM9_@;(k&oeoD(YW`l1}gu-c@#W<8ig*N#hS64yl0;#9@nbSx|8fbclR-U{>dZBbH*47 zTzLjn{Nw_v`q@QP#wi|{6~1}_mEL>~`BqHH%mpwrA7+(>N4O{h2~7B4;c*3(;Saut zMC&nf4=)$#WBEuPsq~sN#qK`ZZ-Pu!0SFL;6--ZIQb-s7LI_y6(#%LLWIw8! zHR6i5i6G$W8VoEL$y5qMoYoyOA)f#M=~yD!l4WK9W{wNm<`9v0w{x!Eksb9jar6?d zn^H@@OQw_e{3)b;sa6PvDtH(b)SHe{WbH1aCIjE;^+Z9hI7hE$KRuy}JWCtIq!0I^ z@kHY*`5GB*F^}-UT41myvBNYZ%nXZfYatKf0>gqxFfl0J)K2l1Ba~?CphPoNAoT8YzB-+eDkHLIGT77i2>F)j=Vxlm!4|3aSO*He&HOo^XL_78g1WM*?v8 z$l*pYk4*(jnp>TkoC~oO^*pv#43B0-&D-UqoH5?crU9=&tfQk7ozn8qj z%E`kKee}H@l-Qd6P6L?V^W0~guY1WivNC6?n&tNyxHp%G4U7r~tbj;eA^eI029bZA*!dX*u^M0(*k&7Y%jx4|}xBt318Ba#Rh(6%vp?OY#8$c8b zGln_sUH80A>GjQ|btN(>7YKs(&4ue>^0kf_CEndd9e2Maa^@@`59X{u!-NgdmeL;Y zPVZ{xo7KoyUqxOnc+k|ddIQBiv45X2*?g3`9{NBGRr^L(k#AHrd061xta+|b2@8kM zC~Tg?0d^T7@(r&f|L9sO8CNH^lgctVDU5uwC2*IA$WvWPp2{$J@O4sdS7X6cGbPZ? z?$tB#Wir(@v!Lo}J^9KS_P2bcOr<@TI(dO(LOt7Co(qhtS=wi)5_^tDsq^=*a}Z^p zk^#60>BC?O@jM%h@lC5I&)8~_UTGEVyTLF3CiX}VCHJtujaj;Q1ibwqCHAys6E6qQM^V@sU~0Jr?UtI4KC|YgS-X)^ zCJ%93!2QO^B(AAaIkfOJ@{F#^e5;sgB4m_JIc5VN)4-Xf4Ioa#U^u z3}C1}3^RlKq(=aoO%WwCMG$O>hd_KeCtnB20-pyaiJ%Jc0NUfr4aiF;U_9Dk0ZU_e zlbNq`B(5j8pHhHx09HyW1Af)u4gh_?c)P`|wFxz(E#ov98H?F%)K^f%Lr({1)L+9} z*0WMgaN+{cK&qv+7bnaIZz6#%Y## z3zypy!KH=2E*OT!i~PNl3->uQ(>Fi!0TGyTKOpE<%m+}P^R4629GnWFHqi%ekJH>e z&HLWrEifzZ%{mbPApM)WZhwWMe3MG>0(hp3u$^Fm36xedTVza-4}C`T1^_Z0a{@5Q zuApD|Ef(m99rFR~v!a^-(^?x{nf(+ML-TBzKHI(-pPX|TjrFTQzhH{300ucFo)s`n%rdnz z0sXYHl-d~1N-mhf=KpXe4U`yGN|AuJyJo?pIX#gGMz-=2FFzGB0EdzXTMxcr=>|9; z!Alt`JRnjYvuNoG7(&wqf%$+_t72!O@j#|O%tyOURu(}&E&Gb~0%L5+%*;oJO8wM+ z^vFxhd`PV$^Hh)k+`H<*{}g6NWh(FW&KylH(?Umrcn(awov9lv=1Vvg0=Owvh;2=? zLx3($ED(^j5~`1ts-cDmZ!?(z^UneA?xwxZ@RlS04-_KE=yAAfbJJU)hT$`_+yDn7 z(N&*N^u0#03C(s&DAm+r+EzNpM;Rn=UOo$x3oZv13P84kiLC(c2^L@=kz!$#Zm_(( zJZJEyO|2ts$wVT2VAGt&4lku>*wZ{^#e!L%H|=BJ;OyJOg@`hGm}qTld&qJM7fYsi zS;LSEOubg;vD+2Z&pKf~fKRhI)nqF;wKBrrGt*H9n)!fi6EQ)~$e#mnZQ2OV?u{%- z0)cr&fR6QaKg`U}oBNwlumJq#-rqmK*#O==$ka-(MbL(Y$u|Qpq!bUQ3>7f~1OUHA zU7?U|I00P2U@#w$!UX}qn1@}_IryWRaNiF~0i`9B(kTA?YcJlI7n{wedHIC%@ELFmSF#pr-=XqCeKg36i-| zRPJZxx0jNyiUk1CzZny%smG(g5c<*xd{GRuw+6)m0BAV==(A7UE~YiBR)BrCHli%& zE8Mx@G)Gspz7S2$0?u{7Sf|W)68PF7mxb|98A-me9Q@%s0cIfZ4*6+g`Hn;6>c_GVw;L-sv1umGL*)9NuFwu$`{n5^R=Q?d0ZUSb!*et>BJUr(J zEuBo%$&tT#N*hoUqOR`lPrmxCE8gTS1ZRUT0H8+fP(D3TJQ{ zkl8TC-Lkj^nglhouw-{InLCNf~|66u# zzoVtCwV>cnq8I@Hl@k|Sclqmwn-0Ec8AWhLP;%ik$Fqe%U?u&z}PoCwi zg0&wgMgRa%CAQ|{k8Tx9lv-E;%(V|*Jj1BS4W~rT#e4~?wxE$9s1yVN5ZY7#Rnwii zCBZCZWG`nrmj`&A9IgaU0?RI$otZIx;P{+H0X#Y{E1~r}w*A}38$ZRfcxM5W0xSJ> z3fR-ovF!)$E*n#O1yd?hD*>WnR?YouDE{eQqcR&{m=hBVMqt3i36K#;rmAD^XeZLs zlhJE6SEgm6eq$jH z0nDVDG>ke^(dVmAA9r0MnZOGY&eA6Z#aaLW6pQ}z?|<`iy)&8+oiYQ2^Lr?G#Tn#= z|FVG4Fomghfe;7|^XR1Xg8x>ZHGt{TBA6k!%@zc8(oLvE3JT&1E9L_bJoFoutB@l4 z$I-oa1qXiZ?Ap!D2RQIc`CVNvz46*D%zV5`RFw7u`4iyW(BJ#uz4%p^e!Z)9SnYY1 zLcm#px2}R>A7)P&vC{l-nDbnQI$1<8qksZ{F})_=0EA8s>zaXcgvJ|?ZR7%k0H)qf zXaVfAx}F^%uq9<7@_lVqW}U)a?HM{sU~c00Dr)aIcJI6k&&I$H(gJ6u(E|Ok001r= zoqE>XyN(?=^p0g~%w*TZ8VX;((5T2jXutW!7$7E?2J_cnfPq#|8pQyTa$N~%G~mP~ z0V3Grk_+gAlYu4)SRmI~6Ul|={kz%ps}nxPR#GID+;-bNcm9fN@Ib) z9prTd_*V*q9l%_ilMm=euIri+SkyqlbEXjOJ(Bq#lo?FJR8>jWx-FY-{?-rvWx{JkROjXI)Jz%nCy0w#%2aaZGAp$9L=VnD;m<-oD*c-!Gf20<$ThxKm=ATMIR(Y%2&&g zUTV*+zrXFrYd-#n4=66>v%)~R012#0kxryjZ!BA|W&jsxR+K zW{sips}_(8%tyX&o@j%hk2ODC8R+=SqYq#G(|`H}-u3}8Ob7K3*_7%(K&`+lPp@8f z?%B(pq7d6Jt3{q5*|8+0UfxRDd%2fK@9yq)Bm{^XiXDfKMk0bqR*-qW6JYSiDMHJq zQ0U9kNyGE~Jqq(7#GLM>YeSuz8h8A7#-ce7bM1hceu=>l005RH_~GmCoHuXo8IOxE zU8-;4V0-^j@&3QQvyJpeJ~eh^1KM@;2rQpHpqYpxthC<=5Fg|UI*XY;W(SRP`S67^ zD0tQ+j`o=bP3-ge9{XS%Grukz-MRPkpHG@Q{a&uYXwZO}eu=>n0053M`0nc0zr1Mi zqDRDn#!?9IyS_OyvjwY%o<3YW=@RSss!zNOM5CDxFWaG*ctHi)w@W>R>1QEu0!(p( z&|1M=5u~zf7m<%MBHF`3jaR$O07nG#%i_ED?)k@tIaBZC8a(M6aOMMpDFA>Ff_GNG zcERGsiys!Ngh%*3B=aTk(E|>2Fs-?J)!N>PrA`4q4&UEjfN6M6U35b=VEzQs+L@P|TEvGPvw-LNGwV6LPwsy3(MPVj@Un~XULTl`4h$;uffHo` zBp`5pCSa&#=ia+(t7|S5%x=s)AIJh?1NMnn2?GKUd3~!`Q%_oi{-k~RP*hsTdAnzP zEd?%`E|#|wWBHBkl;!IIq`~7Vh0E(n#NYbGKmPCU{`QXBIXLS71D--~q6Gi|<-oPj z#t+xsc>2_-|3aNHjkd8%!0aL`U@;^JLNyCQdpE`2Z=~2;+sW^C_AsUxV1fuHCp?{Bdi^0hd z007q&!Qs>6C1?LS6bQ@`Pr!C&zR70^5U##VXbq71Xpi`8ZEE8I*k(~Tkig)R zT~3e1CwvXV#J35()9Xp|d71Ida6H1b6J!K>V>4Rc8R^;Z*8A`NuZu6g^gZ4KNr5jM zbd#^*WC;L(Yr`5Kf(tcn+V-P~Z-4j4 zJMO#fx3_U%&};HfIP-y%DF6}>0+A*B?$+BTU$b)MFRCglFBJh3VgvP=xC#s~VX-8< zGF8b$<~tIrjNpUT_*%z-W2CorQ5xx&!zEl0mE-d^E^aej$tfoLbFAXoyC^35hQJPO zTKRV~z<6kVO^9VX{@zQgU;6o1uey8#?~z)6LQTGkQ$YX#^g~*Mz~hgsTC!rFp@Mq=;}a>;nR#NVHe?%eECLqA$4o~$#^-7{ z2X#0P$AQVnSkMRjt**>z1u!1VxUg_`M|wV9yY}NdS6p(zQ;9?ZxjpjVlcx1%fMll< z&>vU>1c|{{o_+DcdGpTrQCV5pY(aQDJ80rOx)6U4#^VKwATt#UM!^qbja@|H*oP~k zIXtSy;0&0H?-zmbSPX-O#xc+)zTG>X1J?2q>gkDmytA?K&nvILZq=r(n~}%DTyUc& zpYal>ngB?^8i-a1g_6`TCApl01iGK{v19YzX$-$K_Ch=8w)@pv%nk% z`Rf(a#**<^tSJ(UeYSt!zIQmNd;jMD@wYpou_zc0NkfrLKV^J;K77#xzzp;qMGAu~ z-qE8*`|rE^o`oYu)lUcoL-nQM@C2XFSLb%Shw&MeCH@j0|KeDA|7ks~Ct~qfT+_6p z$wcx9|J@vqCt6xtTeq|wI<(`7XP#=j{r20Dw}Z)Gw$$=39MjGCA`5^S@;+c4q=k^b z@^4wFG!%AMRaSZ#E@rrvN~Ls;*psbot?~5n$AFTt=3g_jW%)wmuSEc?Any&oR>cY` zW5I0TuY%b_7{U;SFoYotVF*JQ!Vrcqg#YFs`v3fwc4`p|61D&U002ovPDHLkV1lHj BjmH20 literal 0 HcmV?d00001 diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index fce50c43d2..6e7a07e192 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -7,7 +7,14 @@ osu! ppy.osu.Game + icon.png + + + True + icon.png + + From 8d290a324291dcceccbbc587b40f483106cf0436 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 23:43:13 +0800 Subject: [PATCH 3714/5608] Resolve CS0067. --- osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs | 6 +++++- .../Visual/Gameplay/TestSceneSkinnableDrawable.cs | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs index 685a51d208..46769f65fe 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs @@ -101,7 +101,11 @@ namespace osu.Game.Rulesets.Osu.Tests public IBindable GetConfig(TLookup lookup) => throw new NotImplementedException(); - public event Action SourceChanged; + public event Action SourceChanged + { + add { } + remove { } + } } private class MovingCursorInputManager : ManualInputManager diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs index b3d4820737..8beb107269 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs @@ -326,7 +326,11 @@ namespace osu.Game.Tests.Visual.Gameplay public IBindable GetConfig(TLookup lookup) => throw new NotImplementedException(); - public event Action SourceChanged; + public event Action SourceChanged + { + add { } + remove { } + } } private class TestSkinComponent : ISkinComponent From ff3db9f3b26eb9182116d53916a030eba4946dcb Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 31 Oct 2019 02:58:58 +0800 Subject: [PATCH 3715/5608] Update README to require VS2019 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0460e9cbcf..1e2d539697 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ 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 working with the codebase, we recommend using an IDE with intellisense and syntax highlighting, such as [Visual Studio 2017+](https://visualstudio.microsoft.com/vs/), [Jetbrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). +- When working with the codebase, we recommend using an IDE with intellisense 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! From 473045308374118211ae5338e06d9b96a2f949c6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 31 Oct 2019 02:10:00 +0300 Subject: [PATCH 3716/5608] Apply suggestions --- .../Visual/Online/TestSceneVotePill.cs | 22 ++++++++++++------- osu.Game/Overlays/Comments/VotePill.cs | 20 ++++++++--------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index 7ccb025b47..22e11aa464 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -8,6 +8,8 @@ using osu.Framework.Graphics; using osu.Game.Overlays.Comments; using osu.Framework.Allocation; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Users; +using osu.Framework.MathUtils; namespace osu.Game.Tests.Visual.Online { @@ -24,13 +26,6 @@ namespace osu.Game.Tests.Visual.Online [BackgroundDependencyLoader] private void load() { - var userComment = new Comment - { - IsVoted = false, - UserId = API.LocalUser.Value.Id, - VotesCount = 10, - }; - var randomComment = new Comment { IsVoted = false, @@ -38,7 +33,11 @@ namespace osu.Game.Tests.Visual.Online VotesCount = 2, }; - AddStep("User comment", () => addVotePill(userComment)); + AddStep("Log in", () => API.LocalUser.Value = new User + { + Id = RNG.Next(2, 100000) + }); + AddStep("User comment", () => addVotePill(getUserComment())); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => !votePill.IsLoading); @@ -52,6 +51,13 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Not loading", () => !votePill.IsLoading); } + private Comment getUserComment() => new Comment + { + IsVoted = false, + UserId = API.LocalUser.Value.Id, + VotesCount = 10, + }; + private void addVotePill(Comment comment) { Clear(); diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 54eba63095..ad17264229 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -158,18 +158,18 @@ namespace osu.Game.Overlays.Comments private void updateDisplay() { - if (Action != null) - { - if (isVoted.Value) - { - hoverLayer.FadeTo(IsHovered ? 1 : 0); - sideNumber.Hide(); - } - else - sideNumber.FadeTo(IsHovered ? 1 : 0); + if (Action == null) + return; - borderContainer.BorderThickness = IsHovered ? 3 : 0; + if (isVoted.Value) + { + hoverLayer.FadeTo(IsHovered ? 1 : 0); + sideNumber.Hide(); } + else + sideNumber.FadeTo(IsHovered ? 1 : 0); + + borderContainer.BorderThickness = IsHovered ? 3 : 0; } private void onHoverAction() From 32dabf80a6f896cba970220d0e2435051a2c5982 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 13:42:11 +0900 Subject: [PATCH 3717/5608] Ensure forceful exit completely exits from mutliplayer Previously it may have gotten blocked by being in a sub screen. --- osu.Game/Screens/Multi/Multiplayer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 5945e9de13..941d7a2478 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -174,7 +174,10 @@ namespace osu.Game.Screens.Multi { // This is temporary since we don't currently have a way to force screens to be exited if (this.IsCurrentScreen()) - this.Exit(); + { + while (this.IsCurrentScreen()) + this.Exit(); + } else { this.MakeCurrent(); From 5b405abc5253480414eb421028d48c1cb019ef0b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 13:43:25 +0900 Subject: [PATCH 3718/5608] Schedule forcefullyExit call for safety Screen state may have changed at an inopportune moment. Run on local scheduler, not API scheduler to avoid any weirdness. --- osu.Game/Screens/Multi/Multiplayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 941d7a2478..86d52ff791 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -167,7 +167,7 @@ namespace osu.Game.Screens.Multi public void APIStateChanged(IAPIProvider api, APIState state) { if (state != APIState.Online) - forcefullyExit(); + Schedule(forcefullyExit); } private void forcefullyExit() From 0cd912fcd3ad364b8ade2a7d5e98685f3e3c68d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 15:04:13 +0900 Subject: [PATCH 3719/5608] Cover all non-APIAccess APIRequest calls with exception handling --- osu.Game/Beatmaps/BeatmapManager.cs | 11 ++++-- .../DownloadableArchiveModelManager.cs | 35 ++++++++++++------- .../Changelog/ChangelogSingleBuild.cs | 12 ++++++- osu.Game/Overlays/ChangelogOverlay.cs | 19 ++++++++-- 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index dd2044b4bc..6e485f642a 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -392,8 +392,15 @@ namespace osu.Game.Beatmaps req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); }; - // intentionally blocking to limit web request concurrency - req.Perform(api); + try + { + // intentionally blocking to limit web request concurrency + req.Perform(api); + } + catch (Exception e) + { + LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); + } } } } diff --git a/osu.Game/Database/DownloadableArchiveModelManager.cs b/osu.Game/Database/DownloadableArchiveModelManager.cs index e3c6ad25e6..a81dff3475 100644 --- a/osu.Game/Database/DownloadableArchiveModelManager.cs +++ b/osu.Game/Database/DownloadableArchiveModelManager.cs @@ -86,16 +86,7 @@ namespace osu.Game.Database }, TaskCreationOptions.LongRunning); }; - request.Failure += error => - { - DownloadFailed?.Invoke(request); - - if (error is OperationCanceledException) return; - - notification.State = ProgressNotificationState.Cancelled; - Logger.Error(error, $"{HumanisedModelName.Titleize()} download failed!"); - currentDownloads.Remove(request); - }; + request.Failure += triggerFailure; notification.CancelRequested += () => { @@ -108,11 +99,31 @@ namespace osu.Game.Database currentDownloads.Add(request); PostNotification?.Invoke(notification); - Task.Factory.StartNew(() => request.Perform(api), TaskCreationOptions.LongRunning); + Task.Factory.StartNew(() => + { + try + { + request.Perform(api); + } + catch (Exception error) + { + triggerFailure(error); + } + }, TaskCreationOptions.LongRunning); DownloadBegan?.Invoke(request); - return true; + + void triggerFailure(Exception error) + { + DownloadFailed?.Invoke(request); + + if (error is OperationCanceledException) return; + + notification.State = ProgressNotificationState.Cancelled; + Logger.Error(error, $"{HumanisedModelName.Titleize()} download failed!"); + currentDownloads.Remove(request); + } } public bool IsAvailableLocally(TModel model) => CheckLocalAvailability(model, modelStore.ConsumableItems.Where(m => !m.DeletePending)); diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index 9c3504f477..adcd33fb48 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -44,7 +44,17 @@ namespace osu.Game.Overlays.Changelog req.Failure += _ => complete = true; // This is done on a separate thread to support cancellation below - Task.Run(() => req.Perform(api)); + Task.Run(() => + { + try + { + req.Perform(api); + } + catch + { + complete = true; + } + }); while (!complete) { diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index dfe3669813..559989af5c 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -170,6 +170,7 @@ namespace osu.Game.Overlays var tcs = new TaskCompletionSource(); var req = new GetChangelogRequest(); + req.Success += res => Schedule(() => { // remap streams to builds to ensure model equality @@ -183,8 +184,22 @@ namespace osu.Game.Overlays tcs.SetResult(true); }); - req.Failure += _ => initialFetchTask = null; - req.Perform(API); + + req.Failure += _ => + { + initialFetchTask = null; + tcs.SetResult(false); + }; + + try + { + req.Perform(API); + } + catch + { + initialFetchTask = null; + tcs.SetResult(false); + } await tcs.Task; }); From 7a3ebcd0b1c77b7caaac8c88f0a722353acd4a25 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 15:52:38 +0900 Subject: [PATCH 3720/5608] Fix path changes not updating tail circle --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 010bf072e8..f60b7e67b2 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -37,6 +37,8 @@ namespace osu.Game.Rulesets.Osu.Objects { PathBindable.Value = value; endPositionCache.Invalidate(); + + updateNestedPositions(); } } @@ -48,14 +50,9 @@ namespace osu.Game.Rulesets.Osu.Objects set { base.Position = value; - endPositionCache.Invalidate(); - if (HeadCircle != null) - HeadCircle.Position = value; - - if (TailCircle != null) - TailCircle.Position = EndPosition; + updateNestedPositions(); } } @@ -197,6 +194,15 @@ namespace osu.Game.Rulesets.Osu.Objects } } + private void updateNestedPositions() + { + if (HeadCircle != null) + HeadCircle.Position = Position; + + if (TailCircle != null) + TailCircle.Position = EndPosition; + } + private List getNodeSamples(int nodeIndex) => nodeIndex < NodeSamples.Count ? NodeSamples[nodeIndex] : Samples; From f8187fa30125db2a93b455bd369fe123903bbb44 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 16:23:10 +0900 Subject: [PATCH 3721/5608] Don't rely on masking for bar display --- osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs index 5227bec92a..8c150e6ed1 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs @@ -33,7 +33,6 @@ namespace osu.Game.Overlays.BeatmapSet : base(value) { AutoSizeAxes = Axes.Both; - Masking = true; FillFlowContainer nameContainer; @@ -87,7 +86,6 @@ namespace osu.Game.Overlays.BeatmapSet Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.X, - Height = 4f, }, new HoverClickSounds(), }; @@ -95,9 +93,10 @@ namespace osu.Game.Overlays.BeatmapSet BeatmapSet.BindValueChanged(setInfo => { var beatmapsCount = setInfo.NewValue?.Beatmaps.Count(b => b.Ruleset.Equals(Value)) ?? 0; - count.Text = beatmapsCount.ToString(); + count.Text = beatmapsCount.ToString(); count.Alpha = beatmapsCount > 0 ? 1f : 0f; + Enabled.Value = beatmapsCount > 0; }, true); @@ -120,9 +119,10 @@ namespace osu.Game.Overlays.BeatmapSet private void updateState() { var isHoveredOrActive = IsHovered || Active.Value; - name.Colour = isHoveredOrActive ? colour.GrayE : colour.GrayC; - bar.MoveToY(isHoveredOrActive ? 0f : bar.Height, 120); + bar.ResizeHeightTo(isHoveredOrActive ? 4 : 1, 200, Easing.OutQuint); + + name.Colour = isHoveredOrActive ? colour.GrayE : colour.GrayC; name.Font = name.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Regular); } From e23a75c64a400705b202122570ca1f41d09c0735 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 16:23:54 +0900 Subject: [PATCH 3722/5608] Implement control point selection --- .../Components/PathControlPointPiece.cs | 84 +++++++++++++++---- .../Components/PathControlPointVisualiser.cs | 21 +++++ 2 files changed, 87 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 7afb8fcf49..3b0b9bce1f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Lines; @@ -11,18 +12,21 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Rulesets.Osu.Objects; using osuTK; +using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public class PathControlPointPiece : BlueprintPiece { public Action ControlPointsChanged; + public readonly Bindable IsSelected = new Bindable(); + + public readonly int Index; private readonly Slider slider; - private readonly int index; - private readonly Path path; - private readonly CircularContainer marker; + private readonly Container marker; + private readonly Drawable markerRing; [Resolved] private OsuColour colours { get; set; } @@ -30,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public PathControlPointPiece(Slider slider, int index) { this.slider = slider; - this.index = index; + Index = index; Origin = Anchor.Centre; AutoSizeAxes = Axes.Both; @@ -42,13 +46,36 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components Anchor = Anchor.Centre, PathRadius = 1 }, - marker = new CircularContainer + marker = new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(10), - Masking = true, - Child = new Box { RelativeSizeAxes = Axes.Both } + AutoSizeAxes = Axes.Both, + Children = new[] + { + new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(10), + }, + markerRing = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(14), + Masking = true, + BorderThickness = 2, + BorderColour = Color4.White, + Alpha = 0, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + } + } + } } }; } @@ -57,21 +84,42 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { base.Update(); - Position = slider.StackedPosition + slider.Path.ControlPoints[index]; + Position = slider.StackedPosition + slider.Path.ControlPoints[Index]; - marker.Colour = isSegmentSeparator ? colours.Red : colours.Yellow; + updateMarkerDisplay(); + updateConnectingPath(); + } + /// + /// Updates the state of the circular control point marker. + /// + private void updateMarkerDisplay() + { + markerRing.Alpha = IsSelected.Value ? 1 : 0; + + Color4 colour = isSegmentSeparator ? colours.Red : colours.Yellow; + if (IsHovered || IsSelected.Value) + colour = Color4.White; + marker.Colour = colour; + } + + /// + /// Updates the path connecting this control point to the previous one. + /// + private void updateConnectingPath() + { path.ClearVertices(); - if (index != slider.Path.ControlPoints.Length - 1) + if (Index != slider.Path.ControlPoints.Length - 1) { path.AddVertex(Vector2.Zero); - path.AddVertex(slider.Path.ControlPoints[index + 1] - slider.Path.ControlPoints[index]); + path.AddVertex(slider.Path.ControlPoints[Index + 1] - slider.Path.ControlPoints[Index]); } path.OriginPosition = path.PositionInBoundingBox(Vector2.Zero); } + // The connecting path is excluded from positional input public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => marker.ReceivePositionalInputAt(screenSpacePos); protected override bool OnDragStart(DragStartEvent e) => true; @@ -80,7 +128,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { var newControlPoints = slider.Path.ControlPoints.ToArray(); - if (index == 0) + if (Index == 0) { // Special handling for the head - only the position of the slider changes slider.Position += e.Delta; @@ -90,13 +138,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components newControlPoints[i] -= e.Delta; } else - newControlPoints[index] += e.Delta; + newControlPoints[Index] += e.Delta; if (isSegmentSeparatorWithNext) - newControlPoints[index + 1] = newControlPoints[index]; + newControlPoints[Index + 1] = newControlPoints[Index]; if (isSegmentSeparatorWithPrevious) - newControlPoints[index - 1] = newControlPoints[index]; + newControlPoints[Index - 1] = newControlPoints[Index]; ControlPointsChanged?.Invoke(newControlPoints); @@ -107,8 +155,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private bool isSegmentSeparator => isSegmentSeparatorWithNext || isSegmentSeparatorWithPrevious; - private bool isSegmentSeparatorWithNext => index < slider.Path.ControlPoints.Length - 1 && slider.Path.ControlPoints[index + 1] == slider.Path.ControlPoints[index]; + private bool isSegmentSeparatorWithNext => Index < slider.Path.ControlPoints.Length - 1 && slider.Path.ControlPoints[Index + 1] == slider.Path.ControlPoints[Index]; - private bool isSegmentSeparatorWithPrevious => index > 0 && slider.Path.ControlPoints[index - 1] == slider.Path.ControlPoints[index]; + private bool isSegmentSeparatorWithPrevious => Index > 0 && slider.Path.ControlPoints[Index - 1] == slider.Path.ControlPoints[Index]; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 0385824b27..b0e579907d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.Objects; using osuTK; @@ -21,6 +22,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { this.slider = slider; + RelativeSizeAxes = Axes.Both; + InternalChild = pieces = new Container { RelativeSizeAxes = Axes.Both }; } @@ -33,5 +36,23 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components while (slider.Path.ControlPoints.Length < pieces.Count) pieces.Remove(pieces[pieces.Count - 1]); } + + protected override bool OnMouseDown(MouseDownEvent e) + { + bool anySelected = false; + + foreach (var piece in pieces) + { + if (piece.IsHovered) + { + piece.IsSelected.Value = true; + anySelected = true; + } + else + piece.IsSelected.Value = false; + } + + return anySelected; + } } } From bf45fa630984d624828bbeaf34ee7498a93fc170 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 16:24:03 +0900 Subject: [PATCH 3723/5608] Use lambda function expression --- osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs index 8c150e6ed1..3fecfbdaaf 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs @@ -138,10 +138,7 @@ namespace osu.Game.Overlays.BeatmapSet return false; } - protected override void OnHoverLost(HoverLostEvent e) - { - updateState(); - } + protected override void OnHoverLost(HoverLostEvent e) => updateState(); #endregion } From cfdf7106764b904c733e001eeba71b1e6b005d97 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 16:51:58 +0900 Subject: [PATCH 3724/5608] Add test --- .../TestSceneSliderSelectionBlueprint.cs | 33 +++++++++++++++++++ .../Components/PathControlPointVisualiser.cs | 16 ++++----- .../Sliders/SliderSelectionBlueprint.cs | 3 +- .../Visual/SelectionBlueprintTestScene.cs | 2 +- 4 files changed, 44 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs index 5df0b70f12..0e7d8c9c08 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs @@ -16,6 +16,7 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Tests.Visual; using osuTK; +using osuTK.Input; namespace osu.Game.Rulesets.Osu.Tests { @@ -85,6 +86,25 @@ namespace osu.Game.Rulesets.Osu.Tests checkPositions(); } + [Test] + public void TestSingleControlPointSelection() + { + moveMouseToControlPoint(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkControlPointSelected(0, true); + checkControlPointSelected(1, false); + + moveMouseToControlPoint(1); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkControlPointSelected(0, false); + checkControlPointSelected(1, true); + + AddStep("move mouse outside control point", () => InputManager.MoveMouseTo(drawableObject)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkControlPointSelected(0, false); + checkControlPointSelected(1, false); + } + private void moveHitObject() { AddStep("move hitobject", () => @@ -104,11 +124,24 @@ namespace osu.Game.Rulesets.Osu.Tests () => Precision.AlmostEquals(blueprint.TailBlueprint.CirclePiece.ScreenSpaceDrawQuad.Centre, drawableObject.TailCircle.ScreenSpaceDrawQuad.Centre)); } + private void moveMouseToControlPoint(int index) + { + AddStep($"move mouse to control point {index}", () => + { + Vector2 position = slider.Position + slider.Path.ControlPoints[index]; + InputManager.MoveMouseTo(drawableObject.Parent.ToScreenSpace(position)); + }); + } + + private void checkControlPointSelected(int index, bool selected) + => AddAssert($"control point {index} {(selected ? "selected" : "not selected")}", () => blueprint.ControlPointVisualiser.Pieces[index].IsSelected.Value == selected); + private class TestSliderBlueprint : SliderSelectionBlueprint { public new SliderBodyPiece BodyPiece => base.BodyPiece; public new TestSliderCircleBlueprint HeadBlueprint => (TestSliderCircleBlueprint)base.HeadBlueprint; public new TestSliderCircleBlueprint TailBlueprint => (TestSliderCircleBlueprint)base.TailBlueprint; + public new PathControlPointVisualiser ControlPointVisualiser => base.ControlPointVisualiser; public TestSliderBlueprint(DrawableSlider slider) : base(slider) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index b0e579907d..6efa0ef550 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -14,9 +14,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public Action ControlPointsChanged; - private readonly Slider slider; + internal Container Pieces { get; } - private readonly Container pieces; + private readonly Slider slider; public PathControlPointVisualiser(Slider slider) { @@ -24,24 +24,24 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components RelativeSizeAxes = Axes.Both; - InternalChild = pieces = new Container { RelativeSizeAxes = Axes.Both }; + InternalChild = Pieces = new Container { RelativeSizeAxes = Axes.Both }; } protected override void Update() { base.Update(); - while (slider.Path.ControlPoints.Length > pieces.Count) - pieces.Add(new PathControlPointPiece(slider, pieces.Count) { ControlPointsChanged = c => ControlPointsChanged?.Invoke(c) }); - while (slider.Path.ControlPoints.Length < pieces.Count) - pieces.Remove(pieces[pieces.Count - 1]); + while (slider.Path.ControlPoints.Length > Pieces.Count) + Pieces.Add(new PathControlPointPiece(slider, Pieces.Count) { ControlPointsChanged = c => ControlPointsChanged?.Invoke(c) }); + while (slider.Path.ControlPoints.Length < Pieces.Count) + Pieces.Remove(Pieces[Pieces.Count - 1]); } protected override bool OnMouseDown(MouseDownEvent e) { bool anySelected = false; - foreach (var piece in pieces) + foreach (var piece in Pieces) { if (piece.IsHovered) { diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index b09f598bcc..ba502d3a7c 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -18,6 +18,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders protected readonly SliderBodyPiece BodyPiece; protected readonly SliderCircleSelectionBlueprint HeadBlueprint; protected readonly SliderCircleSelectionBlueprint TailBlueprint; + protected readonly PathControlPointVisualiser ControlPointVisualiser; [Resolved(CanBeNull = true)] private HitObjectComposer composer { get; set; } @@ -32,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders BodyPiece = new SliderBodyPiece(), HeadBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.Start), TailBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.End), - new PathControlPointVisualiser(sliderObject) { ControlPointsChanged = onNewControlPoints }, + ControlPointVisualiser = new PathControlPointVisualiser(sliderObject) { ControlPointsChanged = onNewControlPoints }, }; } diff --git a/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs index f53c12b047..3233ee160d 100644 --- a/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs +++ b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.Edit; namespace osu.Game.Tests.Visual { - public abstract class SelectionBlueprintTestScene : OsuTestScene + public abstract class SelectionBlueprintTestScene : ManualInputManagerTestScene { protected override Container Content => content ?? base.Content; private readonly Container content; From fe93df718675d16c931a67b903e4fbeee7fe6dcc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 16:52:56 +0900 Subject: [PATCH 3725/5608] Remove unnecessary using statement --- osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 6c7a3e4108..286971bc90 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -3,7 +3,6 @@ using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapSet; From 4f04abf2825d374f3deefd4bc013606f50d2400f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 16:54:28 +0900 Subject: [PATCH 3726/5608] Fix tabs to match design (should not show pinhair line) --- osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs index 3fecfbdaaf..cdea49afe7 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs @@ -120,7 +120,7 @@ namespace osu.Game.Overlays.BeatmapSet { var isHoveredOrActive = IsHovered || Active.Value; - bar.ResizeHeightTo(isHoveredOrActive ? 4 : 1, 200, Easing.OutQuint); + bar.ResizeHeightTo(isHoveredOrActive ? 4 : 0, 200, Easing.OutQuint); name.Colour = isHoveredOrActive ? colour.GrayE : colour.GrayC; name.Font = name.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Regular); From 3e3ff812291f343d1847ecd037914e38ddf70d50 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 17:13:00 +0900 Subject: [PATCH 3727/5608] Reorder methods --- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index bffe779da1..bf2a92cd4f 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -45,38 +45,10 @@ namespace osu.Game.Overlays.BeatmapSet if (value == beatmapSet) return; beatmapSet = value; - updateDisplay(); } } - private void updateDisplay() - { - Difficulties.Clear(); - - if (BeatmapSet != null) - { - Difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.Where(b => b.Ruleset.Equals(ruleset.Value)).OrderBy(b => b.StarDifficulty).Select(b => new DifficultySelectorButton(b) - { - State = DifficultySelectorState.NotSelected, - OnHovered = beatmap => - { - showBeatmap(beatmap); - starRating.Text = beatmap.StarDifficulty.ToString("Star Difficulty 0.##"); - starRating.FadeIn(100); - }, - OnClicked = beatmap => { Beatmap.Value = beatmap; }, - }); - } - - starRating.FadeOut(100); - Beatmap.Value = Difficulties.FirstOrDefault()?.Beatmap; - plays.Value = BeatmapSet?.OnlineInfo.PlayCount ?? 0; - favourites.Value = BeatmapSet?.OnlineInfo.FavouriteCount ?? 0; - - updateDifficultyButtons(); - } - public BeatmapPicker() { RelativeSizeAxes = Axes.X; @@ -169,6 +141,33 @@ namespace osu.Game.Overlays.BeatmapSet Beatmap.TriggerChange(); } + private void updateDisplay() + { + Difficulties.Clear(); + + if (BeatmapSet != null) + { + Difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps.Where(b => b.Ruleset.Equals(ruleset.Value)).OrderBy(b => b.StarDifficulty).Select(b => new DifficultySelectorButton(b) + { + State = DifficultySelectorState.NotSelected, + OnHovered = beatmap => + { + showBeatmap(beatmap); + starRating.Text = beatmap.StarDifficulty.ToString("Star Difficulty 0.##"); + starRating.FadeIn(100); + }, + OnClicked = beatmap => { Beatmap.Value = beatmap; }, + }); + } + + starRating.FadeOut(100); + Beatmap.Value = Difficulties.FirstOrDefault()?.Beatmap; + plays.Value = BeatmapSet?.OnlineInfo.PlayCount ?? 0; + favourites.Value = BeatmapSet?.OnlineInfo.FavouriteCount ?? 0; + + updateDifficultyButtons(); + } + private void showBeatmap(BeatmapInfo beatmap) { version.Text = beatmap?.Version; From 8d50b155e8022f43bca1a9c824ee8697aa4acf70 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 17:13:10 +0900 Subject: [PATCH 3728/5608] Make selection happen on click only --- .../Components/PathControlPointPiece.cs | 25 ++++++++++++++-- .../Components/PathControlPointVisualiser.cs | 30 ++++++++++--------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 3b0b9bce1f..bd6a905b38 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -18,9 +18,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public class PathControlPointPiece : BlueprintPiece { + public Action RequestSelection; public Action ControlPointsChanged; - public readonly Bindable IsSelected = new Bindable(); + public readonly Bindable IsSelected = new Bindable(); public readonly int Index; private readonly Slider slider; @@ -28,6 +29,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private readonly Container marker; private readonly Drawable markerRing; + private bool isClicked; + [Resolved] private OsuColour colours { get; set; } @@ -98,7 +101,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components markerRing.Alpha = IsSelected.Value ? 1 : 0; Color4 colour = isSegmentSeparator ? colours.Red : colours.Yellow; - if (IsHovered || IsSelected.Value) + if (IsHovered || isClicked || IsSelected.Value) colour = Color4.White; marker.Colour = colour; } @@ -122,6 +125,24 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components // The connecting path is excluded from positional input public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => marker.ReceivePositionalInputAt(screenSpacePos); + protected override bool OnMouseDown(MouseDownEvent e) + { + isClicked = true; + return true; + } + + protected override bool OnMouseUp(MouseUpEvent e) + { + isClicked = false; + return true; + } + + protected override bool OnClick(ClickEvent e) + { + RequestSelection?.Invoke(Index); + return true; + } + protected override bool OnDragStart(DragStartEvent e) => true; protected override bool OnDrag(DragEvent e) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 6efa0ef550..160168eb37 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -32,27 +32,29 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components base.Update(); while (slider.Path.ControlPoints.Length > Pieces.Count) - Pieces.Add(new PathControlPointPiece(slider, Pieces.Count) { ControlPointsChanged = c => ControlPointsChanged?.Invoke(c) }); + { + Pieces.Add(new PathControlPointPiece(slider, Pieces.Count) + { + ControlPointsChanged = c => ControlPointsChanged?.Invoke(c), + RequestSelection = selectPiece + }); + } + while (slider.Path.ControlPoints.Length < Pieces.Count) Pieces.Remove(Pieces[Pieces.Count - 1]); } - protected override bool OnMouseDown(MouseDownEvent e) + protected override bool OnClick(ClickEvent e) { - bool anySelected = false; - foreach (var piece in Pieces) - { - if (piece.IsHovered) - { - piece.IsSelected.Value = true; - anySelected = true; - } - else - piece.IsSelected.Value = false; - } + piece.IsSelected.Value = false; + return false; + } - return anySelected; + private void selectPiece(int index) + { + foreach (var piece in Pieces) + piece.IsSelected.Value = piece.Index == index; } } } From ce19b2ed36b04186014123222a12067e9301c927 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 17:16:26 +0900 Subject: [PATCH 3729/5608] Avoid using CreateChildDependencies with a *child* bindable Don't do this. --- osu.Game/Overlays/BeatmapSet/Header.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 0e3d29c25b..7b42e7e459 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -50,6 +50,9 @@ namespace osu.Game.Overlays.BeatmapSet private readonly LoadingAnimation loading; + [Cached(typeof(IBindable))] + private readonly Bindable ruleset = new Bindable(); + public Header() { ExternalLinkButton externalLink; @@ -80,6 +83,7 @@ namespace osu.Game.Overlays.BeatmapSet }, RulesetSelector = new BeatmapRulesetSelector { + Current = ruleset, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, } @@ -222,13 +226,6 @@ namespace osu.Game.Overlays.BeatmapSet }; } - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs>(RulesetSelector.Current); - return dependencies; - } - [BackgroundDependencyLoader] private void load(OsuColour colours) { From 20aeb7aaffe4fe48bfcfa820a49f7765dc544bce Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 17:25:30 +0900 Subject: [PATCH 3730/5608] Implement multiple selection --- .../TestSceneSliderSelectionBlueprint.cs | 68 +++++++++++++++++++ .../Components/PathControlPointVisualiser.cs | 22 ++++-- 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs index 0e7d8c9c08..dde2aa53e0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs @@ -93,11 +93,79 @@ namespace osu.Game.Rulesets.Osu.Tests AddStep("click", () => InputManager.Click(MouseButton.Left)); checkControlPointSelected(0, true); checkControlPointSelected(1, false); + } + + [Test] + public void TestSingleControlPointDeselectionViaOtherControlPoint() + { + moveMouseToControlPoint(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); moveMouseToControlPoint(1); AddStep("click", () => InputManager.Click(MouseButton.Left)); checkControlPointSelected(0, false); checkControlPointSelected(1, true); + } + + [Test] + public void TestSingleControlPointDeselectionViaClickOutside() + { + moveMouseToControlPoint(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + + AddStep("move mouse outside control point", () => InputManager.MoveMouseTo(drawableObject)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkControlPointSelected(0, false); + checkControlPointSelected(1, false); + } + + [Test] + public void TestMultipleControlPointSelection() + { + moveMouseToControlPoint(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + moveMouseToControlPoint(1); + AddStep("ctrl + click", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.Click(MouseButton.Left); + InputManager.ReleaseKey(Key.ControlLeft); + }); + checkControlPointSelected(0, true); + checkControlPointSelected(1, true); + } + + [Test] + public void TestMultipleControlPointDeselectionViaOtherControlPoint() + { + moveMouseToControlPoint(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + moveMouseToControlPoint(1); + AddStep("ctrl + click", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.Click(MouseButton.Left); + InputManager.ReleaseKey(Key.ControlLeft); + }); + + moveMouseToControlPoint(2); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkControlPointSelected(0, false); + checkControlPointSelected(1, false); + } + + [Test] + public void TestMultipleControlPointDeselectionViaClickOutside() + { + moveMouseToControlPoint(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + moveMouseToControlPoint(1); + AddStep("ctrl + click", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.Click(MouseButton.Left); + InputManager.ReleaseKey(Key.ControlLeft); + }); AddStep("move mouse outside control point", () => InputManager.MoveMouseTo(drawableObject)); AddStep("click", () => InputManager.Click(MouseButton.Left)); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 160168eb37..bbe771d8b0 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.Objects; using osuTK; @@ -14,10 +15,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public Action ControlPointsChanged; - internal Container Pieces { get; } - + internal readonly Container Pieces; private readonly Slider slider; + private InputManager inputManager; + public PathControlPointVisualiser(Slider slider) { this.slider = slider; @@ -27,6 +29,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components InternalChild = Pieces = new Container { RelativeSizeAxes = Axes.Both }; } + protected override void LoadComplete() + { + base.LoadComplete(); + + inputManager = GetContainingInputManager(); + } + protected override void Update() { base.Update(); @@ -53,8 +62,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private void selectPiece(int index) { - foreach (var piece in Pieces) - piece.IsSelected.Value = piece.Index == index; + if (inputManager.CurrentState.Keyboard.ControlPressed) + Pieces[index].IsSelected.Value = true; + else + { + foreach (var piece in Pieces) + piece.IsSelected.Value = piece.Index == index; + } } } } From 43b2cbb865f031eacb431a7d8ccb5fd4fbd04954 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 16:25:26 +0900 Subject: [PATCH 3731/5608] Implement slider control point deletion --- .../Components/PathControlPointVisualiser.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index bbe771d8b0..b578c75474 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -2,12 +2,16 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Edit.Compose; using osuTK; +using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { @@ -20,6 +24,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private InputManager inputManager; + [Resolved(CanBeNull = true)] + private IPlacementHandler placementHandler { get; set; } + public PathControlPointVisualiser(Slider slider) { this.slider = slider; @@ -70,5 +77,44 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components piece.IsSelected.Value = piece.Index == index; } } + + protected override bool OnKeyDown(KeyDownEvent e) + { + switch (e.Key) + { + case Key.Delete: + var newControlPoints = new List(); + + foreach (var piece in pieces) + { + if (!piece.IsSelected.Value) + newControlPoints.Add(slider.Path.ControlPoints[piece.Index]); + } + + // Ensure that there are any points to be deleted + if (newControlPoints.Count == slider.Path.ControlPoints.Length) + return false; + + // If there are 0 remaining control points, treat the slider as being deleted + if (newControlPoints.Count == 0) + { + placementHandler?.Delete(slider); + return true; + } + + // Make control points relative + Vector2 first = newControlPoints[0]; + for (int i = 0; i < newControlPoints.Count; i++) + newControlPoints[i] = newControlPoints[i] - first; + + // The slider's position defines the position of the first control point, and all further control points are relative to that point + slider.Position = slider.Position + first; + ControlPointsChanged?.Invoke(newControlPoints.ToArray()); + + return true; + } + + return false; + } } } From 83abb845b648def4b42b2cebace3f5ace3c78e01 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 17:50:06 +0900 Subject: [PATCH 3732/5608] Fix code quality --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 66911d9615..efd4aae23e 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -74,7 +74,13 @@ namespace osu.Game.Graphics.Containers { RelativeSizeAxes = Axes.Both, TooltipText = tooltipText ?? (url != text ? url : string.Empty), - Action = action ?? (() => game.HandleLink(url, linkType, linkArgument)), + Action = () => + { + if (action != null) + action(); + else + game.HandleLink(url, linkType, linkArgument); + }, }); return drawables; From 78194cfa6e193c53cef9a4417a8cbbbe7d7283f6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 17:54:06 +0900 Subject: [PATCH 3733/5608] Implement slider control point deletions --- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index b578c75474..17eb236ae0 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components case Key.Delete: var newControlPoints = new List(); - foreach (var piece in pieces) + foreach (var piece in Pieces) { if (!piece.IsSelected.Value) newControlPoints.Add(slider.Path.ControlPoints[piece.Index]); From 18f374eec653612784227dfcbe7d6aaf914e5c5b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 17:58:33 +0900 Subject: [PATCH 3734/5608] Deselect deleted control points --- .../Sliders/Components/PathControlPointVisualiser.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 17eb236ae0..a6ee928c90 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -109,6 +109,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components // The slider's position defines the position of the first control point, and all further control points are relative to that point slider.Position = slider.Position + first; + + // Since pieces are re-used, they will not point to the deleted control points while remaining selected + foreach (var piece in Pieces) + piece.IsSelected.Value = false; + ControlPointsChanged?.Invoke(newControlPoints.ToArray()); return true; From 9f28b1905b50b19511d10b698d1d97da0a2267f9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 18:15:19 +0900 Subject: [PATCH 3735/5608] Expose composer method to update hitobject --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 23 +++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 5922bfba78..1c942e52ce 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Edit EditorBeatmap = new EditorBeatmap(playableBeatmap); EditorBeatmap.HitObjectAdded += addHitObject; EditorBeatmap.HitObjectRemoved += removeHitObject; - EditorBeatmap.StartTimeChanged += updateHitObject; + EditorBeatmap.StartTimeChanged += UpdateHitObject; var dependencies = new DependencyContainer(parent); dependencies.CacheAs(EditorBeatmap); @@ -225,11 +225,7 @@ namespace osu.Game.Rulesets.Edit private ScheduledDelegate scheduledUpdate; - private void addHitObject(HitObject hitObject) => updateHitObject(hitObject); - - private void removeHitObject(HitObject hitObject) => updateHitObject(null); - - private void updateHitObject([CanBeNull] HitObject hitObject) + public override void UpdateHitObject(HitObject hitObject) { scheduledUpdate?.Cancel(); scheduledUpdate = Schedule(() => @@ -240,6 +236,10 @@ namespace osu.Game.Rulesets.Edit }); } + private void addHitObject(HitObject hitObject) => UpdateHitObject(hitObject); + + private void removeHitObject(HitObject hitObject) => UpdateHitObject(null); + public override IEnumerable HitObjects => drawableRulesetWrapper.Playfield.AllHitObjects; public override bool CursorInPlacementArea => drawableRulesetWrapper.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); @@ -351,11 +351,22 @@ namespace osu.Game.Rulesets.Edit [CanBeNull] protected virtual DistanceSnapGrid CreateDistanceSnapGrid([NotNull] IEnumerable selectedHitObjects) => null; + /// + /// Updates a , invoking and re-processing the beatmap. + /// + /// The to update. + public abstract void UpdateHitObject([CanBeNull] HitObject hitObject); + public abstract (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time); + public abstract float GetBeatSnapDistanceAt(double referenceTime); + public abstract float DurationToDistance(double referenceTime, double duration); + public abstract double DistanceToDuration(double referenceTime, float distance); + public abstract double GetSnappedDurationFromDistance(double referenceTime, float distance); + public abstract float GetSnappedDistanceFromDistance(double referenceTime, float distance); } } From 41ae66d517e7a005f5f17e3faf1e583eb26b2151 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 18:24:38 +0900 Subject: [PATCH 3736/5608] Update slider when control points change --- .../Blueprints/Sliders/SliderSelectionBlueprint.cs | 2 ++ osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index b09f598bcc..585a477aba 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -49,6 +49,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders var snappedDistance = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)unsnappedPath.Distance) ?? (float)unsnappedPath.Distance; HitObject.Path = new SliderPath(unsnappedPath.Type, controlPoints, snappedDistance); + + UpdateHitObject(); } public override Vector2 SelectionPoint => HeadBlueprint.SelectionPoint; diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 44f38acfd4..0701513933 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -3,10 +3,12 @@ using System; using osu.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osuTK; @@ -36,6 +38,9 @@ namespace osu.Game.Rulesets.Edit public override bool HandlePositionalInput => ShouldBeAlive; public override bool RemoveWhenNotAlive => false; + [Resolved(CanBeNull = true)] + private HitObjectComposer composer { get; set; } + protected SelectionBlueprint(DrawableHitObject drawableObject) { DrawableObject = drawableObject; @@ -89,6 +94,11 @@ namespace osu.Game.Rulesets.Edit public bool IsSelected => State == SelectionState.Selected; + /// + /// Updates the , invoking and re-processing the beatmap. + /// + protected void UpdateHitObject() => composer?.UpdateHitObject(DrawableObject.HitObject); + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => DrawableObject.ReceivePositionalInputAt(screenSpacePos); /// From 11447023eb21ad6f251a95d1310d16bf7852c003 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 18:34:41 +0900 Subject: [PATCH 3737/5608] Improve splitting out of link handling --- .../Graphics/Containers/LinkFlowContainer.cs | 29 +++++++++--------- osu.Game/Online/Chat/MessageFormatter.cs | 19 ++++++------ osu.Game/OsuGame.cs | 30 +++++++------------ osu.Game/Overlays/Changelog/ChangelogBuild.cs | 4 +-- .../Screens/Multi/Components/BeatmapTitle.cs | 2 +- osu.iOS/AppDelegate.cs | 2 +- 6 files changed, 40 insertions(+), 46 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index efd4aae23e..b5ffd1c6ad 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -44,46 +44,47 @@ namespace osu.Game.Graphics.Containers foreach (var link in links) { AddText(text.Substring(previousLinkEnd, link.Index - previousLinkEnd)); - AddLink(text.Substring(link.Index, link.Length), link.Url, link.Action, link.Argument); + AddLink(text.Substring(link.Index, link.Length), link.Action, link.Argument ?? link.Url); previousLinkEnd = link.Index + link.Length; } AddText(text.Substring(previousLinkEnd)); } - public IEnumerable AddLink(string text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action creationParameters = null) - => createLink(AddText(text, creationParameters), text, url, linkType, linkArgument, tooltipText); + public void AddLink(string text, string url, Action creationParameters = null) => + createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.External, url), text); - public IEnumerable AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) - => createLink(AddText(text, creationParameters), text, tooltipText: tooltipText, action: action); + public void AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) + => createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.Custom, null), tooltipText, action); - public IEnumerable AddLink(IEnumerable text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null) + public void AddLink(string text, LinkAction action, string argument, string tooltipText = null, Action creationParameters = null) + => createLink(AddText(text, creationParameters), new LinkDetails(action, argument), null); + + public void AddLink(IEnumerable text, LinkAction action = LinkAction.External, string linkArgument = null, string tooltipText = null) { foreach (var t in text) AddArbitraryDrawable(t); - return createLink(text, null, url, linkType, linkArgument, tooltipText); + createLink(text, new LinkDetails(action, linkArgument), tooltipText); } - public IEnumerable AddUserLink(User user, Action creationParameters = null) - => createLink(AddText(user.Username, creationParameters), user.Username, null, LinkAction.OpenUserProfile, user.Id.ToString(), "View profile"); + public void AddUserLink(User user, Action creationParameters = null) + => createLink(AddText(user.Username, creationParameters), new LinkDetails(LinkAction.OpenUserProfile, user.Id.ToString()), "View Profile"); - private IEnumerable createLink(IEnumerable drawables, string text, string url = null, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action action = null) + private void createLink(IEnumerable drawables, LinkDetails link, string tooltipText, Action action = null) { AddInternal(new DrawableLinkCompiler(drawables.OfType().ToList()) { RelativeSizeAxes = Axes.Both, - TooltipText = tooltipText ?? (url != text ? url : string.Empty), + TooltipText = tooltipText, Action = () => { if (action != null) action(); else - game.HandleLink(url, linkType, linkArgument); + game.HandleLink(link); }, }); - - return drawables; } // We want the compilers to always be visible no matter where they are, so RelativeSizeAxes is used. diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 31a324d0ea..717de18c14 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -255,17 +255,17 @@ namespace osu.Game.Online.Chat OriginalText = Text = text; } } + } - public class LinkDetails + public class LinkDetails + { + public LinkAction Action; + public string Argument; + + public LinkDetails(LinkAction action, string argument) { - public LinkAction Action; - public string Argument; - - public LinkDetails(LinkAction action, string argument) - { - Action = action; - Argument = argument; - } + Action = action; + Argument = argument; } } @@ -279,6 +279,7 @@ namespace osu.Game.Online.Chat JoinMultiplayerMatch, Spectate, OpenUserProfile, + Custom } public class Link : IComparable diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index c028896cff..b55cc41454 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -43,7 +43,6 @@ using osu.Game.Scoring; using osu.Game.Screens.Select; using osu.Game.Utils; using LogLevel = osu.Framework.Logging.LogLevel; -using static osu.Game.Online.Chat.MessageFormatter; namespace osu.Game { @@ -216,7 +215,9 @@ namespace osu.Game private ExternalLinkOpener externalLinkOpener; - public void HandleLink(string url, LinkAction linkType, string linkArgument) + public void HandleLink(string url) => HandleLink(MessageFormatter.GetLinkDetails(url)); + + public void HandleLink(LinkDetails link) { Action showNotImplementedError = () => notifications?.Post(new SimpleNotification { @@ -224,27 +225,27 @@ namespace osu.Game Icon = FontAwesome.Solid.LifeRing, }); - switch (linkType) + switch (link.Action) { case LinkAction.OpenBeatmap: // TODO: proper query params handling - if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) + if (link.Argument != null && int.TryParse(link.Argument.Contains('?') ? link.Argument.Split('?')[0] : link.Argument, out int beatmapId)) ShowBeatmap(beatmapId); break; case LinkAction.OpenBeatmapSet: - if (int.TryParse(linkArgument, out int setId)) + if (int.TryParse(link.Argument, out int setId)) ShowBeatmapSet(setId); break; case LinkAction.OpenChannel: try { - channelManager.OpenChannel(linkArgument); + channelManager.OpenChannel(link.Argument); } catch (ChannelNotFoundException) { - Logger.Log($"The requested channel \"{linkArgument}\" does not exist"); + Logger.Log($"The requested channel \"{link.Argument}\" does not exist"); } break; @@ -256,28 +257,19 @@ namespace osu.Game break; case LinkAction.External: - OpenUrlExternally(url); + OpenUrlExternally(link.Argument); break; case LinkAction.OpenUserProfile: - if (long.TryParse(linkArgument, out long userId)) + if (long.TryParse(link.Argument, out long userId)) ShowUser(userId); break; default: - throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); + throw new NotImplementedException($"This {nameof(LinkAction)} ({link.Action.ToString()}) is missing an associated action."); } } - public void HandleUrl(string url) - { - Logger.Log($"Request to handle url: {url}"); - - LinkDetails linkDetails = GetLinkDetails(url); - - Schedule(() => HandleLink(url, linkDetails.Action, linkDetails.Argument)); - } - public void OpenUrlExternally(string url) { if (url.StartsWith("/")) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index bce1be5941..d8488b21ab 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -110,7 +110,7 @@ namespace osu.Game.Overlays.Changelog t.Font = fontLarge; t.Colour = entryColour; }); - title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, Online.Chat.LinkAction.External, + title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, creationParameters: t => { t.Font = fontLarge; @@ -140,7 +140,7 @@ namespace osu.Game.Overlays.Changelog t.Colour = entryColour; }); else if (entry.GithubUser.GithubUrl != null) - title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t => + title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, t => { t.Font = fontMedium; t.Colour = entryColour; diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index e096fb33da..f79cac7649 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Multi.Components Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title)), Font = OsuFont.GetFont(size: TextSize), } - }, null, LinkAction.OpenBeatmap, beatmap.OnlineBeatmapID.ToString(), "Open beatmap"); + }, LinkAction.OpenBeatmap, beatmap.OnlineBeatmapID.ToString(), "Open beatmap"); } } } diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs index 07e0245195..164a182ebe 100644 --- a/osu.iOS/AppDelegate.cs +++ b/osu.iOS/AppDelegate.cs @@ -21,7 +21,7 @@ namespace osu.iOS if (url.IsFileUrl) Task.Run(() => game.Import(url.Path)); else - Task.Run(() => game.HandleUrl(url.AbsoluteString)); + Task.Run(() => game.HandleLink(url.AbsoluteString)); return true; } } From f13dc93a4d867352797046d7a5b46a9c941eaf06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 18:49:13 +0900 Subject: [PATCH 3738/5608] Fix external link tooltip regression --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index b5ffd1c6ad..61391b7102 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -52,7 +52,7 @@ namespace osu.Game.Graphics.Containers } public void AddLink(string text, string url, Action creationParameters = null) => - createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.External, url), text); + createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.External, url), url); public void AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) => createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.Custom, null), tooltipText, action); From e3ca64bb8c6dad982b579d126fbaefa402629c04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 19:18:54 +0900 Subject: [PATCH 3739/5608] Remove iOS "import from stable" for now --- osu.Game/Database/ArchiveModelManager.cs | 2 +- osu.iOS/Info.plist | 8 +++----- osu.iOS/OsuGameIOS.cs | 2 -- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 3c1e07b765..9fed8e03ac 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -67,7 +67,7 @@ namespace osu.Game.Database public virtual string[] HandledExtensions => new[] { ".zip" }; - public virtual bool SupportsImportFromStable => (RuntimeInfo.IsDesktop || RuntimeInfo.OS == RuntimeInfo.Platform.iOS); + public virtual bool SupportsImportFromStable => RuntimeInfo.IsDesktop; protected readonly FileStore Files; diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index 67f71b64b6..5ceccdf99f 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -34,9 +34,9 @@ UIStatusBarHidden NSCameraUsageDescription - We don't really use the camera. - NSMicrophoneUsageDescription - We don't really use the microphone. + We don't really use the camera. + NSMicrophoneUsageDescription + We don't really use the microphone. UISupportedInterfaceOrientations UIInterfaceOrientationPortrait @@ -111,8 +111,6 @@ - UIFileSharingEnabled - CFBundleURLTypes diff --git a/osu.iOS/OsuGameIOS.cs b/osu.iOS/OsuGameIOS.cs index ac66357fc9..6cf18df9a6 100644 --- a/osu.iOS/OsuGameIOS.cs +++ b/osu.iOS/OsuGameIOS.cs @@ -3,14 +3,12 @@ using System; using Foundation; -using osu.Framework.Platform; using osu.Game; namespace osu.iOS { public class OsuGameIOS : OsuGame { - public override Storage GetStorageForStableInstall() => Storage; public override Version AssemblyVersion => new Version(NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString()); } } From ba65d0e4ee712fcc1f87b3f07205db05c1406c26 Mon Sep 17 00:00:00 2001 From: Jai Sharma Date: Thu, 31 Oct 2019 12:39:09 +0000 Subject: [PATCH 3740/5608] Force ordering of issue templates --- .github/ISSUE_TEMPLATE/{mobile-issues.md => 00-mobile-issues.md} | 0 .github/ISSUE_TEMPLATE/{bug-issues.md => 01-bug-issues.md} | 0 .github/ISSUE_TEMPLATE/{crash-issues.md => 02-crash-issues.md} | 0 .../{missing-for-live-issues.md => 03-missing-for-live.md} | 0 .../{feature-request-issues.md => 04-feature-request-issues.md} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename .github/ISSUE_TEMPLATE/{mobile-issues.md => 00-mobile-issues.md} (100%) rename .github/ISSUE_TEMPLATE/{bug-issues.md => 01-bug-issues.md} (100%) rename .github/ISSUE_TEMPLATE/{crash-issues.md => 02-crash-issues.md} (100%) rename .github/ISSUE_TEMPLATE/{missing-for-live-issues.md => 03-missing-for-live.md} (100%) rename .github/ISSUE_TEMPLATE/{feature-request-issues.md => 04-feature-request-issues.md} (100%) diff --git a/.github/ISSUE_TEMPLATE/mobile-issues.md b/.github/ISSUE_TEMPLATE/00-mobile-issues.md similarity index 100% rename from .github/ISSUE_TEMPLATE/mobile-issues.md rename to .github/ISSUE_TEMPLATE/00-mobile-issues.md diff --git a/.github/ISSUE_TEMPLATE/bug-issues.md b/.github/ISSUE_TEMPLATE/01-bug-issues.md similarity index 100% rename from .github/ISSUE_TEMPLATE/bug-issues.md rename to .github/ISSUE_TEMPLATE/01-bug-issues.md diff --git a/.github/ISSUE_TEMPLATE/crash-issues.md b/.github/ISSUE_TEMPLATE/02-crash-issues.md similarity index 100% rename from .github/ISSUE_TEMPLATE/crash-issues.md rename to .github/ISSUE_TEMPLATE/02-crash-issues.md diff --git a/.github/ISSUE_TEMPLATE/missing-for-live-issues.md b/.github/ISSUE_TEMPLATE/03-missing-for-live.md similarity index 100% rename from .github/ISSUE_TEMPLATE/missing-for-live-issues.md rename to .github/ISSUE_TEMPLATE/03-missing-for-live.md diff --git a/.github/ISSUE_TEMPLATE/feature-request-issues.md b/.github/ISSUE_TEMPLATE/04-feature-request-issues.md similarity index 100% rename from .github/ISSUE_TEMPLATE/feature-request-issues.md rename to .github/ISSUE_TEMPLATE/04-feature-request-issues.md From 08b1631dbbfe496c0df15ad8aa2632dfa20b8e9f Mon Sep 17 00:00:00 2001 From: Jai Sharma Date: Thu, 31 Oct 2019 12:42:25 +0000 Subject: [PATCH 3741/5608] Add issue template config --- .github/ISSUE_TEMPLATE/config.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..69baeee60c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: osu!stable issues + url: https://github.com/ppy/osu-stable-issues + about: For issues regarding osu!stable (not osu!lazer), open them here. From 3ada1510d04f635ae36050060b8534f66c5e2a08 Mon Sep 17 00:00:00 2001 From: Jai Sharma Date: Thu, 31 Oct 2019 13:09:36 +0000 Subject: [PATCH 3742/5608] Remove 'missing-for-live.md' --- ...ture-request-issues.md => 03-feature-request-issues.md} | 0 .github/ISSUE_TEMPLATE/03-missing-for-live.md | 7 ------- 2 files changed, 7 deletions(-) rename .github/ISSUE_TEMPLATE/{04-feature-request-issues.md => 03-feature-request-issues.md} (100%) delete mode 100644 .github/ISSUE_TEMPLATE/03-missing-for-live.md diff --git a/.github/ISSUE_TEMPLATE/04-feature-request-issues.md b/.github/ISSUE_TEMPLATE/03-feature-request-issues.md similarity index 100% rename from .github/ISSUE_TEMPLATE/04-feature-request-issues.md rename to .github/ISSUE_TEMPLATE/03-feature-request-issues.md diff --git a/.github/ISSUE_TEMPLATE/03-missing-for-live.md b/.github/ISSUE_TEMPLATE/03-missing-for-live.md deleted file mode 100644 index 5822da9c65..0000000000 --- a/.github/ISSUE_TEMPLATE/03-missing-for-live.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -name: Missing for Live -about: Features which are available in osu!stable but not yet in osu!lazer. ---- -**Describe the missing feature:** - -**Proposal designs of the feature:** From 944380906324d53936b67b04b30e9a01097bdb42 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 11:22:32 +0900 Subject: [PATCH 3743/5608] Protect against requests to show overlays before the target overlay is ready --- osu.Game/OsuGame.cs | 77 ++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b55cc41454..fb9a7f7965 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -215,16 +215,20 @@ namespace osu.Game private ExternalLinkOpener externalLinkOpener; - public void HandleLink(string url) => HandleLink(MessageFormatter.GetLinkDetails(url)); + /// + /// Handle an arbitrary URL. Displays via in-game overlays where possible. + /// This can be called from a non-thread-safe non-game-loaded state. + /// + /// The URL to load. + public void HandleLink(string url) => Schedule(() => HandleLink(MessageFormatter.GetLinkDetails(url))); + /// + /// Handle a specific . + /// This can be called from a non-thread-safe non-game-loaded state. + /// + /// The link to load. public void HandleLink(LinkDetails link) { - Action showNotImplementedError = () => notifications?.Post(new SimpleNotification - { - Text = @"This link type is not yet supported!", - Icon = FontAwesome.Solid.LifeRing, - }); - switch (link.Action) { case LinkAction.OpenBeatmap: @@ -239,21 +243,17 @@ namespace osu.Game break; case LinkAction.OpenChannel: - try - { - channelManager.OpenChannel(link.Argument); - } - catch (ChannelNotFoundException) - { - Logger.Log($"The requested channel \"{link.Argument}\" does not exist"); - } - + ShowChannel(link.Argument); break; case LinkAction.OpenEditorTimestamp: case LinkAction.JoinMultiplayerMatch: case LinkAction.Spectate: - showNotImplementedError.Invoke(); + waitForReady(() => notifications, _ => notifications?.Post(new SimpleNotification + { + Text = @"This link type is not yet supported!", + Icon = FontAwesome.Solid.LifeRing, + })); break; case LinkAction.External: @@ -270,31 +270,47 @@ namespace osu.Game } } - public void OpenUrlExternally(string url) + public void OpenUrlExternally(string url) => waitForReady(() => externalLinkOpener, _ => { if (url.StartsWith("/")) url = $"{API.Endpoint}{url}"; externalLinkOpener.OpenUrlExternally(url); - } + }); + + /// + /// Open a specific channel in chat. + /// + /// The channel to display. + public void ShowChannel(string channel) => waitForReady(() => channelManager, _ => + { + try + { + channelManager.OpenChannel(channel); + } + catch (ChannelNotFoundException) + { + Logger.Log($"The requested channel \"{channel}\" does not exist"); + } + }); /// /// Show a beatmap set as an overlay. /// /// The set to display. - public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId); + public void ShowBeatmapSet(int setId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmapSet(setId)); /// /// Show a user's profile as an overlay. /// /// The user to display. - public void ShowUser(long userId) => userProfile.ShowUser(userId); + public void ShowUser(long userId) => waitForReady(() => userProfile, _ => userProfile.ShowUser(userId)); /// /// Show a beatmap's set as an overlay, displaying the given beatmap. /// /// The beatmap to show. - public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId); + public void ShowBeatmap(int beatmapId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId)); /// /// Present a beatmap at song select immediately. @@ -452,6 +468,23 @@ namespace osu.Game performFromMainMenuTask = Schedule(() => performFromMainMenu(action, taskName)); } + /// + /// Wait for the game (and target component) to become loaded and then run an action. + /// + /// A function to retrieve a (potentially not-yet-constructed) target instance. + /// The action to perform on the instance when load is confirmed. + /// The type of the target instance. + private void waitForReady(Func retrieveInstance, Action action) + where T : Drawable + { + var instance = retrieveInstance(); + + if (ScreenStack == null || ScreenStack.CurrentScreen is StartupScreen || instance?.IsLoaded != true) + Schedule(() => waitForReady(retrieveInstance, action)); + else + action(instance); + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From 898520935ec5c26994ac209ccd8229eb362b880e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 11:40:51 +0900 Subject: [PATCH 3744/5608] Move link handling code to OsuGame This allows for future calls from arguments / associations --- .../Graphics/Containers/LinkFlowContainer.cs | 92 +++++-------------- osu.Game/Online/Chat/MessageFormatter.cs | 25 ++--- osu.Game/OsuGame.cs | 55 +++++++++++ osu.Game/Overlays/Changelog/ChangelogBuild.cs | 4 +- .../Screens/Multi/Components/BeatmapTitle.cs | 2 +- 5 files changed, 92 insertions(+), 86 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 15068d81c0..61391b7102 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -8,9 +8,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using System.Collections.Generic; using osu.Framework.Graphics; -using osu.Framework.Logging; -using osu.Game.Overlays; -using osu.Game.Overlays.Notifications; using osu.Game.Users; namespace osu.Game.Graphics.Containers @@ -23,21 +20,12 @@ namespace osu.Game.Graphics.Containers } private OsuGame game; - private ChannelManager channelManager; - private Action showNotImplementedError; [BackgroundDependencyLoader(true)] - private void load(OsuGame game, NotificationOverlay notifications, ChannelManager channelManager) + private void load(OsuGame game) { // will be null in tests this.game = game; - this.channelManager = channelManager; - - showNotImplementedError = () => notifications?.Post(new SimpleNotification - { - Text = @"This link type is not yet supported!", - Icon = FontAwesome.Solid.LifeRing, - }); } public void AddLinks(string text, List links) @@ -56,85 +44,47 @@ namespace osu.Game.Graphics.Containers foreach (var link in links) { AddText(text.Substring(previousLinkEnd, link.Index - previousLinkEnd)); - AddLink(text.Substring(link.Index, link.Length), link.Url, link.Action, link.Argument); + AddLink(text.Substring(link.Index, link.Length), link.Action, link.Argument ?? link.Url); previousLinkEnd = link.Index + link.Length; } AddText(text.Substring(previousLinkEnd)); } - public IEnumerable AddLink(string text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action creationParameters = null) - => createLink(AddText(text, creationParameters), text, url, linkType, linkArgument, tooltipText); + public void AddLink(string text, string url, Action creationParameters = null) => + createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.External, url), url); - public IEnumerable AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) - => createLink(AddText(text, creationParameters), text, tooltipText: tooltipText, action: action); + public void AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) + => createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.Custom, null), tooltipText, action); - public IEnumerable AddLink(IEnumerable text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null) + public void AddLink(string text, LinkAction action, string argument, string tooltipText = null, Action creationParameters = null) + => createLink(AddText(text, creationParameters), new LinkDetails(action, argument), null); + + public void AddLink(IEnumerable text, LinkAction action = LinkAction.External, string linkArgument = null, string tooltipText = null) { foreach (var t in text) AddArbitraryDrawable(t); - return createLink(text, null, url, linkType, linkArgument, tooltipText); + createLink(text, new LinkDetails(action, linkArgument), tooltipText); } - public IEnumerable AddUserLink(User user, Action creationParameters = null) - => createLink(AddText(user.Username, creationParameters), user.Username, null, LinkAction.OpenUserProfile, user.Id.ToString(), "View profile"); + public void AddUserLink(User user, Action creationParameters = null) + => createLink(AddText(user.Username, creationParameters), new LinkDetails(LinkAction.OpenUserProfile, user.Id.ToString()), "View Profile"); - private IEnumerable createLink(IEnumerable drawables, string text, string url = null, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action action = null) + private void createLink(IEnumerable drawables, LinkDetails link, string tooltipText, Action action = null) { AddInternal(new DrawableLinkCompiler(drawables.OfType().ToList()) { RelativeSizeAxes = Axes.Both, - TooltipText = tooltipText ?? (url != text ? url : string.Empty), - Action = action ?? (() => + TooltipText = tooltipText, + Action = () => { - switch (linkType) - { - case LinkAction.OpenBeatmap: - // TODO: proper query params handling - if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) - game?.ShowBeatmap(beatmapId); - break; - - case LinkAction.OpenBeatmapSet: - if (int.TryParse(linkArgument, out int setId)) - game?.ShowBeatmapSet(setId); - break; - - case LinkAction.OpenChannel: - try - { - channelManager?.OpenChannel(linkArgument); - } - catch (ChannelNotFoundException) - { - Logger.Log($"The requested channel \"{linkArgument}\" does not exist"); - } - - break; - - case LinkAction.OpenEditorTimestamp: - case LinkAction.JoinMultiplayerMatch: - case LinkAction.Spectate: - showNotImplementedError?.Invoke(); - break; - - case LinkAction.External: - game?.OpenUrlExternally(url); - break; - - case LinkAction.OpenUserProfile: - if (long.TryParse(linkArgument, out long userId)) - game?.ShowUser(userId); - break; - - default: - throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); - } - }), + if (action != null) + action(); + else + game.HandleLink(link); + }, }); - - return drawables; } // We want the compilers to always be visible no matter where they are, so RelativeSizeAxes is used. diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 3ffff281f8..717de18c14 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -81,7 +81,7 @@ namespace osu.Game.Online.Chat //since we just changed the line display text, offset any already processed links. result.Links.ForEach(l => l.Index -= l.Index > index ? m.Length - displayText.Length : 0); - var details = getLinkDetails(linkText); + var details = GetLinkDetails(linkText); result.Links.Add(new Link(linkText, index, displayText.Length, linkActionOverride ?? details.Action, details.Argument)); //adjust the offset for processing the current matches group. @@ -98,7 +98,7 @@ namespace osu.Game.Online.Chat var linkText = m.Groups["link"].Value; var indexLength = linkText.Length; - var details = getLinkDetails(linkText); + var details = GetLinkDetails(linkText); var link = new Link(linkText, index, indexLength, details.Action, details.Argument); // sometimes an already-processed formatted link can reduce to a simple URL, too @@ -109,7 +109,7 @@ namespace osu.Game.Online.Chat } } - private static LinkDetails getLinkDetails(string url) + public static LinkDetails GetLinkDetails(string url) { var args = url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); args[0] = args[0].TrimEnd(':'); @@ -255,17 +255,17 @@ namespace osu.Game.Online.Chat OriginalText = Text = text; } } + } - public class LinkDetails + public class LinkDetails + { + public LinkAction Action; + public string Argument; + + public LinkDetails(LinkAction action, string argument) { - public LinkAction Action; - public string Argument; - - public LinkDetails(LinkAction action, string argument) - { - Action = action; - Argument = argument; - } + Action = action; + Argument = argument; } } @@ -279,6 +279,7 @@ namespace osu.Game.Online.Chat JoinMultiplayerMatch, Spectate, OpenUserProfile, + Custom } public class Link : IComparable diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 4dcc181bea..b55cc41454 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -215,6 +215,61 @@ namespace osu.Game private ExternalLinkOpener externalLinkOpener; + public void HandleLink(string url) => HandleLink(MessageFormatter.GetLinkDetails(url)); + + public void HandleLink(LinkDetails link) + { + Action showNotImplementedError = () => notifications?.Post(new SimpleNotification + { + Text = @"This link type is not yet supported!", + Icon = FontAwesome.Solid.LifeRing, + }); + + switch (link.Action) + { + case LinkAction.OpenBeatmap: + // TODO: proper query params handling + if (link.Argument != null && int.TryParse(link.Argument.Contains('?') ? link.Argument.Split('?')[0] : link.Argument, out int beatmapId)) + ShowBeatmap(beatmapId); + break; + + case LinkAction.OpenBeatmapSet: + if (int.TryParse(link.Argument, out int setId)) + ShowBeatmapSet(setId); + break; + + case LinkAction.OpenChannel: + try + { + channelManager.OpenChannel(link.Argument); + } + catch (ChannelNotFoundException) + { + Logger.Log($"The requested channel \"{link.Argument}\" does not exist"); + } + + break; + + case LinkAction.OpenEditorTimestamp: + case LinkAction.JoinMultiplayerMatch: + case LinkAction.Spectate: + showNotImplementedError.Invoke(); + break; + + case LinkAction.External: + OpenUrlExternally(link.Argument); + break; + + case LinkAction.OpenUserProfile: + if (long.TryParse(link.Argument, out long userId)) + ShowUser(userId); + break; + + default: + throw new NotImplementedException($"This {nameof(LinkAction)} ({link.Action.ToString()}) is missing an associated action."); + } + } + public void OpenUrlExternally(string url) { if (url.StartsWith("/")) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index bce1be5941..d8488b21ab 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -110,7 +110,7 @@ namespace osu.Game.Overlays.Changelog t.Font = fontLarge; t.Colour = entryColour; }); - title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, Online.Chat.LinkAction.External, + title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, creationParameters: t => { t.Font = fontLarge; @@ -140,7 +140,7 @@ namespace osu.Game.Overlays.Changelog t.Colour = entryColour; }); else if (entry.GithubUser.GithubUrl != null) - title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t => + title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, t => { t.Font = fontMedium; t.Colour = entryColour; diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index e096fb33da..f79cac7649 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Multi.Components Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title)), Font = OsuFont.GetFont(size: TextSize), } - }, null, LinkAction.OpenBeatmap, beatmap.OnlineBeatmapID.ToString(), "Open beatmap"); + }, LinkAction.OpenBeatmap, beatmap.OnlineBeatmapID.ToString(), "Open beatmap"); } } } From f038c579f01b89327c57f0ff307c0917957c9667 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 11:22:32 +0900 Subject: [PATCH 3745/5608] Protect against requests to show overlays before the target overlay is ready --- osu.Game/OsuGame.cs | 77 ++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b55cc41454..fb9a7f7965 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -215,16 +215,20 @@ namespace osu.Game private ExternalLinkOpener externalLinkOpener; - public void HandleLink(string url) => HandleLink(MessageFormatter.GetLinkDetails(url)); + /// + /// Handle an arbitrary URL. Displays via in-game overlays where possible. + /// This can be called from a non-thread-safe non-game-loaded state. + /// + /// The URL to load. + public void HandleLink(string url) => Schedule(() => HandleLink(MessageFormatter.GetLinkDetails(url))); + /// + /// Handle a specific . + /// This can be called from a non-thread-safe non-game-loaded state. + /// + /// The link to load. public void HandleLink(LinkDetails link) { - Action showNotImplementedError = () => notifications?.Post(new SimpleNotification - { - Text = @"This link type is not yet supported!", - Icon = FontAwesome.Solid.LifeRing, - }); - switch (link.Action) { case LinkAction.OpenBeatmap: @@ -239,21 +243,17 @@ namespace osu.Game break; case LinkAction.OpenChannel: - try - { - channelManager.OpenChannel(link.Argument); - } - catch (ChannelNotFoundException) - { - Logger.Log($"The requested channel \"{link.Argument}\" does not exist"); - } - + ShowChannel(link.Argument); break; case LinkAction.OpenEditorTimestamp: case LinkAction.JoinMultiplayerMatch: case LinkAction.Spectate: - showNotImplementedError.Invoke(); + waitForReady(() => notifications, _ => notifications?.Post(new SimpleNotification + { + Text = @"This link type is not yet supported!", + Icon = FontAwesome.Solid.LifeRing, + })); break; case LinkAction.External: @@ -270,31 +270,47 @@ namespace osu.Game } } - public void OpenUrlExternally(string url) + public void OpenUrlExternally(string url) => waitForReady(() => externalLinkOpener, _ => { if (url.StartsWith("/")) url = $"{API.Endpoint}{url}"; externalLinkOpener.OpenUrlExternally(url); - } + }); + + /// + /// Open a specific channel in chat. + /// + /// The channel to display. + public void ShowChannel(string channel) => waitForReady(() => channelManager, _ => + { + try + { + channelManager.OpenChannel(channel); + } + catch (ChannelNotFoundException) + { + Logger.Log($"The requested channel \"{channel}\" does not exist"); + } + }); /// /// Show a beatmap set as an overlay. /// /// The set to display. - public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId); + public void ShowBeatmapSet(int setId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmapSet(setId)); /// /// Show a user's profile as an overlay. /// /// The user to display. - public void ShowUser(long userId) => userProfile.ShowUser(userId); + public void ShowUser(long userId) => waitForReady(() => userProfile, _ => userProfile.ShowUser(userId)); /// /// Show a beatmap's set as an overlay, displaying the given beatmap. /// /// The beatmap to show. - public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId); + public void ShowBeatmap(int beatmapId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId)); /// /// Present a beatmap at song select immediately. @@ -452,6 +468,23 @@ namespace osu.Game performFromMainMenuTask = Schedule(() => performFromMainMenu(action, taskName)); } + /// + /// Wait for the game (and target component) to become loaded and then run an action. + /// + /// A function to retrieve a (potentially not-yet-constructed) target instance. + /// The action to perform on the instance when load is confirmed. + /// The type of the target instance. + private void waitForReady(Func retrieveInstance, Action action) + where T : Drawable + { + var instance = retrieveInstance(); + + if (ScreenStack == null || ScreenStack.CurrentScreen is StartupScreen || instance?.IsLoaded != true) + Schedule(() => waitForReady(retrieveInstance, action)); + else + action(instance); + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From 0171b2ae7c0882e2d0ad7e499d4e4369b580af6b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 12:10:03 +0900 Subject: [PATCH 3746/5608] Fix scrolling hitobjects expiring too soon --- .../UI/Scrolling/ScrollingHitObjectContainer.cs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index e00597dd56..857929ff9e 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -13,12 +13,6 @@ namespace osu.Game.Rulesets.UI.Scrolling { public class ScrollingHitObjectContainer : HitObjectContainer { - /// - /// A multiplier applied to the length of the scrolling area to determine a safe default lifetime end for hitobjects. - /// This is only used to limit the lifetime end within reason, as proper lifetime management should be implemented on hitobjects themselves. - /// - private const float safe_lifetime_end_multiplier = 2; - private readonly IBindable timeRange = new BindableDouble(); private readonly IBindable direction = new Bindable(); @@ -123,28 +117,22 @@ namespace osu.Game.Rulesets.UI.Scrolling if (cached.IsValid) return; - double endTime = hitObject.HitObject.StartTime; - if (hitObject.HitObject is IHasEndTime e) { - endTime = e.EndTime; - switch (direction.Value) { case ScrollingDirection.Up: case ScrollingDirection.Down: - hitObject.Height = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, endTime, timeRange.Value, scrollLength); + hitObject.Height = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, e.EndTime, timeRange.Value, scrollLength); break; case ScrollingDirection.Left: case ScrollingDirection.Right: - hitObject.Width = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, endTime, timeRange.Value, scrollLength); + hitObject.Width = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, e.EndTime, timeRange.Value, scrollLength); break; } } - hitObject.LifetimeEnd = scrollingInfo.Algorithm.TimeAt(scrollLength * safe_lifetime_end_multiplier, endTime, timeRange.Value, scrollLength); - foreach (var obj in hitObject.NestedHitObjects) { computeInitialStateRecursive(obj); From ac02bb005d982603c55002d8212af592453a584d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 14:11:18 +0900 Subject: [PATCH 3747/5608] Fix GameplayClockContainer operating on beatmap's track after scren exited --- osu.Game/Screens/Play/GameplayClockContainer.cs | 15 ++++++++++++++- osu.Game/Screens/Play/Player.cs | 4 ++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 6a03271b86..f2efbe6073 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -29,7 +30,7 @@ namespace osu.Game.Screens.Play /// /// The original source (usually a 's track). /// - private readonly IAdjustableClock sourceClock; + private IAdjustableClock sourceClock; public readonly BindableBool IsPaused = new BindableBool(); @@ -153,6 +154,18 @@ namespace osu.Game.Screens.Play IsPaused.Value = true; } + /// + /// Changes the backing clock to avoid using the originally provided beatmap's track. + /// + public void StopUsingBeatmapClock() + { + if (sourceClock != beatmap.Track) + return; + + sourceClock = new TrackVirtual(beatmap.Track.Length); + adjustableClock.ChangeSource(sourceClock); + } + public void ResetLocalAdjustments() { // In the case of replays, we may have changed the playback rate. diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0b363eac4d..4820c62da3 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -527,6 +527,10 @@ namespace osu.Game.Screens.Play GameplayClockContainer.ResetLocalAdjustments(); + // 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(); + fadeOut(); return base.OnExiting(next); } From dcc8f6e82799b3fe7055068b446780ad5ed76113 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 14:43:52 +0900 Subject: [PATCH 3748/5608] Better group cancel conditional --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7eccde4555..280ebca651 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -446,9 +446,9 @@ namespace osu.Game.Screens.Play if (IsResuming) { DrawableRuleset.CancelResume(); + IsResuming = false; } - IsResuming = false; GameplayClockContainer.Stop(); PauseOverlay.Show(); lastPauseActionTime = GameplayClockContainer.GameplayClock.CurrentTime; From 05002ea3e8cd308e46e8147f909920ebd56300b3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 14:50:38 +0900 Subject: [PATCH 3749/5608] Move Show/Hide code to PopIn/PopOut --- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 8347d255fa..aecfac3b70 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -38,9 +38,10 @@ namespace osu.Game.Rulesets.Osu.UI }); } - public override void Show() + protected override void PopIn() { - base.Show(); + base.PopIn(); + GameplayCursor.ActiveCursor.Hide(); cursorScaleContainer.MoveTo(GameplayCursor.ActiveCursor.Position); clickToResumeCursor.Appear(); @@ -55,13 +56,13 @@ namespace osu.Game.Rulesets.Osu.UI } } - public override void Hide() + protected override void PopOut() { + base.PopOut(); + localCursorContainer?.Expire(); localCursorContainer = null; - GameplayCursor.ActiveCursor.Show(); - - base.Hide(); + GameplayCursor?.ActiveCursor.Show(); } protected override bool OnHover(HoverEvent e) => true; From 14fec6f1f35e4cf9e9a0e65a535e407c68ba9ed5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 15:06:36 +0900 Subject: [PATCH 3750/5608] Move ReplayDownloadButton to correct namespace --- .../Visual/Gameplay/TestSceneReplayDownloadButton.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs | 1 + .../{Play => Ranking/Pages}/ReplayDownloadButton.cs | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) rename osu.Game/Screens/{Play => Ranking/Pages}/ReplayDownloadButton.cs (98%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs index 0dfcda122f..4c870e04f5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs @@ -7,11 +7,11 @@ using osu.Game.Online; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Osu; using osu.Game.Scoring; -using osu.Game.Screens.Play; using osu.Game.Users; using osuTK; using System; using System.Collections.Generic; +using osu.Game.Screens.Ranking.Pages; namespace osu.Game.Tests.Visual.Gameplay { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs index f3c8f89db7..c4b42f6356 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs @@ -26,6 +26,7 @@ namespace osu.Game.Tests.Visual.Gameplay typeof(Results), typeof(ResultsPage), typeof(ScoreResultsPage), + typeof(ReplayDownloadButton), typeof(LocalLeaderboardPage) }; diff --git a/osu.Game/Screens/Play/ReplayDownloadButton.cs b/osu.Game/Screens/Ranking/Pages/ReplayDownloadButton.cs similarity index 98% rename from osu.Game/Screens/Play/ReplayDownloadButton.cs rename to osu.Game/Screens/Ranking/Pages/ReplayDownloadButton.cs index 290e00f287..c8f4ecd2d5 100644 --- a/osu.Game/Screens/Play/ReplayDownloadButton.cs +++ b/osu.Game/Screens/Ranking/Pages/ReplayDownloadButton.cs @@ -4,12 +4,12 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Online; -using osu.Game.Scoring; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Graphics.UserInterface; +using osu.Game.Online; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Scoring; -namespace osu.Game.Screens.Play +namespace osu.Game.Screens.Ranking.Pages { public class ReplayDownloadButton : DownloadTrackingComposite { From e23ea94383e293c26764125637ef4627232f436f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 15:33:38 +0900 Subject: [PATCH 3751/5608] Add one more level of null check --- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index aecfac3b70..3b18e41f30 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Osu.UI localCursorContainer?.Expire(); localCursorContainer = null; - GameplayCursor?.ActiveCursor.Show(); + GameplayCursor?.ActiveCursor?.Show(); } protected override bool OnHover(HoverEvent e) => true; From 84d17f3702bdf25f37a1bfffa34a216a8ab031f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 15:32:06 +0900 Subject: [PATCH 3752/5608] Add retry button --- .../Gameplay/TestSceneReplayDownloadButton.cs | 2 - .../Visual/Gameplay/TestSceneResults.cs | 2 +- osu.Game/Screens/Play/Player.cs | 8 +-- .../Ranking/Pages/ReplayDownloadButton.cs | 2 + osu.Game/Screens/Ranking/Pages/RetryButton.cs | 59 +++++++++++++++++++ .../Screens/Ranking/Pages/ScoreResultsPage.cs | 11 +++- 6 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 osu.Game/Screens/Ranking/Pages/RetryButton.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs index 4c870e04f5..7b22fedbd5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs @@ -8,7 +8,6 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Osu; using osu.Game.Scoring; using osu.Game.Users; -using osuTK; using System; using System.Collections.Generic; using osu.Game.Screens.Ranking.Pages; @@ -42,7 +41,6 @@ namespace osu.Game.Tests.Visual.Gameplay { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(80, 40), }; }); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs index c4b42f6356..bf26892539 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs @@ -22,10 +22,10 @@ namespace osu.Game.Tests.Visual.Gameplay public override IReadOnlyList RequiredTypes => new[] { - typeof(ScoreInfo), typeof(Results), typeof(ResultsPage), typeof(ScoreResultsPage), + typeof(RetryButton), typeof(ReplayDownloadButton), typeof(LocalLeaderboardPage) }; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0b363eac4d..38068ec751 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -30,6 +30,7 @@ using osu.Game.Users; namespace osu.Game.Screens.Play { + [Cached] public class Player : ScreenWithBeatmapBackground { public override bool AllowBackButton => false; // handled by HoldForMenuButton @@ -313,12 +314,11 @@ namespace osu.Game.Screens.Play public void Restart() { - if (!this.IsCurrentScreen()) return; - sampleRestart?.Play(); - RestartRequested?.Invoke(); - performImmediateExit(); + + if (this.IsCurrentScreen()) + performImmediateExit(); } private ScheduledDelegate completionProgressDelegate; diff --git a/osu.Game/Screens/Ranking/Pages/ReplayDownloadButton.cs b/osu.Game/Screens/Ranking/Pages/ReplayDownloadButton.cs index c8f4ecd2d5..73c647d6fa 100644 --- a/osu.Game/Screens/Ranking/Pages/ReplayDownloadButton.cs +++ b/osu.Game/Screens/Ranking/Pages/ReplayDownloadButton.cs @@ -8,6 +8,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online; using osu.Game.Online.API.Requests.Responses; using osu.Game.Scoring; +using osuTK; namespace osu.Game.Screens.Ranking.Pages { @@ -33,6 +34,7 @@ namespace osu.Game.Screens.Ranking.Pages public ReplayDownloadButton(ScoreInfo score) : base(score) { + Size = new Vector2(50, 30); } [BackgroundDependencyLoader(true)] diff --git a/osu.Game/Screens/Ranking/Pages/RetryButton.cs b/osu.Game/Screens/Ranking/Pages/RetryButton.cs new file mode 100644 index 0000000000..c4f63b265d --- /dev/null +++ b/osu.Game/Screens/Ranking/Pages/RetryButton.cs @@ -0,0 +1,59 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Screens; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Play; +using osuTK; + +namespace osu.Game.Screens.Ranking.Pages +{ + public class RetryButton : OsuAnimatedButton + { + private readonly Box background; + + [Resolved(canBeNull: true)] + private Player player { get; set; } + + public RetryButton() + { + Size = new Vector2(50, 30); + + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + Depth = float.MaxValue + }, + new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(13), + Icon = FontAwesome.Solid.ArrowCircleLeft, + }, + }; + + TooltipText = "Retry"; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.Green; + + if (player != null) + Action = () => + { + player.Restart(); + player.MakeCurrent(); + }; + } + } +} diff --git a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs index 56ae069a26..27cea99f1c 100644 --- a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs +++ b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs @@ -169,12 +169,19 @@ namespace osu.Game.Screens.Ranking.Pages }, }, }, - new ReplayDownloadButton(score) + new FillFlowContainer { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, Margin = new MarginPadding { Bottom = 10 }, - Size = new Vector2(50, 30), + Spacing = new Vector2(5), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new ReplayDownloadButton(score), + new RetryButton() + } }, }; From c532f7765737b6dfd9e7609eba0dde8fddc324ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 15:49:36 +0900 Subject: [PATCH 3753/5608] Add hold-to-retry support to results --- osu.Game/Screens/Ranking/Results.cs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index cac26b3dbf..a7ff1fe6a0 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -19,6 +19,7 @@ using osu.Game.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Sprites; using osu.Game.Scoring; +using osu.Game.Screens.Play; namespace osu.Game.Screens.Ranking { @@ -34,6 +35,9 @@ namespace osu.Game.Screens.Ranking private ResultModeTabControl modeChangeButtons; + [Resolved(canBeNull: true)] + private Player player { get; set; } + public override bool DisallowExternalBeatmapRulesetChanges => true; protected readonly ScoreInfo Score; @@ -100,10 +104,7 @@ namespace osu.Game.Screens.Ranking public override bool OnExiting(IScreen next) { - allCircles.ForEach(c => - { - c.ScaleTo(0, transition_time, Easing.OutSine); - }); + allCircles.ForEach(c => { c.ScaleTo(0, transition_time, Easing.OutSine); }); Background.ScaleTo(1f, transition_time / 4, Easing.OutQuint); @@ -253,7 +254,17 @@ namespace osu.Game.Screens.Ranking } } } - } + }, + new HotkeyRetryOverlay + { + Action = () => + { + if (!this.IsCurrentScreen()) return; + + player.Restart(); + player.MakeCurrent(); + }, + }, }; var pages = CreateResultPages(); From 14453da1d2b254af738c322f9fd9ba25bb078b0e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 15:51:10 +0900 Subject: [PATCH 3754/5608] Centralise MakeCurrent call --- osu.Game/Screens/Play/Player.cs | 2 ++ osu.Game/Screens/Ranking/Pages/RetryButton.cs | 7 +------ osu.Game/Screens/Ranking/Results.cs | 1 - 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 38068ec751..769688e829 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -319,6 +319,8 @@ namespace osu.Game.Screens.Play if (this.IsCurrentScreen()) performImmediateExit(); + else + this.MakeCurrent(); } private ScheduledDelegate completionProgressDelegate; diff --git a/osu.Game/Screens/Ranking/Pages/RetryButton.cs b/osu.Game/Screens/Ranking/Pages/RetryButton.cs index c4f63b265d..2a281224c1 100644 --- a/osu.Game/Screens/Ranking/Pages/RetryButton.cs +++ b/osu.Game/Screens/Ranking/Pages/RetryButton.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play; @@ -49,11 +48,7 @@ namespace osu.Game.Screens.Ranking.Pages background.Colour = colours.Green; if (player != null) - Action = () => - { - player.Restart(); - player.MakeCurrent(); - }; + Action = () => player.Restart(); } } } diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index a7ff1fe6a0..ca2ee5adae 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -262,7 +262,6 @@ namespace osu.Game.Screens.Ranking if (!this.IsCurrentScreen()) return; player.Restart(); - player.MakeCurrent(); }, }, }; From daa0ebe2b57916f5408cdd5b3dbc1b0b6591e9f8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 15:51:45 +0900 Subject: [PATCH 3755/5608] Add xmldoc --- osu.Game/Screens/Play/Player.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 769688e829..f97114f929 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -312,6 +312,10 @@ namespace osu.Game.Screens.Play this.Exit(); } + /// + /// Restart gameplay via a parent . + /// This can be called from a child screen in order to trigger the restart process. + /// public void Restart() { sampleRestart?.Play(); From 156d0ae9b91c1bd6ea03a7b753807b0bcb4260a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 16:08:44 +0900 Subject: [PATCH 3756/5608] Remove braces Co-Authored-By: Salman Ahmed --- osu.Game/Screens/Ranking/Results.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index ca2ee5adae..d89932e105 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -104,7 +104,7 @@ namespace osu.Game.Screens.Ranking public override bool OnExiting(IScreen next) { - allCircles.ForEach(c => { c.ScaleTo(0, transition_time, Easing.OutSine); }); + allCircles.ForEach(c => c.ScaleTo(0, transition_time, Easing.OutSine)); Background.ScaleTo(1f, transition_time / 4, Easing.OutQuint); From ddd58ea3da88aedcb7123cd7921f656f4b5c9498 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 19:40:45 +0900 Subject: [PATCH 3757/5608] Use LongRunningLoad on network load components --- osu.Game/Audio/PreviewTrack.cs | 1 + osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs | 1 + osu.Game/Users/Drawables/DrawableAvatar.cs | 1 + 3 files changed, 3 insertions(+) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 22ce7d4711..ff667249a7 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -9,6 +9,7 @@ using osu.Framework.Threading; namespace osu.Game.Audio { + [LongRunningLoad] public abstract class PreviewTrack : Component { /// diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs index d0db7765c2..5245bc319d 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Beatmaps.Drawables { + [LongRunningLoad] public class BeatmapSetCover : Sprite { private readonly BeatmapSetInfo set; diff --git a/osu.Game/Users/Drawables/DrawableAvatar.cs b/osu.Game/Users/Drawables/DrawableAvatar.cs index ee3cf6331b..ee9af15863 100644 --- a/osu.Game/Users/Drawables/DrawableAvatar.cs +++ b/osu.Game/Users/Drawables/DrawableAvatar.cs @@ -13,6 +13,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Users.Drawables { + [LongRunningLoad] public class DrawableAvatar : Container { /// From d9a91100fb6448d33ec26896da0fd946d4b566dd Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Fri, 1 Nov 2019 22:46:13 +0700 Subject: [PATCH 3758/5608] Add tint to user's score container background --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 9387482f14..e5a8f565aa 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -21,6 +21,7 @@ using osu.Game.Users.Drawables; using osuTK; using osuTK.Graphics; using Humanizer; +using osu.Game.Online.API; namespace osu.Game.Online.Leaderboards { @@ -59,7 +60,7 @@ namespace osu.Game.Online.Leaderboards } [BackgroundDependencyLoader] - private void load() + private void load(IAPIProvider api, OsuColour colour) { var user = score.User; @@ -100,7 +101,7 @@ namespace osu.Game.Online.Leaderboards background = new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, + Colour = user.Id == api.LocalUser.Value.Id ? colour.YellowLight : Color4.Black, Alpha = background_alpha, }, }, From ce3b34a76878ee47c9c7ed93098e00c285c420e8 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Fri, 1 Nov 2019 23:00:55 +0700 Subject: [PATCH 3759/5608] Fix UserTopScoreContainer is also tinted --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 6 ++++-- .../Screens/Select/Leaderboards/UserTopScoreContainer.cs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index e5a8f565aa..f8d7c0b697 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -38,6 +38,7 @@ namespace osu.Game.Online.Leaderboards private readonly ScoreInfo score; private readonly int rank; + private readonly bool canHighlighted; private Box background; private Container content; @@ -50,10 +51,11 @@ namespace osu.Game.Online.Leaderboards private List statisticsLabels; - public LeaderboardScore(ScoreInfo score, int rank) + public LeaderboardScore(ScoreInfo score, int rank, bool canHighlighted = true) { this.score = score; this.rank = rank; + this.canHighlighted = canHighlighted; RelativeSizeAxes = Axes.X; Height = HEIGHT; @@ -101,7 +103,7 @@ namespace osu.Game.Online.Leaderboards background = new Box { RelativeSizeAxes = Axes.Both, - Colour = user.Id == api.LocalUser.Value.Id ? colour.YellowLight : Color4.Black, + Colour = user.Id == api.LocalUser.Value.Id && canHighlighted ? colour.YellowLight : Color4.Black, Alpha = background_alpha, }, }, diff --git a/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs index da8f676cd0..a787eb5629 100644 --- a/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs @@ -77,7 +77,7 @@ namespace osu.Game.Screens.Select.Leaderboards if (newScore == null) return; - LoadComponentAsync(new LeaderboardScore(newScore.Score, newScore.Position) + LoadComponentAsync(new LeaderboardScore(newScore.Score, newScore.Position, false) { Action = () => ScoreSelected?.Invoke(newScore.Score) }, drawableScore => From 8da15f68974258cf63c27a96ed92ed19195ae28c Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Fri, 1 Nov 2019 23:19:15 +0700 Subject: [PATCH 3760/5608] Fix all score are highlighted on local scope --- osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 337d46ecdd..3ef1fe5bc5 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -179,7 +179,7 @@ namespace osu.Game.Screens.Select.Leaderboards return req; } - protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) => new LeaderboardScore(model, index) + protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) => new LeaderboardScore(model, index, IsOnlineScope) { Action = () => ScoreSelected?.Invoke(model) }; From 2f703090ef1996c34eb4db392a894f015cdb0130 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 1 Nov 2019 21:49:50 +0300 Subject: [PATCH 3761/5608] 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 5be7d439ae2f149772372bdce9356c1d88163764 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sat, 2 Nov 2019 10:32:23 +0900 Subject: [PATCH 3762/5608] Add null check for nullable dependency --- osu.Game/Screens/Ranking/Results.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index d89932e105..3640197dad 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -261,7 +261,7 @@ namespace osu.Game.Screens.Ranking { if (!this.IsCurrentScreen()) return; - player.Restart(); + player?.Restart(); }, }, }; From fe3583b6eec4575a9bde01ef3454452071bdd161 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 3 Nov 2019 13:16:54 +0900 Subject: [PATCH 3763/5608] Move schedule call --- osu.Game/OsuGame.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index fb9a7f7965..1f823e6eba 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -220,14 +220,14 @@ namespace osu.Game /// This can be called from a non-thread-safe non-game-loaded state. /// /// The URL to load. - public void HandleLink(string url) => Schedule(() => HandleLink(MessageFormatter.GetLinkDetails(url))); + public void HandleLink(string url) => HandleLink(MessageFormatter.GetLinkDetails(url)); /// /// Handle a specific . /// This can be called from a non-thread-safe non-game-loaded state. /// /// The link to load. - public void HandleLink(LinkDetails link) + public void HandleLink(LinkDetails link) => Schedule(() => { switch (link.Action) { @@ -268,7 +268,7 @@ namespace osu.Game default: throw new NotImplementedException($"This {nameof(LinkAction)} ({link.Action.ToString()}) is missing an associated action."); } - } + }); public void OpenUrlExternally(string url) => waitForReady(() => externalLinkOpener, _ => { From 4dbdfcdd3c601a547887b9b563c06692feb6c53f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 3 Nov 2019 18:41:29 +0900 Subject: [PATCH 3764/5608] Change control to toggle rather than always select --- .../Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs | 2 +- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index bd6a905b38..e2ea6a12d7 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public Action RequestSelection; public Action ControlPointsChanged; - public readonly Bindable IsSelected = new Bindable(); + public readonly BindableBool IsSelected = new BindableBool(); public readonly int Index; private readonly Slider slider; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index bbe771d8b0..b70c11427a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private void selectPiece(int index) { if (inputManager.CurrentState.Keyboard.ControlPressed) - Pieces[index].IsSelected.Value = true; + Pieces[index].IsSelected.Toggle(); else { foreach (var piece in Pieces) From bcf8a6d514d6c44df4f3bcd4fca97a51464c7297 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 3 Nov 2019 19:59:37 +0900 Subject: [PATCH 3765/5608] Fix slider creation regressing with path selection changes --- .../Sliders/Components/PathControlPointPiece.cs | 13 +++++++++---- .../Components/PathControlPointVisualiser.cs | 14 ++++++++++---- .../Blueprints/Sliders/SliderPlacementBlueprint.cs | 2 +- .../Blueprints/Sliders/SliderSelectionBlueprint.cs | 2 +- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index e2ea6a12d7..cfcd266c7f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -128,19 +128,24 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components protected override bool OnMouseDown(MouseDownEvent e) { isClicked = true; - return true; + return false; } protected override bool OnMouseUp(MouseUpEvent e) { isClicked = false; - return true; + return false; } protected override bool OnClick(ClickEvent e) { - RequestSelection?.Invoke(Index); - return true; + if (RequestSelection != null) + { + RequestSelection.Invoke(Index); + return true; + } + + return false; } protected override bool OnDragStart(DragStartEvent e) => true; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index b70c11427a..c0fc5ccb0a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -17,12 +17,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components internal readonly Container Pieces; private readonly Slider slider; + private readonly bool allowSelection; private InputManager inputManager; - public PathControlPointVisualiser(Slider slider) + public PathControlPointVisualiser(Slider slider, bool allowSelection) { this.slider = slider; + this.allowSelection = allowSelection; RelativeSizeAxes = Axes.Both; @@ -42,11 +44,15 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components while (slider.Path.ControlPoints.Length > Pieces.Count) { - Pieces.Add(new PathControlPointPiece(slider, Pieces.Count) + var piece = new PathControlPointPiece(slider, Pieces.Count) { ControlPointsChanged = c => ControlPointsChanged?.Invoke(c), - RequestSelection = selectPiece - }); + }; + + if (allowSelection) + piece.RequestSelection = selectPiece; + + Pieces.Add(piece); } while (slider.Path.ControlPoints.Length < Pieces.Count) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 6f5309c2c2..9c0afada29 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders bodyPiece = new SliderBodyPiece(), headCirclePiece = new HitCirclePiece(), tailCirclePiece = new HitCirclePiece(), - new PathControlPointVisualiser(HitObject) { ControlPointsChanged = _ => updateSlider() }, + new PathControlPointVisualiser(HitObject, false) { ControlPointsChanged = _ => updateSlider() }, }; setState(PlacementState.Initial); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index f612ba9dfc..25362820a3 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders BodyPiece = new SliderBodyPiece(), HeadBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.Start), TailBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.End), - ControlPointVisualiser = new PathControlPointVisualiser(sliderObject) { ControlPointsChanged = onNewControlPoints }, + ControlPointVisualiser = new PathControlPointVisualiser(sliderObject, true) { ControlPointsChanged = onNewControlPoints }, }; } From 48385dbdfe2dfbe685fbd03a8ca09206a794c4e1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 3 Nov 2019 14:31:23 +0300 Subject: [PATCH 3766/5608] 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 3767/5608] 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 3768/5608] 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 3769/5608] 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 3770/5608] 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 3771/5608] 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 3772/5608] 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 3773/5608] 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 3774/5608] 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 3775/5608] 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 3776/5608] 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 3777/5608] 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 fe23b9a262d90ad9926d754e9d6bc4df5dd3ca42 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 3 Nov 2019 07:32:47 -0800 Subject: [PATCH 3778/5608] Fix mod section overflowing mod select overlay at higher ui scale --- osu.Game/Overlays/Mods/ModSection.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index dedd397fa5..35a94eb43f 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -158,7 +158,8 @@ namespace osu.Game.Overlays.Mods }, ButtonsContainer = new FillFlowContainer { - AutoSizeAxes = Axes.Both, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, Spacing = new Vector2(50f, 0f), From 1a7b803d4db52d824eb7899ca0e479e2cebed1a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 4 Nov 2019 08:39:51 +0900 Subject: [PATCH 3779/5608] Change colour to green to match web implementation --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index f8d7c0b697..623db07938 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -38,7 +38,7 @@ namespace osu.Game.Online.Leaderboards private readonly ScoreInfo score; private readonly int rank; - private readonly bool canHighlighted; + private readonly bool allowHighlight; private Box background; private Container content; @@ -51,11 +51,11 @@ namespace osu.Game.Online.Leaderboards private List statisticsLabels; - public LeaderboardScore(ScoreInfo score, int rank, bool canHighlighted = true) + public LeaderboardScore(ScoreInfo score, int rank, bool allowHighlight = true) { this.score = score; this.rank = rank; - this.canHighlighted = canHighlighted; + this.allowHighlight = allowHighlight; RelativeSizeAxes = Axes.X; Height = HEIGHT; @@ -103,7 +103,7 @@ namespace osu.Game.Online.Leaderboards background = new Box { RelativeSizeAxes = Axes.Both, - Colour = user.Id == api.LocalUser.Value.Id && canHighlighted ? colour.YellowLight : Color4.Black, + Colour = user.Id == api.LocalUser.Value.Id && allowHighlight ? colour.Green : Color4.Black, Alpha = background_alpha, }, }, From 3ec9580ba8b6724a2ae418933690e5a305444b4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 4 Nov 2019 01:52:26 +0100 Subject: [PATCH 3780/5608] Add test for retry overlay presence Add visual tests checking presence (or lack thereof) of the hold-to-retry overlay in the results screen. --- .../Visual/Gameplay/TestSceneResults.cs | 98 +++++++++++++++---- 1 file changed, 80 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs index bf26892539..7790126db5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneResults.cs @@ -3,11 +3,16 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Screens; using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; using osu.Game.Screens.Ranking.Pages; @@ -27,7 +32,8 @@ namespace osu.Game.Tests.Visual.Gameplay typeof(ScoreResultsPage), typeof(RetryButton), typeof(ReplayDownloadButton), - typeof(LocalLeaderboardPage) + typeof(LocalLeaderboardPage), + typeof(TestPlayer) }; [BackgroundDependencyLoader] @@ -43,26 +49,82 @@ namespace osu.Game.Tests.Visual.Gameplay var beatmapInfo = beatmaps.QueryBeatmap(b => b.RulesetID == 0); if (beatmapInfo != null) Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); + } - LoadScreen(new SoloResults(new ScoreInfo + private TestSoloResults createResultsScreen() => new TestSoloResults(new ScoreInfo + { + TotalScore = 2845370, + Accuracy = 0.98, + MaxCombo = 123, + Rank = ScoreRank.A, + Date = DateTimeOffset.Now, + Statistics = new Dictionary { - TotalScore = 2845370, - Accuracy = 0.98, - MaxCombo = 123, - Rank = ScoreRank.A, - Date = DateTimeOffset.Now, - Statistics = new Dictionary + { HitResult.Great, 50 }, + { HitResult.Good, 20 }, + { HitResult.Meh, 50 }, + { HitResult.Miss, 1 } + }, + User = new User + { + Username = "peppy", + } + }); + + [Test] + public void ResultsWithoutPlayer() + { + TestSoloResults screen = null; + + AddStep("load results", () => Child = new OsuScreenStack(screen = createResultsScreen()) + { + RelativeSizeAxes = Axes.Both + }); + AddUntilStep("wait for loaded", () => screen.IsLoaded); + AddAssert("retry overlay not present", () => screen.RetryOverlay == null); + } + + [Test] + public void ResultsWithPlayer() + { + TestSoloResults screen = null; + + AddStep("load results", () => Child = new TestResultsContainer(screen = createResultsScreen())); + AddUntilStep("wait for loaded", () => screen.IsLoaded); + AddAssert("retry overlay present", () => screen.RetryOverlay != null); + } + + private class TestResultsContainer : Container + { + [Cached(typeof(Player))] + private readonly Player player = new TestPlayer(); + + public TestResultsContainer(IScreen screen) + { + RelativeSizeAxes = Axes.Both; + + InternalChild = new OsuScreenStack(screen) { - { HitResult.Great, 50 }, - { HitResult.Good, 20 }, - { HitResult.Meh, 50 }, - { HitResult.Miss, 1 } - }, - User = new User - { - Username = "peppy", - } - })); + RelativeSizeAxes = Axes.Both, + }; + } + } + + private class TestSoloResults : SoloResults + { + public HotkeyRetryOverlay RetryOverlay; + + public TestSoloResults(ScoreInfo score) + : base(score) + { + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + RetryOverlay = InternalChildren.OfType().SingleOrDefault(); + } } } } From 539f8ad6dd952dd40943db2eea26d1c400fc74f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 4 Nov 2019 01:57:31 +0100 Subject: [PATCH 3781/5608] Remove overlay when viewing leaderboard scores Do not add the hold-to-retry hotkey overlay if the user has navigated to the results screen from the leaderboard and not from gameplay. --- osu.Game/Screens/Ranking/Results.cs | 269 ++++++++++++++-------------- 1 file changed, 135 insertions(+), 134 deletions(-) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 3640197dad..d063988b3f 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -116,146 +116,147 @@ namespace osu.Game.Screens.Ranking [BackgroundDependencyLoader] private void load(OsuColour colours) { - InternalChildren = new Drawable[] + InternalChild = new AspectContainer { - new AspectContainer + RelativeSizeAxes = Axes.Y, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Height = overscan, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Y, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Height = overscan, - Children = new Drawable[] + circleOuterBackground = new CircularContainer { - circleOuterBackground = new CircularContainer + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Masking = true, - Children = new Drawable[] + new Box { - new Box - { - Alpha = 0.2f, - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - } - } - }, - circleOuter = new CircularContainer - { - Size = new Vector2(circle_outer_scale), - EdgeEffect = new EdgeEffectParameters - { - Colour = Color4.Black.Opacity(0.4f), - Type = EdgeEffectType.Shadow, - Radius = 15, - }, - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Masking = true, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.White, - }, - backgroundParallax = new ParallaxContainer - { - RelativeSizeAxes = Axes.Both, - ParallaxAmount = 0.01f, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Children = new Drawable[] - { - new Sprite - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.2f, - Texture = Beatmap.Value.Background, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - FillMode = FillMode.Fill - } - } - }, - modeChangeButtons = new ResultModeTabControl - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - RelativeSizeAxes = Axes.X, - Height = 50, - Margin = new MarginPadding { Bottom = 110 }, - }, - new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.BottomCentre, - Text = $"{Score.MaxCombo}x", - RelativePositionAxes = Axes.X, - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 40), - X = 0.1f, - Colour = colours.BlueDarker, - }, - new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.TopCentre, - Text = "max combo", - Font = OsuFont.GetFont(size: 20), - RelativePositionAxes = Axes.X, - X = 0.1f, - Colour = colours.Gray6, - }, - new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.BottomCentre, - Text = $"{Score.Accuracy:P2}", - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 40), - RelativePositionAxes = Axes.X, - X = 0.9f, - Colour = colours.BlueDarker, - }, - new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.TopCentre, - Text = "accuracy", - Font = OsuFont.GetFont(size: 20), - RelativePositionAxes = Axes.X, - X = 0.9f, - Colour = colours.Gray6, - }, - } - }, - circleInner = new CircularContainer - { - Size = new Vector2(0.6f), - EdgeEffect = new EdgeEffectParameters - { - Colour = Color4.Black.Opacity(0.4f), - Type = EdgeEffectType.Shadow, - Radius = 15, - }, - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Masking = true, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.White, - }, + Alpha = 0.2f, + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, } } + }, + circleOuter = new CircularContainer + { + Size = new Vector2(circle_outer_scale), + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0.4f), + Type = EdgeEffectType.Shadow, + Radius = 15, + }, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }, + backgroundParallax = new ParallaxContainer + { + RelativeSizeAxes = Axes.Both, + ParallaxAmount = 0.01f, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Sprite + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.2f, + Texture = Beatmap.Value.Background, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill + } + } + }, + modeChangeButtons = new ResultModeTabControl + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + Height = 50, + Margin = new MarginPadding { Bottom = 110 }, + }, + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.BottomCentre, + Text = $"{Score.MaxCombo}x", + RelativePositionAxes = Axes.X, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 40), + X = 0.1f, + Colour = colours.BlueDarker, + }, + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.TopCentre, + Text = "max combo", + Font = OsuFont.GetFont(size: 20), + RelativePositionAxes = Axes.X, + X = 0.1f, + Colour = colours.Gray6, + }, + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.BottomCentre, + Text = $"{Score.Accuracy:P2}", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 40), + RelativePositionAxes = Axes.X, + X = 0.9f, + Colour = colours.BlueDarker, + }, + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.TopCentre, + Text = "accuracy", + Font = OsuFont.GetFont(size: 20), + RelativePositionAxes = Axes.X, + X = 0.9f, + Colour = colours.Gray6, + }, + } + }, + circleInner = new CircularContainer + { + Size = new Vector2(0.6f), + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0.4f), + Type = EdgeEffectType.Shadow, + Radius = 15, + }, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }, + } } - }, - new HotkeyRetryOverlay + } + }; + + if (player != null) + { + AddInternal(new HotkeyRetryOverlay { Action = () => { @@ -263,8 +264,8 @@ namespace osu.Game.Screens.Ranking player?.Restart(); }, - }, - }; + }); + } var pages = CreateResultPages(); From 2bc6932567548187d6696f4900ae98cfd1eaddc9 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Nov 2019 00:55:55 +0800 Subject: [PATCH 3782/5608] make interface mod applicable --- osu.Game/Rulesets/Mods/IModHasSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/IModHasSettings.cs b/osu.Game/Rulesets/Mods/IModHasSettings.cs index 004279f71d..b5058de82b 100644 --- a/osu.Game/Rulesets/Mods/IModHasSettings.cs +++ b/osu.Game/Rulesets/Mods/IModHasSettings.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Mods /// /// An interface for mods that allows user control over it's properties. /// - public interface IModHasSettings + public interface IModHasSettings : IApplicableMod { Drawable[] CreateControls(); } From a92b32f6dc94a164e5a2502e5f070240673f555e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Nov 2019 00:56:09 +0800 Subject: [PATCH 3783/5608] add basic tests --- .../TestSceneModCustomizationSettings.cs | 108 ++++++++++++++++++ osu.Game/Overlays/Mods/ModSelectOverlay.cs | 8 +- 2 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs new file mode 100644 index 0000000000..ec5b3c1e16 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.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 System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Mods; +using osu.Game.Overlays.Settings; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneModCustomizationSettings : OsuTestScene + { + private TestModSelectOverlay modSelect; + + [BackgroundDependencyLoader] + private void load() + { + Add(modSelect = new TestModSelectOverlay + { + RelativeSizeAxes = Axes.X, + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + }); + + var testMod = new TestModCustomizable(); + + AddStep("open", modSelect.Show); + AddAssert("button disabled", () => !modSelect.CustomizeButton.Enabled.Value); + AddStep("select mod", () => modSelect.SelectMod(testMod)); + AddAssert("button enabled", () => modSelect.CustomizeButton.Enabled.Value); + AddStep("open customization", () => modSelect.CustomizeButton.Click()); + AddAssert("controls exist", () => modSelect.GetControlSection(testMod) != null); + AddStep("deselect mod", () => modSelect.SelectMod(testMod)); + AddAssert("controls hidden", () => modSelect.ModSettingsContainer.Alpha == 0); + } + + private class TestModSelectOverlay : ModSelectOverlay + { + public new Container ModSettingsContainer => base.ModSettingsContainer; + public new TriangleButton CustomizeButton => base.CustomizeButton; + + public void SelectMod(Mod mod) => + ModSectionsContainer.Children.Single((s) => s.ModType == mod.Type) + .ButtonsContainer.OfType().Single(b => b.Mods.Any(m => m.GetType() == mod.GetType())).SelectNext(1); + + public ModControlSection GetControlSection(Mod mod) => + ModSettingsContent.Children.FirstOrDefault((s) => s.Mod == mod); + + protected override void LoadComplete() + { + base.LoadComplete(); + + foreach (var section in ModSectionsContainer) + if (section.ModType == ModType.Conversion) + section.Mods = new Mod[] { new TestModCustomizable() }; + else + section.Mods = new Mod[] { }; + } + } + + private class TestModCustomizable : Mod, IModHasSettings + { + public override string Name => "Customizable Mod"; + + public override string Acronym => "CM"; + + public override double ScoreMultiplier => 1.0; + + public override ModType Type => ModType.Conversion; + + public readonly BindableFloat sliderBindable = new BindableFloat + { + MinValue = 0, + MaxValue = 10, + }; + + public readonly BindableBool tickBindable = new BindableBool(); + + public Drawable[] CreateControls() + { + BindableFloat sliderControl = new BindableFloat(); + BindableBool tickControl = new BindableBool(); + + sliderControl.BindTo(sliderBindable); + tickControl.BindTo(tickBindable); + + return new Drawable[] + { + new SettingsSlider + { + LabelText = "Slider", + Bindable = sliderControl + }, + new SettingsCheckbox + { + LabelText = "Checkbox", + Bindable = tickControl + } + }; + } + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index a344bcc254..fc5ed1b3f3 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -331,6 +331,7 @@ namespace osu.Game.Overlays.Mods SelectedMods.ValueChanged += updateModSettings; Ruleset.ValueChanged += _ => ModSettingsContent.Clear(); + CustomizeButton.Enabled.Value = false; sampleOn = audio.Samples.Get(@"UI/check-on"); sampleOff = audio.Samples.Get(@"UI/check-off"); @@ -344,7 +345,12 @@ namespace osu.Game.Overlays.Mods if (added is IModHasSettings) ModSettingsContent.Add(new ModControlSection(added)); else if (removed is IModHasSettings) - ModSettingsContent.Remove(ModSettingsContent.Children.Where(section => section.Mod == removed).FirstOrDefault()); + ModSettingsContent.Remove(ModSettingsContent.Children.Where(section => section.Mod == removed).Single()); + + CustomizeButton.Enabled.Value = ModSettingsContent.Children.Count > 0; + + if (ModSettingsContainer.Alpha == 1 && ModSettingsContent.Children.Count == 0) + ModSettingsContainer.Alpha = 0; } public void DeselectAll() From 66253a0bd4142166cb7164bb0d9aca4712b9b6e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 5 Nov 2019 02:21:50 +0900 Subject: [PATCH 3784/5608] Handle selection on mouse down instead of click This is how other elements work, and feels better with drag preselection --- .../Components/PathControlPointPiece.cs | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index cfcd266c7f..0353ba241c 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -29,8 +29,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private readonly Container marker; private readonly Drawable markerRing; - private bool isClicked; - [Resolved] private OsuColour colours { get; set; } @@ -101,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components markerRing.Alpha = IsSelected.Value ? 1 : 0; Color4 colour = isSegmentSeparator ? colours.Red : colours.Yellow; - if (IsHovered || isClicked || IsSelected.Value) + if (IsHovered || IsSelected.Value) colour = Color4.White; marker.Colour = colour; } @@ -126,18 +124,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => marker.ReceivePositionalInputAt(screenSpacePos); protected override bool OnMouseDown(MouseDownEvent e) - { - isClicked = true; - return false; - } - - protected override bool OnMouseUp(MouseUpEvent e) - { - isClicked = false; - return false; - } - - protected override bool OnClick(ClickEvent e) { if (RequestSelection != null) { @@ -148,6 +134,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return false; } + protected override bool OnMouseUp(MouseUpEvent e) => RequestSelection != null; + + protected override bool OnClick(ClickEvent e) => RequestSelection != null; + protected override bool OnDragStart(DragStartEvent e) => true; protected override bool OnDrag(DragEvent e) From 64d900b38770da44090c9124fb4ba1e83c39033c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 11:33:37 +0900 Subject: [PATCH 3785/5608] Disable input for non-selected blueprints --- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 0701513933..2923411ce1 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -82,6 +82,9 @@ namespace osu.Game.Rulesets.Edit } } + // When not selected, input is only required for the blueprint itself to receive IsHovering + protected override bool ShouldBeConsideredForInput(Drawable child) => State == SelectionState.Selected; + /// /// Selects this , causing it to become visible. /// From c8beb5296f512d8c932c248eeea651675902c8d1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 13:26:44 +0900 Subject: [PATCH 3786/5608] Use PlatformAction.Delete instead of Delete key --- .../Components/PathControlPointVisualiser.cs | 11 +++++++---- .../Edit/Compose/Components/SelectionHandler.cs | 17 +++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 1118cae344..f2a392feee 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; 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.Osu.Objects; using osu.Game.Screens.Edit.Compose; @@ -15,7 +16,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { - public class PathControlPointVisualiser : CompositeDrawable + public class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler { public Action ControlPointsChanged; @@ -84,11 +85,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components } } - protected override bool OnKeyDown(KeyDownEvent e) + public bool OnPressed(PlatformAction action) { - switch (e.Key) + switch (action.ActionMethod) { - case Key.Delete: + case PlatformActionMethod.Delete: var newControlPoints = new List(); foreach (var piece in Pieces) @@ -127,5 +128,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return false; } + + public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index d7821eff07..664b9e3a8c 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -8,6 +8,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Graphics; @@ -22,7 +24,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// A component which outlines s and handles movement of selections. /// - public class SelectionHandler : CompositeDrawable + public class SelectionHandler : CompositeDrawable, IKeyBindingHandler { public const float BORDER_RADIUS = 2; @@ -72,22 +74,21 @@ namespace osu.Game.Screens.Edit.Compose.Components { } - protected override bool OnKeyDown(KeyDownEvent e) + public bool OnPressed(PlatformAction action) { - if (e.Repeat) - return base.OnKeyDown(e); - - switch (e.Key) + switch (action.ActionMethod) { - case Key.Delete: + case PlatformActionMethod.Delete: foreach (var h in selectedBlueprints.ToList()) placementHandler.Delete(h.DrawableObject.HitObject); return true; } - return base.OnKeyDown(e); + return false; } + public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; + #endregion #region Selection Handling From 7c20a589f2dac47c55bcad3b032d9e04fc99fc6d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 13:56:21 +0900 Subject: [PATCH 3787/5608] Remove unused usings --- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 1 - osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs | 2 -- 2 files changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index f2a392feee..6962736157 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -12,7 +12,6 @@ using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose; using osuTK; -using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 664b9e3a8c..1722476e53 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -10,14 +10,12 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osuTK; -using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components { From fe374eabe04b3c51efa732c88a71ea6802b322ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 5 Nov 2019 15:47:01 +0900 Subject: [PATCH 3788/5608] 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 8b31be3f12..78c7583923 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0cb09d9b14..42b930b1af 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 719aced705..dfc9c2d60a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From 44d079167676370c41e2a9677b8a8d2f4dce3341 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 5 Nov 2019 16:26:31 +0900 Subject: [PATCH 3789/5608] Update button usage --- osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs | 2 +- osu.Game/Graphics/UserInterface/OsuButton.cs | 2 +- osu.Game/Overlays/Settings/SidebarButton.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index a8c2362910..b6b2b2f92d 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -101,7 +101,7 @@ namespace osu.Game.Tests.Visual.Editor } } - private class StartStopButton : Button + private class StartStopButton : BasicButton { private IAdjustableClock adjustableClock; private bool started; diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 4124d2ad58..319c3dd0b4 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -17,7 +17,7 @@ namespace osu.Game.Graphics.UserInterface /// /// A button with added default sound effects. /// - public class OsuButton : Button + public class OsuButton : BasicButton { private Box hover; diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index a94f76e7af..cdb4dc463a 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -17,7 +17,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public class SidebarButton : Button + public class SidebarButton : BasicButton { private readonly SpriteIcon drawableIcon; private readonly SpriteText headerText; From 0db34a47f8314f1d46c48f44e04e31d8a80a9077 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 17:28:42 +0900 Subject: [PATCH 3790/5608] Fix selecting underneath selected blueprints --- .../Compose/Components/BlueprintContainer.cs | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index a145dea6af..7a3a303ff3 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -254,15 +254,31 @@ namespace osu.Game.Screens.Edit.Compose.Components { Debug.Assert(!clickSelectionBegan); - foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) + bool hoveringSelected = false; + + // Make sure any already-selected blueprints aren't being hovered over + foreach (SelectionBlueprint selected in selectionHandler.SelectedBlueprints) { - if (blueprint.IsHovered) + if (selected.IsHovered) { - selectionHandler.HandleSelectionRequested(blueprint, e.CurrentState); - clickSelectionBegan = true; + hoveringSelected = true; break; } } + + // Attempt a new selection at the mouse position + if (!hoveringSelected) + { + foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) + { + if (blueprint.IsHovered) + { + selectionHandler.HandleSelectionRequested(blueprint, e.CurrentState); + clickSelectionBegan = true; + break; + } + } + } } /// From d77882c21bcc9ebb4379fd7e6ad6d04a1f2ea451 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 17:31:52 +0900 Subject: [PATCH 3791/5608] Fix slider selection input handled outside path --- .../Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index d28cf7b492..78f4c4d992 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -43,5 +43,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components Size = body.Size; OriginPosition = body.PathOffset; } + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => body.ReceivePositionalInputAt(screenSpacePos); } } From 861268eb1ded856d1ebf6fb21115af38e7baec49 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 14:52:33 +0900 Subject: [PATCH 3792/5608] Add basic structure for new follow point renderer --- .../TestSceneFollowPoints.cs | 315 ++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs new file mode 100644 index 0000000000..c33c94c9c8 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -0,0 +1,315 @@ +// 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 JetBrains.Annotations; +using NUnit.Framework; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestSceneFollowPoints : OsuTestScene + { + private Container hitObjectContainer; + private FollowPointRenderer followPointRenderer; + + [SetUp] + public void Setup() => Schedule(() => + { + Children = new Drawable[] + { + hitObjectContainer = new Container { RelativeSizeAxes = Axes.Both }, + followPointRenderer = new FollowPointRenderer { RelativeSizeAxes = Axes.Both } + }; + }); + + [Test] + public void TestAddSingleHitObject() + { + addObject(new HitCircle { Position = new Vector2(100, 100) }); + } + + [Test] + public void TestRemoveSingleHitObject() + { + } + + [Test] + public void TestAddMultipleHitObjects() + { + } + + [Test] + public void TestRemoveEndObject() + { + } + + [Test] + public void TestRemoveStartObject() + { + } + + [Test] + public void TestRemoveMiddleObject() + { + } + + private void addObject(HitCircle hitCircle, Action func = null) + { + AddStep("add hitobject", () => + { + hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + var drawableCircle = new DrawableHitCircle(hitCircle); + + hitObjectContainer.Add(drawableCircle); + followPointRenderer.AddFollowPoints(drawableCircle); + + func?.Invoke(drawableCircle); + }); + } + + private void removeObject(Func func) + { + AddStep("remove hitobject", () => + { + var drawableObject = func?.Invoke(); + + hitObjectContainer.Remove(drawableObject); + followPointRenderer.RemoveFollowPoints(drawableObject); + }); + } + + private class FollowPointRenderer : CompositeDrawable + { + /// + /// Adds the s around a . + /// This includes s leading into , and s exiting . + /// + /// The to add s for. + public void AddFollowPoints(DrawableHitObject hitObject) + { + var startGroup = new FollowPointGroup(hitObject); + AddInternal(startGroup); + + // Groups are sorted by their start time when added, so the index can be used to post-process other surrounding groups + int startIndex = IndexOfInternal(startGroup); + + if (startIndex < InternalChildren.Count - 1) + { + // h1 -> -> -> h2 + // hitObject nextGroup + + var nextGroup = (FollowPointGroup)InternalChildren[startIndex + 1]; + startGroup.End = nextGroup.Start; + } + + if (startIndex > 0) + { + // h1 -> -> -> h2 + // prevGroup hitObject + + var previousGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; + previousGroup.End = startGroup.Start; + } + } + + /// + /// Removes the s around a . + /// This includes s leading into , and s exiting . + /// + /// The to remove s for. + public void RemoveFollowPoints(DrawableHitObject hitObject) + { + var groups = findGroups(hitObject); + + // Regardless of the position of the hitobject in the beatmap, there will always be a group leading from the hitobject + RemoveInternal(groups.start); + + if (groups.end != null) + { + // When there were two groups referencing the same hitobject, merge them by updating the end group to point to the new end (the start group was already removed) + groups.end.End = groups.start.End; + } + } + + /// + /// Finds the s with as the start and end s. + /// + /// The to find the relevant of. + /// A tuple containing the end group (the where is the end of), + /// and the start group (the where is the start of). + private (FollowPointGroup start, FollowPointGroup end) findGroups(DrawableHitObject hitObject) + { + // endGroup startGroup + // h1 -> -> -> -> -> h2 -> -> -> -> -> h3 + // hitObject + + FollowPointGroup startGroup = null; // The group which the hitobject is the start in + FollowPointGroup endGroup = null; // The group which the hitobject is the end in + + int startIndex = 0; + + for (; startIndex < InternalChildren.Count; startIndex++) + { + var group = (FollowPointGroup)InternalChildren[startIndex]; + + if (group.Start == hitObject) + { + startGroup = group; + break; + } + } + + if (startIndex > 0) + endGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; + + return (startGroup, endGroup); + } + + protected override int Compare(Drawable x, Drawable y) + { + var groupX = (FollowPointGroup)x; + var groupY = (FollowPointGroup)y; + + return groupX.Start.HitObject.StartTime.CompareTo(groupY.Start.HitObject.StartTime); + } + } + + private class FollowPointGroup : CompositeDrawable + { + private const int spacing = 32; + private const double preempt = 800; + + public FollowPointGroup(DrawableHitObject start) + { + Start = start; + } + + /// + /// The which s will exit from. + /// + [NotNull] + public DrawableHitObject Start { get; } + + private DrawableHitObject end; + + /// + /// The which s will enter. + /// + [CanBeNull] + public DrawableHitObject End + { + get => end; + set + { + end = value; + refreshFollowPoints(); + } + } + + private void refreshFollowPoints() + { + ClearInternal(); + + if (End == null) + return; + + OsuHitObject osuStart = (OsuHitObject)Start.HitObject; + OsuHitObject osuEnd = (OsuHitObject)End.HitObject; + + if (osuEnd.NewCombo) + return; + + if (osuStart is Spinner || osuEnd is Spinner) + return; + + Vector2 startPosition = osuStart.EndPosition; + Vector2 endPosition = osuEnd.Position; + double startTime = (osuStart as IHasEndTime)?.EndTime ?? osuStart.StartTime; + double endTime = osuEnd.StartTime; + + Vector2 distanceVector = endPosition - startPosition; + int distance = (int)distanceVector.Length; + float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI)); + double duration = endTime - startTime; + + for (int d = (int)(spacing * 1.5); d < distance - spacing; d += spacing) + { + float fraction = (float)d / distance; + Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; + Vector2 pointEndPosition = startPosition + fraction * distanceVector; + double fadeOutTime = startTime + fraction * duration; + double fadeInTime = fadeOutTime - preempt; + + FollowPoint fp; + + AddInternal(fp = new FollowPoint + { + Position = pointStartPosition, + Rotation = rotation, + Alpha = 0, + Scale = new Vector2(1.5f * osuEnd.Scale), + }); + + using (fp.BeginAbsoluteSequence(fadeInTime)) + { + fp.FadeIn(osuEnd.TimeFadeIn); + fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out); + fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out); + fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn); + } + + fp.Expire(true); + } + } + } + + private class FollowPoint : CompositeDrawable + { + private const float width = 8; + + public override bool RemoveWhenNotAlive => false; + + public FollowPoint() + { + Origin = Anchor.Centre; + + InternalChild = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.FollowPoint), _ => new Container + { + Masking = true, + AutoSizeAxes = Axes.Both, + CornerRadius = width / 2, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = Color4.White.Opacity(0.2f), + Radius = 4, + }, + Child = new Box + { + Size = new Vector2(width), + Blending = BlendingParameters.Additive, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Alpha = 0.5f, + } + }, confineMode: ConfineMode.NoScaling); + } + } + } +} From 7e60bc724097d12c180a6ed5ff521257dc332f5e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:12:32 +0900 Subject: [PATCH 3793/5608] Fix groups having 0 size --- osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index c33c94c9c8..ca7be9bb64 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -198,6 +198,7 @@ namespace osu.Game.Rulesets.Osu.Tests public FollowPointGroup(DrawableHitObject start) { Start = start; + RelativeSizeAxes = Axes.Both; } /// From c1850b2353c1e85b0153c301f0b82d980ab87211 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:12:42 +0900 Subject: [PATCH 3794/5608] Add some basic tests --- .../TestSceneFollowPoints.cs | 100 ++++++++++++++++-- 1 file changed, 90 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index ca7be9bb64..66aea68a3c 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; +using System.Linq; using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Extensions.Color4Extensions; @@ -40,54 +42,132 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestAddSingleHitObject() { - addObject(new HitCircle { Position = new Vector2(100, 100) }); + addObjects(() => new[] { new HitCircle { Position = new Vector2(100, 100) } }); } [Test] public void TestRemoveSingleHitObject() { + DrawableHitObject obj = null; + + addObjects(() => new[] { new HitCircle { Position = new Vector2(100, 100) } }, o => obj = o); + removeObject(() => obj); } [Test] public void TestAddMultipleHitObjects() { + addObjects(() => new[] + { + new HitCircle { Position = new Vector2(100, 100) }, + new HitCircle { Position = new Vector2(200, 200) }, + new HitCircle { Position = new Vector2(300, 300) }, + new HitCircle { Position = new Vector2(400, 400) }, + new HitCircle { Position = new Vector2(500, 500) }, + }); } [Test] public void TestRemoveEndObject() { + var objects = new List(); + + AddStep("reset", () => objects.Clear()); + + addObjects(() => new[] + { + new HitCircle { Position = new Vector2(100, 100) }, + new HitCircle { Position = new Vector2(200, 200) }, + new HitCircle { Position = new Vector2(300, 300) }, + new HitCircle { Position = new Vector2(400, 400) }, + new HitCircle { Position = new Vector2(500, 500) }, + }, o => objects.Add(o)); + + removeObject(() => objects.Last()); } [Test] public void TestRemoveStartObject() { + var objects = new List(); + + AddStep("reset", () => objects.Clear()); + + addObjects(() => new[] + { + new HitCircle { Position = new Vector2(100, 100) }, + new HitCircle { Position = new Vector2(200, 200) }, + new HitCircle { Position = new Vector2(300, 300) }, + new HitCircle { Position = new Vector2(400, 400) }, + new HitCircle { Position = new Vector2(500, 500) }, + }, o => objects.Add(o)); + + removeObject(() => objects.First()); } [Test] public void TestRemoveMiddleObject() { + var objects = new List(); + + AddStep("reset", () => objects.Clear()); + + addObjects(() => new[] + { + new HitCircle { Position = new Vector2(100, 100) }, + new HitCircle { Position = new Vector2(200, 200) }, + new HitCircle { Position = new Vector2(300, 300) }, + new HitCircle { Position = new Vector2(400, 400) }, + new HitCircle { Position = new Vector2(500, 500) }, + }, o => objects.Add(o)); + + removeObject(() => objects[2]); } - private void addObject(HitCircle hitCircle, Action func = null) + [Test] + public void TestMoveHitObject() { - AddStep("add hitobject", () => + var objects = new List(); + + AddStep("reset", () => objects.Clear()); + + addObjects(() => new[] { - hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + new HitCircle { Position = new Vector2(100, 100) }, + new HitCircle { Position = new Vector2(200, 200) }, + new HitCircle { Position = new Vector2(300, 300) }, + new HitCircle { Position = new Vector2(400, 400) }, + new HitCircle { Position = new Vector2(500, 500) }, + }, o => objects.Add(o)); - var drawableCircle = new DrawableHitCircle(hitCircle); + AddStep("move hitobject", () => ((OsuHitObject)objects[2].HitObject).Position = new Vector2(300, 100)); + } - hitObjectContainer.Add(drawableCircle); - followPointRenderer.AddFollowPoints(drawableCircle); + private void addObjects(Func ctorFunc, Action storeFunc = null) + { + AddStep("add hitobjects", () => + { + var circles = ctorFunc(); - func?.Invoke(drawableCircle); + for (int i = 0; i < circles.Length; i++) + { + circles[i].StartTime = Time.Current + 1000 + 500 * (i + 1); + circles[i].ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + var drawableCircle = new DrawableHitCircle(circles[i]); + hitObjectContainer.Add(drawableCircle); + followPointRenderer.AddFollowPoints(drawableCircle); + + storeFunc?.Invoke(drawableCircle); + } }); } - private void removeObject(Func func) + private void removeObject(Func getFunc) { AddStep("remove hitobject", () => { - var drawableObject = func?.Invoke(); + var drawableObject = getFunc?.Invoke(); hitObjectContainer.Remove(drawableObject); followPointRenderer.RemoveFollowPoints(drawableObject); From f861d8099c1344c60f67db77ea955ad47c33013e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:13:50 +0900 Subject: [PATCH 3795/5608] Remove unnecessary class --- .../TestSceneFollowPoints.cs | 39 +------------------ 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index 66aea68a3c..ed1d8f5184 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -6,21 +6,17 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using NUnit.Framework; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Skinning; +using osu.Game.Rulesets.Osu.Objects.Drawables.Connections; using osu.Game.Tests.Visual; using osuTK; -using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Tests { @@ -359,38 +355,5 @@ namespace osu.Game.Rulesets.Osu.Tests } } } - - private class FollowPoint : CompositeDrawable - { - private const float width = 8; - - public override bool RemoveWhenNotAlive => false; - - public FollowPoint() - { - Origin = Anchor.Centre; - - InternalChild = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.FollowPoint), _ => new Container - { - Masking = true, - AutoSizeAxes = Axes.Both, - CornerRadius = width / 2, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Colour = Color4.White.Opacity(0.2f), - Radius = 4, - }, - Child = new Box - { - Size = new Vector2(width), - Blending = BlendingParameters.Additive, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Alpha = 0.5f, - } - }, confineMode: ConfineMode.NoScaling); - } - } } } From 513ad96adf09130dcc613d9b15d934e257118909 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:15:13 +0900 Subject: [PATCH 3796/5608] Cleanup property --- .../TestSceneFollowPoints.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index ed1d8f5184..43d6cc9ab9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -268,21 +268,22 @@ namespace osu.Game.Rulesets.Osu.Tests private class FollowPointGroup : CompositeDrawable { + // Todo: These shouldn't be constants private const int spacing = 32; private const double preempt = 800; + /// + /// The which s will exit from. + /// + [NotNull] + public readonly DrawableHitObject Start; + public FollowPointGroup(DrawableHitObject start) { Start = start; RelativeSizeAxes = Axes.Both; } - /// - /// The which s will exit from. - /// - [NotNull] - public DrawableHitObject Start { get; } - private DrawableHitObject end; /// From c0badf1dce9d5a2463f40ce698b431c25ed23852 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:17:51 +0900 Subject: [PATCH 3797/5608] Type to DrawableOsuHitObject --- .../TestSceneFollowPoints.cs | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index 43d6cc9ab9..bb3e6a5044 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -22,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Tests { public class TestSceneFollowPoints : OsuTestScene { - private Container hitObjectContainer; + private Container hitObjectContainer; private FollowPointRenderer followPointRenderer; [SetUp] @@ -30,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.Tests { Children = new Drawable[] { - hitObjectContainer = new Container { RelativeSizeAxes = Axes.Both }, + hitObjectContainer = new Container { RelativeSizeAxes = Axes.Both }, followPointRenderer = new FollowPointRenderer { RelativeSizeAxes = Axes.Both } }; }); @@ -44,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestRemoveSingleHitObject() { - DrawableHitObject obj = null; + DrawableOsuHitObject obj = null; addObjects(() => new[] { new HitCircle { Position = new Vector2(100, 100) } }, o => obj = o); removeObject(() => obj); @@ -66,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestRemoveEndObject() { - var objects = new List(); + var objects = new List(); AddStep("reset", () => objects.Clear()); @@ -85,7 +84,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestRemoveStartObject() { - var objects = new List(); + var objects = new List(); AddStep("reset", () => objects.Clear()); @@ -104,7 +103,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestRemoveMiddleObject() { - var objects = new List(); + var objects = new List(); AddStep("reset", () => objects.Clear()); @@ -123,7 +122,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestMoveHitObject() { - var objects = new List(); + var objects = new List(); AddStep("reset", () => objects.Clear()); @@ -136,10 +135,10 @@ namespace osu.Game.Rulesets.Osu.Tests new HitCircle { Position = new Vector2(500, 500) }, }, o => objects.Add(o)); - AddStep("move hitobject", () => ((OsuHitObject)objects[2].HitObject).Position = new Vector2(300, 100)); + AddStep("move hitobject", () => objects[2].HitObject.Position = new Vector2(300, 100)); } - private void addObjects(Func ctorFunc, Action storeFunc = null) + private void addObjects(Func ctorFunc, Action storeFunc = null) { AddStep("add hitobjects", () => { @@ -159,7 +158,7 @@ namespace osu.Game.Rulesets.Osu.Tests }); } - private void removeObject(Func getFunc) + private void removeObject(Func getFunc) { AddStep("remove hitobject", () => { @@ -173,11 +172,11 @@ namespace osu.Game.Rulesets.Osu.Tests private class FollowPointRenderer : CompositeDrawable { /// - /// Adds the s around a . + /// Adds the s around a . /// This includes s leading into , and s exiting . /// - /// The to add s for. - public void AddFollowPoints(DrawableHitObject hitObject) + /// The to add s for. + public void AddFollowPoints(DrawableOsuHitObject hitObject) { var startGroup = new FollowPointGroup(hitObject); AddInternal(startGroup); @@ -205,11 +204,11 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Removes the s around a . + /// Removes the s around a . /// This includes s leading into , and s exiting . /// - /// The to remove s for. - public void RemoveFollowPoints(DrawableHitObject hitObject) + /// The to remove s for. + public void RemoveFollowPoints(DrawableOsuHitObject hitObject) { var groups = findGroups(hitObject); @@ -224,12 +223,12 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Finds the s with as the start and end s. + /// Finds the s with as the start and end s. /// - /// The to find the relevant of. + /// The to find the relevant of. /// A tuple containing the end group (the where is the end of), /// and the start group (the where is the start of). - private (FollowPointGroup start, FollowPointGroup end) findGroups(DrawableHitObject hitObject) + private (FollowPointGroup start, FollowPointGroup end) findGroups(DrawableOsuHitObject hitObject) { // endGroup startGroup // h1 -> -> -> -> -> h2 -> -> -> -> -> h3 @@ -273,24 +272,24 @@ namespace osu.Game.Rulesets.Osu.Tests private const double preempt = 800; /// - /// The which s will exit from. + /// The which s will exit from. /// [NotNull] - public readonly DrawableHitObject Start; + public readonly DrawableOsuHitObject Start; - public FollowPointGroup(DrawableHitObject start) + public FollowPointGroup(DrawableOsuHitObject start) { Start = start; RelativeSizeAxes = Axes.Both; } - private DrawableHitObject end; + private DrawableOsuHitObject end; /// - /// The which s will enter. + /// The which s will enter. /// [CanBeNull] - public DrawableHitObject End + public DrawableOsuHitObject End { get => end; set @@ -307,8 +306,8 @@ namespace osu.Game.Rulesets.Osu.Tests if (End == null) return; - OsuHitObject osuStart = (OsuHitObject)Start.HitObject; - OsuHitObject osuEnd = (OsuHitObject)End.HitObject; + OsuHitObject osuStart = Start.HitObject; + OsuHitObject osuEnd = End.HitObject; if (osuEnd.NewCombo) return; From e0ba35db755e97abdd33a07db109dbb3ecfff3a1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:22:37 +0900 Subject: [PATCH 3798/5608] Implement binding to hitobjects + refreshing --- .../TestSceneFollowPoints.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index bb3e6a5044..b914a8b29d 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -283,6 +283,12 @@ namespace osu.Game.Rulesets.Osu.Tests RelativeSizeAxes = Axes.Both; } + protected override void LoadComplete() + { + base.LoadComplete(); + bindHitObject(Start); + } + private DrawableOsuHitObject end; /// @@ -295,10 +301,19 @@ namespace osu.Game.Rulesets.Osu.Tests set { end = value; + + bindHitObject(end); refreshFollowPoints(); } } + private void bindHitObject(DrawableOsuHitObject drawableObject) + { + drawableObject.HitObject.StartTimeBindable.BindValueChanged(_ => refreshFollowPoints()); + drawableObject.HitObject.PositionBindable.BindValueChanged(_ => refreshFollowPoints()); + drawableObject.HitObject.DefaultsApplied += refreshFollowPoints; + } + private void refreshFollowPoints() { ClearInternal(); From 02a7f92d18375176eee9827e17aa126b708f8106 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:34:13 +0900 Subject: [PATCH 3799/5608] Allow constructing arbitrary hitobject types --- .../TestSceneFollowPoints.cs | 62 ++++++++++++------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index b914a8b29d..68f37e5d1d 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -35,24 +35,24 @@ namespace osu.Game.Rulesets.Osu.Tests }); [Test] - public void TestAddSingleHitObject() + public void TestAddSingleHitCircle() { - addObjects(() => new[] { new HitCircle { Position = new Vector2(100, 100) } }); + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }); } [Test] - public void TestRemoveSingleHitObject() + public void TestRemoveSingleHitCircle() { DrawableOsuHitObject obj = null; - addObjects(() => new[] { new HitCircle { Position = new Vector2(100, 100) } }, o => obj = o); + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }, o => obj = o); removeObject(() => obj); } [Test] - public void TestAddMultipleHitObjects() + public void TestAddMultipleHitCircles() { - addObjects(() => new[] + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) }, new HitCircle { Position = new Vector2(200, 200) }, @@ -63,13 +63,13 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveEndObject() + public void TestRemoveEndHitCircle() { var objects = new List(); AddStep("reset", () => objects.Clear()); - addObjects(() => new[] + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) }, new HitCircle { Position = new Vector2(200, 200) }, @@ -82,13 +82,13 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveStartObject() + public void TestRemoveStartHitCircle() { var objects = new List(); AddStep("reset", () => objects.Clear()); - addObjects(() => new[] + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) }, new HitCircle { Position = new Vector2(200, 200) }, @@ -101,13 +101,13 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveMiddleObject() + public void TestRemoveMiddleHitCircle() { var objects = new List(); AddStep("reset", () => objects.Clear()); - addObjects(() => new[] + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) }, new HitCircle { Position = new Vector2(200, 200) }, @@ -120,13 +120,13 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestMoveHitObject() + public void TestMoveHitCircle() { var objects = new List(); AddStep("reset", () => objects.Clear()); - addObjects(() => new[] + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) }, new HitCircle { Position = new Vector2(200, 200) }, @@ -138,22 +138,38 @@ namespace osu.Game.Rulesets.Osu.Tests AddStep("move hitobject", () => objects[2].HitObject.Position = new Vector2(300, 100)); } - private void addObjects(Func ctorFunc, Action storeFunc = null) + private void addObjects(Func ctorFunc, Action storeFunc = null) { AddStep("add hitobjects", () => { - var circles = ctorFunc(); + var objects = ctorFunc(); - for (int i = 0; i < circles.Length; i++) + for (int i = 0; i < objects.Length; i++) { - circles[i].StartTime = Time.Current + 1000 + 500 * (i + 1); - circles[i].ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + objects[i].StartTime = Time.Current + 1000 + 500 * (i + 1); + objects[i].ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - var drawableCircle = new DrawableHitCircle(circles[i]); - hitObjectContainer.Add(drawableCircle); - followPointRenderer.AddFollowPoints(drawableCircle); + DrawableOsuHitObject drawableObject = null; - storeFunc?.Invoke(drawableCircle); + switch (objects[i]) + { + case HitCircle circle: + drawableObject = new DrawableHitCircle(circle); + break; + + case Slider slider: + drawableObject = new DrawableSlider(slider); + break; + + case Spinner spinner: + drawableObject = new DrawableSpinner(spinner); + break; + } + + hitObjectContainer.Add(drawableObject); + followPointRenderer.AddFollowPoints(drawableObject); + + storeFunc?.Invoke(drawableObject); } }); } From bfe7309964b772d1b5a33aa6ee89be9b5359023f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:34:17 +0900 Subject: [PATCH 3800/5608] Fix nullref --- osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index 68f37e5d1d..9587c721c6 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -318,7 +318,9 @@ namespace osu.Game.Rulesets.Osu.Tests { end = value; - bindHitObject(end); + if (end != null) + bindHitObject(end); + refreshFollowPoints(); } } From ddfcda9e029e5385ca8969a58e9aac33d70fc75c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:34:24 +0900 Subject: [PATCH 3801/5608] Remove abstract ConnectionRenderer class --- .../Connections/ConnectionRenderer.cs | 21 ------------------- .../Connections/FollowPointRenderer.cs | 5 +++-- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 2 +- 3 files changed, 4 insertions(+), 24 deletions(-) delete mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs deleted file mode 100644 index 9106f4c7bd..0000000000 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects; -using System.Collections.Generic; - -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections -{ - /// - /// Connects hit objects visually, for example with follow points. - /// - public abstract class ConnectionRenderer : LifetimeManagementContainer - where T : HitObject - { - /// - /// Hit objects to create connections for - /// - public abstract IEnumerable HitObjects { get; set; } - } -} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index a269b87c75..863ce869aa 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -5,11 +5,12 @@ using System; using System.Collections.Generic; using osuTK; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { - public class FollowPointRenderer : ConnectionRenderer + public class FollowPointRenderer : CompositeDrawable { private int pointDistance = 32; @@ -47,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections private IEnumerable hitObjects; - public override IEnumerable HitObjects + public IEnumerable HitObjects { get => hitObjects; set diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 69e53d6eea..cbb29ce387 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.UI { private readonly ApproachCircleProxyContainer approachCircles; private readonly JudgementContainer judgementLayer; - private readonly ConnectionRenderer connectionLayer; + private readonly FollowPointRenderer connectionLayer; public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); From 712253ff50ec387a324cc1a0e10bb3bb948d372c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:39:23 +0900 Subject: [PATCH 3802/5608] Replace follow point renderer with new implementation --- .../TestSceneFollowPoints.cs | 206 ------------------ .../Drawables/Connections/FollowPointGroup.cs | 120 ++++++++++ .../Connections/FollowPointRenderer.cs | 168 +++++++------- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 16 +- 4 files changed, 206 insertions(+), 304 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index 9587c721c6..3c447e5009 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -4,13 +4,11 @@ using System; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Connections; @@ -184,209 +182,5 @@ namespace osu.Game.Rulesets.Osu.Tests followPointRenderer.RemoveFollowPoints(drawableObject); }); } - - private class FollowPointRenderer : CompositeDrawable - { - /// - /// Adds the s around a . - /// This includes s leading into , and s exiting . - /// - /// The to add s for. - public void AddFollowPoints(DrawableOsuHitObject hitObject) - { - var startGroup = new FollowPointGroup(hitObject); - AddInternal(startGroup); - - // Groups are sorted by their start time when added, so the index can be used to post-process other surrounding groups - int startIndex = IndexOfInternal(startGroup); - - if (startIndex < InternalChildren.Count - 1) - { - // h1 -> -> -> h2 - // hitObject nextGroup - - var nextGroup = (FollowPointGroup)InternalChildren[startIndex + 1]; - startGroup.End = nextGroup.Start; - } - - if (startIndex > 0) - { - // h1 -> -> -> h2 - // prevGroup hitObject - - var previousGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; - previousGroup.End = startGroup.Start; - } - } - - /// - /// Removes the s around a . - /// This includes s leading into , and s exiting . - /// - /// The to remove s for. - public void RemoveFollowPoints(DrawableOsuHitObject hitObject) - { - var groups = findGroups(hitObject); - - // Regardless of the position of the hitobject in the beatmap, there will always be a group leading from the hitobject - RemoveInternal(groups.start); - - if (groups.end != null) - { - // When there were two groups referencing the same hitobject, merge them by updating the end group to point to the new end (the start group was already removed) - groups.end.End = groups.start.End; - } - } - - /// - /// Finds the s with as the start and end s. - /// - /// The to find the relevant of. - /// A tuple containing the end group (the where is the end of), - /// and the start group (the where is the start of). - private (FollowPointGroup start, FollowPointGroup end) findGroups(DrawableOsuHitObject hitObject) - { - // endGroup startGroup - // h1 -> -> -> -> -> h2 -> -> -> -> -> h3 - // hitObject - - FollowPointGroup startGroup = null; // The group which the hitobject is the start in - FollowPointGroup endGroup = null; // The group which the hitobject is the end in - - int startIndex = 0; - - for (; startIndex < InternalChildren.Count; startIndex++) - { - var group = (FollowPointGroup)InternalChildren[startIndex]; - - if (group.Start == hitObject) - { - startGroup = group; - break; - } - } - - if (startIndex > 0) - endGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; - - return (startGroup, endGroup); - } - - protected override int Compare(Drawable x, Drawable y) - { - var groupX = (FollowPointGroup)x; - var groupY = (FollowPointGroup)y; - - return groupX.Start.HitObject.StartTime.CompareTo(groupY.Start.HitObject.StartTime); - } - } - - private class FollowPointGroup : CompositeDrawable - { - // Todo: These shouldn't be constants - private const int spacing = 32; - private const double preempt = 800; - - /// - /// The which s will exit from. - /// - [NotNull] - public readonly DrawableOsuHitObject Start; - - public FollowPointGroup(DrawableOsuHitObject start) - { - Start = start; - RelativeSizeAxes = Axes.Both; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - bindHitObject(Start); - } - - private DrawableOsuHitObject end; - - /// - /// The which s will enter. - /// - [CanBeNull] - public DrawableOsuHitObject End - { - get => end; - set - { - end = value; - - if (end != null) - bindHitObject(end); - - refreshFollowPoints(); - } - } - - private void bindHitObject(DrawableOsuHitObject drawableObject) - { - drawableObject.HitObject.StartTimeBindable.BindValueChanged(_ => refreshFollowPoints()); - drawableObject.HitObject.PositionBindable.BindValueChanged(_ => refreshFollowPoints()); - drawableObject.HitObject.DefaultsApplied += refreshFollowPoints; - } - - private void refreshFollowPoints() - { - ClearInternal(); - - if (End == null) - return; - - OsuHitObject osuStart = Start.HitObject; - OsuHitObject osuEnd = End.HitObject; - - if (osuEnd.NewCombo) - return; - - if (osuStart is Spinner || osuEnd is Spinner) - return; - - Vector2 startPosition = osuStart.EndPosition; - Vector2 endPosition = osuEnd.Position; - double startTime = (osuStart as IHasEndTime)?.EndTime ?? osuStart.StartTime; - double endTime = osuEnd.StartTime; - - Vector2 distanceVector = endPosition - startPosition; - int distance = (int)distanceVector.Length; - float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI)); - double duration = endTime - startTime; - - for (int d = (int)(spacing * 1.5); d < distance - spacing; d += spacing) - { - float fraction = (float)d / distance; - Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; - Vector2 pointEndPosition = startPosition + fraction * distanceVector; - double fadeOutTime = startTime + fraction * duration; - double fadeInTime = fadeOutTime - preempt; - - FollowPoint fp; - - AddInternal(fp = new FollowPoint - { - Position = pointStartPosition, - Rotation = rotation, - Alpha = 0, - Scale = new Vector2(1.5f * osuEnd.Scale), - }); - - using (fp.BeginAbsoluteSequence(fadeInTime)) - { - fp.FadeIn(osuEnd.TimeFadeIn); - fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out); - fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out); - fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn); - } - - fp.Expire(true); - } - } - } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs new file mode 100644 index 0000000000..06aadcc342 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -0,0 +1,120 @@ +// 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 JetBrains.Annotations; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects.Types; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections +{ + public class FollowPointGroup : CompositeDrawable + { + // Todo: These shouldn't be constants + private const int spacing = 32; + private const double preempt = 800; + + /// + /// The which s will exit from. + /// + [NotNull] + public readonly DrawableOsuHitObject Start; + + public FollowPointGroup(DrawableOsuHitObject start) + { + Start = start; + RelativeSizeAxes = Axes.Both; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + bindHitObject(Start); + } + + private DrawableOsuHitObject end; + + /// + /// The which s will enter. + /// + [CanBeNull] + public DrawableOsuHitObject End + { + get => end; + set + { + end = value; + + if (end != null) + bindHitObject(end); + + refreshFollowPoints(); + } + } + + private void bindHitObject(DrawableOsuHitObject drawableObject) + { + drawableObject.HitObject.StartTimeBindable.BindValueChanged(_ => refreshFollowPoints()); + drawableObject.HitObject.PositionBindable.BindValueChanged(_ => refreshFollowPoints()); + drawableObject.HitObject.DefaultsApplied += refreshFollowPoints; + } + + private void refreshFollowPoints() + { + ClearInternal(); + + if (End == null) + return; + + OsuHitObject osuStart = Start.HitObject; + OsuHitObject osuEnd = End.HitObject; + + if (osuEnd.NewCombo) + return; + + if (osuStart is Spinner || osuEnd is Spinner) + return; + + Vector2 startPosition = osuStart.EndPosition; + Vector2 endPosition = osuEnd.Position; + double startTime = (osuStart as IHasEndTime)?.EndTime ?? osuStart.StartTime; + double endTime = osuEnd.StartTime; + + Vector2 distanceVector = endPosition - startPosition; + int distance = (int)distanceVector.Length; + float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI)); + double duration = endTime - startTime; + + for (int d = (int)(spacing * 1.5); d < distance - spacing; d += spacing) + { + float fraction = (float)d / distance; + Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; + Vector2 pointEndPosition = startPosition + fraction * distanceVector; + double fadeOutTime = startTime + fraction * duration; + double fadeInTime = fadeOutTime - preempt; + + FollowPoint fp; + + AddInternal(fp = new FollowPoint + { + Position = pointStartPosition, + Rotation = rotation, + Alpha = 0, + Scale = new Vector2(1.5f * osuEnd.Scale), + }); + + using (fp.BeginAbsoluteSequence(fadeInTime)) + { + fp.FadeIn(osuEnd.TimeFadeIn); + fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out); + fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out); + fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn); + } + + fp.Expire(true); + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 863ce869aa..47c35746f0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -1,122 +1,104 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using System.Collections.Generic; -using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { public class FollowPointRenderer : CompositeDrawable { - private int pointDistance = 32; + /// + /// Adds the s around a . + /// This includes s leading into , and s exiting . + /// + /// The to add s for. + public void AddFollowPoints(DrawableOsuHitObject hitObject) + { + var startGroup = new FollowPointGroup(hitObject); + AddInternal(startGroup); + + // Groups are sorted by their start time when added, so the index can be used to post-process other surrounding groups + int startIndex = IndexOfInternal(startGroup); + + if (startIndex < InternalChildren.Count - 1) + { + // h1 -> -> -> h2 + // hitObject nextGroup + + var nextGroup = (FollowPointGroup)InternalChildren[startIndex + 1]; + startGroup.End = nextGroup.Start; + } + + if (startIndex > 0) + { + // h1 -> -> -> h2 + // prevGroup hitObject + + var previousGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; + previousGroup.End = startGroup.Start; + } + } /// - /// Determines how much space there is between points. + /// Removes the s around a . + /// This includes s leading into , and s exiting . /// - public int PointDistance + /// The to remove s for. + public void RemoveFollowPoints(DrawableOsuHitObject hitObject) { - get => pointDistance; - set - { - if (pointDistance == value) return; + var groups = findGroups(hitObject); - pointDistance = value; - update(); + // Regardless of the position of the hitobject in the beatmap, there will always be a group leading from the hitobject + RemoveInternal(groups.start); + + if (groups.end != null) + { + // When there were two groups referencing the same hitobject, merge them by updating the end group to point to the new end (the start group was already removed) + groups.end.End = groups.start.End; } } - private int preEmpt = 800; - /// - /// Follow points to the next hitobject start appearing for this many milliseconds before an hitobject's end time. + /// Finds the s with as the start and end s. /// - public int PreEmpt + /// The to find the relevant of. + /// A tuple containing the end group (the where is the end of), + /// and the start group (the where is the start of). + private (FollowPointGroup start, FollowPointGroup end) findGroups(DrawableOsuHitObject hitObject) { - get => preEmpt; - set + // endGroup startGroup + // h1 -> -> -> -> -> h2 -> -> -> -> -> h3 + // hitObject + + FollowPointGroup startGroup = null; // The group which the hitobject is the start in + FollowPointGroup endGroup = null; // The group which the hitobject is the end in + + int startIndex = 0; + + for (; startIndex < InternalChildren.Count; startIndex++) { - if (preEmpt == value) return; + var group = (FollowPointGroup)InternalChildren[startIndex]; - preEmpt = value; - update(); - } - } - - private IEnumerable hitObjects; - - public IEnumerable HitObjects - { - get => hitObjects; - set - { - hitObjects = value; - update(); - } - } - - public override bool RemoveCompletedTransforms => false; - - private void update() - { - ClearInternal(); - - if (hitObjects == null) - return; - - OsuHitObject prevHitObject = null; - - foreach (var currHitObject in hitObjects) - { - if (prevHitObject != null && !currHitObject.NewCombo && !(prevHitObject is Spinner) && !(currHitObject is Spinner)) + if (group.Start == hitObject) { - Vector2 startPosition = prevHitObject.EndPosition; - Vector2 endPosition = currHitObject.Position; - double startTime = (prevHitObject as IHasEndTime)?.EndTime ?? prevHitObject.StartTime; - double endTime = currHitObject.StartTime; - - Vector2 distanceVector = endPosition - startPosition; - int distance = (int)distanceVector.Length; - float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI)); - double duration = endTime - startTime; - - for (int d = (int)(PointDistance * 1.5); d < distance - PointDistance; d += PointDistance) - { - float fraction = (float)d / distance; - Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; - Vector2 pointEndPosition = startPosition + fraction * distanceVector; - double fadeOutTime = startTime + fraction * duration; - double fadeInTime = fadeOutTime - PreEmpt; - - FollowPoint fp; - - AddInternal(fp = new FollowPoint - { - Position = pointStartPosition, - Rotation = rotation, - Alpha = 0, - Scale = new Vector2(1.5f * currHitObject.Scale), - }); - - using (fp.BeginAbsoluteSequence(fadeInTime)) - { - fp.FadeIn(currHitObject.TimeFadeIn); - fp.ScaleTo(currHitObject.Scale, currHitObject.TimeFadeIn, Easing.Out); - - fp.MoveTo(pointEndPosition, currHitObject.TimeFadeIn, Easing.Out); - - fp.Delay(fadeOutTime - fadeInTime).FadeOut(currHitObject.TimeFadeIn); - } - - fp.Expire(true); - } + startGroup = group; + break; } - - prevHitObject = currHitObject; } + + if (startIndex > 0) + endGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; + + return (startGroup, endGroup); + } + + protected override int Compare(Drawable x, Drawable y) + { + var groupX = (FollowPointGroup)x; + var groupY = (FollowPointGroup)y; + + return groupX.Start.HitObject.StartTime.CompareTo(groupY.Start.HitObject.StartTime); } } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index cbb29ce387..6d1ea4bbfc 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -9,7 +9,6 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Connections; using osu.Game.Rulesets.UI; -using System.Linq; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Skinning; @@ -20,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.UI { private readonly ApproachCircleProxyContainer approachCircles; private readonly JudgementContainer judgementLayer; - private readonly FollowPointRenderer connectionLayer; + private readonly FollowPointRenderer followPoints; public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); @@ -30,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.UI { InternalChildren = new Drawable[] { - connectionLayer = new FollowPointRenderer + followPoints = new FollowPointRenderer { RelativeSizeAxes = Axes.Both, Depth = 2, @@ -64,11 +63,18 @@ namespace osu.Game.Rulesets.Osu.UI }; base.Add(h); + + followPoints.AddFollowPoints((DrawableOsuHitObject)h); } - public override void PostProcess() + public override bool Remove(DrawableHitObject h) { - connectionLayer.HitObjects = HitObjectContainer.Objects.Select(d => d.HitObject).OfType(); + bool result = base.Remove(h); + + if (result) + followPoints.RemoveFollowPoints((DrawableOsuHitObject)h); + + return result; } private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) From a19e26f8aa6c8d1bbb5bf80c499704cb14f6f729 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 19:21:39 +0900 Subject: [PATCH 3803/5608] Improve performance of refreshes --- .../Drawables/Connections/FollowPointGroup.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs index 06aadcc342..750e9559fc 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections protected override void LoadComplete() { base.LoadComplete(); - bindHitObject(Start); + bindEvents(Start); } private DrawableOsuHitObject end; @@ -48,20 +48,21 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections end = value; if (end != null) - bindHitObject(end); + bindEvents(end); - refreshFollowPoints(); + refresh(); } } - private void bindHitObject(DrawableOsuHitObject drawableObject) + private void bindEvents(DrawableOsuHitObject drawableObject) { - drawableObject.HitObject.StartTimeBindable.BindValueChanged(_ => refreshFollowPoints()); - drawableObject.HitObject.PositionBindable.BindValueChanged(_ => refreshFollowPoints()); - drawableObject.HitObject.DefaultsApplied += refreshFollowPoints; + drawableObject.HitObject.PositionBindable.BindValueChanged(_ => scheduleRefresh()); + drawableObject.HitObject.DefaultsApplied += scheduleRefresh; } - private void refreshFollowPoints() + private void scheduleRefresh() => Scheduler.AddOnce(refresh); + + private void refresh() { ClearInternal(); From 3b6064336b63f6bd00f7bdee699cb6dae2903279 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 19:22:07 +0900 Subject: [PATCH 3804/5608] Implement group re-ordering based on start time --- .../Drawables/Connections/FollowPointGroup.cs | 12 +- .../Connections/FollowPointRenderer.cs | 115 ++++++++---------- 2 files changed, 65 insertions(+), 62 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs index 750e9559fc..79d69acd67 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -3,6 +3,7 @@ using System; using JetBrains.Annotations; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Types; @@ -16,16 +17,25 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections private const int spacing = 32; private const double preempt = 800; + public readonly Bindable StartTime = new Bindable(); + /// /// The which s will exit from. /// [NotNull] public readonly DrawableOsuHitObject Start; - public FollowPointGroup(DrawableOsuHitObject start) + /// + /// Creates a new . + /// + /// The which s will exit from. + public FollowPointGroup([NotNull] DrawableOsuHitObject start) { Start = start; + RelativeSizeAxes = Axes.Both; + + StartTime.BindTo(Start.HitObject.StartTimeBindable); } protected override void LoadComplete() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 47c35746f0..892442f0a7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -1,6 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -8,97 +11,87 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { public class FollowPointRenderer : CompositeDrawable { + private readonly List groups = new List(); + /// /// Adds the s around a . /// This includes s leading into , and s exiting . /// /// The to add s for. public void AddFollowPoints(DrawableOsuHitObject hitObject) - { - var startGroup = new FollowPointGroup(hitObject); - AddInternal(startGroup); - - // Groups are sorted by their start time when added, so the index can be used to post-process other surrounding groups - int startIndex = IndexOfInternal(startGroup); - - if (startIndex < InternalChildren.Count - 1) - { - // h1 -> -> -> h2 - // hitObject nextGroup - - var nextGroup = (FollowPointGroup)InternalChildren[startIndex + 1]; - startGroup.End = nextGroup.Start; - } - - if (startIndex > 0) - { - // h1 -> -> -> h2 - // prevGroup hitObject - - var previousGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; - previousGroup.End = startGroup.Start; - } - } + => addGroup(new FollowPointGroup(hitObject).With(g => g.StartTime.BindValueChanged(_ => onStartTimeChanged(g)))); /// /// Removes the s around a . /// This includes s leading into , and s exiting . /// /// The to remove s for. - public void RemoveFollowPoints(DrawableOsuHitObject hitObject) + public void RemoveFollowPoints(DrawableOsuHitObject hitObject) => removeGroup(groups.Single(g => g.Start == hitObject)); + + /// + /// Adds a to this . + /// + /// The to add. + /// The index of in . + private int addGroup(FollowPointGroup group) { - var groups = findGroups(hitObject); + AddInternal(group); - // Regardless of the position of the hitobject in the beatmap, there will always be a group leading from the hitobject - RemoveInternal(groups.start); + // Groups are sorted by their start time when added such that the index can be used to post-process other surrounding groups + int index = groups.AddInPlace(group, Comparer.Create((g1, g2) => g1.StartTime.Value.CompareTo(g2.StartTime.Value))); - if (groups.end != null) + if (index < groups.Count - 1) { - // When there were two groups referencing the same hitobject, merge them by updating the end group to point to the new end (the start group was already removed) - groups.end.End = groups.start.End; + // Update the group's end point to the next hitobject + // h1 -> -> -> h2 + // hitObject nextGroup + + FollowPointGroup nextGroup = groups[index + 1]; + group.End = nextGroup.Start; } + + if (index > 0) + { + // Previous group's end point to the current group's start point + // h1 -> -> -> h2 + // prevGroup hitObject + + FollowPointGroup previousGroup = groups[index - 1]; + previousGroup.End = group.Start; + } + + return index; } /// - /// Finds the s with as the start and end s. + /// Removes a from this . /// - /// The to find the relevant of. - /// A tuple containing the end group (the where is the end of), - /// and the start group (the where is the start of). - private (FollowPointGroup start, FollowPointGroup end) findGroups(DrawableOsuHitObject hitObject) + /// The to remove. + /// Whether was removed. + private bool removeGroup(FollowPointGroup group) { - // endGroup startGroup - // h1 -> -> -> -> -> h2 -> -> -> -> -> h3 - // hitObject + RemoveInternal(group); - FollowPointGroup startGroup = null; // The group which the hitobject is the start in - FollowPointGroup endGroup = null; // The group which the hitobject is the end in + int index = groups.IndexOf(group); - int startIndex = 0; - - for (; startIndex < InternalChildren.Count; startIndex++) + if (index > 0) { - var group = (FollowPointGroup)InternalChildren[startIndex]; - - if (group.Start == hitObject) - { - startGroup = group; - break; - } + // Update the previous group's end point to the next group's start point + // h1 -> -> -> h2 -> -> -> h3 + // prevGroup group nextGroup + // The current group's end point is used since there may not be a next group + FollowPointGroup previousGroup = groups[index - 1]; + previousGroup.End = group.End; } - if (startIndex > 0) - endGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; - - return (startGroup, endGroup); + return groups.Remove(group); } - protected override int Compare(Drawable x, Drawable y) + private void onStartTimeChanged(FollowPointGroup group) { - var groupX = (FollowPointGroup)x; - var groupY = (FollowPointGroup)y; - - return groupX.Start.HitObject.StartTime.CompareTo(groupY.Start.HitObject.StartTime); + // Naive but can be improved if performance becomes problematic + removeGroup(group); + addGroup(group); } } } From 1ef2b81041dfd9225ffb7e792b8c55bfa76d6ff1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 22:08:50 +0900 Subject: [PATCH 3805/5608] Fix follow point lifetime not being updated correctly --- .../Drawables/Connections/FollowPointGroup.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs index 79d69acd67..47196f4893 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -118,13 +118,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections using (fp.BeginAbsoluteSequence(fadeInTime)) { - fp.FadeIn(osuEnd.TimeFadeIn); - fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out); - fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out); - fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn); - } + // See: Expire calls are separated due to https://github.com/ppy/osu-framework/issues/2941 - fp.Expire(true); + fp.FadeIn(osuEnd.TimeFadeIn).Expire(true); + + fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out) + .MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out) + .Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn) + .Expire(); + } } } } From f77de7d88013f30bd3567b4af2f7d223029b50e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 5 Nov 2019 18:25:38 +0900 Subject: [PATCH 3806/5608] Simplify implementation --- .../Compose/Components/BlueprintContainer.cs | 26 +++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 7a3a303ff3..02dd60eac1 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -254,31 +254,19 @@ namespace osu.Game.Screens.Edit.Compose.Components { Debug.Assert(!clickSelectionBegan); - bool hoveringSelected = false; + // If a select blueprint is already hovered, disallow changes in selection. + if (selectionHandler.SelectedBlueprints.Any(s => s.IsHovered)) + return; - // Make sure any already-selected blueprints aren't being hovered over - foreach (SelectionBlueprint selected in selectionHandler.SelectedBlueprints) + foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) { - if (selected.IsHovered) + if (blueprint.IsHovered) { - hoveringSelected = true; + selectionHandler.HandleSelectionRequested(blueprint, e.CurrentState); + clickSelectionBegan = true; break; } } - - // Attempt a new selection at the mouse position - if (!hoveringSelected) - { - foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) - { - if (blueprint.IsHovered) - { - selectionHandler.HandleSelectionRequested(blueprint, e.CurrentState); - clickSelectionBegan = true; - break; - } - } - } } /// From f4b93ec9438f49d852bb7172ad3a6b8c368fd5d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 5 Nov 2019 18:29:08 +0900 Subject: [PATCH 3807/5608] Add exception when holding control --- .../Screens/Edit/Compose/Components/BlueprintContainer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 02dd60eac1..288c712bde 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -255,7 +255,9 @@ namespace osu.Game.Screens.Edit.Compose.Components Debug.Assert(!clickSelectionBegan); // If a select blueprint is already hovered, disallow changes in selection. - if (selectionHandler.SelectedBlueprints.Any(s => s.IsHovered)) + // Exception is made when holding control, as deselection should still be allowed. + if (!e.CurrentState.Keyboard.ControlPressed && + selectionHandler.SelectedBlueprints.Any(s => s.IsHovered)) return; foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) From 6c58faf30cab3f8f36d2b8d77621f0bca2529f1a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 19:31:48 +0900 Subject: [PATCH 3808/5608] Fix group ends potentially not being updated correctly --- .../Objects/Drawables/Connections/FollowPointRenderer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 892442f0a7..e29cf6e128 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -49,6 +49,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections FollowPointGroup nextGroup = groups[index + 1]; group.End = nextGroup.Start; } + else + group.End = null; if (index > 0) { From f2118b0eba6fa022023ef453b11b9ed61dcf2580 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 19:31:58 +0900 Subject: [PATCH 3809/5608] Add automated test cases --- .../TestSceneFollowPoints.cs | 178 +++++++++++------- .../Connections/FollowPointRenderer.cs | 2 + 2 files changed, 113 insertions(+), 67 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index 3c447e5009..aac0119dc7 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -2,8 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; -using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -27,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Tests { Children = new Drawable[] { - hitObjectContainer = new Container { RelativeSizeAxes = Axes.Both }, + hitObjectContainer = new TestHitObjectContainer { RelativeSizeAxes = Axes.Both }, followPointRenderer = new FollowPointRenderer { RelativeSizeAxes = Axes.Both } }; }); @@ -35,108 +33,97 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestAddSingleHitCircle() { - addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }); + addObjectsStep(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }); + + assertGroups(); } [Test] public void TestRemoveSingleHitCircle() { - DrawableOsuHitObject obj = null; + addObjectsStep(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }); - addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }, o => obj = o); - removeObject(() => obj); + removeObjectStep(() => getObject(0)); + + assertGroups(); } [Test] public void TestAddMultipleHitCircles() { - addObjects(() => new OsuHitObject[] - { - new HitCircle { Position = new Vector2(100, 100) }, - new HitCircle { Position = new Vector2(200, 200) }, - new HitCircle { Position = new Vector2(300, 300) }, - new HitCircle { Position = new Vector2(400, 400) }, - new HitCircle { Position = new Vector2(500, 500) }, - }); + addMultipleObjectsStep(); + + assertGroups(); } [Test] public void TestRemoveEndHitCircle() { - var objects = new List(); + addMultipleObjectsStep(); - AddStep("reset", () => objects.Clear()); + removeObjectStep(() => getObject(4)); - addObjects(() => new OsuHitObject[] - { - new HitCircle { Position = new Vector2(100, 100) }, - new HitCircle { Position = new Vector2(200, 200) }, - new HitCircle { Position = new Vector2(300, 300) }, - new HitCircle { Position = new Vector2(400, 400) }, - new HitCircle { Position = new Vector2(500, 500) }, - }, o => objects.Add(o)); - - removeObject(() => objects.Last()); + assertGroups(); } [Test] public void TestRemoveStartHitCircle() { - var objects = new List(); + addMultipleObjectsStep(); - AddStep("reset", () => objects.Clear()); + removeObjectStep(() => getObject(0)); - addObjects(() => new OsuHitObject[] - { - new HitCircle { Position = new Vector2(100, 100) }, - new HitCircle { Position = new Vector2(200, 200) }, - new HitCircle { Position = new Vector2(300, 300) }, - new HitCircle { Position = new Vector2(400, 400) }, - new HitCircle { Position = new Vector2(500, 500) }, - }, o => objects.Add(o)); - - removeObject(() => objects.First()); + assertGroups(); } [Test] public void TestRemoveMiddleHitCircle() { - var objects = new List(); + addMultipleObjectsStep(); - AddStep("reset", () => objects.Clear()); + removeObjectStep(() => getObject(2)); - addObjects(() => new OsuHitObject[] - { - new HitCircle { Position = new Vector2(100, 100) }, - new HitCircle { Position = new Vector2(200, 200) }, - new HitCircle { Position = new Vector2(300, 300) }, - new HitCircle { Position = new Vector2(400, 400) }, - new HitCircle { Position = new Vector2(500, 500) }, - }, o => objects.Add(o)); - - removeObject(() => objects[2]); + assertGroups(); } [Test] public void TestMoveHitCircle() { - var objects = new List(); + addMultipleObjectsStep(); - AddStep("reset", () => objects.Clear()); + AddStep("move hitobject", () => getObject(2).HitObject.Position = new Vector2(300, 100)); - addObjects(() => new OsuHitObject[] - { - new HitCircle { Position = new Vector2(100, 100) }, - new HitCircle { Position = new Vector2(200, 200) }, - new HitCircle { Position = new Vector2(300, 300) }, - new HitCircle { Position = new Vector2(400, 400) }, - new HitCircle { Position = new Vector2(500, 500) }, - }, o => objects.Add(o)); - - AddStep("move hitobject", () => objects[2].HitObject.Position = new Vector2(300, 100)); + assertGroups(); } - private void addObjects(Func ctorFunc, Action storeFunc = null) + [TestCase(0, 0)] // Start -> Start + [TestCase(0, 2)] // Start -> Middle + [TestCase(0, 5)] // Start -> End + [TestCase(2, 0)] // Middle -> Start + [TestCase(1, 3)] // Middle -> Middle (forwards) + [TestCase(3, 1)] // Middle -> Middle (backwards) + [TestCase(4, 0)] // End -> Start + [TestCase(4, 2)] // End -> Middle + [TestCase(4, 4)] // End -> End + public void TestReorderHitObjects(int startIndex, int endIndex) + { + addMultipleObjectsStep(); + + reorderObjectStep(startIndex, endIndex); + + assertGroups(); + } + + private void addMultipleObjectsStep() => addObjectsStep(() => new OsuHitObject[] + { + new HitCircle { Position = new Vector2(100, 100) }, + new HitCircle { Position = new Vector2(200, 200) }, + new HitCircle { Position = new Vector2(300, 300) }, + new HitCircle { Position = new Vector2(400, 400) }, + new HitCircle { Position = new Vector2(500, 500) }, + }); + + private void addObjectsStep(Func ctorFunc) { AddStep("add hitobjects", () => { @@ -166,13 +153,11 @@ namespace osu.Game.Rulesets.Osu.Tests hitObjectContainer.Add(drawableObject); followPointRenderer.AddFollowPoints(drawableObject); - - storeFunc?.Invoke(drawableObject); } }); } - private void removeObject(Func getFunc) + private void removeObjectStep(Func getFunc) { AddStep("remove hitobject", () => { @@ -182,5 +167,64 @@ namespace osu.Game.Rulesets.Osu.Tests followPointRenderer.RemoveFollowPoints(drawableObject); }); } + + private void reorderObjectStep(int startIndex, int endIndex) + { + AddStep($"move object {startIndex} to {endIndex}", () => + { + DrawableOsuHitObject toReorder = getObject(startIndex); + + double targetTime; + if (endIndex < hitObjectContainer.Count) + targetTime = getObject(endIndex).HitObject.StartTime - 1; + else + targetTime = getObject(hitObjectContainer.Count - 1).HitObject.StartTime + 1; + + hitObjectContainer.Remove(toReorder); + toReorder.HitObject.StartTime = targetTime; + hitObjectContainer.Add(toReorder); + }); + } + + private void assertGroups() + { + AddAssert("has correct group count", () => followPointRenderer.Groups.Count == hitObjectContainer.Count); + AddAssert("group endpoints are correct", () => + { + for (int i = 0; i < hitObjectContainer.Count; i++) + { + DrawableOsuHitObject expectedStart = getObject(i); + DrawableOsuHitObject expectedEnd = i < hitObjectContainer.Count - 1 ? getObject(i + 1) : null; + + if (getGroup(i).Start != expectedStart) + throw new AssertionException($"Object {i} expected to be the start of group {i}."); + + if (getGroup(i).End != expectedEnd) + throw new AssertionException($"Object {(expectedEnd == null ? "null" : i.ToString())} expected to be the end of group {i}."); + } + + return true; + }); + } + + private DrawableOsuHitObject getObject(int index) => hitObjectContainer[index]; + + private FollowPointGroup getGroup(int index) => followPointRenderer.Groups[index]; + + private class TestHitObjectContainer : Container + { + protected override int Compare(Drawable x, Drawable y) + { + var osuX = (DrawableOsuHitObject)x; + var osuY = (DrawableOsuHitObject)y; + + int compare = osuX.HitObject.StartTime.CompareTo(osuY.HitObject.StartTime); + + if (compare == 0) + return base.Compare(x, y); + + return compare; + } + } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index e29cf6e128..e5e8efae8e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -11,6 +11,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { public class FollowPointRenderer : CompositeDrawable { + internal IReadOnlyList Groups => groups; + private readonly List groups = new List(); /// From d0286037696594660cc0641d94e68ca616ba9bdf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 22:50:01 +0900 Subject: [PATCH 3810/5608] Rename tests --- .../TestSceneFollowPoints.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index aac0119dc7..79a1bb579f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Tests }); [Test] - public void TestAddSingleHitCircle() + public void TestAddObject() { addObjectsStep(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }); @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveSingleHitCircle() + public void TestRemoveObject() { addObjectsStep(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }); @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestAddMultipleHitCircles() + public void TestAddMultipleObjects() { addMultipleObjectsStep(); @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveEndHitCircle() + public void TestRemoveEndObject() { addMultipleObjectsStep(); @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveStartHitCircle() + public void TestRemoveStartObject() { addMultipleObjectsStep(); @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveMiddleHitCircle() + public void TestRemoveMiddleObject() { addMultipleObjectsStep(); @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestMoveHitCircle() + public void TestMoveObject() { addMultipleObjectsStep(); @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Osu.Tests [TestCase(4, 0)] // End -> Start [TestCase(4, 2)] // End -> Middle [TestCase(4, 4)] // End -> End - public void TestReorderHitObjects(int startIndex, int endIndex) + public void TestReorderObjects(int startIndex, int endIndex) { addMultipleObjectsStep(); From 68a81e0eb0f813fc3710ea09aa273d75ac2b8671 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 22:50:21 +0900 Subject: [PATCH 3811/5608] Fix follow point transforms not working after rewind --- .../Objects/Drawables/Connections/FollowPoint.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index 89ffddf4cb..7ba044b462 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections public override bool RemoveWhenNotAlive => false; + public override bool RemoveCompletedTransforms => false; + public FollowPoint() { Origin = Anchor.Centre; From d762ec959c9240594a46ba2228095fea4b7e10ca Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 22:50:38 +0900 Subject: [PATCH 3812/5608] Schedule group refresh when loaded --- .../Objects/Drawables/Connections/FollowPointGroup.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs index 47196f4893..c77ecd355f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -60,7 +60,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections if (end != null) bindEvents(end); - refresh(); + if (IsLoaded) + scheduleRefresh(); + else + refresh(); } } From 0a2af2b0fe067b3caece643b1acbdc29b427a823 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 23:02:39 +0900 Subject: [PATCH 3813/5608] Apply transform override at a higher level --- .../Objects/Drawables/Connections/FollowPoint.cs | 2 -- .../Objects/Drawables/Connections/FollowPointRenderer.cs | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index 7ba044b462..89ffddf4cb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -18,8 +18,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections public override bool RemoveWhenNotAlive => false; - public override bool RemoveCompletedTransforms => false; - public FollowPoint() { Origin = Anchor.Centre; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index e5e8efae8e..aa9ec8d96d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -15,6 +15,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections private readonly List groups = new List(); + public override bool RemoveCompletedTransforms => false; + /// /// Adds the s around a . /// This includes s leading into , and s exiting . From aff275ea21784999ca29e37a695da2df430332a7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 23:03:05 +0900 Subject: [PATCH 3814/5608] Revert "Fix follow point lifetime not being updated correctly" This reverts commit 1ef2b81041dfd9225ffb7e792b8c55bfa76d6ff1. --- .../Drawables/Connections/FollowPointGroup.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs index c77ecd355f..9d651373ff 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -121,15 +121,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections using (fp.BeginAbsoluteSequence(fadeInTime)) { - // See: Expire calls are separated due to https://github.com/ppy/osu-framework/issues/2941 - - fp.FadeIn(osuEnd.TimeFadeIn).Expire(true); - - fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out) - .MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out) - .Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn) - .Expire(); + fp.FadeIn(osuEnd.TimeFadeIn); + fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out); + fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out); + fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn); } + + fp.Expire(true); } } } From 68ca5cb26a6b1f0d56ba258c0edb29afb808c646 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 23:20:46 +0900 Subject: [PATCH 3815/5608] Adjust comments --- .../Drawables/Connections/FollowPoint.cs | 3 +++ .../Drawables/Connections/FollowPointGroup.cs | 6 ++++++ .../Connections/FollowPointRenderer.cs | 19 ++++++++++++++----- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index 89ffddf4cb..db34ae1d87 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -12,6 +12,9 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { + /// + /// A single follow point positioned between two adjacent s. + /// public class FollowPoint : Container { private const float width = 8; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs index 9d651373ff..168d2b8532 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -11,12 +11,18 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { + /// + /// Visualises the s between two s. + /// public class FollowPointGroup : CompositeDrawable { // Todo: These shouldn't be constants private const int spacing = 32; private const double preempt = 800; + /// + /// The start time of . + /// public readonly Bindable StartTime = new Bindable(); /// diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index aa9ec8d96d..afd86e004d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -9,8 +9,14 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { + /// + /// Visualises groups of s. + /// public class FollowPointRenderer : CompositeDrawable { + /// + /// All the s contained by this . + /// internal IReadOnlyList Groups => groups; private readonly List groups = new List(); @@ -46,21 +52,24 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections if (index < groups.Count - 1) { - // Update the group's end point to the next hitobject + // Update the group's end point to the next group's start point // h1 -> -> -> h2 - // hitObject nextGroup + // group nextGroup FollowPointGroup nextGroup = groups[index + 1]; group.End = nextGroup.Start; } else + { + // The end point may be non-null during re-ordering group.End = null; + } if (index > 0) { - // Previous group's end point to the current group's start point + // Update the previous group's end point to the current group's start point // h1 -> -> -> h2 - // prevGroup hitObject + // prevGroup group FollowPointGroup previousGroup = groups[index - 1]; previousGroup.End = group.Start; @@ -95,7 +104,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections private void onStartTimeChanged(FollowPointGroup group) { - // Naive but can be improved if performance becomes problematic + // Naive but can be improved if performance becomes an issue removeGroup(group); addGroup(group); } From 1f40641d05cc9a1da02d00eaf4ba14a30c367299 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 10:32:09 +0900 Subject: [PATCH 3816/5608] Add failing test --- osu.Game.Tests/Visual/Gameplay/TestScenePause.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 64022b2410..6e8975f11b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -237,6 +237,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("player not exited", () => Player.IsCurrentScreen()); AddStep("exit", () => Player.Exit()); confirmExited(); + confirmNoTrackAdjustments(); } private void confirmPaused() @@ -258,6 +259,11 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("player exited", () => !Player.IsCurrentScreen()); } + private void confirmNoTrackAdjustments() + { + AddAssert("track has no adjustments", () => Beatmap.Value.Track.AggregateFrequency.Value == 1); + } + private void restart() => AddStep("restart", () => Player.Restart()); private void pause() => AddStep("pause", () => Player.Pause()); private void resume() => AddStep("resume", () => Player.Resume()); From cd1dd0f8981d2ed7c5c03b67d401ebc1ec0b4a62 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 10:38:04 +0900 Subject: [PATCH 3817/5608] Fix adjustments not being removed correctly on retry from pause --- osu.Game/Screens/Play/GameplayClockContainer.cs | 16 ++++++++++------ osu.Game/Screens/Play/Player.cs | 2 -- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index f2efbe6073..2f2028ff53 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -162,16 +162,12 @@ namespace osu.Game.Screens.Play if (sourceClock != beatmap.Track) return; + removeSourceClockAdjustments(); + sourceClock = new TrackVirtual(beatmap.Track.Length); adjustableClock.ChangeSource(sourceClock); } - public void ResetLocalAdjustments() - { - // In the case of replays, we may have changed the playback rate. - UserPlaybackRate.Value = 1; - } - protected override void Update() { if (!IsPaused.Value) @@ -198,6 +194,14 @@ namespace osu.Game.Screens.Play protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); + + removeSourceClockAdjustments(); + sourceClock = null; + } + + private void removeSourceClockAdjustments() + { + sourceClock.ResetSpeedAdjustments(); (sourceClock as IAdjustableAudioComponent)?.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a3c39d9cc1..a9b0649fab 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -536,8 +536,6 @@ namespace osu.Game.Screens.Play return true; } - GameplayClockContainer.ResetLocalAdjustments(); - // 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 892ef017ef3b85ba184e35202a3eb14f59a51c09 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2019 03:05:03 +0000 Subject: [PATCH 3818/5608] Bump ppy.osu.Framework.iOS from 2019.1029.0 to 2019.1106.0 Bumps [ppy.osu.Framework.iOS](https://github.com/ppy/osu-framework) from 2019.1029.0 to 2019.1106.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.1029.0...2019.1106.0) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 719aced705..d257948831 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -119,7 +119,7 @@ - + From 1d83f51a804f9a0972455433666f42219ed057c9 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2019 03:05:05 +0000 Subject: [PATCH 3819/5608] Bump ppy.osu.Framework.Android from 2019.1029.0 to 2019.1106.0 Bumps [ppy.osu.Framework.Android](https://github.com/ppy/osu-framework) from 2019.1029.0 to 2019.1106.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.1029.0...2019.1106.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index 8b31be3f12..d1860acbf9 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ - + From 8cf349c1eefa1996a1d5f9446181150bcf574ae8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 12:10:53 +0900 Subject: [PATCH 3820/5608] Update once more --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 42b930b1af..dbe6559c40 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + From f20bfe7a554849d6d1fc762741e0fd4f084a4e07 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 12:16:48 +0900 Subject: [PATCH 3821/5608] Fix extra semicolon --- osu.Game/Screens/Edit/Timing/DifficultySection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Timing/DifficultySection.cs b/osu.Game/Screens/Edit/Timing/DifficultySection.cs index bd363c3158..cd33425ee5 100644 --- a/osu.Game/Screens/Edit/Timing/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Timing/DifficultySection.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier::0.##}x"; }); + ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier:0.##}x"; }); } protected override DifficultyControlPoint CreatePoint() From 9dd7f997d2c01836a43ad9630261e095e14a8c36 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 12:17:18 +0900 Subject: [PATCH 3822/5608] Reoder SampleSection to match others --- osu.Game/Screens/Edit/Timing/SampleSection.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/SampleSection.cs b/osu.Game/Screens/Edit/Timing/SampleSection.cs index 0477ad4e78..e665db0a4d 100644 --- a/osu.Game/Screens/Edit/Timing/SampleSection.cs +++ b/osu.Game/Screens/Edit/Timing/SampleSection.cs @@ -22,17 +22,6 @@ namespace osu.Game.Screens.Edit.Timing }); } - protected override SampleControlPoint CreatePoint() - { - var reference = Beatmap.Value.Beatmap.ControlPointInfo.SamplePointAt(SelectedGroup.Value.Time); - - return new SampleControlPoint - { - SampleBank = reference.SampleBank, - SampleVolume = reference.SampleVolume, - }; - } - protected override void LoadComplete() { base.LoadComplete(); @@ -43,5 +32,16 @@ namespace osu.Game.Screens.Edit.Timing volume.Text = $"Volume: {point.NewValue?.SampleVolume}%"; }); } + + protected override SampleControlPoint CreatePoint() + { + var reference = Beatmap.Value.Beatmap.ControlPointInfo.SamplePointAt(SelectedGroup.Value.Time); + + return new SampleControlPoint + { + SampleBank = reference.SampleBank, + SampleVolume = reference.SampleVolume, + }; + } } } From 7cd4cb8a935c797fd0d977198b99f7515bc225e8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 12:32:12 +0900 Subject: [PATCH 3823/5608] Rename selectedPoints to selectedGroup --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 6ae01e056f..9317448262 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Edit.Timing public class TimingScreen : EditorScreenWithTimeline { [Cached] - private Bindable selectedPoints = new Bindable(); + private Bindable selectedGroup = new Bindable(); [Resolved] private IAdjustableClock clock { get; set; } @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - selectedPoints.BindValueChanged(selected => { clock.Seek(selected.NewValue.Time); }); + selectedGroup.BindValueChanged(selected => { clock.Seek(selected.NewValue.Time); }); } public class ControlPointList : CompositeDrawable From 322a1f0a860eff545c166426e026f14da48437f3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 12:45:35 +0900 Subject: [PATCH 3824/5608] Fix potential nullref --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 9317448262..d9da3ff92d 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -47,7 +47,11 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - selectedGroup.BindValueChanged(selected => { clock.Seek(selected.NewValue.Time); }); + selectedGroup.BindValueChanged(selected => + { + if (selected.NewValue != null) + clock.Seek(selected.NewValue.Time); + }); } public class ControlPointList : CompositeDrawable From 4ce3450cfc6a003c3ff220d6f57cd566d49613f7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 14:08:52 +0900 Subject: [PATCH 3825/5608] Move button implementation to OsuButton --- .../Editor/TestSceneEditorComposeTimeline.cs | 4 +- osu.Game/Graphics/UserInterface/OsuButton.cs | 106 ++++++++++++++---- osu.Game/Overlays/Settings/SidebarButton.cs | 28 +---- osu.Game/Overlays/SettingsPanel.cs | 4 +- 4 files changed, 87 insertions(+), 55 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index b6b2b2f92d..6e5b3b93e9 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -10,9 +10,9 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Edit.Compose.Components.Timeline; using osuTK; using osuTK.Graphics; @@ -101,7 +101,7 @@ namespace osu.Game.Tests.Visual.Editor } } - private class StartStopButton : BasicButton + private class StartStopButton : OsuButton { private IAdjustableClock adjustableClock; private bool started; diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 319c3dd0b4..2750e61f0d 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -1,10 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; @@ -17,55 +19,106 @@ namespace osu.Game.Graphics.UserInterface /// /// A button with added default sound effects. /// - public class OsuButton : BasicButton + public class OsuButton : Button { - private Box hover; + public string Text + { + get => SpriteText?.Text; + set + { + if (SpriteText != null) + SpriteText.Text = value; + } + } + + private Color4? backgroundColour; + + public Color4 BackgroundColour + { + set + { + backgroundColour = value; + Background.FadeColour(value); + } + } + + protected override Container Content { get; } + + protected Box Hover; + protected Box Background; + protected SpriteText SpriteText; public OsuButton() { Height = 40; - Content.Masking = true; - Content.CornerRadius = 5; + AddInternal(Content = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + CornerRadius = 5, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + Background = new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + }, + Hover = new Box + { + Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = Color4.White.Opacity(.1f), + Blending = BlendingParameters.Additive, + Depth = float.MinValue + }, + SpriteText = CreateText(), + new HoverClickSounds(HoverSampleSet.Loud), + } + }); + + Enabled.BindValueChanged(enabledChanged, true); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - BackgroundColour = colours.BlueDark; - - AddRange(new Drawable[] - { - hover = new Box - { - RelativeSizeAxes = Axes.Both, - Blending = BlendingParameters.Additive, - Colour = Color4.White.Opacity(0.1f), - Alpha = 0, - Depth = -1 - }, - new HoverClickSounds(HoverSampleSet.Loud), - }); + if (backgroundColour == null) + BackgroundColour = colours.BlueDark; Enabled.ValueChanged += enabledChanged; Enabled.TriggerChange(); } - private void enabledChanged(ValueChangedEvent e) + protected override bool OnClick(ClickEvent e) { - this.FadeColour(e.NewValue ? Color4.White : Color4.Gray, 200, Easing.OutQuint); + if (Enabled.Value) + { + Debug.Assert(backgroundColour != null); + Background.FlashColour(backgroundColour.Value, 200); + } + + return base.OnClick(e); } protected override bool OnHover(HoverEvent e) { - hover.FadeIn(200); - return true; + if (Enabled.Value) + Hover.FadeIn(200, Easing.OutQuint); + + return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - hover.FadeOut(200); base.OnHoverLost(e); + + Hover.FadeOut(300); } protected override bool OnMouseDown(MouseDownEvent e) @@ -80,12 +133,17 @@ namespace osu.Game.Graphics.UserInterface return base.OnMouseUp(e); } - protected override SpriteText CreateText() => new OsuSpriteText + protected virtual SpriteText CreateText() => new OsuSpriteText { Depth = -1, Origin = Anchor.Centre, Anchor = Anchor.Centre, Font = OsuFont.GetFont(weight: FontWeight.Bold) }; + + private void enabledChanged(ValueChangedEvent e) + { + this.FadeColour(e.NewValue ? Color4.White : Color4.Gray, 200, Easing.OutQuint); + } } } diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index cdb4dc463a..5930c89d29 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.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 osuTK; using osuTK.Graphics; using osu.Framework.Allocation; @@ -9,21 +8,18 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public class SidebarButton : BasicButton + public class SidebarButton : OsuButton { private readonly SpriteIcon drawableIcon; private readonly SpriteText headerText; private readonly Box selectionIndicator; private readonly Container text; - public new Action Action; private SettingsSection section; @@ -62,9 +58,6 @@ namespace osu.Game.Overlays.Settings public SidebarButton() { - BackgroundColour = OsuColour.Gray(60); - Background.Alpha = 0; - Height = Sidebar.DEFAULT_WIDTH; RelativeSizeAxes = Axes.X; @@ -99,7 +92,6 @@ namespace osu.Game.Overlays.Settings Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, }, - new HoverClickSounds(HoverSampleSet.Loud), }); } @@ -108,23 +100,5 @@ namespace osu.Game.Overlays.Settings { selectionIndicator.Colour = colours.Yellow; } - - protected override bool OnClick(ClickEvent e) - { - Action?.Invoke(section); - return base.OnClick(e); - } - - protected override bool OnHover(HoverEvent e) - { - Background.FadeTo(0.4f, 200); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - Background.FadeTo(0, 200); - base.OnHoverLost(e); - } } } diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index d028664fe0..2948231c4b 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -123,9 +123,9 @@ namespace osu.Game.Overlays var button = new SidebarButton { Section = section, - Action = s => + Action = () => { - SectionsContainer.ScrollTo(s); + SectionsContainer.ScrollTo(section); Sidebar.State = ExpandedState.Contracted; }, }; From ebfb5d050d740e9df7ecd1d14d6ce716d57039c8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 14:36:43 +0900 Subject: [PATCH 3826/5608] Move section update code to abstract method to avoid incorrect BindValue usage --- osu.Game/Screens/Edit/Timing/DifficultySection.cs | 7 +++---- osu.Game/Screens/Edit/Timing/EffectSection.cs | 12 ++++-------- osu.Game/Screens/Edit/Timing/SampleSection.cs | 12 ++++-------- osu.Game/Screens/Edit/Timing/Section.cs | 4 ++++ osu.Game/Screens/Edit/Timing/TimingSection.cs | 12 ++++-------- 5 files changed, 19 insertions(+), 28 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/DifficultySection.cs b/osu.Game/Screens/Edit/Timing/DifficultySection.cs index cd33425ee5..05e45014eb 100644 --- a/osu.Game/Screens/Edit/Timing/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Timing/DifficultySection.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; @@ -20,11 +21,9 @@ namespace osu.Game.Screens.Edit.Timing }); } - protected override void LoadComplete() + protected override void OnControlPointChanged(ValueChangedEvent point) { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier:0.##}x"; }); + multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier:0.##}x"; } protected override DifficultyControlPoint CreatePoint() diff --git a/osu.Game/Screens/Edit/Timing/EffectSection.cs b/osu.Game/Screens/Edit/Timing/EffectSection.cs index bafdfd0b0d..2b37ffaaaf 100644 --- a/osu.Game/Screens/Edit/Timing/EffectSection.cs +++ b/osu.Game/Screens/Edit/Timing/EffectSection.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; @@ -22,15 +23,10 @@ namespace osu.Game.Screens.Edit.Timing }); } - protected override void LoadComplete() + protected override void OnControlPointChanged(ValueChangedEvent point) { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => - { - kiai.Text = $"Kiai: {(point.NewValue?.KiaiMode == true ? "on" : "off")}"; - omitBarLine.Text = $"Skip Bar Line: {(point.NewValue?.OmitFirstBarLine == true ? "on" : "off")}"; - }); + kiai.Text = $"Kiai: {(point.NewValue?.KiaiMode == true ? "on" : "off")}"; + omitBarLine.Text = $"Skip Bar Line: {(point.NewValue?.OmitFirstBarLine == true ? "on" : "off")}"; } protected override EffectControlPoint CreatePoint() diff --git a/osu.Game/Screens/Edit/Timing/SampleSection.cs b/osu.Game/Screens/Edit/Timing/SampleSection.cs index e665db0a4d..1bedb1ff42 100644 --- a/osu.Game/Screens/Edit/Timing/SampleSection.cs +++ b/osu.Game/Screens/Edit/Timing/SampleSection.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; @@ -22,15 +23,10 @@ namespace osu.Game.Screens.Edit.Timing }); } - protected override void LoadComplete() + protected override void OnControlPointChanged(ValueChangedEvent point) { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => - { - bank.Text = $"Bank: {point.NewValue?.SampleBank}"; - volume.Text = $"Volume: {point.NewValue?.SampleVolume}%"; - }); + bank.Text = $"Bank: {point.NewValue?.SampleBank}"; + volume.Text = $"Volume: {point.NewValue?.SampleVolume}%"; } protected override SampleControlPoint CreatePoint() diff --git a/osu.Game/Screens/Edit/Timing/Section.cs b/osu.Game/Screens/Edit/Timing/Section.cs index c6140ff497..ccf1582486 100644 --- a/osu.Game/Screens/Edit/Timing/Section.cs +++ b/osu.Game/Screens/Edit/Timing/Section.cs @@ -119,8 +119,12 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.Value = points.NewValue?.ControlPoints.OfType().FirstOrDefault(); checkbox.Current.Value = ControlPoint.Value != null; }, true); + + ControlPoint.BindValueChanged(OnControlPointChanged, true); } + protected abstract void OnControlPointChanged(ValueChangedEvent point); + protected abstract T CreatePoint(); } } diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs index 8609da4c4d..15007ffdb3 100644 --- a/osu.Game/Screens/Edit/Timing/TimingSection.cs +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; @@ -22,15 +23,10 @@ namespace osu.Game.Screens.Edit.Timing }); } - protected override void LoadComplete() + protected override void OnControlPointChanged(ValueChangedEvent point) { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => - { - bpm.Text = $"BPM: {point.NewValue?.BPM:0.##}"; - timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; - }); + bpm.Text = $"BPM: {point.NewValue?.BPM:0.##}"; + timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; } protected override TimingControlPoint CreatePoint() From 5e416bd18d5dc77b458cc1d1d59db2372d1b6ec8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 14:47:31 +0900 Subject: [PATCH 3827/5608] Fix tournament client crashing if beatmap added with an ID of zero --- osu.Game.Tournament/TournamentGameBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index dbfa70704b..21552882ef 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -215,7 +215,7 @@ namespace osu.Game.Tournament foreach (var r in ladder.Rounds) foreach (var b in r.Beatmaps) - if (b.BeatmapInfo == null) + if (b.BeatmapInfo == null && b.ID > 0) { var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); req.Perform(API); From 0b09fb293e0ad9bea8657a84e19dd135c1eb566d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 15:09:08 +0900 Subject: [PATCH 3828/5608] Fix background being coloured --- osu.Game/Overlays/Settings/SidebarButton.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index 5930c89d29..68836bc6b3 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -61,6 +61,8 @@ namespace osu.Game.Overlays.Settings Height = Sidebar.DEFAULT_WIDTH; RelativeSizeAxes = Axes.X; + BackgroundColour = Color4.Black; + AddRange(new Drawable[] { text = new Container From 020b08b4500c811702380b2c3286427a36d2e3b3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 14:55:05 +0900 Subject: [PATCH 3829/5608] Initial implementation of limited distance snap --- .../TestSceneOsuDistanceSnapGrid.cs | 2 +- .../Edit/OsuDistanceSnapGrid.cs | 4 +-- .../Edit/OsuHitObjectComposer.cs | 33 ++++++++++++------- .../Editor/TestSceneDistanceSnapGrid.cs | 2 +- .../Components/CircularDistanceSnapGrid.cs | 12 ++++--- .../Compose/Components/DistanceSnapGrid.cs | 21 +++++++++++- 6 files changed, 52 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index a9a6097182..aba1d8fa1d 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -153,7 +153,7 @@ namespace osu.Game.Rulesets.Osu.Tests public new float DistanceSpacing => base.DistanceSpacing; public TestOsuDistanceSnapGrid(OsuHitObject hitObject) - : base(hitObject) + : base(hitObject, null) { } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs index 79cd51a7f4..9b00204d51 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs @@ -8,8 +8,8 @@ namespace osu.Game.Rulesets.Osu.Edit { public class OsuDistanceSnapGrid : CircularDistanceSnapGrid { - public OsuDistanceSnapGrid(OsuHitObject hitObject) - : base(hitObject, hitObject.StackedEndPosition) + public OsuDistanceSnapGrid(OsuHitObject hitObject, OsuHitObject nextHitObject) + : base(hitObject, nextHitObject, hitObject.StackedEndPosition) { Masking = true; } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index fcf2772219..a021f70598 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; @@ -60,25 +61,33 @@ namespace osu.Game.Rulesets.Osu.Edit var objects = selectedHitObjects.ToList(); if (objects.Count == 0) + return createGrid(h => h.StartTime <= EditorClock.CurrentTime); + + double minTime = objects.Min(h => h.StartTime); + return createGrid(h => h.StartTime < minTime); + } + + private OsuDistanceSnapGrid createGrid(Func hitObjectSelector) + { + int lastIndex = -1; + + for (int i = 0; i < EditorBeatmap.HitObjects.Count; i++) { - var lastObject = EditorBeatmap.HitObjects.LastOrDefault(h => h.StartTime <= EditorClock.CurrentTime); + HitObject hitObject = EditorBeatmap.HitObjects[i]; - if (lastObject == null) - return null; + if (!hitObjectSelector(hitObject)) + break; - return new OsuDistanceSnapGrid(lastObject); + lastIndex = i; } - else - { - double minTime = objects.Min(h => h.StartTime); - var lastObject = EditorBeatmap.HitObjects.LastOrDefault(h => h.StartTime < minTime); + if (lastIndex == -1) + return null; - if (lastObject == null) - return null; + OsuHitObject lastObject = EditorBeatmap.HitObjects[lastIndex]; + OsuHitObject nextObject = lastIndex == EditorBeatmap.HitObjects.Count - 1 ? null : EditorBeatmap.HitObjects[lastIndex + 1]; - return new OsuDistanceSnapGrid(lastObject); - } + return new OsuDistanceSnapGrid(lastObject, nextObject); } } } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index b8c31d5dbb..0681dff528 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -62,7 +62,7 @@ namespace osu.Game.Tests.Visual.Editor public new float DistanceSpacing => base.DistanceSpacing; public TestDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) - : base(hitObject, centrePosition) + : base(hitObject, null, centrePosition) { } diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index f45115e1e4..0f2bae6305 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -12,8 +12,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { public abstract class CircularDistanceSnapGrid : DistanceSnapGrid { - protected CircularDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) - : base(hitObject, centrePosition) + protected CircularDistanceSnapGrid(HitObject hitObject, HitObject nextHitObject, Vector2 centrePosition) + : base(hitObject, nextHitObject, centrePosition) { } @@ -45,7 +45,7 @@ namespace osu.Game.Screens.Edit.Compose.Components float dx = Math.Max(centrePosition.X, DrawWidth - centrePosition.X); float dy = Math.Max(centrePosition.Y, DrawHeight - centrePosition.Y); float maxDistance = new Vector2(dx, dy).Length; - int requiredCircles = (int)(maxDistance / DistanceSpacing); + int requiredCircles = Math.Min(MaxIntervals, (int)(maxDistance / DistanceSpacing)); for (int i = 0; i < requiredCircles; i++) { @@ -65,15 +65,17 @@ namespace osu.Game.Screens.Edit.Compose.Components public override (Vector2 position, double time) GetSnappedPosition(Vector2 position) { - Vector2 direction = position - CentrePosition; + if (MaxIntervals == 0) + return (CentrePosition, StartTime); + Vector2 direction = position - CentrePosition; if (direction == Vector2.Zero) direction = new Vector2(0.001f, 0.001f); float distance = direction.Length; float radius = DistanceSpacing; - int radialCount = Math.Max(1, (int)Math.Round(distance / radius)); + int radialCount = MathHelper.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); Vector2 normalisedDirection = direction * new Vector2(1f / distance); Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 193474093f..475b6e7274 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.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 JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Graphics; @@ -29,6 +30,11 @@ namespace osu.Game.Screens.Edit.Compose.Components /// protected double StartTime { get; private set; } + /// + /// The maximum number of distance snapping intervals allowed. + /// + protected int MaxIntervals { get; private set; } + /// /// The position which the grid is centred on. /// The first beat snapping tick is located at + in the desired direction. @@ -49,12 +55,15 @@ namespace osu.Game.Screens.Edit.Compose.Components private readonly Cached gridCache = new Cached(); private readonly HitObject hitObject; + private readonly HitObject nextHitObject; - protected DistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) + protected DistanceSnapGrid(HitObject hitObject, [CanBeNull] HitObject nextHitObject, Vector2 centrePosition) { this.hitObject = hitObject; + this.nextHitObject = nextHitObject; CentrePosition = centrePosition; + RelativeSizeAxes = Axes.Both; } @@ -74,6 +83,16 @@ namespace osu.Game.Screens.Edit.Compose.Components private void updateSpacing() { DistanceSpacing = SnapProvider.GetBeatSnapDistanceAt(StartTime); + + if (nextHitObject == null) + MaxIntervals = int.MaxValue; + else + { + // +1 is added since a snapped hitobject may have its start time slightly less than the snapped time due to floating point errors + double maxDuration = nextHitObject.StartTime - StartTime + 1; + MaxIntervals = (int)(maxDuration / SnapProvider.DistanceToDuration(StartTime, DistanceSpacing)); + } + gridCache.Invalidate(); } From c1a6cb1defaa7fc0008f1de0db821d3faf253fdb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 15:58:47 +0900 Subject: [PATCH 3830/5608] Fix audio preview muting game audio indefinitely when beatmap panel is off-screen --- osu.Game/Audio/PreviewTrack.cs | 5 ++++- osu.Game/Audio/PreviewTrackManager.cs | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 22ce7d4711..937ad7e45a 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -13,11 +13,13 @@ namespace osu.Game.Audio { /// /// Invoked when this has stopped playing. + /// Not invoked in a thread-safe context. /// public event Action Stopped; /// /// Invoked when this has started playing. + /// Not invoked in a thread-safe context. /// public event Action Started; @@ -29,7 +31,7 @@ namespace osu.Game.Audio { track = GetTrack(); if (track != null) - track.Completed += () => Schedule(Stop); + track.Completed += Stop; } /// @@ -93,6 +95,7 @@ namespace osu.Game.Audio hasStarted = false; track.Stop(); + Stopped?.Invoke(); } diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index e12c46ef16..fad2b5a5e8 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -46,18 +46,18 @@ namespace osu.Game.Audio { var track = CreatePreviewTrack(beatmapSetInfo, trackStore); - track.Started += () => + track.Started += () => Schedule(() => { current?.Stop(); current = track; audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); - }; + }); - track.Stopped += () => + track.Stopped += () => Schedule(() => { current = null; audio.Tracks.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); - }; + }); return track; } From 2588534eda26d2a00f6cf070f0d150a9ee556eb1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 16:04:20 +0900 Subject: [PATCH 3831/5608] Skin entire selection, add xmldocs --- .../Edit/OsuHitObjectComposer.cs | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index a021f70598..812afaaa24 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -64,30 +64,37 @@ namespace osu.Game.Rulesets.Osu.Edit return createGrid(h => h.StartTime <= EditorClock.CurrentTime); double minTime = objects.Min(h => h.StartTime); - return createGrid(h => h.StartTime < minTime); + return createGrid(h => h.StartTime < minTime, objects.Count + 1); } - private OsuDistanceSnapGrid createGrid(Func hitObjectSelector) + /// + /// Creates a grid from the last matching a predicate to a target . + /// + /// A predicate that matches s where the grid can start from. + /// Only the last matching the predicate is used. + /// An offset from the selected via at which the grid should stop. + /// The from a selected to a target . + private OsuDistanceSnapGrid createGrid(Func sourceSelector, int targetOffset = 1) { - int lastIndex = -1; + if (targetOffset < 1) throw new ArgumentOutOfRangeException(nameof(targetOffset)); + + int sourceIndex = -1; for (int i = 0; i < EditorBeatmap.HitObjects.Count; i++) { - HitObject hitObject = EditorBeatmap.HitObjects[i]; - - if (!hitObjectSelector(hitObject)) + if (!sourceSelector(EditorBeatmap.HitObjects[i])) break; - lastIndex = i; + sourceIndex = i; } - if (lastIndex == -1) + if (sourceIndex == -1) return null; - OsuHitObject lastObject = EditorBeatmap.HitObjects[lastIndex]; - OsuHitObject nextObject = lastIndex == EditorBeatmap.HitObjects.Count - 1 ? null : EditorBeatmap.HitObjects[lastIndex + 1]; + OsuHitObject sourceObject = EditorBeatmap.HitObjects[sourceIndex]; + OsuHitObject targetObject = sourceIndex + targetOffset < EditorBeatmap.HitObjects.Count ? EditorBeatmap.HitObjects[sourceIndex + targetOffset] : null; - return new OsuDistanceSnapGrid(lastObject, nextObject); + return new OsuDistanceSnapGrid(sourceObject, targetObject); } } } From d985d048574ef01800fd3973d65583e273d4c45a Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Wed, 6 Nov 2019 14:07:05 +0700 Subject: [PATCH 3832/5608] Add background colour to music player ProgressBar --- osu.Game/Overlays/NowPlayingOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 6b79f2af07..8c7e717a82 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -174,6 +174,7 @@ namespace osu.Game.Overlays Anchor = Anchor.BottomCentre, Height = progress_height, FillColour = colours.Yellow, + BackgroundColour = colours.YellowDarker.Opacity(0.5f), OnSeek = musicController.SeekTo } }, From 02c21a1379e24a7ec2bb4c2b47c2c6efbcd0a103 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Wed, 6 Nov 2019 14:11:47 +0700 Subject: [PATCH 3833/5608] Make progress bar hoverable --- osu.Game/Overlays/NowPlayingOverlay.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 8c7e717a82..4f73cbfacd 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -168,11 +168,11 @@ namespace osu.Game.Overlays }, } }, - progressBar = new ProgressBar + progressBar = new HoverableProgressBar { Origin = Anchor.BottomCentre, Anchor = Anchor.BottomCentre, - Height = progress_height, + Height = progress_height / 2, FillColour = colours.Yellow, BackgroundColour = colours.YellowDarker.Opacity(0.5f), OnSeek = musicController.SeekTo @@ -402,5 +402,20 @@ namespace osu.Game.Overlays return base.OnDragEnd(e); } } + + private class HoverableProgressBar : ProgressBar + { + protected override bool OnHover(HoverEvent e) + { + this.ResizeHeightTo(progress_height, 500, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + this.ResizeHeightTo(progress_height / 2, 500, Easing.OutQuint); + base.OnHoverLost(e); + } + } } } From b83ceab1c1b2ba594efa02d166f364a32142e4ac Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 16:20:13 +0900 Subject: [PATCH 3834/5608] Add tests --- .../TestSceneOsuDistanceSnapGrid.cs | 47 ++++++++++++++----- .../Editor/TestSceneDistanceSnapGrid.cs | 39 +++++++++++---- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index aba1d8fa1d..eff4d919b0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -42,11 +42,19 @@ namespace osu.Game.Rulesets.Osu.Tests [Cached(typeof(IDistanceSnapProvider))] private readonly SnapProvider snapProvider = new SnapProvider(); - private readonly TestOsuDistanceSnapGrid grid; + private TestOsuDistanceSnapGrid grid; public TestSceneOsuDistanceSnapGrid() { editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + } + + [SetUp] + public void Setup() => Schedule(() => + { + editorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 1; + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); Children = new Drawable[] { @@ -58,14 +66,6 @@ namespace osu.Game.Rulesets.Osu.Tests grid = new TestOsuDistanceSnapGrid(new HitCircle { Position = grid_position }), new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position } }; - } - - [SetUp] - public void Setup() => Schedule(() => - { - editorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 1; - editorBeatmap.ControlPointInfo.Clear(); - editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); }); [TestCase(1)] @@ -102,6 +102,27 @@ namespace osu.Game.Rulesets.Osu.Tests assertSnappedDistance((float)beat_length * 2); } + [Test] + public void TestLimitedDistance() + { + AddStep("create limited grid", () => + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.SlateGray + }, + grid = new TestOsuDistanceSnapGrid(new HitCircle { Position = grid_position }, new HitCircle { StartTime = 200 }), + new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position } + }; + }); + + AddStep("move mouse outside grid", () => InputManager.MoveMouseTo(grid.ToScreenSpace(grid_position + new Vector2((float)beat_length, 0) * 3f))); + assertSnappedDistance((float)beat_length * 2); + } + private void assertSnappedDistance(float expectedDistance) => AddAssert($"snap distance = {expectedDistance}", () => { Vector2 snappedPosition = grid.GetSnappedPosition(grid.ToLocalSpace(InputManager.CurrentState.Mouse.Position)).position; @@ -152,8 +173,8 @@ namespace osu.Game.Rulesets.Osu.Tests { public new float DistanceSpacing => base.DistanceSpacing; - public TestOsuDistanceSnapGrid(OsuHitObject hitObject) - : base(hitObject, null) + public TestOsuDistanceSnapGrid(OsuHitObject hitObject, OsuHitObject nextHitObject = null) + : base(hitObject, nextHitObject) { } } @@ -164,9 +185,9 @@ namespace osu.Game.Rulesets.Osu.Tests public float GetBeatSnapDistanceAt(double referenceTime) => (float)beat_length; - public float DurationToDistance(double referenceTime, double duration) => 0; + public float DurationToDistance(double referenceTime, double duration) => (float)duration; - public double DistanceToDuration(double referenceTime, float distance) => 0; + public double DistanceToDuration(double referenceTime, float distance) => distance; public double GetSnappedDurationFromDistance(double referenceTime, float distance) => 0; diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index 0681dff528..e4c987923c 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -32,7 +32,11 @@ namespace osu.Game.Tests.Visual.Editor { editorBeatmap = new EditorBeatmap(new OsuBeatmap()); editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); + } + [SetUp] + public void Setup() => Schedule(() => + { Children = new Drawable[] { new Box @@ -42,7 +46,7 @@ namespace osu.Game.Tests.Visual.Editor }, new TestDistanceSnapGrid(new HitObject(), grid_position) }; - } + }); [TestCase(1)] [TestCase(2)] @@ -57,12 +61,29 @@ namespace osu.Game.Tests.Visual.Editor AddStep($"set beat divisor = {divisor}", () => BeatDivisor.Value = divisor); } + [Test] + public void TestLimitedDistance() + { + AddStep("create limited grid", () => + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.SlateGray + }, + new TestDistanceSnapGrid(new HitObject(), grid_position, new HitObject { StartTime = 100 }) + }; + }); + } + private class TestDistanceSnapGrid : DistanceSnapGrid { public new float DistanceSpacing => base.DistanceSpacing; - public TestDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) - : base(hitObject, null, centrePosition) + public TestDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition, HitObject nextHitObject = null) + : base(hitObject, nextHitObject, centrePosition) { } @@ -77,7 +98,7 @@ namespace osu.Game.Tests.Visual.Editor int beatIndex = 0; - for (float s = centrePosition.X + DistanceSpacing; s <= DrawWidth; s += DistanceSpacing, beatIndex++) + for (float s = centrePosition.X + DistanceSpacing; s <= DrawWidth && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++) { AddInternal(new Circle { @@ -90,7 +111,7 @@ namespace osu.Game.Tests.Visual.Editor beatIndex = 0; - for (float s = centrePosition.X - DistanceSpacing; s >= 0; s -= DistanceSpacing, beatIndex++) + for (float s = centrePosition.X - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++) { AddInternal(new Circle { @@ -103,7 +124,7 @@ namespace osu.Game.Tests.Visual.Editor beatIndex = 0; - for (float s = centrePosition.Y + DistanceSpacing; s <= DrawHeight; s += DistanceSpacing, beatIndex++) + for (float s = centrePosition.Y + DistanceSpacing; s <= DrawHeight && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++) { AddInternal(new Circle { @@ -116,7 +137,7 @@ namespace osu.Game.Tests.Visual.Editor beatIndex = 0; - for (float s = centrePosition.Y - DistanceSpacing; s >= 0; s -= DistanceSpacing, beatIndex++) + for (float s = centrePosition.Y - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++) { AddInternal(new Circle { @@ -138,9 +159,9 @@ namespace osu.Game.Tests.Visual.Editor public float GetBeatSnapDistanceAt(double referenceTime) => 10; - public float DurationToDistance(double referenceTime, double duration) => 0; + public float DurationToDistance(double referenceTime, double duration) => (float)duration; - public double DistanceToDuration(double referenceTime, float distance) => 0; + public double DistanceToDuration(double referenceTime, float distance) => distance; public double GetSnappedDurationFromDistance(double referenceTime, float distance) => 0; From ee544e174a3971716fcd9a6ea0f284c2cb213da3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 16:33:42 +0900 Subject: [PATCH 3835/5608] Group -> Connection --- .../TestSceneFollowPoints.cs | 4 +- ...PointGroup.cs => FollowPointConnection.cs} | 6 +- .../Connections/FollowPointRenderer.cs | 76 +++++++++---------- 3 files changed, 43 insertions(+), 43 deletions(-) rename osu.Game.Rulesets.Osu/Objects/Drawables/Connections/{FollowPointGroup.cs => FollowPointConnection.cs} (95%) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index 79a1bb579f..94ca2d4cd1 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -188,7 +188,7 @@ namespace osu.Game.Rulesets.Osu.Tests private void assertGroups() { - AddAssert("has correct group count", () => followPointRenderer.Groups.Count == hitObjectContainer.Count); + AddAssert("has correct group count", () => followPointRenderer.Connections.Count == hitObjectContainer.Count); AddAssert("group endpoints are correct", () => { for (int i = 0; i < hitObjectContainer.Count; i++) @@ -209,7 +209,7 @@ namespace osu.Game.Rulesets.Osu.Tests private DrawableOsuHitObject getObject(int index) => hitObjectContainer[index]; - private FollowPointGroup getGroup(int index) => followPointRenderer.Groups[index]; + private FollowPointConnection getGroup(int index) => followPointRenderer.Connections[index]; private class TestHitObjectContainer : Container { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs similarity index 95% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs index 168d2b8532..1e032eb977 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// Visualises the s between two s. /// - public class FollowPointGroup : CompositeDrawable + public class FollowPointConnection : CompositeDrawable { // Todo: These shouldn't be constants private const int spacing = 32; @@ -32,10 +32,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections public readonly DrawableOsuHitObject Start; /// - /// Creates a new . + /// Creates a new . /// /// The which s will exit from. - public FollowPointGroup([NotNull] DrawableOsuHitObject start) + public FollowPointConnection([NotNull] DrawableOsuHitObject start) { Start = start; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index afd86e004d..00ef0ba0d0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -10,16 +10,16 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { /// - /// Visualises groups of s. + /// Visualises connections between s. /// public class FollowPointRenderer : CompositeDrawable { /// - /// All the s contained by this . + /// All the s contained by this . /// - internal IReadOnlyList Groups => groups; + internal IReadOnlyList Connections => connections; - private readonly List groups = new List(); + private readonly List connections = new List(); public override bool RemoveCompletedTransforms => false; @@ -29,84 +29,84 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// The to add s for. public void AddFollowPoints(DrawableOsuHitObject hitObject) - => addGroup(new FollowPointGroup(hitObject).With(g => g.StartTime.BindValueChanged(_ => onStartTimeChanged(g)))); + => addConnection(new FollowPointConnection(hitObject).With(g => g.StartTime.BindValueChanged(_ => onStartTimeChanged(g)))); /// /// Removes the s around a . /// This includes s leading into , and s exiting . /// /// The to remove s for. - public void RemoveFollowPoints(DrawableOsuHitObject hitObject) => removeGroup(groups.Single(g => g.Start == hitObject)); + public void RemoveFollowPoints(DrawableOsuHitObject hitObject) => removeGroup(connections.Single(g => g.Start == hitObject)); /// - /// Adds a to this . + /// Adds a to this . /// - /// The to add. - /// The index of in . - private int addGroup(FollowPointGroup group) + /// The to add. + /// The index of in . + private int addConnection(FollowPointConnection connection) { - AddInternal(group); + AddInternal(connection); - // Groups are sorted by their start time when added such that the index can be used to post-process other surrounding groups - int index = groups.AddInPlace(group, Comparer.Create((g1, g2) => g1.StartTime.Value.CompareTo(g2.StartTime.Value))); + // Groups are sorted by their start time when added such that the index can be used to post-process other surrounding connections + int index = connections.AddInPlace(connection, Comparer.Create((g1, g2) => g1.StartTime.Value.CompareTo(g2.StartTime.Value))); - if (index < groups.Count - 1) + if (index < connections.Count - 1) { - // Update the group's end point to the next group's start point + // Update the connection's end point to the next connection's start point // h1 -> -> -> h2 - // group nextGroup + // connection nextGroup - FollowPointGroup nextGroup = groups[index + 1]; - group.End = nextGroup.Start; + FollowPointConnection nextConnection = connections[index + 1]; + connection.End = nextConnection.Start; } else { // The end point may be non-null during re-ordering - group.End = null; + connection.End = null; } if (index > 0) { - // Update the previous group's end point to the current group's start point + // Update the previous connection's end point to the current connection's start point // h1 -> -> -> h2 - // prevGroup group + // prevGroup connection - FollowPointGroup previousGroup = groups[index - 1]; - previousGroup.End = group.Start; + FollowPointConnection previousConnection = connections[index - 1]; + previousConnection.End = connection.Start; } return index; } /// - /// Removes a from this . + /// Removes a from this . /// - /// The to remove. - /// Whether was removed. - private bool removeGroup(FollowPointGroup group) + /// The to remove. + /// Whether was removed. + private bool removeGroup(FollowPointConnection connection) { - RemoveInternal(group); + RemoveInternal(connection); - int index = groups.IndexOf(group); + int index = connections.IndexOf(connection); if (index > 0) { - // Update the previous group's end point to the next group's start point + // Update the previous connection's end point to the next connection's start point // h1 -> -> -> h2 -> -> -> h3 - // prevGroup group nextGroup - // The current group's end point is used since there may not be a next group - FollowPointGroup previousGroup = groups[index - 1]; - previousGroup.End = group.End; + // prevGroup connection nextGroup + // The current connection's end point is used since there may not be a next connection + FollowPointConnection previousConnection = connections[index - 1]; + previousConnection.End = connection.End; } - return groups.Remove(group); + return connections.Remove(connection); } - private void onStartTimeChanged(FollowPointGroup group) + private void onStartTimeChanged(FollowPointConnection connection) { // Naive but can be improved if performance becomes an issue - removeGroup(group); - addGroup(group); + removeGroup(connection); + addConnection(connection); } } } From 7b5b3ff15c21d378d607b2e4cccafe2a8f366bc3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 16:36:12 +0900 Subject: [PATCH 3836/5608] Remove unused returns --- .../Objects/Drawables/Connections/FollowPointRenderer.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 00ef0ba0d0..be192080f9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// The to add. /// The index of in . - private int addConnection(FollowPointConnection connection) + private void addConnection(FollowPointConnection connection) { AddInternal(connection); @@ -74,8 +74,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections FollowPointConnection previousConnection = connections[index - 1]; previousConnection.End = connection.Start; } - - return index; } /// @@ -83,7 +81,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// The to remove. /// Whether was removed. - private bool removeGroup(FollowPointConnection connection) + private void removeGroup(FollowPointConnection connection) { RemoveInternal(connection); @@ -99,7 +97,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections previousConnection.End = connection.End; } - return connections.Remove(connection); + connections.Remove(connection); } private void onStartTimeChanged(FollowPointConnection connection) From 2c1bfd62efaba5e37651de1ea97911674c1c5539 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 17:27:41 +0900 Subject: [PATCH 3837/5608] Disallow selections to be moved outside of the playfield --- .../Edit/ManiaSelectionHandler.cs | 4 +-- .../Edit/OsuSelectionHandler.cs | 25 +++++++++++++++++-- .../Compose/Components/BlueprintContainer.cs | 3 ++- .../Compose/Components/SelectionHandler.cs | 5 ++-- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 732231b0d9..9cdf045b5b 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Edit editorClock = clock; } - public override void HandleMovement(MoveSelectionEvent moveEvent) + public override bool HandleMovement(MoveSelectionEvent moveEvent) { var maniaBlueprint = (ManiaSelectionBlueprint)moveEvent.Blueprint; int lastColumn = maniaBlueprint.DrawableObject.HitObject.Column; @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Edit performDragMovement(moveEvent); performColumnMovement(lastColumn, moveEvent); - base.HandleMovement(moveEvent); + return true; } /// diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index 472267eb66..9418565907 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -4,13 +4,34 @@ using System.Linq; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose.Components; +using osuTK; namespace osu.Game.Rulesets.Osu.Edit { public class OsuSelectionHandler : SelectionHandler { - public override void HandleMovement(MoveSelectionEvent moveEvent) + public override bool HandleMovement(MoveSelectionEvent moveEvent) { + Vector2 minPosition = new Vector2(float.MaxValue, float.MaxValue); + Vector2 maxPosition = new Vector2(float.MinValue, float.MinValue); + + // Go through all hitobjects to make sure they would remain in the bounds of the editor after movement, before any movement is attempted + foreach (var h in SelectedHitObjects.OfType()) + { + if (h is Spinner) + { + // Spinners don't support position adjustments + continue; + } + + // Stacking is not considered + minPosition = Vector2.ComponentMin(minPosition, Vector2.ComponentMin(h.EndPosition + moveEvent.InstantDelta, h.Position + moveEvent.InstantDelta)); + maxPosition = Vector2.ComponentMax(maxPosition, Vector2.ComponentMax(h.EndPosition + moveEvent.InstantDelta, h.Position + moveEvent.InstantDelta)); + } + + if (minPosition.X < 0 || minPosition.Y < 0 || maxPosition.X > DrawWidth || maxPosition.Y > DrawHeight) + return false; + foreach (var h in SelectedHitObjects.OfType()) { if (h is Spinner) @@ -22,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Edit h.Position += moveEvent.InstantDelta; } - base.HandleMovement(moveEvent); + return true; } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 288c712bde..c4d8176c7a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -367,7 +367,8 @@ namespace osu.Game.Screens.Edit.Compose.Components (Vector2 snappedPosition, double snappedTime) = composer.GetSnappedPosition(ToLocalSpace(movePosition), draggedObject.StartTime); // Move the hitobjects - selectionHandler.HandleMovement(new MoveSelectionEvent(movementBlueprint, startPosition, ToScreenSpace(snappedPosition))); + if (!selectionHandler.HandleMovement(new MoveSelectionEvent(movementBlueprint, startPosition, ToScreenSpace(snappedPosition)))) + return true; // Apply the start time at the newly snapped-to position double offset = snappedTime - draggedObject.StartTime; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 1722476e53..44bf22cfe1 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -68,9 +68,8 @@ namespace osu.Game.Screens.Edit.Compose.Components /// Handles the selected s being moved. /// /// The move event. - public virtual void HandleMovement(MoveSelectionEvent moveEvent) - { - } + /// Whether any s were moved. + public virtual bool HandleMovement(MoveSelectionEvent moveEvent) => false; public bool OnPressed(PlatformAction action) { From ee4839b7e7e3f44b4be35b536a5abcacf96aa8cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 18:09:36 +0900 Subject: [PATCH 3838/5608] Reduce delay on parallax --- osu.Game/Graphics/Containers/ParallaxContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index f65a0a469a..a5ebac5b1f 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -71,7 +71,7 @@ namespace osu.Game.Graphics.Containers double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000); - content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, 1000, Easing.OutQuint); + content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, 100, Easing.OutQuint); content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); } From aaa06396f0e8699a3737dbb34293acb9a9784c0b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 18:11:56 +0900 Subject: [PATCH 3839/5608] Reduce editor parallax --- osu.Game/Screens/Edit/Editor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 35408e4003..e97c89c2dc 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -36,6 +36,8 @@ namespace osu.Game.Screens.Edit { protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4"); + public override float BackgroundParallaxAmount => 0.1f; + public override bool AllowBackButton => false; public override bool HideOverlaysOnEnter => true; From 3680e7c7047853f936075675855a2410b93b3721 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 18:15:57 +0900 Subject: [PATCH 3840/5608] Seek editor when hit objects are double clicked --- .../Edit/Compose/Components/BlueprintContainer.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 288c712bde..1ce7863d60 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Input; using osu.Framework.Input.Events; +using osu.Framework.Timing; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Objects; @@ -30,6 +31,9 @@ namespace osu.Game.Screens.Edit.Compose.Components private SelectionHandler selectionHandler; private InputManager inputManager; + [Resolved] + private IAdjustableClock adjustableClock { get; set; } + [Resolved] private HitObjectComposer composer { get; set; } @@ -106,6 +110,17 @@ namespace osu.Game.Screens.Edit.Compose.Components return true; } + protected override bool OnDoubleClick(DoubleClickEvent e) + { + SelectionBlueprint clickedBlueprint = selectionHandler.SelectedBlueprints.FirstOrDefault(b => b.IsHovered); + + if (clickedBlueprint == null) + return false; + + adjustableClock?.Seek(clickedBlueprint.DrawableObject.HitObject.StartTime); + return true; + } + protected override bool OnMouseUp(MouseUpEvent e) { // Special case for when a drag happened instead of a click From 4330507da8862d9d6cb8118bba95ac375bbd5972 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 6 Nov 2019 12:46:25 +0300 Subject: [PATCH 3841/5608] Use api.IsLoggedIn --- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 12 +++++++++--- osu.Game/Overlays/Comments/VotePill.cs | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index 22e11aa464..c113bf0a04 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -10,6 +10,7 @@ using osu.Framework.Allocation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Users; using osu.Framework.MathUtils; +using osu.Game.Online.API; namespace osu.Game.Tests.Visual.Online { @@ -21,6 +22,11 @@ namespace osu.Game.Tests.Visual.Online typeof(VotePill) }; + protected override bool UseOnlineAPI => true; + + [Resolved] + private IAPIProvider api { get; set; } + private VotePill votePill; [BackgroundDependencyLoader] @@ -33,7 +39,7 @@ namespace osu.Game.Tests.Visual.Online VotesCount = 2, }; - AddStep("Log in", () => API.LocalUser.Value = new User + AddStep("Log in", () => api.LocalUser.Value = new User { Id = RNG.Next(2, 100000) }); @@ -45,7 +51,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("Click", () => votePill.Click()); AddAssert("Loading", () => votePill.IsLoading); - AddStep("Log out", API.Logout); + AddStep("Log out", api.Logout); AddStep("Random comment", () => addVotePill(randomComment)); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => !votePill.IsLoading); @@ -54,7 +60,7 @@ namespace osu.Game.Tests.Visual.Online private Comment getUserComment() => new Comment { IsVoted = false, - UserId = API.LocalUser.Value.Id, + UserId = api.LocalUser.Value.Id, VotesCount = 10, }; diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index ad17264229..a5a19f5111 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Comments AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; hoverLayer.Colour = Color4.Black.Opacity(0.5f); - if (api.LocalUser.Value.Id != comment.UserId && api.LocalUser.Value.Id != 1) + if (api.LocalUser.Value.Id != comment.UserId && api.IsLoggedIn) Action = onAction; } From 5589329e16aec04e473f41310ffb307bd08e0f51 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 6 Nov 2019 12:54:04 +0300 Subject: [PATCH 3842/5608] Split tests --- .../Visual/Online/TestSceneVotePill.cs | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index c113bf0a04..c93fbabb41 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -29,16 +29,9 @@ namespace osu.Game.Tests.Visual.Online private VotePill votePill; - [BackgroundDependencyLoader] - private void load() + [Test] + public void TestUserCommentPill() { - var randomComment = new Comment - { - IsVoted = false, - UserId = 4444, - VotesCount = 2, - }; - AddStep("Log in", () => api.LocalUser.Value = new User { Id = RNG.Next(2, 100000) @@ -46,13 +39,25 @@ namespace osu.Game.Tests.Visual.Online AddStep("User comment", () => addVotePill(getUserComment())); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => !votePill.IsLoading); + } - AddStep("Random comment", () => addVotePill(randomComment)); + [Test] + public void TestRandomCommentPill() + { + AddStep("Log in", () => api.LocalUser.Value = new User + { + Id = RNG.Next(2, 100000) + }); + AddStep("Random comment", () => addVotePill(getRandomComment())); AddStep("Click", () => votePill.Click()); AddAssert("Loading", () => votePill.IsLoading); + } + [Test] + public void TestOfflineRandomCommentPill() + { AddStep("Log out", api.Logout); - AddStep("Random comment", () => addVotePill(randomComment)); + AddStep("Random comment", () => addVotePill(getRandomComment())); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => !votePill.IsLoading); } @@ -64,6 +69,13 @@ namespace osu.Game.Tests.Visual.Online VotesCount = 10, }; + private Comment getRandomComment() => new Comment + { + IsVoted = false, + UserId = 4444, + VotesCount = 2, + }; + private void addVotePill(Comment comment) { Clear(); From 31f2d6a842e380077b4866e948b8b50dfce864e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 19:06:24 +0900 Subject: [PATCH 3843/5608] Fix regressed test --- .../Components/TestScenePreviewTrackManager.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index df6740421b..f3f6444149 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -34,6 +34,7 @@ namespace osu.Game.Tests.Visual.Components PreviewTrack track = null; AddStep("get track", () => track = getOwnedTrack()); + AddUntilStep("wait loaded", () => track.IsLoaded); AddStep("start", () => track.Start()); AddAssert("started", () => track.IsRunning); AddStep("stop", () => track.Stop()); @@ -52,6 +53,8 @@ namespace osu.Game.Tests.Visual.Components track2 = getOwnedTrack(); }); + AddUntilStep("wait loaded", () => track1.IsLoaded && track2.IsLoaded); + AddStep("start track 1", () => track1.Start()); AddStep("start track 2", () => track2.Start()); AddAssert("track 1 stopped", () => !track1.IsRunning); @@ -64,6 +67,7 @@ namespace osu.Game.Tests.Visual.Components PreviewTrack track = null; AddStep("get track", () => track = getOwnedTrack()); + AddUntilStep("wait loaded", () => track.IsLoaded); AddStep("start", () => track.Start()); AddStep("stop by owner", () => trackManager.StopAnyPlaying(this)); AddAssert("stopped", () => !track.IsRunning); @@ -76,6 +80,7 @@ namespace osu.Game.Tests.Visual.Components PreviewTrack track = null; AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack()))); + AddUntilStep("wait loaded", () => track.IsLoaded); AddStep("start", () => track.Start()); AddStep("attempt stop", () => trackManager.StopAnyPlaying(this)); AddAssert("not stopped", () => track.IsRunning); @@ -89,16 +94,24 @@ namespace osu.Game.Tests.Visual.Components { var track = getTrack(); - Add(track); + LoadComponentAsync(track, Add); return track; } private class TestTrackOwner : CompositeDrawable, IPreviewTrackOwner { + private readonly PreviewTrack track; + public TestTrackOwner(PreviewTrack track) { - AddInternal(track); + this.track = track; + } + + [BackgroundDependencyLoader] + private void load() + { + LoadComponentAsync(track, AddInternal); } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) From 423e26a4d147cef6525e9e88b3e86497e3978189 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 6 Nov 2019 13:07:25 +0300 Subject: [PATCH 3844/5608] 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 6ecea0e4c1e3ce8a42a5880baf7c6a7730d85844 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 18:15:49 +0300 Subject: [PATCH 3845/5608] Fix DummyAPIAccess being potentially incorrect --- osu.Game/Online/API/DummyAPIAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 6c04c77dc0..28132765d3 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -19,7 +19,7 @@ namespace osu.Game.Online.API public Bindable Activity { get; } = new Bindable(); - public bool IsLoggedIn => true; + public bool IsLoggedIn => State == APIState.Online; public string ProvidedUsername => LocalUser.Value.Username; From 8395df596b8cc14000aa3548d0b96f81c727fab2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 6 Nov 2019 18:24:30 +0300 Subject: [PATCH 3846/5608] Don't use online API for tests --- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index c93fbabb41..5bdafdfec4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -6,11 +6,9 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Overlays.Comments; -using osu.Framework.Allocation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Users; using osu.Framework.MathUtils; -using osu.Game.Online.API; namespace osu.Game.Tests.Visual.Online { @@ -22,17 +20,12 @@ namespace osu.Game.Tests.Visual.Online typeof(VotePill) }; - protected override bool UseOnlineAPI => true; - - [Resolved] - private IAPIProvider api { get; set; } - private VotePill votePill; [Test] public void TestUserCommentPill() { - AddStep("Log in", () => api.LocalUser.Value = new User + AddStep("Log in", () => API.LocalUser.Value = new User { Id = RNG.Next(2, 100000) }); @@ -44,7 +37,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestRandomCommentPill() { - AddStep("Log in", () => api.LocalUser.Value = new User + AddStep("Log in", () => API.LocalUser.Value = new User { Id = RNG.Next(2, 100000) }); @@ -56,7 +49,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestOfflineRandomCommentPill() { - AddStep("Log out", api.Logout); + AddStep("Log out", API.Logout); AddStep("Random comment", () => addVotePill(getRandomComment())); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => !votePill.IsLoading); @@ -65,7 +58,7 @@ namespace osu.Game.Tests.Visual.Online private Comment getUserComment() => new Comment { IsVoted = false, - UserId = api.LocalUser.Value.Id, + UserId = API.LocalUser.Value.Id, VotesCount = 10, }; From 59aa9b59d62a5c830e12454aae1bb5d0f1e15cde Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 6 Nov 2019 18:32:09 +0300 Subject: [PATCH 3847/5608] Move login to it's own function --- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index 5bdafdfec4..8197cf72de 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -7,8 +7,6 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Overlays.Comments; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Users; -using osu.Framework.MathUtils; namespace osu.Game.Tests.Visual.Online { @@ -25,10 +23,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestUserCommentPill() { - AddStep("Log in", () => API.LocalUser.Value = new User - { - Id = RNG.Next(2, 100000) - }); + AddStep("Log in", logIn); AddStep("User comment", () => addVotePill(getUserComment())); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => !votePill.IsLoading); @@ -37,10 +32,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestRandomCommentPill() { - AddStep("Log in", () => API.LocalUser.Value = new User - { - Id = RNG.Next(2, 100000) - }); + AddStep("Log in", logIn); AddStep("Random comment", () => addVotePill(getRandomComment())); AddStep("Click", () => votePill.Click()); AddAssert("Loading", () => votePill.IsLoading); @@ -55,6 +47,8 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Not loading", () => !votePill.IsLoading); } + private void logIn() => API.Login("localUser", "password"); + private Comment getUserComment() => new Comment { IsVoted = false, From 55230a36dd089d49513f074ddcfc8b3070db056e Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 19:58:07 +0300 Subject: [PATCH 3848/5608] Set correct legacy version --- osu.Game/Skinning/LegacySkinConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs index 051d10747b..f9bf78b8ad 100644 --- a/osu.Game/Skinning/LegacySkinConfiguration.cs +++ b/osu.Game/Skinning/LegacySkinConfiguration.cs @@ -5,7 +5,7 @@ namespace osu.Game.Skinning { public class LegacySkinConfiguration : DefaultSkinConfiguration { - public const decimal LATEST_VERSION = 2.5m; + public const decimal LATEST_VERSION = 2.7m; /// /// Legacy version of this skin. From 502dcc566978b9bc2420d102e76ecbf51260b875 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 20:23:22 +0300 Subject: [PATCH 3849/5608] Fix incorrect skin version case --- osu.Game/Skinning/LegacySkinDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index ea087353a0..7dcb7ea3ac 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -34,7 +34,7 @@ namespace osu.Game.Skinning return; case @"Version": - if (pair.Value == "latest" || pair.Value == "User") + if (pair.Value == "latest") skin.LegacyVersion = LegacySkinConfiguration.LATEST_VERSION; else if (decimal.TryParse(pair.Value, out var version)) skin.LegacyVersion = version; From 947602f70afcc6b58d473f0f36ceb28bddfe41b7 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 20:24:19 +0300 Subject: [PATCH 3850/5608] Specify why legacy version is nullable --- osu.Game/Skinning/LegacySkinConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs index f9bf78b8ad..33c29cd47c 100644 --- a/osu.Game/Skinning/LegacySkinConfiguration.cs +++ b/osu.Game/Skinning/LegacySkinConfiguration.cs @@ -8,7 +8,7 @@ namespace osu.Game.Skinning public const decimal LATEST_VERSION = 2.7m; /// - /// Legacy version of this skin. + /// Legacy version of this skin. Null if no version was set to allow fallback to a parent skin version. /// public decimal? LegacyVersion { get; internal set; } } From ba14345107fc46fc1e00656d58a96e89a69d2abd Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 20:27:55 +0300 Subject: [PATCH 3851/5608] Specify culture and number style --- osu.Game/Skinning/LegacySkinDecoder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 7dcb7ea3ac..88ba7b23b7 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.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.Globalization; using osu.Game.Beatmaps.Formats; namespace osu.Game.Skinning @@ -36,7 +37,7 @@ namespace osu.Game.Skinning case @"Version": if (pair.Value == "latest") skin.LegacyVersion = LegacySkinConfiguration.LATEST_VERSION; - else if (decimal.TryParse(pair.Value, out var version)) + else if (decimal.TryParse(pair.Value, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var version)) skin.LegacyVersion = version; return; From 69d9a0ae1a0813db3f722df54abdf1fdb53c819d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 20:30:26 +0300 Subject: [PATCH 3852/5608] Use null check and pattern matching --- osu.Game/Skinning/LegacySkin.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index f6a366b21d..c76a61084d 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -77,8 +77,8 @@ namespace osu.Game.Skinning switch (legacy) { case LegacySkinConfigurations.Version: - if (Configuration.LegacyVersion.HasValue) - return SkinUtils.As(new Bindable(Configuration.LegacyVersion.Value)); + if (Configuration.LegacyVersion != null) + return SkinUtils.As(new Bindable((decimal)Configuration.LegacyVersion)); break; } From 198a1750c3db0e2b6a2467478333a08d8a65e6db Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 20:46:02 +0300 Subject: [PATCH 3853/5608] Use `is` pattern matching --- osu.Game/Skinning/LegacySkin.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index c76a61084d..1730effc29 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -77,8 +77,8 @@ namespace osu.Game.Skinning switch (legacy) { case LegacySkinConfigurations.Version: - if (Configuration.LegacyVersion != null) - return SkinUtils.As(new Bindable((decimal)Configuration.LegacyVersion)); + if (Configuration.LegacyVersion is decimal version) + return SkinUtils.As(new Bindable(version)); break; } From cef6e2a26b49cdecd9663aa4af586292c8e8b4e6 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 23:20:36 +0300 Subject: [PATCH 3854/5608] Move colours fallback logic to SkinConfiguration.ComboColours getter --- osu.Game/Skinning/DefaultSkinConfiguration.cs | 10 +------ osu.Game/Skinning/LegacySkin.cs | 9 ++++--- osu.Game/Skinning/SkinConfiguration.cs | 27 ++++++++++++++++++- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/osu.Game/Skinning/DefaultSkinConfiguration.cs b/osu.Game/Skinning/DefaultSkinConfiguration.cs index cd5975edac..8e89ab25b2 100644 --- a/osu.Game/Skinning/DefaultSkinConfiguration.cs +++ b/osu.Game/Skinning/DefaultSkinConfiguration.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK.Graphics; - namespace osu.Game.Skinning { /// @@ -12,13 +10,7 @@ namespace osu.Game.Skinning { public DefaultSkinConfiguration() { - ComboColours.AddRange(new[] - { - new Color4(255, 192, 0, 255), - new Color4(0, 202, 0, 255), - new Color4(18, 124, 255, 255), - new Color4(242, 24, 57, 255), - }); + ComboColours = DefaultComboColours; } } } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index bc12c00cd8..ff1e501a06 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -46,6 +46,8 @@ namespace osu.Game.Skinning else Configuration = new SkinConfiguration(); + Configuration.AllowDefaultColoursFallback = AllowDefaultColoursFallback; + if (storage != null) { Samples = audioManager?.GetSampleStore(storage); @@ -68,10 +70,9 @@ namespace osu.Game.Skinning switch (global) { case GlobalSkinConfiguration.ComboColours: - if (Configuration.ComboColours.Any()) - return SkinUtils.As(new Bindable>(Configuration.ComboColours)); - else if (AllowDefaultColoursFallback) - return SkinUtils.As(new Bindable>(new DefaultSkinConfiguration().ComboColours)); + var comboColours = Configuration.ComboColours; + if (comboColours != null) + return SkinUtils.As(new Bindable>(comboColours)); break; } diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index 54aac86e3c..57b969be33 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -14,7 +14,32 @@ namespace osu.Game.Skinning { public readonly SkinInfo SkinInfo = new SkinInfo(); - public List ComboColours { get; set; } = new List(); + internal bool AllowDefaultColoursFallback; + + public static List DefaultComboColours = new List + { + new Color4(255, 192, 0, 255), + new Color4(0, 202, 0, 255), + new Color4(18, 124, 255, 255), + new Color4(242, 24, 57, 255), + }; + + private List comboColours = new List(); + + public List ComboColours + { + get + { + if (comboColours.Count > 0) + return comboColours; + + if (AllowDefaultColoursFallback) + return DefaultComboColours; + + return null; + } + set => comboColours = value; + } public Dictionary CustomColours { get; set; } = new Dictionary(); From 61778232d8b76436458a87cd60a18d2443159d6d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 23:24:54 +0300 Subject: [PATCH 3855/5608] Rewrite inline comment --- osu.Game/Skinning/LegacyBeatmapSkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacyBeatmapSkin.cs b/osu.Game/Skinning/LegacyBeatmapSkin.cs index c9dec8a55e..4e020083a7 100644 --- a/osu.Game/Skinning/LegacyBeatmapSkin.cs +++ b/osu.Game/Skinning/LegacyBeatmapSkin.cs @@ -9,7 +9,7 @@ namespace osu.Game.Skinning { public class LegacyBeatmapSkin : LegacySkin { - // Null should be returned in the case of no colours provided to fallback into current skin's colours. + // Disallow default colours fallback on beatmap skins to allow using parent skin combo colours. (via SkinProvidingContainer) protected override bool AllowDefaultColoursFallback => false; public LegacyBeatmapSkin(BeatmapInfo beatmap, IResourceStore storage, AudioManager audioManager) From 963215ccbe99fe7170ffe19673937f5013e756b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 6 Nov 2019 22:43:13 +0100 Subject: [PATCH 3856/5608] Wait for track reset in tests Add a wait step in tests for the "now playing" overlay to make sure the current track was restarted before trying to call PreviousTrack() again. --- .../Visual/UserInterface/TestSceneNowPlayingOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index 4626b9d70f..330ccecd54 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -4,6 +4,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Overlays; using osu.Game.Rulesets.Osu; @@ -55,6 +56,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep(@"Seek track to 6 second", () => musicController.SeekTo(6000)); AddUntilStep(@"Wait for current time to update", () => currentBeatmap.Track.CurrentTime > 5000); AddAssert(@"Check action is restart track", () => musicController.PreviousTrack() == PreviousTrackResult.Restart); + AddUntilStep("Wait for current time to update", () => Precision.AlmostEquals(currentBeatmap.Track.CurrentTime, 0)); AddAssert(@"Check track didn't change", () => currentBeatmap == Beatmap.Value); AddAssert(@"Check action is not restart", () => musicController.PreviousTrack() != PreviousTrackResult.Restart); } From d400e4a5f6a576b83a355bd34ef405d774382811 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 7 Nov 2019 09:30:50 +0900 Subject: [PATCH 3857/5608] Add shared constant for parallax amount --- osu.Game/Graphics/Containers/ParallaxContainer.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index a5ebac5b1f..86f922e4b8 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -69,9 +69,11 @@ namespace osu.Game.Graphics.Containers { Vector2 offset = (input.CurrentState.Mouse == null ? Vector2.Zero : ToLocalSpace(input.CurrentState.Mouse.Position) - DrawSize / 2) * ParallaxAmount; - double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000); + const float parallax_duration = 100; - content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, 100, Easing.OutQuint); + double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); + + content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, parallax_duration, Easing.OutQuint); content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); } From 8141509a71cd88cd02eb12f7c84f1832e2cb3a95 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 12:59:05 +0900 Subject: [PATCH 3858/5608] Split hold note blueprints into separate file --- .../HoldNoteNoteSelectionBlueprint.cs | 29 +++++++++++++++++++ .../Blueprints/HoldNoteSelectionBlueprint.cs | 22 -------------- 2 files changed, 29 insertions(+), 22 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs new file mode 100644 index 0000000000..3bbfcae10c --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs @@ -0,0 +1,29 @@ +// 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.Rulesets.Mania.Objects.Drawables; + +namespace osu.Game.Rulesets.Mania.Edit.Blueprints +{ + public class HoldNoteNoteSelectionBlueprint : NoteSelectionBlueprint + { + public HoldNoteNoteSelectionBlueprint(DrawableNote note) + : base(note) + { + Select(); + } + + protected override void Update() + { + base.Update(); + + Anchor = DrawableObject.Anchor; + Origin = DrawableObject.Origin; + + Position = DrawableObject.DrawPosition; + } + + // Todo: This is temporary, since the note masks don't do anything special yet. In the future they will handle input. + public override bool HandlePositionalInput => false; + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs index 3a9eb1f043..a0a3a9d0f7 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs @@ -64,27 +64,5 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints } public override Quad SelectionQuad => ScreenSpaceDrawQuad; - - private class HoldNoteNoteSelectionBlueprint : NoteSelectionBlueprint - { - public HoldNoteNoteSelectionBlueprint(DrawableNote note) - : base(note) - { - Select(); - } - - protected override void Update() - { - base.Update(); - - Anchor = DrawableObject.Anchor; - Origin = DrawableObject.Origin; - - Position = DrawableObject.DrawPosition; - } - - // Todo: This is temporary, since the note masks don't do anything special yet. In the future they will handle input. - public override bool HandlePositionalInput => false; - } } } From 8d42e45fd3aa9b6d6dec99d1373d340096f8982e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 13:23:00 +0900 Subject: [PATCH 3859/5608] Make holdnote notes update lazily --- .../HoldNoteNoteSelectionBlueprint.cs | 24 ++++++++++++++----- .../Edit/Blueprints/HoldNotePosition.cs | 11 +++++++++ .../Blueprints/HoldNoteSelectionBlueprint.cs | 4 ++-- 3 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePosition.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs index 3bbfcae10c..5aaf4c09fd 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs @@ -1,15 +1,24 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; +using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; using osu.Game.Rulesets.Mania.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { - public class HoldNoteNoteSelectionBlueprint : NoteSelectionBlueprint + public class HoldNoteNoteSelectionBlueprint : ManiaSelectionBlueprint { - public HoldNoteNoteSelectionBlueprint(DrawableNote note) - : base(note) + protected new DrawableHoldNote DrawableObject => (DrawableHoldNote)base.DrawableObject; + + private readonly HoldNotePosition position; + + public HoldNoteNoteSelectionBlueprint(DrawableHoldNote holdNote, HoldNotePosition position) + : base(holdNote) { + this.position = position; + InternalChild = new EditNotePiece { RelativeSizeAxes = Axes.X }; + Select(); } @@ -17,10 +26,13 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); - Anchor = DrawableObject.Anchor; - Origin = DrawableObject.Origin; + DrawableNote note = position == HoldNotePosition.Start ? DrawableObject.Head : DrawableObject.Tail; - Position = DrawableObject.DrawPosition; + Anchor = note.Anchor; + Origin = note.Origin; + + Size = note.DrawSize; + Position = note.DrawPosition; } // Todo: This is temporary, since the note masks don't do anything special yet. In the future they will handle input. diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePosition.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePosition.cs new file mode 100644 index 0000000000..219dad566d --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePosition.cs @@ -0,0 +1,11 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Mania.Edit.Blueprints +{ + public enum HoldNotePosition + { + Start, + End + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs index a0a3a9d0f7..244cfa0b69 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs @@ -40,8 +40,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints InternalChildren = new Drawable[] { - new HoldNoteNoteSelectionBlueprint(DrawableObject.Head), - new HoldNoteNoteSelectionBlueprint(DrawableObject.Tail), + new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.Start), + new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.End), new BodyPiece { AccentColour = Color4.Transparent, From 1f9f03dc66aaff484ae279b78cc0c3562c9e4348 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 13:31:06 +0900 Subject: [PATCH 3860/5608] Add temporary fix for null references --- .../Blueprints/HoldNoteNoteSelectionBlueprint.cs | 14 +++++++++----- .../Blueprints/HoldNoteSelectionBlueprint.cs | 16 ++++++++++------ .../Edit/Blueprints/NoteSelectionBlueprint.cs | 4 +++- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs index 5aaf4c09fd..acce41db6f 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs @@ -26,13 +26,17 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); - DrawableNote note = position == HoldNotePosition.Start ? DrawableObject.Head : DrawableObject.Tail; + // Todo: This shouldn't exist, mania should not reference the drawable hitobject directly. + if (DrawableObject.IsLoaded) + { + DrawableNote note = position == HoldNotePosition.Start ? DrawableObject.Head : DrawableObject.Tail; - Anchor = note.Anchor; - Origin = note.Origin; + Anchor = note.Anchor; + Origin = note.Origin; - Size = note.DrawSize; - Position = note.DrawPosition; + Size = note.DrawSize; + Position = note.DrawPosition; + } } // Todo: This is temporary, since the note masks don't do anything special yet. In the future they will handle input. diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs index 244cfa0b69..56c0b671a0 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs @@ -54,13 +54,17 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); - Size = DrawableObject.DrawSize + new Vector2(0, DrawableObject.Tail.DrawHeight); + // Todo: This shouldn't exist, mania should not reference the drawable hitobject directly. + if (DrawableObject.IsLoaded) + { + Size = DrawableObject.DrawSize + new Vector2(0, DrawableObject.Tail.DrawHeight); - // This is a side-effect of not matching the hitobject's anchors/origins, which is kinda hard to do - // When scrolling upwards our origin is already at the top of the head note (which is the intended location), - // but when scrolling downwards our origin is at the _bottom_ of the tail note (where we need to be at the _top_ of the tail note) - if (direction.Value == ScrollingDirection.Down) - Y -= DrawableObject.Tail.DrawHeight; + // This is a side-effect of not matching the hitobject's anchors/origins, which is kinda hard to do + // When scrolling upwards our origin is already at the top of the head note (which is the intended location), + // but when scrolling downwards our origin is at the _bottom_ of the tail note (where we need to be at the _top_ of the tail note) + if (direction.Value == ScrollingDirection.Down) + Y -= DrawableObject.Tail.DrawHeight; + } } public override Quad SelectionQuad => ScreenSpaceDrawQuad; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs index b83c4aa9aa..2bff33c4cf 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs @@ -19,7 +19,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); - Size = DrawableObject.DrawSize; + // Todo: This shouldn't exist, mania should not reference the drawable hitobject directly. + if (DrawableObject.IsLoaded) + Size = DrawableObject.DrawSize; } } } From b1da81571f77132b4267c92b217d5c7ca5c4916e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 14:00:12 +0900 Subject: [PATCH 3861/5608] Implement slider head control point snapping --- .../Sliders/Components/PathControlPointPiece.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 0353ba241c..155e814596 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Lines; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Objects; using osuTK; using osuTK.Graphics; @@ -29,6 +30,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private readonly Container marker; private readonly Drawable markerRing; + [Resolved(CanBeNull = true)] + private IDistanceSnapProvider snapProvider { get; set; } + [Resolved] private OsuColour colours { get; set; } @@ -146,12 +150,16 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components if (Index == 0) { - // Special handling for the head - only the position of the slider changes - slider.Position += e.Delta; + // Special handling for the head control point - the position of the slider changes which means the snapped position and time have to be taken into account + (Vector2 snappedPosition, double snappedTime) = snapProvider?.GetSnappedPosition(e.MousePosition, slider.StartTime) ?? (e.MousePosition, slider.StartTime); + Vector2 movementDelta = snappedPosition - slider.Position; + + slider.Position += movementDelta; + slider.StartTime = snappedTime; // Since control points are relative to the position of the slider, they all need to be offset backwards by the delta for (int i = 1; i < newControlPoints.Length; i++) - newControlPoints[i] -= e.Delta; + newControlPoints[i] -= movementDelta; } else newControlPoints[Index] += e.Delta; From f3ddc4c00b60c3e08b68de08f6409ea967df58ca Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 14:08:02 +0900 Subject: [PATCH 3862/5608] Advance editor clock after a snapped placement --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 1c942e52ce..805fc2b46f 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -40,6 +40,9 @@ namespace osu.Game.Rulesets.Edit [Resolved] protected IFrameBasedClock EditorClock { get; private set; } + [Resolved] + private IAdjustableClock adjustableClock { get; set; } + [Resolved] private BindableBeatDivisor beatDivisor { get; set; } @@ -256,6 +259,9 @@ namespace osu.Game.Rulesets.Edit public void EndPlacement(HitObject hitObject) { EditorBeatmap.Add(hitObject); + + adjustableClock.Seek(hitObject.StartTime); + showGridFor(Enumerable.Empty()); } From f2084df0bb25c9336237f47de7c6d6e4434cb18d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 7 Nov 2019 06:19:49 +0000 Subject: [PATCH 3863/5608] Bump Microsoft.NET.Test.Sdk from 16.3.0 to 16.4.0 Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 16.3.0 to 16.4.0. - [Release notes](https://github.com/microsoft/vstest/releases) - [Commits](https://github.com/microsoft/vstest/compare/v16.3...v16.4.0) Signed-off-by: dependabot-preview[bot] --- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 4b629902cb..1dbe9b39ee 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index 30511d672d..8fc4dbfe72 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 3aea9e0387..fddf176fd0 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 717e795112..b5bd384e05 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index aa29fc802c..c5998c9cfc 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -3,7 +3,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 371ffcdf9e..d58a724c27 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -5,7 +5,7 @@ - + From 20d6eceecff465a37d8c6f9a602ec3fe48ad40bb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 16:03:35 +0900 Subject: [PATCH 3864/5608] Move DrawableOsuMenuItem out of OsuMenu --- .../UserInterface/DrawableOsuMenuItem.cs | 133 ++++++++++++++++++ osu.Game/Graphics/UserInterface/OsuMenu.cs | 123 ---------------- 2 files changed, 133 insertions(+), 123 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs diff --git a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs new file mode 100644 index 0000000000..efa0b3d69c --- /dev/null +++ b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs @@ -0,0 +1,133 @@ +// 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.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Sprites; +using osuTK.Graphics; + +namespace osu.Game.Graphics.UserInterface +{ + public class DrawableOsuMenuItem : Menu.DrawableMenuItem + { + private const int margin_horizontal = 17; + private const int text_size = 17; + private const int transition_length = 80; + public const int MARGIN_VERTICAL = 4; + + private SampleChannel sampleClick; + private SampleChannel sampleHover; + + private TextContainer text; + + public DrawableOsuMenuItem(MenuItem item) + : base(item) + { + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleHover = audio.Samples.Get(@"UI/generic-hover"); + sampleClick = audio.Samples.Get(@"UI/generic-select"); + + BackgroundColour = Color4.Transparent; + BackgroundColourHover = OsuColour.FromHex(@"172023"); + + updateTextColour(); + } + + private void updateTextColour() + { + switch ((Item as OsuMenuItem)?.Type) + { + default: + case MenuItemType.Standard: + text.Colour = Color4.White; + break; + + case MenuItemType.Destructive: + text.Colour = Color4.Red; + break; + + case MenuItemType.Highlighted: + text.Colour = OsuColour.FromHex(@"ffcc22"); + break; + } + } + + protected override bool OnHover(HoverEvent e) + { + sampleHover.Play(); + text.BoldText.FadeIn(transition_length, Easing.OutQuint); + text.NormalText.FadeOut(transition_length, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + text.BoldText.FadeOut(transition_length, Easing.OutQuint); + text.NormalText.FadeIn(transition_length, Easing.OutQuint); + base.OnHoverLost(e); + } + + protected override bool OnClick(ClickEvent e) + { + sampleClick.Play(); + return base.OnClick(e); + } + + protected sealed override Drawable CreateContent() => text = CreateTextContainer(); + protected virtual TextContainer CreateTextContainer() => new TextContainer(); + + protected class TextContainer : Container, IHasText + { + public string Text + { + get => NormalText.Text; + set + { + NormalText.Text = value; + BoldText.Text = value; + } + } + + public readonly SpriteText NormalText; + public readonly SpriteText BoldText; + + public TextContainer() + { + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + + AutoSizeAxes = Axes.Both; + + Children = new Drawable[] + { + NormalText = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: text_size), + Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, + }, + BoldText = new OsuSpriteText + { + AlwaysPresent = true, + Alpha = 0, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), + Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, + } + }; + } + } + } +} diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index c4c6950eb1..be642e6afb 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -1,18 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; using osuTK; namespace osu.Game.Graphics.UserInterface @@ -53,122 +47,5 @@ namespace osu.Game.Graphics.UserInterface { Anchor = Direction == Direction.Horizontal ? Anchor.BottomLeft : Anchor.TopRight }; - - protected class DrawableOsuMenuItem : DrawableMenuItem - { - private const int margin_horizontal = 17; - private const int text_size = 17; - private const int transition_length = 80; - public const int MARGIN_VERTICAL = 4; - - private SampleChannel sampleClick; - private SampleChannel sampleHover; - - private TextContainer text; - - public DrawableOsuMenuItem(MenuItem item) - : base(item) - { - } - - [BackgroundDependencyLoader] - private void load(AudioManager audio) - { - sampleHover = audio.Samples.Get(@"UI/generic-hover"); - sampleClick = audio.Samples.Get(@"UI/generic-select"); - - BackgroundColour = Color4.Transparent; - BackgroundColourHover = OsuColour.FromHex(@"172023"); - - updateTextColour(); - } - - private void updateTextColour() - { - switch ((Item as OsuMenuItem)?.Type) - { - default: - case MenuItemType.Standard: - text.Colour = Color4.White; - break; - - case MenuItemType.Destructive: - text.Colour = Color4.Red; - break; - - case MenuItemType.Highlighted: - text.Colour = OsuColour.FromHex(@"ffcc22"); - break; - } - } - - protected override bool OnHover(HoverEvent e) - { - sampleHover.Play(); - text.BoldText.FadeIn(transition_length, Easing.OutQuint); - text.NormalText.FadeOut(transition_length, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - text.BoldText.FadeOut(transition_length, Easing.OutQuint); - text.NormalText.FadeIn(transition_length, Easing.OutQuint); - base.OnHoverLost(e); - } - - protected override bool OnClick(ClickEvent e) - { - sampleClick.Play(); - return base.OnClick(e); - } - - protected sealed override Drawable CreateContent() => text = CreateTextContainer(); - protected virtual TextContainer CreateTextContainer() => new TextContainer(); - - protected class TextContainer : Container, IHasText - { - public string Text - { - get => NormalText.Text; - set - { - NormalText.Text = value; - BoldText.Text = value; - } - } - - public readonly SpriteText NormalText; - public readonly SpriteText BoldText; - - public TextContainer() - { - Anchor = Anchor.CentreLeft; - Origin = Anchor.CentreLeft; - - AutoSizeAxes = Axes.Both; - - Children = new Drawable[] - { - NormalText = new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: text_size), - Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, - }, - BoldText = new OsuSpriteText - { - AlwaysPresent = true, - Alpha = 0, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), - Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, - } - }; - } - } - } } } From 29672c48e126bb39829426f4174be8207e0f0bc6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 16:04:13 +0900 Subject: [PATCH 3865/5608] Make simple OsuMenuItem ctor invoke the complex one --- osu.Game/Graphics/UserInterface/OsuMenuItem.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs index b7aa666302..0fe41937ce 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs @@ -11,9 +11,8 @@ namespace osu.Game.Graphics.UserInterface public readonly MenuItemType Type; public OsuMenuItem(string text, MenuItemType type = MenuItemType.Standard) - : base(text) + : this(text, type, null) { - Type = type; } public OsuMenuItem(string text, MenuItemType type, Action action) From cea5bb396358c675b9d80327cb849d4c47b6aca2 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 7 Nov 2019 15:50:26 +0300 Subject: [PATCH 3866/5608] Return skin-empty.ini back --- osu.Game.Tests/Resources/skin-empty.ini | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 osu.Game.Tests/Resources/skin-empty.ini diff --git a/osu.Game.Tests/Resources/skin-empty.ini b/osu.Game.Tests/Resources/skin-empty.ini new file mode 100644 index 0000000000..b6c319fe3c --- /dev/null +++ b/osu.Game.Tests/Resources/skin-empty.ini @@ -0,0 +1,2 @@ +[General] +Name: test skin \ No newline at end of file From 41515e9e6cd87857af9a7b1ccbb71195f3691d86 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 7 Nov 2019 15:51:03 +0300 Subject: [PATCH 3867/5608] Update current tests to match the expected behaviour --- osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 76ce2331f5..202161a1b8 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -13,23 +13,38 @@ namespace osu.Game.Tests.Skins [TestFixture] public class LegacySkinDecoderTest { - [Test] - public void TestDecodeSkinColours() + [TestCase(true)] + [TestCase(false)] + [TestCase(false, false)] + public void TestDecodeSkinColours(bool hasColours, bool canFallback = true) { var decoder = new LegacySkinDecoder(); - using (var resStream = TestResources.OpenResource("skin.ini")) + using (var resStream = TestResources.OpenResource(hasColours ? "skin.ini" : "skin-empty.ini")) using (var stream = new LineBufferedReader(resStream)) { - var comboColors = decoder.Decode(stream).ComboColours; + var skinConfiguration = decoder.Decode(stream); + skinConfiguration.AllowDefaultComboColoursFallback = canFallback; - List expectedColors = new List + var comboColors = skinConfiguration.ComboColours; + + if (!canFallback && !hasColours) + { + Assert.IsNull(comboColors); + return; + } + + List expectedColors; + if (hasColours) + expectedColors = new List { new Color4(142, 199, 255, 255), new Color4(255, 128, 128, 255), new Color4(128, 255, 255, 255), new Color4(100, 100, 100, 100), }; + else + expectedColors = SkinConfiguration.DefaultComboColours; Assert.AreEqual(expectedColors.Count, comboColors.Count); for (int i = 0; i < expectedColors.Count; i++) From 808543885f34f26b995a6446d6b7a910fe1b0ea8 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 7 Nov 2019 15:54:30 +0300 Subject: [PATCH 3868/5608] Change ComboColours type to IReadOnlyList Also exposes functions to modify the internal list (AddComboColours, ClearComboColours) --- .../Skins/TestSceneSkinConfigurationLookup.cs | 17 +++++++---------- osu.Game/Beatmaps/Formats/IHasComboColours.cs | 15 ++++++++++++++- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- .../Objects/Drawables/DrawableHitObject.cs | 2 +- osu.Game/Skinning/DefaultLegacySkin.cs | 7 +++---- osu.Game/Skinning/DefaultSkin.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 2 +- osu.Game/Skinning/SkinConfiguration.cs | 10 ++++++++-- 8 files changed, 36 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index 2ea66d8e41..c945568753 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -95,7 +95,7 @@ namespace osu.Game.Tests.Skins [Test] public void TestGlobalLookup() { - AddAssert("Check combo colours", () => requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.Count > 0); + AddAssert("Check combo colours", () => requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.Count > 0); } [Test] @@ -121,19 +121,19 @@ namespace osu.Game.Tests.Skins [TestCase(true)] public void TestEmptyComboColours(bool allowFallback) { - AddStep("Add custom combo colours to fallback source", () => source1.Configuration.ComboColours = new List + AddStep("Add custom combo colours to source1", () => source1.Configuration.ComboColours = new List { new Color4(100, 150, 200, 255), new Color4(55, 110, 166, 255), new Color4(75, 125, 175, 255), }); - AddStep("Clear combo colours from source", () => source2.Configuration.ComboColours.Clear()); - AddStep("Disable default fallback in source", () => source2.AllowColoursFallback = allowFallback); + AddStep("Clear combo colours from source2", () => source2.Configuration.ClearComboColours()); + AddStep("Disallow default colours fallback in source2", () => source2.Configuration.AllowDefaultComboColoursFallback = allowFallback); - AddAssert($"Check retrieved combo colours from {(allowFallback ? "default skin" : "fallback source")}", () => + AddAssert($"Check retrieved combo colours from {(allowFallback ? "source1" : "fallback source")}", () => { - var expectedColours = allowFallback ? new DefaultSkinConfiguration().ComboColours : source1.Configuration.ComboColours; - return requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.SequenceEqual(expectedColours) ?? false; + var expectedColours = allowFallback ? SkinConfiguration.DefaultComboColours : source1.Configuration.ComboColours; + return requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.SequenceEqual(expectedColours) ?? false; }); } @@ -151,9 +151,6 @@ namespace osu.Game.Tests.Skins public class SkinSource : LegacySkin { - public bool AllowColoursFallback = true; - protected override bool AllowDefaultColoursFallback => AllowColoursFallback; - public SkinSource() : base(new SkinInfo(), null, null, string.Empty) { diff --git a/osu.Game/Beatmaps/Formats/IHasComboColours.cs b/osu.Game/Beatmaps/Formats/IHasComboColours.cs index 4c15cb96d1..5ef31c1904 100644 --- a/osu.Game/Beatmaps/Formats/IHasComboColours.cs +++ b/osu.Game/Beatmaps/Formats/IHasComboColours.cs @@ -8,6 +8,19 @@ namespace osu.Game.Beatmaps.Formats { public interface IHasComboColours { - List ComboColours { get; set; } + /// + /// Retrieves the list of combo colours for presentation only. + /// + IReadOnlyList ComboColours { get; set; } + + /// + /// Adds combo colours to the list. + /// + void AddComboColours(params Color4[] colours); + + /// + /// Clear current combo colours from the list. + /// + void ClearComboColours(); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 4899a53cf1..ddaa04b657 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -103,7 +103,7 @@ namespace osu.Game.Beatmaps.Formats { if (!(output is IHasComboColours tHasComboColours)) return; - tHasComboColours.ComboColours.Add(colour); + tHasComboColours.AddComboColours(colour); } else { diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index f8bc74b2a6..09ff7bfded 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -265,7 +265,7 @@ namespace osu.Game.Rulesets.Objects.Drawables { if (HitObject is IHasComboInformation combo) { - var comboColours = CurrentSkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value; + var comboColours = CurrentSkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value; AccentColour.Value = comboColours?.Count > 0 ? comboColours[combo.ComboIndex % comboColours.Count] : Color4.White; } } diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index 4b6eea6b6e..6eda0dfb34 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -13,13 +13,12 @@ namespace osu.Game.Skinning : base(Info, storage, audioManager, string.Empty) { Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); - Configuration.ComboColours.AddRange(new[] - { + Configuration.AddComboColours( new Color4(255, 192, 0, 255), new Color4(0, 202, 0, 255), new Color4(18, 124, 255, 255), - new Color4(242, 24, 57, 255), - }); + new Color4(242, 24, 57, 255) + ); } public static SkinInfo Info { get; } = new SkinInfo diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs index 529c1afca5..2a065ea3d7 100644 --- a/osu.Game/Skinning/DefaultSkin.cs +++ b/osu.Game/Skinning/DefaultSkin.cs @@ -35,7 +35,7 @@ namespace osu.Game.Skinning switch (global) { case GlobalSkinConfiguration.ComboColours: - return SkinUtils.As(new Bindable>(Configuration.ComboColours)); + return SkinUtils.As(new Bindable>(Configuration.ComboColours)); } break; diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index ff1e501a06..94c2c8668f 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -72,7 +72,7 @@ namespace osu.Game.Skinning case GlobalSkinConfiguration.ComboColours: var comboColours = Configuration.ComboColours; if (comboColours != null) - return SkinUtils.As(new Bindable>(comboColours)); + return SkinUtils.As(new Bindable>(comboColours)); break; } diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index 57b969be33..1fd781a5b3 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Beatmaps.Formats; using osuTK.Graphics; @@ -26,7 +28,7 @@ namespace osu.Game.Skinning private List comboColours = new List(); - public List ComboColours + public IReadOnlyList ComboColours { get { @@ -38,9 +40,13 @@ namespace osu.Game.Skinning return null; } - set => comboColours = value; + set => comboColours = value.ToList(); } + public void AddComboColours(params Color4[] colours) => colours.ForEach(c => comboColours.Add(c)); + + public void ClearComboColours() => comboColours.Clear(); + public Dictionary CustomColours { get; set; } = new Dictionary(); public readonly Dictionary ConfigDictionary = new Dictionary(); From 9874ce49ce6f81165862961ee6244b2267629c9a Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 7 Nov 2019 15:55:34 +0300 Subject: [PATCH 3869/5608] Move fallback allowance to the skin configuration only. --- osu.Game/Skinning/LegacyBeatmapSkin.cs | 5 ++--- osu.Game/Skinning/LegacySkin.cs | 7 ------- osu.Game/Skinning/SkinConfiguration.cs | 7 +++++-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/osu.Game/Skinning/LegacyBeatmapSkin.cs b/osu.Game/Skinning/LegacyBeatmapSkin.cs index 4e020083a7..fa7e895a28 100644 --- a/osu.Game/Skinning/LegacyBeatmapSkin.cs +++ b/osu.Game/Skinning/LegacyBeatmapSkin.cs @@ -9,12 +9,11 @@ namespace osu.Game.Skinning { public class LegacyBeatmapSkin : LegacySkin { - // Disallow default colours fallback on beatmap skins to allow using parent skin combo colours. (via SkinProvidingContainer) - protected override bool AllowDefaultColoursFallback => false; - public LegacyBeatmapSkin(BeatmapInfo beatmap, IResourceStore storage, AudioManager audioManager) : base(createSkinInfo(beatmap), new LegacySkinResourceStore(beatmap.BeatmapSet, storage), audioManager, beatmap.Path) { + // Disallow default colours fallback on beatmap skins to allow using parent skin combo colours. (via SkinProvidingContainer) + Configuration.AllowDefaultComboColoursFallback = false; } private static SkinInfo createSkinInfo(BeatmapInfo beatmap) => diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 94c2c8668f..359acc3a8f 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -26,11 +26,6 @@ namespace osu.Game.Skinning [CanBeNull] protected IResourceStore Samples; - /// - /// Whether to allow default combo colours as fallback if none provided in this skin. - /// - protected virtual bool AllowDefaultColoursFallback => true; - public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini") { @@ -46,8 +41,6 @@ namespace osu.Game.Skinning else Configuration = new SkinConfiguration(); - Configuration.AllowDefaultColoursFallback = AllowDefaultColoursFallback; - if (storage != null) { Samples = audioManager?.GetSampleStore(storage); diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index 1fd781a5b3..da833acd98 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -16,7 +16,10 @@ namespace osu.Game.Skinning { public readonly SkinInfo SkinInfo = new SkinInfo(); - internal bool AllowDefaultColoursFallback; + /// + /// Whether to allow as a fallback list for when no combo colours are provided. + /// + internal bool AllowDefaultComboColoursFallback = true; public static List DefaultComboColours = new List { @@ -35,7 +38,7 @@ namespace osu.Game.Skinning if (comboColours.Count > 0) return comboColours; - if (AllowDefaultColoursFallback) + if (AllowDefaultComboColoursFallback) return DefaultComboColours; return null; From 164cb66f6aaa001204b2b2c9054d5e6c3fa47bf5 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 7 Nov 2019 16:13:10 +0300 Subject: [PATCH 3870/5608] Fix indention --- osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 202161a1b8..e2f556dcc3 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -35,7 +35,9 @@ namespace osu.Game.Tests.Skins } List expectedColors; + if (hasColours) + { expectedColors = new List { new Color4(142, 199, 255, 255), @@ -43,8 +45,11 @@ namespace osu.Game.Tests.Skins new Color4(128, 255, 255, 255), new Color4(100, 100, 100, 100), }; + } else + { expectedColors = SkinConfiguration.DefaultComboColours; + } Assert.AreEqual(expectedColors.Count, comboColors.Count); for (int i = 0; i < expectedColors.Count; i++) From c3a3b4091bfd92841521822191b1caea5f6730fb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 22:26:35 +0900 Subject: [PATCH 3871/5608] Add basic implementation of a toggleable menu item --- .../UserInterface/TestSceneToggleMenuItem.cs | 33 ++++++++++ .../UserInterface/DrawableOsuMenuItem.cs | 8 +-- .../UserInterface/DrawableToggleMenuItem.cs | 60 +++++++++++++++++++ osu.Game/Graphics/UserInterface/OsuMenu.cs | 11 +++- .../Graphics/UserInterface/ToggleMenuItem.cs | 25 ++++++++ 5 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs create mode 100644 osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs create mode 100644 osu.Game/Graphics/UserInterface/ToggleMenuItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs new file mode 100644 index 0000000000..97257b5226 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs @@ -0,0 +1,33 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneToggleMenuItem : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuMenu), + typeof(ToggleMenuItem), + typeof(DrawableToggleMenuItem) + }; + + public TestSceneToggleMenuItem() + { + Add(new OsuMenu(Direction.Vertical, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new ToggleMenuItem("Toggle"), + } + }); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs index efa0b3d69c..591ed3df83 100644 --- a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs @@ -16,10 +16,10 @@ namespace osu.Game.Graphics.UserInterface { public class DrawableOsuMenuItem : Menu.DrawableMenuItem { - private const int margin_horizontal = 17; + public const int MARGIN_HORIZONTAL = 17; + public const int MARGIN_VERTICAL = 4; private const int text_size = 17; private const int transition_length = 80; - public const int MARGIN_VERTICAL = 4; private SampleChannel sampleClick; private SampleChannel sampleHover; @@ -115,7 +115,7 @@ namespace osu.Game.Graphics.UserInterface Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(size: text_size), - Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, + Margin = new MarginPadding { Horizontal = MARGIN_HORIZONTAL, Vertical = MARGIN_VERTICAL }, }, BoldText = new OsuSpriteText { @@ -124,7 +124,7 @@ namespace osu.Game.Graphics.UserInterface Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), - Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, + Margin = new MarginPadding { Horizontal = MARGIN_HORIZONTAL, Vertical = MARGIN_VERTICAL }, } }; } diff --git a/osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs new file mode 100644 index 0000000000..cf0f154486 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs @@ -0,0 +1,60 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osuTK; + +namespace osu.Game.Graphics.UserInterface +{ + public class DrawableToggleMenuItem : DrawableOsuMenuItem + { + protected new ToggleMenuItem Item => (ToggleMenuItem)base.Item; + + public DrawableToggleMenuItem(ToggleMenuItem item) + : base(item) + { + } + + protected override TextContainer CreateTextContainer() => new ToggleTextContainer + { + State = { BindTarget = Item.State } + }; + + private class ToggleTextContainer : TextContainer + { + public readonly Bindable State = new Bindable(); + + private readonly SpriteIcon checkmark; + + public ToggleTextContainer() + { + Add(checkmark = new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.Solid.Check, + Size = new Vector2(10), + Margin = new MarginPadding { Horizontal = MARGIN_HORIZONTAL }, + AlwaysPresent = true, + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + State.BindValueChanged(state => checkmark.Alpha = state.NewValue ? 1 : 0, true); + } + + protected override void Update() + { + base.Update(); + + // Todo: This is bad. This can maybe be done better with a refactor of DrawableOsuMenuItem. + checkmark.X = BoldText.DrawWidth + 10; + } + } + } +} diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index be642e6afb..da32a2c861 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -39,7 +39,16 @@ namespace osu.Game.Graphics.UserInterface } } - protected override DrawableMenuItem CreateDrawableMenuItem(MenuItem item) => new DrawableOsuMenuItem(item); + protected override DrawableMenuItem CreateDrawableMenuItem(MenuItem item) + { + switch (item) + { + case ToggleMenuItem toggle: + return new DrawableToggleMenuItem(toggle); + } + + return new DrawableOsuMenuItem(item); + } protected override ScrollContainer CreateScrollContainer(Direction direction) => new OsuScrollContainer(direction); diff --git a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs new file mode 100644 index 0000000000..7b2bb32f47 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ToggleMenuItem.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 System; +using osu.Framework.Bindables; + +namespace osu.Game.Graphics.UserInterface +{ + public class ToggleMenuItem : OsuMenuItem + { + public readonly BindableBool State = new BindableBool(); + + public ToggleMenuItem(string text, MenuItemType type = MenuItemType.Standard) + : this(text, type, null) + { + } + + public ToggleMenuItem(string text, MenuItemType type, Action action) + : base(text, type) + { + Action.Value = () => State.Toggle(); + State.BindValueChanged(state => action?.Invoke(state.NewValue)); + } + } +} From 8ed7bc3f5366ec7b8a98b47439616280d6bc4f25 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 7 Nov 2019 18:42:17 +0300 Subject: [PATCH 3872/5608] Fix another indention --- osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index e2f556dcc3..003b3f5e56 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -39,12 +39,12 @@ namespace osu.Game.Tests.Skins if (hasColours) { expectedColors = new List - { - new Color4(142, 199, 255, 255), - new Color4(255, 128, 128, 255), - new Color4(128, 255, 255, 255), - new Color4(100, 100, 100, 100), - }; + { + new Color4(142, 199, 255, 255), + new Color4(255, 128, 128, 255), + new Color4(128, 255, 255, 255), + new Color4(100, 100, 100, 100), + }; } else { From 517f547590462f6fe26b6cdbe1b55814f5847141 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 7 Nov 2019 19:12:18 +0300 Subject: [PATCH 3873/5608] Fix failing test --- osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs index 6d7159a825..c6d1f9da29 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs @@ -130,7 +130,7 @@ namespace osu.Game.Tests.Gameplay switch (global) { case GlobalSkinConfiguration.ComboColours: - return SkinUtils.As(new Bindable>(ComboColours)); + return SkinUtils.As(new Bindable>(ComboColours)); } break; From 5235d2b3191948818b2e744083b3683a51ab9975 Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 7 Nov 2019 14:38:06 -0800 Subject: [PATCH 3874/5608] Fix home button not closing login and now playing overlays --- osu.Game/OsuGame.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 1f823e6eba..3980390611 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -601,14 +601,14 @@ namespace osu.Game loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true); - loadComponentSingleFile(new LoginOverlay + var login = loadComponentSingleFile(new LoginOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }, rightFloatingOverlayContent.Add, true); - loadComponentSingleFile(new NowPlayingOverlay + var nowPlaying = loadComponentSingleFile(new NowPlayingOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, @@ -671,6 +671,8 @@ namespace osu.Game }; } + overlays.AddRange(new OverlayContainer[] { login, nowPlaying }); + OverlayActivationMode.ValueChanged += mode => { if (mode.NewValue != OverlayActivation.All) CloseAllOverlays(); From 4fe69dbc896d77fd1efea4c469254fdbb3563fe0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 11:13:53 +0900 Subject: [PATCH 3875/5608] Fix context menu sub-menu display --- osu.Game/Graphics/UserInterface/OsuContextMenu.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs index cea8427296..4b629080e1 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterface { @@ -35,5 +36,7 @@ namespace osu.Game.Graphics.UserInterface protected override void AnimateOpen() => this.FadeIn(fade_duration, Easing.OutQuint); protected override void AnimateClose() => this.FadeOut(fade_duration, Easing.OutQuint); + + protected override Menu CreateSubMenu() => new OsuContextMenu(); } } From ce08d664a52fef8633accc8f11b53ecb7d758906 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 11:15:03 +0900 Subject: [PATCH 3876/5608] Abstract statefulness of new menu item type --- .../TestSceneStatefulMenuItem.cs | 90 +++++++++++++++++++ .../UserInterface/TestSceneToggleMenuItem.cs | 33 ------- ...enuItem.cs => DrawableStatefulMenuItem.cs} | 44 +++++---- osu.Game/Graphics/UserInterface/OsuMenu.cs | 4 +- .../UserInterface/StatefulMenuItem.cs | 56 ++++++++++++ .../Graphics/UserInterface/ToggleMenuItem.cs | 11 ++- 6 files changed, 181 insertions(+), 57 deletions(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs delete mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs rename osu.Game/Graphics/UserInterface/{DrawableToggleMenuItem.cs => DrawableStatefulMenuItem.cs} (51%) create mode 100644 osu.Game/Graphics/UserInterface/StatefulMenuItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs new file mode 100644 index 0000000000..fbb35ba09f --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -0,0 +1,90 @@ +// 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; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneStatefulMenuItem : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuMenu), + typeof(ToggleMenuItem), + typeof(DrawableStatefulMenuItem) + }; + + public TestSceneStatefulMenuItem() + { + Add(new OsuMenu(Direction.Vertical, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new TestMenuItem("First", MenuItemType.Standard, getNextState), + new TestMenuItem("Second", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State2 } }, + new TestMenuItem("Third", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State3 } }, + } + }); + } + + private TestStates getNextState(TestStates state) + { + switch (state) + { + case TestStates.State1: + return TestStates.State2; + + case TestStates.State2: + return TestStates.State3; + + case TestStates.State3: + return TestStates.State1; + } + + return TestStates.State1; + } + + private class TestMenuItem : StatefulMenuItem + { + public TestMenuItem(string text, MenuItemType type = MenuItemType.Standard) + : base(text, type) + { + } + + public TestMenuItem(string text, MenuItemType type, Func changeStateFunc) + : base(text, type, changeStateFunc) + { + } + + public override IconUsage? GetIconForState(TestStates state) + { + switch (state) + { + case TestStates.State1: + return FontAwesome.Solid.DiceOne; + + case TestStates.State2: + return FontAwesome.Solid.DiceTwo; + + case TestStates.State3: + return FontAwesome.Solid.DiceThree; + } + + return null; + } + } + + private enum TestStates + { + State1, + State2, + State3 + } + } +} diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs deleted file mode 100644 index 97257b5226..0000000000 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterface; - -namespace osu.Game.Tests.Visual.UserInterface -{ - public class TestSceneToggleMenuItem : OsuTestScene - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(OsuMenu), - typeof(ToggleMenuItem), - typeof(DrawableToggleMenuItem) - }; - - public TestSceneToggleMenuItem() - { - Add(new OsuMenu(Direction.Vertical, true) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Items = new[] - { - new ToggleMenuItem("Toggle"), - } - }); - } - } -} diff --git a/osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs similarity index 51% rename from osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs rename to osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs index cf0f154486..3dc99f2dbe 100644 --- a/osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs @@ -8,33 +8,33 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class DrawableToggleMenuItem : DrawableOsuMenuItem + public class DrawableStatefulMenuItem : DrawableOsuMenuItem { - protected new ToggleMenuItem Item => (ToggleMenuItem)base.Item; + protected new StatefulMenuItem Item => (StatefulMenuItem)base.Item; - public DrawableToggleMenuItem(ToggleMenuItem item) + public DrawableStatefulMenuItem(StatefulMenuItem item) : base(item) { } - protected override TextContainer CreateTextContainer() => new ToggleTextContainer - { - State = { BindTarget = Item.State } - }; + protected override TextContainer CreateTextContainer() => new ToggleTextContainer(Item); private class ToggleTextContainer : TextContainer { - public readonly Bindable State = new Bindable(); + private readonly StatefulMenuItem menuItem; + private readonly Bindable state; + private readonly SpriteIcon stateIcon; - private readonly SpriteIcon checkmark; - - public ToggleTextContainer() + public ToggleTextContainer(StatefulMenuItem menuItem) { - Add(checkmark = new SpriteIcon + this.menuItem = menuItem; + + state = menuItem.State.GetBoundCopy(); + + Add(stateIcon = new SpriteIcon { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Icon = FontAwesome.Solid.Check, Size = new Vector2(10), Margin = new MarginPadding { Horizontal = MARGIN_HORIZONTAL }, AlwaysPresent = true, @@ -44,8 +44,7 @@ namespace osu.Game.Graphics.UserInterface protected override void LoadComplete() { base.LoadComplete(); - - State.BindValueChanged(state => checkmark.Alpha = state.NewValue ? 1 : 0, true); + state.BindValueChanged(updateState, true); } protected override void Update() @@ -53,7 +52,20 @@ namespace osu.Game.Graphics.UserInterface base.Update(); // Todo: This is bad. This can maybe be done better with a refactor of DrawableOsuMenuItem. - checkmark.X = BoldText.DrawWidth + 10; + stateIcon.X = BoldText.DrawWidth + 10; + } + + private void updateState(ValueChangedEvent state) + { + var icon = menuItem.GetIconForState(state.NewValue); + + if (icon == null) + stateIcon.Alpha = 0; + else + { + stateIcon.Alpha = 1; + stateIcon.Icon = icon.Value; + } } } } diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index da32a2c861..e7bf4f66ee 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -43,8 +43,8 @@ namespace osu.Game.Graphics.UserInterface { switch (item) { - case ToggleMenuItem toggle: - return new DrawableToggleMenuItem(toggle); + case StatefulMenuItem stateful: + return new DrawableStatefulMenuItem(stateful); } return new DrawableOsuMenuItem(item); diff --git a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs new file mode 100644 index 0000000000..ede2c9df48 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/StatefulMenuItem.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 System; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Graphics.UserInterface +{ + public abstract class StatefulMenuItem : OsuMenuItem + { + public readonly Bindable State = new Bindable(); + + protected StatefulMenuItem(string text, MenuItemType type = MenuItemType.Standard) + : this(text, type, null) + { + } + + protected StatefulMenuItem(string text, MenuItemType type, Func changeStateFunc) + : base(text, type) + { + Action.Value = () => State.Value = changeStateFunc?.Invoke(State.Value) ?? State.Value; + } + + public abstract IconUsage? GetIconForState(object state); + } + + public abstract class StatefulMenuItem : StatefulMenuItem + where T : struct + { + public new readonly Bindable State = new Bindable(); + + protected StatefulMenuItem(string text, MenuItemType type = MenuItemType.Standard) + : this(text, type, null) + { + } + + protected StatefulMenuItem(string text, MenuItemType type, Func changeStateFunc) + : base(text, type, o => changeStateFunc?.Invoke((T)o) ?? o) + { + base.State.BindValueChanged(state => + { + if (state.NewValue == null) + base.State.Value = default(T); + + State.Value = (T)base.State.Value; + }, true); + + State.BindValueChanged(state => base.State.Value = state.NewValue); + } + + public sealed override IconUsage? GetIconForState(object state) => GetIconForState((T)state); + + public abstract IconUsage? GetIconForState(T state); + } +} diff --git a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs index 7b2bb32f47..a0ed745c5a 100644 --- a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs @@ -2,24 +2,23 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Bindables; +using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { - public class ToggleMenuItem : OsuMenuItem + public class ToggleMenuItem : StatefulMenuItem { - public readonly BindableBool State = new BindableBool(); - public ToggleMenuItem(string text, MenuItemType type = MenuItemType.Standard) : this(text, type, null) { } public ToggleMenuItem(string text, MenuItemType type, Action action) - : base(text, type) + : base(text, type, value => !value) { - Action.Value = () => State.Toggle(); State.BindValueChanged(state => action?.Invoke(state.NewValue)); } + + public override IconUsage? GetIconForState(bool state) => state ? (IconUsage?)FontAwesome.Solid.Check : null; } } From 30f877c4ab7751066bd6a0ca2dc45178de355b69 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 12:47:42 +0900 Subject: [PATCH 3877/5608] Implement a three-state menu item --- .../TestSceneThreeStateMenuItem.cs | 35 ++++++++++++ .../UserInterface/ThreeStateMenuItem.cs | 53 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs create mode 100644 osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs new file mode 100644 index 0000000000..caa07e7b60 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneThreeStateMenuItem : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuMenu), + typeof(ThreeStateMenuItem), + typeof(DrawableStatefulMenuItem) + }; + + public TestSceneThreeStateMenuItem() + { + Add(new OsuMenu(Direction.Vertical, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new ThreeStateMenuItem("First"), + new ThreeStateMenuItem("Second") { State = { Value = ThreeStates.Indeterminate } }, + new ThreeStateMenuItem("Third") { State = { Value = ThreeStates.Enabled } }, + } + }); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs new file mode 100644 index 0000000000..107bfe208b --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs @@ -0,0 +1,53 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Graphics.UserInterface +{ + public class ThreeStateMenuItem : StatefulMenuItem + { + public ThreeStateMenuItem(string text, MenuItemType type = MenuItemType.Standard) + : base(text, type, getNextState) + { + } + + public override IconUsage? GetIconForState(ThreeStates state) + { + switch (state) + { + case ThreeStates.Indeterminate: + return FontAwesome.Regular.Circle; + + case ThreeStates.Enabled: + return FontAwesome.Solid.Check; + } + + return null; + } + + private static ThreeStates getNextState(ThreeStates state) + { + switch (state) + { + case ThreeStates.Disabled: + return ThreeStates.Enabled; + + case ThreeStates.Indeterminate: + return ThreeStates.Enabled; + + case ThreeStates.Enabled: + return ThreeStates.Disabled; + } + + return ThreeStates.Disabled; + } + } + + public enum ThreeStates + { + Disabled, + Indeterminate, + Enabled + } +} From 0a15a13fabd66d5676dfd12e1117772a31ae605a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 12:55:22 +0900 Subject: [PATCH 3878/5608] Reorder parameters --- .../TestSceneStatefulMenuItem.cs | 4 ++-- .../UserInterface/StatefulMenuItem.cs | 20 +++++++++++-------- .../UserInterface/ThreeStateMenuItem.cs | 8 +++++++- .../Graphics/UserInterface/ToggleMenuItem.cs | 3 +-- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index fbb35ba09f..00678a6ab4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -53,12 +53,12 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestMenuItem : StatefulMenuItem { public TestMenuItem(string text, MenuItemType type = MenuItemType.Standard) - : base(text, type) + : this(text, type, null) { } public TestMenuItem(string text, MenuItemType type, Func changeStateFunc) - : base(text, type, changeStateFunc) + : base(text, changeStateFunc, type) { } diff --git a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs index ede2c9df48..b5f9a3d635 100644 --- a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs @@ -11,15 +11,19 @@ namespace osu.Game.Graphics.UserInterface { public readonly Bindable State = new Bindable(); - protected StatefulMenuItem(string text, MenuItemType type = MenuItemType.Standard) - : this(text, type, null) + protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type = MenuItemType.Standard) + : this(text, changeStateFunc, type, null) { } - protected StatefulMenuItem(string text, MenuItemType type, Func changeStateFunc) + protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) : base(text, type) { - Action.Value = () => State.Value = changeStateFunc?.Invoke(State.Value) ?? State.Value; + Action.Value = () => + { + State.Value = changeStateFunc?.Invoke(State.Value) ?? State.Value; + action?.Invoke(State.Value); + }; } public abstract IconUsage? GetIconForState(object state); @@ -30,13 +34,13 @@ namespace osu.Game.Graphics.UserInterface { public new readonly Bindable State = new Bindable(); - protected StatefulMenuItem(string text, MenuItemType type = MenuItemType.Standard) - : this(text, type, null) + protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type = MenuItemType.Standard) + : this(text, changeStateFunc, type, null) { } - protected StatefulMenuItem(string text, MenuItemType type, Func changeStateFunc) - : base(text, type, o => changeStateFunc?.Invoke((T)o) ?? o) + protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) + : base(text, o => changeStateFunc?.Invoke((T)o) ?? o, type, o => action?.Invoke((T)o)) { base.State.BindValueChanged(state => { diff --git a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs index 107bfe208b..d41a95daa1 100644 --- a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface @@ -8,7 +9,12 @@ namespace osu.Game.Graphics.UserInterface public class ThreeStateMenuItem : StatefulMenuItem { public ThreeStateMenuItem(string text, MenuItemType type = MenuItemType.Standard) - : base(text, type, getNextState) + : this(text, type, null) + { + } + + public ThreeStateMenuItem(string text, MenuItemType type, Action action) + : base(text, getNextState, type, action) { } diff --git a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs index a0ed745c5a..f5a442b317 100644 --- a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs @@ -14,9 +14,8 @@ namespace osu.Game.Graphics.UserInterface } public ToggleMenuItem(string text, MenuItemType type, Action action) - : base(text, type, value => !value) + : base(text, value => !value, type, action) { - State.BindValueChanged(state => action?.Invoke(state.NewValue)); } public override IconUsage? GetIconForState(bool state) => state ? (IconUsage?)FontAwesome.Solid.Check : null; From 011bf095166d88d560087bbf83d07567309c585f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 13:14:23 +0900 Subject: [PATCH 3879/5608] Add xmldocs and cleanup --- .../TestSceneStatefulMenuItem.cs | 5 ++- .../UserInterface/StatefulMenuItem.cs | 45 +++++++++++++++++++ .../UserInterface/ThreeStateMenuItem.cs | 45 +++++++++++++++++-- .../Graphics/UserInterface/ToggleMenuItem.cs | 14 ++++++ 4 files changed, 104 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index 00678a6ab4..d010abc862 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -74,9 +74,10 @@ namespace osu.Game.Tests.Visual.UserInterface case TestStates.State3: return FontAwesome.Solid.DiceThree; - } - return null; + default: + throw new ArgumentOutOfRangeException(nameof(state), state, null); + } } } diff --git a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs index b5f9a3d635..0d7b36e51b 100644 --- a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs @@ -7,15 +7,34 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { + /// + /// An which contains and displays a state. + /// public abstract class StatefulMenuItem : OsuMenuItem { + /// + /// The current state that should be displayed. + /// public readonly Bindable State = new Bindable(); + /// + /// Creates a new . + /// + /// The text to display. + /// A function that mutates a state to another state after this is pressed. + /// The type of action which this performs. protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type = MenuItemType.Standard) : this(text, changeStateFunc, type, null) { } + /// + /// Creates a new . + /// + /// The text to display. + /// A function that mutates a state to another state after this is pressed. + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) : base(text, type) { @@ -26,19 +45,40 @@ namespace osu.Game.Graphics.UserInterface }; } + /// + /// Retrieves the icon to be displayed for a state. + /// + /// The state to retrieve the relevant icon for. + /// The icon to be displayed for . public abstract IconUsage? GetIconForState(object state); } public abstract class StatefulMenuItem : StatefulMenuItem where T : struct { + /// + /// The current state that should be displayed. + /// public new readonly Bindable State = new Bindable(); + /// + /// Creates a new . + /// + /// The text to display. + /// A function that mutates a state to another state after this is pressed. + /// The type of action which this performs. protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type = MenuItemType.Standard) : this(text, changeStateFunc, type, null) { } + /// + /// Creates a new . + /// + /// The text to display. + /// A function that mutates a state to another state after this is pressed. + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) : base(text, o => changeStateFunc?.Invoke((T)o) ?? o, type, o => action?.Invoke((T)o)) { @@ -55,6 +95,11 @@ namespace osu.Game.Graphics.UserInterface public sealed override IconUsage? GetIconForState(object state) => GetIconForState((T)state); + /// + /// Retrieves the icon to be displayed for a state. + /// + /// The state to retrieve the relevant icon for. + /// The icon to be displayed for . public abstract IconUsage? GetIconForState(T state); } } diff --git a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs index d41a95daa1..e33c68bebd 100644 --- a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs @@ -6,15 +6,41 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { + /// + /// An with three possible states. + /// public class ThreeStateMenuItem : StatefulMenuItem { + /// + /// Creates a new . + /// + /// The text to display. + /// The type of action which this performs. public ThreeStateMenuItem(string text, MenuItemType type = MenuItemType.Standard) : this(text, type, null) { } + /// + /// Creates a new . + /// + /// The text to display. + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. public ThreeStateMenuItem(string text, MenuItemType type, Action action) - : base(text, getNextState, type, action) + : this(text, getNextState, type, action) + { + } + + /// + /// Creates a new . + /// + /// The text to display. + /// A function that mutates a state to another state after this is pressed. + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. + protected ThreeStateMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) + : base(text, changeStateFunc, type, action) { } @@ -44,16 +70,29 @@ namespace osu.Game.Graphics.UserInterface case ThreeStates.Enabled: return ThreeStates.Disabled; - } - return ThreeStates.Disabled; + default: + throw new ArgumentOutOfRangeException(nameof(state), state, null); + } } } public enum ThreeStates { + /// + /// The current state is disabled. + /// Disabled, + + /// + /// The current state is a combination of and . + /// The state becomes if the is pressed. + /// Indeterminate, + + /// + /// The current state is enabled. + /// Enabled } } diff --git a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs index f5a442b317..f9ff9859dd 100644 --- a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs @@ -6,13 +6,27 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { + /// + /// An which displays an enabled or disabled state. + /// public class ToggleMenuItem : StatefulMenuItem { + /// + /// Creates a new . + /// + /// The text to display. + /// The type of action which this performs. public ToggleMenuItem(string text, MenuItemType type = MenuItemType.Standard) : this(text, type, null) { } + /// + /// Creates a new . + /// + /// The text to display. + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. public ToggleMenuItem(string text, MenuItemType type, Action action) : base(text, value => !value, type, action) { From a2c265c1478f1b33937d8da76343eabd688046ad Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 13:16:09 +0900 Subject: [PATCH 3880/5608] Separate ThreeStates into its own file --- .../UserInterface/ThreeStateMenuItem.cs | 19 ------------- .../Graphics/UserInterface/ThreeStates.cs | 27 +++++++++++++++++++ 2 files changed, 27 insertions(+), 19 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/ThreeStates.cs diff --git a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs index e33c68bebd..ebb6436196 100644 --- a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs @@ -76,23 +76,4 @@ namespace osu.Game.Graphics.UserInterface } } } - - public enum ThreeStates - { - /// - /// The current state is disabled. - /// - Disabled, - - /// - /// The current state is a combination of and . - /// The state becomes if the is pressed. - /// - Indeterminate, - - /// - /// The current state is enabled. - /// - Enabled - } } diff --git a/osu.Game/Graphics/UserInterface/ThreeStates.cs b/osu.Game/Graphics/UserInterface/ThreeStates.cs new file mode 100644 index 0000000000..f099250937 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ThreeStates.cs @@ -0,0 +1,27 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Graphics.UserInterface +{ + /// + /// An on/off state with an extra indeterminate state. + /// + public enum ThreeStates + { + /// + /// The current state is disabled. + /// + Disabled, + + /// + /// The current state is a combination of and . + /// The state becomes if the is pressed. + /// + Indeterminate, + + /// + /// The current state is enabled. + /// + Enabled + } +} From e574aa0e94ee16366a7c4086f2eb80042edb494f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 13:33:15 +0900 Subject: [PATCH 3881/5608] Add toggle menu item test --- .../UserInterface/TestSceneToggleMenuItem.cs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs new file mode 100644 index 0000000000..2abda56a28 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs @@ -0,0 +1,34 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneToggleMenuItem : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuMenu), + typeof(ToggleMenuItem), + typeof(DrawableStatefulMenuItem) + }; + + public TestSceneToggleMenuItem() + { + Add(new OsuMenu(Direction.Vertical, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new ToggleMenuItem("First"), + new ToggleMenuItem("Second") { State = { Value = true } } + } + }); + } + } +} From 92d8526370e8cdc166460b30c58e0d47c4cc2654 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 13:34:27 +0900 Subject: [PATCH 3882/5608] Adjust test namespaces --- .../{ => MenuItems}/TestSceneStatefulMenuItem.cs | 4 ++-- .../{ => MenuItems}/TestSceneThreeStateMenuItem.cs | 2 +- .../UserInterface/{ => MenuItems}/TestSceneToggleMenuItem.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{ => MenuItems}/TestSceneStatefulMenuItem.cs (96%) rename osu.Game.Tests/Visual/UserInterface/{ => MenuItems}/TestSceneThreeStateMenuItem.cs (95%) rename osu.Game.Tests/Visual/UserInterface/{ => MenuItems}/TestSceneToggleMenuItem.cs (94%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneStatefulMenuItem.cs similarity index 96% rename from osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs rename to osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneStatefulMenuItem.cs index d010abc862..95e9aea97f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneStatefulMenuItem.cs @@ -7,14 +7,14 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual.UserInterface +namespace osu.Game.Tests.Visual.UserInterface.MenuItems { public class TestSceneStatefulMenuItem : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(OsuMenu), - typeof(ToggleMenuItem), + typeof(StatefulMenuItem), typeof(DrawableStatefulMenuItem) }; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneThreeStateMenuItem.cs similarity index 95% rename from osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs rename to osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneThreeStateMenuItem.cs index caa07e7b60..e035e43630 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneThreeStateMenuItem.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual.UserInterface +namespace osu.Game.Tests.Visual.UserInterface.MenuItems { public class TestSceneThreeStateMenuItem : OsuTestScene { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneToggleMenuItem.cs similarity index 94% rename from osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs rename to osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneToggleMenuItem.cs index 2abda56a28..92875740cf 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneToggleMenuItem.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual.UserInterface +namespace osu.Game.Tests.Visual.UserInterface.MenuItems { public class TestSceneToggleMenuItem : OsuTestScene { From abb3a6ca5bf610f50ff8519a4847bf1b650a2c67 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 22:51:49 +0900 Subject: [PATCH 3883/5608] Initial right click context menu implementation --- .../Compose/Components/BlueprintContainer.cs | 22 +++ .../Compose/Components/SelectionHandler.cs | 67 +++++++- osu.Game/Screens/Edit/Editor.cs | 143 +++++++++--------- 3 files changed, 162 insertions(+), 70 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 8fa022f129..af0ac22a70 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -17,6 +17,7 @@ using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osuTK; +using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components { @@ -95,12 +96,18 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnMouseDown(MouseDownEvent e) { + if (e.Button == MouseButton.Right) + return false; + beginClickSelection(e); return true; } protected override bool OnClick(ClickEvent e) { + if (e.Button == MouseButton.Right) + return false; + // Deselection should only occur if no selected blueprints are hovered // A special case for when a blueprint was selected via this click is added since OnClick() may occur outside the hitobject and should not trigger deselection if (endClickSelection() || selectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) @@ -112,6 +119,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnDoubleClick(DoubleClickEvent e) { + if (e.Button == MouseButton.Right) + return false; + SelectionBlueprint clickedBlueprint = selectionHandler.SelectedBlueprints.FirstOrDefault(b => b.IsHovered); if (clickedBlueprint == null) @@ -123,6 +133,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnMouseUp(MouseUpEvent e) { + if (e.Button == MouseButton.Right) + return false; + // Special case for when a drag happened instead of a click Schedule(() => endClickSelection()); return true; @@ -141,6 +154,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnDragStart(DragStartEvent e) { + if (e.Button == MouseButton.Right) + return false; + if (!beginSelectionMovement()) { dragBox.UpdateDrag(e); @@ -152,6 +168,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnDrag(DragEvent e) { + if (e.Button == MouseButton.Right) + return false; + if (!moveCurrentSelection(e)) dragBox.UpdateDrag(e); @@ -160,6 +179,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnDragEnd(DragEndEvent e) { + if (e.Button == MouseButton.Right) + return false; + if (!finishSelectionMovement()) { dragBox.FadeOut(250, Easing.OutQuint); diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 44bf22cfe1..779cd86318 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -7,11 +7,16 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Framework.Input.States; +using osu.Game.Audio; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -22,7 +27,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// A component which outlines s and handles movement of selections. /// - public class SelectionHandler : CompositeDrawable, IKeyBindingHandler + public class SelectionHandler : CompositeDrawable, IKeyBindingHandler, IHasContextMenu { public const float BORDER_RADIUS = 2; @@ -142,6 +147,8 @@ namespace osu.Game.Screens.Edit.Compose.Components #endregion + #region Outline Display + /// /// Updates whether this is visible. /// @@ -176,5 +183,63 @@ namespace osu.Game.Screens.Edit.Compose.Components outline.Size = bottomRight - topLeft; outline.Position = topLeft; } + + #endregion + + #region Context Menu + + public virtual MenuItem[] ContextMenuItems + { + get + { + if (!SelectedBlueprints.Any()) + return Array.Empty(); + + return new MenuItem[] + { + new OsuMenuItem("hit sound") + { + Items = new[] + { + createHitSampleMenuItem(HitSampleInfo.HIT_WHISTLE), + createHitSampleMenuItem(HitSampleInfo.HIT_CLAP), + createHitSampleMenuItem(HitSampleInfo.HIT_FINISH) + } + } + }; + } + } + + private MenuItem createHitSampleMenuItem(string sampleName) + { + return new ToggleMenuItem(sampleName, MenuItemType.Standard, setHitSampleState) + { + State = { Value = getHitSampleState() } + }; + + void setHitSampleState(bool enabled) + { + if (enabled) + { + foreach (var h in SelectedHitObjects) + { + // Make sure there isn't already an existing sample + if (h.Samples.Any(s => s.Name == sampleName)) + continue; + + h.Samples.Add(new HitSampleInfo { Name = sampleName }); + } + } + else + { + foreach (var h in SelectedHitObjects) + h.Samples.RemoveAll(s => s.Name == sampleName); + } + } + + bool getHitSampleState() => SelectedHitObjects.All(h => h.Samples.Any(s => s.Name == sampleName)); + } + + #endregion } } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 35408e4003..1ae3fd71ab 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -24,6 +24,7 @@ using osuTK.Input; using System.Collections.Generic; using osu.Framework; using osu.Framework.Input.Bindings; +using osu.Game.Graphics.Cursor; using osu.Game.Input.Bindings; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Setup; @@ -85,87 +86,91 @@ namespace osu.Game.Screens.Edit fileMenuItems.Add(new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit)); - InternalChildren = new[] + InternalChild = new OsuContextMenuContainer { - new Container + RelativeSizeAxes = Axes.Both, + Children = new[] { - Name = "Screen container", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = 40, Bottom = 60 }, - Child = screenContainer = new Container + new Container { + Name = "Screen container", RelativeSizeAxes = Axes.Both, - Masking = true - } - }, - new Container - { - Name = "Top bar", - RelativeSizeAxes = Axes.X, - Height = 40, - Child = menuBar = new EditorMenuBar - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.Both, - Items = new[] - { - new MenuItem("File") - { - Items = fileMenuItems - } - } - } - }, - new Container - { - Name = "Bottom bar", - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Height = 60, - Children = new Drawable[] - { - bottomBackground = new Box { RelativeSizeAxes = Axes.Both }, - new Container + Padding = new MarginPadding { Top = 40, Bottom = 60 }, + Child = screenContainer = new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Vertical = 5, Horizontal = 10 }, - Child = new GridContainer + Masking = true + } + }, + new Container + { + Name = "Top bar", + RelativeSizeAxes = Axes.X, + Height = 40, + Child = menuBar = new EditorMenuBar + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.Both, + Items = new[] + { + new MenuItem("File") + { + Items = fileMenuItems + } + } + } + }, + new Container + { + Name = "Bottom bar", + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = 60, + Children = new Drawable[] + { + bottomBackground = new Box { RelativeSizeAxes = Axes.Both }, + new Container { RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] + Padding = new MarginPadding { Vertical = 5, Horizontal = 10 }, + Child = new GridContainer { - new Dimension(GridSizeMode.Absolute, 220), - new Dimension(), - new Dimension(GridSizeMode.Absolute, 220) - }, - Content = new[] - { - new Drawable[] + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] { - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 10 }, - Child = new TimeInfoContainer { RelativeSizeAxes = Axes.Both }, - }, - new SummaryTimeline - { - RelativeSizeAxes = Axes.Both, - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = 10 }, - Child = new PlaybackControl { RelativeSizeAxes = Axes.Both }, - } + new Dimension(GridSizeMode.Absolute, 220), + new Dimension(), + new Dimension(GridSizeMode.Absolute, 220) }, - } - }, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 10 }, + Child = new TimeInfoContainer { RelativeSizeAxes = Axes.Both }, + }, + new SummaryTimeline + { + RelativeSizeAxes = Axes.Both, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = 10 }, + Child = new PlaybackControl { RelativeSizeAxes = Axes.Both }, + } + }, + } + }, + } } - } - }, + }, + } }; menuBar.Mode.ValueChanged += onModeChanged; From 573d11503e27e7a99202a94ee08b2912e65bcb1f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 11:13:24 +0900 Subject: [PATCH 3884/5608] Remove unused using --- osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 779cd86318..43dbeb35f7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Audio; using osu.Game.Graphics; From 046f0b0fe5947f57ae312ee80c88e6e3d42b2529 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 13:40:47 +0900 Subject: [PATCH 3885/5608] Allow right-clicks to trigger selection --- .../Edit/Compose/Components/BlueprintContainer.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index af0ac22a70..e7877f962e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -96,11 +96,8 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnMouseDown(MouseDownEvent e) { - if (e.Button == MouseButton.Right) - return false; - beginClickSelection(e); - return true; + return e.Button == MouseButton.Left; } protected override bool OnClick(ClickEvent e) @@ -133,12 +130,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnMouseUp(MouseUpEvent e) { - if (e.Button == MouseButton.Right) - return false; - // Special case for when a drag happened instead of a click Schedule(() => endClickSelection()); - return true; + return e.Button == MouseButton.Left; } protected override bool OnMouseMove(MouseMoveEvent e) From 864b8db638b6b3a70eb3f6189d2a9761127b3e1d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 13:52:36 +0900 Subject: [PATCH 3886/5608] Use three states for the hitsound menu items --- .../Compose/Components/SelectionHandler.cs | 56 ++++++++++++------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 43dbeb35f7..dc147a92cd 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -196,47 +196,61 @@ namespace osu.Game.Screens.Edit.Compose.Components return new MenuItem[] { - new OsuMenuItem("hit sound") + new OsuMenuItem("Sound") { Items = new[] { - createHitSampleMenuItem(HitSampleInfo.HIT_WHISTLE), - createHitSampleMenuItem(HitSampleInfo.HIT_CLAP), - createHitSampleMenuItem(HitSampleInfo.HIT_FINISH) + createHitSampleMenuItem("Whistle", HitSampleInfo.HIT_WHISTLE), + createHitSampleMenuItem("Clap", HitSampleInfo.HIT_CLAP), + createHitSampleMenuItem("Finish", HitSampleInfo.HIT_FINISH) } } }; } } - private MenuItem createHitSampleMenuItem(string sampleName) + private MenuItem createHitSampleMenuItem(string name, string sampleName) { - return new ToggleMenuItem(sampleName, MenuItemType.Standard, setHitSampleState) + return new ThreeStateMenuItem(name, MenuItemType.Standard, setHitSampleState) { State = { Value = getHitSampleState() } }; - void setHitSampleState(bool enabled) + void setHitSampleState(ThreeStates state) { - if (enabled) + switch (state) { - foreach (var h in SelectedHitObjects) - { - // Make sure there isn't already an existing sample - if (h.Samples.Any(s => s.Name == sampleName)) - continue; + case ThreeStates.Disabled: + foreach (var h in SelectedHitObjects) + h.Samples.RemoveAll(s => s.Name == sampleName); + break; - h.Samples.Add(new HitSampleInfo { Name = sampleName }); - } - } - else - { - foreach (var h in SelectedHitObjects) - h.Samples.RemoveAll(s => s.Name == sampleName); + case ThreeStates.Enabled: + foreach (var h in SelectedHitObjects) + { + // Make sure there isn't already an existing sample + if (h.Samples.Any(s => s.Name == sampleName)) + continue; + + h.Samples.Add(new HitSampleInfo { Name = sampleName }); + } + + break; } } - bool getHitSampleState() => SelectedHitObjects.All(h => h.Samples.Any(s => s.Name == sampleName)); + ThreeStates getHitSampleState() + { + int countExisting = SelectedHitObjects.Count(h => h.Samples.Any(s => s.Name == sampleName)); + + if (countExisting == 0) + return ThreeStates.Disabled; + + if (countExisting < SelectedHitObjects.Count()) + return ThreeStates.Indeterminate; + + return ThreeStates.Enabled; + } } #endregion From 6fc1be64c2c4adbb7335288d765c77e3343a5e73 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 14:04:57 +0900 Subject: [PATCH 3887/5608] Make hitobject samples a bindable list --- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 2 +- .../Beatmaps/ManiaBeatmapConverter.cs | 2 +- .../Legacy/DistanceObjectPatternGenerator.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs | 6 +++--- osu.Game.Rulesets.Osu/Objects/Slider.cs | 6 +++--- .../Beatmaps/TaikoBeatmapConverter.cs | 6 +++--- osu.Game/Rulesets/Objects/HitObject.cs | 12 ++++++++---- .../Objects/Legacy/Catch/ConvertHitObjectParser.cs | 2 +- .../Objects/Legacy/ConvertHitObjectParser.cs | 4 ++-- osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs | 2 +- .../Objects/Legacy/Mania/ConvertHitObjectParser.cs | 2 +- .../Objects/Legacy/Osu/ConvertHitObjectParser.cs | 2 +- .../Objects/Legacy/Taiko/ConvertHitObjectParser.cs | 2 +- osu.Game/Rulesets/Objects/Types/IHasRepeats.cs | 2 +- .../Edit/Compose/Components/SelectionHandler.cs | 3 ++- 15 files changed, 30 insertions(+), 25 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 0952e8981a..80a3af0aa0 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Catch.Objects public double Distance => Path.Distance; - public List> NodeSamples { get; set; } = new List>(); + public List> NodeSamples { get; set; } = new List>(); public double? LegacyLastTickOffset { get; set; } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index e10602312e..6c5bb304bf 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -255,7 +255,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// /// The time to retrieve the sample info list from. /// - private List sampleInfoListAt(double time) + private IList sampleInfoListAt(double time) { var curveData = HitObject as IHasCurve; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index ea418eedb4..6297a68e08 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -472,7 +472,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// /// The time to retrieve the sample info list from. /// - private List sampleInfoListAt(double time) + private IList sampleInfoListAt(double time) { var curveData = HitObject as IHasCurve; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index a955911bd5..46a2a36ac7 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -275,7 +275,7 @@ namespace osu.Game.Rulesets.Osu.Tests private Drawable createCatmull(int repeats = 0) { - var repeatSamples = new List>(); + var repeatSamples = new List>(); for (int i = 0; i < repeats; i++) repeatSamples.Add(new List()); @@ -297,9 +297,9 @@ namespace osu.Game.Rulesets.Osu.Tests return createDrawable(slider, 3, 1); } - private List> createEmptySamples(int repeats) + private List> createEmptySamples(int repeats) { - var repeatSamples = new List>(); + var repeatSamples = new List>(); for (int i = 0; i < repeats; i++) repeatSamples.Add(new List()); return repeatSamples; diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index f60b7e67b2..c41026d954 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Osu.Objects /// internal float LazyTravelDistance; - public List> NodeSamples { get; set; } = new List>(); + public List> NodeSamples { get; set; } = new List>(); private int repeatCount; @@ -128,7 +128,7 @@ namespace osu.Game.Rulesets.Osu.Objects foreach (var e in SliderEventGenerator.Generate(StartTime, SpanDuration, Velocity, TickDistance, Path.Distance, this.SpanCount(), LegacyLastTickOffset)) { - var firstSample = Samples.Find(s => s.Name == HitSampleInfo.HIT_NORMAL) + var firstSample = Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) var sampleList = new List(); @@ -203,7 +203,7 @@ namespace osu.Game.Rulesets.Osu.Objects TailCircle.Position = EndPosition; } - private List getNodeSamples(int nodeIndex) => + private IList getNodeSamples(int nodeIndex) => nodeIndex < NodeSamples.Count ? NodeSamples[nodeIndex] : Samples; public override Judgement CreateJudgement() => new OsuJudgement(); diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index f0cf8d9c7d..180e0d8309 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps var curveData = obj as IHasCurve; // Old osu! used hit sounding to determine various hit type information - List samples = obj.Samples; + IList samples = obj.Samples; bool strong = samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH); @@ -117,13 +117,13 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength) { - List> allSamples = curveData != null ? curveData.NodeSamples : new List>(new[] { samples }); + List> allSamples = curveData != null ? curveData.NodeSamples : new List>(new[] { samples }); int i = 0; for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing) { - List currentSamples = allSamples[i]; + IList currentSamples = allSamples[i]; bool isRim = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE); strong = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_FINISH); diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 6211fe50e6..ee0705ec5a 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Objects set => StartTimeBindable.Value = value; } - private List samples; + public readonly BindableList SamplesBindable = new BindableList(); /// /// The samples to be played when this hit object is hit. @@ -54,10 +54,14 @@ namespace osu.Game.Rulesets.Objects /// and can be treated as the default samples for the hit object. /// /// - public List Samples + public IList Samples { - get => samples ?? (samples = new List()); - set => samples = value; + get => SamplesBindable; + set + { + SamplesBindable.Clear(); + SamplesBindable.AddRange(value); + } } [JsonIgnore] diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index 71e321f205..545cfe07f8 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch } protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, - List> nodeSamples) + List> nodeSamples) { newCombo |= forceNewCombo; comboOffset += extraComboOffset; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index e990938291..bbf46a0c8f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -181,7 +181,7 @@ namespace osu.Game.Rulesets.Objects.Legacy } // Generate the final per-node samples - var nodeSamples = new List>(nodes); + var nodeSamples = new List>(nodes); for (int i = 0; i < nodes; i++) nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i])); @@ -279,7 +279,7 @@ namespace osu.Game.Rulesets.Objects.Legacy /// The samples to be played when the slider nodes are hit. This includes the head and tail of the slider. /// The hit object. protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, - List> nodeSamples); + List> nodeSamples); /// /// Creates a legacy Spinner-type hit object. diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index ff6b9be8b5..8d523022d6 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Objects.Legacy public double Distance => Path.Distance; - public List> NodeSamples { get; set; } + public List> NodeSamples { get; set; } public int RepeatCount { get; set; } public double EndTime => StartTime + this.SpanCount() * Distance / Velocity; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index 94aba95e90..8012b4230f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania } protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, - List> nodeSamples) + List> nodeSamples) { return new ConvertSlider { diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index 65102f1e89..99872e630d 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu } protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, - List> nodeSamples) + List> nodeSamples) { newCombo |= forceNewCombo; comboOffset += extraComboOffset; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs index eb598f1368..9dc0c01932 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko } protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, - List> nodeSamples) + List> nodeSamples) { return new ConvertSlider { diff --git a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs index 697adeda98..b22752e902 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Objects.Types /// n-1: The last repeat.
/// n: The last node. ///
- List> NodeSamples { get; } + List> NodeSamples { get; } } public static class HasRepeatsExtensions diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index dc147a92cd..5f0bfb6d70 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -222,7 +222,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { case ThreeStates.Disabled: foreach (var h in SelectedHitObjects) - h.Samples.RemoveAll(s => s.Name == sampleName); + h.SamplesBindable.RemoveAll(s => s.Name == sampleName); + break; case ThreeStates.Enabled: From 53e6186b6d4421bdb4abb9feca0674ea827603fe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 14:59:47 +0900 Subject: [PATCH 3888/5608] Fix drawable hitobject samples not updating --- .../Objects/Drawables/DrawableHitObject.cs | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 1d9b66f88d..592cddeff6 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -78,6 +78,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public JudgementResult Result { get; private set; } + private BindableList samplesBindable; private Bindable startTimeBindable; private Bindable comboIndexBindable; @@ -108,20 +109,7 @@ namespace osu.Game.Rulesets.Objects.Drawables throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); } - var samples = GetSamples().ToArray(); - - if (samples.Length > 0) - { - if (HitObject.SampleControlPoint == null) - throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." - + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); - - samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray(); - foreach (var s in samples) - s.Namespace = SampleNamespace; - - AddInternal(Samples = new SkinnableSound(samples)); - } + loadSamples(); } protected override void LoadComplete() @@ -139,10 +127,34 @@ namespace osu.Game.Rulesets.Objects.Drawables comboIndexBindable.BindValueChanged(_ => updateAccentColour(), true); } + samplesBindable = HitObject.SamplesBindable.GetBoundCopy(); + samplesBindable.ItemsAdded += _ => scheduleLoadSamples(); + samplesBindable.ItemsRemoved += _ => scheduleLoadSamples(); + updateState(ArmedState.Idle, true); onDefaultsApplied(); } + private void scheduleLoadSamples() => Scheduler.AddOnce(loadSamples); + + private void loadSamples() + { + var samples = GetSamples().ToArray(); + + if (samples.Length <= 0) + return; + + if (HitObject.SampleControlPoint == null) + throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." + + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); + + samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray(); + foreach (var s in samples) + s.Namespace = SampleNamespace; + + AddInternal(Samples = new SkinnableSound(samples)); + } + private void onDefaultsApplied() => apply(HitObject); private void apply(HitObject hitObject) From df31acb2940ca5333e019e0340c2fdd67ff5f9e9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 15:39:07 +0900 Subject: [PATCH 3889/5608] Fix slider nested hitobject samples not getting updated --- .../TestSceneSlider.cs | 75 +++++++++++++++---- osu.Game.Rulesets.Osu/Objects/Slider.cs | 47 ++++++++---- 2 files changed, 93 insertions(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 46a2a36ac7..5c656bf594 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -126,6 +126,67 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("body positioned correctly", () => slider.Position == slider.HitObject.StackedPosition); } + [Test] + public void TestChangeSamplesWithNoNodeSamples() + { + DrawableSlider slider = null; + + AddStep("create slider", () => + { + slider = (DrawableSlider)createSlider(repeats: 1); + Add(slider); + }); + + AddStep("change samples", () => slider.HitObject.Samples = new[] + { + new HitSampleInfo { Name = HitSampleInfo.HIT_CLAP }, + new HitSampleInfo { Name = HitSampleInfo.HIT_WHISTLE }, + }); + + AddAssert("head samples updated", () => assertSamples(((Slider)slider.HitObject).HeadCircle)); + AddAssert("tick samples not updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertTickSamples)); + AddAssert("repeat samples updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertSamples)); + AddAssert("tail has no samples", () => ((Slider)slider.HitObject).TailCircle.Samples.Count == 0); + + bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; + + bool assertSamples(HitObject hitObject) + { + return hitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP) + && hitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_WHISTLE); + } + } + + [Test] + public void TestChangeSamplesWithNodeSamples() + { + DrawableSlider slider = null; + + AddStep("create slider", () => + { + slider = (DrawableSlider)createSlider(repeats: 1); + + for (int i = 0; i < 2; i++) + ((Slider)slider.HitObject).NodeSamples.Add(new List { new HitSampleInfo { Name = HitSampleInfo.HIT_FINISH } }); + + Add(slider); + }); + + AddStep("change samples", () => slider.HitObject.Samples = new[] + { + new HitSampleInfo { Name = HitSampleInfo.HIT_CLAP }, + new HitSampleInfo { Name = HitSampleInfo.HIT_WHISTLE }, + }); + + AddAssert("head samples not updated", () => assertSamples(((Slider)slider.HitObject).HeadCircle)); + AddAssert("tick samples not updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertTickSamples)); + AddAssert("repeat samples not updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertSamples)); + AddAssert("tail has no samples", () => ((Slider)slider.HitObject).TailCircle.Samples.Count == 0); + + bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; + bool assertSamples(HitObject hitObject) => hitObject.Samples.All(s => s.Name != HitSampleInfo.HIT_CLAP && s.Name != HitSampleInfo.HIT_WHISTLE); + } + private Drawable testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats); private Drawable testSimpleBigLargeStackOffset(int repeats = 0) => createSlider(2, repeats: repeats, stackHeight: 10); @@ -143,7 +204,6 @@ namespace osu.Game.Rulesets.Osu.Tests new Vector2(52, -34) }, 700), RepeatCount = repeats, - NodeSamples = createEmptySamples(repeats), StackHeight = 10 }; @@ -174,7 +234,6 @@ namespace osu.Game.Rulesets.Osu.Tests new Vector2(distance, 0), }, distance), RepeatCount = repeats, - NodeSamples = createEmptySamples(repeats), StackHeight = stackHeight }; @@ -194,7 +253,6 @@ namespace osu.Game.Rulesets.Osu.Tests new Vector2(400, 0) }, 600), RepeatCount = repeats, - NodeSamples = createEmptySamples(repeats) }; return createDrawable(slider, 2, 3); @@ -218,7 +276,6 @@ namespace osu.Game.Rulesets.Osu.Tests new Vector2(430, 0) }), RepeatCount = repeats, - NodeSamples = createEmptySamples(repeats) }; return createDrawable(slider, 2, 3); @@ -241,7 +298,6 @@ namespace osu.Game.Rulesets.Osu.Tests new Vector2(430, 0) }), RepeatCount = repeats, - NodeSamples = createEmptySamples(repeats) }; return createDrawable(slider, 2, 3); @@ -265,7 +321,6 @@ namespace osu.Game.Rulesets.Osu.Tests new Vector2(0, -200) }), RepeatCount = repeats, - NodeSamples = createEmptySamples(repeats) }; return createDrawable(slider, 2, 3); @@ -297,14 +352,6 @@ namespace osu.Game.Rulesets.Osu.Tests return createDrawable(slider, 3, 1); } - private List> createEmptySamples(int repeats) - { - var repeatSamples = new List>(); - for (int i = 0; i < repeats; i++) - repeatSamples.Add(new List()); - return repeatSamples; - } - private Drawable createDrawable(Slider slider, float circleSize, double speedMultiplier) { var cpi = new ControlPointInfo(); diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index c41026d954..f3399af2de 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -108,6 +108,12 @@ namespace osu.Game.Rulesets.Osu.Objects public HitCircle HeadCircle; public SliderTailCircle TailCircle; + public Slider() + { + SamplesBindable.ItemsAdded += _ => updateNestedSamples(); + SamplesBindable.ItemsRemoved += _ => updateNestedSamples(); + } + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); @@ -128,18 +134,6 @@ namespace osu.Game.Rulesets.Osu.Objects foreach (var e in SliderEventGenerator.Generate(StartTime, SpanDuration, Velocity, TickDistance, Path.Distance, this.SpanCount(), LegacyLastTickOffset)) { - var firstSample = Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) - ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) - var sampleList = new List(); - - if (firstSample != null) - sampleList.Add(new HitSampleInfo - { - Bank = firstSample.Bank, - Volume = firstSample.Volume, - Name = @"slidertick", - }); - switch (e.Type) { case SliderEventType.Tick: @@ -151,7 +145,6 @@ namespace osu.Game.Rulesets.Osu.Objects Position = Position + Path.PositionAt(e.PathProgress), StackHeight = StackHeight, Scale = Scale, - Samples = sampleList }); break; @@ -161,7 +154,6 @@ namespace osu.Game.Rulesets.Osu.Objects StartTime = e.Time, Position = Position, StackHeight = StackHeight, - Samples = getNodeSamples(0), SampleControlPoint = SampleControlPoint, }); break; @@ -187,11 +179,12 @@ namespace osu.Game.Rulesets.Osu.Objects Position = Position + Path.PositionAt(e.PathProgress), StackHeight = StackHeight, Scale = Scale, - Samples = getNodeSamples(e.SpanIndex + 1) }); break; } } + + updateNestedSamples(); } private void updateNestedPositions() @@ -203,6 +196,30 @@ namespace osu.Game.Rulesets.Osu.Objects TailCircle.Position = EndPosition; } + private void updateNestedSamples() + { + var firstSample = Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) + ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) + var sampleList = new List(); + + if (firstSample != null) + sampleList.Add(new HitSampleInfo + { + Bank = firstSample.Bank, + Volume = firstSample.Volume, + Name = @"slidertick", + }); + + foreach (var tick in NestedHitObjects.OfType()) + tick.Samples = sampleList; + + foreach (var repeat in NestedHitObjects.OfType()) + repeat.Samples = getNodeSamples(repeat.RepeatIndex + 1); + + if (HeadCircle != null) + HeadCircle.Samples = getNodeSamples(0); + } + private IList getNodeSamples(int nodeIndex) => nodeIndex < NodeSamples.Count ? NodeSamples[nodeIndex] : Samples; From 5fe764b2db98b30113fdc9f2fc7690df8db97ed8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 16:19:34 +0900 Subject: [PATCH 3890/5608] Fix tournament videos stuttering when changing scenes --- .../Components/TourneyVideo.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/osu.Game.Tournament/Components/TourneyVideo.cs b/osu.Game.Tournament/Components/TourneyVideo.cs index 4f4660f645..f28a2773b6 100644 --- a/osu.Game.Tournament/Components/TourneyVideo.cs +++ b/osu.Game.Tournament/Components/TourneyVideo.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Video; +using osu.Framework.Timing; using osu.Game.Graphics; namespace osu.Game.Tournament.Components @@ -15,6 +16,9 @@ namespace osu.Game.Tournament.Components { private readonly VideoSprite video; + private ManualClock manualClock; + private IFrameBasedClock sourceClock; + public TourneyVideo(Stream stream) { if (stream == null) @@ -41,5 +45,22 @@ namespace osu.Game.Tournament.Components video.Loop = value; } } + + protected override void LoadComplete() + { + base.LoadComplete(); + + sourceClock = Clock; + Clock = new FramedClock(manualClock = new ManualClock()); + } + + protected override void Update() + { + base.Update(); + + // we want to avoid seeking as much as possible, because we care about performance, not sync. + // to avoid seeking completely, we only increment out local clock when in an updating state. + manualClock.CurrentTime += sourceClock.ElapsedFrameTime; + } } } From a9b4106075614da8a60eae0afa3f30b85f7bf53d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 16:19:43 +0900 Subject: [PATCH 3891/5608] Remove unnecessary (for now) scheduling --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 592cddeff6..9c72a1a220 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -128,15 +128,13 @@ namespace osu.Game.Rulesets.Objects.Drawables } samplesBindable = HitObject.SamplesBindable.GetBoundCopy(); - samplesBindable.ItemsAdded += _ => scheduleLoadSamples(); - samplesBindable.ItemsRemoved += _ => scheduleLoadSamples(); + samplesBindable.ItemsAdded += _ => loadSamples(); + samplesBindable.ItemsRemoved += _ => loadSamples(); updateState(ArmedState.Idle, true); onDefaultsApplied(); } - private void scheduleLoadSamples() => Scheduler.AddOnce(loadSamples); - private void loadSamples() { var samples = GetSamples().ToArray(); From b4cb4c124366097b79239f267033eed6e7c3dffb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 16:19:55 +0900 Subject: [PATCH 3892/5608] Remove previous samples on change --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 9c72a1a220..818571bb23 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Objects.Drawables // Todo: Rulesets should be overriding the resources instead, but we need to figure out where/when to apply overrides first protected virtual string SampleNamespace => null; - protected SkinnableSound Samples; + protected SkinnableSound Samples { get; private set; } protected virtual IEnumerable GetSamples() => HitObject.Samples; @@ -137,6 +137,12 @@ namespace osu.Game.Rulesets.Objects.Drawables private void loadSamples() { + if (Samples != null) + { + RemoveInternal(Samples); + Samples = null; + } + var samples = GetSamples().ToArray(); if (samples.Length <= 0) From df08a95734e8184847a55210f2da9eed9a6c30f6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 16:46:58 +0900 Subject: [PATCH 3893/5608] Separate addition/removal into separate methods --- .../Compose/Components/SelectionHandler.cs | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 5f0bfb6d70..7b61640c89 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -185,6 +185,36 @@ namespace osu.Game.Screens.Edit.Compose.Components #endregion + #region Sample Changes + + /// + /// Adds a hit sample to all selected s. + /// + /// The name of the hit sample. + public void AddHitSample(string sampleName) + { + foreach (var h in SelectedHitObjects) + { + // Make sure there isn't already an existing sample + if (h.Samples.Any(s => s.Name == sampleName)) + continue; + + h.Samples.Add(new HitSampleInfo { Name = sampleName }); + } + } + + /// + /// Removes a hit sample from all selected s. + /// + /// The name of the hit sample. + public void RemoveHitSample(string sampleName) + { + foreach (var h in SelectedHitObjects) + h.SamplesBindable.RemoveAll(s => s.Name == sampleName); + } + + #endregion + #region Context Menu public virtual MenuItem[] ContextMenuItems @@ -221,21 +251,11 @@ namespace osu.Game.Screens.Edit.Compose.Components switch (state) { case ThreeStates.Disabled: - foreach (var h in SelectedHitObjects) - h.SamplesBindable.RemoveAll(s => s.Name == sampleName); - + RemoveHitSample(sampleName); break; case ThreeStates.Enabled: - foreach (var h in SelectedHitObjects) - { - // Make sure there isn't already an existing sample - if (h.Samples.Any(s => s.Name == sampleName)) - continue; - - h.Samples.Add(new HitSampleInfo { Name = sampleName }); - } - + AddHitSample(sampleName); break; } } From 8bcbc93501626e11d230532647f3dfff374121aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 17:00:47 +0900 Subject: [PATCH 3894/5608] Fix tournament buttons playing sound effects --- .../Screens/Drawings/DrawingsScreen.cs | 9 +++---- .../Screens/Editors/TeamEditorScreen.cs | 3 +-- .../Screens/Editors/TournamentEditorScreen.cs | 3 +-- .../Screens/Gameplay/GameplayScreen.cs | 4 +-- .../Screens/MapPool/MapPoolScreen.cs | 10 ++++---- osu.Game.Tournament/TournamentGameBase.cs | 3 +-- osu.Game.Tournament/TournamentSceneManager.cs | 25 +++++++++---------- osu.Game.Tournament/TourneyButton.cs | 15 +++++++++++ osu.Game/Graphics/UserInterface/OsuButton.cs | 6 +++-- 9 files changed, 45 insertions(+), 33 deletions(-) create mode 100644 osu.Game.Tournament/TourneyButton.cs diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 3a14b6d9c2..e8906466f3 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -15,7 +15,6 @@ using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Drawings.Components; @@ -128,21 +127,21 @@ namespace osu.Game.Tournament.Screens.Drawings // Control panel container new ControlPanel { - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Begin random", Action = teamsContainer.StartScrolling, }, - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Stop random", Action = teamsContainer.StopScrolling, }, - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, @@ -150,7 +149,7 @@ namespace osu.Game.Tournament.Screens.Drawings Action = reloadTeams }, new ControlPanel.Spacer(), - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index a4479f3cfd..e1f6d16623 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Settings; @@ -32,7 +31,7 @@ namespace osu.Game.Tournament.Screens.Editors [BackgroundDependencyLoader] private void load() { - ControlPanel.Add(new OsuButton + ControlPanel.Add(new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Add all countries", diff --git a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs index 50d3207345..32cf6bbcc8 100644 --- a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osuTK; @@ -56,7 +55,7 @@ namespace osu.Game.Tournament.Screens.Editors { Children = new Drawable[] { - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Add new", diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index b9a74bfe16..6a3095d42d 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -103,13 +103,13 @@ namespace osu.Game.Tournament.Screens.Gameplay { Children = new Drawable[] { - warmupButton = new OsuButton + warmupButton = new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Toggle warmup", Action = () => warmup.Toggle() }, - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Toggle chat", diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index ec55bb5b54..7a5fc2cd06 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -60,32 +60,32 @@ namespace osu.Game.Tournament.Screens.MapPool { Text = "Current Mode" }, - buttonRedBan = new OsuButton + buttonRedBan = new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Red Ban", Action = () => setMode(TeamColour.Red, ChoiceType.Ban) }, - buttonBlueBan = new OsuButton + buttonBlueBan = new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Blue Ban", Action = () => setMode(TeamColour.Blue, ChoiceType.Ban) }, - buttonRedPick = new OsuButton + buttonRedPick = new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Red Pick", Action = () => setMode(TeamColour.Red, ChoiceType.Pick) }, - buttonBluePick = new OsuButton + buttonBluePick = new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Blue Pick", Action = () => setMode(TeamColour.Blue, ChoiceType.Pick) }, new ControlPanel.Spacer(), - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Reset", diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 21552882ef..3b7718c61d 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -18,7 +18,6 @@ using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; @@ -76,7 +75,7 @@ namespace osu.Game.Tournament AddRange(new[] { - new OsuButton + new TourneyButton { Text = "Save Changes", Width = 140, diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 02ee1c8603..7164141dea 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Platform; -using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens; @@ -107,23 +106,23 @@ namespace osu.Game.Tournament Direction = FillDirection.Vertical, Children = new Drawable[] { - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Setup", Action = () => SetScreen(typeof(SetupScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Setup", Action = () => SetScreen(typeof(SetupScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Team Editor", Action = () => SetScreen(typeof(TeamEditorScreen)) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Rounds Editor", Action = () => SetScreen(typeof(RoundEditorScreen)) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Team Editor", Action = () => SetScreen(typeof(TeamEditorScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Rounds Editor", Action = () => SetScreen(typeof(RoundEditorScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => SetScreen(typeof(DrawingsScreen)) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => SetScreen(typeof(ShowcaseScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => SetScreen(typeof(DrawingsScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => SetScreen(typeof(ShowcaseScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Schedule", Action = () => SetScreen(typeof(ScheduleScreen)) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => SetScreen(typeof(LadderScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Schedule", Action = () => SetScreen(typeof(ScheduleScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => SetScreen(typeof(LadderScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => SetScreen(typeof(TeamIntroScreen)) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => SetScreen(typeof(MapPoolScreen)) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => SetScreen(typeof(GameplayScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => SetScreen(typeof(TeamIntroScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => SetScreen(typeof(MapPoolScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => SetScreen(typeof(GameplayScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Win", Action = () => SetScreen(typeof(TeamWinScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Win", Action = () => SetScreen(typeof(TeamWinScreen)) }, } }, }, diff --git a/osu.Game.Tournament/TourneyButton.cs b/osu.Game.Tournament/TourneyButton.cs new file mode 100644 index 0000000000..12872d3197 --- /dev/null +++ b/osu.Game.Tournament/TourneyButton.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 osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tournament +{ + public class TourneyButton : OsuButton + { + public TourneyButton() + : base(null) + { + } + } +} diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 2750e61f0d..c6a9aa1c97 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -48,7 +48,7 @@ namespace osu.Game.Graphics.UserInterface protected Box Background; protected SpriteText SpriteText; - public OsuButton() + public OsuButton(HoverSampleSet? hoverSounds = HoverSampleSet.Loud) { Height = 40; @@ -78,10 +78,12 @@ namespace osu.Game.Graphics.UserInterface Depth = float.MinValue }, SpriteText = CreateText(), - new HoverClickSounds(HoverSampleSet.Loud), } }); + if (hoverSounds.HasValue) + AddInternal(new HoverClickSounds(hoverSounds.Value)); + Enabled.BindValueChanged(enabledChanged, true); } From 380859e06e11137716ec7b2748214a58a213b0b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 17:13:45 +0900 Subject: [PATCH 3895/5608] Set clock on video directly; ignore long frames --- .../Components/TourneyVideo.cs | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tournament/Components/TourneyVideo.cs b/osu.Game.Tournament/Components/TourneyVideo.cs index f28a2773b6..8582b1634c 100644 --- a/osu.Game.Tournament/Components/TourneyVideo.cs +++ b/osu.Game.Tournament/Components/TourneyVideo.cs @@ -16,8 +16,7 @@ namespace osu.Game.Tournament.Components { private readonly VideoSprite video; - private ManualClock manualClock; - private IFrameBasedClock sourceClock; + private readonly ManualClock manualClock; public TourneyVideo(Stream stream) { @@ -34,6 +33,7 @@ namespace osu.Game.Tournament.Components { RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, + Clock = new FramedClock(manualClock = new ManualClock()) }; } @@ -46,21 +46,16 @@ namespace osu.Game.Tournament.Components } } - protected override void LoadComplete() - { - base.LoadComplete(); - - sourceClock = Clock; - Clock = new FramedClock(manualClock = new ManualClock()); - } - protected override void Update() { base.Update(); - // we want to avoid seeking as much as possible, because we care about performance, not sync. - // to avoid seeking completely, we only increment out local clock when in an updating state. - manualClock.CurrentTime += sourceClock.ElapsedFrameTime; + if (manualClock != null && Clock.ElapsedFrameTime < 100) + { + // we want to avoid seeking as much as possible, because we care about performance, not sync. + // to avoid seeking completely, we only increment out local clock when in an updating state. + manualClock.CurrentTime += Clock.ElapsedFrameTime; + } } } } From 651a1e2ae10fb5001aa0a7e7fa466fd0e429ca3e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 17:20:20 +0900 Subject: [PATCH 3896/5608] Highlight selected tournament screen's button --- osu.Game.Tournament/TournamentSceneManager.cs | 85 +++++++++++++++---- 1 file changed, 67 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 7164141dea..69248b6692 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Platform; +using osu.Game.Graphics; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens; @@ -35,6 +36,7 @@ namespace osu.Game.Tournament private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay(); private Container chatContainer; + private FillFlowContainer buttons; public TournamentSceneManager() { @@ -100,29 +102,32 @@ namespace osu.Game.Tournament Colour = Color4.Black, RelativeSizeAxes = Axes.Both, }, - new FillFlowContainer + buttons = new FillFlowContainer { RelativeSizeAxes = Axes.Both, Direction = FillDirection.Vertical, + Spacing = new Vector2(2), + Padding = new MarginPadding(2), Children = new Drawable[] { - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Setup", Action = () => SetScreen(typeof(SetupScreen)) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Team Editor", Action = () => SetScreen(typeof(TeamEditorScreen)) }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Rounds Editor", Action = () => SetScreen(typeof(RoundEditorScreen)) }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => SetScreen(typeof(DrawingsScreen)) }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => SetScreen(typeof(ShowcaseScreen)) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Schedule", Action = () => SetScreen(typeof(ScheduleScreen)) }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => SetScreen(typeof(LadderScreen)) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => SetScreen(typeof(TeamIntroScreen)) }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => SetScreen(typeof(MapPoolScreen)) }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => SetScreen(typeof(GameplayScreen)) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Win", Action = () => SetScreen(typeof(TeamWinScreen)) }, + new ScreenButton(typeof(SetupScreen)) { Text = "Setup", RequestSelection = SetScreen }, + new Separator(), + new ScreenButton(typeof(TeamEditorScreen)) { Text = "Team Editor", RequestSelection = SetScreen }, + new ScreenButton(typeof(RoundEditorScreen)) { Text = "Rounds Editor", RequestSelection = SetScreen }, + new ScreenButton(typeof(LadderEditorScreen)) { Text = "Bracket Editor", RequestSelection = SetScreen }, + new Separator(), + new ScreenButton(typeof(ScheduleScreen)) { Text = "Schedule", RequestSelection = SetScreen }, + new ScreenButton(typeof(LadderScreen)) { Text = "Bracket", RequestSelection = SetScreen }, + new Separator(), + new ScreenButton(typeof(TeamIntroScreen)) { Text = "TeamIntro", RequestSelection = SetScreen }, + new Separator(), + new ScreenButton(typeof(MapPoolScreen)) { Text = "MapPool", RequestSelection = SetScreen }, + new ScreenButton(typeof(GameplayScreen)) { Text = "Gameplay", RequestSelection = SetScreen }, + new Separator(), + new ScreenButton(typeof(TeamWinScreen)) { Text = "Win", RequestSelection = SetScreen }, + new Separator(), + new ScreenButton(typeof(DrawingsScreen)) { Text = "Drawings", RequestSelection = SetScreen }, + new ScreenButton(typeof(ShowcaseScreen)) { Text = "Showcase", RequestSelection = SetScreen }, } }, }, @@ -162,6 +167,50 @@ namespace osu.Game.Tournament chatContainer.FadeOut(100); break; } + + foreach (var s in buttons.OfType()) + s.IsSelected = screenType == s.Type; + } + + private class Separator : CompositeDrawable + { + public Separator() + { + RelativeSizeAxes = Axes.X; + Height = 20; + } + } + + private class ScreenButton : TourneyButton + { + public readonly Type Type; + + public ScreenButton(Type type) + { + Type = type; + BackgroundColour = OsuColour.Gray(0.2f); + Action = () => RequestSelection(type); + + RelativeSizeAxes = Axes.X; + } + + private bool isSelected; + + public Action RequestSelection; + + public bool IsSelected + { + get => isSelected; + set + { + if (value == isSelected) + return; + + isSelected = value; + BackgroundColour = isSelected ? Color4.SkyBlue : OsuColour.Gray(0.2f); + SpriteText.Colour = isSelected ? Color4.Black : Color4.White; + } + } } } } From eb9fff96bacec5ca553e0565336d11b9e341bd33 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 17:12:47 +0900 Subject: [PATCH 3897/5608] Read default beat divisor from beatmap --- osu.Game/Screens/Edit/Editor.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 35408e4003..97f01fd9f3 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -64,7 +64,10 @@ namespace osu.Game.Screens.Edit { this.host = host; - // TODO: should probably be done at a DrawableRuleset level to share logic with Player. + beatDivisor.Value = Beatmap.Value.BeatmapInfo.BeatDivisor; + beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue); + + // Todo: should probably be done at a DrawableRuleset level to share logic with Player. var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock(); clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); From 998e1dfe47aa0b1a2e05a63508194d0a831e208b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 17:23:47 +0900 Subject: [PATCH 3898/5608] Fix non-1/1 initial beat divisor control display --- .../Edit/Compose/Components/BeatDivisorControl.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 4d89e43ee5..9e4691e4dd 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -218,12 +218,17 @@ namespace osu.Game.Screens.Edit.Compose.Components } AddInternal(marker = new Marker()); + } - CurrentNumber.ValueChanged += div => + protected override void LoadComplete() + { + base.LoadComplete(); + + CurrentNumber.BindValueChanged(div => { marker.MoveToX(getMappedPosition(div.NewValue), 100, Easing.OutQuint); marker.Flash(); - }; + }, true); } protected override void UpdateValue(float value) From 36cc79f04f94c1c077fe8575a97e9b012f973d84 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 17:24:02 +0900 Subject: [PATCH 3899/5608] Softly handle invalid beat divisors instead of throwing --- osu.Game/Screens/Edit/BindableBeatDivisor.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index a724f354e7..ce95d81f54 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -29,7 +29,10 @@ namespace osu.Game.Screens.Edit set { if (!VALID_DIVISORS.Contains(value)) - throw new ArgumentOutOfRangeException($"Provided divisor is not in {nameof(VALID_DIVISORS)}"); + { + // If it doesn't match, value will be 0, but will be clamped to the valid range via DefaultMinValue + value = Array.FindLast(VALID_DIVISORS, d => d < value); + } base.Value = value; } From e90492831462e68adf09fa71203eb19e775d9f8e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 17:42:19 +0900 Subject: [PATCH 3900/5608] Seek to first hitobject when entering editor --- osu.Game/Screens/Edit/Editor.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 35408e4003..f932517387 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -69,6 +69,14 @@ namespace osu.Game.Screens.Edit clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); + if (Beatmap.Value.Beatmap.HitObjects.Count > 0) + { + double targetTime = Beatmap.Value.Beatmap.HitObjects[0].StartTime; + double beatLength = Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(targetTime).BeatLength; + + clock.Seek(Math.Max(0, targetTime - beatLength)); + } + dependencies.CacheAs(clock); dependencies.CacheAs(clock); dependencies.Cache(beatDivisor); From 7b8ed1ac9ad0567189d327670e37b3b4dd7ad26c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 17:26:24 +0900 Subject: [PATCH 3901/5608] Improve tournament screen transitions --- .../Screens/TournamentScreen.cs | 12 ++--- osu.Game.Tournament/TournamentSceneManager.cs | 54 +++++++++++++------ 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tournament/Screens/TournamentScreen.cs b/osu.Game.Tournament/Screens/TournamentScreen.cs index 9d58ca2240..0b5b3e728b 100644 --- a/osu.Game.Tournament/Screens/TournamentScreen.cs +++ b/osu.Game.Tournament/Screens/TournamentScreen.cs @@ -10,6 +10,8 @@ namespace osu.Game.Tournament.Screens { public abstract class TournamentScreen : CompositeDrawable { + public const double FADE_DELAY = 200; + [Resolved] protected LadderInfo LadderInfo { get; private set; } @@ -18,14 +20,8 @@ namespace osu.Game.Tournament.Screens RelativeSizeAxes = Axes.Both; } - public override void Hide() - { - this.FadeOut(200); - } + public override void Hide() => this.FadeOut(FADE_DELAY); - public override void Show() - { - this.FadeIn(200); - } + public override void Show() => this.FadeIn(FADE_DELAY); } } diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 02ee1c8603..d66f980202 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Platform; +using osu.Framework.Threading; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; @@ -130,37 +131,58 @@ namespace osu.Game.Tournament }, }; + foreach (var drawable in screens) + drawable.Hide(); + SetScreen(typeof(SetupScreen)); } + private float depth; + + private Drawable currentScreen; + private ScheduledDelegate scheduledHide; + public void SetScreen(Type screenType) { - var screen = screens.FirstOrDefault(s => s.GetType() == screenType); - if (screen == null) return; + var target = screens.FirstOrDefault(s => s.GetType() == screenType); - foreach (var s in screens.Children) + if (target == null || currentScreen == target) return; + + if (scheduledHide?.Completed == false) { - if (s == screen) - { - s.Show(); - if (s is IProvideVideo) - video.FadeOut(200); - else - video.Show(); - } - else - s.Hide(); + scheduledHide.RunTask(); + scheduledHide.Cancel(); // see https://github.com/ppy/osu-framework/issues/2967 + scheduledHide = null; } - switch (screen) + var lastScreen = currentScreen; + currentScreen = target; + + if (currentScreen is IProvideVideo) + { + video.FadeOut(200); + + // delay the hide to avoid a double-fade transition. + scheduledHide = Scheduler.AddDelayed(() => lastScreen?.Hide(), TournamentScreen.FADE_DELAY); + } + else + { + lastScreen?.Hide(); + video.Show(); + } + + screens.ChangeChildDepth(currentScreen, depth--); + currentScreen.Show(); + + switch (currentScreen) { case GameplayScreen _: case MapPoolScreen _: - chatContainer.FadeIn(100); + chatContainer.FadeIn(TournamentScreen.FADE_DELAY); break; default: - chatContainer.FadeOut(100); + chatContainer.FadeOut(TournamentScreen.FADE_DELAY); break; } } From 12b855d68feffd9b2053284de58d0c20c7bcdb36 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 17:56:11 +0900 Subject: [PATCH 3902/5608] Make drawing screen transition properly --- osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 3a14b6d9c2..f78124a66a 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -24,7 +24,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Drawings { - public class DrawingsScreen : CompositeDrawable + public class DrawingsScreen : TournamentScreen { private const string results_filename = "drawings_results.txt"; From a849bc074654a65d25500f14ade4cff330683ce0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 18:51:01 +0900 Subject: [PATCH 3903/5608] Move implementation into resetTrack for safety --- osu.Game/Screens/Edit/Editor.cs | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index f932517387..ca3b4fdce5 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -69,14 +69,6 @@ namespace osu.Game.Screens.Edit clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); - if (Beatmap.Value.Beatmap.HitObjects.Count > 0) - { - double targetTime = Beatmap.Value.Beatmap.HitObjects[0].StartTime; - double beatLength = Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(targetTime).BeatLength; - - clock.Seek(Math.Max(0, targetTime - beatLength)); - } - dependencies.CacheAs(clock); dependencies.CacheAs(clock); dependencies.Cache(beatDivisor); @@ -249,7 +241,8 @@ namespace osu.Game.Screens.Edit base.OnEntering(last); Background.FadeColour(Color4.DarkGray, 500); - resetTrack(); + + resetTrack(true); } public override bool OnExiting(IScreen next) @@ -260,10 +253,24 @@ namespace osu.Game.Screens.Edit return base.OnExiting(next); } - private void resetTrack() + private void resetTrack(bool seekToStart = false) { Beatmap.Value.Track?.ResetSpeedAdjustments(); Beatmap.Value.Track?.Stop(); + + if (seekToStart) + { + double targetTime = 0; + + if (Beatmap.Value.Beatmap.HitObjects.Count > 0) + { + // seek to one beat length before the first hitobject + targetTime = Beatmap.Value.Beatmap.HitObjects[0].StartTime; + targetTime -= Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(targetTime).BeatLength; + } + + clock.Seek(Math.Max(0, targetTime)); + } } private void exportBeatmap() => host.OpenFileExternally(Beatmap.Value.Save()); From 8ef9ccc39edf317f14a79b5bcb5a6fcc2ca091ea Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 8 Nov 2019 13:19:06 +0300 Subject: [PATCH 3904/5608] Schedule new track assignment after stopping current track --- osu.Game/Audio/PreviewTrackManager.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index fad2b5a5e8..08a69fa265 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -46,12 +46,18 @@ namespace osu.Game.Audio { var track = CreatePreviewTrack(beatmapSetInfo, trackStore); - track.Started += () => Schedule(() => + track.Started += () => { + // Stopping track should not be within the below schedule since its stop event schedules a null assign to current. + // Due to that, assigning the new track to current must be scheduled after the null assign to avoid current track loss. current?.Stop(); - current = track; - audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); - }); + + Schedule(() => + { + current = track; + audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); + }); + }; track.Stopped += () => Schedule(() => { From 901a8d597b81617c7032e9a16cbd57c5b0181511 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 8 Nov 2019 13:20:02 +0300 Subject: [PATCH 3905/5608] Add test steps ensuring correct behaviour --- .../Visual/Components/TestScenePreviewTrackManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index f3f6444149..7d46958496 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -59,6 +59,9 @@ namespace osu.Game.Tests.Visual.Components AddStep("start track 2", () => track2.Start()); AddAssert("track 1 stopped", () => !track1.IsRunning); AddAssert("track 2 started", () => track2.IsRunning); + AddStep("start track 1", () => track1.Start()); + AddAssert("track 2 stopped", () => !track2.IsRunning); + AddAssert("track 1 started", () => track1.IsRunning); } [Test] From c280f1ab0826ae9b1fe3768ca9b8450d5d98d42f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 19:35:55 +0900 Subject: [PATCH 3906/5608] Fix incorrect DI usage in some tournament screen tests --- .../Screens/TestSceneTeamIntroScreen.cs | 5 ++--- osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs index 3d340e393c..e36b594ff2 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs @@ -3,7 +3,6 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.TeamIntro; @@ -13,7 +12,7 @@ namespace osu.Game.Tournament.Tests.Screens public class TestSceneTeamIntroScreen : LadderTestScene { [Cached] - private readonly Bindable currentMatch = new Bindable(); + private readonly LadderInfo ladder = new LadderInfo(); [BackgroundDependencyLoader] private void load() @@ -22,7 +21,7 @@ namespace osu.Game.Tournament.Tests.Screens match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA"); match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN"); match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals"); - currentMatch.Value = match; + ladder.CurrentMatch.Value = match; Add(new TeamIntroScreen { diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs index 6f5e17a36e..5cb35a506f 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs @@ -3,7 +3,6 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.TeamWin; @@ -13,7 +12,7 @@ namespace osu.Game.Tournament.Tests.Screens public class TestSceneTeamWinScreen : LadderTestScene { [Cached] - private readonly Bindable currentMatch = new Bindable(); + private readonly LadderInfo ladder = new LadderInfo(); [BackgroundDependencyLoader] private void load() @@ -22,7 +21,7 @@ namespace osu.Game.Tournament.Tests.Screens match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA"); match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN"); match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals"); - currentMatch.Value = match; + ladder.CurrentMatch.Value = match; Add(new TeamWinScreen { From 97ea07db0e6ec5406f8b73cdc05618b8aad35793 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 19:44:47 +0900 Subject: [PATCH 3907/5608] Add delete option to the right-click menu --- .../Edit/Compose/Components/SelectionHandler.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 7b61640c89..9b7082dec5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -80,8 +80,7 @@ namespace osu.Game.Screens.Edit.Compose.Components switch (action.ActionMethod) { case PlatformActionMethod.Delete: - foreach (var h in selectedBlueprints.ToList()) - placementHandler.Delete(h.DrawableObject.HitObject); + deleteSelected(); return true; } @@ -144,6 +143,12 @@ namespace osu.Game.Screens.Edit.Compose.Components UpdateVisibility(); } + private void deleteSelected() + { + foreach (var h in selectedBlueprints.ToList()) + placementHandler.Delete(h.DrawableObject.HitObject); + } + #endregion #region Outline Display @@ -234,7 +239,8 @@ namespace osu.Game.Screens.Edit.Compose.Components createHitSampleMenuItem("Clap", HitSampleInfo.HIT_CLAP), createHitSampleMenuItem("Finish", HitSampleInfo.HIT_FINISH) } - } + }, + new OsuMenuItem("Delete", MenuItemType.Destructive, deleteSelected), }; } } From 9ed8b3a125ec5b549d4d67e96775dd5d7b7897e6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 8 Nov 2019 21:15:24 +0800 Subject: [PATCH 3908/5608] Use original dotsettings, with word IOS added to dictionary. --- osu.sln.DotSettings | 829 ++++++++++++++++++++++---------------------- 1 file changed, 409 insertions(+), 420 deletions(-) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 0a65fad9df..eb9e3ffafb 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -125,7 +125,6 @@ WARNING WARNING WARNING - WARNING WARNING WARNING ERROR @@ -202,7 +201,6 @@ HINT HINT - HINT WARNING WARNING WARNING @@ -273,8 +271,6 @@ GC GL GLSL - 2D - 3D HID HUD ID @@ -291,400 +287,399 @@ RGB RNG SHA - RGB SRGB TK - SS - PP - GMT - QAT - BNG + SS + PP + GMT + QAT + BNG UI False HINT <?xml version="1.0" encoding="utf-16"?> <Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> - <TypePattern DisplayName="COM interfaces or structs"> - <TypePattern.Match> - <Or> - <And> - <Kind Is="Interface" /> - <Or> - <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> - <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> - </Or> - </And> - <Kind Is="Struct" /> - </Or> - </TypePattern.Match> - </TypePattern> - <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> - <TypePattern.Match> - <And> - <Kind Is="Class" /> - <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> - </And> - </TypePattern.Match> - <Entry DisplayName="Setup/Teardown Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <Or> - <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="All other members" /> - <Entry Priority="100" DisplayName="Test Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <HasAttribute Name="NUnit.Framework.TestAttribute" /> - </And> - </Entry.Match> - <Entry.SortBy> - <Name /> - </Entry.SortBy> - </Entry> - </TypePattern> - <TypePattern DisplayName="Default Pattern"> - <Group DisplayName="Fields/Properties"> - <Group DisplayName="Public Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Public Properties"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Internal Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Internal Properties"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Protected Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Protected Properties"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Private Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Private Properties"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Constructor/Destructor"> - <Entry DisplayName="Ctor"> - <Entry.Match> - <Kind Is="Constructor" /> - </Entry.Match> - </Entry> - <Region Name="Disposal"> - <Entry DisplayName="Dtor"> - <Entry.Match> - <Kind Is="Destructor" /> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose()"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose(true)"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Virtual /> - <Override /> - </Or> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - </Region> - </Group> - <Group DisplayName="Methods"> - <Group DisplayName="Public"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Internal"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Protected"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Private"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - </Group> - </TypePattern> + <TypePattern DisplayName="COM interfaces or structs"> + <TypePattern.Match> + <Or> + <And> + <Kind Is="Interface" /> + <Or> + <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> + <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> + </Or> + </And> + <Kind Is="Struct" /> + </Or> + </TypePattern.Match> + </TypePattern> + <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> + <TypePattern.Match> + <And> + <Kind Is="Class" /> + <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> + </And> + </TypePattern.Match> + <Entry DisplayName="Setup/Teardown Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <Or> + <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="All other members" /> + <Entry Priority="100" DisplayName="Test Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <HasAttribute Name="NUnit.Framework.TestAttribute" /> + </And> + </Entry.Match> + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + </TypePattern> + <TypePattern DisplayName="Default Pattern"> + <Group DisplayName="Fields/Properties"> + <Group DisplayName="Public Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Public Properties"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Internal Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Internal Properties"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Protected Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Protected Properties"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Private Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Private Properties"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Constructor/Destructor"> + <Entry DisplayName="Ctor"> + <Entry.Match> + <Kind Is="Constructor" /> + </Entry.Match> + </Entry> + <Region Name="Disposal"> + <Entry DisplayName="Dtor"> + <Entry.Match> + <Kind Is="Destructor" /> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose()"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose(true)"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Virtual /> + <Override /> + </Or> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + </Region> + </Group> + <Group DisplayName="Methods"> + <Group DisplayName="Public"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Internal"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Protected"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Private"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + </Group> + </TypePattern> </Patterns> Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. See the LICENCE file in the repository root for full licence text. @@ -744,7 +739,6 @@ See the LICENCE file in the repository root for full licence text. <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - True True True @@ -780,7 +774,7 @@ Origin = Anchor.$anchor$, True InternalChildren = new Drawable[] { - $END$ + $END$ }; True True @@ -793,12 +787,12 @@ Origin = Anchor.$anchor$, True new GridContainer { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { $END$ }, - new Drawable[] { } - } + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { $END$ }, + new Drawable[] { } + } }; True True @@ -811,12 +805,12 @@ Origin = Anchor.$anchor$, True new FillFlowContainer { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - $END$ - } + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + $END$ + } }, True True @@ -829,11 +823,11 @@ Origin = Anchor.$anchor$, True new Container { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - $END$ - } + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + $END$ + } }, True True @@ -847,7 +841,7 @@ Origin = Anchor.$anchor$, [BackgroundDependencyLoader] private void load() { - $END$ + $END$ } True True @@ -860,8 +854,8 @@ private void load() True new Box { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, }, True True @@ -874,9 +868,8 @@ private void load() True Children = new Drawable[] { - $END$ + $END$ }; - True True True True @@ -894,8 +887,4 @@ private void load() True True True - True - True - True - True - True + True From a0f58ba9c47da15216ee769b9483d01c40d38f42 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 8 Nov 2019 21:17:59 +0800 Subject: [PATCH 3909/5608] Add missing project to iOS filter. --- osu.iOS.slnf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.iOS.slnf b/osu.iOS.slnf index 33a1497a54..48b1a095a1 100644 --- a/osu.iOS.slnf +++ b/osu.iOS.slnf @@ -12,7 +12,8 @@ "osu.Game.Rulesets.Taiko\\osu.Game.Rulesets.Taiko.csproj", "osu.Game.Tests.iOS\\osu.Game.Tests.iOS.csproj", "osu.Game.Tests\\osu.Game.Tests.csproj", - "osu.Game\\osu.Game.csproj" + "osu.Game\\osu.Game.csproj", + "osu.iOS\\osu.iOS.csproj" ] } } \ No newline at end of file From ff225c3691312bbb9d79bbc733c5ed760d5c9b25 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 8 Nov 2019 06:04:18 -0800 Subject: [PATCH 3910/5608] Remove toolbarElements --- osu.Game/OsuGame.cs | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 3980390611..145b7de9f2 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -102,8 +102,6 @@ namespace osu.Game private readonly List overlays = new List(); - private readonly List toolbarElements = new List(); - private readonly List visibleBlockingOverlays = new List(); public OsuGame(string[] args = null) @@ -134,17 +132,13 @@ namespace osu.Game /// /// Close all game-wide overlays. /// - /// Whether the toolbar (and accompanying controls) should also be hidden. - public void CloseAllOverlays(bool hideToolbarElements = true) + /// Whether the toolbar should also be hidden. + public void CloseAllOverlays(bool hideToolbar = true) { foreach (var overlay in overlays) overlay.Hide(); - if (hideToolbarElements) - { - foreach (var overlay in toolbarElements) - overlay.Hide(); - } + if (hideToolbar) Toolbar.Hide(); } private DependencyContainer dependencies; @@ -570,11 +564,7 @@ namespace osu.Game CloseAllOverlays(false); menuScreen?.MakeCurrent(); }, - }, d => - { - topMostOverlayContent.Add(d); - toolbarElements.Add(d); - }); + }, topMostOverlayContent.Add); loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add, true); @@ -613,11 +603,7 @@ namespace osu.Game GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - }, d => - { - rightFloatingOverlayContent.Add(d); - toolbarElements.Add(d); - }, true); + }, rightFloatingOverlayContent.Add, true); loadComponentSingleFile(new AccountCreationOverlay(), topMostOverlayContent.Add, true); loadComponentSingleFile(new DialogOverlay(), topMostOverlayContent.Add, true); From 2dd514012aa945d5f1d077b77c3cd0e6e9dc45e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 23:28:22 +0900 Subject: [PATCH 3911/5608] 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 d1860acbf9..7bfc27109f 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index dbe6559c40..a646fc01d1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 4010ef1d74..e3a49ea1b3 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From b675024161746b0f77d89a974f7ac905196e98d1 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 8 Nov 2019 20:28:24 -0800 Subject: [PATCH 3912/5608] Remove horizontal padding on toolbar ruleset selector --- osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 2c79f5bc0e..8f2dbce6f7 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -18,8 +18,6 @@ namespace osu.Game.Overlays.Toolbar { public class ToolbarRulesetSelector : RulesetSelector { - private const float padding = 10; - protected Drawable ModeButtonLine { get; private set; } public ToolbarRulesetSelector() @@ -39,7 +37,7 @@ namespace osu.Game.Overlays.Toolbar }, ModeButtonLine = new Container { - Size = new Vector2(padding * 2 + ToolbarButton.WIDTH, 3), + Size = new Vector2(ToolbarButton.WIDTH, 3), Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft, Masking = true, @@ -91,7 +89,6 @@ namespace osu.Game.Overlays.Toolbar RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, Direction = FillDirection.Horizontal, - Padding = new MarginPadding { Left = padding, Right = padding }, }; protected override bool OnKeyDown(KeyDownEvent e) From 5c476416080276e01a7000b1644ea35170693672 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 9 Nov 2019 16:23:22 +0900 Subject: [PATCH 3913/5608] Reorder conditional --- osu.Game/Overlays/Comments/VotePill.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index a5a19f5111..ab35a477aa 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Comments AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; hoverLayer.Colour = Color4.Black.Opacity(0.5f); - if (api.LocalUser.Value.Id != comment.UserId && api.IsLoggedIn) + if (api.IsLoggedIn && api.LocalUser.Value.Id != comment.UserId) Action = onAction; } From 20ed6c4d520444955e7fa690a9e06b6d1391ef9e Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 10 Nov 2019 23:07:51 +0300 Subject: [PATCH 3914/5608] Use track check solution for this --- osu.Game/Audio/PreviewTrackManager.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 08a69fa265..f104dc8f9f 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -46,21 +46,20 @@ namespace osu.Game.Audio { var track = CreatePreviewTrack(beatmapSetInfo, trackStore); - track.Started += () => + track.Started += () => Schedule(() => { - // Stopping track should not be within the below schedule since its stop event schedules a null assign to current. - // Due to that, assigning the new track to current must be scheduled after the null assign to avoid current track loss. - current?.Stop(); + var last = current; + current = track; + last?.Stop(); - Schedule(() => - { - current = track; - audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); - }); - }; + audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); + }); track.Stopped += () => Schedule(() => { + if (current != track) + return; + current = null; audio.Tracks.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); }); From 9d61d73cedf9088af374f18f1018f7e32f64b3cd Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 10 Nov 2019 23:09:04 +0300 Subject: [PATCH 3915/5608] Change Track and TrackManagerPreviewTrack accessibilities --- osu.Game/Audio/PreviewTrack.cs | 25 +++++++++++++------------ osu.Game/Audio/PreviewTrackManager.cs | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 1234554e79..b39d2bc8f8 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -24,36 +24,37 @@ namespace osu.Game.Audio /// public event Action Started; - private Track track; + protected Track Track; + private bool hasStarted; [BackgroundDependencyLoader] private void load() { - track = GetTrack(); - if (track != null) - track.Completed += Stop; + Track = GetTrack(); + if (Track != null) + Track.Completed += Stop; } /// /// Length of the track. /// - public double Length => track?.Length ?? 0; + public double Length => Track?.Length ?? 0; /// /// The current track time. /// - public double CurrentTime => track?.CurrentTime ?? 0; + public double CurrentTime => Track?.CurrentTime ?? 0; /// /// Whether the track is loaded. /// - public bool TrackLoaded => track?.IsLoaded ?? false; + public bool TrackLoaded => Track?.IsLoaded ?? false; /// /// Whether the track is playing. /// - public bool IsRunning => track?.IsRunning ?? false; + public bool IsRunning => Track?.IsRunning ?? false; private ScheduledDelegate startDelegate; @@ -63,7 +64,7 @@ namespace osu.Game.Audio /// Whether the track is started or already playing. public bool Start() { - if (track == null) + if (Track == null) return false; startDelegate = Schedule(() => @@ -73,7 +74,7 @@ namespace osu.Game.Audio hasStarted = true; - track.Restart(); + Track.Restart(); Started?.Invoke(); }); @@ -87,7 +88,7 @@ namespace osu.Game.Audio { startDelegate?.Cancel(); - if (track == null) + if (Track == null) return; if (!hasStarted) @@ -95,7 +96,7 @@ namespace osu.Game.Audio hasStarted = false; - track.Stop(); + Track.Stop(); Stopped?.Invoke(); } diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index f104dc8f9f..1c1b4c3059 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -90,7 +90,7 @@ namespace osu.Game.Audio /// protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TrackManagerPreviewTrack(beatmapSetInfo, trackStore); - protected class TrackManagerPreviewTrack : PreviewTrack + public class TrackManagerPreviewTrack : PreviewTrack { public IPreviewTrackOwner Owner { get; private set; } From 9a00898c0d3dae94f922782fc3eebc871959d04b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 10 Nov 2019 23:21:46 +0300 Subject: [PATCH 3916/5608] Add test for non-present preview tracks To avoid reverting what #6738 solved --- .../TestScenePreviewTrackManager.cs | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 7d46958496..3a9fce90cd 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -7,6 +7,7 @@ using osu.Framework.Audio.Track; using osu.Framework.Graphics.Containers; using osu.Game.Audio; using osu.Game.Beatmaps; +using static osu.Game.Tests.Visual.Components.TestScenePreviewTrackManager.TestPreviewTrackManager; namespace osu.Game.Tests.Visual.Components { @@ -91,9 +92,25 @@ namespace osu.Game.Tests.Visual.Components AddAssert("stopped", () => !track.IsRunning); } - private PreviewTrack getTrack() => trackManager.Get(null); + [Test] + public void TestNonPresentTrack() + { + TestPreviewTrack track = null; - private PreviewTrack getOwnedTrack() + AddStep("get non-present track", () => + { + Add(new TestTrackOwner(track = getTrack())); + track.Alpha = 0; + }); + AddUntilStep("wait loaded", () => track.IsLoaded); + AddStep("start", () => track.Start()); + AddStep("seek to end", () => track.Track.Seek(track.Track.Length)); + AddAssert("track stopped", () => !track.IsRunning); + } + + private TestPreviewTrack getTrack() => (TestPreviewTrack)trackManager.Get(null); + + private TestPreviewTrack getOwnedTrack() { var track = getTrack(); @@ -125,14 +142,16 @@ namespace osu.Game.Tests.Visual.Components } } - private class TestPreviewTrackManager : PreviewTrackManager + public class TestPreviewTrackManager : PreviewTrackManager { protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore); - protected class TestPreviewTrack : TrackManagerPreviewTrack + public class TestPreviewTrack : TrackManagerPreviewTrack { private readonly ITrackStore trackManager; + public new Track Track => base.Track; + public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackManager) : base(beatmapSetInfo, trackManager) { From 8f4916ad2d7fee51b0c28acad32a89fdf6c8f3ec Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 10 Nov 2019 23:53:31 +0300 Subject: [PATCH 3917/5608] Add inline comment --- osu.Game/Audio/PreviewTrackManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 1c1b4c3059..8f723194e3 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -48,6 +48,7 @@ namespace osu.Game.Audio track.Started += () => Schedule(() => { + // Assign the new track to current before stopping last track to avoid assigning null to current. var last = current; current = track; last?.Stop(); From 93954c8da0996307f277473bf4ac894d97d06395 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 10 Nov 2019 23:58:07 +0300 Subject: [PATCH 3918/5608] Use BindableList for selected mods --- .../Online/TestSceneLeaderboardModSelector.cs | 31 +++++++++++++------ .../BeatmapSet/LeaderboardModSelector.cs | 20 +++++------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index 3a64ac79f6..799528220b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Bindables; using osu.Game.Rulesets; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Tests.Visual.Online { @@ -26,10 +27,10 @@ namespace osu.Game.Tests.Visual.Online public TestSceneLeaderboardModSelector() { LeaderboardModSelector modSelector; - FillFlowContainer selectedMods; + FillFlowContainer selectedMods; Bindable ruleset = new Bindable(); - Add(selectedMods = new FillFlowContainer + Add(selectedMods = new FillFlowContainer { Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, @@ -42,16 +43,28 @@ namespace osu.Game.Tests.Visual.Online Ruleset = { BindTarget = ruleset } }); - modSelector.SelectedMods.BindValueChanged(mods => + modSelector.SelectedMods.ItemsAdded += mods => { - selectedMods.Clear(); + mods.ForEach(mod => selectedMods.Add(new SpriteText + { + Text = mod.Acronym, + })); + }; - foreach (var mod in mods.NewValue) - selectedMods.Add(new SpriteText + modSelector.SelectedMods.ItemsRemoved += mods => + { + mods.ForEach(mod => + { + foreach (var selected in selectedMods) { - Text = mod.Acronym, - }); - }); + if (selected.Text == mod.Acronym) + { + selectedMods.Remove(selected); + break; + } + } + }); + }; AddStep("osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo); AddStep("mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo); diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 4b6fd5bfc2..75c24cb710 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Rulesets.Mods; using osu.Framework.Bindables; -using System.Collections.Generic; using osu.Game.Rulesets; using osuTK; using osu.Game.Rulesets.UI; @@ -21,7 +20,7 @@ namespace osu.Game.Overlays.BeatmapSet { public class LeaderboardModSelector : CompositeDrawable { - public readonly Bindable> SelectedMods = new Bindable>(); + public readonly BindableList SelectedMods = new BindableList(); public readonly Bindable Ruleset = new Bindable(); private readonly FillFlowContainer modsContainer; @@ -47,8 +46,7 @@ namespace osu.Game.Overlays.BeatmapSet private void onRulesetChanged(ValueChangedEvent ruleset) { - SelectedMods.Value = new List(); - + SelectedMods.Clear(); modsContainer.Clear(); if (ruleset.NewValue == null) @@ -67,22 +65,18 @@ namespace osu.Game.Overlays.BeatmapSet private void selectionChanged(Mod mod, bool selected) { - var mods = SelectedMods.Value.ToList(); - if (selected) - mods.Add(mod); + SelectedMods.Add(mod); else - mods.Remove(mod); + SelectedMods.Remove(mod); - SelectedMods.Value = mods; - - if (!mods.Any() && !IsHovered) + if (!SelectedMods.Any() && !IsHovered) highlightAll(); } protected override bool OnHover(HoverEvent e) { - if (!SelectedMods.Value.Any()) + if (!SelectedMods.Any()) modsContainer.ForEach(button => { if (!button.IsHovered) @@ -96,7 +90,7 @@ namespace osu.Game.Overlays.BeatmapSet { base.OnHoverLost(e); - if (!SelectedMods.Value.Any()) + if (!SelectedMods.Any()) highlightAll(); } From 5e70e1e53f6c3be0cf4eb0348095cb78e712682f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 11:31:42 +0900 Subject: [PATCH 3919/5608] Update .gitignore --- .gitignore | 100 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index e60058ab35..e6b5db5904 100644 --- a/.gitignore +++ b/.gitignore @@ -10,14 +10,8 @@ # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs -### Cake ### -tools/** -build/tools/** - -fastlane/report.xml - # Build results -bin/[Dd]ebug/ +[Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ @@ -104,7 +98,6 @@ $tf/ _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user -inspectcode # JustCode is a .NET coding add-in .JustCode @@ -254,20 +247,87 @@ paket-files/ # FAKE - F# Make .fake/ -# JetBrains Rider -.idea/.idea.osu/.idea/*.xml -.idea/.idea.osu/.idea/codeStyles/*.xml -.idea/.idea.osu/.idea/dataSources/*.xml -.idea/.idea.osu/.idea/dictionaries/*.xml -.idea/.idea.osu/*.iml -*.sln.iml - -# CodeRush -.cr/ - # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc -Staging/ +# Cake # +/tools/** +/build/tools/** +/build/temp/** + +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +.idea/modules.xml +.idea/*.iml +.idea/modules +*.iml +*.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +# fastlane +fastlane/report.xml + +# inspectcode inspectcodereport.xml +inspectcode From 93f1c3c1520c95ecd7494e36bbdbc9fd4f50bbc3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 11:31:55 +0900 Subject: [PATCH 3920/5608] Update rider configurations --- .idea/.gitignore | 0 .idea/.idea.osu.Desktop/.idea/.name | 1 + .../.idea/codeStyles/codeStyleConfig.xml | 5 +++++ .idea/.idea.osu.Desktop/.idea/dataSources.xml | 14 ++++++++++++++ .idea/.idea.osu.Desktop/.idea/encodings.xml | 4 ++++ .idea/.idea.osu.Desktop/.idea/indexLayout.xml | 8 ++++++++ .idea/.idea.osu.Desktop/.idea/misc.xml | 6 ++++++ .idea/.idea.osu.Desktop/.idea/modules.xml | 8 ++++++++ .../.idea/projectSettingsUpdater.xml | 6 ++++++ .../runConfigurations/CatchRuleset__Tests_.xml | 0 .../runConfigurations/ManiaRuleset__Tests_.xml | 0 .../runConfigurations/OsuRuleset__Tests_.xml | 0 .../runConfigurations/TaikoRuleset__Tests_.xml | 0 .../.idea/runConfigurations/Tournament.xml | 0 .../runConfigurations/Tournament__Tests_.xml | 0 .../.idea/runConfigurations/osu_.xml | 0 .../.idea/runConfigurations/osu___Tests_.xml | 0 .idea/.idea.osu.Desktop/.idea/vcs.xml | 16 ++++++++++++++++ .idea/.idea.osu/.idea/indexLayout.xml | 8 ++++++++ .idea/.idea.osu/.idea/modules.xml | 8 ++++++++ .idea/.idea.osu/.idea/projectSettingsUpdater.xml | 6 ++++++ .idea/.idea.osu/.idea/vcs.xml | 6 ++++++ 22 files changed, 96 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/.idea.osu.Desktop/.idea/.name create mode 100644 .idea/.idea.osu.Desktop/.idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/.idea.osu.Desktop/.idea/dataSources.xml create mode 100644 .idea/.idea.osu.Desktop/.idea/encodings.xml create mode 100644 .idea/.idea.osu.Desktop/.idea/indexLayout.xml create mode 100644 .idea/.idea.osu.Desktop/.idea/misc.xml create mode 100644 .idea/.idea.osu.Desktop/.idea/modules.xml create mode 100644 .idea/.idea.osu.Desktop/.idea/projectSettingsUpdater.xml rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/CatchRuleset__Tests_.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/ManiaRuleset__Tests_.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/OsuRuleset__Tests_.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/TaikoRuleset__Tests_.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/Tournament.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/Tournament__Tests_.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/osu_.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/osu___Tests_.xml (100%) create mode 100644 .idea/.idea.osu.Desktop/.idea/vcs.xml create mode 100644 .idea/.idea.osu/.idea/indexLayout.xml create mode 100644 .idea/.idea.osu/.idea/modules.xml create mode 100644 .idea/.idea.osu/.idea/projectSettingsUpdater.xml create mode 100644 .idea/.idea.osu/.idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.idea/.idea.osu.Desktop/.idea/.name b/.idea/.idea.osu.Desktop/.idea/.name new file mode 100644 index 0000000000..12bf4aebba --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/.name @@ -0,0 +1 @@ +osu.Desktop \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/codeStyles/codeStyleConfig.xml b/.idea/.idea.osu.Desktop/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000000..a55e7a179b --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/dataSources.xml b/.idea/.idea.osu.Desktop/.idea/dataSources.xml new file mode 100644 index 0000000000..10f8c1c84d --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/dataSources.xml @@ -0,0 +1,14 @@ + + + + + sqlite.xerial + true + org.sqlite.JDBC + jdbc:sqlite:$USER_HOME$/.local/share/osu/client.db + + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/encodings.xml b/.idea/.idea.osu.Desktop/.idea/encodings.xml new file mode 100644 index 0000000000..15a15b218a --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/indexLayout.xml b/.idea/.idea.osu.Desktop/.idea/indexLayout.xml new file mode 100644 index 0000000000..27ba142e96 --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/misc.xml b/.idea/.idea.osu.Desktop/.idea/misc.xml new file mode 100644 index 0000000000..1d8c84d0af --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/modules.xml b/.idea/.idea.osu.Desktop/.idea/modules.xml new file mode 100644 index 0000000000..fe63f5faf3 --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/projectSettingsUpdater.xml b/.idea/.idea.osu.Desktop/.idea/projectSettingsUpdater.xml new file mode 100644 index 0000000000..7515e76054 --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/projectSettingsUpdater.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/runConfigurations/CatchRuleset__Tests_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/CatchRuleset__Tests_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/CatchRuleset__Tests_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/CatchRuleset__Tests_.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/ManiaRuleset__Tests_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/ManiaRuleset__Tests_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/ManiaRuleset__Tests_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/ManiaRuleset__Tests_.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/OsuRuleset__Tests_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/OsuRuleset__Tests_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/OsuRuleset__Tests_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/OsuRuleset__Tests_.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/TaikoRuleset__Tests_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/TaikoRuleset__Tests_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/TaikoRuleset__Tests_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/TaikoRuleset__Tests_.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/Tournament.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/Tournament.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/Tournament.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/Tournament.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/Tournament__Tests_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/Tournament__Tests_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/Tournament__Tests_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/Tournament__Tests_.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/osu_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/osu_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/osu_.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/osu___Tests_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu___Tests_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/osu___Tests_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/osu___Tests_.xml diff --git a/.idea/.idea.osu.Desktop/.idea/vcs.xml b/.idea/.idea.osu.Desktop/.idea/vcs.xml new file mode 100644 index 0000000000..3de04b744c --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/vcs.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/indexLayout.xml b/.idea/.idea.osu/.idea/indexLayout.xml new file mode 100644 index 0000000000..27ba142e96 --- /dev/null +++ b/.idea/.idea.osu/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/modules.xml b/.idea/.idea.osu/.idea/modules.xml new file mode 100644 index 0000000000..0360fdbc5e --- /dev/null +++ b/.idea/.idea.osu/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/projectSettingsUpdater.xml b/.idea/.idea.osu/.idea/projectSettingsUpdater.xml new file mode 100644 index 0000000000..7515e76054 --- /dev/null +++ b/.idea/.idea.osu/.idea/projectSettingsUpdater.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/vcs.xml b/.idea/.idea.osu/.idea/vcs.xml new file mode 100644 index 0000000000..94a25f7f4c --- /dev/null +++ b/.idea/.idea.osu/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From 990a82cd06593da8d7a4b6e30b24b26dc98d00ab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 11:32:06 +0900 Subject: [PATCH 3921/5608] Update readme --- README.md | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 1e2d539697..67eb3254e1 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,8 @@ git pull 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). -> Visual Studio Code users must run the `Restore` task before any build attempt. +- 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: @@ -69,18 +70,6 @@ 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`. -#### A note for Linux users - -On Linux, the environment variable `LD_LIBRARY_PATH` must point to the build directory, located at `osu.Desktop/bin/Debug/$NETCORE_VERSION`. - -`$NETCORE_VERSION` is the version of the targeted .NET Core SDK. You can check it by running `grep TargetFramework osu.Desktop/osu.Desktop.csproj | sed -r 's/.*>(.*)<\/.*/\1/'`. - -For example, you can run osu! with the following command: - -```shell -LD_LIBRARY_PATH="$(pwd)/osu.Desktop/bin/Debug/netcoreapp3.0" dotnet run --project osu.Desktop -``` - ### 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. From e924a5d51e0596ab003d07c38ee3417bacb431a4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Nov 2019 13:04:38 +0900 Subject: [PATCH 3922/5608] Disable ruleset input in the editor --- osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs index af565f8896..4710465536 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs @@ -64,6 +64,10 @@ namespace osu.Game.Rulesets.Edit drawableRuleset.Playfield.PostProcess(); } + public override bool PropagatePositionalInputSubTree => false; + + public override bool PropagateNonPositionalInputSubTree => false; + public PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => drawableRuleset.CreatePlayfieldAdjustmentContainer(); protected override void Dispose(bool isDisposing) From 3b13ad480af5afa7f0fe15c300a5e02bcf0fb4d7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Nov 2019 13:06:41 +0900 Subject: [PATCH 3923/5608] Increase fade-out time of hitobjects in the editor --- .../Edit/DrawableOsuEditRuleset.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs index cc08d356f9..e262fa3c60 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -2,8 +2,12 @@ // 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.Game.Beatmaps; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.UI; using osuTK; @@ -17,6 +21,25 @@ namespace osu.Game.Rulesets.Osu.Edit { } + public override DrawableHitObject CreateDrawableRepresentation(OsuHitObject h) + => base.CreateDrawableRepresentation(h)?.With(d => d.ApplyCustomUpdateState += updateState); + + private void updateState(DrawableHitObject hitObject, ArmedState state) + { + switch (state) + { + case ArmedState.Miss: + // Get the existing fade out transform + var existing = hitObject.Transforms.LastOrDefault(t => t.TargetMember == nameof(Alpha)); + if (existing == null) + return; + + using (hitObject.BeginAbsoluteSequence(existing.StartTime)) + hitObject.FadeOut(500).Expire(); + break; + } + } + protected override Playfield CreatePlayfield() => new OsuPlayfieldNoCursor(); public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new OsuPlayfieldAdjustmentContainer { Size = Vector2.One }; From f3dc38e3427f9c52364bcc11a8ea36d065b0934c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Nov 2019 13:41:10 +0900 Subject: [PATCH 3924/5608] Add Ctrl+A to select all (esc to deselect all) --- .../Compose/Components/BlueprintContainer.cs | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 8fa022f129..7528ac8aa6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Rulesets.Edit; @@ -17,10 +18,11 @@ using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osuTK; +using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components { - public class BlueprintContainer : CompositeDrawable + public class BlueprintContainer : CompositeDrawable, IKeyBindingHandler { public event Action> SelectionChanged; @@ -169,6 +171,37 @@ namespace osu.Game.Screens.Edit.Compose.Components return true; } + protected override bool OnKeyDown(KeyDownEvent e) + { + switch (e.Key) + { + case Key.Escape: + if (!selectionHandler.SelectedBlueprints.Any()) + return false; + + deselectAll(); + return true; + } + + return false; + } + + protected override bool OnKeyUp(KeyUpEvent e) => false; + + public bool OnPressed(PlatformAction action) + { + switch (action.ActionType) + { + case PlatformActionType.SelectAll: + selectAll(); + return true; + } + + return false; + } + + public bool OnReleased(PlatformAction action) => false; + protected override void Update() { base.Update(); @@ -314,6 +347,15 @@ namespace osu.Game.Screens.Edit.Compose.Components } } + /// + /// Selects all s. + /// + private void selectAll() + { + selectionBlueprints.ToList().ForEach(m => m.Select()); + selectionHandler.UpdateVisibility(); + } + /// /// Deselects all selected s. /// From dc88bd3d611a1a5c31c3768eb637725b6a6bf02d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 13:49:12 +0900 Subject: [PATCH 3925/5608] Add local preserving container to OsuTestScene to ensure correct test dimensions --- osu.Game/Tests/Visual/OsuTestScene.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 96b39b303e..daa1a56221 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -10,12 +10,16 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Database; +using osu.Game.Graphics.Containers; using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -93,6 +97,10 @@ namespace osu.Game.Tests.Visual return Dependencies; } + protected override Container Content => content ?? base.Content; + + private readonly Container content; + protected OsuTestScene() { localStorage = new Lazy(() => new NativeStorage($"{GetType().Name}-{Guid.NewGuid()}")); @@ -104,6 +112,8 @@ namespace osu.Game.Tests.Visual usage.Migrate(); return factory; }); + + base.Content.Add(content = new DrawSizePreservingFillContainer()); } [Resolved] From 8ac708ada5f44773ed593f02f5badd144d9a93f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 13:58:35 +0900 Subject: [PATCH 3926/5608] Move scaling container to OsuGame so OsuGameBase doesn't apply UI scale --- osu.Game/OsuGame.cs | 2 ++ osu.Game/OsuGameBase.cs | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 1f823e6eba..c375ccda81 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -393,6 +393,8 @@ namespace osu.Game protected virtual Loader CreateLoader() => new Loader(); + protected override Container CreateScalingContainer() => new ScalingContainer(ScalingMode.Everything); + #region Beatmap progression private void beatmapChanged(ValueChangedEvent beatmap) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 194a439b06..947df75783 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -26,7 +26,6 @@ using osu.Framework.Input; using osu.Framework.Logging; using osu.Game.Audio; using osu.Game.Database; -using osu.Game.Graphics.Containers; using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.IO; @@ -228,7 +227,7 @@ namespace osu.Game Child = content = new OsuTooltipContainer(MenuCursorContainer.Cursor) { RelativeSizeAxes = Axes.Both } }; - base.Content.Add(new ScalingContainer(ScalingMode.Everything) { Child = MenuCursorContainer }); + base.Content.Add(CreateScalingContainer().WithChild(MenuCursorContainer)); KeyBindingStore.Register(globalBinding); dependencies.Cache(globalBinding); @@ -238,6 +237,8 @@ namespace osu.Game Add(previewTrackManager); } + protected virtual Container CreateScalingContainer() => new DrawSizePreservingFillContainer(); + protected override void LoadComplete() { base.LoadComplete(); From 13fd95d513da835f427e59095b606ced479ff29b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 14:03:29 +0900 Subject: [PATCH 3927/5608] Remove misplaced usings --- osu.Game/Tests/Visual/OsuTestScene.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index daa1a56221..345fff90aa 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -17,9 +17,7 @@ using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Beatmaps; -using osu.Game.Configuration; using osu.Game.Database; -using osu.Game.Graphics.Containers; using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; From fced262c41859aa3fc01f3ffcb3eeded6610245e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 17:03:40 +0900 Subject: [PATCH 3928/5608] Add labelled dropdown component --- .../UserInterfaceV2/LabelledDropdown.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs new file mode 100644 index 0000000000..7e50fa7bc6 --- /dev/null +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs @@ -0,0 +1,29 @@ +// 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.Game.Graphics.UserInterface; + +namespace osu.Game.Graphics.UserInterfaceV2 +{ + public class LabelledDropdown : LabelledComponent, T> + { + public LabelledDropdown() + : base(true) + { + } + + public IEnumerable Items + { + get => Component.Items; + set => Component.Items = value; + } + + protected override OsuDropdown CreateComponent() => new OsuDropdown + { + RelativeSizeAxes = Axes.X, + Width = 0.5f, + }; + } +} From 702a1c496bd6e2a146dd5a7b2a82d42752f90e42 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 17:03:50 +0900 Subject: [PATCH 3929/5608] Add ruleset selection to tournament client --- osu.Game.Tournament/Models/LadderInfo.cs | 3 +++ osu.Game.Tournament/Screens/SetupScreen.cs | 13 ++++++++++++- osu.Game.Tournament/TournamentGameBase.cs | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Models/LadderInfo.cs b/osu.Game.Tournament/Models/LadderInfo.cs index 547c4eab08..5db0b01547 100644 --- a/osu.Game.Tournament/Models/LadderInfo.cs +++ b/osu.Game.Tournament/Models/LadderInfo.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; using osu.Framework.Bindables; +using osu.Game.Rulesets; namespace osu.Game.Tournament.Models { @@ -14,6 +15,8 @@ namespace osu.Game.Tournament.Models [Serializable] public class LadderInfo { + public Bindable Ruleset = new Bindable(); + public BindableList Matches = new BindableList(); public BindableList Rounds = new BindableList(); public BindableList Teams = new BindableList(); diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index a67daa2756..b511d572da 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -10,6 +10,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.API; using osu.Game.Overlays; +using osu.Game.Rulesets; using osu.Game.Tournament.IPC; using osuTK; using osuTK.Graphics; @@ -28,6 +29,9 @@ namespace osu.Game.Tournament.Screens [Resolved] private IAPIProvider api { get; set; } + [Resolved] + private RulesetStore rulesets { get; set; } + [BackgroundDependencyLoader] private void load() { @@ -85,7 +89,14 @@ namespace osu.Game.Tournament.Screens Value = api?.LocalUser.Value.Username, Failing = api?.IsLoggedIn != true, Description = "In order to access the API and display metadata, a login is required." - } + }, + new LabelledDropdown + { + Label = "Ruleset", + Description = "Decides what stats are displayed and which ranks are retrieved for players", + Items = rulesets.AvailableRulesets, + Current = LadderInfo.Ruleset, + }, }; } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 3b7718c61d..59edd18341 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -126,6 +126,8 @@ namespace osu.Game.Tournament ladder = new LadderInfo(); } + Ruleset.BindTo(ladder.Ruleset); + dependencies.Cache(ladder); bool addedInfo = false; From 5d96e6d90a30b85d27866d70ce9ff5f693247e0f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 17:39:48 +0900 Subject: [PATCH 3930/5608] Populate users centrally, using the correct ruleset --- .../Screens/Editors/TeamEditorScreen.cs | 26 +++------------ osu.Game.Tournament/TournamentGameBase.cs | 32 ++++++++++++++++--- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index e1f6d16623..11c2732d62 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; @@ -24,7 +23,7 @@ namespace osu.Game.Tournament.Screens.Editors public class TeamEditorScreen : TournamentEditorScreen { [Resolved] - private Framework.Game game { get; set; } + private TournamentGameBase game { get; set; } protected override BindableList Storage => LadderInfo.Teams; @@ -198,6 +197,9 @@ namespace osu.Game.Tournament.Screens.Editors [Resolved] protected IAPIProvider API { get; private set; } + [Resolved] + private TournamentGameBase game { get; set; } + private readonly Bindable userId = new Bindable(); private readonly Container drawableContainer; @@ -280,25 +282,7 @@ namespace osu.Game.Tournament.Screens.Editors return; } - var req = new GetUserRequest(user.Id); - - req.Success += res => - { - // TODO: this should be done in a better way. - user.Username = res.Username; - user.Country = res.Country; - user.Cover = res.Cover; - - updatePanel(); - }; - - req.Failure += _ => - { - user.Id = 1; - updatePanel(); - }; - - API.Queue(req); + game.PopulateUser(user, updatePanel, updatePanel); }, true); } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 59edd18341..b0ca099a86 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.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.Drawing; using System.IO; using System.Linq; @@ -21,11 +22,13 @@ using osu.Game.Graphics; using osu.Game.Online.API.Requests; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; +using osu.Game.Users; using osuTK.Graphics; using osuTK.Input; namespace osu.Game.Tournament { + [Cached(typeof(TournamentGameBase))] public abstract class TournamentGameBase : OsuGameBase { private const string bracket_filename = "bracket.json"; @@ -197,10 +200,7 @@ namespace osu.Game.Tournament foreach (var p in t.Players) if (string.IsNullOrEmpty(p.Username)) { - var req = new GetUserRequest(p.Id); - req.Perform(API); - p.Username = req.Result.Username; - + PopulateUser(p); addedInfo = true; } @@ -228,6 +228,30 @@ namespace osu.Game.Tournament return addedInfo; } + public void PopulateUser(User user, Action success = null, Action failure = null) + { + var req = new GetUserRequest(user.Id, Ruleset.Value); + + req.Success += res => + { + user.Username = res.Username; + user.Statistics = res.Statistics; + user.Username = res.Username; + user.Country = res.Country; + user.Cover = res.Cover; + + success?.Invoke(); + }; + + req.Failure += _ => + { + user.Id = 1; + failure?.Invoke(); + }; + + API.Queue(req); + } + protected override void LoadComplete() { MenuCursorContainer.Cursor.AlwaysPresent = true; // required for tooltip display From 6d3d7c5d95823d9915e197116e7f327dad54592b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 11 Nov 2019 11:57:14 +0300 Subject: [PATCH 3931/5608] Remove unnecessary use of local --- osu.Game/Audio/PreviewTrackManager.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 8f723194e3..72b33c4073 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -48,11 +48,8 @@ namespace osu.Game.Audio track.Started += () => Schedule(() => { - // Assign the new track to current before stopping last track to avoid assigning null to current. - var last = current; + current?.Stop(); current = track; - last?.Stop(); - audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); }); From a345fd8a86ef706aed8f004ccd1d380e5ee15495 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2019 09:26:56 +0000 Subject: [PATCH 3932/5608] Bump Newtonsoft.Json from 12.0.2 to 12.0.3 Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 12.0.2 to 12.0.3. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/12.0.2...12.0.3) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 42f746c286..baa1c14071 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -19,7 +19,7 @@ - + From ce4843be22ff62e95362da8a2f24530c1fb9b91c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 18:42:32 +0900 Subject: [PATCH 3933/5608] Move tests to parent namespace for now --- .../UserInterface/{MenuItems => }/TestSceneStatefulMenuItem.cs | 2 +- .../{MenuItems => }/TestSceneThreeStateMenuItem.cs | 2 +- .../UserInterface/{MenuItems => }/TestSceneToggleMenuItem.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{MenuItems => }/TestSceneStatefulMenuItem.cs (98%) rename osu.Game.Tests/Visual/UserInterface/{MenuItems => }/TestSceneThreeStateMenuItem.cs (95%) rename osu.Game.Tests/Visual/UserInterface/{MenuItems => }/TestSceneToggleMenuItem.cs (94%) diff --git a/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs similarity index 98% rename from osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneStatefulMenuItem.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index 95e9aea97f..fd30da39e6 100644 --- a/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual.UserInterface.MenuItems +namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneStatefulMenuItem : OsuTestScene { diff --git a/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneThreeStateMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs similarity index 95% rename from osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneThreeStateMenuItem.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs index e035e43630..caa07e7b60 100644 --- a/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneThreeStateMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual.UserInterface.MenuItems +namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneThreeStateMenuItem : OsuTestScene { diff --git a/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneToggleMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs similarity index 94% rename from osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneToggleMenuItem.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs index 92875740cf..2abda56a28 100644 --- a/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneToggleMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual.UserInterface.MenuItems +namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneToggleMenuItem : OsuTestScene { From bed62e0d2f2b62d19a76bfb051c04263900706c8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 18:56:18 +0900 Subject: [PATCH 3934/5608] Rename ThreeState -> TernaryState and add basic tests --- .../UserInterface/TestSceneTernaryMenuItem.cs | 65 +++++++++++++++++++ .../TestSceneThreeStateMenuItem.cs | 35 ---------- .../{ThreeStates.cs => TernaryState.cs} | 14 ++-- .../UserInterface/ThreeStateMenuItem.cs | 28 ++++---- 4 files changed, 86 insertions(+), 56 deletions(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs delete mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs rename osu.Game/Graphics/UserInterface/{ThreeStates.cs => TernaryState.cs} (56%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs new file mode 100644 index 0000000000..fdb8c330c5 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs @@ -0,0 +1,65 @@ +// 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.Bindables; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneTernaryMenuItem : ManualInputManagerTestScene + { + private readonly OsuMenu menu; + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuMenu), + typeof(ThreeStateMenuItem), + typeof(DrawableStatefulMenuItem) + }; + + private readonly Bindable state = new Bindable(TernaryState.Indeterminate); + + public TestSceneTernaryMenuItem() + { + Add(menu = new OsuMenu(Direction.Vertical, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new ThreeStateMenuItem("First"), + new ThreeStateMenuItem("Second") { State = { BindTarget = state } }, + new ThreeStateMenuItem("Third") { State = { Value = TernaryState.True } }, + } + }); + + checkState(TernaryState.Indeterminate); + + click(); + checkState(TernaryState.True); + + click(); + checkState(TernaryState.False); + + click(); + checkState(TernaryState.True); + + click(); + checkState(TernaryState.False); + } + + private void click() => + AddStep("click", () => + { + InputManager.MoveMouseTo(menu.ScreenSpaceDrawQuad.Centre); + InputManager.Click(MouseButton.Left); + }); + + private void checkState(TernaryState expected) + => AddAssert($"state is {expected}", () => state.Value == expected); + } +} diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs deleted file mode 100644 index caa07e7b60..0000000000 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterface; - -namespace osu.Game.Tests.Visual.UserInterface -{ - public class TestSceneThreeStateMenuItem : OsuTestScene - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(OsuMenu), - typeof(ThreeStateMenuItem), - typeof(DrawableStatefulMenuItem) - }; - - public TestSceneThreeStateMenuItem() - { - Add(new OsuMenu(Direction.Vertical, true) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Items = new[] - { - new ThreeStateMenuItem("First"), - new ThreeStateMenuItem("Second") { State = { Value = ThreeStates.Indeterminate } }, - new ThreeStateMenuItem("Third") { State = { Value = ThreeStates.Enabled } }, - } - }); - } - } -} diff --git a/osu.Game/Graphics/UserInterface/ThreeStates.cs b/osu.Game/Graphics/UserInterface/TernaryState.cs similarity index 56% rename from osu.Game/Graphics/UserInterface/ThreeStates.cs rename to osu.Game/Graphics/UserInterface/TernaryState.cs index f099250937..784122e35c 100644 --- a/osu.Game/Graphics/UserInterface/ThreeStates.cs +++ b/osu.Game/Graphics/UserInterface/TernaryState.cs @@ -6,22 +6,22 @@ namespace osu.Game.Graphics.UserInterface /// /// An on/off state with an extra indeterminate state. /// - public enum ThreeStates + public enum TernaryState { /// - /// The current state is disabled. + /// The current state is false. /// - Disabled, + False, /// - /// The current state is a combination of and . - /// The state becomes if the is pressed. + /// The current state is a combination of and . + /// The state becomes if the is pressed. /// Indeterminate, /// - /// The current state is enabled. + /// The current state is true. /// - Enabled + True } } diff --git a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs index ebb6436196..c5b9edf3c4 100644 --- a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs @@ -9,7 +9,7 @@ namespace osu.Game.Graphics.UserInterface /// /// An with three possible states. /// - public class ThreeStateMenuItem : StatefulMenuItem + public class ThreeStateMenuItem : StatefulMenuItem { /// /// Creates a new . @@ -27,7 +27,7 @@ namespace osu.Game.Graphics.UserInterface /// The text to display. /// The type of action which this performs. /// A delegate to be invoked when this is pressed. - public ThreeStateMenuItem(string text, MenuItemType type, Action action) + public ThreeStateMenuItem(string text, MenuItemType type, Action action) : this(text, getNextState, type, action) { } @@ -39,37 +39,37 @@ namespace osu.Game.Graphics.UserInterface /// A function that mutates a state to another state after this is pressed. /// The type of action which this performs. /// A delegate to be invoked when this is pressed. - protected ThreeStateMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) + protected ThreeStateMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) : base(text, changeStateFunc, type, action) { } - public override IconUsage? GetIconForState(ThreeStates state) + public override IconUsage? GetIconForState(TernaryState state) { switch (state) { - case ThreeStates.Indeterminate: - return FontAwesome.Regular.Circle; + case TernaryState.Indeterminate: + return FontAwesome.Solid.DotCircle; - case ThreeStates.Enabled: + case TernaryState.True: return FontAwesome.Solid.Check; } return null; } - private static ThreeStates getNextState(ThreeStates state) + private static TernaryState getNextState(TernaryState state) { switch (state) { - case ThreeStates.Disabled: - return ThreeStates.Enabled; + case TernaryState.False: + return TernaryState.True; - case ThreeStates.Indeterminate: - return ThreeStates.Enabled; + case TernaryState.Indeterminate: + return TernaryState.True; - case ThreeStates.Enabled: - return ThreeStates.Disabled; + case TernaryState.True: + return TernaryState.False; default: throw new ArgumentOutOfRangeException(nameof(state), state, null); From 82cc6aa0c5b2b251a229808b0a6494ba684a7cbb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 19:00:14 +0900 Subject: [PATCH 3935/5608] Remove unused constructor --- .../Visual/UserInterface/TestSceneStatefulMenuItem.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index fd30da39e6..bd7f73c6d8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -52,11 +52,6 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestMenuItem : StatefulMenuItem { - public TestMenuItem(string text, MenuItemType type = MenuItemType.Standard) - : this(text, type, null) - { - } - public TestMenuItem(string text, MenuItemType type, Func changeStateFunc) : base(text, changeStateFunc, type) { From 54da8e4035cd3b033eee59839e5c7428a297d25d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 19:09:38 +0900 Subject: [PATCH 3936/5608] Combine similar tests --- .../TestSceneStatefulMenuItem.cs | 81 ++++++++++++++++--- .../UserInterface/TestSceneTernaryMenuItem.cs | 65 --------------- 2 files changed, 70 insertions(+), 76 deletions(-) delete mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index bd7f73c6d8..1eff30d15e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -3,33 +3,92 @@ using System; using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneStatefulMenuItem : OsuTestScene + public class TestSceneStatefulMenuItem : ManualInputManagerTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(OsuMenu), typeof(StatefulMenuItem), - typeof(DrawableStatefulMenuItem) + typeof(ThreeStateMenuItem), + typeof(DrawableStatefulMenuItem), }; - public TestSceneStatefulMenuItem() + [Test] + public void TestTernaryMenuItem() { - Add(new OsuMenu(Direction.Vertical, true) + OsuMenu menu = null; + + Bindable state = new Bindable(TernaryState.Indeterminate); + + AddStep("create menu", () => { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Items = new[] + state.Value = TernaryState.Indeterminate; + + Child = menu = new OsuMenu(Direction.Vertical, true) { - new TestMenuItem("First", MenuItemType.Standard, getNextState), - new TestMenuItem("Second", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State2 } }, - new TestMenuItem("Third", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State3 } }, - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new ThreeStateMenuItem("First"), + new ThreeStateMenuItem("Second") { State = { BindTarget = state } }, + new ThreeStateMenuItem("Third") { State = { Value = TernaryState.True } }, + } + }; + }); + + checkState(TernaryState.Indeterminate); + + click(); + checkState(TernaryState.True); + + click(); + checkState(TernaryState.False); + + click(); + checkState(TernaryState.True); + + click(); + checkState(TernaryState.False); + + AddStep("change state via bindable", () => state.Value = TernaryState.True); + + void click() => + AddStep("click", () => + { + InputManager.MoveMouseTo(menu.ScreenSpaceDrawQuad.Centre); + InputManager.Click(MouseButton.Left); + }); + + void checkState(TernaryState expected) + => AddAssert($"state is {expected}", () => state.Value == expected); + } + + [Test] + public void TestCustomState() + { + AddStep("create menu", () => + { + Child = new OsuMenu(Direction.Vertical, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new TestMenuItem("First", MenuItemType.Standard, getNextState), + new TestMenuItem("Second", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State2 } }, + new TestMenuItem("Third", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State3 } }, + } + }; }); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs deleted file mode 100644 index fdb8c330c5..0000000000 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterface; -using osuTK.Input; - -namespace osu.Game.Tests.Visual.UserInterface -{ - public class TestSceneTernaryMenuItem : ManualInputManagerTestScene - { - private readonly OsuMenu menu; - - public override IReadOnlyList RequiredTypes => new[] - { - typeof(OsuMenu), - typeof(ThreeStateMenuItem), - typeof(DrawableStatefulMenuItem) - }; - - private readonly Bindable state = new Bindable(TernaryState.Indeterminate); - - public TestSceneTernaryMenuItem() - { - Add(menu = new OsuMenu(Direction.Vertical, true) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Items = new[] - { - new ThreeStateMenuItem("First"), - new ThreeStateMenuItem("Second") { State = { BindTarget = state } }, - new ThreeStateMenuItem("Third") { State = { Value = TernaryState.True } }, - } - }); - - checkState(TernaryState.Indeterminate); - - click(); - checkState(TernaryState.True); - - click(); - checkState(TernaryState.False); - - click(); - checkState(TernaryState.True); - - click(); - checkState(TernaryState.False); - } - - private void click() => - AddStep("click", () => - { - InputManager.MoveMouseTo(menu.ScreenSpaceDrawQuad.Centre); - InputManager.Click(MouseButton.Left); - }); - - private void checkState(TernaryState expected) - => AddAssert($"state is {expected}", () => state.Value == expected); - } -} From 9c1a9c29e45bac8624e2374192d6c2b60b4cc3f3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 18:40:28 +0800 Subject: [PATCH 3937/5608] Remove redundant package references in iOS props. --- osu.iOS.props | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.iOS.props b/osu.iOS.props index d2d7d490e9..0184e45c15 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,12 +73,6 @@ - - - - - - From 3d1c31f2ae57d010e1845d4a77dcd4b4b395ab74 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 19:45:52 +0800 Subject: [PATCH 3938/5608] Copy configs from framework repo. --- .editorconfig | 167 ++++++++- osu.sln.DotSettings | 846 +++++++++++++++++++++++--------------------- 2 files changed, 594 insertions(+), 419 deletions(-) diff --git a/.editorconfig b/.editorconfig index 0dd7ef8ed1..8f9d0ca9b0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,16 +12,171 @@ trim_trailing_whitespace = true #PascalCase for public and protected members dotnet_naming_style.pascalcase.capitalization = pascal_case -dotnet_naming_symbols.public_members.applicable_accessibilities = public,internal,protected,protected_internal -dotnet_naming_symbols.public_members.applicable_kinds = property,method,field,event,delegate -dotnet_naming_rule.public_members_pascalcase.severity = suggestion +dotnet_naming_symbols.public_members.applicable_accessibilities = public,internal,protected,protected_internal,private_protected +dotnet_naming_symbols.public_members.applicable_kinds = property,method,field,event +dotnet_naming_rule.public_members_pascalcase.severity = error dotnet_naming_rule.public_members_pascalcase.symbols = public_members dotnet_naming_rule.public_members_pascalcase.style = pascalcase #camelCase for private members dotnet_naming_style.camelcase.capitalization = camel_case + dotnet_naming_symbols.private_members.applicable_accessibilities = private -dotnet_naming_symbols.private_members.applicable_kinds = property,method,field,event,delegate -dotnet_naming_rule.private_members_camelcase.severity = suggestion +dotnet_naming_symbols.private_members.applicable_kinds = property,method,field,event +dotnet_naming_rule.private_members_camelcase.severity = warning dotnet_naming_rule.private_members_camelcase.symbols = private_members -dotnet_naming_rule.private_members_camelcase.style = camelcase \ No newline at end of file +dotnet_naming_rule.private_members_camelcase.style = camelcase + +dotnet_naming_symbols.local_function.applicable_kinds = local_function +dotnet_naming_rule.local_function_camelcase.severity = warning +dotnet_naming_rule.local_function_camelcase.symbols = local_function +dotnet_naming_rule.local_function_camelcase.style = camelcase + +#all_lower for private and local constants/static readonlys +dotnet_naming_style.all_lower.capitalization = all_lower +dotnet_naming_style.all_lower.word_separator = _ + +dotnet_naming_symbols.private_constants.applicable_accessibilities = private +dotnet_naming_symbols.private_constants.required_modifiers = const +dotnet_naming_symbols.private_constants.applicable_kinds = field +dotnet_naming_rule.private_const_all_lower.severity = warning +dotnet_naming_rule.private_const_all_lower.symbols = private_constants +dotnet_naming_rule.private_const_all_lower.style = all_lower + +dotnet_naming_symbols.private_static_readonly.applicable_accessibilities = private +dotnet_naming_symbols.private_static_readonly.required_modifiers = static,readonly +dotnet_naming_symbols.private_static_readonly.applicable_kinds = field +dotnet_naming_rule.private_static_readonly_all_lower.severity = warning +dotnet_naming_rule.private_static_readonly_all_lower.symbols = private_static_readonly +dotnet_naming_rule.private_static_readonly_all_lower.style = all_lower + +dotnet_naming_symbols.local_constants.applicable_kinds = local +dotnet_naming_symbols.local_constants.required_modifiers = const +dotnet_naming_rule.local_const_all_lower.severity = warning +dotnet_naming_rule.local_const_all_lower.symbols = local_constants +dotnet_naming_rule.local_const_all_lower.style = all_lower + +#ALL_UPPER for non private constants/static readonlys +dotnet_naming_style.all_upper.capitalization = all_upper +dotnet_naming_style.all_upper.word_separator = _ + +dotnet_naming_symbols.public_constants.applicable_accessibilities = public,internal,protected,protected_internal,private_protected +dotnet_naming_symbols.public_constants.required_modifiers = const +dotnet_naming_symbols.public_constants.applicable_kinds = field +dotnet_naming_rule.public_const_all_upper.severity = warning +dotnet_naming_rule.public_const_all_upper.symbols = public_constants +dotnet_naming_rule.public_const_all_upper.style = all_upper + +dotnet_naming_symbols.public_static_readonly.applicable_accessibilities = public,internal,protected,protected_internal,private_protected +dotnet_naming_symbols.public_static_readonly.required_modifiers = static,readonly +dotnet_naming_symbols.public_static_readonly.applicable_kinds = field +dotnet_naming_rule.public_static_readonly_all_upper.severity = warning +dotnet_naming_rule.public_static_readonly_all_upper.symbols = public_static_readonly +dotnet_naming_rule.public_static_readonly_all_upper.style = all_upper + +#Roslyn formating options + +#Formatting - indentation options +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = false +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +#Formatting - new line options +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_open_brace = all +#csharp_new_line_before_members_in_anonymous_types = true +#csharp_new_line_before_members_in_object_initializers = true # Currently no effect in VS/dotnet format (16.4), and makes Rider confusing +csharp_new_line_between_query_expression_clauses = true + +#Formatting - organize using options +dotnet_sort_system_directives_first = true + +#Formatting - spacing options +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_parameter_list_parentheses = false + +#Formatting - wrapping options +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#Roslyn language styles + +#Style - type names +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +csharp_style_var_when_type_is_apparent = true:none +csharp_style_var_for_built_in_types = true:none +csharp_style_var_elsewhere = true:silent + +#Style - modifiers +dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning +csharp_preferred_modifier_order = public,private,protected,internal,new,abstract,virtual,sealed,override,static,readonly,extern,unsafe,volatile,async:warning + +#Style - parentheses +# Skipped because roslyn cannot separate +-*/ with << >> + +#Style - expression bodies +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_constructors = false:none +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_methods = true:silent +csharp_style_expression_bodied_operators = true:silent +csharp_style_expression_bodied_properties = true:silent + +#Style - expression preferences +dotnet_style_object_initializer = true:warning +dotnet_style_collection_initializer = true:warning +dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_prefer_compound_assignment = true:warning + +#Style - null/type checks +dotnet_style_coalesce_expression = true:warning +dotnet_style_null_propagation = true:warning +csharp_style_pattern_matching_over_is_with_cast_check = true:silent +csharp_style_pattern_matching_over_as_with_null_check = true:silent +csharp_style_throw_expression = true:silent +csharp_style_conditional_delegate_call = true:suggestion + +#Style - unused +dotnet_code_quality_unused_parameters = non_public:silent +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_style_unused_value_assignment_preference = discard_variable:suggestion + +#Style - variable declaration +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_deconstructed_variable_declaration = true:silent + +#Style - other C# 7.x features +csharp_style_expression_bodied_local_functions = true:silent +dotnet_style_prefer_inferred_tuple_names = true:warning +csharp_prefer_simple_default_expression = true:warning +csharp_style_pattern_local_over_anonymous_function = true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent + +#Supressing roslyn built-in analyzers +# Suppress: EC112 + +#Field can be readonly +dotnet_diagnostic.IDE0044.severity = silent +#Private method is unused +dotnet_diagnostic.IDE0051.severity = silent +#Private member is unused +dotnet_diagnostic.IDE0052.severity = silent + +#Rules for disposable +dotnet_diagnostic.IDE0067.severity = none +dotnet_diagnostic.IDE0068.severity = none +dotnet_diagnostic.IDE0069.severity = none \ No newline at end of file diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index eb9e3ffafb..44c5c05bc0 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -12,7 +12,7 @@ HINT HINT WARNING - + WARNING True WARNING WARNING @@ -70,11 +70,20 @@ WARNING WARNING DO_NOT_SHOW + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING HINT WARNING DO_NOT_SHOW WARNING HINT + DO_NOT_SHOW HINT HINT ERROR @@ -125,6 +134,7 @@ WARNING WARNING WARNING + WARNING WARNING WARNING ERROR @@ -171,7 +181,7 @@ WARNING WARNING WARNING - HINT + WARNING WARNING WARNING WARNING @@ -201,6 +211,7 @@ HINT HINT + HINT WARNING WARNING WARNING @@ -218,9 +229,14 @@ WARNING <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> Code Cleanup (peppy) - Required - Required - Required + RequiredForMultiline + RequiredForMultiline + RequiredForMultiline + RequiredForMultiline + RequiredForMultiline + RequiredForMultiline + RequiredForMultiline + RequiredForMultiline Explicit ExpressionBody ExpressionBody @@ -239,6 +255,10 @@ 1 NEXT_LINE MULTILINE + True + True + True + True NEXT_LINE 1 1 @@ -289,397 +309,397 @@ SHA SRGB TK - SS - PP - GMT - QAT - BNG + SS + PP + GMT + QAT + BNG UI False HINT <?xml version="1.0" encoding="utf-16"?> <Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> - <TypePattern DisplayName="COM interfaces or structs"> - <TypePattern.Match> - <Or> - <And> - <Kind Is="Interface" /> - <Or> - <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> - <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> - </Or> - </And> - <Kind Is="Struct" /> - </Or> - </TypePattern.Match> - </TypePattern> - <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> - <TypePattern.Match> - <And> - <Kind Is="Class" /> - <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> - </And> - </TypePattern.Match> - <Entry DisplayName="Setup/Teardown Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <Or> - <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="All other members" /> - <Entry Priority="100" DisplayName="Test Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <HasAttribute Name="NUnit.Framework.TestAttribute" /> - </And> - </Entry.Match> - <Entry.SortBy> - <Name /> - </Entry.SortBy> - </Entry> - </TypePattern> - <TypePattern DisplayName="Default Pattern"> - <Group DisplayName="Fields/Properties"> - <Group DisplayName="Public Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Public Properties"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Internal Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Internal Properties"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Protected Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Protected Properties"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Private Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Private Properties"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Constructor/Destructor"> - <Entry DisplayName="Ctor"> - <Entry.Match> - <Kind Is="Constructor" /> - </Entry.Match> - </Entry> - <Region Name="Disposal"> - <Entry DisplayName="Dtor"> - <Entry.Match> - <Kind Is="Destructor" /> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose()"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose(true)"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Virtual /> - <Override /> - </Or> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - </Region> - </Group> - <Group DisplayName="Methods"> - <Group DisplayName="Public"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Internal"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Protected"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Private"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - </Group> - </TypePattern> + <TypePattern DisplayName="COM interfaces or structs"> + <TypePattern.Match> + <Or> + <And> + <Kind Is="Interface" /> + <Or> + <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> + <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> + </Or> + </And> + <Kind Is="Struct" /> + </Or> + </TypePattern.Match> + </TypePattern> + <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> + <TypePattern.Match> + <And> + <Kind Is="Class" /> + <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> + </And> + </TypePattern.Match> + <Entry DisplayName="Setup/Teardown Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <Or> + <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="All other members" /> + <Entry Priority="100" DisplayName="Test Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <HasAttribute Name="NUnit.Framework.TestAttribute" /> + </And> + </Entry.Match> + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + </TypePattern> + <TypePattern DisplayName="Default Pattern"> + <Group DisplayName="Fields/Properties"> + <Group DisplayName="Public Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Public Properties"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Internal Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Internal Properties"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Protected Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Protected Properties"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Private Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Private Properties"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Constructor/Destructor"> + <Entry DisplayName="Ctor"> + <Entry.Match> + <Kind Is="Constructor" /> + </Entry.Match> + </Entry> + <Region Name="Disposal"> + <Entry DisplayName="Dtor"> + <Entry.Match> + <Kind Is="Destructor" /> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose()"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose(true)"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Virtual /> + <Override /> + </Or> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + </Region> + </Group> + <Group DisplayName="Methods"> + <Group DisplayName="Public"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Internal"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Protected"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Private"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + </Group> + </TypePattern> </Patterns> Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. See the LICENCE file in the repository root for full licence text. @@ -774,7 +794,7 @@ Origin = Anchor.$anchor$, True InternalChildren = new Drawable[] { - $END$ + $END$ }; True True @@ -787,12 +807,12 @@ Origin = Anchor.$anchor$, True new GridContainer { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { $END$ }, - new Drawable[] { } - } + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { $END$ }, + new Drawable[] { } + } }; True True @@ -805,12 +825,12 @@ Origin = Anchor.$anchor$, True new FillFlowContainer { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - $END$ - } + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + $END$ + } }, True True @@ -823,11 +843,11 @@ Origin = Anchor.$anchor$, True new Container { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - $END$ - } + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + $END$ + } }, True True @@ -841,7 +861,7 @@ Origin = Anchor.$anchor$, [BackgroundDependencyLoader] private void load() { - $END$ + $END$ } True True @@ -854,8 +874,8 @@ private void load() True new Box { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, }, True True @@ -868,7 +888,7 @@ private void load() True Children = new Drawable[] { - $END$ + $END$ }; True True From ccc8aa6fa4296bf6061527544269caf55c5baff6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 19:53:22 +0800 Subject: [PATCH 3939/5608] Apply brace style. --- .../TestSceneHyperDash.cs | 2 + .../Beatmaps/CatchBeatmapProcessor.cs | 4 ++ .../Objects/BananaShower.cs | 2 + .../Legacy/HitObjectPatternGenerator.cs | 4 ++ .../TestSceneDrawableJudgement.cs | 2 + .../TestSceneHitCircleLongCombo.cs | 2 + osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs | 4 ++ osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 + .../NonVisual/FramedReplayInputHandlerTest.cs | 2 + osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 2 + .../Online/TestSceneStandAloneChatDisplay.cs | 4 ++ .../SongSelect/TestSceneBeatmapCarousel.cs | 2 + .../SongSelect/TestScenePlaySongSelect.cs | 2 + osu.Game.Tests/Visual/TestSceneOsuGame.cs | 4 ++ .../TestSceneTournamentMatchChatDisplay.cs | 28 +++++------ .../Components/TournamentBeatmapPanel.cs | 2 + .../Components/TourneyVideo.cs | 2 + osu.Game.Tournament/IPC/FileBasedIPC.cs | 2 + .../Screens/Editors/RoundEditorScreen.cs | 2 + .../Screens/Ladder/LadderScreen.cs | 6 ++- .../Screens/TeamIntro/TeamIntroScreen.cs | 2 + osu.Game.Tournament/TournamentGameBase.cs | 48 +++++++++++-------- .../Formats/LegacyStoryboardDecoder.cs | 24 +++++----- osu.Game/Beatmaps/WorkingBeatmap.cs | 6 ++- osu.Game/Database/ArchiveModelManager.cs | 8 ++++ .../Graphics/Containers/ShakeContainer.cs | 2 + .../Graphics/UserInterface/OsuTabControl.cs | 2 + .../Graphics/UserInterface/ScoreCounter.cs | 2 + osu.Game/Input/KeyBindingStore.cs | 2 + osu.Game/Online/Leaderboards/Leaderboard.cs | 6 +++ osu.Game/OsuGame.cs | 2 + osu.Game/OsuGameBase.cs | 2 + osu.Game/Overlays/Changelog/ChangelogBuild.cs | 6 +++ .../Changelog/ChangelogSingleBuild.cs | 2 + .../Overlays/Comments/CommentsContainer.cs | 2 + osu.Game/Overlays/Direct/DirectPanel.cs | 2 + osu.Game/Overlays/Mods/ModButton.cs | 2 + osu.Game/Overlays/Mods/ModSection.cs | 2 + .../Difficulty/Utils/LimitedCapacityStack.cs | 2 + .../Objects/Drawables/DrawableHitObject.cs | 2 + .../Objects/Legacy/ConvertHitObjectParser.cs | 2 + osu.Game/Rulesets/Objects/SliderPath.cs | 2 + osu.Game/Rulesets/RulesetStore.cs | 2 + osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 + osu.Game/Rulesets/UI/Playfield.cs | 4 ++ .../Screens/Multi/Components/BeatmapTitle.cs | 2 + .../Screens/Play/HUD/HoldForMenuButton.cs | 2 + osu.Game/Screens/Play/SkipOverlay.cs | 3 ++ .../Select/Carousel/CarouselBeatmap.cs | 4 ++ osu.Game/Screens/Select/SongSelect.cs | 4 ++ osu.Game/Skinning/LegacySkin.cs | 2 + osu.Game/Skinning/LegacySkinExtensions.cs | 6 ++- osu.Game/Skinning/SkinnableSound.cs | 8 ++++ osu.Game/Storyboards/CommandTimelineGroup.cs | 2 + osu.Game/Storyboards/StoryboardSprite.cs | 3 ++ .../Tests/Beatmaps/BeatmapConversionTest.cs | 4 ++ osu.Game/Tests/Visual/OsuGridTestScene.cs | 6 ++- osu.Game/Users/UserCoverBackground.cs | 2 + 58 files changed, 214 insertions(+), 52 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs index 7b8c699f2c..da36673930 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs @@ -40,8 +40,10 @@ namespace osu.Game.Rulesets.Catch.Tests beatmap.HitObjects.Add(new Fruit { StartTime = 1008, X = 56 / 512f, }); for (int i = 0; i < 512; i++) + { if (i % 5 < 3) beatmap.HitObjects.Add(new Fruit { X = i % 10 < 5 ? 0.02f : 0.98f, StartTime = 2000 + i * 100, NewCombo = i % 8 == 0 }); + } return beatmap; } diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 5ab47c1611..5d0c6116d7 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -196,9 +196,13 @@ namespace osu.Game.Rulesets.Catch.Beatmaps if (currentObject is Fruit) objectWithDroplets.Add(currentObject); if (currentObject is JuiceStream) + { foreach (var currentJuiceElement in currentObject.NestedHitObjects) + { if (!(currentJuiceElement is TinyDroplet)) objectWithDroplets.Add((CatchHitObject)currentJuiceElement); + } + } } objectWithDroplets.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime)); diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index 6d44e4660e..267e6d12c7 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -27,11 +27,13 @@ namespace osu.Game.Rulesets.Catch.Objects return; for (double i = StartTime; i <= EndTime; i += spacing) + { AddNested(new Banana { Samples = Samples, StartTime = i }); + } } public double EndTime => StartTime + Duration; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index decd159ee9..ada960a78d 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -109,8 +109,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { // Generate a new pattern by copying the last hit objects in reverse-column order for (int i = RandomStart; i < TotalColumns; i++) + { if (PreviousPattern.ColumnHasObject(i)) addToPattern(pattern, RandomStart + TotalColumns - i - 1); + } return pattern; } @@ -132,8 +134,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { // Generate a new pattern by placing on the already filled columns for (int i = RandomStart; i < TotalColumns; i++) + { if (PreviousPattern.ColumnHasObject(i)) addToPattern(pattern, i); + } return pattern; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index 433ec6bd25..ac627aa23e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs @@ -24,12 +24,14 @@ namespace osu.Game.Rulesets.Osu.Tests public TestSceneDrawableJudgement() { foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType().Skip(1)) + { AddStep("Show " + result.GetDescription(), () => SetContents(() => new DrawableOsuJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null) { Anchor = Anchor.Centre, Origin = Anchor.Centre, })); + } } } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs index 95c2810e94..b99cd523ff 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs @@ -29,8 +29,10 @@ namespace osu.Game.Rulesets.Osu.Tests }; for (int i = 0; i < 512; i++) + { if (i % 32 < 20) beatmap.HitObjects.Add(new HitCircle { Position = new Vector2(256, 192), StartTime = i * 100 }); + } return beatmap; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs index 17fcd03dd5..1664a37a66 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs @@ -55,8 +55,10 @@ namespace osu.Game.Rulesets.Osu.Mods } for (int i = 0; i < amountWiggles; i++) + { using (drawable.BeginAbsoluteSequence(osuObject.StartTime - osuObject.TimePreempt + i * wiggle_duration, true)) wiggle(); + } // Keep wiggling sliders and spinners for their duration if (!(osuObject is IHasEndTime endTime)) @@ -65,8 +67,10 @@ namespace osu.Game.Rulesets.Osu.Mods amountWiggles = (int)(endTime.Duration / wiggle_duration); for (int i = 0; i < amountWiggles; i++) + { using (drawable.BeginAbsoluteSequence(osuObject.StartTime + i * wiggle_duration, true)) wiggle(); + } } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index f60b7e67b2..3e23d09741 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -133,12 +133,14 @@ namespace osu.Game.Rulesets.Osu.Objects var sampleList = new List(); if (firstSample != null) + { sampleList.Add(new HitSampleInfo { Bank = firstSample.Bank, Volume = firstSample.Volume, Name = @"slidertick", }); + } switch (e.Type) { diff --git a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs index 18cbd4e7c5..7df7df22ea 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs @@ -225,8 +225,10 @@ namespace osu.Game.Tests.NonVisual private void fastForwardToPoint(double destination) { for (int i = 0; i < 1000; i++) + { if (handler.SetFrameFromTime(destination) == null) return; + } throw new TimeoutException("Seek was never fulfilled"); } diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 0d96dd08da..ea9d51a9b8 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -26,6 +26,7 @@ namespace osu.Game.Tests.Skins List expectedColors; if (hasColours) + { expectedColors = new List { new Color4(142, 199, 255, 255), @@ -33,6 +34,7 @@ namespace osu.Game.Tests.Skins new Color4(128, 255, 255, 255), new Color4(100, 100, 100, 100), }; + } else expectedColors = new DefaultSkin().Configuration.ComboColours; diff --git a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs index 01400bf1d9..28b5693ef4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs @@ -130,12 +130,14 @@ namespace osu.Game.Tests.Visual.Online AddRepeatStep("add many messages", () => { for (int i = 0; i < messages_per_call; i++) + { testChannel.AddNewMessages(new Message(sequence++) { Sender = longUsernameUser, Content = "Many messages! " + Guid.NewGuid(), Timestamp = DateTimeOffset.Now }); + } }, Channel.MAX_HISTORY / messages_per_call + 5); AddAssert("Ensure no adjacent day separators", () => @@ -143,8 +145,10 @@ namespace osu.Game.Tests.Visual.Online var indices = chatDisplay.FillFlow.OfType().Select(ds => chatDisplay.FillFlow.IndexOf(ds)); foreach (var i in indices) + { if (i < chatDisplay.FillFlow.Count && chatDisplay.FillFlow[i + 1] is DrawableChannel.DaySeparator) return false; + } return true; }); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 8b82567a8d..aa63bc1cf6 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -467,8 +467,10 @@ namespace osu.Game.Tests.Visual.SongSelect private void advanceSelection(bool diff, int direction = 1, int count = 1) { if (count == 1) + { AddStep($"select {(direction > 0 ? "next" : "prev")} {(diff ? "diff" : "set")}", () => carousel.SelectNext(direction, !diff)); + } else { AddRepeatStep($"select {(direction > 0 ? "next" : "prev")} {(diff ? "diff" : "set")}", () => diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index efe7fee5e4..794d135b06 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -132,11 +132,13 @@ namespace osu.Game.Tests.Visual.SongSelect changeRuleset(1); if (rulesetsInSameBeatmap) + { AddStep("import multi-ruleset map", () => { var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray(); manager.Import(createTestBeatmapSet(0, usableRulesets)).Wait(); }); + } else { addRulesetImportStep(1); diff --git a/osu.Game.Tests/Visual/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/TestSceneOsuGame.cs index fcc3a3596f..36cd49d839 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuGame.cs @@ -109,16 +109,20 @@ namespace osu.Game.Tests.Visual AddAssert("check OsuGame DI members", () => { foreach (var type in requiredGameDependencies) + { if (game.Dependencies.Get(type) == null) throw new Exception($"{type} has not been cached"); + } return true; }); AddAssert("check OsuGameBase DI members", () => { foreach (var type in requiredGameBaseDependencies) + { if (gameBase.Dependencies.Get(type) == null) throw new Exception($"{type} has not been cached"); + } return true; }); diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index 41d32d9448..d77a0b75a5 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -103,20 +103,20 @@ namespace osu.Game.Tournament.Tests.Components })); AddStep("multiple messages", () => testChannel.AddNewMessages(new Message(nextMessageId()) - { - Sender = admin, - Content = "I spam you!" - }, - new Message(nextMessageId()) - { - Sender = admin, - Content = "I spam you!!!1" - }, - new Message(nextMessageId()) - { - Sender = admin, - Content = "I spam you!1!1" - })); + { + Sender = admin, + Content = "I spam you!" + }, + new Message(nextMessageId()) + { + Sender = admin, + Content = "I spam you!!!1" + }, + new Message(nextMessageId()) + { + Sender = admin, + Content = "I spam you!1!1" + })); AddStep("change channel to 2", () => chatDisplay.Channel.Value = testChannel2); diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index f6c1be0e36..0908814537 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -131,6 +131,7 @@ namespace osu.Game.Tournament.Components }); if (!string.IsNullOrEmpty(mods)) + { AddInternal(new Sprite { Texture = textures.Get($"mods/{mods}"), @@ -139,6 +140,7 @@ namespace osu.Game.Tournament.Components Margin = new MarginPadding(20), Scale = new Vector2(0.5f) }); + } } private void matchChanged(ValueChangedEvent match) diff --git a/osu.Game.Tournament/Components/TourneyVideo.cs b/osu.Game.Tournament/Components/TourneyVideo.cs index 8582b1634c..206689ca1a 100644 --- a/osu.Game.Tournament/Components/TourneyVideo.cs +++ b/osu.Game.Tournament/Components/TourneyVideo.cs @@ -29,12 +29,14 @@ namespace osu.Game.Tournament.Components }; } else + { InternalChild = video = new VideoSprite(stream) { RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, Clock = new FramedClock(manualClock = new ManualClock()) }; + } } public bool Loop diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index e05d96e098..47f2bed77a 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -60,6 +60,7 @@ namespace osu.Game.Tournament.IPC const string file_ipc_channel_filename = "ipc-channel.txt"; if (Storage.Exists(file_ipc_filename)) + { scheduled = Scheduler.AddDelayed(delegate { try @@ -134,6 +135,7 @@ namespace osu.Game.Tournament.IPC // file might be in use. } }, 250, true); + } } catch (Exception e) { diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index b036350879..2c515edda7 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -266,12 +266,14 @@ namespace osu.Game.Tournament.Screens.Editors drawableContainer.Clear(); if (Model.BeatmapInfo != null) + { drawableContainer.Child = new TournamentBeatmapPanel(Model.BeatmapInfo, Model.Mods) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Width = 300 }; + } } } } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 83a41a662f..66e68a0f37 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -81,8 +81,10 @@ namespace osu.Game.Tournament.Screens.Ladder LadderInfo.Matches.ItemsRemoved += matches => { foreach (var p in matches) - foreach (var d in MatchesContainer.Where(d => d.Match == p)) - d.Expire(); + { + foreach (var d in MatchesContainer.Where(d => d.Match == p)) + d.Expire(); + } layout.Invalidate(); }; diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index c901a5c7ef..47c923ff30 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -164,6 +164,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro if (team != null) { foreach (var p in team.Players) + { players.Add(new OsuSpriteText { Text = p.Username, @@ -172,6 +173,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft, Origin = left ? Anchor.CentreRight : Anchor.CentreLeft, }); + } } } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 3b7718c61d..d34ea9648d 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -164,15 +164,17 @@ namespace osu.Game.Tournament // link matches to rounds foreach (var round in ladder.Rounds) - foreach (var id in round.Matches) { - var found = ladder.Matches.FirstOrDefault(p => p.ID == id); - - if (found != null) + foreach (var id in round.Matches) { - found.Round.Value = round; - if (round.StartDate.Value > found.Date.Value) - found.Date.Value = round.StartDate.Value; + var found = ladder.Matches.FirstOrDefault(p => p.ID == id); + + if (found != null) + { + found.Round.Value = round; + if (round.StartDate.Value > found.Date.Value) + found.Date.Value = round.StartDate.Value; + } } } @@ -192,15 +194,19 @@ namespace osu.Game.Tournament bool addedInfo = false; foreach (var t in ladder.Teams) - foreach (var p in t.Players) - if (string.IsNullOrEmpty(p.Username)) + { + foreach (var p in t.Players) { - var req = new GetUserRequest(p.Id); - req.Perform(API); - p.Username = req.Result.Username; + if (string.IsNullOrEmpty(p.Username)) + { + var req = new GetUserRequest(p.Id); + req.Perform(API); + p.Username = req.Result.Username; - addedInfo = true; + addedInfo = true; + } } + } return addedInfo; } @@ -213,15 +219,19 @@ namespace osu.Game.Tournament bool addedInfo = false; foreach (var r in ladder.Rounds) - foreach (var b in r.Beatmaps) - if (b.BeatmapInfo == null && b.ID > 0) + { + foreach (var b in r.Beatmaps) { - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); - req.Perform(API); - b.BeatmapInfo = req.Result?.ToBeatmap(RulesetStore); + if (b.BeatmapInfo == null && b.ID > 0) + { + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); + req.Perform(API); + b.BeatmapInfo = req.Result?.ToBeatmap(RulesetStore); - addedInfo = true; + addedInfo = true; + } } + } return addedInfo; } diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 5dbd67d304..a86fa43f3c 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -144,16 +144,16 @@ namespace osu.Game.Beatmaps.Formats var endTime = split.Length > 3 ? double.Parse(split[3], CultureInfo.InvariantCulture) : double.MaxValue; var groupNumber = split.Length > 4 ? int.Parse(split[4]) : 0; timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber); - } break; + } case "L": { var startTime = double.Parse(split[1], CultureInfo.InvariantCulture); var loopCount = int.Parse(split[2]); timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount); - } break; + } default: { @@ -172,7 +172,7 @@ namespace osu.Game.Beatmaps.Formats var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue); } - break; + break; case "S": { @@ -180,7 +180,7 @@ namespace osu.Game.Beatmaps.Formats var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue)); } - break; + break; case "V": { @@ -190,7 +190,7 @@ namespace osu.Game.Beatmaps.Formats var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY)); } - break; + break; case "R": { @@ -198,7 +198,7 @@ namespace osu.Game.Beatmaps.Formats var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue)); } - break; + break; case "M": { @@ -209,7 +209,7 @@ namespace osu.Game.Beatmaps.Formats timelineGroup?.X.Add(easing, startTime, endTime, startX, endX); timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY); } - break; + break; case "MX": { @@ -217,7 +217,7 @@ namespace osu.Game.Beatmaps.Formats var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue); } - break; + break; case "MY": { @@ -225,7 +225,7 @@ namespace osu.Game.Beatmaps.Formats var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue); } - break; + break; case "C": { @@ -239,7 +239,7 @@ namespace osu.Game.Beatmaps.Formats new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1), new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1)); } - break; + break; case "P": { @@ -260,13 +260,13 @@ namespace osu.Game.Beatmaps.Formats break; } } - break; + break; default: throw new InvalidDataException($@"Unknown command type: {commandType}"); } } - break; + break; } } } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 3fc33e9f52..7c69a992dd 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -133,8 +133,10 @@ namespace osu.Game.Beatmaps obj.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty); foreach (var mod in mods.OfType()) - foreach (var obj in converted.HitObjects) - mod.ApplyToHitObject(obj); + { + foreach (var obj in converted.HitObjects) + mod.ApplyToHitObject(obj); + } processor?.PostProcess(); diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 9fed8e03ac..a262b76125 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -265,8 +265,10 @@ namespace osu.Game.Database // for now, concatenate all .osu files in the set to create a unique hash. MemoryStream hashable = new MemoryStream(); foreach (string file in reader.Filenames.Where(f => HashableFileTypes.Any(f.EndsWith))) + { using (Stream s = reader.GetStream(file)) s.CopyTo(hashable); + } return hashable.Length > 0 ? hashable.ComputeSHA2Hash() : null; } @@ -485,12 +487,16 @@ namespace osu.Game.Database // import files to manager foreach (string file in reader.Filenames) + { using (Stream s = reader.GetStream(file)) + { fileInfos.Add(new TFileModel { Filename = FileSafety.PathStandardise(file.Substring(prefix.Length)), FileInfo = files.Add(s) }); + } + } return fileInfos; } @@ -651,8 +657,10 @@ namespace osu.Game.Database private void handleEvent(Action a) { if (delayingEvents) + { lock (queuedEvents) queuedEvents.Add(a); + } else a.Invoke(); } diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index e5a6bcc28e..dca9df1e98 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -43,9 +43,11 @@ namespace osu.Game.Graphics.Containers // if we don't have enough time for the second shake, skip it. if (!maximumLength.HasValue || maximumLength >= ShakeDuration * 4) + { sequence = sequence .MoveToX(shake_amount, ShakeDuration, Easing.InOutSine).Then() .MoveToX(-shake_amount, ShakeDuration, Easing.InOutSine).Then(); + } sequence.MoveToX(0, ShakeDuration / 2, Easing.InSine); } diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index c55d14456b..5d1bdc62e9 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -51,8 +51,10 @@ namespace osu.Game.Graphics.UserInterface }); if (isEnumType && AddEnumEntriesAutomatically) + { foreach (var val in (T[])Enum.GetValues(typeof(T))) AddItem(val); + } } [BackgroundDependencyLoader] diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index 63062cdc9d..ee96b78844 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -44,8 +44,10 @@ namespace osu.Game.Graphics.UserInterface { string format = new string('0', (int)LeadingZeroes); if (UseCommaSeparator) + { for (int i = format.Length - 3; i > 0; i -= 3) format = format.Insert(i, @","); + } return ((long)count).ToString(format); } diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index caddb1ae0d..b1c794a856 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -47,6 +47,7 @@ namespace osu.Game.Input foreach (var insertable in group.Skip(count).Take(aimCount - count)) // insert any defaults which are missing. + { usage.Context.DatabasedKeyBinding.Add(new DatabasedKeyBinding { KeyCombination = insertable.KeyCombination, @@ -54,6 +55,7 @@ namespace osu.Game.Input RulesetID = rulesetId, Variant = variant }); + } } } } diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 83de0635fb..d214743b30 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -75,8 +75,10 @@ namespace osu.Game.Online.Leaderboards int i = 0; foreach (var s in scrollFlow.Children) + { using (s.BeginDelayedSequence(i++ * 50, true)) s.Show(); + } scrollContainer.ScrollTo(0f, false); }, (showScoresCancellationSource = new CancellationTokenSource()).Token)); @@ -342,13 +344,17 @@ namespace osu.Game.Online.Leaderboards else { if (bottomY - fadeBottom > 0 && FadeBottom) + { c.Colour = ColourInfo.GradientVertical( Color4.White.Opacity(Math.Min(1 - (topY - fadeBottom) / LeaderboardScore.HEIGHT, 1)), Color4.White.Opacity(Math.Min(1 - (bottomY - fadeBottom) / LeaderboardScore.HEIGHT, 1))); + } else if (FadeTop) + { c.Colour = ColourInfo.GradientVertical( Color4.White.Opacity(Math.Min(1 - (fadeTop - topY) / LeaderboardScore.HEIGHT, 1)), Color4.White.Opacity(Math.Min(1 - (fadeTop - bottomY) / LeaderboardScore.HEIGHT, 1))); + } } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 1f823e6eba..7735030bbb 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -402,8 +402,10 @@ namespace osu.Game nextBeatmap.Track.Completed += currentTrackCompleted; using (var oldBeatmap = beatmap.OldValue) + { if (oldBeatmap?.Track != null) oldBeatmap.Track.Completed -= currentTrackCompleted; + } nextBeatmap?.LoadBeatmapAsync(); } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 194a439b06..87321030a9 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -292,8 +292,10 @@ namespace osu.Game var extension = Path.GetExtension(paths.First())?.ToLowerInvariant(); foreach (var importer in fileImporters) + { if (importer.HandledExtensions.Contains(extension)) await importer.Import(paths); + } } public string[] HandledExtensions => fileImporters.SelectMany(i => i.HandledExtensions).ToArray(); diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index d8488b21ab..5a3ce6291e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -130,6 +130,7 @@ namespace osu.Game.Overlays.Changelog }); if (entry.GithubUser.UserId != null) + { title.AddUserLink(new User { Username = entry.GithubUser.OsuUsername, @@ -139,18 +140,23 @@ namespace osu.Game.Overlays.Changelog t.Font = fontMedium; t.Colour = entryColour; }); + } else if (entry.GithubUser.GithubUrl != null) + { title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, t => { t.Font = fontMedium; t.Colour = entryColour; }); + } else + { title.AddText(entry.GithubUser.DisplayName, t => { t.Font = fontSmall; t.Colour = entryColour; }); + } ChangelogEntries.Add(titleContainer); diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index adcd33fb48..3297b00322 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -68,11 +68,13 @@ namespace osu.Game.Overlays.Changelog } if (build != null) + { Children = new Drawable[] { new ChangelogBuildWithNavigation(build) { SelectBuild = SelectBuild }, new Comments(build) }; + } } public class ChangelogBuildWithNavigation : ChangelogBuild diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index abc1b7233d..560123eb55 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -162,10 +162,12 @@ namespace osu.Game.Overlays.Comments foreach (var c in response.Comments) { if (c.IsTopLevel) + { page.Add(new DrawableComment(c) { ShowDeleted = { BindTarget = ShowDeleted } }); + } } LoadComponentAsync(page, loaded => diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 3ffc3f332b..c1c5113c5e 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -149,8 +149,10 @@ namespace osu.Game.Overlays.Direct icons.Add(new GroupedDifficultyIcon(SetInfo.Beatmaps.FindAll(b => b.Ruleset.Equals(ruleset)), ruleset, this is DirectListPanel ? Color4.White : colours.Gray5)); } else + { foreach (var b in SetInfo.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty)) icons.Add(new DifficultyIcon(b)); + } return icons; } diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index 58892cd0dd..8252020e9b 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -194,8 +194,10 @@ namespace osu.Game.Overlays.Mods start = Mods.Length - 1; for (int i = start; i < Mods.Length && i >= 0; i += direction) + { if (SelectAt(i)) return; + } Deselect(); } diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index dedd397fa5..5c2ab8e18c 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -112,6 +112,7 @@ namespace osu.Game.Overlays.Mods if (selected == null) continue; foreach (var type in modTypes) + { if (type.IsInstanceOfType(selected)) { if (immediate) @@ -119,6 +120,7 @@ namespace osu.Game.Overlays.Mods else Scheduler.AddDelayed(button.Deselect, delay += 50); } + } } } diff --git a/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs index 95b7d9b19d..d47caf409b 100644 --- a/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs +++ b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs @@ -81,8 +81,10 @@ namespace osu.Game.Rulesets.Difficulty.Utils yield return array[i]; if (Count == capacity) + { for (int i = 0; i < marker; ++i) yield return array[i]; + } } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 1d9b66f88d..af1a2fb63a 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -113,8 +113,10 @@ namespace osu.Game.Rulesets.Objects.Drawables if (samples.Length > 0) { if (HitObject.SampleControlPoint == null) + { throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); + } samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray(); foreach (var s in samples) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index e990938291..64f01952b1 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -75,8 +75,10 @@ namespace osu.Game.Rulesets.Objects.Legacy int pointCount = 1; foreach (var t in pointSplit) + { if (t.Length > 1) pointCount++; + } var points = new Vector2[pointCount]; diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index bc9571c85d..7763b0eaaf 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -185,8 +185,10 @@ namespace osu.Game.Rulesets.Objects ReadOnlySpan cpSpan = ControlPoints.Slice(start, end - start); foreach (Vector2 t in calculateSubpath(cpSpan)) + { if (calculatedPath.Count == 0 || calculatedPath.Last() != t) calculatedPath.Add(t); + } start = end; } diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 23988ff0ff..7d13afe9e5 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -69,8 +69,10 @@ namespace osu.Game.Rulesets //add any other modes foreach (var r in instances.Where(r => r.LegacyID == null)) + { if (context.RulesetInfo.FirstOrDefault(ri => ri.InstantiationInfo == r.RulesetInfo.InstantiationInfo) == null) context.RulesetInfo.Add(r.RulesetInfo); + } context.SaveChanges(); diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index e005eea831..d1749d33c0 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -436,8 +436,10 @@ namespace osu.Game.Rulesets.UI return h.HitWindows; foreach (var n in h.NestedHitObjects) + { if (h.HitWindows.WindowFor(HitResult.Miss) > 0) return n.HitWindows; + } } return null; diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index f2e7f51b52..ca4983e3d7 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -130,9 +130,13 @@ namespace osu.Game.Rulesets.UI base.Update(); if (beatmap != null) + { foreach (var mod in mods) + { if (mod is IUpdatableByPlayfield updatable) updatable.Update(this); + } + } } /// diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index f79cac7649..b41b2d073e 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs @@ -57,11 +57,13 @@ namespace osu.Game.Screens.Multi.Components var beatmap = CurrentItem.Value?.Beatmap; if (beatmap == null) + { textFlow.AddText("No beatmap selected", s => { s.Font = s.Font.With(size: TextSize); s.Colour = colours.PinkLight; }); + } else { textFlow.AddLink(new[] diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index a05937801c..968b83e68c 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -100,9 +100,11 @@ namespace osu.Game.Screens.Play.HUD if (text.Alpha > 0 || button.Progress.Value > 0 || button.IsHovered) Alpha = 1; else + { Alpha = Interpolation.ValueAt( MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 200), Alpha, MathHelper.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); + } } private class Button : HoldToConfirmContainer, IKeyBindingHandler diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 31cdff5fb9..835867fe62 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -181,8 +181,11 @@ namespace osu.Game.Screens.Play this.FadeIn(500, Easing.OutExpo); if (!IsHovered && !IsDragged) + { using (BeginDelayedSequence(1000)) scheduledHide = Schedule(Hide); + } + break; case Visibility.Hidden: diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 6c3c9d20f3..afd6211dec 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -44,10 +44,14 @@ namespace osu.Game.Screens.Select.Carousel criteria.Artist.Matches(Beatmap.Metadata.ArtistUnicode); if (match) + { 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; + } + } Filtered.Value = !match; } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 409ea4bbbe..78ff150f08 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -251,11 +251,13 @@ namespace osu.Game.Screens.Select { // if we have no beatmaps but osu-stable is found, let's prompt the user to import. if (!beatmaps.GetAllUsableBeatmapSetsEnumerable().Any() && beatmaps.StableInstallationAvailable) + { dialogOverlay.Push(new ImportFromStablePopup(() => { Task.Run(beatmaps.ImportFromStableAsync).ContinueWith(_ => scores.ImportFromStableAsync(), TaskContinuationOptions.OnlyOnRanToCompletion); Task.Run(skins.ImportFromStableAsync); })); + } }); } } @@ -333,11 +335,13 @@ namespace osu.Game.Screens.Select if (this.IsCurrentScreen() && !Carousel.SelectBeatmap(e.NewValue?.BeatmapInfo, false)) // If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch + { if (e.NewValue?.BeatmapInfo?.Ruleset != null && !e.NewValue.BeatmapInfo.Ruleset.Equals(decoupledRuleset.Value)) { Ruleset.Value = e.NewValue.BeatmapInfo.Ruleset; Carousel.SelectBeatmap(e.NewValue.BeatmapInfo); } + } } // We need to keep track of the last selected beatmap ignoring debounce to play the correct selection sounds. diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index fea15458e4..593b80c012 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -36,8 +36,10 @@ namespace osu.Game.Skinning { Stream stream = storage?.GetStream(filename); if (stream != null) + { using (LineBufferedReader reader = new LineBufferedReader(stream)) Configuration = new LegacySkinDecoder().Decode(reader); + } else Configuration = new DefaultSkinConfiguration(); diff --git a/osu.Game/Skinning/LegacySkinExtensions.cs b/osu.Game/Skinning/LegacySkinExtensions.cs index c5582af836..c758b699ed 100644 --- a/osu.Game/Skinning/LegacySkinExtensions.cs +++ b/osu.Game/Skinning/LegacySkinExtensions.cs @@ -22,17 +22,19 @@ namespace osu.Game.Skinning if (animatable) { - for (int i = 0;; i++) + for (int i = 0; true; i++) { if ((texture = getFrameTexture(i)) == null) break; if (animation == null) + { animation = new TextureAnimation { DefaultFrameLength = default_frame_time, Repeat = looping }; + } animation.AddFrame(texture); } @@ -42,10 +44,12 @@ namespace osu.Game.Skinning return animation; if ((texture = source.GetTexture(componentName)) != null) + { return new Sprite { Texture = texture }; + } return null; } diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index bdf8be773b..6d23f22515 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -81,9 +81,13 @@ namespace osu.Game.Skinning var ch = skin.GetSample(s); if (ch == null && allowFallback) + { foreach (var lookup in s.LookupNames) + { if ((ch = samples.Get($"Gameplay/{lookup}")) != null) break; + } + } if (ch != null) { @@ -91,8 +95,10 @@ namespace osu.Game.Skinning ch.Volume.Value = s.Volume / 100.0; if (adjustments != null) + { foreach (var adjustment in adjustments) ch.AddAdjustment(adjustment.property, adjustment.bindable); + } } return ch; @@ -104,8 +110,10 @@ namespace osu.Game.Skinning base.Dispose(isDisposing); if (channels != null) + { foreach (var c in channels) c.Dispose(); + } } } } diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index 461ee762e9..364c971874 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -65,6 +65,7 @@ namespace osu.Game.Storyboards public virtual IEnumerable.TypedCommand> GetCommands(CommandTimelineSelector timelineSelector, double offset = 0) { if (offset != 0) + { return timelineSelector(this).Commands.Select(command => new CommandTimeline.TypedCommand { @@ -74,6 +75,7 @@ namespace osu.Game.Storyboards StartValue = command.StartValue, EndValue = command.EndValue, }); + } return timelineSelector(this).Commands; } diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 37c3ff495f..96c7ceea8d 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -106,8 +106,11 @@ namespace osu.Game.Storyboards foreach (var loop in loops) commands = commands.Concat(loop.GetCommands(timelineSelector)); if (triggeredGroups != null) + { foreach (var pair in triggeredGroups) commands = commands.Concat(pair.Item1.GetCommands(timelineSelector, pair.Item2)); + } + return commands; } diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index e99b5fc5fb..b144de35c5 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -72,11 +72,15 @@ namespace osu.Game.Tests.Beatmaps break; if (objectCounter >= ourMapping.Objects.Count) + { Assert.Fail($"The conversion did not generate a hitobject, but should have, for hitobject at time: {expectedMapping.StartTime}:\n" + $"Expected: {JsonConvert.SerializeObject(expectedMapping.Objects[objectCounter])}\n"); + } else if (objectCounter >= expectedMapping.Objects.Count) + { Assert.Fail($"The conversion generated a hitobject, but should not have, for hitobject at time: {ourMapping.StartTime}:\n" + $"Received: {JsonConvert.SerializeObject(ourMapping.Objects[objectCounter])}\n"); + } else if (!expectedMapping.Objects[objectCounter].Equals(ourMapping.Objects[objectCounter])) { Assert.Fail($"The conversion generated differing hitobjects for object at time: {expectedMapping.StartTime}:\n" diff --git a/osu.Game/Tests/Visual/OsuGridTestScene.cs b/osu.Game/Tests/Visual/OsuGridTestScene.cs index c09f4d6218..33ede9453e 100644 --- a/osu.Game/Tests/Visual/OsuGridTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGridTestScene.cs @@ -38,8 +38,10 @@ namespace osu.Game.Tests.Visual cells = new Drawable[rows, cols]; for (int r = 0; r < rows; r++) - for (int c = 0; c < cols; c++) - cells[r, c] = new Container { RelativeSizeAxes = Axes.Both }; + { + for (int c = 0; c < cols; c++) + cells[r, c] = new Container { RelativeSizeAxes = Axes.Both }; + } testContainer.Content = cells.ToJagged(); } diff --git a/osu.Game/Users/UserCoverBackground.cs b/osu.Game/Users/UserCoverBackground.cs index e583acac9f..a45fd85901 100644 --- a/osu.Game/Users/UserCoverBackground.cs +++ b/osu.Game/Users/UserCoverBackground.cs @@ -46,6 +46,7 @@ namespace osu.Game.Users }; } else + { InternalChild = new Sprite { RelativeSizeAxes = Axes.Both, @@ -54,6 +55,7 @@ namespace osu.Game.Users Anchor = Anchor.Centre, Origin = Anchor.Centre }; + } } protected override void LoadComplete() From d8482448dc91ecf93e63789075fc287e0b2c7258 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 19:53:41 +0800 Subject: [PATCH 3940/5608] Save iOS projects with BOM to avoid VS continuously changing them. --- .../osu.Game.Rulesets.Catch.Tests.iOS.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.iOS.csproj | 2 +- .../osu.Game.Rulesets.Osu.Tests.iOS.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.iOS.csproj | 2 +- osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj | 2 +- osu.iOS/osu.iOS.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj index 708779986c..be6044bbd0 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj @@ -1,4 +1,4 @@ - + Debug diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj index 52e558931b..88ad484bc1 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj @@ -1,4 +1,4 @@ - + Debug diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj index cacd035078..545abcec6c 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj @@ -1,4 +1,4 @@ - + Debug diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj index c20bd4fe02..8ee640cd99 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj @@ -1,4 +1,4 @@ - + Debug diff --git a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj index 583d188295..ca68369ebb 100644 --- a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj +++ b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj @@ -1,4 +1,4 @@ - + Debug diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj index 378ac231c2..d60a3475e7 100644 --- a/osu.iOS/osu.iOS.csproj +++ b/osu.iOS/osu.iOS.csproj @@ -1,4 +1,4 @@ - + Debug From e9b8cbb5165a65db0c779cc8ef4b97a580d8d3cc Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 20:05:36 +0800 Subject: [PATCH 3941/5608] Apply other styles. --- .../Beatmaps/CatchBeatmapProcessor.cs | 1 + osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 1 + .../TestSceneTournamentMatchChatDisplay.cs | 31 ++++++++++--------- .../Formats/LegacyStoryboardDecoder.cs | 22 +++++++------ osu.Game/Database/ArchiveModelManager.cs | 1 + .../Graphics/UserInterface/ScoreCounter.cs | 1 + osu.Game/Input/KeyBindingStore.cs | 2 +- osu.Game/Online/Chat/ChannelManager.cs | 2 +- .../Objects/Legacy/ConvertHitObjectParser.cs | 1 + osu.Game/Screens/Select/SongSelect.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 1 + osu.Game/Storyboards/StoryboardSprite.cs | 1 + osu.Game/Tests/Visual/OsuGridTestScene.cs | 1 + osu.iOS/AppDelegate.cs | 1 - 14 files changed, 39 insertions(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 5d0c6116d7..58bf811fac 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -195,6 +195,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { if (currentObject is Fruit) objectWithDroplets.Add(currentObject); + if (currentObject is JuiceStream) { foreach (var currentJuiceElement in currentObject.NestedHitObjects) diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index ea9d51a9b8..085f502517 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -25,6 +25,7 @@ namespace osu.Game.Tests.Skins var comboColors = decoder.Decode(stream).ComboColours; List expectedColors; + if (hasColours) { expectedColors = new List diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index d77a0b75a5..9905e17824 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -102,21 +102,22 @@ namespace osu.Game.Tournament.Tests.Components Content = "Okay okay, calm down guys. Let's do this!" })); - AddStep("multiple messages", () => testChannel.AddNewMessages(new Message(nextMessageId()) - { - Sender = admin, - Content = "I spam you!" - }, - new Message(nextMessageId()) - { - Sender = admin, - Content = "I spam you!!!1" - }, - new Message(nextMessageId()) - { - Sender = admin, - Content = "I spam you!1!1" - })); + AddStep("multiple messages", () => testChannel.AddNewMessages( + new Message(nextMessageId()) + { + Sender = admin, + Content = "I spam you!" + }, + new Message(nextMessageId()) + { + Sender = admin, + Content = "I spam you!!!1" + }, + new Message(nextMessageId()) + { + Sender = admin, + Content = "I spam you!1!1" + })); AddStep("change channel to 2", () => chatDisplay.Channel.Value = testChannel2); diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index a86fa43f3c..e3320f62ac 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -171,16 +171,16 @@ namespace osu.Game.Beatmaps.Formats var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue); + break; } - break; case "S": { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue)); + break; } - break; case "V": { @@ -189,16 +189,16 @@ namespace osu.Game.Beatmaps.Formats var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX; var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY)); + break; } - break; case "R": { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue)); + break; } - break; case "M": { @@ -208,24 +208,24 @@ namespace osu.Game.Beatmaps.Formats var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; timelineGroup?.X.Add(easing, startTime, endTime, startX, endX); timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY); + break; } - break; case "MX": { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue); + break; } - break; case "MY": { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue); + break; } - break; case "C": { @@ -238,8 +238,8 @@ namespace osu.Game.Beatmaps.Formats timelineGroup?.Colour.Add(easing, startTime, endTime, new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1), new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1)); + break; } - break; case "P": { @@ -259,14 +259,16 @@ namespace osu.Game.Beatmaps.Formats timelineGroup?.FlipV.Add(easing, startTime, endTime, true, startTime == endTime); break; } + + break; } - break; default: throw new InvalidDataException($@"Unknown command type: {commandType}"); } + + break; } - break; } } } diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index a262b76125..8fa4eaf267 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -264,6 +264,7 @@ namespace osu.Game.Database { // for now, concatenate all .osu files in the set to create a unique hash. MemoryStream hashable = new MemoryStream(); + foreach (string file in reader.Filenames.Where(f => HashableFileTypes.Any(f.EndsWith))) { using (Stream s = reader.GetStream(file)) diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index ee96b78844..e291401670 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -43,6 +43,7 @@ namespace osu.Game.Graphics.UserInterface protected override string FormatCount(double count) { string format = new string('0', (int)LeadingZeroes); + if (UseCommaSeparator) { for (int i = format.Length - 3; i > 0; i -= 3) diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index b1c794a856..74b3134964 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -46,8 +46,8 @@ namespace osu.Game.Input continue; foreach (var insertable in group.Skip(count).Take(aimCount - count)) - // insert any defaults which are missing. { + // insert any defaults which are missing. usage.Context.DatabasedKeyBinding.Add(new DatabasedKeyBinding { KeyCombination = insertable.KeyCombination, diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 4f6066cab1..1d8c5609d9 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -220,7 +220,7 @@ namespace osu.Game.Online.Chat break; } - var channel = availableChannels.Where(c => c.Name == content || c.Name == $"#{content}").FirstOrDefault(); + var channel = availableChannels.FirstOrDefault(c => c.Name == content || c.Name == $"#{content}"); if (channel == null) { diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 64f01952b1..4049e40013 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -74,6 +74,7 @@ namespace osu.Game.Rulesets.Objects.Legacy string[] pointSplit = split[5].Split('|'); int pointCount = 1; + foreach (var t in pointSplit) { if (t.Length > 1) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 78ff150f08..375b994169 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -334,8 +334,8 @@ namespace osu.Game.Screens.Select if (e.NewValue is DummyWorkingBeatmap) return; if (this.IsCurrentScreen() && !Carousel.SelectBeatmap(e.NewValue?.BeatmapInfo, false)) - // If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch { + // If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch if (e.NewValue?.BeatmapInfo?.Ruleset != null && !e.NewValue.BeatmapInfo.Ruleset.Equals(decoupledRuleset.Value)) { Ruleset.Value = e.NewValue.BeatmapInfo.Ruleset; diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 593b80c012..67a83f19e2 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -35,6 +35,7 @@ namespace osu.Game.Skinning : base(skin) { Stream stream = storage?.GetStream(filename); + if (stream != null) { using (LineBufferedReader reader = new LineBufferedReader(stream)) diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 96c7ceea8d..d5e69fd103 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -105,6 +105,7 @@ namespace osu.Game.Storyboards var commands = TimelineGroup.GetCommands(timelineSelector); foreach (var loop in loops) commands = commands.Concat(loop.GetCommands(timelineSelector)); + if (triggeredGroups != null) { foreach (var pair in triggeredGroups) diff --git a/osu.Game/Tests/Visual/OsuGridTestScene.cs b/osu.Game/Tests/Visual/OsuGridTestScene.cs index 33ede9453e..48f85be6ba 100644 --- a/osu.Game/Tests/Visual/OsuGridTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGridTestScene.cs @@ -37,6 +37,7 @@ namespace osu.Game.Tests.Visual Add(testContainer = new GridContainer { RelativeSizeAxes = Axes.Both }); cells = new Drawable[rows, cols]; + for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs index 164a182ebe..14e3627752 100644 --- a/osu.iOS/AppDelegate.cs +++ b/osu.iOS/AppDelegate.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using Foundation; using osu.Framework.iOS; -using osu.Framework.Threading; using UIKit; namespace osu.iOS From d3858622676274c0c30d731099311a9bca1401d2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 20:32:32 +0800 Subject: [PATCH 3942/5608] Add dotnet format check. --- .config/dotnet-tools.json | 6 ++++++ build/build.cake | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 1b70c949eb..6ba6ae82c8 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -7,6 +7,12 @@ "commands": [ "dotnet-cake" ] + }, + "dotnet-format": { + "version": "3.1.37601", + "commands": [ + "dotnet-format" + ] } } } \ No newline at end of file diff --git a/build/build.cake b/build/build.cake index 389ff4829d..274e57ef4e 100644 --- a/build/build.cake +++ b/build/build.cake @@ -11,6 +11,7 @@ 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"); @@ -60,8 +61,12 @@ Task("CodeFileSanity") }); }); +Task("DotnetFormat") + .Does(() => DotNetCoreTool(sln.FullPath, "format", "--dry-run --check")); + Task("Build") .IsDependentOn("CodeFileSanity") + .IsDependentOn("DotnetFormat") .IsDependentOn("InspectCode") .IsDependentOn("Test"); From 1ef645a7105977268c17c5fe438341be1f59ab5a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 21:02:48 +0800 Subject: [PATCH 3943/5608] Turn off some more not applied styles. --- .editorconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.editorconfig b/.editorconfig index 8f9d0ca9b0..2c000d3881 100644 --- a/.editorconfig +++ b/.editorconfig @@ -140,7 +140,7 @@ dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning dotnet_style_prefer_auto_properties = true:silent dotnet_style_prefer_conditional_expression_over_assignment = true:silent dotnet_style_prefer_conditional_expression_over_return = true:silent -dotnet_style_prefer_compound_assignment = true:warning +dotnet_style_prefer_compound_assignment = true:silent #Style - null/type checks dotnet_style_coalesce_expression = true:warning @@ -153,17 +153,17 @@ csharp_style_conditional_delegate_call = true:suggestion #Style - unused dotnet_code_quality_unused_parameters = non_public:silent csharp_style_unused_value_expression_statement_preference = discard_variable:silent -csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:silent #Style - variable declaration -csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_inlined_variable_declaration = true:silent csharp_style_deconstructed_variable_declaration = true:silent #Style - other C# 7.x features csharp_style_expression_bodied_local_functions = true:silent dotnet_style_prefer_inferred_tuple_names = true:warning csharp_prefer_simple_default_expression = true:warning -csharp_style_pattern_local_over_anonymous_function = true:warning +csharp_style_pattern_local_over_anonymous_function = true:silent dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent #Supressing roslyn built-in analyzers From 3655f881806ee7b13cd6e22074439d7d07405885 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 17:56:57 +0300 Subject: [PATCH 3944/5608] Merge dependency --- .../Online/TestSceneLeaderboardModSelector.cs | 77 ++++++++ .../BeatmapSet/LeaderboardModSelector.cs | 165 ++++++++++++++++++ osu.Game/Rulesets/UI/ModIcon.cs | 19 +- 3 files changed, 259 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs create mode 100644 osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs new file mode 100644 index 0000000000..799528220b --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -0,0 +1,77 @@ +// 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.Overlays.BeatmapSet; +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Taiko; +using osu.Game.Rulesets.Catch; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Bindables; +using osu.Game.Rulesets; +using osu.Framework.Extensions.IEnumerableExtensions; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneLeaderboardModSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(LeaderboardModSelector), + }; + + public TestSceneLeaderboardModSelector() + { + LeaderboardModSelector modSelector; + FillFlowContainer selectedMods; + Bindable ruleset = new Bindable(); + + Add(selectedMods = new FillFlowContainer + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }); + + Add(modSelector = new LeaderboardModSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Ruleset = { BindTarget = ruleset } + }); + + modSelector.SelectedMods.ItemsAdded += mods => + { + mods.ForEach(mod => selectedMods.Add(new SpriteText + { + Text = mod.Acronym, + })); + }; + + modSelector.SelectedMods.ItemsRemoved += mods => + { + mods.ForEach(mod => + { + foreach (var selected in selectedMods) + { + if (selected.Text == mod.Acronym) + { + selectedMods.Remove(selected); + break; + } + } + }); + }; + + AddStep("osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo); + AddStep("mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo); + AddStep("taiko ruleset", () => ruleset.Value = new TaikoRuleset().RulesetInfo); + AddStep("catch ruleset", () => ruleset.Value = new CatchRuleset().RulesetInfo); + AddStep("Deselect all", () => modSelector.DeselectAll()); + AddStep("null ruleset", () => ruleset.Value = null); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs new file mode 100644 index 0000000000..75c24cb710 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -0,0 +1,165 @@ +// 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.Containers; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Framework.Bindables; +using osu.Game.Rulesets; +using osuTK; +using osu.Game.Rulesets.UI; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; +using osuTK.Graphics; +using System; +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Overlays.BeatmapSet +{ + public class LeaderboardModSelector : CompositeDrawable + { + public readonly BindableList SelectedMods = new BindableList(); + public readonly Bindable Ruleset = new Bindable(); + + private readonly FillFlowContainer modsContainer; + + public LeaderboardModSelector() + { + AutoSizeAxes = Axes.Both; + InternalChild = modsContainer = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Full, + Spacing = new Vector2(4), + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Ruleset.BindValueChanged(onRulesetChanged, true); + } + + private void onRulesetChanged(ValueChangedEvent ruleset) + { + SelectedMods.Clear(); + modsContainer.Clear(); + + if (ruleset.NewValue == null) + return; + + modsContainer.Add(new ModButton(new NoMod())); + + ruleset.NewValue.CreateInstance().GetAllMods().ForEach(mod => + { + if (mod.Ranked) + modsContainer.Add(new ModButton(mod)); + }); + + modsContainer.ForEach(button => button.OnSelectionChanged += selectionChanged); + } + + private void selectionChanged(Mod mod, bool selected) + { + if (selected) + SelectedMods.Add(mod); + else + SelectedMods.Remove(mod); + + if (!SelectedMods.Any() && !IsHovered) + highlightAll(); + } + + protected override bool OnHover(HoverEvent e) + { + if (!SelectedMods.Any()) + modsContainer.ForEach(button => + { + if (!button.IsHovered) + button.Highlighted.Value = false; + }); + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + if (!SelectedMods.Any()) + highlightAll(); + } + + public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); + + private void highlightAll() => modsContainer.ForEach(mod => mod.Highlighted.Value = true); + + private class ModButton : ModIcon + { + private const float mod_scale = 0.4f; + private const int duration = 200; + + public readonly BindableBool Selected = new BindableBool(); + public Action OnSelectionChanged; + + public ModButton(Mod mod) + : base(mod) + { + Scale = new Vector2(mod_scale); + Highlighted.Value = true; + Add(new HoverClickSounds()); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Selected.BindValueChanged(selected => + { + updateState(); + OnSelectionChanged?.Invoke(Mod, selected.NewValue); + }); + } + + protected override bool OnClick(ClickEvent e) + { + Selected.Value = !Selected.Value; + return base.OnClick(e); + } + + protected override bool OnHover(HoverEvent e) + { + updateState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + updateState(); + } + + private void updateState() => Highlighted.Value = IsHovered || Selected.Value; + + protected override void OnHighlightedChanged(ValueChangedEvent highlighted) => + this.FadeColour(highlighted.NewValue ? Color4.White : Color4.Gray, duration, Easing.OutQuint); + } + + private class NoMod : Mod + { + public override string Name => "NoMod"; + + public override string Acronym => "NM"; + + public override double ScoreMultiplier => 1; + + public override IconUsage Icon => FontAwesome.Solid.Ban; + + public override ModType Type => ModType.System; + } + } +} diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 88a2338b94..19211e0c80 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -34,9 +34,11 @@ namespace osu.Game.Rulesets.UI public virtual string TooltipText { get; } + protected Mod Mod { get; private set; } + public ModIcon(Mod mod) { - if (mod == null) throw new ArgumentNullException(nameof(mod)); + Mod = mod ?? throw new ArgumentNullException(nameof(mod)); type = mod.Type; @@ -98,13 +100,26 @@ namespace osu.Game.Rulesets.UI backgroundColour = colours.Pink; highlightedColour = colours.PinkLight; break; + + case ModType.System: + backgroundColour = colours.Gray6; + highlightedColour = colours.Gray7; + modIcon.Colour = colours.Yellow; + break; } + + background.Colour = backgroundColour; } protected override void LoadComplete() { base.LoadComplete(); - Highlighted.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); + Highlighted.BindValueChanged(OnHighlightedChanged, true); + } + + protected virtual void OnHighlightedChanged(ValueChangedEvent highlighted) + { + background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour; } } } From 32b2f5e330e70fe7ef910bf28dec1f84255e93c1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 18:10:25 +0300 Subject: [PATCH 3945/5608] Use Bindable for ScoresContainer --- .../BeatmapSet/Scores/ScoresContainer.cs | 31 +++++++------------ osu.Game/Overlays/BeatmapSetOverlay.cs | 6 ++-- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 4bbcd8d631..580e863a0c 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -13,6 +13,7 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Framework.Bindables; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -20,6 +21,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { private const int spacing = 15; + public readonly Bindable Beatmap = new Bindable(); + private readonly Box background; private readonly ScoreTable scoreTable; private readonly FillFlowContainer topScoresContainer; @@ -30,22 +33,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private GetScoresRequest getScoresRequest; - private BeatmapInfo beatmap; - - public BeatmapInfo Beatmap - { - get => beatmap; - set - { - if (beatmap == value) - return; - - beatmap = value; - - getScores(beatmap); - } - } - protected APILegacyScores Scores { set @@ -125,18 +112,24 @@ namespace osu.Game.Overlays.BeatmapSet.Scores background.Colour = colours.Gray2; } - private void getScores(BeatmapInfo beatmap) + protected override void LoadComplete() + { + base.LoadComplete(); + Beatmap.BindValueChanged(getScores, true); + } + + private void getScores(ValueChangedEvent beatmap) { getScoresRequest?.Cancel(); getScoresRequest = null; Scores = null; - if (beatmap?.OnlineBeatmapID.HasValue != true || beatmap.Status <= BeatmapSetOnlineStatus.Pending) + if (beatmap.NewValue?.OnlineBeatmapID.HasValue != true || beatmap.NewValue.Status <= BeatmapSetOnlineStatus.Pending) return; loadingAnimation.Show(); - getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); + getScoresRequest = new GetScoresRequest(beatmap.NewValue, beatmap.NewValue.Ruleset); getScoresRequest.Success += scores => { loadingAnimation.Hide(); diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index c20e6368d8..65d68e4c8c 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -59,7 +59,10 @@ namespace osu.Game.Overlays { Header = new Header(), info = new Info(), - scoreContainer = new ScoresContainer(), + scoreContainer = new ScoresContainer + { + Beatmap = { BindTarget = Header.Picker.Beatmap } + } }, }, }, @@ -71,7 +74,6 @@ namespace osu.Game.Overlays Header.Picker.Beatmap.ValueChanged += b => { info.Beatmap = b.NewValue; - scoreContainer.Beatmap = b.NewValue; scroll.ScrollToStart(); }; From e690a8a301d6c9e451b6723d215be23d9fdc4d14 Mon Sep 17 00:00:00 2001 From: recapitalverb <41869184+recapitalverb@users.noreply.github.com> Date: Mon, 11 Nov 2019 22:15:19 +0700 Subject: [PATCH 3946/5608] Fix capitalisation in README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 67eb3254e1..bc5beeb83d 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh ## Requirements - 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 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 working with the codebase, we recommend using an IDE with intellisense 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/). +- When working with the codebase, we recommend using an IDE with IntelliSense 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! From 00b92297375b3062337d303cdb9f6885e440fc71 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 18:21:07 +0300 Subject: [PATCH 3947/5608] Add mod filter to beatmap overlay --- .../BeatmapSet/Scores/ScoresContainer.cs | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 580e863a0c..acf0f08956 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -14,6 +14,7 @@ using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Framework.Bindables; +using osu.Game.Rulesets; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -22,11 +23,14 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private const int spacing = 15; public readonly Bindable Beatmap = new Bindable(); + private readonly Bindable ruleset = new Bindable(); private readonly Box background; private readonly ScoreTable scoreTable; private readonly FillFlowContainer topScoresContainer; private readonly LoadingAnimation loadingAnimation; + private readonly FillFlowContainer modFilter; + private readonly LeaderboardModSelector modSelector; [Resolved] private IAPIProvider api { get; set; } @@ -84,6 +88,22 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { + modFilter = new FillFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, spacing), + Children = new Drawable[] + { + new LeaderboardScopeSelector(), + modSelector = new LeaderboardModSelector + { + Ruleset = { BindTarget = ruleset } + } + } + }, topScoresContainer = new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -115,21 +135,33 @@ namespace osu.Game.Overlays.BeatmapSet.Scores protected override void LoadComplete() { base.LoadComplete(); - Beatmap.BindValueChanged(getScores, true); + Beatmap.BindValueChanged(onBeatmapChanged, true); } - private void getScores(ValueChangedEvent beatmap) + private void onBeatmapChanged(ValueChangedEvent beatmap) + { + var beatmapRuleset = beatmap.NewValue?.Ruleset; + + if (modSelector.Ruleset.Value?.Equals(beatmapRuleset) ?? false) + modSelector.DeselectAll(); + else + ruleset.Value = beatmapRuleset; + + getScores(beatmap.NewValue); + } + + private void getScores(BeatmapInfo beatmap) { getScoresRequest?.Cancel(); getScoresRequest = null; Scores = null; - if (beatmap.NewValue?.OnlineBeatmapID.HasValue != true || beatmap.NewValue.Status <= BeatmapSetOnlineStatus.Pending) + if (beatmap?.OnlineBeatmapID.HasValue != true || beatmap.Status <= BeatmapSetOnlineStatus.Pending) return; loadingAnimation.Show(); - getScoresRequest = new GetScoresRequest(beatmap.NewValue, beatmap.NewValue.Ruleset); + getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); getScoresRequest.Success += scores => { loadingAnimation.Hide(); From 2cfd54ca0d577da1872f74b92c83596a6001e1d1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 18:27:48 +0300 Subject: [PATCH 3948/5608] Handle scope changing --- .../BeatmapSet/Scores/ScoresContainer.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index acf0f08956..8058d0fc0f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -15,6 +15,7 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Framework.Bindables; using osu.Game.Rulesets; +using osu.Game.Screens.Select.Leaderboards; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -24,6 +25,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public readonly Bindable Beatmap = new Bindable(); private readonly Bindable ruleset = new Bindable(); + private readonly Bindable scope = new Bindable(); private readonly Box background; private readonly ScoreTable scoreTable; @@ -97,7 +99,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(0, spacing), Children = new Drawable[] { - new LeaderboardScopeSelector(), + new LeaderboardScopeSelector + { + Current = { BindTarget = scope } + }, modSelector = new LeaderboardModSelector { Ruleset = { BindTarget = ruleset } @@ -135,6 +140,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores protected override void LoadComplete() { base.LoadComplete(); + scope.BindValueChanged(_ => getScores()); Beatmap.BindValueChanged(onBeatmapChanged, true); } @@ -147,21 +153,21 @@ namespace osu.Game.Overlays.BeatmapSet.Scores else ruleset.Value = beatmapRuleset; - getScores(beatmap.NewValue); + getScores(); } - private void getScores(BeatmapInfo beatmap) + private void getScores() { getScoresRequest?.Cancel(); getScoresRequest = null; Scores = null; - if (beatmap?.OnlineBeatmapID.HasValue != true || beatmap.Status <= BeatmapSetOnlineStatus.Pending) + if (Beatmap.Value?.OnlineBeatmapID.HasValue != true || Beatmap.Value.Status <= BeatmapSetOnlineStatus.Pending) return; loadingAnimation.Show(); - getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); + getScoresRequest = new GetScoresRequest(Beatmap.Value, Beatmap.Value.Ruleset, scope.Value); getScoresRequest.Success += scores => { loadingAnimation.Hide(); From 31191dadf1c9e487174bbc36a21199f697e721e2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 18:31:42 +0300 Subject: [PATCH 3949/5608] Handle mods change --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 8058d0fc0f..5c1f1ed7e4 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -141,6 +141,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { base.LoadComplete(); scope.BindValueChanged(_ => getScores()); + + modSelector.SelectedMods.ItemsAdded += _ => getScores(); + modSelector.SelectedMods.ItemsRemoved += _ => getScores(); + Beatmap.BindValueChanged(onBeatmapChanged, true); } @@ -167,7 +171,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores return; loadingAnimation.Show(); - getScoresRequest = new GetScoresRequest(Beatmap.Value, Beatmap.Value.Ruleset, scope.Value); + getScoresRequest = new GetScoresRequest(Beatmap.Value, Beatmap.Value.Ruleset, scope.Value, modSelector.SelectedMods); getScoresRequest.Success += scores => { loadingAnimation.Hide(); From 851b414e9874fc5c6bb1e024b8eda2db3ddf94db Mon Sep 17 00:00:00 2001 From: recapitalverb <41869184+recapitalverb@users.noreply.github.com> Date: Mon, 11 Nov 2019 22:37:15 +0700 Subject: [PATCH 3950/5608] Update README.md Co-Authored-By: Joseph Madamba --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc5beeb83d..0ee1bedae4 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ 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 working with the codebase, we recommend using an IDE with IntelliSense 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/). +- When working with the codebase, we recommend using an IDE with IntelliSense 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! From 5f5d130d1a7f2d7022424ce771ec1cc59795ed62 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 18:40:57 +0300 Subject: [PATCH 3951/5608] Update mod filter visibility on user change --- .../BeatmapSet/Scores/ScoresContainer.cs | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 5c1f1ed7e4..1dd224e737 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -16,6 +16,7 @@ using osu.Game.Online.API.Requests; using osu.Framework.Bindables; using osu.Game.Rulesets; using osu.Game.Screens.Select.Leaderboards; +using osu.Game.Users; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -145,7 +146,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores modSelector.SelectedMods.ItemsAdded += _ => getScores(); modSelector.SelectedMods.ItemsRemoved += _ => getScores(); - Beatmap.BindValueChanged(onBeatmapChanged, true); + Beatmap.BindValueChanged(onBeatmapChanged); + api.LocalUser.BindValueChanged(onUserChanged, true); } private void onBeatmapChanged(ValueChangedEvent beatmap) @@ -160,6 +162,18 @@ namespace osu.Game.Overlays.BeatmapSet.Scores getScores(); } + private void onUserChanged(ValueChangedEvent user) + { + scope.Value = BeatmapLeaderboardScope.Global; + modSelector.DeselectAll(); + updateModFilterVisibility(); + } + + private void updateModFilterVisibility() + { + modFilter.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter && !hasNoLeaderboard ? 1 : 0); + } + private void getScores() { getScoresRequest?.Cancel(); @@ -167,7 +181,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Scores = null; - if (Beatmap.Value?.OnlineBeatmapID.HasValue != true || Beatmap.Value.Status <= BeatmapSetOnlineStatus.Pending) + updateModFilterVisibility(); + + if (hasNoLeaderboard) return; loadingAnimation.Show(); @@ -179,5 +195,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }; api.Queue(getScoresRequest); } + + private bool hasNoLeaderboard => Beatmap.Value?.OnlineBeatmapID.HasValue != true || Beatmap.Value.Status <= BeatmapSetOnlineStatus.Pending; } } From c5b64e26a306885caf7f10f2fdab073aa7cd005c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 18:51:29 +0300 Subject: [PATCH 3952/5608] Layout adjustment --- .../BeatmapSet/Scores/ScoresContainer.cs | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 1dd224e737..2f30cde5af 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -110,25 +110,44 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } }, - topScoresContainer = new FillFlowContainer + new Container { - RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), - }, - scoreTable = new ScoreTable - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, spacing), + Children = new Drawable[] + { + topScoresContainer = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + }, + scoreTable = new ScoreTable + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + } + } + }, + loadingAnimation = new LoadingAnimation + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Alpha = 0, + }, + } } } }, - loadingAnimation = new LoadingAnimation - { - Alpha = 0, - Margin = new MarginPadding(20), - }, }; } From 810cfab870dc042ec48e21361cc11dec7097cd1e Mon Sep 17 00:00:00 2001 From: recapitalverb Date: Mon, 11 Nov 2019 22:53:16 +0700 Subject: [PATCH 3953/5608] Fix capitalisation and grammar in README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0ee1bedae4..b8c6451c75 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh ## Requirements - 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 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 working with the codebase, we recommend using an IDE with IntelliSense 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/). +- 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! @@ -68,7 +68,7 @@ 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 the build fails, try to restore nuget packages with `dotnet restore`. +If the build fails, try to restore NuGet packages with `dotnet restore`. ### Testing with resource/framework modifications @@ -76,11 +76,11 @@ Sometimes it may be necessary to cross-test changes in [osu-resources](https://g ### 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. +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. ## 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 on 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). From 32cc7b3d4d69926c49071c85c1113c6ef1625423 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 19:04:50 +0300 Subject: [PATCH 3954/5608] CI fix --- osu.Game/Overlays/BeatmapSetOverlay.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 65d68e4c8c..50fb2782d4 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -37,7 +37,6 @@ namespace osu.Game.Overlays { OsuScrollContainer scroll; Info info; - ScoresContainer scoreContainer; Children = new Drawable[] { @@ -59,7 +58,7 @@ namespace osu.Game.Overlays { Header = new Header(), info = new Info(), - scoreContainer = new ScoresContainer + new ScoresContainer { Beatmap = { BindTarget = Header.Picker.Beatmap } } From 0578f91a764733afafded1fb6b78c1e7990b81b6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 19:06:46 +0300 Subject: [PATCH 3955/5608] Small logic adjustments --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 2f30cde5af..73253546bb 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -161,6 +161,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { base.LoadComplete(); scope.BindValueChanged(_ => getScores()); + ruleset.BindValueChanged(_ => getScores()); modSelector.SelectedMods.ItemsAdded += _ => getScores(); modSelector.SelectedMods.ItemsRemoved += _ => getScores(); @@ -173,12 +174,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { var beatmapRuleset = beatmap.NewValue?.Ruleset; - if (modSelector.Ruleset.Value?.Equals(beatmapRuleset) ?? false) + if (ruleset.Value?.Equals(beatmapRuleset) ?? false) modSelector.DeselectAll(); else ruleset.Value = beatmapRuleset; - getScores(); + scope.Value = BeatmapLeaderboardScope.Global; } private void onUserChanged(ValueChangedEvent user) From 9efcc6addde56b5080ea2ab6b34c8c7aa6b1e647 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 11 Nov 2019 08:53:05 -0800 Subject: [PATCH 3956/5608] Fix remaining proper nouns --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b8c6451c75..a078265d6c 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Before starting, please make sure you are familiar with the [development and tes 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. -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. +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 From 8402fb1490c32a920a2b3ae9a0df122a563560de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 10:02:42 +0900 Subject: [PATCH 3957/5608] Move to const and add some xmldoc for future visitors --- osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs index e262fa3c60..3437af8c1e 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -16,6 +16,12 @@ namespace osu.Game.Rulesets.Osu.Edit { public class DrawableOsuEditRuleset : DrawableOsuRuleset { + /// + /// Hit objects are intentionally made to fade out at a constant slower rate than in gameplay. + /// This allows a mapper to gain better historical context and use recent hitobjects as reference / snap points. + /// + private const double editor_hit_object_fade_out_extension = 500; + public DrawableOsuEditRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { @@ -35,7 +41,7 @@ namespace osu.Game.Rulesets.Osu.Edit return; using (hitObject.BeginAbsoluteSequence(existing.StartTime)) - hitObject.FadeOut(500).Expire(); + hitObject.FadeOut(editor_hit_object_fade_out_extension).Expire(); break; } } From 5bb65d0716ad1f0520b152e3ab14701b1f998fd8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 10:18:25 +0900 Subject: [PATCH 3958/5608] Rename button class --- .../TestSceneStatefulMenuItem.cs | 8 +++--- .../Graphics/UserInterface/TernaryState.cs | 2 +- ...ateMenuItem.cs => TernaryStateMenuItem.cs} | 26 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) rename osu.Game/Graphics/UserInterface/{ThreeStateMenuItem.cs => TernaryStateMenuItem.cs} (69%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index 1eff30d15e..2ada5b927b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.UserInterface { typeof(OsuMenu), typeof(StatefulMenuItem), - typeof(ThreeStateMenuItem), + typeof(TernaryStateMenuItem), typeof(DrawableStatefulMenuItem), }; @@ -39,9 +39,9 @@ namespace osu.Game.Tests.Visual.UserInterface Origin = Anchor.Centre, Items = new[] { - new ThreeStateMenuItem("First"), - new ThreeStateMenuItem("Second") { State = { BindTarget = state } }, - new ThreeStateMenuItem("Third") { State = { Value = TernaryState.True } }, + new TernaryStateMenuItem("First"), + new TernaryStateMenuItem("Second") { State = { BindTarget = state } }, + new TernaryStateMenuItem("Third") { State = { Value = TernaryState.True } }, } }; }); diff --git a/osu.Game/Graphics/UserInterface/TernaryState.cs b/osu.Game/Graphics/UserInterface/TernaryState.cs index 784122e35c..d4de28044f 100644 --- a/osu.Game/Graphics/UserInterface/TernaryState.cs +++ b/osu.Game/Graphics/UserInterface/TernaryState.cs @@ -15,7 +15,7 @@ namespace osu.Game.Graphics.UserInterface /// /// The current state is a combination of and . - /// The state becomes if the is pressed. + /// The state becomes if the is pressed. /// Indeterminate, diff --git a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs b/osu.Game/Graphics/UserInterface/TernaryStateMenuItem.cs similarity index 69% rename from osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs rename to osu.Game/Graphics/UserInterface/TernaryStateMenuItem.cs index c5b9edf3c4..2d9e2106d4 100644 --- a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/TernaryStateMenuItem.cs @@ -9,37 +9,37 @@ namespace osu.Game.Graphics.UserInterface /// /// An with three possible states. /// - public class ThreeStateMenuItem : StatefulMenuItem + public class TernaryStateMenuItem : StatefulMenuItem { /// - /// Creates a new . + /// Creates a new . /// /// The text to display. - /// The type of action which this performs. - public ThreeStateMenuItem(string text, MenuItemType type = MenuItemType.Standard) + /// The type of action which this performs. + public TernaryStateMenuItem(string text, MenuItemType type = MenuItemType.Standard) : this(text, type, null) { } /// - /// Creates a new . + /// Creates a new . /// /// The text to display. - /// The type of action which this performs. - /// A delegate to be invoked when this is pressed. - public ThreeStateMenuItem(string text, MenuItemType type, Action action) + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. + public TernaryStateMenuItem(string text, MenuItemType type, Action action) : this(text, getNextState, type, action) { } /// - /// Creates a new . + /// Creates a new . /// /// The text to display. - /// A function that mutates a state to another state after this is pressed. - /// The type of action which this performs. - /// A delegate to be invoked when this is pressed. - protected ThreeStateMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) + /// A function that mutates a state to another state after this is pressed. + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. + protected TernaryStateMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) : base(text, changeStateFunc, type, action) { } From a43b0ee01bc9b92db30ff4084c11c09b3547dd26 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 10:45:46 +0900 Subject: [PATCH 3959/5608] Apply naming and styling changes --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 ++ .../Edit/Compose/Components/SelectionHandler.cs | 16 ++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index f3399af2de..c6f5a075e0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -203,12 +203,14 @@ namespace osu.Game.Rulesets.Osu.Objects var sampleList = new List(); if (firstSample != null) + { sampleList.Add(new HitSampleInfo { Bank = firstSample.Bank, Volume = firstSample.Volume, Name = @"slidertick", }); + } foreach (var tick in NestedHitObjects.OfType()) tick.Samples = sampleList; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 7b61640c89..942643d116 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -241,36 +241,36 @@ namespace osu.Game.Screens.Edit.Compose.Components private MenuItem createHitSampleMenuItem(string name, string sampleName) { - return new ThreeStateMenuItem(name, MenuItemType.Standard, setHitSampleState) + return new TernaryStateMenuItem(name, MenuItemType.Standard, setHitSampleState) { State = { Value = getHitSampleState() } }; - void setHitSampleState(ThreeStates state) + void setHitSampleState(TernaryState state) { switch (state) { - case ThreeStates.Disabled: + case TernaryState.False: RemoveHitSample(sampleName); break; - case ThreeStates.Enabled: + case TernaryState.True: AddHitSample(sampleName); break; } } - ThreeStates getHitSampleState() + TernaryState getHitSampleState() { int countExisting = SelectedHitObjects.Count(h => h.Samples.Any(s => s.Name == sampleName)); if (countExisting == 0) - return ThreeStates.Disabled; + return TernaryState.False; if (countExisting < SelectedHitObjects.Count()) - return ThreeStates.Indeterminate; + return TernaryState.Indeterminate; - return ThreeStates.Enabled; + return TernaryState.True; } } From 2f8768a4b10af5290f94c80cba54184b2957b5d9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 11:04:49 +0900 Subject: [PATCH 3960/5608] Move LabelledDropdown local to usage --- osu.Game.Tournament/Screens/SetupScreen.cs | 21 ++++++++++++++ .../UserInterfaceV2/LabelledDropdown.cs | 29 ------------------- 2 files changed, 21 insertions(+), 29 deletions(-) delete mode 100644 osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index b511d572da..8e1481d87c 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -100,6 +101,26 @@ namespace osu.Game.Tournament.Screens }; } + public class LabelledDropdown : LabelledComponent, T> + { + public LabelledDropdown() + : base(true) + { + } + + public IEnumerable Items + { + get => Component.Items; + set => Component.Items = value; + } + + protected override OsuDropdown CreateComponent() => new OsuDropdown + { + RelativeSizeAxes = Axes.X, + Width = 0.5f, + }; + } + private class ActionableInfo : LabelledDrawable { private OsuButton button; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs deleted file mode 100644 index 7e50fa7bc6..0000000000 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterface; - -namespace osu.Game.Graphics.UserInterfaceV2 -{ - public class LabelledDropdown : LabelledComponent, T> - { - public LabelledDropdown() - : base(true) - { - } - - public IEnumerable Items - { - get => Component.Items; - set => Component.Items = value; - } - - protected override OsuDropdown CreateComponent() => new OsuDropdown - { - RelativeSizeAxes = Axes.X, - Width = 0.5f, - }; - } -} From 9f1d490ac9876457e7299ed758da3858f893b105 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 12:18:24 +0900 Subject: [PATCH 3961/5608] Only handle selection input on blueprints --- osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 942643d116..258304d775 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -90,6 +90,8 @@ namespace osu.Game.Screens.Edit.Compose.Components public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => selectedBlueprints.Any(b => b.IsHovered); + #endregion #region Selection Handling From 3f8928ca253660e6ae7a686e5c6f0d3faad60075 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 13:41:54 +0900 Subject: [PATCH 3962/5608] Suppress warnings --- osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs | 3 ++- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 ++ osu.Game/Rulesets/RulesetConfigCache.cs | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs index 179cd5e2dc..5a3ad5e786 100644 --- a/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Configuration.Tracking; namespace osu.Game.Rulesets.Configuration { - public interface IRulesetConfigManager : ITrackableConfigManager + public interface IRulesetConfigManager : ITrackableConfigManager, IDisposable { } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 818571bb23..35228e9ad1 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -149,8 +149,10 @@ namespace osu.Game.Rulesets.Objects.Drawables return; if (HitObject.SampleControlPoint == null) + { throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); + } samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray(); foreach (var s in samples) diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index cdcd2666cf..d42428638c 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets // ensures any potential database operations are finalised before game destruction. foreach (var c in configCache.Values) - (c as IDisposable)?.Dispose(); + c?.Dispose(); } } } From b4525c1f6e95d61a56ca33b5a09cbeba38d60ab5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 14:42:30 +0900 Subject: [PATCH 3963/5608] Fix right clicking to select not showing context menu --- osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 258304d775..3a7c85d36c 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -90,8 +90,6 @@ namespace osu.Game.Screens.Edit.Compose.Components public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => selectedBlueprints.Any(b => b.IsHovered); - #endregion #region Selection Handling @@ -223,7 +221,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { get { - if (!SelectedBlueprints.Any()) + if (!selectedBlueprints.Any(b => b.IsHovered)) return Array.Empty(); return new MenuItem[] From a69a4643c950526a0683120799c06f7051f478ba Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 12 Nov 2019 08:45:21 +0300 Subject: [PATCH 3964/5608] Simplify LINQ expressions --- .../Overlays/BeatmapSet/LeaderboardModSelector.cs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 75c24cb710..a7128ca157 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -53,12 +53,7 @@ namespace osu.Game.Overlays.BeatmapSet return; modsContainer.Add(new ModButton(new NoMod())); - - ruleset.NewValue.CreateInstance().GetAllMods().ForEach(mod => - { - if (mod.Ranked) - modsContainer.Add(new ModButton(mod)); - }); + modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); modsContainer.ForEach(button => button.OnSelectionChanged += selectionChanged); } @@ -77,11 +72,7 @@ namespace osu.Game.Overlays.BeatmapSet protected override bool OnHover(HoverEvent e) { if (!SelectedMods.Any()) - modsContainer.ForEach(button => - { - if (!button.IsHovered) - button.Highlighted.Value = false; - }); + modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = false); return base.OnHover(e); } From 461f76926f6e23015eaec30ae5344f3ea9085861 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 13:32:31 +0900 Subject: [PATCH 3965/5608] Add right-click menu to support control point addition --- .../Sliders/SliderSelectionBlueprint.cs | 55 ++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 25362820a3..a77350714f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -1,8 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -10,10 +15,11 @@ using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osuTK; +using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { - public class SliderSelectionBlueprint : OsuSelectionBlueprint + public class SliderSelectionBlueprint : OsuSelectionBlueprint, IHasContextMenu { protected readonly SliderBodyPiece BodyPiece; protected readonly SliderCircleSelectionBlueprint HeadBlueprint; @@ -44,6 +50,48 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders BodyPiece.UpdateFrom(HitObject); } + private Vector2 rightClickPosition; + + protected override bool OnMouseDown(MouseDownEvent e) + { + if (e.Button == MouseButton.Right) + rightClickPosition = e.MouseDownPosition; + + return false; + } + + private void addControlPoint() + { + Vector2 position = rightClickPosition - HitObject.Position; + + var controlPoints = new Vector2[HitObject.Path.ControlPoints.Length + 1]; + HitObject.Path.ControlPoints.CopyTo(controlPoints); + + // Find the index at which the point will be inserted, by increasing x-coordinates + int insertionIndex = Array.FindIndex(controlPoints, 0, controlPoints.Length - 1, c => c.X >= position.X); + + // If no index was found, it should be inserted at the end + if (insertionIndex == -1) + insertionIndex = controlPoints.Length - 1; + + // Move the control points from the insertion index onwards to make room for the insertion + Array.Copy(controlPoints, insertionIndex, controlPoints, insertionIndex + 1, controlPoints.Length - insertionIndex - 1); + + if (insertionIndex == 0) + { + // Special case for a new first control point being added - the entire slider moves + HitObject.Position += position; + + // The first control point is always at (0, 0), but all other control points need to be re-referenced + for (int i = 1; i < controlPoints.Length; i++) + controlPoints[i] -= position; + } + else + controlPoints[insertionIndex] = position; + + onNewControlPoints(controlPoints); + } + private void onNewControlPoints(Vector2[] controlPoints) { var unsnappedPath = new SliderPath(controlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, controlPoints); @@ -54,6 +102,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders UpdateHitObject(); } + public MenuItem[] ContextMenuItems => new MenuItem[] + { + new OsuMenuItem("Add control point", MenuItemType.Standard, addControlPoint), + }; + public override Vector2 SelectionPoint => HeadBlueprint.SelectionPoint; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => BodyPiece.ReceivePositionalInputAt(screenSpacePos); From 10fd5ef5a7137a66f037e0c49fdf19173986e0e8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 13:38:42 +0900 Subject: [PATCH 3966/5608] Merge context menus --- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 5 ++--- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 6 ++++++ .../Screens/Edit/Compose/Components/SelectionHandler.cs | 7 ++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index a77350714f..e87145fdc3 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -4,7 +4,6 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; @@ -19,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { - public class SliderSelectionBlueprint : OsuSelectionBlueprint, IHasContextMenu + public class SliderSelectionBlueprint : OsuSelectionBlueprint { protected readonly SliderBodyPiece BodyPiece; protected readonly SliderCircleSelectionBlueprint HeadBlueprint; @@ -102,7 +101,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders UpdateHitObject(); } - public MenuItem[] ContextMenuItems => new MenuItem[] + public override MenuItem[] ContextMenuItems => new MenuItem[] { new OsuMenuItem("Add control point", MenuItemType.Standard, addControlPoint), }; diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 2923411ce1..bf99f83e0b 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -104,6 +105,11 @@ namespace osu.Game.Rulesets.Edit public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => DrawableObject.ReceivePositionalInputAt(screenSpacePos); + /// + /// The s to be displayed in the context menu for this . + /// + public virtual MenuItem[] ContextMenuItems => Array.Empty(); + /// /// The screen-space point that causes this to be selected. /// diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 3a7c85d36c..d5bbeeb907 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -224,7 +224,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (!selectedBlueprints.Any(b => b.IsHovered)) return Array.Empty(); - return new MenuItem[] + var items = new List { new OsuMenuItem("Sound") { @@ -236,6 +236,11 @@ namespace osu.Game.Screens.Edit.Compose.Components } } }; + + if (selectedBlueprints.Count == 1) + items.AddRange(selectedBlueprints[0].ContextMenuItems); + + return items.ToArray(); } } From 13b11996e0f625cec223e18ebecf8a83a2898bd0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 14:37:07 +0900 Subject: [PATCH 3967/5608] Improve closest segment algorithm --- .../Sliders/SliderSelectionBlueprint.cs | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index e87145fdc3..9da684025f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -66,27 +66,33 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders var controlPoints = new Vector2[HitObject.Path.ControlPoints.Length + 1]; HitObject.Path.ControlPoints.CopyTo(controlPoints); - // Find the index at which the point will be inserted, by increasing x-coordinates - int insertionIndex = Array.FindIndex(controlPoints, 0, controlPoints.Length - 1, c => c.X >= position.X); + int insertionIndex = 0; + float minDistance = float.MaxValue; - // If no index was found, it should be inserted at the end - if (insertionIndex == -1) - insertionIndex = controlPoints.Length - 1; + for (int i = 0; i < controlPoints.Length - 2; i++) + { + Vector2 p1 = controlPoints[i]; + Vector2 p2 = controlPoints[i + 1]; + + if (p1 == p2) + continue; + + Vector2 dir = p2 - p1; + float projLength = MathHelper.Clamp(Vector2.Dot(position - p1, dir) / dir.LengthSquared, 0, 1); + Vector2 proj = p1 + projLength * dir; + + float dist = Vector2.Distance(position, proj); + + if (dist < minDistance) + { + insertionIndex = i + 1; + minDistance = dist; + } + } // Move the control points from the insertion index onwards to make room for the insertion Array.Copy(controlPoints, insertionIndex, controlPoints, insertionIndex + 1, controlPoints.Length - insertionIndex - 1); - - if (insertionIndex == 0) - { - // Special case for a new first control point being added - the entire slider moves - HitObject.Position += position; - - // The first control point is always at (0, 0), but all other control points need to be re-referenced - for (int i = 1; i < controlPoints.Length; i++) - controlPoints[i] -= position; - } - else - controlPoints[insertionIndex] = position; + controlPoints[insertionIndex] = position; onNewControlPoints(controlPoints); } From 316dcae6145594ec2cc83ab2aed1b3c7fb1ba6c7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 14:41:10 +0900 Subject: [PATCH 3968/5608] Use squared distance --- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 9da684025f..0f058dc088 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -78,10 +78,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders continue; Vector2 dir = p2 - p1; + float projLength = MathHelper.Clamp(Vector2.Dot(position - p1, dir) / dir.LengthSquared, 0, 1); Vector2 proj = p1 + projLength * dir; - float dist = Vector2.Distance(position, proj); + float dist = Vector2.DistanceSquared(position, proj); if (dist < minDistance) { From 407ca41ba454f1bd644ecb3fc1f5eabf9f1fe564 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 14:44:11 +0900 Subject: [PATCH 3969/5608] Simplify using existing tools --- .../Blueprints/Sliders/SliderSelectionBlueprint.cs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 0f058dc088..34dc7ddc24 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; @@ -71,18 +72,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders for (int i = 0; i < controlPoints.Length - 2; i++) { - Vector2 p1 = controlPoints[i]; - Vector2 p2 = controlPoints[i + 1]; - - if (p1 == p2) - continue; - - Vector2 dir = p2 - p1; - - float projLength = MathHelper.Clamp(Vector2.Dot(position - p1, dir) / dir.LengthSquared, 0, 1); - Vector2 proj = p1 + projLength * dir; - - float dist = Vector2.DistanceSquared(position, proj); + float dist = new Line(controlPoints[i], controlPoints[i + 1]).DistanceToPoint(position); if (dist < minDistance) { From 93d8cd38ca4652f5082fdfbd3d87120e144bbc37 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 15:00:57 +0900 Subject: [PATCH 3970/5608] Implement addition via ctrl+click --- .../Sliders/SliderSelectionBlueprint.cs | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 34dc7ddc24..226afd68b1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; @@ -54,15 +55,47 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders protected override bool OnMouseDown(MouseDownEvent e) { - if (e.Button == MouseButton.Right) - rightClickPosition = e.MouseDownPosition; + switch (e.Button) + { + case MouseButton.Right: + rightClickPosition = e.MouseDownPosition; + return false; // Allow right click to be handled by context menu + + case MouseButton.Left when e.ControlPressed: + placementControlPointIndex = addControlPoint(e.MousePosition); + return true; // Stop input from being handled and modifying the selection + } return false; } - private void addControlPoint() + private int? placementControlPointIndex; + + protected override bool OnDragStart(DragStartEvent e) => placementControlPointIndex != null; + + protected override bool OnDrag(DragEvent e) { - Vector2 position = rightClickPosition - HitObject.Position; + Debug.Assert(placementControlPointIndex != null); + + Vector2 position = e.MousePosition - HitObject.Position; + + var controlPoints = HitObject.Path.ControlPoints.ToArray(); + controlPoints[placementControlPointIndex.Value] = position; + + onNewControlPoints(controlPoints); + + return true; + } + + protected override bool OnDragEnd(DragEndEvent e) + { + placementControlPointIndex = null; + return true; + } + + private int addControlPoint(Vector2 position) + { + position -= HitObject.Position; var controlPoints = new Vector2[HitObject.Path.ControlPoints.Length + 1]; HitObject.Path.ControlPoints.CopyTo(controlPoints); @@ -86,6 +119,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders controlPoints[insertionIndex] = position; onNewControlPoints(controlPoints); + + return insertionIndex; } private void onNewControlPoints(Vector2[] controlPoints) @@ -100,7 +135,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders public override MenuItem[] ContextMenuItems => new MenuItem[] { - new OsuMenuItem("Add control point", MenuItemType.Standard, addControlPoint), + new OsuMenuItem("Add control point", MenuItemType.Standard, () => addControlPoint(rightClickPosition)), }; public override Vector2 SelectionPoint => HeadBlueprint.SelectionPoint; From 25eb9642904dfe8e640e85c2430c290de04e6462 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 15:03:58 +0900 Subject: [PATCH 3971/5608] Simplify overlay adding logic --- osu.Game/OsuGame.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index fa97044c95..e2ece8422c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -593,14 +593,14 @@ namespace osu.Game loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true); - var login = loadComponentSingleFile(new LoginOverlay + loadComponentSingleFile(new LoginOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }, rightFloatingOverlayContent.Add, true); - var nowPlaying = loadComponentSingleFile(new NowPlayingOverlay + loadComponentSingleFile(new NowPlayingOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, @@ -615,10 +615,10 @@ namespace osu.Game Add(externalLinkOpener = new ExternalLinkOpener()); + // side overlays which cancel each other. var singleDisplaySideOverlays = new OverlayContainer[] { Settings, notifications }; - overlays.AddRange(singleDisplaySideOverlays); - foreach (var overlay in singleDisplaySideOverlays) + foreach (var overlay in new OverlayContainer[] { Settings, notifications }) { overlay.State.ValueChanged += state => { @@ -630,7 +630,6 @@ namespace osu.Game // eventually informational overlays should be displayed in a stack, but for now let's only allow one to stay open at a time. var informationalOverlays = new OverlayContainer[] { beatmapSetOverlay, userProfile }; - overlays.AddRange(informationalOverlays); foreach (var overlay in informationalOverlays) { @@ -644,7 +643,6 @@ namespace osu.Game // ensure only one of these overlays are open at once. var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, social, direct, changelogOverlay }; - overlays.AddRange(singleDisplayOverlays); foreach (var overlay in singleDisplayOverlays) { @@ -659,8 +657,6 @@ namespace osu.Game }; } - overlays.AddRange(new OverlayContainer[] { login, nowPlaying }); - OverlayActivationMode.ValueChanged += mode => { if (mode.NewValue != OverlayActivation.All) CloseAllOverlays(); @@ -747,6 +743,9 @@ namespace osu.Game if (cache) dependencies.Cache(d); + if (d is OverlayContainer overlay) + overlays.Add(overlay); + // schedule is here to ensure that all component loads are done after LoadComplete is run (and thus all dependencies are cached). // with some better organisation of LoadComplete to do construction and dependency caching in one step, followed by calls to loadComponentSingleFile, // we could avoid the need for scheduling altogether. From 35351d7f7c34cb8f0395aa0992f245b7dfc52ddb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 15:04:51 +0900 Subject: [PATCH 3972/5608] Use variable instead of duplicated list --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e2ece8422c..f6b8d5cfbb 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -618,7 +618,7 @@ namespace osu.Game // side overlays which cancel each other. var singleDisplaySideOverlays = new OverlayContainer[] { Settings, notifications }; - foreach (var overlay in new OverlayContainer[] { Settings, notifications }) + foreach (var overlay in singleDisplaySideOverlays) { overlay.State.ValueChanged += state => { From a0884fe9d42a0815f642eb7203246b6bf608d838 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 15:07:54 +0900 Subject: [PATCH 3973/5608] Fix being able to add while not selected --- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 226afd68b1..820d6c92d7 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders rightClickPosition = e.MouseDownPosition; return false; // Allow right click to be handled by context menu - case MouseButton.Left when e.ControlPressed: + case MouseButton.Left when e.ControlPressed && IsSelected: placementControlPointIndex = addControlPoint(e.MousePosition); return true; // Stop input from being handled and modifying the selection } From 47be20fa3773c1fed6ba2e521d9a71b4c93a3582 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 15:13:47 +0900 Subject: [PATCH 3974/5608] Private set on track for safety --- osu.Game/Audio/PreviewTrack.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index b39d2bc8f8..5df656e1e0 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -24,7 +24,7 @@ namespace osu.Game.Audio /// public event Action Started; - protected Track Track; + protected Track Track { get; private set; } private bool hasStarted; From 46d02d9077e75619b535975778118175fa704601 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 17:37:01 +0900 Subject: [PATCH 3975/5608] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 6c40dc4812..6fab2e7868 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 baa1c14071..af60da3e70 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 0184e45c15..8124357312 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,6 +73,6 @@ - + From 58df6930b279791e6cad547718d4182bd91aa22c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 19:34:20 +0900 Subject: [PATCH 3976/5608] Get error message from server --- osu.Game/Online/API/APIRequest.cs | 23 +++++++++++++++++++ .../BeatmapSet/Buttons/FavouriteButton.cs | 13 ++++------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index 4f613d5c3c..ea0d50511f 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using Newtonsoft.Json; using osu.Framework.IO.Network; using osu.Framework.Logging; @@ -112,6 +113,22 @@ namespace osu.Game.Online.API cancelled = true; WebRequest?.Abort(); + string responseString = WebRequest?.ResponseString; + + if (!string.IsNullOrEmpty(responseString)) + { + try + { + // attempt to decode a displayable error string. + var error = JsonConvert.DeserializeObject(responseString); + if (error != null) + e = new Exception(error.ErrorMessage, e); + } + catch + { + } + } + Logger.Log($@"Failing request {this} ({e})", LoggingTarget.Network); pendingFailure = () => Failure?.Invoke(e); checkAndScheduleFailure(); @@ -129,6 +146,12 @@ namespace osu.Game.Online.API pendingFailure = null; return true; } + + private class DisplayableError + { + [JsonProperty("error")] + public string ErrorMessage; + } } public delegate void APIFailureHandler(Exception e); diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index e2bc1ee008..f059e06214 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -71,15 +71,12 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons request.Success += () => favourited.Value = !favourited.Value; request.Failure += exception => { - if (exception.Message == "UnprocessableEntity") + notifications.Post(new SimpleNotification { - notifications.Post(new SimpleNotification - { - Text = @"You have too many favourited beatmaps! Please unfavourite some before trying again.", - Icon = FontAwesome.Solid.Times, - }); - loading.Hide(); - } + Text = exception.Message, + Icon = FontAwesome.Solid.Times, + }); + loading.Hide(); }; api.Queue(request); }; From bbeab6fa7650c07441dddb5bc648f58033634378 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 17:45:42 +0800 Subject: [PATCH 3977/5608] Use auto property. --- .editorconfig | 2 +- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 8 +------- .../Objects/Drawables/Pieces/TaikoPiece.cs | 16 ++-------------- .../Gameplay/TestSceneSkinnableDrawable.cs | 6 ++---- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 6 ++---- osu.Game/OsuGameBase.cs | 12 +++++------- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 5 ++--- osu.Game/Overlays/Chat/ChatLine.cs | 9 ++++----- .../KeyBinding/VariantBindingsSubsection.cs | 5 ++--- osu.Game/Overlays/VolumeOverlay.cs | 7 +++---- osu.Game/Skinning/SkinnableSprite.cs | 6 ++---- .../Storyboards/Drawables/DrawableStoryboard.cs | 5 ++--- osu.sln.DotSettings | 4 +++- 13 files changed, 31 insertions(+), 60 deletions(-) diff --git a/.editorconfig b/.editorconfig index 2c000d3881..34217e6206 100644 --- a/.editorconfig +++ b/.editorconfig @@ -137,7 +137,7 @@ csharp_style_expression_bodied_properties = true:silent dotnet_style_object_initializer = true:warning dotnet_style_collection_initializer = true:warning dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning -dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_auto_properties = true:warning dotnet_style_prefer_conditional_expression_over_assignment = true:silent dotnet_style_prefer_conditional_expression_over_return = true:silent dotnet_style_prefer_compound_assignment = true:silent diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 80a3af0aa0..33780427b6 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -116,13 +116,7 @@ namespace osu.Game.Rulesets.Catch.Objects public double Duration => EndTime - StartTime; - private SliderPath path; - - public SliderPath Path - { - get => path; - set => path = value; - } + public SliderPath Path { get; set; } public double Distance => Path.Distance; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs index 773e3ae907..8067054f8f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs @@ -10,27 +10,15 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces { public class TaikoPiece : BeatSyncedContainer, IHasAccentColour { - private Color4 accentColour; - /// /// The colour of the inner circle and outer glows. /// - public virtual Color4 AccentColour - { - get => accentColour; - set => accentColour = value; - } - - private bool kiaiMode; + public virtual Color4 AccentColour { get; set; } /// /// Whether Kiai mode effects are enabled for this circle piece. /// - public virtual bool KiaiMode - { - get => kiaiMode; - set => kiaiMode = value; - } + public virtual bool KiaiMode { get; set; } public TaikoPiece() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs index 8beb107269..ec94053679 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs @@ -335,16 +335,14 @@ namespace osu.Game.Tests.Visual.Gameplay private class TestSkinComponent : ISkinComponent { - private readonly string name; - public TestSkinComponent(string name) { - this.name = name; + LookupName = name; } public string ComponentGroup => string.Empty; - public string LookupName => name; + public string LookupName { get; } } } } diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 623db07938..6ac5219282 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -288,17 +288,15 @@ namespace osu.Game.Online.Leaderboards private class ScoreComponentLabel : Container, IHasTooltip { private const float icon_size = 20; - - private readonly string name; private readonly FillFlowContainer content; public override bool Contains(Vector2 screenSpacePos) => content.Contains(screenSpacePos); - public string TooltipText => name; + public string TooltipText { get; } public ScoreComponentLabel(LeaderboardScoreStatistic statistic) { - name = statistic.Name; + TooltipText = statistic.Name; AutoSizeAxes = Axes.Both; Child = content = new FillFlowContainer diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 4a432bf74e..0845a33639 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -74,8 +74,6 @@ namespace osu.Game protected Storage Storage { get; set; } - private Bindable beatmap; // cached via load() method - [Cached] [Cached(typeof(IBindable))] protected readonly Bindable Ruleset = new Bindable(); @@ -85,7 +83,7 @@ namespace osu.Game [Cached(Type = typeof(IBindable>))] protected readonly Bindable> Mods = new Bindable>(Array.Empty()); - protected Bindable Beatmap => beatmap; + protected Bindable Beatmap { get; private set; } // cached via load() method private Bindable fpsDisplayVisible; @@ -201,16 +199,16 @@ namespace osu.Game // this adds a global reduction of track volume for the time being. Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8)); - beatmap = new NonNullableBindable(defaultBeatmap); - beatmap.BindValueChanged(b => ScheduleAfterChildren(() => + Beatmap = new NonNullableBindable(defaultBeatmap); + Beatmap.BindValueChanged(b => ScheduleAfterChildren(() => { // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo) if (b.OldValue?.TrackLoaded == true && b.OldValue?.Track != b.NewValue?.Track) b.OldValue.RecycleTrack(); })); - dependencies.CacheAs>(beatmap); - dependencies.CacheAs(beatmap); + dependencies.CacheAs>(Beatmap); + dependencies.CacheAs(Beatmap); FileStore.Cleanup(); diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 5b10c4e0bb..7092b860a0 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -91,10 +91,9 @@ namespace osu.Game.Overlays.BeatmapSet private class Statistic : Container, IHasTooltip { - private readonly string name; private readonly OsuSpriteText value; - public string TooltipText => name; + public string TooltipText { get; } public string Value { @@ -104,7 +103,7 @@ namespace osu.Game.Overlays.BeatmapSet public Statistic(IconUsage icon, string name) { - this.name = name; + TooltipText = name; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index db378bde73..8abde8a24f 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -58,9 +58,8 @@ namespace osu.Game.Overlays.Chat private Message message; private OsuSpriteText username; - private LinkFlowContainer contentFlow; - public LinkFlowContainer ContentFlow => contentFlow; + public LinkFlowContainer ContentFlow { get; private set; } public Message Message { @@ -164,7 +163,7 @@ namespace osu.Game.Overlays.Chat Padding = new MarginPadding { Left = MessagePadding + HorizontalPadding }, Children = new Drawable[] { - contentFlow = new LinkFlowContainer(t => + ContentFlow = new LinkFlowContainer(t => { t.Shadow = false; @@ -206,8 +205,8 @@ namespace osu.Game.Overlays.Chat // remove non-existent channels from the link list message.Links.RemoveAll(link => link.Action == LinkAction.OpenChannel && chatManager?.AvailableChannels.Any(c => c.Name == link.Argument) != true); - contentFlow.Clear(); - contentFlow.AddLinks(message.DisplayContent, message.Links); + ContentFlow.Clear(); + ContentFlow.AddLinks(message.DisplayContent, message.Links); } private class MessageSender : OsuClickableContainer, IHasContextMenu diff --git a/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs index 07af657686..861d59c8f4 100644 --- a/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs +++ b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs @@ -7,8 +7,7 @@ namespace osu.Game.Overlays.KeyBinding { public class VariantBindingsSubsection : KeyBindingsSubsection { - protected override string Header => variantName; - private readonly string variantName; + protected override string Header { get; } public VariantBindingsSubsection(RulesetInfo ruleset, int variant) : base(variant) @@ -17,7 +16,7 @@ namespace osu.Game.Overlays.KeyBinding var rulesetInstance = ruleset.CreateInstance(); - variantName = rulesetInstance.GetVariantName(variant); + Header = rulesetInstance.GetVariantName(variant); Defaults = rulesetInstance.GetDefaultKeyBindings(variant); } } diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index ca7665eba5..b484921cce 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -30,8 +30,7 @@ namespace osu.Game.Overlays private readonly BindableDouble muteAdjustment = new BindableDouble(); - private readonly Bindable isMuted = new Bindable(); - public Bindable IsMuted => isMuted; + public Bindable IsMuted { get; } = new Bindable(); [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colours) @@ -66,7 +65,7 @@ namespace osu.Game.Overlays muteButton = new MuteButton { Margin = new MarginPadding { Top = 100 }, - Current = { BindTarget = isMuted } + Current = { BindTarget = IsMuted } } } }, @@ -76,7 +75,7 @@ namespace osu.Game.Overlays volumeMeterEffect.Bindable.BindTo(audio.VolumeSample); volumeMeterMusic.Bindable.BindTo(audio.VolumeTrack); - isMuted.BindValueChanged(muted => + IsMuted.BindValueChanged(muted => { if (muted.NewValue) audio.AddAdjustment(AdjustableProperty.Volume, muteAdjustment); diff --git a/osu.Game/Skinning/SkinnableSprite.cs b/osu.Game/Skinning/SkinnableSprite.cs index 4b78493e97..e225bfc490 100644 --- a/osu.Game/Skinning/SkinnableSprite.cs +++ b/osu.Game/Skinning/SkinnableSprite.cs @@ -28,14 +28,12 @@ namespace osu.Game.Skinning private class SpriteComponent : ISkinComponent { - private readonly string textureName; - public SpriteComponent(string textureName) { - this.textureName = textureName; + LookupName = textureName; } - public string LookupName => textureName; + public string LookupName { get; } } } } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index 2b27a56844..7a84ac009a 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -16,8 +16,7 @@ namespace osu.Game.Storyboards.Drawables { public Storyboard Storyboard { get; private set; } - private readonly Container content; - protected override Container Content => content; + protected override Container Content { get; } protected override Vector2 DrawScale => new Vector2(Parent.DrawHeight / 480); @@ -49,7 +48,7 @@ namespace osu.Game.Storyboards.Drawables Anchor = Anchor.Centre; Origin = Anchor.Centre; - AddInternal(content = new Container + AddInternal(Content = new Container { Size = new Vector2(640, 480), Anchor = Anchor.Centre, diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 44c5c05bc0..63d055702b 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -63,7 +63,9 @@ WARNING WARNING WARNING - HINT + WARNING + WARNING + WARNING WARNING WARNING HINT From 4b75e0bf6a5824668ee78921bf047a1f5ead940f Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 17:50:50 +0800 Subject: [PATCH 3978/5608] Redundant assignment. --- .editorconfig | 2 +- .../Legacy/HitObjectPatternGenerator.cs | 24 +++++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/.editorconfig b/.editorconfig index 34217e6206..05927526d5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -153,7 +153,7 @@ csharp_style_conditional_delegate_call = true:suggestion #Style - unused dotnet_code_quality_unused_parameters = non_public:silent csharp_style_unused_value_expression_statement_preference = discard_variable:silent -csharp_style_unused_value_assignment_preference = discard_variable:silent +csharp_style_unused_value_assignment_preference = discard_variable:suggestion #Style - variable declaration csharp_style_inlined_variable_declaration = true:silent diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index ada960a78d..be3c43699d 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -168,43 +168,43 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } if (convertType.HasFlag(PatternType.KeepSingle)) - return pattern = generateRandomNotes(1); + return generateRandomNotes(1); if (convertType.HasFlag(PatternType.Mirror)) { if (ConversionDifficulty > 6.5) - return pattern = generateRandomPatternWithMirrored(0.12, 0.38, 0.12); + return generateRandomPatternWithMirrored(0.12, 0.38, 0.12); if (ConversionDifficulty > 4) - return pattern = generateRandomPatternWithMirrored(0.12, 0.17, 0); + return generateRandomPatternWithMirrored(0.12, 0.17, 0); - return pattern = generateRandomPatternWithMirrored(0.12, 0, 0); + return generateRandomPatternWithMirrored(0.12, 0, 0); } if (ConversionDifficulty > 6.5) { if (convertType.HasFlag(PatternType.LowProbability)) - return pattern = generateRandomPattern(0.78, 0.42, 0, 0); + return generateRandomPattern(0.78, 0.42, 0, 0); - return pattern = generateRandomPattern(1, 0.62, 0, 0); + return generateRandomPattern(1, 0.62, 0, 0); } if (ConversionDifficulty > 4) { if (convertType.HasFlag(PatternType.LowProbability)) - return pattern = generateRandomPattern(0.35, 0.08, 0, 0); + return generateRandomPattern(0.35, 0.08, 0, 0); - return pattern = generateRandomPattern(0.52, 0.15, 0, 0); + return generateRandomPattern(0.52, 0.15, 0, 0); } if (ConversionDifficulty > 2) { if (convertType.HasFlag(PatternType.LowProbability)) - return pattern = generateRandomPattern(0.18, 0, 0, 0); + return generateRandomPattern(0.18, 0, 0, 0); - return pattern = generateRandomPattern(0.45, 0, 0, 0); + return generateRandomPattern(0.45, 0, 0, 0); } - return pattern = generateRandomPattern(0, 0, 0, 0); + return generateRandomPattern(0, 0, 0, 0); } finally { @@ -384,8 +384,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// The amount of notes to be generated. The note to be added to the centre column will NOT be part of this count. private int getRandomNoteCountMirrored(double centreProbability, double p2, double p3, out bool addToCentre) { - addToCentre = false; - switch (TotalColumns) { case 2: From 7d7b9e36b25ea355c22b258e4fbee768b3274844 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 17:56:38 +0800 Subject: [PATCH 3979/5608] Use compound assignment. --- .editorconfig | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs | 2 +- osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- .../Difficulty/Preprocessing/OsuDifficultyHitObject.cs | 2 +- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 2 +- osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs | 2 +- osu.Game/Graphics/UserInterface/PercentageCounter.cs | 2 +- osu.Game/Graphics/UserInterface/ScoreCounter.cs | 2 +- osu.Game/Graphics/UserInterface/SimpleComboCounter.cs | 2 +- osu.Game/Screens/Play/HUD/ComboCounter.cs | 2 +- osu.Game/Screens/Play/HUD/ComboResultCounter.cs | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.editorconfig b/.editorconfig index 05927526d5..35cbfe769f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -140,7 +140,7 @@ dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning dotnet_style_prefer_auto_properties = true:warning dotnet_style_prefer_conditional_expression_over_assignment = true:silent dotnet_style_prefer_conditional_expression_over_return = true:silent -dotnet_style_prefer_compound_assignment = true:silent +dotnet_style_prefer_compound_assignment = true:warning #Style - null/type checks dotnet_style_coalesce_expression = true:warning diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 56c8b33e02..435c5ac463 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -198,7 +198,7 @@ namespace osu.Game.Rulesets.Catch.UI var additive = createCatcherSprite(); additive.Anchor = Anchor; - additive.OriginPosition = additive.OriginPosition + new Vector2(DrawWidth / 2, 0); // also temporary to align sprite correctly. + additive.OriginPosition += new Vector2(DrawWidth / 2, 0); // also temporary to align sprite correctly. additive.Position = Position; additive.Scale = Scale; additive.Colour = HyperDashing ? Color4.Red : Color4.White; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 6c5bb304bf..c3a8cbd274 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps if (TargetColumns >= 10) { - TargetColumns = TargetColumns / 2; + TargetColumns /= 2; Dual = true; } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 9cdf045b5b..90dbe6ec8f 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Mania.Edit // Flip the vertical coordinate space when scrolling downwards if (scrollingInfo.Direction.Value == ScrollingDirection.Down) - targetPosition = targetPosition - referenceParent.DrawHeight; + targetPosition -= referenceParent.DrawHeight; float movementDelta = targetPosition - reference.DrawableObject.Position.Y; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 5ab07416a6..08f6049782 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Mania.UI foreach (var stage in stages) { - sum = sum + stage.Columns.Count; + sum += stage.Columns.Count; if (sum > column) return stage; } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs index eacac7ae6a..fa6c5c4d9c 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing if (progress % 2 >= 1) progress = 1 - progress % 1; else - progress = progress % 1; + progress %= 1; // ReSharper disable once PossibleInvalidOperationException (bugged in current r# version) var diff = slider.StackedPosition + slider.Path.PositionAt(progress) - slider.LazyEndPosition.Value; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 6962736157..8565506c75 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components newControlPoints[i] = newControlPoints[i] - first; // The slider's position defines the position of the first control point, and all further control points are relative to that point - slider.Position = slider.Position + first; + slider.Position += first; // Since pieces are re-used, they will not point to the deleted control points while remaining selected foreach (var piece in Pieces) diff --git a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index f613ce5f46..d1f7a1e8d3 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -34,7 +34,7 @@ namespace osu.Game.Tournament.Screens.Ladder { var newScale = MathHelper.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); - this.MoveTo(target = target - e.MousePosition * (newScale - scale), 2000, Easing.OutQuint); + this.MoveTo(target -= e.MousePosition * (newScale - scale), 2000, Easing.OutQuint); this.ScaleTo(scale = newScale, 2000, Easing.OutQuint); return true; diff --git a/osu.Game/Graphics/UserInterface/PercentageCounter.cs b/osu.Game/Graphics/UserInterface/PercentageCounter.cs index 8254bdda7c..064c663d59 100644 --- a/osu.Game/Graphics/UserInterface/PercentageCounter.cs +++ b/osu.Game/Graphics/UserInterface/PercentageCounter.cs @@ -41,7 +41,7 @@ namespace osu.Game.Graphics.UserInterface public override void Increment(double amount) { - Current.Value = Current.Value + amount; + Current.Value += amount; } } } diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index e291401670..24d8009f40 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -55,7 +55,7 @@ namespace osu.Game.Graphics.UserInterface public override void Increment(double amount) { - Current.Value = Current.Value + amount; + Current.Value += amount; } } } diff --git a/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs b/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs index 4717401c75..af03cbb63e 100644 --- a/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs +++ b/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs @@ -33,7 +33,7 @@ namespace osu.Game.Graphics.UserInterface public override void Increment(int amount) { - Current.Value = Current.Value + amount; + Current.Value += amount; } } } diff --git a/osu.Game/Screens/Play/HUD/ComboCounter.cs b/osu.Game/Screens/Play/HUD/ComboCounter.cs index 5ac3dac5f7..ea50a4a578 100644 --- a/osu.Game/Screens/Play/HUD/ComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboCounter.cs @@ -114,7 +114,7 @@ namespace osu.Game.Screens.Play.HUD /// public void Increment(int amount = 1) { - Current.Value = Current.Value + amount; + Current.Value += amount; } /// diff --git a/osu.Game/Screens/Play/HUD/ComboResultCounter.cs b/osu.Game/Screens/Play/HUD/ComboResultCounter.cs index 3f6b1e29e6..7ae8bc0ddf 100644 --- a/osu.Game/Screens/Play/HUD/ComboResultCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboResultCounter.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Play.HUD public override void Increment(long amount) { - Current.Value = Current.Value + amount; + Current.Value += amount; } } } From e5e8e70704936cf24e86f10c758590a63bd489c1 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:16:51 +0800 Subject: [PATCH 3980/5608] Use pattern matching. --- .editorconfig | 4 +- .../Beatmaps/CatchBeatmapConverter.cs | 73 +++---- .../Beatmaps/ManiaBeatmapConverter.cs | 72 +++--- .../Legacy/DistanceObjectPatternGenerator.cs | 14 +- .../TestSceneSlider.cs | 33 ++- .../Beatmaps/OsuBeatmapConverter.cs | 81 ++++--- osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs | 19 +- .../Beatmaps/TaikoBeatmapConverter.cs | 206 +++++++++--------- .../Replays/TaikoAutoGenerator.cs | 121 +++++----- .../Components/ScrollingTeamContainer.cs | 53 ++--- .../Sections/General/LoginSettings.cs | 6 +- .../UI/Scrolling/DrawableScrollingRuleset.cs | 8 +- .../Backgrounds/BackgroundScreenCustom.cs | 6 +- 13 files changed, 348 insertions(+), 348 deletions(-) diff --git a/.editorconfig b/.editorconfig index 35cbfe769f..b70f17887e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -145,8 +145,8 @@ dotnet_style_prefer_compound_assignment = true:warning #Style - null/type checks dotnet_style_coalesce_expression = true:warning dotnet_style_null_propagation = true:warning -csharp_style_pattern_matching_over_is_with_cast_check = true:silent -csharp_style_pattern_matching_over_as_with_null_check = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:warning +csharp_style_pattern_matching_over_as_with_null_check = true:warning csharp_style_throw_expression = true:silent csharp_style_conditional_delegate_call = true:suggestion diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 0d9a663b9f..b5497ea89f 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -8,6 +8,7 @@ using System; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Rulesets.Catch.Beatmaps { @@ -22,48 +23,44 @@ namespace osu.Game.Rulesets.Catch.Beatmaps protected override IEnumerable ConvertHitObject(HitObject obj, IBeatmap beatmap) { - var curveData = obj as IHasCurve; var positionData = obj as IHasXPosition; var comboData = obj as IHasCombo; - var endTime = obj as IHasEndTime; - var legacyOffset = obj as IHasLegacyLastTickOffset; - if (curveData != null) + switch (obj) { - yield return new JuiceStream - { - StartTime = obj.StartTime, - Samples = obj.Samples, - Path = curveData.Path, - NodeSamples = curveData.NodeSamples, - RepeatCount = curveData.RepeatCount, - X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH, - NewCombo = comboData?.NewCombo ?? false, - ComboOffset = comboData?.ComboOffset ?? 0, - LegacyLastTickOffset = legacyOffset?.LegacyLastTickOffset ?? 0 - }; - } - else if (endTime != null) - { - yield return new BananaShower - { - StartTime = obj.StartTime, - Samples = obj.Samples, - Duration = endTime.Duration, - NewCombo = comboData?.NewCombo ?? false, - ComboOffset = comboData?.ComboOffset ?? 0, - }; - } - else - { - yield return new Fruit - { - StartTime = obj.StartTime, - Samples = obj.Samples, - NewCombo = comboData?.NewCombo ?? false, - ComboOffset = comboData?.ComboOffset ?? 0, - X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH - }; + case IHasCurve curveData: + return new JuiceStream + { + StartTime = obj.StartTime, + Samples = obj.Samples, + Path = curveData.Path, + NodeSamples = curveData.NodeSamples, + RepeatCount = curveData.RepeatCount, + X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH, + NewCombo = comboData?.NewCombo ?? false, + ComboOffset = comboData?.ComboOffset ?? 0, + LegacyLastTickOffset = (obj as IHasLegacyLastTickOffset)?.LegacyLastTickOffset ?? 0 + }.Yield(); + + case IHasEndTime endTime: + return new BananaShower + { + StartTime = obj.StartTime, + Samples = obj.Samples, + Duration = endTime.Duration, + NewCombo = comboData?.NewCombo ?? false, + ComboOffset = comboData?.ComboOffset ?? 0, + }.Yield(); + + default: + return new Fruit + { + StartTime = obj.StartTime, + Samples = obj.Samples, + NewCombo = comboData?.NewCombo ?? false, + ComboOffset = comboData?.ComboOffset ?? 0, + X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH + }.Yield(); } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index c3a8cbd274..6e3d5761ac 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -156,37 +156,44 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// The hit objects generated. private IEnumerable generateConverted(HitObject original, IBeatmap originalBeatmap) { - var endTimeData = original as IHasEndTime; - var distanceData = original as IHasDistance; - var positionData = original as IHasPosition; - Patterns.PatternGenerator conversion = null; - if (distanceData != null) + switch (original) { - var generator = new DistanceObjectPatternGenerator(Random, original, beatmap, lastPattern, originalBeatmap); - conversion = generator; - - for (double time = original.StartTime; !Precision.DefinitelyBigger(time, generator.EndTime); time += generator.SegmentDuration) + case IHasDistance _: { - recordNote(time, positionData?.Position ?? Vector2.Zero); - computeDensity(time); + var generator = new DistanceObjectPatternGenerator(Random, original, beatmap, lastPattern, originalBeatmap); + conversion = generator; + + var positionData = original as IHasPosition; + + for (double time = original.StartTime; !Precision.DefinitelyBigger(time, generator.EndTime); time += generator.SegmentDuration) + { + recordNote(time, positionData?.Position ?? Vector2.Zero); + computeDensity(time); + } + + break; } - } - else if (endTimeData != null) - { - conversion = new EndTimeObjectPatternGenerator(Random, original, beatmap, originalBeatmap); - recordNote(endTimeData.EndTime, new Vector2(256, 192)); - computeDensity(endTimeData.EndTime); - } - else if (positionData != null) - { - computeDensity(original.StartTime); + case IHasEndTime endTimeData: + { + conversion = new EndTimeObjectPatternGenerator(Random, original, beatmap, originalBeatmap); - conversion = new HitObjectPatternGenerator(Random, original, beatmap, lastPattern, lastTime, lastPosition, density, lastStair, originalBeatmap); + recordNote(endTimeData.EndTime, new Vector2(256, 192)); + computeDensity(endTimeData.EndTime); + break; + } - recordNote(original.StartTime, positionData.Position); + case IHasPosition positionData: + { + computeDensity(original.StartTime); + + conversion = new HitObjectPatternGenerator(Random, original, beatmap, lastPattern, lastTime, lastPosition, density, lastStair, originalBeatmap); + + recordNote(original.StartTime, positionData.Position); + break; + } } if (conversion == null) @@ -219,14 +226,13 @@ namespace osu.Game.Rulesets.Mania.Beatmaps private Pattern generate() { - var endTimeData = HitObject as IHasEndTime; var positionData = HitObject as IHasXPosition; int column = GetColumn(positionData?.X ?? 0); var pattern = new Pattern(); - if (endTimeData != null) + if (HitObject is IHasEndTime endTimeData) { pattern.Add(new HoldNote { @@ -237,7 +243,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps Tail = { Samples = sampleInfoListAt(endTimeData.EndTime) }, }); } - else if (positionData != null) + else if (HitObject is IHasXPosition) { pattern.Add(new Note { @@ -257,15 +263,15 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// private IList sampleInfoListAt(double time) { - var curveData = HitObject as IHasCurve; + if (HitObject is IHasCurve curveData) + { + double segmentTime = (curveData.EndTime - HitObject.StartTime) / curveData.SpanCount(); - if (curveData == null) - return HitObject.Samples; + int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); + return curveData.NodeSamples[index]; + } - double segmentTime = (curveData.EndTime - HitObject.StartTime) / curveData.SpanCount(); - - int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); - return curveData.NodeSamples[index]; + return HitObject.Samples; } } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 6297a68e08..4e98b08377 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -474,15 +474,15 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// private IList sampleInfoListAt(double time) { - var curveData = HitObject as IHasCurve; + if (HitObject is IHasCurve curveData) + { + double segmentTime = (EndTime - HitObject.StartTime) / spanCount; - if (curveData == null) - return HitObject.Samples; + int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); + return curveData.NodeSamples[index]; + } - double segmentTime = (EndTime - HitObject.StartTime) / spanCount; - - int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); - return curveData.NodeSamples[index]; + return HitObject.Samples; } /// diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 5c656bf594..8e8fbf8976 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -379,26 +379,25 @@ namespace osu.Game.Rulesets.Osu.Tests private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) { - var osuObject = judgedObject as DrawableOsuHitObject; - if (osuObject == null) - return; - - OsuSpriteText text; - Add(text = new OsuSpriteText + if (judgedObject is DrawableOsuHitObject osuObject) { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = result.IsHit ? "Hit!" : "Miss!", - Colour = result.IsHit ? Color4.Green : Color4.Red, - Font = OsuFont.GetFont(size: 30), - Position = osuObject.HitObject.StackedEndPosition + judgementOffsetDirection * new Vector2(0, 45) - }); + OsuSpriteText text; + Add(text = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = result.IsHit ? "Hit!" : "Miss!", + Colour = result.IsHit ? Color4.Green : Color4.Red, + Font = OsuFont.GetFont(size: 30), + Position = osuObject.HitObject.StackedEndPosition + judgementOffsetDirection * new Vector2(0, 45) + }); - text.Delay(150) - .Then().FadeOut(200) - .Then().Expire(); + text.Delay(150) + .Then().FadeOut(200) + .Then().Expire(); - judgementOffsetDirection *= -1; + judgementOffsetDirection *= -1; + } } } } diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 6a41e93c35..2296030f81 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using osu.Game.Rulesets.Objects.Types; using System; using osu.Game.Rulesets.Osu.UI; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Rulesets.Osu.Beatmaps { @@ -23,52 +24,48 @@ namespace osu.Game.Rulesets.Osu.Beatmaps protected override IEnumerable ConvertHitObject(HitObject original, IBeatmap beatmap) { - var curveData = original as IHasCurve; - var endTimeData = original as IHasEndTime; var positionData = original as IHasPosition; var comboData = original as IHasCombo; - var legacyOffset = original as IHasLegacyLastTickOffset; - if (curveData != null) + switch (original) { - yield return new Slider - { - StartTime = original.StartTime, - Samples = original.Samples, - Path = curveData.Path, - NodeSamples = curveData.NodeSamples, - RepeatCount = curveData.RepeatCount, - Position = positionData?.Position ?? Vector2.Zero, - NewCombo = comboData?.NewCombo ?? false, - ComboOffset = comboData?.ComboOffset ?? 0, - LegacyLastTickOffset = legacyOffset?.LegacyLastTickOffset, - // prior to v8, speed multipliers don't adjust for how many ticks are generated over the same distance. - // this results in more (or less) ticks being generated in ().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); + slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); + var newControlPoints = new Vector2[slider.Path.ControlPoints.Length]; + for (int i = 0; i < slider.Path.ControlPoints.Length; i++) + newControlPoints[i] = new Vector2(slider.Path.ControlPoints[i].X, -slider.Path.ControlPoints[i].Y); - var newControlPoints = new Vector2[slider.Path.ControlPoints.Length]; - for (int i = 0; i < slider.Path.ControlPoints.Length; i++) - newControlPoints[i] = new Vector2(slider.Path.ControlPoints[i].X, -slider.Path.ControlPoints[i].Y); - - slider.Path = new SliderPath(slider.Path.Type, newControlPoints, slider.Path.ExpectedDistance); + slider.Path = new SliderPath(slider.Path.Type, newControlPoints, slider.Path.ExpectedDistance); + } } } } diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 180e0d8309..10cc861b7e 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -73,127 +73,133 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps protected override IEnumerable ConvertHitObject(HitObject obj, IBeatmap beatmap) { - var distanceData = obj as IHasDistance; - var repeatsData = obj as IHasRepeats; - var endTimeData = obj as IHasEndTime; - var curveData = obj as IHasCurve; - // Old osu! used hit sounding to determine various hit type information IList samples = obj.Samples; bool strong = samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH); - if (distanceData != null) + switch (obj) { - // Number of spans of the object - one for the initial length and for each repeat - int spans = repeatsData?.SpanCount() ?? 1; - - TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(obj.StartTime); - DifficultyControlPoint difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(obj.StartTime); - - double speedAdjustment = difficultyPoint.SpeedMultiplier; - double speedAdjustedBeatLength = timingPoint.BeatLength / speedAdjustment; - - // The true distance, accounting for any repeats. This ends up being the drum roll distance later - double distance = distanceData.Distance * spans * legacy_velocity_multiplier; - - // The velocity of the taiko hit object - calculated as the velocity of a drum roll - double taikoVelocity = taiko_base_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / speedAdjustedBeatLength; - // The duration of the taiko hit object - double taikoDuration = distance / taikoVelocity; - - // The velocity of the osu! hit object - calculated as the velocity of a slider - double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / speedAdjustedBeatLength; - // The duration of the osu! hit object - double osuDuration = distance / osuVelocity; - - // osu-stable always uses the speed-adjusted beatlength to determine the velocities, but - // only uses it for tick rate if beatmap version < 8 - if (beatmap.BeatmapInfo.BeatmapVersion >= 8) - speedAdjustedBeatLength *= speedAdjustment; - - // If the drum roll is to be split into hit circles, assume the ticks are 1/8 spaced within the duration of one beat - double tickSpacing = Math.Min(speedAdjustedBeatLength / beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate, taikoDuration / spans); - - if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength) + case IHasDistance distanceData: { - List> allSamples = curveData != null ? curveData.NodeSamples : new List>(new[] { samples }); + // Number of spans of the object - one for the initial length and for each repeat + int spans = (obj as IHasRepeats)?.SpanCount() ?? 1; - int i = 0; + TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(obj.StartTime); + DifficultyControlPoint difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(obj.StartTime); - for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing) + double speedAdjustment = difficultyPoint.SpeedMultiplier; + double speedAdjustedBeatLength = timingPoint.BeatLength / speedAdjustment; + + // The true distance, accounting for any repeats. This ends up being the drum roll distance later + double distance = distanceData.Distance * spans * legacy_velocity_multiplier; + + // The velocity of the taiko hit object - calculated as the velocity of a drum roll + double taikoVelocity = taiko_base_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / speedAdjustedBeatLength; + // The duration of the taiko hit object + double taikoDuration = distance / taikoVelocity; + + // The velocity of the osu! hit object - calculated as the velocity of a slider + double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / speedAdjustedBeatLength; + // The duration of the osu! hit object + double osuDuration = distance / osuVelocity; + + // osu-stable always uses the speed-adjusted beatlength to determine the velocities, but + // only uses it for tick rate if beatmap version < 8 + if (beatmap.BeatmapInfo.BeatmapVersion >= 8) + speedAdjustedBeatLength *= speedAdjustment; + + // If the drum roll is to be split into hit circles, assume the ticks are 1/8 spaced within the duration of one beat + double tickSpacing = Math.Min(speedAdjustedBeatLength / beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate, taikoDuration / spans); + + if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength) { - IList currentSamples = allSamples[i]; - bool isRim = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE); - strong = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_FINISH); + List> allSamples = obj is IHasCurve curveData ? curveData.NodeSamples : new List>(new[] { samples }); - if (isRim) - { - yield return new RimHit - { - StartTime = j, - Samples = currentSamples, - IsStrong = strong - }; - } - else - { - yield return new CentreHit - { - StartTime = j, - Samples = currentSamples, - IsStrong = strong - }; - } + int i = 0; - i = (i + 1) % allSamples.Count; + for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing) + { + IList currentSamples = allSamples[i]; + bool isRim = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE); + strong = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_FINISH); + + if (isRim) + { + yield return new RimHit + { + StartTime = j, + Samples = currentSamples, + IsStrong = strong + }; + } + else + { + yield return new CentreHit + { + StartTime = j, + Samples = currentSamples, + IsStrong = strong + }; + } + + i = (i + 1) % allSamples.Count; + } } - } - else - { - yield return new DrumRoll + else { - StartTime = obj.StartTime, - Samples = obj.Samples, - IsStrong = strong, - Duration = taikoDuration, - TickRate = beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate == 3 ? 3 : 4 - }; - } - } - else if (endTimeData != null) - { - double hitMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, 3, 5, 7.5) * swell_hit_multiplier; + yield return new DrumRoll + { + StartTime = obj.StartTime, + Samples = obj.Samples, + IsStrong = strong, + Duration = taikoDuration, + TickRate = beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate == 3 ? 3 : 4 + }; + } - yield return new Swell - { - StartTime = obj.StartTime, - Samples = obj.Samples, - Duration = endTimeData.Duration, - RequiredHits = (int)Math.Max(1, endTimeData.Duration / 1000 * hitMultiplier) - }; - } - else - { - bool isRim = samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE); - - if (isRim) - { - yield return new RimHit - { - StartTime = obj.StartTime, - Samples = obj.Samples, - IsStrong = strong - }; + break; } - else + + case IHasEndTime endTimeData: { - yield return new CentreHit + double hitMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, 3, 5, 7.5) * swell_hit_multiplier; + + yield return new Swell { StartTime = obj.StartTime, Samples = obj.Samples, - IsStrong = strong + Duration = endTimeData.Duration, + RequiredHits = (int)Math.Max(1, endTimeData.Duration / 1000 * hitMultiplier) }; + + break; + } + + default: + { + bool isRim = samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE); + + if (isRim) + { + yield return new RimHit + { + StartTime = obj.StartTime, + Samples = obj.Samples, + IsStrong = strong + }; + } + else + { + yield return new CentreHit + { + StartTime = obj.StartTime, + Samples = obj.Samples, + IsStrong = strong + }; + } + + break; } } } diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 299679b2c1..e61953aeb8 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -43,76 +43,83 @@ namespace osu.Game.Rulesets.Taiko.Replays IHasEndTime endTimeData = h as IHasEndTime; double endTime = endTimeData?.EndTime ?? h.StartTime; - Swell swell = h as Swell; - DrumRoll drumRoll = h as DrumRoll; - Hit hit = h as Hit; - - if (swell != null) + switch (h) { - int d = 0; - int count = 0; - int req = swell.RequiredHits; - double hitRate = Math.Min(swell_hit_speed, swell.Duration / req); - - for (double j = h.StartTime; j < endTime; j += hitRate) + case Swell swell: { - TaikoAction action; + int d = 0; + int count = 0; + int req = swell.RequiredHits; + double hitRate = Math.Min(swell_hit_speed, swell.Duration / req); - switch (d) + for (double j = h.StartTime; j < endTime; j += hitRate) { - default: - case 0: - action = TaikoAction.LeftCentre; - break; + TaikoAction action; - case 1: - action = TaikoAction.LeftRim; - break; + switch (d) + { + default: + case 0: + action = TaikoAction.LeftCentre; + break; - case 2: - action = TaikoAction.RightCentre; - break; + case 1: + action = TaikoAction.LeftRim; + break; - case 3: - action = TaikoAction.RightRim; + case 2: + action = TaikoAction.RightCentre; + break; + + case 3: + action = TaikoAction.RightRim; + break; + } + + Frames.Add(new TaikoReplayFrame(j, action)); + d = (d + 1) % 4; + if (++count == req) break; } - Frames.Add(new TaikoReplayFrame(j, action)); - d = (d + 1) % 4; - if (++count == req) - break; - } - } - else if (drumRoll != null) - { - foreach (var tick in drumRoll.NestedHitObjects.OfType()) - { - Frames.Add(new TaikoReplayFrame(tick.StartTime, hitButton ? TaikoAction.LeftCentre : TaikoAction.RightCentre)); - hitButton = !hitButton; - } - } - else if (hit != null) - { - TaikoAction[] actions; - - if (hit is CentreHit) - { - actions = h.IsStrong - ? new[] { TaikoAction.LeftCentre, TaikoAction.RightCentre } - : new[] { hitButton ? TaikoAction.LeftCentre : TaikoAction.RightCentre }; - } - else - { - actions = h.IsStrong - ? new[] { TaikoAction.LeftRim, TaikoAction.RightRim } - : new[] { hitButton ? TaikoAction.LeftRim : TaikoAction.RightRim }; + break; } - Frames.Add(new TaikoReplayFrame(h.StartTime, actions)); + case DrumRoll drumRoll: + { + foreach (var tick in drumRoll.NestedHitObjects.OfType()) + { + Frames.Add(new TaikoReplayFrame(tick.StartTime, hitButton ? TaikoAction.LeftCentre : TaikoAction.RightCentre)); + hitButton = !hitButton; + } + + break; + } + + case Hit hit: + { + TaikoAction[] actions; + + if (hit is CentreHit) + { + actions = h.IsStrong + ? new[] { TaikoAction.LeftCentre, TaikoAction.RightCentre } + : new[] { hitButton ? TaikoAction.LeftCentre : TaikoAction.RightCentre }; + } + else + { + actions = h.IsStrong + ? new[] { TaikoAction.LeftRim, TaikoAction.RightRim } + : new[] { hitButton ? TaikoAction.LeftRim : TaikoAction.RightRim }; + } + + Frames.Add(new TaikoReplayFrame(h.StartTime, actions)); + break; + } + + default: + throw new InvalidOperationException("Unknown hit object type."); } - else - throw new InvalidOperationException("Unknown hit object type."); var nextHitObject = GetNextObject(i); // Get the next object that requires pressing the same button diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index b147d680f0..fff73fcf70 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -125,22 +125,20 @@ namespace osu.Game.Tournament.Screens.Drawings.Components foreach (var c in Children) { - var stc = c as ScrollingTeam; - - if (stc == null) - continue; - - if (closest == null) + if (c is ScrollingTeam stc) { - closest = stc; - continue; + if (closest == null) + { + closest = stc; + continue; + } + + float o = Math.Abs(c.Position.X + c.DrawWidth / 2f - DrawWidth / 2f); + float lastOffset = Math.Abs(closest.Position.X + closest.DrawWidth / 2f - DrawWidth / 2f); + + if (o < lastOffset) + closest = stc; } - - float o = Math.Abs(c.Position.X + c.DrawWidth / 2f - DrawWidth / 2f); - float lastOffset = Math.Abs(closest.Position.X + closest.DrawWidth / 2f - DrawWidth / 2f); - - if (o < lastOffset) - closest = stc; } Trace.Assert(closest != null, "closest != null"); @@ -203,15 +201,13 @@ namespace osu.Game.Tournament.Screens.Drawings.Components foreach (var c in Children) { - ScrollingTeam st = c as ScrollingTeam; - - if (st == null) - continue; - - if (st.Team == team) + if (c is ScrollingTeam st) { - st.FadeOut(200); - st.Expire(); + if (st.Team == team) + { + st.FadeOut(200); + st.Expire(); + } } } } @@ -295,14 +291,13 @@ namespace osu.Game.Tournament.Screens.Drawings.Components { foreach (var c in Children) { - ScrollingTeam st = c as ScrollingTeam; - if (st == null) - continue; - - if (st.Selected) + if (c is ScrollingTeam st) { - st.Selected = false; - RemoveTeam(st.Team); + if (st.Selected) + { + st.Selected = false; + RemoveTeam(st.Team); + } } } } diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index a8bbccb168..d739035d46 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -297,10 +297,8 @@ namespace osu.Game.Overlays.Settings.Sections.General { set { - var h = Header as UserDropdownHeader; - if (h == null) return; - - h.StatusColour = value; + if (Header is UserDropdownHeader h) + h.StatusColour = value; } } diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index f178c01fd6..31a0e3cb4e 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -148,13 +148,9 @@ namespace osu.Game.Rulesets.UI.Scrolling // Generate the timing points, making non-timing changes use the previous timing change and vice-versa var timingChanges = allPoints.Select(c => { - var timingPoint = c as TimingControlPoint; - var difficultyPoint = c as DifficultyControlPoint; - - if (timingPoint != null) + if (c is TimingControlPoint timingPoint) lastTimingPoint = timingPoint; - - if (difficultyPoint != null) + else if (c is DifficultyControlPoint difficultyPoint) lastDifficultyPoint = difficultyPoint; return new MultiplierControlPoint(c.Time) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs index 0cb41bc562..49c7934ed9 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs @@ -17,10 +17,10 @@ namespace osu.Game.Screens.Backgrounds public override bool Equals(BackgroundScreen other) { - var backgroundScreenCustom = other as BackgroundScreenCustom; - if (backgroundScreenCustom == null) return false; + if (other is BackgroundScreenCustom backgroundScreenCustom) + return base.Equals(other) && textureName == backgroundScreenCustom.textureName; - return base.Equals(other) && textureName == backgroundScreenCustom.textureName; + return false; } } } From 0d81b96c5f5dee2e2e8d9ae475f0ec3daea977c5 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:19:48 +0800 Subject: [PATCH 3981/5608] Use deconstruction declaration. --- .editorconfig | 2 +- osu.Game.Tournament/Components/SongBar.cs | 6 +++--- osu.Game/Skinning/SkinnableSound.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.editorconfig b/.editorconfig index b70f17887e..e6bef25e93 100644 --- a/.editorconfig +++ b/.editorconfig @@ -157,7 +157,7 @@ csharp_style_unused_value_assignment_preference = discard_variable:suggestion #Style - variable declaration csharp_style_inlined_variable_declaration = true:silent -csharp_style_deconstructed_variable_declaration = true:silent +csharp_style_deconstructed_variable_declaration = true:warning #Style - other C# 7.x features csharp_style_expression_bodied_local_functions = true:silent diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 7005c068ae..38094695fc 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -230,7 +230,7 @@ namespace osu.Game.Tournament.Components for (var i = 0; i < tuples.Length; i++) { - var tuple = tuples[i]; + var (heading, content) = tuples[i]; if (i > 0) { @@ -241,9 +241,9 @@ namespace osu.Game.Tournament.Components }); } - AddText(new OsuSpriteText { Text = tuple.heading }, s => cp(s, OsuColour.Gray(0.33f))); + AddText(new OsuSpriteText { Text = heading }, s => cp(s, OsuColour.Gray(0.33f))); AddText(" ", s => cp(s, OsuColour.Gray(0.33f))); - AddText(new OsuSpriteText { Text = tuple.content }, s => cp(s, OsuColour.Gray(0.5f))); + AddText(new OsuSpriteText { Text = content }, s => cp(s, OsuColour.Gray(0.5f))); } } } diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 6d23f22515..fc6afd0b27 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -96,8 +96,8 @@ namespace osu.Game.Skinning if (adjustments != null) { - foreach (var adjustment in adjustments) - ch.AddAdjustment(adjustment.property, adjustment.bindable); + foreach (var (property, bindable) in adjustments) + ch.AddAdjustment(property, bindable); } } From 31cc0d13da17951a324455b6923d964558c288a8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:22:35 +0800 Subject: [PATCH 3982/5608] Use 'out var'. --- .editorconfig | 2 +- .../Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs | 3 +-- osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs | 4 +--- osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs | 4 +--- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 4 +--- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 4 +--- osu.Game/IO/Legacy/SerializationReader.cs | 4 +--- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 3 +-- osu.Game/Storyboards/Storyboard.cs | 3 +-- 9 files changed, 9 insertions(+), 22 deletions(-) diff --git a/.editorconfig b/.editorconfig index e6bef25e93..588661b59d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -156,7 +156,7 @@ csharp_style_unused_value_expression_statement_preference = discard_variable:sil csharp_style_unused_value_assignment_preference = discard_variable:suggestion #Style - variable declaration -csharp_style_inlined_variable_declaration = true:silent +csharp_style_inlined_variable_declaration = true:warning csharp_style_deconstructed_variable_declaration = true:warning #Style - other C# 7.x features diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index be3c43699d..3b7a24726e 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -303,8 +303,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy var pattern = new Pattern(); - bool addToCentre; - int noteCount = getRandomNoteCountMirrored(centreProbability, p2, p3, out addToCentre); + int noteCount = getRandomNoteCountMirrored(centreProbability, p2, p3, out var addToCentre); int columnLimit = (TotalColumns % 2 == 0 ? TotalColumns : TotalColumns - 1) / 2; int nextColumn = GetRandomColumn(upperBound: columnLimit); diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 2c515edda7..7119533743 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -225,9 +225,7 @@ namespace osu.Game.Tournament.Screens.Editors beatmapId.Value = Model.ID.ToString(); beatmapId.BindValueChanged(idString => { - int parsed; - - int.TryParse(idString.NewValue, out parsed); + int.TryParse(idString.NewValue, out var parsed); Model.ID = parsed; diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index 11c2732d62..494dd73edd 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -267,9 +267,7 @@ namespace osu.Game.Tournament.Screens.Editors userId.Value = user.Id.ToString(); userId.BindValueChanged(idString => { - long parsed; - - long.TryParse(idString.NewValue, out parsed); + long.TryParse(idString.NewValue, out var parsed); user.Id = parsed; diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index aeb5df46f8..838b1c2f07 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -293,9 +293,7 @@ namespace osu.Game.Beatmaps.Formats { string[] split = line.Split(','); - EventType type; - - if (!Enum.TryParse(split[0], out type)) + if (!Enum.TryParse(split[0], out EventType type)) throw new InvalidDataException($@"Unknown event type: {split[0]}"); switch (type) diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index e3320f62ac..f94ab3f27b 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -83,9 +83,7 @@ namespace osu.Game.Beatmaps.Formats { storyboardSprite = null; - EventType type; - - if (!Enum.TryParse(split[0], out type)) + if (!Enum.TryParse(split[0], out EventType type)) throw new InvalidDataException($@"Unknown event type: {split[0]}"); switch (type) diff --git a/osu.Game/IO/Legacy/SerializationReader.cs b/osu.Game/IO/Legacy/SerializationReader.cs index 7a84c11930..82b2c4be32 100644 --- a/osu.Game/IO/Legacy/SerializationReader.cs +++ b/osu.Game/IO/Legacy/SerializationReader.cs @@ -226,9 +226,7 @@ namespace osu.Game.IO.Legacy public override Type BindToType(string assemblyName, string typeName) { - Type typeToDeserialize; - - if (cache.TryGetValue(assemblyName + typeName, out typeToDeserialize)) + if (cache.TryGetValue(assemblyName + typeName, out var typeToDeserialize)) return typeToDeserialize; List tmpTypes = new List(); diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 6c35b261d4..5e7d0d050a 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -177,8 +177,7 @@ namespace osu.Game.Rulesets.Objects.Legacy if (i >= adds.Length) break; - int sound; - int.TryParse(adds[i], out sound); + int.TryParse(adds[i], out var sound); nodeSoundTypes[i] = (LegacySoundType)sound; } } diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 3d988c5fe3..a76eedfc78 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -27,8 +27,7 @@ namespace osu.Game.Storyboards public StoryboardLayer GetLayer(string name) { - StoryboardLayer layer; - if (!layers.TryGetValue(name, out layer)) + if (!layers.TryGetValue(name, out var layer)) layers[name] = layer = new StoryboardLayer(name, layers.Values.Min(l => l.Depth) - 1); return layer; From 8a1b70513c05be230fd593225f5d70623bc0e554 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:24:19 +0800 Subject: [PATCH 3983/5608] No this. qualification. --- .editorconfig | 6 ++++++ osu.Game/Beatmaps/ControlPoints/ControlPoint.cs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 588661b59d..abaa003115 100644 --- a/.editorconfig +++ b/.editorconfig @@ -111,6 +111,12 @@ csharp_preserve_single_line_statements = true #Roslyn language styles +#Style - this. qualification +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning + #Style - type names dotnet_style_predefined_type_for_locals_parameters_members = true:silent dotnet_style_predefined_type_for_member_access = true:silent diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 0861e00d8d..7351187ab9 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -14,7 +14,7 @@ namespace osu.Game.Beatmaps.ControlPoints private ControlPointGroup controlPointGroup; - public void AttachGroup(ControlPointGroup pointGroup) => this.controlPointGroup = pointGroup; + public void AttachGroup(ControlPointGroup pointGroup) => controlPointGroup = pointGroup; public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); From ca52d09e815b776e9e021ae138049b88481063b5 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:26:42 +0800 Subject: [PATCH 3984/5608] Enforce expression body for typical simple ones. --- .editorconfig | 10 +++--- .../API/Requests/Responses/CommentBundle.cs | 13 +++---- .../BeatmapSet/Scores/ScoresContainer.cs | 35 +++++++++---------- osu.Game/Users/User.cs | 2 +- 4 files changed, 27 insertions(+), 33 deletions(-) diff --git a/.editorconfig b/.editorconfig index abaa003115..a555a3d2bc 100644 --- a/.editorconfig +++ b/.editorconfig @@ -132,12 +132,13 @@ csharp_preferred_modifier_order = public,private,protected,internal,new,abstract # Skipped because roslyn cannot separate +-*/ with << >> #Style - expression bodies -csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_accessors = true:warning csharp_style_expression_bodied_constructors = false:none -csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_indexers = true:warning csharp_style_expression_bodied_methods = true:silent -csharp_style_expression_bodied_operators = true:silent -csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_operators = true:warning +csharp_style_expression_bodied_properties = true:warning +csharp_style_expression_bodied_local_functions = true:silent #Style - expression preferences dotnet_style_object_initializer = true:warning @@ -166,7 +167,6 @@ csharp_style_inlined_variable_declaration = true:warning csharp_style_deconstructed_variable_declaration = true:warning #Style - other C# 7.x features -csharp_style_expression_bodied_local_functions = true:silent dotnet_style_prefer_inferred_tuple_names = true:warning csharp_prefer_simple_default_expression = true:warning csharp_style_pattern_local_over_anonymous_function = true:silent diff --git a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs index 7db3126ade..8db5d8d6ad 100644 --- a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs +++ b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs @@ -50,17 +50,14 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"user_votes")] private List userVotes { - set + set => value.ForEach(v => { - value.ForEach(v => + Comments.ForEach(c => { - Comments.ForEach(c => - { - if (v == c.Id) - c.IsVoted = true; - }); + if (v == c.Id) + c.IsVoted = true; }); - } + }); } private List users; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 4bbcd8d631..80de8f8230 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -48,31 +48,28 @@ namespace osu.Game.Overlays.BeatmapSet.Scores protected APILegacyScores Scores { - set + set => Schedule(() => { - Schedule(() => + topScoresContainer.Clear(); + + if (value?.Scores.Any() != true) { - topScoresContainer.Clear(); + scoreTable.Scores = null; + scoreTable.Hide(); + return; + } - if (value?.Scores.Any() != true) - { - scoreTable.Scores = null; - scoreTable.Hide(); - return; - } + scoreTable.Scores = value.Scores; + scoreTable.Show(); - scoreTable.Scores = value.Scores; - scoreTable.Show(); + var topScore = value.Scores.First(); + var userScore = value.UserScore; - var topScore = value.Scores.First(); - var userScore = value.UserScore; + topScoresContainer.Add(new DrawableTopScore(topScore)); - topScoresContainer.Add(new DrawableTopScore(topScore)); - - if (userScore != null && userScore.Score.OnlineScoreID != topScore.OnlineScoreID) - topScoresContainer.Add(new DrawableTopScore(userScore.Score, userScore.Position)); - }); - } + if (userScore != null && userScore.Score.OnlineScoreID != topScore.OnlineScoreID) + topScoresContainer.Add(new DrawableTopScore(userScore.Score, userScore.Position)); + }); } public ScoresContainer() diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 1cb395fd75..b15789f324 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -129,7 +129,7 @@ namespace osu.Game.Users [JsonProperty] private string[] playstyle { - set { PlayStyles = value?.Select(str => Enum.Parse(typeof(PlayStyle), str, true)).Cast().ToArray(); } + set => PlayStyles = value?.Select(str => Enum.Parse(typeof(PlayStyle), str, true)).Cast().ToArray(); } public PlayStyle[] PlayStyles; From 205eda8566baf7566d5b315112e0d33ce47cd5e0 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:30:25 +0800 Subject: [PATCH 3985/5608] Use readonly field when not reflected. --- .editorconfig | 3 +-- osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.editorconfig b/.editorconfig index a555a3d2bc..92d06da4f3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -158,6 +158,7 @@ csharp_style_throw_expression = true:silent csharp_style_conditional_delegate_call = true:suggestion #Style - unused +dotnet_style_readonly_field = true:silent dotnet_code_quality_unused_parameters = non_public:silent csharp_style_unused_value_expression_statement_preference = discard_variable:silent csharp_style_unused_value_assignment_preference = discard_variable:suggestion @@ -175,8 +176,6 @@ dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent #Supressing roslyn built-in analyzers # Suppress: EC112 -#Field can be readonly -dotnet_diagnostic.IDE0044.severity = silent #Private method is unused dotnet_diagnostic.IDE0051.severity = silent #Private member is unused diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index 9869ddde41..7b2913b817 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -87,7 +87,7 @@ namespace osu.Game.Tests.NonVisual.Filtering Assert.IsNull(filterCriteria.BPM.Max); } - private static object[] lengthQueryExamples = + private static readonly object[] length_query_examples = { new object[] { "6ms", TimeSpan.FromMilliseconds(6), TimeSpan.FromMilliseconds(1) }, new object[] { "23s", TimeSpan.FromSeconds(23), TimeSpan.FromSeconds(1) }, @@ -97,7 +97,7 @@ namespace osu.Game.Tests.NonVisual.Filtering }; [Test] - [TestCaseSource(nameof(lengthQueryExamples))] + [TestCaseSource(nameof(length_query_examples))] public void TestApplyLengthQueries(string lengthQuery, TimeSpan expectedLength, TimeSpan scale) { string query = $"length={lengthQuery} time"; From 64fc5007fc447dd14c54f7c1985ff2c83fce87f0 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:33:24 +0800 Subject: [PATCH 3986/5608] Use language primitive types. --- .editorconfig | 4 ++-- osu.Desktop/OsuGameDesktop.cs | 2 +- osu.Game.Tournament/IPC/FileBasedIPC.cs | 2 +- osu.Game/Tests/Visual/OsuTestScene.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.editorconfig b/.editorconfig index 92d06da4f3..2c68b0ca09 100644 --- a/.editorconfig +++ b/.editorconfig @@ -118,8 +118,8 @@ dotnet_style_qualification_for_method = false:warning dotnet_style_qualification_for_event = false:warning #Style - type names -dotnet_style_predefined_type_for_locals_parameters_members = true:silent -dotnet_style_predefined_type_for_member_access = true:silent +dotnet_style_predefined_type_for_locals_parameters_members = true:warning +dotnet_style_predefined_type_for_member_access = true:warning csharp_style_var_when_type_is_apparent = true:none csharp_style_var_for_built_in_types = true:none csharp_style_var_elsewhere = true:silent diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 7725ee6451..26a730b442 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -119,7 +119,7 @@ namespace osu.Desktop try { using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) - stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(String.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); + stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); if (checkExists(stableInstallPath)) return stableInstallPath; diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 47f2bed77a..8ec8a21280 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -180,7 +180,7 @@ namespace osu.Game.Tournament.IPC try { using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) - stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(String.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); + stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); if (checkExists(stableInstallPath)) return stableInstallPath; diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 345fff90aa..e350b40c25 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -218,7 +218,7 @@ namespace osu.Game.Tests.Visual public IEnumerable GetAvailableResources() => throw new NotImplementedException(); - public Track GetVirtual(double length = Double.PositiveInfinity) + public Track GetVirtual(double length = double.PositiveInfinity) { var track = new TrackVirtualManual(referenceClock) { Length = length }; AddItem(track); From 2270f33c33ac80f9489545f016fa3085af126df9 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 21:20:18 +0800 Subject: [PATCH 3987/5608] Enable C# 8. --- Directory.Build.props | 2 +- osu.Android.props | 3 ++- osu.iOS.props | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index b4baa2833e..cb0d0f05b0 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 7.3 + 8.0 $(MSBuildThisFileDirectory)app.manifest diff --git a/osu.Android.props b/osu.Android.props index 6fab2e7868..74f899e81d 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -1,5 +1,6 @@ - + + 8.0 bin\$(Configuration) 4 2.0 diff --git a/osu.iOS.props b/osu.iOS.props index 8124357312..d529b5f4e2 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -1,5 +1,6 @@ + 8.0 {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Resources PackageReference From dcfa98414f1a20b05a63fd9460c1b0937978c67a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:35:08 +0800 Subject: [PATCH 3988/5608] Use ??=. --- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 6 +++--- osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs | 2 +- .../Objects/Drawables/DrawableOsuHitObject.cs | 2 +- osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 4 ++-- osu.Game/Rulesets/Objects/SliderPath.cs | 2 +- osu.Game/Skinning/SkinManager.cs | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index fba52dfc32..f225173326 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -148,9 +148,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy protected int FindAvailableColumn(int initialColumn, int? lowerBound = null, int? upperBound = null, Func nextColumn = null, [InstantHandle] Func validation = null, params Pattern[] patterns) { - lowerBound = lowerBound ?? RandomStart; - upperBound = upperBound ?? TotalColumns; - nextColumn = nextColumn ?? (_ => GetRandomColumn(lowerBound, upperBound)); + lowerBound ??= RandomStart; + upperBound ??= TotalColumns; + nextColumn ??= (_ => GetRandomColumn(lowerBound, upperBound)); // Check for the initial column if (isValid(initialColumn)) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs index 84a7bfc53e..64f353c4d9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Tests private Drawable testSingle(float circleSize, bool auto = false, double timeOffset = 0, Vector2? positionOffset = null) { - positionOffset = positionOffset ?? Vector2.Zero; + positionOffset ??= Vector2.Zero; var circle = new HitCircle { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index c46343c73c..a677cb6a72 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; private OsuInputManager osuActionInputManager; - internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); + internal OsuInputManager OsuActionInputManager => osuActionInputManager ??= GetContainingInputManager() as OsuInputManager; protected virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength); diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index b879b92f01..4924842e81 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -84,7 +84,7 @@ namespace osu.Game.Beatmaps { try { - return (trackStore ?? (trackStore = AudioManager.GetTrackStore(store))).Get(getPathForFile(Metadata.AudioFile)); + return (trackStore ??= AudioManager.GetTrackStore(store)).Get(getPathForFile(Metadata.AudioFile)); } catch { diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 7c69a992dd..44d6d33cef 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -150,7 +150,7 @@ namespace osu.Game.Beatmaps public bool BeatmapLoaded => beatmapLoadTask?.IsCompleted ?? false; - public Task LoadBeatmapAsync() => (beatmapLoadTask ?? (beatmapLoadTask = Task.Factory.StartNew(() => + public Task LoadBeatmapAsync() => beatmapLoadTask ??= Task.Factory.StartNew(() => { // Todo: Handle cancellation during beatmap parsing var b = GetBeatmap() ?? new Beatmap(); @@ -162,7 +162,7 @@ namespace osu.Game.Beatmaps b.BeatmapInfo = BeatmapInfo; return b; - }, beatmapCancellation.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default))); + }, beatmapCancellation.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); public IBeatmap Beatmap { diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 7763b0eaaf..61c27d0fba 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -129,7 +129,7 @@ namespace osu.Game.Rulesets.Objects isInitialised = true; - controlPoints = controlPoints ?? Array.Empty(); + controlPoints ??= Array.Empty(); calculatedPath = new List(); cumulativeLength = new List(); diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index aa3b3981c2..3d469ab6e1 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -96,7 +96,7 @@ namespace osu.Game.Skinning else { model.Name = model.Name.Replace(".osk", ""); - model.Creator = model.Creator ?? "Unknown"; + model.Creator ??= "Unknown"; } } From 144812669dd1e861c108bf8747a777c6ab853265 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:37:20 +0800 Subject: [PATCH 3989/5608] Use static local functions. --- .editorconfig | 3 +++ osu.Desktop/OsuGameDesktop.cs | 2 +- .../Objects/Drawable/DrawableFruit.cs | 2 +- .../Patterns/Legacy/DistanceObjectPatternGenerator.cs | 2 +- osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs | 9 +++++---- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 2 +- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 6 +++--- .../Online/TestSceneBeatmapSetOverlaySuccessRate.cs | 2 +- osu.Game.Tournament/Components/SongBar.cs | 2 +- osu.Game.Tournament/IPC/FileBasedIPC.cs | 2 +- .../Screens/Ladder/Components/ProgressionPath.cs | 2 +- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 2 +- .../Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 2 +- 14 files changed, 22 insertions(+), 18 deletions(-) diff --git a/.editorconfig b/.editorconfig index 2c68b0ca09..8c2dde00aa 100644 --- a/.editorconfig +++ b/.editorconfig @@ -173,6 +173,9 @@ csharp_prefer_simple_default_expression = true:warning csharp_style_pattern_local_over_anonymous_function = true:silent dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent +#Style _ C# 8 features +csharp_prefer_static_local_function = true:warning + #Supressing roslyn built-in analyzers # Suppress: EC112 diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 26a730b442..66e7bb381c 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -112,7 +112,7 @@ namespace osu.Desktop { protected override string LocateBasePath() { - bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")); + static bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")); string stableInstallPath; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 1af77b75fc..a6da682aee 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable const float small_pulp = large_pulp_3 / 2; - Vector2 positionAt(float angle, float distance) => new Vector2( + static Vector2 positionAt(float angle, float distance) => new Vector2( distance * (float)Math.Sin(angle * Math.PI / 180), distance * (float)Math.Cos(angle * Math.PI / 180)); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 4e98b08377..0cbf5cf51c 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -364,7 +364,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy break; } - bool isDoubleSample(HitSampleInfo sample) => sample.Name == HitSampleInfo.HIT_CLAP || sample.Name == HitSampleInfo.HIT_FINISH; + static bool isDoubleSample(HitSampleInfo sample) => sample.Name == HitSampleInfo.HIT_CLAP || sample.Name == HitSampleInfo.HIT_FINISH; bool canGenerateTwoNotes = !convertType.HasFlag(PatternType.LowProbability); canGenerateTwoNotes &= HitObject.Samples.Any(isDoubleSample) || sampleInfoListAt(HitObject.StartTime).Any(isDoubleSample); diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index e9fdf924c3..0c55194250 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Osu.Tests break; } - ConvertValue createConvertValue(OsuHitObject obj) => new ConvertValue + static ConvertValue createConvertValue(OsuHitObject obj) => new ConvertValue { StartTime = obj.StartTime, EndTime = (obj as IHasEndTime)?.EndTime ?? obj.StartTime, diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 8e8fbf8976..88c9324d4c 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -148,9 +148,9 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("repeat samples updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertSamples)); AddAssert("tail has no samples", () => ((Slider)slider.HitObject).TailCircle.Samples.Count == 0); - bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; + static bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; - bool assertSamples(HitObject hitObject) + static bool assertSamples(HitObject hitObject) { return hitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP) && hitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_WHISTLE); @@ -183,8 +183,9 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("repeat samples not updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertSamples)); AddAssert("tail has no samples", () => ((Slider)slider.HitObject).TailCircle.Samples.Count == 0); - bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; - bool assertSamples(HitObject hitObject) => hitObject.Samples.All(s => s.Name != HitSampleInfo.HIT_CLAP && s.Name != HitSampleInfo.HIT_WHISTLE); + static bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; + + static bool assertSamples(HitObject hitObject) => hitObject.Samples.All(s => s.Name != HitSampleInfo.HIT_CLAP && s.Name != HitSampleInfo.HIT_WHISTLE); } private Drawable testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats); diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 32c9e913c6..7f53340fb8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override void ApplyToDrawableHitObjects(IEnumerable drawables) { - void adjustFadeIn(OsuHitObject h) => h.TimeFadeIn = h.TimePreempt * fade_in_duration_multiplier; + static void adjustFadeIn(OsuHitObject h) => h.TimeFadeIn = h.TimePreempt * fade_in_duration_multiplier; foreach (var d in drawables.OfType()) { diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 2ecc516919..26e70f19e4 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -413,7 +413,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual("soft-hitnormal8", getTestableSampleInfo(hitObjects[4]).LookupNames.First()); } - HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); + static HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); } [Test] @@ -431,7 +431,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual("normal-hitnormal3", getTestableSampleInfo(hitObjects[2]).LookupNames.First()); } - HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); + static HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); } [Test] @@ -451,7 +451,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(70, getTestableSampleInfo(hitObjects[3]).Volume); } - HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); + static HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); } [Test] diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs index 05f5c117e4..80fad44593 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("set second set", () => successRate.Beatmap = secondBeatmap); AddAssert("ratings set", () => successRate.Graph.Metrics == secondBeatmap.Metrics); - BeatmapInfo createBeatmap() => new BeatmapInfo + static BeatmapInfo createBeatmap() => new BeatmapInfo { Metrics = new BeatmapMetrics { diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 38094695fc..61618aedc0 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -222,7 +222,7 @@ namespace osu.Game.Tournament.Components Margin = new MarginPadding { Horizontal = 15, Vertical = 1 }; AutoSizeAxes = Axes.Both; - void cp(SpriteText s, Color4 colour) + static void cp(SpriteText s, Color4 colour) { s.Colour = colour; s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15); diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 8ec8a21280..b19f2bedf0 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -152,7 +152,7 @@ namespace osu.Game.Tournament.IPC { protected override string LocateBasePath() { - bool checkExists(string p) + static bool checkExists(string p) { return File.Exists(Path.Combine(p, "ipc.txt")); } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs index 34e0dc770f..84a329085a 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs @@ -26,7 +26,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { base.LoadComplete(); - Vector2 getCenteredVector(Vector2 top, Vector2 bottom) => new Vector2(top.X, top.Y + (bottom.Y - top.Y) / 2); + static Vector2 getCenteredVector(Vector2 top, Vector2 bottom) => new Vector2(top.X, top.Y + (bottom.Y - top.Y) / 2); var q1 = Source.ScreenSpaceDrawQuad; var q2 = Destination.ScreenSpaceDrawQuad; diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 7a5fc2cd06..c3875716b8 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -120,7 +120,7 @@ namespace osu.Game.Tournament.Screens.MapPool pickColour = colour; pickType = choiceType; - Color4 setColour(bool active) => active ? Color4.White : Color4.Gray; + static Color4 setColour(bool active) => active ? Color4.White : Color4.Gray; buttonRedBan.Colour = setColour(pickColour == TeamColour.Red && pickType == ChoiceType.Ban); buttonBlueBan.Colour = setColour(pickColour == TeamColour.Blue && pickType == ChoiceType.Ban); diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 5e7d0d050a..5348ff1f02 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Objects.Legacy } // osu-stable special-cased colinear perfect curves to a CurveType.Linear - bool isLinear(Vector2[] p) => Precision.AlmostEquals(0, (p[1].Y - p[0].Y) * (p[2].X - p[0].X) - (p[1].X - p[0].X) * (p[2].Y - p[0].Y)); + static bool isLinear(Vector2[] p) => Precision.AlmostEquals(0, (p[1].Y - p[0].Y) * (p[2].X - p[0].X) - (p[1].X - p[0].X) * (p[2].Y - p[0].Y)); if (points.Length == 3 && pathType == PathType.PerfectCurve && isLinear(points)) pathType = PathType.Linear; From 5f3e9a791c6e44747ba3e9ff1e33cb50ced91425 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:45:19 +0800 Subject: [PATCH 3990/5608] Disable suggestions not applicable for this PR. --- .editorconfig | 6 +++++- osu.sln.DotSettings | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.editorconfig b/.editorconfig index 8c2dde00aa..3e7325e15b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -173,8 +173,12 @@ csharp_prefer_simple_default_expression = true:warning csharp_style_pattern_local_over_anonymous_function = true:silent dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent -#Style _ C# 8 features +#Style - C# 8 features csharp_prefer_static_local_function = true:warning +csharp_prefer_simple_using_statement = true:silent +csharp_style_prefer_index_operator = false:none +csharp_style_prefer_range_operator = false:none +csharp_style_prefer_switch_expression = false:none #Supressing roslyn built-in analyzers # Suppress: EC112 diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 63d055702b..b08d314dbe 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -70,6 +70,7 @@ WARNING HINT WARNING + HINT WARNING DO_NOT_SHOW WARNING @@ -118,6 +119,7 @@ HINT HINT HINT + DO_NOT_SHOW HINT HINT WARNING @@ -132,7 +134,6 @@ DO_NOT_SHOW DO_NOT_SHOW WARNING - WARNING WARNING WARNING @@ -211,12 +212,13 @@ HINT HINT HINT - HINT HINT + DO_NOT_SHOW WARNING WARNING WARNING + DO_NOT_SHOW WARNING True From d60493a961dc44185702e5d101476fdd915f4752 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 20:03:21 +0800 Subject: [PATCH 3991/5608] Use discards. --- osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs | 2 +- osu.Game/Configuration/DatabasedConfigManager.cs | 2 +- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- osu.sln.DotSettings | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs b/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs index b3863bcf44..669acc3202 100644 --- a/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Beatmaps.Formats { try { - var _ = int.Parse(input); + _ = int.Parse(input); } catch (Exception e) { diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs index 02382cfd2b..1ef4c2527a 100644 --- a/osu.Game/Configuration/DatabasedConfigManager.cs +++ b/osu.Game/Configuration/DatabasedConfigManager.cs @@ -36,7 +36,7 @@ namespace osu.Game.Configuration protected override void PerformLoad() { databasedSettings = settings.Query(ruleset?.ID, variant); - legacySettingsExist = databasedSettings.Any(s => int.TryParse(s.Key, out var _)); + legacySettingsExist = databasedSettings.Any(s => int.TryParse(s.Key, out _)); } protected override bool PerformSave() diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index c3436ffd45..b58753bdbb 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -79,7 +79,7 @@ namespace osu.Game.Screens.Select newRoot.Filter(activeCriteria); // preload drawables as the ctor overhead is quite high currently. - var _ = newRoot.Drawables; + _ = newRoot.Drawables; root = newRoot; if (selectedBeatmapSet != null && !beatmapSets.Contains(selectedBeatmapSet.BeatmapSet)) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index b08d314dbe..9b400de390 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -17,6 +17,7 @@ WARNING WARNING HINT + DO_NOT_SHOW HINT HINT HINT From 42a98c5d87124ac18f6ec6228430ea88aec0db89 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 20:07:01 +0800 Subject: [PATCH 3992/5608] Use constants. --- osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs | 2 +- osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs | 2 +- osu.Game/Overlays/Dialog/PopupDialog.cs | 4 ++-- osu.Game/Overlays/SearchableList/SearchableListOverlay.cs | 2 +- osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs | 2 +- osu.Game/Screens/Select/FooterButton.cs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs index 621728830a..505d2d6f89 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Chat.Selection { public class ChannelSelectionOverlay : WaveOverlayContainer { - public static readonly float WIDTH_PADDING = 170; + public const float WIDTH_PADDING = 170; private const float transition_duration = 500; diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 8b88d81b88..a14765ee88 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -14,7 +14,7 @@ namespace osu.Game.Overlays.Chat.Tabs { public class ChannelTabControl : OsuTabControl { - public static readonly float SHEAR_WIDTH = 10; + public const float SHEAR_WIDTH = 10; public Action OnRequestLeave; diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index cff887865a..ee88ff258a 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -21,8 +21,8 @@ namespace osu.Game.Overlays.Dialog { public abstract class PopupDialog : VisibilityContainer { - public static readonly float ENTER_DURATION = 500; - public static readonly float EXIT_DURATION = 200; + public const float ENTER_DURATION = 500; + public const float EXIT_DURATION = 200; private readonly Vector2 ringSize = new Vector2(100f); private readonly Vector2 ringMinifiedSize = new Vector2(20f); diff --git a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs index 177f731f12..fb0c1d9808 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.SearchableList { public abstract class SearchableListOverlay : FullscreenOverlay { - public static readonly float WIDTH_PADDING = 80; + public const float WIDTH_PADDING = 80; } public abstract class SearchableListOverlay : SearchableListOverlay diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index bba72c7ee1..433e8ee398 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Select { public class BeatmapDetailAreaTabControl : Container { - public static readonly float HEIGHT = 24; + public const float HEIGHT = 24; private readonly OsuTabControlCheckbox modsCheckbox; private readonly OsuTabControl tabs; private readonly Container tabsContainer; diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index c1478aa4ce..b77da36748 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Select { public class FooterButton : OsuClickableContainer { - public static readonly float SHEAR_WIDTH = 7.5f; + public const float SHEAR_WIDTH = 7.5f; protected static readonly Vector2 SHEAR = new Vector2(SHEAR_WIDTH / Footer.HEIGHT, 0); From f3f5094c2686f7964c1613fc0b0f7799f4b3c7df Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 20:12:11 +0800 Subject: [PATCH 3993/5608] Convert delegate to local function. --- .editorconfig | 2 +- osu.Game/Screens/Menu/Disclaimer.cs | 3 +-- .../Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs | 8 ++++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.editorconfig b/.editorconfig index 3e7325e15b..bfa071acd8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -170,7 +170,7 @@ csharp_style_deconstructed_variable_declaration = true:warning #Style - other C# 7.x features dotnet_style_prefer_inferred_tuple_names = true:warning csharp_prefer_simple_default_expression = true:warning -csharp_style_pattern_local_over_anonymous_function = true:silent +csharp_style_pattern_local_over_anonymous_function = true:warning dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent #Style - C# 8 features diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index 17f999d519..bcab73715b 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.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.Bindables; @@ -93,7 +92,7 @@ namespace osu.Game.Screens.Menu textFlow.AddParagraph("Things may not work as expected", t => t.Font = t.Font.With(size: 20)); textFlow.NewParagraph(); - Action format = t => t.Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold); + static void format(SpriteText t) => t.Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold); textFlow.AddParagraph("Detailed bug reports are welcomed via github issues.", format); textFlow.NewParagraph(); diff --git a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs index d20b021fc6..e389611caf 100644 --- a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs +++ b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.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.Collections.Generic; using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.Allocation; @@ -77,12 +76,13 @@ namespace osu.Game.Screens.Multi.Ranking.Pages private void scoresLoaded(IEnumerable scores) { - Action gray = s => s.Colour = colours.GrayC; - Action white = s => + void gray(SpriteText s) => s.Colour = colours.GrayC; + + void white(SpriteText s) { s.Font = s.Font.With(size: s.Font.Size * 1.4f); s.Colour = colours.GrayF; - }; + } rankText.AddText(name + "\n", white); rankText.AddText("You are placed ", gray); From 2d46eed8aee992b136a5a20972cc109928948650 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 20:15:55 +0800 Subject: [PATCH 3994/5608] Turn on missing rules. --- .editorconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index bfa071acd8..b5333ad8e7 100644 --- a/.editorconfig +++ b/.editorconfig @@ -155,13 +155,13 @@ dotnet_style_null_propagation = true:warning csharp_style_pattern_matching_over_is_with_cast_check = true:warning csharp_style_pattern_matching_over_as_with_null_check = true:warning csharp_style_throw_expression = true:silent -csharp_style_conditional_delegate_call = true:suggestion +csharp_style_conditional_delegate_call = true:warning #Style - unused dotnet_style_readonly_field = true:silent dotnet_code_quality_unused_parameters = non_public:silent csharp_style_unused_value_expression_statement_preference = discard_variable:silent -csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:warning #Style - variable declaration csharp_style_inlined_variable_declaration = true:warning From 61464c5c89723cbfe06dc975e760d207c2d8dc8b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 21:27:15 +0900 Subject: [PATCH 3995/5608] Fix potential nullref in unrelated test --- osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs index c8c36789c4..5652b8d2bd 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs @@ -19,7 +19,7 @@ namespace osu.Game.Online.API.Requests public SearchBeatmapSetsRequest(string query, RulesetInfo ruleset, BeatmapSearchCategory searchCategory = BeatmapSearchCategory.Any, DirectSortCriteria sortCriteria = DirectSortCriteria.Ranked, SortDirection direction = SortDirection.Descending) { - this.query = System.Uri.EscapeDataString(query); + this.query = string.IsNullOrEmpty(query) ? string.Empty : System.Uri.EscapeDataString(query); this.ruleset = ruleset; this.searchCategory = searchCategory; this.sortCriteria = sortCriteria; From 1349289c0eae4e15db47ec3a807ef658cb7d7b59 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 20:32:41 +0800 Subject: [PATCH 3996/5608] Remove SharpRaven package and install Sentry. --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index af60da3e70..a64334c4cc 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -22,9 +22,9 @@ + - From 5110ae82a1cd76a970ef11bfebf7559dea0c9514 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 21:38:08 +0900 Subject: [PATCH 3997/5608] Tidy up implementation --- .../BeatmapSet/Buttons/FavouriteButton.cs | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index f059e06214..33df1fa485 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -1,6 +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 System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -20,7 +21,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { public readonly Bindable BeatmapSet = new Bindable(); - private readonly Bindable favourited = new Bindable(); + private readonly BindableBool favourited = new BindableBool(); private PostBeatmapFavouriteRequest request; private DimmedLoadingLayer loading; @@ -44,40 +45,45 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons loading = new DimmedLoadingLayer(), }); + favourited.ValueChanged += favourited => icon.Icon = favourited.NewValue ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart; + BeatmapSet.BindValueChanged(setInfo => { - if (setInfo.NewValue?.OnlineInfo?.HasFavourited == null) - return; - - favourited.Value = setInfo.NewValue.OnlineInfo.HasFavourited; - }); - - favourited.ValueChanged += favourited => - { - loading.Hide(); - - icon.Icon = favourited.NewValue ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart; - }; + Enabled.Value = BeatmapSet.Value?.OnlineBeatmapSetID > 0; + favourited.Value = setInfo.NewValue?.OnlineInfo?.HasFavourited ?? false; + }, true); Action = () => { if (loading.State.Value == Visibility.Visible) return; + // guaranteed by disabled state abvove. + Debug.Assert(BeatmapSet.Value.OnlineBeatmapSetID != null); + loading.Show(); request?.Cancel(); - request = new PostBeatmapFavouriteRequest(BeatmapSet.Value?.OnlineBeatmapSetID ?? 0, favourited.Value ? BeatmapFavouriteAction.UnFavourite : BeatmapFavouriteAction.Favourite); - request.Success += () => favourited.Value = !favourited.Value; - request.Failure += exception => + + request = new PostBeatmapFavouriteRequest(BeatmapSet.Value.OnlineBeatmapSetID.Value, favourited.Value ? BeatmapFavouriteAction.UnFavourite : BeatmapFavouriteAction.Favourite); + + request.Success += () => + { + favourited.Toggle(); + loading.Hide(); + }; + + request.Failure += e => { notifications.Post(new SimpleNotification { - Text = exception.Message, + Text = e.Message, Icon = FontAwesome.Solid.Times, }); + loading.Hide(); }; + api.Queue(request); }; } From da819261e0063b6f3a98ed5c28821696c662dcdf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 21:38:16 +0900 Subject: [PATCH 3998/5608] Shrink and darken loading layer to better suit button --- osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs | 7 ++++--- osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs index b7d2222f33..f7138827cc 100644 --- a/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs +++ b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.Color4Extensions; +using osuTK; namespace osu.Game.Graphics.UserInterface { @@ -15,7 +16,7 @@ namespace osu.Game.Graphics.UserInterface private readonly LoadingAnimation loading; - public DimmedLoadingLayer() + public DimmedLoadingLayer(float dimAmount = 0.5f, float iconScale = 1f) { RelativeSizeAxes = Axes.Both; Children = new Drawable[] @@ -23,9 +24,9 @@ namespace osu.Game.Graphics.UserInterface new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(0.5f), + Colour = Color4.Black.Opacity(dimAmount), }, - loading = new LoadingAnimation(), + loading = new LoadingAnimation { Scale = new Vector2(iconScale) }, }; } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 33df1fa485..cfb34e4adf 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.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.Diagnostics; @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons Size = new Vector2(18), Shadow = false, }, - loading = new DimmedLoadingLayer(), + loading = new DimmedLoadingLayer(0.8f, 0.5f), }); favourited.ValueChanged += favourited => icon.Icon = favourited.NewValue ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart; From de732c6c2447e6f1b231cd2d843fa74413819539 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 21:12:38 +0800 Subject: [PATCH 3999/5608] Change code to use Sentry client. --- osu.Game.Tests/Visual/TestSceneOsuGame.cs | 2 +- osu.Game/OsuGame.cs | 4 ++-- .../Utils/{RavenLogger.cs => SentryLogger.cs} | 22 +++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) rename osu.Game/Utils/{RavenLogger.cs => SentryLogger.cs} (84%) diff --git a/osu.Game.Tests/Visual/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/TestSceneOsuGame.cs index 36cd49d839..e495b2a95a 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuGame.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual private IReadOnlyList requiredGameDependencies => new[] { typeof(OsuGame), - typeof(RavenLogger), + typeof(SentryLogger), typeof(OsuLogo), typeof(IdleTracker), typeof(OnScreenDisplay), diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 328c964976..541050a30f 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -71,7 +71,7 @@ namespace osu.Game [Cached] private readonly ScreenshotManager screenshotManager = new ScreenshotManager(); - protected RavenLogger RavenLogger; + protected SentryLogger RavenLogger; public virtual Storage GetStorageForStableInstall() => null; @@ -110,7 +110,7 @@ namespace osu.Game forwardLoggedErrorsToNotifications(); - RavenLogger = new RavenLogger(this); + RavenLogger = new SentryLogger(this); } private void updateBlockingOverlayFade() => diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/SentryLogger.cs similarity index 84% rename from osu.Game/Utils/RavenLogger.cs rename to osu.Game/Utils/SentryLogger.cs index 16178e63bd..9629e830bd 100644 --- a/osu.Game/Utils/RavenLogger.cs +++ b/osu.Game/Utils/SentryLogger.cs @@ -7,26 +7,26 @@ using System.IO; using System.Net; using System.Threading.Tasks; using osu.Framework.Logging; -using SharpRaven; -using SharpRaven.Data; +using Sentry; namespace osu.Game.Utils { /// /// Report errors to sentry. /// - public class RavenLogger : IDisposable + public class SentryLogger : IDisposable { - private readonly RavenClient raven = new RavenClient("https://5e342cd55f294edebdc9ad604d28bbd3@sentry.io/1255255"); - private readonly List tasks = new List(); - public RavenLogger(OsuGame game) + public SentryLogger(OsuGame game) { - raven.Release = game.Version; - if (!game.IsDeployedBuild) return; + SentrySdk.Init(new SentryOptions + { + Dsn = new Dsn("https://5e342cd55f294edebdc9ad604d28bbd3@sentry.io/1255255"), + Release = game.Version + }); Exception lastException = null; Logger.NewEntry += entry => @@ -46,10 +46,10 @@ namespace osu.Game.Utils return; lastException = exception; - queuePendingTask(raven.CaptureAsync(new SentryEvent(exception) { Message = entry.Message })); + SentrySdk.CaptureEvent(new SentryEvent(exception) { Message = entry.Message }); } else - raven.AddTrail(new Breadcrumb(entry.Target.ToString(), BreadcrumbType.Navigation) { Message = entry.Message }); + SentrySdk.AddBreadcrumb(category: entry.Target.ToString(), type: "navigation", message: entry.Message); }; } @@ -93,7 +93,7 @@ namespace osu.Game.Utils #region Disposal - ~RavenLogger() + ~SentryLogger() { Dispose(false); } From e01a50e4b332a0ea70f2dead860f75faf266611a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 21:39:38 +0800 Subject: [PATCH 4000/5608] Correct disposal. --- osu.Game/Utils/SentryLogger.cs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/osu.Game/Utils/SentryLogger.cs b/osu.Game/Utils/SentryLogger.cs index 9629e830bd..256c52489b 100644 --- a/osu.Game/Utils/SentryLogger.cs +++ b/osu.Game/Utils/SentryLogger.cs @@ -16,13 +16,13 @@ namespace osu.Game.Utils /// public class SentryLogger : IDisposable { - private readonly List tasks = new List(); + private IDisposable sentry; public SentryLogger(OsuGame game) { if (!game.IsDeployedBuild) return; - SentrySdk.Init(new SentryOptions + sentry = SentrySdk.Init(new SentryOptions { Dsn = new Dsn("https://5e342cd55f294edebdc9ad604d28bbd3@sentry.io/1255255"), Release = game.Version @@ -81,16 +81,6 @@ namespace osu.Game.Utils return true; } - private void queuePendingTask(Task task) - { - lock (tasks) tasks.Add(task); - task.ContinueWith(_ => - { - lock (tasks) - tasks.Remove(task); - }); - } - #region Disposal ~SentryLogger() @@ -112,7 +102,8 @@ namespace osu.Game.Utils return; isDisposed = true; - lock (tasks) Task.WaitAll(tasks.ToArray(), 5000); + sentry.Dispose(); + sentry = null; } #endregion From 8276428efc0ff891a935acb69220b4f8e4bb7478 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Tue, 12 Nov 2019 20:48:26 +0700 Subject: [PATCH 4001/5608] Add IsPresent check when dialog popping out --- osu.Game/Overlays/Dialog/PopupDialog.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index cff887865a..13eb677263 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -241,7 +241,7 @@ namespace osu.Game.Overlays.Dialog protected override void PopOut() { - if (!actionInvoked) + if (!actionInvoked && content.IsPresent) // In the case a user did not choose an action before a hide was triggered, press the last button. // This is presumed to always be a sane default "cancel" action. buttonsContainer.Last().Click(); From 70a02d27a99e86f4308f62aac12dbe10f75fa5bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 22:53:01 +0900 Subject: [PATCH 4002/5608] Update solution paths --- fastlane/Fastfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 7adf42a1eb..28a83fbbae 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -49,12 +49,12 @@ desc 'Deploy to play store' desc 'Compile the project' lane :build do |options| nuget_restore( - project_path: 'osu.Android.sln' + project_path: 'osu.sln' ) souyuz( build_configuration: 'Release', - solution_path: 'osu.Android.sln', + solution_path: 'osu.sln', platform: "android", output_path: "osu.Android/bin/Release/", keystore_path: options[:keystore_path], @@ -70,7 +70,7 @@ desc 'Deploy to play store' android_build = split.join('') app_version( - solution_path: 'osu.Android.sln', + solution_path: 'osu.sln', version: options[:version], build: android_build, ) @@ -106,7 +106,7 @@ platform :ios do desc 'Compile the project' lane :build do nuget_restore( - project_path: 'osu.iOS.sln' + project_path: 'osu.sln' ) souyuz( From 6ae6603dede8c6fb0c5e9b1671a1e65e5330ccd8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 22:08:16 +0800 Subject: [PATCH 4003/5608] Cleanup. --- osu.Game/OsuGame.cs | 8 ++++---- osu.Game/Utils/SentryLogger.cs | 4 +--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 541050a30f..55768baa7e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -71,7 +71,7 @@ namespace osu.Game [Cached] private readonly ScreenshotManager screenshotManager = new ScreenshotManager(); - protected SentryLogger RavenLogger; + protected SentryLogger SentryLogger; public virtual Storage GetStorageForStableInstall() => null; @@ -110,7 +110,7 @@ namespace osu.Game forwardLoggedErrorsToNotifications(); - RavenLogger = new SentryLogger(this); + SentryLogger = new SentryLogger(this); } private void updateBlockingOverlayFade() => @@ -166,7 +166,7 @@ namespace osu.Game dependencies.CacheAs(this); - dependencies.Cache(RavenLogger); + dependencies.Cache(SentryLogger); dependencies.Cache(osuLogo = new OsuLogo { Alpha = 0 }); @@ -486,7 +486,7 @@ namespace osu.Game protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - RavenLogger.Dispose(); + SentryLogger.Dispose(); } protected override void LoadComplete() diff --git a/osu.Game/Utils/SentryLogger.cs b/osu.Game/Utils/SentryLogger.cs index 256c52489b..5badd2546e 100644 --- a/osu.Game/Utils/SentryLogger.cs +++ b/osu.Game/Utils/SentryLogger.cs @@ -2,10 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.IO; using System.Net; -using System.Threading.Tasks; using osu.Framework.Logging; using Sentry; @@ -102,7 +100,7 @@ namespace osu.Game.Utils return; isDisposed = true; - sentry.Dispose(); + sentry?.Dispose(); sentry = null; } From 8a1276db3aa05c9188490f17e745156b28c1430e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 22:16:48 +0800 Subject: [PATCH 4004/5608] Change to use instance API of sentry. --- osu.Game/Utils/SentryLogger.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Utils/SentryLogger.cs b/osu.Game/Utils/SentryLogger.cs index 5badd2546e..7e879741d6 100644 --- a/osu.Game/Utils/SentryLogger.cs +++ b/osu.Game/Utils/SentryLogger.cs @@ -14,17 +14,21 @@ namespace osu.Game.Utils /// public class SentryLogger : IDisposable { - private IDisposable sentry; + private SentryClient sentry; + private Scope sentryScope; public SentryLogger(OsuGame game) { if (!game.IsDeployedBuild) return; - sentry = SentrySdk.Init(new SentryOptions + var options = new SentryOptions { Dsn = new Dsn("https://5e342cd55f294edebdc9ad604d28bbd3@sentry.io/1255255"), Release = game.Version - }); + }; + sentry = new SentryClient(options); + sentryScope = new Scope(options); + Exception lastException = null; Logger.NewEntry += entry => @@ -44,10 +48,10 @@ namespace osu.Game.Utils return; lastException = exception; - SentrySdk.CaptureEvent(new SentryEvent(exception) { Message = entry.Message }); + sentry.CaptureEvent(new SentryEvent(exception) { Message = entry.Message }, sentryScope); } else - SentrySdk.AddBreadcrumb(category: entry.Target.ToString(), type: "navigation", message: entry.Message); + sentryScope.AddBreadcrumb(DateTimeOffset.Now, entry.Message, entry.Target.ToString(), "navigation"); }; } @@ -102,6 +106,7 @@ namespace osu.Game.Utils isDisposed = true; sentry?.Dispose(); sentry = null; + sentryScope = null; } #endregion From dfd5c8807515bf6f5aec86610ff116e439b99d50 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 00:00:08 +0300 Subject: [PATCH 4005/5608] Typo fix --- osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index cfb34e4adf..4c2a8652f3 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -58,7 +58,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons if (loading.State.Value == Visibility.Visible) return; - // guaranteed by disabled state abvove. + // guaranteed by disabled state above. Debug.Assert(BeatmapSet.Value.OnlineBeatmapSetID != null); loading.Show(); From 3903e59f2fecca4c63de60897a66279763973936 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 00:01:13 +0300 Subject: [PATCH 4006/5608] Add null check for notification overlay --- osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 4c2a8652f3..163251d798 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons request.Failure += e => { - notifications.Post(new SimpleNotification + notifications?.Post(new SimpleNotification { Text = e.Message, Icon = FontAwesome.Solid.Times, From 27f721eec232a056e208d9ffcbbac1b8459db063 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 00:24:13 +0300 Subject: [PATCH 4007/5608] Use = instead of += for OnSelectionChanged Action --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index a7128ca157..09c388a3b0 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -55,7 +55,7 @@ namespace osu.Game.Overlays.BeatmapSet modsContainer.Add(new ModButton(new NoMod())); modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); - modsContainer.ForEach(button => button.OnSelectionChanged += selectionChanged); + modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); } private void selectionChanged(Mod mod, bool selected) From 99ec84ed38643c504378ede2a10894cd0ae5f350 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 00:26:19 +0300 Subject: [PATCH 4008/5608] Update dependency --- .../Overlays/BeatmapSet/LeaderboardModSelector.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 75c24cb710..bd639881e7 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -54,13 +54,9 @@ namespace osu.Game.Overlays.BeatmapSet modsContainer.Add(new ModButton(new NoMod())); - ruleset.NewValue.CreateInstance().GetAllMods().ForEach(mod => - { - if (mod.Ranked) - modsContainer.Add(new ModButton(mod)); - }); + modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); - modsContainer.ForEach(button => button.OnSelectionChanged += selectionChanged); + modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); } private void selectionChanged(Mod mod, bool selected) @@ -77,11 +73,7 @@ namespace osu.Game.Overlays.BeatmapSet protected override bool OnHover(HoverEvent e) { if (!SelectedMods.Any()) - modsContainer.ForEach(button => - { - if (!button.IsHovered) - button.Highlighted.Value = false; - }); + modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = false); return base.OnHover(e); } From 5f609b48da9619025998a867882527b273e19905 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 00:29:28 +0300 Subject: [PATCH 4009/5608] Use local bindable for api.LocalUser --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 73253546bb..bc5daa39a0 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -27,6 +27,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public readonly Bindable Beatmap = new Bindable(); private readonly Bindable ruleset = new Bindable(); private readonly Bindable scope = new Bindable(); + private readonly Bindable user = new Bindable(); private readonly Box background; private readonly ScoreTable scoreTable; @@ -155,6 +156,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void load(OsuColour colours) { background.Colour = colours.Gray2; + + user.BindTo(api.LocalUser); } protected override void LoadComplete() @@ -167,7 +170,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores modSelector.SelectedMods.ItemsRemoved += _ => getScores(); Beatmap.BindValueChanged(onBeatmapChanged); - api.LocalUser.BindValueChanged(onUserChanged, true); + user.BindValueChanged(onUserChanged, true); } private void onBeatmapChanged(ValueChangedEvent beatmap) From 2b8a105ec5cab7296966efab2cc87fcc2d01347e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 11:49:36 +0900 Subject: [PATCH 4010/5608] Fix osu!direct test fail Unsure how this occurred only now; may warrant further investigation. --- osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs index c8c36789c4..5652b8d2bd 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs @@ -19,7 +19,7 @@ namespace osu.Game.Online.API.Requests public SearchBeatmapSetsRequest(string query, RulesetInfo ruleset, BeatmapSearchCategory searchCategory = BeatmapSearchCategory.Any, DirectSortCriteria sortCriteria = DirectSortCriteria.Ranked, SortDirection direction = SortDirection.Descending) { - this.query = System.Uri.EscapeDataString(query); + this.query = string.IsNullOrEmpty(query) ? string.Empty : System.Uri.EscapeDataString(query); this.ruleset = ruleset; this.searchCategory = searchCategory; this.sortCriteria = sortCriteria; From 3c5008f94c20a968e6248dd0e5dcad74c649722d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 11:59:03 +0900 Subject: [PATCH 4011/5608] Add test --- .../Visual/Online/TestSceneFavouriteButton.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs new file mode 100644 index 0000000000..ae21245b59 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs @@ -0,0 +1,46 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Overlays.BeatmapSet.Buttons; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneFavouriteButton : OsuTestScene + { + private FavouriteButton favourite; + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("create button", () => Child = favourite = new FavouriteButton()); + } + + [Test] + public void TestLoggedOutIn() + { + AddStep("set valid beatmap", () => favourite.BeatmapSet.Value = new BeatmapSetInfo { OnlineBeatmapSetID = 88 }); + AddStep("log out", () => API.Logout()); + checkEnabled(false); + AddStep("log in", () => API.Login("test", "test")); + checkEnabled(true); + } + + [Test] + public void TestBeatmapChange() + { + AddStep("log in", () => API.Login("test", "test")); + AddStep("set valid beatmap", () => favourite.BeatmapSet.Value = new BeatmapSetInfo { OnlineBeatmapSetID = 88 }); + checkEnabled(true); + AddStep("set invalid beatmap", () => favourite.BeatmapSet.Value = new BeatmapSetInfo()); + checkEnabled(true); + } + + private void checkEnabled(bool expected) + { + AddAssert("is " + (expected ? "enabled" : "disabled"), () => favourite.Enabled.Value == expected); + } + } +} From f18263aa70dc215af08e6b008c74a5be7a700d39 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 12:09:18 +0900 Subject: [PATCH 4012/5608] Add tests --- .../Visual/Online/TestSceneFavouriteButton.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs index ae21245b59..8e2ee4e28d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs @@ -2,9 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Overlays.BeatmapSet.Buttons; +using osuTK; namespace osu.Game.Tests.Visual.Online { @@ -15,7 +17,13 @@ namespace osu.Game.Tests.Visual.Online [SetUpSteps] public void SetUpSteps() { - AddStep("create button", () => Child = favourite = new FavouriteButton()); + AddStep("create button", () => Child = favourite = new FavouriteButton + { + RelativeSizeAxes = Axes.None, + Size = new Vector2(50), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); } [Test] @@ -35,7 +43,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("set valid beatmap", () => favourite.BeatmapSet.Value = new BeatmapSetInfo { OnlineBeatmapSetID = 88 }); checkEnabled(true); AddStep("set invalid beatmap", () => favourite.BeatmapSet.Value = new BeatmapSetInfo()); - checkEnabled(true); + checkEnabled(false); } private void checkEnabled(bool expected) From c751328665b1c5e1ff2b51f7aa359570518d6f8d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 12:13:33 +0900 Subject: [PATCH 4013/5608] Disable button when not logged in --- .../BeatmapSet/Buttons/FavouriteButton.cs | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 163251d798..af0987d183 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -13,6 +13,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Notifications; +using osu.Game.Users; using osuTK; namespace osu.Game.Overlays.BeatmapSet.Buttons @@ -26,12 +27,23 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private PostBeatmapFavouriteRequest request; private DimmedLoadingLayer loading; - public string TooltipText => (favourited.Value ? "Unfavourite" : "Favourite") + " this beatmapset"; + private readonly Bindable localUser = new Bindable(); + + public string TooltipText + { + get + { + if (!Enabled.Value) return string.Empty; + + return (favourited.Value ? "Unfavourite" : "Favourite") + " this beatmapset"; + } + } [BackgroundDependencyLoader(true)] private void load(IAPIProvider api, NotificationOverlay notifications) { SpriteIcon icon; + AddRange(new Drawable[] { icon = new SpriteIcon @@ -45,14 +57,6 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons loading = new DimmedLoadingLayer(0.8f, 0.5f), }); - favourited.ValueChanged += favourited => icon.Icon = favourited.NewValue ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart; - - BeatmapSet.BindValueChanged(setInfo => - { - Enabled.Value = BeatmapSet.Value?.OnlineBeatmapSetID > 0; - favourited.Value = setInfo.NewValue?.OnlineInfo?.HasFavourited ?? false; - }, true); - Action = () => { if (loading.State.Value == Visibility.Visible) @@ -86,8 +90,22 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons api.Queue(request); }; + + favourited.ValueChanged += favourited => icon.Icon = favourited.NewValue ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart; + + localUser.BindTo(api.LocalUser); + localUser.BindValueChanged(_ => updateEnabled()); + + // must be run after setting the Action to ensure correct enabled state (setting an Action forces a button to be enabled). + BeatmapSet.BindValueChanged(setInfo => + { + updateEnabled(); + favourited.Value = setInfo.NewValue?.OnlineInfo?.HasFavourited ?? false; + }, true); } + private void updateEnabled() => Enabled.Value = !(localUser.Value is GuestUser) && BeatmapSet.Value?.OnlineBeatmapSetID > 0; + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); From 4c0bca5c070da01dfdd6800e93113e58c1bebed6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 18:35:28 +0900 Subject: [PATCH 4014/5608] Add ability to delete control points via right-click option --- .../Components/PathControlPointPiece.cs | 10 +- .../Components/PathControlPointVisualiser.cs | 102 +++++++++++------- 2 files changed, 69 insertions(+), 43 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 155e814596..70b4842089 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -14,6 +14,7 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Objects; using osuTK; using osuTK.Graphics; +using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { @@ -129,6 +130,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components protected override bool OnMouseDown(MouseDownEvent e) { + if (e.Button != MouseButton.Left) + return false; + if (RequestSelection != null) { RequestSelection.Invoke(Index); @@ -138,11 +142,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return false; } - protected override bool OnMouseUp(MouseUpEvent e) => RequestSelection != null; + protected override bool OnMouseUp(MouseUpEvent e) => e.Button == MouseButton.Left && RequestSelection != null; - protected override bool OnClick(ClickEvent e) => RequestSelection != null; + protected override bool OnClick(ClickEvent e) => e.Button == MouseButton.Left && RequestSelection != null; - protected override bool OnDragStart(DragStartEvent e) => true; + protected override bool OnDragStart(DragStartEvent e) => e.Button == MouseButton.Left; protected override bool OnDrag(DragEvent e) { diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 6962736157..f3fbb1f93f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -3,19 +3,23 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose; using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { - public class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler + public class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler, IHasContextMenu { public Action ControlPointsChanged; @@ -73,6 +77,19 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return false; } + public bool OnPressed(PlatformAction action) + { + switch (action.ActionMethod) + { + case PlatformActionMethod.Delete: + return deleteSelected(); + } + + return false; + } + + public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; + private void selectPiece(int index) { if (inputManager.CurrentState.Keyboard.ControlPressed) @@ -84,50 +101,55 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components } } - public bool OnPressed(PlatformAction action) + private bool deleteSelected() { - switch (action.ActionMethod) + var newControlPoints = new List(); + + foreach (var piece in Pieces) { - case PlatformActionMethod.Delete: - var newControlPoints = new List(); - - foreach (var piece in Pieces) - { - if (!piece.IsSelected.Value) - newControlPoints.Add(slider.Path.ControlPoints[piece.Index]); - } - - // Ensure that there are any points to be deleted - if (newControlPoints.Count == slider.Path.ControlPoints.Length) - return false; - - // If there are 0 remaining control points, treat the slider as being deleted - if (newControlPoints.Count == 0) - { - placementHandler?.Delete(slider); - return true; - } - - // Make control points relative - Vector2 first = newControlPoints[0]; - for (int i = 0; i < newControlPoints.Count; i++) - newControlPoints[i] = newControlPoints[i] - first; - - // The slider's position defines the position of the first control point, and all further control points are relative to that point - slider.Position = slider.Position + first; - - // Since pieces are re-used, they will not point to the deleted control points while remaining selected - foreach (var piece in Pieces) - piece.IsSelected.Value = false; - - ControlPointsChanged?.Invoke(newControlPoints.ToArray()); - - return true; + if (!piece.IsSelected.Value) + newControlPoints.Add(slider.Path.ControlPoints[piece.Index]); } - return false; + // Ensure that there are any points to be deleted + if (newControlPoints.Count == slider.Path.ControlPoints.Length) + return false; + + // If there are 0 remaining control points, treat the slider as being deleted + if (newControlPoints.Count == 0) + { + placementHandler?.Delete(slider); + return true; + } + + // Make control points relative + Vector2 first = newControlPoints[0]; + for (int i = 0; i < newControlPoints.Count; i++) + newControlPoints[i] = newControlPoints[i] - first; + + // The slider's position defines the position of the first control point, and all further control points are relative to that point + slider.Position = slider.Position + first; + + // Since pieces are re-used, they will not point to the deleted control points while remaining selected + foreach (var piece in Pieces) + piece.IsSelected.Value = false; + + ControlPointsChanged?.Invoke(newControlPoints.ToArray()); + return true; } - public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; + public MenuItem[] ContextMenuItems + { + get + { + if (!Pieces.Any(p => p.IsSelected.Value)) + return Array.Empty(); + + return new MenuItem[] + { + new OsuMenuItem("Delete control points", MenuItemType.Destructive, () => deleteSelected()) + }; + } + } } } From 9c52d239b44c06a2bdfeb9336e531fed5a1c9eb5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Nov 2019 16:56:48 +0900 Subject: [PATCH 4015/5608] Return null to allow passthrough --- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index f3fbb1f93f..fd14e6dc23 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components get { if (!Pieces.Any(p => p.IsSelected.Value)) - return Array.Empty(); + return null; return new MenuItem[] { From 76ab0ecd3c0b5e27bf87750981bf30ed83cb2a79 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Nov 2019 17:21:48 +0900 Subject: [PATCH 4016/5608] Disallow deselections with right clicks --- .../Edit/Compose/Components/BlueprintContainer.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 2be4ca684a..195bc663f1 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -313,14 +313,15 @@ namespace osu.Game.Screens.Edit.Compose.Components /// Attempts to select any hovered blueprints. /// /// The input event that triggered this selection. - private void beginClickSelection(UIEvent e) + private void beginClickSelection(MouseButtonEvent e) { Debug.Assert(!clickSelectionBegan); - // If a select blueprint is already hovered, disallow changes in selection. - // Exception is made when holding control, as deselection should still be allowed. - if (!e.CurrentState.Keyboard.ControlPressed && - selectionHandler.SelectedBlueprints.Any(s => s.IsHovered)) + // Deselections are only allowed for control + left clicks + bool allowDeselection = e.ControlPressed && e.Button == MouseButton.Left; + + // Todo: This is probably incorrectly disallowing multiple selections on stacked objects + if (!allowDeselection && selectionHandler.SelectedBlueprints.Any(s => s.IsHovered)) return; foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) From c56503ee88c2969c90df8a5679774f870371782e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Nov 2019 17:28:18 +0900 Subject: [PATCH 4017/5608] Select single control point on right click --- .../Components/PathControlPointPiece.cs | 20 ++++++++++++------- .../Components/PathControlPointVisualiser.cs | 5 +++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 70b4842089..0ccf020300 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public class PathControlPointPiece : BlueprintPiece { - public Action RequestSelection; + public Action RequestSelection; public Action ControlPointsChanged; public readonly BindableBool IsSelected = new BindableBool(); @@ -130,21 +130,27 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components protected override bool OnMouseDown(MouseDownEvent e) { - if (e.Button != MouseButton.Left) + if (RequestSelection == null) return false; - if (RequestSelection != null) + switch (e.Button) { - RequestSelection.Invoke(Index); - return true; + case MouseButton.Left: + RequestSelection.Invoke(Index, e); + return true; + + case MouseButton.Right: + if (!IsSelected.Value) + RequestSelection.Invoke(Index, e); + return false; // Allow context menu to show } return false; } - protected override bool OnMouseUp(MouseUpEvent e) => e.Button == MouseButton.Left && RequestSelection != null; + protected override bool OnMouseUp(MouseUpEvent e) => RequestSelection != null; - protected override bool OnClick(ClickEvent e) => e.Button == MouseButton.Left && RequestSelection != null; + protected override bool OnClick(ClickEvent e) => RequestSelection != null; protected override bool OnDragStart(DragStartEvent e) => e.Button == MouseButton.Left; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index fd14e6dc23..97c756417c 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -16,6 +16,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose; using osuTK; +using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { @@ -90,9 +91,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; - private void selectPiece(int index) + private void selectPiece(int index, MouseButtonEvent e) { - if (inputManager.CurrentState.Keyboard.ControlPressed) + if (e.Button == MouseButton.Left && inputManager.CurrentState.Keyboard.ControlPressed) Pieces[index].IsSelected.Toggle(); else { From d835def4abfc5d52d22d604e35f7f596e3c54a48 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Nov 2019 17:36:46 +0900 Subject: [PATCH 4018/5608] Add point count to the menu item text --- .../Sliders/Components/PathControlPointVisualiser.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 97c756417c..8d598f1ab3 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Humanizer; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -143,12 +144,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { get { - if (!Pieces.Any(p => p.IsSelected.Value)) + int selectedPoints = Pieces.Count(p => p.IsSelected.Value); + + if (selectedPoints == 0) return null; return new MenuItem[] { - new OsuMenuItem("Delete control points", MenuItemType.Destructive, () => deleteSelected()) + new OsuMenuItem($"Delete {"control point".ToQuantity(selectedPoints)}", MenuItemType.Destructive, () => deleteSelected()) }; } } From 031b686ee96386d8d7bd5b00d4f5a336037ea874 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Nov 2019 17:38:34 +0900 Subject: [PATCH 4019/5608] Only accept input while hovered --- .../Sliders/Components/PathControlPointVisualiser.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 8d598f1ab3..2bcce99c89 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -144,6 +144,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { get { + if (!Pieces.Any(p => p.IsHovered)) + return null; + int selectedPoints = Pieces.Count(p => p.IsSelected.Value); if (selectedPoints == 0) From bca1be0bfa69c0c6c6e5bb1a756eb573f1e0d0e0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 18:54:33 +0900 Subject: [PATCH 4020/5608] Add failing test --- .../SongSelect/TestScenePlaySongSelect.cs | 53 +++++++++++++------ osu.Game/Screens/Select/SongSelect.cs | 4 +- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 794d135b06..2d1a786bb9 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -57,23 +57,6 @@ namespace osu.Game.Tests.Visual.SongSelect typeof(DrawableCarouselBeatmapSet), }; - private class TestSongSelect : PlaySongSelect - { - public Action StartRequested; - - public new Bindable Ruleset => base.Ruleset; - - public WorkingBeatmap CurrentBeatmap => Beatmap.Value; - public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap; - public new BeatmapCarousel Carousel => base.Carousel; - - protected override bool OnStart() - { - StartRequested?.Invoke(); - return base.OnStart(); - } - } - private TestSongSelect songSelect; [BackgroundDependencyLoader] @@ -101,6 +84,17 @@ namespace osu.Game.Tests.Visual.SongSelect manager?.Delete(manager.GetAllUsableBeatmapSets()); }); + [Test] + public void TestSingleFilterOnEnter() + { + addRulesetImportStep(0); + addRulesetImportStep(0); + + createSongSelect(); + + AddAssert("filter count is 1", () => songSelect.FilterCount == 1); + } + [Test] public void TestAudioResuming() { @@ -357,5 +351,30 @@ namespace osu.Game.Tests.Visual.SongSelect base.Dispose(isDisposing); rulesets?.Dispose(); } + + private class TestSongSelect : PlaySongSelect + { + public Action StartRequested; + + public new Bindable Ruleset => base.Ruleset; + + public WorkingBeatmap CurrentBeatmap => Beatmap.Value; + public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap; + public new BeatmapCarousel Carousel => base.Carousel; + + protected override bool OnStart() + { + StartRequested?.Invoke(); + return base.OnStart(); + } + + public int FilterCount; + + protected override void ApplyFilterToCarousel(FilterCriteria criteria) + { + FilterCount++; + base.ApplyFilterToCarousel(criteria); + } + } } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 375b994169..6810f77b93 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -165,7 +165,7 @@ namespace osu.Game.Screens.Select { RelativeSizeAxes = Axes.X, Height = FilterControl.HEIGHT, - FilterChanged = c => Carousel.Filter(c), + FilterChanged = ApplyFilterToCarousel, Background = { Width = 2 }, }, } @@ -217,6 +217,8 @@ namespace osu.Game.Screens.Select BeatmapDetails.Leaderboard.ScoreSelected += score => this.Push(new SoloResults(score)); } + protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) => Carousel.Filter(criteria); + [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { From 280c1a0eb42b16954c4ffd98257bfb7e92ec0440 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 18:00:45 +0900 Subject: [PATCH 4021/5608] Fix carousel filtering twice on startup due to unpopulated ruleset --- osu.Game/Screens/Select/SongSelect.cs | 37 +++++++++++++++------------ 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 6810f77b93..269fb1b683 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -46,40 +46,40 @@ namespace osu.Game.Screens.Select protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; - public readonly FilterControl FilterControl; + public FilterControl FilterControl; protected virtual bool ShowFooter => true; /// /// Can be null if is false. /// - protected readonly BeatmapOptionsOverlay BeatmapOptions; + protected BeatmapOptionsOverlay BeatmapOptions; /// /// Can be null if is false. /// - protected readonly Footer Footer; + protected Footer Footer; /// /// Contains any panel which is triggered by a footer button. /// Helps keep them located beneath the footer itself. /// - protected readonly Container FooterPanels; + protected Container FooterPanels; protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(); - protected readonly BeatmapCarousel Carousel; - private readonly BeatmapInfoWedge beatmapInfoWedge; + protected BeatmapCarousel Carousel; + private BeatmapInfoWedge beatmapInfoWedge; private DialogOverlay dialogOverlay; private BeatmapManager beatmaps; - protected readonly ModSelectOverlay ModSelect; + protected ModSelectOverlay ModSelect; protected SampleChannel SampleConfirm; private SampleChannel sampleChangeDifficulty; private SampleChannel sampleChangeBeatmap; - protected readonly BeatmapDetailArea BeatmapDetails; + protected BeatmapDetailArea BeatmapDetails; private readonly Bindable decoupledRuleset = new Bindable(); @@ -90,8 +90,14 @@ namespace osu.Game.Screens.Select [Cached(Type = typeof(IBindable>))] private readonly Bindable> mods = new Bindable>(Array.Empty()); // Bound to the game's mods, but is not reset on exiting - protected SongSelect() + protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) => Carousel.Filter(criteria); + + [BackgroundDependencyLoader(true)] + private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { + // transfer initial value so filter is in a good state (it uses our re-cached bindables). + transferRulesetValue(); + AddRangeInternal(new Drawable[] { new ParallaxContainer @@ -215,13 +221,7 @@ namespace osu.Game.Screens.Select } BeatmapDetails.Leaderboard.ScoreSelected += score => this.Push(new SoloResults(score)); - } - protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) => Carousel.Filter(criteria); - - [BackgroundDependencyLoader(true)] - private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) - { if (Footer != null) { Footer.AddButton(new FooterButtonMods { Current = mods }, ModSelect); @@ -640,7 +640,7 @@ namespace osu.Game.Screens.Select return; // manual binding to parent ruleset to allow for delayed load in the incoming direction. - rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value; + transferRulesetValue(); Ruleset.ValueChanged += r => updateSelectedRuleset(r.NewValue); decoupledRuleset.ValueChanged += r => Ruleset.Value = r.NewValue; @@ -652,6 +652,11 @@ namespace osu.Game.Screens.Select boundLocalBindables = true; } + private void transferRulesetValue() + { + rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value; + } + private void delete(BeatmapSetInfo beatmap) { if (beatmap == null || beatmap.ID <= 0) return; From 2cd156f3d4d005e445e7015de7af4171d716f013 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 19:09:03 +0900 Subject: [PATCH 4022/5608] Clean up carousel tests --- .../SongSelect/TestSceneBeatmapCarousel.cs | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index aa63bc1cf6..783bd8ae39 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -10,6 +10,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets; @@ -51,11 +52,6 @@ namespace osu.Game.Tests.Visual.SongSelect private void load(RulesetStore rulesets) { this.rulesets = rulesets; - - Add(carousel = new TestBeatmapCarousel - { - RelativeSizeAxes = Axes.Both, - }); } /// @@ -375,6 +371,8 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestSelectingFilteredRuleset() { + createCarousel(); + var testMixed = createTestBeatmapSet(set_count + 1); AddStep("add mixed ruleset beatmapset", () => { @@ -429,6 +427,8 @@ namespace osu.Game.Tests.Visual.SongSelect private void loadBeatmaps(List beatmapSets = null) { + createCarousel(); + if (beatmapSets == null) { beatmapSets = new List(); @@ -448,6 +448,17 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("Wait for load", () => changed); } + private void createCarousel(Container target = null) + { + AddStep($"Create carousel", () => + { + (target ?? this).Child = carousel = new TestBeatmapCarousel + { + RelativeSizeAxes = Axes.Both, + }; + }); + } + private void ensureRandomFetchSuccess() => AddAssert("ensure prev random fetch worked", () => selectedSets.Peek() == carousel.SelectedBeatmapSet); From 110c155fa0daa22ebbb54e89f7e22ee4c07cee1b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 19:42:05 +0900 Subject: [PATCH 4023/5608] Fix background loading twice when entering song select --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 375b994169..b814253f25 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -66,7 +66,7 @@ namespace osu.Game.Screens.Select /// protected readonly Container FooterPanels; - protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(); + protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); protected readonly BeatmapCarousel Carousel; private readonly BeatmapInfoWedge beatmapInfoWedge; From 2fe068174ab434634a29c124ff15910cd3906c2e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 19:42:33 +0900 Subject: [PATCH 4024/5608] Fix unnecessary string interpolation --- osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 783bd8ae39..14077c8e53 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -450,7 +450,7 @@ namespace osu.Game.Tests.Visual.SongSelect private void createCarousel(Container target = null) { - AddStep($"Create carousel", () => + AddStep("Create carousel", () => { (target ?? this).Child = carousel = new TestBeatmapCarousel { From 8f7fd9993d787c9be72fb088acd57e57a22c49d5 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 13 Nov 2019 14:24:22 +0300 Subject: [PATCH 4025/5608] Fix preview track manager potentially not updating --- osu.Game/Audio/PreviewTrackManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 72b33c4073..ede84e18fb 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -24,6 +24,8 @@ namespace osu.Game.Audio private TrackManagerPreviewTrack current; + public override bool IsPresent => Scheduler.HasPendingTasks; + [BackgroundDependencyLoader] private void load(AudioManager audio) { From 6715b25ddd767c1a1d2b8891033b827765ce2ac7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 16:04:15 +0300 Subject: [PATCH 4026/5608] Apply suggestions --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 09c388a3b0..b400141abf 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -118,14 +118,14 @@ namespace osu.Game.Overlays.BeatmapSet protected override bool OnClick(ClickEvent e) { - Selected.Value = !Selected.Value; - return base.OnClick(e); + Selected.Toggle(); + return true; } protected override bool OnHover(HoverEvent e) { updateState(); - return base.OnHover(e); + return false; } protected override void OnHoverLost(HoverLostEvent e) From 2dbee5da79e027b3903acb8fd280b6fa9aa85333 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 16:06:37 +0300 Subject: [PATCH 4027/5608] Update dependency --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index bd639881e7..b400141abf 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -53,7 +53,6 @@ namespace osu.Game.Overlays.BeatmapSet return; modsContainer.Add(new ModButton(new NoMod())); - modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); @@ -119,14 +118,14 @@ namespace osu.Game.Overlays.BeatmapSet protected override bool OnClick(ClickEvent e) { - Selected.Value = !Selected.Value; - return base.OnClick(e); + Selected.Toggle(); + return true; } protected override bool OnHover(HoverEvent e) { updateState(); - return base.OnHover(e); + return false; } protected override void OnHoverLost(HoverLostEvent e) From 47cbd516f392b8d824d4cd8782bce0ecb88e0e44 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 13 Nov 2019 16:11:13 +0300 Subject: [PATCH 4028/5608] Revert "Fix preview track manager potentially not updating" This reverts commit 8f7fd9993d787c9be72fb088acd57e57a22c49d5. --- osu.Game/Audio/PreviewTrackManager.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index ede84e18fb..72b33c4073 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -24,8 +24,6 @@ namespace osu.Game.Audio private TrackManagerPreviewTrack current; - public override bool IsPresent => Scheduler.HasPendingTasks; - [BackgroundDependencyLoader] private void load(AudioManager audio) { From 172e777416e551c2a9ea177fb4e6cf6838d2c71b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 13 Nov 2019 16:16:06 +0300 Subject: [PATCH 4029/5608] Fix preview track manager permanently muting game tracks --- osu.Game/Audio/PreviewTrackManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 72b33c4073..201671849a 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -80,7 +80,6 @@ namespace osu.Game.Audio return; current.Stop(); - current = null; } /// From 4e90daf212d718d3a64611d1e153bcca292fce53 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 16:39:33 +0300 Subject: [PATCH 4030/5608] Implement NoScoresPlaceholder --- .../BeatmapSet/Scores/NoScoresPlaceholder.cs | 50 +++++++++++++++++++ .../BeatmapSet/Scores/ScoresContainer.cs | 13 +++++ 2 files changed, 63 insertions(+) create mode 100644 osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs new file mode 100644 index 0000000000..b34e54b301 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs @@ -0,0 +1,50 @@ +// 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.Framework.Bindables; +using osu.Game.Screens.Select.Leaderboards; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Overlays.BeatmapSet.Scores +{ + public class NoScoresPlaceholder : Container + { + public readonly Bindable Scope = new Bindable(); + + private readonly SpriteText text; + + public NoScoresPlaceholder() + { + AutoSizeAxes = Axes.Both; + Child = text = new SpriteText + { + Font = OsuFont.GetFont(), + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Scope.BindValueChanged(scope => text.Text = getText(scope.NewValue), true); + } + + private string getText(BeatmapLeaderboardScope scope) + { + switch (scope) + { + default: + case BeatmapLeaderboardScope.Global: + return @"No scores yet. Maybe should try setting some?"; + + case BeatmapLeaderboardScope.Friend: + return @"None of your friends has set a score on this map yet!"; + + case BeatmapLeaderboardScope.Country: + return @"No one from your country has set a score on this map yet!"; + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index bc5daa39a0..62ec9ca609 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -35,6 +35,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly LoadingAnimation loadingAnimation; private readonly FillFlowContainer modFilter; private readonly LeaderboardModSelector modSelector; + private readonly NoScoresPlaceholder noScoresPlaceholder; [Resolved] private IAPIProvider api { get; set; } @@ -125,6 +126,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(0, spacing), Children = new Drawable[] { + noScoresPlaceholder = new NoScoresPlaceholder + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Alpha = 0, + Scope = { BindTarget = scope } + }, topScoresContainer = new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -204,6 +212,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Scores = null; + noScoresPlaceholder.Hide(); + updateModFilterVisibility(); if (hasNoLeaderboard) @@ -215,6 +225,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { loadingAnimation.Hide(); Scores = scores; + + if (!scores.Scores.Any()) + noScoresPlaceholder.Show(); }; api.Queue(getScoresRequest); } From 3f6140db6dbe88f0412ca7e08c8206a1657c2b1f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 17:18:58 +0300 Subject: [PATCH 4031/5608] Improve loading animation --- .../BeatmapSet/Scores/NoScoresPlaceholder.cs | 20 +++----- .../BeatmapSet/Scores/ScoresContainer.cs | 50 +++++++++++-------- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs index b34e54b301..4241ea3e54 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs @@ -4,7 +4,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; -using osu.Framework.Bindables; using osu.Game.Screens.Select.Leaderboards; using osu.Framework.Graphics.Sprites; @@ -12,8 +11,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { public class NoScoresPlaceholder : Container { - public readonly Bindable Scope = new Bindable(); - private readonly SpriteText text; public NoScoresPlaceholder() @@ -25,25 +22,22 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }; } - protected override void LoadComplete() - { - base.LoadComplete(); - Scope.BindValueChanged(scope => text.Text = getText(scope.NewValue), true); - } - - private string getText(BeatmapLeaderboardScope scope) + public void UpdateText(BeatmapLeaderboardScope scope) { switch (scope) { default: case BeatmapLeaderboardScope.Global: - return @"No scores yet. Maybe should try setting some?"; + text.Text = @"No scores yet. Maybe should try setting some?"; + return; case BeatmapLeaderboardScope.Friend: - return @"None of your friends has set a score on this map yet!"; + text.Text = @"None of your friends has set a score on this map yet!"; + return; case BeatmapLeaderboardScope.Country: - return @"No one from your country has set a score on this map yet!"; + text.Text = @"No one from your country has set a score on this map yet!"; + return; } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 62ec9ca609..c74c4e3df0 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -23,6 +23,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public class ScoresContainer : CompositeDrawable { private const int spacing = 15; + private const int duration = 200; public readonly Bindable Beatmap = new Bindable(); private readonly Bindable ruleset = new Bindable(); @@ -32,7 +33,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly Box background; private readonly ScoreTable scoreTable; private readonly FillFlowContainer topScoresContainer; - private readonly LoadingAnimation loadingAnimation; + private readonly DimmedLoadingLayer loading; private readonly FillFlowContainer modFilter; private readonly LeaderboardModSelector modSelector; private readonly NoScoresPlaceholder noScoresPlaceholder; @@ -89,7 +90,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores AutoSizeAxes = Axes.Y, Width = 0.95f, Direction = FillDirection.Vertical, - Spacing = new Vector2(0, spacing), Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { @@ -116,8 +116,17 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, + Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { + noScoresPlaceholder = new NoScoresPlaceholder + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Alpha = 0, + AlwaysPresent = true, + Margin = new MarginPadding { Vertical = 10 } + }, new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -126,13 +135,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(0, spacing), Children = new Drawable[] { - noScoresPlaceholder = new NoScoresPlaceholder - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Alpha = 0, - Scope = { BindTarget = scope } - }, topScoresContainer = new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -147,12 +149,16 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } }, - loadingAnimation = new LoadingAnimation + new Container { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Alpha = 0, - }, + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 10, + Child = loading = new DimmedLoadingLayer(iconScale: 0.8f) + { + Alpha = 0, + }, + } } } } @@ -210,24 +216,28 @@ namespace osu.Game.Overlays.BeatmapSet.Scores getScoresRequest?.Cancel(); getScoresRequest = null; - Scores = null; - - noScoresPlaceholder.Hide(); + noScoresPlaceholder.FadeOut(duration, Easing.OutQuint); updateModFilterVisibility(); if (hasNoLeaderboard) + { + Scores = null; return; + } - loadingAnimation.Show(); + loading.Show(); getScoresRequest = new GetScoresRequest(Beatmap.Value, Beatmap.Value.Ruleset, scope.Value, modSelector.SelectedMods); getScoresRequest.Success += scores => { - loadingAnimation.Hide(); + loading.Hide(); Scores = scores; if (!scores.Scores.Any()) - noScoresPlaceholder.Show(); + { + noScoresPlaceholder.UpdateText(scope.Value); + noScoresPlaceholder.FadeIn(duration, Easing.OutQuint); + } }; api.Queue(getScoresRequest); } From 8005ee73af2f77b9cb12f00cdeb07e40b05c9e77 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 17:23:46 +0300 Subject: [PATCH 4032/5608] Trim whitespace --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index c74c4e3df0..bc950a0c0c 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -116,7 +116,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, - Margin = new MarginPadding { Vertical = spacing }, + Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { noScoresPlaceholder = new NoScoresPlaceholder From f90a9db2b226bfc929430333898c7dc1e5195a7c Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 13 Nov 2019 22:29:44 +0800 Subject: [PATCH 4033/5608] Add BannedApiAnalyzer --- CodeAnalysis/BannedSymbols.txt | 4 ++++ Directory.Build.props | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 CodeAnalysis/BannedSymbols.txt diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt new file mode 100644 index 0000000000..9fb86485d2 --- /dev/null +++ b/CodeAnalysis/BannedSymbols.txt @@ -0,0 +1,4 @@ +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. +T:System.IComparable;Don't use non-generic IComparable. Use generic version instead. diff --git a/Directory.Build.props b/Directory.Build.props index b4baa2833e..9735c78913 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -14,6 +14,10 @@ + + + + From d1853ea55bfc0ddd04c7785ebb246a9865877389 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 17:29:50 +0300 Subject: [PATCH 4034/5608] Fix incorrect formatting for switch/case --- .../BeatmapSet/Scores/NoScoresPlaceholder.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs index 4241ea3e54..aefff5d567 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs @@ -28,16 +28,16 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { default: case BeatmapLeaderboardScope.Global: - text.Text = @"No scores yet. Maybe should try setting some?"; - return; + text.Text = @"No scores yet. Maybe should try setting some?"; + return; case BeatmapLeaderboardScope.Friend: - text.Text = @"None of your friends has set a score on this map yet!"; - return; + text.Text = @"None of your friends has set a score on this map yet!"; + return; case BeatmapLeaderboardScope.Country: - text.Text = @"No one from your country has set a score on this map yet!"; - return; + text.Text = @"No one from your country has set a score on this map yet!"; + return; } } } From 87d40cf8d019756114e91708e082fc34feb30878 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 13 Nov 2019 22:35:50 +0800 Subject: [PATCH 4035/5608] Resolve equals usages. --- osu.Game/Online/Leaderboards/Leaderboard.cs | 2 +- osu.Game/Overlays/DirectOverlay.cs | 2 +- osu.Game/Overlays/SocialOverlay.cs | 2 +- osu.Game/Screens/Menu/MenuSideFlashes.cs | 2 +- osu.Game/Screens/Play/KeyCounterAction.cs | 6 ++++-- osu.Game/Screens/Select/SongSelect.cs | 2 +- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index d214743b30..94c50185da 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -101,7 +101,7 @@ namespace osu.Game.Online.Leaderboards get => scope; set { - if (value.Equals(scope)) + if (EqualityComparer.Default.Equals(value, scope)) return; scope = value; diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 7dcf76e41f..494bfcb2cc 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays get => beatmapSets; set { - if (beatmapSets?.Equals(value) ?? false) return; + if (beatmapSets?.SequenceEqual(value) ?? false) return; beatmapSets = value?.ToList(); diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 6f468bbeb7..5987a5f138 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays get => users; set { - if (users?.Equals(value) ?? false) + if (users?.SequenceEqual(value) ?? false) return; users = value?.ToList(); diff --git a/osu.Game/Screens/Menu/MenuSideFlashes.cs b/osu.Game/Screens/Menu/MenuSideFlashes.cs index 55a6a33e89..3a88cda4ef 100644 --- a/osu.Game/Screens/Menu/MenuSideFlashes.cs +++ b/osu.Game/Screens/Menu/MenuSideFlashes.cs @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Menu private void flash(Drawable d, double beatLength, bool kiai, TrackAmplitudes amplitudes) { - d.FadeTo(Math.Max(0, ((d.Equals(leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier)), box_fade_in_time) + d.FadeTo(Math.Max(0, ((ReferenceEquals(d, leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier)), box_fade_in_time) .Then() .FadeOut(beatLength, Easing.In); } diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterAction.cs index f60ad7aa5a..33d675358c 100644 --- a/osu.Game/Screens/Play/KeyCounterAction.cs +++ b/osu.Game/Screens/Play/KeyCounterAction.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; + namespace osu.Game.Screens.Play { public class KeyCounterAction : KeyCounter @@ -16,7 +18,7 @@ namespace osu.Game.Screens.Play public bool OnPressed(T action, bool forwards) { - if (!action.Equals(Action)) + if (!EqualityComparer.Default.Equals(action, Action)) return false; IsLit = true; @@ -27,7 +29,7 @@ namespace osu.Game.Screens.Play public bool OnReleased(T action, bool forwards) { - if (!action.Equals(Action)) + if (!EqualityComparer.Default.Equals(action, Action)) return false; IsLit = false; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 375b994169..fb057fcf18 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -405,7 +405,7 @@ namespace osu.Game.Screens.Select // We may be arriving here due to another component changing the bindable Beatmap. // In these cases, the other component has already loaded the beatmap, so we don't need to do so again. - if (!Equals(beatmap, Beatmap.Value.BeatmapInfo)) + if (!beatmap.Equals(Beatmap.Value.BeatmapInfo)) { Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\""); From 633c497602db249d5113eb2e35a725f1a53fff3d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 17:36:08 +0300 Subject: [PATCH 4036/5608] Hide content if beatmap has no leaderboard --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index bc950a0c0c..32e5314fba 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -37,6 +37,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly FillFlowContainer modFilter; private readonly LeaderboardModSelector modSelector; private readonly NoScoresPlaceholder noScoresPlaceholder; + private readonly FillFlowContainer content; [Resolved] private IAPIProvider api { get; set; } @@ -82,7 +83,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { RelativeSizeAxes = Axes.Both, }, - new FillFlowContainer + content = new FillFlowContainer { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -223,9 +224,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (hasNoLeaderboard) { Scores = null; + content.Hide(); return; } + content.Show(); loading.Show(); getScoresRequest = new GetScoresRequest(Beatmap.Value, Beatmap.Value.Ruleset, scope.Value, modSelector.SelectedMods); getScoresRequest.Success += scores => From 2d3fadc1a8d21ed1895db93542bec2b597a50645 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 14 Nov 2019 00:38:37 +0300 Subject: [PATCH 4037/5608] Don't update mod filter visibility on every beatmap change --- .../Overlays/BeatmapSet/Scores/ScoresContainer.cs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 32e5314fba..3e3f823368 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -204,12 +204,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { scope.Value = BeatmapLeaderboardScope.Global; modSelector.DeselectAll(); - updateModFilterVisibility(); - } - - private void updateModFilterVisibility() - { - modFilter.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter && !hasNoLeaderboard ? 1 : 0); + modFilter.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter ? 1 : 0); } private void getScores() @@ -219,9 +214,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores noScoresPlaceholder.FadeOut(duration, Easing.OutQuint); - updateModFilterVisibility(); - - if (hasNoLeaderboard) + if (Beatmap.Value?.OnlineBeatmapID.HasValue != true || Beatmap.Value.Status <= BeatmapSetOnlineStatus.Pending) { Scores = null; content.Hide(); @@ -244,7 +237,5 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }; api.Queue(getScoresRequest); } - - private bool hasNoLeaderboard => Beatmap.Value?.OnlineBeatmapID.HasValue != true || Beatmap.Value.Status <= BeatmapSetOnlineStatus.Pending; } } From a580b9079a7995718fb7a1083882a9288a339ea7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 08:28:41 +0900 Subject: [PATCH 4038/5608] Reword comment --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 269fb1b683..1f16b134c4 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -95,7 +95,7 @@ namespace osu.Game.Screens.Select [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { - // transfer initial value so filter is in a good state (it uses our re-cached bindables). + // initial value transfer is requried for FilterControl (it uses our re-cached bindables in its asynd loac for the initial filter). transferRulesetValue(); AddRangeInternal(new Drawable[] From d8a5750e5d1f3462bf7edc4d7d48ba5f35341fd1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 08:38:01 +0900 Subject: [PATCH 4039/5608] Fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bartłomiej Dach --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 1f16b134c4..b595003f0a 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -95,7 +95,7 @@ namespace osu.Game.Screens.Select [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { - // initial value transfer is requried for FilterControl (it uses our re-cached bindables in its asynd loac for the initial filter). + // initial value transfer is required for FilterControl (it uses our re-cached bindables in its async load for the initial filter). transferRulesetValue(); AddRangeInternal(new Drawable[] From 1109d201c3b41c5fb134b075965c064bc78f0d6d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 13:28:13 +0900 Subject: [PATCH 4040/5608] Add failing test --- .../Visual/SongSelect/TestScenePlaySongSelect.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 794d135b06..d45b1bdba2 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -242,6 +242,22 @@ namespace osu.Game.Tests.Visual.SongSelect void onRulesetChange(ValueChangedEvent e) => rulesetChangeIndex = actionIndex++; } + [Test] + public void TestModsRetainedBetweenSongSelect() + { + AddAssert("empty mods", () => !Mods.Value.Any()); + + createSongSelect(); + + addRulesetImportStep(0); + + changeMods(new OsuModHardRock()); + + createSongSelect(); + + AddAssert("mods retained", () => Mods.Value.Any()); + } + [Test] public void TestStartAfterUnMatchingFilterDoesNotStart() { From c15f909d8383ccae1a670a6b0e673cb576b4bfcf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 13:29:06 +0900 Subject: [PATCH 4041/5608] Remove local bindable at song select, along with misplaced reset logic --- osu.Game/Screens/Select/SongSelect.cs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 375b994169..00f2cc7e5b 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -30,7 +30,6 @@ using osuTK; using osuTK.Graphics; using osuTK.Input; using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Graphics.Sprites; @@ -86,10 +85,6 @@ namespace osu.Game.Screens.Select [Resolved(canBeNull: true)] private MusicController music { get; set; } - [Cached] - [Cached(Type = typeof(IBindable>))] - private readonly Bindable> mods = new Bindable>(Array.Empty()); // Bound to the game's mods, but is not reset on exiting - protected SongSelect() { AddRangeInternal(new Drawable[] @@ -222,7 +217,7 @@ namespace osu.Game.Screens.Select { if (Footer != null) { - Footer.AddButton(new FooterButtonMods { Current = mods }, ModSelect); + Footer.AddButton(new FooterButtonMods { Current = Mods }, ModSelect); Footer.AddButton(new FooterButtonRandom { Action = triggerRandom }); Footer.AddButton(new FooterButtonOptions(), BeatmapOptions); @@ -262,13 +257,6 @@ namespace osu.Game.Screens.Select } } - protected override void LoadComplete() - { - base.LoadComplete(); - - mods.BindTo(Mods); - } - private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -390,7 +378,7 @@ namespace osu.Game.Screens.Select { Logger.Log($"ruleset changed from \"{decoupledRuleset.Value}\" to \"{ruleset}\""); - mods.Value = Array.Empty(); + Mods.Value = Array.Empty(); decoupledRuleset.Value = ruleset; // force a filter before attempting to change the beatmap. @@ -538,9 +526,6 @@ namespace osu.Game.Screens.Select if (Beatmap.Value.Track != null) Beatmap.Value.Track.Looping = false; - mods.UnbindAll(); - Mods.Value = Array.Empty(); - return false; } From bf567e6df56fad7ef637a03b274cad2a1afa10fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 14:19:55 +0900 Subject: [PATCH 4042/5608] Make settings textboxes commit on focus lost --- osu.Game/Overlays/Settings/SettingsTextBox.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Settings/SettingsTextBox.cs b/osu.Game/Overlays/Settings/SettingsTextBox.cs index 0f257c2bfb..5e700a1d6b 100644 --- a/osu.Game/Overlays/Settings/SettingsTextBox.cs +++ b/osu.Game/Overlays/Settings/SettingsTextBox.cs @@ -12,6 +12,7 @@ namespace osu.Game.Overlays.Settings { Margin = new MarginPadding { Top = 5 }, RelativeSizeAxes = Axes.X, + CommitOnFocusLost = true, }; } } From 677717875e924aa1450954346ad04091489c2b0b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 14 Nov 2019 17:35:02 +0800 Subject: [PATCH 4043/5608] Change a case to EqualityComparer.Default to handle null properly. --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 8c92f57b68..12ae395cea 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -405,7 +405,7 @@ namespace osu.Game.Screens.Select // We may be arriving here due to another component changing the bindable Beatmap. // In these cases, the other component has already loaded the beatmap, so we don't need to do so again. - if (!beatmap.Equals(Beatmap.Value.BeatmapInfo)) + if (!EqualityComparer.Default.Equals(beatmap, Beatmap.Value.BeatmapInfo)) { Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\""); From 81033e1fdf4fccf8e5f5947d79c4660477ed3822 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 18:52:07 +0900 Subject: [PATCH 4044/5608] Add extra logging --- osu.Game/Beatmaps/BeatmapManager.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 6e485f642a..7a616ed8f2 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -129,9 +129,12 @@ namespace osu.Game.Beatmaps { var beatmapIds = beatmapSet.Beatmaps.Where(b => b.OnlineBeatmapID.HasValue).Select(b => b.OnlineBeatmapID).ToList(); + LogForModel(beatmapSet, "Validating online IDs..."); + // ensure all IDs are unique if (beatmapIds.GroupBy(b => b).Any(g => g.Count() > 1)) { + LogForModel(beatmapSet, "Found non-unique IDs, resetting..."); resetIds(); return; } @@ -144,8 +147,12 @@ namespace osu.Game.Beatmaps // reset the import ids (to force a re-fetch) *unless* they match the candidate CheckForExisting set. // we can ignore the case where the new ids are contained by the CheckForExisting set as it will either be used (import skipped) or deleted. var existing = CheckForExisting(beatmapSet); + if (existing == null || existingBeatmaps.Any(b => !existing.Beatmaps.Contains(b))) + { + LogForModel(beatmapSet, "Found existing import with IDs already, resetting..."); resetIds(); + } } void resetIds() => beatmapSet.Beatmaps.ForEach(b => b.OnlineBeatmapID = null); From 1bc0eae2a6fa08edf390f47a4f40cc80f71af3f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 18:53:22 +0900 Subject: [PATCH 4045/5608] Fix beatmap online retrieval response running incorrectly scheduled --- osu.Game/Beatmaps/BeatmapManager.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 7a616ed8f2..80d41c5267 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -387,22 +387,21 @@ namespace osu.Game.Beatmaps var req = new GetBeatmapRequest(beatmap); - req.Success += res => - { - LogForModel(set, $"Online retrieval mapped {beatmap} to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}."); - - beatmap.Status = res.Status; - beatmap.BeatmapSet.Status = res.BeatmapSet.Status; - beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID; - beatmap.OnlineBeatmapID = res.OnlineBeatmapID; - }; - req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); }; try { // intentionally blocking to limit web request concurrency req.Perform(api); + + var res = req.Result; + + beatmap.Status = res.Status; + beatmap.BeatmapSet.Status = res.BeatmapSet.Status; + beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID; + beatmap.OnlineBeatmapID = res.OnlineBeatmapID; + + LogForModel(set, $"Online retrieval mapped {beatmap} to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}."); } catch (Exception e) { From fbf81207d4a634bb4213d9794cdd72ed491c1ab5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 18:54:03 +0900 Subject: [PATCH 4046/5608] Don't assign server-fetched online id if it was assigned elsewhere --- osu.Game/Beatmaps/BeatmapManager.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 80d41c5267..7057bd46bb 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -399,7 +399,11 @@ namespace osu.Game.Beatmaps beatmap.Status = res.Status; beatmap.BeatmapSet.Status = res.BeatmapSet.Status; beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID; - beatmap.OnlineBeatmapID = res.OnlineBeatmapID; + + // note that this check only needs to be here if two identical hashed beatmaps exist int he same import. + // probably fine to leave it for safety. + if (set.Beatmaps.All(b => b.OnlineBeatmapID != res.OnlineBeatmapID)) + beatmap.OnlineBeatmapID = res.OnlineBeatmapID; LogForModel(set, $"Online retrieval mapped {beatmap} to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}."); } From 9f62ec869a6b8f6fed16e8cc6266df12e27e8e94 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 19:15:15 +0900 Subject: [PATCH 4047/5608] Add failing test --- .../Beatmaps/IO/ImportBeatmapTest.cs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 4e81954f50..4766411cbd 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -411,6 +411,48 @@ namespace osu.Game.Tests.Beatmaps.IO } } + [Test] + public async Task TestImportWithDuplicateHashes() + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportNestedStructure))) + { + try + { + var osu = loadOsu(host); + + var temp = TestResources.GetTestBeatmapForImport(); + + string extractedFolder = $"{temp}_extracted"; + Directory.CreateDirectory(extractedFolder); + + try + { + using (var zip = ZipArchive.Open(temp)) + zip.WriteToDirectory(extractedFolder); + + using (var zip = ZipArchive.Create()) + { + zip.AddAllFromDirectory(extractedFolder); + zip.AddEntry("duplicate.osu", Directory.GetFiles(extractedFolder, "*.osu").First()); + zip.SaveTo(temp, new ZipWriterOptions(CompressionType.Deflate)); + } + + await osu.Dependencies.Get().Import(temp); + + ensureLoaded(osu); + } + finally + { + Directory.Delete(extractedFolder, true); + } + } + finally + { + host.Exit(); + } + } + } + [Test] public async Task TestImportNestedStructure() { From 12243aaa9aa32933e1c6ca3ff3a82629212a0851 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 19:02:11 +0900 Subject: [PATCH 4048/5608] Dedupe .osu files with same hash in same set --- osu.Game/Beatmaps/BeatmapManager.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 6e485f642a..524e4c7bf2 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -296,8 +296,13 @@ namespace osu.Game.Beatmaps var decoder = Decoder.GetDecoder(sr); IBeatmap beatmap = decoder.Decode(sr); + string hash = ms.ComputeSHA2Hash(); + + if (beatmapInfos.Any(b => b.Hash == hash)) + continue; + beatmap.BeatmapInfo.Path = file.Filename; - beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash(); + beatmap.BeatmapInfo.Hash = hash; beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash(); var ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID); From 4e79bbad6b030f712242e3d2221c39e072e1be6a Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 14 Nov 2019 14:19:42 +0300 Subject: [PATCH 4049/5608] Add inline comment --- osu.Game/Audio/PreviewTrackManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 201671849a..56d507ef0e 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -80,6 +80,8 @@ namespace osu.Game.Audio return; current.Stop(); + // CurrentTrack must not change until the scheduled stopped event has been invoked. + // To ensure that this doesn't early-return on (CurrentTrack != track) check. } /// From d2ce0878bc5c99629ae29a9f6e833af21e869289 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 14 Nov 2019 14:20:29 +0300 Subject: [PATCH 4050/5608] Change 'current' accessibility to protected --- osu.Game/Audio/PreviewTrackManager.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 56d507ef0e..d85df42d2b 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -22,7 +22,7 @@ namespace osu.Game.Audio private AudioManager audio; private PreviewTrackStore trackStore; - private TrackManagerPreviewTrack current; + protected TrackManagerPreviewTrack CurrentTrack; [BackgroundDependencyLoader] private void load(AudioManager audio) @@ -48,17 +48,17 @@ namespace osu.Game.Audio track.Started += () => Schedule(() => { - current?.Stop(); - current = track; + CurrentTrack?.Stop(); + CurrentTrack = track; audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); }); track.Stopped += () => Schedule(() => { - if (current != track) + if (CurrentTrack != track) return; - current = null; + CurrentTrack = null; audio.Tracks.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); }); @@ -76,10 +76,10 @@ namespace osu.Game.Audio /// The which may be the owner of the . public void StopAnyPlaying(IPreviewTrackOwner source) { - if (current == null || current.Owner != source) + if (CurrentTrack == null || CurrentTrack.Owner != source) return; - current.Stop(); + CurrentTrack.Stop(); // CurrentTrack must not change until the scheduled stopped event has been invoked. // To ensure that this doesn't early-return on (CurrentTrack != track) check. } From 08e9813192f52d68cc0694f2c92e6661b0a9d742 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 14 Nov 2019 14:23:52 +0300 Subject: [PATCH 4051/5608] Add test ensuring correct changing behaviour --- .../TestScenePreviewTrackManager.cs | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 3a9fce90cd..0c5b485728 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual.Components { public class TestScenePreviewTrackManager : OsuTestScene, IPreviewTrackOwner { - private readonly PreviewTrackManager trackManager = new TestPreviewTrackManager(); + private readonly TestPreviewTrackManager trackManager = new TestPreviewTrackManager(); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { @@ -108,6 +108,26 @@ namespace osu.Game.Tests.Visual.Components AddAssert("track stopped", () => !track.IsRunning); } + /// + /// Ensures that changes correctly. + /// + [Test] + public void TestCurrentTrackChanges() + { + PreviewTrack track = null; + TestTrackOwner owner = null; + + AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack()))); + AddUntilStep("wait loaded", () => track.IsLoaded); + AddStep("start track", () => track.Start()); + AddAssert("current is track", () => trackManager.CurrentTrack == track); + AddStep("pause manager updates", () => trackManager.AllowUpdate = false); + AddStep("stop any playing", () => trackManager.StopAnyPlaying(owner)); + AddAssert("current not changed", () => trackManager.CurrentTrack == track); + AddStep("resume manager updates", () => trackManager.AllowUpdate = true); + AddAssert("current is null", () => trackManager.CurrentTrack == null); + } + private TestPreviewTrack getTrack() => (TestPreviewTrack)trackManager.Get(null); private TestPreviewTrack getOwnedTrack() @@ -144,8 +164,20 @@ namespace osu.Game.Tests.Visual.Components public class TestPreviewTrackManager : PreviewTrackManager { + public bool AllowUpdate = true; + + public new PreviewTrack CurrentTrack => base.CurrentTrack; + protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore); + public override bool UpdateSubTree() + { + if (!AllowUpdate) + return true; + + return base.UpdateSubTree(); + } + public class TestPreviewTrack : TrackManagerPreviewTrack { private readonly ITrackStore trackManager; From 0998afdbdb68eb3b5861b31a6370572e28d264e2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 14 Nov 2019 19:23:19 +0800 Subject: [PATCH 4052/5608] Use ReferenceEquals instead of SequenceEqual. --- osu.Game/Overlays/DirectOverlay.cs | 2 +- osu.Game/Overlays/SocialOverlay.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 494bfcb2cc..aedbd1b08b 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays get => beatmapSets; set { - if (beatmapSets?.SequenceEqual(value) ?? false) return; + if (ReferenceEquals(beatmapSets, value)) return; beatmapSets = value?.ToList(); diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 5987a5f138..da05cc7f9b 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays get => users; set { - if (users?.SequenceEqual(value) ?? false) + if (ReferenceEquals(users, value)) return; users = value?.ToList(); From 8ae869b788c70474726438935bfa78e59d65fd66 Mon Sep 17 00:00:00 2001 From: Gerard Dalmau Date: Thu, 14 Nov 2019 21:14:59 +0100 Subject: [PATCH 4053/5608] ADD version badge --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a078265d6c..65fb97eb5d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,10 @@ # osu! -[![Build status](https://ci.appveyor.com/api/projects/status/u2p01nx7l6og8buh?svg=true)](https://ci.appveyor.com/project/peppy/osu) [![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) +[![Build status](https://ci.appveyor.com/api/projects/status/u2p01nx7l6og8buh?svg=true)](https://ci.appveyor.com/project/peppy/osu) +[![GitHub release](https://img.shields.io/github/release/ppy/osu.svg)]() +[![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. From 8f02e57d1f799aadcbcfdc747e15a1be2a4e1f1a Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 15 Nov 2019 01:08:40 +0300 Subject: [PATCH 4054/5608] Add test ensuring correct muting behaviour --- .../TestScenePreviewTrackManager.cs | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 0c5b485728..5dac40104a 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Containers; using osu.Game.Audio; @@ -15,6 +16,8 @@ namespace osu.Game.Tests.Visual.Components { private readonly TestPreviewTrackManager trackManager = new TestPreviewTrackManager(); + private AudioManager audio; + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); @@ -24,8 +27,10 @@ namespace osu.Game.Tests.Visual.Components } [BackgroundDependencyLoader] - private void load() + private void load(AudioManager audio) { + this.audio = audio; + Add(trackManager); } @@ -128,6 +133,29 @@ namespace osu.Game.Tests.Visual.Components AddAssert("current is null", () => trackManager.CurrentTrack == null); } + /// + /// Ensures that mutes game-wide audio tracks correctly. + /// + [TestCase(false)] + [TestCase(true)] + public void TestEnsureMutingCorrectly(bool stopAnyPlaying) + { + PreviewTrack track = null; + TestTrackOwner owner = null; + + AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack()))); + AddUntilStep("wait loaded", () => track.IsLoaded); + AddStep("start track", () => track.Start()); + AddAssert("game is muted", () => audio.Tracks.AggregateVolume.Value == 0); + + if (stopAnyPlaying) + AddStep("stop any playing", () => trackManager.StopAnyPlaying(owner)); + else + AddStep("stop track", () => track.Stop()); + + AddAssert("game not muted", () => audio.Tracks.AggregateVolume.Value != 0); + } + private TestPreviewTrack getTrack() => (TestPreviewTrack)trackManager.Get(null); private TestPreviewTrack getOwnedTrack() From 956fb9912d71168e8c579d698150a49deeefa78e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 Nov 2019 08:23:56 +0900 Subject: [PATCH 4055/5608] Hook up multiplayer search filter --- .../Screens/Multi/Lounge/Components/RoomsContainer.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 99a6de0064..f5f43a52b1 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -24,6 +24,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly FillFlowContainer roomFlow; public IReadOnlyList Rooms => roomFlow; + [Resolved] + private Bindable filter { get; set; } + [Resolved] private Bindable currentRoom { get; set; } @@ -57,6 +60,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components addRooms(rooms); } + protected override void LoadComplete() + { + filter.BindValueChanged(f => Filter(f.NewValue), true); + } + private FilterCriteria currentFilter; public void Filter(FilterCriteria criteria) From 6d5484646297c146f5202cae667552416d5edac1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 10:18:47 +0900 Subject: [PATCH 4056/5608] Null online id on lookup failure --- osu.Game/Beatmaps/BeatmapManager.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 7057bd46bb..77fcf44a9b 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -387,7 +387,7 @@ namespace osu.Game.Beatmaps var req = new GetBeatmapRequest(beatmap); - req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); }; + req.Failure += fail; try { @@ -399,16 +399,18 @@ namespace osu.Game.Beatmaps beatmap.Status = res.Status; beatmap.BeatmapSet.Status = res.BeatmapSet.Status; beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID; - - // note that this check only needs to be here if two identical hashed beatmaps exist int he same import. - // probably fine to leave it for safety. - if (set.Beatmaps.All(b => b.OnlineBeatmapID != res.OnlineBeatmapID)) - beatmap.OnlineBeatmapID = res.OnlineBeatmapID; + beatmap.OnlineBeatmapID = res.OnlineBeatmapID; LogForModel(set, $"Online retrieval mapped {beatmap} to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}."); } catch (Exception e) { + fail(e); + } + + void fail(Exception e) + { + beatmap.OnlineBeatmapID = null; LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); } } From f0b7b2e1c42d9a1fa5e0b257f5eac057922173c6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 Nov 2019 11:07:16 +0900 Subject: [PATCH 4057/5608] Fix broken test case --- osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index f5f43a52b1..4e9f645732 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly FillFlowContainer roomFlow; public IReadOnlyList Rooms => roomFlow; - [Resolved] + [Resolved(CanBeNull = true)] private Bindable filter { get; set; } [Resolved] @@ -62,7 +62,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components protected override void LoadComplete() { - filter.BindValueChanged(f => Filter(f.NewValue), true); + filter?.BindValueChanged(f => Filter(f.NewValue), true); } private FilterCriteria currentFilter; From 22c3be2c6f2ea039d11007778113464adc8884ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 11:18:19 +0900 Subject: [PATCH 4058/5608] Clear count variables on carousel creation --- osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 14077c8e53..7ec76cdd2f 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -452,6 +452,9 @@ namespace osu.Game.Tests.Visual.SongSelect { AddStep("Create carousel", () => { + selectedSets.Clear(); + eagerSelectedIDs.Clear(); + (target ?? this).Child = carousel = new TestBeatmapCarousel { RelativeSizeAxes = Axes.Both, From e81dfcad4c62faf6844c1d20340c4026ed53b6f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 11:46:32 +0900 Subject: [PATCH 4059/5608] Fix remaining cases of pollution --- .../SongSelect/TestSceneBeatmapCarousel.cs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 7ec76cdd2f..132b104afb 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -334,10 +334,19 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestHiding() { - BeatmapSetInfo hidingSet = createTestBeatmapSet(1); - hidingSet.Beatmaps[1].Hidden = true; + BeatmapSetInfo hidingSet = null; + List hiddenList = new List(); - loadBeatmaps(new List { hidingSet }); + AddStep("create hidden set", () => + { + hidingSet = createTestBeatmapSet(1); + hidingSet.Beatmaps[1].Hidden = true; + + hiddenList.Clear(); + hiddenList.Add(hidingSet); + }); + + loadBeatmaps(hiddenList); setSelected(1, 1); @@ -371,11 +380,14 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestSelectingFilteredRuleset() { + BeatmapSetInfo testMixed = null; + createCarousel(); - var testMixed = createTestBeatmapSet(set_count + 1); AddStep("add mixed ruleset beatmapset", () => { + testMixed = createTestBeatmapSet(set_count + 1); + for (int i = 0; i <= 2; i++) { testMixed.Beatmaps[i].Ruleset = rulesets.AvailableRulesets.ElementAt(i); From 15e85234e4d4b80df421bb1c9d8383b35c5aab10 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Nov 2019 11:12:51 +0800 Subject: [PATCH 4060/5608] remove unecessary step --- .../Visual/UserInterface/TestSceneModCustomizationSettings.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs index ec5b3c1e16..83d77cccdb 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs @@ -34,7 +34,6 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("select mod", () => modSelect.SelectMod(testMod)); AddAssert("button enabled", () => modSelect.CustomizeButton.Enabled.Value); AddStep("open customization", () => modSelect.CustomizeButton.Click()); - AddAssert("controls exist", () => modSelect.GetControlSection(testMod) != null); AddStep("deselect mod", () => modSelect.SelectMod(testMod)); AddAssert("controls hidden", () => modSelect.ModSettingsContainer.Alpha == 0); } From 6d06b444bae4f8ccfbb7b00cd0ee16390e47d458 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 13:47:14 +0900 Subject: [PATCH 4061/5608] Allow screen to specify whether to apply audio rate adjustments from mods --- osu.Game/OsuGame.cs | 2 ++ osu.Game/Overlays/MusicController.cs | 27 ++++++++++++++++++++++++--- osu.Game/Screens/IOsuScreen.cs | 5 +++++ osu.Game/Screens/Menu/MainMenu.cs | 2 ++ osu.Game/Screens/OsuScreen.cs | 2 ++ osu.Game/Screens/StartupScreen.cs | 2 ++ 6 files changed, 37 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 328c964976..20e343ac0a 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -925,6 +925,8 @@ namespace osu.Game { OverlayActivationMode.Value = newOsuScreen.InitialOverlayActivationMode; + musicController.AllowRateAdjustments = newOsuScreen.AllowRateAdjustments; + if (newOsuScreen.HideOverlaysOnEnter) CloseAllOverlays(); else diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 9ec0364420..0db05ae6f7 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays private OnScreenDisplay onScreenDisplay { get; set; } [BackgroundDependencyLoader] - private void load() + private void load(OsuGame game) { beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next())); beatmaps.ItemAdded += handleBeatmapAdded; @@ -233,6 +233,24 @@ namespace osu.Game.Overlays queuedDirection = null; } + private bool allowRateAdjustments; + + /// + /// Whether mod rate adjustments are allowed to be applied. + /// + public bool AllowRateAdjustments + { + get => allowRateAdjustments; + set + { + if (allowRateAdjustments == value) + return; + + allowRateAdjustments = value; + ResetTrackAdjustments(); + } + } + public void ResetTrackAdjustments() { var track = current?.Track; @@ -241,8 +259,11 @@ namespace osu.Game.Overlays track.ResetSpeedAdjustments(); - foreach (var mod in mods.Value.OfType()) - mod.ApplyToClock(track); + if (allowRateAdjustments) + { + foreach (var mod in mods.Value.OfType()) + mod.ApplyToClock(track); + } } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index 9fc907c2a4..22fe0ad816 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -51,5 +51,10 @@ namespace osu.Game.Screens Bindable Beatmap { get; } Bindable Ruleset { get; } + + /// + /// Whether mod rate adjustments are allowed to be applied. + /// + bool AllowRateAdjustments { get; } } } diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index c195ed6cb6..08338845e6 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -37,6 +37,8 @@ namespace osu.Game.Screens.Menu public override bool AllowExternalScreenChange => true; + public override bool AllowRateAdjustments => false; + private Screen songSelect; private MenuSideFlashes sideFlashes; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 328631ff9c..94165fe4b7 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -91,6 +91,8 @@ namespace osu.Game.Screens public Bindable Ruleset { get; private set; } + public virtual bool AllowRateAdjustments => true; + public Bindable> Mods { get; private set; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) diff --git a/osu.Game/Screens/StartupScreen.cs b/osu.Game/Screens/StartupScreen.cs index 797f185a37..c3e36c8e9d 100644 --- a/osu.Game/Screens/StartupScreen.cs +++ b/osu.Game/Screens/StartupScreen.cs @@ -16,6 +16,8 @@ namespace osu.Game.Screens public override bool CursorVisible => false; + public override bool AllowRateAdjustments => false; + public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; } } From 2c3109980ab69e08eb0a25b1e86a57b5df5dcdb2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 13:51:39 +0900 Subject: [PATCH 4062/5608] Fix broken merge --- osu.Game/Screens/Select/SongSelect.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 862f8f9aa8..e3cd98454a 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -30,6 +30,7 @@ using osuTK; using osuTK.Graphics; using osuTK.Input; using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Graphics.Sprites; From c7d0b88854a66cfacab8ac91c2e885088a606ca3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 14:15:09 +0900 Subject: [PATCH 4063/5608] Update test scene --- .../Visual/Gameplay/{TestCaseLeadIn.cs => TestSceneLeadIn.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Tests/Visual/Gameplay/{TestCaseLeadIn.cs => TestSceneLeadIn.cs} (97%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs similarity index 97% rename from osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs index 41cd80ed8c..3522c2265a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { - public class TestCaseLeadIn : RateAdjustedBeatmapTestScene + public class TestSceneLeadIn : RateAdjustedBeatmapTestScene { private Ruleset ruleset; From dbfec215e7acdf716f4c11c42f3ab8bd6c7711d6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 14:47:28 +0900 Subject: [PATCH 4064/5608] Improve test quality --- .../Visual/Gameplay/TestSceneLeadIn.cs | 50 ++++++++----------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs index 3522c2265a..addf7c3b28 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs @@ -1,61 +1,55 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps; -using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { public class TestSceneLeadIn : RateAdjustedBeatmapTestScene { - private Ruleset ruleset; - private LeadInPlayer player; - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) - { - Add(new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Depth = int.MaxValue - }); - - ruleset = rulesets.AvailableRulesets.First().CreateInstance(); - } - [Test] public void TestShortLeadIn() { - AddStep("create player", () => loadPlayerWithBeatmap(new TestBeatmap(ruleset.RulesetInfo) { BeatmapInfo = { AudioLeadIn = 1000 } })); - AddUntilStep("correct lead-in", () => player.FirstFrameClockTime == 0); + loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo) + { + BeatmapInfo = { AudioLeadIn = 1000 } + }); + + AddUntilStep("player loaded", () => player.IsLoaded && player.Alpha == 1); + + AddAssert("correct lead-in", () => player.FirstFrameClockTime == 0); } [Test] public void TestLongLeadIn() { - AddStep("create player", () => loadPlayerWithBeatmap(new TestBeatmap(ruleset.RulesetInfo) { BeatmapInfo = { AudioLeadIn = 10000 } })); - AddUntilStep("correct lead-in", () => player.FirstFrameClockTime == player.GameplayStartTime - 10000); + loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo) + { + BeatmapInfo = { AudioLeadIn = 10000 } + }); + + AddAssert("correct lead-in", () => player.FirstFrameClockTime == player.GameplayStartTime - 10000); } private void loadPlayerWithBeatmap(IBeatmap beatmap) { - Beatmap.Value = new TestWorkingBeatmap(beatmap); + AddStep("create player", () => + { + Beatmap.Value = CreateWorkingBeatmap(beatmap); + LoadScreen(player = new LeadInPlayer()); + }); - LoadScreen(player = new LeadInPlayer()); + AddUntilStep("player loaded", () => player.IsLoaded && player.Alpha == 1); } - private class LeadInPlayer : Player + private class LeadInPlayer : TestPlayer { public LeadInPlayer() : base(false, false) From 813aebca1df0a46c4008b6cadcf5d536764cf086 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 14:51:01 +0900 Subject: [PATCH 4065/5608] Remove unintentional dependency --- osu.Game/Overlays/MusicController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 0db05ae6f7..5e0a67c2f7 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays private OnScreenDisplay onScreenDisplay { get; set; } [BackgroundDependencyLoader] - private void load(OsuGame game) + private void load() { beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next())); beatmaps.ItemAdded += handleBeatmapAdded; From 1b4bcb81c895da963e7fbc655493864abbc3b96b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 Nov 2019 17:49:02 +0900 Subject: [PATCH 4066/5608] Fix filtering breaking on secondary filters --- .../Screens/Multi/Lounge/Components/DrawableRoom.cs | 10 ++++++++-- .../Screens/Multi/Lounge/Components/RoomsContainer.cs | 8 ++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index 6ec8f2bfe5..f6cbe300f3 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -74,7 +74,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components set { matchingFilter = value; - this.FadeTo(MatchingFilter ? 1 : 0, 200); + + if (IsLoaded) + this.FadeTo(MatchingFilter ? 1 : 0, 200); } } @@ -203,7 +205,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components protected override void LoadComplete() { base.LoadComplete(); - this.FadeInFromZero(transition_duration); + + if (matchingFilter) + this.FadeInFromZero(transition_duration); + else + Alpha = 0; } private class RoomName : OsuSpriteText diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 4e9f645732..77f4632bf1 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -65,8 +65,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components filter?.BindValueChanged(f => Filter(f.NewValue), true); } - private FilterCriteria currentFilter; - public void Filter(FilterCriteria criteria) { roomFlow.Children.ForEach(r => @@ -82,15 +80,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components { default: case SecondaryFilter.Public: - r.MatchingFilter = r.Room.Availability.Value == RoomAvailability.Public; + matchingFilter &= r.Room.Availability.Value == RoomAvailability.Public; break; } r.MatchingFilter = matchingFilter; } }); - - currentFilter = criteria; } private void addRooms(IEnumerable rooms) @@ -98,7 +94,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components foreach (var r in rooms) roomFlow.Add(new DrawableRoom(r) { Action = () => selectRoom(r) }); - Filter(currentFilter); + filter?.TriggerChange(); } private void removeRooms(IEnumerable rooms) From 1218d41b50ee6d1e52552c533c110448b312e63d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 15 Nov 2019 11:52:49 +0300 Subject: [PATCH 4067/5608] Make Ruleset a property --- .../BeatmapSet/LeaderboardModSelector.cs | 49 +++++++++++-------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index b400141abf..660d957e1a 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -21,7 +21,34 @@ namespace osu.Game.Overlays.BeatmapSet public class LeaderboardModSelector : CompositeDrawable { public readonly BindableList SelectedMods = new BindableList(); - public readonly Bindable Ruleset = new Bindable(); + + private RulesetInfo ruleset; + + public RulesetInfo Ruleset + { + get => ruleset; + set + { + if (ruleset == value) + { + DeselectAll(); + return; + } + + ruleset = value; + + SelectedMods.Clear(); + modsContainer.Clear(); + + if (ruleset == null) + return; + + modsContainer.Add(new ModButton(new NoMod())); + modsContainer.AddRange(ruleset.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); + + modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); + } + } private readonly FillFlowContainer modsContainer; @@ -38,26 +65,6 @@ namespace osu.Game.Overlays.BeatmapSet }; } - protected override void LoadComplete() - { - base.LoadComplete(); - Ruleset.BindValueChanged(onRulesetChanged, true); - } - - private void onRulesetChanged(ValueChangedEvent ruleset) - { - SelectedMods.Clear(); - modsContainer.Clear(); - - if (ruleset.NewValue == null) - return; - - modsContainer.Add(new ModButton(new NoMod())); - modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); - - modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); - } - private void selectionChanged(Mod mod, bool selected) { if (selected) From 2592a0489b05fb4a7d5dfe112adc1802e5c27694 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 15 Nov 2019 11:57:40 +0300 Subject: [PATCH 4068/5608] Use existing ModNoMod --- .../Online/TestSceneLeaderboardModSelector.cs | 12 +++++------- .../BeatmapSet/LeaderboardModSelector.cs | 16 +--------------- osu.Game/Rulesets/Mods/ModNoMod.cs | 4 ++++ 3 files changed, 10 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index 799528220b..94540eeb5b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -28,7 +28,6 @@ namespace osu.Game.Tests.Visual.Online { LeaderboardModSelector modSelector; FillFlowContainer selectedMods; - Bindable ruleset = new Bindable(); Add(selectedMods = new FillFlowContainer { @@ -40,7 +39,6 @@ namespace osu.Game.Tests.Visual.Online { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Ruleset = { BindTarget = ruleset } }); modSelector.SelectedMods.ItemsAdded += mods => @@ -66,12 +64,12 @@ namespace osu.Game.Tests.Visual.Online }); }; - AddStep("osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo); - AddStep("mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo); - AddStep("taiko ruleset", () => ruleset.Value = new TaikoRuleset().RulesetInfo); - AddStep("catch ruleset", () => ruleset.Value = new CatchRuleset().RulesetInfo); + AddStep("osu ruleset", () => modSelector.Ruleset = new OsuRuleset().RulesetInfo); + AddStep("mania ruleset", () => modSelector.Ruleset = new ManiaRuleset().RulesetInfo); + AddStep("taiko ruleset", () => modSelector.Ruleset = new TaikoRuleset().RulesetInfo); + AddStep("catch ruleset", () => modSelector.Ruleset = new CatchRuleset().RulesetInfo); AddStep("Deselect all", () => modSelector.DeselectAll()); - AddStep("null ruleset", () => ruleset.Value = null); + AddStep("null ruleset", () => modSelector.Ruleset = null); } } } diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 660d957e1a..c96840c959 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -14,7 +14,6 @@ using osuTK.Graphics; using System; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet { @@ -43,7 +42,7 @@ namespace osu.Game.Overlays.BeatmapSet if (ruleset == null) return; - modsContainer.Add(new ModButton(new NoMod())); + modsContainer.Add(new ModButton(new ModNoMod())); modsContainer.AddRange(ruleset.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); @@ -146,18 +145,5 @@ namespace osu.Game.Overlays.BeatmapSet protected override void OnHighlightedChanged(ValueChangedEvent highlighted) => this.FadeColour(highlighted.NewValue ? Color4.White : Color4.Gray, duration, Easing.OutQuint); } - - private class NoMod : Mod - { - public override string Name => "NoMod"; - - public override string Acronym => "NM"; - - public override double ScoreMultiplier => 1; - - public override IconUsage Icon => FontAwesome.Solid.Ban; - - public override ModType Type => ModType.System; - } } } diff --git a/osu.Game/Rulesets/Mods/ModNoMod.cs b/osu.Game/Rulesets/Mods/ModNoMod.cs index 0ddbd2a8cb..487985b2b3 100644 --- a/osu.Game/Rulesets/Mods/ModNoMod.cs +++ b/osu.Game/Rulesets/Mods/ModNoMod.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics.Sprites; + namespace osu.Game.Rulesets.Mods { /// @@ -11,5 +13,7 @@ namespace osu.Game.Rulesets.Mods public override string Name => "No Mod"; public override string Acronym => "NM"; public override double ScoreMultiplier => 1; + public override IconUsage Icon => FontAwesome.Solid.Ban; + public override ModType Type => ModType.System; } } From 10287eb66dfe31fb02a864e3343ce7373d2914bf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 Nov 2019 17:58:47 +0900 Subject: [PATCH 4069/5608] Add debounce logic in several places --- .../Multi/Lounge/Components/RoomsContainer.cs | 17 ++++++++++++++++- osu.Game/Screens/Multi/RoomManager.cs | 11 ++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 77f4632bf1..3dde9452e4 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -9,6 +9,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Threading; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osuTK; @@ -62,7 +63,10 @@ namespace osu.Game.Screens.Multi.Lounge.Components protected override void LoadComplete() { - filter?.BindValueChanged(f => Filter(f.NewValue), true); + filter?.BindValueChanged(f => scheduleFilter()); + + if (filter != null) + Filter(filter.Value); } public void Filter(FilterCriteria criteria) @@ -89,6 +93,17 @@ namespace osu.Game.Screens.Multi.Lounge.Components }); } + private ScheduledDelegate scheduledFilter; + + private void scheduleFilter() + { + if (filter == null) + return; + + scheduledFilter?.Cancel(); + scheduledFilter = Scheduler.AddDelayed(() => Filter(filter.Value), 200); + } + private void addRooms(IEnumerable rooms) { foreach (var r in rooms) diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index cdaba85b9e..d6d3ec37ef 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Logging; +using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Online; using osu.Game.Online.API; @@ -44,7 +45,7 @@ namespace osu.Game.Screens.Multi currentFilter.BindValueChanged(_ => { if (IsLoaded) - PollImmediately(); + schedulePoll(); }); } @@ -157,6 +158,14 @@ namespace osu.Game.Screens.Multi return tcs.Task; } + private ScheduledDelegate scheduledPoll; + + private void schedulePoll() + { + scheduledPoll?.Cancel(); + scheduledPoll = Scheduler.AddDelayed(PollImmediately, 200); + } + /// /// Updates a local with a remote copy. /// From 18f77008dbcafb9c69d1b09a25bf31fdb95c67b0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 15 Nov 2019 12:04:01 +0300 Subject: [PATCH 4070/5608] Update dependency --- .../Online/TestSceneLeaderboardModSelector.cs | 14 ++--- .../BeatmapSet/LeaderboardModSelector.cs | 63 +++++++++---------- .../BeatmapSet/Scores/ScoresContainer.cs | 13 +--- osu.Game/Rulesets/Mods/ModNoMod.cs | 4 ++ 4 files changed, 39 insertions(+), 55 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index 799528220b..c0c18c2583 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -11,8 +11,6 @@ using osu.Game.Rulesets.Taiko; using osu.Game.Rulesets.Catch; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Bindables; -using osu.Game.Rulesets; using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Tests.Visual.Online @@ -28,7 +26,6 @@ namespace osu.Game.Tests.Visual.Online { LeaderboardModSelector modSelector; FillFlowContainer selectedMods; - Bindable ruleset = new Bindable(); Add(selectedMods = new FillFlowContainer { @@ -40,7 +37,6 @@ namespace osu.Game.Tests.Visual.Online { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Ruleset = { BindTarget = ruleset } }); modSelector.SelectedMods.ItemsAdded += mods => @@ -66,12 +62,12 @@ namespace osu.Game.Tests.Visual.Online }); }; - AddStep("osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo); - AddStep("mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo); - AddStep("taiko ruleset", () => ruleset.Value = new TaikoRuleset().RulesetInfo); - AddStep("catch ruleset", () => ruleset.Value = new CatchRuleset().RulesetInfo); + AddStep("osu ruleset", () => modSelector.Ruleset = new OsuRuleset().RulesetInfo); + AddStep("mania ruleset", () => modSelector.Ruleset = new ManiaRuleset().RulesetInfo); + AddStep("taiko ruleset", () => modSelector.Ruleset = new TaikoRuleset().RulesetInfo); + AddStep("catch ruleset", () => modSelector.Ruleset = new CatchRuleset().RulesetInfo); AddStep("Deselect all", () => modSelector.DeselectAll()); - AddStep("null ruleset", () => ruleset.Value = null); + AddStep("null ruleset", () => modSelector.Ruleset = null); } } } diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index b400141abf..c96840c959 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -14,14 +14,40 @@ using osuTK.Graphics; using System; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet { public class LeaderboardModSelector : CompositeDrawable { public readonly BindableList SelectedMods = new BindableList(); - public readonly Bindable Ruleset = new Bindable(); + + private RulesetInfo ruleset; + + public RulesetInfo Ruleset + { + get => ruleset; + set + { + if (ruleset == value) + { + DeselectAll(); + return; + } + + ruleset = value; + + SelectedMods.Clear(); + modsContainer.Clear(); + + if (ruleset == null) + return; + + modsContainer.Add(new ModButton(new ModNoMod())); + modsContainer.AddRange(ruleset.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); + + modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); + } + } private readonly FillFlowContainer modsContainer; @@ -38,26 +64,6 @@ namespace osu.Game.Overlays.BeatmapSet }; } - protected override void LoadComplete() - { - base.LoadComplete(); - Ruleset.BindValueChanged(onRulesetChanged, true); - } - - private void onRulesetChanged(ValueChangedEvent ruleset) - { - SelectedMods.Clear(); - modsContainer.Clear(); - - if (ruleset.NewValue == null) - return; - - modsContainer.Add(new ModButton(new NoMod())); - modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); - - modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); - } - private void selectionChanged(Mod mod, bool selected) { if (selected) @@ -139,18 +145,5 @@ namespace osu.Game.Overlays.BeatmapSet protected override void OnHighlightedChanged(ValueChangedEvent highlighted) => this.FadeColour(highlighted.NewValue ? Color4.White : Color4.Gray, duration, Easing.OutQuint); } - - private class NoMod : Mod - { - public override string Name => "NoMod"; - - public override string Acronym => "NM"; - - public override double ScoreMultiplier => 1; - - public override IconUsage Icon => FontAwesome.Solid.Ban; - - public override ModType Type => ModType.System; - } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 3e3f823368..bdcf536e39 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -107,10 +107,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Current = { BindTarget = scope } }, - modSelector = new LeaderboardModSelector - { - Ruleset = { BindTarget = ruleset } - } + modSelector = new LeaderboardModSelector() } }, new Container @@ -190,13 +187,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void onBeatmapChanged(ValueChangedEvent beatmap) { - var beatmapRuleset = beatmap.NewValue?.Ruleset; - - if (ruleset.Value?.Equals(beatmapRuleset) ?? false) - modSelector.DeselectAll(); - else - ruleset.Value = beatmapRuleset; - + ruleset.Value = modSelector.Ruleset = beatmap.NewValue?.Ruleset; scope.Value = BeatmapLeaderboardScope.Global; } diff --git a/osu.Game/Rulesets/Mods/ModNoMod.cs b/osu.Game/Rulesets/Mods/ModNoMod.cs index 0ddbd2a8cb..487985b2b3 100644 --- a/osu.Game/Rulesets/Mods/ModNoMod.cs +++ b/osu.Game/Rulesets/Mods/ModNoMod.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics.Sprites; + namespace osu.Game.Rulesets.Mods { /// @@ -11,5 +13,7 @@ namespace osu.Game.Rulesets.Mods public override string Name => "No Mod"; public override string Acronym => "NM"; public override double ScoreMultiplier => 1; + public override IconUsage Icon => FontAwesome.Solid.Ban; + public override ModType Type => ModType.System; } } From e51fd00d588cd2b7488995b15f15b5533a8d759d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 15 Nov 2019 12:09:31 +0300 Subject: [PATCH 4071/5608] CI fix --- osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs | 2 -- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index 94540eeb5b..c0c18c2583 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -11,8 +11,6 @@ using osu.Game.Rulesets.Taiko; using osu.Game.Rulesets.Catch; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Bindables; -using osu.Game.Rulesets; using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Tests.Visual.Online diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index c96840c959..e62a754e92 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.BeatmapSet get => ruleset; set { - if (ruleset == value) + if (ruleset?.Equals(value) ?? false) { DeselectAll(); return; From f2862e95e0be0544027118cbf47cac3f00b99fa9 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 15 Nov 2019 12:15:51 +0300 Subject: [PATCH 4072/5608] CI fix --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index c96840c959..e62a754e92 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.BeatmapSet get => ruleset; set { - if (ruleset == value) + if (ruleset?.Equals(value) ?? false) { DeselectAll(); return; From e9e37fc821b1ce075d3cc2fba3ff92f5a260f8cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 18:23:35 +0900 Subject: [PATCH 4073/5608] Add private setter for FilterControl --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 974120e658..089510513b 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Select protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; - public FilterControl FilterControl; + public FilterControl FilterControl { get; private set; } protected virtual bool ShowFooter => true; From 509440ea14bf0f6e9540953d1f8dbcb77328f420 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 16 Nov 2019 18:02:34 +0300 Subject: [PATCH 4074/5608] TotalCommentsCounter implementation --- .../Online/TestSceneTotalCommentsCounter.cs | 36 +++++++++ .../Overlays/Comments/TotalCommentsCounter.cs | 80 +++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs create mode 100644 osu.Game/Overlays/Comments/TotalCommentsCounter.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs new file mode 100644 index 0000000000..4702d24125 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs @@ -0,0 +1,36 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Bindables; +using osu.Game.Overlays.Comments; +using osu.Framework.MathUtils; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneTotalCommentsCounter : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(TotalCommentsCounter), + }; + + public TestSceneTotalCommentsCounter() + { + var count = new BindableInt(); + + Add(new TotalCommentsCounter + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = count } + }); + + AddStep(@"Set 100", () => count.Value = 100); + AddStep(@"Set 0", () => count.Value = 0); + AddStep(@"Set random", () => count.Value = RNG.Next(0, int.MaxValue)); + } + } +} diff --git a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs new file mode 100644 index 0000000000..c71ca762e1 --- /dev/null +++ b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs @@ -0,0 +1,80 @@ +// 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.Containers; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Framework.Graphics.Sprites; +using osuTK; +using osu.Framework.Allocation; +using osu.Framework.Bindables; + +namespace osu.Game.Overlays.Comments +{ + public class TotalCommentsCounter : CompositeDrawable + { + public readonly BindableInt Current = new BindableInt(); + + private readonly SpriteText counter; + + public TotalCommentsCounter() + { + RelativeSizeAxes = Axes.X; + Height = 50; + AddInternal(new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding { Left = 50 }, + Spacing = new Vector2(5, 0), + Children = new Drawable[] + { + new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: 20, italics: true), + Text = @"Comments" + }, + new CircularContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Masking = true, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.05f) + }, + counter = new SpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) + } + }, + } + } + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + counter.Colour = colours.BlueLighter; + } + + protected override void LoadComplete() + { + Current.BindValueChanged(value => counter.Text = value.NewValue.ToString("N0"), true); + base.LoadComplete(); + } + } +} From 5727963f8642989bf87b915f48fe00053efd19d6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Nov 2019 20:43:34 +0800 Subject: [PATCH 4075/5608] Turn on xmldoc warning, and use appendive syntax for NoWarn. --- Directory.Build.props | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 9735c78913..838851b712 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -18,10 +18,14 @@ + + true + $(NoWarn);CS1591 + - NU1701 + $(NoWarn);NU1701 ppy Pty Ltd From f05b83d7d450c458077cafeaf012a8cb57283b00 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Nov 2019 20:48:23 +0800 Subject: [PATCH 4076/5608] Use typeparamref. --- osu.Game/Beatmaps/Formats/Decoder.cs | 2 +- osu.Game/Database/ArchiveModelManager.cs | 12 ++++++------ .../DownloadableArchiveModelManager.cs | 12 ++++++------ osu.Game/Database/IModelDownloader.cs | 18 +++++++++--------- osu.Game/Database/IModelManager.cs | 2 +- .../Database/MutableDatabaseBackedStore.cs | 8 ++++---- .../Graphics/UserInterface/OsuTabControl.cs | 2 +- .../Bindings/DatabasedKeyBindingContainer.cs | 2 +- osu.Game/Online/DownloadTrackingComposite.cs | 4 ++-- osu.Game/Rulesets/UI/DrawableRuleset.cs | 4 ++-- 10 files changed, 33 insertions(+), 33 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs index 40c329eb7e..45122f6312 100644 --- a/osu.Game/Beatmaps/Formats/Decoder.cs +++ b/osu.Game/Beatmaps/Formats/Decoder.cs @@ -93,7 +93,7 @@ namespace osu.Game.Beatmaps.Formats /// /// Registers a fallback decoder instantiation function. /// The fallback will be returned if the first non-empty line of the decoded stream does not match any known magic. - /// Calling this method will overwrite any existing global fallback registration for type - use with caution. + /// Calling this method will overwrite any existing global fallback registration for type - use with caution. /// /// Type of object being decoded. /// A function that constructs the fallback. diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 8fa4eaf267..7cce2fb92f 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -54,13 +54,13 @@ namespace osu.Game.Database public Action PostNotification { protected get; set; } /// - /// Fired when a new becomes available in the database. + /// Fired when a new becomes available in the database. /// This is not guaranteed to run on the update thread. /// public event Action ItemAdded; /// - /// Fired when a is removed from the database. + /// Fired when a is removed from the database. /// This is not guaranteed to run on the update thread. /// public event Action ItemRemoved; @@ -95,7 +95,7 @@ namespace osu.Game.Database } /// - /// Import one or more items from filesystem . + /// Import one or more items from filesystem . /// This will post notifications tracking progress. /// /// One or more archive locations on disk. @@ -173,7 +173,7 @@ namespace osu.Game.Database } /// - /// Import one from the filesystem and delete the file on success. + /// Import one from the filesystem and delete the file on success. /// /// The archive location on disk. /// An optional cancellation token. @@ -275,7 +275,7 @@ namespace osu.Game.Database } /// - /// Import an item from a . + /// Import an item from a . /// /// The model to be imported. /// An optional archive to use for model population. @@ -589,7 +589,7 @@ namespace osu.Game.Database protected TModel CheckForExisting(TModel model) => model.Hash == null ? null : ModelStore.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash); /// - /// After an existing is found during an import process, the default behaviour is to restore the existing + /// After an existing is found during an import process, the default behaviour is to restore the existing /// item and skip the import. This method allows changing that behaviour. /// /// The existing model. diff --git a/osu.Game/Database/DownloadableArchiveModelManager.cs b/osu.Game/Database/DownloadableArchiveModelManager.cs index a81dff3475..0b7d63f469 100644 --- a/osu.Game/Database/DownloadableArchiveModelManager.cs +++ b/osu.Game/Database/DownloadableArchiveModelManager.cs @@ -41,17 +41,17 @@ namespace osu.Game.Database } /// - /// Creates the download request for this . + /// Creates the download request for this . /// - /// The to be downloaded. + /// The to be downloaded. /// Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle. /// The request object. protected abstract ArchiveDownloadRequest CreateDownloadRequest(TModel model, bool minimiseDownloadSize); /// - /// Begin a download for the requested . + /// Begin a download for the requested . /// - /// The to be downloaded. + /// The to be downloaded. /// Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle. /// Whether the download was started. public bool Download(TModel model, bool minimiseDownloadSize = false) @@ -131,9 +131,9 @@ namespace osu.Game.Database /// /// Performs implementation specific comparisons to determine whether a given model is present in the local store. /// - /// The whose existence needs to be checked. + /// The whose existence needs to be checked. /// The usable items present in the store. - /// Whether the exists. + /// Whether the exists. protected abstract bool CheckLocalAvailability(TModel model, IQueryable items); public ArchiveDownloadRequest GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Model.Equals(model)); diff --git a/osu.Game/Database/IModelDownloader.cs b/osu.Game/Database/IModelDownloader.cs index f6f4b0aa42..17f1ccab06 100644 --- a/osu.Game/Database/IModelDownloader.cs +++ b/osu.Game/Database/IModelDownloader.cs @@ -14,34 +14,34 @@ namespace osu.Game.Database where TModel : class { /// - /// Fired when a download begins. + /// Fired when a download begins. /// event Action> DownloadBegan; /// - /// Fired when a download is interrupted, either due to user cancellation or failure. + /// Fired when a download is interrupted, either due to user cancellation or failure. /// event Action> DownloadFailed; /// - /// Checks whether a given is already available in the local store. + /// Checks whether a given is already available in the local store. /// - /// The whose existence needs to be checked. - /// Whether the exists. + /// The whose existence needs to be checked. + /// Whether the exists. bool IsAvailableLocally(TModel model); /// - /// Begin a download for the requested . + /// Begin a download for the requested . /// - /// The to be downloaded. + /// The to be downloaded. /// Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle.. /// Whether the download was started. bool Download(TModel model, bool minimiseDownloadSize); /// - /// Gets an existing download request if it exists. + /// Gets an existing download request if it exists. /// - /// The whose request is wanted. + /// The whose request is wanted. /// The object if it exists, otherwise null. ArchiveDownloadRequest GetExistingDownload(TModel model); } diff --git a/osu.Game/Database/IModelManager.cs b/osu.Game/Database/IModelManager.cs index 884814cb38..1bdbbb48e6 100644 --- a/osu.Game/Database/IModelManager.cs +++ b/osu.Game/Database/IModelManager.cs @@ -6,7 +6,7 @@ using System; namespace osu.Game.Database { /// - /// Represents a model manager that publishes events when s are added or removed. + /// Represents a model manager that publishes events when s are added or removed. /// /// The model type. public interface IModelManager diff --git a/osu.Game/Database/MutableDatabaseBackedStore.cs b/osu.Game/Database/MutableDatabaseBackedStore.cs index 39a48b5be6..4ca1eef989 100644 --- a/osu.Game/Database/MutableDatabaseBackedStore.cs +++ b/osu.Game/Database/MutableDatabaseBackedStore.cs @@ -30,7 +30,7 @@ namespace osu.Game.Database public IQueryable ConsumableItems => AddIncludesForConsumption(ContextFactory.Get().Set()); /// - /// Add a to the database. + /// Add a to the database. /// /// The item to add. public void Add(T item) @@ -45,7 +45,7 @@ namespace osu.Game.Database } /// - /// Update a in the database. + /// Update a in the database. /// /// The item to update. public void Update(T item) @@ -58,7 +58,7 @@ namespace osu.Game.Database } /// - /// Delete a from the database. + /// Delete a from the database. /// /// The item to delete. public bool Delete(T item) @@ -77,7 +77,7 @@ namespace osu.Game.Database } /// - /// Restore a from a deleted state. + /// Restore a from a deleted state. /// /// The item to undelete. public bool Undelete(T item) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 5d1bdc62e9..585a46f3e1 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -32,7 +32,7 @@ namespace osu.Game.Graphics.UserInterface protected virtual float StripHeight() => 1; /// - /// Whether entries should be automatically populated if is an type. + /// Whether entries should be automatically populated if is an type. /// protected virtual bool AddEnumEntriesAutomatically => true; diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs index f34b8f14b0..ea274284ac 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs @@ -30,7 +30,7 @@ namespace osu.Game.Input.Bindings /// /// A reference to identify the current . Used to lookup mappings. Null for global mappings. /// An optional variant for the specified . Used when a ruleset has more than one possible keyboard layouts. - /// Specify how to deal with multiple matches of s and s. + /// Specify how to deal with multiple matches of s and s. public DatabasedKeyBindingContainer(RulesetInfo ruleset = null, int? variant = null, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None) : base(simultaneousMode) { diff --git a/osu.Game/Online/DownloadTrackingComposite.cs b/osu.Game/Online/DownloadTrackingComposite.cs index 7bfdc7ff69..dcec17788a 100644 --- a/osu.Game/Online/DownloadTrackingComposite.cs +++ b/osu.Game/Online/DownloadTrackingComposite.cs @@ -11,7 +11,7 @@ using osu.Game.Online.API; namespace osu.Game.Online { /// - /// A component which tracks a through potential download/import/deletion. + /// A component which tracks a through potential download/import/deletion. /// public abstract class DownloadTrackingComposite : CompositeDrawable where TModel : class, IEquatable @@ -22,7 +22,7 @@ namespace osu.Game.Online private TModelManager manager; /// - /// Holds the current download state of the , whether is has already been downloaded, is in progress, or is not downloaded. + /// Holds the current download state of the , whether is has already been downloaded, is in progress, or is not downloaded. /// protected readonly Bindable State = new Bindable(); diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index d1749d33c0..aec0e58a10 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -246,9 +246,9 @@ namespace osu.Game.Rulesets.UI } /// - /// Creates and adds the visual representation of a to this . + /// Creates and adds the visual representation of a to this . /// - /// The to add the visual representation for. + /// The to add the visual representation for. private void addHitObject(TObject hitObject) { var drawableObject = CreateDrawableRepresentation(hitObject); From b1b234c6fbbdc55c7ceef31193350ea63baa437e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Nov 2019 20:49:36 +0800 Subject: [PATCH 4077/5608] Use paramref. --- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 2 +- osu.Game/Overlays/OnScreenDisplay.cs | 2 +- .../Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index c3e2b469ae..ce2783004c 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -218,7 +218,7 @@ namespace osu.Game.Beatmaps.ControlPoints } /// - /// Check whether should be added. + /// Check whether should be added. /// /// The time to find the timing control point at. /// A point to be added. diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index a92320945e..e6708093c4 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -86,7 +86,7 @@ namespace osu.Game.Overlays /// The object that registered the to be tracked. /// The that is being tracked. /// If is null. - /// If is not being tracked from the same . + /// If is not being tracked from the same . public void StopTracking(object source, ITrackableConfigManager configManager) { if (configManager == null) throw new ArgumentNullException(nameof(configManager)); diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs index b7a5eedc22..5f053975c7 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms /// /// The point in time. /// The amount of visible time. - /// The time at which enters . + /// The time at which enters . double GetDisplayStartTime(double time, double timeRange); /// @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms /// The start time. /// The end time. /// The amount of visible time. - /// The absolute spatial length through . + /// The absolute spatial length through . /// The absolute spatial length. float GetLength(double startTime, double endTime, double timeRange, float scrollLength); @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms /// The time to compute the spatial position of. /// The current time. /// The amount of visible time. - /// The absolute spatial length through . + /// The absolute spatial length through . /// The absolute spatial position. float PositionAt(double time, double currentTime, double timeRange, float scrollLength); @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms /// The absolute spatial position. /// The current time. /// The amount of visible time. - /// The absolute spatial length through . + /// The absolute spatial length through . /// The time at which == . double TimeAt(float position, double currentTime, double timeRange, float scrollLength); From b04bca7db653c6e925313d567f813be8e898b252 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Nov 2019 20:55:40 +0800 Subject: [PATCH 4078/5608] Reference elements in origin definition. --- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 4 ++-- osu.Game/Graphics/Sprites/OsuSpriteText.cs | 4 ++-- osu.Game/Graphics/UserInterface/IconButton.cs | 4 ++-- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index fba52dfc32..149dafe449 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -139,7 +139,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// A function to retrieve the next column. If null, a randomisation scheme will be used. /// A function to perform additional validation checks to determine if a column is a valid candidate for a . /// The minimum column index. If null, is used. - /// The maximum column index. If null, is used. + /// The maximum column index. If null, is used. /// A list of patterns for which the validity of a column should be checked against. /// A column is not a valid candidate if a occupies the same column in any of the patterns. /// A column which has passed the check and for which there are no @@ -184,7 +184,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// Returns a random column index in the range [, ). /// /// The minimum column index. If null, is used. - /// The maximum column index. If null, is used. + /// The maximum column index. If null, is used. protected int GetRandomColumn(int? lowerBound = null, int? upperBound = null) => Random.Next(lowerBound ?? RandomStart, upperBound ?? TotalColumns); /// diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index ed771bb03f..bd1a7791e8 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -19,7 +19,7 @@ namespace osu.Game.Graphics.Sprites public static class OsuSpriteTextTransformExtensions { /// - /// Sets to a new value after a duration. + /// Sets to a new value after a duration. /// /// A to which further transforms can be added. public static TransformSequence TransformTextTo(this T spriteText, string newText, double duration = 0, Easing easing = Easing.None) @@ -27,7 +27,7 @@ namespace osu.Game.Graphics.Sprites => spriteText.TransformTo(nameof(OsuSpriteText.Text), newText, duration, easing); /// - /// Sets to a new value after a duration. + /// Sets to a new value after a duration. /// /// A to which further transforms can be added. public static TransformSequence TransformTextTo(this TransformSequence t, string newText, double duration = 0, Easing easing = Easing.None) diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs index 27427581fd..8600c5dcb1 100644 --- a/osu.Game/Graphics/UserInterface/IconButton.cs +++ b/osu.Game/Graphics/UserInterface/IconButton.cs @@ -16,7 +16,7 @@ namespace osu.Game.Graphics.UserInterface private Color4? iconColour; /// - /// The icon colour. This does not affect . + /// The icon colour. This does not affect . /// public Color4 IconColour { @@ -49,7 +49,7 @@ namespace osu.Game.Graphics.UserInterface } /// - /// The icon scale. This does not affect . + /// The icon scale. This does not affect . /// public Vector2 IconScale { diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index c3436ffd45..fa0ca3d9b3 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -351,7 +351,7 @@ namespace osu.Game.Screens.Select /// /// Half the height of the visible content. /// - /// This is different from the height of , since + /// This is different from the height of .displayableContent, since /// the beatmap carousel bleeds into the and the /// /// From 4d1513cef60c2c0d74632ab08202a913dcbf652b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Nov 2019 21:01:56 +0800 Subject: [PATCH 4079/5608] Sadly, xmldoc doesn't support tuple elements. --- osu.Game/Beatmaps/BeatmapDifficulty.cs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index 8727431e0e..c56fec67aa 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -56,10 +56,22 @@ namespace osu.Game.Beatmaps /// Maps a difficulty value [0, 10] to a two-piece linear range of values. /// /// The difficulty value to be mapped. - /// The values that define the two linear ranges. - /// Minimum of the resulting range which will be achieved by a difficulty value of 0. - /// Midpoint of the resulting range which will be achieved by a difficulty value of 5. - /// Maximum of the resulting range which will be achieved by a difficulty value of 10. + /// The values that define the two linear ranges. + /// + /// + /// od0 + /// Minimum of the resulting range which will be achieved by a difficulty value of 0. + /// + /// + /// od5 + /// Midpoint of the resulting range which will be achieved by a difficulty value of 5. + /// + /// + /// od10 + /// Maximum of the resulting range which will be achieved by a difficulty value of 10. + /// + /// + /// /// Value to which the difficulty value maps in the specified range. public static double DifficultyRange(double difficulty, (double od0, double od5, double od10) range) => DifficultyRange(difficulty, range.od0, range.od5, range.od10); From 53bc2dcab7a064ca0678497cf85c40a50c6e7a21 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 18 Nov 2019 15:29:18 +0800 Subject: [PATCH 4080/5608] Use costum displaying text for inherited references. --- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 2 +- osu.Game/Graphics/Sprites/OsuSpriteText.cs | 4 ++-- osu.Game/Graphics/UserInterface/IconButton.cs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index 149dafe449..f989f22298 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -139,7 +139,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// A function to retrieve the next column. If null, a randomisation scheme will be used. /// A function to perform additional validation checks to determine if a column is a valid candidate for a . /// The minimum column index. If null, is used. - /// The maximum column index. If null, is used. + /// The maximum column index. If null, TotalColumns is used. /// A list of patterns for which the validity of a column should be checked against. /// A column is not a valid candidate if a occupies the same column in any of the patterns. /// A column which has passed the check and for which there are no diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index bd1a7791e8..cd988c347b 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -19,7 +19,7 @@ namespace osu.Game.Graphics.Sprites public static class OsuSpriteTextTransformExtensions { /// - /// Sets to a new value after a duration. + /// Sets Text to a new value after a duration. /// /// A to which further transforms can be added. public static TransformSequence TransformTextTo(this T spriteText, string newText, double duration = 0, Easing easing = Easing.None) @@ -27,7 +27,7 @@ namespace osu.Game.Graphics.Sprites => spriteText.TransformTo(nameof(OsuSpriteText.Text), newText, duration, easing); /// - /// Sets to a new value after a duration. + /// Sets Text to a new value after a duration. /// /// A to which further transforms can be added. public static TransformSequence TransformTextTo(this TransformSequence t, string newText, double duration = 0, Easing easing = Easing.None) diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs index 8600c5dcb1..d7e5666545 100644 --- a/osu.Game/Graphics/UserInterface/IconButton.cs +++ b/osu.Game/Graphics/UserInterface/IconButton.cs @@ -16,7 +16,7 @@ namespace osu.Game.Graphics.UserInterface private Color4? iconColour; /// - /// The icon colour. This does not affect . + /// The icon colour. This does not affect Colour. /// public Color4 IconColour { @@ -49,7 +49,7 @@ namespace osu.Game.Graphics.UserInterface } /// - /// The icon scale. This does not affect . + /// The icon scale. This does not affect Scale. /// public Vector2 IconScale { From 140278bf4c4753e749ccca2884479b6493b7e8bd Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 13 Nov 2019 18:15:16 +0800 Subject: [PATCH 4081/5608] Bump Xamarin.Android version to 10.0 --- osu.Android.props | 2 +- osu.Android/Properties/AndroidManifest.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 6fab2e7868..d06e04aea4 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ Off True Xamarin.Android.Net.AndroidClientHandler - v9.0 + v10.0 false true armeabi-v7a;x86;arm64-v8a diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index acd21f9587..770eaf2222 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -1,6 +1,6 @@  - + From 608785b99aecb959aeab0dbe470d1181890090de Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 13 Nov 2019 18:28:56 +0800 Subject: [PATCH 4082/5608] Update .Net Standard projects to 2.1 --- osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj | 2 +- osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 2 +- osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 2 +- osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj | 2 +- osu.Game.Tournament/osu.Game.Tournament.csproj | 2 +- osu.Game/osu.Game.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index f24cf1def9..b19affbf9f 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true catch the fruit. to the beat. diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 0af200d19b..07ef1022ae 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true smash the keys. to the beat. diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index fb3fe8808d..bffeaabb55 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true click the circles. to the beat. diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 0a2b189c3a..ebed8c6d7c 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true bash the drum. to the beat. diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index f5306facaf..8e881fdd9c 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true tools for tournaments. diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index af60da3e70..8e3858d0f1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true From efbab5420667370d995e5b9f3a1315040ebff1bc Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 18 Nov 2019 18:48:29 +0800 Subject: [PATCH 4083/5608] Bump Android test projects version. --- .../Properties/AndroidManifest.xml | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../Properties/AndroidManifest.xml | 2 +- osu.Game.Tests.Android/Properties/AndroidManifest.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml index db95e18f13..0fa3b7730d 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml index e6728c801d..de7935b2ef 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml index aad907b241..3ce17ccc27 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml index cd4b74aa16..d9de0fde4e 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Tests.Android/Properties/AndroidManifest.xml index bb996dc5ca..4a63f0c357 100644 --- a/osu.Game.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file From 465c8c26186aba9f98688fa048165046adbe66ad Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Tue, 19 Nov 2019 13:47:29 +0900 Subject: [PATCH 4084/5608] Re-add package references to osu.iOS.props --- osu.iOS.props | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.iOS.props b/osu.iOS.props index 8124357312..6965b16303 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -75,4 +75,17 @@ + + + + + + + + + + + + + From 08b8cedfdf4766b4d29c2e36bd4ed33277c3cd33 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 20 Nov 2019 01:15:40 +0300 Subject: [PATCH 4085/5608] Add setter to legacy skin configuration access --- osu.Game/Skinning/LegacySkin.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 35aca3aa7b..0ee41e654e 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -26,7 +26,11 @@ namespace osu.Game.Skinning [CanBeNull] protected IResourceStore Samples; - protected new LegacySkinConfiguration Configuration => (LegacySkinConfiguration)base.Configuration; + protected new LegacySkinConfiguration Configuration + { + get => base.Configuration as LegacySkinConfiguration; + set => base.Configuration = value; + } public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini") @@ -41,10 +45,10 @@ namespace osu.Game.Skinning if (stream != null) { using (LineBufferedReader reader = new LineBufferedReader(stream)) - base.Configuration = new LegacySkinDecoder().Decode(reader); + Configuration = new LegacySkinDecoder().Decode(reader); } else - base.Configuration = new LegacySkinConfiguration { LegacyVersion = LegacySkinConfiguration.LATEST_VERSION }; + Configuration = new LegacySkinConfiguration { LegacyVersion = LegacySkinConfiguration.LATEST_VERSION }; if (storage != null) { From 76ed573c56793b267fdbc74832daafb46826044b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 20 Nov 2019 12:21:49 +0900 Subject: [PATCH 4086/5608] Fix crash when loading results after gameplay --- osu.Game/Scoring/ScoreInfo.cs | 5 ++++- osu.Game/Scoring/ScoreManager.cs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index d3c37bd4f4..ab344c7791 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -183,6 +183,9 @@ namespace osu.Game.Scoring public override string ToString() => $"{User} playing {Beatmap}"; - public bool Equals(ScoreInfo other) => other?.OnlineScoreID == OnlineScoreID; + public bool Equals(ScoreInfo other) => + other?.OnlineScoreID == OnlineScoreID + && other?.BeatmapInfoID == BeatmapInfoID + && other.Hash == Hash; } } diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 8475158c78..3279af05b6 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -69,6 +69,6 @@ namespace osu.Game.Scoring protected override ArchiveDownloadRequest CreateDownloadRequest(ScoreInfo score, bool minimiseDownload) => new DownloadReplayRequest(score); - protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) => items.Any(s => s.OnlineScoreID == model.OnlineScoreID && s.Files.Any()); + protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) => items.Any(s => s.Equals(model) && s.Files.Any()); } } From 6288e6da566a29e5e61f1cc0e64fc4478838bf39 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 20 Nov 2019 13:42:54 +0900 Subject: [PATCH 4087/5608] Add null check --- osu.Game/Scoring/ScoreInfo.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index ab344c7791..f7bac82e74 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -184,8 +184,9 @@ namespace osu.Game.Scoring public override string ToString() => $"{User} playing {Beatmap}"; public bool Equals(ScoreInfo other) => - other?.OnlineScoreID == OnlineScoreID - && other?.BeatmapInfoID == BeatmapInfoID + other != null + && other.OnlineScoreID == OnlineScoreID + && other.BeatmapInfoID == BeatmapInfoID && other.Hash == Hash; } } From bcb1504110f732679752f43254f2bdf1f9b0fd0b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Nov 2019 15:40:35 +0900 Subject: [PATCH 4088/5608] Fix naming --- osu.Game/Skinning/LegacySkin.cs | 4 ++-- osu.Game/Skinning/LegacySkinConfiguration.cs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 0ee41e654e..7ffed18d7b 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -80,10 +80,10 @@ namespace osu.Game.Skinning case GlobalSkinColour colour: return SkinUtils.As(getCustomColour(colour.ToString())); - case LegacySkinConfigurations legacy: + case LegacySkinConfiguration.LegacySetting legacy: switch (legacy) { - case LegacySkinConfigurations.Version: + case LegacySkinConfiguration.LegacySetting.Version: if (Configuration.LegacyVersion is decimal version) return SkinUtils.As(new Bindable(version)); diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs index 33c29cd47c..6a667e69f4 100644 --- a/osu.Game/Skinning/LegacySkinConfiguration.cs +++ b/osu.Game/Skinning/LegacySkinConfiguration.cs @@ -11,10 +11,10 @@ namespace osu.Game.Skinning /// Legacy version of this skin. Null if no version was set to allow fallback to a parent skin version. /// public decimal? LegacyVersion { get; internal set; } - } - public enum LegacySkinConfigurations - { - Version, + public enum LegacySetting + { + Version, + } } } From e0f59d8e24ea0c0f2f64dcda6fc8a6ddf5e72cf9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Nov 2019 15:43:00 +0900 Subject: [PATCH 4089/5608] Move method --- osu.Game/Screens/Select/SongSelect.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 089510513b..b5e62740f2 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -88,8 +88,6 @@ namespace osu.Game.Screens.Select [Resolved(canBeNull: true)] private MusicController music { get; set; } - protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) => Carousel.Filter(criteria); - [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { @@ -262,6 +260,8 @@ namespace osu.Game.Screens.Select } } + protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) => Carousel.Filter(criteria); + private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) From 5b416eb7ba35c261810368b2115079e375d17dd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Nov 2019 17:24:43 +0900 Subject: [PATCH 4090/5608] Move initial filter to run on entering --- osu.Game/Screens/Select/SongSelect.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index b5e62740f2..a52edb70db 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -260,7 +260,11 @@ namespace osu.Game.Screens.Select } } - protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) => Carousel.Filter(criteria); + protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) + { + if (this.IsCurrentScreen()) + Carousel.Filter(criteria); + } private DependencyContainer dependencies; @@ -433,6 +437,8 @@ namespace osu.Game.Screens.Select { base.OnEntering(last); + Carousel.Filter(FilterControl.CreateCriteria(), false); + this.FadeInFromZero(250); FilterControl.Activate(); } From 3ba9f840fdbae2ba70b6f23edf0f12806ac23917 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Nov 2019 19:38:39 +0900 Subject: [PATCH 4091/5608] Fix song select not always scrolling to the correct location --- osu.Game/Screens/Select/BeatmapCarousel.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index fa0ca3d9b3..beffa5b33f 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -452,9 +452,6 @@ namespace osu.Game.Screens.Select if (!itemsCache.IsValid) updateItems(); - if (!scrollPositionCache.IsValid) - updateScrollPosition(); - // Remove all items that should no longer be on-screen scrollableContent.RemoveAll(p => p.Y < visibleUpperBound - p.DrawHeight || p.Y > visibleBottomBound || !p.IsPresent); @@ -519,6 +516,14 @@ namespace osu.Game.Screens.Select updateItem(p); } + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + if (!scrollPositionCache.IsValid) + updateScrollPosition(); + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -637,8 +642,11 @@ namespace osu.Game.Screens.Select private void updateScrollPosition() { - if (scrollTarget != null) scroll.ScrollTo(scrollTarget.Value); - scrollPositionCache.Validate(); + if (scrollTarget != null) + { + scroll.ScrollTo(scrollTarget.Value); + scrollPositionCache.Validate(); + } } /// From 6cace0c5f5cba38be8c97a65368031a22330a8d8 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Wed, 20 Nov 2019 12:43:14 +0100 Subject: [PATCH 4092/5608] Replace all Mathhelper.Clamp usages with Math.Clamp --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 5 ++--- .../Difficulty/CatchPerformanceCalculator.cs | 2 +- osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 4 ++-- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 6 +++--- osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs | 3 ++- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 3 ++- .../Objects/Drawables/DrawableSliderHead.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 3 ++- .../Objects/Drawables/Pieces/SnakingSliderBody.cs | 2 +- .../Objects/Drawables/DrawableDrumRoll.cs | 4 ++-- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs | 3 +-- .../UI/TaikoPlayfieldAdjustmentContainer.cs | 3 ++- osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs | 3 ++- osu.Game/Graphics/Containers/ParallaxContainer.cs | 3 ++- osu.Game/Graphics/UserInterface/Bar.cs | 4 ++-- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 4 ++-- osu.Game/Graphics/UserInterface/OsuTabControl.cs | 2 +- osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs | 2 +- osu.Game/Overlays/Music/PlaylistList.cs | 2 +- .../Overlays/Profile/Header/Components/SupporterIcon.cs | 4 ++-- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 3 +-- osu.Game/Rulesets/Objects/SliderEventGenerator.cs | 2 +- osu.Game/Rulesets/Objects/SliderPath.cs | 2 +- osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs | 2 +- .../UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs | 4 ++-- .../Edit/Components/Timelines/Summary/Parts/MarkerPart.cs | 3 ++- .../Edit/Compose/Components/CircularDistanceSnapGrid.cs | 2 +- .../Compose/Components/Timeline/ZoomableScrollContainer.cs | 4 ++-- osu.Game/Screens/Edit/EditorClock.cs | 3 +-- osu.Game/Screens/Menu/Button.cs | 2 +- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 4 ++-- osu.Game/Screens/Play/SongProgressBar.cs | 2 +- osu.Game/Screens/Play/SquareGraph.cs | 2 +- osu.Game/Screens/ScreenWhiteBox.cs | 6 +++--- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- osu.Game/Screens/Select/Details/FailRetryGraph.cs | 4 ++-- osu.Game/Tests/Visual/OsuTestScene.cs | 3 +-- 42 files changed, 65 insertions(+), 63 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 58bf811fac..db52fbac1b 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -8,7 +8,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects.Types; -using osuTK; using osu.Game.Rulesets.Catch.MathUtils; using osu.Game.Rulesets.Mods; @@ -78,7 +77,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps catchObject.XOffset = 0; if (catchObject is TinyDroplet) - catchObject.XOffset = MathHelper.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); + catchObject.XOffset = Math.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); else if (catchObject is Droplet) rng.Next(); // osu!stable retrieved a random droplet rotation } @@ -230,7 +229,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps else { currentObject.DistanceToHyperDash = distanceToHyper; - lastExcess = MathHelper.Clamp(distanceToHyper, 0, halfCatcherWidth); + lastExcess = Math.Clamp(distanceToHyper, 0, halfCatcherWidth); } lastDirection = thisDirection; diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index 5a640f6d1a..638fd3f603 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty return value; } - private float accuracy() => totalHits() == 0 ? 0 : MathHelper.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); + private float accuracy() => totalHits() == 0 ? 0 : Math.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed; private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit; private int totalComboHits() => misses + ticksHit + fruitsHit; diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index d146153294..800346280d 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills if (lastPlayerPosition == null) lastPlayerPosition = catchCurrent.LastNormalizedPosition; - float playerPosition = MathHelper.Clamp( + float playerPosition = Math.Clamp( lastPlayerPosition.Value, catchCurrent.NormalizedPosition - (normalized_hitobject_radius - absolute_player_positioning_error), catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 1af77b75fc..eae652573b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -278,7 +278,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { base.Update(); - border.Alpha = (float)MathHelper.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); + border.Alpha = (float)Math.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); } private Color4 colourForRepresentation(FruitVisualRepresentation representation) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 56c8b33e02..d330add1c4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -235,7 +235,7 @@ namespace osu.Game.Rulesets.Catch.UI fruit.Y -= RNG.NextSingle() * diff; } - fruit.X = MathHelper.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); + fruit.X = Math.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); caughtFruit.Add(fruit); } @@ -378,7 +378,7 @@ namespace osu.Game.Rulesets.Catch.UI double speed = BASE_SPEED * dashModifier * hyperDashModifier; Scale = new Vector2(Math.Abs(Scale.X) * direction, Scale.Y); - X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); + X = (float)Math.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); // Correct overshooting. if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index f989f22298..eadf60b10b 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -54,11 +54,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (allowSpecial && TotalColumns == 8) { const float local_x_divisor = 512f / 7; - return MathHelper.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; + return Math.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; } float localXDivisor = 512f / TotalColumns; - return MathHelper.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); + return Math.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); } /// @@ -113,7 +113,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy drainTime = 10000; BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty; - conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; + conversionDifficulty = ((difficulty.DrainRate + Math.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; conversionDifficulty = Math.Min(conversionDifficulty.Value, 12); return conversionDifficulty.Value; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 9cdf045b5b..53f7e30dfd 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.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.Linq; using osu.Framework.Allocation; using osu.Framework.Timing; @@ -9,7 +10,6 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit.Compose.Components; -using osuTK; namespace osu.Game.Rulesets.Mania.Edit { @@ -119,7 +119,7 @@ namespace osu.Game.Rulesets.Mania.Edit maxColumn = obj.Column; } - columnDelta = MathHelper.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); + columnDelta = Math.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); foreach (var obj in SelectedHitObjects.OfType()) obj.Column += columnDelta; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 1eb37f8119..63110b2797 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,7 +14,6 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Mods }; } - private float calculateGap(float value) => MathHelper.Clamp(value, 0, target_clamp) * targetBreakMultiplier; + private float calculateGap(float value) => Math.Clamp(value, 0, target_clamp) * targetBreakMultiplier; // lagrange polinominal for (0,0) (0.6,0.4) (1,1) should make a good curve private static float applyAdjustmentCurve(float value) => 0.6f * value * value + 0.4f * value; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 7fa3dbe07e..778c2f7d43 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; @@ -55,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Mods var destination = e.MousePosition; FlashlightPosition = Interpolation.ValueAt( - MathHelper.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); + Math.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); return base.OnMouseMove(e); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 84d2a4af9b..122975d55e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables else { // If we're already snaking, interpolate to smooth out sharp curves (linear sliders, mainly). - Rotation = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint); + Rotation = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 433d29f2e4..69189758a6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.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 osuTK; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; @@ -165,7 +166,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Tracking.Value = Ball.Tracking; - double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); Ball.UpdateProgress(completionProgress); Body.UpdateProgress(completionProgress); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index 66b6f0f9ac..a10c66d1df 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.Update(); - double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); //todo: we probably want to reconsider this before adding scoring, but it looks and feels nice. if (!IsHit) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index d1b9ee6cb4..1261d3d19a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.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.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -136,7 +137,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindTo(HitObject.PositionBindable); } - public float Progress => MathHelper.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); + public float Progress => Math.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); protected override void CheckForResult(bool userTriggered, double timeOffset) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index 70a1bad4a3..f2150280b3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces var spanProgress = slider.ProgressAt(completionProgress); double start = 0; - double end = SnakingIn.Value ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; + double end = SnakingIn.Value ? Math.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; if (span >= slider.SpanCount() - 1) { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index cc0d6829ba..338fd9e20f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.MathUtils; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osuTK; using osuTK.Graphics; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Framework.Graphics; @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables else rollingHits--; - rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); + rollingHits = Math.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1); MainPiece.FadeAccent(newColour, 100); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 9c9dfc5f9e..fa39819199 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Objects; @@ -179,7 +178,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables var completion = (float)numHits / HitObject.RequiredHits; expandingRing - .FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50) + .FadeTo(expandingRing.Alpha + Math.Clamp(completion / 16, 0.1f, 0.6f), 50) .Then() .FadeTo(completion / 8, 2000, Easing.OutQuint); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 84464b199e..980f5ea340 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Game.Rulesets.UI; using osuTK; @@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.UI { base.Update(); - float aspectAdjust = MathHelper.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; + float aspectAdjust = Math.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; Size = new Vector2(1, default_relative_height * aspectAdjust); } } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index f613ce5f46..724612ebce 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; @@ -32,7 +33,7 @@ namespace osu.Game.Tournament.Screens.Ladder protected override bool OnScroll(ScrollEvent e) { - var newScale = MathHelper.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); + var newScale = Math.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); this.MoveTo(target = target - e.MousePosition * (newScale - scale), 2000, Easing.OutQuint); this.ScaleTo(scale = newScale, 2000, Easing.OutQuint); diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index 86f922e4b8..f8c21eabc2 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Input; @@ -71,7 +72,7 @@ namespace osu.Game.Graphics.Containers const float parallax_duration = 100; - double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); + double elapsed = Math.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, parallax_duration, Easing.OutQuint); content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); diff --git a/osu.Game/Graphics/UserInterface/Bar.cs b/osu.Game/Graphics/UserInterface/Bar.cs index f8d5955503..0be928cf83 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using System; namespace osu.Game.Graphics.UserInterface { @@ -29,7 +29,7 @@ namespace osu.Game.Graphics.UserInterface get => length; set { - length = MathHelper.Clamp(value, 0, 1); + length = Math.Clamp(value, 0, 1); updateBarLength(); } } diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 11aba80d76..7412224f6c 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -175,9 +175,9 @@ namespace osu.Game.Graphics.UserInterface protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - leftBox.Scale = new Vector2(MathHelper.Clamp( + leftBox.Scale = new Vector2(Math.Clamp( Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); - rightBox.Scale = new Vector2(MathHelper.Clamp( + rightBox.Scale = new Vector2(Math.Clamp( DrawWidth - Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); } diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 585a46f3e1..064cba6adf 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -99,7 +99,7 @@ namespace osu.Game.Graphics.UserInterface // dont bother calculating if the strip is invisible if (strip.Colour.MaxAlpha > 0) - strip.Width = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); + strip.Width = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); } public class OsuTabItem : TabItem, IHasAccentColour diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 8b88d81b88..583db460f4 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -99,7 +99,7 @@ namespace osu.Game.Overlays.Chat.Tabs private void tabCloseRequested(TabItem tab) { int totalTabs = TabContainer.Count - 1; // account for selectorTab - int currentIndex = MathHelper.Clamp(TabContainer.IndexOf(tab), 1, totalTabs); + int currentIndex = Math.Clamp(TabContainer.IndexOf(tab), 1, totalTabs); if (tab == SelectedTab && totalTabs > 1) // Select the tab after tab-to-be-removed's index, or the tab before if current == last diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index e3acd31626..83528298b1 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -217,7 +217,7 @@ namespace osu.Game.Overlays.Music break; } - dstIndex = MathHelper.Clamp(dstIndex, 0, items.Count - 1); + dstIndex = Math.Clamp(dstIndex, 0, items.Count - 1); if (srcIndex == dstIndex) return; diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index fa60a37ddb..d581e2750c 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -8,7 +9,6 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { set { - int count = MathHelper.Clamp(value, 0, 3); + int count = Math.Clamp(value, 0, 3); if (count == 0) { diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 9edf57ad00..f217512965 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -9,7 +9,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; -using osuTK; namespace osu.Game.Rulesets.Mods { @@ -59,7 +58,7 @@ namespace osu.Game.Rulesets.Mods /// The amount of adjustment to apply (from 0..1). private void applyAdjustment(double amount) { - double adjust = 1 + (Math.Sign(FinalRateAdjustment) * MathHelper.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); + double adjust = 1 + (Math.Sign(FinalRateAdjustment) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); switch (clock) { diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs index 0d8796b4cb..1a671e8041 100644 --- a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Objects const double max_length = 100000; var length = Math.Min(max_length, totalDistance); - tickDistance = MathHelper.Clamp(tickDistance, 0, length); + tickDistance = Math.Clamp(tickDistance, 0, length); var minDistanceFromEnd = velocity * 10; diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 7763b0eaaf..e8ef16e825 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -246,7 +246,7 @@ namespace osu.Game.Rulesets.Objects private double progressToDistance(double progress) { - return MathHelper.Clamp(progress, 0, 1) * Distance; + return Math.Clamp(progress, 0, 1) * Distance; } private Vector2 interpolateVertices(int i, double d) diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 4c011388fa..cb89653675 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Replays private int? currentFrameIndex; - private int nextFrameIndex => currentFrameIndex.HasValue ? MathHelper.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; + private int nextFrameIndex => currentFrameIndex.HasValue ? Math.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; protected FramedReplayInputHandler(Replay replay) { diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs index 5316585493..fe22a86fad 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs @@ -1,9 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Lists; using osu.Game.Rulesets.Timing; -using osuTK; namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms } } - i = MathHelper.Clamp(i, 0, controlPoints.Count - 1); + i = Math.Clamp(i, 0, controlPoints.Count - 1); return controlPoints[i].StartTime + (position - pos) * timeRange / controlPoints[i].Multiplier / scrollLength; } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index 07d307f293..79ada40a89 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.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 osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -59,7 +60,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts if (Beatmap.Value == null) return; - float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); + float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); adjustableClock.Seek(markerPos / DrawWidth * Beatmap.Value.Track.Length); }); } diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 0f2bae6305..fc7d51db4b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Edit.Compose.Components float distance = direction.Length; float radius = DistanceSpacing; - int radialCount = MathHelper.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); + int radialCount = Math.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); Vector2 normalisedDirection = direction * new Vector2(1f / distance); Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index cffb6bedf3..54922fec5e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline get => zoomTarget; set { - value = MathHelper.Clamp(value, MinZoom, MaxZoom); + value = Math.Clamp(value, MinZoom, MaxZoom); if (IsLoaded) setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); @@ -117,7 +117,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void setZoomTarget(float newZoom, float focusPoint) { - zoomTarget = MathHelper.Clamp(newZoom, MinZoom, MaxZoom); + zoomTarget = Math.Clamp(newZoom, MinZoom, MaxZoom); transformZoomTo(zoomTarget, focusPoint, ZoomDuration, ZoomEasing); } diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index bd2db4ae2b..93a5f19121 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -7,7 +7,6 @@ using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osuTK; namespace osu.Game.Screens.Edit { @@ -125,7 +124,7 @@ namespace osu.Game.Screens.Edit seekTime = nextTimingPoint.Time; // Ensure the sought point is within the boundaries - seekTime = MathHelper.Clamp(seekTime, 0, TrackLength); + seekTime = Math.Clamp(seekTime, 0, TrackLength); Seek(seekTime); } } diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index ffeadb96c7..fac6b69e1f 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -236,7 +236,7 @@ namespace osu.Game.Screens.Menu protected override void Update() { - iconText.Alpha = MathHelper.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1); + iconText.Alpha = Math.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1); base.Update(); } diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 968b83e68c..640224c057 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -102,8 +102,8 @@ namespace osu.Game.Screens.Play.HUD else { Alpha = Interpolation.ValueAt( - MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 200), - Alpha, MathHelper.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); + Math.Clamp(Clock.ElapsedFrameTime, 0, 200), + Alpha, Math.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); } } diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index 33c7595b37..cdf495e257 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -116,7 +116,7 @@ namespace osu.Game.Screens.Play { base.Update(); - float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, MathHelper.Clamp(Time.Elapsed / 40, 0, 1)); + float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Math.Clamp(Time.Elapsed / 40, 0, 1)); fill.Width = newX; handleBase.X = newX; diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 05f6128ac2..715ba3c065 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -256,7 +256,7 @@ namespace osu.Game.Screens.Play { Color4 colour = State == ColumnState.Lit ? LitColour : DimmedColour; - int countFilled = (int)MathHelper.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); + int countFilled = (int)Math.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); for (int i = 0; i < drawableRows.Count; i++) drawableRows[i].Colour = i < countFilled ? colour : EmptyColour; diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index e4971221c4..3d8fd5dad7 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -87,9 +87,9 @@ namespace osu.Game.Screens private static Color4 getColourFor(object type) { int hash = type.GetHashCode(); - byte r = (byte)MathHelper.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); - byte g = (byte)MathHelper.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); - byte b = (byte)MathHelper.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); + byte r = (byte)Math.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); + byte g = (byte)Math.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); + byte b = (byte)Math.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); return new Color4(r, g, b, 255); } diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index fa0ca3d9b3..c328eebca7 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -677,7 +677,7 @@ namespace osu.Game.Screens.Select // We are applying a multiplicative alpha (which is internally done by nesting an // additional container and setting that container's alpha) such that we can // layer transformations on top, with a similar reasoning to the previous comment. - p.SetMultiplicativeAlpha(MathHelper.Clamp(1.75f - 1.5f * dist, 0, 1)); + p.SetMultiplicativeAlpha(Math.Clamp(1.75f - 1.5f * dist, 0, 1)); } private class CarouselRoot : CarouselGroupEagerSelect diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index 34297d89a4..121f8efe5a 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -1,7 +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 osuTK; +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Select.Details retryGraph.MaxValue = maxValue; failGraph.Values = fails.Select(f => (float)f); - retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + MathHelper.Clamp(fail, 0, maxValue)); + retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + Math.Clamp(fail, 0, maxValue)); } } diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 345fff90aa..13e08c7d22 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -22,7 +22,6 @@ using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Tests.Beatmaps; -using osuTK; namespace osu.Game.Tests.Visual { @@ -250,7 +249,7 @@ namespace osu.Game.Tests.Visual public override bool Seek(double seek) { - offset = MathHelper.Clamp(seek, 0, Length); + offset = Math.Clamp(seek, 0, Length); lastReferenceTime = null; return offset == seek; From b7d5e3689015b584c7464f312f33c7cfa87268d3 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Wed, 20 Nov 2019 13:18:03 +0100 Subject: [PATCH 4093/5608] Remove unused Using directives --- osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs | 1 - osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs | 1 - .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 1 - osu.Game/Rulesets/Objects/SliderEventGenerator.cs | 1 - osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs | 1 - 5 files changed, 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index 638fd3f603..a7f0d358ed 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Scoring.Legacy; -using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty { diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index 800346280d..7cd569035b 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -6,7 +6,6 @@ using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; -using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty.Skills { diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index eadf60b10b..b9984a8b90 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -7,7 +7,6 @@ using JetBrains.Annotations; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Objects; -using osuTK; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs index 1a671e8041..e9ee3833b7 100644 --- a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using osuTK; namespace osu.Game.Rulesets.Objects { diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index cb89653675..7e17396fde 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -7,7 +7,6 @@ using JetBrains.Annotations; using osu.Framework.Input.StateChanges; using osu.Game.Input.Handlers; using osu.Game.Replays; -using osuTK; namespace osu.Game.Rulesets.Replays { From da41b70d438108d09b058bdc05b8f6f93c8d1f19 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Wed, 20 Nov 2019 13:19:49 +0100 Subject: [PATCH 4094/5608] .NET Standard 2.1 implements Math.Clamp , use it instead of MathHelper.Clamp from osuTK. --- osu.Android.props | 2 +- osu.Android/Properties/AndroidManifest.xml | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../Beatmaps/CatchBeatmapProcessor.cs | 5 +- .../Difficulty/CatchPerformanceCalculator.cs | 3 +- .../Difficulty/Skills/Movement.cs | 3 +- .../Objects/Drawable/DrawableFruit.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 4 +- .../osu.Game.Rulesets.Catch.csproj | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../Patterns/Legacy/PatternGenerator.cs | 7 ++- .../Edit/ManiaSelectionHandler.cs | 4 +- .../osu.Game.Rulesets.Mania.csproj | 2 +- .../Properties/AndroidManifest.xml | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 4 +- .../Mods/OsuModFlashlight.cs | 3 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- .../Objects/Drawables/DrawableSlider.cs | 3 +- .../Objects/Drawables/DrawableSliderHead.cs | 2 +- .../Objects/Drawables/DrawableSpinner.cs | 3 +- .../Drawables/Pieces/SnakingSliderBody.cs | 2 +- .../osu.Game.Rulesets.Osu.csproj | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../Objects/Drawables/DrawableDrumRoll.cs | 4 +- .../Objects/Drawables/DrawableSwell.cs | 3 +- .../UI/TaikoPlayfieldAdjustmentContainer.cs | 3 +- .../osu.Game.Rulesets.Taiko.csproj | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../SongSelect/TestScenePlaySongSelect.cs | 53 +++++++++++++------ .../Screens/Ladder/LadderDragContainer.cs | 3 +- .../osu.Game.Tournament.csproj | 2 +- .../Graphics/Containers/ParallaxContainer.cs | 3 +- osu.Game/Graphics/UserInterface/Bar.cs | 4 +- .../Graphics/UserInterface/OsuSliderBar.cs | 4 +- .../Graphics/UserInterface/OsuTabControl.cs | 2 +- .../Overlays/Chat/Tabs/ChannelTabControl.cs | 2 +- osu.Game/Overlays/Music/PlaylistList.cs | 2 +- .../Header/Components/SupporterIcon.cs | 4 +- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 3 +- .../Rulesets/Objects/SliderEventGenerator.cs | 3 +- osu.Game/Rulesets/Objects/SliderPath.cs | 2 +- .../Replays/FramedReplayInputHandler.cs | 3 +- .../Algorithms/OverlappingScrollAlgorithm.cs | 4 +- osu.Game/Scoring/ScoreInfo.cs | 6 ++- osu.Game/Scoring/ScoreManager.cs | 2 +- .../Timelines/Summary/Parts/MarkerPart.cs | 3 +- .../Components/CircularDistanceSnapGrid.cs | 2 +- .../Timeline/ZoomableScrollContainer.cs | 4 +- osu.Game/Screens/Edit/EditorClock.cs | 3 +- osu.Game/Screens/Menu/Button.cs | 2 +- .../Screens/Play/HUD/HoldForMenuButton.cs | 4 +- osu.Game/Screens/Play/SongProgressBar.cs | 2 +- osu.Game/Screens/Play/SquareGraph.cs | 2 +- osu.Game/Screens/ScreenWhiteBox.cs | 6 +-- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- .../Screens/Select/Details/FailRetryGraph.cs | 4 +- osu.Game/Screens/Select/SongSelect.cs | 47 ++++++++++------ osu.Game/Tests/Visual/OsuTestScene.cs | 3 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 13 +++++ 60 files changed, 164 insertions(+), 116 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 6fab2e7868..d06e04aea4 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ Off True Xamarin.Android.Net.AndroidClientHandler - v9.0 + v10.0 false true armeabi-v7a;x86;arm64-v8a diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index acd21f9587..770eaf2222 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -1,6 +1,6 @@  - + diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml index db95e18f13..0fa3b7730d 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 58bf811fac..db52fbac1b 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -8,7 +8,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects.Types; -using osuTK; using osu.Game.Rulesets.Catch.MathUtils; using osu.Game.Rulesets.Mods; @@ -78,7 +77,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps catchObject.XOffset = 0; if (catchObject is TinyDroplet) - catchObject.XOffset = MathHelper.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); + catchObject.XOffset = Math.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); else if (catchObject is Droplet) rng.Next(); // osu!stable retrieved a random droplet rotation } @@ -230,7 +229,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps else { currentObject.DistanceToHyperDash = distanceToHyper; - lastExcess = MathHelper.Clamp(distanceToHyper, 0, halfCatcherWidth); + lastExcess = Math.Clamp(distanceToHyper, 0, halfCatcherWidth); } lastDirection = thisDirection; diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index 5a640f6d1a..a7f0d358ed 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Scoring.Legacy; -using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty { @@ -96,7 +95,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty return value; } - private float accuracy() => totalHits() == 0 ? 0 : MathHelper.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); + private float accuracy() => totalHits() == 0 ? 0 : Math.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed; private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit; private int totalComboHits() => misses + ticksHit + fruitsHit; diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index d146153294..7cd569035b 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -6,7 +6,6 @@ using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; -using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty.Skills { @@ -31,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills if (lastPlayerPosition == null) lastPlayerPosition = catchCurrent.LastNormalizedPosition; - float playerPosition = MathHelper.Clamp( + float playerPosition = Math.Clamp( lastPlayerPosition.Value, catchCurrent.NormalizedPosition - (normalized_hitobject_radius - absolute_player_positioning_error), catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 1af77b75fc..eae652573b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -278,7 +278,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { base.Update(); - border.Alpha = (float)MathHelper.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); + border.Alpha = (float)Math.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); } private Color4 colourForRepresentation(FruitVisualRepresentation representation) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 56c8b33e02..d330add1c4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -235,7 +235,7 @@ namespace osu.Game.Rulesets.Catch.UI fruit.Y -= RNG.NextSingle() * diff; } - fruit.X = MathHelper.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); + fruit.X = Math.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); caughtFruit.Add(fruit); } @@ -378,7 +378,7 @@ namespace osu.Game.Rulesets.Catch.UI double speed = BASE_SPEED * dashModifier * hyperDashModifier; Scale = new Vector2(Math.Abs(Scale.X) * direction, Scale.Y); - X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); + X = (float)Math.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); // Correct overshooting. if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index f24cf1def9..b19affbf9f 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true catch the fruit. to the beat. diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml index e6728c801d..de7935b2ef 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index f989f22298..b9984a8b90 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -7,7 +7,6 @@ using JetBrains.Annotations; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Objects; -using osuTK; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { @@ -54,11 +53,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (allowSpecial && TotalColumns == 8) { const float local_x_divisor = 512f / 7; - return MathHelper.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; + return Math.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; } float localXDivisor = 512f / TotalColumns; - return MathHelper.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); + return Math.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); } /// @@ -113,7 +112,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy drainTime = 10000; BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty; - conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; + conversionDifficulty = ((difficulty.DrainRate + Math.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; conversionDifficulty = Math.Min(conversionDifficulty.Value, 12); return conversionDifficulty.Value; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 9cdf045b5b..53f7e30dfd 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.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.Linq; using osu.Framework.Allocation; using osu.Framework.Timing; @@ -9,7 +10,6 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit.Compose.Components; -using osuTK; namespace osu.Game.Rulesets.Mania.Edit { @@ -119,7 +119,7 @@ namespace osu.Game.Rulesets.Mania.Edit maxColumn = obj.Column; } - columnDelta = MathHelper.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); + columnDelta = Math.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); foreach (var obj in SelectedHitObjects.OfType()) obj.Column += columnDelta; diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 0af200d19b..07ef1022ae 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true smash the keys. to the beat. diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml index aad907b241..3ce17ccc27 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 1eb37f8119..63110b2797 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,7 +14,6 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Mods }; } - private float calculateGap(float value) => MathHelper.Clamp(value, 0, target_clamp) * targetBreakMultiplier; + private float calculateGap(float value) => Math.Clamp(value, 0, target_clamp) * targetBreakMultiplier; // lagrange polinominal for (0,0) (0.6,0.4) (1,1) should make a good curve private static float applyAdjustmentCurve(float value) => 0.6f * value * value + 0.4f * value; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 7fa3dbe07e..778c2f7d43 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; @@ -55,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Mods var destination = e.MousePosition; FlashlightPosition = Interpolation.ValueAt( - MathHelper.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); + Math.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); return base.OnMouseMove(e); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 84d2a4af9b..122975d55e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables else { // If we're already snaking, interpolate to smooth out sharp curves (linear sliders, mainly). - Rotation = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint); + Rotation = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 433d29f2e4..69189758a6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.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 osuTK; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; @@ -165,7 +166,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Tracking.Value = Ball.Tracking; - double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); Ball.UpdateProgress(completionProgress); Body.UpdateProgress(completionProgress); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index 66b6f0f9ac..a10c66d1df 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.Update(); - double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); //todo: we probably want to reconsider this before adding scoring, but it looks and feels nice. if (!IsHit) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index d1b9ee6cb4..1261d3d19a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.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.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -136,7 +137,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindTo(HitObject.PositionBindable); } - public float Progress => MathHelper.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); + public float Progress => Math.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); protected override void CheckForResult(bool userTriggered, double timeOffset) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index 70a1bad4a3..f2150280b3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces var spanProgress = slider.ProgressAt(completionProgress); double start = 0; - double end = SnakingIn.Value ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; + double end = SnakingIn.Value ? Math.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; if (span >= slider.SpanCount() - 1) { diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index fb3fe8808d..bffeaabb55 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true click the circles. to the beat. diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml index cd4b74aa16..d9de0fde4e 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index cc0d6829ba..338fd9e20f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.MathUtils; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osuTK; using osuTK.Graphics; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Framework.Graphics; @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables else rollingHits--; - rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); + rollingHits = Math.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1); MainPiece.FadeAccent(newColour, 100); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 9c9dfc5f9e..fa39819199 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Objects; @@ -179,7 +178,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables var completion = (float)numHits / HitObject.RequiredHits; expandingRing - .FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50) + .FadeTo(expandingRing.Alpha + Math.Clamp(completion / 16, 0.1f, 0.6f), 50) .Then() .FadeTo(completion / 8, 2000, Easing.OutQuint); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 84464b199e..980f5ea340 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Game.Rulesets.UI; using osuTK; @@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.UI { base.Update(); - float aspectAdjust = MathHelper.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; + float aspectAdjust = Math.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; Size = new Vector2(1, default_relative_height * aspectAdjust); } } diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 0a2b189c3a..ebed8c6d7c 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true bash the drum. to the beat. diff --git a/osu.Game.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Tests.Android/Properties/AndroidManifest.xml index bb996dc5ca..4a63f0c357 100644 --- a/osu.Game.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index d45b1bdba2..a4b8d1a24a 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -57,23 +57,6 @@ namespace osu.Game.Tests.Visual.SongSelect typeof(DrawableCarouselBeatmapSet), }; - private class TestSongSelect : PlaySongSelect - { - public Action StartRequested; - - public new Bindable Ruleset => base.Ruleset; - - public WorkingBeatmap CurrentBeatmap => Beatmap.Value; - public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap; - public new BeatmapCarousel Carousel => base.Carousel; - - protected override bool OnStart() - { - StartRequested?.Invoke(); - return base.OnStart(); - } - } - private TestSongSelect songSelect; [BackgroundDependencyLoader] @@ -101,6 +84,17 @@ namespace osu.Game.Tests.Visual.SongSelect manager?.Delete(manager.GetAllUsableBeatmapSets()); }); + [Test] + public void TestSingleFilterOnEnter() + { + addRulesetImportStep(0); + addRulesetImportStep(0); + + createSongSelect(); + + AddAssert("filter count is 1", () => songSelect.FilterCount == 1); + } + [Test] public void TestAudioResuming() { @@ -373,5 +367,30 @@ namespace osu.Game.Tests.Visual.SongSelect base.Dispose(isDisposing); rulesets?.Dispose(); } + + private class TestSongSelect : PlaySongSelect + { + public Action StartRequested; + + public new Bindable Ruleset => base.Ruleset; + + public WorkingBeatmap CurrentBeatmap => Beatmap.Value; + public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap; + public new BeatmapCarousel Carousel => base.Carousel; + + protected override bool OnStart() + { + StartRequested?.Invoke(); + return base.OnStart(); + } + + public int FilterCount; + + protected override void ApplyFilterToCarousel(FilterCriteria criteria) + { + FilterCount++; + base.ApplyFilterToCarousel(criteria); + } + } } } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index f613ce5f46..724612ebce 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; @@ -32,7 +33,7 @@ namespace osu.Game.Tournament.Screens.Ladder protected override bool OnScroll(ScrollEvent e) { - var newScale = MathHelper.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); + var newScale = Math.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); this.MoveTo(target = target - e.MousePosition * (newScale - scale), 2000, Easing.OutQuint); this.ScaleTo(scale = newScale, 2000, Easing.OutQuint); diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index f5306facaf..8e881fdd9c 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true tools for tournaments. diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index 86f922e4b8..f8c21eabc2 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Input; @@ -71,7 +72,7 @@ namespace osu.Game.Graphics.Containers const float parallax_duration = 100; - double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); + double elapsed = Math.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, parallax_duration, Easing.OutQuint); content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); diff --git a/osu.Game/Graphics/UserInterface/Bar.cs b/osu.Game/Graphics/UserInterface/Bar.cs index f8d5955503..0be928cf83 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using System; namespace osu.Game.Graphics.UserInterface { @@ -29,7 +29,7 @@ namespace osu.Game.Graphics.UserInterface get => length; set { - length = MathHelper.Clamp(value, 0, 1); + length = Math.Clamp(value, 0, 1); updateBarLength(); } } diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 11aba80d76..7412224f6c 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -175,9 +175,9 @@ namespace osu.Game.Graphics.UserInterface protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - leftBox.Scale = new Vector2(MathHelper.Clamp( + leftBox.Scale = new Vector2(Math.Clamp( Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); - rightBox.Scale = new Vector2(MathHelper.Clamp( + rightBox.Scale = new Vector2(Math.Clamp( DrawWidth - Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); } diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 585a46f3e1..064cba6adf 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -99,7 +99,7 @@ namespace osu.Game.Graphics.UserInterface // dont bother calculating if the strip is invisible if (strip.Colour.MaxAlpha > 0) - strip.Width = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); + strip.Width = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); } public class OsuTabItem : TabItem, IHasAccentColour diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 8b88d81b88..583db460f4 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -99,7 +99,7 @@ namespace osu.Game.Overlays.Chat.Tabs private void tabCloseRequested(TabItem tab) { int totalTabs = TabContainer.Count - 1; // account for selectorTab - int currentIndex = MathHelper.Clamp(TabContainer.IndexOf(tab), 1, totalTabs); + int currentIndex = Math.Clamp(TabContainer.IndexOf(tab), 1, totalTabs); if (tab == SelectedTab && totalTabs > 1) // Select the tab after tab-to-be-removed's index, or the tab before if current == last diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index e3acd31626..83528298b1 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -217,7 +217,7 @@ namespace osu.Game.Overlays.Music break; } - dstIndex = MathHelper.Clamp(dstIndex, 0, items.Count - 1); + dstIndex = Math.Clamp(dstIndex, 0, items.Count - 1); if (srcIndex == dstIndex) return; diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index fa60a37ddb..d581e2750c 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -8,7 +9,6 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { set { - int count = MathHelper.Clamp(value, 0, 3); + int count = Math.Clamp(value, 0, 3); if (count == 0) { diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 9edf57ad00..f217512965 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -9,7 +9,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; -using osuTK; namespace osu.Game.Rulesets.Mods { @@ -59,7 +58,7 @@ namespace osu.Game.Rulesets.Mods /// The amount of adjustment to apply (from 0..1). private void applyAdjustment(double amount) { - double adjust = 1 + (Math.Sign(FinalRateAdjustment) * MathHelper.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); + double adjust = 1 + (Math.Sign(FinalRateAdjustment) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); switch (clock) { diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs index 0d8796b4cb..e9ee3833b7 100644 --- a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using osuTK; namespace osu.Game.Rulesets.Objects { @@ -18,7 +17,7 @@ namespace osu.Game.Rulesets.Objects const double max_length = 100000; var length = Math.Min(max_length, totalDistance); - tickDistance = MathHelper.Clamp(tickDistance, 0, length); + tickDistance = Math.Clamp(tickDistance, 0, length); var minDistanceFromEnd = velocity * 10; diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 7763b0eaaf..e8ef16e825 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -246,7 +246,7 @@ namespace osu.Game.Rulesets.Objects private double progressToDistance(double progress) { - return MathHelper.Clamp(progress, 0, 1) * Distance; + return Math.Clamp(progress, 0, 1) * Distance; } private Vector2 interpolateVertices(int i, double d) diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 4c011388fa..7e17396fde 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -7,7 +7,6 @@ using JetBrains.Annotations; using osu.Framework.Input.StateChanges; using osu.Game.Input.Handlers; using osu.Game.Replays; -using osuTK; namespace osu.Game.Rulesets.Replays { @@ -52,7 +51,7 @@ namespace osu.Game.Rulesets.Replays private int? currentFrameIndex; - private int nextFrameIndex => currentFrameIndex.HasValue ? MathHelper.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; + private int nextFrameIndex => currentFrameIndex.HasValue ? Math.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; protected FramedReplayInputHandler(Replay replay) { diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs index 5316585493..fe22a86fad 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs @@ -1,9 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Lists; using osu.Game.Rulesets.Timing; -using osuTK; namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms } } - i = MathHelper.Clamp(i, 0, controlPoints.Count - 1); + i = Math.Clamp(i, 0, controlPoints.Count - 1); return controlPoints[i].StartTime + (position - pos) * timeRange / controlPoints[i].Multiplier / scrollLength; } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index d3c37bd4f4..f7bac82e74 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -183,6 +183,10 @@ namespace osu.Game.Scoring public override string ToString() => $"{User} playing {Beatmap}"; - public bool Equals(ScoreInfo other) => other?.OnlineScoreID == OnlineScoreID; + public bool Equals(ScoreInfo other) => + other != null + && other.OnlineScoreID == OnlineScoreID + && other.BeatmapInfoID == BeatmapInfoID + && other.Hash == Hash; } } diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 8475158c78..3279af05b6 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -69,6 +69,6 @@ namespace osu.Game.Scoring protected override ArchiveDownloadRequest CreateDownloadRequest(ScoreInfo score, bool minimiseDownload) => new DownloadReplayRequest(score); - protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) => items.Any(s => s.OnlineScoreID == model.OnlineScoreID && s.Files.Any()); + protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) => items.Any(s => s.Equals(model) && s.Files.Any()); } } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index 07d307f293..79ada40a89 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.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 osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -59,7 +60,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts if (Beatmap.Value == null) return; - float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); + float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); adjustableClock.Seek(markerPos / DrawWidth * Beatmap.Value.Track.Length); }); } diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 0f2bae6305..fc7d51db4b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Edit.Compose.Components float distance = direction.Length; float radius = DistanceSpacing; - int radialCount = MathHelper.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); + int radialCount = Math.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); Vector2 normalisedDirection = direction * new Vector2(1f / distance); Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index cffb6bedf3..54922fec5e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline get => zoomTarget; set { - value = MathHelper.Clamp(value, MinZoom, MaxZoom); + value = Math.Clamp(value, MinZoom, MaxZoom); if (IsLoaded) setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); @@ -117,7 +117,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void setZoomTarget(float newZoom, float focusPoint) { - zoomTarget = MathHelper.Clamp(newZoom, MinZoom, MaxZoom); + zoomTarget = Math.Clamp(newZoom, MinZoom, MaxZoom); transformZoomTo(zoomTarget, focusPoint, ZoomDuration, ZoomEasing); } diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index bd2db4ae2b..93a5f19121 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -7,7 +7,6 @@ using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osuTK; namespace osu.Game.Screens.Edit { @@ -125,7 +124,7 @@ namespace osu.Game.Screens.Edit seekTime = nextTimingPoint.Time; // Ensure the sought point is within the boundaries - seekTime = MathHelper.Clamp(seekTime, 0, TrackLength); + seekTime = Math.Clamp(seekTime, 0, TrackLength); Seek(seekTime); } } diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index ffeadb96c7..fac6b69e1f 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -236,7 +236,7 @@ namespace osu.Game.Screens.Menu protected override void Update() { - iconText.Alpha = MathHelper.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1); + iconText.Alpha = Math.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1); base.Update(); } diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 968b83e68c..640224c057 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -102,8 +102,8 @@ namespace osu.Game.Screens.Play.HUD else { Alpha = Interpolation.ValueAt( - MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 200), - Alpha, MathHelper.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); + Math.Clamp(Clock.ElapsedFrameTime, 0, 200), + Alpha, Math.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); } } diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index 33c7595b37..cdf495e257 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -116,7 +116,7 @@ namespace osu.Game.Screens.Play { base.Update(); - float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, MathHelper.Clamp(Time.Elapsed / 40, 0, 1)); + float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Math.Clamp(Time.Elapsed / 40, 0, 1)); fill.Width = newX; handleBase.X = newX; diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 05f6128ac2..715ba3c065 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -256,7 +256,7 @@ namespace osu.Game.Screens.Play { Color4 colour = State == ColumnState.Lit ? LitColour : DimmedColour; - int countFilled = (int)MathHelper.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); + int countFilled = (int)Math.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); for (int i = 0; i < drawableRows.Count; i++) drawableRows[i].Colour = i < countFilled ? colour : EmptyColour; diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index e4971221c4..3d8fd5dad7 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -87,9 +87,9 @@ namespace osu.Game.Screens private static Color4 getColourFor(object type) { int hash = type.GetHashCode(); - byte r = (byte)MathHelper.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); - byte g = (byte)MathHelper.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); - byte b = (byte)MathHelper.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); + byte r = (byte)Math.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); + byte g = (byte)Math.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); + byte b = (byte)Math.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); return new Color4(r, g, b, 255); } diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index fa0ca3d9b3..c328eebca7 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -677,7 +677,7 @@ namespace osu.Game.Screens.Select // We are applying a multiplicative alpha (which is internally done by nesting an // additional container and setting that container's alpha) such that we can // layer transformations on top, with a similar reasoning to the previous comment. - p.SetMultiplicativeAlpha(MathHelper.Clamp(1.75f - 1.5f * dist, 0, 1)); + p.SetMultiplicativeAlpha(Math.Clamp(1.75f - 1.5f * dist, 0, 1)); } private class CarouselRoot : CarouselGroupEagerSelect diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index 34297d89a4..121f8efe5a 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -1,7 +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 osuTK; +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Select.Details retryGraph.MaxValue = maxValue; failGraph.Values = fails.Select(f => (float)f); - retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + MathHelper.Clamp(fail, 0, maxValue)); + retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + Math.Clamp(fail, 0, maxValue)); } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index e3cd98454a..a52edb70db 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -46,48 +46,54 @@ namespace osu.Game.Screens.Select protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; - public readonly FilterControl FilterControl; + public FilterControl FilterControl { get; private set; } protected virtual bool ShowFooter => true; /// /// Can be null if is false. /// - protected readonly BeatmapOptionsOverlay BeatmapOptions; + protected BeatmapOptionsOverlay BeatmapOptions { get; private set; } /// /// Can be null if is false. /// - protected readonly Footer Footer; + protected Footer Footer { get; private set; } /// /// Contains any panel which is triggered by a footer button. /// Helps keep them located beneath the footer itself. /// - protected readonly Container FooterPanels; + protected Container FooterPanels { get; private set; } protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); - protected readonly BeatmapCarousel Carousel; - private readonly BeatmapInfoWedge beatmapInfoWedge; + protected BeatmapCarousel Carousel { get; private set; } + + private BeatmapInfoWedge beatmapInfoWedge; private DialogOverlay dialogOverlay; private BeatmapManager beatmaps; - protected readonly ModSelectOverlay ModSelect; + protected ModSelectOverlay ModSelect { get; private set; } + + protected SampleChannel SampleConfirm { get; private set; } - protected SampleChannel SampleConfirm; private SampleChannel sampleChangeDifficulty; private SampleChannel sampleChangeBeatmap; - protected readonly BeatmapDetailArea BeatmapDetails; + protected BeatmapDetailArea BeatmapDetails { get; private set; } private readonly Bindable decoupledRuleset = new Bindable(); [Resolved(canBeNull: true)] private MusicController music { get; set; } - protected SongSelect() + [BackgroundDependencyLoader(true)] + private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { + // initial value transfer is required for FilterControl (it uses our re-cached bindables in its async load for the initial filter). + transferRulesetValue(); + AddRangeInternal(new Drawable[] { new ParallaxContainer @@ -161,7 +167,7 @@ namespace osu.Game.Screens.Select { RelativeSizeAxes = Axes.X, Height = FilterControl.HEIGHT, - FilterChanged = c => Carousel.Filter(c), + FilterChanged = ApplyFilterToCarousel, Background = { Width = 2 }, }, } @@ -211,11 +217,7 @@ namespace osu.Game.Screens.Select } BeatmapDetails.Leaderboard.ScoreSelected += score => this.Push(new SoloResults(score)); - } - [BackgroundDependencyLoader(true)] - private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) - { if (Footer != null) { Footer.AddButton(new FooterButtonMods { Current = Mods }, ModSelect); @@ -258,6 +260,12 @@ namespace osu.Game.Screens.Select } } + protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) + { + if (this.IsCurrentScreen()) + Carousel.Filter(criteria); + } + private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -429,6 +437,8 @@ namespace osu.Game.Screens.Select { base.OnEntering(last); + Carousel.Filter(FilterControl.CreateCriteria(), false); + this.FadeInFromZero(250); FilterControl.Activate(); } @@ -624,7 +634,7 @@ namespace osu.Game.Screens.Select return; // manual binding to parent ruleset to allow for delayed load in the incoming direction. - rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value; + transferRulesetValue(); Ruleset.ValueChanged += r => updateSelectedRuleset(r.NewValue); decoupledRuleset.ValueChanged += r => Ruleset.Value = r.NewValue; @@ -636,6 +646,11 @@ namespace osu.Game.Screens.Select boundLocalBindables = true; } + private void transferRulesetValue() + { + rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value; + } + private void delete(BeatmapSetInfo beatmap) { if (beatmap == null || beatmap.ID <= 0) return; diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 345fff90aa..13e08c7d22 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -22,7 +22,6 @@ using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Tests.Beatmaps; -using osuTK; namespace osu.Game.Tests.Visual { @@ -250,7 +249,7 @@ namespace osu.Game.Tests.Visual public override bool Seek(double seek) { - offset = MathHelper.Clamp(seek, 0, Length); + offset = Math.Clamp(seek, 0, Length); lastReferenceTime = null; return offset == seek; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index af60da3e70..8e3858d0f1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true diff --git a/osu.iOS.props b/osu.iOS.props index 8124357312..6965b16303 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -75,4 +75,17 @@ + + + + + + + + + + + + + From 6cab517b2df2c8296d311a931ed21ddfc8f2c0ca Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Wed, 20 Nov 2019 13:19:49 +0100 Subject: [PATCH 4095/5608] .NET Standard 2.1 implements Math.Clamp , use it instead of MathHelper.Clamp from osuTK. --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 5 ++--- .../Difficulty/CatchPerformanceCalculator.cs | 3 +-- osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs | 3 +-- osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 4 ++-- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 7 +++---- osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs | 3 ++- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 3 ++- .../Objects/Drawables/DrawableSliderHead.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 3 ++- .../Objects/Drawables/Pieces/SnakingSliderBody.cs | 2 +- .../Objects/Drawables/DrawableDrumRoll.cs | 4 ++-- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs | 3 +-- .../UI/TaikoPlayfieldAdjustmentContainer.cs | 3 ++- osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs | 3 ++- osu.Game/Graphics/Containers/ParallaxContainer.cs | 3 ++- osu.Game/Graphics/UserInterface/Bar.cs | 4 ++-- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 4 ++-- osu.Game/Graphics/UserInterface/OsuTabControl.cs | 2 +- osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs | 2 +- osu.Game/Overlays/Music/PlaylistList.cs | 2 +- .../Overlays/Profile/Header/Components/SupporterIcon.cs | 4 ++-- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 3 +-- osu.Game/Rulesets/Objects/SliderEventGenerator.cs | 3 +-- osu.Game/Rulesets/Objects/SliderPath.cs | 2 +- osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs | 3 +-- .../UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs | 4 ++-- .../Edit/Components/Timelines/Summary/Parts/MarkerPart.cs | 3 ++- .../Edit/Compose/Components/CircularDistanceSnapGrid.cs | 2 +- .../Compose/Components/Timeline/ZoomableScrollContainer.cs | 4 ++-- osu.Game/Screens/Edit/EditorClock.cs | 3 +-- osu.Game/Screens/Menu/Button.cs | 2 +- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 4 ++-- osu.Game/Screens/Play/SongProgressBar.cs | 2 +- osu.Game/Screens/Play/SquareGraph.cs | 2 +- osu.Game/Screens/ScreenWhiteBox.cs | 6 +++--- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- osu.Game/Screens/Select/Details/FailRetryGraph.cs | 4 ++-- osu.Game/Tests/Visual/OsuTestScene.cs | 3 +-- 42 files changed, 65 insertions(+), 68 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 58bf811fac..db52fbac1b 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -8,7 +8,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects.Types; -using osuTK; using osu.Game.Rulesets.Catch.MathUtils; using osu.Game.Rulesets.Mods; @@ -78,7 +77,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps catchObject.XOffset = 0; if (catchObject is TinyDroplet) - catchObject.XOffset = MathHelper.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); + catchObject.XOffset = Math.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); else if (catchObject is Droplet) rng.Next(); // osu!stable retrieved a random droplet rotation } @@ -230,7 +229,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps else { currentObject.DistanceToHyperDash = distanceToHyper; - lastExcess = MathHelper.Clamp(distanceToHyper, 0, halfCatcherWidth); + lastExcess = Math.Clamp(distanceToHyper, 0, halfCatcherWidth); } lastDirection = thisDirection; diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index 5a640f6d1a..a7f0d358ed 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Scoring.Legacy; -using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty { @@ -96,7 +95,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty return value; } - private float accuracy() => totalHits() == 0 ? 0 : MathHelper.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); + private float accuracy() => totalHits() == 0 ? 0 : Math.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed; private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit; private int totalComboHits() => misses + ticksHit + fruitsHit; diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index d146153294..7cd569035b 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -6,7 +6,6 @@ using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; -using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty.Skills { @@ -31,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills if (lastPlayerPosition == null) lastPlayerPosition = catchCurrent.LastNormalizedPosition; - float playerPosition = MathHelper.Clamp( + float playerPosition = Math.Clamp( lastPlayerPosition.Value, catchCurrent.NormalizedPosition - (normalized_hitobject_radius - absolute_player_positioning_error), catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 1af77b75fc..eae652573b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -278,7 +278,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { base.Update(); - border.Alpha = (float)MathHelper.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); + border.Alpha = (float)Math.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); } private Color4 colourForRepresentation(FruitVisualRepresentation representation) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 56c8b33e02..d330add1c4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -235,7 +235,7 @@ namespace osu.Game.Rulesets.Catch.UI fruit.Y -= RNG.NextSingle() * diff; } - fruit.X = MathHelper.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); + fruit.X = Math.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); caughtFruit.Add(fruit); } @@ -378,7 +378,7 @@ namespace osu.Game.Rulesets.Catch.UI double speed = BASE_SPEED * dashModifier * hyperDashModifier; Scale = new Vector2(Math.Abs(Scale.X) * direction, Scale.Y); - X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); + X = (float)Math.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); // Correct overshooting. if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index f989f22298..b9984a8b90 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -7,7 +7,6 @@ using JetBrains.Annotations; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Objects; -using osuTK; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { @@ -54,11 +53,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (allowSpecial && TotalColumns == 8) { const float local_x_divisor = 512f / 7; - return MathHelper.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; + return Math.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; } float localXDivisor = 512f / TotalColumns; - return MathHelper.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); + return Math.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); } /// @@ -113,7 +112,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy drainTime = 10000; BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty; - conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; + conversionDifficulty = ((difficulty.DrainRate + Math.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; conversionDifficulty = Math.Min(conversionDifficulty.Value, 12); return conversionDifficulty.Value; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 9cdf045b5b..53f7e30dfd 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.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.Linq; using osu.Framework.Allocation; using osu.Framework.Timing; @@ -9,7 +10,6 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit.Compose.Components; -using osuTK; namespace osu.Game.Rulesets.Mania.Edit { @@ -119,7 +119,7 @@ namespace osu.Game.Rulesets.Mania.Edit maxColumn = obj.Column; } - columnDelta = MathHelper.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); + columnDelta = Math.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); foreach (var obj in SelectedHitObjects.OfType()) obj.Column += columnDelta; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 1eb37f8119..63110b2797 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,7 +14,6 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Mods }; } - private float calculateGap(float value) => MathHelper.Clamp(value, 0, target_clamp) * targetBreakMultiplier; + private float calculateGap(float value) => Math.Clamp(value, 0, target_clamp) * targetBreakMultiplier; // lagrange polinominal for (0,0) (0.6,0.4) (1,1) should make a good curve private static float applyAdjustmentCurve(float value) => 0.6f * value * value + 0.4f * value; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 7fa3dbe07e..778c2f7d43 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; @@ -55,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Mods var destination = e.MousePosition; FlashlightPosition = Interpolation.ValueAt( - MathHelper.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); + Math.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); return base.OnMouseMove(e); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 84d2a4af9b..122975d55e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables else { // If we're already snaking, interpolate to smooth out sharp curves (linear sliders, mainly). - Rotation = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint); + Rotation = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 433d29f2e4..69189758a6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.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 osuTK; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; @@ -165,7 +166,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Tracking.Value = Ball.Tracking; - double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); Ball.UpdateProgress(completionProgress); Body.UpdateProgress(completionProgress); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index 66b6f0f9ac..a10c66d1df 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.Update(); - double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); //todo: we probably want to reconsider this before adding scoring, but it looks and feels nice. if (!IsHit) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index d1b9ee6cb4..1261d3d19a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.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.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -136,7 +137,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindTo(HitObject.PositionBindable); } - public float Progress => MathHelper.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); + public float Progress => Math.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); protected override void CheckForResult(bool userTriggered, double timeOffset) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index 70a1bad4a3..f2150280b3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces var spanProgress = slider.ProgressAt(completionProgress); double start = 0; - double end = SnakingIn.Value ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; + double end = SnakingIn.Value ? Math.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; if (span >= slider.SpanCount() - 1) { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index cc0d6829ba..338fd9e20f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.MathUtils; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osuTK; using osuTK.Graphics; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Framework.Graphics; @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables else rollingHits--; - rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); + rollingHits = Math.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1); MainPiece.FadeAccent(newColour, 100); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 9c9dfc5f9e..fa39819199 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Objects; @@ -179,7 +178,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables var completion = (float)numHits / HitObject.RequiredHits; expandingRing - .FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50) + .FadeTo(expandingRing.Alpha + Math.Clamp(completion / 16, 0.1f, 0.6f), 50) .Then() .FadeTo(completion / 8, 2000, Easing.OutQuint); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 84464b199e..980f5ea340 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Game.Rulesets.UI; using osuTK; @@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.UI { base.Update(); - float aspectAdjust = MathHelper.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; + float aspectAdjust = Math.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; Size = new Vector2(1, default_relative_height * aspectAdjust); } } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index f613ce5f46..724612ebce 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; @@ -32,7 +33,7 @@ namespace osu.Game.Tournament.Screens.Ladder protected override bool OnScroll(ScrollEvent e) { - var newScale = MathHelper.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); + var newScale = Math.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); this.MoveTo(target = target - e.MousePosition * (newScale - scale), 2000, Easing.OutQuint); this.ScaleTo(scale = newScale, 2000, Easing.OutQuint); diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index 86f922e4b8..f8c21eabc2 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Input; @@ -71,7 +72,7 @@ namespace osu.Game.Graphics.Containers const float parallax_duration = 100; - double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); + double elapsed = Math.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, parallax_duration, Easing.OutQuint); content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); diff --git a/osu.Game/Graphics/UserInterface/Bar.cs b/osu.Game/Graphics/UserInterface/Bar.cs index f8d5955503..0be928cf83 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using System; namespace osu.Game.Graphics.UserInterface { @@ -29,7 +29,7 @@ namespace osu.Game.Graphics.UserInterface get => length; set { - length = MathHelper.Clamp(value, 0, 1); + length = Math.Clamp(value, 0, 1); updateBarLength(); } } diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 11aba80d76..7412224f6c 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -175,9 +175,9 @@ namespace osu.Game.Graphics.UserInterface protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - leftBox.Scale = new Vector2(MathHelper.Clamp( + leftBox.Scale = new Vector2(Math.Clamp( Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); - rightBox.Scale = new Vector2(MathHelper.Clamp( + rightBox.Scale = new Vector2(Math.Clamp( DrawWidth - Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); } diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 585a46f3e1..064cba6adf 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -99,7 +99,7 @@ namespace osu.Game.Graphics.UserInterface // dont bother calculating if the strip is invisible if (strip.Colour.MaxAlpha > 0) - strip.Width = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); + strip.Width = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); } public class OsuTabItem : TabItem, IHasAccentColour diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 8b88d81b88..583db460f4 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -99,7 +99,7 @@ namespace osu.Game.Overlays.Chat.Tabs private void tabCloseRequested(TabItem tab) { int totalTabs = TabContainer.Count - 1; // account for selectorTab - int currentIndex = MathHelper.Clamp(TabContainer.IndexOf(tab), 1, totalTabs); + int currentIndex = Math.Clamp(TabContainer.IndexOf(tab), 1, totalTabs); if (tab == SelectedTab && totalTabs > 1) // Select the tab after tab-to-be-removed's index, or the tab before if current == last diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index e3acd31626..83528298b1 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -217,7 +217,7 @@ namespace osu.Game.Overlays.Music break; } - dstIndex = MathHelper.Clamp(dstIndex, 0, items.Count - 1); + dstIndex = Math.Clamp(dstIndex, 0, items.Count - 1); if (srcIndex == dstIndex) return; diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index fa60a37ddb..d581e2750c 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -8,7 +9,6 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { set { - int count = MathHelper.Clamp(value, 0, 3); + int count = Math.Clamp(value, 0, 3); if (count == 0) { diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 9edf57ad00..f217512965 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -9,7 +9,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; -using osuTK; namespace osu.Game.Rulesets.Mods { @@ -59,7 +58,7 @@ namespace osu.Game.Rulesets.Mods /// The amount of adjustment to apply (from 0..1). private void applyAdjustment(double amount) { - double adjust = 1 + (Math.Sign(FinalRateAdjustment) * MathHelper.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); + double adjust = 1 + (Math.Sign(FinalRateAdjustment) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); switch (clock) { diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs index 0d8796b4cb..e9ee3833b7 100644 --- a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using osuTK; namespace osu.Game.Rulesets.Objects { @@ -18,7 +17,7 @@ namespace osu.Game.Rulesets.Objects const double max_length = 100000; var length = Math.Min(max_length, totalDistance); - tickDistance = MathHelper.Clamp(tickDistance, 0, length); + tickDistance = Math.Clamp(tickDistance, 0, length); var minDistanceFromEnd = velocity * 10; diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 7763b0eaaf..e8ef16e825 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -246,7 +246,7 @@ namespace osu.Game.Rulesets.Objects private double progressToDistance(double progress) { - return MathHelper.Clamp(progress, 0, 1) * Distance; + return Math.Clamp(progress, 0, 1) * Distance; } private Vector2 interpolateVertices(int i, double d) diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 4c011388fa..7e17396fde 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -7,7 +7,6 @@ using JetBrains.Annotations; using osu.Framework.Input.StateChanges; using osu.Game.Input.Handlers; using osu.Game.Replays; -using osuTK; namespace osu.Game.Rulesets.Replays { @@ -52,7 +51,7 @@ namespace osu.Game.Rulesets.Replays private int? currentFrameIndex; - private int nextFrameIndex => currentFrameIndex.HasValue ? MathHelper.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; + private int nextFrameIndex => currentFrameIndex.HasValue ? Math.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; protected FramedReplayInputHandler(Replay replay) { diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs index 5316585493..fe22a86fad 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs @@ -1,9 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Lists; using osu.Game.Rulesets.Timing; -using osuTK; namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms } } - i = MathHelper.Clamp(i, 0, controlPoints.Count - 1); + i = Math.Clamp(i, 0, controlPoints.Count - 1); return controlPoints[i].StartTime + (position - pos) * timeRange / controlPoints[i].Multiplier / scrollLength; } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index 07d307f293..79ada40a89 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.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 osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -59,7 +60,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts if (Beatmap.Value == null) return; - float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); + float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); adjustableClock.Seek(markerPos / DrawWidth * Beatmap.Value.Track.Length); }); } diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 0f2bae6305..fc7d51db4b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Edit.Compose.Components float distance = direction.Length; float radius = DistanceSpacing; - int radialCount = MathHelper.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); + int radialCount = Math.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); Vector2 normalisedDirection = direction * new Vector2(1f / distance); Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index cffb6bedf3..54922fec5e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline get => zoomTarget; set { - value = MathHelper.Clamp(value, MinZoom, MaxZoom); + value = Math.Clamp(value, MinZoom, MaxZoom); if (IsLoaded) setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); @@ -117,7 +117,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void setZoomTarget(float newZoom, float focusPoint) { - zoomTarget = MathHelper.Clamp(newZoom, MinZoom, MaxZoom); + zoomTarget = Math.Clamp(newZoom, MinZoom, MaxZoom); transformZoomTo(zoomTarget, focusPoint, ZoomDuration, ZoomEasing); } diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index bd2db4ae2b..93a5f19121 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -7,7 +7,6 @@ using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osuTK; namespace osu.Game.Screens.Edit { @@ -125,7 +124,7 @@ namespace osu.Game.Screens.Edit seekTime = nextTimingPoint.Time; // Ensure the sought point is within the boundaries - seekTime = MathHelper.Clamp(seekTime, 0, TrackLength); + seekTime = Math.Clamp(seekTime, 0, TrackLength); Seek(seekTime); } } diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index ffeadb96c7..fac6b69e1f 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -236,7 +236,7 @@ namespace osu.Game.Screens.Menu protected override void Update() { - iconText.Alpha = MathHelper.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1); + iconText.Alpha = Math.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1); base.Update(); } diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 968b83e68c..640224c057 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -102,8 +102,8 @@ namespace osu.Game.Screens.Play.HUD else { Alpha = Interpolation.ValueAt( - MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 200), - Alpha, MathHelper.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); + Math.Clamp(Clock.ElapsedFrameTime, 0, 200), + Alpha, Math.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); } } diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index 33c7595b37..cdf495e257 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -116,7 +116,7 @@ namespace osu.Game.Screens.Play { base.Update(); - float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, MathHelper.Clamp(Time.Elapsed / 40, 0, 1)); + float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Math.Clamp(Time.Elapsed / 40, 0, 1)); fill.Width = newX; handleBase.X = newX; diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 05f6128ac2..715ba3c065 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -256,7 +256,7 @@ namespace osu.Game.Screens.Play { Color4 colour = State == ColumnState.Lit ? LitColour : DimmedColour; - int countFilled = (int)MathHelper.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); + int countFilled = (int)Math.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); for (int i = 0; i < drawableRows.Count; i++) drawableRows[i].Colour = i < countFilled ? colour : EmptyColour; diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index e4971221c4..3d8fd5dad7 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -87,9 +87,9 @@ namespace osu.Game.Screens private static Color4 getColourFor(object type) { int hash = type.GetHashCode(); - byte r = (byte)MathHelper.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); - byte g = (byte)MathHelper.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); - byte b = (byte)MathHelper.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); + byte r = (byte)Math.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); + byte g = (byte)Math.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); + byte b = (byte)Math.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); return new Color4(r, g, b, 255); } diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index fa0ca3d9b3..c328eebca7 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -677,7 +677,7 @@ namespace osu.Game.Screens.Select // We are applying a multiplicative alpha (which is internally done by nesting an // additional container and setting that container's alpha) such that we can // layer transformations on top, with a similar reasoning to the previous comment. - p.SetMultiplicativeAlpha(MathHelper.Clamp(1.75f - 1.5f * dist, 0, 1)); + p.SetMultiplicativeAlpha(Math.Clamp(1.75f - 1.5f * dist, 0, 1)); } private class CarouselRoot : CarouselGroupEagerSelect diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index 34297d89a4..121f8efe5a 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -1,7 +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 osuTK; +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Select.Details retryGraph.MaxValue = maxValue; failGraph.Values = fails.Select(f => (float)f); - retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + MathHelper.Clamp(fail, 0, maxValue)); + retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + Math.Clamp(fail, 0, maxValue)); } } diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 345fff90aa..13e08c7d22 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -22,7 +22,6 @@ using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Tests.Beatmaps; -using osuTK; namespace osu.Game.Tests.Visual { @@ -250,7 +249,7 @@ namespace osu.Game.Tests.Visual public override bool Seek(double seek) { - offset = MathHelper.Clamp(seek, 0, Length); + offset = Math.Clamp(seek, 0, Length); lastReferenceTime = null; return offset == seek; From 66a3837ff4fe6c0cea4b12bb37f344885badf1ee Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Wed, 20 Nov 2019 14:25:44 +0100 Subject: [PATCH 4096/5608] Fix CI --- osu.Game/Graphics/Containers/ParallaxContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index f8c21eabc2..bf743b90ed 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -49,7 +49,7 @@ namespace osu.Game.Graphics.Containers if (!parallaxEnabled.Value) { content.MoveTo(Vector2.Zero, firstUpdate ? 0 : 1000, Easing.OutQuint); - content.Scale = new Vector2(1 + System.Math.Abs(ParallaxAmount)); + content.Scale = new Vector2(1 + Math.Abs(ParallaxAmount)); } }; } @@ -75,7 +75,7 @@ namespace osu.Game.Graphics.Containers double elapsed = Math.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, parallax_duration, Easing.OutQuint); - content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); + content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); } firstUpdate = false; From e820ddd3e8c34da3b6f3d292062340942274589d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 20 Nov 2019 19:27:34 +0300 Subject: [PATCH 4097/5608] Implement settings keywords --- .../Settings/Sections/Audio/AudioDevicesSettings.cs | 5 ++++- .../Overlays/Settings/Sections/Audio/VolumeSettings.cs | 2 ++ .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 1 + .../Overlays/Settings/Sections/Gameplay/ModsSettings.cs | 3 ++- .../Settings/Sections/Gameplay/SongSelectSettings.cs | 7 +++++-- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 4 +++- .../Settings/Sections/Graphics/RendererSettings.cs | 2 ++ osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs | 6 ++++-- osu.Game/Overlays/Settings/SettingsItem.cs | 7 ++++++- osu.Game/Overlays/Settings/SettingsSubsection.cs | 7 ++++++- 10 files changed, 35 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index 2c25808170..e9ae784061 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -60,7 +60,10 @@ namespace osu.Game.Overlays.Settings.Sections.Audio Children = new Drawable[] { - dropdown = new AudioDeviceSettingsDropdown() + dropdown = new AudioDeviceSettingsDropdown + { + Keywords = new[] { "Speaker" } + } }; updateItems(); diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 0124f7090e..c297f694c0 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -22,6 +22,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio new SettingsSlider { LabelText = "Effect", Bindable = audio.VolumeSample, KeyboardStep = 0.01f }, new SettingsSlider { LabelText = "Music", Bindable = audio.VolumeTrack, KeyboardStep = 0.01f }, }; + + Keywords = new[] { "Sound" }; } } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 520a8852b3..3ebfae05b2 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -38,6 +38,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show health display even when you can't fail", Bindable = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), + Keywords = new[] { "bar" } }, new SettingsCheckbox { diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index 2c6b2663c6..06d120762b 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -18,7 +18,8 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay new SettingsCheckbox { LabelText = "Increase visibility of first object when visual impairment mods are enabled", - Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility) + Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility), + Keywords = new[] { "Hidden", "Traceable" } }, }; } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs index 3e2272dba6..fce0e3dea8 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs @@ -26,18 +26,21 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show converted beatmaps", Bindable = config.GetBindable(OsuSetting.ShowConvertedBeatmaps), + Keywords = new[] { "Converts" } }, new SettingsSlider { LabelText = "Display beatmaps from", Bindable = config.GetBindable(OsuSetting.DisplayStarsMinimum), - KeyboardStep = 0.1f + KeyboardStep = 0.1f, + Keywords = new[] { "Stars" } }, new SettingsSlider { LabelText = "up to", Bindable = config.GetBindable(OsuSetting.DisplayStarsMaximum), - KeyboardStep = 0.1f + KeyboardStep = 0.1f, + Keywords = new[] { "Stars" } }, new SettingsEnumDropdown { diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index f4de4c0c41..8275d6dc0a 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -75,12 +75,14 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics LabelText = "UI Scaling", TransferValueOnCommit = true, Bindable = osuConfig.GetBindable(OsuSetting.UIScale), - KeyboardStep = 0.01f + KeyboardStep = 0.01f, + Keywords = new[] { "Scale" }, }, new SettingsEnumDropdown { LabelText = "Screen Scaling", Bindable = osuConfig.GetBindable(OsuSetting.Scaling), + Keywords = new[] { "Scale" }, }, scalingSettings = new FillFlowContainer> { diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 7317076c54..1aee9a8efe 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -30,6 +30,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Bindable = osuConfig.GetBindable(OsuSetting.ShowFpsDisplay) }, }; + + Keywords = new[] { "fps" }; } } } diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index 4f2f3dfd1a..f1071314c6 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -27,12 +27,14 @@ namespace osu.Game.Overlays.Settings.Sections.Input new SettingsCheckbox { LabelText = "Raw input", - Bindable = rawInputToggle + Bindable = rawInputToggle, + Keywords = new[] { "Speed" } }, sensitivity = new SensitivitySetting { LabelText = "Cursor sensitivity", - Bindable = config.GetBindable(FrameworkSetting.CursorSensitivity) + Bindable = config.GetBindable(FrameworkSetting.CursorSensitivity), + Keywords = new[] { "Speed" } }, new SettingsCheckbox { diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index d48c0b6b66..9a50185e11 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -76,7 +76,12 @@ namespace osu.Game.Overlays.Settings } } - public virtual IEnumerable FilterTerms => new[] { LabelText }; + public virtual IEnumerable FilterTerms => Keywords == null ? new[] { LabelText } : new List(Keywords) + { + LabelText + }.ToArray(); + + public IEnumerable Keywords { get; set; } public bool MatchingFilter { diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index c9c763e8d4..0023888b91 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -21,7 +21,12 @@ namespace osu.Game.Overlays.Settings protected abstract string Header { get; } public IEnumerable FilterableChildren => Children.OfType(); - public IEnumerable FilterTerms => new[] { Header }; + public virtual IEnumerable FilterTerms => Keywords == null ? new[] { Header } : new List(Keywords) + { + Header + }.ToArray(); + + public IEnumerable Keywords { get; set; } public bool MatchingFilter { From 7d8252183eed2a85ef2a0ee89615fcff9d8c1cb2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 20 Nov 2019 19:42:57 +0300 Subject: [PATCH 4098/5608] CI fix --- osu.Game/Overlays/Settings/SettingsItem.cs | 5 +---- osu.Game/Overlays/Settings/SettingsSubsection.cs | 6 ++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 9a50185e11..8863e43cca 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -76,10 +76,7 @@ namespace osu.Game.Overlays.Settings } } - public virtual IEnumerable FilterTerms => Keywords == null ? new[] { LabelText } : new List(Keywords) - { - LabelText - }.ToArray(); + public virtual IEnumerable FilterTerms => Keywords == null ? new[] { LabelText } : new List(Keywords) { LabelText }.ToArray(); public IEnumerable Keywords { get; set; } diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 0023888b91..15f20d252c 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -21,10 +21,8 @@ namespace osu.Game.Overlays.Settings protected abstract string Header { get; } public IEnumerable FilterableChildren => Children.OfType(); - public virtual IEnumerable FilterTerms => Keywords == null ? new[] { Header } : new List(Keywords) - { - Header - }.ToArray(); + + public virtual IEnumerable FilterTerms => Keywords == null ? new[] { Header } : new List(Keywords) { Header }.ToArray(); public IEnumerable Keywords { get; set; } From f3d9abc84aa1226c56f85861682e23cfd4a2eac3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 20 Nov 2019 19:57:02 +0300 Subject: [PATCH 4099/5608] Capitalize Bar for consistency --- osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 3ebfae05b2..ad9f3eec68 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show health display even when you can't fail", Bindable = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), - Keywords = new[] { "bar" } + Keywords = new[] { "Bar" } }, new SettingsCheckbox { From 6b3010535fc289d2e5d1cd0c7836302e78122911 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 20 Nov 2019 21:03:31 +0300 Subject: [PATCH 4100/5608] Simplify Keywords usage for SettingsSubsection --- osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs | 6 ++++-- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 6 ++++-- osu.Game/Overlays/Settings/SettingsSubsection.cs | 5 +---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index c297f694c0..7bfec0fad8 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; @@ -12,6 +14,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { protected override string Header => "Volume"; + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "Sound" }); + [BackgroundDependencyLoader] private void load(AudioManager audio, OsuConfigManager config) { @@ -22,8 +26,6 @@ namespace osu.Game.Overlays.Settings.Sections.Audio new SettingsSlider { LabelText = "Effect", Bindable = audio.VolumeSample, KeyboardStep = 0.01f }, new SettingsSlider { LabelText = "Music", Bindable = audio.VolumeTrack, KeyboardStep = 0.01f }, }; - - Keywords = new[] { "Sound" }; } } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 1aee9a8efe..92f4823142 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -12,6 +14,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { protected override string Header => "Renderer"; + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "FPS" }); + [BackgroundDependencyLoader] private void load(FrameworkConfigManager config, OsuConfigManager osuConfig) { @@ -30,8 +34,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Bindable = osuConfig.GetBindable(OsuSetting.ShowFpsDisplay) }, }; - - Keywords = new[] { "fps" }; } } } diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 15f20d252c..9b3b2f570c 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -21,10 +21,7 @@ namespace osu.Game.Overlays.Settings protected abstract string Header { get; } public IEnumerable FilterableChildren => Children.OfType(); - - public virtual IEnumerable FilterTerms => Keywords == null ? new[] { Header } : new List(Keywords) { Header }.ToArray(); - - public IEnumerable Keywords { get; set; } + public virtual IEnumerable FilterTerms => new[] { Header }; public bool MatchingFilter { From f066d8434cafcce2335518085b3d212933bc3e0d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 00:26:39 +0300 Subject: [PATCH 4101/5608] Apply suggestions --- osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs | 4 ---- osu.Game/Overlays/Settings/Sections/AudioSection.cs | 5 +++++ .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- .../Overlays/Settings/Sections/Gameplay/ModsSettings.cs | 2 +- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 4 ---- osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs | 6 ++---- osu.Game/Overlays/Settings/SettingsSection.cs | 2 +- 7 files changed, 10 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 7bfec0fad8..0124f7090e 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; @@ -14,8 +12,6 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { protected override string Header => "Volume"; - public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "Sound" }); - [BackgroundDependencyLoader] private void load(AudioManager audio, OsuConfigManager config) { diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index 7ca313a751..254af6ea21 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Settings.Sections.Audio; @@ -10,6 +12,9 @@ namespace osu.Game.Overlays.Settings.Sections public class AudioSection : SettingsSection { public override string Header => "Audio"; + + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "Sound" }); + public override IconUsage Icon => FontAwesome.Solid.VolumeUp; public AudioSection() diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index ad9f3eec68..0ac145ffe2 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show health display even when you can't fail", Bindable = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), - Keywords = new[] { "Bar" } + Keywords = new[] { "Bar", "Hp" } }, new SettingsCheckbox { diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index 06d120762b..a71919a2fc 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Increase visibility of first object when visual impairment mods are enabled", Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility), - Keywords = new[] { "Hidden", "Traceable" } + Keywords = new[] { "Mod" } }, }; } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 92f4823142..7317076c54 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -14,8 +12,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { protected override string Header => "Renderer"; - public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "FPS" }); - [BackgroundDependencyLoader] private void load(FrameworkConfigManager config, OsuConfigManager osuConfig) { diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index f1071314c6..4f2f3dfd1a 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -27,14 +27,12 @@ namespace osu.Game.Overlays.Settings.Sections.Input new SettingsCheckbox { LabelText = "Raw input", - Bindable = rawInputToggle, - Keywords = new[] { "Speed" } + Bindable = rawInputToggle }, sensitivity = new SensitivitySetting { LabelText = "Cursor sensitivity", - Bindable = config.GetBindable(FrameworkSetting.CursorSensitivity), - Keywords = new[] { "Speed" } + Bindable = config.GetBindable(FrameworkSetting.CursorSensitivity) }, new SettingsCheckbox { diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index c878a9fc65..be3696029e 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Settings public abstract string Header { get; } public IEnumerable FilterableChildren => Children.OfType(); - public IEnumerable FilterTerms => new[] { Header }; + public virtual IEnumerable FilterTerms => new[] { Header }; private const int header_size = 26; private const int header_margin = 25; From 4a4f5ccbb2ecb5adee902922c3d6d43fe3bd7ac5 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 21 Nov 2019 02:35:58 +0300 Subject: [PATCH 4102/5608] Implement IAggregateAudioAdjustments properties for FallbackSampleStore --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index d1749d33c0..bb8149a57d 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -517,6 +517,12 @@ namespace osu.Game.Rulesets.UI public BindableDouble Frequency => throw new NotImplementedException(); + public IBindable AggregateVolume => throw new NotImplementedException(); + + public IBindable AggregateBalance => throw new NotImplementedException(); + + public IBindable AggregateFrequency => throw new NotImplementedException(); + public int PlaybackConcurrency { get => throw new NotImplementedException(); From ebae92db7b2fcafb6ce94f8f81f56af1b7b8d897 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 21 Nov 2019 03:18:31 +0300 Subject: [PATCH 4103/5608] Revert "Implement IAggregateAudioAdjustments properties for FallbackSampleStore" This reverts commit 4a4f5ccbb2ecb5adee902922c3d6d43fe3bd7ac5. --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index bb8149a57d..d1749d33c0 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -517,12 +517,6 @@ namespace osu.Game.Rulesets.UI public BindableDouble Frequency => throw new NotImplementedException(); - public IBindable AggregateVolume => throw new NotImplementedException(); - - public IBindable AggregateBalance => throw new NotImplementedException(); - - public IBindable AggregateFrequency => throw new NotImplementedException(); - public int PlaybackConcurrency { get => throw new NotImplementedException(); From 5391c752b4e896b44ca8782dd6c795d4c57dc447 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 21 Nov 2019 02:35:58 +0300 Subject: [PATCH 4104/5608] Implement IAggregateAudioAdjustments properties for FallbackSampleStore --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index aec0e58a10..e0aeff8330 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -517,6 +517,12 @@ namespace osu.Game.Rulesets.UI public BindableDouble Frequency => throw new NotImplementedException(); + public IBindable AggregateVolume => throw new NotImplementedException(); + + public IBindable AggregateBalance => throw new NotImplementedException(); + + public IBindable AggregateFrequency => throw new NotImplementedException(); + public int PlaybackConcurrency { get => throw new NotImplementedException(); From 76e63722cc51cb0a683fefab2b946198b4aa46a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 10:26:10 +0900 Subject: [PATCH 4105/5608] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 6fab2e7868..cd317b76f4 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 af60da3e70..515edf6f9d 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 8124357312..9ea6576957 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,6 +73,6 @@ - + From be62e482964c08479d13d173793ad95ec57cf6a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 10:35:10 +0900 Subject: [PATCH 4106/5608] Fix tests not working if main or audio volume is zero --- .../Visual/Components/TestScenePreviewTrackManager.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 5dac40104a..d76905dab8 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -143,6 +143,17 @@ namespace osu.Game.Tests.Visual.Components PreviewTrack track = null; TestTrackOwner owner = null; + AddStep("ensure volume not zero", () => + { + if (audio.Volume.Value == 0) + audio.Volume.Value = 1; + + if (audio.VolumeTrack.Value == 0) + audio.VolumeTrack.Value = 1; + }); + + AddAssert("game not muted", () => audio.Tracks.AggregateVolume.Value != 0); + AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack()))); AddUntilStep("wait loaded", () => track.IsLoaded); AddStep("start track", () => track.Start()); From cf0f0f8a1bf534f7bfaab3a2c69a502143311f6e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 10:37:50 +0900 Subject: [PATCH 4107/5608] Reword comment --- osu.Game/Audio/PreviewTrackManager.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index d85df42d2b..6f0b62543d 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -80,8 +80,7 @@ namespace osu.Game.Audio return; CurrentTrack.Stop(); - // CurrentTrack must not change until the scheduled stopped event has been invoked. - // To ensure that this doesn't early-return on (CurrentTrack != track) check. + // CurrentTrack should not be set to null here as it will result in incorrect handling in the track.Stopped callback above. } /// From 19dfbb0a45ba3a208ad34ba6b0e6b1507e3e605e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 10:55:31 +0900 Subject: [PATCH 4108/5608] Update obsolete usages --- osu.Game/Online/API/APIAccess.cs | 2 +- osu.Game/Online/API/APIRequest.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index d722c7a98a..b6127027cc 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -227,7 +227,7 @@ namespace osu.Game.Online.API { try { - return JObject.Parse(req.ResponseString).SelectToken("form_error", true).ToObject(); + return JObject.Parse(req.GetResponseString()).SelectToken("form_error", true).ToObject(); } catch { diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index ea0d50511f..53b23f5922 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -113,7 +113,7 @@ namespace osu.Game.Online.API cancelled = true; WebRequest?.Abort(); - string responseString = WebRequest?.ResponseString; + string responseString = WebRequest?.GetResponseString(); if (!string.IsNullOrEmpty(responseString)) { From 0cbe29dbecb7ab231480726edc515e33955ea313 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 21 Nov 2019 11:05:18 +0900 Subject: [PATCH 4109/5608] Refactor / cleanup debouncing --- .../Multi/Lounge/Components/FilterControl.cs | 11 +++++++++- .../Multi/Lounge/Components/RoomsContainer.cs | 20 +++---------------- osu.Game/Screens/Multi/RoomManager.cs | 11 +--------- 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index d0d983bbff..1f92806fbb 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Overlays.SearchableList; using osuTK.Graphics; @@ -37,10 +38,18 @@ namespace osu.Game.Screens.Multi.Lounge.Components { base.LoadComplete(); - Search.Current.BindValueChanged(_ => updateFilter()); + Search.Current.BindValueChanged(_ => scheduleUpdateFilter()); Tabs.Current.BindValueChanged(_ => updateFilter(), true); } + private ScheduledDelegate scheduledFilterUpdate; + + private void scheduleUpdateFilter() + { + scheduledFilterUpdate?.Cancel(); + scheduledFilterUpdate = Scheduler.AddDelayed(updateFilter, 200); + } + private void updateFilter() { filter.Value = new FilterCriteria diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 3dde9452e4..607b081653 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -9,7 +9,6 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Threading; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osuTK; @@ -63,10 +62,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components protected override void LoadComplete() { - filter?.BindValueChanged(f => scheduleFilter()); - - if (filter != null) - Filter(filter.Value); + filter?.BindValueChanged(f => Filter(f.NewValue), true); } public void Filter(FilterCriteria criteria) @@ -93,23 +89,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components }); } - private ScheduledDelegate scheduledFilter; - - private void scheduleFilter() - { - if (filter == null) - return; - - scheduledFilter?.Cancel(); - scheduledFilter = Scheduler.AddDelayed(() => Filter(filter.Value), 200); - } - private void addRooms(IEnumerable rooms) { foreach (var r in rooms) roomFlow.Add(new DrawableRoom(r) { Action = () => selectRoom(r) }); - filter?.TriggerChange(); + if (filter != null) + Filter(filter.Value); } private void removeRooms(IEnumerable rooms) diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index d6d3ec37ef..cdaba85b9e 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Logging; -using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Online; using osu.Game.Online.API; @@ -45,7 +44,7 @@ namespace osu.Game.Screens.Multi currentFilter.BindValueChanged(_ => { if (IsLoaded) - schedulePoll(); + PollImmediately(); }); } @@ -158,14 +157,6 @@ namespace osu.Game.Screens.Multi return tcs.Task; } - private ScheduledDelegate scheduledPoll; - - private void schedulePoll() - { - scheduledPoll?.Cancel(); - scheduledPoll = Scheduler.AddDelayed(PollImmediately, 200); - } - /// /// Updates a local with a remote copy. /// From 2325f0382ca4413059b2ec68a1f0db4eb34b8dda Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 13:46:45 +0900 Subject: [PATCH 4110/5608] Cancel a potentially pending filter update when an update occurs --- osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index 1f92806fbb..29d41132a7 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -52,6 +52,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components private void updateFilter() { + scheduledFilterUpdate?.Cancel(); + filter.Value = new FilterCriteria { SearchString = Search.Current.Value ?? string.Empty, From 8369be90f20842c6b9a6aaf4eba5a4671c0c2915 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 15:19:06 +0900 Subject: [PATCH 4111/5608] Allow skip button to actuate more than once --- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 13 +--------- .../Screens/Play/GameplayClockContainer.cs | 26 ++++++++++++++++--- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Play/SkipOverlay.cs | 20 +++----------- 4 files changed, 29 insertions(+), 32 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index b152c21454..0d62d9a520 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual.Gameplay { skip = new SkipOverlay(6000) { - RequestSeek = _ => requestCount++ + RequestSkip = () => requestCount++ } }, }; @@ -60,17 +60,6 @@ namespace osu.Game.Tests.Visual.Gameplay checkRequestCount(1); } - [Test] - public void TestClickOnlyActuatesOnce() - { - AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); - AddStep("click", () => InputManager.Click(MouseButton.Left)); - AddStep("click", () => InputManager.Click(MouseButton.Left)); - AddStep("click", () => InputManager.Click(MouseButton.Left)); - AddStep("click", () => InputManager.Click(MouseButton.Left)); - checkRequestCount(1); - } - [Test] public void TestDoesntFadeOnMouseDown() { diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 671711f5a4..e1f4d8fa94 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -89,6 +89,11 @@ namespace osu.Game.Screens.Play private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset; + /// + /// Duration before gameplay start time required before skip button displays. + /// + public const double MINIMUM_SKIP_TIME = 1000; + private readonly BindableDouble pauseFreqAdjust = new BindableDouble(1); [BackgroundDependencyLoader] @@ -104,11 +109,9 @@ namespace osu.Game.Screens.Play startTime = Math.Min(startTime, 0); Seek(startTime); + adjustableClock.ProcessFrame(); - UserPlaybackRate.ValueChanged += _ => updateRate(); - - Seek(Math.Min(-beatmap.BeatmapInfo.AudioLeadIn, gameplayStartTime)); } public void Restart() @@ -139,6 +142,23 @@ namespace osu.Game.Screens.Play this.TransformBindableTo(pauseFreqAdjust, 1, 200, Easing.In); } + /// + /// Skip forwardto the next valid skip point. + /// + public void Skip() + { + if (GameplayClock.CurrentTime > gameplayStartTime - MINIMUM_SKIP_TIME) + return; + + double skipTarget = gameplayStartTime - MINIMUM_SKIP_TIME; + + if (GameplayClock.CurrentTime < 0 && skipTarget > 6000) + // double skip exception for storyboards with very long intros + skipTarget = 0; + + Seek(skipTarget); + } + /// /// Seek to a specific time in gameplay. /// diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a9b0649fab..d6488dc209 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -203,7 +203,7 @@ namespace osu.Game.Screens.Play }, new SkipOverlay(DrawableRuleset.GameplayStartTime) { - RequestSeek = GameplayClockContainer.Seek + RequestSkip = GameplayClockContainer.Skip }, FailOverlay = new FailOverlay { diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 835867fe62..3abe61d1a9 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Play { private readonly double startTime; - public Action RequestSeek; + public Action RequestSkip; private Button button; private Box remainingTimeBox; @@ -90,11 +90,6 @@ namespace osu.Game.Screens.Play }; } - /// - /// Duration before gameplay start time required before skip button displays. - /// - private const double skip_buffer = 1000; - private const double fade_time = 300; private double beginFadeTime => startTime - fade_time; @@ -104,7 +99,7 @@ namespace osu.Game.Screens.Play base.LoadComplete(); // skip is not required if there is no extra "empty" time to skip. - if (Clock.CurrentTime > beginFadeTime - skip_buffer) + if (Clock.CurrentTime > beginFadeTime - GameplayClockContainer.MINIMUM_SKIP_TIME) { Alpha = 0; Expire(); @@ -115,10 +110,9 @@ namespace osu.Game.Screens.Play using (BeginAbsoluteSequence(beginFadeTime)) this.FadeOut(fade_time); - button.Action = () => RequestSeek?.Invoke(beginFadeTime); + button.Action = () => RequestSkip?.Invoke(); displayTime = Time.Current; - Expire(); } @@ -335,13 +329,7 @@ namespace osu.Game.Screens.Play box.FlashColour(Color4.White, 500, Easing.OutQuint); aspect.ScaleTo(1.2f, 2000, Easing.OutQuint); - bool result = base.OnClick(e); - - // for now, let's disable the skip button after the first press. - // this will likely need to be contextual in the future (bound from external components). - Enabled.Value = false; - - return result; + return base.OnClick(e); } } } From 586e31efc256964b722de2112d55d367ee88ea56 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 15:56:08 +0900 Subject: [PATCH 4112/5608] Update tests --- osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs index addf7c3b28..9275dc636c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Osu; @@ -22,9 +23,7 @@ namespace osu.Game.Tests.Visual.Gameplay BeatmapInfo = { AudioLeadIn = 1000 } }); - AddUntilStep("player loaded", () => player.IsLoaded && player.Alpha == 1); - - AddAssert("correct lead-in", () => player.FirstFrameClockTime == 0); + AddAssert("correct lead-in", () => Precision.AlmostEquals(player.FirstFrameClockTime.Value, 0, 100)); } [Test] @@ -35,7 +34,7 @@ namespace osu.Game.Tests.Visual.Gameplay BeatmapInfo = { AudioLeadIn = 10000 } }); - AddAssert("correct lead-in", () => player.FirstFrameClockTime == player.GameplayStartTime - 10000); + AddAssert("correct lead-in", () => Precision.AlmostEquals(player.FirstFrameClockTime.Value, player.GameplayStartTime - 10000, 100)); } private void loadPlayerWithBeatmap(IBeatmap beatmap) From 9acfc2587aa6a8dcd34a2535f3fc4bcf928bac1b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 15:59:59 +0900 Subject: [PATCH 4113/5608] Switch android to using managed network components --- osu.Android.props | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Android.props b/osu.Android.props index 4a1165d57f..0f0e82d56a 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -16,6 +16,8 @@ armeabi-v7a;x86;arm64-v8a true cjk,mideast,other,rare,west + System.Net.Http.HttpClientHandler + legacy SdkOnly prompt From 2dd2e3d861706d22991174ed0e068f7f3c738ae9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 16:55:18 +0900 Subject: [PATCH 4114/5608] Add correct AudioLeadIn support --- osu.Game/Screens/Play/GameplayClockContainer.cs | 17 +++++++++++++---- osu.Game/Screens/Play/Player.cs | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index e1f4d8fa94..bc6f649492 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -41,6 +41,8 @@ namespace osu.Game.Screens.Play private readonly double gameplayStartTime; + private readonly double firstHitObjectTime; + public readonly Bindable UserPlaybackRate = new BindableDouble(1) { Default = 1, @@ -61,11 +63,12 @@ namespace osu.Game.Screens.Play private readonly FramedOffsetClock platformOffsetClock; - public GameplayClockContainer(WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime) + public GameplayClockContainer(WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime, double firstHitObjectTime) { this.beatmap = beatmap; this.mods = mods; this.gameplayStartTime = gameplayStartTime; + this.firstHitObjectTime = firstHitObjectTime; RelativeSizeAxes = Axes.Both; @@ -102,11 +105,17 @@ namespace osu.Game.Screens.Play userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); userAudioOffset.BindValueChanged(offset => userOffsetClock.Offset = offset.NewValue, true); - double startTime = -beatmap.BeatmapInfo.AudioLeadIn; + // sane default provided by ruleset. + double startTime = Math.Min(0, gameplayStartTime); + // if a storyboard is present, it may dictate the appropriate start time by having events in negative time space. + // this is commonly used to display an intro before the audio track start. startTime = Math.Min(startTime, beatmap.Storyboard.FirstEventTime); - startTime = Math.Min(startTime, gameplayStartTime); - startTime = Math.Min(startTime, 0); + + // some beatmaps specify a current lead-in time which should be used instead of the ruleset-provided value when available. + // this is not available as an option in the live editor but can still be applied via .osu editing. + if (beatmap.BeatmapInfo.AudioLeadIn > 0) + startTime = Math.Min(startTime, firstHitObjectTime - beatmap.BeatmapInfo.AudioLeadIn); Seek(startTime); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d6488dc209..cb71693312 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -129,7 +129,7 @@ namespace osu.Game.Screens.Play if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); - InternalChild = GameplayClockContainer = new GameplayClockContainer(working, Mods.Value, DrawableRuleset.GameplayStartTime); + InternalChild = GameplayClockContainer = new GameplayClockContainer(working, Mods.Value, DrawableRuleset.GameplayStartTime, DrawableRuleset.Objects.First().StartTime); addUnderlayComponents(GameplayClockContainer); addGameplayComponents(GameplayClockContainer, working); From 29d23749285dfc0773a152ee81536a061cc0c9ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 17:12:29 +0900 Subject: [PATCH 4115/5608] Add back skip button actuation count tests --- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 51 +++++++++++++++++-- osu.Game/Screens/Play/SkipOverlay.cs | 2 + 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index 0d62d9a520..1b4b0b4dcc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -18,27 +18,41 @@ namespace osu.Game.Tests.Visual.Gameplay private SkipOverlay skip; private int requestCount; + private FramedOffsetClock offsetClock; + private StopwatchClock stopwatchClock; + + private double increment; + [SetUp] public void SetUp() => Schedule(() => { requestCount = 0; + increment = 6000; + Child = new Container { RelativeSizeAxes = Axes.Both, - Clock = new FramedOffsetClock(Clock) - { - Offset = -Clock.CurrentTime, - }, + Clock = offsetClock = new FramedOffsetClock(stopwatchClock = new StopwatchClock(true)), Children = new Drawable[] { skip = new SkipOverlay(6000) { - RequestSkip = () => requestCount++ + RequestSkip = () => + { + requestCount++; + offsetClock.Offset += increment; + } } }, }; }); + protected override void Update() + { + if (stopwatchClock != null) + stopwatchClock.Rate = Clock.Rate; + } + [Test] public void TestFadeOnIdle() { @@ -60,6 +74,33 @@ namespace osu.Game.Tests.Visual.Gameplay checkRequestCount(1); } + [Test] + public void TestClickOnlyActuatesOnce() + { + AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); + AddStep("click", () => + { + increment = 6000 - offsetClock.CurrentTime - GameplayClockContainer.MINIMUM_SKIP_TIME / 2; + InputManager.Click(MouseButton.Left); + }); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkRequestCount(1); + } + + [Test] + public void TestClickOnlyActuatesMultipleTimes() + { + AddStep("set increment lower", () => increment = 3000); + AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkRequestCount(2); + } + [Test] public void TestDoesntFadeOnMouseDown() { diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 3abe61d1a9..2c6b33be39 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -124,6 +124,8 @@ namespace osu.Game.Screens.Play { base.Update(); remainingTimeBox.ResizeWidthTo((float)Math.Max(0, 1 - (Time.Current - displayTime) / (beginFadeTime - displayTime)), 120, Easing.OutQuint); + + button.Enabled.Value = Time.Current < startTime - GameplayClockContainer.MINIMUM_SKIP_TIME; } protected override bool OnMouseMove(MouseMoveEvent e) From 4e53bca8dd1e8ad8392a13010af04a9e42b69e50 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 18:21:49 +0900 Subject: [PATCH 4116/5608] Simplify tests --- .../Visual/Gameplay/TestSceneLeadIn.cs | 31 +++++++++++-------- osu.Game/Beatmaps/BeatmapInfo.cs | 2 +- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs index 9275dc636c..6434387f51 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Diagnostics; +using System.Linq; using NUnit.Framework; using osu.Framework.MathUtils; using osu.Game.Beatmaps; @@ -15,26 +17,26 @@ namespace osu.Game.Tests.Visual.Gameplay { private LeadInPlayer player; - [Test] - public void TestShortLeadIn() + private const double lenience_ms = 10; + + private const double first_hit_object = 2170; + + [TestCase(1000, 0)] + [TestCase(2000, 0)] + [TestCase(3000, first_hit_object - 3000)] + [TestCase(10000, first_hit_object - 10000)] + public void TestLeadInProducesCorrectStartTime(double leadIn, double expectedStartTime) { loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo) { - BeatmapInfo = { AudioLeadIn = 1000 } + BeatmapInfo = { AudioLeadIn = leadIn } }); - AddAssert("correct lead-in", () => Precision.AlmostEquals(player.FirstFrameClockTime.Value, 0, 100)); - } - - [Test] - public void TestLongLeadIn() - { - loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo) + AddAssert($"first frame is {expectedStartTime}", () => { - BeatmapInfo = { AudioLeadIn = 10000 } + Debug.Assert(player.FirstFrameClockTime != null); + return Precision.AlmostEquals(player.FirstFrameClockTime.Value, expectedStartTime, lenience_ms); }); - - AddAssert("correct lead-in", () => Precision.AlmostEquals(player.FirstFrameClockTime.Value, player.GameplayStartTime - 10000, 100)); } private void loadPlayerWithBeatmap(IBeatmap beatmap) @@ -61,6 +63,8 @@ namespace osu.Game.Tests.Visual.Gameplay public double GameplayStartTime => DrawableRuleset.GameplayStartTime; + public double FirstHitObjectTime => DrawableRuleset.Objects.First().StartTime; + public double GameplayClockTime => GameplayClockContainer.GameplayClock.CurrentTime; protected override void UpdateAfterChildren() @@ -73,6 +77,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddInternal(new OsuSpriteText { Text = $"GameplayStartTime: {DrawableRuleset.GameplayStartTime} " + + $"FirstHitObjectTime: {FirstHitObjectTime} " + $"LeadInTime: {Beatmap.Value.BeatmapInfo.AudioLeadIn} " + $"FirstFrameClockTime: {FirstFrameClockTime}" }); diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 198046df4f..6e82c465dc 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -76,7 +76,7 @@ namespace osu.Game.Beatmaps public string MD5Hash { get; set; } // General - public int AudioLeadIn { get; set; } + public double AudioLeadIn { get; set; } public bool Countdown { get; set; } = true; public float StackLeniency { get; set; } = 0.7f; public bool SpecialStyle { get; set; } From 8d1b11d4bd86b644c683bd74eac0dc893f61823a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 18:50:54 +0900 Subject: [PATCH 4117/5608] Add storyboard lead-in tests --- .../TestSceneSkinFallbacks.cs | 7 +++-- .../TestSceneSpinnerRotation.cs | 5 ++-- .../Visual/Gameplay/TestSceneAutoplay.cs | 5 ++-- .../Gameplay/TestSceneGameplayRewinding.cs | 5 ++-- .../Visual/Gameplay/TestSceneLeadIn.cs | 29 +++++++++++++++++-- .../TestScenePlayerReferenceLeaking.cs | 5 ++-- .../Drawables/DrawableStoryboardSprite.cs | 2 +- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 10 +++++-- osu.Game/Tests/Visual/OsuTestScene.cs | 14 +++++---- 9 files changed, 60 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index 02c65db6ad..7ca311118e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -19,6 +19,7 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Screens.Play; using osu.Game.Skinning; +using osu.Game.Storyboards; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests @@ -75,14 +76,14 @@ namespace osu.Game.Rulesets.Osu.Tests protected override Player CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin); - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) => new CustomSkinWorkingBeatmap(beatmap, Clock, audio, testBeatmapSkin); + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => new CustomSkinWorkingBeatmap(beatmap, storyboard, Clock, audio, testBeatmapSkin); public class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap { private readonly ISkinSource skin; - public CustomSkinWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock frameBasedClock, AudioManager audio, ISkinSource skin) - : base(beatmap, frameBasedClock, audio) + public CustomSkinWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock frameBasedClock, AudioManager audio, ISkinSource skin) + : base(beatmap, storyboard, frameBasedClock, audio) { this.skin = skin; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index cded7f0e95..d0ce0c33c2 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -15,6 +15,7 @@ using osu.Game.Tests.Visual; using osuTK; using System.Collections.Generic; using System.Linq; +using osu.Game.Storyboards; using static osu.Game.Tests.Visual.OsuTestScene.ClockBackedTestWorkingBeatmap; namespace osu.Game.Rulesets.Osu.Tests @@ -28,9 +29,9 @@ namespace osu.Game.Rulesets.Osu.Tests protected override bool Autoplay => true; - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) { - var working = new ClockBackedTestWorkingBeatmap(beatmap, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + var working = new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); track = (TrackVirtualManual)working.Track; return working; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index f94071a7a9..5ee109e3dd 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -7,6 +7,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; +using osu.Game.Storyboards; namespace osu.Game.Tests.Visual.Gameplay { @@ -29,9 +30,9 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("key counter reset", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); } - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) { - var working = base.CreateWorkingBeatmap(beatmap); + var working = base.CreateWorkingBeatmap(beatmap, storyboard); track = (ClockBackedTestWorkingBeatmap.TrackVirtualManual)working.Track; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index ffc025a942..b2b58a63fb 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -17,6 +17,7 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; +using osu.Game.Storyboards; using osuTK; namespace osu.Game.Tests.Visual.Gameplay @@ -35,9 +36,9 @@ namespace osu.Game.Tests.Visual.Gameplay private Track track; - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) { - var working = new ClockBackedTestWorkingBeatmap(beatmap, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + var working = new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); track = working.Track; return working; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs index 6434387f51..0150c6ea74 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs @@ -4,12 +4,15 @@ using System.Diagnostics; using System.Linq; using NUnit.Framework; +using osu.Framework.Graphics; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; +using osu.Game.Storyboards; using osu.Game.Tests.Beatmaps; +using osuTK; namespace osu.Game.Tests.Visual.Gameplay { @@ -39,11 +42,33 @@ namespace osu.Game.Tests.Visual.Gameplay }); } - private void loadPlayerWithBeatmap(IBeatmap beatmap) + [TestCase(1000, 0)] + [TestCase(0, 0)] + [TestCase(-1000, -1000)] + [TestCase(-10000, -10000)] + public void TestStoryboardProducesCorrectStartTime(double firstStoryboardEvent, double expectedStartTime) + { + var storyboard = new Storyboard(); + + var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero); + sprite.TimelineGroup.Alpha.Add(Easing.None, firstStoryboardEvent, firstStoryboardEvent + 500, 0, 1); + + storyboard.GetLayer("Background").Add(sprite); + + loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo), storyboard); + + AddAssert($"first frame is {expectedStartTime}", () => + { + Debug.Assert(player.FirstFrameClockTime != null); + return Precision.AlmostEquals(player.FirstFrameClockTime.Value, expectedStartTime, lenience_ms); + }); + } + + private void loadPlayerWithBeatmap(IBeatmap beatmap, Storyboard storyboard = null) { AddStep("create player", () => { - Beatmap.Value = CreateWorkingBeatmap(beatmap); + Beatmap.Value = CreateWorkingBeatmap(beatmap, storyboard); LoadScreen(player = new LeadInPlayer()); }); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs index 65b56319e8..4d701f56a9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs @@ -6,6 +6,7 @@ using osu.Framework.Lists; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Screens.Play; +using osu.Game.Storyboards; namespace osu.Game.Tests.Visual.Gameplay { @@ -42,9 +43,9 @@ namespace osu.Game.Tests.Visual.Gameplay }); } - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) { - var working = base.CreateWorkingBeatmap(beatmap); + var working = base.CreateWorkingBeatmap(beatmap, storyboard); workingWeakReferences.Add(working); return working; } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index 5f1f5ddacb..3a117d1713 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -66,7 +66,7 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader] private void load(IBindable beatmap, TextureStore textureStore) { - var path = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.Equals(Sprite.Path, StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath; + var path = beatmap.Value.BeatmapSetInfo?.Files?.Find(f => f.Filename.Equals(Sprite.Path, StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath; if (path == null) return; diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index 0d9f4f51be..871d8ee3f1 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -5,25 +5,31 @@ using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Video; using osu.Game.Beatmaps; +using osu.Game.Storyboards; namespace osu.Game.Tests.Beatmaps { public class TestWorkingBeatmap : WorkingBeatmap { private readonly IBeatmap beatmap; + private readonly Storyboard storyboard; /// /// Create an instance which provides the when requested. /// - /// The beatmap - public TestWorkingBeatmap(IBeatmap beatmap) + /// The beatmap. + /// An optional storyboard. + public TestWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) : base(beatmap.BeatmapInfo, null) { this.beatmap = beatmap; + this.storyboard = storyboard; } protected override IBeatmap GetBeatmap() => beatmap; + protected override Storyboard GetStoryboard() => storyboard ?? base.GetStoryboard(); + protected override Texture GetBackground() => null; protected override VideoSprite GetVideo() => null; diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 13e08c7d22..be67c2fe23 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -21,6 +21,7 @@ using osu.Game.Database; using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Storyboards; using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual @@ -119,10 +120,10 @@ namespace osu.Game.Tests.Visual protected virtual IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset); protected WorkingBeatmap CreateWorkingBeatmap(RulesetInfo ruleset) => - CreateWorkingBeatmap(CreateBeatmap(ruleset)); + CreateWorkingBeatmap(CreateBeatmap(ruleset), null); - protected virtual WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) => - new ClockBackedTestWorkingBeatmap(beatmap, Clock, audio); + protected virtual WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => + new ClockBackedTestWorkingBeatmap(beatmap, storyboard, Clock, audio); [BackgroundDependencyLoader] private void load(RulesetStore rulesets) @@ -168,7 +169,7 @@ namespace osu.Game.Tests.Visual /// A clock which should be used instead of a stopwatch for virtual time progression. /// Audio manager. Required if a reference clock isn't provided. public ClockBackedTestWorkingBeatmap(RulesetInfo ruleset, IFrameBasedClock referenceClock, AudioManager audio) - : this(new TestBeatmap(ruleset), referenceClock, audio) + : this(new TestBeatmap(ruleset), null, referenceClock, audio) { } @@ -176,11 +177,12 @@ namespace osu.Game.Tests.Visual /// Create an instance which provides the when requested. /// /// The beatmap + /// The storyboard. /// An optional clock which should be used instead of a stopwatch for virtual time progression. /// Audio manager. Required if a reference clock isn't provided. /// The length of the returned virtual track. - public ClockBackedTestWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock referenceClock, AudioManager audio, double length = 60000) - : base(beatmap) + public ClockBackedTestWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock referenceClock, AudioManager audio, double length = 60000) + : base(beatmap, storyboard) { if (referenceClock != null) { From 46a94821d44129975336136556b2b18e9e791e1b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 18:57:19 +0900 Subject: [PATCH 4118/5608] Add support for consecutive skips --- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 42 ++++++++++++++++--- .../Screens/Play/GameplayClockContainer.cs | 22 ++++++++++ osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Play/SkipOverlay.cs | 22 +++------- 4 files changed, 65 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index b152c21454..1b4b0b4dcc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -18,27 +18,41 @@ namespace osu.Game.Tests.Visual.Gameplay private SkipOverlay skip; private int requestCount; + private FramedOffsetClock offsetClock; + private StopwatchClock stopwatchClock; + + private double increment; + [SetUp] public void SetUp() => Schedule(() => { requestCount = 0; + increment = 6000; + Child = new Container { RelativeSizeAxes = Axes.Both, - Clock = new FramedOffsetClock(Clock) - { - Offset = -Clock.CurrentTime, - }, + Clock = offsetClock = new FramedOffsetClock(stopwatchClock = new StopwatchClock(true)), Children = new Drawable[] { skip = new SkipOverlay(6000) { - RequestSeek = _ => requestCount++ + RequestSkip = () => + { + requestCount++; + offsetClock.Offset += increment; + } } }, }; }); + protected override void Update() + { + if (stopwatchClock != null) + stopwatchClock.Rate = Clock.Rate; + } + [Test] public void TestFadeOnIdle() { @@ -64,13 +78,29 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestClickOnlyActuatesOnce() { AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); - AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => + { + increment = 6000 - offsetClock.CurrentTime - GameplayClockContainer.MINIMUM_SKIP_TIME / 2; + InputManager.Click(MouseButton.Left); + }); AddStep("click", () => InputManager.Click(MouseButton.Left)); AddStep("click", () => InputManager.Click(MouseButton.Left)); AddStep("click", () => InputManager.Click(MouseButton.Left)); checkRequestCount(1); } + [Test] + public void TestClickOnlyActuatesMultipleTimes() + { + AddStep("set increment lower", () => increment = 3000); + AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkRequestCount(2); + } + [Test] public void TestDoesntFadeOnMouseDown() { diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 2f2028ff53..6903ccf06d 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -89,6 +89,11 @@ namespace osu.Game.Screens.Play private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset; + /// + /// Duration before gameplay start time required before skip button displays. + /// + public const double MINIMUM_SKIP_TIME = 1000; + private readonly BindableDouble pauseFreqAdjust = new BindableDouble(1); [BackgroundDependencyLoader] @@ -130,6 +135,23 @@ namespace osu.Game.Screens.Play this.TransformBindableTo(pauseFreqAdjust, 1, 200, Easing.In); } + /// + /// Skip forward to the next valid skip point. + /// + public void Skip() + { + if (GameplayClock.CurrentTime > gameplayStartTime - MINIMUM_SKIP_TIME) + return; + + double skipTarget = gameplayStartTime - MINIMUM_SKIP_TIME; + + if (GameplayClock.CurrentTime < 0 && skipTarget > 6000) + // double skip exception for storyboards with very long intros + skipTarget = 0; + + Seek(skipTarget); + } + /// /// Seek to a specific time in gameplay. /// diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a9b0649fab..d6488dc209 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -203,7 +203,7 @@ namespace osu.Game.Screens.Play }, new SkipOverlay(DrawableRuleset.GameplayStartTime) { - RequestSeek = GameplayClockContainer.Seek + RequestSkip = GameplayClockContainer.Skip }, FailOverlay = new FailOverlay { diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 835867fe62..2c6b33be39 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Play { private readonly double startTime; - public Action RequestSeek; + public Action RequestSkip; private Button button; private Box remainingTimeBox; @@ -90,11 +90,6 @@ namespace osu.Game.Screens.Play }; } - /// - /// Duration before gameplay start time required before skip button displays. - /// - private const double skip_buffer = 1000; - private const double fade_time = 300; private double beginFadeTime => startTime - fade_time; @@ -104,7 +99,7 @@ namespace osu.Game.Screens.Play base.LoadComplete(); // skip is not required if there is no extra "empty" time to skip. - if (Clock.CurrentTime > beginFadeTime - skip_buffer) + if (Clock.CurrentTime > beginFadeTime - GameplayClockContainer.MINIMUM_SKIP_TIME) { Alpha = 0; Expire(); @@ -115,10 +110,9 @@ namespace osu.Game.Screens.Play using (BeginAbsoluteSequence(beginFadeTime)) this.FadeOut(fade_time); - button.Action = () => RequestSeek?.Invoke(beginFadeTime); + button.Action = () => RequestSkip?.Invoke(); displayTime = Time.Current; - Expire(); } @@ -130,6 +124,8 @@ namespace osu.Game.Screens.Play { base.Update(); remainingTimeBox.ResizeWidthTo((float)Math.Max(0, 1 - (Time.Current - displayTime) / (beginFadeTime - displayTime)), 120, Easing.OutQuint); + + button.Enabled.Value = Time.Current < startTime - GameplayClockContainer.MINIMUM_SKIP_TIME; } protected override bool OnMouseMove(MouseMoveEvent e) @@ -335,13 +331,7 @@ namespace osu.Game.Screens.Play box.FlashColour(Color4.White, 500, Easing.OutQuint); aspect.ScaleTo(1.2f, 2000, Easing.OutQuint); - bool result = base.OnClick(e); - - // for now, let's disable the skip button after the first press. - // this will likely need to be contextual in the future (bound from external components). - Enabled.Value = false; - - return result; + return base.OnClick(e); } } } From bd6831624a58802f022eccc616d90f977c9155e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 19:51:22 +0900 Subject: [PATCH 4119/5608] Decouple skip button animations from gameplay clock --- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 32 +++++++-------- osu.Game/Screens/Play/SkipOverlay.cs | 40 +++++++++---------- 2 files changed, 33 insertions(+), 39 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index 1b4b0b4dcc..a21f55e361 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -4,8 +4,8 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Timing; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; using osuTK; using osuTK.Input; @@ -18,40 +18,38 @@ namespace osu.Game.Tests.Visual.Gameplay private SkipOverlay skip; private int requestCount; - private FramedOffsetClock offsetClock; - private StopwatchClock stopwatchClock; - private double increment; + private GameplayClockContainer gameplayClockContainer; + private GameplayClock gameplayClock; + + private const double skip_time = 6000; + [SetUp] public void SetUp() => Schedule(() => { requestCount = 0; - increment = 6000; + increment = skip_time; - Child = new Container + Child = gameplayClockContainer = new GameplayClockContainer(CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)), new Mod[] { }, 0) { RelativeSizeAxes = Axes.Both, - Clock = offsetClock = new FramedOffsetClock(stopwatchClock = new StopwatchClock(true)), Children = new Drawable[] { - skip = new SkipOverlay(6000) + skip = new SkipOverlay(skip_time) { RequestSkip = () => { requestCount++; - offsetClock.Offset += increment; + gameplayClockContainer.Seek(gameplayClock.CurrentTime + increment); } } }, }; - }); - protected override void Update() - { - if (stopwatchClock != null) - stopwatchClock.Rate = Clock.Rate; - } + gameplayClockContainer.Start(); + gameplayClock = gameplayClockContainer.GameplayClock; + }); [Test] public void TestFadeOnIdle() @@ -80,7 +78,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); AddStep("click", () => { - increment = 6000 - offsetClock.CurrentTime - GameplayClockContainer.MINIMUM_SKIP_TIME / 2; + increment = skip_time - gameplayClock.CurrentTime - GameplayClockContainer.MINIMUM_SKIP_TIME / 2; InputManager.Click(MouseButton.Left); }); AddStep("click", () => InputManager.Click(MouseButton.Left)); diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 2c6b33be39..1a5ed20953 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -19,6 +19,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Containers; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Framework.MathUtils; using osu.Game.Input.Bindings; namespace osu.Game.Screens.Play @@ -35,6 +36,9 @@ namespace osu.Game.Screens.Play private FadeContainer fadeContainer; private double displayTime; + [Resolved] + private GameplayClock gameplayClock { get; set; } + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; /// @@ -45,8 +49,6 @@ namespace osu.Game.Screens.Play { this.startTime = startTime; - Show(); - RelativePositionAxes = Axes.Both; RelativeSizeAxes = Axes.X; @@ -57,13 +59,8 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, GameplayClock clock) + private void load(OsuColour colours) { - var baseClock = Clock; - - if (clock != null) - Clock = clock; - Children = new Drawable[] { fadeContainer = new FadeContainer @@ -73,7 +70,6 @@ namespace osu.Game.Screens.Play { button = new Button { - Clock = baseClock, Anchor = Anchor.Centre, Origin = Anchor.Centre, }, @@ -92,40 +88,40 @@ namespace osu.Game.Screens.Play private const double fade_time = 300; - private double beginFadeTime => startTime - fade_time; + private double fadeOutBeginTime => startTime - GameplayClockContainer.MINIMUM_SKIP_TIME; protected override void LoadComplete() { base.LoadComplete(); // skip is not required if there is no extra "empty" time to skip. - if (Clock.CurrentTime > beginFadeTime - GameplayClockContainer.MINIMUM_SKIP_TIME) + // we may need to remove this if rewinding before the initial player load position becomes a thing. + if (fadeOutBeginTime < gameplayClock.CurrentTime) { - Alpha = 0; Expire(); return; } - this.FadeInFromZero(fade_time); - using (BeginAbsoluteSequence(beginFadeTime)) - this.FadeOut(fade_time); - button.Action = () => RequestSkip?.Invoke(); + displayTime = gameplayClock.CurrentTime; - displayTime = Time.Current; - Expire(); + Show(); } - protected override void PopIn() => this.FadeIn(); + protected override void PopIn() => this.FadeIn(fade_time); - protected override void PopOut() => this.FadeOut(); + protected override void PopOut() => this.FadeOut(fade_time); protected override void Update() { base.Update(); - remainingTimeBox.ResizeWidthTo((float)Math.Max(0, 1 - (Time.Current - displayTime) / (beginFadeTime - displayTime)), 120, Easing.OutQuint); - button.Enabled.Value = Time.Current < startTime - GameplayClockContainer.MINIMUM_SKIP_TIME; + var progress = Math.Max(0, 1 - (gameplayClock.CurrentTime - displayTime) / (fadeOutBeginTime - displayTime)); + + remainingTimeBox.Width = (float)Interpolation.Lerp(remainingTimeBox.Width, progress, Math.Clamp(Time.Elapsed / 40, 0, 1)); + + button.Enabled.Value = progress > 0; + State.Value = progress > 0 ? Visibility.Visible : Visibility.Hidden; } protected override bool OnMouseMove(MouseMoveEvent e) From 71a64da566a685cce2ad929d989afab589c2b60e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 22:07:37 +0900 Subject: [PATCH 4120/5608] Fix test regressions --- osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index a21f55e361..875e7b9758 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); AddStep("button down", () => InputManager.PressButton(MouseButton.Left)); - AddUntilStep("wait for overlay disapper", () => !skip.IsAlive); + AddUntilStep("wait for overlay disappear", () => !skip.IsPresent); AddAssert("ensure button didn't disappear", () => skip.Children.First().Alpha > 0); AddStep("button up", () => InputManager.ReleaseButton(MouseButton.Left)); checkRequestCount(0); From 8b1fb2d5a1ab47fdf05f46e6f24b713d739440ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 22:35:15 +0900 Subject: [PATCH 4121/5608] Standardise keyword specifications --- .../Settings/Sections/Audio/AudioDevicesSettings.cs | 2 +- osu.Game/Overlays/Settings/Sections/AudioSection.cs | 2 +- .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- .../Overlays/Settings/Sections/Gameplay/ModsSettings.cs | 5 ++++- .../Settings/Sections/Gameplay/SongSelectSettings.cs | 6 +++--- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 4 ++-- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index e9ae784061..0612f028bc 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { dropdown = new AudioDeviceSettingsDropdown { - Keywords = new[] { "Speaker" } + Keywords = new[] { "speaker", "headphone", "output" } } }; diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index 254af6ea21..b18488b616 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Settings.Sections { public override string Header => "Audio"; - public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "Sound" }); + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "sound" }); public override IconUsage Icon => FontAwesome.Solid.VolumeUp; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 0ac145ffe2..f4aa9a0144 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show health display even when you can't fail", Bindable = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), - Keywords = new[] { "Bar", "Hp" } + Keywords = new[] { "hp", "bar" } }, new SettingsCheckbox { diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index a71919a2fc..0babb98066 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Game.Configuration; @@ -10,6 +12,8 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { protected override string Header => "Mods"; + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "mod" }); + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { @@ -19,7 +23,6 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Increase visibility of first object when visual impairment mods are enabled", Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility), - Keywords = new[] { "Mod" } }, }; } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs index fce0e3dea8..f4a861141f 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs @@ -26,21 +26,21 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show converted beatmaps", Bindable = config.GetBindable(OsuSetting.ShowConvertedBeatmaps), - Keywords = new[] { "Converts" } + Keywords = new[] { "convert" } }, new SettingsSlider { LabelText = "Display beatmaps from", Bindable = config.GetBindable(OsuSetting.DisplayStarsMinimum), KeyboardStep = 0.1f, - Keywords = new[] { "Stars" } + Keywords = new[] { "star", "difficulty" } }, new SettingsSlider { LabelText = "up to", Bindable = config.GetBindable(OsuSetting.DisplayStarsMaximum), KeyboardStep = 0.1f, - Keywords = new[] { "Stars" } + Keywords = new[] { "star", "difficulty" } }, new SettingsEnumDropdown { diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 8275d6dc0a..02b9edd975 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -76,13 +76,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics TransferValueOnCommit = true, Bindable = osuConfig.GetBindable(OsuSetting.UIScale), KeyboardStep = 0.01f, - Keywords = new[] { "Scale" }, + Keywords = new[] { "scale", "letterbox" }, }, new SettingsEnumDropdown { LabelText = "Screen Scaling", Bindable = osuConfig.GetBindable(OsuSetting.Scaling), - Keywords = new[] { "Scale" }, + Keywords = new[] { "scale", "letterbox" }, }, scalingSettings = new FillFlowContainer> { From d7cb23a9094304d2e1f70172c2c2093c886de11f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 22:51:00 +0900 Subject: [PATCH 4122/5608] Remove redundant keyword --- .../Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs index f4a861141f..a5f56ae76e 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs @@ -26,7 +26,6 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show converted beatmaps", Bindable = config.GetBindable(OsuSetting.ShowConvertedBeatmaps), - Keywords = new[] { "convert" } }, new SettingsSlider { From 4475307707251bc591335cd02424274430fb6777 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 22:55:31 +0900 Subject: [PATCH 4123/5608] Fix spacing --- osu.Game/Utils/SentryLogger.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Utils/SentryLogger.cs b/osu.Game/Utils/SentryLogger.cs index 7e879741d6..981251784e 100644 --- a/osu.Game/Utils/SentryLogger.cs +++ b/osu.Game/Utils/SentryLogger.cs @@ -26,6 +26,7 @@ namespace osu.Game.Utils Dsn = new Dsn("https://5e342cd55f294edebdc9ad604d28bbd3@sentry.io/1255255"), Release = game.Version }; + sentry = new SentryClient(options); sentryScope = new Scope(options); From 737c2bd1c8fa1a66bcf47160cc675fe082985941 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 18:50:29 +0300 Subject: [PATCH 4124/5608] Remove pointless const --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index e62a754e92..ac8952bebb 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -97,7 +97,6 @@ namespace osu.Game.Overlays.BeatmapSet private class ModButton : ModIcon { - private const float mod_scale = 0.4f; private const int duration = 200; public readonly BindableBool Selected = new BindableBool(); @@ -106,7 +105,7 @@ namespace osu.Game.Overlays.BeatmapSet public ModButton(Mod mod) : base(mod) { - Scale = new Vector2(mod_scale); + Scale = new Vector2(0.4f); Highlighted.Value = true; Add(new HoverClickSounds()); } From 20f01ff3e9c68ea9ffd45cc60e76121ae1101038 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 21 Nov 2019 23:46:39 +0800 Subject: [PATCH 4125/5608] Revert false positives of 'unused assignment'. --- .../Legacy/HitObjectPatternGenerator.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 3b7a24726e..ba9aa9e87f 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -168,43 +168,43 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } if (convertType.HasFlag(PatternType.KeepSingle)) - return generateRandomNotes(1); + return pattern = generateRandomNotes(1); if (convertType.HasFlag(PatternType.Mirror)) { if (ConversionDifficulty > 6.5) - return generateRandomPatternWithMirrored(0.12, 0.38, 0.12); + return pattern = generateRandomPatternWithMirrored(0.12, 0.38, 0.12); if (ConversionDifficulty > 4) - return generateRandomPatternWithMirrored(0.12, 0.17, 0); + return pattern = generateRandomPatternWithMirrored(0.12, 0.17, 0); - return generateRandomPatternWithMirrored(0.12, 0, 0); + return pattern = generateRandomPatternWithMirrored(0.12, 0, 0); } if (ConversionDifficulty > 6.5) { if (convertType.HasFlag(PatternType.LowProbability)) - return generateRandomPattern(0.78, 0.42, 0, 0); + return pattern = generateRandomPattern(0.78, 0.42, 0, 0); - return generateRandomPattern(1, 0.62, 0, 0); + return pattern = generateRandomPattern(1, 0.62, 0, 0); } if (ConversionDifficulty > 4) { if (convertType.HasFlag(PatternType.LowProbability)) - return generateRandomPattern(0.35, 0.08, 0, 0); + return pattern = generateRandomPattern(0.35, 0.08, 0, 0); - return generateRandomPattern(0.52, 0.15, 0, 0); + return pattern = generateRandomPattern(0.52, 0.15, 0, 0); } if (ConversionDifficulty > 2) { if (convertType.HasFlag(PatternType.LowProbability)) - return generateRandomPattern(0.18, 0, 0, 0); + return pattern = generateRandomPattern(0.18, 0, 0, 0); - return generateRandomPattern(0.45, 0, 0, 0); + return pattern = generateRandomPattern(0.45, 0, 0, 0); } - return generateRandomPattern(0, 0, 0, 0); + return pattern = generateRandomPattern(0, 0, 0, 0); } finally { From 984ec11a78ca071e70d04cd5899ee7b07cfad140 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 18:56:48 +0300 Subject: [PATCH 4126/5608] Make Ruleset a bindable --- .../Online/TestSceneLeaderboardModSelector.cs | 14 ++++-- .../BeatmapSet/LeaderboardModSelector.cs | 49 ++++++++----------- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index c0c18c2583..ebe233a5f4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -12,6 +12,8 @@ using osu.Game.Rulesets.Catch; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Bindables; +using osu.Game.Rulesets; namespace osu.Game.Tests.Visual.Online { @@ -26,6 +28,7 @@ namespace osu.Game.Tests.Visual.Online { LeaderboardModSelector modSelector; FillFlowContainer selectedMods; + var ruleset = new Bindable(); Add(selectedMods = new FillFlowContainer { @@ -37,6 +40,7 @@ namespace osu.Game.Tests.Visual.Online { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Ruleset = { BindTarget = ruleset } }); modSelector.SelectedMods.ItemsAdded += mods => @@ -62,12 +66,12 @@ namespace osu.Game.Tests.Visual.Online }); }; - AddStep("osu ruleset", () => modSelector.Ruleset = new OsuRuleset().RulesetInfo); - AddStep("mania ruleset", () => modSelector.Ruleset = new ManiaRuleset().RulesetInfo); - AddStep("taiko ruleset", () => modSelector.Ruleset = new TaikoRuleset().RulesetInfo); - AddStep("catch ruleset", () => modSelector.Ruleset = new CatchRuleset().RulesetInfo); + AddStep("osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo); + AddStep("mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo); + AddStep("taiko ruleset", () => ruleset.Value = new TaikoRuleset().RulesetInfo); + AddStep("catch ruleset", () => ruleset.Value = new CatchRuleset().RulesetInfo); AddStep("Deselect all", () => modSelector.DeselectAll()); - AddStep("null ruleset", () => modSelector.Ruleset = null); + AddStep("null ruleset", () => ruleset.Value = null); } } } diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index ac8952bebb..ba42e8c310 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -20,34 +20,7 @@ namespace osu.Game.Overlays.BeatmapSet public class LeaderboardModSelector : CompositeDrawable { public readonly BindableList SelectedMods = new BindableList(); - - private RulesetInfo ruleset; - - public RulesetInfo Ruleset - { - get => ruleset; - set - { - if (ruleset?.Equals(value) ?? false) - { - DeselectAll(); - return; - } - - ruleset = value; - - SelectedMods.Clear(); - modsContainer.Clear(); - - if (ruleset == null) - return; - - modsContainer.Add(new ModButton(new ModNoMod())); - modsContainer.AddRange(ruleset.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); - - modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); - } - } + public readonly Bindable Ruleset = new Bindable(); private readonly FillFlowContainer modsContainer; @@ -64,6 +37,26 @@ namespace osu.Game.Overlays.BeatmapSet }; } + protected override void LoadComplete() + { + base.LoadComplete(); + Ruleset.BindValueChanged(onRulesetChanged, true); + } + + private void onRulesetChanged(ValueChangedEvent ruleset) + { + SelectedMods.Clear(); + modsContainer.Clear(); + + if (ruleset.NewValue == null) + return; + + modsContainer.Add(new ModButton(new ModNoMod())); + modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); + + modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); + } + private void selectionChanged(Mod mod, bool selected) { if (selected) From 23fc7b198782d79333edfa849a29bfe27f9805cd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 19:02:24 +0300 Subject: [PATCH 4127/5608] Implement updateHighlighted method --- .../BeatmapSet/LeaderboardModSelector.cs | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index ba42e8c310..0a053c98db 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -64,24 +64,34 @@ namespace osu.Game.Overlays.BeatmapSet else SelectedMods.Remove(mod); - if (!SelectedMods.Any() && !IsHovered) + updateHighlighted(); + } + + private void updateHighlighted() + { + if (SelectedMods.Any()) + return; + + if (IsHovered) + { + modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = false); + } + else + { highlightAll(); + } } protected override bool OnHover(HoverEvent e) { - if (!SelectedMods.Any()) - modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = false); - + updateHighlighted(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - - if (!SelectedMods.Any()) - highlightAll(); + updateHighlighted(); } public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); From 4cd7d67fe4eef0213128dfc619091c1844b50c63 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 22 Nov 2019 00:02:40 +0800 Subject: [PATCH 4128/5608] Use early return for if-pattern-matching. --- .../Beatmaps/ManiaBeatmapConverter.cs | 12 +++---- .../Legacy/DistanceObjectPatternGenerator.cs | 12 +++---- .../TestSceneSlider.cs | 32 +++++++++---------- osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs | 18 +++++------ .../Components/ScrollingTeamContainer.cs | 24 +++++++------- 5 files changed, 47 insertions(+), 51 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 6e3d5761ac..f5bd52146c 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -263,15 +263,13 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// private IList sampleInfoListAt(double time) { - if (HitObject is IHasCurve curveData) - { - double segmentTime = (curveData.EndTime - HitObject.StartTime) / curveData.SpanCount(); + if (!(HitObject is IHasCurve curveData)) + return HitObject.Samples; - int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); - return curveData.NodeSamples[index]; - } + double segmentTime = (curveData.EndTime - HitObject.StartTime) / curveData.SpanCount(); - return HitObject.Samples; + int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); + return curveData.NodeSamples[index]; } } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 0cbf5cf51c..cf75441200 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -474,15 +474,13 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// private IList sampleInfoListAt(double time) { - if (HitObject is IHasCurve curveData) - { - double segmentTime = (EndTime - HitObject.StartTime) / spanCount; + if (!(HitObject is IHasCurve curveData)) + return HitObject.Samples; - int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); - return curveData.NodeSamples[index]; - } + double segmentTime = (EndTime - HitObject.StartTime) / spanCount; - return HitObject.Samples; + int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); + return curveData.NodeSamples[index]; } /// diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 88c9324d4c..a9d5c03517 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -380,25 +380,25 @@ namespace osu.Game.Rulesets.Osu.Tests private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) { - if (judgedObject is DrawableOsuHitObject osuObject) + if (!(judgedObject is DrawableOsuHitObject osuObject)) + return; + + OsuSpriteText text; + Add(text = new OsuSpriteText { - OsuSpriteText text; - Add(text = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = result.IsHit ? "Hit!" : "Miss!", - Colour = result.IsHit ? Color4.Green : Color4.Red, - Font = OsuFont.GetFont(size: 30), - Position = osuObject.HitObject.StackedEndPosition + judgementOffsetDirection * new Vector2(0, 45) - }); + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = result.IsHit ? "Hit!" : "Miss!", + Colour = result.IsHit ? Color4.Green : Color4.Red, + Font = OsuFont.GetFont(size: 30), + Position = osuObject.HitObject.StackedEndPosition + judgementOffsetDirection * new Vector2(0, 45) + }); - text.Delay(150) - .Then().FadeOut(200) - .Then().Expire(); + text.Delay(150) + .Then().FadeOut(200) + .Then().Expire(); - judgementOffsetDirection *= -1; - } + judgementOffsetDirection *= -1; } } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs index b031707248..3d566362ae 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs @@ -22,17 +22,17 @@ namespace osu.Game.Rulesets.Osu.Mods osuObject.Position = new Vector2(osuObject.Position.X, OsuPlayfield.BASE_SIZE.Y - osuObject.Y); - if (hitObject is Slider slider) - { - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); + if (!(hitObject is Slider slider)) + return; - var newControlPoints = new Vector2[slider.Path.ControlPoints.Length]; - for (int i = 0; i < slider.Path.ControlPoints.Length; i++) - newControlPoints[i] = new Vector2(slider.Path.ControlPoints[i].X, -slider.Path.ControlPoints[i].Y); + slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); + slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); - slider.Path = new SliderPath(slider.Path.Type, newControlPoints, slider.Path.ExpectedDistance); - } + var newControlPoints = new Vector2[slider.Path.ControlPoints.Length]; + for (int i = 0; i < slider.Path.ControlPoints.Length; i++) + newControlPoints[i] = new Vector2(slider.Path.ControlPoints[i].X, -slider.Path.ControlPoints[i].Y); + + slider.Path = new SliderPath(slider.Path.Type, newControlPoints, slider.Path.ExpectedDistance); } } } diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index fff73fcf70..a345f93896 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -125,20 +125,20 @@ namespace osu.Game.Tournament.Screens.Drawings.Components foreach (var c in Children) { - if (c is ScrollingTeam stc) + if (!(c is ScrollingTeam stc)) + continue; + + if (closest == null) { - if (closest == null) - { - closest = stc; - continue; - } - - float o = Math.Abs(c.Position.X + c.DrawWidth / 2f - DrawWidth / 2f); - float lastOffset = Math.Abs(closest.Position.X + closest.DrawWidth / 2f - DrawWidth / 2f); - - if (o < lastOffset) - closest = stc; + closest = stc; + continue; } + + float o = Math.Abs(c.Position.X + c.DrawWidth / 2f - DrawWidth / 2f); + float lastOffset = Math.Abs(closest.Position.X + closest.DrawWidth / 2f - DrawWidth / 2f); + + if (o < lastOffset) + closest = stc; } Trace.Assert(closest != null, "closest != null"); From 8239c2da61228e0045a23b06a55ce4c1a3461e56 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 22 Nov 2019 00:12:03 +0800 Subject: [PATCH 4129/5608] Refactor to avoid using try-finally as control flow. --- .../Legacy/HitObjectPatternGenerator.cs | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index ba9aa9e87f..84f950997d 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { @@ -88,15 +89,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy public override IEnumerable Generate() { - yield return generate(); - } - - private Pattern generate() - { - var pattern = new Pattern(); - - try + Pattern generateCore() { + var pattern = new Pattern(); + if (TotalColumns == 1) { addToPattern(pattern, 0); @@ -168,54 +164,56 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } if (convertType.HasFlag(PatternType.KeepSingle)) - return pattern = generateRandomNotes(1); + return generateRandomNotes(1); if (convertType.HasFlag(PatternType.Mirror)) { if (ConversionDifficulty > 6.5) - return pattern = generateRandomPatternWithMirrored(0.12, 0.38, 0.12); + return generateRandomPatternWithMirrored(0.12, 0.38, 0.12); if (ConversionDifficulty > 4) - return pattern = generateRandomPatternWithMirrored(0.12, 0.17, 0); + return generateRandomPatternWithMirrored(0.12, 0.17, 0); - return pattern = generateRandomPatternWithMirrored(0.12, 0, 0); + return generateRandomPatternWithMirrored(0.12, 0, 0); } if (ConversionDifficulty > 6.5) { if (convertType.HasFlag(PatternType.LowProbability)) - return pattern = generateRandomPattern(0.78, 0.42, 0, 0); + return generateRandomPattern(0.78, 0.42, 0, 0); - return pattern = generateRandomPattern(1, 0.62, 0, 0); + return generateRandomPattern(1, 0.62, 0, 0); } if (ConversionDifficulty > 4) { if (convertType.HasFlag(PatternType.LowProbability)) - return pattern = generateRandomPattern(0.35, 0.08, 0, 0); + return generateRandomPattern(0.35, 0.08, 0, 0); - return pattern = generateRandomPattern(0.52, 0.15, 0, 0); + return generateRandomPattern(0.52, 0.15, 0, 0); } if (ConversionDifficulty > 2) { if (convertType.HasFlag(PatternType.LowProbability)) - return pattern = generateRandomPattern(0.18, 0, 0, 0); + return generateRandomPattern(0.18, 0, 0, 0); - return pattern = generateRandomPattern(0.45, 0, 0, 0); + return generateRandomPattern(0.45, 0, 0, 0); } - return pattern = generateRandomPattern(0, 0, 0, 0); + return generateRandomPattern(0, 0, 0, 0); } - finally + + var p = generateCore(); + + foreach (var obj in p.HitObjects) { - foreach (var obj in pattern.HitObjects) - { - if (convertType.HasFlag(PatternType.Stair) && obj.Column == TotalColumns - 1) - StairType = PatternType.ReverseStair; - if (convertType.HasFlag(PatternType.ReverseStair) && obj.Column == RandomStart) - StairType = PatternType.Stair; - } + if (convertType.HasFlag(PatternType.Stair) && obj.Column == TotalColumns - 1) + StairType = PatternType.ReverseStair; + if (convertType.HasFlag(PatternType.ReverseStair) && obj.Column == RandomStart) + StairType = PatternType.Stair; } + + return p.Yield(); } /// From e22a71c6b80125e63660b3a0799b7325bce50348 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 19:42:07 +0300 Subject: [PATCH 4130/5608] Add visual difference between hovered and selected states --- .../BeatmapSet/LeaderboardModSelector.cs | 44 ++++++++----------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 0a053c98db..0e9e848e7a 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -72,14 +72,7 @@ namespace osu.Game.Overlays.BeatmapSet if (SelectedMods.Any()) return; - if (IsHovered) - { - modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = false); - } - else - { - highlightAll(); - } + modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.IsActive.Value = !IsHovered); } protected override bool OnHover(HoverEvent e) @@ -94,22 +87,19 @@ namespace osu.Game.Overlays.BeatmapSet updateHighlighted(); } - public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); - - private void highlightAll() => modsContainer.ForEach(mod => mod.Highlighted.Value = true); + public void DeselectAll() => modsContainer.ForEach(mod => mod.Highlighted.Value = false); private class ModButton : ModIcon { private const int duration = 200; - public readonly BindableBool Selected = new BindableBool(); + public readonly BindableBool IsActive = new BindableBool(); public Action OnSelectionChanged; public ModButton(Mod mod) : base(mod) { Scale = new Vector2(0.4f); - Highlighted.Value = true; Add(new HoverClickSounds()); } @@ -117,35 +107,39 @@ namespace osu.Game.Overlays.BeatmapSet { base.LoadComplete(); - Selected.BindValueChanged(selected => + IsActive.BindValueChanged(hovered => { - updateState(); - OnSelectionChanged?.Invoke(Mod, selected.NewValue); - }); + if (Highlighted.Value) + return; + + this.FadeColour(hovered.NewValue ? Color4.White : Color4.DimGray, duration, Easing.OutQuint); + }, true); + } + + protected override void OnHighlightedChanged(ValueChangedEvent highlighted) + { + base.OnHighlightedChanged(highlighted); + OnSelectionChanged?.Invoke(Mod, highlighted.NewValue); + IsActive.TriggerChange(); } protected override bool OnClick(ClickEvent e) { - Selected.Toggle(); + Highlighted.Toggle(); return true; } protected override bool OnHover(HoverEvent e) { - updateState(); + IsActive.Value = true; return false; } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - updateState(); + IsActive.Value = false; } - - private void updateState() => Highlighted.Value = IsHovered || Selected.Value; - - protected override void OnHighlightedChanged(ValueChangedEvent highlighted) => - this.FadeColour(highlighted.NewValue ? Color4.White : Color4.Gray, duration, Easing.OutQuint); } } } From c7c8527f5ff780ccf012b41720545084757486b8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 20:22:15 +0300 Subject: [PATCH 4131/5608] Remove OnHighlightedChanged function --- .../Overlays/BeatmapSet/LeaderboardModSelector.cs | 11 +++++------ osu.Game/Rulesets/UI/ModIcon.cs | 9 +-------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 0e9e848e7a..bb6f889c40 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -114,13 +114,12 @@ namespace osu.Game.Overlays.BeatmapSet this.FadeColour(hovered.NewValue ? Color4.White : Color4.DimGray, duration, Easing.OutQuint); }, true); - } - protected override void OnHighlightedChanged(ValueChangedEvent highlighted) - { - base.OnHighlightedChanged(highlighted); - OnSelectionChanged?.Invoke(Mod, highlighted.NewValue); - IsActive.TriggerChange(); + Highlighted.BindValueChanged(highlighted => + { + OnSelectionChanged?.Invoke(Mod, highlighted.NewValue); + IsActive.TriggerChange(); + }, true); } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 19211e0c80..cf1bbadb57 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -107,19 +107,12 @@ namespace osu.Game.Rulesets.UI modIcon.Colour = colours.Yellow; break; } - - background.Colour = backgroundColour; } protected override void LoadComplete() { base.LoadComplete(); - Highlighted.BindValueChanged(OnHighlightedChanged, true); - } - - protected virtual void OnHighlightedChanged(ValueChangedEvent highlighted) - { - background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour; + Highlighted.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); } } } From f390e558c76532b4ac2d784a9cc02af0058122bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 02:32:02 +0900 Subject: [PATCH 4132/5608] Combine and simplify beatmap change logic --- osu.Game/Graphics/Containers/ScalingContainer.cs | 10 ---------- .../Screens/Backgrounds/BackgroundScreenDefault.cs | 1 + osu.Game/Screens/Menu/MainMenu.cs | 11 ----------- 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 023d295b08..8f07c3a656 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -6,7 +6,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; -using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Screens; using osu.Game.Screens.Backgrounds; @@ -155,15 +154,6 @@ namespace osu.Game.Graphics.Containers private class ScalingBackgroundScreen : BackgroundScreenDefault { - private IBindable beatmap; - - [BackgroundDependencyLoader] - private void load(IBindable beatmap) - { - this.beatmap = beatmap.GetBoundCopy(); - this.beatmap.ValueChanged += _ => Next(); - } - public override void OnEntering(IScreen last) { this.FadeInFromZero(4000, Easing.OutQuint); diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 93590b0543..d49751f511 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -46,6 +46,7 @@ namespace osu.Game.Screens.Backgrounds user.ValueChanged += _ => Next(); skin.ValueChanged += _ => Next(); mode.ValueChanged += _ => Next(); + beatmap.ValueChanged += _ => Next(); currentDisplay = RNG.Next(0, background_count); diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 08338845e6..231115d1e1 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Platform; using osu.Framework.Screens; -using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -170,8 +169,6 @@ namespace osu.Game.Screens.Menu track.Start(); } } - - Beatmap.ValueChanged += beatmap_ValueChanged; } private bool exitConfirmed; @@ -220,14 +217,6 @@ namespace osu.Game.Screens.Menu seq.OnAbort(_ => buttons.SetOsuLogo(null)); } - private void beatmap_ValueChanged(ValueChangedEvent e) - { - if (!this.IsCurrentScreen()) - return; - - ((BackgroundScreenDefault)Background).Next(); - } - public override void OnSuspending(IScreen next) { base.OnSuspending(next); From 0f1a3d97c8d5c7a6daf9330663e3d81677d6d3f6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 20:34:19 +0300 Subject: [PATCH 4133/5608] Naming adjustments --- .../BeatmapSet/LeaderboardModSelector.cs | 32 +++++++++---------- osu.Game/Overlays/Mods/ModButton.cs | 2 +- osu.Game/Rulesets/UI/ModIcon.cs | 4 +-- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index bb6f889c40..a6f69617d0 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -72,7 +72,7 @@ namespace osu.Game.Overlays.BeatmapSet if (SelectedMods.Any()) return; - modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.IsActive.Value = !IsHovered); + modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = !IsHovered); } protected override bool OnHover(HoverEvent e) @@ -87,13 +87,13 @@ namespace osu.Game.Overlays.BeatmapSet updateHighlighted(); } - public void DeselectAll() => modsContainer.ForEach(mod => mod.Highlighted.Value = false); + public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); private class ModButton : ModIcon { private const int duration = 200; - public readonly BindableBool IsActive = new BindableBool(); + public readonly BindableBool Highlighted = new BindableBool(); public Action OnSelectionChanged; public ModButton(Mod mod) @@ -107,37 +107,37 @@ namespace osu.Game.Overlays.BeatmapSet { base.LoadComplete(); - IsActive.BindValueChanged(hovered => - { - if (Highlighted.Value) - return; - - this.FadeColour(hovered.NewValue ? Color4.White : Color4.DimGray, duration, Easing.OutQuint); - }, true); - Highlighted.BindValueChanged(highlighted => { - OnSelectionChanged?.Invoke(Mod, highlighted.NewValue); - IsActive.TriggerChange(); + if (Selected.Value) + return; + + this.FadeColour(highlighted.NewValue ? Color4.White : Color4.DimGray, duration, Easing.OutQuint); + }, true); + + Selected.BindValueChanged(selected => + { + OnSelectionChanged?.Invoke(Mod, selected.NewValue); + Highlighted.TriggerChange(); }, true); } protected override bool OnClick(ClickEvent e) { - Highlighted.Toggle(); + Selected.Toggle(); return true; } protected override bool OnHover(HoverEvent e) { - IsActive.Value = true; + Highlighted.Value = true; return false; } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - IsActive.Value = false; + Highlighted.Value = false; } } } diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index 8252020e9b..c6b4787ff1 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -96,7 +96,7 @@ namespace osu.Game.Overlays.Mods } } - foregroundIcon.Highlighted.Value = Selected; + foregroundIcon.Selected.Value = Selected; SelectionChanged?.Invoke(SelectedMod); return true; diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index cf1bbadb57..1be70ff48f 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.UI { public class ModIcon : Container, IHasTooltip { - public readonly BindableBool Highlighted = new BindableBool(); + public readonly BindableBool Selected = new BindableBool(); private readonly SpriteIcon modIcon; private readonly SpriteIcon background; @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.UI protected override void LoadComplete() { base.LoadComplete(); - Highlighted.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); + Selected.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); } } } From eb2f7c1d0a63f2bd0aa21cc56eeb61f58a066d5a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 20:37:02 +0300 Subject: [PATCH 4134/5608] Rename forgotten variable --- osu.Game/Rulesets/UI/ModIcon.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 1be70ff48f..945dbe4cc9 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.UI protected override void LoadComplete() { base.LoadComplete(); - Selected.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); + Selected.BindValueChanged(selected => background.Colour = selected.NewValue ? highlightedColour : backgroundColour, true); } } } From ab42fac43abe3250ece9eb306e07ad2a49db94cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 02:38:31 +0900 Subject: [PATCH 4135/5608] Improve naming --- .../{BackgroundMode.cs => BackgroundSource.cs} | 4 ++-- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- .../Overlays/Settings/Sections/Audio/MainMenuSettings.cs | 8 ++++---- osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) rename osu.Game/Configuration/{BackgroundMode.cs => BackgroundSource.cs} (81%) diff --git a/osu.Game/Configuration/BackgroundMode.cs b/osu.Game/Configuration/BackgroundSource.cs similarity index 81% rename from osu.Game/Configuration/BackgroundMode.cs rename to osu.Game/Configuration/BackgroundSource.cs index 50d54f1eb2..5726e96eb1 100644 --- a/osu.Game/Configuration/BackgroundMode.cs +++ b/osu.Game/Configuration/BackgroundSource.cs @@ -3,9 +3,9 @@ namespace osu.Game.Configuration { - public enum BackgroundMode + public enum BackgroundSource { - Default, + Skin, Beatmap } } diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index b847f96a1f..b71463841a 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -118,7 +118,7 @@ namespace osu.Game.Configuration Set(OsuSetting.IntroSequence, IntroSequence.Triangles); - Set(OsuSetting.BackgroundMode, BackgroundMode.Default); + Set(OsuSetting.MenuBackgroundSource, BackgroundSource.Skin); } public OsuConfigManager(Storage storage) @@ -189,6 +189,6 @@ namespace osu.Game.Configuration IntroSequence, UIHoldActivationDelay, HitLighting, - BackgroundMode + MenuBackgroundSource } } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs index 76a6aafe45..a303f93b34 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs @@ -34,11 +34,11 @@ namespace osu.Game.Overlays.Settings.Sections.Audio Bindable = config.GetBindable(OsuSetting.IntroSequence), Items = Enum.GetValues(typeof(IntroSequence)).Cast() }, - new SettingsDropdown + new SettingsDropdown { - LabelText = "Background", - Bindable = config.GetBindable(OsuSetting.BackgroundMode), - Items = Enum.GetValues(typeof(BackgroundMode)).Cast() + LabelText = "Background source", + Bindable = config.GetBindable(OsuSetting.MenuBackgroundSource), + Items = Enum.GetValues(typeof(BackgroundSource)).Cast() } }; } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index d49751f511..095985e9d1 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Backgrounds private Bindable user; private Bindable skin; - private Bindable mode; + private Bindable mode; [Resolved] private IBindable beatmap { get; set; } @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Backgrounds { user = api.LocalUser.GetBoundCopy(); skin = skinManager.CurrentSkin.GetBoundCopy(); - mode = config.GetBindable(OsuSetting.BackgroundMode); + mode = config.GetBindable(OsuSetting.MenuBackgroundSource); user.ValueChanged += _ => Next(); skin.ValueChanged += _ => Next(); @@ -78,7 +78,7 @@ namespace osu.Game.Screens.Backgrounds { switch (mode.Value) { - case BackgroundMode.Beatmap: + case BackgroundSource.Beatmap: newBackground = new BeatmapBackground(beatmap.Value, backgroundName); break; From 57d38c5c74c956e36920f43de95a4af9c11a0f9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 02:39:54 +0900 Subject: [PATCH 4136/5608] Add final newline --- osu.Game/Graphics/Backgrounds/BeatmapBackground.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs index 40c6dae43c..387e189dc4 100644 --- a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs @@ -25,4 +25,4 @@ namespace osu.Game.Graphics.Backgrounds Sprite.Texture = Beatmap?.Background ?? textures.Get(fallbackTextureName); } } -} \ No newline at end of file +} From e170cd289269f9a028fb699953f2a28551a3e570 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 10:29:16 +0900 Subject: [PATCH 4137/5608] Move private methods below --- .../BeatmapSet/LeaderboardModSelector.cs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index a6f69617d0..60fd520681 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -57,6 +57,18 @@ namespace osu.Game.Overlays.BeatmapSet modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); } + protected override bool OnHover(HoverEvent e) + { + updateHighlighted(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + updateHighlighted(); + } + private void selectionChanged(Mod mod, bool selected) { if (selected) @@ -75,18 +87,6 @@ namespace osu.Game.Overlays.BeatmapSet modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = !IsHovered); } - protected override bool OnHover(HoverEvent e) - { - updateHighlighted(); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - updateHighlighted(); - } - public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); private class ModButton : ModIcon From d8260f4a6511ce6118507f114e06eed4cd0bc229 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 10:51:49 +0900 Subject: [PATCH 4138/5608] Reduce carousel scroll motion on initial display --- osu.Game/Screens/Select/BeatmapCarousel.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 538656a5fa..17736e7819 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -640,10 +640,19 @@ namespace osu.Game.Screens.Select itemsCache.Validate(); } + private bool firstScroll = true; + private void updateScrollPosition() { if (scrollTarget != null) { + if (firstScroll) + { + // reduce movement when first displaying the carousel. + scroll.ScrollTo(scrollTarget.Value - 200, false); + firstScroll = false; + } + scroll.ScrollTo(scrollTarget.Value); scrollPositionCache.Validate(); } From da425c93fac6a629490690a3555d8d84e64e4118 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 22 Nov 2019 05:08:50 +0300 Subject: [PATCH 4139/5608] Fix beatmap switch doesn't trigger scores update --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 3e3f823368..b33b5feb4d 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -193,7 +193,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores var beatmapRuleset = beatmap.NewValue?.Ruleset; if (ruleset.Value?.Equals(beatmapRuleset) ?? false) + { modSelector.DeselectAll(); + ruleset.TriggerChange(); + } else ruleset.Value = beatmapRuleset; From 745047fd193ce406f4c6d2896429279918536d67 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 22 Nov 2019 05:10:47 +0300 Subject: [PATCH 4140/5608] Remove useless line from ModIcon --- osu.Game/Rulesets/UI/ModIcon.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index c22120d6e0..945dbe4cc9 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -107,8 +107,6 @@ namespace osu.Game.Rulesets.UI modIcon.Colour = colours.Yellow; break; } - - background.Colour = backgroundColour; } protected override void LoadComplete() From f079ebe857ebf708c5aae6ee0a7c102ea4c9c5f5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 16:13:48 +0900 Subject: [PATCH 4141/5608] Simplify beatmap lookup to use a single endpoint --- osu.Game/Online/API/Requests/GetBeatmapRequest.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs index b37a6804fe..8e92cf0611 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs @@ -10,13 +10,11 @@ namespace osu.Game.Online.API.Requests { private readonly BeatmapInfo beatmap; - private string lookupString => beatmap.OnlineBeatmapID > 0 ? beatmap.OnlineBeatmapID.ToString() : $@"lookup?checksum={beatmap.MD5Hash}&filename={System.Uri.EscapeUriString(beatmap.Path)}"; - public GetBeatmapRequest(BeatmapInfo beatmap) { this.beatmap = beatmap; } - protected override string Target => $@"beatmaps/{lookupString}"; + protected override string Target => $@"beatmaps/lookup?id={beatmap.OnlineBeatmapID}&checksum={beatmap.MD5Hash}&filename={System.Uri.EscapeUriString(beatmap.Path)}"; } } From 0cc1698b6d1764b183e663db9d27f7d3e2b5ee0e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 18:05:12 +0900 Subject: [PATCH 4142/5608] Rename incorrectly named container --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index b33b5feb4d..ac39671f56 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly ScoreTable scoreTable; private readonly FillFlowContainer topScoresContainer; private readonly DimmedLoadingLayer loading; - private readonly FillFlowContainer modFilter; + private readonly FillFlowContainer filterControls; private readonly LeaderboardModSelector modSelector; private readonly NoScoresPlaceholder noScoresPlaceholder; private readonly FillFlowContainer content; @@ -94,7 +94,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { - modFilter = new FillFlowContainer + filterControls = new FillFlowContainer { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -207,7 +207,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { scope.Value = BeatmapLeaderboardScope.Global; modSelector.DeselectAll(); - modFilter.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter ? 1 : 0); + filterControls.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter ? 1 : 0); } private void getScores() From 16bdf4e6bd250ac5dd9cb6fa497d80e984002af1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 18:07:56 +0900 Subject: [PATCH 4143/5608] Update english to be more readable --- osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs index aefff5d567..9cfce4ef5b 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs @@ -27,16 +27,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores switch (scope) { default: - case BeatmapLeaderboardScope.Global: - text.Text = @"No scores yet. Maybe should try setting some?"; + text.Text = @"No scores have been set yet. Maybe you can be the first!"; return; case BeatmapLeaderboardScope.Friend: - text.Text = @"None of your friends has set a score on this map yet!"; + text.Text = @"None of your friends have set a score on this map yet."; return; case BeatmapLeaderboardScope.Country: - text.Text = @"No one from your country has set a score on this map yet!"; + text.Text = @"No one from your country has set a score on this map yet."; return; } } From dad2e5c678dc6f781ea46d4e6acf82411da46bd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 18:10:44 +0900 Subject: [PATCH 4144/5608] Improve legibility of NoScroesPlaceholder --- .../BeatmapSet/Scores/NoScoresPlaceholder.cs | 21 +++++++++++-------- .../BeatmapSet/Scores/ScoresContainer.cs | 8 ++----- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs index 9cfce4ef5b..391ba93a4b 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs @@ -3,9 +3,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; using osu.Game.Screens.Select.Leaderboards; using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -16,27 +16,30 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public NoScoresPlaceholder() { AutoSizeAxes = Axes.Both; - Child = text = new SpriteText - { - Font = OsuFont.GetFont(), - }; + Child = text = new OsuSpriteText(); } - public void UpdateText(BeatmapLeaderboardScope scope) + public override void Show() => this.FadeIn(200, Easing.OutQuint); + + public override void Hide() => this.FadeOut(200, Easing.OutQuint); + + public void ShowWithScope(BeatmapLeaderboardScope scope) { + Show(); + switch (scope) { default: text.Text = @"No scores have been set yet. Maybe you can be the first!"; - return; + break; case BeatmapLeaderboardScope.Friend: text.Text = @"None of your friends have set a score on this map yet."; - return; + break; case BeatmapLeaderboardScope.Country: text.Text = @"No one from your country has set a score on this map yet."; - return; + break; } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index ac39671f56..86fb455eb8 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -23,7 +23,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public class ScoresContainer : CompositeDrawable { private const int spacing = 15; - private const int duration = 200; public readonly Bindable Beatmap = new Bindable(); private readonly Bindable ruleset = new Bindable(); @@ -215,7 +214,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores getScoresRequest?.Cancel(); getScoresRequest = null; - noScoresPlaceholder.FadeOut(duration, Easing.OutQuint); + noScoresPlaceholder.Hide(); if (Beatmap.Value?.OnlineBeatmapID.HasValue != true || Beatmap.Value.Status <= BeatmapSetOnlineStatus.Pending) { @@ -233,10 +232,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Scores = scores; if (!scores.Scores.Any()) - { - noScoresPlaceholder.UpdateText(scope.Value); - noScoresPlaceholder.FadeIn(duration, Easing.OutQuint); - } + noScoresPlaceholder.ShowWithScope(scope.Value); }; api.Queue(getScoresRequest); } From 66e2a259f0fcdcf7e349816f8f83a918edd7fcea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 18:21:40 +0900 Subject: [PATCH 4145/5608] Fix usage of SpriteText instead of OsuSpriteText --- CodeAnalysis/BannedSymbols.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt index 9fb86485d2..3ad8d5db5b 100644 --- a/CodeAnalysis/BannedSymbols.txt +++ b/CodeAnalysis/BannedSymbols.txt @@ -2,3 +2,4 @@ M:System.Object.Equals(System.Object,System.Object)~System.Boolean;Don't use obj 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. T:System.IComparable;Don't use non-generic IComparable. Use generic version instead. +T:osu.Framework.Graphics.Sprites.SpriteText;Use OsuSpriteText. From b026197859bd0fb362f80323621f7a53576d3fbd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 18:23:48 +0900 Subject: [PATCH 4146/5608] Add spacing --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 86fb455eb8..f6f4b39c14 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -225,6 +225,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores content.Show(); loading.Show(); + getScoresRequest = new GetScoresRequest(Beatmap.Value, Beatmap.Value.Ruleset, scope.Value, modSelector.SelectedMods); getScoresRequest.Success += scores => { @@ -234,6 +235,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (!scores.Scores.Any()) noScoresPlaceholder.ShowWithScope(scope.Value); }; + api.Queue(getScoresRequest); } } From 6469199f0dd594049208f1634d127d4d04a4b5ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 19:47:21 +0900 Subject: [PATCH 4147/5608] 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 0f0e82d56a..0da3e66236 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -55,6 +55,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 28ef7d3d92..449b4dc4e3 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 364b0b2c78..871a9238e3 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,7 +73,7 @@ - + @@ -81,7 +81,7 @@ - + From c2e85a205733bfad5d8433d5688dd94dd81f0012 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 19:49:20 +0900 Subject: [PATCH 4148/5608] Apply CornerExponent fixes --- .../Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs | 2 ++ .../Objects/Drawables/Connections/FollowPoint.cs | 3 +-- .../Objects/Drawables/Pieces/CirclePiece.cs | 2 ++ osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs | 3 +-- osu.Game.Tournament/Components/SongBar.cs | 2 ++ osu.Game.Tournament/Components/TournamentBeatmapPanel.cs | 1 + osu.Game/Overlays/Comments/DrawableComment.cs | 1 + osu.Game/Overlays/Volume/MuteButton.cs | 1 + osu.Game/Screens/Edit/Components/CircularButton.cs | 1 + osu.Game/Users/Drawables/UpdateableAvatar.cs | 6 ++++++ 10 files changed, 18 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs index 2b6b93a590..2868ddeaa4 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs @@ -17,7 +17,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components Origin = Anchor.Centre; Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); + CornerRadius = Size.X / 2; + CornerExponent = 2; InternalChild = new RingPiece(); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index db34ae1d87..7e530ca047 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -25,11 +25,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { Origin = Anchor.Centre; - Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.FollowPoint), _ => new Container + Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.FollowPoint), _ => new CircularContainer { Masking = true, AutoSizeAxes = Axes.Both, - CornerRadius = width / 2, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index 210d5ff839..aab01f45d4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -16,7 +16,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Masking = true; + CornerRadius = Size.X / 2; + CornerExponent = 2; Anchor = Anchor.Centre; Origin = Anchor.Centre; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs index c97b74756a..82e4383143 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs @@ -18,10 +18,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Anchor = Anchor.Centre; Origin = Anchor.Centre; - InternalChild = new Container + InternalChild = new CircularContainer { Masking = true, - CornerRadius = Size.X / 2, BorderThickness = 10, BorderColour = Color4.White, RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 7005c068ae..43958aca7a 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -106,6 +106,7 @@ namespace osu.Game.Tournament.Components Width = main_width, Height = TournamentBeatmapPanel.HEIGHT, CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, + CornerExponent = 2, Children = new Drawable[] { new Box @@ -126,6 +127,7 @@ namespace osu.Game.Tournament.Components { Masking = true, CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, + CornerExponent = 2, Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 0908814537..51483a0964 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -52,6 +52,7 @@ namespace osu.Game.Tournament.Components currentMatch.BindTo(ladder.CurrentMatch); CornerRadius = HEIGHT / 2; + CornerExponent = 2; Masking = true; AddRangeInternal(new Drawable[] diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 3fb9867f0e..0d00f7c63b 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -100,6 +100,7 @@ namespace osu.Game.Overlays.Comments Size = new Vector2(avatar_size), Masking = true, CornerRadius = avatar_size / 2f, + CornerExponent = 2, }, } }, diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index 6d876a77b1..bcc9394aba 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.cs @@ -43,6 +43,7 @@ namespace osu.Game.Overlays.Volume { Content.BorderThickness = 3; Content.CornerRadius = HEIGHT / 2; + Content.CornerExponent = 2; Size = new Vector2(width, HEIGHT); diff --git a/osu.Game/Screens/Edit/Components/CircularButton.cs b/osu.Game/Screens/Edit/Components/CircularButton.cs index 931c7d03a0..40b5ac663a 100644 --- a/osu.Game/Screens/Edit/Components/CircularButton.cs +++ b/osu.Game/Screens/Edit/Components/CircularButton.cs @@ -20,6 +20,7 @@ namespace osu.Game.Screens.Edit.Components { base.Update(); Content.CornerRadius = DrawHeight / 2f; + Content.CornerExponent = 2; } } } diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index 795b90ba11..59fbb5f910 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -31,6 +31,12 @@ namespace osu.Game.Users.Drawables set => base.CornerRadius = value; } + public new float CornerExponent + { + get => base.CornerExponent; + set => base.CornerExponent = value; + } + public new EdgeEffectParameters EdgeEffect { get => base.EdgeEffect; From d0002cc1c25e9da8ede3277257c588b884a28c65 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 19:50:30 +0900 Subject: [PATCH 4149/5608] Update performance logging setting --- osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs index 7eec971b62..457f064f89 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Settings.Sections.Debug new SettingsCheckbox { LabelText = "Performance logging", - Bindable = frameworkConfig.GetBindable(FrameworkSetting.PerformanceLogging) + Bindable = config.GetBindable(DebugSetting.PerformanceLogging) }, new SettingsCheckbox { From 4063135a3a894e262f880cca2b91904c51fb33c2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 20:45:05 +0900 Subject: [PATCH 4150/5608] Fix result mode button's corner exponent --- osu.Game/Screens/Ranking/ResultModeButton.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Ranking/ResultModeButton.cs b/osu.Game/Screens/Ranking/ResultModeButton.cs index 1383511241..38636b0c3b 100644 --- a/osu.Game/Screens/Ranking/ResultModeButton.cs +++ b/osu.Game/Screens/Ranking/ResultModeButton.cs @@ -36,7 +36,9 @@ namespace osu.Game.Screens.Ranking Size = new Vector2(50); Masking = true; + CornerRadius = 25; + CornerExponent = 2; activeColour = colours.PinkDarker; inactiveColour = OsuColour.Gray(0.8f); From 4cb09df754aa0b03e145936660cd518117b1959d Mon Sep 17 00:00:00 2001 From: Albie Spriddell Date: Fri, 22 Nov 2019 18:23:48 +0000 Subject: [PATCH 4151/5608] increase padding --- osu.Game/Overlays/Mods/ModSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 3b16189e73..9c0a164ad6 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -167,7 +167,7 @@ namespace osu.Game.Overlays.Mods Spacing = new Vector2(50f, 0f), Margin = new MarginPadding { - Top = 6, + Top = 20, }, AlwaysPresent = true }, From d6c9387bebcc44dafc92693e6e6d6ceb3f46117e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 22 Nov 2019 21:55:21 +0300 Subject: [PATCH 4152/5608] Implement NotSupporterPlaceholder --- .../Online/TestSceneBeatmapSetOverlay.cs | 1 + .../Scores/NotSupporterPlaceholder.cs | 51 +++++++++++++++++++ .../BeatmapSet/Scores/ScoresContainer.cs | 1 + 3 files changed, 53 insertions(+) create mode 100644 osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 286971bc90..5ca2c9868f 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -42,6 +42,7 @@ namespace osu.Game.Tests.Visual.Online typeof(BeatmapAvailability), typeof(BeatmapRulesetSelector), typeof(BeatmapRulesetTabItem), + typeof(NotSupporterPlaceholder) }; protected override bool UseOnlineAPI => true; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs new file mode 100644 index 0000000000..86b02c0cff --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs @@ -0,0 +1,51 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osuTK; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Overlays.BeatmapSet.Scores +{ + public class NotSupporterPlaceholder : Container + { + public NotSupporterPlaceholder() + { + LinkFlowContainer text; + + AutoSizeAxes = Axes.Both; + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = @"You need to be an osu!supporter to access the friend and country rankings!", + Font = OsuFont.GetFont(weight: FontWeight.Bold), + }, + text = new LinkFlowContainer(t => t.Font = t.Font.With(size: 12)) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + } + } + }; + + text.AddText("Click "); + text.AddLink("here", "/home/support"); + text.AddText(" to see all the fancy features that you can get!"); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index f6f4b39c14..fe42ef2975 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -106,6 +106,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Current = { BindTarget = scope } }, + new NotSupporterPlaceholder(), modSelector = new LeaderboardModSelector { Ruleset = { BindTarget = ruleset } From aede1b183a597b0a354f2919e7787928eb409445 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 22 Nov 2019 22:04:58 +0300 Subject: [PATCH 4153/5608] Make ScopeSelector always visible --- .../Scores/NotSupporterPlaceholder.cs | 2 -- .../BeatmapSet/Scores/ScoresContainer.cs | 22 +++++++++++++------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs index 86b02c0cff..ba08a78a61 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs @@ -17,8 +17,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores LinkFlowContainer text; AutoSizeAxes = Axes.Both; - Anchor = Anchor.TopCentre; - Origin = Anchor.TopCentre; Child = new FillFlowContainer { AutoSizeAxes = Axes.Both, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index fe42ef2975..0389d4cf25 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -33,10 +33,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly ScoreTable scoreTable; private readonly FillFlowContainer topScoresContainer; private readonly DimmedLoadingLayer loading; - private readonly FillFlowContainer filterControls; private readonly LeaderboardModSelector modSelector; private readonly NoScoresPlaceholder noScoresPlaceholder; private readonly FillFlowContainer content; + private readonly NotSupporterPlaceholder notSupporterPlaceholder; [Resolved] private IAPIProvider api { get; set; } @@ -93,22 +93,30 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { - filterControls = new FillFlowContainer + new FillFlowContainer { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - AutoSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, Spacing = new Vector2(0, spacing), Children = new Drawable[] { new LeaderboardScopeSelector { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Current = { BindTarget = scope } }, - new NotSupporterPlaceholder(), + notSupporterPlaceholder = new NotSupporterPlaceholder + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Alpha = 0, + }, modSelector = new LeaderboardModSelector { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Ruleset = { BindTarget = ruleset } } } @@ -207,7 +215,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { scope.Value = BeatmapLeaderboardScope.Global; modSelector.DeselectAll(); - filterControls.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter ? 1 : 0); + modSelector.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter ? 1 : 0); } private void getScores() From 2e161f7e997538dea478ca788a895473006ebd27 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 22 Nov 2019 22:25:58 +0300 Subject: [PATCH 4154/5608] Hook up the rest of the logic --- .../BeatmapSet/Scores/ScoresContainer.cs | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 0389d4cf25..e91d12b9fc 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public readonly Bindable Beatmap = new Bindable(); private readonly Bindable ruleset = new Bindable(); - private readonly Bindable scope = new Bindable(); + private readonly Bindable scope = new Bindable(BeatmapLeaderboardScope.Global); private readonly Bindable user = new Bindable(); private readonly Box background; @@ -107,12 +107,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.TopCentre, Current = { BindTarget = scope } }, - notSupporterPlaceholder = new NotSupporterPlaceholder - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Alpha = 0, - }, modSelector = new LeaderboardModSelector { Anchor = Anchor.TopCentre, @@ -136,6 +130,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores AlwaysPresent = true, Margin = new MarginPadding { Vertical = 10 } }, + notSupporterPlaceholder = new NotSupporterPlaceholder + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Alpha = 0, + }, new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -213,9 +213,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void onUserChanged(ValueChangedEvent user) { - scope.Value = BeatmapLeaderboardScope.Global; modSelector.DeselectAll(); - modSelector.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter ? 1 : 0); + modSelector.FadeTo(userIsSupporter ? 1 : 0); + getScores(); } private void getScores() @@ -232,6 +232,18 @@ namespace osu.Game.Overlays.BeatmapSet.Scores return; } + if (scope.Value != BeatmapLeaderboardScope.Global && !userIsSupporter) + { + Scores = null; + notSupporterPlaceholder.Show(); + loading.Hide(); + return; + } + else + { + notSupporterPlaceholder.Hide(); + } + content.Show(); loading.Show(); @@ -247,5 +259,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores api.Queue(getScoresRequest); } + + private bool userIsSupporter => api.IsLoggedIn && api.LocalUser.Value.IsSupporter; } } From e3f3b1ab1a1101f86e7b9cdfe6c3d1af7c3c5226 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Nov 2019 20:52:41 +0900 Subject: [PATCH 4155/5608] Display useful statistics on song bar depending on current ruleset --- osu.Game.Tournament/Components/SongBar.cs | 48 +++++++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 43958aca7a..4a738ae36b 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,6 +14,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets; using osu.Game.Screens.Menu; using osuTK; using osuTK.Graphics; @@ -23,6 +25,9 @@ namespace osu.Game.Tournament.Components { private BeatmapInfo beatmap; + [Resolved] + private IBindable ruleset { get; set; } + public BeatmapInfo Beatmap { get => beatmap; @@ -165,7 +170,8 @@ namespace osu.Game.Tournament.Components string hardRockExtra = ""; string srExtra = ""; - //var ar = beatmap.BaseDifficulty.ApproachRate; + var ar = beatmap.BaseDifficulty.ApproachRate; + if ((mods & LegacyMods.HardRock) > 0) { hardRockExtra = "*"; @@ -174,12 +180,43 @@ namespace osu.Game.Tournament.Components if ((mods & LegacyMods.DoubleTime) > 0) { - //ar *= 1.5f; + ar *= 1.5f; bpm *= 1.5f; length /= 1.5f; srExtra = "*"; } + (string heading, string content)[] stats; + + switch (ruleset.Value.ID) + { + default: + stats = new (string heading, string content)[] + { + ("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), + ("AR", $"{ar:0.#}{srExtra}"), + ("OD", $"{beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}"), + }; + break; + + case 1: + case 3: + stats = new (string heading, string content)[] + { + ("OD", $"{beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}"), + ("HP", $"{beatmap.BaseDifficulty.DrainRate:0.#}{hardRockExtra}") + }; + break; + + case 2: + stats = new (string heading, string content)[] + { + ("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), + ("AR", $"{ar:0.#}{srExtra}"), + }; + break; + } + panelContents.Children = new Drawable[] { new DiffPiece(("Length", TimeSpan.FromMilliseconds(length).ToString(@"mm\:ss"))) @@ -192,12 +229,7 @@ namespace osu.Game.Tournament.Components Anchor = Anchor.CentreLeft, Origin = Anchor.TopLeft }, - new DiffPiece( - //("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), - //("AR", $"{ar:0.#}{srExtra}"), - ("OD", $"{beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}"), - ("HP", $"{beatmap.BaseDifficulty.DrainRate:0.#}{hardRockExtra}") - ) + new DiffPiece(stats) { Anchor = Anchor.CentreRight, Origin = Anchor.BottomRight From eb81d15463721c4e3abaf9a89fbef8a9a5eca562 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Nov 2019 20:52:55 +0900 Subject: [PATCH 4156/5608] Don't attempt to repopulate already populated users on startup --- osu.Game.Tournament/TournamentGameBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index f2a158971b..ec696c818d 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -202,7 +202,8 @@ namespace osu.Game.Tournament { foreach (var p in t.Players) { - PopulateUser(p); + if (p.Username == null || p.Statistics == null) + PopulateUser(p); addedInfo = true; } } @@ -243,7 +244,6 @@ namespace osu.Game.Tournament { user.Username = res.Username; user.Statistics = res.Statistics; - user.Username = res.Username; user.Country = res.Country; user.Cover = res.Cover; From 65d71b94424ab46a3fa307784a8637334d75f172 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Nov 2019 20:54:01 +0900 Subject: [PATCH 4157/5608] Fix beatmap lookups failing for beatmaps with no local path Turns out the underlying EscapeUriString doesn't like nulls --- osu.Game/Online/API/Requests/GetBeatmapRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs index 8e92cf0611..87925b94c6 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs @@ -15,6 +15,6 @@ namespace osu.Game.Online.API.Requests this.beatmap = beatmap; } - protected override string Target => $@"beatmaps/lookup?id={beatmap.OnlineBeatmapID}&checksum={beatmap.MD5Hash}&filename={System.Uri.EscapeUriString(beatmap.Path)}"; + protected override string Target => $@"beatmaps/lookup?id={beatmap.OnlineBeatmapID}&checksum={beatmap.MD5Hash}&filename={System.Uri.EscapeUriString(beatmap.Path ?? string.Empty)}"; } } From 1bd9fa413e76c4f65300cf1005ba8231e9548be3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Nov 2019 23:29:34 +0900 Subject: [PATCH 4158/5608] Fix incorrect NativeLibs version reference --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 871a9238e3..ff6839f5ca 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -86,6 +86,6 @@ - + From 326a8f62eb49da63a172a4a6eb8aadbfeb35570a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 Nov 2019 00:21:34 +0900 Subject: [PATCH 4159/5608] Calculate more correct AR locally for now --- osu.Game.Tournament/Components/SongBar.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 4a738ae36b..23dc4bb22c 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -180,7 +180,10 @@ namespace osu.Game.Tournament.Components if ((mods & LegacyMods.DoubleTime) > 0) { - ar *= 1.5f; + // temporary local calculation (taken from OsuDifficultyCalculator) + double preempt = (int)BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / 1.5; + ar = (float)(preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5); + bpm *= 1.5f; length /= 1.5f; srExtra = "*"; From 244177880e3ce004a11942e469cbdbe91f2eca1a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 Nov 2019 01:45:21 +0900 Subject: [PATCH 4160/5608] Only show star on HR --- osu.Game.Tournament/Components/SongBar.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 23dc4bb22c..727dddeb7b 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -197,7 +197,7 @@ namespace osu.Game.Tournament.Components stats = new (string heading, string content)[] { ("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), - ("AR", $"{ar:0.#}{srExtra}"), + ("AR", $"{ar:0.#}{hardRockExtra}"), ("OD", $"{beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}"), }; break; @@ -215,7 +215,7 @@ namespace osu.Game.Tournament.Components stats = new (string heading, string content)[] { ("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), - ("AR", $"{ar:0.#}{srExtra}"), + ("AR", $"{ar:0.#}"), }; break; } From 20edaf4ba6a04adf9836ef4c3f2b2b61991e6a21 Mon Sep 17 00:00:00 2001 From: Albie Spriddell Date: Sat, 23 Nov 2019 17:32:16 +0000 Subject: [PATCH 4161/5608] add cinema mod support --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 6 ++++-- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 6 ++++-- osu.Game.Rulesets.Osu/OsuRuleset.cs | 6 ++++-- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 6 ++++-- osu.Game/Rulesets/Mods/ModCinema.cs | 24 ++++++++++++++++++++++-- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 71d68ace94..bf2b1c0def 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -51,7 +51,9 @@ namespace osu.Game.Rulesets.Catch else if (mods.HasFlag(LegacyMods.SuddenDeath)) yield return new CatchModSuddenDeath(); - if (mods.HasFlag(LegacyMods.Autoplay)) + if (mods.HasFlag(LegacyMods.Cinema)) + yield return new CatchModCinema(); + else if (mods.HasFlag(LegacyMods.Autoplay)) yield return new CatchModAutoplay(); if (mods.HasFlag(LegacyMods.Easy)) @@ -101,7 +103,7 @@ namespace osu.Game.Rulesets.Catch case ModType.Automation: return new Mod[] { - new MultiMod(new CatchModAutoplay(), new ModCinema()), + new MultiMod(new CatchModAutoplay(), new CatchModCinema()), new CatchModRelax(), }; diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index c74a292331..c632cc0b7b 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -51,7 +51,9 @@ namespace osu.Game.Rulesets.Mania else if (mods.HasFlag(LegacyMods.SuddenDeath)) yield return new ManiaModSuddenDeath(); - if (mods.HasFlag(LegacyMods.Autoplay)) + if (mods.HasFlag(LegacyMods.Cinema)) + yield return new ManiaModCinema(); + else if (mods.HasFlag(LegacyMods.Autoplay)) yield return new ManiaModAutoplay(); if (mods.HasFlag(LegacyMods.Easy)) @@ -148,7 +150,7 @@ namespace osu.Game.Rulesets.Mania case ModType.Automation: return new Mod[] { - new MultiMod(new ManiaModAutoplay(), new ModCinema()), + new MultiMod(new ManiaModAutoplay(), new ManiaModCinema()), }; case ModType.Fun: diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index fa69cec78d..2b5a0df3ed 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -60,7 +60,9 @@ namespace osu.Game.Rulesets.Osu if (mods.HasFlag(LegacyMods.Autopilot)) yield return new OsuModAutopilot(); - if (mods.HasFlag(LegacyMods.Autoplay)) + if (mods.HasFlag(LegacyMods.Cinema)) + yield return new OsuModCinema(); + else if (mods.HasFlag(LegacyMods.Autoplay)) yield return new OsuModAutoplay(); if (mods.HasFlag(LegacyMods.Easy)) @@ -126,7 +128,7 @@ namespace osu.Game.Rulesets.Osu case ModType.Automation: return new Mod[] { - new MultiMod(new OsuModAutoplay(), new ModCinema()), + new MultiMod(new OsuModAutoplay(), new OsuModCinema()), new OsuModRelax(), new OsuModAutopilot(), }; diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index b2655f592c..3f3a198f4a 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -50,7 +50,9 @@ namespace osu.Game.Rulesets.Taiko else if (mods.HasFlag(LegacyMods.SuddenDeath)) yield return new TaikoModSuddenDeath(); - if (mods.HasFlag(LegacyMods.Autoplay)) + if (mods.HasFlag(LegacyMods.Cinema)) + yield return new TaikoModCinema(); + else if (mods.HasFlag(LegacyMods.Autoplay)) yield return new TaikoModAutoplay(); if (mods.HasFlag(LegacyMods.Easy)) @@ -100,7 +102,7 @@ namespace osu.Game.Rulesets.Taiko case ModType.Automation: return new Mod[] { - new MultiMod(new TaikoModAutoplay(), new ModCinema()), + new MultiMod(new TaikoModAutoplay(), new TaikoModCinema()), new TaikoModRelax(), }; diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs index 3c6a3a54aa..4396c3384b 100644 --- a/osu.Game/Rulesets/Mods/ModCinema.cs +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -3,15 +3,35 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.UI; +using osu.Game.Screens.Play; namespace osu.Game.Rulesets.Mods { - public class ModCinema : ModAutoplay + public abstract class ModCinema : ModCinema, IApplicableToDrawableRuleset + where T : HitObject + { + public virtual void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) + { + drawableRuleset.SetReplayScore(CreateReplayScore(drawableRuleset.Beatmap)); + + drawableRuleset.Playfield.AlwaysPresent = true; + drawableRuleset.Playfield.Hide(); + } + } + + public class ModCinema : ModAutoplay, IApplicableToHUD { public override string Name => "Cinema"; public override string Acronym => "CN"; - public override bool HasImplementation => false; public override IconUsage Icon => OsuIcon.ModCinema; public override string Description => "Watch the video without visual distractions."; + + public void ApplyToHUD(HUDOverlay overlay) + { + overlay.AlwaysPresent = true; + overlay.Hide(); + } } } From 3b9f59cb335bb84964737fca27138668127cd371 Mon Sep 17 00:00:00 2001 From: Albie Spriddell Date: Sat, 23 Nov 2019 17:34:53 +0000 Subject: [PATCH 4162/5608] add cinema mod support --- .../Mods/CatchModCinema.cs | 21 ++++++++++++++++ .../Mods/ManiaModCinema.cs | 22 ++++++++++++++++ osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs | 25 +++++++++++++++++++ .../Mods/TaikoModCinema.cs | 21 ++++++++++++++++ 4 files changed, 89 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs create mode 100644 osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs create mode 100644 osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs b/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs new file mode 100644 index 0000000000..3bc1ee5bf5 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Replays; +using osu.Game.Rulesets.Mods; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModCinema : ModCinema + { + public override Score CreateReplayScore(IBeatmap beatmap) => new Score + { + ScoreInfo = new ScoreInfo { User = new User { Username = "osu!salad!" } }, + Replay = new CatchAutoGenerator(beatmap).Generate(), + }; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs new file mode 100644 index 0000000000..02c1fc1b79 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Replays; +using osu.Game.Rulesets.Mods; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModCinema : ModCinema + { + public override Score CreateReplayScore(IBeatmap beatmap) => new Score + { + ScoreInfo = new ScoreInfo { User = new User { Username = "osu!topus!" } }, + Replay = new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(), + }; + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs b/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs new file mode 100644 index 0000000000..5d9a524577 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModCinema.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 System; +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Replays; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModCinema : ModCinema + { + public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray(); + + public override Score CreateReplayScore(IBeatmap beatmap) => new Score + { + ScoreInfo = new ScoreInfo { User = new User { Username = "Autoplay" } }, + Replay = new OsuAutoGenerator(beatmap).Generate() + }; + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs new file mode 100644 index 0000000000..71aa007d3b --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Replays; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModCinema : ModCinema + { + public override Score CreateReplayScore(IBeatmap beatmap) => new Score + { + ScoreInfo = new ScoreInfo { User = new User { Username = "mekkadosu!" } }, + Replay = new TaikoAutoGenerator(beatmap).Generate(), + }; + } +} From 29b05e293913c75490242416786c9a537b307041 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 24 Nov 2019 00:01:49 +0300 Subject: [PATCH 4163/5608] Fix getScores can be fired twice on user change --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index e91d12b9fc..d65a03acad 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -213,9 +213,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void onUserChanged(ValueChangedEvent user) { - modSelector.DeselectAll(); + if (modSelector.SelectedMods.Any()) + modSelector.DeselectAll(); + else + getScores(); + modSelector.FadeTo(userIsSupporter ? 1 : 0); - getScores(); } private void getScores() From 96533631fc546046a2b75f94d10324a0145aa446 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 24 Nov 2019 01:29:11 +0300 Subject: [PATCH 4164/5608] Simplify if/else statement --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index d65a03acad..112903b0f3 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -242,10 +242,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores loading.Hide(); return; } - else - { - notSupporterPlaceholder.Hide(); - } + + notSupporterPlaceholder.Hide(); content.Show(); loading.Show(); From 1e24ee795613543c1d32756a374a6ec2168a7540 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 24 Nov 2019 02:07:56 +0300 Subject: [PATCH 4165/5608] Remove ClearComboColours() --- osu.Game/Beatmaps/Formats/IHasComboColours.cs | 5 ----- osu.Game/Skinning/SkinConfiguration.cs | 2 -- 2 files changed, 7 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/IHasComboColours.cs b/osu.Game/Beatmaps/Formats/IHasComboColours.cs index 5ef31c1904..ac0d32dbaa 100644 --- a/osu.Game/Beatmaps/Formats/IHasComboColours.cs +++ b/osu.Game/Beatmaps/Formats/IHasComboColours.cs @@ -17,10 +17,5 @@ namespace osu.Game.Beatmaps.Formats /// Adds combo colours to the list. /// void AddComboColours(params Color4[] colours); - - /// - /// Clear current combo colours from the list. - /// - void ClearComboColours(); } } diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index da833acd98..94a1160b38 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -48,8 +48,6 @@ namespace osu.Game.Skinning public void AddComboColours(params Color4[] colours) => colours.ForEach(c => comboColours.Add(c)); - public void ClearComboColours() => comboColours.Clear(); - public Dictionary CustomColours { get; set; } = new Dictionary(); public readonly Dictionary ConfigDictionary = new Dictionary(); From 0f9978b34a8e250ba6458dd9ecee6eb90529a403 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 24 Nov 2019 02:08:36 +0300 Subject: [PATCH 4166/5608] Use AddRange instead --- osu.Game/Skinning/SkinConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index 94a1160b38..0a21594f2a 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -46,7 +46,7 @@ namespace osu.Game.Skinning set => comboColours = value.ToList(); } - public void AddComboColours(params Color4[] colours) => colours.ForEach(c => comboColours.Add(c)); + public void AddComboColours(params Color4[] colours) => comboColours.AddRange(colours); public Dictionary CustomColours { get; set; } = new Dictionary(); From 5bf6e57eb0f19b4fedc09d06ca1e5d52cef5b129 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 24 Nov 2019 02:16:43 +0300 Subject: [PATCH 4167/5608] Remove unnecessary usage --- osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs | 1 - osu.Game/Skinning/SkinConfiguration.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index c945568753..c300799476 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -127,7 +127,6 @@ namespace osu.Game.Tests.Skins new Color4(55, 110, 166, 255), new Color4(75, 125, 175, 255), }); - AddStep("Clear combo colours from source2", () => source2.Configuration.ClearComboColours()); AddStep("Disallow default colours fallback in source2", () => source2.Configuration.AllowDefaultComboColoursFallback = allowFallback); AddAssert($"Check retrieved combo colours from {(allowFallback ? "source1" : "fallback source")}", () => diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index 0a21594f2a..3bfc941fd7 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Beatmaps.Formats; using osuTK.Graphics; From 20a8a653c2f7f9fd8e64e6ef30c5116bb4c4be50 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 24 Nov 2019 04:10:04 +0300 Subject: [PATCH 4168/5608] Change LegacySkin.Configuration accessibility --- osu.Game/Skinning/LegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 7ffed18d7b..868e3921bb 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -26,7 +26,7 @@ namespace osu.Game.Skinning [CanBeNull] protected IResourceStore Samples; - protected new LegacySkinConfiguration Configuration + public new LegacySkinConfiguration Configuration { get => base.Configuration as LegacySkinConfiguration; set => base.Configuration = value; From 2437cfd28c008e9f9af01c7ca10ebca41246971d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 24 Nov 2019 04:36:16 +0300 Subject: [PATCH 4169/5608] Add test ensuring correct version lookup --- osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index 578030748b..8b9c648442 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -116,6 +116,14 @@ namespace osu.Game.Tests.Skins }); } + [Test] + public void TestLegacyVersionLookup() + { + AddStep("Set source1 version 2.3", () => source1.Configuration.LegacyVersion = 2.3m); + AddStep("Set source2 version null", () => source2.Configuration.LegacyVersion = null); + AddAssert("Check legacy version lookup", () => requester.GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value == 2.3m); + } + public enum LookupType { Test From b58afa3eb693c29d74d5aac93f7160f5f35dc639 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 24 Nov 2019 04:36:34 +0300 Subject: [PATCH 4170/5608] Remove unnecessary mentioning in xmldoc --- osu.Game/Skinning/LegacySkinConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs index 6a667e69f4..b1679bd464 100644 --- a/osu.Game/Skinning/LegacySkinConfiguration.cs +++ b/osu.Game/Skinning/LegacySkinConfiguration.cs @@ -8,7 +8,7 @@ namespace osu.Game.Skinning public const decimal LATEST_VERSION = 2.7m; /// - /// Legacy version of this skin. Null if no version was set to allow fallback to a parent skin version. + /// Legacy version of this skin. /// public decimal? LegacyVersion { get; internal set; } From 6126fd9a6b573a422aae719d240b31f80fea4950 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Sun, 24 Nov 2019 10:42:05 +0900 Subject: [PATCH 4171/5608] ApplyToDrawableHitObjects should be able to get all the hitobject in nasted Playfield --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index e0aeff8330..5ed1e5a368 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -224,7 +224,7 @@ namespace osu.Game.Rulesets.UI Playfield.PostProcess(); foreach (var mod in mods.OfType()) - mod.ApplyToDrawableHitObjects(Playfield.HitObjectContainer.Objects); + mod.ApplyToDrawableHitObjects(Playfield.AllHitObjects); } public override void RequestResume(Action continueResume) From b8e5796af51eb47f8f897906b7da72b3b1cbc9d5 Mon Sep 17 00:00:00 2001 From: Albie Date: Sun, 24 Nov 2019 07:37:06 +0000 Subject: [PATCH 4172/5608] add forced video/storyboard and disabled dim for mod inside new interface --- .../Graphics/Containers/UserDimContainer.cs | 6 +++++ osu.Game/Rulesets/Mods/IApplicableToScreen.cs | 26 +++++++++++++++++++ osu.Game/Rulesets/Mods/ModCinema.cs | 9 ++++++- osu.Game/Screens/Play/DimmableStoryboard.cs | 4 +-- osu.Game/Screens/Play/DimmableVideo.cs | 5 ++-- osu.Game/Screens/Play/Player.cs | 20 ++++++++++++-- 6 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 osu.Game/Rulesets/Mods/IApplicableToScreen.cs diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 7683bbcd63..42a25a79b1 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -21,6 +21,11 @@ namespace osu.Game.Graphics.Containers /// public readonly Bindable EnableUserDim = new Bindable(true); + /// + /// Whether or not user-configured settings relating to visibility of elements should be ignored + /// + public readonly Bindable IgnoreUserSettings = new Bindable(); + /// /// Whether or not the storyboard loaded should completely hide the background behind it. /// @@ -63,6 +68,7 @@ namespace osu.Game.Graphics.Containers ShowStoryboard.ValueChanged += _ => UpdateVisuals(); ShowVideo.ValueChanged += _ => UpdateVisuals(); StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals(); + IgnoreUserSettings.ValueChanged += _ => UpdateVisuals(); } protected override void LoadComplete() diff --git a/osu.Game/Rulesets/Mods/IApplicableToScreen.cs b/osu.Game/Rulesets/Mods/IApplicableToScreen.cs new file mode 100644 index 0000000000..f1a631ccba --- /dev/null +++ b/osu.Game/Rulesets/Mods/IApplicableToScreen.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Mods +{ + /// + /// An interface for a mod which can temporarily override screen settings. + /// + public interface IApplicableToScreen : IApplicableMod + { + /// + /// Whether to enable image, video and storyboard dimming + /// + bool EnableDim { get; } + + /// + /// Weather to force the video (if present) + /// + bool ForceVideo { get; } + + /// + /// Weather to force the storyboard (if present) + /// + bool ForceStoryboard { get; } + } +} diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs index 4396c3384b..8a777b364a 100644 --- a/osu.Game/Rulesets/Mods/ModCinema.cs +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -1,7 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Graphics.Sprites; +using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; @@ -21,7 +24,7 @@ namespace osu.Game.Rulesets.Mods } } - public class ModCinema : ModAutoplay, IApplicableToHUD + public class ModCinema : ModAutoplay, IApplicableToHUD, IApplicableToScreen { public override string Name => "Cinema"; public override string Acronym => "CN"; @@ -33,5 +36,9 @@ namespace osu.Game.Rulesets.Mods overlay.AlwaysPresent = true; overlay.Hide(); } + + public bool EnableDim => false; + public bool ForceVideo => true; + public bool ForceStoryboard => true; } } diff --git a/osu.Game/Screens/Play/DimmableStoryboard.cs b/osu.Game/Screens/Play/DimmableStoryboard.cs index 2154526e54..4c7bb272cc 100644 --- a/osu.Game/Screens/Play/DimmableStoryboard.cs +++ b/osu.Game/Screens/Play/DimmableStoryboard.cs @@ -33,14 +33,14 @@ namespace osu.Game.Screens.Play base.LoadComplete(); } - protected override bool ShowDimContent => ShowStoryboard.Value && DimLevel < 1; + protected override bool ShowDimContent => IgnoreUserSettings.Value || ShowStoryboard.Value && DimLevel < 1; private void initializeStoryboard(bool async) { if (drawableStoryboard != null) return; - if (!ShowStoryboard.Value) + if (!ShowStoryboard.Value && !IgnoreUserSettings.Value) return; drawableStoryboard = storyboard.CreateDrawable(); diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index 4d6c10d69d..09ec5a3f5d 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -33,7 +34,7 @@ namespace osu.Game.Screens.Play base.LoadComplete(); } - protected override bool ShowDimContent => ShowVideo.Value && DimLevel < 1; + protected override bool ShowDimContent => IgnoreUserSettings.Value || ShowVideo.Value && DimLevel < 1; private void initializeVideo(bool async) { @@ -43,7 +44,7 @@ namespace osu.Game.Screens.Play if (drawableVideo != null) return; - if (!ShowVideo.Value) + if (!ShowVideo.Value && !IgnoreUserSettings.Value) return; drawableVideo = new DrawableVideo(video); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d6488dc209..3d6a9fe78f 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -498,8 +498,24 @@ namespace osu.Game.Screens.Play .Delay(250) .FadeIn(250); - Background.EnableUserDim.Value = true; - Background.BlurAmount.Value = 0; + var screenOverride = Mods.Value.OfType(); + + if (screenOverride.Count() == 1) + { + var setting = screenOverride.Single(); + + Background.EnableUserDim.Value = setting.EnableDim; + DimmableVideo.EnableUserDim.Value = setting.EnableDim; + DimmableStoryboard.EnableUserDim.Value = setting.EnableDim; + + DimmableVideo.IgnoreUserSettings.Value = setting.ForceVideo; + DimmableStoryboard.IgnoreUserSettings.Value = setting.ForceStoryboard; + } + else + { + Background.EnableUserDim.Value = true; + Background.BlurAmount.Value = 0; + } Background.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); DimmableStoryboard.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); From 1d6665fe57510c4dc950881b15728c5e64e7fa74 Mon Sep 17 00:00:00 2001 From: Albie Date: Sun, 24 Nov 2019 07:42:39 +0000 Subject: [PATCH 4173/5608] improve code quality using resharper and codefactor advice --- osu.Game/Rulesets/Mods/ModCinema.cs | 3 --- osu.Game/Screens/Play/DimmableStoryboard.cs | 2 +- osu.Game/Screens/Play/DimmableVideo.cs | 3 +-- osu.Game/Screens/Play/Player.cs | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs index 8a777b364a..5a876dbf51 100644 --- a/osu.Game/Rulesets/Mods/ModCinema.cs +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -1,10 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; using osu.Framework.Graphics.Sprites; -using osu.Game.Beatmaps; -using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; diff --git a/osu.Game/Screens/Play/DimmableStoryboard.cs b/osu.Game/Screens/Play/DimmableStoryboard.cs index 4c7bb272cc..0fe315fbab 100644 --- a/osu.Game/Screens/Play/DimmableStoryboard.cs +++ b/osu.Game/Screens/Play/DimmableStoryboard.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Play base.LoadComplete(); } - protected override bool ShowDimContent => IgnoreUserSettings.Value || ShowStoryboard.Value && DimLevel < 1; + protected override bool ShowDimContent => IgnoreUserSettings.Value || (ShowStoryboard.Value && DimLevel < 1); private void initializeStoryboard(bool async) { diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index 09ec5a3f5d..1a01cace17 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -34,7 +33,7 @@ namespace osu.Game.Screens.Play base.LoadComplete(); } - protected override bool ShowDimContent => IgnoreUserSettings.Value || ShowVideo.Value && DimLevel < 1; + protected override bool ShowDimContent => IgnoreUserSettings.Value || (ShowVideo.Value && DimLevel < 1); private void initializeVideo(bool async) { diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 3d6a9fe78f..dc4612a525 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -432,7 +432,7 @@ namespace osu.Game.Screens.Play // cannot pause if we are already in a fail state && !HasFailed // cannot pause if already paused (or in a cooldown state) unless we are in a resuming state. - && (IsResuming || (GameplayClockContainer.IsPaused.Value == false && !pauseCooldownActive)); + && (IsResuming || GameplayClockContainer.IsPaused.Value == false && !pauseCooldownActive); private bool pauseCooldownActive => lastPauseActionTime.HasValue && GameplayClockContainer.GameplayClock.CurrentTime < lastPauseActionTime + pause_cooldown; From 9a8e3fe1da79ea53328b2f293b7996eaa43bb138 Mon Sep 17 00:00:00 2001 From: Albie Date: Sun, 24 Nov 2019 07:44:35 +0000 Subject: [PATCH 4174/5608] add brackets --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index dc4612a525..3d6a9fe78f 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -432,7 +432,7 @@ namespace osu.Game.Screens.Play // cannot pause if we are already in a fail state && !HasFailed // cannot pause if already paused (or in a cooldown state) unless we are in a resuming state. - && (IsResuming || GameplayClockContainer.IsPaused.Value == false && !pauseCooldownActive); + && (IsResuming || (GameplayClockContainer.IsPaused.Value == false && !pauseCooldownActive)); private bool pauseCooldownActive => lastPauseActionTime.HasValue && GameplayClockContainer.GameplayClock.CurrentTime < lastPauseActionTime + pause_cooldown; From fccdbffa9370d23cc606d4d3ced16a702801ca07 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Mon, 25 Nov 2019 00:45:42 +0100 Subject: [PATCH 4175/5608] Use MathF instead of Math- functions when possible MathF-functions are faster than the Math-counterpart and it looks cleaner, so use MathF when we cast to float or int anyway. --- .../Difficulty/CatchPerformanceCalculator.cs | 2 +- .../Objects/Drawable/DrawableFruit.cs | 4 ++-- .../Beatmaps/ManiaBeatmapConverter.cs | 2 +- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs | 2 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- .../Objects/Drawables/Pieces/SpinnerTicks.cs | 10 +++++----- osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs | 10 +++++----- .../Screens/Drawings/Components/GroupContainer.cs | 2 +- .../Screens/Gameplay/Components/MatchScoreDisplay.cs | 2 +- osu.Game/Graphics/Backgrounds/Triangles.cs | 2 +- osu.Game/Overlays/NowPlayingOverlay.cs | 2 +- .../Overlays/Profile/Header/Components/RankGraph.cs | 4 ++-- .../Edit/Compose/Components/BeatDivisorControl.cs | 2 +- .../Compose/Components/CircularDistanceSnapGrid.cs | 2 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 4 ++-- osu.Game/Screens/Select/BeatmapCarousel.cs | 4 ++-- osu.Game/Screens/Select/Details/AdvancedStats.cs | 2 +- 18 files changed, 31 insertions(+), 31 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index a7f0d358ed..b876c774b2 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty // Longer maps are worth more float lengthBonus = 0.95f + 0.4f * Math.Min(1.0f, numTotalHits / 3000.0f) + - (numTotalHits > 3000 ? (float)Math.Log10(numTotalHits / 3000.0f) * 0.5f : 0.0f); + (numTotalHits > 3000 ? MathF.Log10(numTotalHits / 3000.0f) * 0.5f : 0.0f); // Longer maps are worth more value *= lengthBonus; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index eae652573b..2c97e5083d 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -99,8 +99,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable const float small_pulp = large_pulp_3 / 2; Vector2 positionAt(float angle, float distance) => new Vector2( - distance * (float)Math.Sin(angle * Math.PI / 180), - distance * (float)Math.Cos(angle * Math.PI / 180)); + distance * MathF.Sin(angle * MathF.PI / 180), + distance * MathF.Cos(angle * MathF.PI / 180)); switch (representation) { diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 6c5bb304bf..5fa1e31c78 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps { BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty; - int seed = (int)Math.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)Math.Round(difficulty.ApproachRate); + int seed = (int)MathF.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)MathF.Round(difficulty.ApproachRate); Random = new FastRandom(seed); return base.ConvertBeatmap(original); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index b9984a8b90..a249c6f0f3 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -53,11 +53,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (allowSpecial && TotalColumns == 8) { const float local_x_divisor = 512f / 7; - return Math.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; + return Math.Clamp((int)MathF.Floor(position / local_x_divisor), 0, 6) + 1; } float localXDivisor = 512f / TotalColumns; - return Math.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); + return Math.Clamp((int)MathF.Floor(position / localXDivisor), 0, TotalColumns - 1); } /// diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs index 9b079895fa..a9475af638 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Mods float appearDistance = (float)(hitObject.TimePreempt - hitObject.TimeFadeIn) / 2; Vector2 originalPosition = drawable.Position; - Vector2 appearOffset = new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance; + Vector2 appearOffset = new Vector2(MathF.Cos(theta), MathF.Sin(theta)) * appearDistance; //the - 1 and + 1 prevents the hit objects to appear in the wrong position. double appearTime = hitObject.StartTime - hitObject.TimePreempt - 1; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 122975d55e..71cb9a9691 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables break; } - float aimRotation = MathHelper.RadiansToDegrees((float)Math.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X)); + float aimRotation = MathHelper.RadiansToDegrees(MathF.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X)); while (Math.Abs(aimRotation - Rotation) > 180) aimRotation += aimRotation < Rotation ? 360 : -360; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs index 9219fab830..676cefb236 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs @@ -20,9 +20,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Anchor = Anchor.Centre; RelativeSizeAxes = Axes.Both; - const int count = 18; + const float count = 18; - for (int i = 0; i < count; i++) + for (float i = 0; i < count; i++) { Add(new Container { @@ -40,10 +40,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Size = new Vector2(60, 10), Origin = Anchor.Centre, Position = new Vector2( - 0.5f + (float)Math.Sin((float)i / count * 2 * MathHelper.Pi) / 2 * 0.86f, - 0.5f + (float)Math.Cos((float)i / count * 2 * MathHelper.Pi) / 2 * 0.86f + 0.5f + MathF.Sin(i / count * 2 * MathF.PI) / 2 * 0.86f, + 0.5f + MathF.Cos(i / count * 2 * MathF.PI) / 2 * 0.86f ), - Rotation = -(float)i / count * 360 + 90, + Rotation = -i / count * 360 + 90, Children = new[] { new Box diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index 24320b6579..d50b2098d6 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -185,14 +185,14 @@ namespace osu.Game.Rulesets.Osu.Replays { Vector2 spinCentreOffset = SPINNER_CENTRE - prevPos; float distFromCentre = spinCentreOffset.Length; - float distToTangentPoint = (float)Math.Sqrt(distFromCentre * distFromCentre - SPIN_RADIUS * SPIN_RADIUS); + float distToTangentPoint = MathF.Sqrt(distFromCentre * distFromCentre - SPIN_RADIUS * SPIN_RADIUS); if (distFromCentre > SPIN_RADIUS) { // Previous cursor position was outside spin circle, set startPosition to the tangent point. // Angle between centre offset and tangent point offset. - float angle = (float)Math.Asin(SPIN_RADIUS / distFromCentre); + float angle = MathF.Asin(SPIN_RADIUS / distFromCentre); if (angle > 0) { @@ -204,8 +204,8 @@ namespace osu.Game.Rulesets.Osu.Replays } // Rotate by angle so it's parallel to tangent line - spinCentreOffset.X = spinCentreOffset.X * (float)Math.Cos(angle) - spinCentreOffset.Y * (float)Math.Sin(angle); - spinCentreOffset.Y = spinCentreOffset.X * (float)Math.Sin(angle) + spinCentreOffset.Y * (float)Math.Cos(angle); + spinCentreOffset.X = spinCentreOffset.X * MathF.Cos(angle) - spinCentreOffset.Y * MathF.Sin(angle); + spinCentreOffset.Y = spinCentreOffset.X * MathF.Sin(angle) + spinCentreOffset.Y * MathF.Cos(angle); // Set length to distToTangentPoint spinCentreOffset.Normalize(); @@ -331,7 +331,7 @@ namespace osu.Game.Rulesets.Osu.Replays Vector2 difference = startPosition - SPINNER_CENTRE; float radius = difference.Length; - float angle = radius == 0 ? 0 : (float)Math.Atan2(difference.Y, difference.X); + float angle = radius == 0 ? 0 : MathF.Atan2(difference.Y, difference.X); double t; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs index 8a66ca7bf6..b9a19090df 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs @@ -57,7 +57,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components groups.Add(g); nextGroupName++; - if (i < (int)Math.Ceiling(numGroups / 2f)) + if (i < (int)MathF.Ceiling(numGroups / 2f)) topGroups.Add(g); else bottomGroups.Add(g); diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs index 78455c8bb7..cc7903f2fa 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs @@ -100,7 +100,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components var diff = Math.Max(score1.Value, score2.Value) - Math.Min(score1.Value, score2.Value); losingBar.ResizeWidthTo(0, 400, Easing.OutQuint); - winningBar.ResizeWidthTo(Math.Min(0.4f, (float)Math.Pow(diff / 1500000f, 0.5) / 2), 400, Easing.OutQuint); + winningBar.ResizeWidthTo(Math.Min(0.4f, MathF.Pow(diff / 1500000f, 0.5f) / 2), 400, Easing.OutQuint); } protected override void Update() diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index dffa0c4fd5..6d88808150 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -111,7 +111,7 @@ namespace osu.Game.Graphics.Backgrounds float adjustedAlpha = HideAlphaDiscrepancies // Cubically scale alpha to make it drop off more sharply. - ? (float)Math.Pow(DrawColourInfo.Colour.AverageColour.Linear.A, 3) + ? MathF.Pow(DrawColourInfo.Colour.AverageColour.Linear.A, 3) : 1; float elapsedSeconds = (float)Time.Elapsed / 1000; diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 4f73cbfacd..de30e1a754 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -390,7 +390,7 @@ namespace osu.Game.Overlays Vector2 change = e.MousePosition - e.MouseDownPosition; // Diminish the drag distance as we go further to simulate "rubber band" feeling. - change *= change.Length <= 0 ? 0 : (float)Math.Pow(change.Length, 0.7f) / change.Length; + change *= change.Length <= 0 ? 0 : MathF.Pow(change.Length, 0.7f) / change.Length; this.MoveTo(change); return true; diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index c6d96c5917..250b345db7 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -90,7 +90,7 @@ namespace osu.Game.Overlays.Profile.Header.Components placeholder.FadeOut(fade_duration, Easing.Out); graph.DefaultValueCount = ranks.Length; - graph.Values = ranks.Select(x => -(float)Math.Log(x.Value)); + graph.Values = ranks.Select(x => -MathF.Log(x.Value)); } graph.FadeTo(ranks.Length > 1 ? 1 : 0, fade_duration, Easing.Out); @@ -187,7 +187,7 @@ namespace osu.Game.Overlays.Profile.Header.Components public void HideBar() => bar.FadeOut(fade_duration); - private int calculateIndex(float mouseXPosition) => (int)Math.Round(mouseXPosition / DrawWidth * (DefaultValueCount - 1)); + private int calculateIndex(float mouseXPosition) => (int)MathF.Round(mouseXPosition / DrawWidth * (DefaultValueCount - 1)); private Vector2 calculateBallPosition(int index) { diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 9e4691e4dd..42773ef687 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -289,7 +289,7 @@ namespace osu.Game.Screens.Edit.Compose.Components OnUserChange(Current.Value); } - private float getMappedPosition(float divisor) => (float)Math.Pow((divisor - 1) / (availableDivisors.Last() - 1), 0.90f); + private float getMappedPosition(float divisor) => MathF.Pow((divisor - 1) / (availableDivisors.Last() - 1), 0.90f); private class Tick : CompositeDrawable { diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index fc7d51db4b..91e19f9cc0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Edit.Compose.Components float distance = direction.Length; float radius = DistanceSpacing; - int radialCount = Math.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); + int radialCount = Math.Clamp((int)MathF.Round(distance / radius), 1, MaxIntervals); Vector2 normalisedDirection = direction * new Vector2(1f / distance); Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 59ab6ad265..1a625f8d83 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -206,8 +206,8 @@ namespace osu.Game.Screens.Menu continue; float rotation = MathHelper.DegreesToRadians(i / (float)bars_per_visualiser * 360 + j * 360 / visualiser_rounds); - float rotationCos = (float)Math.Cos(rotation); - float rotationSin = (float)Math.Sin(rotation); + float rotationCos = MathF.Cos(rotation); + float rotationSin = MathF.Sin(rotation); //taking the cos and sin to the 0..1 range var barPosition = new Vector2(rotationCos / 2 + 0.5f, rotationSin / 2 + 0.5f) * size; diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 17736e7819..838ca5322c 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -670,8 +670,8 @@ namespace osu.Game.Screens.Select { // The radius of the circle the carousel moves on. const float circle_radius = 3; - double discriminant = Math.Max(0, circle_radius * circle_radius - dist * dist); - float x = (circle_radius - (float)Math.Sqrt(discriminant)) * halfHeight; + float discriminant = MathF.Max(0, circle_radius * circle_radius - dist * dist); + float x = (circle_radius - MathF.Sqrt(discriminant)) * halfHeight; return 125 + x; } diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 52a57dd506..c5bdc230d0 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Select.Details if ((Beatmap?.Ruleset?.ID ?? 0) == 3) { firstValue.Title = "Key Amount"; - firstValue.Value = (int)Math.Round(Beatmap?.BaseDifficulty?.CircleSize ?? 0); + firstValue.Value = (int)MathF.Round(Beatmap?.BaseDifficulty?.CircleSize ?? 0); } else { From 45514ff660a403a41e2c284c6e6be5ef81406331 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 11:30:55 +0900 Subject: [PATCH 4176/5608] Apply fixes --- osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs | 4 ++-- osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs | 3 ++- .../Visual/Gameplay/TestSceneBarHitErrorMeter.cs | 8 ++++---- .../Visual/Online/TestSceneLeaderboardModSelector.cs | 3 ++- .../Visual/Online/TestSceneRankingsDismissableFlag.cs | 3 ++- osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs | 6 +++--- osu.Game.Tournament/TournamentGameBase.cs | 4 ++-- osu.Game/Online/API/APIRequest.cs | 2 +- osu.Game/Overlays/Chat/DrawableChannel.cs | 3 ++- osu.Game/Overlays/Comments/CommentsHeader.cs | 5 +++-- .../Overlays/Comments/DeletedChildrenPlaceholder.cs | 3 ++- osu.Game/Overlays/Comments/DrawableComment.cs | 11 ++++++----- osu.Game/Overlays/Comments/SortTabControl.cs | 3 ++- osu.Game/Overlays/Comments/TotalCommentsCounter.cs | 5 +++-- osu.Game/Overlays/Comments/VotePill.cs | 2 +- .../Profile/Header/Components/PreviousUsernames.cs | 3 ++- osu.Game/Overlays/Rankings/HeaderTitle.cs | 5 +++-- 17 files changed, 42 insertions(+), 31 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 720ef1db42..9b529a2e4c 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -11,12 +11,12 @@ using System; using System.Collections.Generic; using osu.Game.Skinning; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osuTK.Graphics; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics.Textures; using osu.Game.Audio; +using osu.Game.Graphics.Sprites; namespace osu.Game.Rulesets.Catch.Tests { @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Catch.Tests RelativeSizeAxes = Axes.Both, Colour = Color4.Blue }, - new SpriteText + new OsuSpriteText { Text = "custom" } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index 7ca311118e..4da1b1dae0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -16,6 +16,7 @@ using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Screens.Play; using osu.Game.Skinning; @@ -125,7 +126,7 @@ namespace osu.Game.Rulesets.Osu.Tests { if (!enabled) return null; - return new SpriteText + return new OsuSpriteText { Text = identifier, Font = OsuFont.Default.With(size: 30), diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs index a934d22b5d..e3688c276f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Judgements; using osu.Framework.MathUtils; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Osu.Scoring; @@ -85,9 +85,9 @@ namespace osu.Game.Tests.Visual.Gameplay AutoSizeAxes = Axes.Both, Children = new[] { - new SpriteText { Text = $@"Great: {hitWindows?.WindowFor(HitResult.Great)}" }, - new SpriteText { Text = $@"Good: {hitWindows?.WindowFor(HitResult.Good)}" }, - new SpriteText { Text = $@"Meh: {hitWindows?.WindowFor(HitResult.Meh)}" }, + new OsuSpriteText { Text = $@"Great: {hitWindows?.WindowFor(HitResult.Great)}" }, + new OsuSpriteText { Text = $@"Good: {hitWindows?.WindowFor(HitResult.Good)}" }, + new OsuSpriteText { Text = $@"Meh: {hitWindows?.WindowFor(HitResult.Meh)}" }, } }); diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index ebe233a5f4..e0e5a088ce 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Bindables; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; namespace osu.Game.Tests.Visual.Online @@ -45,7 +46,7 @@ namespace osu.Game.Tests.Visual.Online modSelector.SelectedMods.ItemsAdded += mods => { - mods.ForEach(mod => selectedMods.Add(new SpriteText + mods.ForEach(mod => selectedMods.Add(new OsuSpriteText { Text = mod.Acronym, })); diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs index db6afa9bf3..cd954cd6bd 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Rankings; using osu.Game.Users; using osuTK; @@ -45,7 +46,7 @@ namespace osu.Game.Tests.Visual.Online Size = new Vector2(30, 20), Country = countryA, }, - text = new SpriteText + text = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs b/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs index 18d6028cb8..0f41247571 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Mania; using osu.Game.Users; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Taiko; using osu.Game.Graphics.UserInterface; @@ -94,11 +94,11 @@ namespace osu.Game.Tests.Visual.Online AddRange(new Drawable[] { - new SpriteText + new OsuSpriteText { Text = $@"Username: {user.NewValue?.Username}" }, - new SpriteText + new OsuSpriteText { Text = $@"RankedScore: {user.NewValue?.Statistics.RankedScore}" }, diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index f2a158971b..9e3dfa3ea6 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -12,13 +12,13 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Input; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; @@ -104,7 +104,7 @@ namespace osu.Game.Tournament Colour = Color4.Red, RelativeSizeAxes = Axes.Both, }, - new SpriteText + new OsuSpriteText { Text = "Please make the window wider", Font = OsuFont.Default.With(weight: "bold"), diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index 53b23f5922..b424e0f086 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -150,7 +150,7 @@ namespace osu.Game.Online.API private class DisplayableError { [JsonProperty("error")] - public string ErrorMessage; + public string ErrorMessage { get; set; } } } diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 427bd8dcde..443f2b7bf7 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -16,6 +16,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Chat { @@ -202,7 +203,7 @@ namespace osu.Game.Overlays.Chat RelativeSizeAxes = Axes.X, Height = lineHeight, }, - text = new SpriteText + text = new OsuSpriteText { Margin = new MarginPadding { Horizontal = 10 }, Text = time.ToLocalTime().ToString("dd MMM yyyy"), diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index 66fe7ff3fa..6a7a678cc7 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -10,6 +10,7 @@ using osu.Game.Graphics; using osu.Framework.Graphics.Sprites; using osuTK; using osu.Framework.Input.Events; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Comments { @@ -48,7 +49,7 @@ namespace osu.Game.Overlays.Comments Origin = Anchor.CentreLeft, Children = new Drawable[] { - new SpriteText + new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -101,7 +102,7 @@ namespace osu.Game.Overlays.Comments Origin = Anchor.CentreLeft, Size = new Vector2(10), }, - new SpriteText + new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs b/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs index e849691597..6b41453b91 100644 --- a/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs +++ b/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Sprites; using osuTK; using osu.Framework.Bindables; using Humanizer; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Comments { @@ -31,7 +32,7 @@ namespace osu.Game.Overlays.Comments Icon = FontAwesome.Solid.Trash, Size = new Vector2(14), }, - countText = new SpriteText + countText = new OsuSpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), } diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 3fb9867f0e..9a11e85a7b 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -14,6 +14,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; using System.Linq; +using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; namespace osu.Game.Overlays.Comments @@ -122,7 +123,7 @@ namespace osu.Game.Overlays.Comments AutoSizeAxes = Axes.Both, }, new ParentUsername(comment), - new SpriteText + new OsuSpriteText { Alpha = comment.IsDeleted ? 1 : 0, Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), @@ -144,7 +145,7 @@ namespace osu.Game.Overlays.Comments Colour = OsuColour.Gray(0.7f), Children = new Drawable[] { - new SpriteText + new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -195,7 +196,7 @@ namespace osu.Game.Overlays.Comments if (comment.EditedAt.HasValue) { - info.Add(new SpriteText + info.Add(new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -290,7 +291,7 @@ namespace osu.Game.Overlays.Comments this.count = count; Alpha = count == 0 ? 0 : 1; - Child = text = new SpriteText + Child = text = new OsuSpriteText { Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), }; @@ -323,7 +324,7 @@ namespace osu.Game.Overlays.Comments Icon = FontAwesome.Solid.Reply, Size = new Vector2(14), }, - new SpriteText + new OsuSpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), Text = parentComment?.User?.Username ?? parentComment?.LegacyName diff --git a/osu.Game/Overlays/Comments/SortTabControl.cs b/osu.Game/Overlays/Comments/SortTabControl.cs index f5423e692f..a114197b8d 100644 --- a/osu.Game/Overlays/Comments/SortTabControl.cs +++ b/osu.Game/Overlays/Comments/SortTabControl.cs @@ -11,6 +11,7 @@ using osu.Game.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Bindables; using osu.Framework.Allocation; +using osu.Game.Graphics.Sprites; using osuTK.Graphics; namespace osu.Game.Overlays.Comments @@ -61,7 +62,7 @@ namespace osu.Game.Overlays.Comments public TabButton(CommentsSortCriteria value) { - Add(text = new SpriteText + Add(text = new OsuSpriteText { Font = OsuFont.GetFont(size: 14), Text = value.ToString() diff --git a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs index c71ca762e1..376853c1de 100644 --- a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs +++ b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Sprites; using osuTK; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Comments { @@ -32,7 +33,7 @@ namespace osu.Game.Overlays.Comments Spacing = new Vector2(5, 0), Children = new Drawable[] { - new SpriteText + new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -52,7 +53,7 @@ namespace osu.Game.Overlays.Comments RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.05f) }, - counter = new SpriteText + counter = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index ab35a477aa..978846549e 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -110,7 +110,7 @@ namespace osu.Game.Overlays.Comments } } }, - sideNumber = new SpriteText + sideNumber = new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreRight, diff --git a/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs index f18f319e27..e4c0fe3a5a 100644 --- a/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs +++ b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK; @@ -63,7 +64,7 @@ namespace osu.Game.Overlays.Profile.Header.Components new Drawable[] { hoverIcon = new HoverIconContainer(), - header = new SpriteText + header = new OsuSpriteText { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, diff --git a/osu.Game/Overlays/Rankings/HeaderTitle.cs b/osu.Game/Overlays/Rankings/HeaderTitle.cs index cba407ecf7..a1a893fa6b 100644 --- a/osu.Game/Overlays/Rankings/HeaderTitle.cs +++ b/osu.Game/Overlays/Rankings/HeaderTitle.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osuTK; using osu.Game.Graphics; using osu.Framework.Allocation; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Rankings { @@ -41,13 +42,13 @@ namespace osu.Game.Overlays.Rankings Margin = new MarginPadding { Bottom = flag_margin }, Size = new Vector2(30, 20), }, - scopeText = new SpriteText + scopeText = new OsuSpriteText { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Light) }, - new SpriteText + new OsuSpriteText { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, From 4904346814feeb39dd95a5879abd6eb0120be701 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 11:31:03 +0900 Subject: [PATCH 4177/5608] Fix false warnings --- CodeAnalysis/BannedSymbols.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt index 3ad8d5db5b..c54c639b4f 100644 --- a/CodeAnalysis/BannedSymbols.txt +++ b/CodeAnalysis/BannedSymbols.txt @@ -2,4 +2,4 @@ M:System.Object.Equals(System.Object,System.Object)~System.Boolean;Don't use obj 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. T:System.IComparable;Don't use non-generic IComparable. Use generic version instead. -T:osu.Framework.Graphics.Sprites.SpriteText;Use OsuSpriteText. +T:osu.Framework.Graphics.Sprites.SpriteText.#ctor;Use OsuSpriteText. From 36cabe72cf854cbfd05f01fb0d03dc91e9717078 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 11:49:54 +0900 Subject: [PATCH 4178/5608] Make DimmedLoadingLayer block input when active --- osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs index f7138827cc..f2f6dd429b 100644 --- a/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs +++ b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class DimmedLoadingLayer : VisibilityContainer + public class DimmedLoadingLayer : OverlayContainer { private const float transition_duration = 250; From 9fdbb2a58e8aea3e7232d9853170d96502c3e2bb Mon Sep 17 00:00:00 2001 From: Albie Date: Mon, 25 Nov 2019 07:24:29 +0000 Subject: [PATCH 4179/5608] change name of interface and expose method instead of seperate values --- osu.Game/Rulesets/Mods/IApplicableToPlayer.cs | 15 +++++++++++ osu.Game/Rulesets/Mods/IApplicableToScreen.cs | 26 ------------------ osu.Game/Rulesets/Mods/ModCinema.cs | 14 +++++++--- osu.Game/Screens/Play/Player.cs | 27 +++++-------------- .../Play/ScreenWithBeatmapBackground.cs | 2 +- 5 files changed, 33 insertions(+), 51 deletions(-) create mode 100644 osu.Game/Rulesets/Mods/IApplicableToPlayer.cs delete mode 100644 osu.Game/Rulesets/Mods/IApplicableToScreen.cs diff --git a/osu.Game/Rulesets/Mods/IApplicableToPlayer.cs b/osu.Game/Rulesets/Mods/IApplicableToPlayer.cs new file mode 100644 index 0000000000..bf78428470 --- /dev/null +++ b/osu.Game/Rulesets/Mods/IApplicableToPlayer.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 osu.Game.Screens.Play; + +namespace osu.Game.Rulesets.Mods +{ + /// + /// An interface for a mod which can temporarily override the settings. + /// + public interface IApplicableToPlayer : IApplicableMod + { + void ApplyToPlayer(Player player); + } +} diff --git a/osu.Game/Rulesets/Mods/IApplicableToScreen.cs b/osu.Game/Rulesets/Mods/IApplicableToScreen.cs deleted file mode 100644 index f1a631ccba..0000000000 --- a/osu.Game/Rulesets/Mods/IApplicableToScreen.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Rulesets.Mods -{ - /// - /// An interface for a mod which can temporarily override screen settings. - /// - public interface IApplicableToScreen : IApplicableMod - { - /// - /// Whether to enable image, video and storyboard dimming - /// - bool EnableDim { get; } - - /// - /// Weather to force the video (if present) - /// - bool ForceVideo { get; } - - /// - /// Weather to force the storyboard (if present) - /// - bool ForceStoryboard { get; } - } -} diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs index 5a876dbf51..77bf80b149 100644 --- a/osu.Game/Rulesets/Mods/ModCinema.cs +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mods } } - public class ModCinema : ModAutoplay, IApplicableToHUD, IApplicableToScreen + public class ModCinema : ModAutoplay, IApplicableToHUD, IApplicableToPlayer { public override string Name => "Cinema"; public override string Acronym => "CN"; @@ -34,8 +34,14 @@ namespace osu.Game.Rulesets.Mods overlay.Hide(); } - public bool EnableDim => false; - public bool ForceVideo => true; - public bool ForceStoryboard => true; + public void ApplyToPlayer(Player player) + { + player.Background.EnableUserDim.Value = false; + player.DimmableVideo.EnableUserDim.Value = false; + player.DimmableStoryboard.EnableUserDim.Value = false; + + player.DimmableVideo.IgnoreUserSettings.Value = true; + player.DimmableStoryboard.IgnoreUserSettings.Value = true; + } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 3d6a9fe78f..90171da747 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -80,8 +80,8 @@ namespace osu.Game.Screens.Play protected GameplayClockContainer GameplayClockContainer { get; private set; } - protected DimmableStoryboard DimmableStoryboard { get; private set; } - protected DimmableVideo DimmableVideo { get; private set; } + public DimmableStoryboard DimmableStoryboard { get; private set; } + public DimmableVideo DimmableVideo { get; private set; } [Cached] [Cached(Type = typeof(IBindable>))] @@ -498,24 +498,8 @@ namespace osu.Game.Screens.Play .Delay(250) .FadeIn(250); - var screenOverride = Mods.Value.OfType(); - - if (screenOverride.Count() == 1) - { - var setting = screenOverride.Single(); - - Background.EnableUserDim.Value = setting.EnableDim; - DimmableVideo.EnableUserDim.Value = setting.EnableDim; - DimmableStoryboard.EnableUserDim.Value = setting.EnableDim; - - DimmableVideo.IgnoreUserSettings.Value = setting.ForceVideo; - DimmableStoryboard.IgnoreUserSettings.Value = setting.ForceStoryboard; - } - else - { - Background.EnableUserDim.Value = true; - Background.BlurAmount.Value = 0; - } + Background.EnableUserDim.Value = true; + Background.BlurAmount.Value = 0; Background.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); DimmableStoryboard.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); @@ -525,6 +509,9 @@ namespace osu.Game.Screens.Play GameplayClockContainer.Restart(); GameplayClockContainer.FadeInFromZero(750, Easing.OutQuint); + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToPlayer(this); + foreach (var mod in Mods.Value.OfType()) mod.ApplyToHUD(HUDOverlay); } diff --git a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs index d7d2c97598..8eb253608b 100644 --- a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs +++ b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs @@ -9,6 +9,6 @@ namespace osu.Game.Screens.Play { protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); - protected new BackgroundScreenBeatmap Background => (BackgroundScreenBeatmap)base.Background; + public new BackgroundScreenBeatmap Background => (BackgroundScreenBeatmap)base.Background; } } From 94e6bfeed33e9c3f1f3acf2ce0fc256d7fca30eb Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2019 07:30:17 +0000 Subject: [PATCH 4180/5608] Bump Microsoft.Build.Traversal from 2.0.19 to 2.0.24 Bumps [Microsoft.Build.Traversal](https://github.com/Microsoft/MSBuildSdks) from 2.0.19 to 2.0.24. - [Release notes](https://github.com/Microsoft/MSBuildSdks/releases) - [Changelog](https://github.com/microsoft/MSBuildSdks/blob/master/RELEASE.md) - [Commits](https://github.com/Microsoft/MSBuildSdks/compare/Microsoft.Build.Traversal.2.0.19...Microsoft.Build.Traversal.2.0.24) Signed-off-by: dependabot-preview[bot] --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index d8b8d14c36..43bb34912a 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "msbuild-sdks": { - "Microsoft.Build.Traversal": "2.0.19" + "Microsoft.Build.Traversal": "2.0.24" } } \ No newline at end of file From 137f3495e3d5ffa8c84ccec04ba83d3507f195e4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 23 Nov 2019 22:10:27 +0800 Subject: [PATCH 4181/5608] 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 4182/5608] 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 4183/5608] 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 4184/5608] 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 4185/5608] 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 4186/5608] 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 4187/5608] 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 4188/5608] 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 4189/5608] 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 719f0d5947e4d92db11682259a8033c361a6d2b7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 25 Nov 2019 18:28:43 +0900 Subject: [PATCH 4190/5608] Fix stutters when changing beatmap difficulties --- osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 3de0ab191c..7b68460e6b 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Backgrounds Schedule(() => { - if ((Background as BeatmapBackground)?.Beatmap == beatmap) + if ((Background as BeatmapBackground)?.Beatmap.BeatmapInfo.BackgroundEquals(beatmap?.BeatmapInfo) ?? false) return; cancellationSource?.Cancel(); From de3079d8e9bfa577914823eaacb594b6eeed82ee Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 25 Nov 2019 17:14:35 +0800 Subject: [PATCH 4191/5608] 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 6b8983b489a095c6aa43d7346d9b9d47e1af826e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 18:48:58 +0900 Subject: [PATCH 4192/5608] Consider intro and outro time as "break" time --- osu.Game/Screens/Play/BreakOverlay.cs | 12 +++++++++--- osu.Game/Screens/Play/Player.cs | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 6fdee85f45..28691c0d09 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; @@ -16,6 +16,8 @@ namespace osu.Game.Screens.Play { public class BreakOverlay : Container { + private readonly ScoreProcessor scoreProcessor; + /// /// The duration of the break overlay fading. /// @@ -60,9 +62,12 @@ namespace osu.Game.Screens.Play private readonly RemainingTimeCounter remainingTimeCounter; private readonly BreakInfo info; private readonly BreakArrows breakArrows; + private readonly double gameplayStartTime; - public BreakOverlay(bool letterboxing, ScoreProcessor scoreProcessor = null) + public BreakOverlay(bool letterboxing, double gameplayStartTime = 0, ScoreProcessor scoreProcessor = null) { + this.gameplayStartTime = gameplayStartTime; + this.scoreProcessor = scoreProcessor; RelativeSizeAxes = Axes.Both; Child = fadeContainer = new Container { @@ -154,7 +159,8 @@ namespace osu.Game.Screens.Play } var currentBreak = breaks[CurrentBreakIndex]; - isBreakTime.Value = currentBreak.HasEffect && currentBreak.Contains(time); + + isBreakTime.Value = (currentBreak.HasEffect && currentBreak.Contains(time)) || (time < gameplayStartTime || scoreProcessor.HasCompleted); } private void initializeBreaks() diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d6488dc209..7f32db2ebf 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -179,7 +179,7 @@ namespace osu.Game.Screens.Play { target.AddRange(new[] { - breakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) + breakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, DrawableRuleset.GameplayStartTime, ScoreProcessor) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -468,7 +468,7 @@ namespace osu.Game.Screens.Play PauseOverlay.Hide(); // breaks and time-based conditions may allow instant resume. - if (breakOverlay.IsBreakTime.Value || GameplayClockContainer.GameplayClock.CurrentTime < Beatmap.Value.Beatmap.HitObjects.First().StartTime) + if (breakOverlay.IsBreakTime.Value) completeResume(); else DrawableRuleset.RequestResume(completeResume); From 709ec1404f650cb368a56f88593ceed9f265f303 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 19:01:24 +0900 Subject: [PATCH 4193/5608] Centralise End/StartTime retrieval to extension method --- .../Objects/Drawable/DrawableCatchHitObject.cs | 4 ++-- .../ManiaBeatmapConversionTest.cs | 3 +-- .../Legacy/DistanceObjectPatternGenerator.cs | 2 +- .../Replays/ManiaAutoGenerator.cs | 3 +-- .../OsuBeatmapConversionTest.cs | 3 +-- .../Beatmaps/OsuBeatmapProcessor.cs | 12 ++++++------ osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 4 ++-- .../Drawables/Connections/FollowPointConnection.cs | 4 ++-- osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs | 6 +++--- .../TaikoBeatmapConversionTest.cs | 3 +-- osu.Game/Beatmaps/BeatmapManager.cs | 5 +++-- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 3 +-- osu.Game/Rulesets/Objects/BarLineGenerator.cs | 3 +-- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 6 +++--- osu.Game/Rulesets/Objects/HitObject.cs | 13 +++++++++++++ .../UI/Scrolling/DrawableScrollingRuleset.cs | 3 +-- .../Edit/Compose/Components/DistanceSnapGrid.cs | 3 +-- osu.Game/Screens/Play/SongProgress.cs | 4 ++-- osu.Game/Screens/Play/SongProgressGraph.cs | 5 ++--- 19 files changed, 47 insertions(+), 42 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index dd4a58a5ef..b7c05392f3 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -4,8 +4,8 @@ using System; using osuTK; using osu.Framework.Graphics; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Objects.Drawable @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable protected override void UpdateStateTransforms(ArmedState state) { - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + var endTime = HitObject.GetEndTime(); using (BeginAbsoluteSequence(endTime, true)) { diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index 6f10540973..12865385b6 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -9,7 +9,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Mania.Tests @@ -27,7 +26,7 @@ namespace osu.Game.Rulesets.Mania.Tests yield return new ConvertValue { StartTime = hitObject.StartTime, - EndTime = (hitObject as IHasEndTime)?.EndTime ?? hitObject.StartTime, + EndTime = hitObject.GetEndTime(), Column = ((ManiaHitObject)hitObject).Column }; } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 6297a68e08..5404cf2d23 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy foreach (var obj in originalPattern.HitObjects) { - if (!Precision.AlmostEquals(EndTime, (obj as IHasEndTime)?.EndTime ?? obj.StartTime)) + if (!Precision.AlmostEquals(EndTime, obj.GetEndTime())) intermediatePattern.Add(obj); else endTimePattern.Add(obj); diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 2b336ca16d..483327d5b3 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Game.Replays; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Mania.Replays @@ -84,7 +83,7 @@ namespace osu.Game.Rulesets.Mania.Replays var currentObject = Beatmap.HitObjects[i]; var nextObjectInColumn = GetNextObject(i); // Get the next object that requires pressing the same button - double endTime = (currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime; + double endTime = currentObject.GetEndTime(); bool canDelayKeyUp = nextObjectInColumn == null || nextObjectInColumn.StartTime > endTime + RELEASE_DELAY; diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index e9fdf924c3..1a36bb37d5 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Tests.Beatmaps; @@ -44,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Tests ConvertValue createConvertValue(OsuHitObject obj) => new ConvertValue { StartTime = obj.StartTime, - EndTime = (obj as IHasEndTime)?.EndTime ?? obj.StartTime, + EndTime = obj.GetEndTime(), X = obj.StackedPosition.X, Y = obj.StackedPosition.Y }; diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index bb19b783aa..3a829f72fa 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -4,7 +4,7 @@ using System; using osu.Framework.Graphics; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osuTK; @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps if (objectN is Spinner) continue; - double endTime = (stackBaseObject as IHasEndTime)?.EndTime ?? stackBaseObject.StartTime; + double endTime = stackBaseObject.GetEndTime(); double stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo.StackLeniency; if (objectN.StartTime - endTime > stackThreshold) @@ -121,7 +121,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps OsuHitObject objectN = beatmap.HitObjects[n]; if (objectN is Spinner) continue; - double endTime = (objectN as IHasEndTime)?.EndTime ?? objectN.StartTime; + double endTime = objectN.GetEndTime(); if (objectI.StartTime - endTime > stackThreshold) //We are no longer within stacking range of the previous object. @@ -199,7 +199,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps if (currHitObject.StackHeight != 0 && !(currHitObject is Slider)) continue; - double startTime = (currHitObject as IHasEndTime)?.EndTime ?? currHitObject.StartTime; + double startTime = currHitObject.GetEndTime(); int sliderStack = 0; for (int j = i + 1; j < beatmap.HitObjects.Count; j++) @@ -217,14 +217,14 @@ namespace osu.Game.Rulesets.Osu.Beatmaps if (Vector2Extensions.Distance(beatmap.HitObjects[j].Position, currHitObject.Position) < stack_distance) { currHitObject.StackHeight++; - startTime = (beatmap.HitObjects[j] as IHasEndTime)?.EndTime ?? beatmap.HitObjects[j].StartTime; + startTime = beatmap.HitObjects[j].GetEndTime(); } else if (Vector2Extensions.Distance(beatmap.HitObjects[j].Position, position2) < stack_distance) { //Case for sliders - bump notes down and right, rather than up and left. sliderStack++; beatmap.HitObjects[j].StackHeight -= sliderStack; - startTime = (beatmap.HitObjects[j] as IHasEndTime)?.EndTime ?? beatmap.HitObjects[j].StartTime; + startTime = beatmap.HitObjects[j].GetEndTime(); } } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 32c9e913c6..9f384ea2e8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Mods @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Mods var fadeOutDuration = h.TimePreempt * fade_out_duration_multiplier; // new duration from completed fade in to end (before fading out) - var longFadeDuration = ((h as IHasEndTime)?.EndTime ?? h.StartTime) - fadeOutStartTime; + var longFadeDuration = h.GetEndTime() - fadeOutStartTime; switch (drawable) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs index 1e032eb977..6c4fbbac17 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs @@ -6,7 +6,7 @@ using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Objects; using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections Vector2 startPosition = osuStart.EndPosition; Vector2 endPosition = osuEnd.Position; - double startTime = (osuStart as IHasEndTime)?.EndTime ?? osuStart.StartTime; + double startTime = osuStart.GetEndTime(); double endTime = osuEnd.StartTime; Vector2 distanceVector = endPosition - startPosition; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index d50b2098d6..bd59e8a03f 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -10,7 +10,7 @@ using System.Diagnostics; using System.Linq; using osu.Framework.Graphics; using osu.Game.Replays; -using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Osu.Replays private void addDelayedMovements(OsuHitObject h, OsuHitObject prev) { - double endTime = (prev as IHasEndTime)?.EndTime ?? prev.StartTime; + double endTime = prev.GetEndTime(); HitWindows hitWindows = null; @@ -275,7 +275,7 @@ namespace osu.Game.Rulesets.Osu.Replays var startFrame = new OsuReplayFrame(h.StartTime, new Vector2(startPosition.X, startPosition.Y), action); // TODO: Why do we delay 1 ms if the object is a spinner? There already is KEY_UP_DELAY from hEndTime. - double hEndTime = ((h as IHasEndTime)?.EndTime ?? h.StartTime) + KEY_UP_DELAY; + double hEndTime = h.GetEndTime() + KEY_UP_DELAY; int endDelay = h is Spinner ? 1 : 0; var endFrame = new OsuReplayFrame(hEndTime + endDelay, new Vector2(h.StackedEndPosition.X, h.StackedEndPosition.Y)); diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index 6c1882b4e2..28f5d4d301 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Tests.Beatmaps; @@ -27,7 +26,7 @@ namespace osu.Game.Rulesets.Taiko.Tests yield return new ConvertValue { StartTime = hitObject.StartTime, - EndTime = (hitObject as IHasEndTime)?.EndTime ?? hitObject.StartTime, + EndTime = hitObject.GetEndTime(), IsRim = hitObject is RimHit, IsCentre = hitObject is CentreHit, IsDrumRoll = hitObject is DrumRoll, diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index e6783ec828..bc78e50f5d 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -25,7 +25,7 @@ using osu.Game.IO.Archives; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Rulesets; -using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Objects; namespace osu.Game.Beatmaps { @@ -334,7 +334,8 @@ namespace osu.Game.Beatmaps var lastObject = b.HitObjects.Last(); - double endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime; + //TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list). + double endTime = lastObject.GetEndTime(); double startTime = b.HitObjects.First().StartTime; return endTime - startTime; diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index f217512965..e231225e3c 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -8,7 +8,6 @@ using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Mods { @@ -42,7 +41,7 @@ namespace osu.Game.Rulesets.Mods HitObject lastObject = beatmap.HitObjects.LastOrDefault(); beginRampTime = beatmap.HitObjects.FirstOrDefault()?.StartTime ?? 0; - finalRateTime = final_rate_progress * ((lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0); + finalRateTime = final_rate_progress * (lastObject?.GetEndTime() ?? 0); } public virtual void Update(Playfield playfield) diff --git a/osu.Game/Rulesets/Objects/BarLineGenerator.cs b/osu.Game/Rulesets/Objects/BarLineGenerator.cs index 4f9395435e..07f0595015 100644 --- a/osu.Game/Rulesets/Objects/BarLineGenerator.cs +++ b/osu.Game/Rulesets/Objects/BarLineGenerator.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects { @@ -28,7 +27,7 @@ namespace osu.Game.Rulesets.Objects return; HitObject lastObject = beatmap.HitObjects.Last(); - double lastHitTime = 1 + ((lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime); + double lastHitTime = 1 + (lastObject.GetEndTime()); var timingPoints = beatmap.ControlPointInfo.TimingPoints; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 35228e9ad1..ed48ddbc2f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -382,7 +382,7 @@ namespace osu.Game.Rulesets.Objects.Drawables if (Result != null && Result.HasResult) { - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + var endTime = HitObject.GetEndTime(); if (Result.TimeOffset + endTime > Time.Current) { @@ -460,7 +460,7 @@ namespace osu.Game.Rulesets.Objects.Drawables throw new InvalidOperationException($"{GetType().ReadableName()} applied a {nameof(JudgementResult)} but did not update {nameof(JudgementResult.Type)}."); // Ensure that the judgement is given a valid time offset, because this may not get set by the caller - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + var endTime = HitObject.GetEndTime(); Result.TimeOffset = Math.Min(HitObject.HitWindows.WindowFor(HitResult.Miss), Time.Current - endTime); @@ -495,7 +495,7 @@ namespace osu.Game.Rulesets.Objects.Drawables if (Judged) return false; - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + var endTime = HitObject.GetEndTime(); CheckForResult(userTriggered, Time.Current - endTime); return Judged; diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index ee0705ec5a..1179efaa6e 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -158,4 +158,17 @@ namespace osu.Game.Rulesets.Objects [NotNull] protected virtual HitWindows CreateHitWindows() => new HitWindows(); } + + public static class HitObjectExtensions + { + /// + /// Returns the end time of this object. + /// + /// + /// This returns the where available, falling back to otherwise. + /// + /// The object. + /// The end time of this object. + public static double GetEndTime(this HitObject hitObject) => (hitObject as IHasEndTime)?.EndTime ?? hitObject.StartTime; + } } diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index f178c01fd6..cfec5d3f49 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -15,7 +15,6 @@ using osu.Game.Configuration; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI.Scrolling.Algorithms; @@ -112,7 +111,7 @@ namespace osu.Game.Rulesets.UI.Scrolling [BackgroundDependencyLoader] private void load() { - double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; + double lastObjectTime = Objects.LastOrDefault()?.GetEndTime() ?? double.MaxValue; double baseBeatLength = TimingControlPoint.DEFAULT_BEAT_LENGTH; if (RelativeScaleBeatLengths) diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 475b6e7274..9508a2cdf0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osuTK; namespace osu.Game.Screens.Edit.Compose.Components @@ -70,7 +69,7 @@ namespace osu.Game.Screens.Edit.Compose.Components [BackgroundDependencyLoader] private void load() { - StartTime = (hitObject as IHasEndTime)?.EndTime ?? hitObject.StartTime; + StartTime = hitObject.GetEndTime(); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 3df06ebfa8..713d27bd16 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -12,7 +12,6 @@ using System.Linq; using osu.Framework.Bindables; using osu.Framework.Timing; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; namespace osu.Game.Screens.Play @@ -34,7 +33,8 @@ namespace osu.Game.Screens.Play public override bool HandleNonPositionalInput => AllowSeeking; public override bool HandlePositionalInput => AllowSeeking; - private double lastHitTime => ((objects.Last() as IHasEndTime)?.EndTime ?? objects.Last().StartTime) + 1; + //TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list). + private double lastHitTime => objects.Last().GetEndTime() + 1; private double firstHitTime => objects.First().StartTime; diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs index e480c5b502..e182a1a53d 100644 --- a/osu.Game/Screens/Play/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/SongProgressGraph.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Collections.Generic; using System.Diagnostics; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Play @@ -26,7 +25,7 @@ namespace osu.Game.Screens.Play return; var firstHit = objects.First().StartTime; - var lastHit = objects.Max(o => (o as IHasEndTime)?.EndTime ?? o.StartTime); + var lastHit = objects.Max(o => (o.GetEndTime())); if (lastHit == 0) lastHit = objects.Last().StartTime; @@ -35,7 +34,7 @@ namespace osu.Game.Screens.Play foreach (var h in objects) { - var endTime = (h as IHasEndTime)?.EndTime ?? h.StartTime; + var endTime = h.GetEndTime(); Debug.Assert(endTime >= h.StartTime); From 9fcc56634121d21a5c34e8153d3c4f0bf23d7e1b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 25 Nov 2019 18:32:41 +0800 Subject: [PATCH 4194/5608] 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 1fd5ed3c0f88f284a2155a379fff07275d9e6a7c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 21:35:25 +0900 Subject: [PATCH 4195/5608] Change login placeholder text to ask for username --- osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index a8bbccb168..d8833ee2f4 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -225,7 +225,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { username = new OsuTextBox { - PlaceholderText = "email address", + PlaceholderText = "username", RelativeSizeAxes = Axes.X, Text = api?.ProvidedUsername ?? string.Empty, TabbableContentContainer = this @@ -239,7 +239,7 @@ namespace osu.Game.Overlays.Settings.Sections.General }, new SettingsCheckbox { - LabelText = "Remember email address", + LabelText = "Remember username", Bindable = config.GetBindable(OsuSetting.SaveUsername), }, new SettingsCheckbox From fbebbab5dbb4db0faaf633accc82e99f29982c5a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 22:37:07 +0900 Subject: [PATCH 4196/5608] Remove excess parenthesis --- osu.Game/Rulesets/Objects/BarLineGenerator.cs | 2 +- osu.Game/Screens/Play/SongProgressGraph.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/BarLineGenerator.cs b/osu.Game/Rulesets/Objects/BarLineGenerator.cs index 07f0595015..99672240e2 100644 --- a/osu.Game/Rulesets/Objects/BarLineGenerator.cs +++ b/osu.Game/Rulesets/Objects/BarLineGenerator.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Objects return; HitObject lastObject = beatmap.HitObjects.Last(); - double lastHitTime = 1 + (lastObject.GetEndTime()); + double lastHitTime = 1 + lastObject.GetEndTime(); var timingPoints = beatmap.ControlPointInfo.TimingPoints; diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs index e182a1a53d..78eb456bb5 100644 --- a/osu.Game/Screens/Play/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/SongProgressGraph.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Play return; var firstHit = objects.First().StartTime; - var lastHit = objects.Max(o => (o.GetEndTime())); + var lastHit = objects.Max(o => o.GetEndTime()); if (lastHit == 0) lastHit = objects.Last().StartTime; From 41fd3f67494c1131affda5c9e9c62da994e4cde1 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 25 Nov 2019 23:42:59 +0800 Subject: [PATCH 4197/5608] Correct BannedSymbols.txt. --- CodeAnalysis/BannedSymbols.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt index c54c639b4f..5d86b99fd7 100644 --- a/CodeAnalysis/BannedSymbols.txt +++ b/CodeAnalysis/BannedSymbols.txt @@ -2,4 +2,4 @@ M:System.Object.Equals(System.Object,System.Object)~System.Boolean;Don't use obj 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. T:System.IComparable;Don't use non-generic IComparable. Use generic version instead. -T:osu.Framework.Graphics.Sprites.SpriteText.#ctor;Use OsuSpriteText. +M:osu.Framework.Graphics.Sprites.SpriteText.#ctor;Use OsuSpriteText. From 8928f05f4f262c9fdcdb596e5debb95f05d21a5f Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 26 Nov 2019 01:39:48 +0800 Subject: [PATCH 4198/5608] 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 8e25214eeea21dca5ea24727a968ba6b91223e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 25 Nov 2019 21:21:56 +0100 Subject: [PATCH 4199/5608] Revert Android to using native network components This reverts commit 9acfc2587aa6a8dcd34a2535f3fc4bcf928bac1b ("Switch android to using managed network components") due to it causing crashes on every online call. The managed legacy TLS provider is slated for removal in later mono releases as it stands anyway. --- osu.Android.props | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 0da3e66236..f2d2af5678 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -16,8 +16,6 @@ armeabi-v7a;x86;arm64-v8a true cjk,mideast,other,rare,west - System.Net.Http.HttpClientHandler - legacy SdkOnly prompt From a453129d448ae718973248cd3eed11727425f7b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Nov 2019 15:13:50 +0900 Subject: [PATCH 4200/5608] Fix nullref in tests --- osu.Game/Screens/Play/BreakOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 28691c0d09..9ba18224ce 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -160,7 +160,7 @@ namespace osu.Game.Screens.Play var currentBreak = breaks[CurrentBreakIndex]; - isBreakTime.Value = (currentBreak.HasEffect && currentBreak.Contains(time)) || (time < gameplayStartTime || scoreProcessor.HasCompleted); + isBreakTime.Value = (currentBreak.HasEffect && currentBreak.Contains(time)) || (time < gameplayStartTime || scoreProcessor?.HasCompleted == true); } private void initializeBreaks() From 77ce9642ba616cb668ca8d9259c3b5a4a4792bfe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Nov 2019 15:21:43 +0900 Subject: [PATCH 4201/5608] Add test coverage and simplify break time updating --- .../Visual/Gameplay/TestSceneBreakOverlay.cs | 13 ++++++ osu.Game/Screens/Play/BreakOverlay.cs | 41 +++++++++++-------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs index 879e15c548..19dce303ea 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs @@ -95,6 +95,19 @@ namespace osu.Game.Tests.Visual.Gameplay seekAndAssertBreak("seek to break after end", testBreaks[1].EndTime + 500, false); } + [TestCase(true)] + [TestCase(false)] + public void TestBeforeGameplayStart(bool withBreaks) + { + setClock(true); + + if (withBreaks) + loadBreaksStep("multiple breaks", testBreaks); + + seekAndAssertBreak("seek to break intro time", -100, true); + seekAndAssertBreak("seek to break intro time", 0, false); + } + private void addShowBreakStep(double seconds) { AddStep($"show '{seconds}s' break", () => breakOverlay.Breaks = new List diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 9ba18224ce..ee8be87352 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -140,27 +140,34 @@ namespace osu.Game.Screens.Play updateBreakTimeBindable(); } - private void updateBreakTimeBindable() + private void updateBreakTimeBindable() => + isBreakTime.Value = getCurrentBreak()?.HasEffect == true + || Clock.CurrentTime < gameplayStartTime + || scoreProcessor?.HasCompleted == true; + + private BreakPeriod getCurrentBreak() { - if (breaks == null || breaks.Count == 0) - return; - - var time = Clock.CurrentTime; - - if (time > breaks[CurrentBreakIndex].EndTime) + if (breaks?.Count > 0) { - while (time > breaks[CurrentBreakIndex].EndTime && CurrentBreakIndex < breaks.Count - 1) - CurrentBreakIndex++; - } - else - { - while (time < breaks[CurrentBreakIndex].StartTime && CurrentBreakIndex > 0) - CurrentBreakIndex--; + var time = Clock.CurrentTime; + + if (time > breaks[CurrentBreakIndex].EndTime) + { + while (time > breaks[CurrentBreakIndex].EndTime && CurrentBreakIndex < breaks.Count - 1) + CurrentBreakIndex++; + } + else + { + while (time < breaks[CurrentBreakIndex].StartTime && CurrentBreakIndex > 0) + CurrentBreakIndex--; + } + + var closest = breaks[CurrentBreakIndex]; + + return closest.Contains(time) ? closest : null; } - var currentBreak = breaks[CurrentBreakIndex]; - - isBreakTime.Value = (currentBreak.HasEffect && currentBreak.Contains(time)) || (time < gameplayStartTime || scoreProcessor?.HasCompleted == true); + return null; } private void initializeBreaks() From ab017ee648df15b51fe635e6c5cec70d96f1635e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Nov 2019 15:37:13 +0900 Subject: [PATCH 4202/5608] 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..b80881e2f6 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..2f633bdbc1 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..38134074f2 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,7 +73,7 @@ - + @@ -81,7 +81,7 @@ - + From aa1545c9388a937db3ee4d1b4651d8cd0cf55747 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 26 Nov 2019 15:52:22 +0800 Subject: [PATCH 4203/5608] 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 4204/5608] 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 9425e80a5d23f29c45b91a6ef9e009cf61a17faf Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 26 Nov 2019 18:34:23 +0800 Subject: [PATCH 4205/5608] Unify to use double in performance calculators. --- .../Difficulty/CatchPerformanceCalculator.cs | 36 +++++---- .../Difficulty/OsuPerformanceCalculator.cs | 76 +++++++++---------- .../Difficulty/TaikoPerformanceCalculator.cs | 2 +- 3 files changed, 56 insertions(+), 58 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index b876c774b2..3c237c86be 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -47,55 +47,53 @@ namespace osu.Game.Rulesets.Catch.Difficulty return 0; // We are heavily relying on aim in catch the beat - double value = Math.Pow(5.0f * Math.Max(1.0f, Attributes.StarRating / 0.0049f) - 4.0f, 2.0f) / 100000.0f; + double value = Math.Pow(5.0 * Math.Max(1.0, Attributes.StarRating / 0.0049) - 4.0, 2.0) / 100000.0; // Longer maps are worth more. "Longer" means how many hits there are which can contribute to combo int numTotalHits = totalComboHits(); // Longer maps are worth more - float lengthBonus = - 0.95f + 0.4f * Math.Min(1.0f, numTotalHits / 3000.0f) + - (numTotalHits > 3000 ? MathF.Log10(numTotalHits / 3000.0f) * 0.5f : 0.0f); + double lengthBonus = + 0.95 + 0.4 * Math.Min(1.0, numTotalHits / 3000.0) + + (numTotalHits > 3000 ? Math.Log10(numTotalHits / 3000.0) * 0.5 : 0.0); // Longer maps are worth more value *= lengthBonus; // Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available - value *= Math.Pow(0.97f, misses); + value *= Math.Pow(0.97, misses); // Combo scaling - float beatmapMaxCombo = Attributes.MaxCombo; - if (beatmapMaxCombo > 0) - value *= Math.Min(Math.Pow(Attributes.MaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f); + if (Attributes.MaxCombo > 0) + value *= Math.Min(Math.Pow(Attributes.MaxCombo, 0.8) / Math.Pow(Attributes.MaxCombo, 0.8), 1.0); - float approachRate = (float)Attributes.ApproachRate; - float approachRateFactor = 1.0f; - if (approachRate > 9.0f) - approachRateFactor += 0.1f * (approachRate - 9.0f); // 10% for each AR above 9 - else if (approachRate < 8.0f) - approachRateFactor += 0.025f * (8.0f - approachRate); // 2.5% for each AR below 8 + double approachRateFactor = 1.0; + if (Attributes.ApproachRate > 9.0) + approachRateFactor += 0.1 * (Attributes.ApproachRate - 9.0); // 10% for each AR above 9 + else if (Attributes.ApproachRate < 8.0) + approachRateFactor += 0.025 * (8.0 - Attributes.ApproachRate); // 2.5% for each AR below 8 value *= approachRateFactor; if (mods.Any(m => m is ModHidden)) // Hiddens gives nothing on max approach rate, and more the lower it is - value *= 1.05f + 0.075f * (10.0f - Math.Min(10.0f, approachRate)); // 7.5% for each AR below 10 + value *= 1.05 + 0.075 * (10.0 - Math.Min(10.0, Attributes.ApproachRate)); // 7.5% for each AR below 10 if (mods.Any(m => m is ModFlashlight)) // Apply length bonus again if flashlight is on simply because it becomes a lot harder on longer maps. - value *= 1.35f * lengthBonus; + value *= 1.35 * lengthBonus; // Scale the aim value with accuracy _slightly_ - value *= Math.Pow(accuracy(), 5.5f); + value *= Math.Pow(accuracy(), 5.5); // Custom multipliers for NoFail. SpunOut is not applicable. if (mods.Any(m => m is ModNoFail)) - value *= 0.90f; + value *= 0.90; return value; } - private float accuracy() => totalHits() == 0 ? 0 : Math.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); + private float accuracy() => totalHits() == 0 ? 0 : Math.Clamp((float)totalSuccessfulHits() / totalHits(), 0, 1); private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed; private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit; private int totalComboHits() => misses + ticksHit + fruitsHit; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 093081b6a1..05c78cbc95 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -55,22 +55,22 @@ namespace osu.Game.Rulesets.Osu.Difficulty return 0; // Custom multipliers for NoFail and SpunOut. - double multiplier = 1.12f; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things + double multiplier = 1.12; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things if (mods.Any(m => m is OsuModNoFail)) - multiplier *= 0.90f; + multiplier *= 0.90; if (mods.Any(m => m is OsuModSpunOut)) - multiplier *= 0.95f; + multiplier *= 0.95; double aimValue = computeAimValue(); double speedValue = computeSpeedValue(); double accuracyValue = computeAccuracyValue(); double totalValue = Math.Pow( - Math.Pow(aimValue, 1.1f) + - Math.Pow(speedValue, 1.1f) + - Math.Pow(accuracyValue, 1.1f), 1.0f / 1.1f + Math.Pow(aimValue, 1.1) + + Math.Pow(speedValue, 1.1) + + Math.Pow(accuracyValue, 1.1), 1.0 / 1.1 ) * multiplier; if (categoryRatings != null) @@ -93,82 +93,82 @@ namespace osu.Game.Rulesets.Osu.Difficulty if (mods.Any(m => m is OsuModTouchDevice)) rawAim = Math.Pow(rawAim, 0.8); - double aimValue = Math.Pow(5.0f * Math.Max(1.0f, rawAim / 0.0675f) - 4.0f, 3.0f) / 100000.0f; + double aimValue = Math.Pow(5.0 * Math.Max(1.0, rawAim / 0.0675) - 4.0, 3.0) / 100000.0; // Longer maps are worth more - double lengthBonus = 0.95f + 0.4f * Math.Min(1.0f, totalHits / 2000.0f) + - (totalHits > 2000 ? Math.Log10(totalHits / 2000.0f) * 0.5f : 0.0f); + double lengthBonus = 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) + + (totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0); aimValue *= lengthBonus; // Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available - aimValue *= Math.Pow(0.97f, countMiss); + aimValue *= Math.Pow(0.97, countMiss); // Combo scaling if (beatmapMaxCombo > 0) - aimValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f); + aimValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(beatmapMaxCombo, 0.8), 1.0); - double approachRateFactor = 1.0f; + double approachRateFactor = 1.0; - if (Attributes.ApproachRate > 10.33f) - approachRateFactor += 0.3f * (Attributes.ApproachRate - 10.33f); - else if (Attributes.ApproachRate < 8.0f) + if (Attributes.ApproachRate > 10.33) + approachRateFactor += 0.3 * (Attributes.ApproachRate - 10.33); + else if (Attributes.ApproachRate < 8.0) { - approachRateFactor += 0.01f * (8.0f - Attributes.ApproachRate); + approachRateFactor += 0.01 * (8.0 - Attributes.ApproachRate); } aimValue *= approachRateFactor; // We want to give more reward for lower AR when it comes to aim and HD. This nerfs high AR and buffs lower AR. if (mods.Any(h => h is OsuModHidden)) - aimValue *= 1.0f + 0.04f * (12.0f - Attributes.ApproachRate); + aimValue *= 1.0 + 0.04 * (12.0 - Attributes.ApproachRate); if (mods.Any(h => h is OsuModFlashlight)) { // Apply object-based bonus for flashlight. - aimValue *= 1.0f + 0.35f * Math.Min(1.0f, totalHits / 200.0f) + + aimValue *= 1.0 + 0.35 * Math.Min(1.0, totalHits / 200.0) + (totalHits > 200 - ? 0.3f * Math.Min(1.0f, (totalHits - 200) / 300.0f) + - (totalHits > 500 ? (totalHits - 500) / 1200.0f : 0.0f) - : 0.0f); + ? 0.3 * Math.Min(1.0, (totalHits - 200) / 300.0) + + (totalHits > 500 ? (totalHits - 500) / 1200.0 : 0.0) + : 0.0); } // Scale the aim value with accuracy _slightly_ - aimValue *= 0.5f + accuracy / 2.0f; + aimValue *= 0.5 + accuracy / 2.0; // It is important to also consider accuracy difficulty when doing that - aimValue *= 0.98f + Math.Pow(Attributes.OverallDifficulty, 2) / 2500; + aimValue *= 0.98 + Math.Pow(Attributes.OverallDifficulty, 2) / 2500; return aimValue; } private double computeSpeedValue() { - double speedValue = Math.Pow(5.0f * Math.Max(1.0f, Attributes.SpeedStrain / 0.0675f) - 4.0f, 3.0f) / 100000.0f; + double speedValue = Math.Pow(5.0 * Math.Max(1.0, Attributes.SpeedStrain / 0.0675) - 4.0, 3.0) / 100000.0; // Longer maps are worth more - speedValue *= 0.95f + 0.4f * Math.Min(1.0f, totalHits / 2000.0f) + - (totalHits > 2000 ? Math.Log10(totalHits / 2000.0f) * 0.5f : 0.0f); + speedValue *= 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) + + (totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0); // Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available - speedValue *= Math.Pow(0.97f, countMiss); + speedValue *= Math.Pow(0.97, countMiss); // Combo scaling if (beatmapMaxCombo > 0) - speedValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f); + speedValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(beatmapMaxCombo, 0.8), 1.0); - double approachRateFactor = 1.0f; - if (Attributes.ApproachRate > 10.33f) - approachRateFactor += 0.3f * (Attributes.ApproachRate - 10.33f); + double approachRateFactor = 1.0; + if (Attributes.ApproachRate > 10.33) + approachRateFactor += 0.3 * (Attributes.ApproachRate - 10.33); speedValue *= approachRateFactor; if (mods.Any(m => m is OsuModHidden)) - speedValue *= 1.0f + 0.04f * (12.0f - Attributes.ApproachRate); + speedValue *= 1.0 + 0.04 * (12.0 - Attributes.ApproachRate); // Scale the speed value with accuracy _slightly_ - speedValue *= 0.02f + accuracy; + speedValue *= 0.02 + accuracy; // It is important to also consider accuracy difficulty when doing that - speedValue *= 0.96f + Math.Pow(Attributes.OverallDifficulty, 2) / 1600; + speedValue *= 0.96 + Math.Pow(Attributes.OverallDifficulty, 2) / 1600; return speedValue; } @@ -190,15 +190,15 @@ namespace osu.Game.Rulesets.Osu.Difficulty // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accuracyValue = Math.Pow(1.52163f, Attributes.OverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83f; + double accuracyValue = Math.Pow(1.52163, Attributes.OverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83; // Bonus for many hitcircles - it's harder to keep good accuracy up for longer - accuracyValue *= Math.Min(1.15f, Math.Pow(amountHitObjectsWithAccuracy / 1000.0f, 0.3f)); + accuracyValue *= Math.Min(1.15, Math.Pow(amountHitObjectsWithAccuracy / 1000.0, 0.3)); if (mods.Any(m => m is OsuModHidden)) - accuracyValue *= 1.08f; + accuracyValue *= 1.08; if (mods.Any(m => m is OsuModFlashlight)) - accuracyValue *= 1.02f; + accuracyValue *= 1.02; return accuracyValue; } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index 70249db0f6..c3638253e4 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty double strainValue = Math.Pow(5.0 * Math.Max(1.0, Attributes.StarRating / 0.0075) - 4.0, 2.0) / 100000.0; // Longer maps are worth more - double lengthBonus = 1 + 0.1f * Math.Min(1.0, totalHits / 1500.0); + double lengthBonus = 1 + 0.1 * Math.Min(1.0, totalHits / 1500.0); strainValue *= lengthBonus; // Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available From eba8657d38b6cd26256b3fc461c87eaca3bc5bdd Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 26 Nov 2019 18:41:19 +0800 Subject: [PATCH 4206/5608] Remove newly introduced redundant `this`. --- osu.Game/Screens/Play/GameplayClockContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 0b8bab3ffc..ff78d85bf0 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -68,7 +68,7 @@ namespace osu.Game.Screens.Play this.beatmap = beatmap; this.mods = mods; this.gameplayStartTime = gameplayStartTime; - this.firstHitObjectTime = beatmap.Beatmap.HitObjects.First().StartTime; + firstHitObjectTime = beatmap.Beatmap.HitObjects.First().StartTime; RelativeSizeAxes = Axes.Both; From d1e3718038f806afff93aaebd9bf8a1481312f34 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Nov 2019 15:04:09 +0900 Subject: [PATCH 4207/5608] 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 4208/5608] 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 4209/5608] 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 4210/5608] 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 4211/5608] 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 4212/5608] 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 4213/5608] 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 4214/5608] 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 4215/5608] 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 4216/5608] 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 4217/5608] 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 4218/5608] 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 4219/5608] 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 4220/5608] 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 4221/5608] 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 4222/5608] 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 4223/5608] 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 4224/5608] 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 4225/5608] 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 4226/5608] 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 944835da234c0c300af3a38a4ae45052237052be Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Thu, 28 Nov 2019 12:01:40 +0700 Subject: [PATCH 4227/5608] Add multiplier score text on mods footer button --- osu.Game/Screens/Select/FooterButtonMods.cs | 44 +++++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 29b1364944..8dc0a2a132 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -7,11 +7,14 @@ using osu.Framework.Graphics.Containers; using osu.Game.Screens.Play.HUD; using osu.Game.Rulesets.Mods; using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osuTK; +using osuTK.Graphics; using osuTK.Input; namespace osu.Game.Screens.Select @@ -24,23 +27,40 @@ namespace osu.Game.Screens.Select set => modDisplay.Current = value; } + protected readonly OsuSpriteText MultiplierText; private readonly FooterModDisplay modDisplay; + private Color4 lowMultiplierColour; + private Color4 highMultiplierColour; public FooterButtonMods() { - Add(new Container + Add(new FillFlowContainer { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, + Direction = FillDirection.Horizontal, Shear = -SHEAR, - Child = modDisplay = new FooterModDisplay + Children = new Drawable[] { - DisplayUnrankedText = false, - Scale = new Vector2(0.8f) + modDisplay = new FooterModDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + DisplayUnrankedText = false, + Scale = new Vector2(0.8f) + }, + MultiplierText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(weight: FontWeight.Bold), + } }, AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Left = 70 } }); + + Current.ValueChanged += _ => updateMultiplierText(); } [BackgroundDependencyLoader] @@ -48,10 +68,26 @@ namespace osu.Game.Screens.Select { SelectedColour = colours.Yellow; DeselectedColour = SelectedColour.Opacity(0.5f); + lowMultiplierColour = colours.Red; + highMultiplierColour = colours.Green; Text = @"mods"; Hotkey = Key.F1; } + private void updateMultiplierText() + { + var multiplier = Current.Value.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier); + + MultiplierText.Text = multiplier.Equals(1.0) ? string.Empty : $"{multiplier:N2}x"; + + if (multiplier > 1.0) + MultiplierText.FadeColour(highMultiplierColour, 200); + else if (multiplier < 1.0) + MultiplierText.FadeColour(lowMultiplierColour, 200); + else + MultiplierText.FadeColour(Color4.White, 200); + } + private class FooterModDisplay : ModDisplay { public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Parent?.Parent?.ReceivePositionalInputAt(screenSpacePos) ?? false; From 6149482b5d81d67778ab66043926dec885802374 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Thu, 28 Nov 2019 12:03:11 +0700 Subject: [PATCH 4228/5608] Add test --- .../UserInterface/TestCaseFooterButtonMods.cs | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestCaseFooterButtonMods.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseFooterButtonMods.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseFooterButtonMods.cs new file mode 100644 index 0000000000..0c437800bc --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseFooterButtonMods.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; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Screens.Select; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestCaseFooterButtonMods : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(FooterButtonMods) + }; + + private readonly TestFooterButtonMods footerButtonMods; + + public TestCaseFooterButtonMods() + { + Add(footerButtonMods = new TestFooterButtonMods()); + } + + [Test] + public void TestIncrementMultiplier() + { + AddStep(@"Add Hidden", () => changeMods(new Mod[] { new OsuModHidden() })); + AddAssert(@"Check Hidden multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"1.06x")); + AddStep(@"Add HardRock", () => changeMods(new Mod[] { new OsuModHidden() })); + AddAssert(@"Check HardRock multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"1.06x")); + AddStep(@"Add DoubleTime", () => changeMods(new Mod[] { new OsuModDoubleTime() })); + AddAssert(@"Check DoubleTime multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"1.12x")); + AddStep(@"Add multiple Mods", () => changeMods(new Mod[] { new OsuModDoubleTime(), new OsuModHidden(), new OsuModHidden() })); + AddAssert(@"Check multiple mod multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"1.26x")); + } + + [Test] + public void TestDecrementMultiplier() + { + AddStep(@"Add Easy", () => changeMods(new Mod[] { new OsuModEasy() })); + AddAssert(@"Check Easy multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"0.50x")); + AddStep(@"Add NoFail", () => changeMods(new Mod[] { new OsuModNoFail() })); + AddAssert(@"Check NoFail multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"0.50x")); + AddStep(@"Add Multiple Mods", () => changeMods(new Mod[] { new OsuModEasy(), new OsuModNoFail() })); + AddAssert(@"Check multiple mod multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"0.25x")); + } + + [Test] + public void TestClearMultiplier() + { + AddStep(@"Add mods", () => changeMods(new Mod[] { new OsuModDoubleTime(), new OsuModFlashlight() })); + AddStep(@"Clear selected mod", () => changeMods(Array.Empty())); + AddAssert(@"Check empty multiplier", () => footerButtonMods.MultiplierText.Text.Equals(string.Empty)); + } + + private void changeMods(IReadOnlyList mods) + { + footerButtonMods.Current.Value = mods; + } + + private class TestFooterButtonMods : FooterButtonMods + { + public new OsuSpriteText MultiplierText => base.MultiplierText; + } + } +} From 92ab8026a006bd9e7977bd659dcb3e9b1a41d63e Mon Sep 17 00:00:00 2001 From: Min Date: Thu, 28 Nov 2019 16:03:59 +1100 Subject: [PATCH 4229/5608] 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 54a8c00bb854c8bf70cd077302cd6fbba240504a Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Thu, 28 Nov 2019 17:09:54 +1030 Subject: [PATCH 4230/5608] Add support for --sdl command line arg --- .../.idea/runConfigurations/osu_SDL.xml | 20 +++++++++++++++++++ osu.Desktop/Program.cs | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 .idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml diff --git a/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml new file mode 100644 index 0000000000..1fd10e0e1a --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml @@ -0,0 +1,20 @@ + + + + \ No newline at end of file diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 141b2cdbbc..bd91bcc933 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -22,8 +22,9 @@ namespace osu.Desktop { // Back up the cwd before DesktopGameHost changes it var cwd = Environment.CurrentDirectory; + bool useSdl = args.Contains("--sdl"); - using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true)) + using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true, useSdl: useSdl)) { host.ExceptionThrown += handleException; From f504370867a1f221444c743a2520a686dc5459c2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Nov 2019 15:58:26 +0900 Subject: [PATCH 4231/5608] 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 4232/5608] 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 ada8dabf7eac666ad118790110b6ee383bc93d60 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Thu, 28 Nov 2019 18:48:43 +0700 Subject: [PATCH 4233/5608] Add right margin on score multiplier text --- osu.Game/Screens/Select/FooterButtonMods.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 8dc0a2a132..fbeda8f18e 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -54,6 +54,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(weight: FontWeight.Bold), + Margin = new MarginPadding { Right = 10 } } }, AutoSizeAxes = Axes.Both, From a4f584c6a4771c0f8c40bafaa544d4e83e8a571e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Nov 2019 22:00:01 +0900 Subject: [PATCH 4234/5608] 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 af5c5a3000beb54796f9f356d4cd59b804a500a4 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Thu, 28 Nov 2019 20:06:15 +0700 Subject: [PATCH 4235/5608] Apply reviews Also rename the class name to match with the others --- ...onMods.cs => TestSceneFooterButtonMods.cs} | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{TestCaseFooterButtonMods.cs => TestSceneFooterButtonMods.cs} (81%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseFooterButtonMods.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs similarity index 81% rename from osu.Game.Tests/Visual/UserInterface/TestCaseFooterButtonMods.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs index 0c437800bc..e8d3475a11 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestCaseFooterButtonMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs @@ -11,7 +11,7 @@ using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.UserInterface { - public class TestCaseFooterButtonMods : OsuTestScene + public class TestSceneFooterButtonMods : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.UserInterface private readonly TestFooterButtonMods footerButtonMods; - public TestCaseFooterButtonMods() + public TestSceneFooterButtonMods() { Add(footerButtonMods = new TestFooterButtonMods()); } @@ -29,24 +29,24 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestIncrementMultiplier() { AddStep(@"Add Hidden", () => changeMods(new Mod[] { new OsuModHidden() })); - AddAssert(@"Check Hidden multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"1.06x")); + AddAssert(@"Check Hidden multiplier", () => footerButtonMods.MultiplierText.Text == @"1.06x"); AddStep(@"Add HardRock", () => changeMods(new Mod[] { new OsuModHidden() })); - AddAssert(@"Check HardRock multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"1.06x")); + AddAssert(@"Check HardRock multiplier", () => footerButtonMods.MultiplierText.Text == @"1.06x"); AddStep(@"Add DoubleTime", () => changeMods(new Mod[] { new OsuModDoubleTime() })); - AddAssert(@"Check DoubleTime multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"1.12x")); + AddAssert(@"Check DoubleTime multiplier", () => footerButtonMods.MultiplierText.Text == @"1.12x"); AddStep(@"Add multiple Mods", () => changeMods(new Mod[] { new OsuModDoubleTime(), new OsuModHidden(), new OsuModHidden() })); - AddAssert(@"Check multiple mod multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"1.26x")); + AddAssert(@"Check multiple mod multiplier", () => footerButtonMods.MultiplierText.Text == @"1.26x"); } [Test] public void TestDecrementMultiplier() { AddStep(@"Add Easy", () => changeMods(new Mod[] { new OsuModEasy() })); - AddAssert(@"Check Easy multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"0.50x")); + AddAssert(@"Check Easy multiplier", () => footerButtonMods.MultiplierText.Text == @"0.50x"); AddStep(@"Add NoFail", () => changeMods(new Mod[] { new OsuModNoFail() })); - AddAssert(@"Check NoFail multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"0.50x")); + AddAssert(@"Check NoFail multiplier", () => footerButtonMods.MultiplierText.Text == @"0.50x"); AddStep(@"Add Multiple Mods", () => changeMods(new Mod[] { new OsuModEasy(), new OsuModNoFail() })); - AddAssert(@"Check multiple mod multiplier", () => footerButtonMods.MultiplierText.Text.Equals(@"0.25x")); + AddAssert(@"Check multiple mod multiplier", () => footerButtonMods.MultiplierText.Text == @"0.25x"); } [Test] @@ -54,7 +54,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep(@"Add mods", () => changeMods(new Mod[] { new OsuModDoubleTime(), new OsuModFlashlight() })); AddStep(@"Clear selected mod", () => changeMods(Array.Empty())); - AddAssert(@"Check empty multiplier", () => footerButtonMods.MultiplierText.Text.Equals(string.Empty)); + AddAssert(@"Check empty multiplier", () => string.IsNullOrEmpty(footerButtonMods.MultiplierText.Text)); } private void changeMods(IReadOnlyList mods) From 71a871d7d1dede52cc9d75b435b7a70b664befc3 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Thu, 28 Nov 2019 21:59:57 +0700 Subject: [PATCH 4236/5608] 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 4237/5608] 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 4238/5608] 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 4239/5608] 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 4240/5608] 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 4241/5608] 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 4242/5608] 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 4243/5608] 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 4244/5608] 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 4245/5608] 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 4246/5608] 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 4247/5608] 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 4248/5608] 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 4249/5608] 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 4250/5608] 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 4251/5608] 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 4252/5608] 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 4253/5608] 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 4254/5608] 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 4255/5608] 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 c4515429158bb5ed4a7a14b10b65f218fd8cd481 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 30 Nov 2019 03:01:07 +0300 Subject: [PATCH 4256/5608] Rankings overlay basic implementation --- .../Visual/Online/TestSceneRankingsOverlay.cs | 59 ++++++ osu.Game/Overlays/RankingsOverlay.cs | 198 ++++++++++++++++++ osu.Game/Users/Drawables/UpdateableFlag.cs | 14 ++ 3 files changed, 271 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs create mode 100644 osu.Game/Overlays/RankingsOverlay.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs new file mode 100644 index 0000000000..1f08fe7530 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs @@ -0,0 +1,59 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Game.Overlays.Rankings.Tables; +using osu.Framework.Allocation; +using osu.Game.Overlays; +using NUnit.Framework; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsOverlay : OsuTestScene + { + protected override bool UseOnlineAPI => true; + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(PerformanceTable), + typeof(ScoresTable), + typeof(CountriesTable), + typeof(TableRowBackground), + typeof(UserBasedTable), + typeof(RankingsTable<>), + typeof(RankingsOverlay) + }; + + [Cached] + private RankingsOverlay rankingsOverlay; + + public TestSceneRankingsOverlay() + { + Add(rankingsOverlay = new RankingsOverlay()); + } + + [Test] + public void TestShow() + { + AddStep("Show", rankingsOverlay.Show); + } + + [Test] + public void TestShowCountry() + { + AddStep("Show US", () => rankingsOverlay.ShowCountry(new Country + { + FlagName = "US", + FullName = "United States" + })); + } + + [Test] + public void TestHide() + { + AddStep("Hide", rankingsOverlay.Hide); + } + } +} diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs new file mode 100644 index 0000000000..b9b2fe7232 --- /dev/null +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -0,0 +1,198 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Overlays.Rankings; +using osu.Game.Users; +using osu.Game.Rulesets; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using System.Threading; +using osu.Game.Online.API.Requests; +using osu.Game.Overlays.Rankings.Tables; + +namespace osu.Game.Overlays +{ + public class RankingsOverlay : FullscreenOverlay + { + private readonly Bindable country = new Bindable(); + private readonly Bindable scope = new Bindable(); + private readonly Bindable ruleset = new Bindable(); + + private readonly BasicScrollContainer scrollFlow; + private readonly Box background; + private readonly Container contentPlaceholder; + private readonly DimmedLoadingLayer loading; + + private APIRequest request; + private CancellationTokenSource cancellationToken; + + [Resolved] + private IAPIProvider api { get; set; } + + public RankingsOverlay() + { + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + scrollFlow = new BasicScrollContainer + { + RelativeSizeAxes = Axes.Both, + ScrollbarVisible = false, + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new RankingsHeader + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Country = { BindTarget = country }, + Scope = { BindTarget = scope }, + Ruleset = { BindTarget = ruleset } + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + contentPlaceholder = new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Margin = new MarginPadding { Vertical = 10 } + }, + loading = new DimmedLoadingLayer(), + } + } + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colour) + { + Waves.FirstWaveColour = colour.Green; + Waves.SecondWaveColour = colour.GreenLight; + Waves.ThirdWaveColour = colour.GreenDark; + Waves.FourthWaveColour = colour.GreenDarker; + + background.Colour = OsuColour.Gray(0.1f); + } + + protected override void LoadComplete() + { + country.BindValueChanged(_ => redraw(), true); + scope.BindValueChanged(_ => redraw(), true); + ruleset.BindValueChanged(_ => redraw(), true); + base.LoadComplete(); + } + + public void ShowCountry(Country requested) + { + if (requested == null) + return; + + Show(); + + if (country.Value?.FlagName == requested.FlagName) + return; + + country.Value = requested; + } + + private void redraw() + { + scrollFlow.ScrollToStart(); + + loading.Show(); + + cancellationToken?.Cancel(); + request?.Cancel(); + + cancellationToken = new CancellationTokenSource(); + + switch (scope.Value) + { + default: + contentPlaceholder.Clear(); + loading.Hide(); + return; + + case RankingsScope.Performance: + createPerformanceTable(); + return; + + case RankingsScope.Country: + createCountryTable(); + return; + + case RankingsScope.Score: + createScoreTable(); + return; + } + } + + private void createCountryTable() + { + request = new GetCountryRankingsRequest(ruleset.Value); + ((GetCountryRankingsRequest)request).Success += rankings => Schedule(() => + { + var table = new CountriesTable(1, rankings.Countries); + loadTable(table); + }); + + api.Queue(request); + } + + private void createPerformanceTable() + { + request = new GetUserRankingsRequest(ruleset.Value, country: country.Value?.FlagName); + ((GetUserRankingsRequest)request).Success += rankings => Schedule(() => + { + var table = new PerformanceTable(1, rankings.Users); + loadTable(table); + }); + + api.Queue(request); + } + + private void createScoreTable() + { + request = new GetUserRankingsRequest(ruleset.Value, UserRankingsType.Score); + ((GetUserRankingsRequest)request).Success += rankings => Schedule(() => + { + var table = new ScoresTable(1, rankings.Users); + loadTable(table); + }); + + api.Queue(request); + } + + private void loadTable(Drawable table) + { + LoadComponentAsync(table, t => + { + contentPlaceholder.Clear(); + contentPlaceholder.Add(t); + loading.Hide(); + }, cancellationToken.Token); + } + } +} diff --git a/osu.Game/Users/Drawables/UpdateableFlag.cs b/osu.Game/Users/Drawables/UpdateableFlag.cs index abc16b2390..e7c23d3c23 100644 --- a/osu.Game/Users/Drawables/UpdateableFlag.cs +++ b/osu.Game/Users/Drawables/UpdateableFlag.cs @@ -1,8 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; +using osu.Game.Overlays; namespace osu.Game.Users.Drawables { @@ -34,5 +37,16 @@ namespace osu.Game.Users.Drawables RelativeSizeAxes = Axes.Both, }; } + + [Resolved(canBeNull: true)] + private RankingsOverlay rankingsOverlay { get; set; } + + protected override bool OnClick(ClickEvent e) + { + if (Country != null) + rankingsOverlay?.ShowCountry(Country); + + return true; + } } } From 0ac46755468b9bf840c816707674a626ae7e95c6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 1 Dec 2019 03:52:41 +0300 Subject: [PATCH 4257/5608] Implement IEquatable --- osu.Game/Overlays/RankingsOverlay.cs | 3 --- osu.Game/Users/Country.cs | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index b9b2fe7232..d3586a538b 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -111,9 +111,6 @@ namespace osu.Game.Overlays Show(); - if (country.Value?.FlagName == requested.FlagName) - return; - country.Value = requested; } diff --git a/osu.Game/Users/Country.cs b/osu.Game/Users/Country.cs index 1dcce6e870..101d268a60 100644 --- a/osu.Game/Users/Country.cs +++ b/osu.Game/Users/Country.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using Newtonsoft.Json; namespace osu.Game.Users { - public class Country + public class Country : IEquatable { /// /// The name of this country. @@ -18,5 +19,7 @@ namespace osu.Game.Users /// [JsonProperty(@"code")] public string FlagName; + + public bool Equals(Country other) => FlagName == other.FlagName; } } From f375db368f1ac0208d7dd4dd5497da93ec6ab448 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 1 Dec 2019 03:56:03 +0300 Subject: [PATCH 4258/5608] Remove useless null check --- osu.Game/Users/Drawables/UpdateableFlag.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Users/Drawables/UpdateableFlag.cs b/osu.Game/Users/Drawables/UpdateableFlag.cs index e7c23d3c23..1d30720889 100644 --- a/osu.Game/Users/Drawables/UpdateableFlag.cs +++ b/osu.Game/Users/Drawables/UpdateableFlag.cs @@ -43,9 +43,7 @@ namespace osu.Game.Users.Drawables protected override bool OnClick(ClickEvent e) { - if (Country != null) - rankingsOverlay?.ShowCountry(Country); - + rankingsOverlay?.ShowCountry(Country); return true; } } From 62daea195c5ab9b90d170c878c5fbaba5161e360 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 1 Dec 2019 04:09:45 +0300 Subject: [PATCH 4259/5608] Fix possible null --- osu.Game/Users/Country.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Users/Country.cs b/osu.Game/Users/Country.cs index 101d268a60..a9fcd69286 100644 --- a/osu.Game/Users/Country.cs +++ b/osu.Game/Users/Country.cs @@ -20,6 +20,6 @@ namespace osu.Game.Users [JsonProperty(@"code")] public string FlagName; - public bool Equals(Country other) => FlagName == other.FlagName; + public bool Equals(Country other) => FlagName == other?.FlagName; } } From 3b88afd069fd179195d4593db439e9da9247cdaf Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 1 Dec 2019 12:02:47 -0800 Subject: [PATCH 4260/5608] 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 4261/5608] 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 4262/5608] 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 4263/5608] 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 4264/5608] 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 4265/5608] 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 4266/5608] 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 4267/5608] 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 4268/5608] 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 4269/5608] 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 4270/5608] 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 4271/5608] 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 4272/5608] 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 4273/5608] 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 4274/5608] 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 4275/5608] 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 4276/5608] 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 4277/5608] 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 4278/5608] 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 4279/5608] 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 48732e49b94967317181137d08f2cbc642f54b9f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 5 Dec 2019 04:20:13 +0300 Subject: [PATCH 4280/5608] Improve async logic --- osu.Game/Overlays/RankingsOverlay.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index d3586a538b..948d165b82 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -15,6 +15,7 @@ using osu.Game.Online.API; using System.Threading; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Rankings.Tables; +using osu.Framework.Threading; namespace osu.Game.Overlays { @@ -30,6 +31,7 @@ namespace osu.Game.Overlays private readonly DimmedLoadingLayer loading; private APIRequest request; + private ScheduledDelegate showTableDelegate; private CancellationTokenSource cancellationToken; [Resolved] @@ -120,11 +122,10 @@ namespace osu.Game.Overlays loading.Show(); + showTableDelegate?.Cancel(); cancellationToken?.Cancel(); request?.Cancel(); - cancellationToken = new CancellationTokenSource(); - switch (scope.Value) { default: @@ -184,12 +185,12 @@ namespace osu.Game.Overlays private void loadTable(Drawable table) { - LoadComponentAsync(table, t => + showTableDelegate = Schedule(() => LoadComponentAsync(table, t => { contentPlaceholder.Clear(); contentPlaceholder.Add(t); loading.Hide(); - }, cancellationToken.Token); + }, (cancellationToken = new CancellationTokenSource()).Token)); } } } From f8f144b6c04671f0daf7155791e7314e5cdf26e3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 5 Dec 2019 05:20:22 +0300 Subject: [PATCH 4281/5608] Remove pointless ScheduledDelegate --- osu.Game/Overlays/RankingsOverlay.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index 948d165b82..0ec03ebcc9 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -15,7 +15,6 @@ using osu.Game.Online.API; using System.Threading; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Rankings.Tables; -using osu.Framework.Threading; namespace osu.Game.Overlays { @@ -31,7 +30,6 @@ namespace osu.Game.Overlays private readonly DimmedLoadingLayer loading; private APIRequest request; - private ScheduledDelegate showTableDelegate; private CancellationTokenSource cancellationToken; [Resolved] @@ -122,7 +120,6 @@ namespace osu.Game.Overlays loading.Show(); - showTableDelegate?.Cancel(); cancellationToken?.Cancel(); request?.Cancel(); @@ -185,12 +182,12 @@ namespace osu.Game.Overlays private void loadTable(Drawable table) { - showTableDelegate = Schedule(() => LoadComponentAsync(table, t => + LoadComponentAsync(table, t => { contentPlaceholder.Clear(); contentPlaceholder.Add(t); loading.Hide(); - }, (cancellationToken = new CancellationTokenSource()).Token)); + }, (cancellationToken = new CancellationTokenSource()).Token); } } } From 40d0700fa514da9d4df1abd78fbe3a74a053d985 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Dec 2019 13:43:38 +0900 Subject: [PATCH 4282/5608] Add structure for path control points --- osu.Game/Rulesets/Objects/PathControlPoint.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 osu.Game/Rulesets/Objects/PathControlPoint.cs diff --git a/osu.Game/Rulesets/Objects/PathControlPoint.cs b/osu.Game/Rulesets/Objects/PathControlPoint.cs new file mode 100644 index 0000000000..40a8b0251b --- /dev/null +++ b/osu.Game/Rulesets/Objects/PathControlPoint.cs @@ -0,0 +1,16 @@ +using System; +using osu.Framework.Bindables; +using osu.Game.Rulesets.Objects.Types; +using osuTK; + +namespace osu.Game.Rulesets.Objects +{ + public class PathControlPoint : IEquatable + { + public readonly Bindable Position = new Bindable(); + + public readonly Bindable Type = new Bindable(); + + public bool Equals(PathControlPoint other) => Position.Value == other.Position.Value && Type.Value == other.Type.Value; + } +} From 5f9b9631ef38bae53c320a9aa1512250399b1f47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 14:07:39 +0900 Subject: [PATCH 4283/5608] Move scope/country restrictions into RankingsOverlay --- osu.Game/Overlays/Rankings/HeaderTitle.cs | 10 +--------- osu.Game/Overlays/RankingsOverlay.cs | 24 +++++++++++++++++++---- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Rankings/HeaderTitle.cs b/osu.Game/Overlays/Rankings/HeaderTitle.cs index a1a893fa6b..b08a2a3900 100644 --- a/osu.Game/Overlays/Rankings/HeaderTitle.cs +++ b/osu.Game/Overlays/Rankings/HeaderTitle.cs @@ -74,13 +74,7 @@ namespace osu.Game.Overlays.Rankings base.LoadComplete(); } - private void onScopeChanged(ValueChangedEvent scope) - { - scopeText.Text = scope.NewValue.ToString(); - - if (scope.NewValue != RankingsScope.Performance) - Country.Value = null; - } + private void onScopeChanged(ValueChangedEvent scope) => scopeText.Text = scope.NewValue.ToString(); private void onCountryChanged(ValueChangedEvent country) { @@ -90,8 +84,6 @@ namespace osu.Game.Overlays.Rankings return; } - Scope.Value = RankingsScope.Performance; - flag.Country = country.NewValue; flag.Show(); } diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index 0ec03ebcc9..b989e9473b 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -98,9 +98,25 @@ namespace osu.Game.Overlays protected override void LoadComplete() { - country.BindValueChanged(_ => redraw(), true); - scope.BindValueChanged(_ => redraw(), true); - ruleset.BindValueChanged(_ => redraw(), true); + country.BindValueChanged(_ => + { + // if a country is requested, force performance scope. + if (country.Value != null) + scope.Value = RankingsScope.Performance; + + Scheduler.AddOnce(loadNewContent); + }, true); + scope.BindValueChanged(_ => + { + // country filtering is only valid for performance scope. + if (scope.Value != RankingsScope.Performance) + country.Value = null; + + Scheduler.AddOnce(loadNewContent); + }, true); + + ruleset.BindValueChanged(_ => Scheduler.AddOnce(loadNewContent), true); + base.LoadComplete(); } @@ -114,7 +130,7 @@ namespace osu.Game.Overlays country.Value = requested; } - private void redraw() + private void loadNewContent() { scrollFlow.ScrollToStart(); From cd473f207a1dab9f058cc1e370508fdc63e3a0a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 14:09:33 +0900 Subject: [PATCH 4284/5608] Use child set, not Clear/Add --- osu.Game/Overlays/RankingsOverlay.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index b989e9473b..154cf0e47b 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -200,8 +200,7 @@ namespace osu.Game.Overlays { LoadComponentAsync(table, t => { - contentPlaceholder.Clear(); - contentPlaceholder.Add(t); + contentPlaceholder.Child = t; loading.Hide(); }, (cancellationToken = new CancellationTokenSource()).Token); } From 6e9157d59c75cf680c11d216f68cd42b233b9dc2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 14:26:36 +0900 Subject: [PATCH 4285/5608] Standardise request/response handling --- .../API/Requests/GetUserRankingsRequest.cs | 7 +- osu.Game/Overlays/RankingsOverlay.cs | 97 ++++++++++--------- 2 files changed, 55 insertions(+), 49 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs b/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs index 9c3eba9fdc..6f657aee8d 100644 --- a/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs @@ -8,13 +8,14 @@ namespace osu.Game.Online.API.Requests { public class GetUserRankingsRequest : GetRankingsRequest { + public readonly UserRankingsType Type; + 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.Type = type; this.country = country; } @@ -28,7 +29,7 @@ namespace osu.Game.Online.API.Requests return req; } - protected override string TargetPostfix() => type.ToString().ToLowerInvariant(); + protected override string TargetPostfix() => Type.ToString().ToLowerInvariant(); } public enum UserRankingsType diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index 154cf0e47b..aa42b029e0 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -26,10 +26,10 @@ namespace osu.Game.Overlays private readonly BasicScrollContainer scrollFlow; private readonly Box background; - private readonly Container contentPlaceholder; + private readonly Container tableContainer; private readonly DimmedLoadingLayer loading; - private APIRequest request; + private APIRequest lastRequest; private CancellationTokenSource cancellationToken; [Resolved] @@ -68,7 +68,7 @@ namespace osu.Game.Overlays AutoSizeAxes = Axes.Y, Children = new Drawable[] { - contentPlaceholder = new Container + tableContainer = new Container { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -132,76 +132,81 @@ namespace osu.Game.Overlays private void loadNewContent() { - scrollFlow.ScrollToStart(); - loading.Show(); cancellationToken?.Cancel(); - request?.Cancel(); + lastRequest?.Cancel(); + var request = createScopedRequest(); + lastRequest = request; + + if (request == null) + { + loadTable(null); + return; + } + + request.Success += () => loadTable(createTableFromResponse(request)); + request.Failure += _ => loadTable(null); + + api.Queue(request); + } + + private APIRequest createScopedRequest() + { switch (scope.Value) { - default: - contentPlaceholder.Clear(); - loading.Hide(); - return; - case RankingsScope.Performance: - createPerformanceTable(); - return; + return new GetUserRankingsRequest(ruleset.Value, country: country.Value?.FlagName); case RankingsScope.Country: - createCountryTable(); - return; + return new GetCountryRankingsRequest(ruleset.Value); case RankingsScope.Score: - createScoreTable(); - return; + return new GetUserRankingsRequest(ruleset.Value, UserRankingsType.Score); } + + return null; } - private void createCountryTable() + private Drawable createTableFromResponse(APIRequest request) { - request = new GetCountryRankingsRequest(ruleset.Value); - ((GetCountryRankingsRequest)request).Success += rankings => Schedule(() => + switch (request) { - var table = new CountriesTable(1, rankings.Countries); - loadTable(table); - }); + case GetUserRankingsRequest userRequest: + switch (userRequest.Type) + { + case UserRankingsType.Performance: + return new PerformanceTable(1, userRequest.Result.Users); - api.Queue(request); - } + case UserRankingsType.Score: + return new ScoresTable(1, userRequest.Result.Users); + } - private void createPerformanceTable() - { - request = new GetUserRankingsRequest(ruleset.Value, country: country.Value?.FlagName); - ((GetUserRankingsRequest)request).Success += rankings => Schedule(() => - { - var table = new PerformanceTable(1, rankings.Users); - loadTable(table); - }); + return null; - api.Queue(request); - } + case GetCountryRankingsRequest countryRequest: + return new CountriesTable(1, countryRequest.Result.Countries); + } - private void createScoreTable() - { - request = new GetUserRankingsRequest(ruleset.Value, UserRankingsType.Score); - ((GetUserRankingsRequest)request).Success += rankings => Schedule(() => - { - var table = new ScoresTable(1, rankings.Users); - loadTable(table); - }); - - api.Queue(request); + return null; } private void loadTable(Drawable table) { + scrollFlow.ScrollToStart(); + + if (table == null) + { + tableContainer.Clear(); + loading.Hide(); + return; + } + LoadComponentAsync(table, t => { - contentPlaceholder.Child = t; loading.Hide(); + tableContainer.Child = table; }, (cancellationToken = new CancellationTokenSource()).Token); } } From 3e0f499e72a3149920ea13f16fd859a3e35fea6d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Dec 2019 14:38:21 +0900 Subject: [PATCH 4286/5608] Add xmldocs --- osu.Game/Rulesets/Objects/PathControlPoint.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Rulesets/Objects/PathControlPoint.cs b/osu.Game/Rulesets/Objects/PathControlPoint.cs index 40a8b0251b..fe66fb79cb 100644 --- a/osu.Game/Rulesets/Objects/PathControlPoint.cs +++ b/osu.Game/Rulesets/Objects/PathControlPoint.cs @@ -7,8 +7,15 @@ namespace osu.Game.Rulesets.Objects { public class PathControlPoint : IEquatable { + /// + /// The position of this . + /// public readonly Bindable Position = new Bindable(); + /// + /// The type of path segment starting at this . + /// If null, this will be a part of the previous path segment. + /// public readonly Bindable Type = new Bindable(); public bool Equals(PathControlPoint other) => Position.Value == other.Position.Value && Type.Value == other.Type.Value; From 0149e476739c1e86ddd3b4c32d7ec4292fe37355 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Dec 2019 14:38:32 +0900 Subject: [PATCH 4287/5608] Expose general control point change event --- osu.Game/Rulesets/Objects/PathControlPoint.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Rulesets/Objects/PathControlPoint.cs b/osu.Game/Rulesets/Objects/PathControlPoint.cs index fe66fb79cb..d68ef4112b 100644 --- a/osu.Game/Rulesets/Objects/PathControlPoint.cs +++ b/osu.Game/Rulesets/Objects/PathControlPoint.cs @@ -18,6 +18,17 @@ namespace osu.Game.Rulesets.Objects /// public readonly Bindable Type = new Bindable(); + /// + /// Invoked when any property of this is changed. + /// + internal event Action Changed; + + public PathControlPoint() + { + Position.ValueChanged += _ => Changed?.Invoke(); + Type.ValueChanged += _ => Changed?.Invoke(); + } + public bool Equals(PathControlPoint other) => Position.Value == other.Position.Value && Type.Value == other.Type.Value; } } From de413418c7404f7c34fcb75ef16a6fac942ae5ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 14:50:12 +0900 Subject: [PATCH 4288/5608] Remove redundant prefix --- osu.Game/Online/API/Requests/GetUserRankingsRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs b/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs index 6f657aee8d..143d21e40d 100644 --- a/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs @@ -15,7 +15,7 @@ namespace osu.Game.Online.API.Requests public GetUserRankingsRequest(RulesetInfo ruleset, UserRankingsType type = UserRankingsType.Performance, int page = 1, string country = null) : base(ruleset, page) { - this.Type = type; + Type = type; this.country = country; } From 33737d3d89b7381b29f695c5bfc6312464c74ff2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 5 Dec 2019 09:53:25 +0300 Subject: [PATCH 4289/5608] Move tests to TestSceneRankingsOverlay due to refactoring --- .../Visual/Online/TestSceneRankingsHeader.cs | 2 - .../Online/TestSceneRankingsHeaderTitle.cs | 5 --- .../Visual/Online/TestSceneRankingsOverlay.cs | 39 ++++++++++++++++--- osu.Game/Overlays/RankingsOverlay.cs | 26 ++++++------- 4 files changed, 46 insertions(+), 26 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs index c0da605cdb..e708934bc3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs @@ -68,9 +68,7 @@ namespace osu.Game.Tests.Visual.Online }; AddStep("Set country", () => countryBindable.Value = country); - AddAssert("Check scope is Performance", () => scope.Value == RankingsScope.Performance); AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); - AddAssert("Check country is Null", () => countryBindable.Value == null); AddStep("Set country with no flag", () => countryBindable.Value = unknownCountry); } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs index 849ca2defc..0edf104da0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs @@ -43,11 +43,6 @@ namespace osu.Game.Tests.Visual.Online FullName = "United States" }; - AddStep("Set country", () => countryBindable.Value = countryA); - AddAssert("Check scope is Performance", () => scope.Value == RankingsScope.Performance); - AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); - AddAssert("Check country is Null", () => countryBindable.Value == null); - AddStep("Set country 1", () => countryBindable.Value = countryA); AddStep("Set country 2", () => countryBindable.Value = countryB); AddStep("Set null country", () => countryBindable.Value = null); diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs index 1f08fe7530..09f008b308 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs @@ -8,6 +8,8 @@ using osu.Framework.Allocation; using osu.Game.Overlays; using NUnit.Framework; using osu.Game.Users; +using osu.Framework.Bindables; +using osu.Game.Overlays.Rankings; namespace osu.Game.Tests.Visual.Online { @@ -29,9 +31,16 @@ namespace osu.Game.Tests.Visual.Online [Cached] private RankingsOverlay rankingsOverlay; + private readonly Bindable countryBindable = new Bindable(); + private readonly Bindable scope = new Bindable(); + public TestSceneRankingsOverlay() { - Add(rankingsOverlay = new RankingsOverlay()); + Add(rankingsOverlay = new TestRankingsOverlay + { + Country = { BindTarget = countryBindable }, + Scope = { BindTarget = scope }, + }); } [Test] @@ -40,14 +49,19 @@ namespace osu.Game.Tests.Visual.Online AddStep("Show", rankingsOverlay.Show); } + [Test] + public void TestFlagScopeDependency() + { + AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); + AddAssert("Check country is Null", () => countryBindable.Value == null); + AddStep("Set country", () => countryBindable.Value = us_country); + AddAssert("Check scope is Performance", () => scope.Value == RankingsScope.Performance); + } + [Test] public void TestShowCountry() { - AddStep("Show US", () => rankingsOverlay.ShowCountry(new Country - { - FlagName = "US", - FullName = "United States" - })); + AddStep("Show US", () => rankingsOverlay.ShowCountry(us_country)); } [Test] @@ -55,5 +69,18 @@ namespace osu.Game.Tests.Visual.Online { AddStep("Hide", rankingsOverlay.Hide); } + + private static Country us_country = new Country + { + FlagName = "US", + FullName = "United States" + }; + + private class TestRankingsOverlay : RankingsOverlay + { + public new Bindable Country => base.Country; + + public new Bindable Scope => base.Scope; + } } } diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index aa42b029e0..e7c8b94a10 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -20,8 +20,8 @@ namespace osu.Game.Overlays { public class RankingsOverlay : FullscreenOverlay { - private readonly Bindable country = new Bindable(); - private readonly Bindable scope = new Bindable(); + protected readonly Bindable Country = new Bindable(); + protected readonly Bindable Scope = new Bindable(); private readonly Bindable ruleset = new Bindable(); private readonly BasicScrollContainer scrollFlow; @@ -58,8 +58,8 @@ namespace osu.Game.Overlays { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Country = { BindTarget = country }, - Scope = { BindTarget = scope }, + Country = { BindTarget = Country }, + Scope = { BindTarget = Scope }, Ruleset = { BindTarget = ruleset } }, new Container @@ -98,19 +98,19 @@ namespace osu.Game.Overlays protected override void LoadComplete() { - country.BindValueChanged(_ => + Country.BindValueChanged(_ => { // if a country is requested, force performance scope. - if (country.Value != null) - scope.Value = RankingsScope.Performance; + if (Country.Value != null) + Scope.Value = RankingsScope.Performance; Scheduler.AddOnce(loadNewContent); }, true); - scope.BindValueChanged(_ => + Scope.BindValueChanged(_ => { // country filtering is only valid for performance scope. - if (scope.Value != RankingsScope.Performance) - country.Value = null; + if (Scope.Value != RankingsScope.Performance) + Country.Value = null; Scheduler.AddOnce(loadNewContent); }, true); @@ -127,7 +127,7 @@ namespace osu.Game.Overlays Show(); - country.Value = requested; + Country.Value = requested; } private void loadNewContent() @@ -154,10 +154,10 @@ namespace osu.Game.Overlays private APIRequest createScopedRequest() { - switch (scope.Value) + switch (Scope.Value) { case RankingsScope.Performance: - return new GetUserRankingsRequest(ruleset.Value, country: country.Value?.FlagName); + return new GetUserRankingsRequest(ruleset.Value, country: Country.Value?.FlagName); case RankingsScope.Country: return new GetCountryRankingsRequest(ruleset.Value); From bf7c309d4c87c7e74f0bcca629c81976067d00dd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 5 Dec 2019 10:05:04 +0300 Subject: [PATCH 4290/5608] Make field readonly --- osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs index 09f008b308..568e36df4c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs @@ -70,7 +70,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("Hide", rankingsOverlay.Hide); } - private static Country us_country = new Country + private static readonly Country us_country = new Country { FlagName = "US", FullName = "United States" From 5e9b739b6718c44b643679fdb72b94f0ee378d91 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Dec 2019 16:45:02 +0900 Subject: [PATCH 4291/5608] Re-implement slider paths to support multiple segments --- .../Visual/Gameplay/TestSceneSliderPath2.cs | 159 ++++++++++ osu.Game/Rulesets/Objects/SliderPath2.cs | 274 ++++++++++++++++++ 2 files changed, 433 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath2.cs create mode 100644 osu.Game/Rulesets/Objects/SliderPath2.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath2.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath2.cs new file mode 100644 index 0000000000..08d54fcdda --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath2.cs @@ -0,0 +1,159 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Lines; +using osu.Framework.MathUtils; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using osuTK; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestSceneSliderPath2 : OsuTestScene + { + private readonly SmoothPath drawablePath; + private SliderPath2 path; + + public TestSceneSliderPath2() + { + Child = drawablePath = new SmoothPath + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }; + } + + [SetUp] + public void Setup() => Schedule(() => + { + path = new SliderPath2(); + }); + + protected override void Update() + { + base.Update(); + + if (path != null) + { + List vertices = new List(); + path.GetPathToProgress(vertices, 0, 1); + + drawablePath.Vertices = vertices; + } + } + + [Test] + public void TestEmptyPath() + { + } + + [TestCase(PathType.Linear)] + [TestCase(PathType.Bezier)] + [TestCase(PathType.Catmull)] + [TestCase(PathType.PerfectCurve)] + public void TestSingleSegment(PathType type) + => AddStep("create path", () => path.ControlPoints.AddRange(createSegment(type, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); + + [TestCase(PathType.Linear)] + [TestCase(PathType.Bezier)] + [TestCase(PathType.Catmull)] + [TestCase(PathType.PerfectCurve)] + public void TestMultipleSegment(PathType type) + { + AddStep("create path", () => + { + path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero)); + path.ControlPoints.AddRange(createSegment(type, new Vector2(0, 100), new Vector2(100), Vector2.Zero)); + }); + } + + [Test] + public void TestAddControlPoint() + { + AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100)))); + AddStep("add point", () => path.ControlPoints.Add(new PathControlPoint { Position = { Value = new Vector2(100) } })); + } + + [Test] + public void TestInsertControlPoint() + { + AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(100)))); + AddStep("insert point", () => path.ControlPoints.Insert(1, new PathControlPoint { Position = { Value = new Vector2(0, 100) } })); + } + + [Test] + public void TestRemoveControlPoint() + { + AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); + AddStep("remove second point", () => path.ControlPoints.RemoveAt(1)); + } + + [Test] + public void TestChangePathType() + { + AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); + AddStep("change type to bezier", () => path.ControlPoints[0].Type.Value = PathType.Bezier); + } + + [Test] + public void TestAddSegmentByChangingType() + { + AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100), new Vector2(100, 0)))); + AddStep("change second point type to bezier", () => path.ControlPoints[1].Type.Value = PathType.Bezier); + } + + [Test] + public void TestRemoveSegmentByChangingType() + { + AddStep("create path", () => + { + path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100), new Vector2(100, 0))); + path.ControlPoints[1].Type.Value = PathType.Bezier; + }); + + AddStep("change second point type to null", () => path.ControlPoints[1].Type.Value = null); + } + + [Test] + public void TestRemoveSegmentByRemovingControlPoint() + { + AddStep("create path", () => + { + path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100), new Vector2(100, 0))); + path.ControlPoints[1].Type.Value = PathType.Bezier; + }); + + AddStep("remove second point", () => path.ControlPoints.RemoveAt(1)); + } + + [TestCase(2)] + [TestCase(4)] + public void TestPerfectCurveFallbackScenarios(int points) + { + AddStep("create path", () => + { + switch (points) + { + case 2: + path.ControlPoints.AddRange(createSegment(PathType.PerfectCurve, Vector2.Zero, new Vector2(0, 100))); + break; + case 4: + path.ControlPoints.AddRange(createSegment(PathType.PerfectCurve, Vector2.Zero, new Vector2(0, 100), new Vector2(100), new Vector2(100, 0))); + break; + } + }); + + } + + private List createSegment(PathType type, params Vector2[] controlPoints) + { + var points = controlPoints.Select(p => new PathControlPoint { Position = { Value = p } }).ToList(); + points[0].Type.Value = type; + return points; + } + } +} diff --git a/osu.Game/Rulesets/Objects/SliderPath2.cs b/osu.Game/Rulesets/Objects/SliderPath2.cs new file mode 100644 index 0000000000..560313a4d5 --- /dev/null +++ b/osu.Game/Rulesets/Objects/SliderPath2.cs @@ -0,0 +1,274 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Newtonsoft.Json; +using osu.Framework.Bindables; +using osu.Framework.Caching; +using osu.Framework.MathUtils; +using osu.Game.Rulesets.Objects.Types; +using osuTK; + +namespace osu.Game.Rulesets.Objects +{ + public class SliderPath2 + { + /// + /// The user-set distance of the path. If non-null, will match this value, + /// and the path will be shortened/lengthened to match this length. + /// + public readonly double? ExpectedDistance; + + /// + /// The control points of the path. + /// + public readonly BindableList ControlPoints = new BindableList(); + + private readonly Cached pathCache = new Cached(); + + private readonly List calculatedPath = new List(); + private readonly List cumulativeLength = new List(); + + /// + /// Creates a new . + /// + /// A user-set distance of the path that may be shorter or longer than the true distance between all control points. + /// The path will be shortened/lengthened to match this length. If null, the path will use the true distance between all control points. + [JsonConstructor] + public SliderPath2(double? expectedDistance = null) + { + ExpectedDistance = expectedDistance; + + ControlPoints.ItemsAdded += items => + { + foreach (var c in items) + c.Changed += onControlPointChanged; + + onControlPointChanged(); + }; + + ControlPoints.ItemsRemoved += items => + { + foreach (var c in items) + c.Changed -= onControlPointChanged; + + onControlPointChanged(); + }; + + void onControlPointChanged() => pathCache.Invalidate(); + } + + /// + /// The distance of the path after lengthening/shortening to account for . + /// + [JsonIgnore] + public double Distance + { + get + { + ensureValid(); + return cumulativeLength.Count == 0 ? 0 : cumulativeLength[cumulativeLength.Count - 1]; + } + } + + /// + /// Computes the slider path until a given progress that ranges from 0 (beginning of the slider) + /// to 1 (end of the slider) and stores the generated path in the given list. + /// + /// The list to be filled with the computed path. + /// Start progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider). + /// End progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider). + public void GetPathToProgress(List path, double p0, double p1) + { + ensureValid(); + + double d0 = progressToDistance(p0); + double d1 = progressToDistance(p1); + + path.Clear(); + + int i = 0; + + for (; i < calculatedPath.Count && cumulativeLength[i] < d0; ++i) + { + } + + path.Add(interpolateVertices(i, d0)); + + for (; i < calculatedPath.Count && cumulativeLength[i] <= d1; ++i) + path.Add(calculatedPath[i]); + + path.Add(interpolateVertices(i, d1)); + } + + /// + /// Computes the position on the slider at a given progress that ranges from 0 (beginning of the path) + /// to 1 (end of the path). + /// + /// Ranges from 0 (beginning of the path) to 1 (end of the path). + /// + public Vector2 PositionAt(double progress) + { + ensureValid(); + + double d = progressToDistance(progress); + return interpolateVertices(indexOfDistance(d), d); + } + + private void ensureValid() + { + if (pathCache.IsValid) + return; + + calculatePath(); + calculateCumulativeLength(); + + pathCache.Validate(); + } + + private void calculatePath() + { + calculatedPath.Clear(); + + if (ControlPoints.Count == 0) + return; + + if (ControlPoints[0].Type.Value == null) + throw new InvalidOperationException($"The first control point in a {nameof(SliderPath2)} must have a non-null type."); + + Vector2[] vertices = new Vector2[ControlPoints.Count]; + for (int i = 0; i < ControlPoints.Count; i++) + vertices[i] = ControlPoints[i].Position.Value; + + int start = 0; + + for (int i = 0; i < ControlPoints.Count; i++) + { + if (ControlPoints[i].Type.Value == null && i < ControlPoints.Count - 1) + continue; + + Debug.Assert(ControlPoints[start].Type.Value.HasValue); + + // The current vertex ends the segment + var segmentVertices = vertices.AsSpan().Slice(start, i - start + 1); + var segmentType = ControlPoints[start].Type.Value.Value; + + foreach (Vector2 t in computeSubPath(segmentVertices, segmentType)) + { + if (calculatedPath.Count == 0 || calculatedPath.Last() != t) + calculatedPath.Add(t); + } + + // Start the new segment at the current vertex + start = i; + } + + static List computeSubPath(ReadOnlySpan subControlPoints, PathType type) + { + switch (type) + { + case PathType.Linear: + return PathApproximator.ApproximateLinear(subControlPoints); + + case PathType.PerfectCurve: + if (subControlPoints.Length != 3) + break; + + List subpath = PathApproximator.ApproximateCircularArc(subControlPoints); + + // If for some reason a circular arc could not be fit to the 3 given points, fall back to a numerically stable bezier approximation. + if (subpath.Count == 0) + break; + + return subpath; + + case PathType.Catmull: + return PathApproximator.ApproximateCatmull(subControlPoints); + } + + return PathApproximator.ApproximateBezier(subControlPoints); + } + } + + private void calculateCumulativeLength() + { + double l = 0; + + cumulativeLength.Clear(); + cumulativeLength.Add(l); + + for (int i = 0; i < calculatedPath.Count - 1; ++i) + { + Vector2 diff = calculatedPath[i + 1] - calculatedPath[i]; + double d = diff.Length; + + // Shorted slider paths that are too long compared to the expected distance + if (ExpectedDistance.HasValue && ExpectedDistance - l < d) + { + calculatedPath[i + 1] = calculatedPath[i] + diff * (float)((ExpectedDistance - l) / d); + calculatedPath.RemoveRange(i + 2, calculatedPath.Count - 2 - i); + + l = ExpectedDistance.Value; + cumulativeLength.Add(l); + break; + } + + l += d; + cumulativeLength.Add(l); + } + + // Lengthen slider paths that are too short compared to the expected distance + if (ExpectedDistance.HasValue && l < ExpectedDistance && calculatedPath.Count > 1) + { + Vector2 diff = calculatedPath[calculatedPath.Count - 1] - calculatedPath[calculatedPath.Count - 2]; + double d = diff.Length; + + if (d <= 0) + return; + + calculatedPath[calculatedPath.Count - 1] += diff * (float)((ExpectedDistance - l) / d); + cumulativeLength[calculatedPath.Count - 1] = ExpectedDistance.Value; + } + } + + private int indexOfDistance(double d) + { + int i = cumulativeLength.BinarySearch(d); + if (i < 0) i = ~i; + + return i; + } + + private double progressToDistance(double progress) + { + return Math.Clamp(progress, 0, 1) * Distance; + } + + private Vector2 interpolateVertices(int i, double d) + { + if (calculatedPath.Count == 0) + return Vector2.Zero; + + if (i <= 0) + return calculatedPath.First(); + if (i >= calculatedPath.Count) + return calculatedPath.Last(); + + Vector2 p0 = calculatedPath[i - 1]; + Vector2 p1 = calculatedPath[i]; + + double d0 = cumulativeLength[i - 1]; + double d1 = cumulativeLength[i]; + + // Avoid division by and almost-zero number in case two points are extremely close to each other. + if (Precision.AlmostEquals(d0, d1)) + return p0; + + double w = (d - d0) / (d1 - d0); + return p0 + (p1 - p0) * (float)w; + } + } +} From 0e9787146115d728eff1b04f3e79d6b6724955ed Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Thu, 5 Dec 2019 14:53:01 +0700 Subject: [PATCH 4292/5608] 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 2702edfa555fc98b68c9e11c45ce30b30ba02737 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Dec 2019 17:49:32 +0900 Subject: [PATCH 4293/5608] Rename new path, replace existing one --- ...eSliderPath2.cs => TestSceneSliderPath.cs} | 8 +- osu.Game/Rulesets/Objects/SliderPath.cs | 177 +++++------ osu.Game/Rulesets/Objects/SliderPath2.cs | 274 ------------------ 3 files changed, 93 insertions(+), 366 deletions(-) rename osu.Game.Tests/Visual/Gameplay/{TestSceneSliderPath2.cs => TestSceneSliderPath.cs} (97%) delete mode 100644 osu.Game/Rulesets/Objects/SliderPath2.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath2.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs similarity index 97% rename from osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath2.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs index 08d54fcdda..fe2cc188a5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath2.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs @@ -13,12 +13,12 @@ using osuTK; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSliderPath2 : OsuTestScene + public class TestSceneSliderPath : OsuTestScene { private readonly SmoothPath drawablePath; - private SliderPath2 path; + private SliderPath path; - public TestSceneSliderPath2() + public TestSceneSliderPath() { Child = drawablePath = new SmoothPath { @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Visual.Gameplay [SetUp] public void Setup() => Schedule(() => { - path = new SliderPath2(); + path = new SliderPath(); }); protected override void Update() diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index ae6aad5b9c..cc2b537afc 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -1,17 +1,20 @@ -// 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; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using Newtonsoft.Json; +using osu.Framework.Bindables; +using osu.Framework.Caching; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Types; using osuTK; namespace osu.Game.Rulesets.Objects { - public struct SliderPath : IEquatable + public class SliderPath { /// /// The user-set distance of the path. If non-null, will match this value, @@ -20,49 +23,47 @@ namespace osu.Game.Rulesets.Objects public readonly double? ExpectedDistance; /// - /// The type of path. + /// The control points of the path. /// - public readonly PathType Type; + public readonly BindableList ControlPoints = new BindableList(); - [JsonProperty] - private Vector2[] controlPoints; + public readonly List Test = new List(); - private List calculatedPath; - private List cumulativeLength; + private readonly Cached pathCache = new Cached(); - private bool isInitialised; + private readonly List calculatedPath = new List(); + private readonly List cumulativeLength = new List(); /// /// Creates a new . /// - /// The type of path. - /// The control points of the path. - /// A user-set distance of the path that may be shorter or longer than the true distance between all - /// . The path will be shortened/lengthened to match this length. - /// If null, the path will use the true distance between all . + /// An optional set of s to initialise the path with. + /// A user-set distance of the path that may be shorter or longer than the true distance between all control points. + /// The path will be shortened/lengthened to match this length. If null, the path will use the true distance between all control points. [JsonConstructor] - public SliderPath(PathType type, Vector2[] controlPoints, double? expectedDistance = null) + public SliderPath(PathControlPoint[] controlPoints = null, double? expectedDistance = null) { - this = default; - this.controlPoints = controlPoints; - - Type = type; ExpectedDistance = expectedDistance; - ensureInitialised(); - } - - /// - /// The control points of the path. - /// - [JsonIgnore] - public ReadOnlySpan ControlPoints - { - get + ControlPoints.ItemsAdded += items => { - ensureInitialised(); - return controlPoints.AsSpan(); - } + foreach (var c in items) + c.Changed += onControlPointChanged; + + onControlPointChanged(); + }; + + ControlPoints.ItemsRemoved += items => + { + foreach (var c in items) + c.Changed -= onControlPointChanged; + + onControlPointChanged(); + }; + + ControlPoints.AddRange(controlPoints); + + void onControlPointChanged() => pathCache.Invalidate(); } /// @@ -73,7 +74,7 @@ namespace osu.Game.Rulesets.Objects { get { - ensureInitialised(); + ensureValid(); return cumulativeLength.Count == 0 ? 0 : cumulativeLength[cumulativeLength.Count - 1]; } } @@ -87,7 +88,7 @@ namespace osu.Game.Rulesets.Objects /// End progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider). public void GetPathToProgress(List path, double p0, double p1) { - ensureInitialised(); + ensureValid(); double d0 = progressToDistance(p0); double d1 = progressToDistance(p1); @@ -116,82 +117,84 @@ namespace osu.Game.Rulesets.Objects /// public Vector2 PositionAt(double progress) { - ensureInitialised(); + ensureValid(); double d = progressToDistance(progress); return interpolateVertices(indexOfDistance(d), d); } - private void ensureInitialised() + private void ensureValid() { - if (isInitialised) + if (pathCache.IsValid) return; - isInitialised = true; - - controlPoints ??= Array.Empty(); - calculatedPath = new List(); - cumulativeLength = new List(); - calculatePath(); calculateCumulativeLength(); - } - private List calculateSubpath(ReadOnlySpan subControlPoints) - { - switch (Type) - { - case PathType.Linear: - return PathApproximator.ApproximateLinear(subControlPoints); - - case PathType.PerfectCurve: - //we can only use CircularArc iff we have exactly three control points and no dissection. - if (ControlPoints.Length != 3 || subControlPoints.Length != 3) - break; - - // Here we have exactly 3 control points. Attempt to fit a circular arc. - List subpath = PathApproximator.ApproximateCircularArc(subControlPoints); - - // If for some reason a circular arc could not be fit to the 3 given points, fall back to a numerically stable bezier approximation. - if (subpath.Count == 0) - break; - - return subpath; - - case PathType.Catmull: - return PathApproximator.ApproximateCatmull(subControlPoints); - } - - return PathApproximator.ApproximateBezier(subControlPoints); + pathCache.Validate(); } private void calculatePath() { calculatedPath.Clear(); - // Sliders may consist of various subpaths separated by two consecutive vertices - // with the same position. The following loop parses these subpaths and computes - // their shape independently, consecutively appending them to calculatedPath. + if (ControlPoints.Count == 0) + return; + + if (ControlPoints[0].Type.Value == null) + throw new InvalidOperationException($"The first control point in a {nameof(SliderPath)} must have a non-null type."); + + Vector2[] vertices = new Vector2[ControlPoints.Count]; + for (int i = 0; i < ControlPoints.Count; i++) + vertices[i] = ControlPoints[i].Position.Value; int start = 0; - int end = 0; - for (int i = 0; i < ControlPoints.Length; ++i) + for (int i = 0; i < ControlPoints.Count; i++) { - end++; + if (ControlPoints[i].Type.Value == null && i < ControlPoints.Count - 1) + continue; - if (i == ControlPoints.Length - 1 || ControlPoints[i] == ControlPoints[i + 1]) + Debug.Assert(ControlPoints[start].Type.Value.HasValue); + + // The current vertex ends the segment + var segmentVertices = vertices.AsSpan().Slice(start, i - start + 1); + var segmentType = ControlPoints[start].Type.Value.Value; + + foreach (Vector2 t in computeSubPath(segmentVertices, segmentType)) { - ReadOnlySpan cpSpan = ControlPoints.Slice(start, end - start); - - foreach (Vector2 t in calculateSubpath(cpSpan)) - { - if (calculatedPath.Count == 0 || calculatedPath.Last() != t) - calculatedPath.Add(t); - } - - start = end; + if (calculatedPath.Count == 0 || calculatedPath.Last() != t) + calculatedPath.Add(t); } + + // Start the new segment at the current vertex + start = i; + } + + static List computeSubPath(ReadOnlySpan subControlPoints, PathType type) + { + switch (type) + { + case PathType.Linear: + return PathApproximator.ApproximateLinear(subControlPoints); + + case PathType.PerfectCurve: + if (subControlPoints.Length != 3) + break; + + List subpath = PathApproximator.ApproximateCircularArc(subControlPoints); + + // If for some reason a circular arc could not be fit to the 3 given points, fall back to a numerically stable bezier approximation. + if (subpath.Count == 0) + break; + + return subpath; + + case PathType.Catmull: + return PathApproximator.ApproximateCatmull(subControlPoints); + } + + return PathApproximator.ApproximateBezier(subControlPoints); } } @@ -272,7 +275,5 @@ namespace osu.Game.Rulesets.Objects double w = (d - d0) / (d1 - d0); return p0 + (p1 - p0) * (float)w; } - - public bool Equals(SliderPath other) => ControlPoints.SequenceEqual(other.ControlPoints) && ExpectedDistance == other.ExpectedDistance && Type == other.Type; } } diff --git a/osu.Game/Rulesets/Objects/SliderPath2.cs b/osu.Game/Rulesets/Objects/SliderPath2.cs deleted file mode 100644 index 560313a4d5..0000000000 --- a/osu.Game/Rulesets/Objects/SliderPath2.cs +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using Newtonsoft.Json; -using osu.Framework.Bindables; -using osu.Framework.Caching; -using osu.Framework.MathUtils; -using osu.Game.Rulesets.Objects.Types; -using osuTK; - -namespace osu.Game.Rulesets.Objects -{ - public class SliderPath2 - { - /// - /// The user-set distance of the path. If non-null, will match this value, - /// and the path will be shortened/lengthened to match this length. - /// - public readonly double? ExpectedDistance; - - /// - /// The control points of the path. - /// - public readonly BindableList ControlPoints = new BindableList(); - - private readonly Cached pathCache = new Cached(); - - private readonly List calculatedPath = new List(); - private readonly List cumulativeLength = new List(); - - /// - /// Creates a new . - /// - /// A user-set distance of the path that may be shorter or longer than the true distance between all control points. - /// The path will be shortened/lengthened to match this length. If null, the path will use the true distance between all control points. - [JsonConstructor] - public SliderPath2(double? expectedDistance = null) - { - ExpectedDistance = expectedDistance; - - ControlPoints.ItemsAdded += items => - { - foreach (var c in items) - c.Changed += onControlPointChanged; - - onControlPointChanged(); - }; - - ControlPoints.ItemsRemoved += items => - { - foreach (var c in items) - c.Changed -= onControlPointChanged; - - onControlPointChanged(); - }; - - void onControlPointChanged() => pathCache.Invalidate(); - } - - /// - /// The distance of the path after lengthening/shortening to account for . - /// - [JsonIgnore] - public double Distance - { - get - { - ensureValid(); - return cumulativeLength.Count == 0 ? 0 : cumulativeLength[cumulativeLength.Count - 1]; - } - } - - /// - /// Computes the slider path until a given progress that ranges from 0 (beginning of the slider) - /// to 1 (end of the slider) and stores the generated path in the given list. - /// - /// The list to be filled with the computed path. - /// Start progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider). - /// End progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider). - public void GetPathToProgress(List path, double p0, double p1) - { - ensureValid(); - - double d0 = progressToDistance(p0); - double d1 = progressToDistance(p1); - - path.Clear(); - - int i = 0; - - for (; i < calculatedPath.Count && cumulativeLength[i] < d0; ++i) - { - } - - path.Add(interpolateVertices(i, d0)); - - for (; i < calculatedPath.Count && cumulativeLength[i] <= d1; ++i) - path.Add(calculatedPath[i]); - - path.Add(interpolateVertices(i, d1)); - } - - /// - /// Computes the position on the slider at a given progress that ranges from 0 (beginning of the path) - /// to 1 (end of the path). - /// - /// Ranges from 0 (beginning of the path) to 1 (end of the path). - /// - public Vector2 PositionAt(double progress) - { - ensureValid(); - - double d = progressToDistance(progress); - return interpolateVertices(indexOfDistance(d), d); - } - - private void ensureValid() - { - if (pathCache.IsValid) - return; - - calculatePath(); - calculateCumulativeLength(); - - pathCache.Validate(); - } - - private void calculatePath() - { - calculatedPath.Clear(); - - if (ControlPoints.Count == 0) - return; - - if (ControlPoints[0].Type.Value == null) - throw new InvalidOperationException($"The first control point in a {nameof(SliderPath2)} must have a non-null type."); - - Vector2[] vertices = new Vector2[ControlPoints.Count]; - for (int i = 0; i < ControlPoints.Count; i++) - vertices[i] = ControlPoints[i].Position.Value; - - int start = 0; - - for (int i = 0; i < ControlPoints.Count; i++) - { - if (ControlPoints[i].Type.Value == null && i < ControlPoints.Count - 1) - continue; - - Debug.Assert(ControlPoints[start].Type.Value.HasValue); - - // The current vertex ends the segment - var segmentVertices = vertices.AsSpan().Slice(start, i - start + 1); - var segmentType = ControlPoints[start].Type.Value.Value; - - foreach (Vector2 t in computeSubPath(segmentVertices, segmentType)) - { - if (calculatedPath.Count == 0 || calculatedPath.Last() != t) - calculatedPath.Add(t); - } - - // Start the new segment at the current vertex - start = i; - } - - static List computeSubPath(ReadOnlySpan subControlPoints, PathType type) - { - switch (type) - { - case PathType.Linear: - return PathApproximator.ApproximateLinear(subControlPoints); - - case PathType.PerfectCurve: - if (subControlPoints.Length != 3) - break; - - List subpath = PathApproximator.ApproximateCircularArc(subControlPoints); - - // If for some reason a circular arc could not be fit to the 3 given points, fall back to a numerically stable bezier approximation. - if (subpath.Count == 0) - break; - - return subpath; - - case PathType.Catmull: - return PathApproximator.ApproximateCatmull(subControlPoints); - } - - return PathApproximator.ApproximateBezier(subControlPoints); - } - } - - private void calculateCumulativeLength() - { - double l = 0; - - cumulativeLength.Clear(); - cumulativeLength.Add(l); - - for (int i = 0; i < calculatedPath.Count - 1; ++i) - { - Vector2 diff = calculatedPath[i + 1] - calculatedPath[i]; - double d = diff.Length; - - // Shorted slider paths that are too long compared to the expected distance - if (ExpectedDistance.HasValue && ExpectedDistance - l < d) - { - calculatedPath[i + 1] = calculatedPath[i] + diff * (float)((ExpectedDistance - l) / d); - calculatedPath.RemoveRange(i + 2, calculatedPath.Count - 2 - i); - - l = ExpectedDistance.Value; - cumulativeLength.Add(l); - break; - } - - l += d; - cumulativeLength.Add(l); - } - - // Lengthen slider paths that are too short compared to the expected distance - if (ExpectedDistance.HasValue && l < ExpectedDistance && calculatedPath.Count > 1) - { - Vector2 diff = calculatedPath[calculatedPath.Count - 1] - calculatedPath[calculatedPath.Count - 2]; - double d = diff.Length; - - if (d <= 0) - return; - - calculatedPath[calculatedPath.Count - 1] += diff * (float)((ExpectedDistance - l) / d); - cumulativeLength[calculatedPath.Count - 1] = ExpectedDistance.Value; - } - } - - private int indexOfDistance(double d) - { - int i = cumulativeLength.BinarySearch(d); - if (i < 0) i = ~i; - - return i; - } - - private double progressToDistance(double progress) - { - return Math.Clamp(progress, 0, 1) * Distance; - } - - private Vector2 interpolateVertices(int i, double d) - { - if (calculatedPath.Count == 0) - return Vector2.Zero; - - if (i <= 0) - return calculatedPath.First(); - if (i >= calculatedPath.Count) - return calculatedPath.Last(); - - Vector2 p0 = calculatedPath[i - 1]; - Vector2 p1 = calculatedPath[i]; - - double d0 = cumulativeLength[i - 1]; - double d1 = cumulativeLength[i]; - - // Avoid division by and almost-zero number in case two points are extremely close to each other. - if (Precision.AlmostEquals(d0, d1)) - return p0; - - double w = (d - d0) / (d1 - d0); - return p0 + (p1 - p0) * (float)w; - } - } -} From 986ac1cee4df72dc07c93f15f24032bc714a1edc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Dec 2019 17:49:54 +0900 Subject: [PATCH 4294/5608] Make expected distance a bindable --- osu.Game/Rulesets/Objects/SliderPath.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index cc2b537afc..9d68e1337a 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Objects /// The user-set distance of the path. If non-null, will match this value, /// and the path will be shortened/lengthened to match this length. /// - public readonly double? ExpectedDistance; + public readonly Bindable ExpectedDistance = new Bindable(); /// /// The control points of the path. @@ -43,7 +43,8 @@ namespace osu.Game.Rulesets.Objects [JsonConstructor] public SliderPath(PathControlPoint[] controlPoints = null, double? expectedDistance = null) { - ExpectedDistance = expectedDistance; + ExpectedDistance.Value = expectedDistance; + ExpectedDistance.ValueChanged += _ => pathCache.Invalidate(); ControlPoints.ItemsAdded += items => { @@ -205,18 +206,20 @@ namespace osu.Game.Rulesets.Objects cumulativeLength.Clear(); cumulativeLength.Add(l); + double? expectedDistance = ExpectedDistance.Value; + for (int i = 0; i < calculatedPath.Count - 1; ++i) { Vector2 diff = calculatedPath[i + 1] - calculatedPath[i]; double d = diff.Length; // Shorted slider paths that are too long compared to the expected distance - if (ExpectedDistance.HasValue && ExpectedDistance - l < d) + if (expectedDistance.HasValue && expectedDistance - l < d) { - calculatedPath[i + 1] = calculatedPath[i] + diff * (float)((ExpectedDistance - l) / d); + calculatedPath[i + 1] = calculatedPath[i] + diff * (float)((expectedDistance - l) / d); calculatedPath.RemoveRange(i + 2, calculatedPath.Count - 2 - i); - l = ExpectedDistance.Value; + l = expectedDistance.Value; cumulativeLength.Add(l); break; } @@ -226,7 +229,7 @@ namespace osu.Game.Rulesets.Objects } // Lengthen slider paths that are too short compared to the expected distance - if (ExpectedDistance.HasValue && l < ExpectedDistance && calculatedPath.Count > 1) + if (expectedDistance.HasValue && l < expectedDistance && calculatedPath.Count > 1) { Vector2 diff = calculatedPath[calculatedPath.Count - 1] - calculatedPath[calculatedPath.Count - 2]; double d = diff.Length; @@ -234,8 +237,8 @@ namespace osu.Game.Rulesets.Objects if (d <= 0) return; - calculatedPath[calculatedPath.Count - 1] += diff * (float)((ExpectedDistance - l) / d); - cumulativeLength[calculatedPath.Count - 1] = ExpectedDistance.Value; + calculatedPath[calculatedPath.Count - 1] += diff * (float)((expectedDistance - l) / d); + cumulativeLength[calculatedPath.Count - 1] = expectedDistance.Value; } } From 1585d83b969016e287cb9c2af06abdbe2df431f3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Dec 2019 18:19:42 +0900 Subject: [PATCH 4295/5608] Add legacy constructor --- osu.Game/Rulesets/Objects/SliderPath.cs | 33 +++++++++++++++++++------ 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 9d68e1337a..bbeb03992e 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -37,13 +37,8 @@ namespace osu.Game.Rulesets.Objects /// /// Creates a new . /// - /// An optional set of s to initialise the path with. - /// A user-set distance of the path that may be shorter or longer than the true distance between all control points. - /// The path will be shortened/lengthened to match this length. If null, the path will use the true distance between all control points. - [JsonConstructor] - public SliderPath(PathControlPoint[] controlPoints = null, double? expectedDistance = null) + public SliderPath() { - ExpectedDistance.Value = expectedDistance; ExpectedDistance.ValueChanged += _ => pathCache.Invalidate(); ControlPoints.ItemsAdded += items => @@ -62,11 +57,33 @@ namespace osu.Game.Rulesets.Objects onControlPointChanged(); }; - ControlPoints.AddRange(controlPoints); - void onControlPointChanged() => pathCache.Invalidate(); } + /// + /// Creates a new . + /// + /// An optional set of s to initialise the path with. + /// A user-set distance of the path that may be shorter or longer than the true distance between all control points. + /// The path will be shortened/lengthened to match this length. If null, the path will use the true distance between all control points. + [JsonConstructor] + public SliderPath(PathControlPoint[] controlPoints, double? expectedDistance = null) + : this() + { + ControlPoints.AddRange(controlPoints); + ExpectedDistance.Value = expectedDistance; + } + + public SliderPath(PathType type, Vector2[] controlPoints, double? expectedDistance = null) + : this() + { + foreach (var c in controlPoints) + ControlPoints.Add(new PathControlPoint { Position = { Value = c } }); + ControlPoints[0].Type.Value = type; + + ExpectedDistance.Value = expectedDistance; + } + /// /// The distance of the path after lengthening/shortening to account for . /// From 2419077c0763612f0cb05f8e503e7208373dfd47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 18:31:13 +0900 Subject: [PATCH 4296/5608] 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 c9a66c0d07a8a89267355133a0eb8caead972c88 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Dec 2019 18:31:28 +0900 Subject: [PATCH 4297/5608] Expose a version to indicate path changes --- osu.Game/Rulesets/Objects/SliderPath.cs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index bbeb03992e..6ad5d2f1c3 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -16,6 +16,13 @@ namespace osu.Game.Rulesets.Objects { public class SliderPath { + /// + /// The current version of this . Updated when any change to the path occurs. + /// + public IBindable Version => version; + + private readonly Bindable version = new Bindable(); + /// /// The user-set distance of the path. If non-null, will match this value, /// and the path will be shortened/lengthened to match this length. @@ -39,25 +46,23 @@ namespace osu.Game.Rulesets.Objects /// public SliderPath() { - ExpectedDistance.ValueChanged += _ => pathCache.Invalidate(); + ExpectedDistance.ValueChanged += _ => invalidate(); ControlPoints.ItemsAdded += items => { foreach (var c in items) - c.Changed += onControlPointChanged; + c.Changed += invalidate; - onControlPointChanged(); + invalidate(); }; ControlPoints.ItemsRemoved += items => { foreach (var c in items) - c.Changed -= onControlPointChanged; + c.Changed -= invalidate; - onControlPointChanged(); + invalidate(); }; - - void onControlPointChanged() => pathCache.Invalidate(); } /// @@ -141,6 +146,12 @@ namespace osu.Game.Rulesets.Objects return interpolateVertices(indexOfDistance(d), d); } + private void invalidate() + { + pathCache.Invalidate(); + version.Value++; + } + private void ensureValid() { if (pathCache.IsValid) From e225b0032aa092c79322fb948fd7e3adb7aac2b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 19:31:40 +0900 Subject: [PATCH 4298/5608] Add basic hitobject display to timeline --- .../Editor/TestSceneEditorComposeTimeline.cs | 16 ++++ .../Compose/Components/Timeline/Timeline.cs | 21 +++-- .../Timeline/TimelineHitObjectDisplay.cs | 85 +++++++++++++++++++ 3 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index 6e5b3b93e9..b67ea798a0 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -13,6 +13,10 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose.Components.Timeline; using osuTK; using osuTK.Graphics; @@ -25,11 +29,23 @@ namespace osu.Game.Tests.Visual.Editor public override IReadOnlyList RequiredTypes => new[] { typeof(TimelineArea), + typeof(TimelineHitObjectDisplay), typeof(Timeline), typeof(TimelineButton), typeof(CentreMarker) }; + [Cached(typeof(IEditorBeatmap))] + private readonly EditorBeatmap editorBeatmap; + + public TestSceneEditorComposeTimeline() + { + editorBeatmap = new EditorBeatmap( + (Beatmap) + CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, new Mod[] { }) + ); + } + [BackgroundDependencyLoader] private void load(AudioManager audio) { diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 748c9e2ba3..1f8c134d84 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -36,14 +36,21 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { this.adjustableClock = adjustableClock; - Child = waveform = new WaveformGraph + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = colours.Blue.Opacity(0.2f), - LowColour = colours.BlueLighter, - MidColour = colours.BlueDark, - HighColour = colours.BlueDarker, - Depth = float.MaxValue + waveform = new WaveformGraph + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Blue.Opacity(0.2f), + LowColour = colours.BlueLighter, + MidColour = colours.BlueDark, + HighColour = colours.BlueDarker, + Depth = float.MaxValue + }, + new TimelineHitObjectDisplay + { + RelativeSizeAxes = Axes.Both, + }, }; // We don't want the centre marker to scroll diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs new file mode 100644 index 0000000000..8bc0bf1a86 --- /dev/null +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs @@ -0,0 +1,85 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Edit.Compose.Components.Timeline +{ + internal class TimelineHitObjectDisplay : TimelinePart + { + [Resolved] + private IEditorBeatmap beatmap { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + foreach (var h in beatmap.HitObjects) + add(h); + + beatmap.HitObjectAdded += add; + beatmap.HitObjectRemoved += remove; + } + + private void remove(HitObject h) + { + foreach (var d in InternalChildren.OfType().Where(c => c.HitObject == h)) + d.Expire(); + } + + private void add(HitObject h) + { + Add(new TimelineHitObjectRepresentation(h)); + } + + private class TimelineHitObjectRepresentation : CompositeDrawable + { + public readonly HitObject HitObject; + + public TimelineHitObjectRepresentation(HitObject hitObject) + { + this.HitObject = hitObject; + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + + Width = (float)(hitObject.GetEndTime() - hitObject.StartTime); + + X = (float)hitObject.StartTime; + + RelativePositionAxes = Axes.X; + RelativeSizeAxes = Axes.X; + + AddInternal(new Circle + { + Size = new Vector2(16), + Anchor = Anchor.CentreLeft, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.X, + AlwaysPresent = true, + Colour = Color4.White, + }); + + if (hitObject is IHasEndTime) + { + AddInternal(new Box + { + Size = new Vector2(1, 5), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativePositionAxes = Axes.X, + RelativeSizeAxes = Axes.X, + Colour = Color4.White, + }); + } + } + } + } +} From 3ebbf62b2ab11d58fd372a091fe179eb7f827188 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Dec 2019 19:53:31 +0900 Subject: [PATCH 4299/5608] Initial game-wide update with the new SliderPath --- .../TestSceneSliderSelectionBlueprint.cs | 2 +- .../Components/PathControlPointPiece.cs | 28 +++-------- .../Components/PathControlPointVisualiser.cs | 24 +++++---- .../Sliders/SliderPlacementBlueprint.cs | 18 +++---- .../Sliders/SliderSelectionBlueprint.cs | 25 +++------- osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs | 7 +-- .../Objects/Drawables/DrawableSlider.cs | 6 +-- .../Objects/Drawables/DrawableSliderHead.cs | 6 +-- .../Objects/Drawables/DrawableSliderTail.cs | 6 +-- osu.Game.Rulesets.Osu/Objects/Slider.cs | 14 +----- .../Objects/SliderTailCircle.cs | 6 +-- .../Legacy/Catch/ConvertHitObjectParser.cs | 4 +- .../Objects/Legacy/ConvertHitObjectParser.cs | 50 +++++++++++++++---- .../Legacy/Mania/ConvertHitObjectParser.cs | 4 +- .../Legacy/Osu/ConvertHitObjectParser.cs | 4 +- .../Legacy/Taiko/ConvertHitObjectParser.cs | 4 +- 16 files changed, 97 insertions(+), 111 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs index dde2aa53e0..013920684c 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs @@ -196,7 +196,7 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep($"move mouse to control point {index}", () => { - Vector2 position = slider.Position + slider.Path.ControlPoints[index]; + Vector2 position = slider.Position + slider.Path.ControlPoints[index].Position.Value; InputManager.MoveMouseTo(drawableObject.Parent.ToScreenSpace(position)); }); } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 0ccf020300..159916f16f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { base.Update(); - Position = slider.StackedPosition + slider.Path.ControlPoints[Index]; + Position = slider.StackedPosition + slider.Path.ControlPoints[Index].Position.Value; updateMarkerDisplay(); updateConnectingPath(); @@ -116,10 +116,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { path.ClearVertices(); - if (Index != slider.Path.ControlPoints.Length - 1) + if (Index != slider.Path.ControlPoints.Count - 1) { path.AddVertex(Vector2.Zero); - path.AddVertex(slider.Path.ControlPoints[Index + 1] - slider.Path.ControlPoints[Index]); + path.AddVertex(slider.Path.ControlPoints[Index + 1].Position.Value - slider.Path.ControlPoints[Index].Position.Value); } path.OriginPosition = path.PositionInBoundingBox(Vector2.Zero); @@ -156,8 +156,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components protected override bool OnDrag(DragEvent e) { - var newControlPoints = slider.Path.ControlPoints.ToArray(); - if (Index == 0) { // Special handling for the head control point - the position of the slider changes which means the snapped position and time have to be taken into account @@ -168,29 +166,17 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components slider.StartTime = snappedTime; // Since control points are relative to the position of the slider, they all need to be offset backwards by the delta - for (int i = 1; i < newControlPoints.Length; i++) - newControlPoints[i] -= movementDelta; + for (int i = 1; i < slider.Path.ControlPoints.Count; i++) + slider.Path.ControlPoints[i].Position.Value -= movementDelta; } else - newControlPoints[Index] += e.Delta; - - if (isSegmentSeparatorWithNext) - newControlPoints[Index + 1] = newControlPoints[Index]; - - if (isSegmentSeparatorWithPrevious) - newControlPoints[Index - 1] = newControlPoints[Index]; - - ControlPointsChanged?.Invoke(newControlPoints); + slider.Path.ControlPoints[Index].Position.Value += e.Delta; return true; } protected override bool OnDragEnd(DragEndEvent e) => true; - private bool isSegmentSeparator => isSegmentSeparatorWithNext || isSegmentSeparatorWithPrevious; - - private bool isSegmentSeparatorWithNext => Index < slider.Path.ControlPoints.Length - 1 && slider.Path.ControlPoints[Index + 1] == slider.Path.ControlPoints[Index]; - - private bool isSegmentSeparatorWithPrevious => Index > 0 && slider.Path.ControlPoints[Index - 1] == slider.Path.ControlPoints[Index]; + private bool isSegmentSeparator => slider.Path.ControlPoints[Index].Type.Value.HasValue; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index cdca48490e..c47e4d7d4a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { base.Update(); - while (slider.Path.ControlPoints.Length > Pieces.Count) + while (slider.Path.ControlPoints.Count > Pieces.Count) { var piece = new PathControlPointPiece(slider, Pieces.Count) { @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components Pieces.Add(piece); } - while (slider.Path.ControlPoints.Length < Pieces.Count) + while (slider.Path.ControlPoints.Count < Pieces.Count) Pieces.Remove(Pieces[Pieces.Count - 1]); } @@ -105,29 +105,32 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private bool deleteSelected() { - var newControlPoints = new List(); + int countDeleted = 0; foreach (var piece in Pieces) { - if (!piece.IsSelected.Value) - newControlPoints.Add(slider.Path.ControlPoints[piece.Index]); + if (piece.IsSelected.Value) + { + slider.Path.ControlPoints.RemoveAt(piece.Index); + countDeleted++; + } } // Ensure that there are any points to be deleted - if (newControlPoints.Count == slider.Path.ControlPoints.Length) + if (countDeleted == 0) return false; // If there are 0 remaining control points, treat the slider as being deleted - if (newControlPoints.Count == 0) + if (slider.Path.ControlPoints.Count == 0) { placementHandler?.Delete(slider); return true; } // Make control points relative - Vector2 first = newControlPoints[0]; - for (int i = 0; i < newControlPoints.Count; i++) - newControlPoints[i] = newControlPoints[i] - first; + Vector2 first = slider.Path.ControlPoints[0].Position.Value; + for (int i = 0; i < slider.Path.ControlPoints.Count; i++) + slider.Path.ControlPoints[i].Position.Value = slider.Path.ControlPoints[i].Position.Value - first; // The slider's position defines the position of the first control point, and all further control points are relative to that point slider.Position += first; @@ -136,7 +139,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components foreach (var piece in Pieces) piece.IsSelected.Value = false; - ControlPointsChanged?.Invoke(newControlPoints.ToArray()); return true; } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 9c0afada29..62a22dc858 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -27,8 +27,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private HitCirclePiece headCirclePiece; private HitCirclePiece tailCirclePiece; - private readonly List segments = new List(); - private Vector2 cursor; private InputManager inputManager; private PlacementState state; @@ -40,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders : base(new Objects.Slider()) { RelativeSizeAxes = Axes.Both; - segments.Add(new Segment(Vector2.Zero)); + HitObject.Path.ControlPoints.Add(new PathControlPoint { Position = { Value = Vector2.Zero } }); } [BackgroundDependencyLoader] @@ -74,7 +72,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders case PlacementState.Body: // The given screen-space position may have been externally snapped, but the unsnapped position from the input manager // is used instead since snapping control points doesn't make much sense - cursor = ToLocalSpace(inputManager.CurrentState.Mouse.Position) - HitObject.Position; + HitObject.Path.ControlPoints[HitObject.Path.ControlPoints.Count - 1].Position.Value = ToLocalSpace(inputManager.CurrentState.Mouse.Position) - HitObject.Position; break; } } @@ -91,7 +89,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders switch (e.Button) { case MouseButton.Left: - segments.Last().ControlPoints.Add(cursor); + HitObject.Path.ControlPoints.Add(new PathControlPoint { Position = { Value = HitObject.Path.ControlPoints[HitObject.Path.ControlPoints.Count - 1].Position.Value } }); break; } @@ -110,7 +108,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders protected override bool OnDoubleClick(DoubleClickEvent e) { - segments.Add(new Segment(segments[segments.Count - 1].ControlPoints.Last())); + HitObject.Path.ControlPoints[HitObject.Path.ControlPoints.Count - 2].Type.Value = PathType.Bezier; return true; } @@ -134,12 +132,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private void updateSlider() { - Vector2[] newControlPoints = segments.SelectMany(s => s.ControlPoints).Concat(cursor.Yield()).ToArray(); - - var unsnappedPath = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints); - var snappedDistance = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)unsnappedPath.Distance) ?? (float)unsnappedPath.Distance; - - HitObject.Path = new SliderPath(unsnappedPath.Type, newControlPoints, snappedDistance); + HitObject.Path.ExpectedDistance.Value = null; + HitObject.Path.ExpectedDistance.Value = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)HitObject.Path.Distance) ?? (float)HitObject.Path.Distance; bodyPiece.UpdateFrom(HitObject); headCirclePiece.UpdateFrom(HitObject.HeadCircle); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 820d6c92d7..ab52c906e8 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -77,12 +77,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { Debug.Assert(placementControlPointIndex != null); - Vector2 position = e.MousePosition - HitObject.Position; - - var controlPoints = HitObject.Path.ControlPoints.ToArray(); - controlPoints[placementControlPointIndex.Value] = position; - - onNewControlPoints(controlPoints); + HitObject.Path.ControlPoints[placementControlPointIndex.Value].Position.Value = e.MousePosition - HitObject.Position; return true; } @@ -97,15 +92,12 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { position -= HitObject.Position; - var controlPoints = new Vector2[HitObject.Path.ControlPoints.Length + 1]; - HitObject.Path.ControlPoints.CopyTo(controlPoints); - int insertionIndex = 0; float minDistance = float.MaxValue; - for (int i = 0; i < controlPoints.Length - 2; i++) + for (int i = 0; i < HitObject.Path.ControlPoints.Count - 2; i++) { - float dist = new Line(controlPoints[i], controlPoints[i + 1]).DistanceToPoint(position); + float dist = new Line(HitObject.Path.ControlPoints[i].Position.Value, HitObject.Path.ControlPoints[i + 1].Position.Value).DistanceToPoint(position); if (dist < minDistance) { @@ -115,20 +107,15 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders } // Move the control points from the insertion index onwards to make room for the insertion - Array.Copy(controlPoints, insertionIndex, controlPoints, insertionIndex + 1, controlPoints.Length - insertionIndex - 1); - controlPoints[insertionIndex] = position; - - onNewControlPoints(controlPoints); + HitObject.Path.ControlPoints.Insert(insertionIndex, new PathControlPoint { Position = { Value = position } }); return insertionIndex; } private void onNewControlPoints(Vector2[] controlPoints) { - var unsnappedPath = new SliderPath(controlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, controlPoints); - var snappedDistance = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)unsnappedPath.Distance) ?? (float)unsnappedPath.Distance; - - HitObject.Path = new SliderPath(unsnappedPath.Type, controlPoints, snappedDistance); + HitObject.Path.ExpectedDistance.Value = null; + HitObject.Path.ExpectedDistance.Value = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)HitObject.Path.Distance) ?? (float)HitObject.Path.Distance; UpdateHitObject(); } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs index 3d566362ae..bc5f79331f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs @@ -28,11 +28,8 @@ namespace osu.Game.Rulesets.Osu.Mods slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); - var newControlPoints = new Vector2[slider.Path.ControlPoints.Length]; - for (int i = 0; i < slider.Path.ControlPoints.Length; i++) - newControlPoints[i] = new Vector2(slider.Path.ControlPoints[i].X, -slider.Path.ControlPoints[i].Y); - - slider.Path = new SliderPath(slider.Path.Type, newControlPoints, slider.Path.ExpectedDistance); + foreach (var point in slider.Path.ControlPoints) + point.Position.Value = new Vector2(point.Position.Value.X, -point.Position.Value.Y); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 69189758a6..1e0402d492 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly IBindable positionBindable = new Bindable(); private readonly IBindable stackHeightBindable = new Bindable(); private readonly IBindable scaleBindable = new Bindable(); - private readonly IBindable pathBindable = new Bindable(); + private readonly IBindable pathVersion = new Bindable(); [Resolved(CanBeNull = true)] private OsuRulesetConfigManager config { get; set; } @@ -84,9 +84,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindTo(HitObject.PositionBindable); stackHeightBindable.BindTo(HitObject.StackHeightBindable); scaleBindable.BindTo(HitObject.ScaleBindable); - pathBindable.BindTo(slider.PathBindable); + pathVersion.BindTo(slider.Path.Version); - pathBindable.BindValueChanged(_ => Body.Refresh()); + pathVersion.BindValueChanged(_ => Body.Refresh()); AccentColour.BindValueChanged(colour => { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index a10c66d1df..166defbc41 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public class DrawableSliderHead : DrawableHitCircle { private readonly IBindable positionBindable = new Bindable(); - private readonly IBindable pathBindable = new Bindable(); + private readonly IBindable pathVersion = new Bindable(); private readonly Slider slider; @@ -27,10 +27,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private void load() { positionBindable.BindTo(HitObject.PositionBindable); - pathBindable.BindTo(slider.PathBindable); + pathVersion.BindTo(slider.Path.Version); positionBindable.BindValueChanged(_ => updatePosition()); - pathBindable.BindValueChanged(_ => updatePosition(), true); + pathVersion.BindValueChanged(_ => updatePosition(), true); } protected override void Update() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index 42bf5e4d21..8e2f6ffa66 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public bool Tracking { get; set; } private readonly IBindable positionBindable = new Bindable(); - private readonly IBindable pathBindable = new Bindable(); + private readonly IBindable pathVersion = new Bindable(); public DrawableSliderTail(Slider slider, SliderTailCircle hitCircle) : base(hitCircle) @@ -36,10 +36,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables AlwaysPresent = true; positionBindable.BindTo(hitCircle.PositionBindable); - pathBindable.BindTo(slider.PathBindable); + pathVersion.BindTo(slider.Path.Version); positionBindable.BindValueChanged(_ => updatePosition()); - pathBindable.BindValueChanged(_ => updatePosition(), true); + pathVersion.BindValueChanged(_ => updatePosition(), true); // TODO: This has no drawable content. Support for skins should be added. } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index c6f5a075e0..b68595c67e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -28,19 +28,7 @@ namespace osu.Game.Rulesets.Osu.Objects public Vector2 StackedPositionAt(double t) => StackedPosition + this.CurvePositionAt(t); - public readonly Bindable PathBindable = new Bindable(); - - public SliderPath Path - { - get => PathBindable.Value; - set - { - PathBindable.Value = value; - endPositionCache.Invalidate(); - - updateNestedPositions(); - } - } + public SliderPath Path { get; set; } = new SliderPath(new[] { new PathControlPoint { Type = { Value = PathType.Bezier } } }); public double Distance => Path.Distance; diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index 14c3369967..c17d2275b8 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -15,12 +15,12 @@ namespace osu.Game.Rulesets.Osu.Objects /// public class SliderTailCircle : SliderCircle { - private readonly IBindable pathBindable = new Bindable(); + private readonly IBindable pathVersion = new Bindable(); public SliderTailCircle(Slider slider) { - pathBindable.BindTo(slider.PathBindable); - pathBindable.BindValueChanged(_ => Position = slider.EndPosition); + pathVersion.BindTo(slider.Path.Version); + pathVersion.BindValueChanged(_ => Position = slider.EndPosition); } public override Judgement CreateJudgement() => new OsuSliderTailJudgement(); diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index 545cfe07f8..afa1f2996e 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount, List> nodeSamples) { newCombo |= forceNewCombo; @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch X = position.X, NewCombo = FirstObject || newCombo, ComboOffset = comboOffset, - Path = new SliderPath(pathType, controlPoints, length), + Path = new SliderPath(controlPoints, length), NodeSamples = nodeSamples, RepeatCount = repeatCount }; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 5348ff1f02..1ac7284772 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -115,12 +115,6 @@ namespace osu.Game.Rulesets.Objects.Legacy points[pointIndex++] = new Vector2((int)Parsing.ParseDouble(temp[0], Parsing.MAX_COORDINATE_VALUE), (int)Parsing.ParseDouble(temp[1], Parsing.MAX_COORDINATE_VALUE)) - pos; } - // osu-stable special-cased colinear perfect curves to a CurveType.Linear - static bool isLinear(Vector2[] p) => Precision.AlmostEquals(0, (p[1].Y - p[0].Y) * (p[2].X - p[0].X) - (p[1].X - p[0].X) * (p[2].Y - p[0].Y)); - - if (points.Length == 3 && pathType == PathType.PerfectCurve && isLinear(points)) - pathType = PathType.Linear; - int repeatCount = Parsing.ParseInt(split[6]); if (repeatCount > 9000) @@ -187,7 +181,7 @@ namespace osu.Game.Rulesets.Objects.Legacy for (int i = 0; i < nodes; i++) nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i])); - result = CreateSlider(pos, combo, comboOffset, points, length, pathType, repeatCount, nodeSamples); + result = CreateSlider(pos, combo, comboOffset, convertControlPoints(points, pathType), length, repeatCount, nodeSamples); // The samples are played when the slider ends, which is the last node result.Samples = nodeSamples[nodeSamples.Count - 1]; @@ -259,6 +253,45 @@ namespace osu.Game.Rulesets.Objects.Legacy bankInfo.Filename = split.Length > 4 ? split[4] : null; } + private PathControlPoint[] convertControlPoints(Vector2[] vertices, PathType type) + { + if (type == PathType.PerfectCurve) + { + if (vertices.Length == 3) + { + // osu-stable special-cased colinear perfect curves to a linear path + if (isLinear(vertices)) + type = PathType.Linear; + } + else + type = PathType.Bezier; + } + + var points = new List(vertices.Length) + { + new PathControlPoint + { + Position = { Value = vertices[0] }, + Type = { Value = type } + } + }; + + for (int i = 1; i < vertices.Length; i++) + { + if (vertices[i] == vertices[i - 1]) + { + points[points.Count - 1].Type.Value = type; + continue; + } + + points.Add(new PathControlPoint { Position = { Value = vertices[i] } }); + } + + return points.ToArray(); + + static bool isLinear(Vector2[] p) => Precision.AlmostEquals(0, (p[1].Y - p[0].Y) * (p[2].X - p[0].X) - (p[1].X - p[0].X) * (p[2].Y - p[0].Y)); + } + /// /// Creates a legacy Hit-type hit object. /// @@ -276,11 +309,10 @@ namespace osu.Game.Rulesets.Objects.Legacy /// When starting a new combo, the offset of the new combo relative to the current one. /// The slider control points. /// The slider length. - /// The slider curve type. /// The slider repeat count. /// The samples to be played when the slider nodes are hit. This includes the head and tail of the slider. /// The hit object. - protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount, List> nodeSamples); /// diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index 8012b4230f..d1a8adc2b7 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -26,13 +26,13 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount, List> nodeSamples) { return new ConvertSlider { X = position.X, - Path = new SliderPath(pathType, controlPoints, length), + Path = new SliderPath(controlPoints, length), NodeSamples = nodeSamples, RepeatCount = repeatCount }; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index 99872e630d..6628f7d059 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount, List> nodeSamples) { newCombo |= forceNewCombo; @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu Position = position, NewCombo = FirstObject || newCombo, ComboOffset = comboOffset, - Path = new SliderPath(pathType, controlPoints, length), + Path = new SliderPath(controlPoints, length), NodeSamples = nodeSamples, RepeatCount = repeatCount }; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs index 9dc0c01932..7b1d64b19f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -23,12 +23,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko return new ConvertHit(); } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount, List> nodeSamples) { return new ConvertSlider { - Path = new SliderPath(pathType, controlPoints, length), + Path = new SliderPath(controlPoints, length), NodeSamples = nodeSamples, RepeatCount = repeatCount }; From d8620a70fbbb7bbc9f983126a98478447fba9dc5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 20:12:25 +0900 Subject: [PATCH 4300/5608] Make work in editor --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 8 ++++++-- .../Timelines/Summary/Parts/TimelinePart.cs | 6 +++--- .../Compose/Components/Timeline/Timeline.cs | 4 ---- .../Components/Timeline/TimelineArea.cs | 10 +++++++--- .../Timeline/TimelineHitObjectDisplay.cs | 20 ++++++++++++------- .../Screens/Edit/Compose/ComposeScreen.cs | 13 ++++++++++-- .../Screens/Edit/EditorScreenWithTimeline.cs | 10 ++++++++-- osu.Game/Screens/Edit/IEditorBeatmap.cs | 5 +++++ 8 files changed, 53 insertions(+), 23 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 805fc2b46f..368520ba43 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -34,7 +34,9 @@ namespace osu.Game.Rulesets.Edit where TObject : HitObject { protected IRulesetConfigManager Config { get; private set; } - protected EditorBeatmap EditorBeatmap { get; private set; } + + protected new EditorBeatmap EditorBeatmap { get; private set; } + protected readonly Ruleset Ruleset; [Resolved] @@ -148,7 +150,7 @@ namespace osu.Game.Rulesets.Edit beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap); - EditorBeatmap = new EditorBeatmap(playableBeatmap); + base.EditorBeatmap = EditorBeatmap = new EditorBeatmap(playableBeatmap); EditorBeatmap.HitObjectAdded += addHitObject; EditorBeatmap.HitObjectRemoved += removeHitObject; EditorBeatmap.StartTimeChanged += UpdateHitObject; @@ -333,6 +335,8 @@ namespace osu.Game.Rulesets.Edit /// public abstract IEnumerable HitObjects { get; } + public IEditorBeatmap EditorBeatmap { get; protected set; } + /// /// Whether the user's cursor is currently in an area of the that is valid for placement. /// diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs index 26d9614631..7706e33179 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -14,12 +14,14 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// /// Represents a part of the summary timeline.. /// - public abstract class TimelinePart : CompositeDrawable + public abstract class TimelinePart : Container { protected readonly IBindable Beatmap = new Bindable(); private readonly Container timeline; + protected override Container Content => timeline; + protected TimelinePart() { AddInternal(timeline = new Container { RelativeSizeAxes = Axes.Both }); @@ -50,8 +52,6 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts timeline.RelativeChildSize = new Vector2((float)Math.Max(1, Beatmap.Value.Track.Length), 1); } - protected void Add(Drawable visualisation) => timeline.Add(visualisation); - protected virtual void LoadBeatmap(WorkingBeatmap beatmap) { timeline.Clear(); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 1f8c134d84..2a565d028f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -47,10 +47,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline HighColour = colours.BlueDarker, Depth = float.MaxValue }, - new TimelineHitObjectDisplay - { - RelativeSizeAxes = Axes.Both, - }, }; // We don't want the centre marker to scroll diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 863a120fc3..93dac059e3 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -11,11 +12,14 @@ using osuTK; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - public class TimelineArea : CompositeDrawable + public class TimelineArea : Container { - private readonly Timeline timeline; + private Timeline timeline; - public TimelineArea() + protected override Container Content => timeline; + + [BackgroundDependencyLoader] + private void load() { Masking = true; CornerRadius = 5; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs index 8bc0bf1a86..fc16d29639 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs @@ -16,8 +16,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { internal class TimelineHitObjectDisplay : TimelinePart { - [Resolved] - private IEditorBeatmap beatmap { get; set; } + private IEditorBeatmap beatmap { get; } + + public TimelineHitObjectDisplay(IEditorBeatmap beatmap) + { + this.beatmap = beatmap; + } [BackgroundDependencyLoader] private void load() @@ -27,18 +31,20 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline beatmap.HitObjectAdded += add; beatmap.HitObjectRemoved += remove; + beatmap.StartTimeChanged += h => + { + remove(h); + add(h); + }; } private void remove(HitObject h) { - foreach (var d in InternalChildren.OfType().Where(c => c.HitObject == h)) + foreach (var d in Children.OfType().Where(c => c.HitObject == h)) d.Expire(); } - private void add(HitObject h) - { - Add(new TimelineHitObjectRepresentation(h)); - } + private void add(HitObject h) => Add(new TimelineHitObjectRepresentation(h)); private class TimelineHitObjectRepresentation : CompositeDrawable { diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 2e9094ebe6..8511bc3242 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -3,17 +3,21 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Edit; +using osu.Game.Screens.Edit.Compose.Components.Timeline; using osu.Game.Skinning; namespace osu.Game.Screens.Edit.Compose { public class ComposeScreen : EditorScreenWithTimeline { + private HitObjectComposer composer; + protected override Drawable CreateMainContent() { var ruleset = Beatmap.Value.BeatmapInfo.Ruleset?.CreateInstance(); - var composer = ruleset?.CreateHitObjectComposer(); + composer = ruleset?.CreateHitObjectComposer(); if (composer != null) { @@ -25,10 +29,15 @@ namespace osu.Game.Screens.Edit.Compose // load the skinning hierarchy first. // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. - return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(ruleset.CreateHitObjectComposer())); + return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(composer)); } return new ScreenWhiteBox.UnderConstructionMessage(ruleset == null ? "This beatmap" : $"{ruleset.Description}'s composer"); } + + protected override Drawable CreateTimelineContent() => new TimelineHitObjectDisplay(composer.EditorBeatmap) + { + RelativeSizeAxes = Axes.Both, + }; } } diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index 752356e8c4..1b9d1be4f8 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -20,6 +20,8 @@ namespace osu.Game.Screens.Edit private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); + private TimelineArea timelineArea; + [BackgroundDependencyLoader(true)] private void load([CanBeNull] BindableBeatDivisor beatDivisor) { @@ -64,7 +66,7 @@ namespace osu.Game.Screens.Edit { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Right = 5 }, - Child = CreateTimeline() + Child = timelineArea = CreateTimelineArea() }, new BeatDivisorControl(beatDivisor) { RelativeSizeAxes = Axes.Both } }, @@ -97,11 +99,15 @@ namespace osu.Game.Screens.Edit { mainContent.Add(content); content.FadeInFromZero(300, Easing.OutQuint); + + LoadComponentAsync(CreateTimelineContent(), timelineArea.Add); }); } protected abstract Drawable CreateMainContent(); - protected virtual Drawable CreateTimeline() => new TimelineArea { RelativeSizeAxes = Axes.Both }; + protected virtual Drawable CreateTimelineContent() => new Container { }; + + protected TimelineArea CreateTimelineArea() => new TimelineArea { RelativeSizeAxes = Axes.Both }; } } diff --git a/osu.Game/Screens/Edit/IEditorBeatmap.cs b/osu.Game/Screens/Edit/IEditorBeatmap.cs index 2f250ba446..3e3418ef79 100644 --- a/osu.Game/Screens/Edit/IEditorBeatmap.cs +++ b/osu.Game/Screens/Edit/IEditorBeatmap.cs @@ -23,6 +23,11 @@ namespace osu.Game.Screens.Edit /// Invoked when a is removed from this . /// event Action HitObjectRemoved; + + /// + /// Invoked when the start time of a in this was changed. + /// + event Action StartTimeChanged; } /// From e76f8bdd6414542de669ea0301bebf921cf0be06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 23:31:21 +0900 Subject: [PATCH 4301/5608] Fix warnings --- .../Editor/TestSceneEditorComposeTimeline.cs | 16 +++---- .../Timeline/TimelineHitObjectDisplay.cs | 43 ++++++++++++------- .../Screens/Edit/EditorScreenWithTimeline.cs | 2 +- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index b67ea798a0..2b46418659 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -35,20 +35,14 @@ namespace osu.Game.Tests.Visual.Editor typeof(CentreMarker) }; - [Cached(typeof(IEditorBeatmap))] - private readonly EditorBeatmap editorBeatmap; - - public TestSceneEditorComposeTimeline() - { - editorBeatmap = new EditorBeatmap( - (Beatmap) - CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, new Mod[] { }) - ); - } - [BackgroundDependencyLoader] private void load(AudioManager audio) { + var editorBeatmap = new EditorBeatmap( + (Beatmap) + CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, new Mod[] { }) + ); + Beatmap.Value = new WaveformTestBeatmap(audio); Children = new Drawable[] diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs index fc16d29639..337fd9a6b2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs @@ -44,7 +44,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline d.Expire(); } - private void add(HitObject h) => Add(new TimelineHitObjectRepresentation(h)); + private void add(HitObject h) + { + var yOffset = Children.Count(d => d.X == h.StartTime); + + Add(new TimelineHitObjectRepresentation(h) { Y = -yOffset * 4 }); + } private class TimelineHitObjectRepresentation : CompositeDrawable { @@ -52,7 +57,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public TimelineHitObjectRepresentation(HitObject hitObject) { - this.HitObject = hitObject; + HitObject = hitObject; Anchor = Anchor.CentreLeft; Origin = Anchor.CentreLeft; @@ -63,6 +68,25 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline RelativePositionAxes = Axes.X; RelativeSizeAxes = Axes.X; + if (hitObject is IHasEndTime) + { + AddInternal(new Container + { + CornerRadius = 2, + Masking = true, + Size = new Vector2(1, 3), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativePositionAxes = Axes.X, + RelativeSizeAxes = Axes.X, + Colour = Color4.Black, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + } + }); + } + AddInternal(new Circle { Size = new Vector2(16), @@ -71,20 +95,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline RelativePositionAxes = Axes.X, AlwaysPresent = true, Colour = Color4.White, + BorderColour = Color4.Black, + BorderThickness = 3, }); - - if (hitObject is IHasEndTime) - { - AddInternal(new Box - { - Size = new Vector2(1, 5), - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativePositionAxes = Axes.X, - RelativeSizeAxes = Axes.X, - Colour = Color4.White, - }); - } } } } diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index 1b9d1be4f8..aa8d99b517 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -106,7 +106,7 @@ namespace osu.Game.Screens.Edit protected abstract Drawable CreateMainContent(); - protected virtual Drawable CreateTimelineContent() => new Container { }; + protected virtual Drawable CreateTimelineContent() => new Container(); protected TimelineArea CreateTimelineArea() => new TimelineArea { RelativeSizeAxes = Axes.Both }; } From 12a98438353fbec5966e234dad10ab8d7f4a1dc9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 10:48:18 +0900 Subject: [PATCH 4302/5608] Move thickness to a constant --- .../Components/Timeline/TimelineHitObjectDisplay.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs index 337fd9a6b2..7d6d8fd729 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs @@ -48,11 +48,13 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { var yOffset = Children.Count(d => d.X == h.StartTime); - Add(new TimelineHitObjectRepresentation(h) { Y = -yOffset * 4 }); + Add(new TimelineHitObjectRepresentation(h) { Y = -yOffset * TimelineHitObjectRepresentation.THICKNESS }); } private class TimelineHitObjectRepresentation : CompositeDrawable { + public const float THICKNESS = 3; + public readonly HitObject HitObject; public TimelineHitObjectRepresentation(HitObject hitObject) @@ -74,7 +76,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { CornerRadius = 2, Masking = true, - Size = new Vector2(1, 3), + Size = new Vector2(1, THICKNESS), Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, RelativePositionAxes = Axes.X, @@ -96,7 +98,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline AlwaysPresent = true, Colour = Color4.White, BorderColour = Color4.Black, - BorderThickness = 3, + BorderThickness = THICKNESS, }); } } From 28400aa865d4727eb885d50ffe0b0a1a553cff6c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 11:26:50 +0900 Subject: [PATCH 4303/5608] Update test scene --- .../Editor/TestSceneEditorComposeTimeline.cs | 12 ++++-------- .../Compose/Components/Timeline/Timeline.cs | 19 ++++++++----------- .../Components/Timeline/TimelineArea.cs | 4 ++-- .../Timeline/TimelineHitObjectDisplay.cs | 2 ++ .../Screens/Edit/Compose/ComposeScreen.cs | 5 +---- 5 files changed, 17 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index 2b46418659..e618256c03 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -13,9 +13,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Osu; -using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose.Components.Timeline; using osuTK; @@ -38,13 +36,10 @@ namespace osu.Game.Tests.Visual.Editor [BackgroundDependencyLoader] private void load(AudioManager audio) { - var editorBeatmap = new EditorBeatmap( - (Beatmap) - CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, new Mod[] { }) - ); - Beatmap.Value = new WaveformTestBeatmap(audio); + var editorBeatmap = new EditorBeatmap((Beatmap)Beatmap.Value.Beatmap); + Children = new Drawable[] { new FillFlowContainer @@ -60,6 +55,7 @@ namespace osu.Game.Tests.Visual.Editor }, new TimelineArea { + Child = new TimelineHitObjectDisplay(editorBeatmap), Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.X, diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 2a565d028f..b4f3b1f610 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -36,18 +36,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { this.adjustableClock = adjustableClock; - Children = new Drawable[] + Add(waveform = new WaveformGraph { - waveform = new WaveformGraph - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Blue.Opacity(0.2f), - LowColour = colours.BlueLighter, - MidColour = colours.BlueDark, - HighColour = colours.BlueDarker, - Depth = float.MaxValue - }, - }; + RelativeSizeAxes = Axes.Both, + Colour = colours.Blue.Opacity(0.2f), + LowColour = colours.BlueLighter, + MidColour = colours.BlueDark, + HighColour = colours.BlueDarker, + Depth = float.MaxValue + }); // We don't want the centre marker to scroll AddInternal(new CentreMarker()); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 93dac059e3..8909b3d422 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { public class TimelineArea : Container { - private Timeline timeline; + private readonly Timeline timeline = new Timeline { RelativeSizeAxes = Axes.Both }; protected override Container Content => timeline; @@ -111,7 +111,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } }, - timeline = new Timeline { RelativeSizeAxes = Axes.Both } + timeline }, }, ColumnDimensions = new[] diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs index 7d6d8fd729..db4aca75e5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs @@ -20,6 +20,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public TimelineHitObjectDisplay(IEditorBeatmap beatmap) { + RelativeSizeAxes = Axes.Both; + this.beatmap = beatmap; } diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 8511bc3242..cb8f2b2caa 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -35,9 +35,6 @@ namespace osu.Game.Screens.Edit.Compose return new ScreenWhiteBox.UnderConstructionMessage(ruleset == null ? "This beatmap" : $"{ruleset.Description}'s composer"); } - protected override Drawable CreateTimelineContent() => new TimelineHitObjectDisplay(composer.EditorBeatmap) - { - RelativeSizeAxes = Axes.Both, - }; + protected override Drawable CreateTimelineContent() => new TimelineHitObjectDisplay(composer.EditorBeatmap); } } From 23c7132c4fdc452ab2e3b1b7d60fd179f0ea4082 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Dec 2019 11:53:22 +0900 Subject: [PATCH 4304/5608] Add missing license header --- osu.Game/Rulesets/Objects/PathControlPoint.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Objects/PathControlPoint.cs b/osu.Game/Rulesets/Objects/PathControlPoint.cs index d68ef4112b..83436b7a36 100644 --- a/osu.Game/Rulesets/Objects/PathControlPoint.cs +++ b/osu.Game/Rulesets/Objects/PathControlPoint.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using System; using osu.Framework.Bindables; using osu.Game.Rulesets.Objects.Types; From 8be6abf6076224b1a3a5a7aa1490793911ab7426 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Fri, 6 Dec 2019 10:07:16 +0700 Subject: [PATCH 4305/5608] 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; } } From 9f4c8db39508f52fe377d07d58cee38682dc1087 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 12:17:41 +0900 Subject: [PATCH 4306/5608] Add xmldoc --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 368520ba43..9ac967ef74 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -335,6 +335,9 @@ namespace osu.Game.Rulesets.Edit /// public abstract IEnumerable HitObjects { get; } + /// + /// An editor-specific beatmap, exposing mutation events. + /// public IEditorBeatmap EditorBeatmap { get; protected set; } /// From 9248fbe881f81a0d0d0516ad1e770179fb71a5d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 12:22:44 +0900 Subject: [PATCH 4307/5608] Remove extra checkboxes for now --- .../Edit/Compose/Components/Timeline/TimelineArea.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 8909b3d422..02e5db306d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -24,8 +24,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline Masking = true; CornerRadius = 5; - OsuCheckbox hitObjectsCheckbox; - OsuCheckbox hitSoundsCheckbox; OsuCheckbox waveformCheckbox; InternalChildren = new Drawable[] @@ -64,8 +62,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline Spacing = new Vector2(0, 4), Children = new[] { - hitObjectsCheckbox = new OsuCheckbox { LabelText = "Hit objects" }, - hitSoundsCheckbox = new OsuCheckbox { LabelText = "Hit sounds" }, waveformCheckbox = new OsuCheckbox { LabelText = "Waveform" } } } @@ -123,8 +119,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } }; - hitObjectsCheckbox.Current.Value = true; - hitSoundsCheckbox.Current.Value = true; waveformCheckbox.Current.Value = true; timeline.WaveformVisible.BindTo(waveformCheckbox.Current); From 247609388ff71a2321baae9171bd29d364c3b397 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Dec 2019 12:31:22 +0900 Subject: [PATCH 4308/5608] Clean up unused/unnecessary properties --- .../Blueprints/Sliders/Components/PathControlPointPiece.cs | 5 +---- .../Sliders/Components/PathControlPointVisualiser.cs | 7 +------ .../Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs | 2 +- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 2 +- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 159916f16f..4fe02135c4 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -21,7 +21,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public class PathControlPointPiece : BlueprintPiece { public Action RequestSelection; - public Action ControlPointsChanged; public readonly BindableBool IsSelected = new BindableBool(); public readonly int Index; @@ -103,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { markerRing.Alpha = IsSelected.Value ? 1 : 0; - Color4 colour = isSegmentSeparator ? colours.Red : colours.Yellow; + Color4 colour = slider.Path.ControlPoints[Index].Type.Value.HasValue ? colours.Red : colours.Yellow; if (IsHovered || IsSelected.Value) colour = Color4.White; marker.Colour = colour; @@ -176,7 +175,5 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components } protected override bool OnDragEnd(DragEndEvent e) => true; - - private bool isSegmentSeparator => slider.Path.ControlPoints[Index].Type.Value.HasValue; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index c47e4d7d4a..d599ebd893 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -23,8 +23,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler, IHasContextMenu { - public Action ControlPointsChanged; - internal readonly Container Pieces; private readonly Slider slider; private readonly bool allowSelection; @@ -57,10 +55,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components while (slider.Path.ControlPoints.Count > Pieces.Count) { - var piece = new PathControlPointPiece(slider, Pieces.Count) - { - ControlPointsChanged = c => ControlPointsChanged?.Invoke(c), - }; + var piece = new PathControlPointPiece(slider, Pieces.Count); if (allowSelection) piece.RequestSelection = selectPiece; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 62a22dc858..341db249cc 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders bodyPiece = new SliderBodyPiece(), headCirclePiece = new HitCirclePiece(), tailCirclePiece = new HitCirclePiece(), - new PathControlPointVisualiser(HitObject, false) { ControlPointsChanged = _ => updateSlider() }, + new PathControlPointVisualiser(HitObject, false) }; setState(PlacementState.Initial); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index ab52c906e8..8388d78c42 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders BodyPiece = new SliderBodyPiece(), HeadBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.Start), TailBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.End), - ControlPointVisualiser = new PathControlPointVisualiser(sliderObject, true) { ControlPointsChanged = onNewControlPoints }, + ControlPointVisualiser = new PathControlPointVisualiser(sliderObject, true) }; } From b1426d1b22fe9789dd99df497ae2f315b1ac2c2a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 12:51:43 +0900 Subject: [PATCH 4309/5608] Full impossible nullref --- .../Screens/Edit/Compose/ComposeScreen.cs | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index cb8f2b2caa..6984716a2c 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -16,23 +16,20 @@ namespace osu.Game.Screens.Edit.Compose protected override Drawable CreateMainContent() { var ruleset = Beatmap.Value.BeatmapInfo.Ruleset?.CreateInstance(); - composer = ruleset?.CreateHitObjectComposer(); - if (composer != null) - { - var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin); + if (ruleset == null || composer == null) + return new ScreenWhiteBox.UnderConstructionMessage(ruleset == null ? "This beatmap" : $"{ruleset.Description}'s composer"); - // the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation - // full access to all skin sources. - var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider)); + var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin); - // load the skinning hierarchy first. - // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. - return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(composer)); - } + // the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation + // full access to all skin sources. + var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider)); - return new ScreenWhiteBox.UnderConstructionMessage(ruleset == null ? "This beatmap" : $"{ruleset.Description}'s composer"); + // load the skinning hierarchy first. + // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. + return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(composer)); } protected override Drawable CreateTimelineContent() => new TimelineHitObjectDisplay(composer.EditorBeatmap); From a89a23fe08ea1ec85749a665717c94c6d7b7cc9b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Dec 2019 13:08:28 +0900 Subject: [PATCH 4310/5608] Use linq to simplify some expressions --- .../Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 341db249cc..6f53a9e4b1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders case PlacementState.Body: // The given screen-space position may have been externally snapped, but the unsnapped position from the input manager // is used instead since snapping control points doesn't make much sense - HitObject.Path.ControlPoints[HitObject.Path.ControlPoints.Count - 1].Position.Value = ToLocalSpace(inputManager.CurrentState.Mouse.Position) - HitObject.Position; + HitObject.Path.ControlPoints.Last().Position.Value = ToLocalSpace(inputManager.CurrentState.Mouse.Position) - HitObject.Position; break; } } @@ -89,7 +89,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders switch (e.Button) { case MouseButton.Left: - HitObject.Path.ControlPoints.Add(new PathControlPoint { Position = { Value = HitObject.Path.ControlPoints[HitObject.Path.ControlPoints.Count - 1].Position.Value } }); + HitObject.Path.ControlPoints.Add(new PathControlPoint { Position = { Value = HitObject.Path.ControlPoints.Last().Position.Value } }); break; } @@ -108,6 +108,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders protected override bool OnDoubleClick(DoubleClickEvent e) { + // At the point of a double click, there's guaranteed to be at least two points - one from the click, and one from the cursor HitObject.Path.ControlPoints[HitObject.Path.ControlPoints.Count - 2].Type.Value = PathType.Bezier; return true; } From de23364608a8f6568f7bb1c46080c8c6ef6fee60 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 13:47:34 +0900 Subject: [PATCH 4311/5608] Add failing test --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 26 +++++++++++++++++++ osu.Game/Screens/Play/PlayerLoader.cs | 10 ++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 74ae641bfe..5142b98898 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -19,6 +20,7 @@ using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens; @@ -55,6 +57,9 @@ namespace osu.Game.Tests.Visual.Gameplay beforeLoadAction?.Invoke(); Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToClock(Beatmap.Value.Track); + InputManager.Child = container = new TestPlayerLoaderContainer( loader = new TestPlayerLoader(() => { @@ -63,6 +68,25 @@ namespace osu.Game.Tests.Visual.Gameplay })); } + /// + /// When exits early, it has to wait for the player load task + /// to complete before running disposal on player. This previously caused an issue where mod + /// speed adjustments were undone too late, causing cross-screen pollution. + /// + [Test] + public void TestEarlyExit() + { + AddStep("apply mods", () => Mods.Value = new[] { new OsuModNightcore() }); + AddStep("load dummy beatmap", () => ResetPlayer(false)); + AddUntilStep("wait for current", () => loader.IsCurrentScreen()); + AddAssert("mod rate applied", () => Beatmap.Value.Track.Rate != 1); + AddStep("exit loader", () => loader.Exit()); + AddUntilStep("wait for not current", () => !loader.IsCurrentScreen()); + AddAssert("player did not load", () => !player.IsLoaded); + AddUntilStep("player disposed", () => loader.DisposalTask?.IsCompleted == true); + AddAssert("mod rate still applied", () => Beatmap.Value.Track.Rate != 1); + } + [Test] public void TestBlockLoadViaMouseMovement() { @@ -196,6 +220,8 @@ namespace osu.Game.Tests.Visual.Gameplay { public new VisualSettings VisualSettings => base.VisualSettings; + public new Task DisposalTask => base.DisposalTask; + public TestPlayerLoader(Func createPlayer) : base(createPlayer) { diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 87d902b547..774ca02be1 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -55,7 +55,9 @@ namespace osu.Game.Screens.Play protected override bool PlayResumeSound => false; - private Task loadTask; + protected Task LoadTask; + + protected Task DisposalTask; private InputManager inputManager; private IdleTracker idleTracker; @@ -159,7 +161,7 @@ namespace osu.Game.Screens.Play player.RestartCount = restartCount; player.RestartRequested = restartRequested; - loadTask = LoadComponentAsync(player, _ => info.Loading = false); + LoadTask = LoadComponentAsync(player, _ => info.Loading = false); } private void contentIn() @@ -250,7 +252,7 @@ namespace osu.Game.Screens.Play { if (!this.IsCurrentScreen()) return; - loadTask = null; + LoadTask = null; //By default, we want to load the player and never be returned to. //Note that this may change if the player we load requested a re-run. @@ -301,7 +303,7 @@ namespace osu.Game.Screens.Play if (isDisposing) { // if the player never got pushed, we should explicitly dispose it. - loadTask?.ContinueWith(_ => player.Dispose()); + DisposalTask = LoadTask?.ContinueWith(_ => player.Dispose()); } } From 48c6279e8bb9d9544afae76e9cb5d1598b62627b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 13:49:01 +0900 Subject: [PATCH 4312/5608] Only undo adjustments in GameplayClockContainer if applied at least once --- osu.Game/Screens/Play/GameplayClockContainer.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index ff78d85bf0..58c9a6a784 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -214,10 +214,13 @@ namespace osu.Game.Screens.Play base.Update(); } + private bool speedAdjustmentsApplied; + private void updateRate() { if (sourceClock == null) return; + speedAdjustmentsApplied = true; sourceClock.ResetSpeedAdjustments(); if (sourceClock is IHasTempoAdjust tempo) @@ -239,7 +242,12 @@ namespace osu.Game.Screens.Play private void removeSourceClockAdjustments() { - sourceClock.ResetSpeedAdjustments(); + if (speedAdjustmentsApplied) + { + sourceClock.ResetSpeedAdjustments(); + speedAdjustmentsApplied = false; + } + (sourceClock as IAdjustableAudioComponent)?.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); } } From 21ceb7f85dbbffb771c443f394a98385a3b75b87 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 14:40:45 +0900 Subject: [PATCH 4313/5608] Always display skins at native sizes for now --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs | 4 +++- osu.Game/Skinning/SkinnableDrawable.cs | 4 ++-- osu.Game/Skinning/SkinnableSprite.cs | 2 +- osu.Game/Skinning/SkinnableSpriteText.cs | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 479c250eab..ec9792d59d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -49,7 +49,9 @@ namespace osu.Game.Rulesets.Osu.Skinning return this.GetAnimation(component.LookupName, true, false); case OsuSkinComponents.SliderFollowCircle: - return this.GetAnimation("sliderfollowcircle", true, true); + var followCircle = this.GetAnimation("sliderfollowcircle", true, true); + followCircle.Scale *= 0.5f; + return followCircle; case OsuSkinComponents.SliderBall: var sliderBallContent = this.GetAnimation("sliderb", true, true, ""); diff --git a/osu.Game/Skinning/SkinnableDrawable.cs b/osu.Game/Skinning/SkinnableDrawable.cs index 9ca5d60cb0..fda031e6cb 100644 --- a/osu.Game/Skinning/SkinnableDrawable.cs +++ b/osu.Game/Skinning/SkinnableDrawable.cs @@ -29,13 +29,13 @@ namespace osu.Game.Skinning /// A function to create the default skin implementation of this element. /// A conditional to decide whether to allow fallback to the default implementation if a skinned element is not present. /// How (if at all) the should be resize to fit within our own bounds. - public SkinnableDrawable(ISkinComponent component, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + public SkinnableDrawable(ISkinComponent component, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.NoScaling) : this(component, allowFallback, confineMode) { createDefault = defaultImplementation; } - protected SkinnableDrawable(ISkinComponent component, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + protected SkinnableDrawable(ISkinComponent component, Func allowFallback = null, ConfineMode confineMode = ConfineMode.NoScaling) : base(allowFallback) { this.component = component; diff --git a/osu.Game/Skinning/SkinnableSprite.cs b/osu.Game/Skinning/SkinnableSprite.cs index e225bfc490..5352928ec6 100644 --- a/osu.Game/Skinning/SkinnableSprite.cs +++ b/osu.Game/Skinning/SkinnableSprite.cs @@ -19,7 +19,7 @@ namespace osu.Game.Skinning [Resolved] private TextureStore textures { get; set; } - public SkinnableSprite(string textureName, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + public SkinnableSprite(string textureName, Func allowFallback = null, ConfineMode confineMode = ConfineMode.NoScaling) : base(new SpriteComponent(textureName), allowFallback, confineMode) { } diff --git a/osu.Game/Skinning/SkinnableSpriteText.cs b/osu.Game/Skinning/SkinnableSpriteText.cs index e72f9c9811..567dd348e1 100644 --- a/osu.Game/Skinning/SkinnableSpriteText.cs +++ b/osu.Game/Skinning/SkinnableSpriteText.cs @@ -8,7 +8,7 @@ namespace osu.Game.Skinning { public class SkinnableSpriteText : SkinnableDrawable, IHasText { - public SkinnableSpriteText(ISkinComponent component, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + public SkinnableSpriteText(ISkinComponent component, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.NoScaling) : base(component, defaultImplementation, allowFallback, confineMode) { } From 27dd12a66d885d12b74ddc1a5e0ead595b2f0d30 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Dec 2019 15:06:31 +0900 Subject: [PATCH 4314/5608] Rewrite slider length calculation for readability --- osu.Game/Rulesets/Objects/SliderPath.cs | 63 +++++++++++++------------ 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 6ad5d2f1c3..6c24ee6878 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -40,6 +40,7 @@ namespace osu.Game.Rulesets.Objects private readonly List calculatedPath = new List(); private readonly List cumulativeLength = new List(); + private double calculatedLength; /// /// Creates a new . @@ -158,7 +159,7 @@ namespace osu.Game.Rulesets.Objects return; calculatePath(); - calculateCumulativeLength(); + calculateLength(); pathCache.Validate(); } @@ -227,46 +228,48 @@ namespace osu.Game.Rulesets.Objects } } - private void calculateCumulativeLength() + private void calculateLength() { - double l = 0; - + calculatedLength = 0; cumulativeLength.Clear(); - cumulativeLength.Add(l); + cumulativeLength.Add(0); - double? expectedDistance = ExpectedDistance.Value; - - for (int i = 0; i < calculatedPath.Count - 1; ++i) + for (int i = 0; i < calculatedPath.Count - 1; i++) { Vector2 diff = calculatedPath[i + 1] - calculatedPath[i]; - double d = diff.Length; - - // Shorted slider paths that are too long compared to the expected distance - if (expectedDistance.HasValue && expectedDistance - l < d) - { - calculatedPath[i + 1] = calculatedPath[i] + diff * (float)((expectedDistance - l) / d); - calculatedPath.RemoveRange(i + 2, calculatedPath.Count - 2 - i); - - l = expectedDistance.Value; - cumulativeLength.Add(l); - break; - } - - l += d; - cumulativeLength.Add(l); + calculatedLength += diff.Length; + cumulativeLength.Add(calculatedLength); } - // Lengthen slider paths that are too short compared to the expected distance - if (expectedDistance.HasValue && l < expectedDistance && calculatedPath.Count > 1) + if (ExpectedDistance.Value is double expectedDistance && calculatedLength != expectedDistance) { - Vector2 diff = calculatedPath[calculatedPath.Count - 1] - calculatedPath[calculatedPath.Count - 2]; - double d = diff.Length; + // The last length is always incorrect + cumulativeLength.RemoveAt(cumulativeLength.Count - 1); - if (d <= 0) + int pathEndIndex = calculatedPath.Count - 1; + + if (calculatedLength > expectedDistance) + { + // The path will be shortened further, in which case we should trim any more unnecessary lengths and their associated path segments + while (cumulativeLength.Count > 0 && cumulativeLength[cumulativeLength.Count - 1] > expectedDistance) + { + cumulativeLength.RemoveAt(cumulativeLength.Count - 1); + calculatedPath.RemoveAt(pathEndIndex--); + } + } + + if (pathEndIndex <= 0) + { + // The expected distance is negative or zero + // TODO: Perhaps negative path lengths should be disallowed altogether return; + } - calculatedPath[calculatedPath.Count - 1] += diff * (float)((expectedDistance - l) / d); - cumulativeLength[calculatedPath.Count - 1] = expectedDistance.Value; + // The direction of the segment to shorten or lengthen + Vector2 dir = (calculatedPath[pathEndIndex] - calculatedPath[pathEndIndex - 1]).Normalized(); + + calculatedPath[pathEndIndex] = calculatedPath[pathEndIndex - 1] + dir * (float)(expectedDistance - cumulativeLength[cumulativeLength.Count - 1]); + cumulativeLength.Add(expectedDistance); } } From 12f1c9e088c307ac86a1411fd7e80d6feba7fefd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 15:29:02 +0900 Subject: [PATCH 4315/5608] Fix test failure --- osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 5142b98898..dbea8d28a6 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -76,8 +76,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestEarlyExit() { - AddStep("apply mods", () => Mods.Value = new[] { new OsuModNightcore() }); - AddStep("load dummy beatmap", () => ResetPlayer(false)); + AddStep("load dummy beatmap", () => ResetPlayer(false, () => Mods.Value = new[] { new OsuModNightcore() })); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddAssert("mod rate applied", () => Beatmap.Value.Track.Rate != 1); AddStep("exit loader", () => loader.Exit()); From 2654710d917e47b44f80f38d3600203d14355a0c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Dec 2019 15:37:00 +0900 Subject: [PATCH 4316/5608] Add tests and fix negative expected distances --- .../Visual/Gameplay/TestSceneSliderPath.cs | 34 +++++++++++++++++++ osu.Game/Rulesets/Objects/SliderPath.cs | 1 + 2 files changed, 35 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs index fe2cc188a5..27d39d0f17 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs @@ -146,7 +146,41 @@ namespace osu.Game.Tests.Visual.Gameplay break; } }); + } + [Test] + public void TestLengthenLastSegment() + { + AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); + AddStep("lengthen last segment", () => path.ExpectedDistance.Value = 300); + } + + [Test] + public void TestShortenLastSegment() + { + AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); + AddStep("shorten last segment", () => path.ExpectedDistance.Value = 150); + } + + [Test] + public void TestShortenFirstSegment() + { + AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); + AddStep("shorten first segment", () => path.ExpectedDistance.Value = 50); + } + + [Test] + public void TestShortenToZeroLength() + { + AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); + AddStep("shorten to 0 length", () => path.ExpectedDistance.Value = 0); + } + + [Test] + public void TestShortenToNegativeLength() + { + AddStep("create path", () => path.ControlPoints.AddRange(createSegment(PathType.Linear, Vector2.Zero, new Vector2(0, 100), new Vector2(100)))); + AddStep("shorten to -10 length", () => path.ExpectedDistance.Value = -10); } private List createSegment(PathType type, params Vector2[] controlPoints) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 6c24ee6878..095353e3f3 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -262,6 +262,7 @@ namespace osu.Game.Rulesets.Objects { // The expected distance is negative or zero // TODO: Perhaps negative path lengths should be disallowed altogether + cumulativeLength.Add(0); return; } From af35df4077015c5b45ebb5b8f304e9bdc58702f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 15:42:11 +0900 Subject: [PATCH 4317/5608] Add multiple mod testing and update test code style --- .../TestSceneModCustomizationSettings.cs | 56 +++++++++++-------- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 +- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs index 83d77cccdb..f789e60252 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.UserInterface Anchor = Anchor.BottomCentre, }); - var testMod = new TestModCustomizable(); + var testMod = new TestModCustomizable1(); AddStep("open", modSelect.Show); AddAssert("button disabled", () => !modSelect.CustomizeButton.Enabled.Value); @@ -44,64 +44,74 @@ namespace osu.Game.Tests.Visual.UserInterface public new TriangleButton CustomizeButton => base.CustomizeButton; public void SelectMod(Mod mod) => - ModSectionsContainer.Children.Single((s) => s.ModType == mod.Type) - .ButtonsContainer.OfType().Single(b => b.Mods.Any(m => m.GetType() == mod.GetType())).SelectNext(1); + ModSectionsContainer.Children.Single(s => s.ModType == mod.Type) + .ButtonsContainer.OfType().Single(b => b.Mods.Any(m => m.GetType() == mod.GetType())).SelectNext(1); public ModControlSection GetControlSection(Mod mod) => - ModSettingsContent.Children.FirstOrDefault((s) => s.Mod == mod); + ModSettingsContent.Children.FirstOrDefault(s => s.Mod == mod); protected override void LoadComplete() { base.LoadComplete(); foreach (var section in ModSectionsContainer) + { if (section.ModType == ModType.Conversion) - section.Mods = new Mod[] { new TestModCustomizable() }; + { + section.Mods = new Mod[] + { + new TestModCustomizable1(), + new TestModCustomizable2() + }; + } else section.Mods = new Mod[] { }; + } } } - private class TestModCustomizable : Mod, IModHasSettings + private class TestModCustomizable1 : TestModCustomizable { - public override string Name => "Customizable Mod"; + public override string Name => "Customizable Mod 1"; - public override string Acronym => "CM"; + public override string Acronym => "CM1"; + } + private class TestModCustomizable2 : TestModCustomizable + { + public override string Name => "Customizable Mod 2"; + + public override string Acronym => "CM2"; + } + + private abstract class TestModCustomizable : Mod, IModHasSettings + { public override double ScoreMultiplier => 1.0; public override ModType Type => ModType.Conversion; - public readonly BindableFloat sliderBindable = new BindableFloat + public readonly BindableFloat SliderBindable = new BindableFloat { MinValue = 0, MaxValue = 10, }; - public readonly BindableBool tickBindable = new BindableBool(); + public readonly BindableBool TickBindable = new BindableBool(); - public Drawable[] CreateControls() - { - BindableFloat sliderControl = new BindableFloat(); - BindableBool tickControl = new BindableBool(); - - sliderControl.BindTo(sliderBindable); - tickControl.BindTo(tickBindable); - - return new Drawable[] + public Drawable[] CreateControls() => + new Drawable[] { new SettingsSlider { LabelText = "Slider", - Bindable = sliderControl + Bindable = SliderBindable }, new SettingsCheckbox { LabelText = "Checkbox", - Bindable = tickControl + Bindable = TickBindable } }; - } } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index fc5ed1b3f3..d7d1135e81 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -345,7 +345,7 @@ namespace osu.Game.Overlays.Mods if (added is IModHasSettings) ModSettingsContent.Add(new ModControlSection(added)); else if (removed is IModHasSettings) - ModSettingsContent.Remove(ModSettingsContent.Children.Where(section => section.Mod == removed).Single()); + ModSettingsContent.Remove(ModSettingsContent.Children.Single(section => section.Mod == removed)); CustomizeButton.Enabled.Value = ModSettingsContent.Children.Count > 0; From 3358ab9f8abde79becfd4bca2a56361170aef2e1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Dec 2019 15:53:01 +0900 Subject: [PATCH 4318/5608] Adjust diffcalc test expected value The difference is caused by the reworked calculateLength() of SliderPath. This comes as a result of the increased accuracy of path lengthenings due to calculating the final position relative to the second-to-last point, rather than relative to the last point. --- osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs index 693faee3b7..85a41137d4 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Tests { protected override string ResourceAssembly => "osu.Game.Rulesets.Osu"; - [TestCase(6.931145117263422, "diffcalc-test")] + [TestCase(6.9311451172608853d, "diffcalc-test")] [TestCase(1.0736587013228804d, "zero-length-sliders")] public void Test(double expected, string name) => base.Test(expected, name); From b4e1b5fa983fdb826ec8693b3fabdcd66e03e2c1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Dec 2019 15:53:19 +0900 Subject: [PATCH 4319/5608] Explose + use the full calculated length of the path --- .../Blueprints/Sliders/SliderPlacementBlueprint.cs | 3 +-- .../Blueprints/Sliders/SliderSelectionBlueprint.cs | 3 +-- osu.Game/Rulesets/Objects/SliderPath.cs | 14 +++++++++++++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 6f53a9e4b1..bbdc43e16f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -133,8 +133,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private void updateSlider() { - HitObject.Path.ExpectedDistance.Value = null; - HitObject.Path.ExpectedDistance.Value = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)HitObject.Path.Distance) ?? (float)HitObject.Path.Distance; + HitObject.Path.ExpectedDistance.Value = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)HitObject.Path.CalculatedDistance) ?? (float)HitObject.Path.CalculatedDistance; bodyPiece.UpdateFrom(HitObject); headCirclePiece.UpdateFrom(HitObject.HeadCircle); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 8388d78c42..7b3ca29e35 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -114,8 +114,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private void onNewControlPoints(Vector2[] controlPoints) { - HitObject.Path.ExpectedDistance.Value = null; - HitObject.Path.ExpectedDistance.Value = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)HitObject.Path.Distance) ?? (float)HitObject.Path.Distance; + HitObject.Path.ExpectedDistance.Value = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)HitObject.Path.CalculatedDistance) ?? (float)HitObject.Path.CalculatedDistance; UpdateHitObject(); } diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 095353e3f3..f6e7c40e12 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -103,6 +103,18 @@ namespace osu.Game.Rulesets.Objects } } + /// + /// The distance of the path prior to lengthening/shortening to account for . + /// + public double CalculatedDistance + { + get + { + ensureValid(); + return calculatedLength; + } + } + /// /// Computes the slider path until a given progress that ranges from 0 (beginning of the slider) /// to 1 (end of the slider) and stores the generated path in the given list. @@ -251,7 +263,7 @@ namespace osu.Game.Rulesets.Objects if (calculatedLength > expectedDistance) { // The path will be shortened further, in which case we should trim any more unnecessary lengths and their associated path segments - while (cumulativeLength.Count > 0 && cumulativeLength[cumulativeLength.Count - 1] > expectedDistance) + while (cumulativeLength.Count > 0 && cumulativeLength[cumulativeLength.Count - 1] >= expectedDistance) { cumulativeLength.RemoveAt(cumulativeLength.Count - 1); calculatedPath.RemoveAt(pathEndIndex--); From d29ccdc25e4ea515c54a3de945fd9724271bf3e7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Dec 2019 16:36:08 +0900 Subject: [PATCH 4320/5608] Fix selection blueprint not re-snapping the path --- .../Blueprints/Sliders/SliderSelectionBlueprint.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 7b3ca29e35..9a504445f4 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.UserInterface; @@ -44,6 +45,16 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders }; } + private IBindable pathVersion; + + protected override void LoadComplete() + { + base.LoadComplete(); + + pathVersion = HitObject.Path.Version.GetBoundCopy(); + pathVersion.BindValueChanged(_ => updatePath()); + } + protected override void Update() { base.Update(); @@ -112,10 +123,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders return insertionIndex; } - private void onNewControlPoints(Vector2[] controlPoints) + private void updatePath() { HitObject.Path.ExpectedDistance.Value = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)HitObject.Path.CalculatedDistance) ?? (float)HitObject.Path.CalculatedDistance; - UpdateHitObject(); } From 2b5f9515de1b8fe386a76e6f2c1398912005dd5c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Dec 2019 17:03:54 +0900 Subject: [PATCH 4321/5608] Fix multiple control point deletions --- .../Components/PathControlPointVisualiser.cs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index d599ebd893..cbc2a20328 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -14,6 +14,7 @@ using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose; using osuTK; @@ -100,21 +101,15 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private bool deleteSelected() { - int countDeleted = 0; - - foreach (var piece in Pieces) - { - if (piece.IsSelected.Value) - { - slider.Path.ControlPoints.RemoveAt(piece.Index); - countDeleted++; - } - } + List toRemove = Pieces.Where(p => p.IsSelected.Value).Select(p => p.Index).Select(i => slider.Path.ControlPoints[i]).ToList(); // Ensure that there are any points to be deleted - if (countDeleted == 0) + if (toRemove.Count == 0) return false; + foreach (var c in toRemove) + slider.Path.ControlPoints.Remove(c); + // If there are 0 remaining control points, treat the slider as being deleted if (slider.Path.ControlPoints.Count == 0) { From 23e47530c50a38bd42874f85ec4c698b967f9e86 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 17:09:24 +0900 Subject: [PATCH 4322/5608] Add a method for getting settings UI components automatically from a target class --- .../Configuration/SettingSourceAttribute.cs | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 osu.Game/Configuration/SettingSourceAttribute.cs diff --git a/osu.Game/Configuration/SettingSourceAttribute.cs b/osu.Game/Configuration/SettingSourceAttribute.cs new file mode 100644 index 0000000000..fe582b1461 --- /dev/null +++ b/osu.Game/Configuration/SettingSourceAttribute.cs @@ -0,0 +1,85 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using JetBrains.Annotations; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Overlays.Settings; + +namespace osu.Game.Configuration +{ + /// + /// An attribute to mark a bindable as being exposed to the user via settings controls. + /// Can be used in conjunction with to automatically create UI controls. + /// + [MeansImplicitUse] + [AttributeUsage(AttributeTargets.Property)] + public class SettingSourceAttribute : Attribute + { + public string Label { get; } + + public string Description { get; } + + public SettingSourceAttribute(string label, string description = null) + { + Label = label ?? string.Empty; + Description = description ?? string.Empty; + } + } + + public static class SettingSourceExtensions + { + public static IEnumerable CreateSettingsControls(this object obj) + { + var configProperties = obj.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance).Where(p => p.GetCustomAttribute(true) != null); + + foreach (var property in configProperties) + { + var attr = property.GetCustomAttribute(true); + + switch (property.GetValue(obj)) + { + case BindableNumber bNumber: + yield return new SettingsSlider + { + LabelText = attr.Label, + Bindable = bNumber + }; + + break; + + case BindableNumber bNumber: + yield return new SettingsSlider + { + LabelText = attr.Label, + Bindable = bNumber + }; + + break; + + case BindableNumber bNumber: + yield return new SettingsSlider + { + LabelText = attr.Label, + Bindable = bNumber + }; + + break; + + case Bindable bBool: + yield return new SettingsCheckbox + { + LabelText = attr.Label, + Bindable = bBool + }; + + break; + } + } + } + } +} From a5d5099868f2c7d1a8672dc266030065366592c2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 17:09:48 +0900 Subject: [PATCH 4323/5608] Use SettingsSource for mod cusomisation --- .../TestSceneModCustomizationSettings.cs | 30 +++++-------------- osu.Game/Overlays/Mods/ModControlSection.cs | 6 ++-- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 24 ++++++++------- osu.Game/Rulesets/Mods/IModHasSettings.cs | 15 ---------- 4 files changed, 25 insertions(+), 50 deletions(-) delete mode 100644 osu.Game/Rulesets/Mods/IModHasSettings.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs index f789e60252..8227fe8f7a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs @@ -6,9 +6,9 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods; -using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Mods; namespace osu.Game.Tests.Visual.UserInterface @@ -47,9 +47,6 @@ namespace osu.Game.Tests.Visual.UserInterface ModSectionsContainer.Children.Single(s => s.ModType == mod.Type) .ButtonsContainer.OfType().Single(b => b.Mods.Any(m => m.GetType() == mod.GetType())).SelectNext(1); - public ModControlSection GetControlSection(Mod mod) => - ModSettingsContent.Children.FirstOrDefault(s => s.Mod == mod); - protected override void LoadComplete() { base.LoadComplete(); @@ -84,34 +81,23 @@ namespace osu.Game.Tests.Visual.UserInterface public override string Acronym => "CM2"; } - private abstract class TestModCustomizable : Mod, IModHasSettings + private abstract class TestModCustomizable : Mod, IApplicableMod { public override double ScoreMultiplier => 1.0; public override ModType Type => ModType.Conversion; - public readonly BindableFloat SliderBindable = new BindableFloat + [SettingSource("Sample float", "Change something for a mod")] + public BindableFloat SliderBindable { get; } = new BindableFloat { MinValue = 0, MaxValue = 10, + Default = 5, + Value = 7 }; - public readonly BindableBool TickBindable = new BindableBool(); - - public Drawable[] CreateControls() => - new Drawable[] - { - new SettingsSlider - { - LabelText = "Slider", - Bindable = SliderBindable - }, - new SettingsCheckbox - { - LabelText = "Checkbox", - Bindable = TickBindable - } - }; + [SettingSource("Sample bool", "Clicking this changes a setting")] + public BindableBool TickBindable { get; } = new BindableBool(); } } } diff --git a/osu.Game/Overlays/Mods/ModControlSection.cs b/osu.Game/Overlays/Mods/ModControlSection.cs index df6f4d15b0..f4b588ddb3 100644 --- a/osu.Game/Overlays/Mods/ModControlSection.cs +++ b/osu.Game/Overlays/Mods/ModControlSection.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Mods; @@ -34,8 +35,7 @@ namespace osu.Game.Overlays.Mods RelativeSizeAxes = Axes.X, }; - if (Mod is IModHasSettings modHasSettings) - AddRange(modHasSettings.CreateControls()); + AddRange(Mod.CreateSettingsControls()); } [BackgroundDependencyLoader] @@ -53,4 +53,4 @@ namespace osu.Game.Overlays.Mods }); } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index d7d1135e81..cfad0126eb 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; @@ -236,6 +237,7 @@ namespace osu.Game.Overlays.Mods Width = 180, Text = "Customization", Action = () => ModSettingsContainer.Alpha = ModSettingsContainer.Alpha == 1 ? 0 : 1, + Enabled = { Value = false }, Margin = new MarginPadding { Right = 20 @@ -331,7 +333,6 @@ namespace osu.Game.Overlays.Mods SelectedMods.ValueChanged += updateModSettings; Ruleset.ValueChanged += _ => ModSettingsContent.Clear(); - CustomizeButton.Enabled.Value = false; sampleOn = audio.Samples.Get(@"UI/check-on"); sampleOff = audio.Samples.Get(@"UI/check-off"); @@ -339,18 +340,21 @@ namespace osu.Game.Overlays.Mods private void updateModSettings(ValueChangedEvent> selectedMods) { - var added = selectedMods.NewValue.Except(selectedMods.OldValue).FirstOrDefault(); - var removed = selectedMods.OldValue.Except(selectedMods.NewValue).FirstOrDefault(); + foreach (var added in selectedMods.NewValue.Except(selectedMods.OldValue)) + { + var controls = added.CreateSettingsControls().ToList(); + if (controls.Count > 0) + ModSettingsContent.Add(new ModControlSection(added) { Children = controls }); + } - if (added is IModHasSettings) - ModSettingsContent.Add(new ModControlSection(added)); - else if (removed is IModHasSettings) - ModSettingsContent.Remove(ModSettingsContent.Children.Single(section => section.Mod == removed)); + foreach (var removed in selectedMods.OldValue.Except(selectedMods.NewValue)) + ModSettingsContent.RemoveAll(section => section.Mod == removed); - CustomizeButton.Enabled.Value = ModSettingsContent.Children.Count > 0; + bool hasSettings = ModSettingsContent.Children.Count > 0; + CustomizeButton.Enabled.Value = hasSettings; - if (ModSettingsContainer.Alpha == 1 && ModSettingsContent.Children.Count == 0) - ModSettingsContainer.Alpha = 0; + if (!hasSettings) + ModSettingsContainer.Hide(); } public void DeselectAll() diff --git a/osu.Game/Rulesets/Mods/IModHasSettings.cs b/osu.Game/Rulesets/Mods/IModHasSettings.cs deleted file mode 100644 index b5058de82b..0000000000 --- a/osu.Game/Rulesets/Mods/IModHasSettings.cs +++ /dev/null @@ -1,15 +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; - -namespace osu.Game.Rulesets.Mods -{ - /// - /// An interface for mods that allows user control over it's properties. - /// - public interface IModHasSettings : IApplicableMod - { - Drawable[] CreateControls(); - } -} From 9de032e35f1394571e3fcc05b4caa94a81b3e27d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 17:10:06 +0900 Subject: [PATCH 4324/5608] Fix SettingsItem bindable logic --- osu.Game/Overlays/Settings/SettingsItem.cs | 29 ++++++++-------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 8863e43cca..212ef5545d 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -53,27 +53,10 @@ namespace osu.Game.Overlays.Settings } } - // hold a reference to the provided bindable so we don't have to in every settings section. - private Bindable bindable; - public virtual Bindable Bindable { - get => bindable; - - set - { - if (bindable != null) - controlWithCurrent?.Current.UnbindFrom(bindable); - - bindable = value; - controlWithCurrent?.Current.BindTo(bindable); - - if (ShowsDefaultIndicator) - { - restoreDefaultButton.Bindable = bindable.GetBoundCopy(); - restoreDefaultButton.Bindable.TriggerChange(); - } - } + get => controlWithCurrent.Current; + set => controlWithCurrent.Current = value; } public virtual IEnumerable FilterTerms => Keywords == null ? new[] { LabelText } : new List(Keywords) { LabelText }.ToArray(); @@ -110,7 +93,15 @@ namespace osu.Game.Overlays.Settings private void load() { if (controlWithCurrent != null) + { controlWithCurrent.Current.DisabledChanged += disabled => { Colour = disabled ? Color4.Gray : Color4.White; }; + + if (ShowsDefaultIndicator) + { + restoreDefaultButton.Bindable = controlWithCurrent.Current; + restoreDefaultButton.Bindable.TriggerChange(); + } + } } private class RestoreDefaultValueButton : Container, IHasTooltip From 901eb5d99639edc7a21caa1f2c7577507415e42a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 18:03:50 +0900 Subject: [PATCH 4325/5608] Fix incorrect trigger logic --- osu.Game/Overlays/Settings/SettingsItem.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 212ef5545d..9c390c34ec 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -97,10 +97,7 @@ namespace osu.Game.Overlays.Settings controlWithCurrent.Current.DisabledChanged += disabled => { Colour = disabled ? Color4.Gray : Color4.White; }; if (ShowsDefaultIndicator) - { restoreDefaultButton.Bindable = controlWithCurrent.Current; - restoreDefaultButton.Bindable.TriggerChange(); - } } } @@ -116,6 +113,7 @@ namespace osu.Game.Overlays.Settings bindable = value; bindable.ValueChanged += _ => UpdateState(); bindable.DisabledChanged += _ => UpdateState(); + UpdateState(); } } From ed6d1ccd958622bbca51c8cab54f0c3dfd4a6296 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 17:09:24 +0900 Subject: [PATCH 4326/5608] Add a method for getting settings UI components automatically from a target class --- .../Configuration/SettingSourceAttribute.cs | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 osu.Game/Configuration/SettingSourceAttribute.cs diff --git a/osu.Game/Configuration/SettingSourceAttribute.cs b/osu.Game/Configuration/SettingSourceAttribute.cs new file mode 100644 index 0000000000..fe582b1461 --- /dev/null +++ b/osu.Game/Configuration/SettingSourceAttribute.cs @@ -0,0 +1,85 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using JetBrains.Annotations; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Overlays.Settings; + +namespace osu.Game.Configuration +{ + /// + /// An attribute to mark a bindable as being exposed to the user via settings controls. + /// Can be used in conjunction with to automatically create UI controls. + /// + [MeansImplicitUse] + [AttributeUsage(AttributeTargets.Property)] + public class SettingSourceAttribute : Attribute + { + public string Label { get; } + + public string Description { get; } + + public SettingSourceAttribute(string label, string description = null) + { + Label = label ?? string.Empty; + Description = description ?? string.Empty; + } + } + + public static class SettingSourceExtensions + { + public static IEnumerable CreateSettingsControls(this object obj) + { + var configProperties = obj.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance).Where(p => p.GetCustomAttribute(true) != null); + + foreach (var property in configProperties) + { + var attr = property.GetCustomAttribute(true); + + switch (property.GetValue(obj)) + { + case BindableNumber bNumber: + yield return new SettingsSlider + { + LabelText = attr.Label, + Bindable = bNumber + }; + + break; + + case BindableNumber bNumber: + yield return new SettingsSlider + { + LabelText = attr.Label, + Bindable = bNumber + }; + + break; + + case BindableNumber bNumber: + yield return new SettingsSlider + { + LabelText = attr.Label, + Bindable = bNumber + }; + + break; + + case Bindable bBool: + yield return new SettingsCheckbox + { + LabelText = attr.Label, + Bindable = bBool + }; + + break; + } + } + } + } +} From 2fa0b30fa27801b00927b49025134cf8c8ee8ce1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 17:49:41 +0900 Subject: [PATCH 4327/5608] Add textbox and dropdown support --- .../Configuration/SettingSourceAttribute.cs | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/osu.Game/Configuration/SettingSourceAttribute.cs b/osu.Game/Configuration/SettingSourceAttribute.cs index fe582b1461..dceef1cb7d 100644 --- a/osu.Game/Configuration/SettingSourceAttribute.cs +++ b/osu.Game/Configuration/SettingSourceAttribute.cs @@ -8,6 +8,7 @@ using System.Reflection; using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; using osu.Game.Overlays.Settings; namespace osu.Game.Configuration @@ -40,8 +41,9 @@ namespace osu.Game.Configuration foreach (var property in configProperties) { var attr = property.GetCustomAttribute(true); + var prop = property.GetValue(obj); - switch (property.GetValue(obj)) + switch (prop) { case BindableNumber bNumber: yield return new SettingsSlider @@ -78,6 +80,30 @@ namespace osu.Game.Configuration }; break; + + case Bindable bString: + yield return new SettingsTextBox + { + LabelText = attr.Label, + Bindable = bString + }; + + break; + + case IBindable bindable: + + var dropdownType = typeof(SettingsEnumDropdown<>).MakeGenericType(bindable.GetType().GetGenericArguments()[0]); + + var dropdown = (Drawable)Activator.CreateInstance(dropdownType); + + dropdown.GetType().GetProperty(nameof(IHasCurrentValue.Current))?.SetValue(dropdown, obj); + + yield return dropdown; + + break; + + default: + throw new InvalidOperationException($"{nameof(SettingSourceAttribute)} was attached to an unsupported type ({prop})"); } } } From f84705ab9605776f579f745ac6164b856bf5903e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 17:49:52 +0900 Subject: [PATCH 4328/5608] Add tests --- .../Settings/TestSceneSettingsSource.cs | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs new file mode 100644 index 0000000000..e3dae9c27e --- /dev/null +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs @@ -0,0 +1,65 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Configuration; +using osuTK; + +namespace osu.Game.Tests.Visual.Settings +{ + [TestFixture] + public class TestSceneSettingsSource : OsuTestScene + { + public TestSceneSettingsSource() + { + Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(20), + Width = 0.5f, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Padding = new MarginPadding(50), + ChildrenEnumerable = new TestTargetClass().CreateSettingsControls() + }, + }; + } + + private class TestTargetClass + { + [SettingSource("Sample bool", "Clicking this changes a setting")] + public BindableBool TickBindable { get; } = new BindableBool(); + + [SettingSource("Sample float", "Change something for a mod")] + public BindableFloat SliderBindable { get; } = new BindableFloat + { + MinValue = 0, + MaxValue = 10, + Default = 5, + Value = 7 + }; + + [SettingSource("Sample enum", "Change something for a mod")] + public Bindable EnumBindable { get; } = new Bindable + { + Default = TestEnum.Value1, + Value = TestEnum.Value2 + }; + + [SettingSource("Sample string", "Change something for a mod")] + public Bindable StringBindable { get; } = new Bindable(); + } + + private enum TestEnum + { + Value1, + Value2 + } + } +} From 16f8341a0228ebb5fb92c8070918537b980352cb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Dec 2019 18:49:01 +0900 Subject: [PATCH 4329/5608] Handle control point positional updates within SliderPath --- .../Components/PathControlPointVisualiser.cs | 8 -------- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 ++ osu.Game/Rulesets/Objects/SliderPath.cs | 20 +++++++++++++++++++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index cbc2a20328..974b611533 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -117,14 +117,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return true; } - // Make control points relative - Vector2 first = slider.Path.ControlPoints[0].Position.Value; - for (int i = 0; i < slider.Path.ControlPoints.Count; i++) - slider.Path.ControlPoints[i].Position.Value = slider.Path.ControlPoints[i].Position.Value - first; - - // The slider's position defines the position of the first control point, and all further control points are relative to that point - slider.Position += first; - // Since pieces are re-used, they will not point to the deleted control points while remaining selected foreach (var piece in Pieces) piece.IsSelected.Value = false; diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index b68595c67e..09657b2d47 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -100,6 +100,8 @@ namespace osu.Game.Rulesets.Osu.Objects { SamplesBindable.ItemsAdded += _ => updateNestedSamples(); SamplesBindable.ItemsRemoved += _ => updateNestedSamples(); + + Path.OffsetChanged += offset => Position += offset; } protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index f6e7c40e12..969cdcc463 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -16,6 +16,12 @@ namespace osu.Game.Rulesets.Objects { public class SliderPath { + /// + /// Invoked when the offset of the path changes. + /// The provided value indicates the offset, and should be used to re-calculate the position of the containing drawable. + /// + public event Action OffsetChanged; + /// /// The current version of this . Updated when any change to the path occurs. /// @@ -62,6 +68,20 @@ namespace osu.Game.Rulesets.Objects foreach (var c in items) c.Changed -= invalidate; + // Make all control points relative to the first one + if (ControlPoints.Count > 0) + { + Vector2 first = ControlPoints[0].Position.Value; + + if (first != Vector2.Zero) + { + foreach (var c in ControlPoints) + c.Position.Value -= first; + + OffsetChanged?.Invoke(first); + } + } + invalidate(); }; } From 52dd7bf716fa277fc157397a2cdcebe0c134e180 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Dec 2019 18:49:14 +0900 Subject: [PATCH 4330/5608] Fix deleting the first control point not working --- .../Sliders/Components/PathControlPointVisualiser.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 974b611533..ee4a37a4f2 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -108,7 +108,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return false; foreach (var c in toRemove) + { + // The first control point in the slider must have a type, so take it from the previous "first" one + // Todo: Should be handled within SliderPath itself + if (c == slider.Path.ControlPoints[0] && slider.Path.ControlPoints.Count > 1 && slider.Path.ControlPoints[1].Type.Value == null) + slider.Path.ControlPoints[1].Type.Value = slider.Path.ControlPoints[0].Type.Value; + slider.Path.ControlPoints.Remove(c); + } // If there are 0 remaining control points, treat the slider as being deleted if (slider.Path.ControlPoints.Count == 0) From 680b2653aeedbaa02cf359f6079347931db267c6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 18:49:03 +0900 Subject: [PATCH 4331/5608] Improve animation of popup dialog buttons --- .../UserInterface/TestScenePopupDialog.cs | 22 ++++++++++++++----- .../Graphics/UserInterface/DialogButton.cs | 13 ++++++++--- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs index 3d39bb7003..7207506ccd 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs @@ -1,9 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Dialog; namespace osu.Game.Tests.Visual.UserInterface @@ -11,13 +14,22 @@ namespace osu.Game.Tests.Visual.UserInterface [TestFixture] public class TestScenePopupDialog : OsuTestScene { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(PopupDialogOkButton), + typeof(PopupDialogCancelButton), + typeof(PopupDialogButton), + typeof(DialogButton), + }; + public TestScenePopupDialog() { - Add(new TestPopupDialog - { - RelativeSizeAxes = Axes.Both, - State = { Value = Framework.Graphics.Containers.Visibility.Visible }, - }); + AddStep("new popup", () => + Add(new TestPopupDialog + { + RelativeSizeAxes = Axes.Both, + State = { Value = Framework.Graphics.Containers.Visibility.Visible }, + })); } private class TestPopupDialog : PopupDialog diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index 927ad13829..15c09b10b4 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -20,6 +20,7 @@ namespace osu.Game.Graphics.UserInterface { public class DialogButton : OsuClickableContainer { + private const float idle_width = 0.8f; private const float hover_width = 0.9f; private const float hover_duration = 500; private const float glow_fade_duration = 250; @@ -99,7 +100,7 @@ namespace osu.Game.Graphics.UserInterface RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, Anchor = Anchor.Centre, - Width = 0.8f, + Width = idle_width, Masking = true, MaskingSmoothness = 2, EdgeEffect = new EdgeEffectParameters @@ -199,14 +200,18 @@ namespace osu.Game.Graphics.UserInterface public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => backgroundContainer.ReceivePositionalInputAt(screenSpacePos); + private bool clicked; + protected override bool OnClick(ClickEvent e) { + clicked = true; colourContainer.ResizeTo(new Vector2(1.5f, 1f), click_duration, Easing.In); flash(); this.Delay(click_duration).Schedule(delegate { - colourContainer.ResizeTo(new Vector2(0.8f, 1f)); + clicked = false; + colourContainer.ResizeTo(new Vector2(idle_width, 1f)); spriteText.Spacing = Vector2.Zero; glowContainer.FadeOut(); }); @@ -230,6 +235,8 @@ namespace osu.Game.Graphics.UserInterface private void selectionChanged(ValueChangedEvent args) { + if (clicked) return; + if (args.NewValue) { spriteText.TransformSpacingTo(hoverSpacing, hover_duration, Easing.OutElastic); @@ -238,7 +245,7 @@ namespace osu.Game.Graphics.UserInterface } else { - colourContainer.ResizeTo(new Vector2(0.8f, 1f), hover_duration, Easing.OutElastic); + colourContainer.ResizeTo(new Vector2(idle_width, 1f), hover_duration, Easing.OutElastic); spriteText.TransformSpacingTo(Vector2.Zero, hover_duration, Easing.OutElastic); glowContainer.FadeOut(glow_fade_duration, Easing.Out); } From af2305bb77491397b87aebc7f9f3d1ed49de31bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 18:53:30 +0900 Subject: [PATCH 4332/5608] Add null check --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index ec9792d59d..fa701a3c41 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -50,7 +50,8 @@ namespace osu.Game.Rulesets.Osu.Skinning case OsuSkinComponents.SliderFollowCircle: var followCircle = this.GetAnimation("sliderfollowcircle", true, true); - followCircle.Scale *= 0.5f; + if (followCircle != null) + followCircle.Scale *= 0.5f; return followCircle; case OsuSkinComponents.SliderBall: From f958485be1c268d53967522ccb3481716e21d3a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 18:54:54 +0900 Subject: [PATCH 4333/5608] Add comment about size change --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index fa701a3c41..f5b7d9166f 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -51,6 +51,7 @@ namespace osu.Game.Rulesets.Osu.Skinning case OsuSkinComponents.SliderFollowCircle: var followCircle = this.GetAnimation("sliderfollowcircle", true, true); if (followCircle != null) + // follow circles are 2x the hitcircle resolution in legacy skins (since they are scaled down from >1x followCircle.Scale *= 0.5f; return followCircle; From 46d055604a6f049735a6d2b0ed12d33ef5287dab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 18:57:11 +0900 Subject: [PATCH 4334/5608] Customize -> Customise --- ...ionSettings.cs => TestSceneModSettings.cs} | 26 +++++++++---------- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 6 ++--- 2 files changed, 16 insertions(+), 16 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{TestSceneModCustomizationSettings.cs => TestSceneModSettings.cs} (78%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs similarity index 78% rename from osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index 8227fe8f7a..7a11ba5294 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModCustomizationSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneModCustomizationSettings : OsuTestScene + public class TestSceneModSettings : OsuTestScene { private TestModSelectOverlay modSelect; @@ -27,13 +27,13 @@ namespace osu.Game.Tests.Visual.UserInterface Anchor = Anchor.BottomCentre, }); - var testMod = new TestModCustomizable1(); + var testMod = new TestModCustomisable1(); AddStep("open", modSelect.Show); - AddAssert("button disabled", () => !modSelect.CustomizeButton.Enabled.Value); + AddAssert("button disabled", () => !modSelect.CustomiseButton.Enabled.Value); AddStep("select mod", () => modSelect.SelectMod(testMod)); - AddAssert("button enabled", () => modSelect.CustomizeButton.Enabled.Value); - AddStep("open customization", () => modSelect.CustomizeButton.Click()); + AddAssert("button enabled", () => modSelect.CustomiseButton.Enabled.Value); + AddStep("open Customisation", () => modSelect.CustomiseButton.Click()); AddStep("deselect mod", () => modSelect.SelectMod(testMod)); AddAssert("controls hidden", () => modSelect.ModSettingsContainer.Alpha == 0); } @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestModSelectOverlay : ModSelectOverlay { public new Container ModSettingsContainer => base.ModSettingsContainer; - public new TriangleButton CustomizeButton => base.CustomizeButton; + public new TriangleButton CustomiseButton => base.CustomiseButton; public void SelectMod(Mod mod) => ModSectionsContainer.Children.Single(s => s.ModType == mod.Type) @@ -57,8 +57,8 @@ namespace osu.Game.Tests.Visual.UserInterface { section.Mods = new Mod[] { - new TestModCustomizable1(), - new TestModCustomizable2() + new TestModCustomisable1(), + new TestModCustomisable2() }; } else @@ -67,21 +67,21 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class TestModCustomizable1 : TestModCustomizable + private class TestModCustomisable1 : TestModCustomisable { - public override string Name => "Customizable Mod 1"; + public override string Name => "Customisable Mod 1"; public override string Acronym => "CM1"; } - private class TestModCustomizable2 : TestModCustomizable + private class TestModCustomisable2 : TestModCustomisable { - public override string Name => "Customizable Mod 2"; + public override string Name => "Customisable Mod 2"; public override string Acronym => "CM2"; } - private abstract class TestModCustomizable : Mod, IApplicableMod + private abstract class TestModCustomisable : Mod, IApplicableMod { public override double ScoreMultiplier => 1.0; diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index cfad0126eb..e860463b23 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Mods public class ModSelectOverlay : WaveOverlayContainer { protected readonly TriangleButton DeselectAllButton; - protected readonly TriangleButton CustomizeButton; + protected readonly TriangleButton CustomiseButton; protected readonly TriangleButton CloseButton; protected readonly OsuSpriteText MultiplierLabel; @@ -232,7 +232,7 @@ namespace osu.Game.Overlays.Mods Right = 20 } }, - CustomizeButton = new TriangleButton + CustomiseButton = new TriangleButton { Width = 180, Text = "Customization", @@ -351,7 +351,7 @@ namespace osu.Game.Overlays.Mods ModSettingsContent.RemoveAll(section => section.Mod == removed); bool hasSettings = ModSettingsContent.Children.Count > 0; - CustomizeButton.Enabled.Value = hasSettings; + CustomiseButton.Enabled.Value = hasSettings; if (!hasSettings) ModSettingsContainer.Hide(); From 347373a3ba3ef852dabd35306721ff689b47b0af Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 19:04:55 +0900 Subject: [PATCH 4335/5608] Fix test failures --- .../UserInterface/TestSceneModSettings.cs | 3 +++ osu.Game/Overlays/Mods/ModSection.cs | 22 +++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index 7a11ba5294..435dfd92be 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs @@ -31,6 +31,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("open", modSelect.Show); AddAssert("button disabled", () => !modSelect.CustomiseButton.Enabled.Value); + AddUntilStep("wait for button load", () => modSelect.ButtonsLoaded); AddStep("select mod", () => modSelect.SelectMod(testMod)); AddAssert("button enabled", () => modSelect.CustomiseButton.Enabled.Value); AddStep("open Customisation", () => modSelect.CustomiseButton.Click()); @@ -43,6 +44,8 @@ namespace osu.Game.Tests.Visual.UserInterface public new Container ModSettingsContainer => base.ModSettingsContainer; public new TriangleButton CustomiseButton => base.CustomiseButton; + public bool ButtonsLoaded => ModSectionsContainer.Children.All(c => c.ModIconsLoaded); + public void SelectMod(Mod mod) => ModSectionsContainer.Children.Single(s => s.ModType == mod.Type) .ButtonsContainer.OfType().Single(b => b.Mods.Any(m => m.GetType() == mod.GetType())).SelectNext(1); diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 9c0a164ad6..c55d1d8f70 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -57,6 +57,15 @@ namespace osu.Game.Overlays.Mods }).ToArray(); modsLoadCts?.Cancel(); + + if (modContainers.Length == 0) + { + ModIconsLoaded = true; + headerLabel.Hide(); + Hide(); + return; + } + ModIconsLoaded = false; LoadComponentsAsync(modContainers, c => @@ -67,17 +76,8 @@ namespace osu.Game.Overlays.Mods buttons = modContainers.OfType().ToArray(); - if (value.Any()) - { - headerLabel.FadeIn(200); - this.FadeIn(200); - } - else - { - // transition here looks weird as mods instantly disappear. - headerLabel.Hide(); - Hide(); - } + headerLabel.FadeIn(200); + this.FadeIn(200); } } From 41437242a29c4fdd7dbae5055dd679fd4763e149 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Dec 2019 19:39:25 +0900 Subject: [PATCH 4336/5608] Add initial path type progression support --- .../Sliders/SliderPlacementBlueprint.cs | 51 +++++++++++++++++-- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index bbdc43e16f..cd93aa0074 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -30,6 +30,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private InputManager inputManager; private PlacementState state; + private PathControlPoint segmentStart; + private PathControlPoint cursor; + private int currentSegmentLength = 1; [Resolved(CanBeNull = true)] private HitObjectComposer composer { get; set; } @@ -38,7 +41,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders : base(new Objects.Slider()) { RelativeSizeAxes = Axes.Both; - HitObject.Path.ControlPoints.Add(new PathControlPoint { Position = { Value = Vector2.Zero } }); + + segmentStart = HitObject.Path.ControlPoints[0]; + } [BackgroundDependencyLoader] @@ -70,9 +75,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders break; case PlacementState.Body: + ensureCursor(); + // The given screen-space position may have been externally snapped, but the unsnapped position from the input manager // is used instead since snapping control points doesn't make much sense - HitObject.Path.ControlPoints.Last().Position.Value = ToLocalSpace(inputManager.CurrentState.Mouse.Position) - HitObject.Position; + cursor.Position.Value = ToLocalSpace(inputManager.CurrentState.Mouse.Position) - HitObject.Position; break; } } @@ -89,7 +96,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders switch (e.Button) { case MouseButton.Left: - HitObject.Path.ControlPoints.Add(new PathControlPoint { Position = { Value = HitObject.Path.ControlPoints.Last().Position.Value } }); + ensureCursor(); + + // Detatch the cursor + cursor = null; break; } @@ -108,8 +118,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders protected override bool OnDoubleClick(DoubleClickEvent e) { - // At the point of a double click, there's guaranteed to be at least two points - one from the click, and one from the cursor - HitObject.Path.ControlPoints[HitObject.Path.ControlPoints.Count - 2].Type.Value = PathType.Bezier; + // Todo: This should all not occur on double click, but rather if the previous control point is hovered. + segmentStart = HitObject.Path.ControlPoints[HitObject.Path.ControlPoints.Count - 1]; + segmentStart.Type.Value = PathType.Linear; + + currentSegmentLength = 1; return true; } @@ -131,6 +144,34 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders updateSlider(); } + private void updatePathType() + { + switch (currentSegmentLength) + { + case 1: + case 2: + segmentStart.Type.Value = PathType.Linear; + break; + case 3: + segmentStart.Type.Value = PathType.PerfectCurve; + break; + default: + segmentStart.Type.Value = PathType.Bezier; + break; + } + } + + private void ensureCursor() + { + if (cursor == null) + { + HitObject.Path.ControlPoints.Add(cursor = new PathControlPoint { Position = { Value = Vector2.Zero } }); + currentSegmentLength++; + + updatePathType(); + } + } + private void updateSlider() { HitObject.Path.ExpectedDistance.Value = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)HitObject.Path.CalculatedDistance) ?? (float)HitObject.Path.CalculatedDistance; From 5347e7c4a2aadd5694722786f57b45b8f2ab65d2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 20:14:06 +0900 Subject: [PATCH 4337/5608] Apply code quality improvements --- osu.Game/Configuration/SettingSourceAttribute.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Configuration/SettingSourceAttribute.cs b/osu.Game/Configuration/SettingSourceAttribute.cs index dceef1cb7d..056fa8bcc0 100644 --- a/osu.Game/Configuration/SettingSourceAttribute.cs +++ b/osu.Game/Configuration/SettingSourceAttribute.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; using JetBrains.Annotations; using osu.Framework.Bindables; @@ -36,11 +35,13 @@ namespace osu.Game.Configuration { public static IEnumerable CreateSettingsControls(this object obj) { - var configProperties = obj.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance).Where(p => p.GetCustomAttribute(true) != null); - - foreach (var property in configProperties) + foreach (var property in obj.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance)) { var attr = property.GetCustomAttribute(true); + + if (attr == null) + continue; + var prop = property.GetValue(obj); switch (prop) @@ -91,9 +92,7 @@ namespace osu.Game.Configuration break; case IBindable bindable: - var dropdownType = typeof(SettingsEnumDropdown<>).MakeGenericType(bindable.GetType().GetGenericArguments()[0]); - var dropdown = (Drawable)Activator.CreateInstance(dropdownType); dropdown.GetType().GetProperty(nameof(IHasCurrentValue.Current))?.SetValue(dropdown, obj); From f65866648e3e914a358ec4a1639d24d4862c01c7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 20:14:56 +0900 Subject: [PATCH 4338/5608] Use Array.Empty --- osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index 435dfd92be..fc44c5f595 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.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.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -65,7 +66,7 @@ namespace osu.Game.Tests.Visual.UserInterface }; } else - section.Mods = new Mod[] { }; + section.Mods = Array.Empty(); } } } From b9d12e5fe4ba3446e168355220bdf9f35ccf36ec Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Dec 2019 20:53:40 +0900 Subject: [PATCH 4339/5608] Fix nested hitobjects not updating --- .../Objects/JuiceStream.cs | 18 ++++++++++++++- osu.Game.Rulesets.Osu/Objects/Slider.cs | 23 ++++++++++++++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 33780427b6..366f10d61d 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -116,7 +116,23 @@ namespace osu.Game.Rulesets.Catch.Objects public double Duration => EndTime - StartTime; - public SliderPath Path { get; set; } + private readonly SliderPath path = new SliderPath(new[] { new PathControlPoint { Type = { Value = PathType.Linear } } }); + + public SliderPath Path + { + get => path; + set + { + path.ControlPoints.Clear(); + path.ExpectedDistance.Value = null; + + if (value != null) + { + path.ControlPoints.AddRange(value.ControlPoints); + path.ExpectedDistance.Value = value.ExpectedDistance.Value; + } + } + } public double Distance => Path.Distance; diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 09657b2d47..4ba5265d17 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -28,7 +28,23 @@ namespace osu.Game.Rulesets.Osu.Objects public Vector2 StackedPositionAt(double t) => StackedPosition + this.CurvePositionAt(t); - public SliderPath Path { get; set; } = new SliderPath(new[] { new PathControlPoint { Type = { Value = PathType.Bezier } } }); + private readonly SliderPath path = new SliderPath(new[] { new PathControlPoint { Type = { Value = PathType.Linear } } }); + + public SliderPath Path + { + get => path; + set + { + path.ControlPoints.Clear(); + path.ExpectedDistance.Value = null; + + if (value != null) + { + path.ControlPoints.AddRange(value.ControlPoints); + path.ExpectedDistance.Value = value.ExpectedDistance.Value; + } + } + } public double Distance => Path.Distance; @@ -38,8 +54,6 @@ namespace osu.Game.Rulesets.Osu.Objects set { base.Position = value; - endPositionCache.Invalidate(); - updateNestedPositions(); } } @@ -102,6 +116,7 @@ namespace osu.Game.Rulesets.Osu.Objects SamplesBindable.ItemsRemoved += _ => updateNestedSamples(); Path.OffsetChanged += offset => Position += offset; + Path.Version.ValueChanged += _ => updateNestedPositions(); } protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) @@ -179,6 +194,8 @@ namespace osu.Game.Rulesets.Osu.Objects private void updateNestedPositions() { + endPositionCache.Invalidate(); + if (HeadCircle != null) HeadCircle.Position = Position; From 54798b134e99fb136fc50a5749a8d38a2b201892 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sun, 8 Dec 2019 03:16:41 +0900 Subject: [PATCH 4340/5608] Add accessibility modifiers --- osu.Game/Screens/Play/PlayerLoader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 774ca02be1..57021dfc68 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -55,9 +55,9 @@ namespace osu.Game.Screens.Play protected override bool PlayResumeSound => false; - protected Task LoadTask; + protected Task LoadTask { get; private set; } - protected Task DisposalTask; + protected Task DisposalTask { get; private set; } private InputManager inputManager; private IdleTracker idleTracker; From ff8544597c3bd5d0fa1dc26b19f469dcbbdc0632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 7 Dec 2019 19:51:54 +0100 Subject: [PATCH 4341/5608] Add explicit app manifest to desktop project After the .NET Core bump to version 3.0 in the 2019.1011.0 release, reports popped up of the game not starting any more on some computers using Intel graphics cards (HD 3000 in particular). After investigation the auto-generated application manifest changed in .NET Core 3.0. In particular this seems to be a root cause for the failed start-ups on Intel cards, due to a Windows version compatibility section appearing. The section in turn affects some WinAPI calls like GetVersionEx, which will return major version 10 instead of 6 if compatibility with Windows 10 is declared. This combined with a broken check in the Intel OpenGL driver caused the crashes. To resolve this without having to patch binaries, add an explicit application manifest to the desktop project with the compatibility section removed. --- osu.Desktop/app.manifest | 20 ++++++++++++++++++++ osu.Desktop/osu.Desktop.csproj | 1 + 2 files changed, 21 insertions(+) create mode 100644 osu.Desktop/app.manifest diff --git a/osu.Desktop/app.manifest b/osu.Desktop/app.manifest new file mode 100644 index 0000000000..2e9127bf44 --- /dev/null +++ b/osu.Desktop/app.manifest @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + true + + + \ No newline at end of file diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 453cf6f94d..01e4ada2f1 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -8,6 +8,7 @@ osu!lazer osu!lazer lazer.ico + app.manifest 0.0.0 0.0.0 From 929be3e9e7e32954385f36f348f9cea8d9a7595c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 8 Dec 2019 12:34:07 +0300 Subject: [PATCH 4342/5608] Highlight own score in BeatmapSetOverlay --- .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 2 +- .../Scores/ScoreTableRowBackground.cs | 24 +++++++++++++------ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 58f5f02956..f6723839b2 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -63,7 +63,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores return; for (int i = 0; i < value.Count; i++) - backgroundFlow.Add(new ScoreTableRowBackground(i)); + backgroundFlow.Add(new ScoreTableRowBackground(i, value[i])); Columns = createHeaders(value[0]); Content = value.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs index d820f4d89d..1e10c200ab 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs @@ -7,6 +7,8 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Online.API; +using osu.Game.Scoring; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -17,8 +19,14 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly Box hoveredBackground; private readonly Box background; - public ScoreTableRowBackground(int index) + private readonly int index; + private readonly ScoreInfo score; + + public ScoreTableRowBackground(int index, ScoreInfo score) { + this.index = index; + this.score = score; + RelativeSizeAxes = Axes.X; Height = 25; @@ -37,16 +45,18 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Alpha = 0, }, }; - - if (index % 2 != 0) - background.Alpha = 0; } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, IAPIProvider api) { - hoveredBackground.Colour = colours.Gray4; - background.Colour = colours.Gray3; + var isOwnScore = api.LocalUser.Value.Id == score.UserID; + + if (index % 2 != 0 && !isOwnScore) + background.Alpha = 0; + + hoveredBackground.Colour = isOwnScore ? colours.GreenDark : colours.Gray4; + background.Colour = isOwnScore ? colours.GreenDarker : colours.Gray3; } protected override bool OnHover(HoverEvent e) From 13b891f3f4ed6eae1c572737238a005e199efbd1 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sun, 8 Dec 2019 20:05:02 +0800 Subject: [PATCH 4343/5608] Crude legacy cursor rotation support --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index 470ba3acae..6bef90fbaa 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -19,6 +19,8 @@ namespace osu.Game.Rulesets.Osu.Skinning Origin = Anchor.Centre; } + private NonPlayfieldSprite cursor; + [BackgroundDependencyLoader] private void load(ISkinSource skin) { @@ -30,13 +32,14 @@ namespace osu.Game.Rulesets.Osu.Skinning Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - new NonPlayfieldSprite + cursor = new NonPlayfieldSprite { Texture = skin.GetTexture("cursor"), Anchor = Anchor.Centre, Origin = Anchor.Centre, } }; + cursor.Spin(10000, RotationDirection.Clockwise); } } } From 4cd0dd7856e8b553a9698d86dc114f0ca0768a92 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sun, 8 Dec 2019 20:47:28 +0800 Subject: [PATCH 4344/5608] Move transformation to LoadComplete --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index 6bef90fbaa..11039227c6 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -39,6 +39,10 @@ namespace osu.Game.Rulesets.Osu.Skinning Origin = Anchor.Centre, } }; + } + + protected override void LoadComplete() + { cursor.Spin(10000, RotationDirection.Clockwise); } } From 8956768fe0d49a9d433b7ff88b601f4d6dd90e1e Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 8 Dec 2019 08:55:45 -0800 Subject: [PATCH 4345/5608] Fix mod buttons being selected when drag scrolling overlay --- osu.Game/Overlays/Mods/ModButton.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index c6b4787ff1..ce623dc182 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -167,10 +167,6 @@ namespace osu.Game.Overlays.Mods { switch (e.Button) { - case MouseButton.Left: - SelectNext(1); - break; - case MouseButton.Right: SelectNext(-1); break; @@ -180,6 +176,15 @@ namespace osu.Game.Overlays.Mods return true; } + protected override bool OnClick(ClickEvent e) + { + scaleContainer.ScaleTo(1, 500, Easing.OutElastic); + + SelectNext(1); + + return base.OnClick(e); + } + /// /// Select the next available mod in a specified direction. /// From 463b6c00300b1686fe4eb66742ca0f63ea373e03 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 8 Dec 2019 09:04:34 -0800 Subject: [PATCH 4346/5608] Remove whitespace --- osu.Game/Overlays/Mods/ModButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index ce623dc182..5af3ebab3b 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -179,7 +179,7 @@ namespace osu.Game.Overlays.Mods protected override bool OnClick(ClickEvent e) { scaleContainer.ScaleTo(1, 500, Easing.OutElastic); - + SelectNext(1); return base.OnClick(e); From e394b28799f4df5e7e01e87dbed07a8bc50127a2 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 8 Dec 2019 09:12:32 -0800 Subject: [PATCH 4347/5608] Remove redundant transform --- osu.Game/Overlays/Mods/ModButton.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index 5af3ebab3b..69a4a4181a 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -178,11 +178,9 @@ namespace osu.Game.Overlays.Mods protected override bool OnClick(ClickEvent e) { - scaleContainer.ScaleTo(1, 500, Easing.OutElastic); - SelectNext(1); - return base.OnClick(e); + return true; } /// From c2a40c574dabf83556a23272e869768759b966d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Dec 2019 02:13:47 +0900 Subject: [PATCH 4348/5608] Split out if statement for readability --- .../Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs index 1e10c200ab..724a7f8b55 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs @@ -52,11 +52,14 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { var isOwnScore = api.LocalUser.Value.Id == score.UserID; - if (index % 2 != 0 && !isOwnScore) + if (isOwnScore) + background.Colour = colours.GreenDarker; + else if (index % 2 == 0) + background.Colour = colours.Gray3; + else background.Alpha = 0; hoveredBackground.Colour = isOwnScore ? colours.GreenDark : colours.Gray4; - background.Colour = isOwnScore ? colours.GreenDarker : colours.Gray3; } protected override bool OnHover(HoverEvent e) From 88ec0c14862a862750060e0717324cf2c03606f9 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 8 Dec 2019 18:49:58 +0100 Subject: [PATCH 4349/5608] Add missing async content loading logic to NewsOverlay --- osu.Game/Overlays/NewsOverlay.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index aadca8883e..db4b118bf8 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.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; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -16,7 +17,6 @@ namespace osu.Game.Overlays { private NewsHeader header; - //ReSharper disable NotAccessedField.Local private Container content; public readonly Bindable Current = new Bindable(null); @@ -59,6 +59,21 @@ namespace osu.Game.Overlays Current.TriggerChange(); } + private CancellationTokenSource loadChildCancellation; + + protected void LoadAndShowChild(NewsContent newContent) + { + content.FadeTo(0.2f, 300, Easing.OutQuint); + + loadChildCancellation?.Cancel(); + + LoadComponentAsync(newContent, c => + { + content.Child = c; + content.FadeIn(300, Easing.OutQuint); + }, (loadChildCancellation = new CancellationTokenSource()).Token); + } + public void ShowFrontPage() { Current.Value = null; From 5cf35869e956ffcf0fc2671705bf3cb7c33cab2c Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 8 Dec 2019 10:40:39 -0800 Subject: [PATCH 4350/5608] Fix key config search not clearing after pressing escape --- osu.Game/Overlays/SettingsSubPanel.cs | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/osu.Game/Overlays/SettingsSubPanel.cs b/osu.Game/Overlays/SettingsSubPanel.cs index 5000156e97..2235f9f338 100644 --- a/osu.Game/Overlays/SettingsSubPanel.cs +++ b/osu.Game/Overlays/SettingsSubPanel.cs @@ -4,12 +4,10 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Input.Bindings; using osu.Game.Overlays.Settings; using osu.Game.Screens.Ranking; using osuTK; @@ -36,7 +34,7 @@ namespace osu.Game.Overlays protected override bool DimMainContent => false; // dimming is handled by main overlay - private class BackButton : OsuClickableContainer, IKeyBindingHandler + private class BackButton : OsuClickableContainer { private AspectContainer aspect; @@ -85,20 +83,6 @@ namespace osu.Game.Overlays aspect.ScaleTo(1, 1000, Easing.OutElastic); return base.OnMouseUp(e); } - - public bool OnPressed(GlobalAction action) - { - switch (action) - { - case GlobalAction.Back: - Click(); - return true; - } - - return false; - } - - public bool OnReleased(GlobalAction action) => false; } } } From 9974fff5cc3d52d36e0ebaf2f57cc3af5eddc4ea Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 8 Dec 2019 10:51:25 -0800 Subject: [PATCH 4351/5608] Make sub panel back button inherit osu button --- osu.Game/Overlays/SettingsSubPanel.cs | 32 +++++++++------------------ 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/osu.Game/Overlays/SettingsSubPanel.cs b/osu.Game/Overlays/SettingsSubPanel.cs index 2235f9f338..1fa233d9d4 100644 --- a/osu.Game/Overlays/SettingsSubPanel.cs +++ b/osu.Game/Overlays/SettingsSubPanel.cs @@ -3,14 +3,14 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; -using osu.Game.Screens.Ranking; using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays { @@ -34,21 +34,21 @@ namespace osu.Game.Overlays protected override bool DimMainContent => false; // dimming is handled by main overlay - private class BackButton : OsuClickableContainer + private class BackButton : OsuButton { - private AspectContainer aspect; - [BackgroundDependencyLoader] private void load() { Size = new Vector2(Sidebar.DEFAULT_WIDTH); - Children = new Drawable[] + + BackgroundColour = Color4.Black; + + AddRange(new Drawable[] { - aspect = new AspectContainer + new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, Children = new Drawable[] { new SpriteIcon @@ -69,19 +69,7 @@ namespace osu.Game.Overlays }, } } - }; - } - - protected override bool OnMouseDown(MouseDownEvent e) - { - aspect.ScaleTo(0.75f, 2000, Easing.OutQuint); - return base.OnMouseDown(e); - } - - protected override bool OnMouseUp(MouseUpEvent e) - { - aspect.ScaleTo(1, 1000, Easing.OutElastic); - return base.OnMouseUp(e); + }); } } } From b2b252a1cc446f96c306129fe6d6011b07dafe66 Mon Sep 17 00:00:00 2001 From: mcendu Date: Mon, 9 Dec 2019 08:36:07 +0800 Subject: [PATCH 4352/5608] Allow skin to disable spin --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 8 ++++++-- .../Skinning/OsuLegacySkinTransformer.cs | 4 +++- osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index 11039227c6..68cf99caf1 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -11,15 +11,18 @@ namespace osu.Game.Rulesets.Osu.Skinning { public class LegacyCursor : CompositeDrawable { - public LegacyCursor() + public LegacyCursor(bool spin = true) { Size = new Vector2(50); Anchor = Anchor.Centre; Origin = Anchor.Centre; + + rotate = spin; } private NonPlayfieldSprite cursor; + private bool rotate; [BackgroundDependencyLoader] private void load(ISkinSource skin) @@ -43,7 +46,8 @@ namespace osu.Game.Rulesets.Osu.Skinning protected override void LoadComplete() { - cursor.Spin(10000, RotationDirection.Clockwise); + if (rotate) + cursor.Spin(10000, RotationDirection.Clockwise); } } } diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index f5b7d9166f..f58b96844e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -81,7 +81,9 @@ namespace osu.Game.Rulesets.Osu.Skinning case OsuSkinComponents.Cursor: if (source.GetTexture("cursor") != null) - return new LegacyCursor(); + { + return new LegacyCursor(GetConfig(OsuSkinConfiguration.CursorRotate)?.Value ?? true); + } return null; diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs index 98219cafe8..5d99960f10 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs @@ -11,5 +11,6 @@ namespace osu.Game.Rulesets.Osu.Skinning SliderPathRadius, AllowSliderBallTint, CursorExpand, + CursorRotate } } From 1cf81c49066dbf3fdafc3d029c187ad012b26d0d Mon Sep 17 00:00:00 2001 From: mcendu Date: Mon, 9 Dec 2019 08:37:32 +0800 Subject: [PATCH 4353/5608] rm unnecessary curlies --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index f58b96844e..56c8e74509 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -81,9 +81,7 @@ namespace osu.Game.Rulesets.Osu.Skinning case OsuSkinComponents.Cursor: if (source.GetTexture("cursor") != null) - { return new LegacyCursor(GetConfig(OsuSkinConfiguration.CursorRotate)?.Value ?? true); - } return null; From eb065286ae5b17081910d708fc1deb2421c969bd Mon Sep 17 00:00:00 2001 From: mcendu Date: Mon, 9 Dec 2019 08:49:44 +0800 Subject: [PATCH 4354/5608] fix ci --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index 68cf99caf1..85ae9d0fc4 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Skinning } private NonPlayfieldSprite cursor; - private bool rotate; + private readonly bool rotate; [BackgroundDependencyLoader] private void load(ISkinSource skin) From 76aabdd2971effca216074ee33e7399b8e8b92b0 Mon Sep 17 00:00:00 2001 From: mcendu Date: Mon, 9 Dec 2019 12:11:04 +0800 Subject: [PATCH 4355/5608] rename field rotate to spin --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index 85ae9d0fc4..d0d11b9157 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -18,11 +18,11 @@ namespace osu.Game.Rulesets.Osu.Skinning Anchor = Anchor.Centre; Origin = Anchor.Centre; - rotate = spin; + this.spin = spin; } private NonPlayfieldSprite cursor; - private readonly bool rotate; + private readonly bool spin; [BackgroundDependencyLoader] private void load(ISkinSource skin) @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Skinning protected override void LoadComplete() { - if (rotate) + if (spin) cursor.Spin(10000, RotationDirection.Clockwise); } } From 4905709ea497799416c71fbcdba485612c60b67e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 13:19:21 +0900 Subject: [PATCH 4356/5608] Remove unused usings --- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 2 -- .../Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs | 2 -- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 2 -- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs | 1 - osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs | 1 - osu.Game.Rulesets.Osu/Objects/Slider.cs | 1 - .../Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs | 1 - .../Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs | 1 - osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs | 1 - .../Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs | 1 - 10 files changed, 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index ee4a37a4f2..a9616026f5 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.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.Collections.Generic; using System.Linq; using Humanizer; @@ -17,7 +16,6 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose; -using osuTK; using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index cd93aa0074..639e18681b 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -2,9 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Events; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 9a504445f4..7431972673 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -12,7 +11,6 @@ using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index 166defbc41..c5609b01e0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -4,7 +4,6 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index 8e2f6ffa66..21a3a0d236 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -3,7 +3,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 4ba5265d17..4c299fd7c2 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -6,7 +6,6 @@ using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; using osu.Game.Rulesets.Objects; using System.Linq; -using osu.Framework.Bindables; using osu.Framework.Caching; using osu.Game.Audio; using osu.Game.Beatmaps; diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index afa1f2996e..43e8d01297 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -3,7 +3,6 @@ using osuTK; using osu.Game.Audio; -using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; namespace osu.Game.Rulesets.Objects.Legacy.Catch diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index d1a8adc2b7..f94c4aaa75 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -3,7 +3,6 @@ using osuTK; using osu.Game.Audio; -using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; namespace osu.Game.Rulesets.Objects.Legacy.Mania diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index 6628f7d059..b95ec703b6 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osuTK; -using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; using osu.Game.Audio; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs index 7b1d64b19f..db65a61c90 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osuTK; -using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; using osu.Game.Audio; From 69deb0ca96f2ef4d22233fd8333311c290b965b0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 9 Dec 2019 07:19:55 +0300 Subject: [PATCH 4357/5608] Fix unavailable replays can be accessed via leaderboard --- osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs index 79ce04ed66..b941cd8973 100644 --- a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs @@ -34,7 +34,7 @@ namespace osu.Game.Online.API.Requests.Responses PP = PP, Beatmap = Beatmap, RulesetID = OnlineRulesetID, - Hash = "online", // todo: temporary? + Hash = Replay ? "online" : string.Empty, // todo: temporary? Rank = Rank, Ruleset = ruleset, Mods = mods, From 03d18186c23ab92eddda00a04f958d592ca9abf5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Dec 2019 14:11:44 +0900 Subject: [PATCH 4358/5608] Fix broken merge --- .../Graphics/UserInterface/DialogButton.cs | 73 ++++++++++--------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index 15c09b10b4..aed07e56ee 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -22,8 +22,8 @@ namespace osu.Game.Graphics.UserInterface { private const float idle_width = 0.8f; private const float hover_width = 0.9f; + private const float hover_duration = 500; - private const float glow_fade_duration = 250; private const float click_duration = 200; public readonly BindableBool Selected = new BindableBool(); @@ -200,30 +200,50 @@ namespace osu.Game.Graphics.UserInterface public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => backgroundContainer.ReceivePositionalInputAt(screenSpacePos); - private bool clicked; + private bool clickAnimating; protected override bool OnClick(ClickEvent e) { - clicked = true; - colourContainer.ResizeTo(new Vector2(1.5f, 1f), click_duration, Easing.In); - flash(); - - this.Delay(click_duration).Schedule(delegate + var flash = new Box { - clicked = false; - colourContainer.ResizeTo(new Vector2(idle_width, 1f)); - spriteText.Spacing = Vector2.Zero; - glowContainer.FadeOut(); - }); + RelativeSizeAxes = Axes.Both, + Colour = ButtonColour, + Blending = BlendingParameters.Additive, + Alpha = 0.05f + }; + + colourContainer.Add(flash); + flash.FadeOutFromOne(100).Expire(); + + clickAnimating = true; + colourContainer.ResizeWidthTo(colourContainer.Width * 1.05f, 100, Easing.OutQuint) + .OnComplete(_ => + { + clickAnimating = false; + Selected.TriggerChange(); + }); return base.OnClick(e); } + protected override bool OnMouseDown(MouseDownEvent e) + { + colourContainer.ResizeWidthTo(hover_width * 0.98f, click_duration * 4, Easing.OutQuad); + return base.OnMouseDown(e); + } + + protected override bool OnMouseUp(MouseUpEvent e) + { + if (Selected.Value) + colourContainer.ResizeWidthTo(hover_width, click_duration, Easing.In); + return base.OnMouseUp(e); + } + protected override bool OnHover(HoverEvent e) { base.OnHover(e); - Selected.Value = true; + return true; } @@ -235,38 +255,23 @@ namespace osu.Game.Graphics.UserInterface private void selectionChanged(ValueChangedEvent args) { - if (clicked) return; + if (clickAnimating) + return; if (args.NewValue) { spriteText.TransformSpacingTo(hoverSpacing, hover_duration, Easing.OutElastic); - colourContainer.ResizeTo(new Vector2(hover_width, 1f), hover_duration, Easing.OutElastic); - glowContainer.FadeIn(glow_fade_duration, Easing.Out); + colourContainer.ResizeWidthTo(hover_width, hover_duration, Easing.OutElastic); + glowContainer.FadeIn(hover_duration, Easing.OutQuint); } else { - colourContainer.ResizeTo(new Vector2(idle_width, 1f), hover_duration, Easing.OutElastic); + colourContainer.ResizeWidthTo(idle_width, hover_duration, Easing.OutElastic); spriteText.TransformSpacingTo(Vector2.Zero, hover_duration, Easing.OutElastic); - glowContainer.FadeOut(glow_fade_duration, Easing.Out); + glowContainer.FadeOut(hover_duration, Easing.OutQuint); } } - private void flash() - { - var flash = new Box - { - RelativeSizeAxes = Axes.Both - }; - - colourContainer.Add(flash); - - flash.Colour = ButtonColour; - flash.Blending = BlendingParameters.Additive; - flash.Alpha = 0.3f; - flash.FadeOutFromOne(click_duration); - flash.Expire(); - } - private void updateGlow() { leftGlow.Colour = ColourInfo.GradientHorizontal(new Color4(ButtonColour.R, ButtonColour.G, ButtonColour.B, 0f), ButtonColour); From aff1b93a0790672311926a9e0f6bec711c1ce011 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 14:43:23 +0900 Subject: [PATCH 4359/5608] Move config retrieval into LegacySliderBall --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 12 ++++++------ .../Skinning/OsuLegacySkinTransformer.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index d0d11b9157..05b38ae195 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -11,22 +11,22 @@ namespace osu.Game.Rulesets.Osu.Skinning { public class LegacyCursor : CompositeDrawable { - public LegacyCursor(bool spin = true) + private NonPlayfieldSprite cursor; + private bool spin; + + public LegacyCursor() { Size = new Vector2(50); Anchor = Anchor.Centre; Origin = Anchor.Centre; - - this.spin = spin; } - private NonPlayfieldSprite cursor; - private readonly bool spin; - [BackgroundDependencyLoader] private void load(ISkinSource skin) { + spin = skin.GetConfig(OsuSkinConfiguration.CursorRotate)?.Value ?? true; + InternalChildren = new Drawable[] { new NonPlayfieldSprite diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 56c8e74509..f5b7d9166f 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Osu.Skinning case OsuSkinComponents.Cursor: if (source.GetTexture("cursor") != null) - return new LegacyCursor(GetConfig(OsuSkinConfiguration.CursorRotate)?.Value ?? true); + return new LegacyCursor(); return null; From 12cfb7dedb3a8e631abdeb73c18d2169d7dd8255 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2019 07:28:11 +0000 Subject: [PATCH 4360/5608] Bump System.ComponentModel.Annotations from 4.6.0 to 4.7.0 Bumps [System.ComponentModel.Annotations](https://github.com/dotnet/corefx) from 4.6.0 to 4.7.0. - [Release notes](https://github.com/dotnet/corefx/releases) - [Commits](https://github.com/dotnet/corefx/commits) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 086359ee41..ef16738908 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -27,6 +27,6 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 0eb8d98a63..5090190f28 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -86,7 +86,7 @@ - + From 53f7c753fb83cec669a56a12b9a4a19e096e9390 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 16:44:19 +0900 Subject: [PATCH 4361/5608] General cleanups --- .../Sliders/Components/PathControlPointVisualiser.cs | 2 +- .../Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs | 3 ++- osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index a9616026f5..f0888b34fe 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private bool deleteSelected() { - List toRemove = Pieces.Where(p => p.IsSelected.Value).Select(p => p.Index).Select(i => slider.Path.ControlPoints[i]).ToList(); + List toRemove = Pieces.Where(p => p.IsSelected.Value).Select(p => slider.Path.ControlPoints[p.Index]).ToList(); // Ensure that there are any points to be deleted if (toRemove.Count == 0) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 639e18681b..7dd2017e48 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -41,7 +41,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders RelativeSizeAxes = Axes.Both; segmentStart = HitObject.Path.ControlPoints[0]; - } [BackgroundDependencyLoader] @@ -150,9 +149,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders case 2: segmentStart.Type.Value = PathType.Linear; break; + case 3: segmentStart.Type.Value = PathType.PerfectCurve; break; + default: segmentStart.Type.Value = PathType.Bezier; break; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs index 27d39d0f17..606395c289 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs @@ -6,7 +6,6 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Lines; -using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osuTK; @@ -141,6 +140,7 @@ namespace osu.Game.Tests.Visual.Gameplay case 2: path.ControlPoints.AddRange(createSegment(PathType.PerfectCurve, Vector2.Zero, new Vector2(0, 100))); break; + case 4: path.ControlPoints.AddRange(createSegment(PathType.PerfectCurve, Vector2.Zero, new Vector2(0, 100), new Vector2(100), new Vector2(100, 0))); break; From b764a74919e5da3ac88b576e7b954b4a7bab6463 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2019 07:52:22 +0000 Subject: [PATCH 4362/5608] Bump Microsoft.Win32.Registry from 4.6.0 to 4.7.0 Bumps [Microsoft.Win32.Registry](https://github.com/dotnet/corefx) from 4.6.0 to 4.7.0. - [Release notes](https://github.com/dotnet/corefx/releases) - [Commits](https://github.com/dotnet/corefx/commits) Signed-off-by: dependabot-preview[bot] --- osu.Desktop/osu.Desktop.csproj | 2 +- osu.Game.Tournament/osu.Game.Tournament.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 01e4ada2f1..63aa999a97 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -28,7 +28,7 @@ - + diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index 8e881fdd9c..9cce40c9d3 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -9,6 +9,6 @@ - + \ No newline at end of file From 3861abce826e0f533f97cc678b5333046409b55f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2019 07:52:23 +0000 Subject: [PATCH 4363/5608] Bump System.IO.Packaging from 4.6.0 to 4.7.0 Bumps [System.IO.Packaging](https://github.com/dotnet/corefx) from 4.6.0 to 4.7.0. - [Release notes](https://github.com/dotnet/corefx/releases) - [Commits](https://github.com/dotnet/corefx/commits) Signed-off-by: dependabot-preview[bot] --- osu.Desktop/osu.Desktop.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 01e4ada2f1..70b9d5c184 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -24,7 +24,7 @@ - + From 0c7e5a2e3b0cf886eae6f2828c33b793c2501cc0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Dec 2019 19:15:49 +0900 Subject: [PATCH 4364/5608] Add bindable adjustments for DT/HT rate --- osu.Game/Rulesets/Mods/ModDoubleTime.cs | 14 +++++++++++++- osu.Game/Rulesets/Mods/ModHalfTime.cs | 14 +++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModDoubleTime.cs b/osu.Game/Rulesets/Mods/ModDoubleTime.cs index a5e76e32b1..1a6831d974 100644 --- a/osu.Game/Rulesets/Mods/ModDoubleTime.cs +++ b/osu.Game/Rulesets/Mods/ModDoubleTime.cs @@ -3,7 +3,9 @@ using System; using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; using osu.Game.Graphics; namespace osu.Game.Rulesets.Mods @@ -19,6 +21,16 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModHalfTime)).ToArray(); - protected override double RateAdjust => 1.5; + [SettingSource("Speed increase", "The actual increase to apply")] + public BindableNumber SpeedChange { get; } = new BindableDouble + { + MinValue = 1.01, + MaxValue = 2, + Default = 1.5, + Value = 1.5, + Precision = 0.01, + }; + + protected override double RateAdjust => SpeedChange.Value; } } diff --git a/osu.Game/Rulesets/Mods/ModHalfTime.cs b/osu.Game/Rulesets/Mods/ModHalfTime.cs index 27369f4c30..4acf771fa8 100644 --- a/osu.Game/Rulesets/Mods/ModHalfTime.cs +++ b/osu.Game/Rulesets/Mods/ModHalfTime.cs @@ -3,7 +3,9 @@ using System; using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; using osu.Game.Graphics; namespace osu.Game.Rulesets.Mods @@ -19,6 +21,16 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModDoubleTime)).ToArray(); - protected override double RateAdjust => 0.75; + [SettingSource("Speed decrease", "The actual decrease to apply")] + public BindableNumber SpeedChange { get; } = new BindableDouble + { + MinValue = 0.5, + MaxValue = 0.99, + Default = 0.75, + Value = 0.75, + Precision = 0.01, + }; + + protected override double RateAdjust => SpeedChange.Value; } } From eb074b7058cc6586f447d308131db79b8af5724e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Dec 2019 17:34:04 +0900 Subject: [PATCH 4365/5608] Allow mods to apply to track, not clock --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 4 +- osu.Game/Overlays/MusicController.cs | 4 +- .../Difficulty/DifficultyCalculator.cs | 8 ++-- .../Difficulty/PerformanceCalculator.cs | 8 ++-- ...icableToClock.cs => IApplicableToTrack.cs} | 6 +-- osu.Game/Rulesets/Mods/ModDaycore.cs | 10 ++--- osu.Game/Rulesets/Mods/ModDoubleTime.cs | 2 +- osu.Game/Rulesets/Mods/ModHalfTime.cs | 2 +- osu.Game/Rulesets/Mods/ModNightcore.cs | 10 ++--- osu.Game/Rulesets/Mods/ModTimeAdjust.cs | 12 ++---- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 32 ++++------------ .../Screens/Play/GameplayClockContainer.cs | 37 +++++++++---------- 12 files changed, 52 insertions(+), 83 deletions(-) rename osu.Game/Rulesets/Mods/{IApplicableToClock.cs => IApplicableToTrack.cs} (69%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index dbea8d28a6..f02361e685 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -57,8 +57,8 @@ namespace osu.Game.Tests.Visual.Gameplay beforeLoadAction?.Invoke(); Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); - foreach (var mod in Mods.Value.OfType()) - mod.ApplyToClock(Beatmap.Value.Track); + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToTrack(Beatmap.Value.Track); InputManager.Child = container = new TestPlayerLoaderContainer( loader = new TestPlayerLoader(() => diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 5e0a67c2f7..bafdad3508 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -261,8 +261,8 @@ namespace osu.Game.Overlays if (allowRateAdjustments) { - foreach (var mod in mods.Value.OfType()) - mod.ApplyToClock(track); + foreach (var mod in mods.Value.OfType()) + mod.ApplyToTrack(track); } } diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index e31c963403..1902de5bda 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -4,8 +4,8 @@ using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Audio.Track; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; @@ -41,10 +41,10 @@ namespace osu.Game.Rulesets.Difficulty IBeatmap playableBeatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo, mods); - var clock = new StopwatchClock(); - mods.OfType().ForEach(m => m.ApplyToClock(clock)); + var track = new TrackVirtual(10000); + mods.OfType().ForEach(m => m.ApplyToTrack(track)); - return calculate(playableBeatmap, mods, clock.Rate); + return calculate(playableBeatmap, mods, track.Rate); } /// diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index 9ab81b9580..ac3b817840 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using System.Linq; +using osu.Framework.Audio.Track; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; @@ -35,9 +35,9 @@ namespace osu.Game.Rulesets.Difficulty protected virtual void ApplyMods(Mod[] mods) { - var clock = new StopwatchClock(); - mods.OfType().ForEach(m => m.ApplyToClock(clock)); - TimeRate = clock.Rate; + var track = new TrackVirtual(10000); + mods.OfType().ForEach(m => m.ApplyToTrack(track)); + TimeRate = track.Rate; } public abstract double Calculate(Dictionary categoryDifficulty = null); diff --git a/osu.Game/Rulesets/Mods/IApplicableToClock.cs b/osu.Game/Rulesets/Mods/IApplicableToTrack.cs similarity index 69% rename from osu.Game/Rulesets/Mods/IApplicableToClock.cs rename to osu.Game/Rulesets/Mods/IApplicableToTrack.cs index e5767b5fbf..4d6d958e82 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToClock.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToTrack.cs @@ -1,15 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Timing; +using osu.Framework.Audio.Track; namespace osu.Game.Rulesets.Mods { /// /// An interface for mods that make adjustments to the track. /// - public interface IApplicableToClock : IApplicableMod + public interface IApplicableToTrack : IApplicableMod { - void ApplyToClock(IAdjustableClock clock); + void ApplyToTrack(Track track); } } diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index 7e6d959119..dcb3cb5597 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Audio; +using osu.Framework.Audio.Track; using osu.Framework.Graphics.Sprites; -using osu.Framework.Timing; namespace osu.Game.Rulesets.Mods { @@ -14,12 +13,9 @@ namespace osu.Game.Rulesets.Mods public override IconUsage Icon => FontAwesome.Solid.Question; public override string Description => "Whoaaaaa..."; - public override void ApplyToClock(IAdjustableClock clock) + public override void ApplyToTrack(Track track) { - if (clock is IHasPitchAdjust pitchAdjust) - pitchAdjust.PitchAdjust *= RateAdjust; - else - base.ApplyToClock(clock); + track.Frequency.Value *= RateAdjust; } } } diff --git a/osu.Game/Rulesets/Mods/ModDoubleTime.cs b/osu.Game/Rulesets/Mods/ModDoubleTime.cs index a5e76e32b1..5e685b040e 100644 --- a/osu.Game/Rulesets/Mods/ModDoubleTime.cs +++ b/osu.Game/Rulesets/Mods/ModDoubleTime.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics; namespace osu.Game.Rulesets.Mods { - public abstract class ModDoubleTime : ModTimeAdjust, IApplicableToClock + public abstract class ModDoubleTime : ModTimeAdjust { public override string Name => "Double Time"; public override string Acronym => "DT"; diff --git a/osu.Game/Rulesets/Mods/ModHalfTime.cs b/osu.Game/Rulesets/Mods/ModHalfTime.cs index 27369f4c30..d17ddd2253 100644 --- a/osu.Game/Rulesets/Mods/ModHalfTime.cs +++ b/osu.Game/Rulesets/Mods/ModHalfTime.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics; namespace osu.Game.Rulesets.Mods { - public abstract class ModHalfTime : ModTimeAdjust, IApplicableToClock + public abstract class ModHalfTime : ModTimeAdjust { public override string Name => "Half Time"; public override string Acronym => "HT"; diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index dc0fc33088..a4f1ef5a72 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Audio; +using osu.Framework.Audio.Track; using osu.Framework.Graphics.Sprites; -using osu.Framework.Timing; using osu.Game.Graphics; namespace osu.Game.Rulesets.Mods @@ -15,12 +14,9 @@ namespace osu.Game.Rulesets.Mods public override IconUsage Icon => OsuIcon.ModNightcore; public override string Description => "Uguuuuuuuu..."; - public override void ApplyToClock(IAdjustableClock clock) + public override void ApplyToTrack(Track track) { - if (clock is IHasPitchAdjust pitchAdjust) - pitchAdjust.PitchAdjust *= RateAdjust; - else - base.ApplyToClock(clock); + track.Frequency.Value *= RateAdjust; } } } diff --git a/osu.Game/Rulesets/Mods/ModTimeAdjust.cs b/osu.Game/Rulesets/Mods/ModTimeAdjust.cs index 513883f552..f137a75ed8 100644 --- a/osu.Game/Rulesets/Mods/ModTimeAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModTimeAdjust.cs @@ -2,23 +2,19 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Audio; -using osu.Framework.Timing; +using osu.Framework.Audio.Track; namespace osu.Game.Rulesets.Mods { - public abstract class ModTimeAdjust : Mod + public abstract class ModTimeAdjust : Mod, IApplicableToTrack { public override Type[] IncompatibleMods => new[] { typeof(ModTimeRamp) }; protected abstract double RateAdjust { get; } - public virtual void ApplyToClock(IAdjustableClock clock) + public virtual void ApplyToTrack(Track track) { - if (clock is IHasTempoAdjust tempo) - tempo.TempoAdjust *= RateAdjust; - else - clock.Rate *= RateAdjust; + track.TempoAdjust *= RateAdjust; } } } diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index e231225e3c..d95d354487 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -3,15 +3,14 @@ using System; using System.Linq; -using osu.Framework.Audio; -using osu.Framework.Timing; +using osu.Framework.Audio.Track; using osu.Game.Beatmaps; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mods { - public abstract class ModTimeRamp : Mod, IUpdatableByPlayfield, IApplicableToClock, IApplicableToBeatmap + public abstract class ModTimeRamp : Mod, IUpdatableByPlayfield, IApplicableToTrack, IApplicableToBeatmap { /// /// The point in the beatmap at which the final ramping rate should be reached. @@ -24,11 +23,11 @@ namespace osu.Game.Rulesets.Mods private double finalRateTime; private double beginRampTime; - private IAdjustableClock clock; + private Track track; - public virtual void ApplyToClock(IAdjustableClock clock) + public virtual void ApplyToTrack(Track track) { - this.clock = clock; + this.track = track; lastAdjust = 1; @@ -46,7 +45,7 @@ namespace osu.Game.Rulesets.Mods public virtual void Update(Playfield playfield) { - applyAdjustment((clock.CurrentTime - beginRampTime) / finalRateTime); + applyAdjustment((track.CurrentTime - beginRampTime) / finalRateTime); } private double lastAdjust = 1; @@ -59,23 +58,8 @@ namespace osu.Game.Rulesets.Mods { double adjust = 1 + (Math.Sign(FinalRateAdjustment) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); - switch (clock) - { - case IHasPitchAdjust pitch: - pitch.PitchAdjust /= lastAdjust; - pitch.PitchAdjust *= adjust; - break; - - case IHasTempoAdjust tempo: - tempo.TempoAdjust /= lastAdjust; - tempo.TempoAdjust *= adjust; - break; - - default: - clock.Rate /= lastAdjust; - clock.Rate *= adjust; - break; - } + track.Tempo.Value /= lastAdjust; + track.Tempo.Value *= lastAdjust; lastAdjust = adjust; } diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 58c9a6a784..1508758c87 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -28,9 +28,9 @@ namespace osu.Game.Screens.Play private readonly IReadOnlyList mods; /// - /// The original source (usually a 's track). + /// The 's track. /// - private IAdjustableClock sourceClock; + private Track track; public readonly BindableBool IsPaused = new BindableBool(); @@ -72,8 +72,8 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both; - sourceClock = (IAdjustableClock)beatmap.Track ?? new StopwatchClock(); - (sourceClock as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); + track = beatmap.Track; + track.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; @@ -127,11 +127,11 @@ namespace osu.Game.Screens.Play { Task.Run(() => { - sourceClock.Reset(); + track.Reset(); Schedule(() => { - adjustableClock.ChangeSource(sourceClock); + adjustableClock.ChangeSource(track); updateRate(); if (!IsPaused.Value) @@ -197,13 +197,13 @@ namespace osu.Game.Screens.Play /// public void StopUsingBeatmapClock() { - if (sourceClock != beatmap.Track) + if (track != beatmap.Track) return; removeSourceClockAdjustments(); - sourceClock = new TrackVirtual(beatmap.Track.Length); - adjustableClock.ChangeSource(sourceClock); + track = new TrackVirtual(beatmap.Track.Length); + adjustableClock.ChangeSource(track); } protected override void Update() @@ -218,18 +218,15 @@ namespace osu.Game.Screens.Play private void updateRate() { - if (sourceClock == null) return; + if (track == null) return; speedAdjustmentsApplied = true; - sourceClock.ResetSpeedAdjustments(); + track.ResetSpeedAdjustments(); - if (sourceClock is IHasTempoAdjust tempo) - tempo.TempoAdjust = UserPlaybackRate.Value; - else - sourceClock.Rate = UserPlaybackRate.Value; + track.Tempo.Value = UserPlaybackRate.Value; - foreach (var mod in mods.OfType()) - mod.ApplyToClock(sourceClock); + foreach (var mod in mods.OfType()) + mod.ApplyToTrack(track); } protected override void Dispose(bool isDisposing) @@ -237,18 +234,18 @@ namespace osu.Game.Screens.Play base.Dispose(isDisposing); removeSourceClockAdjustments(); - sourceClock = null; + track = null; } private void removeSourceClockAdjustments() { if (speedAdjustmentsApplied) { - sourceClock.ResetSpeedAdjustments(); + track.ResetSpeedAdjustments(); speedAdjustmentsApplied = false; } - (sourceClock as IAdjustableAudioComponent)?.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); + (track as IAdjustableAudioComponent)?.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); } } } From 5a093c039cedd3b214827871a77c3ef6c69852c7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 17:45:08 +0900 Subject: [PATCH 4366/5608] Simplify path/point construction --- osu.Game/Rulesets/Objects/PathControlPoint.cs | 15 ++++++++++++++- osu.Game/Rulesets/Objects/SliderPath.cs | 15 ++++----------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/osu.Game/Rulesets/Objects/PathControlPoint.cs b/osu.Game/Rulesets/Objects/PathControlPoint.cs index 83436b7a36..de40c24060 100644 --- a/osu.Game/Rulesets/Objects/PathControlPoint.cs +++ b/osu.Game/Rulesets/Objects/PathControlPoint.cs @@ -26,12 +26,25 @@ namespace osu.Game.Rulesets.Objects /// internal event Action Changed; + /// + /// Creates a new . + /// public PathControlPoint() + : this(Vector2.Zero, null) + { + } + + /// + /// Creates a new with a provided position and type. + /// + /// The initial position. + /// The initial type. + public PathControlPoint(Vector2 position, PathType? type = null) { Position.ValueChanged += _ => Changed?.Invoke(); Type.ValueChanged += _ => Changed?.Invoke(); } - public bool Equals(PathControlPoint other) => Position.Value == other.Position.Value && Type.Value == other.Type.Value; + public bool Equals(PathControlPoint other) => Position.Value == other?.Position.Value && Type.Value == other.Type.Value; } } diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 969cdcc463..dbd236107c 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -40,12 +40,10 @@ namespace osu.Game.Rulesets.Objects /// public readonly BindableList ControlPoints = new BindableList(); - public readonly List Test = new List(); - - private readonly Cached pathCache = new Cached(); - private readonly List calculatedPath = new List(); private readonly List cumulativeLength = new List(); + private readonly Cached pathCache = new Cached(); + private double calculatedLength; /// @@ -87,7 +85,7 @@ namespace osu.Game.Rulesets.Objects } /// - /// Creates a new . + /// Creates a new initialised with a list of control points. /// /// An optional set of s to initialise the path with. /// A user-set distance of the path that may be shorter or longer than the true distance between all control points. @@ -101,13 +99,8 @@ namespace osu.Game.Rulesets.Objects } public SliderPath(PathType type, Vector2[] controlPoints, double? expectedDistance = null) - : this() + : this(controlPoints.Select((c, i) => new PathControlPoint(c, i == 0 ? (PathType?)type : null)).ToArray(), expectedDistance) { - foreach (var c in controlPoints) - ControlPoints.Add(new PathControlPoint { Position = { Value = c } }); - ControlPoints[0].Type.Value = type; - - ExpectedDistance.Value = expectedDistance; } /// From 9cb649436c838047fdddbc91b87f08f07e94afd2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 17:47:05 +0900 Subject: [PATCH 4367/5608] Default to linear control point type --- osu.Game/Rulesets/Objects/SliderPath.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index dbd236107c..e323054234 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -196,9 +196,6 @@ namespace osu.Game.Rulesets.Objects if (ControlPoints.Count == 0) return; - if (ControlPoints[0].Type.Value == null) - throw new InvalidOperationException($"The first control point in a {nameof(SliderPath)} must have a non-null type."); - Vector2[] vertices = new Vector2[ControlPoints.Count]; for (int i = 0; i < ControlPoints.Count; i++) vertices[i] = ControlPoints[i].Position.Value; @@ -214,7 +211,7 @@ namespace osu.Game.Rulesets.Objects // The current vertex ends the segment var segmentVertices = vertices.AsSpan().Slice(start, i - start + 1); - var segmentType = ControlPoints[start].Type.Value.Value; + var segmentType = ControlPoints[start].Type.Value ?? PathType.Linear; foreach (Vector2 t in computeSubPath(segmentVertices, segmentType)) { From fa1468325e504a22f7a6e7f9dff5c34dd8878d41 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 17:48:27 +0900 Subject: [PATCH 4368/5608] Refactor hitobjects to remove default control point --- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 366f10d61d..d5d99640af 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Catch.Objects public double Duration => EndTime - StartTime; - private readonly SliderPath path = new SliderPath(new[] { new PathControlPoint { Type = { Value = PathType.Linear } } }); + private readonly SliderPath path = new SliderPath(); public SliderPath Path { diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 4c299fd7c2..134576316a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Objects public Vector2 StackedPositionAt(double t) => StackedPosition + this.CurvePositionAt(t); - private readonly SliderPath path = new SliderPath(new[] { new PathControlPoint { Type = { Value = PathType.Linear } } }); + private readonly SliderPath path = new SliderPath(); public SliderPath Path { From 883d5bc11d54cfd72e58f2e7d42c21b8fea1141b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 17:54:19 +0900 Subject: [PATCH 4369/5608] Remove automatic slider path offsetting --- .../Components/PathControlPointVisualiser.cs | 8 ++++++++ osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 -- osu.Game/Rulesets/Objects/SliderPath.cs | 20 ------------------- 3 files changed, 8 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index f0888b34fe..434e74ddeb 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -16,6 +16,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose; +using osuTK; using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components @@ -122,6 +123,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return true; } + // The path will have a non-zero offset if the head is removed, but sliders don't support this behaviour since the head is positioned at the slider's position + // So the slider needs to be offset by this amount instead, and all control points offset backwards such that the path is re-positioned at (0, 0) + Vector2 first = slider.Path.ControlPoints[0].Position.Value; + foreach (var c in slider.Path.ControlPoints) + c.Position.Value -= first; + slider.Position += first; + // Since pieces are re-used, they will not point to the deleted control points while remaining selected foreach (var piece in Pieces) piece.IsSelected.Value = false; diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 134576316a..34e5a7f3cd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -113,8 +113,6 @@ namespace osu.Game.Rulesets.Osu.Objects { SamplesBindable.ItemsAdded += _ => updateNestedSamples(); SamplesBindable.ItemsRemoved += _ => updateNestedSamples(); - - Path.OffsetChanged += offset => Position += offset; Path.Version.ValueChanged += _ => updateNestedPositions(); } diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index e323054234..d868ee27f0 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -16,12 +16,6 @@ namespace osu.Game.Rulesets.Objects { public class SliderPath { - /// - /// Invoked when the offset of the path changes. - /// The provided value indicates the offset, and should be used to re-calculate the position of the containing drawable. - /// - public event Action OffsetChanged; - /// /// The current version of this . Updated when any change to the path occurs. /// @@ -66,20 +60,6 @@ namespace osu.Game.Rulesets.Objects foreach (var c in items) c.Changed -= invalidate; - // Make all control points relative to the first one - if (ControlPoints.Count > 0) - { - Vector2 first = ControlPoints[0].Position.Value; - - if (first != Vector2.Zero) - { - foreach (var c in ControlPoints) - c.Position.Value -= first; - - OffsetChanged?.Invoke(first); - } - } - invalidate(); }; } From bfbb9aa18e09640549f580748be35a5e7690d82b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 18:01:02 +0900 Subject: [PATCH 4370/5608] Remove outdated assert --- osu.Game/Rulesets/Objects/SliderPath.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index d868ee27f0..d5ae6f471d 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -187,8 +187,6 @@ namespace osu.Game.Rulesets.Objects if (ControlPoints[i].Type.Value == null && i < ControlPoints.Count - 1) continue; - Debug.Assert(ControlPoints[start].Type.Value.HasValue); - // The current vertex ends the segment var segmentVertices = vertices.AsSpan().Slice(start, i - start + 1); var segmentType = ControlPoints[start].Type.Value ?? PathType.Linear; From a1798fd38d29e8cc25a0919025b78bd4e1f24e39 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 18:01:13 +0900 Subject: [PATCH 4371/5608] Fix bad ctor implementation --- osu.Game/Rulesets/Objects/PathControlPoint.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Objects/PathControlPoint.cs b/osu.Game/Rulesets/Objects/PathControlPoint.cs index de40c24060..5737d3f618 100644 --- a/osu.Game/Rulesets/Objects/PathControlPoint.cs +++ b/osu.Game/Rulesets/Objects/PathControlPoint.cs @@ -41,6 +41,9 @@ namespace osu.Game.Rulesets.Objects /// The initial type. public PathControlPoint(Vector2 position, PathType? type = null) { + Position.Value = position; + Type.Value = type; + Position.ValueChanged += _ => Changed?.Invoke(); Type.ValueChanged += _ => Changed?.Invoke(); } From d650bfb6d6d3c56439c3a56e1c1afd940d9d989b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Dec 2019 18:05:14 +0900 Subject: [PATCH 4372/5608] Remove unnecessary cast --- osu.Game/Screens/Play/GameplayClockContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 1508758c87..2cc03ae453 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -245,7 +245,7 @@ namespace osu.Game.Screens.Play speedAdjustmentsApplied = false; } - (track as IAdjustableAudioComponent)?.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); + track.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); } } } From 2dbf94f3abc054504d74a831fc8e885640710d1b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 18:10:33 +0900 Subject: [PATCH 4373/5608] Make placement blueprint add an initial segment --- .../Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 7dd2017e48..c004b6db28 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private PlacementState state; private PathControlPoint segmentStart; private PathControlPoint cursor; - private int currentSegmentLength = 1; + private int currentSegmentLength; [Resolved(CanBeNull = true)] private HitObjectComposer composer { get; set; } @@ -40,7 +40,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { RelativeSizeAxes = Axes.Both; - segmentStart = HitObject.Path.ControlPoints[0]; + HitObject.Path.ControlPoints.Add(segmentStart = new PathControlPoint(Vector2.Zero, PathType.Linear)); + currentSegmentLength = 1; } [BackgroundDependencyLoader] From b6e2738236da446fd99de6f44fa6cb5930572a3f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 18:15:00 +0900 Subject: [PATCH 4374/5608] Remove unused using --- osu.Game/Rulesets/Objects/SliderPath.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index d5ae6f471d..d8c6320c6d 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using Newtonsoft.Json; using osu.Framework.Bindables; From 6d9cd0fafe6b405d48fe74061c529bcdf0aaeeac Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 18:25:13 +0900 Subject: [PATCH 4375/5608] Split out complex method --- osu.Game/Rulesets/Objects/SliderPath.cs | 38 ++++++++++++------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index d8c6320c6d..6a151d7d33 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -190,7 +190,7 @@ namespace osu.Game.Rulesets.Objects var segmentVertices = vertices.AsSpan().Slice(start, i - start + 1); var segmentType = ControlPoints[start].Type.Value ?? PathType.Linear; - foreach (Vector2 t in computeSubPath(segmentVertices, segmentType)) + foreach (Vector2 t in calculateSubPath(segmentVertices, segmentType)) { if (calculatedPath.Count == 0 || calculatedPath.Last() != t) calculatedPath.Add(t); @@ -199,32 +199,32 @@ namespace osu.Game.Rulesets.Objects // Start the new segment at the current vertex start = i; } + } - static List computeSubPath(ReadOnlySpan subControlPoints, PathType type) + private List calculateSubPath(ReadOnlySpan subControlPoints, PathType type) + { + switch (type) { - switch (type) - { - case PathType.Linear: - return PathApproximator.ApproximateLinear(subControlPoints); + case PathType.Linear: + return PathApproximator.ApproximateLinear(subControlPoints); - case PathType.PerfectCurve: - if (subControlPoints.Length != 3) - break; + case PathType.PerfectCurve: + if (subControlPoints.Length != 3) + break; - List subpath = PathApproximator.ApproximateCircularArc(subControlPoints); + List subpath = PathApproximator.ApproximateCircularArc(subControlPoints); - // If for some reason a circular arc could not be fit to the 3 given points, fall back to a numerically stable bezier approximation. - if (subpath.Count == 0) - break; + // If for some reason a circular arc could not be fit to the 3 given points, fall back to a numerically stable bezier approximation. + if (subpath.Count == 0) + break; - return subpath; + return subpath; - case PathType.Catmull: - return PathApproximator.ApproximateCatmull(subControlPoints); - } - - return PathApproximator.ApproximateBezier(subControlPoints); + case PathType.Catmull: + return PathApproximator.ApproximateCatmull(subControlPoints); } + + return PathApproximator.ApproximateBezier(subControlPoints); } private void calculateLength() From 04b3297a0515c9a204109b387bf4e5e3008cabe8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 6 Dec 2019 21:32:31 +0800 Subject: [PATCH 4376/5608] Constrain configuration lookup as enum. --- osu.Game/Configuration/DatabasedConfigManager.cs | 7 ++++--- osu.Game/Configuration/InMemoryConfigManager.cs | 5 +++-- osu.Game/Rulesets/Configuration/RulesetConfigManager.cs | 5 +++-- osu.Game/Skinning/SkinConfigManager.cs | 3 ++- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs index 1ef4c2527a..b3783b45a8 100644 --- a/osu.Game/Configuration/DatabasedConfigManager.cs +++ b/osu.Game/Configuration/DatabasedConfigManager.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; @@ -9,8 +10,8 @@ using osu.Game.Rulesets; namespace osu.Game.Configuration { - public abstract class DatabasedConfigManager : ConfigManager - where T : struct + public abstract class DatabasedConfigManager : ConfigManager + where TLookup : struct, Enum { private readonly SettingsStore settings; @@ -53,7 +54,7 @@ namespace osu.Game.Configuration private readonly List dirtySettings = new List(); - protected override void AddBindable(T lookup, Bindable bindable) + protected override void AddBindable(TLookup lookup, Bindable bindable) { base.AddBindable(lookup, bindable); diff --git a/osu.Game/Configuration/InMemoryConfigManager.cs b/osu.Game/Configuration/InMemoryConfigManager.cs index b0dc6b0e9c..ccf697f680 100644 --- a/osu.Game/Configuration/InMemoryConfigManager.cs +++ b/osu.Game/Configuration/InMemoryConfigManager.cs @@ -1,12 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Configuration; namespace osu.Game.Configuration { - public class InMemoryConfigManager : ConfigManager - where T : struct + public class InMemoryConfigManager : ConfigManager + where TLookup : struct, Enum { public InMemoryConfigManager() { diff --git a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs index ed5fdf9809..0ff3455f00 100644 --- a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs @@ -1,12 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Game.Configuration; namespace osu.Game.Rulesets.Configuration { - public abstract class RulesetConfigManager : DatabasedConfigManager, IRulesetConfigManager - where T : struct + public abstract class RulesetConfigManager : DatabasedConfigManager, IRulesetConfigManager + where TLookup : struct, Enum { protected RulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) : base(settings, ruleset, variant) diff --git a/osu.Game/Skinning/SkinConfigManager.cs b/osu.Game/Skinning/SkinConfigManager.cs index 896444d1d2..682138a2e9 100644 --- a/osu.Game/Skinning/SkinConfigManager.cs +++ b/osu.Game/Skinning/SkinConfigManager.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Configuration; namespace osu.Game.Skinning { - public class SkinConfigManager : ConfigManager where T : struct + public class SkinConfigManager : ConfigManager where TLookup : struct, Enum { protected override void PerformLoad() { From 40a5c1fd96bfd197131f15bc6c9eececba82c437 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 7 Dec 2019 19:49:52 +0800 Subject: [PATCH 4377/5608] Constrain transformable with class. --- osu.Game/Graphics/IHasAccentColour.cs | 2 +- osu.Game/Storyboards/Drawables/IFlippable.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/IHasAccentColour.cs b/osu.Game/Graphics/IHasAccentColour.cs index 1a66819379..af497da70f 100644 --- a/osu.Game/Graphics/IHasAccentColour.cs +++ b/osu.Game/Graphics/IHasAccentColour.cs @@ -24,7 +24,7 @@ namespace osu.Game.Graphics /// /// A to which further transforms can be added. public static TransformSequence FadeAccent(this T accentedDrawable, Color4 newColour, double duration = 0, Easing easing = Easing.None) - where T : IHasAccentColour + where T : class, IHasAccentColour => accentedDrawable.TransformTo(nameof(accentedDrawable.AccentColour), newColour, duration, easing); /// diff --git a/osu.Game/Storyboards/Drawables/IFlippable.cs b/osu.Game/Storyboards/Drawables/IFlippable.cs index 9e12de5833..1c4cdde22d 100644 --- a/osu.Game/Storyboards/Drawables/IFlippable.cs +++ b/osu.Game/Storyboards/Drawables/IFlippable.cs @@ -41,7 +41,7 @@ namespace osu.Game.Storyboards.Drawables /// /// A to which further transforms can be added. public static TransformSequence TransformFlipH(this T flippable, bool newValue, double delay = 0) - where T : IFlippable + where T : class, IFlippable => flippable.TransformTo(flippable.PopulateTransform(new TransformFlipH(), newValue, delay)); /// @@ -49,7 +49,7 @@ namespace osu.Game.Storyboards.Drawables /// /// A to which further transforms can be added. public static TransformSequence TransformFlipV(this T flippable, bool newValue, double delay = 0) - where T : IFlippable + where T : class, IFlippable => flippable.TransformTo(flippable.PopulateTransform(new TransformFlipV(), newValue, delay)); } } From c3518a2b9491960e573e5de0e3860d66a178a0c7 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 7 Dec 2019 19:56:56 +0800 Subject: [PATCH 4378/5608] Enum constraint for enum dropdown. --- .../Graphics/UserInterface/OsuEnumDropdown.cs | 4 +--- .../SearchableList/DisplayStyleControl.cs | 2 ++ .../SearchableListFilterControl.cs | 19 +++++++++---------- .../SearchableList/SearchableListHeader.cs | 4 +--- .../SearchableList/SearchableListOverlay.cs | 14 +++++++++----- .../SearchableList/SlimEnumDropdown.cs | 2 ++ .../Overlays/Settings/SettingsEnumDropdown.cs | 2 ++ 7 files changed, 26 insertions(+), 21 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs b/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs index e132027787..528d7d60f8 100644 --- a/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs @@ -6,12 +6,10 @@ using System; namespace osu.Game.Graphics.UserInterface { public class OsuEnumDropdown : OsuDropdown + where T : struct, Enum { public OsuEnumDropdown() { - if (!typeof(T).IsEnum) - throw new InvalidOperationException("OsuEnumDropdown only supports enums as the generic type argument"); - Items = (T[])Enum.GetValues(typeof(T)); } } diff --git a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs b/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs index 0808cc8fcc..a33f4eb30d 100644 --- a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs +++ b/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Bindables; using osuTK; using osu.Framework.Graphics; @@ -11,6 +12,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.SearchableList { public class DisplayStyleControl : Container + where T : struct, Enum { public readonly SlimEnumDropdown Dropdown; public readonly Bindable DisplayStyle = new Bindable(); diff --git a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs index 372da94b37..117f905de4 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs @@ -13,7 +13,9 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Overlays.SearchableList { - public abstract class SearchableListFilterControl : Container + public abstract class SearchableListFilterControl : Container + where TTab : struct, Enum + where TCategory : struct, Enum { private const float padding = 10; @@ -21,12 +23,12 @@ namespace osu.Game.Overlays.SearchableList private readonly Box tabStrip; public readonly SearchTextBox Search; - public readonly PageTabControl Tabs; - public readonly DisplayStyleControl DisplayStyleControl; + public readonly PageTabControl Tabs; + public readonly DisplayStyleControl DisplayStyleControl; protected abstract Color4 BackgroundColour { get; } - protected abstract T DefaultTab { get; } - protected abstract U DefaultCategory { get; } + protected abstract TTab DefaultTab { get; } + protected abstract TCategory DefaultCategory { get; } protected virtual Drawable CreateSupplementaryControls() => null; /// @@ -36,9 +38,6 @@ namespace osu.Game.Overlays.SearchableList protected SearchableListFilterControl() { - if (!typeof(T).IsEnum) - throw new InvalidOperationException("SearchableListFilterControl's sort tabs only support enums as the generic type argument"); - RelativeSizeAxes = Axes.X; var controls = CreateSupplementaryControls(); @@ -90,7 +89,7 @@ namespace osu.Game.Overlays.SearchableList RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Right = 225 }, - Child = Tabs = new PageTabControl + Child = Tabs = new PageTabControl { RelativeSizeAxes = Axes.X, }, @@ -105,7 +104,7 @@ namespace osu.Game.Overlays.SearchableList }, }, }, - DisplayStyleControl = new DisplayStyleControl + DisplayStyleControl = new DisplayStyleControl { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, diff --git a/osu.Game/Overlays/SearchableList/SearchableListHeader.cs b/osu.Game/Overlays/SearchableList/SearchableListHeader.cs index 73dca956d1..66fedf0a56 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListHeader.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListHeader.cs @@ -14,6 +14,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.SearchableList { public abstract class SearchableListHeader : Container + where T : struct, Enum { public readonly HeaderTabControl Tabs; @@ -24,9 +25,6 @@ namespace osu.Game.Overlays.SearchableList protected SearchableListHeader() { - if (!typeof(T).IsEnum) - throw new InvalidOperationException("BrowseHeader only supports enums as the generic type argument"); - RelativeSizeAxes = Axes.X; Height = 90; diff --git a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs index fb0c1d9808..37478d902b 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListOverlay.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 osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -16,19 +17,22 @@ namespace osu.Game.Overlays.SearchableList public const float WIDTH_PADDING = 80; } - public abstract class SearchableListOverlay : SearchableListOverlay + public abstract class SearchableListOverlay : SearchableListOverlay + where THeader : struct, Enum + where TTab : struct, Enum + where TCategory : struct, Enum { private readonly Container scrollContainer; - protected readonly SearchableListHeader Header; - protected readonly SearchableListFilterControl Filter; + protected readonly SearchableListHeader Header; + protected readonly SearchableListFilterControl Filter; protected readonly FillFlowContainer ScrollFlow; protected abstract Color4 BackgroundColour { get; } protected abstract Color4 TrianglesColourLight { get; } protected abstract Color4 TrianglesColourDark { get; } - protected abstract SearchableListHeader CreateHeader(); - protected abstract SearchableListFilterControl CreateFilterControl(); + protected abstract SearchableListHeader CreateHeader(); + protected abstract SearchableListFilterControl CreateFilterControl(); protected SearchableListOverlay() { diff --git a/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs b/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs index f320ef1344..9e7ff1205f 100644 --- a/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs +++ b/osu.Game/Overlays/SearchableList/SlimEnumDropdown.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 osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -11,6 +12,7 @@ using osuTK; namespace osu.Game.Overlays.SearchableList { public class SlimEnumDropdown : OsuEnumDropdown + where T : struct, Enum { protected override DropdownHeader CreateHeader() => new SlimDropdownHeader(); diff --git a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs b/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs index 9f09f251c2..c77d14632b 100644 --- a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs +++ b/osu.Game/Overlays/Settings/SettingsEnumDropdown.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 osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { public class SettingsEnumDropdown : SettingsDropdown + where T : struct, Enum { protected override OsuDropdown CreateDropdown() => new DropdownControl(); From ad1fb3bda2b75bb357d4bd2b8930af7d533e3384 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 9 Dec 2019 17:48:41 +0800 Subject: [PATCH 4379/5608] Remove IComparable in constraint. --- osu.Game/Screens/Select/FilterCriteria.cs | 2 +- osu.Game/Screens/Select/FilterQueryParser.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index abcb1f2171..e3ad76ac35 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Select } public struct OptionalRange : IEquatable> - where T : struct, IComparable + where T : struct { public bool HasFilter => Max != null || Min != null; diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index ffe1258168..89afc729fe 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -170,7 +170,7 @@ namespace osu.Game.Screens.Select } private static void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value) - where T : struct, IComparable + where T : struct { switch (op) { From 1e49078c526f2050a137f087cf0000f678f3484e Mon Sep 17 00:00:00 2001 From: mcendu Date: Mon, 9 Dec 2019 17:51:44 +0800 Subject: [PATCH 4380/5608] Add OsuCursorSprite --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs new file mode 100644 index 0000000000..56c04ce1fc --- /dev/null +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs @@ -0,0 +1,13 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Rulesets.Osu.UI.Cursor +{ + public class OsuCursorSprite : CompositeDrawable + { + public Drawable ExpandTarget { get; protected set; } + } +} From 22f2a4bed2284ab2fa81f7cfbb4a6a17f56ecb27 Mon Sep 17 00:00:00 2001 From: mcendu Date: Mon, 9 Dec 2019 17:53:16 +0800 Subject: [PATCH 4381/5608] Fix LegacyCursor's cursormiddle expanding --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 8 ++++---- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs | 18 +++++++++++------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index 05b38ae195..cf133f54ea 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -5,13 +5,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Skinning; +using osu.Game.Rulesets.Osu.UI.Cursor; using osuTK; namespace osu.Game.Rulesets.Osu.Skinning { - public class LegacyCursor : CompositeDrawable + public class LegacyCursor : OsuCursorSprite { - private NonPlayfieldSprite cursor; private bool spin; public LegacyCursor() @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Osu.Skinning Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - cursor = new NonPlayfieldSprite + ExpandTarget = new NonPlayfieldSprite { Texture = skin.GetTexture("cursor"), Anchor = Anchor.Centre, @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Osu.Skinning protected override void LoadComplete() { if (spin) - cursor.Spin(10000, RotationDirection.Clockwise); + ExpandTarget.Spin(10000, RotationDirection.Clockwise); } } } diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index 0aa8661fd3..4a67d23f57 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private bool cursorExpand; - private Container expandTarget; + private OsuCursorSprite cursorSprite; public OsuCursor() { @@ -37,17 +37,19 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor [BackgroundDependencyLoader] private void load() { - InternalChild = expandTarget = new Container + SkinnableDrawable cursor; + InternalChild = new Container { RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, Anchor = Anchor.Centre, - Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.Cursor), _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling) + Child = cursor = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.Cursor), _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling) { Origin = Anchor.Centre, Anchor = Anchor.Centre, } }; + cursorSprite = cursor.Drawable as OsuCursorSprite; } private const float pressed_scale = 1.2f; @@ -57,12 +59,12 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { if (!cursorExpand) return; - expandTarget.ScaleTo(released_scale).ScaleTo(pressed_scale, 100, Easing.OutQuad); + cursorSprite.ExpandTarget.ScaleTo(released_scale).ScaleTo(pressed_scale, 100, Easing.OutQuad); } - public void Contract() => expandTarget.ScaleTo(released_scale, 100, Easing.OutQuad); + public void Contract() => cursorSprite.ExpandTarget.ScaleTo(released_scale, 100, Easing.OutQuad); - private class DefaultCursor : CompositeDrawable + private class DefaultCursor : OsuCursorSprite { public DefaultCursor() { @@ -73,8 +75,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor InternalChildren = new Drawable[] { - new CircularContainer + ExpandTarget = new CircularContainer { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, Masking = true, BorderThickness = size / 6, From 6b667daf0965ec6386632bca78415cfe8bca1365 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Dec 2019 19:41:18 +0900 Subject: [PATCH 4382/5608] Update bindable types in line with framework --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 14 +++++++++----- .../Tests/Visual/RateAdjustedBeatmapTestScene.cs | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 96275c1274..c15b5d4786 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -511,15 +511,17 @@ namespace osu.Game.Rulesets.UI public IEnumerable GetAvailableResources() => throw new NotImplementedException(); - public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => throw new NotImplementedException(); + public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable) => throw new NotImplementedException(); - public void RemoveAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => throw new NotImplementedException(); + public void RemoveAdjustment(AdjustableProperty type, BindableNumber adjustBindable) => throw new NotImplementedException(); - public BindableDouble Volume => throw new NotImplementedException(); + public BindableNumber Volume => throw new NotImplementedException(); - public BindableDouble Balance => throw new NotImplementedException(); + public BindableNumber Balance => throw new NotImplementedException(); - public BindableDouble Frequency => throw new NotImplementedException(); + public BindableNumber Frequency => throw new NotImplementedException(); + + public BindableNumber Tempo => throw new NotImplementedException(); public IBindable AggregateVolume => throw new NotImplementedException(); @@ -527,6 +529,8 @@ namespace osu.Game.Rulesets.UI public IBindable AggregateFrequency => throw new NotImplementedException(); + public IBindable AggregateTempo => throw new NotImplementedException(); + public int PlaybackConcurrency { get => throw new NotImplementedException(); diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs index 921a1d9789..ad24ffc7b8 100644 --- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual base.Update(); // note that this will override any mod rate application - Beatmap.Value.Track.TempoAdjust = Clock.Rate; + Beatmap.Value.Track.Tempo.Value = Clock.Rate; } } } From 7fd52c21f56cdf6fdc2f9004e6b9f449e26b9bba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Dec 2019 19:41:31 +0900 Subject: [PATCH 4383/5608] Update mods and user adjust to use adjustments --- osu.Game/Rulesets/Mods/ModDaycore.cs | 3 +- osu.Game/Rulesets/Mods/ModDoubleTime.cs | 6 ++-- osu.Game/Rulesets/Mods/ModHalfTime.cs | 6 ++-- osu.Game/Rulesets/Mods/ModNightcore.cs | 3 +- .../{ModTimeAdjust.cs => ModRateAdjust.cs} | 8 +++-- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 35 +++++++++---------- .../Screens/Play/GameplayClockContainer.cs | 9 ++--- 7 files changed, 32 insertions(+), 38 deletions(-) rename osu.Game/Rulesets/Mods/{ModTimeAdjust.cs => ModRateAdjust.cs} (60%) diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index dcb3cb5597..f7da1e86db 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Sprites; @@ -15,7 +16,7 @@ namespace osu.Game.Rulesets.Mods public override void ApplyToTrack(Track track) { - track.Frequency.Value *= RateAdjust; + track.AddAdjustment(AdjustableProperty.Frequency, SpeedChange); } } } diff --git a/osu.Game/Rulesets/Mods/ModDoubleTime.cs b/osu.Game/Rulesets/Mods/ModDoubleTime.cs index b9faad8cbd..7015460c51 100644 --- a/osu.Game/Rulesets/Mods/ModDoubleTime.cs +++ b/osu.Game/Rulesets/Mods/ModDoubleTime.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics; namespace osu.Game.Rulesets.Mods { - public abstract class ModDoubleTime : ModTimeAdjust + public abstract class ModDoubleTime : ModRateAdjust { public override string Name => "Double Time"; public override string Acronym => "DT"; @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModHalfTime)).ToArray(); [SettingSource("Speed increase", "The actual increase to apply")] - public BindableNumber SpeedChange { get; } = new BindableDouble + public override BindableNumber SpeedChange { get; } = new BindableDouble { MinValue = 1.01, MaxValue = 2, @@ -30,7 +30,5 @@ namespace osu.Game.Rulesets.Mods Value = 1.5, Precision = 0.01, }; - - protected override double RateAdjust => SpeedChange.Value; } } diff --git a/osu.Game/Rulesets/Mods/ModHalfTime.cs b/osu.Game/Rulesets/Mods/ModHalfTime.cs index 255c5b7065..15f7afa312 100644 --- a/osu.Game/Rulesets/Mods/ModHalfTime.cs +++ b/osu.Game/Rulesets/Mods/ModHalfTime.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics; namespace osu.Game.Rulesets.Mods { - public abstract class ModHalfTime : ModTimeAdjust + public abstract class ModHalfTime : ModRateAdjust { public override string Name => "Half Time"; public override string Acronym => "HT"; @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModDoubleTime)).ToArray(); [SettingSource("Speed decrease", "The actual decrease to apply")] - public BindableNumber SpeedChange { get; } = new BindableDouble + public override BindableNumber SpeedChange { get; } = new BindableDouble { MinValue = 0.5, MaxValue = 0.99, @@ -30,7 +30,5 @@ namespace osu.Game.Rulesets.Mods Value = 0.75, Precision = 0.01, }; - - protected override double RateAdjust => SpeedChange.Value; } } diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index a4f1ef5a72..e41f1415ab 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; @@ -16,7 +17,7 @@ namespace osu.Game.Rulesets.Mods public override void ApplyToTrack(Track track) { - track.Frequency.Value *= RateAdjust; + track.AddAdjustment(AdjustableProperty.Frequency, SpeedChange); } } } diff --git a/osu.Game/Rulesets/Mods/ModTimeAdjust.cs b/osu.Game/Rulesets/Mods/ModRateAdjust.cs similarity index 60% rename from osu.Game/Rulesets/Mods/ModTimeAdjust.cs rename to osu.Game/Rulesets/Mods/ModRateAdjust.cs index f137a75ed8..5aa3e09fee 100644 --- a/osu.Game/Rulesets/Mods/ModTimeAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModRateAdjust.cs @@ -2,19 +2,21 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Audio; using osu.Framework.Audio.Track; +using osu.Framework.Bindables; namespace osu.Game.Rulesets.Mods { - public abstract class ModTimeAdjust : Mod, IApplicableToTrack + public abstract class ModRateAdjust : Mod, IApplicableToTrack { public override Type[] IncompatibleMods => new[] { typeof(ModTimeRamp) }; - protected abstract double RateAdjust { get; } + public abstract BindableNumber SpeedChange { get; } public virtual void ApplyToTrack(Track track) { - track.TempoAdjust *= RateAdjust; + track.AddAdjustment(AdjustableProperty.Tempo, SpeedChange); } } } diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index d95d354487..36de546707 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -3,36 +3,42 @@ using System; using System.Linq; +using osu.Framework.Audio; using osu.Framework.Audio.Track; +using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mods { - public abstract class ModTimeRamp : Mod, IUpdatableByPlayfield, IApplicableToTrack, IApplicableToBeatmap + public abstract class ModTimeRamp : Mod, IUpdatableByPlayfield, IApplicableToBeatmap, IApplicableToTrack { /// /// The point in the beatmap at which the final ramping rate should be reached. /// private const double final_rate_progress = 0.75f; - public override Type[] IncompatibleMods => new[] { typeof(ModTimeAdjust) }; + public override Type[] IncompatibleMods => new[] { typeof(ModRateAdjust) }; protected abstract double FinalRateAdjustment { get; } private double finalRateTime; private double beginRampTime; + + public BindableNumber SpeedChange { get; } = new BindableDouble + { + Default = 1, + Value = 1, + Precision = 0.01, + }; + private Track track; - public virtual void ApplyToTrack(Track track) + public void ApplyToTrack(Track track) { this.track = track; - - lastAdjust = 1; - - // for preview purposes. during gameplay, Update will overwrite this setting. - applyAdjustment(1); + track.AddAdjustment(AdjustableProperty.Frequency, SpeedChange); } public virtual void ApplyToBeatmap(IBeatmap beatmap) @@ -48,20 +54,11 @@ namespace osu.Game.Rulesets.Mods applyAdjustment((track.CurrentTime - beginRampTime) / finalRateTime); } - private double lastAdjust = 1; - /// /// Adjust the rate along the specified ramp /// /// The amount of adjustment to apply (from 0..1). - private void applyAdjustment(double amount) - { - double adjust = 1 + (Math.Sign(FinalRateAdjustment) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); - - track.Tempo.Value /= lastAdjust; - track.Tempo.Value *= lastAdjust; - - lastAdjust = adjust; - } + private void applyAdjustment(double amount) => + SpeedChange.Value = 1 + (Math.Sign(FinalRateAdjustment) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); } } diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 2cc03ae453..9f46fddc5e 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Play private readonly double firstHitObjectTime; - public readonly Bindable UserPlaybackRate = new BindableDouble(1) + public readonly BindableNumber UserPlaybackRate = new BindableDouble(1) { Default = 1, MinValue = 0.5, @@ -73,7 +73,6 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both; track = beatmap.Track; - track.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; @@ -120,7 +119,6 @@ namespace osu.Game.Screens.Play Seek(startTime); adjustableClock.ProcessFrame(); - UserPlaybackRate.ValueChanged += _ => updateRate(); } public void Restart() @@ -223,7 +221,8 @@ namespace osu.Game.Screens.Play speedAdjustmentsApplied = true; track.ResetSpeedAdjustments(); - track.Tempo.Value = UserPlaybackRate.Value; + track.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); + track.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate); foreach (var mod in mods.OfType()) mod.ApplyToTrack(track); @@ -244,8 +243,6 @@ namespace osu.Game.Screens.Play track.ResetSpeedAdjustments(); speedAdjustmentsApplied = false; } - - track.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); } } } From edc82205543106251bba5a9b8a2c92ea3b81e7ad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Dec 2019 19:58:51 +0900 Subject: [PATCH 4384/5608] Add time ramp settings --- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 8 ++++++-- osu.Game/Rulesets/Mods/ModWindDown.cs | 12 +++++++++++- osu.Game/Rulesets/Mods/ModWindUp.cs | 12 +++++++++++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 36de546707..bffe4f7b70 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -7,6 +7,7 @@ using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Objects; @@ -21,7 +22,8 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => new[] { typeof(ModRateAdjust) }; - protected abstract double FinalRateAdjustment { get; } + [SettingSource("Final rate", "The final speed to ramp to")] + public abstract BindableNumber FinalRate { get; } private double finalRateTime; private double beginRampTime; @@ -45,6 +47,8 @@ namespace osu.Game.Rulesets.Mods { HitObject lastObject = beatmap.HitObjects.LastOrDefault(); + SpeedChange.SetDefault(); + beginRampTime = beatmap.HitObjects.FirstOrDefault()?.StartTime ?? 0; finalRateTime = final_rate_progress * (lastObject?.GetEndTime() ?? 0); } @@ -59,6 +63,6 @@ namespace osu.Game.Rulesets.Mods /// /// The amount of adjustment to apply (from 0..1). private void applyAdjustment(double amount) => - SpeedChange.Value = 1 + (Math.Sign(FinalRateAdjustment) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); + SpeedChange.Value = 1 + (Math.Sign(FinalRate.Value) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRate.Value)); } } diff --git a/osu.Game/Rulesets/Mods/ModWindDown.cs b/osu.Game/Rulesets/Mods/ModWindDown.cs index b2e3abb59d..680c1a10fb 100644 --- a/osu.Game/Rulesets/Mods/ModWindDown.cs +++ b/osu.Game/Rulesets/Mods/ModWindDown.cs @@ -3,7 +3,9 @@ using System; using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; namespace osu.Game.Rulesets.Mods { @@ -15,7 +17,15 @@ namespace osu.Game.Rulesets.Mods public override IconUsage Icon => FontAwesome.Solid.ChevronCircleDown; public override double ScoreMultiplier => 1.0; - protected override double FinalRateAdjustment => -0.25; + [SettingSource("Final rate", "The speed increase to ramp towards")] + public override BindableNumber FinalRate { get; } = new BindableDouble + { + MinValue = -0.5, + MaxValue = -0.01, + Default = -0.25, + Value = -0.25, + Precision = 0.01, + }; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindUp)).ToArray(); } diff --git a/osu.Game/Rulesets/Mods/ModWindUp.cs b/osu.Game/Rulesets/Mods/ModWindUp.cs index 8df35a1de2..ca9ce0ea3e 100644 --- a/osu.Game/Rulesets/Mods/ModWindUp.cs +++ b/osu.Game/Rulesets/Mods/ModWindUp.cs @@ -3,7 +3,9 @@ using System; using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; namespace osu.Game.Rulesets.Mods { @@ -15,7 +17,15 @@ namespace osu.Game.Rulesets.Mods public override IconUsage Icon => FontAwesome.Solid.ChevronCircleUp; public override double ScoreMultiplier => 1.0; - protected override double FinalRateAdjustment => 0.5; + [SettingSource("Final rate", "The speed increase to ramp towards")] + public override BindableNumber FinalRate { get; } = new BindableDouble + { + MinValue = 0.01, + MaxValue = 2, + Default = 1.5, + Value = 1.5, + Precision = 0.01, + }; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindDown)).ToArray(); } From 47f3c4a596a3b0b8f54e492dd723644e1665241f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 20:18:18 +0900 Subject: [PATCH 4385/5608] Don't serialise path version --- osu.Game/Rulesets/Objects/SliderPath.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 6a151d7d33..86deba3b93 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -18,6 +18,7 @@ namespace osu.Game.Rulesets.Objects /// /// The current version of this . Updated when any change to the path occurs. /// + [JsonIgnore] public IBindable Version => version; private readonly Bindable version = new Bindable(); From 12bdb1dafd98d09db5af10de7961b8ee17c94a05 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Dec 2019 20:40:38 +0900 Subject: [PATCH 4386/5608] Pin DC/NC pitch --- osu.Game/Rulesets/Mods/ModDaycore.cs | 13 ++++++++++++- osu.Game/Rulesets/Mods/ModNightcore.cs | 13 ++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index f7da1e86db..474e793dd1 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -3,6 +3,7 @@ using osu.Framework.Audio; using osu.Framework.Audio.Track; +using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; namespace osu.Game.Rulesets.Mods @@ -14,9 +15,19 @@ namespace osu.Game.Rulesets.Mods public override IconUsage Icon => FontAwesome.Solid.Question; public override string Description => "Whoaaaaa..."; + private readonly BindableNumber tempoAdjust = new BindableDouble(1); + private readonly BindableNumber freqAdjust = new BindableDouble(1); + public override void ApplyToTrack(Track track) { - track.AddAdjustment(AdjustableProperty.Frequency, SpeedChange); + track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); + track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); + + SpeedChange.BindValueChanged(val => + { + freqAdjust.Value = SpeedChange.Default; + tempoAdjust.Value = val.NewValue / SpeedChange.Default; + }, true); } } } diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index e41f1415ab..401814d18b 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -3,6 +3,7 @@ using osu.Framework.Audio; using osu.Framework.Audio.Track; +using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; @@ -15,9 +16,19 @@ namespace osu.Game.Rulesets.Mods public override IconUsage Icon => OsuIcon.ModNightcore; public override string Description => "Uguuuuuuuu..."; + private readonly BindableNumber tempoAdjust = new BindableDouble(1); + private readonly BindableNumber freqAdjust = new BindableDouble(1); + public override void ApplyToTrack(Track track) { - track.AddAdjustment(AdjustableProperty.Frequency, SpeedChange); + track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); + track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); + + SpeedChange.BindValueChanged(val => + { + freqAdjust.Value = SpeedChange.Default; + tempoAdjust.Value = val.NewValue / SpeedChange.Default; + }, true); } } } From af90b45c407a0cbad892224204e83e5c6cfe0778 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 20:49:59 +0900 Subject: [PATCH 4387/5608] Refactor path visualisers to use bindables --- .../Components/PathControlPointPiece.cs | 116 ++++++++++++------ .../Components/PathControlPointVisualiser.cs | 34 +++-- 2 files changed, 98 insertions(+), 52 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 4fe02135c4..38da5939b6 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -11,6 +11,8 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osuTK; using osuTK.Graphics; @@ -20,10 +22,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public class PathControlPointPiece : BlueprintPiece { - public Action RequestSelection; + public Action RequestSelection; public readonly BindableBool IsSelected = new BindableBool(); - public readonly int Index; + + public readonly PathControlPoint ControlPoint; private readonly Slider slider; private readonly Path path; @@ -36,10 +39,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components [Resolved] private OsuColour colours { get; set; } - public PathControlPointPiece(Slider slider, int index) + private IBindable sliderPosition; + private IBindable pathVersion; + + public PathControlPointPiece(Slider slider, PathControlPoint controlPoint) { this.slider = slider; - Index = index; + + ControlPoint = controlPoint; Origin = Anchor.Centre; AutoSizeAxes = Axes.Both; @@ -85,48 +92,41 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components }; } - protected override void Update() + protected override void LoadComplete() { - base.Update(); + base.LoadComplete(); - Position = slider.StackedPosition + slider.Path.ControlPoints[Index].Position.Value; + sliderPosition = slider.PositionBindable.GetBoundCopy(); + sliderPosition.BindValueChanged(_ => updateDisplay()); + pathVersion = slider.Path.Version.GetBoundCopy(); + pathVersion.BindValueChanged(_ => updateDisplay()); + + IsSelected.BindValueChanged(_ => updateMarkerDisplay()); + + updateDisplay(); + } + + private void updateDisplay() + { updateMarkerDisplay(); updateConnectingPath(); } - /// - /// Updates the state of the circular control point marker. - /// - private void updateMarkerDisplay() - { - markerRing.Alpha = IsSelected.Value ? 1 : 0; - - Color4 colour = slider.Path.ControlPoints[Index].Type.Value.HasValue ? colours.Red : colours.Yellow; - if (IsHovered || IsSelected.Value) - colour = Color4.White; - marker.Colour = colour; - } - - /// - /// Updates the path connecting this control point to the previous one. - /// - private void updateConnectingPath() - { - path.ClearVertices(); - - if (Index != slider.Path.ControlPoints.Count - 1) - { - path.AddVertex(Vector2.Zero); - path.AddVertex(slider.Path.ControlPoints[Index + 1].Position.Value - slider.Path.ControlPoints[Index].Position.Value); - } - - path.OriginPosition = path.PositionInBoundingBox(Vector2.Zero); - } - // The connecting path is excluded from positional input public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => marker.ReceivePositionalInputAt(screenSpacePos); + protected override bool OnHover(HoverEvent e) + { + updateMarkerDisplay(); + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateMarkerDisplay(); + } + protected override bool OnMouseDown(MouseDownEvent e) { if (RequestSelection == null) @@ -135,12 +135,12 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components switch (e.Button) { case MouseButton.Left: - RequestSelection.Invoke(Index, e); + RequestSelection.Invoke(this, e); return true; case MouseButton.Right: if (!IsSelected.Value) - RequestSelection.Invoke(Index, e); + RequestSelection.Invoke(this, e); return false; // Allow context menu to show } @@ -155,7 +155,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components protected override bool OnDrag(DragEvent e) { - if (Index == 0) + if (ControlPoint == slider.Path.ControlPoints[0]) { // Special handling for the head control point - the position of the slider changes which means the snapped position and time have to be taken into account (Vector2 snappedPosition, double snappedTime) = snapProvider?.GetSnappedPosition(e.MousePosition, slider.StartTime) ?? (e.MousePosition, slider.StartTime); @@ -169,11 +169,47 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components slider.Path.ControlPoints[i].Position.Value -= movementDelta; } else - slider.Path.ControlPoints[Index].Position.Value += e.Delta; + ControlPoint.Position.Value += e.Delta; return true; } protected override bool OnDragEnd(DragEndEvent e) => true; + + /// + /// Updates the state of the circular control point marker. + /// + private void updateMarkerDisplay() + { + Position = slider.StackedPosition + ControlPoint.Position.Value; + + markerRing.Alpha = IsSelected.Value ? 1 : 0; + + Color4 colour = ControlPoint.Type.Value != null ? colours.Red : colours.Yellow; + if (IsHovered || IsSelected.Value) + colour = Color4.White; + marker.Colour = colour; + } + + /// + /// Updates the path connecting this control point to the previous one. + /// + private void updateConnectingPath() + { + path.ClearVertices(); + + int index = slider.Path.ControlPoints.IndexOf(ControlPoint); + + if (index == -1) + return; + + if (++index != slider.Path.ControlPoints.Count) + { + path.AddVertex(Vector2.Zero); + path.AddVertex(slider.Path.ControlPoints[index].Position.Value - ControlPoint.Position.Value); + } + + path.OriginPosition = path.PositionInBoundingBox(Vector2.Zero); + } } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 434e74ddeb..eb6e3c01e1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using Humanizer; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -32,6 +33,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components [Resolved(CanBeNull = true)] private IPlacementHandler placementHandler { get; set; } + private IBindableList controlPoints; + public PathControlPointVisualiser(Slider slider, bool allowSelection) { this.slider = slider; @@ -47,24 +50,31 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components base.LoadComplete(); inputManager = GetContainingInputManager(); + + controlPoints = slider.Path.ControlPoints.GetBoundCopy(); + controlPoints.ItemsAdded += addControlPoints; + controlPoints.ItemsRemoved += removeControlPoints; + + addControlPoints(controlPoints); } - protected override void Update() + private void addControlPoints(IEnumerable controlPoints) { - base.Update(); - - while (slider.Path.ControlPoints.Count > Pieces.Count) + foreach (var point in controlPoints) { - var piece = new PathControlPointPiece(slider, Pieces.Count); + var piece = new PathControlPointPiece(slider, point); if (allowSelection) piece.RequestSelection = selectPiece; Pieces.Add(piece); } + } - while (slider.Path.ControlPoints.Count < Pieces.Count) - Pieces.Remove(Pieces[Pieces.Count - 1]); + private void removeControlPoints(IEnumerable controlPoints) + { + foreach (var point in controlPoints) + Pieces.RemoveAll(p => p.ControlPoint == point); } protected override bool OnClick(ClickEvent e) @@ -87,20 +97,20 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; - private void selectPiece(int index, MouseButtonEvent e) + private void selectPiece(PathControlPointPiece piece, MouseButtonEvent e) { if (e.Button == MouseButton.Left && inputManager.CurrentState.Keyboard.ControlPressed) - Pieces[index].IsSelected.Toggle(); + piece.IsSelected.Toggle(); else { - foreach (var piece in Pieces) - piece.IsSelected.Value = piece.Index == index; + foreach (var p in Pieces) + p.IsSelected.Value = p == piece; } } private bool deleteSelected() { - List toRemove = Pieces.Where(p => p.IsSelected.Value).Select(p => slider.Path.ControlPoints[p.Index]).ToList(); + List toRemove = Pieces.Where(p => p.IsSelected.Value).Select(p => p.ControlPoint).ToList(); // Ensure that there are any points to be deleted if (toRemove.Count == 0) From bd2b0af2695048a1f5baae9cbde9f80a18e28957 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 22:35:19 +0900 Subject: [PATCH 4388/5608] Consider having only 1 control point as being deleted --- .../Sliders/Components/PathControlPointVisualiser.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 434e74ddeb..f7692c64f4 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -116,8 +116,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components slider.Path.ControlPoints.Remove(c); } - // If there are 0 remaining control points, treat the slider as being deleted - if (slider.Path.ControlPoints.Count == 0) + // If there are 0 or 1 remaining control points, the slider is in a degenerate (single point) form and should be deleted + if (slider.Path.ControlPoints.Count <= 1) { placementHandler?.Delete(slider); return true; From 2c4c190f15238574285407bd7fd5925b22c1c768 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 22:44:47 +0900 Subject: [PATCH 4389/5608] Fix control points not adding to last segment --- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 7431972673..68873093a6 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders int insertionIndex = 0; float minDistance = float.MaxValue; - for (int i = 0; i < HitObject.Path.ControlPoints.Count - 2; i++) + for (int i = 0; i < HitObject.Path.ControlPoints.Count - 1; i++) { float dist = new Line(HitObject.Path.ControlPoints[i].Position.Value, HitObject.Path.ControlPoints[i + 1].Position.Value).DistanceToPoint(position); From 0ee303f7d6417130079bd7862938e78c403c0e19 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Dec 2019 22:45:44 +0900 Subject: [PATCH 4390/5608] Remove unused using --- .../Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 38da5939b6..7c66f38854 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -12,7 +12,6 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osuTK; using osuTK.Graphics; From 9b318d2869a99a97f7e213946b7993fac71cf972 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Dec 2019 00:07:07 +0900 Subject: [PATCH 4391/5608] Add right-click menu item to change path type --- .../Components/PathControlPointPiece.cs | 2 +- .../Components/PathControlPointVisualiser.cs | 45 ++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 7c66f38854..c2aefac587 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -118,7 +118,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components protected override bool OnHover(HoverEvent e) { updateMarkerDisplay(); - return true; + return false; } protected override void OnHoverLost(HoverLostEvent e) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index eb6e3c01e1..352bb56030 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using Humanizer; @@ -15,6 +16,7 @@ using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose; using osuTK; @@ -161,9 +163,50 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return new MenuItem[] { - new OsuMenuItem($"Delete {"control point".ToQuantity(selectedPoints)}", MenuItemType.Destructive, () => deleteSelected()) + new OsuMenuItem($"Delete {"control point".ToQuantity(selectedPoints)}", MenuItemType.Destructive, () => deleteSelected()), + new OsuMenuItem("Type") + { + Items = new[] + { + createMenuItemForPathType(null), + createMenuItemForPathType(PathType.Linear), + createMenuItemForPathType(PathType.PerfectCurve), + createMenuItemForPathType(PathType.Catmull) + } + } }; } } + + private MenuItem createMenuItemForPathType(PathType? type) + { + int totalCount = Pieces.Count(p => p.IsSelected.Value); + int countOfState = Pieces.Where(p => p.IsSelected.Value).Count(p => p.ControlPoint.Type.Value == type); + + var item = new PathTypeMenuItem(type, () => + { + foreach (var p in Pieces.Where(p => p.IsSelected.Value)) + p.ControlPoint.Type.Value = type; + }); + + if (countOfState == totalCount) + item.State.Value = TernaryState.True; + else if (countOfState > 0) + item.State.Value = TernaryState.Indeterminate; + else + item.State.Value = TernaryState.False; + + return item; + } + + private class PathTypeMenuItem : TernaryStateMenuItem + { + public PathTypeMenuItem(PathType? type, Action action) + : base(type == null ? "Inherit" : type.ToString().Humanize(), changeState, MenuItemType.Standard, _ => action?.Invoke()) + { + } + + private static TernaryState changeState(TernaryState state) => TernaryState.True; + } } } From 1b14b0e5b6cecdbfacbf44024f2ff0fa42252d93 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Dec 2019 00:08:38 +0900 Subject: [PATCH 4392/5608] Fix pieces blocking context menu --- .../Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 7c66f38854..c2aefac587 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -118,7 +118,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components protected override bool OnHover(HoverEvent e) { updateMarkerDisplay(); - return true; + return false; } protected override void OnHoverLost(HoverLostEvent e) From 1e71681916b3fe6473da6f3fda1e2fb35f9dc7fd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Dec 2019 02:00:39 +0900 Subject: [PATCH 4393/5608] Fix osu!catch catcher not scaling down correctly --- osu.Game.Rulesets.Catch/UI/CatcherSprite.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherSprite.cs b/osu.Game.Rulesets.Catch/UI/CatcherSprite.cs index e3c6c93d01..025fa9c56e 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherSprite.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherSprite.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.UI [BackgroundDependencyLoader] private void load() { - InternalChild = new SkinnableSprite("Gameplay/catch/fruit-catcher-idle") + InternalChild = new SkinnableSprite("Gameplay/catch/fruit-catcher-idle", confineMode: ConfineMode.ScaleDownToFit) { RelativeSizeAxes = Axes.Both, Anchor = Anchor.TopCentre, From dc9775742ca0dfc20f65e9de2d043c714a6f1a61 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Dec 2019 02:23:17 +0900 Subject: [PATCH 4394/5608] Fix incorrect code migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bartłomiej Dach --- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index d95d354487..839b2ae36e 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Mods double adjust = 1 + (Math.Sign(FinalRateAdjustment) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); track.Tempo.Value /= lastAdjust; - track.Tempo.Value *= lastAdjust; + track.Tempo.Value *= adjust; lastAdjust = adjust; } From cdde5d1d690adf16a02cc8b48cdb85467f68fb61 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Dec 2019 02:30:23 +0900 Subject: [PATCH 4395/5608] Fix song select filters not reapplied if in a child screen Closes https://github.com/ppy/osu/issues/6980. --- .../SongSelect/TestScenePlaySongSelect.cs | 36 +++++++++++++++++++ .../Visual/TestSceneOsuScreenStack.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 8 ++--- osu.Game/Tests/Visual/ScreenTestScene.cs | 10 +++--- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index a4b8d1a24a..5dd02c1ddd 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -95,6 +95,42 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("filter count is 1", () => songSelect.FilterCount == 1); } + [Test] + public void TestNoFilterOnSimpleResume() + { + addRulesetImportStep(0); + addRulesetImportStep(0); + + createSongSelect(); + + AddStep("push child screen", () => Stack.Push(new TestSceneOsuScreenStack.TestScreen("test child"))); + AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen()); + + AddStep("return", () => songSelect.MakeCurrent()); + AddUntilStep("wait for current", () => songSelect.IsCurrentScreen()); + AddAssert("filter count is 1", () => songSelect.FilterCount == 1); + } + + [Test] + public void TestFilterOnResumeAfterChange() + { + addRulesetImportStep(0); + addRulesetImportStep(0); + + AddStep("change convert setting", () => config.Set(OsuSetting.ShowConvertedBeatmaps, false)); + + createSongSelect(); + + AddStep("push child screen", () => Stack.Push(new TestSceneOsuScreenStack.TestScreen("test child"))); + AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen()); + + AddStep("change convert setting", () => config.Set(OsuSetting.ShowConvertedBeatmaps, true)); + + AddStep("return", () => songSelect.MakeCurrent()); + AddUntilStep("wait for current", () => songSelect.IsCurrentScreen()); + AddAssert("filter count is 2", () => songSelect.FilterCount == 2); + } + [Test] public void TestAudioResuming() { diff --git a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs index a68fd0ef40..c55988d1bb 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual AddAssert("Parallax is off", () => stack.ParallaxAmount == 0); } - private class TestScreen : ScreenWithBeatmapBackground + public class TestScreen : ScreenWithBeatmapBackground { private readonly string screenText; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index a52edb70db..8f7ad2022d 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -262,8 +262,10 @@ namespace osu.Game.Screens.Select protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) { - if (this.IsCurrentScreen()) - Carousel.Filter(criteria); + // if not the current screen, we want to get carousel in a good presentation state before displaying (resume or enter). + bool shouldDebounce = this.IsCurrentScreen(); + + Schedule(() => Carousel.Filter(criteria, shouldDebounce)); } private DependencyContainer dependencies; @@ -437,8 +439,6 @@ namespace osu.Game.Screens.Select { base.OnEntering(last); - Carousel.Filter(FilterControl.CreateCriteria(), false); - this.FadeInFromZero(250); FilterControl.Activate(); } diff --git a/osu.Game/Tests/Visual/ScreenTestScene.cs b/osu.Game/Tests/Visual/ScreenTestScene.cs index 23f45e0d0f..707aa61283 100644 --- a/osu.Game/Tests/Visual/ScreenTestScene.cs +++ b/osu.Game/Tests/Visual/ScreenTestScene.cs @@ -12,7 +12,7 @@ namespace osu.Game.Tests.Visual /// public abstract class ScreenTestScene : ManualInputManagerTestScene { - private readonly OsuScreenStack stack; + protected readonly OsuScreenStack Stack; private readonly Container content; @@ -22,16 +22,16 @@ namespace osu.Game.Tests.Visual { base.Content.AddRange(new Drawable[] { - stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, + Stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, content = new Container { RelativeSizeAxes = Axes.Both } }); } protected void LoadScreen(OsuScreen screen) { - if (stack.CurrentScreen != null) - stack.Exit(); - stack.Push(screen); + if (Stack.CurrentScreen != null) + Stack.Exit(); + Stack.Push(screen); } } } From 1db218f9082749578b8af301d7a329c677b8dfe1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Dec 2019 03:29:25 +0900 Subject: [PATCH 4396/5608] Don't show count when deleting only one control point Reads better. --- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index cdca48490e..629604357d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -154,7 +154,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return new MenuItem[] { - new OsuMenuItem($"Delete {"control point".ToQuantity(selectedPoints)}", MenuItemType.Destructive, () => deleteSelected()) + new OsuMenuItem($"Delete {"control point".ToQuantity(selectedPoints, selectedPoints > 1 ? ShowQuantityAs.Numeric : ShowQuantityAs.None)}", MenuItemType.Destructive, () => deleteSelected()) }; } } From e9ec6591a907209bda53c4dc8fce87805b7d3e67 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Dec 2019 11:20:08 +0900 Subject: [PATCH 4397/5608] Separate path connections from control points --- .../Components/PathControlPointConnection.cs | 72 +++++++++++++++++++ .../Components/PathControlPointPiece.cs | 43 ++--------- .../Components/PathControlPointVisualiser.cs | 22 ++++-- 3 files changed, 92 insertions(+), 45 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnection.cs diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnection.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnection.cs new file mode 100644 index 0000000000..f57299c5a9 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnection.cs @@ -0,0 +1,72 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Lines; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components +{ + public class PathControlPointConnection : CompositeDrawable + { + public PathControlPoint ControlPoint; + + private readonly Path path; + private readonly Slider slider; + + private IBindable sliderPosition; + private IBindable pathVersion; + + public PathControlPointConnection(Slider slider, PathControlPoint controlPoint) + { + this.slider = slider; + ControlPoint = controlPoint; + + Origin = Anchor.Centre; + AutoSizeAxes = Axes.Both; + + InternalChild = path = new SmoothPath + { + Anchor = Anchor.Centre, + PathRadius = 1 + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + sliderPosition = slider.PositionBindable.GetBoundCopy(); + sliderPosition.BindValueChanged(_ => updateConnectingPath()); + + pathVersion = slider.Path.Version.GetBoundCopy(); + pathVersion.BindValueChanged(_ => updateConnectingPath()); + + updateConnectingPath(); + } + + /// + /// Updates the path connecting this control point to the next one. + /// + private void updateConnectingPath() + { + Position = slider.StackedPosition + ControlPoint.Position.Value; + + path.ClearVertices(); + + int index = slider.Path.ControlPoints.IndexOf(ControlPoint) + 1; + + if (index == 0 || index == slider.Path.ControlPoints.Count) + return; + + path.AddVertex(Vector2.Zero); + path.AddVertex(slider.Path.ControlPoints[index].Position.Value - ControlPoint.Position.Value); + + path.OriginPosition = path.PositionInBoundingBox(Vector2.Zero); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index c2aefac587..42812ff934 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -6,7 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Lines; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics; @@ -28,7 +27,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public readonly PathControlPoint ControlPoint; private readonly Slider slider; - private readonly Path path; private readonly Container marker; private readonly Drawable markerRing; @@ -39,12 +37,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private OsuColour colours { get; set; } private IBindable sliderPosition; - private IBindable pathVersion; + private IBindable controlPointPosition; public PathControlPointPiece(Slider slider, PathControlPoint controlPoint) { this.slider = slider; - ControlPoint = controlPoint; Origin = Anchor.Centre; @@ -52,11 +49,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components InternalChildren = new Drawable[] { - path = new SmoothPath - { - Anchor = Anchor.Centre, - PathRadius = 1 - }, marker = new Container { Anchor = Anchor.Centre, @@ -96,20 +88,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components base.LoadComplete(); sliderPosition = slider.PositionBindable.GetBoundCopy(); - sliderPosition.BindValueChanged(_ => updateDisplay()); + sliderPosition.BindValueChanged(_ => updateMarkerDisplay()); - pathVersion = slider.Path.Version.GetBoundCopy(); - pathVersion.BindValueChanged(_ => updateDisplay()); + controlPointPosition = ControlPoint.Position.GetBoundCopy(); + controlPointPosition.BindValueChanged(_ => updateMarkerDisplay()); IsSelected.BindValueChanged(_ => updateMarkerDisplay()); - updateDisplay(); - } - - private void updateDisplay() - { updateMarkerDisplay(); - updateConnectingPath(); } // The connecting path is excluded from positional input @@ -189,26 +175,5 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components colour = Color4.White; marker.Colour = colour; } - - /// - /// Updates the path connecting this control point to the previous one. - /// - private void updateConnectingPath() - { - path.ClearVertices(); - - int index = slider.Path.ControlPoints.IndexOf(ControlPoint); - - if (index == -1) - return; - - if (++index != slider.Path.ControlPoints.Count) - { - path.AddVertex(Vector2.Zero); - path.AddVertex(slider.Path.ControlPoints[index].Position.Value - ControlPoint.Position.Value); - } - - path.OriginPosition = path.PositionInBoundingBox(Vector2.Zero); - } } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index eb6e3c01e1..e45dc1d47a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -25,6 +25,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler, IHasContextMenu { internal readonly Container Pieces; + + private readonly Container connections; private readonly Slider slider; private readonly bool allowSelection; @@ -42,7 +44,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components RelativeSizeAxes = Axes.Both; - InternalChild = Pieces = new Container { RelativeSizeAxes = Axes.Both }; + InternalChildren = new Drawable[] + { + connections = new Container { RelativeSizeAxes = Axes.Both }, + Pieces = new Container { RelativeSizeAxes = Axes.Both } + }; } protected override void LoadComplete() @@ -62,19 +68,23 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { foreach (var point in controlPoints) { - var piece = new PathControlPointPiece(slider, point); + Pieces.Add(new PathControlPointPiece(slider, point).With(d => + { + if (allowSelection) + d.RequestSelection = selectPiece; + })); - if (allowSelection) - piece.RequestSelection = selectPiece; - - Pieces.Add(piece); + connections.Add(new PathControlPointConnection(slider, point)); } } private void removeControlPoints(IEnumerable controlPoints) { foreach (var point in controlPoints) + { Pieces.RemoveAll(p => p.ControlPoint == point); + connections.RemoveAll(c => c.ControlPoint == point); + } } protected override bool OnClick(ClickEvent e) From ab0f2e7c6a1c1692a115ca54512344a162ec2230 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Dec 2019 13:12:54 +0900 Subject: [PATCH 4398/5608] Apply suggested refactorings --- .../Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 9 ++++----- osu.Game/Rulesets/Objects/PathControlPoint.cs | 7 +++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 1ac7284772..b5b1e26486 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -257,14 +257,13 @@ namespace osu.Game.Rulesets.Objects.Legacy { if (type == PathType.PerfectCurve) { - if (vertices.Length == 3) + if (vertices.Length != 3) + type = PathType.Bezier; + else if (isLinear(vertices)) { // osu-stable special-cased colinear perfect curves to a linear path - if (isLinear(vertices)) - type = PathType.Linear; + type = PathType.Linear; } - else - type = PathType.Bezier; } var points = new List(vertices.Length) diff --git a/osu.Game/Rulesets/Objects/PathControlPoint.cs b/osu.Game/Rulesets/Objects/PathControlPoint.cs index 5737d3f618..0336f94313 100644 --- a/osu.Game/Rulesets/Objects/PathControlPoint.cs +++ b/osu.Game/Rulesets/Objects/PathControlPoint.cs @@ -30,8 +30,9 @@ namespace osu.Game.Rulesets.Objects /// Creates a new . /// public PathControlPoint() - : this(Vector2.Zero, null) { + Position.ValueChanged += _ => Changed?.Invoke(); + Type.ValueChanged += _ => Changed?.Invoke(); } /// @@ -40,12 +41,10 @@ namespace osu.Game.Rulesets.Objects /// The initial position. /// The initial type. public PathControlPoint(Vector2 position, PathType? type = null) + : this() { Position.Value = position; Type.Value = type; - - Position.ValueChanged += _ => Changed?.Invoke(); - Type.ValueChanged += _ => Changed?.Invoke(); } public bool Equals(PathControlPoint other) => Position.Value == other?.Position.Value && Type.Value == other.Type.Value; From 94a298a82d5e965ff54e63e56b332c78af50f775 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Dec 2019 16:00:09 +0900 Subject: [PATCH 4399/5608] Refactor distance snap grid to not require hitobjects --- .../Edit/OsuDistanceSnapGrid.cs | 5 +- .../Editor/TestSceneDistanceSnapGrid.cs | 29 ++++++----- .../Components/CircularDistanceSnapGrid.cs | 25 +++++----- .../Compose/Components/DistanceSnapGrid.cs | 50 +++++++++---------- 4 files changed, 52 insertions(+), 57 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs index 9b00204d51..bde86a2890 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.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 JetBrains.Annotations; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose.Components; @@ -8,8 +9,8 @@ namespace osu.Game.Rulesets.Osu.Edit { public class OsuDistanceSnapGrid : CircularDistanceSnapGrid { - public OsuDistanceSnapGrid(OsuHitObject hitObject, OsuHitObject nextHitObject) - : base(hitObject, nextHitObject, hitObject.StackedEndPosition) + public OsuDistanceSnapGrid(OsuHitObject hitObject, [CanBeNull] OsuHitObject nextHitObject = null) + : base(hitObject.StackedPosition, hitObject.StartTime, nextHitObject?.StartTime) { Masking = true; } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index e4c987923c..39b4bf7218 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit; @@ -44,7 +43,7 @@ namespace osu.Game.Tests.Visual.Editor RelativeSizeAxes = Axes.Both, Colour = Color4.SlateGray }, - new TestDistanceSnapGrid(new HitObject(), grid_position) + new TestDistanceSnapGrid() }; }); @@ -73,7 +72,7 @@ namespace osu.Game.Tests.Visual.Editor RelativeSizeAxes = Axes.Both, Colour = Color4.SlateGray }, - new TestDistanceSnapGrid(new HitObject(), grid_position, new HitObject { StartTime = 100 }) + new TestDistanceSnapGrid(100) }; }); } @@ -82,68 +81,68 @@ namespace osu.Game.Tests.Visual.Editor { public new float DistanceSpacing => base.DistanceSpacing; - public TestDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition, HitObject nextHitObject = null) - : base(hitObject, nextHitObject, centrePosition) + public TestDistanceSnapGrid(double? endTime = null) + : base(grid_position, 0, endTime) { } - protected override void CreateContent(Vector2 centrePosition) + protected override void CreateContent(Vector2 startPosition) { AddInternal(new Circle { Origin = Anchor.Centre, Size = new Vector2(5), - Position = centrePosition + Position = startPosition }); int beatIndex = 0; - for (float s = centrePosition.X + DistanceSpacing; s <= DrawWidth && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++) + for (float s = startPosition.X + DistanceSpacing; s <= DrawWidth && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++) { AddInternal(new Circle { Origin = Anchor.Centre, Size = new Vector2(5, 10), - Position = new Vector2(s, centrePosition.Y), + Position = new Vector2(s, startPosition.Y), Colour = GetColourForBeatIndex(beatIndex) }); } beatIndex = 0; - for (float s = centrePosition.X - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++) + for (float s = startPosition.X - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++) { AddInternal(new Circle { Origin = Anchor.Centre, Size = new Vector2(5, 10), - Position = new Vector2(s, centrePosition.Y), + Position = new Vector2(s, startPosition.Y), Colour = GetColourForBeatIndex(beatIndex) }); } beatIndex = 0; - for (float s = centrePosition.Y + DistanceSpacing; s <= DrawHeight && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++) + for (float s = startPosition.Y + DistanceSpacing; s <= DrawHeight && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++) { AddInternal(new Circle { Origin = Anchor.Centre, Size = new Vector2(10, 5), - Position = new Vector2(centrePosition.X, s), + Position = new Vector2(startPosition.X, s), Colour = GetColourForBeatIndex(beatIndex) }); } beatIndex = 0; - for (float s = centrePosition.Y - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++) + for (float s = startPosition.Y - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++) { AddInternal(new Circle { Origin = Anchor.Centre, Size = new Vector2(10, 5), - Position = new Vector2(centrePosition.X, s), + Position = new Vector2(startPosition.X, s), Colour = GetColourForBeatIndex(beatIndex) }); } diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 91e19f9cc0..23ed10b92d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -5,19 +5,18 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; -using osu.Game.Rulesets.Objects; using osuTK; namespace osu.Game.Screens.Edit.Compose.Components { public abstract class CircularDistanceSnapGrid : DistanceSnapGrid { - protected CircularDistanceSnapGrid(HitObject hitObject, HitObject nextHitObject, Vector2 centrePosition) - : base(hitObject, nextHitObject, centrePosition) + protected CircularDistanceSnapGrid(Vector2 startPosition, double startTime, double? endTime = null) + : base(startPosition, startTime, endTime) { } - protected override void CreateContent(Vector2 centrePosition) + protected override void CreateContent(Vector2 startPosition) { const float crosshair_thickness = 1; const float crosshair_max_size = 10; @@ -27,7 +26,7 @@ namespace osu.Game.Screens.Edit.Compose.Components new Box { Origin = Anchor.Centre, - Position = centrePosition, + Position = startPosition, Width = crosshair_thickness, EdgeSmoothness = new Vector2(1), Height = Math.Min(crosshair_max_size, DistanceSpacing * 2), @@ -35,15 +34,15 @@ namespace osu.Game.Screens.Edit.Compose.Components new Box { Origin = Anchor.Centre, - Position = centrePosition, + Position = startPosition, EdgeSmoothness = new Vector2(1), Width = Math.Min(crosshair_max_size, DistanceSpacing * 2), Height = crosshair_thickness, } }); - float dx = Math.Max(centrePosition.X, DrawWidth - centrePosition.X); - float dy = Math.Max(centrePosition.Y, DrawHeight - centrePosition.Y); + float dx = Math.Max(startPosition.X, DrawWidth - startPosition.X); + float dy = Math.Max(startPosition.Y, DrawHeight - startPosition.Y); float maxDistance = new Vector2(dx, dy).Length; int requiredCircles = Math.Min(MaxIntervals, (int)(maxDistance / DistanceSpacing)); @@ -54,7 +53,7 @@ namespace osu.Game.Screens.Edit.Compose.Components AddInternal(new CircularProgress { Origin = Anchor.Centre, - Position = centrePosition, + Position = startPosition, Current = { Value = 1 }, Size = new Vector2(radius), InnerRadius = 4 * 1f / radius, @@ -66,9 +65,9 @@ namespace osu.Game.Screens.Edit.Compose.Components public override (Vector2 position, double time) GetSnappedPosition(Vector2 position) { if (MaxIntervals == 0) - return (CentrePosition, StartTime); + return (StartPosition, StartTime); - Vector2 direction = position - CentrePosition; + Vector2 direction = position - StartPosition; if (direction == Vector2.Zero) direction = new Vector2(0.001f, 0.001f); @@ -78,9 +77,9 @@ namespace osu.Game.Screens.Edit.Compose.Components int radialCount = Math.Clamp((int)MathF.Round(distance / radius), 1, MaxIntervals); Vector2 normalisedDirection = direction * new Vector2(1f / distance); - Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; + Vector2 snappedPosition = StartPosition + normalisedDirection * radialCount * radius; - return (snappedPosition, StartTime + SnapProvider.GetSnappedDurationFromDistance(StartTime, (snappedPosition - CentrePosition).Length)); + return (snappedPosition, StartTime + SnapProvider.GetSnappedDurationFromDistance(StartTime, (snappedPosition - StartPosition).Length)); } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 9508a2cdf0..00326d04f7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.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 JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Graphics; @@ -9,7 +8,6 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Objects; using osuTK; namespace osu.Game.Screens.Edit.Compose.Components @@ -24,21 +22,21 @@ namespace osu.Game.Screens.Edit.Compose.Components /// protected float DistanceSpacing { get; private set; } - /// - /// The snapping time at . - /// - protected double StartTime { get; private set; } - /// /// The maximum number of distance snapping intervals allowed. /// protected int MaxIntervals { get; private set; } /// - /// The position which the grid is centred on. - /// The first beat snapping tick is located at + in the desired direction. + /// The position which the grid should start. + /// The first beat snapping tick is located at + away from this point. /// - protected readonly Vector2 CentrePosition; + protected readonly Vector2 StartPosition; + + /// + /// The snapping time at . + /// + protected readonly double StartTime; [Resolved] protected OsuColour Colours { get; private set; } @@ -53,25 +51,23 @@ namespace osu.Game.Screens.Edit.Compose.Components private BindableBeatDivisor beatDivisor { get; set; } private readonly Cached gridCache = new Cached(); - private readonly HitObject hitObject; - private readonly HitObject nextHitObject; + private readonly double? endTime; - protected DistanceSnapGrid(HitObject hitObject, [CanBeNull] HitObject nextHitObject, Vector2 centrePosition) + /// + /// Creates a new . + /// + /// The position at which the grid should start. The first tick is located one distance spacing length away from this point. + /// The snapping time at . + /// The time at which the snapping grid should end. If null, the grid will continue until the bounds of the screen are exceeded. + protected DistanceSnapGrid(Vector2 startPosition, double startTime, double? endTime = null) { - this.hitObject = hitObject; - this.nextHitObject = nextHitObject; - - CentrePosition = centrePosition; + this.endTime = endTime; + StartPosition = startPosition; + StartTime = startTime; RelativeSizeAxes = Axes.Both; } - [BackgroundDependencyLoader] - private void load() - { - StartTime = hitObject.GetEndTime(); - } - protected override void LoadComplete() { base.LoadComplete(); @@ -83,12 +79,12 @@ namespace osu.Game.Screens.Edit.Compose.Components { DistanceSpacing = SnapProvider.GetBeatSnapDistanceAt(StartTime); - if (nextHitObject == null) + if (endTime == null) MaxIntervals = int.MaxValue; else { // +1 is added since a snapped hitobject may have its start time slightly less than the snapped time due to floating point errors - double maxDuration = nextHitObject.StartTime - StartTime + 1; + double maxDuration = endTime.Value - StartTime + 1; MaxIntervals = (int)(maxDuration / SnapProvider.DistanceToDuration(StartTime, DistanceSpacing)); } @@ -110,7 +106,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (!gridCache.IsValid) { ClearInternal(); - CreateContent(CentrePosition); + CreateContent(StartPosition); gridCache.Validate(); } } @@ -118,7 +114,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Creates the content which visualises the grid ticks. /// - protected abstract void CreateContent(Vector2 centrePosition); + protected abstract void CreateContent(Vector2 startPosition); /// /// Snaps a position to this grid. From 609c51130964ccb85e00160be1556ec4aa7bec61 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Dec 2019 16:43:58 +0900 Subject: [PATCH 4400/5608] 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 301c615ce4..914d352070 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 ef16738908..473ce82443 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 5090190f28..d03005012a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From f7f4a57c5f6b1b3d64bec8c22461e261c05bae97 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Dec 2019 19:41:18 +0900 Subject: [PATCH 4401/5608] Update bindable types in line with framework --- osu.Game/Rulesets/Mods/ModTimeAdjust.cs | 2 +- osu.Game/Rulesets/UI/DrawableRuleset.cs | 16 +++++++++++----- .../Tests/Visual/RateAdjustedBeatmapTestScene.cs | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModTimeAdjust.cs b/osu.Game/Rulesets/Mods/ModTimeAdjust.cs index f137a75ed8..7d0cc2a7c3 100644 --- a/osu.Game/Rulesets/Mods/ModTimeAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModTimeAdjust.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mods public virtual void ApplyToTrack(Track track) { - track.TempoAdjust *= RateAdjust; + track.Tempo.Value *= RateAdjust; } } } diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 96275c1274..a856974292 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -511,15 +511,19 @@ namespace osu.Game.Rulesets.UI public IEnumerable GetAvailableResources() => throw new NotImplementedException(); - public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => throw new NotImplementedException(); + public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable) => throw new NotImplementedException(); - public void RemoveAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => throw new NotImplementedException(); + public void RemoveAdjustment(AdjustableProperty type, BindableNumber adjustBindable) => throw new NotImplementedException(); - public BindableDouble Volume => throw new NotImplementedException(); + public BindableNumber Volume => throw new NotImplementedException(); - public BindableDouble Balance => throw new NotImplementedException(); + public BindableNumber Balance => throw new NotImplementedException(); - public BindableDouble Frequency => throw new NotImplementedException(); + public BindableNumber Frequency => throw new NotImplementedException(); + + public BindableNumber Tempo => throw new NotImplementedException(); + + public IBindable GetAggregate(AdjustableProperty type) => throw new NotImplementedException(); public IBindable AggregateVolume => throw new NotImplementedException(); @@ -527,6 +531,8 @@ namespace osu.Game.Rulesets.UI public IBindable AggregateFrequency => throw new NotImplementedException(); + public IBindable AggregateTempo => throw new NotImplementedException(); + public int PlaybackConcurrency { get => throw new NotImplementedException(); diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs index 921a1d9789..ad24ffc7b8 100644 --- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual base.Update(); // note that this will override any mod rate application - Beatmap.Value.Track.TempoAdjust = Clock.Rate; + Beatmap.Value.Track.Tempo.Value = Clock.Rate; } } } From 65f2d1f8757f809eb5f33b639abc5e7b338b6060 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Dec 2019 17:49:42 +0900 Subject: [PATCH 4402/5608] 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 914d352070..3cd4dc48bf 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 473ce82443..530d62f583 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 d03005012a..fb753b8c6f 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 55c938e5daa07a0a471d313645c172d5372ba73c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Dec 2019 18:08:11 +0900 Subject: [PATCH 4403/5608] Fix bindable usage --- osu.Game/Online/DownloadTrackingComposite.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/DownloadTrackingComposite.cs b/osu.Game/Online/DownloadTrackingComposite.cs index dcec17788a..9a0e112727 100644 --- a/osu.Game/Online/DownloadTrackingComposite.cs +++ b/osu.Game/Online/DownloadTrackingComposite.cs @@ -26,7 +26,7 @@ namespace osu.Game.Online /// protected readonly Bindable State = new Bindable(); - protected readonly Bindable Progress = new Bindable(); + protected readonly BindableNumber Progress = new BindableNumber { MinValue = 0, MaxValue = 1 }; protected DownloadTrackingComposite(TModel model = null) { From f593caf0eaa4d8750d314d16f17278c7fdc178d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Dec 2019 18:08:51 +0900 Subject: [PATCH 4404/5608] Remove unused class --- .../Blueprints/Sliders/SliderPlacementBlueprint.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index c004b6db28..9b820261ab 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.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.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input; @@ -191,15 +190,5 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders Initial, Body, } - - private class Segment - { - public readonly List ControlPoints = new List(); - - public Segment(Vector2 offset) - { - ControlPoints.Add(offset); - } - } } } From 48976f5d0e0e14663ac8b5d5c1f106c0fd592f1f Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 9 Dec 2019 21:46:29 +0800 Subject: [PATCH 4405/5608] Add VS launcher profile for tournament client. --- osu.Desktop/Properties/launchSettings.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 osu.Desktop/Properties/launchSettings.json diff --git a/osu.Desktop/Properties/launchSettings.json b/osu.Desktop/Properties/launchSettings.json new file mode 100644 index 0000000000..5e768ec9fa --- /dev/null +++ b/osu.Desktop/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "osu! Desktop": { + "commandName": "Project" + }, + "osu! Tournament": { + "commandName": "Project", + "commandLineArgs": "--tournament" + } + } +} \ No newline at end of file From 8012b21ffae925fc610fd23d96b334ea50d37e8f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Dec 2019 20:04:37 +0900 Subject: [PATCH 4406/5608] Extract legacy sound type enum --- .../Beatmaps/Legacy/LegacyHitSoundType.cs | 14 +++++++++++ .../Objects/Legacy/ConvertHitObjectParser.cs | 24 ++++++------------- 2 files changed, 21 insertions(+), 17 deletions(-) create mode 100644 osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs diff --git a/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs b/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs new file mode 100644 index 0000000000..69adbf8f67 --- /dev/null +++ b/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs @@ -0,0 +1,14 @@ +using System; + +namespace osu.Game.Beatmaps.Legacy +{ + [Flags] + internal enum LegacyHitSoundType + { + None = 0, + Normal = 1, + Whistle = 2, + Finish = 4, + Clap = 8 + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index b5b1e26486..c22955cbf1 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -54,7 +54,7 @@ namespace osu.Game.Rulesets.Objects.Legacy bool combo = type.HasFlag(ConvertHitObjectType.NewCombo); type &= ~ConvertHitObjectType.NewCombo; - var soundType = (LegacySoundType)Parsing.ParseInt(split[4]); + var soundType = (LegacyHitSoundType)Parsing.ParseInt(split[4]); var bankInfo = new SampleBankInfo(); HitObject result = null; @@ -157,7 +157,7 @@ namespace osu.Game.Rulesets.Objects.Legacy } // Populate node sound types with the default hit object sound type - var nodeSoundTypes = new List(); + var nodeSoundTypes = new List(); for (int i = 0; i < nodes; i++) nodeSoundTypes.Add(soundType); @@ -172,7 +172,7 @@ namespace osu.Game.Rulesets.Objects.Legacy break; int.TryParse(adds[i], out var sound); - nodeSoundTypes[i] = (LegacySoundType)sound; + nodeSoundTypes[i] = (LegacyHitSoundType)sound; } } @@ -333,7 +333,7 @@ namespace osu.Game.Rulesets.Objects.Legacy /// The hold end time. protected abstract HitObject CreateHold(Vector2 position, bool newCombo, int comboOffset, double endTime); - private List convertSoundType(LegacySoundType type, SampleBankInfo bankInfo) + private List convertSoundType(LegacyHitSoundType type, SampleBankInfo bankInfo) { // Todo: This should return the normal SampleInfos if the specified sample file isn't found, but that's a pretty edge-case scenario if (!string.IsNullOrEmpty(bankInfo.Filename)) @@ -359,7 +359,7 @@ namespace osu.Game.Rulesets.Objects.Legacy } }; - if (type.HasFlag(LegacySoundType.Finish)) + if (type.HasFlag(LegacyHitSoundType.Finish)) { soundTypes.Add(new LegacyHitSampleInfo { @@ -370,7 +370,7 @@ namespace osu.Game.Rulesets.Objects.Legacy }); } - if (type.HasFlag(LegacySoundType.Whistle)) + if (type.HasFlag(LegacyHitSoundType.Whistle)) { soundTypes.Add(new LegacyHitSampleInfo { @@ -381,7 +381,7 @@ namespace osu.Game.Rulesets.Objects.Legacy }); } - if (type.HasFlag(LegacySoundType.Clap)) + if (type.HasFlag(LegacyHitSoundType.Clap)) { soundTypes.Add(new LegacyHitSampleInfo { @@ -430,15 +430,5 @@ namespace osu.Game.Rulesets.Objects.Legacy Path.ChangeExtension(Filename, null) }; } - - [Flags] - private enum LegacySoundType - { - None = 0, - Normal = 1, - Whistle = 2, - Finish = 4, - Clap = 8 - } } } From e3f925f69afd6bb69081729c5f419c2af43208bb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Dec 2019 20:19:16 +0900 Subject: [PATCH 4407/5608] Extract legacy hitobject type enum --- .../Beatmaps/Legacy/LegacyHitObjectType.cs | 15 +++++++++++++++ .../Objects/Legacy/ConvertHitObjectParser.cs | 19 ++++++++++--------- .../Objects/Legacy/ConvertHitObjectType.cs | 18 ------------------ 3 files changed, 25 insertions(+), 27 deletions(-) create mode 100644 osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs delete mode 100644 osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs diff --git a/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs b/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs new file mode 100644 index 0000000000..9223f7df31 --- /dev/null +++ b/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs @@ -0,0 +1,15 @@ +using System; + +namespace osu.Game.Beatmaps.Legacy +{ + [Flags] + internal enum LegacyHitObjectType + { + Circle = 1, + Slider = 1 << 1, + NewCombo = 1 << 2, + Spinner = 1 << 3, + ComboOffset = (1 << 4) | (1 << 5) | (1 << 6), + Hold = 1 << 7 + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index c22955cbf1..b83c67acff 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -11,6 +11,7 @@ using osu.Game.Audio; using System.Linq; using JetBrains.Annotations; using osu.Framework.MathUtils; +using osu.Game.Beatmaps.Legacy; namespace osu.Game.Rulesets.Objects.Legacy { @@ -46,27 +47,27 @@ namespace osu.Game.Rulesets.Objects.Legacy double startTime = Parsing.ParseDouble(split[2]) + Offset; - ConvertHitObjectType type = (ConvertHitObjectType)Parsing.ParseInt(split[3]); + LegacyHitObjectType type = (LegacyHitObjectType)Parsing.ParseInt(split[3]); - int comboOffset = (int)(type & ConvertHitObjectType.ComboOffset) >> 4; - type &= ~ConvertHitObjectType.ComboOffset; + int comboOffset = (int)(type & LegacyHitObjectType.ComboOffset) >> 4; + type &= ~LegacyHitObjectType.ComboOffset; - bool combo = type.HasFlag(ConvertHitObjectType.NewCombo); - type &= ~ConvertHitObjectType.NewCombo; + bool combo = type.HasFlag(LegacyHitObjectType.NewCombo); + type &= ~LegacyHitObjectType.NewCombo; var soundType = (LegacyHitSoundType)Parsing.ParseInt(split[4]); var bankInfo = new SampleBankInfo(); HitObject result = null; - if (type.HasFlag(ConvertHitObjectType.Circle)) + if (type.HasFlag(LegacyHitObjectType.Circle)) { result = CreateHit(pos, combo, comboOffset); if (split.Length > 5) readCustomSampleBanks(split[5], bankInfo); } - else if (type.HasFlag(ConvertHitObjectType.Slider)) + else if (type.HasFlag(LegacyHitObjectType.Slider)) { PathType pathType = PathType.Catmull; double? length = null; @@ -186,7 +187,7 @@ namespace osu.Game.Rulesets.Objects.Legacy // The samples are played when the slider ends, which is the last node result.Samples = nodeSamples[nodeSamples.Count - 1]; } - else if (type.HasFlag(ConvertHitObjectType.Spinner)) + else if (type.HasFlag(LegacyHitObjectType.Spinner)) { double endTime = Math.Max(startTime, Parsing.ParseDouble(split[5]) + Offset); @@ -195,7 +196,7 @@ namespace osu.Game.Rulesets.Objects.Legacy if (split.Length > 6) readCustomSampleBanks(split[6], bankInfo); } - else if (type.HasFlag(ConvertHitObjectType.Hold)) + else if (type.HasFlag(LegacyHitObjectType.Hold)) { // Note: Hold is generated by BMS converts diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs deleted file mode 100644 index eab37b682c..0000000000 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; - -namespace osu.Game.Rulesets.Objects.Legacy -{ - [Flags] - internal enum ConvertHitObjectType - { - Circle = 1, - Slider = 1 << 1, - NewCombo = 1 << 2, - Spinner = 1 << 3, - ComboOffset = (1 << 4) | (1 << 5) | (1 << 6), - Hold = 1 << 7 - } -} From 3c18872a16605e4dc87261a520cdbc5ecb27e921 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Dec 2019 20:19:31 +0900 Subject: [PATCH 4408/5608] Extract legacy effect flags enum --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 15 ++++----------- osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs | 12 ++++++++++++ 2 files changed, 16 insertions(+), 11 deletions(-) create mode 100644 osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 838b1c2f07..ff4e6503ee 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -10,6 +10,7 @@ using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Beatmaps.ControlPoints; using osu.Game.IO; +using osu.Game.Beatmaps.Legacy; namespace osu.Game.Beatmaps.Formats { @@ -358,9 +359,9 @@ namespace osu.Game.Beatmaps.Formats if (split.Length >= 8) { - EffectFlags effectFlags = (EffectFlags)Parsing.ParseInt(split[7]); - kiaiMode = effectFlags.HasFlag(EffectFlags.Kiai); - omitFirstBarSignature = effectFlags.HasFlag(EffectFlags.OmitFirstBarLine); + LegacyEffectFlags effectFlags = (LegacyEffectFlags)Parsing.ParseInt(split[7]); + kiaiMode = effectFlags.HasFlag(LegacyEffectFlags.Kiai); + omitFirstBarSignature = effectFlags.HasFlag(LegacyEffectFlags.OmitFirstBarLine); } string stringSampleSet = sampleSet.ToString().ToLowerInvariant(); @@ -448,13 +449,5 @@ namespace osu.Game.Beatmaps.Formats private double getOffsetTime(double time) => time + (ApplyOffsets ? offset : 0); protected virtual TimingControlPoint CreateTimingControlPoint() => new TimingControlPoint(); - - [Flags] - internal enum EffectFlags - { - None = 0, - Kiai = 1, - OmitFirstBarLine = 8 - } } } diff --git a/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs b/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs new file mode 100644 index 0000000000..ce141031fd --- /dev/null +++ b/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs @@ -0,0 +1,12 @@ +using System; + +namespace osu.Game.Beatmaps.Legacy +{ + [Flags] + internal enum LegacyEffectFlags + { + None = 0, + Kiai = 1, + OmitFirstBarLine = 8 + } +} From c378e525dae265a0d513090a002e2cc235a04415 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Dec 2019 20:23:15 +0900 Subject: [PATCH 4409/5608] Extract the rest of legacy enums --- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 8 ++-- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 37 ------------------- .../Formats/LegacyStoryboardDecoder.cs | 11 +++--- osu.Game/Beatmaps/Legacy/LegacyEventType.cs | 13 +++++++ osu.Game/Beatmaps/Legacy/LegacyOrigins.cs | 16 ++++++++ osu.Game/Beatmaps/Legacy/LegacySampleBank.cs | 10 +++++ osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs | 10 +++++ .../Objects/Legacy/ConvertHitObjectParser.cs | 4 +- 8 files changed, 61 insertions(+), 48 deletions(-) create mode 100644 osu.Game/Beatmaps/Legacy/LegacyEventType.cs create mode 100644 osu.Game/Beatmaps/Legacy/LegacyOrigins.cs create mode 100644 osu.Game/Beatmaps/Legacy/LegacySampleBank.cs create mode 100644 osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index ff4e6503ee..1b24e2953b 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -294,22 +294,22 @@ namespace osu.Game.Beatmaps.Formats { string[] split = line.Split(','); - if (!Enum.TryParse(split[0], out EventType type)) + if (!Enum.TryParse(split[0], out LegacyEventType type)) throw new InvalidDataException($@"Unknown event type: {split[0]}"); switch (type) { - case EventType.Background: + case LegacyEventType.Background: string bgFilename = split[2].Trim('"'); beatmap.BeatmapInfo.Metadata.BackgroundFile = FileSafety.PathStandardise(bgFilename); break; - case EventType.Video: + case LegacyEventType.Video: string videoFilename = split[2].Trim('"'); beatmap.BeatmapInfo.Metadata.VideoFile = FileSafety.PathStandardise(videoFilename); break; - case EventType.Break: + case LegacyEventType.Break: double start = getOffsetTime(Parsing.ParseDouble(split[1])); var breakEvent = new BreakPeriod diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 2b914669cb..1c2ca4b6f8 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -148,46 +148,9 @@ namespace osu.Game.Beatmaps.Formats Fonts } - internal enum LegacySampleBank - { - None = 0, - Normal = 1, - Soft = 2, - Drum = 3 - } - internal enum EventType - { - Background = 0, - Video = 1, - Break = 2, - Colour = 3, - Sprite = 4, - Sample = 5, - Animation = 6 - } - internal enum LegacyOrigins - { - TopLeft, - Centre, - CentreLeft, - TopRight, - BottomCentre, - TopCentre, - Custom, - CentreRight, - BottomLeft, - BottomRight - } - internal enum StoryLayer - { - Background = 0, - Fail = 1, - Pass = 2, - Foreground = 3 - } internal class LegacyDifficultyControlPoint : DifficultyControlPoint { diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index f94ab3f27b..b8323edc23 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics; using osu.Framework.IO.File; using osu.Game.IO; using osu.Game.Storyboards; +using osu.Game.Beatmaps.Legacy; namespace osu.Game.Beatmaps.Formats { @@ -83,12 +84,12 @@ namespace osu.Game.Beatmaps.Formats { storyboardSprite = null; - if (!Enum.TryParse(split[0], out EventType type)) + if (!Enum.TryParse(split[0], out LegacyEventType type)) throw new InvalidDataException($@"Unknown event type: {split[0]}"); switch (type) { - case EventType.Sprite: + case LegacyEventType.Sprite: { var layer = parseLayer(split[1]); var origin = parseOrigin(split[2]); @@ -100,7 +101,7 @@ namespace osu.Game.Beatmaps.Formats break; } - case EventType.Animation: + case LegacyEventType.Animation: { var layer = parseLayer(split[1]); var origin = parseOrigin(split[2]); @@ -115,7 +116,7 @@ namespace osu.Game.Beatmaps.Formats break; } - case EventType.Sample: + case LegacyEventType.Sample: { var time = double.Parse(split[1], CultureInfo.InvariantCulture); var layer = parseLayer(split[2]); @@ -271,7 +272,7 @@ namespace osu.Game.Beatmaps.Formats } } - private string parseLayer(string value) => Enum.Parse(typeof(StoryLayer), value).ToString(); + private string parseLayer(string value) => Enum.Parse(typeof(LegacyStoryLayer), value).ToString(); private Anchor parseOrigin(string value) { diff --git a/osu.Game/Beatmaps/Legacy/LegacyEventType.cs b/osu.Game/Beatmaps/Legacy/LegacyEventType.cs new file mode 100644 index 0000000000..57b1e6c29f --- /dev/null +++ b/osu.Game/Beatmaps/Legacy/LegacyEventType.cs @@ -0,0 +1,13 @@ +namespace osu.Game.Beatmaps.Legacy +{ + internal enum LegacyEventType + { + Background = 0, + Video = 1, + Break = 2, + Colour = 3, + Sprite = 4, + Sample = 5, + Animation = 6 + } +} diff --git a/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs b/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs new file mode 100644 index 0000000000..93c8920761 --- /dev/null +++ b/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs @@ -0,0 +1,16 @@ +namespace osu.Game.Beatmaps.Legacy +{ + internal enum LegacyOrigins + { + TopLeft, + Centre, + CentreLeft, + TopRight, + BottomCentre, + TopCentre, + Custom, + CentreRight, + BottomLeft, + BottomRight + } +} diff --git a/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs b/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs new file mode 100644 index 0000000000..0d54998d15 --- /dev/null +++ b/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs @@ -0,0 +1,10 @@ +namespace osu.Game.Beatmaps.Legacy +{ + internal enum LegacySampleBank + { + None = 0, + Normal = 1, + Soft = 2, + Drum = 3 + } +} diff --git a/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs b/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs new file mode 100644 index 0000000000..509f39f830 --- /dev/null +++ b/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs @@ -0,0 +1,10 @@ +namespace osu.Game.Beatmaps.Legacy +{ + internal enum LegacyStoryLayer + { + Background = 0, + Fail = 1, + Pass = 2, + Foreground = 3 + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index b83c67acff..d3682de73f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -232,8 +232,8 @@ namespace osu.Game.Rulesets.Objects.Legacy string[] split = str.Split(':'); - var bank = (LegacyBeatmapDecoder.LegacySampleBank)Parsing.ParseInt(split[0]); - var addbank = (LegacyBeatmapDecoder.LegacySampleBank)Parsing.ParseInt(split[1]); + var bank = (LegacySampleBank)Parsing.ParseInt(split[0]); + var addbank = (LegacySampleBank)Parsing.ParseInt(split[1]); string stringBank = bank.ToString().ToLowerInvariant(); if (stringBank == @"none") From 06cde2b0c22feca53459df4213f46eb82ca6d0c1 Mon Sep 17 00:00:00 2001 From: mcendu Date: Tue, 10 Dec 2019 19:30:46 +0800 Subject: [PATCH 4410/5608] remove unused using directive --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index cf133f54ea..4e027c4351 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -3,7 +3,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Game.Skinning; using osu.Game.Rulesets.Osu.UI.Cursor; using osuTK; From e37369304b7f75f67aafaa59947ca49b214a399e Mon Sep 17 00:00:00 2001 From: mcendu Date: Tue, 10 Dec 2019 19:45:06 +0800 Subject: [PATCH 4411/5608] property-ize expand target --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index 4a67d23f57..07cde5e407 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -20,7 +20,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private bool cursorExpand; - private OsuCursorSprite cursorSprite; + private SkinnableDrawable cursorSprite; + + private Drawable ExpandTarget => (cursorSprite.Drawable as OsuCursorSprite)?.ExpandTarget ?? cursorSprite; public OsuCursor() { @@ -37,19 +39,17 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor [BackgroundDependencyLoader] private void load() { - SkinnableDrawable cursor; InternalChild = new Container { RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, Anchor = Anchor.Centre, - Child = cursor = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.Cursor), _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling) + Child = cursorSprite = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.Cursor), _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling) { Origin = Anchor.Centre, Anchor = Anchor.Centre, } }; - cursorSprite = cursor.Drawable as OsuCursorSprite; } private const float pressed_scale = 1.2f; @@ -59,10 +59,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { if (!cursorExpand) return; - cursorSprite.ExpandTarget.ScaleTo(released_scale).ScaleTo(pressed_scale, 100, Easing.OutQuad); + ExpandTarget.ScaleTo(released_scale).ScaleTo(pressed_scale, 100, Easing.OutQuad); } - public void Contract() => cursorSprite.ExpandTarget.ScaleTo(released_scale, 100, Easing.OutQuad); + public void Contract() => ExpandTarget.ScaleTo(released_scale, 100, Easing.OutQuad); private class DefaultCursor : OsuCursorSprite { From 1afeaf31bcad901bceec6766d3ec7a6810b5f82b Mon Sep 17 00:00:00 2001 From: mcendu Date: Tue, 10 Dec 2019 19:58:56 +0800 Subject: [PATCH 4412/5608] make OsuCursorSprite abstract --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs index 56c04ce1fc..909c764b9e 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Rulesets.Osu.UI.Cursor { - public class OsuCursorSprite : CompositeDrawable + public abstract class OsuCursorSprite : CompositeDrawable { public Drawable ExpandTarget { get; protected set; } } From b93bbf81aa4cba9b9ad840a4c804d7419c3a25be Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 10 Dec 2019 15:10:35 +0300 Subject: [PATCH 4413/5608] Add lighten background during breaks setting --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index b71463841a..947e864a87 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -80,6 +80,7 @@ namespace osu.Game.Configuration // Gameplay Set(OsuSetting.DimLevel, 0.3, 0, 1, 0.01); Set(OsuSetting.BlurLevel, 0, 0, 1, 0.01); + Set(OsuSetting.LightenDuringBreaks, true); Set(OsuSetting.HitLighting, true); @@ -142,6 +143,7 @@ namespace osu.Game.Configuration AutoCursorSize, DimLevel, BlurLevel, + LightenDuringBreaks, ShowStoryboard, ShowVideoBackground, KeyOverlay, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index f4aa9a0144..3f8bc2b0c7 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -30,6 +30,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay KeyboardStep = 0.01f }, new SettingsCheckbox + { + LabelText = "Lighten playfield during breaks", + Bindable = config.GetBindable(OsuSetting.LightenDuringBreaks) + }, + new SettingsCheckbox { LabelText = "Show score overlay", Bindable = config.GetBindable(OsuSetting.ShowInterface) From bb078c2afc82b34bc1e9fae15cd8b09627d38892 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 10 Dec 2019 15:13:44 +0300 Subject: [PATCH 4414/5608] Lighten user-dim container if on break time --- .../Graphics/Containers/UserDimContainer.cs | 22 ++++++++++++++++--- .../Backgrounds/BackgroundScreenBeatmap.cs | 3 +++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 7683bbcd63..20f5a4fd83 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -1,11 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; +using osu.Game.Screens.Play; namespace osu.Game.Graphics.Containers { @@ -14,7 +16,9 @@ namespace osu.Game.Graphics.Containers /// public abstract class UserDimContainer : Container { - protected const float BACKGROUND_FADE_DURATION = 800; + private const float break_lighten_amount = 0.3f; + + protected const double BACKGROUND_FADE_DURATION = 800; /// /// Whether or not user-configured dim levels should be applied to the container. @@ -26,6 +30,12 @@ namespace osu.Game.Graphics.Containers /// public readonly Bindable StoryboardReplacesBackground = new Bindable(); + /// + /// Whether player is in break time. + /// Must be bound to to allow for dim adjustments in gameplay. + /// + internal readonly IBindable IsBreakTime = new Bindable(); + /// /// Whether the content of this container is currently being displayed. /// @@ -33,11 +43,14 @@ namespace osu.Game.Graphics.Containers protected Bindable UserDimLevel { get; private set; } + protected Bindable LightenDuringBreaks { get; private set; } + protected Bindable ShowStoryboard { get; private set; } protected Bindable ShowVideo { get; private set; } - protected double DimLevel => EnableUserDim.Value ? UserDimLevel.Value : 0; + private float breakLightening => LightenDuringBreaks.Value && IsBreakTime.Value ? break_lighten_amount : 0; + protected float DimLevel => Math.Max(EnableUserDim.Value ? (float)UserDimLevel.Value - breakLightening : 0, 0); protected override Container Content => dimContent; @@ -55,11 +68,14 @@ namespace osu.Game.Graphics.Containers private void load(OsuConfigManager config) { UserDimLevel = config.GetBindable(OsuSetting.DimLevel); + LightenDuringBreaks = config.GetBindable(OsuSetting.LightenDuringBreaks); ShowStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); ShowVideo = config.GetBindable(OsuSetting.ShowVideoBackground); EnableUserDim.ValueChanged += _ => UpdateVisuals(); UserDimLevel.ValueChanged += _ => UpdateVisuals(); + LightenDuringBreaks.ValueChanged += _ => UpdateVisuals(); + IsBreakTime.ValueChanged += _ => UpdateVisuals(); ShowStoryboard.ValueChanged += _ => UpdateVisuals(); ShowVideo.ValueChanged += _ => UpdateVisuals(); StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals(); @@ -84,7 +100,7 @@ namespace osu.Game.Graphics.Containers ContentDisplayed = ShowDimContent; dimContent.FadeTo(ContentDisplayed ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint); - dimContent.FadeColour(OsuColour.Gray(1 - (float)DimLevel), BACKGROUND_FADE_DURATION, Easing.OutQuint); + dimContent.FadeColour(OsuColour.Gray(1f - DimLevel), BACKGROUND_FADE_DURATION, Easing.OutQuint); } } } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 7b68460e6b..1ab3a5b533 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -38,6 +38,8 @@ namespace osu.Game.Screens.Backgrounds /// public readonly Bindable BlurAmount = new Bindable(); + internal readonly IBindable IsBreakTime = new Bindable(); + private readonly DimmableBackground dimmable; protected virtual DimmableBackground CreateFadeContainer() => new DimmableBackground { RelativeSizeAxes = Axes.Both }; @@ -48,6 +50,7 @@ namespace osu.Game.Screens.Backgrounds InternalChild = dimmable = CreateFadeContainer(); dimmable.EnableUserDim.BindTo(EnableUserDim); + dimmable.IsBreakTime.BindTo(IsBreakTime); dimmable.BlurAmount.BindTo(BlurAmount); } From 38f1a8bc170d11a3a4edacc4d058f7ef791fbd32 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 10 Dec 2019 15:14:47 +0300 Subject: [PATCH 4415/5608] Bind UserDimContainer.IsBreakTime from Player --- osu.Game/Screens/Play/Player.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d40c448452..9b372c3791 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -140,6 +140,11 @@ namespace osu.Game.Screens.Play // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); + // bind break into components that require it. + Background.IsBreakTime.BindTo(breakOverlay.IsBreakTime); + DimmableStoryboard.IsBreakTime.BindTo(breakOverlay.IsBreakTime); + DimmableVideo.IsBreakTime.BindTo(breakOverlay.IsBreakTime); + // Bind ScoreProcessor to ourselves ScoreProcessor.AllJudged += onCompletion; ScoreProcessor.Failed += onFail; From 63f66aa5fa9fa2c178910e6bb9f1a68de5e0a372 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 10 Dec 2019 15:25:03 +0300 Subject: [PATCH 4416/5608] Check by UserDimContainer.DimLevel instead --- .../Visual/Background/TestSceneUserDimContainer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index 8f71584b4d..910c462718 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -314,7 +314,7 @@ namespace osu.Game.Tests.Visual.Background config.BindWith(OsuSetting.BlurLevel, BlurLevel); } - public bool IsBackgroundDimmed() => ((FadeAccessibleBackground)Background).CurrentColour == OsuColour.Gray(1 - (float)DimLevel.Value); + public bool IsBackgroundDimmed() => ((FadeAccessibleBackground)Background).CurrentColour == OsuColour.Gray(1f - ((FadeAccessibleBackground)Background).CurrentDim); public bool IsBackgroundUndimmed() => ((FadeAccessibleBackground)Background).CurrentColour == Color4.White; @@ -404,6 +404,8 @@ namespace osu.Game.Tests.Visual.Background public float CurrentAlpha => dimmable.CurrentAlpha; + public float CurrentDim => dimmable.DimLevel; + public Vector2 CurrentBlur => Background.BlurSigma; private TestDimmableBackground dimmable; @@ -418,6 +420,8 @@ namespace osu.Game.Tests.Visual.Background { public Color4 CurrentColour => Content.Colour; public float CurrentAlpha => Content.Alpha; + + public new float DimLevel => base.DimLevel; } } } From dbe46c6cf7df3dc77eb66bdfd88679d7d88add3c Mon Sep 17 00:00:00 2001 From: mcendu Date: Tue, 10 Dec 2019 20:40:10 +0800 Subject: [PATCH 4417/5608] conform to coding styles --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 2 +- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index 4e027c4351..02152fa51e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Skinning { spin = skin.GetConfig(OsuSkinConfiguration.CursorRotate)?.Value ?? true; - InternalChildren = new Drawable[] + InternalChildren = new[] { new NonPlayfieldSprite { diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index 07cde5e407..4f3d07f208 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private SkinnableDrawable cursorSprite; - private Drawable ExpandTarget => (cursorSprite.Drawable as OsuCursorSprite)?.ExpandTarget ?? cursorSprite; + private Drawable expandTarget => (cursorSprite.Drawable as OsuCursorSprite)?.ExpandTarget ?? cursorSprite; public OsuCursor() { @@ -59,10 +59,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { if (!cursorExpand) return; - ExpandTarget.ScaleTo(released_scale).ScaleTo(pressed_scale, 100, Easing.OutQuad); + expandTarget.ScaleTo(released_scale).ScaleTo(pressed_scale, 100, Easing.OutQuad); } - public void Contract() => ExpandTarget.ScaleTo(released_scale, 100, Easing.OutQuad); + public void Contract() => expandTarget.ScaleTo(released_scale, 100, Easing.OutQuad); private class DefaultCursor : OsuCursorSprite { @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor Anchor = Anchor.Centre; Origin = Anchor.Centre; - InternalChildren = new Drawable[] + InternalChildren = new[] { ExpandTarget = new CircularContainer { From 6c1ae3bc8ac77bd1babbd0f0395071fd583a905a Mon Sep 17 00:00:00 2001 From: Albie Date: Tue, 10 Dec 2019 16:59:31 +0000 Subject: [PATCH 4418/5608] add tests --- .../Background/TestSceneUserDimContainer.cs | 17 +++++++++++++++++ .../Graphics/Containers/UserDimContainer.cs | 9 +++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index f858174ff2..ecea80d6cc 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -165,6 +165,21 @@ namespace osu.Game.Tests.Visual.Background AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied()); } + /// + /// Ensure is able to disable user-defined display settings. + /// + [Test] + public void DisableUserDisplaySettingsTest() + { + performFullSetup(); + AddStep("Enable user dim", () => player.DimmableStoryboard.EnableUserDim.Value = true); + AddStep("Set user dim to max", () => player.DimmableStoryboard.) + waitForDim(); + AddStep("Turn on IgnoreUserSettings", () => player.DimmableStoryboard.IgnoreUserSettings.Value = true); + waitForDim(); + AddAssert("Check the background is undimmed", () => player.IsBackgroundUndimmed()); + } + /// /// Ensure is properly accepting user-defined visual changes for a storyboard. /// @@ -352,6 +367,8 @@ namespace osu.Game.Tests.Visual.Background public new DimmableStoryboard DimmableStoryboard => base.DimmableStoryboard; + public bool IsBackgroundUndimmed() => ((FadeAccessibleBackground)Background).Colour == Color4.White; + // Whether or not the player should be allowed to load. public bool BlockLoad; diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 42a25a79b1..74d922704e 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; +using osuTK.Graphics; namespace osu.Game.Graphics.Containers { @@ -22,7 +23,7 @@ namespace osu.Game.Graphics.Containers public readonly Bindable EnableUserDim = new Bindable(true); /// - /// Whether or not user-configured settings relating to visibility of elements should be ignored + /// Whether or not user-configured settings relating to brightness of elements should be ignored /// public readonly Bindable IgnoreUserSettings = new Bindable(); @@ -36,14 +37,14 @@ namespace osu.Game.Graphics.Containers /// public bool ContentDisplayed { get; private set; } + public double DimLevel => EnableUserDim.Value && !IgnoreUserSettings.Value ? UserDimLevel.Value : 0; + protected Bindable UserDimLevel { get; private set; } protected Bindable ShowStoryboard { get; private set; } protected Bindable ShowVideo { get; private set; } - protected double DimLevel => EnableUserDim.Value ? UserDimLevel.Value : 0; - protected override Container Content => dimContent; private Container dimContent { get; } @@ -90,7 +91,7 @@ namespace osu.Game.Graphics.Containers ContentDisplayed = ShowDimContent; dimContent.FadeTo(ContentDisplayed ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint); - dimContent.FadeColour(OsuColour.Gray(1 - (float)DimLevel), BACKGROUND_FADE_DURATION, Easing.OutQuint); + dimContent.FadeColour(IgnoreUserSettings.Value ? OsuColour.Gray(1 - (float)DimLevel) : Color4.White, BACKGROUND_FADE_DURATION, Easing.OutQuint); } } } From 479acdcb5b670b0644a2755cd3b93396b3a95764 Mon Sep 17 00:00:00 2001 From: Albie Date: Tue, 10 Dec 2019 17:06:34 +0000 Subject: [PATCH 4419/5608] fix build bug --- osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index ecea80d6cc..8c7948ebef 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -173,7 +173,6 @@ namespace osu.Game.Tests.Visual.Background { performFullSetup(); AddStep("Enable user dim", () => player.DimmableStoryboard.EnableUserDim.Value = true); - AddStep("Set user dim to max", () => player.DimmableStoryboard.) waitForDim(); AddStep("Turn on IgnoreUserSettings", () => player.DimmableStoryboard.IgnoreUserSettings.Value = true); waitForDim(); From 12fb17572c1ce4ad6cb8f1e37b6755c11c13dc8f Mon Sep 17 00:00:00 2001 From: Albie Date: Tue, 10 Dec 2019 18:16:34 +0000 Subject: [PATCH 4420/5608] cleanup test logic --- .../Background/TestSceneUserDimContainer.cs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index 5b7900bad4..28cc7a8532 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -148,6 +148,20 @@ namespace osu.Game.Tests.Visual.Background AddAssert("Background is visible", () => songSelect.IsBackgroundVisible()); } + /// + /// Ensure is able to disable user-defined display settings. + /// + [Test] + public void DisableUserDisplaySettingsTest() + { + performFullSetup(); + AddStep("Enable user dim", () => player.DimmableStoryboard.EnableUserDim.Value = true); + waitForDim(); + AddStep("Turn on IgnoreUserSettings", () => player.DimmableStoryboard.IgnoreUserSettings.Value = true); + waitForDim(); + AddAssert("Check the background is undimmed", () => player.IsBackgroundUndimmed()); + } + /// /// Ensure is properly accepting user-defined visual changes for a background. /// @@ -165,20 +179,6 @@ namespace osu.Game.Tests.Visual.Background AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied()); } - /// - /// Ensure is able to disable user-defined display settings. - /// - [Test] - public void DisableUserDisplaySettingsTest() - { - performFullSetup(); - AddStep("Enable user dim", () => player.DimmableStoryboard.EnableUserDim.Value = true); - waitForDim(); - AddStep("Turn on IgnoreUserSettings", () => player.DimmableStoryboard.IgnoreUserSettings.Value = true); - waitForDim(); - AddAssert("Check the background is undimmed", () => player.IsBackgroundUndimmed()); - } - /// /// Ensure is properly accepting user-defined visual changes for a storyboard. /// @@ -367,7 +367,7 @@ namespace osu.Game.Tests.Visual.Background public new DimmableStoryboard DimmableStoryboard => base.DimmableStoryboard; - public bool IsBackgroundUndimmed() => ((FadeAccessibleBackground)Background).Colour == Color4.White; + public bool IsBackgroundUndimmed() => ((FadeAccessibleBackground)Background).CurrentColour == Color4.White; // Whether or not the player should be allowed to load. public bool BlockLoad; From 53daa37eaa97e3575261c333f67b68cd6ab5ad92 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 10 Dec 2019 23:06:13 +0300 Subject: [PATCH 4421/5608] Fix failing tests --- osu.Game/Screens/Play/Player.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 9b372c3791..8684798632 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -140,11 +140,6 @@ namespace osu.Game.Screens.Play // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); - // bind break into components that require it. - Background.IsBreakTime.BindTo(breakOverlay.IsBreakTime); - DimmableStoryboard.IsBreakTime.BindTo(breakOverlay.IsBreakTime); - DimmableVideo.IsBreakTime.BindTo(breakOverlay.IsBreakTime); - // Bind ScoreProcessor to ourselves ScoreProcessor.AllJudged += onCompletion; ScoreProcessor.Failed += onFail; @@ -506,6 +501,11 @@ namespace osu.Game.Screens.Play Background.EnableUserDim.Value = true; Background.BlurAmount.Value = 0; + // bind component bindables. + Background.IsBreakTime.BindTo(breakOverlay.IsBreakTime); + DimmableStoryboard.IsBreakTime.BindTo(breakOverlay.IsBreakTime); + DimmableVideo.IsBreakTime.BindTo(breakOverlay.IsBreakTime); + Background.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); DimmableStoryboard.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); From a37af311d010a1122d64ff5b8ca1c025a2ec3931 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 13:19:02 +0900 Subject: [PATCH 4422/5608] Simplify settings update logic --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 47 +++++++++++----------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index e860463b23..ec5f99dc31 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -331,32 +331,10 @@ namespace osu.Game.Overlays.Mods Ruleset.BindTo(ruleset); if (mods != null) SelectedMods.BindTo(mods); - SelectedMods.ValueChanged += updateModSettings; - Ruleset.ValueChanged += _ => ModSettingsContent.Clear(); - sampleOn = audio.Samples.Get(@"UI/check-on"); sampleOff = audio.Samples.Get(@"UI/check-off"); } - private void updateModSettings(ValueChangedEvent> selectedMods) - { - foreach (var added in selectedMods.NewValue.Except(selectedMods.OldValue)) - { - var controls = added.CreateSettingsControls().ToList(); - if (controls.Count > 0) - ModSettingsContent.Add(new ModControlSection(added) { Children = controls }); - } - - foreach (var removed in selectedMods.OldValue.Except(selectedMods.NewValue)) - ModSettingsContent.RemoveAll(section => section.Mod == removed); - - bool hasSettings = ModSettingsContent.Children.Count > 0; - CustomiseButton.Enabled.Value = hasSettings; - - if (!hasSettings) - ModSettingsContainer.Hide(); - } - public void DeselectAll() { foreach (var section in ModSectionsContainer.Children) @@ -450,12 +428,14 @@ namespace osu.Game.Overlays.Mods refreshSelectedMods(); } - private void selectedModsChanged(ValueChangedEvent> e) + private void selectedModsChanged(ValueChangedEvent> mods) { foreach (var section in ModSectionsContainer.Children) - section.SelectTypes(e.NewValue.Select(m => m.GetType()).ToList()); + section.SelectTypes(mods.NewValue.Select(m => m.GetType()).ToList()); updateMods(); + + updateModSettings(mods); } private void updateMods() @@ -480,6 +460,25 @@ namespace osu.Game.Overlays.Mods UnrankedLabel.FadeTo(ranked ? 0 : 1, 200); } + private void updateModSettings(ValueChangedEvent> selectedMods) + { + foreach (var added in selectedMods.NewValue.Except(selectedMods.OldValue)) + { + var controls = added.CreateSettingsControls().ToList(); + if (controls.Count > 0) + ModSettingsContent.Add(new ModControlSection(added) { Children = controls }); + } + + foreach (var removed in selectedMods.OldValue.Except(selectedMods.NewValue)) + ModSettingsContent.RemoveAll(section => section.Mod == removed); + + bool hasSettings = ModSettingsContent.Children.Count > 0; + CustomiseButton.Enabled.Value = hasSettings; + + if (!hasSettings) + ModSettingsContainer.Hide(); + } + private void modButtonPressed(Mod selectedMod) { if (selectedMod != null) From 5624b9fd3f981451db3c52a7da0c94bc56971a20 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 13:19:13 +0900 Subject: [PATCH 4423/5608] Fix US english --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index ec5f99dc31..e8ea43e3f2 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -235,7 +235,7 @@ namespace osu.Game.Overlays.Mods CustomiseButton = new TriangleButton { Width = 180, - Text = "Customization", + Text = "Customisation", Action = () => ModSettingsContainer.Alpha = ModSettingsContainer.Alpha == 1 ? 0 : 1, Enabled = { Value = false }, Margin = new MarginPadding From 77b9989e115fa5681e17236415cf6c01f939b863 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 14:10:35 +0900 Subject: [PATCH 4424/5608] Fix some weird private field names --- .../MathUtils/FastRandom.cs | 20 +-- .../Components/ScrollingTeamContainer.cs | 121 +++++++++--------- osu.Game/Online/Multiplayer/PlaylistItem.cs | 22 ++-- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 34 +++-- 4 files changed, 94 insertions(+), 103 deletions(-) diff --git a/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs b/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs index c721ff862a..46e427e1b7 100644 --- a/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs +++ b/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs @@ -12,14 +12,14 @@ namespace osu.Game.Rulesets.Catch.MathUtils { private const double int_to_real = 1.0 / (int.MaxValue + 1.0); private const uint int_mask = 0x7FFFFFFF; - private const uint y = 842502087; - private const uint z = 3579807591; - private const uint w = 273326509; - private uint _x, _y = y, _z = z, _w = w; + private const uint y_initial = 842502087; + private const uint z_initial = 3579807591; + private const uint w_initial = 273326509; + private uint x, y = y_initial, z = z_initial, w = w_initial; public FastRandom(int seed) { - _x = (uint)seed; + x = (uint)seed; } public FastRandom() @@ -33,11 +33,11 @@ namespace osu.Game.Rulesets.Catch.MathUtils /// The random value. public uint NextUInt() { - uint t = _x ^ (_x << 11); - _x = _y; - _y = _z; - _z = _w; - return _w = _w ^ (_w >> 19) ^ t ^ (t >> 8); + uint t = x ^ (x << 11); + x = y; + y = z; + z = w; + return w = w ^ (w >> 19) ^ t ^ (t >> 8); } /// diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index a345f93896..3ff4718b75 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -83,88 +83,81 @@ namespace osu.Game.Tournament.Screens.Drawings.Components }; } - private ScrollState _scrollState; + private ScrollState scrollState; - private ScrollState scrollState + private void setScrollState(ScrollState newstate) { - get => _scrollState; + if (scrollState == newstate) + return; - set + delayedStateChangeDelegate?.Cancel(); + + switch (scrollState = newstate) { - if (_scrollState == value) - return; + case ScrollState.Scrolling: + resetSelected(); - _scrollState = value; + OnScrollStarted?.Invoke(); - delayedStateChangeDelegate?.Cancel(); + speedTo(1000f, 200); + tracker.FadeOut(100); + break; - switch (value) - { - case ScrollState.Scrolling: - resetSelected(); + case ScrollState.Stopping: + speedTo(0f, 2000); + tracker.FadeIn(200); - OnScrollStarted?.Invoke(); + delayedStateChangeDelegate = Scheduler.AddDelayed(() => setScrollState(ScrollState.Stopped), 2300); + break; - speedTo(1000f, 200); - tracker.FadeOut(100); + case ScrollState.Stopped: + // Find closest to center + if (!Children.Any()) break; - case ScrollState.Stopping: - speedTo(0f, 2000); - tracker.FadeIn(200); + ScrollingTeam closest = null; - delayedStateChangeDelegate = Scheduler.AddDelayed(() => scrollState = ScrollState.Stopped, 2300); - break; + foreach (var c in Children) + { + if (!(c is ScrollingTeam stc)) + continue; - case ScrollState.Stopped: - // Find closest to center - if (!Children.Any()) - break; - - ScrollingTeam closest = null; - - foreach (var c in Children) + if (closest == null) { - if (!(c is ScrollingTeam stc)) - continue; - - if (closest == null) - { - closest = stc; - continue; - } - - float o = Math.Abs(c.Position.X + c.DrawWidth / 2f - DrawWidth / 2f); - float lastOffset = Math.Abs(closest.Position.X + closest.DrawWidth / 2f - DrawWidth / 2f); - - if (o < lastOffset) - closest = stc; + closest = stc; + continue; } - Trace.Assert(closest != null, "closest != null"); + float o = Math.Abs(c.Position.X + c.DrawWidth / 2f - DrawWidth / 2f); + float lastOffset = Math.Abs(closest.Position.X + closest.DrawWidth / 2f - DrawWidth / 2f); - // ReSharper disable once PossibleNullReferenceException - offset += DrawWidth / 2f - (closest.Position.X + closest.DrawWidth / 2f); + if (o < lastOffset) + closest = stc; + } - ScrollingTeam st = closest; + Trace.Assert(closest != null, "closest != null"); - availableTeams.RemoveAll(at => at == st.Team); + // ReSharper disable once PossibleNullReferenceException + offset += DrawWidth / 2f - (closest.Position.X + closest.DrawWidth / 2f); - st.Selected = true; - OnSelected?.Invoke(st.Team); + ScrollingTeam st = closest; - delayedStateChangeDelegate = Scheduler.AddDelayed(() => scrollState = ScrollState.Idle, 10000); - break; + availableTeams.RemoveAll(at => at == st.Team); - case ScrollState.Idle: - resetSelected(); + st.Selected = true; + OnSelected?.Invoke(st.Team); - OnScrollStarted?.Invoke(); + delayedStateChangeDelegate = Scheduler.AddDelayed(() => setScrollState(ScrollState.Idle), 10000); + break; - speedTo(40f, 200); - tracker.FadeOut(100); - break; - } + case ScrollState.Idle: + resetSelected(); + + OnScrollStarted?.Invoke(); + + speedTo(40f, 200); + tracker.FadeOut(100); + break; } } @@ -176,7 +169,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components availableTeams.Add(team); RemoveAll(c => c is ScrollingTeam); - scrollState = ScrollState.Idle; + setScrollState(ScrollState.Idle); } public void AddTeams(IEnumerable teams) @@ -192,7 +185,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components { availableTeams.Clear(); RemoveAll(c => c is ScrollingTeam); - scrollState = ScrollState.Idle; + setScrollState(ScrollState.Idle); } public void RemoveTeam(TournamentTeam team) @@ -217,7 +210,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components if (availableTeams.Count == 0) return; - scrollState = ScrollState.Scrolling; + setScrollState(ScrollState.Scrolling); } public void StopScrolling() @@ -232,13 +225,13 @@ namespace osu.Game.Tournament.Screens.Drawings.Components return; } - scrollState = ScrollState.Stopping; + setScrollState(ScrollState.Stopping); } protected override void LoadComplete() { base.LoadComplete(); - scrollState = ScrollState.Idle; + setScrollState(ScrollState.Idle); } protected override void UpdateAfterChildren() @@ -305,7 +298,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components private void speedTo(float value, double duration = 0, Easing easing = Easing.None) => this.TransformTo(nameof(speed), value, duration, easing); - private enum ScrollState + protected enum ScrollState { None, Idle, diff --git a/osu.Game/Online/Multiplayer/PlaylistItem.cs b/osu.Game/Online/Multiplayer/PlaylistItem.cs index e47d497d94..d13e8b31e6 100644 --- a/osu.Game/Online/Multiplayer/PlaylistItem.cs +++ b/osu.Game/Online/Multiplayer/PlaylistItem.cs @@ -45,23 +45,25 @@ namespace osu.Game.Online.Multiplayer [JsonProperty("beatmap")] private APIBeatmap apiBeatmap { get; set; } + private APIMod[] allowedModsBacking; + [JsonProperty("allowed_mods")] private APIMod[] allowedMods { get => AllowedMods.Select(m => new APIMod { Acronym = m.Acronym }).ToArray(); - set => _allowedMods = value; + set => allowedModsBacking = value; } + private APIMod[] requiredModsBacking; + [JsonProperty("required_mods")] private APIMod[] requiredMods { get => RequiredMods.Select(m => new APIMod { Acronym = m.Acronym }).ToArray(); - set => _requiredMods = value; + set => requiredModsBacking = value; } private BeatmapInfo beatmap; - private APIMod[] _allowedMods; - private APIMod[] _requiredMods; public void MapObjects(BeatmapManager beatmaps, RulesetStore rulesets) { @@ -70,20 +72,20 @@ namespace osu.Game.Online.Multiplayer Beatmap = apiBeatmap == null ? beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == BeatmapID) : apiBeatmap.ToBeatmap(rulesets); Ruleset = rulesets.GetRuleset(RulesetID); - if (_allowedMods != null) + if (allowedModsBacking != null) { AllowedMods.Clear(); - AllowedMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => _allowedMods.Any(m => m.Acronym == mod.Acronym))); + AllowedMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => allowedModsBacking.Any(m => m.Acronym == mod.Acronym))); - _allowedMods = null; + allowedModsBacking = null; } - if (_requiredMods != null) + if (requiredModsBacking != null) { RequiredMods.Clear(); - RequiredMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => _requiredMods.Any(m => m.Acronym == mod.Acronym))); + RequiredMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => requiredModsBacking.Any(m => m.Acronym == mod.Acronym))); - _requiredMods = null; + requiredModsBacking = null; } } diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index f54d638584..2fa5098890 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -188,26 +188,22 @@ namespace osu.Game.Screens.Play InternalButtons.Add(button); } - private int _selectionIndex = -1; + private int selectionIndex = -1; - private int selectionIndex + private void setSelected(int value) { - get => _selectionIndex; - set - { - if (_selectionIndex == value) - return; + if (selectionIndex == value) + return; - // Deselect the previously-selected button - if (_selectionIndex != -1) - InternalButtons[_selectionIndex].Selected.Value = false; + // Deselect the previously-selected button + if (selectionIndex != -1) + InternalButtons[selectionIndex].Selected.Value = false; - _selectionIndex = value; + selectionIndex = value; - // Select the newly-selected button - if (_selectionIndex != -1) - InternalButtons[_selectionIndex].Selected.Value = true; - } + // Select the newly-selected button + if (selectionIndex != -1) + InternalButtons[selectionIndex].Selected.Value = true; } protected override bool OnKeyDown(KeyDownEvent e) @@ -218,16 +214,16 @@ namespace osu.Game.Screens.Play { case Key.Up: if (selectionIndex == -1 || selectionIndex == 0) - selectionIndex = InternalButtons.Count - 1; + setSelected(InternalButtons.Count - 1); else - selectionIndex--; + setSelected(selectionIndex--); return true; case Key.Down: if (selectionIndex == -1 || selectionIndex == InternalButtons.Count - 1) - selectionIndex = 0; + setSelected(0); else - selectionIndex++; + setSelected(selectionIndex++); return true; } } From 9ebad16436cf7a079586c62216964f9f5648f20f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 14:34:17 +0900 Subject: [PATCH 4425/5608] Fix logic regression --- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 2fa5098890..adfbe977a4 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -216,14 +216,14 @@ namespace osu.Game.Screens.Play if (selectionIndex == -1 || selectionIndex == 0) setSelected(InternalButtons.Count - 1); else - setSelected(selectionIndex--); + setSelected(selectionIndex - 1); return true; case Key.Down: if (selectionIndex == -1 || selectionIndex == InternalButtons.Count - 1) setSelected(0); else - setSelected(selectionIndex++); + setSelected(selectionIndex + 1); return true; } } @@ -262,9 +262,9 @@ namespace osu.Game.Screens.Play private void buttonSelectionChanged(DialogButton button, bool isSelected) { if (!isSelected) - selectionIndex = -1; + setSelected(-1); else - selectionIndex = InternalButtons.IndexOf(button); + setSelected(InternalButtons.IndexOf(button)); } private void updateRetryCount() From 6c8f325063affe692a31ba0d3c1cd1688b3456c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 15:24:06 +0900 Subject: [PATCH 4426/5608] Add failing test --- .../Visual/Gameplay/TestScenePause.cs | 2 - .../Gameplay/TestScenePauseWhenInactive.cs | 49 +++++++++++++++++++ osu.Game/Tests/Visual/TestPlayer.cs | 7 ++- 3 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 803cab9325..e04315894e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -285,8 +285,6 @@ namespace osu.Game.Tests.Visual.Gameplay protected class PausePlayer : TestPlayer { - public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; - public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new HUDOverlay HUDOverlay => base.HUDOverlay; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs new file mode 100644 index 0000000000..5f29b46fe6 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs @@ -0,0 +1,49 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Platform; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual.Gameplay +{ + [HeadlessTest] // we alter unsafe properties on the game host to test inactive window state. + public class TestScenePauseWhenInactive : PlayerTestScene + { + protected new TestPlayer Player => (TestPlayer)base.Player; + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) + { + var beatmap = (Beatmap)base.CreateBeatmap(ruleset); + + beatmap.HitObjects.RemoveAll(h => h.StartTime < 30000); + + return beatmap; + } + + [Resolved] + private GameHost host { get; set; } + + public TestScenePauseWhenInactive() + : base(new OsuRuleset()) + { + } + + [Test] + public void TestDoesntPauseDuringIntro() + { + AddStep("set inactive", () => ((Bindable)host.IsActive).Value = false); + AddStep("resume player", () => Player.GameplayClockContainer.Start()); + AddUntilStep("wait for pause", () => Player.GameplayClockContainer.IsPaused.Value); + AddAssert("time of pause is after gameplay start time", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= Player.DrawableRuleset.GameplayStartTime); + } + + protected override Player CreatePlayer(Ruleset ruleset) => new TestPlayer(true, true, true); + } +} diff --git a/osu.Game/Tests/Visual/TestPlayer.cs b/osu.Game/Tests/Visual/TestPlayer.cs index 31f6edadec..8e3821f1a0 100644 --- a/osu.Game/Tests/Visual/TestPlayer.cs +++ b/osu.Game/Tests/Visual/TestPlayer.cs @@ -8,13 +8,16 @@ namespace osu.Game.Tests.Visual { public class TestPlayer : Player { - protected override bool PauseOnFocusLost => false; + protected override bool PauseOnFocusLost { get; } public new DrawableRuleset DrawableRuleset => base.DrawableRuleset; - public TestPlayer(bool allowPause = true, bool showResults = true) + public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; + + public TestPlayer(bool allowPause = true, bool showResults = true, bool pauseOnFocusLost = false) : base(allowPause, showResults) { + PauseOnFocusLost = pauseOnFocusLost; } } } From 75f92506451b47a1815530d00ffed7a74c23f41b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 15:45:50 +0900 Subject: [PATCH 4427/5608] Don't automatically pause when window is inactive if in break time --- osu.Game/Screens/Play/Player.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d40c448452..9feee82989 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -135,7 +135,7 @@ namespace osu.Game.Screens.Play addGameplayComponents(GameplayClockContainer, working); addOverlayComponents(GameplayClockContainer, working); - DrawableRuleset.HasReplayLoaded.BindValueChanged(e => HUDOverlay.HoldToQuit.PauseOnFocusLost = !e.NewValue && PauseOnFocusLost, true); + DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updatePauseOnFocusLostState(), true); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); @@ -146,6 +146,7 @@ namespace osu.Game.Screens.Play foreach (var mod in Mods.Value.OfType()) mod.ApplyToScoreProcessor(ScoreProcessor); + breakOverlay.IsBreakTime.ValueChanged += _ => updatePauseOnFocusLostState(); } private void addUnderlayComponents(Container target) @@ -241,6 +242,11 @@ namespace osu.Game.Screens.Play }); } + private void updatePauseOnFocusLostState() => + HUDOverlay.HoldToQuit.PauseOnFocusLost = PauseOnFocusLost + && !DrawableRuleset.HasReplayLoaded.Value + && !breakOverlay.IsBreakTime.Value; + private WorkingBeatmap loadBeatmap() { WorkingBeatmap working = Beatmap.Value; From 274958669c826236e48f681b8edb3c00ea8bf2b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 15:47:34 +0900 Subject: [PATCH 4428/5608] Add early assert as sanity check --- osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs index 5f29b46fe6..3513b6c25a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs @@ -39,7 +39,9 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestDoesntPauseDuringIntro() { AddStep("set inactive", () => ((Bindable)host.IsActive).Value = false); + AddStep("resume player", () => Player.GameplayClockContainer.Start()); + AddAssert("ensure not paused", () => !Player.GameplayClockContainer.IsPaused.Value); AddUntilStep("wait for pause", () => Player.GameplayClockContainer.IsPaused.Value); AddAssert("time of pause is after gameplay start time", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= Player.DrawableRuleset.GameplayStartTime); } From 83b2e0525e9055dae18b7eb7396a5804dbd21d39 Mon Sep 17 00:00:00 2001 From: Albie Date: Wed, 11 Dec 2019 07:02:51 +0000 Subject: [PATCH 4429/5608] further fixes, not perfect yet --- .../Visual/Background/TestSceneUserDimContainer.cs | 6 ++---- osu.Game/Graphics/Containers/UserDimContainer.cs | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index 28cc7a8532..f867b98fda 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -155,9 +155,7 @@ namespace osu.Game.Tests.Visual.Background public void DisableUserDisplaySettingsTest() { performFullSetup(); - AddStep("Enable user dim", () => player.DimmableStoryboard.EnableUserDim.Value = true); - waitForDim(); - AddStep("Turn on IgnoreUserSettings", () => player.DimmableStoryboard.IgnoreUserSettings.Value = true); + AddStep("Start ignoring user settings", () => player.DimmableStoryboard.IgnoreUserSettings.Value = true); waitForDim(); AddAssert("Check the background is undimmed", () => player.IsBackgroundUndimmed()); } @@ -367,7 +365,7 @@ namespace osu.Game.Tests.Visual.Background public new DimmableStoryboard DimmableStoryboard => base.DimmableStoryboard; - public bool IsBackgroundUndimmed() => ((FadeAccessibleBackground)Background).CurrentColour == Color4.White; + public bool IsBackgroundUndimmed() => ((FadeAccessibleBackground)Background).CurrentColour == OsuColour.Gray(1); // Whether or not the player should be allowed to load. public bool BlockLoad; diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 74d922704e..bddbbca0ea 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -91,7 +91,7 @@ namespace osu.Game.Graphics.Containers ContentDisplayed = ShowDimContent; dimContent.FadeTo(ContentDisplayed ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint); - dimContent.FadeColour(IgnoreUserSettings.Value ? OsuColour.Gray(1 - (float)DimLevel) : Color4.White, BACKGROUND_FADE_DURATION, Easing.OutQuint); + dimContent.FadeColour(IgnoreUserSettings.Value ? Color4.White : OsuColour.Gray(1 - (float)DimLevel), BACKGROUND_FADE_DURATION, Easing.OutQuint); } } } From d8cebd20edac75973ad00c65b35421fcab97a9e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 16:06:20 +0900 Subject: [PATCH 4430/5608] Add xmldoc --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs index 909c764b9e..573c408a78 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs @@ -8,6 +8,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { public abstract class OsuCursorSprite : CompositeDrawable { + /// + /// The an optional piece of the cursor to expand when in a clicked state. + /// If null, the whole cursor will be affected by expansion. + /// public Drawable ExpandTarget { get; protected set; } } } From 6b3c7c842198b1fe6e24314c6bad453cfd73d37b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 19 Nov 2019 20:34:35 +0800 Subject: [PATCH 4431/5608] Remove usages of FileSafety class. --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 8 ++++---- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 4 ++-- osu.Game/Beatmaps/WorkingBeatmap.cs | 7 +++++-- osu.Game/Database/ArchiveModelManager.cs | 3 +-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 838b1c2f07..bffe999896 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using osu.Framework.IO.File; +using osu.Framework.Extensions; using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Beatmaps.ControlPoints; @@ -112,7 +112,7 @@ namespace osu.Game.Beatmaps.Formats switch (pair.Key) { case @"AudioFilename": - metadata.AudioFile = FileSafety.PathStandardise(pair.Value); + metadata.AudioFile = pair.Value.PathStandardise(); break; case @"AudioLeadIn": @@ -300,12 +300,12 @@ namespace osu.Game.Beatmaps.Formats { case EventType.Background: string bgFilename = split[2].Trim('"'); - beatmap.BeatmapInfo.Metadata.BackgroundFile = FileSafety.PathStandardise(bgFilename); + beatmap.BeatmapInfo.Metadata.BackgroundFile = bgFilename.PathStandardise(); break; case EventType.Video: string videoFilename = split[2].Trim('"'); - beatmap.BeatmapInfo.Metadata.VideoFile = FileSafety.PathStandardise(videoFilename); + beatmap.BeatmapInfo.Metadata.VideoFile = videoFilename.PathStandardise(); break; case EventType.Break: diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index f94ab3f27b..d79c0f7fa8 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -8,8 +8,8 @@ using System.IO; using System.Linq; using osuTK; using osuTK.Graphics; +using osu.Framework.Extensions; using osu.Framework.Graphics; -using osu.Framework.IO.File; using osu.Game.IO; using osu.Game.Storyboards; @@ -335,6 +335,6 @@ namespace osu.Game.Beatmaps.Formats } } - private string cleanFilename(string path) => FileSafety.PathStandardise(path.Trim('"')); + private string cleanFilename(string path) => path.Trim('"').PathStandardise(); } } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 44d6d33cef..f23669579a 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -7,7 +7,6 @@ using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; using osu.Game.Storyboards; -using osu.Framework.IO.File; using System.IO; using System.Linq; using System.Threading; @@ -83,7 +82,11 @@ namespace osu.Game.Beatmaps /// The absolute path of the output file. public string Save() { - var path = FileSafety.GetTempPath(Guid.NewGuid().ToString().Replace("-", string.Empty) + ".json"); + // copied from osu.Framework.IO.File.FileSafety.GetTempPath + string directory = Path.Combine(Path.GetTempPath(), @"osu!"); + Directory.CreateDirectory(directory); + + var path = Path.Combine(directory, Guid.NewGuid().ToString().Replace("-", string.Empty) + ".json"); using (var sw = new StreamWriter(path)) sw.WriteLine(Beatmap.Serialize()); return path; diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 7cce2fb92f..5cd2b947fe 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -13,7 +13,6 @@ using Microsoft.EntityFrameworkCore; using osu.Framework; using osu.Framework.Extensions; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.IO.File; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Threading; @@ -493,7 +492,7 @@ namespace osu.Game.Database { fileInfos.Add(new TFileModel { - Filename = FileSafety.PathStandardise(file.Substring(prefix.Length)), + Filename = file.Substring(prefix.Length).PathStandardise(), FileInfo = files.Add(s) }); } From b86a3dbfabbc1db04314b6e6282cf88343e50eeb Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 11 Dec 2019 16:06:56 +0800 Subject: [PATCH 4432/5608] PathStandardise -> ToStandardisedPath --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 6 +++--- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 2 +- osu.Game/Database/ArchiveModelManager.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index bffe999896..f8275ec4f6 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -112,7 +112,7 @@ namespace osu.Game.Beatmaps.Formats switch (pair.Key) { case @"AudioFilename": - metadata.AudioFile = pair.Value.PathStandardise(); + metadata.AudioFile = pair.Value.ToStandardisedPath(); break; case @"AudioLeadIn": @@ -300,12 +300,12 @@ namespace osu.Game.Beatmaps.Formats { case EventType.Background: string bgFilename = split[2].Trim('"'); - beatmap.BeatmapInfo.Metadata.BackgroundFile = bgFilename.PathStandardise(); + beatmap.BeatmapInfo.Metadata.BackgroundFile = bgFilename.ToStandardisedPath(); break; case EventType.Video: string videoFilename = split[2].Trim('"'); - beatmap.BeatmapInfo.Metadata.VideoFile = videoFilename.PathStandardise(); + beatmap.BeatmapInfo.Metadata.VideoFile = videoFilename.ToStandardisedPath(); break; case EventType.Break: diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index d79c0f7fa8..ccd46ab559 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -335,6 +335,6 @@ namespace osu.Game.Beatmaps.Formats } } - private string cleanFilename(string path) => path.Trim('"').PathStandardise(); + private string cleanFilename(string path) => path.Trim('"').ToStandardisedPath(); } } diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 5cd2b947fe..fd455d7cd5 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -492,7 +492,7 @@ namespace osu.Game.Database { fileInfos.Add(new TFileModel { - Filename = file.Substring(prefix.Length).PathStandardise(), + Filename = file.Substring(prefix.Length).ToStandardisedPath(), FileInfo = files.Add(s) }); } From cffeceb2290c4ce9b6ce37dacdd7d766e00d216e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 11 Dec 2019 16:24:22 +0800 Subject: [PATCH 4433/5608] Remove unnecessary comment. --- osu.Game/Beatmaps/WorkingBeatmap.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index f23669579a..4452d26fcd 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -82,7 +82,6 @@ namespace osu.Game.Beatmaps /// The absolute path of the output file. public string Save() { - // copied from osu.Framework.IO.File.FileSafety.GetTempPath string directory = Path.Combine(Path.GetTempPath(), @"osu!"); Directory.CreateDirectory(directory); From 48f1dad4aa4546402ed6c0bd860ae54598c7365d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Dec 2019 17:25:06 +0900 Subject: [PATCH 4434/5608] Remove abstract ScoreProcessor class --- .../Scoring/CatchScoreProcessor.cs | 10 +- .../UI/DrawableCatchRuleset.cs | 2 +- .../Scoring/ManiaScoreProcessor.cs | 12 +- .../UI/DrawableManiaRuleset.cs | 2 +- .../Scoring/OsuScoreProcessor.cs | 10 +- .../UI/DrawableOsuRuleset.cs | 2 +- .../Scoring/TaikoScoreProcessor.cs | 12 +- .../UI/DrawableTaikoRuleset.cs | 2 +- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 276 ++++++++---------- osu.Game/Rulesets/UI/DrawableRuleset.cs | 26 +- osu.Game/Screens/Play/Player.cs | 3 + 11 files changed, 165 insertions(+), 192 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 18785d65ea..f67ca1213e 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -2,23 +2,21 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; -using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Catch.Scoring { - public class CatchScoreProcessor : ScoreProcessor + public class CatchScoreProcessor : ScoreProcessor { - public CatchScoreProcessor(DrawableRuleset drawableRuleset) - : base(drawableRuleset) + public CatchScoreProcessor(IBeatmap beatmap) + : base(beatmap) { } private float hpDrainRate; - protected override void ApplyBeatmap(Beatmap beatmap) + protected override void ApplyBeatmap(IBeatmap beatmap) { base.ApplyBeatmap(beatmap); diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index 6b7f00c5d0..f5bddeb2cb 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Catch.UI TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450); } - public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this); + public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(Beatmap); protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay); diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 49894a644c..a678ef60e7 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -3,13 +3,11 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.Scoring { - internal class ManiaScoreProcessor : ScoreProcessor + internal class ManiaScoreProcessor : ScoreProcessor { /// /// The hit HP multiplier at OD = 0. @@ -51,12 +49,12 @@ namespace osu.Game.Rulesets.Mania.Scoring /// private double hpMultiplier = 1; - public ManiaScoreProcessor(DrawableRuleset drawableRuleset) - : base(drawableRuleset) + public ManiaScoreProcessor(IBeatmap beatmap) + : base(beatmap) { } - protected override void ApplyBeatmap(Beatmap beatmap) + protected override void ApplyBeatmap(IBeatmap beatmap) { base.ApplyBeatmap(beatmap); @@ -65,7 +63,7 @@ namespace osu.Game.Rulesets.Mania.Scoring hpMissMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_miss_min, hp_multiplier_miss_mid, hp_multiplier_miss_max); } - protected override void SimulateAutoplay(Beatmap beatmap) + protected override void SimulateAutoplay(IBeatmap beatmap) { while (true) { diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index d371c1f7a8..0607bf0abd 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Mania.UI protected override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages); - public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); + public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(Beatmap); public override int Variant => (int)(Beatmap.Stages.Count == 1 ? PlayfieldType.Single : PlayfieldType.Dual) + Beatmap.TotalColumns; diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index affe18a30d..6779271cb3 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -5,22 +5,20 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; -using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu.Scoring { - internal class OsuScoreProcessor : ScoreProcessor + internal class OsuScoreProcessor : ScoreProcessor { - public OsuScoreProcessor(DrawableRuleset drawableRuleset) - : base(drawableRuleset) + public OsuScoreProcessor(IBeatmap beatmap) + : base(beatmap) { } private float hpDrainRate; - protected override void ApplyBeatmap(Beatmap beatmap) + protected override void ApplyBeatmap(IBeatmap beatmap) { base.ApplyBeatmap(beatmap); diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index 49aea52902..5bb728a9b0 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -33,7 +33,7 @@ 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); + public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(Beatmap); protected override Playfield CreatePlayfield() => new OsuPlayfield(); diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 75a27ff639..ae593d2e3a 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -1,15 +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.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Objects; -using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Taiko.Scoring { - internal class TaikoScoreProcessor : ScoreProcessor + internal class TaikoScoreProcessor : ScoreProcessor { /// /// A value used for calculating . @@ -31,16 +31,16 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// private double hpMissMultiplier; - public TaikoScoreProcessor(DrawableRuleset drawableRuleset) - : base(drawableRuleset) + public TaikoScoreProcessor(IBeatmap beatmap) + : base(beatmap) { } - protected override void ApplyBeatmap(Beatmap beatmap) + protected override void ApplyBeatmap(IBeatmap beatmap) { base.ApplyBeatmap(beatmap); - hpMultiplier = 1 / (object_count_factor * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98)); + hpMultiplier = 1 / (object_count_factor * beatmap.HitObjects.OfType().Count() * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98)); hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120); } diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index fc109bf6a6..d4ea9a043a 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Taiko.UI new BarLineGenerator(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar.Major ? new DrawableBarLineMajor(bar) : new DrawableBarLine(bar))); } - public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); + public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(Beatmap); public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new TaikoPlayfieldAdjustmentContainer(); diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 18c2a2ca01..a8a2294498 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -13,13 +13,16 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.UI; using osu.Game.Scoring; namespace osu.Game.Rulesets.Scoring { - public abstract class ScoreProcessor + public class ScoreProcessor { + private const double base_portion = 0.3; + private const double combo_portion = 0.7; + private const double max_score = 1000000; + /// /// Invoked when the is in a failed state. /// This may occur regardless of whether an event is invoked. @@ -67,11 +70,6 @@ namespace osu.Game.Rulesets.Scoring /// public readonly Bindable> Mods = new Bindable>(Array.Empty()); - /// - /// Create a for this processor. - /// - public virtual HitWindows CreateHitWindows() => new HitWindows(); - /// /// The current rank. /// @@ -90,132 +88,23 @@ namespace osu.Game.Rulesets.Scoring /// /// Whether all s have been processed. /// - public virtual bool HasCompleted => false; - - /// - /// The total number of judged s at the current point in time. - /// - public int JudgedHits { get; protected set; } + public bool HasCompleted => JudgedHits == MaxHits; /// /// Whether this ScoreProcessor has already triggered the failed state. /// - public virtual bool HasFailed { get; private set; } + public bool HasFailed { get; private set; } /// - /// The default conditions for failing. + /// The maximum number of hits that can be judged. /// - protected virtual bool DefaultFailCondition => Precision.AlmostBigger(Health.MinValue, Health.Value); - - protected ScoreProcessor() - { - Combo.ValueChanged += delegate { HighestCombo.Value = Math.Max(HighestCombo.Value, Combo.Value); }; - Accuracy.ValueChanged += delegate - { - Rank.Value = rankFrom(Accuracy.Value); - foreach (var mod in Mods.Value.OfType()) - Rank.Value = mod.AdjustRank(Rank.Value, Accuracy.Value); - }; - } - - private ScoreRank rankFrom(double acc) - { - if (acc == 1) - return ScoreRank.X; - if (acc > 0.95) - return ScoreRank.S; - if (acc > 0.9) - return ScoreRank.A; - if (acc > 0.8) - return ScoreRank.B; - if (acc > 0.7) - return ScoreRank.C; - - return ScoreRank.D; - } - - /// - /// Resets this ScoreProcessor to a default state. - /// - /// Whether to store the current state of the for future use. - protected virtual void Reset(bool storeResults) - { - TotalScore.Value = 0; - Accuracy.Value = 1; - Health.Value = 1; - Combo.Value = 0; - Rank.Value = ScoreRank.X; - HighestCombo.Value = 0; - - JudgedHits = 0; - - HasFailed = false; - } - - /// - /// Checks if the score is in a failed state and notifies subscribers. - /// - /// This can only ever notify subscribers once. - /// - /// - protected void UpdateFailed(JudgementResult result) - { - if (HasFailed) - return; - - if (!DefaultFailCondition && FailConditions?.Invoke(this, result) != true) - return; - - if (Failed?.Invoke() != false) - HasFailed = true; - } - - /// - /// Notifies subscribers of that a new judgement has occurred. - /// - /// The judgement scoring result to notify subscribers of. - protected void NotifyNewJudgement(JudgementResult result) - { - NewJudgement?.Invoke(result); - - if (HasCompleted) - AllJudged?.Invoke(); - } - - /// - /// Retrieve a score populated with data for the current play this processor is responsible for. - /// - public virtual void PopulateScore(ScoreInfo score) - { - score.TotalScore = (long)Math.Round(TotalScore.Value); - score.Combo = Combo.Value; - score.MaxCombo = HighestCombo.Value; - score.Accuracy = Math.Round(Accuracy.Value, 4); - score.Rank = Rank.Value; - score.Date = DateTimeOffset.Now; - - var hitWindows = CreateHitWindows(); - - foreach (var result in Enum.GetValues(typeof(HitResult)).OfType().Where(r => r > HitResult.None && hitWindows.IsHitResultAllowed(r))) - score.Statistics[result] = GetStatistic(result); - } - - public abstract int GetStatistic(HitResult result); - - public abstract double GetStandardisedScore(); - } - - public class ScoreProcessor : ScoreProcessor - where TObject : HitObject - { - private const double base_portion = 0.3; - private const double combo_portion = 0.7; - private const double max_score = 1000000; - - public sealed override bool HasCompleted => JudgedHits == MaxHits; - protected int MaxHits { get; private set; } + /// + /// The total number of judged s at the current point in time. + /// + public int JudgedHits { get; private set; } + private double maxHighestCombo; private double maxBaseScore; @@ -225,17 +114,22 @@ namespace osu.Game.Rulesets.Scoring private double scoreMultiplier = 1; - public ScoreProcessor(DrawableRuleset drawableRuleset) + public ScoreProcessor(IBeatmap beatmap) { Debug.Assert(base_portion + combo_portion == 1.0); - drawableRuleset.OnNewResult += applyResult; - drawableRuleset.OnRevertResult += revertResult; + Combo.ValueChanged += combo => HighestCombo.Value = Math.Max(HighestCombo.Value, combo.NewValue); + Accuracy.ValueChanged += accuracy => + { + Rank.Value = rankFrom(accuracy.NewValue); + foreach (var mod in Mods.Value.OfType()) + Rank.Value = mod.AdjustRank(Rank.Value, accuracy.NewValue); + }; - ApplyBeatmap(drawableRuleset.Beatmap); + ApplyBeatmap(beatmap); Reset(false); - SimulateAutoplay(drawableRuleset.Beatmap); + SimulateAutoplay(beatmap); Reset(true); if (maxBaseScore == 0 || maxHighestCombo == 0) @@ -257,19 +151,19 @@ namespace osu.Game.Rulesets.Scoring } /// - /// Applies any properties of the which affect scoring to this . + /// Applies any properties of the which affect scoring to this . /// - /// The to read properties from. - protected virtual void ApplyBeatmap(Beatmap beatmap) + /// The to read properties from. + protected virtual void ApplyBeatmap(IBeatmap beatmap) { } /// - /// Simulates an autoplay of the to determine scoring values. + /// Simulates an autoplay of the to determine scoring values. /// /// This provided temporarily. DO NOT USE. - /// The to simulate. - protected virtual void SimulateAutoplay(Beatmap beatmap) + /// The to simulate. + protected virtual void SimulateAutoplay(IBeatmap beatmap) { foreach (var obj in beatmap.HitObjects) simulate(obj); @@ -289,7 +183,7 @@ namespace osu.Game.Rulesets.Scoring result.Type = judgement.MaxResult; - applyResult(result); + ApplyResult(result); } } @@ -297,22 +191,26 @@ namespace osu.Game.Rulesets.Scoring /// Applies the score change of a to this . /// /// The to apply. - private void applyResult(JudgementResult result) + public void ApplyResult(JudgementResult result) { - ApplyResult(result); - updateScore(); + ApplyResultInternal(result); - UpdateFailed(result); - NotifyNewJudgement(result); + updateScore(); + updateFailed(result); + + NewJudgement?.Invoke(result); + + if (HasCompleted) + AllJudged?.Invoke(); } /// /// Reverts the score change of a that was applied to this . /// /// The judgement scoring result. - private void revertResult(JudgementResult result) + public void RevertResult(JudgementResult result) { - RevertResult(result); + RevertResultInternal(result); updateScore(); } @@ -322,10 +220,10 @@ namespace osu.Game.Rulesets.Scoring /// Applies the score change of a to this . /// /// - /// Any changes applied via this method can be reverted via . + /// Any changes applied via this method can be reverted via . /// /// The to apply. - protected virtual void ApplyResult(JudgementResult result) + protected virtual void ApplyResultInternal(JudgementResult result) { result.ComboAtJudgement = Combo.Value; result.HighestComboAtJudgement = HighestCombo.Value; @@ -372,10 +270,10 @@ namespace osu.Game.Rulesets.Scoring } /// - /// Reverts the score change of a that was applied to this via . + /// Reverts the score change of a that was applied to this via . /// /// The judgement scoring result. - protected virtual void RevertResult(JudgementResult result) + protected virtual void RevertResultInternal(JudgementResult result) { Combo.Value = result.ComboAtJudgement; HighestCombo.Value = result.HighestComboAtJudgement; @@ -432,11 +330,49 @@ namespace osu.Game.Rulesets.Scoring } } - public override int GetStatistic(HitResult result) => scoreResultCounts.GetOrDefault(result); + /// + /// Checks if the score is in a failed state and notifies subscribers. + /// + /// This can only ever notify subscribers once. + /// + /// + private void updateFailed(JudgementResult result) + { + if (HasFailed) + return; - public override double GetStandardisedScore() => getScore(ScoringMode.Standardised); + if (!DefaultFailCondition && FailConditions?.Invoke(this, result) != true) + return; - protected override void Reset(bool storeResults) + if (Failed?.Invoke() != false) + HasFailed = true; + } + + private ScoreRank rankFrom(double acc) + { + if (acc == 1) + return ScoreRank.X; + if (acc > 0.95) + return ScoreRank.S; + if (acc > 0.9) + return ScoreRank.A; + if (acc > 0.8) + return ScoreRank.B; + if (acc > 0.7) + return ScoreRank.C; + + return ScoreRank.D; + } + + public int GetStatistic(HitResult result) => scoreResultCounts.GetOrDefault(result); + + public double GetStandardisedScore() => getScore(ScoringMode.Standardised); + + /// + /// Resets this ScoreProcessor to a default state. + /// + /// Whether to store the current state of the for future use. + protected virtual void Reset(bool storeResults) { scoreResultCounts.Clear(); @@ -447,13 +383,49 @@ namespace osu.Game.Rulesets.Scoring maxBaseScore = baseScore; } - base.Reset(storeResults); - + JudgedHits = 0; baseScore = 0; rollingMaxBaseScore = 0; bonusScore = 0; + + TotalScore.Value = 0; + Accuracy.Value = 1; + Health.Value = 1; + Combo.Value = 0; + Rank.Value = ScoreRank.X; + HighestCombo.Value = 0; + + HasFailed = false; } + /// + /// Retrieve a score populated with data for the current play this processor is responsible for. + /// + public virtual void PopulateScore(ScoreInfo score) + { + score.TotalScore = (long)Math.Round(TotalScore.Value); + score.Combo = Combo.Value; + score.MaxCombo = HighestCombo.Value; + score.Accuracy = Math.Round(Accuracy.Value, 4); + score.Rank = Rank.Value; + score.Date = DateTimeOffset.Now; + + var hitWindows = CreateHitWindows(); + + foreach (var result in Enum.GetValues(typeof(HitResult)).OfType().Where(r => r > HitResult.None && hitWindows.IsHitResultAllowed(r))) + score.Statistics[result] = GetStatistic(result); + } + + /// + /// The default conditions for failing. + /// + protected virtual bool DefaultFailCondition => Precision.AlmostBigger(Health.MinValue, Health.Value); + + /// + /// Create a for this processor. + /// + public virtual HitWindows CreateHitWindows() => new HitWindows(); + /// /// Creates the that represents the scoring result for a . /// diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index a856974292..10657f6b39 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -45,6 +45,10 @@ namespace osu.Game.Rulesets.UI public abstract class DrawableRuleset : DrawableRuleset, IProvideCursor, ICanAttachKeyCounter where TObject : HitObject { + public override event Action OnNewResult; + + public override event Action OnRevertResult; + /// /// The selected variant. /// @@ -91,16 +95,6 @@ namespace osu.Game.Rulesets.UI } } - /// - /// Invoked when a has been applied by a . - /// - public event Action OnNewResult; - - /// - /// Invoked when a is being reverted by a . - /// - public event Action OnRevertResult; - /// /// The beatmap. /// @@ -309,7 +303,7 @@ namespace osu.Game.Rulesets.UI /// The Playfield. protected abstract Playfield CreatePlayfield(); - public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(this); + public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(Beatmap); /// /// Applies the active mods to this DrawableRuleset. @@ -366,6 +360,16 @@ namespace osu.Game.Rulesets.UI /// public abstract class DrawableRuleset : CompositeDrawable { + /// + /// Invoked when a has been applied by a . + /// + public abstract event Action OnNewResult; + + /// + /// Invoked when a is being reverted by a . + /// + public abstract event Action OnRevertResult; + /// /// Whether a replay is currently loaded. /// diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d40c448452..d3df137328 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -140,6 +140,9 @@ namespace osu.Game.Screens.Play // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); + DrawableRuleset.OnNewResult += ScoreProcessor.ApplyResult; + DrawableRuleset.OnRevertResult += ScoreProcessor.RevertResult; + // Bind ScoreProcessor to ourselves ScoreProcessor.AllJudged += onCompletion; ScoreProcessor.Failed += onFail; From 97ca2e2753151ec527264d0226a5e0b2459f6cd9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 17:58:59 +0900 Subject: [PATCH 4435/5608] Add missing bezier option to menu --- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index d706fb51d5..ab6064602b 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -171,6 +171,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components createMenuItemForPathType(null), createMenuItemForPathType(PathType.Linear), createMenuItemForPathType(PathType.PerfectCurve), + createMenuItemForPathType(PathType.Bezier), createMenuItemForPathType(PathType.Catmull) } } From 03040d175092313cd9a5657fa1f9915917d22927 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 18:18:16 +0900 Subject: [PATCH 4436/5608] Don't show inherit menu item when first control point is selected --- .../Components/PathControlPointVisualiser.cs | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index ab6064602b..e406bb6426 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -27,7 +27,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler, IHasContextMenu { internal readonly Container Pieces; + private readonly Slider slider; + private readonly bool allowSelection; private InputManager inputManager; @@ -82,7 +84,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components protected override bool OnClick(ClickEvent e) { foreach (var piece in Pieces) + { piece.IsSelected.Value = false; + } + return false; } @@ -156,24 +161,29 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components if (!Pieces.Any(p => p.IsHovered)) return null; - int selectedPoints = Pieces.Count(p => p.IsSelected.Value); + var selectedPieces = Pieces.Where(p => p.IsSelected.Value).ToList(); + int count = selectedPieces.Count; - if (selectedPoints == 0) + if (count == 0) return null; + List items = new List(); + + if (!selectedPieces.Contains(Pieces[0])) + items.Add(createMenuItemForPathType(null)); + + // todo: hide/disable items which aren't valid for selected points + items.Add(createMenuItemForPathType(PathType.Linear)); + items.Add(createMenuItemForPathType(PathType.PerfectCurve)); + items.Add(createMenuItemForPathType(PathType.Bezier)); + items.Add(createMenuItemForPathType(PathType.Catmull)); + return new MenuItem[] { - new OsuMenuItem($"Delete {"control point".ToQuantity(selectedPoints, selectedPoints > 1 ? ShowQuantityAs.Numeric : ShowQuantityAs.None)}", MenuItemType.Destructive, () => deleteSelected()), + new OsuMenuItem($"Delete {"control point".ToQuantity(count, count > 1 ? ShowQuantityAs.Numeric : ShowQuantityAs.None)}", MenuItemType.Destructive, () => deleteSelected()), new OsuMenuItem("Type") { - Items = new[] - { - createMenuItemForPathType(null), - createMenuItemForPathType(PathType.Linear), - createMenuItemForPathType(PathType.PerfectCurve), - createMenuItemForPathType(PathType.Bezier), - createMenuItemForPathType(PathType.Catmull) - } + Items = items } }; } From d82ba3e7f7ebb69b29a7529299dbe3aaa800a373 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 18:20:28 +0900 Subject: [PATCH 4437/5608] Curve -> Curve type --- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index e406bb6426..22155ab7af 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -181,7 +181,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return new MenuItem[] { new OsuMenuItem($"Delete {"control point".ToQuantity(count, count > 1 ? ShowQuantityAs.Numeric : ShowQuantityAs.None)}", MenuItemType.Destructive, () => deleteSelected()), - new OsuMenuItem("Type") + new OsuMenuItem("Curve type") { Items = items } From 23959f3a3ccb462a21c52460163b70bc474e8fa1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 18:52:38 +0900 Subject: [PATCH 4438/5608] Move control point removal to SliderSelectionBlueprint --- .../Components/PathControlPointVisualiser.cs | 32 ++----------- .../Sliders/SliderSelectionBlueprint.cs | 47 +++++++++++++++++-- 2 files changed, 47 insertions(+), 32 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 22155ab7af..cd19653a2e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; using Humanizer; -using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -18,8 +17,6 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Screens.Edit.Compose; -using osuTK; using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components @@ -34,11 +31,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private InputManager inputManager; - [Resolved(CanBeNull = true)] - private IPlacementHandler placementHandler { get; set; } - private IBindableList controlPoints; + public Action> RemoveControlPointsRequested; + public PathControlPointVisualiser(Slider slider, bool allowSelection) { this.slider = slider; @@ -123,29 +119,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components if (toRemove.Count == 0) return false; - foreach (var c in toRemove) - { - // The first control point in the slider must have a type, so take it from the previous "first" one - // Todo: Should be handled within SliderPath itself - if (c == slider.Path.ControlPoints[0] && slider.Path.ControlPoints.Count > 1 && slider.Path.ControlPoints[1].Type.Value == null) - slider.Path.ControlPoints[1].Type.Value = slider.Path.ControlPoints[0].Type.Value; - - slider.Path.ControlPoints.Remove(c); - } - - // If there are 0 or 1 remaining control points, the slider is in a degenerate (single point) form and should be deleted - if (slider.Path.ControlPoints.Count <= 1) - { - placementHandler?.Delete(slider); - return true; - } - - // The path will have a non-zero offset if the head is removed, but sliders don't support this behaviour since the head is positioned at the slider's position - // So the slider needs to be offset by this amount instead, and all control points offset backwards such that the path is re-positioned at (0, 0) - Vector2 first = slider.Path.ControlPoints[0].Position.Value; - foreach (var c in slider.Path.ControlPoints) - c.Position.Value -= first; - slider.Position += first; + RemoveControlPointsRequested?.Invoke(toRemove); // Since pieces are re-used, they will not point to the deleted control points while remaining selected foreach (var piece in Pieces) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 68873093a6..3165c441fb 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.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.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -14,6 +15,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Screens.Edit.Compose; using osuTK; using osuTK.Input; @@ -29,6 +31,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders [Resolved(CanBeNull = true)] private HitObjectComposer composer { get; set; } + [Resolved(CanBeNull = true)] + private IPlacementHandler placementHandler { get; set; } + public SliderSelectionBlueprint(DrawableSlider slider) : base(slider) { @@ -40,6 +45,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders HeadBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.Start), TailBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.End), ControlPointVisualiser = new PathControlPointVisualiser(sliderObject, true) + { + RemoveControlPointsRequested = removeControlPoints + } }; } @@ -97,6 +105,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders return true; } + private BindableList controlPoints => HitObject.Path.ControlPoints; + private int addControlPoint(Vector2 position) { position -= HitObject.Position; @@ -104,9 +114,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders int insertionIndex = 0; float minDistance = float.MaxValue; - for (int i = 0; i < HitObject.Path.ControlPoints.Count - 1; i++) + for (int i = 0; i < controlPoints.Count - 1; i++) { - float dist = new Line(HitObject.Path.ControlPoints[i].Position.Value, HitObject.Path.ControlPoints[i + 1].Position.Value).DistanceToPoint(position); + float dist = new Line(controlPoints[i].Position.Value, controlPoints[i + 1].Position.Value).DistanceToPoint(position); if (dist < minDistance) { @@ -116,11 +126,42 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders } // Move the control points from the insertion index onwards to make room for the insertion - HitObject.Path.ControlPoints.Insert(insertionIndex, new PathControlPoint { Position = { Value = position } }); + controlPoints.Insert(insertionIndex, new PathControlPoint { Position = { Value = position } }); return insertionIndex; } + private void removeControlPoints(List toRemove) + { + // Ensure that there are any points to be deleted + if (toRemove.Count == 0) + return; + + foreach (var c in toRemove) + { + // The first control point in the slider must have a type, so take it from the previous "first" one + // Todo: Should be handled within SliderPath itself + if (c == controlPoints[0] && controlPoints.Count > 1 && controlPoints[1].Type.Value == null) + controlPoints[1].Type.Value = controlPoints[0].Type.Value; + + controlPoints.Remove(c); + } + + // If there are 0 or 1 remaining control points, the slider is in a degenerate (single point) form and should be deleted + if (controlPoints.Count <= 1) + { + placementHandler?.Delete(HitObject); + return; + } + + // The path will have a non-zero offset if the head is removed, but sliders don't support this behaviour since the head is positioned at the slider's position + // So the slider needs to be offset by this amount instead, and all control points offset backwards such that the path is re-positioned at (0, 0) + Vector2 first = controlPoints[0].Position.Value; + foreach (var c in controlPoints) + c.Position.Value -= first; + HitObject.Position += first; + } + private void updatePath() { HitObject.Path.ExpectedDistance.Value = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)HitObject.Path.CalculatedDistance) ?? (float)HitObject.Path.CalculatedDistance; From 9963d18d17c00777a68d36768429c5ee9ebd4006 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 11 Dec 2019 19:13:04 +0900 Subject: [PATCH 4439/5608] Add whitespace --- osu.Game/Overlays/RankingsOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index e7c8b94a10..c8874ef891 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -106,6 +106,7 @@ namespace osu.Game.Overlays Scheduler.AddOnce(loadNewContent); }, true); + Scope.BindValueChanged(_ => { // country filtering is only valid for performance scope. From 404d3207ffc0c963dedde39d10b27d7de5f890fd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Dec 2019 19:43:32 +0900 Subject: [PATCH 4440/5608] Refactor ModNightcore/ModDaycore --- osu.Game/Rulesets/Mods/ModDaycore.cs | 12 ++++++++---- osu.Game/Rulesets/Mods/ModNightcore.cs | 12 ++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index 474e793dd1..9445895fb0 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -18,16 +18,20 @@ namespace osu.Game.Rulesets.Mods private readonly BindableNumber tempoAdjust = new BindableDouble(1); private readonly BindableNumber freqAdjust = new BindableDouble(1); - public override void ApplyToTrack(Track track) + public ModDaycore() { - track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); - track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); - SpeedChange.BindValueChanged(val => { freqAdjust.Value = SpeedChange.Default; tempoAdjust.Value = val.NewValue / SpeedChange.Default; }, true); } + + public override void ApplyToTrack(Track track) + { + // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) + track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); + track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); + } } } diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 401814d18b..9b27925693 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -19,16 +19,20 @@ namespace osu.Game.Rulesets.Mods private readonly BindableNumber tempoAdjust = new BindableDouble(1); private readonly BindableNumber freqAdjust = new BindableDouble(1); - public override void ApplyToTrack(Track track) + public ModNightcore() { - track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); - track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); - SpeedChange.BindValueChanged(val => { freqAdjust.Value = SpeedChange.Default; tempoAdjust.Value = val.NewValue / SpeedChange.Default; }, true); } + + public override void ApplyToTrack(Track track) + { + // base.ApplyToTrack() intentionally not called (different tempo adjustment is applied) + track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); + track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); + } } } From c34b6b59eda2e6a62c5e1b1aca36b9e9c45f88c1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Dec 2019 19:48:57 +0900 Subject: [PATCH 4441/5608] Remove time ramp and rate adjust mod incompatibility --- osu.Game/Rulesets/Mods/ModRateAdjust.cs | 2 -- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 2 -- 2 files changed, 4 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModRateAdjust.cs b/osu.Game/Rulesets/Mods/ModRateAdjust.cs index 5aa3e09fee..9143836fb7 100644 --- a/osu.Game/Rulesets/Mods/ModRateAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModRateAdjust.cs @@ -10,8 +10,6 @@ namespace osu.Game.Rulesets.Mods { public abstract class ModRateAdjust : Mod, IApplicableToTrack { - public override Type[] IncompatibleMods => new[] { typeof(ModTimeRamp) }; - public abstract BindableNumber SpeedChange { get; } public virtual void ApplyToTrack(Track track) diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index bffe4f7b70..e10afa7d7c 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -20,8 +20,6 @@ namespace osu.Game.Rulesets.Mods /// private const double final_rate_progress = 0.75f; - public override Type[] IncompatibleMods => new[] { typeof(ModRateAdjust) }; - [SettingSource("Final rate", "The final speed to ramp to")] public abstract BindableNumber FinalRate { get; } From 40f918dce6a65a77589bd6a5800f510f82d1ff53 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Dec 2019 19:49:32 +0900 Subject: [PATCH 4442/5608] Remove unused using --- osu.Game/Rulesets/Mods/ModRateAdjust.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModRateAdjust.cs b/osu.Game/Rulesets/Mods/ModRateAdjust.cs index 9143836fb7..1739524bcd 100644 --- a/osu.Game/Rulesets/Mods/ModRateAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModRateAdjust.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 osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; From 47b6b0173913ad78ac3beaf702676b0e929c8515 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 20:11:48 +0900 Subject: [PATCH 4443/5608] Rename class to signify it is a drawable --- ...ointConnection.cs => PathControlPointConnectionPiece.cs} | 4 ++-- .../Sliders/Components/PathControlPointVisualiser.cs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) rename osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/{PathControlPointConnection.cs => PathControlPointConnectionPiece.cs} (92%) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnection.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs similarity index 92% rename from osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnection.cs rename to osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs index f57299c5a9..4dfe7834fd 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnection.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { - public class PathControlPointConnection : CompositeDrawable + public class PathControlPointConnectionPiece : CompositeDrawable { public PathControlPoint ControlPoint; @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private IBindable sliderPosition; private IBindable pathVersion; - public PathControlPointConnection(Slider slider, PathControlPoint controlPoint) + public PathControlPointConnectionPiece(Slider slider, PathControlPoint controlPoint) { this.slider = slider; ControlPoint = controlPoint; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 64a8faa02a..a97c0b4a72 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { internal readonly Container Pieces; - private readonly Container connections; + private readonly Container connections; private readonly Slider slider; @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components InternalChildren = new Drawable[] { - connections = new Container { RelativeSizeAxes = Axes.Both }, + connections = new Container { RelativeSizeAxes = Axes.Both }, Pieces = new Container { RelativeSizeAxes = Axes.Both } }; } @@ -78,7 +78,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components d.RequestSelection = selectPiece; })); - connections.Add(new PathControlPointConnection(slider, point)); + connections.Add(new PathControlPointConnectionPiece(slider, point)); } } From 50377e728637b48c96769e1917cc628e4e70a1c9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Dec 2019 20:14:16 +0900 Subject: [PATCH 4444/5608] Add summary xmldoc --- .../Sliders/Components/PathControlPointConnectionPiece.cs | 3 +++ .../Blueprints/Sliders/Components/PathControlPointPiece.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs index 4dfe7834fd..0fc441fec6 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs @@ -11,6 +11,9 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { + /// + /// A visualisation of the line between two s. + /// public class PathControlPointConnectionPiece : CompositeDrawable { public PathControlPoint ControlPoint; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 42812ff934..6a0730db91 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -18,6 +18,9 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { + /// + /// A visualisation of a single in a . + /// public class PathControlPointPiece : BlueprintPiece { public Action RequestSelection; From b795532aa5db67c7c0e5242c3607dcede7b9fbc1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Dec 2019 19:43:16 +0800 Subject: [PATCH 4445/5608] add difficulty adjustment mods --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 6 +++ .../Mods/CatchModDifficultyAdjust.cs | 51 ++++++++++++++++++ osu.Game.Rulesets.Mania/ManiaRuleset.cs | 1 + .../Mods/ManiaModDifficultyAdjust.cs | 22 ++++++++ .../Mods/OsuModDifficultyAdjust.cs | 52 +++++++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 1 + .../Mods/TaikoModDifficultyAdjust.cs | 42 +++++++++++++++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 6 +++ osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 43 +++++++++++++++ 9 files changed, 224 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs create mode 100644 osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs create mode 100644 osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs create mode 100644 osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 71d68ace94..6495c5379b 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -98,6 +98,12 @@ namespace osu.Game.Rulesets.Catch new CatchModFlashlight(), }; + case ModType.Conversion: + return new Mod[] + { + new CatchModDifficultyAdjust(), + }; + case ModType.Automation: return new Mod[] { diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs new file mode 100644 index 0000000000..7dfd5e8964 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs @@ -0,0 +1,51 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModDifficultyAdjust : ModDifficultyAdjust + { + [SettingSource("Drain Rate", "Override the beatmap's set HP")] + public override BindableNumber DrainRate { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 1F, + }; + + [SettingSource("Fruit Size", "Override the beatmap's set CS")] + public override BindableNumber CircleSize { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; + + [SettingSource("Approach Rate", "Override the beatmap's set AR")] + public override BindableNumber ApproachRate { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; + + public override void ApplyToDifficulty(BeatmapDifficulty difficulty) + { + difficulty.DrainRate = DrainRate.Value; + difficulty.CircleSize = CircleSize.Value; + difficulty.ApproachRate = ApproachRate.Value; + difficulty.OverallDifficulty = ApproachRate.Value; + } + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index c74a292331..c4908d1993 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -143,6 +143,7 @@ namespace osu.Game.Rulesets.Mania new ManiaModRandom(), new ManiaModDualStages(), new ManiaModMirror(), + new ManiaModDifficultyAdjust(), }; case ModType.Automation: diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs new file mode 100644 index 0000000000..67e464f7d8 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModDifficultyAdjust : ModDifficultyAdjust + { + [SettingSource("Overall Difficulty", "Override the beatmap's set OD")] + public override BindableNumber OverallDifficulty { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs new file mode 100644 index 0000000000..6851fe0d0a --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs @@ -0,0 +1,52 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModDifficultyAdjust : ModDifficultyAdjust + { + [SettingSource("Drain Rate", "Override the beatmap's set HP")] + public override BindableNumber DrainRate { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; + + [SettingSource("Circle Size", "Override the beatmap's set CS")] + public override BindableNumber CircleSize { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; + + [SettingSource("Approach Rate", "Override the beatmap's set AR")] + public override BindableNumber ApproachRate { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; + + [SettingSource("Overall Difficulty", "Override the beatmap's set OD")] + public override BindableNumber OverallDifficulty { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index fa69cec78d..746876b217 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -121,6 +121,7 @@ namespace osu.Game.Rulesets.Osu return new Mod[] { new OsuModTarget(), + new OsuModDifficultyAdjust(), }; case ModType.Automation: diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs new file mode 100644 index 0000000000..611f74f707 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs @@ -0,0 +1,42 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModDifficultyAdjust : ModDifficultyAdjust + { + [SettingSource("Drain Rate", "Override the beatmap's set HP")] + public override BindableNumber DrainRate { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; + + [SettingSource("Approach Rate", "Override the beatmap's set AR")] + public override BindableNumber ApproachRate { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; + + [SettingSource("Overall Difficulty", "Override the beatmap's set OD")] + public override BindableNumber OverallDifficulty { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index b2655f592c..c4c85c183b 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -97,6 +97,12 @@ namespace osu.Game.Rulesets.Taiko new TaikoModFlashlight(), }; + case ModType.Conversion: + return new Mod[] + { + new TaikoModDifficultyAdjust(), + }; + case ModType.Automation: return new Mod[] { diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs new file mode 100644 index 0000000000..6e7233e4d0 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -0,0 +1,43 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Beatmaps; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Sprites; +using System; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModDifficultyAdjust : Mod, IApplicableToDifficulty + { + public override string Name => @"Difficulty Adjust"; + + public override string Description => @"Override a beatmap's difficulty settings"; + + public override string Acronym => "DA"; + + public override ModType Type => ModType.Conversion; + + public override IconUsage Icon => FontAwesome.Solid.Hammer; + + public override double ScoreMultiplier => 1.0; + + public override Type[] IncompatibleMods => new[] { typeof(ModEasy), typeof(ModHardRock) }; + + public virtual BindableNumber DrainRate { get; } + + public virtual BindableNumber CircleSize { get; } + + public virtual BindableNumber ApproachRate { get; } + + public virtual BindableNumber OverallDifficulty { get; } + + public virtual void ApplyToDifficulty(BeatmapDifficulty difficulty) + { + difficulty.DrainRate = DrainRate != null ? DrainRate.Value : difficulty.DrainRate; + difficulty.CircleSize = CircleSize != null ? CircleSize.Value : difficulty.CircleSize; + difficulty.ApproachRate = ApproachRate != null ? ApproachRate.Value : difficulty.ApproachRate; + difficulty.OverallDifficulty = OverallDifficulty != null ? OverallDifficulty.Value: difficulty.OverallDifficulty; + } + } +} \ No newline at end of file From be3634cce16a53eca471d185218f5b168002a5e7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Dec 2019 20:02:23 +0800 Subject: [PATCH 4446/5608] remove ApproachRate setting --- .../Mods/TaikoModDifficultyAdjust.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs index 611f74f707..7b7bc69aad 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs @@ -19,16 +19,6 @@ namespace osu.Game.Rulesets.Taiko.Mods Precision = 0.1F, }; - [SettingSource("Approach Rate", "Override the beatmap's set AR")] - public override BindableNumber ApproachRate { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; - [SettingSource("Overall Difficulty", "Override the beatmap's set OD")] public override BindableNumber OverallDifficulty { get; } = new BindableFloat { From b0cf44c3bedfa3973be04befbbd1b56771206acc Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Dec 2019 20:12:29 +0800 Subject: [PATCH 4447/5608] fix appveyor issues --- osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs | 2 +- osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs | 2 +- osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs index 7dfd5e8964..6643ebadf1 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs @@ -48,4 +48,4 @@ namespace osu.Game.Rulesets.Catch.Mods difficulty.OverallDifficulty = ApproachRate.Value; } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs index 67e464f7d8..67554e6b92 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs @@ -19,4 +19,4 @@ namespace osu.Game.Rulesets.Mania.Mods Precision = 0.1F, }; } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs index 6851fe0d0a..86ab4579bb 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs @@ -49,4 +49,4 @@ namespace osu.Game.Rulesets.Osu.Mods Precision = 0.1F, }; } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs index 7b7bc69aad..ed76cf77ac 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs @@ -29,4 +29,4 @@ namespace osu.Game.Rulesets.Taiko.Mods Precision = 0.1F, }; } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs index 6e7233e4d0..d1f6bf45b4 100644 --- a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Mods difficulty.DrainRate = DrainRate != null ? DrainRate.Value : difficulty.DrainRate; difficulty.CircleSize = CircleSize != null ? CircleSize.Value : difficulty.CircleSize; difficulty.ApproachRate = ApproachRate != null ? ApproachRate.Value : difficulty.ApproachRate; - difficulty.OverallDifficulty = OverallDifficulty != null ? OverallDifficulty.Value: difficulty.OverallDifficulty; + difficulty.OverallDifficulty = OverallDifficulty != null ? OverallDifficulty.Value : difficulty.OverallDifficulty; } } -} \ No newline at end of file +} From e7a06aeadcefa773cb13efb2f39916b0a66bfd89 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 11 Dec 2019 14:32:43 +0100 Subject: [PATCH 4448/5608] Update NewsOverlay visual tests to expose LoadAndShowChild() for testing purposes --- osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index 546f6ac182..98f90f2daa 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -2,22 +2,28 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Overlays; +using osu.Game.Overlays.News; namespace osu.Game.Tests.Visual.Online { public class TestSceneNewsOverlay : OsuTestScene { - private NewsOverlay news; + private TestNewsOverlay news; protected override void LoadComplete() { base.LoadComplete(); - Add(news = new NewsOverlay()); + Add(news = new TestNewsOverlay()); AddStep(@"Show", news.Show); AddStep(@"Hide", news.Hide); AddStep(@"Show front page", () => news.ShowFrontPage()); AddStep(@"Custom article", () => news.Current.Value = "Test Article 101"); } + + private class TestNewsOverlay : NewsOverlay + { + public new void LoadAndShowChild(NewsContent content) => base.LoadAndShowChild(content); + } } } From caa9286a9091f2482ba4ba5b6879f4894cc675ad Mon Sep 17 00:00:00 2001 From: Albie Date: Wed, 11 Dec 2019 17:39:40 +0000 Subject: [PATCH 4449/5608] update tests, change binding and reduce lines in cinema mod --- .../Background/TestSceneUserDimContainer.cs | 15 +++++++++++---- osu.Game/Graphics/Containers/UserDimContainer.cs | 14 +++++++++++--- osu.Game/Rulesets/Mods/ModCinema.cs | 2 -- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index f867b98fda..fdfde9cc2f 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -155,9 +155,18 @@ namespace osu.Game.Tests.Visual.Background public void DisableUserDisplaySettingsTest() { performFullSetup(); - AddStep("Start ignoring user settings", () => player.DimmableStoryboard.IgnoreUserSettings.Value = true); + createFakeStoryboard(); + AddStep("Enable Storyboard", () => + { + player.ReplacesBackground.Value = true; + player.StoryboardEnabled.Value = true; + }); + AddStep("Enable user dim", () => player.DimmableStoryboard.EnableUserDim.Value = true); + AddStep("Set dim level to 1", () => songSelect.DimLevel.Value = 1f); waitForDim(); - AddAssert("Check the background is undimmed", () => player.IsBackgroundUndimmed()); + AddAssert("Ignore User Settings", () => player.DimmableStoryboard.IgnoreUserSettings.Value = true); + waitForDim(); + AddAssert("User dim settings ignored", () => !player.DimmableStoryboard.EnableUserDim.Value && player.DimmableStoryboard.DimLevel == 0); } /// @@ -365,8 +374,6 @@ namespace osu.Game.Tests.Visual.Background public new DimmableStoryboard DimmableStoryboard => base.DimmableStoryboard; - public bool IsBackgroundUndimmed() => ((FadeAccessibleBackground)Background).CurrentColour == OsuColour.Gray(1); - // Whether or not the player should be allowed to load. public bool BlockLoad; diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index bddbbca0ea..ae4e5557be 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -37,7 +37,7 @@ namespace osu.Game.Graphics.Containers /// public bool ContentDisplayed { get; private set; } - public double DimLevel => EnableUserDim.Value && !IgnoreUserSettings.Value ? UserDimLevel.Value : 0; + public double DimLevel => EnableUserDim.Value ? UserDimLevel.Value : 0; protected Bindable UserDimLevel { get; private set; } @@ -69,7 +69,7 @@ namespace osu.Game.Graphics.Containers ShowStoryboard.ValueChanged += _ => UpdateVisuals(); ShowVideo.ValueChanged += _ => UpdateVisuals(); StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals(); - IgnoreUserSettings.ValueChanged += _ => UpdateVisuals(); + IgnoreUserSettings.ValueChanged += _ => updateSettings(); } protected override void LoadComplete() @@ -91,7 +91,15 @@ namespace osu.Game.Graphics.Containers ContentDisplayed = ShowDimContent; dimContent.FadeTo(ContentDisplayed ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint); - dimContent.FadeColour(IgnoreUserSettings.Value ? Color4.White : OsuColour.Gray(1 - (float)DimLevel), BACKGROUND_FADE_DURATION, Easing.OutQuint); + dimContent.FadeColour(OsuColour.Gray(1 - (float)DimLevel), BACKGROUND_FADE_DURATION, Easing.OutQuint); + } + + /// + /// Invoked when the IgnoreUserSettings bindable is changed + /// + private void updateSettings() + { + EnableUserDim.Value = !IgnoreUserSettings.Value; } } } diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs index 77bf80b149..5faa2f4f3e 100644 --- a/osu.Game/Rulesets/Mods/ModCinema.cs +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -37,8 +37,6 @@ namespace osu.Game.Rulesets.Mods public void ApplyToPlayer(Player player) { player.Background.EnableUserDim.Value = false; - player.DimmableVideo.EnableUserDim.Value = false; - player.DimmableStoryboard.EnableUserDim.Value = false; player.DimmableVideo.IgnoreUserSettings.Value = true; player.DimmableStoryboard.IgnoreUserSettings.Value = true; From 2ca722423b76898ca121bf3dee1444f552f03d4a Mon Sep 17 00:00:00 2001 From: Albie Date: Wed, 11 Dec 2019 18:58:14 +0000 Subject: [PATCH 4450/5608] remove uneccesary using statement --- osu.Game/Graphics/Containers/UserDimContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index ae4e5557be..f83b85e023 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -6,7 +6,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; -using osuTK.Graphics; namespace osu.Game.Graphics.Containers { From 663405d17d4ffeb6e74063db2fddd33f6715bc72 Mon Sep 17 00:00:00 2001 From: Albie Date: Wed, 11 Dec 2019 19:55:45 +0000 Subject: [PATCH 4451/5608] reduce test length and fix the poorly worded description --- .../Background/TestSceneUserDimContainer.cs | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index fdfde9cc2f..52f8fe0a2e 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -119,11 +119,7 @@ namespace osu.Game.Tests.Visual.Background { performFullSetup(); createFakeStoryboard(); - AddStep("Enable Storyboard", () => - { - player.ReplacesBackground.Value = true; - player.StoryboardEnabled.Value = true; - }); + enableStoryboard(); waitForDim(); AddAssert("Background is invisible, storyboard is visible", () => songSelect.IsBackgroundInvisible() && player.IsStoryboardVisible); AddStep("Disable Storyboard", () => @@ -149,22 +145,17 @@ namespace osu.Game.Tests.Visual.Background } /// - /// Ensure is able to disable user-defined display settings. + /// Ensure can disable user-defined display settings. /// [Test] public void DisableUserDisplaySettingsTest() { performFullSetup(); createFakeStoryboard(); - AddStep("Enable Storyboard", () => - { - player.ReplacesBackground.Value = true; - player.StoryboardEnabled.Value = true; - }); + enableStoryboard(); AddStep("Enable user dim", () => player.DimmableStoryboard.EnableUserDim.Value = true); - AddStep("Set dim level to 1", () => songSelect.DimLevel.Value = 1f); waitForDim(); - AddAssert("Ignore User Settings", () => player.DimmableStoryboard.IgnoreUserSettings.Value = true); + AddAssert("Ignore user settings", () => player.DimmableStoryboard.IgnoreUserSettings.Value = true); waitForDim(); AddAssert("User dim settings ignored", () => !player.DimmableStoryboard.EnableUserDim.Value && player.DimmableStoryboard.DimLevel == 0); } @@ -194,11 +185,7 @@ namespace osu.Game.Tests.Visual.Background { performFullSetup(); createFakeStoryboard(); - AddStep("Enable Storyboard", () => - { - player.ReplacesBackground.Value = true; - player.StoryboardEnabled.Value = true; - }); + enableStoryboard(); AddStep("Enable user dim", () => player.DimmableStoryboard.EnableUserDim.Value = true); AddStep("Set dim level to 1", () => songSelect.DimLevel.Value = 1f); waitForDim(); @@ -285,6 +272,12 @@ namespace osu.Game.Tests.Visual.Background }); }); + private void enableStoryboard() => AddStep("Enable Storyboard", () => + { + player.ReplacesBackground.Value = true; + player.StoryboardEnabled.Value = true; + }); + private void performFullSetup(bool allowPause = false) { setupUserSettings(); From bc02cfc2e24cdaa26832f004b8ad8910b5b8342c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Dec 2019 00:30:16 +0300 Subject: [PATCH 4452/5608] TestSceneUserDimContainer -> TestSceneUserDimBackgrounds --- ...tSceneUserDimContainer.cs => TestSceneUserDimBackgrounds.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Tests/Visual/Background/{TestSceneUserDimContainer.cs => TestSceneUserDimBackgrounds.cs} (99%) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs similarity index 99% rename from osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs rename to osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs index 910c462718..2d2726bbd3 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs @@ -36,7 +36,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Background { [TestFixture] - public class TestSceneUserDimContainer : ManualInputManagerTestScene + public class TestSceneUserDimBackgrounds : ManualInputManagerTestScene { public override IReadOnlyList RequiredTypes => new[] { From 4f6b85e5ea19381ab19a2ebdab80336bcf4a59e0 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Dec 2019 00:32:39 +0300 Subject: [PATCH 4453/5608] Add test ensuring correct break lightening behaviour --- .../Background/TestSceneUserDimContainer.cs | 82 +++++++++++++++++++ .../Graphics/Containers/UserDimContainer.cs | 5 +- 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs new file mode 100644 index 0000000000..0aad9bed75 --- /dev/null +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -0,0 +1,82 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Configuration; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Background +{ + public class TestSceneUserDimContainer : OsuTestScene + { + private readonly TestUserDimContainer container; + private readonly BindableBool isBreakTime = new BindableBool(); + private readonly Bindable lightenDuringBreaks = new Bindable(); + + public TestSceneUserDimContainer() + { + Add(container = new TestUserDimContainer + { + RelativeSizeAxes = Axes.Both, + Child = new Box + { + Colour = Color4.White, + RelativeSizeAxes = Axes.Both, + }, + }); + + container.IsBreakTime.BindTo(isBreakTime); + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + config.BindWith(OsuSetting.LightenDuringBreaks, lightenDuringBreaks); + } + + [SetUp] + public void SetUp() + { + isBreakTime.Value = false; + lightenDuringBreaks.Value = false; + } + + [TestCase(0.6f, 0.3f)] + [TestCase(0.2f, 0.0f)] + [TestCase(0.0f, 0.0f)] + public void TestBreakLightening(float userDim, float expectedBreakDim) + { + AddStep($"set dim level {userDim}", () => container.UserDimLevel.Value = userDim); + + AddStep("set break", () => isBreakTime.Value = true); + AddWaitStep("wait for dim", 3); + AddAssert($"is current dim {userDim}", () => container.DimEqual(userDim)); + + AddStep("set lighten during break", () => lightenDuringBreaks.Value = true); + AddWaitStep("wait for dim", 3); + AddAssert($"is current dim {expectedBreakDim}", () => container.DimEqual(expectedBreakDim)); + + AddStep("clear lighten during break", () => lightenDuringBreaks.Value = false); + AddWaitStep("wait for dim", 3); + AddAssert($"is current dim {userDim}", () => container.DimEqual(userDim)); + + AddStep("clear break", () => isBreakTime.Value = false); + AddStep("set lighten during break", () => lightenDuringBreaks.Value = true); + AddWaitStep("wait for dim", 3); + AddAssert($"is current dim {userDim}", () => container.DimEqual(userDim)); + } + + private class TestUserDimContainer : UserDimContainer + { + public bool DimEqual(float expectedDimLevel) => Content.Colour == OsuColour.Gray(1f - expectedDimLevel); + + public new Bindable UserDimLevel => base.UserDimLevel; + } + } +} diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 20f5a4fd83..dcc8a52e9d 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -16,6 +16,9 @@ namespace osu.Game.Graphics.Containers /// public abstract class UserDimContainer : Container { + /// + /// Amount of lightening to apply to current dim level during break times. + /// private const float break_lighten_amount = 0.3f; protected const double BACKGROUND_FADE_DURATION = 800; @@ -34,7 +37,7 @@ namespace osu.Game.Graphics.Containers /// Whether player is in break time. /// Must be bound to to allow for dim adjustments in gameplay. /// - internal readonly IBindable IsBreakTime = new Bindable(); + public readonly IBindable IsBreakTime = new Bindable(); /// /// Whether the content of this container is currently being displayed. From 61265ed452d14b2353bc5957ae5af6b25e442a2b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Dec 2019 00:52:33 +0300 Subject: [PATCH 4454/5608] Increase the waiting steps --- .../Visual/Background/TestSceneUserDimContainer.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index 0aad9bed75..bdbfacaea2 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -55,20 +55,20 @@ namespace osu.Game.Tests.Visual.Background AddStep($"set dim level {userDim}", () => container.UserDimLevel.Value = userDim); AddStep("set break", () => isBreakTime.Value = true); - AddWaitStep("wait for dim", 3); + AddWaitStep("wait for dim", 5); AddAssert($"is current dim {userDim}", () => container.DimEqual(userDim)); AddStep("set lighten during break", () => lightenDuringBreaks.Value = true); - AddWaitStep("wait for dim", 3); + AddWaitStep("wait for dim", 5); AddAssert($"is current dim {expectedBreakDim}", () => container.DimEqual(expectedBreakDim)); AddStep("clear lighten during break", () => lightenDuringBreaks.Value = false); - AddWaitStep("wait for dim", 3); + AddWaitStep("wait for dim", 5); AddAssert($"is current dim {userDim}", () => container.DimEqual(userDim)); AddStep("clear break", () => isBreakTime.Value = false); AddStep("set lighten during break", () => lightenDuringBreaks.Value = true); - AddWaitStep("wait for dim", 3); + AddWaitStep("wait for dim", 5); AddAssert($"is current dim {userDim}", () => container.DimEqual(userDim)); } From 035a53cb9e2edb0f232369aa933989b2c0b3fdb8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Dec 2019 01:10:43 +0300 Subject: [PATCH 4455/5608] Schedule SetUp() --- osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index bdbfacaea2..25c11d2292 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -41,11 +41,11 @@ namespace osu.Game.Tests.Visual.Background } [SetUp] - public void SetUp() + public void SetUp() => Schedule(() => { isBreakTime.Value = false; lightenDuringBreaks.Value = false; - } + }); [TestCase(0.6f, 0.3f)] [TestCase(0.2f, 0.0f)] From 472fa9822cc7409487935ea6e0657e8c52a38594 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Dec 2019 08:25:51 +0800 Subject: [PATCH 4456/5608] make ModDifficultyAdjust incompatible with ModEasy and ModHardRock --- osu.Game/Rulesets/Mods/ModEasy.cs | 2 +- osu.Game/Rulesets/Mods/ModHardRock.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index a55ebc51d6..7a34b2de3c 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.DifficultyReduction; public override double ScoreMultiplier => 0.5; public override bool Ranked => true; - public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) }; + public override Type[] IncompatibleMods => new[] { typeof(ModHardRock), typeof(ModDifficultyAdjust) }; private int retries = 2; diff --git a/osu.Game/Rulesets/Mods/ModHardRock.cs b/osu.Game/Rulesets/Mods/ModHardRock.cs index 2044cbeae2..2bcac3e4a9 100644 --- a/osu.Game/Rulesets/Mods/ModHardRock.cs +++ b/osu.Game/Rulesets/Mods/ModHardRock.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mods public override IconUsage Icon => OsuIcon.ModHardrock; public override ModType Type => ModType.DifficultyIncrease; public override string Description => "Everything just got a bit harder..."; - public override Type[] IncompatibleMods => new[] { typeof(ModEasy) }; + public override Type[] IncompatibleMods => new[] { typeof(ModEasy), typeof(ModDifficultyAdjust) }; public void ApplyToDifficulty(BeatmapDifficulty difficulty) { From 606bd33aa664fa4d50d15c0b23340ddb52c64274 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 13:04:32 +0900 Subject: [PATCH 4457/5608] Use beatmap background in editor --- osu.Game/Screens/Edit/Editor.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 33a4c48d28..1b4964c068 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -4,7 +4,6 @@ using System; using osuTK.Graphics; using osu.Framework.Screens; -using osu.Game.Screens.Backgrounds; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -29,14 +28,13 @@ using osu.Game.Input.Bindings; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Setup; using osu.Game.Screens.Edit.Timing; +using osu.Game.Screens.Play; using osu.Game.Users; namespace osu.Game.Screens.Edit { - public class Editor : OsuScreen, IKeyBindingHandler + public class Editor : ScreenWithBeatmapBackground, IKeyBindingHandler { - protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4"); - public override float BackgroundParallaxAmount => 0.1f; public override bool AllowBackButton => false; @@ -250,8 +248,12 @@ namespace osu.Game.Screens.Edit { base.OnEntering(last); + // todo: temporary. we want to be applying dim using the UserDimContainer eventually. Background.FadeColour(Color4.DarkGray, 500); + Background.EnableUserDim.Value = false; + Background.BlurAmount.Value = 0; + resetTrack(true); } From b6c86d512a5c7c5ffcb87b362e956c6457b8fd1d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 13:28:27 +0900 Subject: [PATCH 4458/5608] 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 3cd4dc48bf..252570a150 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 530d62f583..a07348b57c 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 fb753b8c6f..544bba3963 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 76a7e9cde82d8a37670802b6ea2d1583b79b7c1c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 14:04:57 +0900 Subject: [PATCH 4459/5608] Catch file exception in test reset --- osu.Game/Database/DatabaseContextFactory.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index bb6bef1c50..1ed5fb3268 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.cs @@ -149,7 +149,15 @@ namespace osu.Game.Database lock (writeLock) { recycleThreadContexts(); - storage.DeleteDatabase(database_name); + + try + { + storage.DeleteDatabase(database_name); + } + catch + { + // for now we are not sure why file handles are kept open by EF, but this is generally only used in testing + } } } } From ad2528d4d2e03a1c355c84934dd73104b1afb81e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 15:05:29 +0900 Subject: [PATCH 4460/5608] Hide key counter along with other hud elements Also tidies up HUD hide logic and protects against incorrect hiding. --- osu.Game/Screens/Play/HUDOverlay.cs | 60 ++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 0f9edf5606..35157fca58 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -43,8 +44,15 @@ namespace osu.Game.Screens.Play private readonly DrawableRuleset drawableRuleset; private readonly IReadOnlyList mods; - private Bindable showHud; + /// + /// Whether the elements that can optionally be hidden should be visible. + /// + public Bindable ShowHud { get; } = new BindableBool(); + + private Bindable configShowHud; + private readonly Container visibilityContainer; + private readonly BindableBool replayLoaded = new BindableBool(); private static bool hasShownNotificationOnce; @@ -53,6 +61,8 @@ namespace osu.Game.Screens.Play private readonly Container topScoreContainer; + private IEnumerable hideTargets => new Drawable[] { visibilityContainer, KeyCounter }; + public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, IReadOnlyList mods) { this.scoreProcessor = scoreProcessor; @@ -73,8 +83,6 @@ namespace osu.Game.Screens.Play Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both, - AutoSizeDuration = 200, - AutoSizeEasing = Easing.Out, Children = new Drawable[] { AccuracyCounter = CreateAccuracyCounter(), @@ -95,6 +103,8 @@ namespace osu.Game.Screens.Play Origin = Anchor.BottomRight, Position = -new Vector2(5, TwoLayerButton.SIZE_RETRACTED.Y), AutoSizeAxes = Axes.Both, + AutoSizeDuration = 150, + AutoSizeEasing = Easing.OutQuint, Direction = FillDirection.Vertical, Children = new Drawable[] { @@ -118,8 +128,29 @@ namespace osu.Game.Screens.Play ModDisplay.Current.Value = mods; - showHud = config.GetBindable(OsuSetting.ShowInterface); - showHud.BindValueChanged(visible => visibilityContainer.FadeTo(visible.NewValue ? 1 : 0, duration, easing), true); + configShowHud = config.GetBindable(OsuSetting.ShowInterface); + + if (!configShowHud.Value && !hasShownNotificationOnce) + { + hasShownNotificationOnce = true; + + notificationOverlay?.Post(new SimpleNotification + { + Text = @"The score overlay is currently disabled. You can toggle this by pressing Shift+Tab." + }); + } + + // start all elements hidden + hideTargets.ForEach(d => d.Hide()); + } + + public override void Hide() => throw new InvalidOperationException($"{nameof(HUDOverlay)} should not be hidden as it will remove the ability of a user to quit. Use {nameof(ShowHud)} instead."); + + protected override void LoadComplete() + { + base.LoadComplete(); + + ShowHud.BindValueChanged(visible => hideTargets.ForEach(d => d.FadeTo(visible.NewValue ? 1 : 0, duration, easing))); ShowHealthbar.BindValueChanged(healthBar => { @@ -135,20 +166,11 @@ namespace osu.Game.Screens.Play } }, true); - if (!showHud.Value && !hasShownNotificationOnce) + configShowHud.BindValueChanged(visible => { - hasShownNotificationOnce = true; - - notificationOverlay?.Post(new SimpleNotification - { - Text = @"The score overlay is currently disabled. You can toggle this by pressing Shift+Tab." - }); - } - } - - protected override void LoadComplete() - { - base.LoadComplete(); + if (!ShowHud.Disabled) + ShowHud.Value = visible.NewValue; + }, true); replayLoaded.BindValueChanged(replayLoadedValueChanged, true); } @@ -189,7 +211,7 @@ namespace osu.Game.Screens.Play switch (e.Key) { case Key.Tab: - showHud.Value = !showHud.Value; + configShowHud.Value = !configShowHud.Value; return true; } } From ffb5cdc6aef7056a8430cd76f79299d5ee087d84 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 14:19:04 +0900 Subject: [PATCH 4461/5608] Hide settings overlay along with other HUD-hidden content --- osu.Game/Screens/Play/HUDOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 35157fca58..64c3cddf2a 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -94,9 +94,9 @@ namespace osu.Game.Screens.Play Progress = CreateProgress(), ModDisplay = CreateModsContainer(), HitErrorDisplay = CreateHitErrorDisplayOverlay(), + PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), } }, - PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), new FillFlowContainer { Anchor = Anchor.BottomRight, From 6a539e307a2bdab3517ee840ee542dcf462c162c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Dec 2019 09:20:56 +0300 Subject: [PATCH 4462/5608] Split into small tests and add more cases --- .../Background/TestSceneUserDimContainer.cs | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index 25c11d2292..03206402c3 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -53,23 +53,37 @@ namespace osu.Game.Tests.Visual.Background public void TestBreakLightening(float userDim, float expectedBreakDim) { AddStep($"set dim level {userDim}", () => container.UserDimLevel.Value = userDim); + AddStep("set lighten during break", () => lightenDuringBreaks.Value = true); AddStep("set break", () => isBreakTime.Value = true); - AddWaitStep("wait for dim", 5); - AddAssert($"is current dim {userDim}", () => container.DimEqual(userDim)); - - AddStep("set lighten during break", () => lightenDuringBreaks.Value = true); - AddWaitStep("wait for dim", 5); - AddAssert($"is current dim {expectedBreakDim}", () => container.DimEqual(expectedBreakDim)); - - AddStep("clear lighten during break", () => lightenDuringBreaks.Value = false); - AddWaitStep("wait for dim", 5); - AddAssert($"is current dim {userDim}", () => container.DimEqual(userDim)); - + AddUntilStep("has lightened", () => container.DimEqual(expectedBreakDim)); AddStep("clear break", () => isBreakTime.Value = false); + AddUntilStep("not lightened", () => container.DimEqual(userDim)); + } + + [Test] + public void TestEnableSettingDuringBreak() + { + AddStep("set dim level 0.6", () => container.UserDimLevel.Value = 0.6f); + + AddStep("set break", () => isBreakTime.Value = true); + AddUntilStep("not lightened", () => container.DimEqual(0.6f)); AddStep("set lighten during break", () => lightenDuringBreaks.Value = true); - AddWaitStep("wait for dim", 5); - AddAssert($"is current dim {userDim}", () => container.DimEqual(userDim)); + AddUntilStep("has lightened", () => container.DimEqual(0.3f)); + } + + [Test] + public void TestDisableSettingDuringBreak() + { + AddStep("set dim level 0.6", () => container.UserDimLevel.Value = 0.6f); + AddStep("set lighten during break", () => lightenDuringBreaks.Value = true); + + AddStep("set break", () => isBreakTime.Value = true); + AddUntilStep("has lightened", () => container.DimEqual(0.3f)); + AddStep("clear lighten during break", () => lightenDuringBreaks.Value = false); + AddUntilStep("not lightened", () => container.DimEqual(0.6f)); + AddStep("clear break", () => isBreakTime.Value = false); + AddUntilStep("not lightened", () => container.DimEqual(0.6f)); } private class TestUserDimContainer : UserDimContainer From 4c4199269c267c32ee651369e183c0e4d62a477a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 15:25:37 +0900 Subject: [PATCH 4463/5608] Use protected constructors --- osu.Game/Rulesets/Mods/ModDaycore.cs | 2 +- osu.Game/Rulesets/Mods/ModNightcore.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index 9445895fb0..71a666414f 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mods private readonly BindableNumber tempoAdjust = new BindableDouble(1); private readonly BindableNumber freqAdjust = new BindableDouble(1); - public ModDaycore() + protected ModDaycore() { SpeedChange.BindValueChanged(val => { diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 9b27925693..c14e02e64d 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mods private readonly BindableNumber tempoAdjust = new BindableDouble(1); private readonly BindableNumber freqAdjust = new BindableDouble(1); - public ModNightcore() + protected ModNightcore() { SpeedChange.BindValueChanged(val => { From 5861eca80d291bbfd6261ca732d4101012a86713 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 15:58:11 +0900 Subject: [PATCH 4464/5608] Make DrawableRuleset take a converted beatmap --- .../TestSceneDrawableHitObjects.cs | 2 +- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- .../UI/DrawableCatchRuleset.cs | 4 +- .../Edit/DrawableManiaEditRuleset.cs | 2 +- .../Edit/ManiaHitObjectComposer.cs | 2 +- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../UI/DrawableManiaRuleset.cs | 2 +- .../Edit/DrawableOsuEditRuleset.cs | 2 +- .../Edit/OsuHitObjectComposer.cs | 2 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../UI/DrawableOsuRuleset.cs | 2 +- .../TestSceneTaikoPlayfield.cs | 3 +- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- .../UI/DrawableTaikoRuleset.cs | 2 +- .../TestSceneDrawableScrollingRuleset.cs | 6 +-- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/IWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 4 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 8 ++-- osu.Game/Rulesets/Ruleset.cs | 2 +- osu.Game/Rulesets/UI/DrawableRuleset.cs | 18 ++++---- .../UI/Scrolling/DrawableScrollingRuleset.cs | 2 +- osu.Game/Screens/Play/Player.cs | 41 ++++++++++--------- 23 files changed, 59 insertions(+), 57 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs index 0369b6db4e..02a017ce45 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Catch.Tests RelativeSizeAxes = Axes.Both, Children = new[] { - drawableRuleset = new DrawableCatchRuleset(new CatchRuleset(), beatmap, Array.Empty()) + drawableRuleset = new DrawableCatchRuleset(new CatchRuleset(), beatmap.GetPlayableBeatmap(new CatchRuleset().RulesetInfo)) } }); diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 71d68ace94..506fa23fa9 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch { public class CatchRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableCatchRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableCatchRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index f5bddeb2cb..278ff97195 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -25,11 +25,11 @@ namespace osu.Game.Rulesets.Catch.UI protected override bool UserScrollSpeedAdjustment => false; - public DrawableCatchRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) + public DrawableCatchRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset, beatmap, mods) { Direction.Value = ScrollingDirection.Down; - TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450); + TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450); } public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(Beatmap); diff --git a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs index 97d8aaa052..445df79f6f 100644 --- a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs +++ b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Edit { public new IScrollingInfo ScrollingInfo => base.ScrollingInfo; - public DrawableManiaEditRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) + public DrawableManiaEditRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 0bfe6f9517..1632b6a583 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.Edit public int TotalColumns => ((ManiaPlayfield)drawableRuleset.Playfield).TotalColumns; - protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) + protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) { drawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap, mods); diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index c74a292331..a96c79b40b 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Mania { public class ManiaRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableManiaRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableManiaRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score); diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 0607bf0abd..cf1970c28b 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly Bindable configDirection = new Bindable(); - public DrawableManiaRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) + public DrawableManiaRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset, beatmap, mods) { BarLines = new BarLineGenerator(Beatmap).BarLines; diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs index 3437af8c1e..22b4c3e82e 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Edit /// private const double editor_hit_object_fade_out_extension = 500; - public DrawableOsuEditRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) + public DrawableOsuEditRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 812afaaa24..675b09fc6d 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Edit { } - protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) + protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableOsuEditRuleset(ruleset, beatmap, mods); protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index fa69cec78d..2f43909332 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu { public class OsuRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableOsuRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableOsuRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index 5bb728a9b0..039d38e4fd 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.UI { protected new OsuRulesetConfigManager Config => (OsuRulesetConfigManager)base.Config; - public DrawableOsuRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) + public DrawableOsuRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index 8522a42739..b2c8c7feda 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -11,7 +11,6 @@ using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; @@ -91,7 +90,7 @@ namespace osu.Game.Rulesets.Taiko.Tests Origin = Anchor.Centre, RelativeSizeAxes = Axes.X, Height = 768, - Children = new[] { drawableRuleset = new DrawableTaikoRuleset(new TaikoRuleset(), beatmap, Array.Empty()) } + Children = new[] { drawableRuleset = new DrawableTaikoRuleset(new TaikoRuleset(), beatmap.GetPlayableBeatmap(new TaikoRuleset().RulesetInfo)) } }); } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index b2655f592c..ab9c95159c 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko { public class TaikoRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableTaikoRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableTaikoRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); public const string SHORT_NAME = "taiko"; diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index d4ea9a043a..2233658428 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.UI protected override bool UserScrollSpeedAdjustment => false; - public DrawableTaikoRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) + public DrawableTaikoRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset, beatmap, mods) { Direction.Value = ScrollingDirection.Left; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index 684e79b3f5..071dc381e0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -172,7 +172,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var ruleset = new TestScrollingRuleset(); - drawableRuleset = (TestDrawableScrollingRuleset)ruleset.CreateDrawableRulesetWith(CreateWorkingBeatmap(beatmap), Array.Empty()); + drawableRuleset = (TestDrawableScrollingRuleset)ruleset.CreateDrawableRulesetWith(beatmap); drawableRuleset.FrameStablePlayback = false; overrideAction?.Invoke(drawableRuleset); @@ -201,7 +201,7 @@ namespace osu.Game.Tests.Visual.Gameplay public override IEnumerable GetModsFor(ModType type) => throw new NotImplementedException(); - public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => new TestDrawableScrollingRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new TestDrawableScrollingRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap); @@ -222,7 +222,7 @@ namespace osu.Game.Tests.Visual.Gameplay public new Bindable TimeRange => base.TimeRange; - public TestDrawableScrollingRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) + public TestDrawableScrollingRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset, beatmap, mods) { TimeRange.Value = time_range; diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index a3ab01c886..59a27e3fde 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -57,7 +57,7 @@ namespace osu.Game.Beatmaps { public override IEnumerable GetModsFor(ModType type) => new Mod[] { }; - public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) { throw new NotImplementedException(); } diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index a087a52ada..5f1f0d1e40 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -62,6 +62,6 @@ namespace osu.Game.Beatmaps /// The s to apply to the . /// The converted . /// If could not be converted to . - IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods); + IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods = null); } } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 4452d26fcd..1255665cf0 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -99,8 +99,10 @@ namespace osu.Game.Beatmaps /// The applicable . protected virtual IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) => ruleset.CreateBeatmapConverter(beatmap); - public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods) + public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods = null) { + mods ??= Array.Empty(); + var rulesetInstance = ruleset.CreateInstance(); IBeatmapConverter converter = CreateBeatmapConverter(Beatmap, rulesetInstance); diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 9ac967ef74..22d94abcb9 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -48,7 +48,6 @@ namespace osu.Game.Rulesets.Edit [Resolved] private BindableBeatDivisor beatDivisor { get; set; } - private IWorkingBeatmap workingBeatmap; private Beatmap playableBeatmap; private IBeatmapProcessor beatmapProcessor; @@ -71,7 +70,7 @@ namespace osu.Game.Rulesets.Edit { try { - drawableRulesetWrapper = new DrawableEditRulesetWrapper(CreateDrawableRuleset(Ruleset, workingBeatmap, Array.Empty())) + drawableRulesetWrapper = new DrawableEditRulesetWrapper(CreateDrawableRuleset(Ruleset, playableBeatmap)) { Clock = framedClock, ProcessCustomClock = false @@ -145,8 +144,7 @@ namespace osu.Game.Rulesets.Edit { var parentWorkingBeatmap = parent.Get>().Value; - playableBeatmap = (Beatmap)parentWorkingBeatmap.GetPlayableBeatmap(Ruleset.RulesetInfo, Array.Empty()); - workingBeatmap = new EditorWorkingBeatmap(playableBeatmap, parentWorkingBeatmap); + playableBeatmap = (Beatmap)parentWorkingBeatmap.GetPlayableBeatmap(Ruleset.RulesetInfo); beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap); @@ -250,7 +248,7 @@ namespace osu.Game.Rulesets.Edit protected abstract IReadOnlyList CompositionTools { get; } - protected abstract DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods); + protected abstract DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null); public void BeginPlacement(HitObject hitObject) { diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index dd1b3615c7..45aa904b98 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -60,7 +60,7 @@ namespace osu.Game.Rulesets /// The s to apply. /// Unable to successfully load the beatmap to be usable with this ruleset. /// - public abstract DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods); + public abstract DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null); /// /// Creates a to convert a to one that is applicable for this . diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 10657f6b39..5033fd0686 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.UI /// /// The beatmap. /// - public Beatmap Beatmap; + public readonly Beatmap Beatmap; public override IEnumerable Objects => Beatmap.HitObjects; @@ -118,20 +118,22 @@ namespace osu.Game.Rulesets.UI /// Creates a ruleset visualisation for the provided ruleset and beatmap. /// /// The ruleset being represented. - /// The beatmap to create the hit renderer for. + /// The beatmap to create the hit renderer for. /// The s to apply. - protected DrawableRuleset(Ruleset ruleset, IWorkingBeatmap workingBeatmap, IReadOnlyList mods) + protected DrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset) { - if (workingBeatmap == null) - throw new ArgumentException("Beatmap cannot be null.", nameof(workingBeatmap)); + if (beatmap == null) + throw new ArgumentNullException(nameof(beatmap), "Beatmap cannot be null."); - this.mods = mods.ToArray(); + if (!(beatmap is Beatmap tBeatmap)) + throw new ArgumentException($"{GetType()} expected the beatmap to contain hitobjects of type {typeof(TObject)}.", nameof(beatmap)); + + Beatmap = tBeatmap; + this.mods = mods?.ToArray() ?? Array.Empty(); RelativeSizeAxes = Axes.Both; - Beatmap = (Beatmap)workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo, mods); - KeyBindingInputManager = CreateInputManager(); playfield = new Lazy(CreatePlayfield); diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index cf714b5d46..fda1d7c723 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.UI.Scrolling [Cached(Type = typeof(IScrollingInfo))] private readonly LocalScrollingInfo scrollingInfo; - protected DrawableScrollingRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) + protected DrawableScrollingRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset, beatmap, mods) { scrollingInfo = new LocalScrollingInfo(); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 9f4ca7d817..b65d20dcbb 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -114,26 +114,31 @@ namespace osu.Game.Screens.Play Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray(); - WorkingBeatmap working = loadBeatmap(); + if (Beatmap.Value is DummyWorkingBeatmap) + return; - if (working == null) + IBeatmap playableBeatmap = loadPlayableBeatmap(); + + if (playableBeatmap == null) return; sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); + DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value); + ScoreProcessor = DrawableRuleset.CreateScoreProcessor(); ScoreProcessor.Mods.BindTo(Mods); if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); - InternalChild = GameplayClockContainer = new GameplayClockContainer(working, Mods.Value, DrawableRuleset.GameplayStartTime); + InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, Mods.Value, DrawableRuleset.GameplayStartTime); addUnderlayComponents(GameplayClockContainer); - addGameplayComponents(GameplayClockContainer, working); - addOverlayComponents(GameplayClockContainer, working); + addGameplayComponents(GameplayClockContainer, Beatmap.Value); + addOverlayComponents(GameplayClockContainer, Beatmap.Value); DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updatePauseOnFocusLostState(), true); @@ -250,36 +255,32 @@ namespace osu.Game.Screens.Play && !DrawableRuleset.HasReplayLoaded.Value && !breakOverlay.IsBreakTime.Value; - private WorkingBeatmap loadBeatmap() + private IBeatmap loadPlayableBeatmap() { - WorkingBeatmap working = Beatmap.Value; - if (working is DummyWorkingBeatmap) - return null; + IBeatmap playable; try { - var beatmap = working.Beatmap; - - if (beatmap == null) + if (Beatmap.Value.Beatmap == null) throw new InvalidOperationException("Beatmap was not loaded"); - rulesetInfo = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset; + rulesetInfo = Ruleset.Value ?? Beatmap.Value.BeatmapInfo.Ruleset; ruleset = rulesetInfo.CreateInstance(); try { - DrawableRuleset = ruleset.CreateDrawableRulesetWith(working, Mods.Value); + playable = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Mods.Value); } catch (BeatmapInvalidForRulesetException) { - // we may fail to create a DrawableRuleset if the beatmap cannot be loaded with the user's preferred ruleset - // let's try again forcing the beatmap's ruleset. - rulesetInfo = beatmap.BeatmapInfo.Ruleset; + // A playable beatmap may not be creatable with the user's preferred ruleset, so try using the beatmap's default ruleset + rulesetInfo = Beatmap.Value.BeatmapInfo.Ruleset; ruleset = rulesetInfo.CreateInstance(); - DrawableRuleset = ruleset.CreateDrawableRulesetWith(Beatmap.Value, Mods.Value); + + playable = Beatmap.Value.GetPlayableBeatmap(rulesetInfo, Mods.Value); } - if (!DrawableRuleset.Objects.Any()) + if (playable.HitObjects.Count == 0) { Logger.Log("Beatmap contains no hit objects!", level: LogLevel.Error); return null; @@ -292,7 +293,7 @@ namespace osu.Game.Screens.Play return null; } - return working; + return playable; } private void performImmediateExit() From 59345c97e4d3ec412d4d1b519f3021eb3988d70c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 15:58:31 +0900 Subject: [PATCH 4465/5608] Remove now unnecessary editor working beatmap --- osu.Game/Screens/Edit/EditorWorkingBeatmap.cs | 49 ------------------- 1 file changed, 49 deletions(-) delete mode 100644 osu.Game/Screens/Edit/EditorWorkingBeatmap.cs diff --git a/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs b/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs deleted file mode 100644 index 4b8720fe1c..0000000000 --- a/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using osu.Framework.Audio.Track; -using osu.Framework.Graphics.Textures; -using osu.Framework.Graphics.Video; -using osu.Game.Beatmaps; -using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects; -using osu.Game.Skinning; -using osu.Game.Storyboards; - -namespace osu.Game.Screens.Edit -{ - /// - /// Encapsulates a while providing an overridden . - /// - /// - public class EditorWorkingBeatmap : IWorkingBeatmap - where TObject : HitObject - { - private readonly Beatmap playableBeatmap; - private readonly WorkingBeatmap workingBeatmap; - - public EditorWorkingBeatmap(Beatmap playableBeatmap, WorkingBeatmap workingBeatmap) - { - this.playableBeatmap = playableBeatmap; - this.workingBeatmap = workingBeatmap; - } - - public IBeatmap Beatmap => workingBeatmap.Beatmap; - - public Texture Background => workingBeatmap.Background; - - public VideoSprite Video => workingBeatmap.Video; - - public Track Track => workingBeatmap.Track; - - public Waveform Waveform => workingBeatmap.Waveform; - - public Storyboard Storyboard => workingBeatmap.Storyboard; - - public ISkin Skin => workingBeatmap.Skin; - - public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods) => playableBeatmap; - } -} From 3ccfee64f6ff44c82f3b66270f790b951c745da5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 16:09:42 +0900 Subject: [PATCH 4466/5608] Add HUDOverlay tests --- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 81 +++++++++++++++++++ osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 7 +- osu.Game/Screens/Play/HUDOverlay.cs | 19 +++-- 3 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs new file mode 100644 index 0000000000..39c42980ab --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -0,0 +1,81 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestSceneHUDOverlay : ManualInputManagerTestScene + { + private HUDOverlay hudOverlay; + + private Drawable hideTarget => hudOverlay.KeyCounter; // best way of checking hideTargets without exposing. + + [Resolved] + private OsuConfigManager config { get; set; } + + [Test] + public void TestShownByDefault() + { + createNew(); + + AddAssert("showhud is set", () => hudOverlay.ShowHud.Value); + + AddAssert("hidetarget is visible", () => hideTarget.IsPresent); + AddAssert("pause button is visible", () => hudOverlay.HoldToQuit.IsPresent); + } + + [Test] + public void TestFadesInOnLoadComplete() + { + float? initialAlpha = null; + + createNew(h => h.OnLoadComplete += _ => initialAlpha = hideTarget.Alpha); + AddUntilStep("wait for load", () => hudOverlay.IsAlive); + AddAssert("initial alpha was less than 1", () => initialAlpha != null && initialAlpha < 1); + } + + [Test] + public void TestHideExternally() + { + createNew(); + + AddStep("set showhud false", () => hudOverlay.ShowHud.Value = false); + + AddUntilStep("hidetarget is hidden", () => !hideTarget.IsPresent); + AddAssert("pause button is still visible", () => hudOverlay.HoldToQuit.IsPresent); + } + + [Test] + public void TestExternalHideDoesntAffectConfig() + { + bool originalConfigValue = false; + + createNew(); + + AddStep("get original config value", () => originalConfigValue = config.Get(OsuSetting.ShowInterface)); + + AddStep("set showhud false", () => hudOverlay.ShowHud.Value = false); + AddAssert("config unchanged", () => originalConfigValue == config.Get(OsuSetting.ShowInterface)); + + AddStep("set showhud true", () => hudOverlay.ShowHud.Value = true); + AddAssert("config unchanged", () => originalConfigValue == config.Get(OsuSetting.ShowInterface)); + } + + private void createNew(Action action = null) + { + AddStep("create overlay", () => + { + Child = hudOverlay = new HUDOverlay(null, null, Array.Empty()); + + action?.Invoke(hudOverlay); + }); + } + } +} diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 54556f8648..6196ce4026 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -31,7 +31,8 @@ namespace osu.Game.Screens.Play.HUD RelativeSizeAxes = Axes.Both; - processor.NewJudgement += onNewJudgement; + if (processor != null) + processor.NewJudgement += onNewJudgement; } [BackgroundDependencyLoader] @@ -96,7 +97,9 @@ namespace osu.Game.Screens.Play.HUD protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - processor.NewJudgement -= onNewJudgement; + + if (processor != null) + processor.NewJudgement -= onNewJudgement; } } } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 64c3cddf2a..7df780b678 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -118,13 +118,18 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader(true)] private void load(OsuConfigManager config, NotificationOverlay notificationOverlay) { - BindProcessor(scoreProcessor); - BindDrawableRuleset(drawableRuleset); + if (scoreProcessor != null) + BindProcessor(scoreProcessor); - Progress.Objects = drawableRuleset.Objects; - Progress.AllowSeeking = drawableRuleset.HasReplayLoaded.Value; - Progress.RequestSeek = time => RequestSeek(time); - Progress.ReferenceClock = drawableRuleset.FrameStableClock; + if (drawableRuleset != null) + { + BindDrawableRuleset(drawableRuleset); + + Progress.Objects = drawableRuleset.Objects; + Progress.AllowSeeking = drawableRuleset.HasReplayLoaded.Value; + Progress.RequestSeek = time => RequestSeek(time); + Progress.ReferenceClock = drawableRuleset.FrameStableClock; + } ModDisplay.Current.Value = mods; @@ -279,7 +284,7 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20, Right = 10 }, }; - protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset.FirstAvailableHitWindows); + protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset?.FirstAvailableHitWindows); protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); From 94f3dbb2f65afef1aaff9f63a7070efa11f0985b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 16:09:50 +0900 Subject: [PATCH 4467/5608] Adjust transitions slightly --- osu.Game/Screens/Play/HUDOverlay.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 7df780b678..dc32fc7cd5 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -24,8 +24,8 @@ namespace osu.Game.Screens.Play { public class HUDOverlay : Container { - private const int duration = 250; - private const Easing easing = Easing.OutQuint; + private const int fade_duration = 400; + private const Easing fade_easing = Easing.Out; public readonly KeyCounterDisplay KeyCounter; public readonly RollingCounter ComboCounter; @@ -103,8 +103,8 @@ namespace osu.Game.Screens.Play Origin = Anchor.BottomRight, Position = -new Vector2(5, TwoLayerButton.SIZE_RETRACTED.Y), AutoSizeAxes = Axes.Both, - AutoSizeDuration = 150, - AutoSizeEasing = Easing.OutQuint, + AutoSizeDuration = fade_duration, + AutoSizeEasing = fade_easing, Direction = FillDirection.Vertical, Children = new Drawable[] { @@ -155,19 +155,19 @@ namespace osu.Game.Screens.Play { base.LoadComplete(); - ShowHud.BindValueChanged(visible => hideTargets.ForEach(d => d.FadeTo(visible.NewValue ? 1 : 0, duration, easing))); + ShowHud.BindValueChanged(visible => hideTargets.ForEach(d => d.FadeTo(visible.NewValue ? 1 : 0, fade_duration, fade_easing))); ShowHealthbar.BindValueChanged(healthBar => { if (healthBar.NewValue) { - HealthDisplay.FadeIn(duration, easing); - topScoreContainer.MoveToY(30, duration, easing); + HealthDisplay.FadeIn(fade_duration, fade_easing); + topScoreContainer.MoveToY(30, fade_duration, fade_easing); } else { - HealthDisplay.FadeOut(duration, easing); - topScoreContainer.MoveToY(0, duration, easing); + HealthDisplay.FadeOut(fade_duration, fade_easing); + topScoreContainer.MoveToY(0, fade_duration, fade_easing); } }, true); From e4297ffeaded24ea61f8fd188e7fb92215d70674 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 15:09:55 +0900 Subject: [PATCH 4468/5608] Hide HUD in a better way --- osu.Game/Rulesets/Mods/ModCinema.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs index 5faa2f4f3e..5262813b08 100644 --- a/osu.Game/Rulesets/Mods/ModCinema.cs +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -30,8 +30,8 @@ namespace osu.Game.Rulesets.Mods public void ApplyToHUD(HUDOverlay overlay) { - overlay.AlwaysPresent = true; - overlay.Hide(); + overlay.ShowHud.Value = false; + overlay.ShowHud.Disabled = true; } public void ApplyToPlayer(Player player) From 99280db69487c1f0b8542031c8d6037fe875084e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 15:16:34 +0900 Subject: [PATCH 4469/5608] Add note about AlwaysPresent requirement --- osu.Game/Rulesets/Mods/ModCinema.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs index 5262813b08..1e4cf66711 100644 --- a/osu.Game/Rulesets/Mods/ModCinema.cs +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -16,6 +16,7 @@ namespace osu.Game.Rulesets.Mods { drawableRuleset.SetReplayScore(CreateReplayScore(drawableRuleset.Beatmap)); + // AlwaysPresent required for hitsounds drawableRuleset.Playfield.AlwaysPresent = true; drawableRuleset.Playfield.Hide(); } From d15f49f60f33c5beba335b75f0e0b8d40fc8ee10 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 15:14:59 +0900 Subject: [PATCH 4470/5608] Also hide the break overlay --- osu.Game/Rulesets/Mods/ModCinema.cs | 2 ++ osu.Game/Screens/Play/Player.cs | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs index 1e4cf66711..3487d49e08 100644 --- a/osu.Game/Rulesets/Mods/ModCinema.cs +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -41,6 +41,8 @@ namespace osu.Game.Rulesets.Mods player.DimmableVideo.IgnoreUserSettings.Value = true; player.DimmableStoryboard.IgnoreUserSettings.Value = true; + + player.BreakOverlay.Hide(); } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7abd60b3c1..1d1252063f 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -69,7 +69,7 @@ namespace osu.Game.Screens.Play private SampleChannel sampleRestart; - private BreakOverlay breakOverlay; + public BreakOverlay BreakOverlay; protected ScoreProcessor ScoreProcessor { get; private set; } protected DrawableRuleset DrawableRuleset { get; private set; } @@ -149,7 +149,7 @@ namespace osu.Game.Screens.Play foreach (var mod in Mods.Value.OfType()) mod.ApplyToScoreProcessor(ScoreProcessor); - breakOverlay.IsBreakTime.ValueChanged += _ => updatePauseOnFocusLostState(); + BreakOverlay.IsBreakTime.ValueChanged += _ => updatePauseOnFocusLostState(); } private void addUnderlayComponents(Container target) @@ -183,7 +183,7 @@ namespace osu.Game.Screens.Play { target.AddRange(new[] { - breakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, DrawableRuleset.GameplayStartTime, ScoreProcessor) + BreakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, DrawableRuleset.GameplayStartTime, ScoreProcessor) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -248,7 +248,7 @@ namespace osu.Game.Screens.Play private void updatePauseOnFocusLostState() => HUDOverlay.HoldToQuit.PauseOnFocusLost = PauseOnFocusLost && !DrawableRuleset.HasReplayLoaded.Value - && !breakOverlay.IsBreakTime.Value; + && !BreakOverlay.IsBreakTime.Value; private WorkingBeatmap loadBeatmap() { @@ -477,7 +477,7 @@ namespace osu.Game.Screens.Play PauseOverlay.Hide(); // breaks and time-based conditions may allow instant resume. - if (breakOverlay.IsBreakTime.Value) + if (BreakOverlay.IsBreakTime.Value) completeResume(); else DrawableRuleset.RequestResume(completeResume); From 1807fc9b6153e7c02881bae15efd00c5545c4d88 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 16:48:33 +0900 Subject: [PATCH 4471/5608] Fix testcase not converting beatmap --- .../Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index 071dc381e0..c958932730 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -172,7 +172,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var ruleset = new TestScrollingRuleset(); - drawableRuleset = (TestDrawableScrollingRuleset)ruleset.CreateDrawableRulesetWith(beatmap); + drawableRuleset = (TestDrawableScrollingRuleset)ruleset.CreateDrawableRulesetWith(CreateWorkingBeatmap(beatmap).GetPlayableBeatmap(ruleset.RulesetInfo)); drawableRuleset.FrameStablePlayback = false; overrideAction?.Invoke(drawableRuleset); From a0792f82e8bb8031cd97c22cdadd6109a0445e04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 17:05:47 +0900 Subject: [PATCH 4472/5608] Re-jig mod select logic to reduce event fires --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index e8ea43e3f2..a6f9642a56 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -360,8 +360,8 @@ namespace osu.Game.Overlays.Mods { base.LoadComplete(); + SelectedMods.BindValueChanged(selectedModsChanged); Ruleset.BindValueChanged(rulesetChanged, true); - SelectedMods.BindValueChanged(selectedModsChanged, true); } protected override void PopOut() From c4bc57484fdee19279ac616d690891494d67e0a4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 17:12:01 +0900 Subject: [PATCH 4473/5608] Fix test logic and add regression test --- .../UserInterface/TestSceneModSettings.cs | 84 ++++++++++++++----- 1 file changed, 62 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index fc44c5f595..8117a4ad78 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs @@ -2,15 +2,20 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; -using osu.Framework.Allocation; +using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; namespace osu.Game.Tests.Visual.UserInterface { @@ -18,28 +23,51 @@ namespace osu.Game.Tests.Visual.UserInterface { private TestModSelectOverlay modSelect; - [BackgroundDependencyLoader] - private void load() + Mod testCustomisableMod = new TestModCustomisable1(); + + [Test] + public void TestButtonShowsOnCustomisableMod() { - Add(modSelect = new TestModSelectOverlay - { - RelativeSizeAxes = Axes.X, - Origin = Anchor.BottomCentre, - Anchor = Anchor.BottomCentre, - }); + createModSelect(); - var testMod = new TestModCustomisable1(); - - AddStep("open", modSelect.Show); + AddStep("open", () => modSelect.Show()); AddAssert("button disabled", () => !modSelect.CustomiseButton.Enabled.Value); AddUntilStep("wait for button load", () => modSelect.ButtonsLoaded); - AddStep("select mod", () => modSelect.SelectMod(testMod)); + AddStep("select mod", () => modSelect.SelectMod(testCustomisableMod)); AddAssert("button enabled", () => modSelect.CustomiseButton.Enabled.Value); AddStep("open Customisation", () => modSelect.CustomiseButton.Click()); - AddStep("deselect mod", () => modSelect.SelectMod(testMod)); + AddStep("deselect mod", () => modSelect.SelectMod(testCustomisableMod)); AddAssert("controls hidden", () => modSelect.ModSettingsContainer.Alpha == 0); } + [Test] + public void TestButtonShowsOnModAlreadyAdded() + { + AddStep("set active mods", () => Mods.Value = new List { testCustomisableMod }); + + createModSelect(); + + AddAssert("mods still active", () => Mods.Value.Count == 1); + + AddStep("open", () => modSelect.Show()); + AddAssert("button enabled", () => modSelect.CustomiseButton.Enabled.Value); + } + + private void createModSelect() + { + AddStep("create mod select", () => + { + Ruleset.Value = new TestRulesetInfo(); + + Child = modSelect = new TestModSelectOverlay + { + RelativeSizeAxes = Axes.X, + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + }; + }); + } + private class TestModSelectOverlay : ModSelectOverlay { public new Container ModSettingsContainer => base.ModSettingsContainer; @@ -50,24 +78,36 @@ namespace osu.Game.Tests.Visual.UserInterface public void SelectMod(Mod mod) => ModSectionsContainer.Children.Single(s => s.ModType == mod.Type) .ButtonsContainer.OfType().Single(b => b.Mods.Any(m => m.GetType() == mod.GetType())).SelectNext(1); + } - protected override void LoadComplete() + public class TestRulesetInfo : RulesetInfo + { + public override Ruleset CreateInstance() => new TestCustomisableModRuleset(); + + public class TestCustomisableModRuleset : Ruleset { - base.LoadComplete(); - - foreach (var section in ModSectionsContainer) + public override IEnumerable GetModsFor(ModType type) { - if (section.ModType == ModType.Conversion) + if (type == ModType.Conversion) { - section.Mods = new Mod[] + return new Mod[] { new TestModCustomisable1(), new TestModCustomisable2() }; } - else - section.Mods = Array.Empty(); + + return Array.Empty(); } + + public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => throw new NotImplementedException(); + + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new NotImplementedException(); + + public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new NotImplementedException(); + + public override string Description { get; } + public override string ShortName { get; } } } From 623ab1ef3be8f3ef21b71797622894690b21d735 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 17:28:31 +0900 Subject: [PATCH 4474/5608] Update time ramp preview on setting change --- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index e10afa7d7c..5276c196f7 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -35,6 +35,12 @@ namespace osu.Game.Rulesets.Mods private Track track; + public ModTimeRamp() + { + // for preview purpose at song select. eventually we'll want to be able to update every frame. + FinalRate.BindValueChanged(val => applyAdjustment(1), true); + } + public void ApplyToTrack(Track track) { this.track = track; From 81c849303853cdcc328793b39a440cc76844f477 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Dec 2019 12:16:19 +0300 Subject: [PATCH 4475/5608] Split combo colour decoding to small test cases --- osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 69 ++++++++++--------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 003b3f5e56..cb2af359b9 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -13,43 +13,21 @@ namespace osu.Game.Tests.Skins [TestFixture] public class LegacySkinDecoderTest { - [TestCase(true)] - [TestCase(false)] - [TestCase(false, false)] - public void TestDecodeSkinColours(bool hasColours, bool canFallback = true) + public void TestDecodeSkinColours() { var decoder = new LegacySkinDecoder(); - using (var resStream = TestResources.OpenResource(hasColours ? "skin.ini" : "skin-empty.ini")) + using (var resStream = TestResources.OpenResource("skin.ini")) using (var stream = new LineBufferedReader(resStream)) { - var skinConfiguration = decoder.Decode(stream); - skinConfiguration.AllowDefaultComboColoursFallback = canFallback; - - var comboColors = skinConfiguration.ComboColours; - - if (!canFallback && !hasColours) + var comboColors = decoder.Decode(stream).ComboColours; + var expectedColors = new List { - Assert.IsNull(comboColors); - return; - } - - List expectedColors; - - if (hasColours) - { - expectedColors = new List - { - new Color4(142, 199, 255, 255), - new Color4(255, 128, 128, 255), - new Color4(128, 255, 255, 255), - new Color4(100, 100, 100, 100), - }; - } - else - { - expectedColors = SkinConfiguration.DefaultComboColours; - } + new Color4(142, 199, 255, 255), + new Color4(255, 128, 128, 255), + new Color4(128, 255, 255, 255), + new Color4(100, 100, 100, 100), + }; Assert.AreEqual(expectedColors.Count, comboColors.Count); for (int i = 0; i < expectedColors.Count; i++) @@ -57,6 +35,35 @@ namespace osu.Game.Tests.Skins } } + public void TestDecodeEmptySkinColours() + { + var decoder = new LegacySkinDecoder(); + + using (var resStream = TestResources.OpenResource("skin-empty.ini")) + using (var stream = new LineBufferedReader(resStream)) + { + var comboColors = decoder.Decode(stream).ComboColours; + var expectedColors = SkinConfiguration.DefaultComboColours; + + Assert.AreEqual(expectedColors.Count, comboColors.Count); + for (int i = 0; i < expectedColors.Count; i++) + Assert.AreEqual(expectedColors[i], comboColors[i]); + } + } + + public void TestDecodeEmptySkinColoursNoFallback() + { + var decoder = new LegacySkinDecoder(); + + using (var resStream = TestResources.OpenResource("skin-empty.ini")) + using (var stream = new LineBufferedReader(resStream)) + { + var skinConfiguration = decoder.Decode(stream); + skinConfiguration.AllowDefaultComboColoursFallback = false; + Assert.IsNull(skinConfiguration.ComboColours); + } + } + [Test] public void TestDecodeGeneral() { From be000e13e445ff6c63c0b43b3551e5eb34607992 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Dec 2019 20:44:45 +0900 Subject: [PATCH 4476/5608] Implement initial legacy beatmap encoding support --- .../Formats/LegacyBeatmapEncoderTest.cs | 142 +++++++ .../Beatmaps/Formats/LegacyBeatmapEncoder.cs | 375 ++++++++++++++++++ 2 files changed, 517 insertions(+) create mode 100644 osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs create mode 100644 osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs new file mode 100644 index 0000000000..c4a3877c1c --- /dev/null +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs @@ -0,0 +1,142 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.IO; +using System.Linq; +using NUnit.Framework; +using osu.Game.Audio; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Formats; +using osu.Game.IO; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Tests.Resources; +using osuTK; + +namespace osu.Game.Tests.Beatmaps.Formats +{ + [TestFixture] + public class LegacyBeatmapEncoderTest + { + private const string normal = "Soleily - Renatus (Gamu) [Insane].osu"; + + [Test] + public void TestDecodeMetadata() + { + var beatmap = decode(normal); + var meta = beatmap.BeatmapInfo.Metadata; + Assert.AreEqual(241526, beatmap.BeatmapInfo.BeatmapSet.OnlineBeatmapSetID); + Assert.AreEqual("Soleily", meta.Artist); + Assert.AreEqual("Soleily", meta.ArtistUnicode); + Assert.AreEqual("03. Renatus - Soleily 192kbps.mp3", meta.AudioFile); + Assert.AreEqual("Gamu", meta.AuthorString); + Assert.AreEqual("machinetop_background.jpg", meta.BackgroundFile); + Assert.AreEqual(164471, meta.PreviewTime); + Assert.AreEqual(string.Empty, meta.Source); + Assert.AreEqual("MBC7 Unisphere 地球ヤバイEP Chikyu Yabai", meta.Tags); + Assert.AreEqual("Renatus", meta.Title); + Assert.AreEqual("Renatus", meta.TitleUnicode); + } + + [Test] + public void TestDecodeGeneral() + { + var beatmap = decode(normal); + var beatmapInfo = beatmap.BeatmapInfo; + Assert.AreEqual(0, beatmapInfo.AudioLeadIn); + Assert.AreEqual(false, beatmapInfo.Countdown); + Assert.AreEqual(0.7f, beatmapInfo.StackLeniency); + Assert.AreEqual(false, beatmapInfo.SpecialStyle); + Assert.IsTrue(beatmapInfo.RulesetID == 0); + Assert.AreEqual(false, beatmapInfo.LetterboxInBreaks); + Assert.AreEqual(false, beatmapInfo.WidescreenStoryboard); + } + + [Test] + public void TestDecodeEditor() + { + var beatmap = decode(normal); + var beatmapInfo = beatmap.BeatmapInfo; + + int[] expectedBookmarks = + { + 11505, 22054, 32604, 43153, 53703, 64252, 74802, 85351, + 95901, 106450, 116999, 119637, 130186, 140735, 151285, + 161834, 164471, 175020, 185570, 196119, 206669, 209306 + }; + Assert.AreEqual(expectedBookmarks.Length, beatmapInfo.Bookmarks.Length); + for (int i = 0; i < expectedBookmarks.Length; i++) + Assert.AreEqual(expectedBookmarks[i], beatmapInfo.Bookmarks[i]); + Assert.AreEqual(1.8, beatmapInfo.DistanceSpacing); + Assert.AreEqual(4, beatmapInfo.BeatDivisor); + Assert.AreEqual(4, beatmapInfo.GridSize); + Assert.AreEqual(2, beatmapInfo.TimelineZoom); + } + + [Test] + public void TestDecodeDifficulty() + { + var beatmap = decode(normal); + var difficulty = beatmap.BeatmapInfo.BaseDifficulty; + Assert.AreEqual(6.5f, difficulty.DrainRate); + Assert.AreEqual(4, difficulty.CircleSize); + Assert.AreEqual(8, difficulty.OverallDifficulty); + Assert.AreEqual(9, difficulty.ApproachRate); + Assert.AreEqual(1.8, difficulty.SliderMultiplier); + Assert.AreEqual(2, difficulty.SliderTickRate); + } + + [Test] + public void TestDecodeHitObjects() + { + var beatmap = decode(normal); + + var curveData = beatmap.HitObjects[0] as IHasCurve; + var positionData = beatmap.HitObjects[0] as IHasPosition; + + Assert.IsNotNull(positionData); + Assert.IsNotNull(curveData); + Assert.AreEqual(new Vector2(192, 168), positionData.Position); + Assert.AreEqual(956, beatmap.HitObjects[0].StartTime); + Assert.IsTrue(beatmap.HitObjects[0].Samples.Any(s => s.Name == HitSampleInfo.HIT_NORMAL)); + + positionData = beatmap.HitObjects[1] as IHasPosition; + + Assert.IsNotNull(positionData); + Assert.AreEqual(new Vector2(304, 56), positionData.Position); + Assert.AreEqual(1285, beatmap.HitObjects[1].StartTime); + Assert.IsTrue(beatmap.HitObjects[1].Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP)); + } + + private Beatmap decode(string filename) + { + decode(filename, out Beatmap jsonDecoded); + return jsonDecoded; + } + + private Beatmap decode(string filename, out Beatmap decoded) + { + using (var stream = TestResources.OpenResource(filename)) + using (var sr = new LineBufferedReader(stream)) + { + var legacyDecoded = new LegacyBeatmapDecoder { ApplyOffsets = false }.Decode(sr); + + using (var ms = new MemoryStream()) + using (var sw = new StreamWriter(ms)) + using (var sr2 = new LineBufferedReader(ms)) + { + new LegacyBeatmapEncoder(legacyDecoded).Encode(sw); + sw.Flush(); + + ms.Position = 0; + + string result = sr2.ReadToEnd(); + + ms.Position = 0; + + decoded = new LegacyBeatmapDecoder { ApplyOffsets = false }.Decode(sr2); + return legacyDecoded; + } + } + } + } +} diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs new file mode 100644 index 0000000000..1dc29ba5db --- /dev/null +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -0,0 +1,375 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using osu.Game.Audio; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Beatmaps.Formats +{ + public class LegacyBeatmapEncoder + { + public const int LATEST_VERSION = 14234; + + private readonly IBeatmap beatmap; + + public LegacyBeatmapEncoder(IBeatmap beatmap) + { + this.beatmap = beatmap; + + if (beatmap.BeatmapInfo.RulesetID < 0 || beatmap.BeatmapInfo.RulesetID > 3) + throw new ArgumentException("Only beatmaps in the osu, taiko, catch, or mania rulesets can be encoded to the legacy beatmap format.", nameof(beatmap)); + } + + public void Encode(TextWriter writer) + { + writer.WriteLine($"osu file format v{LATEST_VERSION}"); + + writer.WriteLine(); + handleGeneral(writer); + + writer.WriteLine(); + handleEditor(writer); + + writer.WriteLine(); + handleMetadata(writer); + + writer.WriteLine(); + handleDifficulty(writer); + + writer.WriteLine(); + handleEvents(writer); + + writer.WriteLine(); + handleTimingPoints(writer); + + writer.WriteLine(); + handleHitObjects(writer); + } + + private void handleGeneral(TextWriter writer) + { + writer.WriteLine("[General]"); + + writer.WriteLine(FormattableString.Invariant($"AudioFilename: {Path.GetFileName(beatmap.Metadata.AudioFile)}")); + writer.WriteLine(FormattableString.Invariant($"AudioLeadIn: {beatmap.BeatmapInfo.AudioLeadIn}")); + writer.WriteLine(FormattableString.Invariant($"PreviewTime: {beatmap.Metadata.PreviewTime}")); + // Todo: Not all countdown types are supported by lazer yet + writer.WriteLine(FormattableString.Invariant($"Countdown: {(beatmap.BeatmapInfo.Countdown ? "1" : "0")}")); + writer.WriteLine(FormattableString.Invariant($"SampleSet: {(int)toLegacySampleBank(beatmap.ControlPointInfo.SamplePoints[0].SampleBank)}")); + writer.WriteLine(FormattableString.Invariant($"StackLeniency: {beatmap.BeatmapInfo.StackLeniency}")); + writer.WriteLine(FormattableString.Invariant($"Mode: {beatmap.BeatmapInfo.RulesetID}")); + writer.WriteLine(FormattableString.Invariant($"LetterboxInBreaks: {(beatmap.BeatmapInfo.LetterboxInBreaks ? "1" : "0")}")); + // if (beatmap.BeatmapInfo.UseSkinSprites) + // writer.WriteLine(@"UseSkinSprites: 1"); + // if (b.AlwaysShowPlayfield) + // writer.WriteLine(@"AlwaysShowPlayfield: 1"); + // if (b.OverlayPosition != OverlayPosition.NoChange) + // writer.WriteLine(@"OverlayPosition: " + b.OverlayPosition); + // if (!string.IsNullOrEmpty(b.SkinPreference)) + // writer.WriteLine(@"SkinPreference:" + b.SkinPreference); + // if (b.EpilepsyWarning) + // writer.WriteLine(@"EpilepsyWarning: 1"); + // if (b.CountdownOffset > 0) + // writer.WriteLine(@"CountdownOffset: " + b.CountdownOffset.ToString()); + if (beatmap.BeatmapInfo.RulesetID == 3) + writer.WriteLine(FormattableString.Invariant($"SpecialStyle: {(beatmap.BeatmapInfo.SpecialStyle ? "1" : "0")}")); + writer.WriteLine(FormattableString.Invariant($"WidescreenStoryboard: {(beatmap.BeatmapInfo.WidescreenStoryboard ? "1" : "0")}")); + // if (b.SamplesMatchPlaybackRate) + // writer.WriteLine(@"SamplesMatchPlaybackRate: 1"); + } + + private void handleEditor(TextWriter writer) + { + writer.WriteLine("[Editor]"); + + if (beatmap.BeatmapInfo.Bookmarks.Length > 0) + writer.WriteLine(FormattableString.Invariant($"Bookmarks: {string.Join(',', beatmap.BeatmapInfo.Bookmarks)}")); + writer.WriteLine(FormattableString.Invariant($"DistanceSpacing: {beatmap.BeatmapInfo.DistanceSpacing}")); + writer.WriteLine(FormattableString.Invariant($"BeatDivisor: {beatmap.BeatmapInfo.BeatDivisor}")); + writer.WriteLine(FormattableString.Invariant($"GridSize: {beatmap.BeatmapInfo.GridSize}")); + writer.WriteLine(FormattableString.Invariant($"TimelineZoom: {beatmap.BeatmapInfo.TimelineZoom}")); + } + + private void handleMetadata(TextWriter writer) + { + writer.WriteLine("[Metadata]"); + + writer.WriteLine(FormattableString.Invariant($"Title: {beatmap.Metadata.Title}")); + writer.WriteLine(FormattableString.Invariant($"TitleUnicode: {beatmap.Metadata.TitleUnicode}")); + writer.WriteLine(FormattableString.Invariant($"Artist: {beatmap.Metadata.Artist}")); + writer.WriteLine(FormattableString.Invariant($"ArtistUnicode: {beatmap.Metadata.ArtistUnicode}")); + writer.WriteLine(FormattableString.Invariant($"Creator: {beatmap.Metadata.AuthorString}")); + writer.WriteLine(FormattableString.Invariant($"Version: {beatmap.Metadata.Artist}")); + writer.WriteLine(FormattableString.Invariant($"Source: {beatmap.Metadata.Source}")); + writer.WriteLine(FormattableString.Invariant($"Tags: {beatmap.Metadata.Tags}")); + writer.WriteLine(FormattableString.Invariant($"BeatmapID: {beatmap.BeatmapInfo.OnlineBeatmapID ?? 0}")); + writer.WriteLine(FormattableString.Invariant($"BeatmapSetID: {beatmap.BeatmapInfo.BeatmapSet.OnlineBeatmapSetID ?? 0}")); + } + + private void handleDifficulty(TextWriter writer) + { + writer.WriteLine("[Difficulty]"); + + writer.WriteLine(FormattableString.Invariant($"HPDrainRate: {beatmap.BeatmapInfo.BaseDifficulty.DrainRate}")); + writer.WriteLine(FormattableString.Invariant($"CircleSize: {beatmap.BeatmapInfo.BaseDifficulty.CircleSize}")); + writer.WriteLine(FormattableString.Invariant($"OverallDifficulty: {beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty}")); + writer.WriteLine(FormattableString.Invariant($"ApproachRate: {beatmap.BeatmapInfo.BaseDifficulty.ApproachRate}")); + writer.WriteLine(FormattableString.Invariant($"SliderMultiplier: {beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier}")); + writer.WriteLine(FormattableString.Invariant($"SliderTickRate: {beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate}")); + } + + private void handleEvents(TextWriter writer) + { + // Todo: Storyboard events + } + + private void handleTimingPoints(TextWriter writer) + { + if (beatmap.ControlPointInfo.Groups.Count == 0) + return; + + writer.WriteLine("[TimingPoints]"); + + foreach (var group in beatmap.ControlPointInfo.Groups) + { + var timingPoint = group.ControlPoints.OfType().FirstOrDefault(); + var difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(group.Time); + var samplePoint = beatmap.ControlPointInfo.SamplePointAt(group.Time); + var effectPoint = beatmap.ControlPointInfo.EffectPointAt(group.Time); + + // Convert beat length the legacy format + double beatLength; + if (timingPoint != null) + beatLength = timingPoint.BeatLength; + else + beatLength = -100 / difficultyPoint.SpeedMultiplier; + + // Apply the control point to a hit sample to uncover legacy properties (e.g. suffix) + HitSampleInfo tempHitSample = samplePoint.ApplyTo(new HitSampleInfo()); + + // Convert effect flags to the legacy format + LegacyEffectFlags effectFlags = LegacyEffectFlags.None; + if (effectPoint.KiaiMode) + effectFlags |= LegacyEffectFlags.Kiai; + if (effectPoint.OmitFirstBarLine) + effectFlags |= LegacyEffectFlags.OmitFirstBarLine; + + writer.Write(FormattableString.Invariant($"{group.Time},")); + writer.Write(FormattableString.Invariant($"{beatLength},")); + writer.Write(FormattableString.Invariant($"{(int)beatmap.ControlPointInfo.TimingPointAt(group.Time).TimeSignature},")); + writer.Write(FormattableString.Invariant($"{(int)toLegacySampleBank(tempHitSample.Bank)},")); + writer.Write(FormattableString.Invariant($"{toLegacyCustomSampleBank(tempHitSample.Suffix)},")); + writer.Write(FormattableString.Invariant($"{tempHitSample.Volume},")); + writer.Write(FormattableString.Invariant($"{(timingPoint != null ? "1" : "0")},")); + writer.Write(FormattableString.Invariant($"{(int)effectFlags}")); + writer.Write("\n"); + } + } + + private void handleHitObjects(TextWriter writer) + { + if (beatmap.HitObjects.Count == 0) + return; + + writer.WriteLine("[HitObjects]"); + + foreach (var h in beatmap.HitObjects) + { + switch (beatmap.BeatmapInfo.RulesetID) + { + case 0: + handleOsuHitObject(writer, h); + break; + + case 1: + handleTaikoHitObject(writer, h); + break; + + case 2: + handleCatchHitObject(writer, h); + break; + + case 3: + handleManiaHitObject(writer, h); + break; + } + } + } + + private void handleOsuHitObject(TextWriter writer, HitObject hitObject) + { + var positionData = hitObject as IHasPosition; + var comboData = hitObject as IHasCombo; + + Debug.Assert(positionData != null); + Debug.Assert(comboData != null); + + LegacyHitObjectType hitObjectType = (LegacyHitObjectType)(comboData.ComboOffset << 4); + if (comboData.NewCombo) + hitObjectType |= LegacyHitObjectType.NewCombo; + + if (hitObject is IHasCurve _) + hitObjectType |= LegacyHitObjectType.Slider; + else if (hitObject is IHasEndTime _) + hitObjectType |= LegacyHitObjectType.Spinner; + else + hitObjectType |= LegacyHitObjectType.Circle; + + LegacyHitSoundType soundType = LegacyHitSoundType.Normal; + HitSampleInfo firstAdditionSound = hitObject.Samples.FirstOrDefault(s => s.Name != HitSampleInfo.HIT_NORMAL); + if (firstAdditionSound != null) + soundType |= toLegacyHitSound(firstAdditionSound.Name); + + writer.Write(FormattableString.Invariant($"{positionData.X},")); + writer.Write(FormattableString.Invariant($"{positionData.Y},")); + writer.Write(FormattableString.Invariant($"{hitObject.StartTime},")); + writer.Write(FormattableString.Invariant($"{(int)hitObjectType},")); + writer.Write(FormattableString.Invariant($"{(int)soundType},")); + + if (hitObject is IHasCurve curveData) + { + for (int i = 0; i < curveData.Path.ControlPoints.Count; i++) + { + PathControlPoint point = curveData.Path.ControlPoints[i]; + + switch (point.Type.Value) + { + case PathType.Bezier: + writer.Write("B|"); + break; + + case PathType.Catmull: + writer.Write("C|"); + break; + + case PathType.PerfectCurve: + writer.Write("P|"); + break; + + case PathType.Linear: + writer.Write("L|"); + break; + } + + writer.Write(FormattableString.Invariant($"{point.Position.Value.X}:{point.Position.Value.Y}")); + writer.Write(i != curveData.Path.ControlPoints.Count - 1 ? "|" : ","); + } + + writer.Write(FormattableString.Invariant($"{curveData.RepeatCount - 1},")); + writer.Write(FormattableString.Invariant($"{curveData.Path.Distance},")); + + for (int i = 0; i < curveData.NodeSamples.Count; i++) + { + LegacyHitSoundType type = LegacyHitSoundType.None; + + foreach (var sample in curveData.NodeSamples[i]) + type |= toLegacyHitSound(sample.Name); + + writer.Write(FormattableString.Invariant($"{(int)type}")); + writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ","); + } + + for (int i = 0; i < curveData.NodeSamples.Count; i++) + { + writer.Write(getSampleBank(curveData.NodeSamples[i], true)); + writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ","); + } + } + else if (hitObject is IHasEndTime endTimeData) + writer.Write(FormattableString.Invariant($"{endTimeData.EndTime},")); + + writer.Write(getSampleBank(hitObject.Samples)); + writer.Write(Environment.NewLine); + } + + private void handleTaikoHitObject(TextWriter writer, HitObject hitObject) + { + } + + private void handleCatchHitObject(TextWriter writer, HitObject hitObject) + { + } + + private void handleManiaHitObject(TextWriter writer, HitObject hitObject) + { + } + + private string getSampleBank(IList samples, bool banksOnly = false) + { + LegacySampleBank normalBank = toLegacySampleBank(samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL)?.Bank); + LegacySampleBank addBank = toLegacySampleBank(samples.FirstOrDefault(s => !string.IsNullOrEmpty(s.Name) && s.Name != HitSampleInfo.HIT_NORMAL)?.Bank); + + if (addBank == LegacySampleBank.None) + addBank = normalBank; + + string customSampleBank = toLegacyCustomSampleBank(samples.FirstOrDefault()?.Suffix); + string sampleFilename = samples.FirstOrDefault(s => string.IsNullOrEmpty(s.Name))?.LookupNames.First() ?? string.Empty; + + int volume = samples.First().Volume; + + StringBuilder sb = new StringBuilder(); + + sb.Append(FormattableString.Invariant($"{(int)normalBank}:")); + sb.Append(FormattableString.Invariant($"{(int)addBank}:")); + + if (!banksOnly) + { + sb.Append(FormattableString.Invariant($"{customSampleBank}:")); + sb.Append(FormattableString.Invariant($"{volume}:")); + sb.Append(FormattableString.Invariant($"{sampleFilename}")); + } + + return sb.ToString(); + } + + private LegacyHitSoundType toLegacyHitSound(string hitSoundName) + { + switch (hitSoundName) + { + case HitSampleInfo.HIT_NORMAL: + return LegacyHitSoundType.Normal; + + case HitSampleInfo.HIT_WHISTLE: + return LegacyHitSoundType.Whistle; + + case HitSampleInfo.HIT_FINISH: + return LegacyHitSoundType.Finish; + + case HitSampleInfo.HIT_CLAP: + return LegacyHitSoundType.Clap; + + default: + return LegacyHitSoundType.None; + } + } + + private LegacySampleBank toLegacySampleBank(string sampleBank) + { + switch (sampleBank?.ToLower()) + { + case "normal": + return LegacySampleBank.Normal; + + case "soft": + return LegacySampleBank.Soft; + + case "drum": + return LegacySampleBank.Drum; + + default: + return LegacySampleBank.None; + } + } + + private string toLegacyCustomSampleBank(string sampleSuffix) => string.IsNullOrEmpty(sampleSuffix) ? "0" : sampleSuffix; + } +} From 8f03599a62971f50443cbe772f8f89a96dcc6c6d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 18:40:33 +0900 Subject: [PATCH 4477/5608] Write default sampleset by name --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 1dc29ba5db..4011bf2d02 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -64,7 +64,7 @@ namespace osu.Game.Beatmaps.Formats writer.WriteLine(FormattableString.Invariant($"PreviewTime: {beatmap.Metadata.PreviewTime}")); // Todo: Not all countdown types are supported by lazer yet writer.WriteLine(FormattableString.Invariant($"Countdown: {(beatmap.BeatmapInfo.Countdown ? "1" : "0")}")); - writer.WriteLine(FormattableString.Invariant($"SampleSet: {(int)toLegacySampleBank(beatmap.ControlPointInfo.SamplePoints[0].SampleBank)}")); + writer.WriteLine(FormattableString.Invariant($"SampleSet: {toLegacySampleBank(beatmap.ControlPointInfo.SamplePoints[0].SampleBank)}")); writer.WriteLine(FormattableString.Invariant($"StackLeniency: {beatmap.BeatmapInfo.StackLeniency}")); writer.WriteLine(FormattableString.Invariant($"Mode: {beatmap.BeatmapInfo.RulesetID}")); writer.WriteLine(FormattableString.Invariant($"LetterboxInBreaks: {(beatmap.BeatmapInfo.LetterboxInBreaks ? "1" : "0")}")); From c3475a2ddeca1333053f204ebbdeef11bef510eb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 18:41:13 +0900 Subject: [PATCH 4478/5608] Write control points in absolute coordinates --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 4011bf2d02..bfbc3babed 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -260,7 +260,7 @@ namespace osu.Game.Beatmaps.Formats break; } - writer.Write(FormattableString.Invariant($"{point.Position.Value.X}:{point.Position.Value.Y}")); + writer.Write(FormattableString.Invariant($"{positionData.X + point.Position.Value.X}:{positionData.Y + point.Position.Value.Y}")); writer.Write(i != curveData.Path.ControlPoints.Count - 1 ? "|" : ","); } From d1dc3456d101fde973a84ac800c89601ece949ad Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 18:42:48 +0900 Subject: [PATCH 4479/5608] Fix incorrect repeat point count --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index bfbc3babed..23054838f8 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -264,7 +264,7 @@ namespace osu.Game.Beatmaps.Formats writer.Write(i != curveData.Path.ControlPoints.Count - 1 ? "|" : ","); } - writer.Write(FormattableString.Invariant($"{curveData.RepeatCount - 1},")); + writer.Write(FormattableString.Invariant($"{curveData.RepeatCount + 1},")); writer.Write(FormattableString.Invariant($"{curveData.Path.Distance},")); for (int i = 0; i < curveData.NodeSamples.Count; i++) From e09bbf0315643c4d8bd4c6b7ccfa19176780caab Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 18:47:28 +0900 Subject: [PATCH 4480/5608] Implement background/video/break encoding --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 23054838f8..20706c73c1 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -129,7 +129,11 @@ namespace osu.Game.Beatmaps.Formats private void handleEvents(TextWriter writer) { - // Todo: Storyboard events + writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Background},0,{beatmap.BeatmapInfo.Metadata.BackgroundFile}")); + writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Video},0,{beatmap.BeatmapInfo.Metadata.VideoFile}")); + + foreach (var b in beatmap.Breaks) + writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Break},{b.StartTime},{b.EndTime}")); } private void handleTimingPoints(TextWriter writer) From ebd778da2de92377a1e1c874f294d73d0b90494a Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Dec 2019 12:48:07 +0300 Subject: [PATCH 4481/5608] More test splitting --- .../Skins/TestSceneSkinConfigurationLookup.cs | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index fe96cbd633..8808cf2185 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -117,9 +117,8 @@ namespace osu.Game.Tests.Skins }); } - [TestCase(false)] - [TestCase(true)] - public void TestEmptyComboColours(bool allowFallback) + [Test] + public void TestEmptyComboColours() { AddStep("Add custom combo colours to source1", () => source1.Configuration.ComboColours = new List { @@ -127,11 +126,25 @@ namespace osu.Game.Tests.Skins new Color4(55, 110, 166, 255), new Color4(75, 125, 175, 255), }); - AddStep("Disallow default colours fallback in source2", () => source2.Configuration.AllowDefaultComboColoursFallback = allowFallback); - AddAssert($"Check retrieved combo colours from {(allowFallback ? "source1" : "fallback source")}", () => + AddAssert("Check retrieved combo colours is skin default colours", () => + requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.SequenceEqual(SkinConfiguration.DefaultComboColours) ?? false); + } + + [Test] + public void TestEmptyComboColoursNoFallback() + { + AddStep("Add custom combo colours to source1", () => source1.Configuration.ComboColours = new List { - var expectedColours = allowFallback ? SkinConfiguration.DefaultComboColours : source1.Configuration.ComboColours; + new Color4(100, 150, 200, 255), + new Color4(55, 110, 166, 255), + new Color4(75, 125, 175, 255), + }); + AddStep("Disallow default colours fallback in source2", () => source2.Configuration.AllowDefaultComboColoursFallback = false); + + AddAssert("Check retrieved combo colours from source1", () => + { + var expectedColours = source1.Configuration.ComboColours; return requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.SequenceEqual(expectedColours) ?? false; }); } From f89042cd0aa3c9e7c120901e2e2d6dd5e0a4706d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 18:48:22 +0900 Subject: [PATCH 4482/5608] Add missing section header --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 20706c73c1..8acd8eb17b 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -129,6 +129,8 @@ namespace osu.Game.Beatmaps.Formats private void handleEvents(TextWriter writer) { + writer.WriteLine("[Events]"); + writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Background},0,{beatmap.BeatmapInfo.Metadata.BackgroundFile}")); writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Video},0,{beatmap.BeatmapInfo.Metadata.VideoFile}")); From 51bdb73b913255b0f4f2fd8079c0079fc684680e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 18:49:47 +0900 Subject: [PATCH 4483/5608] Don't write empty file names --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 8acd8eb17b..136b152eff 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -131,8 +131,11 @@ namespace osu.Game.Beatmaps.Formats { writer.WriteLine("[Events]"); - writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Background},0,{beatmap.BeatmapInfo.Metadata.BackgroundFile}")); - writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Video},0,{beatmap.BeatmapInfo.Metadata.VideoFile}")); + if (!string.IsNullOrEmpty(beatmap.BeatmapInfo.Metadata.BackgroundFile)) + writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Background},0,{beatmap.BeatmapInfo.Metadata.BackgroundFile}")); + + if (!string.IsNullOrEmpty(beatmap.BeatmapInfo.Metadata.VideoFile)) + writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Video},0,{beatmap.BeatmapInfo.Metadata.VideoFile}")); foreach (var b in beatmap.Breaks) writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Break},{b.StartTime},{b.EndTime}")); From 60063eefd237572af3c6905096db837dcc0d7401 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 18:51:05 +0900 Subject: [PATCH 4484/5608] Fix up background/video events --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 136b152eff..f7a70b0d32 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -132,10 +132,10 @@ namespace osu.Game.Beatmaps.Formats writer.WriteLine("[Events]"); if (!string.IsNullOrEmpty(beatmap.BeatmapInfo.Metadata.BackgroundFile)) - writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Background},0,{beatmap.BeatmapInfo.Metadata.BackgroundFile}")); + writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Background},0,\"{beatmap.BeatmapInfo.Metadata.BackgroundFile}\",0,0")); if (!string.IsNullOrEmpty(beatmap.BeatmapInfo.Metadata.VideoFile)) - writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Video},0,{beatmap.BeatmapInfo.Metadata.VideoFile}")); + writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Video},0,\"{beatmap.BeatmapInfo.Metadata.VideoFile}\",0,0")); foreach (var b in beatmap.Breaks) writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Break},{b.StartTime},{b.EndTime}")); From 4760307bbb6d30b59f14c78ef8a19e4d0af8b582 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 19:01:15 +0900 Subject: [PATCH 4485/5608] Don't output the first slider control point --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index f7a70b0d32..479f2765bb 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -269,8 +269,11 @@ namespace osu.Game.Beatmaps.Formats break; } - writer.Write(FormattableString.Invariant($"{positionData.X + point.Position.Value.X}:{positionData.Y + point.Position.Value.Y}")); - writer.Write(i != curveData.Path.ControlPoints.Count - 1 ? "|" : ","); + if (i != 0) + { + writer.Write(FormattableString.Invariant($"{positionData.X + point.Position.Value.X}:{positionData.Y + point.Position.Value.Y}")); + writer.Write(i != curveData.Path.ControlPoints.Count - 1 ? "|" : ","); + } } writer.Write(FormattableString.Invariant($"{curveData.RepeatCount + 1},")); From d35d34c01b148fb96a4f129764a3b53eb7f4e655 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 19:01:43 +0900 Subject: [PATCH 4486/5608] Fix hanging semicolon for per-node bank output --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 479f2765bb..41cb49615c 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -331,10 +331,11 @@ namespace osu.Game.Beatmaps.Formats StringBuilder sb = new StringBuilder(); sb.Append(FormattableString.Invariant($"{(int)normalBank}:")); - sb.Append(FormattableString.Invariant($"{(int)addBank}:")); + sb.Append(FormattableString.Invariant($"{(int)addBank}")); if (!banksOnly) { + sb.Append(":"); sb.Append(FormattableString.Invariant($"{customSampleBank}:")); sb.Append(FormattableString.Invariant($"{volume}:")); sb.Append(FormattableString.Invariant($"{sampleFilename}")); From dedae69db8b4144586eb94f9661c42354749ee32 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 19:52:15 +0900 Subject: [PATCH 4487/5608] Prefer legacy curve format if possible --- .../Beatmaps/Formats/LegacyBeatmapEncoder.cs | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 41cb49615c..f64d505df9 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -246,27 +246,42 @@ namespace osu.Game.Beatmaps.Formats if (hitObject is IHasCurve curveData) { + PathType? lastType = null; + for (int i = 0; i < curveData.Path.ControlPoints.Count; i++) { PathControlPoint point = curveData.Path.ControlPoints[i]; - switch (point.Type.Value) + if (point.Type.Value != null) { - case PathType.Bezier: - writer.Write("B|"); - break; + if (point.Type.Value != lastType) + { + switch (point.Type.Value) + { + case PathType.Bezier: + writer.Write("B|"); + break; - case PathType.Catmull: - writer.Write("C|"); - break; + case PathType.Catmull: + writer.Write("C|"); + break; - case PathType.PerfectCurve: - writer.Write("P|"); - break; + case PathType.PerfectCurve: + writer.Write("P|"); + break; - case PathType.Linear: - writer.Write("L|"); - break; + case PathType.Linear: + writer.Write("L|"); + break; + } + + lastType = point.Type.Value; + } + else + { + // New segment with the same type - duplicate the control point + writer.Write(FormattableString.Invariant($"{positionData.X + point.Position.Value.X}:{positionData.Y + point.Position.Value.Y}|")); + } } if (i != 0) From ac984423bb9c149fab9d09922d79e03bd0765418 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 19:53:30 +0900 Subject: [PATCH 4488/5608] Fix only single sound type being written --- .../Beatmaps/Formats/LegacyBeatmapEncoder.cs | 47 ++++++++----------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index f64d505df9..0eeacf733d 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -225,7 +225,6 @@ namespace osu.Game.Beatmaps.Formats LegacyHitObjectType hitObjectType = (LegacyHitObjectType)(comboData.ComboOffset << 4); if (comboData.NewCombo) hitObjectType |= LegacyHitObjectType.NewCombo; - if (hitObject is IHasCurve _) hitObjectType |= LegacyHitObjectType.Slider; else if (hitObject is IHasEndTime _) @@ -233,16 +232,11 @@ namespace osu.Game.Beatmaps.Formats else hitObjectType |= LegacyHitObjectType.Circle; - LegacyHitSoundType soundType = LegacyHitSoundType.Normal; - HitSampleInfo firstAdditionSound = hitObject.Samples.FirstOrDefault(s => s.Name != HitSampleInfo.HIT_NORMAL); - if (firstAdditionSound != null) - soundType |= toLegacyHitSound(firstAdditionSound.Name); - writer.Write(FormattableString.Invariant($"{positionData.X},")); writer.Write(FormattableString.Invariant($"{positionData.Y},")); writer.Write(FormattableString.Invariant($"{hitObject.StartTime},")); writer.Write(FormattableString.Invariant($"{(int)hitObjectType},")); - writer.Write(FormattableString.Invariant($"{(int)soundType},")); + writer.Write(FormattableString.Invariant($"{(int)toLegacyHitSoundType(hitObject.Samples)},")); if (hitObject is IHasCurve curveData) { @@ -296,12 +290,7 @@ namespace osu.Game.Beatmaps.Formats for (int i = 0; i < curveData.NodeSamples.Count; i++) { - LegacyHitSoundType type = LegacyHitSoundType.None; - - foreach (var sample in curveData.NodeSamples[i]) - type |= toLegacyHitSound(sample.Name); - - writer.Write(FormattableString.Invariant($"{(int)type}")); + writer.Write(FormattableString.Invariant($"{(int)toLegacyHitSoundType(curveData.NodeSamples[i])}")); writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ","); } @@ -359,25 +348,29 @@ namespace osu.Game.Beatmaps.Formats return sb.ToString(); } - private LegacyHitSoundType toLegacyHitSound(string hitSoundName) + private LegacyHitSoundType toLegacyHitSoundType(IList samples) { - switch (hitSoundName) + LegacyHitSoundType type = LegacyHitSoundType.None; + + foreach (var sample in samples) { - case HitSampleInfo.HIT_NORMAL: - return LegacyHitSoundType.Normal; + switch (sample.Name) + { + case HitSampleInfo.HIT_WHISTLE: + type |= LegacyHitSoundType.Whistle; + break; - case HitSampleInfo.HIT_WHISTLE: - return LegacyHitSoundType.Whistle; + case HitSampleInfo.HIT_FINISH: + type |= LegacyHitSoundType.Finish; + break; - case HitSampleInfo.HIT_FINISH: - return LegacyHitSoundType.Finish; - - case HitSampleInfo.HIT_CLAP: - return LegacyHitSoundType.Clap; - - default: - return LegacyHitSoundType.None; + case HitSampleInfo.HIT_CLAP: + type |= LegacyHitSoundType.Clap; + break; + } } + + return type; } private LegacySampleBank toLegacySampleBank(string sampleBank) From bf8caee53fdbf9fc392462fea7dfdb549af0e7cb Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Dec 2019 14:05:24 +0300 Subject: [PATCH 4489/5608] Inherit SkinConfiguration directly --- osu.Game/Skinning/LegacySkinConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs index b1679bd464..027f5b8883 100644 --- a/osu.Game/Skinning/LegacySkinConfiguration.cs +++ b/osu.Game/Skinning/LegacySkinConfiguration.cs @@ -3,7 +3,7 @@ namespace osu.Game.Skinning { - public class LegacySkinConfiguration : DefaultSkinConfiguration + public class LegacySkinConfiguration : SkinConfiguration { public const decimal LATEST_VERSION = 2.7m; From 4406172eb4151a367cabc659456c44f5822631b8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Dec 2019 14:05:37 +0300 Subject: [PATCH 4490/5608] Add missing test attributes --- osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 8dbd894a0e..cef38bbbb8 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -13,6 +13,7 @@ namespace osu.Game.Tests.Skins [TestFixture] public class LegacySkinDecoderTest { + [Test] public void TestDecodeSkinColours() { var decoder = new LegacySkinDecoder(); @@ -35,6 +36,7 @@ namespace osu.Game.Tests.Skins } } + [Test] public void TestDecodeEmptySkinColours() { var decoder = new LegacySkinDecoder(); @@ -51,6 +53,7 @@ namespace osu.Game.Tests.Skins } } + [Test] public void TestDecodeEmptySkinColoursNoFallback() { var decoder = new LegacySkinDecoder(); From 7e1d21fa1658efcdf344f0ac632b7db83010847e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Dec 2019 14:08:35 +0300 Subject: [PATCH 4491/5608] Simplify combo colours lookup tests --- .../Skins/TestSceneSkinConfigurationLookup.cs | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index 8808cf2185..ed54cc982d 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -120,13 +120,6 @@ namespace osu.Game.Tests.Skins [Test] public void TestEmptyComboColours() { - AddStep("Add custom combo colours to source1", () => source1.Configuration.ComboColours = new List - { - new Color4(100, 150, 200, 255), - new Color4(55, 110, 166, 255), - new Color4(75, 125, 175, 255), - }); - AddAssert("Check retrieved combo colours is skin default colours", () => requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.SequenceEqual(SkinConfiguration.DefaultComboColours) ?? false); } @@ -134,19 +127,16 @@ namespace osu.Game.Tests.Skins [Test] public void TestEmptyComboColoursNoFallback() { - AddStep("Add custom combo colours to source1", () => source1.Configuration.ComboColours = new List - { + AddStep("Add custom combo colours to source1", () => source1.Configuration.AddComboColours( new Color4(100, 150, 200, 255), new Color4(55, 110, 166, 255), - new Color4(75, 125, 175, 255), - }); + new Color4(75, 125, 175, 255) + )); + AddStep("Disallow default colours fallback in source2", () => source2.Configuration.AllowDefaultComboColoursFallback = false); AddAssert("Check retrieved combo colours from source1", () => - { - var expectedColours = source1.Configuration.ComboColours; - return requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.SequenceEqual(expectedColours) ?? false; - }); + requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.SequenceEqual(source1.Configuration.ComboColours) ?? false); } [Test] From 5e634c118309cf56ccd14ce43d5681293aff529f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 20:51:58 +0900 Subject: [PATCH 4492/5608] Move test values to constants --- .../Background/TestSceneUserDimContainer.cs | 19 +++++++++++-------- .../Graphics/Containers/UserDimContainer.cs | 4 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index 03206402c3..8eb256538a 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -47,7 +47,10 @@ namespace osu.Game.Tests.Visual.Background lightenDuringBreaks.Value = false; }); - [TestCase(0.6f, 0.3f)] + private const float test_user_dim = 0.6f; + private const float test_user_dim_lightened = test_user_dim - UserDimContainer.BREAK_LIGHTEN_AMOUNT; + + [TestCase(test_user_dim, test_user_dim_lightened)] [TestCase(0.2f, 0.0f)] [TestCase(0.0f, 0.0f)] public void TestBreakLightening(float userDim, float expectedBreakDim) @@ -64,26 +67,26 @@ namespace osu.Game.Tests.Visual.Background [Test] public void TestEnableSettingDuringBreak() { - AddStep("set dim level 0.6", () => container.UserDimLevel.Value = 0.6f); + AddStep("set dim level 0.6", () => container.UserDimLevel.Value = test_user_dim); AddStep("set break", () => isBreakTime.Value = true); - AddUntilStep("not lightened", () => container.DimEqual(0.6f)); + AddUntilStep("not lightened", () => container.DimEqual(test_user_dim)); AddStep("set lighten during break", () => lightenDuringBreaks.Value = true); - AddUntilStep("has lightened", () => container.DimEqual(0.3f)); + AddUntilStep("has lightened", () => container.DimEqual(test_user_dim_lightened)); } [Test] public void TestDisableSettingDuringBreak() { - AddStep("set dim level 0.6", () => container.UserDimLevel.Value = 0.6f); + AddStep("set dim level 0.6", () => container.UserDimLevel.Value = test_user_dim); AddStep("set lighten during break", () => lightenDuringBreaks.Value = true); AddStep("set break", () => isBreakTime.Value = true); - AddUntilStep("has lightened", () => container.DimEqual(0.3f)); + AddUntilStep("has lightened", () => container.DimEqual(test_user_dim_lightened)); AddStep("clear lighten during break", () => lightenDuringBreaks.Value = false); - AddUntilStep("not lightened", () => container.DimEqual(0.6f)); + AddUntilStep("not lightened", () => container.DimEqual(test_user_dim)); AddStep("clear break", () => isBreakTime.Value = false); - AddUntilStep("not lightened", () => container.DimEqual(0.6f)); + AddUntilStep("not lightened", () => container.DimEqual(test_user_dim)); } private class TestUserDimContainer : UserDimContainer diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index dcc8a52e9d..e67cd94d5c 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -19,7 +19,7 @@ namespace osu.Game.Graphics.Containers /// /// Amount of lightening to apply to current dim level during break times. /// - private const float break_lighten_amount = 0.3f; + public const float BREAK_LIGHTEN_AMOUNT = 0.3f; protected const double BACKGROUND_FADE_DURATION = 800; @@ -52,7 +52,7 @@ namespace osu.Game.Graphics.Containers protected Bindable ShowVideo { get; private set; } - private float breakLightening => LightenDuringBreaks.Value && IsBreakTime.Value ? break_lighten_amount : 0; + private float breakLightening => LightenDuringBreaks.Value && IsBreakTime.Value ? BREAK_LIGHTEN_AMOUNT : 0; protected float DimLevel => Math.Max(EnableUserDim.Value ? (float)UserDimLevel.Value - breakLightening : 0, 0); protected override Container Content => dimContent; From ecc7fdc561a8d98e064fd0b47cc6bc7605dff53e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 21:04:56 +0900 Subject: [PATCH 4493/5608] Ensure a clean run on each test method --- .../Background/TestSceneUserDimContainer.cs | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index 8eb256538a..472c43096f 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -15,13 +15,22 @@ namespace osu.Game.Tests.Visual.Background { public class TestSceneUserDimContainer : OsuTestScene { - private readonly TestUserDimContainer container; - private readonly BindableBool isBreakTime = new BindableBool(); - private readonly Bindable lightenDuringBreaks = new Bindable(); + private TestUserDimContainer userDimContainer; - public TestSceneUserDimContainer() + private readonly BindableBool isBreakTime = new BindableBool(); + + private Bindable lightenDuringBreaks = new Bindable(); + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) { - Add(container = new TestUserDimContainer + lightenDuringBreaks = config.GetBindable(OsuSetting.LightenDuringBreaks); + } + + [SetUp] + public void SetUp() => Schedule(() => + { + Child = userDimContainer = new TestUserDimContainer { RelativeSizeAxes = Axes.Both, Child = new Box @@ -29,21 +38,11 @@ namespace osu.Game.Tests.Visual.Background Colour = Color4.White, RelativeSizeAxes = Axes.Both, }, - }); + }; - container.IsBreakTime.BindTo(isBreakTime); - } - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - config.BindWith(OsuSetting.LightenDuringBreaks, lightenDuringBreaks); - } - - [SetUp] - public void SetUp() => Schedule(() => - { + userDimContainer.IsBreakTime.BindTo(isBreakTime); isBreakTime.Value = false; + lightenDuringBreaks.Value = false; }); @@ -55,38 +54,38 @@ namespace osu.Game.Tests.Visual.Background [TestCase(0.0f, 0.0f)] public void TestBreakLightening(float userDim, float expectedBreakDim) { - AddStep($"set dim level {userDim}", () => container.UserDimLevel.Value = userDim); + AddStep($"set dim level {userDim}", () => userDimContainer.UserDimLevel.Value = userDim); AddStep("set lighten during break", () => lightenDuringBreaks.Value = true); AddStep("set break", () => isBreakTime.Value = true); - AddUntilStep("has lightened", () => container.DimEqual(expectedBreakDim)); + AddUntilStep("has lightened", () => userDimContainer.DimEqual(expectedBreakDim)); AddStep("clear break", () => isBreakTime.Value = false); - AddUntilStep("not lightened", () => container.DimEqual(userDim)); + AddUntilStep("not lightened", () => userDimContainer.DimEqual(userDim)); } [Test] public void TestEnableSettingDuringBreak() { - AddStep("set dim level 0.6", () => container.UserDimLevel.Value = test_user_dim); + AddStep("set dim level 0.6", () => userDimContainer.UserDimLevel.Value = test_user_dim); AddStep("set break", () => isBreakTime.Value = true); - AddUntilStep("not lightened", () => container.DimEqual(test_user_dim)); + AddUntilStep("not lightened", () => userDimContainer.DimEqual(test_user_dim)); AddStep("set lighten during break", () => lightenDuringBreaks.Value = true); - AddUntilStep("has lightened", () => container.DimEqual(test_user_dim_lightened)); + AddUntilStep("has lightened", () => userDimContainer.DimEqual(test_user_dim_lightened)); } [Test] public void TestDisableSettingDuringBreak() { - AddStep("set dim level 0.6", () => container.UserDimLevel.Value = test_user_dim); + AddStep("set dim level 0.6", () => userDimContainer.UserDimLevel.Value = test_user_dim); AddStep("set lighten during break", () => lightenDuringBreaks.Value = true); AddStep("set break", () => isBreakTime.Value = true); - AddUntilStep("has lightened", () => container.DimEqual(test_user_dim_lightened)); + AddUntilStep("has lightened", () => userDimContainer.DimEqual(test_user_dim_lightened)); AddStep("clear lighten during break", () => lightenDuringBreaks.Value = false); - AddUntilStep("not lightened", () => container.DimEqual(test_user_dim)); + AddUntilStep("not lightened", () => userDimContainer.DimEqual(test_user_dim)); AddStep("clear break", () => isBreakTime.Value = false); - AddUntilStep("not lightened", () => container.DimEqual(test_user_dim)); + AddUntilStep("not lightened", () => userDimContainer.DimEqual(test_user_dim)); } private class TestUserDimContainer : UserDimContainer From 002a125b4aee43b6eac28581a784ffe1fecd21bd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Dec 2019 21:14:26 +0800 Subject: [PATCH 4494/5608] make ModDifficultyAdjust generic --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- .../Mods/CatchModDifficultyAdjust.cs | 51 ------------------ osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../Mods/ManiaModDifficultyAdjust.cs | 22 -------- .../Mods/OsuModDifficultyAdjust.cs | 52 ------------------- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../Mods/TaikoModDifficultyAdjust.cs | 32 ------------ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 51 ++++++++++++++---- 9 files changed, 46 insertions(+), 170 deletions(-) delete mode 100644 osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs delete mode 100644 osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs delete mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs delete mode 100644 osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 6495c5379b..5973eea602 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.Catch case ModType.Conversion: return new Mod[] { - new CatchModDifficultyAdjust(), + new ModDifficultyAdjust(), }; case ModType.Automation: diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs deleted file mode 100644 index 6643ebadf1..0000000000 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Bindables; -using osu.Game.Beatmaps; -using osu.Game.Configuration; -using osu.Game.Rulesets.Mods; - -namespace osu.Game.Rulesets.Catch.Mods -{ - public class CatchModDifficultyAdjust : ModDifficultyAdjust - { - [SettingSource("Drain Rate", "Override the beatmap's set HP")] - public override BindableNumber DrainRate { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 1F, - }; - - [SettingSource("Fruit Size", "Override the beatmap's set CS")] - public override BindableNumber CircleSize { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; - - [SettingSource("Approach Rate", "Override the beatmap's set AR")] - public override BindableNumber ApproachRate { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; - - public override void ApplyToDifficulty(BeatmapDifficulty difficulty) - { - difficulty.DrainRate = DrainRate.Value; - difficulty.CircleSize = CircleSize.Value; - difficulty.ApproachRate = ApproachRate.Value; - difficulty.OverallDifficulty = ApproachRate.Value; - } - } -} diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index c4908d1993..520bcfb586 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Mania new ManiaModRandom(), new ManiaModDualStages(), new ManiaModMirror(), - new ManiaModDifficultyAdjust(), + new ModDifficultyAdjust(), }; case ModType.Automation: diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs deleted file mode 100644 index 67554e6b92..0000000000 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Bindables; -using osu.Game.Configuration; -using osu.Game.Rulesets.Mods; - -namespace osu.Game.Rulesets.Mania.Mods -{ - public class ManiaModDifficultyAdjust : ModDifficultyAdjust - { - [SettingSource("Overall Difficulty", "Override the beatmap's set OD")] - public override BindableNumber OverallDifficulty { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; - } -} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs deleted file mode 100644 index 86ab4579bb..0000000000 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Bindables; -using osu.Game.Configuration; -using osu.Game.Rulesets.Mods; - -namespace osu.Game.Rulesets.Osu.Mods -{ - public class OsuModDifficultyAdjust : ModDifficultyAdjust - { - [SettingSource("Drain Rate", "Override the beatmap's set HP")] - public override BindableNumber DrainRate { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; - - [SettingSource("Circle Size", "Override the beatmap's set CS")] - public override BindableNumber CircleSize { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; - - [SettingSource("Approach Rate", "Override the beatmap's set AR")] - public override BindableNumber ApproachRate { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; - - [SettingSource("Overall Difficulty", "Override the beatmap's set OD")] - public override BindableNumber OverallDifficulty { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; - } -} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 746876b217..b9fa14baa1 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -121,7 +121,7 @@ namespace osu.Game.Rulesets.Osu return new Mod[] { new OsuModTarget(), - new OsuModDifficultyAdjust(), + new ModDifficultyAdjust(), }; case ModType.Automation: diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs deleted file mode 100644 index ed76cf77ac..0000000000 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Bindables; -using osu.Game.Configuration; -using osu.Game.Rulesets.Mods; - -namespace osu.Game.Rulesets.Taiko.Mods -{ - public class TaikoModDifficultyAdjust : ModDifficultyAdjust - { - [SettingSource("Drain Rate", "Override the beatmap's set HP")] - public override BindableNumber DrainRate { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; - - [SettingSource("Overall Difficulty", "Override the beatmap's set OD")] - public override BindableNumber OverallDifficulty { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; - } -} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index c4c85c183b..40ce58aeca 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -100,7 +100,7 @@ namespace osu.Game.Rulesets.Taiko case ModType.Conversion: return new Mod[] { - new TaikoModDifficultyAdjust(), + new ModDifficultyAdjust(), }; case ModType.Automation: diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs index d1f6bf45b4..532da8a647 100644 --- a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -5,10 +5,11 @@ using osu.Game.Beatmaps; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using System; +using osu.Game.Configuration; namespace osu.Game.Rulesets.Mods { - public abstract class ModDifficultyAdjust : Mod, IApplicableToDifficulty + public class ModDifficultyAdjust : Mod, IApplicableToDifficulty { public override string Name => @"Difficulty Adjust"; @@ -24,20 +25,52 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => new[] { typeof(ModEasy), typeof(ModHardRock) }; - public virtual BindableNumber DrainRate { get; } + [SettingSource("Drain Rate", "Override the beatmap's set HP")] + public BindableNumber DrainRate { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; - public virtual BindableNumber CircleSize { get; } + [SettingSource("Circle Size", "Override the beatmap's set CS")] + public BindableNumber CircleSize { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; - public virtual BindableNumber ApproachRate { get; } + [SettingSource("Approach Rate", "Override the beatmap's set AR")] + public BindableNumber ApproachRate { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; - public virtual BindableNumber OverallDifficulty { get; } + [SettingSource("Overall Difficulty", "Override the beatmap's set OD")] + public BindableNumber OverallDifficulty { get; } = new BindableFloat + { + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + Precision = 0.1F, + }; public virtual void ApplyToDifficulty(BeatmapDifficulty difficulty) { - difficulty.DrainRate = DrainRate != null ? DrainRate.Value : difficulty.DrainRate; - difficulty.CircleSize = CircleSize != null ? CircleSize.Value : difficulty.CircleSize; - difficulty.ApproachRate = ApproachRate != null ? ApproachRate.Value : difficulty.ApproachRate; - difficulty.OverallDifficulty = OverallDifficulty != null ? OverallDifficulty.Value : difficulty.OverallDifficulty; + difficulty.DrainRate = DrainRate.Value; + difficulty.CircleSize = CircleSize.Value; + difficulty.ApproachRate = ApproachRate.Value; + difficulty.OverallDifficulty = OverallDifficulty.Value; } } } From c6cbf0f28a968ce42c5ba3f7731f98da822ac7e6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 12 Dec 2019 16:27:11 +0300 Subject: [PATCH 4495/5608] Add 1.0 skin to osu! ruleset test --- .../Resources/old-skin/approachcircle.png | Bin 0 -> 4540 bytes .../Resources/old-skin/hit0.png | Bin 0 -> 12904 bytes .../Resources/old-skin/hit100.png | Bin 0 -> 30853 bytes .../Resources/old-skin/hit300.png | Bin 0 -> 33649 bytes .../Resources/old-skin/hit50.png | Bin 0 -> 27832 bytes .../Resources/old-skin/hitcircle.png | Bin 0 -> 3572 bytes .../Resources/old-skin/hitcircleoverlay.png | Bin 0 -> 7113 bytes .../Resources/old-skin/skin.ini | 2 ++ .../SkinnableTestScene.cs | 5 ++++- 9 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/approachcircle.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/hit0.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/hit100.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/hit300.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/hit50.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/hitcircle.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/hitcircleoverlay.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/skin.ini diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/approachcircle.png b/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/approachcircle.png new file mode 100644 index 0000000000000000000000000000000000000000..ff8b02ce800824f510e8655a1a9d977418bbdeb3 GIT binary patch literal 4540 zcmV;t5ku~YP);J

@NHN+%xmd&%Mk3yL--e&pG%0_n}mDQ`*|v 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�cZa_2kS}f04>ihEu+(-}$68mAH8q>c4Yg}Zw1U5cyjPrzcc;21 zO}$F%L)_@T&0)*iXf-CvhjIO&mqFgsMtO0u9|8C^bCA~uMy{agX#U1Lf3yS=T8V3V zC`|-zcm6mMrruab(wUEJ^lq~9wIU%F(T@Dr`RSvfIRR#VjIn%mnC8%Gu%2`$9~bp< z+maNMH~22(3vM`d=S(0OZ@g$m<3Y_Ge4+FUjoH2rY^OlFHiUDH9u2-Jr!WDfO;0sQ zSH5~hJhf0|pdF`2)~VAW?&z%MnQ=!f&<|VfzMBwInyt$Rx%>X<=SlD4!;UNT>@PlNtt*&nR zy0BzmIP`)3j5bWkjyClEQIg)5FK C#z4*13%nv%sar3_~4ci)7wz%BiUeMi~U~D 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 Dvd!~3 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/hit300.png b/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/hit300.png new file mode 100644 index 0000000000000000000000000000000000000000..24945f7d925ee3cd4dbb741907aa1a4e8e90a1c5 GIT binary patch literal 33649 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 PUkRuy>nK&jZ6p5&sNh6p literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/hitcircle.png b/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/hitcircle.png new file mode 100644 index 0000000000000000000000000000000000000000..a5a3545abf2510e7eec395bf47b73d9082e1fd8d GIT binary patch literal 3572 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 u5 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/skin.ini b/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/skin.ini new file mode 100644 index 0000000000..5369de24e9 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/skin.ini @@ -0,0 +1,2 @@ +[General] +Version: 1.0 \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs b/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs index 38aac50df6..2fad3bd04f 100644 --- a/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs +++ b/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs @@ -19,9 +19,10 @@ namespace osu.Game.Rulesets.Osu.Tests private Skin metricsSkin; private Skin defaultSkin; private Skin specialSkin; + private Skin oldSkin; protected SkinnableTestScene() - : base(2, 2) + : base(2, 3) { } @@ -33,6 +34,7 @@ namespace osu.Game.Rulesets.Osu.Tests metricsSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore(dllStore, "Resources/metrics_skin"), audio, true); defaultSkin = skinManager.GetSkin(DefaultLegacySkin.Info); specialSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore(dllStore, "Resources/special_skin"), audio, true); + oldSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore(dllStore, "Resources/old_skin"), audio, true); } public void SetContents(Func creationFunction) @@ -41,6 +43,7 @@ namespace osu.Game.Rulesets.Osu.Tests Cell(1).Child = createProvider(metricsSkin, creationFunction); Cell(2).Child = createProvider(defaultSkin, creationFunction); Cell(3).Child = createProvider(specialSkin, creationFunction); + Cell(4).Child = createProvider(oldSkin, creationFunction); } private Drawable createProvider(Skin skin, Func creationFunction) From ec5b50696058f293dda54c2f0e8b8f2cf9620a57 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Dec 2019 23:41:46 +0800 Subject: [PATCH 4496/5608] apply mod difficulty settings during song select --- .../SongSelect/TestSceneBeatmapDetailArea.cs | 69 ++++++++++++++++- .../Screens/Select/Details/AdvancedStats.cs | 77 +++++++++++++++---- 2 files changed, 128 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index ed9e01a67e..ad7ef558c4 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -8,6 +8,9 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Select; using osu.Game.Tests.Beatmaps; using osuTK; @@ -20,8 +23,10 @@ namespace osu.Game.Tests.Visual.SongSelect { public override IReadOnlyList RequiredTypes => new[] { typeof(BeatmapDetails) }; + private ModDisplay modDisplay; + [BackgroundDependencyLoader] - private void load(OsuGameBase game) + private void load(OsuGameBase game, RulesetStore rulesets) { BeatmapDetailArea detailsArea; Add(detailsArea = new BeatmapDetailArea @@ -31,6 +36,16 @@ namespace osu.Game.Tests.Visual.SongSelect Size = new Vector2(550f, 450f), }); + Add(modDisplay = new ModDisplay + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Position = new Vector2(0, 25), + }); + + modDisplay.Current.BindTo(Mods); + AddStep("all metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { BeatmapInfo = @@ -163,6 +178,58 @@ namespace osu.Game.Tests.Visual.SongSelect })); AddStep("null beatmap", () => detailsArea.Beatmap = null); + + AddStep("with EZ mod", () => + { + detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap + { + BeatmapInfo = + { + Version = "Has Easy Mod", + Metadata = new BeatmapMetadata + { + Source = "osu!lazer", + Tags = "this beatmap has the easy mod enabled", + }, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 3, + DrainRate = 3, + OverallDifficulty = 3, + ApproachRate = 3, + }, + StarDifficulty = 1f, + } + }); + + Mods.Value = new[] { rulesets.AvailableRulesets.First().CreateInstance().GetAllMods().First(m => m is ModEasy) }; + }); + + AddStep("with HR mod", () => + { + detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap + { + BeatmapInfo = + { + Version = "Has Hard Rock Mod", + Metadata = new BeatmapMetadata + { + Source = "osu!lazer", + Tags = "this beatmap has the hard rock mod enabled", + }, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 3, + DrainRate = 3, + OverallDifficulty = 3, + ApproachRate = 3, + }, + StarDifficulty = 1f, + } + }); + + Mods.Value = new[] { rulesets.AvailableRulesets.First().CreateInstance().GetAllMods().First(m => m is ModHardRock) }; + }); } } } diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index c5bdc230d0..be03b7ddd5 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -12,11 +12,21 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using System; using osu.Game.Beatmaps; +using osu.Framework.Bindables; +using System.Collections.Generic; +using osu.Game.Rulesets.Mods; +using System.Linq; namespace osu.Game.Screens.Select.Details { public class AdvancedStats : Container { + [Resolved] + private IBindable> mods { get; set; } + + [Resolved] + private OsuColour colours { get; set; } + private readonly StatisticRow firstValue, hpDrain, accuracy, approachRate, starDifficulty; private BeatmapInfo beatmap; @@ -30,22 +40,7 @@ namespace osu.Game.Screens.Select.Details beatmap = value; - //mania specific - if ((Beatmap?.Ruleset?.ID ?? 0) == 3) - { - firstValue.Title = "Key Amount"; - firstValue.Value = (int)MathF.Round(Beatmap?.BaseDifficulty?.CircleSize ?? 0); - } - else - { - firstValue.Title = "Circle Size"; - firstValue.Value = Beatmap?.BaseDifficulty?.CircleSize ?? 0; - } - - hpDrain.Value = Beatmap?.BaseDifficulty?.DrainRate ?? 0; - accuracy.Value = Beatmap?.BaseDifficulty?.OverallDifficulty ?? 0; - approachRate.Value = Beatmap?.BaseDifficulty?.ApproachRate ?? 0; - starDifficulty.Value = (float)(Beatmap?.StarDifficulty ?? 0); + updateStatistics(); } } @@ -65,12 +60,60 @@ namespace osu.Game.Screens.Select.Details starDifficulty = new StatisticRow(10, true) { Title = "Star Difficulty" }, }, }; + } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { starDifficulty.AccentColour = colours.Yellow; + mods.ValueChanged += _ => updateStatistics(); + } + + private void updateStatistics() + { + BeatmapInfo processed = Beatmap?.Clone(); + + if (processed != null && mods.Value.Any(m => m is IApplicableToDifficulty)) + { + processed.BaseDifficulty = processed.BaseDifficulty.Clone(); + + foreach (var mod in mods.Value.OfType()) + mod.ApplyToDifficulty(processed.BaseDifficulty); + } + + BeatmapDifficulty baseDifficulty = Beatmap?.BaseDifficulty; + BeatmapDifficulty moddedDifficulty = processed?.BaseDifficulty; + + //mania specific + if ((processed?.Ruleset?.ID ?? 0) == 3) + { + firstValue.Title = "Key Amount"; + firstValue.Value = (int)MathF.Round(moddedDifficulty?.CircleSize ?? 0); + } + else + { + firstValue.Title = "Circle Size"; + firstValue.Value = moddedDifficulty?.CircleSize ?? 0; + } + + hpDrain.Value = moddedDifficulty?.DrainRate ?? 0; + accuracy.Value = moddedDifficulty?.OverallDifficulty ?? 0; + approachRate.Value = moddedDifficulty?.ApproachRate ?? 0; + starDifficulty.Value = (float)(processed?.StarDifficulty ?? 0); + + hpDrain.AccentColour = (moddedDifficulty?.DrainRate ?? 0) == (baseDifficulty?.DrainRate ?? 0) ? + Color4.White : (moddedDifficulty?.DrainRate ?? 0) < (baseDifficulty?.DrainRate ?? 0) ? + colours.BlueLight : colours.RedLight; + accuracy.AccentColour = (moddedDifficulty?.OverallDifficulty ?? 0) == (baseDifficulty?.OverallDifficulty ?? 0) ? + Color4.White : (moddedDifficulty?.OverallDifficulty ?? 0) < (baseDifficulty?.OverallDifficulty ?? 0) ? + colours.BlueLight : colours.RedLight; + approachRate.AccentColour = (moddedDifficulty?.ApproachRate ?? 0) == (baseDifficulty?.ApproachRate ?? 0) ? + Color4.White : (moddedDifficulty?.ApproachRate ?? 0) < (baseDifficulty?.ApproachRate ?? 0) ? + colours.BlueLight : colours.RedLight; + firstValue.AccentColour = (moddedDifficulty?.CircleSize ?? 0) == (baseDifficulty?.CircleSize ?? 0) ? + Color4.White : (moddedDifficulty?.CircleSize ?? 0) < (baseDifficulty?.CircleSize ?? 0) ? + colours.BlueLight : colours.RedLight; } private class StatisticRow : Container, IHasAccentColour From 3945e7403aec4c08a249a9fd6a041f71327e96ee Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Dec 2019 09:39:54 +0800 Subject: [PATCH 4497/5608] improve tests and refactor AdvancedStats --- .../SongSelect/TestSceneBeatmapDetailArea.cs | 6 +- .../Screens/Select/Details/AdvancedStats.cs | 77 ++++++++++++------- 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index ad7ef558c4..d4805a73e4 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -179,6 +179,8 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("null beatmap", () => detailsArea.Beatmap = null); + Ruleset ruleset = rulesets.AvailableRulesets.First().CreateInstance(); + AddStep("with EZ mod", () => { detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap @@ -202,7 +204,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - Mods.Value = new[] { rulesets.AvailableRulesets.First().CreateInstance().GetAllMods().First(m => m is ModEasy) }; + Mods.Value = new[] { ruleset.GetAllMods().First(m => m is ModEasy) }; }); AddStep("with HR mod", () => @@ -228,7 +230,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - Mods.Value = new[] { rulesets.AvailableRulesets.First().CreateInstance().GetAllMods().First(m => m is ModHardRock) }; + Mods.Value = new[] { ruleset.GetAllMods().First(m => m is ModHardRock) }; }); } } diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index be03b7ddd5..3e7d4e244b 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -24,9 +24,6 @@ namespace osu.Game.Screens.Select.Details [Resolved] private IBindable> mods { get; set; } - [Resolved] - private OsuColour colours { get; set; } - private readonly StatisticRow firstValue, hpDrain, accuracy, approachRate, starDifficulty; private BeatmapInfo beatmap; @@ -60,11 +57,10 @@ namespace osu.Game.Screens.Select.Details starDifficulty = new StatisticRow(10, true) { Title = "Star Difficulty" }, }, }; - } [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { starDifficulty.AccentColour = colours.Yellow; mods.ValueChanged += _ => updateStatistics(); @@ -89,31 +85,24 @@ namespace osu.Game.Screens.Select.Details if ((processed?.Ruleset?.ID ?? 0) == 3) { firstValue.Title = "Key Amount"; - firstValue.Value = (int)MathF.Round(moddedDifficulty?.CircleSize ?? 0); + firstValue.BaseValue = (int)MathF.Round(baseDifficulty?.CircleSize ?? 0); + firstValue.ModdedValue = (int)MathF.Round(moddedDifficulty?.CircleSize ?? 0); } else { firstValue.Title = "Circle Size"; - firstValue.Value = moddedDifficulty?.CircleSize ?? 0; + firstValue.BaseValue = baseDifficulty?.CircleSize ?? 0; + firstValue.ModdedValue = moddedDifficulty?.CircleSize ?? 0; } - hpDrain.Value = moddedDifficulty?.DrainRate ?? 0; - accuracy.Value = moddedDifficulty?.OverallDifficulty ?? 0; - approachRate.Value = moddedDifficulty?.ApproachRate ?? 0; - starDifficulty.Value = (float)(processed?.StarDifficulty ?? 0); + hpDrain.BaseValue = baseDifficulty?.DrainRate ?? 0; + accuracy.BaseValue = baseDifficulty?.OverallDifficulty ?? 0; + approachRate.BaseValue = baseDifficulty?.ApproachRate ?? 0; + starDifficulty.BaseValue = (float)(processed?.StarDifficulty ?? 0); - hpDrain.AccentColour = (moddedDifficulty?.DrainRate ?? 0) == (baseDifficulty?.DrainRate ?? 0) ? - Color4.White : (moddedDifficulty?.DrainRate ?? 0) < (baseDifficulty?.DrainRate ?? 0) ? - colours.BlueLight : colours.RedLight; - accuracy.AccentColour = (moddedDifficulty?.OverallDifficulty ?? 0) == (baseDifficulty?.OverallDifficulty ?? 0) ? - Color4.White : (moddedDifficulty?.OverallDifficulty ?? 0) < (baseDifficulty?.OverallDifficulty ?? 0) ? - colours.BlueLight : colours.RedLight; - approachRate.AccentColour = (moddedDifficulty?.ApproachRate ?? 0) == (baseDifficulty?.ApproachRate ?? 0) ? - Color4.White : (moddedDifficulty?.ApproachRate ?? 0) < (baseDifficulty?.ApproachRate ?? 0) ? - colours.BlueLight : colours.RedLight; - firstValue.AccentColour = (moddedDifficulty?.CircleSize ?? 0) == (baseDifficulty?.CircleSize ?? 0) ? - Color4.White : (moddedDifficulty?.CircleSize ?? 0) < (baseDifficulty?.CircleSize ?? 0) ? - colours.BlueLight : colours.RedLight; + hpDrain.ModdedValue = moddedDifficulty?.DrainRate ?? 0; + accuracy.ModdedValue = moddedDifficulty?.OverallDifficulty ?? 0; + approachRate.ModdedValue = moddedDifficulty?.ApproachRate ?? 0; } private class StatisticRow : Container, IHasAccentColour @@ -124,7 +113,10 @@ namespace osu.Game.Screens.Select.Details private readonly float maxValue; private readonly bool forceDecimalPlaces; private readonly OsuSpriteText name, value; - private readonly Bar bar; + private readonly Bar bar, modBar; + + [Resolved] + private OsuColour colours { get; set; } public string Title { @@ -132,19 +124,39 @@ namespace osu.Game.Screens.Select.Details set => name.Text = value; } - private float difficultyValue; + private float baseValue; - public float Value + private float moddedValue; + + public float BaseValue { - get => difficultyValue; + get => baseValue; set { - difficultyValue = value; + baseValue = value; bar.Length = value / maxValue; this.value.Text = value.ToString(forceDecimalPlaces ? "0.00" : "0.##"); } } + public float ModdedValue + { + get => moddedValue; + set + { + moddedValue = value; + modBar.Length = value / maxValue; + this.value.Text = value.ToString(forceDecimalPlaces ? "0.00" : "0.##"); + + if (moddedValue > baseValue) + modBar.AccentColour = this.value.Colour = colours.Red; + else if (moddedValue < baseValue) + modBar.AccentColour = this.value.Colour = colours.BlueDark; + else + modBar.AccentColour = this.value.Colour = Color4.White; + } + } + public Color4 AccentColour { get => bar.AccentColour; @@ -178,6 +190,15 @@ namespace osu.Game.Screens.Select.Details BackgroundColour = Color4.White.Opacity(0.5f), Padding = new MarginPadding { Left = name_width + 10, Right = value_width + 10 }, }, + modBar = new Bar + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, + Alpha = 0.5f, + Height = 5, + Padding = new MarginPadding { Left = name_width + 10, Right = value_width + 10 }, + }, new Container { Anchor = Anchor.TopRight, From ababe7b6c995b2943ad71ce23d9734a62b412bcc Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Dec 2019 15:22:07 +0800 Subject: [PATCH 4498/5608] refactor mod to make use of #7175 --- osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs index 532da8a647..f65340e90c 100644 --- a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -65,12 +65,24 @@ namespace osu.Game.Rulesets.Mods Precision = 0.1F, }; + private BeatmapDifficulty difficulty; + public virtual void ApplyToDifficulty(BeatmapDifficulty difficulty) { - difficulty.DrainRate = DrainRate.Value; - difficulty.CircleSize = CircleSize.Value; - difficulty.ApproachRate = ApproachRate.Value; - difficulty.OverallDifficulty = OverallDifficulty.Value; + if (this.difficulty == null || this.difficulty.ID != difficulty.ID) + { + this.difficulty = difficulty; + DrainRate.Value = DrainRate.Default = difficulty.DrainRate; + CircleSize.Value = CircleSize.Default = difficulty.CircleSize; + ApproachRate.Value = ApproachRate.Default = difficulty.ApproachRate; + OverallDifficulty.Value = OverallDifficulty.Default = difficulty.OverallDifficulty; + } else + { + difficulty.DrainRate = DrainRate.Value; + difficulty.CircleSize = CircleSize.Value; + difficulty.ApproachRate = ApproachRate.Value; + difficulty.OverallDifficulty = OverallDifficulty.Value; + } } } } From 0311cc83ad1387d2191d104fab1617a5b4db347a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Dec 2019 15:27:34 +0800 Subject: [PATCH 4499/5608] add whitespace --- osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs index f65340e90c..f6216df2b5 100644 --- a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -76,7 +76,8 @@ namespace osu.Game.Rulesets.Mods CircleSize.Value = CircleSize.Default = difficulty.CircleSize; ApproachRate.Value = ApproachRate.Default = difficulty.ApproachRate; OverallDifficulty.Value = OverallDifficulty.Default = difficulty.OverallDifficulty; - } else + } + else { difficulty.DrainRate = DrainRate.Value; difficulty.CircleSize = CircleSize.Value; From ab5aa8594de8cf994834014885ae28818827030f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Dec 2019 15:46:58 +0800 Subject: [PATCH 4500/5608] remove whitespace --- osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs index f6216df2b5..b23297345b 100644 --- a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Mods CircleSize.Value = CircleSize.Default = difficulty.CircleSize; ApproachRate.Value = ApproachRate.Default = difficulty.ApproachRate; OverallDifficulty.Value = OverallDifficulty.Default = difficulty.OverallDifficulty; - } + } else { difficulty.DrainRate = DrainRate.Value; From 53a665a034cfa95f926c3334c4a8e77bf370a803 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 20:04:46 +0900 Subject: [PATCH 4501/5608] Fix sound types and banks not being written correctly --- .../Beatmaps/Formats/LegacyBeatmapEncoder.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 0eeacf733d..4c8b83820d 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -236,6 +236,10 @@ namespace osu.Game.Beatmaps.Formats writer.Write(FormattableString.Invariant($"{positionData.Y},")); writer.Write(FormattableString.Invariant($"{hitObject.StartTime},")); writer.Write(FormattableString.Invariant($"{(int)hitObjectType},")); + + if (hitObject is IHasCurve _) + writer.Write(FormattableString.Invariant($"0,")); // A sound type of "none" is written since it's stored per-node + else writer.Write(FormattableString.Invariant($"{(int)toLegacyHitSoundType(hitObject.Samples)},")); if (hitObject is IHasCurve curveData) @@ -303,7 +307,11 @@ namespace osu.Game.Beatmaps.Formats else if (hitObject is IHasEndTime endTimeData) writer.Write(FormattableString.Invariant($"{endTimeData.EndTime},")); - writer.Write(getSampleBank(hitObject.Samples)); + if (hitObject is IHasCurve _) + writer.Write(getSampleBank(hitObject.Samples, zeroBanks: true)); // A bank of "none" is written since it's stored per-node + else + writer.Write(getSampleBank(hitObject.Samples)); + writer.Write(Environment.NewLine); } @@ -319,14 +327,11 @@ namespace osu.Game.Beatmaps.Formats { } - private string getSampleBank(IList samples, bool banksOnly = false) + private string getSampleBank(IList samples, bool banksOnly = false, bool zeroBanks = false) { LegacySampleBank normalBank = toLegacySampleBank(samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL)?.Bank); LegacySampleBank addBank = toLegacySampleBank(samples.FirstOrDefault(s => !string.IsNullOrEmpty(s.Name) && s.Name != HitSampleInfo.HIT_NORMAL)?.Bank); - if (addBank == LegacySampleBank.None) - addBank = normalBank; - string customSampleBank = toLegacyCustomSampleBank(samples.FirstOrDefault()?.Suffix); string sampleFilename = samples.FirstOrDefault(s => string.IsNullOrEmpty(s.Name))?.LookupNames.First() ?? string.Empty; @@ -334,8 +339,8 @@ namespace osu.Game.Beatmaps.Formats StringBuilder sb = new StringBuilder(); - sb.Append(FormattableString.Invariant($"{(int)normalBank}:")); - sb.Append(FormattableString.Invariant($"{(int)addBank}")); + sb.Append(FormattableString.Invariant($"{(zeroBanks ? 0 : (int)normalBank)}:")); + sb.Append(FormattableString.Invariant($"{(zeroBanks ? 0 : (int)addBank)}")); if (!banksOnly) { From 0b7c4f252c19578ff4d1da03cb4d6f3962e497fe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Dec 2019 17:01:59 +0900 Subject: [PATCH 4502/5608] Fix artist being written in place of version --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 4c8b83820d..efb8527d65 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -108,7 +108,7 @@ namespace osu.Game.Beatmaps.Formats writer.WriteLine(FormattableString.Invariant($"Artist: {beatmap.Metadata.Artist}")); writer.WriteLine(FormattableString.Invariant($"ArtistUnicode: {beatmap.Metadata.ArtistUnicode}")); writer.WriteLine(FormattableString.Invariant($"Creator: {beatmap.Metadata.AuthorString}")); - writer.WriteLine(FormattableString.Invariant($"Version: {beatmap.Metadata.Artist}")); + writer.WriteLine(FormattableString.Invariant($"Version: {beatmap.BeatmapInfo.Version}")); writer.WriteLine(FormattableString.Invariant($"Source: {beatmap.Metadata.Source}")); writer.WriteLine(FormattableString.Invariant($"Tags: {beatmap.Metadata.Tags}")); writer.WriteLine(FormattableString.Invariant($"BeatmapID: {beatmap.BeatmapInfo.OnlineBeatmapID ?? 0}")); From 97158fce7de679c07393307303d8438f3ea473f6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Dec 2019 17:02:10 +0900 Subject: [PATCH 4503/5608] Always attach a new combo to spinners --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index efb8527d65..ff5d6ceebe 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -228,7 +228,7 @@ namespace osu.Game.Beatmaps.Formats if (hitObject is IHasCurve _) hitObjectType |= LegacyHitObjectType.Slider; else if (hitObject is IHasEndTime _) - hitObjectType |= LegacyHitObjectType.Spinner; + hitObjectType |= LegacyHitObjectType.Spinner | LegacyHitObjectType.NewCombo; else hitObjectType |= LegacyHitObjectType.Circle; From 654499d8b017c19a37b76ef1a3dbbe45a410ace3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Dec 2019 17:33:18 +0900 Subject: [PATCH 4504/5608] Remove whitespace --- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 1c2ca4b6f8..5bc7897499 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -148,10 +148,6 @@ namespace osu.Game.Beatmaps.Formats Fonts } - - - - internal class LegacyDifficultyControlPoint : DifficultyControlPoint { public LegacyDifficultyControlPoint() From 87a7f340e3100b7f1ee1f9a2c4b05abdb194b86b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Dec 2019 18:12:44 +0900 Subject: [PATCH 4505/5608] Fix first sample point being treated as redundant --- osu.Game.Tests/NonVisual/ControlPointInfoTest.cs | 12 ++++++------ osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs index a51b90851c..0535473a3f 100644 --- a/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs +++ b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs @@ -60,18 +60,18 @@ namespace osu.Game.Tests.NonVisual { var cpi = new ControlPointInfo(); - cpi.Add(0, new SampleControlPoint()); // is redundant + cpi.Add(0, new SampleControlPoint()); // is *not* redundant, special exception for first sample point cpi.Add(1000, new SampleControlPoint()); // is redundant - Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); Assert.That(cpi.TimingPoints.Count, Is.EqualTo(0)); - Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); cpi.Add(1000, new SampleControlPoint { SampleVolume = 50 }); // is not redundant - Assert.That(cpi.Groups.Count, Is.EqualTo(1)); - Assert.That(cpi.SamplePoints.Count, Is.EqualTo(1)); - Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); + Assert.That(cpi.Groups.Count, Is.EqualTo(2)); + Assert.That(cpi.SamplePoints.Count, Is.EqualTo(2)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(2)); } [Test] diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index ce2783004c..6965544292 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -239,7 +239,7 @@ namespace osu.Game.Beatmaps.ControlPoints break; case SampleControlPoint _: - existing = SamplePointAt(time); + existing = binarySearch(SamplePoints, time); break; case DifficultyControlPoint _: From 36f541d8e5ce77a846646063ba10903a93690965 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Dec 2019 18:13:24 +0900 Subject: [PATCH 4506/5608] Fix incorrect asserts --- osu.Game.Tests/NonVisual/ControlPointInfoTest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs index 0535473a3f..2782e902fe 100644 --- a/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs +++ b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.NonVisual cpi.Add(1000, new DifficultyControlPoint()); // is redundant Assert.That(cpi.Groups.Count, Is.EqualTo(0)); - Assert.That(cpi.TimingPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(0)); Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(0)); cpi.Add(1000, new DifficultyControlPoint { SpeedMultiplier = 2 }); // is not redundant @@ -64,7 +64,7 @@ namespace osu.Game.Tests.NonVisual cpi.Add(1000, new SampleControlPoint()); // is redundant Assert.That(cpi.Groups.Count, Is.EqualTo(1)); - Assert.That(cpi.TimingPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.SamplePoints.Count, Is.EqualTo(1)); Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); cpi.Add(1000, new SampleControlPoint { SampleVolume = 50 }); // is not redundant @@ -83,7 +83,7 @@ namespace osu.Game.Tests.NonVisual cpi.Add(1000, new EffectControlPoint()); // is redundant Assert.That(cpi.Groups.Count, Is.EqualTo(0)); - Assert.That(cpi.TimingPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.EffectPoints.Count, Is.EqualTo(0)); Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(0)); cpi.Add(1000, new EffectControlPoint { KiaiMode = true }); // is not redundant From c976427206680d9cfbad6b7ac6a463d50c85081f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Dec 2019 19:00:28 +0900 Subject: [PATCH 4507/5608] Refactor test to be more complete --- .../Formats/LegacyBeatmapEncoderTest.cs | 112 ++---------------- osu.Game.Tests/Resources/TestResources.cs | 6 +- 2 files changed, 16 insertions(+), 102 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs index c4a3877c1c..f2b3a16f68 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs @@ -1,16 +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 System.IO; using System.Linq; using NUnit.Framework; -using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.IO; -using osu.Game.Rulesets.Objects.Types; +using osu.Game.IO.Serialization; using osu.Game.Tests.Resources; -using osuTK; namespace osu.Game.Tests.Beatmaps.Formats { @@ -19,101 +18,18 @@ namespace osu.Game.Tests.Beatmaps.Formats { private const string normal = "Soleily - Renatus (Gamu) [Insane].osu"; - [Test] - public void TestDecodeMetadata() + private static IEnumerable allBeatmaps => TestResources.GetStore().GetAvailableResources().Where(res => res.EndsWith(".osu")); + + [TestCaseSource(nameof(allBeatmaps))] + public void TestDecodeEncodedBeatmap(string name) { - var beatmap = decode(normal); - var meta = beatmap.BeatmapInfo.Metadata; - Assert.AreEqual(241526, beatmap.BeatmapInfo.BeatmapSet.OnlineBeatmapSetID); - Assert.AreEqual("Soleily", meta.Artist); - Assert.AreEqual("Soleily", meta.ArtistUnicode); - Assert.AreEqual("03. Renatus - Soleily 192kbps.mp3", meta.AudioFile); - Assert.AreEqual("Gamu", meta.AuthorString); - Assert.AreEqual("machinetop_background.jpg", meta.BackgroundFile); - Assert.AreEqual(164471, meta.PreviewTime); - Assert.AreEqual(string.Empty, meta.Source); - Assert.AreEqual("MBC7 Unisphere 地球ヤバイEP Chikyu Yabai", meta.Tags); - Assert.AreEqual("Renatus", meta.Title); - Assert.AreEqual("Renatus", meta.TitleUnicode); + var decoded = decode(normal, out var encoded); + + Assert.That(decoded.HitObjects.Count, Is.EqualTo(encoded.HitObjects.Count)); + Assert.That(encoded.Serialize(), Is.EqualTo(decoded.Serialize())); } - [Test] - public void TestDecodeGeneral() - { - var beatmap = decode(normal); - var beatmapInfo = beatmap.BeatmapInfo; - Assert.AreEqual(0, beatmapInfo.AudioLeadIn); - Assert.AreEqual(false, beatmapInfo.Countdown); - Assert.AreEqual(0.7f, beatmapInfo.StackLeniency); - Assert.AreEqual(false, beatmapInfo.SpecialStyle); - Assert.IsTrue(beatmapInfo.RulesetID == 0); - Assert.AreEqual(false, beatmapInfo.LetterboxInBreaks); - Assert.AreEqual(false, beatmapInfo.WidescreenStoryboard); - } - - [Test] - public void TestDecodeEditor() - { - var beatmap = decode(normal); - var beatmapInfo = beatmap.BeatmapInfo; - - int[] expectedBookmarks = - { - 11505, 22054, 32604, 43153, 53703, 64252, 74802, 85351, - 95901, 106450, 116999, 119637, 130186, 140735, 151285, - 161834, 164471, 175020, 185570, 196119, 206669, 209306 - }; - Assert.AreEqual(expectedBookmarks.Length, beatmapInfo.Bookmarks.Length); - for (int i = 0; i < expectedBookmarks.Length; i++) - Assert.AreEqual(expectedBookmarks[i], beatmapInfo.Bookmarks[i]); - Assert.AreEqual(1.8, beatmapInfo.DistanceSpacing); - Assert.AreEqual(4, beatmapInfo.BeatDivisor); - Assert.AreEqual(4, beatmapInfo.GridSize); - Assert.AreEqual(2, beatmapInfo.TimelineZoom); - } - - [Test] - public void TestDecodeDifficulty() - { - var beatmap = decode(normal); - var difficulty = beatmap.BeatmapInfo.BaseDifficulty; - Assert.AreEqual(6.5f, difficulty.DrainRate); - Assert.AreEqual(4, difficulty.CircleSize); - Assert.AreEqual(8, difficulty.OverallDifficulty); - Assert.AreEqual(9, difficulty.ApproachRate); - Assert.AreEqual(1.8, difficulty.SliderMultiplier); - Assert.AreEqual(2, difficulty.SliderTickRate); - } - - [Test] - public void TestDecodeHitObjects() - { - var beatmap = decode(normal); - - var curveData = beatmap.HitObjects[0] as IHasCurve; - var positionData = beatmap.HitObjects[0] as IHasPosition; - - Assert.IsNotNull(positionData); - Assert.IsNotNull(curveData); - Assert.AreEqual(new Vector2(192, 168), positionData.Position); - Assert.AreEqual(956, beatmap.HitObjects[0].StartTime); - Assert.IsTrue(beatmap.HitObjects[0].Samples.Any(s => s.Name == HitSampleInfo.HIT_NORMAL)); - - positionData = beatmap.HitObjects[1] as IHasPosition; - - Assert.IsNotNull(positionData); - Assert.AreEqual(new Vector2(304, 56), positionData.Position); - Assert.AreEqual(1285, beatmap.HitObjects[1].StartTime); - Assert.IsTrue(beatmap.HitObjects[1].Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP)); - } - - private Beatmap decode(string filename) - { - decode(filename, out Beatmap jsonDecoded); - return jsonDecoded; - } - - private Beatmap decode(string filename, out Beatmap decoded) + private Beatmap decode(string filename, out Beatmap encoded) { using (var stream = TestResources.OpenResource(filename)) using (var sr = new LineBufferedReader(stream)) @@ -129,11 +45,7 @@ namespace osu.Game.Tests.Beatmaps.Formats ms.Position = 0; - string result = sr2.ReadToEnd(); - - ms.Position = 0; - - decoded = new LegacyBeatmapDecoder { ApplyOffsets = false }.Decode(sr2); + encoded = new LegacyBeatmapDecoder { ApplyOffsets = false }.Decode(sr2); return legacyDecoded; } } diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index 66084a3204..932021afe5 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -9,9 +9,11 @@ namespace osu.Game.Tests.Resources { public static class TestResources { - public static Stream OpenResource(string name) => new DllResourceStore("osu.Game.Tests.dll").GetStream($"Resources/{name}"); + public static DllResourceStore GetStore() => new DllResourceStore("osu.Game.Tests.dll"); - public static Stream GetTestBeatmapStream(bool virtualTrack = false) => new DllResourceStore("osu.Game.Resources.dll").GetStream($"Beatmaps/241526 Soleily - Renatus{(virtualTrack ? "_virtual" : "")}.osz"); + public static Stream OpenResource(string name) => GetStore().GetStream($"Resources/{name}"); + + public static Stream GetTestBeatmapStream(bool virtualTrack = false) => GetStore().GetStream($"Beatmaps/241526 Soleily - Renatus{(virtualTrack ? "_virtual" : "")}.osz"); public static string GetTestBeatmapForImport(bool virtualTrack = false) { From 0ad28a9400b821e2d11a8e0c234f2030387e0119 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Dec 2019 19:11:45 +0900 Subject: [PATCH 4508/5608] Start at version 128 --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index ff5d6ceebe..f367ab3817 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -17,7 +17,7 @@ namespace osu.Game.Beatmaps.Formats { public class LegacyBeatmapEncoder { - public const int LATEST_VERSION = 14234; + public const int LATEST_VERSION = 128; private readonly IBeatmap beatmap; From 9bc02f489ee46f098cbea53d78e3cb6c2d001e5b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Dec 2019 19:14:49 +0900 Subject: [PATCH 4509/5608] Add missing headers --- osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs | 3 +++ osu.Game/Beatmaps/Legacy/LegacyEventType.cs | 3 +++ osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs | 3 +++ osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs | 3 +++ osu.Game/Beatmaps/Legacy/LegacyOrigins.cs | 3 +++ osu.Game/Beatmaps/Legacy/LegacySampleBank.cs | 3 +++ osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs | 3 +++ 7 files changed, 21 insertions(+) diff --git a/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs b/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs index ce141031fd..5bf80c34d7 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs @@ -1,3 +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; namespace osu.Game.Beatmaps.Legacy diff --git a/osu.Game/Beatmaps/Legacy/LegacyEventType.cs b/osu.Game/Beatmaps/Legacy/LegacyEventType.cs index 57b1e6c29f..32a7122978 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyEventType.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyEventType.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + namespace osu.Game.Beatmaps.Legacy { internal enum LegacyEventType diff --git a/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs b/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs index 9223f7df31..ec9839b893 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs @@ -1,3 +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; namespace osu.Game.Beatmaps.Legacy diff --git a/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs b/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs index 69adbf8f67..d7743565f8 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs @@ -1,3 +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; namespace osu.Game.Beatmaps.Legacy diff --git a/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs b/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs index 93c8920761..31f67d6dfd 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + namespace osu.Game.Beatmaps.Legacy { internal enum LegacyOrigins diff --git a/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs b/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs index 0d54998d15..8cac29cb87 100644 --- a/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs +++ b/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + namespace osu.Game.Beatmaps.Legacy { internal enum LegacySampleBank diff --git a/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs b/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs index 509f39f830..5237445640 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + namespace osu.Game.Beatmaps.Legacy { internal enum LegacyStoryLayer From 952bc96bbf3223b2415a486c3b8b922e57328ee4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:05:38 +0900 Subject: [PATCH 4510/5608] Use GameBase data sources for Beatmap/Mods/Ruleset Sourced in via OsuScreenDependencies for management --- osu.Game/Tests/Visual/OsuTestScene.cs | 40 ++++++++++----------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 4ca0ec0f7e..4a561f17a3 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -12,7 +12,6 @@ using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Textures; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Timing; @@ -21,6 +20,7 @@ using osu.Game.Database; using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Screens; using osu.Game.Storyboards; using osu.Game.Tests.Beatmaps; @@ -28,21 +28,13 @@ namespace osu.Game.Tests.Visual { public abstract class OsuTestScene : TestScene { - [Cached(typeof(Bindable))] - [Cached(typeof(IBindable))] - private NonNullableBindable beatmap; + protected Bindable Beatmap { get; private set; } - protected Bindable Beatmap => beatmap; + protected Bindable Ruleset; - [Cached] - [Cached(typeof(IBindable))] - protected readonly Bindable Ruleset = new Bindable(); + protected Bindable> Mods; - [Cached] - [Cached(Type = typeof(IBindable>))] - protected readonly Bindable> Mods = new Bindable>(Array.Empty()); - - protected new DependencyContainer Dependencies { get; private set; } + protected new OsuScreenDependencies Dependencies { get; private set; } private readonly Lazy localStorage; protected Storage LocalStorage => localStorage.Value; @@ -72,18 +64,16 @@ namespace osu.Game.Tests.Visual protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - // This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures - var working = new DummyWorkingBeatmap(parent.Get(), parent.Get()); + Dependencies = new OsuScreenDependencies(false, base.CreateChildDependencies(parent)); - beatmap = new NonNullableBindable(working) { Default = working }; - beatmap.BindValueChanged(b => ScheduleAfterChildren(() => - { - // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo) - if (b.OldValue?.TrackLoaded == true && b.OldValue?.Track != b.NewValue?.Track) - b.OldValue.RecycleTrack(); - })); + Beatmap = Dependencies.Beatmap; + Beatmap.SetDefault(); - Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + Ruleset = Dependencies.Ruleset; + Ruleset.SetDefault(); + + Mods = Dependencies.Mods; + Mods.SetDefault(); if (!UseOnlineAPI) { @@ -135,8 +125,8 @@ namespace osu.Game.Tests.Visual { base.Dispose(isDisposing); - if (beatmap?.Value.TrackLoaded == true) - beatmap.Value.Track.Stop(); + if (Beatmap?.Value.TrackLoaded == true) + Beatmap.Value.Track.Stop(); if (contextFactory.IsValueCreated) contextFactory.Value.ResetDatabase(); From 395b058ff872a28cf74554088ec04f26eff319d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:05:54 +0900 Subject: [PATCH 4511/5608] Fix OsuScreenDependencies not caching non-leased versions --- osu.Game/Screens/OsuScreenDependencies.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Screens/OsuScreenDependencies.cs b/osu.Game/Screens/OsuScreenDependencies.cs index 115f4b7e1a..8d54829d49 100644 --- a/osu.Game/Screens/OsuScreenDependencies.cs +++ b/osu.Game/Screens/OsuScreenDependencies.cs @@ -26,16 +26,26 @@ namespace osu.Game.Screens Beatmap = parent.Get>()?.GetBoundCopy(); if (Beatmap == null) + { Cache(Beatmap = parent.Get>().BeginLease(false)); + CacheAs(Beatmap); + } Ruleset = parent.Get>()?.GetBoundCopy(); if (Ruleset == null) + { Cache(Ruleset = parent.Get>().BeginLease(true)); + CacheAs(Ruleset); + } Mods = parent.Get>>()?.GetBoundCopy(); + if (Mods == null) + { Cache(Mods = parent.Get>>().BeginLease(true)); + CacheAs(Mods); + } } else { From 3dc2b59d2a066e4827f52aff6c7951cd72cfddd4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:06:12 +0900 Subject: [PATCH 4512/5608] Move variable above common bindables --- osu.Game/Screens/OsuScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 94165fe4b7..6394fb8d23 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -87,12 +87,12 @@ namespace osu.Game.Screens public virtual float BackgroundParallaxAmount => 1; + public virtual bool AllowRateAdjustments => true; + public Bindable Beatmap { get; private set; } public Bindable Ruleset { get; private set; } - public virtual bool AllowRateAdjustments => true; - public Bindable> Mods { get; private set; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) From 7033974733537e4d32984f4efeae2c578534fc04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:06:56 +0900 Subject: [PATCH 4513/5608] Fix test regressions (incorrect from the start) --- .../TestSceneDrawableHitObjectsHidden.cs | 6 ++++-- osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs | 5 +++-- osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs | 5 +++-- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs | 5 +++-- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs index f6d26addaa..08107e01eb 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NUnit.Framework; using osu.Game.Rulesets.Catch.Mods; namespace osu.Game.Rulesets.Catch.Tests @@ -12,9 +13,10 @@ namespace osu.Game.Rulesets.Catch.Tests { public override IReadOnlyList RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(CatchModHidden) }).ToList(); - public TestSceneDrawableHitObjectsHidden() + [SetUp] + public void SetUp() => Schedule(() => { Mods.Value = new[] { new CatchModHidden() }; - } + }); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs index 55c6b22146..eaba82a469 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs @@ -14,9 +14,10 @@ namespace osu.Game.Rulesets.Osu.Tests { public override IReadOnlyList RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(OsuModHidden) }).ToList(); - public TestSceneHitCircleHidden() + [SetUp] + public void SetUp() => Schedule(() => { Mods.Value = new[] { new OsuModHidden() }; - } + }); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs index 2a9c1d167b..a1795fb877 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs @@ -14,9 +14,10 @@ namespace osu.Game.Rulesets.Osu.Tests { public override IReadOnlyList RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(OsuModHidden) }).ToList(); - public TestSceneSliderHidden() + [SetUp] + public void SetUp() => Schedule(() => { Mods.Value = new[] { new OsuModHidden() }; - } + }); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs index a0ab1908d6..2976d4fdce 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs @@ -14,9 +14,10 @@ namespace osu.Game.Rulesets.Osu.Tests { public override IReadOnlyList RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(OsuModHidden) }).ToList(); - public TestSceneSpinnerHidden() + [SetUp] + public void SetUp() => Schedule(() => { Mods.Value = new[] { new OsuModHidden() }; - } + }); } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index be50200e1c..8cf2d29906 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -124,7 +124,7 @@ namespace osu.Game.Tests.Visual.UserInterface var easierMods = instance.GetModsFor(ModType.DifficultyReduction); var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); - AddStep("set mods externally", () => { modDisplay.Current.Value = new[] { noFailMod }; }); + AddStep("set mods externally", () => { Mods.Value = new[] { noFailMod }; }); changeRuleset(rulesetOsu); From a1f8ab1735b755bd98b27697dbf3f99828716f28 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:13:53 +0900 Subject: [PATCH 4514/5608] Fix unrequired type keyword --- osu.Game/OsuGameBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index f310da3883..207fb91aab 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -80,7 +80,7 @@ namespace osu.Game // todo: move this to SongSelect once Screen has the ability to unsuspend. [Cached] - [Cached(Type = typeof(IBindable>))] + [Cached(typeof(IBindable>))] protected readonly Bindable> Mods = new Bindable>(Array.Empty()); protected Bindable Beatmap { get; private set; } // cached via load() method From 0bbaf9b7fbe760d4b57ca66bf82c114e952cf824 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:21:35 +0900 Subject: [PATCH 4515/5608] Fix mod select overlay tests not running individually --- .../TestSceneModSelectOverlay.cs | 101 +++++++++--------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 8cf2d29906..5f77116c67 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -8,13 +8,16 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Testing; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods; using osu.Game.Overlays.Mods.Sections; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.UI; using osu.Game.Screens.Play.HUD; @@ -48,42 +51,48 @@ namespace osu.Game.Tests.Visual.UserInterface private void load(RulesetStore rulesets) { this.rulesets = rulesets; + } - Add(modSelect = new TestModSelectOverlay + [SetUp] + public void SetUp() => Schedule(() => + { + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - Origin = Anchor.BottomCentre, - Anchor = Anchor.BottomCentre, - }); + modSelect = new TestModSelectOverlay + { + RelativeSizeAxes = Axes.X, + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + }, - Add(modDisplay = new ModDisplay - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Position = new Vector2(0, 25), - }); + modDisplay = new ModDisplay + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Position = new Vector2(0, 25), + Current = { BindTarget = modSelect.SelectedMods } + } + }; + }); - modDisplay.Current.UnbindBindings(); - modDisplay.Current.BindTo(modSelect.SelectedMods); - - AddStep("Show", modSelect.Show); - AddStep("Toggle", modSelect.ToggleVisibility); - AddStep("Toggle", modSelect.ToggleVisibility); + [SetUpSteps] + public void SetUpSteps() + { + AddStep("show", () => modSelect.Show()); } [Test] public void TestOsuMods() { - var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 0); - changeRuleset(ruleset); + changeRuleset(0); - var instance = ruleset.CreateInstance(); + var osu = new OsuRuleset(); - var easierMods = instance.GetModsFor(ModType.DifficultyReduction); - var harderMods = instance.GetModsFor(ModType.DifficultyIncrease); + var easierMods = osu.GetModsFor(ModType.DifficultyReduction); + var harderMods = osu.GetModsFor(ModType.DifficultyIncrease); - var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); + var noFailMod = osu.GetModsFor(ModType.DifficultyReduction).FirstOrDefault(m => m is OsuModNoFail); var hiddenMod = harderMods.FirstOrDefault(m => m is OsuModHidden); var doubleTimeMod = harderMods.OfType().FirstOrDefault(m => m.Mods.Any(a => a is OsuModDoubleTime)); @@ -97,8 +106,8 @@ namespace osu.Game.Tests.Visual.UserInterface testMultiMod(doubleTimeMod); testIncompatibleMods(easy, hardRock); testDeselectAll(easierMods.Where(m => !(m is MultiMod))); - testMultiplierTextColour(noFailMod, modSelect.LowMultiplierColour); - testMultiplierTextColour(hiddenMod, modSelect.HighMultiplierColour); + testMultiplierTextColour(noFailMod, () => modSelect.LowMultiplierColour); + testMultiplierTextColour(hiddenMod, () => modSelect.HighMultiplierColour); testUnimplementedMod(spunOutMod); } @@ -106,37 +115,31 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TestManiaMods() { - var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 3); - changeRuleset(ruleset); + changeRuleset(3); - testRankedText(ruleset.CreateInstance().GetModsFor(ModType.Conversion).First(m => m is ManiaModRandom)); + testRankedText(new ManiaRuleset().GetModsFor(ModType.Conversion).First(m => m is ManiaModRandom)); } [Test] public void TestRulesetChanges() { - var rulesetOsu = rulesets.AvailableRulesets.First(r => r.ID == 0); - var rulesetMania = rulesets.AvailableRulesets.First(r => r.ID == 3); + changeRuleset(0); - changeRuleset(null); - - var instance = rulesetOsu.CreateInstance(); - var easierMods = instance.GetModsFor(ModType.DifficultyReduction); - var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); + var noFailMod = new OsuRuleset().GetModsFor(ModType.DifficultyReduction).FirstOrDefault(m => m is OsuModNoFail); AddStep("set mods externally", () => { Mods.Value = new[] { noFailMod }; }); - changeRuleset(rulesetOsu); + changeRuleset(0); AddAssert("ensure mods still selected", () => modDisplay.Current.Value.Single(m => m is OsuModNoFail) != null); - changeRuleset(rulesetMania); + changeRuleset(3); - AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any(m => m is OsuModNoFail)); + AddAssert("ensure mods not selected", () => modDisplay.Current.Value.Count == 0); - changeRuleset(rulesetOsu); + changeRuleset(0); - AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any()); + AddAssert("ensure mods not selected", () => modDisplay.Current.Value.Count == 0); } private void testSingleMod(Mod mod) @@ -198,19 +201,19 @@ namespace osu.Game.Tests.Visual.UserInterface selectNext(mod); AddAssert("check for any selection", () => modSelect.SelectedMods.Value.Any()); - AddStep("deselect all", modSelect.DeselectAllButton.Action.Invoke); + AddStep("deselect all", () => modSelect.DeselectAllButton.Action.Invoke()); AddAssert("check for no selection", () => !modSelect.SelectedMods.Value.Any()); } - private void testMultiplierTextColour(Mod mod, Color4 colour) + private void testMultiplierTextColour(Mod mod, Func getCorrectColour) { - checkLabelColor(Color4.White); + checkLabelColor(() => Color4.White); selectNext(mod); AddWaitStep("wait for changing colour", 1); - checkLabelColor(colour); + checkLabelColor(getCorrectColour); selectPrevious(mod); AddWaitStep("wait for changing colour", 1); - checkLabelColor(Color4.White); + checkLabelColor(() => Color4.White); } private void testRankedText(Mod mod) @@ -235,9 +238,9 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private void changeRuleset(RulesetInfo ruleset) + private void changeRuleset(int? id) { - AddStep($"change ruleset to {ruleset}", () => { Ruleset.Value = ruleset; }); + AddStep($"change ruleset to {(id.ToString() ?? "none")}", () => { Ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(r => r.ID == id); }); waitForLoad(); } @@ -253,7 +256,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private void checkLabelColor(Color4 color) => AddAssert("check label has expected colour", () => modSelect.MultiplierLabel.Colour.AverageColour == color); + private void checkLabelColor(Func getColour) => AddAssert("check label has expected colour", () => modSelect.MultiplierLabel.Colour.AverageColour == getColour()); private class TestModSelectOverlay : ModSelectOverlay { From 34f67b9cadf7a01e8bae1a31dcc8e0b2435ca40f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:31:20 +0900 Subject: [PATCH 4516/5608] 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 252570a150..8b266b08ba 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 a07348b57c..9ec833c9ac 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 544bba3963..1829cbe32a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From f349e7ff78f9f3a7dec1851241c5478209dc8ca2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:35:34 +0900 Subject: [PATCH 4517/5608] Fix non-null ?? usage --- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 5f77116c67..2738b5b8fc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -240,7 +240,7 @@ namespace osu.Game.Tests.Visual.UserInterface private void changeRuleset(int? id) { - AddStep($"change ruleset to {(id.ToString() ?? "none")}", () => { Ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(r => r.ID == id); }); + AddStep($"change ruleset to {(id?.ToString() ?? "none")}", () => { Ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(r => r.ID == id); }); waitForLoad(); } From ea4eb6b2043e6cc9cb63c20a2c3d8461f276d983 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Dec 2019 21:29:10 +0900 Subject: [PATCH 4518/5608] CI cleanups --- .../Beatmaps/Formats/LegacyBeatmapEncoder.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index f367ab3817..e16411f343 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -225,9 +225,9 @@ namespace osu.Game.Beatmaps.Formats LegacyHitObjectType hitObjectType = (LegacyHitObjectType)(comboData.ComboOffset << 4); if (comboData.NewCombo) hitObjectType |= LegacyHitObjectType.NewCombo; - if (hitObject is IHasCurve _) + if (hitObject is IHasCurve) hitObjectType |= LegacyHitObjectType.Slider; - else if (hitObject is IHasEndTime _) + else if (hitObject is IHasEndTime) hitObjectType |= LegacyHitObjectType.Spinner | LegacyHitObjectType.NewCombo; else hitObjectType |= LegacyHitObjectType.Circle; @@ -237,10 +237,9 @@ namespace osu.Game.Beatmaps.Formats writer.Write(FormattableString.Invariant($"{hitObject.StartTime},")); writer.Write(FormattableString.Invariant($"{(int)hitObjectType},")); - if (hitObject is IHasCurve _) - writer.Write(FormattableString.Invariant($"0,")); // A sound type of "none" is written since it's stored per-node - else - writer.Write(FormattableString.Invariant($"{(int)toLegacyHitSoundType(hitObject.Samples)},")); + writer.Write(hitObject is IHasCurve + ? FormattableString.Invariant($"0,") + : FormattableString.Invariant($"{(int)toLegacyHitSoundType(hitObject.Samples)},")); if (hitObject is IHasCurve curveData) { @@ -307,10 +306,9 @@ namespace osu.Game.Beatmaps.Formats else if (hitObject is IHasEndTime endTimeData) writer.Write(FormattableString.Invariant($"{endTimeData.EndTime},")); - if (hitObject is IHasCurve _) - writer.Write(getSampleBank(hitObject.Samples, zeroBanks: true)); // A bank of "none" is written since it's stored per-node - else - writer.Write(getSampleBank(hitObject.Samples)); + writer.Write(hitObject is IHasCurve + ? getSampleBank(hitObject.Samples, zeroBanks: true) + : getSampleBank(hitObject.Samples)); writer.Write(Environment.NewLine); } From 0d49bc244e6972990e83a3b21474e8a1a4af8ad9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Dec 2019 21:30:28 +0900 Subject: [PATCH 4519/5608] Fix test beatmap not being retrievable anymore --- osu.Game.Tests/Resources/TestResources.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index 932021afe5..a57405628a 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Resources public static Stream OpenResource(string name) => GetStore().GetStream($"Resources/{name}"); - public static Stream GetTestBeatmapStream(bool virtualTrack = false) => GetStore().GetStream($"Beatmaps/241526 Soleily - Renatus{(virtualTrack ? "_virtual" : "")}.osz"); + public static Stream GetTestBeatmapStream(bool virtualTrack = false) => new DllResourceStore("osu.Game.Resources.dll").GetStream($"Beatmaps/241526 Soleily - Renatus{(virtualTrack ? "_virtual" : "")}.osz"); public static string GetTestBeatmapForImport(bool virtualTrack = false) { From 440a8470e146276a20899dcb8b8513a02b1fa622 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 18:53:25 +0900 Subject: [PATCH 4520/5608] Move available mods to global context This also tidies up ModSelectOverlay and setting creation flow in general. --- osu.Game/OsuGameBase.cs | 17 ++++++++ osu.Game/Overlays/Mods/ModControlSection.cs | 10 ++--- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 43 ++++++++------------- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 207fb91aab..78a035c5d6 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -83,6 +83,11 @@ namespace osu.Game [Cached(typeof(IBindable>))] protected readonly Bindable> Mods = new Bindable>(Array.Empty()); + ///

+ /// Mods available for the current . + /// + public readonly Bindable>> AvailableMods = new Bindable>>(); + protected Bindable Beatmap { get; private set; } // cached via load() method private Bindable fpsDisplayVisible; @@ -233,6 +238,18 @@ namespace osu.Game PreviewTrackManager previewTrackManager; dependencies.Cache(previewTrackManager = new PreviewTrackManager()); Add(previewTrackManager); + + Ruleset.BindValueChanged(onRulesetChanged); + } + + private void onRulesetChanged(ValueChangedEvent r) + { + var dict = new Dictionary>(); + + foreach (ModType type in Enum.GetValues(typeof(ModType))) dict[type] = r.NewValue?.CreateInstance().GetModsFor(type).ToList(); + + SelectedMods.Value = Array.Empty(); + AvailableMods.Value = dict; } protected virtual Container CreateScalingContainer() => new DrawSizePreservingFillContainer(); diff --git a/osu.Game/Overlays/Mods/ModControlSection.cs b/osu.Game/Overlays/Mods/ModControlSection.cs index f4b588ddb3..10b3bc7c2b 100644 --- a/osu.Game/Overlays/Mods/ModControlSection.cs +++ b/osu.Game/Overlays/Mods/ModControlSection.cs @@ -1,10 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Mods; @@ -12,14 +12,13 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public class ModControlSection : Container + public class ModControlSection : CompositeDrawable { protected FillFlowContainer FlowContent; - protected override Container Content => FlowContent; public readonly Mod Mod; - public ModControlSection(Mod mod) + public ModControlSection(Mod mod, IEnumerable modControls) { Mod = mod; @@ -33,9 +32,8 @@ namespace osu.Game.Overlays.Mods Direction = FillDirection.Vertical, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, + ChildrenEnumerable = modControls }; - - AddRange(Mod.CreateSettingsControls()); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index e8ea43e3f2..247f4a2947 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -20,7 +20,6 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods.Sections; -using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens; using osuTK; @@ -50,7 +49,7 @@ namespace osu.Game.Overlays.Mods protected readonly Bindable> SelectedMods = new Bindable>(Array.Empty()); - protected readonly IBindable Ruleset = new Bindable(); + private Bindable>> availableMods; protected Color4 LowMultiplierColour; protected Color4 HighMultiplierColour; @@ -322,14 +321,14 @@ namespace osu.Game.Overlays.Mods } [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, IBindable ruleset, AudioManager audio, Bindable> mods) + private void load(OsuColour colours, AudioManager audio, Bindable> selectedMods, OsuGameBase osu) { LowMultiplierColour = colours.Red; HighMultiplierColour = colours.Green; UnrankedLabel.Colour = colours.Blue; - Ruleset.BindTo(ruleset); - if (mods != null) SelectedMods.BindTo(mods); + availableMods = osu.AvailableMods.GetBoundCopy(); + SelectedMods.BindTo(selectedMods); sampleOn = audio.Samples.Get(@"UI/check-on"); sampleOff = audio.Samples.Get(@"UI/check-off"); @@ -360,7 +359,7 @@ namespace osu.Game.Overlays.Mods { base.LoadComplete(); - Ruleset.BindValueChanged(rulesetChanged, true); + availableMods.BindValueChanged(availableModsChanged, true); SelectedMods.BindValueChanged(selectedModsChanged, true); } @@ -410,22 +409,12 @@ namespace osu.Game.Overlays.Mods return base.OnKeyDown(e); } - private void rulesetChanged(ValueChangedEvent e) + private void availableModsChanged(ValueChangedEvent>> mods) { - if (e.NewValue == null) return; - - var instance = e.NewValue.CreateInstance(); + if (mods.NewValue == null) return; foreach (var section in ModSectionsContainer.Children) - section.Mods = instance.GetModsFor(section.ModType); - - // attempt to re-select any already selected mods. - // this may be the first time we are receiving the ruleset, in which case they will still match. - selectedModsChanged(new ValueChangedEvent>(SelectedMods.Value, SelectedMods.Value)); - - // write the mods back to the SelectedMods bindable in the case a change was not applicable. - // this generally isn't required as the previous line will perform deselection; just here for safety. - refreshSelectedMods(); + section.Mods = mods.NewValue[section.ModType]; } private void selectedModsChanged(ValueChangedEvent> mods) @@ -462,17 +451,17 @@ namespace osu.Game.Overlays.Mods private void updateModSettings(ValueChangedEvent> selectedMods) { - foreach (var added in selectedMods.NewValue.Except(selectedMods.OldValue)) + ModSettingsContent.Clear(); + + foreach (var mod in selectedMods.NewValue) { - var controls = added.CreateSettingsControls().ToList(); - if (controls.Count > 0) - ModSettingsContent.Add(new ModControlSection(added) { Children = controls }); + var settings = mod.CreateSettingsControls().ToList(); + if (settings.Count > 0) + ModSettingsContent.Add(new ModControlSection(mod, settings)); } - foreach (var removed in selectedMods.OldValue.Except(selectedMods.NewValue)) - ModSettingsContent.RemoveAll(section => section.Mod == removed); + bool hasSettings = ModSettingsContent.Count > 0; - bool hasSettings = ModSettingsContent.Children.Count > 0; CustomiseButton.Enabled.Value = hasSettings; if (!hasSettings) @@ -502,7 +491,7 @@ namespace osu.Game.Overlays.Mods { base.Dispose(isDisposing); - Ruleset.UnbindAll(); + availableMods.UnbindAll(); SelectedMods.UnbindAll(); } From 7fdaf338f3af99870215902b66ff759228d53038 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 17:12:01 +0900 Subject: [PATCH 4521/5608] Fix test logic and add regression test --- .../UserInterface/TestSceneModSettings.cs | 84 ++++++++++++++----- 1 file changed, 62 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index fc44c5f595..8117a4ad78 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs @@ -2,15 +2,20 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; -using osu.Framework.Allocation; +using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; namespace osu.Game.Tests.Visual.UserInterface { @@ -18,28 +23,51 @@ namespace osu.Game.Tests.Visual.UserInterface { private TestModSelectOverlay modSelect; - [BackgroundDependencyLoader] - private void load() + Mod testCustomisableMod = new TestModCustomisable1(); + + [Test] + public void TestButtonShowsOnCustomisableMod() { - Add(modSelect = new TestModSelectOverlay - { - RelativeSizeAxes = Axes.X, - Origin = Anchor.BottomCentre, - Anchor = Anchor.BottomCentre, - }); + createModSelect(); - var testMod = new TestModCustomisable1(); - - AddStep("open", modSelect.Show); + AddStep("open", () => modSelect.Show()); AddAssert("button disabled", () => !modSelect.CustomiseButton.Enabled.Value); AddUntilStep("wait for button load", () => modSelect.ButtonsLoaded); - AddStep("select mod", () => modSelect.SelectMod(testMod)); + AddStep("select mod", () => modSelect.SelectMod(testCustomisableMod)); AddAssert("button enabled", () => modSelect.CustomiseButton.Enabled.Value); AddStep("open Customisation", () => modSelect.CustomiseButton.Click()); - AddStep("deselect mod", () => modSelect.SelectMod(testMod)); + AddStep("deselect mod", () => modSelect.SelectMod(testCustomisableMod)); AddAssert("controls hidden", () => modSelect.ModSettingsContainer.Alpha == 0); } + [Test] + public void TestButtonShowsOnModAlreadyAdded() + { + AddStep("set active mods", () => Mods.Value = new List { testCustomisableMod }); + + createModSelect(); + + AddAssert("mods still active", () => Mods.Value.Count == 1); + + AddStep("open", () => modSelect.Show()); + AddAssert("button enabled", () => modSelect.CustomiseButton.Enabled.Value); + } + + private void createModSelect() + { + AddStep("create mod select", () => + { + Ruleset.Value = new TestRulesetInfo(); + + Child = modSelect = new TestModSelectOverlay + { + RelativeSizeAxes = Axes.X, + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + }; + }); + } + private class TestModSelectOverlay : ModSelectOverlay { public new Container ModSettingsContainer => base.ModSettingsContainer; @@ -50,24 +78,36 @@ namespace osu.Game.Tests.Visual.UserInterface public void SelectMod(Mod mod) => ModSectionsContainer.Children.Single(s => s.ModType == mod.Type) .ButtonsContainer.OfType().Single(b => b.Mods.Any(m => m.GetType() == mod.GetType())).SelectNext(1); + } - protected override void LoadComplete() + public class TestRulesetInfo : RulesetInfo + { + public override Ruleset CreateInstance() => new TestCustomisableModRuleset(); + + public class TestCustomisableModRuleset : Ruleset { - base.LoadComplete(); - - foreach (var section in ModSectionsContainer) + public override IEnumerable GetModsFor(ModType type) { - if (section.ModType == ModType.Conversion) + if (type == ModType.Conversion) { - section.Mods = new Mod[] + return new Mod[] { new TestModCustomisable1(), new TestModCustomisable2() }; } - else - section.Mods = Array.Empty(); + + return Array.Empty(); } + + public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => throw new NotImplementedException(); + + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new NotImplementedException(); + + public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new NotImplementedException(); + + public override string Description { get; } + public override string ShortName { get; } } } From 76aa4f9fb2ecd55d0e209a197d73ad13f5370bbe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 17:36:37 +0900 Subject: [PATCH 4522/5608] Fix code style issues --- osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index 8117a4ad78..d17408ff95 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.UserInterface { private TestModSelectOverlay modSelect; - Mod testCustomisableMod = new TestModCustomisable1(); + private readonly Mod testCustomisableMod = new TestModCustomisable1(); [Test] public void TestButtonShowsOnCustomisableMod() @@ -106,8 +106,8 @@ namespace osu.Game.Tests.Visual.UserInterface public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new NotImplementedException(); - public override string Description { get; } - public override string ShortName { get; } + public override string Description { get; } = "test"; + public override string ShortName { get; } = "tst"; } } From 8052aeb2383da8302aa677782acb4f2457edd200 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 00:23:32 +0900 Subject: [PATCH 4523/5608] Fix potential nullref in disposal logic --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 247f4a2947..7f07ce620c 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -491,8 +491,8 @@ namespace osu.Game.Overlays.Mods { base.Dispose(isDisposing); - availableMods.UnbindAll(); - SelectedMods.UnbindAll(); + availableMods?.UnbindAll(); + SelectedMods?.UnbindAll(); } #endregion From bc311465609b5ee76dff71e4850feaa409863da6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 21:45:38 +0900 Subject: [PATCH 4524/5608] Mods -> SelectedMods --- .../TestSceneAutoJuiceStream.cs | 2 +- .../TestSceneDrawableHitObjects.cs | 2 +- .../TestSceneDrawableHitObjectsHidden.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs | 2 +- .../TestSceneHitCircleHidden.cs | 2 +- .../TestSceneOsuFlashlight.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs | 2 +- .../TestSceneSpinnerHidden.cs | 2 +- .../TestSceneTaikoSuddenDeath.cs | 2 +- .../Visual/Background/TestSceneUserDimBackgrounds.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs | 2 +- .../Visual/Gameplay/TestSceneFailAnimation.cs | 2 +- .../Visual/Gameplay/TestSceneFailJudgement.cs | 2 +- .../Visual/Gameplay/TestSceneGameplayRewinding.cs | 2 +- .../Visual/Gameplay/TestScenePlayerLoader.cs | 6 +++--- .../Visual/SongSelect/TestScenePlaySongSelect.cs | 12 ++++++------ .../UserInterface/TestSceneModSelectOverlay.cs | 2 +- .../Visual/UserInterface/TestSceneModSettings.cs | 6 +++--- osu.Game/OsuGameBase.cs | 2 +- osu.Game/Tests/Visual/AllPlayersTestScene.cs | 2 +- osu.Game/Tests/Visual/OsuTestScene.cs | 6 +++--- osu.Game/Tests/Visual/PlayerTestScene.cs | 4 ++-- 24 files changed, 36 insertions(+), 36 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index ab3c040b4e..74a9c05bf9 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.Tests protected override Player CreatePlayer(Ruleset ruleset) { - Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); + SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); return base.CreatePlayer(ruleset); } } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs index 02a017ce45..1eb913e900 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs @@ -151,7 +151,7 @@ namespace osu.Game.Rulesets.Catch.Tests private void addToPlayfield(DrawableCatchHitObject drawable) { - foreach (var mod in Mods.Value.OfType()) + foreach (var mod in SelectedMods.Value.OfType()) mod.ApplyToDrawableHitObjects(new[] { drawable }); drawableRuleset.Playfield.Add(drawable); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs index 08107e01eb..8c3dfef39c 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Catch.Tests [SetUp] public void SetUp() => Schedule(() => { - Mods.Value = new[] { new CatchModHidden() }; + SelectedMods.Value = new[] { new CatchModHidden() }; }); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs index 64f353c4d9..098e277fff 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Osu.Tests var drawable = CreateDrawableHitCircle(circle, auto); - foreach (var mod in Mods.Value.OfType()) + foreach (var mod in SelectedMods.Value.OfType()) mod.ApplyToDrawableHitObjects(new[] { drawable }); return drawable; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs index eaba82a469..21ebce8c23 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Tests [SetUp] public void SetUp() => Schedule(() => { - Mods.Value = new[] { new OsuModHidden() }; + SelectedMods.Value = new[] { new OsuModHidden() }; }); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs index 64e7632b1b..412effe176 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Osu.Tests { protected override Player CreatePlayer(Ruleset ruleset) { - Mods.Value = new Mod[] { new OsuModAutoplay(), new OsuModFlashlight(), }; + SelectedMods.Value = new Mod[] { new OsuModAutoplay(), new OsuModFlashlight(), }; return base.CreatePlayer(ruleset); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index a9d5c03517..e8386363be 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -362,7 +362,7 @@ namespace osu.Game.Rulesets.Osu.Tests var drawable = CreateDrawableSlider(slider); - foreach (var mod in Mods.Value.OfType()) + foreach (var mod in SelectedMods.Value.OfType()) mod.ApplyToDrawableHitObjects(new[] { drawable }); drawable.OnNewResult += onNewResult; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs index a1795fb877..d0ee1bddb5 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Tests [SetUp] public void SetUp() => Schedule(() => { - Mods.Value = new[] { new OsuModHidden() }; + SelectedMods.Value = new[] { new OsuModHidden() }; }); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs index 3ed3f3e981..f53b64c729 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Tests Depth = depthIndex++ }; - foreach (var mod in Mods.Value.OfType()) + foreach (var mod in SelectedMods.Value.OfType()) mod.ApplyToDrawableHitObjects(new[] { drawable }); Add(drawable); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs index 2976d4fdce..dd863deed2 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Tests [SetUp] public void SetUp() => Schedule(() => { - Mods.Value = new[] { new OsuModHidden() }; + SelectedMods.Value = new[] { new OsuModHidden() }; }); } } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs index d0db193738..140433a523 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Taiko.Tests protected override Player CreatePlayer(Ruleset ruleset) { - Mods.Value = Mods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray(); + SelectedMods.Value = SelectedMods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray(); return new ScoreAccessiblePlayer(); } diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs index 2d2726bbd3..589ec7e8aa 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs @@ -280,7 +280,7 @@ namespace osu.Game.Tests.Visual.Background AddUntilStep("Song select has selection", () => songSelect.Carousel.SelectedBeatmap != null); AddStep("Set default user settings", () => { - Mods.Value = Mods.Value.Concat(new[] { new OsuModNoFail() }).ToArray(); + SelectedMods.Value = SelectedMods.Value.Concat(new[] { new OsuModNoFail() }).ToArray(); songSelect.DimLevel.Value = 0.7f; songSelect.BlurLevel.Value = 0.4f; }); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index 5ee109e3dd..069b965d9b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Player CreatePlayer(Ruleset ruleset) { - Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); + SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); return new ScoreAccessiblePlayer(); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs index f4e8a68819..992c47f856 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Gameplay { protected override Player CreatePlayer(Ruleset ruleset) { - Mods.Value = Array.Empty(); + SelectedMods.Value = Array.Empty(); return new FailPlayer(); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index cca6301b02..1580aac8c5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Gameplay { protected override Player CreatePlayer(Ruleset ruleset) { - Mods.Value = Array.Empty(); + SelectedMods.Value = Array.Empty(); return new FailPlayer(); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index b2b58a63fb..5336c720a1 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -67,7 +67,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Player CreatePlayer(Ruleset ruleset) { - Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); + SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); return new RulesetExposingPlayer(); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index f02361e685..f68f4b8b83 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.Gameplay beforeLoadAction?.Invoke(); Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); - foreach (var mod in Mods.Value.OfType()) + foreach (var mod in SelectedMods.Value.OfType()) mod.ApplyToTrack(Beatmap.Value.Track); InputManager.Child = container = new TestPlayerLoaderContainer( @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestEarlyExit() { - AddStep("load dummy beatmap", () => ResetPlayer(false, () => Mods.Value = new[] { new OsuModNightcore() })); + AddStep("load dummy beatmap", () => ResetPlayer(false, () => SelectedMods.Value = new[] { new OsuModNightcore() })); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddAssert("mod rate applied", () => Beatmap.Value.Track.Rate != 1); AddStep("exit loader", () => loader.Exit()); @@ -123,7 +123,7 @@ namespace osu.Game.Tests.Visual.Gameplay TestMod playerMod1 = null; TestMod playerMod2 = null; - AddStep("load player", () => { ResetPlayer(true, () => Mods.Value = new[] { gameMod = new TestMod() }); }); + AddStep("load player", () => { ResetPlayer(true, () => SelectedMods.Value = new[] { gameMod = new TestMod() }); }); AddUntilStep("wait for loader to become current", () => loader.IsCurrentScreen()); AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 5dd02c1ddd..00fa95bedc 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -256,17 +256,17 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("change ruleset", () => { - Mods.ValueChanged += onModChange; + SelectedMods.ValueChanged += onModChange; songSelect.Ruleset.ValueChanged += onRulesetChange; Ruleset.Value = new TaikoRuleset().RulesetInfo; - Mods.ValueChanged -= onModChange; + SelectedMods.ValueChanged -= onModChange; songSelect.Ruleset.ValueChanged -= onRulesetChange; }); AddAssert("mods changed before ruleset", () => modChangeIndex < rulesetChangeIndex); - AddAssert("empty mods", () => !Mods.Value.Any()); + AddAssert("empty mods", () => !SelectedMods.Value.Any()); void onModChange(ValueChangedEvent> e) => modChangeIndex = actionIndex++; void onRulesetChange(ValueChangedEvent e) => rulesetChangeIndex = actionIndex++; @@ -275,7 +275,7 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestModsRetainedBetweenSongSelect() { - AddAssert("empty mods", () => !Mods.Value.Any()); + AddAssert("empty mods", () => !SelectedMods.Value.Any()); createSongSelect(); @@ -285,7 +285,7 @@ namespace osu.Game.Tests.Visual.SongSelect createSongSelect(); - AddAssert("mods retained", () => Mods.Value.Any()); + AddAssert("mods retained", () => SelectedMods.Value.Any()); } [Test] @@ -332,7 +332,7 @@ namespace osu.Game.Tests.Visual.SongSelect private void checkMusicPlaying(bool playing) => AddUntilStep($"music {(playing ? "" : "not ")}playing", () => music.IsPlaying == playing); - private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => Mods.Value = mods); + private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => SelectedMods.Value = mods); private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id)); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 2738b5b8fc..12ee4ceb2e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -127,7 +127,7 @@ namespace osu.Game.Tests.Visual.UserInterface var noFailMod = new OsuRuleset().GetModsFor(ModType.DifficultyReduction).FirstOrDefault(m => m is OsuModNoFail); - AddStep("set mods externally", () => { Mods.Value = new[] { noFailMod }; }); + AddStep("set mods externally", () => { SelectedMods.Value = new[] { noFailMod }; }); changeRuleset(0); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index d17408ff95..edc749cbaa 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs @@ -43,11 +43,11 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TestButtonShowsOnModAlreadyAdded() { - AddStep("set active mods", () => Mods.Value = new List { testCustomisableMod }); + AddStep("set active mods", () => SelectedMods.Value = new List { testCustomisableMod }); createModSelect(); - AddAssert("mods still active", () => Mods.Value.Count == 1); + AddAssert("mods still active", () => SelectedMods.Value.Count == 1); AddStep("open", () => modSelect.Show()); AddAssert("button enabled", () => modSelect.CustomiseButton.Enabled.Value); @@ -100,7 +100,7 @@ namespace osu.Game.Tests.Visual.UserInterface return Array.Empty(); } - public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => throw new NotImplementedException(); + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => throw new NotImplementedException(); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new NotImplementedException(); diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 78a035c5d6..834a64e597 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -81,7 +81,7 @@ namespace osu.Game // todo: move this to SongSelect once Screen has the ability to unsuspend. [Cached] [Cached(typeof(IBindable>))] - protected readonly Bindable> Mods = new Bindable>(Array.Empty()); + protected readonly Bindable> SelectedMods = new Bindable>(Array.Empty()); /// /// Mods available for the current . diff --git a/osu.Game/Tests/Visual/AllPlayersTestScene.cs b/osu.Game/Tests/Visual/AllPlayersTestScene.cs index b7d1979b0d..dd65c8c382 100644 --- a/osu.Game/Tests/Visual/AllPlayersTestScene.cs +++ b/osu.Game/Tests/Visual/AllPlayersTestScene.cs @@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual var working = CreateWorkingBeatmap(rulesetInfo); Beatmap.Value = working; - Mods.Value = new[] { ruleset.GetAllMods().First(m => m is ModNoFail) }; + SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModNoFail) }; Player?.Exit(); Player = null; diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 4a561f17a3..18dbd212cc 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual protected Bindable Ruleset; - protected Bindable> Mods; + protected Bindable> SelectedMods; protected new OsuScreenDependencies Dependencies { get; private set; } @@ -72,8 +72,8 @@ namespace osu.Game.Tests.Visual Ruleset = Dependencies.Ruleset; Ruleset.SetDefault(); - Mods = Dependencies.Mods; - Mods.SetDefault(); + SelectedMods = Dependencies.Mods; + SelectedMods.SetDefault(); if (!UseOnlineAPI) { diff --git a/osu.Game/Tests/Visual/PlayerTestScene.cs b/osu.Game/Tests/Visual/PlayerTestScene.cs index 2c5a51ca02..3ed65bee61 100644 --- a/osu.Game/Tests/Visual/PlayerTestScene.cs +++ b/osu.Game/Tests/Visual/PlayerTestScene.cs @@ -53,14 +53,14 @@ namespace osu.Game.Tests.Visual { var noFailMod = ruleset.GetAllMods().FirstOrDefault(m => m is ModNoFail); if (noFailMod != null) - Mods.Value = new[] { noFailMod }; + SelectedMods.Value = new[] { noFailMod }; } if (Autoplay) { var mod = ruleset.GetAutoplayMod(); if (mod != null) - Mods.Value = Mods.Value.Concat(mod.Yield()).ToArray(); + SelectedMods.Value = SelectedMods.Value.Concat(mod.Yield()).ToArray(); } Player = CreatePlayer(ruleset); From af1566285698e8341a998d8d2f8bf7dea65697dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Dec 2019 17:45:11 +0900 Subject: [PATCH 4525/5608] Fix WindUp applying too much change --- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 4 +++- osu.Game/Rulesets/Mods/ModWindDown.cs | 8 ++++---- osu.Game/Rulesets/Mods/ModWindUp.cs | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 5276c196f7..4ce364ef1a 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -45,6 +45,8 @@ namespace osu.Game.Rulesets.Mods { this.track = track; track.AddAdjustment(AdjustableProperty.Frequency, SpeedChange); + + FinalRate.TriggerChange(); } public virtual void ApplyToBeatmap(IBeatmap beatmap) @@ -67,6 +69,6 @@ namespace osu.Game.Rulesets.Mods /// /// The amount of adjustment to apply (from 0..1). private void applyAdjustment(double amount) => - SpeedChange.Value = 1 + (Math.Sign(FinalRate.Value) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRate.Value)); + SpeedChange.Value = 1 + (FinalRate.Value - 1) * Math.Clamp(amount, 0, 1); } } diff --git a/osu.Game/Rulesets/Mods/ModWindDown.cs b/osu.Game/Rulesets/Mods/ModWindDown.cs index 680c1a10fb..5416f1ac22 100644 --- a/osu.Game/Rulesets/Mods/ModWindDown.cs +++ b/osu.Game/Rulesets/Mods/ModWindDown.cs @@ -20,10 +20,10 @@ namespace osu.Game.Rulesets.Mods [SettingSource("Final rate", "The speed increase to ramp towards")] public override BindableNumber FinalRate { get; } = new BindableDouble { - MinValue = -0.5, - MaxValue = -0.01, - Default = -0.25, - Value = -0.25, + MinValue = 0.5, + MaxValue = 0.99, + Default = 0.75, + Value = 0.75, Precision = 0.01, }; diff --git a/osu.Game/Rulesets/Mods/ModWindUp.cs b/osu.Game/Rulesets/Mods/ModWindUp.cs index ca9ce0ea3e..3cf584f3dd 100644 --- a/osu.Game/Rulesets/Mods/ModWindUp.cs +++ b/osu.Game/Rulesets/Mods/ModWindUp.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Mods [SettingSource("Final rate", "The speed increase to ramp towards")] public override BindableNumber FinalRate { get; } = new BindableDouble { - MinValue = 0.01, + MinValue = 1.01, MaxValue = 2, Default = 1.5, Value = 1.5, From 72ea871bffd35b6cab8ac8b83a6015e628e22d80 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Dec 2019 23:33:18 +0900 Subject: [PATCH 4526/5608] Make constructor protected --- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 4ce364ef1a..133f9ceb39 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Mods private Track track; - public ModTimeRamp() + protected ModTimeRamp() { // for preview purpose at song select. eventually we'll want to be able to update every frame. FinalRate.BindValueChanged(val => applyAdjustment(1), true); From ef94df917ceb55dd7cdca2ce116495998d36ea7a Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 13 Dec 2019 21:56:03 +0900 Subject: [PATCH 4527/5608] Add whitespace --- osu.Game/OsuGameBase.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 834a64e597..d9b569bf0e 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -246,7 +246,8 @@ namespace osu.Game { var dict = new Dictionary>(); - foreach (ModType type in Enum.GetValues(typeof(ModType))) dict[type] = r.NewValue?.CreateInstance().GetModsFor(type).ToList(); + foreach (ModType type in Enum.GetValues(typeof(ModType))) + dict[type] = r.NewValue?.CreateInstance().GetModsFor(type).ToList(); SelectedMods.Value = Array.Empty(); AvailableMods.Value = dict; From b94d5bf82eba5c96f0303e408caf170885a86c3b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 14 Dec 2019 00:42:31 +0900 Subject: [PATCH 4528/5608] Fix error when entering multiplayer game in different ruleset --- osu.Game/OsuGameBase.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index d9b569bf0e..21cc4eaccc 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -249,7 +249,8 @@ namespace osu.Game foreach (ModType type in Enum.GetValues(typeof(ModType))) dict[type] = r.NewValue?.CreateInstance().GetModsFor(type).ToList(); - SelectedMods.Value = Array.Empty(); + if (!SelectedMods.Disabled) + SelectedMods.Value = Array.Empty(); AvailableMods.Value = dict; } From e05c9426ed56921fc982c10e9cf5d3be169ebc78 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 13 Dec 2019 18:50:49 +0100 Subject: [PATCH 4529/5608] Initial implementation of NewsArticleCover class --- .../Visual/Online/TestSceneNewsOverlay.cs | 38 +++++ osu.Game/Overlays/News/NewsArticleCover.cs | 156 ++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 osu.Game/Overlays/News/NewsArticleCover.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index 98f90f2daa..7903709bd6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -1,6 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Overlays; using osu.Game.Overlays.News; @@ -19,11 +22,46 @@ namespace osu.Game.Tests.Visual.Online AddStep(@"Show front page", () => news.ShowFrontPage()); AddStep(@"Custom article", () => news.Current.Value = "Test Article 101"); + + AddStep(@"Article covers", () => news.LoadAndShowChild(new NewsCoverTest())); } private class TestNewsOverlay : NewsOverlay { public new void LoadAndShowChild(NewsContent content) => base.LoadAndShowChild(content); } + + private class NewsCoverTest : NewsContent + { + public NewsCoverTest() + { + Spacing = new osuTK.Vector2(0, 10); + + var article = new NewsArticleCover.ArticleInfo() + { + Author = "Ephemeral", + CoverURL = "https://assets.ppy.sh/artists/58/header.jpg", + Time = new DateTime(2019, 12, 4), + Title = "New Featured Artist: Kurokotei" + }; + + Children = new Drawable[] + { + new NewsArticleCover(article) + { + Height = 200 + }, + new NewsArticleCover(article) + { + Height = 120 + }, + new NewsArticleCover(article) + { + RelativeSizeAxes = Axes.None, + Size = new osuTK.Vector2(400, 200), + } + }; + } + } } } diff --git a/osu.Game/Overlays/News/NewsArticleCover.cs b/osu.Game/Overlays/News/NewsArticleCover.cs new file mode 100644 index 0000000000..3274cedbac --- /dev/null +++ b/osu.Game/Overlays/News/NewsArticleCover.cs @@ -0,0 +1,156 @@ +using System; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK.Graphics; + +namespace osu.Game.Overlays.News +{ + public class NewsArticleCover : Container + { + public NewsArticleCover(ArticleInfo info) + { + RelativeSizeAxes = Axes.X; + Masking = true; + CornerRadius = 4; + + NewsBackground bg; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(OsuColour.Gray(0.2f), OsuColour.Gray(0.1f)) + }, + new DelayedLoadWrapper(bg = new NewsBackground(info.CoverURL) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fill, + Alpha = 0 + }) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.1f), Color4.Black.Opacity(0.6f)), + Alpha = 1f, + }, + new DateContainer(info.Time) + { + Margin = new MarginPadding() + { + Right = 20, + Top = 20, + } + }, + new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Margin = new MarginPadding() + { + Left = 25, + Bottom = 50, + }, + Font = OsuFont.GetFont(Typeface.Exo, 24, FontWeight.Bold), + Text = info.Title, + }, + new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Margin = new MarginPadding() + { + Left = 25, + Bottom = 30, + }, + Font = OsuFont.GetFont(Typeface.Exo, 16, FontWeight.Bold), + Text = "by " + info.Author + } + }; + + bg.OnLoadComplete += d => d.FadeIn(250, Easing.In); + } + + //news article cover background + [LongRunningLoad] + private class NewsBackground : Sprite + { + private readonly string url; + + public NewsBackground(string coverUrl) + { + url = coverUrl ?? "Headers/news"; + } + + [BackgroundDependencyLoader] + private void load(LargeTextureStore store) + { + Texture = store.Get(url); + } + } + + //date container + private class DateContainer : Container, IHasTooltip + { + private readonly DateTime date; + + public DateContainer(DateTime date) + { + this.date = date; + + Anchor = Anchor.TopRight; + Origin = Anchor.TopRight; + Masking = true; + CornerRadius = 4; + AutoSizeAxes = Axes.Both; + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0.5f), + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(Typeface.Exo, 12, FontWeight.Black, false, false), + Text = date.ToString("dd MMM yyy"), + Margin = new MarginPadding() + { + Vertical = 4, + Horizontal = 8, + } + } + }; + } + + public string TooltipText => date.ToString("dddd dd MMMM yyyy hh:mm:ss UTCz"); + } + + //fake API data struct to use for now as a skeleton for data, as there is no API struct for news article info for now + public class ArticleInfo + { + public string Title { get; set; } + public string CoverURL { get; set; } + public DateTime Time { get; set; } + public string Author { get; set; } + } + } +} From 43720fbf45869a4e22d9ebb1ffebcb7f79e20557 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 13 Dec 2019 18:59:40 +0100 Subject: [PATCH 4530/5608] Fix CI issues --- .../Visual/Online/TestSceneNewsOverlay.cs | 5 ++--- osu.Game/Overlays/News/NewsArticleCover.cs | 17 ++++++++++------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index 7903709bd6..f870a12fc3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Game.Overlays; using osu.Game.Overlays.News; @@ -37,10 +36,10 @@ namespace osu.Game.Tests.Visual.Online { Spacing = new osuTK.Vector2(0, 10); - var article = new NewsArticleCover.ArticleInfo() + var article = new NewsArticleCover.ArticleInfo { Author = "Ephemeral", - CoverURL = "https://assets.ppy.sh/artists/58/header.jpg", + CoverUrl = "https://assets.ppy.sh/artists/58/header.jpg", Time = new DateTime(2019, 12, 4), Title = "New Featured Artist: Kurokotei" }; diff --git a/osu.Game/Overlays/News/NewsArticleCover.cs b/osu.Game/Overlays/News/NewsArticleCover.cs index 3274cedbac..e2485bd170 100644 --- a/osu.Game/Overlays/News/NewsArticleCover.cs +++ b/osu.Game/Overlays/News/NewsArticleCover.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -31,7 +34,7 @@ namespace osu.Game.Overlays.News RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical(OsuColour.Gray(0.2f), OsuColour.Gray(0.1f)) }, - new DelayedLoadWrapper(bg = new NewsBackground(info.CoverURL) + new DelayedLoadWrapper(bg = new NewsBackground(info.CoverUrl) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -52,7 +55,7 @@ namespace osu.Game.Overlays.News }, new DateContainer(info.Time) { - Margin = new MarginPadding() + Margin = new MarginPadding { Right = 20, Top = 20, @@ -62,7 +65,7 @@ namespace osu.Game.Overlays.News { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Margin = new MarginPadding() + Margin = new MarginPadding { Left = 25, Bottom = 50, @@ -74,7 +77,7 @@ namespace osu.Game.Overlays.News { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Margin = new MarginPadding() + Margin = new MarginPadding { Left = 25, Bottom = 30, @@ -132,7 +135,7 @@ namespace osu.Game.Overlays.News Origin = Anchor.Centre, Font = OsuFont.GetFont(Typeface.Exo, 12, FontWeight.Black, false, false), Text = date.ToString("dd MMM yyy"), - Margin = new MarginPadding() + Margin = new MarginPadding { Vertical = 4, Horizontal = 8, @@ -148,7 +151,7 @@ namespace osu.Game.Overlays.News public class ArticleInfo { public string Title { get; set; } - public string CoverURL { get; set; } + public string CoverUrl { get; set; } public DateTime Time { get; set; } public string Author { get; set; } } From ddb2cfc46de5ee7881aaa66c9e752109e935e021 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 14 Dec 2019 18:02:56 +0800 Subject: [PATCH 4531/5608] Use GetEndTime in Taiko and Mania --- osu.Game.Rulesets.Mania/Difficulty/Skills/Individual.cs | 4 ++-- osu.Game.Rulesets.Mania/Difficulty/Skills/Overall.cs | 4 ++-- osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs | 3 +-- osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs | 5 +---- osu.Game/Rulesets/Objects/HitObject.cs | 2 +- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/Skills/Individual.cs b/osu.Game.Rulesets.Mania/Difficulty/Skills/Individual.cs index 059cd39641..4f7ab87fad 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/Skills/Individual.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/Skills/Individual.cs @@ -5,7 +5,7 @@ using System.Linq; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mania.Difficulty.Preprocessing; -using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mania.Difficulty.Skills { @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills protected override double StrainValueOf(DifficultyHitObject current) { var maniaCurrent = (ManiaDifficultyHitObject)current; - var endTime = (maniaCurrent.BaseObject as HoldNote)?.EndTime ?? maniaCurrent.BaseObject.StartTime; + var endTime = maniaCurrent.BaseObject.GetEndTime(); try { diff --git a/osu.Game.Rulesets.Mania/Difficulty/Skills/Overall.cs b/osu.Game.Rulesets.Mania/Difficulty/Skills/Overall.cs index ed25173d38..bbbb93fd8b 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/Skills/Overall.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/Skills/Overall.cs @@ -4,7 +4,7 @@ using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mania.Difficulty.Preprocessing; -using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mania.Difficulty.Skills { @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills protected override double StrainValueOf(DifficultyHitObject current) { var maniaCurrent = (ManiaDifficultyHitObject)current; - var endTime = (maniaCurrent.BaseObject as HoldNote)?.EndTime ?? maniaCurrent.BaseObject.StartTime; + var endTime = maniaCurrent.BaseObject.GetEndTime(); double holdFactor = 1.0; // Factor in case something else is held double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index 6f4fbd0651..c41727557b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -3,7 +3,6 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Scoring; @@ -38,7 +37,7 @@ namespace osu.Game.Rulesets.Taiko.Objects base.CreateNestedHitObjects(); if (IsStrong) - AddNested(new StrongHitObject { StartTime = (this as IHasEndTime)?.EndTime ?? StartTime }); + AddNested(new StrongHitObject { StartTime = this.GetEndTime() }); } public override Judgement CreateJudgement() => new TaikoJudgement(); diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index e61953aeb8..4b234b56d4 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Replays; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Taiko.Beatmaps; @@ -39,9 +38,7 @@ namespace osu.Game.Rulesets.Taiko.Replays for (int i = 0; i < Beatmap.HitObjects.Count; i++) { TaikoHitObject h = Beatmap.HitObjects[i]; - - IHasEndTime endTimeData = h as IHasEndTime; - double endTime = endTimeData?.EndTime ?? h.StartTime; + double endTime = h.GetEndTime(); switch (h) { diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 1179efaa6e..bd96441ebb 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Objects ApplyDefaultsToSelf(controlPointInfo, difficulty); // This is done here since ApplyDefaultsToSelf may be used to determine the end time - SampleControlPoint = controlPointInfo.SamplePointAt(((this as IHasEndTime)?.EndTime ?? StartTime) + control_point_leniency); + SampleControlPoint = controlPointInfo.SamplePointAt(this.GetEndTime() + control_point_leniency); nestedHitObjects.Clear(); From 489d9dc7b5d1f56ca7429774fe44970106a0aed8 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sat, 14 Dec 2019 18:33:56 +0800 Subject: [PATCH 4532/5608] Switch Expandtarget and "cursormiddle" --- osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs index 02152fa51e..e96bd29ad5 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -28,18 +28,18 @@ namespace osu.Game.Rulesets.Osu.Skinning InternalChildren = new[] { + ExpandTarget = new NonPlayfieldSprite + { + Texture = skin.GetTexture("cursor"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, new NonPlayfieldSprite { Texture = skin.GetTexture("cursormiddle"), Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - ExpandTarget = new NonPlayfieldSprite - { - Texture = skin.GetTexture("cursor"), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } }; } From 41d4609c9238e26b8f4fb73a68bb381eff1cf04e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 15 Dec 2019 02:36:49 +0900 Subject: [PATCH 4533/5608] Fix crash on trying to retrieve mods from unavailable ruleset --- osu.Game/OsuGameBase.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 21cc4eaccc..22b8d9d012 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -246,8 +246,11 @@ namespace osu.Game { var dict = new Dictionary>(); - foreach (ModType type in Enum.GetValues(typeof(ModType))) - dict[type] = r.NewValue?.CreateInstance().GetModsFor(type).ToList(); + if (r.NewValue?.Available == true) + { + foreach (ModType type in Enum.GetValues(typeof(ModType))) + dict[type] = r.NewValue.CreateInstance().GetModsFor(type).ToList(); + } if (!SelectedMods.Disabled) SelectedMods.Value = Array.Empty(); From 244eb56455d5bbb7deb1afecdbbd6013f913294e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 15 Dec 2019 03:01:37 +0900 Subject: [PATCH 4534/5608] Fix test ruleset availability --- osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index edc749cbaa..8dcb7dcbf8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs @@ -84,6 +84,11 @@ namespace osu.Game.Tests.Visual.UserInterface { public override Ruleset CreateInstance() => new TestCustomisableModRuleset(); + public TestRulesetInfo() + { + Available = true; + } + public class TestCustomisableModRuleset : Ruleset { public override IEnumerable GetModsFor(ModType type) From 91bb851a7dbc1db8f470be81a7bd4506d9f45a17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 15 Dec 2019 03:32:50 +0900 Subject: [PATCH 4535/5608] 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 8b266b08ba..239e1c2d31 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 9ec833c9ac..56d65830f9 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 1829cbe32a..a90e90db19 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From a04f4b76bb93f9a94d06724cf803ac6a0b835a43 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 13 Dec 2019 22:27:14 -0800 Subject: [PATCH 4536/5608] Allow changing volume using alt when hovering scroll containers --- osu.Game/Graphics/Containers/OsuScrollContainer.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Graphics/Containers/OsuScrollContainer.cs b/osu.Game/Graphics/Containers/OsuScrollContainer.cs index 2721ce55dc..df4c3a3324 100644 --- a/osu.Game/Graphics/Containers/OsuScrollContainer.cs +++ b/osu.Game/Graphics/Containers/OsuScrollContainer.cs @@ -83,6 +83,13 @@ namespace osu.Game.Graphics.Containers return base.OnDragEnd(e); } + protected override bool OnScroll(ScrollEvent e) + { + if (e.AltPressed) return false; + + return base.OnScroll(e); + } + protected override ScrollbarContainer CreateScrollbar(Direction direction) => new OsuScrollbar(direction); protected class OsuScrollbar : ScrollbarContainer From 5af363c92043d81c86d5254e07ac986c06a4d5ad Mon Sep 17 00:00:00 2001 From: Joehu Date: Sat, 14 Dec 2019 12:58:13 -0800 Subject: [PATCH 4537/5608] Use default placeholder text on chat channel search box --- osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs index 505d2d6f89..25a9a51638 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs @@ -115,11 +115,7 @@ namespace osu.Game.Overlays.Chat.Selection Font = OsuFont.GetFont(size: 20), Shadow = false, }, - search = new HeaderSearchTextBox - { - RelativeSizeAxes = Axes.X, - PlaceholderText = @"Search", - }, + search = new HeaderSearchTextBox { RelativeSizeAxes = Axes.X }, }, }, }, From 01c036b0b0c88421a639d9e3d92c7f6b006b421c Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 Dec 2019 16:56:02 +0800 Subject: [PATCH 4538/5608] implement backing beats for nightcore mods --- .../Mods/CatchModNightcore.cs | 3 +- .../Mods/ManiaModNightcore.cs | 3 +- osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs | 3 +- .../Mods/TaikoModNightcore.cs | 3 +- osu.Game/Rulesets/Mods/ModNightcore.cs | 57 ++++++++++++++++++- 5 files changed, 64 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs b/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs index da2edcee44..c07087efaf 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Mods { - public class CatchModNightcore : ModNightcore + public class CatchModNightcore : ModNightcore { public override double ScoreMultiplier => 1.06; } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs index 2d94fb6af5..4cc712060c 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModNightcore : ModNightcore + public class ManiaModNightcore : ModNightcore { public override double ScoreMultiplier => 1; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs b/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs index 5668c17792..7780e23a26 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs @@ -2,10 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModNightcore : ModNightcore + public class OsuModNightcore : ModNightcore { public override double ScoreMultiplier => 1.12; } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs index e45081b6d6..5377eb1072 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs @@ -2,10 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Mods { - public class TaikoModNightcore : ModNightcore + public class TaikoModNightcore : ModNightcore { public override double ScoreMultiplier => 1.12; } diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index c14e02e64d..22d8d4ba66 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -1,15 +1,28 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Game.Audio; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.UI; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Mods { - public abstract class ModNightcore : ModDoubleTime + public abstract class ModNightcore : ModDoubleTime, IApplicableToDrawableRuleset + where TObject : HitObject { public override string Name => "Nightcore"; public override string Acronym => "NC"; @@ -34,5 +47,47 @@ namespace osu.Game.Rulesets.Mods track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust); track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust); } + + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) + { + drawableRuleset.Overlays.Add(new NightcoreBeatContainer()); + } + + public class NightcoreBeatContainer : BeatSyncedContainer + { + private SkinnableSound hatSample; + private SkinnableSound clapSample; + private SkinnableSound kickSample; + private SkinnableSound finishSample; + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + InternalChildren = new Drawable[] + { + hatSample = new SkinnableSound(new SampleInfo("nightcore-hat")), + clapSample = new SkinnableSound(new SampleInfo("nightcore-clap")), + kickSample = new SkinnableSound(new SampleInfo("nightcore-kick")), + finishSample = new SkinnableSound(new SampleInfo("nightcore-finish")), + }; + } + + protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) + { + base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); + + if (beatIndex > -1) + { + if (beatIndex % 16 == 0) + finishSample?.Play(); + else if (beatIndex % 2 == 0) + kickSample?.Play(); + else if (beatIndex % 2 == 1) + clapSample?.Play(); + else + hatSample?.Play(); + } + } + } } } From 6da168118e84965914bfec15bfae2794676c4470 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 Dec 2019 17:02:29 +0800 Subject: [PATCH 4539/5608] remove unused usings --- osu.Game/Rulesets/Mods/ModNightcore.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 22d8d4ba66..97d96bbca2 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -1,17 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Audio; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; From 154bc57c6e62136b49f4560af8614fe5889a7d9e Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 Dec 2019 17:46:44 +0800 Subject: [PATCH 4540/5608] remove unused dependency --- osu.Game/Rulesets/Mods/ModNightcore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 97d96bbca2..3a67fedd4d 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Mods private SkinnableSound finishSample; [BackgroundDependencyLoader] - private void load(AudioManager audio) + private void load() { InternalChildren = new Drawable[] { From c06e558f874fe975502894658617d00214731777 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 Dec 2019 18:12:37 +0800 Subject: [PATCH 4541/5608] add setting to start fully wounded --- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 133f9ceb39..d21990ae91 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -23,6 +23,9 @@ namespace osu.Game.Rulesets.Mods [SettingSource("Final rate", "The final speed to ramp to")] public abstract BindableNumber FinalRate { get; } + [SettingSource("Start wounded", "Start at 100% of the final rate")] + public BindableBool Reverse { get; } = new BindableBool(); + private double finalRateTime; private double beginRampTime; @@ -61,7 +64,10 @@ namespace osu.Game.Rulesets.Mods public virtual void Update(Playfield playfield) { - applyAdjustment((track.CurrentTime - beginRampTime) / finalRateTime); + if (!Reverse.Value) + applyAdjustment((track.CurrentTime - beginRampTime) / finalRateTime); + else + applyAdjustment(1 - ((track.CurrentTime - beginRampTime) / finalRateTime)); } /// From ad077042ba61a9e4fa297e0c9f5e971f3047008c Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Sun, 15 Dec 2019 02:18:12 -0800 Subject: [PATCH 4542/5608] Created ContextMenu for scores by adding OsuContextMenuContainer as a child of LeaderboardScore and a Drawable that extended the IHasContextMenu interface to the MenuContainer. Tried to the LeaderboardScore extend IHASContextMenu itself, but it is not working yet. --- .../Online/Leaderboards/LeaderboardScore.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 6ac5219282..c4bc306f05 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -11,10 +11,13 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Users.Drawables; @@ -227,9 +230,28 @@ namespace osu.Game.Online.Leaderboards }, }; + Add( + new OsuContextMenuContainer + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { + new ContextMenuArea{ + RelativeSizeAxes = Axes.Both + } + } + } + ); + innerAvatar.OnLoadComplete += d => d.FadeInFromZero(200); } + private class ContextMenuArea : Drawable, IHasContextMenu + { + public MenuItem[] ContextMenuItems => new MenuItem[] + { + new OsuMenuItem("Delete", MenuItemType.Destructive), + }; + } public override void Show() { foreach (var d in new[] { avatar, nameLabel, scoreLabel, scoreRank, flagBadgeContainer, modsContainer }.Concat(statisticsLabels)) From 19a3c959923328c8b91e4653ee003b101f60c770 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 14 Dec 2019 21:27:26 +0800 Subject: [PATCH 4543/5608] Update InspectCode to 2019.3 --- build/InspectCode.cake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/InspectCode.cake b/build/InspectCode.cake index bd3fdf5f93..06c56dce87 100644 --- a/build/InspectCode.cake +++ b/build/InspectCode.cake @@ -1,5 +1,5 @@ #addin "nuget:?package=CodeFileSanity&version=0.0.33" -#addin "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2019.2.1" +#addin "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2019.3.0" #tool "nuget:?package=NVika.MSBuild&version=1.0.1" var nVikaToolPath = GetFiles("./tools/NVika.MSBuild.*/tools/NVika.exe").First(); From ab70abe8bd2b577c049cad84283f0b74e1dcbc60 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 14 Dec 2019 21:28:13 +0800 Subject: [PATCH 4544/5608] Turn off unexpected new warnings. --- osu.Game/Screens/Select/BeatmapCarousel.cs | 4 ++++ osu.sln.DotSettings | 1 + 2 files changed, 5 insertions(+) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index ec524043ee..4acc619753 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -587,13 +587,16 @@ namespace osu.Game.Screens.Select switch (d) { case DrawableCarouselBeatmapSet set: + { lastSet = set; set.MoveToX(set.Item.State.Value == CarouselItemState.Selected ? -100 : 0, 500, Easing.OutExpo); set.MoveToY(currentY, 750, Easing.OutExpo); break; + } case DrawableCarouselBeatmap beatmap: + { if (beatmap.Item.State.Value == CarouselItemState.Selected) scrollTarget = currentY + beatmap.DrawHeight / 2 - DrawHeight / 2; @@ -619,6 +622,7 @@ namespace osu.Game.Screens.Select } break; + } } } diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 9b400de390..105d22fe3e 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -215,6 +215,7 @@ HINT HINT HINT + HINT DO_NOT_SHOW WARNING WARNING From 8b570233495c2c654b9493bb7d6415580c4c8174 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 14 Dec 2019 20:22:39 +0800 Subject: [PATCH 4545/5608] Require 3.1.100 SDK in global.json --- global.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/global.json b/global.json index 43bb34912a..6858d4044d 100644 --- a/global.json +++ b/global.json @@ -1,4 +1,9 @@ { + "sdk": { + "allowPrerelease": false, + "rollForward": "minor", + "version": "3.1.100" + }, "msbuild-sdks": { "Microsoft.Build.Traversal": "2.0.24" } From cea3a66d4a0f9e235aa7d5e3966281507229cfc1 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 14 Dec 2019 20:26:28 +0800 Subject: [PATCH 4546/5608] Use static local method fixed for roslyn 3.4 --- .../Visual/Online/TestSceneBeatmapSetOverlayDetails.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs index 2a45e68c0a..96c0c59695 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("set second set", () => details.BeatmapSet = secondSet); AddAssert("ratings set", () => details.Ratings.Metrics == secondSet.Metrics); - BeatmapSetInfo createSet() => new BeatmapSetInfo + static BeatmapSetInfo createSet() => new BeatmapSetInfo { Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).Select(_ => RNG.Next(10)).ToArray() }, Beatmaps = new List From c457571da6d69f41ac7722bda6532fa99722c611 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 14 Dec 2019 20:54:22 +0800 Subject: [PATCH 4547/5608] Use index and range expressions --- .editorconfig | 4 ++-- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs | 6 +++--- .../Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs | 2 +- osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs | 8 ++++---- .../Visual/UserInterface/TestSceneBeatSyncedContainer.cs | 4 ++-- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 4 ++-- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 2 +- .../Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 4 ++-- osu.Game/Rulesets/Objects/SliderPath.cs | 6 +++--- osu.sln.DotSettings | 2 +- 12 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.editorconfig b/.editorconfig index b5333ad8e7..8cdb92d11c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -176,8 +176,8 @@ dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent #Style - C# 8 features csharp_prefer_static_local_function = true:warning csharp_prefer_simple_using_statement = true:silent -csharp_style_prefer_index_operator = false:none -csharp_style_prefer_range_operator = false:none +csharp_style_prefer_index_operator = true:warning +csharp_style_prefer_range_operator = true:warning csharp_style_prefer_switch_expression = false:none #Supressing roslyn built-in analyzers diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 9069c09ae4..6e4491de94 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps prevNoteTimes.RemoveAt(0); prevNoteTimes.Add(newNoteTime); - density = (prevNoteTimes[prevNoteTimes.Count - 1] - prevNoteTimes[0]) / prevNoteTimes.Count; + density = (prevNoteTimes[^1] - prevNoteTimes[0]) / prevNoteTimes.Count; } private double lastTime; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index 5f75cbabec..b6fc9821a4 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -286,11 +286,11 @@ namespace osu.Game.Rulesets.Osu.Tests private bool assertGreatJudge() => judgementResults.Last().Type == HitResult.Great; - private bool assertHeadMissTailTracked() => judgementResults[judgementResults.Count - 2].Type == HitResult.Great && judgementResults.First().Type == HitResult.Miss; + private bool assertHeadMissTailTracked() => judgementResults[^2].Type == HitResult.Great && judgementResults.First().Type == HitResult.Miss; - private bool assertMidSliderJudgements() => judgementResults[judgementResults.Count - 2].Type == HitResult.Great; + private bool assertMidSliderJudgements() => judgementResults[^2].Type == HitResult.Great; - private bool assertMidSliderJudgementFail() => judgementResults[judgementResults.Count - 2].Type == HitResult.Miss; + private bool assertMidSliderJudgementFail() => judgementResults[^2].Type == HitResult.Miss; private ScoreAccessibleReplayPlayer currentPlayer; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 9b820261ab..2497e428fc 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders protected override bool OnDoubleClick(DoubleClickEvent e) { // Todo: This should all not occur on double click, but rather if the previous control point is hovered. - segmentStart = HitObject.Path.ControlPoints[HitObject.Path.ControlPoints.Count - 1]; + segmentStart = HitObject.Path.ControlPoints[^1]; segmentStart.Type.Value = PathType.Linear; currentSegmentLength = 1; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index bd59e8a03f..2686ba4fd2 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -156,9 +156,9 @@ namespace osu.Game.Rulesets.Osu.Replays // TODO: Shouldn't the spinner always spin in the same direction? if (h is Spinner) { - calcSpinnerStartPosAndDirection(((OsuReplayFrame)Frames[Frames.Count - 1]).Position, out startPosition, out spinnerDirection); + calcSpinnerStartPosAndDirection(((OsuReplayFrame)Frames[^1]).Position, out startPosition, out spinnerDirection); - Vector2 spinCentreOffset = SPINNER_CENTRE - ((OsuReplayFrame)Frames[Frames.Count - 1]).Position; + Vector2 spinCentreOffset = SPINNER_CENTRE - ((OsuReplayFrame)Frames[^1]).Position; if (spinCentreOffset.Length > SPIN_RADIUS) { @@ -230,7 +230,7 @@ namespace osu.Game.Rulesets.Osu.Replays private void moveToHitObject(OsuHitObject h, Vector2 targetPos, Easing easing) { - OsuReplayFrame lastFrame = (OsuReplayFrame)Frames[Frames.Count - 1]; + OsuReplayFrame lastFrame = (OsuReplayFrame)Frames[^1]; // Wait until Auto could "see and react" to the next note. double waitTime = h.StartTime - Math.Max(0.0, h.TimePreempt - reactionTime); @@ -363,7 +363,7 @@ namespace osu.Game.Rulesets.Osu.Replays } // We only want to let go of our button if we are at the end of the current replay. Otherwise something is still going on after us so we need to keep the button pressed! - if (Frames[Frames.Count - 1].Time <= endFrame.Time) + if (Frames[^1].Time <= endFrame.Time) AddFrameToReplay(endFrame); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index ed44d82bce..b0b673d6a4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -157,7 +157,7 @@ namespace osu.Game.Tests.Visual.UserInterface private TimingControlPoint getNextTimingPoint(TimingControlPoint current) { - if (timingPoints[timingPoints.Count - 1] == current) + if (timingPoints[^1] == current) return current; int index = timingPoints.IndexOf(current); // -1 means that this is a "default beat" @@ -169,7 +169,7 @@ namespace osu.Game.Tests.Visual.UserInterface { if (timingPoints.Count == 0) return 0; - if (timingPoints[timingPoints.Count - 1] == current) + if (timingPoints[^1] == current) return (int)Math.Ceiling((Beatmap.Value.Track.Length - current.Time) / current.BeatLength); return (int)Math.Ceiling((getNextTimingPoint(current).Time - current.Time) / current.BeatLength); diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index ce2783004c..03496952e7 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -195,8 +195,8 @@ namespace osu.Game.Beatmaps.ControlPoints if (time < list[0].Time) return null; - if (time >= list[list.Count - 1].Time) - return list[list.Count - 1]; + if (time >= list[^1].Time) + return list[^1]; int l = 0; int r = list.Count - 2; diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 2b914669cb..e401e3fb97 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -34,7 +34,7 @@ namespace osu.Game.Beatmaps.Formats if (line.StartsWith(@"[", StringComparison.Ordinal) && line.EndsWith(@"]", StringComparison.Ordinal)) { - if (!Enum.TryParse(line.Substring(1, line.Length - 2), out section)) + if (!Enum.TryParse(line[1..^1], out section)) { Logger.Log($"Unknown section \"{line}\" in \"{output}\""); section = Section.None; diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 2bbac92f7f..9735f6373d 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -37,7 +37,7 @@ namespace osu.Game.Graphics.Containers foreach (var link in links) { - AddText(text.Substring(previousLinkEnd, link.Index - previousLinkEnd)); + AddText(text[previousLinkEnd..link.Index]); AddLink(text.Substring(link.Index, link.Length), link.Action, link.Argument ?? link.Url); previousLinkEnd = link.Index + link.Length; } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index b5b1e26486..7fddb442d1 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -184,7 +184,7 @@ namespace osu.Game.Rulesets.Objects.Legacy result = CreateSlider(pos, combo, comboOffset, convertControlPoints(points, pathType), length, repeatCount, nodeSamples); // The samples are played when the slider ends, which is the last node - result.Samples = nodeSamples[nodeSamples.Count - 1]; + result.Samples = nodeSamples[^1]; } else if (type.HasFlag(ConvertHitObjectType.Spinner)) { @@ -279,7 +279,7 @@ namespace osu.Game.Rulesets.Objects.Legacy { if (vertices[i] == vertices[i - 1]) { - points[points.Count - 1].Type.Value = type; + points[^1].Type.Value = type; continue; } diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 86deba3b93..293138097f 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Objects get { ensureValid(); - return cumulativeLength.Count == 0 ? 0 : cumulativeLength[cumulativeLength.Count - 1]; + return cumulativeLength.Count == 0 ? 0 : cumulativeLength[^1]; } } @@ -251,7 +251,7 @@ namespace osu.Game.Rulesets.Objects if (calculatedLength > expectedDistance) { // The path will be shortened further, in which case we should trim any more unnecessary lengths and their associated path segments - while (cumulativeLength.Count > 0 && cumulativeLength[cumulativeLength.Count - 1] >= expectedDistance) + while (cumulativeLength.Count > 0 && cumulativeLength[^1] >= expectedDistance) { cumulativeLength.RemoveAt(cumulativeLength.Count - 1); calculatedPath.RemoveAt(pathEndIndex--); @@ -269,7 +269,7 @@ namespace osu.Game.Rulesets.Objects // The direction of the segment to shorten or lengthen Vector2 dir = (calculatedPath[pathEndIndex] - calculatedPath[pathEndIndex - 1]).Normalized(); - calculatedPath[pathEndIndex] = calculatedPath[pathEndIndex - 1] + dir * (float)(expectedDistance - cumulativeLength[cumulativeLength.Count - 1]); + calculatedPath[pathEndIndex] = calculatedPath[pathEndIndex - 1] + dir * (float)(expectedDistance - cumulativeLength[^1]); cumulativeLength.Add(expectedDistance); } } diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 105d22fe3e..12571be31d 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -220,7 +220,7 @@ WARNING WARNING WARNING - DO_NOT_SHOW + WARNING WARNING True From 0e658790c141bd28eaa7a62d4b41b2f6b0231e5c Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Sun, 15 Dec 2019 22:42:44 +0700 Subject: [PATCH 4548/5608] Add function to assert multiplier value instead of hardcoded string --- .../TestSceneFooterButtonMods.cs | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs index e8d3475a11..6eb621ca3b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Mods; @@ -28,33 +29,46 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TestIncrementMultiplier() { - AddStep(@"Add Hidden", () => changeMods(new Mod[] { new OsuModHidden() })); - AddAssert(@"Check Hidden multiplier", () => footerButtonMods.MultiplierText.Text == @"1.06x"); - AddStep(@"Add HardRock", () => changeMods(new Mod[] { new OsuModHidden() })); - AddAssert(@"Check HardRock multiplier", () => footerButtonMods.MultiplierText.Text == @"1.06x"); - AddStep(@"Add DoubleTime", () => changeMods(new Mod[] { new OsuModDoubleTime() })); - AddAssert(@"Check DoubleTime multiplier", () => footerButtonMods.MultiplierText.Text == @"1.12x"); - AddStep(@"Add multiple Mods", () => changeMods(new Mod[] { new OsuModDoubleTime(), new OsuModHidden(), new OsuModHidden() })); - AddAssert(@"Check multiple mod multiplier", () => footerButtonMods.MultiplierText.Text == @"1.26x"); + var hiddenMod = new Mod[] { new OsuModHidden() }; + AddStep(@"Add Hidden", () => changeMods(hiddenMod)); + AddAssert(@"Check Hidden multiplier", () => assertModsMultiplier(hiddenMod)); + + var hardRockMod = new Mod[] { new OsuModHardRock() }; + AddStep(@"Add HardRock", () => changeMods(hardRockMod)); + AddAssert(@"Check HardRock multiplier", () => assertModsMultiplier(hardRockMod)); + + var doubleTimeMod = new Mod[] { new OsuModDoubleTime() }; + AddStep(@"Add DoubleTime", () => changeMods(doubleTimeMod)); + AddAssert(@"Check DoubleTime multiplier", () => assertModsMultiplier(doubleTimeMod)); + + var mutlipleIncrementMods = new Mod[] { new OsuModDoubleTime(), new OsuModHidden(), new OsuModHardRock() }; + AddStep(@"Add multiple Mods", () => changeMods(mutlipleIncrementMods)); + AddAssert(@"Check multiple mod multiplier", () => assertModsMultiplier(mutlipleIncrementMods)); } [Test] public void TestDecrementMultiplier() { - AddStep(@"Add Easy", () => changeMods(new Mod[] { new OsuModEasy() })); - AddAssert(@"Check Easy multiplier", () => footerButtonMods.MultiplierText.Text == @"0.50x"); - AddStep(@"Add NoFail", () => changeMods(new Mod[] { new OsuModNoFail() })); - AddAssert(@"Check NoFail multiplier", () => footerButtonMods.MultiplierText.Text == @"0.50x"); - AddStep(@"Add Multiple Mods", () => changeMods(new Mod[] { new OsuModEasy(), new OsuModNoFail() })); - AddAssert(@"Check multiple mod multiplier", () => footerButtonMods.MultiplierText.Text == @"0.25x"); + var easyMod = new Mod[] { new OsuModEasy() }; + AddStep(@"Add Easy", () => changeMods(easyMod)); + AddAssert(@"Check Easy multiplier", () => assertModsMultiplier(easyMod)); + + var noFailMod = new Mod[] { new OsuModNoFail() }; + AddStep(@"Add NoFail", () => changeMods(noFailMod)); + AddAssert(@"Check NoFail multiplier", () => assertModsMultiplier(noFailMod)); + + var multipleDecrementMods = new Mod[] { new OsuModEasy(), new OsuModNoFail() }; + AddStep(@"Add Multiple Mods", () => changeMods(multipleDecrementMods)); + AddAssert(@"Check multiple mod multiplier", () => assertModsMultiplier(multipleDecrementMods)); } [Test] public void TestClearMultiplier() { - AddStep(@"Add mods", () => changeMods(new Mod[] { new OsuModDoubleTime(), new OsuModFlashlight() })); + var multipleMods = new Mod[] { new OsuModDoubleTime(), new OsuModFlashlight() }; + AddStep(@"Add mods", () => changeMods(multipleMods)); AddStep(@"Clear selected mod", () => changeMods(Array.Empty())); - AddAssert(@"Check empty multiplier", () => string.IsNullOrEmpty(footerButtonMods.MultiplierText.Text)); + AddAssert(@"Check empty multiplier", () => assertModsMultiplier(Array.Empty())); } private void changeMods(IReadOnlyList mods) @@ -62,6 +76,14 @@ namespace osu.Game.Tests.Visual.UserInterface footerButtonMods.Current.Value = mods; } + private bool assertModsMultiplier(IEnumerable mods) + { + var multiplier = mods.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier); + var expectedValue = multiplier.Equals(1.0) ? string.Empty : $"{multiplier:N2}x"; + + return expectedValue == footerButtonMods.MultiplierText.Text; + } + private class TestFooterButtonMods : FooterButtonMods { public new OsuSpriteText MultiplierText => base.MultiplierText; From 88d3a1707d0b2d3893e497d4eb319d31a845d2d9 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 Dec 2019 06:35:18 +0800 Subject: [PATCH 4549/5608] ensure beatIndex is 0 before starting beats --- osu.Game/Rulesets/Mods/ModNightcore.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 3a67fedd4d..1374c385cc 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -55,6 +55,7 @@ namespace osu.Game.Rulesets.Mods private SkinnableSound clapSample; private SkinnableSound kickSample; private SkinnableSound finishSample; + private bool started; [BackgroundDependencyLoader] private void load() @@ -72,7 +73,10 @@ namespace osu.Game.Rulesets.Mods { base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); - if (beatIndex > -1) + if (!started && beatIndex == 0) + started = true; + + if (started && beatIndex > -1) { if (beatIndex % 16 == 0) finishSample?.Play(); From 9062fe1935b114fd214b5d84f9319fbdb7cd2053 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Dec 2019 13:32:53 +0900 Subject: [PATCH 4550/5608] Fix crashes on custom skins due to extension-less file lookups --- osu.Game/Skinning/LegacySkinResourceStore.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Skinning/LegacySkinResourceStore.cs b/osu.Game/Skinning/LegacySkinResourceStore.cs index 72f3b9ed78..7c799d9c89 100644 --- a/osu.Game/Skinning/LegacySkinResourceStore.cs +++ b/osu.Game/Skinning/LegacySkinResourceStore.cs @@ -22,10 +22,8 @@ namespace osu.Game.Skinning if (source.Files == null) return null; - bool hasExtension = filename.Contains('.'); - var file = source.Files.Find(f => - string.Equals(hasExtension ? f.Filename : Path.ChangeExtension(f.Filename, null), filename, StringComparison.InvariantCultureIgnoreCase)); + string.Equals(f.Filename, filename, StringComparison.InvariantCultureIgnoreCase)); return file?.FileInfo.StoragePath; } From befb78f83b890f847b16cbcd2c52310bc7d15975 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Dec 2019 14:01:08 +0900 Subject: [PATCH 4551/5608] Simplify LegacySkinResourceStore by deriving from ResourceStore --- osu.Game/Skinning/LegacySkinResourceStore.cs | 60 ++++---------------- 1 file changed, 12 insertions(+), 48 deletions(-) diff --git a/osu.Game/Skinning/LegacySkinResourceStore.cs b/osu.Game/Skinning/LegacySkinResourceStore.cs index 7c799d9c89..79a4e2e932 100644 --- a/osu.Game/Skinning/LegacySkinResourceStore.cs +++ b/osu.Game/Skinning/LegacySkinResourceStore.cs @@ -3,75 +3,39 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Threading.Tasks; using osu.Framework.IO.Stores; using osu.Game.Database; namespace osu.Game.Skinning { - public class LegacySkinResourceStore : IResourceStore + public class LegacySkinResourceStore : ResourceStore where T : INamedFileInfo { private readonly IHasFiles source; - private readonly IResourceStore underlyingStore; - - private string getPathForFile(string filename) - { - if (source.Files == null) - return null; - - var file = source.Files.Find(f => - string.Equals(f.Filename, filename, StringComparison.InvariantCultureIgnoreCase)); - return file?.FileInfo.StoragePath; - } public LegacySkinResourceStore(IHasFiles source, IResourceStore underlyingStore) + : base(underlyingStore) { this.source = source; - this.underlyingStore = underlyingStore; } - public Stream GetStream(string name) + protected override IEnumerable GetFilenames(string name) { - string path = getPathForFile(name); - return path == null ? null : underlyingStore.GetStream(path); - } + if (source.Files == null) + yield break; - public IEnumerable GetAvailableResources() => source.Files.Select(f => f.Filename); - - byte[] IResourceStore.Get(string name) => GetAsync(name).Result; - - public Task GetAsync(string name) - { - string path = getPathForFile(name); - return path == null ? Task.FromResult(null) : underlyingStore.GetAsync(path); - } - - #region IDisposable Support - - private bool isDisposed; - - protected virtual void Dispose(bool disposing) - { - if (!isDisposed) + foreach (var filename in base.GetFilenames(name)) { - isDisposed = true; + var path = getPathForFile(filename); + if (path != null) + yield return path; } } - ~LegacySkinResourceStore() - { - Dispose(false); - } + private string getPathForFile(string filename) => + source.Files.Find(f => string.Equals(f.Filename, filename, StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath; - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - #endregion + public override IEnumerable GetAvailableResources() => source.Files.Select(f => f.Filename); } } From db3dc4f3755e7254c4c039ea48f23c7a2edb1bb7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 15:15:26 +0900 Subject: [PATCH 4552/5608] Optimise cursortrail with custom vertex logic --- .../UI/Cursor/CursorTrail.cs | 70 +++++++++++-------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 80291c002e..4d6db83d7a 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -174,7 +174,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private void addPart(Vector2 screenSpacePosition) { parts[currentIndex].Position = screenSpacePosition; - parts[currentIndex].Time = time; + parts[currentIndex].Time = time + 1; ++parts[currentIndex].InvalidationID; currentIndex = (currentIndex + 1) % max_sprites; @@ -201,7 +201,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly TrailPart[] parts = new TrailPart[max_sprites]; private Vector2 size; - private readonly TrailBatch vertexBatch = new TrailBatch(max_sprites, 1); + private readonly QuadBatch vertexBatch = new QuadBatch(max_sprites, 1); public TrailDrawNode(CursorTrail source) : base(source) @@ -227,23 +227,50 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor shader.Bind(); shader.GetUniform("g_FadeClock").UpdateValue(ref time); - for (int i = 0; i < parts.Length; ++i) + RectangleF textureRect = texture.GetTextureRect(); + + foreach (var part in parts) { - if (parts[i].InvalidationID == -1) + if (part.InvalidationID == -1) continue; - vertexBatch.DrawTime = parts[i].Time; + if (time - part.Time >= 1) + continue; - Vector2 pos = parts[i].Position; + vertexBatch.Add(new TexturedTrailVertex + { + Position = new Vector2(part.Position.X - size.X / 2, part.Position.Y + size.Y / 2), + TexturePosition = textureRect.BottomLeft, + Colour = DrawColourInfo.Colour.BottomLeft.Linear, + Time = part.Time + }); - DrawQuad( - texture, - new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y), - DrawColourInfo.Colour, - null, - vertexBatch.AddAction); + vertexBatch.Add(new TexturedTrailVertex + { + Position = new Vector2(part.Position.X + size.X / 2, part.Position.Y + size.Y / 2), + TexturePosition = textureRect.BottomRight, + Colour = DrawColourInfo.Colour.BottomRight.Linear, + Time = part.Time + }); + + vertexBatch.Add(new TexturedTrailVertex + { + Position = new Vector2(part.Position.X + size.X / 2, part.Position.Y - size.Y / 2), + TexturePosition = textureRect.TopRight, + Colour = DrawColourInfo.Colour.TopRight.Linear, + Time = part.Time + }); + + vertexBatch.Add(new TexturedTrailVertex + { + Position = new Vector2(part.Position.X - size.X / 2, part.Position.Y - size.Y / 2), + TexturePosition = textureRect.TopLeft, + Colour = DrawColourInfo.Colour.TopLeft.Linear, + Time = part.Time + }); } + vertexBatch.Draw(); shader.Unbind(); } @@ -253,25 +280,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor vertexBatch.Dispose(); } - - // Todo: This shouldn't exist, but is currently used to reduce allocations by caching variable-capturing closures. - private class TrailBatch : QuadBatch - { - public new readonly Action AddAction; - public float DrawTime; - - public TrailBatch(int size, int maxBuffers) - : base(size, maxBuffers) - { - AddAction = v => Add(new TexturedTrailVertex - { - Position = v.Position, - TexturePosition = v.TexturePosition, - Time = DrawTime + 1, - Colour = v.Colour, - }); - } - } } [StructLayout(LayoutKind.Sequential)] From a554ca728bf0b8e4f7db9034e08a908c7c549dc5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 15:27:54 +0900 Subject: [PATCH 4553/5608] Don't reuse the same control point references --- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index d5d99640af..a4ed966abb 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -128,7 +128,7 @@ namespace osu.Game.Rulesets.Catch.Objects if (value != null) { - path.ControlPoints.AddRange(value.ControlPoints); + path.ControlPoints.AddRange(value.ControlPoints.Select(c => new PathControlPoint(c.Position.Value, c.Type.Value))); path.ExpectedDistance.Value = value.ExpectedDistance.Value; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 34e5a7f3cd..fe65ab78d1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Objects if (value != null) { - path.ControlPoints.AddRange(value.ControlPoints); + path.ControlPoints.AddRange(value.ControlPoints.Select(c => new PathControlPoint(c.Position.Value, c.Type.Value))); path.ExpectedDistance.Value = value.ExpectedDistance.Value; } } From fef1877095ff240dbb65bb6d020cc376d965e482 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2019 07:36:30 +0000 Subject: [PATCH 4554/5608] Bump ppy.osu.Game.Resources from 2019.1010.0 to 2019.1215.0 Bumps [ppy.osu.Game.Resources](https://github.com/ppy/osu-resources) from 2019.1010.0 to 2019.1215.0. - [Release notes](https://github.com/ppy/osu-resources/releases) - [Commits](https://github.com/ppy/osu-resources/compare/2019.1010.0...2019.1215.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 239e1c2d31..abb3cc8244 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -53,7 +53,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 56d65830f9..e5f34b1c7e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -22,7 +22,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index a90e90db19..c84e617285 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,7 +73,7 @@ - + From 58e3fb0d0fbd506aa4e2bc8342d503f60a7a6a54 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 16:43:20 +0900 Subject: [PATCH 4555/5608] Coalesce to -1 --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index e16411f343..4280112967 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -112,7 +112,7 @@ namespace osu.Game.Beatmaps.Formats writer.WriteLine(FormattableString.Invariant($"Source: {beatmap.Metadata.Source}")); writer.WriteLine(FormattableString.Invariant($"Tags: {beatmap.Metadata.Tags}")); writer.WriteLine(FormattableString.Invariant($"BeatmapID: {beatmap.BeatmapInfo.OnlineBeatmapID ?? 0}")); - writer.WriteLine(FormattableString.Invariant($"BeatmapSetID: {beatmap.BeatmapInfo.BeatmapSet.OnlineBeatmapSetID ?? 0}")); + writer.WriteLine(FormattableString.Invariant($"BeatmapSetID: {beatmap.BeatmapInfo.BeatmapSet.OnlineBeatmapSetID ?? -1}")); } private void handleDifficulty(TextWriter writer) From 596fda3c1fd0f1844842a721453e0980d64fcfa6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 16:57:40 +0900 Subject: [PATCH 4556/5608] Refactor switch --- .../Beatmaps/Formats/LegacyBeatmapEncoder.cs | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 4280112967..efe20e8d34 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -191,26 +191,27 @@ namespace osu.Game.Beatmaps.Formats writer.WriteLine("[HitObjects]"); - foreach (var h in beatmap.HitObjects) + switch (beatmap.BeatmapInfo.RulesetID) { - switch (beatmap.BeatmapInfo.RulesetID) - { - case 0: + case 0: + foreach (var h in beatmap.HitObjects) handleOsuHitObject(writer, h); - break; + break; - case 1: + case 1: + foreach (var h in beatmap.HitObjects) handleTaikoHitObject(writer, h); - break; + break; - case 2: + case 2: + foreach (var h in beatmap.HitObjects) handleCatchHitObject(writer, h); - break; + break; - case 3: + case 3: + foreach (var h in beatmap.HitObjects) handleManiaHitObject(writer, h); - break; - } + break; } } From d56e99865cdc859be192c547e895e2792b03c9e1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 16:57:49 +0900 Subject: [PATCH 4557/5608] Throw not implemented exceptions --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index efe20e8d34..e600dc06b7 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -314,17 +314,11 @@ namespace osu.Game.Beatmaps.Formats writer.Write(Environment.NewLine); } - private void handleTaikoHitObject(TextWriter writer, HitObject hitObject) - { - } + private void handleTaikoHitObject(TextWriter writer, HitObject hitObject) => throw new NotImplementedException(); - private void handleCatchHitObject(TextWriter writer, HitObject hitObject) - { - } + private void handleCatchHitObject(TextWriter writer, HitObject hitObject) => throw new NotImplementedException(); - private void handleManiaHitObject(TextWriter writer, HitObject hitObject) - { - } + private void handleManiaHitObject(TextWriter writer, HitObject hitObject) => throw new NotImplementedException(); private string getSampleBank(IList samples, bool banksOnly = false, bool zeroBanks = false) { From 98dd1c2590796010060759b17cd1a444ab3f60b2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 17:03:58 +0900 Subject: [PATCH 4558/5608] Use SingleOrDefault() where possible --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index e600dc06b7..5c8d128d5a 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -322,13 +322,13 @@ namespace osu.Game.Beatmaps.Formats private string getSampleBank(IList samples, bool banksOnly = false, bool zeroBanks = false) { - LegacySampleBank normalBank = toLegacySampleBank(samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL)?.Bank); + LegacySampleBank normalBank = toLegacySampleBank(samples.SingleOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL)?.Bank); LegacySampleBank addBank = toLegacySampleBank(samples.FirstOrDefault(s => !string.IsNullOrEmpty(s.Name) && s.Name != HitSampleInfo.HIT_NORMAL)?.Bank); string customSampleBank = toLegacyCustomSampleBank(samples.FirstOrDefault()?.Suffix); string sampleFilename = samples.FirstOrDefault(s => string.IsNullOrEmpty(s.Name))?.LookupNames.First() ?? string.Empty; - int volume = samples.First().Volume; + int volume = samples.FirstOrDefault()?.Volume ?? 100; StringBuilder sb = new StringBuilder(); From 9fa6954ac2f139171ec33b5b887b25eb4cb20d14 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 17:05:24 +0900 Subject: [PATCH 4559/5608] Refactor getSampleBank a bit --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 5c8d128d5a..9e643857f1 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -325,11 +325,6 @@ namespace osu.Game.Beatmaps.Formats LegacySampleBank normalBank = toLegacySampleBank(samples.SingleOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL)?.Bank); LegacySampleBank addBank = toLegacySampleBank(samples.FirstOrDefault(s => !string.IsNullOrEmpty(s.Name) && s.Name != HitSampleInfo.HIT_NORMAL)?.Bank); - string customSampleBank = toLegacyCustomSampleBank(samples.FirstOrDefault()?.Suffix); - string sampleFilename = samples.FirstOrDefault(s => string.IsNullOrEmpty(s.Name))?.LookupNames.First() ?? string.Empty; - - int volume = samples.FirstOrDefault()?.Volume ?? 100; - StringBuilder sb = new StringBuilder(); sb.Append(FormattableString.Invariant($"{(zeroBanks ? 0 : (int)normalBank)}:")); @@ -337,6 +332,10 @@ namespace osu.Game.Beatmaps.Formats if (!banksOnly) { + string customSampleBank = toLegacyCustomSampleBank(samples.FirstOrDefault()?.Suffix); + string sampleFilename = samples.FirstOrDefault(s => string.IsNullOrEmpty(s.Name))?.LookupNames.First() ?? string.Empty; + int volume = samples.FirstOrDefault()?.Volume ?? 100; + sb.Append(":"); sb.Append(FormattableString.Invariant($"{customSampleBank}:")); sb.Append(FormattableString.Invariant($"{volume}:")); From 27150d6bbc484c14fd1466e3751c64149c35c53a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 17:06:52 +0900 Subject: [PATCH 4560/5608] Use char concatenation for performance --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 9e643857f1..65edd356d7 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -63,11 +63,11 @@ namespace osu.Game.Beatmaps.Formats writer.WriteLine(FormattableString.Invariant($"AudioLeadIn: {beatmap.BeatmapInfo.AudioLeadIn}")); writer.WriteLine(FormattableString.Invariant($"PreviewTime: {beatmap.Metadata.PreviewTime}")); // Todo: Not all countdown types are supported by lazer yet - writer.WriteLine(FormattableString.Invariant($"Countdown: {(beatmap.BeatmapInfo.Countdown ? "1" : "0")}")); + writer.WriteLine(FormattableString.Invariant($"Countdown: {(beatmap.BeatmapInfo.Countdown ? '1' : '0')}")); writer.WriteLine(FormattableString.Invariant($"SampleSet: {toLegacySampleBank(beatmap.ControlPointInfo.SamplePoints[0].SampleBank)}")); writer.WriteLine(FormattableString.Invariant($"StackLeniency: {beatmap.BeatmapInfo.StackLeniency}")); writer.WriteLine(FormattableString.Invariant($"Mode: {beatmap.BeatmapInfo.RulesetID}")); - writer.WriteLine(FormattableString.Invariant($"LetterboxInBreaks: {(beatmap.BeatmapInfo.LetterboxInBreaks ? "1" : "0")}")); + writer.WriteLine(FormattableString.Invariant($"LetterboxInBreaks: {(beatmap.BeatmapInfo.LetterboxInBreaks ? '1' : '0')}")); // if (beatmap.BeatmapInfo.UseSkinSprites) // writer.WriteLine(@"UseSkinSprites: 1"); // if (b.AlwaysShowPlayfield) @@ -81,8 +81,8 @@ namespace osu.Game.Beatmaps.Formats // if (b.CountdownOffset > 0) // writer.WriteLine(@"CountdownOffset: " + b.CountdownOffset.ToString()); if (beatmap.BeatmapInfo.RulesetID == 3) - writer.WriteLine(FormattableString.Invariant($"SpecialStyle: {(beatmap.BeatmapInfo.SpecialStyle ? "1" : "0")}")); - writer.WriteLine(FormattableString.Invariant($"WidescreenStoryboard: {(beatmap.BeatmapInfo.WidescreenStoryboard ? "1" : "0")}")); + writer.WriteLine(FormattableString.Invariant($"SpecialStyle: {(beatmap.BeatmapInfo.SpecialStyle ? '1' : '0')}")); + writer.WriteLine(FormattableString.Invariant($"WidescreenStoryboard: {(beatmap.BeatmapInfo.WidescreenStoryboard ? '1' : '0')}")); // if (b.SamplesMatchPlaybackRate) // writer.WriteLine(@"SamplesMatchPlaybackRate: 1"); } @@ -178,7 +178,7 @@ namespace osu.Game.Beatmaps.Formats writer.Write(FormattableString.Invariant($"{(int)toLegacySampleBank(tempHitSample.Bank)},")); writer.Write(FormattableString.Invariant($"{toLegacyCustomSampleBank(tempHitSample.Suffix)},")); writer.Write(FormattableString.Invariant($"{tempHitSample.Volume},")); - writer.Write(FormattableString.Invariant($"{(timingPoint != null ? "1" : "0")},")); + writer.Write(FormattableString.Invariant($"{(timingPoint != null ? '1' : '0')},")); writer.Write(FormattableString.Invariant($"{(int)effectFlags}")); writer.Write("\n"); } From 5278236458c82cd6b0a0be6a207dbc3ce689af88 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 17:07:30 +0900 Subject: [PATCH 4561/5608] Use invariant ToLower() --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 65edd356d7..d55adfa756 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -372,7 +372,7 @@ namespace osu.Game.Beatmaps.Formats private LegacySampleBank toLegacySampleBank(string sampleBank) { - switch (sampleBank?.ToLower()) + switch (sampleBank?.ToLowerInvariant()) { case "normal": return LegacySampleBank.Normal; From 3c9884456f0111afb9e71c3ebeeb0860aaa31fae Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 17:08:46 +0900 Subject: [PATCH 4562/5608] Use writeline --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index d55adfa756..139be3ce2f 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -180,7 +180,7 @@ namespace osu.Game.Beatmaps.Formats writer.Write(FormattableString.Invariant($"{tempHitSample.Volume},")); writer.Write(FormattableString.Invariant($"{(timingPoint != null ? '1' : '0')},")); writer.Write(FormattableString.Invariant($"{(int)effectFlags}")); - writer.Write("\n"); + writer.WriteLine(); } } @@ -311,7 +311,7 @@ namespace osu.Game.Beatmaps.Formats ? getSampleBank(hitObject.Samples, zeroBanks: true) : getSampleBank(hitObject.Samples)); - writer.Write(Environment.NewLine); + writer.WriteLine(); } private void handleTaikoHitObject(TextWriter writer, HitObject hitObject) => throw new NotImplementedException(); From be7b00cc34e64d66b69550f0496f4c948dc62d5d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 17:12:31 +0900 Subject: [PATCH 4563/5608] Fix potentially incorrect custom sample bank --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 139be3ce2f..d38ff482ad 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -332,7 +332,7 @@ namespace osu.Game.Beatmaps.Formats if (!banksOnly) { - string customSampleBank = toLegacyCustomSampleBank(samples.FirstOrDefault()?.Suffix); + string customSampleBank = toLegacyCustomSampleBank(samples.FirstOrDefault(s => !string.IsNullOrEmpty(s.Name))?.Suffix); string sampleFilename = samples.FirstOrDefault(s => string.IsNullOrEmpty(s.Name))?.LookupNames.First() ?? string.Empty; int volume = samples.FirstOrDefault()?.Volume ?? 100; From add04e98e18d734e84fd88a1aad35fe71a5c90ba Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 18:10:44 +0900 Subject: [PATCH 4564/5608] Fix cursortrail texture not being bound --- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 4d6db83d7a..4e86662ec6 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -227,6 +227,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor shader.Bind(); shader.GetUniform("g_FadeClock").UpdateValue(ref time); + texture.TextureGL.Bind(); + RectangleF textureRect = texture.GetTextureRect(); foreach (var part in parts) From 9de6b62fb136e7b7705858970b3b15c818e353de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Dec 2019 18:24:29 +0900 Subject: [PATCH 4565/5608] Fix nightcore beat not playing if song doesn't hit beat index 0 --- osu.Game/Rulesets/Mods/ModNightcore.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 1374c385cc..4d11b9de1d 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; @@ -55,7 +56,8 @@ namespace osu.Game.Rulesets.Mods private SkinnableSound clapSample; private SkinnableSound kickSample; private SkinnableSound finishSample; - private bool started; + + private int? firstBeat; [BackgroundDependencyLoader] private void load() @@ -73,10 +75,10 @@ namespace osu.Game.Rulesets.Mods { base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); - if (!started && beatIndex == 0) - started = true; + if (beatIndex < firstBeat || !firstBeat.HasValue) + firstBeat = Math.Max(0, beatIndex / 16 * 16); - if (started && beatIndex > -1) + if (beatIndex > firstBeat) { if (beatIndex % 16 == 0) finishSample?.Play(); From 83f77d9c3510cd4c68f1574c2a90993d04932779 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 18:41:02 +0900 Subject: [PATCH 4566/5608] Make the layout faster --- osu.Game/Screens/Play/HUDOverlay.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index dc32fc7cd5..840c1d37e3 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Play { public class HUDOverlay : Container { - private const int fade_duration = 400; + private const float fade_duration = 400; private const Easing fade_easing = Easing.Out; public readonly KeyCounterDisplay KeyCounter; @@ -103,8 +103,8 @@ namespace osu.Game.Screens.Play Origin = Anchor.BottomRight, Position = -new Vector2(5, TwoLayerButton.SIZE_RETRACTED.Y), AutoSizeAxes = Axes.Both, - AutoSizeDuration = fade_duration, - AutoSizeEasing = fade_easing, + LayoutDuration = fade_duration / 2, + LayoutEasing = fade_easing, Direction = FillDirection.Vertical, Children = new Drawable[] { From a276643a4bcc8a2a6d376ec43fee0ce816cddea2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Dec 2019 18:41:14 +0900 Subject: [PATCH 4567/5608] Reorder health display and score elements --- osu.Game/Screens/Play/HUDOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 840c1d37e3..e2f362780d 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -78,6 +78,7 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, Children = new Drawable[] { + HealthDisplay = CreateHealthDisplay(), topScoreContainer = new Container { Anchor = Anchor.TopCentre, @@ -90,7 +91,6 @@ namespace osu.Game.Screens.Play ComboCounter = CreateComboCounter(), }, }, - HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), ModDisplay = CreateModsContainer(), HitErrorDisplay = CreateHitErrorDisplayOverlay(), From 3e0fda58ea59e10d6fac5ce75d70afc769478bd1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Dec 2019 18:47:06 +0900 Subject: [PATCH 4568/5608] Play finish in addition to kick, not isolated --- osu.Game/Rulesets/Mods/ModNightcore.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 4d11b9de1d..f4599ed88a 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -82,7 +82,8 @@ namespace osu.Game.Rulesets.Mods { if (beatIndex % 16 == 0) finishSample?.Play(); - else if (beatIndex % 2 == 0) + + if (beatIndex % 2 == 0) kickSample?.Play(); else if (beatIndex % 2 == 1) clapSample?.Play(); From c883c97bab8e81a3bd67db0ef5d4c7110b5d3161 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Dec 2019 18:50:58 +0900 Subject: [PATCH 4569/5608] Fix off-by-one starting bar --- osu.Game/Rulesets/Mods/ModNightcore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index f4599ed88a..1c46b82f79 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Mods base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); if (beatIndex < firstBeat || !firstBeat.HasValue) - firstBeat = Math.Max(0, beatIndex / 16 * 16); + firstBeat = Math.Max(0, (beatIndex / 16 + 1) * 16); if (beatIndex > firstBeat) { From 0f9ff32cdc8ee2528024e2c8a3dbf545af5916d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Dec 2019 18:51:22 +0900 Subject: [PATCH 4570/5608] Fix beat playing while paused --- osu.Game/Graphics/Containers/BeatSyncedContainer.cs | 8 ++++++++ osu.Game/Rulesets/Mods/ModNightcore.cs | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 2e76ab964f..1374b34aca 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -42,6 +42,8 @@ namespace osu.Game.Graphics.Containers private EffectControlPoint defaultEffect; private TrackAmplitudes defaultAmplitudes; + protected bool IsBeatSyncedWithTrack { get; private set; } + protected override void Update() { Track track = null; @@ -65,10 +67,16 @@ namespace osu.Game.Graphics.Containers effectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTrackTime); if (timingPoint.BeatLength == 0) + { + IsBeatSyncedWithTrack = false; return; + } + + IsBeatSyncedWithTrack = true; } else { + IsBeatSyncedWithTrack = false; currentTrackTime = Clock.CurrentTime; timingPoint = defaultTiming; effectPoint = defaultEffect; diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 1c46b82f79..f1f25f70e6 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -75,7 +75,13 @@ namespace osu.Game.Rulesets.Mods { base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); - if (beatIndex < firstBeat || !firstBeat.HasValue) + if (!IsBeatSyncedWithTrack) + { + firstBeat = null; + return; + } + + if (!firstBeat.HasValue || beatIndex < firstBeat) firstBeat = Math.Max(0, (beatIndex / 16 + 1) * 16); if (beatIndex > firstBeat) From 210fecc95188b72cfc1d988fc48936872161ccf8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Dec 2019 18:57:11 +0900 Subject: [PATCH 4571/5608] Fix incorrect hat logic; add support for first barline omission --- osu.Game/Rulesets/Mods/ModNightcore.cs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index f1f25f70e6..830cb87822 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -84,17 +84,25 @@ namespace osu.Game.Rulesets.Mods if (!firstBeat.HasValue || beatIndex < firstBeat) firstBeat = Math.Max(0, (beatIndex / 16 + 1) * 16); - if (beatIndex > firstBeat) + if (beatIndex >= firstBeat) { - if (beatIndex % 16 == 0) + if (beatIndex % 16 == 0 && (beatIndex > firstBeat || !effectPoint.OmitFirstBarLine)) finishSample?.Play(); - if (beatIndex % 2 == 0) - kickSample?.Play(); - else if (beatIndex % 2 == 1) - clapSample?.Play(); - else - hatSample?.Play(); + switch (beatIndex % (int)timingPoint.TimeSignature) + { + case 0: + kickSample?.Play(); + break; + + case 2: + clapSample?.Play(); + break; + + default: + hatSample?.Play(); + break; + } } } } From 72404bff9a7d24466bdc5ef761b44de981f119b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Dec 2019 19:16:54 +0900 Subject: [PATCH 4572/5608] Add support for simple triple time --- .../Containers/BeatSyncedContainer.cs | 15 +++-- osu.Game/Rulesets/Mods/ModNightcore.cs | 55 +++++++++++++++---- 2 files changed, 56 insertions(+), 14 deletions(-) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 1374b34aca..a68e536a18 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -33,6 +33,11 @@ namespace osu.Game.Graphics.Containers /// public double TimeSinceLastBeat { get; private set; } + /// + /// How many baets per beatlength to trigger. Defaults to 1. + /// + public int Divisor { get; set; } = 1; + /// /// Default length of a beat in milliseconds. Used whenever there is no beatmap or track playing. /// @@ -82,17 +87,19 @@ namespace osu.Game.Graphics.Containers effectPoint = defaultEffect; } - int beatIndex = (int)((currentTrackTime - timingPoint.Time) / timingPoint.BeatLength); + double beatLength = timingPoint.BeatLength / Divisor; + + int beatIndex = (int)((currentTrackTime - timingPoint.Time) / beatLength); // The beats before the start of the first control point are off by 1, this should do the trick if (currentTrackTime < timingPoint.Time) beatIndex--; - TimeUntilNextBeat = (timingPoint.Time - currentTrackTime) % timingPoint.BeatLength; + TimeUntilNextBeat = (timingPoint.Time - currentTrackTime) % beatLength; if (TimeUntilNextBeat < 0) - TimeUntilNextBeat += timingPoint.BeatLength; + TimeUntilNextBeat += beatLength; - TimeSinceLastBeat = timingPoint.BeatLength - TimeUntilNextBeat; + TimeSinceLastBeat = beatLength - TimeUntilNextBeat; if (timingPoint.Equals(lastTimingPoint) && beatIndex == lastBeat) return; diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 830cb87822..16ed3a5e31 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Audio; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Beatmaps.Timing; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Rulesets.Objects; @@ -59,6 +60,11 @@ namespace osu.Game.Rulesets.Mods private int? firstBeat; + public NightcoreBeatContainer() + { + Divisor = 2; + } + [BackgroundDependencyLoader] private void load() { @@ -71,10 +77,15 @@ namespace osu.Game.Rulesets.Mods }; } + private const int segment_bar_length = 4; + protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) { base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); + int beatsPerBar = (int)timingPoint.TimeSignature; + int segmentLength = beatsPerBar * Divisor * segment_bar_length; + if (!IsBeatSyncedWithTrack) { firstBeat = null; @@ -82,25 +93,49 @@ namespace osu.Game.Rulesets.Mods } if (!firstBeat.HasValue || beatIndex < firstBeat) - firstBeat = Math.Max(0, (beatIndex / 16 + 1) * 16); + firstBeat = Math.Max(0, (beatIndex / segmentLength + 1) * segmentLength); if (beatIndex >= firstBeat) { - if (beatIndex % 16 == 0 && (beatIndex > firstBeat || !effectPoint.OmitFirstBarLine)) + if (beatIndex % segmentLength == 0 && (beatIndex > firstBeat || !effectPoint.OmitFirstBarLine)) finishSample?.Play(); - switch (beatIndex % (int)timingPoint.TimeSignature) + switch (timingPoint.TimeSignature) { - case 0: - kickSample?.Play(); + case TimeSignatures.SimpleTriple: + switch (beatIndex % 6) + { + case 0: + kickSample?.Play(); + break; + + case 3: + clapSample?.Play(); + break; + + default: + hatSample?.Play(); + break; + } + break; - case 2: - clapSample?.Play(); - break; + case TimeSignatures.SimpleQuadruple: + switch (beatIndex % 4) + { + case 0: + kickSample?.Play(); + break; + + case 2: + clapSample?.Play(); + break; + + default: + hatSample?.Play(); + break; + } - default: - hatSample?.Play(); break; } } From cfd811112061663c00edf15096273da32a1f5102 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Dec 2019 19:40:43 +0900 Subject: [PATCH 4573/5608] Better initial beat handling --- osu.Game/Rulesets/Mods/ModNightcore.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 16ed3a5e31..abbeca3150 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.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 osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; @@ -93,7 +92,7 @@ namespace osu.Game.Rulesets.Mods } if (!firstBeat.HasValue || beatIndex < firstBeat) - firstBeat = Math.Max(0, (beatIndex / segmentLength + 1) * segmentLength); + firstBeat = beatIndex < 0 ? 0 : (beatIndex / segmentLength + 1) * segmentLength; if (beatIndex >= firstBeat) { From 7d979e12649ef7ea4346a7c535ebd2ace3202f14 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Dec 2019 19:41:04 +0900 Subject: [PATCH 4574/5608] Add finalised test scene --- .../TestSceneNightcoreBeatContainer.cs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs new file mode 100644 index 0000000000..3473b03eaf --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs @@ -0,0 +1,38 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Game.Beatmaps.Timing; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu; +using osu.Game.Tests.Visual.UserInterface; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestSceneNightcoreBeatContainer : TestSceneBeatSyncedContainer + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ModNightcore<>) + }; + + protected override void LoadComplete() + { + base.LoadComplete(); + + Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + + Beatmap.Value.Track.Start(); + Beatmap.Value.Track.Seek(Beatmap.Value.Beatmap.HitObjects.First().StartTime - 1000); + + Add(new ModNightcore.NightcoreBeatContainer()); + + AddStep("change signature to quadruple", () => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints.ForEach(p => p.TimeSignature = TimeSignatures.SimpleQuadruple)); + AddStep("change signature to triple", () => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints.ForEach(p => p.TimeSignature = TimeSignatures.SimpleTriple)); + } + } +} From 438d97f4f56ac84058745dafd809b5fa9198ab18 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Dec 2019 19:42:28 +0900 Subject: [PATCH 4575/5608] Rename variable for clarity --- osu.Game/Rulesets/Mods/ModNightcore.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index abbeca3150..16902cc792 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -76,14 +76,14 @@ namespace osu.Game.Rulesets.Mods }; } - private const int segment_bar_length = 4; + private const int bars_per_segment = 4; protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) { base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes); int beatsPerBar = (int)timingPoint.TimeSignature; - int segmentLength = beatsPerBar * Divisor * segment_bar_length; + int segmentLength = beatsPerBar * Divisor * bars_per_segment; if (!IsBeatSyncedWithTrack) { From 795416c066437f9b5f1cc44898c68c429b2059ea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Dec 2019 12:06:09 +0900 Subject: [PATCH 4576/5608] Move first beat offset to BeatSyncedContainer --- osu.Game/Graphics/Containers/BeatSyncedContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index a68e536a18..b04d01004a 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -89,7 +89,7 @@ namespace osu.Game.Graphics.Containers double beatLength = timingPoint.BeatLength / Divisor; - int beatIndex = (int)((currentTrackTime - timingPoint.Time) / beatLength); + int beatIndex = (int)((currentTrackTime - timingPoint.Time) / beatLength) - (effectPoint.OmitFirstBarLine ? 1 : 0); // The beats before the start of the first control point are off by 1, this should do the trick if (currentTrackTime < timingPoint.Time) From 87035f8251965b81d5a5ecb572a6fd803fd97837 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Dec 2019 12:12:15 +0900 Subject: [PATCH 4577/5608] Simplify complex method --- osu.Game/Rulesets/Mods/ModNightcore.cs | 72 ++++++++++++++------------ 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 16902cc792..a8c79bb896 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -92,51 +92,55 @@ namespace osu.Game.Rulesets.Mods } if (!firstBeat.HasValue || beatIndex < firstBeat) + // decide on a good starting beat index if once has not yet been decided. firstBeat = beatIndex < 0 ? 0 : (beatIndex / segmentLength + 1) * segmentLength; if (beatIndex >= firstBeat) + playBeatFor(beatIndex % segmentLength, timingPoint.TimeSignature); + } + + private void playBeatFor(int beatIndex, TimeSignatures signature) + { + if (beatIndex == 0) + finishSample?.Play(); + + switch (signature) { - if (beatIndex % segmentLength == 0 && (beatIndex > firstBeat || !effectPoint.OmitFirstBarLine)) - finishSample?.Play(); + case TimeSignatures.SimpleTriple: + switch (beatIndex % 6) + { + case 0: + kickSample?.Play(); + break; - switch (timingPoint.TimeSignature) - { - case TimeSignatures.SimpleTriple: - switch (beatIndex % 6) - { - case 0: - kickSample?.Play(); - break; + case 3: + clapSample?.Play(); + break; - case 3: - clapSample?.Play(); - break; + default: + hatSample?.Play(); + break; + } - default: - hatSample?.Play(); - break; - } + break; - break; + case TimeSignatures.SimpleQuadruple: + switch (beatIndex % 4) + { + case 0: + kickSample?.Play(); + break; - case TimeSignatures.SimpleQuadruple: - switch (beatIndex % 4) - { - case 0: - kickSample?.Play(); - break; + case 2: + clapSample?.Play(); + break; - case 2: - clapSample?.Play(); - break; + default: + hatSample?.Play(); + break; + } - default: - hatSample?.Play(); - break; - } - - break; - } + break; } } } From a85653ebec2607ca2675a1b106ebcd814c75fa66 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Dec 2019 12:24:59 +0900 Subject: [PATCH 4578/5608] Add comment --- osu.Game/Graphics/Containers/OsuScrollContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Graphics/Containers/OsuScrollContainer.cs b/osu.Game/Graphics/Containers/OsuScrollContainer.cs index df4c3a3324..ab72276ad0 100644 --- a/osu.Game/Graphics/Containers/OsuScrollContainer.cs +++ b/osu.Game/Graphics/Containers/OsuScrollContainer.cs @@ -85,6 +85,8 @@ namespace osu.Game.Graphics.Containers protected override bool OnScroll(ScrollEvent e) { + // allow for controlling volume when alt is held. + // mostly for compatibility with osu-stable. if (e.AltPressed) return false; return base.OnScroll(e); From bef9637fdf8806f302185fbbc3545c7b85cf0936 Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Mon, 16 Dec 2019 19:25:28 -0800 Subject: [PATCH 4579/5608] Implemented delete local score individually. Currently does not refresh the score screen after the delete is compelete. --- osu.Game/Online/Leaderboards/Leaderboard.cs | 9 +++-- .../Online/Leaderboards/LeaderboardScore.cs | 34 +++++++------------ .../Select/BeatmapClearScoresDialog.cs | 26 ++++++++++++++ .../Select/Leaderboards/BeatmapLeaderboard.cs | 12 ++++--- 4 files changed, 53 insertions(+), 28 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 94c50185da..0e2864e88c 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Threading; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osuTK; @@ -180,10 +181,14 @@ namespace osu.Game.Online.Leaderboards { new Drawable[] { - scrollContainer = new OsuScrollContainer + new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - ScrollbarVisible = false, + Child = scrollContainer = new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + ScrollbarVisible = false, + } } }, new Drawable[] diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index c4bc306f05..3e5096b051 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -14,11 +14,12 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics; -using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Select; using osu.Game.Scoring; using osu.Game.Users.Drawables; using osuTK; @@ -28,7 +29,7 @@ using osu.Game.Online.API; namespace osu.Game.Online.Leaderboards { - public class LeaderboardScore : OsuClickableContainer + public class LeaderboardScore : OsuClickableContainer, IHasContextMenu { public const float HEIGHT = 60; @@ -53,6 +54,8 @@ namespace osu.Game.Online.Leaderboards private FillFlowContainer modsContainer; private List statisticsLabels; + + private DialogOverlay dialogOverlay; public LeaderboardScore(ScoreInfo score, int rank, bool allowHighlight = true) { @@ -65,9 +68,10 @@ namespace osu.Game.Online.Leaderboards } [BackgroundDependencyLoader] - private void load(IAPIProvider api, OsuColour colour) + private void load(IAPIProvider api, OsuColour colour, DialogOverlay overlay) { var user = score.User; + dialogOverlay = overlay; statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s)).ToList(); @@ -230,28 +234,9 @@ namespace osu.Game.Online.Leaderboards }, }; - Add( - new OsuContextMenuContainer - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] { - new ContextMenuArea{ - RelativeSizeAxes = Axes.Both - } - } - } - ); - innerAvatar.OnLoadComplete += d => d.FadeInFromZero(200); } - private class ContextMenuArea : Drawable, IHasContextMenu - { - public MenuItem[] ContextMenuItems => new MenuItem[] - { - new OsuMenuItem("Delete", MenuItemType.Destructive), - }; - } public override void Show() { foreach (var d in new[] { avatar, nameLabel, scoreLabel, scoreRank, flagBadgeContainer, modsContainer }.Concat(statisticsLabels)) @@ -381,5 +366,10 @@ namespace osu.Game.Online.Leaderboards Value = value; } } + + public MenuItem[] ContextMenuItems => new MenuItem[] + { + new OsuMenuItem("Delete", MenuItemType.Destructive, () => dialogOverlay?.Push(new BeatmapClearScoresDialog(this.score, null))) + }; } } diff --git a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs index c9b6ca7bb3..b4889bfffc 100644 --- a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs +++ b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs @@ -39,6 +39,32 @@ namespace osu.Game.Screens.Select }; } + public BeatmapClearScoresDialog(ScoreInfo score, Action onCompletion) + { + string accuracy = string.Format(score?.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", score?.Accuracy); + + BodyText = $@"{score?.Beatmap?.Metadata?.Artist} - {score?.Beatmap?.Metadata?.Title} {Environment.NewLine} {score?.User} - Rank: {score?.Rank} - Max Combo: {score?.MaxCombo} - {accuracy} - {score?.Date.Date.ToShortDateString()}"; + + Icon = FontAwesome.Solid.Eraser; + HeaderText = @"Clearing this local score. Are you sure?"; + Buttons = new PopupDialogButton[] + { + new PopupDialogOkButton + { + Text = @"Yes. Please.", + Action = () => + { + Task.Run(() => scoreManager.Delete(score)) + .ContinueWith(_ => onCompletion); + } + }, + new PopupDialogCancelButton + { + Text = @"No, I'm still attached.", + }, + }; + } + [BackgroundDependencyLoader] private void load(ScoreManager scoreManager) { diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 1b45a9d270..d609ee3bdc 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -182,9 +182,13 @@ namespace osu.Game.Screens.Select.Leaderboards return req; } - protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) => new LeaderboardScore(model, index, IsOnlineScope) - { - Action = () => ScoreSelected?.Invoke(model) - }; + protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index){ + model.Beatmap = beatmap; + + return new LeaderboardScore(model, index, IsOnlineScope) + { + Action = () => ScoreSelected?.Invoke(model) + }; + } } } From f8ffa676931ebdc01946520c5cf5072ac7caf2f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Dec 2019 13:21:23 +0900 Subject: [PATCH 4580/5608] Add test and isolate ignore bindable from EnableUserDim --- .../Visual/Background/TestSceneUserDimContainer.cs | 14 ++++++++++++++ osu.Game/Graphics/Containers/UserDimContainer.cs | 12 ++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index 472c43096f..d5d4c7e5ec 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -88,6 +88,20 @@ namespace osu.Game.Tests.Visual.Background AddUntilStep("not lightened", () => userDimContainer.DimEqual(test_user_dim)); } + [Test] + public void TestIgnoreUserSettings() + { + AddStep("set dim level 0.6", () => userDimContainer.UserDimLevel.Value = test_user_dim); + AddUntilStep("dim reached", () => userDimContainer.DimEqual(test_user_dim)); + + AddStep($"ignore settings", () => userDimContainer.IgnoreUserSettings.Value = true); + AddUntilStep("no dim", () => userDimContainer.DimEqual(0)); + AddStep("set break", () => isBreakTime.Value = true); + AddAssert("no dim", () => userDimContainer.DimEqual(0)); + AddStep("clear break", () => isBreakTime.Value = false); + AddAssert("no dim", () => userDimContainer.DimEqual(0)); + } + private class TestUserDimContainer : UserDimContainer { public bool DimEqual(float expectedDimLevel) => Content.Colour == OsuColour.Gray(1f - expectedDimLevel); diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index e44e7a0d57..65c104b92f 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -59,7 +59,7 @@ namespace osu.Game.Graphics.Containers private float breakLightening => LightenDuringBreaks.Value && IsBreakTime.Value ? BREAK_LIGHTEN_AMOUNT : 0; - protected float DimLevel => Math.Max(EnableUserDim.Value ? (float)UserDimLevel.Value - breakLightening : 0, 0); + protected float DimLevel => Math.Max(EnableUserDim.Value && !IgnoreUserSettings.Value ? (float)UserDimLevel.Value - breakLightening : 0, 0); protected override Container Content => dimContent; @@ -88,7 +88,7 @@ namespace osu.Game.Graphics.Containers ShowStoryboard.ValueChanged += _ => UpdateVisuals(); ShowVideo.ValueChanged += _ => UpdateVisuals(); StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals(); - IgnoreUserSettings.ValueChanged += _ => updateSettings(); + IgnoreUserSettings.ValueChanged += _ => UpdateVisuals(); } protected override void LoadComplete() @@ -112,13 +112,5 @@ namespace osu.Game.Graphics.Containers dimContent.FadeTo(ContentDisplayed ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint); dimContent.FadeColour(OsuColour.Gray(1f - DimLevel), BACKGROUND_FADE_DURATION, Easing.OutQuint); } - - /// - /// Invoked when the IgnoreUserSettings bindable is changed - /// - private void updateSettings() - { - EnableUserDim.Value = !IgnoreUserSettings.Value; - } } } From 46dc2251e88703029e0234c18794850a5c1475e9 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 28 Nov 2019 21:39:33 +0800 Subject: [PATCH 4581/5608] Add fxcop with every violated rule off. --- CodeAnalysis/osu.ruleset | 63 ++++++++++++++++++++++++++++++++++++++++ Directory.Build.props | 4 +++ osu.sln | 1 + 3 files changed, 68 insertions(+) create mode 100644 CodeAnalysis/osu.ruleset diff --git a/CodeAnalysis/osu.ruleset b/CodeAnalysis/osu.ruleset new file mode 100644 index 0000000000..9bcca40983 --- /dev/null +++ b/CodeAnalysis/osu.ruleset @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index c0d740bac1..27a0bd0d48 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -18,7 +18,11 @@ + + + $(MSBuildThisFileDirectory)CodeAnalysis\osu.ruleset + true $(NoWarn);CS1591 diff --git a/osu.sln b/osu.sln index 1f4faae6b9..79823848f0 100644 --- a/osu.sln +++ b/osu.sln @@ -60,6 +60,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution global.json = global.json osu.Android.props = osu.Android.props osu.iOS.props = osu.iOS.props + CodeAnalysis\osu.ruleset = CodeAnalysis\osu.ruleset osu.sln.DotSettings = osu.sln.DotSettings osu.TestProject.props = osu.TestProject.props EndProjectSection From 9875fcea9971470479006fe81bf15103142fdb79 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Dec 2019 13:54:25 +0900 Subject: [PATCH 4582/5608] Add numbers to old skin for better identification --- .../Resources/old-skin/default-0.png | Bin 0 -> 2003 bytes .../Resources/old-skin/default-1.png | Bin 0 -> 1191 bytes .../Resources/old-skin/default-2.png | Bin 0 -> 1756 bytes .../Resources/old-skin/default-3.png | Bin 0 -> 1822 bytes .../Resources/old-skin/default-4.png | Bin 0 -> 1814 bytes .../Resources/old-skin/default-5.png | Bin 0 -> 1848 bytes .../Resources/old-skin/default-6.png | Bin 0 -> 2014 bytes .../Resources/old-skin/default-7.png | Bin 0 -> 1452 bytes .../Resources/old-skin/default-8.png | Bin 0 -> 1953 bytes .../Resources/old-skin/default-9.png | Bin 0 -> 1814 bytes 10 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-0.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-1.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-2.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-3.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-4.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-5.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-6.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-7.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-8.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-9.png diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-0.png b/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-0.png new file mode 100644 index 0000000000000000000000000000000000000000..2af0569bcb30f4e87135669268698a79ac486f1f GIT binary patch literal 2003 zcmV;^2Q2uBP)0&s!{Eg(K)vw7OGA_klVuXw5~tP0kR@Dz8%i8MTl@(y z-HHy1)1^gl{JB-y+HK0-x1Q6y9t-`>_Z71(JIO;iA0MaZIq(1befqh%Io-c~gz5eR zLm$Gm41gB_aex&76Cer@2?%HRpx7S*9suqGCK+)4NX?g`CPir6_!2+@zzkReSO<_@ z^LM}y;5NVxn2{xn2}vVXR=YR*Dp~j2@G20fY&*JmX?;P$jC^e%tp`?UA%a4 zu&1YI6!hJjnwo0bzI}UET3VV}Mj~dj*+MQgfi!+r62RUDG$O!&o84~r!#T;(-`_t1 zr}!~nhvLwoLto3R)z;S5PyYV{z;cY#9Qpu~Nd?qsv4QUH?i(a@TN=^W5s+ zINU!W^Bs7wM5WSLKIbQq$h?xz7Su@L?Afz4dAr6`C(!syOAst9EQ}-NzzRxYHNR=s zu3gdz9R@X$wA};TU93o+l9ECXIGU4)pvhf!cD7k|;j34#(ya4GsxqM->FMe5LV4gL zVPg8_OE1)@(z$czD2ZQ!RAic(6H!r7MxjXaEf~YS645tVd*DWlMgMq^+n4fRFqaBN zw+4T#B&sA$0s|IFmu&!-QWAoGYhn^jPDVP-76R5i1;za`zg0#@8#V6#F((n_Uwzp! z=|!zp>m;o(75s~)Lz|tQ^^&QVlUPa%5!ppYMn;@M4{82_Uat>l%{8u0(%&~UG(-cW zi<2;Dk!NRT=LCrlP6euz!W#{;MOJ{}4oNST81*z4??Raas~UBiH*Z!|=0c@7N~ZTU zlfV`WRaXT@?cX?%NY*HM2PN^RS`t%JQ`81LLF~c6YZV+DHf%7fkUDkec52vedXomh zJW`-adE6e;ka%ICUKk*YCz)zgskynCR*g47l^%+c7!wjX z#l<_Bu4KVXl)`fOc$3fT>+5sW)GNo19pjlYI-)yb?&RjhJ6b*#`!ZjEM#_GDjmH4N zBdzDEg!iiHq8~kaw2OEp?4V4EB+$Y~_=QuaPDzp2wrv}i1{PPZa%sRPM&k^;h2Lwj zSfo2B!^6W4^4tR5xD{0CQJ?~4lo^Ze#EBCQ{70oA`X}+PQNlZN#-x8x~2pS*Ol7_U_%=En^qhTp*W9bx$4#6z~h!0;;X8EmEUKq=VAO z4EmXP6fPuFsMD)#Hk&IUA>j|u;WbLWtfZu5?bz7ZIC!_G5{GOg3pBG6=N{Y_U&tI!1Q-ydi0I`H>!)LlD z45>cBG@7uSp104&w z{3XU<8rTAj@Oe6P7}95XE9d0NleZwRn%uN$)5`{fAtKZS&YU@Osj{-Nqqnzrh9r|; z00x5*STNrSBoQ>!hK7b5aI3jmt1@(-*mT1twD2$ir-<9c^HomT($(d0h7A8xHu!Y zZ17;uHPe5A_(nb#ulv=dk=v5~f3R1R!9V>)r0sg5V) zH9!!_AOU<)Wi?B)Q+RVX$fobIVg`XPp}3U3NfT-k;)r0a7;M5VXA%n|UdF>(IS6kk lHvJ5V|K9=phm5}k7yxVV^TAT2(qBnTK@ z0-l32%{aNe_uRQn>?9|hf!n#ip2wW8x3=Ts3m|d+4Qb+fVseKf#rdn zA?|+&whi_j>@!#lY)`y^MH#JOM?c(q&ai4^Z*+HeKd=%Lm&=tO3A<6cJILgb*v)S|t*jXcwTurt&j1E-0hBxf&;7YnT zaKvIUo~)Z-yL#n|N9;wGU>Q!QGizaCA(Ck0yu7^Z+}zwOiin+^oxP!S<4u>OyDx{~UhYP_b_|;Gd6SKuUGbbgpp9`t4 zuP>&Gn4O&!z42De57RsXBCzh=d|g#lMHVtPHYN&LW+|WyMwhvehK7cGGhylN?d3wy z(_gF-T0Ak^+uOZn!Xh-gFxXFJArKb)^hJCPozzWzFLZ6OLOwxQ4y||u5%CTW3-#G%EpOKiF?SBr{}0zPSNZ7njxA)!!clPzCqVIo-wgyl56+~n(;ni_Jo1OkD1Vfhil za$v)$cVI>ZjFcm#>+F2@4IJ*tqtzP@=%Sg1mf)-rL@(a}LpQi(m5Sff)D!f5RVU)R;u zk%dU?u>@h+wc?TUV7K|g=kt+;=&^^25GQMNC+uM+ECPG1COS4pH=SMgkj!@Zy;t^zzGL^7M?C~|t z6(P*kfX1LgbBAOApi1 z{yuZhQ9(k1J@9cko>SVso=31tK4U#XWniAXQxWlxN0?XA z85)+b3Nrd#2H(8Hm=weF!_2XsP{{urDf3fW$_V)*zyQwC!s?l~#8?0T002ovPDHLk FV1oRZC2Ifx literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-2.png b/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-2.png new file mode 100644 index 0000000000000000000000000000000000000000..dbf7bc73bc620b8782be5518443a36c91d1216cb GIT binary patch literal 1756 zcmV<21|#{2P)p$w|{(9A*RO z%p)u&yhey6EFmmnL=hHhoQDXF6GjOWgfYS};Su3)o_`i<;vgGCSVdS(SWj3U!T>%b z+#z@f_XrR8=7J&~#YA@yR?dK)=2trhXbg7}s#TVi5kV`Gf|W4K6PU!MmH&*(K^ z1P2Zr5N41hELn{>GGIKuq^71W2{vM6m$taLxGxF|3vJM?k?Rx}7t2q5wLguAeAL(1 zd#qNg4NpPuxe7O14mqn4ALo>7ayp%lgY{;GQ%tnBwmOYm3$o>}uS3pi#Q)`b!GuH* zj6OR$I(}8oojrT@wvlT|vPE&XXc}?OPItxe$&)9q8eN!WWo6gZBohMVS+q2cOy!fw z@#DvP+S=NB^j^8Ds_L?ox~~v!hiJJVuurv!|Aove4l*(_?0U#oR8-h;!+eMW>3Xn6 z(A?ZC90_TERP|ykmtMlRGWo-Y51;p^d3g4&UAr13(ik?vbCLCOa&i)k$WE$T{y?p6 z(fTowA0yl8;zM7tRasf-2Jp|bv$I#m#Kicz9gWfyi~K8Y5T<+>=jkQxa=GMn;U#X* zE&fiB$fHBaVk<)R=9P*cwed5djUQ_i*BQP+Ph_KB;!RCWZt3uM-|7r>5|ekK_9v_( zY=AqdoD1*oBftXtQN_`D5gct4Z6>5{y#*U&LWQ0n{+Oi_m^hP%Muz|*gJ@nNyo#*O zt9(Q>yrS6WVhug&PH`Qw$M^L{n|$9P>HC^+JB!{65wWKn-3I}F8i%zg4o;mqWi=A* zW5(j~V$B3@mV+SuA<7HU_T9R5>oZh} zdamPeINa&!>F1@S^Eq)H)NCX|O`7VJJiVlmEB5T!W0$7BferpI=ZA=}nHMYMkuH-q zqU-(p_n(&}f^y*oudUD#XZKi!+(JkWmNd1BHYrCSdtV{aqtmLaAW27XD*uGAG{mHl zXue~cRoxRbO8ONvuY@8&8ty^q|5LrB(b6eMBiWsSi%e>`hsB^Y;&?A{tGvra2`0;k zdtf0-nuc?HjZb;!Dk$Pa8jbW?&W6k6VDJ3N( z88eMCBHY>8={|Dg$W@K~Z!`#M^G`Ta-r+?$?w2@|ewXlp{3FQX=+UFrnQ9ptzHs4! zi*D4Zh_I0X8FeekE2XkZCas4s$Wr^}K7IQ1?Eu}8-tjRfqkd(5ZQ`ge;2%{2y}iBY zV!}4)iTxzF5K;tB0XcKx)!#O;-Sr|~m*^RFb#*T3aKvBA2T?OiWPLbEqpX$W=2Dil zQ^YyJtO=$Q59P4gY|3_RTr1+(P)rdr3CF7w#r~qaS$fxBb%?jbzE>2vxw&E0Hrz?_ z{4U-OoKBo&vQA87W@aXalXzoeqbw7*Rz^j{k#yb`>3p`{Woiv+^Jik3cPofTibjA+ z%&?M1ZLZk-d8k>dFzI}g^bYYQ8DEl2Zu*Nj%pEWL|9Oc>+x^L8s>q@RYT=G%13S#Z yFpz!1`;+&0({xl z!WaUPdgUhj#U&~~aA31EC}4od2qXp);Rk>C$q(V@0L@|`3WhWb5t+!%0Xk{M#jwO7 zFy87s^+8jVj(AW5lU`k2HI|i?>6ues16J%NAXsfYe_EJVR8;t6wX3VE zSrhpVa0^y@&r#+K0;sL=Co@y+3lnK+X)(|g6VEjuz3VLHV>CI12US&7Q6V8Ahka}! zeHcmD@7Rmu)|4I@85uk~J8N*4gi@&t=6&$O!on_*i7c2!nNn^mbApYdV-}Nxx;?_f z!vm(Krrzfv-rn9mnxCI9tTsjy9dP{X5sr3<1W z930H%4Sf)^H{*i zBS{23h>YEV&d$zkj2iBePfAL3r{lM!Xu;d&A9CaVthdcD?N@}gDm z0j^g(N?h~+p(Fv+QpuyO2L%OPpy_qMm(EHzw+0F`z+JRQz&J@&lSuWsJkUqbN^g;mSxM zT!Pmws0%MwZN(QZF1vWPUU$a#S@Iu^!cEWv=#M*<86LjhJejQzO*3&iVy0Oqs=}c^78V|VEb9L^3T!n)9mi?uJ-iwG}{)zAn>o) zRH7&YS{gtoba-xnJ#*CK%&C_sDjlchk}Nkjms_j%_xH~;(|h9TJb<>r(jQz|St)T> zBrz%a0kswq$#J<~3W$==I$n?MulP}{wpWMGgDweGY!)P?#mqK!LbJHXy&Ex1u8VV5|6Z3J^r>Hsg2ytxRT5j0W(_@fAd~9rN zQD_QHOiX0+kjBNaC8iu}0 z)H~d>*;k=$m=R7u93Pg@Ru1KL!s6m$9lpP0NF$dHN2INV1oi*UQajCJo0XN7Y2JE0 zh%4OK*!UCkszew+5Z262DjaJCM6bTjQ<}EeDTJ}Nq|}UJvgiXq_NEQNbqnx4;10eD zbg9~6h$~2Fz03AZPy#@@j*Ezh2z8d6Fe)r8ELfZioYMfu#?jHyKN*J;k2$K8egz&I zTxBA=BUD77D9Ql5?4{6dqA>RhzySB(bgRC#^C|^bHkMMh$^%4ilPQtOJaYUw8a|12={s5$!(MW|36v#JpL1403@th-uUEs@Bjb+ M07*qoM6N<$f~Rj>w*UYD literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-4.png b/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-4.png new file mode 100644 index 0000000000000000000000000000000000000000..4564f6d8bff88ce7a1e983aa9192b8c882789f5d GIT binary patch literal 1814 zcmV+x2kH2UP)MX4xD zf25+&_`^?;7>(E#Nd$>eNnaomF(fo5Ch!6eeIN!x0uMwXfe?AmHFJrMt*yQ6a5&_FpC`1^Z%w=C zJCY8WYw)Tc313)1#2v`)6Jb+6$LNigvs5SK0`Y68Roagv#t zd04gI?(XgpsX0WL_w_Uuj!^g^YjkvUm{A7?@uH%lNN(QG(FqU9pAJXFeQ9ZFQL245 zH#f^fMrnrsQX#Tpr%s)UGP@en)6?beh7t+$b>j)X=yP{WO#V^nzYkT ziD-p&VPZL<2?uf!UK@vnZc~*cFyuGx+{z;nBC(An#oOW<1R!anXgv}n{$vuE zg|7&3&&S1m85tRoCf&**?`=v%m;{7fnh2L5k)NNR||qVjAY%u8;Hj*e1)OT4L0@dLYwS=z2sXh`JJ z%nFIRy1F#Irw9_*^);6di-j#4_6{SG#Dy$+QPaLj_>#sv?CXNWD}<+o7IH^|T&d3m z30*Ui&cZ4yD?M$zNSj}U+pZQLhy%XR^MwTqMMWqq>!TaKBZ*Om^nL@*6nY(h( zesPn{W{cm-Bw%fAZ3A+Gg>sOHTKmM+q@<)HmMw0Y1ZzYt2dx$vjA$Tln2QAKu5!?V zeB)LoVz=96w;C2o*jGwvSFF0a`rEBcq`bUb-nYh9_dt$XSRk>S;h zK?z%})-&Avj&PR7@05u^BtAxXhwD!3W*r?JNqV`9E2Ti0XQyJN6UP!^m&@uJd}_D{>E`RYWN-cbhDXLyEsd@;Ht{L zsYE0)D6<~oHKX!BSCcIMuCIl}x)SlW{ZC}8+1~;T0CqcF2-dk}y8r+H07*qoM6N<$ Ef`bE6AOHXW literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-5.png b/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-5.png new file mode 100644 index 0000000000000000000000000000000000000000..dcef35eb594a4c047cf37dcfb7acb660cb155de6 GIT binary patch literal 1848 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-7.png b/osu.Game.Rulesets.Osu.Tests/Resources/old-skin/default-7.png new file mode 100644 index 0000000000000000000000000000000000000000..b9079ad5d5f863ccbbbeac6ab2677ac0d2645698 GIT binary patch literal 1452 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 n?OHhGXep*ZTPPG6 z96*o~Ka@eKiOiH35FtuXA%TyY06%;%fA9$jL;O%6p$U)@HP(nCkWvBxO@t7JLo&jBQyWN|r{ch6hwv-du0@2lV4-PIkJVTV8TdcDlE zHUN9TS%53R8Q=i0C7*c=FajO`wgC6o^^r7LL4u9|Pr%CzJ_65g1Lgn=fF-~R;343N zmWTD|1{y4@XBK=F@FpXB5Cch%17-mmY$vRfwfX_Q9=G--K&;Y=US3}IadB~OF)=Y- zo}Ql09v&V}%I8;BR<@RxmkkRG3tNMOgX^80oogyzgKlyIa0~d{mm&*9&%otvKoq@S zP*C8Po}L~Q931Q?YD%NgxHCLFJlECLHCIzpGpG3TAYcG}dsl^+MY4?OWk4vumz|yM zU0q$B;Ns%qbPztUxw*O3*w{E&R#rAiZr=iQ0IzjTWR*m5yIWgZqaq_CgAOAlO;1lR z#>U3BFD)(Yuv@Z(Ep`kRmx*cW?MJs1zWwjHZ{u$5*{2tO& zM2Vh)OW1yhqE9w7Gz@rqdw&7z)rN(IT^$=6o7?L-bS-%9GJYq!^$y@giRG3}K^4QRZOk=;(+P-TJ(|ymkdq z^A=`iX7+1Y12YT;GMoAXUQlxbFF*+X5*ixnl$e+pEJAc(U|_Pjxp|RI(GvB5&j6-K z$Kb(0(y~@@ad9}A27w{%&17L>%T6cLsH&>EBpM(^MMZ;T`W@g;7R}TA=Ire3nwGT! z0s_3jSbSG;x6e__q6m3|TU9hgp;bplMz*-y0d51)$3zd9hQVOi(YhuaI=*D;LCIcV z0!5dSlHx6D)!N$HaWWkRqDC^8(x4Dzl*a{1)*MLj@$r75`H=+GG*eS_oRlGpu0WOSCPWCiWQbOqp6&0EOr8s14>8`oDx;l%j zO;Q-T!D&wRgzPcd*Vjk4-JoJse;&B|5J1T9q|E^z@&731&jX&54P3P{MeR%WRnrj{ z@Rbc*mGQ(zxqVts89rcpsgIu}zhlq_b3r5{)YsS7cgTsjZKDhfEJH*V3=9lBPo}Ri zjiF;DkjVvdb91GvN>bt~>I_cStja+W3RxCUI}9E+eI0NS2%lqxrD>$5rV5L8%->|X z0V(kjC2O*7eSQ5LN`XVQqqerTF;VMQ zR8&yw`CCv>nnzDh4;AdIX0l9l{LcSUQc^Om*oHkvX=!PKg0Qqz`3@69uId<39jg}X zS?yJW0Eu>OS7J;}O)WsF{sUxy&o?$U3^Hqsj*iZ99)M(QNtrluvWzeW#;5#)V5u9s zM=)SVz9D1-IX`6$hHWC;wkxd3X4=ZSy1HZs2M7EAqf-bmvj)XxE2+W00*()!scu;p zXlv>&W5XJV=xFw>(WLZkX&P@t!xQP~-xb+I6BY-;^L{YrMsnkt+wp>M_8{EN~O1jQh5XIM=AM?&4=F#5X-efHT2G4jbi!w4Y zhLp`4z_8B3J1$wvIC4EiEm{d$oQzNi2!TmYZrnEU5qs)^eyUS^oOd6!H1_ z`BByqz7>)(Fa2M9!(H+oGBg=jEL*B$aYLa_Z3P|`o z)32V)HPqho$eCgySO5S307*qoM6N<$ Ef@aS_IsgCw literal 0 HcmV?d00001 From ecfc6dfa3d41f27190381abe28f9dd28e86e46bd Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 28 Nov 2019 21:41:29 +0800 Subject: [PATCH 4583/5608] CA1825: use Array.Empty. --- CodeAnalysis/osu.ruleset | 3 --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 3 ++- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 4 ++-- osu.Game.Rulesets.Osu/OsuRuleset.cs | 3 ++- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 3 ++- osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs | 3 ++- .../Visual/Multiplayer/TestSceneMatchParticipants.cs | 2 +- osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs | 2 +- .../Visual/Online/TestSceneUserProfilePreviousUsernames.cs | 2 +- osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs | 2 +- .../Screens/Ladder/Components/DrawableMatchTeam.cs | 2 +- osu.Game/Beatmaps/BeatmapInfo.cs | 4 ++-- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Overlays/Mods/ModSection.cs | 2 +- osu.Game/Overlays/Music/PlaylistList.cs | 2 +- osu.Game/Overlays/UserProfileOverlay.cs | 6 ++---- osu.Game/Rulesets/Mods/Mod.cs | 2 +- osu.Game/Rulesets/Ruleset.cs | 4 ++-- osu.Game/Screens/Play/SquareGraph.cs | 2 +- osu.Game/Screens/Select/Details/FailRetryGraph.cs | 4 ++-- 20 files changed, 28 insertions(+), 29 deletions(-) diff --git a/CodeAnalysis/osu.ruleset b/CodeAnalysis/osu.ruleset index 9bcca40983..61e6520beb 100644 --- a/CodeAnalysis/osu.ruleset +++ b/CodeAnalysis/osu.ruleset @@ -57,7 +57,4 @@ - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 506fa23fa9..bf5b00528b 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Difficulty; using osu.Game.Rulesets.Difficulty; using osu.Game.Scoring; +using System; namespace osu.Game.Rulesets.Catch { @@ -112,7 +113,7 @@ namespace osu.Game.Rulesets.Catch }; default: - return new Mod[] { }; + return Array.Empty(); } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index a96c79b40b..3e3dc5cf66 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -158,7 +158,7 @@ namespace osu.Game.Rulesets.Mania }; default: - return new Mod[] { }; + return Array.Empty(); } } @@ -268,7 +268,7 @@ namespace osu.Game.Rulesets.Mania return stage1Bindings.Concat(stage2Bindings); } - return new KeyBinding[0]; + return Array.Empty(); } public override string GetVariantName(int variant) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 2f43909332..b182e5a658 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -26,6 +26,7 @@ using osu.Game.Rulesets.Osu.Difficulty; using osu.Game.Rulesets.Osu.Skinning; using osu.Game.Scoring; using osu.Game.Skinning; +using System; namespace osu.Game.Rulesets.Osu { @@ -149,7 +150,7 @@ namespace osu.Game.Rulesets.Osu }; default: - return new Mod[] { }; + return Array.Empty(); } } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index ab9c95159c..0b4cb9801e 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Difficulty; using osu.Game.Scoring; +using System; namespace osu.Game.Rulesets.Taiko { @@ -111,7 +112,7 @@ namespace osu.Game.Rulesets.Taiko }; default: - return new Mod[] { }; + return Array.Empty(); } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index 875e7b9758..4c5c18f38a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.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.Linq; using NUnit.Framework; using osu.Framework.Graphics; @@ -31,7 +32,7 @@ namespace osu.Game.Tests.Visual.Gameplay requestCount = 0; increment = skip_time; - Child = gameplayClockContainer = new GameplayClockContainer(CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)), new Mod[] { }, 0) + Child = gameplayClockContainer = new GameplayClockContainer(CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)), Array.Empty(), 0) { RelativeSizeAxes = Axes.Both, Children = new Drawable[] diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchParticipants.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchParticipants.cs index 50df4022dc..1ac914e27d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchParticipants.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchParticipants.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.Multiplayer }); AddStep(@"set max", () => Room.MaxParticipants.Value = 10); - AddStep(@"clear users", () => Room.Participants.Value = new User[] { }); + AddStep(@"clear users", () => Room.Participants.Value = System.Array.Empty()); AddStep(@"set max to null", () => Room.MaxParticipants.Value = null); } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index 98da63508b..15f9c9a013 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -70,7 +70,7 @@ namespace osu.Game.Tests.Visual.Online }, Title = "osu!volunteer", Colour = "ff0000", - Achievements = new User.UserAchievement[0], + Achievements = Array.Empty(), }; public TestSceneUserProfileOverlay() diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs index d09a50b12c..048a1950fd 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Online new User { PreviousUsernames = new[] { "longusername", "longerusername" } }, new User { PreviousUsernames = new[] { "test", "angelsim", "verylongusername" } }, new User { PreviousUsernames = new[] { "ihavenoidea", "howcani", "makethistext", "anylonger" } }, - new User { PreviousUsernames = new string[0] }, + new User { PreviousUsernames = Array.Empty() }, null }; diff --git a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs index ba63013886..f3eecf8afe 100644 --- a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs @@ -49,7 +49,7 @@ namespace osu.Game.Tournament.Screens.Editors get { if (editorInfo == null) - return new MenuItem[0]; + return Array.Empty(); return new MenuItem[] { diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index ded21730f3..031d6bf3d2 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -192,7 +192,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components get { if (editorInfo == null) - return new MenuItem[0]; + return Array.Empty(); return new MenuItem[] { diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 6e82c465dc..bcc9ab885e 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -98,7 +98,7 @@ namespace osu.Game.Beatmaps { if (string.IsNullOrEmpty(value)) { - Bookmarks = new int[0]; + Bookmarks = Array.Empty(); return; } @@ -111,7 +111,7 @@ namespace osu.Game.Beatmaps } [NotMapped] - public int[] Bookmarks { get; set; } = new int[0]; + public int[] Bookmarks { get; set; } = Array.Empty(); public double DistanceSpacing { get; set; } public int BeatDivisor { get; set; } diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 59a27e3fde..9ea254b23f 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -55,7 +55,7 @@ namespace osu.Game.Beatmaps private class DummyRuleset : Ruleset { - public override IEnumerable GetModsFor(ModType type) => new Mod[] { }; + public override IEnumerable GetModsFor(ModType type) => Array.Empty(); public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) { diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index c55d1d8f70..7235a18a23 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -81,7 +81,7 @@ namespace osu.Game.Overlays.Mods } } - private ModButton[] buttons = { }; + private ModButton[] buttons = Array.Empty(); protected override bool OnKeyDown(KeyDownEvent e) { diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 83528298b1..3cd04ac809 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -239,7 +239,7 @@ namespace osu.Game.Overlays.Music private class ItemSearchContainer : FillFlowContainer, IHasFilterableChildren { - public IEnumerable FilterTerms => new string[] { }; + public IEnumerable FilterTerms => Array.Empty(); public bool MatchingFilter { diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 468eb22b01..b5e7b8bedb 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.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.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -55,10 +56,7 @@ namespace osu.Game.Overlays new BeatmapsSection(), new KudosuSection() } - : new ProfileSection[] - { - //new AboutSection(), - }; + : Array.Empty(); tabs = new ProfileTabControl { diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 1c280c820d..b780ec9e76 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Mods /// The mods this mod cannot be enabled with. /// [JsonIgnore] - public virtual Type[] IncompatibleMods => new Type[] { }; + public virtual Type[] IncompatibleMods => Array.Empty(); ///

/// Creates a copy of this initialised to a default state. diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 45aa904b98..2550f69286 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets /// /// The legacy enum which will be converted /// An enumerable of constructed s - public virtual IEnumerable ConvertLegacyMods(LegacyMods mods) => new Mod[] { }; + public virtual IEnumerable ConvertLegacyMods(LegacyMods mods) => Array.Empty(); public ModAutoplay GetAutoplayMod() => GetAllMods().OfType().First(); @@ -116,7 +116,7 @@ namespace osu.Game.Rulesets /// /// A variant. /// A list of valid s. - public virtual IEnumerable GetDefaultKeyBindings(int variant = 0) => new KeyBinding[] { }; + public virtual IEnumerable GetDefaultKeyBindings(int variant = 0) => Array.Empty(); /// /// Gets the name for a key binding variant. This is used for display in the settings overlay. diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 715ba3c065..a667466965 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -38,7 +38,7 @@ namespace osu.Game.Screens.Play } } - private float[] calculatedValues = { }; // values but adjusted to fit the amount of columns + private float[] calculatedValues = Array.Empty(); // values but adjusted to fit the amount of columns private int[] values; diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index 121f8efe5a..134fd0598a 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -27,8 +27,8 @@ namespace osu.Game.Screens.Select.Details metrics = value; - var retries = Metrics?.Retries ?? new int[0]; - var fails = Metrics?.Fails ?? new int[0]; + var retries = Metrics?.Retries ?? Array.Empty(); + var fails = Metrics?.Fails ?? Array.Empty(); float maxValue = fails.Any() ? fails.Zip(retries, (fail, retry) => fail + retry).Max() : 0; failGraph.MaxValue = maxValue; From d7b3578cc61f6cd99d940443ef0d14e8faeccbb2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 28 Nov 2019 21:52:05 +0800 Subject: [PATCH 4584/5608] CA2201: throw correct exception type. --- CodeAnalysis/osu.ruleset | 3 +++ osu.Game.Tests/Visual/TestSceneOsuGame.cs | 4 ++-- osu.Game/Online/API/APIRequest.cs | 10 +++++++++- .../Rulesets/Difficulty/Utils/LimitedCapacityStack.cs | 2 +- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CodeAnalysis/osu.ruleset b/CodeAnalysis/osu.ruleset index 61e6520beb..b82799fea4 100644 --- a/CodeAnalysis/osu.ruleset +++ b/CodeAnalysis/osu.ruleset @@ -57,4 +57,7 @@ + + + \ No newline at end of file diff --git a/osu.Game.Tests/Visual/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/TestSceneOsuGame.cs index e495b2a95a..492494ada3 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuGame.cs @@ -111,7 +111,7 @@ namespace osu.Game.Tests.Visual foreach (var type in requiredGameDependencies) { if (game.Dependencies.Get(type) == null) - throw new Exception($"{type} has not been cached"); + throw new InvalidOperationException($"{type} has not been cached"); } return true; @@ -121,7 +121,7 @@ namespace osu.Game.Tests.Visual foreach (var type in requiredGameBaseDependencies) { if (gameBase.Dependencies.Get(type) == null) - throw new Exception($"{type} has not been cached"); + throw new InvalidOperationException($"{type} has not been cached"); } return true; diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index b424e0f086..fcbd4d314a 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -122,7 +122,7 @@ namespace osu.Game.Online.API // attempt to decode a displayable error string. var error = JsonConvert.DeserializeObject(responseString); if (error != null) - e = new Exception(error.ErrorMessage, e); + e = new APIException(error.ErrorMessage, e); } catch { @@ -154,6 +154,14 @@ namespace osu.Game.Online.API } } + public class APIException : InvalidOperationException + { + public APIException(string messsage, Exception innerException) + : base(messsage, innerException) + { + } + } + public delegate void APIFailureHandler(Exception e); public delegate void APISuccessHandler(); diff --git a/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs index d47caf409b..3cab04d904 100644 --- a/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs +++ b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Difficulty.Utils get { if (i < 0 || i > Count - 1) - throw new IndexOutOfRangeException(); + throw new ArgumentOutOfRangeException(nameof(i)); i += marker; if (i > capacity - 1) From 3c39fde7ff938f0397639cec8f7e871fdf8c4b9f Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 28 Nov 2019 21:59:49 +0800 Subject: [PATCH 4585/5608] CA1065: throw NotSupportedException in properties. --- CodeAnalysis/osu.ruleset | 1 - osu.Game/Rulesets/UI/DrawableRuleset.cs | 28 ++++++++++++------------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/CodeAnalysis/osu.ruleset b/CodeAnalysis/osu.ruleset index b82799fea4..2f072ffa45 100644 --- a/CodeAnalysis/osu.ruleset +++ b/CodeAnalysis/osu.ruleset @@ -39,7 +39,6 @@ - diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 5033fd0686..0bb99517ef 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -515,34 +515,34 @@ namespace osu.Game.Rulesets.UI public Stream GetStream(string name) => primary.GetStream(name) ?? secondary.GetStream(name); - public IEnumerable GetAvailableResources() => throw new NotImplementedException(); + public IEnumerable GetAvailableResources() => throw new NotSupportedException(); - public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable) => throw new NotImplementedException(); + public void AddAdjustment(AdjustableProperty type, BindableNumber adjustBindable) => throw new NotSupportedException(); - public void RemoveAdjustment(AdjustableProperty type, BindableNumber adjustBindable) => throw new NotImplementedException(); + public void RemoveAdjustment(AdjustableProperty type, BindableNumber adjustBindable) => throw new NotSupportedException(); - public BindableNumber Volume => throw new NotImplementedException(); + public BindableNumber Volume => throw new NotSupportedException(); - public BindableNumber Balance => throw new NotImplementedException(); + public BindableNumber Balance => throw new NotSupportedException(); - public BindableNumber Frequency => throw new NotImplementedException(); + public BindableNumber Frequency => throw new NotSupportedException(); - public BindableNumber Tempo => throw new NotImplementedException(); + public BindableNumber Tempo => throw new NotSupportedException(); - public IBindable GetAggregate(AdjustableProperty type) => throw new NotImplementedException(); + public IBindable GetAggregate(AdjustableProperty type) => throw new NotSupportedException(); - public IBindable AggregateVolume => throw new NotImplementedException(); + public IBindable AggregateVolume => throw new NotSupportedException(); - public IBindable AggregateBalance => throw new NotImplementedException(); + public IBindable AggregateBalance => throw new NotSupportedException(); - public IBindable AggregateFrequency => throw new NotImplementedException(); + public IBindable AggregateFrequency => throw new NotSupportedException(); - public IBindable AggregateTempo => throw new NotImplementedException(); + public IBindable AggregateTempo => throw new NotSupportedException(); public int PlaybackConcurrency { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); + get => throw new NotSupportedException(); + set => throw new NotSupportedException(); } public void Dispose() From 09257b0c6dd17130b5d7c6e9f31726328e9bb368 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 28 Nov 2019 22:07:46 +0800 Subject: [PATCH 4586/5608] CA1820: use IsNullOrEmpty. --- CodeAnalysis/osu.ruleset | 1 - osu.Game/Overlays/DirectOverlay.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CodeAnalysis/osu.ruleset b/CodeAnalysis/osu.ruleset index 2f072ffa45..5329e84024 100644 --- a/CodeAnalysis/osu.ruleset +++ b/CodeAnalysis/osu.ruleset @@ -48,7 +48,6 @@ - diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index aedbd1b08b..9daf55c796 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -116,7 +116,7 @@ namespace osu.Game.Overlays Filter.Search.Current.ValueChanged += text => { - if (text.NewValue != string.Empty) + if (!string.IsNullOrEmpty(text.NewValue)) { Header.Tabs.Current.Value = DirectTab.Search; From d5994ed4845b196b249f0c51db70d999ccbe359d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 28 Nov 2019 22:21:21 +0800 Subject: [PATCH 4587/5608] CA2208: create exceptions correctly. --- CodeAnalysis/osu.ruleset | 1 - osu.Game/Graphics/ScreenshotManager.cs | 2 +- osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs | 2 +- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 4 ++-- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 2 +- osu.Game/Rulesets/Scoring/HitWindows.cs | 2 +- osu.Game/Screens/Play/ReplayPlayerLoader.cs | 2 +- osu.Game/Users/UserPanel.cs | 2 +- 8 files changed, 8 insertions(+), 9 deletions(-) diff --git a/CodeAnalysis/osu.ruleset b/CodeAnalysis/osu.ruleset index 5329e84024..2a0c6fb928 100644 --- a/CodeAnalysis/osu.ruleset +++ b/CodeAnalysis/osu.ruleset @@ -51,7 +51,6 @@ - diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 02d928ec66..b9151b7393 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -119,7 +119,7 @@ namespace osu.Game.Graphics break; default: - throw new ArgumentOutOfRangeException(nameof(screenshotFormat)); + throw new InvalidOperationException($"Unknown enum member {nameof(ScreenshotFormat)} {screenshotFormat.Value}."); } notificationOverlay.Post(new SimpleNotification diff --git a/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs index 3cab04d904..1fc5abce90 100644 --- a/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs +++ b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Difficulty.Utils public LimitedCapacityStack(int capacity) { if (capacity < 0) - throw new ArgumentOutOfRangeException(); + throw new ArgumentOutOfRangeException(nameof(capacity)); this.capacity = capacity; array = new T[capacity]; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index ed48ddbc2f..386805d7e5 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -150,8 +150,8 @@ namespace osu.Game.Rulesets.Objects.Drawables if (HitObject.SampleControlPoint == null) { - throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." - + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); + throw new InvalidOperationException($"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." + + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); } samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray(); diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 7fddb442d1..bdd019719b 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -118,7 +118,7 @@ namespace osu.Game.Rulesets.Objects.Legacy int repeatCount = Parsing.ParseInt(split[6]); if (repeatCount > 9000) - throw new ArgumentOutOfRangeException(nameof(repeatCount), @"Repeat count is way too high"); + throw new FormatException(@"Repeat count is way too high"); // osu-stable treated the first span of the slider as a repeat, but no repeats are happening repeatCount = Math.Max(0, repeatCount - 1); diff --git a/osu.Game/Rulesets/Scoring/HitWindows.cs b/osu.Game/Rulesets/Scoring/HitWindows.cs index 39d67f1071..018b50bd3d 100644 --- a/osu.Game/Rulesets/Scoring/HitWindows.cs +++ b/osu.Game/Rulesets/Scoring/HitWindows.cs @@ -165,7 +165,7 @@ namespace osu.Game.Rulesets.Scoring return miss; default: - throw new ArgumentException(nameof(result)); + throw new ArgumentException("Unknown enum member", nameof(result)); } } diff --git a/osu.Game/Screens/Play/ReplayPlayerLoader.cs b/osu.Game/Screens/Play/ReplayPlayerLoader.cs index 86179ef067..c8ca604902 100644 --- a/osu.Game/Screens/Play/ReplayPlayerLoader.cs +++ b/osu.Game/Screens/Play/ReplayPlayerLoader.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Play : base(() => new ReplayPlayer(score)) { if (score.Replay == null) - throw new ArgumentNullException(nameof(score.Replay), $"{nameof(score)} must have a non-null {nameof(score.Replay)}."); + throw new ArgumentException($"{nameof(score)} must have a non-null {nameof(score.Replay)}.", nameof(score)); scoreInfo = score.ScoreInfo; } diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index c63c12773e..6ddbc13a06 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -63,7 +63,7 @@ namespace osu.Game.Users private void load(UserProfileOverlay profile) { if (colours == null) - throw new ArgumentNullException(nameof(colours)); + throw new InvalidOperationException($"{nameof(colours)} not initialized!"); FillFlowContainer infoContainer; From e46f6627e4f0a932a5d52c255810d6277a7263c7 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 28 Nov 2019 22:26:10 +0800 Subject: [PATCH 4588/5608] CA1052: make type static. --- CodeAnalysis/osu.ruleset | 1 - osu.Game/IO/Legacy/SerializationReader.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CodeAnalysis/osu.ruleset b/CodeAnalysis/osu.ruleset index 2a0c6fb928..0756adb05c 100644 --- a/CodeAnalysis/osu.ruleset +++ b/CodeAnalysis/osu.ruleset @@ -9,7 +9,6 @@ - diff --git a/osu.Game/IO/Legacy/SerializationReader.cs b/osu.Game/IO/Legacy/SerializationReader.cs index 82b2c4be32..aeb3ce754d 100644 --- a/osu.Game/IO/Legacy/SerializationReader.cs +++ b/osu.Game/IO/Legacy/SerializationReader.cs @@ -192,7 +192,7 @@ namespace osu.Game.IO.Legacy } } - public class DynamicDeserializer + public static class DynamicDeserializer { private static VersionConfigToNamespaceAssemblyObjectBinder versionBinder; private static BinaryFormatter formatter; From caf3f774baac67213e470d66f5e21e8e8f7616c5 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 28 Nov 2019 22:39:09 +0800 Subject: [PATCH 4589/5608] CA1309: compare strings correctly. --- CodeAnalysis/osu.ruleset | 1 + osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs | 2 +- osu.Game/Scoring/ScoreManager.cs | 2 +- osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 6 +++--- osu.Game/Screens/Select/FilterCriteria.cs | 2 +- osu.Game/Skinning/LegacySkinResourceStore.cs | 2 +- .../Storyboards/Drawables/DrawableStoryboardAnimation.cs | 2 +- osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs | 2 +- 9 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CodeAnalysis/osu.ruleset b/CodeAnalysis/osu.ruleset index 0756adb05c..1aa8f66c93 100644 --- a/CodeAnalysis/osu.ruleset +++ b/CodeAnalysis/osu.ruleset @@ -54,6 +54,7 @@ + \ No newline at end of file diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 4924842e81..f9d71a2a6e 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -42,7 +42,7 @@ namespace osu.Game.Beatmaps } } - private string getPathForFile(string filename) => BeatmapSetInfo.Files.FirstOrDefault(f => string.Equals(f.Filename, filename, StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath; + private string getPathForFile(string filename) => BeatmapSetInfo.Files.FirstOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; private TextureStore textureStore; diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 42865c686c..393bcfdb3c 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -70,6 +70,6 @@ namespace osu.Game.Beatmaps.ControlPoints public override bool EquivalentTo(ControlPoint other) => other is SampleControlPoint otherTyped && - string.Equals(SampleBank, otherTyped.SampleBank) && SampleVolume == otherTyped.SampleVolume; + SampleBank == otherTyped.SampleBank && SampleVolume == otherTyped.SampleVolume; } } diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 3279af05b6..332b3e3f05 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -57,7 +57,7 @@ namespace osu.Game.Scoring } protected override IEnumerable GetStableImportPaths(Storage stableStorage) - => stableStorage.GetFiles(ImportFromStablePath).Where(p => HandledExtensions.Any(ext => Path.GetExtension(p)?.Equals(ext, StringComparison.InvariantCultureIgnoreCase) ?? false)); + => stableStorage.GetFiles(ImportFromStablePath).Where(p => HandledExtensions.Any(ext => Path.GetExtension(p)?.Equals(ext, StringComparison.OrdinalIgnoreCase) ?? false)); public Score GetScore(ScoreInfo score) => new LegacyDatabasedScore(score, rulesets, beatmaps(), Files.Store); diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 35816fe620..301d0d4dae 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -37,13 +37,13 @@ namespace osu.Game.Screens.Select.Carousel { default: case SortMode.Artist: - return string.Compare(BeatmapSet.Metadata.Artist, otherSet.BeatmapSet.Metadata.Artist, StringComparison.InvariantCultureIgnoreCase); + return string.Compare(BeatmapSet.Metadata.Artist, otherSet.BeatmapSet.Metadata.Artist, StringComparison.OrdinalIgnoreCase); case SortMode.Title: - return string.Compare(BeatmapSet.Metadata.Title, otherSet.BeatmapSet.Metadata.Title, StringComparison.InvariantCultureIgnoreCase); + return string.Compare(BeatmapSet.Metadata.Title, otherSet.BeatmapSet.Metadata.Title, StringComparison.OrdinalIgnoreCase); case SortMode.Author: - return string.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username, StringComparison.InvariantCultureIgnoreCase); + return string.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username, StringComparison.OrdinalIgnoreCase); case SortMode.DateAdded: return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded); diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index e3ad76ac35..c4d9996377 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -105,7 +105,7 @@ namespace osu.Game.Screens.Select public string SearchTerm; - public bool Equals(OptionalTextFilter other) => SearchTerm?.Equals(other.SearchTerm) ?? true; + public bool Equals(OptionalTextFilter other) => SearchTerm == other.SearchTerm; } } } diff --git a/osu.Game/Skinning/LegacySkinResourceStore.cs b/osu.Game/Skinning/LegacySkinResourceStore.cs index 79a4e2e932..249d48b34b 100644 --- a/osu.Game/Skinning/LegacySkinResourceStore.cs +++ b/osu.Game/Skinning/LegacySkinResourceStore.cs @@ -34,7 +34,7 @@ namespace osu.Game.Skinning } private string getPathForFile(string filename) => - source.Files.Find(f => string.Equals(f.Filename, filename, StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath; + source.Files.Find(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; public override IEnumerable GetAvailableResources() => source.Files.Select(f => f.Filename); } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index de3077c025..4f8e39fa1b 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -71,7 +71,7 @@ namespace osu.Game.Storyboards.Drawables { var framePath = Animation.Path.Replace(".", frame + "."); - var path = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.Equals(framePath, StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath; + var path = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.Equals(framePath, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; if (path == null) continue; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index 3a117d1713..ff48dab7e5 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -66,7 +66,7 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader] private void load(IBindable beatmap, TextureStore textureStore) { - var path = beatmap.Value.BeatmapSetInfo?.Files?.Find(f => f.Filename.Equals(Sprite.Path, StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath; + var path = beatmap.Value.BeatmapSetInfo?.Files?.Find(f => f.Filename.Equals(Sprite.Path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; if (path == null) return; From 61a6106e5270f692b19fe7c265b990e64254ff73 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 3 Dec 2019 19:20:49 +0800 Subject: [PATCH 4590/5608] CA2200: don't explictly throw caught exception. --- CodeAnalysis/osu.ruleset | 1 - osu.Game/Online/API/APIAccess.cs | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CodeAnalysis/osu.ruleset b/CodeAnalysis/osu.ruleset index 1aa8f66c93..0ec2f24797 100644 --- a/CodeAnalysis/osu.ruleset +++ b/CodeAnalysis/osu.ruleset @@ -38,7 +38,6 @@ - diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 1c45d26afd..8bfc28e774 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -10,6 +10,7 @@ using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json.Linq; using osu.Framework.Bindables; +using osu.Framework.Extensions.ExceptionExtensions; using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Game.Configuration; @@ -249,7 +250,7 @@ namespace osu.Game.Online.API catch { // if we couldn't deserialize the error message let's throw the original exception outwards. - throw e; + e.Rethrow(); } } From 40b43b85f17499d0e772b03ebcaf9b02434f343c Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 10 Dec 2019 21:04:26 +0800 Subject: [PATCH 4591/5608] CA1715: use prefix for generic parameters. --- CodeAnalysis/osu.ruleset | 1 - .../Objects/Drawables/DrawableTaikoHitObject.cs | 8 ++++---- ...MutableDatabaseBackedStoreWithFileIncludes.cs | 6 +++--- .../UserInterfaceV2/LabelledComponent.cs | 6 +++--- osu.Game/IO/Legacy/SerializationReader.cs | 6 +++--- osu.Game/IO/Legacy/SerializationWriter.cs | 4 ++-- osu.Game/Online/Leaderboards/Leaderboard.cs | 10 +++++----- osu.Game/Overlays/OverlayHeaderTabControl.cs | 2 +- osu.Game/Overlays/OverlayTabControl.cs | 8 ++++---- osu.Game/Overlays/Settings/SettingsSlider.cs | 16 ++++++++-------- osu.Game/Overlays/UserProfileOverlay.cs | 2 +- 11 files changed, 34 insertions(+), 35 deletions(-) diff --git a/CodeAnalysis/osu.ruleset b/CodeAnalysis/osu.ruleset index 0ec2f24797..d497365f87 100644 --- a/CodeAnalysis/osu.ruleset +++ b/CodeAnalysis/osu.ruleset @@ -17,7 +17,6 @@ - diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 0db6498c12..2da5a9c403 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -105,19 +105,19 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - public abstract class DrawableTaikoHitObject : DrawableTaikoHitObject - where TaikoHitType : TaikoHitObject + public abstract class DrawableTaikoHitObject : DrawableTaikoHitObject + where TTaikoHit : TaikoHitObject { public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); - public new TaikoHitType HitObject; + public new TTaikoHit HitObject; protected readonly Vector2 BaseSize; protected readonly TaikoPiece MainPiece; private readonly Container strongHitContainer; - protected DrawableTaikoHitObject(TaikoHitType hitObject) + protected DrawableTaikoHitObject(TTaikoHit hitObject) : base(hitObject) { HitObject = hitObject; diff --git a/osu.Game/Database/MutableDatabaseBackedStoreWithFileIncludes.cs b/osu.Game/Database/MutableDatabaseBackedStoreWithFileIncludes.cs index 5d6ff6b09b..102081cd65 100644 --- a/osu.Game/Database/MutableDatabaseBackedStoreWithFileIncludes.cs +++ b/osu.Game/Database/MutableDatabaseBackedStoreWithFileIncludes.cs @@ -7,9 +7,9 @@ using osu.Framework.Platform; namespace osu.Game.Database { - public abstract class MutableDatabaseBackedStoreWithFileIncludes : MutableDatabaseBackedStore - where T : class, IHasPrimaryKey, ISoftDelete, IHasFiles - where U : INamedFileInfo + public abstract class MutableDatabaseBackedStoreWithFileIncludes : MutableDatabaseBackedStore + where T : class, IHasPrimaryKey, ISoftDelete, IHasFiles + where TFileInfo : INamedFileInfo { protected MutableDatabaseBackedStoreWithFileIncludes(IDatabaseContextFactory contextFactory, Storage storage = null) : base(contextFactory, storage) diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs index 1819b36667..dd6a902989 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs @@ -7,15 +7,15 @@ using osu.Framework.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public abstract class LabelledComponent : LabelledDrawable, IHasCurrentValue - where T : Drawable, IHasCurrentValue + public abstract class LabelledComponent : LabelledDrawable, IHasCurrentValue + where TDrawable : Drawable, IHasCurrentValue { protected LabelledComponent(bool padded) : base(padded) { } - public Bindable Current + public Bindable Current { get => Component.Current; set => Component.Current = value; diff --git a/osu.Game/IO/Legacy/SerializationReader.cs b/osu.Game/IO/Legacy/SerializationReader.cs index aeb3ce754d..17cbd19838 100644 --- a/osu.Game/IO/Legacy/SerializationReader.cs +++ b/osu.Game/IO/Legacy/SerializationReader.cs @@ -116,13 +116,13 @@ namespace osu.Game.IO.Legacy } /// Reads a generic Dictionary from the buffer. - public IDictionary ReadDictionary() + public IDictionary ReadDictionary() { int count = ReadInt32(); if (count < 0) return null; - IDictionary d = new Dictionary(); - for (int i = 0; i < count; i++) d[(T)ReadObject()] = (U)ReadObject(); + IDictionary d = new Dictionary(); + for (int i = 0; i < count; i++) d[(TKey)ReadObject()] = (TValue)ReadObject(); return d; } diff --git a/osu.Game/IO/Legacy/SerializationWriter.cs b/osu.Game/IO/Legacy/SerializationWriter.cs index f30e4492af..c75de93bc8 100644 --- a/osu.Game/IO/Legacy/SerializationWriter.cs +++ b/osu.Game/IO/Legacy/SerializationWriter.cs @@ -102,7 +102,7 @@ namespace osu.Game.IO.Legacy } /// Writes a generic IDictionary to the buffer. - public void Write(IDictionary d) + public void Write(IDictionary d) { if (d == null) { @@ -112,7 +112,7 @@ namespace osu.Game.IO.Legacy { Write(d.Count); - foreach (KeyValuePair kvp in d) + foreach (KeyValuePair kvp in d) { WriteObject(kvp.Key); WriteObject(kvp.Value); diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 94c50185da..9c48ebd09b 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Online.Leaderboards { - public abstract class Leaderboard : Container, IOnlineComponent + public abstract class Leaderboard : Container, IOnlineComponent { private const double fade_duration = 300; @@ -39,9 +39,9 @@ namespace osu.Game.Online.Leaderboards protected override Container Content => content; - private IEnumerable scores; + private IEnumerable scores; - public IEnumerable Scores + public IEnumerable Scores { get => scores; set @@ -288,7 +288,7 @@ namespace osu.Game.Online.Leaderboards /// /// A callback which should be called when fetching is completed. Scheduling is not required. /// An responsible for the fetch operation. This will be queued and performed automatically. - protected abstract APIRequest FetchScores(Action> scoresCallback); + protected abstract APIRequest FetchScores(Action> scoresCallback); private Placeholder currentPlaceholder; @@ -359,6 +359,6 @@ namespace osu.Game.Online.Leaderboards } } - protected abstract LeaderboardScore CreateDrawableScore(ScoreInfo model, int index); + protected abstract LeaderboardScore CreateDrawableScore(TScoreInfo model, int index); } } diff --git a/osu.Game/Overlays/OverlayHeaderTabControl.cs b/osu.Game/Overlays/OverlayHeaderTabControl.cs index 5b56771dc1..7d0cdad6d8 100644 --- a/osu.Game/Overlays/OverlayHeaderTabControl.cs +++ b/osu.Game/Overlays/OverlayHeaderTabControl.cs @@ -12,7 +12,7 @@ namespace osu.Game.Overlays AccentColour = AccentColour, }; - private class OverlayHeaderTabItem : OverlayTabItem + private class OverlayHeaderTabItem : OverlayTabItem { public OverlayHeaderTabItem(string value) : base(value) diff --git a/osu.Game/Overlays/OverlayTabControl.cs b/osu.Game/Overlays/OverlayTabControl.cs index 20649c8a74..4c396eabc1 100644 --- a/osu.Game/Overlays/OverlayTabControl.cs +++ b/osu.Game/Overlays/OverlayTabControl.cs @@ -32,7 +32,7 @@ namespace osu.Game.Overlays foreach (TabItem tabItem in TabContainer) { - ((OverlayTabItem)tabItem).AccentColour = value; + ((OverlayTabItem)tabItem).AccentColour = value; } } } @@ -59,9 +59,9 @@ namespace osu.Game.Overlays protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(T value) => new OverlayTabItem(value); + protected override TabItem CreateTabItem(T value) => new OverlayTabItem(value); - protected class OverlayTabItem : TabItem + protected class OverlayTabItem : TabItem { private readonly ExpandingBar bar; @@ -84,7 +84,7 @@ namespace osu.Game.Overlays } } - public OverlayTabItem(U value) + public OverlayTabItem(T value) : base(value) { AutoSizeAxes = Axes.X; diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index 20e08c0cd8..96c0279a7b 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -12,11 +12,11 @@ namespace osu.Game.Overlays.Settings { } - public class SettingsSlider : SettingsItem - where T : struct, IEquatable, IComparable, IConvertible - where U : OsuSliderBar, new() + public class SettingsSlider : SettingsItem + where TValue : struct, IEquatable, IComparable, IConvertible + where TSlider : OsuSliderBar, new() { - protected override Drawable CreateControl() => new U + protected override Drawable CreateControl() => new TSlider { Margin = new MarginPadding { Top = 5, Bottom = 5 }, RelativeSizeAxes = Axes.X @@ -24,14 +24,14 @@ namespace osu.Game.Overlays.Settings public bool TransferValueOnCommit { - get => ((U)Control).TransferValueOnCommit; - set => ((U)Control).TransferValueOnCommit = value; + get => ((TSlider)Control).TransferValueOnCommit; + set => ((TSlider)Control).TransferValueOnCommit = value; } public float KeyboardStep { - get => ((U)Control).KeyboardStep; - set => ((U)Control).KeyboardStep = value; + get => ((TSlider)Control).KeyboardStep; + set => ((TSlider)Control).KeyboardStep = value; } } } diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index b5e7b8bedb..a34fc619a8 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -165,7 +165,7 @@ namespace osu.Game.Overlays AccentColour = colours.Seafoam; } - private class ProfileTabItem : OverlayTabItem + private class ProfileTabItem : OverlayTabItem { public ProfileTabItem(ProfileSection value) : base(value) From 5079feaad16ccd4df3b0e993d4bc7c6705deb686 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Dec 2019 14:04:03 +0900 Subject: [PATCH 4592/5608] Remove unnecessary string interpolation --- osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index d5d4c7e5ec..fede99f450 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -94,7 +94,7 @@ namespace osu.Game.Tests.Visual.Background AddStep("set dim level 0.6", () => userDimContainer.UserDimLevel.Value = test_user_dim); AddUntilStep("dim reached", () => userDimContainer.DimEqual(test_user_dim)); - AddStep($"ignore settings", () => userDimContainer.IgnoreUserSettings.Value = true); + AddStep("ignore settings", () => userDimContainer.IgnoreUserSettings.Value = true); AddUntilStep("no dim", () => userDimContainer.DimEqual(0)); AddStep("set break", () => isBreakTime.Value = true); AddAssert("no dim", () => userDimContainer.DimEqual(0)); From 946a202ee555cc26f12aabca4d9964dea2d99cdf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Dec 2019 15:34:16 +0900 Subject: [PATCH 4593/5608] Fix online replays not being available locally --- osu.Game/Beatmaps/BeatmapManager.cs | 4 +++- osu.Game/Database/DownloadableArchiveModelManager.cs | 6 ++++-- osu.Game/Scoring/ScoreManager.cs | 4 +++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index a2e750cac5..a10ad73817 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -158,7 +158,9 @@ namespace osu.Game.Beatmaps void resetIds() => beatmapSet.Beatmaps.ForEach(b => b.OnlineBeatmapID = null); } - protected override bool CheckLocalAvailability(BeatmapSetInfo model, IQueryable items) => items.Any(b => b.OnlineBeatmapSetID == model.OnlineBeatmapSetID); + protected override bool CheckLocalAvailability(BeatmapSetInfo model, IQueryable items) + => base.CheckLocalAvailability(model, items) + || (model.OnlineBeatmapSetID != null && items.Any(b => b.OnlineBeatmapSetID == model.OnlineBeatmapSetID)); /// /// Delete a beatmap difficulty. diff --git a/osu.Game/Database/DownloadableArchiveModelManager.cs b/osu.Game/Database/DownloadableArchiveModelManager.cs index 243060388f..5f688c149d 100644 --- a/osu.Game/Database/DownloadableArchiveModelManager.cs +++ b/osu.Game/Database/DownloadableArchiveModelManager.cs @@ -33,7 +33,8 @@ namespace osu.Game.Database private readonly MutableDatabaseBackedStoreWithFileIncludes modelStore; - protected DownloadableArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, IAPIProvider api, MutableDatabaseBackedStoreWithFileIncludes modelStore, IIpcHost importHost = null) + protected DownloadableArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, IAPIProvider api, MutableDatabaseBackedStoreWithFileIncludes modelStore, + IIpcHost importHost = null) : base(storage, contextFactory, modelStore, importHost) { this.api = api; @@ -124,7 +125,8 @@ namespace osu.Game.Database /// The whose existence needs to be checked. /// The usable items present in the store. /// Whether the exists. - protected abstract bool CheckLocalAvailability(TModel model, IQueryable items); + protected virtual bool CheckLocalAvailability(TModel model, IQueryable items) + => model.ID > 0 && items.Any(i => i.ID == model.ID && i.Files.Any()); public ArchiveDownloadRequest GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Model.Equals(model)); diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 3279af05b6..5c846e8062 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -69,6 +69,8 @@ namespace osu.Game.Scoring protected override ArchiveDownloadRequest CreateDownloadRequest(ScoreInfo score, bool minimiseDownload) => new DownloadReplayRequest(score); - protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) => items.Any(s => s.Equals(model) && s.Files.Any()); + protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) + => base.CheckLocalAvailability(model, items) + || (model.OnlineScoreID != null && items.Any(i => i.OnlineScoreID == model.OnlineScoreID)); } } From 59c3b39ed8a7ab63fe653ec60a0d9cdf3e4551af Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Dec 2019 15:46:50 +0900 Subject: [PATCH 4594/5608] Add test --- osu.Game.Tests/Scores/IO/ImportScoreTest.cs | 47 ++++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs index 89b5db9e1b..a95e699470 100644 --- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -10,6 +11,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Platform; using osu.Game.Beatmaps; +using osu.Game.IO.Archives; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; @@ -154,7 +156,30 @@ namespace osu.Game.Tests.Scores.IO } } - private async Task loadIntoOsu(OsuGameBase osu, ScoreInfo score) + [Test] + public async Task TestOnlineScoreIsAvailableLocally() + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWithDeletedBeatmapSet")) + { + try + { + var osu = await loadOsu(host); + + await loadIntoOsu(osu, new ScoreInfo { OnlineScoreID = 2 }, new TestArchiveReader()); + + var scoreManager = osu.Dependencies.Get(); + + // Note: A new score reference is used here since the import process mutates the original object to set an ID + Assert.That(scoreManager.IsAvailableLocally(new ScoreInfo { OnlineScoreID = 2 })); + } + finally + { + host.Exit(); + } + } + } + + private async Task loadIntoOsu(OsuGameBase osu, ScoreInfo score, ArchiveReader archive = null) { var beatmapManager = osu.Dependencies.Get(); @@ -165,7 +190,7 @@ namespace osu.Game.Tests.Scores.IO score.Ruleset = new OsuRuleset().RulesetInfo; var scoreManager = osu.Dependencies.Get(); - await scoreManager.Import(score); + await scoreManager.Import(score, archive); return scoreManager.GetAllUsableScores().FirstOrDefault(); } @@ -196,5 +221,23 @@ namespace osu.Game.Tests.Scores.IO Assert.IsTrue(task.Wait(timeout), failureMessage); } + + private class TestArchiveReader : ArchiveReader + { + public TestArchiveReader() + : base("test_archive") + { + } + + public override Stream GetStream(string name) => new MemoryStream(); + + public override void Dispose() + { + } + + public override IEnumerable Filenames => new[] { "test_file.osr" }; + + public override Stream GetUnderlyingStream() => new MemoryStream(); + } } } From 927ba4c1133088a67233a32fd56ccbe670c97500 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 17 Dec 2019 15:20:05 +0800 Subject: [PATCH 4595/5608] Update expected exception in test. --- osu.Game.Tests/NonVisual/LimitedCapacityStackTest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/NonVisual/LimitedCapacityStackTest.cs b/osu.Game.Tests/NonVisual/LimitedCapacityStackTest.cs index 1c78b63499..d5ac38008e 100644 --- a/osu.Game.Tests/NonVisual/LimitedCapacityStackTest.cs +++ b/osu.Game.Tests/NonVisual/LimitedCapacityStackTest.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tests.NonVisual { Assert.AreEqual(0, stack.Count); - Assert.Throws(() => + Assert.Throws(() => { int unused = stack[0]; }); @@ -55,7 +55,7 @@ namespace osu.Game.Tests.NonVisual // e.g. indices 3, 4, 5, 6 (out of range) for (int i = stack.Count; i < stack.Count + capacity; i++) { - Assert.Throws(() => + Assert.Throws(() => { int unused = stack[i]; }); @@ -80,7 +80,7 @@ namespace osu.Game.Tests.NonVisual // e.g. indices 3, 4, 5, 6 (out of range) for (int i = stack.Count; i < stack.Count + capacity; i++) { - Assert.Throws(() => + Assert.Throws(() => { int unused = stack[i]; }); From 6da581f3fe86047762679905ca3ce14bbccb836b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Dec 2019 16:35:40 +0900 Subject: [PATCH 4596/5608] Snap based on end position/time of the previous object --- .../Edit/OsuDistanceSnapGrid.cs | 3 ++- .../Edit/OsuHitObjectComposer.cs | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs index bde86a2890..ff3be97427 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using JetBrains.Annotations; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose.Components; @@ -10,7 +11,7 @@ namespace osu.Game.Rulesets.Osu.Edit public class OsuDistanceSnapGrid : CircularDistanceSnapGrid { public OsuDistanceSnapGrid(OsuHitObject hitObject, [CanBeNull] OsuHitObject nextHitObject = null) - : base(hitObject.StackedPosition, hitObject.StartTime, nextHitObject?.StartTime) + : base(hitObject.StackedEndPosition, hitObject.GetEndTime(), nextHitObject?.StartTime) { Masking = true; } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 675b09fc6d..a2c1a5f5f4 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -92,7 +92,24 @@ namespace osu.Game.Rulesets.Osu.Edit return null; OsuHitObject sourceObject = EditorBeatmap.HitObjects[sourceIndex]; - OsuHitObject targetObject = sourceIndex + targetOffset < EditorBeatmap.HitObjects.Count ? EditorBeatmap.HitObjects[sourceIndex + targetOffset] : null; + + int targetIndex = sourceIndex + targetOffset; + OsuHitObject targetObject = null; + + // Keep advancing the target object while its start time falls before the end time of the source object + while (true) + { + if (targetIndex >= EditorBeatmap.HitObjects.Count) + break; + + if (EditorBeatmap.HitObjects[targetIndex].StartTime >= sourceObject.GetEndTime()) + { + targetObject = EditorBeatmap.HitObjects[targetIndex]; + break; + } + + targetIndex++; + } return new OsuDistanceSnapGrid(sourceObject, targetObject); } From 1e798a8dbe1c31244e52e7ab7d01ec96a5ce76ff Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Dec 2019 17:53:48 +0900 Subject: [PATCH 4597/5608] Add abstract implementation of slider path --- .../Objects/Drawables/DrawableSlider.cs | 2 +- .../Drawables/Pieces/DrawableSliderPath.cs | 70 ++++++++++++++ .../Objects/Drawables/Pieces/SliderBody.cs | 92 ++++--------------- 3 files changed, 88 insertions(+), 76 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DrawableSliderPath.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 1e0402d492..e6ab2e580c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -201,7 +201,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.ApplySkin(skin, allowFallback); - Body.BorderSize = skin.GetConfig(OsuSkinConfiguration.SliderBorderSize)?.Value ?? SliderBody.DEFAULT_BORDER_SIZE; + Body.BorderSize = skin.GetConfig(OsuSkinConfiguration.SliderBorderSize)?.Value ?? 1; sliderPathRadius = skin.GetConfig(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS; updatePathRadius(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DrawableSliderPath.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DrawableSliderPath.cs new file mode 100644 index 0000000000..c31d6beb01 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DrawableSliderPath.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 osu.Framework.Graphics.Lines; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +{ + public abstract class DrawableSliderPath : SmoothPath + { + protected const float BORDER_PORTION = 0.128f; + protected const float GRADIENT_PORTION = 1 - BORDER_PORTION; + + private const float border_max_size = 8f; + private const float border_min_size = 0f; + + private Color4 borderColour = Color4.White; + + public Color4 BorderColour + { + get => borderColour; + set + { + if (borderColour == value) + return; + + borderColour = value; + + InvalidateTexture(); + } + } + + private Color4 accentColour = Color4.White; + + public Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) + return; + + accentColour = value; + + InvalidateTexture(); + } + } + + private float borderSize = 1; + + public float BorderSize + { + get => borderSize; + set + { + if (borderSize == value) + return; + + if (value < border_min_size || value > border_max_size) + return; + + borderSize = value; + + InvalidateTexture(); + } + } + + protected float CalculatedBorderPortion => BorderSize * BORDER_PORTION; + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 24a437c20e..dcaa9748e9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Lines; using osuTK; @@ -12,9 +13,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public abstract class SliderBody : CompositeDrawable { - public const float DEFAULT_BORDER_SIZE = 1; - - private SliderPath path; + private DrawableSliderPath path; protected Path Path => path; @@ -80,19 +79,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } /// - /// Initialises a new , releasing all resources retained by the old one. + /// Initialises a new , releasing all resources retained by the old one. /// public virtual void RecyclePath() { - InternalChild = path = new SliderPath + InternalChild = path = CreateSliderPath().With(p => { - Position = path?.Position ?? Vector2.Zero, - PathRadius = path?.PathRadius ?? 10, - AccentColour = path?.AccentColour ?? Color4.White, - BorderColour = path?.BorderColour ?? Color4.White, - BorderSize = path?.BorderSize ?? DEFAULT_BORDER_SIZE, - Vertices = path?.Vertices ?? Array.Empty() - }; + p.Position = path?.Position ?? Vector2.Zero; + p.PathRadius = path?.PathRadius ?? 10; + p.AccentColour = path?.AccentColour ?? Color4.White; + p.BorderColour = path?.BorderColour ?? Color4.White; + p.BorderSize = path?.BorderSize ?? 1; + p.Vertices = path?.Vertices ?? Array.Empty(); + }); } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => path.ReceivePositionalInputAt(screenSpacePos); @@ -103,77 +102,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces /// The vertices protected void SetVertices(IReadOnlyList vertices) => path.Vertices = vertices; - private class SliderPath : SmoothPath + protected virtual DrawableSliderPath CreateSliderPath() => new DefaultDrawableSliderPath(); + + protected class DefaultDrawableSliderPath : DrawableSliderPath { - private const float border_max_size = 8f; - private const float border_min_size = 0f; - - private const float border_portion = 0.128f; - private const float gradient_portion = 1 - border_portion; - private const float opacity_at_centre = 0.3f; private const float opacity_at_edge = 0.8f; - private Color4 borderColour = Color4.White; - - public Color4 BorderColour - { - get => borderColour; - set - { - if (borderColour == value) - return; - - borderColour = value; - - InvalidateTexture(); - } - } - - private Color4 accentColour = Color4.White; - - public Color4 AccentColour - { - get => accentColour; - set - { - if (accentColour == value) - return; - - accentColour = value; - - InvalidateTexture(); - } - } - - private float borderSize = DEFAULT_BORDER_SIZE; - - public float BorderSize - { - get => borderSize; - set - { - if (borderSize == value) - return; - - if (value < border_min_size || value > border_max_size) - return; - - borderSize = value; - - InvalidateTexture(); - } - } - - private float calculatedBorderPortion => BorderSize * border_portion; - protected override Color4 ColourAt(float position) { - if (calculatedBorderPortion != 0f && position <= calculatedBorderPortion) + if (CalculatedBorderPortion != 0f && position <= CalculatedBorderPortion) return BorderColour; - position -= calculatedBorderPortion; - return new Color4(AccentColour.R, AccentColour.G, AccentColour.B, (opacity_at_edge - (opacity_at_edge - opacity_at_centre) * position / gradient_portion) * AccentColour.A); + position -= CalculatedBorderPortion; + return new Color4(AccentColour.R, AccentColour.G, AccentColour.B, (opacity_at_edge - (opacity_at_edge - opacity_at_centre) * position / GRADIENT_PORTION) * AccentColour.A); } } } From 8cd96acffc2e3f3fe61062983804da1a4db33ff9 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 17 Dec 2019 12:05:35 +0300 Subject: [PATCH 4598/5608] CounterPill implementation --- .../Online/TestSceneProfileCounterPill.cs | 42 +++++++++++++ .../Overlays/Profile/Sections/CounterPill.cs | 61 +++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneProfileCounterPill.cs create mode 100644 osu.Game/Overlays/Profile/Sections/CounterPill.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneProfileCounterPill.cs b/osu.Game.Tests/Visual/Online/TestSceneProfileCounterPill.cs new file mode 100644 index 0000000000..468239cf08 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneProfileCounterPill.cs @@ -0,0 +1,42 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Overlays.Profile.Sections; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneProfileCounterPill : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(CounterPill) + }; + + private readonly CounterPill pill; + private readonly BindableInt value = new BindableInt(); + + public TestSceneProfileCounterPill() + { + Child = pill = new CounterPill + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = value } + }; + } + + [Test] + public void TestVisibility() + { + AddStep("Set value to 0", () => value.Value = 0); + AddAssert("Check hidden", () => !pill.IsPresent); + AddStep("Set value to 10", () => value.Value = 10); + AddAssert("Check visible", () => pill.IsPresent); + } + } +} diff --git a/osu.Game/Overlays/Profile/Sections/CounterPill.cs b/osu.Game/Overlays/Profile/Sections/CounterPill.cs new file mode 100644 index 0000000000..bd760c4139 --- /dev/null +++ b/osu.Game/Overlays/Profile/Sections/CounterPill.cs @@ -0,0 +1,61 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Framework.Bindables; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Overlays.Profile.Sections +{ + public class CounterPill : CircularContainer + { + private const int duration = 200; + + public readonly BindableInt Current = new BindableInt(); + + private readonly OsuSpriteText counter; + + public CounterPill() + { + AutoSizeAxes = Axes.Both; + Alpha = 0; + Masking = true; + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.05f) + }, + counter = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Current.BindValueChanged(onCurrentChanged, true); + } + + private void onCurrentChanged(ValueChangedEvent value) + { + if (value.NewValue == 0) + { + this.FadeOut(duration, Easing.OutQuint); + return; + } + + counter.Text = value.NewValue.ToString(); + this.FadeIn(duration, Easing.OutQuint); + } + } +} From 9caed9e98a25993d6984eb74d541c9e3ad1c6012 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Dec 2019 18:16:25 +0900 Subject: [PATCH 4599/5608] Add legacy slider body support --- .../Objects/Drawables/DrawableSlider.cs | 6 ++- .../Drawables/Pieces/SnakingSliderBody.cs | 12 ++--- osu.Game.Rulesets.Osu/OsuSkinComponents.cs | 3 +- .../Skinning/LegacySliderBody.cs | 47 +++++++++++++++++++ .../Skinning/OsuLegacySkinTransformer.cs | 6 +++ 5 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index e6ab2e580c..46a219a69c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -24,9 +24,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public DrawableSliderHead HeadCircle => headContainer.Child; public DrawableSliderTail TailCircle => tailContainer.Child; - public readonly SnakingSliderBody Body; public readonly SliderBall Ball; + public SnakingSliderBody Body => (SnakingSliderBody)skinnedBody.Drawable; + + private readonly SkinnableDrawable skinnedBody; private readonly Container headContainer; private readonly Container tailContainer; private readonly Container tickContainer; @@ -51,7 +53,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables InternalChildren = new Drawable[] { - Body = new SnakingSliderBody(s), + skinnedBody = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBody), _ => new SnakingSliderBody(), confineMode: ConfineMode.NoScaling), tickContainer = new Container { RelativeSizeAxes = Axes.Both }, repeatContainer = new Container { RelativeSizeAxes = Axes.Both }, Ball = new SliderBall(s, this) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index f2150280b3..8a8668d6af 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osuTK; @@ -50,16 +51,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces /// private Vector2 snakedPathOffset; - private readonly Slider slider; - - public SnakingSliderBody(Slider slider) - { - this.slider = slider; - } + private Slider slider; [BackgroundDependencyLoader] - private void load() + private void load(DrawableHitObject drawableObject) { + slider = (Slider)drawableObject.HitObject; + Refresh(); } diff --git a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs index 8dd48eace0..4ea4220faf 100644 --- a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs +++ b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs @@ -14,6 +14,7 @@ namespace osu.Game.Rulesets.Osu ReverseArrow, HitCircleText, SliderFollowCircle, - SliderBall + SliderBall, + SliderBody, } } diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs new file mode 100644 index 0000000000..6a26529f4c --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs @@ -0,0 +1,47 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.MathUtils; +using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Skinning +{ + public class LegacySliderBody : SnakingSliderBody + { + protected override DrawableSliderPath CreateSliderPath() => new LegacyDrawableSliderPath(); + + private class LegacyDrawableSliderPath : DrawableSliderPath + { + public new Color4 AccentColour => new Color4(base.AccentColour.R, base.AccentColour.G, base.AccentColour.B, 0.70f); + + protected override Color4 ColourAt(float position) + { + if (CalculatedBorderPortion != 0f && position <= CalculatedBorderPortion) + return BorderColour; + + position -= BORDER_PORTION; + + Color4 outerColour = AccentColour.Darken(0.1f); + Color4 innerColour = lighten(AccentColour, 0.5f); + + return Interpolation.ValueAt(position / GRADIENT_PORTION, outerColour, innerColour, 0, 1); + } + + /// + /// Lightens a colour in a way more friendly to dark or strong colours. + /// + private static Color4 lighten(Color4 color, float amount) + { + amount *= 0.5f; + return new Color4( + Math.Min(1, color.R * (1 + 0.5f * amount) + 1 * amount), + Math.Min(1, color.G * (1 + 0.5f * amount) + 1 * amount), + Math.Min(1, color.B * (1 + 0.5f * amount) + 1 * amount), + color.A); + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index f5b7d9166f..71770dedce 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -73,6 +73,12 @@ namespace osu.Game.Rulesets.Osu.Skinning return null; + case OsuSkinComponents.SliderBody: + if (hasHitCircle.Value) + return new LegacySliderBody(); + + return null; + case OsuSkinComponents.HitCircle: if (hasHitCircle.Value) return new LegacyMainCirclePiece(); From 023892738af69c35902c39c43945906fb0b284ea Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 17 Dec 2019 12:36:44 +0300 Subject: [PATCH 4600/5608] Integration into overlay --- .../Beatmaps/PaginatedBeatmapContainer.cs | 22 +++++++++++++++ .../Profile/Sections/PaginatedContainer.cs | 28 +++++++++++++++++-- .../Sections/Ranks/PaginatedScoreContainer.cs | 12 ++++++++ osu.Game/Users/User.cs | 18 ++++++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 919f8a2fa0..6684420cf4 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -38,5 +38,27 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }; + + protected override int GetCount(User user) + { + switch (type) + { + default: + case BeatmapSetType.Favourite: + return user.FavouriteBeatmapsetCount; + + case BeatmapSetType.Graveyard: + return user.GraveyardBeatmapsetCount; + + case BeatmapSetType.Loved: + return user.LovedBeatmapsetCount; + + case BeatmapSetType.RankedAndApproved: + return user.RankedAndApprovedBeatmapsetCount; + + case BeatmapSetType.Unranked: + return user.UnrankedBeatmapsetCount; + } + } } } diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index dc1a847b14..94d5f99f86 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -23,6 +23,7 @@ namespace osu.Game.Overlays.Profile.Sections private readonly OsuSpriteText missingText; private APIRequest> retrievalRequest; private CancellationTokenSource loadCancellation; + private readonly BindableInt count = new BindableInt(); [Resolved] private IAPIProvider api { get; set; } @@ -44,11 +45,28 @@ namespace osu.Game.Overlays.Profile.Sections Children = new Drawable[] { - new OsuSpriteText + new FillFlowContainer { - Text = header, - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), Margin = new MarginPadding { Top = 10, Bottom = 10 }, + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = header, + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold), + }, + new CounterPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Current = { BindTarget = count } + } + } }, ItemsContainer = new FillFlowContainer { @@ -90,6 +108,8 @@ namespace osu.Game.Overlays.Profile.Sections VisiblePages = 0; ItemsContainer.Clear(); + count.Value = GetCount(e.NewValue); + if (e.NewValue != null) showMore(); } @@ -124,6 +144,8 @@ namespace osu.Game.Overlays.Profile.Sections }, loadCancellation.Token); }); + protected virtual int GetCount(User user) => 0; + protected abstract APIRequest> CreateRequest(); protected abstract Drawable CreateDrawableItem(TModel model); diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 5b58fc0930..fa74d76dfc 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -32,6 +32,18 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks protected override APIRequest> CreateRequest() => new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); + protected override int GetCount(User user) + { + switch (type) + { + default: + return 0; + + case ScoreType.Firsts: + return user.ScoresFirstCount; + } + } + protected override Drawable CreateDrawableItem(APILegacyScoreInfo model) { switch (type) diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index b15789f324..ebd9dbecd1 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -126,6 +126,24 @@ namespace osu.Game.Users [JsonProperty(@"follower_count")] public int FollowerCount; + [JsonProperty(@"favourite_beatmapset_count")] + public int FavouriteBeatmapsetCount; + + [JsonProperty(@"graveyard_beatmapset_count")] + public int GraveyardBeatmapsetCount; + + [JsonProperty(@"loved_beatmapset_count")] + public int LovedBeatmapsetCount; + + [JsonProperty(@"ranked_and_approved_beatmapset_count")] + public int RankedAndApprovedBeatmapsetCount; + + [JsonProperty(@"unranked_beatmapset_count")] + public int UnrankedBeatmapsetCount; + + [JsonProperty(@"scores_first_count")] + public int ScoresFirstCount; + [JsonProperty] private string[] playstyle { From bc9177983adc209fa185cbf549de01bcbab77222 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 17 Dec 2019 12:50:50 +0300 Subject: [PATCH 4601/5608] Fix possible null --- osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 94d5f99f86..a30ff786fb 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -108,10 +108,11 @@ namespace osu.Game.Overlays.Profile.Sections VisiblePages = 0; ItemsContainer.Clear(); - count.Value = GetCount(e.NewValue); - if (e.NewValue != null) + { showMore(); + count.Value = GetCount(e.NewValue); + } } private void showMore() From 7c2884700eaffe391e37fa79a80deb3a30a431aa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Dec 2019 19:29:27 +0900 Subject: [PATCH 4602/5608] Fix various display issues by abstracting further --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 5 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 3 +- .../Objects/Drawables/DrawableSlider.cs | 52 +++++------------ .../Drawables/Pieces/PlaySliderBody.cs | 57 +++++++++++++++++++ .../Objects/Drawables/Pieces/SliderBody.cs | 2 +- .../Skinning/LegacySliderBody.cs | 2 +- 6 files changed, 78 insertions(+), 43 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/PlaySliderBody.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 7e20feba02..0cca3ae40c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -11,6 +11,7 @@ using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; namespace osu.Game.Rulesets.Osu.Mods { @@ -57,8 +58,8 @@ namespace osu.Game.Rulesets.Osu.Mods slider.AccentColour.BindValueChanged(_ => { //will trigger on skin change. - slider.Body.AccentColour = slider.AccentColour.Value.Opacity(0); - slider.Body.BorderColour = slider.AccentColour.Value; + ((PlaySliderBody)slider.Body.Drawable).AccentColour = slider.AccentColour.Value.Opacity(0); + ((PlaySliderBody)slider.Body.Drawable).BorderColour = slider.AccentColour.Value; }, true); break; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 71cb9a9691..b81d94a673 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osu.Game.Rulesets.Scoring; using osuTK; using osu.Game.Skinning; @@ -98,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public void UpdateSnakingPosition(Vector2 start, Vector2 end) { bool isRepeatAtEnd = repeatPoint.RepeatIndex % 2 == 0; - List curve = drawableSlider.Body.CurrentCurve; + List curve = ((PlaySliderBody)drawableSlider.Body.Drawable).CurrentCurve; Position = isRepeatAtEnd ? end : start; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 46a219a69c..03183beff1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -11,7 +11,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Skinning; using osu.Game.Rulesets.Scoring; using osuTK.Graphics; @@ -25,10 +24,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public DrawableSliderTail TailCircle => tailContainer.Child; public readonly SliderBall Ball; + public readonly SkinnableDrawable Body; - public SnakingSliderBody Body => (SnakingSliderBody)skinnedBody.Drawable; + private PlaySliderBody sliderBody => (PlaySliderBody)Body.Drawable; - private readonly SkinnableDrawable skinnedBody; private readonly Container headContainer; private readonly Container tailContainer; private readonly Container tickContainer; @@ -39,10 +38,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly IBindable positionBindable = new Bindable(); private readonly IBindable stackHeightBindable = new Bindable(); private readonly IBindable scaleBindable = new Bindable(); - private readonly IBindable pathVersion = new Bindable(); - - [Resolved(CanBeNull = true)] - private OsuRulesetConfigManager config { get; set; } public DrawableSlider(Slider s) : base(s) @@ -53,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables InternalChildren = new Drawable[] { - skinnedBody = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBody), _ => new SnakingSliderBody(), confineMode: ConfineMode.NoScaling), + Body = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBody), _ => new DefaultSliderBody(), confineMode: ConfineMode.NoScaling), tickContainer = new Container { RelativeSizeAxes = Axes.Both }, repeatContainer = new Container { RelativeSizeAxes = Axes.Both }, Ball = new SliderBall(s, this) @@ -72,28 +67,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables [BackgroundDependencyLoader] private void load() { - config?.BindWith(OsuRulesetSetting.SnakingInSliders, Body.SnakingIn); - config?.BindWith(OsuRulesetSetting.SnakingOutSliders, Body.SnakingOut); - positionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); stackHeightBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); - scaleBindable.BindValueChanged(scale => - { - updatePathRadius(); - Ball.Scale = new Vector2(scale.NewValue); - }); + scaleBindable.BindValueChanged(scale => Ball.Scale = new Vector2(scale.NewValue)); positionBindable.BindTo(HitObject.PositionBindable); stackHeightBindable.BindTo(HitObject.StackHeightBindable); scaleBindable.BindTo(HitObject.ScaleBindable); - pathVersion.BindTo(slider.Path.Version); - - pathVersion.BindValueChanged(_ => Body.Refresh()); AccentColour.BindValueChanged(colour => { - Body.AccentColour = colour.NewValue; - foreach (var drawableHitObject in NestedHitObjects) drawableHitObject.AccentColour.Value = colour.NewValue; }, true); @@ -171,16 +154,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); Ball.UpdateProgress(completionProgress); - Body.UpdateProgress(completionProgress); + sliderBody.UpdateProgress(completionProgress); foreach (DrawableHitObject hitObject in NestedHitObjects) { - if (hitObject is ITrackSnaking s) s.UpdateSnakingPosition(slider.Path.PositionAt(Body.SnakedStart ?? 0), slider.Path.PositionAt(Body.SnakedEnd ?? 0)); + if (hitObject is ITrackSnaking s) s.UpdateSnakingPosition(slider.Path.PositionAt(sliderBody.SnakedStart ?? 0), slider.Path.PositionAt(sliderBody.SnakedEnd ?? 0)); if (hitObject is IRequireTracking t) t.Tracking = Ball.Tracking; } - Size = Body.Size; - OriginPosition = Body.PathOffset; + Size = sliderBody.Size; + OriginPosition = sliderBody.PathOffset; if (DrawSize != Vector2.Zero) { @@ -194,28 +177,17 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public override void OnKilled() { base.OnKilled(); - Body.RecyclePath(); + sliderBody.RecyclePath(); } - private float sliderPathRadius; - protected override void ApplySkin(ISkinSource skin, bool allowFallback) { base.ApplySkin(skin, allowFallback); - Body.BorderSize = skin.GetConfig(OsuSkinConfiguration.SliderBorderSize)?.Value ?? 1; - sliderPathRadius = skin.GetConfig(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS; - updatePathRadius(); - - Body.AccentColour = skin.GetConfig(OsuSkinColour.SliderTrackOverride)?.Value ?? AccentColour.Value; - Body.BorderColour = skin.GetConfig(OsuSkinColour.SliderBorder)?.Value ?? Color4.White; - bool allowBallTint = skin.GetConfig(OsuSkinConfiguration.AllowSliderBallTint)?.Value ?? false; Ball.Colour = allowBallTint ? AccentColour.Value : Color4.White; } - private void updatePathRadius() => Body.PathRadius = slider.Scale * sliderPathRadius; - protected override void CheckForResult(bool userTriggered, double timeOffset) { if (userTriggered || Time.Current < slider.EndTime) @@ -266,6 +238,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public Drawable ProxiedLayer => HeadCircle.ProxiedLayer; - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Body.ReceivePositionalInputAt(screenSpacePos); + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => sliderBody.ReceivePositionalInputAt(screenSpacePos); + + private class DefaultSliderBody : PlaySliderBody + { + } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/PlaySliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/PlaySliderBody.cs new file mode 100644 index 0000000000..aa9caf193e --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/PlaySliderBody.cs @@ -0,0 +1,57 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Configuration; +using osu.Game.Rulesets.Osu.Skinning; +using osu.Game.Skinning; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +{ + public abstract class PlaySliderBody : SnakingSliderBody + { + private IBindable scaleBindable; + private IBindable pathVersion; + private IBindable accentColour; + + [Resolved] + private DrawableHitObject drawableObject { get; set; } + + [Resolved(CanBeNull = true)] + private OsuRulesetConfigManager config { get; set; } + + private Slider slider; + private float defaultPathRadius; + + [BackgroundDependencyLoader] + private void load(ISkinSource skin) + { + slider = (Slider)drawableObject.HitObject; + defaultPathRadius = skin.GetConfig(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS; + + scaleBindable = slider.ScaleBindable.GetBoundCopy(); + scaleBindable.BindValueChanged(_ => updatePathRadius(), true); + + pathVersion = slider.Path.Version.GetBoundCopy(); + pathVersion.BindValueChanged(_ => Refresh()); + + accentColour = drawableObject.AccentColour.GetBoundCopy(); + accentColour.BindValueChanged(accent => updateAccentColour(skin, accent.NewValue), true); + + config?.BindWith(OsuRulesetSetting.SnakingInSliders, SnakingIn); + config?.BindWith(OsuRulesetSetting.SnakingOutSliders, SnakingOut); + + BorderSize = skin.GetConfig(OsuSkinConfiguration.SliderBorderSize)?.Value ?? 1; + BorderColour = skin.GetConfig(OsuSkinColour.SliderBorder)?.Value ?? Color4.White; + } + + private void updatePathRadius() + => PathRadius = defaultPathRadius * scaleBindable.Value; + + private void updateAccentColour(ISkinSource skin, Color4 defaultAccentColour) + => AccentColour = skin.GetConfig(OsuSkinColour.SliderTrackOverride)?.Value ?? defaultAccentColour; + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index dcaa9748e9..8758a4a066 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces protected virtual DrawableSliderPath CreateSliderPath() => new DefaultDrawableSliderPath(); - protected class DefaultDrawableSliderPath : DrawableSliderPath + private class DefaultDrawableSliderPath : DrawableSliderPath { private const float opacity_at_centre = 0.3f; private const float opacity_at_edge = 0.8f; diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs index 6a26529f4c..18a5d7a320 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs @@ -9,7 +9,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning { - public class LegacySliderBody : SnakingSliderBody + public class LegacySliderBody : PlaySliderBody { protected override DrawableSliderPath CreateSliderPath() => new LegacyDrawableSliderPath(); From f6cde911e2b4a13e57acb84863d9b524668c2985 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 17 Dec 2019 13:41:28 +0300 Subject: [PATCH 4603/5608] Use switch expressions --- .../Beatmaps/PaginatedBeatmapContainer.cs | 28 ++++++------------- .../Sections/Ranks/PaginatedScoreContainer.cs | 14 +++------- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 6684420cf4..fcd12e2b54 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -39,26 +39,14 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps Origin = Anchor.TopCentre, }; - protected override int GetCount(User user) + protected override int GetCount(User user) => type switch { - switch (type) - { - default: - case BeatmapSetType.Favourite: - return user.FavouriteBeatmapsetCount; - - case BeatmapSetType.Graveyard: - return user.GraveyardBeatmapsetCount; - - case BeatmapSetType.Loved: - return user.LovedBeatmapsetCount; - - case BeatmapSetType.RankedAndApproved: - return user.RankedAndApprovedBeatmapsetCount; - - case BeatmapSetType.Unranked: - return user.UnrankedBeatmapsetCount; - } - } + BeatmapSetType.Favourite => user.FavouriteBeatmapsetCount, + BeatmapSetType.Graveyard => user.GraveyardBeatmapsetCount, + BeatmapSetType.Loved => user.LovedBeatmapsetCount, + BeatmapSetType.RankedAndApproved => user.RankedAndApprovedBeatmapsetCount, + BeatmapSetType.Unranked => user.UnrankedBeatmapsetCount, + _ => 0 + }; } } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index fa74d76dfc..e0f1c935da 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -32,17 +32,11 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks protected override APIRequest> CreateRequest() => new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); - protected override int GetCount(User user) + protected override int GetCount(User user) => type switch { - switch (type) - { - default: - return 0; - - case ScoreType.Firsts: - return user.ScoresFirstCount; - } - } + ScoreType.Firsts => user.ScoresFirstCount, + _ => 0 + }; protected override Drawable CreateDrawableItem(APILegacyScoreInfo model) { From 527ab1a72f08ce6c3c5eef7226ec166c9fb726b1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Dec 2019 19:49:13 +0900 Subject: [PATCH 4604/5608] Fix traceable mod not working on skin change --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 15 ++++++++------- osu.Game/Skinning/SkinReloadableDrawable.cs | 15 ++++++++++++++- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 0cca3ae40c..cf1ce517e8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -55,13 +55,8 @@ namespace osu.Game.Rulesets.Osu.Mods break; case DrawableSlider slider: - slider.AccentColour.BindValueChanged(_ => - { - //will trigger on skin change. - ((PlaySliderBody)slider.Body.Drawable).AccentColour = slider.AccentColour.Value.Opacity(0); - ((PlaySliderBody)slider.Body.Drawable).BorderColour = slider.AccentColour.Value; - }, true); - + slider.Body.OnSkinChanged += () => applySliderState(slider); + applySliderState(slider); break; case DrawableSpinner spinner: @@ -70,5 +65,11 @@ namespace osu.Game.Rulesets.Osu.Mods break; } } + + private void applySliderState(DrawableSlider slider) + { + ((PlaySliderBody)slider.Body.Drawable).AccentColour = slider.AccentColour.Value.Opacity(0); + ((PlaySliderBody)slider.Body.Drawable).BorderColour = slider.AccentColour.Value; + } } } diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index 6d0b22dd51..4a1aaa62bf 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -12,6 +12,11 @@ namespace osu.Game.Skinning /// public abstract class SkinReloadableDrawable : CompositeDrawable { + /// + /// Invoked when has changed. + /// + public event Action OnSkinChanged; + /// /// The current skin source. /// @@ -43,12 +48,18 @@ namespace osu.Game.Skinning private void onChange() => // schedule required to avoid calls after disposed. // note that this has the side-effect of components only performing a skin change when they are alive. - Scheduler.AddOnce(() => SkinChanged(CurrentSkin, allowDefaultFallback)); + Scheduler.AddOnce(skinChanged); protected override void LoadAsyncComplete() { base.LoadAsyncComplete(); + skinChanged(); + } + + private void skinChanged() + { SkinChanged(CurrentSkin, allowDefaultFallback); + OnSkinChanged?.Invoke(); } /// @@ -66,6 +77,8 @@ namespace osu.Game.Skinning if (CurrentSkin != null) CurrentSkin.SourceChanged -= onChange; + + OnSkinChanged = null; } } } From 2d85145eeccde1868c1fb843c852450e37c2abf7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Dec 2019 19:52:33 +0900 Subject: [PATCH 4605/5608] Make legacy accent colour multiplicative --- osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs index 18a5d7a320..dea08f843e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Osu.Skinning private class LegacyDrawableSliderPath : DrawableSliderPath { - public new Color4 AccentColour => new Color4(base.AccentColour.R, base.AccentColour.G, base.AccentColour.B, 0.70f); + public new Color4 AccentColour => new Color4(base.AccentColour.R, base.AccentColour.G, base.AccentColour.B, base.AccentColour.A * 0.70f); protected override Color4 ColourAt(float position) { From 49bf8d27d10ad2ceaf9feefe737b2f60ce2dffdd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Dec 2019 20:08:13 +0900 Subject: [PATCH 4606/5608] Move CreateScoreProcessor() to Ruleset --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 5 +++++ osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs | 4 ---- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 6 ++++++ osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 4 ---- osu.Game.Rulesets.Osu/OsuRuleset.cs | 6 ++++++ osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs | 4 ---- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 5 +++++ osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs | 4 ---- osu.Game/Rulesets/Ruleset.cs | 7 +++++++ osu.Game/Rulesets/UI/DrawableRuleset.cs | 9 --------- osu.Game/Screens/Play/Player.cs | 2 +- 11 files changed, 30 insertions(+), 26 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 9fe287d1cc..ba5c1dee92 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -16,7 +16,9 @@ using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Difficulty; +using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; namespace osu.Game.Rulesets.Catch @@ -24,6 +26,9 @@ namespace osu.Game.Rulesets.Catch public class CatchRuleset : Ruleset { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableCatchRuleset(this, beatmap, mods); + + public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new CatchScoreProcessor(beatmap); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index 278ff97195..fdd820b891 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -10,10 +10,8 @@ using osu.Game.Replays; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.Replays; -using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; @@ -32,8 +30,6 @@ namespace osu.Game.Rulesets.Catch.UI TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450); } - public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(Beatmap); - protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay); protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty, CreateDrawableRepresentation); diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index bcafadb4c5..dc98a063b4 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -25,6 +25,8 @@ using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Difficulty; using osu.Game.Rulesets.Mania.Edit; +using osu.Game.Rulesets.Mania.Scoring; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; namespace osu.Game.Rulesets.Mania @@ -32,7 +34,11 @@ namespace osu.Game.Rulesets.Mania public class ManiaRuleset : Ruleset { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableManiaRuleset(this, beatmap, mods); + + public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new ManiaScoreProcessor(beatmap); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); + public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score); public const string SHORT_NAME = "mania"; diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index cf1970c28b..2c497541a8 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -14,11 +14,9 @@ using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Replays; -using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osuTK; @@ -67,8 +65,6 @@ namespace osu.Game.Rulesets.Mania.UI protected override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages); - public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(Beatmap); - public override int Variant => (int)(Beatmap.Stages.Count == 1 ? PlayfieldType.Single : PlayfieldType.Dual) + Beatmap.TotalColumns; protected override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, Variant); diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index beaa788229..ff08d97385 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -23,7 +23,9 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Difficulty; +using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Osu.Skinning; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Skinning; @@ -32,7 +34,11 @@ namespace osu.Game.Rulesets.Osu public class OsuRuleset : Ruleset { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableOsuRuleset(this, beatmap, mods); + + public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new OsuScoreProcessor(beatmap); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap); + public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap); public const string SHORT_NAME = "osu"; diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index 039d38e4fd..a37ef8d9a0 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -14,8 +14,6 @@ using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Replays; -using osu.Game.Rulesets.Osu.Scoring; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using osuTK; @@ -33,8 +31,6 @@ namespace osu.Game.Rulesets.Osu.UI public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; // always show the gameplay cursor - public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(Beatmap); - protected override Playfield CreatePlayfield() => new OsuPlayfield(); protected override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo); diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 68e6a3b07e..59ce715a1f 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -15,8 +15,10 @@ using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Difficulty; +using osu.Game.Rulesets.Taiko.Scoring; using osu.Game.Scoring; namespace osu.Game.Rulesets.Taiko @@ -24,6 +26,9 @@ namespace osu.Game.Rulesets.Taiko public class TaikoRuleset : Ruleset { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableTaikoRuleset(this, beatmap, mods); + + public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new TaikoScoreProcessor(beatmap); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); public const string SHORT_NAME = "taiko"; diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index 2233658428..0c7495aa52 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -5,10 +5,8 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; -using osu.Game.Rulesets.Taiko.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Taiko.Replays; using osu.Framework.Input; @@ -40,8 +38,6 @@ namespace osu.Game.Rulesets.Taiko.UI new BarLineGenerator(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar.Major ? new DrawableBarLineMajor(bar) : new DrawableBarLine(bar))); } - public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(Beatmap); - public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new TaikoPlayfieldAdjustmentContainer(); protected override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo); diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 45aa904b98..cfe04fc6d1 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -18,6 +18,7 @@ using osu.Game.Beatmaps.Legacy; using osu.Game.Configuration; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Skinning; @@ -62,6 +63,12 @@ namespace osu.Game.Rulesets /// public abstract DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null); + /// + /// Creates a for a beatmap converted to this ruleset. + /// + /// The score processor. + public virtual ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new ScoreProcessor(beatmap); + /// /// Creates a to convert a to one that is applicable for this . /// diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 5033fd0686..4ff8ce9e0a 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -305,8 +305,6 @@ namespace osu.Game.Rulesets.UI /// The Playfield. protected abstract Playfield CreatePlayfield(); - public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(Beatmap); - /// /// Applies the active mods to this DrawableRuleset. /// @@ -475,13 +473,6 @@ namespace osu.Game.Rulesets.UI /// Invoked when the user requests to pause while the resume overlay is active. /// public abstract void CancelResume(); - - /// - /// Create a for the associated ruleset and link with this - /// . - /// - /// A score processor. - public abstract ScoreProcessor CreateScoreProcessor(); } public class BeatmapInvalidForRulesetException : ArgumentException diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fa320e9a4f..5dfdeb5ebc 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -128,7 +128,7 @@ namespace osu.Game.Screens.Play DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value); - ScoreProcessor = DrawableRuleset.CreateScoreProcessor(); + ScoreProcessor = ruleset.CreateScoreProcessor(playableBeatmap); ScoreProcessor.Mods.BindTo(Mods); if (!ScoreProcessor.Mode.Disabled) From 35276c37399e9fbfcc0b16c88eb4448760e16470 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Dec 2019 21:26:23 +0900 Subject: [PATCH 4607/5608] Prevent test scene failures through casting softly --- .../Objects/Drawables/DrawableSlider.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 03183beff1..cd3c572ba0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public readonly SliderBall Ball; public readonly SkinnableDrawable Body; - private PlaySliderBody sliderBody => (PlaySliderBody)Body.Drawable; + private PlaySliderBody sliderBody => Body.Drawable as PlaySliderBody; private readonly Container headContainer; private readonly Container tailContainer; @@ -154,16 +154,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); Ball.UpdateProgress(completionProgress); - sliderBody.UpdateProgress(completionProgress); + sliderBody?.UpdateProgress(completionProgress); foreach (DrawableHitObject hitObject in NestedHitObjects) { - if (hitObject is ITrackSnaking s) s.UpdateSnakingPosition(slider.Path.PositionAt(sliderBody.SnakedStart ?? 0), slider.Path.PositionAt(sliderBody.SnakedEnd ?? 0)); + if (hitObject is ITrackSnaking s) s.UpdateSnakingPosition(slider.Path.PositionAt(sliderBody?.SnakedStart ?? 0), slider.Path.PositionAt(sliderBody?.SnakedEnd ?? 0)); if (hitObject is IRequireTracking t) t.Tracking = Ball.Tracking; } - Size = sliderBody.Size; - OriginPosition = sliderBody.PathOffset; + Size = sliderBody?.Size ?? Vector2.Zero; + OriginPosition = sliderBody?.PathOffset ?? Vector2.Zero; if (DrawSize != Vector2.Zero) { @@ -177,7 +177,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public override void OnKilled() { base.OnKilled(); - sliderBody.RecyclePath(); + sliderBody?.RecyclePath(); } protected override void ApplySkin(ISkinSource skin, bool allowFallback) @@ -238,7 +238,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public Drawable ProxiedLayer => HeadCircle.ProxiedLayer; - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => sliderBody.ReceivePositionalInputAt(screenSpacePos); + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => sliderBody?.ReceivePositionalInputAt(screenSpacePos) ?? base.ReceivePositionalInputAt(screenSpacePos); private class DefaultSliderBody : PlaySliderBody { From 69da6ed9a16438aa6b9fe034ee127879b4d66c00 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Dec 2019 23:53:18 +0900 Subject: [PATCH 4608/5608] Fix test re-using the same storage --- osu.Game.Tests/Scores/IO/ImportScoreTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs index a95e699470..a139c3a8c2 100644 --- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs @@ -159,7 +159,7 @@ namespace osu.Game.Tests.Scores.IO [Test] public async Task TestOnlineScoreIsAvailableLocally() { - using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWithDeletedBeatmapSet")) + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestOnlineScoreIsAvailableLocally")) { try { From bcc19e29f2c2d41621025c9708cf976fce370a55 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Dec 2019 02:56:29 +0900 Subject: [PATCH 4609/5608] Fix editor crashing after re-ordering objects --- osu.Game/Rulesets/UI/HitObjectContainer.cs | 36 ++++++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index 9485189433..b7508a82f3 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; @@ -14,13 +15,42 @@ namespace osu.Game.Rulesets.UI public IEnumerable Objects => InternalChildren.Cast().OrderBy(h => h.HitObject.StartTime); public IEnumerable AliveObjects => AliveInternalChildren.Cast().OrderBy(h => h.HitObject.StartTime); + private readonly Dictionary bindable, double timeAtAdd)> startTimeMap = new Dictionary, double)>(); + public HitObjectContainer() { RelativeSizeAxes = Axes.Both; } - public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject); - public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject); + public virtual void Add(DrawableHitObject hitObject) + { + // Added first for the comparer to remain ordered during AddInternal + startTimeMap[hitObject] = (hitObject.HitObject.StartTimeBindable.GetBoundCopy(), hitObject.HitObject.StartTime); + startTimeMap[hitObject].bindable.BindValueChanged(_ => onStartTimeChanged(hitObject)); + + AddInternal(hitObject); + } + + public virtual bool Remove(DrawableHitObject hitObject) + { + bool result = RemoveInternal(hitObject); + + // Removed last for the comparer to remain ordered during RemoveInternal + startTimeMap[hitObject].bindable.UnbindAll(); + startTimeMap.Remove(hitObject); + + return result; + } + + private void onStartTimeChanged(DrawableHitObject hitObject) + { + if (!RemoveInternal(hitObject)) + return; + + // Update the stored time, preserving the existing bindable + startTimeMap[hitObject] = (startTimeMap[hitObject].bindable, hitObject.HitObject.StartTime); + AddInternal(hitObject); + } protected override int Compare(Drawable x, Drawable y) { @@ -28,7 +58,7 @@ namespace osu.Game.Rulesets.UI return base.Compare(x, y); // Put earlier hitobjects towards the end of the list, so they handle input first - int i = yObj.HitObject.StartTime.CompareTo(xObj.HitObject.StartTime); + int i = startTimeMap[yObj].timeAtAdd.CompareTo(startTimeMap[xObj].timeAtAdd); return i == 0 ? CompareReverseChildID(x, y) : i; } From 0a278ef9432d06ab6ae6f94be332296c5eba9e6f Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 14 Dec 2019 11:40:59 +0100 Subject: [PATCH 4610/5608] Apply review suggestions --- osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs | 2 +- osu.Game/Overlays/News/NewsArticleCover.cs | 6 ++---- osu.Game/Overlays/NewsOverlay.cs | 8 ++++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index f870a12fc3..a8e1f40ecf 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.Online private class TestNewsOverlay : NewsOverlay { - public new void LoadAndShowChild(NewsContent content) => base.LoadAndShowChild(content); + public new void LoadAndShowChild(NewsContent content) => base.LoadAndShowContent(content); } private class NewsCoverTest : NewsContent diff --git a/osu.Game/Overlays/News/NewsArticleCover.cs b/osu.Game/Overlays/News/NewsArticleCover.cs index e2485bd170..e484309a18 100644 --- a/osu.Game/Overlays/News/NewsArticleCover.cs +++ b/osu.Game/Overlays/News/NewsArticleCover.cs @@ -90,7 +90,6 @@ namespace osu.Game.Overlays.News bg.OnLoadComplete += d => d.FadeIn(250, Easing.In); } - //news article cover background [LongRunningLoad] private class NewsBackground : Sprite { @@ -108,7 +107,6 @@ namespace osu.Game.Overlays.News } } - //date container private class DateContainer : Container, IHasTooltip { private readonly DateTime date; @@ -134,7 +132,7 @@ namespace osu.Game.Overlays.News Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(Typeface.Exo, 12, FontWeight.Black, false, false), - Text = date.ToString("dd MMM yyy"), + Text = date.ToString("d MMM yyy").ToUpper(), Margin = new MarginPadding { Vertical = 4, @@ -144,7 +142,7 @@ namespace osu.Game.Overlays.News }; } - public string TooltipText => date.ToString("dddd dd MMMM yyyy hh:mm:ss UTCz"); + public string TooltipText => date.ToString("dddd dd MMMM yyyy hh:mm:ss UTCz").ToUpper(); } //fake API data struct to use for now as a skeleton for data, as there is no API struct for news article info for now diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index db4b118bf8..e7471cb21d 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -59,19 +59,19 @@ namespace osu.Game.Overlays Current.TriggerChange(); } - private CancellationTokenSource loadChildCancellation; + private CancellationTokenSource loadContentCancellation; - protected void LoadAndShowChild(NewsContent newContent) + protected void LoadAndShowContent(NewsContent newContent) { content.FadeTo(0.2f, 300, Easing.OutQuint); - loadChildCancellation?.Cancel(); + loadContentCancellation?.Cancel(); LoadComponentAsync(newContent, c => { content.Child = c; content.FadeIn(300, Easing.OutQuint); - }, (loadChildCancellation = new CancellationTokenSource()).Token); + }, (loadContentCancellation = new CancellationTokenSource()).Token); } public void ShowFrontPage() From ad7923f9b9edf87dfd6bd1acedaa44fad9f234be Mon Sep 17 00:00:00 2001 From: Lucas A Date: Tue, 17 Dec 2019 19:25:17 +0100 Subject: [PATCH 4611/5608] Fix test methods not being renamed. --- osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index a8e1f40ecf..d47c972564 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -22,12 +22,12 @@ namespace osu.Game.Tests.Visual.Online AddStep(@"Show front page", () => news.ShowFrontPage()); AddStep(@"Custom article", () => news.Current.Value = "Test Article 101"); - AddStep(@"Article covers", () => news.LoadAndShowChild(new NewsCoverTest())); + AddStep(@"Article covers", () => news.LoadAndShowContent(new NewsCoverTest())); } private class TestNewsOverlay : NewsOverlay { - public new void LoadAndShowChild(NewsContent content) => base.LoadAndShowContent(content); + public new void LoadAndShowContent(NewsContent content) => base.LoadAndShowContent(content); } private class NewsCoverTest : NewsContent From 8aeef3f59a59747e42bc898cb155048204143ff0 Mon Sep 17 00:00:00 2001 From: wltu Date: Tue, 17 Dec 2019 12:56:30 -0800 Subject: [PATCH 4612/5608] Added refresh scoreboard upon deleting local score and formatted the code --- .../Online/Leaderboards/LeaderboardScore.cs | 17 +++++++++++++---- .../Screens/Select/BeatmapClearScoresDialog.cs | 6 +----- .../Select/Leaderboards/BeatmapLeaderboard.cs | 10 +++++++--- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 3e5096b051..ccac748535 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -54,9 +55,11 @@ namespace osu.Game.Online.Leaderboards private FillFlowContainer modsContainer; private List statisticsLabels; - + private DialogOverlay dialogOverlay; + public Action RefreshAction { get; set; } + public LeaderboardScore(ScoreInfo score, int rank, bool allowHighlight = true) { this.score = score; @@ -367,9 +370,15 @@ namespace osu.Game.Online.Leaderboards } } - public MenuItem[] ContextMenuItems => new MenuItem[] + public MenuItem[] ContextMenuItems { - new OsuMenuItem("Delete", MenuItemType.Destructive, () => dialogOverlay?.Push(new BeatmapClearScoresDialog(this.score, null))) - }; + get + { + return (this.allowHighlight) ? null : new MenuItem[] + { + new OsuMenuItem("Delete", MenuItemType.Destructive, () => dialogOverlay?.Push(new BeatmapClearScoresDialog(this.score, () => Schedule(this.RefreshAction)))) + }; + } + } } } diff --git a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs index b4889bfffc..2c5427993b 100644 --- a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs +++ b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs @@ -52,11 +52,7 @@ namespace osu.Game.Screens.Select new PopupDialogOkButton { Text = @"Yes. Please.", - Action = () => - { - Task.Run(() => scoreManager.Delete(score)) - .ContinueWith(_ => onCompletion); - } + Action = (() => scoreManager.Delete(score)) + onCompletion }, new PopupDialogCancelButton { diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index d609ee3bdc..ee360d1e57 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -15,6 +15,8 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; +using osu.Framework.Graphics.UserInterface; + namespace osu.Game.Screens.Select.Leaderboards { public class BeatmapLeaderboard : Leaderboard @@ -182,12 +184,14 @@ namespace osu.Game.Screens.Select.Leaderboards return req; } - protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index){ + protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) + { model.Beatmap = beatmap; - + return new LeaderboardScore(model, index, IsOnlineScope) { - Action = () => ScoreSelected?.Invoke(model) + Action = () => ScoreSelected?.Invoke(model), + RefreshAction = () => this.RefreshScores() }; } } From 4646524bf9ff4a3f3923f3a77af9a9fb5f0b08d6 Mon Sep 17 00:00:00 2001 From: wltu Date: Tue, 17 Dec 2019 13:18:20 -0800 Subject: [PATCH 4613/5608] Remove unnecessary library --- osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index ee360d1e57..8747bc2d28 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -15,8 +15,6 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; -using osu.Framework.Graphics.UserInterface; - namespace osu.Game.Screens.Select.Leaderboards { public class BeatmapLeaderboard : Leaderboard From 7e58b4a948c1d4fb3b1b50e4df01b315917afe77 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Dec 2019 03:03:12 +0300 Subject: [PATCH 4614/5608] Early-return on potential division by zero in SPM calculation --- .../Objects/Drawables/Pieces/SpinnerSpmCounter.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs index b1d90c49f6..97a7b98c5b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.MathUtils; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -62,6 +63,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public void SetRotation(float currentRotation) { + // Never calculate SPM by same time of record to avoid 0 / 0 = NaN or X / 0 = Infinity result. + if (Precision.AlmostEquals(0, Time.Elapsed)) + return; + // If we've gone back in time, it's fine to work with a fresh set of records for now if (records.Count > 0 && Time.Current < records.Last().Time) records.Clear(); @@ -71,6 +76,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces var record = records.Peek(); while (records.Count > 0 && Time.Current - records.Peek().Time > spm_count_duration) record = records.Dequeue(); + SpinsPerMinute = (currentRotation - record.Rotation) / (Time.Current - record.Time) * 1000 * 60 / 360; } From cbfbbf9999be5dfb60a36ebad95c9d29f292b8f8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Dec 2019 03:04:37 +0300 Subject: [PATCH 4615/5608] Make SpmCounter public --- .../Objects/Drawables/DrawableSpinner.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 1261d3d19a..de11ab6419 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public readonly SpinnerDisc Disc; public readonly SpinnerTicks Ticks; - private readonly SpinnerSpmCounter spmCounter; + public readonly SpinnerSpmCounter SpmCounter; private readonly Container mainContainer; @@ -110,7 +110,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, } }, - spmCounter = new SpinnerSpmCounter + SpmCounter = new SpinnerSpmCounter { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -177,8 +177,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void Update() { Disc.Tracking = OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false; - if (!spmCounter.IsPresent && Disc.Tracking) - spmCounter.FadeIn(HitObject.TimeFadeIn); + if (!SpmCounter.IsPresent && Disc.Tracking) + SpmCounter.FadeIn(HitObject.TimeFadeIn); base.Update(); } @@ -189,7 +189,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circle.Rotation = Disc.Rotation; Ticks.Rotation = Disc.Rotation; - spmCounter.SetRotation(Disc.RotationAbsolute); + SpmCounter.SetRotation(Disc.RotationAbsolute); float relativeCircleScale = Spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight; Disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint); From 12a02cf6d927e583c6cba57142beda24f7bef041 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Dec 2019 03:07:06 +0300 Subject: [PATCH 4616/5608] Extend spinner duration a bit To allow the times sought to be in the spinner time range --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index d0ce0c33c2..ea42251a69 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -84,7 +84,7 @@ namespace osu.Game.Rulesets.Osu.Tests new Spinner { Position = new Vector2(256, 192), - EndTime = 5000, + EndTime = 6000, }, // placeholder object to avoid hitting the results screen new HitObject From f359a79b7ec5d12b9ec8aa2b71e31c86039ab2ad Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Dec 2019 03:08:05 +0300 Subject: [PATCH 4617/5608] Add test ensuring correct SPM calculation on rewinding --- .../TestSceneSpinnerRotation.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index ea42251a69..2eda555018 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -70,6 +70,19 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("is rotation absolute almost same", () => Precision.AlmostEquals(drawableSpinner.Disc.RotationAbsolute, estimatedRotation, 100)); } + [Test] + public void TestSpinPerMinuteOnRewind() + { + double estimatedSpm = 0; + + addSeekStep(2500); + AddStep("retrieve spm", () => estimatedSpm = drawableSpinner.SpmCounter.SpinsPerMinute); + + addSeekStep(5000); + addSeekStep(2500); + AddAssert("is spm almost same", () => Precision.AlmostEquals(drawableSpinner.SpmCounter.SpinsPerMinute, estimatedSpm, 1.0)); + } + private void addSeekStep(double time) { AddStep($"seek to {time}", () => track.Seek(time)); From df8f8ffd0d3fc699b9a0dee2e3aa698231227afe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Dec 2019 12:03:15 +0900 Subject: [PATCH 4618/5608] Fix potential exception during removal --- osu.Game/Rulesets/UI/HitObjectContainer.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index b7508a82f3..1e33b15184 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -33,13 +33,14 @@ namespace osu.Game.Rulesets.UI public virtual bool Remove(DrawableHitObject hitObject) { - bool result = RemoveInternal(hitObject); + if (!RemoveInternal(hitObject)) + return false; // Removed last for the comparer to remain ordered during RemoveInternal startTimeMap[hitObject].bindable.UnbindAll(); startTimeMap.Remove(hitObject); - return result; + return true; } private void onStartTimeChanged(DrawableHitObject hitObject) From 0f5ef78b69c552545e5cc7dfc9b6a91bd2afafb7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 12:39:50 +0900 Subject: [PATCH 4619/5608] Update client id --- osu.Desktop/DiscordRichPresenceClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/DiscordRichPresenceClient.cs b/osu.Desktop/DiscordRichPresenceClient.cs index af5b42b275..7a661fe6a2 100644 --- a/osu.Desktop/DiscordRichPresenceClient.cs +++ b/osu.Desktop/DiscordRichPresenceClient.cs @@ -16,7 +16,7 @@ namespace osu.Desktop { internal class DiscordRichPresenceClient : Component { - private const string client_id = "563024054391537674"; + private const string client_id = "367827983903490050"; private Bindable user; From 1fe0e45a9cf4e3c1de1deab229aadce365008d26 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Dec 2019 13:37:37 +0900 Subject: [PATCH 4620/5608] Implement legacy slider border shadow --- .../Objects/Drawables/Pieces/PlaySliderBody.cs | 7 +------ osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs | 14 +++++++++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/PlaySliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/PlaySliderBody.cs index aa9caf193e..cedf2f6e09 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/PlaySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/PlaySliderBody.cs @@ -24,16 +24,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private OsuRulesetConfigManager config { get; set; } private Slider slider; - private float defaultPathRadius; [BackgroundDependencyLoader] private void load(ISkinSource skin) { slider = (Slider)drawableObject.HitObject; - defaultPathRadius = skin.GetConfig(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS; scaleBindable = slider.ScaleBindable.GetBoundCopy(); - scaleBindable.BindValueChanged(_ => updatePathRadius(), true); + scaleBindable.BindValueChanged(scale => PathRadius = OsuHitObject.OBJECT_RADIUS * scale.NewValue, true); pathVersion = slider.Path.Version.GetBoundCopy(); pathVersion.BindValueChanged(_ => Refresh()); @@ -48,9 +46,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces BorderColour = skin.GetConfig(OsuSkinColour.SliderBorder)?.Value ?? Color4.White; } - private void updatePathRadius() - => PathRadius = defaultPathRadius * scaleBindable.Value; - private void updateAccentColour(ISkinSource skin, Color4 defaultAccentColour) => AccentColour = skin.GetConfig(OsuSkinColour.SliderTrackOverride)?.Value ?? defaultAccentColour; } diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs index dea08f843e..8fc07d2c9d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs @@ -15,19 +15,27 @@ namespace osu.Game.Rulesets.Osu.Skinning private class LegacyDrawableSliderPath : DrawableSliderPath { + private const float shadow_portion = 0.06f; + public new Color4 AccentColour => new Color4(base.AccentColour.R, base.AccentColour.G, base.AccentColour.B, base.AccentColour.A * 0.70f); protected override Color4 ColourAt(float position) { - if (CalculatedBorderPortion != 0f && position <= CalculatedBorderPortion) + float realBorderPortion = shadow_portion + CalculatedBorderPortion; + float realGradientPortion = 1 - realBorderPortion; + + if (position <= shadow_portion) + return new Color4(0f, 0f, 0f, 0.25f * position / shadow_portion); + + if (position <= realBorderPortion) return BorderColour; - position -= BORDER_PORTION; + position -= realBorderPortion; Color4 outerColour = AccentColour.Darken(0.1f); Color4 innerColour = lighten(AccentColour, 0.5f); - return Interpolation.ValueAt(position / GRADIENT_PORTION, outerColour, innerColour, 0, 1); + return Interpolation.ValueAt(position / realGradientPortion, outerColour, innerColour, 0, 1); } /// From 756d847ad8c848ac24800fd4436ef31fbf261d59 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 14:07:03 +0900 Subject: [PATCH 4621/5608] Fix user not getting an initial status --- osu.Game/Online/API/APIAccess.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 8bfc28e774..23c931d161 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -153,6 +153,10 @@ namespace osu.Game.Online.API userReq.Success += u => { LocalUser.Value = u; + + // todo: save/pull from settings + LocalUser.Value.Status.Value = new UserStatusOnline(); + failureCount = 0; //we're connected! From 2f5b27e97c11d122be488e2dbb4ff5dee349e4e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 14:07:12 +0900 Subject: [PATCH 4622/5608] Make user bindables readonly --- osu.Game/Users/User.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index ebd9dbecd1..5d0ffd5a67 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -26,9 +26,9 @@ namespace osu.Game.Users [JsonProperty(@"country")] public Country Country; - public Bindable Status = new Bindable(); + public readonly Bindable Status = new Bindable(); - public IBindable Activity = new Bindable(); + public readonly Bindable Activity = new Bindable(); //public Team Team; From f53fd6e4bcfce9b22eb692c223bdf0cb30332e09 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 14:07:21 +0900 Subject: [PATCH 4623/5608] Fix status capitalisation --- osu.Game/Users/UserActivity.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 918c547978..8030fc55a2 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -62,7 +62,7 @@ namespace osu.Game.Users public class InLobby : UserActivity { - public override string Status => @"In a Multiplayer Lobby"; + public override string Status => @"In a multiplayer lobby"; } } } From 0a3d339dd91a6d18f23e1bf7097aec50fe8a65a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 14:07:32 +0900 Subject: [PATCH 4624/5608] Load discord RPC asynchronously --- osu.Desktop/OsuGameDesktop.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 9f2a4b12a1..f70cc24159 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -61,7 +61,7 @@ namespace osu.Desktop Add(new SimpleUpdateManager()); } - Add(new DiscordRichPresenceClient()); + LoadComponentAsync(new DiscordRichPresence(), Add); } protected override void ScreenChanged(IScreen lastScreen, IScreen newScreen) From b65847b0d76bd3fffb629176e0a33cdb34764c40 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 14:07:53 +0900 Subject: [PATCH 4625/5608] Refactor / rewrite discord code --- osu.Desktop/DiscordRichPresence.cs | 120 +++++++++++++++++++++++ osu.Desktop/DiscordRichPresenceClient.cs | 104 -------------------- 2 files changed, 120 insertions(+), 104 deletions(-) create mode 100644 osu.Desktop/DiscordRichPresence.cs delete mode 100644 osu.Desktop/DiscordRichPresenceClient.cs diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs new file mode 100644 index 0000000000..d1bd8fd292 --- /dev/null +++ b/osu.Desktop/DiscordRichPresence.cs @@ -0,0 +1,120 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using DiscordRPC; +using DiscordRPC.Message; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Logging; +using osu.Game.Online.API; +using osu.Game.Rulesets; +using osu.Game.Users; +using LogLevel = osu.Framework.Logging.LogLevel; +using User = osu.Game.Users.User; + +namespace osu.Desktop +{ + internal class DiscordRichPresence : Component + { + private const string client_id = "367827983903490050"; + + private DiscordRpcClient client; + + [Resolved] + private IBindable ruleset { get; set; } + + private Bindable user; + + private readonly IBindable status = new Bindable(); + private readonly IBindable activity = new Bindable(); + + private readonly RichPresence presence = new RichPresence + { + Assets = new Assets { LargeImageKey = "osu_logo_lazer", } + }; + + [BackgroundDependencyLoader] + private void load(IAPIProvider provider) + { + client = new DiscordRpcClient(client_id) + { + SkipIdenticalPresence = false // handles better on discord IPC loss, see updateStatus call in onReady. + }; + + client.OnReady += onReady; + client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network, LogLevel.Error); + client.OnConnectionFailed += (_, e) => Logger.Log($"An connection occurred with Discord RPC Client: {e.Type}", LoggingTarget.Network, LogLevel.Error); + + (user = provider.LocalUser.GetBoundCopy()).BindValueChanged(u => + { + status.UnbindBindings(); + status.BindTo(u.NewValue.Status); + + activity.UnbindBindings(); + activity.BindTo(u.NewValue.Activity); + }, true); + + ruleset.BindValueChanged(_ => updateStatus()); + status.BindValueChanged(_ => updateStatus()); + activity.BindValueChanged(_ => updateStatus()); + + client.Initialize(); + } + + private void onReady(object _, ReadyMessage __) + { + Logger.Log("Discord RPC Client ready.", LoggingTarget.Network, LogLevel.Debug); + updateStatus(); + } + + private void updateStatus() + { + if (status.Value is UserStatusOffline) + { + client.ClearPresence(); + return; + } + + if (status.Value is UserStatusOnline && activity.Value != null) + { + presence.State = activity.Value.Status; + presence.Details = getDetails(activity.Value); + } + else + { + presence.State = "Idle"; + presence.Details = string.Empty; + } + + // update user information + presence.Assets.LargeImageText = $"{user.Value.Username}" + (user.Value.Statistics?.Ranks.Global > 0 ? $" (rank #{user.Value.Statistics.Ranks.Global:N0})" : string.Empty); + + // update ruleset + presence.Assets.SmallImageKey = ruleset.Value.ID <= 3 ? $"mode_{ruleset.Value.ID}" : "mode_unknown"; + presence.Assets.SmallImageText = ruleset.Value.Name; + + client.SetPresence(presence); + } + + private string getDetails(UserActivity activity) + { + switch (activity) + { + case UserActivity.SoloGame solo: + return solo.Beatmap.ToString(); + + case UserActivity.Editing edit: + return edit.Beatmap.ToString(); + } + + return string.Empty; + } + + protected override void Dispose(bool isDisposing) + { + client.Dispose(); + base.Dispose(isDisposing); + } + } +} diff --git a/osu.Desktop/DiscordRichPresenceClient.cs b/osu.Desktop/DiscordRichPresenceClient.cs deleted file mode 100644 index 7a661fe6a2..0000000000 --- a/osu.Desktop/DiscordRichPresenceClient.cs +++ /dev/null @@ -1,104 +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 DiscordRPC; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Logging; -using osu.Game.Online.API; -using osu.Game.Rulesets; -using osu.Game.Users; -using static osu.Game.Users.UserActivity; -using User = osu.Game.Users.User; - -namespace osu.Desktop -{ - internal class DiscordRichPresenceClient : Component - { - private const string client_id = "367827983903490050"; - - private Bindable user; - - private readonly DiscordRpcClient client = new DiscordRpcClient(client_id); - - [BackgroundDependencyLoader] - private void load(IAPIProvider provider) - { - user = provider.LocalUser.GetBoundCopy(); - - user.ValueChanged += usr => - { - usr.NewValue.Activity.ValueChanged += activity => updateStatus(user.Value.Status.Value, activity.NewValue); - usr.NewValue.Status.ValueChanged += status => updateStatus(status.NewValue, user.Value.Activity.Value); - }; - - user.TriggerChange(); - - enableLogging(); - - client.Initialize(); - } - - private void enableLogging() - { - client.OnReady += (_, __) => Logger.Log("Discord RPC Client ready.", LoggingTarget.Network, LogLevel.Debug); - client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client : {e.Message}", LoggingTarget.Network, LogLevel.Debug); - client.OnConnectionFailed += (_, e) => Logger.Log("Discord RPC Client failed to initialize : is discord running ?", LoggingTarget.Network, LogLevel.Debug); - client.OnPresenceUpdate += (_, __) => Logger.Log("Updated Discord Rich Presence", LoggingTarget.Network, LogLevel.Debug); - } - - private void updateStatus(UserStatus st, UserActivity a) - { - var presence = defaultPresence(st is UserStatusOnline ? a?.Status ?? st.Message : st.Message); //display the current user activity if the user status is online & user activity != null, else display the current user online status - - if (!(st is UserStatusOnline)) //don't update the presence any further if the current user status is DND / Offline & simply return with the default presence - { - client.SetPresence(presence); - return; - } - - switch (a) - { - case SoloGame game: - presence.State = $"{game.Beatmap.Metadata.Artist} - {game.Beatmap.Metadata.Title} [{game.Beatmap.Version}]"; - setPresenceGamemode(game.Ruleset, presence); - break; - - case Editing editing: - presence.State = $"{editing.Beatmap.Metadata.Artist} - {editing.Beatmap.Metadata.Title} " + (!string.IsNullOrEmpty(editing.Beatmap.Version) ? $"[{editing.Beatmap.Version}]" : ""); - presence.Assets.SmallImageKey = "edit"; - presence.Assets.SmallImageText = "editing"; - break; - } - - client.SetPresence(presence); - } - - private void setPresenceGamemode(RulesetInfo ruleset, RichPresence presence) - { - if (ruleset.ID != null && ruleset.ID <= 3) //legacy rulesets use an ID between 0 and 3 - presence.Assets.SmallImageKey = ruleset.ShortName; - else - presence.Assets.SmallImageKey = "unknown"; //not a legacy ruleset so let's display the unknown ruleset icon. - - presence.Assets.SmallImageText = ruleset.ShortName; - } - - private RichPresence defaultPresence(string status) => new RichPresence - { - Details = status, - Assets = new Assets - { - LargeImageKey = "lazer", - LargeImageText = user.Value.Username - } - }; - - protected override void Dispose(bool isDisposing) - { - client.Dispose(); - base.Dispose(isDisposing); - } - } -} From 0710e5ba13749212b158f008ecc9c2b5987b3ca8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 14:35:18 +0900 Subject: [PATCH 4626/5608] Rename unknown mode assets (discord dev page broken) --- osu.Desktop/DiscordRichPresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index d1bd8fd292..b53ca6161b 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -91,7 +91,7 @@ namespace osu.Desktop presence.Assets.LargeImageText = $"{user.Value.Username}" + (user.Value.Statistics?.Ranks.Global > 0 ? $" (rank #{user.Value.Statistics.Ranks.Global:N0})" : string.Empty); // update ruleset - presence.Assets.SmallImageKey = ruleset.Value.ID <= 3 ? $"mode_{ruleset.Value.ID}" : "mode_unknown"; + presence.Assets.SmallImageKey = ruleset.Value.ID <= 3 ? $"mode_{ruleset.Value.ID}" : "mode_custom"; presence.Assets.SmallImageText = ruleset.Value.Name; client.SetPresence(presence); From 6e0802e50cfdfe0cb1010a64ca1f1a1fbaff7dba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 14:49:09 +0900 Subject: [PATCH 4627/5608] Remove RulesetInfo parameter from Ruleset constructor --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 5 ----- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 5 ----- osu.Game.Rulesets.Osu/OsuRuleset.cs | 5 ----- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 5 ----- .../Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs | 5 ----- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 7 +------ osu.Game/Rulesets/Ruleset.cs | 4 ++-- osu.Game/Rulesets/RulesetInfo.cs | 2 +- osu.Game/Rulesets/RulesetStore.cs | 4 ++-- 9 files changed, 6 insertions(+), 36 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 065771bc4a..b8a844cb86 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -137,10 +137,5 @@ namespace osu.Game.Rulesets.Catch public override int? LegacyID => 2; public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new CatchReplayFrame(); - - public CatchRuleset(RulesetInfo rulesetInfo = null) - : base(rulesetInfo) - { - } } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 8b53ce01f6..bf630cf892 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -186,11 +186,6 @@ namespace osu.Game.Rulesets.Mania public override RulesetSettingsSubsection CreateSettings() => new ManiaSettingsSubsection(this); - public ManiaRuleset(RulesetInfo rulesetInfo = null) - : base(rulesetInfo) - { - } - public override IEnumerable AvailableVariants { get diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 835ae2564c..27af615935 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -183,10 +183,5 @@ namespace osu.Game.Rulesets.Osu public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new OsuReplayFrame(); public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new OsuRulesetConfigManager(settings, RulesetInfo); - - public OsuRuleset(RulesetInfo rulesetInfo = null) - : base(rulesetInfo) - { - } } } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 4d6c5fa1c0..ca7ab30867 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -136,10 +136,5 @@ namespace osu.Game.Rulesets.Taiko public override int? LegacyID => 1; public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new TaikoReplayFrame(); - - public TaikoRuleset(RulesetInfo rulesetInfo = null) - : base(rulesetInfo) - { - } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index c958932730..ae20bbc86d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -194,11 +194,6 @@ namespace osu.Game.Tests.Visual.Gameplay private class TestScrollingRuleset : Ruleset { - public TestScrollingRuleset(RulesetInfo rulesetInfo = null) - : base(rulesetInfo) - { - } - public override IEnumerable GetModsFor(ModType type) => throw new NotImplementedException(); public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new TestDrawableScrollingRuleset(this, beatmap, mods); diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 9ea254b23f..46efe38d37 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -51,7 +51,7 @@ namespace osu.Game.Beatmaps private class DummyRulesetInfo : RulesetInfo { - public override Ruleset CreateInstance() => new DummyRuleset(this); + public override Ruleset CreateInstance() => new DummyRuleset(); private class DummyRuleset : Ruleset { @@ -70,11 +70,6 @@ namespace osu.Game.Beatmaps public override string ShortName => "dummy"; - public DummyRuleset(RulesetInfo rulesetInfo = null) - : base(rulesetInfo) - { - } - private class DummyBeatmapConverter : IBeatmapConverter { public event Action> ObjectConverted; diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 6f5fe066aa..7ad93379f0 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -49,9 +49,9 @@ namespace osu.Game.Rulesets public virtual ISkin CreateLegacySkinProvider(ISkinSource source) => null; - protected Ruleset(RulesetInfo rulesetInfo = null) + protected Ruleset() { - RulesetInfo = rulesetInfo ?? createRulesetInfo(); + RulesetInfo = createRulesetInfo(); } /// diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 6a69fd8dd0..d695e0b56d 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets { if (!Available) return null; - return (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo), this); + return (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo)); } public bool Equals(RulesetInfo other) => other != null && ID == other.ID && Available == other.Available && Name == other.Name && InstantiationInfo == other.InstantiationInfo; diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 7d13afe9e5..5d0c5c7ccf 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets { var context = usage.Context; - var instances = loadedAssemblies.Values.Select(r => (Ruleset)Activator.CreateInstance(r, (RulesetInfo)null)).ToList(); + var instances = loadedAssemblies.Values.Select(r => (Ruleset)Activator.CreateInstance(r)).ToList(); //add all legacy modes in correct order foreach (var r in instances.Where(r => r.LegacyID != null).OrderBy(r => r.LegacyID)) @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets // this allows for debug builds to successfully load rulesets (even though debug rulesets have a 0.0.0 version). asm.Version = null; return Assembly.Load(asm); - }, null), (RulesetInfo)null)).RulesetInfo; + }, null))).RulesetInfo; r.Name = instanceInfo.Name; r.ShortName = instanceInfo.ShortName; From 826b271371188a64d9e9e6660fbe2d23af254ca6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 15:39:36 +0900 Subject: [PATCH 4628/5608] Use exact ratio of legacy to default object size --- osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs | 3 ++- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs index 8fc07d2c9d..d41135ca69 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.MathUtils; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osuTK.Graphics; @@ -15,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Skinning private class LegacyDrawableSliderPath : DrawableSliderPath { - private const float shadow_portion = 0.06f; + private const float shadow_portion = 1 - (OsuLegacySkinTransformer.LEGACY_CIRCLE_RADIUS / OsuHitObject.OBJECT_RADIUS); public new Color4 AccentColour => new Color4(base.AccentColour.R, base.AccentColour.G, base.AccentColour.B, base.AccentColour.A * 0.70f); diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 71770dedce..266b619334 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Skinning /// Their hittable area is 128px, but the actual circle portion is 118px. /// We must account for some gameplay elements such as slider bodies, where this padding is not present. /// - private const float legacy_circle_radius = 64 - 5; + public const float LEGACY_CIRCLE_RADIUS = 64 - 5; public OsuLegacySkinTransformer(ISkinSource source) { @@ -130,7 +130,7 @@ namespace osu.Game.Rulesets.Osu.Skinning { case OsuSkinConfiguration.SliderPathRadius: if (hasHitCircle.Value) - return SkinUtils.As(new BindableFloat(legacy_circle_radius)); + return SkinUtils.As(new BindableFloat(LEGACY_CIRCLE_RADIUS)); break; } From d4a4efb734f8799337525c767d01e3825083d897 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 16:07:14 +0900 Subject: [PATCH 4629/5608] Tidy up test --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index 2eda555018..02ce77e707 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -79,8 +79,10 @@ namespace osu.Game.Rulesets.Osu.Tests AddStep("retrieve spm", () => estimatedSpm = drawableSpinner.SpmCounter.SpinsPerMinute); addSeekStep(5000); + AddAssert("spm still valid", () => Precision.AlmostEquals(drawableSpinner.SpmCounter.SpinsPerMinute, estimatedSpm, 1.0)); + addSeekStep(2500); - AddAssert("is spm almost same", () => Precision.AlmostEquals(drawableSpinner.SpmCounter.SpinsPerMinute, estimatedSpm, 1.0)); + AddAssert("spm still valid", () => Precision.AlmostEquals(drawableSpinner.SpmCounter.SpinsPerMinute, estimatedSpm, 1.0)); } private void addSeekStep(double time) From 54572b6de9e685e96168ff36263103437684ede9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 16:42:18 +0900 Subject: [PATCH 4630/5608] Update selected mdos references --- .../Visual/SongSelect/TestSceneBeatmapDetailArea.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index d4805a73e4..66144cbfe4 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.SongSelect Position = new Vector2(0, 25), }); - modDisplay.Current.BindTo(Mods); + modDisplay.Current.BindTo(SelectedMods); AddStep("all metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { @@ -204,7 +204,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - Mods.Value = new[] { ruleset.GetAllMods().First(m => m is ModEasy) }; + SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModEasy) }; }); AddStep("with HR mod", () => @@ -230,7 +230,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - Mods.Value = new[] { ruleset.GetAllMods().First(m => m is ModHardRock) }; + SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModHardRock) }; }); } } From e87aa281bfde25de44342ceed4ac21c7309c1c14 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 17:00:35 +0900 Subject: [PATCH 4631/5608] Don't clone beatmap unnecessarily --- .../Screens/Select/Details/AdvancedStats.cs | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 3e7d4e244b..529d63b475 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -68,41 +68,39 @@ namespace osu.Game.Screens.Select.Details private void updateStatistics() { - BeatmapInfo processed = Beatmap?.Clone(); + var baseDifficulty = Beatmap?.BaseDifficulty; + var adjustedDifficulty = baseDifficulty; - if (processed != null && mods.Value.Any(m => m is IApplicableToDifficulty)) + if (baseDifficulty != null && mods.Value.Any(m => m is IApplicableToDifficulty)) { - processed.BaseDifficulty = processed.BaseDifficulty.Clone(); + adjustedDifficulty = adjustedDifficulty?.Clone(); foreach (var mod in mods.Value.OfType()) - mod.ApplyToDifficulty(processed.BaseDifficulty); + mod.ApplyToDifficulty(adjustedDifficulty); } - BeatmapDifficulty baseDifficulty = Beatmap?.BaseDifficulty; - BeatmapDifficulty moddedDifficulty = processed?.BaseDifficulty; - //mania specific - if ((processed?.Ruleset?.ID ?? 0) == 3) + if ((Beatmap?.Ruleset?.ID ?? 0) == 3) { firstValue.Title = "Key Amount"; firstValue.BaseValue = (int)MathF.Round(baseDifficulty?.CircleSize ?? 0); - firstValue.ModdedValue = (int)MathF.Round(moddedDifficulty?.CircleSize ?? 0); + firstValue.ModdedValue = (int)MathF.Round(adjustedDifficulty?.CircleSize ?? 0); } else { firstValue.Title = "Circle Size"; firstValue.BaseValue = baseDifficulty?.CircleSize ?? 0; - firstValue.ModdedValue = moddedDifficulty?.CircleSize ?? 0; + firstValue.ModdedValue = adjustedDifficulty?.CircleSize ?? 0; } hpDrain.BaseValue = baseDifficulty?.DrainRate ?? 0; accuracy.BaseValue = baseDifficulty?.OverallDifficulty ?? 0; approachRate.BaseValue = baseDifficulty?.ApproachRate ?? 0; - starDifficulty.BaseValue = (float)(processed?.StarDifficulty ?? 0); + starDifficulty.BaseValue = (float)(Beatmap?.StarDifficulty ?? 0); - hpDrain.ModdedValue = moddedDifficulty?.DrainRate ?? 0; - accuracy.ModdedValue = moddedDifficulty?.OverallDifficulty ?? 0; - approachRate.ModdedValue = moddedDifficulty?.ApproachRate ?? 0; + hpDrain.ModdedValue = adjustedDifficulty?.DrainRate ?? 0; + accuracy.ModdedValue = adjustedDifficulty?.OverallDifficulty ?? 0; + approachRate.ModdedValue = adjustedDifficulty?.ApproachRate ?? 0; } private class StatisticRow : Container, IHasAccentColour From ada2ae2b2c9e279b4ab4922be136c42e87d7205b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 17:12:41 +0900 Subject: [PATCH 4632/5608] Use tuple to avoid potential for incorrect display --- .../Screens/Select/Details/AdvancedStats.cs | 66 ++++++++----------- 1 file changed, 27 insertions(+), 39 deletions(-) diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 529d63b475..f684238a38 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -68,12 +68,12 @@ namespace osu.Game.Screens.Select.Details private void updateStatistics() { - var baseDifficulty = Beatmap?.BaseDifficulty; - var adjustedDifficulty = baseDifficulty; + BeatmapDifficulty baseDifficulty = Beatmap?.BaseDifficulty; + BeatmapDifficulty adjustedDifficulty = null; if (baseDifficulty != null && mods.Value.Any(m => m is IApplicableToDifficulty)) { - adjustedDifficulty = adjustedDifficulty?.Clone(); + adjustedDifficulty = baseDifficulty.Clone(); foreach (var mod in mods.Value.OfType()) mod.ApplyToDifficulty(adjustedDifficulty); @@ -83,24 +83,19 @@ namespace osu.Game.Screens.Select.Details if ((Beatmap?.Ruleset?.ID ?? 0) == 3) { firstValue.Title = "Key Amount"; - firstValue.BaseValue = (int)MathF.Round(baseDifficulty?.CircleSize ?? 0); - firstValue.ModdedValue = (int)MathF.Round(adjustedDifficulty?.CircleSize ?? 0); + firstValue.Value = ((int)MathF.Round(baseDifficulty?.CircleSize ?? 0), (int)MathF.Round(adjustedDifficulty?.CircleSize ?? 0)); } else { firstValue.Title = "Circle Size"; - firstValue.BaseValue = baseDifficulty?.CircleSize ?? 0; - firstValue.ModdedValue = adjustedDifficulty?.CircleSize ?? 0; + firstValue.Value = (baseDifficulty?.CircleSize ?? 0, adjustedDifficulty?.CircleSize); } - hpDrain.BaseValue = baseDifficulty?.DrainRate ?? 0; - accuracy.BaseValue = baseDifficulty?.OverallDifficulty ?? 0; - approachRate.BaseValue = baseDifficulty?.ApproachRate ?? 0; - starDifficulty.BaseValue = (float)(Beatmap?.StarDifficulty ?? 0); + starDifficulty.Value = ((float)(Beatmap?.StarDifficulty ?? 0), null); - hpDrain.ModdedValue = adjustedDifficulty?.DrainRate ?? 0; - accuracy.ModdedValue = adjustedDifficulty?.OverallDifficulty ?? 0; - approachRate.ModdedValue = adjustedDifficulty?.ApproachRate ?? 0; + hpDrain.Value = (baseDifficulty?.DrainRate ?? 0, adjustedDifficulty?.DrainRate); + accuracy.Value = (baseDifficulty?.OverallDifficulty ?? 0, adjustedDifficulty?.OverallDifficulty); + approachRate.Value = (baseDifficulty?.ApproachRate ?? 0, adjustedDifficulty?.ApproachRate); } private class StatisticRow : Container, IHasAccentColour @@ -110,7 +105,7 @@ namespace osu.Game.Screens.Select.Details private readonly float maxValue; private readonly bool forceDecimalPlaces; - private readonly OsuSpriteText name, value; + private readonly OsuSpriteText name, valueText; private readonly Bar bar, modBar; [Resolved] @@ -122,36 +117,29 @@ namespace osu.Game.Screens.Select.Details set => name.Text = value; } - private float baseValue; + private (float baseValue, float? adjustedValue) value; - private float moddedValue; - - public float BaseValue + public (float baseValue, float? adjustedValue) Value { - get => baseValue; + get => value; set { - baseValue = value; - bar.Length = value / maxValue; - this.value.Text = value.ToString(forceDecimalPlaces ? "0.00" : "0.##"); - } - } + if (value == this.value) + return; - public float ModdedValue - { - get => moddedValue; - set - { - moddedValue = value; - modBar.Length = value / maxValue; - this.value.Text = value.ToString(forceDecimalPlaces ? "0.00" : "0.##"); + this.value = value; - if (moddedValue > baseValue) - modBar.AccentColour = this.value.Colour = colours.Red; - else if (moddedValue < baseValue) - modBar.AccentColour = this.value.Colour = colours.BlueDark; + bar.Length = value.baseValue / maxValue; + + valueText.Text = (value.adjustedValue ?? value.baseValue).ToString(forceDecimalPlaces ? "0.00" : "0.##"); + modBar.Length = (value.adjustedValue ?? 0) / maxValue; + + if (value.adjustedValue > value.baseValue) + modBar.AccentColour = valueText.Colour = colours.Red; + else if (value.adjustedValue < value.baseValue) + modBar.AccentColour = valueText.Colour = colours.BlueDark; else - modBar.AccentColour = this.value.Colour = Color4.White; + modBar.AccentColour = valueText.Colour = Color4.White; } } @@ -203,7 +191,7 @@ namespace osu.Game.Screens.Select.Details Origin = Anchor.TopRight, Width = value_width, RelativeSizeAxes = Axes.Y, - Child = value = new OsuSpriteText + Child = valueText = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 602ce698d5633a3b655682a1b94d952a4adc99ee Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Dec 2019 17:21:38 +0900 Subject: [PATCH 4633/5608] Fix storyboard vectorscale and scale cross-pollution --- .../Formats/LegacyStoryboardDecoder.cs | 4 +-- osu.Game/Storyboards/CommandTimelineGroup.cs | 3 ++- .../Drawables/DrawableStoryboardAnimation.cs | 27 +++++++++++++++++-- .../Drawables/DrawableStoryboardSprite.cs | 27 +++++++++++++++++-- osu.Game/Storyboards/Drawables/IFlippable.cs | 8 +++--- .../Storyboards/Drawables/IVectorScalable.cs | 21 +++++++++++++++ osu.Game/Storyboards/StoryboardSprite.cs | 20 ++++++++++---- 7 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 osu.Game/Storyboards/Drawables/IVectorScalable.cs diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index ccd46ab559..756aa45eed 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -176,7 +176,7 @@ namespace osu.Game.Beatmaps.Formats { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; - timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue)); + timelineGroup?.Scale.Add(easing, startTime, endTime, startValue, endValue); break; } @@ -186,7 +186,7 @@ namespace osu.Game.Beatmaps.Formats var startY = float.Parse(split[5], CultureInfo.InvariantCulture); var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX; var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; - timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY)); + timelineGroup?.VectorScale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY)); break; } diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index 364c971874..7b6e667d4f 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -16,7 +16,8 @@ namespace osu.Game.Storyboards { public CommandTimeline X = new CommandTimeline(); public CommandTimeline Y = new CommandTimeline(); - public CommandTimeline Scale = new CommandTimeline(); + public CommandTimeline Scale = new CommandTimeline(); + public CommandTimeline VectorScale = new CommandTimeline(); public CommandTimeline Rotation = new CommandTimeline(); public CommandTimeline Colour = new CommandTimeline(); public CommandTimeline Alpha = new CommandTimeline(); diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index 4f8e39fa1b..a452c7540d 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -8,21 +8,44 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Textures; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; namespace osu.Game.Storyboards.Drawables { - public class DrawableStoryboardAnimation : TextureAnimation, IFlippable + public class DrawableStoryboardAnimation : TextureAnimation, IFlippable, IVectorScalable { public StoryboardAnimation Animation { get; private set; } public bool FlipH { get; set; } public bool FlipV { get; set; } + private Vector2 vectorScale = Vector2.One; + + public Vector2 VectorScale + { + get => vectorScale; + set + { + if (Math.Abs(value.X) < Precision.FLOAT_EPSILON) + value.X = Precision.FLOAT_EPSILON; + if (Math.Abs(value.Y) < Precision.FLOAT_EPSILON) + value.Y = Precision.FLOAT_EPSILON; + + if (vectorScale == value) + return; + + if (!Validation.IsFinite(value)) throw new ArgumentException($@"{nameof(VectorScale)} must be finite, but is {value}."); + + vectorScale = value; + Invalidate(Invalidation.MiscGeometry); + } + } + public override bool RemoveWhenNotAlive => false; protected override Vector2 DrawScale - => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y); + => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y) * VectorScale; public override Anchor Origin { diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index ff48dab7e5..42c7cfacb2 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -8,21 +8,44 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; namespace osu.Game.Storyboards.Drawables { - public class DrawableStoryboardSprite : Sprite, IFlippable + public class DrawableStoryboardSprite : Sprite, IFlippable, IVectorScalable { public StoryboardSprite Sprite { get; private set; } public bool FlipH { get; set; } public bool FlipV { get; set; } + private Vector2 vectorScale = Vector2.One; + + public Vector2 VectorScale + { + get => vectorScale; + set + { + if (Math.Abs(value.X) < Precision.FLOAT_EPSILON) + value.X = Precision.FLOAT_EPSILON; + if (Math.Abs(value.Y) < Precision.FLOAT_EPSILON) + value.Y = Precision.FLOAT_EPSILON; + + if (vectorScale == value) + return; + + if (!Validation.IsFinite(value)) throw new ArgumentException($@"{nameof(VectorScale)} must be finite, but is {value}."); + + vectorScale = value; + Invalidate(Invalidation.MiscGeometry); + } + } + public override bool RemoveWhenNotAlive => false; protected override Vector2 DrawScale - => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y); + => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y) * VectorScale; public override Anchor Origin { diff --git a/osu.Game/Storyboards/Drawables/IFlippable.cs b/osu.Game/Storyboards/Drawables/IFlippable.cs index 1c4cdde22d..165b3d97cc 100644 --- a/osu.Game/Storyboards/Drawables/IFlippable.cs +++ b/osu.Game/Storyboards/Drawables/IFlippable.cs @@ -6,13 +6,13 @@ using osu.Framework.Graphics.Transforms; namespace osu.Game.Storyboards.Drawables { - public interface IFlippable : ITransformable + internal interface IFlippable : ITransformable { bool FlipH { get; set; } bool FlipV { get; set; } } - public class TransformFlipH : Transform + internal class TransformFlipH : Transform { private bool valueAt(double time) => time < EndTime ? StartValue : EndValue; @@ -23,7 +23,7 @@ namespace osu.Game.Storyboards.Drawables protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipH; } - public class TransformFlipV : Transform + internal class TransformFlipV : Transform { private bool valueAt(double time) => time < EndTime ? StartValue : EndValue; @@ -34,7 +34,7 @@ namespace osu.Game.Storyboards.Drawables protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipV; } - public static class FlippableExtensions + internal static class FlippableExtensions { /// /// Adjusts after a delay. diff --git a/osu.Game/Storyboards/Drawables/IVectorScalable.cs b/osu.Game/Storyboards/Drawables/IVectorScalable.cs new file mode 100644 index 0000000000..fcc407d460 --- /dev/null +++ b/osu.Game/Storyboards/Drawables/IVectorScalable.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Transforms; +using osuTK; + +namespace osu.Game.Storyboards.Drawables +{ + internal interface IVectorScalable : ITransformable + { + Vector2 VectorScale { get; set; } + } + + internal static class VectorScalableExtensions + { + public static TransformSequence VectorScaleTo(this T target, Vector2 newVectorScale, double duration = 0, Easing easing = Easing.None) + where T : class, IVectorScalable + => target.TransformTo(nameof(IVectorScalable.VectorScale), newVectorScale, duration, easing); + } +} diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index d5e69fd103..abf9f58804 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -65,20 +65,30 @@ namespace osu.Game.Storyboards { applyCommands(drawable, getCommands(g => g.X, triggeredGroups), (d, value) => d.X = value, (d, value, duration, easing) => d.MoveToX(value, duration, easing)); applyCommands(drawable, getCommands(g => g.Y, triggeredGroups), (d, value) => d.Y = value, (d, value, duration, easing) => d.MoveToY(value, duration, easing)); - applyCommands(drawable, getCommands(g => g.Scale, triggeredGroups), (d, value) => d.Scale = value, (d, value, duration, easing) => d.ScaleTo(value, duration, easing)); + applyCommands(drawable, getCommands(g => g.Scale, triggeredGroups), (d, value) => d.Scale = new Vector2(value), (d, value, duration, easing) => d.ScaleTo(value, duration, easing)); applyCommands(drawable, getCommands(g => g.Rotation, triggeredGroups), (d, value) => d.Rotation = value, (d, value, duration, easing) => d.RotateTo(value, duration, easing)); applyCommands(drawable, getCommands(g => g.Colour, triggeredGroups), (d, value) => d.Colour = value, (d, value, duration, easing) => d.FadeColour(value, duration, easing)); applyCommands(drawable, getCommands(g => g.Alpha, triggeredGroups), (d, value) => d.Alpha = value, (d, value, duration, easing) => d.FadeTo(value, duration, easing)); - applyCommands(drawable, getCommands(g => g.BlendingParameters, triggeredGroups), (d, value) => d.Blending = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), false); + applyCommands(drawable, getCommands(g => g.BlendingParameters, triggeredGroups), (d, value) => d.Blending = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), + false); + + if (drawable is IVectorScalable vectorScalable) + { + applyCommands(drawable, getCommands(g => g.VectorScale, triggeredGroups), (d, value) => vectorScalable.VectorScale = value, + (d, value, duration, easing) => vectorScalable.VectorScaleTo(value, duration, easing)); + } if (drawable is IFlippable flippable) { - applyCommands(drawable, getCommands(g => g.FlipH, triggeredGroups), (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration), false); - applyCommands(drawable, getCommands(g => g.FlipV, triggeredGroups), (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), false); + applyCommands(drawable, getCommands(g => g.FlipH, triggeredGroups), (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration), + false); + applyCommands(drawable, getCommands(g => g.FlipV, triggeredGroups), (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), + false); } } - private void applyCommands(Drawable drawable, IEnumerable.TypedCommand> commands, DrawablePropertyInitializer initializeProperty, DrawableTransformer transform, bool alwaysInitialize = true) + private void applyCommands(Drawable drawable, IEnumerable.TypedCommand> commands, DrawablePropertyInitializer initializeProperty, DrawableTransformer transform, + bool alwaysInitialize = true) where T : struct { var initialized = false; From 5aca523d353f46881df089c698275fdb9344d90e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Dec 2019 17:27:13 +0900 Subject: [PATCH 4634/5608] Fix storyboard flipping potentially not having an effect --- .../Drawables/DrawableStoryboardAnimation.cs | 31 +++++++++++++++++-- .../Drawables/DrawableStoryboardSprite.cs | 31 +++++++++++++++++-- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index 4f8e39fa1b..66c6d179b8 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -16,8 +16,35 @@ namespace osu.Game.Storyboards.Drawables { public StoryboardAnimation Animation { get; private set; } - public bool FlipH { get; set; } - public bool FlipV { get; set; } + private bool flipH; + + public bool FlipH + { + get => flipH; + set + { + if (flipH == value) + return; + + flipH = value; + Invalidate(Invalidation.MiscGeometry); + } + } + + private bool flipV; + + public bool FlipV + { + get => flipV; + set + { + if (flipV == value) + return; + + flipV = value; + Invalidate(Invalidation.MiscGeometry); + } + } public override bool RemoveWhenNotAlive => false; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index ff48dab7e5..aa60096661 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -16,8 +16,35 @@ namespace osu.Game.Storyboards.Drawables { public StoryboardSprite Sprite { get; private set; } - public bool FlipH { get; set; } - public bool FlipV { get; set; } + private bool flipH; + + public bool FlipH + { + get => flipH; + set + { + if (flipH == value) + return; + + flipH = value; + Invalidate(Invalidation.MiscGeometry); + } + } + + private bool flipV; + + public bool FlipV + { + get => flipV; + set + { + if (flipV == value) + return; + + flipV = value; + Invalidate(Invalidation.MiscGeometry); + } + } public override bool RemoveWhenNotAlive => false; From 4befabc2573072c06130ff21903e93d94dbf6f69 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 17:35:51 +0900 Subject: [PATCH 4635/5608] Split out complex method --- .../Beatmaps/Formats/LegacyBeatmapEncoder.cs | 180 ++++++++++-------- 1 file changed, 99 insertions(+), 81 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index d38ff482ad..8d16278f60 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -217,26 +217,12 @@ namespace osu.Game.Beatmaps.Formats private void handleOsuHitObject(TextWriter writer, HitObject hitObject) { - var positionData = hitObject as IHasPosition; - var comboData = hitObject as IHasCombo; - - Debug.Assert(positionData != null); - Debug.Assert(comboData != null); - - LegacyHitObjectType hitObjectType = (LegacyHitObjectType)(comboData.ComboOffset << 4); - if (comboData.NewCombo) - hitObjectType |= LegacyHitObjectType.NewCombo; - if (hitObject is IHasCurve) - hitObjectType |= LegacyHitObjectType.Slider; - else if (hitObject is IHasEndTime) - hitObjectType |= LegacyHitObjectType.Spinner | LegacyHitObjectType.NewCombo; - else - hitObjectType |= LegacyHitObjectType.Circle; + var positionData = (IHasPosition)hitObject; writer.Write(FormattableString.Invariant($"{positionData.X},")); writer.Write(FormattableString.Invariant($"{positionData.Y},")); writer.Write(FormattableString.Invariant($"{hitObject.StartTime},")); - writer.Write(FormattableString.Invariant($"{(int)hitObjectType},")); + writer.Write(FormattableString.Invariant($"{(int)getObjectType(hitObject)},")); writer.Write(hitObject is IHasCurve ? FormattableString.Invariant($"0,") @@ -244,76 +230,108 @@ namespace osu.Game.Beatmaps.Formats if (hitObject is IHasCurve curveData) { - PathType? lastType = null; - - for (int i = 0; i < curveData.Path.ControlPoints.Count; i++) - { - PathControlPoint point = curveData.Path.ControlPoints[i]; - - if (point.Type.Value != null) - { - if (point.Type.Value != lastType) - { - switch (point.Type.Value) - { - case PathType.Bezier: - writer.Write("B|"); - break; - - case PathType.Catmull: - writer.Write("C|"); - break; - - case PathType.PerfectCurve: - writer.Write("P|"); - break; - - case PathType.Linear: - writer.Write("L|"); - break; - } - - lastType = point.Type.Value; - } - else - { - // New segment with the same type - duplicate the control point - writer.Write(FormattableString.Invariant($"{positionData.X + point.Position.Value.X}:{positionData.Y + point.Position.Value.Y}|")); - } - } - - if (i != 0) - { - writer.Write(FormattableString.Invariant($"{positionData.X + point.Position.Value.X}:{positionData.Y + point.Position.Value.Y}")); - writer.Write(i != curveData.Path.ControlPoints.Count - 1 ? "|" : ","); - } - } - - writer.Write(FormattableString.Invariant($"{curveData.RepeatCount + 1},")); - writer.Write(FormattableString.Invariant($"{curveData.Path.Distance},")); - - for (int i = 0; i < curveData.NodeSamples.Count; i++) - { - writer.Write(FormattableString.Invariant($"{(int)toLegacyHitSoundType(curveData.NodeSamples[i])}")); - writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ","); - } - - for (int i = 0; i < curveData.NodeSamples.Count; i++) - { - writer.Write(getSampleBank(curveData.NodeSamples[i], true)); - writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ","); - } + addCurveData(writer, curveData, positionData); + writer.Write(getSampleBank(hitObject.Samples, zeroBanks: true)); + } + else + { + if (hitObject is IHasEndTime endTimeData) + writer.Write(FormattableString.Invariant($"{endTimeData.EndTime},")); + writer.Write(getSampleBank(hitObject.Samples)); } - else if (hitObject is IHasEndTime endTimeData) - writer.Write(FormattableString.Invariant($"{endTimeData.EndTime},")); - - writer.Write(hitObject is IHasCurve - ? getSampleBank(hitObject.Samples, zeroBanks: true) - : getSampleBank(hitObject.Samples)); writer.WriteLine(); } + private static LegacyHitObjectType getObjectType(HitObject hitObject) + { + var comboData = (IHasCombo)hitObject; + + var type = (LegacyHitObjectType)(comboData.ComboOffset << 4); + + if (comboData.NewCombo) type |= LegacyHitObjectType.NewCombo; + + switch (hitObject) + { + case IHasCurve _: + type |= LegacyHitObjectType.Slider; + break; + + case IHasEndTime _: + type |= LegacyHitObjectType.Spinner | LegacyHitObjectType.NewCombo; + break; + + default: + type |= LegacyHitObjectType.Circle; + break; + } + + return type; + } + + private void addCurveData(TextWriter writer, IHasCurve curveData, IHasPosition positionData) + { + PathType? lastType = null; + + for (int i = 0; i < curveData.Path.ControlPoints.Count; i++) + { + PathControlPoint point = curveData.Path.ControlPoints[i]; + + if (point.Type.Value != null) + { + if (point.Type.Value != lastType) + { + switch (point.Type.Value) + { + case PathType.Bezier: + writer.Write("B|"); + break; + + case PathType.Catmull: + writer.Write("C|"); + break; + + case PathType.PerfectCurve: + writer.Write("P|"); + break; + + case PathType.Linear: + writer.Write("L|"); + break; + } + + lastType = point.Type.Value; + } + else + { + // New segment with the same type - duplicate the control point + writer.Write(FormattableString.Invariant($"{positionData.X + point.Position.Value.X}:{positionData.Y + point.Position.Value.Y}|")); + } + } + + if (i != 0) + { + writer.Write(FormattableString.Invariant($"{positionData.X + point.Position.Value.X}:{positionData.Y + point.Position.Value.Y}")); + writer.Write(i != curveData.Path.ControlPoints.Count - 1 ? "|" : ","); + } + } + + writer.Write(FormattableString.Invariant($"{curveData.RepeatCount + 1},")); + writer.Write(FormattableString.Invariant($"{curveData.Path.Distance},")); + + for (int i = 0; i < curveData.NodeSamples.Count; i++) + { + writer.Write(FormattableString.Invariant($"{(int)toLegacyHitSoundType(curveData.NodeSamples[i])}")); + writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ","); + } + + for (int i = 0; i < curveData.NodeSamples.Count; i++) + { + writer.Write(getSampleBank(curveData.NodeSamples[i], true)); + writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ","); + } + } + private void handleTaikoHitObject(TextWriter writer, HitObject hitObject) => throw new NotImplementedException(); private void handleCatchHitObject(TextWriter writer, HitObject hitObject) => throw new NotImplementedException(); From 8e651962c7d7c5dbe98bc8e801db9a3514745e7a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Dec 2019 17:41:30 +0900 Subject: [PATCH 4636/5608] Fix incorrectly binding inside BDL load() --- osu.Game/Screens/Select/Details/AdvancedStats.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index f684238a38..9c9c33274f 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -63,7 +63,13 @@ namespace osu.Game.Screens.Select.Details private void load(OsuColour colours) { starDifficulty.AccentColour = colours.Yellow; - mods.ValueChanged += _ => updateStatistics(); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + mods.BindValueChanged(_ => updateStatistics(), true); } private void updateStatistics() From bf85f4affb1eca46513b17dd2442b40df78cce32 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 17:53:26 +0900 Subject: [PATCH 4637/5608] Fix editor crashing when loading a beatmap for an unsupported ruleset --- osu.Game/Screens/Edit/Compose/ComposeScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 6984716a2c..5d9757778d 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -32,6 +32,6 @@ namespace osu.Game.Screens.Edit.Compose return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(composer)); } - protected override Drawable CreateTimelineContent() => new TimelineHitObjectDisplay(composer.EditorBeatmap); + protected override Drawable CreateTimelineContent() => composer == null ? base.CreateTimelineContent() : new TimelineHitObjectDisplay(composer.EditorBeatmap); } } From d65e37d7959fe4e89a6091c53b805059dbe73935 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Dec 2019 17:58:29 +0900 Subject: [PATCH 4638/5608] Fix typo --- osu.Game/Graphics/Containers/BeatSyncedContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index b04d01004a..b9ef279f5c 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -34,7 +34,7 @@ namespace osu.Game.Graphics.Containers public double TimeSinceLastBeat { get; private set; } /// - /// How many baets per beatlength to trigger. Defaults to 1. + /// How many beats per beatlength to trigger. Defaults to 1. /// public int Divisor { get; set; } = 1; From 1f3e1b308590409c6c09c33a91d62c88f3664962 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 17:59:07 +0900 Subject: [PATCH 4639/5608] Remove unused using --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 8d16278f60..433becd8cc 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Text; From 5664ce3109d9cb40ede788e76b05cb5b503a237a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Dec 2019 18:51:12 +0900 Subject: [PATCH 4640/5608] Add hitobject container regression test --- .../Gameplay/TestSceneHitObjectContainer.cs | 75 +++++++++++++++++++ osu.Game/Rulesets/UI/HitObjectContainer.cs | 2 + 2 files changed, 77 insertions(+) create mode 100644 osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs new file mode 100644 index 0000000000..f2bfccb6de --- /dev/null +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs @@ -0,0 +1,75 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using JetBrains.Annotations; +using NUnit.Framework; +using osu.Framework.Testing; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI; +using osu.Game.Tests.Visual; + +namespace osu.Game.Tests.Gameplay +{ + [HeadlessTest] + public class TestSceneHitObjectContainer : OsuTestScene + { + private HitObjectContainer container; + + [SetUp] + public void Setup() => Schedule(() => + { + Child = container = new HitObjectContainer(); + }); + + [Test] + public void TestLateHitObjectIsAddedEarlierInList() + { + DrawableHitObject hitObject = null; + + AddStep("setup", () => container.Add(new TestDrawableHitObject(new HitObject { StartTime = 500 }))); + + AddStep("add late hitobject", () => container.Add(hitObject = new TestDrawableHitObject(new HitObject { StartTime = 1000 }))); + + AddAssert("hitobject index is 0", () => container.IndexOf(hitObject) == 0); + } + + [Test] + public void TestEarlyHitObjectIsAddedLaterInList() + { + DrawableHitObject hitObject = null; + + AddStep("setup", () => container.Add(new TestDrawableHitObject(new HitObject { StartTime = 500 }))); + + AddStep("add early hitobject", () => container.Add(hitObject = new TestDrawableHitObject(new HitObject()))); + + AddAssert("hitobject index is 0", () => container.IndexOf(hitObject) == 1); + } + + [Test] + public void TestHitObjectsResortedAfterStartTimeChange() + { + DrawableHitObject firstObject = null; + DrawableHitObject secondObject = null; + + AddStep("setup", () => + { + container.Add(firstObject = new TestDrawableHitObject(new HitObject())); + container.Add(secondObject = new TestDrawableHitObject(new HitObject { StartTime = 1000 })); + }); + + AddStep("move first object after second", () => firstObject.HitObject.StartTime = 2000); + + AddAssert("first object index is 1", () => container.IndexOf(firstObject) == 0); + AddAssert("second object index is 0", () => container.IndexOf(secondObject) == 1); + } + + private class TestDrawableHitObject : DrawableHitObject + { + public TestDrawableHitObject([NotNull] HitObject hitObject) + : base(hitObject) + { + } + } + } +} diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index 1e33b15184..dea981c3ad 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -43,6 +43,8 @@ namespace osu.Game.Rulesets.UI return true; } + public int IndexOf(DrawableHitObject hitObject) => IndexOfInternal(hitObject); + private void onStartTimeChanged(DrawableHitObject hitObject) { if (!RemoveInternal(hitObject)) From cb5a35f8f9f23c5b53d456611d3cf6c65f16f86f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Dec 2019 21:08:38 +0900 Subject: [PATCH 4641/5608] Fix incorrect bindable valuechanged usage --- osu.Game/Screens/Select/FooterButtonMods.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index fbeda8f18e..dde6e90ee3 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -60,8 +60,6 @@ namespace osu.Game.Screens.Select AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Left = 70 } }); - - Current.ValueChanged += _ => updateMultiplierText(); } [BackgroundDependencyLoader] @@ -75,6 +73,13 @@ namespace osu.Game.Screens.Select Hotkey = Key.F1; } + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(_ => updateMultiplierText(), true); + } + private void updateMultiplierText() { var multiplier = Current.Value.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier); From 2905a4418d5960f7edadaefedfb81545d4b7b943 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Dec 2019 21:30:57 +0900 Subject: [PATCH 4642/5608] Fix potential nullref --- osu.Game/Screens/Select/FooterButtonMods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index dde6e90ee3..8419ee0c2a 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -82,7 +82,7 @@ namespace osu.Game.Screens.Select private void updateMultiplierText() { - var multiplier = Current.Value.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier); + double multiplier = Current.Value?.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier) ?? 1; MultiplierText.Text = multiplier.Equals(1.0) ? string.Empty : $"{multiplier:N2}x"; From 9ac15ef3a8141d0e583009aa7a604e112f6c1d06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Dec 2019 22:56:00 +0900 Subject: [PATCH 4643/5608] Don't log discord connection failures --- osu.Desktop/DiscordRichPresence.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index b53ca6161b..8818cef8eb 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -43,8 +43,7 @@ namespace osu.Desktop }; client.OnReady += onReady; - client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network, LogLevel.Error); - client.OnConnectionFailed += (_, e) => Logger.Log($"An connection occurred with Discord RPC Client: {e.Type}", LoggingTarget.Network, LogLevel.Error); + client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network); (user = provider.LocalUser.GetBoundCopy()).BindValueChanged(u => { From 8d6987c8703d27b4459fb3f30f586a1b1b9ae8a9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Dec 2019 23:59:48 +0900 Subject: [PATCH 4644/5608] Refactor storyboard timeline to reduce GC / fix crashes --- osu.Game/Storyboards/CommandTimeline.cs | 29 +++++---- osu.Game/Storyboards/CommandTimelineGroup.cs | 65 +++++++++++++++----- 2 files changed, 69 insertions(+), 25 deletions(-) diff --git a/osu.Game/Storyboards/CommandTimeline.cs b/osu.Game/Storyboards/CommandTimeline.cs index bcf642b4ea..c71806352d 100644 --- a/osu.Game/Storyboards/CommandTimeline.cs +++ b/osu.Game/Storyboards/CommandTimeline.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Caching; using osu.Framework.Graphics; using System; using System.Collections.Generic; @@ -12,27 +11,35 @@ namespace osu.Game.Storyboards public class CommandTimeline : ICommandTimeline { private readonly List commands = new List(); + public IEnumerable Commands => commands.OrderBy(c => c.StartTime); + public bool HasCommands => commands.Count > 0; - private readonly Cached startTimeBacking = new Cached(); - public double StartTime => startTimeBacking.IsValid ? startTimeBacking : startTimeBacking.Value = HasCommands ? commands.Min(c => c.StartTime) : double.MinValue; + public double StartTime { get; private set; } = double.MaxValue; + public double EndTime { get; private set; } = double.MinValue; - private readonly Cached endTimeBacking = new Cached(); - public double EndTime => endTimeBacking.IsValid ? endTimeBacking : endTimeBacking.Value = HasCommands ? commands.Max(c => c.EndTime) : double.MaxValue; - - public T StartValue => HasCommands ? commands.OrderBy(c => c.StartTime).First().StartValue : default; - public T EndValue => HasCommands ? commands.OrderByDescending(c => c.EndTime).First().EndValue : default; + public T StartValue { get; private set; } + public T EndValue { get; private set; } public void Add(Easing easing, double startTime, double endTime, T startValue, T endValue) { if (endTime < startTime) return; - commands.Add(new TypedCommand { Easing = easing, StartTime = startTime, EndTime = endTime, StartValue = startValue, EndValue = endValue, }); + commands.Add(new TypedCommand { Easing = easing, StartTime = startTime, EndTime = endTime, StartValue = startValue, EndValue = endValue }); - startTimeBacking.Invalidate(); - endTimeBacking.Invalidate(); + if (startTime < StartTime) + { + StartValue = startValue; + StartTime = startTime; + } + + if (endTime > EndTime) + { + EndValue = endValue; + EndTime = endTime; + } } public override string ToString() diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index 7b6e667d4f..6ce3b617e9 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.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 osuTK; using osuTK.Graphics; using osu.Framework.Graphics; @@ -25,28 +26,52 @@ namespace osu.Game.Storyboards public CommandTimeline FlipH = new CommandTimeline(); public CommandTimeline FlipV = new CommandTimeline(); + private readonly ICommandTimeline[] timelines; + + public CommandTimelineGroup() + { + timelines = new ICommandTimeline[] + { + X, + Y, + Scale, + VectorScale, + Rotation, + Colour, + Alpha, + BlendingParameters, + FlipH, + FlipV + }; + } + [JsonIgnore] - public IEnumerable Timelines + public double CommandsStartTime { get { - yield return X; - yield return Y; - yield return Scale; - yield return Rotation; - yield return Colour; - yield return Alpha; - yield return BlendingParameters; - yield return FlipH; - yield return FlipV; + double min = double.MaxValue; + + for (int i = 0; i < timelines.Length; i++) + min = Math.Min(min, timelines[i].StartTime); + + return min; } } [JsonIgnore] - public double CommandsStartTime => Timelines.Where(t => t.HasCommands).Min(t => t.StartTime); + public double CommandsEndTime + { + get + { + double max = double.MinValue; - [JsonIgnore] - public double CommandsEndTime => Timelines.Where(t => t.HasCommands).Max(t => t.EndTime); + for (int i = 0; i < timelines.Length; i++) + max = Math.Max(max, timelines[i].EndTime); + + return max; + } + } [JsonIgnore] public double CommandsDuration => CommandsEndTime - CommandsStartTime; @@ -61,7 +86,19 @@ namespace osu.Game.Storyboards public double Duration => EndTime - StartTime; [JsonIgnore] - public bool HasCommands => Timelines.Any(t => t.HasCommands); + public bool HasCommands + { + get + { + for (int i = 0; i < timelines.Length; i++) + { + if (timelines[i].HasCommands) + return true; + } + + return false; + } + } public virtual IEnumerable.TypedCommand> GetCommands(CommandTimelineSelector timelineSelector, double offset = 0) { From f38853d2291835e6cbda7cc12a2dcf1e4f9eae5f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Dec 2019 00:52:50 +0900 Subject: [PATCH 4645/5608] Improve performance of storyboard loading --- osu.Game/Storyboards/StoryboardSprite.cs | 83 ++++++++++++++++++------ 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index abf9f58804..22e1929419 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -7,6 +7,7 @@ using osu.Game.Storyboards.Drawables; using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; namespace osu.Game.Storyboards { @@ -63,50 +64,56 @@ namespace osu.Game.Storyboards public void ApplyTransforms(Drawable drawable, IEnumerable> triggeredGroups = null) { - applyCommands(drawable, getCommands(g => g.X, triggeredGroups), (d, value) => d.X = value, (d, value, duration, easing) => d.MoveToX(value, duration, easing)); - applyCommands(drawable, getCommands(g => g.Y, triggeredGroups), (d, value) => d.Y = value, (d, value, duration, easing) => d.MoveToY(value, duration, easing)); - applyCommands(drawable, getCommands(g => g.Scale, triggeredGroups), (d, value) => d.Scale = new Vector2(value), (d, value, duration, easing) => d.ScaleTo(value, duration, easing)); - applyCommands(drawable, getCommands(g => g.Rotation, triggeredGroups), (d, value) => d.Rotation = value, (d, value, duration, easing) => d.RotateTo(value, duration, easing)); - applyCommands(drawable, getCommands(g => g.Colour, triggeredGroups), (d, value) => d.Colour = value, (d, value, duration, easing) => d.FadeColour(value, duration, easing)); - applyCommands(drawable, getCommands(g => g.Alpha, triggeredGroups), (d, value) => d.Alpha = value, (d, value, duration, easing) => d.FadeTo(value, duration, easing)); - applyCommands(drawable, getCommands(g => g.BlendingParameters, triggeredGroups), (d, value) => d.Blending = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), + // For performance reasons, we need to apply the commands in order by start time. Not doing so will cause many functions to be interleaved, resulting in O(n^2) complexity. + // To achieve this, commands are "generated" as pairs of (command, initFunc, transformFunc) and batched into a contiguous list + // The list is then stably-sorted (to preserve command order), and applied to the drawable sequentially. + + List generated = new List(); + + generateCommands(generated, getCommands(g => g.X, triggeredGroups), (d, value) => d.X = value, (d, value, duration, easing) => d.MoveToX(value, duration, easing)); + generateCommands(generated, getCommands(g => g.Y, triggeredGroups), (d, value) => d.Y = value, (d, value, duration, easing) => d.MoveToY(value, duration, easing)); + generateCommands(generated, getCommands(g => g.Scale, triggeredGroups), (d, value) => d.Scale = new Vector2(value), (d, value, duration, easing) => d.ScaleTo(value, duration, easing)); + generateCommands(generated, getCommands(g => g.Rotation, triggeredGroups), (d, value) => d.Rotation = value, (d, value, duration, easing) => d.RotateTo(value, duration, easing)); + generateCommands(generated, getCommands(g => g.Colour, triggeredGroups), (d, value) => d.Colour = value, (d, value, duration, easing) => d.FadeColour(value, duration, easing)); + generateCommands(generated, getCommands(g => g.Alpha, triggeredGroups), (d, value) => d.Alpha = value, (d, value, duration, easing) => d.FadeTo(value, duration, easing)); + generateCommands(generated, getCommands(g => g.BlendingParameters, triggeredGroups), (d, value) => d.Blending = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), false); if (drawable is IVectorScalable vectorScalable) { - applyCommands(drawable, getCommands(g => g.VectorScale, triggeredGroups), (d, value) => vectorScalable.VectorScale = value, + generateCommands(generated, getCommands(g => g.VectorScale, triggeredGroups), (d, value) => vectorScalable.VectorScale = value, (d, value, duration, easing) => vectorScalable.VectorScaleTo(value, duration, easing)); } if (drawable is IFlippable flippable) { - applyCommands(drawable, getCommands(g => g.FlipH, triggeredGroups), (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration), + generateCommands(generated, getCommands(g => g.FlipH, triggeredGroups), (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration), false); - applyCommands(drawable, getCommands(g => g.FlipV, triggeredGroups), (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), + generateCommands(generated, getCommands(g => g.FlipV, triggeredGroups), (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), false); } + + foreach (var command in generated.OrderBy(g => g.StartTime)) + command.ApplyTo(drawable); } - private void applyCommands(Drawable drawable, IEnumerable.TypedCommand> commands, DrawablePropertyInitializer initializeProperty, DrawableTransformer transform, - bool alwaysInitialize = true) - where T : struct + private void generateCommands(List resultList, IEnumerable.TypedCommand> commands, + DrawablePropertyInitializer initializeProperty, DrawableTransformer transform, bool alwaysInitialize = true) { - var initialized = false; + bool initialized = false; - foreach (var command in commands.OrderBy(l => l)) + foreach (var command in commands) { + DrawablePropertyInitializer initFunc = null; + if (!initialized) { if (alwaysInitialize || command.StartTime == command.EndTime) - initializeProperty.Invoke(drawable, command.StartValue); + initFunc = initializeProperty; initialized = true; } - using (drawable.BeginAbsoluteSequence(command.StartTime)) - { - transform(drawable, command.StartValue, 0, Easing.None); - transform(drawable, command.EndValue, command.Duration, command.Easing); - } + resultList.Add(new GeneratedCommand(command, initFunc, transform)); } } @@ -127,5 +134,39 @@ namespace osu.Game.Storyboards public override string ToString() => $"{Path}, {Origin}, {InitialPosition}"; + + private interface IGeneratedCommand + { + double StartTime { get; } + + void ApplyTo(Drawable drawable); + } + + private readonly struct GeneratedCommand : IGeneratedCommand + { + public double StartTime => command.StartTime; + + private readonly DrawablePropertyInitializer initializeProperty; + private readonly DrawableTransformer transform; + private readonly CommandTimeline.TypedCommand command; + + public GeneratedCommand([NotNull] CommandTimeline.TypedCommand command, [CanBeNull] DrawablePropertyInitializer initializeProperty, [NotNull] DrawableTransformer transform) + { + this.command = command; + this.initializeProperty = initializeProperty; + this.transform = transform; + } + + public void ApplyTo(Drawable drawable) + { + initializeProperty?.Invoke(drawable, command.StartValue); + + using (drawable.BeginAbsoluteSequence(command.StartTime)) + { + transform(drawable, command.StartValue, 0, Easing.None); + transform(drawable, command.EndValue, command.Duration, command.Easing); + } + } + } } } From 007e2e80c1cd193e9e7a1ded3df6191571bed8a3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Dec 2019 02:02:57 +0900 Subject: [PATCH 4646/5608] Refactor to fix sorting issues --- osu.Game/Overlays/SocialOverlay.cs | 70 +++++++++++++----------------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 5b3acf8e46..01dd1ee635 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; @@ -15,7 +16,6 @@ using osu.Game.Online.API.Requests; using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.Social; using osu.Game.Users; -using System; using System.Threading; using osu.Framework.Threading; @@ -33,17 +33,18 @@ namespace osu.Game.Overlays protected override SearchableListHeader CreateHeader() => new Header(); protected override SearchableListFilterControl CreateFilterControl() => new FilterControl(); - private IEnumerable users; + private User[] users = Array.Empty(); - public IEnumerable Users + public User[] Users { get => users; set { - if (ReferenceEquals(users, value)) + if (users == value) return; - users = value?.ToList(); + users = value ?? Array.Empty(); + recreatePanels(); } } @@ -72,8 +73,8 @@ namespace osu.Game.Overlays Filter.Tabs.Current.ValueChanged += _ => onFilterUpdate(); - Filter.DisplayStyleControl.DisplayStyle.ValueChanged += style => recreatePanels(style.NewValue); - Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => updateUsers(Users); + Filter.DisplayStyleControl.DisplayStyle.ValueChanged += _ => recreatePanels(); + Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => recreatePanels(); currentQuery.BindTo(Filter.Search.Current); currentQuery.ValueChanged += query => @@ -115,19 +116,19 @@ namespace osu.Game.Overlays { case SocialTab.Friends: var friendRequest = new GetFriendsRequest(); // TODO filter arguments? - friendRequest.Success += updateUsers; + friendRequest.Success += users => Users = users.ToArray(); API.Queue(getUsersRequest = friendRequest); break; default: var userRequest = new GetUsersRequest(); // TODO filter arguments! - userRequest.Success += res => updateUsers(res.Users.Select(r => r.User)); + userRequest.Success += res => Users = res.Users.Select(r => r.User).ToArray(); API.Queue(getUsersRequest = userRequest); break; } } - private void recreatePanels(PanelDisplayStyle displayStyle) + private void recreatePanels() { clearPanels(); @@ -139,17 +140,33 @@ namespace osu.Game.Overlays loadCancellation = new CancellationTokenSource(); + IEnumerable sortedUsers = Users; + + switch (Filter.Tabs.Current.Value) + { + case SocialSortCriteria.Location: + sortedUsers = sortedUsers.OrderBy(u => u.Country.FullName); + break; + + case SocialSortCriteria.Name: + sortedUsers = sortedUsers.OrderBy(u => u.Username); + break; + } + + if (Filter.DisplayStyleControl.Dropdown.Current.Value == SortDirection.Descending) + sortedUsers = sortedUsers.Reverse(); + var newPanels = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Spacing = new Vector2(10f), Margin = new MarginPadding { Top = 10 }, - ChildrenEnumerable = Users.Select(u => + ChildrenEnumerable = sortedUsers.Select(u => { SocialPanel panel; - switch (displayStyle) + switch (Filter.DisplayStyleControl.DisplayStyle.Value) { case PanelDisplayStyle.Grid: panel = new SocialGridPanel(u) @@ -188,36 +205,9 @@ namespace osu.Game.Overlays return; } - updateUsers(Users); + recreatePanels(); } - private void updateUsers(IEnumerable newUsers) - { - var sortDirection = Filter.DisplayStyleControl.Dropdown.Current.Value; - - IEnumerable sortedUsers = newUsers; - - if (sortedUsers.Any()) - { - switch (Filter.Tabs.Current.Value) - { - case SocialSortCriteria.Location: - sortedUsers = sortBy(sortedUsers, u => u.Country.FullName, sortDirection); - break; - - case SocialSortCriteria.Name: - sortedUsers = sortBy(sortedUsers, u => u.Username, sortDirection); - break; - } - } - - Users = sortedUsers; - recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); - } - - private IEnumerable sortBy(IEnumerable users, Func condition, SortDirection sortDirection) => - sortDirection == SortDirection.Ascending ? users.OrderBy(condition) : users.OrderByDescending(condition); - private void clearPanels() { loading.Show(); From dd68106d909d9deffb321a39536fbb35454bf05d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Dec 2019 02:21:33 +0900 Subject: [PATCH 4647/5608] Recreate panels only while loading/loaded --- osu.Game/Overlays/SocialOverlay.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 01dd1ee635..7cc3b6e3ce 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -17,6 +17,7 @@ using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.Social; using osu.Game.Users; using System.Threading; +using osu.Framework.Allocation; using osu.Framework.Threading; namespace osu.Game.Overlays @@ -44,7 +45,9 @@ namespace osu.Game.Overlays return; users = value ?? Array.Empty(); - recreatePanels(); + + if (LoadState >= LoadState.Ready) + recreatePanels(); } } @@ -70,7 +73,6 @@ namespace osu.Game.Overlays }; Header.Tabs.Current.ValueChanged += _ => queueUpdate(); - Filter.Tabs.Current.ValueChanged += _ => onFilterUpdate(); Filter.DisplayStyleControl.DisplayStyle.ValueChanged += _ => recreatePanels(); @@ -88,6 +90,12 @@ namespace osu.Game.Overlays }; } + [BackgroundDependencyLoader] + private void load() + { + recreatePanels(); + } + private APIRequest getUsersRequest; private readonly Bindable currentQuery = new Bindable(); From a46602f705c2686ad45a58ea2997bb715bb8265e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Dec 2019 11:26:22 +0900 Subject: [PATCH 4648/5608] Move cancellation token construction closer to usage --- osu.Game/Overlays/SocialOverlay.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 7cc3b6e3ce..0c99962def 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -146,8 +146,6 @@ namespace osu.Game.Overlays return; } - loadCancellation = new CancellationTokenSource(); - IEnumerable sortedUsers = Users; switch (Filter.Tabs.Current.Value) @@ -202,7 +200,7 @@ namespace osu.Game.Overlays loading.Hide(); ScrollFlow.Add(panels = newPanels); - }, loadCancellation.Token); + }, (loadCancellation = new CancellationTokenSource()).Token); } private void onFilterUpdate() From 531ac16743edde6d824ae149cd46e26247e12b34 Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Wed, 18 Dec 2019 19:22:42 -0800 Subject: [PATCH 4649/5608] Update Scoreboard Refresh Method for deleting individual scores --- .../Online/Leaderboards/LeaderboardScore.cs | 11 +++- .../Select/BeatmapClearScoresDialog.cs | 22 ------- .../Select/Leaderboards/BeatmapLeaderboard.cs | 25 +++++++- .../Screens/Select/LocalScoreDeleteDialog.cs | 59 +++++++++++++++++++ 4 files changed, 90 insertions(+), 27 deletions(-) create mode 100644 osu.Game/Screens/Select/LocalScoreDeleteDialog.cs diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index ccac748535..2578b6bbea 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -58,8 +58,6 @@ namespace osu.Game.Online.Leaderboards private DialogOverlay dialogOverlay; - public Action RefreshAction { get; set; } - public LeaderboardScore(ScoreInfo score, int rank, bool allowHighlight = true) { this.score = score; @@ -370,13 +368,20 @@ namespace osu.Game.Online.Leaderboards } } + private void deleteLocalScore(ScoreInfo score) + { + if (score == null || score.ID <= 0) return; + + dialogOverlay?.Push(new LocalScoreDeleteDialog(score)); + } + public MenuItem[] ContextMenuItems { get { return (this.allowHighlight) ? null : new MenuItem[] { - new OsuMenuItem("Delete", MenuItemType.Destructive, () => dialogOverlay?.Push(new BeatmapClearScoresDialog(this.score, () => Schedule(this.RefreshAction)))) + new OsuMenuItem("Delete", MenuItemType.Destructive, () => deleteLocalScore(this.score)) }; } } diff --git a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs index 2c5427993b..c9b6ca7bb3 100644 --- a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs +++ b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs @@ -39,28 +39,6 @@ namespace osu.Game.Screens.Select }; } - public BeatmapClearScoresDialog(ScoreInfo score, Action onCompletion) - { - string accuracy = string.Format(score?.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", score?.Accuracy); - - BodyText = $@"{score?.Beatmap?.Metadata?.Artist} - {score?.Beatmap?.Metadata?.Title} {Environment.NewLine} {score?.User} - Rank: {score?.Rank} - Max Combo: {score?.MaxCombo} - {accuracy} - {score?.Date.Date.ToShortDateString()}"; - - Icon = FontAwesome.Solid.Eraser; - HeaderText = @"Clearing this local score. Are you sure?"; - Buttons = new PopupDialogButton[] - { - new PopupDialogOkButton - { - Text = @"Yes. Please.", - Action = (() => scoreManager.Delete(score)) + onCompletion - }, - new PopupDialogCancelButton - { - Text = @"No, I'm still attached.", - }, - }; - } - [BackgroundDependencyLoader] private void load(ScoreManager scoreManager) { diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 8747bc2d28..751ea7fffd 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -19,8 +19,10 @@ namespace osu.Game.Screens.Select.Leaderboards { public class BeatmapLeaderboard : Leaderboard { + public Action ScoreSelected; + [Resolved] private RulesetStore rulesets { get; set; } @@ -103,6 +105,8 @@ namespace osu.Game.Screens.Select.Leaderboards { ScoreSelected = s => ScoreSelected?.Invoke(s) }); + + scoreManager.ItemRemoved += deleteLocalScore; } protected override void Reset() @@ -111,6 +115,16 @@ namespace osu.Game.Screens.Select.Leaderboards TopScore = null; } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (scoreManager != null) + { + scoreManager.ItemRemoved -= deleteLocalScore; + } + } + protected override bool IsOnlineScope => Scope != BeatmapLeaderboardScope.Local; protected override APIRequest FetchScores(Action> scoresCallback) @@ -188,9 +202,16 @@ namespace osu.Game.Screens.Select.Leaderboards return new LeaderboardScore(model, index, IsOnlineScope) { - Action = () => ScoreSelected?.Invoke(model), - RefreshAction = () => this.RefreshScores() + Action = () => ScoreSelected?.Invoke(model) }; } + + private void deleteLocalScore(ScoreInfo score) + { + if (score == null) + return; + + Schedule(() => this.RefreshScores()); + } } } diff --git a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs new file mode 100644 index 0000000000..fb0954bdf2 --- /dev/null +++ b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs @@ -0,0 +1,59 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Game.Overlays.Dialog; +using osu.Game.Scoring; +using System; +using System.Threading.Tasks; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Logging; + +namespace osu.Game.Screens.Select +{ + public class LocalScoreDeleteDialog : PopupDialog + { + private ScoreManager scoreManager; + + public LocalScoreDeleteDialog (ScoreInfo score) + { + try{ + string accuracy = string.Format(score?.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", score?.Accuracy); + + BodyText = $@"{score} {Environment.NewLine} Rank: {score.Rank} - Max Combo: {score.MaxCombo} - {accuracy}"; + Icon = FontAwesome.Solid.Eraser; + HeaderText = @"Clearing this local score. Are you sure?"; + Buttons = new PopupDialogButton[] + { + new PopupDialogOkButton + { + Text = @"Yes. Please.", + Action = () => scoreManager.Delete(score) + }, + new PopupDialogCancelButton + { + Text = @"No, I'm still attached.", + }, + }; + } catch (Exception e){ + Logger.Error(e, "ScoreInfo cannot be null!"); + + HeaderText = $@"ScoreInfo cannot be null!"; + Icon = FontAwesome.Solid.Ambulance; + Buttons = new PopupDialogButton[] + { + new PopupDialogCancelButton + { + Text = @"OK, thanks.", + }, + }; + } + } + + [BackgroundDependencyLoader] + private void load(ScoreManager scoreManager) + { + this.scoreManager = scoreManager; + } + } +} From b67f9860588d1369333d43409ede90b36354ebcb Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Wed, 18 Dec 2019 19:26:35 -0800 Subject: [PATCH 4650/5608] Fix CodeFactor issues --- .../Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 2 -- osu.Game/Screens/Select/LocalScoreDeleteDialog.cs | 9 ++++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 751ea7fffd..df29666a8a 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -19,10 +19,8 @@ namespace osu.Game.Screens.Select.Leaderboards { public class BeatmapLeaderboard : Leaderboard { - public Action ScoreSelected; - [Resolved] private RulesetStore rulesets { get; set; } diff --git a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs index fb0954bdf2..9aa2e5c6e6 100644 --- a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs +++ b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs @@ -15,9 +15,10 @@ namespace osu.Game.Screens.Select { private ScoreManager scoreManager; - public LocalScoreDeleteDialog (ScoreInfo score) + public LocalScoreDeleteDialog(ScoreInfo score) { - try{ + try + { string accuracy = string.Format(score?.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", score?.Accuracy); BodyText = $@"{score} {Environment.NewLine} Rank: {score.Rank} - Max Combo: {score.MaxCombo} - {accuracy}"; @@ -35,7 +36,9 @@ namespace osu.Game.Screens.Select Text = @"No, I'm still attached.", }, }; - } catch (Exception e){ + } + catch (Exception e) + { Logger.Error(e, "ScoreInfo cannot be null!"); HeaderText = $@"ScoreInfo cannot be null!"; From 27163a51338a37cb2eee249d7102aca7d5c49547 Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Wed, 18 Dec 2019 21:04:10 -0800 Subject: [PATCH 4651/5608] Removed unnecessary code for deleting individual local score. --- .../Online/Leaderboards/LeaderboardScore.cs | 7 +-- .../Select/Leaderboards/BeatmapLeaderboard.cs | 5 +- .../Screens/Select/LocalScoreDeleteDialog.cs | 49 +++++++------------ 3 files changed, 20 insertions(+), 41 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 2578b6bbea..54eebd69c1 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.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.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -370,8 +369,6 @@ namespace osu.Game.Online.Leaderboards private void deleteLocalScore(ScoreInfo score) { - if (score == null || score.ID <= 0) return; - dialogOverlay?.Push(new LocalScoreDeleteDialog(score)); } @@ -379,9 +376,9 @@ namespace osu.Game.Online.Leaderboards { get { - return (this.allowHighlight) ? null : new MenuItem[] + return (allowHighlight) ? null : new MenuItem[] { - new OsuMenuItem("Delete", MenuItemType.Destructive, () => deleteLocalScore(this.score)) + new OsuMenuItem("Delete", MenuItemType.Destructive, () => deleteLocalScore(score)), }; } } diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index df29666a8a..8442e91712 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -206,10 +206,7 @@ namespace osu.Game.Screens.Select.Leaderboards private void deleteLocalScore(ScoreInfo score) { - if (score == null) - return; - - Schedule(() => this.RefreshScores()); + Schedule(RefreshScores); } } } diff --git a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs index 9aa2e5c6e6..635906c08a 100644 --- a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs +++ b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs @@ -5,7 +5,7 @@ using osu.Framework.Allocation; using osu.Game.Overlays.Dialog; using osu.Game.Scoring; using System; -using System.Threading.Tasks; +using System.Diagnostics; using osu.Framework.Graphics.Sprites; using osu.Framework.Logging; @@ -17,40 +17,25 @@ namespace osu.Game.Screens.Select public LocalScoreDeleteDialog(ScoreInfo score) { - try - { - string accuracy = string.Format(score?.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", score?.Accuracy); + Debug.Assert(score != null); - BodyText = $@"{score} {Environment.NewLine} Rank: {score.Rank} - Max Combo: {score.MaxCombo} - {accuracy}"; - Icon = FontAwesome.Solid.Eraser; - HeaderText = @"Clearing this local score. Are you sure?"; - Buttons = new PopupDialogButton[] - { - new PopupDialogOkButton - { - Text = @"Yes. Please.", - Action = () => scoreManager.Delete(score) - }, - new PopupDialogCancelButton - { - Text = @"No, I'm still attached.", - }, - }; - } - catch (Exception e) - { - Logger.Error(e, "ScoreInfo cannot be null!"); + string accuracy = string.Format(score.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", score.Accuracy); - HeaderText = $@"ScoreInfo cannot be null!"; - Icon = FontAwesome.Solid.Ambulance; - Buttons = new PopupDialogButton[] + BodyText = $@"{score} {Environment.NewLine} Rank: {score.Rank} - Max Combo: {score.MaxCombo} - {accuracy}"; + Icon = FontAwesome.Solid.Eraser; + HeaderText = @"Deleting this local score. Are you sure?"; + Buttons = new PopupDialogButton[] + { + new PopupDialogOkButton { - new PopupDialogCancelButton - { - Text = @"OK, thanks.", - }, - }; - } + Text = @"Yes. Please.", + Action = () => scoreManager.Delete(score) + }, + new PopupDialogCancelButton + { + Text = @"No, I'm still attached.", + }, + }; } [BackgroundDependencyLoader] From ed07b779b167284f7b51d2031fb67f20bca97eb5 Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Wed, 18 Dec 2019 21:54:02 -0800 Subject: [PATCH 4652/5608] Update to use score.ID identify local scores --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 9 +++------ osu.Game/Screens/Select/LocalScoreDeleteDialog.cs | 1 - 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 54eebd69c1..d2d82d849d 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -374,13 +374,10 @@ namespace osu.Game.Online.Leaderboards public MenuItem[] ContextMenuItems { - get + get => (score.ID == 0) ? null : new MenuItem[] { - return (allowHighlight) ? null : new MenuItem[] - { - new OsuMenuItem("Delete", MenuItemType.Destructive, () => deleteLocalScore(score)), - }; - } + new OsuMenuItem("Delete", MenuItemType.Destructive, () => deleteLocalScore(score)), + }; } } } diff --git a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs index 635906c08a..d5f2195c42 100644 --- a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs +++ b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs @@ -7,7 +7,6 @@ using osu.Game.Scoring; using System; using System.Diagnostics; using osu.Framework.Graphics.Sprites; -using osu.Framework.Logging; namespace osu.Game.Screens.Select { From b1533ae2a9d32eee264464d1d12ee374c59cd1bb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Dec 2019 14:58:56 +0900 Subject: [PATCH 4653/5608] Fix score serialisation failing for unknown mod properties --- osu.Game/Scoring/ScoreInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index c7609e8a0b..c37bab9086 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -89,7 +89,7 @@ namespace osu.Game.Scoring if (mods == null) return null; - return modsJson = JsonConvert.SerializeObject(mods); + return modsJson = JsonConvert.SerializeObject(mods.Select(m => new DeserializedMod { Acronym = m.Acronym })); } set { From 643911ada972f93bcb17d34514b17878dc758a40 Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Wed, 18 Dec 2019 22:41:07 -0800 Subject: [PATCH 4654/5608] Fix code format for CI --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index d2d82d849d..c6a3368a91 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -372,12 +372,18 @@ namespace osu.Game.Online.Leaderboards dialogOverlay?.Push(new LocalScoreDeleteDialog(score)); } + public MenuItem[] ContextMenuItems { - get => (score.ID == 0) ? null : new MenuItem[] + get { - new OsuMenuItem("Delete", MenuItemType.Destructive, () => deleteLocalScore(score)), - }; + List items = new List(); + + if (score.ID != 0) + items.Add(new OsuMenuItem("Delete", MenuItemType.Destructive, () => deleteLocalScore(score))); + + return items.ToArray(); + } } } } From d4d4ddc624c194751e9adbcd319cf42e170798d1 Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Wed, 18 Dec 2019 22:42:26 -0800 Subject: [PATCH 4655/5608] Remove new line for CodeFactor --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index c6a3368a91..c0d366f642 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -372,7 +372,6 @@ namespace osu.Game.Online.Leaderboards dialogOverlay?.Push(new LocalScoreDeleteDialog(score)); } - public MenuItem[] ContextMenuItems { get From 1da8cc86900a3f3538f6c2b7d4edcaa10fcc4f13 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Dec 2019 19:02:11 +0900 Subject: [PATCH 4656/5608] Encapsulate common logic of ScoreProcessor --- .../Rulesets/Scoring/JudgementProcessor.cs | 126 +++++++++++++++++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 129 +++--------------- 2 files changed, 146 insertions(+), 109 deletions(-) create mode 100644 osu.Game/Rulesets/Scoring/JudgementProcessor.cs diff --git a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs new file mode 100644 index 0000000000..854b926846 --- /dev/null +++ b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs @@ -0,0 +1,126 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Extensions.TypeExtensions; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Scoring +{ + public abstract class JudgementProcessor + { + /// + /// The maximum number of hits that can be judged. + /// + protected int MaxHits { get; private set; } + + /// + /// The total number of judged s at the current point in time. + /// + public int JudgedHits { get; private set; } + + protected JudgementProcessor(IBeatmap beatmap) + { + ApplyBeatmap(beatmap); + + Reset(false); + SimulateAutoplay(beatmap); + Reset(true); + } + + /// + /// Applies any properties of the which affect scoring to this . + /// + /// The to read properties from. + protected virtual void ApplyBeatmap(IBeatmap beatmap) + { + } + + /// + /// Applies the score change of a to this . + /// + /// The to apply. + public void ApplyResult(JudgementResult result) + { + JudgedHits++; + + ApplyResultInternal(result); + } + + /// + /// Reverts the score change of a that was applied to this . + /// + /// The judgement scoring result. + public void RevertResult(JudgementResult result) + { + JudgedHits--; + + RevertResultInternal(result); + } + + /// + /// Applies the score change of a to this . + /// + /// + /// Any changes applied via this method can be reverted via . + /// + /// The to apply. + protected abstract void ApplyResultInternal(JudgementResult result); + + /// + /// Reverts the score change of a that was applied to this via . + /// + /// The judgement scoring result. + protected abstract void RevertResultInternal(JudgementResult result); + + /// + /// Resets this to a default state. + /// + /// Whether to store the current state of the for future use. + protected virtual void Reset(bool storeResults) + { + if (storeResults) + MaxHits = JudgedHits; + + JudgedHits = 0; + } + + /// + /// Creates the that represents the scoring result for a . + /// + /// The which was judged. + /// The that provides the scoring information. + protected virtual JudgementResult CreateResult(HitObject hitObject, Judgement judgement) => new JudgementResult(hitObject, judgement); + + /// + /// Simulates an autoplay of the to determine scoring values. + /// + /// This provided temporarily. DO NOT USE. + /// The to simulate. + protected virtual void SimulateAutoplay(IBeatmap beatmap) + { + foreach (var obj in beatmap.HitObjects) + simulate(obj); + + void simulate(HitObject obj) + { + foreach (var nested in obj.NestedHitObjects) + simulate(nested); + + var judgement = obj.CreateJudgement(); + if (judgement == null) + return; + + var result = CreateResult(obj, judgement); + if (result == null) + throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); + + result.Type = judgement.MaxResult; + + ApplyResult(result); + } + } + } +} diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index a8a2294498..f885a860ec 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -7,7 +7,6 @@ using System.Diagnostics; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Extensions; -using osu.Framework.Extensions.TypeExtensions; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; @@ -17,7 +16,7 @@ using osu.Game.Scoring; namespace osu.Game.Rulesets.Scoring { - public class ScoreProcessor + public class ScoreProcessor : JudgementProcessor { private const double base_portion = 0.3; private const double combo_portion = 0.7; @@ -95,16 +94,6 @@ namespace osu.Game.Rulesets.Scoring /// public bool HasFailed { get; private set; } - /// - /// The maximum number of hits that can be judged. - /// - protected int MaxHits { get; private set; } - - /// - /// The total number of judged s at the current point in time. - /// - public int JudgedHits { get; private set; } - private double maxHighestCombo; private double maxBaseScore; @@ -115,8 +104,14 @@ namespace osu.Game.Rulesets.Scoring private double scoreMultiplier = 1; public ScoreProcessor(IBeatmap beatmap) + : base(beatmap) { Debug.Assert(base_portion + combo_portion == 1.0); + } + + protected override void ApplyBeatmap(IBeatmap beatmap) + { + base.ApplyBeatmap(beatmap); Combo.ValueChanged += combo => HighestCombo.Value = Math.Max(HighestCombo.Value, combo.NewValue); Accuracy.ValueChanged += accuracy => @@ -126,12 +121,6 @@ namespace osu.Game.Rulesets.Scoring Rank.Value = mod.AdjustRank(Rank.Value, accuracy.NewValue); }; - ApplyBeatmap(beatmap); - - Reset(false); - SimulateAutoplay(beatmap); - Reset(true); - if (maxBaseScore == 0 || maxHighestCombo == 0) { Mode.Value = ScoringMode.Classic; @@ -150,80 +139,9 @@ namespace osu.Game.Rulesets.Scoring }; } - /// - /// Applies any properties of the which affect scoring to this . - /// - /// The to read properties from. - protected virtual void ApplyBeatmap(IBeatmap beatmap) - { - } - - /// - /// Simulates an autoplay of the to determine scoring values. - /// - /// This provided temporarily. DO NOT USE. - /// The to simulate. - protected virtual void SimulateAutoplay(IBeatmap beatmap) - { - foreach (var obj in beatmap.HitObjects) - simulate(obj); - - void simulate(HitObject obj) - { - foreach (var nested in obj.NestedHitObjects) - simulate(nested); - - var judgement = obj.CreateJudgement(); - if (judgement == null) - return; - - var result = CreateResult(obj, judgement); - if (result == null) - throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); - - result.Type = judgement.MaxResult; - - ApplyResult(result); - } - } - - /// - /// Applies the score change of a to this . - /// - /// The to apply. - public void ApplyResult(JudgementResult result) - { - ApplyResultInternal(result); - - updateScore(); - updateFailed(result); - - NewJudgement?.Invoke(result); - - if (HasCompleted) - AllJudged?.Invoke(); - } - - /// - /// Reverts the score change of a that was applied to this . - /// - /// The judgement scoring result. - public void RevertResult(JudgementResult result) - { - RevertResultInternal(result); - updateScore(); - } - private readonly Dictionary scoreResultCounts = new Dictionary(); - /// - /// Applies the score change of a to this . - /// - /// - /// Any changes applied via this method can be reverted via . - /// - /// The to apply. - protected virtual void ApplyResultInternal(JudgementResult result) + protected sealed override void ApplyResultInternal(JudgementResult result) { result.ComboAtJudgement = Combo.Value; result.HighestComboAtJudgement = HighestCombo.Value; @@ -233,8 +151,6 @@ namespace osu.Game.Rulesets.Scoring if (HasFailed) return; - JudgedHits++; - if (result.Judgement.AffectsCombo) { switch (result.Type) @@ -267,13 +183,17 @@ namespace osu.Game.Rulesets.Scoring } Health.Value += HealthAdjustmentFactorFor(result) * result.Judgement.HealthIncreaseFor(result); + + updateScore(); + updateFailed(result); + + NewJudgement?.Invoke(result); + + if (HasCompleted) + AllJudged?.Invoke(); } - /// - /// Reverts the score change of a that was applied to this via . - /// - /// The judgement scoring result. - protected virtual void RevertResultInternal(JudgementResult result) + protected sealed override void RevertResultInternal(JudgementResult result) { Combo.Value = result.ComboAtJudgement; HighestCombo.Value = result.HighestComboAtJudgement; @@ -284,8 +204,6 @@ namespace osu.Game.Rulesets.Scoring if (result.FailedAtJudgement) return; - JudgedHits--; - if (result.Judgement.IsBonus) { if (result.IsHit) @@ -372,18 +290,18 @@ namespace osu.Game.Rulesets.Scoring /// Resets this ScoreProcessor to a default state. /// /// Whether to store the current state of the for future use. - protected virtual void Reset(bool storeResults) + protected override void Reset(bool storeResults) { + base.Reset(storeResults); + scoreResultCounts.Clear(); if (storeResults) { - MaxHits = JudgedHits; maxHighestCombo = HighestCombo.Value; maxBaseScore = baseScore; } - JudgedHits = 0; baseScore = 0; rollingMaxBaseScore = 0; bonusScore = 0; @@ -425,13 +343,6 @@ namespace osu.Game.Rulesets.Scoring /// Create a for this processor. /// public virtual HitWindows CreateHitWindows() => new HitWindows(); - - /// - /// Creates the that represents the scoring result for a . - /// - /// The which was judged. - /// The that provides the scoring information. - protected virtual JudgementResult CreateResult(HitObject hitObject, Judgement judgement) => new JudgementResult(hitObject, judgement); } public enum ScoringMode From 81e842f6b4bab33100c8f79eae63c6ab41155730 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Dec 2019 19:48:48 +0900 Subject: [PATCH 4657/5608] Fix waveform test beatmap accessing zip archive across multiple threads --- .../Editor/TestSceneEditorComposeTimeline.cs | 14 +++----- osu.Game.Tests/WaveformTestBeatmap.cs | 32 +++++++++++-------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index e618256c03..ed6bc5fe0c 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -68,8 +68,11 @@ namespace osu.Game.Tests.Visual.Editor { private readonly Drawable marker; - private readonly IBindable beatmap = new Bindable(); - private IAdjustableClock adjustableClock; + [Resolved] + private IBindable beatmap { get; set; } + + [Resolved] + private IAdjustableClock adjustableClock { get; set; } public AudioVisualiser() { @@ -91,13 +94,6 @@ namespace osu.Game.Tests.Visual.Editor }; } - [BackgroundDependencyLoader] - private void load(IAdjustableClock adjustableClock, IBindable beatmap) - { - this.adjustableClock = adjustableClock; - this.beatmap.BindTo(beatmap); - } - protected override void Update() { base.Update(); diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index 0d16a78f75..59f322e24c 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -20,23 +20,21 @@ namespace osu.Game.Tests /// public class WaveformTestBeatmap : WorkingBeatmap { - private readonly ZipArchiveReader reader; - private readonly Stream stream; private readonly ITrackStore trackStore; + private Stream getStream() => TestResources.GetTestBeatmapStream(); + + private ZipArchiveReader getZipReader() => new ZipArchiveReader(getStream()); + public WaveformTestBeatmap(AudioManager audioManager) : base(new BeatmapInfo(), audioManager) { - stream = TestResources.GetTestBeatmapStream(); - reader = new ZipArchiveReader(stream); - trackStore = audioManager.GetTrackStore(reader); + trackStore = audioManager.GetTrackStore(getZipReader()); } protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - stream?.Dispose(); - reader?.Dispose(); trackStore?.Dispose(); } @@ -50,15 +48,23 @@ namespace osu.Game.Tests protected override Track GetTrack() => trackStore.Get(firstAudioFile); - private string firstAudioFile => reader.Filenames.First(f => f.EndsWith(".mp3")); - - private Stream getBeatmapStream() => reader.GetStream(reader.Filenames.First(f => f.EndsWith(".osu"))); + private string firstAudioFile + { + get + { + using (var reader = getZipReader()) + return reader.Filenames.First(f => f.EndsWith(".mp3")); + } + } private Beatmap createTestBeatmap() { - using (var beatmapStream = getBeatmapStream()) - using (var beatmapReader = new LineBufferedReader(beatmapStream)) - return Decoder.GetDecoder(beatmapReader).Decode(beatmapReader); + using (var reader = getZipReader()) + { + using (var beatmapStream = reader.GetStream(reader.Filenames.First(f => f.EndsWith(".osu")))) + using (var beatmapReader = new LineBufferedReader(beatmapStream)) + return Decoder.GetDecoder(beatmapReader).Decode(beatmapReader); + } } } } From 76f2fb378fbbed997505b64fd2a6624270a32704 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Dec 2019 20:03:14 +0900 Subject: [PATCH 4658/5608] Separate score and health parts of ScoreProcessor --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 + .../Scoring/CatchHealthProcessor.cs | 38 +++++++ .../Scoring/CatchScoreProcessor.cs | 22 ---- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 + .../Scoring/ManiaHealthProcessor.cs | 69 ++++++++++++ .../Scoring/ManiaScoreProcessor.cs | 69 ------------ osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 6 +- .../Scoring/OsuHealthProcessor.cs | 54 ++++++++++ .../Scoring/OsuScoreProcessor.cs | 33 ------ .../Scoring/TaikoHealthProcessor.cs | 58 ++++++++++ .../Scoring/TaikoScoreProcessor.cs | 42 -------- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 + .../Visual/Gameplay/TestSceneFailAnimation.cs | 2 +- .../Visual/Gameplay/TestSceneFailJudgement.cs | 2 +- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 2 +- .../Visual/Gameplay/TestScenePause.cs | 8 +- .../Mods/IApplicableToHealthProcessor.cs | 15 +++ osu.Game/Rulesets/Mods/ModEasy.cs | 9 +- osu.Game/Rulesets/Mods/ModPerfect.cs | 2 +- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 11 +- osu.Game/Rulesets/Ruleset.cs | 6 ++ osu.Game/Rulesets/Scoring/HealthProcessor.cs | 102 ++++++++++++++++++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 66 +----------- osu.Game/Screens/Play/HUDOverlay.cs | 17 ++- osu.Game/Screens/Play/Player.cs | 30 ++++-- 25 files changed, 404 insertions(+), 265 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs create mode 100644 osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs create mode 100644 osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs create mode 100644 osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs create mode 100644 osu.Game/Rulesets/Mods/IApplicableToHealthProcessor.cs create mode 100644 osu.Game/Rulesets/Scoring/HealthProcessor.cs diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index b8a844cb86..26e6112f83 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -30,6 +30,8 @@ namespace osu.Game.Rulesets.Catch public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new CatchScoreProcessor(beatmap); + public override HealthProcessor CreateHealthProcessor(IBeatmap beatmap) => new CatchHealthProcessor(beatmap); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs new file mode 100644 index 0000000000..49ba0f6122 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs @@ -0,0 +1,38 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Catch.Scoring +{ + public class CatchHealthProcessor : HealthProcessor + { + public CatchHealthProcessor(IBeatmap beatmap) + : base(beatmap) + { + } + + private float hpDrainRate; + + protected override void ApplyBeatmap(IBeatmap beatmap) + { + base.ApplyBeatmap(beatmap); + + hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate; + } + + protected override double HealthAdjustmentFactorFor(JudgementResult result) + { + switch (result.Type) + { + case HitResult.Miss: + return hpDrainRate; + + default: + return 10.2 - hpDrainRate; // Award less HP as drain rate is increased + } + } + } +} diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index f67ca1213e..ad7520d57d 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Scoring @@ -14,27 +13,6 @@ namespace osu.Game.Rulesets.Catch.Scoring { } - private float hpDrainRate; - - protected override void ApplyBeatmap(IBeatmap beatmap) - { - base.ApplyBeatmap(beatmap); - - hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate; - } - - protected override double HealthAdjustmentFactorFor(JudgementResult result) - { - switch (result.Type) - { - case HitResult.Miss: - return hpDrainRate; - - default: - return 10.2 - hpDrainRate; // Award less HP as drain rate is increased - } - } - public override HitWindows CreateHitWindows() => new CatchHitWindows(); } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index bf630cf892..0ec1264cce 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -37,6 +37,8 @@ namespace osu.Game.Rulesets.Mania public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new ManiaScoreProcessor(beatmap); + public override HealthProcessor CreateHealthProcessor(IBeatmap beatmap) => new ManiaHealthProcessor(beatmap); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score); diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs new file mode 100644 index 0000000000..c362c906a4 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs @@ -0,0 +1,69 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Mania.Scoring +{ + public class ManiaHealthProcessor : HealthProcessor + { + /// + /// The hit HP multiplier at OD = 0. + /// + private const double hp_multiplier_min = 0.75; + + /// + /// The hit HP multiplier at OD = 0. + /// + private const double hp_multiplier_mid = 0.85; + + /// + /// The hit HP multiplier at OD = 0. + /// + private const double hp_multiplier_max = 1; + + /// + /// The MISS HP multiplier at OD = 0. + /// + private const double hp_multiplier_miss_min = 0.5; + + /// + /// The MISS HP multiplier at OD = 5. + /// + private const double hp_multiplier_miss_mid = 0.75; + + /// + /// The MISS HP multiplier at OD = 10. + /// + private const double hp_multiplier_miss_max = 1; + + /// + /// The MISS HP multiplier. This is multiplied to the miss hp increase. + /// + private double hpMissMultiplier = 1; + + /// + /// The HIT HP multiplier. This is multiplied to hit hp increases. + /// + private double hpMultiplier = 1; + + public ManiaHealthProcessor(IBeatmap beatmap) + : base(beatmap) + { + } + + protected override void ApplyBeatmap(IBeatmap beatmap) + { + base.ApplyBeatmap(beatmap); + + BeatmapDifficulty difficulty = beatmap.BeatmapInfo.BaseDifficulty; + hpMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_min, hp_multiplier_mid, hp_multiplier_max); + hpMissMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_miss_min, hp_multiplier_miss_mid, hp_multiplier_miss_max); + } + + protected override double HealthAdjustmentFactorFor(JudgementResult result) + => result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier; + } +} diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index a678ef60e7..97f1ea721c 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -2,86 +2,17 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Scoring { internal class ManiaScoreProcessor : ScoreProcessor { - /// - /// The hit HP multiplier at OD = 0. - /// - private const double hp_multiplier_min = 0.75; - - /// - /// The hit HP multiplier at OD = 0. - /// - private const double hp_multiplier_mid = 0.85; - - /// - /// The hit HP multiplier at OD = 0. - /// - private const double hp_multiplier_max = 1; - - /// - /// The MISS HP multiplier at OD = 0. - /// - private const double hp_multiplier_miss_min = 0.5; - - /// - /// The MISS HP multiplier at OD = 5. - /// - private const double hp_multiplier_miss_mid = 0.75; - - /// - /// The MISS HP multiplier at OD = 10. - /// - private const double hp_multiplier_miss_max = 1; - - /// - /// The MISS HP multiplier. This is multiplied to the miss hp increase. - /// - private double hpMissMultiplier = 1; - - /// - /// The HIT HP multiplier. This is multiplied to hit hp increases. - /// - private double hpMultiplier = 1; - public ManiaScoreProcessor(IBeatmap beatmap) : base(beatmap) { } - protected override void ApplyBeatmap(IBeatmap beatmap) - { - base.ApplyBeatmap(beatmap); - - BeatmapDifficulty difficulty = beatmap.BeatmapInfo.BaseDifficulty; - hpMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_min, hp_multiplier_mid, hp_multiplier_max); - hpMissMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_miss_min, hp_multiplier_miss_mid, hp_multiplier_miss_max); - } - - protected override void SimulateAutoplay(IBeatmap beatmap) - { - while (true) - { - base.SimulateAutoplay(beatmap); - - if (!HasFailed) - break; - - hpMultiplier *= 1.01; - hpMissMultiplier *= 0.98; - - Reset(false); - } - } - - protected override double HealthAdjustmentFactorFor(JudgementResult result) - => result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier; - public override HitWindows CreateHitWindows() => new ManiaHitWindows(); } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 63110b2797..831e4a700f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModBlinds : Mod, IApplicableToDrawableRuleset, IApplicableToScoreProcessor + public class OsuModBlinds : Mod, IApplicableToDrawableRuleset, IApplicableToHealthProcessor { public override string Name => "Blinds"; public override string Description => "Play with blinds on your screen."; @@ -37,9 +37,9 @@ namespace osu.Game.Rulesets.Osu.Mods drawableRuleset.Overlays.Add(blinds = new DrawableOsuBlinds(drawableRuleset.Playfield.HitObjectContainer, drawableRuleset.Beatmap)); } - public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + public void ApplyToHealthProcessor(HealthProcessor healthProcessor) { - scoreProcessor.Health.ValueChanged += health => { blinds.AnimateClosedness((float)health.NewValue); }; + healthProcessor.Health.ValueChanged += health => { blinds.AnimateClosedness((float)health.NewValue); }; } public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs new file mode 100644 index 0000000000..36ccc80af6 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs @@ -0,0 +1,54 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Osu.Scoring +{ + public class OsuHealthProcessor : HealthProcessor + { + public OsuHealthProcessor(IBeatmap beatmap) + : base(beatmap) + { + } + + private float hpDrainRate; + + protected override void ApplyBeatmap(IBeatmap beatmap) + { + base.ApplyBeatmap(beatmap); + + hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate; + } + + protected override double HealthAdjustmentFactorFor(JudgementResult result) + { + switch (result.Type) + { + case HitResult.Great: + return 10.2 - hpDrainRate; + + case HitResult.Good: + return 8 - hpDrainRate; + + case HitResult.Meh: + return 4 - hpDrainRate; + + // case HitResult.SliderTick: + // return Math.Max(7 - hpDrainRate, 0) * 0.01; + + case HitResult.Miss: + return hpDrainRate; + + default: + return 0; + } + } + + protected override JudgementResult CreateResult(HitObject hitObject, Judgement judgement) => new OsuJudgementResult(hitObject, judgement); + } +} diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 6779271cb3..4593364e42 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -16,39 +16,6 @@ namespace osu.Game.Rulesets.Osu.Scoring { } - private float hpDrainRate; - - protected override void ApplyBeatmap(IBeatmap beatmap) - { - base.ApplyBeatmap(beatmap); - - hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate; - } - - protected override double HealthAdjustmentFactorFor(JudgementResult result) - { - switch (result.Type) - { - case HitResult.Great: - return 10.2 - hpDrainRate; - - case HitResult.Good: - return 8 - hpDrainRate; - - case HitResult.Meh: - return 4 - hpDrainRate; - - // case HitResult.SliderTick: - // return Math.Max(7 - hpDrainRate, 0) * 0.01; - - case HitResult.Miss: - return hpDrainRate; - - default: - return 0; - } - } - protected override JudgementResult CreateResult(HitObject hitObject, Judgement judgement) => new OsuJudgementResult(hitObject, judgement); public override HitWindows CreateHitWindows() => new OsuHitWindows(); diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs new file mode 100644 index 0000000000..c8aa32a678 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.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 System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Objects; + +namespace osu.Game.Rulesets.Taiko.Scoring +{ + public class TaikoHealthProcessor : HealthProcessor + { + /// + /// A value used for calculating . + /// + private const double object_count_factor = 3; + + /// + /// Taiko fails at the end of the map if the player has not half-filled their HP bar. + /// + protected override bool DefaultFailCondition => JudgedHits == MaxHits && Health.Value <= 0.5; + + /// + /// HP multiplier for a successful . + /// + private double hpMultiplier; + + /// + /// HP multiplier for a . + /// + private double hpMissMultiplier; + + public TaikoHealthProcessor(IBeatmap beatmap) + : base(beatmap) + { + } + + protected override void ApplyBeatmap(IBeatmap beatmap) + { + base.ApplyBeatmap(beatmap); + + hpMultiplier = 1 / (object_count_factor * beatmap.HitObjects.OfType().Count() * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98)); + + hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120); + } + + protected override double HealthAdjustmentFactorFor(JudgementResult result) + => result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier; + + protected override void Reset(bool storeResults) + { + base.Reset(storeResults); + + Health.Value = 0; + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index ae593d2e3a..10011d2669 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -1,60 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Scoring { internal class TaikoScoreProcessor : ScoreProcessor { - /// - /// A value used for calculating . - /// - private const double object_count_factor = 3; - - /// - /// Taiko fails at the end of the map if the player has not half-filled their HP bar. - /// - protected override bool DefaultFailCondition => JudgedHits == MaxHits && Health.Value <= 0.5; - - /// - /// HP multiplier for a successful . - /// - private double hpMultiplier; - - /// - /// HP multiplier for a . - /// - private double hpMissMultiplier; - public TaikoScoreProcessor(IBeatmap beatmap) : base(beatmap) { } - protected override void ApplyBeatmap(IBeatmap beatmap) - { - base.ApplyBeatmap(beatmap); - - hpMultiplier = 1 / (object_count_factor * beatmap.HitObjects.OfType().Count() * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98)); - - hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120); - } - - protected override double HealthAdjustmentFactorFor(JudgementResult result) - => result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier; - - protected override void Reset(bool storeResults) - { - base.Reset(storeResults); - - Health.Value = 0; - } - public override HitWindows CreateHitWindows() => new TaikoHitWindows(); } } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index ca7ab30867..0644f7fea6 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -30,6 +30,8 @@ namespace osu.Game.Rulesets.Taiko public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new TaikoScoreProcessor(beatmap); + public override HealthProcessor CreateHealthProcessor(IBeatmap beatmap) => new TaikoHealthProcessor(beatmap); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); public const string SHORT_NAME = "taiko"; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs index 992c47f856..81050b1637 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void LoadComplete() { base.LoadComplete(); - ScoreProcessor.FailConditions += (_, __) => true; + HealthProcessor.FailConditions += (_, __) => true; } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index 1580aac8c5..a0c25521a6 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void LoadComplete() { base.LoadComplete(); - ScoreProcessor.FailConditions += (_, __) => true; + HealthProcessor.FailConditions += (_, __) => true; } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 39c42980ab..ee58219cd3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -72,7 +72,7 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("create overlay", () => { - Child = hudOverlay = new HUDOverlay(null, null, Array.Empty()); + Child = hudOverlay = new HUDOverlay(null, null, null, Array.Empty()); action?.Invoke(hudOverlay); }); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index e04315894e..1a83e35e4f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestResumeWithResumeOverlay() { AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre)); - AddUntilStep("wait for hitobjects", () => Player.ScoreProcessor.Health.Value < 1); + AddUntilStep("wait for hitobjects", () => Player.HealthProcessor.Health.Value < 1); pauseAndConfirm(); resume(); @@ -73,7 +73,7 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestPauseWithResumeOverlay() { AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre)); - AddUntilStep("wait for hitobjects", () => Player.ScoreProcessor.Health.Value < 1); + AddUntilStep("wait for hitobjects", () => Player.HealthProcessor.Health.Value < 1); pauseAndConfirm(); @@ -92,7 +92,7 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("move cursor to button", () => InputManager.MoveMouseTo(Player.HUDOverlay.HoldToQuit.Children.OfType().First().ScreenSpaceDrawQuad.Centre)); - AddUntilStep("wait for hitobjects", () => Player.ScoreProcessor.Health.Value < 1); + AddUntilStep("wait for hitobjects", () => Player.HealthProcessor.Health.Value < 1); pauseAndConfirm(); resumeAndConfirm(); @@ -285,7 +285,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected class PausePlayer : TestPlayer { - public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + public new HealthProcessor HealthProcessor => base.HealthProcessor; public new HUDOverlay HUDOverlay => base.HUDOverlay; diff --git a/osu.Game/Rulesets/Mods/IApplicableToHealthProcessor.cs b/osu.Game/Rulesets/Mods/IApplicableToHealthProcessor.cs new file mode 100644 index 0000000000..a181955653 --- /dev/null +++ b/osu.Game/Rulesets/Mods/IApplicableToHealthProcessor.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 osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Mods +{ + public interface IApplicableToHealthProcessor : IApplicableMod + { + /// + /// Provide a to a mod. Called once on initialisation of a play instance. + /// + void ApplyToHealthProcessor(HealthProcessor healthProcessor); + } +} diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index a55ebc51d6..494bebbf10 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -7,11 +7,10 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Scoring; -using osu.Game.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModEasy : Mod, IApplicableToDifficulty, IApplicableFailOverride, IApplicableToScoreProcessor + public abstract class ModEasy : Mod, IApplicableToDifficulty, IApplicableFailOverride, IApplicableToHealthProcessor { public override string Name => "Easy"; public override string Acronym => "EZ"; @@ -49,11 +48,9 @@ namespace osu.Game.Rulesets.Mods public bool RestartOnFail => false; - public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + public void ApplyToHealthProcessor(HealthProcessor healthProcessor) { - health = scoreProcessor.Health.GetBoundCopy(); + health = healthProcessor.Health.GetBoundCopy(); } - - public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; } } diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 0994d1f7d3..afa263f1c9 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -15,6 +15,6 @@ namespace osu.Game.Rulesets.Mods public override IconUsage Icon => OsuIcon.ModPerfect; public override string Description => "SS or quit."; - protected override bool FailCondition(ScoreProcessor scoreProcessor, JudgementResult result) => scoreProcessor.Accuracy.Value != 1; + protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) => result.Type != result.Judgement.MaxResult; } } diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index c4c4ab1f04..a4d0631d8c 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -6,11 +6,10 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -using osu.Game.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModSuddenDeath : Mod, IApplicableToScoreProcessor, IApplicableFailOverride + public abstract class ModSuddenDeath : Mod, IApplicableToHealthProcessor, IApplicableFailOverride { public override string Name => "Sudden Death"; public override string Acronym => "SD"; @@ -24,13 +23,11 @@ namespace osu.Game.Rulesets.Mods public bool AllowFail => true; public bool RestartOnFail => true; - public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + public void ApplyToHealthProcessor(HealthProcessor healthProcessor) { - scoreProcessor.FailConditions += FailCondition; + healthProcessor.FailConditions += FailCondition; } - public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; - - protected virtual bool FailCondition(ScoreProcessor scoreProcessor, JudgementResult result) => scoreProcessor.Combo.Value == 0 && result.Judgement.AffectsCombo; + protected virtual bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) => !result.IsHit && result.Judgement.AffectsCombo; } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 7ad93379f0..a98412b434 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -69,6 +69,12 @@ namespace osu.Game.Rulesets /// The score processor. public virtual ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new ScoreProcessor(beatmap); + /// + /// Creates a for a beatmap converted to this ruleset. + /// + /// The health processor. + public virtual HealthProcessor CreateHealthProcessor(IBeatmap beatmap) => new HealthProcessor(beatmap); + /// /// Creates a to convert a to one that is applicable for this . /// diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs new file mode 100644 index 0000000000..8af8177083 --- /dev/null +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.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 System; +using osu.Framework.Bindables; +using osu.Framework.MathUtils; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Judgements; + +namespace osu.Game.Rulesets.Scoring +{ + public class HealthProcessor : JudgementProcessor + { + /// + /// Invoked when the is in a failed state. + /// Return true if the fail was permitted. + /// + public event Func Failed; + + /// + /// Additional conditions on top of that cause a failing state. + /// + public event Func FailConditions; + + /// + /// The current health. + /// + public readonly BindableDouble Health = new BindableDouble(1) { MinValue = 0, MaxValue = 1 }; + + /// + /// Whether this ScoreProcessor has already triggered the failed state. + /// + public bool HasFailed { get; private set; } + + public HealthProcessor(IBeatmap beatmap) + : base(beatmap) + { + } + + protected override void ApplyResultInternal(JudgementResult result) + { + result.HealthAtJudgement = Health.Value; + result.FailedAtJudgement = HasFailed; + + if (HasFailed) + return; + + Health.Value += HealthAdjustmentFactorFor(result) * result.Judgement.HealthIncreaseFor(result); + + if (!DefaultFailCondition && FailConditions?.Invoke(this, result) != true) + return; + + if (Failed?.Invoke() != false) + HasFailed = true; + } + + protected override void RevertResultInternal(JudgementResult result) + { + Health.Value = result.HealthAtJudgement; + + // Todo: Revert HasFailed state with proper player support + } + + /// + /// An adjustment factor which is multiplied into the health increase provided by a . + /// + /// The for which the adjustment should apply. + /// The adjustment factor. + protected virtual double HealthAdjustmentFactorFor(JudgementResult result) => 1; + + /// + /// The default conditions for failing. + /// + protected virtual bool DefaultFailCondition => Precision.AlmostBigger(Health.MinValue, Health.Value); + + protected override void Reset(bool storeResults) + { + base.Reset(storeResults); + + Health.Value = 1; + HasFailed = false; + } + + /// + /// Checks if the score is in a failed state and notifies subscribers. + /// + /// This can only ever notify subscribers once. + /// + /// + private void updateFailed(JudgementResult result) + { + if (HasFailed) + return; + + if (!DefaultFailCondition && FailConditions?.Invoke(this, result) != true) + return; + + if (Failed?.Invoke() != false) + HasFailed = true; + } + } +} diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index f885a860ec..945c21e196 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -7,7 +7,6 @@ using System.Diagnostics; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Extensions; -using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; @@ -22,13 +21,6 @@ namespace osu.Game.Rulesets.Scoring private const double combo_portion = 0.7; private const double max_score = 1000000; - /// - /// Invoked when the is in a failed state. - /// This may occur regardless of whether an event is invoked. - /// Return true if the fail was permitted. - /// - public event Func Failed; - /// /// Invoked when all s have been judged. /// @@ -39,11 +31,6 @@ namespace osu.Game.Rulesets.Scoring /// public event Action NewJudgement; - /// - /// Additional conditions on top of that cause a failing state. - /// - public event Func FailConditions; - /// /// The current total score. /// @@ -54,11 +41,6 @@ namespace osu.Game.Rulesets.Scoring /// public readonly BindableDouble Accuracy = new BindableDouble(1) { MinValue = 0, MaxValue = 1 }; - /// - /// The current health. - /// - public readonly BindableDouble Health = new BindableDouble(1) { MinValue = 0, MaxValue = 1 }; - /// /// The current combo. /// @@ -89,11 +71,6 @@ namespace osu.Game.Rulesets.Scoring /// public bool HasCompleted => JudgedHits == MaxHits; - /// - /// Whether this ScoreProcessor has already triggered the failed state. - /// - public bool HasFailed { get; private set; } - private double maxHighestCombo; private double maxBaseScore; @@ -145,10 +122,8 @@ namespace osu.Game.Rulesets.Scoring { result.ComboAtJudgement = Combo.Value; result.HighestComboAtJudgement = HighestCombo.Value; - result.HealthAtJudgement = Health.Value; - result.FailedAtJudgement = HasFailed; - if (HasFailed) + if (result.FailedAtJudgement) return; if (result.Judgement.AffectsCombo) @@ -182,10 +157,7 @@ namespace osu.Game.Rulesets.Scoring rollingMaxBaseScore += result.Judgement.MaxNumericResult; } - Health.Value += HealthAdjustmentFactorFor(result) * result.Judgement.HealthIncreaseFor(result); - updateScore(); - updateFailed(result); NewJudgement?.Invoke(result); @@ -197,9 +169,6 @@ namespace osu.Game.Rulesets.Scoring { Combo.Value = result.ComboAtJudgement; HighestCombo.Value = result.HighestComboAtJudgement; - Health.Value = result.HealthAtJudgement; - - // Todo: Revert HasFailed state with proper player support if (result.FailedAtJudgement) return; @@ -219,13 +188,6 @@ namespace osu.Game.Rulesets.Scoring } } - /// - /// An adjustment factor which is multiplied into the health increase provided by a . - /// - /// The for which the adjustment should apply. - /// The adjustment factor. - protected virtual double HealthAdjustmentFactorFor(JudgementResult result) => 1; - private void updateScore() { if (rollingMaxBaseScore != 0) @@ -248,24 +210,6 @@ namespace osu.Game.Rulesets.Scoring } } - /// - /// Checks if the score is in a failed state and notifies subscribers. - /// - /// This can only ever notify subscribers once. - /// - /// - private void updateFailed(JudgementResult result) - { - if (HasFailed) - return; - - if (!DefaultFailCondition && FailConditions?.Invoke(this, result) != true) - return; - - if (Failed?.Invoke() != false) - HasFailed = true; - } - private ScoreRank rankFrom(double acc) { if (acc == 1) @@ -308,12 +252,9 @@ namespace osu.Game.Rulesets.Scoring TotalScore.Value = 0; Accuracy.Value = 1; - Health.Value = 1; Combo.Value = 0; Rank.Value = ScoreRank.X; HighestCombo.Value = 0; - - HasFailed = false; } /// @@ -334,11 +275,6 @@ namespace osu.Game.Rulesets.Scoring score.Statistics[result] = GetStatistic(result); } - /// - /// The default conditions for failing. - /// - protected virtual bool DefaultFailCondition => Precision.AlmostBigger(Health.MinValue, Health.Value); - /// /// Create a for this processor. /// diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index e2f362780d..236bdc8442 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -41,6 +41,7 @@ namespace osu.Game.Screens.Play public Bindable ShowHealthbar = new Bindable(true); private readonly ScoreProcessor scoreProcessor; + private readonly HealthProcessor healthProcessor; private readonly DrawableRuleset drawableRuleset; private readonly IReadOnlyList mods; @@ -63,9 +64,10 @@ namespace osu.Game.Screens.Play private IEnumerable hideTargets => new Drawable[] { visibilityContainer, KeyCounter }; - public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, IReadOnlyList mods) + public HUDOverlay(ScoreProcessor scoreProcessor, HealthProcessor healthProcessor, DrawableRuleset drawableRuleset, IReadOnlyList mods) { this.scoreProcessor = scoreProcessor; + this.healthProcessor = healthProcessor; this.drawableRuleset = drawableRuleset; this.mods = mods; @@ -119,7 +121,10 @@ namespace osu.Game.Screens.Play private void load(OsuConfigManager config, NotificationOverlay notificationOverlay) { if (scoreProcessor != null) - BindProcessor(scoreProcessor); + BindScoreProcessor(scoreProcessor); + + if (healthProcessor != null) + BindHealthProcessor(healthProcessor); if (drawableRuleset != null) { @@ -288,15 +293,19 @@ namespace osu.Game.Screens.Play protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); - protected virtual void BindProcessor(ScoreProcessor processor) + protected virtual void BindScoreProcessor(ScoreProcessor processor) { ScoreCounter?.Current.BindTo(processor.TotalScore); AccuracyCounter?.Current.BindTo(processor.Accuracy); ComboCounter?.Current.BindTo(processor.Combo); - HealthDisplay?.Current.BindTo(processor.Health); if (HealthDisplay is StandardHealthDisplay shd) processor.NewJudgement += shd.Flash; } + + protected virtual void BindHealthProcessor(HealthProcessor processor) + { + HealthDisplay?.Current.BindTo(processor.Health); + } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 5dfdeb5ebc..b64604728c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -72,6 +72,9 @@ namespace osu.Game.Screens.Play public BreakOverlay BreakOverlay; protected ScoreProcessor ScoreProcessor { get; private set; } + + protected HealthProcessor HealthProcessor { get; private set; } + protected DrawableRuleset DrawableRuleset { get; private set; } protected HUDOverlay HUDOverlay { get; private set; } @@ -131,6 +134,8 @@ namespace osu.Game.Screens.Play ScoreProcessor = ruleset.CreateScoreProcessor(playableBeatmap); ScoreProcessor.Mods.BindTo(Mods); + HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap); + if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); @@ -145,15 +150,28 @@ namespace osu.Game.Screens.Play // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); - DrawableRuleset.OnNewResult += ScoreProcessor.ApplyResult; - DrawableRuleset.OnRevertResult += ScoreProcessor.RevertResult; + DrawableRuleset.OnNewResult += r => + { + HealthProcessor.ApplyResult(r); + ScoreProcessor.ApplyResult(r); + }; - // Bind ScoreProcessor to ourselves + DrawableRuleset.OnRevertResult += r => + { + HealthProcessor.RevertResult(r); + ScoreProcessor.RevertResult(r); + }; + + // Bind the judgement processors to ourselves ScoreProcessor.AllJudged += onCompletion; - ScoreProcessor.Failed += onFail; + HealthProcessor.Failed += onFail; foreach (var mod in Mods.Value.OfType()) mod.ApplyToScoreProcessor(ScoreProcessor); + + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToHealthProcessor(HealthProcessor); + BreakOverlay.IsBreakTime.ValueChanged += _ => updatePauseOnFocusLostState(); } @@ -197,7 +215,7 @@ namespace osu.Game.Screens.Play // display the cursor above some HUD elements. DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), DrawableRuleset.ResumeOverlay?.CreateProxy() ?? new Container(), - HUDOverlay = new HUDOverlay(ScoreProcessor, DrawableRuleset, Mods.Value) + HUDOverlay = new HUDOverlay(ScoreProcessor, HealthProcessor, DrawableRuleset, Mods.Value) { HoldToQuit = { @@ -342,7 +360,7 @@ namespace osu.Game.Screens.Play private void onCompletion() { // Only show the completion screen if the player hasn't failed - if (ScoreProcessor.HasFailed || completionProgressDelegate != null) + if (HealthProcessor.HasFailed || completionProgressDelegate != null) return; ValidForResume = false; From 04c3a6f8a4c58672cca7b98085548e00197554ce Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Dec 2019 20:18:17 +0900 Subject: [PATCH 4659/5608] Move more properties to the base class --- .../Rulesets/Scoring/JudgementProcessor.cs | 20 ++++++++++++++++++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 21 ------------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs index 854b926846..c7ac466eb0 100644 --- a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs +++ b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs @@ -11,6 +11,16 @@ namespace osu.Game.Rulesets.Scoring { public abstract class JudgementProcessor { + /// + /// Invoked when all s have been judged by this . + /// + public event Action AllJudged; + + /// + /// Invoked when a new judgement has occurred. This occurs after the judgement has been processed by this . + /// + public event Action NewJudgement; + /// /// The maximum number of hits that can be judged. /// @@ -21,6 +31,11 @@ namespace osu.Game.Rulesets.Scoring /// public int JudgedHits { get; private set; } + /// + /// Whether all s have been processed. + /// + public bool HasCompleted => JudgedHits == MaxHits; + protected JudgementProcessor(IBeatmap beatmap) { ApplyBeatmap(beatmap); @@ -47,6 +62,11 @@ namespace osu.Game.Rulesets.Scoring JudgedHits++; ApplyResultInternal(result); + + NewJudgement?.Invoke(result); + + if (HasCompleted) + AllJudged?.Invoke(); } /// diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 945c21e196..093ba16e57 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -10,7 +10,6 @@ using osu.Framework.Extensions; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects; using osu.Game.Scoring; namespace osu.Game.Rulesets.Scoring @@ -21,16 +20,6 @@ namespace osu.Game.Rulesets.Scoring private const double combo_portion = 0.7; private const double max_score = 1000000; - /// - /// Invoked when all s have been judged. - /// - public event Action AllJudged; - - /// - /// Invoked when a new judgement has occurred. This occurs after the judgement has been processed by the . - /// - public event Action NewJudgement; - /// /// The current total score. /// @@ -66,11 +55,6 @@ namespace osu.Game.Rulesets.Scoring /// public readonly Bindable Mode = new Bindable(); - /// - /// Whether all s have been processed. - /// - public bool HasCompleted => JudgedHits == MaxHits; - private double maxHighestCombo; private double maxBaseScore; @@ -158,11 +142,6 @@ namespace osu.Game.Rulesets.Scoring } updateScore(); - - NewJudgement?.Invoke(result); - - if (HasCompleted) - AllJudged?.Invoke(); } protected sealed override void RevertResultInternal(JudgementResult result) From 50fa6c5f77284fe61805f7bd04f473e5f93558d4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Dec 2019 20:18:23 +0900 Subject: [PATCH 4660/5608] Update score on reverts --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 093ba16e57..acd394d955 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -165,6 +165,8 @@ namespace osu.Game.Rulesets.Scoring baseScore -= result.Judgement.NumericResultFor(result); rollingMaxBaseScore -= result.Judgement.MaxNumericResult; } + + updateScore(); } private void updateScore() From a3154f2f7b3046db8930de15b55636adf6f510d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Dec 2019 20:30:58 +0900 Subject: [PATCH 4661/5608] 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 abb3cc8244..dd11804b90 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 e5f34b1c7e..757e0e11fa 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 c84e617285..0dba92b975 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 3ac0e3ce51cd811cb2cc07afbfd329aae5e853a5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Dec 2019 23:03:31 +0900 Subject: [PATCH 4662/5608] Fix iOS project failing to compile --- osu.Game.Rulesets.Catch.Tests.iOS/Application.cs | 2 +- osu.Game.Rulesets.Mania.Tests.iOS/Application.cs | 2 +- osu.Game.Rulesets.Osu.Tests.iOS/Application.cs | 2 +- osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs | 2 +- osu.Game.Tests.iOS/Application.cs | 2 +- osu.iOS/Application.cs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs index beca477943..f7f07ef938 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs @@ -5,7 +5,7 @@ using UIKit; namespace osu.Game.Rulesets.Catch.Tests.iOS { - public class Application + public static class Application { public static void Main(string[] args) { diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs index 0362402320..c381ea585d 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs @@ -5,7 +5,7 @@ using UIKit; namespace osu.Game.Rulesets.Mania.Tests.iOS { - public class Application + public static class Application { public static void Main(string[] args) { diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs index 3718264a42..b36d0b5728 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs @@ -5,7 +5,7 @@ using UIKit; namespace osu.Game.Rulesets.Osu.Tests.iOS { - public class Application + public static class Application { public static void Main(string[] args) { diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs index 330cb42901..73faf16d9f 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs @@ -5,7 +5,7 @@ using UIKit; namespace osu.Game.Rulesets.Taiko.Tests.iOS { - public class Application + public static class Application { public static void Main(string[] args) { diff --git a/osu.Game.Tests.iOS/Application.cs b/osu.Game.Tests.iOS/Application.cs index d96a3e27a4..9533b90131 100644 --- a/osu.Game.Tests.iOS/Application.cs +++ b/osu.Game.Tests.iOS/Application.cs @@ -5,7 +5,7 @@ using UIKit; namespace osu.Game.Tests.iOS { - public class Application + public static class Application { public static void Main(string[] args) { diff --git a/osu.iOS/Application.cs b/osu.iOS/Application.cs index 30e0e15ad1..740937e0e1 100644 --- a/osu.iOS/Application.cs +++ b/osu.iOS/Application.cs @@ -5,7 +5,7 @@ using UIKit; namespace osu.iOS { - public class Application + public static class Application { public static void Main(string[] args) { From 7d090d6cd90fd14810aa84d0c30d549f198c09a7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Dec 2019 17:52:58 +0300 Subject: [PATCH 4663/5608] Fix key overlay appearing regardless of the setting --- osu.Game/Screens/Play/KeyCounterDisplay.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index 1edb95ca46..9c107f0293 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -43,6 +43,11 @@ namespace osu.Game.Screens.Play private void load(OsuConfigManager config) { config.BindWith(OsuSetting.KeyOverlay, configVisibility); + } + + protected override void LoadComplete() + { + base.LoadComplete(); Visible.BindValueChanged(_ => updateVisibility()); configVisibility.BindValueChanged(_ => updateVisibility(), true); From 656c58450305770ec5f76a7742cf3964e74c40aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Dec 2019 13:50:47 +0900 Subject: [PATCH 4664/5608] Update RestoreDefaultValueButton when default value changes --- osu.Game/Overlays/Settings/SettingsItem.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 9c390c34ec..31fcb7abd8 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -113,6 +113,7 @@ namespace osu.Game.Overlays.Settings bindable = value; bindable.ValueChanged += _ => UpdateState(); bindable.DisabledChanged += _ => UpdateState(); + bindable.DefaultChanged += _ => UpdateState(); UpdateState(); } } From de8154bc7f5af6a970715c35b347d7900915f34b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Dec 2019 13:54:13 +0900 Subject: [PATCH 4665/5608] Update readme with new testflight link source --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e2e854c755..753dee548b 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ If you are not interested in developing the game, you can still consume our [bin **Latest build:** -| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) | [iOS(iOS 10+)](https://testflight.apple.com/join/2tLcjWlF) | [Android (5+)](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) +| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) | [iOS(iOS 10+)](https://osu.ppy.sh/home/testflight) | [Android (5+)](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) | ------------- | ------------- | ------------- | ------------- | - **Linux** users are recommended to self-compile until we have official deployment in place. From 11214628adb34e9cec915706c38b9efae6833d64 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Dec 2019 13:50:57 +0900 Subject: [PATCH 4666/5608] Add post-update notification for iOS users --- osu.Game/Updater/UpdateManager.cs | 5 ++++- osu.iOS/OsuGameIOS.cs | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Updater/UpdateManager.cs b/osu.Game/Updater/UpdateManager.cs index e256cdbe45..48505a9891 100644 --- a/osu.Game/Updater/UpdateManager.cs +++ b/osu.Game/Updater/UpdateManager.cs @@ -11,7 +11,10 @@ using osu.Game.Overlays.Notifications; namespace osu.Game.Updater { - public abstract class UpdateManager : CompositeDrawable + /// + /// An update manager which only shows notifications after an update completes. + /// + public class UpdateManager : CompositeDrawable { [Resolved] private OsuConfigManager config { get; set; } diff --git a/osu.iOS/OsuGameIOS.cs b/osu.iOS/OsuGameIOS.cs index 6cf18df9a6..e5ff4aec95 100644 --- a/osu.iOS/OsuGameIOS.cs +++ b/osu.iOS/OsuGameIOS.cs @@ -4,11 +4,19 @@ using System; using Foundation; using osu.Game; +using osu.Game.Updater; namespace osu.iOS { public class OsuGameIOS : OsuGame { public override Version AssemblyVersion => new Version(NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString()); + + protected override void LoadComplete() + { + base.LoadComplete(); + + Add(new UpdateManager()); + } } } From 8ab26e8889ee5ca41d129e0aa9e0ba2db7c2fb8a Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Thu, 19 Dec 2019 21:29:54 -0800 Subject: [PATCH 4667/5608] Update Tests with dependencies on LeaderboardScore. Added its dependency on DialogOverlay for the tests. Added test for deleting individual local score --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 21 +- .../TestSceneUserTopScoreContainer.cs | 22 +- .../TestSceneDeleteLocalScore.cs | 230 ++++++++++++++++++ .../Online/Leaderboards/LeaderboardScore.cs | 2 +- 4 files changed, 270 insertions(+), 5 deletions(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 57e297bcd5..551fffde54 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -3,10 +3,12 @@ using System; using System.Collections.Generic; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; +using osu.Game.Overlays; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; using osu.Game.Screens.Select.Leaderboards; @@ -28,15 +30,22 @@ namespace osu.Game.Tests.Visual.SongSelect private readonly FailableLeaderboard leaderboard; + private DialogOverlay dialogOverlay; + public TestSceneBeatmapLeaderboard() { - Add(leaderboard = new FailableLeaderboard + Add(dialogOverlay = new DialogOverlay() + { + Depth = -1 + }); + + leaderboard = new FailableLeaderboard { Origin = Anchor.Centre, Anchor = Anchor.Centre, Size = new Vector2(550f, 450f), Scope = BeatmapLeaderboardScope.Global, - }); + }; AddStep(@"New Scores", newScores); AddStep(@"Show personal best", showPersonalBest); @@ -281,5 +290,13 @@ namespace osu.Game.Tests.Visual.SongSelect PlaceholderState = state; } } + + [BackgroundDependencyLoader] + private void load() + { + Dependencies.Cache(dialogOverlay); + + Add(leaderboard); + } } } diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs index e34e1844ce..0545f13d44 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs @@ -1,11 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osuTK.Graphics; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; using osu.Game.Scoring; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.Select.Leaderboards; @@ -15,11 +17,19 @@ namespace osu.Game.Tests.Visual.SongSelect { public class TestSceneUserTopScoreContainer : OsuTestScene { + private DialogOverlay dialogOverlay; + private Container container; + public TestSceneUserTopScoreContainer() { UserTopScoreContainer topScoreContainer; - Add(new Container + Add(dialogOverlay = new DialogOverlay() + { + Depth = -1 + }); + + container = new Container { Origin = Anchor.BottomCentre, Anchor = Anchor.Centre, @@ -38,7 +48,7 @@ namespace osu.Game.Tests.Visual.SongSelect Anchor = Anchor.BottomCentre, } } - }); + }; var scores = new[] { @@ -114,5 +124,13 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"Add score(rank 22333)", () => topScoreContainer.Score.Value = scores[2]); AddStep(@"Add null score", () => topScoreContainer.Score.Value = null); } + + [BackgroundDependencyLoader] + private void load() + { + Dependencies.Cache(dialogOverlay); + + Add(container); + } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs new file mode 100644 index 0000000000..5a75cb3e08 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -0,0 +1,230 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Sprites; +using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Online.Leaderboards; +using osu.Game.Overlays; +using osu.Game.Overlays.Dialog; +using osu.Game.Scoring; +using osu.Game.Screens.Select.Leaderboards; +using osu.Game.Users; +using osuTK; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneDeleteLocalScore : ManualInputManagerTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(Placeholder), + typeof(MessagePlaceholder), + typeof(RetrievalFailurePlaceholder), + typeof(UserTopScoreContainer), + typeof(Leaderboard), + typeof(LeaderboardScore), + + }; + + private readonly FailableLeaderboard leaderboard; + + private DialogOverlay dialogOverlay; + + public TestSceneDeleteLocalScore() + { + Add(dialogOverlay = new DialogOverlay() + { + Depth = -1 + }); + + leaderboard = new FailableLeaderboard(dialogOverlay) + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(550f, 450f), + Scope = BeatmapLeaderboardScope.Local, + Beatmap = new BeatmapInfo + { + ID = 1, + Metadata = new BeatmapMetadata + { + ID = 1, + Title = "TestSong", + Artist = "TestArtist", + Author = new User + { + Username = "TestAuthor" + }, + }, + Version = "Insane" + }, + }; + + AddStep("Insert Locacl Scores", null); + + TestConfirmDeleteLocalScore(); + TestCancelDeleteLocalScore(); + } + + private void TestConfirmDeleteLocalScore() + { + AddStep("Move to leaderboard", () => InputManager.MoveMouseTo(leaderboard)); + AddStep("Show ContextMenu", () => InputManager.Click(MouseButton.Right)); + AddUntilStep("Wait for ContextMenu", () => typeof(OsuContextMenu) == InputManager.FocusedDrawable.GetType() && InputManager.FocusedDrawable.IsLoaded); + AddStep("Move to Delete Context Menu", () => InputManager.MoveMouseTo(InputManager.FocusedDrawable)); + AddStep("Show Delete Score Dialog", () => InputManager.Click(MouseButton.Left)); + AddUntilStep("Wait for DialogOverlay", () => dialogOverlay.CurrentDialog.IsLoaded); + AddStep("Move to confirm button", () => InputManager.MoveMouseTo(((TestLocalScoreDeleteDialog)dialogOverlay.CurrentDialog).confirmButton)); + AddStep("Confirm Action", () => InputManager.Click(MouseButton.Left)); + AddAssert("Check Score Count", () => leaderboard.ScoreCount() == 49); + } + + private void TestCancelDeleteLocalScore() + { + AddStep("Move to leaderboard", () => InputManager.MoveMouseTo(leaderboard)); + AddStep("Show ContextMenu", () => InputManager.Click(MouseButton.Right)); + AddUntilStep("Wait for ContextMenu", () => typeof(OsuContextMenu) == InputManager.FocusedDrawable.GetType() && InputManager.FocusedDrawable.IsLoaded); + AddStep("Move to Delete Context Menu", () => InputManager.MoveMouseTo(InputManager.FocusedDrawable)); + AddStep("Show Delete Score Dialog", () => InputManager.Click(MouseButton.Left)); + AddUntilStep("Wait for DialogOverlay", () => dialogOverlay.CurrentDialog.IsLoaded); + AddStep("Move to cancel button", () => InputManager.MoveMouseTo(((TestLocalScoreDeleteDialog)dialogOverlay.CurrentDialog).cancelButton)); + AddStep("Cancel Action", () => InputManager.Click(MouseButton.Left)); + AddAssert("Check Score Count", () => leaderboard.ScoreCount() == 49); + } + + [BackgroundDependencyLoader] + private void load() + { + Dependencies.Cache(dialogOverlay); + Add(leaderboard); + } + + private class FailableLeaderboard : BeatmapLeaderboard + { + private DialogOverlay dialogOverlay; + + private List scoreList; + + private Random rnd; + + private bool initialLoad; + + public void DeleteScore(ScoreInfo score) + { + scoreList.Remove(score); + RefreshScores(); + } + + public int ScoreCount() + { + return scoreList.Count; + } + + public FailableLeaderboard(DialogOverlay dialogOverlay) + : base() + { + this.dialogOverlay = dialogOverlay; + initialLoad = true; + } + + public void SetRetrievalState(PlaceholderState state) + { + PlaceholderState = state; + } + + protected override APIRequest FetchScores(Action> scoresCallback) + { + if (initialLoad) + { + rnd = new Random(); + + scoreList = Enumerable.Range(1, 50).Select(createScore).ToList(); + Scores = scoreList.OrderByDescending(s => s.TotalScore).ToArray(); + + initialLoad = false; + } + else + { + Scores = scoreList.OrderByDescending(s => s.TotalScore).ToArray(); + } + + return null; + } + + private ScoreInfo createScore(int id) => new ScoreInfo + { + ID = id, + Accuracy = rnd.NextDouble(), + PP = rnd.Next(1, 1000000), + TotalScore = rnd.Next(1, 1000000), + MaxCombo = rnd.Next(1, 1000), + Rank = ScoreRank.XH, + User = new User { Username = "TestUser" }, + }; + + protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) + { + model.Beatmap = Beatmap; + return new TestLeaderboardScore(model, index, dialogOverlay, this, IsOnlineScope); + } + } + + private class TestLeaderboardScore : LeaderboardScore + { + private DialogOverlay dialogOverlay; + + private FailableLeaderboard leaderboard; + + public TestLeaderboardScore(ScoreInfo score, int rank, DialogOverlay dialogOverlay, FailableLeaderboard leaderboard, bool allowHighlight = true) + : base(score, rank, allowHighlight) + { + this.dialogOverlay = dialogOverlay; + this.leaderboard = leaderboard; + } + + protected override void deleteLocalScore(ScoreInfo score) + { + dialogOverlay?.Push(new TestLocalScoreDeleteDialog(score, leaderboard)); + } + } + + private class TestLocalScoreDeleteDialog : PopupDialog + { + public PopupDialogOkButton confirmButton; + + public PopupDialogCancelButton cancelButton; + + public TestLocalScoreDeleteDialog(ScoreInfo score, FailableLeaderboard leaderboard) + { + Debug.Assert(score != null); + + string accuracy = string.Format(score.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", score.Accuracy); + + BodyText = $@"{score} {Environment.NewLine} Rank: {score.Rank} - Max Combo: {score.MaxCombo} - {accuracy}"; + Icon = FontAwesome.Solid.Eraser; + HeaderText = @"Deleting this local score. Are you sure?"; + Buttons = new PopupDialogButton[] + { + confirmButton = new PopupDialogOkButton + { + Text = @"Yes. Please.", + Action = () => leaderboard.DeleteScore(score) + }, + cancelButton = new PopupDialogCancelButton + { + Text = @"No, I'm still attached.", + }, + }; + } + } + } +} diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index c0d366f642..b706adb8ff 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -367,7 +367,7 @@ namespace osu.Game.Online.Leaderboards } } - private void deleteLocalScore(ScoreInfo score) + protected virtual void deleteLocalScore(ScoreInfo score) { dialogOverlay?.Push(new LocalScoreDeleteDialog(score)); } From e42894cfcf86f6a5a78036b5833f819eed7d7238 Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Thu, 19 Dec 2019 21:32:54 -0800 Subject: [PATCH 4668/5608] Fixed error for CodeFactor --- osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index 5a75cb3e08..fbfe3b835e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -32,7 +32,6 @@ namespace osu.Game.Tests.Visual.UserInterface typeof(UserTopScoreContainer), typeof(Leaderboard), typeof(LeaderboardScore), - }; private readonly FailableLeaderboard leaderboard; From 6abbd33b512b34cca22eec8b64629b02aa4fbd93 Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Thu, 19 Dec 2019 21:57:14 -0800 Subject: [PATCH 4669/5608] Fixed CI issues --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 4 +-- .../TestSceneUserTopScoreContainer.cs | 6 ++--- .../TestSceneDeleteLocalScore.cs | 25 +++++++++---------- .../Online/Leaderboards/LeaderboardScore.cs | 4 +-- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 551fffde54..386fadc0d3 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -30,11 +30,11 @@ namespace osu.Game.Tests.Visual.SongSelect private readonly FailableLeaderboard leaderboard; - private DialogOverlay dialogOverlay; + private readonly DialogOverlay dialogOverlay; public TestSceneBeatmapLeaderboard() { - Add(dialogOverlay = new DialogOverlay() + Add(dialogOverlay = new DialogOverlay { Depth = -1 }); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs index 0545f13d44..c69626321d 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs @@ -17,14 +17,14 @@ namespace osu.Game.Tests.Visual.SongSelect { public class TestSceneUserTopScoreContainer : OsuTestScene { - private DialogOverlay dialogOverlay; - private Container container; + private readonly DialogOverlay dialogOverlay; + private readonly Container container; public TestSceneUserTopScoreContainer() { UserTopScoreContainer topScoreContainer; - Add(dialogOverlay = new DialogOverlay() + Add(dialogOverlay = new DialogOverlay { Depth = -1 }); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index fbfe3b835e..e804891444 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -36,11 +36,11 @@ namespace osu.Game.Tests.Visual.UserInterface private readonly FailableLeaderboard leaderboard; - private DialogOverlay dialogOverlay; + private readonly DialogOverlay dialogOverlay; public TestSceneDeleteLocalScore() { - Add(dialogOverlay = new DialogOverlay() + Add(dialogOverlay = new DialogOverlay { Depth = -1 }); @@ -70,11 +70,11 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Insert Locacl Scores", null); - TestConfirmDeleteLocalScore(); - TestCancelDeleteLocalScore(); + testConfirmDeleteLocalScore(); + testCancelDeleteLocalScore(); } - private void TestConfirmDeleteLocalScore() + private void testConfirmDeleteLocalScore() { AddStep("Move to leaderboard", () => InputManager.MoveMouseTo(leaderboard)); AddStep("Show ContextMenu", () => InputManager.Click(MouseButton.Right)); @@ -87,7 +87,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("Check Score Count", () => leaderboard.ScoreCount() == 49); } - private void TestCancelDeleteLocalScore() + private void testCancelDeleteLocalScore() { AddStep("Move to leaderboard", () => InputManager.MoveMouseTo(leaderboard)); AddStep("Show ContextMenu", () => InputManager.Click(MouseButton.Right)); @@ -109,7 +109,7 @@ namespace osu.Game.Tests.Visual.UserInterface private class FailableLeaderboard : BeatmapLeaderboard { - private DialogOverlay dialogOverlay; + private readonly DialogOverlay dialogOverlay; private List scoreList; @@ -129,7 +129,6 @@ namespace osu.Game.Tests.Visual.UserInterface } public FailableLeaderboard(DialogOverlay dialogOverlay) - : base() { this.dialogOverlay = dialogOverlay; initialLoad = true; @@ -179,9 +178,9 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestLeaderboardScore : LeaderboardScore { - private DialogOverlay dialogOverlay; + private readonly DialogOverlay dialogOverlay; - private FailableLeaderboard leaderboard; + private readonly FailableLeaderboard leaderboard; public TestLeaderboardScore(ScoreInfo score, int rank, DialogOverlay dialogOverlay, FailableLeaderboard leaderboard, bool allowHighlight = true) : base(score, rank, allowHighlight) @@ -190,7 +189,7 @@ namespace osu.Game.Tests.Visual.UserInterface this.leaderboard = leaderboard; } - protected override void deleteLocalScore(ScoreInfo score) + protected override void DeleteLocalScore(ScoreInfo score) { dialogOverlay?.Push(new TestLocalScoreDeleteDialog(score, leaderboard)); } @@ -198,9 +197,9 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestLocalScoreDeleteDialog : PopupDialog { - public PopupDialogOkButton confirmButton; + public readonly PopupDialogOkButton confirmButton; - public PopupDialogCancelButton cancelButton; + public readonly PopupDialogCancelButton cancelButton; public TestLocalScoreDeleteDialog(ScoreInfo score, FailableLeaderboard leaderboard) { diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index b706adb8ff..b49a8bf483 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -367,7 +367,7 @@ namespace osu.Game.Online.Leaderboards } } - protected virtual void deleteLocalScore(ScoreInfo score) + protected virtual void DeleteLocalScore(ScoreInfo score) { dialogOverlay?.Push(new LocalScoreDeleteDialog(score)); } @@ -379,7 +379,7 @@ namespace osu.Game.Online.Leaderboards List items = new List(); if (score.ID != 0) - items.Add(new OsuMenuItem("Delete", MenuItemType.Destructive, () => deleteLocalScore(score))); + items.Add(new OsuMenuItem("Delete", MenuItemType.Destructive, () => DeleteLocalScore(score))); return items.ToArray(); } From 6672cf60590f101acb7d7c7871597d2a9b039df4 Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Thu, 19 Dec 2019 22:22:46 -0800 Subject: [PATCH 4670/5608] Update variable name --- .../Visual/UserInterface/TestSceneDeleteLocalScore.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index e804891444..635ad904e3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -82,7 +82,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Move to Delete Context Menu", () => InputManager.MoveMouseTo(InputManager.FocusedDrawable)); AddStep("Show Delete Score Dialog", () => InputManager.Click(MouseButton.Left)); AddUntilStep("Wait for DialogOverlay", () => dialogOverlay.CurrentDialog.IsLoaded); - AddStep("Move to confirm button", () => InputManager.MoveMouseTo(((TestLocalScoreDeleteDialog)dialogOverlay.CurrentDialog).confirmButton)); + AddStep("Move to confirm button", () => InputManager.MoveMouseTo(((TestLocalScoreDeleteDialog)dialogOverlay.CurrentDialog).ConfirmButton)); AddStep("Confirm Action", () => InputManager.Click(MouseButton.Left)); AddAssert("Check Score Count", () => leaderboard.ScoreCount() == 49); } @@ -95,7 +95,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Move to Delete Context Menu", () => InputManager.MoveMouseTo(InputManager.FocusedDrawable)); AddStep("Show Delete Score Dialog", () => InputManager.Click(MouseButton.Left)); AddUntilStep("Wait for DialogOverlay", () => dialogOverlay.CurrentDialog.IsLoaded); - AddStep("Move to cancel button", () => InputManager.MoveMouseTo(((TestLocalScoreDeleteDialog)dialogOverlay.CurrentDialog).cancelButton)); + AddStep("Move to cancel button", () => InputManager.MoveMouseTo(((TestLocalScoreDeleteDialog)dialogOverlay.CurrentDialog).CancelButton)); AddStep("Cancel Action", () => InputManager.Click(MouseButton.Left)); AddAssert("Check Score Count", () => leaderboard.ScoreCount() == 49); } @@ -197,9 +197,9 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestLocalScoreDeleteDialog : PopupDialog { - public readonly PopupDialogOkButton confirmButton; + public readonly PopupDialogOkButton ConfirmButton; - public readonly PopupDialogCancelButton cancelButton; + public readonly PopupDialogCancelButton CancelButton; public TestLocalScoreDeleteDialog(ScoreInfo score, FailableLeaderboard leaderboard) { From afc11aa547b8401cf0b22f5478e186cabdc61762 Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Thu, 19 Dec 2019 22:37:09 -0800 Subject: [PATCH 4671/5608] Fixed issues caused by renaming variables --- .../Visual/UserInterface/TestSceneDeleteLocalScore.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index 635ad904e3..da91051175 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -212,12 +212,12 @@ namespace osu.Game.Tests.Visual.UserInterface HeaderText = @"Deleting this local score. Are you sure?"; Buttons = new PopupDialogButton[] { - confirmButton = new PopupDialogOkButton + ConfirmButton = new PopupDialogOkButton { Text = @"Yes. Please.", Action = () => leaderboard.DeleteScore(score) }, - cancelButton = new PopupDialogCancelButton + CancelButton = new PopupDialogCancelButton { Text = @"No, I'm still attached.", }, From 1802e0ff111559f07dd28eba251498d3e2876b1b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Dec 2019 16:04:05 +0900 Subject: [PATCH 4672/5608] Fix storyboard incorrectly re-ordering elements --- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 67c4105e6d..b1b27278fe 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using osuTK; using osuTK.Graphics; using osu.Framework.Extensions; @@ -42,10 +41,6 @@ namespace osu.Game.Beatmaps.Formats { this.storyboard = storyboard; base.ParseStreamInto(stream, storyboard); - - // OrderBy is used to guarantee that the parsing order of elements with equal start times is maintained (stably-sorted) - foreach (StoryboardLayer layer in storyboard.Layers) - layer.Elements = layer.Elements.OrderBy(h => h.StartTime).ToList(); } protected override void ParseLine(Storyboard storyboard, Section section, string line) From 705cdde148db14e740e51d02662a0152800b5666 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Dec 2019 16:42:45 +0900 Subject: [PATCH 4673/5608] Fix incorrect test --- osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index 66d53d7e7b..96ff6b81e3 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs @@ -71,7 +71,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(new Vector2(320, 240), sprite.InitialPosition); Assert.IsTrue(sprite.IsDrawable); Assert.AreEqual(Anchor.Centre, sprite.Origin); - Assert.AreEqual("SB/black.jpg", sprite.Path); + Assert.AreEqual("SB/lyric/ja-21.png", sprite.Path); var animation = background.Elements.OfType().First(); Assert.NotNull(animation); From 822903d5db8476bcc7c38629b03c21ea8ea0bd30 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Dec 2019 18:00:04 +0900 Subject: [PATCH 4674/5608] Update song select statistics when mod changes settings --- osu.Game/Overlays/Settings/ISettingsItem.cs | 13 +++++++ osu.Game/Overlays/Settings/SettingsItem.cs | 16 +++++---- .../Screens/Select/Details/AdvancedStats.cs | 36 ++++++++++++++++++- 3 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Overlays/Settings/ISettingsItem.cs diff --git a/osu.Game/Overlays/Settings/ISettingsItem.cs b/osu.Game/Overlays/Settings/ISettingsItem.cs new file mode 100644 index 0000000000..e7afa48502 --- /dev/null +++ b/osu.Game/Overlays/Settings/ISettingsItem.cs @@ -0,0 +1,13 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Graphics; + +namespace osu.Game.Overlays.Settings +{ + public interface ISettingsItem : IDrawable, IDisposable + { + event Action SettingChanged; + } +} diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 31fcb7abd8..35f28ab1b2 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -20,7 +21,7 @@ using osuTK; namespace osu.Game.Overlays.Settings { - public abstract class SettingsItem : Container, IFilterable + public abstract class SettingsItem : Container, IFilterable, ISettingsItem { protected abstract Drawable CreateControl(); @@ -34,8 +35,6 @@ namespace osu.Game.Overlays.Settings private SpriteText text; - private readonly RestoreDefaultValueButton restoreDefaultButton; - public bool ShowsDefaultIndicator = true; public virtual string LabelText @@ -70,8 +69,12 @@ namespace osu.Game.Overlays.Settings public bool FilteringActive { get; set; } + public event Action SettingChanged; + protected SettingsItem() { + RestoreDefaultValueButton restoreDefaultButton; + RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Padding = new MarginPadding { Right = SettingsPanel.CONTENT_MARGINS }; @@ -87,13 +90,12 @@ namespace osu.Game.Overlays.Settings Child = Control = CreateControl() }, }; - } - [BackgroundDependencyLoader] - private void load() - { + // all bindable logic is in constructor intentionally to support "CreateSettingsControls" being used in a context it is + // never loaded, but requires bindable storage. if (controlWithCurrent != null) { + controlWithCurrent.Current.ValueChanged += _ => SettingChanged?.Invoke(); controlWithCurrent.Current.DisabledChanged += disabled => { Colour = disabled ? Color4.Gray : Color4.White; }; if (ShowsDefaultIndicator) diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 9c9c33274f..ad2b5885d7 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -16,6 +16,10 @@ using osu.Framework.Bindables; using System.Collections.Generic; using osu.Game.Rulesets.Mods; using System.Linq; +using System.Threading.Tasks; +using osu.Framework.Threading; +using osu.Game.Configuration; +using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Select.Details { @@ -69,7 +73,37 @@ namespace osu.Game.Screens.Select.Details { base.LoadComplete(); - mods.BindValueChanged(_ => updateStatistics(), true); + mods.BindValueChanged(modsChanged, true); + } + + private readonly List references = new List(); + + private void modsChanged(ValueChangedEvent> mods) + { + // TODO: find a more permanent solution for this if/when it is needed in other components. + // this is generating drawables for the only purpose of storing bindable references. + foreach (var r in references) + r.Dispose(); + + references.Clear(); + + ScheduledDelegate debounce = null; + + foreach (var mod in mods.NewValue.OfType()) + { + foreach (var setting in mod.CreateSettingsControls().OfType()) + { + setting.SettingChanged += () => + { + debounce?.Cancel(); + debounce = Scheduler.AddDelayed(updateStatistics, 100); + }; + + references.Add(setting); + } + } + + updateStatistics(); } private void updateStatistics() From 351e826120093ea0fb383f37237b361d4debd741 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 16 Dec 2019 15:28:18 +0800 Subject: [PATCH 4675/5608] Upgrade project targets to netcoreapp3.1 --- .../CatchRuleset__Tests_.xml | 4 +-- .../ManiaRuleset__Tests_.xml | 4 +-- .../runConfigurations/OsuRuleset__Tests_.xml | 4 +-- .../TaikoRuleset__Tests_.xml | 4 +-- .../.idea/runConfigurations/Tournament.xml | 4 +-- .../runConfigurations/Tournament__Tests_.xml | 4 +-- .../.idea/runConfigurations/osu_.xml | 4 +-- .../.idea/runConfigurations/osu___Tests_.xml | 4 +-- .vscode/launch.json | 32 +++++++++---------- .vscode/tasks.json | 2 +- README.md | 4 +-- osu.Desktop/osu.Desktop.csproj | 2 +- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- .../osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- .../osu.Game.Tournament.Tests.csproj | 2 +- 18 files changed, 42 insertions(+), 42 deletions(-) diff --git a/.idea/.idea.osu.Desktop/.idea/runConfigurations/CatchRuleset__Tests_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/CatchRuleset__Tests_.xml index 5372b6f28a..a4154623b6 100644 --- a/.idea/.idea.osu.Desktop/.idea/runConfigurations/CatchRuleset__Tests_.xml +++ b/.idea/.idea.osu.Desktop/.idea/runConfigurations/CatchRuleset__Tests_.xml @@ -1,6 +1,6 @@ - WinExe - netcoreapp3.0 + netcoreapp3.1 diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index 8fc4dbfe72..dea6e6c0fb 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -9,7 +9,7 @@ WinExe - netcoreapp3.0 + netcoreapp3.1 diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index fddf176fd0..9d4e016eae 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -9,7 +9,7 @@ WinExe - netcoreapp3.0 + netcoreapp3.1 diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index b5bd384e05..d728d65bfd 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -9,7 +9,7 @@ WinExe - netcoreapp3.0 + netcoreapp3.1 diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index c5998c9cfc..6c799e5e90 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -10,7 +10,7 @@ WinExe - netcoreapp3.0 + netcoreapp3.1 diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index d58a724c27..7ecfd6ef70 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -11,7 +11,7 @@ WinExe - netcoreapp3.0 + netcoreapp3.1 From 0ebdf90dfa9d4ed99b6df992844fe16a85beaf33 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Dec 2019 18:07:39 +0900 Subject: [PATCH 4676/5608] Move methods below ctor --- osu.Game.Tests/WaveformTestBeatmap.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index 59f322e24c..b7d7bb1ee1 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -22,10 +22,6 @@ namespace osu.Game.Tests { private readonly ITrackStore trackStore; - private Stream getStream() => TestResources.GetTestBeatmapStream(); - - private ZipArchiveReader getZipReader() => new ZipArchiveReader(getStream()); - public WaveformTestBeatmap(AudioManager audioManager) : base(new BeatmapInfo(), audioManager) { @@ -38,6 +34,10 @@ namespace osu.Game.Tests trackStore?.Dispose(); } + private Stream getStream() => TestResources.GetTestBeatmapStream(); + + private ZipArchiveReader getZipReader() => new ZipArchiveReader(getStream()); + protected override IBeatmap GetBeatmap() => createTestBeatmap(); protected override Texture GetBackground() => null; From a6bdf04f6b6372fc7e6fb4f62d7dcb27e761c6f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Dec 2019 18:36:39 +0900 Subject: [PATCH 4677/5608] Remove unused using --- osu.Game/Screens/Select/Details/AdvancedStats.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index ad2b5885d7..a147527f6c 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -16,7 +16,6 @@ using osu.Framework.Bindables; using System.Collections.Generic; using osu.Game.Rulesets.Mods; using System.Linq; -using System.Threading.Tasks; using osu.Framework.Threading; using osu.Game.Configuration; using osu.Game.Overlays.Settings; From 492a91067191708b5e4d1896181249a4c0fcb3ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Dec 2019 19:08:05 +0900 Subject: [PATCH 4678/5608] Update missed launch configurations --- osu.Game.Rulesets.Catch.Tests/.vscode/launch.json | 4 ++-- osu.Game.Rulesets.Mania.Tests/.vscode/launch.json | 4 ++-- osu.Game.Rulesets.Osu.Tests/.vscode/launch.json | 4 ++-- osu.Game.Rulesets.Taiko.Tests/.vscode/launch.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/.vscode/launch.json b/osu.Game.Rulesets.Catch.Tests/.vscode/launch.json index 4030d2d9e7..67d27c33eb 100644 --- a/osu.Game.Rulesets.Catch.Tests/.vscode/launch.json +++ b/osu.Game.Rulesets.Catch.Tests/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Debug/netcoreapp3.0/osu.Game.Rulesets.Catch.Tests.dll" + "${workspaceRoot}/bin/Debug/netcoreapp3.1/osu.Game.Rulesets.Catch.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Debug)", @@ -20,7 +20,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Release/netcoreapp3.0/osu.Game.Rulesets.Catch.Tests.dll" + "${workspaceRoot}/bin/Release/netcoreapp3.1/osu.Game.Rulesets.Catch.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release)", diff --git a/osu.Game.Rulesets.Mania.Tests/.vscode/launch.json b/osu.Game.Rulesets.Mania.Tests/.vscode/launch.json index 779eb4f277..0811c2724c 100644 --- a/osu.Game.Rulesets.Mania.Tests/.vscode/launch.json +++ b/osu.Game.Rulesets.Mania.Tests/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Debug/netcoreapp3.0/osu.Game.Rulesets.Mania.Tests.dll" + "${workspaceRoot}/bin/Debug/netcoreapp3.1/osu.Game.Rulesets.Mania.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Debug)", @@ -20,7 +20,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Release/netcoreapp3.0/osu.Game.Rulesets.Mania.Tests.dll" + "${workspaceRoot}/bin/Release/netcoreapp3.1/osu.Game.Rulesets.Mania.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release)", diff --git a/osu.Game.Rulesets.Osu.Tests/.vscode/launch.json b/osu.Game.Rulesets.Osu.Tests/.vscode/launch.json index 67338b7bbe..94568e3852 100644 --- a/osu.Game.Rulesets.Osu.Tests/.vscode/launch.json +++ b/osu.Game.Rulesets.Osu.Tests/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Debug/netcoreapp3.0/osu.Game.Rulesets.Osu.Tests.dll" + "${workspaceRoot}/bin/Debug/netcoreapp3.1/osu.Game.Rulesets.Osu.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Debug)", @@ -20,7 +20,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Release/netcoreapp3.0/osu.Game.Rulesets.Osu.Tests.dll" + "${workspaceRoot}/bin/Release/netcoreapp3.1/osu.Game.Rulesets.Osu.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release)", diff --git a/osu.Game.Rulesets.Taiko.Tests/.vscode/launch.json b/osu.Game.Rulesets.Taiko.Tests/.vscode/launch.json index 7d929e6bbf..5b02ecfc91 100644 --- a/osu.Game.Rulesets.Taiko.Tests/.vscode/launch.json +++ b/osu.Game.Rulesets.Taiko.Tests/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Debug/netcoreapp3.0/osu.Game.Rulesets.Taiko.Tests.dll" + "${workspaceRoot}/bin/Debug/netcoreapp3.1/osu.Game.Rulesets.Taiko.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Debug)", @@ -20,7 +20,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Release/netcoreapp3.0/osu.Game.Rulesets.Taiko.Tests.dll" + "${workspaceRoot}/bin/Release/netcoreapp3.1/osu.Game.Rulesets.Taiko.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release)", From ba2cff60ca15827c16836ff9f222452e15a01499 Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Fri, 20 Dec 2019 02:13:49 -0800 Subject: [PATCH 4679/5608] Removed Automation Testing steps for delete local scores. Only manual testing now. --- .../TestSceneDeleteLocalScore.cs | 60 +++++-------------- 1 file changed, 16 insertions(+), 44 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index da91051175..0441d8659e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.Leaderboards; using osu.Game.Overlays; @@ -18,7 +17,6 @@ using osu.Game.Scoring; using osu.Game.Screens.Select.Leaderboards; using osu.Game.Users; using osuTK; -using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { @@ -45,7 +43,7 @@ namespace osu.Game.Tests.Visual.UserInterface Depth = -1 }); - leaderboard = new FailableLeaderboard(dialogOverlay) + leaderboard = new FailableLeaderboard { Origin = Anchor.Centre, Anchor = Anchor.Centre, @@ -68,36 +66,13 @@ namespace osu.Game.Tests.Visual.UserInterface }, }; - AddStep("Insert Locacl Scores", null); - - testConfirmDeleteLocalScore(); - testCancelDeleteLocalScore(); + AddStep("Insert Local Scores", () => reset()); } - private void testConfirmDeleteLocalScore() + private void reset() { - AddStep("Move to leaderboard", () => InputManager.MoveMouseTo(leaderboard)); - AddStep("Show ContextMenu", () => InputManager.Click(MouseButton.Right)); - AddUntilStep("Wait for ContextMenu", () => typeof(OsuContextMenu) == InputManager.FocusedDrawable.GetType() && InputManager.FocusedDrawable.IsLoaded); - AddStep("Move to Delete Context Menu", () => InputManager.MoveMouseTo(InputManager.FocusedDrawable)); - AddStep("Show Delete Score Dialog", () => InputManager.Click(MouseButton.Left)); - AddUntilStep("Wait for DialogOverlay", () => dialogOverlay.CurrentDialog.IsLoaded); - AddStep("Move to confirm button", () => InputManager.MoveMouseTo(((TestLocalScoreDeleteDialog)dialogOverlay.CurrentDialog).ConfirmButton)); - AddStep("Confirm Action", () => InputManager.Click(MouseButton.Left)); - AddAssert("Check Score Count", () => leaderboard.ScoreCount() == 49); - } - - private void testCancelDeleteLocalScore() - { - AddStep("Move to leaderboard", () => InputManager.MoveMouseTo(leaderboard)); - AddStep("Show ContextMenu", () => InputManager.Click(MouseButton.Right)); - AddUntilStep("Wait for ContextMenu", () => typeof(OsuContextMenu) == InputManager.FocusedDrawable.GetType() && InputManager.FocusedDrawable.IsLoaded); - AddStep("Move to Delete Context Menu", () => InputManager.MoveMouseTo(InputManager.FocusedDrawable)); - AddStep("Show Delete Score Dialog", () => InputManager.Click(MouseButton.Left)); - AddUntilStep("Wait for DialogOverlay", () => dialogOverlay.CurrentDialog.IsLoaded); - AddStep("Move to cancel button", () => InputManager.MoveMouseTo(((TestLocalScoreDeleteDialog)dialogOverlay.CurrentDialog).CancelButton)); - AddStep("Cancel Action", () => InputManager.Click(MouseButton.Left)); - AddAssert("Check Score Count", () => leaderboard.ScoreCount() == 49); + leaderboard.initialLoad = true; + leaderboard.RefreshScores(); } [BackgroundDependencyLoader] @@ -109,13 +84,11 @@ namespace osu.Game.Tests.Visual.UserInterface private class FailableLeaderboard : BeatmapLeaderboard { - private readonly DialogOverlay dialogOverlay; - private List scoreList; private Random rnd; - private bool initialLoad; + public bool initialLoad; public void DeleteScore(ScoreInfo score) { @@ -123,14 +96,8 @@ namespace osu.Game.Tests.Visual.UserInterface RefreshScores(); } - public int ScoreCount() + public FailableLeaderboard() { - return scoreList.Count; - } - - public FailableLeaderboard(DialogOverlay dialogOverlay) - { - this.dialogOverlay = dialogOverlay; initialLoad = true; } @@ -172,20 +139,19 @@ namespace osu.Game.Tests.Visual.UserInterface protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) { model.Beatmap = Beatmap; - return new TestLeaderboardScore(model, index, dialogOverlay, this, IsOnlineScope); + return new TestLeaderboardScore(model, index, this, IsOnlineScope); } } private class TestLeaderboardScore : LeaderboardScore { - private readonly DialogOverlay dialogOverlay; + private DialogOverlay dialogOverlay; private readonly FailableLeaderboard leaderboard; - public TestLeaderboardScore(ScoreInfo score, int rank, DialogOverlay dialogOverlay, FailableLeaderboard leaderboard, bool allowHighlight = true) + public TestLeaderboardScore(ScoreInfo score, int rank, FailableLeaderboard leaderboard, bool allowHighlight = true) : base(score, rank, allowHighlight) { - this.dialogOverlay = dialogOverlay; this.leaderboard = leaderboard; } @@ -193,6 +159,12 @@ namespace osu.Game.Tests.Visual.UserInterface { dialogOverlay?.Push(new TestLocalScoreDeleteDialog(score, leaderboard)); } + + [BackgroundDependencyLoader] + private void load(DialogOverlay dialogOverlay) + { + this.dialogOverlay = dialogOverlay; + } } private class TestLocalScoreDeleteDialog : PopupDialog From 08b477ed5248211d9f501258b33b906a8efa7c7b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Dec 2019 18:30:23 +0800 Subject: [PATCH 4680/5608] make ModDifficultyAdjust abstract --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- .../Mods/CatchModDifficultyAdjust.cs | 52 ++++++++++++++ osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../Mods/ManiaModDifficultyAdjust.cs | 32 +++++++++ .../Mods/OsuModDifficultyAdjust.cs | 52 ++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../Mods/TaikoModDifficultyAdjust.cs | 32 +++++++++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 67 ++++++------------- 9 files changed, 193 insertions(+), 50 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs create mode 100644 osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs create mode 100644 osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 8f946343a7..4228b86795 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -109,7 +109,7 @@ namespace osu.Game.Rulesets.Catch case ModType.Conversion: return new Mod[] { - new ModDifficultyAdjust(), + new CatchModDifficultyAdjust(), }; case ModType.Automation: diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs new file mode 100644 index 0000000000..127b6c1c0b --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs @@ -0,0 +1,52 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModDifficultyAdjust : ModDifficultyAdjust + { + [SettingSource("Drain Rate", "Override a beatmap's set HP.")] + public override BindableNumber DrainRate { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; + + [SettingSource("Fruit Size", "Override a beatmap's set CS.")] + public override BindableNumber CircleSize { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; + + [SettingSource("Approach Rate", "Override a beatmap's set AR.")] + public override BindableNumber ApproachRate { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; + + [SettingSource("Overall Difficulty", "Override a beatmap's set OD.")] + public override BindableNumber OverallDifficulty { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; + } +} diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index ea64dfaffa..9ab588c550 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -151,7 +151,7 @@ namespace osu.Game.Rulesets.Mania new ManiaModRandom(), new ManiaModDualStages(), new ManiaModMirror(), - new ModDifficultyAdjust(), + new ManiaModDifficultyAdjust(), }; case ModType.Automation: diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs new file mode 100644 index 0000000000..fd1315523c --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs @@ -0,0 +1,32 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModDifficultyAdjust : ModDifficultyAdjust + { + [SettingSource("Drain Rate", "Override a beatmap's set HP.")] + public override BindableNumber DrainRate { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; + + [SettingSource("Overall Difficulty", "Override a beatmap's set OD.")] + public override BindableNumber OverallDifficulty { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs new file mode 100644 index 0000000000..3531e002b8 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs @@ -0,0 +1,52 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModDifficultyAdjust : ModDifficultyAdjust + { + [SettingSource("Drain Rate", "Override a beatmap's set HP.")] + public override BindableNumber DrainRate { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; + + [SettingSource("Circle Size", "Override a beatmap's set CS.")] + public override BindableNumber CircleSize { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; + + [SettingSource("Approach Rate", "Override a beatmap's set AR.")] + public override BindableNumber ApproachRate { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; + + [SettingSource("Overall Difficulty", "Override a beatmap's set OD.")] + public override BindableNumber OverallDifficulty { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index d097235839..a42402151f 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -130,7 +130,7 @@ namespace osu.Game.Rulesets.Osu return new Mod[] { new OsuModTarget(), - new ModDifficultyAdjust(), + new OsuModDifficultyAdjust(), }; case ModType.Automation: diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs new file mode 100644 index 0000000000..b7007eedcd --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs @@ -0,0 +1,32 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModDifficultyAdjust : ModDifficultyAdjust + { + [SettingSource("Drain Rate", "Override a beatmap's set HP.")] + public override BindableNumber DrainRate { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; + + [SettingSource("Overall Difficulty", "Override a beatmap's set OD.")] + public override BindableNumber OverallDifficulty { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; + } +} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 29b74fc4e0..a055c29efe 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -108,7 +108,7 @@ namespace osu.Game.Rulesets.Taiko case ModType.Conversion: return new Mod[] { - new ModDifficultyAdjust(), + new TaikoModDifficultyAdjust(), }; case ModType.Automation: diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs index b23297345b..625749903a 100644 --- a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -5,11 +5,10 @@ using osu.Game.Beatmaps; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using System; -using osu.Game.Configuration; namespace osu.Game.Rulesets.Mods { - public class ModDifficultyAdjust : Mod, IApplicableToDifficulty + public abstract class ModDifficultyAdjust : Mod, IApplicableToDifficulty { public override string Name => @"Difficulty Adjust"; @@ -25,45 +24,13 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => new[] { typeof(ModEasy), typeof(ModHardRock) }; - [SettingSource("Drain Rate", "Override the beatmap's set HP")] - public BindableNumber DrainRate { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; + public virtual BindableNumber DrainRate { get; } - [SettingSource("Circle Size", "Override the beatmap's set CS")] - public BindableNumber CircleSize { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; + public virtual BindableNumber CircleSize { get; } - [SettingSource("Approach Rate", "Override the beatmap's set AR")] - public BindableNumber ApproachRate { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; + public virtual BindableNumber ApproachRate { get; } - [SettingSource("Overall Difficulty", "Override the beatmap's set OD")] - public BindableNumber OverallDifficulty { get; } = new BindableFloat - { - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - Precision = 0.1F, - }; + public virtual BindableNumber OverallDifficulty { get; } private BeatmapDifficulty difficulty; @@ -72,17 +39,25 @@ namespace osu.Game.Rulesets.Mods if (this.difficulty == null || this.difficulty.ID != difficulty.ID) { this.difficulty = difficulty; - DrainRate.Value = DrainRate.Default = difficulty.DrainRate; - CircleSize.Value = CircleSize.Default = difficulty.CircleSize; - ApproachRate.Value = ApproachRate.Default = difficulty.ApproachRate; - OverallDifficulty.Value = OverallDifficulty.Default = difficulty.OverallDifficulty; + + if (DrainRate != null) + DrainRate.Value = DrainRate.Default = difficulty.DrainRate; + + if (CircleSize != null) + CircleSize.Value = CircleSize.Default = difficulty.CircleSize; + + if (ApproachRate != null) + ApproachRate.Value = ApproachRate.Default = difficulty.ApproachRate; + + if (OverallDifficulty != null) + OverallDifficulty.Value = OverallDifficulty.Default = difficulty.OverallDifficulty; } else { - difficulty.DrainRate = DrainRate.Value; - difficulty.CircleSize = CircleSize.Value; - difficulty.ApproachRate = ApproachRate.Value; - difficulty.OverallDifficulty = OverallDifficulty.Value; + difficulty.DrainRate = DrainRate?.Value ?? difficulty.DrainRate; + difficulty.CircleSize = CircleSize?.Value ?? difficulty.CircleSize; + difficulty.ApproachRate = ApproachRate?.Value ?? difficulty.ApproachRate; + difficulty.OverallDifficulty = OverallDifficulty?.Value ?? difficulty.OverallDifficulty; } } } From 1bd44529dd31302a62a55d424135c316233d5384 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Dec 2019 18:31:16 +0800 Subject: [PATCH 4681/5608] add full-stop to mod description for consistency --- osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs index 625749903a..546533709e 100644 --- a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mods { public override string Name => @"Difficulty Adjust"; - public override string Description => @"Override a beatmap's difficulty settings"; + public override string Description => @"Override a beatmap's difficulty settings."; public override string Acronym => "DA"; From 0eef21894561c17718fc641d94db16a193fabd03 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Dec 2019 18:42:29 +0800 Subject: [PATCH 4682/5608] add missing new line --- osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs index 3531e002b8..4847ddc3c4 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs @@ -49,4 +49,4 @@ namespace osu.Game.Rulesets.Osu.Mods Value = 5, }; } -} \ No newline at end of file +} From df14f473c25f023b8b5cc25c0dca8a9042a89f05 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Dec 2019 19:00:37 +0900 Subject: [PATCH 4683/5608] Split tests out --- .../SongSelect/TestSceneBeatmapDetailArea.cs | 156 ++++++++---------- 1 file changed, 66 insertions(+), 90 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index 66144cbfe4..de4e77fe70 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -25,57 +25,43 @@ namespace osu.Game.Tests.Visual.SongSelect private ModDisplay modDisplay; + private BeatmapDetailArea detailsArea; + + [Resolved] + private RulesetStore rulesets { get; set; } + [BackgroundDependencyLoader] private void load(OsuGameBase game, RulesetStore rulesets) { - BeatmapDetailArea detailsArea; - Add(detailsArea = new BeatmapDetailArea - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(550f, 450f), - }); + } - Add(modDisplay = new ModDisplay + [SetUp] + public void SetUp() => Schedule(() => + { + Children = new Drawable[] { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Position = new Vector2(0, 25), - }); + detailsArea = new BeatmapDetailArea + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(550f, 450f), + }, + modDisplay = new ModDisplay + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Position = new Vector2(0, 25), + } + }; modDisplay.Current.BindTo(SelectedMods); + }); - AddStep("all metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap - { - BeatmapInfo = - { - BeatmapSet = new BeatmapSetInfo - { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } - }, - Version = "All Metrics", - Metadata = new BeatmapMetadata - { - Source = "osu!lazer", - Tags = "this beatmap has all the metrics", - }, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 7, - DrainRate = 1, - OverallDifficulty = 5.7f, - ApproachRate = 3.5f, - }, - StarDifficulty = 5.3f, - Metrics = new BeatmapMetrics - { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, - } - })); - + [Test] + public void TestBasicScenarios() + { + showAllMetrics(); AddStep("all except source", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { BeatmapInfo = @@ -178,60 +164,50 @@ namespace osu.Game.Tests.Visual.SongSelect })); AddStep("null beatmap", () => detailsArea.Beatmap = null); + } + + [Test] + public void TestModAdjustments() + { + showAllMetrics(); Ruleset ruleset = rulesets.AvailableRulesets.First().CreateInstance(); - AddStep("with EZ mod", () => + AddStep("with EZ mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModEasy) }); + AddStep("with HR mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModHardRock) }); + } + + private void showAllMetrics() + { + AddStep("all metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { - detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap + BeatmapInfo = { - BeatmapInfo = + BeatmapSet = new BeatmapSetInfo { - Version = "Has Easy Mod", - Metadata = new BeatmapMetadata - { - Source = "osu!lazer", - Tags = "this beatmap has the easy mod enabled", - }, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 3, - DrainRate = 3, - OverallDifficulty = 3, - ApproachRate = 3, - }, - StarDifficulty = 1f, - } - }); - - SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModEasy) }; - }); - - AddStep("with HR mod", () => - { - detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap - { - BeatmapInfo = + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + }, + Version = "All Metrics", + Metadata = new BeatmapMetadata { - Version = "Has Hard Rock Mod", - Metadata = new BeatmapMetadata - { - Source = "osu!lazer", - Tags = "this beatmap has the hard rock mod enabled", - }, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 3, - DrainRate = 3, - OverallDifficulty = 3, - ApproachRate = 3, - }, - StarDifficulty = 1f, - } - }); - - SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModHardRock) }; - }); + Source = "osu!lazer", + Tags = "this beatmap has all the metrics", + }, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 7, + DrainRate = 1, + OverallDifficulty = 5.7f, + ApproachRate = 3.5f, + }, + StarDifficulty = 5.3f, + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + }, + } + })); } } } From a55e5c5c437da004583e22e4297632f5e29d376e Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Fri, 20 Dec 2019 11:16:54 -0800 Subject: [PATCH 4684/5608] Removed unnecessary code --- .../TestSceneDeleteLocalScore.cs | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index 0441d8659e..6ca75ea9cb 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -66,12 +66,12 @@ namespace osu.Game.Tests.Visual.UserInterface }, }; - AddStep("Insert Local Scores", () => reset()); + AddStep("Insert Local Scores", reset); } private void reset() { - leaderboard.initialLoad = true; + leaderboard.InitialLoad = true; leaderboard.RefreshScores(); } @@ -88,7 +88,7 @@ namespace osu.Game.Tests.Visual.UserInterface private Random rnd; - public bool initialLoad; + public bool InitialLoad; public void DeleteScore(ScoreInfo score) { @@ -98,7 +98,7 @@ namespace osu.Game.Tests.Visual.UserInterface public FailableLeaderboard() { - initialLoad = true; + InitialLoad = true; } public void SetRetrievalState(PlaceholderState state) @@ -108,14 +108,14 @@ namespace osu.Game.Tests.Visual.UserInterface protected override APIRequest FetchScores(Action> scoresCallback) { - if (initialLoad) + if (InitialLoad) { rnd = new Random(); scoreList = Enumerable.Range(1, 50).Select(createScore).ToList(); Scores = scoreList.OrderByDescending(s => s.TotalScore).ToArray(); - initialLoad = false; + InitialLoad = false; } else { @@ -169,10 +169,6 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestLocalScoreDeleteDialog : PopupDialog { - public readonly PopupDialogOkButton ConfirmButton; - - public readonly PopupDialogCancelButton CancelButton; - public TestLocalScoreDeleteDialog(ScoreInfo score, FailableLeaderboard leaderboard) { Debug.Assert(score != null); @@ -184,12 +180,12 @@ namespace osu.Game.Tests.Visual.UserInterface HeaderText = @"Deleting this local score. Are you sure?"; Buttons = new PopupDialogButton[] { - ConfirmButton = new PopupDialogOkButton + new PopupDialogOkButton { Text = @"Yes. Please.", Action = () => leaderboard.DeleteScore(score) }, - CancelButton = new PopupDialogCancelButton + new PopupDialogCancelButton { Text = @"No, I'm still attached.", }, From 8353c893c07200bc6a97f00b3153e17c446b0b0b Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Fri, 20 Dec 2019 12:00:10 -0800 Subject: [PATCH 4685/5608] Update BodyText of LocalScoreDeleteDialog --- .../Visual/UserInterface/TestSceneDeleteLocalScore.cs | 2 +- osu.Game/Screens/Select/LocalScoreDeleteDialog.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index 6ca75ea9cb..2369b22ec2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -175,7 +175,7 @@ namespace osu.Game.Tests.Visual.UserInterface string accuracy = string.Format(score.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", score.Accuracy); - BodyText = $@"{score} {Environment.NewLine} Rank: {score.Rank} - Max Combo: {score.MaxCombo} - {accuracy}"; + BodyText = $@"{score.User}'s {accuracy} {score.Rank} Rank on {score.Beatmap}"; Icon = FontAwesome.Solid.Eraser; HeaderText = @"Deleting this local score. Are you sure?"; Buttons = new PopupDialogButton[] diff --git a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs index d5f2195c42..3f52b54e64 100644 --- a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs +++ b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Select string accuracy = string.Format(score.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", score.Accuracy); - BodyText = $@"{score} {Environment.NewLine} Rank: {score.Rank} - Max Combo: {score.MaxCombo} - {accuracy}"; + BodyText = $@"{score.User}'s {accuracy} {score.Rank} Rank on {score.Beatmap}"; Icon = FontAwesome.Solid.Eraser; HeaderText = @"Deleting this local score. Are you sure?"; Buttons = new PopupDialogButton[] From 8e60ae70393e891776cee0f2431eb927b8eef007 Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Fri, 20 Dec 2019 15:45:20 -0800 Subject: [PATCH 4686/5608] Removed directive is not required --- osu.Game/Screens/Select/LocalScoreDeleteDialog.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs index 3f52b54e64..514c5adf95 100644 --- a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs +++ b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Game.Overlays.Dialog; using osu.Game.Scoring; -using System; using System.Diagnostics; using osu.Framework.Graphics.Sprites; From 8d0dd1497b291898dc216754a7561e1c61e3b73c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 21 Dec 2019 12:26:58 +0300 Subject: [PATCH 4687/5608] Add legacy beatmap skin test scene with combo colours tests --- .../TestSceneLegacyBeatmapSkin.cs | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs new file mode 100644 index 0000000000..8ad66d833f --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -0,0 +1,173 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Textures; +using osu.Framework.IO.Stores; +using osu.Game.Audio; +using osu.Game.Beatmaps; +using osu.Game.Graphics.Containers; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens; +using osu.Game.Screens.Play; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestSceneLegacyBeatmapSkin : OsuTestScene + { + [Resolved] + private AudioManager audio { get; set; } + + [Test] + public void TestBeatmapComboColours() + { + ExposedPlayer player = null; + ISkin gameplaySkin = null; + IReadOnlyList colours = null; + + AddStep("load beatmap", () => player = loadBeatmap(false, true)); + AddUntilStep("wait for player", () => player.IsLoaded); + AddStep("attach skin requester", () => gameplaySkin = addSkinRequester(player)); + + AddStep("retrieve combo colours", () => colours = gameplaySkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value); + AddAssert("is beatmap colours", () => colours.SequenceEqual(TestBeatmapSkin.Colours)); + } + + [Test] + public void TestEmptyBeatmapComboColours() + { + ExposedPlayer player = null; + ISkin gameplaySkin = null; + IReadOnlyList colours = null; + + AddStep("load no-colour beatmap", () => player = loadBeatmap(false, false)); + AddUntilStep("wait for player", () => player.IsLoaded); + AddStep("attach skin requester", () => gameplaySkin = addSkinRequester(player)); + + AddStep("retrieve combo colours", () => colours = gameplaySkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value); + AddAssert("is default skin colours", () => colours.SequenceEqual(SkinConfiguration.DefaultComboColours)); + } + + [Test] + public void TestEmptyBeatmapCustomSkinColours() + { + ExposedPlayer player = null; + ISkin gameplaySkin = null; + IReadOnlyList colours = null; + + AddStep("load no-colour beatmap", () => player = loadBeatmap(true, false)); + AddUntilStep("wait for player", () => player.IsLoaded); + AddStep("attach skin requester", () => gameplaySkin = addSkinRequester(player)); + + AddStep("retrieve combo colours", () => colours = gameplaySkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value); + AddAssert("is custom skin colours", () => colours.SequenceEqual(TestSkin.Colours)); + } + + private ExposedPlayer loadBeatmap(bool skinHasCustomColours, bool beatmapHasCustomColours) + { + ExposedPlayer player; + + Beatmap.Value = new CustomSkinWorkingBeatmap(audio, beatmapHasCustomColours); + Child = new SkinProvidingContainer(new TestSkin(skinHasCustomColours)) + .WithChild(new OsuScreenStack(player = new ExposedPlayer()) { RelativeSizeAxes = Axes.Both }); + + return player; + } + + private ISkin addSkinRequester(ExposedPlayer player) + { + SkinRequester skin; + player.BeatmapSkinContainer.Add(skin = new SkinRequester()); + return skin; + } + + private class SkinRequester : Component, ISkin + { + [Resolved] + private ISkinSource skin { get; set; } + + public Drawable GetDrawableComponent(ISkinComponent component) => skin.GetDrawableComponent(component); + + public Texture GetTexture(string componentName) => skin.GetTexture(componentName); + + public SampleChannel GetSample(ISampleInfo sampleInfo) => skin.GetSample(sampleInfo); + + public IBindable GetConfig(TLookup lookup) => skin.GetConfig(lookup); + } + + private class ExposedPlayer : Player + { + public ExposedPlayer() + : base(false, false) + { + } + + public BeatmapSkinProvidingContainer BeatmapSkinContainer => GameplayClockContainer.OfType().First().OfType().First(); + } + + private class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap + { + private readonly bool hasColours; + + public CustomSkinWorkingBeatmap(AudioManager audio, bool hasColours) + : base(new Beatmap + { + BeatmapInfo = + { + BeatmapSet = new BeatmapSetInfo(), + Ruleset = new OsuRuleset().RulesetInfo, + }, + HitObjects = { new HitCircle { Position = new Vector2(256, 192) } } + }, null, null, audio) + { + this.hasColours = hasColours; + } + + protected override ISkin GetSkin() => new TestBeatmapSkin(BeatmapInfo, hasColours); + } + + private class TestBeatmapSkin : LegacyBeatmapSkin + { + public static Color4[] Colours { get; } = + { + new Color4(50, 100, 150, 255), + new Color4(40, 80, 120, 255), + }; + + public TestBeatmapSkin(BeatmapInfo beatmap, bool hasColours) + : base(beatmap, new ResourceStore(), null) + { + if (hasColours) + Configuration.AddComboColours(Colours); + } + } + + private class TestSkin : LegacySkin + { + public static Color4[] Colours { get; } = + { + new Color4(10, 100, 150, 255), + new Color4(20, 20, 20, 255), + }; + + public TestSkin(bool hasCustomColours) + : base(new SkinInfo(), null, null, string.Empty) + { + if (hasCustomColours) + Configuration.AddComboColours(Colours); + } + } + } +} From ff5e6c0dcfeb8d9eb62ad5527486faa7af24af75 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 21 Dec 2019 12:36:34 +0300 Subject: [PATCH 4688/5608] Make DefaultComboColours a property --- osu.Game/Skinning/SkinConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index 3bfc941fd7..e3a0ab23fa 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -20,7 +20,7 @@ namespace osu.Game.Skinning /// internal bool AllowDefaultComboColoursFallback = true; - public static List DefaultComboColours = new List + public static List DefaultComboColours { get; } = new List { new Color4(255, 192, 0, 255), new Color4(0, 202, 0, 255), From a6632cf1ef9708faeacbb35c61e812fc2a8bcc83 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 21 Dec 2019 12:53:05 +0300 Subject: [PATCH 4689/5608] Remove unnecessary skin requester and user-skin providing container --- .../TestSceneLegacyBeatmapSkin.cs | 74 ++++++++----------- 1 file changed, 29 insertions(+), 45 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index 8ad66d833f..c26afefc41 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -1,18 +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.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Audio.Sample; -using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; -using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; using osu.Game.Rulesets.Osu.Objects; @@ -34,87 +30,69 @@ namespace osu.Game.Rulesets.Osu.Tests public void TestBeatmapComboColours() { ExposedPlayer player = null; - ISkin gameplaySkin = null; IReadOnlyList colours = null; AddStep("load beatmap", () => player = loadBeatmap(false, true)); AddUntilStep("wait for player", () => player.IsLoaded); - AddStep("attach skin requester", () => gameplaySkin = addSkinRequester(player)); - AddStep("retrieve combo colours", () => colours = gameplaySkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value); - AddAssert("is beatmap colours", () => colours.SequenceEqual(TestBeatmapSkin.Colours)); + AddStep("retrieve combo colours", () => colours = player.BeatmapSkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value); + AddAssert("is beatmap skin colours", () => colours.SequenceEqual(TestBeatmapSkin.Colours)); } [Test] public void TestEmptyBeatmapComboColours() { ExposedPlayer player = null; - ISkin gameplaySkin = null; IReadOnlyList colours = null; AddStep("load no-colour beatmap", () => player = loadBeatmap(false, false)); AddUntilStep("wait for player", () => player.IsLoaded); - AddStep("attach skin requester", () => gameplaySkin = addSkinRequester(player)); - AddStep("retrieve combo colours", () => colours = gameplaySkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value); - AddAssert("is default skin colours", () => colours.SequenceEqual(SkinConfiguration.DefaultComboColours)); + AddStep("retrieve combo colours", () => colours = player.BeatmapSkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value); + AddAssert("is default user skin colours", () => colours.SequenceEqual(SkinConfiguration.DefaultComboColours)); } [Test] public void TestEmptyBeatmapCustomSkinColours() { ExposedPlayer player = null; - ISkin gameplaySkin = null; IReadOnlyList colours = null; AddStep("load no-colour beatmap", () => player = loadBeatmap(true, false)); AddUntilStep("wait for player", () => player.IsLoaded); - AddStep("attach skin requester", () => gameplaySkin = addSkinRequester(player)); - AddStep("retrieve combo colours", () => colours = gameplaySkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value); - AddAssert("is custom skin colours", () => colours.SequenceEqual(TestSkin.Colours)); + AddStep("retrieve combo colours", () => colours = player.BeatmapSkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value); + AddAssert("is custom user skin colours", () => colours.SequenceEqual(TestSkin.Colours)); } - private ExposedPlayer loadBeatmap(bool skinHasCustomColours, bool beatmapHasCustomColours) + private ExposedPlayer loadBeatmap(bool userHasCustomColours, bool beatmapHasColours) { ExposedPlayer player; - Beatmap.Value = new CustomSkinWorkingBeatmap(audio, beatmapHasCustomColours); - Child = new SkinProvidingContainer(new TestSkin(skinHasCustomColours)) - .WithChild(new OsuScreenStack(player = new ExposedPlayer()) { RelativeSizeAxes = Axes.Both }); + Beatmap.Value = new CustomSkinWorkingBeatmap(audio, beatmapHasColours); + Child = new OsuScreenStack(player = new ExposedPlayer(userHasCustomColours)) { RelativeSizeAxes = Axes.Both }; return player; } - private ISkin addSkinRequester(ExposedPlayer player) - { - SkinRequester skin; - player.BeatmapSkinContainer.Add(skin = new SkinRequester()); - return skin; - } - - private class SkinRequester : Component, ISkin - { - [Resolved] - private ISkinSource skin { get; set; } - - public Drawable GetDrawableComponent(ISkinComponent component) => skin.GetDrawableComponent(component); - - public Texture GetTexture(string componentName) => skin.GetTexture(componentName); - - public SampleChannel GetSample(ISampleInfo sampleInfo) => skin.GetSample(sampleInfo); - - public IBindable GetConfig(TLookup lookup) => skin.GetConfig(lookup); - } - private class ExposedPlayer : Player { - public ExposedPlayer() + private readonly bool userHasCustomColours; + + public ExposedPlayer(bool userHasCustomColours) : base(false, false) { + this.userHasCustomColours = userHasCustomColours; } - public BeatmapSkinProvidingContainer BeatmapSkinContainer => GameplayClockContainer.OfType().First().OfType().First(); + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.CacheAs(new TestSkin(userHasCustomColours)); + return dependencies; + } + + public BeatmapSkinProvidingContainer BeatmapSkin => GameplayClockContainer.OfType().First().OfType().First(); } private class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap @@ -154,7 +132,7 @@ namespace osu.Game.Rulesets.Osu.Tests } } - private class TestSkin : LegacySkin + private class TestSkin : LegacySkin, ISkinSource { public static Color4[] Colours { get; } = { @@ -168,6 +146,12 @@ namespace osu.Game.Rulesets.Osu.Tests if (hasCustomColours) Configuration.AddComboColours(Colours); } + + public event Action SourceChanged + { + add { } + remove { } + } } } } From c69e88eb97b90c73b3e2dcd2bebe18c8aa4b8540 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 21 Dec 2019 13:32:25 +0300 Subject: [PATCH 4690/5608] Add more types to dropdown --- osu.Game/Configuration/ScoreMeterType.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Configuration/ScoreMeterType.cs b/osu.Game/Configuration/ScoreMeterType.cs index b85ef9309d..156c4b1377 100644 --- a/osu.Game/Configuration/ScoreMeterType.cs +++ b/osu.Game/Configuration/ScoreMeterType.cs @@ -18,5 +18,14 @@ namespace osu.Game.Configuration [Description("Hit Error (both)")] HitErrorBoth, + + [Description("Colour (left)")] + ColourLeft, + + [Description("Colour (right)")] + ColourRight, + + [Description("Colour (both)")] + ColourBoth, } } From 5b115d8d8a94fff0f265d8a5aba113c0c1b1ad53 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 21 Dec 2019 13:41:50 +0300 Subject: [PATCH 4691/5608] Implement basic logic --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 31 +++++++++++++++++ .../HUD/HitErrorMeters/ColourHitErrorMeter.cs | 33 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 6196ce4026..4d28f00f39 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -77,6 +77,19 @@ namespace osu.Game.Screens.Play.HUD case ScoreMeterType.HitErrorRight: createBar(true); break; + + case ScoreMeterType.ColourBoth: + createColour(false); + createColour(true); + break; + + case ScoreMeterType.ColourLeft: + createColour(false); + break; + + case ScoreMeterType.ColourRight: + createColour(true); + break; } } @@ -90,6 +103,24 @@ namespace osu.Game.Screens.Play.HUD Alpha = 0, }; + completeDisplayLoading(display); + } + + private void createColour(bool rightAligned) + { + var display = new ColourHitErrorMeter(hitWindows) + { + Margin = new MarginPadding(margin), + Anchor = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, + Alpha = 0, + }; + + completeDisplayLoading(display); + } + + private void completeDisplayLoading(HitErrorMeter display) + { Add(display); display.FadeInFromZero(fade_duration, Easing.OutQuint); } diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs new file mode 100644 index 0000000000..95d4940b17 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -0,0 +1,33 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Scoring; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Play.HUD.HitErrorMeters +{ + public class ColourHitErrorMeter : HitErrorMeter + { + public ColourHitErrorMeter(HitWindows hitWindows) + : base(hitWindows) + { + + } + + public override void OnNewJudgement(JudgementResult judgement) + { + throw new System.NotImplementedException(); + } + } +} From 5e3c3f2a90190b9a785800627b44e4af136d6dba Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 21 Dec 2019 14:30:41 +0300 Subject: [PATCH 4692/5608] Make judgements work --- .../HUD/HitErrorMeters/ColourHitErrorMeter.cs | 70 +++++++++++++++++-- 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs index 95d4940b17..41401a0048 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -1,33 +1,89 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD.HitErrorMeters { public class ColourHitErrorMeter : HitErrorMeter { + private const int bar_height = 200; + + private readonly FillFlowContainer judgementsFlow; + public ColourHitErrorMeter(HitWindows hitWindows) : base(hitWindows) { - + AutoSizeAxes = Axes.Both; + InternalChild = judgementsFlow = new FillFlowContainer + { + AutoSizeAxes = Axes.X, + Height = bar_height, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 2), + Masking = true, + }; } public override void OnNewJudgement(JudgementResult judgement) { - throw new System.NotImplementedException(); + judgementsFlow.Add(new DrawableJudgement(HitWindows.ResultFor(judgement.TimeOffset))); + } + + private class DrawableJudgement : CircularContainer + { + private readonly Box background; + private readonly HitResult result; + + public DrawableJudgement(HitResult result) + { + this.result = result; + + Masking = true; + Size = new Vector2(8); + Child = background = new Box + { + RelativeSizeAxes = Axes.Both, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + switch (result) + { + case HitResult.Miss: + background.Colour = colours.Red; + break; + + case HitResult.Meh: + background.Colour = colours.Yellow; + break; + + case HitResult.Ok: + background.Colour = colours.Green; + break; + + case HitResult.Good: + background.Colour = colours.GreenLight; + break; + + case HitResult.Great: + background.Colour = colours.Blue; + break; + + default: + background.Colour = colours.BlueLight; + break; + } + } } } } From 5af126009488554a4322fa292c24e39f8ef0f898 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 21 Dec 2019 14:30:49 +0300 Subject: [PATCH 4693/5608] Improve testing --- ...rrorMeter.cs => TestSceneHitErrorMeter.cs} | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) rename osu.Game.Tests/Visual/Gameplay/{TestSceneBarHitErrorMeter.cs => TestSceneHitErrorMeter.cs} (75%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs similarity index 75% rename from osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs index e3688c276f..b208a2e0e7 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs @@ -19,18 +19,22 @@ using osu.Game.Screens.Play.HUD.HitErrorMeters; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneBarHitErrorMeter : OsuTestScene + public class TestSceneHitErrorMeter : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(HitErrorMeter), + typeof(BarHitErrorMeter), + typeof(ColourHitErrorMeter) }; - private HitErrorMeter meter; - private HitErrorMeter meter2; + private BarHitErrorMeter barMeter; + private BarHitErrorMeter barMeter2; + private ColourHitErrorMeter colourMeter; + private ColourHitErrorMeter colourMeter2; private HitWindows hitWindows; - public TestSceneBarHitErrorMeter() + public TestSceneHitErrorMeter() { recreateDisplay(new OsuHitWindows(), 5); @@ -91,17 +95,31 @@ namespace osu.Game.Tests.Visual.Gameplay } }); - Add(meter = new BarHitErrorMeter(hitWindows, true) + Add(barMeter = new BarHitErrorMeter(hitWindows, true) { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, }); - Add(meter2 = new BarHitErrorMeter(hitWindows, false) + Add(barMeter2 = new BarHitErrorMeter(hitWindows, false) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, }); + + Add(colourMeter = new ColourHitErrorMeter(hitWindows) + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Margin = new MarginPadding { Right = 50 } + }); + + Add(colourMeter2 = new ColourHitErrorMeter(hitWindows) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Left = 50 } + }); } private void newJudgement(double offset = 0) @@ -112,8 +130,10 @@ namespace osu.Game.Tests.Visual.Gameplay Type = HitResult.Perfect, }; - meter.OnNewJudgement(judgement); - meter2.OnNewJudgement(judgement); + barMeter.OnNewJudgement(judgement); + barMeter2.OnNewJudgement(judgement); + colourMeter.OnNewJudgement(judgement); + colourMeter2.OnNewJudgement(judgement); } } } From b61aa660c63f0e126f32643ef17e7bb458d2a1ae Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 21 Dec 2019 14:52:53 +0300 Subject: [PATCH 4694/5608] Move colours to HitErrorMeter class --- .../HUD/HitErrorMeters/BarHitErrorMeter.cs | 25 +--------- .../HUD/HitErrorMeters/ColourHitErrorMeter.cs | 46 ++----------------- .../Play/HUD/HitErrorMeters/HitErrorMeter.cs | 30 ++++++++++++ 3 files changed, 37 insertions(+), 64 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 03a0f23fb6..208bdd17ad 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -163,30 +163,9 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters centre.Width = 2.5f; colourBars.Add(centre); - Color4 getColour(HitResult result) - { - switch (result) - { - case HitResult.Meh: - return colours.Yellow; - - case HitResult.Ok: - return colours.Green; - - case HitResult.Good: - return colours.GreenLight; - - case HitResult.Great: - return colours.Blue; - - default: - return colours.BlueLight; - } - } - Drawable createColourBar(HitResult result, float height, bool first = false) { - var colour = getColour(result); + var colour = GetColourForHitResult(result); if (first) { @@ -201,7 +180,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters new Box { RelativeSizeAxes = Axes.Both, - Colour = getColour(result), + Colour = colour, Height = height * gradient_start }, new Box diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs index 41401a0048..6775b98f84 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -1,14 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD.HitErrorMeters { @@ -34,56 +33,21 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters public override void OnNewJudgement(JudgementResult judgement) { - judgementsFlow.Add(new DrawableJudgement(HitWindows.ResultFor(judgement.TimeOffset))); + judgementsFlow.Add(new DrawableJudgement(GetColourForHitResult(HitWindows.ResultFor(judgement.TimeOffset)))); } private class DrawableJudgement : CircularContainer { - private readonly Box background; - private readonly HitResult result; - - public DrawableJudgement(HitResult result) + public DrawableJudgement(Color4 colour) { - this.result = result; - Masking = true; Size = new Vector2(8); - Child = background = new Box + Child = new Box { RelativeSizeAxes = Axes.Both, + Colour = colour }; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - switch (result) - { - case HitResult.Miss: - background.Colour = colours.Red; - break; - - case HitResult.Meh: - background.Colour = colours.Yellow; - break; - - case HitResult.Ok: - background.Colour = colours.Green; - break; - - case HitResult.Good: - background.Colour = colours.GreenLight; - break; - - case HitResult.Great: - background.Colour = colours.Blue; - break; - - default: - background.Colour = colours.BlueLight; - break; - } - } } } } diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs index dee25048ed..b3edfdedec 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs @@ -1,9 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; +using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD.HitErrorMeters { @@ -11,11 +14,38 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { protected readonly HitWindows HitWindows; + [Resolved] + private OsuColour colours { get; set; } + protected HitErrorMeter(HitWindows hitWindows) { HitWindows = hitWindows; } public abstract void OnNewJudgement(JudgementResult judgement); + + protected Color4 GetColourForHitResult(HitResult result) + { + switch (result) + { + case HitResult.Miss: + return colours.Red; + + case HitResult.Meh: + return colours.Yellow; + + case HitResult.Ok: + return colours.Green; + + case HitResult.Good: + return colours.GreenLight; + + case HitResult.Great: + return colours.Blue; + + default: + return colours.BlueLight; + } + } } } From 14a77a8f16d849483a59c68cf726e7784966052a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 21 Dec 2019 16:08:28 +0300 Subject: [PATCH 4695/5608] Improve animations --- .../HUD/HitErrorMeters/ColourHitErrorMeter.cs | 83 +++++++++++++++---- 1 file changed, 69 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs index 6775b98f84..649f29810e 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -1,6 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -13,35 +17,86 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { public class ColourHitErrorMeter : HitErrorMeter { - private const int bar_height = 200; + private const int max_available_judgements = 20; - private readonly FillFlowContainer judgementsFlow; + private readonly JudgementFlow judgementsFlow; + private readonly BindableList<(Color4 colour, JudgementResult result)> judgements = new BindableList<(Color4 colour, JudgementResult result)>(); public ColourHitErrorMeter(HitWindows hitWindows) : base(hitWindows) { AutoSizeAxes = Axes.Both; - InternalChild = judgementsFlow = new FillFlowContainer - { - AutoSizeAxes = Axes.X, - Height = bar_height, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 2), - Masking = true, - }; + InternalChild = judgementsFlow = new JudgementFlow(); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + judgementsFlow.Judgements.BindTo(judgements); } public override void OnNewJudgement(JudgementResult judgement) { - judgementsFlow.Add(new DrawableJudgement(GetColourForHitResult(HitWindows.ResultFor(judgement.TimeOffset)))); + judgements.Add((GetColourForHitResult(HitWindows.ResultFor(judgement.TimeOffset)), judgement)); + + if (judgements.Count > max_available_judgements) + judgements.RemoveAt(0); } - private class DrawableJudgement : CircularContainer + private class JudgementFlow : Container { - public DrawableJudgement(Color4 colour) + private const int drawable_judgement_size = 8; + private const int spacing = 2; + private const int animation_duration = 200; + + public readonly BindableList<(Color4 colour, JudgementResult result)> Judgements = new BindableList<(Color4 colour, JudgementResult result)>(); + + public JudgementFlow() { + AutoSizeAxes = Axes.X; + Height = max_available_judgements * (drawable_judgement_size + spacing); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Judgements.ItemsAdded += push; + Judgements.ItemsRemoved += pop; + } + + private void push(IEnumerable<(Color4 colour, JudgementResult result)> judgements) + { + Children.ForEach(c => c.FinishTransforms()); + + var (colour, result) = judgements.Single(); + var drawableJudgement = new DrawableResult(colour, result, drawable_judgement_size) + { + Alpha = 0, + Y = -(drawable_judgement_size + spacing) + }; + + Add(drawableJudgement); + drawableJudgement.FadeInFromZero(animation_duration, Easing.OutQuint); + + Children.ForEach(c => c.MoveToOffset(new Vector2(0, drawable_judgement_size + spacing), animation_duration, Easing.OutQuint)); + } + + private void pop(IEnumerable<(Color4 colour, JudgementResult result)> judgements) + { + Children.FirstOrDefault(c => c.Result == judgements.Single().result).FadeOut(animation_duration, Easing.OutQuint).Expire(); + } + } + + private class DrawableResult : CircularContainer + { + public JudgementResult Result { get; private set; } + + public DrawableResult(Color4 colour, JudgementResult result, int size) + { + Result = result; + Masking = true; - Size = new Vector2(8); + Size = new Vector2(size); Child = new Box { RelativeSizeAxes = Axes.Both, From 13425568945c4bde5c130266b2ff19156f867fef Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 15 Dec 2019 08:34:57 -0800 Subject: [PATCH 4696/5608] Allow ctrl tabbing navigation to chat and song select leaderboards --- osu.Game/Overlays/ChatOverlay.cs | 1 + osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 33bcc4c139..08043a097b 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -171,6 +171,7 @@ namespace osu.Game.Overlays d.Origin = Anchor.BottomLeft; d.RelativeSizeAxes = Axes.Both; d.OnRequestLeave = channelManager.LeaveChannel; + d.Tabbable = true; }), } }, diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index 433e8ee398..a6933b478e 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -48,6 +48,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, + Tabbable = true, }, }, modsCheckbox = new OsuTabControlCheckbox From 119b48ccb0e77e8ed35c3e2537b2dc1fb51b4d2d Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 15 Dec 2019 08:35:38 -0800 Subject: [PATCH 4697/5608] Remove redundant tab item override --- osu.Game/Graphics/UserInterface/BreadcrumbControl.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index d1e55fee24..93ea6bbbe6 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -52,7 +52,6 @@ namespace osu.Game.Graphics.UserInterface public override bool HandleNonPositionalInput => State == Visibility.Visible; public override bool HandlePositionalInput => State == Visibility.Visible; - public override bool IsRemovable => true; private Visibility state; From 725008286f1cd5861fef48d5acbc5ca11e505496 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Dec 2019 06:09:16 +0900 Subject: [PATCH 4698/5608] Move test and remove pointless duplicate tests --- .../SongSelect/TestSceneBeatmapDetailArea.cs | 213 ------------------ .../SongSelect/TestSceneBeatmapDetails.cs | 15 ++ 2 files changed, 15 insertions(+), 213 deletions(-) delete mode 100644 osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs deleted file mode 100644 index de4e77fe70..0000000000 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Game.Beatmaps; -using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; -using osu.Game.Screens.Play.HUD; -using osu.Game.Screens.Select; -using osu.Game.Tests.Beatmaps; -using osuTK; - -namespace osu.Game.Tests.Visual.SongSelect -{ - [TestFixture] - [System.ComponentModel.Description("PlaySongSelect leaderboard/details area")] - public class TestSceneBeatmapDetailArea : OsuTestScene - { - public override IReadOnlyList RequiredTypes => new[] { typeof(BeatmapDetails) }; - - private ModDisplay modDisplay; - - private BeatmapDetailArea detailsArea; - - [Resolved] - private RulesetStore rulesets { get; set; } - - [BackgroundDependencyLoader] - private void load(OsuGameBase game, RulesetStore rulesets) - { - } - - [SetUp] - public void SetUp() => Schedule(() => - { - Children = new Drawable[] - { - detailsArea = new BeatmapDetailArea - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(550f, 450f), - }, - modDisplay = new ModDisplay - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Position = new Vector2(0, 25), - } - }; - - modDisplay.Current.BindTo(SelectedMods); - }); - - [Test] - public void TestBasicScenarios() - { - showAllMetrics(); - AddStep("all except source", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap - { - BeatmapInfo = - { - BeatmapSet = new BeatmapSetInfo - { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } - }, - Version = "All Metrics", - Metadata = new BeatmapMetadata - { - Tags = "this beatmap has all the metrics", - }, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 7, - DrainRate = 1, - OverallDifficulty = 5.7f, - ApproachRate = 3.5f, - }, - StarDifficulty = 5.3f, - Metrics = new BeatmapMetrics - { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, - } - })); - - AddStep("ratings", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap - { - BeatmapInfo = - { - BeatmapSet = new BeatmapSetInfo - { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } - }, - Version = "Only Ratings", - Metadata = new BeatmapMetadata - { - Source = "osu!lazer", - Tags = "this beatmap has ratings metrics but not retries or fails", - }, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 6, - DrainRate = 9, - OverallDifficulty = 6, - ApproachRate = 6, - }, - StarDifficulty = 4.8f - } - })); - - AddStep("fails+retries", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap - { - BeatmapInfo = - { - Version = "Only Retries and Fails", - Metadata = new BeatmapMetadata - { - Source = "osu!lazer", - Tags = "this beatmap has retries and fails but no ratings", - }, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 3.7f, - DrainRate = 6, - OverallDifficulty = 6, - ApproachRate = 7, - }, - StarDifficulty = 2.91f, - Metrics = new BeatmapMetrics - { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, - } - })); - - AddStep("null metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap - { - BeatmapInfo = - { - Version = "No Metrics", - Metadata = new BeatmapMetadata - { - Source = "osu!lazer", - Tags = "this beatmap has no metrics", - }, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 5, - DrainRate = 5, - OverallDifficulty = 5.5f, - ApproachRate = 6.5f, - }, - StarDifficulty = 1.97f, - } - })); - - AddStep("null beatmap", () => detailsArea.Beatmap = null); - } - - [Test] - public void TestModAdjustments() - { - showAllMetrics(); - - Ruleset ruleset = rulesets.AvailableRulesets.First().CreateInstance(); - - AddStep("with EZ mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModEasy) }); - AddStep("with HR mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModHardRock) }); - } - - private void showAllMetrics() - { - AddStep("all metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap - { - BeatmapInfo = - { - BeatmapSet = new BeatmapSetInfo - { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } - }, - Version = "All Metrics", - Metadata = new BeatmapMetadata - { - Source = "osu!lazer", - Tags = "this beatmap has all the metrics", - }, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 7, - DrainRate = 1, - OverallDifficulty = 5.7f, - ApproachRate = 3.5f, - }, - StarDifficulty = 5.3f, - Metrics = new BeatmapMetrics - { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, - } - })); - } - } -} diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index acf037198f..2521d248e7 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -3,8 +3,11 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.SongSelect @@ -174,5 +177,17 @@ namespace osu.Game.Tests.Visual.SongSelect OnlineBeatmapID = 162, }); } + + [Resolved] + private RulesetStore rulesets { get; set; } + + [Test] + public void TestModAdjustments() + { + Ruleset ruleset = rulesets.AvailableRulesets.First().CreateInstance(); + + AddStep("with EZ mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModEasy) }); + AddStep("with HR mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModHardRock) }); + } } } From 69227d61799a79b6a71249e5769e6a657acea009 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Dec 2019 06:37:18 +0900 Subject: [PATCH 4699/5608] Add asserts --- .../Visual/SongSelect/TestSceneBeatmapDetails.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index 2521d248e7..6aa5a76490 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -5,7 +5,10 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Select; @@ -181,13 +184,23 @@ namespace osu.Game.Tests.Visual.SongSelect [Resolved] private RulesetStore rulesets { get; set; } + [Resolved] + private OsuColour colours { get; set; } + [Test] public void TestModAdjustments() { + TestAllMetrics(); + Ruleset ruleset = rulesets.AvailableRulesets.First().CreateInstance(); AddStep("with EZ mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModEasy) }); + + AddAssert("first bar coloured blue", () => details.ChildrenOfType().Skip(1).First().AccentColour == colours.BlueDark); + AddStep("with HR mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModHardRock) }); + + AddAssert("first bar coloured red", () => details.ChildrenOfType().Skip(1).First().AccentColour == colours.Red); } } } From 46501cf0ac2984537d8a96b885fc87804d4ece15 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 22 Dec 2019 03:06:57 +0300 Subject: [PATCH 4700/5608] Use FillFlowContainer --- .../HUD/HitErrorMeters/ColourHitErrorMeter.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs index 649f29810e..d730a8d321 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -43,7 +42,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters judgements.RemoveAt(0); } - private class JudgementFlow : Container + private class JudgementFlow : FillFlowContainer { private const int drawable_judgement_size = 8; private const int spacing = 2; @@ -51,10 +50,16 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters public readonly BindableList<(Color4 colour, JudgementResult result)> Judgements = new BindableList<(Color4 colour, JudgementResult result)>(); + private int runningDepth; + public JudgementFlow() { AutoSizeAxes = Axes.X; Height = max_available_judgements * (drawable_judgement_size + spacing); + Spacing = new Vector2(0, spacing); + Direction = FillDirection.Vertical; + LayoutDuration = animation_duration; + LayoutEasing = Easing.OutQuint; } protected override void LoadComplete() @@ -66,24 +71,20 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters private void push(IEnumerable<(Color4 colour, JudgementResult result)> judgements) { - Children.ForEach(c => c.FinishTransforms()); - var (colour, result) = judgements.Single(); var drawableJudgement = new DrawableResult(colour, result, drawable_judgement_size) { Alpha = 0, - Y = -(drawable_judgement_size + spacing) }; - Add(drawableJudgement); + Insert(runningDepth--, drawableJudgement); drawableJudgement.FadeInFromZero(animation_duration, Easing.OutQuint); - - Children.ForEach(c => c.MoveToOffset(new Vector2(0, drawable_judgement_size + spacing), animation_duration, Easing.OutQuint)); } private void pop(IEnumerable<(Color4 colour, JudgementResult result)> judgements) { - Children.FirstOrDefault(c => c.Result == judgements.Single().result).FadeOut(animation_duration, Easing.OutQuint).Expire(); + var (colour, result) = judgements.Single(); + Children.FirstOrDefault(c => c.Result == result).FadeOut(animation_duration, Easing.OutQuint).Expire(); } } From eb75c6c70f342ff84d50b038af92e6873f1d080c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 22 Dec 2019 03:17:56 +0300 Subject: [PATCH 4701/5608] Update FadeIn animation for new judgement --- .../HUD/HitErrorMeters/ColourHitErrorMeter.cs | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs index d730a8d321..b76f2c7817 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -17,6 +17,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters public class ColourHitErrorMeter : HitErrorMeter { private const int max_available_judgements = 20; + private const int animation_duration = 200; private readonly JudgementFlow judgementsFlow; private readonly BindableList<(Color4 colour, JudgementResult result)> judgements = new BindableList<(Color4 colour, JudgementResult result)>(); @@ -46,7 +47,6 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { private const int drawable_judgement_size = 8; private const int spacing = 2; - private const int animation_duration = 200; public readonly BindableList<(Color4 colour, JudgementResult result)> Judgements = new BindableList<(Color4 colour, JudgementResult result)>(); @@ -72,13 +72,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters private void push(IEnumerable<(Color4 colour, JudgementResult result)> judgements) { var (colour, result) = judgements.Single(); - var drawableJudgement = new DrawableResult(colour, result, drawable_judgement_size) - { - Alpha = 0, - }; - - Insert(runningDepth--, drawableJudgement); - drawableJudgement.FadeInFromZero(animation_duration, Easing.OutQuint); + Insert(runningDepth--, new DrawableResult(colour, result, drawable_judgement_size)); } private void pop(IEnumerable<(Color4 colour, JudgementResult result)> judgements) @@ -88,22 +82,37 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters } } - private class DrawableResult : CircularContainer + private class DrawableResult : Container { public JudgementResult Result { get; private set; } + private readonly CircularContainer content; + public DrawableResult(Color4 colour, JudgementResult result, int size) { Result = result; - Masking = true; Size = new Vector2(size); - Child = new Box + Child = content = new CircularContainer { RelativeSizeAxes = Axes.Both, - Colour = colour + Masking = true, + Alpha = 0, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colour + }, }; } + + protected override void LoadComplete() + { + base.LoadComplete(); + content.FadeInFromZero(animation_duration, Easing.OutQuint); + content.MoveToY(-DrawSize.Y); + content.MoveToY(0, animation_duration, Easing.OutQuint); + } } } } From aded12af9e157ea0535dfbf8da48ed7fe3a8c2f0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 22 Dec 2019 03:30:17 +0300 Subject: [PATCH 4702/5608] Refactoor to avoid bindable usage --- .../HUD/HitErrorMeters/ColourHitErrorMeter.cs | 54 ++++++------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs index b76f2c7817..196eb23da6 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -1,9 +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.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -16,11 +14,9 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { public class ColourHitErrorMeter : HitErrorMeter { - private const int max_available_judgements = 20; private const int animation_duration = 200; private readonly JudgementFlow judgementsFlow; - private readonly BindableList<(Color4 colour, JudgementResult result)> judgements = new BindableList<(Color4 colour, JudgementResult result)>(); public ColourHitErrorMeter(HitWindows hitWindows) : base(hitWindows) @@ -29,69 +25,43 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters InternalChild = judgementsFlow = new JudgementFlow(); } - protected override void LoadComplete() - { - base.LoadComplete(); - judgementsFlow.Judgements.BindTo(judgements); - } - - public override void OnNewJudgement(JudgementResult judgement) - { - judgements.Add((GetColourForHitResult(HitWindows.ResultFor(judgement.TimeOffset)), judgement)); - - if (judgements.Count > max_available_judgements) - judgements.RemoveAt(0); - } + public override void OnNewJudgement(JudgementResult judgement) => judgementsFlow.Push(GetColourForHitResult(HitWindows.ResultFor(judgement.TimeOffset))); private class JudgementFlow : FillFlowContainer { + private const int max_available_judgements = 20; private const int drawable_judgement_size = 8; private const int spacing = 2; - public readonly BindableList<(Color4 colour, JudgementResult result)> Judgements = new BindableList<(Color4 colour, JudgementResult result)>(); - private int runningDepth; public JudgementFlow() { AutoSizeAxes = Axes.X; - Height = max_available_judgements * (drawable_judgement_size + spacing); + Height = max_available_judgements * (drawable_judgement_size + spacing) - spacing; Spacing = new Vector2(0, spacing); Direction = FillDirection.Vertical; LayoutDuration = animation_duration; LayoutEasing = Easing.OutQuint; } - protected override void LoadComplete() + public void Push(Color4 colour) { - base.LoadComplete(); - Judgements.ItemsAdded += push; - Judgements.ItemsRemoved += pop; - } + Insert(runningDepth--, new DrawableResult(colour, drawable_judgement_size)); - private void push(IEnumerable<(Color4 colour, JudgementResult result)> judgements) - { - var (colour, result) = judgements.Single(); - Insert(runningDepth--, new DrawableResult(colour, result, drawable_judgement_size)); - } - - private void pop(IEnumerable<(Color4 colour, JudgementResult result)> judgements) - { - var (colour, result) = judgements.Single(); - Children.FirstOrDefault(c => c.Result == result).FadeOut(animation_duration, Easing.OutQuint).Expire(); + if (Children.Count > max_available_judgements) + Children.FirstOrDefault(c => !c.IsRemoved).Remove(); } } private class DrawableResult : Container { - public JudgementResult Result { get; private set; } + public bool IsRemoved { get; private set; } private readonly CircularContainer content; - public DrawableResult(Color4 colour, JudgementResult result, int size) + public DrawableResult(Color4 colour, int size) { - Result = result; - Size = new Vector2(size); Child = content = new CircularContainer { @@ -113,6 +83,12 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters content.MoveToY(-DrawSize.Y); content.MoveToY(0, animation_duration, Easing.OutQuint); } + + public void Remove() + { + IsRemoved = true; + this.FadeOut(animation_duration, Easing.OutQuint).Expire(); + } } } } From 7a0d76ae77e5b830f158dcde6bfdb80797165e70 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 22 Dec 2019 03:41:19 +0300 Subject: [PATCH 4703/5608] Fix nullref --- osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs index 196eb23da6..d18f6f3743 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters Insert(runningDepth--, new DrawableResult(colour, drawable_judgement_size)); if (Children.Count > max_available_judgements) - Children.FirstOrDefault(c => !c.IsRemoved).Remove(); + Children.FirstOrDefault(c => !c.IsRemoved)?.Remove(); } } From fe73b9f8d3919a0a983965f5db17569b4f2bd83d Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 22 Dec 2019 16:45:32 +0800 Subject: [PATCH 4704/5608] make HP and OD generic and instantiate CS and AR to modes that need it --- .../Mods/CatchModDifficultyAdjust.cs | 37 ++++++------ .../Mods/ManiaModDifficultyAdjust.cs | 19 ------ .../Mods/OsuModDifficultyAdjust.cs | 37 ++++++------ .../Mods/TaikoModDifficultyAdjust.cs | 19 ------ osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 59 +++++++++++-------- 5 files changed, 68 insertions(+), 103 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs index 127b6c1c0b..2e1e655844 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; +using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets.Mods; @@ -9,18 +10,8 @@ namespace osu.Game.Rulesets.Catch.Mods { public class CatchModDifficultyAdjust : ModDifficultyAdjust { - [SettingSource("Drain Rate", "Override a beatmap's set HP.")] - public override BindableNumber DrainRate { get; } = new BindableFloat() - { - Precision = 0.1f, - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - }; - [SettingSource("Fruit Size", "Override a beatmap's set CS.")] - public override BindableNumber CircleSize { get; } = new BindableFloat() + public BindableNumber CircleSize { get; } = new BindableFloat() { Precision = 0.1f, MinValue = 1, @@ -30,7 +21,7 @@ namespace osu.Game.Rulesets.Catch.Mods }; [SettingSource("Approach Rate", "Override a beatmap's set AR.")] - public override BindableNumber ApproachRate { get; } = new BindableFloat() + public BindableNumber ApproachRate { get; } = new BindableFloat() { Precision = 0.1f, MinValue = 1, @@ -39,14 +30,20 @@ namespace osu.Game.Rulesets.Catch.Mods Value = 5, }; - [SettingSource("Overall Difficulty", "Override a beatmap's set OD.")] - public override BindableNumber OverallDifficulty { get; } = new BindableFloat() + protected override void UpdateSettings(BeatmapDifficulty difficulty) { - Precision = 0.1f, - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - }; + base.UpdateSettings(difficulty); + + CircleSize.Value = CircleSize.Default = difficulty.CircleSize; + ApproachRate.Value = ApproachRate.Default = difficulty.ApproachRate; + } + + protected override void ApplySettings(BeatmapDifficulty difficulty) + { + base.ApplySettings(difficulty); + + difficulty.CircleSize = CircleSize.Value; + difficulty.ApproachRate = ApproachRate.Value; + } } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs index fd1315523c..5920e0c3b8 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs @@ -9,24 +9,5 @@ namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModDifficultyAdjust : ModDifficultyAdjust { - [SettingSource("Drain Rate", "Override a beatmap's set HP.")] - public override BindableNumber DrainRate { get; } = new BindableFloat() - { - Precision = 0.1f, - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - }; - - [SettingSource("Overall Difficulty", "Override a beatmap's set OD.")] - public override BindableNumber OverallDifficulty { get; } = new BindableFloat() - { - Precision = 0.1f, - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - }; } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs index 4847ddc3c4..3e9c51db85 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; +using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets.Mods; @@ -9,18 +10,8 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModDifficultyAdjust : ModDifficultyAdjust { - [SettingSource("Drain Rate", "Override a beatmap's set HP.")] - public override BindableNumber DrainRate { get; } = new BindableFloat() - { - Precision = 0.1f, - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - }; - [SettingSource("Circle Size", "Override a beatmap's set CS.")] - public override BindableNumber CircleSize { get; } = new BindableFloat() + public BindableNumber CircleSize { get; } = new BindableFloat() { Precision = 0.1f, MinValue = 1, @@ -30,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Mods }; [SettingSource("Approach Rate", "Override a beatmap's set AR.")] - public override BindableNumber ApproachRate { get; } = new BindableFloat() + public BindableNumber ApproachRate { get; } = new BindableFloat() { Precision = 0.1f, MinValue = 1, @@ -39,14 +30,20 @@ namespace osu.Game.Rulesets.Osu.Mods Value = 5, }; - [SettingSource("Overall Difficulty", "Override a beatmap's set OD.")] - public override BindableNumber OverallDifficulty { get; } = new BindableFloat() + protected override void UpdateSettings(BeatmapDifficulty difficulty) { - Precision = 0.1f, - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - }; + base.UpdateSettings(difficulty); + + CircleSize.Value = CircleSize.Default = difficulty.CircleSize; + ApproachRate.Value = ApproachRate.Default = difficulty.ApproachRate; + } + + protected override void ApplySettings(BeatmapDifficulty difficulty) + { + base.ApplySettings(difficulty); + + difficulty.CircleSize = CircleSize.Value; + difficulty.ApproachRate = ApproachRate.Value; + } } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs index b7007eedcd..3c4812f922 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs @@ -9,24 +9,5 @@ namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModDifficultyAdjust : ModDifficultyAdjust { - [SettingSource("Drain Rate", "Override a beatmap's set HP.")] - public override BindableNumber DrainRate { get; } = new BindableFloat() - { - Precision = 0.1f, - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - }; - - [SettingSource("Overall Difficulty", "Override a beatmap's set OD.")] - public override BindableNumber OverallDifficulty { get; } = new BindableFloat() - { - Precision = 0.1f, - MinValue = 1, - MaxValue = 10, - Default = 5, - Value = 5, - }; } } diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs index 546533709e..1405ccec8d 100644 --- a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -5,6 +5,7 @@ using osu.Game.Beatmaps; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using System; +using osu.Game.Configuration; namespace osu.Game.Rulesets.Mods { @@ -24,41 +25,49 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => new[] { typeof(ModEasy), typeof(ModHardRock) }; - public virtual BindableNumber DrainRate { get; } + [SettingSource("Drain Rate", "Override a beatmap's set HP.")] + public BindableNumber DrainRate { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; - public virtual BindableNumber CircleSize { get; } - - public virtual BindableNumber ApproachRate { get; } - - public virtual BindableNumber OverallDifficulty { get; } + [SettingSource("Overall Difficulty", "Override a beatmap's set OD.")] + public BindableNumber OverallDifficulty { get; } = new BindableFloat() + { + Precision = 0.1f, + MinValue = 1, + MaxValue = 10, + Default = 5, + Value = 5, + }; private BeatmapDifficulty difficulty; - public virtual void ApplyToDifficulty(BeatmapDifficulty difficulty) + public void ApplyToDifficulty(BeatmapDifficulty difficulty) { if (this.difficulty == null || this.difficulty.ID != difficulty.ID) { this.difficulty = difficulty; - - if (DrainRate != null) - DrainRate.Value = DrainRate.Default = difficulty.DrainRate; - - if (CircleSize != null) - CircleSize.Value = CircleSize.Default = difficulty.CircleSize; - - if (ApproachRate != null) - ApproachRate.Value = ApproachRate.Default = difficulty.ApproachRate; - - if (OverallDifficulty != null) - OverallDifficulty.Value = OverallDifficulty.Default = difficulty.OverallDifficulty; + UpdateSettings(difficulty); } else - { - difficulty.DrainRate = DrainRate?.Value ?? difficulty.DrainRate; - difficulty.CircleSize = CircleSize?.Value ?? difficulty.CircleSize; - difficulty.ApproachRate = ApproachRate?.Value ?? difficulty.ApproachRate; - difficulty.OverallDifficulty = OverallDifficulty?.Value ?? difficulty.OverallDifficulty; - } + ApplySettings(difficulty); + } + + protected virtual void UpdateSettings(BeatmapDifficulty difficulty) + { + DrainRate.Value = DrainRate.Default = difficulty.DrainRate; + OverallDifficulty.Value = OverallDifficulty.Default = difficulty.OverallDifficulty; + } + + protected virtual void ApplySettings(BeatmapDifficulty difficulty) + { + difficulty.DrainRate = DrainRate.Value; + difficulty.OverallDifficulty = OverallDifficulty.Value; } } } From 00ef2bd8d37c1b226ed39429ca0044723ebb3199 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 22 Dec 2019 16:57:07 +0800 Subject: [PATCH 4705/5608] remove unused usings --- osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs | 2 -- osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs | 2 -- 2 files changed, 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs index 5920e0c3b8..0817f8f9fc 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Bindables; -using osu.Game.Configuration; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs index 3c4812f922..56a73ad7df 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Bindables; -using osu.Game.Configuration; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Taiko.Mods From 5d29ff29cbe4464288b299dc2841664d7c970430 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sun, 22 Dec 2019 20:52:00 +0800 Subject: [PATCH 4706/5608] Animate "Good bye" instead on exit --- osu.Game/Screens/Menu/MainMenu.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 231115d1e1..8437748d9d 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; @@ -132,6 +133,8 @@ namespace osu.Game.Screens.Menu private void confirmAndExit() { + if (exitConfirmed) return; + exitConfirmed = true; this.Exit(); } @@ -250,6 +253,12 @@ namespace osu.Game.Screens.Menu return true; } + if (dialogOverlay.CurrentDialog is ConfirmExitDialog) + { + exitConfirmed = true; + dialogOverlay.CurrentDialog.Buttons.First().Click(); + } + buttons.State = ButtonSystemState.Exit; this.FadeOut(3000); return base.OnExiting(next); From 1f41acc5b92648a2d3c51afcf775346cf9090404 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sun, 22 Dec 2019 21:20:55 +0800 Subject: [PATCH 4707/5608] Integrate auto click into exit confirmed check --- osu.Game/Screens/Menu/MainMenu.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 8437748d9d..ee4d98bd89 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -247,14 +247,14 @@ namespace osu.Game.Screens.Menu public override bool OnExiting(IScreen next) { - if (!exitConfirmed && dialogOverlay != null && !(dialogOverlay.CurrentDialog is ConfirmExitDialog)) + if (!exitConfirmed && dialogOverlay != null) { - dialogOverlay.Push(new ConfirmExitDialog(confirmAndExit, () => exitConfirmOverlay.Abort())); - return true; - } + if (!(dialogOverlay.CurrentDialog is ConfirmExitDialog)) + { + dialogOverlay.Push(new ConfirmExitDialog(confirmAndExit, () => exitConfirmOverlay.Abort())); + return true; + } - if (dialogOverlay.CurrentDialog is ConfirmExitDialog) - { exitConfirmed = true; dialogOverlay.CurrentDialog.Buttons.First().Click(); } From 796223d3e0e3f62c640a7c4a64046c781b257d87 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sun, 22 Dec 2019 21:39:25 +0800 Subject: [PATCH 4708/5608] Invert if --- osu.Game/Screens/Menu/MainMenu.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index ee4d98bd89..b28d572b5c 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -249,14 +249,16 @@ namespace osu.Game.Screens.Menu { if (!exitConfirmed && dialogOverlay != null) { - if (!(dialogOverlay.CurrentDialog is ConfirmExitDialog)) + if (dialogOverlay.CurrentDialog is ConfirmExitDialog exitDialog) + { + exitConfirmed = true; + exitDialog.Buttons.First().Click(); + } + else { dialogOverlay.Push(new ConfirmExitDialog(confirmAndExit, () => exitConfirmOverlay.Abort())); return true; } - - exitConfirmed = true; - dialogOverlay.CurrentDialog.Buttons.First().Click(); } buttons.State = ButtonSystemState.Exit; From e2b4e3580cc55caaa7a0a0941150ab5464d063f8 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 21 Dec 2019 15:48:15 +0100 Subject: [PATCH 4709/5608] Truncate strings passed to the Discord RPC client to a maximum of 128 bytes --- osu.Desktop/DiscordRichPresence.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index b53ca6161b..45552f1906 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -1,7 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; +using System.Text; using DiscordRPC; +using DiscordRPC.Helper; using DiscordRPC.Message; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -78,8 +81,8 @@ namespace osu.Desktop if (status.Value is UserStatusOnline && activity.Value != null) { - presence.State = activity.Value.Status; - presence.Details = getDetails(activity.Value); + presence.State = truncate(activity.Value.Status); + presence.Details = truncate(getDetails(activity.Value)); } else { @@ -97,6 +100,8 @@ namespace osu.Desktop client.SetPresence(presence); } + private string truncate(string str) => str.WithinLength(128) ? str : new string (str.TakeWhile((c, i) => Encoding.UTF8.GetByteCount(str.Substring(0, i + 1)) <= 125).ToArray()) + '…'; //the ellipsis char is 3 bytes long in UTF8 + private string getDetails(UserActivity activity) { switch (activity) From b038c192d12df09206f072214c2e20959dd4fe09 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 22 Dec 2019 19:47:47 -0800 Subject: [PATCH 4710/5608] Rename property to IsSwitchable --- osu.Game/Overlays/ChatOverlay.cs | 2 +- osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 08043a097b..e80c51d82a 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -171,7 +171,7 @@ namespace osu.Game.Overlays d.Origin = Anchor.BottomLeft; d.RelativeSizeAxes = Axes.Both; d.OnRequestLeave = channelManager.LeaveChannel; - d.Tabbable = true; + d.IsSwitchable = true; }), } }, diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index a6933b478e..19ecdb6dbf 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -48,7 +48,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, - Tabbable = true, + IsSwitchable = true, }, }, modsCheckbox = new OsuTabControlCheckbox From 6e7426a0981b8111ffc2c8b96ead455d1b5fa2d9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Dec 2019 17:44:18 +0900 Subject: [PATCH 4711/5608] Simplify/improve beatmap conversion precheck --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs | 4 ++-- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs | 4 ++-- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs | 4 ++-- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 4 ++-- .../Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs | 2 +- osu.Game/Beatmaps/BeatmapConverter.cs | 7 +------ osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/IBeatmapConverter.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- 9 files changed, 13 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index b5497ea89f..088f187621 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -4,7 +4,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using System.Collections.Generic; -using System; +using System.Linq; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects; @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { } - protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; + public override bool CanConvert() => Beatmap.HitObjects.All(h => h is IHasXPosition); protected override IEnumerable ConvertHitObject(HitObject obj, IBeatmap beatmap) { diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 6e4491de94..c2f92090a1 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -24,8 +24,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// private const int max_notes_for_density = 7; - protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; - public int TargetColumns; public bool Dual; public readonly bool IsForCurrentRuleset; @@ -69,6 +67,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps } } + public override bool CanConvert() => Beatmap.HitObjects.All(h => h is IHasXPosition || h is ManiaHitObject); + protected override Beatmap ConvertBeatmap(IBeatmap original) { BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty; diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 2296030f81..a05fb5e9de 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using System.Collections.Generic; using osu.Game.Rulesets.Objects.Types; -using System; +using System.Linq; using osu.Game.Rulesets.Osu.UI; using osu.Framework.Extensions.IEnumerableExtensions; @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps { } - protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasPosition) }; + public override bool CanConvert() => Beatmap.HitObjects.All(h => h is IHasPosition); protected override IEnumerable ConvertHitObject(HitObject original, IBeatmap beatmap) { diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 10cc861b7e..f506f31831 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -39,14 +39,14 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps private readonly bool isForCurrentRuleset; - protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(HitObject) }; - public TaikoBeatmapConverter(IBeatmap beatmap) : base(beatmap) { isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(new TaikoRuleset().RulesetInfo); } + public override bool CanConvert() => true; + protected override Beatmap ConvertBeatmap(IBeatmap original) { // Rewrite the beatmap info to add the slider velocity multiplier diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index ae20bbc86d..f0363d2e6d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -273,7 +273,7 @@ namespace osu.Game.Tests.Visual.Gameplay { } - protected override IEnumerable ValidConversionTypes => new[] { typeof(HitObject) }; + public override bool CanConvert() => true; protected override IEnumerable ConvertHitObject(HitObject original, IBeatmap beatmap) { diff --git a/osu.Game/Beatmaps/BeatmapConverter.cs b/osu.Game/Beatmaps/BeatmapConverter.cs index 7922843626..0964f3f1ed 100644 --- a/osu.Game/Beatmaps/BeatmapConverter.cs +++ b/osu.Game/Beatmaps/BeatmapConverter.cs @@ -33,7 +33,7 @@ namespace osu.Game.Beatmaps /// /// Whether can be converted by this . /// - public bool CanConvert => !Beatmap.HitObjects.Any() || ValidConversionTypes.All(t => Beatmap.HitObjects.Any(t.IsInstanceOfType)); + public abstract bool CanConvert(); /// /// Converts . @@ -92,11 +92,6 @@ namespace osu.Game.Beatmaps return result; } - /// - /// The types of HitObjects that can be converted to be used for this Beatmap. - /// - protected abstract IEnumerable ValidConversionTypes { get; } - /// /// Creates the that will be returned by this . /// diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 46efe38d37..bfcc38e4a9 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -76,7 +76,7 @@ namespace osu.Game.Beatmaps public IBeatmap Beatmap { get; set; } - public bool CanConvert => true; + public bool CanConvert() => true; public IBeatmap Convert() { diff --git a/osu.Game/Beatmaps/IBeatmapConverter.cs b/osu.Game/Beatmaps/IBeatmapConverter.cs index f2213b85f1..173d5494ba 100644 --- a/osu.Game/Beatmaps/IBeatmapConverter.cs +++ b/osu.Game/Beatmaps/IBeatmapConverter.cs @@ -25,7 +25,7 @@ namespace osu.Game.Beatmaps /// /// Whether can be converted by this . /// - bool CanConvert { get; } + bool CanConvert(); /// /// Converts . diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 1255665cf0..baa15699be 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -108,7 +108,7 @@ namespace osu.Game.Beatmaps IBeatmapConverter converter = CreateBeatmapConverter(Beatmap, rulesetInstance); // Check if the beatmap can be converted - if (!converter.CanConvert) + if (!converter.CanConvert()) throw new BeatmapInvalidForRulesetException($"{nameof(Beatmaps.Beatmap)} can not be converted for the ruleset (ruleset: {ruleset.InstantiationInfo}, converter: {converter})."); // Apply conversion mods From 3e03916c3999fe9764c6fe299ac6ae83cb070179 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Dec 2019 17:45:59 +0900 Subject: [PATCH 4712/5608] Add length check back to workingbeatmap --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index baa15699be..6aba5257f5 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -108,7 +108,7 @@ namespace osu.Game.Beatmaps IBeatmapConverter converter = CreateBeatmapConverter(Beatmap, rulesetInstance); // Check if the beatmap can be converted - if (!converter.CanConvert()) + if (Beatmap.HitObjects.Count > 0 && !converter.CanConvert()) throw new BeatmapInvalidForRulesetException($"{nameof(Beatmaps.Beatmap)} can not be converted for the ruleset (ruleset: {ruleset.InstantiationInfo}, converter: {converter})."); // Apply conversion mods From 78b30a076f8a0a8e8cb6caba99f34c8f5e0d3579 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Dec 2019 15:40:14 +0900 Subject: [PATCH 4713/5608] Add mania player test scene --- osu.Game.Rulesets.Mania.Tests/TestScenePlayer.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 osu.Game.Rulesets.Mania.Tests/TestScenePlayer.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestScenePlayer.cs b/osu.Game.Rulesets.Mania.Tests/TestScenePlayer.cs new file mode 100644 index 0000000000..cd25d162d0 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestScenePlayer.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 osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Mania.Tests +{ + public class TestScenePlayer : PlayerTestScene + { + public TestScenePlayer() + : base(new ManiaRuleset()) + { + } + } +} From 42853b5af645e4ead92c2d1ed7d9077c4d924189 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Dec 2019 15:43:58 +0900 Subject: [PATCH 4714/5608] Separate head/tail notes from hold note class --- .../Objects/Drawables/DrawableHoldNote.cs | 129 +++--------------- .../Objects/Drawables/DrawableHoldNoteHead.cs | 37 +++++ .../Objects/Drawables/DrawableHoldNoteTail.cs | 74 ++++++++++ 3 files changed, 127 insertions(+), 113 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs create mode 100644 osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 87b9633c80..ca3b966d40 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.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.Diagnostics; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; @@ -24,8 +23,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public DrawableNote Head => headContainer.Child; public DrawableNote Tail => tailContainer.Child; - private readonly Container headContainer; - private readonly Container tailContainer; + private readonly Container headContainer; + private readonly Container tailContainer; private readonly Container tickContainer; private readonly BodyPiece bodyPiece; @@ -33,12 +32,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// Time at which the user started holding this hold note. Null if the user is not holding this hold note. /// - private double? holdStartTime; + internal double? HoldStartTime; /// /// Whether the hold note has been released too early and shouldn't give full score for the release. /// - private bool hasBroken; + internal bool HasBroken; public DrawableHoldNote(HoldNote hitObject) : base(hitObject) @@ -49,8 +48,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { bodyPiece = new BodyPiece { RelativeSizeAxes = Axes.X }, tickContainer = new Container { RelativeSizeAxes = Axes.Both }, - headContainer = new Container { RelativeSizeAxes = Axes.Both }, - tailContainer = new Container { RelativeSizeAxes = Axes.Both }, + headContainer = new Container { RelativeSizeAxes = Axes.Both }, + tailContainer = new Container { RelativeSizeAxes = Axes.Both }, }); AccentColour.BindValueChanged(colour => @@ -65,11 +64,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables switch (hitObject) { - case DrawableHeadNote head: + case DrawableHoldNoteHead head: headContainer.Child = head; break; - case DrawableTailNote tail: + case DrawableHoldNoteTail tail: tailContainer.Child = tail; break; @@ -92,7 +91,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables switch (hitObject) { case TailNote _: - return new DrawableTailNote(this) + return new DrawableHoldNoteTail(this) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -100,7 +99,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }; case Note _: - return new DrawableHeadNote(this) + return new DrawableHoldNoteHead(this) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -110,7 +109,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables case HoldNoteTick tick: return new DrawableHoldNoteTick(tick) { - HoldStartTime = () => holdStartTime, + HoldStartTime = () => HoldStartTime, AccentColour = { BindTarget = AccentColour } }; } @@ -146,15 +145,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables base.UpdateStateTransforms(state); } - protected void BeginHold() + internal void BeginHold() { - holdStartTime = Time.Current; + HoldStartTime = Time.Current; bodyPiece.Hitting = true; } protected void EndHold() { - holdStartTime = null; + HoldStartTime = null; bodyPiece.Hitting = false; } @@ -177,7 +176,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public bool OnReleased(ManiaAction action) { // Make sure that the user started holding the key during the hold note - if (!holdStartTime.HasValue) + if (!HoldStartTime.HasValue) return false; if (action != Action.Value) @@ -187,105 +186,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables // If the key has been released too early, the user should not receive full score for the release if (!Tail.IsHit) - hasBroken = true; + HasBroken = true; return true; } - - /// - /// The head note of a hold. - /// - private class DrawableHeadNote : DrawableNote - { - private readonly DrawableHoldNote holdNote; - - public DrawableHeadNote(DrawableHoldNote holdNote) - : base(holdNote.HitObject.Head) - { - this.holdNote = holdNote; - } - - public override bool OnPressed(ManiaAction action) - { - if (!base.OnPressed(action)) - return false; - - // If the key has been released too early, the user should not receive full score for the release - if (Result.Type == HitResult.Miss) - holdNote.hasBroken = true; - - // The head note also handles early hits before the body, but we want accurate early hits to count as the body being held - // The body doesn't handle these early early hits, so we have to explicitly set the holding state here - holdNote.BeginHold(); - - return true; - } - } - - /// - /// The tail note of a hold. - /// - private class DrawableTailNote : DrawableNote - { - /// - /// Lenience of release hit windows. This is to make cases where the hold note release - /// is timed alongside presses of other hit objects less awkward. - /// Todo: This shouldn't exist for non-LegacyBeatmapDecoder beatmaps - /// - private const double release_window_lenience = 1.5; - - private readonly DrawableHoldNote holdNote; - - public DrawableTailNote(DrawableHoldNote holdNote) - : base(holdNote.HitObject.Tail) - { - this.holdNote = holdNote; - } - - protected override void CheckForResult(bool userTriggered, double timeOffset) - { - Debug.Assert(HitObject.HitWindows != null); - - // Factor in the release lenience - timeOffset /= release_window_lenience; - - if (!userTriggered) - { - if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(r => r.Type = HitResult.Miss); - - return; - } - - var result = HitObject.HitWindows.ResultFor(timeOffset); - if (result == HitResult.None) - return; - - ApplyResult(r => - { - if (holdNote.hasBroken && (result == HitResult.Perfect || result == HitResult.Perfect)) - result = HitResult.Good; - - r.Type = result; - }); - } - - public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down - - public override bool OnReleased(ManiaAction action) - { - // Make sure that the user started holding the key during the hold note - if (!holdNote.holdStartTime.HasValue) - return false; - - if (action != Action.Value) - return false; - - UpdateResult(true); - - // Handled by the hold note, which will set holding = false - return false; - } - } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs new file mode 100644 index 0000000000..a1c9a09014 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs @@ -0,0 +1,37 @@ +// 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.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Mania.Objects.Drawables +{ + /// + /// The head of a . + /// + public class DrawableHoldNoteHead : DrawableNote + { + private readonly DrawableHoldNote holdNote; + + public DrawableHoldNoteHead(DrawableHoldNote holdNote) + : base(holdNote.HitObject.Head) + { + this.holdNote = holdNote; + } + + public override bool OnPressed(ManiaAction action) + { + if (!base.OnPressed(action)) + return false; + + // If the key has been released too early, the user should not receive full score for the release + if (Result.Type == HitResult.Miss) + holdNote.HasBroken = true; + + // The head note also handles early hits before the body, but we want accurate early hits to count as the body being held + // The body doesn't handle these early early hits, so we have to explicitly set the holding state here + holdNote.BeginHold(); + + return true; + } + } +} diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs new file mode 100644 index 0000000000..2b23fb1eef --- /dev/null +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs @@ -0,0 +1,74 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Diagnostics; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Mania.Objects.Drawables +{ + /// + /// The tail of a . + /// + public class DrawableHoldNoteTail : DrawableNote + { + /// + /// Lenience of release hit windows. This is to make cases where the hold note release + /// is timed alongside presses of other hit objects less awkward. + /// Todo: This shouldn't exist for non-LegacyBeatmapDecoder beatmaps + /// + private const double release_window_lenience = 1.5; + + private readonly DrawableHoldNote holdNote; + + public DrawableHoldNoteTail(DrawableHoldNote holdNote) + : base(holdNote.HitObject.Tail) + { + this.holdNote = holdNote; + } + + protected override void CheckForResult(bool userTriggered, double timeOffset) + { + Debug.Assert(HitObject.HitWindows != null); + + // Factor in the release lenience + timeOffset /= release_window_lenience; + + if (!userTriggered) + { + if (!HitObject.HitWindows.CanBeHit(timeOffset)) + ApplyResult(r => r.Type = HitResult.Miss); + + return; + } + + var result = HitObject.HitWindows.ResultFor(timeOffset); + if (result == HitResult.None) + return; + + ApplyResult(r => + { + if (holdNote.HasBroken && (result == HitResult.Perfect || result == HitResult.Perfect)) + result = HitResult.Good; + + r.Type = result; + }); + } + + public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down + + public override bool OnReleased(ManiaAction action) + { + // Make sure that the user started holding the key during the hold note + if (!holdNote.HoldStartTime.HasValue) + return false; + + if (action != Action.Value) + return false; + + UpdateResult(true); + + // Handled by the hold note, which will set holding = false + return false; + } + } +} From 7ac6f68de8c4b7ce07d5aab461ff6cb9831558ca Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Dec 2019 17:48:48 +0900 Subject: [PATCH 4715/5608] Rewrite hold note input handling --- .../HoldNoteNoteSelectionBlueprint.cs | 2 +- .../Objects/Drawables/DrawableHoldNote.cs | 58 +++++++++++-------- .../Objects/Drawables/DrawableHoldNoteHead.cs | 21 +------ .../Objects/Drawables/DrawableHoldNoteTail.cs | 19 ++---- 4 files changed, 41 insertions(+), 59 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs index acce41db6f..4e73883de0 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints // Todo: This shouldn't exist, mania should not reference the drawable hitobject directly. if (DrawableObject.IsLoaded) { - DrawableNote note = position == HoldNotePosition.Start ? DrawableObject.Head : DrawableObject.Tail; + DrawableNote note = position == HoldNotePosition.Start ? (DrawableNote)DrawableObject.Head : DrawableObject.Tail; Anchor = note.Anchor; Origin = note.Origin; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index ca3b966d40..c4a3e23cce 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -20,8 +20,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { public override bool DisplayResult => false; - public DrawableNote Head => headContainer.Child; - public DrawableNote Tail => tailContainer.Child; + public DrawableHoldNoteHead Head => headContainer.Child; + public DrawableHoldNoteTail Tail => tailContainer.Child; private readonly Container headContainer; private readonly Container tailContainer; @@ -124,12 +124,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables bodyPiece.Anchor = bodyPiece.Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; } - protected override void CheckForResult(bool userTriggered, double timeOffset) - { - if (Tail.AllJudged) - ApplyResult(r => r.Type = HitResult.Perfect); - } - protected override void Update() { base.Update(); @@ -145,44 +139,52 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables base.UpdateStateTransforms(state); } - internal void BeginHold() + protected override void CheckForResult(bool userTriggered, double timeOffset) { - HoldStartTime = Time.Current; - bodyPiece.Hitting = true; - } + if (Tail.AllJudged) + ApplyResult(r => r.Type = HitResult.Perfect); - protected void EndHold() - { - HoldStartTime = null; - bodyPiece.Hitting = false; + if (Tail.Result.Type == HitResult.Miss) + HasBroken = true; } public bool OnPressed(ManiaAction action) { - // Make sure the action happened within the body of the hold note - if (Time.Current < HitObject.StartTime || Time.Current > HitObject.EndTime) + if (AllJudged) return false; if (action != Action.Value) return false; - // The user has pressed during the body of the hold note, after the head note and its hit windows have passed - // and within the limited range of the above if-statement. This state will be managed by the head note if the - // user has pressed during the hit windows of the head note. - BeginHold(); + beginHoldAt(Time.Current - Head.HitObject.StartTime); + Head.UpdateResult(); + return true; } + private void beginHoldAt(double timeOffset) + { + if (timeOffset < -Head.HitObject.HitWindows.WindowFor(HitResult.Miss)) + return; + + HoldStartTime = Time.Current; + bodyPiece.Hitting = true; + } + public bool OnReleased(ManiaAction action) { - // Make sure that the user started holding the key during the hold note - if (!HoldStartTime.HasValue) + if (AllJudged) return false; if (action != Action.Value) return false; - EndHold(); + // Make sure a hold was started + if (HoldStartTime == null) + return false; + + Tail.UpdateResult(); + endHold(); // If the key has been released too early, the user should not receive full score for the release if (!Tail.IsHit) @@ -190,5 +192,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables return true; } + + private void endHold() + { + HoldStartTime = null; + bodyPiece.Hitting = false; + } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs index a1c9a09014..a5d03bf765 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Rulesets.Scoring; - namespace osu.Game.Rulesets.Mania.Objects.Drawables { /// @@ -10,28 +8,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// public class DrawableHoldNoteHead : DrawableNote { - private readonly DrawableHoldNote holdNote; - public DrawableHoldNoteHead(DrawableHoldNote holdNote) : base(holdNote.HitObject.Head) { - this.holdNote = holdNote; } - public override bool OnPressed(ManiaAction action) - { - if (!base.OnPressed(action)) - return false; + public void UpdateResult() => base.UpdateResult(true); - // If the key has been released too early, the user should not receive full score for the release - if (Result.Type == HitResult.Miss) - holdNote.HasBroken = true; + public override bool OnPressed(ManiaAction action) => false; // Handled by the hold note - // The head note also handles early hits before the body, but we want accurate early hits to count as the body being held - // The body doesn't handle these early early hits, so we have to explicitly set the holding state here - holdNote.BeginHold(); - - return true; - } + public override bool OnReleased(ManiaAction action) => false; // Handled by the hold note } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs index 2b23fb1eef..a1f34a6db2 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs @@ -26,6 +26,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables this.holdNote = holdNote; } + public void UpdateResult() => base.UpdateResult(true); + protected override void CheckForResult(bool userTriggered, double timeOffset) { Debug.Assert(HitObject.HitWindows != null); @@ -54,21 +56,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }); } - public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down + public override bool OnPressed(ManiaAction action) => false; // Handled by the hold note - public override bool OnReleased(ManiaAction action) - { - // Make sure that the user started holding the key during the hold note - if (!holdNote.HoldStartTime.HasValue) - return false; - - if (action != Action.Value) - return false; - - UpdateResult(true); - - // Handled by the hold note, which will set holding = false - return false; - } + public override bool OnReleased(ManiaAction action) => false; // Handled by the hold note } } From 7bb4a08f10a534246bd4f5ccce2c23e89044506e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Dec 2019 18:35:40 +0900 Subject: [PATCH 4716/5608] Add failing tests --- .../TestSceneHoldNoteInput.cs | 314 ++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs new file mode 100644 index 0000000000..8682604b13 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -0,0 +1,314 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Screens; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Replays; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Replays; +using osu.Game.Rulesets.Replays; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Screens.Play; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Mania.Tests +{ + public class TestSceneHoldNoteInput : RateAdjustedBeatmapTestScene + { + private const double time_before_head = 250; + private const double time_head = 1500; + private const double time_during_hold_1 = 2500; + private const double time_tail = 4000; + private const double time_after_tail = 5250; + + private List judgementResults; + private bool allJudgedFired; + + /// + /// -----[ ]----- + /// o o + /// + [Test] + public void TestNoInput() + { + performTest(new List + { + new ManiaReplayFrame(time_before_head), + new ManiaReplayFrame(time_after_tail), + }); + + assertHeadJudgement(HitResult.Miss); + assertTickJudgement(HitResult.Miss); + assertTailJudgement(HitResult.Miss); + assertNoteJudgement(HitResult.Perfect); + } + + /// + /// -----[ ]----- + /// x o + /// + [Test] + public void TestPressTooEarlyAndReleaseAfterTail() + { + performTest(new List + { + new ManiaReplayFrame(time_before_head, ManiaAction.Key1), + new ManiaReplayFrame(time_after_tail, ManiaAction.Key1), + }); + + assertHeadJudgement(HitResult.Miss); + assertTickJudgement(HitResult.Miss); + assertTailJudgement(HitResult.Miss); + } + + /// + /// -----[ ]----- + /// x o + /// + [Test] + public void TestPressTooEarlyAndReleaseAtTail() + { + performTest(new List + { + new ManiaReplayFrame(time_before_head, ManiaAction.Key1), + new ManiaReplayFrame(time_tail), + }); + + assertHeadJudgement(HitResult.Miss); + assertTickJudgement(HitResult.Miss); + assertTailJudgement(HitResult.Miss); + } + + /// + /// -----[ ]----- + /// xo x o + /// + [Test] + public void TestPressTooEarlyThenPressAtStartAndReleaseAfterTail() + { + performTest(new List + { + new ManiaReplayFrame(time_before_head, ManiaAction.Key1), + new ManiaReplayFrame(time_before_head + 10), + new ManiaReplayFrame(time_head, ManiaAction.Key1), + new ManiaReplayFrame(time_after_tail), + }); + + assertHeadJudgement(HitResult.Perfect); + assertTickJudgement(HitResult.Perfect); + assertTailJudgement(HitResult.Miss); + } + + /// + /// -----[ ]----- + /// xo x o + /// + [Test] + public void TestPressTooEarlyThenPressAtStartAndReleaseAtTail() + { + performTest(new List + { + new ManiaReplayFrame(time_before_head, ManiaAction.Key1), + new ManiaReplayFrame(time_before_head + 10), + new ManiaReplayFrame(time_head, ManiaAction.Key1), + new ManiaReplayFrame(time_tail), + }); + + assertHeadJudgement(HitResult.Perfect); + assertTickJudgement(HitResult.Perfect); + assertTailJudgement(HitResult.Perfect); + } + + /// + /// -----[ ]----- + /// xo o + /// + [Test] + public void TestPressAtStartAndBreak() + { + performTest(new List + { + new ManiaReplayFrame(time_head, ManiaAction.Key1), + new ManiaReplayFrame(time_head + 10), + new ManiaReplayFrame(time_after_tail), + }); + + assertHeadJudgement(HitResult.Perfect); + assertTickJudgement(HitResult.Miss); + assertTailJudgement(HitResult.Miss); + } + + /// + /// -----[ ]----- + /// xo x o + /// + [Test] + public void TestPressAtStartThenBreakThenRepressAndReleaseAfterTail() + { + performTest(new List + { + new ManiaReplayFrame(time_head, ManiaAction.Key1), + new ManiaReplayFrame(time_head + 10), + new ManiaReplayFrame(time_during_hold_1, ManiaAction.Key1), + new ManiaReplayFrame(time_after_tail), + }); + + assertHeadJudgement(HitResult.Perfect); + assertTickJudgement(HitResult.Perfect); + assertTailJudgement(HitResult.Miss); + } + + /// + /// -----[ ]----- + /// xo x o o + /// + [Test] + public void TestPressAtStartThenBreakThenRepressAndReleaseAtTail() + { + performTest(new List + { + new ManiaReplayFrame(time_head, ManiaAction.Key1), + new ManiaReplayFrame(time_head + 10), + new ManiaReplayFrame(time_during_hold_1, ManiaAction.Key1), + new ManiaReplayFrame(time_tail), + }); + + assertHeadJudgement(HitResult.Perfect); + assertTickJudgement(HitResult.Perfect); + assertTailJudgement(HitResult.Meh); + } + + /// + /// -----[ ]----- + /// x o + /// + [Test] + public void TestPressDuringNoteAndReleaseAfterTail() + { + performTest(new List + { + new ManiaReplayFrame(time_during_hold_1, ManiaAction.Key1), + new ManiaReplayFrame(time_after_tail), + }); + + assertHeadJudgement(HitResult.Miss); + assertTickJudgement(HitResult.Perfect); + assertTailJudgement(HitResult.Miss); + } + + /// + /// -----[ ]----- + /// x o o + /// + [Test] + public void TestPressDuringNoteAndReleaseAtTail() + { + performTest(new List + { + new ManiaReplayFrame(time_during_hold_1, ManiaAction.Key1), + new ManiaReplayFrame(time_tail), + }); + + assertHeadJudgement(HitResult.Miss); + assertTickJudgement(HitResult.Perfect); + assertTailJudgement(HitResult.Meh); + } + + /// + /// -----[ ]----- + /// xo o + /// + [Test] + public void TestPressAndReleaseAtTail() + { + performTest(new List + { + new ManiaReplayFrame(time_tail, ManiaAction.Key1), + new ManiaReplayFrame(time_tail + 10), + }); + + assertHeadJudgement(HitResult.Miss); + assertTickJudgement(HitResult.Miss); + assertTailJudgement(HitResult.Meh); + } + + private void assertHeadJudgement(HitResult result) + => AddAssert($"head judged as{result}", () => judgementResults[0].Type == result); + + private void assertTailJudgement(HitResult result) + => AddAssert($"tail judged as {result}", () => judgementResults[^2].Type == result); + + private void assertNoteJudgement(HitResult result) + => AddAssert($"hold note judged as {result}", () => judgementResults[^1].Type == result); + + private void assertTickJudgement(HitResult result) + => AddAssert($"tick judged as {result}", () => judgementResults[6].Type == result); // arbitrary tick + + private ScoreAccessibleReplayPlayer currentPlayer; + + private void performTest(List frames) + { + AddStep("load player", () => + { + Beatmap.Value = CreateWorkingBeatmap(new Beatmap + { + HitObjects = + { + new HoldNote + { + StartTime = time_head, + Duration = time_tail - time_head, + Column = 0, + } + }, + BeatmapInfo = + { + BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 4 }, + Ruleset = new ManiaRuleset().RulesetInfo + }, + }); + + Beatmap.Value.Beatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = 0.1f }); + + var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }); + + p.OnLoadComplete += _ => + { + p.ScoreProcessor.NewJudgement += result => + { + if (currentPlayer == p) judgementResults.Add(result); + }; + p.ScoreProcessor.AllJudged += () => + { + if (currentPlayer == p) allJudgedFired = true; + }; + }; + + LoadScreen(currentPlayer = p); + allJudgedFired = false; + judgementResults = new List(); + }); + + AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0); + AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); + AddUntilStep("Wait for all judged", () => allJudgedFired); + } + + private class ScoreAccessibleReplayPlayer : ReplayPlayer + { + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + + protected override bool PauseOnFocusLost => false; + + public ScoreAccessibleReplayPlayer(Score score) + : base(score, false, false) + { + } + } + } +} From d6fd1007c46228c1d4df70c7855ad9bd3f3c3d0d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Dec 2019 18:48:14 +0900 Subject: [PATCH 4717/5608] internal -> public --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index c4a3e23cce..155adb958b 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -32,12 +32,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// Time at which the user started holding this hold note. Null if the user is not holding this hold note. /// - internal double? HoldStartTime; + public double? HoldStartTime { get; private set; } /// /// Whether the hold note has been released too early and shouldn't give full score for the release. /// - internal bool HasBroken; + public bool HasBroken { get; private set; } public DrawableHoldNote(HoldNote hitObject) : base(hitObject) From 63c96d5a83560e864d62585aa27e9443bd968236 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Dec 2019 18:49:08 +0900 Subject: [PATCH 4718/5608] Fix tail note not properly capping result --- .../Objects/Drawables/DrawableHoldNoteTail.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs index a1f34a6db2..a660144dd1 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs @@ -49,8 +49,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables ApplyResult(r => { - if (holdNote.HasBroken && (result == HitResult.Perfect || result == HitResult.Perfect)) - result = HitResult.Good; + // If the head wasn't hit or the hold note was broken, cap the max score to Meh. + if (result > HitResult.Meh && (!holdNote.Head.IsHit || holdNote.HasBroken)) + result = HitResult.Meh; r.Type = result; }); From d5288760a7e85fd60320dbbc6b91c88737e8cf7d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Dec 2019 18:50:18 +0900 Subject: [PATCH 4719/5608] Fix test text --- osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index 8682604b13..7b0cf40d45 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -238,7 +238,7 @@ namespace osu.Game.Rulesets.Mania.Tests } private void assertHeadJudgement(HitResult result) - => AddAssert($"head judged as{result}", () => judgementResults[0].Type == result); + => AddAssert($"head judged as {result}", () => judgementResults[0].Type == result); private void assertTailJudgement(HitResult result) => AddAssert($"tail judged as {result}", () => judgementResults[^2].Type == result); From 125f4286ae75fec93c83a50c243536782a898aed Mon Sep 17 00:00:00 2001 From: Lucas A Date: Mon, 23 Dec 2019 10:55:44 +0100 Subject: [PATCH 4720/5608] Move truncate() to a method body --- osu.Desktop/DiscordRichPresence.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 45552f1906..cd5fba533b 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -100,7 +100,13 @@ namespace osu.Desktop client.SetPresence(presence); } - private string truncate(string str) => str.WithinLength(128) ? str : new string (str.TakeWhile((c, i) => Encoding.UTF8.GetByteCount(str.Substring(0, i + 1)) <= 125).ToArray()) + '…'; //the ellipsis char is 3 bytes long in UTF8 + private string truncate(string str) + { + if (str.WithinLength(128)) + return str; + + return new string(str.TakeWhile((c, i) => Encoding.UTF8.GetByteCount(str.Substring(0, i + 1)) <= 125).ToArray()) + '…'; //the ellipsis char is 3 bytes long in UTF8 + } private string getDetails(UserActivity activity) { From c766477abc64c192f458d8aca45edb7fe47e40db Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Dec 2019 19:08:16 +0900 Subject: [PATCH 4721/5608] Fix testcase containing bad hitobject --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index 02ce77e707..bd9d948782 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Tests EndTime = 6000, }, // placeholder object to avoid hitting the results screen - new HitObject + new HitCircle { StartTime = 99999, } From c7936e40d5c2b02a37ef7821b5d9698146e68a88 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Dec 2019 19:13:36 +0900 Subject: [PATCH 4722/5608] Protect against potential nullref --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 5dfdeb5ebc..8970f9ac88 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -562,7 +562,7 @@ namespace osu.Game.Screens.Play // 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(); + GameplayClockContainer?.StopUsingBeatmapClock(); fadeOut(); return base.OnExiting(next); From 43024122430816e425d69174bf554edfd2be4930 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Dec 2019 19:34:12 +0900 Subject: [PATCH 4723/5608] Simplify implementation --- osu.Desktop/DiscordRichPresence.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index cd5fba533b..85e4b8db55 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -1,10 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; +using System; using System.Text; using DiscordRPC; -using DiscordRPC.Helper; using DiscordRPC.Message; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -100,12 +99,19 @@ namespace osu.Desktop client.SetPresence(presence); } - private string truncate(string str) + private string truncate(ReadOnlySpan str) { - if (str.WithinLength(128)) - return str; + if (Encoding.UTF8.GetByteCount(str) < 128) + return new string(str); - return new string(str.TakeWhile((c, i) => Encoding.UTF8.GetByteCount(str.Substring(0, i + 1)) <= 125).ToArray()) + '…'; //the ellipsis char is 3 bytes long in UTF8 + int ellipsisLength = Encoding.UTF8.GetByteCount(new[] { '…' }); + + do + { + str = str[..^1]; + } while (Encoding.UTF8.GetByteCount(str) + ellipsisLength > 128); + + return new string(str) + '…'; } private string getDetails(UserActivity activity) From b9bc1c954eae7513a1fbb31e90cc71ed43c2aabd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Dec 2019 19:50:35 +0900 Subject: [PATCH 4724/5608] Disable automatic retry of failed discord RPC connections --- osu.Desktop/DiscordRichPresence.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 8818cef8eb..71b73ec78e 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -43,6 +43,10 @@ namespace osu.Desktop }; client.OnReady += onReady; + + // safety measure for now, until we performance test / improve backoff for failed connections. + client.OnConnectionFailed += (_, __) => client.Deinitialize(); + client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network); (user = provider.LocalUser.GetBoundCopy()).BindValueChanged(u => From f1f9e1f658cca54a0888629a6cd9e5c761fe3115 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Dec 2019 19:56:05 +0900 Subject: [PATCH 4725/5608] Don't truncate with exactly 128 bytes --- osu.Desktop/DiscordRichPresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 9d2fad2e1a..ce878edda8 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -100,7 +100,7 @@ namespace osu.Desktop private string truncate(ReadOnlySpan str) { - if (Encoding.UTF8.GetByteCount(str) < 128) + if (Encoding.UTF8.GetByteCount(str) <= 128) return new string(str); int ellipsisLength = Encoding.UTF8.GetByteCount(new[] { '…' }); From a324bfbc2c6960016362c647458f1dfaf536a8c1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Dec 2019 13:48:27 +0900 Subject: [PATCH 4726/5608] Remove LegacyID from Ruleset --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 4 ++-- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 4 ++-- osu.Game.Rulesets.Osu/OsuRuleset.cs | 4 ++-- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 4 ++-- osu.Game/Rulesets/ILegacyRuleset.cs | 13 +++++++++++++ osu.Game/Rulesets/Ruleset.cs | 8 +------- osu.Game/Rulesets/RulesetStore.cs | 11 ++++++++--- 7 files changed, 30 insertions(+), 18 deletions(-) create mode 100644 osu.Game/Rulesets/ILegacyRuleset.cs diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index b8a844cb86..063294f836 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -24,7 +24,7 @@ using System; namespace osu.Game.Rulesets.Catch { - public class CatchRuleset : Ruleset + public class CatchRuleset : Ruleset, ILegacyRuleset { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableCatchRuleset(this, beatmap, mods); @@ -134,7 +134,7 @@ namespace osu.Game.Rulesets.Catch public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new CatchPerformanceCalculator(this, beatmap, score); - public override int? LegacyID => 2; + public int LegacyID => 2; public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new CatchReplayFrame(); } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index bf630cf892..dc2485bfb0 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -31,7 +31,7 @@ using osu.Game.Scoring; namespace osu.Game.Rulesets.Mania { - public class ManiaRuleset : Ruleset + public class ManiaRuleset : Ruleset, ILegacyRuleset { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableManiaRuleset(this, beatmap, mods); @@ -178,7 +178,7 @@ namespace osu.Game.Rulesets.Mania public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new ManiaDifficultyCalculator(this, beatmap); - public override int? LegacyID => 3; + public int LegacyID => 3; public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new ManiaReplayFrame(); diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 27af615935..cab1980dde 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -32,7 +32,7 @@ using System; namespace osu.Game.Rulesets.Osu { - public class OsuRuleset : Ruleset + public class OsuRuleset : Ruleset, ILegacyRuleset { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableOsuRuleset(this, beatmap, mods); @@ -178,7 +178,7 @@ namespace osu.Game.Rulesets.Osu public override ISkin CreateLegacySkinProvider(ISkinSource source) => new OsuLegacySkinTransformer(source); - public override int? LegacyID => 0; + public int LegacyID => 0; public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new OsuReplayFrame(); diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index ca7ab30867..a4cfce0dcc 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -24,7 +24,7 @@ using System; namespace osu.Game.Rulesets.Taiko { - public class TaikoRuleset : Ruleset + public class TaikoRuleset : Ruleset, ILegacyRuleset { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableTaikoRuleset(this, beatmap, mods); @@ -133,7 +133,7 @@ namespace osu.Game.Rulesets.Taiko public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new TaikoPerformanceCalculator(this, beatmap, score); - public override int? LegacyID => 1; + public int LegacyID => 1; public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new TaikoReplayFrame(); } diff --git a/osu.Game/Rulesets/ILegacyRuleset.cs b/osu.Game/Rulesets/ILegacyRuleset.cs new file mode 100644 index 0000000000..06a85b5261 --- /dev/null +++ b/osu.Game/Rulesets/ILegacyRuleset.cs @@ -0,0 +1,13 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets +{ + public interface ILegacyRuleset + { + /// + /// Identifies the server-side ID of a legacy ruleset. + /// + int LegacyID { get; } + } +} diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 7ad93379f0..21d96123f1 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets { public abstract class Ruleset { - public readonly RulesetInfo RulesetInfo; + public RulesetInfo RulesetInfo { get; internal set; } public IEnumerable GetAllMods() => Enum.GetValues(typeof(ModType)).Cast() // Confine all mods of each mod type into a single IEnumerable @@ -103,11 +103,6 @@ namespace osu.Game.Rulesets /// The to store the settings. public virtual IRulesetConfigManager CreateConfig(SettingsStore settings) => null; - /// - /// Do not override this unless you are a legacy mode. - /// - public virtual int? LegacyID => null; - /// /// A unique short name to reference this ruleset in online requests. /// @@ -148,7 +143,6 @@ namespace osu.Game.Rulesets Name = Description, ShortName = ShortName, InstantiationInfo = GetType().AssemblyQualifiedName, - ID = LegacyID, Available = true }; } diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 5d0c5c7ccf..5d2a7df458 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -59,16 +59,21 @@ namespace osu.Game.Rulesets var instances = loadedAssemblies.Values.Select(r => (Ruleset)Activator.CreateInstance(r)).ToList(); //add all legacy modes in correct order - foreach (var r in instances.Where(r => r.LegacyID != null).OrderBy(r => r.LegacyID)) + foreach (var r in instances.Where(r => r is ILegacyRuleset)) { - if (context.RulesetInfo.SingleOrDefault(rsi => rsi.ID == r.RulesetInfo.ID) == null) + int legacyId = ((ILegacyRuleset)r).LegacyID; + + if (context.RulesetInfo.SingleOrDefault(rsi => rsi.ID == legacyId) == null) + { + r.RulesetInfo.ID = legacyId; context.RulesetInfo.Add(r.RulesetInfo); + } } context.SaveChanges(); //add any other modes - foreach (var r in instances.Where(r => r.LegacyID == null)) + foreach (var r in instances.Where(r => !(r is ILegacyRuleset))) { if (context.RulesetInfo.FirstOrDefault(ri => ri.InstantiationInfo == r.RulesetInfo.InstantiationInfo) == null) context.RulesetInfo.Add(r.RulesetInfo); From 0bfd7579362d55a258163c70ba1a8640b1e11eff Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 24 Dec 2019 14:21:16 +0900 Subject: [PATCH 4727/5608] Make OsuTextBox use BasicTextBox --- osu.Game/Graphics/UserInterface/OsuTextBox.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index 1cac4d76ab..72fa135699 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -12,7 +12,7 @@ using osu.Framework.Input.Events; namespace osu.Game.Graphics.UserInterface { - public class OsuTextBox : TextBox + public class OsuTextBox : BasicTextBox { protected override float LeftRightPadding => 10; @@ -41,6 +41,8 @@ namespace osu.Game.Graphics.UserInterface BackgroundCommit = BorderColour = colour.Yellow; } + protected override Color4 SelectionColour => new Color4(249, 90, 255, 255); + protected override void OnFocus(FocusEvent e) { BorderThickness = 3; From 0677f746aaf2fb7bbf134b7dc1237c04cabbf24d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Dec 2019 16:02:16 +0900 Subject: [PATCH 4728/5608] Provide the ruleset to converter classes --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs | 4 ++-- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs | 6 +++--- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs | 2 +- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs | 4 ++-- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 6 +++--- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 5 +++-- .../Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs | 6 +++--- osu.Game/Beatmaps/BeatmapConverter.cs | 3 ++- 12 files changed, 23 insertions(+), 21 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index b5497ea89f..036c86ffa3 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -14,8 +14,8 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { public class CatchBeatmapConverter : BeatmapConverter { - public CatchBeatmapConverter(IBeatmap beatmap) - : base(beatmap) + public CatchBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) + : base(beatmap, ruleset) { } diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 063294f836..b329f6cd98 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Catch public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new CatchScoreProcessor(beatmap); - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap, this); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); public const string SHORT_NAME = "fruits"; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 6e4491de94..aac3f914a4 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -37,10 +37,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps private ManiaBeatmap beatmap; - public ManiaBeatmapConverter(IBeatmap beatmap) - : base(beatmap) + public ManiaBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) + : base(beatmap, ruleset) { - IsForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(new ManiaRuleset().RulesetInfo); + IsForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo); var roundedCircleSize = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.CircleSize); var roundedOverallDifficulty = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index dc2485bfb0..28971b11c5 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Mania public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new ManiaScoreProcessor(beatmap); - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap, this); public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score); diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index 70ba5cd938..877a9ee410 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mania.Replays public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) { // We don't need to fully convert, just create the converter - var converter = new ManiaBeatmapConverter(beatmap); + var converter = new ManiaBeatmapConverter(beatmap, new ManiaRuleset()); // NB: Via co-op mod, osu-stable can have two stages with floor(col/2) and ceil(col/2) columns. This will need special handling // elsewhere in the game if we do choose to support the old co-op mod anyway. For now, assume that there is only one stage. diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 2296030f81..7bc14c3e41 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -15,8 +15,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps { public class OsuBeatmapConverter : BeatmapConverter { - public OsuBeatmapConverter(IBeatmap beatmap) - : base(beatmap) + public OsuBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) + : base(beatmap, ruleset) { } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index cab1980dde..57d99df5fb 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Osu public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new OsuScoreProcessor(beatmap); - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap, this); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 10cc861b7e..96e7722e73 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -41,10 +41,10 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(HitObject) }; - public TaikoBeatmapConverter(IBeatmap beatmap) - : base(beatmap) + public TaikoBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) + : base(beatmap, ruleset) { - isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(new TaikoRuleset().RulesetInfo); + isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo); } protected override Beatmap ConvertBeatmap(IBeatmap original) diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index a4cfce0dcc..529dfe765c 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Taiko public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new TaikoScoreProcessor(beatmap); - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap, this); public const string SHORT_NAME = "taiko"; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 26e70f19e4..33f484a9aa 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -14,6 +14,7 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Timing; using osu.Game.IO; +using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; @@ -313,7 +314,7 @@ namespace osu.Game.Tests.Beatmaps.Formats { var beatmap = decoder.Decode(stream); - var converted = new OsuBeatmapConverter(beatmap).Convert(); + var converted = new OsuBeatmapConverter(beatmap, new OsuRuleset()).Convert(); new OsuBeatmapProcessor(converted).PreProcess(); new OsuBeatmapProcessor(converted).PostProcess(); @@ -336,7 +337,7 @@ namespace osu.Game.Tests.Beatmaps.Formats { var beatmap = decoder.Decode(stream); - var converted = new CatchBeatmapConverter(beatmap).Convert(); + var converted = new CatchBeatmapConverter(beatmap, new CatchRuleset()).Convert(); new CatchBeatmapProcessor(converted).PreProcess(); new CatchBeatmapProcessor(converted).PostProcess(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index ae20bbc86d..dc950e43bd 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -198,7 +198,7 @@ namespace osu.Game.Tests.Visual.Gameplay public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new TestDrawableScrollingRuleset(this, beatmap, mods); - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap, null); public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new NotImplementedException(); @@ -268,8 +268,8 @@ namespace osu.Game.Tests.Visual.Gameplay private class TestBeatmapConverter : BeatmapConverter { - public TestBeatmapConverter(IBeatmap beatmap) - : base(beatmap) + public TestBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) + : base(beatmap, ruleset) { } diff --git a/osu.Game/Beatmaps/BeatmapConverter.cs b/osu.Game/Beatmaps/BeatmapConverter.cs index 7922843626..e6de1eebcd 100644 --- a/osu.Game/Beatmaps/BeatmapConverter.cs +++ b/osu.Game/Beatmaps/BeatmapConverter.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; namespace osu.Game.Beatmaps @@ -25,7 +26,7 @@ namespace osu.Game.Beatmaps public IBeatmap Beatmap { get; } - protected BeatmapConverter(IBeatmap beatmap) + protected BeatmapConverter(IBeatmap beatmap, Ruleset ruleset) { Beatmap = beatmap; } From d87203857b24c55b1bc8fb58229d9743c142044d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Dec 2019 16:02:35 +0900 Subject: [PATCH 4729/5608] Move default construction into constructor --- osu.Game/Rulesets/Ruleset.cs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 21d96123f1..107633194f 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -51,7 +51,14 @@ namespace osu.Game.Rulesets protected Ruleset() { - RulesetInfo = createRulesetInfo(); + RulesetInfo = new RulesetInfo + { + Name = Description, + ShortName = ShortName, + ID = (this as ILegacyRuleset)?.LegacyID, + InstantiationInfo = GetType().AssemblyQualifiedName, + Available = true + }; } /// @@ -133,17 +140,5 @@ namespace osu.Game.Rulesets /// /// An empty frame for the current ruleset, or null if unsupported. public virtual IConvertibleReplayFrame CreateConvertibleReplayFrame() => null; - - /// - /// Create a ruleset info based on this ruleset. - /// - /// A filled . - private RulesetInfo createRulesetInfo() => new RulesetInfo - { - Name = Description, - ShortName = ShortName, - InstantiationInfo = GetType().AssemblyQualifiedName, - Available = true - }; } } From 57382676422d614f87cb3e7177234b8a2068028e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Dec 2019 16:05:20 +0900 Subject: [PATCH 4730/5608] Copy ruleset info over default --- osu.Game/Rulesets/RulesetInfo.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index d695e0b56d..ececc18c96 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -20,11 +20,17 @@ namespace osu.Game.Rulesets [JsonIgnore] public bool Available { get; set; } + // TODO: this should probably be moved to RulesetStore. public virtual Ruleset CreateInstance() { if (!Available) return null; - return (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo)); + var ruleset = (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo)); + + // overwrite the pre-populated RulesetInfo with a potentially database attached copy. + ruleset.RulesetInfo = this; + + return ruleset; } public bool Equals(RulesetInfo other) => other != null && ID == other.ID && Available == other.Available && Name == other.Name && InstantiationInfo == other.InstantiationInfo; From fcb7a9ade50320e552236810c4ad5aff7b5d0e58 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Dec 2019 16:16:55 +0900 Subject: [PATCH 4731/5608] Update RulesetStore to read from populated defaults --- osu.Game/Rulesets/RulesetStore.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 5d2a7df458..a389d4ff75 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -58,16 +58,11 @@ namespace osu.Game.Rulesets var instances = loadedAssemblies.Values.Select(r => (Ruleset)Activator.CreateInstance(r)).ToList(); - //add all legacy modes in correct order + //add all legacy rulesets first to ensure they have exclusive choice of primary key. foreach (var r in instances.Where(r => r is ILegacyRuleset)) { - int legacyId = ((ILegacyRuleset)r).LegacyID; - - if (context.RulesetInfo.SingleOrDefault(rsi => rsi.ID == legacyId) == null) - { - r.RulesetInfo.ID = legacyId; + if (context.RulesetInfo.SingleOrDefault(dbRuleset => dbRuleset.ID == r.RulesetInfo.ID) == null) context.RulesetInfo.Add(r.RulesetInfo); - } } context.SaveChanges(); From 00546787c889489362283dc28d998c2f035c8d3a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Dec 2019 20:36:57 +0900 Subject: [PATCH 4732/5608] Remove unused method --- osu.Game/Rulesets/Scoring/HealthProcessor.cs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index 8af8177083..d05e2d7b6b 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -80,23 +80,5 @@ namespace osu.Game.Rulesets.Scoring Health.Value = 1; HasFailed = false; } - - /// - /// Checks if the score is in a failed state and notifies subscribers. - /// - /// This can only ever notify subscribers once. - /// - /// - private void updateFailed(JudgementResult result) - { - if (HasFailed) - return; - - if (!DefaultFailCondition && FailConditions?.Invoke(this, result) != true) - return; - - if (Failed?.Invoke() != false) - HasFailed = true; - } } } From e088a856620a584ba4dd8b639e9033b6df7f65f8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Dec 2019 17:12:12 +0900 Subject: [PATCH 4733/5608] 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 dd11804b90..d684b73d8d 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 757e0e11fa..4c5f3e0f38 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 0dba92b975..ccfbee9a62 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From e3753ae29fb88c1aec22896abf4bdcd54df6ded6 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Mon, 23 Dec 2019 11:23:03 +0100 Subject: [PATCH 4734/5608] Make the easy mod's extra life count customizable --- osu.Game/Rulesets/Mods/ModEasy.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index a55ebc51d6..7f52cccbc5 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; @@ -21,7 +22,14 @@ namespace osu.Game.Rulesets.Mods public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) }; - private int retries = 2; + [SettingSource("Extra Lives", "Number of extra lives")] + public Bindable Retries { get; } = new BindableInt(2) + { + MinValue = 0, + MaxValue = 10 + }; + + private int retries; private BindableNumber health; @@ -32,6 +40,8 @@ namespace osu.Game.Rulesets.Mods difficulty.ApproachRate *= ratio; difficulty.DrainRate *= ratio; difficulty.OverallDifficulty *= ratio; + + retries = Retries.Value; } public bool AllowFail From bc75bd34f6222c5fa3ccd5678d745700061e10a4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Dec 2019 18:23:09 +0900 Subject: [PATCH 4735/5608] Fix caret width having changed --- osu.Game/Graphics/UserInterface/OsuTextBox.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index 72fa135699..f5b7bc3073 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -16,6 +16,8 @@ namespace osu.Game.Graphics.UserInterface { protected override float LeftRightPadding => 10; + protected override float CaretWidth => 3; + protected override SpriteText CreatePlaceholder() => new OsuSpriteText { Font = OsuFont.GetFont(italics: true), From 36dd0e69980eb39c4df566a4ead1b5773dec737d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 11:14:40 +0900 Subject: [PATCH 4736/5608] Make ellipsis length into a static --- osu.Desktop/DiscordRichPresence.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index ce878edda8..73c717b97c 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -98,17 +98,17 @@ namespace osu.Desktop client.SetPresence(presence); } + private static readonly int ellipsis_length = Encoding.UTF8.GetByteCount(new[] { '…' }); + private string truncate(ReadOnlySpan str) { if (Encoding.UTF8.GetByteCount(str) <= 128) return new string(str); - int ellipsisLength = Encoding.UTF8.GetByteCount(new[] { '…' }); - do { str = str[..^1]; - } while (Encoding.UTF8.GetByteCount(str) + ellipsisLength > 128); + } while (Encoding.UTF8.GetByteCount(str) + ellipsis_length > 128); return new string(str) + '…'; } From 1a7937bcf73f0fe3bc87666df542b6e1c0cd3ba6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 12:04:28 +0900 Subject: [PATCH 4737/5608] Apply suggested optimisations --- osu.Desktop/DiscordRichPresence.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 73c717b97c..05004cf76e 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -100,17 +100,23 @@ namespace osu.Desktop private static readonly int ellipsis_length = Encoding.UTF8.GetByteCount(new[] { '…' }); - private string truncate(ReadOnlySpan str) + private string truncate(string str) { if (Encoding.UTF8.GetByteCount(str) <= 128) - return new string(str); + return str; + + ReadOnlyMemory strMem = str.AsMemory(); do { - str = str[..^1]; - } while (Encoding.UTF8.GetByteCount(str) + ellipsis_length > 128); + strMem = strMem[..^1]; + } while (Encoding.UTF8.GetByteCount(strMem.Span) + ellipsis_length > 128); - return new string(str) + '…'; + return string.Create(strMem.Length + 1, strMem, (span, mem) => + { + mem.Span.CopyTo(span); + span[^1] = '…'; + }); } private string getDetails(UserActivity activity) From 145ac8e0b547c3f8472f4a0344dec7b6e3a4730a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Dec 2019 14:55:05 +0900 Subject: [PATCH 4738/5608] Remove redundant setter --- osu.Game/Beatmaps/Formats/IHasComboColours.cs | 2 +- osu.Game/Skinning/SkinConfiguration.cs | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/IHasComboColours.cs b/osu.Game/Beatmaps/Formats/IHasComboColours.cs index ac0d32dbaa..41c85db063 100644 --- a/osu.Game/Beatmaps/Formats/IHasComboColours.cs +++ b/osu.Game/Beatmaps/Formats/IHasComboColours.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps.Formats /// /// Retrieves the list of combo colours for presentation only. /// - IReadOnlyList ComboColours { get; set; } + IReadOnlyList ComboColours { get; } /// /// Adds combo colours to the list. diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index e3a0ab23fa..a55870aa6d 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Linq; using osu.Game.Beatmaps.Formats; using osuTK.Graphics; @@ -28,7 +27,7 @@ namespace osu.Game.Skinning new Color4(242, 24, 57, 255), }; - private List comboColours = new List(); + private readonly List comboColours = new List(); public IReadOnlyList ComboColours { @@ -42,7 +41,6 @@ namespace osu.Game.Skinning return null; } - set => comboColours = value.ToList(); } public void AddComboColours(params Color4[] colours) => comboColours.AddRange(colours); From 04cbdd9c6c253f04a63b13fd9052cbe1cf181477 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Dec 2019 14:55:13 +0900 Subject: [PATCH 4739/5608] Make test easier to visually examine --- osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index c26afefc41..9adcf26529 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Osu.Tests { public static Color4[] Colours { get; } = { - new Color4(10, 100, 150, 255), + new Color4(150, 100, 50, 255), new Color4(20, 20, 20, 255), }; From 783159f7a06de9438552f0de2b9654662b78b6ac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Dec 2019 14:55:22 +0900 Subject: [PATCH 4740/5608] Remove redundant logic --- osu.Game/Skinning/DefaultSkinConfiguration.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Skinning/DefaultSkinConfiguration.cs b/osu.Game/Skinning/DefaultSkinConfiguration.cs index 8e89ab25b2..5842ee82ee 100644 --- a/osu.Game/Skinning/DefaultSkinConfiguration.cs +++ b/osu.Game/Skinning/DefaultSkinConfiguration.cs @@ -8,9 +8,5 @@ namespace osu.Game.Skinning /// public class DefaultSkinConfiguration : SkinConfiguration { - public DefaultSkinConfiguration() - { - ComboColours = DefaultComboColours; - } } } From 9090d13e05ffe278e31c951f7f8ebf9d990da11c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Dec 2019 15:01:05 +0900 Subject: [PATCH 4741/5608] Simplify tests --- .../TestSceneLegacyBeatmapSkin.cs | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index 9adcf26529..e26b671d57 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -9,8 +9,8 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; using osu.Framework.IO.Stores; +using osu.Framework.Testing; using osu.Game.Beatmaps; -using osu.Game.Graphics.Containers; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens; using osu.Game.Screens.Play; @@ -30,39 +30,33 @@ namespace osu.Game.Rulesets.Osu.Tests public void TestBeatmapComboColours() { ExposedPlayer player = null; - IReadOnlyList colours = null; - AddStep("load beatmap", () => player = loadBeatmap(false, true)); + AddStep("load coloured beatmap", () => player = loadBeatmap(false, true)); AddUntilStep("wait for player", () => player.IsLoaded); - AddStep("retrieve combo colours", () => colours = player.BeatmapSkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value); - AddAssert("is beatmap skin colours", () => colours.SequenceEqual(TestBeatmapSkin.Colours)); + AddAssert("is beatmap skin colours", () => player.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours)); } [Test] public void TestEmptyBeatmapComboColours() { ExposedPlayer player = null; - IReadOnlyList colours = null; AddStep("load no-colour beatmap", () => player = loadBeatmap(false, false)); AddUntilStep("wait for player", () => player.IsLoaded); - AddStep("retrieve combo colours", () => colours = player.BeatmapSkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value); - AddAssert("is default user skin colours", () => colours.SequenceEqual(SkinConfiguration.DefaultComboColours)); + AddAssert("is default user skin colours", () => player.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours)); } [Test] public void TestEmptyBeatmapCustomSkinColours() { ExposedPlayer player = null; - IReadOnlyList colours = null; - AddStep("load no-colour beatmap", () => player = loadBeatmap(true, false)); + AddStep("load custom-skin colour", () => player = loadBeatmap(true, false)); AddUntilStep("wait for player", () => player.IsLoaded); - AddStep("retrieve combo colours", () => colours = player.BeatmapSkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value); - AddAssert("is custom user skin colours", () => colours.SequenceEqual(TestSkin.Colours)); + AddAssert("is custom user skin colours", () => player.UsableComboColours.SequenceEqual(TestSkin.Colours)); } private ExposedPlayer loadBeatmap(bool userHasCustomColours, bool beatmapHasColours) @@ -92,7 +86,10 @@ namespace osu.Game.Rulesets.Osu.Tests return dependencies; } - public BeatmapSkinProvidingContainer BeatmapSkin => GameplayClockContainer.OfType().First().OfType().First(); + public IReadOnlyList UsableComboColours => + GameplayClockContainer.ChildrenOfType() + .First() + .GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value; } private class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap From 3485ef33a726b1caee8a0245188691d79da38674 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Dec 2019 15:05:08 +0900 Subject: [PATCH 4742/5608] Rename tests and add missing coverage --- .../TestSceneLegacyBeatmapSkin.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index e26b671d57..4676f14655 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -26,19 +26,20 @@ namespace osu.Game.Rulesets.Osu.Tests [Resolved] private AudioManager audio { get; set; } - [Test] - public void TestBeatmapComboColours() + [TestCase(true)] + [TestCase(false)] + public void TestBeatmapComboColours(bool customSkinColoursPresent) { ExposedPlayer player = null; - AddStep("load coloured beatmap", () => player = loadBeatmap(false, true)); + AddStep("load coloured beatmap", () => player = loadBeatmap(customSkinColoursPresent, true)); AddUntilStep("wait for player", () => player.IsLoaded); AddAssert("is beatmap skin colours", () => player.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours)); } [Test] - public void TestEmptyBeatmapComboColours() + public void TestBeatmapNoComboColours() { ExposedPlayer player = null; @@ -49,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestEmptyBeatmapCustomSkinColours() + public void TestBeatmapNoComboColoursSkinOverride() { ExposedPlayer player = null; From 52ba0cd816381fe5a1208c7aba8266caa0f839b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Dec 2019 15:20:04 +0900 Subject: [PATCH 4743/5608] Rename method to be more appropriate Also adds xmldoc. --- .../Mods/CatchModDifficultyAdjust.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs | 4 ++-- osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 12 ++++++++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs index 2e1e655844..a3e314eee8 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs @@ -30,9 +30,9 @@ namespace osu.Game.Rulesets.Catch.Mods Value = 5, }; - protected override void UpdateSettings(BeatmapDifficulty difficulty) + protected override void TransferSettings(BeatmapDifficulty difficulty) { - base.UpdateSettings(difficulty); + base.TransferSettings(difficulty); CircleSize.Value = CircleSize.Default = difficulty.CircleSize; ApproachRate.Value = ApproachRate.Default = difficulty.ApproachRate; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs index 3e9c51db85..6c76de5440 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs @@ -30,9 +30,9 @@ namespace osu.Game.Rulesets.Osu.Mods Value = 5, }; - protected override void UpdateSettings(BeatmapDifficulty difficulty) + protected override void TransferSettings(BeatmapDifficulty difficulty) { - base.UpdateSettings(difficulty); + base.TransferSettings(difficulty); CircleSize.Value = CircleSize.Default = difficulty.CircleSize; ApproachRate.Value = ApproachRate.Default = difficulty.ApproachRate; diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs index 1405ccec8d..9721784aee 100644 --- a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -52,18 +52,26 @@ namespace osu.Game.Rulesets.Mods if (this.difficulty == null || this.difficulty.ID != difficulty.ID) { this.difficulty = difficulty; - UpdateSettings(difficulty); + TransferSettings(difficulty); } else ApplySettings(difficulty); } - protected virtual void UpdateSettings(BeatmapDifficulty difficulty) + /// + /// Transfer initial settings from the beatmap to settings. + /// + /// The beatmap's initial values. + protected virtual void TransferSettings(BeatmapDifficulty difficulty) { DrainRate.Value = DrainRate.Default = difficulty.DrainRate; OverallDifficulty.Value = OverallDifficulty.Default = difficulty.OverallDifficulty; } + /// + /// Apply all custom settings to the provided beatmap. + /// + /// The beatmap to have settings applied. protected virtual void ApplySettings(BeatmapDifficulty difficulty) { difficulty.DrainRate = DrainRate.Value; From 911dc2d98dfe1074feeba9d9b83dd2ebaa9a02ce Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Dec 2019 15:20:10 +0900 Subject: [PATCH 4744/5608] Fix code inspections --- osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs | 4 ++-- osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs index a3e314eee8..4c0f5d510e 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Catch.Mods public class CatchModDifficultyAdjust : ModDifficultyAdjust { [SettingSource("Fruit Size", "Override a beatmap's set CS.")] - public BindableNumber CircleSize { get; } = new BindableFloat() + public BindableNumber CircleSize { get; } = new BindableFloat { Precision = 0.1f, MinValue = 1, @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Catch.Mods }; [SettingSource("Approach Rate", "Override a beatmap's set AR.")] - public BindableNumber ApproachRate { get; } = new BindableFloat() + public BindableNumber ApproachRate { get; } = new BindableFloat { Precision = 0.1f, MinValue = 1, diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs index 6c76de5440..0514e2ab34 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Osu.Mods public class OsuModDifficultyAdjust : ModDifficultyAdjust { [SettingSource("Circle Size", "Override a beatmap's set CS.")] - public BindableNumber CircleSize { get; } = new BindableFloat() + public BindableNumber CircleSize { get; } = new BindableFloat { Precision = 0.1f, MinValue = 1, @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Mods }; [SettingSource("Approach Rate", "Override a beatmap's set AR.")] - public BindableNumber ApproachRate { get; } = new BindableFloat() + public BindableNumber ApproachRate { get; } = new BindableFloat { Precision = 0.1f, MinValue = 1, diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs index 9721784aee..224fc78508 100644 --- a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => new[] { typeof(ModEasy), typeof(ModHardRock) }; [SettingSource("Drain Rate", "Override a beatmap's set HP.")] - public BindableNumber DrainRate { get; } = new BindableFloat() + public BindableNumber DrainRate { get; } = new BindableFloat { Precision = 0.1f, MinValue = 1, @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Mods }; [SettingSource("Overall Difficulty", "Override a beatmap's set OD.")] - public BindableNumber OverallDifficulty { get; } = new BindableFloat() + public BindableNumber OverallDifficulty { get; } = new BindableFloat { Precision = 0.1f, MinValue = 1, From 81c330ec2677d07e091e31254bfc665bed282d85 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 Dec 2019 18:51:44 +0900 Subject: [PATCH 4745/5608] 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 d684b73d8d..e7f90af5fd 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 4c5f3e0f38..0c0a58d533 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 ccfbee9a62..edeeea239e 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From a47e5aeead8382a9b889d30c3e16183bf6a7ae7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 26 Dec 2019 00:51:44 +0900 Subject: [PATCH 4746/5608] Fix sample lookup not working correctly for custom rulesets --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index df1b8078a6..f318539bb7 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -159,7 +159,7 @@ namespace osu.Game.Rulesets.UI dependencies.Cache(textureStore); localSampleStore = dependencies.Get().GetSampleStore(new NamespacedResourceStore(resources, "Samples")); - dependencies.CacheAs(new FallbackSampleStore(localSampleStore, dependencies.Get())); + dependencies.CacheAs(new FallbackSampleStore(localSampleStore, dependencies.Get())); } onScreenDisplay = dependencies.Get(); From 3e3415511476aa6941b8b0b914a72f7b2026fdf4 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 25 Dec 2019 21:56:43 +0300 Subject: [PATCH 4747/5608] Update ScreenTitle with the new design --- .../Graphics/UserInterface/ScreenTitle.cs | 52 ++++++++++++------- .../UserInterface/ScreenTitleTextureIcon.cs | 39 +++----------- osu.Game/Overlays/OverlayHeader.cs | 2 +- osu.Game/Screens/Multi/Header.cs | 2 +- 4 files changed, 41 insertions(+), 54 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index 10fc312d8b..bea37d4f34 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Sprites; using osuTK; @@ -13,15 +14,12 @@ namespace osu.Game.Graphics.UserInterface { public abstract class ScreenTitle : CompositeDrawable, IHasAccentColour { - public const float ICON_WIDTH = ICON_SIZE + icon_spacing; - - public const float ICON_SIZE = 25; + public const float ICON_SIZE = 30; + private const int text_offset = 2; private SpriteIcon iconSprite; private readonly OsuSpriteText titleText, pageText; - private const float icon_spacing = 10; - protected IconUsage Icon { set @@ -63,26 +61,40 @@ namespace osu.Game.Graphics.UserInterface new FillFlowContainer { AutoSizeAxes = Axes.Both, - Spacing = new Vector2(icon_spacing, 0), + Spacing = new Vector2(6, 0), + Direction = FillDirection.Horizontal, Children = new[] { - CreateIcon(), - new FillFlowContainer + CreateIcon().With(t => { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(6, 0), - Children = new[] + t.Anchor = Anchor.Centre; + t.Origin = Anchor.Centre; + }), + titleText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold), + Margin = new MarginPadding { Bottom = text_offset } + }, + new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + Size = new Vector2(4), + Child = new Box { - titleText = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light), - }, - pageText = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light), - } + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray, } + }, + pageText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 20), + Margin = new MarginPadding { Bottom = text_offset } } } }, diff --git a/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs b/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs index f590e7e357..e36000af4e 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osuTK; @@ -16,8 +15,6 @@ namespace osu.Game.Graphics.UserInterface /// public class ScreenTitleTextureIcon : CompositeDrawable { - private const float circle_allowance = 0.8f; - private readonly string textureName; public ScreenTitleTextureIcon(string textureName) @@ -26,38 +23,16 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private void load(TextureStore textures, OsuColour colours) + private void load(TextureStore textures) { - Size = new Vector2(ScreenTitle.ICON_SIZE / circle_allowance); + Size = new Vector2(ScreenTitle.ICON_SIZE); - InternalChildren = new Drawable[] + InternalChild = new Sprite { - new CircularContainer - { - Masking = true, - BorderColour = colours.Violet, - BorderThickness = 3, - MaskingSmoothness = 1, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Sprite - { - RelativeSizeAxes = Axes.Both, - Texture = textures.Get(textureName), - Size = new Vector2(circle_allowance), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Violet, - Alpha = 0, - AlwaysPresent = true, - }, - } - }, + RelativeSizeAxes = Axes.Both, + Texture = textures.Get(textureName), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, }; } } diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index 2e032db2ba..95de1eace1 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -39,7 +39,7 @@ namespace osu.Game.Overlays Depth = -float.MaxValue, Children = new Drawable[] { - CreateTitle().With(t => t.X = -ScreenTitle.ICON_WIDTH), + CreateTitle().With(t => t.X = -ScreenTitle.ICON_SIZE), TabControl = new OverlayHeaderTabControl { Anchor = Anchor.BottomLeft, diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index 1cbf2a45e7..402c5ca5bb 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Multi { Anchor = Anchor.CentreLeft, Origin = Anchor.BottomLeft, - X = -ScreenTitle.ICON_WIDTH, + X = -ScreenTitle.ICON_SIZE, }, breadcrumbs = new HeaderBreadcrumbControl(stack) { From c77679e36c6e4d339544a1c304459cf1bcdad141 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 25 Dec 2019 21:57:22 +0300 Subject: [PATCH 4748/5608] Naming fixes for overlays using ScreenTitle --- .../Overlays/Changelog/ChangelogHeader.cs | 2 +- osu.Game/Overlays/News/NewsHeader.cs | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index b2e9be24b3..18dcdf721c 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -111,7 +111,7 @@ namespace osu.Game.Overlays.Changelog public ChangelogHeaderTitle() { - Title = "Changelog"; + Title = "changelog"; Version = null; } diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 27620ab523..0f73663605 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -15,7 +15,7 @@ namespace osu.Game.Overlays.News { public class NewsHeader : OverlayHeader { - private const string front_page_string = "Front Page"; + private const string front_page_string = "frontpage"; private NewsHeaderTitle title; @@ -33,7 +33,7 @@ namespace osu.Game.Overlays.News ShowFrontPage?.Invoke(); }; - Current.ValueChanged += showArticle; + Current.ValueChanged += showPost; } [BackgroundDependencyLoader] @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.News TabControl.AccentColour = colour.Violet; } - private void showArticle(ValueChangedEvent e) + private void showPost(ValueChangedEvent e) { if (e.OldValue != null) TabControl.RemoveItem(e.OldValue); @@ -52,12 +52,12 @@ namespace osu.Game.Overlays.News TabControl.AddItem(e.NewValue); TabControl.Current.Value = e.NewValue; - title.IsReadingArticle = true; + title.IsReadingPost = true; } else { TabControl.Current.Value = front_page_string; - title.IsReadingArticle = false; + title.IsReadingPost = false; } } @@ -84,17 +84,17 @@ namespace osu.Game.Overlays.News private class NewsHeaderTitle : ScreenTitle { - private const string article_string = "Article"; + private const string post_string = "post"; - public bool IsReadingArticle + public bool IsReadingPost { - set => Section = value ? article_string : front_page_string; + set => Section = value ? post_string : front_page_string; } public NewsHeaderTitle() { - Title = "News"; - IsReadingArticle = false; + Title = "news"; + IsReadingPost = false; } protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/news"); From bb4d02a1f8d353c752ee2ba6fa4210869273156a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 25 Dec 2019 22:09:14 +0300 Subject: [PATCH 4749/5608] Fix incorrect icon offset --- osu.Game/Graphics/UserInterface/ScreenTitle.cs | 5 ++++- osu.Game/Overlays/OverlayHeader.cs | 2 +- osu.Game/Screens/Multi/Header.cs | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index bea37d4f34..a8c8005a41 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -14,7 +14,10 @@ namespace osu.Game.Graphics.UserInterface { public abstract class ScreenTitle : CompositeDrawable, IHasAccentColour { + public const float ICON_WIDTH = ICON_SIZE + spacing; + public const float ICON_SIZE = 30; + private const float spacing = 6; private const int text_offset = 2; private SpriteIcon iconSprite; @@ -61,7 +64,7 @@ namespace osu.Game.Graphics.UserInterface new FillFlowContainer { AutoSizeAxes = Axes.Both, - Spacing = new Vector2(6, 0), + Spacing = new Vector2(spacing, 0), Direction = FillDirection.Horizontal, Children = new[] { diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index 95de1eace1..2e032db2ba 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -39,7 +39,7 @@ namespace osu.Game.Overlays Depth = -float.MaxValue, Children = new Drawable[] { - CreateTitle().With(t => t.X = -ScreenTitle.ICON_SIZE), + CreateTitle().With(t => t.X = -ScreenTitle.ICON_WIDTH), TabControl = new OverlayHeaderTabControl { Anchor = Anchor.BottomLeft, diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index 402c5ca5bb..1cbf2a45e7 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Multi { Anchor = Anchor.CentreLeft, Origin = Anchor.BottomLeft, - X = -ScreenTitle.ICON_SIZE, + X = -ScreenTitle.ICON_WIDTH, }, breadcrumbs = new HeaderBreadcrumbControl(stack) { From 89fa1be2c8d1fc38cf86dbd9dc3522c5687c151f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 25 Dec 2019 22:55:14 +0300 Subject: [PATCH 4750/5608] Fix download manager potentially not handling cancel requests --- osu.Game/Database/DownloadableArchiveModelManager.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Database/DownloadableArchiveModelManager.cs b/osu.Game/Database/DownloadableArchiveModelManager.cs index 5f688c149d..71bf195a8d 100644 --- a/osu.Game/Database/DownloadableArchiveModelManager.cs +++ b/osu.Game/Database/DownloadableArchiveModelManager.cs @@ -92,8 +92,6 @@ namespace osu.Game.Database notification.CancelRequested += () => { request.Cancel(); - currentDownloads.Remove(request); - notification.State = ProgressNotificationState.Cancelled; return true; }; @@ -109,11 +107,11 @@ namespace osu.Game.Database { DownloadFailed?.Invoke(request); - if (error is OperationCanceledException) return; - - notification.State = ProgressNotificationState.Cancelled; - Logger.Error(error, $"{HumanisedModelName.Titleize()} download failed!"); currentDownloads.Remove(request); + notification.State = ProgressNotificationState.Cancelled; + + if (!(error is OperationCanceledException)) + Logger.Error(error, $"{HumanisedModelName.Titleize()} download failed!"); } } From f603dd82bc87a59c6704ce30a74927b3a8ec7739 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 26 Dec 2019 14:52:08 +0900 Subject: [PATCH 4751/5608] Fix difficulty adjust mod not correctly reading settings while leaderboard visible --- osu.Game/OsuGame.cs | 22 +++++++++++++++++++ .../Rulesets/Mods/IApplicableToDifficulty.cs | 11 ++++++++++ osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 6 ++--- osu.Game/Rulesets/Mods/ModEasy.cs | 2 ++ osu.Game/Rulesets/Mods/ModHardRock.cs | 2 ++ 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index c7c746bed3..84aba4af52 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -39,6 +39,7 @@ using osu.Game.Online.Chat; using osu.Game.Skinning; using osuTK.Graphics; using osu.Game.Overlays.Volume; +using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Screens.Select; using osu.Game.Utils; @@ -204,6 +205,7 @@ namespace osu.Game Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade); + SelectedMods.BindValueChanged(modsChanged); Beatmap.BindValueChanged(beatmapChanged, true); } @@ -403,9 +405,29 @@ namespace osu.Game oldBeatmap.Track.Completed -= currentTrackCompleted; } + updateModDefaults(); + nextBeatmap?.LoadBeatmapAsync(); } + private void modsChanged(ValueChangedEvent> mods) + { + updateModDefaults(); + } + + private void updateModDefaults() + { + BeatmapDifficulty baseDifficulty = Beatmap.Value.BeatmapInfo.BaseDifficulty; + + if (baseDifficulty != null && SelectedMods.Value.Any(m => m is IApplicableToDifficulty)) + { + var adjustedDifficulty = baseDifficulty.Clone(); + + foreach (var mod in SelectedMods.Value.OfType()) + mod.ReadFromDifficulty(adjustedDifficulty); + } + } + private void currentTrackCompleted() => Schedule(() => { if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled) diff --git a/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs b/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs index 4d4cd75434..d1d85f5aca 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs @@ -10,6 +10,17 @@ namespace osu.Game.Rulesets.Mods /// public interface IApplicableToDifficulty : IApplicableMod { + /// + /// Called when a beatmap is changed. Can be used to read default values. + /// Any changes made will not be preserved. + /// + /// + void ReadFromDifficulty(BeatmapDifficulty difficulty); + + /// + /// Called post beatmap conversion. Can be used to apply changes to difficulty attributes. + /// + /// void ApplyToDifficulty(BeatmapDifficulty difficulty); } } diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs index 224fc78508..7b8d4bb3df 100644 --- a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -47,17 +47,17 @@ namespace osu.Game.Rulesets.Mods private BeatmapDifficulty difficulty; - public void ApplyToDifficulty(BeatmapDifficulty difficulty) + public void ReadFromDifficulty(BeatmapDifficulty difficulty) { if (this.difficulty == null || this.difficulty.ID != difficulty.ID) { this.difficulty = difficulty; TransferSettings(difficulty); } - else - ApplySettings(difficulty); } + public void ApplyToDifficulty(BeatmapDifficulty difficulty) => ApplySettings(difficulty); + /// /// Transfer initial settings from the beatmap to settings. /// diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index a91e4dfd5c..a8058961ee 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -33,6 +33,8 @@ namespace osu.Game.Rulesets.Mods private BindableNumber health; + public void ReadFromDifficulty(BeatmapDifficulty difficulty) { } + public void ApplyToDifficulty(BeatmapDifficulty difficulty) { const float ratio = 0.5f; diff --git a/osu.Game/Rulesets/Mods/ModHardRock.cs b/osu.Game/Rulesets/Mods/ModHardRock.cs index 2bcac3e4a9..a613d41cf4 100644 --- a/osu.Game/Rulesets/Mods/ModHardRock.cs +++ b/osu.Game/Rulesets/Mods/ModHardRock.cs @@ -17,6 +17,8 @@ namespace osu.Game.Rulesets.Mods public override string Description => "Everything just got a bit harder..."; public override Type[] IncompatibleMods => new[] { typeof(ModEasy), typeof(ModDifficultyAdjust) }; + public void ReadFromDifficulty(BeatmapDifficulty difficulty) { } + public void ApplyToDifficulty(BeatmapDifficulty difficulty) { const float ratio = 1.4f; From 90cb9d9162cc11909a230b0b4fa9c058235a4e73 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 24 Dec 2019 17:01:17 +0900 Subject: [PATCH 4752/5608] Simplify scoreprocesor/healthprocessor implementations --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 4 +- .../Scoring/CatchHealthProcessor.cs | 27 --------- .../Scoring/CatchScoreProcessor.cs | 6 -- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 4 +- .../Scoring/ManiaHealthProcessor.cs | 58 ------------------- .../Scoring/ManiaScoreProcessor.cs | 6 -- osu.Game.Rulesets.Osu/OsuRuleset.cs | 4 +- .../Scoring/OsuHealthProcessor.cs | 39 ------------- .../Scoring/OsuScoreProcessor.cs | 6 -- .../Scoring/TaikoHealthProcessor.cs | 36 ------------ .../Scoring/TaikoScoreProcessor.cs | 6 -- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 4 +- osu.Game/Rulesets/Ruleset.cs | 8 +-- osu.Game/Rulesets/Scoring/HealthProcessor.cs | 6 -- .../Rulesets/Scoring/JudgementProcessor.cs | 16 ++--- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 21 +++---- osu.Game/Screens/Play/Player.cs | 6 +- 17 files changed, 29 insertions(+), 228 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index f0e50c5ba5..b86fa09484 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -28,9 +28,9 @@ namespace osu.Game.Rulesets.Catch { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableCatchRuleset(this, beatmap, mods); - public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new CatchScoreProcessor(beatmap); + public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(); - public override HealthProcessor CreateHealthProcessor(IBeatmap beatmap) => new CatchHealthProcessor(beatmap); + public override HealthProcessor CreateHealthProcessor() => new CatchHealthProcessor(); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap, this); diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs index 49ba0f6122..77a6c665bd 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs @@ -1,38 +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.Beatmaps; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Scoring { public class CatchHealthProcessor : HealthProcessor { - public CatchHealthProcessor(IBeatmap beatmap) - : base(beatmap) - { - } - - private float hpDrainRate; - - protected override void ApplyBeatmap(IBeatmap beatmap) - { - base.ApplyBeatmap(beatmap); - - hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate; - } - - protected override double HealthAdjustmentFactorFor(JudgementResult result) - { - switch (result.Type) - { - case HitResult.Miss: - return hpDrainRate; - - default: - return 10.2 - hpDrainRate; // Award less HP as drain rate is increased - } - } } } diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index ad7520d57d..4c7bc4ab73 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -1,18 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Scoring { public class CatchScoreProcessor : ScoreProcessor { - public CatchScoreProcessor(IBeatmap beatmap) - : base(beatmap) - { - } - public override HitWindows CreateHitWindows() => new CatchHitWindows(); } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 5bca8588b6..4cc439f909 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -35,9 +35,9 @@ namespace osu.Game.Rulesets.Mania { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableManiaRuleset(this, beatmap, mods); - public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new ManiaScoreProcessor(beatmap); + public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(); - public override HealthProcessor CreateHealthProcessor(IBeatmap beatmap) => new ManiaHealthProcessor(beatmap); + public override HealthProcessor CreateHealthProcessor() => new ManiaHealthProcessor(); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap, this); diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs index c362c906a4..391fe0ace7 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs @@ -1,69 +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.Beatmaps; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Scoring { public class ManiaHealthProcessor : HealthProcessor { - /// - /// The hit HP multiplier at OD = 0. - /// - private const double hp_multiplier_min = 0.75; - - /// - /// The hit HP multiplier at OD = 0. - /// - private const double hp_multiplier_mid = 0.85; - - /// - /// The hit HP multiplier at OD = 0. - /// - private const double hp_multiplier_max = 1; - - /// - /// The MISS HP multiplier at OD = 0. - /// - private const double hp_multiplier_miss_min = 0.5; - - /// - /// The MISS HP multiplier at OD = 5. - /// - private const double hp_multiplier_miss_mid = 0.75; - - /// - /// The MISS HP multiplier at OD = 10. - /// - private const double hp_multiplier_miss_max = 1; - - /// - /// The MISS HP multiplier. This is multiplied to the miss hp increase. - /// - private double hpMissMultiplier = 1; - - /// - /// The HIT HP multiplier. This is multiplied to hit hp increases. - /// - private double hpMultiplier = 1; - - public ManiaHealthProcessor(IBeatmap beatmap) - : base(beatmap) - { - } - - protected override void ApplyBeatmap(IBeatmap beatmap) - { - base.ApplyBeatmap(beatmap); - - BeatmapDifficulty difficulty = beatmap.BeatmapInfo.BaseDifficulty; - hpMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_min, hp_multiplier_mid, hp_multiplier_max); - hpMissMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_miss_min, hp_multiplier_miss_mid, hp_multiplier_miss_max); - } - - protected override double HealthAdjustmentFactorFor(JudgementResult result) - => result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier; } } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 97f1ea721c..9b54b48de3 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -1,18 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Scoring { internal class ManiaScoreProcessor : ScoreProcessor { - public ManiaScoreProcessor(IBeatmap beatmap) - : base(beatmap) - { - } - public override HitWindows CreateHitWindows() => new ManiaHitWindows(); } } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index c8a156dc57..f7b4f90209 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -36,7 +36,9 @@ namespace osu.Game.Rulesets.Osu { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableOsuRuleset(this, beatmap, mods); - public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new OsuScoreProcessor(beatmap); + public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(); + + public override HealthProcessor CreateHealthProcessor() => new OsuHealthProcessor(); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap, this); diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs index 36ccc80af6..d6d83425ff 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; @@ -11,44 +10,6 @@ namespace osu.Game.Rulesets.Osu.Scoring { public class OsuHealthProcessor : HealthProcessor { - public OsuHealthProcessor(IBeatmap beatmap) - : base(beatmap) - { - } - - private float hpDrainRate; - - protected override void ApplyBeatmap(IBeatmap beatmap) - { - base.ApplyBeatmap(beatmap); - - hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate; - } - - protected override double HealthAdjustmentFactorFor(JudgementResult result) - { - switch (result.Type) - { - case HitResult.Great: - return 10.2 - hpDrainRate; - - case HitResult.Good: - return 8 - hpDrainRate; - - case HitResult.Meh: - return 4 - hpDrainRate; - - // case HitResult.SliderTick: - // return Math.Max(7 - hpDrainRate, 0) * 0.01; - - case HitResult.Miss: - return hpDrainRate; - - default: - return 0; - } - } - protected override JudgementResult CreateResult(HitObject hitObject, Judgement judgement) => new OsuJudgementResult(hitObject, judgement); } } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 4593364e42..1de7d488f3 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; @@ -11,11 +10,6 @@ namespace osu.Game.Rulesets.Osu.Scoring { internal class OsuScoreProcessor : ScoreProcessor { - public OsuScoreProcessor(IBeatmap beatmap) - : base(beatmap) - { - } - protected override JudgementResult CreateResult(HitObject hitObject, Judgement judgement) => new OsuJudgementResult(hitObject, judgement); public override HitWindows CreateHitWindows() => new OsuHitWindows(); diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs index c8aa32a678..df5dd19de3 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs @@ -1,53 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Scoring { public class TaikoHealthProcessor : HealthProcessor { - /// - /// A value used for calculating . - /// - private const double object_count_factor = 3; - /// /// Taiko fails at the end of the map if the player has not half-filled their HP bar. /// protected override bool DefaultFailCondition => JudgedHits == MaxHits && Health.Value <= 0.5; - /// - /// HP multiplier for a successful . - /// - private double hpMultiplier; - - /// - /// HP multiplier for a . - /// - private double hpMissMultiplier; - - public TaikoHealthProcessor(IBeatmap beatmap) - : base(beatmap) - { - } - - protected override void ApplyBeatmap(IBeatmap beatmap) - { - base.ApplyBeatmap(beatmap); - - hpMultiplier = 1 / (object_count_factor * beatmap.HitObjects.OfType().Count() * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98)); - - hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120); - } - - protected override double HealthAdjustmentFactorFor(JudgementResult result) - => result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier; - protected override void Reset(bool storeResults) { base.Reset(storeResults); diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 10011d2669..003d40af56 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -1,18 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Scoring { internal class TaikoScoreProcessor : ScoreProcessor { - public TaikoScoreProcessor(IBeatmap beatmap) - : base(beatmap) - { - } - public override HitWindows CreateHitWindows() => new TaikoHitWindows(); } } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index c5c2027af1..6763a1d340 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -28,9 +28,9 @@ namespace osu.Game.Rulesets.Taiko { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawableTaikoRuleset(this, beatmap, mods); - public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new TaikoScoreProcessor(beatmap); + public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(); - public override HealthProcessor CreateHealthProcessor(IBeatmap beatmap) => new TaikoHealthProcessor(beatmap); + public override HealthProcessor CreateHealthProcessor() => new TaikoHealthProcessor(); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap, this); diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index bfd6a16729..72973cc677 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -71,16 +71,16 @@ namespace osu.Game.Rulesets public abstract DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null); /// - /// Creates a for a beatmap converted to this ruleset. + /// Creates a for this . /// /// The score processor. - public virtual ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new ScoreProcessor(beatmap); + public virtual ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(); /// - /// Creates a for a beatmap converted to this ruleset. + /// Creates a for this . /// /// The health processor. - public virtual HealthProcessor CreateHealthProcessor(IBeatmap beatmap) => new HealthProcessor(beatmap); + public virtual HealthProcessor CreateHealthProcessor() => new HealthProcessor(); /// /// Creates a to convert a to one that is applicable for this . diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index d05e2d7b6b..f027cac8bd 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -4,7 +4,6 @@ using System; using osu.Framework.Bindables; using osu.Framework.MathUtils; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; namespace osu.Game.Rulesets.Scoring @@ -32,11 +31,6 @@ namespace osu.Game.Rulesets.Scoring /// public bool HasFailed { get; private set; } - public HealthProcessor(IBeatmap beatmap) - : base(beatmap) - { - } - protected override void ApplyResultInternal(JudgementResult result) { result.HealthAtJudgement = Health.Value; diff --git a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs index c7ac466eb0..54debebde9 100644 --- a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs +++ b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs @@ -36,23 +36,17 @@ namespace osu.Game.Rulesets.Scoring /// public bool HasCompleted => JudgedHits == MaxHits; - protected JudgementProcessor(IBeatmap beatmap) + /// + /// Applies a to this . + /// + /// The to read properties from. + public void ApplyBeatmap(IBeatmap beatmap) { - ApplyBeatmap(beatmap); - Reset(false); SimulateAutoplay(beatmap); Reset(true); } - /// - /// Applies any properties of the which affect scoring to this . - /// - /// The to read properties from. - protected virtual void ApplyBeatmap(IBeatmap beatmap) - { - } - /// /// Applies the score change of a to this . /// diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index acd394d955..8ccc2af93b 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -7,7 +7,6 @@ using System.Diagnostics; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Extensions; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; @@ -64,15 +63,9 @@ namespace osu.Game.Rulesets.Scoring private double scoreMultiplier = 1; - public ScoreProcessor(IBeatmap beatmap) - : base(beatmap) + public ScoreProcessor() { Debug.Assert(base_portion + combo_portion == 1.0); - } - - protected override void ApplyBeatmap(IBeatmap beatmap) - { - base.ApplyBeatmap(beatmap); Combo.ValueChanged += combo => HighestCombo.Value = Math.Max(HighestCombo.Value, combo.NewValue); Accuracy.ValueChanged += accuracy => @@ -82,12 +75,6 @@ namespace osu.Game.Rulesets.Scoring Rank.Value = mod.AdjustRank(Rank.Value, accuracy.NewValue); }; - if (maxBaseScore == 0 || maxHighestCombo == 0) - { - Mode.Value = ScoringMode.Classic; - Mode.Disabled = true; - } - Mode.ValueChanged += _ => updateScore(); Mods.ValueChanged += mods => { @@ -225,6 +212,12 @@ namespace osu.Game.Rulesets.Scoring { maxHighestCombo = HighestCombo.Value; maxBaseScore = baseScore; + + if (maxBaseScore == 0 || maxHighestCombo == 0) + { + Mode.Value = ScoringMode.Classic; + Mode.Disabled = true; + } } baseScore = 0; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index f57bfb0bde..3699763e14 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -131,10 +131,12 @@ namespace osu.Game.Screens.Play DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value); - ScoreProcessor = ruleset.CreateScoreProcessor(playableBeatmap); + ScoreProcessor = ruleset.CreateScoreProcessor(); + ScoreProcessor.ApplyBeatmap(playableBeatmap); ScoreProcessor.Mods.BindTo(Mods); - HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap); + HealthProcessor = ruleset.CreateHealthProcessor(); + HealthProcessor.ApplyBeatmap(playableBeatmap); if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); From 985277da797e4985d4291f86aa4af2aa5c5b34fc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 24 Dec 2019 17:12:58 +0900 Subject: [PATCH 4753/5608] Add time elapsation to judgement simulation --- osu.Game/Rulesets/Scoring/JudgementProcessor.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs index 54debebde9..b0bc205ea9 100644 --- a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs +++ b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs @@ -47,6 +47,10 @@ namespace osu.Game.Rulesets.Scoring Reset(true); } + public virtual void ApplyElapsedTime(double elapsedTime) + { + } + /// /// Applies the score change of a to this . /// @@ -115,6 +119,8 @@ namespace osu.Game.Rulesets.Scoring /// The to simulate. protected virtual void SimulateAutoplay(IBeatmap beatmap) { + HitObject lastObject = null; + foreach (var obj in beatmap.HitObjects) simulate(obj); @@ -123,6 +129,9 @@ namespace osu.Game.Rulesets.Scoring foreach (var nested in obj.NestedHitObjects) simulate(nested); + if (lastObject != null) + ApplyElapsedTime(lastObject.GetEndTime() - obj.StartTime); + var judgement = obj.CreateJudgement(); if (judgement == null) return; @@ -132,8 +141,9 @@ namespace osu.Game.Rulesets.Scoring throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); result.Type = judgement.MaxResult; - ApplyResult(result); + + lastObject = obj; } } } From a4b1c79e18bb9656e3c1392b42de2431e15827d6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 13:09:04 +0900 Subject: [PATCH 4754/5608] Initial implementation of HP drain --- osu.Game/Rulesets/Scoring/HealthProcessor.cs | 48 +++++++++++++++++++- osu.Game/Screens/Play/Player.cs | 8 ++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index f027cac8bd..270128b60e 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -2,9 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using osu.Framework.Bindables; using osu.Framework.MathUtils; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Scoring { @@ -31,15 +33,23 @@ namespace osu.Game.Rulesets.Scoring /// public bool HasFailed { get; private set; } + private readonly List<(double time, double health)> healthIncreases = new List<(double time, double health)>(); + private double drainRate = 1; + + public override void ApplyElapsedTime(double elapsedTime) => Health.Value -= drainRate * elapsedTime; + protected override void ApplyResultInternal(JudgementResult result) { result.HealthAtJudgement = Health.Value; result.FailedAtJudgement = HasFailed; + double healthIncrease = HealthAdjustmentFactorFor(result) * result.Judgement.HealthIncreaseFor(result); + healthIncreases.Add((result.HitObject.GetEndTime() + result.TimeOffset, healthIncrease)); + if (HasFailed) return; - Health.Value += HealthAdjustmentFactorFor(result) * result.Judgement.HealthIncreaseFor(result); + Health.Value += healthIncrease; if (!DefaultFailCondition && FailConditions?.Invoke(this, result) != true) return; @@ -71,6 +81,42 @@ namespace osu.Game.Rulesets.Scoring { base.Reset(storeResults); + drainRate = 1; + + if (storeResults) + { + const double percentage_target = 0.5; + + int count = 1; + + while (true) + { + double currentHealth = 1; + double lowestHealth = 1; + + for (int i = 0; i < healthIncreases.Count; i++) + { + var lastTime = i > 0 ? healthIncreases[i - 1].time : 0; + + currentHealth -= (healthIncreases[i].time - lastTime) * drainRate; + lowestHealth = Math.Min(lowestHealth, currentHealth); + currentHealth = Math.Min(1, currentHealth + healthIncreases[i].health); + + // Common scenario for when the drain rate is definitely too harsh + if (lowestHealth < 0) + break; + } + + if (Math.Abs(lowestHealth - percentage_target) <= 0.01) + break; + + count *= 2; + drainRate += 1.0 / count * Math.Sign(lowestHealth - percentage_target); + } + } + + healthIncreases.Clear(); + Health.Value = 1; HasFailed = false; } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 3699763e14..bc6510440a 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -342,6 +342,14 @@ namespace osu.Game.Screens.Play this.Exit(); } + protected override void Update() + { + base.Update(); + + if (!GameplayClockContainer.IsPaused.Value) + HealthProcessor.ApplyElapsedTime(GameplayClockContainer.GameplayClock.ElapsedFrameTime); + } + /// /// Restart gameplay via a parent . /// This can be called from a child screen in order to trigger the restart process. From 70d2d8a2fabdea21d4328077fa8a827552cd8f3a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 13:32:58 +0900 Subject: [PATCH 4755/5608] Add adjustable target percentage --- osu.Game/Rulesets/Scoring/HealthProcessor.cs | 14 ++++++++++---- osu.Game/Rulesets/Scoring/JudgementProcessor.cs | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index 270128b60e..bb8f377f84 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using osu.Framework.Bindables; using osu.Framework.MathUtils; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; @@ -34,8 +35,15 @@ namespace osu.Game.Rulesets.Scoring public bool HasFailed { get; private set; } private readonly List<(double time, double health)> healthIncreases = new List<(double time, double health)>(); + private double targetMinimumHealth; private double drainRate = 1; + public override void ApplyBeatmap(IBeatmap beatmap) + { + targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.95, 0.85, 0.65); + base.ApplyBeatmap(beatmap); + } + public override void ApplyElapsedTime(double elapsedTime) => Health.Value -= drainRate * elapsedTime; protected override void ApplyResultInternal(JudgementResult result) @@ -85,8 +93,6 @@ namespace osu.Game.Rulesets.Scoring if (storeResults) { - const double percentage_target = 0.5; - int count = 1; while (true) @@ -107,11 +113,11 @@ namespace osu.Game.Rulesets.Scoring break; } - if (Math.Abs(lowestHealth - percentage_target) <= 0.01) + if (Math.Abs(lowestHealth - targetMinimumHealth) <= 0.01) break; count *= 2; - drainRate += 1.0 / count * Math.Sign(lowestHealth - percentage_target); + drainRate += 1.0 / count * Math.Sign(lowestHealth - targetMinimumHealth); } } diff --git a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs index b0bc205ea9..33dc4b9a22 100644 --- a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs +++ b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Scoring /// Applies a to this . /// /// The to read properties from. - public void ApplyBeatmap(IBeatmap beatmap) + public virtual void ApplyBeatmap(IBeatmap beatmap) { Reset(false); SimulateAutoplay(beatmap); From bd74d086fb412e32cb9249e41287c47dbb037f5c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 13:33:50 +0900 Subject: [PATCH 4756/5608] Remove adjustment factor --- osu.Game/Rulesets/Scoring/HealthProcessor.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index bb8f377f84..8c2e2b66ca 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Scoring result.HealthAtJudgement = Health.Value; result.FailedAtJudgement = HasFailed; - double healthIncrease = HealthAdjustmentFactorFor(result) * result.Judgement.HealthIncreaseFor(result); + double healthIncrease = result.Judgement.HealthIncreaseFor(result); healthIncreases.Add((result.HitObject.GetEndTime() + result.TimeOffset, healthIncrease)); if (HasFailed) @@ -73,13 +73,6 @@ namespace osu.Game.Rulesets.Scoring // Todo: Revert HasFailed state with proper player support } - /// - /// An adjustment factor which is multiplied into the health increase provided by a . - /// - /// The for which the adjustment should apply. - /// The adjustment factor. - protected virtual double HealthAdjustmentFactorFor(JudgementResult result) => 1; - /// /// The default conditions for failing. /// From 85c44b5a5a015217931c16651f5389ab47d52fab Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 13:34:13 +0900 Subject: [PATCH 4757/5608] Disable list additions during gameplay --- osu.Game/Rulesets/Scoring/HealthProcessor.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index 8c2e2b66ca..2cb51fa853 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -34,14 +34,19 @@ namespace osu.Game.Rulesets.Scoring /// public bool HasFailed { get; private set; } - private readonly List<(double time, double health)> healthIncreases = new List<(double time, double health)>(); + private List<(double time, double health)> healthIncreases; private double targetMinimumHealth; private double drainRate = 1; public override void ApplyBeatmap(IBeatmap beatmap) { + healthIncreases = new List<(double time, double health)>(); targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.95, 0.85, 0.65); + base.ApplyBeatmap(beatmap); + + // Only required during the simulation stage + healthIncreases = null; } public override void ApplyElapsedTime(double elapsedTime) => Health.Value -= drainRate * elapsedTime; @@ -52,7 +57,7 @@ namespace osu.Game.Rulesets.Scoring result.FailedAtJudgement = HasFailed; double healthIncrease = result.Judgement.HealthIncreaseFor(result); - healthIncreases.Add((result.HitObject.GetEndTime() + result.TimeOffset, healthIncrease)); + healthIncreases?.Add((result.HitObject.GetEndTime() + result.TimeOffset, healthIncrease)); if (HasFailed) return; From 977fb3d1bfe862f9fc38b37b110894a12d0379bd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 14:35:32 +0900 Subject: [PATCH 4758/5608] Make processors and break overlay frame-stable --- osu.Game/Rulesets/Scoring/HealthProcessor.cs | 7 +++++- .../Rulesets/Scoring/JudgementProcessor.cs | 14 ++--------- osu.Game/Rulesets/UI/DrawableRuleset.cs | 25 ++++++++++++------- osu.Game/Screens/Play/Player.cs | 24 ++++++++---------- 4 files changed, 34 insertions(+), 36 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index 2cb51fa853..b9638fed15 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -49,7 +49,12 @@ namespace osu.Game.Rulesets.Scoring healthIncreases = null; } - public override void ApplyElapsedTime(double elapsedTime) => Health.Value -= drainRate * elapsedTime; + protected override void Update() + { + base.Update(); + + Health.Value -= drainRate * Time.Elapsed; + } protected override void ApplyResultInternal(JudgementResult result) { diff --git a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs index 33dc4b9a22..3016007f98 100644 --- a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs +++ b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs @@ -3,13 +3,14 @@ using System; using osu.Framework.Extensions.TypeExtensions; +using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Scoring { - public abstract class JudgementProcessor + public abstract class JudgementProcessor : Component { /// /// Invoked when all s have been judged by this . @@ -47,10 +48,6 @@ namespace osu.Game.Rulesets.Scoring Reset(true); } - public virtual void ApplyElapsedTime(double elapsedTime) - { - } - /// /// Applies the score change of a to this . /// @@ -119,8 +116,6 @@ namespace osu.Game.Rulesets.Scoring /// The to simulate. protected virtual void SimulateAutoplay(IBeatmap beatmap) { - HitObject lastObject = null; - foreach (var obj in beatmap.HitObjects) simulate(obj); @@ -129,9 +124,6 @@ namespace osu.Game.Rulesets.Scoring foreach (var nested in obj.NestedHitObjects) simulate(nested); - if (lastObject != null) - ApplyElapsedTime(lastObject.GetEndTime() - obj.StartTime); - var judgement = obj.CreateJudgement(); if (judgement == null) return; @@ -142,8 +134,6 @@ namespace osu.Game.Rulesets.Scoring result.Type = judgement.MaxResult; ApplyResult(result); - - lastObject = obj; } } } diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index f318539bb7..e624fb80fa 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -72,10 +72,9 @@ namespace osu.Game.Rulesets.UI /// public override Playfield Playfield => playfield.Value; - /// - /// Place to put drawables above hit objects but below UI. - /// - public Container Overlays { get; private set; } + private Container overlays; + + public override Container Overlays => overlays; public override GameplayClock FrameStableClock => frameStabilityContainer.GameplayClock; @@ -185,12 +184,15 @@ namespace osu.Game.Rulesets.UI frameStabilityContainer = new FrameStabilityContainer(GameplayStartTime) { FrameStablePlayback = FrameStablePlayback, - Child = KeyBindingInputManager - .WithChild(CreatePlayfieldAdjustmentContainer() - .WithChild(Playfield) - ) + Children = new Drawable[] + { + KeyBindingInputManager + .WithChild(CreatePlayfieldAdjustmentContainer() + .WithChild(Playfield) + ), + overlays = new Container { RelativeSizeAxes = Axes.Both } + } }, - Overlays = new Container { RelativeSizeAxes = Axes.Both } }; if ((ResumeOverlay = CreateResumeOverlay()) != null) @@ -385,6 +387,11 @@ namespace osu.Game.Rulesets.UI /// public abstract Playfield Playfield { get; } + /// + /// Place to put drawables above hit objects but below UI. + /// + public abstract Container Overlays { get; } + /// /// The frame-stable clock which is being used for playfield display. /// diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index bc6510440a..620a9195f7 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -208,12 +208,6 @@ namespace osu.Game.Screens.Play { target.AddRange(new[] { - BreakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, DrawableRuleset.GameplayStartTime, ScoreProcessor) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Breaks = working.Beatmap.Breaks - }, // display the cursor above some HUD elements. DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), DrawableRuleset.ResumeOverlay?.CreateProxy() ?? new Container(), @@ -268,6 +262,16 @@ namespace osu.Game.Screens.Play }, failAnimation = new FailAnimation(DrawableRuleset) { OnComplete = onFailComplete, } }); + + DrawableRuleset.Overlays.Add(BreakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, DrawableRuleset.GameplayStartTime, ScoreProcessor) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Breaks = working.Beatmap.Breaks + }); + + DrawableRuleset.Overlays.Add(ScoreProcessor); + DrawableRuleset.Overlays.Add(HealthProcessor); } private void updatePauseOnFocusLostState() => @@ -342,14 +346,6 @@ namespace osu.Game.Screens.Play this.Exit(); } - protected override void Update() - { - base.Update(); - - if (!GameplayClockContainer.IsPaused.Value) - HealthProcessor.ApplyElapsedTime(GameplayClockContainer.GameplayClock.ElapsedFrameTime); - } - /// /// Restart gameplay via a parent . /// This can be called from a child screen in order to trigger the restart process. From b348abcd0779fe203e9c10dc91018ca7d54d1fc6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 14:49:17 +0900 Subject: [PATCH 4759/5608] Only drain health in non-break times --- osu.Game/Rulesets/Scoring/HealthProcessor.cs | 8 +++++++- osu.Game/Screens/Play/Player.cs | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index b9638fed15..af81f3b8b5 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -29,6 +29,11 @@ namespace osu.Game.Rulesets.Scoring /// public readonly BindableDouble Health = new BindableDouble(1) { MinValue = 0, MaxValue = 1 }; + /// + /// Whether gameplay is currently in a break. + /// + public readonly IBindable IsBreakTime = new Bindable(); + /// /// Whether this ScoreProcessor has already triggered the failed state. /// @@ -53,7 +58,8 @@ namespace osu.Game.Rulesets.Scoring { base.Update(); - Health.Value -= drainRate * Time.Elapsed; + if (!IsBreakTime.Value) + Health.Value -= drainRate * Time.Elapsed; } protected override void ApplyResultInternal(JudgementResult result) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 620a9195f7..dc0dd86c51 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -272,6 +272,8 @@ namespace osu.Game.Screens.Play DrawableRuleset.Overlays.Add(ScoreProcessor); DrawableRuleset.Overlays.Add(HealthProcessor); + + HealthProcessor.IsBreakTime.BindTo(BreakOverlay.IsBreakTime); } private void updatePauseOnFocusLostState() => From 522847987bd4c16b6d24b83955c02a9e3455c0fb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 15:33:13 +0900 Subject: [PATCH 4760/5608] Implement break/gameplay start times --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 -- .../Scoring/CatchHealthProcessor.cs | 11 -------- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 -- .../Scoring/ManiaHealthProcessor.cs | 11 -------- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 -- .../Scoring/OsuHealthProcessor.cs | 15 ---------- .../Scoring/TaikoHealthProcessor.cs | 22 --------------- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 -- osu.Game/Rulesets/Ruleset.cs | 2 +- osu.Game/Rulesets/Scoring/HealthProcessor.cs | 28 +++++++++++++++++-- osu.Game/Screens/Play/Player.cs | 2 +- 11 files changed, 28 insertions(+), 71 deletions(-) delete mode 100644 osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs delete mode 100644 osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs delete mode 100644 osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs delete mode 100644 osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index b86fa09484..dc8df28e6a 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -30,8 +30,6 @@ namespace osu.Game.Rulesets.Catch public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(); - public override HealthProcessor CreateHealthProcessor() => new CatchHealthProcessor(); - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap, this); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs deleted file mode 100644 index 77a6c665bd..0000000000 --- a/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Rulesets.Catch.Scoring -{ - public class CatchHealthProcessor : HealthProcessor - { - } -} diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 4cc439f909..c693aa05de 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -37,8 +37,6 @@ namespace osu.Game.Rulesets.Mania public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(); - public override HealthProcessor CreateHealthProcessor() => new ManiaHealthProcessor(); - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap, this); diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs deleted file mode 100644 index 391fe0ace7..0000000000 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Rulesets.Mania.Scoring -{ - public class ManiaHealthProcessor : HealthProcessor - { - } -} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index f7b4f90209..36346eb78a 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -38,8 +38,6 @@ namespace osu.Game.Rulesets.Osu public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(); - public override HealthProcessor CreateHealthProcessor() => new OsuHealthProcessor(); - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap, this); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs deleted file mode 100644 index d6d83425ff..0000000000 --- a/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Osu.Judgements; -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Rulesets.Osu.Scoring -{ - public class OsuHealthProcessor : HealthProcessor - { - protected override JudgementResult CreateResult(HitObject hitObject, Judgement judgement) => new OsuJudgementResult(hitObject, judgement); - } -} diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs deleted file mode 100644 index df5dd19de3..0000000000 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Rulesets.Taiko.Scoring -{ - public class TaikoHealthProcessor : HealthProcessor - { - /// - /// Taiko fails at the end of the map if the player has not half-filled their HP bar. - /// - protected override bool DefaultFailCondition => JudgedHits == MaxHits && Health.Value <= 0.5; - - protected override void Reset(bool storeResults) - { - base.Reset(storeResults); - - Health.Value = 0; - } - } -} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 6763a1d340..79de2d0334 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -30,8 +30,6 @@ namespace osu.Game.Rulesets.Taiko public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(); - public override HealthProcessor CreateHealthProcessor() => new TaikoHealthProcessor(); - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap, this); diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 72973cc677..6310b19cd3 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets /// Creates a for this . /// /// The health processor. - public virtual HealthProcessor CreateHealthProcessor() => new HealthProcessor(); + public virtual HealthProcessor CreateHealthProcessor(double gameplayStartTime) => new HealthProcessor(gameplayStartTime); /// /// Creates a to convert a to one that is applicable for this . diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index af81f3b8b5..772e317955 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -39,14 +39,25 @@ namespace osu.Game.Rulesets.Scoring /// public bool HasFailed { get; private set; } + private readonly double gameplayStartTime; + + private IBeatmap beatmap; + private List<(double time, double health)> healthIncreases; private double targetMinimumHealth; private double drainRate = 1; + public HealthProcessor(double gameplayStartTime) + { + this.gameplayStartTime = gameplayStartTime; + } + public override void ApplyBeatmap(IBeatmap beatmap) { + this.beatmap = beatmap; + healthIncreases = new List<(double time, double health)>(); - targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.95, 0.85, 0.65); + targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.95, 0.6, 0.2); base.ApplyBeatmap(beatmap); @@ -108,11 +119,24 @@ namespace osu.Game.Rulesets.Scoring { double currentHealth = 1; double lowestHealth = 1; + int currentBreak = -1; for (int i = 0; i < healthIncreases.Count; i++) { - var lastTime = i > 0 ? healthIncreases[i - 1].time : 0; + double currentTime = healthIncreases[i].time; + double lastTime = i > 0 ? healthIncreases[i - 1].time : gameplayStartTime; + // Subtract any break time from the duration since the last object + if (beatmap.Breaks.Count > 0) + { + while (currentBreak + 1 < beatmap.Breaks.Count && beatmap.Breaks[currentBreak + 1].EndTime < currentTime) + currentBreak++; + + if (currentBreak >= 0) + lastTime = Math.Max(lastTime, beatmap.Breaks[currentBreak].EndTime); + } + + // Apply health adjustments currentHealth -= (healthIncreases[i].time - lastTime) * drainRate; lowestHealth = Math.Min(lowestHealth, currentHealth); currentHealth = Math.Min(1, currentHealth + healthIncreases[i].health); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index dc0dd86c51..c56fbaf847 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -135,7 +135,7 @@ namespace osu.Game.Screens.Play ScoreProcessor.ApplyBeatmap(playableBeatmap); ScoreProcessor.Mods.BindTo(Mods); - HealthProcessor = ruleset.CreateHealthProcessor(); + HealthProcessor = ruleset.CreateHealthProcessor(DrawableRuleset.GameplayStartTime); HealthProcessor.ApplyBeatmap(playableBeatmap); if (!ScoreProcessor.Mode.Disabled) From 90a0569660a593e53e27cc1853155a73df09bbf6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 19:19:57 +0900 Subject: [PATCH 4761/5608] Tweak drain values --- osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs | 13 +++++++++++-- osu.Game/Rulesets/Scoring/HealthProcessor.cs | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs index 7a5b98864c..845ff76ce6 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs @@ -8,6 +8,11 @@ namespace osu.Game.Rulesets.Osu.Judgements { public class OsuJudgement : Judgement { + /// + /// The health increase for a maximum judgement result. + /// + protected const double MAX_HEALTH_INCREASE = 0.05; + public override HitResult MaxResult => HitResult.Great; protected override int NumericResultFor(HitResult result) @@ -33,12 +38,16 @@ namespace osu.Game.Rulesets.Osu.Judgements switch (result) { case HitResult.Miss: - return -0.02; + return -MAX_HEALTH_INCREASE; case HitResult.Meh: + return -MAX_HEALTH_INCREASE * 0.05; + case HitResult.Good: + return MAX_HEALTH_INCREASE * 0.3; + case HitResult.Great: - return 0.01; + return MAX_HEALTH_INCREASE; default: return 0; diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index 772e317955..a1389d7ee9 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Scoring this.beatmap = beatmap; healthIncreases = new List<(double time, double health)>(); - targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.95, 0.6, 0.2); + targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.95, 0.70, 0.30); base.ApplyBeatmap(beatmap); From 0454c5022d997b22835f94f446f5ba9bcf345dfa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 19:39:59 +0900 Subject: [PATCH 4762/5608] Fix some maps potentially starting with 0 health --- osu.Game/Rulesets/Scoring/HealthProcessor.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index a1389d7ee9..8dd6cc1ed9 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -70,7 +70,11 @@ namespace osu.Game.Rulesets.Scoring base.Update(); if (!IsBreakTime.Value) - Health.Value -= drainRate * Time.Elapsed; + { + // When jumping from before the gameplay start to after it or vice-versa, we only want to consider any drain since the gameplay start time + double lastTime = Math.Max(gameplayStartTime, Time.Current - Time.Elapsed); + Health.Value -= drainRate * (Time.Current - lastTime); + } } protected override void ApplyResultInternal(JudgementResult result) From 3b07c3913dd9209be68f7f928cb704ac6c6ba168 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 19:58:23 +0900 Subject: [PATCH 4763/5608] Add perfect and ok values, move to base Judgement --- .../Judgements/OsuJudgement.cs | 26 --------------- osu.Game/Rulesets/Judgements/Judgement.cs | 33 ++++++++++++++++++- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs index 845ff76ce6..bf30fbc351 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs @@ -8,11 +8,6 @@ namespace osu.Game.Rulesets.Osu.Judgements { public class OsuJudgement : Judgement { - /// - /// The health increase for a maximum judgement result. - /// - protected const double MAX_HEALTH_INCREASE = 0.05; - public override HitResult MaxResult => HitResult.Great; protected override int NumericResultFor(HitResult result) @@ -32,26 +27,5 @@ namespace osu.Game.Rulesets.Osu.Judgements return 300; } } - - protected override double HealthIncreaseFor(HitResult result) - { - switch (result) - { - case HitResult.Miss: - return -MAX_HEALTH_INCREASE; - - case HitResult.Meh: - return -MAX_HEALTH_INCREASE * 0.05; - - case HitResult.Good: - return MAX_HEALTH_INCREASE * 0.3; - - case HitResult.Great: - return MAX_HEALTH_INCREASE; - - default: - return 0; - } - } } } diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index f07f76a2b8..599135ba54 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -11,6 +11,12 @@ namespace osu.Game.Rulesets.Judgements /// public class Judgement { + /// + /// The default health increase for a maximum judgement, as a proportion of total health. + /// By default, each maximum judgement restores 5% of total health. + /// + protected const double DEFAULT_MAX_HEALTH_INCREASE = 0.05; + /// /// The maximum that can be achieved. /// @@ -55,7 +61,32 @@ namespace osu.Game.Rulesets.Judgements /// /// The to find the numeric health increase for. /// The numeric health increase of . - protected virtual double HealthIncreaseFor(HitResult result) => 0; + protected virtual double HealthIncreaseFor(HitResult result) + { + switch (result) + { + case HitResult.Miss: + return -DEFAULT_MAX_HEALTH_INCREASE; + + case HitResult.Meh: + return -DEFAULT_MAX_HEALTH_INCREASE * 0.05; + + case HitResult.Ok: + return -DEFAULT_MAX_HEALTH_INCREASE * 0.01; + + case HitResult.Good: + return DEFAULT_MAX_HEALTH_INCREASE * 0.3; + + case HitResult.Great: + return DEFAULT_MAX_HEALTH_INCREASE; + + case HitResult.Perfect: + return DEFAULT_MAX_HEALTH_INCREASE * 1.05; + + default: + return 0; + } + } /// /// Retrieves the numeric health increase of a . From eba6371526095c2e39f850f734c33671a496866c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 21:16:40 +0900 Subject: [PATCH 4764/5608] Re-implement taiko's accumulating health processor --- .../Scoring/TaikoHealthProcessor.cs | 47 ++++++++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 + osu.Game/Rulesets/Ruleset.cs | 2 +- .../Scoring/AccumulatingHealthProcessor.cs | 20 ++++ .../Scoring/DrainingHealthProcessor.cs | 108 ++++++++++++++++++ osu.Game/Rulesets/Scoring/HealthProcessor.cs | 99 ++-------------- 6 files changed, 188 insertions(+), 90 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs create mode 100644 osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs create mode 100644 osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs new file mode 100644 index 0000000000..679addc32d --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs @@ -0,0 +1,47 @@ +// 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.Game.Beatmaps; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Objects; + +namespace osu.Game.Rulesets.Taiko.Scoring +{ + public class TaikoHealthProcessor : AccumulatingHealthProcessor + { + /// + /// A value used for calculating . + /// + private const double object_count_factor = 3; + + /// + /// HP multiplier for a successful . + /// + private double hpMultiplier; + + /// + /// HP multiplier for a . + /// + private double hpMissMultiplier; + + public TaikoHealthProcessor(double gameplayStartTime) + : base(gameplayStartTime) + { + } + + public override void ApplyBeatmap(IBeatmap beatmap) + { + base.ApplyBeatmap(beatmap); + + hpMultiplier = 1 / (object_count_factor * beatmap.HitObjects.OfType().Count() * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98)); + hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120); + } + + protected override double GetHealthIncreaseFor(JudgementResult result) + => base.GetHealthIncreaseFor(result) * (result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier); + + protected override bool DefaultFailCondition => JudgedHits == MaxHits && Health.Value <= 0.5; + } +} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 79de2d0334..de589f81b6 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -30,6 +30,8 @@ namespace osu.Game.Rulesets.Taiko public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(); + public override HealthProcessor CreateHealthProcessor(double gameplayStartTime) => new TaikoHealthProcessor(gameplayStartTime); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap, this); diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 6310b19cd3..ff58d3c8dc 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets /// Creates a for this . /// /// The health processor. - public virtual HealthProcessor CreateHealthProcessor(double gameplayStartTime) => new HealthProcessor(gameplayStartTime); + public virtual HealthProcessor CreateHealthProcessor(double gameplayStartTime) => new DrainingHealthProcessor(gameplayStartTime); /// /// Creates a to convert a to one that is applicable for this . diff --git a/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs new file mode 100644 index 0000000000..edc8d18804 --- /dev/null +++ b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Scoring +{ + public class AccumulatingHealthProcessor : HealthProcessor + { + public AccumulatingHealthProcessor(double gameplayStartTime) + : base(gameplayStartTime) + { + } + + protected override void Reset(bool storeResults) + { + base.Reset(storeResults); + + Health.Value = 0; + } + } +} diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs new file mode 100644 index 0000000000..8b30728caf --- /dev/null +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.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 System; +using System.Collections.Generic; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Scoring +{ + public class DrainingHealthProcessor : HealthProcessor + { + private IBeatmap beatmap; + + private List<(double time, double health)> healthIncreases; + private double targetMinimumHealth; + private double drainRate = 1; + + public DrainingHealthProcessor(double gameplayStartTime) + : base(gameplayStartTime) + { + } + + protected override void Update() + { + base.Update(); + + if (!IsBreakTime.Value) + { + // When jumping from before the gameplay start to after it or vice-versa, we only want to consider any drain since the gameplay start time + double lastTime = Math.Max(GameplayStartTime, Time.Current - Time.Elapsed); + Health.Value -= drainRate * (Time.Current - lastTime); + } + } + + public override void ApplyBeatmap(IBeatmap beatmap) + { + this.beatmap = beatmap; + + healthIncreases = new List<(double time, double health)>(); + targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.95, 0.70, 0.30); + + base.ApplyBeatmap(beatmap); + + // Only required during the simulation stage + healthIncreases = null; + } + + protected override void ApplyResultInternal(JudgementResult result) + { + base.ApplyResultInternal(result); + healthIncreases?.Add((result.HitObject.GetEndTime() + result.TimeOffset, GetHealthIncreaseFor(result))); + } + + protected override void Reset(bool storeResults) + { + base.Reset(storeResults); + + drainRate = 1; + + if (storeResults) + { + int count = 1; + + while (true) + { + double currentHealth = 1; + double lowestHealth = 1; + int currentBreak = -1; + + for (int i = 0; i < healthIncreases.Count; i++) + { + double currentTime = healthIncreases[i].time; + double lastTime = i > 0 ? healthIncreases[i - 1].time : GameplayStartTime; + + // Subtract any break time from the duration since the last object + if (beatmap.Breaks.Count > 0) + { + while (currentBreak + 1 < beatmap.Breaks.Count && beatmap.Breaks[currentBreak + 1].EndTime < currentTime) + currentBreak++; + + if (currentBreak >= 0) + lastTime = Math.Max(lastTime, beatmap.Breaks[currentBreak].EndTime); + } + + // Apply health adjustments + currentHealth -= (healthIncreases[i].time - lastTime) * drainRate; + lowestHealth = Math.Min(lowestHealth, currentHealth); + currentHealth = Math.Min(1, currentHealth + healthIncreases[i].health); + + // Common scenario for when the drain rate is definitely too harsh + if (lowestHealth < 0) + break; + } + + if (Math.Abs(lowestHealth - targetMinimumHealth) <= 0.01) + break; + + count *= 2; + drainRate += 1.0 / count * Math.Sign(lowestHealth - targetMinimumHealth); + } + } + + healthIncreases.Clear(); + } + } +} diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index 8dd6cc1ed9..597989701d 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -2,16 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using osu.Framework.Bindables; using osu.Framework.MathUtils; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Scoring { - public class HealthProcessor : JudgementProcessor + public abstract class HealthProcessor : JudgementProcessor { /// /// Invoked when the is in a failed state. @@ -39,42 +36,14 @@ namespace osu.Game.Rulesets.Scoring /// public bool HasFailed { get; private set; } - private readonly double gameplayStartTime; + /// + /// The gameplay start time. + /// + protected readonly double GameplayStartTime; - private IBeatmap beatmap; - - private List<(double time, double health)> healthIncreases; - private double targetMinimumHealth; - private double drainRate = 1; - - public HealthProcessor(double gameplayStartTime) + protected HealthProcessor(double gameplayStartTime) { - this.gameplayStartTime = gameplayStartTime; - } - - public override void ApplyBeatmap(IBeatmap beatmap) - { - this.beatmap = beatmap; - - healthIncreases = new List<(double time, double health)>(); - targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.95, 0.70, 0.30); - - base.ApplyBeatmap(beatmap); - - // Only required during the simulation stage - healthIncreases = null; - } - - protected override void Update() - { - base.Update(); - - if (!IsBreakTime.Value) - { - // When jumping from before the gameplay start to after it or vice-versa, we only want to consider any drain since the gameplay start time - double lastTime = Math.Max(gameplayStartTime, Time.Current - Time.Elapsed); - Health.Value -= drainRate * (Time.Current - lastTime); - } + GameplayStartTime = gameplayStartTime; } protected override void ApplyResultInternal(JudgementResult result) @@ -82,13 +51,10 @@ namespace osu.Game.Rulesets.Scoring result.HealthAtJudgement = Health.Value; result.FailedAtJudgement = HasFailed; - double healthIncrease = result.Judgement.HealthIncreaseFor(result); - healthIncreases?.Add((result.HitObject.GetEndTime() + result.TimeOffset, healthIncrease)); - if (HasFailed) return; - Health.Value += healthIncrease; + Health.Value += GetHealthIncreaseFor(result); if (!DefaultFailCondition && FailConditions?.Invoke(this, result) != true) return; @@ -104,6 +70,8 @@ namespace osu.Game.Rulesets.Scoring // Todo: Revert HasFailed state with proper player support } + protected virtual double GetHealthIncreaseFor(JudgementResult result) => result.Judgement.HealthIncreaseFor(result); + /// /// The default conditions for failing. /// @@ -113,53 +81,6 @@ namespace osu.Game.Rulesets.Scoring { base.Reset(storeResults); - drainRate = 1; - - if (storeResults) - { - int count = 1; - - while (true) - { - double currentHealth = 1; - double lowestHealth = 1; - int currentBreak = -1; - - for (int i = 0; i < healthIncreases.Count; i++) - { - double currentTime = healthIncreases[i].time; - double lastTime = i > 0 ? healthIncreases[i - 1].time : gameplayStartTime; - - // Subtract any break time from the duration since the last object - if (beatmap.Breaks.Count > 0) - { - while (currentBreak + 1 < beatmap.Breaks.Count && beatmap.Breaks[currentBreak + 1].EndTime < currentTime) - currentBreak++; - - if (currentBreak >= 0) - lastTime = Math.Max(lastTime, beatmap.Breaks[currentBreak].EndTime); - } - - // Apply health adjustments - currentHealth -= (healthIncreases[i].time - lastTime) * drainRate; - lowestHealth = Math.Min(lowestHealth, currentHealth); - currentHealth = Math.Min(1, currentHealth + healthIncreases[i].health); - - // Common scenario for when the drain rate is definitely too harsh - if (lowestHealth < 0) - break; - } - - if (Math.Abs(lowestHealth - targetMinimumHealth) <= 0.01) - break; - - count *= 2; - drainRate += 1.0 / count * Math.Sign(lowestHealth - targetMinimumHealth); - } - } - - healthIncreases.Clear(); - Health.Value = 1; HasFailed = false; } From e0c1072ab22cd78f002fca32c512236c6b786feb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 25 Dec 2019 21:22:46 +0900 Subject: [PATCH 4765/5608] Add xmldocs --- .../Scoring/TaikoHealthProcessor.cs | 3 +-- .../Scoring/AccumulatingHealthProcessor.cs | 16 +++++++++++++++- .../Rulesets/Scoring/DrainingHealthProcessor.cs | 7 +++++++ osu.Game/Rulesets/Scoring/HealthProcessor.cs | 9 +++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs index 679addc32d..85f072fa54 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring private double hpMissMultiplier; public TaikoHealthProcessor(double gameplayStartTime) - : base(gameplayStartTime) + : base(gameplayStartTime, 0.5) { } @@ -42,6 +42,5 @@ namespace osu.Game.Rulesets.Taiko.Scoring protected override double GetHealthIncreaseFor(JudgementResult result) => base.GetHealthIncreaseFor(result) * (result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier); - protected override bool DefaultFailCondition => JudgedHits == MaxHits && Health.Value <= 0.5; } } diff --git a/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs index edc8d18804..540b4b8a1d 100644 --- a/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs @@ -3,11 +3,25 @@ namespace osu.Game.Rulesets.Scoring { + /// + /// A that accumulates health and causes a fail if the final health + /// is less than a value required to pass the beatmap. + /// public class AccumulatingHealthProcessor : HealthProcessor { - public AccumulatingHealthProcessor(double gameplayStartTime) + protected override bool DefaultFailCondition => JudgedHits == MaxHits && Health.Value < requiredHealth; + + private readonly double requiredHealth; + + /// + /// Creates a new . + /// + /// The gameplay start time. + /// The minimum amount of health required to beatmap. + public AccumulatingHealthProcessor(double gameplayStartTime, double requiredHealth) : base(gameplayStartTime) { + this.requiredHealth = requiredHealth; } protected override void Reset(bool storeResults) diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index 8b30728caf..df9fba0cca 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -9,6 +9,9 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Scoring { + /// + /// A which continuously drains health. + /// public class DrainingHealthProcessor : HealthProcessor { private IBeatmap beatmap; @@ -17,6 +20,10 @@ namespace osu.Game.Rulesets.Scoring private double targetMinimumHealth; private double drainRate = 1; + /// + /// Creates a new . + /// + /// The gameplay start time. public DrainingHealthProcessor(double gameplayStartTime) : base(gameplayStartTime) { diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index 597989701d..d8addc2b4d 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -41,6 +41,10 @@ namespace osu.Game.Rulesets.Scoring /// protected readonly double GameplayStartTime; + /// + /// Creates a new . + /// + /// The gameplay start time. protected HealthProcessor(double gameplayStartTime) { GameplayStartTime = gameplayStartTime; @@ -70,6 +74,11 @@ namespace osu.Game.Rulesets.Scoring // Todo: Revert HasFailed state with proper player support } + /// + /// Retrieves the health increase for a . + /// + /// The . + /// The health increase. protected virtual double GetHealthIncreaseFor(JudgementResult result) => result.Judgement.HealthIncreaseFor(result); /// From 96a4f9ae53f537c236a17ad4728bf92c0ad87831 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Dec 2019 15:14:19 +0900 Subject: [PATCH 4766/5608] Fix nub position getting offset by size changes --- .../Graphics/UserInterface/OsuSliderBar.cs | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 563dc2dad9..958390d5d2 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; @@ -31,6 +32,7 @@ namespace osu.Game.Graphics.UserInterface protected readonly Nub Nub; private readonly Box leftBox; private readonly Box rightBox; + private readonly Container nubContainer; public virtual string TooltipText { get; private set; } @@ -72,10 +74,15 @@ namespace osu.Game.Graphics.UserInterface Origin = Anchor.CentreRight, Alpha = 0.5f, }, - Nub = new Nub + nubContainer = new Container { - Origin = Anchor.TopCentre, - Expanded = true, + RelativeSizeAxes = Axes.Both, + Child = Nub = new Nub + { + Origin = Anchor.TopCentre, + RelativePositionAxes = Axes.X, + Expanded = true, + }, }, new HoverClickSounds() }; @@ -90,6 +97,13 @@ namespace osu.Game.Graphics.UserInterface AccentColour = colours.Pink; } + protected override void Update() + { + base.Update(); + + nubContainer.Padding = new MarginPadding { Horizontal = RangePadding }; + } + protected override void LoadComplete() { base.LoadComplete(); @@ -176,14 +190,14 @@ namespace osu.Game.Graphics.UserInterface { base.UpdateAfterChildren(); leftBox.Scale = new Vector2(Math.Clamp( - Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); + RangePadding + Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); rightBox.Scale = new Vector2(Math.Clamp( - DrawWidth - Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); + DrawWidth - Nub.DrawPosition.X - RangePadding - Nub.DrawWidth / 2, 0, DrawWidth), 1); } protected override void UpdateValue(float value) { - Nub.MoveToX(RangePadding + UsableWidth * value, 250, Easing.OutQuint); + Nub.MoveToX(value, 250, Easing.OutQuint); } /// From 9a013acb26b84e162e0a9a53d748728d93de7646 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 26 Dec 2019 14:25:41 +0800 Subject: [PATCH 4767/5608] Fix name typo of OsuModObjectScaleTween --- osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs | 2 +- .../{OsuModeObjectScaleTween.cs => OsuModObjectScaleTween.cs} | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename osu.Game.Rulesets.Osu/Mods/{OsuModeObjectScaleTween.cs => OsuModObjectScaleTween.cs} (96%) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs index adca95cf8a..9bf7525d33 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModDeflate : OsuModeObjectScaleTween + public class OsuModDeflate : OsuModObjectScaleTween { public override string Name => "Deflate"; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs index 3c81203ad7..76676ce888 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Rulesets.Osu.Mods { - internal class OsuModGrow : OsuModeObjectScaleTween + internal class OsuModGrow : OsuModObjectScaleTween { public override string Name => "Grow"; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs b/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs similarity index 96% rename from osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs rename to osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs index 923278f484..42ddddc4dd 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Mods /// /// Adjusts the size of hit objects during their fade in animation. /// - public abstract class OsuModeObjectScaleTween : Mod, IReadFromConfig, IApplicableToDrawableHitObjects + public abstract class OsuModObjectScaleTween : Mod, IReadFromConfig, IApplicableToDrawableHitObjects { public override ModType Type => ModType.Fun; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index e786ec86f9..eae218509e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; // todo: this mod should be able to be compatible with hidden with a bit of further implementation. - public override Type[] IncompatibleMods => new[] { typeof(OsuModeObjectScaleTween), typeof(OsuModHidden), typeof(OsuModTraceable) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModObjectScaleTween), typeof(OsuModHidden), typeof(OsuModTraceable) }; private const int rotate_offset = 360; private const float rotate_starting_width = 2; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index cf1ce517e8..dff9a77807 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModSpinIn), typeof(OsuModeObjectScaleTween) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModSpinIn), typeof(OsuModObjectScaleTween) }; private Bindable increaseFirstObjectVisibility = new Bindable(); public void ReadFromConfig(OsuConfigManager config) From 429272b864b022547c21c488961931b3095c5a57 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Dec 2019 15:28:30 +0900 Subject: [PATCH 4768/5608] Clean up + document taiko health processor --- osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs index 85f072fa54..279d119626 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs @@ -9,6 +9,10 @@ using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Scoring { + /// + /// A for the taiko ruleset. + /// Taiko fails if the player has not half-filled their health by the end of the map. + /// public class TaikoHealthProcessor : AccumulatingHealthProcessor { /// @@ -41,6 +45,5 @@ namespace osu.Game.Rulesets.Taiko.Scoring protected override double GetHealthIncreaseFor(JudgementResult result) => base.GetHealthIncreaseFor(result) * (result.Type == HitResult.Miss ? hpMissMultiplier : hpMultiplier); - } } From 662ec2d8122448f30138a18b40b3eb4b88295758 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Dec 2019 15:46:07 +0900 Subject: [PATCH 4769/5608] Refactor gameplay-time drain limitation --- .../Rulesets/Scoring/DrainingHealthProcessor.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index df9fba0cca..3735dc75c1 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -16,6 +16,8 @@ namespace osu.Game.Rulesets.Scoring { private IBeatmap beatmap; + private double gameplayEndTime; + private List<(double time, double health)> healthIncreases; private double targetMinimumHealth; private double drainRate = 1; @@ -35,9 +37,11 @@ namespace osu.Game.Rulesets.Scoring if (!IsBreakTime.Value) { - // When jumping from before the gameplay start to after it or vice-versa, we only want to consider any drain since the gameplay start time - double lastTime = Math.Max(GameplayStartTime, Time.Current - Time.Elapsed); - Health.Value -= drainRate * (Time.Current - lastTime); + // When jumping in and out of gameplay time within a single frame, health should only be drained for the period within the gameplay time + double lastGameplayTime = Math.Clamp(Time.Current - Time.Elapsed, GameplayStartTime, gameplayEndTime); + double currentGameplayTime = Math.Clamp(Time.Current, GameplayStartTime, gameplayEndTime); + + Health.Value -= drainRate * (currentGameplayTime - lastGameplayTime); } } @@ -45,6 +49,9 @@ namespace osu.Game.Rulesets.Scoring { this.beatmap = beatmap; + if (beatmap.HitObjects.Count > 0) + gameplayEndTime = beatmap.HitObjects[^1].GetEndTime(); + healthIncreases = new List<(double time, double health)>(); targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.95, 0.70, 0.30); From f5dbd57d55cb285b04bf367b27476dce54411157 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Dec 2019 17:36:40 +0900 Subject: [PATCH 4770/5608] Refactor drain calculation for resiliency --- .../Scoring/DrainingHealthProcessor.cs | 79 +++++++++++-------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index 3735dc75c1..e7e8656efb 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -14,8 +14,12 @@ namespace osu.Game.Rulesets.Scoring /// public class DrainingHealthProcessor : HealthProcessor { - private IBeatmap beatmap; + /// + /// A reasonable allowable error for the minimum health offset from . A 1% error is unnoticeable. + /// + private const double minimum_health_error = 0.01; + private IBeatmap beatmap; private double gameplayEndTime; private List<(double time, double health)> healthIncreases; @@ -74,49 +78,60 @@ namespace osu.Game.Rulesets.Scoring drainRate = 1; if (storeResults) + drainRate = computeDrainRate(); + } + + private double computeDrainRate() + { + if (healthIncreases == null || healthIncreases.Count == 0) + return 0; + + int adjustment = 1; + double result = 1; + + // Although we expect the following loop to converge within 30 iterations (health within 1/2^31 accuracy of the target), + // we'll still keep a safety measure to avoid infinite loops by detecting overflows. + while (adjustment > 0) { - int count = 1; + double currentHealth = 1; + double lowestHealth = 1; + int currentBreak = -1; - while (true) + for (int i = 0; i < healthIncreases.Count; i++) { - double currentHealth = 1; - double lowestHealth = 1; - int currentBreak = -1; + double currentTime = healthIncreases[i].time; + double lastTime = i > 0 ? healthIncreases[i - 1].time : GameplayStartTime; - for (int i = 0; i < healthIncreases.Count; i++) + // Subtract any break time from the duration since the last object + if (beatmap.Breaks.Count > 0) { - double currentTime = healthIncreases[i].time; - double lastTime = i > 0 ? healthIncreases[i - 1].time : GameplayStartTime; + while (currentBreak + 1 < beatmap.Breaks.Count && beatmap.Breaks[currentBreak + 1].EndTime < currentTime) + currentBreak++; - // Subtract any break time from the duration since the last object - if (beatmap.Breaks.Count > 0) - { - while (currentBreak + 1 < beatmap.Breaks.Count && beatmap.Breaks[currentBreak + 1].EndTime < currentTime) - currentBreak++; - - if (currentBreak >= 0) - lastTime = Math.Max(lastTime, beatmap.Breaks[currentBreak].EndTime); - } - - // Apply health adjustments - currentHealth -= (healthIncreases[i].time - lastTime) * drainRate; - lowestHealth = Math.Min(lowestHealth, currentHealth); - currentHealth = Math.Min(1, currentHealth + healthIncreases[i].health); - - // Common scenario for when the drain rate is definitely too harsh - if (lowestHealth < 0) - break; + if (currentBreak >= 0) + lastTime = Math.Max(lastTime, beatmap.Breaks[currentBreak].EndTime); } - if (Math.Abs(lowestHealth - targetMinimumHealth) <= 0.01) - break; + // Apply health adjustments + currentHealth -= (healthIncreases[i].time - lastTime) * result; + lowestHealth = Math.Min(lowestHealth, currentHealth); + currentHealth = Math.Min(1, currentHealth + healthIncreases[i].health); - count *= 2; - drainRate += 1.0 / count * Math.Sign(lowestHealth - targetMinimumHealth); + // Common scenario for when the drain rate is definitely too harsh + if (lowestHealth < 0) + break; } + + // Stop if the resulting health is within a reasonable offset from the target + if (Math.Abs(lowestHealth - targetMinimumHealth) <= minimum_health_error) + break; + + // This effectively works like a binary search - each iteration the search space moves closer to the the target, but may exceed it. + adjustment *= 2; + result += 1.0 / adjustment * Math.Sign(lowestHealth - targetMinimumHealth); } - healthIncreases.Clear(); + return result; } } } From 7ee0370d237a25f145ce224c202900e566589e44 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Dec 2019 17:48:46 +0900 Subject: [PATCH 4771/5608] Add some tests --- .../TestSceneDrainingHealthProcessor.cs | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs diff --git a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs new file mode 100644 index 0000000000..4996c86e5d --- /dev/null +++ b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs @@ -0,0 +1,149 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.MathUtils; +using osu.Framework.Testing; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; +using osu.Game.Tests.Visual; + +namespace osu.Game.Tests.Gameplay +{ + [HeadlessTest] + public class TestSceneDrainingHealthProcessor : OsuTestScene + { + private Bindable breakTime; + private HealthProcessor processor; + private ManualClock clock; + + [Test] + public void TestInitialHealthStartsAtOne() + { + createProcessor(createBeatmap(1000, 2000)); + + assertHealthEqualTo(1); + } + + [Test] + public void TestHealthNotDrainedBeforeGameplayStart() + { + createProcessor(createBeatmap(1000, 2000)); + + setTime(100); + assertHealthEqualTo(1); + setTime(900); + assertHealthEqualTo(1); + } + + [Test] + public void TestHealthNotDrainedAfterGameplayEnd() + { + createProcessor(createBeatmap(1000, 2000)); + setTime(2001); // After the hitobjects + setHealth(1); // Reset the current health for assertions to take place + + setTime(2100); + assertHealthEqualTo(1); + setTime(3000); + assertHealthEqualTo(1); + } + + [Test] + public void TestHealthNotDrainedDuringBreak() + { + createProcessor(createBeatmap(0, 2000)); + setBreak(true); + + setTime(700); + assertHealthEqualTo(1); + setTime(900); + assertHealthEqualTo(1); + } + + [Test] + public void TestHealthDrainedDuringGameplay() + { + createProcessor(createBeatmap(0, 1000)); + + setTime(500); + assertHealthNotEqualTo(1); + } + + [Test] + public void TestHealthGainedOnHit() + { + Beatmap beatmap = createBeatmap(0, 1000); + + createProcessor(beatmap); + setTime(10); // Decrease health slightly + assertHealthNotEqualTo(1); + + AddStep("apply hit result", () => processor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new Judgement()) { Type = HitResult.Perfect })); + assertHealthEqualTo(1); + } + + [Test] + public void TestHealthRemovedOnRevert() + { + var beatmap = createBeatmap(0, 1000); + JudgementResult result = null; + + createProcessor(beatmap); + setTime(10); // Decrease health slightly + AddStep("apply hit result", () => processor.ApplyResult(result = new JudgementResult(beatmap.HitObjects[0], new Judgement()) { Type = HitResult.Perfect })); + + AddStep("revert hit result", () => processor.RevertResult(result)); + assertHealthNotEqualTo(1); + } + + private Beatmap createBeatmap(double startTime, double endTime) + { + var beatmap = new Beatmap + { + BeatmapInfo = { BaseDifficulty = { DrainRate = 5 } }, + }; + + for (double time = startTime; time <= endTime; time += 100) + beatmap.HitObjects.Add(new JudgeableHitObject { StartTime = time }); + + return beatmap; + } + + private void createProcessor(Beatmap beatmap) => AddStep("create processor", () => + { + breakTime = new Bindable(); + + Child = processor = new DrainingHealthProcessor(beatmap.HitObjects[0].StartTime).With(d => + { + d.RelativeSizeAxes = Axes.Both; + d.Clock = new FramedClock(clock = new ManualClock()); + }); + + processor.IsBreakTime.BindTo(breakTime); + processor.ApplyBeatmap(beatmap); + }); + + private void setTime(double time) => AddStep($"set time = {time}", () => clock.CurrentTime = time); + + private void setHealth(double health) => AddStep($"set health = {health}", () => processor.Health.Value = health); + + private void setBreak(bool enabled) => AddStep($"{(enabled ? "enable" : "disable")} break", () => breakTime.Value = enabled); + + private void assertHealthEqualTo(double value) + => AddAssert($"health = {value}", () => Precision.AlmostEquals(value, processor.Health.Value, 0.0001f)); + + private void assertHealthNotEqualTo(double value) + => AddAssert($"health != {value}", () => !Precision.AlmostEquals(value, processor.Health.Value, 0.0001f)); + + private class JudgeableHitObject : HitObject + { + public override Judgement CreateJudgement() => new Judgement(); + } + } +} From 35f64d9aaea7729829fc0233792b93f3484b7c9c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Dec 2019 17:54:31 +0900 Subject: [PATCH 4772/5608] More comments --- osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index e7e8656efb..96242205d4 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -105,6 +105,7 @@ namespace osu.Game.Rulesets.Scoring // Subtract any break time from the duration since the last object if (beatmap.Breaks.Count > 0) { + // Advance the last break occuring before the current time while (currentBreak + 1 < beatmap.Breaks.Count && beatmap.Breaks[currentBreak + 1].EndTime < currentTime) currentBreak++; @@ -126,7 +127,7 @@ namespace osu.Game.Rulesets.Scoring if (Math.Abs(lowestHealth - targetMinimumHealth) <= minimum_health_error) break; - // This effectively works like a binary search - each iteration the search space moves closer to the the target, but may exceed it. + // This effectively works like a binary search - each iteration the search space moves closer to the target, but may exceed it. adjustment *= 2; result += 1.0 / adjustment * Math.Sign(lowestHealth - targetMinimumHealth); } From d45556eb6a07280a6be18c275fa5e3b9aa340e09 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Dec 2019 17:57:16 +0900 Subject: [PATCH 4773/5608] Remove whitespace --- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 1 - osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 5bca8588b6..a579a7d07e 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -41,7 +41,6 @@ namespace osu.Game.Rulesets.Mania public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap, this); - public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score); public const string SHORT_NAME = "mania"; diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index c5c2027af1..d713a4145d 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -34,7 +34,6 @@ namespace osu.Game.Rulesets.Taiko public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap, this); - public const string SHORT_NAME = "taiko"; public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] From 8903f286efa4e92c6276fc18ea29af29d0b5f8d2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Dec 2019 18:27:48 +0900 Subject: [PATCH 4774/5608] Fix escape not continuing to results screen --- osu.Game/Screens/Play/Player.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 8970f9ac88..ab32c55229 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -541,8 +541,14 @@ namespace osu.Game.Screens.Play { if (completionProgressDelegate != null && !completionProgressDelegate.Cancelled && !completionProgressDelegate.Completed) { - // proceed to result screen if beatmap already finished playing - completionProgressDelegate.RunTask(); + // Proceed to result screen if beatmap already finished playing. + // This is scheduled since the player needs to become the current screen before the delegate runs. This happens after the return true. + Scheduler.Add(() => + { + if (!completionProgressDelegate.Completed && !completionProgressDelegate.Cancelled) + completionProgressDelegate.RunTask(); + }); + return true; } From 74d875a2e063fbf1878479d9cc7646b1d02b920a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 26 Dec 2019 18:44:31 +0900 Subject: [PATCH 4775/5608] Give empty archives a hash based on archive name to avoid duplicate imports --- osu.Game/Database/ArchiveModelManager.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index fd455d7cd5..45fe034a70 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -259,6 +259,9 @@ namespace osu.Game.Database /// /// Create a SHA-2 hash from the provided archive based on file content of all files matching . /// + /// + /// In the case of no matching files, a hash will be generated from the passed archive's . + /// private string computeHash(ArchiveReader reader) { // for now, concatenate all .osu files in the set to create a unique hash. @@ -270,7 +273,7 @@ namespace osu.Game.Database s.CopyTo(hashable); } - return hashable.Length > 0 ? hashable.ComputeSHA2Hash() : null; + return hashable.Length > 0 ? hashable.ComputeSHA2Hash() : reader.Name.ComputeSHA2Hash(); } /// From a041f32072ac44dd1d0ae9c6877ce7e753fc161e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 26 Dec 2019 19:05:32 +0900 Subject: [PATCH 4776/5608] Use cleaner solution via cancellation of older schedule --- osu.Game/Screens/Play/Player.cs | 36 +++++++++++++++------------------ 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index ab32c55229..6368c30def 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -350,18 +350,7 @@ namespace osu.Game.Screens.Play if (!showResults) return; using (BeginDelayedSequence(1000)) - { - completionProgressDelegate = Schedule(delegate - { - if (!this.IsCurrentScreen()) return; - - var score = CreateScore(); - if (DrawableRuleset.ReplayScore == null) - scoreManager.Import(score).Wait(); - - this.Push(CreateResults(score)); - }); - } + scheduleGotoRanking(); } protected virtual ScoreInfo CreateScore() @@ -541,14 +530,8 @@ namespace osu.Game.Screens.Play { if (completionProgressDelegate != null && !completionProgressDelegate.Cancelled && !completionProgressDelegate.Completed) { - // Proceed to result screen if beatmap already finished playing. - // This is scheduled since the player needs to become the current screen before the delegate runs. This happens after the return true. - Scheduler.Add(() => - { - if (!completionProgressDelegate.Completed && !completionProgressDelegate.Cancelled) - completionProgressDelegate.RunTask(); - }); - + // proceed to result screen if beatmap already finished playing + scheduleGotoRanking(); return true; } @@ -583,6 +566,19 @@ namespace osu.Game.Screens.Play storyboardReplacesBackground.Value = false; } + private void scheduleGotoRanking() + { + completionProgressDelegate?.Cancel(); + completionProgressDelegate = Schedule(delegate + { + var score = CreateScore(); + if (DrawableRuleset.ReplayScore == null) + scoreManager.Import(score).Wait(); + + this.Push(CreateResults(score)); + }); + } + #endregion } } From 00a36c388c76db43e9373369c1c54c9cf8a0c905 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 26 Dec 2019 19:18:39 +0900 Subject: [PATCH 4777/5608] Fix tests --- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 ++ osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index c8a156dc57..c9ea5e6cf1 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -38,6 +38,8 @@ namespace osu.Game.Rulesets.Osu public override ScoreProcessor CreateScoreProcessor(IBeatmap beatmap) => new OsuScoreProcessor(beatmap); + public override HealthProcessor CreateHealthProcessor(IBeatmap beatmap) => new OsuHealthProcessor(beatmap); + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap, this); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index a0c25521a6..2045072c79 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -22,12 +22,12 @@ namespace osu.Game.Tests.Visual.Gameplay { AddUntilStep("wait for fail", () => Player.HasFailed); AddUntilStep("wait for multiple judged objects", () => ((FailPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.Count(h => h.AllJudged) > 1); - AddAssert("total judgements == 1", () => ((FailPlayer)Player).ScoreProcessor.JudgedHits == 1); + AddAssert("total judgements == 1", () => ((FailPlayer)Player).HealthProcessor.JudgedHits >= 1); } private class FailPlayer : TestPlayer { - public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + public new HealthProcessor HealthProcessor => base.HealthProcessor; public FailPlayer() : base(false, false) From a4d4efc312317f2a51e5a5624ee4901b582dc403 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 26 Dec 2019 19:33:59 +0900 Subject: [PATCH 4778/5608] Fix missing comments --- osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs b/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs index d1d85f5aca..34198da722 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs @@ -14,13 +14,13 @@ namespace osu.Game.Rulesets.Mods /// Called when a beatmap is changed. Can be used to read default values. /// Any changes made will not be preserved. /// - /// + /// The difficulty to read from. void ReadFromDifficulty(BeatmapDifficulty difficulty); /// /// Called post beatmap conversion. Can be used to apply changes to difficulty attributes. /// - /// + /// The difficulty to mutate. void ApplyToDifficulty(BeatmapDifficulty difficulty); } } From 2c1a65d90acfa70f206cf46a00b26da5d93111c8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 26 Dec 2019 19:37:55 +0900 Subject: [PATCH 4779/5608] Add simple test --- .../Editor/TestSceneBlueprintContainer.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 osu.Game.Tests/Editor/TestSceneBlueprintContainer.cs diff --git a/osu.Game.Tests/Editor/TestSceneBlueprintContainer.cs b/osu.Game.Tests/Editor/TestSceneBlueprintContainer.cs new file mode 100644 index 0000000000..5ccce5b3c6 --- /dev/null +++ b/osu.Game.Tests/Editor/TestSceneBlueprintContainer.cs @@ -0,0 +1,20 @@ +// 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.Screens.Edit.Compose.Components; +using osu.Game.Tests.Visual; + +namespace osu.Game.Tests.Editor +{ + public class TestSceneBlueprintContainer : EditorClockTestScene + { + private BlueprintContainer blueprintContainer; + + [SetUp] + public void Setup() => Schedule(() => + { + Child = blueprintContainer = new BlueprintContainer(); + }); + } +} From 92dd1ade175c5c709e9da9ccd68bf6eed7204410 Mon Sep 17 00:00:00 2001 From: mcendu Date: Thu, 26 Dec 2019 21:03:21 +0800 Subject: [PATCH 4780/5608] Attempt to implement mania-specific sprites --- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 4 ++ .../Skinning/ManiaLegacySkinTransformer.cs | 62 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index b07e1d8f54..f0c78f8009 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -26,7 +26,9 @@ using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Difficulty; using osu.Game.Rulesets.Mania.Edit; using osu.Game.Rulesets.Mania.Scoring; +using osu.Game.Rulesets.Mania.Skinning; using osu.Game.Rulesets.Scoring; +using osu.Game.Skinning; using osu.Game.Scoring; namespace osu.Game.Rulesets.Mania @@ -45,6 +47,8 @@ namespace osu.Game.Rulesets.Mania public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this); + public override ISkin CreateLegacySkinProvider(ISkinSource source) => new ManiaLegacySkinTransformer(source); + public override IEnumerable ConvertLegacyMods(LegacyMods mods) { if (mods.HasFlag(LegacyMods.Nightcore)) diff --git a/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs new file mode 100644 index 0000000000..29991a4a6d --- /dev/null +++ b/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs @@ -0,0 +1,62 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Textures; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Game.Rulesets.Scoring; +using osu.Game.Audio; +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Mania.Skinning +{ + public class ManiaLegacySkinTransformer : ISkin + { + private readonly ISkin source; + + public ManiaLegacySkinTransformer(ISkin source) + { + this.source = source; + } + + public Drawable GetDrawableComponent(ISkinComponent component) + { + switch (component) + { + case GameplaySkinComponent resultComponent: + switch (resultComponent.Component) + { + case HitResult.Miss: + return this.GetAnimation("mania-hit0", true, true); + + case HitResult.Meh: + return this.GetAnimation("mania-hit50", true, true); + + case HitResult.Ok: + return this.GetAnimation("mania-hit100", true, true); + + case HitResult.Good: + return this.GetAnimation("mania-hit200", true, true); + + case HitResult.Great: + return this.GetAnimation("mania-hit300", true, true); + + case HitResult.Perfect: + return this.GetAnimation("mania-hit300g", true, true); + } + + break; + } + + return null; + } + + public Texture GetTexture(string componentName) => source.GetTexture(componentName); + + public SampleChannel GetSample(ISampleInfo sample) => source.GetSample(sample); + + public IBindable GetConfig(TLookup lookup) => + source.GetConfig(lookup); + } +} From 8ebfe5cfd89059d8066662fd33392a3ff167f656 Mon Sep 17 00:00:00 2001 From: mcendu Date: Thu, 26 Dec 2019 21:15:49 +0800 Subject: [PATCH 4781/5608] add tests --- .../SkinnableTestScene.cs | 74 +++++++++++++++++++ .../TestSceneDrawableJudgement.cs | 37 ++++++++++ 2 files changed, 111 insertions(+) create mode 100644 osu.Game.Rulesets.Mania.Tests/SkinnableTestScene.cs create mode 100644 osu.Game.Rulesets.Mania.Tests/TestSceneDrawableJudgement.cs diff --git a/osu.Game.Rulesets.Mania.Tests/SkinnableTestScene.cs b/osu.Game.Rulesets.Mania.Tests/SkinnableTestScene.cs new file mode 100644 index 0000000000..3822c8ce86 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/SkinnableTestScene.cs @@ -0,0 +1,74 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Text.RegularExpressions; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Textures; +using osu.Framework.IO.Stores; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Mania.Tests +{ + public abstract class SkinnableTestScene : OsuGridTestScene + { + private Skin defaultSkin; + + protected SkinnableTestScene() + : base(1, 2) + { + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio, SkinManager skinManager) + { + defaultSkin = skinManager.GetSkin(DefaultLegacySkin.Info); + } + + public void SetContents(Func creationFunction) + { + Cell(0).Child = createProvider(null, creationFunction); + Cell(1).Child = createProvider(defaultSkin, creationFunction); + } + + private Drawable createProvider(Skin skin, Func creationFunction) + { + var mainProvider = new SkinProvidingContainer(skin); + + return mainProvider + .WithChild(new SkinProvidingContainer(Ruleset.Value.CreateInstance().CreateLegacySkinProvider(mainProvider)) + { + Child = creationFunction() + }); + } + + private class TestLegacySkin : LegacySkin + { + private readonly bool extrapolateAnimations; + + public TestLegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager, bool extrapolateAnimations) + : base(skin, storage, audioManager, "skin.ini") + { + this.extrapolateAnimations = extrapolateAnimations; + } + + public override Texture GetTexture(string componentName) + { + // extrapolate frames to test longer animations + if (extrapolateAnimations) + { + var match = Regex.Match(componentName, "-([0-9]*)"); + + if (match.Length > 0 && int.TryParse(match.Groups[1].Value, out var number) && number < 60) + return base.GetTexture(componentName.Replace($"-{number}", $"-{number % 2}")); + } + + return base.GetTexture(componentName); + } + } + } +} diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableJudgement.cs new file mode 100644 index 0000000000..eea1a36a19 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableJudgement.cs @@ -0,0 +1,37 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Mania.Tests +{ + public class TestSceneDrawableJudgement : SkinnableTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(DrawableJudgement), + typeof(DrawableManiaJudgement) + }; + + public TestSceneDrawableJudgement() + { + foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType().Skip(1)) + { + AddStep("Show " + result.GetDescription(), () => SetContents(() => + new DrawableManiaJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + })); + } + } + } +} From 75d1e4cc7606468002a3af7ec6ece16dc34e663b Mon Sep 17 00:00:00 2001 From: mcendu Date: Thu, 26 Dec 2019 22:06:29 +0800 Subject: [PATCH 4782/5608] rm TestLegacySkin --- .../SkinnableTestScene.cs | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/SkinnableTestScene.cs b/osu.Game.Rulesets.Mania.Tests/SkinnableTestScene.cs index 3822c8ce86..1c8a9c4ca6 100644 --- a/osu.Game.Rulesets.Mania.Tests/SkinnableTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/SkinnableTestScene.cs @@ -45,30 +45,5 @@ namespace osu.Game.Rulesets.Mania.Tests Child = creationFunction() }); } - - private class TestLegacySkin : LegacySkin - { - private readonly bool extrapolateAnimations; - - public TestLegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager, bool extrapolateAnimations) - : base(skin, storage, audioManager, "skin.ini") - { - this.extrapolateAnimations = extrapolateAnimations; - } - - public override Texture GetTexture(string componentName) - { - // extrapolate frames to test longer animations - if (extrapolateAnimations) - { - var match = Regex.Match(componentName, "-([0-9]*)"); - - if (match.Length > 0 && int.TryParse(match.Groups[1].Value, out var number) && number < 60) - return base.GetTexture(componentName.Replace($"-{number}", $"-{number % 2}")); - } - - return base.GetTexture(componentName); - } - } } } From 64381bf4b14f1d9574c00641ae05b753407c7426 Mon Sep 17 00:00:00 2001 From: mcendu Date: Thu, 26 Dec 2019 22:08:46 +0800 Subject: [PATCH 4783/5608] rm unnecessary usings --- osu.Game.Rulesets.Mania.Tests/SkinnableTestScene.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/SkinnableTestScene.cs b/osu.Game.Rulesets.Mania.Tests/SkinnableTestScene.cs index 1c8a9c4ca6..80b1b3df8e 100644 --- a/osu.Game.Rulesets.Mania.Tests/SkinnableTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/SkinnableTestScene.cs @@ -2,13 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Text.RegularExpressions; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Textures; -using osu.Framework.IO.Stores; using osu.Game.Skinning; using osu.Game.Tests.Visual; From ca3e8db79f7ba1db9c98f401789c111018d049e3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 26 Dec 2019 21:03:39 +0300 Subject: [PATCH 4784/5608] Merge dependency --- .../Graphics/UserInterface/ScreenTitle.cs | 53 ++++++++++++------- .../UserInterface/ScreenTitleTextureIcon.cs | 39 +++----------- .../Overlays/Changelog/ChangelogHeader.cs | 2 +- osu.Game/Overlays/News/NewsHeader.cs | 20 +++---- 4 files changed, 52 insertions(+), 62 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index 10fc312d8b..a8c8005a41 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Sprites; using osuTK; @@ -13,15 +14,15 @@ namespace osu.Game.Graphics.UserInterface { public abstract class ScreenTitle : CompositeDrawable, IHasAccentColour { - public const float ICON_WIDTH = ICON_SIZE + icon_spacing; + public const float ICON_WIDTH = ICON_SIZE + spacing; - public const float ICON_SIZE = 25; + public const float ICON_SIZE = 30; + private const float spacing = 6; + private const int text_offset = 2; private SpriteIcon iconSprite; private readonly OsuSpriteText titleText, pageText; - private const float icon_spacing = 10; - protected IconUsage Icon { set @@ -63,26 +64,40 @@ namespace osu.Game.Graphics.UserInterface new FillFlowContainer { AutoSizeAxes = Axes.Both, - Spacing = new Vector2(icon_spacing, 0), + Spacing = new Vector2(spacing, 0), + Direction = FillDirection.Horizontal, Children = new[] { - CreateIcon(), - new FillFlowContainer + CreateIcon().With(t => { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(6, 0), - Children = new[] + t.Anchor = Anchor.Centre; + t.Origin = Anchor.Centre; + }), + titleText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold), + Margin = new MarginPadding { Bottom = text_offset } + }, + new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + Size = new Vector2(4), + Child = new Box { - titleText = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light), - }, - pageText = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light), - } + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray, } + }, + pageText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 20), + Margin = new MarginPadding { Bottom = text_offset } } } }, diff --git a/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs b/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs index f590e7e357..e36000af4e 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osuTK; @@ -16,8 +15,6 @@ namespace osu.Game.Graphics.UserInterface /// public class ScreenTitleTextureIcon : CompositeDrawable { - private const float circle_allowance = 0.8f; - private readonly string textureName; public ScreenTitleTextureIcon(string textureName) @@ -26,38 +23,16 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private void load(TextureStore textures, OsuColour colours) + private void load(TextureStore textures) { - Size = new Vector2(ScreenTitle.ICON_SIZE / circle_allowance); + Size = new Vector2(ScreenTitle.ICON_SIZE); - InternalChildren = new Drawable[] + InternalChild = new Sprite { - new CircularContainer - { - Masking = true, - BorderColour = colours.Violet, - BorderThickness = 3, - MaskingSmoothness = 1, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Sprite - { - RelativeSizeAxes = Axes.Both, - Texture = textures.Get(textureName), - Size = new Vector2(circle_allowance), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Violet, - Alpha = 0, - AlwaysPresent = true, - }, - } - }, + RelativeSizeAxes = Axes.Both, + Texture = textures.Get(textureName), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, }; } } diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index b2e9be24b3..18dcdf721c 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -111,7 +111,7 @@ namespace osu.Game.Overlays.Changelog public ChangelogHeaderTitle() { - Title = "Changelog"; + Title = "changelog"; Version = null; } diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 27620ab523..0f73663605 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -15,7 +15,7 @@ namespace osu.Game.Overlays.News { public class NewsHeader : OverlayHeader { - private const string front_page_string = "Front Page"; + private const string front_page_string = "frontpage"; private NewsHeaderTitle title; @@ -33,7 +33,7 @@ namespace osu.Game.Overlays.News ShowFrontPage?.Invoke(); }; - Current.ValueChanged += showArticle; + Current.ValueChanged += showPost; } [BackgroundDependencyLoader] @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.News TabControl.AccentColour = colour.Violet; } - private void showArticle(ValueChangedEvent e) + private void showPost(ValueChangedEvent e) { if (e.OldValue != null) TabControl.RemoveItem(e.OldValue); @@ -52,12 +52,12 @@ namespace osu.Game.Overlays.News TabControl.AddItem(e.NewValue); TabControl.Current.Value = e.NewValue; - title.IsReadingArticle = true; + title.IsReadingPost = true; } else { TabControl.Current.Value = front_page_string; - title.IsReadingArticle = false; + title.IsReadingPost = false; } } @@ -84,17 +84,17 @@ namespace osu.Game.Overlays.News private class NewsHeaderTitle : ScreenTitle { - private const string article_string = "Article"; + private const string post_string = "post"; - public bool IsReadingArticle + public bool IsReadingPost { - set => Section = value ? article_string : front_page_string; + set => Section = value ? post_string : front_page_string; } public NewsHeaderTitle() { - Title = "News"; - IsReadingArticle = false; + Title = "news"; + IsReadingPost = false; } protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/news"); From 647c83e6c858c3a11e74717f8c5af754b248482a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 26 Dec 2019 21:21:15 +0300 Subject: [PATCH 4785/5608] Add ability to not create content for headers Rather than creating an empty container --- osu.Game/Overlays/Changelog/ChangelogHeader.cs | 2 +- osu.Game/Overlays/News/NewsHeader.cs | 2 -- osu.Game/Overlays/OverlayHeader.cs | 16 ++++++++++------ osu.Game/Overlays/Profile/ProfileHeader.cs | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 18dcdf721c..c6fedc0032 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays.Changelog protected override Drawable CreateBackground() => new HeaderBackground(); - protected override Drawable CreateContent() => new Container + protected override Drawable CreateContent => new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 0f73663605..6e17303a9d 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -63,8 +63,6 @@ namespace osu.Game.Overlays.News protected override Drawable CreateBackground() => new NewsHeaderBackground(); - protected override Drawable CreateContent() => new Container(); - protected override ScreenTitle CreateTitle() => title = new NewsHeaderTitle(); private class NewsHeaderBackground : Sprite diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index 2e032db2ba..ed27bf7048 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Children = new Drawable[] + AddRange(new[] { new Container { @@ -50,20 +50,24 @@ namespace osu.Game.Overlays Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN } } } - }, - new Container + } + }); + + if (CreateContent != null) + { + Add(new Container { Margin = new MarginPadding { Top = cover_height }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = CreateContent() - } + Child = CreateContent + }); }; } protected abstract Drawable CreateBackground(); - protected abstract Drawable CreateContent(); + protected virtual Drawable CreateContent => null; protected abstract ScreenTitle CreateTitle(); } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 76613c156d..454ac72a7b 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -58,7 +58,7 @@ namespace osu.Game.Overlays.Profile } }; - protected override Drawable CreateContent() => new FillFlowContainer + protected override Drawable CreateContent => new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, From a1c91af0956fb710ad313b61243ead16e3250bf0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 26 Dec 2019 22:09:06 +0300 Subject: [PATCH 4786/5608] Update layout of every overlay using OverlayHeader --- .../Overlays/Changelog/ChangelogHeader.cs | 2 + osu.Game/Overlays/News/NewsHeader.cs | 7 +- osu.Game/Overlays/OverlayHeader.cs | 109 ++++++++++++------ osu.Game/Overlays/Profile/ProfileHeader.cs | 5 + 4 files changed, 84 insertions(+), 39 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index c6fedc0032..0cddeabdaa 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -47,6 +47,8 @@ namespace osu.Game.Overlays.Changelog private void load(OsuColour colours) { TabControl.AccentColour = colours.Violet; + TitleBackgroundColour = colours.GreyVioletDarker; + ControlBackgroundColour = colours.GreyVioletDark; } private ChangelogHeaderTitle title; diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 6e17303a9d..e3cf58ed0a 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; @@ -37,9 +36,11 @@ namespace osu.Game.Overlays.News } [BackgroundDependencyLoader] - private void load(OsuColour colour) + private void load(OsuColour colours) { - TabControl.AccentColour = colour.Violet; + TabControl.AccentColour = colours.Violet; + TitleBackgroundColour = colours.GreyVioletDarker; + ControlBackgroundColour = colours.GreyVioletDark; } private void showPost(ValueChangedEvent e) diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index ed27bf7048..47d7a30b0b 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -3,7 +3,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.UserInterface; +using osuTK.Graphics; namespace osu.Game.Overlays { @@ -11,58 +13,93 @@ namespace osu.Game.Overlays { protected readonly OverlayHeaderTabControl TabControl; - private const float cover_height = 150; - private const float cover_info_height = 75; + private readonly Box titleBackground; + private readonly Box controlBackground; + private readonly Container background; + + protected Color4 TitleBackgroundColour + { + set => titleBackground.Colour = value; + } + + protected Color4 ControlBackgroundColour + { + set => controlBackground.Colour = value; + } + + protected float BackgroundHeight + { + set => background.Height = value; + } protected OverlayHeader() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - AddRange(new[] + FillFlowContainer flow; + + Add(flow = new FillFlowContainer { - new Container + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - Height = cover_height, - Masking = true, - Child = CreateBackground() - }, - new Container - { - Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, - Y = cover_height, - Height = cover_info_height, - RelativeSizeAxes = Axes.X, - Anchor = Anchor.TopLeft, - Origin = Anchor.BottomLeft, - Depth = -float.MaxValue, - Children = new Drawable[] + background = new Container { - CreateTitle().With(t => t.X = -ScreenTitle.ICON_WIDTH), - TabControl = new OverlayHeaderTabControl + RelativeSizeAxes = Axes.X, + Height = 80, + Masking = true, + Child = CreateBackground() + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Height = cover_info_height - 30, - Margin = new MarginPadding { Left = -UserProfileOverlay.CONTENT_X_MARGIN }, - Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN } + titleBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray, + }, + CreateTitle().With(title => + { + title.Margin = new MarginPadding + { + Vertical = 5, + Left = UserProfileOverlay.CONTENT_X_MARGIN + }; + }) + } + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + controlBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray, + }, + TabControl = new OverlayHeaderTabControl + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = 30, + Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, + } } } } }); if (CreateContent != null) - { - Add(new Container - { - Margin = new MarginPadding { Top = cover_height }, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = CreateContent - }); - }; + flow.Add(CreateContent); } protected abstract Drawable CreateBackground(); diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 454ac72a7b..f9c7062c69 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -26,6 +26,8 @@ namespace osu.Game.Overlays.Profile public ProfileHeader() { + BackgroundHeight = 150; + User.ValueChanged += e => updateDisplay(e.NewValue); TabControl.AddItem("Info"); @@ -38,6 +40,8 @@ namespace osu.Game.Overlays.Profile private void load(OsuColour colours) { TabControl.AccentColour = colours.Seafoam; + TitleBackgroundColour = colours.GreySeafoamDarker; + ControlBackgroundColour = colours.GreySeafoam; } protected override Drawable CreateBackground() => @@ -103,6 +107,7 @@ namespace osu.Game.Overlays.Profile { Title = "Player"; Section = "Info"; + X = -ICON_WIDTH; } [BackgroundDependencyLoader] From e360aa458864d3026fbe5eceee09f7dabea64ec1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 26 Dec 2019 22:16:20 +0300 Subject: [PATCH 4787/5608] Fix TabControl wasn't on top of everything --- osu.Game/Overlays/OverlayHeader.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index 47d7a30b0b..bfb2c4cd5e 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -78,6 +78,7 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Depth = -float.MaxValue, Children = new Drawable[] { controlBackground = new Box From 005ec4b3733cdb3a8197efa9e45dc9f4129c9a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 26 Dec 2019 20:17:51 +0100 Subject: [PATCH 4788/5608] Demonstrate bug in scrolling container scene Modify TestSceneScrollingHitObjects to showcase the effect of origin choice on object lifetime for all four scrolling directions. --- .../Visual/Gameplay/TestSceneScrollingHitObjects.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs index aa80819694..7ab53b2d65 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.Gameplay RelativeSizeAxes = Axes.Both, Child = playfields[0] = new TestPlayfield() }, - scrollContainers[1] = new ScrollingTestContainer(ScrollingDirection.Up) + scrollContainers[1] = new ScrollingTestContainer(ScrollingDirection.Down) { RelativeSizeAxes = Axes.Both, Child = playfields[1] = new TestPlayfield() @@ -53,12 +53,12 @@ namespace osu.Game.Tests.Visual.Gameplay }, new Drawable[] { - scrollContainers[2] = new ScrollingTestContainer(ScrollingDirection.Up) + scrollContainers[2] = new ScrollingTestContainer(ScrollingDirection.Left) { RelativeSizeAxes = Axes.Both, Child = playfields[2] = new TestPlayfield() }, - scrollContainers[3] = new ScrollingTestContainer(ScrollingDirection.Up) + scrollContainers[3] = new ScrollingTestContainer(ScrollingDirection.Right) { RelativeSizeAxes = Axes.Both, Child = playfields[3] = new TestPlayfield() @@ -207,7 +207,9 @@ namespace osu.Game.Tests.Visual.Gameplay public TestDrawableHitObject(double time) : base(new HitObject { StartTime = time }) { - Origin = Anchor.Centre; + Origin = Anchor.Custom; + OriginPosition = new Vector2(75 / 4.0f); + AutoSizeAxes = Axes.Both; AddInternal(new Box { Size = new Vector2(75) }); From 193e41f8789c5f1da4acc038569fca9f1a858327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 26 Dec 2019 20:23:16 +0100 Subject: [PATCH 4789/5608] Add origin adjustment for hitobject lifetime Visual inspection of taiko gameplay has shown that hitobjects appeared on screen only when the origin of the hitobject came into the bounds of the screen, instead of appearing when any visible part of the hitobject came into the screen bounds. This behaviour was due to lifetime calculation being based on the origin of the hitobject and not taking into account the actual object dimensions. Adjust the lifetime start of the hitobject by subtracting the time needed to show the part of the hitobject that should already be visible on screen when the origin comes into frame. --- .../Scrolling/ScrollingHitObjectContainer.cs | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 857929ff9e..04b4374fc4 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -100,7 +100,7 @@ namespace osu.Game.Rulesets.UI.Scrolling private void computeLifetimeStartRecursive(DrawableHitObject hitObject) { - hitObject.LifetimeStart = scrollingInfo.Algorithm.GetDisplayStartTime(hitObject.HitObject.StartTime, timeRange.Value); + hitObject.LifetimeStart = computeOriginAdjustedLifetimeStart(hitObject); foreach (var obj in hitObject.NestedHitObjects) computeLifetimeStartRecursive(obj); @@ -108,6 +108,35 @@ namespace osu.Game.Rulesets.UI.Scrolling private readonly Dictionary hitObjectInitialStateCache = new Dictionary(); + private double computeOriginAdjustedLifetimeStart(DrawableHitObject hitObject) + { + float originAdjustment = 0.0f; + + // calculate the dimension of the part of the hitobject that should already be visible + // when the hitobject origin first appears inside the scrolling container + switch (direction.Value) + { + case ScrollingDirection.Up: + originAdjustment = hitObject.OriginPosition.Y; + break; + + case ScrollingDirection.Down: + originAdjustment = hitObject.DrawHeight - hitObject.OriginPosition.Y; + break; + + case ScrollingDirection.Left: + originAdjustment = hitObject.OriginPosition.X; + break; + + case ScrollingDirection.Right: + originAdjustment = hitObject.DrawWidth - hitObject.OriginPosition.X; + break; + } + + var adjustedStartTime = scrollingInfo.Algorithm.TimeAt(-originAdjustment, hitObject.HitObject.StartTime, timeRange.Value, scrollLength); + return scrollingInfo.Algorithm.GetDisplayStartTime(adjustedStartTime, timeRange.Value); + } + // Cant use AddOnce() since the delegate is re-constructed every invocation private void computeInitialStateRecursive(DrawableHitObject hitObject) => hitObject.Schedule(() => { From 3d7c7a1ced8d88bf034429b38a1858a734e85839 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 26 Dec 2019 22:39:13 +0300 Subject: [PATCH 4790/5608] Fix profile title wasn't in lowercase --- osu.Game/Overlays/Profile/ProfileHeader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 76613c156d..3970fb2b97 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -101,8 +101,8 @@ namespace osu.Game.Overlays.Profile { public ProfileHeaderTitle() { - Title = "Player"; - Section = "Info"; + Title = "player"; + Section = "info"; } [BackgroundDependencyLoader] From fd8c5d77061b743300a8d16acd6120d1e84f3220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 26 Dec 2019 22:23:25 +0100 Subject: [PATCH 4791/5608] Improve notification overlay test robustness Stress testing one of the notification overlay tests by running it 10000 times on repeat has shown that it is susceptible to intermittent failures due to races between delays and asserts checking the number of currently progressing notifications and the actual progress update, which contains a random generation factor. Replace step sequences checking for notification completion by waiting and asserting with explicit until steps that don't terminate unless there are zero progressing notifications. --- .../UserInterface/TestSceneNotificationOverlay.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs index d8a4514df1..35e5f9719c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs @@ -67,9 +67,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddRepeatStep(@"add many simple", sendManyNotifications, 3); - AddWaitStep("wait some", 5); - - checkProgressingCount(0); + waitForCompletion(); AddStep(@"progress #3", sendUploadProgress); @@ -77,9 +75,7 @@ namespace osu.Game.Tests.Visual.UserInterface checkDisplayedCount(33); - AddWaitStep("wait some", 10); - - checkProgressingCount(0); + waitForCompletion(); } [Test] @@ -109,9 +105,9 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep(@"background progress #1", sendBackgroundUploadProgress); - AddWaitStep("wait some", 5); + checkProgressingCount(1); - checkProgressingCount(0); + waitForCompletion(); checkDisplayedCount(2); @@ -190,6 +186,8 @@ namespace osu.Game.Tests.Visual.UserInterface private void checkProgressingCount(int expected) => AddAssert($"progressing count is {expected}", () => progressingNotifications.Count == expected); + private void waitForCompletion() => AddUntilStep("wait for notification progress completion", () => progressingNotifications.Count == 0); + private void sendBarrage() { switch (RNG.Next(0, 4)) From 25f6517fba6a83e9255d47521eabec8e606e18a0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 27 Dec 2019 03:53:01 +0300 Subject: [PATCH 4792/5608] Update dependency --- osu.Game/Overlays/Profile/ProfileHeader.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index f9c7062c69..52baa57121 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -105,9 +105,8 @@ namespace osu.Game.Overlays.Profile { public ProfileHeaderTitle() { - Title = "Player"; - Section = "Info"; - X = -ICON_WIDTH; + Title = "player"; + Section = "info"; } [BackgroundDependencyLoader] From bd6e603be3948b02ddd3546b3302f3a2bea32bed Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 27 Dec 2019 04:01:33 +0300 Subject: [PATCH 4793/5608] Add icon for profile header --- osu.Game/Overlays/Profile/ProfileHeader.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 52baa57121..14430c958e 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -114,6 +114,8 @@ namespace osu.Game.Overlays.Profile { AccentColour = colours.Seafoam; } + + protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/profile"); } } } From 183307d636b8bcd1fca0571276e300459d47ccd5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 27 Dec 2019 10:53:20 +0900 Subject: [PATCH 4794/5608] Use circle instead of CircularContainer --- osu.Game/Graphics/UserInterface/ScreenTitle.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index a8c8005a41..f5bb97d465 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -80,17 +80,12 @@ namespace osu.Game.Graphics.UserInterface Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold), Margin = new MarginPadding { Bottom = text_offset } }, - new CircularContainer + new Circle { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Masking = true, Size = new Vector2(4), - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Gray, - } + Colour = Color4.Gray, }, pageText = new OsuSpriteText { From dc720dd65338f8513f8e22ae647be0311479f140 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 27 Dec 2019 05:27:36 +0300 Subject: [PATCH 4795/5608] Bump ppy.osu.Game.Resources from 2019.1215.0 to 2019.1227.0 --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index e7f90af5fd..82bde17805 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -53,7 +53,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0c0a58d533..5ffc6be066 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -22,7 +22,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index edeeea239e..67da9eac95 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,7 +73,7 @@ - + From 380c3161f156cab8e8e6df4d0008ceaa6fe9fc33 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 27 Dec 2019 11:28:07 +0900 Subject: [PATCH 4796/5608] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0c0a58d533..5ffc6be066 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -22,7 +22,7 @@ - + From cfa1dfa1a4daef0e8a0f992a275e184768859176 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 27 Dec 2019 11:37:05 +0900 Subject: [PATCH 4797/5608] Split out into own method --- .../Skinning/ManiaLegacySkinTransformer.cs | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs index 29991a4a6d..f3739ce7c2 100644 --- a/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/ManiaLegacySkinTransformer.cs @@ -25,28 +25,33 @@ namespace osu.Game.Rulesets.Mania.Skinning switch (component) { case GameplaySkinComponent resultComponent: - switch (resultComponent.Component) - { - case HitResult.Miss: - return this.GetAnimation("mania-hit0", true, true); + return getResult(resultComponent); + } - case HitResult.Meh: - return this.GetAnimation("mania-hit50", true, true); + return null; + } - case HitResult.Ok: - return this.GetAnimation("mania-hit100", true, true); + private Drawable getResult(GameplaySkinComponent resultComponent) + { + switch (resultComponent.Component) + { + case HitResult.Miss: + return this.GetAnimation("mania-hit0", true, true); - case HitResult.Good: - return this.GetAnimation("mania-hit200", true, true); + case HitResult.Meh: + return this.GetAnimation("mania-hit50", true, true); - case HitResult.Great: - return this.GetAnimation("mania-hit300", true, true); + case HitResult.Ok: + return this.GetAnimation("mania-hit100", true, true); - case HitResult.Perfect: - return this.GetAnimation("mania-hit300g", true, true); - } + case HitResult.Good: + return this.GetAnimation("mania-hit200", true, true); - break; + case HitResult.Great: + return this.GetAnimation("mania-hit300", true, true); + + case HitResult.Perfect: + return this.GetAnimation("mania-hit300g", true, true); } return null; From 3feaaa3e4da9c688fd5f4c89bae004c8468db549 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 27 Dec 2019 05:37:06 +0300 Subject: [PATCH 4798/5608] Use FillMode.Fit for icons --- osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs b/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs index e36000af4e..c2a13970de 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs @@ -33,6 +33,7 @@ namespace osu.Game.Graphics.UserInterface Texture = textures.Get(textureName), Anchor = Anchor.Centre, Origin = Anchor.Centre, + FillMode = FillMode.Fit }; } } From 2d167a51612ac2a6fd0ce4ef173c0e43b8d66612 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 27 Dec 2019 05:53:31 +0300 Subject: [PATCH 4799/5608] Some little size adjustments --- osu.Game/Graphics/UserInterface/ScreenTitle.cs | 2 +- osu.Game/Overlays/OverlayHeader.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index f5bb97d465..ecd0508258 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -16,7 +16,7 @@ namespace osu.Game.Graphics.UserInterface { public const float ICON_WIDTH = ICON_SIZE + spacing; - public const float ICON_SIZE = 30; + public const float ICON_SIZE = 25; private const float spacing = 6; private const int text_offset = 2; diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index bfb2c4cd5e..72e86b2400 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -68,7 +68,7 @@ namespace osu.Game.Overlays { title.Margin = new MarginPadding { - Vertical = 5, + Vertical = 10, Left = UserProfileOverlay.CONTENT_X_MARGIN }; }) From 04a4821a9fc1b3aaa5ed8e8ff7b57d799dc69331 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 27 Dec 2019 06:36:41 +0300 Subject: [PATCH 4800/5608] Make CreateContent a method again --- osu.Game/Overlays/Changelog/ChangelogHeader.cs | 2 +- osu.Game/Overlays/OverlayHeader.cs | 8 +++++--- osu.Game/Overlays/Profile/ProfileHeader.cs | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 0cddeabdaa..3b6f0d778d 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Changelog protected override Drawable CreateBackground() => new HeaderBackground(); - protected override Drawable CreateContent => new Container + protected override Drawable CreateContent() => new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index 72e86b2400..9e88273443 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -99,13 +99,15 @@ namespace osu.Game.Overlays } }); - if (CreateContent != null) - flow.Add(CreateContent); + var content = CreateContent(); + + if (content != null) + flow.Add(content); } protected abstract Drawable CreateBackground(); - protected virtual Drawable CreateContent => null; + protected virtual Drawable CreateContent() => null; protected abstract ScreenTitle CreateTitle(); } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 14430c958e..4a792f7375 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Profile } }; - protected override Drawable CreateContent => new FillFlowContainer + protected override Drawable CreateContent() => new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, From 099b044f04c556aefe50db9ab9a40fe9dee06c12 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 27 Dec 2019 06:37:36 +0300 Subject: [PATCH 4801/5608] Add headless test ensuring correct cancelling download behaviour --- .../Online/TestSceneBeatmapDownloading.cs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs diff --git a/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs b/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs new file mode 100644 index 0000000000..1572b813c0 --- /dev/null +++ b/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs @@ -0,0 +1,44 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Overlays.Notifications; +using osu.Game.Tests.Visual; + +namespace osu.Game.Tests.Online +{ + [HeadlessTest] + public class TestSceneBeatmapManager : OsuTestScene + { + private BeatmapManager beatmaps; + private ProgressNotification recentNotification; + + private static readonly BeatmapSetInfo test_model = new BeatmapSetInfo { OnlineBeatmapSetID = 1 }; + + [BackgroundDependencyLoader] + private void load(BeatmapManager beatmaps) + { + this.beatmaps = beatmaps; + + beatmaps.PostNotification = n => recentNotification = n as ProgressNotification; + } + + [TestCase(true)] + [TestCase(false)] + public void TestCancelDownloadFromRequest(bool closeFromRequest) + { + AddStep("download beatmap", () => beatmaps.Download(test_model)); + + if (closeFromRequest) + AddStep("cancel download from request", () => beatmaps.GetExistingDownload(test_model).Cancel()); + else + AddStep("cancel download from notification", () => recentNotification.Close()); + + AddUntilStep("is removed from download list", () => beatmaps.GetExistingDownload(test_model) == null); + AddAssert("is notification cancelled", () => recentNotification.State == ProgressNotificationState.Cancelled); + } + } +} From fbbd16b4f02e9a4fbda6ee9d511e6d846c0d95fc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 27 Dec 2019 12:39:25 +0900 Subject: [PATCH 4802/5608] Remove healthIncreases nullability --- osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index 96242205d4..ba29a9a0ce 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Scoring private IBeatmap beatmap; private double gameplayEndTime; - private List<(double time, double health)> healthIncreases; + private readonly List<(double time, double health)> healthIncreases = new List<(double, double)>(); private double targetMinimumHealth; private double drainRate = 1; @@ -56,19 +56,15 @@ namespace osu.Game.Rulesets.Scoring if (beatmap.HitObjects.Count > 0) gameplayEndTime = beatmap.HitObjects[^1].GetEndTime(); - healthIncreases = new List<(double time, double health)>(); targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.95, 0.70, 0.30); base.ApplyBeatmap(beatmap); - - // Only required during the simulation stage - healthIncreases = null; } protected override void ApplyResultInternal(JudgementResult result) { base.ApplyResultInternal(result); - healthIncreases?.Add((result.HitObject.GetEndTime() + result.TimeOffset, GetHealthIncreaseFor(result))); + healthIncreases.Add((result.HitObject.GetEndTime() + result.TimeOffset, GetHealthIncreaseFor(result))); } protected override void Reset(bool storeResults) @@ -79,11 +75,13 @@ namespace osu.Game.Rulesets.Scoring if (storeResults) drainRate = computeDrainRate(); + + healthIncreases.Clear(); } private double computeDrainRate() { - if (healthIncreases == null || healthIncreases.Count == 0) + if (healthIncreases.Count == 0) return 0; int adjustment = 1; From e030266e9575f3d24be45cc8fc3b61d88a32b182 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 27 Dec 2019 06:40:01 +0300 Subject: [PATCH 4803/5608] Fix test name --- osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs b/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs index 1572b813c0..7887002e1f 100644 --- a/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs +++ b/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs @@ -28,7 +28,7 @@ namespace osu.Game.Tests.Online [TestCase(true)] [TestCase(false)] - public void TestCancelDownloadFromRequest(bool closeFromRequest) + public void TestCancelDownloadRequest(bool closeFromRequest) { AddStep("download beatmap", () => beatmaps.Download(test_model)); From f03f310bde651aee3a608fc0b1928dbee2ae93c0 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 27 Dec 2019 06:43:43 +0300 Subject: [PATCH 4804/5608] Match file name --- ...{TestSceneBeatmapDownloading.cs => TestSceneBeatmapManager.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Tests/Online/{TestSceneBeatmapDownloading.cs => TestSceneBeatmapManager.cs} (100%) diff --git a/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs b/osu.Game.Tests/Online/TestSceneBeatmapManager.cs similarity index 100% rename from osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs rename to osu.Game.Tests/Online/TestSceneBeatmapManager.cs From c22744de2cc8df0ef116cfc4ca32f63ed25506b7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 27 Dec 2019 12:46:35 +0900 Subject: [PATCH 4805/5608] Better define minimum health targets --- .../Scoring/DrainingHealthProcessor.cs | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index ba29a9a0ce..34ede153dd 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -10,7 +10,10 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Scoring { /// - /// A which continuously drains health. + /// A which continuously drains health.
+ /// At HP=0, the minimum health reached for a perfect play is 95%.
+ /// At HP=5, the minimum health reached for a perfect play is 70%.
+ /// At HP=10, the minimum health reached for a perfect play is 30%. ///
public class DrainingHealthProcessor : HealthProcessor { @@ -19,6 +22,21 @@ namespace osu.Game.Rulesets.Scoring ///
private const double minimum_health_error = 0.01; + /// + /// The minimum health target at an HP drain rate of 0. + /// + private const double min_health_target = 0.95; + + /// + /// The minimum health target at an HP drain rate of 5. + /// + private const double mid_health_target = 0.70; + + /// + /// The minimum health target at an HP drain rate of 10. + /// + private const double max_health_target = 0.30; + private IBeatmap beatmap; private double gameplayEndTime; @@ -56,7 +74,7 @@ namespace osu.Game.Rulesets.Scoring if (beatmap.HitObjects.Count > 0) gameplayEndTime = beatmap.HitObjects[^1].GetEndTime(); - targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.95, 0.70, 0.30); + targetMinimumHealth = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, min_health_target, mid_health_target, max_health_target); base.ApplyBeatmap(beatmap); } From 35cdd67c4a184b1284e41e71205c54ac81a82c1c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 27 Dec 2019 12:47:23 +0900 Subject: [PATCH 4806/5608] Remove instantiation of non-existing processor --- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 203e37f91a..36346eb78a 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -38,8 +38,6 @@ namespace osu.Game.Rulesets.Osu public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(); - public override HealthProcessor CreateHealthProcessor(IBeatmap beatmap) => new OsuHealthProcessor(beatmap); - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap, this); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap); From 9f3c53cc0a896453857044e30098102078aa792b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 27 Dec 2019 13:02:54 +0900 Subject: [PATCH 4807/5608] Update resources --- osu.Android.props | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index e7f90af5fd..82bde17805 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -53,7 +53,7 @@
- + diff --git a/osu.iOS.props b/osu.iOS.props index edeeea239e..67da9eac95 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,7 +73,7 @@ - + From 9478fe5ec3830162fb4040bcd3fc3e0853548281 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 27 Dec 2019 13:15:55 +0900 Subject: [PATCH 4808/5608] Revert to using empty container, not null --- osu.Game/Overlays/OverlayHeader.cs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index 9e88273443..7a397d10c6 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.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 JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -37,14 +38,12 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - FillFlowContainer flow; - - Add(flow = new FillFlowContainer + Add(new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, - Children = new Drawable[] + Children = new[] { background = new Container { @@ -95,19 +94,16 @@ namespace osu.Game.Overlays Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, } } - } + }, + CreateContent() } }); - - var content = CreateContent(); - - if (content != null) - flow.Add(content); } protected abstract Drawable CreateBackground(); - protected virtual Drawable CreateContent() => null; + [NotNull] + protected virtual Drawable CreateContent() => new Container(); protected abstract ScreenTitle CreateTitle(); } From ea52bbea35820be055ea323ef4ee75aa0af582d2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 27 Dec 2019 14:05:48 +0900 Subject: [PATCH 4809/5608] 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 e7f90af5fd..2928464ba0 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 0c0a58d533..55400fb577 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 edeeea239e..489dbd7415 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From b330aec03e54447b0788c2029d13d55b1db70e6d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 27 Dec 2019 16:14:49 +0900 Subject: [PATCH 4810/5608] Drain starting at the first hitobject, not gameplay start --- .../Scoring/TaikoHealthProcessor.cs | 4 ++-- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- osu.Game/Rulesets/Ruleset.cs | 2 +- .../Scoring/AccumulatingHealthProcessor.cs | 4 +--- .../Rulesets/Scoring/DrainingHealthProcessor.cs | 15 +++++++++------ osu.Game/Rulesets/Scoring/HealthProcessor.cs | 14 -------------- osu.Game/Screens/Play/Player.cs | 2 +- 7 files changed, 15 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs index 279d119626..edb089dbac 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs @@ -30,8 +30,8 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// private double hpMissMultiplier; - public TaikoHealthProcessor(double gameplayStartTime) - : base(gameplayStartTime, 0.5) + public TaikoHealthProcessor() + : base(0.5) { } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 371236e47a..777b68a993 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Taiko public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(); - public override HealthProcessor CreateHealthProcessor(double gameplayStartTime) => new TaikoHealthProcessor(gameplayStartTime); + public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new TaikoHealthProcessor(); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap, this); diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index ff58d3c8dc..67ec6d15ea 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets /// Creates a for this . /// /// The health processor. - public virtual HealthProcessor CreateHealthProcessor(double gameplayStartTime) => new DrainingHealthProcessor(gameplayStartTime); + public virtual HealthProcessor CreateHealthProcessor(double drainStartTime) => new DrainingHealthProcessor(drainStartTime); /// /// Creates a to convert a to one that is applicable for this . diff --git a/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs index 540b4b8a1d..5dfb5167f4 100644 --- a/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs @@ -16,10 +16,8 @@ namespace osu.Game.Rulesets.Scoring /// /// Creates a new . /// - /// The gameplay start time. /// The minimum amount of health required to beatmap. - public AccumulatingHealthProcessor(double gameplayStartTime, double requiredHealth) - : base(gameplayStartTime) + public AccumulatingHealthProcessor(double requiredHealth) { this.requiredHealth = requiredHealth; } diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index 34ede153dd..fffcbb3c9f 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -38,8 +38,11 @@ namespace osu.Game.Rulesets.Scoring private const double max_health_target = 0.30; private IBeatmap beatmap; + private double gameplayEndTime; + private readonly double drainStartTime; + private readonly List<(double time, double health)> healthIncreases = new List<(double, double)>(); private double targetMinimumHealth; private double drainRate = 1; @@ -47,10 +50,10 @@ namespace osu.Game.Rulesets.Scoring /// /// Creates a new . /// - /// The gameplay start time. - public DrainingHealthProcessor(double gameplayStartTime) - : base(gameplayStartTime) + /// The time after which draining should begin. + public DrainingHealthProcessor(double drainStartTime) { + this.drainStartTime = drainStartTime; } protected override void Update() @@ -60,8 +63,8 @@ namespace osu.Game.Rulesets.Scoring if (!IsBreakTime.Value) { // When jumping in and out of gameplay time within a single frame, health should only be drained for the period within the gameplay time - double lastGameplayTime = Math.Clamp(Time.Current - Time.Elapsed, GameplayStartTime, gameplayEndTime); - double currentGameplayTime = Math.Clamp(Time.Current, GameplayStartTime, gameplayEndTime); + double lastGameplayTime = Math.Clamp(Time.Current - Time.Elapsed, drainStartTime, gameplayEndTime); + double currentGameplayTime = Math.Clamp(Time.Current, drainStartTime, gameplayEndTime); Health.Value -= drainRate * (currentGameplayTime - lastGameplayTime); } @@ -116,7 +119,7 @@ namespace osu.Game.Rulesets.Scoring for (int i = 0; i < healthIncreases.Count; i++) { double currentTime = healthIncreases[i].time; - double lastTime = i > 0 ? healthIncreases[i - 1].time : GameplayStartTime; + double lastTime = i > 0 ? healthIncreases[i - 1].time : drainStartTime; // Subtract any break time from the duration since the last object if (beatmap.Breaks.Count > 0) diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index d8addc2b4d..0c6b3f67b4 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -36,20 +36,6 @@ namespace osu.Game.Rulesets.Scoring /// public bool HasFailed { get; private set; } - /// - /// The gameplay start time. - /// - protected readonly double GameplayStartTime; - - /// - /// Creates a new . - /// - /// The gameplay start time. - protected HealthProcessor(double gameplayStartTime) - { - GameplayStartTime = gameplayStartTime; - } - protected override void ApplyResultInternal(JudgementResult result) { result.HealthAtJudgement = Health.Value; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a3d512cdaa..7228e22382 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -135,7 +135,7 @@ namespace osu.Game.Screens.Play ScoreProcessor.ApplyBeatmap(playableBeatmap); ScoreProcessor.Mods.BindTo(Mods); - HealthProcessor = ruleset.CreateHealthProcessor(DrawableRuleset.GameplayStartTime); + HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime); HealthProcessor.ApplyBeatmap(playableBeatmap); if (!ScoreProcessor.Mode.Disabled) From 7507fee9f9657479602104aa17de5926aaa373ad Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 27 Dec 2019 16:55:46 +0900 Subject: [PATCH 4811/5608] Add test for HP rewind --- .../Gameplay/TestSceneDrainingHealthProcessor.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs index 4996c86e5d..eec52669ff 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs @@ -75,6 +75,16 @@ namespace osu.Game.Tests.Gameplay assertHealthNotEqualTo(1); } + [Test] + public void TestHealthGainedAfterRewind() + { + createProcessor(createBeatmap(0, 1000)); + setTime(500); + + setTime(0); + assertHealthEqualTo(1); + } + [Test] public void TestHealthGainedOnHit() { From 2c8879f0fb7f2f754725274821a707ff95c77af1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 27 Dec 2019 19:05:17 +0900 Subject: [PATCH 4812/5608] Lock user adjusted difficulty settings when changing beatmap --- .../Mods/CatchModDifficultyAdjust.cs | 4 +-- .../Mods/OsuModDifficultyAdjust.cs | 4 +-- osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 30 +++++++++++++++++-- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs index 4c0f5d510e..8377b3786a 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs @@ -34,8 +34,8 @@ namespace osu.Game.Rulesets.Catch.Mods { base.TransferSettings(difficulty); - CircleSize.Value = CircleSize.Default = difficulty.CircleSize; - ApproachRate.Value = ApproachRate.Default = difficulty.ApproachRate; + TransferSetting(CircleSize, difficulty.CircleSize); + TransferSetting(ApproachRate, difficulty.ApproachRate); } protected override void ApplySettings(BeatmapDifficulty difficulty) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs index 0514e2ab34..7eee71be81 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs @@ -34,8 +34,8 @@ namespace osu.Game.Rulesets.Osu.Mods { base.TransferSettings(difficulty); - CircleSize.Value = CircleSize.Default = difficulty.CircleSize; - ApproachRate.Value = ApproachRate.Default = difficulty.ApproachRate; + TransferSetting(CircleSize, difficulty.CircleSize); + TransferSetting(ApproachRate, difficulty.ApproachRate); } protected override void ApplySettings(BeatmapDifficulty difficulty) diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs index 7b8d4bb3df..1c26e5a720 100644 --- a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -5,6 +5,7 @@ using osu.Game.Beatmaps; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using System; +using System.Collections.Generic; using osu.Game.Configuration; namespace osu.Game.Rulesets.Mods @@ -51,8 +52,8 @@ namespace osu.Game.Rulesets.Mods { if (this.difficulty == null || this.difficulty.ID != difficulty.ID) { - this.difficulty = difficulty; TransferSettings(difficulty); + this.difficulty = difficulty; } } @@ -64,8 +65,31 @@ namespace osu.Game.Rulesets.Mods /// The beatmap's initial values. protected virtual void TransferSettings(BeatmapDifficulty difficulty) { - DrainRate.Value = DrainRate.Default = difficulty.DrainRate; - OverallDifficulty.Value = OverallDifficulty.Default = difficulty.OverallDifficulty; + TransferSetting(DrainRate, difficulty.DrainRate); + TransferSetting(OverallDifficulty, difficulty.OverallDifficulty); + } + + private readonly Dictionary userChangedSettings = new Dictionary(); + + /// + /// Transfer a setting from to a configuration bindable. + /// Only performs the transfer if the user it not currently overriding.. + /// + protected void TransferSetting(BindableNumber bindable, T beatmapDefault) + where T : struct, IComparable, IConvertible, IEquatable + { + bindable.UnbindEvents(); + + userChangedSettings.TryAdd(bindable, false); + + // users generally choose a difficulty setting and want it to stick across multiple beatmap changes. + // we only want to value transfer if the user hasn't changed the value previously. + if (!userChangedSettings[bindable]) + { + bindable.Value = bindable.Default = beatmapDefault; + } + + bindable.ValueChanged += _ => userChangedSettings[bindable] = !bindable.IsDefault; } /// From ca862124a5b7cae97ddba65176e92003e77400c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 27 Dec 2019 19:36:48 +0900 Subject: [PATCH 4813/5608] Fix replay import from main menu causing a hard crash --- osu.Game/Screens/Play/PlayerLoader.cs | 30 ++++++++++----------- osu.Game/Screens/Play/ReplayPlayerLoader.cs | 8 +++--- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 57021dfc68..64fcc48004 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -118,8 +118,6 @@ namespace osu.Game.Screens.Play }, idleTracker = new IdleTracker(750) }); - - loadNewPlayer(); } protected override void LoadComplete() @@ -127,6 +125,21 @@ namespace osu.Game.Screens.Play base.LoadComplete(); inputManager = GetContainingInputManager(); + } + + public override void OnEntering(IScreen last) + { + base.OnEntering(last); + + loadNewPlayer(); + + content.ScaleTo(0.7f); + Background?.FadeColour(Color4.White, 800, Easing.OutQuint); + + contentIn(); + + info.Delay(750).FadeIn(500); + this.Delay(1800).Schedule(pushWhenLoaded); if (!muteWarningShownOnce.Value) { @@ -179,19 +192,6 @@ namespace osu.Game.Screens.Play content.FadeOut(250); } - public override void OnEntering(IScreen last) - { - base.OnEntering(last); - - content.ScaleTo(0.7f); - Background?.FadeColour(Color4.White, 800, Easing.OutQuint); - - contentIn(); - - info.Delay(750).FadeIn(500); - this.Delay(1800).Schedule(pushWhenLoaded); - } - protected override void LogoArriving(OsuLogo logo, bool resuming) { base.LogoArriving(logo, resuming); diff --git a/osu.Game/Screens/Play/ReplayPlayerLoader.cs b/osu.Game/Screens/Play/ReplayPlayerLoader.cs index c8ca604902..4572570437 100644 --- a/osu.Game/Screens/Play/ReplayPlayerLoader.cs +++ b/osu.Game/Screens/Play/ReplayPlayerLoader.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Allocation; +using osu.Framework.Screens; using osu.Game.Scoring; namespace osu.Game.Screens.Play @@ -20,15 +20,13 @@ namespace osu.Game.Screens.Play scoreInfo = score.ScoreInfo; } - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + public override void OnEntering(IScreen last) { - var dependencies = base.CreateChildDependencies(parent); - // these will be reverted thanks to PlayerLoader's lease. Mods.Value = scoreInfo.Mods; Ruleset.Value = scoreInfo.Ruleset; - return dependencies; + base.OnEntering(last); } } } From 6069d98ceda7bd4d036f2a28cb2511e39c43fd7b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 27 Dec 2019 19:39:30 +0900 Subject: [PATCH 4814/5608] Remove generic editor beatmap --- .../TestSceneOsuDistanceSnapGrid.cs | 4 +- .../Edit/OsuHitObjectComposer.cs | 6 +- osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs | 14 ++-- ...tSceneHitObjectComposerDistanceSnapping.cs | 3 +- .../Editor/TestSceneDistanceSnapGrid.cs | 5 +- .../Editor/TestSceneEditorComposeTimeline.cs | 2 +- .../Edit/DrawableEditRulesetWrapper.cs | 2 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 5 +- osu.Game/Screens/Edit/EditorBeatmap.cs | 75 ++++++++++--------- osu.Game/Screens/Edit/IEditorBeatmap.cs | 13 +--- 10 files changed, 59 insertions(+), 70 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index eff4d919b0..75c57467c3 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Tests }; [Cached(typeof(IEditorBeatmap))] - private readonly EditorBeatmap editorBeatmap; + private readonly EditorBeatmap editorBeatmap; [Cached] private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Tests public TestSceneOsuDistanceSnapGrid() { - editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + editorBeatmap = new EditorBeatmap(new OsuBeatmap()); } [SetUp] diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index a2c1a5f5f4..49624ea733 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -91,10 +91,10 @@ namespace osu.Game.Rulesets.Osu.Edit if (sourceIndex == -1) return null; - OsuHitObject sourceObject = EditorBeatmap.HitObjects[sourceIndex]; + HitObject sourceObject = EditorBeatmap.HitObjects[sourceIndex]; int targetIndex = sourceIndex + targetOffset; - OsuHitObject targetObject = null; + HitObject targetObject = null; // Keep advancing the target object while its start time falls before the end time of the source object while (true) @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Osu.Edit targetIndex++; } - return new OsuDistanceSnapGrid(sourceObject, targetObject); + return new OsuDistanceSnapGrid((OsuHitObject)sourceObject, (OsuHitObject)targetObject); } } } diff --git a/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs b/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs index 98e630abd2..12d729d09f 100644 --- a/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/EditorBeatmapTest.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestHitObjectAddEvent() { - var editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + var editorBeatmap = new EditorBeatmap(new OsuBeatmap()); HitObject addedObject = null; editorBeatmap.HitObjectAdded += h => addedObject = h; @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Beatmaps public void HitObjectRemoveEvent() { var hitCircle = new HitCircle(); - var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); + var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); HitObject removedObject = null; editorBeatmap.HitObjectRemoved += h => removedObject = h; @@ -55,7 +55,7 @@ namespace osu.Game.Tests.Beatmaps public void TestInitialHitObjectStartTimeChangeEvent() { var hitCircle = new HitCircle(); - var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); + var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); HitObject changedObject = null; editorBeatmap.StartTimeChanged += h => changedObject = h; @@ -71,7 +71,7 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestAddedHitObjectStartTimeChangeEvent() { - var editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + var editorBeatmap = new EditorBeatmap(new OsuBeatmap()); HitObject changedObject = null; editorBeatmap.StartTimeChanged += h => changedObject = h; @@ -92,7 +92,7 @@ namespace osu.Game.Tests.Beatmaps public void TestRemovedHitObjectStartTimeChangeEvent() { var hitCircle = new HitCircle(); - var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); + var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } }); HitObject changedObject = null; editorBeatmap.StartTimeChanged += h => changedObject = h; @@ -110,7 +110,7 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestAddHitObjectInMiddle() { - var editorBeatmap = new EditorBeatmap(new OsuBeatmap + var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { @@ -134,7 +134,7 @@ namespace osu.Game.Tests.Beatmaps public void TestResortWhenStartTimeChanged() { var hitCircle = new HitCircle { StartTime = 1000 }; - var editorBeatmap = new EditorBeatmap(new OsuBeatmap + var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { diff --git a/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs b/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs index fe3cc375ea..b94f08aeaa 100644 --- a/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs +++ b/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs @@ -6,7 +6,6 @@ using osu.Framework.Testing; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Edit; -using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit; using osu.Game.Tests.Visual; @@ -183,7 +182,7 @@ namespace osu.Game.Tests.Editor private class TestHitObjectComposer : OsuHitObjectComposer { - public new EditorBeatmap EditorBeatmap => base.EditorBeatmap; + public new EditorBeatmap EditorBeatmap => base.EditorBeatmap; public TestHitObjectComposer() : base(new OsuRuleset()) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index 39b4bf7218..83b1f43f38 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Beatmaps; -using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose.Components; using osuTK; @@ -22,14 +21,14 @@ namespace osu.Game.Tests.Visual.Editor private static readonly Vector2 grid_position = new Vector2(512, 384); [Cached(typeof(IEditorBeatmap))] - private readonly EditorBeatmap editorBeatmap; + private readonly EditorBeatmap editorBeatmap; [Cached(typeof(IDistanceSnapProvider))] private readonly SnapProvider snapProvider = new SnapProvider(); public TestSceneDistanceSnapGrid() { - editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + editorBeatmap = new EditorBeatmap(new OsuBeatmap()); editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index ed6bc5fe0c..29575cb42e 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Editor { Beatmap.Value = new WaveformTestBeatmap(audio); - var editorBeatmap = new EditorBeatmap((Beatmap)Beatmap.Value.Beatmap); + var editorBeatmap = new EditorBeatmap((Beatmap)Beatmap.Value.Beatmap); Children = new Drawable[] { diff --git a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs index 4710465536..ab2332ea86 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Edit private readonly DrawableRuleset drawableRuleset; [Resolved] - private IEditorBeatmap beatmap { get; set; } + private IEditorBeatmap beatmap { get; set; } public DrawableEditRulesetWrapper(DrawableRuleset drawableRuleset) { diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 22d94abcb9..a550cf4a02 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Edit { protected IRulesetConfigManager Config { get; private set; } - protected new EditorBeatmap EditorBeatmap { get; private set; } + protected new EditorBeatmap EditorBeatmap { get; private set; } protected readonly Ruleset Ruleset; @@ -148,14 +148,13 @@ namespace osu.Game.Rulesets.Edit beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap); - base.EditorBeatmap = EditorBeatmap = new EditorBeatmap(playableBeatmap); + base.EditorBeatmap = EditorBeatmap = new EditorBeatmap(playableBeatmap); EditorBeatmap.HitObjectAdded += addHitObject; EditorBeatmap.HitObjectRemoved += removeHitObject; EditorBeatmap.StartTimeChanged += UpdateHitObject; var dependencies = new DependencyContainer(parent); dependencies.CacheAs(EditorBeatmap); - dependencies.CacheAs>(EditorBeatmap); Config = dependencies.Get().GetConfigFor(Ruleset); diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index c3a322ea36..5a45ea05a0 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections; using System.Collections.Generic; using osu.Framework.Bindables; using osu.Game.Beatmaps; @@ -11,28 +12,27 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Edit { - public class EditorBeatmap : IEditorBeatmap - where T : HitObject + public class EditorBeatmap : IEditorBeatmap { /// - /// Invoked when a is added to this . + /// Invoked when a is added to this . /// public event Action HitObjectAdded; /// - /// Invoked when a is removed from this . + /// Invoked when a is removed from this . /// public event Action HitObjectRemoved; /// - /// Invoked when the start time of a in this was changed. + /// Invoked when the start time of a in this was changed. /// public event Action StartTimeChanged; - private readonly Dictionary> startTimeBindables = new Dictionary>(); - private readonly Beatmap beatmap; + private readonly Dictionary> startTimeBindables = new Dictionary>(); + private readonly IBeatmap beatmap; - public EditorBeatmap(Beatmap beatmap) + public EditorBeatmap(IBeatmap beatmap) { this.beatmap = beatmap; @@ -54,70 +54,71 @@ namespace osu.Game.Screens.Edit public double TotalBreakTime => beatmap.TotalBreakTime; - public IReadOnlyList HitObjects => beatmap.HitObjects; + public IReadOnlyList HitObjects => beatmap.HitObjects; IReadOnlyList IBeatmap.HitObjects => beatmap.HitObjects; public IEnumerable GetStatistics() => beatmap.GetStatistics(); - public IBeatmap Clone() => (EditorBeatmap)MemberwiseClone(); + public IBeatmap Clone() => (EditorBeatmap)MemberwiseClone(); /// - /// Adds a to this . + /// Adds a to this . /// /// The to add. - public void Add(T hitObject) + public void Add(HitObject hitObject) { trackStartTime(hitObject); // Preserve existing sorting order in the beatmap - var insertionIndex = beatmap.HitObjects.FindLastIndex(h => h.StartTime <= hitObject.StartTime); - beatmap.HitObjects.Insert(insertionIndex + 1, hitObject); + var insertionIndex = findInsertionIndex(beatmap.HitObjects, hitObject.StartTime); + ((IList)beatmap.HitObjects).Insert(insertionIndex + 1, hitObject); HitObjectAdded?.Invoke(hitObject); } /// - /// Removes a from this . + /// Removes a from this . /// /// The to add. - public void Remove(T hitObject) + public void Remove(HitObject hitObject) { - if (beatmap.HitObjects.Remove(hitObject)) - { - var bindable = startTimeBindables[hitObject]; - bindable.UnbindAll(); + if (!((IList)beatmap.HitObjects).Contains(hitObject)) + return; - startTimeBindables.Remove(hitObject); - HitObjectRemoved?.Invoke(hitObject); - } + ((IList)beatmap.HitObjects).Remove(hitObject); + + var bindable = startTimeBindables[hitObject]; + bindable.UnbindAll(); + + startTimeBindables.Remove(hitObject); + HitObjectRemoved?.Invoke(hitObject); } - private void trackStartTime(T hitObject) + private void trackStartTime(HitObject hitObject) { startTimeBindables[hitObject] = hitObject.StartTimeBindable.GetBoundCopy(); startTimeBindables[hitObject].ValueChanged += _ => { // For now we'll remove and re-add the hitobject. This is not optimal and can be improved if required. - beatmap.HitObjects.Remove(hitObject); + ((IList)beatmap.HitObjects).Remove(hitObject); - var insertionIndex = beatmap.HitObjects.FindLastIndex(h => h.StartTime <= hitObject.StartTime); - beatmap.HitObjects.Insert(insertionIndex + 1, hitObject); + var insertionIndex = findInsertionIndex(beatmap.HitObjects, hitObject.StartTime); + ((IList)beatmap.HitObjects).Insert(insertionIndex + 1, hitObject); StartTimeChanged?.Invoke(hitObject); }; } - /// - /// Adds a to this . - /// - /// The to add. - public void Add(HitObject hitObject) => Add((T)hitObject); + private int findInsertionIndex(IReadOnlyList list, double startTime) + { + for (int i = 0; i < list.Count; i++) + { + if (list[i].StartTime > startTime) + return i - 1; + } - /// - /// Removes a from this . - /// - /// The to add. - public void Remove(HitObject hitObject) => Remove((T)hitObject); + return list.Count - 1; + } } } diff --git a/osu.Game/Screens/Edit/IEditorBeatmap.cs b/osu.Game/Screens/Edit/IEditorBeatmap.cs index 3e3418ef79..df4efd289e 100644 --- a/osu.Game/Screens/Edit/IEditorBeatmap.cs +++ b/osu.Game/Screens/Edit/IEditorBeatmap.cs @@ -10,7 +10,7 @@ namespace osu.Game.Screens.Edit { /// /// Interface for the contained by the see . - /// Children of may resolve the beatmap via or . + /// Children of may resolve the beatmap via . /// public interface IEditorBeatmap : IBeatmap { @@ -25,17 +25,8 @@ namespace osu.Game.Screens.Edit event Action HitObjectRemoved; /// - /// Invoked when the start time of a in this was changed. + /// Invoked when the start time of a in this was changed. /// event Action StartTimeChanged; } - - /// - /// Interface for the contained by the see . - /// Children of may resolve the beatmap via or . - /// - public interface IEditorBeatmap : IEditorBeatmap, IBeatmap - where T : HitObject - { - } } From 651abd2e119520b9ff7d46f277040722342e8a33 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 27 Dec 2019 21:51:18 +0900 Subject: [PATCH 4815/5608] 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 a43c834406..6ff9416e47 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 3f64ce8dfd..806aadde84 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 c2d4e3ad8e..230ff01cce 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 5efb7e801552d4a61bb407ad54728d05f9ab2c0d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 27 Dec 2019 23:01:52 +0900 Subject: [PATCH 4816/5608] Always update default value --- osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs index 1c26e5a720..c5b8a1bc73 100644 --- a/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs +++ b/osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs @@ -82,12 +82,12 @@ namespace osu.Game.Rulesets.Mods userChangedSettings.TryAdd(bindable, false); + bindable.Default = beatmapDefault; + // users generally choose a difficulty setting and want it to stick across multiple beatmap changes. // we only want to value transfer if the user hasn't changed the value previously. if (!userChangedSettings[bindable]) - { - bindable.Value = bindable.Default = beatmapDefault; - } + bindable.Value = beatmapDefault; bindable.ValueChanged += _ => userChangedSettings[bindable] = !bindable.IsDefault; } From e2a55b79cac9c4bc9c5a95dbf2122baef3fd3f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 27 Dec 2019 16:47:46 +0100 Subject: [PATCH 4817/5608] Refactor scrolling hit object scene To better demonstrate the desired effect of the fix introduced in 193e41f, refactor TestSceneScrollingHitObjects to contain two tests, one of which contains the pre-existing controls to test scroll algorithms, and the other aims to showcase the fix by setting scroll parameters appropriately. --- .../Gameplay/TestSceneScrollingHitObjects.cs | 60 +++++++++++++------ 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs index 7ab53b2d65..922001f3dd 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs @@ -3,12 +3,14 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Threading; using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; @@ -28,12 +30,16 @@ namespace osu.Game.Tests.Visual.Gameplay [Cached(typeof(IReadOnlyList))] private IReadOnlyList mods { get; set; } = Array.Empty(); + private const int spawn_interval = 5000; + private readonly ScrollingTestContainer[] scrollContainers = new ScrollingTestContainer[4]; private readonly TestPlayfield[] playfields = new TestPlayfield[4]; + private ScheduledDelegate hitObjectSpawnDelegate; - public TestSceneScrollingHitObjects() + [SetUp] + public void Setup() { - Add(new GridContainer + Child = new GridContainer { RelativeSizeAxes = Axes.Both, Content = new[] @@ -43,12 +49,14 @@ namespace osu.Game.Tests.Visual.Gameplay scrollContainers[0] = new ScrollingTestContainer(ScrollingDirection.Up) { RelativeSizeAxes = Axes.Both, - Child = playfields[0] = new TestPlayfield() + Child = playfields[0] = new TestPlayfield(), + TimeRange = spawn_interval }, scrollContainers[1] = new ScrollingTestContainer(ScrollingDirection.Down) { RelativeSizeAxes = Axes.Both, - Child = playfields[1] = new TestPlayfield() + Child = playfields[1] = new TestPlayfield(), + TimeRange = spawn_interval }, }, new Drawable[] @@ -56,35 +64,51 @@ namespace osu.Game.Tests.Visual.Gameplay scrollContainers[2] = new ScrollingTestContainer(ScrollingDirection.Left) { RelativeSizeAxes = Axes.Both, - Child = playfields[2] = new TestPlayfield() + Child = playfields[2] = new TestPlayfield(), + TimeRange = spawn_interval }, scrollContainers[3] = new ScrollingTestContainer(ScrollingDirection.Right) { RelativeSizeAxes = Axes.Both, - Child = playfields[3] = new TestPlayfield() + Child = playfields[3] = new TestPlayfield(), + TimeRange = spawn_interval } } } - }); + }; + setUpHitObjects(); + } + + private void setUpHitObjects() + { + scrollContainers.ForEach(c => c.ControlPoints.Add(new MultiplierControlPoint(0))); + + for (int i = 0; i <= spawn_interval; i += 1000) + addHitObject(Time.Current + i); + + hitObjectSpawnDelegate?.Cancel(); + hitObjectSpawnDelegate = Scheduler.AddDelayed(() => addHitObject(Time.Current + spawn_interval), 1000, true); + } + + [Test] + public void TestScrollAlgorithms() + { AddStep("Constant scroll", () => setScrollAlgorithm(ScrollVisualisationMethod.Constant)); AddStep("Overlapping scroll", () => setScrollAlgorithm(ScrollVisualisationMethod.Overlapping)); AddStep("Sequential scroll", () => setScrollAlgorithm(ScrollVisualisationMethod.Sequential)); - AddSliderStep("Time range", 100, 10000, 5000, v => scrollContainers.ForEach(c => c.TimeRange = v)); - AddStep("Add control point", () => addControlPoint(Time.Current + 5000)); + AddSliderStep("Time range", 100, 10000, spawn_interval, v => scrollContainers.Where(c => c != null).ForEach(c => c.TimeRange = v)); + AddStep("Add control point", () => addControlPoint(Time.Current + spawn_interval)); } - protected override void LoadComplete() + [Test] + public void TestScrollLifetime() { - base.LoadComplete(); - - scrollContainers.ForEach(c => c.ControlPoints.Add(new MultiplierControlPoint(0))); - - for (int i = 0; i <= 5000; i += 1000) - addHitObject(Time.Current + i); - - Scheduler.AddDelayed(() => addHitObject(Time.Current + 5000), 1000, true); + AddStep("Set constant scroll", () => setScrollAlgorithm(ScrollVisualisationMethod.Constant)); + // scroll container time range must be less than the rate of spawning hitobjects + // otherwise the hitobjects will spawn already partly visible on screen and look wrong + AddStep("Set time range", () => scrollContainers.ForEach(c => c.TimeRange = spawn_interval / 2.0)); } private void addHitObject(double time) From d828b31ae4b1582ef901f06499a83bd2eec3d3b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 27 Dec 2019 17:16:43 +0100 Subject: [PATCH 4818/5608] Schedule child mutation in test setup --- .../Visual/Gameplay/TestSceneScrollingHitObjects.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs index 922001f3dd..8629522dc2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs @@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual.Gameplay private ScheduledDelegate hitObjectSpawnDelegate; [SetUp] - public void Setup() + public void Setup() => Schedule(() => { Child = new GridContainer { @@ -78,7 +78,7 @@ namespace osu.Game.Tests.Visual.Gameplay }; setUpHitObjects(); - } + }); private void setUpHitObjects() { From f2ff57d6b7bad548b99c4cc780e95cac9b15b687 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 28 Dec 2019 02:50:52 +0300 Subject: [PATCH 4819/5608] Update design of OverlayHeaderTabControl --- osu.Game/Overlays/OverlayHeader.cs | 5 ++--- osu.Game/Overlays/OverlayHeaderTabControl.cs | 21 ++++++++++++++++++++ osu.Game/Overlays/OverlayTabControl.cs | 16 +++++++++------ osu.Game/Overlays/Profile/ProfileHeader.cs | 4 ++-- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index 7a397d10c6..d406fc2b8a 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -89,9 +89,8 @@ namespace osu.Game.Overlays { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Height = 30, - Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, + Height = 35, + Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN } } } }, diff --git a/osu.Game/Overlays/OverlayHeaderTabControl.cs b/osu.Game/Overlays/OverlayHeaderTabControl.cs index 7d0cdad6d8..1ddface2b7 100644 --- a/osu.Game/Overlays/OverlayHeaderTabControl.cs +++ b/osu.Game/Overlays/OverlayHeaderTabControl.cs @@ -2,22 +2,43 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.UserInterface; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osuTK; +using osu.Game.Graphics; namespace osu.Game.Overlays { public class OverlayHeaderTabControl : OverlayTabControl { + public OverlayHeaderTabControl() + { + BarHeight = 1; + RelativeSizeAxes = Axes.None; + AutoSizeAxes = Axes.X; + } + protected override TabItem CreateTabItem(string value) => new OverlayHeaderTabItem(value) { AccentColour = AccentColour, }; + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + }; + private class OverlayHeaderTabItem : OverlayTabItem { public OverlayHeaderTabItem(string value) : base(value) { Text.Text = value; + Text.Font = OsuFont.GetFont(size: 14); + Bar.ExpandedSize = 5; } } } diff --git a/osu.Game/Overlays/OverlayTabControl.cs b/osu.Game/Overlays/OverlayTabControl.cs index 4c396eabc1..812f8963c9 100644 --- a/osu.Game/Overlays/OverlayTabControl.cs +++ b/osu.Game/Overlays/OverlayTabControl.cs @@ -43,6 +43,11 @@ namespace osu.Game.Overlays set => TabContainer.Padding = value; } + protected float BarHeight + { + set => bar.Height = value; + } + protected OverlayTabControl() { TabContainer.Masking = false; @@ -63,8 +68,7 @@ namespace osu.Game.Overlays protected class OverlayTabItem : TabItem { - private readonly ExpandingBar bar; - + protected readonly ExpandingBar Bar; protected readonly OsuSpriteText Text; private Color4 accentColour; @@ -78,7 +82,7 @@ namespace osu.Game.Overlays return; accentColour = value; - bar.Colour = value; + Bar.Colour = value; updateState(); } @@ -99,7 +103,7 @@ namespace osu.Game.Overlays Anchor = Anchor.BottomLeft, Font = OsuFont.GetFont(), }, - bar = new ExpandingBar + Bar = new ExpandingBar { Anchor = Anchor.BottomCentre, ExpandedSize = 7.5f, @@ -149,13 +153,13 @@ namespace osu.Game.Overlays protected virtual void HoverAction() { - bar.Expand(); + Bar.Expand(); Text.FadeColour(Color4.White, 120, Easing.InQuad); } protected virtual void UnhoverAction() { - bar.Collapse(); + Bar.Collapse(); Text.FadeColour(AccentColour, 120, Easing.InQuad); } } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 4a792f7375..077941df6c 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -30,8 +30,8 @@ namespace osu.Game.Overlays.Profile User.ValueChanged += e => updateDisplay(e.NewValue); - TabControl.AddItem("Info"); - TabControl.AddItem("Modding"); + TabControl.AddItem("info"); + TabControl.AddItem("modding"); centreHeaderContainer.DetailsVisible.BindValueChanged(visible => detailHeaderContainer.Expanded = visible.NewValue, true); } From ac2280c4efee1fdb06b829ad32041102140e7197 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 28 Dec 2019 04:57:41 +0300 Subject: [PATCH 4820/5608] Implement BreadcrumbControlOverlayHeader --- .../UserInterface/BreadcrumbControl.cs | 17 +++++----- .../BreadcrumbControlOverlayHeader.cs | 10 ++++++ .../Overlays/Changelog/ChangelogHeader.cs | 4 +-- osu.Game/Overlays/News/NewsHeader.cs | 2 +- osu.Game/Overlays/OverlayHeader.cs | 16 ++++------ .../OverlayHeaderBreadcrumbControl.cs | 32 +++++++++++++++++++ osu.Game/Overlays/OverlayHeaderTabControl.cs | 3 ++ osu.Game/Overlays/Profile/ProfileHeader.cs | 2 +- osu.Game/Overlays/TabControlOverlayHeader.cs | 10 ++++++ 9 files changed, 75 insertions(+), 21 deletions(-) create mode 100644 osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs create mode 100644 osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs create mode 100644 osu.Game/Overlays/TabControlOverlayHeader.cs diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index 93ea6bbbe6..d96aa4b486 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -15,17 +15,18 @@ namespace osu.Game.Graphics.UserInterface public class BreadcrumbControl : OsuTabControl { private const float padding = 10; - private const float item_chevron_size = 10; + private float itemChevronSize; - protected override TabItem CreateTabItem(T value) => new BreadcrumbTabItem(value) + protected override TabItem CreateTabItem(T value) => new BreadcrumbTabItem(value, itemChevronSize) { AccentColour = AccentColour, }; - protected override float StripWidth() => base.StripWidth() - (padding + item_chevron_size); + protected override float StripWidth() => base.StripWidth() - (padding + itemChevronSize); - public BreadcrumbControl() + public BreadcrumbControl(float itemChevronSize = 10) { + this.itemChevronSize = itemChevronSize; Height = 32; TabContainer.Spacing = new Vector2(padding, 0f); Current.ValueChanged += index => @@ -41,7 +42,7 @@ namespace osu.Game.Graphics.UserInterface }; } - private class BreadcrumbTabItem : OsuTabItem, IStateful + protected class BreadcrumbTabItem : OsuTabItem, IStateful { public event Action StateChanged; @@ -85,17 +86,17 @@ namespace osu.Game.Graphics.UserInterface public override void Show() => State = Visibility.Visible; - public BreadcrumbTabItem(T value) + public BreadcrumbTabItem(T value, float itemChevronSize) : base(value) { Text.Font = Text.Font.With(size: 18); Text.Margin = new MarginPadding { Vertical = 8 }; - Padding = new MarginPadding { Right = padding + item_chevron_size }; + Padding = new MarginPadding { Right = padding + itemChevronSize }; Add(Chevron = new SpriteIcon { Anchor = Anchor.CentreRight, Origin = Anchor.CentreLeft, - Size = new Vector2(item_chevron_size), + Size = new Vector2(itemChevronSize), Icon = FontAwesome.Solid.ChevronRight, Margin = new MarginPadding { Left = padding }, Alpha = 0f, diff --git a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs new file mode 100644 index 0000000000..10664fc5be --- /dev/null +++ b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs @@ -0,0 +1,10 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Overlays +{ + public abstract class BreadcrumbControlOverlayHeader : OverlayHeader + { + protected override OverlayHeaderBreadcrumbControl CreateControl() => new OverlayHeaderBreadcrumbControl(); + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 3b6f0d778d..ddf07e4b50 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -15,7 +15,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Changelog { - public class ChangelogHeader : OverlayHeader + public class ChangelogHeader : BreadcrumbControlOverlayHeader { public readonly Bindable Current = new Bindable(); @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Changelog public UpdateStreamBadgeArea Streams; - private const string listing_string = "Listing"; + private const string listing_string = "listing"; public ChangelogHeader() { diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index e3cf58ed0a..2cbe2fa04e 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -12,7 +12,7 @@ using System; namespace osu.Game.Overlays.News { - public class NewsHeader : OverlayHeader + public class NewsHeader : BreadcrumbControlOverlayHeader { private const string front_page_string = "frontpage"; diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index d406fc2b8a..da7cfd0ce7 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -5,14 +5,16 @@ using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osuTK.Graphics; namespace osu.Game.Overlays { - public abstract class OverlayHeader : Container + public abstract class OverlayHeader : Container + where TModel : TabControl { - protected readonly OverlayHeaderTabControl TabControl; + protected readonly TModel TabControl; private readonly Box titleBackground; private readonly Box controlBackground; @@ -85,13 +87,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Colour = Color4.Gray, }, - TabControl = new OverlayHeaderTabControl - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Height = 35, - Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN } - } + TabControl = CreateControl().With(control => control.Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }) } }, CreateContent() @@ -105,5 +101,7 @@ namespace osu.Game.Overlays protected virtual Drawable CreateContent() => new Container(); protected abstract ScreenTitle CreateTitle(); + + protected abstract TModel CreateControl(); } } diff --git a/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs b/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs new file mode 100644 index 0000000000..d772aa0d46 --- /dev/null +++ b/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs @@ -0,0 +1,32 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Graphics.UserInterface; +using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; + +namespace osu.Game.Overlays +{ + public class OverlayHeaderBreadcrumbControl : BreadcrumbControl + { + private const float item_chevron_size = 8; + + public OverlayHeaderBreadcrumbControl() + : base(item_chevron_size) + { + RelativeSizeAxes = Axes.X; + } + + protected override TabItem CreateTabItem(string value) => new ControlTabItem(value, item_chevron_size); + + private class ControlTabItem : BreadcrumbTabItem + { + public ControlTabItem(string value, float itemChevronSize) + : base(value, itemChevronSize) + { + Text.Font = Text.Font.With(size: 14); + Chevron.Y = 3; + } + } + } +} diff --git a/osu.Game/Overlays/OverlayHeaderTabControl.cs b/osu.Game/Overlays/OverlayHeaderTabControl.cs index 1ddface2b7..7e11e066c7 100644 --- a/osu.Game/Overlays/OverlayHeaderTabControl.cs +++ b/osu.Game/Overlays/OverlayHeaderTabControl.cs @@ -16,6 +16,9 @@ namespace osu.Game.Overlays BarHeight = 1; RelativeSizeAxes = Axes.None; AutoSizeAxes = Axes.X; + Anchor = Anchor.BottomLeft; + Origin = Anchor.BottomLeft; + Height = 35; } protected override TabItem CreateTabItem(string value) => new OverlayHeaderTabItem(value) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 077941df6c..59e64dfc26 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -15,7 +15,7 @@ using osu.Game.Users; namespace osu.Game.Overlays.Profile { - public class ProfileHeader : OverlayHeader + public class ProfileHeader : TabControlOverlayHeader { private UserCoverBackground coverContainer; diff --git a/osu.Game/Overlays/TabControlOverlayHeader.cs b/osu.Game/Overlays/TabControlOverlayHeader.cs new file mode 100644 index 0000000000..8570bf63b8 --- /dev/null +++ b/osu.Game/Overlays/TabControlOverlayHeader.cs @@ -0,0 +1,10 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Overlays +{ + public abstract class TabControlOverlayHeader : OverlayHeader + { + protected override OverlayHeaderTabControl CreateControl() => new OverlayHeaderTabControl(); + } +} From 7af622426a1f208142b1fe39afc4a18faaeaa5b0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 28 Dec 2019 05:11:28 +0300 Subject: [PATCH 4821/5608] Make field readonly --- osu.Game/Graphics/UserInterface/BreadcrumbControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index d96aa4b486..6014840a45 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -15,7 +15,7 @@ namespace osu.Game.Graphics.UserInterface public class BreadcrumbControl : OsuTabControl { private const float padding = 10; - private float itemChevronSize; + private readonly float itemChevronSize; protected override TabItem CreateTabItem(T value) => new BreadcrumbTabItem(value, itemChevronSize) { From bf162f148e320f93cc85456ee780383c030878a2 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sat, 28 Dec 2019 13:48:10 +0800 Subject: [PATCH 4822/5608] Move mania stage hint to its own class --- .../UI/Components/ColumnHitObjectArea.cs | 108 ++++++++++++------ .../UI/Components/StageHint.cs | 14 +++ 2 files changed, 90 insertions(+), 32 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/UI/Components/StageHint.cs diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index 386bcbb724..dde718d5ba 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -22,26 +22,15 @@ namespace osu.Game.Rulesets.Mania.UI.Components private readonly IBindable direction = new Bindable(); - private readonly Container hitTargetLine; - private readonly Drawable hitTargetBar; + private readonly Drawable stageHint; public ColumnHitObjectArea(HitObjectContainer hitObjectContainer) { - InternalChildren = new[] + InternalChildren = new Drawable[] { - hitTargetBar = new Box + stageHint = new DefaultStageHint { RelativeSizeAxes = Axes.X, - Height = NotePiece.NOTE_HEIGHT, - Alpha = 0.6f, - Colour = Color4.Black - }, - hitTargetLine = new Container - { - RelativeSizeAxes = Axes.X, - Height = hit_target_bar_height, - Masking = true, - Child = new Box { RelativeSizeAxes = Axes.Both } }, hitObjectContainer }; @@ -55,17 +44,10 @@ namespace osu.Game.Rulesets.Mania.UI.Components { Anchor anchor = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - hitTargetBar.Anchor = hitTargetBar.Origin = anchor; - hitTargetLine.Anchor = hitTargetLine.Origin = anchor; + stageHint.Anchor = stageHint.Origin = anchor; }, true); } - protected override void LoadComplete() - { - base.LoadComplete(); - updateColours(); - } - private Color4 accentColour; public Color4 AccentColour @@ -77,22 +59,84 @@ namespace osu.Game.Rulesets.Mania.UI.Components return; accentColour = value; - - updateColours(); } } - private void updateColours() + private class DefaultStageHint : StageHint { - if (!IsLoaded) - return; + private readonly IBindable direction = new Bindable(); - hitTargetLine.EdgeEffect = new EdgeEffectParameters + private readonly Container hitTargetLine; + private readonly Drawable hitTargetBar; + + public DefaultStageHint() { - Type = EdgeEffectType.Glow, - Radius = 5, - Colour = accentColour.Opacity(0.5f), - }; + InternalChildren = new[] + { + hitTargetBar = new Box + { + RelativeSizeAxes = Axes.X, + Height = NotePiece.NOTE_HEIGHT, + Alpha = 0.6f, + Colour = Color4.Black + }, + hitTargetLine = new Container + { + RelativeSizeAxes = Axes.X, + Height = hit_target_bar_height, + Masking = true, + Child = new Box { RelativeSizeAxes = Axes.Both } + }, + }; + } + + [BackgroundDependencyLoader] + private void load(IScrollingInfo scrollingInfo) + { + direction.BindTo(scrollingInfo.Direction); + direction.BindValueChanged(dir => + { + Anchor anchor = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + + hitTargetBar.Anchor = hitTargetBar.Origin = anchor; + hitTargetLine.Anchor = hitTargetLine.Origin = anchor; + }, true); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateColours(); + } + + private Color4 accentColour; + + public override Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) + return; + + accentColour = value; + + updateColours(); + } + } + + private void updateColours() + { + if (!IsLoaded) + return; + + hitTargetLine.EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Radius = 5, + Colour = accentColour.Opacity(0.5f), + }; + } } } } diff --git a/osu.Game.Rulesets.Mania/UI/Components/StageHint.cs b/osu.Game.Rulesets.Mania/UI/Components/StageHint.cs new file mode 100644 index 0000000000..9574f77eb5 --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/Components/StageHint.cs @@ -0,0 +1,14 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Mania.UI.Components +{ + public abstract class StageHint : CompositeDrawable, IHasAccentColour + { + public abstract Color4 AccentColour { get; set; } + } +} From 5d2b5cc950b5608cdf369c1d3e226733a7648689 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sat, 28 Dec 2019 14:05:46 +0800 Subject: [PATCH 4823/5608] correct type of field stageHint --- osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index dde718d5ba..6bfb2b89aa 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components private readonly IBindable direction = new Bindable(); - private readonly Drawable stageHint; + private readonly StageHint stageHint; public ColumnHitObjectArea(HitObjectContainer hitObjectContainer) { @@ -59,6 +59,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components return; accentColour = value; + + stageHint.AccentColour = accentColour; } } From 1b3358166796da218c09217ed7b8a7372f1d9736 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 28 Dec 2019 21:13:18 +0800 Subject: [PATCH 4824/5608] Construct DllResourceStore with assemblies --- osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs | 2 +- osu.Game.Tests/Resources/TestResources.cs | 5 +++-- osu.Game.Tournament/TournamentGameBase.cs | 2 +- osu.Game/OsuGameBase.cs | 3 ++- osu.Game/Rulesets/Ruleset.cs | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs b/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs index 2fad3bd04f..d4c3000d3f 100644 --- a/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs +++ b/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.Tests [BackgroundDependencyLoader] private void load(AudioManager audio, SkinManager skinManager) { - var dllStore = new DllResourceStore("osu.Game.Rulesets.Osu.Tests.dll"); + var dllStore = new DllResourceStore(typeof(SkinnableTestScene).Assembly); metricsSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore(dllStore, "Resources/metrics_skin"), audio, true); defaultSkin = skinManager.GetSkin(DefaultLegacySkin.Info); diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index a57405628a..be9f1dd9b0 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -4,16 +4,17 @@ using System.IO; using NUnit.Framework; using osu.Framework.IO.Stores; +using osu.Game.Resources; namespace osu.Game.Tests.Resources { public static class TestResources { - public static DllResourceStore GetStore() => new DllResourceStore("osu.Game.Tests.dll"); + public static DllResourceStore GetStore() => new DllResourceStore(typeof(TestResources).Assembly); public static Stream OpenResource(string name) => GetStore().GetStream($"Resources/{name}"); - public static Stream GetTestBeatmapStream(bool virtualTrack = false) => new DllResourceStore("osu.Game.Resources.dll").GetStream($"Beatmaps/241526 Soleily - Renatus{(virtualTrack ? "_virtual" : "")}.osz"); + public static Stream GetTestBeatmapStream(bool virtualTrack = false) => new DllResourceStore(OsuResources.ResourceAssembly).GetStream($"Beatmaps/241526 Soleily - Renatus{(virtualTrack ? "_virtual" : "")}.osz"); public static string GetTestBeatmapForImport(bool virtualTrack = false) { diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 4d7abfe272..bd91ad9704 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -52,7 +52,7 @@ namespace osu.Game.Tournament [BackgroundDependencyLoader] private void load(Storage storage, FrameworkConfigManager frameworkConfig) { - Resources.AddStore(new DllResourceStore(@"osu.Game.Tournament.dll")); + Resources.AddStore(new DllResourceStore(typeof(TournamentGameBase).Assembly)); AddFont(Resources, @"Resources/Fonts/Aquatico-Regular"); AddFont(Resources, @"Resources/Fonts/Aquatico-Light"); diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 22b8d9d012..0819642d2d 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -29,6 +29,7 @@ using osu.Game.Database; using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.IO; +using osu.Game.Resources; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; @@ -125,7 +126,7 @@ namespace osu.Game [BackgroundDependencyLoader] private void load() { - Resources.AddStore(new DllResourceStore(@"osu.Game.Resources.dll")); + Resources.AddStore(new DllResourceStore(OsuResources.ResourceAssembly)); dependencies.Cache(contextFactory = new DatabaseContextFactory(Storage)); diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 67ec6d15ea..693d85c574 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets public virtual Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.Solid.QuestionCircle }; - public virtual IResourceStore CreateResourceStore() => new NamespacedResourceStore(new DllResourceStore(GetType().Assembly.Location), @"Resources"); + public virtual IResourceStore CreateResourceStore() => new NamespacedResourceStore(new DllResourceStore(GetType().Assembly), @"Resources"); public abstract string Description { get; } From e8bcb52612d13667ef93842d570384c225297e43 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 28 Dec 2019 18:07:55 +0300 Subject: [PATCH 4825/5608] Set UserAgent for API requests --- osu.Game/Online/API/APIRequest.cs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index fcbd4d314a..0956c749a2 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -14,7 +14,7 @@ namespace osu.Game.Online.API /// Type of the response (used for deserialisation). public abstract class APIRequest : APIRequest { - protected override WebRequest CreateWebRequest() => new JsonWebRequest(Uri); + protected override WebRequest CreateWebRequest() => new OsuJsonWebRequest(Uri); public T Result => ((JsonWebRequest)WebRequest).ResponseObject; @@ -30,6 +30,16 @@ namespace osu.Game.Online.API /// This will be scheduled to the API's internal scheduler (run on update thread automatically). /// public new event APISuccessHandler Success; + + private class OsuJsonWebRequest : JsonWebRequest + { + public OsuJsonWebRequest(string uri) + : base(uri) + { + } + + protected override string UserAgent => "osu!"; + } } /// @@ -39,7 +49,7 @@ namespace osu.Game.Online.API { protected abstract string Target { get; } - protected virtual WebRequest CreateWebRequest() => new WebRequest(Uri); + protected virtual WebRequest CreateWebRequest() => new OsuWebRequest(Uri); protected virtual string Uri => $@"{API.Endpoint}/api/v2/{Target}"; @@ -152,6 +162,16 @@ namespace osu.Game.Online.API [JsonProperty("error")] public string ErrorMessage { get; set; } } + + private class OsuWebRequest : WebRequest + { + public OsuWebRequest(string uri) + : base(uri) + { + } + + protected override string UserAgent => "osu!"; + } } public class APIException : InvalidOperationException From b3d32710df2cf43bc3a969f88ea43b6cc7a5ed30 Mon Sep 17 00:00:00 2001 From: Viktor Rosvall Date: Sun, 29 Dec 2019 00:19:51 +0100 Subject: [PATCH 4826/5608] Centered button mods by adding padding to FillFlowContainer --- osu.Game/Screens/Select/FooterButtonMods.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 8419ee0c2a..bb733f10ed 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -54,11 +54,10 @@ namespace osu.Game.Screens.Select Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(weight: FontWeight.Bold), - Margin = new MarginPadding { Right = 10 } } }, AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Left = 70 } + Margin = new MarginPadding { Left = 70, Right = 15 } }); } From cb2b89a2c9197fa56aca6d86c0f3429a14bef27a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 29 Dec 2019 03:01:14 +0300 Subject: [PATCH 4827/5608] Fix crashing TextSceneMedalOverlay --- osu.Game/Overlays/MedalOverlay.cs | 4 ++-- osu.Game/Overlays/MedalSplash/DrawableMedal.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 1f15c773f4..5da573e81a 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -155,12 +155,12 @@ namespace osu.Game.Overlays Radius = 50, }; - disc.Add(drawableMedal = new DrawableMedal(medal) + LoadComponentAsync(drawableMedal = new DrawableMedal(medal) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Both, - }); + }, disc.Add); } protected override void LoadComplete() diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index a9b4bed334..3cf7befb45 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -51,7 +51,7 @@ namespace osu.Game.Overlays.MedalSplash { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Scale = new Vector2(0.81f), + Scale = new Vector2(0.41f), }, medalGlow = new Sprite { From cdfbe96e9bdceecc7f04ff2262e23b4e207720e7 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sun, 29 Dec 2019 14:52:51 +0800 Subject: [PATCH 4828/5608] Make AccentColour of StageHint virtual --- osu.Game.Rulesets.Mania/UI/Components/StageHint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/UI/Components/StageHint.cs b/osu.Game.Rulesets.Mania/UI/Components/StageHint.cs index 9574f77eb5..813a6928c9 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/StageHint.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/StageHint.cs @@ -9,6 +9,6 @@ namespace osu.Game.Rulesets.Mania.UI.Components { public abstract class StageHint : CompositeDrawable, IHasAccentColour { - public abstract Color4 AccentColour { get; set; } + public virtual Color4 AccentColour { get; set; } } } From bf463fe5e0c13f2d07b257a2a21060620cb672b5 Mon Sep 17 00:00:00 2001 From: Viktor Rosvall Date: Sun, 29 Dec 2019 08:57:14 +0100 Subject: [PATCH 4829/5608] adjusted the margin values --- .../Visual/UserInterface/TestSceneFooterButtonMods.cs | 7 +++++++ osu.Game/Screens/Select/FooterButtonMods.cs | 1 + 2 files changed, 8 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs index 6eb621ca3b..de67968fbc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs @@ -45,6 +45,13 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep(@"Add multiple Mods", () => changeMods(mutlipleIncrementMods)); AddAssert(@"Check multiple mod multiplier", () => assertModsMultiplier(mutlipleIncrementMods)); } + + [Test] + public void Temporary() + { + var hiddenMod = new Mod[] { new OsuModRelax() }; + AddStep(@"Add Hidden", () => changeMods(hiddenMod)); + } [Test] public void TestDecrementMultiplier() diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index bb733f10ed..d533d5444c 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -54,6 +54,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(weight: FontWeight.Bold), + Margin = new MarginPadding { Right = 6 } } }, AutoSizeAxes = Axes.Both, From 875a25c5297b0797b84af4974c2bf5e0d68ed6c6 Mon Sep 17 00:00:00 2001 From: Viktor Rosvall Date: Sun, 29 Dec 2019 08:57:14 +0100 Subject: [PATCH 4830/5608] adjusted the margin values --- osu.Game/Screens/Select/FooterButtonMods.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index bb733f10ed..d533d5444c 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -54,6 +54,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(weight: FontWeight.Bold), + Margin = new MarginPadding { Right = 6 } } }, AutoSizeAxes = Axes.Both, From e85910c4e465ab174ee8d328b75442d8886c8cb9 Mon Sep 17 00:00:00 2001 From: Viktor Rosvall Date: Sun, 29 Dec 2019 09:18:27 +0100 Subject: [PATCH 4831/5608] removed unnecessary test code --- .../Visual/UserInterface/TestSceneFooterButtonMods.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs index de67968fbc..6eb621ca3b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs @@ -45,13 +45,6 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep(@"Add multiple Mods", () => changeMods(mutlipleIncrementMods)); AddAssert(@"Check multiple mod multiplier", () => assertModsMultiplier(mutlipleIncrementMods)); } - - [Test] - public void Temporary() - { - var hiddenMod = new Mod[] { new OsuModRelax() }; - AddStep(@"Add Hidden", () => changeMods(hiddenMod)); - } [Test] public void TestDecrementMultiplier() From 61fb9f5613dc47c07a96b88eba4f40f23efeb0c2 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sun, 29 Dec 2019 23:18:50 +0800 Subject: [PATCH 4832/5608] Remove class StageHint and usage --- .../UI/Components/ColumnHitObjectArea.cs | 9 +++++---- osu.Game.Rulesets.Mania/UI/Components/StageHint.cs | 14 -------------- 2 files changed, 5 insertions(+), 18 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/UI/Components/StageHint.cs diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index 6bfb2b89aa..494da6c61b 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -22,11 +22,11 @@ namespace osu.Game.Rulesets.Mania.UI.Components private readonly IBindable direction = new Bindable(); - private readonly StageHint stageHint; + private readonly Drawable stageHint; public ColumnHitObjectArea(HitObjectContainer hitObjectContainer) { - InternalChildren = new Drawable[] + InternalChildren = new[] { stageHint = new DefaultStageHint { @@ -60,11 +60,12 @@ namespace osu.Game.Rulesets.Mania.UI.Components accentColour = value; - stageHint.AccentColour = accentColour; + if (stageHint is IHasAccentColour colouredHitTarget) + colouredHitTarget.AccentColour = accentColour; } } - private class DefaultStageHint : StageHint + private class DefaultStageHint : CompositeDrawable, IHasAccentColour { private readonly IBindable direction = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/UI/Components/StageHint.cs b/osu.Game.Rulesets.Mania/UI/Components/StageHint.cs deleted file mode 100644 index 813a6928c9..0000000000 --- a/osu.Game.Rulesets.Mania/UI/Components/StageHint.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 osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osuTK.Graphics; - -namespace osu.Game.Rulesets.Mania.UI.Components -{ - public abstract class StageHint : CompositeDrawable, IHasAccentColour - { - public virtual Color4 AccentColour { get; set; } - } -} From 51000765ddca9c9f4b4a60605e10bd554e74c111 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sun, 29 Dec 2019 23:29:00 +0800 Subject: [PATCH 4833/5608] remove override --- osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index 494da6c61b..c78023a58b 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components private Color4 accentColour; - public override Color4 AccentColour + public Color4 AccentColour { get => accentColour; set From 20c5748342efacb4d36c6d971d9e9bcdf689d650 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sun, 29 Dec 2019 23:37:28 +0800 Subject: [PATCH 4834/5608] Use hitTarget in place of stageHint --- .../UI/Components/ColumnHitObjectArea.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index c78023a58b..ee2cec1bbd 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -22,13 +22,13 @@ namespace osu.Game.Rulesets.Mania.UI.Components private readonly IBindable direction = new Bindable(); - private readonly Drawable stageHint; + private readonly Drawable hitTarget; public ColumnHitObjectArea(HitObjectContainer hitObjectContainer) { InternalChildren = new[] { - stageHint = new DefaultStageHint + hitTarget = new DefaultHitTarget { RelativeSizeAxes = Axes.X, }, @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components { Anchor anchor = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - stageHint.Anchor = stageHint.Origin = anchor; + hitTarget.Anchor = hitTarget.Origin = anchor; }, true); } @@ -60,19 +60,19 @@ namespace osu.Game.Rulesets.Mania.UI.Components accentColour = value; - if (stageHint is IHasAccentColour colouredHitTarget) + if (hitTarget is IHasAccentColour colouredHitTarget) colouredHitTarget.AccentColour = accentColour; } } - private class DefaultStageHint : CompositeDrawable, IHasAccentColour + private class DefaultHitTarget : CompositeDrawable, IHasAccentColour { private readonly IBindable direction = new Bindable(); private readonly Container hitTargetLine; private readonly Drawable hitTargetBar; - public DefaultStageHint() + public DefaultHitTarget() { InternalChildren = new[] { From 39d77386a809c4900600e97db86fe8558e18b52a Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 29 Dec 2019 10:49:28 -0800 Subject: [PATCH 4835/5608] Fix context menus not showing on social panels --- .../SearchableList/SearchableListOverlay.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs index 37478d902b..5975e94ffc 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Cursor; namespace osu.Game.Overlays.SearchableList { @@ -61,21 +62,20 @@ namespace osu.Game.Overlays.SearchableList scrollContainer = new Container { RelativeSizeAxes = Axes.Both, - Children = new[] + Child = new OsuContextMenuContainer { - new OsuScrollContainer + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = new OsuScrollContainer { RelativeSizeAxes = Axes.Both, ScrollbarVisible = false, - Children = new[] + Child = ScrollFlow = new FillFlowContainer { - ScrollFlow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = WIDTH_PADDING, Bottom = 50 }, - Direction = FillDirection.Vertical, - }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = WIDTH_PADDING, Bottom = 50 }, + Direction = FillDirection.Vertical, }, }, }, From bcf7156882aeb0dd86fbd67a1feba7166e76d218 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 29 Dec 2019 11:19:46 -0800 Subject: [PATCH 4836/5608] Add context menu on direct panels --- osu.Game/Overlays/Direct/DirectPanel.cs | 27 +++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index c1c5113c5e..0ec0466580 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -9,21 +10,25 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.Direct { - public abstract class DirectPanel : Container + public abstract class DirectPanel : OsuClickableContainer, IHasContextMenu { public readonly BeatmapSetInfo SetInfo; @@ -44,6 +49,8 @@ namespace osu.Game.Overlays.Direct protected override Container Content => content; + protected Action ViewBeatmap; + protected DirectPanel(BeatmapSetInfo setInfo) { Debug.Assert(setInfo.OnlineBeatmapSetID != null); @@ -88,6 +95,12 @@ namespace osu.Game.Overlays.Direct }, } }); + + Action = ViewBeatmap = () => + { + Debug.Assert(SetInfo.OnlineBeatmapSetID != null); + beatmapSetOverlay?.FetchAndShowBeatmapSet(SetInfo.OnlineBeatmapSetID.Value); + }; } protected override void Update() @@ -120,13 +133,6 @@ namespace osu.Game.Overlays.Direct base.OnHoverLost(e); } - protected override bool OnClick(ClickEvent e) - { - Debug.Assert(SetInfo.OnlineBeatmapSetID != null); - beatmapSetOverlay?.FetchAndShowBeatmapSet(SetInfo.OnlineBeatmapSetID.Value); - return true; - } - protected override void LoadComplete() { base.LoadComplete(); @@ -203,5 +209,10 @@ namespace osu.Game.Overlays.Direct Value = value; } } + + public MenuItem[] ContextMenuItems => new MenuItem[] + { + new OsuMenuItem("View Beatmap", MenuItemType.Highlighted, ViewBeatmap), + }; } } From 0eccfc79cc84403609b080665bf70465992a3eae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 30 Dec 2019 11:51:33 +0900 Subject: [PATCH 4837/5608] Remove unused field --- osu.Game/Overlays/Direct/DirectPanel.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 0ec0466580..4ad8e95512 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -37,8 +37,6 @@ namespace osu.Game.Overlays.Direct private Container content; - private BeatmapSetOverlay beatmapSetOverlay; - public PreviewTrack Preview => PlayButton.Preview; public Bindable PreviewPlaying => PlayButton?.Playing; @@ -77,8 +75,6 @@ namespace osu.Game.Overlays.Direct [BackgroundDependencyLoader(permitNulls: true)] private void load(BeatmapManager beatmaps, OsuColour colours, BeatmapSetOverlay beatmapSetOverlay) { - this.beatmapSetOverlay = beatmapSetOverlay; - AddInternal(content = new Container { RelativeSizeAxes = Axes.Both, From 5748b60a069f4e378c0028b7a46f5dcd12afde47 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 30 Dec 2019 08:26:49 +0300 Subject: [PATCH 4838/5608] Make item chevron size virtual --- osu.Game/Graphics/UserInterface/BreadcrumbControl.cs | 10 +++++----- osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs | 7 +++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index 6014840a45..d4705c539a 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -15,18 +15,18 @@ namespace osu.Game.Graphics.UserInterface public class BreadcrumbControl : OsuTabControl { private const float padding = 10; - private readonly float itemChevronSize; - protected override TabItem CreateTabItem(T value) => new BreadcrumbTabItem(value, itemChevronSize) + protected virtual float ItemChevronSize => 10; + + protected override TabItem CreateTabItem(T value) => new BreadcrumbTabItem(value, ItemChevronSize) { AccentColour = AccentColour, }; - protected override float StripWidth() => base.StripWidth() - (padding + itemChevronSize); + protected override float StripWidth() => base.StripWidth() - (padding + ItemChevronSize); - public BreadcrumbControl(float itemChevronSize = 10) + public BreadcrumbControl() { - this.itemChevronSize = itemChevronSize; Height = 32; TabContainer.Spacing = new Vector2(padding, 0f); Current.ValueChanged += index => diff --git a/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs b/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs index d772aa0d46..eee43ec229 100644 --- a/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs +++ b/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs @@ -9,15 +9,14 @@ namespace osu.Game.Overlays { public class OverlayHeaderBreadcrumbControl : BreadcrumbControl { - private const float item_chevron_size = 8; - public OverlayHeaderBreadcrumbControl() - : base(item_chevron_size) { RelativeSizeAxes = Axes.X; } - protected override TabItem CreateTabItem(string value) => new ControlTabItem(value, item_chevron_size); + protected override float ItemChevronSize => 8; + + protected override TabItem CreateTabItem(string value) => new ControlTabItem(value, ItemChevronSize); private class ControlTabItem : BreadcrumbTabItem { From 8c378dc625869644cff887aed4aaebbb375c6189 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 27 Dec 2019 19:46:33 +0900 Subject: [PATCH 4839/5608] Move EditorBeatmap construction/conversion to Editor --- .../TestSceneOsuDistanceSnapGrid.cs | 2 +- .../Editor/TestSceneDistanceSnapGrid.cs | 2 +- .../Edit/DrawableEditRulesetWrapper.cs | 2 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 45 ++++++------------- .../Compose/Components/BlueprintContainer.cs | 2 +- .../Compose/Components/DistanceSnapGrid.cs | 2 +- .../Timeline/TimelineHitObjectDisplay.cs | 4 +- .../Screens/Edit/Compose/ComposeScreen.cs | 2 +- osu.Game/Screens/Edit/Editor.cs | 9 +++- osu.Game/Screens/Edit/EditorBeatmap.cs | 43 +++++++++--------- osu.Game/Screens/Edit/EditorScreen.cs | 3 ++ osu.Game/Screens/Edit/IEditorBeatmap.cs | 32 ------------- 12 files changed, 53 insertions(+), 95 deletions(-) delete mode 100644 osu.Game/Screens/Edit/IEditorBeatmap.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index 75c57467c3..c9b3d08a22 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Tests typeof(CircularDistanceSnapGrid) }; - [Cached(typeof(IEditorBeatmap))] + [Cached(typeof(EditorBeatmap))] private readonly EditorBeatmap editorBeatmap; [Cached] diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index 83b1f43f38..847d168e51 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.Editor private const double beat_length = 100; private static readonly Vector2 grid_position = new Vector2(512, 384); - [Cached(typeof(IEditorBeatmap))] + [Cached(typeof(EditorBeatmap))] private readonly EditorBeatmap editorBeatmap; [Cached(typeof(IDistanceSnapProvider))] diff --git a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs index ab2332ea86..89e7866707 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Edit private readonly DrawableRuleset drawableRuleset; [Resolved] - private IEditorBeatmap beatmap { get; set; } + private EditorBeatmap beatmap { get; set; } public DrawableEditRulesetWrapper(DrawableRuleset drawableRuleset) { diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index a550cf4a02..bfaa7e8872 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; @@ -35,20 +34,20 @@ namespace osu.Game.Rulesets.Edit { protected IRulesetConfigManager Config { get; private set; } - protected new EditorBeatmap EditorBeatmap { get; private set; } - protected readonly Ruleset Ruleset; [Resolved] protected IFrameBasedClock EditorClock { get; private set; } + [Resolved] + protected EditorBeatmap EditorBeatmap { get; private set; } + [Resolved] private IAdjustableClock adjustableClock { get; set; } [Resolved] private BindableBeatDivisor beatDivisor { get; set; } - private Beatmap playableBeatmap; private IBeatmapProcessor beatmapProcessor; private DrawableEditRulesetWrapper drawableRulesetWrapper; @@ -68,9 +67,17 @@ namespace osu.Game.Rulesets.Edit [BackgroundDependencyLoader] private void load(IFrameBasedClock framedClock) { + beatmapProcessor = Ruleset.CreateBeatmapProcessor(EditorBeatmap.PlayableBeatmap); + + EditorBeatmap.HitObjectAdded += addHitObject; + EditorBeatmap.HitObjectRemoved += removeHitObject; + EditorBeatmap.StartTimeChanged += UpdateHitObject; + + Config = Dependencies.Get().GetConfigFor(Ruleset); + try { - drawableRulesetWrapper = new DrawableEditRulesetWrapper(CreateDrawableRuleset(Ruleset, playableBeatmap)) + drawableRulesetWrapper = new DrawableEditRulesetWrapper(CreateDrawableRuleset(Ruleset, EditorBeatmap.PlayableBeatmap)) { Clock = framedClock, ProcessCustomClock = false @@ -140,27 +147,6 @@ namespace osu.Game.Rulesets.Edit blueprintContainer.SelectionChanged += selectionChanged; } - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var parentWorkingBeatmap = parent.Get>().Value; - - playableBeatmap = (Beatmap)parentWorkingBeatmap.GetPlayableBeatmap(Ruleset.RulesetInfo); - - beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap); - - base.EditorBeatmap = EditorBeatmap = new EditorBeatmap(playableBeatmap); - EditorBeatmap.HitObjectAdded += addHitObject; - EditorBeatmap.HitObjectRemoved += removeHitObject; - EditorBeatmap.StartTimeChanged += UpdateHitObject; - - var dependencies = new DependencyContainer(parent); - dependencies.CacheAs(EditorBeatmap); - - Config = dependencies.Get().GetConfigFor(Ruleset); - - return base.CreateChildDependencies(dependencies); - } - protected override void LoadComplete() { base.LoadComplete(); @@ -233,7 +219,7 @@ namespace osu.Game.Rulesets.Edit scheduledUpdate = Schedule(() => { beatmapProcessor?.PreProcess(); - hitObject?.ApplyDefaults(playableBeatmap.ControlPointInfo, playableBeatmap.BeatmapInfo.BaseDifficulty); + hitObject?.ApplyDefaults(EditorBeatmap.ControlPointInfo, EditorBeatmap.BeatmapInfo.BaseDifficulty); beatmapProcessor?.PostProcess(); }); } @@ -332,11 +318,6 @@ namespace osu.Game.Rulesets.Edit /// public abstract IEnumerable HitObjects { get; } - /// - /// An editor-specific beatmap, exposing mutation events. - /// - public IEditorBeatmap EditorBeatmap { get; protected set; } - /// /// Whether the user's cursor is currently in an area of the that is valid for placement. /// diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 195bc663f1..cafaddc39e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -40,7 +40,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private HitObjectComposer composer { get; set; } [Resolved] - private IEditorBeatmap beatmap { get; set; } + private EditorBeatmap beatmap { get; set; } public BlueprintContainer() { diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 00326d04f7..53c5cf97fa 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -45,7 +45,7 @@ namespace osu.Game.Screens.Edit.Compose.Components protected IDistanceSnapProvider SnapProvider { get; private set; } [Resolved] - private IEditorBeatmap beatmap { get; set; } + private EditorBeatmap beatmap { get; set; } [Resolved] private BindableBeatDivisor beatDivisor { get; set; } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs index db4aca75e5..b20f2fa11d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs @@ -16,9 +16,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { internal class TimelineHitObjectDisplay : TimelinePart { - private IEditorBeatmap beatmap { get; } + private EditorBeatmap beatmap { get; } - public TimelineHitObjectDisplay(IEditorBeatmap beatmap) + public TimelineHitObjectDisplay(EditorBeatmap beatmap) { RelativeSizeAxes = Axes.Both; diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 5d9757778d..1a6aae294a 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -32,6 +32,6 @@ namespace osu.Game.Screens.Edit.Compose return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(composer)); } - protected override Drawable CreateTimelineContent() => composer == null ? base.CreateTimelineContent() : new TimelineHitObjectDisplay(composer.EditorBeatmap); + protected override Drawable CreateTimelineContent() => composer == null ? base.CreateTimelineContent() : new TimelineHitObjectDisplay(EditorBeatmap); } } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 1b4964c068..14d69cddd1 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -23,6 +23,7 @@ using osuTK.Input; using System.Collections.Generic; using osu.Framework; using osu.Framework.Input.Bindings; +using osu.Game.Beatmaps; using osu.Game.Graphics.Cursor; using osu.Game.Input.Bindings; using osu.Game.Screens.Edit.Compose; @@ -49,9 +50,11 @@ namespace osu.Game.Screens.Edit private EditorScreen currentScreen; private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); - private EditorClock clock; + private IBeatmap playableBeatmap; + private EditorBeatmap editorBeatmap; + private DependencyContainer dependencies; private GameHost host; @@ -73,9 +76,13 @@ namespace osu.Game.Screens.Edit clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); + playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Beatmap.Value.BeatmapInfo.Ruleset); + editorBeatmap = new EditorBeatmap(playableBeatmap); + dependencies.CacheAs(clock); dependencies.CacheAs(clock); dependencies.Cache(beatDivisor); + dependencies.CacheAs(editorBeatmap); EditorMenuBar menuBar; diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index 5a45ea05a0..83879f0470 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Edit { - public class EditorBeatmap : IEditorBeatmap + public class EditorBeatmap : IBeatmap { /// /// Invoked when a is added to this . @@ -29,12 +29,13 @@ namespace osu.Game.Screens.Edit /// public event Action StartTimeChanged; - private readonly Dictionary> startTimeBindables = new Dictionary>(); - private readonly IBeatmap beatmap; + public readonly IBeatmap PlayableBeatmap; - public EditorBeatmap(IBeatmap beatmap) + private readonly Dictionary> startTimeBindables = new Dictionary>(); + + public EditorBeatmap(IBeatmap playableBeatmap) { - this.beatmap = beatmap; + PlayableBeatmap = playableBeatmap; foreach (var obj in HitObjects) trackStartTime(obj); @@ -42,23 +43,21 @@ namespace osu.Game.Screens.Edit public BeatmapInfo BeatmapInfo { - get => beatmap.BeatmapInfo; - set => beatmap.BeatmapInfo = value; + get => PlayableBeatmap.BeatmapInfo; + set => PlayableBeatmap.BeatmapInfo = value; } - public BeatmapMetadata Metadata => beatmap.Metadata; + public BeatmapMetadata Metadata => PlayableBeatmap.Metadata; - public ControlPointInfo ControlPointInfo => beatmap.ControlPointInfo; + public ControlPointInfo ControlPointInfo => PlayableBeatmap.ControlPointInfo; - public List Breaks => beatmap.Breaks; + public List Breaks => PlayableBeatmap.Breaks; - public double TotalBreakTime => beatmap.TotalBreakTime; + public double TotalBreakTime => PlayableBeatmap.TotalBreakTime; - public IReadOnlyList HitObjects => beatmap.HitObjects; + public IReadOnlyList HitObjects => PlayableBeatmap.HitObjects; - IReadOnlyList IBeatmap.HitObjects => beatmap.HitObjects; - - public IEnumerable GetStatistics() => beatmap.GetStatistics(); + public IEnumerable GetStatistics() => PlayableBeatmap.GetStatistics(); public IBeatmap Clone() => (EditorBeatmap)MemberwiseClone(); @@ -71,8 +70,8 @@ namespace osu.Game.Screens.Edit trackStartTime(hitObject); // Preserve existing sorting order in the beatmap - var insertionIndex = findInsertionIndex(beatmap.HitObjects, hitObject.StartTime); - ((IList)beatmap.HitObjects).Insert(insertionIndex + 1, hitObject); + var insertionIndex = findInsertionIndex(PlayableBeatmap.HitObjects, hitObject.StartTime); + ((IList)PlayableBeatmap.HitObjects).Insert(insertionIndex + 1, hitObject); HitObjectAdded?.Invoke(hitObject); } @@ -83,10 +82,10 @@ namespace osu.Game.Screens.Edit /// The to add. public void Remove(HitObject hitObject) { - if (!((IList)beatmap.HitObjects).Contains(hitObject)) + if (!((IList)PlayableBeatmap.HitObjects).Contains(hitObject)) return; - ((IList)beatmap.HitObjects).Remove(hitObject); + ((IList)PlayableBeatmap.HitObjects).Remove(hitObject); var bindable = startTimeBindables[hitObject]; bindable.UnbindAll(); @@ -101,10 +100,10 @@ namespace osu.Game.Screens.Edit startTimeBindables[hitObject].ValueChanged += _ => { // For now we'll remove and re-add the hitobject. This is not optimal and can be improved if required. - ((IList)beatmap.HitObjects).Remove(hitObject); + ((IList)PlayableBeatmap.HitObjects).Remove(hitObject); - var insertionIndex = findInsertionIndex(beatmap.HitObjects, hitObject.StartTime); - ((IList)beatmap.HitObjects).Insert(insertionIndex + 1, hitObject); + var insertionIndex = findInsertionIndex(PlayableBeatmap.HitObjects, hitObject.StartTime); + ((IList)PlayableBeatmap.HitObjects).Insert(insertionIndex + 1, hitObject); StartTimeChanged?.Invoke(hitObject); }; diff --git a/osu.Game/Screens/Edit/EditorScreen.cs b/osu.Game/Screens/Edit/EditorScreen.cs index 1b57c703ae..d42447ac4b 100644 --- a/osu.Game/Screens/Edit/EditorScreen.cs +++ b/osu.Game/Screens/Edit/EditorScreen.cs @@ -17,6 +17,9 @@ namespace osu.Game.Screens.Edit [Resolved] protected IBindable Beatmap { get; private set; } + [Resolved] + protected EditorBeatmap EditorBeatmap { get; private set; } + protected override Container Content => content; private readonly Container content; diff --git a/osu.Game/Screens/Edit/IEditorBeatmap.cs b/osu.Game/Screens/Edit/IEditorBeatmap.cs deleted file mode 100644 index df4efd289e..0000000000 --- a/osu.Game/Screens/Edit/IEditorBeatmap.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Objects; - -namespace osu.Game.Screens.Edit -{ - /// - /// Interface for the contained by the see . - /// Children of may resolve the beatmap via . - /// - public interface IEditorBeatmap : IBeatmap - { - /// - /// Invoked when a is added to this . - /// - event Action HitObjectAdded; - - /// - /// Invoked when a is removed from this . - /// - event Action HitObjectRemoved; - - /// - /// Invoked when the start time of a in this was changed. - /// - event Action StartTimeChanged; - } -} From 8ae4cfaa5205111b5e2afe06aba07fe66e9c5f8c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2019 07:33:49 +0000 Subject: [PATCH 4840/5608] Bump ppy.osu.Game.Resources from 2019.1227.0 to 2019.1230.0 Bumps [ppy.osu.Game.Resources](https://github.com/ppy/osu-resources) from 2019.1227.0 to 2019.1230.0. - [Release notes](https://github.com/ppy/osu-resources/releases) - [Commits](https://github.com/ppy/osu-resources/compare/2019.1227.0...2019.1230.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 6ff9416e47..0b41d5cda4 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -53,7 +53,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 806aadde84..565608b40f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -22,7 +22,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 230ff01cce..60355b8592 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,7 +73,7 @@ - + From 32e4d4a5633e907130da26f9e5e82fa991ade859 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 30 Dec 2019 09:29:46 -0800 Subject: [PATCH 4841/5608] Fix search textboxes absorbing home/end input on scroll containers --- osu.Game/Graphics/UserInterface/SearchTextBox.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index ff3618b263..cdae36e700 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -40,6 +40,13 @@ namespace osu.Game.Graphics.UserInterface if (action.ActionType == PlatformActionType.CharNext && action.ActionMethod == PlatformActionMethod.Delete) return false; + switch (action.ActionType) + { + case PlatformActionType.LineEnd: + case PlatformActionType.LineStart: + return false; + } + return base.OnPressed(action); } From 25be3fd799855d4a234c05d80ff2e1cb431c97d4 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 30 Dec 2019 09:38:22 -0800 Subject: [PATCH 4842/5608] Move shift-delete handling to switch --- osu.Game/Graphics/UserInterface/SearchTextBox.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index cdae36e700..dbaf2cd073 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -34,17 +34,19 @@ 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 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; - switch (action.ActionType) { case PlatformActionType.LineEnd: case PlatformActionType.LineStart: return false; + + // 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 caret should always be at the end of text) + // Avoid handling it here to allow other components to potentially consume the shortcut. + case PlatformActionType.CharNext: + if (action.ActionMethod == PlatformActionMethod.Delete) + return false; + break; } return base.OnPressed(action); From a292d235d6f6cf7f78a28ad195c40f857b498193 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 30 Dec 2019 09:49:34 -0800 Subject: [PATCH 4843/5608] Separate statement with newline --- osu.Game/Graphics/UserInterface/SearchTextBox.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index dbaf2cd073..fe8756a4d2 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -46,6 +46,7 @@ namespace osu.Game.Graphics.UserInterface case PlatformActionType.CharNext: if (action.ActionMethod == PlatformActionMethod.Delete) return false; + break; } From b0bcbf8b93ab24b96a2fe3f73491c2703b31675b Mon Sep 17 00:00:00 2001 From: Viktor Rosvall Date: Mon, 30 Dec 2019 21:55:09 +0100 Subject: [PATCH 4844/5608] Adjusted margin to fix the 1 px increase --- osu.Game/Screens/Select/FooterButtonMods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index d533d5444c..a0e34a7f87 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -58,7 +58,7 @@ namespace osu.Game.Screens.Select } }, AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Left = 70, Right = 15 } + Margin = new MarginPadding { Left = 70, Right = 14 } }); } From f40ebc83caea08d02810065d7150c30c8fe60ffb Mon Sep 17 00:00:00 2001 From: Viktor Rosvall Date: Mon, 30 Dec 2019 23:58:49 +0100 Subject: [PATCH 4845/5608] Begun refractorization process of wrapping Button text in a FillFlowContainer --- .../TestSceneFooterButtonMods.cs | 3 +- osu.Game/Screens/Select/FooterButton.cs | 23 +++++++---- osu.Game/Screens/Select/FooterButtonMods.cs | 38 +++++++------------ 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs index 6eb621ca3b..63197ed26a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs @@ -16,7 +16,8 @@ namespace osu.Game.Tests.Visual.UserInterface { public override IReadOnlyList RequiredTypes => new[] { - typeof(FooterButtonMods) + typeof(FooterButtonMods), + typeof(FooterButton) }; private readonly TestFooterButtonMods footerButtonMods; diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index b77da36748..18c9d1091c 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Select } } - protected readonly Container TextContainer; + protected FillFlowContainer TextContainer; protected readonly SpriteText SpriteText; private readonly Box box; private readonly Box light; @@ -80,15 +80,24 @@ namespace osu.Game.Screens.Select EdgeSmoothness = new Vector2(2, 0), RelativeSizeAxes = Axes.X, }, - TextContainer = new Container + TextContainer = new FillFlowContainer { - Size = new Vector2(100 - SHEAR_WIDTH, 50), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Horizontal, Shear = -SHEAR, - Child = SpriteText = new OsuSpriteText + Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } + SpriteText = new OsuSpriteText + { + Size = new Vector2(100 - SHEAR_WIDTH, 50), + Shear = -SHEAR, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }, + AutoSizeAxes = Axes.Both, + // Margin = new MarginPadding { Left = 70, Right = 14 } }, }; } diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index a0e34a7f87..2141c04cd6 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -3,7 +3,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; +// using osu.Framework.Graphics.Containers; using osu.Game.Screens.Play.HUD; using osu.Game.Rulesets.Mods; using System.Collections.Generic; @@ -34,31 +34,19 @@ namespace osu.Game.Screens.Select public FooterButtonMods() { - Add(new FillFlowContainer + TextContainer.Add(modDisplay = new FooterModDisplay { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Direction = FillDirection.Horizontal, - Shear = -SHEAR, - Children = new Drawable[] - { - modDisplay = new FooterModDisplay - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - DisplayUnrankedText = false, - Scale = new Vector2(0.8f) - }, - MultiplierText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(weight: FontWeight.Bold), - Margin = new MarginPadding { Right = 6 } - } - }, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Left = 70, Right = 14 } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + DisplayUnrankedText = false, + Scale = new Vector2(0.8f) + }); + TextContainer.Add(MultiplierText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(weight: FontWeight.Bold), + Margin = new MarginPadding { Right = 6 } }); } From 8695e57f627aa2dc6da22c4eb53836265328cc30 Mon Sep 17 00:00:00 2001 From: Viktor Rosvall Date: Tue, 31 Dec 2019 12:21:55 +0100 Subject: [PATCH 4846/5608] Hides mod display when no mods are active to fix issue of invisible margin --- osu.Game/Screens/Select/FooterButton.cs | 2 +- osu.Game/Screens/Select/FooterButtonMods.cs | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index 18c9d1091c..7acb2fd221 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -91,7 +91,7 @@ namespace osu.Game.Screens.Select SpriteText = new OsuSpriteText { Size = new Vector2(100 - SHEAR_WIDTH, 50), - Shear = -SHEAR, + Shear = SHEAR, Anchor = Anchor.Centre, Origin = Anchor.Centre, } diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 2141c04cd6..a3453fee05 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(weight: FontWeight.Bold), - Margin = new MarginPadding { Right = 6 } + // Margin = new MarginPadding { Right = 6 } }); } @@ -80,6 +80,11 @@ namespace osu.Game.Screens.Select MultiplierText.FadeColour(lowMultiplierColour, 200); else MultiplierText.FadeColour(Color4.White, 200); + + if (Current.Value?.Count > 0) + modDisplay.FadeIn(0); + else + modDisplay.FadeOut(0); } private class FooterModDisplay : ModDisplay From 3a71abe8ff7ab10d1be61d700f9b8cd76286dc03 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 31 Dec 2019 17:52:41 +0300 Subject: [PATCH 4847/5608] Add xmldoc and better parameter naming --- osu.Game/Overlays/OverlayHeader.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index da7cfd0ce7..4356c54fdf 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -11,10 +11,11 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public abstract class OverlayHeader : Container - where TModel : TabControl + /// A control for overlay. + public abstract class OverlayHeader : Container + where TControl : TabControl { - protected readonly TModel TabControl; + protected readonly TControl TabControl; private readonly Box titleBackground; private readonly Box controlBackground; @@ -102,6 +103,6 @@ namespace osu.Game.Overlays protected abstract ScreenTitle CreateTitle(); - protected abstract TModel CreateControl(); + protected abstract TControl CreateControl(); } } From 19e7867aba19ad7c0dd7c7364c49058b4b0038e2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 31 Dec 2019 18:12:03 +0300 Subject: [PATCH 4848/5608] Make OverlayHeader non-generic --- osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs | 8 ++++++-- osu.Game/Overlays/OverlayHeader.cs | 10 +++------- osu.Game/Overlays/TabControlOverlayHeader.cs | 8 ++++++-- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs index 10664fc5be..6f9445bd47 100644 --- a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs +++ b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs @@ -1,10 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics.UserInterface; + namespace osu.Game.Overlays { - public abstract class BreadcrumbControlOverlayHeader : OverlayHeader + public abstract class BreadcrumbControlOverlayHeader : OverlayHeader { - protected override OverlayHeaderBreadcrumbControl CreateControl() => new OverlayHeaderBreadcrumbControl(); + protected OverlayHeaderBreadcrumbControl TabControl; + + protected override TabControl CreateControl() => TabControl = new OverlayHeaderBreadcrumbControl(); } } diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index 4356c54fdf..7575801aac 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -11,12 +11,8 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - /// A control for overlay. - public abstract class OverlayHeader : Container - where TControl : TabControl + public abstract class OverlayHeader : Container { - protected readonly TControl TabControl; - private readonly Box titleBackground; private readonly Box controlBackground; private readonly Container background; @@ -88,7 +84,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Colour = Color4.Gray, }, - TabControl = CreateControl().With(control => control.Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }) + CreateControl().With(control => control.Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }) } }, CreateContent() @@ -103,6 +99,6 @@ namespace osu.Game.Overlays protected abstract ScreenTitle CreateTitle(); - protected abstract TControl CreateControl(); + protected abstract TabControl CreateControl(); } } diff --git a/osu.Game/Overlays/TabControlOverlayHeader.cs b/osu.Game/Overlays/TabControlOverlayHeader.cs index 8570bf63b8..f8683b3e7d 100644 --- a/osu.Game/Overlays/TabControlOverlayHeader.cs +++ b/osu.Game/Overlays/TabControlOverlayHeader.cs @@ -1,10 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics.UserInterface; + namespace osu.Game.Overlays { - public abstract class TabControlOverlayHeader : OverlayHeader + public abstract class TabControlOverlayHeader : OverlayHeader { - protected override OverlayHeaderTabControl CreateControl() => new OverlayHeaderTabControl(); + protected OverlayHeaderTabControl TabControl; + + protected override TabControl CreateControl() => TabControl = new OverlayHeaderTabControl(); } } From 6ade46d752e743e784db0a451373f2cda5eaa87c Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Wed, 1 Jan 2020 06:38:59 +0000 Subject: [PATCH 4849/5608] Fix File Sharing on iOS 13 --- osu.iOS/Info.plist | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index 5ceccdf99f..a82fa9bcf4 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -14,15 +14,15 @@ 0.1.0 LSRequiresIPhoneOS - LSSupportsOpeningDocumentsInPlace - MinimumOSVersion 10.0 UIDeviceFamily 1 2 - + + UIFileSharingEnabled + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities @@ -51,7 +51,7 @@ UTTypeConformsTo - + public.data UTTypeIdentifier sh.ppy.osu.items @@ -104,7 +104,9 @@ LSHandlerRank Owner CFBundleTypeName - Supported osu! files + Supported osu! files + CFBundleTypeRole + Viewer LSItemContentTypes sh.ppy.osu.items From 47ca2804f6640a54693b9f4aba6573980a0c0682 Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Wed, 1 Jan 2020 06:41:17 +0000 Subject: [PATCH 4850/5608] Adjust Tab Performance --- osu.iOS/Info.plist | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index a82fa9bcf4..249474b1d7 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -20,9 +20,9 @@ 1 2 - - UIFileSharingEnabled - + + UIFileSharingEnabled + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities @@ -104,9 +104,9 @@ LSHandlerRank Owner CFBundleTypeName - Supported osu! files - CFBundleTypeRole - Viewer + Supported osu! files + CFBundleTypeRole + Viewer LSItemContentTypes sh.ppy.osu.items From ddec59ec9158c0f88ca9a35048de161f232c5bd6 Mon Sep 17 00:00:00 2001 From: Viktor Rosvall Date: Wed, 1 Jan 2020 12:22:19 +0100 Subject: [PATCH 4851/5608] Further refactoring. I think this may have polluted the FooterButton too much. Not sure what to do about the centering. --- osu.Game/Screens/Select/FooterButton.cs | 40 +++++++++++++-------- osu.Game/Screens/Select/FooterButtonMods.cs | 6 ++-- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index 7acb2fd221..869e9e8aa4 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -56,7 +56,8 @@ namespace osu.Game.Screens.Select } } - protected FillFlowContainer TextContainer; + protected FillFlowContainer ButtonContentContainer; + protected readonly Container TextContainer; protected readonly SpriteText SpriteText; private readonly Box box; private readonly Box light; @@ -80,24 +81,35 @@ namespace osu.Game.Screens.Select EdgeSmoothness = new Vector2(2, 0), RelativeSizeAxes = Axes.X, }, - TextContainer = new FillFlowContainer + new Container { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Direction = FillDirection.Horizontal, - Shear = -SHEAR, + AutoSizeAxes = Axes.Both, Children = new Drawable[] { - SpriteText = new OsuSpriteText + ButtonContentContainer = new FillFlowContainer { - Size = new Vector2(100 - SHEAR_WIDTH, 50), - Shear = SHEAR, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Horizontal, + Shear = -SHEAR, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Horizontal = SHEAR_WIDTH / 4 }, + Children = new Drawable[] + { + TextContainer = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(100 - SHEAR_WIDTH, 50), + Child = SpriteText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }, + }, + }, }, - AutoSizeAxes = Axes.Both, - // Margin = new MarginPadding { Left = 70, Right = 14 } }, }; } diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index a3453fee05..67b491cf9e 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -34,19 +34,19 @@ namespace osu.Game.Screens.Select public FooterButtonMods() { - TextContainer.Add(modDisplay = new FooterModDisplay + ButtonContentContainer.Add(modDisplay = new FooterModDisplay { Anchor = Anchor.Centre, Origin = Anchor.Centre, DisplayUnrankedText = false, Scale = new Vector2(0.8f) }); - TextContainer.Add(MultiplierText = new OsuSpriteText + ButtonContentContainer.Add(MultiplierText = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(weight: FontWeight.Bold), - // Margin = new MarginPadding { Right = 6 } + Margin = new MarginPadding { Right = 10 } }); } From 4f2fa2626acf8a7b7193a40cceffb584626cd972 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 1 Jan 2020 21:24:00 +0900 Subject: [PATCH 4852/5608] Centralise calls to mutable hitobjects list --- osu.Game/OsuGameBase.cs | 4 ++++ osu.Game/Screens/Edit/EditorBeatmap.cs | 12 +++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 22b8d9d012..41aa15b381 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; +using ManagedBass; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; @@ -125,6 +126,9 @@ namespace osu.Game [BackgroundDependencyLoader] private void load() { + Bass.Configure(ManagedBass.Configuration.DeviceBufferLength, 2); + Bass.Configure(ManagedBass.Configuration.DevicePeriod, -512); + Resources.AddStore(new DllResourceStore(@"osu.Game.Resources.dll")); dependencies.Cache(contextFactory = new DatabaseContextFactory(Storage)); diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index 5a45ea05a0..b4177432e0 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -62,6 +62,8 @@ namespace osu.Game.Screens.Edit public IBeatmap Clone() => (EditorBeatmap)MemberwiseClone(); + private IList mutableHitObjects => (IList)beatmap.HitObjects; + /// /// Adds a to this . /// @@ -72,7 +74,7 @@ namespace osu.Game.Screens.Edit // Preserve existing sorting order in the beatmap var insertionIndex = findInsertionIndex(beatmap.HitObjects, hitObject.StartTime); - ((IList)beatmap.HitObjects).Insert(insertionIndex + 1, hitObject); + mutableHitObjects.Insert(insertionIndex + 1, hitObject); HitObjectAdded?.Invoke(hitObject); } @@ -83,10 +85,10 @@ namespace osu.Game.Screens.Edit /// The to add. public void Remove(HitObject hitObject) { - if (!((IList)beatmap.HitObjects).Contains(hitObject)) + if (!mutableHitObjects.Contains(hitObject)) return; - ((IList)beatmap.HitObjects).Remove(hitObject); + mutableHitObjects.Remove(hitObject); var bindable = startTimeBindables[hitObject]; bindable.UnbindAll(); @@ -101,10 +103,10 @@ namespace osu.Game.Screens.Edit startTimeBindables[hitObject].ValueChanged += _ => { // For now we'll remove and re-add the hitobject. This is not optimal and can be improved if required. - ((IList)beatmap.HitObjects).Remove(hitObject); + mutableHitObjects.Remove(hitObject); var insertionIndex = findInsertionIndex(beatmap.HitObjects, hitObject.StartTime); - ((IList)beatmap.HitObjects).Insert(insertionIndex + 1, hitObject); + mutableHitObjects.Insert(insertionIndex + 1, hitObject); StartTimeChanged?.Invoke(hitObject); }; From e4bbdb1956955e640586af30b6a52460ae302589 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 2 Jan 2020 00:41:06 +0900 Subject: [PATCH 4853/5608] Fix regressing test --- .../Editor/TestSceneHitObjectComposerDistanceSnapping.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs b/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs index b94f08aeaa..2d336bd19c 100644 --- a/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs +++ b/osu.Game.Tests/Editor/TestSceneHitObjectComposerDistanceSnapping.cs @@ -2,9 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Testing; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Edit; using osu.Game.Screens.Edit; using osu.Game.Tests.Visual; @@ -16,6 +18,9 @@ namespace osu.Game.Tests.Editor { private TestHitObjectComposer composer; + [Cached(typeof(EditorBeatmap))] + private readonly EditorBeatmap editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + [SetUp] public void Setup() => Schedule(() => { From 2d6482f586da3cf77e0b1a50a7785754f6c1d167 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 2 Jan 2020 01:23:21 +0900 Subject: [PATCH 4854/5608] Fix remaining tests --- .../Visual/Editor/TestSceneComposeScreen.cs | 15 ++++++++++++++- .../Visual/Editor/TestSceneHitObjectComposer.cs | 4 ++++ .../Visual/Editor/TestSceneTimingScreen.cs | 8 ++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneComposeScreen.cs b/osu.Game.Tests/Visual/Editor/TestSceneComposeScreen.cs index 9f16e1d781..3562689482 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneComposeScreen.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneComposeScreen.cs @@ -4,6 +4,8 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose; namespace osu.Game.Tests.Visual.Editor @@ -11,10 +13,21 @@ namespace osu.Game.Tests.Visual.Editor [TestFixture] public class TestSceneComposeScreen : EditorClockTestScene { + [Cached(typeof(EditorBeatmap))] + private readonly EditorBeatmap editorBeatmap = + new EditorBeatmap(new OsuBeatmap + { + BeatmapInfo = + { + Ruleset = new OsuRuleset().RulesetInfo + } + }); + [BackgroundDependencyLoader] private void load() { - Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + Beatmap.Value = CreateWorkingBeatmap(editorBeatmap.PlayableBeatmap); + Child = new ComposeScreen(); } } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs b/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs index b7c7028b52..c001c83877 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs @@ -16,6 +16,7 @@ using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose.Components; using osuTK; @@ -59,9 +60,12 @@ namespace osu.Game.Tests.Visual.Editor }, }); + var editorBeatmap = new EditorBeatmap(Beatmap.Value.GetPlayableBeatmap(new OsuRuleset().RulesetInfo)); + var clock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; Dependencies.CacheAs(clock); Dependencies.CacheAs(clock); + Dependencies.CacheAs(editorBeatmap); Child = new OsuHitObjectComposer(new OsuRuleset()); } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs index 121853d8d0..adfed9a299 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs @@ -5,7 +5,8 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Timing; namespace osu.Game.Tests.Visual.Editor @@ -25,10 +26,13 @@ namespace osu.Game.Tests.Visual.Editor typeof(RowAttribute) }; + [Cached(typeof(EditorBeatmap))] + private readonly EditorBeatmap editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + [BackgroundDependencyLoader] private void load() { - Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + Beatmap.Value = CreateWorkingBeatmap(editorBeatmap.PlayableBeatmap); Child = new TimingScreen(); } } From af248457b02b9380c49dc09d8dd2085b9ebe7766 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 1 Jan 2020 22:49:04 +0300 Subject: [PATCH 4855/5608] Implement OverlayRulesetSelector --- .../TestSceneOverlayRulesetSelector.cs | 68 +++++++++++++ osu.Game/Overlays/OverlayRulesetSelector.cs | 44 +++++++++ osu.Game/Overlays/OverlayRulesetTabItem.cs | 98 +++++++++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs create mode 100644 osu.Game/Overlays/OverlayRulesetSelector.cs create mode 100644 osu.Game/Overlays/OverlayRulesetTabItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs new file mode 100644 index 0000000000..6c921b13b4 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs @@ -0,0 +1,68 @@ +// 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 System; +using System.Collections.Generic; +using osu.Game.Rulesets.Catch; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Taiko; +using osu.Framework.Bindables; +using osu.Game.Overlays; +using osu.Game.Rulesets; +using NUnit.Framework; +using osu.Game.Graphics; +using osu.Framework.Allocation; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneOverlayRulesetSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OverlayRulesetSelector), + typeof(OverlayRulesetTabItem), + }; + + private readonly OverlayRulesetSelector selector; + private readonly Bindable ruleset = new Bindable(); + + public TestSceneOverlayRulesetSelector() + { + Add(selector = new OverlayRulesetSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = ruleset, + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + selector.AccentColour = colours.Lime; + } + + [Test] + public void TestSelection() + { + var osuRuleset = new OsuRuleset().RulesetInfo; + var maniaRuleset = new ManiaRuleset().RulesetInfo; + var taikoRuleset = new TaikoRuleset().RulesetInfo; + var catchRuleset = new CatchRuleset().RulesetInfo; + + AddStep("Select osu!", () => ruleset.Value = osuRuleset); + AddAssert("Check osu! selected", () => selector.Current.Value == osuRuleset); + + AddStep("Select mania", () => ruleset.Value = maniaRuleset); + AddAssert("Check mania selected", () => selector.Current.Value == maniaRuleset); + + AddStep("Select taiko", () => ruleset.Value = taikoRuleset); + AddAssert("Check taiko selected", () => selector.Current.Value == taikoRuleset); + + AddStep("Select catch", () => ruleset.Value = catchRuleset); + AddAssert("Check catch selected", () => selector.Current.Value == catchRuleset); + } + } +} diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs new file mode 100644 index 0000000000..1dcfc97562 --- /dev/null +++ b/osu.Game/Overlays/OverlayRulesetSelector.cs @@ -0,0 +1,44 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using osu.Game.Rulesets; +using osuTK; +using osuTK.Graphics; +using System.Linq; + +namespace osu.Game.Overlays +{ + public class OverlayRulesetSelector : RulesetSelector + { + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + accentColour = value; + foreach (var i in TabContainer.Children.OfType()) + i.AccentColour = value; + } + } + + public OverlayRulesetSelector() + { + AutoSizeAxes = Axes.Both; + } + + protected override TabItem CreateTabItem(RulesetInfo value) => new OverlayRulesetTabItem(value); + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(25, 0), + }; + } +} diff --git a/osu.Game/Overlays/OverlayRulesetTabItem.cs b/osu.Game/Overlays/OverlayRulesetTabItem.cs new file mode 100644 index 0000000000..9d6d28a81f --- /dev/null +++ b/osu.Game/Overlays/OverlayRulesetTabItem.cs @@ -0,0 +1,98 @@ +// 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.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets; +using osuTK.Graphics; +using osuTK; + +namespace osu.Game.Overlays +{ + public class OverlayRulesetTabItem : TabItem, IHasAccentColour + { + protected readonly OsuSpriteText Text; + private readonly FillFlowContainer content; + + public override bool PropagatePositionalInputSubTree => Enabled.Value && !Active.Value && base.PropagatePositionalInputSubTree; + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) + return; + + accentColour = value; + + UpdateState(); + } + } + + protected override Container Content => content; + + public OverlayRulesetTabItem(RulesetInfo value) + : base(value) + { + AutoSizeAxes = Axes.Both; + + AddRangeInternal(new Drawable[] + { + content = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(3, 0), + Child = Text = new OsuSpriteText + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Text = value.Name, + } + }, + new HoverClickSounds() + }); + + Enabled.Value = true; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Enabled.BindValueChanged(_ => UpdateState(), true); + } + + protected override bool OnHover(HoverEvent e) + { + base.OnHover(e); + UpdateState(); + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + UpdateState(); + } + + protected override void OnActivated() => UpdateState(); + + protected override void OnDeactivated() => UpdateState(); + + protected virtual void UpdateState() + { + Text.Font = Text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Medium); + Text.FadeColour(GetColour(), 120, Easing.OutQuint); + } + + protected Color4 GetColour() => IsHovered || Active.Value ? Color4.White : Enabled.Value ? AccentColour : Color4.DimGray; + } +} From b016238c16f8ac0d8e2c6e97d1e2559c6c58930e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 1 Jan 2020 22:55:28 +0300 Subject: [PATCH 4856/5608] Make ProfileRulesetSelector inherit from OverlayRulesetSelector --- .../Online/TestSceneProfileRulesetSelector.cs | 2 +- .../Components/ProfileRulesetSelector.cs | 33 +------ .../Components/ProfileRulesetTabItem.cs | 97 +++---------------- 3 files changed, 20 insertions(+), 112 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs index 1f5ba67e03..a36b6880d2 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.Online public TestSceneProfileRulesetSelector() { ProfileRulesetSelector selector; - Bindable user = new Bindable(); + var user = new Bindable(); Child = selector = new ProfileRulesetSelector { diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs index 2c9a3dd5f9..e63102f989 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs @@ -3,37 +3,21 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Rulesets; using osu.Game.Users; -using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { - public class ProfileRulesetSelector : RulesetSelector + public class ProfileRulesetSelector : OverlayRulesetSelector { - private Color4 accentColour = Color4.White; - public readonly Bindable User = new Bindable(); - public ProfileRulesetSelector() - { - TabContainer.Masking = false; - TabContainer.Spacing = new Vector2(10, 0); - AutoSizeAxes = Axes.Both; - } - [BackgroundDependencyLoader] private void load(OsuColour colours) { - accentColour = colours.Seafoam; - - foreach (TabItem tabItem in TabContainer) - ((ProfileRulesetTabItem)tabItem).AccentColour = accentColour; + AccentColour = colours.Seafoam; } protected override void LoadComplete() @@ -45,19 +29,10 @@ namespace osu.Game.Overlays.Profile.Header.Components public void SetDefaultRuleset(RulesetInfo ruleset) { - foreach (TabItem tabItem in TabContainer) + foreach (var tabItem in TabContainer) ((ProfileRulesetTabItem)tabItem).IsDefault = ((ProfileRulesetTabItem)tabItem).Value.ID == ruleset.ID; } - protected override TabItem CreateTabItem(RulesetInfo value) => new ProfileRulesetTabItem(value) - { - AccentColour = accentColour - }; - - protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - }; + protected override TabItem CreateTabItem(RulesetInfo value) => new ProfileRulesetTabItem(value); } } diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs index b5170ea3a2..adf324b259 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs @@ -2,38 +2,21 @@ // 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.Sprites; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Events; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { - public class ProfileRulesetTabItem : TabItem, IHasAccentColour + public class ProfileRulesetTabItem : OverlayRulesetTabItem { - private readonly OsuSpriteText text; private readonly SpriteIcon icon; - private Color4 accentColour; - - public Color4 AccentColour + public new Color4 AccentColour { - get => accentColour; - set - { - if (accentColour == value) - return; - - accentColour = value; - - updateState(); - } + get => base.AccentColour; + set => base.AccentColour = icon.Colour = value; } private bool isDefault; @@ -55,71 +38,21 @@ namespace osu.Game.Overlays.Profile.Header.Components public ProfileRulesetTabItem(RulesetInfo value) : base(value) { - AutoSizeAxes = Axes.Both; - - Children = new Drawable[] + Add(icon = new SpriteIcon { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Origin = Anchor.BottomLeft, - Anchor = Anchor.BottomLeft, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(3, 0), - Children = new Drawable[] - { - text = new OsuSpriteText - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Text = value.Name, - }, - icon = new SpriteIcon - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Alpha = 0, - AlwaysPresent = true, - Icon = FontAwesome.Solid.Star, - Size = new Vector2(12), - }, - } - }, - new HoverClickSounds() - }; + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Alpha = 0, + AlwaysPresent = true, + Icon = FontAwesome.Solid.Star, + Size = new Vector2(12), + }); } - protected override bool OnHover(HoverEvent e) + protected override void UpdateState() { - base.OnHover(e); - updateState(); - return true; - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - updateState(); - } - - protected override void OnActivated() => updateState(); - - protected override void OnDeactivated() => updateState(); - - private void updateState() - { - text.Font = text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Medium); - - if (IsHovered || Active.Value) - { - text.FadeColour(Color4.White, 120, Easing.InQuad); - icon.FadeColour(Color4.White, 120, Easing.InQuad); - } - else - { - text.FadeColour(AccentColour, 120, Easing.InQuad); - icon.FadeColour(AccentColour, 120, Easing.InQuad); - } + base.UpdateState(); + icon.FadeColour(GetColour(), 120, Easing.OutQuint); } } } From 2d6a07e970420893feea193e778f1ff3cc28e4f9 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 1 Jan 2020 23:14:26 +0300 Subject: [PATCH 4857/5608] Fix OverlayRulesetSelector don't have default colour --- .../TestSceneOverlayRulesetSelector.cs | 35 +++++++++---------- osu.Game/Overlays/OverlayRulesetSelector.cs | 8 +++++ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs index 6c921b13b4..93aa414c94 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs @@ -25,6 +25,9 @@ namespace osu.Game.Tests.Visual.UserInterface typeof(OverlayRulesetTabItem), }; + [Resolved] + private OsuColour colours { get; set; } + private readonly OverlayRulesetSelector selector; private readonly Bindable ruleset = new Bindable(); @@ -38,31 +41,27 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - selector.AccentColour = colours.Lime; - } - [Test] public void TestSelection() { - var osuRuleset = new OsuRuleset().RulesetInfo; - var maniaRuleset = new ManiaRuleset().RulesetInfo; - var taikoRuleset = new TaikoRuleset().RulesetInfo; - var catchRuleset = new CatchRuleset().RulesetInfo; + AddStep("Select osu!", () => ruleset.Value = new OsuRuleset().RulesetInfo); + AddAssert("Check osu! selected", () => selector.Current.Value.Equals(new OsuRuleset().RulesetInfo)); - AddStep("Select osu!", () => ruleset.Value = osuRuleset); - AddAssert("Check osu! selected", () => selector.Current.Value == osuRuleset); + AddStep("Select mania", () => ruleset.Value = new ManiaRuleset().RulesetInfo); + AddAssert("Check mania selected", () => selector.Current.Value.Equals(new ManiaRuleset().RulesetInfo)); - AddStep("Select mania", () => ruleset.Value = maniaRuleset); - AddAssert("Check mania selected", () => selector.Current.Value == maniaRuleset); + AddStep("Select taiko", () => ruleset.Value = new TaikoRuleset().RulesetInfo); + AddAssert("Check taiko selected", () => selector.Current.Value.Equals(new TaikoRuleset().RulesetInfo)); - AddStep("Select taiko", () => ruleset.Value = taikoRuleset); - AddAssert("Check taiko selected", () => selector.Current.Value == taikoRuleset); + AddStep("Select catch", () => ruleset.Value = new CatchRuleset().RulesetInfo); + AddAssert("Check catch selected", () => selector.Current.Value.Equals(new CatchRuleset().RulesetInfo)); + } - AddStep("Select catch", () => ruleset.Value = catchRuleset); - AddAssert("Check catch selected", () => selector.Current.Value == catchRuleset); + [Test] + public void TestColours() + { + AddStep("Set colour to blue", () => selector.AccentColour = colours.Blue); + AddAssert("Check colour is blue", () => selector.AccentColour == colours.Blue); } } } diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs index 1dcfc97562..da49335250 100644 --- a/osu.Game/Overlays/OverlayRulesetSelector.cs +++ b/osu.Game/Overlays/OverlayRulesetSelector.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; @@ -32,6 +33,13 @@ namespace osu.Game.Overlays AutoSizeAxes = Axes.Both; } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + if (accentColour == default) + AccentColour = colours.Pink; + } + protected override TabItem CreateTabItem(RulesetInfo value) => new OverlayRulesetTabItem(value); protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer From 09cd66adb0c165817bd3f776dc2a5d43d222599d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Jan 2020 14:07:22 +0900 Subject: [PATCH 4858/5608] Fix storyboard samples not loading from subfolders --- osu.Game/Skinning/LegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 48c520986a..671d37fda4 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -175,7 +175,7 @@ namespace osu.Game.Skinning { foreach (var lookup in sampleInfo.LookupNames) { - var sample = Samples?.Get(getFallbackName(lookup)); + var sample = Samples?.Get(lookup); if (sample != null) return sample; From 546f64f951f7dc9c4e402ace175bea324aa17ffa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 2 Jan 2020 14:19:31 +0900 Subject: [PATCH 4859/5608] Method to property --- osu.Game/Graphics/UserInterface/BreadcrumbControl.cs | 2 +- osu.Game/Graphics/UserInterface/OsuTabControl.cs | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index d4705c539a..c98280bc75 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -23,7 +23,7 @@ namespace osu.Game.Graphics.UserInterface AccentColour = AccentColour, }; - protected override float StripWidth() => base.StripWidth() - (padding + ItemChevronSize); + protected override float StripWidth => base.StripWidth - (padding + ItemChevronSize); public BreadcrumbControl() { diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 064cba6adf..a6ee666e1d 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -28,8 +28,9 @@ namespace osu.Game.Graphics.UserInterface protected override TabItem CreateTabItem(T value) => new OsuTabItem(value); - protected virtual float StripWidth() => TabContainer.Children.Sum(c => c.IsPresent ? c.DrawWidth + TabContainer.Spacing.X : 0) - TabContainer.Spacing.X; - protected virtual float StripHeight() => 1; + protected virtual float StripWidth => TabContainer.Children.Sum(c => c.IsPresent ? c.DrawWidth + TabContainer.Spacing.X : 0) - TabContainer.Spacing.X; + + protected virtual float StripHeight => 1; /// /// Whether entries should be automatically populated if is an type. @@ -46,7 +47,7 @@ namespace osu.Game.Graphics.UserInterface { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Height = StripHeight(), + Height = StripHeight, Colour = Color4.White.Opacity(0), }); @@ -99,7 +100,7 @@ namespace osu.Game.Graphics.UserInterface // dont bother calculating if the strip is invisible if (strip.Colour.MaxAlpha > 0) - strip.Width = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); + strip.Width = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth, 0, 500, Easing.OutQuint); } public class OsuTabItem : TabItem, IHasAccentColour From 43903b2feabc1785763d88253d84d23690468a99 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 2 Jan 2020 14:24:58 +0900 Subject: [PATCH 4860/5608] Make test scene usable --- ...{TestSceneBreadcrumbs.cs => TestSceneBreadcrumbControl.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{TestSceneBreadcrumbs.cs => TestSceneBreadcrumbControl.cs} (92%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbs.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs similarity index 92% rename from osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbs.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs index 554696765e..19eebc89b6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbs.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs @@ -10,11 +10,11 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneBreadcrumbs : OsuTestScene + public class TestSceneBreadcrumbControl : OsuTestScene { private readonly BreadcrumbControl breadcrumbs; - public TestSceneBreadcrumbs() + public TestSceneBreadcrumbControl() { Add(breadcrumbs = new BreadcrumbControl { From d1d19c2cd9dbcf9f575bfbfbb49f6d0c0ee86dd3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 2 Jan 2020 14:26:40 +0900 Subject: [PATCH 4861/5608] Move chevron size implementation --- .../Graphics/UserInterface/BreadcrumbControl.cs | 14 +++++++------- .../Overlays/OverlayHeaderBreadcrumbControl.cs | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index c98280bc75..e2438cc4cd 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -16,14 +16,12 @@ namespace osu.Game.Graphics.UserInterface { private const float padding = 10; - protected virtual float ItemChevronSize => 10; - - protected override TabItem CreateTabItem(T value) => new BreadcrumbTabItem(value, ItemChevronSize) + protected override TabItem CreateTabItem(T value) => new BreadcrumbTabItem(value) { AccentColour = AccentColour, }; - protected override float StripWidth => base.StripWidth - (padding + ItemChevronSize); + protected override float StripWidth => base.StripWidth - TabContainer.FirstOrDefault()?.Padding.Right ?? 0; public BreadcrumbControl() { @@ -44,6 +42,8 @@ namespace osu.Game.Graphics.UserInterface protected class BreadcrumbTabItem : OsuTabItem, IStateful { + protected virtual float ChevronSize => 10; + public event Action StateChanged; public readonly SpriteIcon Chevron; @@ -86,17 +86,17 @@ namespace osu.Game.Graphics.UserInterface public override void Show() => State = Visibility.Visible; - public BreadcrumbTabItem(T value, float itemChevronSize) + public BreadcrumbTabItem(T value) : base(value) { Text.Font = Text.Font.With(size: 18); Text.Margin = new MarginPadding { Vertical = 8 }; - Padding = new MarginPadding { Right = padding + itemChevronSize }; + Padding = new MarginPadding { Right = padding + ChevronSize }; Add(Chevron = new SpriteIcon { Anchor = Anchor.CentreRight, Origin = Anchor.CentreLeft, - Size = new Vector2(itemChevronSize), + Size = new Vector2(ChevronSize), Icon = FontAwesome.Solid.ChevronRight, Margin = new MarginPadding { Left = padding }, Alpha = 0f, diff --git a/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs b/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs index eee43ec229..34941c5647 100644 --- a/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs +++ b/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs @@ -14,14 +14,14 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.X; } - protected override float ItemChevronSize => 8; - - protected override TabItem CreateTabItem(string value) => new ControlTabItem(value, ItemChevronSize); + protected override TabItem CreateTabItem(string value) => new ControlTabItem(value); private class ControlTabItem : BreadcrumbTabItem { - public ControlTabItem(string value, float itemChevronSize) - : base(value, itemChevronSize) + protected override float ChevronSize => 8; + + public ControlTabItem(string value) + : base(value) { Text.Font = Text.Font.With(size: 14); Chevron.Y = 3; From 0f8a76afde9250052696fff81b32d133f5f6628a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Jan 2020 14:26:32 +0900 Subject: [PATCH 4862/5608] Remove manual hitobject sample namespacing --- .../Audio/DrumSampleMapping.cs | 4 -- .../Drawables/DrawableTaikoHitObject.cs | 2 - .../Skinning/TaikoLegacySkinTransformer.cs | 55 +++++++++++++++++++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 4 ++ osu.Game/Audio/HitSampleInfo.cs | 14 ----- .../Objects/Drawables/DrawableHitObject.cs | 9 +-- 6 files changed, 60 insertions(+), 28 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs diff --git a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs index aaf113f216..c31b07344d 100644 --- a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs +++ b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs @@ -26,10 +26,6 @@ namespace osu.Game.Rulesets.Taiko.Audio var centre = s.GetSampleInfo(); var rim = s.GetSampleInfo(HitSampleInfo.HIT_CLAP); - // todo: this is ugly - centre.Namespace = "taiko"; - rim.Namespace = "taiko"; - mappings[s.Time] = new DrumSample { Centre = addSound(centre), diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 2da5a9c403..b9d31ff906 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -166,8 +166,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables // Normal and clap samples are handled by the drum protected override IEnumerable GetSamples() => HitObject.Samples.Where(s => s.Name != HitSampleInfo.HIT_NORMAL && s.Name != HitSampleInfo.HIT_CLAP); - protected override string SampleNamespace => "taiko"; - protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(); /// diff --git a/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs new file mode 100644 index 0000000000..381cd14cd4 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Skinning/TaikoLegacySkinTransformer.cs @@ -0,0 +1,55 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Textures; +using osu.Game.Audio; +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Taiko.Skinning +{ + public class TaikoLegacySkinTransformer : ISkin + { + private readonly ISkinSource source; + + public TaikoLegacySkinTransformer(ISkinSource source) + { + this.source = source; + } + + public Drawable GetDrawableComponent(ISkinComponent component) => source.GetDrawableComponent(component); + + public Texture GetTexture(string componentName) => source.GetTexture(componentName); + + public SampleChannel GetSample(ISampleInfo sampleInfo) => source.GetSample(new LegacyTaikoSampleInfo(sampleInfo)); + + public IBindable GetConfig(TLookup lookup) => source.GetConfig(lookup); + + private class LegacyTaikoSampleInfo : ISampleInfo + { + private readonly ISampleInfo source; + + public LegacyTaikoSampleInfo(ISampleInfo source) + { + this.source = source; + } + + public IEnumerable LookupNames + { + get + { + foreach (var name in source.LookupNames) + yield return $"taiko-{name}"; + + foreach (var name in source.LookupNames) + yield return name; + } + } + + public int Volume => source.Volume; + } + } +} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 777b68a993..536cbdc562 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -21,6 +21,8 @@ using osu.Game.Rulesets.Taiko.Difficulty; using osu.Game.Rulesets.Taiko.Scoring; using osu.Game.Scoring; using System; +using osu.Game.Rulesets.Taiko.Skinning; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko { @@ -34,6 +36,8 @@ namespace osu.Game.Rulesets.Taiko public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap, this); + public override ISkin CreateLegacySkinProvider(ISkinSource source) => new TaikoLegacySkinTransformer(source); + public const string SHORT_NAME = "taiko"; public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 23a74d3fa6..f6b0107bd2 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -17,11 +17,6 @@ namespace osu.Game.Audio public const string HIT_NORMAL = @"hitnormal"; public const string HIT_CLAP = @"hitclap"; - /// - /// An optional ruleset namespace. - /// - public string Namespace; - /// /// The bank to load the sample from. /// @@ -49,15 +44,6 @@ namespace osu.Game.Audio { get { - if (!string.IsNullOrEmpty(Namespace)) - { - if (!string.IsNullOrEmpty(Suffix)) - yield return $"{Namespace}/{Bank}-{Name}{Suffix}"; - - yield return $"{Namespace}/{Bank}-{Name}"; - } - - // check non-namespace as a fallback even when we have a namespace if (!string.IsNullOrEmpty(Suffix)) yield return $"{Bank}-{Name}{Suffix}"; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index a959fee9be..4ac30fe7fb 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -31,9 +31,6 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public readonly Bindable AccentColour = new Bindable(Color4.Gray); - // Todo: Rulesets should be overriding the resources instead, but we need to figure out where/when to apply overrides first - protected virtual string SampleNamespace => null; - protected SkinnableSound Samples { get; private set; } protected virtual IEnumerable GetSamples() => HitObject.Samples; @@ -154,11 +151,7 @@ namespace osu.Game.Rulesets.Objects.Drawables + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); } - samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray(); - foreach (var s in samples) - s.Namespace = SampleNamespace; - - AddInternal(Samples = new SkinnableSound(samples)); + AddInternal(Samples = new SkinnableSound(samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)))); } private void onDefaultsApplied() => apply(HitObject); From 878e9f182e1e1fc7d3ba6e8b3b5961df208fca3e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Jan 2020 15:23:41 +0900 Subject: [PATCH 4863/5608] Add storyboard sample test scene --- .../Gameplay/TestSceneStoryboardSamples.cs | 74 ++++++++++++++++++ osu.Game.Tests/Resources/test-sample.mp3 | Bin 0 -> 94525 bytes osu.Game/Tests/Visual/OsuTestScene.cs | 4 +- 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs create mode 100644 osu.Game.Tests/Resources/test-sample.mp3 diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs new file mode 100644 index 0000000000..5deb136c85 --- /dev/null +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -0,0 +1,74 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using NUnit.Framework; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.IO.Stores; +using osu.Game.Audio; +using osu.Game.Skinning; +using osu.Game.Tests.Resources; +using osu.Game.Tests.Visual; + +namespace osu.Game.Tests.Gameplay +{ + public class TestSceneStoryboardSamples : OsuTestScene + { + [Test] + public void TestRetrieveTopLevelSample() + { + ISkin skin = null; + SampleChannel channel = null; + + AddStep("create skin", () => skin = new TestSkin("test-sample", Audio)); + AddStep("retrieve sample", () => channel = skin.GetSample(new SampleInfo("test-sample"))); + + AddAssert("sample is non-null", () => channel != null); + } + + [Test] + public void TestRetrieveSampleInSubFolder() + { + ISkin skin = null; + SampleChannel channel = null; + + AddStep("create skin", () => skin = new TestSkin("folder/test-sample", Audio)); + AddStep("retrieve sample", () => channel = skin.GetSample(new SampleInfo("folder/test-sample"))); + + AddAssert("sample is non-null", () => channel != null); + } + + private class TestSkin : LegacySkin + { + public TestSkin(string resourceName, AudioManager audioManager) + : base(DefaultLegacySkin.Info, new TestResourceStore(resourceName), audioManager, "skin.ini") + { + } + } + + private class TestResourceStore : IResourceStore + { + private readonly string resourceName; + + public TestResourceStore(string resourceName) + { + this.resourceName = resourceName; + } + + public byte[] Get(string name) => name == resourceName ? TestResources.GetStore().Get("Resources/test-sample.mp3") : null; + + public Task GetAsync(string name) => name == resourceName ? TestResources.GetStore().GetAsync("Resources/test-sample.mp3") : null; + + public Stream GetStream(string name) => name == resourceName ? TestResources.GetStore().GetStream("Resources/test-sample.mp3") : null; + + public IEnumerable GetAvailableResources() => new[] { resourceName }; + + public void Dispose() + { + } + } + } +} diff --git a/osu.Game.Tests/Resources/test-sample.mp3 b/osu.Game.Tests/Resources/test-sample.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..f7c344f39ae4fa90c747a80957c69c5fd4b21c0e GIT binary patch literal 94525 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

2pZ3Dxqu% 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

lZ$27b)H1)- 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 G7x-_d5di@J literal 0 HcmV?d00001 diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 18dbd212cc..8926c76018 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -105,7 +105,7 @@ namespace osu.Game.Tests.Visual } [Resolved] - private AudioManager audio { get; set; } + protected AudioManager Audio { get; private set; } protected virtual IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset); @@ -113,7 +113,7 @@ namespace osu.Game.Tests.Visual CreateWorkingBeatmap(CreateBeatmap(ruleset), null); protected virtual WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => - new ClockBackedTestWorkingBeatmap(beatmap, storyboard, Clock, audio); + new ClockBackedTestWorkingBeatmap(beatmap, storyboard, Clock, Audio); [BackgroundDependencyLoader] private void load(RulesetStore rulesets) From cba6d9f7e644ea46b556b833cf2251a403cbee5c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Jan 2020 15:58:11 +0900 Subject: [PATCH 4864/5608] Fix taiko samples not being loaded --- .../Samples/Gameplay/normal-hitclap.wav | Bin 0 -> 519970 bytes .../Samples/Gameplay/normal-hitfinish.wav | Bin 0 -> 520074 bytes .../Samples/Gameplay/normal-hitnormal.wav | Bin 0 -> 389074 bytes .../Samples/Gameplay/normal-hitwhistle.wav | Bin 0 -> 717250 bytes .../Samples/Gameplay/soft-hitclap.wav | Bin 0 -> 573290 bytes .../Samples/Gameplay/soft-hitfinish.wav | Bin 0 -> 447418 bytes .../Samples/Gameplay/soft-hitnormal.wav | Bin 0 -> 218578 bytes .../Samples/Gameplay/soft-hitwhistle.wav | Bin 0 -> 650922 bytes 8 files changed, 0 insertions(+), 0 deletions(-) create mode 100755 osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitclap.wav create mode 100755 osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitfinish.wav create mode 100755 osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitnormal.wav create mode 100755 osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitwhistle.wav create mode 100755 osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitclap.wav create mode 100755 osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitfinish.wav create mode 100755 osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitnormal.wav create mode 100755 osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitwhistle.wav diff --git a/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitclap.wav b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitclap.wav new file mode 100755 index 0000000000000000000000000000000000000000..9ea2be585516a72ebae49f772b53fece207fa136 GIT binary patch literal 519970 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

=ppuLqb+3L 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

RoAtMb|b9zJ=8| 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 >E!>L*bj8 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

tFR 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

nQGn3r64}5J;&RaW= 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

z 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 NeLFhf%H@ef{sEMJC3ye< literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitfinish.wav b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/normal-hitfinish.wav new file mode 100755 index 0000000000000000000000000000000000000000..af270ae12a170eef81ef9def99a01a386d5fdfb1 GIT binary patch literal 520074 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

mcsw7o`c8&f+~3qxF?n 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

  • f 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

    _kKKjzFuPDBzg{w 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

    }q7Ye($1dau2avvW`)K`xDseq?L4S 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 Th5kiXrt=cFl6`>+TDqEB#+cW2uWJwF6 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

  • ZBSQj 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

    hozX^ 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≦KJ& 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%0DBtLvi0&<95P&wt4y1r?!Qg)jeWP# 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ȆisHgS|Zwg(w3v7jc8o@LF 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�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

    eVV{eT6U=MH=!`=y+9RW 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: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%0DNnwEXCc7p*Wh*O__?ib*UppO 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≪8iXb!V2 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%0A9_SfRsC(4@Idnc(pj;tB` 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≥ zwJe=?H2z3KZt8sO%6-~obeOM?I7`ho?Bl?_2dVM5d(G3G6lfPHrYO43#v^OZ^sL5+k79)OzH|{p9Elw^e`|#7>;2nX^`|c3LA#rhT6~Ku+P$Oka==D zZVj!1Wipdc*maVj*^5utHdne1dbV$k$Lplx(Qpl~i3NFqgA*?7n2zt8bU?RJ88~pB zD}JyPcJrcc_%S;ZDYOr!#2rUF9Ehboj$?-Ha5UePiB%qq#qEPKOXkie+A%CWb2iS- z&A?^62yV{5~G(uo>_yTX&PFn=?e3n%Ay ziv-Mh7>~|dcA$yJM(o@;5v9uqv;C9tTb^Y2D(qHWn3xu~2g@1w;^jYkF?RV}Ty}P! zbZJb&4wLrd($z!p`n>%(%&Z5_&f15cTRP&~pL_AdW-HwHeK!XFY9QJ1WGvsbIpO1rf6T@&p(hB%-ZZ*C++XrlR zEW_*jYJl<5IryRcR?WA=M2y_f-QMfL5PaBugg!L9Cr-Bis#`fZqw{N5I`zf|_dQ-k zWz(DC+);^?ajp&;?l@096Va1p~>el;@*)-{DVF6ZZL70Aq!t@^|k|2;6PY zzSB-Zprd%YyX=E`6W#gx^k~Si8^bF_!?wws&hAxuL3dur#T$)a@aUENHdNOR1_$xc zmd096$8i47by?bsm66=2Nr)cuZxipj_)#}{o4`R`?TC)<;$BX(=+@g5j+!1t&A$kX z=-(kKJh`7;{Bo$m@B>`@@Hsi3-_JLl{!-(Dz3f)L8b5uQ!tJY@^5QCqY_ZImXII_M zS9`UW{HieA#XDlUDTZBQMsvFz>v&GubT+sg%1cf!Wb1#cL?2qoKi!w`&YS>_cbdWb zUWD*ci?KYsi)8Aq^=G|sE!*Df!mkIfmpred?AO+F+x9lRYSVhI8DPd8Kdt5FwhcIF zfXvn9YO!CnHGFwXMNTphzf0yH8j~2n^Lz@Zb1i=!b@CE@`?-{F$};NUIB&L#jiDDF zv)K9kJX$hs5^vR4kt9Tn40`>K{c3!rP=h13p^k8l>EKtfT!6B`WCPjzBi4h>V{U7p z_!I{D$J5~908cn`{~(m=j4<@gK8VV#230QXfqQ+jwIkuXA*$I-t)N{Z9L}7HY$6 zv}EyEHtSYX`*-j&y)v<~Pn!LQc;WE0FGtGq3Nd7TKQ8q&cH?a)>-YmHl>-f2Rbx z?ze$r0>X(e_*1I)5}I{j9OX_QE;({rdgKQ*X!AdPS&KTKYSkLiIMMPAUSLXT6NnCnP=x>tN%^|{9K4#T<*d3fy;3I<|62yCS9~S z2KcYnD$I(gfdyp((e`Zvw0RPYCf!@$%-Z4DdTtvW_+~x2OmV>17dB!>atDmyt@!C- zCmh*45$k>Hibl=$;;!jk(bE1fF1Xnlzn^Bj`JW3mdVLJN10Au>zf))}oU`y3S?FDC zfwreE;O^HAaY^foXwjk;mbrQfC&rY+U0ttWQ2!!$P(2rOvTwkw4_DCp55v|`m+?^P zEzqG}4(=^p2^ncwXnLnFI7gqrCSOfp^o4Z15TC0RZ8(JUuMN=ZuSmh9bA`5d25rNt zhV}HE0UL2?^d@~|^KiVGTA)Ye`(xQ~W3pa04_7hL+Fj%DX3=o^*0(PXo3V&0b#q4U z7EHyS7TB_76xnR7i8UrBP?2*n{NB5pwm%o&(V;ZzRyG!H>^en9pAUfjM{?-k-Zxso z-#lt#7jOUT*gfiKvQD2>>Io%3Fr)OqXY@SKj~rcJQkRSSXllVr+GYNLDnz^_%i3jm zMYHGh$D`$-LQ{}Uf$$QXLi%Tnzz{OS`w8`zQLdNB+`V1*SS=30xjNfjUy^; zqA~GTn98lE4(Bg&;F4gv5psbq7_Oib&(H9+F>@$B>^PfTn@9`9w^?L6lAP)u;$;^G z(UEV-yzy)wYF0aea}KyrUSSlwEw-m0Z$fyacPpyhWI5aYGNWO8Jo$5h2|aM@$FKY< z(y+mf{G-Wp-8j&Umv`N-PwipI{B8A9d}qhN#Je(H&e#t}tW5Bt z*;bgbrx^xWhQpWbZLsG0`Ox`advu@PA8yE;R`sJ51mz4vn=PfmHhvPm6brX31qLtS5Ow^B!6OEhaR`rT+!aQQoWf&_ zTf?A?MSL>F7?NME;;-(XwfIkAd~9Tz_I_O?Z+HY^fyV?%jqAPK$0r~pss0_|HSCRhSInGJ>=43kH6wkctLce@Yi|1@Gy?k_v zb5lI2`neMfJco`9I>ryrdei+2#JPi)(&x;BY`JI|-Pw`C3!f~dOA*`n^pyqFW$#8_ zS#~m2%8ua4)do?=)Bt|C#E}ZOE#}_+jA%;46rS4niT<+55YD<5sc&)X!VTY5)#JC@ z@mZ~wed1Wj$oovujK>x<)xrKJF-2vWz zd}xmQQ3x9AOpgNdzs}FuE#C#uyaN6ge;txX8emcVGWh3gX%d_!#6uW!qpM7$DjNH zI!Ab-)ABpe>7pO@G`$2hL&MQ;WG2k57>8ZQr+}|b3Z6c&0eqV3Xz+Up)Nne9himtP z!uQ#D=Wugy3&}(OBcHWOo_DeA?A=<&K9A6NmV>r^%~SLnHpx!0hk8$`rEj-=frXB1 z^>y=~qsPmKdb_-*ICNz#x@-9u*Z6B>5b_Ya_w7$T*4)DyuG460#oOqxZ6&qyzk%5W z5fpgj8rsd;Boaa{u4%KKX5?PN^Q%(G?$Jf8eDV;TIh%vW^mJowG_qdz{a6GZ<~XJP%CespBVP~7x(9(}a!i00pB z(#`G`X#Q+6XR3(wVO_!O%Ll+Oy`heBU^eJ<4eQ)uBLT90rVy20Bvg(OtYQtP+rS$+J5;j<+-k- z*weMR`NIfm)YhC&Ok?7X4{ zq3{@+k1kC$Qp4DNNV2{)DN?!s>+0LO$8nrtRr~ehcJTP#qqO_I_pn>=1;~#tkE62aQvW{fOK9)+i?fDnhwl0(2A@C2_S1Fr5 z`_fM^b1R#EWZD;~XIVD=rLdcd#3|Ky&;v-kUn)Ie$|bNL`G?z{Plx8=-*{)w1W0&U z#Ng`>O=8~gGTWYT!RaaAUtb9>PrS?dL19`!QZ7fWZ<}gXHjBrbMdmenijE>*L4h`Jv}#Z!!Ajb8NZgTx169P=RnR#%cJ>Sm++EvPpQWZPyTc8KWct_ zAlG#)rZwYTd1|L$w6)NN-&y~oHa{Bh2e(pe+qn|2y(C=5m+xuJ;olU0B#Rc`|3NdN zH`CKk#gu!09L2RQq){Oi=&jESI=|9NU)K5_tzOVm3;lJ8EWR5-{^sLU)_Sq9Q}&Zr z!a+z&*+N&oKZU{x!F0KDCG7Hk0+rv;1YN7Pp@thAu>1HQdbgMTaGuphy|l?>jPyL2 z)-r7=e)@3B-n?EgHhv$b)puTx!D}9A#vYsS(bF1`UAPU0HERK}qGzQ2w1;PX_G23x z2XHQxiss{5!T3^yQ*P9TBg4}%)#i!ya(H_ zNvEQ~6wFS^qIWkFF}s`06}$u8XWyV{H50I%%N@!H-Hc1U?$P%?(b#$Wefm*v9r_-A zKrt4f81e2QnNE^>akYoks)BfD8r-K=52m8Q@jH~;ZvFIkZrEeb0Fy2DVM(&1#r$PzGt%L<~PcnJf3O1Yd zqRA6jOE9#g?zL9fUms^cdviVXB@5E^yAMC=4ZKI{n*!{~!nbSM(EF1KooZ?X%pC#ZR!>Dtg4u(0SfZT>FL28%27?&?mMZgG!XLo;Aiij^)9wG(+s{vKwkOFvQRlUuf@99V-V} zKvK^&hnPuRcE}P4%bvpDaR?Nhn8x$N+JO6%Y1}NV0z|)1dFPv3_H!zX<^|Q8r&%Wt;p)cb`ofX@_{xTjx`$;?eplh9e&={+ZqY=t zFYLm*$~U4O7u)eIU!cp04!p5wWRmK{#!Xhz@n6n-u~P)K z4|V0+d$*9iZ#TBAwU4g->BR@#Pg3rae$pv>ldK8{@s36BDg50q-f2~qw+0`RWbiJaWK6NmMh$UEEh+ipUfT2GhR;M z0;>^h?mL5xwhrMLt>;VM;{dj}wS;|}x^bgjeq8o^cb@xM`U-A$;zkz(csjM`YevD` z#1Q%S$q@cptqtcDhVtoDOV)aZ@v~n|__-Fw$CuaPx`iQpV1XgmnG(!1;tV)zX&_I% z_JtOF^5+&7kLaVdFE74*hIX~{=F@hG^k?M^p4B0Ud_IlmJ6C(t(vd^><+C#M;8_o@ z+H!&3T=bhC36<^LPg`<-+@XzWQkOIQP2u<03T%9C66~q1_(Yp`0gGaQh8j-P_V;=L*=&^t;~2p*sF}7o(qZsf`Zf%Ijqw)xnL~ zg?8Dc>Z9#ZckSKQ`uO@aYyI--;gF`KVD{uXIKEB`fPuBqe`sIGcB+9%kGvt)Ky<-D z;n1X<{JmYa!<@}>zpR)FQ@<3$uz6=ecYF`O`rUxp&d;FrkH@gj;11mR@)kmG=YUV> zcj)!`IGheDjiI(_kaeUSwslVd$3K;@hUXTrDz1jZCPc&he>L%<`349wFviK=8{oi! zI(V^hB&6J|hqb+;;hLE#cCgwEcMKb$U)h~d|6LP|$=m}QoXm0Z@-(<3T4JL`Ct%40 z8{Fw~5#E)t!y}t-LV8cY83P`{D`!Xin)VK=mT!k2hW&s&qn)vEQd#u0aF#i+GIo;v z^}^{jF{iF09vfW;SF8lwdd3tJJJ{m1i;Z!Fwe-?dFvHRJn&aP>=9m!J2;X{JVo;6= zmOs`CbKX_QF)ppK!`uq!@vaT7n(!9_9cA@1_nu{kNHU*u-I`iT(N1Y-D1}NT3Qb$GNt97Wlu>xjbt5AYeM^Ou zXsI-$h!&#yo!=i`{(TOw=iKA^eBSS+>{zS~6gRZ7dl*x27gxr6R{CH*Wjb!|Rs)~* zbyzl48dlit#YlN!F#B>8PxyalrW^^zH@Dw2U%v+7-ljID?nxkCczlalx$-17yvk=H zANgSY;{+yin+IO2*~P4X=!&w#(u}0G6MiqU5(PHS36@p=n zs@S9zg9o=5GrFwnjXtE+2pf@TByPN~8dz3o`M?FMe(IuSF!^D*$)5PB^tM&H!G_-#QBIxC6N zf|^u(zh9Exn-GaFWaMb?PhVV}r$}9{IAPXGW$M4u8mCt&Q@Qst7KBr_6o|KPakAag9`GZrq=gWo5*aMaWuF5Tt! zj3pirYM;>+1T z774H?#D!f}69v&>rTpizq0na`%Ukr&3p8;eQ(L+Uq8tXIk zN5j8T#>yum#~JP?x5K`qetH+jJpjw#$RCzb6Lm{=w*6ioo^r?=Yv{ zU%+*eXPFcAMd*5VGINNn#;wtUJkO^482OUVA9i|yxd|@ZjN%iHOyfvWkAC7{-Z1-E zOpq!*nuvjOx!&al8~piIk}4am;`#zIbkYM?G;ffjH6901HB_EPZuZBSy$ZBz%W>@M zmZ$e09mCy>996LJ$M|P5^uaMNwD~JVpAT=xvg;D`{D);2lPyM%PMC=^oJ6R|vT0a( zTaXIKXra(%0m^?NkKgPC=)&0&_)S)bs($;&#x)32t4aNA+iWp9DAmPU8c5KeX?NM( zGo|Q}{oMcKpEOk;D`3s8$j}R77g=3-S?YTwjum<>OOt#!cG(PB`d{dB)^}WrI^I=e zH_efxHYalVU$n*O-JMmX(|d*JYsWO+gp5BJ$X8>U3V&ix)?r3sLqDEzC}TQJ-=lr= zJ4RUeIlc~;fU6vrsq&5vxYjn}g5%a85_kj09T$NMw_X@WIYC15B}~|~9d7JQL;-<4 zp#3HU3qJ0H{@PSykRmpS0A^KMYmZj9^7x4`XdlBm@01hQTa*rg@*FzUOX)i$z$ z@Xd~V?!*mgVG|h>Iav@&u4cxMykj>0P=gIt*O-BetH6cX&7|gq!F0vHyte7tu#mZH zZGW{E=0yhbGqqm8S&(51V@F}&$_zH=m=p=$yO+K1s7^jg>|-x_7!ds<+u8TW%}D8v zrR?u*He}{@J+}Y;Tq0Ih$`|jnCu@E5%RXtYAoJtBc>Zsk$bUywnYXT+$Vzj6=4kO& zvVZXf=JwFDpRoE_V`AuMMUN?&R23Be)j2 zi>Nu7!3EzPM8#_wn5l0ky3WSn#<&oHMFt?eV*|-h(gnS3PQ=Vs11w*yB99)bLEVLA zBq>A%!W!*4f4VxvwJ#*%Iyyk@=aS_0MldaP261LAVU;99l)lV|2f^mVbI2K@#;1@4 z&3iyl2cF$H~0Jovymd0db}S-ayY(F(R1kIJfy!en;@?70#Jt{nExaR zwDjY_b&%^6f87Ny)FR=>scG<6CKSBxJZIK>1q0JHiMbgb48ne0{Qjt5?sFr1CM*nA z9M{AwvncrOvJNj6Btmdm2=4B?00MFsaAR5?%#kWZ_wX{<@Vfy69csbzS||P$y$8h; z`Y>&42N+Ho!>aK&aL!PS-n#e&DmZTCtv}!4*<@8(`Sce&X1JW=ykBr~p#cqlIS6~U znNVkuPoNiWMi11y0yk4DDlXFs+0U)%DQ@oPSZ+=0XIz2Bd}|u2kO;Qdt!aXuH=H-N zqPjC?!levzdN*{K;h!*}*5(Hp8&djgO7}dr;ni~cdBc<{Ue}+kbZkhJQFL~pJK|?EqH8wM zmm}+#`O(hwgvLHb|I%9OXBfutQdiNZRcDz*h2^y4bSASvd@0?ZUc?+vv7;SU)y%d- z^XQv-|1p8=EUMMn#Xu~f1>XHk{YgtIDk%(Ma;Egm1qG;5olF&bHQ`RH4i)n@1Xt+^ zG|1NkMrswQ#Sc?>dPtgXIAjLBm$-Av0dtrqKZ4%-Ex~5|BktI32FlG`U$1jA965Ry z549V@k>!=R@LEf43vbw=m%S#TYw6 z%wg&jVVqZP1dV&DS$9uuID62IP0Ub*ouPqzb6H8)(%HeA;xoi_h($6%_Z~2tBiopT z>DkP$+p=KyVh>{z$^(s~qRfl?YvDm*o%LwGKL{U<=KDR1hrMHpY|q@waJOPR`*zt4 zm{l6XDm-iD<^egZSm-&8E625!X{g>`%K1 z>gU@M zL7!Ya>^`4V9LU4tQ47i1s9fB7ViCzR%EImmi;1V}1=LMkL}JF1aPw0;&T$-r9_b6n zy`%_qK5t8&9SFiTWCp3|48Z-`)@16VgV+^6l{}Vq!<6w!#6fH;-te73WP)69%@#Rw z?bt5dcUYLb`nex%w7$aE13q}z?kQM#p2TsJI(T3ijuUmRLd&#hy!kB&HZ4g)es2ie zGdPd#cRb;<&P6PCSq6<0FXLz5>9A2XAJ6Dbh2QZU18=@2NEQ`hth)+q3opTCxytZl zJBt(VOTpvc6}aKGAOt?H!JL#~X0OFfEIQM}H0-&F{kxkOhTFH@?!3Y@h#{6(gfexs z2wRG#FuAE&Xyp^Y^W&a>n~ev*;7|xA+sECovCyJxO6McT)U|uNl(TfCt{o z!}c95D726V2mX7BQGeINF{@rIPd))n4THF0Q6f}Z45RSH%TTcP4_=q3fH8MLik8jr zd4>o*TlEZf>=UDNgZn|9NYYme1xR;`H2rBTL8jEm(G|z#$%vXFy-=!3QUaA}yt*d& zWvxoDaxR}b%?Y&WpfS62@^Ps)jk!OAWMyg7Y1X#HN>ztic+Mwv zp*nPZ=|Zw`9Kg2EC-UgqSeu)b>AnlHsdD?ZXz6p6~K>v4|b< z+bK=ApPNg5>=dJ)@@EmXokH|Wqz$1;f3dcZM>M^Eq2fPtGPeFJdS5an$_5|t&`x6_ z{iqw)uQwnYRk~0rUynRl)`n43hlEt!!<1o7QWVjExlbn&2fJ#V=dVr{a$T9iN)^)D ze-)Fult^4a20AAykSFSi*dQ!Na*IN+&PIy!DDK9H3{lcxzW@)t{0sEC8rHZCLhr#= z_Qi+SuxR;y_S3r-$lY(wKfUw@+*eXz!kKKa!yLwe9|p%>3xmtWdO9gn}FM@o{t`93VlM@7@9HFJ_>A&IfQw ztiaDdzJsK8JDw8|Ab*E?QPW6_oYERcqXcQv_C<_N4^SW$e9jxCs7hu?O`x+5YLJXF zT^e*=hsb#uQGp|q$aOTM_00z4o-ELS84>*dJZy?dy&q$II? zyo*W@Ve%RNA2%1Wqrdzh|_8na+F~oqr4V{3bMdv;^kr zn9-vO7h(Egefm8%2KK&Fr@qQZVBA86V$y&10ZG@-6-qR|n@6|KX32_sog; z1(-NLjWOC3gGVjYn3X$sV1LDz(i}xoEaq5WTeaS>c>~3)@$+r0y`T_Ew4b-Kd}@gY z&TL?e?ruj@hc0Fk8;LtB^x?$HEcDQDg0%wNJEViVH?-nd^6jZ$r1c6d9+!Zcc0X?P z{tt4ljpB#!7a)B`hIeLEg6sQ@^`%M0=75HJBkxm?9yH^`GJP=s!F%+5*AzNAZ#xAG{=naG)a@ zimJI@yW~E2H~1X4th0oF%UW^cq1Q}6b^|V+x|T^?M={r9tYn}s4|TUMVjm@^V4HLm z`@=jE%VLF5F(UxebBu6FlRG|Bw8Lkz>yf`}BbS9(f~NYr(ZFOjnqNGGJwDbL(eI0b z0hYMF(hu(u9_n86$79hpI5)-*J>6#EE}4Uff%CECo(CSwa6rGUTM(4i;6~SVSS;y+ zZVju@c%vKocsk;&Hh1K0U5w>RJg|4g63o=ziJ^BKkvX^(H+VX5+~18Dma+^#WG};s zvMW*c>3m%GU@cy_Vug!db!-&cgj1si*|R#X*l?+UozHrq$JM#)hbJenstrFEUpzF-X4Z)i<`JClOWfrlMFh+J)V>4asWXC75k%N?HSqQE!J8(TEY@I)^|G-Kl3y4$UOh_d?iq zxj96sN|e<&U`yObbF8OH%_WOnXEE1|YzZ?$ncVraxqEg=NXws2YP<bD{fPVRzx zTc#5EkCEINZxT^zxdd6M>crQi9Nd=3kT%czpt@3k?9F)zUXMOPzuo}2nYV(?;XiQq zQ#p7Z6(x~7FF~}a6lvm^-J$d3h`)y)D0wLmBmMQD$z_Y{jAp~87G-jg8iC`mGI3E= zftth0#79sF5>_j5Y>|(Q?j?B=nDBsURgfXZvXzWRwFEJobA|bGLWKNYp2^&wBuI{^ z#4#T@=bK@dH#6<(2xPum!1xG$gS3<4%p|jZkeC$3o6U7u2S05r)4Tr;ew(!N$KSk$ zCzjjUed}I=uoTP2+<6NAYkshUTn1Wws}3&Fy$8LAm*749I*8tU5TU&SlnzJZDoYl^ z`?Ao*@;ZzOP?UXF2usB7V)@1^(5?3jZ-A={6A9Dn?x;R=|QEBD8YtEO@X) zgxdETL0`KF6`d-_xiduRceAg|91$^kZ%QrWXCO+yoDXO2cMH=UD!R-Y?yf>n#FfXN z_Xn$78NLMlg)Og@Sw9%SThU(Z_sc!_HnNyisd$QmYo4>ud3Q0WN(iTFm19bt0@|F& zLC3x7_~b`4CQQ)A(ZSuAP-B2^ORaE*gBeCvkFvpu7RWw~VtFgAa3DH|FDz<_PfyD* zm8Xm_U_%Kr@1zd8{gs5dbJg%-}a&BG75S3 z1!-_;DIBkorQ!C4Tz_yPmC(t7!gxcv88fFVCMALUV;g$YJ(7FyxwOCY6ny-$ zm`*r$06qjSqeXr10jTzhuTSlG2CxO=s zd-^3n9j4YUq!!y1A!XrQDtTNI1kz?w+dF@my|;lj_WWRqCR@@ri7!mu)Ty-Ju8VQo zYDlw>H875gbm+&*bmr}VI(>50i^(llq;r+@nLT@@X!TGEPkfsY-P{vjwqfQEtkfFe z=PZ4VLotD@cwI9tl&)uOyZAVzNgTVJ(=j&K0&jGM;3LP)sGqhT9qoc}r_^M;KO+Tm zgkQ0?-q+Cb;9hp^$_6YtufZ?OZpV$~3QR`*dlY(qo^eq7iQ5Evn0-G5=*d)7xV~77 zHvA^Ay;qvPS-1kag5~L9MGw%{R;J%vPr?*eRr>o;1nBsvQ`yZ4@Q~Z@-b%gzcYG$$ zfW#d5o;-mDS{Ff&9rv5d`ey2>)0XMA(8Bo@Mh@PApSmh^?wxiHPNYCfQ(nV@#d35F z^95e~mZtveh9N#xl5TVmBmu|7X)4#xlm9M4Hz-Sy#W{j>SB?xB8u^3Ej>r<}X~QUg zQTE#>LlWW>91j(Lkw3YdkMpmVR*y& z1uV(-!xbN%gYSJ;e8Lqeek`P&z>r2 zglCG2*e`dhp})_b-?D~<{S_U&@4pIR-sF>vu=6EgPI9@9$Rv1FEeZ>`{cwh+5fr-b z1Lq7|sFYp}FLpV>?sE(f1rKO_pa@|a{%~RNJ=4271lGMOWU42fhT@67j7Ul}ygsPN z*dIv(yPjyCzhVlwZYwVlbiDxAI#T%BnVInX_;1?h>5wNTm`>Bi%zAsL) zJ2%$Ci@(8amr*m^yc@(88a@NwykJ(7`OM`;PqFD&$H8IsA=dqd1fib0*w3Is-p$&| z79{GB?XNi-(t#<&uRx9c@ym*cpZ>>RFmV>q8u`heth9g>1@`eHp4*dwTkrU>bC;7~ z;cot+U#rOV^Mb6ynziKn7diG%k`wtRG>I)wa3V2I=Il~2Cjw(jSgrasq||yJyR35+ zsnqpi`?Z&opq4|d<+~+hL;nHxalRdy6za#iznsgtdXKR^9y3X>?n%~pAw!}A0@m?sAvd4(E`I|!KA+uD z@E<%6Gh0wONp243#5R83OB-!qxQ8?GqpOt%TRdprO&Cj@f;yp}sd5@c7pQ2gD5Gwb+ z#g+$Lc4=QfK0YBv*Z=*6Qg3DHuiNA3uu_!0Uoqg~#d*Ov5T@n|`4n3Bm&Yko4f-7X`@IJy=U6!QrPyS;wr=C{mMuu;ya#L9TPPqo3{Lu`*f=ai zX8m^&7e+{sXT{OD@~s>>4t{vCT7}Hq;e?J&6G&~4C7v7Myb(XdaaDj0@g1&Z>xMYi z=*pe!Hq%KY+u<<(=JH8IbJkT}4#yz`O!2D&x8MXW*M1Gk9;85JZaS#EPKQ+W7_j`74d+Mvp)9`uKC>>6Xj2B0f@eXj zT^0Nm)r8N{^)NU(z_e;KgRD&dy{Xbm1&-+Ok(*yV!)EQuYB>pPbBI z{@f1(21)E^=Wp<`td-rqc^FdPNTG=K7=-vw!H~UwV7O%|=Jx*urC~2z-0%-})kor| zw105PKLaPO{{uSOENVB7!tK(#s315DFR#7AV;$e1q~JS>I)8;QaS`hJ@H5nK^Ovs& zKEnL(s@S~6w+B80#>s-}ZR>zaZH5L;ZHE`u(`gHL z=DJ=wi>lS!g~ylX(j(pVQ0={t2L7prxBnJVi#ir|{Ilmg&V}$__);pAmxC!NMpAr!p6@IwCvAmI265<8vFlA(hXB9^lTVcD{`5l5v!Am11lyx^Z^SQXX^t77oiB z@sC+^J&D5-Y^-Pq{x)63PH10*=zE%7Cn<^r)%ooCrKi}`zqi@SI792CMXy-bTcOOC zksqwWi*d&Bni#&jY6Ja_s`w$@3&fU8#u&9Y?z7wAuI60eCD~(rTqWFc*n}=6_n|1l z3tR9d3``Eh-amb?{&FOW_zuIrwnW@FUy!_?n1Kg-Mafw0Wy~~^B9Y3)_;86V8Fb`h z$rX8$tzCi2Yn6y$a|L>ps1h&t8<_WZ0$F;3^8_!`BFBX|-f5u@`QllDrd|4E;cSZY zb{LVjXUfo})`a-2D8^epW@Nd~6_l^FBA-n=KWdD(~D5$)MIJzXGYyDgjyEp~&4%v{KgDGe| z(So$@PDLl5$)sF86)*nNAbV}kp+_;-=jU>#l!%b~SK?9b_yCyyio}yHPrzI$5Jfl- zOz|TROn!6`gd$gBnMo+PX8<;YIm3y`6LC_mA;^t?V-uV{aQBl{Y@JgmV;py!-O%aJ zJFYO!?}$=iYc>yAufN1+KQ7Z{mI=#Y!*Cp9KW7#m{?g7ox$c3cXQaS+^fZ$1Ch+WW z2A10|ffo*?*x|JU4hc2jlaGF|x9$-RUkQcn&2O;(eiUpq7(^f2L}(cq$IsJKLFu3f zUE!V%=dvYfS#Bn*T`5NenTw$NN{LnvXTX$s>eRs?1D2iEpwOLU`z6Q!u*Z)Exa+3_bqi`GoZ6#^MFAs2jEY20QoZ(8k7~8SjOnG_qwiBl}&9_8Bf^)|5)nkXLgUcAg}CVd}^PI7`sL z`>U94BMGV(wVat*B~FVR?3gD~Vl+o*CgavFMBnF{F=aL5_)^G(`E+XtV|`4RH62{v zQFkg6zTz8<~6MIo5(EGJ&(^+WtdG(L6{&U$egxVfsgmS=ZQ3^ zp}X@l-kbDBR?+Aj&%AUx+hg2n-LR$0dcnq|vf@jwjGmSkKUCx~6I}L?FCMP}&;2K` z4kwp_^*&oRcCsHdec#Pq+LOTLLZVsa`T1bA;|lA)s~Vcd>)7(0ZBUf|n6=@$s$0*0 zWM#NLO?Ag0drm@}JT(2wmbl4tya`d%U8+XJGo{dCn-(G0o*7bg#D}?R{sl z-rbVSsL8}9ZRVu(P97>Rnnu(n6k*TsRPy;Dx4zDtLLSza;on*#;xER>dxs5)&At+B z+^J7A`Gx4ZK$q;{ILvW}wTOO88ZQ1gk>u;eqrAKtv3nGX?jedKoF2ffsrble^Okyjhx@_{V=gU1B+d1mm(_Nzh8`7r*8jYCZGZCk$R znOcVF73A+6iDJIB_m@pvIfZfj`?~CtWhBpkT4dR)nvt?6%MwdptrcghHJ!>X$GdUo z`6*>F-!8Cnwf9S;wI8xK+#9VHz5mAw`@FM0)}w))FMWB>UfW<&_if&p6Kk@xWE? z6;7Dx01+4Z@MF>rc=_WS8Xhgf0!R#m|X4)z|8YRGZ z-duny`dZ62|KeeFi8ZUgW)j~1c!eF|DPh~BAMBE?|JVX)U9=i+XP+KhfIqhvvpySk zp|VyGJL_*SPI_p-cE5_puEVkXinw$PqO+|Jy~#(jaF!=|suZu8m@qMw)%YptIP-b` z9b}IdFzK6Gk=k}Lon@W)RYU~DwK=cu0S!q1^#SK_4)h6IzTmv{1rWMy2uB>&!>aD@ z_$KloJZ%1fiC;ruFa3!N?Gxc@%ukf-OowNWxDIAv9*CqS(HU8Y*nJGAAGiV$ zRlCtrBomf=a>l}UT+WGO_@v$s1~Wl({4};5*x5RmZ#4(JzbWIvi4$R&s2E<}@r@Bz z_{ByzvP_lvbM|wmCv)7smW}xOm1j3Co1OAd!FuJ@Kvv*QF@M>fIjsAr< za$!v*F6TUq!<$l2-+L-?{*r^MMW>PD{OfpZwHY~ot_sg~P9t$I?_j`oQxfLgh5@}M zWW$Os%=vCaVtn4=pSv6vFYXI=I_r|}AHJc!sU~s#ID#t0s^o0<7*6+7AiQ~F81Y$( z*iRn8z9wPf_2nBb8yg1m5B-?Aun%M+KH%JCUC?mk6)s)f1R3YsankD&m|}1b$E4G^ zZ+|r&XbyohvrF*S{q-Pfnu`Mm^kLbh^C*An8Piu4jVCI%GL8ITT%-1j~Xvb8$U?n5kG+t7mx z-$sLb$so#Xivrc&F|_*}0pqDcRN-ncBzJLH7sI2l`i~Tq;NB&hkIB+~eLJA-lsw%~ zv3IOO1qR;B67GRT7{952c`Y-za)~ zR{=JaWB=CZLCBw8lsRAtlN-4{>w-D3}m1MC=&a3x?P8@xy<9 zP;Y%6{VjuGZDS<%n}>rpcR#-LPdL0wP=Za8O(eHcYtphdn_1<(AJYtq;3XnA(P0Wc8Vx&g<9@7~iLp+>Y7&EF!vd%wc=C4;Hb2{HK zzKb=;lEpum>nb|L?U)Fx%g`eMj`EOgrcZQhG=VA8CyyMB;J%MOY3eWqHy3@P{nrw{ z`b;9@J1roK>*Tmqm_YPRT{3WfGCbR=L&Ps?z$aFd$QDWh?;V%#{Wr+G)a2Mi`EAT> zeMRDPu!Q*-DoZq+(-{?%A~IQ#jFOZ%`P6-qd3Rihh{gLbE7)<^V|R?vTKfZrb{=BX zLqEZmd4bF=Zm#sQGnAPj^#r`jBALs<&EWSZl);2sAo)9zDWv7#bUuiAQ+*w33fvi) zfqZDh`Ha}?OYl*0Ds%I83amGK$CKI@3u|ct&!8m)(v`MayX^1<>v`w+C2KaqjJ$=c z&EOokW|7W%t~G=Qv){5FUZU{ttSTyK-etlh=i&5-L(JODJ*ZV1$V=N4iN@c$`RQrt zcw}}0yVR-_2L-;c|K;4ml4Ay_lJ*EeZxwEO{~9lGeL9tC{a7ECf*lP%aP0jx6#6xa zdTc$~x{u@R2T#z0jG^f0N6w4!3wNy@#u*=maP*}xz327`eK*L^^6lN&d0&}ky?TtF zuWC@^>&;mIK#$t~sl$ZM$y6x<(SPw&8a8kh4|kZ+T9u2)yI@I2Ic8Fxgf&&$5rLIk ztf^b;QOuohMe`zeV^E$s&6~^d0vk=~95aHU%oJ+%K@SBp4C&5#Nn9DCOUK;bvm0-4 zF4>>RzWbm=WA_EIZNt(u;D9>oB`QKkZQS_t!bdS%S&e71tPhiR{@@8be}*Ly%bDU+ zcQHLajDe_f?03y(-v56e>Ql|=)DV>bZ`5dZ?vI9j#g+O(-9TpggbNPA$ z+*TzIs`VmRJW~z6{kY4<_h>;|Y8Y!U!4PWlsN&0u+^AiwR6HLO~d!`mx29g4t) zk&T}L-veTq&D&;xSIjM@Kxqb4FrOJAjTsQOOd8hlrh~DlE>zYLh!?Sd)v-JXpS=LY z;;kV1{c2#j?^|;5b_jORhIaY=&~70Ia%soFHSjN!HWCDXWIi#65+h*AyB5aTBAVk~ zRx|I`#6#BCtIYRMuCtSQmN{mb27Nmsm?Nqe!E=E(WA;58a#z|j7I!Yg*k(gUM7a=j zVxIH9U$_pR#(~#ijj(ai$1=X{4X#u0oj=l34U2;}vqC91;c3VP_I}SzxccrcdsU?l ztSQIw%dZ0(q=gdcwcwmMi{r9ZLe=f9SUJvzLiIo_E-wPj8*!K}d>QUFWTMfLG)UTi z9TRRQK<1WO9QhUw^Zz_Ru=j-?(dT$fNdGS*pR5F7<)k;cin16&0+&IU0REGlz3=*y#&9d&d1+* z*|>_EmwO*g#YaoF;Te}$y#9dWq2CC`r7=hFj@MrNWfh1C2iM?=(GXnl#1b1vPU8=uVT84A6(pZ1*g#jc+2GlV!QI-=jF>dW_1JRSmxmMsm+k7pN0P( zJ_p``i`X;a3+x}gfIo)E;J=s2$p0rwN<0$q`d(Sm7Zru~@2L=b^)N2$tx2BCoj|>L z`Xs2y3-??yA`L>@af`rI5_WJUzR@rvk*4!-&j~Y|js}-y^tu(#Ln~zdVNc81}FM3xH^k_OMs&&}^T}`79rFl@p7(|wya}Y};|sQR3PZe}b+P~5{7lt2`Y?Y$5W<}V*#sKDN$46*e%R{y*!1y4&KQZvNs~1MuM%q z#q~*cWDPIWL88EV>Vx!*rZ9p^WCB(+3oYj9e;2}ETda?TbH_&8hzqrw63r8y5iI)y;FSu%+4JpB((lLMveyhX&0c|Gog2O>`T+kDqVaX}0GPDrVWb?lUmduGF;QF}aqlZM zSuQ{pkN?Khe}d#LN>d4KA)@qlA~oV>^-sEtX?EW~n0OUv_op#nnikScp1YT;3;-+3SQ76sB+kp_r+5JCgHDwOmV2P5f>yeLQ)IYaMxgu;B~NV-|(6ueM4O{-fE z!|axDdRFit99j@Y8~7gFx)?$o7jA=ZI>EFwU@g?$IZ5r0+JkzlKmDsZ2V&PAqU<08 z*3Elp%%Q1JS>#G}m9^pLvkkQ7kqmf$UrDd`k1?4q7gJgDZbrd!4z*of!&I6u)Wqi; z^Cn>`{pH}yY}_=7ay${<#7pYbv^2qXnN zf9%-94!n6u7v+s_bKRM_=(DvHwQjiL`j`xSuN;hK3d`HGy_9G4!Jz^HP^dsLvALej- z`jpR`K^cbeci(9^p+1IMe%WwRP=NBF1~Ryu)Wp^fa5^SJpUoTs8Lr2Y$K^eWs2DZ= ztwhZJaQobedPI3tl(ySVBUAfD>8k-7GRPC9eOy*mvPX#SvRFaD;V+u|Z6E@3hp{-! zl_YWVRq@T9WLn(^oSb!#T;Kl^-@H6RL|!~bKk*af#j<-S@F$SVw$`EV^I*b7zcJl0 zlypWE<8#3<5^^#Zl?p)8yI>;nGXeE41(L|9SgepeP9_z{pzAU} zGHFW;<}LLmR=sENs>>eoCi^tXWbYt_DiOFZX(L%>6pHCPSCOpbKn!SDO#0{eOg?By*orM&hu45~Us;9+{M9&4>I~GJEI|Yp8{=M`?{M&sJc@sM0v^%>tj*~P z2-$s;&7N`rM4V&USGIm|V=lwi3eN`7A36N^nPN~DO0D-;<}jDChIq$-^NNZ)F$y^a z{0m=Fm?nWZc6sm}ChheXR?cyR3Aka1u6HKDx{pq{?ap-2YY##9Y0eNkCmn@X`9VZV z8J?UU1p@1v@$CBxFfykH&7WO`kg(tQH?{&+_KDNHEq7q;Vr5Fb+F|&qHhsB?o4=ef zray%HK-a>GzUTVFeuXpWoQi*7<+p&Yd?idIHaO7RTH=ICt)_cDB+0Eq&U731u4?kz z!g=mxNd4R$bYP(jS+iv~eQm?N!@haaNOfs)=jlHBKv#+^j5t6g93;rW4c>IcA~DkU z-J4$CEJB+74$<3t1xe(VLsb64INUgVh@$aNI8ftFeJuLHZrMQ^f9xGNT6$5@>Mr=4 z=}8NQn&J778(p}t7DN@c(TZc&;j;Ngn$?yGfA_4Rmm*@ok2=sb*(=40KQSiG z;K(L_2Qtd#YvLB$5zWX7cIuZ^M058Cwlm6wcu0xkt$25`c!xFy@AoEoLsqEcag@Xx zFT{rAAhL(^%to9KBP*laQKd1GG{*VjRo@u$V__gxlX!B9>%#@MCX&O$VVGl^OfJ3+ zM;9iAG?bjiM6L5g$)59gn5K~@U!pl)L^{z4i^U1HnZ#Tm0kJ=mR1KcR*E=qf?MW%v zl6R4m#HZnbT9ZwG&8T_kAo|A47`99-*r9Y4S?43(qNs5Q|B#aCyd2@&VtV;OIUQ^yMvj zyKEy%5A-1OYc=U=e~X_T7Lu9EIM&@G9}W|iYK(OU3dUWiIw=fO`d6Aw?{1?`6uFqu^W?ad+BsvF4MEZmL!7dQCTr% z=${;_c+v?feT(R{1KXf_B1<>fxr4ZQ745sWAO4)WMR)u?4Ak>v<9|RP--V%2Xh5V z>7@Rf5N%vYPw&48x$kpn+U9DooS#X1C9B}dxfEKv{stIV#Z$54l`wJI8JZ$l0i^@M zG+|B!d?@pyD+(xF4f3GjV|*A&-9X=5D1rLTOXx@AYcQ>Y(3frnFl(+#n1)mG$jYZqVt-2!r^JdoX2v6ftuy~CO(>>%$xiK1<`H#t}~8D}=0BzAijq3En| za(>4ST<|@bjGsJ(<<3b&ygCNI9X!uD{!;P#hKpoH=_RzR%_XO~?nCn1t7P_pVr;X& zMxM8pqQc%XQm@YOY^*7X&Z|Pj@Jb?{R*NFR)kNjWvz7VpxGyd>XZag^+^|oziB;z2GdlyU&_a72rbV7W@h|3h z(lr;CKUPN*)q8mO&lr3DPd}bhyvHW55~nBE#!GYWp0@t-2CAMyCpUzF|J!uBCNBXJ=4I2so(wL>lTW`$6oBJr?)&YFP`tU63Y69X z)6UW{zh*f1p`5N|I>1?%;{q>y4dI`v=%4IQU@~4!Hw_QLWV0Ho%5gtli`3A)eF8+s zu9`M#36q=8ZqPDEQL?(Ff=VtIC(Y|9-M3YeoN?yU%>mL}PU<>!IwM0m?iSKUB1dLq z=hJ1$@|=%4n`*q2C#mik^tGV^sc}l7H8t|&(!O|lx>t^DwTYxs+*wUuEtqPBNRgXU z4%3$voLh~zoAwU~5v?=psoSQ1P-kIJSEl`h9kXm`Zgd~?W*gJZ99JYjUY#0wJ%uGt zMCqHQ4`AC!FXjt0z^=^OSdHb7yqj}JO}-A(SMJ9*srm5V2`!B4$ONt5+)#$=G8?U( z#al2l2E?7~IFw{492uGpd38s?A~^!|x9oyPCs{Dvz7|Xk-$1bDLO41qMii(ym~hV8 z5(_OD{Kq4~DiUz6mGi*Q|Hz=)cA__@l9Anbm|XQf#W3}u#63usaZQOObK~=^C6iOg zU)v}Au&j&ZN9<8{b7vm8_N$8Rv@0fEcB8EPWIovxr-gR8<>XlSY)tm7A}gz0Fs8MJ zG@G5k6nc}m?~Xyk@H!F_$juW6>&Wv-g&23Xj^t_Fz<`-`L`CF3xoCy5SGd=B8}7gv1unmwsU+=Jr#YT|EC92tmR4Ui>8DRlb7jo8e&GLz>n#o65ps0z;pJzlP)r4J49TZs!@(5Qs%0iM+Qj{vSb ze3&j6c){l14y0EYmVIIyPUVg!u-8sU(J4dg*uT;7bn}=1d%HB5x_KM$eL2>*cak|z zcO;W8j_>B>N#xLTktU3bX&&wPyM=jHbcK4oIK%u)D4@3tvKX0Hg><+anHh_VXnt}t z^WL+FzWVZv$%rbXMJIci?E_b-<=Wp&*p7VqI8g$WJ#%TKvm_KnM+b5|_IjLncOaGI8-d%_~+Anv*Rfz9`!fhR&BHo=XWm!1KG zIqT?HY#i8bT|^s)&cbExeECA_JWLlhpi?ZJW6n=Sk7RsD#QLQHtCJ+2!-!D#pRuat0&WeSeSGi@V91V)w z*E3puXTZ{?hiTW0g!tZR;KlWTg_{1y(3wV4*+yZQ%oLJRC?Xk3ao)X8q(LZY(4ZpC z^E{IJ(qJCSJP(yr5+S_LKA}>IlB5!vq*N+2Q7K8j_lIS%mS4_$p6Bd+-`BMTD?a&Q z#GE+P*yf8BQy6v~I)dRxYw>Nseq3Vq9rM@k!DE(6;x?@|XJ+SS6g{d{jJS*>9L=79`es zQU^x|hKafJ45I9!#h$^*AS;s~R-f$)k%v>ndrX(XL6=kFG5e;#PmMF;j08i-)yxn( zsO!STZJA;xu_7#cb3vTe(95Z0WQpf){mW(LXNe;ov~z4$mN?PnG1tERg7|pfJ#N&$ z^WyQoH@SBf8Df3=RPN>VGh+XrYq(Jt)5O6&y4;TyC&bGG14VHolf+N_CKNX2#EQR{ z>G9UzBgCsN9^=cDkBR>&U*%7C1&EC+9`dd>N5x0mUh)^;dx+Pm{^BdoZW3>prO5D+ zyV%K8n@te1rssBzVXr%wTpybXnx+!6AKGRydco-qELi8;{ZA0z=w6BbN@WHzF13hcrOdn4%VS((gs1 zXxCdM$?dO(biaC-WX*g7(o;2)XeEpgxTaPT*Ro->=&_?@XXqfB?6z2<_@Y16KV2)y zeWXa&7w(eC9grjKHQtiP_y4jB$NVIgx}RB;Qn2LHwwLTm)iH_UlXCX0D_jyUt9(HzpyhMD;hHZN*IOcyzu|LU)5@0h}oAUaojP3 zd+wMdY5#PC>)o3uiM}Zd_iYj+UYiYIUq+myXOsijN@64*ceuhu;e0z>w*k&pgiHPf z>;{R>af#1CKiGdIShC4E1l$b+Btb($pvK-uGAH>M7_K@Xsc}CJi{|f^jI9oVS35RK zCVlV+<&4#mnZ~}*q39+VJoq5!sLzwMYVLv9Ez>3Mw01$Zz((3IU>Dr~Y#~{lvZ>PxLS{CaDrNP$W3aHvM2;bdNMy+A) zcz0QU{Hqs<+JQ=F;9Q7l!{kx^)*~Dr+7ENLd`0i=Js_niFAmu72|k+)5^KMD0b`h+ zc>JH+FxtaRtgtEvPVD2vGjwC1VeBNaudOfm9S}T_hupxqLU@{_Y~XaHvsju8AoamQ zalW|%z~9B<-0=@MigFYG>^{j&tr1?|`$uzC(^iO8rYc%q+r3i!@@0Sirrc`r=_g@) zGuc1$Pf3r2>y;l_3*Y?$7M+{ALN-R#+!MPfH4MGBcaUwp4fmE_Ilh+n#D()8XL zV&(5cNqwQM*voe~MgFl8XKmA`FNGH3E`0+^8EhinEi#~K=k&x+>PFIsyuo7UvXR8; ztB8w#=nK1R!F8XbM<(;yaL^2W8fj98Q%m$|kW49>fFUhClZh7bM%3yVjq>A0)00Lo z9HU@D88_zOlxJgT+ZBC0Y$&)d>{>y8jfk9TW59pEHO>3+owKl-Li#f&^M_2P)BUM- z?AJ7B(teoFCQe>VhX4B5<;6>dU4sebzga;deP^oATumb!_L29()%0*%B;|UoCB@li zs3(6TMMyLHC1h7tsof#%r+cZX{wbwS`;P{Ox01e@FYS--rdN4>G~}GD4;3fGZb%=0Jx%R=7nye}C{HIfXzaEMy2m`L1Dd62whj6|V+BYCKg zlgt^toKCDCC#l~wkK9VkCAmT`x9Y)I$$tYl`f4{uaw}jI-S1~6*(NoFM!5@f}s{*$I8gK^B|&;Lz&1LeSKTpMYZx`0b-Bdt9g2P&R5G<;?$h`*Q8 z*U=xq+diKH!xeF_>uDP9Gy=^`BZ-qid~y6REgC)-L+h54)angbnPf%HTaMtc<{_lH zI~<4hYhf-glQC@O33f+(4s(}}VKJlfuqR>&-@H$PPm(IQAKBMX`om^;cDNk>Iu*fm zfp?WO`VWNNet-_0dbpgg!?c0I8UOwX_Oz|UicK$2W8h(Q{@sK+6=8TX;tkFnlY&ZV z@31NDJZ^OqTnoUkVCP5dHMxlqf&*AR^#S&~)rJL&8nHXM4U-~1Vy5u>Goydt;mnWd zR@;jUDqHZ=HyN?ouonC>T2cIF?OTlB+h3gYxf!?5QWyWsd4&aWgT&<{U*Xa5gT=X> zFLBW~!Be-g5w~{@7V8N4DHWT+VotvSJ2q&FWs)9Xps|Md#<;tfQJ^Zgt8SwGJ0)?B zN(mnKmKAFj2cXFC96Ant0cTPYa8|#QaKt1OE&J?XP4$1cI`;x+eP=EDYxWfWu$_eh zV~4#gwZMv}n^~v6Hiju=u_d_*XlVL^*^O$2_p4=SLd6YmTc<+?4^x4!w4}40yMb$R zAd?x!0$*tfg?K*WVk|dNw&yA?+sBipdbU`e{dJT^eR^NGRp6{XFZSZszY3w1ORw=a zg!|~YOCR|S_oFGoXE0lRD2^0Dt=M3rM4C5N;6!AlQa|lrHc<97Ih$s%`5({H-o{Gy zZf+K->i%FUPM4@mc>ui>Dg|mOhP2218eLJIKp$V+qHfPQ^mkPydFQRAx?%Te+?f9; z=E!4ueK(kXO>CgjL(%kR;Bzv*mO@9oU(tt*bEMh-9qoIYLlY$*=w`EoE@icoY1efs z_WVN8MU~`K{*59AKBVJM1RA8&Q}Vy~gJOG|D5>NpEq^R4bkP8Q%<|pwsWD``S+W75s`udOK6N=?j|R zGLF=W>gjp6Ds4UUfYeuhVA@zo?(x~I^m-|6o3M_3abomb)WI)o$);#szrqbWPtz5* z8ZN0Ko{B`XKy>;Ty?qc4D_XrQ!;oeb}@?=t-RQ!@w;U@R;s# z{N$dCL04k%o_ao3FHOOcGleJ^gfVL(!y1nZI4+B!OGX}MO=CFj6~nd#g?Q&`F*r-Ula6d5KGB97M%2&vDHyPmKBe1W*0jg)6o_#zOxs zSS952UUaU(qw}j!aph7RR9ucb_Rhm;y21?bwLOmCS&Vr)))*|}@sn_mSN6@p_U$7u zsqP$}Emy~OsgtPQERB_0V{xSaI~cGn6i>ljSl4|BkJ=W(+N2HW>=pwj-^@Xqisew~ zD#DL~bUCYf2>LF+&)JO?c57x6IM`DOFNK)&zQlNVEm&&H{>&C!8gKZgy$xJc-$-U7 zCBxkbU%?!{Tk~aGqu4gnc7CzrCHAm<3X|UTkbPReli8U3VEl$KcKc#~DqEP!cz0cD z{B)5OPc)}031f?MZD~|@DN|xDG;Mn&ON!q}``_GSqD%XPY``P-?}IN5-S(6f-3%ec z_0L#pT?9?(_liwciYMb8FPK4NGW}TlicPs;8};H4W?@ELh{}^oX*P^QpeU&bTj7?NhX+4LS7EJzUAo8^a}(U zHuP^Df9AiD66c%n)*bunUwhWjahD8{-I&!>TkON# zU9y5OvWjykaig(Ulp!*E5nUK-50&L}$bG>c$T-u-6x*f+KH6Qpd!sptZ*BLJx6^Z+|x$z}E(Ku{N zKmMadEXx18P~cb{kMpGOivIW}q1zmDZsLC_IA+ihPUcz)p1+jMed~7uT}M`PZM#n3 zn#fizBjp5cJkiA|yidm8!{ng*V?34&l7``((fHw#B7~0&$L<(u*jo~WAFlo3)C!JZ zgZWeL^2D8psrR@YKUUzmTyP}-q6m{TeZVwmNG?P;cGK9t-lliZ@Ghlq~Ft)GM13cCV zUCYT~;5ep$xdx>`>5*nuSacrT%@s*D(y9=k+0=-}I7@oR2(mcKQaHnty zZIJyAuO6+Vvbo*h$Mz5&mBoqO2Pr>Y5j)C!X~6vc_-|(rwZ2!wS(}g1vx)D_?DD1L+NmbWc{PvLx2y4J?MP!QV)%&JlgVy%IZro$&R%Wh6~~#AD5Znf zE*?o^UH|g!#)GNqW;^eHL!RPY-t#9_x>(rKXZ+dC&sp8mT%N7J!sLS2@VQ5lndy?A zLaPg#nCS6o%TvRLGwn(8oYehT{?Q*lPG`J4_fn&rtKj}{*=;hy`LhD{>l%Ss{Rvod zYYL?M)(Od8)%w51xK0d zfn9|iJ}`R5tudH^EUD%Ba^n7`$1T^Hb`jmB(M<6?X# zzllXnSc+pkqu3k!rRde1%{trNas1pWW_E1_Myt25v!QEH!M%sAw_lG5rTxid{6-8k z8cHSFn=z=)fR-NEitjYXQrMJT7&g?36qP)1zO)VPiQR`ECrqN<7x$yyOKVE){~xMY zBK@0s5WWA7r|NOuIO&TqZJlxub!Lp9$EyzFRDBI{vN(Vxd*vwn>OP!n-^spD+l{cK zmK|EX8Aso^%GUl}iTlrF`-UyViW)Np=I(Qs^O znN#4mK^31hWpW#u{y^qFUHETS1MJM-3!ZnqCT`^>z$)WZ?w_tB#tu8ot=CwFZ#Qn@90ImsM;OP&A3KQW157yU zgZ`)mgSa~}A^4&9yGYkR95+q+E}C^E3V)l+bEYv-_+QRVkyJ}GdhNX~`n@*_b*&Rb ze*`vPjp7x{(1*t`t1qi?V2|(~a`#oC-`dRZ=0`{TL_!!BY5yxv~_w+;|M?kNQ)9bur{845LD|G&r|sG#%L=0F4XB)2HS+5E5=h zf>{viKG{*tgUj5d1G7l)^%K#WLkp-h)1AM)W{HsZlxG>XO9bEj3g)wDF(r;qWD2bd zX@bgiwk~V|9qnvo=C5W`RO|qXKQxmb%8#bxn(1`++Y~ZeJ%tL-EuwSIKvB;&&{I`& za#Qo74~C=2XNW&N5ngkXLPAMRxO2}FMbV)G8M^&9jz*mBVC!>|X?D~r7Wg}r0&O0$ zi$hP*T~Q@_?r@6i-dtm^!qVv0>H^jxN~gw)+3alUY0`>1!_MALqaedL_D?yD;x&%5 zar!68=(#_;K7bY3zR z%IySB#?1xrN%D+69B>Ho6)rIyNg{L{2w`O>@*oKvn6JuRFh~`+fwu2p_@}vi@Sh$i zwwBL-(x!}ahtA<-N`_#B-CgdQ)JU9ItN}wT#$fq3E9kr~!vD^=!m=hSOh3ODB413! zj2}lKG1?ASJ`0AY7pG(Pwg8BGJ_Ap`4g{;)j;OBf2W7WsV1}JHIM~_?{EXd@e`Ydj zYVCwEiPmU&W<5A;w!m*!7D4QMV}$q_;8HalH&{BrpkYIBd9(=nJk+rByfK{bP{Ag5 zL$DG245uU`;kcs`+Mdw@xqKy@^KLLK9-x93{nensM;TWHsQ{*`pvO*C*gHxM<;@MC zAXgoCWr|>1pE@pboenj_)G_V06Fg8*6S!3Fu*iJ?wryMux6ddE`?HNOxJ(+Qg8u{c z``^GdHxNDv&v}uT&~bXmgTmH0Fer_J0PPd-ar1I;J$N3*@9qzR>KhIfuHnYsF9RRx zyh1;p8u)qg4zE`F8Ul08S?7f|*s}dUW@+;sMs=jKKQe#eUv4E^)zS}B1Rld^TRF_x zs!YzaWpQ2paB7NGz|hd~^kka?PWQAWgIhAlADK%&_eyAuX_C6M*_&v4^P0`;7K3w!z}(n*g-NW7dtOyLpCD2%5C zH_9RTZ!BG`V899PPnY%#NSzl&W{ycPbwUJnTs{uh*Bz(rR(_xz5=>!E+o90OU+`Wn zhVUicW@tn7<~g*eNevVv))Zf@0$R@v=wn?!*dN)S4qW}m zO}){^w5`5!FO|yJ+{9m8r$;>dapwz1rx!8RYqgwxwLF{IevR9*`WT;dp^T&A`4(H= zNjNuS9}YtcIJH5aIKLMcxSwfy;2}A~`KeC=qm3TikCRTY^~fM@+=|5@-q3MrM4TH8 z8>z&5>9|2<;5q)>J6HI4@*kfyaV~sS0k&?*4Cu7l#ICKH2OZl&+1Qn{z~1aM`=R9w zy-wbuEjPghF%ZOE%B`G*o{3!p0vfhEb>gu_;_VsJhD2bI&g@ zC`XNocPrqf=D{?ha2UD^v%m*A_; zNmTAV2m5@Hei+%|@EhZ3j)@gU3LJ#53(Rr$Z38+YI|^e)kD#%$weflPP_kL8h6Xko z^q@)s8xAN^-J>2@B<$8#q_+#%?KkXzek0sldz*PDR>6Gv9HtX`8T2j$v-)r85cGT+ z^Y#dVv*nNYIo<9MUsqn}vCJ5@=R|N9MttVJKO zImd<1NxCw%WMV)y>^uzSxNSXbx|c5izRv;Odr4H~FMrLXIlMywurl~k~R zPzzdSU&JyprqZL-^Gs&@JnGyN!ya0%r27wi*~08yq`1OBX=tl!CVdgpd8oq#Yt~pCCs#`d=;vBs{5Xx=MI7>&P^0>0pbEGcS$ngysbYWc| zw=Xx7M4|oR#)&L)wbX<^w=Pn?yB?ffm`efKqhMQA9{mU zj!q%@_^N_jZ~>WCOT(Wx`J^=d9rtkMB`VY{;rPC6Dk?w1^;>YB)K*R7B>jYW@?vT3 z+AAUJ;#6-LdpL@y{d&RH>L7Bq4Jrs1Z8p`{Miy=yE+Y9s zSom+a7HP&GEm)=XhmCmSDO#3sgS8p|5qWJ0U>`chavP*ISo1Rn?xpUVLg$uI+;87v zZbe18NU~)v*ne-eobu!}Y|+gwa7%jzF~JJF>IwzSdAXE-y>KKR+;^NmwA%(@@mU@Y zxL{OMF+Y6q7M$Ypnh#evjGImV@W&Shqt-GR_DS&QmHd@ul{JaDbAc4|{&Er@IP~(v z-k!zR;eYv{g;^-~q=#4CnTzv6`Z4S0`B<}Gk%h!FyjQHoo=h*ouZuL<)H#BWMA?8H z6uK9qE=^!2hs#i*b0OPyryOD2ZWhyV2Y+7;W7oG=VSvIZ)_t!EcaF09sNZC1vl z0`K9b%ttIi{T^=cd&NA2&aO}GC$=xO5*zmaVx!L9!O8YL%%kr%E*DR)PUHq)9E7@ZG0gmL(@Vzo}o@n$Aodkk!O+M;a!IYuIK?M5D+OmMIs3 zx1G+icgy^7z_@TWCuI-DdhTJT{;j~$vvw?Tk`sELP+?U<6lll6Jbq}7J_cW(#lNua zkJGmgDzrV`2D%rLM89H6q10;^H!3w8ek$DLY&E9BQ&TzUdVHU&DKdazlPg3c$IpP5 zHGcfHyDMSnm?13QdpDH3tY_glUSPC7nU%mHD0_dCDG7I#`%~K4dGr0Cc36QL_)YM2 zz7A!%E`XvV=488<15bTBI%2F1cdOmVZ?8Nk#O)y4+%McG=1W~;-f%^pVbpiAp7VZ{ zK-%?pxnj+9a&{@@+6DIVz3X?m8Fh?`YwNjbGp`Ciw{jX6Z_=ntML3>VPRn!kg}q`W zRXwza{R^t7_4f|w_08wA|amn5>{t#M;yG&vly z!G3+A)KzPPpM~!8@?}=|_rHC_EwV!YicQogJppUw-04*mV7H1hsm>E&aJ(&@o-8D%*c7h>kE2uljBua6G0EkP#K)ET6gY7NPW`S!bB2$=Au5AO_qRUA^;0L^gpp_x z)Svdc8lw49MKXyTjiH&+RN!Qa=VQB=V}da{Y;0zC#~Wjjr9ff1I~wa^^4Zl-qi~={ z3L7$G1e)IRVds0b@IlvNwsMF%au-IjqJ>I$*61n!VniP#OW+x-gAC?}Zw${7~c1knx8BFtMBNI|o&;CS-@3Jbc5 zd%JuI=qhUW9;S^muOWW+qHtkHCRW%%V@s}~`^pV8#_+1pM-e(%`%7^3uEiw#@G>TN z&835{8D8$0L6PPK_(XLoWoYE!ZecdajmkpLn}Vofa|S9sF`!!sr*X4HhnAG2;3Lqa zM{aTGyi|#5&PQOv&VH1?GZ>|W|DoDAUtt*Xk)1u^fq%C=XOjl5$1hpcEOW36zKzK*o)0|@7A|@)mX?aU~23x9;%twehHlbLb%{9|to9lP5=2H*& zom)>aBZJ-i%13wD!gveI5pTXQji5-b^NAX{4O4{KNhaj*W-i1U*iq1gFvyHwMs^w5 zQ2l5>aVzeCPGu-bb-o97I*}s!_rumh8MHS?6-VCZ>3)wk+Pu3#{Z|+vOsJviWn&RM zo>A3O4*wRtrB!khF(U6Xty^S^@7XVM7-o+zp^s|T+v7cN8Ht~*18x~EFHt%$9b5M* zN=oad<6aqM$!cE*OgyM8IZ-ne%@-?6RxYx^?NgK`utbd2a}*_7t1R%bzP#kZP*bcQ zFZgkl_3-iKKB0>>2q)J6BI)1qC=qr{J7d3tmB&ZgtZIcRZwSLLZu71Hjt9A2p1J1KStL4}MT~}77AjdlU zRq*lAQq1arjVPA73@yyiK!xa=(~wEuv|l}8mGNbJN>7tylqRWD9U zCkrZ<5qCbQv3z%5QT&$ah+59{7t%}BmUb;_;{DfuT0}q65FcHyD7y7rQ@ml9uPFWT zVDUh+e9^7%g9X2ZL^Nvf5OIK?G-vTuQylI!n9H*pB>wHC&Hb4$P>fT@ar?ql#gFCZ za-J7e#Dz;dxV0&Y;^Mo(oQk5Hc+SZbu2M!?+@6xnRXy)U**Do-#E@_JZbCLUt@b?@ zyCw?vvqmgy{*P;QtHm{Xvp8M5+vsp=2>1L@5h`V5h_Yv8=`IZZJUq#=%8qgwKjbHW#s^(5}HaPn=te~W9JHH6$MYPo%5Cy;F8J1(r& zjTX-D;Mg}W%9|zw6E}Q0Vp#%B|M-K`6F3R-hu?F{BQMdKqU+p>pCxqnz8@DR zDW}2@mYhLHHTm975oxchBkS&r!tztkNo(b7UR(Dy1^31Ca#LIAz1DmFWne31Mhs!v z|9ztGORX9I>?=(j=*o=JJ4h_$&1|E-Q@mmryVmuSLcLR1-jOcyc0A8Q2mL0k**R?U z;oo%JG>`2%*G;ID%ieG4CY8!8w%M$kjxIXGbSr<;xeZCI(zJ_wPaR`AE56gib-s)n z-a&R>*RuInKGE5XX)HGW17(dH$}V&@3mxMZe7^H@y0^Lt=y>gjz84$Q)o*?5X8qB(H++SxZiI8v9tgP$^O9ZIrxIdcVfX7`(eO6 zf3`qw4LCQBVwGL1>BBb$y&v)kUa%eUJO# z{uW#t-waITPnwsY#{7JKK7R*~DP;0=1 z!tdelNUMkwwng&4cxCbH<`VwqZzXY3Zx3&vuOybAti`em6vWT=iJ8oFIq{K`YuTrW ze&Tms{%qpOK7omxz|IBy#<3rAnD5MQLYA_OopbqsO8p+O^<9m)@z@*YyZI4Xg?F;| zQ!4PU+g~AvT!cQM(saT;8$<5N)4^}4cyE;=$?OWlXdeZ7<#7P(zRHu~$|b0zAxD+M zooUHEDf0AINBf`MEO1Q&)LMRJa*ENAH{c!9A2kTF#?-TZ+ZKuryH&CACXM`(GbOCu za2?A}%VvL0USydHiR?w+OEx3VkNwb-qg2siwq=M8*;*R2u3KYiQCc%UB5x9<{aemY z`z!c^KJ;2F5Oyk=D||Ucl}$8tw*owH^PtU6wlFu#hw}6M;l$ivny@tkEQUtV!@hFZ zs}e^`v)@3uLo&U&E`>`<(rDlQ{#b6AK?~On#gvT~$!wJ&rYIKB)HE|R`63~;F#F0qxDbd0EjTp;{_eq zXn~{frNEpr$CpEzNGf{_TE1?gFI~n+1x@5P%Lu~;HIY@RK6-tBL07YMalq%NG*5OY zK1#2rSlL1NJ+hWUyi`y$_C6`a$l&ePJES811^VeXXkx#&aDH(y{ik~$R#ac2hx4w0 zR#gTaKY9WDJ5tDge>@mAN6^&MKA>IfOTVh!0K+$t*knAMSDZzgk1D`_!XD+M(k-rO zr3&SNKW89Y%OdUnh$g9qv7eWE0_=+kOX+EdR=E)gPf{eIF~$d4}s;6-hh%HO9H9(gCaY zn3|_S6UVk=#XwC`neqh(>uFMH?ibwNJ&@dGzhOa}DwRfkLv>W9iD$l`;!RnK@@mIy zaWC5rAMl~DD?bzS29Nf>XS4q{;#%$JY{JC`9KGtk;7WdoB7-tEMzs=mj4ogn6Ru-p z!U?vyKcVrBK-RJ2B4&MA#$4P_4zK}0`Zr#fH?Ailw4g2%S?yF&ClM-8@=>S8Id9sh5 zdN8l~64Myb$z4?b$hv$kaULE6$+&$M$FCYkHUIuv7KP5DV6L+;s&YLAhj{W8wmuXg z$>SS^S?rauFZn>l6gsK#gP$?{JO$49!|Saoph&H6eD|Xg>c#i`#<>-Ax$7ElkaeG) z%!=Th^y(mhVqw^}bw{Kt5h>&7#SzV(bi#yMy9e6@99wFR``46e8Y9Tke{SGM(?-A*m z+#qPO5UnsTCOa}Ml#LOd(}bIa{~l(NcV$05O8XQoJuKpLgb(QTGv@L+`N6dH+iL#9 zb}!nx(379-y^OTJ2J_|*rqZjvgS^}$15%vn$*cRyQk#4TUu;pu9K{iQitTasW8!IE zy;_S&K@|^8e+u&?-}wU-0s~c;_pQC?1Y?I-vKILiSQ@#2y}Wl179ZNrE)MI3gMN{0 zlV~tXcBcxRXfr&_pJz%xreL+~Mdoebf>mDGY(vR9fgPU7n%zAxvH28}bM?hzxiReX z^&reX>c^%#9m7*@tJw1g;kfm^C6m>T!U;pV`28l)c<59tpR^+eKgxY6yo@o}oOeR> z_EI!T4?D({C`aMum5;f{AH#5Bj0TL7gkaHA3(!jrz*~Q9;j_~bJm=yJdzO0OfRv>m z8oLpbZY}}K%dR*z!WpFdIiY&PENF3^hqVm~AUZzd>EJu_g8d=A|Cmj_2yodVS(JkAGhmwCfsxk6wMx#3_S*a z3P0`&hmfH2{H+LI`2BqVTm56klGbLjRh?{HHVx8WX&d&(Ro45f_7a zkE1%IXL5@7_@GCRm3UtDxB;0PRr8zH8Bn?VN8ZfEkUrZFVAnm2$fn+uIXaqjGvxGuf&t7CQt2a{TQBir{~mB{fudp=B&ewlq_$;0|sbyq8ME^T8sjL}t@h!wM!HV7;w3S=xX0Y|y96Ec2==YuuE} z>b?oj#Hq8)y5M}Fwn{Af^IDnHH4k78hI!n*F*}&g83k|)nazaSB3RiQGndTuP?Rah zuIxDulS9h*WfM-r$Ri%S2T!na?z_SUx&!O>CtDuf@)Z7ydnK~(`UpW&W^po8|H7t8 z$GD^{Mcigwz^STe;6>?1?#2^sfgLIX(Yr??|KA`OQD%Z=BMo8XyzwX>$idOeh)4cS zhPoXS5w}c+(+6zvk;^nVUq1tXewhJ{k7wg-)9IjV>5PxRPKEAk3((1b63n@`7*id@ zurt{m8+0bZLHiZhdUq0BZd#4@p%YODAA51=&p96Vob3qj3?KwrEF&YBs+Z`&R4>{$Uf;)O4y^>$gdT?&UM7Rmha z>J#87qs2PXh-wWaOi`m@ zzK`JjG<~WXSOXdz7WDScU8p`~OUpKtLFBag)KF3cuO63K0kr;)%N*G+(ng)!8z zbPN<5#*x={GkDk#ONaa|;NbH(+PM&6GbB)VjWwJWGPAckrbBQ_66x$;2*#L9&U&k$ zI68@Xw|YVCp+s7#76|{QCDPKYVt;Odh^lQ=ePu34m9M6C>Ej@wZy~u3R)v*8 z)9Ky(3NEEpOkMBxa8)WMR3TKwbjJ)Ott;t;bq-3jX0Ja#?{O!yv3|?%X{~3SV@Iv7dggdF9)`Sc8ifuiC3X zmH9CR3qEMjnpGSZ^I3<&XWZl(HW<>(;QmmjXGT?7Q(#-%csf(D5yqVWO05ioo((pX z5|#yNe{BW+%`Ny+WluWcFJWk=BdzZF18Dh){HtSd7kfv#LJa98!F`i2696fN;*NN1r zeguuukxpz6z>6vtbSo?rr`4O%=dWSdRx*k${oHdE3a_jMl*N zhgbPuLuIl4dn7+|=Vv(epEB?IsTMAMR2{FVFM)1PO>U=066j=};J9h~!9?jNH(=;Y z=-M#`tcDMP7Pd~v_BL}NiBT|fUnsYBN-h+3eiTJ*s)7e;+6C|Z+F)q(06xWA25+r6 z#2=GW$8$6D_=VZSakN|~ukg|sn`aMTx3tEiTd)ah)RB&)n0=t|gi?2MBnZ8pWsN0`l9=YEjN%bUa zD1QS*)#0ipg)Az&2$r0`#^f4vpz-M)_CDq`)OS5#b;fbyV%mf zIwEU0u>Hbj8D8L?=CrYoqkOpd&n+xie-yVyVsumvf z5ZEWCeTD6AdF+0-6q{1)4Hx`L}b zTEjxCe{oTxpRw}iS}?V*iRm~CQI;QX*wnLbU?to&hJ4xw;m2HxnB-%VgJVwaC_Tp zunTnp?fgcN-1h*j)@Sg2P8b;JK7;v_(uAzwQ^?KCgPNen;9-3o%)Zyau-yBQCa!=R zZ7<+v(G~D>Y76Rue%AdqJtUm+Qai z4|G)><~;BIgefm`3!F{AL4sutKY9EoaI!RHZ@<0=PTPYm-qZ|9|I(QDix;r2^e*$% zX@KejU)hMmk0I1nnY0!@g!h`d)N=Yhq--%G-^MD4JYz+EvQ_Z=vK5tghGJ7T;rCRkZ*gMRHrr6w zg54~raRNz(A7e^SIl6H51XC3D>V`XW*)!KMq@G{O?*A~LRc9WscwHUZ@7TM`rsrRT+`i+~cx8GoLZcb-~uG(~tJH$SVM$)>)X3YM^ zXi7Mc&!;Ukp*4Pf1(#$@C?+m}>q<2uy9xTRdB;c+hOsa)P=}&FpN7wlgDJ3IIhd5H zQd9GL_z6FR=8E3J`J3mWaa6WtTKG)ChdhZZylsyU zx2JQGU6WDu;16y_xfo0H^g(W^1#TZR3tR@9qKwoAaQrLuw|@D9l-nRY^E(nOisUhE zN-|^|=!T~DG)R_ifyQT9u>0==2tO@6KMBR~v|R#4^UuNLN7uo9V>s+vc^d{4c*2QM z_uy^OT=;8S3p3suL!j_puxz3NbZ!;qUE&5#y5JL}2At$HTe~22?|SZokrejVHRK-I z%i!=qHKNkv@_3!bSian*jJ}!4h3{_-z;~m@@%^T$q22O5e0iEGE^|-f+ly2&tg?{5 zY@&+wiqH8;{raQb?9Y5}r80K;$g;P>-?QEU?2SkX^Ad)!+5~x=WuVCh^~m6LTYc8( zFNG?HN3&wq4e^Czm}&YC*x_Kw#?ogvA3K4~O?wMd9*$=|+Al%h*@~6@egri}z>J37 zgtm?eY-(jb#7En*TMtix_8}*xqje0D?A%z?i|ufoU&nqtu!Z}YdsvPAFlbZ{VB)wI z?u&aQyBc|#3(P*r=ERQSnvY#%<_S5X)-#vckp}ky&qcRb!^A6vdL30v<*W|>xAHzK z+B=P3AakF2Y+u43npeY&f6e7#+ynMFZ8BZW>~(NnJ-Ubch((d6`M{le}fQK?{k(db&6u9Z8^-kFOh{m z=Gp$5RAwJ@g{>7jgx34Y*ru2hOe66&^I|ECqN~}=H_6P&o^)cQcu7J#vB_IvvhTj-6wrmwnh8?Oax} zbS*oUMa)BfGLtCXVpjr2v8Qhyu%NMnnc|}t%&$<=wJ`KJ2;)sa_V6v%Yyg^GrE~~iw7U<(#aA6m+)bA@0q=wE^qd}k$L>+DNLR6 zkbP&dg}O^_F$Wv2V0{D6OwLD%dh{|_Nq`}jwk(?6?A*ysbMax<%Cfk9S2wUvRKr~v zIfpfzkpg&U$XZfjo%$Zh36?T!W0n?HDiDOqsN zT8?@CyaI<$4P?>FAAoqL9$U8i6^MK-*_ebcaCm?{+m+J;o$B-1*~KzAZ@W8lbW*_E z-HTb4xIb33yD+U8YPf#$Y_`X3AR5X~WtSWW;#f5^c6Y1>y4wt7TE_;VjpGv`|D}oh z&BOU0!Va@S=S5+(k_KigpA!|8sN(hC$GB(7$|z&=j=SF=i+&j+;O`S5rzzzKaoumB zAWPU`e5--rFG1kZcNt!8Nq~CO6c|@~9@fSD2YmHqkZ4%J=*)6>*Z7Sa)BG4T!|b^C z3*SPUQ($4c?KcSflFEk*=V;k)CFW%-kI@h2v4siBxMzDX+h8u_XxE)(fonA|BIOEO z_IMChdOu{v8iO%^&wIA$vL@=>|IKu!Xy9=LISMXS#k8OSq!FQrcg||k*m5a+^miDo z7G^XBCDT~Ia}NrQ$L{Lj#N#$)-$QJj*Qii{{qw2<*!zbA=8QlurR zG^j+O(y%K3?7hiIb|sSVT)#Ujqq35SP+1isX_5B&->;rGK6rCK_jR4~J?FqOHzh`R zNeYatp3gY#_lBZLilB{PYQzibnEORt%%`qX#_R3T-Pvh8y4OH)tIU4^BqU(edv2AxI-Fj@8 zb_(35Eum4gd+ZI(Js!r(+b)iuj%kqlM;GCT^$&^Qs4+h0DMQ+l-6&9Z1RfNez-j)8 zFu2hdPbe_Z@I4%rs@g&1XFS^O`2r8wGqv0g5$^UMS=b>j%QgLY1v_k&xJD~-@K&4} z_xZ6LbPFL|C+TY#|7sQYV9OQs8ehZp&&@>rdn|{zEDZ-ujkz(uFCll_n42<~gr4_} zxxaH`uuo$xyCoim%t`~U#iT#l*z0o*+&t0Jo%QDBozb;zB{%ks6{^kQay^CgFlC`O z_iv;UGW{Cdn^Hoko~_1R?$$+r-d@UG`67pASuEx@Bp;(^5>>bhq-N9Hv4z|td-*k8 z1eCb>iN863xa~l!Ko6QZsJOh@VnZecE1aLJ;koz**2A(AR0;3FX z$aWtF_kXd_c%u#88)n0|rZOOj1u*Y;7KG&?e0UWCkFHd}>Q6SX`fU|l4qOhFig#gQ z`DfDf{0`V3_9Gfe<&dYaj1zL{HWV!8(pyi9p-S@}z3P<@N9IbR^pb1vcZ)veK1+v3 zI}YH*k13GR?Tf8!Zo6x4B8m(~!}&8;Q7+|BecQO<%Su|DZLsk$@>z_zlAgC9W80*hWI9pynJ#nlA^> zIY={w#ka7wayH{Wh$xUgi-EQa;pjzFHT|NjjB$u~N>9=ss!o#SNmy72!HsK=EYf0#XJ)6wDmli?h%V!pBs42lR=nzu)28C(FaS+ zMLA3QUGbpeZB9Pji9_T*$0}L}^g7*%Vc{8)^)TZ!QP5A2y)g ztqI9rJYj3+a+W^}22JI~;35|V(Zfn0-ER5T= zBhm|--x`v5$pJ9xy+91yM&Uzm2C4h|0hkBXWWMACD6Z}!1@)6KvWyQ*bSJ?!btW89 z{0ueb^TDrU92|cvfx*;wU|FgTdjm&6C7ufn9xtKL(h$zPe+C|BSl*@NF&LMb!q24* zp!?1oRs~gnkD(dpce7{9HUpTEmI0+MtKt4o96Z!#XT1`GVW0R?aI(4prSGMo!Q~_v ze-QzXmg8XjWP+?dZVy?B56Ren_HbG)o5bum0t;9B67w&|KuJl1T)X57FJ?DzK0Nh? zJG&H%e~FDf z=eHI1H^#wZ5iblIj|NfWD0~?Z4&FD@u<^A&xP8vYALs$zdv4>l_Xi;HP9>huT$S6Wb}?>V`#;vtH>yg?*m?&IA0)5P#cIo|VCC!>9Z zs8ZL>;dNiZh-Ky+%1cI{`2E_G-@(sNVj&c#15_MZ)nSS!rz4UweJ zRcAB7$__j)IYp-Qr8ejM{3T4HAV0}IrNwm3K1EhNT*>e+V2E*z0i#5|la8Tv%<3zW z5ENv}xW+CA&KFb0+Q10@Hi%sKtzSN-;(*)SufKst+%wO<-G?&!h{|qy?UL~tLM?j|a9eHT?9L91Kp-`?K zE}Yu{E6oZaX!9w^ue<~oO(UVnJrIuF$bv)9_CxUZQdmnlAd%J#CUVjs8uJSB9=##Q zG{3;@j&xEJAi%Z#rbo8ina*8zA&PT}kz#k9ck(_C$a7yf&!G1dmAG=c`>CndQtqyK zQ55SmxPE&o=?p^-SLk9d9g^U34ZQ@>W>AOgr6GqV1?+qG#v(k*W};F()KHw&>m{x;krcj~-f&Gsc&2g^q5(@9j!l=YwXbKRSoIZpS*bDW1VK?O=bN&HeDN z(!|~k-{5zL3Vt6S1PduCG->RB_s<3JT-klF`#ea^z81qLD5qEKv*6L`M@hB4_i9Po~}z|{7pMaXx&dNfA$c4CrMJ5)I}V;Dz&feXe1x2+j$bx z+3&4-D=JvbBMaR#=$Y@4{z3i6-*Mpd1z;k15v92CjN#A^n4!?_UoGWOx{PsCV% zcT}z`L*J$_3>~RJu0;xJ9j-!&&>VDWtHE5mLcDsZ4h1JlQAV&4(=XKE=@rfBBvOm} z9zVeiru8T=-ix(C4M;-QiL+~$3xrN~0ZNE|B^aT`5`;KbT$1!%r1hxk6Mbkg; zukbRIo%0>@%sYQ^$dqVk>+j#1Srd@iO(N=j7l zkU=_GDNXWtH08q4O|xLx zv}@qYnGbJFGGP3%2AoMxgvss=U^6ouWE6LT$v;0BOF0bN-P|GWk2ARnk6Rp5;oAPyX!$-1k|*}ye-EyMO6_UX{CpGEIs2l{nL;>vHXMUi zQb;L{!>>WN;na&n_TE_n+y5kC+hGQ9elps&@IZH40$$T8fR#FN2uu#RONFBkO$W2^ zAlxpU3?D!H;)c8!*k67QmrV@?86`K2r02nDtt;Mqe;6K4alz4dJHcw66D~Vz0!=5J z@!n%qI6CTtd)?>2WAEe0Vff&P_8ByO)kSjEPhq*_bt1gy1im}qL(IdD;_7B?^2GHp zil3vLqc;y>rS%%l^CTM#{2*0))L{?m%}eGPsqDa&r<-|aewm^0tXI6p5k`22Pl!f} z8sXLDA9)5Q2Kf1TFz-3&p~jkh#Zq&0v3a{LC)-j7HyB^xbeF8cPfL0@$rbu|Z9tTC z>*}-oj2u~Bs)r~BBn5P^x=@Dv;4H`TpZ7V2`EyW8B8jsjQV?&<$4_a~&V zS}hbR+SRdsV;c0<8{vWRLg<}pf#Dj}kfXd01-x6qI`A;&>GlHW)G_=hGXyJEp25Rw zM&W9=C)T;Vg(vUNqDs{moOe5qeQ(AfSjGpZ3%v!W2YzT#ISMY@{qbJa2&9z-qmld& z6kQ9$=3o6_y)76EM7qILCq8;$5 z2OgUF1PWr0V#n1scw)N?cc!)jy}b@Ae|CZOLrrX$@eDrKE8tzWhh~eg7>ZN&^K~C> z{n`m05jhn5pFrwqN80S#4xV~Fyw~dOaQ;PAaY1Ve*4e=}m93zElwI|13}EZVyE9RWWqD%O72r zKBAAb1JFG|0I#I@X82hlB51NAzGF;!9%weOGO)HXG=P8dULW;q&Gzr~R`TDbk~8}yp0 zj+5FWc>UF4Y(4uLlbn_CdCmYP{F6dk|6Y6=FM@)`PjO%EZ>r5{#VVbC`e~>Jub4E` zf6j=-g(cKF>F`CN0_@Vn?m5HdBLDXLtusvw-62o184UGqgC~g=l>Xpa)Mjk_T;<>6uI+VBD@z zWe-*0e5CZ3+a_@Oo=;P&oFQyZDt+VW4=$a-G<8ZWERJ@j@>Xf!ouNf#qi;g{e?NEz z)5;;jFqp^xwgGAj))k*~V>9DNHgnW;UW2aKOk($E96CKsiO0>~P@CjS9&en=Ep@m? z!r!u)-;f&eS5=JdQ0*b*_r$p`jQL^So>^R;=PW39m*6h>H4k3Sk>GwcUktw%%;Mf_ z;DAh^ICplm9)xR(achK3;q*>cmxot;*~$N%^Zaza?$Xxx({~j zPXQ~dcBtoFhX(n2cxugqEDQD?>rx5tkLSZ+VU+W;)n z=F&^Yx}juh8jV}j2@gKE(YP;o8yO1gv#p`PR*QVcLpU zcx{adEG~PGe}KR_kslb-s{&)!`Iu*665#JBz`WT#1$2Z28SS>Gq}*7DS-Z4|Y`HAR zNZtt{d)!%0x!8o9WjhD2^LjWZ@}@A-dqp`%X0j~wjUBv;Ucd3AtT+w2@*TfB*wYUR zUr==-g<89eqe|^vI@e_kch|n6hYN=B&d6W-^4=@dauLOgRo%FvN(#4FcjAx4xhS&z zA^zFRvhB$=*f+cwpC4v1_;Ga%&&@+Oe!w|tmk}D);Nh1MD6VFPDt+fs>7^yB_gJI% zRy$O-V|^5BSG;E=hdblFG1Fp{S~0;W7MxAzM#tjJ?dCM0I2C`6`SAYgu=}!>0h~B( z9_A&QljzIcl{@cZ_k(Ao?!S5zJ}C%`x|+~y{ycb;+l*SK>}=h?NBE!g2B>B| zk>P@!5Vxusf4w~f*JEq(lAtpzwy(r5!lz-|hTAM7;0h~O7hu1c2iytI#=?Id!0Smu zm(cTYLN^?@Mft$r4L+FH;s+gu$5F+A^-yP8qTTBdFdH>OtDV6xIj)VXUi*QV_Aadj-naJoT8kZiBP0hc^X}0#!VNeLpb92bY^}_7AHkkxz3Bnwq7_x0#03zo5 z66^N@V9Ixd9Q`&Grp0V077O^{{JgCMH2#tHZ}vp)%6C$raGo$WlO*#>B=O7nPKw?q zk{60UNovL|GHcTms4uT4b7ICf}1*xWn@ky3V`WOS5e z-|S(Xh#k0eIlxoXy%0Fl7EGeIL4C(|keIs`yiC@@9Ayqn+pW%OIEx^rLL9neKREFU%6Oz_;Q`uFm`LP?76My7dkwH9w?J*v~zW2550u zDJI^Zg1a(#D5pFN-2`snAB%;kd@B=|_;PT4Z4#QtuSL0!VR)R?pnS~E;?x#L+`iEU z*H@iIb?epG!FtO*OB9gW#o_G~eiW>`g#NKj)bCLmx;^%zBh#}`>dp-MsP`Hk?tWM7 zXp)P66tg)C4_`;OJ?5n4eGVSvzes9iuj2=eIwG+3I{u#hi}==E!F!ssAlKk3ZfAAM z^Jp9V9pV0^vL6E+0}VycWMc+U361RoDLq;nRxWO>3{tLv_uCOC> zAIh(C1+Vj)P?K{4f^+rp?hgl;J-HNT{@V|6NwT=_#V$}@#*g9_TVYCEGks@o43QHz zsQz;uFpT<-3e8f3blJu9REPr9{|Vwf|1cA_^e^YgiA@8+Wy0iJ;14owu^q|VF-pG9 z&Lk?f4P-vAnasOK$;XC|q&qN&73*vCClB0ZVdUNeg@j)QN6^ zKA1n8LneQ0fN)$)#?M-UB%7Oe)p7v)yq)CnRknNiwFmhrbQa#0MH7c+f6!66Mxxxp z;7)BRF%FIe>Ev#*o0kmY!u&9NF%wAWEQr~515DzT!2BNrr5ONAy{bSt(Fm?))j{Ty zZIGY*2u!c;gZ6KoAU5d)vk&z`gsmHF-unu?V|-xF-ytYD5&({GM&OA~2&;3wh2suk zpldP;d7mPo?8OL7)sKVq0>e=GH4c(JhJhn~5k9ec&c<~Kuq3JXs4s%B4{q+XxP2(1lC1IO0jYRQi4&Z+na={`(L@uP#u8xmIv!_iQ_!H z>28D71MBdVp&RCUI^x1;e;m>b#G;M}d?%2A0-F;t+3G5`e@;i~_(JqDyM~4PtI#+$ zA9-xYjl!!UlzP{KReupK#f?t-zI=#?a$k1x|My#aY#r_+|Ol`C4UdG9Ug7C(0l;r%00u+b6;YWSPy>7=|QQSew>Ku zLeBdaINH~W$*W$W+ssC+eD?}h#8zSa$V>d`#^Az%Ui^19A1nVoM=Osk+=cBJ7oLF2 zjG9oVITT6AU7VCTi_@Y?(4ou*TQ=uoTkBe!k(`c+l1tgHgeX+Em%`3aZ(MI8gooqo zaKrHt8sE7AZQoQ-$NfuDnM6@ufG~R6?4fsM*|c2S0vczXO{Y&U;zcL#rdhVCyj>3_ zc=-6Z_KWV$VxLbzoIR`4Ic3VfIVF4xi1BeQ5fwZ`KGYl|ysqoyqtHbnY2QMuWy{F{ zr7xtyqKBwj&wxzJU!)|PJy))s31qb@)J#_bp~t$gsDlIHoOLkep#dz+wSs>&7NC-Q z1lDb_hk^s{F!<~o@QeC_r(G~q`36J%=@>X$5D8mHlG(nX1o*Ke1E#!914W-axMzD6 zM4uPH;)FbCDP%yR;1>9$SAmQeg{N5};xHAiOyi z4ZP2rVEwWPsJ*`uwn+v-p3NfQ)cL}rpR?eK>seSi^*s@7JOR^$;r5|@QQBO7@0+orR<3|wlZ|DH6lyX?}EHDrm#ZK^RX zoSgVKL*tP>pSdSz8i5&)Zq@kI=3(ECm;OQ;r z@N91e-dXB{Q@XN{Z#V!u2eWXdVHgh2$ij(zQK+XOm>yP2#jfar*>_Ul<{rF{uF$P-fMM=FSnBuns_m|E@@g1hP%5sQ)IctEc zoNiF4)xxgsgEV;ALgb$L&inXA8s|exv5LJg{`z@^Q{Og5D}79ei%&JR;e`_+nPlqG zTTZOyHqpkP1H`zbhu7NnhvX)f75z3BhbrwH&ckeJ@SMTwF1!VB?sh2Yj#2}McO@iK zRD<=|`bj|Za*)~fgUF9*z>2Kn^M-ZqL4NcK-sQi|;Hxu_r}(u4%t{rC2fSZ`RD6W2-EExuxsxF2J;C80`355)62zqU2k@CLCp{Uzps02oxjOeJOxm0v)oMRr z#%Es=;re`Ht9p2-{E$TLy8~}O)si7n2nySZ$@S7KP}eUYCvL~VtQT3Nf36o?^ob;0TdbhX z#Dh!@s6yRF8#1)}BN^Z~B~7gU)HcB-Gw0W8DW)iqqtb3Pc=cSO41cN8YbCNXeJxJO z*C16h0`WeZGk+Cw4W<3}ljY;=-ROujDJmUCd-Zd~&~yqzuZI)+6SJ5>mLJ@oHjmlY zdy{nccPIU(x~Sq@NH#~Q;wkYy z;=-?p0Xh5-mm-13^QB;$5Rv7~Jz5?8v$3nrdN04i< zHWVylg}7GstZ(BX%++!Yg&C?sT&b(U@Zf+TcMiMdF8WD;d$839jwem!hS!|~rDi_v zbNSQo(()&)*yjK#?Vq4oY$p_(55wn`8==Ud2R3|K0sF4C!1n0*5WMp)xJ?%X_aq(+ zjt!F1@=Q3C#*oEPG4MgmpUCN*g^l-=$TF5OP?nG2gl(M%8_U-4KA3iqC6deNgF1V1 zJvE#22-`R|FK{soX-}A$=I%P(9jT!7!nZ7HdG>py2+YS%XMc*g!*U9J9Cujt%d^#!L`ffZ@+C?wDX~I3{ z+UfqOcQA+3M#BONap$xyYR=6@r{Nw7JL7R8^Ev$`AAomObx@I)b~xfk98M+u5~-jk-9>tPZo#F8 zB9Ks811}7gK>FQw*qCAhQ!fmFjj;`geEI~QKTd<=T0ZVQGk^HJRG7O$ErRuFW^qrK zvH6g_bGRqlQsHg$eD1-FY&iXK5x2iT2LjHivm44c;fxiB>*HDkQFc09i_u~@qOgYh z)0+n$TGw)q=rM2vHgFHJ&ywqa8P`{uflrMax%R>gJapN_{TRo<`O-~Xjk_iAT6Pn+ z<3|Zhn{UQ-;grI^sT;W39cA!pp)q&%?lLf(V!&;^UIxFjbh($lm4o4H4tJJn1-LF# z<6hcV3dx|%9am;RPEnp4Gg1U*f7sq>oqTv(F2s%Nx(49$6CzKiL+91k@Zv~39NE75TzI7?|Za-C8!;>dE$`+OZ$3{CM?KZ7~(c32X37Y{x;kH5D!V_R1!9**ch zOOFKHa^)r4Nt=aVY{qcXARiU`zGM1eF$QN(VaD&2U_zBJ^B z2&Kp1=4Ymi%#A3_K4i-5JQsnZQ%#xd&TxEmX#?X`5QbJ;O_&Y8LvXOih{?~rtM0)6kh5hL zGxqKrHnF=&{(C(z^V&C*5kHB$1P4$c$pO#2dWb2qw)mk3al7?)%#^*1+*c;}>z5BU zTdu&{2AgsD8D(^wJ{MTO#8}Ny& zUrx9d`a;0JNSk|GK?drpmvdEKECbGfD%UW76=;?%<;pHLhY+%eTkW+Mtd}Tp|Lk!D zV?#ymA!Sb(Dw5|aUkZRvowD45DbbKuGn+f3=Mr4jo5|I=m<7RIBHZWhxnS{BfEy0C z;I!s%koH74u=OK&zb=D=^IpJ85IU8N9W;54#esLh66_;bng`>`A!? zopv7ZPwy_AyJHS6IyLZ{UlHO$E8)+_UUGR!8CY6+lM6SBz_8by0~hkZgYP}>+MG=I zGd+^dP`?PyS6xPlH6Vl_y6P+@f+4)F;_FkCF+<5Fp zjZ2i6uA^6}|KMU~&WF2{+pNZ%Xnaa9|7QCjF1(=|E47*29bakB9}eSpbt*p1<}l%P z!g%?n7IU#)80+q8Fy4ORxHwaddAep6rnCL&7M~=rWk{LXQy__&hVz+Kr)619Q;ykx zNdY;nlFZF@Dk!ygI&-6L395+*GG|Y#;T}sqrhSbTo(-QwHWGvBPHZ0Vi#D2hcA=XM z7kM%d@HERgz1>lcCr_+Eho3jF@Vz!(`FR;_eKhf`U=)7Yql(+tUce{*?C(2t2$M3F zWBVFoRQ|4xDpredXTwr_YCaVW&#PlYMFS0IeZ{=S(^Te^ChDlQ@FtSAP}A0l!*s5| zkidQ9!-yXCZ@o`8JL=<$*{pV-rjK9yv_PD*21kr{z-?_KmVrM99$Ss@-s>n(Q!~Ou zpL7@~GsI}Ye0Z6qkD+a4;2yRT*Xz~6f4W?3wrGKuMry2p)di3Hm67gx0S;4@Pf5QVJ%6VDv10ufVaRh9>!@Q-EWLobRu#etE*3O@V z6aNJe8<9^ScRZV5%R9*WSw$N8-@>?m51H0D4AH^DrL}d>oQ3Fr-2vLm7q>#6I#EKgYzGqaN$7-IP%sX_2-L% zyjwipu;z!-p)6E?|BqNKE5u~$adP2F1%5x#MV{9_KCYo9N4|DQjK1U(W|SXo zrNQTfnU_pB?LR8S?2sy?LOX<*G-#nwGX$mv5#STY2*nW$3r%>w4OH8S}fFHy9P)Z~a zHBvi~XC8{%IBlrg9EFo?E^2ASMHFhdk1Gq4@h7Je4LsBF&Lo2zH#RG>un^H97eDId zVo%#moT8eJMixcreU;4{ck{6IZx9}ydK-7GWc5zj3bf-M#E%!MQ0KsUjJaHci-wk> zuU`!=e=3gS{gvp{J4}-<-$CI&#WZ7gImSFaMZa)M(ON=?4m(n;v2ZU69xXtf_#d2V z$VCC}d7@pC$(|nyiK5meWPMe#^FbWSCe48O(g+kS(15jX1F%neJ$e{)I z?|{CuH1Ei+I*2KJ#IbID1om(C5bpzBki3TV>1Xu8n0-IdlpF-zeza0+|AFGOt}s}_D*qKct`?XAA9j8HJ2k2`bLZTNfsFWj6{1}FL1 zp7-4quN%FuX|UpNw02-= z5~#kGDBz;HO`vAN~VqDfd$aEoj- zxrVEve95taV!ZZGiF9OFVt0@uhl(^}U-UX2x33LveV9&-Hh1Gzc@H`$Fo?C&k>+^5 z#j=^BR7`6eMRrX`iDzGNyU-%MZ}AKLlGosa>wmGma3{Wx{D%?)&RFy4A6fivyFTQkvE;|H35y^gJ4zT&Dig{YQ1frs-M)V?)_a_x7}`r$A- zjoigXjaPVURs;UXdXB%;9-?Ad8@`cjMW?|=>}_qw4^=hT`n&_rtCyjd9{UV`x`hWE zo}poVHdfE;#{4Hqn7pGK{cnWfZs8t06Xk(#_jRLIp%qFhJ;&4~fEA)$`2DyTc9%Xu zPV57EW?37?9CxPm9nH8IQ+Z-Z5AZKEbEf#$qs{anvc>uys(tSu1)D3e@X;)I!TPFU z>_kKTU=e12v;q&+8~E!#4;VOd1+C1(fU`3ljlU*<`PxKuV%c$zgh+hSQveA|0#SEE z39O3uKxNq)2v~LyZ4ByQpl}m@RcwOJS-N=Dq!pwK7183yW6*J6^ZVKDFvtEiEz4zNU#<7x16Biryhb&i!^;-Sq}zlHu8$L*T6Zx5Y9@iQV_INBPDIOprSdHsK34j zlMAa!P4A}Y7W4@a_>p)Ox=PgG@x5F)o4*j=R^`F0^>bj% zH4i=&%z)eE2K;Fi0Nt@%*qHv6_=BGN*;z495mAXGX?7+IWrUDdSs5@k)raJ_XTU+@!(^IzCXD|!CHAV>And6?PEWrA zf9;-fHu+{l{mlcMu=`oSKe$7S^DzTHKQQIBvTu^_{DZuwdoRNgc^#T+p9I&!eW;g2 z9E_aErh4}y;I?`rEjtqoYe!$xwbT3{{-OZJbi2ZTDzdmE@hHf|FGgjxz2I!X!Od4U zf$K>_%)~X2V7Uc-^$1jG@4>p!MQ}sN9>3p|1@u3KTUtb+<&ifEvfEY;dxDU@?IMkQ z5h$iwLiQbtMHjC`lCUWemlGQjw(K(U)c$dHd8Oe)rv;n_pA1a+HkY^YOcwU_2+};Y zE2tCZOb>=+3c6s&KyL$AeIXgpz!4#v5tao!w9 z{BB`=njXe97UN4vb-bE~xM|BgoF8->h2Dvw(a{oApEE%Xx0T@U)lcZkq7tkQD5jfP z7U`XO6fM_haQh2$+HB6lY5(|XYeo^S7Cyj}ZMuoAAs4hyi{`T5C7GO(Ls@w0&2%#V z*JX^V-9WsKB;thYDI&N&8YSam$sW646m=;eAD{h)Qh#d*pTtq@)L^ynFWa$2c7zmu zG{i77K1h0|!DdOs;PyXxR1=Ve?p;DS%2NiXC$DKtohB4qxI+(B>w(INi`3Y3BV7G# zN1qm1!_$%(bXTzp)E;%^HJkadT?ve~!o>)P+5M1XQ_Sw0M6M!Dl4)!{D1;^N)* zKIgk2aPa|HsMZ73!^dFT++LVJ%>yi@dZ9Vi7k(ym!){e}KiS|p@ZLm%o$WKY>lh0G zV_k4=Q380IJOOFVWO)3s4Rlvt2JY_`P+y)7X@4KU?W9bYczzE~N@v6F@p3rMK3^GW zJXjx-1%v&$5TTR_Y60osIFtsP^5a1JVhRW>4}yj4chwik(@-H22j!2gKw@hY*s%QQ zNxu+?{x%n6X8MEPpI_uy^Le;lTtjYuZ~=j2fAUP#0pus8N#gX~;P>>7ww1?5u|zjn4sJZQ{jjGEX;W`NLH^^!B2mhNbU5M zsF_N{~dlNH1Y^F2$5KY$~q6-Sk zapu}{)bwr*%BMw85!(l-!0Jch!fm*}Af6V+J;S6;sdWFn%_k!9SoW_KXPSByB z0!-A6DLASk!1$?8$F)nRG7uzmS17T3%qzSm8FsFj%?M47J1)pe;}z0~9hq_waJO zwJ;Bs?N-E|XbR4AXJ8t8PJ7?`jV^q97iJ{3(Nf7q@c58V&mVaNm7fD>S^Hxs-KbB$ zmUY0VGkv@gkEc-fSAsWN>lu8Lexu!7-vts67|zJ}Q~3Eug;c+N3gcofM8xPR^u?tS zpP8NDxcNT$vZWnl+?cz;`|Nz!&m?U-an=v z8>fI^^G9lPdMfz0vYnsFQ^0|63Y#0&$w zUlExp*4R_E=ZS24Jn3I*tC#W=wMS(ZoAG=(ab4UX?kIp*wC-iw7R)d!U7Gn05xw%D-QiJ6U@+R%Vko+w+6cx+$DzVG%?6?lstZ>gqxlU!K-~z zI5loA+v7D2jgvU=IQbp@w{6-j&JSXOv+53S=r3p~CB zbiCge*2LcBh4co&2up)_-wp#&!~Gn7!D#T=HOkqe5(|=B49M?Oaj>B~gnZl)59KRw zlkH1lq0;6B$xw}krCrlttU40vCFj5Zn?rgds|I$uK`^gW57NK*!sKT&V6|kBc(s#d z*_=Uk+zxDy?1R;vC!pVWGi;vk0bKT+xvt2xENVr1mwHb z@zo6<7gTlm;QAgd~xM(y~{QEks3A8K38V ziqIrVr9lIwK|7UFQoi*&zd!uv;<`T0an5t!@AvB^U_YL1BS9Xs*vA{|$$DQi=HKE? zL?h-hxpo)g_jV2&6tN|%U^c7un@J9=GGhZvbVxwnT(-zwjV#(Wmo1(zLnMEjvjboM zfvvj@JGij}Zi_7786dR)j*hI+_%ImwxU%Cr_re(O)vVloChT?yWHvCs*`D3VW>;MSEr@2D-M-LM?s4qSVh(L~Ca}(x8&I_+iP<<5;HLg0*4>G? zgeEbg*^kidQUZ&S{DyDu#4@D@NjB3jiV2!jS<>vC>{O`^n>2MRTQ$doNgUq5{tj3& z7dIedSjcX5w!LcyTjeRmdL;L- z8O=X%q;m{29P1^=%k-%no$H4A}IOg@Y3`{#?*k;o%uuh0(ZU$oHuR#=B z5T-)Do!G$~P8$+wmCa0icp;Ii3u1+7UL-2kmpN;O6PLl|Y!??zTAnzvm(P-ThNLZX zIliCVEiq%Zzp}{TBOH6Dk;i*br!(0DyzkX#0_!L$ASn^!ScQE73GI+z#)^4l#>*e* zyC91!b$N=#@6(C==j-_I+CFkGxeAq^#uMd}d8lt0Mb0YhK%)hlN#Jff3_KPyhh5LsEoV>|2i%Cb4)GlwX-6L zzULsb!;19Co`L6IEJ(HGDahYtPK1|Bp)6@OX`N9352w!}7Y`=FlFJ;)To?+AMheK0 zdyY`?N|#u!G=_O5x&(73fwqhmx&7`JC)%S)Qnoa4yQfd&d6^kpT-5|}Jl2ehv`{0C zQ!51OTI0#f>(7kkB*qitn`3y_RheAwx`@MN3S@=CLsU#1LuBp0VUe>W zF?cbOEm|l-#2gfu`teT?(J+a<)OZ3HqIKDr*k-t?K9l*qN3b6(6K(QNi^|`Tm)&iKR=D|KMQitifUTk=Z1e{sq%}hr&b0PuWZ0x*b z?&6Rq`(QhsJMnJ?qlV4KvsW!)Po!tiN5|}$Uey_D5@W%V<-`zTd9PmiOq}VX%UafK z$JsL`vhw8zu{3`S%UQ&;hJr+xpHVx?-S5S*;@?m-;T9J0`GQkY7x3FY74~?>5mf%B z&AfR=-~)av-l-Uhk)P%q$yF?1L?1O?w2q}g9c6PjvGbOZwD;$3 zc41tfaO#*?_UQFNL10!A+pFToExNdm>8yUjO_J#tir{+s*QL^2CbTBWj)ao*6A zmBQBO?}qaul9)f23F7*(?Bs?L&~%Gp6MrFWShkIgc4!9A%Jrd9t%ddO>&L zVm9e(AKbrc#UA_rf?de#$$p5FoWv=t$5e()`Zr;}*QP|Y>;z5OGmktUV#t+o6Y961V-oU})PMGAmz( zEaYeD%N)j&B8eH~#(W*}B3PSDooY%hm`)_}74ym9BNbwPdYU%-Gc z64CMjxT%pOQ@j-(ZHgiDwlT1L8b^Az@LhbpWU|RQ1~fHO$sH8HCGm9L6?>JFyv5HX z9ZUqm6TD+!do(qlm_dB|)$op7Ix$oW!GyE>$#4eW(Xve?62lL%_)ZdWt`cQl+Y*Ry zl@goP5ks`&cn;aOY}n7g_$4V zX;Coi^lXK+fB<&5i-F=6UlyX41D7^=vQ6AJxRSAqoe!~r$Q914#8Vdj@b8PCn~rfV z&lfP6oLa$&NGsNNX(IJ^n8TbsU($zjO;~`ZA&$Q(V6QfZ1m z5;=|ii+YTgwKUl$ zSi;YC+{oXf-gB;DM3@5$*jR<~F%E3%frB_bc@b+r5RI#A`Lk=TJBo+evFa>soTsyZ zDIWevCr8<`5u!V(sN({DW+^oOw9t+%eUZdPt+!*7tVBR(mmOPn*aAKk+Oxxru~6^5 zkhQ%i0fh+**_75x0KXP8tJoK?=9w)^cM~B+y*6y>ZyA!k&XUz>tC43HdCrlUHgV@a zGdF5XZd^BJBlImu(h&ouZ_nr6+jLpV9~TmMK$E@N;YsX*C-8sU0P^&a3OirAfzLO} z@vNCpvea6NX`GKBCkiFmAML%wg@`ffxM*@>(O;a##S+Z@i5DNolKiqhbgPdgQ&e8y zx2_nn;cy2oE{rB4TyNr@rBTG_5<@GKJw&wT2!^fRNepktV%_*HSi8fE zR9Y>9;p2Y9(^UyZ7lx7pKUQh3Biy zO5|k&&oQ_xL0+2jJ(P8yz^{A;d*T-n2YTl&f}LM)AkZ@eF;V^^ZlF3lrj3uKX)!2Iah~0Rj;7p{I1q+OE(?E@8gf2 zm%s-Ws?0h^i|3$@W&ffraI(or_GRO8tnUAcSBiYle_K1=f%VvJSc|`8L-6Y6Ll`wT zg!i(9;Vo_h9yQj*kWJe$RkMSxd>@Oq9?hlyniKK($j`<%NDAsHZsvMR_ThTjAKWUD z{g`Gy9==Cq;5u1zu+_-I0e2T@S(1YZ`Vru`Cj+nQ?1Nz0T(tGigW|mhQCg`C3O?rJ zdbw&?5nh0f$_-v`Hbl*1J(UmPuy z5A&^pQCOA?r8E*%lea@#Qw-{bhrxsUiTH1WJFMQ9jwe>kh7%VH(PN$}>{(QT%1NW) z;;nKFoA8}mUw;nUY;JJFyRYGh#AL36HsG+VfNLMRiA%jU3POFG(W>%U)zp~V_`6Jw z9{qU-9d<;~uC5kzkvl~vcr~HGvWq$`yMYt?M&JyE1}ynF5;b!#Ve)T9ymPJwPd-&c z^`{I~MjBw{ta3c@&=hr-9m5($a}=ACg_A|hFw80%oog*n{7e8=Ojv+J(N=h88-M;^ zAcq|t^KrQLHZ9(2hPS_m(w|uzrcaR*#^vatg#HAM2B=|ZLnZe!OB@%x5d(=gUuZ7B zUyz*FOVyVxhpAzgsHa&ZI9@tQTkfWV{n=x5&6VS@(c>un*IEZnE6Zryopy+DE~mdL zUPIT)2C6lF0NwzO=&zg+#I;lfO+6&ZO-Tdn#TA4=rKey)Dge? zk0GzeE=CtU86s!27{4x-BGLwq=pHtTcrLX?i>y)PfwKu-l^97v?`z`AJ(6VHL}`4M zCqaU5wo~Jf5oEAoJEfDv$QrFI;hI=+a^_2g;9=DWvOsDs=jJ3qZazxlu9S%ry0?Z) zJUD_}{Pmn0Y!xLYw?A{=7ySc+o*$g&jNdTrL?@R!{2g9JwsG0xK7mw20ViGZ7FrZ0 za`A^dV7>c(fu3dyxQIFkMNZYga>0;LH{&GiHd#P-o9DvkmB}=AdJ@kvKS{S$uZQ%Z zX8PZ&1<=0!8a4IQfDUM)^JWZi|Du|yv{OE3T6T@fJs8L3Ex%6BSE&o0INhK=4+e#Q z|7)fSJnPUx`4)|heLzdv1mX~pQ%l=EDZzod7FxT<82)U0 zLH*+$VM+85t&dv^^rk2dUD*wVPLlY2Ln2(;J{G0*GkKq|Jf0ao1j|2<#2N0VK`u}h zf6iyHf7M9LajyrLqJOm0wi)J+`bKYRw8Nv9-|0K^Zg}VVgnnp!2fEoe>7eURI45_5 zjxx>_S_E=J=o<^@9Rv=YvS@gejCDN;xLO%~Gk#9@) z(aDV}psM2E0i?J{ie8xT&{u7nH!ZU`Gn4ng_*1fj|1eQ;&K zSlFAr72@wts4`x-1U{bIV&pAl0Iz;T8znePK!WZA7hjDi;G za%)3I8~a<%5Jb!!DF3*uR5-KrVO3wI2koBmP5Asz3GGO{B7D|)o93xK70$5`#nhf} zLItU5=prFaPso{LXS*!b{NjnHX2lEN4erFYo2ka3^HZ@vxLH5)otU{Z z9~W!A#;PCbxZ`3!Zg)$;i2Hxg}me#-}qTof{IN1im|y^Wor5oJ33PY ztoQ+@{L$u;BO5SxUlP|jSdIVfuHk-7JITKbz2ppJ@~|#S9F}YC$1HtS_;M!_J=!^V z-06m^Vyt2EfCbjrIl*kFX?R1*9Wn+*5N~;cqCKPQTfAWPLd%~;hDvI?%k9?c%nZZo*(rCS5YgN7vl}_;z7_^wF%}39fvef)8bj(9-_g7EYh`z;ksoK~{eiYTR4|*DftX zX%T-IKnI-Oz7y7`nxkKI3LKrrp~$*4m=`}4OU7rzIo)xn)SL(RUi_pgVuygaJ)|?T z55mGr=crOa4#>FV)7^LgdQ|q%@fk@FmFz|jo{a(JpIY?8neDJ8=dJLsdkD1HI|#is zT_NUWprE*XE@&l)b1_XbAZB48mk~M^9I}v`{OKKM8T*M7&p*#Ogvvtt-~n#)XJh!+ zEW^br*+cb0G@f_c4=k2N2m{=9z*=#6diPfxjFt|h@~tUQw5^h!-IEQjtc!LQ=fJfh zF;uHBf?L+AxM%1v=wIaT{f-k5Yb3xpowM*~gaG5U8ALuY#-CC=i*<_tmu_u@wHr)v z$gc$={~F+*8LcqRT^p}BJcPMX8Yr~xhG8Wol2Ia6(eMq->l}@arEkGTLITsS zy$4?=lN^UaK1pVzIzMSx9jQE zo?bXNwuz4E>jBLzwe*O5FIa!RPD8H0fem_3s6u2fpX2yMdlb9Dec1@q-qs14)0FUS z%p;Hr*TGRYA3)Df4)u=QhLlUQ@X@)eaCoyFJ{7BlZ@#YhHAM*Lp15QEm6LGVe+}A~ z7J-9NAlAENK-$c8m~@iQ2Q>#{^QJw}?HPhs9tDEev@nd?xfoI$!tm1M+2G%^5mTN{ zhu3e`;FbTzLcs)2obvDsr)lks3zs!O%4OzolN!@8?&xi< zSF;S)1`TtI;S#>}REIZX?_*HGOt@j(i?v%<0DS+AYrBG>u6iV!Rm0VTu(Q{p{>pYH-+2{&&)mV%x-UZO{s>mcYGF#$X11wW2nNeT z*po?T;qVbZcK6{i_!YO3Mcq3B5uHvE_A-{vSO$09j-f!z2~09mvG%$hJa_fP zJpYAIqoRRJ4CcVN!4@jN31BSeNTu40VOEG&#mH!N@RQxZWxwVB#v5*PdkSB2V$qW! zacd=48(;^2q+Gd@SsS5H;)%c{@Bn<2lQMe!xB!Zq{t11GPXqpnp$dN0p!@6wJz{hf zG}ejWkvF%%>hE-1#Lt57N;{)=@N>{M3&oFoX5eeiJ`8Lcg2VNt_=$>=OG_`}rAjH% zq|k=>M3HRreTmzDs}ud-LpXES6!JJ@B=dcvLuTC=%X*k0`SnDVIgK(Qjl-Jk=PomH zG+2kVPn$=IeGJ)mulXb^0obpC1>{)cEanr)^Lr%BnEvHOq;|$!=Jah5k=QejeVy${ zY@@7L=zs&6GS!-GeCR;(Wh|L@w;dUpV9ts%7ZQbCvzgrnTOw2?ET-0mEaLlp+0W+@ z<2b%Aj^-rf$^_OTHizsklxLB4K(5-2WOSSnX?x#~e^X|V$hvm?s6LI<@VkY#pEQVB zdOjxks*zKt!|+72JbBV9K((<_#PP>RdZX(vbc_1Y8i&uYSuWpbxo$UjRc3Hg;%-3d z&XG`q{G7#kA!t-qfcd1oaCqNAh~j&s7uO|1!KxZC`MD016*>pzVpZo0ea?Td1x=~x%tWhzIUo=!q( zH#zd*jT>IF8cS?xET2b{A&0XI@W=uwlIVF3>v|>(%`?Zmb~LS5gu=|WsCCn z!rCxL_RT&Vq*InKqc=Wq!qb(lIJFFVj(RZBJvQ(tYZa5TGK2+3yx9)B@vz>;o6pL~ z!ng_#c5Tf+Zhx~It10Z|BCalDiDz$f2?5S*$Ne(y*A-jVxIcwEZ8eWA+T+8Sk0q=- zTAow?q{B4dGzkvNO<*bd4gx+@&Fn~o@qZsg*<~>^qtJ%;xP`xD?8{p5Lis`A-s2R5 zr&bD64rgIh-3WRDLeRfz6b(xhpjpX0YWib&j>oib^#b_4zn`W*j05Mzve?pc3@i($VJLSM(tgjyAlXj1*XWF?vESj8 zg&#ipGJoe@ z%R~8@90|BwjDc(>38^SXW$!tpRkRepSeuc8gc20hoJ%Z59mlCM=H!#par6+kAp5qT zM2qIRB+UFcKH}z*F+L|SmCxSny;_22bY>E1dXzt3a3uKXVf1<|AbZ;mp>n4INlMGd zndN%KYEmw?{N~vPGt+VIFJ0nXoPzoYs z|J5M*xAn18m(STPR>qUx6v>;#eRRRbalDu9BK>J0NoLp-Qv0|;*zhr&R`49!<0}kl zN@)|!DIXMWO*#vwe58e6MrFd$Wzqt}8$odD=2k&vkRJ5YT!EQ#7uWD0RS+0x$rUd< zBEN`#-H~H+QNAs&Z%s{W9R)? zuqjpW#pWn>n#BozQHJjh9T1SCH?YF|sUT|1GxV6P#3eWN;}DVI^3%oH$jLLfZo_d* zM$?mJrhS=A>4d3n-J^<_k@Okp&^LsVr#zVL16A zjj4P)3#>GQt;ni|u+}Ulf9x{I+{s~AJzF5dIgfd&w!ul+JXX(h>_rswm}6821tx%wnw`!M4me)~oU~Y%H{|#(357* ztvx{N;!g}1KOe&VIGMwKw`byX-fjz1-cn<~IR zTTWLwr2nE%8z<9uR?*abLJ~FDdZ%KC&tG=dCK?f z>wNL(03%vsR%20BHM#X|1uh$Nft)FDLG!8$WM;||jJ|MzSgmzJJG~1;!DKPE>(r1b zA6(E(>pb5Ub3ujojGQoY<@17+7|iy-zlD`VTf_rj^6rc`1D@F1aFXl@^~V=~OUbFx z8*q2YVe%($9X`n{BnNy0@%HB&649{+_r5tmRv%o2YuBd`w}vIC`ZR{j>9j#HpGfjA za1P$nUFx;YmFo{Mh^ z6dcsJw_>__GFq3L84K1eBz;*me_7_}s70k`}Ciuo_dQ zv%n9kJ1p79P5yB3FTZ;X4ut0pi`l%jLD2kb1)qIc1yh_o8Md#4ytRJp>r6Xvie1m% zI?Ms%!(r@gssU7WMzBjyG@(ClFI!Zn2tfyUCTqSdtbL!z26v1AW7+*|<(uDJl0DBm znEsS2Xv=02CY%m4JO)X?E&l^L+uUvjN3n02NizQ#QfNtvp zY@(Ds?C?%uCHeNy+QDa%{y2b5_%5bNoMASEvc&u);CjcG6&-Pc%#`I!EZPQ&AKS1g z)h4i@6xg^<4oaCOGm7Bn2Z>`?-ez?u!a=;zCJpnvAK=Yr-?`!mLevSn%`F*!08@f< zxS8pz@T0c_XMINvtN-g4d|F*f)3)XaszaiMTYmOb?T|I(%JcsTw_LB`HjnnB@2`!9 zwY&0ZoaAiK<1W&3qk>?&po3b?O@GgwLK$<*7#Oxlsl4iC=t{@%7v+~3k6!; zDe(4nmO#!c8svVa2x@`?!6Gq3u%p2lG&i3R94jUerk^BGf36OZcj}EB;zXfPa$@E8 z$!EDoo8DE0`1x=zR|gBFXWtWSDijKpx+e%%JiI4#7%-&^?96B=KX3o|!k^xwD6;FmbMf&f6?W6W z0o7#H*g&j1?tzKSOECcdeVW8>$%muh$Yf?$uotZrd00Vm0$R0buiq~EgUaxReFFwbp2e5vgm`rCalE?x2v)}&LyNX_{Lov33j?C?hfg6k z`+1<`y=<)XFvXEW8K`WahQ+&5QMA98);~?cWv0idv|ltf>~*G+9y>8{`3YgG@p+-jE!R(waRox~@-l%H}rFJNg*kf^m!H<(j)?)!T z+g6WkdRxdPJvJetjU8N<@jUYB&Z41CWAkoh~W!iw}jq8E4@ZYc(meGeYPa9IH1Uc82Q z&p`6_`v6$J@h9zJf1ydqpY*>PLB5|`Lx#mh@m@q9^6sh(`8R$QxypC4?tXV8`hMd` zu+ws~G*5w~O>ri3wkVT8Z$~nQ&rbF#*%65WWfJqnntb`GLg4sZV)sLp9R6lP)Krwo z;3Wf6I;=?I!nH`%1vz5H)W{p1u|!^lKZ^y+kg2Ake_5^ZOyU@jdj)dVr$eW7vOB2|g#ZLi3%|ocxO`FqLHpT5TCPSk9uS^$+v! zSr6zJmn>L2elli@#DZCZJDz_K3c;I`QQF%9R$V=b-^T;EYhFj6Rt*U0??$z!d_Vl- z5Srfk$~`cVVq#k!a}l0uZ0Xv|oSL^bbNPIl`*~TwGHxBs7}hD!>W^*mWr@hoEc!>T+3{xExH zu8qyLM_Fj086Gz*W%tyUqMt}9<7XTayJ?q zSAUwYrc1n6xNsV~H+2BT8r9hHb-%HrcQiZEA34Z#H1q7Vs%n-W$xa_!#?6ut zW3~D3xqD}ZuzssH9DCJ=k3@ap+WKy!&FPSpd>1qFD?n%UWqfk31y+~|vC#KDIJF-^ ziF;yXqH{Vz-#8LFBMJ@bCXqUEKeUxIR!x?Z24O@-lB7G@s}-GTUP@s zeJzNPtA*hL6Ef<}C3vfer3UH$&cn^4 zH@G9=m9Sb&pA*|(0uSd%3mb~_KtU^o>Xq&T(}Yjd=*f0a^fko2i7R2IaR5HZn*-5r zl5lIc3W$XAJBt@zxyA1*a8R#;>ke(eO2bW@N>&G!mAn#+{qzpqWs;1S7Y*ak#niY(lLZ-{r|UlHvYRD0=;c`)doSKg$s98#|7VEa z3$$S`zlvf14STjLUJ{cxFJTjJE8}qN3U*rsUHg+x3iUQo5 z<KG`C} zE??V>HrgW0NzEV6roG4apBH27fA=v>)f`pmMU3~5o%%zQq|c&|o}@*%rB^_H(=?(U zeG_sf>5yLSHrPLNI$0^hd!CB4N$uCykT#@APHObQK=>r0(DeiU#HteeoxdS> zA0#HH!I!J=VT|t<(BAk8vj4M#ww9;xp+Fsq%kIKf>zAB&Z3C2iisst1FF@_1bppY! zvygZ7ov`>?A-sQBKuZ>k)I;Pk*VT=Va{uyNZD3=hkr^>z~M!mU2q+B%j^mYjqVL+b3z zodsxYq|KJegyI1k1GfA{GFBZjWy@Y2!tycJY{Sed>?n3*2dl1Pr}PRI{;nNQ?eb!2 z!Z)a%;m>Rb2XW1@jqKmBINMUSjeQfyvPo6D*x6bIwm2_}nTn~iX`f@*vhNzK|79GL ztC-5pg~YSnI=akfD4r=h=`-Wk@honE5$l6E=08=yCN;-0X&;W|4n?zX^9a*C7{xxl zB5cTPC+qPyVV6w8*BP|6m|61~^A-`F zeR9@>8As@`34AUx`0zAV9WkDHH%?*4cF3?oO$|2T$6wUjrOuY}`TEYMO3d|m6P~^> zmaXV5!+lB8Y}nRuNAbs;RAMU%@vNWe}=iqy4+v9 zkE1=>xJaJ{d||2&tzC#|PFrEn;~0L^I}9=2*{D5|?{V?>>vEB9n6}FYSMB@ubl_dVaNN#1nKQZ2$ z$gRJ%iP#KXIQFGlT4mO$V228DyMwCWKw)zppD3 zq_<^|Gm_aLC(e5e4RRszMFyF)BL{XxW{`xP+0dz*wEq%G>V|B%-xN(T%0|V{EFHKy_vdX4WBj3Tr`mc6{f=O6Jtq(?tT!uiV^LtX%N2X9sC@f4yUSa zfe1~9xGR-l^B@bfjI-dyl7l=-Jrsg03*mH|87yinf?Nd=7@v0(j6SDw#y3wv`F9b) zOVui9^t7TOR_8%=O&5KWS`Sg}Mu;=6f)F=iXJ|95znh1S=WfBS2Hxf1a~DKoI?+1h zAuN{}LWPRQ5O+hGeaq+ov!?MZ+2S!w@ziIDB2S^qe-8UO?iq;I*|8^j&%nRVmE9yy zL8IS~Z9nxC=DUTl=66rwecm2sx3e48+4GFi``sM3L{+)F>p==ldIPzeg(<$FoP%rO>~7FKeBl zkJ-UnS$@TQ93Q`q#Wnb1&R-Aa=(+=4&765wK>~(+vSfc&9l)s*fbFTt#Xn=Fv8Hv! zIA(_ms|Y%YlMjt%`mf4S)M^MVRL)^Y<_pa0s==N=8kOO z1vpD_LS8d=tQ~`=+V9|q4~4X^rxlOao)hZaxr?GN1zfywD{e1%zztd5#W$QbEaCIK z%D23reC!<@h)9M54J~Lh|0vM;%~&z99xKp6!pRvv|I{bCnQV7A#s@s(vhn<644Jr@C=|=$8ijDOBj!8(xh9mz-@i{^ z$8R8|FKQ@NUPq`w7LEM0nlxwZq&iDH$qBZcW}jR}x`s_@;2B3^aYLILF18^W-<0U% zM{~%%k-vo#rvUNcSH`I^dc^rshOq7G6msF0ve1~HD~&1}VVrPDp0qvF5tw;Pk$}5# zf{7v`#IB-8(EOnfHdAL2|to}X|G~bBfQa|4la8E4-zW4VEx`U*sq2?q(?7Y*| zar<3kx%cAOHDZ#{K84m_z8yH<}ywM7*d zyC2|?vaM0F?HhbDR>XK?{SachmvLL31XGPFGP<;QESo+~*?9jhCFcD5T%}y!c-H9G zQ{_KqGK(pgE0let%}&_F3tfwJ*x=o>!o^}U*vg`-!bM*V79W6b7#XQf(+ADjw9d(NY5P2OK_H+f!!6mp z$8+fuBTHtGZAVT1nX^N6i>OMt8T;;LPE)*1nbWNKG-erLyGGBW^|^*D{xYH0Z%k(! zm*~;c`zNvLwOVw=Ohwi|@1s!5b2J-YSuONC_6JW)T_~Km^%dqd1yyxTXvR>}M@AZ5 zWvEp6-q>K`0hAf663FiN#d39Z?ox^lYNz;eeg!Y7v~o0OKWhcev#jDOUw<=Ji@nFC zC!})L+F!Z7tA29(JV%0uGl3(qD&RUP48oeHLQ_))gtP)|n0E$bt1Mw#UnBJFbOPf| z9k6i8D%flP6>Lm`!41TT|J-fh*fWN-=k4WZr7EO!b}X#m`(wVBlfi719&uDig=3op zWW)Y6*wHxrvQ6v|re+Vg8%z?KW{C#sF8(v0kA(?z0>4@WY@~u4$c5aI#skc+$3(tOA z^eqYWKkX!^_a#E;)tzMUY8*&kjU!91N9U-+N!tiIdSVSn7534&qepN9-;UB8wqF=KvWl7>$V7=7dVE6lSJ@`RSky3{-xr1w^4nXG%h*x z0z0>lLybG%aa5T+7Uz#(MZ;sTF>DNTZ&${aU^Nzdgy$Y*O=W2!^4QDgV6NZcv&j8s zEYWf-epRq#e;Y?(_1h(E{;q%Y&7oDS&Fup%p1h8&G<`@<-`vEGc3h&Nfjilg{|?c^ zeCNJsD2AR@h-XtZoawwPN$hIfIJ&)ZAKM&zPWYdG8atj)SoQVi0TxnkDwvj=!JeG| zF4(D_$qZABx!l1FHn={NTfaJkeQPY{49=&sTX)ZMZVd;R&FMRw!kIL7u&l`~2!*WWSxd{Eey#KU;6R1Y8hJiC&utX@E za5tCRy(oY^T^z?XRe7?m7apAI4!g6nIEZ zV6!{L1U-E+>_3~~s_wQwcqKPl$O=0#J&g+cSJ&b6rGJIN()sAwXGniYZ^SNhAL`sa z9mCG1(D*mkXeT>PcSJuHMqau}HJuf>@h^Mn``|9_-$rr#@8}Gec~2GZKKJM8jE4BI zIRiG9*x-ZG3aGr{j_1DIfG7Jy@!a^AFlj;zR<`{D*$w%|Q*KX2sNTU> z^IeE|!acN0aV66q-bM2fo<#NGeN@QvAx@q5&_Ugw;P7qyxHyPty||4Yg~8-dF#r6G z-AKMT-o()NVPwLwW?b_*jF{ZJhVMPX$$axG_#|Kx>6luF_LoCRf$DiodmO?$;m)Gp zP%!zq=@>3OA4C+#7UG$^fn@KpOf+m;OFovxqh6UW*}q{6&Y!S~oU2@gE1tTMn_cr! zgSrrPe!u@L*pc_CDx*Y$E&1p7hpr#CBuA^8=WXW~DsnOERu?Z~`2S z=odJym;{;qw}m=3n$U8+n11x13c9~X;3Xvkh#zl?CBCHv7-asdpB z9Y+&mXLz7okFwf}L1D{19QoM|8qdDsJ4U|Xmp_0mr`AK=4l#DxV-sY1NHdMs+rZFQ zfo)l|9on?{-e%V>km;YomagNy>g##-sdqHIU1iMttM`J*2~(zfcrV19GG`eJqF|4y zEfekA1$i+JtTi(dHY7UpUC1q9HpPV*VmQ3eS%FC6k`R*c^U+vDCH_wMdCGJe*wi#Uc<;L{G&0zL#SC&0!3d7TRMnH@S=twPP z|6}O9!@26iFix2vqL8d2h2nR<&nYTYWLHMCkdl&;QjxUC&T1G@5rxunzR!_8LPSMN zMe}VJm3E?f&maEa;xf+V_pJN=+;2MwyqfF6&%DXP*Dfbs)ounPYTNT3#AnH~Q)ML$&T3RAvIkY!^HiE1^!tkuYoQOv?2|!>a7r+*`{y zaJ+n(Nw!Lapi}FJ`t*3vu5Kkue#gVNCvxyHFah)=%s~a>VfNd#@K}@p9qW=|*AwC6 z+4(R-ITjZ8R6vJ%B*-Ur!baa6@LB9F$czdB8G#KG@@Or%37)Oc(&ccaO`X;MG#@M^ z^jY&lGvKYKu*oaNgN5XDR!dGE2CXdEBZGaUJJE)@ixwBpS9H>OP8@uD_2|8`N8*4rBHZ4wCDCpRv zF=1!{+vIGFy3Wq*gbVX=fZDTGW4B=4R2z0nPa@hrwPMTcvM{Q77E98LaDkK=`_x;| zI=>{WL2d&E7))g+)9d(P++;TATsO9V6Bwxv|HBDwngZ+nJ&v8A&UR#d#IaYE*~s`W zc;<@&TQ%W3x>ISkA#eaYgv^q^9|uu0=Nk;h{6*^JyeNPu^Z$HAAus$*?P2lD~ zN+m8!T2V~4gE?$lixsswTv$BCtUvqc`I$v{b?;M}aU}-}R%&BmKq|VbEyAsJf)8?2 z6dr#SjKn$z<&G`EEj}D}F0#RMms{}XQ&SXQ(Ss+W1RaCXM>O#riQfvucuf9BoBU+> zKO^tcqRWZ`|E7!{5mV<2uNZ>0wrn`F&5-bo|xPTBGjewRpqiW7gS=P@~MwvhkxRT89@ zy76r`8sMd{h);NI3@+0a^M09@kW##q-*v(h#O0RqCs(e8s^ldCV{seoyXMJzs7HZe z;39s;ge2JZ%!O}@I{+;^ocTqWnQ(5eEkEhXQP>?ln^(0z0l$)G@|TTIf?N>cA3-q; ziVXPyuM(KDbv$ntdJ%%&sPQr#99T+?4v>8Xn-^^9Unf zHRJDd6nZMoVe$BjQ0ShCbzjeb?7RqMI|`uSgCn}Zark031{KF=!24~t>CHV!pfr6G z9e+bu1jl4@>*xk}eET7zZ?^!FZIj6dNe1%$K9N_IW8l8p;GcsD}7Bol+aEo6zj|mV4{_9GICd^t-T+bl#at9VSb# zquY79c!nv zcIunZAk~8Pzqk)~&9G)e-X-Fqc6&B|+aZjQbYYv_kD~D`5BB=Hd>rgw%Bmhejia@F z1zy})%zNO+-g+j?tFmiZ(<_KW-hr%Sd^wKR+Q9y@sKkcD8(8J()p&H<2G$|82B(y- zV-q!N(Ib5=8*;iDLj-n$!Tbt5yU&-sFs}^zw|lb-ia5ll9_;&D z*~(ElC}TE{J;25MA9G}LH`W1r)fm2ztpWZ37Mwg*Pb)S? zK*;i3>YU~b^3{IST0$9o=c&+D?<&coBqz@0=>(#2v0Rkd8pzGK-N#(@PNCmVyOS%6 zKhf_Ga!HFA!L7<2zVw#vjre_(}rKvd>X_S zIrD9O7vQ0z2Vd1sVMum4A1+Z2acg|}eyvK_e9@mDSXB!%?E?8}H|n9{MG$Wv)c^~} zZ{|hQo1kR*7QRTX1$=_H@ooLBphCj<=A`SeUI174`gTC#f7^LQ@msLYAe0X(xCNne zw(wmOZb6>=W?r`W7F7Qy@aBSVLgxGcK4?ZK>^SPj2dujRlc_haFVPO!y`KEv(iYgf z*@a(!rV;k*I`F-x8{oecbNF4E6=3(koChI7Zfgv~U;4qpqo;=avJn>rj=nDc%i=U- z8II-Cwikd`)F_??<-m$S8UC(DCUoTeL4KC7&l}x~#(xvwY};*gOb~LSN~(nxJOWmi zp2Bjc3ZX6m_;$0SFo!YtRe1&|G<~68W*S23hCNi_wFdYs_*0tgDFX-J zSQ78YABYlrlURPeL!PN=LSt(@%YGGIbQYtWK52&(mP{TG`UG z`V&~G9U;_yxDopxJ%{S=6tP1st+cw?j4jyymYzl{mj5h?-m~r4>EWuV6FQ%*`e}@z z0_S0Ahz*|ZSLbhok z4xJBXSDoSTm(ympaBUsRTZIVxq;}jb5yCdlxQj1eZ)QvVpW^(mVAkgMTdbMBfxV~n z4QHMe?xiaR1#N~O>-$Tb|Fy@5U3y)Dm-AoDcK?$R_T(-s9+&5%XV|gEJC*qDPL`~N zsWP9Z1FWjpX#S|N0UK~?3@@_RVDpGN|9qSRJMdABpRFRs23n2f?J8fw-63^edrLcv zTBOd$FFp?!o{Z)*0uRBicgpsE>+z?l5HS{w8_zS+C|Zi~soZW9${k z^tT)MVc)lrt8H8O<;PBwKL2q3y?z(z7`cbfjT48zha&mgp5q|vZxsL6Q3R+R&3kLx zf_C0Mez?VQnA{)5uYIu2Tb_OgQ9>TYD=Ym{KAb-=V zNMNR|;_G|QLH(HJ{0A!vGsRu`0L4nU_S%+DJz5Vsc9wj~!zQ@#p73#j!hN^Mi1%A? z4fK?C`M^z`a4A-mKh$sw(gc>J*T>uN*Jc>+d*&|en)?amesqEH@@_nR{T}>NZo)-h zy9AxfIdoC(f^^8l%H%uHRu(C&P42*`-!8a##BGT9ql?zJgr4&IeR{U>8oVD0q%UJz zp=H66(hXypp=@Y2sdl>z-zx>ig>Wx+emxdEUX+9GZFd-BLm|l{7DD6BL)e!*SUdeR zSZ}I<^p<=$5cmL+7w5p$d!L~%JsmXrB-o!LlR5GvF}t@ zK+_(EwfHIA-FMGqpKLaPH;=8^6~9y<)<)O^8H>RUYZn%VH4~jw5B9*ZG-5Gr8LO5w zgM@|ou;O#hG2NF|u^AoGr7fq|uwfpB+|v1hf*xIoj(@P8HM+Ej_Cy4+jTN!*2oN4(wEAV|;5r zm$kbv4P&2}vr8XY;!k~{&hMFrjGh4-6ySoj)#KO&iJrJr$nN@+<%8!=OR$T(e9?X9 zXQ1m>q1=$*@4T=ISEgTvx%I0A7DzD|r>w$P1A>1|W+k2~@rCN&OR)L)RG4wo9Ya*! zk+T-_(fxcVIbvgnmAmRiZ%wW6belcxx*>3_r0>%0hfVSLXCuV1hPXv_E%u(!K{>;N zxO~DGthjgque}v)arLVsU(av0yTSPWJ6EAomH`l;$1O}^y9Bl`2g zWZrznbvil?_+*_+bjJfr{(5ybRsQb4$9wOitG2oG5x?hCzoX0fut~D?iQg*zMA-&z zfolNYJ}pXA>k-5oT}!!S%`sgPTg2}{2$jF!D z<@Ten?+x&mZybdiC5F7b?GZSbq0KiLWP!qIW!|m!FlaB6;_q1=f~rm5(d%t0MCm+4 zo7YL;VtW~1VgeL83EqZ_v0z=Fgz7J&z*NHrrR+l?fS- zbcI=Mo~4Q|Hejr~h}<(Ikh-Ux=p4|6sk_u+t)4tMHQ7U3@mF%LX*>KrdX>y#4}yJQ z4!Lxt2;9J%IP2Gfyq7Eq+H(g|N82)%;;&(+f(j??^$QNFOVi&)l5C!p2ki?|WLN7S zpdIaMY)M@uHLcfXzsfwK@9OpZ7n1}J^bGd7mKm-EOSYA< zLD84F>=k8CtWL3Ii=6!MWrPDeJvtaS4LGuWTDveh(3!o^9E0ZS^I7$n{kTkSK3hH_ z4W-@YvpfG~V8d!>f#;fo_A1V-reYqpPH|$l?mvn983(r7{4}0uuwy%%OK|fM8+Lo) zS-dVem)*Dg0_OKvvPY#Z;39$3>KSnXlYas0karQ~Bu&|=qVpJ)W5|}?FG1%LJ=W0t z49XHM_Nsg_7X28*t`{r7=J87G)J3`YphAXaI&&~d&=hP_J%ab{e1tP6(s8f-Q!u}A z2;YWxLTy_bPBU+SUWa7VFunkiMoGBFU0@RACSXQx5=7BhjC0urm!HMp^9*+w7>q=$ zG==u|o!ILt2kB3?;-}cN)ksMw8c@i1pkFupjGp7^bIz_l@)PlqB9;34IalH;knEoS%yh}q)>Y5 zRowUX4Sl!zF`hEMLRCI~!Q!+cS|vT454{sbC;yP+zeP-@>49VT))58Vs>53RxtO1( zSU6G0#wleMs!rvVD@;jECGbc7#gnUHGkDOcB&R>k=4YIFPh7ig_;v$%xV+k)j|tU< zh<%Pc`Hw)JqBB27@X7zT(wX;;^Mr>6PCQo~097&${KsY6pfJRi-}`MZs3=c^ zyTeMjGp54(xik5iyXj!=I*s?;coat7Fy)*7oq%l`%RWlv#JCAA))S#Y!r6r1K1yT1%4jd;aPcN!cxx!=Mc>zFhNzEuWAjRoXYF9rP{ zgTzVgJRGy13O5pq!2G8Vv=-;V1e1O6>1;OC6=Z;2op7(u5_;&)L{Obn4R^;y!EMWS zsF2wRQ5$-|?$2_l9rg|^oE*UO(hp#6G2r;+9~^tH0rB^x*hh&{u;aQMo9Xq26k8~< zP07_{&hOFeZ}UUMx^FDo6Ssn7Qf)SBoF4gFK7kGOJ;#(cO=Mjk)L-m~pUh5_D&$VC zG-j`z9Yam@Oj);0i|N5Wh7Earh>mh+S^YR+&#-TrkW>DE4)ZZ%|K^F|+qGt_(=Qba z`!}5p>6(bW@@DMa6J|J~U^*KuYloJmEIU$W3BLOwVr5qNW5+5JcGZL}xB`sW9WlGH zt3jXrZX1hJ8ns!Ut4XN!L!F&9^$?1Tlvv%Y473!qviU~YSa|dws8=7y{3(L=$0{Gk zw>*F^i%#N?gcgt=U5G~39Q0@wVQ%d)NDnSTm7Q@g`qfF4)bNM3B`5J**G#B1&BsGx z@~|!`7q2X_(j#iI{qW3u40>8x9e-hFE@XNsWpa$13bDM#?dGI#tDc?O$|98jvZ26wF!G+Ip^ zXtR~Y9}Z8kZ23e~O#g(T&oq!95aT~es$g7{4F6DR1a2Im#Jf-WL-i`u_`6B(X?mCr z&pY3v&OQcwqU{xW*l{X<-nEkY2NParL)AuU^A%fDz*q{UHod{)9IPBFxe|CZ3qMc3N$$R6SvR?p*a%bIgq z-{jG_am=0jQ~9$~1^w-?$-K_a zkBm>t1b%p$}A-`xT8Ffd2kG0!J%sV9cIJZMYTIx66R6apkuD?Z1 zgGzF!x(n;mZ<7=An~>Y`h6I?D;)>_LNT|Sex4a_>+C8!8Ocg+K@+!PBax|P8$)IK3 zSoru;0&7l9fN^k&hU-p&g{CU>x-kLqoqmkN)@g8WL?{{9JQIFi?;(qb6=*Hd1+Oe? zFy7$?lA5+4=N<`p#2#K|WI%1NJtTyjfzE9XFsZc$N>|K-`|3C0m(g4>OnL^2gBB1T z(hp}#&0*W%AJ~3_z}hnsY+A`wsQ5X8l^kOr4~=JI^A3xy6CHNNG7au;o+f*F3+2pmG+2D3L6;6wXA3vE zQOStWtm37;)bPC`Tf6fx)lZgVZLCkzGY--$YtTd`9fq-0-)_(gCkDV)?=iizp%41x zKG4dmPhqLzFuYlQ3tqD__^GTBUayqJ10g(g`pDtON5#5$F~QViJwRE-4R-3-ctqM zrpJmT70B^JdwmESA{uT|51yC;!(DVJmtq7p%_iK!DU$_OUn+BbwINvc0@3FU zAVVUPe8@0>#F=-ANM;h`n-2r&)XCsFPX}yYO#$UWOVGY!0*QB)!Ku9_(3KVjiV`BQ zOih5=n<9v}O^3VIrZ6rgA7++Kg>Qe(!TI*75E@hghQ7uyrnmtKyuvSu3{vDRj;7Pvo zAS`;AMZSLh2kxJDlc=O&Y|wxs(c2@*y19=eMt)jHBt zI^x0?$iGxdLmS?~=|jzQ@rkF!kG&1W2S3uc?k#Yn;UD#Et%jR%(zwX46sTwv zF27s=!>_5~mC2dV;;Vzb0ypD{-6TA_DjbwIn_}|`FHlP|!>uuMVg9Rm7;?}MrW&}Q zLV!HT&RU92y&s6Y<7(8At0zOs8}ZS@cv7kuj;qQ=Bq47v8vM*-R$9kmDK0QEdzFCM z%?;eM$Yh+nZ8}{LpNj7)V(78E2eDM<0v$Fc6JJb!K)cN|v1Xe%mJdIIAJbIPH7Xke zHcmm@enen{TME13OdK)K1KpP%#&oqntg1;v`zKL&k4?eT@~Jp?TOxL*=HS`tXzUIw z!v3xZeC$|?PabZ@D2E!X7V_@PhhN3sPItU{{T7axX^YjZkI?X+IbL&ojTtu$@tD;o z{9~t$V}Acc-;D|wJMu3MzconDzZK^%$2_O&t)%#lmL_`cKN((C@EFB!mFHVSBWZG^ z0-r7IN%OQ7`9aSy^oVdDIi^*?t?Nf-c?rv-{d`;wLb>ddtej+u#89yxiMgFRm;~iab=-PV@OAIApm--1D7#soO zb%*d=?MOHj6pNKl1z)J|CX63YgRUKmvAkXvtc%SM^bH}>U@V^1GXcKtH#L1U4Zgf+ zq_%W6^sh;yzk?lsDKMZ59=Jm4YHw~yuo~yF}e2FA7&IK5(^pxHxw(# z;ErvOxW1p9vx@-PQf0WceK%B}5%@`$_kef)Y{+lj0}J98fqCsNK`Xr$qDuEb#lfBM zXY3xpTd|NfAskwqQbF$F7TEGT1FGf(!Me9cVB-9BAon2;Dz#U^#{H*2)!iE`ThBn9 zwg=4BKL?ZdF9cV;QaJa;5nNg*gjLUhf-hz8B77Q5YPrlYG9K@2}oiCvM<4+HeUmCcYdOdJ!Q`GCeoDWt&*;K>&m{J7K{CbY_- zuJF4qd9Hw)ZN`9uwhC@MHXPpk9F6^HZ-}{}8t&WQM)I^Y1s+ZzF*VV_%WLAvff@R! zYUDJnV?Lj1oMJUMeDetQvYctxaLSIw=C2Yna=xM$thD@ zqoGW9icAn^+0YU&!DUkd1ka`kX3dSIKjlqv+^~a`T`>it1`Daf2xH8gQBC&+7-4bt zHENh?j31tK)6)(UalYLfdTB@pO;mr;FY;q?x{Ej}g$wmPbp-B{mBVopmCz_c95+^t z!SkNqXsU!Ja;N{J=_kkIGPaW*wlYNZ>I!=7l_{F4oS>mS1b3W`q)*q*z?J{gdQ`!QGvl`8+qAS}(&*4_}P&)v2PRG2ZCae}GXp^}{#ylH|v7e|*!H z#VOhA$eZE-JYx_?PH3({^@<$w&dVPcJ5VCMZY6HYttP55UT7!LO6L1|;4QZ<@}|le z^-c=Bx2SnoR{oC2?XW~&_6MnSGQ$-og?`jWgpTfi$hmw&6ulRR3^fDX|3eZMpa z2U%GER}C*njfC{!D!5fs8Mcg4#Kdc3;Jn~HSs$+oGISV9Z&U-n&foM|jT+QV`bpo{ zsR8kNLw_WzKunyFf99_U?JW=K*J-jaV}ig1b^lAAPHCqfF87gXFPrE#g@S5ieqOwc=oh9@aa&X38yideI%UYav4J$c z^%fKM(VkwbI>anGr%u1tI5EM>Z@H$c3QYf=gPhOYy`t}y@|>;qAyMeEjiN#EbEfKV zeVIpd4~m+St}{%9nP}eeA;wrrLsZ+OL8QdgM3L%K$hr^DOeYMOlQK_BlOT_!WMbX3 zi^eB66Z7{AOZSMjlg}QTN`GtYA?k^m+|9%oA<^2I>##aZ>S9lEC0a*`R>^;yqR~k* zbGRy4SZ^fkTzP^7#4mJ^|z_g=uDfL}|Sk!bEFgo%n@z`D+pDxxKVC{0TEI{t1nfOl1zd z>7YrX%c3z|&Ggum1En*g%Bb(D9L{U|DLS-CnqD!dw4DH#yk&n`Gq(wuxV^TZe59mxgB zC1~5^Np5O;;hObpiG7q0#w^}Q+$XO@uaRqrzi1VXjP@s*fvYg`(sHs$Yc*cD;7R&# zt;CPFoX9Zr!kCpdWRvMK^s}B#7S8d&6@exs_~}9nmo*~IVs#gg%4$`=!S@5qoNM+|Yn6?1aq?F5wjGJ_aT(ZD!+N0QN}h_AN$5r@4p zsG{so8bXJmYGN2UD%nqMZ1$03pC8ieim}9O&UI=M7f-f0@B+6qi5xqVO;?Afk?+2H zsX@$Pvhv$G@Ie{%dkB1d)ql~0pybcLlaK!Tt4a9nSJr&!vfNv zcTIHlc>z&cp3029UQCGd6{dV;AxR9^Ad3eINqwaq(J(6_5^Hyp5+;w7muC>0KRM*_ z6`s_nW|NiMJIRE)EHZXSKUvn0NtCWh!u9h9h@9y-c(^i|d@M4Cjm8P2Rm%dFpN%4P zkD#Mo7ecs~e&DRKo(N$E@b<7b88ti#PRKfwg~udI|3DIV_;Rs$g+S0%M<8 z3(p*4m`!);g}S<%2`y-bTTB#lX7p8fZMBxsj=KhZO)<>A{WswD>NLjh=uJ2{w}>(Q za2q;D9b!D1?!qVEglJW8tGN~#mnV}bVp1($krHV2S z=uN@XaDiD=+X*ut6fnJ2*T6mLDD&K@4KhD@F`G7A0n=YQm~`KI$dFpkY?T(W$|GzT z#};1De*6$Md_NC2FDNiSYl=Ygv zKb%7!2hT#2i>K&X`{gLtc#aNwhoR^RPupiDVs7{)s&z6Qy>-j!?67=HnN>yC`JTsz zcdKd3k#dw2?6=#*8}U;WM@^#YJ?})pr=N zEtg6+^x><}V^n8aKZY5k)58g0G2rZeI-vVQm=kx=$J|f+u`HOXqz&L$xn&3FdeOy4~Yy9GKkh32B4CUq>;qtZa<3MLI7ksl5t5)T6L7}adaw6A?kAQCNa$L@;KKC-ym!8UC!>!HwfM! zPltv5faa+a>AK}VVf3!K^u^;}@M*a-H9h$YO3r)JsqcP5cFit2_tH44QQmZWNw0@ z<`p`6ek=UgeU+ZPRs-A0TZOMHgPMS=RHf!D>>hrdnmx;h!p0j^`hFJZsJ2r}MZxd6 z=_);|5e-N5TIuJd+n{aAWtvP^LfE(_I`DfTOjvT6{@FDH)?cclnwRw8yJjuD&?5(D z$|`A|u#?F&y+otz8pzibWmI$jK~n$v0(E>ogM8e6mX48WVD5R8(4hl^CX=3=rlP7= z&R5uNg*{q8Ek>T8nR5=(^DFZyVQT1d*&KSOtCv>99H#wZ^7wjB3XRd!#g?J{G~a>6 zQzLiNb-X=>Zt|kS8|KevDJQ)Vk7tgdY971L?9U^veQzAZrSsn_7Zaaok37-Ji#1 zCXrajmgAFe*`#q}B_4TSL{5iP;jK9wdAYv=lex=;tf@qra*MoEuEcZok4Vbxa=e_^ zNA_@+@JYEiSUZ&Aj@xpeuz_MLKN@a*zliJlbYNfASv01`u)w|;?+a8P9kY|DAwLgR zMC4&kuM22vAHldRFVM|Dh`0OJK)84ko|fDME+huGJ`aP|SbD;=nOwk^ic{{l(iB6PhUxw%nS0R zq=%gE_)Egwn~25;1!yuoM;=WP*u}e3$xAh1mwhvYG@LdUv|rZb$6IU2KCeLz+bo1! z_Z}uu)(ZmmMKNo5e~8JrD>By&hLL^+Q~uS32|KxI+|jPRaJn#so3l3t3}ZXE+G`2m zv|UW#oa~zcQtQUxxNqrDK72e%EISBH z%w#N7NCuD-q22LB_$o5P>#t&9?qw@Hn!6i}e%fHB#b)@~Wrym6f(HHTeEc-g1r#1H z#NIe7aO`r!efOt8?DfT{_gfwOTD@`eFDam!zBpO(EfEj($NBb+ZeVULouRP9<3H_M#aGK==>-ce-AUmCC2Mfv~VH54_|{x z2mSHhEFaAB6S%TLo*2129(AufBVTm@m#wkE(04gF;y*J?XHMbxHWPfl;2h2aJzO|I zaf!=V3{0y;*J&fM|5q*Mic4VR`3CI&`GsoNG^6;Y_jH}g6^u~sqT?^M2>i<{)Wf<3 z4?7~wifqA`|4z~#;qxp{9;8OQFJre-lu*YT@L#GQtuL>|abN6d?4v4dS~8Kk535A! zqeEO@P#LZZ;kh4YIrKg1$)#1D$H@+T7vx5q!Q9tojN+e@xbem{#`Sm}+8!Q3{9g<8 z@%miyV@C$6u@S`oN*Xo__rtNB`_Z)YJaH0>!9(Jg$y9>~6zjf2Qhe8A)v1@{di!#W zmHk07#GSBD`2S}f%*1gsr9riFGXAI+Zf<{7kP&uHuXYd7xAJ3P>99`vWd2wvxtvc2 zs>XuM(oJ+mxh9OiD^K;NYYUooRnD9l4=IQaKCug8TxQ5G^j6oX}wB)E*_pfCFmiAk@7iIaa4>-`PF{q-Z+^`ZrCslFx) zXWfAE&PU|=kJ}*s=pIRZe-G|?-ykd89)eF|8+rFY;5qBI5)-%Q@T0bwI1W4q=Oy*z z*X9?HGOnIP4!(qJjas4;_X_rkm61Y^SJ3vWl#FtG4cgA7Z|JA^q4b#bj@G|(TWJDZ_FTmD02E=bzG58Q&680k(_CD4lEzdI`zJ3Dv zQJV}ab0&}o>lnC|twKcm!{PiqHBv9U7Tax*B6@c`!9D0b^Tc5uw0?WQjM%`yR=$Zj zAQ*bTZamK{(UE~=G6$LOjqk~sqIHa|Mgy61M2G44nMtT&8FLdT?tG^i$tU37pX? zCCq(wn!7Q}5M?)B;p`vGLD7*9+=wen@Rf%g<>G@7Jhkc6)q8ORGm{>hkbnw73+b^( z2Ql1WHLXd`#zyU6`d%&{zlkF0 z!4|WlG*!0&?fj3>e}zrB;Z`PXN@&Gt(P`A%<0_KQ15_%f4Oa%G(9#9%c+xb623B0d z@{%pI!K59Jr2EsKTiejg&4niVwBfdsbLoFWLWWQbOH&^;;cl552fi{g>p1}^Pc1GayUWm5hwMy1kag0^#76E923}W+`VOzZa+M(&qkq6@>Sr(@Rr#c%i5H~M%11+8RvZl#>+_!=XGsl^vBDghj}jJ9X~)V2PxCb->1)>bTBLAYN(p@OJ+&W zF@b?E+$lH4&{Rix@*C#Sol$BeA#NmxxIq*+?F(^>jJdeQO9DdoHkDe&D+X7@%q6t*1##s<^I zmQa{C$Di)rz8!X#uA+mXp`c>qKpO>y!=5G^sui*seC*BW7(wf-d7GiH&aQ_4W=^Du zqkKVY%6O_OFjZIi>e5B`7sBf~IDq)1JnVf-{0Z%e4vS7Y#|7W8F{ zKHRpROD8=Y2m59@(6?vSBxugxBs!vRHr*xM!SvIjsLA~p%1h?b`v;=w$6A3oAH9!Gwz^L}4oA>= zCtuTRUYn?x-!EDg>`y-i499;S{`69YEJj{jLC0u}!pE&%^k4rNEIz)3+RCV7)mqla(04C&=!J^XY*gGMYHkHd%zwQkkH`-88!s#tB@*nF1rpQeq2I_tTP zr{nPB_~ugM6=QML!&9Q?$*Q=ve+EPHl(9i3mr3$cL^atSrtGpj&Nm)QxCSY-uMm;8 zui`lSHhjm1M-|NN&ZUdeYWlZL+283VBc&&TMOLBe>=Z(`DO9XgDEX=iVdF zVgkvLi%&_)t2DAQ?-kkmqL>7KeJAwmb%dAbBWs>_koEK%>9KxDB2s^m|0?>3y4D~` z88t*6NdG0jLL|ULZ5YUv$U+ev24}A*f_mC;xVc&tq~=S&%NrUn^|b_yZ_|crJ0)Rf zkx*-mq(OYZ2=w!0z_pEm`e1n|7rb~u*X3b5odrWpiXc{R1rKK_!_K+$z|B$}D$E_g z<&*$|8@T`m#%e>ai#tp-(1o^kH<%Wx2NA;;LDV%pFkin23QHymJ1TeR&6+Iesa>J} z?_}6FM(DxgCV|X7XV@BM0OK2-K=+;=d^=(bx3aWh{3a`Kx~c*8qi4XVI(2wG9N=R7 zXgCx#8A4p;p|Mp1wqBG1*APW0b`=A*Y&huTe znIDc4zl0_-?89F2C!w4yDVk6C@QY+anl{l~kVkT2S{SJ}2Z&_0H*-!bhPW-?KXssK zEBPto#MMl5Azd~d-0dF|iBX{v?OQX*)K7GvMz4yPjdhV!F2IMB zgAA8XyJ`K@D(>!ruQdCjDjoVJjk9!I>B%2zxarw`nq_Bz$+jnHfa^4j(XOX8NptY< z&mKC?cRotQe5Z|_i?QUPB<4!_;crhByd!7`736dTs^K>Dc|RHFJl=r~TL5P}M4`s2 zS?Jgtjj^|^v73p*?(I(aST6ycU%KL%Q~Pn+s%1FmP7-Ry`C{CE$rz-*25(GD!SNG? zd@jQjbZigCKBE+jcHN2tiAk6_H4MYO_v4dI5qL|evvVfx7W{qjm=L%JMXO`+(#buT z=MasrkM6ojKw%pQebu4!B z5p5Ay!hbIdnPibPs*F=2tu+I5Nsc@5Dt<}(GGj^8ns)k6<|Ofc%F$n{b>yf+CJndf zA#Z1d(fKbwkd8%jXv5!O;5l1{9=Df=9${uIiB*F?Q711-`{=^-9BalgZ4$tjZsy`* zQ&@M|fQWWahwHc8iNzudNS-6`7L08mq9=!}@wSJK%2MKcVm>VVD9npJ3!x+V0U0}X z5qNX&Nx97OHK9z;5_H!X+@Gq%3KW*`Q4i0(-t zYxinBkq~y=@#oHyRDm_P;YB)0*3p3Srf^dAN(tOFoe1uhhTsueB*yMH8CT!MOq=(L z3@vkFyo@`^Zrv*;uKOyLAb zMw8ptMf6c!7vuc<3Kjnq%&gORMwu%b0ZFE-J%Lz>o8@_9h$7+kBch1>3{QmQUBdzy1r%!F4ucXduF-f zPQynuuFnBYbRSXKt+UY?d+70b<^mV_E-m~z1rI9UqD|f7v1e^3RXHMPx5}^4M{8v< zRHm6eI6FxF7S+%l{mK=~(;RJuHqil5=Qe(k3u4}mOo=M8k52Ah!pYJe*hkfPasnx z4}+VQCGktofK?Y463Kx~_%ske{wp~GdP}yEV`4*Yyzg=vt`j>mhP=OF(W%H&Ksr290a?h}UFG z$dc_MdygA~XY5TPmOU00dtM{_Rtd07Xe5ur|0BQF$wY{_B@Gcw6Ev+UBk;i*I;`2)8zFOu90SU}f)Tt{xYWK)})&g8)CHaaJRC8erA z=mz`o+^T2ulW(R;>EBd<|8hhBZJj9Kj5BGBk|JbUR*Een=>8? z9`kx3TPWr&HrNS0=!#cppfM3?;D1;;X)-#hJjCdoCRjteu(q3E|MU)gzht_g^KZqO zPSbJZf3?^Wimte$2deuGsP}$>#h@xjeXX2eY1$L+ z4!;~`B%J0BOy3A!pZIgq2ll{^V_d0nPdtQ<$}^q(HC15Wd=Q0<$pUGa)y(nmTXoUBVLy25gD`>1p zB$gf5guCSt5+|hK?K@idKSS3YP30TMtui7rqO61v_kF%^$t+PRDWjxRqNIfO-gXh$ ztCX3P@jl;|%FJphn$kdf_!VuEvRl9Lpu6!2o1S$O zX1{nQ%+lzB!xOsL;J99pYVBriO-0y=t}j`&GHEuf-~}tUNrnCO^CfGtMU#Ck^?GSo|9NgGtg$ZmR@5)A#JGN7yQ38QrPG4d z!VeIrOIYhYb+BZ)343#PBCHsg#HO5I0&`5&+3{a`$X-=p|JkBm=D#X2cI$dK`c3K+ zTpE(Y2ksBxt-mkEvX`K|D+zZWI1Nh_YtiXT2$XJpiybc)LT0S6<7`L+EEg*AUu@dR z$tYcZ|8##cub$zzZu}_di?HP@bo#kZDo%XFj&Sd5? zuL$3LDup+`A;CXtNa6J~CHZ-d$vpN+^XAJF`Leb#JZXsMHLPTLS z|K2gYOKdb>^j3ynlNZTvsvgb9$A@L2Y{fGMNHu0~7+MN^U z*YGR$f5T%dm+~4xJxJ{5@o8c2@c27(UV7eJTv%$%=bn6pHjx_q{pl}phn_6IDEB$) zCjY?4i`#LzRtM&PYsX)iSI!|<$xu~?>dIoBm|B$??NlgfXQX6arFd*xeu+dDg6$F zXse^6+-qxa(2c~qPcXETO8=-?h{Hq_)k_n=#Wg=5}~{Nr)#iCIp>s7iw^ zQpqG1{6w~N{d-b=Uz>f^t_*|1?uLh9uikCpRZ2wtP~gnZpPxHhcMZVV3t+1-=b zfTEKyewHCCQgj-0b{n#z%8G&0Fl2LudjCu2`fN?lHJF)iz)I`fh0)#mtXxqCSSn0r z^RB&w@h^1Qq+S0(^g>;s$L_W%6{tqP-AGqn+jsupAI)`+lkHxI%o<$rKN@e7<|hG1;gYiL#-fHf@- zp{DQ$oY%Sy`&&Q3h5I!SRwLwQ_LV~Z^5;-(aSnoh--oGfDPY&%4AyIp!LMhRA*gdZ ztd2Vm2KK8U|7;et2HHTmUMzH|s>6XNhhd;Z6pkCOhP=);l4NQF&NE_3;9*s0S;COK zhUX;z^e9Gmb|^VwaE9~oeaT#(;z?CY&A1Pl{F-0d{2VKu`X2| z%Ui%X{3iT=cUqIMf14QJogIN*t^?Q~whepU_28luPn0u$j-w6Cg`S5N4ENB$$Xzvf zQ%M@{Z5Q&hy&veirn7jczMfj{J%NAi(&%BQok;Gu(6XVE$%Mcpm}3{legxYC2q55)YFCi=l5(E+iP%!O_1Zu<^+Q zka=4Tg0*kp$G&Ue==cL9mI3CdvIQ<$iDXc3W*!k*oX`fw&1)b z8@*7RwTjSV6+L8F&4&i;e}!`F#d>4*rp|r)z^aE_S}#?ymcDueNdMbRWW15)@iUCR~fLaazgAzS(`0CKZXtPQe{_^ zNw5)ivh2?0-=JA4%6_!$f#a_~fwkKsc)Ir?aDnwOtKlkq^ScOgtgt`eQ3hB|ONNZx za40)@7?|=E;1st6?zb7kMU|;=$?`XGlMw^$KPBYZP!0LzGljeqTSK-gr3*^b9x(^g zzHrx`w3I1X9;fVkmU`}Krh_i0=(Nt!So7l@UA;;dADmZ0VN@KheLNlK9dgG1+&$4l z+!F(~9>Prue%N*(5!X%FgRxEL@ww3vG~G~*g%x3#CwdoEJdWd?xK~&*GZt5U_>KoB zC88)J%KJzqAahEJ?+Q)C@164e&$scor*|Cxd0ISfO4s1sZY7}PM;-pzk3>AeP3HZc zCE)q3hWz<&Noe@Wh+k-!ge@mb`PLID_#(lScN?E7ixWnUhobOrtYcpJc*k z{>sM5j1m8KTOk_w8SuwFN^xJrBwk9q0=IA1;mx|LaCG+s{@v88I7)0h|H1tlPWYh6 zkDYo02hYgz&4N2PE@w0^?RyWG8jA9VY#(BR(ExT%d4v{Adhq4jcAR&*8=p%(!DYwW zQ9HW>v&Y@SnLUs3fJ`+i*FC|MyNDaMJi)4W1$gdC2L>f%;H%xw&}DucYF~JUO2HAh zKsdur=?lUQQg3k2G*A4p;uSvLI}1JcyvKwB1I%#$g!dc9qW`ZxJX}6Ni^hG&30y7x zQ6oH~Cr8l6zCXDAr4_C8`itv~lelZrBe)}^THt+C=-&L*&G@VnOMZP3=M6KD zlP{s-yuEEH2^ufXSLNI%VUnV}N9s?qSLkW)%TR*YrNfwa-T+!Z58&1?TbS_R8y32` zK=p|a=-Ia(o*a3Bd*1DaRg)i~bzcPJwA{dncj6$tpb}@FOMxfV6rHDK!}n=9n7t(* zHnK^Wys8k$#&GmiEdi19LHI}%AyR7|{`*u8%SV}Fpi~u1xvGpyqH96F^%H&M*8oRa zvZ&s|YXC*o)c5-}koLG!c7$mG>7qtvc}W{An!bZLg*|}ZD=!jmYX{6r{6UVGK83Gw znsEH!WAHbh3HQ%DfppakuzJrE@SYk85&93|+6tj&e(zl~2F+dnG6xYXFz< zTf+OpC8#RsfXIaxVeb4MSSXx#`!5W^YVRayIV#Q`dlLa==VVw#<;`&SvLZYBwHv(7 zQ)MHP8PIq;fpvN|2L6WYuv^Fz;y%WJZCsN|9?dpl-~7-aal=zswZ-$9jKZnx&r^w9 zAega}guGRCynr=3T159J5>}zHgT{Oy>?C1%*!>Q|u6}KTx<3h^Nbij}Cs zHp9ni9<4^o;eC23R^K=WtDG(%Uzi56`_5tOlSsIwd5~YXa7h4$qv(?fUzihw1XbZHx;I67f_GKj`*%&KVAQK z4UW-~qx#%lyji)4n=#=S))go+%bip3^F(Fxc3uufDo2p2GsQSAri8o@t;FL?K9J*C z&1jQ029~^O#qZ*VpqJ8t!#iwX>8ID2NWEd|p)csHu><-O`cWw%3@kK8a9m0}%z)8+ z-oewrtQy0omYj$9HwygW2p$BRmHEyuwO~3$o!|7f1=^-h6!JVz;KfBP{@J-#VDnF# zUnl(uZ1g7aX19LBSp7-7v#1E`ZmP$tu9aZdgihj(R!On;VHASL!oejk4Rt-zYJyh8Q8@@(&NlH&Tg>Zx)tN~TjA?CPb?hU z07fe<(B)Do%mi(W8k-Gwiw5Xpmskk-(L~!O907;SG+Gts2Mro_wAa-UYNCC)Gr2}^ zi4$YwmyUt&uA)T5^97L$o=<`%7ZTgBbP^roN}Tl`l4CNLnYm9yA$RCwnQoREoD7&s zm68nsx-#g_ENiIqenpqhUIcDy)$nA6H>{&p=q0fWwCAqDBfG*OD()zH=$(KNzjzdN zNQHd1|SE?U^$vA2LQbjvF)RN=nOgrF1xv)EYZ05)mylBuy^e@jEyAsr5W>En3gS380ErND=2 zd4Zv%EU!>#2fvSw=ErC1gW6;fenx`~Ecy5yZ{2!9;>zA*JF3gUpan#Zc^4JQGi)j$55?+blg=EL3iecq3g}7^vBu&G@n0AP19!M#p`N#c7X<7 znrDMOUq4e(4<9^aQbxD;AH=4(xs>-ji8T+DISN@gYw8VV@y%i+M|?@(vCBwKUL~jX zuH$?@zISHwLu@45|USDG<1>Mr~`bOrY;c?k9IOYr8TPH3^s#>M`x;KKeS6gB$@Bf^ZH zdCt9Xa%d~AiuwU-{Fk6p`~aMoXNy`cf1&xaCYpHE*JVI<-#HPbTF7z2*TD~$Y##NYvCN-7h4F+ z3IbtfYayI;aRD3mLU3J5VEfntkUOaW;{x)aRQdz?6_5iq$2s!Q?hLH+Ur&y0Is=ed z$1Lc|1i87bWiP$cL42=1onV*--uF^z>&6s_lD$cJk_@i#BKWa78Fm_v$K`Q}5L+j} z*L8`|{M!K&dlTTnvz4eYGXc`YcVK9BJhY03qMS!O{Em*oeHC$FTM~;OG!kIGej>h= zjTd$&W#FYb!jAQ-)3`S~8Q#}rqsq-B_+62M_Z}ue#pnWz7JjEr1(@?a5w?EF!-Lfc zu-_yPUH-;`TVXEV6F&~SuV!P=-w+t1a0XA??SaMDGjNsUM(Fm-K(i|z;FgkxCBY8h zc0UC>Qvk#-CZcluL>TIf$Fa$>u+l35%YFYNV}|1}R_6}+D<<>@%_=2saZ%VF7D2*0 z!%$S*mTXxWg5ftlF}eE>;p3Hd%&zZyFz9G$nPAjTR0?>*C7EwVpMC@C@Y)}zH~3Te zW^a5vC612U=ZSV!*QmI#C$uT^3w5R9V2yg4l=?mYX~O1Q%5P*4ll*Y zpij_Jbi4S8y6@e9ckFM{tH1W(bom16T^B{~Zm>~o2)ZVsx}JSU&J3h?YEaZpG)k2OcNAxQNi)?ToJ zg^tCz(Rc|cd2)EGE(m^3iHlyn7Hjp3HjBeU@;ro;( z{4n_eygJZ?C13ABSbrm09=Qj0*Xq#0?;gmCR^yi`_h9FTOQ>Af3ioX|9PqgX`KA|f zLueCdb>yPpW*yY0WZ;>R%g`m9orc6HT(&uebLHrLOOaj)^1=lQz zggOOtwEwytqD*w~UFR||zAuMQ9@)Yl+t1X_QyY}oOZ29g7{HpH^!892v3;pPpO$A3 zgOgLay3m;<_?A9XNh%p5@d+fUXfbLr&tuBk}OFHc`kI zCcwpq>8L4_1Q(>wU{p&I*k3=3)%{7ph~{FiZagGq=3}924D{|Pz>p77pmysVuA3eX z{X%|mn$aORrg;G^mj=RFonpLxeP>)0SEGAhG~C%%!(izv?W{zNuT zq)4@e9NS}x8d=Xs8}c~nPYX%vr&y#`PadV0VOn-2k(phLQd9ED@aIBomOewqX6E6~ z<|Hz68Y4nfWXv}#YMXz^!pi?gab#Gg^LQvHGzA`Q@gJFOmp0?%`>); zc|{I4e07H9`(!akV=c_k8ina$+oA0D2zA^Q2BJ59(Fxhe1fTlFaFl%xT|3sm9*GW6Ul;_j&mY3N zq5V)JxCd2&5ZF8J4j7IIH8IuK;9STta0ssh@%|IwrhWy6g?rCg#S&;N;C1pnNP8IYq*Yh$GOG76M~et^?=rgAnVm0Fq|!0Gk)a&}O$87P-j4EXmcd zxw41o%Pj$g&?0g;*%{O__LHx+)`0oCju>R9;p-uuFrK=2F7XuUYBa{Bb(?3-nuz(h|41{g<84x)g(!T*?l)HYfZcU~KVI+7}Q|BDVsQF~Yvm+)I~gOUiI7&?I0)(uhn3*ngj@*iEIcN`am{iauhXJvPc z2re{EM(Kcl8vG(1I~M<-UIXc!y6%1sigbUZ-HWoZCbWlo?9Rf*%CEHdSSC&r@(_1AQgF-D zZ#48zB04$uQYFt5NTz?MGM2}%HTfOAx-|?>)qJI&$`51Z{yrM|Y71Ibexx^xe6hUZ zGYyyX!a$M#=+bM8@sr1Y)KG0cGEQ%4-&afQZ+%T&Cr`uquAQ`vF+mmAN7UC#2N(Rj zMhjatP$c3CojqRI#WKH$D)%blmYM1F*p)FD?;KA%BqZ>vYbYIU6;10hro+kY)ZJc{nn^a&v>G{j^)sdKul?bMB6%8JaGTqnbecLC-sNg-)9J(H zDsGe@hIU=7;FK0^qhbvgxQ=n&^i*~tH^0`2J}=zMT{0BVJBMw!YZoLafBR?Ix7&4G zw%Uy{PC1I>2HgcV&qs5X(*^~G)Pa!KzRxu?B~lzF@&IjaK6GWw6)(mzN#F33Yf(owQ$ zlCE&AMvyS6=^*ctL_SD30e2^rj32uMOnXv^#SI_m+?7gB#BYX|!kMusd_TlbO(Sx{ zq2MEtL{!1IUzP z`9huITB0v`9-KcdC24cd!~4A!#Kf`~&a71-R_0}3p(a6I|3Ii4*Ti(_mxKJ32u5o| zIXrl9O>jpzf0gH}nyveK1^ivVmmPmnA)E(~a4`{=;FIMoF0!T^)_aK3k8TM3WKH^O zMk&mWx27BGF2a>j8|n7#=V7OKC{61tfHv0{Dt|KvhL;_u=Rz}JFe{!$Y)=M_ka!vx zp8yt~8FWN423B3mpnvy9K%mZ9swH+1B6ZJDgIinRedlSq`MW^i_jG!D z<7}8CnMT_m5!jo4nz{?`r2@+|`t67`IPOTG|Mho~Rd-|Q_TKa4zkN~k`<=riRX>EL zuM{Dh@9m`RcBulzk;T;VNHG`aYDG6rw5C->Ce+d-nXXlnrq)%hbUA;MI~(wqMw4(( zsd5~CK4!v+&IatgA6xcc;9OL=pes=GUxAIyYK&IE7Tnn8&hQzbXr>v@xLU`eSMnR? zb#*%4AM9fu@5#f6KTle4&&uR z@ucC(Fb?Xck*y=cn13UiTreI+Ss{1QNQTg5YX#ZjF@VgWDzYN#Ck}qBCmQ$#FU8y? z`|CfT($Y?H^7c!7wCF9#e*FYzvLA^+{vPT!^^)Zc&1e_@hrC}>jSHrV!ryruYQ7l_ zFM{(hCRGkTpH0WHKgU2)LV7=o)T-UD#FW;NutW<5N z7_W+X&nLn6_AgZCvOd@sUZwLY^+6;ul8&qr`ZW*Q(B(@7U?i2wJ#Q6&k5-XDbe{lH z9OcMS3jr*b+)v6&r$SwCG0|``ftCkv$R1gJ2#=EmMnwm<*BihCb|U27wSr_>4KS@+ z3X8ktLEshuiBuX+TZO`hqG1xO9Sf}=zL8-+VJGL6_arOfEGQX1Bu)kwV1iFQ84luM zhtehTZC*7DN9K~K361dFDVm&7z74#wA30fm5B6(Ykl(wWg3r}nM#1qVg#S)pk~e>V zoSN>E;DevxvxzqM_U{)s^1gs8`>!89<%rNM?IC#3Jc~XR9|HS#d*~&>AMky0f+o)$ z1bkjbFCOm)jYlms{O2$5{`-PneDDo&dVbP|Ri8m|rUce@y@ig0^2qge!uU5DxK;N7 zJZRIwG?82Ibg==ZuCIZTZ&UF(Pr?58bi9|B3+I)s@rrpe#DB2GNh*=>Y3(eWZ6U;$ zh8)n*aV2P$I3j<_4qo{$#IX&AAa#8qn%z_Y=Rb>)pV~)Crn_L))LJ68(-og%6uC9g z4Hq1oK@R!5V#5QTvC?osnYWT7C!yX8oEIt!28jH7GBW}r)419e?R zaQB;^^qYqv`mU3~H3zjYSyb3tRS01&p=HRl&qcN7OM5kka=;MEZnDelQ z)^+X0dspAkipo$lc>9cwlttm3$X05ic@leOR#FkaM6?e^8aM6~TK&kQ-KWmtvxqeM zq&OdC@*?T=+#@326E~rBJ645dj z`#SVSWhQu39UA3kGS?S1;x3<2q%ux8ZyB4D<$^lw(F!6Kz10|?8cRI7Yw-N_Y_iv- z3Of`olhEUp_+)GiDOJ0ImmFHii;fDMzvvnH^B+b3H_ynS;bL62@G04{=sapjb&!wU z=TIi?3ArT5!9MSMWJgLC-WXR)md#7UOZ~-UyKMsMoys9I%wzCVWE^>v7Ksn`A0%!+ z4r4==8|nHLj645MAe(-z#qRbF#-(+!@anmmacr{3^*{9mzbgdjx3;6Kdz}v6s5-@& zeo#Q4?Ze#jNx$hse?8je{g8%7yHao43v{C0KALJ9LY)rB)9dFP=!_k?^i@R%_gIh8 z+eR15M3>joTX%z)uJpS!Z={#`CH9nBt1Tr`JKj^A7)1uR4p15OQnE{Qh`!rYM@(Bq zQ2b^m@lBIJ4O?+IHFFduEL8*54Wsb6aJ?qAN?=TaC0siR>_~e_Up_tz-X(2R*Eb3RJgex_$^`Hnn@#KOPQxLic)H|c0ZjAurJrV%f@s}z zI#O{3UcVdR{A8Np@vd-gRC_C+jcnO~5a0Yr^_Y+370hY6#czX?HuP^{b6H7F<(T9@%R^vxAUFfPlg0BvM=nX!Dw%Oxh$?IbL zW~K_0E$i@j!B|knRy6!B2~FNl@r$b{%uacaLobHNhM*ri=jJeTl|tVyNc(5YLU5!MmHAklUz?k|8`E7HTEx zPvzmscs=3WI|0W97~>s{qbM&Tz^)G~Q9croRRw&(S>d|^;anSMg*j5q)JA$H-dh<# z&#ke+_|?Ol`bRrVZkWM5SD1r~0;dskrFmGky^t8E%)_OgpU7I*1!$A627MD3VXK@4 z97tSO z^Nb4~OuGq!Y!^&5xCft|-O#|i6Y?b8@O=AQs8n8zQ))lMrL;w;c;zQ76gXpg-vEr) zcfg0ohM{4a9mbCrV=doKM-@K_cF$*1d^a+RJ@MTDHHajetfh@s(NgRleI>NAmtrT_ zNTc6HDK;%`kd97}VqY5f(ghEtSjDJz8oP5eyK8&{ZJj=fy}vV?u30S3dVPzegTnQ> zAlidg82p8|juUC_;195kddWE$^ue{UTHLPP??LSBMKdY$7cgSr!?-IwhNH8FnGb7j z1D#5US63sL4{Rd)tE-{@WD?0QK~Pyu$?MTYaA|WZ8IU~#|Kj_IdPO4m{1AuRmdAwo zF^aHi`XRWbtq!Y({UGVSHYnx0LEBp+7`Ji;e1A0+n)4?^=wTLYSB{0X<}AqX>>;l9 z)8Ly@1!2mBwVSWQ$@2s=s1Th=o`xF2b&CpSAWIvbT*@drZKDoTO1e3SQwFmNPr5Zq z666L?QE4p^h<$a9ChzSf|Ly)ui)5dW%TttaZ}&~|?~MtT3#CYbOB^sDIFHP9Sb?b; zNo417AtrV>g51*z!#Ddj6XTb$C?9P{ewU|Vu$(4Ij>|y}H5uXgQG{EZ`xvjqh;ycA zFq7_I!I?AHFxwy2<88;U0;{}c6cN52&b)?qdTy0fUc7<2#|$|an-;viVh?vf;ST=j zJH^dXy@TiE?{g>4+{Sy!!(40L9dvm2lRMvi3r7vfPSB=@dT6FE_%V@h*g}yK4g?AoNS`$)+QkTASSEGv2$83;mvpSFN zl5#YYEx?ACqv*J{vlu2NMwe)x#&j4>HTR@pQ2Ki=Z(kxZ;iKuNTPN_xyT6>0*>OyN zB}aXZgdqq-Xw0z?H0sf$t9y3ig107g(0dztrvd$PZ#|j_?5SM)a$HLtY1~;ClsBD6 zt8UN5g^3HO-exQ07Wz_sVuD#KH_#hSldi|3?4;SN#qQ8EkO-7_MiJ9A)r zpc7f{dk(zzY$y89ieWAZC4>10wa=2tz1(t$G$HD-0pffo-G0cwGCjuS{fccy$Z%o@-XAeRZz_v56b1Wa5hs5 zmP*vZmu794-%$x6dkjD>ssb8UPKE3z6c#RKAb7q|H)zbl(XMkaIeR+fs^&t(ISbf7 zBNLuw+5$;P1op2DESwPyfm^H~Y)U8`6n56^xU~~jrC7s#jrGuFUkpWpVQs>@wk-zPS=X1 zVuzy`*8WOI5p6j&#dZ|{nJm+bLSffIJOGRPmAgU_5Mp_Q{W{->gd4~hV{ zRDGt-H>RK@xk10CYU7Iuxzu=tB60@&^ z`iUb&DPy>y2{*~?I_t97hn=Kv>~%qE!yBTsdmY1z43f|JmzY;aM1?w^K4wy&G?=~@ zmQ~*n?&alrL{pfbfj3Oa)CKw=8Ml};&ozch-SuRn@GO{Vx}DUsEDYTYCwK2#z-jGR zVkv43qs}FgFY{-E^SyLp4fY`VE{n`~Vh2};3W(fQ2Qb$xB4-!aLtO(${8MaTYG(YFq^Dey_QHSse++nHMw9b z4}0!blaD(kA%L$Yr8Ohu#y~k4iTzIU9@Uakn^)xZ%Sy69xr4YwT_qXc?vNb+Mlz$k zp6t$PCf|xL6WQ=)vhHsokajV*&cp@sXU!D zDwD*;D9~+Q$)xhMCS5BZPi_tw&=X0aWV7`&dU2~CNpP^GF6SJ{Wq*4ro@`8fugs*i z0yX06=S4Rke#Nv+T}XeL9%V*eE~i;9#xXNQ-06R>BLrvUTu=-tAgqKk)56Ma3mr%4W--qMy~fOYJlg zXoFU#z*9bkKAvFDn0-1*9fD6Yv;8;Ib9zr0=Jhff93n$9Oi2BYmWihK_h}x-8v*|i9WL(^M=2BTS zDOTFdSgkujE(}~@WGBTCgT+6Y5jKXHmxvL?-?2phv=*5ccAQ9WHYWSLLy2IMHK`Ci zN*eu^lOMJI+MBVnJxknQsWJB=GKppGEy1JpiA3%3gwoLQairwgnKF_T zLUKCBbGeN|t@DvkZjZ?dvhP(s_aJB?xtrC*T~ak8!ahE(ZLJP@>C?|Oyq6~{TE|k0 z90_vqqYBM#eZcHFKb;zT)G*dw)2K(pDTYk9qx*9*nb;@J^j*SMW^>0H+HM=n#LV-j zi8|WMhUYu!Nzr$Lvp<6AwUAK)wZt7%_mF=a+exEKo z8+DX=8rGHN?~JC0%V%(VPR0oDR1VzLZEi%QoEWh)Vy7p$~{_2%X_q_#ZepDCCkv>f7W#K zN&)TrtwYbXSkYOosuX70(5%IxbWExfoqg^xXLe#G-P4xGsrvcRyZtM;fH!OD{VCmL z@j-!fpZ=s0LB)2uT_jS_`g|X4@yixO9z8%ao@y``*6gRXb(@*PN{8tjxl>H-n|*ZM zv#X56c#u$r?Fp| z`S%Xe-wl1ttQ`^bN39HT?G2;e=S7G|_;D(__aD<27eePd%MdOnl=`n!AlcJH=zpk5 z>cT?kmW?K)ck6ySJ7ETy{d))1i?AYBe{P`4du_=Kz4bIv&4C!bcB5<8E+mVl&8IQd z3rO$*Yl^{($Rrg@>X+$ID!`sBqFZrVe{ z?SzHnzPpH6X*x6CID~YURx$qN$BAxNEpu^AG!YN#VHQ3*LB7lqB};;1NE)b+;-qjQ z>90Xn%-Ba>H5rjb&H<$EmMO{qwS>?JTk^Brg4D<^A|JHJlVz}k_^t0}hO(EC7*k;< zN4-0#W!#zByH}GlQ6~lJH&&2Cb8O10$F3n`lAXC--K&UR{2A_<=O!{LQGGk`2; z8s-$zgUNm)85)opNcJ{Npu4YZA<5B`=ttxIMDwHtbz5+l%%5dP%X|aL5iw^vBPful z8F|pgH!I22(v8$~mlyHz*-W|SrNn4K5Iu0qop^EaRBZ(R?->pH`nc4(rRG>6%~pqc7EJHuFCxkd*QQyBYYP4r1}8nacdksg&uV%9s=Q#Y+M zjNZ;_diz!aV-!(M4Km}Hw-(j3G509rk$IWE^4Z3etQY!o^qm>4_F}sHz-;E5+j;t| z+L}4|^DHg=Aj!mTI79bD%P{7dDRiC6Sf;ftmikB!2#P-)qhh9$1RmcG(U@o6f@zyK z(YczIf`7K|^h;n;Y2aRSD!O#2v?g}~4ZU@y^fM8q+oe>?;-ag$@t?xV&WHJN7uMvI z-IlmecCo&)?Bv9DGa2?r*+7^Lqq{|vvz0l`r00roe?uQLcXcLk&pwSKwil;xvt@0_ zv{S+gfXpRCe884FF>4E{4G7{^d^}E^^K9T-hr2}pUpnX%Ox4JLC= zFv~qf!6Y(^32*#I{%fyb${T)>Q2knF`282+G`^X6efy)(TG!6B7ri0>l)o^kA38~L z$Y17%&V8aNCq@$Dt`j4E3@L1_B@&V2NPWgdGC@&=tl$cWi@6?gKX#hj2r?vLzH!9& zJVQ3Gj3NqPK+;z1AU~R>kZkd_WX{gXMDC?4+2=5s_=(IQpWo?`xjj?K)`?nVhn50a z_IezNo-9EuLw}tw0E;Pz_JDrfdlCHVFm%e4G&r^hHb<&2|o^ z36H~RY`;G}J0*(pUOVWAsz_=lx0!aV4WlPDw$n#1BIs+=owTPfoVE-eq?eCH(4NDkUV<#M?QYS*`v-8JkRl^|~Xc$4q%j~4lk;kZoL?Eqqj-}I@z3H;@ zcsk$2jTSvQNyStgXwvv(y0p}m_Ww$t%l0zVODmN!cc##yhIl%1U6ob{vHg^bvb0b= zk*-)Vn)Yd*q~b2(^wYRwbl`67uu09^HxSBcP`O&7-AOLxe;#*W%7A~I|)rQ zAtPps$eQ`KWLk(FnV-0dj9oLE=+Z#)#nXat3L&KJ2asJV$B9mg@VT!@BI|Z4li72# zNpheV>6%$gG?hOx^LuzQY+b|Ly4_4B39dWT%vbDVMA@R&pzhcZFg-K5vhn;F#Y zAp-?gOf~!@`TI;55bYA%tXg z{S!oNJw%QV^_zYyKTO_gi*paMx05kxd$|{(+sU(?cevArn@G(8Df;e#HyQtRD&1(c zl-NC3L@#f2C67EpsB?)uSw1U?E*1sy(Y%oA_D>{5HdWNv;P@qIyfC=LpwP4IKTWbL7?L4(hw`9pWiKFM9mdP}!^WpTF0 z9?+tBNu0#EDr(4NauOo>w4x}Ln?E+1ZrYr{-HlsCm7`8`%i|4cMrRQ>+VCFNC%D4Z zxK8IzExXDsa1RhL3m$W2D-xNK$rn@_Z#%Fy)iF!H8SjUEolCa-fR zQD5r@k|gv+R7~$8i(XpLc|HRq)z_Bh6-$EUJV#phRte0l-RP3-I-odeIel1U0wFKG z=$3GEm^Q|f8sD1@^70q@U#P>K(Di~B zC11)`eOn3>hh572S{8wQOmC@z&m8zQWFlCtUs@^|tWXmQaBN#2t*W8^0F%((>hUumbNld=(w>ZxWF zgBBT8QkLd^=wy36C7ZAg4c^&7x%{4kPWgvY4HpEEKw>bZ79I~vMDJ5cPi3J=tAfg% zC(4Yq3{cz~&N!gxJ5`o&2On4^0u6uu@yXV+_GgKa*KX*k z&nAyHMuLuZDapT|3@YA@mWZ9u|d{sj=LP1eBi*U^vWZL z?ElyfHzhP4>dHR9A%h%$xUpw4CDHzBPxhgzD7x&sowb$~M>o&xWQ7*~0;^NI*ecUu zIK}K{6UIKmvjclsss48GJinVQl*@;d(p_xIwQ~@)Y$s2j;|>wQ-fZxC9cY5BZ0_(4 z>UsGlcC&?I@ug4eS-q0mOw@TNHdSIN{&dBL^?<{;d$&3J)+`Axl{01iZ`{E-{f2C# z-BVnyFqdV|3}B7tDs1_u2|O=RidFIEBc2C@*<~jM$yLQ41j`B&ql+KO*m_aoA@qj0 z+!7(nUo?^J(vsvxTO}c11<9%AYh*KzuMFFHfn==wi|=fRB_mcNxTZOfEYp9BYyG#9 z*@xP3!}jGwDz+L=zN5&p;+xngN0BJ@72w^??Kti3MLeRNiX(9de)>WXdwQRqVYL|!jHs0Jhp$F4jWoU=wt#F%9g}(PT29|Vb z(OCElT&y;rExh7DdY36}av&B8rk2nvW}Stlcb3tbJ7S<-+?IYQ9|$dR4s_wE%w08 zLKiw9&IdLhccvxFj=(C}b+lDv7~F7KLvxP=0DaJj9`1{QRxw9<^}Spe6|twgCW=9A z#EO<)a1WkNSkNS{3DT|1=-hw3us6z-p4<5m0_K>|`u4iJp9lMBIZeMS-q-PI$@t_vb%=~X=M;W(U7I7ohdZUkN9 zbENDz3nnrbiR-@8@G6x{yj~c>6`LwzYBuMyIgx2v!|J`X zAy$=Z*-AeL5~b(Njy+mSJe$|CrpEt~=kxz#XKmj^qHWi(oqM*B$fx!!W#~l=`fb_4 z>s!g%<<_iAsN+`{)~dXR zgp>mCs-sOv!^IjWCiElE`>ME2=?nU|agzDVzha!CdV{F znr=PrN7dKK({YYZDZMx)TG4tA^f#)~LC?IPyF#6|Uw;DX^fhRQoa3;1NQ2IKoC!a+ zXwsLymBUYSby{&om?0F6p?gz^Nq+sV?Q5>ud>Ka(y!C4j^) zNYIxYh0&FA5n4`E2xao}JpNu6LFzAlBa!RENc+SHk6)2RM(Q8YZ(m8&RqzI#Op!;= zvzk%rB6(EY_W(IctDs@sa^&i#jCNKPq1EdZ(3PW?(V5K(=+tx??~EyfGGfl5L^E;J z;t`Dew~3=#!2@Wef*{Ik+JKa;e}KdWGt{Tr59w;!=%-B=u)*S}Mzab+>VAMv?o|kT zUIU#z>5!?M3c??PA%S>6OOpqDD3*ZJCNj{LcA8`Pjt`dnUd%jC$f4qA8sn$pmejJc zD127JnX{e07Uu}(6^SeT!h$Z@+-sYZ$=QlFuGbwClG&lkWD3}lnU?3dj*aUUc-5)ok7+)pYV?SqQy*W`kTJ>1TI zP8yPRq3c}>sf(Ef68iO|L;WGu#9v9S9kHWQA9Bh2G(C<*+ZFQhzzy!ugB0>IGKC3Q z9YM?mJ~PtEexzxWEIy{>LQ>`_a0|faT81_>$BlgwM{xD@`;I<)4mY zESI3m0;yPQ!+O;CA{~!b`l4aK^LVv*6!Mh5jvHsDqR9VpahYO1a;~nzNm4BOeW)JW zWLKl^Q?KzBZYz@f+ky3}deHFJeyl1uh<0Xt!R2DVk)i%1{^}t>*XE63uM?v5xo|$x z{AeaEyp4~%`zu5Lej!SZC@IqV%6#N(t1`XtvM`ZbtV*{k2$R%AHCnw)hFD)xr(H`V zNKvsGow!q)?0Bh4pX-qz%?_$`%sn}hY^+TGyF8OL`^=)dRc4X_5jpxWBTfYLX3|^S zrOC!6;`GFonPi$be+S~FO@2fwAOn0|ni$}anBjr2TccVUvFV4YdO@&Z8 zI*UVJU}&Rv;;x$ApmxI)OL^2&bsg^*u@`Af;HnLb>*`(j=jJR3Frf=d-<1KzG8rq-v1?o&c?{<{XeqWO9weUoF;+s zIw*c*nwVBpU{l1K@3Blb7xmK8*84d2Pi{d{PF$vD~d z`5XML86kgshQK)cBPqV$3r~!CiTwRfaJ;LFWR1Os`W??n+qw?$<#kMauxN$aHFadk z(heTJS50>8tAm{drR1h?6CAL-LEvC5oSBhLdiGSnj4P?c?Dk#QQGJfYwpYLt9*1x{ z9K)$FPZC$c!s~x)Nr=sD;OFt;PEB{!YAllT0A%-z7qd+Y>p#jVuP8!K3Epb0T0+HmMm97N7C27S3|cpD`Q zo)^d9NYOC$yq5PaKblV&Ch4G-->0eAQcEOq_Xt&d$pw8)F)KB)PAShNC50 zmNWka$00noocVX?0&<(4iT^vFkEDGp@X%o{8vVN)hyAHUKa&n(!Q_VsF{${1-(#N6 zpT!2!FA!x?hkq5m;%QX+ac@QsD*N&cms#|qoB4di$a4UV$x9LO*iR_q_e^r%=`&J| zmnZ#=gFMbyk!bgQM0`m~B>Th%q?4dP`r_Uri%> zlqW|vJw;NN6v=o?JqnVMB}&nEQJk?H2`;QahO)9mxt&4JIWk0~BNvIT7bk0UFCg_E zNpkXBJo@G)LiDsF(6wYyk`;ImJ+Tocs+(Mp#}Ntg_tkQQX3r#R_ZTDHQZe$RRUUO8 z5+t=hr(pcOAo-*J1a_PL!NuiKu+MD*%et5WpU+p^W9>$jZyCTn=w8X}(N}o&p$Ud; zc!mq}-EdT4Bj)dp$2KGP@Zr2W_-*DLd^Gwy)()<~QTDQAl_rDT*?Byio{PVBT9Eg- z*KzhgN0McbgC$h9l2ng4T;9B&kj_vnv+^W~+ZBcP2}hCn-I2K5_AHT4J%%4SoF|9Q zp2pFS63A?eZTO~mI*GYxg-ye=$h;8_b~%5E#6MHOb?0+QZNMONH7%da(LB%Wx_*s} z2gx&~CK_w~qLK7e)M~k4SU10$M%MK-8Db zLff4h$;%uKG*hCUR94SMW{x!^_s3jh;9W)LC~Bhyo-a&(h9T-*$`C(4UDUu75}V99 zXp7rr65OMQTvntIr@?v1l|D9Ed>BJoM=ATw-^Z zmq%?nlT2)<(C_eJY&}XNvhXUNeby9R4%~+qG%rHCR%9?QA1p@PR#lGdlo=9QH48SU zFGsg!BEhxC68+)LURAec=&cwZ(iUHiD$Z%4wRx6kkDV2AePf0qJGUW0+XYB&ULdNC z1+-K8JW_pQfX3=CqSnWA(Y%Cwbkao~?T}80{=@S;MJ{+s!V;vSXYWeUVl3bqn-WS$>4J4k}w#%y8M@Qc$! z0#}Y6Q&P}F30~&h3TUSZrDI%2A%8~hhI>vzKPrZh(=9=spYS8v)+j+%M|Pp7_ms$)GcS=$w-!0C z@f2O(t4H3RX+WuL zmne}!OL8S9kr}vPPTEcUaAwsKveExG=5Jm|&JTzY;doP0a14?CGfav5BUdv2BoKG^ z0CLb3NYI}+Qn}Zd^p{*D++Q3*&u7T?xh5nrtdT8Z+*T3Rdxip8`aqJGfh#~yU0IoQ0z_xsB#)^){?Ay(^@r%10Huu;CJmWZGYX>8-;C7n5Ch3hm zR885`AS>LljAri%N@M&6*l@8drtLoyc7)!_9B?#ZL%Qa1sy6AfGb>h5dNOladC_|6 zsQdNJr@%%uI6=Xsne0$v6dbuF%0^sBfJX}j*wCpQ=$rS8IOcNU zq|zX{eXIuRjoy-+^4D-<+Y@qX?@##g^bU#Z{|CDBONiBXaWpgV3aOA+LQpn<8#og+9#-e|7`SX`~~99lR3TWt{~BkTBSA;O!3tAC=s`YI$}cLXV1RVT;H`%&R-9Uk}m3M~lLCH=`y5xdfe zNF1y~vsM|9g!BsJsccM6+Z7|5C=O}O&PKC-08wa)N7dhrN%G-Pw3uT;l$ZLT%om2_ z{?+BEXrmFK1$B_eHX~v=!jGo+8IeB0I;i_Nk6bi84*WU#Bx-FHmAz^%>9jUr+AOt6 z$!i0=;FtFUvF_$v^ClPa#wSLJG9txw2X2`bJ+lQf2uEAkIhM{ zqbeWjv!9G)!7s*u^&nahKFfeTwtq3GGxOLZ6^FQ zT9=E1Bt3W#ex$u3*9N|WLhoY|VLT0m8h6Nz7XnD1zD6!}i6ZTs(Zrl7lDD@y_87=3=E`9aR24lsmav zAKh9c3r>IaP|l7Eux7U*diZe&eis^`=Oo zqCRr!%R~!q>LT_n7d?~FM8@~4k$0mil3L$^be)w@YWoMY>ybSArTr77r%0ot^@6mV zk`%geL5%jgBaC>=2EDw54@r(F(*4=rq1#TCuKDy4JPozz$e0e;BdANC(rkeom3g$_ zqcRvYHKOYzuK*irLVJwHz*#;HU0`z%etH0{zG^)*l_Fjbxh5!70X-QzN$tA;bkx=| zYA%zjWL5AXFD?2f z*kPB%+4K(IJ=j`Zm9|q3#edE#(!BgcyhTffHsj>seK8Vrztugw?6DBNWaJq(^!tZC zr43`}hrDxumIz5GevdxJ%Mz{sI#7P6HZi+eheUT6kd3~jDD%fsa{OvOI{3?y(05aj zQ^9HyWfq10IISn2Z|y{#W1ET2OlxGlb2riTpMxm1y(HRb4Bj0+Or*NGpmpacDXMk^ zUFIms?@Od279As&O|i_1>_g<|hYh&(q(6C}U4&a5eF)k$if8lhB0V;-ST3nc|(^4j@eP^nLe;cHfF#0 z41*nS?yl(LLuZ<`S?Af}DBgTF%W;-R&-4{poo9;ZMV1sh5u%Oa)(f!;*G-Vcw+UkC zwE(&89UyN{FGuax9mMdf9a^@kiuf;Fi#}8qlNEoR(T|*TLW#Pgvk9T(afTZz8r?tw z6TOh(Hhq#CxgA+=|B2Tqdm#0jm#~VpC-QnLhWSQ3(Vn%KqnzN55^~L9k^DNe>@pYr z7OX-K7X5||Uv1IBgLBd36<%i03|n-rcmX1^+t8+4#%O6k2wJ>U2T8n5K!+5S(ORV( zBr_z1Ud}H;4`&D=zverrbk2A1?y5)bn+L$z>N$Eb+y;YHeMn(rCHNm4MWeoX@K$*e zfoB5Dv713Bh6h5isyLl<%>}kK$9*Pke8I|)#)3z&vAzMFrIv_$vvlddcM~yx z)m*y0KNcgcIdod~1-#f%ovsYHjE~gtay29`;g$#`TD|cyUScRuH+(9>`MOfHNdk+L zMI`6}-q|wojSy}2r5_|nDCwfQS z@Ru14WcczT99Pmw-t;Nr_Mv{#e@h7KZWtwB?CY7k^;5)GI*n0R6l9-H%wkM={u}Q< z1KjonGui(<{&8zx$g(EO%}sO`DYDgbJ2`9JR9LTe3(EeT8e20QOK}4<*!ZCs>cosW z?5l4#D2~=#c2u>LdSD1Z(d4-;82VU)b8hjc55A={U2M3T4fN=`i>L7C$J=YUB`m>Aj{kWan`h@d6$ ziKHh~5WP1JB2))I+9=QS82#gEN}Csuw(XN})P5!rKJWvuUOjHI83lXGomhj{TjxIP z&#ZOn2A}57)Sry!Amn=vj;(G4&viYpOt%t@EP344R4IH_UWwjU=R^E9U(~$vGJGwH zMnwa0P`*ABt>aGsR{<{C$-|N6BvqrV3p?R>b}O=LTnY5gUX*e|7Zkg{qHn`f6j$Ug zQhioVx#JnMe#v~w*IkV6n!TIjZ6HkxrM%_}cFNKA3+FM%H!9IwzH-JOO@+=f|H#Z5 zQKQo(jj+$KIxl}>8Fo$7grT$ZFo_g_uH&y2O{5#3B|S)fH{Z_CBk z6Ex|Q?@RE?g&Oo=Ng4L8m`z(wRpN(Z%CwtiCB9g%M7O-UjX5rIbP`XmVdEi1e|T1l zugHthCA02fhi5ZrSF0v`eP9|5#y`f+2fm@F8#}N@@<){B{v7|deuFN`bzv9p$Eee< z8>cR)Mn)n1IQ1`!O1nN|*S7_zRQ3x7p$kYmU=Vk!M5D(&V>t0$05U!E6W8Z>pmndO z@V8f%Xz&Oh`OZ807%ZE{y${9E8&^K!R>}JxI;OG5ygc}%_7`95_kd#QDZFRKJL)mt zFZ^+a4`*A>cN}rKkr^)-#zh~j@d;)S*Z#SThok!Otdw>OCi$cCy~e6J`a#BaMw)IHd2o9@#`e!{cUV&RZh09 z;^I^FkI2BfBAj-kooKmT#o(%U??hNt zoy9oRP?EI>QpRhpOS9&0Cz+q-a;)9mD@;d`0vnX}hr9RMEOzt1F_UW>c=I>OoO+w5 z!rlS5)LZtwHz%tvThc8bKNpXE#~c++3w)AN|wzC^MzlR zrPv1x!Xa?EIP1140qksr*^Sve9qemfm+z8X5FGkN1kPQDA4Q+ZyY*#|G_RX5fp;N~ zhsQ=)SA%6;4G~*Y2L`_ham{XoC6{tZwRba+9Z4iR`#JQug%MYV2P8l8A}>mx!^o%Q zU3pI*K)gR^{?kIwv+!@0TVFG}9$!#VtF3R%kR=PXzJg|!tf=O(PM@Ndo zm>}hFbmv+C^X|?*u>Z#ub>>H>?pKvW8#aSj zY*ooIZX|HnMaDgh~mj#=S#s6xqa2 zdSoLhfotky_+18-`eG^R3%f*hCcBZ)(R_-zaFissCsL}fB8jZi1&W+YCiKHxs%IdZ ze3U&;3EjF*f_V+izNR;cAxfs^O;-{f+jMGF;~`PbDC;tiPuX4j|c&Za#SvzKf|TP$4d9=a}h? zDa@=&VNS<2;45)4%&)u@occMQIk9&MuD8i&4joKj$kj6D{jXfk!Li58{tsU$1=HWm zj$(I+m6X92Sy#ZhOBbt~w}D%`0e;!ckG!5Qz+E27NKR@c?zlf6by;u5R<(|((9jFx z-9G5D;ci@V;1s&}>=;fx5{>%%LvVXn8d?<@fo(GLk>`T5cr=WQY`(_eOGhfv9qU9a z#nX3f-<^()8=8^M^(>s{(uw?SbFq0@Hwt-KfbR_TBW3ODI56%rGE-yl&a!c2>&4=; z#Xr#rQie_U{6WVy-Nt0@G%ByJ!h?Q%wC$D}jDq=Tk>8K7fSdq5Sl5I%uI8t|*gwWS zHT<;Qh9|gm=pRbaYR1Dd(`fmEI(+EAKd9jQUA%eCZ=|MIiJ#?zG*nG={0(w7K7)PwIkzSAvi0y89n^sgTIJBLNU5)F~r|RUeadx zLmrF9=jdSB)~o2jI$3;b#YLol^CM$ubskMVX=d7-!;p1E9+R1}7ui_&Ga6<8p@p!9 zN%80PfMg3Xl9W7B$w@6SSNjNsI@dVPo;N^4NSm@%*a6h;{nTpvK`M|6B#C9V3aLF|wTNxrff6o0HBN6mM^ zzQ#?YnR6NS7*}OfH6Jvl_?_O$?@phZpTA1@qcw zvL~?&uFiNyWW6gPr>UJR-c$pLOb3}BsfU2f=VZ(5CvYPCIT@~Pg&n3H#0ho4-s2sF z)At7C);%Lu4(~ugwVhNP=!1FRT1nW{Fm$#wlV^Tk!R+5-^6c6V&^2!$pDceu?}r+4 zbo(!O6IDg@4vfL=L$`@|{WxU5FD3B)6BO!|kjZ}^!1!q%Ia}BTQNJ${>(O=?lT9Tz z=GTMYU0y!h>Pon}GL(d`FNPhoAJO-|4F5Vekr{7dVd}j#al9V@9XxD%OD%mo<-=FVQiWUV_y zMQxsB;`-!3Ax#rMP4A6#E+O^#k@!mK74#!L7>jBYpoNS4vC5w7 z=<7!x>_8Wxn(7_c+M@&s|8>PLBN=p1Y#qKc%0)(IPB^(8qlPkTytknQP5N43zV%$R zz6s%*i;GeF3M2f%uo!KBqlvG;b);1*hwD5F(S9`<9Pv93y)FL3NIl9y=HVZiNr8)q z`?!v|pMC+&`%=bSk4QwibF!HEk7H5Mzc7Y0MWOY=>zOKE4)e_{C1xbxID+L>+*)2Y z^|InWB}~Uw^uhIeN%taWG;%Z7ByBxU)BWg}iO=>$=&4f%$JJ#X3Z#QL8Mjo?c3*}g zux=(|ZkKRIt@x3w+&7L$%mAp5i&HL14`8jFDRn`<81%m`rabp1LeDjSN<_sQBDV!m zn#%g1(RrErWB!6VUztal9+aSdKe$ivbLE((jkT0sWd}39ZHRhOqmL^Z-cWv!1;~Sl*U1xhPqw~VwK-x-+N-PM?r{aU7QITYZS=k3?vjk!m6@h)RY#G$mPzVKW*qsP zHbSxKNknGmAa!Lq4_9hwqxhICqPMM;D&z5jz31;zHP^53@F$j9awd=1sbx_4>IEeF zdOF3S3W#oi9~I+TKw5V!q&j#x*^=ctRK%NH5*~M(b7t%c?{{c$cDQ5{No|>u%SKt` zNyA0%m|q$%cl0m!MrI~EIYih zLxQvqtif)xe&P6co3L@yOT4#lCmzbF!kd%!;sqD;vGu#-I3qL|MY!LTI< zzjz!0bG8)WJijbh$dzgZ9+l z!j{RK(3^e+AOE%mZ8>`l+i|?n$>>XXiT!Srte1*gHta$6+t1;W+k26t@fjSw=^%3K z-;IC99zuEf>v7?%BWS3`0^fHyiW>ZNdHItk(1DkKnXih0=uvwmQ^*7&E&m|q(V1hY z)!Llt+aHK*&xdf$l8&M1)SaB$;fK+~irJLsPCxV?Pl;~!Y#(~9c$@NOe9-YLqg4Kj ztw_L49{Oi*MoF;-U_5^Kg6rQ(;Bv}GklGv#q5DTc;nD_> zUi<@`Ycyel%OseI-l0B6|AUtfBGd>E7dTuY%Ds1W25N?jOq4TEf9?K-c{M4Bj3-QS zM3W#o{%;3fcTE7DHjKs^_I&7ZeJ-v@;6p2!`*;(Nci$}6j=AUlfXC5ceB{s%_%Y7Q zjPxIaPrag~?%O9Al9DG{cly9#sTvWM>jK-my2NDc71Y&oh-p(BOrBUkZrphSQ5TmI z-|zKM7ruh55_cvIk?@~L@qDn&Btmt;=YIlpCC^n zFw`%Fg;{V0#zkpN$xTt z!0YY1I7*Y^o%g6+{KkYd1yi)!9O9~^O$iMtk(6U`9CuX-5^7sm5-ZI|X6lME7MX+i z!Yda>+xjIo%PwT{VtJXS=bM&u|r`5Cv)XF<(j46higg2s#E*r>Y| z{O|t4_pZGIS&v`1xnK+qOHJVEI({^N&Lq~@A%?bFP2$6}9P)Yp2S=<>MrSns;t5d= zbWd~=H!RmhFUEi1t~Z9rKWrR3Vv748p?=JE9_kac3smIf1j_`cRdxCM8_I#u^?Tfv5?~f#LPt154 zAP1+_c+*QQbbOTOBRs2$GW+J@Ium)MGb)EKnMOA31C0%ilyHPT_@tbpN)5hInai`Ox{JA#h%ZCUG18*=yq{5?_3Mj|O8@5V zRr8s(!2*zf`6@H}qclvI@Z)ZOH5lJ+h?lt46kE`ZF3tBc#X!=V(~yD@)Q2p98C% zvSh1dH2h%X$nfECSYaSb#P~ws^EVmdyY2)u|CS|smwmx(gDg=`*#%9;vgG9v59nPf zOU@;1hUt|uq$YsZ2^Sld)J&RWZ&?H_zB7qzr7=Jr`tZnGf++n}2D1Ti za^%Wxk`d_ zD(4m+@N2knV$D??+;^!YB<%tgUpxO#3J|6V*hQh~ADWQR*H8!|tz9=1BR zhH+daikGZf!u($Sh!L>0XY4*kGmBokGAtHnrnELNnWcwJ#(g(1b}h1$)6-Q)_g+VrJ#w zW602B8QIUBkhJd()6?ArBa81cjeB}wy03<*40#Xfb00G8);w>y-(4m<{VN1}-e&eL z8;3U!uQP*>e!>x_eCFQtckoS%Wv;pZg4FZ-nVsu?LTmma=G{!5zFJ9xSz82eS*+9qX3Teih#UG9uQpx*z-9Pibs{e*d`60h0F%~Tk&w{u_ic_ z#=z$T8qj|?0))S7!A;TAVAiY-)`#}Pl7njCerr8Ab7sTgo7PYtI2)!54WW5N8Dbjb zAaKnr@YWcn4)(~xR6C&zBW8lLi3fFfTmr293OUssf^asxt;BNUUn;!Mh*5F=O1<2Y zz_d}LlzqfA#zEyH)puMJOTO=-1eTiM??+pyYHMdaWb&MPd3HYr*LrI6ttkAb<~H>} zJr%22b183s9;Utc3U%do2_D>(O1bU4jg5jLDB-d?>?`L_+1`GP7o{0fb;|9yaH}{~ zs`&!v&40>y*YOH(sxRe?^mk#dNC9U+{0;V-4;<4+Z}5{p_l%vRdDqlyMUy74u;c9& z+@7JA7}s9sDi^e4L(R|J&d@d--XX&LcdQvNx1Ynf^gqEz_pM>vzdppCSB^1@c{tb2 z(M;y@j|%K|yOil$SB5=2o-hrz7)P=n8LO!4xQ5G*Lkh0q=6G3r#ViMJ#aj5Neg1%u;Q5&=v1UmERta2$8Qo;8q^pmmLQ?VBOG>!= zWg4#eEr5N(({ORXYo>B;2G$&?WX_MKVI#pzrURwmars@$l^dy8_=z%;+n$Vv_UCcw zz$E-4?Tc{?O6295RC62x&tsp}mei``v)IKnh)NlVz`_p;s5ZHic_>Io?w{-++06)k0U}>T$-0^x#buG7qSI#%74T_eq<4YnX ze`f_uZ~`d5Tq_7$W=>h}a)7V@@n){N6WFUVoRy1L!^)+hCZ?a)!u2=WT#K0hz_PoD zJ7a@0Y<%{M8*2C;Jbz6w?$7^&c)xYbA%15l4m`maXgkAkPCSz>zZ#5uE;9wk*T9#G zTTFQ8DhND$pLx2)0dhWfGLDo3$p7nRjCEGQ^rkON?qVBgd@YE-d02zzUTM7d#xn4J ztcqz13wVdraP`cEkX)gM56z{aa}$ky8w?@i`$9a}HW#8KtuSk>4u$3pSWbHuXfIri zTMtP<*`9UywB$6k_0J~U+W(O{)3pirKWL*KkuA8np`6-3!y8XFU7-#oc;nxpXQ^J> z9XR2r2NfN#4QF~9P{-GM-~~Dol<2DM_{jHi&SD-Wi5fO?YC$+m0gc}WyKgzZ)a?Ce-0DWu@e8&w_-}b8b7(`#`KI@Uh22xGoIkDKz~7~}fTl6%W#2cyxm z%XoXM8?!yglXG{YJ7d4DnKSQ>9b;=OLyZirVD^QrpwyxkGr!;NrV1pCnWUCTs$;Gp zlXW7U5?`vy1Rf}))<4!}xV<;2_bCcY`?4pL*;yVQ{r(+gxcnE_XxAY1XzUX=On8Fw z@4e4WOXY{6uB+U;VPdfLU^w@tzc|ES_T`@G+e^aB&{)riVwd`+~--r5o>ywMh8w*^Ja+E+r#;Wyud_tAIEOSPKYnw%;AJ>hd)7^IU#FzLdLy= zobcCs;C)^wC*#2ZIAnj2<8|Z!jA>JxbsT?CEu1vjCwUP3lcr6s3$ZP>YYGxw{LJfti+z%BS73ZESX5|q;ATK*?QU0fr= z-SY1`=hqKDZc4T+$9A4Fm$MA3P6Jh3qnqn_ zT@jzS!f={7!5QH;Y)WH#H5C}6^de?+nE|6X*2vgwS;;(Y=w=)2?|wG&XSN%uVUf83%n#+cxNKeo^PkjwTy`Ujv5>OF3K8MV)OK4;k4G}L zQtPnk@(70G<%W|i&oC!lz46=lQ07nSZmjYj@4ERQp11uR)A#HI7Hv4m_}K*G0I^Ue zFFOni`UEkuufyt+_@iY^4ECL^}jAM2QMd4GvDa`JUNNjU7i;+JPfem;% z-4}5Y*y?8%lhG1_y#=!vyP8n!K9s>kEepXj=Uim!B|>rO&&y1eMF2MZo5{$}3&3Gp zG8p3vzIgVEWM-k1FCLSKW9mb9;;WG{j6~vgyyJE-vp3ik+Z_#NR3@Eq7Y`7er|gI; zhrO9S-&SJ%`Ky@81?HIRzmQp^yAc0+r_3xCGRD253QX>VHon=x$EX>p;FP)n?geKl zZ0u3WJ!ATh5tB&gKI6V)#BbViLn^A7;}4~{9gbHS&l!74q6ESizd;S-nYngM$-~bk zu|eWYMz9X2v~Cf1iESF^H&`#>?-}%(qubEWM zZ5L{F{2eOB%%9TN>ZFc;4xu!Me^LEqnUvygF?jkfpPCF)giU(9+M2D}5axJ`8ZVy* z9w+Zp*C`{o{j7nya|~dYS0h#N&m8oJ8mKl!E4ZQ8Of}421-Y}HQWtETfEIsF{W=W;p^+E!r^_Om)bxTE%k*D{&f`A*bmJMs;J)2 z`yud1DHYbY8#c#cD#vXP#L8Wx66WlJso@-|C}|tKEKa9hWx7MHWeTNm%oRQlou$h4 zoZ;n`(^RgOEu?(#rWQf-B!AsR*)sa@w8@-WAgBuUM335cNg4#^DNqL1 z{IHkhqn4mg)JggGobt$aO1He7^XNl4HTvWNN3|h?s{fwPnSVc!3Wy5fq--1qFKyg#3{x_ktylQoIp357^SFlhNsKOl_-5~4Q?W&i_g6uHl@oF!ZIVFK0D0hdO!s za=&kzN0;3faCxiDXrd?w@U46S4ZAGh{^Fa{ac2Q1x5bhsMT_EYt`%Khy@C7WxR55k z_2cZeT2kXVo?OirN7{eHgOe~{Mx7F!Ih8{$)H2PMTS#oEZOB5dGt`0BbQp0LV;tzc z)dt+12Ts)AUyEC?#Es@oQRejRz3GM&8SdK=FB%m5g(hruqi-cUDD-usYo^_$f&@33 z8T~u0ta73UW8!JJ#tM4>LIAD)?nL)YGo&S)C5?7}PPE!hX`07zqIJTM4y=&Fm37*5 ziL(Y=DA1ytHdetKmlSCDF=>?iK!zUN1W}~oXQIA&Eh=+tCL5c7Lw63>kUPh+(Ng=X zii;39O#z-s=pgvb;zs zvW%V1p0O7rS{1X{9bK|y!lpT_z9+*`#C%b�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 t-wdg8ZVo9N8cvG+-_p-ZeQEi;ca&D#hyIOz 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[ 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 z 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%0A#A=Cg*Vnk3Ei(p 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ξ*hWQHjM+7Z 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%0A-G=90f_i!?OAaOy2) zgQ6Y?Z<<50W4(#ep_7!y8q)@KRlNN*j1e*ZNniA5kwtRr=st0MX7CQT!!f!^<82q< zs@_g|>5~QS=onzFWAnIfb2Bk1q>LhQ1)Jt>W3^;Unu}4?uLCe4w5^7Qa#xb@~>gW$jD@5Vh z-nmfN5ksWKTFI1>S%lpGNG>V%v3duUVU_t?IzjzE(B4=?Wr;DU$D7mBB|*?!nnJtd zPJwFgbY|Q1OjzifLdG74fk59NbF;??vMd#esnb%<<8X*`NQ6MrG8?kwzc6qKY~#;) zzYmVK)v~-h!4UX&8w6@T;?uw z^_d_j4~iqtJ_F)@W>UGW6x!V*tyQ?L$30~{fx zGZPNv9ENi>{?J<%N4~Cgg0<1DbXNOe5H5dBqieRozc;&S*OTw$#(LLag{Cm=jq6rj52RawHcF zl)jPKT@jow{XUZ-J{PQXQ)s4tJF%WN6>nCildL7b=-$&wME~G46nMFn-0(Yw+pY`I z-=AGkV6_A-pEePt<=dF#Cjw~v_6RxkMjR(SnFh1nO=-pBH85?G4|&6IUcW7#WWaHZ zxP3d%WV+5JUrlfD3Km|XKDyKBwml0`?eS|mTJRq_UUx&8qdVC#*#r1-GRuyu$>81f zb@W!cGRoFZMCM@ve&ij);3Jhde+kQFoE!1qvJC7W9m9;rTkx->NZrb#UN{ujhHf9t zaIaK2-re$=%5Xh0nf|AAUe`tbT~S%=sWjxB*44lVPN!LKeO+{qt)^PG+|D>rhTA)z z!J|PP+}@}dO%8EPK{gvTxqbSR_WkH^{49#H`!L#)%gUb5!wS5H4`1HKTNj5>!{aL! zytt2pUtc2Bgkcxwd3dO^7kzEqabun-hX2Xnb}z5#9xmUk*k*#?%M&?1n?2T;Y{Q(F zBKYrFHV*t;g0)x2@YjMWY_Suq%a~M&&HdfDY5WlWP|f9@gIhUY$QqoH9f3ick7AX| zepI|)g%iCx>6)5GT(;mP`{YS0I$1U{YZtWQuTO5wyYk1lvRng?-TsVyOa@w1+(u?s zC|c(>pnKXXG+W<}0hPg69n*>}VVnbDl#dhp<8V;88U_6mP{h6ki#fjZs>;Xsuip-L zE4{%iLunMd+m4U6wX!ib6&RLqlvr@jOP`M>R9jdZ<$GL^zabAlOxuim?|wq9IiIQe z-61Y7Er*{tcV_3eAoOSut2=Lh3eyVSp+n$uoRNASf2o*K>wr=;7#1ZO1ux)`B8j9rMH8lr1o|cX# z$>BU-w82jUoit;GE56ovMW_7DLIurdY_@e2T8$0!yU+RK55vujj?-EEmYc+G63j)5 z@04Tlu19s9X8Jro7`IM!rmuv`@Nls`Yy3PFHI6P}s|#Fkw~#Is@0m`^s*;)h`X1sn zDhhoe)5!GqTR=kRGa^(W z5iau|-o<{fdQR=f2B?5j3Z1RI0|)Bc*vm%`;NPatOiM>TE?TTYXPewY1EG3axi%M9 zOnk|hom57Z3<;R*dYA1OFooJ#vLqwQ6uy;ACIZ8f;MwlUzD$*YwPrsUd&wP8z;7jk z7F%I%S1M)Vtktg_CpEzEb$$Yx;jsKDEXN9s783BiN zjL*P4##`$Px!K3{GySz;^oA4cKP?Fc(FM@fJrDjoJqdTN?SRwn-f*m89SAJX0!wEG z1be+8d$R^~rzn8_yEbz8_hi^U9!fUWt3h$rWEh7P(0%L_j85GG`{q1^FZc4{=K1%a zZuJ75Egk^Jut#u!V*>3xdky>#2%8;qtcPb?CCqH|>!82oE&PE@u;ljfH%o({+@~5; zb_K$Mx^vJn#TnN9%Y$Q~)*#EVm*YqNN6~r5Q~ADeoXpIGjO@LsjPqQ#Rap(uvf`_$ zfrzFCGRg>rgfx+m6mg#GR!Py25KW>qRcLCc{GQ)`{KLzAob%k*_4$0>pIu}U$6C;O zol6utG6=uYkqE0EB-2l^kTY6Erc7K)?r67>2^To8^vOPwP}xQ_KmH>@9DDBPIa&Ly zRiUKt=`V67b1gZ1^E-+CeTb-SmbUNW814`EO4?UG@FnXuNZB{PKSHF!CfKLV?jjbH zl5xCFp03I#g?*RF*{|g!r2aa2^zs4;DT^dmEJ{etLOzs)93fqc9>6MBt|L;n6$H)? z5Sfx;xN!0%(Ju)l$wjT?L(mcObg+YXt*j*xTVIfv<6We4eJhv$=_YlrC}~Q)OiD6Y za)ir|iq6R)OK&7|z7K}{@m6HSy^P3QJq`A0V;K1`gJl=W#gXM%A<*p{M|yJ|$da{} zi0}CWL~PPW^0gXC-In|0j?N7t*~2G2l_f+l^cu&SP9bY!&XdjiB1wPxIkI3=1kq8y zNnW3F=k%UxlA88^Ejf-{{^d#j4xc6-XXlfEh_B@779(PJ?F$K0ehqOm8;PpYSBU>~ zko3*ABQ}j&iK6~r5DVE&!aG+1n;K7yTr|ku-+Rg96hb7oXOhXrui%qxF$vyi&Yfcg znOxvb1_H9U{<3Xwf6F5BKCHXWzn({qXsVKTOHv4pNha(6-XzDO){^&~&xlXvdg8IK zg*3G#k)0pUlIEsVqWS4KnbeU>=EtRwg$ok7%yKH%8?lHyG_E3TuNIS42UJi zyq1Kk#E}Wcl$7sIASz`I+-rD@Xu4ODT{=fe_UL|6u#wZHR@#uqDosFgOvz=JFL2C% z135j*irnquI#h}#5znzD#DvQQyD7(!^KV_jPbHfO4sHhjO$WHU+ePSUVaS`Uli=S{ zeR6xYAgo-HL{4{Jg96hy5)P-JiTMe>f^#@-wG`|w*vZ{{XP~|JbG)1W0k_S3#z^O- zqi4ekU7*Y?`g@)g)oZ~Xtt+UtQ=NKeF?4haLrvZ-qFo99FyL4fir;#G zyp4g3v7Q2bkPw8HODE7(XOG~qn z?yCK49M^lTzi1{qG}wqQGd^O>S}Tr&<4PSr3Q+aTH)wZU2d$#_;P1j4C^RV&e+8y; z`t*K`(mYA$gh^4)Wh?2EM}&sjZ=unPJ?XE(1N4Pz0j+$PKySrYaxB{r8oV!_wqHr2 z9r-a-bMtw6K6w%C5IIIK(P`AZHJWP6?fL&6mez+A(Zdst(7549dQ)v3m3VUqg{KA5 zwr|@p>*5@$GcH31$VPhLr3n4u*+|#i*Wo&2MyW+xEUmB-YUqnOK`m=OQthGBbguq5 zZBs0wVnGTGe^+ud=Fc&Dn)|t(mmX1F)kNCkCDzb7v6zB`Zi6kkNyCI>8=9Ky=*Z(v zdde$|dxo`8t?z^mX7*Eyu|@P?eG~0pV?y64XVWC9*;K=_o;us+)8LTD)Wv=!jS9a+ zV|w)IdG2oVL?(_-UG{>?kA>0fWugs7D+K8Cr~hc7NiAOg?*?6PRhjDkuB5zb9ZFoU zP{Ebjw6L#%y5$;BiL%Rdb>9;_&~lGDwe{kGuvTjMJCaI1s-pwZXXwA6%QTqtvQ=od z(>l&yV|e5|)!sgp2Hwb|$s)p>j(3WFyJtcbG|tdpYj||Sqto<0)u!ubWzw@hMXC9& z)l_KdeoU+krgvX2#ep9@Dy+=0s|Ux?=(jNYKK}?_YmlSdRUtt}(1( zC7b#12RJ=*WVaucCf>Qhc%;;l{PrKktvy1-es}>DJz)S={Q=bIR6QeN{u1p&&DrN` zCD2&c5A!Wg;|=RT{Q9jMsZ$LbZS#)3<(kGUeKG+CpVq^PhRb}j_Cb)mlY&cb2f%03 zM6Ap`!J68w#a;2YaG6#yj&wi58{=>4e^qO;U&IxN%e>tXb;O9sSf67qozH~4!?V$Q z?JC%EU@>dyDFUIJCUdjgX%tMl&J&wtgNpWMF!yLKyxO=LqQ+ZcA4p+r=P|gceH_E% z_CU$;6PPb=1OX#uxJAnjJ1h%vy5a_GxFd^?)n+mWz?z-rr3O8L+tISQirJAaghPYN zKw-QNasz(Dxdcg4`tvn}rF{aCdDG#Dy*G3m|HEKz3|?Gz2{N5lqq^FANb-(>$zjr9 z{&FY$tNG4Xnb}l-WiTCXMa;l39L61j*9Pi?auJ^EPx(T&Oa|Zu^;?%S423$VegpWiO zh~Hdw?0WJYq9b?N8T`Biw|0i&)1ZG)sa?+QJ7`3jvbY(QZ%z_D){;*i_9S$Y0omO& znJh^Sfk`r7c#+_RN=AR!vrk0n)o-_$=Efy-6eeOPmnrx=`3nXgv7?VV^l_)eGaUcY z4q;{f=x#O$;=}T|W{DEyy^X_w!-t?Rp&c~>dZDqq2^NIJ!H5KUXN9t-adKc+P5PLhUB;{T`M;n^iW{ ze~~7s&elXdO_@|0N)hjopTOmiNW$HZkTH?Vr*WL7FV31|$;Z#I-}^Rf650S7JLJjb zpn4Ga?m<@Q7?7`>YsfEcFS1~4Gm(3sORk>|Cb3cdaCeym@w^uguFGQB3%260W?wBv z9G=HA0iT)mzeh2yRg~yE8_}$dXBhpfLUhf(XpHG-Mg^IP?8%L{@zN7zc(imALTD2+ zZH^}Ub=VGse#h{|)+m!(Ze@TC3Pg0@SNQnl`X!?Ei`P1qj{ZeSsIV%IkuD{CVegk< zf4B_vIp#&N&LLQ1Ye1x{YCz-cCs22sNEDoIgTrHCaz6;+fq)#*Hhu!Jj3j9Y?1lNa zA3>Cu4t(8t0bZ=CW;+dLv(~%jf!W8S82jFnq!oQ;+c{t5<KD(!Kv=U@FWhw@j?gU-43N`VIO`%4TomQbQrCKg4Pi*I2z{Ej`n>&T+ShyrciTZ2`e9$fE; z2whfEL~HIIpl0dWwBuVhT_qAlr(55lbMyDnmAoQa=buiq{Fl&iI|CXmQiBVsU$W|< zDj3g!r@b|D*`TFoP-&SnWBP{MeY{D-?_;g_bdfQ=F-@8p=f6cGj%Bc9Sv2Gs?7_5a zVq`+?4YvKLK9uyGL@$Xq^$Xc4v?|w#*P|FgAAB0dXWSg!ZOG7yz|*vxJFkZZSLq}J zCz`sWi&jhiM*~W0=oTF#I*;>>x!5aE$y<8#@7R6LcNRc3eJ-N?(0*F2)`Mn_esnZ< zA$y!ZndW6KhfC);2CZ-+bEJz<|0fBkv+*~MH&WEQGauuMs@b>~9OM4F0@xKjLf4?1 zaM$oOo}8jW1jl~j@e}*u8OM^Au9BEJKz$T@$1vhLD*&|lII`nv_;?2ImE={70g9Ious*VAB7W|V(G;|P(< zM&a-_VY2s2CG9NSW+n{vB{8)veyl)%=H`Ff|Dta2@k~ttw=RvJ!c= z!Hu+RnhRM4)5-cT>zK7uT!{ANUfANqabC-25jlHfqOd8JxIULA`Z}@Xb#Ne=9kZ1T zCWjLP={%DENro(PNhiC?&VtdByYRd)09G6+WI`i^F=*XtFj8~EDxG~y^`_m-$PQ^J zY|m#-Ouh$C*8u9XRN z?8!Ft$l#;y*mr)1!gaPmxC`h1J%!O1)v37UY$+7@~Tt?@JAg zEYYqjot6P-NA9u_wzomjGzDL9odE2|Rup+#!0Sq=KpVvetZ&s19OE)FLQ3O!^FL|o z$FYQ-UfPcXcWz=!ehL~6CpoIb2Mj9<&;(L6i}_pT~t27lM%bkFtZl4eMqO4RAV zikEJ#qOe| zoR;a5u$;v4^8@n-oT|1 zsrY%87hcNm!B2ka%pdNx<`p)v7rTOKdBzyF$mme7Y+1Vaz8kV1kKohJU(6?)v)JhU zjT!3^qWpXTaH)Qb+p?#C^}%F(ylWC$l*X_c{svfEr40FIMf}R-xv*zJ08G2M5u~#@ z_RYyH5ENs?z3;C=ndmBV>x&I(ySkf1PB0;l=S7q7&(+|QqfeeCw!=xz7y7W^6a;Ww zBJZ3K=JEy~;6xP2tK$C8cRYh6cR66F1-5ciXf zkR@LO8=rn)*AH>N!a7~b_nSjSLiDNSMxcwgalHJi9e6z487=y*V#%ki%*1MOsy8wh zW=6bc-yBPYp^DG&XJ|GopQ}a2)i|*E_r;`-yWhU8OCxP@O2oz|oAgVYlM5<~$<}Zg z@?yzZNYJ_s!)1JUr1uQmLIsFsa1VG^dBIYDX>jjbU3bCc3EPzv%Dj#~hIWV7LiL_4 zD6#wztkVx*XXjUfaD*718Lr~(3lGC#r#jw*oL0=4QUaCBvhlTN87#T@ixFC|1P+qD z%-y!xtdILOykeqH4|%&&8(vU&*lan~+TMD%oI7SELlIUxV!}Pl9X}Vt`n%YS3 zqXud-X#3i?s4Dy&Q*Ya%kKZ|b;I55QohR9Mq2tW$eqUIjeg@`ze#6A&_(7~gIs0{Q z7=OfaA1`r@Im%UpGD4e;F>J*JjNPxqb!NKKgs8iU z63)(?Mi=dGVohx%==A#+u&vshe%&NXb%Hk1a8`+9CJWMYOW&~4E<^Q$Z*IU;$(PLL z+%xcdd%8z|rHQXrj9WJ_b4AS`9us zo;ZO~;_YSUwNHX~`Yf#5*bHR}KVhEfB%--11)iI{1tl9P^84Ecu-WZL#4_(N<)-h4#Yk}JDq^(fIYhk~0?iqpm;>cvAZ4J-=r>A`K)nOt zb3K+Q>dKQJua}VviUH(T{biuOb4gGAS+=&@7aBy;@u!9_eq5@FL0#_b)5EolPt<$6 z#_RF0^jZz$D^d*wN%tZ3E*~aFY=q^*Mif+?6aYQY4nOt|UIvn3Ob5BdnMb`8Gv?%s6Zawo99!FycMa zy=yUiaXJL%Tt9V{gF3_4QYCl(CgKG9*@V>!z~v1Y(0%0^8)evTwYqBL&PBvhRxN2@lUL67P(d^xFvAIN@U^>bW-o!`VR z%Xa0Tv@yq~!o}EOUx6PZ1MzjvSKP8%16x;rM4pBwUca*jufFEkPrGzbXz3zU`5{N$ zxk>JsxfFeRgi9++@H4fAa{meRO2QK;ZL!8)S21#Rs2J8nTENPQ?(p+S zA?gie;>91wQ7?EKN;&D{(H%xOgD-^Nk4e+6Vy+W&>wH?z&GW;4!t~a*DAJeS!8a5Y zCN;mhKyIND{HeGI%_r;G<>d=-d|3?IskCEsax6aGtA;X7LwNd}4|{qGj}G7OMU{Z- zIQ-X}I=(r`e7Daj>T4VcdjLtr})t9kW8#Ny2c7*L!;ir3UaL6IKme0mxjObp?yh%cMBhnsbpWa!c3gD6@tnbwv* z#{tLlXw!ET&(GP62l98Z?~>P|g_R#f{7J!vj*Z|Lo`wHzs6tj_9kvAsLiVMN=(fR< z7rJIW_B`Lp?p!#LjyW{)+y$C(+xq+L6yYLvM)G64sdf@KRLF9CZ!7vt>Iq&Mm`VR* zc^F!$O(hRq!{>UVSWhhJrM!12Z^hlC?@y%(8p!H-Or(E9k{SP2O{_}V#c?P1Gb6?} zaBRg%W{GqTyWDXhob#WK{;j1@l+|goPiPBR`)r4KZb@ualO>$-x`=_j$t-KZdCMe1 zvBTF2qw>A6v~U4mzDya0cUeQMOFl^b(Fc3)SBzbO2YjVBZR_^zg`!{$cs5r9?!BE4 zkKevyOLzR^hjx@A<9m%KdMW|;*cibsv2^xD~_d*sDR^_}An zzs#sFoFj~~8#-7+hc-5jKMM;ikFir<9>(htm6(1x4!>4-V(gP?FiUeYRM>unxzb}` z>JSg7%<6%(>#-5XEO7q5X7*mwbXszH4C?};sDVK;-M)(R*xTE4yLTHJx@#}%rJ+IZ z2XA0je=Nfkr$xMw&53q7Nnc@iT?L%j5=^$Y$dZ;b0>r_z2Y#JU#4Vfb!P@F2hR)VO zc1k<8fh0X9B1+HSc!S|$dbDMG6mI6SVw3zo4~@avImbc58VI5Jk-OjjSo;NwGhv4`@p_`7>9}devE?7eSVQ!1I{~N z&a8PfnTAQmGiQf1P^e533RfKllYd7b8CB}1X$>$nrN*@Hfdwv*u%Kd&FWHlsMY#U> zN5;L8!Q!$`h$14mR85+k4|>6@ z1p+Fv^m$Vs^W~^J)o4tC&cJ_|laLM`cQasXO$_u(xsq%8Jkoi@iUbC2Bl_i{WJ0wz z`NZvgD>J8%hNJDwd|y5CK=uMtHBFXS?aT+4k(nH;q6A_;aJ^bC>da%A!>~m9G27++ znyIl|h9&#Yg4N71EE|mhxtc9vfvtud=w$-ZdG`2gArNbas{8i`w7)#`MT)K}$v;JCN)@!MWOf z{fYjF0bZyQC2I!9Fw$fn)QpMIMfonUH(G^mide#oXlT(P&UY>?^c7`tPx9t$x`=r` z*Wo7{hdWAyNP2h`Hb;GhRdrpsckviRo)W~3I%D8HcMlV&U`Ng+iJ<$?Qc`>^97nFI zkePpv;3oSR=$1W=#%Jo7KjCvRGdmF`-#myPMc%@$@ebS@cn#+J?#E*_pBV4nU;OSZ zxm=#ph&?)f5JJyn?TRI)hl_Vi6Xae3?P+$LCS&MOxN@t}u{pH1O zea-%Bdk)*v#@KHeK}08h3BSkkGAs(sU^2}XqH6nfet*zRtkX+HKR+L^Y~s3#!kRe# zN;Miag#dH8j@^2snsJzy$D5n>j6GpE&2IY~&iAVPnsj~qGWNRgN*wnZVH}26;kntNV61c;XLwq| zXhJ)GZXB0EZ2JrER&hBnD@&wi#g#uT*#xjXEq8f=Z;f^REpSiRkk(J)sY zr21LZ-;)S?jc(Z4Tj@fN_aSDBdkz1ziU_voO@%PkAhs>^J}67{F?)|Rfz8Dm?6=k| zh%%ami=U*!;$>cpv-@1o9u43(M##dw`f+x~3uTz^!e=tq{bSF*jAcfHRp^;FQMmfx z8*G?&3&ZYIGn;pmp?Rkd1Ql(c?J-(*c_(HEX5>V9Ok)g zX4Iwkp|$uVQgG=V^RsXcsr7#d{+gyl__hSORILo69gVO&Gy_i_`onBF9f}f1#hKg7 z4zQ9tgP4#|85|#6ga+DD$Zu)D)F4?1eqPV}F4k1PdNqf@w|$8>LR_);TpIT5@x)Qa z3Ksa8v8ld%W<$w4zSW2-s-9Vf!A8T(oi#eBs&oU?OWnZj<$I9aZ$|FBDv`o;7qa%S z8QIv2ZT81_DO8 z&e9z|ycDlZ;FWnE|42K6=k#;fJim)$2d;8*Htb zLFP!@1k?2yq(yWxQEJE|3(s^x{?i~bZ2yU8s`d}I3+bb}k}}DX>|qms#}S8wqs(wj zEE(VE#@d8WB9ob!*s{+Y9J2T1Z6DqwP@++pV zfq}@=xbpZ{ZZGa#NEVBAI{EBvM@Dq_Ih^t$ z5lT#j=*f=dJcYqHG?6T3f1DS`qUmRt+v0h+rK^EIlzG{DkxnhU=|B&xpZf;V^Txrb z){U69Oe8TME8xe=VOaRtl)c{T1)Jv;^342enI9YrI+^Qlu5Vq0{2Z|Ok9W?C#(O!@2++<2IwHn}{^!E(%8poHt}?Xj!*FmD~d z1Ob6E~8gl{LZ6{FHZx?g>qcC06VUM%?Id1HO*lw$jL!4qcOkCT~UB@SimkBy2^Ws~Y2mh)J|uvz}jDJ_D^F3|3SW zps&s%c#^u9F2C@RCvYHx+VlRy%U2H2ANRSgsmXElV2U8^_~}UNt?uFMA{qKZaX;3( zWMFK5FW=GN312>B2RvC@$P}=AaBHt-az34gBqaL9|}0`(g)cX$86AN-TNOWPi?O7WhIcJB?g>q`jubKDIflFdLu zGTrlJ0?itkMei;0rbn)5(szvtRA^lf9yn8s`_&q-wtq6xd~rIuOOrQU@E4XFnPcz# zJp6Q)}+tz^HRVP_*10`HlJBit~QVX}#9K}t`6mX5hIGzev#?*u>vDe+t^K_@4W3~s6 zvzPDg$KEBcSe(Vfv!%JL_jC`tJh@u7)wT(bu6l-MA?s*O{|MU2FQe~vr~q+!j(QH= z5Zhvgj>HDu6*K7SV+fm)4q>ntm#t}yNA-em;#Tj%Z|GS;ek85uvi&M#`Ly>;+5YE{ zGk%^QW0DQd>wB1eudKl%%89>GQ?7oK-fay28IP`c_H@D9YxsXA{$Kw9yzY1j)%^rP z^Ymr*>lr@~P1u9mj<+!di5o99f!7dQ4#L}VAmLgZxH(CawV4Uba(^*Wtgw)s z>#!H5nCxZzC4J%6)%EZvssPr;CxB(HAI$dC#obSr!JLE%lz%TBO1ioCdxblgRV-r+ zUncSIm=Ck8eI5H}V=9{;>&?{g$C<-@HcZ1xd(hsLz;tiZWc*j>LcpCA);-+@o|IX` z;B*t{x&Iv8AG?$J+eYC#m%U>)2$6L`B4jPqB-LhuWZq;w@@9B4iCD+!n7xsZF#S4g z7?OmdsyaBSsYF&jDuJkNo5-dQW6;0Nfn0cQNPbNy1CMVq1n2Gt2Mt4#!TD7y&Tb&b zGnbGH7U?9}FqL5CAyO*7kNh_|f(YF8CsyKSWO=g>@qa2sTn5a^`c3jAW^XneJMThX zv(q3(GMb#(dI*f}ITFmc4RQsi!8xQ4F3Wsja+ejqPUMGHL~@Y=kvsboqz{S^L-}r4w9$~fRr?H?LUvpS z+6VABCq)G6uflF&j=j(Eb8{~_;PU!H*4>9L5b!RJgtQ72qb zJO}rw68R$~MUEfxBbRq^ozbzIxQ;XlVqIZD3Z{sVhu(#7AXb(9-0lfVKNN{uVkJa& z3Xpi8I2iwV5r(c=u!FS*Fu7d@Rz}T(htWpFzN44xC0j`@b`i2*yBCq&9Yp5l8IsvH z_M|lVG1yv5k~0HNF!o|5>^+^%%-Z;Z-FqpRT@%pF^d>E5Li#2XzEVGYoFz>RV)`ZHheqZ!ZK){9xxk&dPF_-GOP56{}W(3uMxF)x$jkuNXAwsTKWv$q7} z^LFCDAZ;wxIEznnL-6nIR*aq@Nk`4sqjK>-w3}j$f)0f^@?QiNWlGx zuTbSzDE=ubLDLo`_UJWhjJqrWt8L2p%E9GuXT>#W(>)K8>@|qCGlZE#A*{8756^Um z3r?OTiK^?3Fla0ro5C)j|4l#K?of|0P70_Su@fU>KH?#XxwytghF)7|hW_{R&|%Lg z>$ZG9PTsl*r&-;{b(TW(QHveT>r|m8amlnfT8y^8%A}EzK!p;vP-g=hdbiY?{`$wq zz1@a1^L-ZT)7dm7yBhx+_odZ^QuLEXC=JYWq~qI6sCCV6)G1tu_fJ%@^S(sjYW_?1 zvSKh!_31OO>3ve&#M62U>**wD!_$B=yE2lq+4(5rWkluUTbhH@x zj)E|AStTZD|Ag`flHBf03XYyJWQDRGj~%noHrf4^ZL{2pK*tQDi0EAw&UiCcKkyqSOZW*W1_3V@Lp zhw`wqY^tRZmI?~c1F2khT!AIMV5&-`0!(Oycn5x!m_*&jyYOM_d#sMKrh%#@c*%Ap zjdOm(Mw=+no>dHoNjIv2 zX(%$2`+Jtwap%ir&!0X+aji|@)|biNTh$3_p55TJRf5QuJ%TXft6Xn$75Fky%!?K` zh>wxxo8s1&M&Nx?wz~|WQ z%)!D-AZio_LrKR$(qKJ!2R8D2b+58bCHL&M*xtqNUjfkFbRSb>=D}dvBGfh!=1RkrHCOrJ8tGgI^h9Rt^&gDfZpHq` z6QGhwP}Xf@FRKQ-i|{=6EFud0dPR|X*T zmGg4nG%|wU?=u%qnZS(KnJ}_KgcUbC4I2tNczla|NST)l({i4{HQ95Z&3^^+6J+6_ z+(a(BcY|5J8OWWBO~9VAC5}P@+f=40|}9lE(Vw%%1SaAbWH_>+;MU7^et)UK9+{drsn$$Plne@5ViQ zb(rrv73f^iEN1mCX?mwL4#Y$!Q5&rekbPQ;kN%000F4x|?wCp(E_A|lHCYm}ZZ163 zn?kyG9O7-}{6%E{YSeS*b}Yrc_`%s6C!ABF6_MxJQwl>kMSlu17iH~opIPv)b9WMf zcig-kY7sQKfcYs@>rgF zHSpQ*8uPGFb2j8(p2s}Mk|Ul5)m&$hG+DY*nk|#*fq44E?nH_tIUJ@A&JqG-zuju| z=~RNIaE3N3ujZ+bIMKqLr`XxgY^g{`3-)+mZP<4SOy+6Sf1e&?|h^G&V+^*32 zN(LzP$l^%2BB@Qz$2IO!#K^WCi#+ade#jH}RWuDwoh@Z8bhBWEX%BCnSqQxP!8!Nu zJm70)oyUg8AZ#(*ghS>zXf2eCy}zVzM8b%kpLUz)X1$1hJJ-)R@A-(fYY~dol(8uE z4;*;ujb}b*f<(h8ItUdratT(nUn8Em{+dUfG%xWY7R%D#OM`Lq>QPL)IfN^YDAH4V zxo5bS8g+isgkBT=V)6!ee17dTK3Jm6NY2Q|ZI6~fLrFKDnGy~LHyZHa;Qe~Z{b%s# zAMUIlR^a^@V=Cr%1oeA0ssGWd*m5oo>pk0XbHQvlJwFGJpO0kAZThg8^CSM6Wi2q_F4GQwYh$@?%X1}H+vaXC|9M&`?RQYTphk(`Y=KFC)@ut z0kxl*urj86Hf{cCzKTUN8{=Yy@`g|GfNdv=+Z#})55*X-eG5Ab0@;k#m+ZRfhvC1L zd1&XJ1^bSa;H?}PT&og+-tp#mX+b>uNM#S`B(H@NJ9;7FcpntJset7ZkHMn(S@0*x z5$f!Jz`>-&ATY;>l&Wn8v&U~B{N@nPGpriMuV2K4f6hQptv|h0lFFYs@d*7n?10rf zH_^>+ zaGnmGAMksf2;LjL0^gH^u>Hp>xapIJ?O}y*tiK&kJC$*qrym&ODF%}cHeiB_0!Uu5 zL~*knu#maW8VhotBehz%)HeX0W-MYKuAy-7-$qtPkq>7L)#+-9J8V)|I$gO;4_)Rb z(@z5Vkk#fx_b%YxTb_pWNn{^Hf4h%w&4o$uKp{?AX-phyF0(n?)X1tR9_*g-7S>*I zWtPvF18;lw<5yi**f-?{cDkJhnd58l($!e-Npr!o4@%%cL=HL&h>`g3obTx7eh{`6 zr9ay*@z>RJ_tH3`xq3U^)L9LqSM*V~PL%jU z5%6jWDcy?j&|xJhnq>^TKP)0WPL9mVS<}d_uU@ckwhG~W<5;O(2C%TKoF|oZ1P|}K zh*`s1F|D^4-yGb-WDYF1Tf<0#@}@ZW+Bs}T(-y(N3SDrVu?zNGm_RaVI>f)9LY&uk z)jQs^Agaq$*p{P7gx+rhU3!v?ZzJTzgc2fiYA(5T=`1l)noSgcrV-&g4`7_$Kth{yeGcyUmlgtu}1P)d$O?z$cM6=g>LTP{EvrYn-A*An64dJ(ee zvlH`fBm^#LtDt?zQ|A0LVGO*}1$H@c%rtI}Sz_W0-#iS-qlj?$^?4b`=x+x-t!Q$g zTA3Wx2q5{o<1lxPG0|Oj4~VHeae7q_O6zTjv&IRqUAKUoDEk6;f2or)&t8x*9D<{t z&cNzTjwHwCAE=#OM&fkGpp50Z_3|ajii0c3&wm{I_DBqQvX1MC)Mv=M*|VVKycnqr zNdk=%I;7_1HCXX(Iw`RF!o2u;6}X-W_Tw9MkP#7pmo0Z;{iGKVnJQ1Nd=Miuj-^3E zX$k12G_k=UMr@q?7VKO-2hUX>V4tX{vp>ExLH^Br@IIzNWK7iwzr%zmywM~noV;?o zeFky5@BrA0_GEmn4Xo)iCbh$ZaCn&tIn|*;R&!sA`;Ed@jn}~II>mg@?g5^Y4SqKB zhRljz?DU>$hF2(!feOl8_jILQeO?*Fk8K3awSr_}u@2m6dk7)rCNMT5685`VfPj?; ztm)i|0-7sf!W%i-F+0;Xqe_k*irj=5*;4d@%p{zrBTipWX=GGmn-C|3LBFUl{^vah zb|r-~>4C{`ZE*P0V}77r_GbRQt+q5pVLkut_$_P-9cD6JuCR`Bk)&livc^SV8`mp$YU(fk&bQ~8+gHV?kBlGw`RPwzKVE}E!E0#oYHfTt!;)qz zu4TCN2A<*e$iE)uGOd;A@OJ8sddb%p;qKDoyaukl%g?%!5n4IK>wMYIYWDl`KIA_{ ziQyr(hSU4*aC3>I$7fFOzRS8^P@#WwlTfU9A(yL?p-$hjXll3dJG%dY8a8Hp#%}R!#{TYC z3>>)u6Zh-Vf$<+O?OO!BaMll`?x)j3{KM?@DMr+wGXq;xtMT@ivzU3qh8Az|z!>E$ z`mS06zlmhfHLIuM?zEk>e?tydCx+30&_+BSKZE|4QpKbse?sROl4M4TJS}*`hk~G) zbXm)5ySW;AwCKtdCOXcDuC&)?Sfw4*VMiURnWWRA*K%}KNES6pZ^W{I6ZC0H5x&z& zpz|%apof$ybx-8MpixY`xD1*7>X$Ms2O&b{mhdFt(0$d+`^W=Eh@v zRtEN6RYb*9QKTWNjK-{0m^a|hbB$=lbp}i7OZ?>MI~`eE`beGr2|a|Z>n732^69wz zy&^sAV2fWGbZF_zOBnvrmd3SF%qTUbKWFx#oT(f=)o)41H>%LfmQ&~}ZzXy!gkq7d z1}#t#q*bx%v|0Byo<98m*OqSNr^cJ%ft(9`8G|`&RlEns(>}_2d)(xEBp*P9hOdmm zMLC+j&ygP{3xkk_0AIxo!O?3PzdTRR2YrV{40S`?R& zJIFMs61HP-FP!rWff2=NWQVH`F`8>fJd(e{c7+P4b(e)JR~x~ydy)2rBkDzFsF!cUWCYg_inV^kk zWUGEAe9V+1>z`GE@`wZ}7~2Y&Jbm)&XCME!i4yrICxKZDufvh*cJ@BFfMakd%9*8r z`#p~5GfRS8D@(-R$wuVy#0YjF*X5;k@;|usX({>gV-RFs7LgJ`RZ{)qCOI^H1^J>{ zPn?}MkjqPQ$Oq1A)vR-p%-LyAqEt#r^E(UD|2K(fwf*7FF@RX=ijim$FVZ?sog{MX zrKkpNax*B2tazqRBs=0ru&)$p+dqpusVjrv^!Jc(r4SYz7_!GkoJ5+Z zl9%37$mE8Dq^R^GwE1!U=|Y@NaYda3w><*YnHD5dXDbNU>XS`(1VFAzftUpObI%H8 zQt)LLKreS*F0D*yT@buZ?_>9wRl~Nf*Q|4j5Ye2b0@o!cl1=#wA!`YjFS*C(<)!t4 zNs|TBX^;gTj-&NKNmJoZbOn~B=)rI86BsMXhrld*SgUpm1pQvZmr0G#=w=J`?jPZS zs{+>fKL&nvD$7sSBtM?H!P?F1$il?EAUkYIoRS*Tdg}}8 z?p1>o7cx+>wGi2#S8z|dJgqu2ftD?^php*e#z+vS3BPJEqFID)P&$OJha_m$XCdC! z&8N`w_+D6@e}^4bOl0yNZsPSiJZA-)^uY35F@I*eAQQ6Ru6|&2jJ+Bx!V?-^$8Y_f zZPyqUj0^3S;HwsC`l&G;OGK2Y%(-$rqaZ?iUbdj=@=theN(IW~@bTV;Le#!kjSABW zP@-=X^#YSPp4Ba6IIVx;&nC>VO~yAuhV(gHrxzjXw+ z+&GDP?X}p_Y=bj@H{<5$JIHXq<5imot*exzlXV2?N&QdU^Fy5OVGrZCc`X<>aVFl- z2*6#leNpkuWNb2JF>2Ws%)8WyH(izJ*0)>HJgF&B@SShFfQFJEmSbbd>M&>y(4~0k+QSt6|k|L>0r6?*X z(V$dFlgdn)2_cnGQKU@oUMD0{BuY|AqNGy&Dv9R4^Zfx_uJ`huv-euhbKiXWc4HIv z;#s~+?W9{?KSe*^YN$MqUQ_`cDYHDYp5)pZYB)v3tF*+jA{TAkR8kOa23 zIf|V!7R)MJ?qzMu^w^d=s_fdPFZix26C-9;V6yohR8}p)`TzD}+uS>NI>`gqI8!u> zZo>~{PRBCD3`LRWnoU#>q5rgbetkMo8+fv7h8&!v^NevoIc_Vm)zy9T(t zmL7JsxA6H~Ln@c%& zx8(XA;}T^16_)S1a*U`fOXYc3*V2=lvq|Gl6RiI|M8`}2@$M(OBY%e*Km5BKY;L}Q zop<7D?9bfBhmoad@H!AB&RnJq;EomFQ#t12evGRNXFc)yg0yibCqrh%kqeKlBUS-|=6L0I*nmb~-Y z17eDoc~Scxk$VCHL??)Fobzn5aFPJ@>{$Uvzeia5b2+K10V%lSISJkRY+%8d9G+Y} z0pvF90I9jPFur0KmV3=%Dz6JLFTCb4f6i3Hi{N^A_b{K_jQ_*?XJ`mNJcRiRI5b1d z_%EKlp9)BvNT9kedT6)Q3~YLqK~oZ}G0;W>{L~`paKS%vc$pC0v8Rh}EgI$PzTZ#f z_4mM##3-3_;{hD)E+xl`jzCO{Ierk_KpFxY@Y25{G+5&tE(=(JUjr*>ie(ZicWIE> zF{x-#m`gmRx6|}gUtZXKNyyFEhh0ZX=%_kF2%&Ns}7UrQsJ z2T+jnU46Ghq~UvT*U2n&X<3EilTY9^lMB4V#1j9g%7c@rCSCKpji&lKpy9#_lz9IF zh3dFmg!em*JeI!S%;0d8`XCVpQNP%>~Wkzc-_Mu|*>mFZ=? z%+L97OzIsk!mS-PihIy`p~W!CB^#623*eU}!aBsI!uY-)SYa+dH_`qg#^o5|``Cy;m<4IyKSRE$7ULaI2h+Lx{f5sYpsVQ#;p+-O_02=t?^MHe zG>7;(wzF8CpCC`sO_6<0e^Fk;eUuM6i0#Q@C@Q-d!=BZXZf94XMT8qD%wG*==LTTn z;>TbxG!7F+m6_~agT%eiGe)0*q=mkqly}+jb2MLM3$D4LG zo`g+RMfX8MuilfuV=b#`-KxbH^?njar)c9;Si;RL39rXr15VxAN;hULgp-d8Xh%H9 z=GG~Ow$*Flq=^`F<=!%wr+)|b3A;c>eiyJ&JhF3c0+@WA!?TZ{#p^nrMwG@JEDs(t zvFvKQS<|Z~1e(oP>5xnX%-gI(j)z`^cO6l1lJi}gZmfkp3Y~CrVK*#~d;r3RIZ&K- z4rUKeCx6G5fGs158Bz{l>fcWDnG>))beM-VYeA>b21?x@5KK=4pKCJk=UW(jek=na zDQ7_G>~2e=f&buk{ZaBt?F3|yYX{{Iq- zjm0=;juV-Zb{QKA253j5I9pmamBhQg#m_ynA!Df#&RhANcK|lw=7mO3sO603dorQj zVg(rOT?sFBxp}!B*ZB&)0FqhaOv0cxAM}Edj`ty__T9{5IH&UlyliLBX88Jbjw|n92{%3px?rtVL^r*7NiVde@Wa>j^Q=1h ziIYhV?1;>TnX4|s;Gzily^ZrNuSx^k*Mdys|NByQgCHZN$q3mNLxjyEU?WmtMr{g& z>t2Gxug^of^hMxbH)7N`ro$JJgUrouKOoY|mbv^*k-1@;2k#@fZd0EV)Wt0Y(~uZY z>D>#Xuee-@K?&Hp&jRJW;>;AjD6_BHf|(|}lriZ20^3w{8Slhj#OIGXvr{gOm=+l^ zMeVOif{g(4Yr=HM75NK3KG&fAEY~fsQQ-2h63pVOoU?grG2A+E8N|7d?d_&2U~bAY zsX{EIiP|z%HQuCEm@tAGR=C6AGraj=#4$@s;QNnC`pl;Ss`uXJUH&=%k@l(J{9Bkw z_)mtJq-f6c?&I7)cNHgnhH`oy2jK2DZrpM}uj-@jDc375*>8h}Pj3@TK`h_2lHleZ9HT-_} zEuQPBLjE%WcJ$XM9vr!e)uk^GWTSAmZXrHk^(V^^V6;U=weS?l)7Xig z^=Kbt$?p9s$xhg!#;#Q5vGE&6Fm%E!wrAT5Y|0U23lomvGxI8JGOR_u+b2w#uEM^y zmSKIS3$Wj~``e<}-#BAq%`59`Zr{eFshV1ajWY&9p4f}J%fZcq45xeQQFstD+ znf2Q;m!0u>7Q24tLH4fLCib;>2&*`U<1qi2$(oueu_C<^>?ZDS+?vpg=N@%q@M&7z zy7&NQIKCs%Y!AKN)k_t%1W=3P;O61I7<%wFHM5Gt@7#B2{)#dhJ9{#|6>8_}&rw7U_>NhL5h&>x zkCOM=ab;W)`kOt&c{eZMi2i?AyQUwvuU29oy;flDIPc=wq)yabUXIN=ne_0CJ{&ni z$^O0a?D3f&NPKV&x_y}s7ICw1iAOa&`rt-q+vmgI>>bbt(T(0Nb1R}G9nR{(BXikMY7!FjUauTO<9dO3jeh}`+HfiytIIsQ`H8l0dyscUhU8$BAtP`)3Le~@#E1lMgJ|QA z5Zrf-_;%z$MXDY;>8$14hS%|p;2hZLN-@t@3beSrt*2!Jk&K-IJoe(azuGp%kSw}r|8*@7_qs}~G< zW}c|6e}J6Y`2=O|IO2sVow!Oaw`QpRJ3Ty*59jZG<&Smbz@>tCzJr7`e0E2g()E%| zeW-_CL%)f}DtYV-ih;Xp=OB95!MpXvxPIjelJ`xFwaE6s9Sv&it>Prq@lj{ddMTQ3 zkYg(~czE-`TU=Y4L^l|B;wP?qDKr>`$tQYYyy^x|VqYTI9*O0Jg!6b?b#|bAMMKT8 z?}cc-?g|Mv+=Dm$Y$5T91YXa-3-pi)Z~pTqFjVbGt{*CcobYMU+9l z$_l*QEQ|5qQgL6IIBxk~%dy+!sYy&7?l|U$-p{$adGtDbd0T?Lu)>U|m7&W%*L9-j zKB}<^XLqAey*XOSZKp|k25|M|DwtMo3d*+xVB}C8DcwJpiWqF|CEkLPxA61b}YQ9F`Jjj~hu64%et%bSL ziS$@@4$ooZOxmrlfd^Y>ptDCXUc0&p7jwLshhn;T$!Ltq=kjE zvY4MD=0mJPOriM47T6|}3;)gG*e5FAVg445dQ+spd^pQFqnWEPO;H>C{q5+KV^U~P z8i)5*r=v;4R-|u=Q7hvM{jQdPFP{(6=NAL9|9cpkF8k}7Eb zX@J`g>v*AGcEP2=lf=Ig=wHoRlE1ExH-AMWai02s>`?8ZS(+WhMD!dwik5O`mSQxm zT!b&>HgmnY)%dI2jyC^xrAv$}YMOUS@s$mip_;z|z7kEwZNu|WXdoMFl7-00IcM-* zvI2Pfy`WzgmyqvY^r53g87f6QV8*dfIHvrMcj2@qtV`H~$DYTM{2j0GU3?&Ec=Q!V zi`r=&BhC&-W#TstWtKfyfDOOjqw0>sh$U^fP|+5za2@e-#YE~nT20?*%!28fsbtQ> ztKg$K%mcAvI9jYrs--g^`=KxyouA0LA3gx0i{~Q3KAc7M%)wHDSh)>y+;Oq0Zbn zvyoCyvofyyvb=7BorRpEL%kB(K)DdLq-V0xDR9Bzk) zN4}7f|7zjnp*!$SU<_U^lVi} zJ}m;=Dvg=AI$`G1@tMrz!5z%142EgFoWP`C31@b5+*{|HnGD(I#5py*n00|17vYj6 zd?=R_&RRAswjyAV9Q@yhh z=w{JL-|`ONt_|6=P}vO)4I~g1YKU^?DeCQ<4!OFHV0nKz=-h0ART++OFQgjYi>!cI zA2?5;p(Kfm4g{0tn|z_4N1;OFGZ{{dfJY)GAU014beg9^#m|kF#?PE!dB}0zSivzU z`lb%0o7ccW*AkfH^_bLM{R(Pz4@fOGL#`s{3hB>+6)FT0*4zgXM3Q#92`+1{q5fQ7 zW^+I$3a&Lpk$x%GdrBrI+?m0eCY-_-C$(8+?(XrvfFfpW!NF4;L+p?_2DSU4+=qMg ziSR|f<9|*reCRsPKWuZk=Su>h~{Yd1-O1 z-dzXQJ=>3^_ZP4VlV`G9LxtI)mKV6a&k`$R-_y9XTq0aXKx&OT*ql8BEgtT36NbgW z^xYp?wPz;vl!?c8R)SPRybGs$JL31P?>II>FJ`sMv2;X@ePpb~Mw-a88xQ}7hOb%F zt^9-WmpOLaL@_peg&Hb#l;O+V3d-0u;J&0ARG*o^{+cvE`)(+*4j&58hjZ-)Y%^nl zC&lImEMn(ch_jl8>a3^YV|-Bj3wE`gruS z`+!NJCvfbH7Q4IZDm61AY}U(VTvuL}9R)?U-}@|Pyx=knqny&ibSl1WzfSj?rc;?o zwZz{%oxCym&ime;$8qUzAhT)@sBW3b{(c*b?_MlmV^-*}TFT2<`Rs+P;k6~~zV5}W z?ph`G_ias<32ntUZci}eX&tUB;iGBuHeBdufMMY*W%+|tJY)v8N*_WIJ9E6dcRNlk z?V}=x<7j#BL4Mx$NV;i*4(zpBg>2(r;#<%~AI7c0e#da0(2Zfd-@>`QI-a5Aw~yEs zl89?NBJo1W9$a+58PU7}+ag5RTU;0B+AdvoXzgKizbeLRFQs_F?jx>;JnXw#goe`s z=>c&m&c%3{KdQ12b1hHNoUt$1^F9KHV?o;AS!x#XtiCN zh!5st($aXE`S%C96y;&hA|3Wq;UnCgWyM;78P1&U&YA_6k#o1^vB$se;jOCrhe5TQ z$*DUJQEA0t*sXQ}Ul#0wXD{YpM~VmRJ3d5d#&MWq$z`5{c7TmyAI8`%hEeG;JZ$)r zD9ooAGE0Z(GhrP6;yH0LSYz3L#}j7$>i-Sk9QGGRWR^Ed&YRARCIqya2l!R5=P>UoOojbTew~D7Zv97Wp8kokz%~JuO$0FB79YE_Ii*!&p#{pH6rlV=`TD&{H1wD=(rCSeW;?0B7$cZSa$!bCD zQdfXoAGVQ_giPM%(9&w3)icSnmR$NTX*N7<{!Q(oQ>f_2y}0XA1kTldL(^xA;;LJM zqD$`S`NIZeW~1;MIM5`Zsk}KP8{oR3k=TSIxVYHIpzq*o1otz zJ)1M#K9pg6vxh)7=oBn6JPM(13n2GT8d=v72`krq&Xc z>1T4QXKsH@HZ8FLOW#i<=4~Z-nq(7vX$XD4PLS`WfhceEv*tbAN4D4xS1RY@k_|=p zJR_6FU471{x{nEeP!pDAo`B}7E8!>Ck?~yD4__ZfgW`=}u%smec>34CY-9!~)6?+O zWexq&dk?NZmZNGu`H+3elg#bb0^5WYP!LiG8*J)fOV(7zC8!134rwtW6W)N?hCV1r zYy+>D1{koB0WJ08P?Z@C28B70=3E2|f98T9CNS-+l zZYwB5Ov*&qx89q|9Mgwdp(~aG{u-8pjv1u;WHwg53nt?hpYTupME(M0N!E6BfTs7~ z#H)u6(^uZP^tiqZ7=1iT+QoBWzOoh=XxG4;`Sy@f`4sf-?}Xw<(#+K)UD);P7{c$8R=F&+VdG@SVCl{$|$W8NVj7KwFqrzJ5*?8LT5)&+CCs<3(Q7=DpC~DFSkP4#1V9 z)u5JR1I707#Hh(0?CYg@SCovvXih3=Ed59W2J~s2bsG9}9ioukld$m_*S(o;N8X%B zM74EKE#C}3LB7To{Q9T?KUA5ZT=!{=osvU4bggi7-VuCtDUy~noW!Gn_sGKRIq1r{ zZsmKb=)HORag*E8qXa-J9nM)+k8IyMlO;L6==j7Zmj&BAe*^MV>vGD`KY*Uyd+h8EX zo)X)RzFC*h>0|;*|2D&AcCFakeH~?=)#3KX60DKIC!F6ez;0=hXGeWTk*pD54O<^# z2a2(Q&JOrwjucxcl*R8GZ0CGjU#ZdcZhZQY#kl=S?3`1AY|rQfw(4ppp5MP7Rb$Jr zLR1HR<*IP2t{VoP48ZVp%483W(}Cs;VmPXa8v-t)^N%GsH$sU$-|?~LLi$5Y<@Om} z&1+CED;nl-nD-^0F2ef=4QQx)231BIA@bT2P&;vvxSExLyF)82j93l&MJi}oH%MmV zQk-fo3I~jeu^`kECLb-uv(DDgDeQy?DgZoEmGInNN*-57p|DB^eP90&^IbC#JfC4? z)B)VmTZZQ(viP!vdHAI-iAcSSMf24sEGI6yh}U$V(?YH*u>R5pOst@IQ#b;*S@+|V ztP~W^_=C6iUd2<1Pf^#k25sgDun$Dz@pv6!e+OmYnWgjC*4Iz4bf-2;70dCph7v2d z=Ni|+y@%^#OyK(tL%L|l9MZzQp{yVr;$AHSPwT>WHv^?f@5>ZI$KlHX>Wm71-&gq#s}z}rT(PMJ%;KU2tnBG1YB-D z18nS$;zQ4B=rQyoImHv1W-fELdxsn&@$DWgZ$&6L!STlCAA`HsFM&1hA#5A0gAD`Q`9+>K+IfjewEgT2Q>{GE^Pj4=abmLAkjDvZ5_u&qpDqWWhRkl{=Yn zQj37C6J{}DXA8hAOOja=col}{*}>~Kry0t)zn%ggJyUofxr02hpG*q2PNu^W_vzg} zNwi8Vq3_GB(4qc7^%rqHY|G<;%Wh%Z==>SnDiq<+TXE)#p8ykit_OxK^_ZIDZ$a#o z2&20CKCF8u$}DZz1VLvtnIXFYlB6C9O1gjOdRwGYPfugtST66%FCo0~IUeqOH04Q3 zK8Kk*eTW2e3yc>yz|0ViRs0|VF02TG2R?#OKVu2E``pDZa-GS|_a9Yl)vboQucEL+ zUV(AD>I*~lvdqMDH%QqgX+~(@W)j;Y&%D=-fNz_JA$3F@B2xQd{X9pMPk93ey9@A% zkvoWYC7>S1beU&CG3ww^R4=%Lo6V!BU2rKzymEngp0Ck;@gYz-%H^{s$bcosyz2;a zg~QUh^rdGKoROVLW||d1(19DIXGs;zQvc2Kbk7DuB{{lnODW|3JVEw6mSN_42SR|< z24=-Wclh(bi}}4>og6tL&xCC;$ADsCCM+fwhkhzBX;*gRY0oBbIPrwG9E=8^sGIav z;4c_`IgPi7OlNKy>VUq*6z1k^Nn#*v&TRTS9m8|9nZB<@=qYanqBHujVeJ^b{@+XV zx++Z1pXG*$6Q*-yYX{`7IohvC+)N$y6rOjSFs;%y_IL$ zRKno-xy8&`xziBExHBEOJlL|;j#=V-n4Wy}2Qpqu;*<_AP&dn@&GUAFf8`+kd@qZ; z<1WUV1=S$rIUQ#&>4tR?TuxA^6Y46RaDPrRq?F|2@XvCd(H9mYM`zQ4@J9TQU`-YN z_Thhpei%4GoE_Bm!e@CZY#?#QKW!T9=#&Te-%2Gm>e(>I^c%zT+CG0zy~ubDzd!(1>^_yValR$zNz7#_;X zRxfWXfym?#s`V=Y%Hq=L)YwAeDiT0n>E~Oz(CiwixmlpO+a8Jxf5DahdPs>9Vaz+Y zeF1+8Gfz#N>GGJ$toA_quRBU@QZ$csgxY@tJ7g`n-z%+cYysZ zTgcvlQW$ZVz&~Vj3J&@oCwyKDX_Am2=Aa0Q>*X*cJ_ghexnX6BHXIZ@iRb`a4(T`>O{?1F%&0?vlDd=pk$B=%bKyM$~R*hcP68^xidTSvRFY|NAp{PW3$)p7U3j>Rk3&ZAB^F@H5TOBtk!F3v1J zV~C%>a|}B-n3FbU4Gx%20-Ie<_(gFkNDYQ!cg#!D?H-L|yaiOfd_9uQW+-;I3YCPp zz2zTq)}!$XiU|Hi75ip9nDiT6x0GNdom5R6R55S(z?KnEy3D^sVd6$xHiNn-VVk<2|r{x|-r-Of} z!P8r)ySJH!Z9T|kVP6tDF&yvnxSrvSXxtjN74jyxW(ET?nNltbg(aoQ-;2vrs8yj!QTU_hF^^)3V`_ z(Pv(fx*~wkV|s3fDOnw}8MS4!Xv!{oJp0iRZ*2KNui59Kb*wRJF^h0#OeB}R2&I`N z>Nqhuo)$e{O$H1@85*!Ofg=#52Ji172OGYPXX4AGAhjL4zzE-e8Img-cL?dkx+GQ%MUC9Hu_U z7E$JdBUbAhAvqF^$5+n6<+;iDLm(7S3v{6V?enOmd=cMP+T(lokCeIpgkLJ}MSl6@ zQm3Jr#LFQC4LmZ@-2NH5pEY1DJ8Lm_#az~P?K~XcEXmIPw-Zg*bmN6TE!gVGoOV&X>32&%=oq6aYK#eL4yC5=LCEuLDTj4R)6!9zdgvCn7|RX=D< z*5!E8xO!#C4x5QV#Q@9wt?}{9X}~zXq_@v^kojkZsdi^a72CT2UkyyfEALmM%rYIk z&CR+@c@JsF-(ZaY<%|tG4&getcvMXz_7l*sC56X3J$Zm7^F&>FQ2s_tJR6Z;a#6Qy_jFs^43+Az*n-em(@&x;ZTeREj) zDu)Q!TET=ieG(Zf3YXKPYLv@8A!*EkcT@H*pvq-4IFvNUS zrY&zNNGw@QJM+>Z!YYaMjkLh}FcXU1ProFe=UOre8V<%o+vHm4Y3hTyUP_FL-E(jY zab%*LuS3mtFJ^!73y6`nXT%EBnK%PQCOd8tbNR;$cz3=NvN%_L4oQFzO>?GmX&SH| zN{sK+R}jLTKaI+tfY+f9ueh1?hlZanI1x(SsOjL{3 zg8UyB7(Sf>UmyU|u3dqHy?US(-~~6OXTwqxVTcn@fF6zuXuPSBL|xPe*YM3GS2~$! zFF8XM9(?Bgo-_?r|MrttLEO0^Hw-Eq9Oxd60$8S2YZtTH}w|BBUDFWWsX@Qeuuh0k|qboj&i!=IvBEiPJSeG!r1FfaF9*{k>sE7 zJ^46niXH^7W1QE+s}3&qYjV82PvCdY58Pffz_?rp%y{JmbKXjDnRG2E9FyaVk$S?L z*~oJ#4u*GYdCV>C;MyW9cvABi z-fQcFw_OG}@>F1EoGkRXXpryaJD@uA4j1Bag>BBVxNLNU9x+~mi#TWD@p%VuP-_wt z?Um)8DG4NawFs|l&naqjuaabjtfV&|HWQts33MprG|k9-Mtf9(vGht2RhhgF+oVN7 zG;|-f&9{XOrfYE2_b&f?hYYm{sG`oZy@@8XgeT%rPIT?#=0xJ;LCSry|KU|SK0AwEAi5Z%{dlUhF?{4DEW_Q6r@s7cFi^R-+SLJmuKtaL)6W zB*DJC--^fYc%WyUCpNFCq4%d|^CRx1;PcKha-6#ti0N^hy&pp8vbvhsdYq;;<4@`G zURSJ>;MnI?=9oHr7Pk5i&=-#Ne9~Tt-Mbv=?3Qlyej!Rr*X+UXlA6@+XBy^iTZd(% z&4@eB;>eL?91Gcso*V@K@9v3cu+Iqd#As9OE3L@1C42i0M`t(t7%o1e2zb}Uqx?Q05s1(wdO2O`n zX|VayY2xjaO1w_k(KCJ)ydH&A+?u5a_iHbr%~l`ck)(%NF+XY4OHud|kV##Ar$D`; z58tK)c%z3Glc1D7^4i-1tR{aXN(%$Q+II;(F=`DilC#KUFFTHbn+}yWS&&@N3NJWb zD^@**bs=2dd0!7Wdy6pZFSo*=p*mA(a|u#*t1@#xTmrSVAK<|IUifwLG)y(S!Ew36 zz=fMvp1zU@zM+%g&f6RCPw6g{D=0EH*-DJrTMOpNd0nQka|)C1Bg{PfUI=CrqTq|^ zRq{77f)sDH=bI0mp@NTJ@ojS*u$>InNQNFqDlW#&Y9ldjk^y$>9mNaHoODZRI!?=; z2>*6YrGrkDWTm1A{qDJn-_q+&KYm?CL`&N$D|V#7vdJbKgQ6Ffsy2baf7RfWs=!po zAAr?stQkx#gZO=RjL#=Q#*6cJh1U*3KHUjPn=)Z3<@&h`5MC$WhUGWj!rpcTW>Mn= zW}3VjV?BQkBXRK|v~ln9pvW*7J1Ea|-Z%p#S5>+9^b06m`56{p$%4+Uu53V z9Qahhz^%C@fD5zXM}9Yar4M1f@JR?SLr7^jOlp7If^EedvT#WgvAMVqG@lNU8{GdG z)r|#iEei`|3*oG2CcK$v0qv`!p!gZ#iMI6;m!@a@`cW z2G2Bt#JMi8tr2COnLL77A{;-+>?(X&F3Y$qIt>R8y#P%QKk#Q9Al0FS+?u3_p4OVg z&OaG>uI^-Hx(oyz?~Fc^)W}feZv3X1%8$|zMSnjHv`_d(BRD^zaJ>&M z+rTIHt*)V(lP}pgVFSLkGeA?{CQ5!qpk8Vs%6!PgKZOz49py79POLyfaOcx(67yL8*WE?Q3q5M=a`Wy8MxeurHjTRu#i1L z>(0pHWtlLlq5F!rBtM!T*FP1`K39cajDmSn6X3b9=pquG6qgFT8frk=uNtHW3vlY@fak5b8#*YOFb2^yER$E>y%njTe8#n!vvF%4Ue z%Q6oe-E7e!y`5gzP(}@Pr=iPFZ>qoUJZkJcN-v#1k8yvZ=>2=1m|=6BmN$stWxohI zV}Cpyp8`ztT%IEbb?I$QNN! zkSN>lrO5ud`T#4hNw6c=)}q!2CEOlO>EV%l;`%<4`f_;>5%~zRXju%_O#L7Eyd2+-PsFCN#Hkf)+6~#6t^M5GK$YEd`2i06RcA-^QgOxSZ}@cL z2-W3guUF|Bnz?%`7H9pYqZjkBI&UFP&P+njzdG2&WwS;8DpH?-)2OB1#(PsY!a6PY5J+pzWIC?o#oV6ZP5;tI5LqfKYkI7t{So?pKH-o8rYBCH8@_W&c@1E z;A!WNXyZ3X$+{lAzWy-(n{+1Thu8rVw;PpGI0h%zcMXzX1v4yGp@HabkjrSKzA~ps zjJ7X=?QR^Ys>h6+Q&>_a!p`>Hf@g3VtGy|Y-WdOf{>DLMuRu21wdPUb{%2^AJ`*3@ z`-H!0`{-t^65O|74OLAYLhm_x#9+5DJ6bS_{P;eA>s3Xu=ooh<@V$V6ra#gAOEjkS zW?-s#Fi+Y31e%vFC)RQq*kz(cs;q6W(0dv*UVKhh$xFfVni=?HdLj9;{u=lF44|?- z6WG-f(KxKE!ls5hV{Nn)tMQ#dafeG7OhN#D{gP7^mPHzaW z!VQ-MENZPH(B039Z_jb~=#P8!N6SylKUF|oe*ERU#=bQ2T_RrZ6QwERUum!M2>-uL zr8In#Az$*!I~u4k1X^DDj4hikr?|1V(jf# z6c3)dGhTPr=NO)0k_L94~&V8N*6f z5QqJp&{<#yKf)Y9VPz}uG|qzYy8qzaLTLupzJsb&l8pC-0Wf*e3^_~FVJLL~l#%Nj zTZu8RHV>0ap_Ont#Rr@}M8X|~E#T%<4vzvW$WxbkxchJ(h)89?jj5+Nufr=c?j;RX z78~iB&dv15v2Rr9z$W_Yr2>AqkwI#H^wURwRl%XBoZRj`2Ng~TB}ab4q8v%4w67d& zH;XYZ6JL@r?hZJwwUj)n5oQX0W`M>47UbeZnd5UyVY9v=Q{N@c0c+Y2Jp28dOfK3K&MkW(vXz`!gsn0&|<7HTID_f^(pK}7@ijCo3h10-k~ zH$^|RY&KarJPs`MQ~S_nSV51Waluv?a9@GmI){O`^50z9BbT^6W(S$7$7S@lE`^i9 z9CyYq3O?rvF#;yCu*ZqpcXBf{H}6;&QXAl9{5c3)&%Ec4a=D3Ce^LB{GC}<&Xf4>rbLtjmS{7@<@>DHmg3Nl5*dxq*SULgz%8D{0cO8ki zpEMKk#LkuCvPZafbsKe3JIIi=d3f5<9(A8fKmVMU2T47nbc>59h zGkGdvn=(H6GzEu(ITnC(9C|FN#3NnhIPyCa?@4;$wB4(*XW3-T~q43%Tfk|Q;fpjoDwv>y+LpPQzER1hIPv8BZN`3su;MuMlI?vLFk zeo|jeQTChT13cMc#=haaj7ld3*n;!dv3Bw_RE+k(0UMSywAay~w=eiDy9#*@eV0+? ziv%t;sztdYrI>teA1aNe;*vEw=>BXijxUy{W5-wGMU&6GiF;!4TWmec;2L+WNy2Dkm%C}{<>c| z4O*GXUJ9%cEq#tms@3T4_8@XQlt^t(0kq9fQ=C8nZ2trkv3jsRstl7AN8j_qVw>wU zS?>@I_?JhHTA}DS_!@cC2)oM7d&qr41wx?|ZT9j**Oe;te33rZt(!|lx~>?t_!wFF zM`6edPZ}2$g74Sb(A$1RygQVr>0UN(GVw2c-;~7_eSAhE)4xFTnns#?@d(&icF~QX zbL>n|4;6-vCi6#sXxU*mR%7^zZpK&f&DK0EpR3Kz3c1)!2Ww~+rqt`+4+n*pf9RUI z9D6#xm^5F?g3Wb%`mfUhZ{AL&fatk+T_h#m{L@18Npp;N@{=g?nrNq@iIA8F(y5Y?02`Fvl4_iMDM_ZSn6uRjQ6NiP8 zlbs=ZcI!0FE?S1G+@{iU)kD}{r-CKUzo5)!mf&X0f-M^^Fk_oYxU+06ojY`!&-ENZ zKi6#`yD3F%>f|k?=$_45+g;c_^S$hH+7>ojzLxbwX0n#n`E(`ZE0-#6Wf|s?+==Va z&?zwPkDk=QC<9;Sp{$EbBE~XryTLfy_!*n2Hx_w&v(o+~FH{vgIXZvmppAn+j1WFU zzvHBtobf*D`uTy28a|k^mnFgAA-2pY<7CO~sn1x0nhE#mf{dtA^$w&r+yI4dXW^03 zEZFq!S!u`R2KYBWgRxorG3aPKEApO#3-}-W2*nXBKU$e?wo21suX1Y0G@zi$&&1u) zpf|^A=)32Q;`op06d+{5P95+hmGNIo{~9hM{c}sf*<4Hu3=;4Mn#a*}B=+g4ZG<0+g)$TQ;p;-oWHA8_vW28qKo~xK&auSJ~ zw$nYFIUyDHO52m>7e_pSV5Pn^VgDci3^3?41LM)%oUG|eoZml5^ya4< zP7jUbat;s0M3YizZu)d=&)*MQ9f=qWP+-95aDboCVQEa+)6f-!hDcYu$0zc(4p|p7jOF!!Z^0D_R`1_vH zu<&lGRanj^&0Ij%wU^j~cXwIK>JIj-HGySknu0>(5s(a@i=J|e(Mu^0uUZ)3l)Yzg z_YZ&YuUZc~v?JNsA@|tJXXj~~X$+(Jt<*Pqed*ub5j10&Hn{1}XUehVoO(nKg!uUW_JSoQHg+;+7Cc?S3j(2+lof%>2UaYChoWVk6UZ!jqOWLmK^+Y2(=_8K+>fX zxS)6ksx0N&OU)5!f&LP;UJ zs(0fS^ciX6bo787vJId&LmS^jBw@MnF+BC54v!A;L2bnX6zGXCWk)`myp+b-8#{2r z%Ww=huW8w9dIeQtv@9#0r=Xfi3kJ>(6LMO~*!v87A=O41NV1Bcbw;w7+AgAn-6!F`##dG*70OK3Z=#Oh-`TBSWn|o6 z%r>iZQ}NutEGxT(-aQ#d7}r1(ey6eDT1~XDH)Lwn+Z@`iGZ0&3t~2?SF*sqh6uxg= zhwY(np?icjUT!jB)BDEbi#uD{?)FJ+qDQK*qdLYmmJg=3Q#zRUxS!$r{jg?=3H4kI zriIyswB$dcduDy4t6M?A^25X(y0tWS*;w(P@?`Sy9WHKsww!W9)y4HO11ac8KXn)W z<-Ol$kp*QycZn;>$UTNLZ;!LU-P*9W(o*R4M)3nLFK1P@m)NDTM@aJaSbEg)fwZ^y zkm-doQeS$897oBK?4BIjp|_gu`2S$N9S6xK$Bi@4S;riYSO6SQ!DNF0xL76&-5N^4 zW7{b#HxFZb64XI*>~Cg2CW$B; zWyE;OFUw>KF+6SHUi63;1~JKMw!A0#N*uHclC@@QWxxp6} zd=+{-uktxf$tEz>U&nB)9)6s6i)Cz*Bp5QQlU*O`$pt)K#@lhuv{%>-B-@Lqq$P(%9Qg@D3U9Ni zqdjrCln2dP_YB-k!^k~x5NCMGh!kWVbA!fJvyiFVVOzy?=zLWMj}NNj>h0H|?YDku z-|9quncFTZD*MMuCCkV;<`lc)nMG?atMVTgJF%n>{V;W{K8A*$!Q~RZI9uRDU%aps zjeY>ysJsI=Ju57Zm%!`ZCsDJ<5jXxhkLO=3K^>RIdPIJPc_9FJ` zv;k&oPo{_8mh-xlO`iX1*eLlx%0Ah{TfUhfuz|dxAu*W#?#bqV32vW=(kOOHaS**| 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

      { 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

      6i9EI4?)w?&^D$MFLxV}sScvt?zRN*+-iC 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 z yNA1)KQC$g|&6`=2d%k)L)B>d;|7?&RqgSN~jGQO{mG^uC6tc-e49jt>ei`x)N zrop$wV>sup0*dr;=skB5k!#(G^B0EVaL_FhJu*N?1@&OwsLX1uvw}M3N|4(ziEKHd zj!lWSbi^ndt(X)Vto4X~X_Ue@t1dGiE?q&e7U5P5+o0-fA

      9E->u73K) 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 z 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∓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

      vT^o?)xzAb|Lo&bA3boR%(swsx?c=Ud^5FHIefL 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 literal 0 HcmV?d00001 From 911816c282896d11a3e38ca0e5e0bc69ffe69525 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Jan 2020 16:43:32 +0900 Subject: [PATCH 4865/5608] Add archive test resources --- .../Archives/241526 Soleily - Renatus.osz | Bin 0 -> 6095156 bytes .../241526 Soleily - Renatus_virtual.osz | Bin 0 -> 445694 bytes osu.Game.Tests/Resources/TestResources.cs | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Resources/Archives/241526 Soleily - Renatus.osz create mode 100644 osu.Game.Tests/Resources/Archives/241526 Soleily - Renatus_virtual.osz diff --git a/osu.Game.Tests/Resources/Archives/241526 Soleily - Renatus.osz b/osu.Game.Tests/Resources/Archives/241526 Soleily - Renatus.osz new file mode 100644 index 0000000000000000000000000000000000000000..987dbea6db79b60c5dd56f23b31ef4aa8832b5a5 GIT binary patch literal 6095156 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�TP_zxuL=2Rit^eSioQ~s%yQV} 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 z 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 } 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

      E7OCSOx*=NXc@wmk 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%0D&6>xGHv0;R22mLbP`jJ z@DEe>S1GYQW1|p$y0ekG@Nb^0!D4U4=;dwX=e{LJGJ!?mM&&j-|H^xJ6LjZW$zOu* z+=X;`wxUK`ZNnIdgg%ErZ~id#x<(y8_62K?cu$sgEvO${y(WL1v8pW$dupF8VCbn7p6C&O+eu(i!FlcHr4-h`B!)sKp+l)EI#PE>CPP`%dENs|RI?@r z&I%$p>*&yOac2Jo8aS#NXj|K=(z1=u?tnjr4t`2UTTuDVS}up4bi66C-$0dhA(A6< zL~PZ`#65rvqNlepr+*ycFKOVY&qsFci!z*%a&+isNDQJ z`@g1OY@9roZEZZwZyCwk2wP51a#)5(GH7TR(&2F$o%a*i7!APQl2$)qbxQ!H9^llJ zN4`6uP5N-+VwB=k(u5E_199mTA&^4tG14zx4L#Jqc2pE_I=vuoS@|n~HZl}XCxK=>?Ug>UAHe~7O3t23>jg==H0jVKVX z3n_`0(i2yu21+TqN^*elVffeFd3|d4F6gKTGAAflI^t|vz)%S3n}+q6CM>oUi?G_J&%qHpIU3X(JYqSmuE^V$KoJKV zh%=vS&rVjjEFAM+<5_XJ!BSg(pNaDMHs}=)|GXYetZ83b^8vFPydN{6lp~VJwl`#lk^Y_Ze&Yn3j)qYhn>8$wkp!N$&l1e$>QhE zjV8d=OaN9RxK6tRWPh%7{+=sPxy;h;aBf&i^DOR!VKeIAWN(S6ET1fN(s>S+Jw^*s zc|?err0UFfA}Zyp`Km$mE!me}k1!IaWB3l!=NATMCqpMVTM&W(XsuaGOqF+HRv@EA4`p!v%|nDSYJB$EkW;($2N6S>onhWLw6MX;_=PWr_=;w`&hO)|kj9f^Xqh@UHVtubO$lvQpt0FxQ=d9 zsEn*G$Fumbp#uO|om!MnVc2d!#4V~$Bd@)HM{OmU&{yku9Qp1&AB;nln|pBs!6VS9 zm~%Vwks+9yrK17cnh`>gAvDTalAW^Sk!Y$S%$`JCxkg!}+>W@ij9|OVwS|z3(&8)K zPb!8yq-GVGi|)wF2soujp1_GNYoyMnD(y5HrfJt{B3?O8sCU+!=485n46sRsPrUU# z_pC~gVR^r1ua_w(ALdJDm?OTM^)ic0nMeTunx8JJqV_b5>vlyOhyxAHOD$RLGP8{( zXcQ*IVzPU=)wX`r)4K|T!!r5AV;w&lWM+f?o>!2RtDp>#l`!R$Rc6aLUV({5$?^>% zRiQ8N`Zf6j#;GGO*UGQfsT&a~314{Uj4fT&MZA00ybC`7!YKi^X^N?{=Sy``5{x4Z z2G5qq->qg{C^|8D-2Lm?Jz6SSDSkYr+8F#aO+@>123c=qK{Arz3lBxTo7)|9@)lUh z`&qM+p9&){Bi5HTp?8cf*h(e>t+vugOAeim!?e`WRVt>1=Z{rNe>J0DI2`3lncpE; zqfFnIT-$BIj8&!Fdep9azYXY=t z0s9V~%Yh;S#4O5BJeuZ1FP3bv@k3w=c%;y$>4_nn-t%mU5+yTl8C=vI2i7=Ya+nNS zyu63%W!mCw&$-q=nDL8nWmzBBimJZ9z7%>GYhd*e5D7Ctn9ftpx|q+b<6iRnK)L_d9){51?F3Qozr+&SE@WdSjQ zdX|U$2qh@1S(KvXJ%>c+zf!!3+`Oh`?IFwyRfOw%ua=(u@M#G5;0mz29VSrK{_444 z!q_L8<(!maSz?N7Vuv@dAuZdr_d13Dp;l~vU{maHcX02X58Ix#D;|JtD{9oG=6@fi z+QDbY`;|BvHFVMUU!FTf?^uI(X;n?4%Tz-=Z^^|#Ypk!D**NW0x`KtHs0-os}JY@O2 zn=XC#wa-@F!r`W`XqsxZcLnUoAtEvwT|JC#Oa4{w5C`BzBVtBv=of&svShoP=@F+u z%~`eQWO_XkZ!oKIg%j;$%8_-o(cHNgbNTX@guZ;`?cJza9Xmo3{T&$fDzk2CIMb>Y zq~;J@F0qOJ2yrLag`oWiv$)Fa)Z1h7qtb8Nw@eWEg0h?q6K%T5cDq)m?D zMbXCF5w_RZ(t14U_<&xehV)H8yanua$G3pO1FR7#U#NU26@#5~vM{3}~j==!Cm zG1p3xuwfsEu6yn;ZwWKiDi`0RR9zqH=x)-YE&U zcW$pMccfubaUl9*IpfgH?Zmya1udQovXcA1=%eJ=ek&IuY1SpDGhUDLMNoG3HR|1f zK#A3&I;X`Tbjti_u{=sDllpvztSlqsDJa}uqfcXz2gqyIc>vM*%2WXAx?C|QvUqb| zgoxYx7!u7%fc&nxDKctUnVFXp^VvfTp?f=k6{SRsLV^291vyt&+7>-OS7>31R3~)X zT83X6w6{@QU%yMl4c%tPR(%p#L03$yN-Wx8FgsSLVo4y_>~`gDUg^BvvHxP~oxKX+ zcHYh3ocAYs#!*rFjE;~xfB!dU-BCrf*NuI{Q@4h$3Jz)be2$W@Jl_aRe@LkG22XlQ zN|7b7ua`nyJ~OE4ne5{K_~QS6mn1lz&gMa}YIeyN=McHcVj%pjGv$wPLU&R3w&D)} z02Un!7B)T$E;d3*r>>|jvIBYK8&4VY2rsdHnOj^f!IuVhqa z%eP~o5E=)R#}bwkjaELIdT7;Fa1n?COzs(56%V>CNB?WneSwYu9E^ z2Ft{%O-Y)enXKJ6ZUSD|B4;b(=h>TVV^iCh!sC!<@QU+eynph-|Lmp%4L^i6nuGYQ z-OaBg@8911OQz0|9Hl>Ax4WHFj7vV3=z|J!cE{gW-QOd+VSm*3UNx9!t}y+izIJ=3 z5b`07dIRE z>2XJY&Q7VEbL_IXOHsZszx!w1<#XCGDuL)|4^Vkr`F7Zb!ojYK%`CnHbnjOps<-@TviIYr5(ExHthF|}80HL<1z>nN?z$5@b0001h zI|*1#VjazC{GY~UuAG&~mw3UBql!$%mR&p8XUepwDyqs31w)1`o~viQYt(e zAD$^;V@vSCeQKVcMG8YXlA-A*6P|fN0LdBCTOXKZdDZ z7diR&j^BS2NN&Hdz$F<_7+%BTeaCz=z#Jo;6a0XB?;~wB&vRdPuHZ_hY9!Uy%>sUk zJ{lJXzN)fz>uV6wwHJCZNmYPgE6mnQ)^B0XvaTC5%{3_4e89PFyCBa3her*~4uQ7E z%Uspi8!elGhF(rHGOv;ybrX@|68%>3pL3VRWe_=9`y^IR9;YU!S90Q#KV?iV3l!)* zD5PFrr8`RuXIj)nutSk#58J(n~WK-G+J*RsvDel^c9VGaD&uW$r z&$;k7@PGNxv2Y4pEKX0wUS|;37s+9Q$xn;iqS32U+U*`K-&sF}Z(49f0su9;eZbGY zG;^={2`1pt?pbYZYBxp)*#`-&QV;|e6~+ww8MdBmpyNka7h$HgGFpcS=pI{`u$@;6 zRn^V_3!BH$BBDuyraOC`K53~JRR)6oPEvpjz?#vic;3@&`u{AL=7PPblcQ=iw1lp! zO|%f9lQRxBNn5r8J@ljK|PU;JO6j>#z+K}3+CY8ql{nN&229^P|?yU`5z zp{pXslvvD(;nmZhj)2dm`BQ~&NVo5$<#6WI;C4ip+HBecC$-653NcZQK7k?*{KD?7TRLSzzBAFhVBY06Y(paDBXpM5K;QqYA zfKQ*gUZ#J!_3(8}3<~;@uvs^&gq?~LtI^L`W~6wMkS9mTAc}R7v<_OVK!}B}wxoO(CbWp_VIsm0ns7eNAygwB8|dzaX&LE8|gp z?^SJNHE*b^&A#J`R07?8Je_g0)6sYj#|^JGTtL7u)90lpnf=3e!sI_&a#`8Z7`!wV zUyij-IrvW`w$-4ccR(^qg)>||z;_L!x39p;AgTKuQ!zB150|EF&x{i~K)g2F!8O)j zR6}G$chkT3jaXF0?~OJa^TsRme^Tm}xPpqAvAJND9;cyN7*f5fGmlpTT?cRnUVDM@ zDlMfBqm?Ie@5Q!DXt%i&Sz?T(3OEnJv^SPp;=fxyoJFv0-(g=H zYcjWY=n)PDqyqpn7ImFEzh$F}3w|(=mnDT2mJPb~nak#ec$DKcmqKJHZolV>g%+pY z>dP(*8hjX9v{CnAQZqaHHZi}f|QK0S_=2%PH5&Cah48Lz-^ z?>Ya)k|(1@T}acp)oy3Z3feB3T_)n4v6Y{pHMo<`FuFf{G1~|?dM#n| zWF+1#3AwSnZ{I(ox1_vB?Aohaj`vyO*9gD#6?6}IedsuTGPq|k!MDT{+@?C5|m0{n=i1qRAQA6js5 z!g0{fX0!4vfDHF(J~SEt{2UPRE-oDVC0~mq?KeQbhGe_5j+Y$JiHH;1IF}{Z#*wa! zZTkq80AWe=(Mx03Y;do3XQ#w6M)V~$+8kAj9Ixc? z_G$`uK1y8TY;m}y%&=8sUlZG+`V5+`Khbuj;PsJ}7UZBfV>R{qI4dFHN4)taL>}YI zRFqh&akW}~M)j|~>tBzV5@4k!WsDpRWBo#W5W@GG4TX->R!b$w$`Zdq4}72Yo?5Sl1yVH!ki0W`{g zmUQ!SYndBBPnw{1ptRuvR`|Gv7uy(_tUyv%43lMj30c3KSXjZ}v|Uw?dj zJjHYn5t2le+p?sq^HKA3{!KsRjC)RMmfK0yx>ENpr8jON3MOxHX!4J+lTVSq-cag& z*^KOrpK^7bb^guT=51_q3Ws>!5A%;FMr&4DzXo_KVvai)k9F@-%s=Y?sPdOyo=SPJ zn0S~wZ~SUD_cdAb1BSkDC-7HV{9EcrhOx%9qQ5Wyy!|UjkdTFkg&!^D()aw;sTZb@@K;&{GL3TJsADg zC99X>yEW2}deHXp?5q=%an;YlM1vd3&oNRM1n-QWTecAoQ%Oq88gw=@m`yKPqIr8P)z_{sAJns@+-k(nJX95sy_>(4#sc{uRSuN$Qa!Q<0}P@j^s zP-kaQEdcRiZ`6SHSBoto9Z3bV>~TEP-lLq};+Jn>EbmU9YN9qsu{Eoo^6`YnK3z(X z6dQ+mFtnbU4+2B z&}IZIZF}!8bsxTA*8|9uL4Zp2VM62bz)}`2Rn4bg898-afG;`lwj61>krg`P;vdK1 zDh4ZdHf>4#__Zb|@Hg6(Y@EcLO1+Bx)xpH&m-t9_vb-;g^C*<#!MZf06WVuqlfgSB zg@hEo>mV#Kv;W#YU_u~HNwN64u=Xn0rsb6oR_Tu8S!JrvPOwhI$1QBRYl;UpfFmQt$^BqFGxo2`nzli82 zL+D#;5oVP)9p`BT8cpi26Y7*A{lOX55YTjHMy|9}bx}$vcaV-gn>yTRO{q3IclgJp z>)q^_+K-gnklg-(tRYczgsy}RZzedY$S-j?Wir<3rMxKduQa9qLllgY?6hr9Ao?kt zcpG6;3j|^+5PZTc*rr|l98n-{04c>f8T~HYGuZ5x2Ku{C(lG2?K+O2 zH)ij7P9Fs1i-eY1KpSaWlg8*+R;-RVvWM>lV| zAfi$ea@5EpXwN8?aOL@r^cjmMQfk=;V;mZk$~-D3%s`JF&{A@?OC9&6tDsPgNFRFQ zkhgs>zm;L|1G5+w8NH@Vr|l;h<}o(jkkH9dE*lki%$h1)wpjl9q1ypQdux}tJzE@}Z~H4!i&n`#c6mC1=wd+&f@-?2>Vv0$sSv}lXfI;#?q`cMW@ z|A8qK{R&jixVluYB~@VOD-(D!mYhCht*A54j%oc6kjWLmdjQs;YT-CwJXix-t1MPFJ*^JOPnPW z6ejo224BGC#n}V+6Ai4411m}^H_&T(I?IhtT%>KY=gXK1RTs9hA?va;s?BA*)qgaT|my9YuR9m zfsi~$eqq)~1>wuPC^jKdhP+q^mYLXiHQm3g>C0u^&9WX+gF_ODrJu$T{G+Z(6Vgxa z5jvKuA$4qw?I4~hV}8=RBM%&1kP*qWcst(WTy4|ZOU+pPcKg`jno)W98~z3}$GM7? z`bzO^@-Hp&2tyB(x+G z88da}4qpNkfWj%Gpsrp;HE#-tyn}=PT#2|o^~w5r)$GE;TuSp8JS>JuG*^>L&a|mo z9$*)n#soS+{eD`JMA?-+?d+AA9<_=@Bsxk@?PgIutFbb4D}k)dEe?4;`uS$^NY(9H zjV$9enY8|VnTxEr6FaC_{#FgILQ0|_LAo)*mW6axhtQ?Dxk_CHK0KRBf!{;VK#oTK zEee$Fw`h%Kp^^L*~_c>ZdIBR%k@ z_G!5mVX}S)68mtE^83uQXVeNV&vANY`7{1goTdWi{--$I<-X-cpzQR=FO>ofm-P0!$vWsa!E~)~&GDA7C-|S13;Ry&IY+)M zPl$Z#0s97pmh>oEyl+XD;?|EXw2&d}$N$dwt^LU#pOm_?5E-0Vn=eO{j{2T)tj@$1 zP7z;1L|I^zC}mYkKbf7k6b}wCpX|W%pNtEZE63K8?BXu_QhYdDUEy0kS*m@u8IMON zM`N!f(f%uJHMg0gxsj~Zq8=quCU`IS<+Psg$@tm1*LpdqFA95Vx3`UGJo+7LZV&o> zE^4@{7jBw8q{JHXLQfx=Iv>b@|9yXv+#6)}Y&>>@q2-;H(kg?O$;?&c?pCJXj?~Ok zoq%N7+`RXBsrH|w_+2*0M!iIJ5|i&t--hDGf(PPl76>}GDXDe7I9s+UK4z3;P~}LX zSpeaHGG25BJ3Z+wm3oy95AgAT>>BkY8;_9;C8DY|Z$v)cMH1pSwATIatoiHo z)A-z?%GVzWQ7yG&|E$06vV+IBLAf59iq2aOcLKi){#Xt#=iS2Sc;_~TY3zcgS*!;7 zoW~7NZT*w%KKdwqVUmv^h{mNy@boeC&!5v#3&9$p;avsO+y(4T87QAn%?wJLd-C2j zF4Iigh3+z$d^um$OO_hMH$uXmP}40+(veAPpuub9rXBhiw>uxDbh}S&UP-&tdE@i= z*fOQ{I%f<5VeYvF7EnY;@_|=AQ%$lOck*aY{T$)@n8q*oelb%dv(vH<#^y6#o`+4& zN)-wRa=rZqq#U&=1asiCSSM~6L9xG=^MYl|0wCz9E| zxlPDu1HA~q*CIi+=ih_)-xm81h^n+wvqg8x%@J?xZPxvqel*iO+77Y3m6FP8u8$1| zDBG9D$q7g@Gep}(Bye@(pi zSuuLN_;oxubbRi(_42Mr%24%D*q|1|+s{TVMHW-cOyrK6<0yo6yzEBCNi@ z!KZV>szoW>ng9E_D_+4V%R6bXch`2Wel%$Cu(s}rQs9)kKHE)}ua}Mw!!X`Fj5-vV z6NB-R!)!HVvy|UX28*IsbeTQtMDxc?e|dXKrrk9JSu|tp=pJ*~YX+CDTvhAaPh-O~ zJiIOLrq)Y(ekfix4=PILdw%+#g`5BQ(5GD1XKif&nGJ5R>IMLCAj=IN9Zo3L+9b)` zf<=Z+H+zdi4@mdUM&oT8R~9xF^*Y!!kx4o<=;=CcDnAo^ksE19tWCRC(!**Q_|@>V z(b=@va(~akY-2g!ySZ~;@-oFly}a?27_v8BY#DaST-Eb0QKsvjzOW*LO0A-Qsl>U= z(5Kcg>t2B|EfgbOFL8-2^M0#yu#U5U6oV5mi_!Zc`IeB^eWaCW@V)--OfDF42B;-_ z0x4f|1!S_PAh}}O_C}Z+Jr(F;!A;6hs_|9w;cWR@#s)M;F$=6EPYvaMCAf$Ez)u|; z4C1>*%MTx0nm%W@%T4_d5L0v#Llj=MD6##%Igrk}W*2#cM z@=q7K*=KbQ&Ze#Ee#r3qasE@+{<~QHN(%z}iOW7nai+Itu@>}pBHiA-wz{pu`2Upkq2WZm`6Oa4L^5F4~fq00uiIClm0y}uQbKhJW~@-OdX z2QMf~jdX4ENiuAm|AQI(MDXR+x(;x@t)GSP=&X*3EY|?Y0RTebQm9AAk|zXksI(l) zW6gh{5t7g0;&`e@K2Bl+&CApA|9-4J^&)S?RQ~z#-3@|bXK3kr^?-#nzkQlt{V*)W zX)ysk@YTxbWyQ(7RLz0V7r&v}%%Q_EidZeS}K&te^SoJW%sMx2SBQOU)@PAz(6?1bDWNRSW?X6%R~TF zK&!uAIH1A}1k_}e3B9m($c zml&i+aHY%LdIy8WF=R1vw0U;AZc0b-eJ1Q$ zbB+UFB22Don6}(3`la!<0|aWkN7)O9d`lNtir_LgVT6-ZOPeMmVC!is3a zL-klr$1U3>tYvr^bO;eMGmGO!wjdhc`rFgr@L<@eo|Th*>Eu=^o|(AR#;w`%=F3El6a<#=TV(HHsbpCp}?8 zX+nlkS0Ox1g3hl=aIlmKl$2eN5Q}sO`KJPUVWj=%CtZ4OgT%3zrNN>b=BR99@MA2n zP)%h@k;jRlohxYs6{OS7(UIoNyR+fZTLnsSr~lFTt!KJ`Z^DkqE<3v4Rao#hba1}$ z+n@hmLX&dQVcYgp>~$LSAxxh0jX`75EAT!Gp^V7oessPx0E-oX57-oel8?SSLWw_n z?iA>w68mP)^_8oD&RX_gNg8c4ZgclG2b zCKf2jsK@FMD;?=kAp=1dZ z`4LK8OsS4o7@l3;3!*w76(kR-zkc<+o1JhBM_D*DH8UJ*5*rHuuoB8iU}N+K7lS=4 zcI&=wS8YkFdilN>MPCfuaYzt!*GsBV8hJNNaald%*cvf}(a-Qdsps0$@`QHiiVl+I`@6L#->U?i(Z}wG5@y6%KS#CO9TLPsQ{_;zX^^tY)pxQ zXu$gBq-5=^KoRco`e18Xa`)awc#>~7xj9yW%~8&Aik|C4uQ1ezi}-ZZ0V?Wt_gZCR zT!lvENtCN-5tM77(hCH!U{Z_UOM|7K?HU+UHsl+c?y@ITe|7mgl+<8ubPeaG3bYGv zIDbbJcm8ZwzV_b;*B7&<OPp>MAvV{H*CW~ zjjf+3S<}d8+Urfzgbx|tigO~9iVeNaMHZA6(H$~{VIg2d(l!+)G1JJ4R`uK%ieie6 zSEp1?MPM>0eP~qcrQ@e}3y<^IdDzH{1gn&Ss#q=pnrPo(Q6m3r17<|h@~JcRFHPXOUMFqs^h zG*C@$j#Al5{*o2X7U)_stDaC~zq?fRUO1qV{}#!N;oYpWI8mJ0*~dYqu$EcRh>=Lj ze`C*3z$0JIv4L)ZImpH%I4_`NoK0t94I=a3y_(=07s-2{hsDGt(3rNK6Yg_P{FN9% zRmyzTnR{k(*Y5WEj;EoYpfVYxiq*^eb#Cf!r)G=>T8%LvM-FoatGvXhh!30K7$SSN-?@GK_^wB*-g$;Q zS})n>RNcO`=f0tT3m9Y40ko$aBB2l`1^~#q!a>yQ3@Ae}-{iv&^#}x}(9hS`sET+E zF85v*HjgOWc-*zplY+cFpDvL@LQha5CCr zFK5{@y6NW3JZU`wiYWRblnjI)?IJ(;ebcjb&B9GF$^0Z%S0mfXYcNl1TP~cDmb<~1 za7jBNd(_CfU1J2Ju&^eH0$>WipByt@7;B50cOTc};QR{t&B0umxRwk_?^GXI4x8K5 zNw0bZIRRhIhR(7eN(VG^Euu+D_Im))*Fk<77q=Za@Q#ThMMBj z`ClLj0BGm9{gfoMmkpM3kzp;-6KQp4Wg#6>7QDP0f%7x?#VZIZEdW1sqMvy&`I0PF zzlUzN;y4PJxQyBAXz|*Us*(;D=ji8gGG(^hd$Dm`SnT5%Sv#xgS;p2a6 z^>kG$B#voJdMDgQB0jWLt@L4|f&jJ_v;MG^yxVQm*sXP%FwIVSKwViU+7=bJ%nL20Ws$?C> zjJ^#9(v8qqZ@bcXW~=L#MWfV*i@L_t-|p6il`7T|{H|mN_idA`dhpbuFzZ~wZ%!eO z&JDmwJClT`1RwW%G5}5O7dZN`Nvo#m19zV`4tw}HvFeaUFY9%qQ{=^jv|Ub5lDR5b z{1kNJ$_4Wcr%J_0(4yR?u6qg{D8Nv~Vu^$|^><1!BfFKg*#*$&Gz0ZS6xv?@ii z*gmg{kfi;U9wWpQRmj2lJ?}2%8mOGPZwr z_5nY0wur*%iHp72ju}pN8YF|pq*jFS5Huy{tctBN({zXek${}|_Z^|yZ3uN4e0BrI zxJpO&KOgeT>$4MYUJwqsEU?%3+G!2_*l;GoSE0Ys%6YV;R-?-~-2d$qL&j!g1(w%T z{;$;sD^n1MuvZ5Da~g2`L06*Ky_!mFNVDzI?+zY>QDz9hJCPo=UZI8%Ft0jFE+hi$ zlo1iuxTr1Q{elT@(}x{3lN>$iFc74-%CBFuDp+$?&}@H#0xn!DL_u0kHF2t++~$Y_ z=a)a5Q~w&9#q0t1_HC-f$xV&o`UKI3Ehljv6Z~tKxma5y2$ngz)$#eLU!dnIqo>W# z?VdGgkR;7UTtLD8N>YOEeJu^O99b0LwU~r*W)=gZuRwFsw}$fb9n3g#;r-fztf`C) zvz-ST`)@;t@kxnLjf1lGg+>GXN(wT#dW{HA`GxFD_9SL@6m&-T+wMD+C?en*`ZD@e z{-nKdY$iJm0}uc}zsQYkb$)$_8{8Lih9pk0QxD4#4449cy4-54$6R_{Lmw{Nl4tJ2 z^5Sn&qK?s)0BAUqi44eqNE4T$&gkrD(uo<;GMO@0GHwx6<5Zl%UzlNjo0yVy6Cm&< zQS~3p=lkS0CZCu^8=V@DD#Hlv?uE)%5j#R(RED#H1#tDX*DnlWa~kW~yS$Fd)W1YW z0RW`^-CC3Dpq#US6aDu;5?`H||7-hv+q%^%#=ns^sPPcFM0b<6Z3moGv2K;Dr#FE+ zQ8^>ZIC(u}qG~6i$88cs?d*XZ#f1jqO@~BOuL_MJ*vvxeB1S~Qv&edml>q8@M+v!u zZL~`pxU6=0T|A_v9)AiOsoI3|w0N>VwA`5oMx972g)J1ir;SejUk<&>Y2)-%=|?WN zl)3FU^=!m*y!s?;ET>%(>h?hLC9`b7TO z6)voH3s-xgDOZMD-tQUsyFcv-$(yF3ut>pl*u zaWkkcl+!3_BWATezRDr|nuG{R0Nc5sgsl^+5Hr&n9%@L}ERrv998wcF>J zmq%l%@m!Q-0cu6`{1`EL;$cdPkie*V@j5sA@NwpC+V)%`27xn>Tn>{#4p7g950z(- z!YdukwCg0&+^fD5wU+(#+>4>CVKFd3_;z5vXt`l!zY`kD6;@Ee*h~I;USK3|g$F$R z8=O7uX2kxEc#6b4IvX7)deUG3TOPylu*taAHJ)HYq{`$;!1TAkXa$p7A}UQiOQd?U zaHfoZTV~gwUqq*vq?L+ z$)i4X%AfB=Qg45{i znIF>V5ufGJ727$jKaH+d(~irrH%GcpP9K4CGL;Ea)O}3U_+(U@V2NVb zZ9nSu^fOcEO$p%;Ld2(((-%u7Y;gjnk{X2;K5`2fYGd+5;+iC_9w5o-fw=hz9bZ68 ziF)+FucV-TVq~y73WV zaT76nQl6;PNr?hOD2V`;{Jl$3ZUG90Rx_IE2KDzZIkkuIpk71Pv`+Y4P!yA4z|xiF z9zGHjG{1*3OI-1HfBfL0C~kZ29a#Q9Di>?B?fhN?keDi!$`a433#)XG2QCkZwY%Sq zz)|ab6!qk7OvK94MVAr~Mn$}xRMU8=mbo{J%U}bl zA`;)8co%cmsxwJKewvd1Z}4`ayEWFoV!wy1;3`@7#57|hDuF^8eU{*6(~xy6MF z$FAdR^<9wE?6tsMazYKx0dqGCG^YJufl7Y58YsCOl3fg z&sK4?x{7Rz@)GF^{H%Ug1w>?`6FK8jbtZpH%_ZOIw9QvOQ+Cm@W)iK95Cdw1#1iiO z70c}_bYy97S^n!sCMa1ic&asG@Aa4(^s4B5re=wP6fOmsb! zYOOo;ifD_N{BAjE#J=>MKPLxKi?3Q$gotjFOE@AmzF|l zyqrt*qaVIijFfn5DwX7rFy|Vb)s(EkMyqF*80%nW228VLo_SSjNdR;JU7gY?zf+=8 zobE2Cl^hE%HKde=WCTpNDVJVZa%qo})uBX32N%z--Pv%r>v0;w5C_0=yC*9X7!~lq zIL<&VqlH+7aVy>Fm2lE~`IHB@2)S^CBd&5A>_X zuTRk5KUj5n(wgLi#5lbouUc?t%DR({&4twtlYnn!A*xIl0tl(BC1Y@Nzwr^qd8ISG z-)ummM&?jkoX6>=d8PR656I1sfJZ0x+?HY5-_1rDike|&*l0^pCXKF8AO6Cfk}0Ig z0UROpofw5oz0?Q@Uu8{ct`U8t6naC#5(=|u{J|(czSoF$MG@YsyP4|P~ zNVe>l@x_lvAFD3Nzi|Q^ep~aS$zkfC|2`G@qE!C2txQ2cL@~*~Dgwj8v&sGsM=C4p z$wVDQeL-p1Jljt{W?{;IFoVAt7Hw0j7fo!-E=>-x&rb5kfotLh@;W0lMJwF6*cn$U zkHTieipk=)b#shXjyatpf~c1dQ4;PL&`nAfa?4P!a^WgoW#tZW4ZQXxL*0e1RW9LT zt`jg&!C*!L-hbNV0-QFj zDgpM&84_B<_2hF`n}10ew4%x46(5)?=D%wN$g&eqU)2zH+|)7uVhJ%vmG^_lMk;d9 zqF^d8>ac|wdR5AbTGp?tSs>bb!AX1NeEH3*EQdc~pdZsG;*mPhdk~TaNzJg+@71Bw z>N7OI*yUL%RkXmvG;c``F8}Ry+W2OZ-wtYj6a*;c%K?5DFp4B=#fZ8UwKX=AZ5$go zh-C2bR-6k434K4W_2Q`QDcZ}H&1FtMwMR7Sa{uor=66hv7s*Gh4z*YK*3ToZHql6%+=Y#j1B zr9H>xb#l6G6>!}{Bf$w*O1D@e5eVZo3a<=i&IT3v2kZOkOgNXRQN}z&ixlzG@)+r+ zd8L?XvYU*`iwpcTQ6x~_U%4tj7TJ8FgNJ~;k6WK z^;S`2YLEIsBJQ&QCzI4*eOj`=%X7Xh_tyhF?&=pv9xUc&wl*nvu7YvTpx);#1bzo0 zb9Z4$$eXNXi%=D zqC7Sr@v0PYNf?Q z&B2muBrV=_SEmAE&-wai3W-2NY%TCw?%9HIq;j|NqH41}#fTWgI*J$)#;(bD{F;L9 zWusYrM{R=LD~q>?e<|`5X=ig#8||l7MgRaWk^(lmEL1(NL&(r!Yb$5bN(g4>p2i=3 zcDgSJlo2AMOAfHfXjKcw1Ns<<8_?zoU!zGvnJ4?$z?~DFQw=X56KdNgcG@p^zj@1k z!IhhmeyKk6XVy(of#)MGgKycI9!g3yG@twarOd&pUCiI%%hFrMmRv+$nFU#3j;*fG zx1Qm{ILgquY6>(tfPN&AiWjAvMqF$+keSG-l_q`QWjqMwbU;Wj#+UG%=EiP@8l@gF3|JtRPu@5P+GO@ad1lJtaRr^)*)%{X&l%>#RG{l@~h z$e{@CQpUm|R6>NL2w14m>=e4Ma8|KEsSqYFTvKO`WhRGe= zy84UYv!wE1?TbAuRyvi&gU>uyyZ%^Am$*n^+cCve_{CTzENqQkewU4n z1+$UFrPHR=X2|@nVs*R*@7a=aoA0`~~JW~=3PM%+5 zGXuSR+%lJnUHmA+_nm0^&EDR}H}92x&3iww8h|D#Gh=Jaapn{PhXe(6>m0?B;N$k3 zvtP0H_U!-F&r%nbC#K+KQFt`}xw|vn^%JQgc{V_u@JyyY| z!YCHO*)a|lkxFq>zFHOY_&LqESrbpI%S_N`htI7!0kN@pFa5VmT+V${&omZ~Wz~7L z8@jm$#P}N_t;E~|n?-e+y|-+NocLFLz%ht48k06$!)4ZCn!P{U^Zfj1!u&RtfT#6I zDJTYw5qn8=uH={%lbNDZx=Xrjl}`%awqo=Mg?2(bI~DmqVmX8(^in1gkj4G{s-^)z ztmz*jo*Rj$%+JR~*@9+=sly_==-ka~vbWwi#k)UhI}mDx_bZjf=*{JDT(Pkx2hGk# z+Iyu%p*g6q@m)7K#9uh%Ls9L)d!K>Q&BsSE`1F)3+tU8jr{7-oKC|E>_hVmA$#;>x z_3z5!mfM7gXX>_v`my&(Cc-ptQMBof^{X}#GtXfjH+nydHMR#@aG<^Gwl#G^y_mnU z&NXt~EB?^K0RR9l2a#U;yS}9d!&DYeEE;?IrsU{ItXDMt44fq{QKwZ}=46s)^_=s% zjf!79yHT5hva`;kk1h;tnY(=|QOS#!KfO=g6}U(^YC2J0*z>y9kIn>E*O$j-m^Ndv zv$9o>*G20eCC*wlR{Ymbb*^vOV;)9bDhrVegtUR~E{Rup(t~I}d!+nTD{@!WX%zqf zKrD_t1@YlFxhQ$}oa` z@y~hL30c-4mL~HQJ+9FGlT;KaeQ#WWg+}V%`ouEbnT&{Bog@MGYLnBSxyL{M(qnAb zgVi+Q0}9;FJo!TYGuw+?rE?TLhF8Y^4ryf}-u~F;0673dWF$jN8NZtEn)vmbcL#LV z7xoz8R?3s4C&5}wAf8!`&zRN+!csW%RhH=)ARwoVWZQ|}ciUGhyudti_{f_$ zBvt8+lbtL%LF*Q7x*fBq?_Xr81M?HZALNS#z`cR&QbgGI$A2*~FJ^^A<(7S1&lu-Y z?7x3}e5U$$Jkb;n`IQVC@GF__ItBcnj0Av@V85j;{RxnT|I+aS2+%{TbeR@lR#0ho zcaDYq1TfG*(0>&XRM;WIFguWL(kTSJwsE7;<3m~Ph$J!^t(ePNA8Has^LeFBefGk; zCnk*sc4Z?V_?lsY4kHU`XFSSdpv=;d?b4*S9ot}YW_)R7Zb%!=vcZB!oqUV1xbS>f zaMwQqap{9D>vCY4Z2Cu+wB|+7TDlKL%>&=t(;V8GuXNv$Sqb?I*FB3FvO^gn$ri7~ z{m|Y*>it@|#5g1Zrt4PV1VqU?S?o?F;4yagm8|k2IBNjRwt7}D&XD%#N;_LOcMzBt zniXM}bX!$gugHR5#KHpK9P?jT$!OMv#aHDdzf%3k6$ckIx~S}RyrYdi*UPf%Q7UE9jyVtV*e+>0gsX+)k{&c-yY@B zhKxR5QedF}d}W%-Efgy4KI?LipXF1nmZbmm=Ds1t#h^dShM06YDb%Od_O7tOMaY13 zS)nfLn2zySfE=FJfP9-={+To97p4i`LM&0zZ=tq?Ed;DiJ&a5jIS~f;?IPOQs@1}4 zHfOJJz z3sPOakX^Mt&8;-Cp#R5|XP?kPV3|t6PJhw}mVPrn8L~MjNd)~lvC2XAQ1=ePCOb>- zOr{A_Odzr=cAt&CAuf_${55_4swe(a(B#jw%IOk+M>Nn3QVLfpzlG#S2PpRowxmug z{x5bi4?bs(Bt@wWZ9SC*Z{4#0&PePr9ZCHRT5i5kVocLx$-3?EAG>e$Hgf+UY$5sv+)96v() zh7Xpd<+vh7YA&S>J41}sMr+94E_5k9=h(ZrpyZxwkLQsT9fn($HS7@HF#kVmAWKn; zoDcS_&K$bgb*|XF7PyO^c}zj!M<&1 z?;wRPmGZ90_*!LeDYGXPx|myhE4pAMmx%#zVC^lV@M&}*7;owIDfDY2>irIO39u0p z+62)!6;|RH`4dAwj`14K=N=wqCp?JZW3rO?8X>{{XlGO4 zcB?{XE*eU0>2foz1>&Z^*;J&<^=$tWWM;HelGC17L{fdrc-yeZxyezVEg{I{>cCCK z=`VR!{}|kAmd~r6vU7q!XO_dHRwfl?4MJ$f`DN?_v2`d_P|+~mczu;OZ70bS22ac+ zKGqMcaBypf6Y#?cVLVgcfUwnF?A@{gCu9jW2leh)G0&L8(Y@OQ*)J& zJuvPj-#DMsNqw-qCay6?^?%B#TOFXw)(n7*=}pcCAV9Ym7SYuaiEb|F@kpP62H*g- zWx-RBzrpI~TQ!q?$a`V$ry9%`eKk=5kp7otB@xMOw7HXo=JwWoX=Kaezw&}dOFNhx z_h{<03~1_PJ2Y~7S{vbTcRIm_+`{_TY~!r?zm8sI!JKM)9qMXnWjll`-hWtCXt$~- z9@7i)nlymUL>Os)9=tz)EyL07ljmJ47`sV-RomY7)?kpWsP`_C2(ST+M1%siPMo3U`Q^vaS0iJj&*lW1kSK-y)!jiOJvB2;)8e9Z4vo3}szuVTR*wJ0vB(zcXoQE(AM!ZkNC{UpSoJ9u;gC+ePV9)hz;r8hbH zS$Klj4LKvmwQUygILMS%?)|0br90&LSN+?L>k-9oWcW$y391;3;!85GB}MgbA^NM9 zsxrBrZK=&-V(%jP;Bo<+;J6ekz#f1}z@qC=vwa~eB2Jdbz>2gzD&Ysq&%iiGTR9UI zx=V$VdQnI^GA8`@G%;jD-kzpCP zSn(kSNdkBJE1v>oK_sCC&xO?W>PqG;0jL!KlT+YGrp8xQ7rku4O{eBaMaZ8^EK=ogU(it#5;1lo8EM*iXC!$u%iD9M z0(?YA$Ts)s$|^B-ai@yhT9ZdInN1j`!})Wyz{(^kbCzUNn+YqmN%?C+eQY} z;s;1-X+G%2RLt#ajO(k1TioSJ%YfF1zk#|oNvAWbPQAC+>-}1;m|Grs=D~mVe+>k1 zDNjH4_1-kQ&L2P;0$ASn;x`rbOav9u>6~-XyXt##WZzP(_@`**TbvX5A-ht2${lluG48)o@SKgy>$^6~TA9 z(B}~7*16Svt3#aBl|W_t?%7+tp9o^d3;;8Uoq{{ z>qAb{2*sE1E9rVnQUxR?)*7_Fq*oWA6BXN(P(UL{hR{&xCE0kNhvWOvI@s+ti52UV zYB9$`sKfn(elZS%8jS*oSPuOxiM06m@Tr?TIIp$QGiRB47RcA3$p;K5@~1Ts4|8p- z6+B_nR(EmJQ^sYsr+DmJxM;l$u~LNo+aY_)H`=y8*b+o((q+e%QL+?e3a|43_K7F} z*^qIA6GC_9FgUTc7VS09k0lL7+GuT(CtqhXbw3hhBZ_;ePkGONwdZ2(nW*5)|3c>e zbL8snP4=;rtuik*dF&=i^r-UfQ>pkSIR)HBVhg&7N!9Qck~ipyL!`_un~Yb)*hO;u z%WlF8|Mh+VAkVVk;sKgzP8?(Mb1Fv~sbN21-hw7CVKSA*#{I6GYP;DizqCbCcpP7< z*pV|P*RcYJIWuE5GbV>VT@YCZ3yyxNrybU1Sn918A4(&uou;rg;mt8#N-~ASTxQ~J z8GZ@h8uXJGp;s{}e?zKJtr{6q(>N)7XRg`J^J_a<%AXZM`h+8?gd9j zO(VXJt7Esg_eyP!p~I=|jcInvw(NO>Vs1>9?Ge*W1Zb_)KRq&Tg+M3|*P<4QM3ka` z8lLntsJem8{-r{MG6A+Bk?(QKaAd6Lbob<9XhlOhM3kHHyo=t*{14*+HOL2ie+6=XXI?5B0VaDWu)LgNn2SN~Fptsct`%z# ztzB|V1d+^mxGwz2dKxst89(>2`u_MOoU%~UlFY|qAo>I3hj>_Ze%DX!QPH;0UjmhIkp*|V--gGg%=Ef%{ zLxkd&EBnP7I~m41keFhQ@6KDi@LH?lGYv^r};wcIj)Avv1aO8={R| zykW__(9jg2Ec{#M;O_&!&R@dI923fPYRj|XT!^dGb}eyc??aGArzS;#@Qb>{+-Bb9{dP&R05jzp<3bNcfQNdO>@qE{A;n+qz>xe2gS3g+qhS8F zuIIc0rvGS-Mwvo)k6U^QRzmFZytPMb!-RO1bt)1C7DbM7TphGO^#0>1eM7|CeXy16 z|2dKv#Ewv3+4MsYlQ)*#U9dG(H%B2g_f>piq}HKdyyRyf#sRlK<63-pkT#_@7)Sw%sW*te*p&Sm;j6&fDt!p4*9=Byt#)^rSTneo}9U;m|YFh{dv z82}&){5){P4}h3=d&d?)hgkV9f8@ZPULWED`57c$c!!X@e6b7=y46EQU&vWGxo%n$`Rr7+KlCUu0I+y78YA zquoQ!@1e7c43&i*={w6i&ILplm%Dv!m<^~8Q+gM(s)0>+{l%i=jtpxyr{?|Uy%EY& z-3heevOhEO*EhFk%(Y+_uBGhFAkTgB0@X5AMXMk)ML~gy zHtL~FH6ljrMU}_*b@3U%ni;74%yfs72eO4#@mHFNJ{28 z#?|=#G=7_ujZIXgvY`+?+xEuhoL=n98qoUDFe%|#-a6#v&pvTe1#DWik<2BfJMAns zJ@@!*{?LQYA~_J(XpwK)pUWyj+zmAsIbe)V59?=*C=;GyY1FmjG+R|4_dfO821fz_ zNhCmS(EZJ)Gkf=yvuXjws@+)0b60Drk{$~3M{m2MJeJ3LGUvceD$388(8ITRQ$8xG z-7g6A91?dW7i~g}dVY!?qoVBd%@L!(l!s|y8t1&$1fq2~!hQbyh%iRSk{qyK^mc*fRn^G@QM!bjg zC*=(`6{>2dXn#Z4i+N$j?NM>n@W`a1>O7cpJ4d$43bla4f=C$ASjR-va{hf+xpRqp zomL_4rwTgSB^xnQ!hs!Uc83gEwi5%yyjmgqSmrx^f)|rMrunydwz^%5dKmWTK4>|= z2|wOm7Z=Vb%Kh12V%@Exn51xAQSB6OM5uhdhfHTmd}S~-7%|M>yy`~o0?v%Byrg0B91dk!`>(2C2QH&0_kYXcm z%0+_CJHg1)+4)X?i#jKPCy3&(;{D;4{n<8uBF5RYe}wUWRL;lQ#G6(5N4i^~tn@@U z1oqxGhJQ5rZM$20Hmenmf-)mIUhGS3vsRBt|7d7=wES}IJ%5`{=vKeqj<(!RtR}iG zc&d1JE7MuZfaODPHhW$iAW5n+MVEsHBcSlHwoPRVxbpijL5u*gs9D3YXK0b1#F`!3 zo0=1DpRbTTC$1F0YUYISln}I475Ipe@lGlh#5SmSRPBgso)&Xv%ZnUwY{>OX00;UU zC@5hh0$#-e7I+2rHd-HP#>{J~+r0eED3>abB$QdAJ)pldHrVKOMnRK;(YGj;R2SkY#de9smFVUh$X86ne!hUL?SDb^URzgG!Mub?=~nRM)3OMWFAi zaKV-g)if0qB$r?~4t)5sTz`3QE;Gjq5&@SafQ2;OZhysjx`OR;Vk+!ky%t}VbS|+P z(A9@G<(!eQodl=>!2f?kh5tEnDX!36R%JohbUm#AE`pS}+rCoZB_4GfudrPuoqmon zz^@GBLGPUDtHLrK+2|-I4&W>IiG!V-l6dBcGDS$<=P}J7kjUL)wN_8rft}5jB zL57*(D(OuSf427pCQJ!P=P3@{hZ4ws7Cc{^za1A&x>9Z#3f#$JzyT!JVnzIU%Ohpi zdQKIjawV>+dP{fhM1BZrqokY#&oj&Ahk5?UT@tS zNLIbq1uacZ`~tn?yf<>un3GgP(+}=h+ly)waG{g8KNcz>&2^Y>!@2x9#(9}UK4f2f zsXqR>X->1Rw7aR+#icHvnezER~q-Ku8xr%8gda>`?>t1>4==4tK8ws&3 zv8wo&8&E;HIh99(zOei!CmeE@xpaCz`lBSX?A#S1l(9WFqdXd`4PrjMbI$f}g$Z8F z@IqRzWi)!o&pu68Jrr__KJIjmse;S@nee$Vr9scptz-$FsI9&M?EC0JZ$$l`Da@Mq zoS?*oSN;Z2wgCd-dfE_cO`uOJkF56M)jl-KT(`eoWQbZa9JLUl$-A7))K)9zSm=tO zSIz{ddz(_P%V#P!gfXN>`Lws0wPy56ycZfq9x|UPRT7JbxJA^ z`Ua(r^SG67zi1NV{)c^tbJ%=Jw3JJ0IOpb{IwB?hY#C2QHe}q!_4AgAK~hnfpVZX9 zQH0@N#D2&rU18MW&wDQx7Y!e}i`XiXBaw_T34V}KjJLs0`M!&- zjIXT^!Y+xF!bM|3xpISncLi6Bj=tO2r7A1gOOUGG5`$@Ufa*Z*qA5)>sp$Lg6GuMj zSS$+*ITu55O-}~vB#+!9tG>E|?bU}uibusjx6ADs&AT3jui39g_IXJ_iNQgKY@+^D zBG^?kiUBrE@sFG-U#(Oi&fU9e;Y$&mGY>X<2UX+WRgX9fd$PK&#LWH-d5!UJ@P6Q= z=IezV?5#ic5Q3ZTI%qYAEZcOy0$Kns*#QGoAP$4}xsL|UG%uqH_9mns=uLtHZxlo? zqcum#{FYqU1TOsg%Xd!r6>bGa3Y%&`fIs}#?sZpx(RP(>X0vDw#G(~}pJGO;g%p(0 zzT6nwCyq`f?sJ>RtR(t8WO@AfN&Z43B91Lh*2!<}AWZq|h8IctTq^}o&7zo!TsbRSA&)Wv_V zR_rb=$c}f4MixpdoJJcp<|63W2~yBPt56&(;xSN3VX1t|V7E|C9~)P$ zMXk<3-6HI1Y&L2g?c>-HT`JkvcIvASVtE9(c>Jr3Wkz;ovNfumj{Nr}9_%Nd5pwF% z4OLM`d7Y@V7uv+BUPsm*wHc9L7wjxkv{ooU4Z^FBhFSao+$1djdc+CX{6~=wclP{v z3BJ;gqT>5!p6Co` z^LPH{G>qMKf+E}_SR4Nl*$c<;UC zPc4@=aXPA}%^D7zGOq{Pu{-oLA6P&pae_R;pSsD$11BRmBS=RuXefp9=|)%Ojd0ql zt7w1d?+4~TL$)tlU1*A~bPdRA9Qm*DQq z##6AorZPY+Hu67}B<=P)9z0fnTyXvN7!aT6HIhc}w4h7O`@Me#rm>vq4z1{Pf3e-+NN}4(|Iacd?|tuwm!q#QSc{c6~sGhC264 zKM6#gaij%|b(G#lXqWz7*S-%PsEb+2xKi4^9l3Llbs7Pae916wFu{GP&W0#Nki3q) zx1MGJlUZ;4jK7DJ+vzdb~Y z)I4S5alj{V;DPPgcYTQF-$jjVURg+30RjkEbY_PE&}))qmDa)2zCzmd<12qzVKzlt z3(9QOURi2XseN}kDYM@A`rtqo$j!tqh)ibFfwUt^+#b*hm-)c ztuvRS!!uX#b6r3n>*NYtZH9BRTy1syGBnml%x@>$?eE!HKZxmcUtsD%8Aqs1S0^xT zZj!gcLCl`6nWO5l(vrmqpk59D$l=Zoy(t@#NUb8x@%Wo*R>AuckF-WFHZPZpb9Had z@x$pb?;PKiA@X!vGY`h1wpD*gdaYlGJNbq^!< zW%W(4e?a7a2u&ONE$36An-uq#X#%Y2B+A9!H8Aoa6=B}c2g)))!8itq9H1`u(-#4n zvbL*fUj^6q@Qda!IF{E;h?rCLD>g|kP zx3G$JrS(F+TEM70~!K+N3qEtd&Zw${$2h4WTh);OM%@d0F|bcb~yhC}%5bDR!um#zzNu z!-cs1Xy)N`N&Nr?YWtOd)3PeAovZC%#c3@Keg4HcaukX&_ zLtfo?@AW7)EQ|Te1aux0CJlFIW-`dy+)jlML`j(rDjfxjxp8;FuR6LzIy4dkn<09h zuXw*FegL6y4|0$IaLvrf&M>vZV4KDWrS`=J=%xqi>Hcx=W11w!3k6`d-kLANJvxDX zvF*j@T5jB3?=Vpy^qB+4zWN=pg5vUTWNcDd0OVk`_o5UpyEwq^XY>`$noL7_CTe8Cxf1Fft=;o7MA9yhb;ZJ3 z0PV?0q8sLpuDIcVY-MKphc~3;>YYiOdS>52QA3HS0`@E6{uw+DhNj z8f216T{t07T8neYst_qn=W014hJc(h z0R?}65KSjn^I?ZqCOBcImCj~@m1G-0Px6U85UcP$#=eR+N=-?3fxjipXT(%4l{Kne zxnPP5Wd2~Iy%5;s3yQbz4tZEDSxj7ouL~V_e?R%0AazjVe_hDT&4D?a$&Y6$&Q`5! zL?K@*hkj`jiAZO&3mI>LL#$kU&>VfSN z!jtFjS>gC5xT!ouIV8*BxPGHGrn+%#t|FJp#=Dt=KD+0FDLQHEIxo8sQZOUQ_(2Dw z0)VC=k7k^Ww@A#rfgxa5w4vJig5&q_A2HS}PUB&hmX-1`QW#6k4WZlKygyXWl+yd9 z6Lod4(`)CKF6Dj8GzQS5akhAKlz!Ytc`aq>)&9O}ACt;wx5~PYz!E_gIn=N7=&b8& zqg>b!<`HmfO}GNjJVEgvOJWn4u86f`@CUQuitlEQ`Lf2m4$&>me?R5i9Jid4gl;li z&)sC0ONf`lJmaZIheZEBw%)R>4Y29j4el-O&=5j!cWr>+8mt6sae@|iiWhfxch{oD z-Q9~6w-%>V_J{Yr-+erLKmXx6)?91W%$(d;JcFPo;6Ma+5;n?Y3MOY!mqz8JP!q=s z%;z`BnV`CX@>fSYb&7Y8qsvdzunp|;og(I%IP5tpIda7Js4+F0EPr|Jz$X0RJlF#S zk&J#hiK=B~tD~768;U@Jt=ND?SJLPo)<)QtOAy_a+&&q{BSt^REa=hLm0V|Xs(q@t zpcM?*{=*n8nW9uzpX}YYphRu}007PBHMxhpkofilS`O9S($0ZUksj?sy!WiU$5w(` zuG#ZLE?=~^(=xnmBGsu=CM{|hrK}FMoj8=-*{DDbH#%r7$}-^%oNug%oNED$5nQ$# z7nZEk%9ZQ@o1iitE+&?NE=ra1bMX$zNP|VYuo%#Tzm4tRtgs~fkU{qW0%#Ul2ug8S zw;RkBP`Q|JbpZA}yQ;A-xeJvUuY;lH%J&Y8` zae?7bqzMHhd5sA(yv0r$19fGbBG6f6QZ00SoVpVHF?1}t7*7@FR!Z}alYEL>qby{9 zr0#y^pKraO40Zn4fD-3^IbhX%^&ynm`#A9W>bJm1nh~ozJg;!D5M56;Xwk3 zi41|I1U~Xbx`+!FR|B$KeIt%(jToVmi;k!zM$+M15(dtAjohxbUTKqWoZk`c_o3@= zU+#tum;$m`(RpO~Y0D z((NZd@v`R;GZj0RXOaxOZ@z3vhOjW`?B0uij`*WIC`cfK#tiaLP163I>Ci+RwDGut(s)Pl$5ho^t+C;Re~`NA+hi zT%m_5GD-SL`jMWELf&!#8h$0KFOS>9!nRuX!bMwu4ZeL7kM){5pr9Gt^aT^d!dppB$D*9?^!R#SYdcEnQ@D{H;s;3?Rf zl=N`T?fL3+S?)izSc6QV&*Gvyn_+6RlkH;D8LsO~lS-J`tI33Yr8DMm4s$B5;{Afi z?z$S2UHX6h`HR$1W z#$Wyb{i>&!m8!g(YEQcHv!WIaHA|~V2dGqOaa`SQLZ*2UWSD4Nz6<=1%6+unM6wF} zNT{)M0FTEI>Bc)0gZn4=1sqxiK~D_hnmEMRD3kGopbz6=IW;R-8q%O7Xr8tS$>{A> zbY|o-c{ZLFGjn$I=mj~4gTG8!mIB##Tg2fp@BaB<&Jv|TlG;-j{}or`DmRB(xlIu5 ziTXs$`!wI6>1-2C1hA>Ul$1fjaWOQwqegKSlhh-lA_=8_O5#9TP=(j^5nI8pjQ5Pu zBBuS{v;q4ykPLwV#73!%#TLX@LxfHg#1y?k_mmMmaF2lO4kH8^Ep4^Kn^bcX9ge(U zr!pw2Y{BDGWbZ^wVZ?k%jPu>$yk5zyZIm{ViNs{!%{8ID)B+tid?U_Lt7!HV=mT~{ z!X_q^hB4JeQh#s!Jv<1&WBupy^7f%bMLR{Ps;Nwpv!

      UVO+#vzw51Zt|@%=Fy@> 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%0A1jZRggSKFTHrqbY@HbBo( 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

      hr^bxCS7xgBbKCvIC406 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%0Ar+|&;DTd;+*2=y^eebyB` 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

      DQ-V|@qR8M*qiBaptK^lJx>$7!m#mlT_ae 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

      U-^z&yYy>v-tl9n%+qy7v78_6Q-cb^3 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

      F$ua@y4k}=5fYRA(+&Uy^G(X9z>M{s4MrwBy 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�?jT-BK!HV@9f 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 z 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

      eQ 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

      vRf4|I{Y}D9+Qu@?`+6O3g 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

      kUNk0qSn8%(C`YnIBu~ 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®+IX(e+%a}>8;Z5r7Ui|okY&<5iPP12$i&o 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 &LNm4cf->+?+Rf6UY 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

      N5@@V*dsztNuL z6+N>u)YlVO$b5B(J#|F=+4Z%70RQ^x@RxG;ohkcQHpVpn^6Sj$a$9?%Al{ITfZKEM zu*Z*ym4nBbDwRs`^l&kWTD|7Ajw;-j=(1*6r%D$p z)-bi>y&mElr8*`)H;W{rE-hSs0yNSa23bj?Pk7`^r4iLjZ-#pO=K0Oue2Q IQKa z^K!Q$ufV_Nb2pZ5O+vpOerzq%!(+U>h#nfWw5mR~j2@@)DJ`}SchoEf zb0t%h{$1%tJsl(0V1N4SYWM6TC|FSojRB(RiF;ix*}vk)o4eE~>xQh1!zNs4*1*x< zy;q8bOG9VZx7ri_yl$_|OZ<}3)YvK_`^m(;YGgVj`>=xc>xHA0pIfredo_#MGw&oh z{D-86*FSA@2wx>xm1`ChWY;!YyEO&Q?8G<;BzSv$JNdOn{@KYy(vgHn@C^R<$7dqA zYNA;l#;R3fnc^zk=>gLV)4zfKnKQSrm3ayQDOZo40u=p)NHd{rjw@S`a%xKm)8mhQa zn^8pd?YXTIF1o+};W6=0w?M|^(_=L8Onw@%b40lHV}Oi-TRk5w6P64Q(;H2`(%tt1 z*Zs-_${|;0jV98VqtmG!1XvYRhn!e9o}yPF#mbPHgyc}J!%mpv=`VM2leg15PKA;6 ztgv-qXTtGNbTJ>6S)D|LDPHoJz>ARkoFFSN{1LXP9rmEF3xUMxU}GAW%I99cl|se zs1d9izL}*-8O4T3p$t`S&aI&y)yhBmJvf!5|MADhc$tl0TB%dxRd>>6wD41ZhFO>S z4dJdaR-P^N?d5fV3)39pE;~GARXQRY94eAq{Bx@Fku{TQX*YtKE=vi`YA2UcQtg-S zX8++x{B2DZFJ*2MOqHgpP zwVHQn6!C;Jx`JXpu_i;p!A zb#4xx@wgV{DvdPt>Kzw`kAGzie_7;^iKEdnjW>6+f9j2vS65|Lecuzh)jqFs_Fh{y zax~>62n+Q@$W!JB>hH1#i@FqlN{avxItYp6(~ULjP1IZJRno8@epR&p24>aaa|QN9 zX26n~U#I+aDNRm(Mc120FSYYNuo~SXaVD2%2t=XWcPSn1{#muJJrj0qX#V7tqCriI z-JMR2sc5E`)&657)+S@Us}6ncv2URE9|1j~@h*N}&->j5^x*mA%t_^oY(>;X&%^t@(>jm);i)?=td_S9D@7Tr z;ZeZYJ?}vP$W`m|p)#h?x&eFVst7sjUz@Ry`e9;a#e6m+c`&k(+x-8~azI3_&Gy-) zqFcPvvz2&s6xct<2 z+)TNe_F;7-1)Av;^p?$X@8^I1!_X0K4Cj%<99~e_EFZqbv>DE;!^NP<=mjY&ED4TQT04k^YW1&X_&qGb+rClH!9_T zLk6MW+shPMtxbJ_w}Ln^N2mbQf>+f&OuM5VA82?iSy)zpUo)q8RkYa>(X*5%0r(_z z4$%bep`n0Y*;6vUV8N8xLrnJW#x5+`D*NgO6lin%dy8KeeX7=^G}yr+g7k&QuN8E- zaF(0bC8rMcW9&i_C7@QP=*G^8$owSq=imG*ccbJw1!1DRz!O%r znCfuBH?l5eA4TrRaA!(!w)=bIo2eTjJhfLuFKJBS4l)DsN%}>V%o)FVqQgRzn0F2( z=Bk#21qKQ-92JrnJ9}ft?kjT=eY_Xrumu*?HOo2M3F@U^w>40zN`yqXRUVhsN6B-& zmHG@(;L6i1n4=9Sbb9U6@~ua(CaZPwqD^IJ>M< zVXa)}llgg6CIwbqH@~w(6a8cltnVjwUl;B@x8bOX|M;Nz|2^eUfwA_cB4=>(WZdmq zai|HBImcb0nQcmu_Zs&;_XiIE0Dz`3{Zg8991M5jYmu&}u=Y3~UypLj5Iz?;qtLa? zrQ(OKb}M=DNC7ulF$^hx;;uSqEbsd=>51a04 ztM`XK;EhRuJw+qt1>t&rfaq2M^~$Gh>MOqt023IN2`C6v7)Qq$)Qrh>^~CmTNB%~?bq~lJ@071D4T=VXnv5Ve zGJ-k{d!}~AyvH`M&(&haTI)0G+5fC*KcGa}ivHO3xt&e+?;3>T$(Qz3)JRE%0IKtG z4`{4%%_a^!t5@y4{EtJ*TY4hn$mRGg*9|@QKN>j2%vmqxDRDI02_>N4Xg>sVJr?If zrY!`>Mzbwg|5UY%H)B+ISYocG1?f2aby8pIwAJ2TB@Jq^(V|qM<7CZ#I@ij#^61zJ z5K~*a%gTy%eA&<508v1$zx{BUUpD})u8yqve%tYpeRvmZzL&kH7=Y#4m24hzm3l{+ z_m+a&UDT4lD%SUh>Piq3BhWzk*h)O^(#fobCeo;Uc%79H-j-GaJ}p`5W<#jSyI(?S zbaNwhYOe|0&m#p=XRK_O_-K>fmG(xyC$6(iWkyq1?CyvYvf*=|uv}s|YXw*lq`kW; z5NlAsjuSsnhR{<>rh7WJNL*QW&=@GPma^4UmjM2cL$lD%MC+2@Bc{|Tiy`oi8(gKM*wE6jaE`*%qguMSL}+Y$jOhZ_E2TK;Il+Y8sJ>&1555JYxGYxtUoz z#;96MkHXyJOvWR};M|m(oKr^5?iZHeSJL;LE-B3QFw;FF{ij45DT;JEB`O793xeTpyHRU~9*B)j@9n?WI7Y zcSJ0$mTA{*mWn5`z7xfx7z29+Pfv+yrXrM?;xb%ouGqGKl){=ny#-&Sm{_I5P=GaY zT@)CB0pm;ZAIejUG^y87+(GSx?y_31W$8g5!YQT--?|$btOWh+;ue%Etx#{W7iEw` zfSe-)h~!{u>Ksftd=*=-V_~eBPETR+J=er3VQ}#VoD(;X)uEAh;^VpaSx{q7hjeSB zEzPop4JYOmQL5o~CajT?S~)G8O_&&U)2eMs1bHZZYJq+TD~Y0tXROR-FxyGRu{9zf z7%O5%F{il9kW7>x+4P2CTGz>a+4b#LZbIZOh(h0C%^TOkkS=(o-*W;nch|mIFn0vR zIKVtcB4(#H40U{cvF0lrta}Ri9KaNn7akiaKOs+F*K~E(KM*u~Zb27|hZ}QitI`ES zN7&H)iuA;bqGKjVn(oyQ{-J&U+b-vBv!it;z?XO#7+?|g4(t%;u28-_CCPj3^+@rA znM@oa4YNQ;qpn`R+H$ZB=m~y8TT5Y8MqT0KAlteFBt;6 zG7MLdVR@NCRZJ@W-F%5N-<9y2;R9@TF$dak6hPO;Bg;sE7Rw%W*4w<=s{aE_$SI>gV-2AM#z(GY_ zGG!}gt7G}^plP}b-qWAIMt9Ll+h*A)s&;uu_iYRO_WzhOh`_|)$88P* zt=AQViS})%$j7IFm;Hf%2JMx4DOx!1vv7+6U`2=3WICM8F;7mzs+t>&d&0RZA185Z z&Cb@YaW!4iIejjgV^?}V_o!%}oX0n45m3WUTn&!|;_- zRY}qy+i;nOMs*0~ynXv)m#^$Meyd6b@AS8e^gd;_KNFnD$j3wUA1XphlRkbR%;~Eh zSbRw;wOO=GOMsVY)5`5%1Wor}sN()W-=!bDct4}RbzvKI=wbP#{#IL?9eQws9tY7n zPmY#r{a*^ie`X4;OdZbnHB+6PVlANWz-%er3QhA ziu$$w=KIwA)|>;UZ;Jsf7aj%Uun>$@4_K#?R1XIQPX=+uaT{9Ur+)-x#_=RKknvoJ zS{SWIn)sbrr4W~swBw}>IIuS6i8Q)lma=045&%c_My>^rv_I@d{O%JyL5I37gw2|j zNoI0X)6&XveMP4u4(sd;;c~Z+Z*Y#th z8Ah$DgPEKr9PoK)!*q7bj01c7iN$uFNbzCCstNdT?HHJtxs^-6Q77hzSfi=WJKJmu zdkal%9U#C1pLWzoy0vR{#L5vXDJCFz>p1PQ+I;;Qj?>ZQ$&|jO+HHKtpIEco;V`5! z+<2SmGaz9{dAupdUl}V*_Z3T*9xy)bNQrHWIKqcJSKvb*v@{KW zz;p*F!-tbTRtsw0U6%C`-m}DTHhb6aeJ1w(d(1d`)x6#UZr^pN`0>0n;eC)f3La>$ zT9Z&|H~}M$S3ihM=9{`M)9jp|@Ens3amm@2_i(d?wUwq~u>8qqEf8z7YW9wBa-ZJx z6`M)T=A@R90?-3bCxB^W@k`PfmMO{xJKCPu4wm}SU;KxBN|x$BgvmH{h)RlfW-3sx zWDu@yOY3d_8R@WB)W_YTEMiT(%QsPcd8TPeNbt2@zWRwMo|NtzCAw`fc^qC9dVc^H z;8$CoQkC%F4?2%aE($WNOG=RMxniOP?aMuAZLty0xM`uZT%Qs=R?3iDf_Y zKZ4Uh2iqO3GXa^TnZOU?F}BFvvbPGw>%;1Bm$o|=9*ht`GJtsk$RPE|^xWFN^w(61 z{xQl|L1#@4*JVDIFcR-jp~WSi1FGZ%RGssxYmCAX+aQN=7meO-$OL|0zA~TzEsB>vYJzoU{EyVMf+~ZoX|!(OTe*|VWCFI8E+#oWr&;|zCw!lD&9?owwTfkABE0gu|%#_zKKQ0 z>zYJ@=*Pnqa})crv!NvfHN39}l&lBQ=S8TB)YsLKtK!B&JW&iQ>sv!>1npoA@PRgf zGzb6ypjJDh>QaI0=bRJfvbBTb9`EYLI?X?uZ_%NWxvn5rX0U=X=QA&=0539 z60Zr@EqwVD__Eje6!lN*AX1ry)rYiJr$Az)43pVaDyNM@|MyGv_J7S3q5}S_U9QP` z+u=-5CIdGxfoF09>7M6Z)wDdN(0t8$pW7`B0H6SbnT9DFoh6rq-Exje?Vs_wt}3U) zwU0S7wn7W_mfc zRrRkMJh`scT0S>V%B;_fTlFudZsI;Vjljj!Z5TvEk{TgxUt&Rd6y-`>%j|*k&Sy?R za(;oAZJ+alIJTo~;on3P*Jyy6BLLte))Z>UAy`A)NL?bDgUmGyh9P&NN0-27=EFQO zSc^yH+gBNqf$+B|2f;&?mq95-ee9XqG#tMiBIT}6TV8bvw>|W}^D{fy)t`#<#3?su z@Wk^}-&0nVE1ia%0*F-Bbeb}&K<6AOwb03oE=}vZez3-G>WaQ3#Z435fcB~!+1~U9hfBA zHiF)mlrb}@g5(KmD%@&ocb#R{njuTO65LllI|Q{xHi8SLfbob;m&ws(otzH0~KcgyWPA?nEXXHa3CIvZuzg zL9HbO{0~#{h*<(5Q>*b2K{xNqrtN$3@K4R>iM-7MH(3ATc*!U`+W`wsiqP)|M-#=S zmzAeA)SGicv@~e?bOx&Te%P(qTPjQnBX*-K*{6L^N>Y`G)r=rDbR7R#eXxA9tMpCw zOTy)LtvIw2DOcvL&@?+N)N)-tnma*i2_QrnSHZ!*Fp-FQ2$Q&0K5Q#R0mLHBrBb{A z%=j5og9}yBLwuN*rEv^CTf@^n#{?~IQBCVWdCi_Um6)dpYKVmgM}N6nq9L^tg-vz7^$$z!87*_P zjxBN}-9uW67nrcDhgEbJt37Tmo9)VkwB;1Mu1ZZ#Ct!QJH`aqjmFdDbzKDj5Zt^`7 z#WDy{PyW6kFXQA_*prwgk2g!NixMnh?PO_E6XRN*mUzS|Kj<}+yLJehMxShv0i+(# z%ao1e%wd#_J7N;~AZ{XcBIbz2nRxBWdJAnnj8-6b(JNDVb~cZcNA9nxJxGlX<^ zw@P<+cZZ}Pg3ll4dwzAE_pq*Yt^3}ewYPuGmh2wp*+D1~5f27uB82LRNYU2^i?Yp& zds8&q|CG|lUyc)PXER3SpvKV&q!>)X0B-MrhXi=WHIM^(nFvpWo!fsZ>$HQUj3m4GUz!SPv+%s^l@O@p|Hm%$|1-<|_+qGlDgP^0(QlHA!A^Y> z=EPV$AEMgG{_ByH=~FTg@O~`BYX{v?v&kgSHq8}bj!-4~rcd`X#kh$zL~>Kmyb z@@+Y2b2QE0@`SAl$LGjVjgB}=3mV7rGx~y>VC7=FKgKd^iNt_^(RM&%iWw34D$=`1gS2S+w*%Up2`uQeYBJ)(I*77n2pfvvu6b)Jd_*bHt_=kO;)f!F6u z@9$Ob)~C?lCrId_RK=(`G!;zZ4)M`6hH38gf3cB~8gn{j z7Yi90hpn|63Y^4(VysB{q%qs6rGZ>QZk69c;ri@I`hJg!=P%(DA>5U=O9uB?5?}gC zJX)gJ&8bHYhZF?B+Dk+N9#Y^emUMFcfoD#t|uEK=6=VAY&XA->5K70TjLZe{- z_nHWaVe@58uQweH@;s`C0qTH^2BGQ8J;THT7#>2DWi-}`0zN#d;$V}eTN+oy$OzKH zS#?ZJEym*KWBEOZvhL2g4cSsUo-NmYpeBfRUHM~|qP}d4B?F_DPT7Oe>W_7+T&BMd zimcnwUR+&A$DzQv`aADs8SZ+R7H!)wE;!>Uiy@`KmZhqz=r;;L1^@sE{=-I>F5&m% z+zlHMXVfj2x1~7oKsl0AO>)gZ13YDq*wuqRy}~c{qf@oLuR5eH9c7@07bm>H7jBxA zLU}!DAuID%C$6zz-_-6D7B~Vcx*994)jWMN62Y&Va0u;3VF6kAoBlV^6o!Hi?qD+A zW&9kt6z^i9JqC@BSn6;Jmyy^V22Y@QCD&(r>o5N;xdiJi+X$7yM7A!tC_{p}XojO~ z{&I|Jvr}^l?F0f{BxdWpyfIPVS7ke5ZlTsAlDtp}(ocsnY?K1i_~ROKh7m;jbP_j` zcsk7W2Hb=|W`*>sl>i;{?~>=kAxcaOwb2<+gZ9$-SP3>Ujqe$}94|f0Pix)}3Qcok zD#D|Qx!;uP$ac|T^ISoldGnIW%K?8poi3FG*`ppX37f){JcU3>4rWBuuH_v@eew## zp{M{_muL!1+4#-7T$&o4|{fofAZG@T_ z*~bW{A3}oMEaePY@yL~0{bnVH+L*Rljj5;mWmK6eoKM`XD^SE*j;k~OeQVvd$z zB;R;paEmoi|0Ma9k$${Ea#la_awwDODWA1d?w@hFiVlmle z!eN))HhjKIq)@6K7bDColsq(@D`_aQq`X)$gHzM>${2JJfsH1i&6#l_9g32|wfD$OKGZB-3sSUszPJm@V9V}1i`zYK_i_#QlW~Jwpq3C0Ny5S2hBWq zWG>&?W7X&t5|F8k0QZB2_DcpKYn$)sxvYyC>EUsV99=+Uq}x|(FGU($VoKwTMBO*- z=GSLpCOYb=_CLVWqtXj0^zG_Vkc396CQ`h(>}P#XZvZMF3z-o@N8OYDDL)?9n@hl62+Szm0;u;DUuxWb$Ltt?C^%*e%Cy(ETftpLbi-uX(SM2 zn&k08+FK1X8Xo2BPu=lBKG%-Kp&)J6#Q8rUiLdph+Nq&xTpWhED9Q*fNiOs_e>Fs^ z@rvo5p#d~Q7nWr^C({?+KjGI=FWI!RXed7mcKfR)KZn8;XLgk5}iKyP!aF3;PN4St{f#BX19ltFaGx}iR|N$x3zf6T-~79%S>I+aq?X@7`!3-s-- zBPBFTCF>h<_EyDeD#3?c=8>W5dT3x5#@SfVpu>!_(fw?_FG#T`S=?(A^&!-~B>C4K zsZl09Ud?xlvar*4g;pTu+O`b|-E8xi;kgAfHy>`b0TYMlikNCUTaQ)`?x?7Yh+nYW zx#lS7E%;#!bbuhw!uV|7m-VopDVX7sY-ZXY2ucD15QK2&2+N(rcDi7FX=a+<&cxp; zR@m}nWTz|`F$pr0r=u;}COO(-nLg@WNR(u0ccTT-RHz{StYTpvL&XfKWB~hnY$k-@ zrsasctkI)qE!gO_=m_Ka5SQO|z}BK9IRcCxr!jYmg=)I}Fjz~AM>h=n7V`lNs6uV! zmpo|3#tw^6#`Ii{G-6oCRMIX|a!Sr7^K2sYpv2S;j>kGK8~5CiMMfv5lNEv&9f_=M z`#zPCZMOpWE||CQQX2dUv}&g{;?^RaRsXp{O$)Po(R8rM9FRv()(aLMGClK)t5th?s2xsMA72zjz#6{q- z&bl_3WvBXo;#{!!zn4ZNgfOI5YlG7Zuxd(`pN?pBp?Yw(OIZT}qC&&v$vwOt2@ycA zuZ$4r-RryUkyXgY&Cq-$pM|J}+)^^vnG?vlgv`~G*WGfX@%F=3MO3S5)06D@572L( zuS)i}zNI+yGsa8k$La0@e5i9lD|OzTFv8%gja&rnVk5*w$s=as#1(XUQxbr#rePELCN25C8#LfZ*Mdb1uGl zYO|uWVz*4cK#94$;JD=0a$%Nko>q*{u?~#AL-V~z)+4hEnc5{zB8G{b4&NQM?w(SM z{alpJ_%8-J4Yz=>JC0+THpVqFkgt!nXU3}GRqRH^XyZ@|Y73XzyH2P03o8>J8iaNE z4vwO>L$k%pn*V#qHH=x_SOE)7Z;M5$&{gPW@ zygGzYDt2zMxB2tCT==2rN{El;uPl6pY!1`1t+l^!s;(0Kq)))xk#AUJHBC8VW}ACG zD=51hgM_kA1C02^5vBi~<$_H%1fykWlCj9(BBN`#E-;U>;^{uE#;fv2I$M0pAOHu_ z4Ng)zMRUc|+{(6s$4?On$eeUCe(xEVNRL}pf0=23d>60Yj}oHSTs6f3R)#1vS-zbv zM@cU^a&Ez!C<#T0*%4E{!NU)Oo8uybY%lXEnB-U2W={ptj2%|pk!DXF0qE4fIertQ zq8BSKd+Lg({;oac;aF_O$is;|{Oug^jZ3rC@Yv~{Al?o@0)S3MB*-IPp3B4lgYtwx z61=-Etuc)_4KQZiH+cqMmU0sx@Nwv*^`CZ_c%Z_cpa%iX~m|0FL1 zFFD4=GJ;K8m|rQBj;+iFNKHe3TiT_#H%N=0rtX~#UL-Eq3|bXlNwwVblUk!ElzA)= zl%8ZJD!1I)?8k|;D?U<_=Iu01=EDB*=dJrV;uYJxO?6`EyNvV^we&0dZ4VwZ>wE>C z`hy)mQ9M_6x-Os(f%dy9&k6t$RXxo?W~5J$<{Q4l*zQB_yNSH0jF{+5HFSJ7guz>@ zFAjU%sfTF>7ak?w{>&Irxp+~hu{tX+>eFYm8qve}nOUpZD89_6aEWTD9>CU_=N-4z z|K56C)r{9hYG&uEeQ130Pta${Sv5THsMMRO-M13CYbrNG(UWT?rHy+W!L`y#+H7*M ze~b7tHr**Xi~7G88q$SX8l6V-N+x3Z!MPZ8)d{|NlocmJItEcQzCr4?1_tBmVU`MJUC{)tS0^jWa?VdY0Qo2H&?TqgmwZC8h3XLX+{C(%3{;@2R4vd32{U_GYg%Wd)jS>L|pC;m8C&aP6&2%zA z4eDC(M8+bK*)wP&@?cd)XTtK_{BOfelIz6cm!%X+`q+(0&C{(J!WBK~U3!XXkUod| zbEc#p$d*nu$R-G&2?L?Q_L7_eM{&ZQot=w>>8912xGQ%Yr&V_eea)#rX_#~a)W6VF zbYqZ_zq#h+tgwp4aI<9+(G>jDn*+bnpyX@<$w-*uMVbZz+}aiw7+yQwbh?;Z`~cd1lBiE%Aa2zeH$D*CNn0?dyCpln^ctHN<4n-822_i|KpqFKPK1r zWmD})**tmTCD$whs_v2NQdYc(F3}7<>1QZ^-vmTN;P3*`(Vvp!Fvystzl)sxTv)uV zM8#&x1$HqDsHv77q|xV}valDFv}n)r*MF}}S*Nj%Uus-3cr=BQJ`W4o z3~7`LbQZ_ivPMr1&O=aV8`6uijm!r(qE&Or=*VJ@f@+wQCa9_&>f;V+7@PRlT@r%0 zSKFqvHfa{^IULoi00QAEsW`N2ADe3 z|EG|dtmRL*aalxn4n*l`pmap?ZggXNpDUGGCP@ia-G<8}6Iqxt>l}v5YgHWnHbPe7 zx`h*6w7Jg1$o#1uN)2EUm!kq82wAtkrv+hjYY%Aeah!d&3^6NKc6-{8;WvVdVht+k z@)NMB2<3UBB%ZPSc5yK6Oyj{k8=2*tcWm6Sl=%g}9j+YBNDgGn)FYi8Tq~XU`BUD_ zXbg-09DSt7Jjnu3R~V&9a~Jy+PgL~%<0e8*jx+>Z`Hki6U^y_x55jtAmumD!arl!( z@7DKDrgHqCpb*5AoLq#EZJwxQAsFw8y)4w=oSbtKXSQ+wTpKoHsu}0sgsVaZ#aYO` z%i|T`&BWC6aA63_RU-vg`t)m_pB0lf7hM|^svEddLAjGtD&k*b#Kip9lT~#PJJ%M{ zq?l{8cz<1d;d}jJFVcF)UCZf&6(yJ7GU&-+Ik2@ECSOujpSmmLm1EetHviv*<`<*W zC_W(U;-yEFp;jHC$fvl64^gQBdU8i=iWD=8N+*GB>}~medOt*Ml?=4_bD>awUtcuc zz%e?m`vqH{Lm=(CGI1Xrr)Uw2U>7Bqk1)pNEj^iSUfUgJdAQyoeCqkxNl65j8J6^( zK@kg3$boHp3R$(TXfmR8UII@l6Sq3wCTyIFIz;fP@-gfcF>FRZms*75p*NDDv_P-d zE4(EZQOmkt1#OiPFQ~!*;>ZkOni%)Sn(l5^vK+GVD`_Jm5giuaUi!^5g4#d#59WFp zj(@ZD=So+qh^$7a{an9Z-5HUQrLSCdc^;E?JWv^>L2H34Ld(H~)qOB=YZV9!Rm{mM zxVS4Vkh%ts(}ZBWO}Tf?)Y(4gG39)yPjza3x9I@2v5;>)Q#-NWa3NPf0{EOw@~@RA zAJGVcil2ox@t&9fm{Oq27L_v&Ul2Gczj9Aj?k>uHmBo`@r~Rv0+Dcx6Z%se5HZJbH zk+jAm|IPmjM(l6?H`{~gKsS_ty^dHi*_J_dZ&c8I{*T?d4lZPO7o&R2%z}wWXY$wh zdMh8Wjh>0;bN81Uw?=#6A|Dq!0+G@CahN92Fal5y#Jw{1_1_2dE35)wX)ybImqPU% z868AA;xTZvtwwSBDq{1cb@YClB9Z2EItECPwIZ3GKN7@IQBA^VAv#E>`6TyqgxVx^ zqV4)U8YRkK38E0D1v8g53}ki^1~sje5AbpRcHR`(Qum*Lq%X|-II^9&cr|vfjJFGZ z@-%vOwq3#PO(rd^RI%99hR#%+*OC$8vN2JS5dpmaXSwh{k_$37oQ;+?PmRNf6J@Bx zm5%i&%MwL2A+ZXM7a0bmTE#w5}15`HTE~+9N7>SB5 z|NbJP0002M>YIvs)fAbgH9b|!DCXB~`y#C|S(atOvqd|!xuN;Fc>dX?$Wh%cJJfAn zr@b#us(RWV$YSvM;%xS7$bj9h6~&Fw4bk*m59uF3-kAAOn4=esR;MKCskto4G3F1B z%|{cYuT$5FXvU4onu}tflRG|vi*2ES&SU=X!{X3o3jiRs{$%Dy5>UR?PB{r@0U!ZL z(i}9fXSpnNlu;MpZ?>;Kx1Rz!ZZ38l?GVURRh(O2_k1tb-vjxG_7*|2BYv|C5SHEz zBxgW)X#fS5otB(jgl&c1(O(XENVbwvG|^jTOM*!!g)^0muW^|%YS*l;RD5DyZbpv1 z4)>d5*4Zh4+`8WJw#Lts?Vo3aZ|64-6l*o=@xlaX(IdZ`(j@^90T2S_bb+f+gdapZ zn@Ib0!^nF`Nk<}ePkcROWa(EUGd^>Wy-b2GAVo2YHotYW(GrT@Uz0ud4RvL&Fda

      UpZ~`XE&eotsb9SR!Kl$Css5vPnQ77bTUQ&EFK=CzSW(@a6n- zyr!p4_~NL4h?2$T&A)}%zTcK0oBLYAXdRTK2;~5krT@jDZ=N10o5wr&)o`KAs7n+; zkLwruG#aj$9_h2*4W%OiW?76MwErnRI5}L@_-4!IrA6_hy?&eAwxiZ;^0`dRo_Aq2 zsMc4-eJ>jaT10jM{dNC`UhakLN+ zE*XMOm2}7%m(Yqdu9T6}JhwolnNKH5(W`C0S=2^HE$&7nBZ`wVWjKyFd?~xcXn2_I z^iz{=DPFtMj`L14>*8aX?meVux>$+d1xsn5`Y#Ms@<$-J*#^B5YvU#pp%Hli>{G)hwoQ@&OV|r>?7%7d<`;z&!X)|Sm;j$v~%b~Azz^aHrfU@$6R8OiY zTxjeiGi)R*WtGFT1EgXztbe7JM)COj6U_e?HWdH~u*sH!Q9<3tVJ!DET6-5=ZS7Iv zljcL(u=k&WPEvYR+^y`;(&`~(TgNp(K~x*5i%gXDIy5w^Tv=6nX<6%@S^jK6LZ)+k znpotZMf;<6-nL{g;pW)&XL(PgO#z^KVNnU*ru)8dRf-Kxn}?lc zolu08DU*}kO0(kJbPPi?}20+8Sq8@8u>k}(&4HS{PW>XRu>WyOmSH7+RA zBgqq>Fam%Wgsd1TqRibP8S*Hyns`AwY~DO7FWcyg_sF&#+l;l;73+OnM~KO=k2Qxx zsD-xRW3?QLXVY&4h_z9@|Zcl~-e!CN7loWM`9!IYL3BPo>1q zG^2=gRy?xj*RsJ{G+A}z)ohZd>Ptq}xP69aVc+xZvS*UpChTUjv1Dfd>P(y_DF^_N zaKp>T6+BlIVA9C|yH^U)5{lHtO3>arV7_;ReP%f@;J>V1TGY>@-S&;cPPtg(@^aC| zmIw|zPQg$7w0mv>Ry4|=)h0kal4hp|-@c4Adj#1dtv8NwMwct%Pd&#Ul}!1mkQ}}d ze)K8fWGspf!u?zArTw2-vaND zj$O5xjLqV8Z(zO?q4MA>2mOJJ@-5TFtb|KgA%_G?nz6H_#3;#P(^R&m_LoxDa{RyI z1?8-=2aPDSXe}bAak_n-q=WWcOK?KPQ6*=+0YdTn_(2EhEZ(eZC(H6@**Rgt2$^A< z%QUNdy3X+^3sk|CEL1x$DaLOLJKjN2bO=-cL$(!)ddVW#15YSo-j~qeEtQn}<6%a7 z+2y3Tu+r8EsbdMsb45M{u8`TjwT$#-lP6N}KH8^uSF`N_w^fc7p5_T_;#1TXbsOE# zUv?}PkF+wU@ty`90bU!g5ISZ0k&HAU@P{kH_3LjyF6%M~e))?daA;MqP zntVbdlq|lUR!C07$&}Uqb>{p(E!K1!qtgf#@f0kw9xjF@T)iTXvJyPWkDOOFk0dS# z#9#m*3RzK+{UhHVPmSkN*gm*uZs&II&pqSm*kwLJDqE;g>(AwqqnNu2S!gq8=;9v(j*69Cc#CgBj8Nx zKHqa_sjD&4`2OxtqP^MjVW!}xrrJk~B>g7l9h1es9+h0O%HsG-!Rzi>-0c{pVue=vv22j9uJ%-?b|$mh%9BLWZ)F)gWmdwMhv*(f>~O{3QLTy2Wj zwM*{nsDS5>J#OMn*KIAv(q+?B{YOHTQ3ZljEYzLaq~}D{8NQW<4ri?CSDMV^p(hpj z69c0*U6JrkuTPwwJDVXQ;XjYk2&! z0q5v+RR8~kW{l;-5pkb5CO>8sq^1Y5MI7MUOzqqFpwo5gcbW!k z6B2lz+Hp5qhx!T7pbP)>iCoI&Cqq;mB6}|{lD3joZSRLVvZIcXrlJ+N;iN^9@gm|m z*Unc!lZ~y->@KFBk;FhRHyf;X8-4ep^tJ{_ITG6oW_q zYKTq8n9#?jzii;|&G|T}<^Tkwiim8UXX;+xotivsnlZ>qS_82B5zC6&O)x1HgYDCy zU$K;5pii*gcJ-RS%P-Z>pt&_H&L?IuzVd)Gh=xM1MtV)5U0i7*i>)cX87|b2E50qQ z5-!a6b6-JxI2~o~@b~@Kw~}{u1I%g7VsGpxe9cPAyo(K$#XF#7*UTB!#!+lfX5s;hlThSlaFpB)USQK002s3 zFH~$MiO|G1o& z&E_c^_fEoveGeCdGOn$kOJx20m{ue7zMm!wP#z5ciUZnhl77VXVVgM!68j54cIDqu z$y=7=wCPURd^h(?F%Z@-FmT(i!(k7&nBBb0n}9e|wqu>PHRUZGx^^<1fzRpBJsK!l z4Kl>}=_#W)38%hf7i3 zv9cYwEScLG*w+ku5*we}>~nXlmU3`=9R2#U(nwLG!NN*C-troL!T!|X8x0e7(XTjROn&24l6pr@BWJk;q;6Amdg ztPh`7i$MR;_`(@rJ{=3zoXbz5#0R=*ElNl9sJdd|29UGqg_8d`u{26NXp<(L(ur~~ z!ey(p1><8JXtOM`WKM))XmjDG;Eon(pcM0I`hR;@0l*Iu|8JxFFUjF2+HBfJ^ZZJ7 z$c_<>2vqMV3O*v?*pq6mrFx`(LK+)H1wfD?QHK6Y3~Ura^2T~J;;0`qN#8Y8xpHzo zx5|7j%F;iozt*lDZwOG5J+7b^%FO1W$bk$~wckZPq-R{KQBK-3dtW^;Oox6ATg@ZB zv+U6_`}3Ed7is8BJ%z1tmPG_des_e5NLmX6o%cjU&|doB*YKw(h8Y;K-bkuT7^tq^ zYRIklqR0E@I)DlRi3$OT9*gFIw=7gnqMv0j>;6;yW|FS889V1eUP}Nu^fyF9E{}Ju zt}SUnx+g>VakGkn6&31{tEVVj_+9PyDc{N135 zxDudH9kP_?-94E#KI&FOb**y9V)TXJ^mxtB3auuR6)cPrgppy&=^XJk3b-#WJy1~qMPI<_3TZQKT}@S7R{EJ2D@4VAl1xb&BJz`Zou72b5w~ z_GTjI2&3N?@*N7wZ|A9<-o48t&ReBLYp39+SYo!G>F^tTV2NTC5@yjY3v>w^vGa8d zc+5}l*d}~~KI9$45;({yiRX*KU!W97HlC|kOIL^TlmR(10?)QdKSSwP)`zMk5(fD_ zXNhVA$MHu5?94^K$$}`zQ`ziL-IJp<)N9!L@<1hjvJ2AxYu?p}1OOnVS#PMF@Jl8; z*vE@TK-I&GyvpjQL)4p~?)PvXz&?;roZfaYD}FRB+mXwhvx(tCnPbeK{q&`!eVR0j zI`>?;4V%(3_k6Pjis0}KtEQTQd?r17m=%OV~|T4<|P_%SIqOi#P3KF5?BrR!V_09ELV}ogFW?=VS&+N_aKat zA9Fq5XyS8=nbu#U8^dC>VdHpBv{EAWN$33AVPkHev{qyz>4pK1+nZ0wj=zhqOeSEC z--HFs$9Zv)uJ2^chV*$3e^co0#=Op*7M_th2e>Ur%IZW@nl)}$2 zlZo}Unh&)aoc*vTLuicv1DaDh*L>j*G}%ZcZQvximP&Vwwpz*3iXrmeW{ zNdLr|T;GpRH}A(1H@jh}@5oACMWng*IYz2D+bQzb(tn*Z8+ z@r5^A>5lmTERub=8*LU6{Tr&9#|ulAOqqCiR3@z7)^0zkj_bkc-j8d0z8a=WVhdy#gK)LaQCx(;siPd;u5FymT7MIrDK@fVCl96LVN0Nmx6+9vq>Fjb(9iI9t2SnPA_CT%hW3c z6bwzJ01(ef+GNZD_95p??Uoc&IeUR0sy$#Pe!xQ@16J@_~WJIjK{gWkl*2@;6 zo7X!U?7p2rb}F+QG4gWFG^-eM+HJrsaWpQ|r5&h4*Qk!`qyMqUtzUS8fVX@;z1b6+ z-qR0HWUTK7cQ3P4!mdwx$Q2EFaf$%fV~QEI6cN`Q5e*0cP-R#xltnKrGpLXcb3zh125QvV?|>%Xj@p75Dwvf0OrGG*ch6nT}>t(uGR z)OtjaCIJBA0AcDN$KG`ZOVaX7r(_%I3YC_e(Meq!6#2Odsie#y5+y9y0THzHtdG~Zc!(ykq~q9ohz>aiUMkiP=} zqUlG~Ri%wWz_)3}?na*Fsr6z(UrN4-1MhIw{(uL9fnAn_g{6|Jt@(4})KA%<@SW8K zC6(GUu5602hnOolTvEHabo0k_d9+PU3R}LSFhiz|y2;$mazBko{Cm?~QhAUWIG#^i zb2e47UD0)BKAhY%>m)S4VT|(t*eOYz{G#z{5 z7^fSgC2|F*=SaZ-IH)Hp>&aUHG~FZbW}@q{N%&Z&Or6-Z{Ir>`(0_R)I%Zu%B93HXcXIZv(Y)Vse zmhO~^O{Cw%1^Z!2)AfjC7r=apcB{LksJG$9{_*^M9aqk!q)&w zK()UpCfmgSz4|O#b$cx>?r#E3p}8D3!#nl|c8=JgoyklU)n&Zim=8Wt`iI~lGyW6M_hsHRIJK@(w{-0hl+hHX_eJ}Lk}g5$U}n>>l6*kz*r+dh)% zo5dKEJ&MKgYSS3@K_Ci^Odb2WJ0WM(QAT=SNAPwxHiA-K@^VX-4d0yXZ60@Iew<33 zurHbECH!r@s-dC0p@m=d&XW$RR2}nfWzG~M+A-KUuMtcwRp!$ID9pi%TDC4b{^=6S z`6{{F8NW*1XdkehSpE89uCRj;L4`!8*+AI#u|w=*?37W4s;YPksdTLKyhNDEM_PGw zQ+g2*W{^W4fze)*{Hm+yQ1NJ=J2T^J$Z@yp(~wg4z<@X+#IN<-Zgr`@Z>6|nK;4ey zpz)X&qlK1ra=>f#S=`qSXDmhWC6`|8H5nKJ0=HU3rBC?ID4-WslX68a-kV#;g}?&JjTl%SXYQ)51^C#hHo;xJWQ3w_KBE>T zX~imf3K~I^dkYYuc5$HJeE66=nj+@Xp_(TK{;j+mof9lD4mIPHQU(v`Z${U8Gz2-F zIi2M{-Slx|@-Vy&nb>^p8Eh%lTw-|dD)*Fe^YlI+i7E&QL0%w9sp7WF%?9fK?8DK{ z;$gKK%drw)#ltyA<36PAovwLWM!UI!*;kvI5n?j`TVXog1%Le> zn3lE3PkpsZ{b2-D{Rv9HaZ2vB^+-Bc4KHQeRrB&H(~XmE=QX{qBUkeXxvTGYn;}?R zIwLBrv}ixwnVWT{U=?q*-045JsjvQnbJGfDU5|4hEzV0JxDO1NN34SZlp5L~npL zMc1%`Ul+q?$%?kI?lvcEQE%9lC8SyzkgCSPWr+C$$JUYyqZBGca41hj1}8NvNfoHS zmoAbwi>$b3Te%lvTd53Apb3?D9aoZu^k>K5+UvFZk~zL zTv@)|`A>7Y9ti+I%COlyO_WZ8IjqNtGS%WrXSGwYEbhK!en~xT{{i1u)j$)t4>KX)vC+IUZbhL0T8H8&=0Jau*&&tN@VHN=Zw zhM`X<*})elcUV9%PUXEJPDn|cO5$N|x+I@AA`neTeKd#>L&`8Rx92FEje|}5q4A`d znu{#ceCge)Zp%Jlu$o*^vdlt}>bxyC=<1`Ez89=;0suw@0Cd{TW^IpjSX66;sjL=T4YUy0QmVu+F%?!k@dG_E z{!-fBm2ekZl|7`jdV?)`;3HGRYJmC(j6;iEDMSl_y3$vdvJ(6;5GVUdKkX_Y76lb?PT9nRTN`#z6?>8z zonVvYKsVWCAb(V?p_Im5rF?03G&y5`p8UAO0$EU17wRX$&-Xpe`$q6xq}Ulft|*YN zhQ7kwtn}8(6M6r$G&3#vughB4Ja@YUh!vEbdFZl9f)9%wS>Yfsx+KYFfv$5lSZh78 z&`kzp1|4t;Iv}DBi1U9 zD9PFSp`XHwr*z_p>Ob(eXRqQ0lVmYRCZK&=wdFo){(_@j8sz%fsh`l`R2(NI$vEhjTM3sg+oFl8a1k&j|jxxDQblL6U+(rq%>CYqi;^uBN z7w@cZzcxv#2}YffMTvAr-X}+sUt>Kqrd@TkV^C}ZCv%@dITG{hh$GwL6f-`0ug{me0S=P4J-W+Qa>~w`oNM^%*K%>}4Z? z;Kc3$TKO_B7qlc-uZ_kigAN|;gL$Wk=+?opILx)`pAx^OSDMidRru0yW z|BA%e9Ad`$qU7lVdT|40pP6V9hv2we-1=5sefl5Qo8?{i91r`hxO?|)+1-nYZZ<6#CWy}oPJbE&Q zkMm~DLTLoavyLvjIu^7j%$xX=okGM-%}s(0iT8z@t=zwNRk-hxd>H9grXU8nK8oE> zadCy#S*gxAzTQQ@J8)q&%+CjwBeY>G17v!H(ONf2z7I_lI|pL}sD?OnK?RbCJ6P`& zdshddeUzE9iaAB1qB6T!a|K>yqOFsS?US0rycj>i6`NWf^nDwal}b$;A+40sTALpf z9mW{*?&Z;)>0w-xqtf~=P8boJnexAytcXP!(a%`J6`buuDg@s+xEL1Ix#etyg+N;i zGsP1v>@gPy%o$YDptL%8je}?I8Sd41Z`%nb? zG>}b`M1m3J@;Qvw;_<|=Oj>9$+;*Cr5XJIT+_R2bBypo~*a(=JuGEUud<-o}W8CO} zvi$z#trp~<**#;+J_>aFs(+=pu#m?xn&brk!MvhNywVQ^;%YjA-{O<(pd|`Qjmv1ixX_cK+QuKK4)8% zs230~lg6VePr5TnUpb`#hI%e7yC(N{jIA?45QOJ=8)uakjOZU;N}uuf3{#ITn?!j; z-)�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ⅈ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%0A(m8Elet{a{9zS`-@lV* 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

      A^(LTw9gr_<>^KPuw>H1v}rUo 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 z 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�Kna4U>$rh$xeLB!q2+$WbbH1f1U1R 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�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

      ldhY^Loe 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

      ?d4Kf|H@j}?M$1% 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

      *a_k03QGV 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
      `+{%clZ98gT0Lk7CRq6Krecb1$+!}$8Jpu0 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

      aoI&#El%5EwVGJ}~%aQX9f8j6ivNaEr$bntiv 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

      Sk}6DY%$Ww6Skry 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%0An=#v+8S65zK5L}&J2 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%0AgCs^4sh=*X)X{I>>U|zfQEb7;OQP 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%0DY3x9?6-lblPlUuh{IQws4}4d>hNO5ua<}Bji_9 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�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

      &}uTo9vxDcC;oV^Nj$ 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

      8t;@LAU}0{nFL+JY}P@TGpm1`TU9 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

      XyC;of1L` zpjL25FzaQ(6EwY|6W{*TfeOu_*P?-+|6HC|K#gsXcoDIOEulytc!bEQ`WQG?JgAXE zZ3W6e8n5^Z(z)%dv$yS>37aC$<6ZLpKC%?W*x6kC?V&2vi3rABsWG2t@arImOw2z< zHkGbTVYrhcJXZSveY!-ZQ!JOq`uATt#&ouA@bPjR7pnvSe1ipya6lpUl4aYq%tD?N z`^Qw|C+fZJ7;MbiK;f5z1dt#;1GxbVfqMe7q#SL_XoTO6LfYuEk`1B~ja1fdx2M!v zNI+Ja*_i?8Y4w7O;|vc<;ucaj-G`t50cz^d5}|l9C~0mEpUs7Mk&FP-;({L zv7IAKeq*KWhT3mYkW6e4%dI2UZ=@O#D^Mt-E7I0%V2EzdM=YYVuKAzd zrdkzaA40#_B@;7ax`(5D;b4*Y=6TptHL^kG5`017VAL&@qW170*Rm4iy@p?T<>qti+MCpNi34`fcS_ zPHBMs#8dG_QnhOA=8FL&4y|>jzF=3M*Qou?zwb7?zj0~W)iK*Hg5A_lyUGxiQ;<=+ z!_V~VVH@ue54QlMFS1B#*1dMP3&fR;mOif5#j8tDq4)L7QFGIazr~YL@8!VtgnGP9_bPH(*`i-85ia9sgYHi!+n9Gy! z+G;o9ew1;9oXl2tjq9(aqfh4)jl>O8=eEy<4}J;A&INbEROF-JFn?#S>V)vI56&G4 zOtYk_FsXm3L_8bg^kY7l+lMndQH8koaexZ@XOVS=xN&3R9Ed=9Y=zdK+O~kMz3Fpl ziZHIrZ~hHLS`l^G5551|k-);Ln(Zznb4#T+lH`ff4`7c)yV$n!fz-KO?Cy#8feHXn zKsV=sie6c6V;2>#3@^Mfp`-6$^3I6*gmz3`()vdAo0uDqW7nofx{_q^N2*-wPG4^8 zBnqNTwRk^{z&^&c-P2{X++Bjt4GIGN%fEi#or!5`G=;pPG=+*`LwCQW-llQ3G|+>> z)*C{Hq5Z{YYpY+!253m0o-#>KTX9zY$KTIxWEMHro8wx!>*yNavkgg;ramy;G- z9$jb-0<)=)$2f%{F2@Z1yCGgp-WrRq6@5bQ_!KyelONw;i4MqQhPy4BM!&}XXG zmdZY8ub^D+o%*yCG2o>#q{*STMn&)KHzZcogi&}U$*RrgF1XhTy)S+Dqy30A!dRfI z4_VE!C4;8LxX?R&w-TQ1EUwznUz7Irgl>K|XPnubggJUi5qU)}AC5jvKuk?8iZfxy zIdFaBD$U_5lViU7L*&LH7O+i+d*w_eI~LpcwHdF?{>KCJ>%l}dDchkh7hz*L`Z>#i z6d|e_rb9)Mz^zKO9ioc;eJHFi?wnLf0}Hld3qNTkZq{FZWamS4R|% zrkjG%SU91v97$I=d^T|piSO<8bNk#;Rf^082Wl`SyE0>)g-tT2CGhLeho{SY#g>JBr7OmdwJ!bchDo+VLpB3@$FYU|zf;Hd3D%M-hD=#7 z=^D-O6y0acJ^j8hidhSflrOzEsbSv<@1+)8lG#%1hEXXDsE89d;c&Jqca3g5#x7n` zBM8ki8DrYmdrtvH007)Yphhg(baWQ`9ne`JBU!8vOM+UArml`Of7^}-(TVS=6_>)p z7%Bc0IxZz!1ai*}w{Ynci~%J18^d9Cq#$F}_8uq9v-(LO%DhG4=1 zz%J?nMnt?TvayMFR6Ui|_`Cs3MRJ<CwMc8sfeUNw_UvUpuiQr61EO|Ogc_+prx z5%|uZ?lsTeg%wCbO!PUYstsr`XI4xs+StbAiItI3HMo1CR{Iz$I0~O&_|@yT2RM0( zn1l*Cx^Z?Y&f4?Q({lQ!#Z}lzAdyY(EMK>{-qr+gaRPML|5LFIA|>$g+6D_123v1# z#CgHnmWJ9ND@vb-eVOViU$KU))Ye4$NW>u)5K*w}n)`LZpzH_^-CM*@L4@HY^X7;G z^+A{LGHn@&H<+FPgZs=}!;Q>iZW>2bqun8xCDKXb70%nyQSn@6rmwF|pVClU0WAM5 zH1aOg@05WZAuu;gS)n_hQld3U-KZh-hR)#yj&LJFPs2X|SCVHlg)dzw@u+wY*O#M8 z>(D#Pp2%uG@2d+j`oOeLTS-Jn2w*ZP&>`;@S_vhKq(o~tl!uJ`wGom9Dnnf0`I0?` zKwp8?dPK(o6RDSes9?Zs!Wv+Z=%H)D5B)gnp*%S^uT~QPk3+?(Ptym7igO<~0sri` zSzK5}8-M&AdR&;^rQT4yH_El4S@UuVbJ-e~d7+W5@^$v2!~0`sAx3MdhW@xiael{3 z=3Y(SoxY;vESS>TKOgg3I=`O2%q+6GF+nw7HEBIR$RHXjVL%aYJCQAUVoPB@ASEE= zbAbXN0n}{LoH5!ADD$P0-H0kpHfR!kyDlYAp(EEvlHFLkDIQpsWf1;VDJCSdRLPHy zifIi|uKg7;j1{--27jO+RWD5Rg`|X)%Rl`+5kBfBcAi^zpHJ6?0!Km zWHwXLNPI-Yo3P=^-Q{!fhoyL281IQUk^h;v^VG|VXYp#u)8nssC3rBsuY6Le6MJ;T z@Vv&6|05`LGuJ0}Rg`sP2EiB5r zw!-4oN^|8jdTuXpfVW;*Nd;~kKjd?6egvyQ7(N|Q=${+%tGKlT0p21y+^E}vaB@pBq? zYV5FWEPWbuf*`xDI`}?cg@-Q99P%^L(OQiV&5j{M<)Cr0K?|dB>5QN$ z(@|FB?oRrZh*Ba`f>8x4LX|QWF?QOGkWz=`sJ8;M4V^h{`$URl5kSHUpv}~T+ifkw zT<>8|*hozH!#a~Wj72P(qhmHaYD%jlo|*D_^um}MwkE{RMZONkhRS{^Vu+omTr-V%i46T zEiCvSEFj~C{Yy{{PdF%T#fB(Os=;H59(!S+BIG}e53tP^+o>0-Vadv`aiURQG=j=K zZ@|7KsVVz z=EbeiuVKkcopw@Vbw~cMDD2I$!Q1jpK2ihkOHIvRXlpq?IV;|_!S_EZy2Tbcj^UTs zTK{PDviIYAJj%+{=A^LtN!38J)fgWG`?swo#!{uxj-ZO$>djE)1D~M?fxErlQaz&? zyEwJ=S_&W}gsn)culT#8A)H7~4dNqEH|ADvli9No>v>mB5{>`v8z-xzrs<(*S2?zW z+u_^3eMF(^EIgz{0N4Dpmg8A~!f>|D4q4xB<`1%@0eEajo3O#;fEuUZQDRo`zCxer z6H6C!RV>|2{mxJ@d#>PN!e#ZoJpWJ^&1!0{w0D!VT z#~xX@@c90OW?2)7iEcX>Y*{Pq{#kjnay+dbP$W1Wi)s4V6BtPM0~(i{E$jAthv9*! zJPB-Z>(Wf+w`9@WXR_3{9AXscbH4$p$PwXhdB7S9L z^=U0Jrp!^DlHYv6^}60F=c(t8cX@^E(k;#MPV_?SV)UdGxp$h{i$ywEuDz(4e6Q51-K5Mj zrY|@yMAS7Y#}50yzq(WEq-Z=7N9JeDFN{IMVx0ZgkyEwU1IKdTrd`a$iPEcLLxsB? z({6(F+g-fw%LJfhfe=KxQA&7PY|Tc$JM}6)tz5R5!cQe%(mFY}1!y4_!;N1l-YZO1 zka!bQZLv+v!&D2rUr_@Y!A%rvMGtuAJ65$zlQW->K#Go~w%TP1BW?-CewCyB#9{H& zmW1(NemVxN`zf*|e8Rz~{*$U`rhKWaxx5U+=Duy#yw%Q}*gTMpS+0w64;6z601UVj z9LLDbLtw5;}FC}Ipd5j#}1n&EmF^l(uNLuR=|Wr`3pGsIu1^4>B0 zde>-8ZjgaCG?hx+4E&2D1~nAjZKVo(uCqC4`qV=?^@#v6jV;MirI$lRKjsClhSzXN zVYa$+p_R0Q(WxOVMW1f)bOJBp18&453?%>u4Gq$>W!wjqLO6#T;>lqeRD1i<$mRy? za?DeOYb+d6xoI)OsuL^cIYP?rco7q8n`ZA;>dzv25$JQfloWGG#lK*#S4~y1_S}`4 z(tgKR_h(STSV9=)+)VD-ZAv}7mFFyIn7ZbWH9%RSEr`*tpj;@eNMM9?N7QIY+W3B# zRwXzpFfm`^ELS#cUF8{Lzxuy<=&(^1yWk5Riv(wqI!>go*pczBa+E*f)HxbEM)MVb zVE_Q=^{NH^9Af%{$c5R(xI4G|$P99>z&H_J-V(!z6RrA_rxzW}#vOKFzMXCmJYWfR zJ_jrropi063Z+(G3Y#8uSyvIU3h)t=7j`*}U1{auTYj0C$rxAnv@MU1)Ct8A8|d~( zyQv?hvN76DmJ$3qP<3@2@mxUV%~MiYjA=p!ci-4GGd~`@uW;Q256uBZCpfySsIq3w z`9hxt$uWX#e3O$FGC04nw=Sj&^e3+=9Cj?IXG&5jeR(F$jjE!vqR>z z4Q-WXJtdo3%h0ETVfj5Ta$PRX5qxr%BN+m~LZ4yc=;=}7%$e8+T6E1#V%j&ws^F%4 zdl{chz<}?(o%y~OP;sc6RP}{{+)?L7v+HUkyFS@uU8wBNn{;OK>sPmT_KZ>Qzzz%y z(m6I8r_M-vY{gLjI?kFrx`vKcU0S;md5e>#zxVMXT} zQFo*w`=_VYqpa7BUn*i05|{u00E%qYc8XLuP!j6Cb;=T4Xb}V|Ir~qDkwPtW)ER53lX#lY7K3!oP#ODrp6Rb{KM0U1!vp@ z6qPZdqW|^%FDMumw$x^4DVA3%@uEMD6TS>Q73?lwu{15y!bUinr-%6s003l*UnH$O z4Y7|D&$wJ9rLOe7^TSLOTf~#8m{C3oMoxkPn_BngSgK+BWU?J%XZ$F9jZTk?p|0hV zMGKo3BjYQ3$F<)L7s(F0y=kLBR5AyC*!e$9k;T91>sc14#evIHlb0HRJKcD7}G+yZEe3jO^G(e_c4WW!4IL7S3)U1S`uxhuQ{PPiE# z4MuxbXjIkr4y%nRw?#~CX4EcdlB7%J0j(JCVLj#X@1Wj$wuF+=r^@ljKo=h=f4`ZA~1b#NS}UFadyR8JholoJr^-Rj-{L$=YhtidRf1 zq~g41j#lzku5QWIGRs^~b`5&=a(gmS7Oj5V@P}w2ZEMaqsqD6qeWrTLtdPL3f$t#3D+F5oW3btB$aw=}sF1_d zv^g(YqQQ3LvS>*?fTbv@RTpN4SPNfXO`latnE_H`XYer}mTwiMPI%J5IznDwIbRwH zUyG?{J)u}T`!V*r(D1?R?>k?n-U~db4?XCQ_txVCEHY0?)7yx8Q=nKCgwp6Yy5KH@ zLZSQulb7UKoNqy0Md#@QqB-htx5(_r;}vmS-@!Hp3`SVDXL z)>#%GMEC`CDTay&^)DE~I-{0g|q;a0})X#oI04uP{z3{z$a z4=~Dk)rNny_!<=t&(>Xo!aWZ^elJ@EGzi;{uQE)irq z*K^8Y2<-HRlA!gMHQM~4f9+lmqDqdfrd!MZnL~$#)i>J}gzzjUD9>bbOy1%^@*S%y zwm|CbjrVsnW`wYSgeF!LZ-4Xmx*w3?{wO?zmm4%N%;#Sgyxeoo%%rnS+nf9?ADZ$>cv%xaox?V#T zFk!u{$S=ep{6}T70q3dR2EU4zwG!{$x zoPu?Isz+tmg1Sz&S)t~d&gI2Fy{hRX{f~#{9%c_Ty+&RyUwQf&5BJeOlL7#u;wu5v zeu78@nsU9NNxV5-K2)z6<*{r-KcYd++I0{E*B7%6k^UOk(-6GZYoI9}za2AA^sgL^ zGxJ7^;mrxu&a&P{UrkNcYg^LJ507kjcVikp6^<+H~P8Y zlA=jJbCJgANY@KJf5M~O5f+%3Gq1UT8i?g#I(-dV zu)ci|^gbugaz)uw__Cl1V)tnb=u* zC@?6N8!ebb9|}v3lz7eX#20EU=YaNWOM#huq6Ta zJeKEl0Gi_A`n7yMR#Tv1>Mq9*2mwN{;qxW3EmX(tmA=#GDSPnI#lVPU8|C|>EmlE} zjn(rPvmUMqZS;QX%b3a2v5{ju4)b3%W_Noy@R77o*m~XNr<60!`!WXIbz(=;ZL&_} zdP^%u*4wp{c;>J#%-KI zI^XHgSyJ`*&*`vE+_*jAX&nte_WUyTIMaK%ijIejQ(i|gJ2TL_5mFmZ(w^}1Y3*Tq zUeu)ZT{*)zG&&{L{u3|&#uxyF$UBN* zN%QX0{}V~6htP6$sJC1YV<#n34S^YkfRo}M2m~|?6Y>EAlUSyNp0g@LhO@ITknmMC zF@<7&N`Y5G{l^T-Q>-TU^k>9l(&~X)HXA-D{vQk)&B-BBatfq7O3C!npckz_4jBZF zLHGsoi$NUfJqtFnqa&>DU`T{~2?);yEbe}Hz5d)$)Ln|63_C;h&JgbJuhQP`EXDRf zjROvqd&Bd=c+KGgPtwE1V%7ry#XumK8dcs1^eFZYJd)S{I6)FmfP<(N8t9aOz9ji5C*2mersrnjt176VtDls=1^#1u+{52ZMPH0+M9d7 zm-8FK$Vh`hL4H|qFQ)GNYf`-6)OsEEKOmg^XFT^fF1+bic?;IN)LNgrV z=wT%CgN z3#T6mhwn!;x}FjkM681^q(kkQRc$ur6AtzTqGv!juSOBj}g0w8A zso+_5RiT`@cp*G@s0Lng#dhF9!~($z#oySam}*xcFYZf%&nfC zSSNo$7;)QV$l>IY`SW*ua-dl(6Hxxx~IJ~onz_-*`koDvkY}(citY^ z7+uWme5djM->v@{xkme~`BMS&wD@1K7RQoW@?{>1<;w#CZLan|vVWpeqd~y%Mf?a{ z&Ki_){+nIq`BroTRok*b4^3 zMV2tnXjPLt@RfC#x>#o&c+V`v_KIZ>{Qz1Qdzq=ekh$apB8(%t=5&!|`*Tmn6`E&7m*woin}z*Vqjy5JU(JM4Hhi2zgAD7UgQu z-8n^Er=;A3)|7b|Z4@%rYWe{6>9E z!i<=21qD3tRz$`&9*47`{(cM5G>!DM`S`QIS^nV_^)j!X4Y38POS>E>BZ5xy{5X34?Ix+ zz4!m^wgI_WZi!sTc&4aQ`C1%HLM_VNFT_UYUB65Wx^Z@z`a&zTRMkxnzFC7P5 z4iHwdq=R+61T=Ln*emgQ{j6;L_UdkbLWjV_9d^=`ztceTi5a;bO$R#a)>aD9Wh+*< z9$lgH?@Ss)=8Ere4o~Vc{Rj{?Ec}?b%sXPaJtZ}@YpYb2H>EW{Hw8{z%q1&h1j8K% zM89eikZ{(kKZ}f5Nfcf4kowf^9zp*J08EnNNLAAqYQ|N<1zs~>2n^KtH&owF0(0)( z%&I(Hs{!NjyOS?9;}8R2I_Ep$p=ozX>3OP|_qFWPw8VCwG;|gf`9k3dZ?NO!Mx`_2 zhdGoB*V}$Q{L33$VuHYnoybrbinhw4cXZ!0L1){fa$=|WM-tjIOgdzo>R3`QYE9p} zf8%Wny|j5bvo?$ug2o_H%*Q%fy3iT@MlS)a_2Qprfp?lhT-bP@P)}w3`;{MjOkdF? zx9CVoPsP()Rhndfgjat+bfkckQaI-$M#5%}jI<21c4RoVd2czJKXq$wZBXR#S5nH& zWv6H6c*`BXB!q^&PJJ5;_j4p+-g@RQ{k|}NN?5>9I=W%R`E#kv5r?ROn)NsNrNl6$ zKtcpPfClb#OQHFe&?n%(k)Y(SLeZ`wrcQc+KNW`!QwU#|>`lQ@?n!m-J}FnIb-$7_ zdcmuZmB2JUDrn=P?cpiROS50Rk*`~A;?lFMDdd|bnVVs{Q{wiQ0Zi-niEqI9k7(FY zg^R{5g?&kUkkG0jv&(%C?e(wn?U?A@Bp!o~&74*ttDj#F%CSR!ky``*O|dqC0D!s9 zZu0<-|9f%+E=nTmE#aRWFU8`O2@?UX?I>nH0Eh$t^e&w`yi?U)_e+|y$8A^NwpDs^ zk$<0_PH{qGqnYyJD#_Hdx(W^dg`t;4@cX%$ntja)Rw&zE<+Igi5%H1ivu2#PZ6Fk? zL+_NJrp>+LpV!KHwj=TD1t;O@&*3FJvE&UlLK6fl-AFh~_=_tXhk==w#vnk+O z`76Tx2WkKM*48c*Xg>4y|MnV0s`c`Djp=6NmlrusjXPJ%)d+14+wTsl|L*@UVhyv| zb~u%5Nkg6oSg@IDHfMP&=FsCvw{pXynEe5IAO=uYouWS&-h@#UIO2Q$HT>M_Y%_?b z=dT!s)~t+V!AS%Rj^A^1#gYq0`{=Edr7`-rkdBm5vQVEf(*;;y(px4O*lysJ+Q&_4 zN5%^)iblve_Oxwjdc?<}N7AVYG@pK0Z?lU@x#oZQriDI6=j?2r3F|6c5j)$xbtIBX zX}~Pdl^y@1e@Ij8wUQJN0s@pZnl$%DiWE#Zqw{`LaS&c>M}P@wN&`f(ir#?4r4o}1 zA%um#7@K_xHs4|cH)b94Y9nl;v^(#h8M2PTRfM8jsIt+gAH{He^M-WtlLQFCw`E zWuCVXpkCHvVg2{@>fw*dbk^+gaGsHFRatFC71i}D-Sv?6hY{+gE^U2ufF2^P`enX( zbpl`=vc!hOUZy&up1a#|bn_Y>3XL~2oxQTg-)xAwRW380T4kP!*mfCp(0?PcF~L&- z>yK8d^x2lYusD8**iM%cNx8Mi}h3XC_9NAr;yGf>=QjwKiMY&y{Y{;_Ct|qD-}P zbKDf07AF*2x#I6~{n0}JKuK-?Sx-YW+hJ}%LI?4vVG+)c$%|Bao=;_AiD6%JERQ-l zN>j5B)$?Jc(6SFI`g+#9ZHD25>stDQ%Efx;WwH8ss@}MhuvewJr09LD57-}pV+CY$4e%g-h<%YF|LKFx~<#z zbIBmu!hugf2mlzRhdQ_KX7Frw7`C1h_&9INkkEqac^klNj>HCc+#lc7R=Mur*+gmA zx<7z%+9Yh!0Ca{HRJkBWO>|vLq>LHSiqyylI4Q$`$737BVu+Ug9fX3Jh&p6|+5En{ z06oDvu~&@txADIDDH?6U?xJ&97S@@J3VO%YF>tj>Mf45RL4RX4!G6>3$LK3J9XtSt zsC+5)@ZN5N;a5J3M|(HPDuk*>wA z9nQTMoylme@ejLlg@A7ivf8J9M`Sg)QGt1N#b$%rluUPgLob_)0co|kYL>at6Xk`| z$Twc%X2|6PI_jvgtnTuE63ZMiqHW7@^lhXT9y-5MqSkTcU8-@aaK(q^jy&1mhN%l1 z(kt>z%4!aZBOHP>D_%QWuBn9UW+^>anNMC-RgAYh1@s=dzm8*7Y+PN?Lo}4?OvZBm z8Ide~zfVGGhFBu);PoC)w)ymbe)Z8nNSp2XcphjBGH-$<3SASG z=ZncaJ)zg?YJZpOk1hoO*w}k}`JPx)cRU5$kzx4-*?z*6oS(df4dEdfLfQFjzm9Ay z8L)3KD~OV8l2{_8lc?f^3G%}x;iU*hh`ej4cR{z$X|gzt*+V~X^DT1n8a`#946{y) zW=LT7>|a^Ei0rVtdMmjtyW!?LTOE#$HV&d|-fLUjwIM>QQqA3-8l#sKZh|I5m@~iO z5K%{*u*W>#N8m#JZb4+umeXh#^W{^rl`_A(nh607!eBH9hPN9pe99zc=NQggwMOjd zqa%Dd4{53we7-qkLPACnZDG#^a_-};PxbSkc#WWA`VkDo6nJ+ld2^#NqnZy3oh#Ot z1Lxe$m|%k#+aIlWcT?PV?>6|JF9d_0=VR!TfJO(BLn?LkOY0Rp@Ej>(!Pt&0u&E8? zXNsuGJikOk&#lswZ| zjf?HdtudRLwHzsxyf%DvzRWz^DbIH-B=Adh6T&s`Nx4b%h>#NTd)F+R$aYj=Z45Eo z_jX~S(oc*23^39IQt(A3`)?#{?LXP%H(%162k2eYFZ3l}2F=t2P0~yIxU?bk9P{UD zFZ@N$Qp;Bh*6XZupst1 zybRA@0b-3%VoaS>%ktb*pdLAx=il{I*!wjwS8I3UFlNS}^e5zWebq#qec{&RaaJeo zMCyOD$^ifXpvi^&`_%$M3y~|gGd?{P_@3w76Dt9$*V0V!u48*tCO0kBc@y2Nf8(Pf^*?KoA|c7KQt=NntP}T#$It;&r{x`@K+KC1oa#17&$9 zSCOM`xp)bik1MJ@_x&A#HJC%u0#OQucTv)#QEx8Bg0n?*bK-?F}o)HGn zLO2_Qon%>U#hK)%6r%=DW}L4DEI9I3Qh9C0Gzca6jJ?1*ra%MLCArLsrUwZwR2kx`?Lr04t1d?%c*)~~5(FvSI z{M~2mKclk`1%&Ge;EKHNMVh!A#V>F$`7#EL@Qy7s1)SIQ>MLBRX|XU`uH|K647>mj zXp^bUg+_^>#tq!mY$C`5Y(!>GX>-@iC8%Je{3`XrTqM-tY3qWdi$4v&b=iM`1t@sE zr-8O5I#s99TdUHrZvMU{l113>rN@F~M6hKEnfA8^Q>qph_g(xsS9 z+gS(CwkPq`y;clS;XD3mla;n6Cc=x~K4*m`cRC){aJ-L4MP=%5)8Xb2oA+|apwFd$ zktj!>j=107|rdvtv$$Nk7Yf^tul)oZgX>} zwd}YwU+UuDI7Q{}Bx(Hn)dB)AL1A`V^QZh;@$rG(5-^08NsfnN`Ragb%a#35?jt%8 z0021F2A)`W;O3q83jX-D7{k3^LI`fz1kufxUc?#TC>&>`cX`U4Byfjfa|tE!_ho)# zEG0smaM#RR)@-e?>a}Ww$)Al>msN(9!GjO{DZXpD{N2b+Ljjx<2zu>4(pnsR^74R% zKLN^L_8eMEVwTiltwRgr-5;4#2#^FC`|+Y&ec7m6{8${l9LwP(3W_ZSi=2R0dO6Vr zsIE>{weB>J3Q{}`_w;p+)8k}B)u142knLEjmPqNNgOPZ!ypC2v%FdTd7x|7X1WmL~ zS9<7amvvHD*p$*Kg-d~|_$y7pcjoATR@Sp*eTseE_Eh#B1QI_HBq_gLamq>pHTfuh z{@&%>E*;-*JbwY>^XSw*2&dD_6OooEBZP|1u?}^H5|!%2>bD?O0-_`1Qxg$j5dWxYN$a(q#ToPo1?*;Kfm}DSHM6fACTe++PkKj_QTF*x|u$tRBeLNhu%0lvZWe+KBRqpMpO-L zZ8`DhF18W_USTFr<;}to>6lLmz47^5oA89~4X@39QPoVNJnk})npsWGopVm!FRy4c zotX21!WE2Y8Sn{yychv!mWz$^~W;!C#-u=UI84GFa2 zw2AuWS>42ob6lHEp*u_NYI+D^vpVlZ9`Rb2DTM!X6xTsQgmJC{}B_mA$Mmu$KJz2!X1c5D7b zFgXsH*C0MttJRR@q1ZG(Va4q#@WAqjzW@pWxUI|&RD|p9`2~EcaZdRnWxHQDuSXIm z6t+)mNJ>_)doYQ4FyMnjrjOh*>{c&kIgQOM@@Tb1Iu>DNB7{IR-2Mm)IlkA}r$&6LNpscxdft z!{ZQj=L#H%V`fZz{sn*#6AVhm&2ABzg$Ev7C&(+=}{-Es2!10DG@`OfK@_bXVN zQihRG>S4&3VsEhB>lqD6uA@90*D~}9@-iXrd1w5dH9P$z`_%9f3LVp{c9yyQW123F zvR@+SS3+W51#JamQ6t^_;G6n+IcDim-AO#g^PdoA$BD`MifNi9SmI1UeCX$7+$d=P z05Etz3O^TOn<6ypjn0s{8*YDxm1!i%*zEB6Z3lwWwxj9f@65`bwNKn^r%!#?-@nyz z%~`o+37@QVNY6qf1{S&p%vZU?XA&p<^^Ie$aQe?=wLoo2p7EJ{$N2nW`CpYb`)YPP zasT$b!%U=EI3(}sH;+_u*Aw~HiA9<%{mhHv3!{kki_WR_e_A7(oYX`RAc6-C1n4wR zTD*PLn4*(0F7!25PK*P3O5D+yR%+O(@@u2Ckv1Ts&gNGal=4cn>o08yzwJK;_T9n@ z_x)s9suLLp9}@0HRh#-@!Hd(iQ8Okl8|yeGMM6Xrfn{awG?M}Ggz{@lqv`Q!pAu}7 zmCtJ@%KQ9zY)os1TJpL1q-tcZJK9*8<^Q_a^=f`+5MX}gFs78T4yZr8V;T`Q@#&6v$Nl~XcV0FJ zNn>AA!y|emEN|XrGl^E?p7nT1Z4?$Hw2)4uRdt2noV_wq|ntys2d)V&w)@PQa zA}&&3uYlRQ*^Ip&>r2S`!@lL>_`>PTycjk8`Mr&;kf(#M@PDJTqO$yg3ynI|tT9C=QU-_bjHDicIT zDTMX094+OVFWQIa+Nt7m3V1sg!}^`t^fL^8c*dj$?#aqZgR`Rmhz7tKlKYwz$yr^E zQp|{&=(dKXc=|7Ju`Ild&3N-Xo#kt0nX9mQzZ5m}YGQSZ^Obg0(#MGmC-2#>Pm`Iu z_gR+7SeWfo#N7Cww;LqBeV#_5ziqjyzjfm+t zew(-rbbd^eqehmn=Vl@FRQ!E&g`4u*y7*;0Fwy^)#hPoseTou-q)$`%N<=wAc}w05 zHO->43%G6#mGy>eZNQ^7aFT>AQebO*SIcKH7%XNzKn<8&qnyb}b#IMJ~lS zMzTueZPHp^ZtZf`DsZQ!2ilo$CD?g<2I}+b<3mU_s1UhEAT zBy*zwhx7;vNgp3}S0)gBlI|BL#D!%n;=xAp%I6u&xsr6KhoR)R4!NA(x9L(eg2`o)klTYggrOc6Q zeK(%mIuTCjm|)PZ&@A9v9xOSSnNgP>?F1`0z9_X2^)@oFD0&n?M*v~f#e36u)xTL+ z^@khBZH&Yt!gDCeO?1SX^*E47_=cs3V01c5+>(-d@1zn;61MSGIb_U|rhCOCHw9|l zTkl{?7OFjRFr8 z!WgLl0AR?IPrYQ~ar3;}ntIPSOv8%XJJnF{SZ_P|)HjG`Q=6Bn&rQSWCSQX&&FEu% zz$8at05UmLSNtJjGx!S;`nA}5UeusNws<{f$)(+ky&%^XL%_7FUGSdy$<>hL1uj!91qN5vRzp@BD( z&kGxFPN|dCWG3~-zb%DyQ(or@2C9YW7M(?CoHd;|YN|(;&MkjmDuE5wd%Z#2AOvPB zSvGVd9dzfA$|zz)ilexDy`9#hit2q0EZ@o;_(Ti>Kz73amMjZQ8)(5=N<=$F^Q>Su7WH8ZvG~1x{x}&)<4`;QN=sQH`m@=nzN?XeW z>e$&jFSvS|X@&!Ai>A0+iFUkjRL)shgfoQR ziP;WSTI&-|vtg#0knD&>50OprU{`(CG`HTaA?9KzMs?dkt>W8}E#mNg6W1S?DEhs>r$ z(I>Arx%jKFr4yq>i85rQ>$uEs+YTXEnBj{<2~=JVHz`sPpR1vB(-z3@Cqktu=#pxB zq@UKKh;rDsjT~uD>FU$^D{3e6)#*cZb>9<2xbeUG>F*t|CecWMk>2PZS@@?3pVTFz z>*8jwH>|C|_Ds{J{Mx9e@1F!3003;b&F-ou;uAkdd8xGvQ24R61dYfJrHG&TJldZ7 zm1V{5Mm9AO?;8Y6l^Ct}wFrwMY}04tBT@QdF{q5vFXC2&lMu(3Bm4BRN~9!;wcXb@ zsfKx|MI);mwuKhAV84y#jNtVOngkZ=Lfv1>-Y}EY)L~bjDeHQx42o9PK7)x4$!B5; zx>=pZhNc21&7YV7P<$wj;;2?d5z~I5kafYlR`+yyYYpz2c-K3kvFUrr0qQR{jlYY= zng-J?(Nw!cenu2+Dbak-i^6HgS*f;UB_Xe3X@neYKq>*UA)ex08LUW5hu+rwv{Y!X0gnPj~P$NlcukUo$!xg zXph98n!aXeE6ysKK;GiiBBYd|%^K3c(+c8F8(*(TuviAR?tbG9NtAQktm3AmD-o&r z;0_c$iHcKm}qxR^D?f=Hy@b^%Q5dcX~(vE}dJ}&DhJoj`XS_ zH^OmT{=uN(L?lxX*qfq|p6=RC^DoX2D7yD7!4I8~f-n1P+^p^2BirR2-UZ$X8oYc}NqXBo;fvV<0(qUrFt@bGq z*{ARV>CO4p8Wxo1nwuKinDzz3pn91#v!P%kt9qo*l_4!4y>oB+;i1;0RNnX8&9H8y z)9u`V*saL4zRofzEfv=N2>{5{N_#o7aqCp5?m2KRFWtw?4$UNly!QUQAQ&c3oxT>6 zq|WYGR6Po=b~ZBcKCi=GNcgRMt3Lkk?D56gel(l9Vqul!k${>&Gpy6#sr7B((M}zl zrBrYG<#7R@SFhKg;WhtPU3lNkDpKjeISZXsmR-I;fnZm7GRUzJwG}x;BShs-T-GC0 zq3vY9xh1s^0MOi6_w)`S2+p9W$j806Dy4rLmu++%&z22aP2)0Z&-`RbpGp&FNl%gq z^Cc@VYN=yJcc*?D%7J|yJGH_2szfB>w%|V7;z(74`qZ(~hs8{ZT$zQ24eVXcxQac8 zIMsI_QeQjTB`&eJjII?o6C~e+pFDgFKO_-!t&aNGcMuX@v15LvVuOA>1)l0t=ybN>#W+ zZ+x*E0!5i%3^dtVj1eT&9#XG+pa^@Tu2Z>|6lacF z3D|or-4a*395H1Hey*vzTmvu=f~Hm~6P)3nTBax*C?{C zhFn&GU{CircU}Cna4pj;AH1Et4|(NVtM*(6PzuE{PvsPs2l=u(U9&_RT8l1Emv8A3 z)~PO-QcGMD5QpiMOrc3rV(%>iQ>U_6CXyZUdYExgqecXY4V{*(*-P#pWQ2~i8QmPI z=nOcY1uUe{0ckL_P)Pa56uasd&CIn7r@Bg;#Y97~tc+4zuHCLlHZs^sPwllA#8yj@ zbS<^-qb%F1%&`sVud)TwXV~eSvpiMTA1)@JnaSui*GA})U&1A+E*JYE!fA;)dxMFW zh`SEa?r+i%+X*U#TIBD-aoDCBvTf7dr}J)5*rem1>LX^D;*O0!j~5FeZT^}AKow65 zhQ;0Y{(Sr~6HOy=@;4?+o629z_R~n0ju{++Ulb@fOTHA;X*DwKSbjRt&vR?rw}y9S zbSTE~WO+dUoQhBhCSkF-wy~?ET@1R$OfE27I=$(M^J6;%#-}K_4MvC*e{)|2-+CX5 zI@$5iaV!XbI?3|eeI7u}d9auz@3~#^&1oRZrAx&n#QflIM-2}cE;bXwCqTjc2pQ@} zYrYe7^Rkck|76g^{#ONo?uY~D^NCW<>YDHsWirqvhehNmJ@%;Bc5mu}NUvcZMYYXR zJgx1?j5{k2{f{WF;hcXXU6|Dx7yXU^I+e8Nm?cgldZvhTI*RJisjQ2 zuU@#a-Q{=y=l}qyF5nq2@D67Zg{obu-M#C)NEfamz&3Q9Ih|5o5D4J+n~&c=zgo`G zLHAPIYbD6x)&fqqc-d};LS>8{CMzN}nTQP~3F@RR?^+C#C!S9e$xbw<{6Cw=^xJ1b}K?3IZp_4n=x zn(AqAr^ax$QQHn%YLtloqXDlOC~_U-n7s zqn@bG?L@poW^kFGe|GX6{ScG)3{T&gc&=^ov?E%`;;Pr`>qgOPO3JvYS;A$wYyh z9-*fT*_w}wB@|QK6b=nTqTyL0u&}S0aP%!P3N2#f_-NX7EYn)-;?(IwT7JC6i=ubn z^A*)$oswQleGWa(ap`^dz}5WPCqzyJiOiAM+P411zKkiY9L*3})~h%6xy9ikl4ElD98UQ~U<9j0#JVvIp{a$eze$h6E@^`r zR35L5A6)AFiOgehoTGt>-E=OIfQ<8)w+>@-!u-`dz^=7bA~)&+tOE!Fm~>~xso-u= z#owqhJ+o2K3~)$JLc}!OWvg`oSwM-5p>R+6?5wPuj3`TAJZz5n@C94_TQvY+jH2)H zf(neNziNH9(P{cw{f_l2zeY_i{cEX#0x?s0MPyT?P%R|H8Wy&juWz! z%@eB}FOF(osX!@r<`36 zh^kQ6EYK)9b`es8N>=qG8`jY8KU*!>J4C7Q68=_H83v}eg`fe}=-Lyu#Z%&C3kp6g z-fLOgFCE?o2hL;<$<9y0S?Vn&m8tDZmCRmcW_pWE2pTCXYj`h*mGrKM$4E}%Hpmd% zABitsTNlP;Uyt$#@Sd=17YPe=rq<4fh08vdx98grbke0ENgRkDwB^`3o-F!v(c{@w z^HE#7Vl2Y%qFuavX{++5BD32-1|DE3#m1VjPmERq)2mCx9%W&6m=ILnVvV68kiS2tIcTN&!2fq^eOs=jk> zAx$fmmgIl*RCRs&F9Xwm%2>@Tw?r=ZZ{j(rVkM%uwU&!Kki7U4951c}9w}iF^5mvqLq?hVGj_f3s6Uzq5=TCB&sZK&&4Q);CibzsJaS#5lO=Al`PbYtPEo zEs55?ZCcGuLMgeLm|@-g6{s{UJJ4CcfhRV(vb{kA005FdLe56Y>S+7i7^O#@rJd2J zr!rjs#2wTYiHf}A@$e1&JSlR8!ymL@E^CBHc@{wF`po2JEv6T9YGAz2RbEv{n9T83 zY>aRW;LGvTqxR+Eagn#4ZA96WsxnzGmgO|_SZazX5k|`0H+;-TRd)3Kdbhw+FR9t1 zm<$h^&8jN5z?#HBh*E?B5P;=W2`E{kj4E{XtRM2^`XE;l#ATVpHl!wGru2eXNUpUt z!D*?{c8G~1yL9cVfxdR<{=$lNTN`!2l-~lf0KtqgT%XW9$AGP9OXq?YZZy=&j8~Te z1(!gO)Bx^PYQBH^>)9l5LMqnS;K~;HXHIhWf{#e`vr8mD8k9{ijNb zY2RWzaAOcxe<`|9``%5$7@G-qX=b@<3$q?cFuUc>=7%>YCv^-q42_;f3u_yze$*EC z{*;##KPXgL?z0`I%R;^{c?v{$s(q7OL+Kb^7Vq;*aIsm!7z3)Dqk#XRR>|k3!u}J7 z9%8$#c_HAL?(C#(5ml|#SLRmLv?gQ4bLkLK+MJ?%zgAgFCuQaAU9J5=#@_bMe#xoK zDJgmO2fp(ZF)zv)Rp4^%dMwi_qSzq+(=_*}AR_%}E!atkZbK8#A=b-ltJZllDNr>_ z@>>NTmRAX$NWjkH3s@iJgYheg zb+FS_)266#j=Mk2V7}`qrC_2hXN~H!eUL1yr3hbRAi<}hve4)A$Ku25RxdmSw$`l5 zk(Og{K~E`z;?6QQTd@O>hKUe&|u9+ioLsxemdR{*2BbV%TpEA3d!x}C9 z?aq@H4Wne!^zrOzn7Qxl?0Sz*+bZ2cK0Cs?Dk0Hh%zoB7iQh8Gh+jpN;H?bJVrPEX z7+4AbVe2Y>HjOTRt=c3+y2y69PG$902WDb1QetBqDUrugq1aG5L8eZP@xXUW%}ST-p+Zz9LQ}@;%MN6Q zn6zUuxFY5UpQjyf?)8!fM{Oxg>d3tCQZ!OTgK$cqY^y&02Q;pX8#P$WzO{6lME?=2 zu?{9m7kuAiFR5}RU}{i_NUy4tKmuI(s_pRDrOfWidCkMUOD@i2&u$3jY8ayV9W zF7?2}8tukk^(|3}Vcns}>x3qksUJJ6CnfXknPoWM$FE1`u`@jk6>c6bpXuMMW5R~m z%5?fQBXf8uvhCb#PO7}9(%f01M{kV>fsMo3f(Cw{H?f|zZ*tdqnXj*}`RpAe*8M(Y zeoIhf;Jkcw(Yq<|)ju9) z8KWsmg@Az&oiMCty0=E!97E@@oRf5Wm$sf+aq8vwMwyN466T4k9^Q4#On#d~*0Z7YzFP>!0=URvyeOQIDvsw5os+U6Jj_?6FX(qC5Rxhqg= zv3RHdDHI=lYk9w$@ptNC!=T}pX8Qswv!(fKmi`LY48lcjYG!t8zm(k*ybyq0{|gCQ z$ytW}!LGz>^55$27bE8-5pVqwGqR=28@>@Y_w}90QDuJ}Cts$Ru}oGk<8P0hi(lVw zTV}MlCQR9sA^yIJ8MpNLDa3Dqnqhp)mBZ-i@d~l8GJ_moY(v%L>oepwE0wScmdlK0@n*YCFXZSLlf(yHjiZX{rFSt373Q{BVEGULm-!mAcJXqY8~9jY)gn+<-7zayPp3n!Qo znt12voR#J3{Q|!Ik*_qTxETMv4uh0ko)qjy&!ui*HB5PAxj<3UCy<+Ei$uyZA zU^FjK(Fm2qm*gfdFO@5vjw@%cGyc}cuWesAVg!%NhH7F8)74SV~Q`D>BS7p0@ zrD%58-~G<@q|6OwY+bxzdod`aHRN+9w|-J(;Zatp3>r zTb$(*g+lQo%MTUmr59FU?xXiCx7Mis%&^C2x|#{_!$o`|L<+UqJck@d?;(6tbVliR z{GV&nfHaW7uL2u`@3^$TQOJQkHF-v{DBP?_>W?%)XkH;l z$b%1HmN$WRxZvIT8{rk>Jqo;1G>=Pt?>bUsT4j#XCk)%9)>=&tf<@@c?uQ3M_y6!N zf6MLDQz5>@smWOJu?fx4X!oz>ixYDEu55R?HE3*xKm^p~N@1Fe{AQBhnPzF}q1aX7S*w#cGWc^y=GC3dKG~nU`yjQE?WV|vfUY0} znX=bpB=p;S9bdeyTAs#ds|%CKY^}eCVd6jD^vt}`SJHAISx8_+#_%6qq(tPkB(x@4 zcHq2kt_n&mO*#^*uTm~;0L(#B7{ovMhKC6&9}XRdd`u>K??!x<{-Qf61W_LPemas{ zi80gt@eoqc-lu0#_Td+>Sj9XR{qGO0ov(#y&SWxgMt$t=7YcOJRaRx(l@B5>Fk}UZ zr<3nlE=1-7rG=ULS9dZ=TqjG)T^CvBQk{Cj2_~-_39-Y!s4y!E`=5Lm&a6MNea+X1 zYo&k(0RtdVC63lZY-Ei^(~nC7o)w+>H-qUP<8tmZD%k$y=h;7FlYcEP{Gt%8hG?MT zQC}Dq5PP-Z;0Xc0?I}IAu9I_r{M{m|J%JOP$<-uXWzXjz-<%omEZEJOMry^2^OB%0 zOmbp_JTm_B2m7ON>QHttBK-#Oa&OEwe5VjVxB*z$@SNA9aEM)as;dT7BHWshDR zhjGl|@!wTb0D1_Jq=S?SgFY+r8$|9n|;48DGm zA+pZ}4NPAcvD0UiH$Bo?sEcN-WiMY>JT8}6MDf=gLqOEk@-01rY`~4OSsM{|_5q*%oEMt^1JD(hUyX-6iMwusrTA{;$G`c`{pO3ta3a@dgnu>Uxm(PJf#2e%#mvY_-Oxya;TNoTa)Jk z?%9b{P^oBcLcLTkmRzwk2;9wkn7L)~9S#2d9s10ARJWn~fy#`%9;Y1MfLUwRPT$RY z%$Zr&0=~10OxCvh_M83~ZWG@b(SN}s=KRptt0gvmYif&aY^VumE<8&^8>9@q`V8Kdvg;3*&8Y+k~XJo&V8Un|*A|XAfV#OPwB!Snt=fNwUek zr4KV|8mXe8Vsym-7ytmY*95P{kIQv3adtHj9__DJnYh_ae-D+aU=$~cI|d@-$?FmG zV(NLtOrDLjr1QMSx4ib0FHJ4AWePN3AB;U43fKM~ODkGVhnv={J;Nm_8G?40Lhmb- zKT~pzK?=i7Qjhy4F!-t|DI4NDK{>c6qw1?KkJ6 zqo>m>VE#}-003;R{Y`#WomMq5q=}rV5j2I2N68H^2G1!$uJGLjnw6b~8?5CNzi8b- z6$|iXv^-jPN3&69OLWn=>$hE_HGDC-{J{bsFS<^N;+!5OVO#R4%u&^v12OSjoMN$I zn~G&~H$nGj-D&RFjNC-dXXB)s>>rEq-_X``CSe!!f^9UlrXGFivMGjxECI<&NFZ_m z1R!a(;gh+T+qyEjemSv=rpFL3`cRuLGd?RXw5%*YTIXIQc(xz@s(!?A0hA*;1Rka} zr4jU$VW|)Bs;RR}U@RD9qPCog-f_!~JLQ9)%Ie)?6_&3nM#d42w-mov)mBkPR#EtH zXnxC-=9f!%v}V(Q1&KI{{Gjh<**!ne$x$^_KFvpbQiz zsFo=jtesirRaL%iq)|DjAFe*S0AHq- z^gMmt=cVWY`>Yr<(T5ghji{C(gy!TtU_UqCUsLu6I_6D5Gq8mu7PC89BsylBb}Hdp zj#hDKgrHCkb4@Vf`^gZE&2$Co8{dijZ-UUbp6T1R*XYDrl8hi$WB@hoL_qHKud8KJ z6~5AA(S6S_G?01__sljm5C2>&aafvqmf6beDXjg5ScGkufYW-z@8)}sZTx9E^DJKk zVebQ@6^}0}k5Do=^b*2~DOwAEWH+wNWvG%BejnAt^Rq zkC(_$HM04q;1%9-n}4g}MTavu#wNEtso*a8wV)Zw$8X}^y?p%)%w{m1cH<{BEV-F* zoJndd{=eE@ZLTa!!KnVRN1%Wf`RM!+LJ0zL0tH>gX=$6mxKeef^^fWA#tBS~w{QJr zM<+YR&_SGwI>&o7mNi|@TpJf#oyhY4V^`nGW*c%MRGK+Ul_%{G^X?R}iSpi$+myZk_rHwuXSsy$;1M~pEhzjP1aX3t< zeem8t=+>P{&fs<=?_j<&t1(jC$zt}xWW)c3`(hB6sP>PT@_9EiQ)b5eLWQHPjnoYD zH)K-uu7n&*Yu2!Gyi1TO{XuxsQI({K*72`17m-0{{$HmQ;VsOQ9WMQA7r4K2#bIpW z0Zi0r53-K^&Icr{O`sk!nU=zlmjTUR)z!Y%$G$!&Qb9#W145D5%wsAkOx8?~>!4jj z#>%U_h6=-zGh(Kt2$f3xi^)b|>?0CNvXY!?m{0J#6V+q=7xM zuN(0{@sDfQ+Uh2-I%*5_O72J2312JOE1W!1gGPe&xyN{$LkoFjQDTyr63Wo>7+$4J zQs&+C-;X8p54NS{?vVq8aVg5oWT!nL%b zI^&>~1r2T>eyA8j9&V1K$0btQ>8Q*Mx5h%r+qfL_TeaN^tq$A*Vm(CIgFrxwh zfF@dE+Va*sxGCh10qQ}ywOB!D#PFwe+&eJ?^tY~_H+U@QjsrtaFsY{=T;>}cS#*hLbM$c!p5APi3 z0 zKmhL1X~t981y+iV33PfBqTl;75sy3ny-Km`oK!eQGD&(SQTqCLKpyV$j>FFCVD3C} zOEowIx&()j&d;m8!t%ev%SChf$d~eG(I~0RTSgp}I6cFQh2BtzbJvc^<%f+8S>GmX zkavGjoBDwqX4UfL{jyl?0beRUOjXxS6+M{_|K$#zwRHhuzM53go}%cF{F%w7Iv=LY z{5$z&lBhKJ4O$7#d5&9k$E3HnI<=`FPkSEaENes^&ZY0hMUqYFMs7e}g^O76NZW%W zv15?EZZW#jL%m;QXt2oLp>K6ccGcRhe^e8=?=u_C6$`ss0u%E3RhzNIqdL_?@Y?OhqWySq!<>-gkE+;s%z#52{oe ztkiWhMO2#xZ2Rl^iF16LYKN5Yr{gIQTit{!3#U{dz)#KHoU!Fw^v;&eDT^u3u2sCI z*=9vNe9qwx%8F{T>i=!Aesb7`L~8)hdK0J=GfaCj%;l&>I9#32&0)ME6&U~kV^8Zv zs%Gzs(U&yRCCRij&U6)SE%MPOW%rU*B<`d)cj|ennRi;x16AUK)>d&%Plbb|S!#U( zk5ncts3x6=t z-F*9HKmK;U`N*B-^V%8o1whVcwEAN>5)9)jx+sW>y6qI_CUKp3A!xHSzPzq7S3Goo zSCQc#g(B!9Ybv=Jsoa77zR$u=II}lkGhdjDAI!mFX4>)!CZ)IW|Tq#LlXusqiX50 zimoJvs2QUED<_)LLSmYo8RBEwORps69a?#oXN@gi997q0#y>7Fzt4zTXk+?>$ix7z z5~nk&~IoZ#d~!}#N4sDG{QP>kvNef1**x65y*A}L;<2Q|V>sF0IKFjUudA>HXl zKx?e!-M=_?k-~(xu0j%Cd;#r^$TRuHza)ndDBr^s5_q+3BRh5%D-vIIk4Dvw*jhc7 zj$A9KY^m){#MwNQkk{E66 zV(>kpXjL!Ad^@4~*CivKgd)+`@E<%nfcP&PkAld6`q2EQvdBH3|AY#dUy1kB0UEJ< zNnyC~$J<361OiS3(8a5-c=Zp0ydz7!6xueT;LMArHI7PkKj!L)Q<=~uM*1Fx^Z4$_ z2BbE%S5kQ;=oM40AA$a`qn}yl z@_T+(SgX7*=u%>=73m_>Uv%8-pJ|q`z+nu`A0<4Y_I`@E7f|Fu6WiGT2$BHAH4a-R zhYBfavsBr<6Ke#sWqyj1OUQKaE1N8GB#bd606=2X_%c&p&&UQgXMXql=l6?}uX90? z@6z~dpr7?z3&T_OP#-HnN?&RyGy2!Jz#AnFHTgG$3HWl1is9@ydCeyDIJH=byf)g`(1vC5 zYm_KlT9czh>0b`2NtEAHZn+oqa@eZ zA*Vuj((!IGU)O9?OA8X;>yKhL3U9vWn3>XAF+pQPIYE$c*_Kz3ufM%5W}=ia!qFA3 zf_dvVMZ@SZ>^1_`zVKvsCs>re+SMBD;O&ci$GPl{hcf9G0FodkHkiNTbipMfa~>;v zn75T>ir>)x$qLAo0036S&-!Y#k)s>~g(`x*sSNQYG$lx1gNxorPFG2iU&=>GLZ2w{ zF>8dV6ojST!6+-;}e8=fX-D@1Vbk^i>fPzMa%x|uA9G0-5$ zEH9u+W^u{5k-t>97Afi5D@))pyznw-JV+46|4-NJ|8xq?7NRwa(>UvDrI?}Gjzs}g zedANA@JrSQiU8RK0su)v2ViBwRN6KkkRwWJs;W)goBaZMj>97zm3LkG5n$`|;?{Nd zDwp?JYqP#Hca!aF`4na6->vhFC5vx%Ugr`tkMB=}jMJVxbF2rb(vn5d;N`u@ zOcTe>1sVC{sWL;hh57e7J(C0oj^`C+`pZ{edQvCm)K)ZOg;akkdwn@w$8Xx z&x$`kMSe^neo}H<4yYLamfzm=G7~Kl@g4MkHZ%d$P>b!8Lj^>tI(C8NM4@(WndedS z+>ko_vidH!8;NliDFqX4ql*=DsOFhi-=Bx%nEbcMdw6=h_`)W7Ea}F0^u{m*D@OWc zYGT2H&_9aWlzvEYMS?0JY&_~o$reTZNySfj7k|bE;rsODV>*+~xMEru7|TmK<|v7k zmqPocoCpp7u3K)ed-OP?O^G<~HTM`)NUOcOET=yE;&4o5gesvc`Iqct*x1%w3V`f^ zngSrHl`{k6c-1pW<! z+n^EWL~!DL1-Gfd=Rr6jwRN-YRm}Qh!{0Be*QM@58S(T#@<~3;M1D3_X&DCcK=s#A z1hxn_-LyqeD5S$Nfwk3hO2dJuf726jpdtH#9Xk{Qz|inn_{Bn4vp)HZgO2(BUFc8S zDkG*cPjAIRHY{f|HjMT3Ph$2>ic1OHxU3`W>CW`av6!HeL&+=)qsx>{ZzwozywHSl zqSQkvo^uE@UOScE+7kv{(pIp!+Ims@P0g>9_Akmx2j|G~cR%>zWLtB}8nT`R{ce!~ z>Ee%vG3N3)mdR3@UnlQ=q%BM>{=d}+0JYv>YvEkLJ$B}7ijP^EFtyC5JeN9Ls*SsC znEo0m3>CoOw*KMI#ExG1Yvy&ndftyEEYALoYR(@&XN7ja|9Ehdck}mX!s~J@wI?{;n1JUdegB)y2OfLmDMu(GE7c2D64@V5KbKr%w_`+&IE=+k%-Cv#a9$OcKT< z*J{IjqxJcS%q9d|%6RJz6XPl`Gu{U8ydSnKkrId+3?it7fYat0Q^gvu`H#{ znTZo-NRT()nf!OaK?#jMf-t;$tr^0EVEIWf=CmTOM>C^?IGR)mU|dq0 zs#>HqXA#Jx?J!u>mAy}LyrpefA7Hqm-#m>s9>j=10#X1klqlISWH1ronZ-$k5_YU= zR=W$0oO^5=BebuSXAi*%-zdf6uXlkT8(;~Ch^hL&(3$#RUmAOgb}7Clp7N6?_};_S z4i+Rm%NygLaulJtnUe}fC#Ey?zp)S(($LM)Jr0)X$#F|^xTzUe#|xqqdM}6m-o2Au zubTq-h-i{T8(%D9X@galSx3|BJ79qkiUf+{39o(?@1dfuac1I$9Jn~y)@W4+;fA(l zgzBBW<&3h;BC*TddPol)J)qYn3@SYOYJFVU<{q{$$e2{0;%yeE<8vbR<5ohfs!-wg z+CoU4>1bhPP~Y}L;NJnrwHmuF(JLJs8nhfli_Ed1{`sIb>66t)ah8p4QfaB7wqBM| z#C)zgX)0|Z@c(xTn^6G(wZnD`a{kUUrG7d=a-v6Dw#ZAVg-k^ne#v@Ee+`7b9m#1>a)*h8qq!DL$FChv9FVgZQ0~sR}0MOi#JT>Q6 zMm!gPg9;0hsO_koKL`eGILv69llCY0i3cf<@zGy8Rwl^YDr`$Yz+`E@gp9_R4!C(x zdNsbtI0Biqa7uMx9u*aqz;)_>KZR8$nDCSRcyX9a?r=_oaS~^)#F5kW!~>Pvk_|5} zVc=U5GDB=(@bBG2?Ewq0Vc(V-hU|o2K25>r(pbiDe9WFMGQ*!a>+6Q~X%Zx}UQ*FF z1(%62DTHb3_dIXpe2REVH3BWU#qWK6i!v!H&#cG0&zf6a`|U{3(JoWdp5`4cpH2%P zZw!6iJ?p!zo0=M69Ajgj_UM5Zp={G6fO1qh4L_i$46M1W{q>J#qRR`Rt}v*{mCG#J z17E>D5>BwA9-44s$TpuqQ?2Mx=u-eBHXJ_H=Ovvsy24ZW+emUXvA{`&q(iU8Ux^{$ ztI~LRQOz=Bwtx5twD!2{B>Blok&8iZ50({Hg&F}gU=Ye8f51Q_WV^^f`MnzSPad>s zi;#FB-7D}N|M5#t2d8a&L)!aFRCy*G$SB-BfK@o3$0=P~emi zW4KgCrS$&=Ihfrx$>1s#zz-C(!{|!nc8I$5?)v zzX!d$ZHr+51?D^Y^f}cWMW4DI;jrl=Cr+0N=1?F9zyN(4pJajOBA!Vy4+A5c4SmE@ z2AfhmVo3V*6qK&Nya6|{*mm9sLT`EwxF(w`9p0#^D~;37>n-kxO-}G~Ftvr{V=}g) z6--AGdoWpX(&5uZ$LL^Epwo1NGSU%X)lE0A%kCQM!?$UUu<+c>rXzDx1SaV zLord&%SVh4;)P2qAYqylQ{?ExbBU%{=$hC7pB8?;y;<( zpPgyJexU)H!9BbO=|=h5x+-cyhCl^?c9;ii&5=uf)Y7>4Y#-_jR(MJD|J(R{G6-s(OU zO3UD!_LH1gf!GH5DM~J>DDht&-@yWq007BP`b~w`*3huVenO(u^G4UERxgbZRx4bl zy_PUvor;k5UG==rhL+_j&MV+gB$Tyr3Y8_f+UP8N&_c$+lj0ji%Bj*|tFY(^i+zKp z%y*Xdax<2$ipm2mt{eFM;e(EuQIm}(b3?e?>o@Y!BSYTd(0(Ovcs0#U{%=pcPa$XR zk2oG0LH=T?01|+DMH`kF#i_%T)s(m0G8NTt?-ITZ>Drq3l94q1nnXTd;!{tvi1y7e z+bt8Dp#7|YnWX#z%NxpLDvxSFM>HzT0TOsLtE6oZb^E0TWQz=?C$&#`7ob5k_F*cD zX330BC!ZQtRg`n@*{gg=_@Gt(4rj+rQSXRDIN(r~j=i@|)fAp7M2TMg0huDS6W66! z5Q7oG)N%0VF-}9Rt9X!)Flj_=AJytgYV9h1bs26L{v$kEYc9;wjURKkp04$T8s)V{ zG|l(Vnk%Vt>8pBP#Lsx}ZiZpdcB@v7>RK2o_JZ`B`F4{aCsC8A@FrH1+vFNn$=BL!t&%~#QE%jly$(+e z8{g$RATcW-%QL60WPEe8A|LkQA4J~)sX_lC2~aP7WVRg)@(nYZ<)K;VnI8160B5Wt z-))4(q0$lSc0=CN3YV$g5WLTn3NSHY> zTlWsIX%Sq))SsHKJwpxl3=e;lrYRX!7-ds$j3hIL$I=S@%xDqByyDNgS9HbwdGqb)eJD&vL6En}A@M$2=SJHI_4^5954lX-vzZ&Th7;sO#8wfmjlW4nxMAWamnMO< zNC{;-jLgFFP{3GBUgdqxO23^A`Ch3Yb(BF%<@*rQ;1C7?0DvYz?h}S-FT(bn439}~ z0ax^QnD?ZBjJuX-^-R#5>~LyjmT3;ye=)P9RjD{GR-NuHgEt?vzZ>nvQmx=)-dwqw zZ4ZjVZQdwvwP#{6sk22rRNHW-r^zQi`FeP!S}=^~mKT{Fo_ph{pqQC_xt#p_$({v6 zNiUMzs8;C+YXr9}2(JD>M=m7ZVXzom-o9vYF zR-CiK?rz3B`iLbJF+tUU`=^T6?|4#$HYO7U3H#y97uZ9&$WwBjF#+#Q$|0zdOWcf+n!W5joi4u}>%VQZa~NwMqND1M zFj;kWD1gB&%y>^L?Ap*UC#3*WK&-!|WM|#^>^Sj`LdqqNTxuUnx~D+d_5s4! z6b3_B)xEQ|E%6x?b|P3EmXsX^>f0YR41TnhPvLwOaI26oqt;#~SF->B0N0OgK+nnTv_GJHV3>PTWSKz4z#@OUDi0t&yrO2R%roAdYcDLL~F}@>jWwB-u)baQN7)3_&eaYzLSfTba$H_}J zYc;QmCfNrqJmQDJZT#yYf!`Kq>Y4BI-_x5 z?eN3dpzLS6kR_3(jq2`8c01e0(dv(dX8+`=L`+YN=rQ0J2*SAi)M?wDx{ULT{obtn z=7vPhVF69TDP?lCA+Z~;K%zJj9x1`TDwB_pdi@@WYBB@13313unD9~%9Vt8pN$FKY zL~dh*p5c@uV?n5-{Esj=97QuFHF%8IneaT~ppRF;eB@d_{O718Ap))5kL4S|p7d77#s^nmM@`^&1J?{Lkm@)DR!l_Oduqj# zR>hr#>wlEa-X7?fY*m6T_g406N0Zs*ipx2=*@eE6drx^djruj=tH*8Wz!rvl*>Y7G zpO)+^XX*4%7td#f%{K|=wi*OPTb)`as=IPq_MNx~;Y#HNx-}DSd^O5`Z%Kp8;~Y4* zeq8cr(7|ioGBAUdHq3WpsATd==p#|W%nX_V5E|-t!petaqg{5AMX;&OI)#>m^>>6| zdn@;lPwaw-6u8G!9a{4?BFRr?_`O~F{67cS{HkED$^@q!E~}K&jKJMQ4xyv*KT>15 zMcq26?OKGL`~7w3|3n{b(rvaO=YltB37aue%pnBb=^ra4*Hq*LxT)`8-Sj8` zfXSuvy+Vs)?WDtQT3F;uL6E-oo&-;F*0akV#0^S?Z|!Gre}5f(BXQ8()5Q5vqp~r? zSxf4o=fS5=omM>l3HRVq!r6zj_H!qc=l)!%>%A``CLrlE+rk$ncAX!X;8lQNeV{e!>cY#b2w=vet*90$?qr6>*bi?C6_6l`cLJ zMj5kbm(@5Ej^DbY$9j=2*FD~&!gX_Xp2_`Q`nR!i)_i(ihLgHRNTJ79NTf=aN}ak_ zx|HqXcm!t2=E=0{7fa)R!-3K9ArnSfLg zjZ+0>l8YH-g8aW%$zE*dp|yK+0%qO0Cp`>8a~=1=gJ!E5o~64G!u=|#)GVR&ZxMKF z%z+NB?F(#QQe2yHgJe^-+ZH=yZ*wH) zy<$!su}s`&QM0zB>XeBj!vX2jIueOr>T8O1v=*$ik=~K+$;AE>(P~f%p1pGBCa?ux!AgQ8TRrR6A$)+}=l$b`W0nIZ#T-cZBhG0?ifc$r(5?CoCJF$6F2xaB^ZnT|=TRNQ z*=WnusO8Zj1k7-Z6<%YtX83g&vw0!Tbm!VQrYFnH3G+#2Im*>&U}Q6|@?c3Rj||+& zzC%->`>VrDchB7kzt@wN`_G6@eNRuk@_1@uc$!0Ndh+-Be>sza#Ol^_KJ`H2|#8)7#a+;~XE{Z4xKgBWCW1EX%R6$a7DS z^2cOb(2dc=DtFyv!I<=_!IqBAu>m+cPfdHHR2h8)IP|W<4M&tmPPr`_zgAte1o0UN z6_4EX=9?N>$*x|Rg(29k0Nx-Bl2loe5IK->ML1Xzv>af23qxp z$wJTO+ksH^0|@cJuJ$VPY`|4n+ljM4o>T52jRDnBnKd7qcW2*lYbO7& zQg4#uGM|g}(q1EX=+q&Sku@V-2c>_vpSU+3w;<|pZPV)UsGhT@kE35qj}QTtrzKtz zGE}!3PRPvoyl+~Meel7lp|XlLc!UcrKux!*py>$1^XC)3Y5k{TQT+odKUS+DzL0J87)wkUm}Vfj4U#q#&C z@V^&HP*B}%Oc&w=5NQqA{Y=rN+H~0-ugX`k)CIUrAIN_Lp#UI*^o9O4D>oU`7KW0NdReqm>&m}O>V#s-T zDr9F>B9c3WDMe?WHb5^N|k)_mt}8IQiEG(0nruIpdr z+;`WJDK9ORuDTorQI!aV$!So@T!UWnHPKerYuJ+I&v+iaa0c{7d}`yN5Zw{%b%A%* zE7}|}$9$B(%*fa2$s<@LbQ3sUgCr~iSJ~b=^qr41X&qZ|Fem&fADT&FNX7>7U|I25RyF3XeiG^Q05$WGoZlpf>W23tmhbl$M4yoR^m?kR~ypwK)={PFA%B zN};7S+<6dbu%#yNnOnd7{ekb9bCa-?d|dF*Sa(rfDbus%aup3}Q2%~V=lM3UR0*Eq z&ICmxlpX%<-j!&peaHAhCDYM2ZVKd~^Yc2GeZpx|MGH|{6 znw9arOHBz@SH3N_H-3*pSG`$h60iHUsTw%)72; zRQyL9mRW>Z+nKCSqbr}jHfE7f%4VE02ij3+q6+kc^Lhw;G+Wrvv>S{Q%$OpX)k`Mf zO^thphv00#Z7H}oft#%O4h;eTp>_!i{=PBgpd>TtBvpQtu;J7%O-s_-CkC(B)ZsXv z>4U;I8dn+a7sD|AI~*g=Uoe>f){aLnJ%#m*@*l&m_;XJmixHwijbZ7k1>ylRpNXZs zBNUnZ!~Dc%+56?Z><0;}6MA?WAgQ$j3Q(EK&+A_=9(_-0%8vHl&9)v6y%RC^VCo^v zxA*xeNx$(ozc~~DWHK5Zw3wLmI|rdVTkGPK2xuc|ur#F4%98sz3e5=|r!}+M!6T+a zK~}86MkW{*9I1c$uT;!FwbE&RTp65`Kk&!Za^<$lD;#Zpt}0`JFB8>t#I{q5RpN9u zXlYW6-%PF1O|RbtY_wX1TqcZ*FQ4C?@RrQOKTP>_zwf>nDx%}-1+`22JK`T@eT|G9 z%9?h7%oG+kh%xhnA~F39M%ka$eEGFptDa&f)F@X~twQkpBzOjR-EEbi$qcsZEAEf7CJZP|ZH2Ze=L9<`B(<)3)zSxq z$b99jTjX%KtsIdgH~SGi{1RE^=oR$yf)#@K5CS=L4RTvV%;m1ltNnLEGt7Q#Ayx#Q z+(0!Y#auuTmh67if<2|kf02I&n;-}U0A+5^=3QOmuWR@0H^{Q`mLJpJEIq3kaHHES zQOL0<$fBj5<`(@M=Ue%7C=5094KR00W`fCNepu)kzusf}=F8UqfjLG2zD$z>k@Q~& z{i>I-eu&wxLy45k5pvY^;I$0TWa{;e%9$KWFd=VKSUF>c!1%S)qcX2(vYf67>gtDc z;XNdn`v}zRj8IXma5}JEv-^V;QZrN)@A3>G&H{3Fa^?@~@6-|bS=s-xLb{si}c%i8Yd z*$g7p)9^RBzfn;nJM;vUke3M!T$FU@ZbpY|h2TTfwDvH^GO~z0rbkCO-!o_V_uEQAlq{;Bv}C9RhPpEDc#@t%gkJF3`7(Yd{H z|HqsOGKZDy1Z7SIc@*etMo@=0u2ew7#tGU|Mb_h|*7QFAq3v%!PA*zEkcS_DeM`~@ zSv&xv)YyH8Mw^3ziv9R+i4@yMrx02(oZYkOGHspOT?5A-PgZ^1vKQX^US5P!q@tOd zOi>GJavF^D<2$?P8AA!?Ej?>(rZ=VD;ch%_IpjCxx3Q!bi_C>i0pxd4mDYupyBPeq zo7>x#;fpRDpgXZw+sLvKz2o+3KUc{PM6bFV^Q;Sl&c$LSsUadFBR_ypEIo}NPO3V> zk%E$aK)UV0s07C-5k(( zzgu{ek?!{4iyoz|Aqug=ESZ2o(icB5WkJdJIZlEAHne${Yq*`lnLmdo`+QT^dP$CS zv!R@J!1q8f=R=x~7qedFM&6FklBoHs?xG2?idzfJ-==>OAX13TZn@=c`{z*nKL>f@ zQqc0dA#=uE7AAQuMYRK&JBWPhlKW_ac6DgB(p2}h7GhsuN&lvlyk;iHsOt+Hu_}0v z|HQiej(?BlHo3lF$0nY4QC2BFPU9@Z-UMF!-%_xX{T9W!PBEyB8@lG96SdQX+v37TdF>jmvTC zXWveGCgBQZxFoA@kxL$Dz{1SdLb-~dRm~gv=VStcskQ+IR8ZCGfz*EV6@^HK#r*M~3#|Zr@7B2L@mtI>*~=F-*&XI`+wUQ*9Z43s8=#ZME_Z%V017rK%Z) zxI>P}7w%<@{Db;i(&ZBu>S*toJ2neCdqY9hS7Ev&=dJR*6*-%2A*Cjpq)|q>fvFjCu z*y%b^&}q#|U*(4~9?lgHt%6-t7a9W3&0r~uB-c43XPzOt6(gzQ9%;h7FxUkXTdLx| zB2Lc?$J`2=Q6rj_XXpEnz_Edtc0wR6OM1e{}Ivr_Y6k`Fi<4Fc>p0&0c_I^m4P9z;eEwzlczQ@8(!U;)*i@#Oi4nbO6<@^zqk{LYc)EQRO?9yAsJLJLGt z)N8~Mqn*TjjmPcRe5IE^YGr)j4DqDW1s~mv`{!s+)UamK8) z3XpxBckZ+jjR^f`vEZhUnhf96Cp z;zp@Hv~5gaDv|ZV=1txa+=w?xID#FZ7}0Ve#o+*wILq*aY1}){!tvwOQ4L-_;rmhe zbtZ58!wGNI=j7JQVAAD@e8t`+Q?}=@3d-dOQ?GW`-{u*=GjMj{?w?iSIDDjAJtYrW zBpw6O&F)pRPE9{pu%($?swjZJULN=9SaINRes+{A+k6AS`mUrFX5V@kzTTD>bE6|)Rj14pVC-^P(boox?{KauC(<}RB@IV{q22*#gvHZv^ zGrcJ^G=i2Gs*X2aI(oCfYBjz1EtULk0?OpHp@RW)+C*&*hwlAL>(t$V3M&=&l0rG^(Y>SKnWyCQB!|L9z zA1U~~Ep1%W2I8TE5hE%^xsGLaTKT=z3Z%tRT|T21LNy#6t!*3h!e6X98tPOBTt)Kj z?@T=lnBJzBZ0mn!QP1OR`nf8DNcT5{FX~fJ)!)tBo(&nhn0n{zh8U~+MK5B7C5^T> zatQ{i+e&*Ge!LtF-abc60)QAhg=JfVU}o}8+FPp-mM@lU$P@u#ah|0z#{?(quFlSC zE1rZC%N@tLnYw#*b9iw*+bi=%6?SPxAYWoOrV1zV*-I?(woNg2u$lwGB!bu#o-|?xgHmGTT0t&4nh$A! zJv^a1`(iJLUV5@>{!~YAaR3d4ezc;H_LS=YDr0nsc3dW9sFv855C4VFTe}PC$&9$P zwmXJ(vuS6%XWUmwF{HsFpc)+VOt%9OE;Pyd8nOox8&nV+-YmpJ{hu-| zXX~mUA?l7r{p#X2?Y)P%SwGGWvhrzYXrB0?H@@evlAvCZPpFWePUQ*VoFHk<&*^_F z>*LiCoAnh=GhPX;t0C=+{=gx+(IRi~iv3XoFE^PwE(0#EkyU*NG0NR!iEf8Tw=LS| z!e{gAN8)HkhAa0-G8iJxPnzEN#(HWUbx0Vj);J3QL_7(hwx9vERIZrw!^+%Rg&Yq| zYh;O(E>n&M1jh+amRd3h^eh=z@7(57ZXB58fAmEZBDqJ2c3k_d@Wx8lMK7A+eo zj?}?(`rR1c6&I+NTU-C4@9=T|EW~Z--(@vtd2cJ~$CKg2u)&h!P;=ff!;Z1BDxafJ zN-oSQ7{P553pYp&YmpYVYRS5P;G{AK%qraGk?;%GI9}15Po{}+?rm#no_BQ>e=1EDeXz1@ZUmf*q8RefcmsFcPeLDu1cgnI< z`%;6d{&x5`rKNz=u6me*$X;E9of8S^@+($qZnRqrrFEjaNnKg%vT~XT`+-i44;iC< ziMC0Ow!2!i`d(64EWqQCPa5soM!Dxz9b?I^ytB3=ByN{Vamx`Y3NWTL_wanuIf9Kb z9WVdstxFrG8Q4^7vyDl6mzJg-Io67nT9L=&pQ-ea9>>TpFE}Rhc+Q8%X0f-5q3!yi zue6RFzsp8s>B^@)qRylS$7UNd4rghbU2$+@-kb-1iB`)~%wl%5RBmT8+vyDe6Me%0 z|1ol&X|XM!6b$Sc1edg|DI>rN#UmEKdo9>_qjIZbyYU zDYU0Uwgo}F^+bG&%?$jEu=?U>ZiP9FzL@0M@wJppW}r4UN1_Z+DlI23OLLUKE+>@( z@qs2W8axFJEDtCW!>VA|QUR}CVo3TkG`%1aVZN@BIXEJu>j zH(w=cOiE(C%XA-sl?+yXkBIrs4*}Xwwua;UK)YO{gZ1g)Xs9{MnPcJXOyJnDF~kKi zHuiHA(>M73p>(lwDdu+fm+48Ux^E~7SAM$Ncbyi$m7j8f!D)~{`UrB}qikK{_X#b>v@`ZodQ|DKZ_$i*8XY2LPYP6 zG*m+wBQGCAzpyR38+0a-he6GFE$v1NCMX!IXgoOT29@)cGR*yiu6%XvsiLXn82qL2}ZdY<&7NZQduGHY?VtU8m!c&)+Rm>B@b( z_*6Xq2(&s@`l~L^y0o(*dp72v4qITBt#d{2J~p!V&J!m}GOn$t-I#$IE^5&f8%Z*G zPc>t0Qly#~%~%KRnfB*6{Im)6wG5MYsxCE5)s`pa67n}jLmQ^bhRdmgIjXdmW!61- z+`s4_fEjbsiUV%qmxQxr5UI~1G7F?+8+73gD`!78mwoB#ppU;l7q$Gh9Yt?JK%5qo zlH~4WRjZM+r+=QK1~tk+gk&k}p{YJ-*dhip;)RfYko+XR%eKC+hT^8HI)PRsMO$vd z?>mT4QIiOY<&B|;;I}A@rTpj;mHWz_w6QKiI^Y5V(I421i_9#P6qudSe_+^BRmJ>- zGcFi5&OrqL08oKhMNmnVCu{nDdlf%3mz-&&PjW_!{{wa9owenbc@yU&P5xbytM+NC%YhXGWWL_+ zoD_56w@*(@AC^AjECB*DSui0I@UTDNj0dy3vc_Ef@z?i5&NZ0rrER#%VMN|8X|Wj z8tSbXNd)y;`Ea8eIzv{Y z=MJjRNSnJ-s93tnv$$#Ew*^6T&vN?$R*X=^8vXC5y39!FI~}D5#_qDb9}2=#T~qnB zY_)H>a?a}0wjh2l8L1EbO&>cG7XHi_Fs?)mqM{t5l_xZWt}#PJ${a;+hm?8`Vw=>g zh`d)0s1LdI;@T*keyz>*n6P{?(yQCFOs;eILAG2<$mrI}EkRVOokm1YrnkI(695Mw zA_k>q^|IpN^zVPyjY@AcuXgQs7C}L001a$`qkLkt3sH8yhO(hHem5|>g0-K3w&Vg* zz&IJ|+WsPT>yE^XLnB{vB+_vfjtV^qwZL+b`Sw*3fjFask95?Th2U#o?DxC7=Gygt z5XLuSi*vuFjnP|51^jl=x{QUZ!E0IiSIpDDu5y^NYko-V(m}ZJVkiJ{Ms@Lu$~ZFp z6bqNj%t~NTCwsEIPH~Dj;>Sv@!w3pd2p9Qchf1?`7jci=T2&vv|4n6k-9Se3c``0L z!ihZxDoh5Yc7vN^hf-n!JZgtGr14*@`Qv{-LHliW#U8S@mOufZ`% zbCs=|k5cBkP`b-##|n^3^yEk8d?Oy?@y@NdjWImvDsfwztw@WLL?3|uv2Z^c1&z~{vn5ULvz7&WNY)& z$BYC!cV#zadR@t`A}Sq{;4fu%6sC==Fopr*YO~(F_>~rl+c~2bS#?QJw4X%|C7G}k zK;gq^ARPa@rT?#5SoHQ^9}pxJel4R*rFMApg&;22%XABX%2r;k2sdp@D}(JHa$5QI zd3e%bKXC-%N>@CIwa7Y98{6;7@czEmF2Nkf(W8Bib?R<=D<#2>L{-F^5xyOmT;7Z6 zqEo!S7#R)7@YUv8xzFeCbhK0A3HqXS-)&0y))FU#7sa}@+SjS9jsgcj1bhrH2)R2M zj7U}%RH>Ic&%q@jS}k_*ijmYxjdgCgZkGLES-UUo^DX&0teRD@JK`hd8e}LBGN^w7 zzhp@aB&!jCA7;&5$K4to$)*PVAj+QNlv*mT0lkRbMF@EleKMstr*Oblp*X=3Ve&I4 z$J^0)h=9;iLzCx~^Rk(htoqz9vhEfhXf1P0fzd`Ta>g$f zvo(}TUzpDBri=_++#@pU$JNa_r0)JFoI2NPUEqxSS8O$Dg$TVU4t}A#498fX6xh-F z4)%l<005u?LqQXWXmt6_JI8HrhRvd?THm(|F`3g&7*SN>XJ+Pp2g#Nl@m4lvVg+|4 zu>{N-^2%Th^pv*h1UL{XX2wZn-(#l2*3xY>>Y8y(kE?8FJy9*wu~?30-jLp7S)Q7ziXVN2PHF1--W6S~=S8J=cN%1r+3;`(Y%B>&(H6lR$pW3Lg}h7TJl}AgwJDaZ7$(BE3PNo1FQ}|E@pv z8)p$(p;S@Km+XaBMFuB`?YGTZl*DB02-jJ=w*mgcIQMs>%wlYycxNnwR<>KKeqd-Vm;KUXkHvE>ULFjDAMi4~hP2F)KF^?0>} z%!`IVAawI0PGO&K0!G=&V+fY{cW|`kdr&)bh=6q29X@e?=Y=%5!(tBs$NT(hTPO^T zTj`nsP-}UizAU6&@M6me5A6ZPBf^Vod=?E2)XWbiv7S~ZjwY8lSbZ7GLi!QG#4J

      `Wsq$zP-@OG`)xR83+%%?zp#&7cjk6ha>vXFv(j(UU?p=RVY(i7QPMOKWu3D$83bJIEr)gbxw+Et(Wj1A32iE|1W(sQ( zC9=U9Sq?X`|I5pPQ>_e+&%h0_6Qofl^rATVx$dQP^P@tX7g%>0`~WEgYAgU;hf^K` zF{(sfjX~xnV@cpVh}TY*{mWO!TtsUsK|#)#K?Mu@L!-t^I?mFT^OlLct^Dz#PL1km zSIrk2@wne;iWc;5j9|*7iP?(I#%$@T>iZQSmL1jsy)ad&2p~A{9w((7hF{V?3q9Y- zh}B}?=4rbWVN5Oe+}Ve(x&BntQ*Ft}`WEe4>K?0u2nYZG81zXN$hldZE;Jm_BuW%; z0`L` zdlD;lwP;FQ-Dae8BYdXLLqZ#uI93DL9!W8&)Vat`!ipk>7rP#Yzq&I>$g;^t8z-5! z(n-A$w3L~9?7uZ9;E>XpnujC@z~TgG4V#PQ_j^?Pw)rIalck3uwC|^N7lF`BD&`Zl zENwpWM2}P2Y2*v~>M9g}{#59Sa`;664@=T?WOhwY)6w-jpaHS8WLCtgy$Y5h68G6y zW||UQ7!zbJ5IY;QBtBj}kEZO9#=h!Y5DlE_0@xyrkW^^os4dOAI02~$eT9n>bd4!E z#w_;-{+3jmKK()h0^o+j0&5(|)xquEVJ2|E#r|{u z7aka4x!!)vBM}G9j1r-bRnN|LmW6?XR2m(v?|?Hz005jTX2G4TfWq}CsaqAxbkh)a z^JrZoi>wygap?%KaMeMw@{rzX1SNX~R_FX%{c41cz(*(C)OY@|>FP|)e*d5qPYJY8 z)G-X6)yAnGILPS$+S>4bty+cWP2|u!YN%7Eo?2Qdhqwfmz7zy`F&mgV)EM)=_AX%4 z;dTy}gfvSlpeK-3E=-o!o*)&&V*%g+7&GI+6bwwxe;FJaIjT?56N^ey8rfo#etl9G zJEu${Q)66{KNM`f>wr(RPO$zy8<(YXFb@l(rZX7c8)o)9<2kPY%6K!>lO7mC^@15{ zU4j_zJ}<3Hfno%g@py-?3ea>3q}B)5x4h`KO)kJ2w{KkRnwLU+W5qk#hAN2>7rWZ> zEYEY#2;Nj2VgMBk9J0Qgpz*pbuTMil17BfXU26IVljO0>J_b~xGc>h^h(FPohnI^) z%Idz)TOXSJKSyZ;^Gb3@3E^vjjY1JlhJ7y~M*t^_(n9D(IuyDz*1JeAO zF|X~mc8iD07REPY3=VUjTL!+!F#9jge`TOt8>L|ducy}IIVEPZTB!=+Wz8;p5l!>^ zT9g-XKx=W7&{kL1)`8A}=TdJS%?ZawD)^v)sz4>5f>wYxHQP46X{IUb0c+8+FDiBM z7dMh=IO_yhW5BY$tOTGO8(phL_Z+6L#9aY54iCXRe4K(elYd4pK#3HxdQM z!`0=|&xd2VM+!6Oa__-QiQk&jX=8@RiJNh9NpdWEnX;n}N!w1KhP;En{(FrTX1zWW z2j+-j{TMD12Ei^)aWAbKiBfHHyt{)v!S|!X!+nzM1^$T{@PzOJHhx ziEcJTT{r0)Or|-2hhFD4 z?>dqaKxt8;b%ae)m`Lv|RSoCk=+&W}5}Q_}Xt7r<@$o7^s##e4>3}>^h&serWzKYh zoxslRSzrJ2z4Wi_+0AU~nu*m0gcirMxAc*?XMe*M{R>-n50*T{04(}MX~n4WUjM&F4RCbD-$8|6(J=I3{ho)q{R>gi>&2MAskkFb?(2|(ou_`2Oy)) z-!yM@-KN{?pz+(2l`(4DV@*MG>ABzCf>NX2Zpz>O|poVTpXajJ?<^f`viQn=lx$ythGhmw3Z8@oS z@s!Q=@XnYtCP*wz*G(a~(9VQ)$FZTbe<&_bE6D)pOKPUZ?KG5#vp+cb4=Sd z6c8@;SY(*+6vmZ8!?ahjq=9?n$RWU`fv^m~(prdzBM)jcK& z_RoLpcWG*?Y+j+?qICbW84eS;ZayfRn4BD3MeUqGlz^9`LKehhfyl0v2=mnau82AF z@S0(Ovdo;dhj~;h3<&FRE`8$Uv51jTk{qGC8Dra+nRVn4#!JBLS{pA!$@4}@_gQh8 zhMX-hi?h&K&8-7>gGDe0gnsO{vnuDE3Z}^vHmSJ!a49FnX{sr(w2%I{`a3#wi6B!K znQf}Es6$&)EMfyUOy9Dpsn#_~9UA|?P+$H=>uN{5I4LZZwkBcz>R!c8GQeecF0S)G z{jg^&0D3%t%|wWDoDIVKlUcK2U$!gz)quiXOCO6yjuIkowrYXM#1`iJn4()fA5eI& zmZ%=o>%Blff-&1QK=kb|H?SQ+{JK6fwMDF8QT&gc}lm165vCD}SD&yiB82bsQ&bOUH@P@Yig#;xajMQIJCgP>BH;6bj`^ z#FqY?d?dIoZrjmG>%t+OB}{1hGaDN!pD2!ytCvyqO^Ifj=QYve;;3F+5L7U9!bla(Q z^frEJct$8%m&k4?MxNvUJkZU1AwaE5r{^AaTKk;Jr{eL1g@Q%}z%7`*nkTJhG5D** z4gKlF5vmhYWNe5qf+l$)H8ye;YvGLgYP0C9DqVd!Mz6yWhht-vc-LQQ7{pelLsECh z-%Uq@rRP~bs`SU+oP3OQT1fkVt%RnzHXk(?b738wB0@JVM%QN?t~kG;su0VYzJ;3C zRQ=^{rYuP~+06gA%Z;z)-A!!V4NJEEgTSCQq8J{cd~mOylC1_YyAj58uB7(to7l9$ z34|p|jyNd9T!x7yJ7)mpVmz=2bQj6;X5&6Dj=(!vJZE^S;NRC@Z98m686!wwX_q8* zlxOh=9q-NbG+QW%JOZ^bKKL=c!EHcb-$McuGSW6Y?=*12bvL6%>7r7_u(`|btEk=U zq|y_ZIJG-Go4#BV@Sk1|fT&}&Im5_xlW_hqNF+>D{W#6#u%5Y3q2Z$Jmj0OFYe;ee zjgOy z!LUO-<&~}!Vr$?}sw!JCLozqcDDxHE&VO49^ET&FQ?2YZ<4LTu(nc+S3Y`_DhZ8MZ z>wIuz;&L+VAo4UlG?h@RcclIvhHjo4O7NB>T@C&HcCdV&M zgva>t*9M-O&F{N9+W92+B3ikuRic|Ymv7`;1ZFF9FnwgH`MXOdZoh63#?DcLkWs0l z85DYN_dj(VF4=$jO7YAtlxd|wjJ;IwN*q$@-vt^O9|o074FkdHhP}43D;DO?eVZxD z?0V~i!eb4MbNQO-suc{~LGpl1XiEtxT;JJ=hR4 z-i|cU+zs!WoB|ulOYVID20$K=xUDWCy${RK-AwmBb=oDthp92U)$Q8U^EWIXO7q}z zuzxprrY_kD&)~nsrdPmu7tNLBJrg5tH~+R7ss0oUF-au|AW|FP^d6|fiSG<&<%afw zn-oWvw=LslE#tdH(wdSk4#|eOG0H}`@99;u)z9MX(d-E~5(#Ko=%YH$QyJN>oT=+>(Ny z`q8z_!_m3(MHw}F_G&3uW2kqeBRJ=AfW4XNa8`)y{0f`40BmoZ3zKp!(uCu9QK5zt;Vbse=KTmRsfo=hvR}+SS?it)Y&jUIe3ATQ#<`=) z$2ku_NP%vPnq_N_n_L}76S$n}BFc)6JRbam2L2NOKm{MkF-DMr8}xx|zl ze3om0ciqxsgeuuMgdJG!y#~v*8hbP9+|1>$HeZdmtyi$5weeR=kZuY~aParVi7hJa z9+jR>DEhhYo?Di`tm2Ac;UQ1V7y~2GD50tdq8~IDoxktI)4jTM5|}g;NZ5pW5+KUF z5hqmYsQ$G7s@q}nqrxq$FRa=g0Z*owTTcvJjMqBSpVhElO=aUT*vYbRldY}LK&F!O z+ZO9Cu5qwLX-89^5v;tq)&cP#A`H+5Ux^jfH@h{6pO30%+TcOVi1Ut$axd;l%n8|` z-0p&+pjzJ^l~1TrK?TWk%0kXv^3y-J*L+B`1Qu5G))&80urMCijYZpU$L;h1b)4lD zG-9Q$VLY8g2?FgEZaXA2aC|MvYD9_uaPam(1M3h{Gw~_fLWTC^LE{BXac=cPvowJ*%kz#C;-(_10adDV%r&H&q@TD}%Pr0@b zl2*c+fvy?Re-Q%nUe^fYT_D%K*`HXJEz7Jz6nlyWLilpqbor@?CBh%f7f)CDI#dDh ziWR>;?2VT1n+Z#xzg5dJC$$RatwzUYB#rzLsWBXYR1GEireAS6XP8HqfKGFZlFqYo zI1a;yIR3ip;CHE|mWXa+u~va+ng&TUQ&Ywc*tS3J=dTyqp`@XtO08zQmx3q0{;;T| z7r>ql93%i%K&iimqU4aTW@cYK@I@tshDK_92oVqO^+k`i2@VgnK%t`gf7Mu}U{(h5 z$KXFn=cJy(!^1dm+0G2b`0y$mRTJSb0R%(|3x%|>=Yz18%o^2?=RoI{ELJ$4RR1?c z(hu0u(HT4y@W042=Z@&|wz+NSt89_J9xaX_8fsiasY22Sa;5*A^$Q3?`Vko+$}i9@ z#+nsad(~zw4}2O}-(@M2L=EO=KWI@a5PZ+RUNnrg4rTAMeP1{27t=-9?b+ZQ_N<*L zcj(J*NRVq`K$^^@jDH`AKty8{P@>X^1yY;;wTSYVW!5maN?Jf%w{WyZRpa^^L+jn* zEv3}|)9>D(+|>T8sc4p8TN;}n8Ioa>G%I#2fubjF!=PEP2*=+-l^29*K?L@?g4~w$ z(Uonz*OeCTpAm+lhDAr(m$lk8wq}6`Y-s;|^pD2TvH2 zN*YvrX%)l(z@gCSMZpj1{27vijJFj&&342U@4vBV@HDA5XVfQg>Y6rZtnJfmMg&Bb zS?@EO@0@o|3C#Sso$6xi_x#k*AvOI{=rxYEs_Z8A{5{szgtw8%uNkFxdnZEjzOuZA@Hl6Eich!mpm;yw(^{wDs4&j{W`;RD0033> ztMo0%)xg8*QjvJ?=@%P4zEYbFP7c}G5yP1k*Mp^mK7JUbAZRW+AokD#Jpla^KaeSX;7j>mDF zT=ipLZTEUtb7&Trns|6g_KwLptSC~(X=%JVQ1~s)VsdW4lW#IW$gLtV&GETgu3kNX z89K(rVJ!!pE(04uW6y0M1lg0+g?d2ZxR?vHX!3P^3L!S9sN%f)gqQ z8j^_$XsDZ=UO~b8EPx7tXhM_O1%c)xNE(-)+<(?s=@43QDW{2j=!`KF5$QMCK5^{k z7bXIr5jt-spqh_hdo~{aV&Nlbaa7l(vKYg2aoWgg)+S@*d6AFiA4?u=ut<)MR~XvI zS-k~vZ6^sQR_~6ck9rluwr1!qJASVRilPm$yc?WHti-TvNSMM!$~)U8>qQa{d_k@eyxr%vu};!yH8QI7XjB0T6UjAcVIvyGihYBJMDvYw*CB3dOpOq(v3AIJtx#X)5QL)5?w6#k zVKRjI>#st^lAw7!3J9qH7e4#9r{A~2Q?%Z<-Wq$A-wr&AK*07%A(l_BPrM{-Idbig zP+KMQ+`AINH_k>C6xw74@2_=;aDe^-D?^(z z`J4DEAq^AyHua6bz`L{nCY2_K*t&QC91Ycc>bgC?GJDx?Vgrx%!eQTSQigjq8KDYF zyd9G8hy1UafFA!M*C?zVm1OT?2m21_BCe3I-;6f9vxkvIvU{Q<2MKkKGE=2R zR)g}zM=w4mO$w$sno#WJ@?D$JKgk|03-m8G!BU+)ehf*)W|^_I?2W_x>LgrZo0pT@ z%-Ja_NgB0&&$IoM!{8{$(N`PiV%Ac(YpJ7kRq*YAhdJl)TLo4a<;^TrF-iG3_gMT2?Yg0zDg z8ZuU5{uSV86;sa2NOF75RLlH$%-y1eOkk(a;TqBF5sZ-Is=Wc@GDEM9K1Ovnj zm+L?rc(LC(kA1cpEL~Rvc3ST2LyQr_F-?u!3?X5QrjTDw)Kas_D46$BU(kZ>_pVb& z&4UO*lDN_tT8$d=0O(we@q99*e&wS;F^QtbtTgOxA!o#|Nqb~(a%Wlt#}-4Y52Zdd zDfg_ZTD{&Bzec^1 z28!qF4mJ-h@WXaTE96{NbMA`|qaykf)mAN(76jvFX1^Vi{C;SpYjjq!XlTGolK`Zu zx|Tg%tdTOEZpzWm$UPy+H0ngXVOA$~GtpY2eETjTR#Xg@uZcQ3A9Y6-6&3h0lly4J zN=WYBLOFUQ^#1<7F%7^11ON;4m6?@Z(@%=Mr)xwbX<4qdx2#lkHK8h6b+egdhQUP5 z{*U51%y{gI4EH@O1*St`y;k2H=dcurgHli>PPrK%7d}-ox5K|a%^_al_-?`eUix`? zk7V_QTp&sHWouYnF2z_pFG{}u@{t19qm`N~NM$+EruhH!8MozQfBd_39Ut#2EC)IR zc37_^6NLp}16#$n#b^KnNl|udIL-PYh!xmY$SxR)iUlhsT9<64&QhL=Oveqn7*$pE zBP%Xz7?W{M{j=8Urm6$g; z#&^}WGu=z;Ka76ia3~MY_xg|r002<6ixcEzId@2?gRa-}A&nmURkoSxE?AVB$06={ z$287{plG}R{8oD&Qfk5`Bla`7!tO#i`t zeJN-QLjyx=wTTs~rB81c>#vCI_C|=_(;X9KR1W_|riGrK_E~8#)1osK{`U;dw0bw0 z#5YT7uiv(3^L?N3*$D?!M?hjFn(VqcXz@D2dz|J^_+VEuopcA6IKE>pH2A1sbL)dq z+IUWDr?#19&$jkDX)IsOcp33ne^`C+%6+Pa*neguh?!P~YG?9SDT=SFB9U?G7Mbp) z^_Zgy_0?GqH079*V({`1vprM<#?|snkRAoNnh!G?6M<;O&t*^F&5c@!+X?eRcmC76 zST#15Uj>wJP`cdm5vT1i^P{!yvwSIC=0wi;4kks(>SlolE}S8W;;1Ed@ehdfm(un` zhgVh>-qeG=z06wXky3G?_EXqt`3m&key@L1a!?=AHQuc{eOp=gkWS9$l^^&wT8Qk5 zB2-59jTzSCo6M2lInQO4RrW0g%sZDb>9ib-XefVuVoCL~r#dF^Z1@6Knt+P8TTg)- zD6-o3L#FyBNQWd2 z@k=OZYg1s2W3@An2OJesx87G+t&FpF2mbTz%3@DNKb{omOtwHZ{4c`)0QXd=b!32m z1jijq_u-WfE{ncmT7Awh!bkm*lb9)N{TgtsSnb2sVQ5-f`c-EUpW&e;drX#ob>BP- z)5g5NST{9Wt-d`tUQm*@6d_clU?9kja_RWmnaXJqQ0tCb<5Nf;fM$$lg6Y>!L09+a zAVQbX#;=9r`39~ir5jvg#btw*0{Xz@z~YH~ zwm4t=h3iAXypZM1A?0&=t6)I{^}Gd_2-z41uc|qWLxvufu0HL*fXt# zM?i8}k2Agy83Xl6(k#D7rmk*hdP&`84hZp}`md9VvM{nalXyuOdp+kE*;UU@b7iO- z>yrn61E-ZhKOm{dQOO|+YDT-12x&VL7<#bIn3&trYq!XW9g=x#s0}aSNHa0dM>mFp z=4gww0~LF+;DW%lYv6Ta2z&^U)UI(+^bm6H!LP!nFi}*@Ij;rE&H**yC-&vy==RHyxOOY>lsM-^ zFzRCBm&iQOz?qPM)YmnO6y{HH^&a~)Dh8%Pze*vXKCcV^gmvdnA`Oi#Obl}w#u>~a zB0n>hICZIY%(3o1WgW(V(0=yNXi{Q>F?hb^8kU$W1s%!iYdg(DvhDL=LR%~l3ilhA zjx3nzy39<&_pXR6eQ$e;Y*|_Xvhk3S*;3o2oacwMQ9%TVKad#<0RTW6ver(HY9Xe9 zJV($8R>t4y?#~r z+5lec<8JI*TN2Su)wbG1hea!WO21C>j<;!*;NlMq({};N5#{WTI3r+-ReUtvPZ%gp zYmc*Ja%{PuZ^}nkYe82bjBiw!(%+z7TunAax%e*oPFA_d;4C((Su@sB*x+($@oa=b zE*D?1cJ7uI@^H+Q>-X4r>F{pFmJRrC4{NB^#>|=c6%_YTePGg$>G%0 zpGn6kAs!&kr1@tX!bP{+>$_{Cxcsb5gt7l|slt0mfhB~u!=hXs{{HQp1_hNhsu_&3 zP&|s3|GUIFd`?2AV%$f(r7EaR9M>npoAHb0@1X};O~ZlJxg*MqW_0Uk0@Jh7c3rYU zefP?J*Mmc~^ga@C_7Ti{0cJ!)M^ zyD(`}%`4PX8%8GXwiq;%m?X&b*hJP~UH$l_A~-JqfC~IG&8X-jZSnojM9Ur9mmxEA z@Ey6dxt^wOv*}nN0bf24F8kbpg&{ zJ~3GnN6^Dw@L>kj!iR_tsbKU<3OrXliD#gUCM2|LzkuKJr;w_Vq~A9vZ^);$BgE@X zOFnUl??IO^_h5f?NcL>oBV~8--WQ0Mk@2N@+rJ0xH zOuAbtD9!bDZY>c(a&&uzQHc1aXjKnPnZJP{BTs!S+}xC_dsTbf+Aj6gMj>L$T4ig~ zRUOFfML;Nh1BSJL=6XcFyuvm~M78^`29Q*XhIt*}*>hQ{?)2_Pe zI17Z~?7wGn2mpW>-Tz@|A`V%u&7p(;q>U>&m_#_L+a$S`=B=Yia@M%rc38nb?UINMA|%UGazG{uy_7Z}K^0C%Z>QAj5$-eJTPBKj zM|BzH|2c+3`Pw&GcbfZIG4^8BJ1f*+E>j*ijdxQu*Lhq@P5kdp-C%CnnAPE)5^oa_ zC&)H?*2aK4giaZwxy@;SO3}WGwP|7NqK@wF7Spmsy1P8+$0`5-MFGT1c=5%EdF1L@ zBdITJWIeLY?@S^6@%`GG$--=UnrbS3?dM%mHkB82Ka-a$XX(snOQKQLrET|-a~A$_ zKy!~n+>ml^ARM%aY7KuWPrykf<{K#(s$2=N`B*%fkVHO#Rja*^* ziD{{UaeRw_)PGK!GxTF%Sk9H4j^_6coyP?4f{px-f*?cy6#)Jh#M0!Kzic?|LrR(A zXh}&DHd>IsSEmPoTZghqWP9xM2y)Pn&xz;4dEZ~AWUIS&A!pnOP8{wYKD0pVljf?&JyPr)gA=m_HH z`G~0WVplyB9v`J_N7PN{a{G}lnY<}ut|~;S@25VD`29Eu80(*UZ8O8^7Okj5_^tJE z(ETF_n#v4yf*8~LIgIh0cfO#84#MWsAdj?Cg-HeCgm6c19JN=F&t9Z(lKU} zEn1(;Gx6}GLruQl5A+@Vm&!#LZ`g#X;3O!%R&&x%sJ>-;(i3?FF>%+F-KFcY9;1bXhuQ9AHtRzh-N%0oN-fPBnnSC?dvBPlST#w zCq4a4AGL~RY<(U19LR<1{HA!Y6x{NQV4uoUn1WM+p6Yz`hYjgQR5cE*@m~7(acsMW zQ*rZubB9ah~L8v?|69ojhdMrtr?{-_O8&D@vj|558SpwI{QN6$@C6(v{d!a|P2mGrXrY7UnOt~$cRY^}8r zVqI8ALI40bKu}@65Rkzn#6B@z0!{`8B?BN}kQY*u(3-lP7nU7YLYZyr^3HkoUR>(9vdPQNh<@e$74qkQ&UOI+0000D9*z#~ z|E!z?6Rp-q&cMIY&U~OEVX^8zGaY5?<|I@a9gglYR+gkvyib~imS)`X69(3`c}L7x z7Xxq1Ws)|`TUI@g@;)0hQ7mTl!Z#LAaF~vPw<3D#*_v}L@4+wP7VPTsyXwiURpq2E z!jbN=gE_;thh%H_Z4C%qnSLa_v%6S8zmbL!4eqy}NAGn|x^O%EQR9-9s^M|aX}4|G zbgD}f6Z!JbOZu}VhtqHHBCBFz5dZ*yzy!6tdlG7A^&6>0ZpPZ?(pPX?U=tGn_&*ffAj=SOTHnyQQs1=A_V)OT$ozpbBU1yUZt8uEwa)Y0e4xS`g3 zMsrh>P})zjQcaeSAAC?$ojZf^--jG2vTYP+!>0T$LyG6`FCGMhbMQr&ycXb16Fr4A zLFX_BLJs^eLi#Lall983vJhdg;<>Dj-!Ls=7U!^lMp`R3u-d{Rb(lDXApxAEJt#d% zk?O~o@BQNh1swp$rzL|r$B2Irx>r!fI#xG^z!f=6=m7Hcn(UC_<+b^HSp z8O$xGWS_#jb%(?%l)E@aa#jQRziZ&Nk))jVqhdc+=N65B;wc z|D|#w*4s9x;G=l^wG0vZCUx>8$HS`CApHi1qx+IToO2%+@REaUCQm z5IXR*QZnOApsRqYlkl-C5;M| z-fjx-o2Dr@eCay-s$&f#5Qik2F?PK>nl@?cW`4qF&cLRKdNwt5`4Kh2S!lvm_wp*2 zMO0hqp}B)hEuD1ZwAL5$4AavPO_!H+wRo1Veoq~JJd(?}y?*tQ*UCX~V@RbK2i{2S zzVrj+w53O(!HL?%hpKR!XU2fk$n2jbyYUPCy{(q z?P}}51``yLP%JO@4x4RM&o<+PJ|g7`tj?^wIGOn{>2l{1{l6eM0K{O^_2VPHx`cC5 zZxQQxoDG<}>`(4KWo{?8p~4h^Tp$%d0yx@^%bob3)LbXfZzvJ_XX- z%cj{sFiG{T3m4}sXgq73cYDB4d1kcfYXlx_k3uBzL%&t#BeFrl|Hsx_w#5N9*}9E8 zG_D~?U-xH|-QCqU5P?(V_e-QC^Y-Q5%5eAqMR?3wfahq~5N&#J0>nK$a0N=9;l zkJN@oj!@X2GW|b{03-q7&>hIM1Agh`=^t}H0}deB_-7bW6RU?dtq=QL+I^*e)|)%n za0oXUEdzGlb#!&!Iy5OrQFF3RrLid)2H7tNyx%GpJem#y_Fp76ofyBTB{IPN%+Gt4 zQ6yLBhE}tDa>qw1ncPrYJy39F6@xzl7+G>c0R|v67dQw!e%D-uj_$KLPn< zzy&vU_1tGODJ_$%NNjU@$JYGoEq@Nh)_`{%pYjPg-)iTNx=l-idj6q>E@eZ)iu6?9 zE73>!$eDl^R7xX-5^4kcrx_18SG^eMpVUCM_8kl)C}TN|Rsp9wNL4QN|7dV%e9SC@hvZfvAN1LZ8v7>nYdlZDsJbG-iG!rP?>w-= zW`ZfRi17tmy-QVLdjs=mQaruMMy%>h_*T6!J=lYekQdfj=}(PThN4o+H=T)Ei1JLY z%t(T$8y1vy`2IO3&yLlFd5pEA`k4mj(>xv@H_Mq2<@AAz?`XM8dQJls>p}i)9wD=u zu?F_^t0ITis29wm5D#&UE0lKh*t$h9R>Pb9HT!vC|{VP1eaivGIzogMVtA zMb|F3VMp76?#t8%Ub5TH$m2)+Ch4-~e5Xy2v2gSKoHSk2*E&zTB|JO; z%kUEQFtKg6(QJR{LN?3%D)5BiT?ux=Jl5wZ+WG8k6*+weQzfqh>_-$am8hRxs>qiA zdG4?PbSG?Y=8Q6b4PKq0Az1dx_vlvt%`bU^Rv}#jVny3>FDAZZh8ha3#p^t!CyIsbmSnvmDBSwjCK4m+ zG^a81n#)`HjLhP*13Pp=(;pU8wpc#88!#^p$KTSM!aimGmlf=9zBL#712WF$Z#&Dy zfbw3lQ!xi#03WMe>3u;TL>h8Xrv2_LH={|g)?9USHB)t{-)RDf0{C|Of$=)=y&TW3e_s#g>w5Q)w$GT^yq?w==i zKOat^p-U)DOED_MROZVPlbs1fseeoPTDc3B?G>;zRaO7cl>_N*RB>)Tg%3@M?pdNb zmIO*4FnlANAx6^GtM5e2&3;g92sUX=bbqolt!;Cc+Sw30b1@jH9^VtCX+a5X`Ym$V zg=)g=qM*Merr2fPdSRSTtBdp3PGKveb@u$krdft;;JVx<8s1f&C23?NBMt%}3<1E% z%DqLw(6%kLfbdP%`V4`@Z{h@wPB zKbA{X9D`{}uz9iLe3Ms%Uog)%l{WEJS8wE>VSY)H%uWjB^K4E4o7L-zdjF;u6OrBA zSky^6sN~^#`i!q}*DPBVpKFYGNYyXYV9Fz&97$sP-Z)`IXvk~>s=SO=^#(Ch!~R_{ zeY!=IkKyTGLJH;)j26=+u6o~(tJxslm$=-|MV?P6S+2ZSEKP;zZI2mzGbMaxe(Np^ zkd#qA6p`%BrIxo#$1UVPN0bLdqUZ7GsymJypILF3!r{ z;VVUO-{JV8JMbY#U+7H~K~%o~7eo_Z2aAlu^uJ7!GP514ONr4$db(`>vRjp>-!3I} zXyeMPSEbJcXW=_2C_I|nU^+DTTF18<^>n}6orS59E87*%cn;8D!9EDp{^Q-92~Ls+ znQ_RWLL5o!pv0H15!XMo^#1F7K_hPncjWt4yV@?MvcYsu88F!BDWcOPh|Kc1Dg7IJ zB!_@{8hYp*ABu>PbDC0L06991m@OGP)wvGQ9*Jjv#dsbiJo3*ETE2f%f-ZqLkJqEa*rBl-qN ziCOK#l_xAQxZ_oG=x`~H5EJeJ$et<+EXRv2sV;pTMJOEsFw6(}+vUYYh`en^G>VjP zkO3scqCcGi^3cfw!lffk;E9b8SWkoNniz*l{ogUZTf_yUn{=wL4RCe#+eX@k`3+3F25;){rbzJD+Xs7Cb>tr&J2?7_Y;k5 zpJ@J0cZ=)anpR_>8`qoEcY?k}?Zu0oQ|}K8gU#ls*pH2`OH#(KTW7tx_Q7XF08rQu zz>evVj?bUaxh$|Vu)^gwc4*}0)3kwS8a(^oKtpRw{kCKI`&iqJ5`hq6<-BB9Nzkf{ z7;`oIGrkpm5CDQPnQlIY!$#oS!0)2s9>_O2Yqm9Vg=f91st_FZ-u+Mh9uH^oGEa>{ zFE$d#gxInug=85_CPyO+dFqzyF$ekqD>`c$QVwZPDvL+M#HJ+mv3fHrEn5PsW}nF~ z%{E+Ec`46Q3h9e9)ohanqa1xo9Zp5~f!qQVK@TfZT**pb>kdzQ6fbMhpk6?LYE@Y{ zBqwi@(t**Qa6ovAfvkR|94Z_0nG`y+f2(YXvt+U%yZEcbm@X5tbOx@e5}7F3<)-oiBA=9 zYayQhUwp6svPz&r|IhaU5)!(=a&zvCqc^K^qDmlKLAfm3`J`}eT#3Ef@)`dXfUr`C zM|AaKzY#$Rg5Kh+RAuS$$2p@cbTv;LpUs%}rSZC_pbg1}&%x8~vUVlb&c}ipXW%+N zcEMJlt>LbWww8j7*_nWLj=Hd>FP1Km^UW0@N9Et2q|s|sSW5zfcIO$xjk$%qsRW*wW%NkeDT@Eub+L0HbX*!QQK zZR1Xq`Lu#|p2vy&WCh-^_Og$ti{WXpI}ROYRs6SPeQ{@h|DETywAifrL{sxm_p_ zRh3!-nR*{q`XA}m1ZBf$N*KuMr|(><9eB8S&@lmO?1; zoT(C{Xv2kwar&R`=@P<_8}HRF&Hw;(FTfAdBkUAYt)umZajA<(BnRoEBj6fBG~340 zX{h34iXr-PUALA-%YfT>`;u|e?OD+7eI4$*ae5>DnF=MjNel+6!e-vAp6my#^FU)9 z7yLIwlK8ha6splZ-{#iA$DraNiF_BMiE9;=XJI^pF1d2UZ4cP6vHWaSIE_NroLZ6V zrnLze?-{@7AJR#1tbBFqp7vB&62w700k99O8er+%hTMiK!) z0uW8+Y^BpnGQ3-!3l}sD6saclV~+7!yB@6hHbPeEq6L<{tiC#iB&F!%K~ec$sPVnw zL_YST`Lo8+J5;PvcpeyUMY>JPv`t*OjX>xhQfu0Wj)iTVDH2*#pD=|sG7&l2V^e&x2el}`+(zd zUQeJ4f_!IG9+)!5@U{D*xf;mQ1^|!(jd`2~Y}2y)qla~54Jws0svm{MtOXg8hg>r6 zi-b9hcbeMu0U2)_CJW*;P)Ch|nwKg8^Dw~Xm?@F)Xrh7KITjVHV1;{G)!tF+9Bz*E%Mv~gX zA#@WphBS9I?Q6sjC^SnK4UKujl@XtS8-W58d>YuHUe^3{Ckxi3M`JaNd zxBJv(8%2k}jqM@#R$_VsCssAS96XB_niNce$C^Dn5`zyWCbCtCQ~zqcJAaQ39QL%g zKb`Mu1(%JGDMiDDm~mqO0e<}6#HiLodI{vZ*4=I`R)b zqUVZ^0QKN;Ys}|*CEqXlxyyTf5kEyI^OHYFE1f(y*^2T&VGWXjSx!*6mMvSIOtv&f zT6q1e4Xv|tS$Go}3#h`YXC-Gou+u8Y9gB04_S{WSe-@o=p7%4)SfHRAWRv}=4o!)M ziM;fgD+=fxHQWim;WyuR9v@o5&LJi5Mkoqz--Ga+qV;Vo7Q|a{?x=RvOG=+Lb(Y1G zOZtwYa>AQfp$UB#5$)Z)lu7GOBHol&h^i1Ly?BKW|4uy(;@^&o@hj(6TM}`@T3CKz@ov|+81SVTIL!@PgXo4U;<;n>JG)Y_D80!_xL&p2`RzwdG1G}TdO zw9BMH2Ulg>7&p%&s!_s|1VDF&Ff$L)5&bJ(fp3+2W^##Fh2Z$7w& zb1;OADpiqtGRW2<>qgM8l%$kmQar2DcwT~M1bN&v6@7)lcE1?uw2s`RX1Hn!A=(Q7 zU`A0Xi-dB5w-k+km2Vt5_ysjxfOh}Qt1rBHE2nupk%XpoFhNWZ@!^iJ*F}bHkLH~^ z1kKn@Jn8F|b{DKREJ){D?<(*-XJ;@OyyXrSbdr&x_TlyHVB@8k@zwF@5(E7!5>L-G zT9#8yo5m*M!C3h9PMn&n_0b~#?AzCI*EYI)7yzDE|02jI1M4jRyW;+j%K1Tim~EaN zi|@xx(RuKX9%9r*I>-qyk6YJYosJaG0m%V=(g>5vL-8HWV)~finJBqVs8+1)_0e#7UyC?NXJ!I*rdrIAjyd=$ld6$}Ol-{4T>%n;T$(T=YO0 z1{CplYB%M>Cuy&6ffT$^5|4g^s(Ww;NjuOX=q_(-@<}ZIu>Yi0{Tnh5OGMI9c>D3W z@fdr$)uEQ;c{IS#4*+FTh<|G>u4%+Rq3o84E2~e6SY!Gdg@Yc~2ed^W>lkJ2Jh)i2 zV*W?-8cf%*RyG}<-|8c5SNFns+xSd@r;XPCGciHPu5psl46;v5#WTG4nk;NhIT@#4 zhE`KQUB$olx0kq_)sM8_4Jb(S;3oCWxRy^2dFC~6d0CxAPimTWyg@fe5{cgiZ&(cg z4FCXS%Qi-{aH&!?yTn3CY#JKapNS3DGf2@ptuNPf)4Pzh1Afm_5T9WSB^2@F1A)`u zOjPYb;vpF4S4EF zA2X}Uc~wwmtGTMCJ|AfKS$T+1U)~Jj5Vw-FBxe*34*O+VC-6=E7k&uAd9?(A&lk0g zb8N;{k$^2%dFA3lR{)OoGTF2QlBEgLr_BDKcgxn1HI9qVd9ewr%Eo`GoVD?maukbm zj9f*AK!}1eIN75Zw1B8ye~tW@am%;}2!N+mT0{xAMM5Sq3&Fw5&H+88ax0zTg|#4+ zZzT44SQg^EKkb8{B;#SlFw1q#ur)Mrfq&*j&veIf;tp74!q@Y0XEhwC+BIOZjDkk( zZb#bbMLyDmYizYyanggp!1+|FP4@0JVPwjGX@2<_tqhLdnx2@={j*YY`5zFJ79enN5Pfxf@F@6@?s1-vX07gMPl~U^_M=I>4Kdi<&{q-|qbX(86 z&Az0N$NCQBc8ur&X?#WM$$8o`kRnPeV|fp~GUwqAk6$RtFBO)Op{taXL^W(gF~lPz zFP0Z`AWtMup{!0{y$njbuT_5GOzT!3wbxX)u3e#4Z;1-AV~)301T_@wm&b&1c%a}G z^SU+a&E0y1?bP+oB8LwKsXvbS{fFWHf0dl8`Iglg`+WT5-%tVSRu%t1kCWP&ai&Il z%RvH5z#@PI07j5m2dT97Dk%KP{>0Ncb5lR0a(RmyxPG_esRtTcBbF0$@R3@%%J^8A zi{LKtB91RNS96CkZ<)*rqDS3Ol9CjB9DKwt9>MSg31h$qbdW`o?15MD@W9Av@|@j% zFTZWA^S16N zYwDx%S=t;Qm6meDM-BLObIq&|V_bOE^lZP{c_;>Ik5DrCFT6xNFPj^bL(b_j#c`?& zKpSpOt*r~c)7|ne9o(FL1qsn;0~MwV7`*B_*v$lm5ui!vNmT4;+V>C@hP9Q8W1rW~ zr%?Ij`za5~c=~74B%8=zH3%k8ZytEQtD_9x$$l|c3XikzwB1>6RsSY~a&*R$y(lB9 zxNQ-xMpoKvY;*FAMtKsl&LX3;(2;8GG~F z4qRKL9vl~>gN$1qmtKbBioXB@q8mm8k^W0NWz{w^hjD~JYc_SBDrbAUo{5eblHJC4{~ z{Kf$mTK0&&O?D=D4bhZ|LxV-KuXana;hy-^E3Tr=?Dy4T?K|D8fnX$h%QdC5iy5>5 zj8_q6dnUr~931kXa!du9{RfyWzBJtAj0~J|`TD{LV1&f?(WJ#QR9!TKF|mmB_S+oU4s%iTr3~4FDh>06;3V)fx~HC?dCyjKbGd zaaCLD+%E{Kq|Wc5+Aq7LL>?XA9>Z8lbn8m|gq-__?DIv#;s+}EUZ)UFTeP#6au$0% z3>V2=R%mpe{QV4waqr2x!7SKZ86JN!sqCyl{=kl1^0z*~O`Q-=tEqChyp3^vf5Neo z$%Mdl8mEs@5!)!r^sr_nGhR_e3l9Q8I6zps$VrJ^Z8F9|FPULsONfj&vkZ9Ttq_^1 z_?fxOY)^1#z3|)}C z;w>~dgj}L~e!Ngdd{5(fNLdK`JKc|X&8dMgVY|{3GHD!fzr$Pxut(V|b%AHTrlv0U z8dH#>xMhCYpiC7+E_#46#bh{=*7L;U=TF5FzrpRp8A_(-q@pf)#?;L5U_*fsNh zkd4*s90kqy59a~h-$)~qv`c_`oB2cU_#vn0dMIjTk{EYlj6v?q1 zga&l&i$|nb=*VJx@P9AILJ(c^5U8g~|o~Y^MCB zUwxxU5&+yeWV7G%i-U!h1_FeIU0$W|7t2c{!Vhywkh~Gjh(fJ#hzoP%!DVRJ9!2|v zgscM@HP!PhUH6wGEuHAR9y~q^7%&ht)P&{9{fJF7f^MOiV9G>1nNhRs9_2KRZ}Q{Z zL$>h}Ng}RUX=&moobB)3odO~=VLf!TRe~CF-a6%xr1_9-hMk>k)|;w=S)Zu*=5$Qg^jr8PRpj@g)CsKV0}#Fu z-7$yHTT#lgU8VD3-Ith9rgfa~DEvs^86(g>R}iH{lCCNP!@RXHV*P0Il2NAp-}%1) zXdlbXxl7jD1O~zofe-@>iCC9nlI?LNc1G$)f>TI8cs~G)v{A1#mVONXrRrnbjPRN~ zV$?VrJ6cep4ug&l`K;MP?2vwWIbP_DSI6CQqvA^ekUyUMxRTAt-nbK@t zm#}%7oY=y2Q-c!i<%DXL5@{d+&~QsCCGOLv$a>DEt6R5p|NhTPByOo8a?fGU;1{mY z#?;haK{LOg?{r>b{kJkQSB8CLaUKAPX!~Crzd4U}zBdqW@rU;)s8(;9iCy3&QmMk28gV9aGB^ZKch2*a2&jMXHYg};Sa z2E*98=OW(y79!g5JoSG-mWz8yc3^m!SO6b_AfKAH~)Nm5{bw|O7S*OlvfySN%&OUL|>O!0U)0eBV z+)_T{a13W4j1UMBRB6g|Dk)qVXJNBve;~VqfJFu*(Cim_Wi>C-4%&VqKK~K1ChpuG zRT)UZK(@cm(u(>8BcQD`ru9!Zq2cj6Zh7sPkhaHq*@!x|*{y$s*Wz3ch5NtcNARIb;EUHsCNegOV7+?Ue|a@2F|!Emr@wJ;%9r zrNIQpQ)g(|5>RCS3_cGo9_zclt5w4D3j+vKQbA@pw+XnoVwFwAE@)>W6kZ3b2U`{= z-#>mhb`w*0M2^joY*6q$6uCxIw}C#|dz79iV9J>QJWxM2wKik4e-mCl*Nve$ysdXe zi6I&E(X1&l2j{~Cb7f7h!I6Ac^@OF_Mt}U>e*EUiq}4!@z$poNj?}@STUo_JY*?>p z?#nJ7o}Zg^^_}Si!--4V)CzYY$ZEDaOREY~qJO4$&?Eq>CUmkBt=q<|CH2uH4G97P zKnOq)ejrDYX0rt5lQ(j+kXLxr119!Bgo0i1kLf-=4YDKE2blM{v41GB8Bk@z%qt|_ zulAj$7vyN#GE!3p6*dVv+(TUlC>qP_ANh z#XFu9uE*grm|y#gfBNimSZuhrCGqnwMVqLdB#+G*YK;vs;NfqnFchBjLmibKEt z)gv~1U5&+_K`9+|FZUed4R!Wxs5|IPeFG!1-8~w!iWkCKk<&FanJEYTR#dy*5Z)Fm z(1D{!M?vUppbp_Z2o(&7p(YKs8w$L2EB$qV6|mhEs?`RWY@t4mgi2OMZ~2&+m&#wz zmtYtXo)8B!k-sZi6tja^iD}eyy>BIB{8jAs&9pT8z`1FW(ml8^#B@mwqxf>S#n8ic{KBobuC$FOSD0T&5Q4?+m#>~?1V{~L?MB&0uHA< z2$U-bIhq#hhuY0fCpDTP87nm2Up_szh(iKH;Yz7tL5fj6skMfg)~H?~woe8Q0ssJr zL}>UOasI|Q)1`R%b7&Km_ddODed6juV|B42B{Z$lAL*REzN(9Zg&_&@+oEv?$P%N; zG#p2*{wdRevt^}WW1h-M75$c~#t6?t+97e2RCaeZixgJW`xl^z7LbGZ0Q(e@_#n6e zG-c^g(s}ai9;13&!GyW~yk@2d#W=~CBeOV*t4akv*fDzFpQczCg_Zz7Lm*&ehe+Z@ z!#b%5WAq~Q+Q*{9S#%T_LL^eTX*v7iMz?`DHaqEwV!N_WWz#qyUa&bzR?Sg~xg*nu*iX{rTZZO4Hs0x0 zp-7DJz=0=cW4hdRp^4qU^oZS`Dx+hN6&_Kf0tV>x3yF8j^{Uf78? zz0sr!uC~j2d>pKbMe9meO8V|ODcVVtpUlGwG-__GEpCkwC>PBA zFrH8*j|MZ?H9q6hR82MR^J4%Yff78L#PCPqj^alXkpp?-PphjJ>YD;w^FK=(yvt?8 z?CpeU-oC75Mlo)m(OJIFY%lE4H#E!=B}M&NVW>XJS5NJ*wnPdP{8+e~#p9KcMs-re zUzVRxzy>FZ@f1c8{HmhEiZ)R6a1xEiGc4Of4@B_dK8~-5b}QyQE%(aH8;iymASTey zALlaAo%Xr=kLM5nt#V1`8)uhn&M{Slo-DBQm_?B`QiVQ6+)JMwIMnIvEbsZG=PCn9aKZ_t$x$vTKsGe{ONUxRM%#TyOz9JrzDS;$}>~fif zd2m|{IH9ThH8f8+#20Ix)WD%C%G#8#(}IvcRRhu=AnQCUS?g#hNI64^+jjHeVRjN)Jm4V-GlwFp0>gc|^BT-hyG0Wh}c0Q`~ zIVACMT`Ht$WN36M|C75|IJO?8&aFVRDFElpuveL8ij)*s<^;~8uAA5MK2%&mRH;)3 zu~tK85b17m?Q>GG@|}f*GOfWuCxy^hIIdJ`xYO0tjZ%%7=l|`!dJgrkZ51RMqfFt zrIKH4olQI?z&xbsL#9m^l;0_K>H4R%KqKse#bkmU;p)2+SH@+HlkGoDAQy7}g~-{O z$B5Q1Jj||K@gnhgF+gS;TAh>JjW8*|zc(pd5uqf7u|3K+>S~b%*!h-lM5QLEhEsQo zN+yGEm)x|9DrgCM9#<)Hx1bhga#jCf8O!J z(Yp0wOp{g|%8*H1p{f@+O-pyrICo!2y!4!4!V{jnVMXAjNNjtbZj~>7ki|8Y?w2ow z)+XZ!x!2F~UrWINXb^jajgUxy*Gn9`>O)h!bzhxpnZ?4?I$44}K+LWvj zKcih~!dBGhrz4WaY)-&k)PE;4mO8k~(4U2^n*1OD5D?I0#S&%ZOXg~3cyx3`TpSAX z&}`Ne#pVpQ*B}sDVtlyz$RnCSD`o)SQ-YW-!mL z^wo^1e`$p6@#n_FcohUSA_PELVv{m96j6?~j-m?HP$ZB*^KBeKhBnE#p@=B9Qj<=` z&huM6?2>)kvbQ2iLR__XbUR7v1^8X15i~z}mK|B3HVH2P7XS}m(o913EeDK^zTuX8 zZy|v{iHAcb0>w(rgHTG!Ckjs>0!OdS-iu|}m`o7Q>NO4@v}Qr_M0~~mj8GreOZMCU zt2YK3Kmr*ZOF0S$7a4K>W3fDo%PU~Fn1av=6DVu}#E?VHIC6bao4!d|7Vf=Z^O}`Qu(smRHQVW@;=nFv21W0 z1XV6_sO@;1$^$&3>&+IebF1DnS;j`}nK0MZIOrww%Lb(bR5i-z*EMb4Y4dz-4!4UM%j34z{c3wyz zl`6UG&;^Em6nFrNFn-$f&w!2PV!QTb@+9T_Gpx)7COuC18TY5Cyg|FZCL`=mGU zO{krZIL*WkneydySle?$1*VCfPMrPYkeKsCgu^?&%Uq}ONHVNd4@&arpkECCJ#M?oBR2nV?lvMdy$zbYzURB1H*9+o#!?Q$`PDxLtbbg1gOn_ z?zC8kUyNBJW(pHhY(>eeh8~&+N>&JJK9(9+(x2kFHxKd&!5i{TaFe7^aGdHi!6Xqs zdeM0SE<9k&iUjp>&Bq(}e1Z;kaKSyRb;@g@I1!|bK@~1-tu2)-bU~zAm@e+0F^@DK z)h^e`jPG_k9Z*J=CbRet#XDqjUScJn49@ZCo`3`ZmOyu-kX4?BA5Jc)2pgbz2^lUr z#-Dmr4RSJ-Z`Z6JkJs&stPn1?Bdp|T9j=Kf+%kwj0|2z9V^k{nDz`=Eb~XH(btV!I(`3x?R}d)dxwJf%#h4R$SRb=Yev!&k zb@-PuaTy8?PnFBkF)H71v38HrvZap#i#K2GU{4y-^4^B7rL$}v%%X9Pu;J6$ZPO{> z`fF5eFfWrle3>xm6yhloh|ub8D={M{t!szKaww!*WEFE$e3*q6Xn1J@bZDJK`q}7EIHk?SedZ4tR2s$Z#NCS=Mta)i@sK^V#$;C} zP>y60UU-UPuL)O>D|IqE`hTPf!UBq}2eytWX1OlORK%B$;c-;fpWDR?mC4RSI=6}c zxL&0$?>Eq&^J^p;6k5vIG%p$dRFXvY`~G)8Nf<&FNR|{%As2OxOaRWaVmN=I|Bi<< zAYk6_xEJzTCf91Y_^ST!CVml-q5BsE%YRC}a{tyV=F*hl|5(o2&R;XiOrr>=JplUq zj7+=zHdyiEBBg7`9iWq8R*cq9FqlT;l__1k+$-HiNFP)t4HmvY;uVRM%UN~_Co>Ek zd{{p-2MrG&&Z*%SAl_LwLI41eNtBSC{i6*qn%}_9FshFW*|umOtZD|7hk?~3H%@3_ zQah|47j8)K=F8_lY0pweXB^^>ZJLJ&qMe>eX23ni- zHjG145LU<3<-Ci9_c$p+tKvgrZ3^0ERLbtvS%ldWI#ZeV_&;wjSlRc7-mCy`Q57NO zkyHn|&bOIre~=QSg#UlOoH(Dp-dq@Ge@xVcJO9|YibtkPN$uD;NBwo_U#07>X-mKaTEMY0Pjh>5t2hGYIJr(0 zoc5(WE@y1|zjB8$eDjLkH2L=|n>+h1%}i-%0Dw|;olX41@!rBspG5p>xip?ar7!=T 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 (u(xav3{)~}Bt>S^Sn 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"s+;@ryEigHmm+bquYqCshnUDbh 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

      Ga)~JT?L&E#+LN+)Uxd`p(f-{hR)o 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%0A*z3HGCSJ4E_0rjEf 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

      7AF zUZSKVcQ-vst31pH>%0Ae4xS7 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%0D+AFS(ZPlHs?U)?J+L}r*R&#-gQpmYq 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�Z98VT<>oUk8f}zRnv>IJ*FY6tH*EB(lTD_< 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%0DY&SAR;bUh>6{N!U+C>q*%B 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

      _X^{1!@$~>mI$B%n@a+ZZR~EPocqb7 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

      Gr0Yv#x5JZ8Nvzs%iQCbQ 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�{{#gC9Srp+E;(FM zuL<)6!{agWi#;WJIUr>?9Nb2-D_|r55UOKVW);`zvYXc=XQ!G+Z?u(L;7GhqNb(lY z3X&L&ziI~BAkkX~xng?ej#_;wPmW&>h79?1KKfd;H%Di@txCvLnItNzAk0oCwk+DY z2|Ulb_&NbHvt+4N3qud(j&sZE#%_Y5p%N(^kVsO5*-DQ^?MKnmWIS zogjQ(qIgUm8^J2>IxJB!Hr|@*=JAHl{L}53-df7I?3b>$`;PnRmCad<^|`BkSB>Nx zl@qwN7-y&0+_w{yv;`v%@`>gW$SO4N5j_;E>jZ~T_ zUUqtgYD~#c<9lT&<%;|eKwAkq^|*=2t>5X9DkX{ZHY7b8$ixS(?stKH5rn?ceciIkH>VvfLXFMs(dn`Br3Br`h5JC-;0M8!hN_ zRETJzj?fqp$`)_j^yXO;P4SRRsEp8?uvPM*M+3xfJw3J+p3VUI{~|QQ!3Wj}k_ah` zgflD?ix{#wp5-NLlMD?GR?kHn$k+U~(&W~=p@w`0QFCZJLCG%SoO;oxJ=aoyBS^$7 z^hV7nZd?{Tbs)K%=upfuvnJ4h=Fufu6(AYF6yBw56@z*4@7bwHn@#@lZD~(J-bUNj z=md)qZLc>1Hb39^YSCCcR-yorKbW*)XJJIA%@W!y=J{4VU{o813hW4i>}rhUBwaB{6pjzWkC_L&|D;`FacLwADNY z$X^@)P}x?`G)=%Hch$KUFxh! z5Oyi!-0LoSh1skE9hopskg5;;PoCRZp-`|K zha<;xkpN&_mm*l#yowYrMX@81P=#?>JS~seJBn?V&W`b0rPzBixvd0jjPKej21B#~ zk>v121>Z&d{oj*c0XF?^qqUCoxx`@H301qE%A^D*5G*^-_YMGVQzY~n zV++car}MXAhVs>mnk*rV=Fo6(7_Z1-+Z$U6hQ4Z=Qkzn_*VbL>WR;U$F^rB3UCMv( zG2>Ed#0qL5iKa;JBRyAEMtP#_C%4+py?YSj_;S1ZZoj#GF8UhDAcZ1CQDZ`OZO(X5 zBh74qxE6H2(XBgw(B@AVe9CmVZfVB0ENPS`{L|oEI=l~Wc(z+9R)T-8LGJd-#jH4chiT*|4f z5oJ4emfU(M#sR z2Oci9IJJ;vSyGG2Aco{D-$nF)w^#u{Yhy!`bLs3jBqU_Y-(#xi{_fHRyMu;o_P<}q z3L!*rDB>nlT^_1tF&P@N>sEG;r__mn8TN@kv1w5DxGL69ernk1U1aV>cu98!Ti@3# zsmH)AB|sAQ9bV$|!Z>)6UxF8OJmLP*`*Ukm2NUib;DC}U$k!$bFDe_7@vfvVhM?*k zidG+>X2{VepvgPZDt)64@_v-P86x1sdmE=hTi@RO7TUY&c0vec^ry6VQNPVhHQ>|H zBMk%Kpdc!ew~UD3;%qcaAS$>QSko(LAFsp?lP(a^z|Owj=YRTcN$EJu`$kxPHO9>LF;%-SQ3Ng={01BOdSl)Q`i&AF0;shR zjVWdAxNfv<3mW*Oe_))uo}QLF8y_W*Sar6kit1M7Q{KX�_nVyPbboM6E__4yen1 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

      Yul1T4FX~vbZyfH__kB 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

      NL z24*^T1@B_;>)jkUZL2?`XFOflf``~rd1#hgTqmHbEX^D1J?xN$N?N8$A~GgBZA}7O zl1-k-SrigwH`ZvW!rcJ-e0{ zTi9v@Qdk;5lXihCQ$(IfAV0Z~CmGaI<*f~&rEF<`oz#-``wZbo@BaqhS#x6ZOGvhF zU?qZoKM`4!kUml1uMAF!So(3@44#D6Ejk29s_pkmUfEQqo;|a!qbx{Pq(dDwk`*Ae zI9-7ln<0+)_WJY*@@(?;a8kO&byhn?vP@b#{9e_xx+Hea|LrKosF&po^=^7eRKL#! zv?AQWb~bpJ8*ych<{<+goV3dLngbug%_?CkQ=1Ke-YTEE{{4l5HEFWiR-`IlqoJHqds_zmf&uudLRFF0MLKhKdv(2$&1<6q%l1Aw> z&8gAIO90yb@v5{At)$wSF9=lcgEFiSn&LEqc&;GtkQKf=yz9;iBk@D$Lw2UIR~Xj zH215JG!KwuJGt`q(&$=z?PB=4FDWQnGWTx>4W93Xo^)FbNhcg8>j%Gf{iphx8Jq$i zd}PLYbQ1C=?Yx8()AOvRX8#G=Q^IHr>LF5TPi-{@JZY}@0Qy}fgWGI za36~3I#XW`Q~qP+Uth0YRVK6gYMs&`bd96(OXojVe|b$slA(8tU%`Dmgj@1>W{I(n zrA+C*uSmfZT+el%kf?PAJJG0)BDo2vgK-Z(R6}q9fY5=d47VR2*JsMl(U?5_&rU!0 z5q+$_I7U#mTv^L;o@eGP6C`6^i@yLz_~f5O1J14tdX^oIGFY;Jgs8T>3@nQ~BC@!{JoP|LTn09R4N>^iuZ4;z0h zTrQq>R3j_#Q$hoa9z$4o1Xsc<$L96K5(uSd)X_zspBcXCUEM+lrVixpuCI3RDo^6C zmOsL?i$;o+z%9b8l_59DI)ap*Rx`Qi0P+|YPx&=hM~vZ8Ed~+>cR0V0qk$n&#@P*; zDgjbp079cv^;xN-Pu5eHqDmaL&c$f9uCKx~4^OXg=?bW$Z1k{=VI?8AoE$cV5m(m5*nFJDdx^xJY&dB2Mt~sO*r!W%g)!JOEhWhFb4=oi6cvT zb-(An(c`9oBgBQU?fX)>X}TdRYkyAQg87Wrn0AIrg{r_-s=U1>d^^rS++Mp@mcU;6 z^*?^)X#t<;*?E)nh;Pq1f0_{_4WeE1w|-n>Wh1y9I}7Ev@{Oo9^O(9puj;n^#NdTa zJssrZ{z5|PxZB85?vNQ=F+8eF@`I00ECHn+Y}rdbzhx%+KC*(i z-&xFLtIp@-PN=++nwpnf`R^2~b&~yd?-`$aMuTyTMNEp;Xt|GK#cG6lJNxz>8Eha5 z09Yhlkko<)s*Ni|S*=u(JHX?lO$tB=vLrES5#K6N@7rz-tn~o2mk<}Sk3RK53kSu6 ztB+oUGQR{|?j5gRw5Nvc4V7CYKAYrmN)wBM(>zhYn-ZVfED=r}WR~K*pw*)f3D^Zr ze+xw4cxL;a%qRy=k5nId{=)Q9D!PVPf%z2+u4CCNb=mVin4Rqbz$*{>A6P8Ch3Qav z=3b7Fql=x`rmc^>Nl8*XTGz+>0%hY!x-rnxFJvZB2_o$qHM-FL6eip2%{x_fi4d=| zK7*Y1E6avsj_Frnre*RIh_M=UY992n?!@HZ z*@o__dq(D&R|oG>7Cxy!c!I*EoO3H%di)*E=4M7^L}JVZTbUy>bFbc4ybe{*jG8g* zNKv#z>9ene(tho48r_?Un9}snC)!?9cqqt>#S3^Wif*KkV|Hwc5}|MzvPv_FEW&c? z?#CL+674<{qa0q!6Q(wsjQefZZ0iMzA^{}gpWL|cC#t6u`B}c*a;&v;X6@juJK-t1 z>1!a0Qq?o5oyCmyd~E!0BS*s~D=bVhjfJN&7lg&ivEmIS+SlUxK6Mb;T3dmCgO?1O zQx?>OmO6`>xtO+c)_eSO7AT zR#7RZjeq^_2DSQH{9o^i91;6p2+e&4JtcZsdI3iP|7?`SXm_$QXwkl){~XO#Xl=Y! zC&Z>7YTdM8LL}IkCQI?LJU|kWg2-}x2VR>Ol&DxQ6gVjA#@`>l`uK}$m~GhH4L|-H z9zr5nwt~h|gJtCOA%=Zdj4*}AX;wtPFIFPgZp_~8%Qpa-20#I{8%z2CT?-><MNj618E-|H2&Hh{ZRT=`q1-M6$u{&0OT^Oc&A@o-5-%b(rKr5TzBU?Q>nRB`LraI zxE4-NPj-ApPCXJ{&7{3vn3P+N$?G%{)TO9vhzl-Mq#Kt|G)}P3sa1yNR9G@JaSRT~ zs>GiPdga`FDeWSwT5lU`6&sZs9<)>Zn2E4sL%BwH^D#fJW8UwW6moYMHa``i;swYl z3&u8Q9kR=d;7b7jx~?x?l-P>3kp9BRbkwN#7o9#wv7)Yd=>Zolp71S@IK!uBF$b1| zxc9B}TO#4flWOsG^9tz)ZY!V(OoVayxL6zIK;&kcnQoI}rN_lD7&qv>h-mK|(joMR z2z_GI>_i@WvQcu^_;p9l02KO^SyDUUD-h(ZBQW(1*@GVJ6q%{;X|-|tuQi^BN2s^d zf8)DQLhZK~&-fNH&K{@4Ti@MCv@yu|WB*&!;rr1I+-vGCjawkdr%_T@pDurLYA1b6 z?Hzh++xps(p>}+8f}hqj$Q#yZoB{VSn$f10nyDa#9+A_-@KskRc^x`+Dh9tQSY{T$ zi!;HgI@8ki%Vjq$@i_Fa@2kUAULhdHl8NXMe6DSijl(wK;TLTO50-LZ>yQdNn>y>$ z#KJY{9~|D9n<|MNqK=BUi&H5-%2TH!K2L02kGbgId#5}fo^BR?THEek;SnG>PK7T2 zguE#dLr{huz8Od+_we!|d^lr*Ci4v{jw-2B()@{y?z_v}%t#^N0za$8$&`=rT6`~? z`7lH%j`G>_^v#RV^SJB#gVr8wc687Tm!?=$Q?EsWT*?Hgq@|Cy+ejCPmYEJy!A<|; z%q+pJ>$%a>$NG9URemLFs-C01WQff~Anu#%7YBbYrtK9s0)wzUFDQ{C2qW1PoK~)* zj4Y|I?f21ZbVULl>JY-`pD9D&)L2{BRc!N*W+8V+*IESIGkOi$-SEGozQW|nY)u?a zjE?~ey+Hy1BxWHTt(z|vEqkJod@)w2ZQ1YQlZW~* zvt778DwO2ysnFZ^`PSkWoFtGL;BQ9_>fCx@vRdeSG`x`-t&zNL2shN$XYNv%UByfj z?9D2v!zR*0Y%tUO{w-wm&pcol+sC+;;zFsSfp=JUcUD$2yfsx=-eYz0*24foq0YI8ccvBE1Q_tMyTEpeQ2aS%rg<%j+6MJTCtg~lZ_!&KK zySR71Wk-r$thl3E>AsgE{UFbDkR|7zzq@GU{YRlW+N?CaPJ^^8*O3!@l18P1-P0oMci&k;!KNi<<#0g)5RfP`533mZ8P_eB_9%b)Oc z7(JgD&*$#bUp&m3=L2!3-#Ggn3Vg`?S0DRGKfK7jQ&~k9i}m~58ycrFIeVB# zM9CDU)c;CXRa%;65!iDpl>Y4;1X<_n$1?SQvJc{F4KS}8u&8|d^6%S!Ub$dflan)9 z&!n>%PVVFHS{}t7imlvJio6#!cjcr=G5`Q5y>=$x{_$g>?o57;()G|E!~L}N`wk}Z zwVcQ1LAh;hN@m;4N2aEm5fqO1!PL=GNaQsWtMkwZBkjcwG8K>+#x87AY()SIe z$Gz3H{G!-DU)~ma8uDe2!MZaSD$=|BJNNW>ZAkgvJ#k;UW{=TVEpkrzZ z$Lk}kzEI1LSr(-E_s9NKG%58qtwh_O{58#6+j(1Mp0CHhu79OitH1^S*;j~r`qTrU zWVjpYT?Dd}$ogN_9j)~vg~a{rG`}N=ZE{@BJW{n#O7|RD=xME9`e>P6@XWUU>()r* z1Gh3lJugPxkZNubKQu7WCcn`V!B1SDXXUxLl~S7?J-%j$;WjxFqgb->9u#P^)Hw+_|2ur` zJ+moWK-JDPP{>m1B-YLbH=%BqK1Z71YmzIkM@P?p%h0T`**^KHUXtb9A1EFd3R?~F zK5ChrQsllcxg!-uVgUdYWeis}WOm=tY*Yob*$3livqLiaqBY_ClhQ*vr6iNFZH7C8 zrf1rz%A|QTyS4ij>X2^w%;wfxL4$_(S*mk9X+2i;PnmxQOA4QN$G8>ACsz+XoapnD z9yTry63;rjmRao@J35OwdnyNqVpB?RhFg?pJJ; zom=IpOoIXdN(`3%Z*EvsV&B%~u9sqqJLFNKqYgJR;m*0oyo*MAihJOiFwpV8tTc&A zo<>c`PkC0V@8csp?#rNyN2fkCx^x{&$#ypMoG0%dw0{ANuZ-_wyW?uY%I*T7HC+;;*Bn=Qpo0oC z-}}Cz;Q}=SE)i>&3yQ);p;(PdL2=K8Kg8_G1vgjc0+C;7MwF{2sQg#MrZlhLmh_|_ zw2a_9{iRKrD+?^Ml_dNyJ=n2TgutC|K+t0LTMNBU*!Idn zireMx;jF~BGm@|9VN9q5r)9DG5eF;^!?8AHGLs&b-oqtbGzuFJCMP3oQF+W^!>`(W z4pWIpe#D7;Z`k)7LE~^IB5|PSyrgKuH%(jHe+$)3#iyag+EP1q6%;E1xVm{_)H-TW zAQj<*Eu6tW)<5w-Is=z?bj}?!oF&IW?NkQ;vvS&c7k0vXm7er=hnpc(3%%S&v0`ON zxr3wTrt}_l2|!k6vFdMz)BWXX9DMHj`#ZPb;yK$K?p#Oh>c(hTNl~6ZTGaq%SzWkm zvSzrd6hO$<6G1o79#qNkxjgD54k=TRg@%=R+l-B_@b$u@h+p@al2{h({;<%iX%oV1 zh%~I~*SmRcTv$9ZeDAwh(vGnOzRyW6)RL!@TP>MPo3L`M3G172U}rQIO05ArlVb3h z89i9XxeQcHg0n|sazso-uG3R!vz2pRRj4v8ptCus@8QeasuFOAsCE26Lx|!$ycHG5 zh^%KX^U-&F9d$EU0V=6TQOUN9h~-G+uxa>=;``Qmx@eSG;ycUJ5&N7EtY&s`_8-ya zrwR*^G+tb09!5wRyg^axIqj5Qsj{b4HKL2x%DyY`u%sn)$OHg@x0z3Dax()T8hmTt z35rE_{GD@gZr^RTz{~lCqdmn#UzW7WH^z#W*~So5ZioJHi&(BpWq_W*p@o(t9H^bLHk}OdQ z_xFOg=r}Zj9~LEfE8|^lvc8I1{-Zu92?qc)RwD}Wx zN`pksGPpWhc@|ONkY_obpJ#5-+4)n1ayG}CrP}PxSvb2I#~gvsRwtWIZg`B)C_BSF z8BW|g+j7~Kw#`z=D9ph=Dn1U8$O&={J9MLda?e7TQe#p;j|&qc=_eE{7sgYN7}O01}4Y!T2yW6&MyLhkI`clJkxx)vjfUlX$Et>%`?$+z+BE?J46bNN=oV+k(~3{Cq2y z;4$3hC6g%>AJEcK=+#BwRxxO!j;@V);OHHQV;Gatr=t6Apz%XPafVue1KAmW?g$2U-SLG0>cbJ33 z((l4pOE#)+*uLgTUmk@HbL|s7!HLralJ%|T0KVu;D=UnKxCq%kFSPID|eh?pcOZebb+1Z{1bfCDqOvwhBV6d>O$l5?1@@Xrpq{Ehqg5t&7?w>8p`p{uREZGRjLh6 z=@-t_2~)UV8%-_#k75n7-C2x*YNa)Z_K7nU!5%8T8X)sSTD%ztc#O zY{e6)MKP7N#uS8xcFAw6zsbmb`Mo$w;vXHLW#y<;5-15)Zv3|p<6CbjP4v@vu`S%r zbpGqEHkJPPJc-q(Wn2>}$F6yaO6SkQG+IAutU|0d1zf; z1^NXcmVAP0eG5=aZ$t-M%eDX?V!)B7w>2Qi;_iI|jSFPb8Zl5woUlB5y$G zip%hw-rvb+%VD0+QV4nqg~_#&eDxHQg2T@>dPeHjfBhE%RVSxZR}MQ2p|cg=YgU;- z)*7>wb03(PxiBUB85ZxUIxAKO&a1LgiM3?+CsS_d6OGT>k1bVRW5O(k))dr8Dza<6 zlsGB!tM<=n2}11I7j8teX08xGO&kCeddI|#y6649y00Q;Zkc12ol=gW^D07{lygCM zu&gVcN_Swl?BJoD{pBBn-P>UtdQdJvoWk#$sJSAADQYq_f=63TLIj5&5E=Z59Z}4j zj-j)Czy6r&>-&|j&}`RGLai;Zl#8WSc`s(z_-pny^o^@{7pSzB%xoM(urD z@n3E=LHFjbZ~*`y*Zd}g`NgH-PJd=AcO1M8?PT$7DhzKFdEV`i>)BIFz}fARCs~>T z8&0cap%`wAGKc&t@xWlCzmgV+&0>?)lUiNG;A1P1>lBZtgA1{xo9nCys+rhiuUz25 zx7wXfenQ5kL+ZOnpUA>dEmsU*RmQ(Xm#MZSKdJHBcWGBuVpqEdlmVpv?9mHG1%`3<(|pyv;R#m8H42biQ>ozc<8GmC(|2i{R`Rlq%(< zPr0!(7i9_29!DN-&;6Q^C{VhOKOcTl()WkS$Zd{k`xOS{66#u@`rASHwGfC*Kp@J{ zhQZQ!2veC^YMp)_V_WIg;6bI5o+TqwS;1CWfj&Ro>E^jk&1?%&<*S?^-_Usu%5Xk) zRMie1f9WM!uOMxZ0)W>dDhf-3NiNUHTXTosCBR>jPSy-QtjM^4uY+hy;DrX)cCI5I z6y2ghQ)9=HL~E5iXfhzxVyLo&{f}eIPXzr+boq<=lZNTUa2IZYLjNtM!oE%ZEB)-L z4S3~OW0!jA41;@>oStr-hF|O=3Hn`A8d>~Ci8f--D>2OVIB&0o;l|UGV(MNgD_wfc zF{2U-YyeFdk{>*QSA!yw#k4&0vlI45PydsgZnWQl zovHjzWfRR2XDEXCl=~>Qq7MmhHQC>hS%3_r03?p98W9SEt?Cf*%B=HuM)_VF#ln85 z9UAP^Gevst!c-#Z|HL4kx@zrBWVjk68tL+Dyz5HACE_@GqRwz@Waja;N zqJ19xj2)JgqM~M^r$c?R?cm>$-OO&4-62qpWZ@kN_+Nt|!7;c7IcI>9n<`VkR^_Q9 z9s{DwcrO5|+tAclm;KYRL8pcZ2*c>nj*TR+#qoBs=_c6ex5B^aw7sMhZz}%Dq~8X-RZ+^ z%Syh|Eh{mPa(~Yf*=rqF-RUvJHGOQ8j7j9No-zvA^0*|w&aXSQfT(;5Q$m`-22=zD zPqGqtshy&Fbep!c*o}fvF|#r&lZG|lOsp&Rd0orrS#el4G;~Ia8S4KjF<$y`*f%+~ zR(5U|S(NBsI4Eh8VI$Fbep<;6e|x z>%@!7S6^PGP+1~DyvQYt_0La?{=9zW=XpY<0KZ3g6c5^deQur|?CrRO!wB)TMdoZMv={L;%(A~C8qmw)< z6=ts{SY_s~Xa$YpD|@qr(SBjll|Q2Lh;DV`_U4NrgOxfeRXNm|HO(4_@AHR;@%88L zEGo>E+cY>s*(cN)@h&)cQHylFo3-{LEXsbz(Dc1I&>kM@NU8VyUL;%@UY1M)puL`9 zK5xxp^UkW{^|h8H^mP$`ACEsD_Y3>YLZjbGTqlApC*DgamD78oa-pu%hRNpD8Qqk; zPu(7K3A)TbPH{!7$W)F(H*G&mHe~$2S&N8_M#ZUr^dgF?t-wNdBA*XpM)Fd4y!!%K!zVsp+DpQ$=vp9Y=Z9<6)sC_^?oHE9S>oUCrE>przcO5+ zlc(u<7x}50UCeZob)CmaSm4DrjrE7aUy_ksoRcIX&n_)qfyQ&2R-+=`mqtRIuH`_` zOUOnT4FCYRI__d*1R!WGYZW@2Z+gPR*_FY%7Eg#MtZQWwuUV)_jtM$4u~iTZcd;KL z{qVP`+A+SWU(2D#8mAh1L#LhnK{pdxydiW|`k6M- z6ax}2NTA29leMEQg)MdqojE=WkvZ6_tP`eKDh&L&Zs~{FpehuksuD!|c$p?EE)ErS z!&6o@l+xL&s72XnTg8^c{>#A&Kq;{{Sv=$CNk~HUi8It_aaVe&L1twX+FY4qNPB?= z02z2aq(!$Ul5E*T)m?hcV~gjZ7;trQKRljz8=<7oc5w(-vmmDMIzMUA8VNF!@7p_N(Ct3JPxzwSz6bRF z94R|fp=|%{TOS-4xPsA;aK4~iR?G({ruzLwBMofG$`6&_G z`u#6cxR04T5a!_Hk18_gruTI>L>52O9TgV>Ws7|PZl3+17Q z=>;Vxr4Br`bvc4<@df2W9QQCP0Y5tz)gpTmxrQ2IQGV3&7=7mSm(X+NLa*#eE<15` z!?b_su%a<&?}L8u4rMq10JIZK9y20VXvqP84L4PVf-+T2imWt0PtUYbP$0<#dJv#v zlfkjp`!tgU!uuU(;-n)h4?f=>=KR%H&Ft7Ar5l?w^oc95*ji^M4B3CpoEHyl=TE zvB+h*-#Ka2i+}AWeWk4BtFAmEYVTgmqv6y$+EiL#R?`Jx42VM&gqLcFAx8zKqlGln z={P*g{^uLMf3I~pMB)pQ9~|r4U5};~DZjV)340^G^Im(Ag?{@R@H21RPA%$Dx5xE0x9HE7bYd(e(rG6>qdM6Ct|Fb|=h5>v_RgTP zTppj{<-;S#e_I9T*=GX0ZpX*UadBiP3X^YcxPPP-L7WF55JiNr{vfsA zu2Dthm2+=jb0mtJ+>MAx&-MRJ$Po+o_Eg~{$ch1z#+FrIJDh)gWUlCBAwKMd+Si@2 z1u?%?6u6FYHCJ1Q|9Gy1ioxwS1kIk^lwcD^XaF43ac+XR7jSos&C&MX7b#J`k@!g!E zA7k5e%4W$zU2jpCRBexo`V>D(ixr5Np(vGy#^5A7=(>g_UQ8n~^?Il8;OYE5aJEaZ z^?P3pi|c0F&%U4@osMFm()4!cr`q7lb1s!dAqT9#{_#KjA028I{(jZ`LM761Pp}$= zs#ZT^7~HQqUVrJ%$hor8^4+-q-slt0IBEg{Kr49U;%U;Rjhk!*>Bz86fwq@+aOaPS z-Sf;SYek0zdKMl;toWOvvZXu-V?p&Hy1V?*($K$LZ$~2HNPf#bh0Mah<79@&{+D@~ z#;0eaIO_I*`+R1E{m%5V>`+N9Lg)l{_8GWO9oFA=xLMHCq0;YWT8H^BIlBI8lVAKi zNyJvt8j(Rw*N?sboaht2>+ojP_hyj_KYU+@a@)5{zQL;dt#c#ZXz=cyCW*0Y%FQRw zjEWpgb@5=6uu~sk`XO!-bh)>In^MO_?A6A3*K|z}Z$5Ld@sxL`v7i@W-oH88iybi)Jy>an@v%tIo@Lr%J^ zeMIqW16x+<%|JLz7uWQZ5uy_A1vH;k6p>TnauBj*S3Qpk|9*4jqk?*EUNDZN$eA?* zij5uQxKeaI#b5S?_N95|%FdjVlbd{g;-6!lKIJ*k>D~R&CAlo@^g}MReatms7?Ey zT@Pultt=cE*_$)kJ4YB?*zBvx)j&O?4);!ztD5GTTy7-CCOs39@a#~k&4%a~&~=0X z?8!&ed_^p1&BJA+Vo8s4-pPnnrr4P%{vG>OWl4Gd58;)V4t0TdsQq(5d}U4j$>{qO znFE#ne?Nhy=**&1m4rKVve_va=Crhg&e*6wsGw9{jMxmeKZz-{n9CGX>O=n>!TDT> zjepi%uF>z;3%< zyU^jmEC0a zE^+S)oh^JkrTWpqh#<~FuVN}0pdJntNpV1vQMxA40s@Vse~_p?6w0<^j0UCu}km z!7ner*yWe>}f}>C)Ljqb>RKk@X;mXqI&-8BZx;+m@eb@Z02< zmg)G6(K9a%f$=f@w`LR)p2c<|a{DvTJ=Z zP7Oa_!2lEh0DuJb#ecUA8?%7gT8xfsCbn`L*spl_;^KO=@O(qGwQphUr>9LrZ8)OwJs*25Q%^KmD*uWHJ=PQ_xOo_pOYzEB8B9lf(^s+%z|f zL5kz}p@5%ugXA$39JVppU=WFBMWL*+v(uETd~t>TS&(fL}>(NF@>2s|=7NAQ-#Q=M>Q=FWENZ}Prc8Q>tp&Vrh9-Hr) zIxr)IT9Tudg$>+NI{@&B5u(#1N4 z6BjZ((6jSck%?tIw`lKCu8~Q>Ru{@4x^*BTfK-3#=4+M4Dl)~!hyLJ(q%Vt7aWksa zTudcWFklLY)>Aq!?Wag4QpbPMk0jZB`$J>eZ1t2N;@YKGPUF0Pp(T4SHSygvIf!9V zq_&dOWOn}OWC8*GCNG-tode=)^zrdmN8u7XgIn>@X&etPMhk=-RE5~Oot-_T>1{lm zUYQukxLQTQ005%&`+vXxZHpnG0??thY8K>dIAjHB6UD6O)Du4Mivt^x- zZl}SEK#nd+1-SjJxeE%(7t+BW3B4ReP?Am<#Tu4u3AlB$^=W@cbP+iUs9R;RevgwA9WldGWBC3(^)x@77eV#&>|GOeb* zG$AswOY!-M^U%8mzADK>2ev}$?$4s$IHJ^S*R7T(J`odtCJHjZZ9uTVG`eRgRCEs1(ys+;=X8M0)54NU8r?LDcF$n=@pz(Y4 zwnCqZoGdVB%eCha`)@#5sx$xr*eQ%VZ~_d*zg-@by<(G-n&3-n^Ll!n#^Y^l$1kKy z*VWxXzl9mFR?JNeeT*zFU&P--C$nbwSuhe)FM-sBT=CrlSUYT^hq7jY zyKW^pVfOEgBdn+3JZn@ZQkF#_@v)Vzno-Ka8U({d&=apYYxSr6r+VsJgA~%HUWfCp z4^FEO)|B}M!uXUWWhc>=t&S+q{X?t$tTh*-rV=9NBv{sz$^7*;UnU*=nef_nG?&|Rkx#I3i6U*nVV{OUr=-+=&KHT6AJm#Yw)kXOP-5fg)_QqEK9j_ z8#N?WeqVJy6#PHZ(EqdLJjrYa5@k}7$;O&Pe*u6*7W&A7*5Y(pt|}kNpOKqF000De z42dYhbo148x4AQdX}YF^sb71uOFUf>&O>H#a_#lnFNfv3vq!rQSCqA%ExTuOwdVIc z10^{0*gj?~jm-*b>58++1A`3Ijj`6xW+t}k|3bqTg{>_jiwYoP9ngrfh&bojL<3f# z9UE#fj!uXCI?Tt`6kxWaW7E*$=xy$-quW8uhkE{LBuWq_p*Y~ZrV1yC=~V?H8ktwd zM-S5lsk7qr$#GEk(Z8yYWb6k($XAC8fhIo6wR6KwIm)le^sG(#c23ei}AK7PxHeX%rR6=W9kIMNS!+V zx)fGi$}y&G?o>$A5pWNnCzctfyh={S7crQ{5K1_^(fP=KlV1NOwA!EfD$8wAbo0c% z@0UFtX;WeAXA*Vy54?(3nSux}0Z;CB`OtC7%h|+ZQ$|^Am~%azYh{YeV!JFVVOo0Y z*Iy=S2@O4&=hz~>_O_qoRip3)7iYZmuQjYucfbBolKA3PT9BMJ@bu=;^DmQb<9CCi z0fXHO`)&ul>6_*5O4jPiAZ)CPSiE@)$#wT-uY4+YHQ15r^)qrY1}a04d;bJYv!+L` z*x{C@PhgPI{(slIqHK3gk7ef55-6%gV=>j8iv46kYhiLc&i8k;dq|`q;)no1_aDLH z=7v=fU00s(=s(?IX(Nu|f!Z@oS9yN=pR3Hg|Fom+N@K5C@8*pZyzvsA?(!1@KxLnR z^N|cF{SE6xNR8jFrzN%ivD3ZhJP$1Q4L7ZBmzX8&`8hMfBwn(vNLMmZD(~&UMG?1; z`|W6WE`c(3Q)K{wSnh*1ix_R<}_9%6bY5zF0u@@G!dS^%zD zKef7MZY46yb{c~QPMw0Vs#n(V@hzC~$6V`c#nRdrry`+7q;4?9p*x0M*L_XVW;Ktg zh@)=jJ-cLcuxYGh=PdZq%&HeWVrDy`h9Ii>p<^qcnb;+nr*IF-r;TJASfF=$y>rf| z{_Z2*f?fFmlvek+kRd)?7aTsSpzOW4ekprVOK9Ew7rCtcAw%H-cH~152~QWm!d3a& zw{s+@*s2vuA)kax8d_QXfaATcr}_N@>KE7H6Wgv9#7E9hyPu!4o7q$BbC1%D-&$29 z7o#KY6umOFAD4zci-!Oaf%pLA#fWh!hys(2dkxMP`$lcqY`?Tt_xSxa$0n)+)pfOBZ{K^?TPx_5_9P$27E*~ou<7nHGiBU&o_10R)_!8F6FmB zXK0bA){>VI#z(T1e@)$D0#o$6w1t!rM8D;~s}_mvF)Nk>X7;UuKkgMRX0O`vchN@) z{JQ=2KRV+wZFf#j`F^ENPt}RW7~?BsdC4^~PRj9I{d@#H1G1$608~JC4_WLO!+W3L zhk}J(++&8LAj-?6zkU=-;&U{To{`Bavpy7N(!|wzGU*xVYFYP>Fy$Ru7lM=t52+?_ zKpbxM@`+EL0juVQs&s%4hMwd1E(&QFi?hE}0BFRVa14y)$JC>XOGy*qm{T1QUcZDB zHGCaFjFRAK=7FoP?%oBortLfx^~hn$T^FLYLjV8(fZ_sHB5*lVTBGP|02aovuIT}v z+~tIA1DV5T7Sw^EkilYv)?HgV==EVq)>CpoR@q96A{l3K)WLNK#STa+I2{WD7> z-e&m$kBCnUezt#Zh7*Z7)SJg(EmSwI1{ThK$ScLGwrZdV=-(hJM8eh2W zm`H9#A)mjdk|tzc+3{}(##aCUV8|;2-wTO>a+!$xwQZNAY1jX;!|U4=W96**jJmdM z>{Cgn!q15riu;&H5$eNngi7t;KBQ*-W9K z>}H)M4dc62GO07>^;<+byQ}s;N^DPrW9PEzZecx3dhr*vRmlVUBKmaf+r-8q1S6D5vwq{foCd5n9W$L~)%>T2?rTm?%qng2$m}8HUXra8Q z-MVszqFkADm{-z^O4j|4?htLt=YDYRw#4Nlft;DzhW^s+uhN`c_GGRmeg@->N<;TG zEq9)uB$3A{-5!q{l-yBEvF_zqTh_q}ObX<2O+HAK&Qx8mLH+nQ8(KsERMk*i|HqU2 zVz#qzA&;Muur(t}*9Uoy_p4~#1najr-`~*>Q2h|c1u!pKi|G6=mMMa9jF@dM5wtrw z*&lWfWT>=y0dh{u3+fvaTC*l6De5w1vCi}g{Nd;r-i$(md6-fn6^IzQC6rtp5j2^t ze>1r0OLGHSs=x{RBuu&!>mE5MxMIY{G3i!JbVMsmi`gNwr&REP#QaT_@opbn86kR` zVg^QX*^XgjThMBVSXogmP&g$Nkb<6GDwdm_>yx9UW;=Svflc{xP49IYX>n}*9%a%l zvc!o4#tw&?**><4Cuy$zL_TbnGXs&R%q^AvLu2JIjuA2JY{9=6_+BPte^b^V@UL)3 zZK`BC6@y`=j65uHc{UX)F(FaplmX0iK=moj%Kau~@Y@%Lq~wGal+!1uS}aA=6pA5Oer9h=r*F>CMNZ{am4Hq;5}VgBL* z7X?D*8op%gX^8|1kuuJqT!Q{j+BP?)y_5%bec>D!?6a14ZB+u$(a4!74z3aj0HBP5 zh0xO$+D^TY^|92vDKg_3SF^L6>>Dc`988z?9*b7nh>twYI;;Qq&*}*sh_y;2Se{e- zN0X{a69_*a9OT{5K1sDjJ^Dpsh@}5YOssEh;ebU}5hrEFh9WKML#1N-ah(wUA#OTN zL3@yizxX^Bt8`QwInFgfc#1tynsPr2j;bViJo3ELMDHh%p6#)=X)Ruid8~c2`Z>w<|VfQn0yLwj2pu*-G=wQIX z`5x)1wh|$GIln%3ZoySh?QGX{-YW5+-NaU5g94o}$ZXYaE^qKcw(R!1h}Z5hCoA-^ zS^$HpH7kz%cRsqtjwYUXDs#Np;2W7qLdA%g<(?pZud*Y*sfCNi+U;s?ra#h#>tVFe z7ttUIg(9T@079DSi-Pss)>X8FU-+r2m*L9&1ba18(wdAECKkhkkHV20ngoM>J?1uX!{tqAOd9RF-U>P^(WUswSeW%dwp#4c3G+#q)Jup z6z2q#b&b5u2jYdeKyJYQg+MSO{Abixo!O4Ug@S9!g+n*}DL_Nn%Z;&#Z%~%Y+42$8 zg)r+AiC71z*s(}j-kijWuGIftD^kOb?j7Ff`U_%joNGffQ7({MT-zo&W&sdME2pq7 zlu}RiA)@XH=W??2TavtrLY>D9*U?=hEf`9UnAkre~CfXlmLi?0H)Wa&AQ_v?)!NKUnbP zyLDC0nmhE<=;ew*U4lP;s3SLI!{TD&+mgAWE))TDA_3kte>gbpyl%s;Z)!_bbECb| zn*+B!#BPXkmLkvsG7d;+D>ZXyYq@!-$<^H$6f)x4)=^nniDc(mJtO(dN6qmx0&lRT zh#+;VijJ=|XC}o@HUdmmUM0Sx8mfXs3JkHB?qC<)P(Xa?@x1%^n~8%nFzHXT)cLv>c{U@OA?W$Zvq&h z07L{p_g9Pvp$vWP9m64Xb5;y);`ozX^HT|W`4Iepy-s)E#L~AI>~xOIvo0a#ebkO5 zNTs}jJQFN3jhkLD;oM%CcDm$*C!gT(`$^eiN3CMFT*w4H#DSXI4 zW4ERB{K})JmBnP;&0LfEy^j~VMB_&gQOE1)uW zl%byA0eQA{X7*|vx`~hQCW&l=H_21_0GLdHxM*G>5^B8dsxf@wHk;S_v{x)--eO~- zZ$SRcjrHZ)D-wnAu2jm2=-QSoqu2zVfiw`}!LS(0rWZs3R_#<^<|l?}Rqc=MF;sb9mvdzMV`yeSwsGE;q}lbjG1aN` z`DvCmCa9<54_6oJVK@HoN5O<;);o|3-rID{SC}Y6z4}0?hY~maBzLQG%6(2J)vX$0 z2(r305yU{{@v<+R4>sqfDnE7J9c${3JfDn>l4S;naP4|B?9-CQYUo%iwlk58=&Xey zKO_EReQiln;&kUZa!TyiEU3n!R+tpsQkRTT;j3E7@8L<;Lz+ay5CgTQvW@Ki5mJ}O zPjj>FYEuA?rl01Dyk?!R|FENk8|v*Zc9}06T?|3p=eGQJN?HkHV5k5@0Q!d?$B?_d zyOB}Q5WR5Y6B{fOB)}l3#O^Vwoj-}kf~1edF{=YU(=Alca+g#8U}tIV*h=RfJtJW? zu>nUbingz3@1T{?R;=tZSoH#W6es1cYEL$dpbU#V|8q}-uW}N;q`BFa5lasMr@blB zEz2n#3U`C^6ZB>DS-MDch~D5D1E;4hpW=hoJ7q|bLI3~&y3G5upEIkqXVm4bn)^%a zyh(5Qvif0}*g51Z+D?b491I{M#kKt#<|dJ{6p_@(5Sytbbq`2bok2HkSAfrC!MRkN zWK8T$=b)cG|J9XfPXz69onStUKY{a~x%V)$=N^4tqF|8(2-|vB{(l*#n*7YZ%h>-@;O?QA0CU=UH^|zH z_h=%V1s`3yic~(I@_W9!=VeFjvMMug#7(Gp;riQBpKwh8SGa2Lm0vQM`H#Jq+@az2 zzH6Vl(exVBQ(-p%CILr>JQ&1rcpWL zCknT()>|iUQ~#wtfPzhpPGfmp(`$S3MWdY6n{xara)5|zjrEoHCBmrL67m34q)u&| zS+uDJsd&N%Lw$FaLuG489R=L=Ac6pRdPs+tCimSu6*v%q%g&R$C1gWJ znnyyz9xWFE>X`}N^~Fo?so0Njh((b)7)I=9sl^8Z0001>XpzyOgORy?aQabO*0Cxf z;*Zl@*_0g?D_@--Ue3QYOM> zF?m6x)n{uqZk3E)9aT-95ZNH;w);-%>DG7En3%}kJRd?fcjLq5c8BfN8DLUJWm;>u zlLF!4kkG(D7S(uOKE1nB>3NX!VNUoDn>sh!2=zg;Fj~KcYfW#d+8y?olY{}(Z+x}x zkY)Qe_dGMIY3u1Y^iPXuXh4K-xwl6%DA|)Rm^& zo@sN)4&!OfUIc1jsEs5d>GzQDvul&%BM9QdFLF@X(X~Xg?Uhikr3`e+&HEGxSIPem z>w}&7uH8?5^E9QYUXclO4fb%?3sJ^Fc|MNHJBFVqXt*GNJiU@5fv50ol+i#7QRacH zsYnO;oKN|>R&;*Vda`MiEgc1zLljnSOTn}cYEh7awN@EaW-F3rJ3I%B7Q4D1%#E8qX_ZHci;@*8VaeO$gKoFAhn!K0QRTS2!51# z3$QIas4X%m4Frw;n=@>D{HGqK#LldJz!X~5|EwYit52C_tH>;H`QCJ%)06(UjcEE? zY^?2{{A1o$>yG|yefwc`S%R8k0iYHkq4S=TCJ=lZLAf$i=-25-LTrX zeEo6wZSf!=1b{FoCH@N;)UNd?u+<5j-w`N}by{P+{cO};VMxs~T9UYMJGY+}|Huu| zfUqT#4QoU&BS8>(ThGc+T64%x%lIU7tR>)%4c4o}4NWMbbt&fQ&fI+!=^Cl_T%*2t zmP-Cx1{}-jB#>@d;xJk{l}DM_6Xs+A&wIsB4PNxRw|3|c!q-Yse#y$8f@;MlS{P;I zEB?XJ!om;$WTBw->I;6Sg6khVz0=Y=Hq$zpyvY?5%6L}_nypTTEc6k_TU-kBP#Rle z=w>>iYpPw_VoB-3;Wp|cY&CJ&Yt@@3SvSe!s|u0(_4Ien+5@wTP{(#gjO7*!EGy5* z)$GMfp>wz2H+-wIPKOtp3C_=;T(l4R3WLzh`N)g|`V;kBwVQk&mC`*-wf{mnK3T)v z(H2F0q!)~Z z*muP{VM${rFyL#miS{2S<(FH}vmJn#7fD)$s{H~If%5Jl?Vbq{XW=>04PkA>+*v4u z+zxlY2<1@@EO7xyP$m&qOD*by2ze2F=fL0xux?F31(nQ&KHlDf0gC;sg|+tJ(t}f& z5xc|n-)lSHDnc6*QPv}m%;x=Lj ze*3Ao7=Gz|x@r8@ayMl*O(5=4nH#*xdq!4mqH#~v4BVilt+(Pi!!j@j`gF|=G~6Z; z2f%lJuJh^WIB^5{Ocm3?gfE9e-#B1cH?$t8>%NbsLj)p0_=Ym)bpA9GT()e#4{Sfs zS+QS;vePGw(#KfLhp3Vbw`?DuWbe#auI3@UZ`r0XyJv=n=ceZGVM+qVN-h_e5hVtu zX|#{7JhLM*R)wqroGC_}xvSD}v_d;j?7Us?w!~?~o0L9$S^(X-V5Hk6t?6R`! zDv+DhuDpyn_EGkRCkS|-dT5iy$LirRJZiEFk?^GfiB(&fI6v*D{_;|nqh+U*-Js)? zo?~COeYue6I;ql@A(nua(K~Rns#r3CHmA=vzA&YLnNtyb>d0Ob=&|fq$F&a9YnaMY z)ZrOC3_DFua?>4)6i&B&MS9-M%l;E2T}gj_t}@`m)E3DBNccwb*u&ywygX+{BIfpm zo%F}9iA0Yk&FU#PR4Jt;BYGtKpjfm^-4TOudH2|jZgHr6w#DRO@1V^?gnY(|(r8tk z&@@QCTy00p-P;LgILE=O71SM&$&V&-qb=i{@v`HX)pMf%XbPXXbtjJH@)w>)8vlna z8CsH0P7j`7Mnm(p1<7|#OIc-l`K6bH0}x|FtWiu+R9uY}`E=XA$ZRfy9NBhaGg7r( z;LwrC`B7x4p|aLy72Vj&@*myiQnFmbO&*hci1ntpannsk84v~FhV}fc@)$d9xSkMA zs;vMA-z9@Pc?yQOE-SW{&3qPw+f?7)$a1gOhn>F^m7yJ4KK$0ow}asVLJfXkAghpA zW@M$t5n7}XsVp}UdY+2%$a(E@6913>Ul-Gz(vxf>rzq2?=IwwR!!j2M#0 zqth_}s%y@_Xs1EL6o-=})S1r?{pR0&f5*jjTh#OTU7kIi(~cX%6jrh3`HuB&=;7Bm z6+rvxxCACmF=AREv*0zR4-cM$*;fi)@o7_DN-X&OJN8+OFE~0@M4(eZevr^zNHkK4&m2R zMmuycCi82UWtnr$=3IFz7`^aTCZs8fjU-?rB>l-$hLC2ilUhNj`XRd}XN(o^c;J>l zs1+8pJI(xZG(N?!P+i!-n_6`laJpB;^ZT1rH4uOxv|apuIoXi!z`E~ktAWcaNR_Ic z&Tm3?(A3r1nDJdQn>Eu%B9L1XC1nx@SeOWxwia*5pliI?CqGx-w8e`pYF0SDmvXj5 z!=*gWyjJJqzOCb#&fS71>uV{*6sSWxNV+;BSfoA#j9Af^fCg)Z(njoH|n)k0}2n)hVmLg0<%%R`EKe`Y{(u z-@=B=W5|)n=wsfuG{@amcmUE9v26haxl9ZQ0TK=u&0G7-x1IpyCLM*ri_? zAMgQHAmV>UX#THw2-6+NDX)9_3`VsmLpFYXj#otv9im_p$IpA18Q|U&06^9r7+=j$ zUzE>L7v{0QEa_9=w`W4z{G25Di!bI3_>w{*9hyFhWi~INlv@^mMd_P^q~&;K|1F#0 zPSwH!jbhd(Olu;))fPjP(QjS@q^d52mu7GH;e8S`Q305!SQ$@V^k>m6`i%*dQ#Cj@ z#r^1QFTd{2;BDIWWn_s=)<57%gGdBfJb7M43AqRW0FV^Nn}sE|Tn^OM^T>WBj+t_& zz4(rdudbX*AZ)U^^!t8_ z=OiheuH&3SnJFW*74Ri0-DqMojkSyQ@F-ROz>Cs*2=fDn&*MmDq#h+=_`8w>@+%u6 ziyJ2CUXe8BKFLPuO##@`!?xuKTM?iZB#s2YD924n%EeehmLD$J$rw8N{NI(BW~)CqFZYN^jGbksyh|KlkyL2jfDi zl)!S{BizU!TOUlrS?D|*UR?ybO&f^CbO)K3(s}RaukJ=+*X+OTSyi6f=fIZtSScTD-FvX8 z&>0N0vm{M_-4&P`l3PlK*a83uUh8~Qb^5v98~B8>oSFMzNl$P5pJBD4-ObT{=%NU|TtG-P;&FC0ZCWPpIRn#<`3WExNKJ;xn5sx>R;Y`ogvO}YSXOPikq5!d!3`^X*Mh|#S(`x zzI;P6MFJp(&9eVUjAF)veGG}~=Bm!Ey!mPehgadH(P1GgAg*>r-5)IUS;|`|$i&gd z>9cO5;40io5hrsBH=c{LmilDaGwoL9MopCNs8zQ7+{jYS9xod$nTBthrzx8xupY_o zpcz6pVJ#~yL@IVzoIW1vTDio$uL{e}zK2&@4$bgB)e8-_WtS68rD*(YGetOJn7BBA zUdl0}a=lbYFUjUsvfcovVo7h1uyuwpne{0Ko@*<1n0c7ENK_^u))e6I3RlX= zETqes%Aqs3dPp_aoX*48I?RIl+ni1=0jE2ptL3sn@txl2QAp8v3N70^fePV=PK4%? z=Es#8vSLHX+IUCsuWEXwvw&{^0Dv&$T53BdYu9Py&FU+AJ)yT(%fxQNWdlZNU^lFP%swE9fz5fY2GY`jGR!@Bg7qz%KUwBy*JolbzQdKz0n@{IJ`LNQ8?vpdYC)*u%Iffn5GYm%la`*4K3=L;OBiRcQb9(wCn^)5UBc;&& z1z9K*Pc9a^JM|GoBg%5osKx83O^X4eB_nNSY==(t4OE4kSeXVAs67= zG^L(Pu8BuHKMx;SvS2U=&o$pL`354MH~@ew5oQ$gMWJd}V#`sWl8Xw>zO1>eu)Zsq z3kUlCS7?@ofVYEwwNOb}jKtm_fl2A6bOC9lXR>OQ%+{Gp&qa5EX!;{z;aAcjT4USR zI47?^NAj?Xl-1p1)<rl-TVu(-RaY{EhZNyR+e934rM3XC$saou<=-JCt3)GT{a_$l+)yNY7E3GT&{5T>mDv(JAZu zSrSwhNy3p05T@wsOO3>6h0UKA$?RWd5$iJ>TxlhzEh?)jsqOtP!-UHC`Cet9ZF<@7 znMyYZmUg{Xc%qzBT1XM=xVpM!k?@m;9;saXn$OK{BjTDe#BNS~yWK->NSqinzI&MT zw6LMCtfb?2Cv1~5o2yDB+_2Z?__y2{Hk?wSVa>1h8Nl?j$D{PSAwVzG5*Lwqx6z+R z-AgA)Cn7oY^`Nr)%_51t-XmuU(8uM~>Ev6g2mW!h(W8-t+2Y7TlmjoFH<)4)@+L=H z9`51pIe*uxbd@SLpNj`-Ag+C`j^e#(1#(PTD;DOEpVHbFOz08*gwhgA;hQsXhr25E zS?G(<8m1c`Hd67(X^Ew+o(RB{~)X|(_KiEm3c-YMuo_D zEq-s7`w4tu(wLir@*bAMW}HfgUc-oj=|fBP?2s(dc$sawwLQ<_fryM9_OoUnYk-)zJP`*t*?LzY(gT##CeAy@Q4$t zB|bXD*q|+bOEQxtZg^!XzSSP%iRk6M|p?)c^oMc7tdv zX_j6nqG(=|wGH#?2gV6%857 z=9}8M#j*0y4g;wX_x=4+MEL!8*I$R0@jFe^X7Mvmu(7-?byOxmb_L_WBb{}E%Iq_S z?`*jZ7eU%*hk$~ePv>m?DCQX-Ez@~x&RFOMLn_~Ad!8OcB`Pf?3kYe%Sw1#2SFx;r z8^+jo+g8KcyVn_(U$P@&>4kJP3j=DthvS+JX0 zxvg|v?Kc^0Lfr%P+%ul@#?XumJs*&%x8rl*2D4{7>fP?&K?Y zvv?S>j?GqFLWb~m=pJ?JHB&v3R+rQ*l~2k_MmM9bhxm#lPeBJ~)d;^w@Y9xJAlK(R z`{^v&=Ht?-{!dJll?(yJGh2grwvngqzTq8&kfd7}+kk!;y4N}Lq(o+xBfog6Weu;j zc2ckNLg=OuN>nL_J-M)I1x~I$sc?@3z=2u1|D6&vHN(+PTMY7S4uR5O001aSK!j@+ zlXtx0nR>@Aks6t&>+Qq3=ugR#Inr)uICNO;Q!51TC!5{D75we?Gsw~h;UwlSX%PMU z68N`jHCB*k?m3SnsWfbZT=kw<{Y18n>Ne*sjJVCGF9{`ZTcIA(Q+tQ9p!l_mSul$> zO};d`MsE%~z$ATa{XY9PNl)G!UsB z{sB&N@4>NWW{=k*Z&Pt=&L$gT;ODT}p5R!FuJ7hv=XZU+fo9RJJ2@7l$g7+=i&mc3 zeC|Z#=aq;Ls~=Zrw^K!Pv@JcvA{2?FB>aG(Eo8^?cnF$zr~Ku5+>DdUl}#E~qWxSR z*&LO;31lCe6NVfiO=7;~){~LnjXS%&`!F!vY(33C9P_3Sk>m~1>4 zX1a%U6$1eB%*!DJC|i`o_U(JT8?2FFW4W}IqVD9LKz^(ZKEc0w42l?&Mbye}=_cB= zV=fus8b(Of-?b-=Gtt zd3{i2ZPD9gLb|F0!8{{{_M@-G)!q*;&DoJxu#tzAVy0lLA0!q>W4?&8KwJPIq)Z86 zfjZeV*{bawn|9|dH^GkJ?A#A!th)}3{K|lFWSPOM4R!p(i!>f4d`8YMgu8}JA}!x< za_`)TI9SY?jV736+kNpnW^?}S3;C4S1ytC(xY)AkOjc=S&w zD^CM6bR#`LyY4Gu(nIP6f?pPp{fwDa%N*Q|=~#Il^$$n;hXcq9?e|Y=hRl=2AT1G> z13~@maXm0zKVh1N=}u+7vOya4+Fgz&$8Z_3x@1F-Im?^po(GuVCm6N%oV32YpaIi- zW#ai{Y;%m*u;2raU|ukGO&)tik6?u#ywEZX1Oxyuyu4976-DSlwews1GPz2}TJtp; zD(6{fHa|Qim-mPE(-YoZW2V{*04bUwA6=n5@HH|z=e2_VAklN_CbC@TUqkBs_w!l_ zVSO53r`q!%lv+AAXI|j@4J9B8Z6YlS5~H448l!s^A{B z#~j<$W9+Y|iiNS2c~6Use2am2p5p(3au%jLrxz0L$ygLKq73!;M)_V9@RdomR_FUi zP$v>S7>I~SKOLAUuU#n7lf21`0ajOXQu}*;ENu4$O9GLKbkHJp0wj{Qv23hu-cp~4 z`JPdMs$#y|CSo|Q>zI60Lw!D7vX~|uJogqqPVnTrwYr}c7e^|A3yfD@PT`aGZLPLo zhUICwX@py)+X$WOeL(cNAFkrYSUSZhe}a%SeSW;O36 z`$uy#a`czAN3;R0Dc9pmdsASPmPOviFgn5+iN6D3rz|Ej`vYdKI3Jyk_htRH=_{&Y zztU?jn;)0E-Lxf{YjnU@Zj<1@qhI=4^?ncm(EtD-0gf7&UPrxIHa1F6<1-G4R3GT`^C>JItf(2f}|dqI9ugK z5NA5Ce0Rp*P|k6($@$0pae`3Fqt$|iDG5W^JMW?$qm8xXyzfaPt9i%f|6}VcyW)(Z zWc{MS-L-KixI=Jhym5DFENF0oyEg9b?w%0b-7UCV2ofN2Kg`TsGjs2MIIC)%UAvzB z+xc6JcnER${@m!3k{-IRuh-&g+3$3FNmhD&08m8Zipq#QdGU2TuNk2cHk_IXc_ywtdytVda(`j+%%}hscl%Cf(Zky2 zzZnzXo}WAd3I(WzR=(-~`R|K!{r}!t5aHkvz09}w&-o$A@xArpkuG=}QEm#&{9q?u zPUa{2ZU7Mg4EM;A^T^G`lG+(Sx7}s8=suqtv*vzqEvkJ-naU%iu`aF{PQ=3jX$<3T zsVc>#03p-WIxNyF1>R`)bpoV5w9WI=X_6guWmatq0gGR{KO8P@wW{8Yh+8$$r!A7KrjlD%$`_j zIyQY9JLl%n=AJjW5$uOMciy%e5q}YnIv= zEr?c`j8yJxqyfyV`3XJ(3NJ!yb++ystquv<<*TyM7!z1@%pdhyXBab zk!#@e!rc|8La~**Y{lk^W;qz|a=z*o57Z8V4S+##+*M>z^x9VeUxQu|$wsZ2k`H&j zFwk`muAYHLH$HlKB~RX!I#nsu;I&gjVC1mp-4sc6>{|j{T{eEP@M(!Boml*aUDeKf z1P@Lx^7{JAx|;UY2`k(SuT|LVGB$lf^x_+y~W|)?(*3W=uCo1{^I1g6%JpcgUA_qhu39)LEzcQ$$Jn4^nY9l6X*tD6o zh@vz=l!W23#~Yk9CD-vNy6h9yQ2dHIhEYVz?&OxihKllPI+UeBzF>BFiR`&(4856(o@L!63 z-DuVHiPQK%tWzJj>~6T@zcZIj>cV>ZzBWmt(B-7m=yNMNOm+KWv-*!Bog@G-r<-96 z6$;o)IdAomA04zCdLAA-{+=QUUrO4cUxE{*$adr2i{iFzuENL?bdW1 zA*?Je&fuwMWEx+4C#xsJLIX6Kfu>P{Ylas5dcs#sSj|PMRp}1+>@czzIB~^=>2(r5pzO*{@uXx{riTBl zIzN%(8Tw9kfQ+;+alK}nrgSU8?tz_aOBRqLjLs}%xyu7(&A-qOl-tK+M?XeAnQnR* z`fHvOVZ1`-Gqgizif|@yPD{q(pto*ea=u^=09a(K*43-I!?opfM>MaYrSMmy!jt47 zYKl>L|G-C43O_4IWx_-$Trk8I<+nzM5^WlFPdarhv^rioIBhUUOy_cnS?FxJ8kpElVM&$uN zM-an5TJ}WdK&0w_v~5ysOwP}F+*2@ed&DDMApON2mCbB}A}u#(Po&*Iu_Oq9LjqrY zjjK7If$^e~FUp_ND4J2m@zvQNq2kjaOR985#o$X3n!ZvA&=@=-d?k(=caK`0ReRH( zc=ZxV@&4o;MfcSRzxqSD5{@cDs(glN>A^63Nn|0bWHhUN@)aq&XD|P@%S0&-fG@!} zFV-Skg#zQS)*Pe{s7j=3ji8MsP?+SlG=G`PKM$xk0J1=U5+Q51JeMX0WYo^iBKwb1 zHLcFNdZq`KK;&zh)tPrj%P|I*`|r_3fsEp}hMh5rnsKEH75c!nl3pG7@e<1E7Cxxl zrLY}^dZCWUNytgwqy!7U-k-m&m1(ToD@vWrqI7Rsvi!$g(hMLep&iX%VkJr)#Vrc7 z%CigYfTlOu9und0;@90MT$e29Z5}A+xQJB7-x<) zCzp2gWaxfo9(!}xRDG#crE|0V;w+;x8lXz863Jkiogz!xYuEph^e$VGw32L1={Nfl z(a`MKnQ5hpe62)j-Ll;>*D!Ln{zEFkL(u(Q>#0}yrZc4ge_sqJ_1mB+1@`x(rf~-A zyrTbk|2NrkXW?9CFwKcPUz~9g!V%}D&`dBX)8bua;QV;#Ac%=z|+EP_m}1etwNTfeR-Jz zJK`*!!-W(^)E{$K@5u^5pWQU3>(gTgiVzH}rk0alKg&rv*VW|YNJ z$d3>TUrG}mQ4AkGA3t<2pN}T!!0P(D77iBx065giPv}iPL4SFlk+gofm??z4)%7W@ z-1voYe8TUr!6SV*c&tGteNWP>lYDEkUZQHfYm6w9PrSa&Kr%D`(e>|O|8{kWW7OMw zqnvwqJm{34vySO^BUQ#WUCp9WwUwfjHt(z*aXUe$HX<8HEC*b44-+2Y@+gvZ4Ztz56e3*t=@TxEk5|VbJ1w+_wH(VOjxIY)*^SEZc$VTv7yGtJwiSe+ zo+}RgU=cUsu(E(o0)Af1}G< z>^u_Yor&J~^yzM*8Sk~1)A$$UXTy5e&bA*j4En)<<&##sq7LhfO{8I1AY>GiG-bUsJ@_a-94oSrf0bbfKZ^n$N zsMk6Md1wr)=J?|5n~Kq(9UHEa0Zr{@zD@N~s8@n;SHu{1z>jAiGiO=ZC(#4buieDV z2fh_4$VR?7ZbOpk>`Ij`Tg|eV9c?U33OQ~p%L2KSvSd#7>}$0S?iUf^Pi(oaKGpLF zGRpSNkL1SRVwtoe#b3v_Gi)_~3{A_+G{=bpAOHYRN0_PTW)NjrprEza>wGQC*~*g> zUWc{n^S$YVHV>3*j>w7W(nX_JA2kpBj+AyZQ+LAEPi{?nATt8bQ>R-g4s3<*eeIn* zAN{_^*q@~GXZP=}ib$*wzNP1k#=gdQ%Y*h5s&Mtwo#e_t-zL*Eio_F8L$h!-Nv>1U zAL=jyI{2R!3sps#6@nC&Zmo)iVgPt}`rb&*QLmDXO22#y%WX`P0|^4Zo-YrhRrT*P zoARt$s}1(#Q@wMbB_quPt%BuzB+Z;xqeaH6`r^V34uf6=bV(c3y#rq3~tC) z5<`QS#O1>V2WKd`n@Fib%WK68r8sYX`&r1b0-!FeZL2&f->@m-_tjT@_6zo3HBa@R zsCHkTQhAklu~F${JV5{mjw^w7lX}3pj*+w(UD(Zac|QC6owFK5d^!=El*Rjpo7^mY z8zV}4lH$kuoXZJFfNpmeyD8#kKVAiyRXkT9Rc!i9B*Fuk;^RJ^HP=CCns#3-=;-(r z^u}(!zxQHsh@Mm_X5VAqJA;D&iuzc2Q?R7+H1+T*lO2^718Wl{YQ^7)vzPeNhERWk zyP;a~Uo}>%9W4wc_xLOH8F9t{yz*i<75WuvW!{Ff2eLg>b4dV|Wy7_(*~8ki64tAC zvVIj3C!A;Xyl5u%Jn=3!WQgF`V)PopMHx#^dGh+CxqC*FN%Yh<#QB*4YM;$=&`O*w zZ7X)L%*jAsOExleLtFpxqXx5vHlW1A?W7^I^;F1_)R!sh7k5^qAk!|I;7;4pU{j|^t{=|4TUz9~Q? ziDj8T6Wq$z=?pUTnV_S={&{;-F)m5S$YbNEVKl=+PunI~QBqSk&rh-bE9PRx)~-d@ z&5~AKlI3#|Jv;yam0FVelh3FspW3U{2py)nQCxg?>ka)mw_ecE~4b;bq(Zj%}Ir=BQ?1fd2_g)w&+-nv#oL4;wq5x1Itg zbJe%%s=(?S=HUjkj?CKyJTewuuN8B9xm%B3%Q(XDYeV-yoxJ#pe* zM%t$ZlFNq&Dn*D{h+R_aIKC*Alw-1uMcf*&i2qP%R$sw~9qVtNb=VHU?Bl4wu09*h zj@TyON?Rb+%;TR|EFBy#=qXmYGq)RjKq9eYJjzD=mMnQ?7TXxfTalNNaN;gO1XEdy z;aDn{A9O~oa|})ql35sx7u)ykB7#E=4$+a$+h$PJc{>g`w@yiEqWY5m!&Q;nV$A=& zH6g+Sh^4kW&=Uoolj<%dPgB@mZUjpL z4m=8O_T=6Qu(GE4C6nhUIXkvKecan=-o`Vpi9xs}T&+*1`FMkC>Bt@AYcuFklB&Ge zT#_Muh>P@5Xdv1EVKLf!h{^yHL>*7Z1S0HvFubc($1Ar6Ip}I=4^}i>OvO&Z8VYE8 z)Qk2?X^{u-4rjZh(L7v=Mp^dtueFN|(EwB>Fy~lz;XC^$`LVI%0%+5QWJmYg1>UJP zPfwM6sn(}%ZbEHTaK83^^)p*yw^yUtY?4;L)@(TkmGiN#3Wk*K&!6l~9fTQvu;PE~ zqA2WGp6xUYlj)qL+3#o`NsO1)3aM4yKRJO2(h2Ki5cO7C5vtpRz6a z#zG6O9=7%qk+<|F0817a0F>ktfadou?@`U~-tMQ))gnNEAJ-^lWA^+>Y{-1sIW7@Q zJW^S}XOnRXag5ZdzL8iSg-B>?vUjUIl>t^l6DX2E&XuP-x}Mxz5obxzfz($D_}WVz z(J*KyRUpbK89Mt5%@U_-8PKY%gM>81(5}5n5V<4wbb3zsC=UGIY^{Tiv@P}=t0;cJvnEtU^ zlomOfi0ql?mPDUJrkCx%H1Kh<1y74s&%giaMKueTse}{D<7iTPh)cd>1bBKX$cwG1%O0ogI3u_!Suqgq9R$jnBc5F@p8|v#F ztUqb(T=l}fptjqX!d0Aku&JA&c9FZ2IFP)^s$yRK;NLhY@}YtQC5rr z5(8ecnf!!Nxt4AAd2@usL2(`AKiFS3Vh#C-A^$v4@@>t_W&5b}_8v{=X) zJd9MRz^5m{o!3UglxQ%8b^JW|e7#Kb@pmcnQH#YsOu=CzmawMV+u_&7B!vfQ<2(uy zfC!&Q86670*yA^F@ObjEiyqfVy5~FuwcbJnt`2=>mBP$$>Crl~1<`zcks&IUeK3tt z*hj3X%HH)&sqVQ^7`z#|kUhuKZi~B+HDy7Qr8izfL(Tr~l@}+(>=uF&j#v@glVe3SXEg@|7FlqJdxlKy?j^ zHeXE%Zgb!vA)H&eaaBjQ*X#{Q;>Vmd=|E|I2#WkAc~#MiFo8VYBp^SC_l}KLJu8d8 zMT3AryJS{8Yrt^^m&0VbJp_R`^}tlIWUuJ&O&t4=##mbBXvrXh{jJ(|=?p%L=(Ir5 z?X5h@_rmZo8Uk)DVQ2lUM32FVIKx#igb*NlR+jVP3oE;&f)U(f@c-)SD_HL?#PHlF zW90UTGjig?m3k;-lMNcTxlo2@cOygtfD+3}7+E^H;Ai`S=$P2P%~40t!M;242%E7@ zIeO}dqb26#>kv~VDla-4Ynt&*qo}bFy z!*B>U%0=1hLG_#i-FoYHJRpUn^*%-#wM-@SN6#L%3n%*kavs&%c|;NbzypVmv&sg* z&P`AgIcycWrt1^Z+G%-O|&4oov5kb5Ktt~Ab^ zmL3NB4Ugbum1Zwv^d8JgY<9BQj&?zS6( z^gc)hDue6}$iY;&?aMjAM}HmUZCWtwm5}phwaEnWMg4wu$TMx^PO31u4`iKKs<=Jv z2r)OV50+vO$hhG#CwJ}gyIOp+%}T)cOSBX}dENRCYeoCdi1nlOj^-7&ds;nttT<#+LAOiPK&D$4-F3HzkczID z!X+1;N!JD_d3;i>9HywZ`0Cb}#(>&=Kcoot&wWvJp->^hl)Lsyy<(?H4-&ZmEoMuWhZ(AXdtOG@a2NCQ{ z48Usj^+9>NNLP3p_veOQ+_8~U&Ee|Z)ureuip_%u;kMbdWzchO%I^`IixqZWr62pN zw`Fm69(@?P8mwrj%1*WD5YuV{C(+xh=0*^8U+eGBaI!5Br zo#}p*O`7g#l%*=fX|EVU+DRQ!<+KXu{|I}02%HG*2?jvr)C*FTDnt8! zQZ{mAP;N_HsUy=nI{4G{{~qMriRdkrdPZHplc{-#bi|7u$viuGNU7#G)D2W8Pt(T? zqe%P|$1uZGxU$XjwgjQdQByNHdn9l{bs7DkILtFLJlTnSkeCqvH2^k#MW&W;mA1KZ zS~x4wlQJePh|y7?uJTbj7P1)M?^G?Z|5WUeKM_9d^g6ebfGQqt#M= z_7VFkucUu@HjXaLe_NOpiObe%4fZ6;EXI=121NQ&=yrC0V2o4t6j#~_$V^0-UYk5L-qg-#i98gA^Y89ugQ@i_Z8;xuAFN&S6RyYjCz9{c-uzk0yr(QD!C{!j z>M(_q_Fr4a(wt#`!nH~nF!KJN!q4~@3QN>{S;8SGOr7U!IJ3Hcrh&DfKIEjRQJ zC2l}C0M9rWia%A;@E6~sL!Kw^wd){0W3p4YzOx|xB7NIXjvX@C8f zenEARg?C&y{m224!@jlGcK3XBH}3L_-Mj4>GyK43sNd7KvwVgxQbnI_&}8`L;Rit| z;>n27b9`!~9m`Yg?$>gOQT!bvQ;C3~mlWME2> zoJ5?Vm-LWYUhQ&ng7)0WY02ZG_4?c;bp6Y&S)=Bi{i&$4_+*|eo^B;Z2O^9*Hf>p!88btgyN!@BciDe!lNJ% zDt7mY4ac!@tS>OV%V98aKjRTq#l}Qcvgu^d$?Tadziq715a4)_RZwv~mhGB7z@2K_ zoes`k33ca9AE{_R;pY=6qhFw6_!N`!5JnffxiJ>G5Y-urjv5s+!{9h`UX1B9&V%8GRUYjG%oCBdO^itu*m)7LHd3a)k z;u72i8>YGulQftjbk(IaMz0S3NKKgh=`XITAovuUwdmo-wPo+OduglGRBXSEIo!ce zeoGW6%>7IMc{A&FcJC7Hld(&i^X_pa))~Uqm`_d3LLcYUBx?^Fox0cJ!_j5$>WTF= zi`fIsLZ!7|Jo9PlLb{C#cMSp~u_NVY)z0Q=d2eprH1e#GF9#u$5-|f!I3xfNegyAi ztjS(g(ZOHAs(3zFwKmQ5TV%b&zTPOZ2v_0{k1CFndM$?!%EGu%^ z6h-FeW(O6IM>D0bR%W`|6itqO1V6a-Yjv)fR!e)nC8cB%}y*zLOBNk{nq@@MnVbjB`QPYtkx@UXUksA~J^!+K*?=L*f<=2@B zSK^3;*^W2($gz+W1$;#+Y`3OTG%$VawBH*^aI@~|u#K9wT(%Lp2jBiQAtnWTlp=FD zwZAQ{Me_%VGp;&_PO~~GV(3q1-sI=b zZVIk#j;V6axSj(Oj$akIS4&*5gD}gR9nHT%L_Y2!8(X)n>RsSEooVBK-(P*iBY|Xg z`hF=h>+vQZYRe@Sjo22b9;KwdrFz^)Pt+wWdoGTjeEla9Q%buD&b+uj_D}F}sp|?J zSsgFo$#fnD{qJL}C}keD#-bQ}dx=+59u~|wkm_`o)3VJ$Gv4d`NRBgL06=xeBGfk! z>uy#%mQgh#Yw!3a^vLm-Y)j1B!G;aF6tJ< PTLJn&dI;O%0Rc<+*#yYqCzltMXZ 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%0DLFTxhS95OSdD9J+*RGmoT0*Ts-%>^@s>m@qYA- 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ℑ_kuyc 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%0AGNwo~<8x`%*-I;GNb-X?%|WGuatjPX2js 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

      LB2MfY9eNmOY~YEC)?0QNR;wS7R?>EHIw4u+Oi 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�^uICLU#gwc3D@qjG^ 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%0AM-bas-$0P*|5I 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�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

      nNo{&u9?$UDUSnec1QrSayi|1!t}NlV9TaoM zrkSRC3_joXs#VF0v;0q~upcv8Qjfh)JqsHj8tUQ1Q;aoLZGWm4##0@8;odLjGl=US zEP|LA(hPUh%P)J*swb?oHw4vE?IK~Cg!Uz5D}jFm>KwG=PQkx!S%U zc1Xna3R13VuvT*1lBgfWq7Y|A*fN5ASF_p&mxgo)oigBs@3)6ltZG zE6|A&;j(DC!(?!x1<*Qn_E&gon}$lnrCOk?8-2c2E86Wbr7=T;(O!~hD(DJ9 zG6nQuSwBq+5}ZAkj+SD#Divz~+?Jkx%+4;Q^I{TEx)GzYTZ)#tOq-aCpdbpnJ>*>(oNugY=~od-KZoFy>J(UDvt;rO6J-qNr%X!s zt2v;zjVF2QO7TjMGX(jr{($AE7>-6X6GDbWleu`yqg*pm>2s+vcodIqYOLajvTn)G zf)}knb-L;e3CJj~Mg~tiSwlqL=AAe1JG~|F43tVFDGn@iRGDrtLo_ttWMzx()^!PM z3{(6F;=hNWg{o{NeNB~8YqB#L1<5T^;$x1D^Bad4gt33EIUwENmSw(;RdB_lNM&_MSNRrQpn?tE)fPd>(# z$MAl8WiAq~O2sIpm8iTZmW@f|m*iDLeS2KfS;K=%Jx)Y^CnT_f=7|Z#SG6>~YdN&& z7JE?6Fa)a@9~Xc9eoV~{sp0=ZBpHggn1CLW4=0Ih>h-odq(glOIcKtc-1RDyMhTFmc(B(8GH#2YJ!dLCY z=pl+HQ!f2o)%?|y&3v)9sWRW3Qm`RQEX5@z{+G~yZyh6UyO$wDZVUhb07lV1(Zy6q zqpnQKM*cUqs&}ZCE_%w)&;k__yLz&P7Ct9gHSXy`16qE&fV{F>o!hsNQY;^fCbS2? z`>iJ|*90n6d>bS(PwPAf?N6RLQ&1TTV)xsNMxo&%j~%*M)EFKe{?!Lxc%wu?Teo)F zg@>*}1An4Y4hQfQmX0tLs}6DBfzI1MIif-XGLzmLnG=;<7JYW}i4n$-ej zKWTvZxu;aUqvUv^Pdncn7CBL`0~G0##3Ny)l=d?hO1iRq5NYd=D_>jNZAUDYjk|89 zSFQvvpU&RA?4u+92k#mZJN zhHeQ>rPNucMN40EeRkYcI=~KbBVV zJnwvagG_tf=C|8?8kRy$D!Zu?j{b~(_5Rp`sRuNaKtgjD)C^$&00tJzazjsE*6hdU z@RV`EDWX_;A$0JI;X)Phi@5!=V7dktm~268E;rC~Y1({Lg+@6NK3{PcLoN@)ol`$L zhzK1CKYMab{9T=i`C`4=w(mlw_xQ1w^2m=`b$ob01c?0NdYX?qA(FVpN1X zD#Cc5t6a>{sM3I9xsM`|Im{d8U-zA$wnKwBq5|+w!#s}kp&j3fR9nYO#`mntK?OxL zK{7ZpGKRmB=VF-G+dhb~zWPk~otZfS=A=S{QzTbT-pDABAX=(7NzAZoH z*K%0FrnlYn2Lb>9{ms^dSoa0u&DQe6kuZ~P;;9`?J=4a`GH$(kkHHDsN>{CsM9oO9 zRgq&Y8Vegy9fYX5JjwM~hVNq0{6j7fp{}yZ)ln`GdYnc;c)+l9ng#Ot2E#%$1iT*R zO1zM&?dt)4oNliO!1pevW|^{(93S_ME8}6F+NI~MTk)mN4IC}V?fsaH6UwI}^>v&0 ze^ejf8?DCGkI5m)GtVNz0~0{?Qc!t@XB7*#rSKr;5<38%v$ldW5?md%l`FN;6h;E$vPkECq|6Xa)m<;ib55J&Je8JGv;2R9M2DV0oY^={0k(o2|w_Z}ZI zGbES1qnVz{_*21Pm;GDHtnR~e(!s@QQ~2Ey+4VWj#y*JV=|=sq#C!>#<1b;cDt0!OyxPDifzvJ z?A{-2bEd&g+bTbZVH0ist#iF#n&YUw^illm6_5GA`u(rlVhMr$7$UE{28Y0s+e?qT z8421bF=ITHt3SoBpf}-s{$fm+vRJaTR3lfeslW1iQk|*8fEbHV?F% zfF84s#a|&CiO{71C5oBKGkmEOnvdM>vl<8iYJjkd$dXJpBs`i1O&wpI-`S+bmM{lo zQ4_l(jqWwEBlYqyKXw1t;y<`>n6_H>_)J>N`*!;|tvqcW{r;+^H zK3CH$?TLHy#94CY@MBH|g_$6><}~M*tzvprQHp9o9_9`qV*}bYq28&fs<2dGv;dN2 zix(O(4EZntpZQM@|D(JecVI!HwIHQfB23r z%TJgCAc;V`wxtpV`k5EZ#7f-$DQ4cP*x7e;D;vKTZ7*&jgyXGm!yhm%3?IOeWj|v$ zjgle5e{dt*G^MCjNh?#pir(6oIh0D`T{b{kKkws$vCczNoTnF=?6Otm!ga1fA74qx zz*4fU)M4C~nRA#1HV{?4$+AcL@Vkn&?O;_Fbj3J8kw+p~lp(wr9v4RE{ta+^5Q%94 zb~)pEaMk(dB#hlKUS&fSNJpb)^ml#hUxbt?^81`hiH`gSc%l7O7T`8%(;sG zv_*k@gH=zre~*42&T3OPJ$v8M@OKpakFI`;^#nAYhcO22%$|L4 z0vKBgD$npXWow}m9>g@~4@82ADvm6Zq>bNm6s?ZC#W`8hp+qUt8aDqj8KZ>Tue`!P z8Hqv!?ktgT#wvLp1x zvfq=_lw_N*2*91UZ!t0h0=UkibTVYRwl-HrW-!FAhZ^nEcB`*WAeg^c>bQKQ ze_Zt#zETqvC9KNuIkQTJ5PektGyk8zDM?3LO+b&y6=GP39EAsufda)$b*fSxp2EY!oO)3Pt8^$1%K2g31_N3*D+Y^g zRs*YT48sYxF?+*ZWM2sME!@^qu2b-{;(Y9CXtndI!HKZqk07a85y9oZ}g=B4KY!H@gFZX2muVVR=raBk< zD#}*M5fKd?6~;-6EfElJ#*ODh-Mc9mtho>5S5TE8+RKa& z$F4#Yi*1&)>rnB0>YQ<@=~%cCadyZ)$M%#%%&}VogJKUi=*tzydN7U$kXBD z%3C~D#x#-+(Nrfp&{c6;lnDa>kdp0d>|_g>?X{)1t_pt#Ao_^0*j^uu3_@2Li#d#l z1wP;;E~t}RrM}sTO&}K*S+o{?qs-W!Id?`>xZ6lAN{1{h|Qw_VtPO1^6` zAO5Q1PnTj_@HcjeSC6bmp!7)PNmSX?d zMb?d6QjDuJx4V~ZQ$ib@#G5Nm;jkS~7sV0Dn~53ZQ@;rECdQ|ibA~6L&{UQ2*}Yum z+naIJ)uqj|_-|71GO~Q1KQ-W_9|m}CjA($liUSGBz5)QO7p+xhv0I4a;g7$Zh& z>EYW_c6E;Y+vd@_{SOZO7aOXWl|otO>4|6rxDt4PlK{d-vd|^gZGg8%NjQ#UOXhX$ zQ)Vtm9U4RElElP`EHJW18v_lt!J{J9!$OfLJBTgwCE(`&Nb^kn7CY>`&HH;eYPpS6 zCr!%8;?4hIX7X9SW-_te2O_`fZ^b9#F3idUR;AG$s4FO4Z@bx1v_LO&jYxW^#H@G{ zqSsdEoTf^W#eWvCk7bX^e>+ZR|88E*@x`!vA~Ay{{a@!&WO*h*E$gVYS1+M`II!Sn z9H6)b=F8`QF1IyA;htsVBngKAwD$LU&1joly4tTcVp?tD3e;u z|7UvcKSwUzS^;`YwjYO1q%1<61t~0MD(Rl55^J&W8^mb9rofU6Jlb4uT6X58mWi9J zaKhu7-N+w=v~|Ds=bR4l> zDm~kZ;?+}RjvXLja;4q)8oGekfrF_%m`nwwYnqd-$#`KO3fk#?!Ol-SEb)bAX5vks zKywAUxlMN{gSCEnQsIu=oeBPXd?~CGDi!<-003Z=>l!(uq$~9A-7U~F{Y4|F&TN{O z?_vGCvi17Qe-&MtLi^|CcmK9OoQ2$y{K}eavSL~8F4>=FOP((h&jO0i5ut4V#W9RVW5Xxi7Ic*CmEI@7lnADL{Ewzzb6k+B(XbC43*#k zC@-^*kES)RhcjVbrs8vW>T6qe=9&c3rDjt49u(tGKIBW9%@fPAf~sXBo;&fw%kU2g zz4)8j?Xiego3Brm)r`y3vKc-r1XdaZ)?99s$O1ZLqP?^RK%tsmr+oI?7Gp`DFF=br z)Mcg1qWmCk*K+OebmCJ!VLl#@SEYNQ&o5U8Gn@YwA&>JNox8k_jkDX!>bfPP$7`9- zIqDcLYd{JB>Bf6q3jCB*OmpyR$|T^IMMGiY5q{7SOiMa?@!dbyUn5%4xL1-}QHkc$ zu3XnZQ)!nyKtv|KnO%2T%eec8bEdT7Bts0tC>*w1n>;P3z*Y{(v#-p>MT0I8M^cyP zMiggv?8KO74Aum!NA)@;NeN)G34!pMfs~+!BeX!%FuJ{=;hpCJ$PAF-zqf5#pbBSf z+`6$>M9RX0H9(_6wv!U~eaRM@mistoyaaWrR_4UA3~{GeYtFq+&FK7G-6Bb?D#zKx zM=o^8ua|LDAgtXZYBKk~ycj!W=Y6rj0h^KG!xoUa{tkW0zQws_Hn^65a-6a0fmVrk z!Ac{HfoF^Pk8g8U=2Yf&bCdZCtD+1|L45n`4NcF;FswX>l}50cVP8d^JO&wa)de;kfCa}r-{EE9*3 zVG+>&g&dywRnFWPyjUTAaEiG8o0@xTJ1TKW;_*AI2$ILLtrYJ+o3?q1N*k5|004ki z+s1b4gDL_Nai}_%dI83$j!h8c-h!OE+N8mH8_r$aol^Q(oA0rsXpBB|p>#^KFXRhT z{plIyT4G(&m~#rJy~Sp!nnXh}?eP#N#P*FjlkkV^QfrX(50l|gbW$XA1r+YY(x9k& zrSVI~(Sc+GRM2z!$;#`EKi1+-eZww(i4y9^Vai$Y5X+Edb*K%vWy~E7qgV6{~upp z*%b#AWZAew;}$x&JB>?lw{Bb$+}$m>ySuvwcL)xRyF+jZBsc*=*bg&%&d$#4{)am6 z*1J~jMhudxci7*WCICPnbf>LL-{|Aa65AsSA04bB5d+mY>&9k7@J7yEgzDirw_dq% zGXFQZL=&f33<732NgV=nMzV50-8IPiYT44cK56X)+Y}T z{5)AC$pV}2-VTDF70d$*>+ZdMP}( zAnN@1k-z+04te3Xzo`sgR`i^eR`xwKe+ZC*HeNpeX|Rz-I%=%BEQIvV8kSYAY0G0q zRE?lf`pP_oW+$=8lfBGQhzRrcF1|R6#$PmBFy!zh;JQBSLup-3K307wRT_4T3kBsi zugm3mxvu}Mz8uVr#AWpX*>CH9v(ezE&WD9Rj~-zF006*1 zTi;+n%*u5l#K3%_fdg+2VsMg=JF_YiU@po!LL1FF-7ZH~#)>FIO*B(l4zl>pCTVMb zBOpopN}WfOt?DSWSK*5K*|;WZ;j6(MZgiiiqEuChj_euGC@8pt%S6Uf*QQ9o(8%10 z`SYC6u3X{bJ1qz6w9Q8e(Jf#FE)ox*5$2$>Ji;kFe|#$AOOK7MEb*Ts=VdkZe8N7F zg2m({N}q+xRm^ol;zupSL&tcZ;7qEC;6|BN-!8kkM-zY6SSn(FrNL6#KZ@6GzBRFR zPAyG_M0HToV>DM-+pB3MIPRE2PU8XgH6^OuI09WExC+giXV5`Be;V!=fs_Dv0M*XGyG8M2SL47ia&gxfZvfPGip8fhg~WJd-CIwjGXiI-VFb% zc?N;$e)3S$Z_R<*z}I3&t*HPHYF-`0Khbb8?`vJV00832=6Z^NAqU$!z1!v$bFBDg z-pVE+Wj@w$#7xxI!o~4bC)b1pWHCiVrxsTwPvxVe_|=W~b!Jvdgl|EPmTP77OSd zxXyXi`0?&+FD$$>Q&Q*I<|$O}qMI5;OC(xkUr)@5Rt}$gp5vSpW*ES#+*Te$(BlvF zu_JY3<(iJ;LcVXayX5`{+s(D2al>xR_9w@c;k- z08q}-)IqbL@{Ok9BELquk<7v>Jd|z0ri2I&$ygcL=OX@(@n)umF3^4w83I0P+9-)z zw^-)j`&7+X%B}Gy5JD_6P3DnjUQRp(mMC03HxS)gNPfT44#LZs9x$L^^kb9p@K&61 zz>Bw_ONvS<&b`>ugA_D*NplN-h-lK4SCFiCs@XV(lB{@-aJHKEkpj#R=ysaVK`{n# zH)C9H?awOOQI8R2%?viV2gg~nR6?#6N3i%J0=ppW?)m)0;f~!U*0mtO z>=RE_oFW$#9+@_TTm#jW?pRUO^;zFJ zq1YxP!6I+k!=+#~bl-mBhzT3hIwt>!EELmu>XVC$%+K*0iu%iDuS+|#TBK8) z1`xc^N&tSRmoP;k_>btrxBoafJ!NwO(v7Ys4d5JJ#fK|qs4QECL0c`r_c?lmK@fC) zx@P{gErcpxuZjU={J7;2q}Uln+;@$ims-YU|*d}r|Hl|a?n!dI&5HWGJN}$o+~dI?s1_msTO)0 zOB|a7X)Uv_mzBqRciBXhCh^Ot+^GO0l;`LD_7dE9pXneVP$}@;T2~DnKazWZM1oA~ zg4CVFhg*TJE?JOe;=6+=Dh!iLm&0XKp%?P5yBq{nBQ{#_K3hZc<{$Y?2_ zfoR)VzN(DSH~jnGen%seL;wi`%Tk0Nr@yAKwpl_qmqk3 zO?&wKE3$f`pNyQ_x@Bo6xGqfDKl9u^{XpIhoRWaJ&HLMcopadWMPK(PD9MVlY|tWGc63LvcjD7 z?^dqrf_gk^O5MMEHesa&W@JNCw?vYtHYlrx^%mTYGwg<=wom(ltkEY=^_8Dq%&M&R zGS(wT+KtJxkI!%G>H`}F((ym}dv5ShzcInyHi|Z96t-z>q@toUc~F-^rn25SY96rp^&NH}MUXWDL1}b362O@7+KlSGKotuq9L zFG?H$X{f1^v#4b-tun-eadXL;l0<4^!-AHpo}o%-x;bVJX(}6WJ@*BM``Je!wLlGQ z#^Jr~@ys2vER7x-G?~00PB^H;*pdKdFgoLU@sBzsWpa~Udcnc;sXsf)c;TiWe(8VO z2&Ql73A}Nin{;4KPFjGarpnT&%thD>{6w^lr}EXKNmPaih{PVkc4jhFx(G5ZCoQ`Q zFsla=I~3f=`0bJ{A$~Wz15Qp;U+?sOGxdwv+dE|hy!9;e*~w0Z^m(2T1w5tTqt2mr|j zt=HiAc8K~ndSeIEfq=?y7lCWNDhV^T>Vb=AO>;-Q?8q{^i-5(E>Kq7fpb0@RmlFhx2ur5jJ^5rt;Plk`?V-$sO=RuUA5JuZL3{0S4CLEf? z;JLH?SY-l%d@v;vX?BTF{%~=oPv-7kFP1 z6MemExReOk1WYixvR;DkODY@y06;gOb(+b=A(4&6X8tV1gxO9cyM|lG2txQ2@_H&v zH)XDB1kLeBBujG%8=VDx!fl?!!}uj*$YYRL>P>m<^+Ky2-EP&Q~+I9WSQeW)xT*xx=U{91t+HkVY=r>I0q zKoFd8!y@nZPoLXNMdVgRHR)3Ow8!2BoC_qe9Li`;s|RK@|5Z}w`^j)CEKb81`r?UF zO!T&5)4l=DU8ZWZ0&BU`7`4GXqOANf;~roU~zTN zDk4J-P>TgBhB7Z|`R;P?9fk!7C;k@zxXooGX+HF@%2eusJ->VSa%Oi(RW`OYgjDI( zt|5vydnrw9g99?EMw#DI?9A1In>o4>+5O@|0WsiiP2t4c{HWxgEj|m~^m-MwXu67x zF+6}Sghdf++9Ko9eDco{Zz33*&NkX-E*MSECiP!E=EWEpqPp3uLi*uS)d8^(>xMz zyTN)UE?zn^mx9U_T7|K#TFN0&6)yADH2HlQFO^R85~>zOzSfr|Q#1|N=h?kgEwwzj zrVmTGH96GWf0(PB~rR8ck(l?k_bxG2$5GJ$*m@BpL^a&~DusSMLk`3hMW zCvG!(coEh=CX(uVh7^YK{r2x=8JDCq*8E!VBUU~u&vV$R{!BFcIQG(_M4i5X*T8K$ z6+#z~aO9k(KGO7cRzZ|YK)18%#B8ze4?|pnIm9`cd&F3deudSt5kK(ix zLHIcn5MO{|Bq$pd(4ms6^@6*2L25i;`#&A#MeP{RX%l#TV$>9+Ec?G7JK9`5s^?xhmh)_I*tJmW73 z;v`&(SK365u2Va&vX@f9Vir9_xmI2g5^+Su^$KdnQkZFIgiA;eDu6T2Wo%963fnDM zP$+9Y10j{3*9Y&FX`dXo(Iia>Bwf}PIz44uBjeA(O5S6jC5^K*Ns4@wB(NAg)}NYP zX|L@HHa{#|bvyu0s%H5RkY6iYv6<3ndRn06!hT&*=sHJOmZ2V~6ubPU;}As-J@ zss$GHZLW9B8bqr}Rq&=rSUcx)cQcluceFJC8k-CPdeF|*~ur}d@B9}?{5jv1EUrKL1Z2V z=G1!s3PWxC=lBGB%Kx^@MOi7@oPc174K{3?!>bxp#S9f9ixNtsV=&Fsd>$uAvRt?ei% z3VG?ly$#zuQ>-xwRYpan$~&7Zltu9033)y!mt2^z?l%yN35+7hLS{skFkUpC=X-ND zY~?;7ST{E#EmtTrUp3n=>Sp$tfPdIT#_%XAM+iQ-Ar?ve8e<}T(UBa)p(ZIM`0-^N z56a=ISCyB(>SOp-y{4`GsYRq*N8wNJQMd0y&z`GT|JRxPmVvt2*SC(b!VZs|MuTR} z^^@ewS`ISaMWb9lQ42C3E7^%bASxpAwgaOIaXLv;?D!u~6zQAxXHECx^<+RItIVwc z)TI04$_di|n>%V=*Mp;RFNYr%413fk&;B-{5LxiSaO~4%DhcH$qlNF5IVqYNQnYmV z7+x%wTo!}Kj(N5&GSkGlx`Do<%;m@4dfP?aDyd6_cXu78cK5L&Qr}E92r87$`N8(u z8-x+T5<&k#1^@4n^H8ukqgYH-on#ZSn1)Im(nOYdnM(XeBMA^74;Pf1p@3MY*fpHB zQhW}=ALocBCqF1&_YvckmCJp?nET--W`7{wx7<6}Y?4@Xn~YcV3Ysi;(7}j1Zm>Sq zE_O|z&&t*-olPCrqi*=>FN6V-8LM;F{duWOtwo2agD=M&`D;zAKO%hi_LtM!^uH@x zAvEM~YLeGxRKwqBILyVUl9`Beh`x+mQ~Irw1OWhuxhdn}io-lwgxY=t@r6hRY~>-v zzr?t~YlG`eJ(Uk@-_}5lG|g)c1(YF*N|Na4`+LZUVf}37tJ9=1@aHxar z!15Sbb6w3W#V$j_AMg?1J|GK!A1vajSUfRzi2-g*Kka5*+H@Fc*G&4bdf8!8OQwzB zi*$81YZXo_FY#ch3QLXxfB-7PnqKEBob-PxC*XaFd@cSlmEK}*(v{awvONJFb+UtS z20giyJG#Hi1rFC7rVKduHm^9_=yqvG>aR^?h(TWsONnmU?9A8n33gS+2cRvZTfC`N zO^_L+BfV2R7P__OhPpl)EK4pS!8tdK#f#&+D@Refuv4NH0%{}=9I~$kE&kiV#oOF{ zb;|OnmC;B583nr(4w{8O`N^Y8L>er|xxIrCE`KeE9x5A>h?+^ab7&E&VnUzUF84Xi ze|$f@ZFg?tS#UI_{-k8iH>WIaVXpEa7$yW^-PQlAsq4RV`t_GZ)>TCdQ3`pR9#YOT za(y!mUlBxGmh)#19LX3LN&za*!8vwYBHz-8|D2~9vi3}EYxS-!7$J@iAT126A}UcRN)1Ne&n z>tVkq;rw0PSiPzwv#uQ)g~{ud08c=$zX$gxn-6AQtVWA zleJ?}O$l0-)WtNLp6<|8O)WnP?ueXzJ(K*IwyBi7I{s>OLiHA~+I5r7eKp{BdUw~- zZpQa?LvDJ&qY_pzb(pO9KJREWq4x&^E+$4C0DyPgF*|S5K=7aS2wg6pcrM6ta_#j` zP7|HNiLWw}i|IS(sI;|^<*%DVvjcnIv2Wl0*$OT@mb*24ouJ9t9Mj-J2cG z5tc!s<(jFbiYH)i(Nfm|N{Qb=+?kW~C7g9=t!^XHR)mh$Qj?m)22QL4y~G5&3FDkO zZ4mv4+*hVvdDZR>4b=gZ*a*#=D-*6V1&C&~yc^tBr$3s}k3*UIoc65B z>^AXM|A`!PExBjAu8R9P$D<-wx1R*e*yrB6pmL_OR#N&jFgD20Yn`fuFX(LxPLZdd zNk>nhqf((4MR5JxnTQwGnBrso_cGaTY`C{i`|qeAExx8HDp@M=PuybTma~UPuBV3( z5Rh{mPjO*gozYuKdRHca@>yaR?>Gd8Nr99=uMb<>J{uQA%5slQI(q-}H|!^{&6@1P z1)84nrM85Z==k%6dP9!z`e5wpVx6i$b5o|DG8ApJQB@1AnkuB>;gH1HV}>TrpjCT$ z&Fs0}K9M65a(5>(@p{VJ^wees3XhcWq)fNg9W08kw!;(W!|=Wd`ftGMVy$R%0uoC7 zCCDL4QwBXQWT`CkD&Yo~gNJdLJ_Knf5o|{j4A2M)*uvZt^0hHma(Vd~cG$1$wSLRq z04GY)huhAEobNxY+imn%(bAC7q|K;I%WZE%hE3x`7%9hS_A0D|2Qe zi9xjX(Qs8e#ob*YXl7I)lVj{`Q_EBPLr>in|JME{R=B#)?*w%F)V9D|4F+|ub@V9j z#%m}2)Vc^m1pwdx%zCWOkf>$$rmRCgRauM&6G5)`O{{06op4P!TnP`j5r|_T^XL?exDJT!H`FyOdy~_F$*8i$>`XG~-LoULbEQYQ zL)fDs1U{)jSk!8))e0pf?+zZo=@K6&pQp^DV^>hm?=VgKN~=e4p2IwmCw;C^^DW!> zUjuat_3B4Vw#oyyOBX3zC~J-2*|dKN&zt)lcR3!B;qiQGcYzcdlp5)Bjx$Fip;0Tt7FTJW0WP$wkLfK8v=0H1CfX8NAYq*fgoa_#9b|s|H`Z9+_u}VnSVZS)XG!O&CnQB zn^1kCSgv`X*OZ%>hE3`6)>q4JYXJOVM#ns4vz}0^$NV>2<#5LJntjHvEb_`sQS>bc zZ^G75ybc;s<3LpTzVV0BW_Az~lcvQ76f=>S%aHM`24~4ELaX0s?mZ@h zDVd7DzODcN^e*XspYf&>ip}Ip8#a;Q259;zU1X7usW{Kk-#hF+adFn5F;Gt7x32gz zc$rQ`xu5>CExV~2=4O2Uijp)eL>*#XeAhQt8?OxGQ9!bP+Uu#hzeXmLs6ZM?i+3>G&%@YbW45RNd1Q0W$rwqM(1PCsn1x1QfNT0K8S z!W2CQ`~?L94q3SH_NwHU!wHUfz z1JcC70TNw$lTOJqEdv$YpJGWRw@n3-x`>%HH-+v@`S*hg=UcJkJ^>k=D%YmHHvEuv zCMI;uCl24lOC0vC?gOtJSwcx^034J%r3ND4+BWW%otjJcRz0@yOOR>}%dHPi*TSK_ zdKEtz7hxXm`0s7#X5WWBZ~YkKH1iakNG@WUZhhJ$?>uS=yh+Tc%KgNw_XlG~!-_ez zaJhtWcn*14z0bvj#K^Ec4BqLFC?fHS{Nph{{@OIn8E!&bTl`j{gs>c=ggV|MZdQX2 zy$5a3nNP(36IcVSm3$&V@(DAfMqD(tcnYNq6(k-P3SbNH9gYPG0G|s!!ZJm6gBk%+ zgT`ifTVE}vvt}Oix-?)zhy#au=G+5oLeKM~5IAZrArtR$xFX8TYC9Y|* zott}_j&&7O`;1#+3X21Z%U}w>5GWyx@*8&1io>C87^xrz=hPOfs>a&${Ige9D{6)k1u8Aa)Co z(>G;_Y$k}My^#)OG5L-dq)SL{U-IJuMB4g8D(vi8_sEI!V11%a`3Y~>1UPDwD!I-} z%?L6=h>|6OVz>`?Ge?)r>(wi^n=|cTv0j;DhMn)3H_MHv8I`FG44CD&#;kB`^=D!cW?K^u6Yx?uI=r*mJ(`@{UF*K2?lUy>cCTwtuAAa+7gEt}L*{X&%N5MARJPALc}4n789%A;8=dD^n%{y~ znrzych-j*$El%8``rYVwY>ov_a|_%)%wTb#7S&63Qen+_am9VD|MRo4%MtM3)d#30 z?D>RZB60dzjdQpW>X1)YndPHsDME8}hhu^WfCmC1%9C4jlP@Ysd{xff9*}CiUzH#_ zz25os#1_;N)v<0Hs%Zg5mX`DVVfqY}UrH0X)<=zMfm3~9WX1W!Y}F?l`e`8hi^wZ^ zZBv>yc@i863{u}#CT5mN1er=kY6!Alf%yjf)VJqBhIpvm7|;;)_Gb1?i= zaynhdMHb+ghX7#!0AeM%3kPEZHI+-~kb88v?DDU2YE58~yMn|Y1aiatr2N?*w{Y&! zmHTo;=|aI8p_e`Mgmk=rBKv;3PI6@>COn{CLiOZ%(lkyyWM~V8tvk^bulNLM30!GE z;u2~2l~|F0+^cCmYgA+7T+K3Qd+MFo1SFA|_U)?{#`nA)9<3b{Kf?rp3JY>NshGR4I zKsg*UI_vFp27hyxn5BIot)p|oZW0X+4f~nqT-Ev!$dXZ#pTMzw#=qaLQWf2$+f#q< zcsS;6Hv*GQsVLa3FO7f)@jpl~BG0%z61+l|$$GdC#;JmT44VGe+ExM=YnaUmg>Ui| zsfftv24rWPDl*F*M%P<*eTTsc1}IRb9LAR=e}NYA=3{L3&r?@ZzYX%572KziHK(*BMF!DL%(eAl)*Yq+{&Dhs0^(eed)9<3QVY1=-9Hmv2J=9{w zl-$NDV(t}gR!YM<6&?Cs1wlJ6@cD&&Esy*}TGyqR$oc9VimiG>J};u5M}L|<>c z%0qPvRH2`0 zPDWnx`zk+;Ho+%tr zF6NvoT+G=Usdr-Tt~$l_(ak>Rsx`ujraA2a-%#9oo>Ylop=;@U@?<4pfO~Wk2>1?2 ze7|G#q>3y#5JcTbCEOa5!|Ip_tQotf9iF^4LTuS6pWBAV&Nj7ci#cX6`=A+I63{vo z!uS=BtI72n1w_t9@W}I9kvTyY3}#wDCC{E2f=Y(lK1UMiN{P=Sa--^!6Pg%LxZG*o z@A+}~^G5RkEO2N*1w>Xz8pnm&uU!|OQ(8c128fMDvYKTCZ~{JVrnAMx`}vutFWRKD ztY;}VeaTxSN5iiiwaHj~9zw`d7@D!;>>stcm56bv#MZT1g;Fx16_?wYOdU{_u7*iN%B| z;vtpsIG<*@VZ4^D?Yc`9^grx!1c0db*Jebxps)tFNt+W8G!<)-LS(oBT7OCtnbl>g z(q2||hm#K%cI76YCEGk^JQ!HQ;^TwFdq1X9gty()y^DFMFj%nXeA{;@XKeA(aMD&H zm90>HLv=nOD$PKhl$PV0{n`q-<^lt;VN-w!YR8AH`)j6{C zOvJ(jxp)nRE9p}(3kMHMEsj8+B)urx8Ga|WS9@mV+1H2^@R>luSE#3r3>czqpMJI9 zWsy8|I(r#dvSDLP$Pr~8f#YjZ^SvTCe6lZ`31OmcE0XEQAPG08Isky!3PYnh3D0ZH zQ%2AKGo{H-&dXbj9hp`!E#ze-Me7hC8fMQe=0ovO%yW(4)|*#>k9q2;;gT%99>p-r z?@yKIVwB8F3cB_f<&Hrc_pw!R*%&o+gF%-F9vs<#eSsp?=t;yCC6WRkzx% zg}zleMTW)m#q6cJzmX+3ccK!AwybzQHK{_lI)?hA`2?VIQF;fdUAt_gM*H} zajA;dYExNe;Frp{rFXu;HTX#@i3&wH>(S1oFt|iSx&B1D}j%p8GWE0=fq)&u%e`lTjxhFP& z+H&t?_gCmm05uBEfTiS!%f0bh@hvYu2Ls3nmxQD$zoXI)e}#`?>(FJ;Zib*4 zp1PaBdDXIhib1G0VH_F;i37LDrgA0K$f_!uGV>~a&T!yYt6k5j-CHoMcJS%)7peDR zO&)AY`fgLDKw&Kt^ft}kYYw0VU?jI^q$D8c=L;AGDj@o~KR451b}fj%B$u|)xU9V< zot6FMbzr5jH#b#{LEt--FMwR8*XWe%15(1>rABvle*wd&GIy>Y8BxPaKh$_e$UmC% zzT2}QdO~&sp2? zt5i*=EA=uhuDT2SsbGkXqaFsHc85qB;Ow|bADcS#5^KNd^(rgG3XYi&2J@{cWYcIVhv02?92S8Hi|d2^pPELBL8Mfo z-Fo-8o!?@TkOk?c`dn1vAlZ(tbcPVqsY7imfB4eW{Ln>N_ZZc7L5#2C8Me*)Lg9yp z8z_u57LMn#m!lB15(o`I>xP>0j#wu3Ail^9H*Nl?Zf(aC$$w6O!n7U3J5l;&=I;&ABHJe!ESk z{xBm}o!YaSQRa!?FwbYU_4)c5Q}DCOvN5L1(^LK{gu3Za`Xco_yNtfAj6$w}F)L^f z+Ag9F007_}CKj_nhG}+BQq(kuAlNG%3pP~s-iY-3 z20R(Jq{4Jq)GMf(tiG`kZd_uEUf8Ul$Wok`XxJMy!!}=%Xr4Sa6xBj*7Qf}r0~9Z5 z_M|R`EnBjlrtm(m3Wa@s<2Jo}DD(KxOvcEv7AnZ{rt&Jr>|p>?;BQDjeYslQ#_mx_T98OsSpw zLeyrstw^B~)EXWn7?9K6Ld)v?x535^x?EZk&!Ujxv6(aE)2vc1ope*B#L@i6e8Q5( znAg6lr`kA%`8G*0*%a}V421F#nI@6^!KNI?5o#|#ErDjvEWD5}r#e|Sp&}&AJg3iF zU=yXdvpsa8t{LFP8MVdpNm$@tH{t;h0RS*eDr^&1fJy@uo@#o|iX?gL`DekMZf3zRt7i-6p+(bzAInc@Ox=@YRgzS{8$G8< zH#>JLv)&E)(BS`bQml3R4G!L#Kl#|K4GI^QwM~(J<@%c`T(wt;5(&x_}sXjHh{h0TgPXkGO_HZ~ESeDVgI@V-KGR zJXnH5nGe0$MoU`3_*6ByR zo-padw;}f_xgdgP97>o^Q5j{4r}Mp8N>-U45GoIGdeGIc+ZeLt0A#h<&X zf-jYMflOB{-`o%Y&;W=h9eR)u>PH51rS8QJ_4dl6)Kemqgn8tg`n1I-_O&v$xqjRR*FNN+oR z2Lceo;L%-1U}>$+CZD@Mv-H_CrHEC#J0_GM&R77kBTKAW#u$xIUwSKb2{q3L!Y&-|W?pn37q<5cS2Rwx6ZC*u3x(nI#JMQPv z-U2faGEoTOOX4MD>8jHqiK2<_*;4j=qiMGBq3BAa!Z(m|H|Nm0dqNTo=*E2A)XKg2 z@vDEA?fd)b`CpL|$v(M)qL|fSnlC?(RZMf_)4aL=2aY7udeYUM2zlFQ zs?5?lFch%>-zW4D1OwqZR+#toCjymE!i;eD9YS4-<$XG<9)ENwr&HJCB&TGW){Zmq zRwh;ZPd3PBJtN3}pl1qtYlJjtaHwtehUG+SEt#H;tGU#2cPKPX#Rz0G<#Tq+Z`4~s zluzw9c9b`X3S zA~?SQ005j5tpz_Ve*WqDg*VHIB<(ht&04lBpvv zpz~38JCQ{c;YP3mEigpr$*FF7U402mQWgbrW zCMRYz8?8GdF$|tZpm~`?E6(ZR57CjivVLOw|9V1q%A6gv1(X+s#y?mrA<&KKX`zPq zfa7cSw6yzW*Mzfo(t-*j#K-Y8x*c0zJ?PYQ&a!yf#W4Yr$*YTIOvy0MtrjDm@?oXW zzKwb_%+^oI8LL1p?$VtXl8F5y*9!^<1xeXMJh~2iy*4ybC;aJ@XkK)=4(6MPVjHcI zNIYpdRtF0*6N1Npu6y|#OQ#2-?b_vN0w`0-`{tsSUF%Y7#q@`$f69-%T_3_3)TYdC zpC&TgqtTR)EU7F*k_`OcQy-t70$nRqWS;*Iho+9@a27vh5>cW?#ufpIe4s(VfRub?a%!?Pqsh!OM!`_jXqncmKpn{qie1!OAmZ z7?nX~yCQUf=#5ah|COhSrCyldh;gDqs@|5Q+VbZPcBYuhC~f`L8#^~8KoS7gy=9ZB z5GuZ)ySz`MfvXhr@;B0*0yI9XU>~a>l5OO*{ZCBfbwEac$M&!hB)xOkW^dz>ELSga zW4(L0ndl8`A(aJI{mxD~V@&=?Rt2l&O;M?I5mChSfG@n+-yJUb=enIuniQi)#|HaX ztBSiMZGSGAjexWBt?EaVDK?ri*n^0{>?W=nR4F>=4&~U4rSi|DMMem@ z3nq&T*k^b_LT~@YKX+5%WO$cs#v4+#5l(_`M99`u-e7+JY@Kttoe&$?VIS*#eg1w| z@blqOG+{8Z0(GPo{*%PU`0wr5{c!Cj?$RK60MH`6^_m(Lt{nUiryeXvwq^J^<%^KI z7u%-3bRXg}s`I29?5X@ve3;h~5JuY-@4D1iJj4(_R@Ff2t#mMR@v{pgAgSyC?pjpH_ZLbah0En4m zVJoID7g4e*>(x92kIwbDwrn3?#gtm!lGE%r6}=rO-b(jFbBEpG%khvc5%JEL?z5wo zl0_xxyv>2#v>F!BX|Aav2K5_8B@$W0d)0`j6&#@CV09Ke8y-mv)heQ03c0S}mo|d} z1MQ{L_Y8jyZt6AGbTjGMi@<=g7M;;#$o3d78RgRaf?&{h%8e}dPU^I#86xv?iq z5hCjvYc{P)G@pZ`xDhPL8QLss4Ey}AesMct+y*XgEegBEmQYKJ)=@5nd*^W4Qg$Yb zNm4V|h6*Xi-TSJY^f z09)*rJ|`qub?VB0DLIEYoqmMI7XAx-5$hOAz2xifCt|l5oR+ETUmDR!HH40+gF!__dB(J`b8aFs7I657AUeLf4mcp zB+ki?O=N=AQ5B1R{1>~Nx3!|p37c=C1DXo$L@u7n6isE82aFPI@i!HRRRI1RfuJ_N zteb0L!nm}*l<%TTmQ}pLco!4nrxu^w^GR647fF3nB^4TuHj{D5*3MW*y}Btj3kf~c zsUf}WS$z8r#z^gvad#M!y#cO_a2n;G&?hC;MJ_}P`m{2M8r1DJhwg&SnP$z|gbvS^ z=p1NUidkW$Omez`u(5HaR~j|F3(u#Ao*rVc`uS3Qf*@1?@=<(6XV#$WABCY?E!2hB zZPk#zU`{1xu**PlFhQ3z3Sm6$T))(A^>dK^*;0Sul48l7PN#L0@(6HrT)%TNOmaxh zOe->>_~23MJcm+~%pi|5_?vD73>-shWB@Wv*K)FX6RZ$t^Svc5A& z?E3tTkd1+6XKE-UCc6OYh@fY79o_CBJTxUEN_P|zEkPC#p@7J{Ns>=^S>a}Q|2b~D z6ebcXxSc>^Y%=+gVT)N&SIw$+l4L(;DUde&zHgY3La;8K z78ReNy57A{LWMX%Yf?1`jZPPk6XYrP;H8@+yd3YZ?36qjs?lJo_kC6eId2PG1$97~ zEzKT@qUDM4pi2HJ;GXBazrUoPU_|~twRrJ3-s(1~zWqDscJ&sYmOn4mrd3ii(EI#Fqu9}vQ z;4#O>WG^FY9n+46II1roI}723O2fnBL$J`tWY>Q&lKj4^n5av>lE>A8(pGrQ$vJI* zghtO%5?aN1mNI#3sN6>04obk|asIf5!kajexQd-4)YEFrw2Gmw^Hz(RmmglreOe_r zg=ub%cvS*R&SJ6D4(xU0>l7zF&y@n*s8hvuiSOdYmN|qrhmm!7hG-jtHnx}lQJ%}= z3nJYO60z!QQ|-G10RUwg7ce>MEGRg0WS4^ixHBCti+fLu%Od$_BS9=%X|3{hh_`XW z^M%A`99F1LTTlW*z1-4|3GlsP;h_C7D$B0H&}|08T__1%6$(JkXNzN@-{E9)X{-K_ zO~oV`pus_xy&a085WA}GA$>PZ9WXd3afCaEH`y3pnR7h7-r7X|dL?T$EfNO!}~-7U?~4bsvfAl=;! zGjw-@NH;1&H$%77&>*RR!uer;&)H}1_x&H%=UUHaJ=c9N{)4t#obI5EJPZ(JbOi|x zlgwbq`=h`T3qr%NE4`zl(KmCvd>p3)ZzdKgz23A=%0k4IcfuY{r{mNl?T)RJhR7Nj z;+v0i?kPtM5A6!Qm?xSE`pU zE}X8>e^;l)O;9F?iN9S76}Ez>zqdph;Sbq4Cb^rNB4HhaNzqv+E3fDK&0_Vtax4S#PaUzADMTT`gl%IQnz8*yd|t5D4-z+Fg=&G-cjk-l zjcnrTu%~*{Ul5?!jkD~x| z7q?N~E`oLMr)^oiU-)5?*`xOA8F(8asfD?v1Ho2HjU<)PE@+GuCpTzqC> zOfX||nd;2Z!x7{l(e<6x6)By)ak@yUfbP!lEE64a8Yv?6_r!(6tW=7p#CGw&;<6QNy8-ym zef5TJ0>fyEtI-Q}L!M~_k3CXAdOIPmIg>SgEo)9Y69g4mWsF-rh6!2A`k&dfbKuCL z{hItZX-;}M0Z;W{NtLVb3TArt7`_bm0JX5?J#2bz*L`ub2 zGQ1jGb=qx+tAO=e-lo_^%(QWO=?w0W{Nxy71mAy&_mIeT@$Jq_o_a&Tr4AE<$ zsJzE6%ajDvZE38~xW7!AXoc#g(-}n_i=tIwWw2$eX-=b`i>7;(-M<(8hYXBcO`krU z3bY=6Qux&Q$&~)r2y=~#)!JsiD8Y6u5jQUTyB?TJr?tv2r`bQ_Q1I|%sA=u%?90El z*AME}M3c1AVT+fZ6Fz!54n=faHpdQP>8kgjOt?4L~vRCH>>?yU` z3f#Wq&;IL%_&mZg;p0W&BZ#G-7Dv1%Lm z<*yEEAw0H_-V`^wI9{Hd+K?Fo5 zB2{xYttXzGEJZp6Lxf+~bC5QqXFg-#kOiaxKIqSh93aJ^kua*Wu*HxHCyZyzM|Up*zrLy)o#} z$fcQOMW`8T!s;Rrq47GOTrd^Os>Dyojt0Pfvn}={l2rKXq$CUgzy)Yt1+f5NEPkDq zgSF!fy4}cFkK>f`t&Uu9S6>PF;F#j2ro;FaOQ3;Y#aoSU+1%#~HW7_K+lB@L;@FKB zgG`!=-x1gmh{SW42AdHUFjaZoE&f8^1s+$q{JmN6Ur&cIWB)FOXWXjpOtPD0wDx|r zTS3j$jykcmb+8Lxzias7nmUd5@xj8+vI^s)@jzv1-2`IsNn&bwa-=3>(|g%!g<^$) zE@o^XL|8GF3Y)!f*pTfcokpRR`Knkmp_y0s)p;(xOi zt#9CwFSK^Gr+a2Xkpx=h?F#z0*Q=eX1G~;CpMC#sUA;odGw1`eE6)P_iM4K>Y^oHo ze@S7f9l zb3B8`=s8pZwzkDzgUS3%H!c~!<2Gz)gQ%SxhbP#o$5gI!VuD)m5yJh2NeUaa2t9Y( zZ~hAI&Di+!xtLi)kPmQPtf?L@>mIxZ-7;^w~?*$JnugBr<#aq zxBriBJh(sJ5Zt2wsKq5$OQ{J^^iF5`?8M^2vMCY|mz=A)cIHlw}@FBpAu zd6s@x#MHBIMN;c5!@ub^@L2$2wh3u?UZ1K8qj^wuos0I=mlM`ve!hk;`!O9zt~N(o z=T$280avv3JctZg<+Y_S_cD(qOUQ+?DssvuUnXsCTJcL+nn~OIsM(K9HH0#|S9$Ze z$x48f*@hSu)^V(a{MZO7+bo7iFE2+{|A*ZbRwBrJjyq*U_XjEf007umK>oO?k{oUC z&Dg_~>V~oyje~6jvXl~&^%r2Dd^6#I@6jmEgOQ;&LNG-rajz=PTam6>KH5eaG)>~P zif^rN)$rVr-L>4$TV;X`+n{Xk&kb;%Z!z9h$zHfysP{1EH?VH`CjW`f`S3x}WXd0! z(UX*6HDNi-3k2I2egJvvIHf42D)Hk*Y5o+~aM#MTTh`5FVuyQ%1u~7h z2-0&bovu=(j8{qB`(`##Pt2llLYG=B0H7etVCcqu+@CpHf+LybpuqaBCp+<07BkO6 zVk{niNMPAm`s6dGh?rCYi5*DfADzrNK`;X{6*ju^lI42Le4GDfZVYufVXkOCy&~1_ zQic-{G36qJ$@eRi&3u?U zd&L6(!Vz_nk7tOjEp)FY@!`Lof`Q47DvqgCVzKIEp**l&eBN^A>KuQkkNh@$uy?$s z`17)@0*)0HG!gD<5>1APdNZP168VsE*ur?yEV!{VVJeg`X`ZK3-L5w{kZ*a`L}#Uy ze1JVa!{I3v`KNR{rSBL1J#_%B+s_=@F0un1f(1KeD-e2lb9dK_4a#9Wzg7WG>GdSB z9K?GP9KBFw7fMV%rm|l0G+4iNiynRWW^yj>1qY$6P`MAyJ_+2zW+M9OH4wZ}# z9soCMAqx&}*0M2>X*(|f&2shfw|`~vGkg8&nY4A*lHqd7 z`sp4h1Po5lxz0pYoLa%{q7L-!{TjFk=O=)@5lN{NkF=}?1A9mGzxUV{%g^pf&C;i1wl4iz55LkaMAI6{)|IVw=s~EzZ4EvyEate{x5fJT6i^ zHTJZN5jmctd<*f|A+sxXDiP9xWbmckEHyvx)3`04_1JL+Wtro586+D`7N>AkQR4h% zklX0tev5;gjbq%O@>Dujrq2o~d70XFCT9D$REcV%hDXgb(h-H_({ zN9QTG%Xn_xn`PGLss`ONSAS~vM|q~D^RQ+}LS5(AERrdQbM7^%Dn=?w`%=w%leM2lwpO}wr1 z!3zpMC1;O(6Gv|UY3IUs!`bZf&va?@uVU_9#vlek8xhG=)`v!waw~Atf}=)%X$>BL zAR@*oXE8=~u?6qSd>)$#NjV@tO~ufNrKNZ|bHJ3<+-!p9dWL8^yULf26uptR@aQO% zba-1z#WEPe%<61*F=t+$d4kqbP>Ku9P%(3^bXEC=F*V>n$fa3vzpGHMrjj>Pq%o&{%tzk=nOD0zT@qe2n zu@2)W2&&UeE@ep`+uzzt<)GLcUndEPiZ&Qd7v&pmB(Z%LBI^sAKhf3yB1a2NE*eJQ zoyJA30ofgdz)yQ`-JGd4Y=+Rt6j9Nx;BgCD72L$7S_K~V#lxSfOf!inB>rp!*LgVP zwv7yKC+}DxTG7OKYMA@BtaMw!QhT@C0u*+XhFDAexMiYs3y0h{FEGk|LuXJFhHBF99Ek4cdv<^K?Sw`E2E@F&> z0n;9hHJl5Z{VlbdoTzFP-9;XYik|0I7%@`Zx`03aeT&ZTx;hmut04s~OX835L)-nI z0~;xac#`r|2O*9|NLtuSo3)qj{H$k0ElCeq^jU%15bByzE;@xIFXD!;R)+dtCuD^v zb15a~J+z{S$Q8&{np0dm`v%9mg3E2%H6}B?8S_{mPqAjfqCnDH3+5UR1=Y`zBp-_p zNDi^a`WGHf>x$+=LAu06&sGT<9Izb>2Z7~?>BwCeYFc4% z!}}<6BaO#rA@hla7WfVfh{S}(7%k_gN3wYqDE08GQHVA9hA>ZW9)*x1BsNVycOGs&ghorW3ip2`nha4-T4^w+tGBxWY7{v zk=#CAiX;hu>p$ecNZ}h&ga+Z zn#H&O+1m2zjDSq%Q;JwXK&rBf>fn_}w<7yv3pD7q!SViGg6-(SkI-PjcUYO~Z}8%% z9DnnkDauWn8|^9)G-|h{Z6;e%r*I;& z`uTmDInieDggEsyX`6Sag&K{gJg^cw@Qf!TfO_Gd7??9o%G`g&Qh?f)%KG?p^W!!b z@fo6d@ptE^VYYqavD8Hn#KJ;zYNt5c>-+v&F55@PjmrI(}vIWAk|TyqSBR`tP&E9W9 zXL6#pJm;@_t15++m>Z(SQksIdjhM7E6%EeT9h77FUzot~Vd1X!W;v7?o{J1z09qKP znJR8X08v1$zw>G#M(kgW7d0Hb?!v~=TCkr{+Ol=6Oi$iO^xJ#YwO`rUbe*$*m;yXx zouObCS>U{*3nTa{2*R-}pJQ~cjj}b$&7T{CT>ox^M!-J_+)?^TTWBezj@rCpWJRLf zWAgOT+~2+#;kNrZ(~|?@MEdo;+g<@ZA?$vAH@xNP^0GWiY7 z0q+mUEBtRc6Mx(HK^<;u9qW6;8IAo6VTZKaw9lye>)hxhe8YApQS!xay)|P-zTZJH zC3=imy9s_KVq3!-oM_h+(FFX5!hZB57{n-!xL53k7&f9ocR0Saw^k0=o680!$&sO= zfZku~x=>kHAdN`_0C-BK$=xz|8P(-b-}rY!XVX&Rq|+He8Dpo}k(~3mEm?74#~Bq( z>LD!AcyWF1gJ4Ax-wtO4=seM|ck`$jVrdrY=rFgYou3P0(}=njNS9z3@;UxWO+0VRN|rG)$Tz|46&x+u?h$8GZ6URz;OIaFY%L0000QedJC0^@LAJud3uyxPuehDvb^k z6Qg9n4;u1&tG%yx*y`^m&3lNzn*eL_nV ztA%&>ZBqJKYQK>Q^_ZJC|C?*LfVsCoWA`$MF7tI<&Fgau5ETF%@>4oNP|K!Zqf7C? z`gPq8sbWhOk(~Ohf8FKDXe=!|M};!%?Y&K0z`!W9HVuQ`61`KR=MAo6aAj`?vhRKP zre4kvu(@x%pz}3_pVvR|kZ`ZMsi3Gots~t&J)d5mt;^dyFdo4*$FA>c^qSzujkN9zW2cN^3j6u~d8|sK%l;AM9Y@Pq7+_<|S-bGLw|R z&0omhK$PZ!HCyI>k-SgQk16 z8pH{z*{l$n>zUyP-<#a5sE?iKa^LsTthh|BD85+}l-+9$Lz|@m09@Trp`;;r2Zhlv z<<_IEYw{=XY>Owau4ek(7mbVawj=_&@iO6EzX!+x-noN6Z}CTya<~<9*)&dO|5;u< zA}8pxHp(J(?nA3OvYK9hZx*+8Bk4>vozc0rCkf7orBKnIgATLG6vH+9_227NHxz9h zuj%}27lD5dcx_v@A5YBF7Bf`;+JB3FL!2Sd9;En??$Tw;bVewR1i;?8)gFw}cU$#o zq(A-(C6d?BZ7v$&cF)3GExGAfpv&da30GO-d|yR%S7h|X*et%+YGNYFIRn4t5)zYS z6)&@F%T8PbQ7hZ(T_9u!{xI6Zoro7Vk#g>YAue^NISvFHf9HdOTut@bpQav<`VpZt zozK^Ot@e*y)81T-F&WdmN6f-)8`BR`nk%8c(}fn?n)JZA|4=T(QPm$o{UK(W?6U-{ z7=NuCR7D!d#woz~6^7BTEKPuqWj$)uy~e@E7NVDE;?`Pri{kU5x(C z_SSYKVq>(UnXME;{X=O5oF%-_DDvR(H6Y9IYC%s{)Qz8om?)U1MF)h^+rl&pNf*qQc?-qV9U^TqUAR)Jp* zuRJ9lI;}2`Yz#1-R)lqVUxg4rI}(m=5P>46zz6^^Y@aY%>8a1>Wcn4AimZQik`VuK z{PRJv)8cD-8yoE*lyAFW3mqsVNAnfpR_zv>s*LW+K>DAf_oc)c zS-K-hxr(nA(1QZULeJfTR9O$_NGgv}D%zJg_ER zx+9t@i8)!fK1PANljod2+V4fRxc<*<9By3qe9M(qO)_pbVO(i%01VS z0+n%(7d1R`6D4|2($dKkba2H6rVMgU+CFVZUDcE)s6`psNbrF~gDVNH8(^vI4`%OT z>d??>^>`%zrpf3u5#63G(_Hs_c&J(+(!RLT@9M!$Q1@LR=W}Q0%+>FI zvyZxBb7sN4D__|MbFZI^^K6ExubMwV@;28;F64QUkkHU@bv+bIiU|0>uD4bQt^P_L zzG&L=tY&4b$OhN!cTs#Tt4Ea0>vz<8rXfC4q2ms?b|1vjw=*}|97-nD|6m!|$g5d| zn0l_6k!6z>7!;PM=X_}}?C8K$b;S#S7?ML(hgME)T;TyTCJLg<7c>8+$CC~Y-v2#% zsnzVQvQyBT)2dUXi&m_9zQ+LC2aPGmS)-8-=cuTE{SW1m{l+X$sKgS_A1!!b<2o`h z<|@)aHkoe5JJ>r8LIC(}Q(YAP*JE2~RkZGNIbkE&@ZtbN}PV_DymL|@z?C$W56vXI4*-k!`FvvMf(AHc7X&#$+CL2(Iqg-S_YCtqDmqX zy^9WQIOHY7vGj_e*u+=VF1PX?;bftegq0r-l_ST|}8@up$q z*GHjAb7!&({2tto#kUf@_pEKEKZVka!s&KG8Ux_H^<9C#mvT7M>a;uZ6uwtP0zctA z%2y5cuzf;Zxz_4D+s_y52l&lK$|ZfZ}L>Jp1i#pJr6yFjRbc8Er^bAMh%Rdl_s1^ zmy%)$znBf!=28>wvZ`+XFPG#$B1y0RsB(;=R^0icB+p=zj`tcvY>xM-y~KXSU0ys7 zK*anD7%)wKAS^Qp9YBuU31xJ?3;r0>@U$n*=MGOF7%J^&TghtTWbCjJp;jKUR&p`o z*9M6w?+MxtZm}%$`;d`{+}(E+ta#V6T|X9?ct{?TmW#< zh0hv$^x$osr2Mv5Lyyu`v^SG74n>(fLgHYT^O3z8#w2 zzj5ZW(>tImzIxAiya&X4g(VWXGpPoBqgGRp#+R=5nD#VsYeq#Y{9>h}_cvf4)6f&P zy7A*!UxZ;ZR0NLMr$BkB9VyDR@4<@w)kj-flihbccA+JMcuCS$|QtpcYX@_SbFgj~(K< zW=tcb58RG;h+&dvg(3-xlIGLruD%^g=erW<=^ZAup7>muWoj^CUJql|f7fX+OLbp) z;9$c%8xvAucKv3`rUhxeChQ7Xr{C&=Rc|R3${`&9Nl4^ZXQKf#BnfmX} zMx}EGoB6E7yNd5aS%n$$AJzUtIco%_Y9dV_5DKhwq5$pm)OXW6Yl!?UW$17CeMAr#T@@*S0SR> zw2lm>2?lIC{Vt^O2L)+A!&K2p>t@NEtxTK3si(2_4!U~ZKP}(au%t`)F(jvRt$GFY zV(2wZ#xleLoS)JM&Xe_expb+%V=PEYZ*%3!NaGxFl6fG@mI1<0uv*5pRFK+SZlzk& z_AP1jjXXkG?h!oLWok9a z>uiOqqb1UmOspq5ts7m3&*2Ft<43nQ(u6`|xGF=Z=3vF7iGk&j<>0fiGwdG7gb?8Y zTnVM`HAkD9Dmc-6+KpHuL4IJ}r$v6cFD>upqNwPe9K7(bHo+3>m!DOj8f+``CtZqe zLY+Z{^JnjF7AlzhO8f`E7RYZ7N`8i&RNfdoj736Yne!(FMAF<^Nf~2@=W@Fe7oGOzc@cYPKbg;Z3eq z<4`R83FZ0(Qu1b<^EGN>KuqXskW3b@nWVmZUw7fsNHRvS&Y6cByE&%2o3MtWHne8& z{nCv*d-eYec-8rUEsq7o(s3TKC15q$yGwMjIlgt`ZMG6H;yzOV04Y&A{@5)ihLVHK zP;WTvR{TZLuK_L?s8`Q{rLrhn;^Hag~ z^MKODW|h(@4sth6z;*hsX+(W!yc}k8-~mJ=g*Di@Y$)LTa6!VDutNF>Us?XDTADr0&T-3P>Z2d*=QWS%+LPbiY;wX7 z&&!31U&~sNV4wC`5$HXpAtDq`i%}~N07(B(De3dCtam`gPQ93a9+gluY|H|NnR zoF6H4o14`l*2zh{@dBg#@2WlQOZH*7DUK*4_K6j6R+bvw zyUTJMlZpHe7(yq&avW!ZsPaUZR}rfXsR{3_F+Ct-12Mhe$qCFDp7e#x9Se;dJA@Bo z1=fGmlXhFCJ3aU*E9KfVYU}FgPg5&1Q)Ze@ijuDNB@0&_+~{57N$7A$+quvH|FZ-K znCvj&h@k!e(QxFDWJuNVFJ?Z<@n_TQw()|Iu#$z9^TnJeS7zmAa^JOg{FRO}qioM3 z@38+JNPGg%^%dm(>C&jx&Wy?{^|U(!^HY7z0vff-d48hZ?Y?a2Z_>fmey8ec{;KJQn`-a_%rWHLCLmd`09_=&#P)vIZ z>_(hOV2+}i9xaO%(sb7b`0H2PbRSa=$8`3&**J=+G~c)QJG*|N{B5${0?xJCS4SVU zh6BHm#7j!5(h75|)R`EN`cNz3)j`YxLO^Xblil96>tmFC(slhT^{n@=eR=cIMbA1FWgD;~HK^7YHNrI=pob<#?l@LYm0S;1Qnh`)F*d zHE94^VMa(lJx!I%CwJClw-RD`k3y*X zFW(4p3K(S!I?ljLXC?N^T4O&x7h~KZ^LdQULTwmPnwj9zjhU_~cb}XU{1iCguXiUE zJ!@;+YtpzxM&;}U5`bVR=n$=;O%O9ykg`!%oSyF4$ks%Zk1$FfTsXS@*KbNKKmY(} zX+P84nzUVCNfMP3r>y&zI1a5J^N6i?@>J`EQPQTva zs$}q}Q;ty~Tl@$Z<)Yyty$;6&{-IMt@j9%H!d#y?(NNqkQi=ZjkG^{LZ{IYIMTaaJ z_B~y?BG$*FLl=+DHc|jBK+Z?mSj|Yl|D9I1S6|+bqyxrD%sUahrrOJ^bgnC8vRWjh z9wAP0hjw$Zz6_FV#S*DUk_=fm*JFq3zrXFeO=|s$x@wcYMm<3SxH3h)I?;C=d8wJ3 zUxk`Dse4av2h%;z=n{xWQpJ_^uKsK;$ z`mAIk-As`p+?x1{EOm|rpP#&)$_(^^!7hpa)``Epve9P0a4DeG*8WZIKlK=zco~eM zU6w)!(@-7_^LXSysxWu-?5p6eTih&t+%g8g3QwUIBF)@Wy!W!LtxH0At|TlB03beq zbQ5oN$+hDAocHl+E|Q`m>f(3@Jn@SBaoSl|cMm_J+ZD)OcdOQq-lFO9P!zLq_!ALO zC&-WU+rxZ#TZ@&|4t`CfUCTHbasQSX4}G8fg3Vb{(L92G1IJu{OJYE(`DwBks+-Q1 zZ$!iTZimx_CArPla+ll)?YeRwwU%78))o@I)ay!-`6S@K>5FVmw?fJW4j2d z^~@&lUtWY7{#GUHQN^;8Zl}#1?A;QQK0H!KvdU4wbC)j8oujq!yW)lQ;K~F?jJQ>_ zr17aQHNG~jNe*o zlD0Eh`a}=BhwMZoNSTjw%?QJ^O(4k8CEv%%wfvs(L*AaP_8!tc^XN+V&Z!TL2cccr zl$GWc6Z7oARqn>NuW#V&i{HO|8ieaZ)$fbR^OuqhuisWC*&EdLy#o~;A~CoY^zrs6 z9g5*&fW_}z>Wc@)p1Tk(P8) zGo3+A*FNFKB;UNGhIE>m>=zCC@eQICZ6-X9BM*IZca3?b788m_0#>!==t*)7dwRI& z%`!4s==MsSi%;zHR=vmbwr_Fax7Q>4B)bb<^A}r5a~JfDh^&9F^Vx4%d~p3y!iZ7plRAyxd!R<(=O&Miw|nSFA+N1je{$ zMQH}~LEJ7!B+O#Ta?RhGW9NC5h}~sv`YX;hnsYu~UVYm{1Or)Gz|iHc7kum4^@NM* zSM!&))Nb=a)`Hzk$*W;5m=2NJq|9X4M?bfZiDM5L;bTAXv)pE=FW>!#a*hs@j|k4= zM2-^<9$1r3eWzEwx9%U&>LTIEV&;t&i z4(Dg@9GR+7wNKx*xAZHtY^{&_HQc{^I%FO~x8{@*lF_4|6sx!{hsHCQR_&JNHUH+# zdLU=89DOJ01OUnSUnZ39X{6gwxPc&Q<%mxD2ST;hP_M7PYoP?4nDJ6wqKcF6p=9_* zGsTnz!Iv1dz{*uyT2QF)Au4A>OX7CC<{x`AlSX^-Q)@e9r13KoeIivBpRUVjIUV@1 z(NIub7%rEIe&mG}qtNsUJ8C8~LN}Wmiy%XVosKm=`%EpW3DGaHAduwWV9Agx5vp^7 zDBrPq^mkkwO8HDXdn-}|F(qk4p;kO!;ivd=Rc-jG$d2=2L@*AKn=4PuIO3?eT~VvX z+-6&FzT$A;?iMs^2xHONe(-`w-RO2NI}J8h1}CVMUG`HkVXo3Cr4*`tvoNwdV*k`! zFcIM@{73`73_Y;5C3dyu>BPrUiRG}mdXKG3>DYg8(5t;rGz17UKFPu#|OeIM7Ay%G}c|IoA85iYSup= zxo_W7E-sUev!Zhh;isMsJh_PPSj~ZI;g6LP4~rUFR^M8!Q;f)Ttd?9A3`h%}v7P73 zN)4jywdiTX83a&vr$o^&X)3$%s2nRrDB^I2(R%^^TO_G*AAdv;`=w8lS@1HX;#*cS zSC@10<1Q{cF-||znk1PmJ!x+8Qg$$@;AX(FMeyufDpVr=wsa|Wivr5OO0&|#>xN9Y( zrz}WaIVrj~RMJUw!1g{+;U8@nEzGv`){8pm!#*F|Wux-*X!!^$q@ziHgrlRikZJ*H zNs-loQkC5q~PtrU*SdWl3v~0K^2b8NZ`|5t!i|#8~$(E60f_3 zg%;CXRv`FsN|;PsNbb??YF?z2zY5jVyB|FNzgf=SVZt9lwGL57f6oJJ)bZ~I9p(7e znf2Is{m2W)z(v-5YiR0H_NA>`V|>k1iXsPl!8~u$VEO9JmXj|8Us-*RO4Bwj3VAt& zicB(FZ{EejgqdiIgVEBo#=IYv)zZ)>y|DX?yIhrn0v9@LbYD_BBR6Q?AibCQ5C?h- z4GNmtQ4UqTG?KjMem-1~ShmGUsj$sM7OWDK)I4f9mX%95$qh3_MfQ!|1gMT_|^GjDx41L2k=Wfh4pyIRFXu4sBLqRK7=qzFDlM zBXFZiTuIB(TkYVH>`Sf@MH7w~wTn0c(2>Z-s+aB@xv(Wgl{PC`Tvp$nD7$FRa_|Mp zbf0A)OFJK6k=q@hcHsT9qrSF^R~Js1>|N7^OIL#L<#;;5RyAM%ka1F+syQz z%F@2pH!|NpfZt%m7V>psVWZrbM#ld&0lT5$1F+X@T=D7jy{OX{RJ=+pKb3yG0tOMG zGq3)jz6tL6xTi9x=a5n`<00a1JZGfmTx2%VfI_ z{9qXORB!0sqB1y^>%sBJpY(R?VFui^XWcX>sT9jM-9##VwlPLw*CnDj_h1g%91p#b zDiB!8&a{KUKp{$b`})^Q%UpHG{Uu32vBvsYZQ^@ZDt&a?nIdDfDyPsYI9Hvn0Ugda z1*igpAeomGl`p;2)GPBKovRo~5Weh~hKXTy+2rV`KKLAx*g$Bp{6rPn z^h}MJxYX`-a~($5^<#2*GID(AZ1Dvx1+IxrO5%-M(n2Zpl68DM%dR+GPX_ijlno_EGmyPht(u5ez~PlDgN%+`|yh+QU|;dK3!)&>&UX09%95ooGeE(Q%~oy!_3 zX9VP18mCT__85Fpk^NIqP983OTo^uizDSvw`G`NJAd1Z&$k7cK41E+9me;ny!S_H$ zs#?(yCcy$vK|#t&-)WGT{KsbA)g`4oxcMJ+H=Y>Px;{I^Q{#?bBUI+IR#5zTE1C?)XJuKBr)Kg2_y#BNKF;!A{` z=qcZX$j@a9^IJmTGq0z6r?FSN8EISL+KqF@PDiV#nW3Se{zQ_ND_SZsn$Mar&q8aI zgA7MlG_UbnpZ{G+@?W}~hq60@Y8}FHqA3Au!e85^i_P(^(-J@6f#LL{;l8Cqa(StA z(yuIBK2hm1FfHqJhQ-@ldcB%}@zh*=%`78XhqfTR9F>x&5=r=K@iwkfma&YUm(_LY zIxHPlc=h6aWfr~)&D_Zb-{WK|Kx{(uggUuM>gbk)BYJ$UsD5py{g#4bzc~&}^%;7F zJsY#+p;?>eUYiB5n>5Q7F;l6!A(@i(u;zJOSsZ z#Z3V$l|8nqbCWE|yVavQ;x+#%m16YdMV)j#WyaYAo^(@}&6@ay1jwRSk@nxh$B+#L zUC-k3<=go5YMy)sCbq;vcSO4y4WT6435hR?s%{G!580~e*p08<9}C0HGFbJ-ze^k2 z^~|5bwsYj)7fD5;O(4jytOjBy<#&_-@LOzF>^Vcz?@7@!!@;6l?Lo3eN$!rl=JB){ zY>Yk|xlG{T6W%yNZ>171ECv*;1Kp#Gg^C?@%>(V$*2R?b&iq$@U%O0Su{>jv=jIM~dSYoH>J5|rR5GPF#b$QxW5X(7|q?QLu)m=@C+l)*1Tqi5R zKZ3TMQ`D+9^D~Ud=aPPRM|4M;VFpE3I)u)F#xi1O^a3PE2r?oR6-c4B#Qk$rz)u-t z=$ljWV>3FU;s14lZ6_Y%saBKK$v7Edy*gA&3^Am>bsFLo0(U8*B6vVKA|qR<(3pcf zK^)_4X$BV;iyaotpN0J2P9dZmbuZ037>T4WKDWe*;a&Sn8EL&Ol{4uIq6Tzz^%l#A z?ams(EHi$yHiJ%HK~G7gCoEqxyNeyuh3o4YB73=&x}-p44IA zJ{qj3ZO_FT@$By>W()_Vu*ctdCsc7*}Vy(jkO4R-5G*v`O>&Jfmzv!w2L_4z${9 zkK*2NU*WwK;Ym66`Za+C0ERu~EkVAXdOML#C`X*r7e_tO@3h`B@{CeP8fzQIyaR%^ zjyo3cE-N7f?vGt6&K6Q3GXSUr8|;MDA4NDYPd#PqUHvFZY=kdYh|1`dBD~G zAGY4ID-Nhz)+GcF?rz<0K_q|?# zX%oNwK`$m-z`8kcH;I(s0GC~h41wVdQ{@{r0soKE6sLO)(Z~&E@mwvlh@V4zAV8eiK+*K zrPT5CEf6C1ukYV3nrNOSR$qNejIgvVTDh{~1D<39yu4?NkbZ8~GYLogDtQU_zTR$k z9d0{0bB0w4)v!oJ;}hlGeo1sB9wAIIdVhU!oDKVTaU%SaKMSGd=e}B0&0-Y$P-obre4R zm~S)+YXP<9k4uA%2Es3x<+FlOpFJOg(G_cqJ;5gQkQwvH3|+>=ipjSJle;*|rjzGf zraJk2Urg&E6l{rBfSNuB_Ht~w3t?1L9{0n`d+`tgksJnUQnHn|j=o@ILueAJt3U@uDKgSe35_-l8m|4t+1t49 z{3j|2S&Fj97AgWVCz|v59>;Ly;?eGH8UWlwCAD9-X9_3N8STt}8it4^uq&GJhU9>B zICIu?XQ-TZGv#S{m{9GX2AU=StJLkWl#+%mqo<}yUolWyl*2c9O)jO^46&EgV@vZT z)GGX1b7Gi=e>RWHf+?uIk{};q$=F=XPbpdB@%-xw_(OhPN+Jv2BarLyn(dMqy-<#5 zd{3Ct1@?L7bm6;#f0ocrM@PC@4m(BGSP-%N+tyMosv9E>PZp&h0|gAjz>EuS7{M_a z>PN{AlqCr<;F%Son~aHyG7WDNcx`Y9cX~ie0i%L5fWQR+bygOxD405RxmF4p9*m8G zDCdIZsWeuim|Tbm0|V~!NthqTz?3ii$Wy`WLkLSmvUWG%JZPAhVfg`~oeo`r=_kEwIy;c8} zuTbq@`%Tr?m>0b(qph6p&hJh^Q~lOQqP`4Uw`A`A1|C+%boZ~l_Ky@iP@*lX162=65RiUC;|(hGVzCIfTNqwsJ8?;#kLxG;%mwTht&wuA>;rTE5n z=ozl$N&r?9klqzlk04KtiXjyEs6%D@&qGbR=<++dLHlLSSbQFi(O3!Qt#UgD`D5k$ zC5p1@*#;JEIpdGj)9|^cOa{^gl&mhE4Ycr1>-2INhaf!O(bL%R)7Z7DBc_anb*1r) z$>lHXA=JlkLd~J2q|xozUpK+5znmywGU0x-GGa3?RckDzI<4P*I@R39CB8_$ZSI;j zIkOAAIQ;6&%uj~rPX`0vnVh>Z5_rv(8z7xHS}Wo$k0+NG_gug^p-ymv@5ZpatCf4c zmZ41B)jE3tFZ0*87_fo@rm{SA-prjOb)P0vn*N?|@_3BIp_mR#EI^(A5mY5-@moBY z3KkQEP8}5SO$v>W9Y*|>vAK!r2yZB<2%%(@Bye(&v0}RKV1{f57F`D#wWQyR%HW3)yd#2QV%`V0wq} z?bBFRF7tZ+2qt}rwqtsvFh#-Q9whrV?`L=_QQPpdZ>8hfg5PXX-lGy{bMe#s`4+}h zLea5_>cpZ}fyWk;uA8rZumbkF%(k3cT^xO*!XS>2Wp)1B3fgq`bAY#to{XtP)%iPh zm)j)x=OF3!lFjl+f}ghV3a8lX#KlE#mux(5coe_Al;dM%jbL0k$~}sI#s7BoV|+(< zkI3v&oEcErA@!i&g>+?v{)}oJB`py2UR;<=^M3A7H<9%=^4xCcLD88nWD{70gIm6r zARhk7cA7s#U4)dRf{K7Dyr7wmIa|jqS`E#2kob!Y za}yJL$$ox`+83NcX=(DMr0sZmP9cdmH$950Z7lpDACu#cf)9pJ7BMH~QKpoUuyG}V za(aVoejZ#G{mUXO*sgsTaZ1`lvjLt6a8>wmT3A+ewXRxEt(nw)O0d5u+Fl_;mqxHS zyvo2xlU3pBy#KSRQHk`3z3yIdW7EGTBvC_dD*pQuM@ORqS>l_LrZ~`7j8SUF`vKqs z=d7IxrwU=Up%RrI)yViwNB(!Wgb!rPRx-D{z@e)B+5nBuuKHp4WQMdSxZU|^!&qNh zTKO3HIdc!B;>k;E+tP;Rh7Ne=+!Sm-0xdA}@zH(usgqA)tpYNKCoD1SVfPliY_0e& z@@w>ks|?^Za2syptDfUN6eTzacmwTDCYiqIVG+lZ>&c`b)R!gd4PH5JM$e?SvarNV zST81SR+tXW;{`ecs*AITG9kHj;TZdN&>gA5gsdLek4eSne&(q|9x*OR|0(=6q zBV-2zttenrpzHXDu##Mzrh^UI$^^SYY@BLE694yTEbL9m8%A2&R#tCeR?;MzT=JTn zXc;RCuPg3v-uiavWu&zz z+Q84qVP03$P4#8>7m_fyjK@rS|;Ml;o$eca@Ks=lmzPExgO8&F8%ET0ArrlGFMyXviN+x~d_#ddv|l z0@QH_jczOHIP_Z?nJpdlku~6-UGI_fnlc@77gw4*hI`AOE-?}h zD-l*locnI%VP88%(cash!;{?*cWscqwm03oFhYFR{yj39%>dJqDaj zp`T_WZl34=k~?yF;2!e&%g_f(aDV-;rZ3VT|EJIpuEkpp3TAOjyOKX;hxA}eOaLM> zJx}F?fb1z4mQ_^vr}5Mv3N?h}HnzgWpeU+ERI`+!vd4PBtoTCeV*p;<@89tiv@MEa zQsh0HV`bpX%n9Fll2#XEAAtuk;03ZS!)GihY{p82oTAL4ik3UA@Ik>!dXQZyp_UM~ zBe|XVHxn`nNiLRs!*;&~+rVf4E>7Q$Mlhb-5S*eW_7LH;d6!INk$Jf_vHA$Ti?TZf zikqZ5tOjsSl5X`$@^;bMgA_GnsA0gX3eq1^#8IdDy#GeYpqCFB#bF^Magh$cL@hmJwo+Gu-L~V0sAZd*BTPW+$z)CuHS|^*Rm6_r=|FOxyHIc-H zNG{Dhpg34g@N1go4ZB)Ize-f8<(N52AzF3{DYf$Daj zC&=!x)_5uAAQ*0@laEY9mqffPjaz!5H&hifBSpzjOa9=QI70-XO0f60Vv~@jHZ77H zyhF}xSSbT&GCUB{MRUe!*kV8uR#)p`(}IK;s;rzntFU>gfv3hNyFSC$I%eninsKXZ z+e-Vht=`F0x@wZ&d*0Ep^*uEp$K)GwqF(Kf|Dv3o&6q8eOh3t40F?$%uL0en0uy?k z%J&p&L9(UDw25fx*JN-Qb^Gy;-X!8{ddRgXj%r-ED^P93R3G$qQiy@)xuFMmUqm z1kb(M(f=$r-@EHU^(^zVazr2x-B)rW(!hH%W%V~rQ)_`;Tyea7EhL6;%T%!vyV5rD z8kdQSif)d#!J9~~Oxr&BO{~vw8m{mht@+OsWt{HLLS93Fa$wvk;T&A&G{$$2Aw|;&~jKSNpE97@w7GoRe`{b_f@O z1C+t>(LZYYLV-ow;OkR2_Q(0KwNHT3_lv(K9~f&nM?zO#R*v5vmDCopB6lMWe`2*W z;4WDsGFNlS8WX0){{QCC;ii1#Y@uXsSr|yKG+=v;%2Jv#LeEnHZi`n4eh+CP@~0n* zDn;u$0M*LeU8q6r_*AXWSFaJq4r|$Nof6o(Zk2QR)H5BmF5hAW14UXBX~$8311x+7 zL@sO82jA7TAPedi`W4VfWa&=2>dKxVDX#vhd^)7>5gsjpX1IE4M|$k=Q5SfAS*E14 zjTF=^w)jl0`sL5kp^< zP0!2pw(aj>7Er%()AS1A_xux`f*5ldVXr^ZR4i^A(D zT;oDsMlx4;N3q111ghv4(ky=}%!(#j3bb{41Ba!X?d_+14J)Qo%7p|KJ+;lOH8{jO zGW+})Z6{!OY9y!rLpf8MF*7ikUwpg(GZ0b_QrM@6$n-o_5H4Ydp!XUM?n$ojFq*y% zpy1)Pm2TrvTPlM<`pNT1|e&Vh|gFK(r z!?az&!V0Mi&LkUvlAhLLb&^%j7xw(NMs?3YRZGf>Me;8WqS)+z?>O(x52hfJtTci; z+K+rglL@PZ4MNMY!**m+6^n9akJ|>WxQJ=Im^h#K+F2tM64!1;zkdFQ*wi@ao%P#I z_VgA9Pi730P6!cxYGKD)dO*J9-{0lm_(i^Fll7qc(S;sD!_(Yor3K+GPgXPupxP4? zrCCVq5e6Y4##n7t@q9n8*MO@9YjKhM+!&K4Pr<=g+IQdiGJ$^JXz`Y0C==n&HrGUY zO_BQvQLH)&dyQX{mOnI-P=Cx}M@sR;7T*e0U={h&EwQkYE!}fZ^1EW}3Hiks#&^z9 z{vhH+VlCjW;DRoxaDTh^%GNVYxDt9N5ekp<~g%vRVFXXW3 z;q@nA%F%i)r##{bMgD-Xh3p#c+mp2~KYutU&$TN26{<~kB;AdEp~8^z3x zILl!aNM8jMxhqH)ka5V8ZD-RZG4pe7NYl$?6N@H>C6+MYHAfFJv8~h#E29~jV)U4} zg8{_51y0HWTYO#Djz9BrovQNkVr3dHQC6n^ZD{N7e3-2CzdOBsPu#kjvN9elxr%cx zrND!Mx~Zfj3qL)36<2Xi)P5R}GXyr;H#P#|Tws!b`>r&FA!%bB^+y12K#;#du8p1k z$4lHDf8<}I5i>po!6+yc0AU^Db3EOlW}t+BUEGE8eQ|Gi3Wt zC9tFnK~qpPK4Y^Psv9vDyO1KjP8$p+94+k(OZGEH6dn)N+dvmQHEf9G5yZWd%AE_idQhETKFn$n(~WdGz19t$4fz9e z;sp@?_l1`yf;1WX7;S_C?c3if7;Ka>OV~etAdZDa29aF>kaplyFHe%dvCj{U+A)qq z#E@j(bbb~8}l7>(kU3AO`F4l!BWA_{H`W^u!+BK7_-qYjr&f^xdM+98mX0%|AoGh$d0tG-5 zg3D0gB9mI=e<-KtJ!VEruAk_PObUe5gA}#^WrUtpB7zp|Dd@d;G<()28z|B>DH;zO z0?p=5s_M3(Nbe4^(x$5&Ljx~t+0}>(atMw{12(wL%9e$l0ExxNw|i7NV&0Gr~Qh1Ka(eN7`C(oZ}8Ht%pefA}(&AXbmGXzk~#O0r`RT z@*4V2zSZ?ZIe|uHR+>guT6u;T>u_#H9-_^rMp3J?s8Ip^Bo-&3?lwIM*1H8KZP7_BFyKHmnJw^ z7`R2>;oWnN+pK#2MiH<+h^!Yd^3$`5uM6mrg5HYrRoSici;a0zL8Y~UP}#OY(>Q^c ziw5Dl9{lHmKHT;IxWY&V&sfm?z+yJC;{9#L6t%ed?uLi$qUL9J!he3yY9TX*me)lL z#&{~=XkPSK!(rW{=Zc=q&anHpgSn*#*6Vnsvw)qWf^M~~lkXpsRWC1MBLO8hS1sN_ z<}HIlo6~0s4B}A&&3ep&RH9~?{OQTfw_3K;(cRxhXi&jnqfIU92Eoo@O5=`XFcJmH zsq{ZRV}-|5Hsf11v;LLz?o;rWPFPT$Txjqd?jMxgzQ*GW;x9y&ysZ)lYm=Y$h&)FT z@F<(psEu6wJwMtBED#nxQoa;ssaSasfbJh&4F@{Cz4yQ6v|9x}rTJ-QOt;>x`GhzS z9pOuQ*d(e8kh@sI*93D<;3}Kz(hK625MmPr13whA$_}(9eM=Ug8>W`y=#=95qU%K_ zh_0B6W7UG{ygYGc-lf!IXpcyyLG+F)Et+3&Mx$v8PdS`hyW1FV@nQ%WG@YZ9a3YFQ zpV3mAwohfh;W8CG2D~XBiuH|>u$!?n{GxdB^HBFSPWbBT_ki zpXtFkj#}v(C(-#;uq1udfNFqDs;uFXzb&P{hm|y0+fX=bJ&uHtChZ;bo-G)SP=_A| zZ?$Jpu`n$mX&$iNd7RW+o^iP27Cr{?_48Eha3k)I4s~=lPNps6Ng^!?PXEbU^jZEt zTFzPldW7efQ*cqb+Rujw!4ha2-z9 z(|xNn($!%+p_P$$78dse%F;5^G|_Z;GEG@#&It=~UfDuKs9c1%O;Nw6j}P0hmD7E~ zc)u-J_C0O2pHIIm1U&6i^w0Ej~5ds^tv--_V?=Na;6>o(x?W+ zVGyhqOAKU_S`k*!}Plm2CM2C2d%@22D$CI%7PW2YoWQ4SZWN}>-56=??g zcnlv~An&`k5hR}n*{hZkuxc;=aa^rLoNQ}eK1;nDY6n@R$&wMcgS(**M7_s{L0fn4 z4?FIcXCG=i{TCaTecQuB+zzJBP+LWte;tgJM=&`>v2?^pdBl%ydagF_DL?*i@sgwG z=q{M-G?7gK1vuJ;y;Mq5M(AB7+p~Y2g8sl0Qe?ff0FZWjreL$uRzmw#yJ}ij=JW8> z2?wT%Rn|+>qRi@wp7BuOv(_w~)8KPd(90B z9DMyqx$5VZ#ev`}RdXNH9&e@@ZFXrco#;sOv};0F6`Vh6KE%F%Fd%;)mTwF%6&0~p zL`tPfVTk*UNg}nf_QQr|gtTV0E2do5mo%Q2{bEUNH97b<*FT?S7x#5CfrmsI1r!nT z!g@|-Nt6X6P6G>CM;tGrAdXg>y03NS{Yw`M2KKd|6r9K-6ewI)!y2Dq@09h5y&~OE z&4x*bi++~4^XX1JIQ#q~ZSVd5@$vCGH54erY#<1n-J4PsB$98t{_A=x9B{?X4PCG0 z#Qdd|xCU?prUETbes-O*9FYo(c@yxRpJKOXFc8d*cLhmY|MAvh`J9s6ki@Mbx>_9P zv9-jrAjP<@EM{>qts?e7y14kSraA3>-=nbuZmVx*aR$Fi9T!uLMEXYC&F0iw9h)~%;*2vjfZ9V`){^2l zhzQH7Qpw`GCbR`^Kns`P@)x3D{3qDTKhsW%q~f_*W5|t^Ltp-1k2T9%eiuxxn2N!F z&Th4dwKM@3CiG_15H7w?LGSQM-b19g{W-72LBk;!@hQA`-i5F~(`v~^RWH%BpGZSz{-Le35n zG!bF{HMuD&Ta#9RkM3kSYjHXpejDQ8 zhDA8iC#p!{4f-XRCbDxieG)d8Qeq>sOL24J$<*Kw!gsnj^aUiTD@L^qw!lPD6VhiD zASvVscflFiG0dKNNo?Xaw>V*I)ZgvCQIR8N6zxbd7-oXDho43_oO>6J>mOwNUG`P0 ztsrRSNs-Qgx$7feLkb%?^{dHHqz+tBaQhH~ZK|1e@&WBZ+yzyN<18!?PSLg_QJ9Dm zkEK2{o(4rFEqURZs3k!R3a0$DP|;|6IcJQ@g{w+f3&D^efo9EA+BgC-MK0*PoLuvs zjuK-x>L+C)OH!>ZNSsQV+Zf&jea++Xnec>rRfvuZlay=5iYR)3OjMFdRZ6}|Gn~*P zE0h%|Jb1iD7~AY$>mHMgi|6%z2rj9*hlJCQ{0?NK|Gxh>&rcqDM0S$s1Vsfx>Ot^3 zRA55yDgmM55(qk!A6%q3ZYCYFSQ}p#u^F(G9*Z|*5v3I%*n6*u_LU$u&PAh2GoYt3 z1ch;pRq}P(w(mOm8%UMjIRw5pLt8*+xvfcIEM>dU`n9Q`=#lp!QqR3!Np5RC&X@U#dB690aGfUv#4C;7Nc8aK#y;ESXzN+#HeLXBJnRbia0gNgEfPqyt-GQ8oVI@kX z$3g>I3G?eyt+WmSH3})GLP>fjG7N{3jgj3sEg7s; z$(_IytAX682|nhKTG{ISRn7IntlFmT1&qg00Eq2+w4Y8dm@sU{fb(W!{Ge-g@g*m7Cg3FB3pV*D5 z^l(#OJ{W2qjbxnZ2VmpE_M}c5ZdnjHvhX6bEZY~JeUcRN@{%}Ez>jKtap(boU)rWU z>kmKbwcEIK|4qjw;& z^O|${ThtDAC+AJW+2r*xmTurGG}@l;$h*yJZa!Vw4O_2NT1EUu0-#8vrlT{-S9Gm9 zqiM+U`C|eHHy3|b{0fdB5jezlW^3{jGp9-7z{MzPNyAhC0N2}pqAORG5nU(qM!A=u zq~e3jCQ3<6rq_lTBS5r<(8bc3+c7b{GbJoaYOFZZR|smIO#^F%ei$xIDdy(^Y)%tQ zM!ce9dClz%A0AFDfoDvV;zF?NqJ&6GMvFS58RfO>zl-+sJL8%BNp$Uf(qfBSThZli zphP^Aq73WtrU*rK#H#ETHXq(nGRWJ&DgRJVO&h%>5N%K$Bd~O@-|@<~VEom&*gaX# zVzP~Ga2eW=20+gAL3tRPs-ViMbsd8Jnf@u%o6E|}wX}pjsatnbKBZMa#^a0FhLy1b z(ZGAM?cYB;f~pz3>O-OED2~RJms2z=e|v$Zstx?&;7EZ>ijN=)Lzp7K4B+t8FMLQ#>}w2`&M3Gsd^tHmDQ=y!Oj`0|BB=!sftGMa+!B#f zMrN&kchGGZ!1nTXj@%p-;l!}z_rd2BRsl8{wx6wi13PFn6W)C01ZmG|D3)7}d8gln z1~?-!u1b*F2f7I_Vc}95uGehgEjFkC^7OQ$s;Fk}IveuDTduSkNF%Dta&XrE@}Q~e zk=56XE(S^Vzmf=JX685X^v{y}`AIPUpegMALRCb$ZAy9ym7fL|6IpSa_~ZDVaGTEx zcQW0=mkAfm)W{Yz$u<|z8nS51qDmN|MgA%dlxnr4DdP_CW?GW&|Txr?)_T4b7WaepsMynZ~0~Wdv?ts51;wQnX;Vq z!u;(^(?Vx;2b-J6n%?nTy2ISCX!UcEqFE4Dv*T(7Z^N02_4G>GSJ7A<_myg+ZfM`+ zBvT7vi&DX~re@XUIv-UrA93?i`$L?oSo_=K+sC=r3$W(hb5lM)qeo-}K?EObIRa24gM9OJCnKkX@*owCXWpoMxHn|T;* zS?+uCuD6l$08jG#hLFIOna|fjpVdd2#8pUy=c0i2eNd$XtAsJoNGp^`m9_aoz}#p# zJIC&I9ZjFy)JSaLX?Uryji-x^KV_`shP39ixiXF;Iu4>qt3{qk6g>4slusc~RmF-3 ziL`CODVl*B?e91lD!>~jMnd$D`0p>(EU!y=S+JYMjRs(;*Y`c&7Hgg8xr4W+a#gk;-uup zmvvDRKHy}obxc9ROS7ih_D=KrRA05w*4yR!>`r&U@QC|1M5GdUsWi;coO6om<*`v_ zZAG5a!C{nWhD7<92c$*l19m9zp+KWlUQv+rP2Xc5y&E47SWc>ken$y0w(ZBHDzH0h zS|PJF3I$D>c!HB;cN}+PY`DR&NVH{K$f@4pNCxowEVYem;aC-s*Y=bm6lMs&?Bdak zjKWo?Yvt?S&pjx1cBUsnZ@D}QIB^p}q5vdXurbM;#wk3<(5m?4qMMA%5!orEZ)fII_VoROb0*B1 zh0pm=Qwp3dVfxXpHl>KiO4yp{D1Vwt&ns>_pg^f^?vLXOdzicKdQ!|=`6xu~M@C~h zcA8KFv58NfZ`fGm1^J_eDSxLgGKuwolAH8~|F-N`a1s!lZ^E(9INp2&b(sIyPHOibUmEcGa2KJUM*jW;J1~QlOUqmhCMyMKVnZ zvP8@}pI(fFtqyJ2Zh1>Zn1W0bMt4Xq2PjafC}qGBSN~saYP%v`iD|Q@w^piy#ilJN zoL4}FM`aD^U}yK>1xrh&mqrgKVivCx(z<}ogN$pynK1%ZQ2mS)JRL4-+A@v}UHM-+W?%z>;=8B9>AiItXEBWDiUt}WDLy0~yP=Me@`8^Z|RS78LkM5@H> zei0E24flv;eF}3GcS({^P024pz$9=86juBbH?SaplZVnw1dEVWmJBgUe-iS_$pO&M zPt~iP=NC6z25*!IkML^OCP(aU`$cIRs)>sb8Vs@)Jq}0$Vz8;l$ zNwRFCJd-{%pOLjeZCATvYV!vvXh{q2<+n`>SGUp;j#X#fUrLWyc{j#0yH|hWkUS;O zCR7hlG>;vT^w%kgsj}e-51Cf8ug+-lJw< zGQV^+`ZXF_R?rZXEUaNRM83QD9)iJu4Okfs16<$M5oy;hRVqJ_nRk4bZ9XXZgcIt@ znk9&iQ%D-VAmkYmk0)6CtDc{PsLZy)n4r>?b2NpPGQB@ZH0QIYi#Ugr>|!Az zk32w0sk%?t8L3r?$(W+;;^A7tz|N@Gnl^{P8=a)BEKT!0E8CQ74MjXJVQH{O(2Id6 zihpl*Tc;qQoDNr04ORe(L}%A>NB%Ii_V<+kZbs;*%96U{T-f*xB2H`fVCo}l_$AQ) zq~@A%g|D5=Yz^K0cgfg6MHJ47H~TgXKCWJ zwSFgR?;LdVl9BPzfB7-t5c4teVrAuKQM$o7`&nfjw8SdINi_O1V!J<37&b0KoW#OB}@>Uzb&;ag(#5s=Zlw1w1V69s}4X3Lz zmE+fsf-K|mVK>_+UyY?S4CD~}8D)3NVsdL-X&Fr!7)&2;K*ew{S_k%jD5vK;x(g=L zO+bGlWrx&*e(#cm#V(^5iU2H9s5`KdCphn#B8oiqM-g9mY##Uw{@pBlMmPL9A}p~> zXz~SK{??qO*AVUQc)Lm=^gS!ao(Ze3#P(&-z&xx-$7K6h$?%`T*3TGSrzcPnOYF2agxDpmHcj( zyw1g9mrRkB)J-z-cZW0i=ivY@jG8j2kIIIYt5wwaGlcWTebnya#r8n z+R0M50<@1Pj@SL^4J!tB5jJ(uC&w?n($DQwgPNl2n2{eUbgOpELz_`{3j-M zoL{=dyr!IYOf1*Buewu|_*kHb<%((<8oadnFpJA!g(>Ao+#{i+(Xg#z+`>(xR*G4E zsaVbY8nv1*e@B3nk<#dqzl=@$rr`M3Z`_; zb=hw$HY-jNF9DZa7wp7_*#(7JSrhg>j>b}OQU8^^XFY&WCVQ7XuH-no^|x71wSMIj|6+1kmGc66zzoE!5>_E8n4*bDBkB9#hAx zh&SJ$5Eyg0IVqLWEOf`3-y{o6S|~aAi>ZCX{ch`4k6WEf{W7;2cyHV6J(uPB{r+p~*ja%=NGf%$24-;T zxJ^2mf(pQ^Z-9Qp4h8Y@VB8I|V0_)O^%=Pd4%LS$F*t1Eex$&5w^i9$PsaF;V*7ov zDQ2FXi+a47$#wOynCvAh(x^qpXUX&2nWmnFO>BbmmNQ6d+TO?6VX0w#eSP8Md)-#I z^-S97_h%#Awe@$mgwPd6E2joAi>3fK;LJ?(uJ9T;c1+k9nnMA>t+#4? z=6>jsD)hIl#H?G*aX6s~{EXfqQ+&1Gz&=?my^X+PE`!A+%dbMrSuZ>d1Uv(k*L0?3 z?k*zb5ZGw&rgDmk*+WK|B_H)-FTX}oj{)8@kR-%53e_`I#(jX9uZHtkybAXaM^^oq zHgEN9xKq9HbS5O`WU}SoeD%a*JU|B_^t9aYd<|nq7vgJ~kRteSU1kvrvRtbLkLYn$ z91ga_$|85{qw+X(#Yk$NI{~Zp>1~ljZ5V{Ag*y+9g=exl(!cebKL@s}IDScL>maAQ{#9T0gm~m_!<3JZ3_9CEG(m; zwJLLpR(@t>Um?p~7OUrp4yxev?}Z7|en^t}f^8|p=$}uI ztTM%RAx^a#)eN>(CVvhtTR}r*!D77gKiAkM-KDO>)@fPV^?Y7wgLB8@cfGy-V%xs& zN)F>0&c?lW&lxt3x>TUMEof4RCj*ve-HZknA~Jg%cA~~-5>)PaG>iq_EgfxI3PG~; z3W&3xAYKd#t9HS!0`KTD>)B*voX*&(+M>z4Rs&M zlsFQE>@X@ezoDs8kSl!)HXf&B^ZReAVIr1*^gQOeCAJ5yuMQWnsty#PHU2A(a0`xFuXPxBm)~)VqzEfhh!2*cecOkO$BOlmu8Z zG$1d$-vB}PF`55yfR)34X1PJOK1)-aL`rVx<@2vFmj(`ggqNQp!obmQ+x@9jAR=ug zyKLZqnW8@JVy&UoSt5#R8o$HmbonT(agYCndg`{m*<`YF?Y2 z4e(RlA$ky<{31?SLRIIYW9@zgrYseLU|~~O?<9h{1qmedc9aE-yX^dqk8fp>iX@w*QA@Ri17aYyqR?J zPC5`_eLAT!XQeJX=hU`toxyTz}r0&7#)vOe5X{qQY?| z1TWVUR@Si9#sSbAOn6-4QlR~}Jl;g-&SDKm2Gqw1ssDO>eEfLjXtb8iH*swJaok?M z>Gk$vBq{K4S*F|CExo21l)gKV-UB=y5Mr{AQj%;&`{UtG6c13KMy`Ug=91^t#@?!_ zO`O-#cY9Gm1PNr~W`}%>1ZtJ2m5@@M^Q)IUkWL-!WOJ|`Q!Vb6ma67m?1j^ECs}^% zv@h7caCVJGQfX3jy(lu)de)f6PEm4w`PTG6KeV8NS^_Q=GF~GFU0Nj1D19gv+Ba5K z=<@R!@1F<(e#}uPLHK{{*LA~luo9YvNTUB||8I`($QUh`Py9s`DG*Yxv9(VDCiGNP z7XetLW_I+{qR305&#f%NiO|==c;w}Ti<|JYe~A}!*^9(M7K6Dmy?ygGdbQ(9h@qCQ zWd3vVdyL$X-(~++&$`XB2%FGJU-|zReGr20ue&jb8&;>goxh}9 z$G|i7Dkjk+JNsehl4UJN$eKFU8raG4Ij4Wpf_rc;rnxgyp~4$1hjVD)*y%Z7@T-K1 zEaI$cNt%oWD*C#*C|Gh@CJEsKd#2f|A#;8_lAL*LqKNKA>?f)LCQ~UBK{1Zft`@sd z8t~y1z6i_y85fx;eVppnRy}D^BStc06fI^T0V*6ZN38X$(lcc!j6qo)fmR83|MIl5 zdrGK2l(K%od~bVXI&n;!v~XMa(6Nmy){w>~GNjo$2%eK1gOWoa3KA!zH=u$01pKfP zJkQn1*+HxePT$y&K7t0cjFrd}mOV(cVJU<*bx8OpLBD4(MAuxL`LPzyzD2i58!V}B z|CPM{RXIsnZZlwzj@hfIX*%UN)N+P{$z$8)$0=7 zS!%B=lhiFLC})cmLb|`MKV{ecx|3&v@0*-Esg| z$kld*rh<+p#%&HHK>9R7)R-)>uwH;nK}|&f001-v|NF880RRM%dPm{r9cY%XNZA=C zE)sFsBc>pF>QB4lq{9xmv_mZ_1IJO7a_Lis&jp(WIyNnF8FL0czg#Rm+476#WRclP z9dqF_cWa~$Il37M+%eudaDvR`nBTeUeu}{rO@sEfKH(x`@c*0))oC(D8flY`l@?&~ zN(yHTgHbKIRU+FWK~KgtbJb(}7k>W_y*#gUmpRdH3_C$`1{u4nQc0;0pn>3!z{*_= z-@uSEnks~~e2EW4AXXi+NR%`W8fj#YJXItHorr^#p|l%1P)e{;{7nYxYkBS51w!v!^+RCUXuab|LK!iRmD9Kf@v5 z5^1`lMUo0-?w9LzQjXr*M0czRtWLTc{`k}$QN<6@i^BYJp;J7G$TE<_YQXvvuDIEH z%Y&w*$Xcl_AfF2>vkyF31_IaXY&x0WevwO_tLN-Hxx134YcQX;edu$3ORrU5~d0`;YAGLbW?!;`?3T800d`p$!R7XYK{#F z9WcY!QyuFWBP7MbRXn4#WSR(W1#L1k;%O6Tt&3>)A%X%ygG|yQOg(&Eq=ZAA$lpnp z1*X*?WI@{rN+y>UiWq1_rkV{(ORe*D)|baV36X=8TV-kmq@Em&g&gE>T`0|*omJtZ zu2OdgsWFBpCB|GOthD)*$r?IlW>dR3KKoqEyPo~}e^}6#gH;aIoaw{ODlIIGDPbTB zI#5nm5_Ps4NyL!>4jM+yP~1@ZYl@V6bydpoF!=q;t9mmxIw&Bj>elVv?8T*-dm6o0 zM#m313{B)I5|rDS3P-Js(g!W+uB8;3Va=k5kwC1#N7k03r7{IU7;&8v8#0hyjtZJ3 zEIyyZej3tmNPI)PF)#ApUAlFoBYkTawc+S9j z@*0hA3+tX9ARH@kw45a}mfrB4sDkX)}WzOVq8-f-JWw(W|JH znmvXO+33!(1xo8oCwb)G>T~wrTB+Y9;4Ffd7Py`fHjU{V zImXctY<9$KBMFBMHmSUzLQ82a6VASYs-9GuD0Pq`5L%rxpjyr9g&@V*FEm~f@$HmS z1?oCyOKYKfnTy?Q#&u$%m8rJ+DrJzwF!g4~m!Ho5e&#>laMt;`^4;szJHP#__M89w z`t2@mYi>&Ai4H^6N3?9#DH8~s1^LeBW;Ap!ZPKG}OhHXW0095{vIGDC1e110;U*mV zldnkX875{Dx#t~&B+iOLI^*=i4tY?6nnBe_2RyPRBx9GNb%9Fisz~rsad*_yw1Di^ zaPpcXHiLsTaCUPlC34UbLRM#vdlu8WAk-_YFc+BS&t6V~k zT96_I0x?2i!@|r}*o9z_KhaD!No#_{3|+Abl)WjI-D-AM^1_cZ?Tl^_j1gU&7>lNg z2-px%A%Hh=FdaYuUl^j2lx-wHijg_UwVLWUHk?^~Bf{#*%4?!M7ES?Y()`Ysr*bnX zwp0}NUGq!Cjl)cI@KLOh7Hije6!SquPi3QOB}iKtSmqi|RHW$Q^LOj#%yhPW{K?Ec zm6q_AXEiDQD=u$)cy`X)`)mBhuK50OtG1n(b=jENMjDs#GX`hVHx;!U43V;Mxvc&G zc9Q6^ch$%sN+6~Y3&4al@c}mkgKD;qQ&o}nhN5REF3&D0>$NcVa}AcJM}O=wVI zYyy*wwvD6JRd_ZzCfOEw6dl89#j$3rf(eY;J%M76 z=%7H@Qr{T|nJBwOA4b0}Va}l}VbY6Ds)!_c@2H$zp@UJzQJJ73S~)9{-d)~8+^~P& zoHaoTSO56lw?1W?=B`&JWrPW}Q+T8nK&HWxxXwEuHy2h}IN5+qLI3-*1ONa8QhG?? zCLL&xZwVbR!`D)w;~|C^cdA}IW3Z8%L6jomC$-wB!7&mj;G%1Lb4E*39wgm8s2q@- zB2IZB$ze-$rGZoAk;Yc?JyArHbQ^d5XUp8<4p1 zBh}fa^<3nLv8RxN-*$?vnNHl>K?HJy;G^kB8tjb#A>H;KWVl_FVq|-FwaSg8A%6A8 zVDcdZ-5CQC9UxA~Jg@gk@AER|+~x24d8D6@vk9fVtXX+JQs!?|pcD$BM2|p>7Ta6? zRAxRzwbk;ssPQsgF(-08l}?_T93*m%>cV7kt)nW=F$SkFHHv_ zxPhpfAWC+sqcH-0D8wV0NqA$1xe#tr^LFJ$#hb~OBlpIdRkY2^$K@=5IiDZNv+_Od z$n|#lD@$R-PB&PB4+Fr)Frgs8p|D-AMvo2LvIO01T}X&5b`^}&B_N0b=e|ME#x#yW zHp|Lp#@&cuhKaStjr%bkdKN(-@^NKZqH|fk7Z%HOmTC8LY=iP5P$F?-%GOxBp7L2e z)HS3XJ;RGbQ-q+9JX5MsnAD8erx8e`dz+U$wpT9(}CTPb}avvNxRz~<5!k!!fAmb=!FLWOhHXW0I{Nz|NF260e}R8 zdPrf09=MW^82u!}u2SXc8>E=E!dX2dXp|eM3b*QkU1cu{^Nd2KEN(9DJoR>A_wG^{ zBYg#Z@~J=DhTj|Coz;!qqzjE?&<-0VkD2@h2 z@9RlTZfNQ#mn*^>_7p&_aSsUcK+MS5g=zUtS`JeQDxD>7BOKP#T!NQ&ue8P{IHH{r zzBT^;PboCa5{4R@6xmusL$Iy0H2L}essGJ)_)K+7H6dsePG{3c=UmVe81w=t6aoW! z1O;K}qy%UrSy7}!$yY8wk$z7y$$;d#s?5w$i$`X-L!ul;gmaO#N(eqCYSP)1oz#~q z*qxcDzY4%qsH2AH47HM3$mG`EkS_&?t1(D6eTLS9d*Vjwl~Fm^w=t<5NuJ}~yhP69 z(6l-|d!_9pBk<@3&P0)%y?rUVlEtkDMLJ0{mPU|un8eK^s2)&w6Iy_Fa@yqF z#Ur`hqRKHT#8YVeXRs}VClghLw=gFveswIZg2?IGgzR7BUuzlvliFHODehJZ3&y%g zwo@ZeMx92%9TO0TM5qNM*;=}ygN@TPhNCGpIYp&+SsDXoV*~?(fylU3GpI|R$K@j5 z9LY%=hQ{Z=q2`C7j@v6qzS5OcYP!?vfzg1A8S32IS z4NIz}{XhLxbpZhZ6Bto2U?yhPg~=v|7DW|Vv?ya75Sf+6F-VCD6e$XkB4}jD2&j`M znna2+#ED_RAfrf;0HfPMQECPy`4TfNq-*J@=QtRSQ{<7(#Fl9iGd-M)!6Se{Oi3eA zIWjO?RoLKA5hYjTW@-Yep^alI@Ph?WB2`4C+O}oQ++s;@W54zP?_VmOaldNb)xXxh ze>Jt=JIz&B?>O4zQDRANeCDG$Op%}xGe5lL5=qfHP*7J+OhHXWGcGweE;9fC08mQ< z1QY-O00;ni1*<}q7>)Swi2(q*<^cc-0000)UqftRa4vUYb~KvjKbQa8fDs}>8BwGt zMTt^`>pWF_iAoe{QHlmFRA^WsLPAO^l$D}H3)lPnkfLE!w1`k5q7r2^?gziuef$x} zljB%rZE0EXNm$5f@tXg(?cP5{PDn^-l#qy!MXr$0lr3UH5<*ji++6p&N_-L)`hWWK zgiTw$^-Nu^>u{YT3pq`(*IehwJ+hA|vOWN81g@|)%o8+!xj|Uga=5?M6}$vmQ2)*bN8|69(tdCfiP>D%iac)EFp87ujpCF_4s+Ed*Eze+G|nSpfD4P40=< zKbnByK3mBAF&EZ`d4kgfJ=m484vH@<0+|;xVC3%-u$Gqr+3?BGa7_k${J(IDv!tQn zW)tVNKpddy2iIUP4}~xm4Cfg^fbk44KeZYpO=m-Vg*{k{sY2LtdvME>2Sv@DP^Tad z^#%LED_9m}lQ%(ytt5Q91Rzo)4wHn`!TiX0$dFZneLiZCDLf7Q#;8F3DjksgssZt5 zW=2M|juo9e=lp!EN1C)FfA-+HkI=qx2SAQP34XHv_lm!%D zodN)NFeTa~)d}rI;_q z?H0lXa-le4z8ZN1Y@K}og*K%@ySNDs&s2dTm2;4J{Sq|XY~noIzJW+(4E&z)6<*4J z21DUa7^(jPN>Q)i_o44lyyPKhF8B?3%f3La#Segm=O8QVF9h*5tVrb?=)8?3C&vn= z5psi!?W1WxJD(nD+@NnMm#IzmE^Xbjik!1=QiW|KuXKMu`7PDQxH)F*#g;Ve?;D4K zW#t%Amw=uVi_oZ+P(t)1&O23%YwnofnUr{Zxz-;X$Nq=sTKbvl{o`PCE0pX^hM3WH zciNs4MUpFbv#$yv6yQscd*D9n*rUjgCl&-g&8IEkE2CVBEYE7EFZ z(IIbG>s>RdHfmz$I?s~LXCu1polS|^vGi5^6un)ZLiJOEsdr}t9l7R73p@AI*{eci z{AUvt-OJ$Qp8sKuf?6=Va>mr@c|Vl?z6kzLU&EUI=TH{-5NcMJ!R?(oc%FHPH3kr6LoBgyNZN`0(HS3-tW>ys~WwxPeyqT5A zHPi`IFpFEO2%A1Uz&>kLiYhw?S|R(rB@t7XP>^eDhliZ$G9VoG7h z!C6U}^)2BUB zyj>s64RinqLHE8gH8{KyP1cIx<-<`J-sFJ`=9i$m&3PO*REyfy&(Ngh5)RJ$hO%A; zI3!ewxAtFyzNOx1-et=zF%m(pq?DOIngmK_E9hKZE?XS4h0MEbX}_j4r3<{s!y=aV z5@?a;sY~DzAjYD$PsaE|k6=&yCbX$ujh|jbV`cX#+~Agpi3@XZ>FOMGZ@P!KbkE|# zW4AHtRVeDJUckT~yKtvN7@nGEg<}>U#_7fr(4b&9>QNFjR4hebk%PQ)y)gFfaAB=l zTA&#@llhq-uU72FWRu_XS?vPmb}O2Rh#qE&??tHoh!9Au`NWE+#6xM!UA|!kK&r_o zh?`>u4Szmyzw`p3)PMth^%xWDZKuGn{25DWInKqGijdprSQd38lBwohU@2DwoRNep z@6|X4E3SmXh{{pCuty)Q)?daGzNc~3K88wz_t52NBX04n#m9*)Xg>23hLzk!r}v*w z`@$;R@}?XiuFG_p-C;cZ!GPRd$AIp_AgXv`M8|)d(J1vWvUdq$u|0-VCq5Ots+C#d zbqVap^YB;Z2-bCR*j*Zrd6Deb%_)?wOi-z$5 zS7KPDSr3?Z)o`P|ZLs-^5;pwVhL6%*F>jSSe(ybqeFJ+j=dLSWy>lF0Ua!IL_d;;b z%@F%$85W#r1`$CQH2&-X=Y>z9!KVW1_cuXd^>5Iac?(pI+oI;S zr|`zX3ytdyaPY=b?9DoWIZhMs-`;&_*rSDm8!a*G);Tiva+d<&;{uAikP2~z_UIv}37Hs5dzu>5t< z_R+#d!AhL`TM3J++_Bis2)z^SQ2UQ19xif5e)UY;;kXG~t8~!&o-Qgyt-;=%5?C+2 z4_`};$Iv4OvG<%VHl}-`%9h3g`=_U#SnjMVm=H+4)ebGYAkx)Z1D4QWVw4DgGa;xPHpuikUf10^hRle zv+8!xZj*+deZmmEE|-ha9t|!s1Ezi^#1(#s<20w1aCMI&xsfxDP<&w#Co;z#a+B1d zVqPX^{wfB{yJ|Qm+iK9fxD)cdOfX5A!Cd|{7K_e7zoq%;vM&JxlFy?I<8kpC3#@i6 z!~$u8#?Hg|mb(Hg)8#O%b`Y{;z5xGtG^S6L!-PLy;eM_(Dt&nZY01@~`f4fk3xz_d zrzoooxNe#ju#>3{Wiq?puAEIoIScrd0pR-3G{xfz_)V_^wc1+H*8KvieY0_Uz9{~Z z1MFC2jccPnLQwWr%v~=5w<49${8bFMMiQV%c`wu-3F6L~e1jtLf%wmJFmSjX@<-O= zVexTjyTb`f&ue4#(Fy3*t%H)z?;-HZ4=7a@LA|@F;1tjYo|Sh%b@>&5te2pD;RR@B zw1JDSG={XPVjgC|p%61nxnjoFs{Mu6a#A!m(20*q;hAi74^x!50s6mhF!xR2Sbg*? zsHR>;^BNEQSe%bv+!C-U@D|eAi@4S5DjE!C#+;-w2jery*t`Dufco~2Q1&c3+NKmJ$E!-5mm%W-`lXLb2N^GD1c&l3e4U5gVS#K%oTn=1}#g*fM?q` zNSz%A?W@eObIWg#o#&0=L$;_s-5l$W1Y!TGchKy*92Ga*1n0e>OaA$gxAkqsi&h zduH`QjQo_P$k<+*E*Om`qv2lGRWOCB%z{|QbXh8{YA@+=xX7ZmPX?HqRxD$?1_Ij; zfqlaq=yA9R713$XskRHwHB3kAUpWw9B z;qG~mwL%v``zZhEK{6j6`z$$DNM%6|^k&gnF-tYjU_qU+q zb^u6Rjfeh^sZhG+9E5ehgRmX9;pm$JC~WM7(&;vQf=?}Us(oP#YNz{@kFD>{c_KEWTQxiBX784Y0nImxdW(ayMX9;${&=6>x&=I(&P8DppJ43K^^b~`2yj;vjpJ4cU&~O5UyO=vwhA>fCaK{2sWF z^yf1)<5?g*aWA39^GS5^)CU@0P(sU;M+wf^zb8XsIYETVU)p<2USRh}N)WqqtbqF> zD+o;%7noiiBghjM6|9gI7wkJVN>J)4DiEDKN{~HKL@U=R9Cu<%>Nma z>M=`-hNa}3J(nKX?4hO-E4scWh>X&Fs5~}+1}%eWl}IpM8StY&t)XP}Y9y7YD2{T666jIt zapF}^&=k3~bp6y3S|O}J+M)qi3GA-v|&4XOP6W`&}3u!E@ z$%4dZrdVuumrr@Biifw0QQ8|fFgkaLoEI)*(>zOw)0si-5Burig)>yFD9 zlo|SzT~%H~x#I7bZrMSqKQNk3`UTUCn8_q2nU`h9Jy;))3n%MY(T?^ z3eDd!Sg1noP4`%3^B|KM2xa!88d>p$MXXU!%PQtgXGx=8FvVHYti_~*dDj2sqh5*9 z$_o?NYY`PPA6&$8mdqx%f1b?Jc0Tp+CzyK2Eb?_b&BTP&NO*q~GbolL^BNEK@uN7! zw=H0cz6w!>ngkP56Q<DVt$@usnghw1>6uP^I~oG?6@$6HY>20qMz*L+95vS&sXMF zTfr;s?PFo8xx9t^2rJY(&ud2fWyMqC`3BR!tTg95FQz6;ZnYKsolhd9f8#gLKORl) zu4C9{sR`sZq{r%n5RV*rnqoX6SES{T7);76pfut05JWXH{<6bf0nIa7C7cte3 z#U_5v=b7sAnVg$qFsnZj#8vdiunw#H+{oYi%&R(yONkL98=p5N9g?%iX@VXrFW5jH zh8NkjjnU-4@jG)cI!{_p^eIR31eHCtC4B>1YCft@<*UX~wNVq(6no9ml2@>(1E<)S z#fSN?&z|yGu6ww&Hy=&>@9ctrsK656^93N0v!f(cE)SfQl)2)Y*FfgQ3=?gq`>-ti z5AWo06X2L1i>llKPBAAL#C35+4NlBy`X#Q?@)K|Ob37F7n#31YAA!2kPo}D=SHZ4| zFX=t_3_5K~SV?*jyxy{v;{#nR+{_Ag&l=R!ed2btc(IFjj=qO*fB`!)ke-dxIQdt)zX5N zHOpW@bOGdUehqpLTtZpihi1srhN-r>_3%k?sc-s<3wmc<1Uk(*T-@# ze3(l~A1ixm%UU{5vR+k3*0V(xvRr#h47ST)|DIBaRojU9cWiK#<1u`_H3lOm973;M z8Tf4JB2@5BL%ll#;8qfb(emCPwcQ$Zey-s3)yHDiiafqLj|cNTQaXwq*w( zaNk2#Ab*!Tp)W*%8yZTw3Z{_0`dD_MY#y06g|p_@vq;u2msKRFklN}?tm29&{kQEX z)68gNtyMZq|LqIbyReA&y!L{v4fEu)p4GDi7dJj|xSfgI^WvBP{KrNLig?j-F_LhS zV@|yy#2wXUdUpnx)AXrqAf=t9nv7ybvJEW$&?A0V(E~PIbCGX|y~>7b)OhduI3`l6 zU@DO~gGIkw&$(RJ;iA{g2HE6IU{}S%%Hz3^b59B%{rCWG-8xv+E{cKWR>-A^qu2b6 zsI<2a?lf=06h{WFmmScn?HGU}haFZ+psQdCD(&s#L?+6iNW^kJdG=ortB~QM9KO;@ zj*67`GV5PCEPnh3mMJ`~#A0Iqy^5aGAYq*XYJ(#XD>(^QC&}V$T#1iAOXJ~9TX5Oc zpOAjY6eED z7p2j@MYsy@K-H%P`@> zVd&S_#DA8=FV}D@*o|~Jv4#TjdvjI#15!l{s@ZhWkA;BM#vre z5|n3%Vqs%16zWaF-oC#uJzxgPE**{b4Rf#}K?SRCEx_(y`e^yd61T_9K#jl7sPphI zH03#>+c5^h_H%Hgei!(8jz!bf`z4AZCY4GSn>qbSuXPa-@2Viq{u z&NMIXWY%j_nCHxEyxTEgp=tox+m3VLNe!HvqA+;QyvC{SkcOxOa@>U1 z?>Tp)TO}4Du3XfCQ@pIymwJjauV7iu z$+(T*wQUKgel#gjoD~gTjblJ*uQ$jhZvxLQc`#qaL1~N;r#ZERYgzM@54(jWPH)dL zx!Ib`DWQpVj@)Bv`VW|~*eEL8w20|T4l*6BAEy0r7n#ytZ_qcW;d>80gZg(*xTyV~ zK%0wz0quNf_?80J<_6HK>IjA#V>rFL>fE&554aS+WIpPE9JIag=hrX;PI1G{l9rS5 ztfuxWAGbDU^78elx%8YJpzQ{;>CxQ7l;xmBLjnGDqjx;L z6!WFl-X_-RyPa%GqnJjiCABOW!_ItBC(lz!#ck7nGnakxP*_yL!s4T#FxH)Ui{1su ztKlv5-b2UJgp!I8afCPzj$c0&`%`7Xufr6V-P{Yds^kq_)P?6WPz$BC!v446>5as0CvI>lf3VN-&<>p8oUeIUmeh{iidwk zx1dXNEv$+;j17N2!7bgh7+)lbDei^1eYy#jPrZ+Obi6TZ;eGUqh`_?45}eT;iC5nj z;%1*vyq0hkUu->utqm9ON$XDBuNjRJp7!WHE)aXn=Ha8LgBTJ!5%aoy(ei;j9{IZ) zOGiyWcES=HuF0UCoeau3)OXwDZL~B0Z;L-?Q zDwj)i(w{=+IYaJTLncIxO*hs490p11hI~i(F);6{;ZtwigTM_9yjR;OES>(Oc>XF) z47j8Khi6)#HWvY7P8~pZjmHqTHW3>#6mjFYbTk>i3_l)7!zU-VqxPIL`0?FVY#bGi zi)PB1ET&xbGsVai1xvXY-P;d{2JU-r=n7PEli&^9n0=~fEy;N zSaYNYLYoz^et#28k5)m*tAR!8T3G4u2JBjApi4;~DDP6hM^Qh)hkk>1;xlM7=!KEp zIbh@d3EWdJf$)MS;G2IDEH+<?Q(*pBMf@FhV9KU`l7Q6XD!}wKb?;?cF|LwpF3JY-OCqHbyWs67MgRwJUGunuH z=ZgNaZx@ z*Vm>Fzi}iluTP$B-`JfelgaH?G+X~pf_nHdoa}?!jEg!Cfj@TfHCg50l;8|TX+B_H zb{TYjuHfz5RzgR@Q`Y)3h>y5zK`{CWbDnjKvKB5O;h7<%_&$Ud8*C?c=}>wj>q_1C z_R{MocC={r9%^1Vg}#<-rjf>WCNHl~YO60Xk5$5Sv`39)nU%20=0Vf=DJxj10SCfU zHkBkfuYi;nicoxE5ocG$L5JgfR%yA7b9w!Wsoqj#t==otX(^97ecBz!( zyp85}-KO?KiL`Z|fTq>uQRI*NRCDbfDW#Rs4pl}&GDQ@dP(oQN@@R>8A(el>K-U&s zp|JKCYI~DJYn!8~>~;Q%9?vL*_Bn@WddKGNXRT>5D^NK0QmBbk%mX{528wBkD{{ZK3YH0>e&c>^t#{Xt(# zT4-O$XKFd~iRyITP+0dnQlIdgtfHUN$F7%jW_LODOlYCid?WZT&*;*DFZB7y zI}*F!NHJAS6nCVG3}#kSSZW=$l=4)_eW0tlWwgttnPz6zlD%>TO;xO>c|Qs$YVa;C zAIK!DjalT-cY0+*j8i&8(zkvu`m><-iX@ey?Kr4QXQjU?}?JtUnGPHgi&(tWg- zJh@%ueRDqb9<(E)>@RF}oD%7uFJWbiud^_G&$3+iuBp5&tY%b6_p@* z=BY+|wUfw1bRB)|x<;d_Lg>zqC*=*;?elv7nj?{^oIqf0pj)nBEa z;Y&1Dg{OG21llguK#B1gl-Sox5i9T0v4$a%v3*5P7l{Z$ds^uGm{Ef0-96-8)l1oH zzmw0W8frh)K&BH)X=zdsndjc6KGUo8xc(CPu*)=k(J4~#i6IH=6zW^*O+6-zwmb+S zsq#lOc0n3#2`i%=uXE|i%?G5&XOeW`3o;nYrq1XW6fS*->OYi|TH77k?M5WkbcI^; zE6C>WWhya#L@6p)DM;fU#az8g74I+8%bUp*?Ve2jO2=tT^i@)Q97Le}c5q*3*r*+0=J;EybLyptTDlC{XDM z?S7I?g5byGZ<$L><1MvTT_u07cQkQPG2I;fm=1*q$j9+E*~aHl^v!hoQ+1BKf@8_# z+HsoI5lnYpZzHXvM=4LimR`$6kB(RYf(| z?$PFVPwDFWLed$zPt*Mi=u1vIjqJ`L{ToL};${?mcXp4)3VqT}*pUKB`%RvP3he}-nq*^^seI{h{cBJGMR^!iRL zMHQ!!n8X>Hs}@O*T%;^b9JiNtgwLUb3x`SZ+)|RA=S@zFHjv8v*@#HS+o+v}IUWKf8gAzUZ@qt0p59U4YA6pPzz(zj5X7$BqndH~YOmgLJmSi2x z>_x-)Mt28h_uG{-yrRTg|H|QOR+n)$7q7GW%@<0PblO`^@6z2$&#Wf$Ae4 zv0y1{;)aFk)e1k-yF8!HWJZzfA~!l!5<@N4$LOV)FRgzUK`os!_&KwLD=7ulrZTXYxStEVpAR}!zDy!#2Pg5ni&anZXM-&hsBq4A_Ah%O-7rz5 zv#Ym~SQL=l^P{BI?m=g|575EG$0+}f4LQ6#LK3}$%;u0i;gAz+{W_W?5@#?snFuC& zHIS)3TEq0*F0%fQqG2hYsT2#dprXXPE{@_aODSIp$MS^Q?I z-Gy+icoh?CUx=k0^C0ZNQJkbW2H(mYMRnLQw z`dtuqi%RM=!XR^R3sdq<+L)`ch`SrV277ljgXhJ~Xq_L3C;(%fWc-(%qrOlWr6>pc4s4a?w^k$1sW*1 zvImp}N|+hXz{{x!e6I|H$ka%1%bJLur3_TFG*Kt07g8Jn*G~Hd_;D9zD#_v&uON(F zWQQHaN3sf4shps_YD78Kqld1~QDWDHdumEhh*~9^Mg6GU@oW{$!ocGsdkmcH2;$>|G z?q>ryuRj0-W0!O0>u$qvjT+Z-QXU7^Il|y%J&dktg**Ig+&xbb_e|5ou%lD(oR%I= zUOEM{nk{jK*({W(L$tCo#g3=)I8r(bh0S?zzBL2`2aKVIKLLv6lR*PgxgwVw=)JX_ z+gu@z0g@r`EMFJh{&j=OLwCHWJj8Q1K_nxe)63C?4liXkY#3GI-MWrt?%mAlXFBi=1;?3NoF15W)$kT6 z4?#7zkE{DP12x}Wh3%JiV8ge`SVTT3F5`~UWfs^R=Y^qWl6W_JF}gph29s-}am|e~ z7`a#j7KU#iz?Z=2+%VV#KY_yUqcC2o4LZudLE7_f$Sr#c{h7_s;gJe<-esV1Z3A#= z;b38518RdKob{%&kTmKAr}MKK?3a3icU=bz94LZsQev1Z{tnu=&p|(RQEXoBis|+X zP-1)#N?zWJ12&QPCoBw~JxoHAYsc}GT^8;#jmQ3vsi<)-1<#5H;pNKHcql~^C7n0n zu9_QA)F_OZ*)yTV`WQqVkmDP~#(-Pl7FKQ4RKop`U`l2ySir_mD0Umya|y(qO@786|DFx7Y+K6jgj zIwv>dF8kMzx>XOg&4WRM8-Pm7ZCu^hWGHnW&nlJ5xPI_r_Dj3@tj8NzjkYJV`|Zkl zZ*6CGU(Yf92_7u<&P~=5bcy8}U1QD*pR$02%dF78hIND=V*vqo*}eIz`T8S4tWfVf zRM7g<{KbUHZ&USPSmMv?H^8GPNNNanf!7PmI6 zyCmR7IM)hQwDNpu=l-(wY0#H2>Ou za%fT~DFrKfTtAf_x5<+l8j@3s9BnXPPAkr75!<|vdKVg#TzoXet2mH$V**Ki@Fg|* zaC%u0MrmPN= zERc+X1ecGTXXY{R928?~!@9YzslQp&cjDzNkCDis23GdAlp_50P~grglF}|9q4n2j z_!gs|_8~NSFqK+qA^rMrfcjUxW9eeEX<*q_W;lzOaJ?fNnK*-i>qC~Cq|QWnX^Q)n z%{JdtptzqunV6+6d8`tqp#Xof`>H}I57J5V;!a9_a)atOU!Xtg7ijF9Y;vWoq@Ht{ zE{BLxYV-zD+Uw0;{{6#zy~P=qx{+BJu4NF{#S3%gY~=3}mTEAD{Fdgk%rrfUmL6gw zHp|H~Qk`6Wm{5EpN0~c1*dk?J(y8)gVXL383dayuSY*od?y9r;nGQ^Lo;Ora8sfcT zh0(<~8o>1-Wfl|2!dZ)@?R&#?jRC!$k5P7s&KZFQErwU@9;{y&zNHIB7b>9E}O5^U|ITE6k3D(f%^=0S4~ z%TSBp4L6Qu9TP6{GB2`C-Hqn+zYlpq!LJvb=EVEpESm~#fxp1Jt^+i4#nAVm1R91F zL0G&LuDmJUqb)pA-8z)N;u!Ux@}c~Z_2l?r5B2FTq(PBoG*UT@4hZQ{ zs=*is+b4pwg@d>>K9bqq!p>-?kZLC(p&&kZ2sR@W9Z?`Dpnd0TU)aM*VYl@uE{1 zo^yDHfvKmkxbrbajnzb-2j@}dMK%OX28&H@W4mBpVfm0Qj1Yy z%_sEPn}~iUgbP?O=Jq9HVZ<)Xw>*JzVf)efO%T4kmw=7=$Iv|YF5Z2VjBbT(ILC&e z$1(}CaYh}eqpM(6zHW?}C@*cMGH!xd+P+^n?!-8=BE4pm?H4g?Vo%Y*@H-0S<)Pj0 zR_rN1h8Nd8M6GfobTB%P&bNl3*ncaAmE46xDVjJ^nE`P>e?nnV2^1ZF2`)RnL0)DD zJZl(*iqGY+V^%XrSWm|2WyO%8CV}Be4FGXnkn~d$&nJnaZ1`lHze*Er4_c$J%>uMt zb`Im+ol*VHJN(&r8R5u3tUmS$_wW0PkSc1X?p1~F=M15jO94KRevP|y(=b$y@SnnY zTw!(%D+8|ML9q%I9GQS2Ow^ zuWk1jYDO=F?E?zvf9DH$PBca@6%998?=L!F)qCyTvixjZk!fI<{M)9ehd7Uy$~0#vA{#S9dP`$B^Z4u z3@fwOqx8p1_);YTu_hZ&4P{^te*)Q1E{2sD;of5jsBcgMFZEVnRHQu!OZ9_ih!${Z z;czxF5pc)}{6>C5ocUGg&X|KEr^J!HT8VdV8{qNNt5AYgV-RnP)7Gv-1L>XUnCXPx z;{x%p{XPuo^u(RQ$8c_-6aKgRAVwItpw4`Eoa?a*TU$KQsW${q3j3kwhh#Llb{wyq zEkIF+RQ&UsQ2*RrJgQZS0aXw1u6O~a{CS9rKOMtMLU&P9`WdXe8i|$se{7`s2Rv&S zMK*#~-hH_`sTF@@{0@2g>nl$q6SJA0vJ}}>ah&GaWM)|Y3|_AF=Mv+mq21l*@bSPD z%(0%1{$B6k*t`EpXW--_c9@s`O8TsaUH2` z{>-@4jpWi?%SqgnqP(ne=n@cC>@js77Djx5?Y)z*`k4xH?Mk@0;(z{md~p=2y2|5) zxUrbDL>^yH5XEO5%ka)85ft4LhgwP|_|hpA9nB+go~K2}6X<(lCXKhZqFt?LXe8nTgDgkVm-J&D;iG8f zg|j6#*V0&V=VQ*UisxOLYx%scU#3dFiOgJKI%`>Sf=}|k$DB-}q41?Td%GzN^v|0@ zLs1Zy)oup96w6sm+;3c6b`(a=yfju?SPvbNvmi2P92VAOfsQ~AeI5=#yp1N7=1fA> z?m{Tfl*g>Y`OFCw&UK?AQmH@qla9{=%zI^HBrTvA#?WRo73%fx>6d@UFSLMn|h;)DMRk)7^MNYb6j z2EFEDYV-z}H`M`EOJs0<*8+5SG#^X-szBC271uBWUVqGGsNS2&UalSD>mEt6t!4GB z;aduL#RfC4@!B{ny#V}}JNkNyqv+K@JU7k)`*WR8McoyX{`?;ccm5A$|Mqb_Q$h(T zLZnDFQbb0X^Y|pRP>KjGw9%%G7TSQj&1fssL zgY6pa(6jR-=$RO?+(~yq*vE;j3=ptvL4%hj3Xp?XgJY6C=ARX}3S4bHmvMKDgdgRVv$lXosz zPJWZ$Vr0@qGEdz^D~FU(`;n`pmtIDqdr#=?nnKEGucptpj?ofOP8v% z_VOW$w`oPw3u{Tb#0ke48&i1v3=}zCME{XL&^R|6Rh0AT^=ExLXPQJ+k2lhI#VM*D zaDwJP&7k$0@@Vs;qZAc)mF6{Xqnhjsw9IcfjoF_}4Zr51?rBdlUosCo2UenBT?>R7 znu(1Q?tr@@5vt1$@Gxx|sD7S64kM@G2dyl+ukfJG!4Ifu)fIZPUPhM;o>5qQEL~gt zn7n8ArCUQ!Q)G%6w#*Te^j$LNGLOgH@F-e%6hY>iPjHXDDfPMZ7yD-pq`);svsgH^xr~l#`DQ-M# zq(YMmqbYIdG0eVfL+KZNvE#^h%v>zOsC%Vo!bBL+b{#AKn}(S;uVJ&*evDgv1JgU- zpz&5E-rQtPdLsu>-`%rlk^3|XFkedkFV+(*oJ|hPVrb_oRcf%>N^PqH(R-^cRS!<# zqt;Yl_}R;1*X-p2HxW0Z*t zcI+LC))(`!q4pHQgy9qx-Grw^t4U|ABMEEQ(4)3Jbam}i`rQyquVaN|w=#$Z+p5y> z)pIE5KVw|Ca~#2hEC`9o#qvF-Orog?)8|ZNl0F|Gz1oTehHJ8t7eaO;NsayS5it+# zzHEzw2MgRZh;`0d!GwlmS>J^l*qq(YY=6WCb}M}@+v&B5-TdsuGQ&5q_;2%>tih9^ z*#hRS=+6$n2UgN?5KMCZ_hW{nu7Z-d^Pu-e0QdT;vrM}Ln6~ma{CL+1&Su9U=e z?OqHL%_K;#wu0cTv!K=Iv|PG#B(xdNN0)?Hd7#HlG%xZ%)$=3h*UGDy|1q3m-Wt=% z$*J`BZWzUGJ5PNV93^q6oK!t>sc`{MGiJ!?=fPw2Y9rBgBO40JJweV6F{rIGg))=s zxSrB;s0iu9LicEM&1<%@w3%|ep=3HC5!tz;&RF<~3Zce9@L7a?<)DYFhq z1;x>;;9yb#_GeDR+vY|Pwksicb|!?_e}}eMXL;@ToACDNTeR%*;L^_qkm!XRbz@S= z>DNpeXr4>{uajtTNCw>)l|h#mC(%5oG#b^kmUhVYQJlF2-HHt&w0u$juOpWm)f^!Kz1$9k^x9KCK+WwkFSH(dSpds)M7MX9b7c>(j7vl`5$> zT;+@J&!;5oXSjC%R*GmA)9Y;xl(cgR3HukJv}zRPEHcGF{uHVVeY1|3J2Rp-gEWGd~10uoP6rRO&fll*2D z*$i7j{*t}q)q4@i#Iwoi=pwq=?LsXpM$xCY(@3TAB^I>lQev4dsr)F!g`-zf=EHBu z*=!@nU=Ip7KY_a629o-N3RL_up}5@H=-F@{wQa-XijY2NK0?k}9$LzkUGe6H>&8Lu z6gh^B8OufV9!|Lrp8m33}W_4~~z^$|oTUe#fYEONGqIE-AMtlJ{A?IR!Di+7%=tP6q)(yO*Q@B{i!-G9{SuY0xXbgA z?OEq3FCm|5Cf+4Ui5C@5&n6QaSDfnWN`k6*h_f7qiK{Z8q4pF=t%m})nxOKzu2|A% z4R~IQ!G?Z!xg2#9s_r`iZMXQ+uz>>F7`vV#n#B}ycmwTN??XEWEuhrvex#Q^lZJeE zAr%*nn&(fXk6SdTO3#v-=TAg4t`p-V{UI{(FCQK>7|aH_L7Dnotan@mXP1m7lU6lO&GQ2-U^z5RaXMCx)WF}<~UrFwJ9-^U}17$=Qi5(_i#pX3zp>+C6E-qm;2nHPo zPfsn7Ts{tI4Z|R4Kp<$(R0D^s%@8N)kC7g$!J)eiFUy|F#nby!y}@-%YkQB~Z(n0X z&o6Y9UPX--A+{>OMt>=|8b{^K?v$zJy$pKDzh+#H)Nzpt-6azesaD z-Jy7VJ$o4$%eCl&?mlYh=S*icbExa%1~OqcsVw;zoqThGelNd3OB3EuZY6!W!e2H5B4yU&fe^6Cho6gqsr5PQQ$Yek>*3CUk$$tzfe#vc$p0t~uhgVU# z@B;n!sgCYd-JzW;>uA#8$25Py1G=;02`wI&O@{4qQq?|8ttuxeEJ8vzTH1%3LfW)p8%&{Gb!ltF6es;4qs1XhccT0gN--iGDo~F}`sH zRu9#rOr3nRFtMZLt}cwycc+p!W|UrSMRChGQVV;CaZk+1)7co)AINa?_H|-GpB}!) zpFy0l6&KMj9op|MfWfwLkmqn2{OksS-n|S6Qq$&whk8Ps_aUpa{0v4 z)fD*T6&h|nNHgN*(I$rk`ul7zT}@d}%EvKe!bGIqx{RWxx8t`%R^(MX9&7v5W9V-H zt$IUrsrm@+qvyiOZz}A3{tsxVxC9>R16cAOLq4qi5!4o{QNVQICcCX6_jPaZtaS_> z)AA;b&QJ=Jhml6bG%}F|kxs!wG*G;@}cZ{S;pK8(o;{g*K0HT+f z^M1eXT6f()=RVKO?Ad$IoRDCKrLv!w?0UGZVTKFuv(rhDr74%+%ir~d+J^lL@AF}A z1%8w}bVX-M5XLX3=6BS8rxfK&*;t+G^kz@zIg)QI6EKI2NK{>kY651&@r zuJ1t+d^P?7?Js)x3HLccb0yXg?y;%S&R--b5AA-+FDb}AF5KEmsL*tQ4&sL!g3-)< zm@2RDgHxZrD-|B-tTU|>E8sucRv*+W=@)uqR9G0FUZrGo+vKga38HgHgocBuy@q>2 ziCok$OM-df+`GZ{O1k_eXIbKaRol8(~udXeSCfJ&R>5;r&lce_Qn^KzpSn4+ERvwynKAl&42WLyzj1=tS zI!8{dO3%n0aG6s@yx))iX(LK@P`G`-9BLBq>d(~c{$S9*&K7qmkS+Dr6MXR4rT%5C zoQ#4sc#7-mKan$?OSTkoj=vd0^Lebur!Lsw^EH?i=$TL`8F<(2(`UpFTIy=ggV3x( zt~2+o-26;rMn0-&&`{*8r!Q?&fHSVv5iHHhLun#Han!egbl(CTsSG)=AF-U4nF%H_ zAH}|P9!yhSBJ%iZ0yIr2D_{{};@Y93^j{#w-!NYBZPq7+?QWFvHkW|2dJ(ER&MXoS z9|NF3v1O`6WQf3za%%>!WhUM~vwfsC-q3g6K%2zyP}Jq03A#w{O&osv{z zGK)3P@uV%MfX}c4?qOSz@gmieRTU^49ZLU%A4H+@{znqjNSW>s(`gr>xtX#^Esq=r zk2-Lhmct|=ti8)J5~^iv{%IRu0Tmdi>a)JX-)g!={yZF<<-J;Jg zR2EFlt(V-57iOrYYgmsXLZW{cCbK<%AjRG-1??&+Fi#V~+hmm)nVEiCFHj5j#RQ+k zAN#?xVCFVT#(>oEyIt2{1h*&U?=63ePdZ5ezMM~i`1P_+o%8sKt%~pw>vUh=3;ly# zWGKKmP8Nov=LVkN?nC>3m@2E}}uetIm_QHvT zz*@(H1+ADs*o$sMiIQkS z7r1%TMdUC8kwI+LcU~?axlJyzrv@?hIg)FpgEs2iK=f>YN5#4o=-p=!H=J5K4bC>( z>4wMBS}-$D5u;zOVYHg^S$;8Vh!}{V@FA?VrYmBd27h1q z=kEDtV+N-Pt2eVqD%}$;Due7gV<&hpZtuSXq=7>{e*#KP_Z*typW)(~Yf zQDBoPVxA&fXay9Oy2}JAi9J}!J`Hm1HS|x`5l(qMbpFH9W8v3Y*3lF^iDE3s>12-d z3S!}&aKSFxoih6G%6g_JCteEMrM|&TTyrm1LR0Ri;b~?rh|VyGR7N~4Z<*A!LouR{ zdcV_Xyg?VNDI*ZnBc>Lo0*zHB`J+7M)W;U=i6i_AkVrC-V&F!@xjdLual|uSzv)u- zutti$ZMF7r2Ny@Q!KbbW`Ygl`>wJ54?k%$pe~7 zb0cm)uoe-f(p#M5?ij(m2?FcotD}!~L!@~~!7)5|>*fv6W0}Q1@;t=KtR}+A-bDFN zW*p%k@UwQG&Jyn|C3Bk<*)^``vPKA$JALGQZr%^_2gN6Qo}ZAq$y1<@)*_XBu5k1d zM?ziuH1_v1eyU@l_AX%{24moI`5jPTJQ#*s!oQ*J*oji=^UPQ2i!F zcA^MN6XEkh{2k$7-(!e3&9*M-^4^+6?Qsi(j~M9IHcB>#ZyvQNHhCkeoIk*`yt_17 ziunjuS7QJE&=$SQ(7WOPO*xj^7oEN}92Y82(?;9s51@<1j{>}Yxg?`_LsHZt?GW(> zIMw8)D2L?ZG&4_bo~~m~RNHBjIpyZM)>Y@^`t3hbp%P5D51+Kqru9fml-0$BTF6o(6kunSi=OB8Qq(=piz$aseioFC9`}r$^R8&C_g;Z zaK}yRa{11m++iIEtjr6qv=&CB;V}1ybyEb|V9s?%N|o`E1nici{AyYX+zzfnW-sW= zQAWzCJh{c=c|BSwrow!0HqIZl=q8u0b=CD)MGOnI?hgE_z6Xr@7rH@e+wPwJ^b|*{ z_aJW;|Fxd<2a@Z?PBlgPM%>?MibX|EHoA!Jo&DmM3lvU~c2-@y(F^q+hML}69EZ2> z7#&IpAbe5`ey@SR#U<*C3@}Zy`NnuWGb^krg{oBCGd?-#DSdVZpr-4LdH=<|!0t)! zW{;xOQ4tRv_$W1bW!Pl#B5AvRf!w#zoNLL&(s6{Uk{Bw`kO4t>y$V3k$WSyfqdoG7 z8n|*QIw9yp5x~G!vN%9zWmT7L9>Q7leKN2F^M(1_ljF7zX6b${lp}sY`h{7AO4%~xHTwNLD3&}KUFCAdW2QQH|DMz%o2R9Z4GcJndMo&;O$KnY3Zzx7&R*MBUdvg~IuO;6Phh z%Z_dsl~&Kp!UMvzolJO9PLz~Z8qjqCt-z;Rt2nBO@BVvK$9FAId(X`U0LfshaHz`d zP>&q?`tziJla4Gnu+hN|23tc^`PUJ01m4(OKj7v#O>>b^X`)ky()elXMRH7_2NitUIev5~`kx`11|AC{T6#vm zTzrV)G>vAJ7h%7&doc%JaZR?!_C$#_`C#Sd4A=bK4u9-!xKU5$4_@^h`QtDk#kUbB z3~B?N9b32yX#>U19k<)`=hr@WI5Qi?{EUR^LH9@&8YF(HL{dTjge}>@BK1Rj>Lj9e zudSl**$H}N(nMkEr(j69X(;1{FYkYlul@zd zZ|dy>m1TfKQL`CGRsBqHnnd|zt>^pH{oam;1^)`869^D+;OA}4v(%0L01Q{)5`y(u z{s`Vr$?vn=XH@0w!4Cm{G~l^=NNwLnZsmWYd`P_5;r193*4<9wRkNM2*vRVl!|Y~|z0*6KrAd(c2TuNpzpT6oqoBbt@nxDOJk%nn5bVN#16IS?e(_c&lU-!SA7ql^6B><%XLpPr9bzF_ zNL~l^MK*e$FYriMVIBOJ>%>kEdsGQi(Ypu8-wqyyg`&! z+(sLJLgd*JbCz=02jIi@{cA=3W!t!eR}Chznb43qDm7X`hzsAeCqU)cKKkWlDFhTH z;3ZU6K{o7-SDW7#dp7*>MX+_b>R~}i_h(tm>0Nqwqy7Ydt~T4_b7$a>l*?~XX(Gqk zJ}EQph_P}5TwHudb6$ow(`qUKFy;MyqRrv^1&@rz>4AaFYCROr^I3h1M2Zo$06e$H zW1d^aqq^s6d{8F$RCF_G=oovVs(}PsbpjQcDcU2g1JUJ>Nvlr+`XSvWgB;F1jMYa% zZ>u6jtdhoedgwYL>Q@N@G93iP?G=Mktuk%Se|Y^{P>V6617T@ubJr*QK-f-dmBs)B zX@MxQ;Fy-@BGR$JdMgu^dX03Rj~G+}oW*7{F)NVw$&W++YhM%po{5jO!NI*MhQgb9 za|&c-q@q7#;Ph9T=&I=n0`MpIssvO@f*?SRP(`<`0uz8;_aF=Y*VW9sP1)JUMgk*F z02$u>nMgCpQN0tTM(IF#;bXrZB}`{hl!9PPz}UQWFuCYko#pY21r%zTlVrrR+n z;EQZw8J_qd90B>np>e?%zRV*kzalT@!7~Bbrp;DpYwYd8>r5ZOWZ4zcUIRt>1gNS(Hht>nK-F8#1JQYUeD#TjBMN7_-)f>v-!6wa3Mm zvZUn%r+t+E4kSFO)Q1LEYfH^=1Ohy}_APMS^;tncJ2t+7XO>4ft2%ozFJA0Rzjt+O zao!0x(DknbKv``R>kY@4?Mng)(CjZ)`8I#Zd?w__Oq^w+f&8TY9b864o2)A%FRd;? z=Wh(t#R>=i8o~+mEYdp10&p{y1JYzDkGxMu>H2Wr05!XIy{Xd115qaHzuC z5b#ALQ`t~L`rJZr_f_h~JOCtWN1xl^p?cwS?^L|#D`LKE0XFB)FX09k4lurKgx@JR zLI-3APLBb7{AF<|S&s3cu+8BKYFGO#Jmamc=VT!dAPQ-(aTVcdu-Vy~x!N8uWaPTN zrYixgN35cgU(g2cx*|JwEVFpq8SZkOgAyUA2b%nSok0$FP}agLMQXFf_Y})G{K5@6 zp$beKuqNbhtIGADBL8yi-yAGc1!|yWTvQyDXFO^Fir>K9oK-8hA#Eef+*F%js?&qP zP$J4m{i2%w<((`Hx*P45se~g3i#g7QX~j6b`g~Qyfw2SavcGs6%4~kuch}*AcbVOr zmg>86+Q6}%m$(z_uPdGKGuwd|UR*8fQa179ZY7^)JxIbimn_)d8GRXW)uHR#*IY|B z_v*(hrmHd?t3gx(%dU?~&3`UUw7Mu6SLkpxo~3P?9}{3<*CTgcmIIb>`1c|hyug3A z7<9hIyYC#4pij^QwAC8Pb3RWow06QDW}1ORvWqM`l4o$9NL8hIefaTXmFVnCrwAM{ zFURz?mBd6YF;pMv7$x7HHMIyj%=&M%4FxtuS$_|o4?ev{Fbs%CXIyfihRx0jpSrIJ zd~5prl{T{r|G|VdvZeooNm|l_CF`rh#}A-wFE!*ETKBG5FIYy!Q4wg-e+Pp7_LH=4@1|| zv(c^Pwn1f7#qOO_9dxlg)eWb{=hYf&R#;Q@VtF=fpTAAh zV^8_0O9%m>L@R8@);P2ktoi=k90N@lD1XwMcLbk>@@Df)rqqpW|T_t8mWEqKyzilt$L)OAdp#>wHY#>E)$k%AZeq~=JgyZ;E=)je=0uaK|>5#A@3RA`LHD~Zhyj%G>9z(+M~7vy!Uk%mG!uo(6HZeI=pKzvPB|brN*6#d^qSM-Av)$aOnIuU_u{wr-g9`fT>iON7B8 zoa-qwBNB~UH#*>lgpdEvL+RDFpGg3agZEmAMaRP%#;N2sSiAmH>G{HL&yL&w6Ku|F zo)-J0b2Y^OkArsRn%rXe#cuF`ME;flw>sxZ@@9oRooAF(c|jd$M+C`j@Zh#I=Mg!Y|>+9w5;T#RBYc#+Rq|_ zOLSs?R;!CB=9f`V>Hpkg}< z`LXTo1cAJbLz} zoj}}MZzM%rclTZ(#L4GgIzpJgSn#q*ZPUr07?n#0OlOF*_yljv(c3YPI<^kLjwiYr z@aVGMr8kaT0uI?+Vszz00%!Z?RTbbEj zF6yALZ!@WU&WdL4Ce^g`irLdM-eUVBwoMHlxd=O1ZBY59c!G8@PLYcs(b1@&s`>jLE(btc8GGs z|Enll!1XmA6SHn{gb)yoUvkVm>j16S9LIX7p8dm5%{6Ov-kR8Hdw-e)fxAwCpM+vn zAcOktw6^DO4DE3?MT1uPh!W}ubB_l;2Gf#1mrS#Pk$6UJ0I{-q**J^jCv&<~B0W)+ zRp9*S55ola-P~u25X6#!%;rlDenw_F-7{9Oh4t7Q;UeUApm{2yk7TOc)#Io9pimtj zF&aM_p-OkaxKDmF5b5=nxjNg6aA0co>G`Jk{FCc6EV8$YAO6aBI>1hp-MZ%$n;VCP z_&Njm-1!6QpAKDdD`#Sw?<<(1le0#EEQ8B(A?ih;$m)+A{>g%kFuE@G#4g|RvCor? z`rJ&09aaY->6$731-A`lV>}EIsWo3D zUcPlB(XzIW;H#F?Cl4^kK(>$nuMvxQ#VW3!M`}ES*AVZ*(Mvl;02IqXVu^XY`|9gp zBwu-Y&me?}(rw7M1h3RWg-{IwtzH~~X*015$OhMZa@v2YG*GOeO#9*zVO~zyF3;wH z$2BJUK5w8UH6-7AsEnYv48J)*R|px5_zzzfC|oyVUd&{M0FDBEiX_T zs8O@}E=IiSgOe4tyV3Obv9SIjTZj58vR3ksa0Ad3a=fMl2aL$6(Au?rh0I9b5JAZ+@z&7LaSyI}6&_Y-Q` zy**qtL4XWx0YqsShLroIh@?Hsp`S9F9zlo`-H}(Gn|1CNR*CLg!ng~8sgxg>(YW}B zMo*MRin⪻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

      &T|+%1H#w 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

      !(eFw9#qZ%x!SW)q`b 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

      G;DTy*LR;c5lYn=-d? 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�U~BITAc-}l*xzW)lMb+%R}C`-Lx@2}cA-YR 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≫SB$)tGQL5@)uDyF+ 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 U*nb?234Un6006_!I^cKz2l{pqkN^Mx literal 0 HcmV?d00001 diff --git a/osu.Game.Tests/Resources/Archives/241526 Soleily - Renatus_virtual.osz b/osu.Game.Tests/Resources/Archives/241526 Soleily - Renatus_virtual.osz new file mode 100644 index 0000000000000000000000000000000000000000..8a92423d355234aa3fedd8ea5114267ce643996d GIT binary patch literal 445694 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%0Dm2ChZaLM`iuUC2$r{Ve{C8Qis_%&< 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

    1. I!%-BLXs?HGnQ2 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 z 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

      fi)W+%lVm?iqS)@`f9cSf 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 z≦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 T`PbLcKkkJe&m@Qc_45A$?pR2? literal 0 HcmV?d00001 diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index a57405628a..c6eb3ae7a4 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Resources public static Stream OpenResource(string name) => GetStore().GetStream($"Resources/{name}"); - public static Stream GetTestBeatmapStream(bool virtualTrack = false) => new DllResourceStore("osu.Game.Resources.dll").GetStream($"Beatmaps/241526 Soleily - Renatus{(virtualTrack ? "_virtual" : "")}.osz"); + public static Stream GetTestBeatmapStream(bool virtualTrack = false) => OpenResource($"Archives/241526 Soleily - Renatus{(virtualTrack ? "_virtual" : "")}.osz"); public static string GetTestBeatmapForImport(bool virtualTrack = false) { From a5c23e7cf793c91d91bd2b67b536f107e10a8ec2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 2 Jan 2020 11:09:47 +0300 Subject: [PATCH 4866/5608] Remove underline from breadcrumb display --- osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs b/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs index 34941c5647..047ca5eba2 100644 --- a/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs +++ b/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs @@ -25,6 +25,7 @@ namespace osu.Game.Overlays { Text.Font = Text.Font.With(size: 14); Chevron.Y = 3; + Bar.Height = 0; } } } From ee332e0d424b0a8a76efc28b413208e14f8b1f6e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 2 Jan 2020 11:46:18 +0900 Subject: [PATCH 4867/5608] Split out BlueprintContainer functionality further --- .../Edit/ManiaBlueprintContainer.cs | 28 +++++++++++++++ .../Edit/ManiaHitObjectComposer.cs | 21 ++--------- .../Edit/OsuBlueprintContainer.cs | 35 +++++++++++++++++++ .../Edit/OsuHitObjectComposer.cs | 24 +------------ .../Editor/TestSceneBlueprintContainer.cs | 4 +-- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 15 ++------ .../Compose/Components/BlueprintContainer.cs | 23 +++++++++--- .../Components/ComposeBlueprintContainer.cs | 12 +++++++ 8 files changed, 101 insertions(+), 61 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs create mode 100644 osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs create mode 100644 osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs new file mode 100644 index 0000000000..9cb4e54234 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs @@ -0,0 +1,28 @@ +// 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.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Edit.Blueprints; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Screens.Edit.Compose.Components; + +namespace osu.Game.Rulesets.Mania.Edit +{ + public class ManiaBlueprintContainer : ComposeBlueprintContainer + { + public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) + { + switch (hitObject) + { + case DrawableNote note: + return new NoteSelectionBlueprint(note); + + case DrawableHoldNote holdNote: + return new HoldNoteSelectionBlueprint(holdNote); + } + + return base.CreateBlueprintFor(hitObject); + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 1632b6a583..824c92184a 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -5,11 +5,8 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Objects.Drawables; using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; @@ -52,26 +49,12 @@ namespace osu.Game.Rulesets.Mania.Edit return drawableRuleset; } + protected override ComposeBlueprintContainer CreateBlueprintContainer() => new ManiaBlueprintContainer(); + protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] { new NoteCompositionTool(), new HoldNoteCompositionTool() }; - - public override SelectionHandler CreateSelectionHandler() => new ManiaSelectionHandler(); - - public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) - { - switch (hitObject) - { - case DrawableNote note: - return new NoteSelectionBlueprint(note); - - case DrawableHoldNote holdNote: - return new HoldNoteSelectionBlueprint(holdNote); - } - - return base.CreateBlueprintFor(hitObject); - } } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs new file mode 100644 index 0000000000..a6a7d9bcc0 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; +using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders; +using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Screens.Edit.Compose.Components; + +namespace osu.Game.Rulesets.Osu.Edit +{ + public class OsuBlueprintContainer : ComposeBlueprintContainer + { + public override SelectionHandler CreateSelectionHandler() => new OsuSelectionHandler(); + + public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) + { + switch (hitObject) + { + case DrawableHitCircle circle: + return new HitCircleSelectionBlueprint(circle); + + case DrawableSlider slider: + return new SliderSelectionBlueprint(slider); + + case DrawableSpinner spinner: + return new SpinnerSelectionBlueprint(spinner); + } + + return base.CreateBlueprintFor(hitObject); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 49624ea733..28f7768aac 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -9,12 +9,7 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; -using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders; -using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.UI; using osu.Game.Screens.Edit.Compose.Components; @@ -37,24 +32,7 @@ namespace osu.Game.Rulesets.Osu.Edit new SpinnerCompositionTool() }; - public override SelectionHandler CreateSelectionHandler() => new OsuSelectionHandler(); - - public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) - { - switch (hitObject) - { - case DrawableHitCircle circle: - return new HitCircleSelectionBlueprint(circle); - - case DrawableSlider slider: - return new SliderSelectionBlueprint(slider); - - case DrawableSpinner spinner: - return new SpinnerSelectionBlueprint(spinner); - } - - return base.CreateBlueprintFor(hitObject); - } + protected override ComposeBlueprintContainer CreateBlueprintContainer() => new OsuBlueprintContainer(); protected override DistanceSnapGrid CreateDistanceSnapGrid(IEnumerable selectedHitObjects) { diff --git a/osu.Game.Tests/Editor/TestSceneBlueprintContainer.cs b/osu.Game.Tests/Editor/TestSceneBlueprintContainer.cs index 5ccce5b3c6..67b0b61545 100644 --- a/osu.Game.Tests/Editor/TestSceneBlueprintContainer.cs +++ b/osu.Game.Tests/Editor/TestSceneBlueprintContainer.cs @@ -9,12 +9,10 @@ namespace osu.Game.Tests.Editor { public class TestSceneBlueprintContainer : EditorClockTestScene { - private BlueprintContainer blueprintContainer; - [SetUp] public void Setup() => Schedule(() => { - Child = blueprintContainer = new BlueprintContainer(); + Child = new ComposeBlueprintContainer(); }); } } diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index bfaa7e8872..536c7767b7 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -95,7 +95,7 @@ namespace osu.Game.Rulesets.Edit new EditorPlayfieldBorder { RelativeSizeAxes = Axes.Both } }); - var layerAboveRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChild(blueprintContainer = new BlueprintContainer()); + var layerAboveRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChild(blueprintContainer = CreateBlueprintContainer()); layerContainers.Add(layerBelowRuleset); layerContainers.Add(layerAboveRuleset); @@ -147,6 +147,8 @@ namespace osu.Game.Rulesets.Edit blueprintContainer.SelectionChanged += selectionChanged; } + protected abstract ComposeBlueprintContainer CreateBlueprintContainer(); + protected override void LoadComplete() { base.LoadComplete(); @@ -323,17 +325,6 @@ namespace osu.Game.Rulesets.Edit ///

    2. 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%0D;^O(DMB~uyG86?ePXE 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

      H`;ON?n1uGtn14g|4{J+BBqnH~2QHjp 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�TP;91oQyV5pd|%gKEfJ3tkHe;Nqc z8g6EYumy3Q3wE4%)YtzNNndqYmQr?69%QuDhM=d|{t~yTT&H88B#URwn=Iazp|?S` zOJU*iEuCVaEb)9Msr~&`ZL-;BK{+wUGiI*w+!W;D6Dv6ksSW2NsS328@R{NYf}Ted zH!pav%DqZRb?X@Zs`++kzE+8WAgA}X?z+ugl|^BQ6JL4e86XBiM@wT>SnXj-_P2Ul zm^YOPpB|Z4912UK4fv8RaMy}fh@GcF+lm(XTJ#MDczlApM1HfyAV8lYM+2C4)*eP9 z5#q^e1YN82le7JoHi72)%m0yuORZ5ofj93eui*&fTKPjbMc8yN)fcLQRU2kL<-lr#F}5qu)S^^eLYpa;k{`hwWQzu z6g^dv3354Ql&27lqB~n#(}*PgTf=|8k<(+Unwm_dL3{%9GS+2{q&Vm9J@^*jF7fmC z$x^#a16RlH<3gd`ryB2R#Z5C#<{L{q_TmJ2Rxg^_)}YX6yb;=?85%uBiRF5AUr+Yw z?bF^;werLdr}t-NxKwh|>7e3CHiK&{SBM;8o+%;F&dwYC2NRq2PY4SMz22uCu;Al; zhRy)GpxfnFhd~naEG_;tfm_2KjKGP~PtYkfmMW7TR*ny%@PX8i!S&-5GxZ4b&dUI`B|onjK3qhhh>;a~%a z6(3j733ZeTbBIL^<3+TjQ-o~2r75f0*>CJB|?ZSql>Wly(sbiI0Ds*lS%EpZD z1~PwQKVXl!Ck7&jg6*am#E7vsbDVM#F5c$ql2(Wo{ZW;`8pcFL0c0(!Cykh}we!yK74@)y{TXjk*7sg9^IfsLskf6VCC!aUkzMWvp*A94FVQbIxIRP~bN-lUXkap5 zbs4i|8a4Nu%;vv-M8*x@5KnoKKDU|#Y7@#9hP-DAv0rjnB>S=%fx|s8E1S{LOUD4R z*lZ2#pONX!J!tA_bHifRT5YK}&eC68bE4l_)91s`ZmH#kt`;BJu=hPFchIERSqR!~ zMwi92u{Fo&|6Oh(mDWIIQcn;ansB5!nA7~&|Gif2>(|0+!Fq)nN> zw@kGXmzMT!iXj>2^a!Tgl}M%q&516SKOD_wg|c3>%}5K1YW{B4n8bI3R0+*M?Kfiw zPofEBi^r*l$<57|1;>-+2@hilzNw)Mj7w+n;-S-sP4}>zlz~Yv!jBBKEhcRdoAt0c zuZ35?&;MIu#RVlGc8Fq>uG8b=GNfZviS|m|Z5u}hp~Cfc_u0OrM9qbyOld?C#yosn zWfER_dd(KtrL0EI7m97fkCq;O^;@h@twEmShaMLXdPKbWo}up*xOYt1-;ExcjEsbH zI+Lv?&mK=@z|MsH6Pk#-Sc^Wa&ZZqyZr>BdVXCJ?G3rW#lnd%VXTkR11kNpYF|58K|$-SxG#!h%_5}WefoM~GkgOKVKi(VI8d65i`HK&VP zsiI$!GhIxhyFs~8tF$fq)z9*JoZ%}Pub_6B@#Ldc;Wms3)Mkm|#EcwlTwdfn68iiK zud+hkv#@c%-oNAe=ZBlyGS%0DNY15?EuQgmO1iV%i>uhr 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≫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 z zFLiJnx;1)OYP$hq9-P40A#z~%Cmk1r1d(TA#W-#F}zbl%}u{cjwP%n->aB1(vq z@SOWrC=Hd8nMg^yNYS97VGBhvBCCv+26@isevFFJP)0+VBBi|t-{$Z9{&Zbjmy7e9 z^EvnZe!pJkxZOIC(ryax=M|=8pXZADv0`?2mji~c-7nTJ)IleWUz{5@T2zsnL`KuIbqY)WkSZ{8T`g&wC1!Dx9Xk? zl`U#zGIgdD+~!5>)id^_HJi>jjc2RIoTt{8jhsX0EvmI@h0-f6WOU00w#bI8I8dk^EkNf8(#-6Hf-1cz1p zTlBYX5#C;U(ap|=8+i5uimVQ^W1<$^rDRNZ0}C+CHiT*q&A{i!(`jsKENI>;rKM}P zvpY9VQ`Ki%^4WTn${N$je!~HJdcK;J=dYrVwKwUvtOCv1aFuG6Zt;`g6sZiagqMxc zz9~8s)uh(!%g$EvtYQ~+P58}C~%eehtHF9r-{ZiXa zJQ}_mL)EUM@)KQ59xeEK@7ltCfxqQy8pFCGEpW`kvGm7#IYh|E(Cry9taIs6I#&;r zwV;OHp58+pngXkK+HrdDMR2dpuAv()M`--)i&TDfH+A^)v}WOWn*5@G)QmzSW>XD{Rk%njMn@u=IOjZ>TAG4+KGw%M2BsXd?((^SmOSPZz$9k(JoryUq$y2S|*Z53`*c`%9*&yE2pfF1mjwlvffQ zH0~<(TylmB-Ov_t9D$zfp=%3FZGH-Mv-@L{Nen8cso|FEmvG;AbsX*b1$)0L@=xG?IW^P15rfZde9=WE4-)z3EsyAW(>2~*w}$9Q8gIEU zn(hYYi0!`#ok!PV?(x^fFyq2Rn5P_oQn~xV+@l(AOEK8y*NX!h8bNybK-&*ab#S&= z!*+DpVaRn=v8~Zv12XkrQLn6#!{wD|Rk4-7RONve{|2#d(c@ul`W@EqW-nVhP>r@H z3SIHtW60>j4f>-!iN0L!qr<&ZX+@5_MB8Z+O_-}7c`7}IoErORzN0+V2|d9%J*U_Q z!QB=V^M>~-f5SRfe&yEn%!0hB=ODqv3-c9Z@#l=wxSZ3)JM%kH>4!QRIseApjxV64 z`X|1fxDIUjCs?jKjejL{REjnoXBKg@aZr#R4ZAxG)|v&-fravyeXN&(dz ze?x&nrm09(TViBULd62pT-=jM8<*Ql=0tC$mF{+u!hu#)E^Q%Me}dTDv4bRo|4tIw z=-m_Uwaoyg+v!-I6FyiQ!JMwdqqE*G2p(C0R&|0?O!>Hwt-X)p8%J=UnvAXek~I9a zOV#$vy$#suu4?z;>8Vyc<-qV`(|s&b$f=g zYu3NnnY!65Nj8MMtWNS#PDhBbD_p?}F{QW_LJ(Du-3t{w6Ob!7FlXb+6G7x?9)Ta5 z`_Y+mX=r~rMcnCAhh}xb>X%gFbl!`}3NyInCpy@)e1SI_sweDFy5W!cMC$iN1?>B~k#&#~ zi&pofkL429aLJJj+xyexHbZ*(co+r0|H%$qF`|3T~}t`6lzI`OrFk_kS~qKc3Hp{~b>e`yJq%tvY@E zw;4)@KVz#k*Fv3Q0n7bw0;HXs$?iBl;3n2I@Uw6LmoYF%G-yepSWUS#O^?L#Mt~deTBg5d)77g5Bu?}7iorhzMSA))1Axq^E2KUm6(Rf8X1nU!)ZO;bt zef3!9B>|_?4S2u29n=hjd&#hua596(`afTw=s-T+x%?H*-it*2QLo|5XnQ=`@C?SN z_rSX!H(~5nb5M?|fH#pB_52cJV!SYWo`4>Lz4k_P79L-(aI}iD1P0 zB-THBG}wsu@~?f2;Q7}{;I&B+{G2~Q?c}eV%qIuD6x_-^*s%k%`CP77H4_cJW4KoX zOR%BUgmZ8?iXY8Si{hOQVu5J8D8gVfPW-xBtUX~kh8XDyy$@$7n7)hewoha6cImwA z=^0cfPT_<571EQGCA{i`yQE}0jBkqnP0%}<7vEEqm_L}yHy==zi2Zl-UoGV&cCC+i z1BG6411%v7e3zu!C$OYTW%TLd64tyll43)WnWdi@Er>2<;T4Se9%rmJ?KzEEGSh`S3aR)bab0B#cC5qN%gcHB#3$HLCkk*`!XMdkeqrliE=DJ0WREJ4X ztz#hjT{MW!TD{|re$}D<)}P_;KW#b^JO@qhOVg8advL*OflVA*g1gQIvqhCvs5E^T zpW}Z8;}&a!@$N=k?VSsgBCp}>InUwQkPCQKXw%e2lGGufOUyc7#>y+ zWv%nDs5S&DR*%NvFAKPY)3PWvH;d1-XoX{27P8|}$D#22Vb-%D1==iY*pjI`!L6!} z85~>=-b(q*^?d-iK5=00Q-i>)*Pj3REFS*#%EQk<9{LM8+lTTmVXLbYCNEMzw^(x= z<2zJf!V6Bpf5UOIz`lEtu7lCzyag|W3`R_ujM)xX;DOn2VV}1I0<2!bfan#XaVfhY z_4_uq)@=^w^HiCj$Am>!`;+v3G249lAYBoT|e$FtVq?j}9Uxmb(53(K~MK$B%DKJY+>n9(i?COV<$mNpRt~V60IFroo z_E3~nEah7?)7IxMLawurWR?3vw!L+mU`cxp3gHT_jWI;iisxqnIOEU7m~)p0hE_; zjC$?j*!J>l+W#n$`*R?aGQ%#w;CX{7@}N1cQ2WIjzFmV6SPl+f6LDeK9Q4_807uzn zp-t_6{QXvfnawfyG`JC!)&24Gnya|_r!h8noI?+@8?eA736E(hfQIfU?CtlGuheMc z?hY$uztq07eV_lZ)RA%I+^a)|$qlrreiQ{*{h$Yz^@L2Xyd6`5rI9RW3;fZo-)XpOHtU%qD`_L1dl%VXa%%7=xc{n$et3J~f`6wd;zuHe54R_m z1$lVKd!cBke=a^6?}00AlhJ;+FywCc!^B$}wq<7qV4XVHdR!R=Wh3U;hAfX~_WEwN z4^Nnp`tPZ>rFN0jzFKhiSstb>B5B*7JI|8zykqG1?tKc`H=>u+*2$pLRYl2{%H8NOKvB|nON?)`K2pf+4!mT_Q`?wcygAd8 zew_Y=eH&F->X$bdG)@jvqOW7Skbjb1myIfg*HHR|1D4JBge%+kz|V-kxb37ZGrIN_ zkCmv>iA~KoYQ%i9v^s!o*LKl>c1?Vi7b|qBZ1}8{ZS=5VJXyuhqSa51k^a*DG+y&9 zc?@)9FGi_Isw|CwMd?Ul?)SrnJ;NjkyPQxWqb^A@-+}%m|Ix(My{HgeL(R(*aNc=g zW^pc1$l#^1MK?#`=~3yh_ewfU7(53fWM1+&g-pn^X;P%}gvUL}J|y3E0oT4yrQsgs zxcv4Bx;;+dByS?Bjz?TBa0jNE&IdXF(^L~z!lZ?McXszY3i8=R9%qkGTe=xV&b~^y znP=J0QTJ(;pGBqele@IyOCh*<3T}|!n)v>48vQ=#gq@#64(Ziv;+Q$vWL@R~U7d;atxTVJ4_-#2_x)pyYxGFnZWT-6;Y${))7{StBgxA~AWAsLU3(?T_w zI5e*eMO~9nydZd|Jgz(8wtkmz&M8$K@$eR|Gdc-xrCZTXO$Kfhp2wkN%=_QS!^%iQ z_Bdz_4$60C2Sp0lzZ2N92miQR4{G>X2+nzy@Cp<7}$zFOldm^4+x|!bZ*1(lc6KF#BH8`LDkY!ZP zgJZ7O_%qyc(c*%If}_cprHB89M~@5HagVXsH|;xKsj-c^Mp5ou#z5Auyw}ko<;gb2IoPsu<(PKK@xrK2EP# zhL0sFH;oaVpP$+H&Uus?70c#-Tt`3M6ZqEFO~Q`(A2;~g8Zyw!gZS(2bp6^NxcARe z=zf@Ej+X+-8GGWBM-pLIwGLj>R@A*4!}ZKxf_aDK;8GEy$`O4i zUMGuxZYhF{LK#G)pW@iesbCRlW7Drag=^oQz_;n?ix*1W;Ulgr;-8JZ!MpSx3{Zt3eUY#xVLaF$XoJpx`Ow>~if@)g zgZ6e2dd3uhQ>q&V$<@Fr!{yj<<|_EPt-Y&w^nkvC`jTYEH{Q=nYt7mIB^kFac08V>*UX6HQPW=;b`dZ+bEhoVk@lM@sdv% zwHGcd5IXa7w?XQO%WP-$K;Vi#uoX#KqDNC@Xx{~W*5xNl3G>de{jtB9itiw*cYVy7 zEu1J(;QdbV3!}F^#%%NEy|lnDK~%dvgM6BOKuY@n>Ghol_bI}2b>B~zVzQ7vG%BK> zf<7&M`5OZ7ontRL8X;)G7Jid-EU2jpKaD0xC|I*lVi3lCX{9+L` z4ruYtf*g}LjQCHu9!_fEOX)xwV0{I;H?60uhyHPmZvx1sNP`V)wxe5-wQT5WIYQyN zx7dC!Gk#-4QE#_ZKK@}!ZclcDOrtto(s&C$wXU(+>smND-~+F**aT~WRzkb?Xw)_u zit`k-@twsstXTaFlwKUekpQE@L9Ql0W9>XDzm4@H^(W-*2Fl)O&p>TSv<5m(9QD<7tF z9RpxmzXJN>#NcX9Dm8{HgWa}If?ukG*q04=K-bL-x?*K9eauIgvt11{J*VOpSp`f@i5EDDA7IGeqlkk~ zfz!f^_}Xp^EU#_CasyY9IyT|_F9VpVYBfq4Vg%3jA(YXsU<-B!;G)#qEX1oHnn~Sb zIggBCd!mH>mm$p-xbJ7lregLyz<^aNerL-p4u})G6e!*K33q(wXO?TU0{FcLScFtD zn2mAbXRf{k9zEgUF`^BO+tks(`Vlzh`{VrDn~wW7{rALiISt>19OhZ}{p$mkZ4cym;TZdG zd^9cFJdsuX&ZB_~6+{X#$7$o9HE?uSDcLXTfz-SM)X#V{`o0b(v!!#f?B58o5Pp|Y zpVQcUi^UkVV+*Gj=PWP=ufzMHg7YtS6egT~28kb>QQE)-`fS`0|K;&Prk1#TEo0)S z=P*N8pLXOtQJKKqw3#X!=}to zmH7W;ys49xWcDR*n5(WXNlE_)$5%>8a;hfd`oJcdHYgCowxS{@6Wj7{0r1f#nPLq2csfP*hxpKWdM2Q9<3PJ|&9X&ijf{k(yLm{uXmyE++Mw zW*oxrrA228aq!~9bUkqv&W=1rpO!~KN_Yv)vr1+@#_6id<$JrcYp?Is3f8Dx>NkFQ-yeb&_@`qSBjFZ z-FW6(4sL6@D0KTG(f-MIJpWRJ_sj;`Mt?aBzVEbcZ%lc`?+nqlO?FVC3*O4MTQ099 z_n>!pUG@;Ed_0Y9cgiXJ)LhgpCpy>S1!LBnCd=+N7Nw9*Po_tZ^GYA8>Z&D|p7 z{Ub>h{uHrbIf+S|6eg+)bB&>!u+{r7z0^M;bi>=o&HEbKC}q>PdF}Y`_eeT;xfTD) z9pb(2i7`ay1DqL@fEs^7@l&HF`iPEVr0i;L#Hvd|uBev{?!JNs54KR%gi0KJ{xrE| zrr^`rx2Ps_0v=n@L0XIA1*hp9dUkO&^Xzw))axv0ct!{*EQz7O=KD;`teCR0rC|A} z3aWc;hQFSa(fgTcIJx2=-EzB#Wj<@@@0`c@dzL!gmpsP+hlNZcd4OZS$-#pwRX8o^ z8py0o!aNN%{GB-r&Hw7-2e};X*6G1`r}`xuqVy76k8B{z`u{r|%V^^kDe=XrP2{y< zA3J*SA&ok!K(en}Y4)ax7^s{;n&ibLgibDRg7EIo;1ns;DqKssu^OTah#771>r zD11Fe2G?x&M;+Jq-1Vu3nEqE_ndqE@UV|ZYu_1($-!-2M?k!~FQX^=~t}b?^D~gH& z^k~0$GmU;{MQ85Lq^9n1bg5hD{))6I*K!Io_HAW;b5&sais9_*+#b+5Eie3CCg9K2 z51`s`9afJu!}|JI?8m%N=58E1l&(jvB3zj5h2bP8XW^a`hMJW`Fv%Wjoi`~xSXdCB4+!}sv$UJpMS zN5R`lYnFX*Agd2uz{bzJ%)W$%us&&3TA~=oUQG~sLX$IC>@G`c3pmLh{~Afgw;I^t z8U5*daVM+Xf0WgZf6u0Ty2Cdu{?4`~^aJU*FWFEXCBW?T$C}Q={Wm$Tmw7*X0X@mbTD~jEIZ(! zhnxOe!)jLy!}#A0OcJh*dAttu@28BX3L1FJv~SRLVKHA`Sq-=KLV1m#2w*ae{O@xz zP?$H4`MkO->Yg6YWTGC3ZC4y;=6e&xwfe+7!lk+U4%KXet}=A&ILSVqPlA7G+t{qp zk3nVQGd?Iu8?z=la;FYXK(*c_kQ48PPM$R|FJK8?8~YPnZ!E&t#6kE@(HWRpx!9&n!M<#@r&BEtaZ=q!FV%#k3j`{ii_&LH7r}fT2XqbfdlLQ{-g{e5F-$R)3 zL4*nyoxrVo2!^W`iM4v4L0h34v+_!X)2$6`SMe7vR!)&3woTx#sO!?<{K@R`KwUaI zD~~afrT5Dkh0g$Ewu@dc3uiT!`t3XObnM_9CcR}grZr$+bdkMG(#6>1-Aw6}JC1g{ z$!}B)L*neY+lOP&3d~`}pBNlq5)D`HZ$Qnn`7m^Z6Q-zUgW^Orv>Lb-{IbQ+=_xpJ z&JTgf*S~Pm_(t4WVaDzGI*Z*O^G>|<%uyC*U&{AfY-QFrllr{|!@vY}Dfhih9FK;4EySaNbZ=tqr%IfDj6VRx5x@8e^l;9oPD`Genl#g$g3 zC5~f#ox@1iPiYn}nZHsp4Tx!DYQp)qwYQu-`LLdj z?;@BwTROps^W^^Ak1LyvdinoldN$FOE)p2R%1)C^6i0y z>wRGVlPXqo{2}B#?dIpN8iIwtEFtiQHP%JH1GkW=C~}{KDVbC7qrq6RR{(J2L}rIF5qOV<`~v<(NAfPU#nt=6c*6VC%vrMYA#t;s8CC@ zCHa3FMk_#(SM#|Pb{1Xb61pzIKD7a` zzMvi0Tyw~+ehTA!MWDH%3p`}zKt%aH7?~OfYwfPWn660Bd~+NON-|(i_EKonItS|Z zMO;ZlGklP7;b%{M1rK9I?9YJbpn5Kq-LAa_=bn|Yc@Hi_x5icRcbI6tu4bzx6dRXLKz{E*ymS*Lz{@V>hUe z9Evf6S~=(yau>ghZL+KoM@2IJS~-WOu1;W=Lq_70=Mk(YQwi-f53(~w?JzC+6uTcB z2k~=wcG>?C_f~X-X;u&AkAK|2I{vD%eeIq6q(4(xA2*x}PjY5WCSzgfwBhWaPBySL z_xKmpZ7^cRL-7dfAJCAvo!cQetCccebJmgX!2Y*9WZdE5Qp;QJp1CV*dK$?oIGczJ zA8GO9)aJ2x#S!dq@Kv_hGlOZ#OOvW^8#`hrsK5rK{T zXQ|&@U5`57UUCH%8-|I@Um4=n*fMU%a8LZO&j?aBZ^Cgwi(y_^1o}LUg_;8axLGR= z{;8PZ=&4z7cZe7|?xn)^z!Y)2Xdf)gxWO#b6X0Wv9W8qr0#mFb$f0x|sC1^0bMa6( z9FRq>wI-a!)_s)cyq0&i+e9t4I;^l7>Ex7f*4}uZ?Ol`0ydqP1yn2*5c^-!Ue&(|o zTP<*sRTO()zYQPB>9GpwY)rUq%A1uGq1W$R?y+M5W`{UK`uiljA$$%s5`D3Ee-Wge zQpBB)i{N6@WH|F98I%=AvDLzU_WiUz<~1vc<4vcMPFgen=G9suhm^*+X%W<~?kOAV zzKIOSE0ZL{odSD?5~rm{0g6LNzqo=Gy;7zj#eRHE$4A!7MZlH)Rm@0s0Os!6$|~=Fn5noy{5UBFKRig~e*B0=|Mwp_&2`}@`KAKTJ>9V6sT@4MF%%V?+qo{w z3h*Afj61)@fjcJeEh-+ojZS>s7ABnw_C zYtqoDr?CBJJ2QSf1XBXmv-|>qi)J#5rx1U%+%E@@qC)ZElLTnIu>lWN*TLdh%kj^) zmoR$6Y`ppEo#5U!LU;LxVEw2A!e5A?w{8ZAq6BiILLPtRN(=Yb`xGnopT*zoQ6}2t z$<$><R|2FAKl$|fgBTN zYiG)!&)5+CdmBM@#9;h7=Mi8)7dS<60w4%OtbF``_C|oWiP29YCLSM7k1Ep&Vt_GF{A|l!K%mhbfiZE8ysfS8+kqa@@*F7ozuWy zQTF5}{}+tyj4AA5H8l3h&?F;QxU@Bo%~!J#dlxD4+Q-(iisEQEGU*m`=@giSLCTaX zc+V;t_36yFWZZjHmz1hX@kFySeQYM275IjEm)BzT&ZEM0$D^(BIJW=I5#06a@wwYA zk+>;zEJzlO!9ayl*duUBwVGeT%-|`^z)l%Atkt4Zep+}(I*85KC1vdMNm7CeuArF|1RlfC6**3m%zc;+y9td@&mq6U3 zf>k9_xb>48Dh^l0457EC6RRZTCR4HMNFRK@upf6#t%0p)VzAC+I*`kJOts%6R;(C| z*JS3fC3Xkk%HA_9V%B`|smu4+f|`8BPwHe#OSI_doCdb?ycez6wx78rN0M@(7JEN8 zkuvD5=evv?ifhBc%NaN_!RZQcmKGvP{6PHMjK_BCjFnHNm-0@Aw zhNO?g22CGKyQ++{n|9;G>PN6%Y7fqAI|%uqQJ82j0vywpV3(YT`)qHH=W8bOdrx11 zhy-PpzDdIEDV@)zrcGhL=S8s*cOJ6p9kEP$ksifO+QF``749?FW;3P5j~#dIYH6HtwG~F$e+MPY zp}0HjI?S@1DD0%-!EWUYjC)_nB{bP%|DnzNCMK2Z2PU3Oza-br(e%u%k4z4DS8B}3cm?yNk!tVA(}W? zzJ&Yn$_k6Z4WX!Y5gz2 ztcYOz4E)BO`dh&cOz+{;Mro6-&TmepzbmD>jes{tHk1ay*ZV4CMSOm0x38qR7A(Zo7tJiOdREacLz6*en5UXIoq`d=@Ng`T<+U8p8f; zSEyfhma{ur#jpNeD&Cz^&VrK$vdNn@C^S8m4LmxH&Wx;Mi(W4yi7Fa(~aM|jy%=#fz9d$+*>pPFKZzUtK7e{UkATVGH8gXj z9QODwqKQePQERjv?NqYCcQJ}IF2o#K|(%%;EUC$s%=DDPI+O6+ZY-V$f1{=5$TN@guZ11 z$sxA|qQV~t`IA^MyB5uceAfV};!S+F_7rZfxgLy7PZDpjISCO-KK!T1KG-fyhrEJ@ z;FEWy{Or%hC?Al+FRdGeD^7ay`wRwQW8VvLPwhJ>SfwtGe|;1L*HNX-jHxgqQImgs zZZ)@W;ydAba_7DI73^V_3TtyHW~u*t*~4#5OwK2qmBnA5nUh0pnc`mwyULA+R>Kf=8$tmB>pFNK-jbD>SO4Bi~y57j!ip?CF3*m$lB zuD-5<_xsx5acLbquB(J)8WnKw_;x5bl?>}u?{SI}8_>An%%|4Q{}iNW+MYa|8rNzvYUBk6C#MYim+E}5_Q zU{~%c(0iRD;;2KnneTl=ch+A5ZL*T_vcyO+&1KFk?! zlc%;LTe$H>_Vj{Z#XYQ9L2^2~IcxDI%IeAD!f+MUXjXEc7f+(m&EL5LdGfSrvnG7q zl*!)an!~x~QT(?V1~B)XCtTQ7&n4b^2)mXnsaz6bgy*))vSU%+==nLBjeoTR?>xNE z;K?2geXUC4zwHrts-vk=GZHNX?$kJ!C3rsCg6`;!!{n!fX_a+1sBL+|u8LUA)N~9w+540W+%fp2K_qJg8(pDkvx%wLhj6A|T z%u$#>45F|H3sK9c-WZI{+!E1>E?aBQH*M2#Y#V|)SwhW?sUE6WH%x+q1pMn=6!)g7^{TOcQ zPQz!$qWlUCI`C>CUJ5kIffpS3anaSL+@@Idh%8+vkm zo6y_3jW2S&lxW_5a&F@`%R^NsB@w`D^VF0j_nR@QlKGxKfGq~Uwh z_z5i{`dHM=-Orjv&B=RVi;E*IuYUm1kH^rsu`(FhqePigG|>E|gq@Dl#@X`Ptjt|q z@T0qO*?sc3bVdTSTEB#=hu(pshXg7*hu|dN7Z7>}jd{g{KQ$!EW&tOB>dDADZh%H$Y zOdFdovE+GzBRp5aE_W`X_~ZlZk%y(=^D<^{bzZP~rOP7uA398gZrj% z6b-w`zjqviKa2ijt3L?rLGYsBdSU6dHd!#Bm9w*6C4x&=I7>b(qc?k9>Ab^HvL3vG z^jBn&>~4iLQR_GTpetCc-@F6=WBBl%YC*P@jZGNEwtCGZS1!l^mqaHID| zG#2=*Q!oQJ4~WOu*dqeVC;_vxkKo@!JJ4@t2FAJ1Mu)U*nDbK>H^f-sqmo51{?BO; zT%+vC#742@?{_ToN-ZmEu_gOY0@ElkkjQ^IrH|f8rVhJEylFFqkKIB2Ke&>z%0gk^ ztV;jgA5Oj516%us1Lu+l&^On!#ue&ZkNo$5oAQeV(MhX9frSW8zOed+$kSTcWL zPc~bWDEFKeU3_IBl99j8s_j+qvam1zWEG9^HOp+)?5n`GT{f`tN(+8JmIVef_tAS) zB|JQG10#_^NB2p5b+#1xW`*OehsogkND3w2r$TYZIZ^4zE-t<6GaEXqSL7rKrg?kE z@_9#(ke2fkerDNuqD8iB(1puX{UMrF{XIwGtmDksD3t;x)w5o6TMB#C!oq_?+4z$! zEHQW=YXbn7~PZ`j2YSPzb<4`ex8Kcn&x!IjMoaumdH~?XSAUHXBK5`)PX?*ms8@d5uo4nku}(v!q_NfE>dYC zoWH7$!H-shtY;D~j!J>*#*5f`t_a$fy+F?e46K@d;EK-6FuVN|TDsqW_6_&218+lC zU>U9!H9=9u5;Xr*1J_37zyEzV|s9rIa<%OjTmW(R#$63+ZGkLhr#KBbEWOO(EiBq<*Y$wD7( zDyl$ zCr{761!AAG#ZNCNW8;4|AuIb6pnAnwL(SGg4`DRyhs-6Cors#dIrw zD)nzZOlm^6y8hZaa?Tvf)_>?_>2q{o&kA|Yzp72huc+f}qY*f{G!8eaIb&0v1bwyr zaM!!X7^dijE{1RM;=c*laG@K0ZmZ#somX){6NA9B2hplU0R}&}#f0tQd>Hw_Rq|&Q z`njx7n6cLHoJv~1?y~va`{=-)XKazd35xT0&JtoPh_k)Ue#sms?(;q-b1sGCqki*$ z`sULjqX_QGi(hPzurvCW+Q)~>Tm<91-Js|37UW%Y@p#i;_%v=cHmLr96FvLzpH>sx z_?3f3=d<8OSPq``84bSq3AokZjHqXTCtitrz^i=k1AiBH_VJX2yXh3q;t~rO6(+KA z=}2LTtJq)^_C<0d*xgfN8gej+e`VN4rG@U?9LsLfvl#*p9zG@fvjmd+-=M}Nd%*EW zF;!LO!bGc8RCw_u41D;C-5z-y+>ZRTF%Hj%#u441;IRkpJa@%uKc>LqHA#4XZ-OxI zE<#iJQa*6YabYjBiJjY)hnsiZWak~Du*CWQj!qlgv&ocNx{4ucr4_Atdy)TPWlGHv z(t;C2l@<+MN{<({unRNN=}qARrWSFOydo>b7s^jib)X|m!#q-(a}^|EJ8112d8{HM z>WI+Aq$57;?<+n0{Ur{R_bQ=lp9B7KY8N{FIryn?GgK$sz&VOGT(jF7)D1OZvhW>M z@6|K;Z?ADm*Z}g-YsTEZk+g^v;hebfbo!njZl7pD`_1ox%cEg5Ec37US?GVv-R&dO zj7w$(*`D<8kUrm6n@k&f7D04h0Yxdlg=g-E$z!ECzB3k>X;t%4Hdx4n4PS@XPbyN> z@^u)pVi;S)&BtSI8$d(P1TTJ3N8alyjKAiAI`)a2=H_s0T$R9N{@acvX=-G?KLD@6 zTsp|i(Xb$lrqcsZyB|$z+D2fwbO*h?dYz96@}t<{xlG-~gp$0!u^p*(Y;uDhbzTkQ z*R)&H+wMJ}BeJ7fVaI&$BuDoeX5o(Arb16A1lOYmJ)RngWpQuV^NZWCSNX88gYd;6 zv18bh&JpP7I7B?<=S7&Y{T;Wpvy=N-<_+blYV3@EBv|`OnBw=%U~o-A=-$qSnF_yP4p)Vdi#~?4G9&hfiNIor7C| zzb#LyLRWv1<50?6u80jnkH|rA^en44Bq>dK%(9-NCOcxv#`{#28 z3({D#_g{Xmq8z(4WFLEL>dY;kc!l*FlnCP&-ebWJ{{!odH(19;E6iObX6-5g=4$)I_Ve zEnM)qHVCpZ;MC^q0~?b%QSWR`C@@A4YX{6z(JYCN*N zLS}pJhJozwx^c|+>qfpda6GFKX>jo{h}o?*f`au=`Ju*1!fbvW@1ezmhE$ZOY-%fv zt*Pcp&$mO%GJR-Lz7J|U`~ku*f@ASI2n{^|jt;9p&3!POVt!Ci`a{pe=h z((ym;+-0V{vD`0@LiWf;4aTjX$E+{RgP;m&7A3tC4&L0u4}TN_!wmLRp6NFqj#Yed z&Xy(nu^V~+Sl^v^Hg}i`ZMc@kY_&8ge?ulKPZKhhskCa}Y`+Qfg1W6xg* z{O;^P_U7|bW+X7aPh}iqUT6Q~=PvYNIDRF6%>Fn(Ur)+rL7oK{)IFHfv2lRYPseeX zR07j1#&c$iUO+;N6c_PJ0moRr6dA117P4Ea+=QATC>J}QGn^oJ>bDhe;|_m-0r9uE z5&O~OOa6)$->(^f&rBCOwMzcvMF|K0wvgf1t(G6DjI1oSQ zKVT0YZbQA^+iX(cHdHxQ#V)fY_~qe#_V$Sto*6xsl^kpb-85U?r0fu9qusz=bIoVN zDkH%v)|ys#wt|*_EbaKFif4u&rN7Z;c)GNPK5Ryeo-4Q|o9yuCKru<;IDGQoL6W;~ zh{+Rtsr1ut;rwue4N5-(m(9*{iMG$Vzm0>i$G@33E{Vi(hjLh&(n;*6@QF#h>hRxa zUF!N-hkH3o(#<-JON=cA9!4AnF4m(ti*>PSk`%@2=W$CfpJ3X;d}E`|FTS5w0&%A< za2I78sB>$v(4+iLy_4l|!SDf+qmQjoFk(pZHhbdRcm>Jil>xX$@}8Qw1*q&V5%_x! z_}Ohe6*nm3e9d#r+BX-j9oq;kZSvfj2Ei?-yop8p&cQ)GeJtc}o#276p))tz&|YI9 zO;&9~{(2}i-l)gOS0S`N{|MG@^QDs$*WuK_aWtw(2|bRyX8SGF!QIG-eO8QRvz=YJ zS=)zEh;}-hTepn1Cw+(S6#@gqKwn^GCXjrBJ+9FVr)ay`Se8AB`ejeSKi(Zo(ai+M ztk>bMJop6eC3SEoGZ^%SPRIHYIz0bqAAb3j#Zt`9U@709+%p89;lJ_JlW`LVH_jm! z_e)5{-t>J?84hZ9qpsX|oO%fa2b>iia8{#RCE1X;zJ{GuY2;tKeCGj${X)TTXe4Wz zTYewd27i*eJqjOhTupNBF6f@`MS=GNP^sI9ij7vFbwD$lw0j9AF74xGP3Pjq)ArDq zV2ZB%Cm7rP4E8#Ra99opH;otL^T_ACeP{?OSl2QB;xat=RGZE&wZ;}@2kQSniq1Qp ztGA8gGP0ZYN{CWY_@3(y4Go17T2hjt(jHVaY_ij$vWij(CEs&hWfY23i1s9-v1&?^pMsOqf-quNcAoPIRI1w<@t@?PU5idOnR8tCME?aq7Ey z2ftsgpgUqaJa*wZT^M7^&8~k(`ePDdRd+KPtM|b*x<_IMV|M8LMY``jjfM8?r(wE| z%%e?(CVjGFeSRbGpwN%=SRM=Oq6e@THzQ{2Unua|*Rk4%x{yCUn(4|-;(zMLG5+>a zY;2EU_Xd{ZpRl#8eSRMvTxP*;KUJd93GHxxtvcQQ=?D>dnsnmUJMk)qp>%PvH}0PJ z51qwjxT*Rs1}p!<5l>REajX(0&GbZzgh6DpN*NPMrKs4WkRRmu78h)F;ve=D;-vif zSAt_!;RewH?&Z)dJ|Llzt0<4>-Y=E{w=s?|TQmgTrR75Hc?IaX^a@68XylS-N-%{n ztGNev6d2{ZiF#%ZV|MYu;{U>ju{ift{Qbp)*_M_v-X>Im8HfMo|Jn!)hBM=_Y{f4S z8++mB`WBerABH7;_u#_ccvJ~0hd;%!X!;-SQ%AfzO;Vbr@Hxj3bIyrGbDBiid7mhilV&D;kxR|qeF6t#bzI+acu4#e#wV7Bt zy$U2}9K*29$H6Ez63gGO0P|_{apJjwP^UW_?Z-uNDa&5+t>K!Yx}z!l$|;-prMw1z zX?H)b@h(aHbAkc3X(twUS&YHvld)FMdKEFD)}mNrXEC2PPgm^XyGnd5L{U7#_cHfg z=AC$dl(19Ve3buvFa-jPig^$F8xUr3oA35`1db{_e8#YM(2}HxODBAQPser8$o~ms zDvZSc^sWj!Yrv;-V_=B+8gwr-gOk&vaI$z8=cg2p&od|UA!ifunYRL7-**)Xa7IUd;OFPSt`td z3lpx`U7tu%I`SC)aSC035sopQQ^>KEN0wwo&d2NV-a0*cP*8_S!oK)r!Bw31BNi74 zevPbmJ9wu>;{@l4HS~E+;O_{Ir1xe8obe6?cK!1lh&3}}@p9=9wQU?b=lB#<29IJf zaD%T02x1JQ1EJRzM3cb{JpzTKKIMn;%T z&Hf>}JW7x5)g|)@3I;@9^)UI?P%^Jyfs5En93C2mG4&fU@^d)eJ)vl2^JP2UdmIII zWs|T+TaMKx-{*@i3Cx;VDdOI5f>YNyldJMeVfxFBAWtTT?bP>ymd`nYk7_%}uQ<+{ zkGX&V@?#U~y0~TgCb1V+v&12)cj4Q;iI|dN$VL7>hla+du;*zn{`J(OHieP&XZ#BC zO0%UGXCmm+1!oFqO(e;^OQ>+lL2B5#l+(hY|EWvZeht8$F z`{s#c8itT&c^zlUlCVvG25{b;qKQYMp;nv==lA8nCV>Srm&(AwVLl7)se|h4yVxzy zM?xVcnn|v#hluqt?CNKPH@*AWmGP<2xzL#zj9diUb||w$1I}{8W1^vFCh#+iSMVlT z20~W23^$jC;j*rg^zcUp8hW`<>c1kiS6D;+)nc6C6 z9q5(qVegaAfmh!ucBniA9QAFO_e=?R`a+7G{xOa(ZP^F9Tjt=T9lwPh%MHA9Fax(M zE7J~>A@tM7g6s@t(aWRGq?+YN0cp!ft8*9qwp>PAQa00?A9HE$?OAl|syU^s{fCWf zLxHM})Y&kKWc6I>?eh=#uWuIh zWcuTb!B5_#(-iS6Q z9qXysYpzCLUK)x6R378WYoj3c?Mlpik_kZ@D~cDMZiR^38$kJ&JnNVE1Zs9#?3aTu zNBynM3JRUrBdejzy5Ca(+exskP0QKxxCYoXU0|Mv9)u1L!Oh|+3!YuYaA|9b;AzO^ z8kH<@rTsFzyyFxuIr|I0u6=-C%56#SMF-xu-bT(JKVZ!ENOBV1rFiZDRk`HiueTx8 zW#*2K!ah~*)oMO}!C30HF6Vl4>Ja~K7xrsI@zh44FZt;b_k4T@M9Lh6iR-0U|GZXc z_LpK-rP8dcxEp%+$qL-aC!nhM5w;w-3=7|%1WC{`-3xOV*O|*pgly&xDa4^dxhh}z?gMVQdX`U{ zph<@`i+G=jmSl43oWM<-O6#4SdB0VR;?oScV=|-3(RMIIjZ~o~iT&_S>kH;B=fUSq zA7@Z)&q?_eWu4 zt3G@BHv=6qRhWTq8~*$K9VTTckxBVgkQVmesvYYf-Ajk2_4;xhqZFttuZjOu`T(ze ziNJ;_%dq}YExO27h=$Dmi|2jf;Gu^SrF-|os85Qt*I+c8ozaU`U+r0bS2?N(U#lGn zi!s~NotcY^#i=Uu*p1~ba9L$6OOI=Ve*)+4zeqForY;(kMtie`)kC=4!BNbwzzp|p zNoM6|^Rc%jnMq&!g4wqYu#J|&&iuJA3np2zm?gZCbG~8l`n!;pavekFcW~u9Lech# zHYU9-Z~ve_pRh7xqasEJ_^9=2Fp2TizoQ%sXMfM)1=ei&w!oeWOAL> z06DJ~Q0LLN5LUUEx?0=eM%Qeb@vjx84K|~d!v5vMUMXsx8U;p!^YQZZr`&dJ6ZBda z$tOoI5cT&&;NRn8VUF4hl#We>@L@tzI8S7h>;a^&XOC*+X7WB%9c(6-ifX2{EvLc_&uvSOL7rDg4!;17k(s`B}YpI1}|kPS?0ibXYzb{LZ9_XSh6v z+BPeG&72`jYezJ%zE0>PswDAAwvzsl{rHi-2#X+gH! zTaX;N0NM_n0-IG)pfkV;hDaZWOH0pi;d&=wMRxK<;28z$Q%)!aSpYSS08n`FW5-+V-!~6Vk#_azlaoMBnvF4l+Y!+s{!NPm7T1x`2 zx!!_9S8wtf?Vq4c*NCrtDZ%osdPJN>KS*jn<wgb}V!mVKn*xmeore#zH{c*QYm|`;;{(#4iX&C!;dyF@z}LP48FN>{`<;r6 zs}kPhtIgQivK;s+HJ!ET=fJJBSuDx@D99vnOtCT;Hg3~k#krH=*P=Jj5-vOgR{~&C z*AvmsfbAk14dBfySD;ShUB3NsGnNGz;l#h%^kkPW){n5FIo`=QRF{!j*%d^;F_g5X z4)vv^=%28+w~Wfdl*`RHQ27Keai#%JRB;gSIS*U&>S2)1Uc4SWoE^_p!|CV7Gnu)J zFR-;_&k~PucP1M!>{|dGSyHSqDgzP?3n2014fv|}kNcbc8g6f^;@>!a1k=uw7%lw{ z6iRwIfM_ra$1Q^_S;16Jz*{dum#T?y8s*`KrdA)~&cfTci{ zGe>dD#vshK{>4w<9gQzdWVvw@_G9cDYfy2UjF)B7!0Kli|EcIM7;PLT(#mNAEt^4t zqy7s_8WsZ^4d26lr7G~Be-%2-zQX|9jZiMBz)q^9aJJ40?9BZVUTv>Ddy%>yN%(e+ zHM@l~+kQjs-fx&U_Zet){6l56i{P~KKNM(w(3)C=MV^wP!xtPT;bW$9_Y=wPgcjq>y={}RD8`-m&GnGl01~aM3Q#iVJEZmqH!5=z19b4zm zhM@67$iw0zED7?aqGuCWzH}0uzv;n#{W?W5J9n^)eP=0Ps6VsyI!Q`9unke?+F+NGtOcoBz6G=Pn-=|#UxFZR3Nk!;@`VHYrhoU-$nL0Aeo zuD#6G>SWR=sa*ENDTRKjCa~sRA+&Ca6YH$ECdFlsz@e-Pvr7s@y_MdgRTIlGvgRI4 z2o}-jni)b*RB)as9ALU3N%T(cG|NgmOdD?%uv_H^$nZr08#2z5qO?x21sW-hoE!PFpi(afvYUurDS)uHtQ+>WYJP+OXJv3KS+x zA@SgA@cO_`3JsJJI3x!swMc_086BXdPu1AC<2$L*sTbVz9qGu(b1+3uiB4_Ogu(#_ z(E3#{e?;@9=&xi1ZdrI3YTO=Ti?1}hRj)vePc7I7OI?cjHIFUoG@?+g1#HAPeOhHY zojoLFD)&%llLX$o!=VfCqbLO(588-If|QZ2=V7DV2Fqi~W;AnE0~gm4NPo|nz@^3% z>iahh(*K>MM+eP7p1(kTauTp)cNUE)%i=D2#?tlFa8ZbmZwMIY#-~O|QZ%xVsjwwDCvVGCC5-Lz=j2kJ&UX6tYTVLXYfMVW;W++5?Ttgv_}&*;oD=t zRPLzbz_s7tfulBGyL=k#s@%^-H~!-#-|9h6K|5}~;SZjH*3>in4219-X<2e54Eh{K zNvj&+N!=d8S#Ll;Z7$_bcn@d#q=;YB3>gL5xZAf0-ucGCMeZUb-nU?RSGR)n$arDb z@r=u@y&}vS1y7-A9b@O8NM9$~;a5!}68^}I-&e!@ZVIS2l z;j^$rRw}JbS4&Q_r6m)E@mMaCFq%nQU!<{7XB@~OJdz!|ZA%wuHY*ppjCG&7;n(X9 z+?q22T%DpZr$Za%yZ7@h`LFPD)12=Jy23ak;1e<-8NEEBiILS^N{?(Dix8x&xv7R+Pn~Anpce4`7 zkv!KBz>N5h+~g-->_Sr*bfr&W*VhslJQ&IbZh8zsN@7@hz6G>(y18?w>fo5kKs+vc z5^zox$_=)H6`wRn-fS=zlsAPI9ec;iEu2p#H~i7T$B~+^UBu5#!VF*QIu6_+LBSpZ z18~e<95(a>Mze74%`Y}4?Gf?N4ElU`uOLVuiRSL;lfWy~J-;GPDvEE~=Wlz&6)dSe)5 zdIh?pL-CM;1H`DC(q0>VPSPxlo;auSt&2~Sgq8`88D2y^PnP20N0;be@p4p+IYsS* zn7}NLq;p5=_?-_Jg%3Dl^>)ZL-0`TL)6pp^Zh7MaOV{PXth|#TrL4nVytxKnau=|m z`X)G0J5CisVY zQDdSXJ)78w2Zj%!cjM0q*|=GlzuX@u>srEL%dxmZILl6(Q_IKfTfufsbLTz%lbA*z z@WEDDEWq54w=p@*RDkEpKObkBUq|BG*#h{=-~h^%II);brP$v08D_|JgrDN5DPQxeS)uN-$T6RT1X8$j$rjtfoQ0wF4z@elGOz7n0HG z;jA!DaL;@O7I;~ouDdK|uZ5qNdF{&{|F;->My+9Gi#0?ube6M*^yOeTZ3dh6;3mj@ z&}3KlNHej19dr#)XWxg|!HYAR%& zxPr>i(PZCq9!^B5QoKnkd`SBbH{{B&wfalz>QZIQ(3}XOuV2@ZEkVGJpCe$oZQ6WC!W8kn+gpp zbl{`^FVK@L0e6p4%y6R&E9^@Be`Ui8%5_;{s4?4BCBeo&8^H4S zWy7?Uc~Dqa%IUdkK!2q^KHaUszcp<_GwB)l@jo3>3OtQhq;04r>OMBkn?*ZzyvHH! zwlwJC3#<|NIeG&wqm|Gfs8n5q(|=mwp05wZm$%;IbaEIp3i}7k?gnt5WXPa&1e4nB z!CaTmW4n*;XCF6gWkv-tY#JZRp0~ua*P|m?R&WGU9lw(q9upky9S*GKQP3gEAw#Fqh<8nvKn1IE;Q;2{TaM2U#@zj?uL8z)Ierybz#1f4+BEBjzk=xsjhL=(6z6muu@ zWLQ{z0QlWfVXunvAgfxHNu9q8nY(0}n_?ymtZafcYq!Jme@S5d@;$fZlOkMdTFg)K zF%*x{+JUACqwrh)LmXg|hO~GX(dDcvQDGvT{ z8GrIExODY3+<8HpdLv44e!qa>*jS9mhfk-3Wf#!>;Y3<2+?z)VSuX3gcr3ho1U2@p z!wTc+Viyxr{5mZeHV&%bb+Absh@W3VP)>d_q>acLObaD*WyETd3FMhz?>r7(v z3M9b)W;iP>8V2WJIXjuF2+!U0S#iTXZlUF6m~knLyKpO(WAjFFd(51$uB1g|H@F$| zt8BTuc6wCz`Vto!1r+^yAQYGYh5uvlTCj-gwXTMYkI&FpAr?Ff?XgjCvu93><=#%a z3MVF?g7xN&Q1MEZ8Kelk<`om!&)oOWALGadWwpb69T(H~% zpZ_iR2VHjeK`BFcXIWH1zSTj|je}PN)=DUL$en}FZqg(glMST}Q>i#E6}nS4(v6uB zpynJ-MXQ{FbB>_eP-)?NxPv~)4&(wu9Vxc=B=4Cwh^pp|!l0L_*dV(XAD%c_Abjnz2x-*Q&60P*VCRqRCANlaVkAo!ZR@l}&Lo9Eri z?~EyeY&%0ypRi}p>geH`wnyWE;Ok1EX+T?pU5#6w9mv*ta%hv z?TM!$Mp7VeA3_1|>y08Aah@ zHP)VgkTPxy&+wFF@@b1^p;fW8>p%*7Xc9z$?{K zY{kdHxaiJsxZhmPUAXR#g`KA$HAs^Ndr7mufxhIpc|3FXji*)GbC{Fhf9$@rklBqq zK?B6DtT!r_BDUEw*&ALIsiw(BCa93Pem(59^hWE^Gr?n*3DgR_@1&7RtXX9qZkJfa zQVjAj!1f^Xl@x$6o3h!pjMvz(=RB*?zm3fYvjlfin!r6xU_V<7(banmQ}GJ2au??P z&!1QVrQU`hqjI?N_XT&qWH5WzJW<#iOkz96zQi9w7wG!bG4xK~hne*)r0%=R+3Qcf zbaU`5w&u$UTD(w?%@MlL3i_|0oBN4{pVz?ZAP3B?GZ%6xkGUJ~+j#q(74Yp)BpNAb z3clhJTqz;2rGlHV;@ARKe7qH{jytmvi{AA)Wi>3j8c^-Q;>?Nlrw~2K> zH5OGG1Tu?^On!y`PG%pkfV-PlvU1mPsNg?^$yyp=MbS{!y;}>rlCHz}CCn(GiHiktzdqT&<$DC%jJFe1Rv9qIGwH(Fmf^H3gaJf&9lFVwndcj#nIZF;_TxX zm~@ewcc~AxyyaleN_~3w%mls*_@qO7Mc`RtM@Ak~LGPap-TFHn&b}Q-y1RrOK*Laa zR4EHtgTLZb*F0`ZSp}YHpCt0^KY}ZJ5_!AKsd&pw6+=h+^JB#Gu*32kmu$ZS|HL># zfocHObSA>NHJ&(ZbSn5iw8o8=yWwT!V4NTSoy&H7!#j#1c?X+PzB4=o<)y>s zTc^(Z$m`MFqH$u&ZFZ!doGu#rbrBhr=y0FYyeMVFFiul`3BA%dEE=UXjfOc~7B2|a zC1GL4+dX-UPZ|fH>X&Wks%eYsC#Z2ltOHTHKL=#oQZe+g8v9iy?&|BF~Qe_a~x{V$YlQHViqp)b2_?1^uqY}kYcV{x^I0voNRiuutO zAzn!ZXKs*!n@=@xTc0EEywwVKRZheCV;17={8ZfO=Zz;zu40g`2R?mJjO%KgaG_c} z-upQLR~Qb!*br3=>{`UFkL~B9G=l_h>m|PD`7@{rsuHU=4PzqFLT zjk|6>fo7}QC?o7k^j-|0-Hov@@7-WJB4kImm?_cy$yVG*DG3U9b>rpJgt?AO7e8NI zje*vh_&neuUOG1tUsoogKsV>BSM0&_(R+A@yiGVG=cLtoBO%A>naf4xA3~%0@vy}B z5}q0z0*A*x!N-#6ki~z;N|lQcw4)!}6wbo<>>jM1oD5?25YK;J3Mqe2q32pj2wd)j z)pPfVJYSvS@8_rUVe0}pi+}of*}(}mNi9Rq51DW_cm*2t--AJ5hZ3qCaN*Mc4Cwj< zW8l6xVO9;)_%?919>QU!X*cu?dB(-Rss@u8^?ZY!1UoV~6W?SE7j`((^zyMDYe}@C z^Mx90<2g4{HI!kezAU9-%WL3#pM$_Hb%e`XN774uCB7)(F;>?Lj#x(xe6dZMY8njS zv?fP~&cB5OV^6w}CSq0&{xryE9cx-A% zwo!?GjMWwT5+>C2%!Zvqk{^*v@V?nDUeRbR$OYWKtZArV+FW69M0AEHdYFdHqCp(X3Kv$JvPlrb@o+5XU` z86KNi=?pd6ALhma^<-$-Arp2i{uy3g)FNzkPT{d@03RD>;fd8e&!Us~;d19NX6q|a znP>prOFh92>eHsi(O0E|mz zFj93oIla*Yw@1sVa=$mn7x<8T&0n#vgeMh8o#sD}wG;Ms_j&s{Le9*rolkpEhaq?V zP(6FwFI zC96{Pj7<2m!-P%`*$aQRnN$3yQBculPS+`vvoSIveT$iV(JW;uT%nG(Iq$GUVhKX$ zS-e^vj19*a_9#W7u1Bl*_2&T8>r;f)_DfNVPGg^ zJ;z;10DEs8_Kohrs{6`JBdrtqAGCqt?=A@3egYiu5$vs$gx+sCU}2!hj}tm>G<`O< zL@(tI?z@0B$MSjmA8&B~1!sJvJCG9g2=|3bdGfQ!N59g3{8lPP+kys^yLcXJ!$a|4 zSppVKU&>z+Ty_zUwBfw+Eq+OQ9t6+S;3{i=L;W2NrVlY>L6;7}-Muqe>#1u{E;vft zSJy(@`lU=FH6L~ib71Gbu7@UDQ^wEF<~lY=F)hA?pZE3*w6@3M_^kusV)-lFJ|>Mf zJ}OU39wnnxy(ayc)q!6Z3Vh&HRjM~rC10^IIjxqYvbCdW=-e7CSgS>miXphD=pU}Q zR?VLjiP60-ko#jX71w;94bKg=#mVdl2pvnh=MA6ENV9nlLf|ML1$M@fu;u4;@yGRH(Doz^;lK6Z z_G`GnR56D32XpAxjho!bYwKv6LaAtH>Ut{dyuceLFQE1E)6k;8m`EZ9N8PB!S>^>8 zFu8%Bs&xm?TP*_F$Y=Ou_is>FXvNd}fThR3zy|VSc7Jc8`-$zW(mVqXJ8WW&0V{D+ z)qFPey(HQg>9VkAOL*nl0(kpGU;M)>P&CXc)2b`yG8;dH1KJ^`UUgzjR z9Nm@zq0zBuIa!}23mx>ULwuO2vMVkb9?MFHDx*cjG3L7}h2OV7l}X%qCpIuiWJ|uJ zS*hD>WTA^oM91EkFpY&zL~s9`gL*k>Zq~#`aZTo6ZrNx;slYZ-fXP@|ZK=qeFI-3S z922-hOC#uQ_CGF6FN${fE)<-LyQ%R+CS*IfP{*DJpsS%l-A`rM``A2mo1@FpEZzC` zAQSekdIMBkHD;};J#f@PhfP)+&t?WFu=|r1u%c5hAvH)4)#ZYlHuWEV_%oH}d>ls8c2A^dw^b<5 zOK_>>3SFfA?dX5=7LN5x$Lg)VXf|Xp?n}|;J;#)ZJ{-}2*IpxFu?i1nbN9ntCwbQJ zGZrfMj~DLTdqARh7JJpG54M)GS+K@r(HTbz7Vj|v_je6sA#=~8UB zo6_-H_Lz3kkrWf_Fve~L_0|eLhPNx|v*RdgHg%*)^GB1Lw=tP6)*?Npci3IpgTEYR z;Zpe&l-m}~oz>jUPu`LX)gx!acHzu$eb^(|S!B&plT=t@fjc|kK91=mtzl~f#{R>! zRm@e$fcZUhVySzjne(5KEO+}=_@40+)O2jX^nfpX`?*`(aAYjENcbB{ACbUmZ*O9z zaQDnQDRA^2U%-;IVH9Uqj3rx!QnOh$zFZ_p!C%(l+|+6m&2HeItlffTk*m48kk7YQ zZv~49@m$lnI;eEo0&j(UbI-%8aJSZk{XX#)ei%$*=6-!}_uUj0I{G{4CQf9Jm)Aqe z7Zp}8I0E=}PXp2ooLJ$OY;mug8dJHs z6!q~UB)or!Rg-JbS7z@Z z&vwSdv4~E2W_2{1J+u1*v0E>(ZhQ=Ni3O}P^f=gkNMk$O2g8Wuy)10)199(TQ}(Ew zL;Z>AF#c5*4vTT+Cm7$w+3I(N0C*#|R8OFP+G6}Ma5a^z4#N>)!IZE0m;VkZGMlXCn)t^1*+CNA@=aJ(0tX>#A(AFi-Qkufyc(WGxT6YYtGoX*oRHy^h@6 zRoH?wb86c^jrD}pq4zH@rm1$Hw+`OUWwwSYvN-1e0DhI?j28AP6lFyl6D-t zs)Tzx6)^6m8T=Bz;JVu9!djs>T1-_BYr-6I z7U9ND1!n$kJSOzt0{ftEsKjvN?ntU{ZH ze}ZPgg&16`$kq?AA}CR1CxqvsQ+YV+{W*d2eFTa?tGwJ?K*zB<){ABeLk%o@QR*d;-0eUV_eY z%PIHEG3*q+Ns&7FxaZezKBbk=vOVJeyE)91(PCycr}4JEFLRaj#QvH@me+Zj@3zcf zM~7YE<|$?}!LJ274jg2AZaszQH|tnJ>=4#mufuk~8O7dQ-X+|QELe#DXjD96$!BqeD4DDqVJK#y{+5?!JRqf-U5DH zeL6ksmBy#P*3)+zBRu4wL=$*b%$y^Of9gN;6$%M3Cgn6Qy~~iT_#@&UN$p_oKTQ!Y zRX)uA>%AZfs7zz>PfR%TdB@o$ukWH*`Dk`}Ns`qEHy37db?V) zaBIIL{m6AiX@NZ;T6~ok&z{BU{XHYfUw9b?mi*y774?|QJU@6LE4YWJron@X?abGs z5O%wTuu<=eV6wn;xNV#bKU3$kNf~?LyGWl|KG22)?It+zQIDJM#^CtK5Wc)Pp8r}k z5M@p$VXQfab{<{$d(SM~?xar3UW@SMCSx-APZ4j7GNi)V1pdPUWeQX=5$)`2!ohjf zoWr>Y{1`DFG^AVje~BLOI`64ywCfJRNv{nS2R6V_yD<2<%@&;JoPpS}U%8}ug7LD9 zD_dFuE6T++S5d_R_)U)2 z(Up@&?^~B}jnrI}X-~lAMS*xF${eM*7?iD?!_Ra%h}z@5xxzK^7+fp|r&af02Acy9 zH#ykeAYOZc#+=`bx?mxG-~;IL8^jMLt85wD_Px{Wq><475pj+n=b zBU>P_N*2{Ozk%i59{A$=4KR5t^yG&nfsDl&oN{P1TsOaju2qtpvWdWHjA-U}JkG-? zlMu}5PDPvFw^31jE8hGoO{$M{as3#5>NvWN7b**Md%r)I^JWIM`*2{|F^ybjB*NoS zmNanz4?V){!(Y?{H`jc^#$9btIqVp=9_fP54U)J^$jasFnTwP*eS#0dy*umNeb_o{ z7udW>hu?m=5c0)C_#aopg~{JJ1HV_W>BdFTwYja}`PP|_pWg(zN51ey8s(69&J6Pm zb0Biaa-4oB5EfbNz~0(P5Tdyn7d_R3^zpNCjP6J<4p7JLZhdImT+HXD8$!svl;Uv) z1~6!Gn&t`I77Up2`HIX}$_Jm`F z37l;8Ns&p7AJ;eaDF5F`15R4f79Ca&6HV|-#ZgZK#8p4;W5BWDJZ|`lix+$H-y7vA zSc>EOb7e_dQkhr4k67BOAa1S9#%H}{BA+HXj1XpoY0??o$EX7k>S-?GSnNwo01q*f0obV{KE7YA+y zLa)!ISX6p-0*;Cc#{4VR=&?wOc5<_kUACp^=1w?y;YynQYZ-38w1uQ3He%GWO+?O~ zXz*bn4cDpAOfJ~sj-0hcoXhFHDj3qGynX2jgY;p+zTKfdZw+?{{?t*;JbabgbcI_O33pG06xuLr4{ zW#B=RX~c`|73}8PG#_;QeoN(6d z@XLF@c`$*o!41ptVfD9ax$80RtdHyB`kfg&Y$gFIE2M?{>lg0Ui5T$i>)?LpM~n9q z_Hjq=o*&JLqL!n3ml!!-IZCzB6lAW zD{ooL5<)xpo8K2OxaNtwhmU7I>yBf?+jgk9FCbK{0V-BkV1v>451ogxH6Enk8NhqI+E3@#S8#vK!|8`Y04zValU6Ud2Dx3XbbdfPBz+J%SdS!F z)sB2D{oMmfU+3`M0t+MXSr{DNbwudl%di(hW@kXpWG1+~MJ4gRti7U<4-4HPFi01m z$k3M!XGc)t^h{=PqD%8Xc*{bf4!q_^r^x z_-RNj@)0=2#h(7$(#OJaf|qjD5`Ipk4dqD5a1o=2QpCZFT-MN2D6jp5Q?@V^^9x^c zdt6gNd--8bt$i5lTdz^9Gv0-5k1gT*l6SK^Gz}|nMzHO1(HL?loJ}k}iEq_53m(B- zRGmD9C8V9ktzW)^TW1WmI10PTKQl4Xdo%{`e8%6#Z#ZwvaIu4|4gK>auDf*u9Z42g z_WBXjd_MyGx&;RO#bcnqGMLU(9fc1??xZs-7V2MXQ^~sRAi*EUfTLD$WPh?K^UWJ> z$FW>E{!r+!OKGr(lUgDpZ6`Kw%rCKtr{FezznP!hwUTX%O6MEVf%T6($w#Q`u_kLJ zK6X-o|2r}r{=YY1Ii83$-kkHa5YuS5eqSMqT~HL-HN4j2??p^bhfxYWPH zw5Km%&eBx3eK@=8(}@liL)nWJh;m<~SVXZiO70c%NA~UFTU$1OIBGad zS@>I|9i9o*YiFUlTqmU3G~u!#x-7Rug?xT;tiN?4>24J6oiYMP+hr_UpJq+!LGmnX z<5;?~s|c)OlxTN+H)n3xgx%V**e&E}yUakX}F&W_2``8m4QKTJmcs-&KN-KV(404=Ef`FalC9-{4fc z9mVx@99(Xhp|jCDh~9b{i;qdOVWuq@&nvQVeo|z7U;w+YP?n4vYGAjKgusDzh5bLC z;PD5;`E8JbYom_fsR>f(wO^h#XZ#awS#LwyM{VK65-&1o$%mE(f6~$V3=_8quK1oo z%%XJ_)!OMZ*foU?d>+XTf*kqA4Pl!~V^LvC8>}km7OibP3X9|OA!v~T-0?PKJt@!X_GMnw|jg{OM1^)j@T}qqUj9DSC?XCKqUO9UW%QKM?fdL6Qd>^g!b=!DBBzj zT-jSxciRL9ub#vQ1|wjuW+A`QEQ#}V91niO-ikXMTjBF>ZS0&eff-0f3VS|pc3Ao{ zKD`vm79}(Y42&rD^7cb)Fx$`6w^yO%X?JFwn~TS-4Oo$HDBeAC3-bE3@z;rVE>Nvr zoZf4IR(qdut7bjHWwL=V@URg%eYynulU&LE`5idkzMTdhzYp&s_mHa{!SZR_=!a$$ z3@}_uamNS1?L$^HVZJTDDpHZuF098H>u%uZueJEM#T}Q7Rw9|2T)tg!yVbmj5XmnG z${c%;oBGCv_SmLzHw&!j;~5)H!B3AYG6wP)n%^);VFba}u(%YFp!KApz@Jp18Sg#^_a_rTW55tJ8H3*+jHDY+;V1~1hT z*mr9=$Goq&H(@M_T@K(1_c|=4YgReyv?;$V9nu=63wLxqHpqA>T{m09!UC32+tPTJ zczrfK@IJ|u&uWrnb_QeTE@17GqpW#fp*Umfk`ofBJ#iUZYbazg zeFw0V9}B2OR}-#XR;Cd_i*UX33S7`9OQPwL@YCFhdIcZO>6Re+xlzO>-3=piu^;31 z`BTc|aQ5flEE@Pdl4aici-BkM2#Cg&MM7v*O$HR%M}U;hJ|Qx4JhWf~BAA%Tpn zo$$nyP{IR>q*v)dy-J>RS2)i+mq{k4*U!;Y=PV5>HNzbBLMmDj!NoV_k;S%PkbifA zzMQxY#{IkKxG)D@;bTI>_I-i0iZd9ytr-$rBE?OTx8TaQbzq~C2K(J=A+>ET_)HqW z((xpX?kEBnBy?9%})v~ze8#nXU5&W4O3!ffl z@J?DyFh5xdK1e9B{o3ciuY5F{b9w+P{ba**OHEi`&NMbb$eOQU)@)>?6RQ{cs85c} zVhR`JnY6P7d;h%}n(wHw@%%nm>iiDcg6p|`d*h(S(~M8P`;as8F~|Q=bmq}myyw5%=(WF#TnrMH59$jwuVFifelioQPxTL3W^X69iM&c7Od*#8uuYLeLcRnJU(+Xf_`g#!U`2?eW z*WmC)DQ2Tr1-ENgV$5vYfyOH^gSCB7SuD&XpXuW|r!BC^ssn_| z(9at{Y(#6Nd*1G!ca_VQG&lIwkud?U;rR!hYyftcThqM=(1|2md9zU`X9> zdh{Nbg4R@~3;vsiQQLgTONYnwXWT3}-I2;)R1gMT@d4z(%KMN6vT!W&HMn|g2K}y& zaARR09QyJD=3q4Z=hh1+zeIqcN)0@e4uCGFEAY?NgJXy;g31^zm{sUczU?|fsy&X= zI_`g!|9uu_t?d=Z_b3emj(5lWR6;gI!bl+DV+u8Bfy-kFOSkS4^|gd1Ue zeIK%d7wNIh)!04ePKpo2p=clv=ucCeJtY+AuO+lKtPrO8TqkXA6>!;U3Ct8Kg+T7_ z()=bx?a`7Cw!?1|e?e@p%4D z*nBz~JJlzGV^J_(o`0U0ZCZ_ob!B+_oWIifag+HXf#v*7|9Z{q%9F@gsvbGg%!A;E z&&ZMYevpwyz-3hu=;Q{#x(Bh)%Dq1dsk;LoDnRm#I4BFYLd&z8yqPMWAZ=+iow4s5 z+_&D02KrqvR+)(hxr|4IKr{ZTzYV?f2Qlw}7byG_Wbw*7vSxxfn|tdke;>zRc%UeU zXAApKN_{uZyHJCkGQn8!J`K+ghGNp!?P&Yi8wJxl=*neF(D0xVPhyD@Mr#Ry&3G}r zcykl12(zOrGNQmxBAowHF$d(2NAez2B76pYQnlp~3`|xgj=OVV5LJ0%BQY?w+lc-8>D^TW!lREi`nf5+vF9xp`?){!l2 za!1GUUF^|2N3oaNUFD~F;VGZ(Y|sfO#AJK+_(xro(lB7{IsWO|;z5*1{m){?^TYV~ zR2#7~tKj*+T?kjgFT#OvIXN@X^VdNsvs1M`so?cEw!YtICX- ztnUZ9-b&23q2)lXy@5>uli}h{DD*{IHAM|MTpgsZ%rmJ_Kjeg-`LfWQ8-yRVUt8EDM59Y(KK;}kgI;T-Q2VDCD#$Qa{~H zxHqeY%7+)i;&otmNT-hH< zd#u`U@4er2c4-C9{-BOaHzeUFE}NRwxd@*PYoqPCBU zdk*-*&u~%nUGjgPHV=okm%_pwXHi(^5p3Fi8yDH%0{8VVag}xetjhR?!1CZ0=kQS3 zlEzi76xe`&J^Z6W>g-^(Ah*NOWG5uKqrAQryZqr56y#VbiF0yMk8^umJXwhQzW1Q@ z$qW?h%ET=@&tX;xmpdsG$K|%usE4~VuhnaSOxmmktGnjNz6r2y&UiteoZqNrPg{;2ud($b1VD3Wtc8SR{}ucKk)$ z9KXSe(ygL4v^GNn+gM9Hsks#0crm#4;{x1zh?`#(PR0BwrTFUdW2#*F6u-|+C}ad! zbP8xBgB8(8wb#LK=jAB6fO2K=66L8fT-eG<7!nRy{&#QFa8nIhZ= zqYDff<@P|(P}BK;zmA)4O<|7v9)T2rzmPDr0PMLgw~)Cogx|ObC*3{By#Q^9_NDwW zt5~wcsDkc3EXP~r$+23xCen<|<>>Ws0?iiPg?oMEEEEjgaAc1eQ6F4}+m=+2@9(B? zJ!37H`?QWuvakpFlScITv7@kHiWe^_J`{#lEhJMoo^u;__6a-r!h+(dkX&F5vFY}3 z;z$P3nd}Ev2iMclOP68RpY_P!cmqy~U_6 zu9vW!U2!^{cJ5fiHm2;xp_bL`*765j?`J9d&G9Q<*lx^Aom&%7S<~V(3k_2tREAgo3A#iCzblD;Wbz}^Sn!o@r|F_+{iNRwZ1etAY_1`^^IOVB@YlUgN`*LNU~w zcVa9y=fI*Lnv7c21z4Y71u6sD@J>J+b~^6l9s2o`T4w&E$NCB|>F;5Dz}+(?=iNrD z{U+?n-^J(xBfX!meP)<(^`X1hCucxEWZJEZeZdk*bGNG>;h~X5Ax{KQjXU{%a(^j=q4p`-xDl zEyUE_?u8{BXUTL#mJyvkfmxcS#re7iAjn;t`Mvc43|Y!ET5mnU@aZqOB#}dcn7eSt z_Y%$1(}W${H{!%oPx)Jp=V94?D?EL^9iNFMqhCxv=5SpMtNQmiZJ-#dXCvN|PCylx zotP_OhTYS*(Vmm?{DzW$#Py~*IRB1=t|x`i{^~U}IEgTWvxnixteMPM4#z0#vu7?w z_rZpyolL+fJ}mWdV_NqthnR<(nQbXwcpY!&GwIyCRXACev9im;ljCe`$VD}0^_PdKXTV+#&=aMI~+gdzvlh_1yzhMC%1P8Hu zqdhn;DaHX|&VL-`frlKXFb@VUQlC&@+P3mZ=(iP&t>-?F(p|$8jby^kIm?)t1yBCZ zmOmou+MS7BwLGjmQ_03)BQV;)E? zph}(AOzo3EUhG~qW<{hudDYXvX%McFozr;0-~5BT;xfcb{;9*h#X*?r$G}3BkEp(J zDHJb|XJb!ofcXnG**g}i!9P-+jkv?Wg?veN(Gx}ZyuTG^CcY>Bwc%*7p@q=6cT{j# z2nvJOk!Z)sP<3kwOs&&~5czBHbjEDXH}?qoGEG5ytOUmP7{IFBe25#>f?9!S$T%wl zzSA9{K;;7|7HlS8IDB#Ji!=P4GA<Pk)v~U_BXUpGGIY)n3F;$;(kt!Iy(Z}<< z+6YG%{~*p9tuP|*1zz3HAUK=C49tK9Cc|LK+YBzM!(`IW-AUtzU(lD8X>HX5NGZ0?}A6urP$4HZV>^FYyEPU57qts2QPiwiI-2+ zqU?r;XcTw})un#ns`=mPyb&3;;I1{fuBXgC3Rn%f#Y*gfPGPPH{WDlVH*C2}bH}o%=3OB)$&99c=M~ZW<3uXFa2CGP z%i;}<@$i9rHaX{Njf#q9aQg2`Obt2?1qDucFgXmi^=-oK+d|=7&`#8iIt0z@_u-+{ zW*~Wc7nvhy--dpec8mny|ePbWin zbSrYiC&*dXg=m%wOD$eud0IEzEXqXH>0*rM!i~7Ma}wtpcca5fQp~EHG2)qjY zV1{%tRLgVhpg*TUjE;h-%@9%JO<_v=Cey=mdW?hUGIUFv$+T78z`pPq%w_ABTpv!6 zVI#Yd*ZT<`m$c*bN3pQC`w{B+v=Fn^0hrwIi0bOK)A*DqT=8W&DKz|yO|ADzh>X;nhUX<%i)w1R-$9ClG+J;=YG$?B#Sfb=JMc4})7v>$$lE!EOcBpiU3 zxLwMs_Aq*O_e!+B)lYtDJw$_9k?@oiV9ozEb31GWcH)o(bM&?vd&W|kS@KDho%&pz zF)x&0$1N2Yg@bQU|IIjUw_yb7;4P}tW; zD@|*`@t7Bma(;|Bau;XGe}ik{wYaAHJ$QMw<1CFwkTvN&{!irlRxmj1cGhG1o#%44_8g}`P-(y zhBsR^(b(!6JiMKR_kF&@z}{AL@a}@%NMSblVGT^a#XTdY-sb!}66|U&@%Cw;8`_io?U}(Re1t6{;`hU`<~%7@R|d z*lX}=`+Xc+dKn5Va`9uZH{{uJ+=k1l;I6d|udJO!I^@LB|MXqjd2uJrd*O&b_ZRZ= zQ?BEGDmlb#xD5Ygi9+|kQe13n0KPqUuzjC7XvPO&rHei&Z#2M`D~fRYRxq{b6@k9A zZN%V1ISE)l7dB+_$cb&2;gZHNeyQAZU}M7Ql*H<3AFu8sZr z;*6`R5uURC0-I#D(bXp#W*TxXuy}hIpD%}Z)cr`vzSs0va0Auf8bp~(p;%rkL|d*l zV$dEH{-F|KcHzRe7OP4X*w1~Nc}Lz(VUL|v=NX!cu#b9o-+Llfi=Ep(@nxnT!1Ab2 zns#yq^~&p~^4Et+)wmKqiVlL<(V2K}e+4|~b-=9pQTV(52v+~)p7q@9H^^Lx`I8rc z`yO!|@naDfkT?##0)Dtvyc*`ralrT7JbZ@LPpYH;i(D|5;kU?+^1r43B8%!xFulhQ z5=tWQZ`V_p<&%#ytp0-bNCmcr$umo&nsK&)IunxLh^sx6nP-}{Sb9!^%aT3D5aG9= z+mMB7lafF}h3h^iD!@F!094Dq#9zy}Ao)BS6PgXs#o;CfczvJ^Ufo!gc!I83B+3qo zNbooAlwxmIeB*t5Da>xnNF*k_c3h|<22*DzWAP9HspX1Tov;gJKlzf7$RMyk6ASA& zGWTiDeKx&u8|S1q=6YdL5P8s%*>HCm`Pu2p3@$U`*w)*aiUvu%?6jQmR$GmqHs~{( zcb&(gbdIy89gg=ymcjIK?k>3@hB}VzM7wzzI4V6#CsjzY3%ykeYk3yzQb$Rc{Lzk` z!@YaI__ve|9j<}Do6Xq2uLT*$AJXi$W6I3;&Igz=MT60sJOdNIC@~XGn35Uk5*%g! z5R@Hj29b_(FqaPiVT%z^FAgNPe@HOfJD0?Vl8CLK(ZsxpjzTGYp*oR){fu%jDV1R(cHo-b)PcGh+m{t;KyD?7Tj31;4daml5OZfLWUaqZ|+e zf!8acbag4r@L2}|J6?h2vzLVzDw`pub}Ke{JcR_GModsjf!+0r9JkpSw7*)iTW3~~ z&GM_+=1(5{ZB0&W^X~U_kBTEZ=?0JM`_Ey6`I|99ScyHP>4HNCU*Quj2Y;+#D>^-E zp+66e@t^nc=$AwhE?aktr|x+YPS+O^->RFiKS~weeRu#yDg+J>l|o9ICArIY5@ZL2qN|fW+<$A)XqJ zpj8$OJ^o=J|EdS#C#6DUGUv&dl@1VX&g^%I1G|0mn444f!kkBQICh0LJW(`cikA72 z-rrLg(P>sRU-uupG1W!m?lOoQ3&HLT510{OfZ_ZQk{?-v%Gds*p5pab^Zp`tuXu_p zs+!QkBnE?fMcEg_YFIozk=?W9aiMO52`*h@H|GqxRytxs_Z^JyU4*Jnny_fyJlt;l7gJUl;oc39YRWr_` z1$APqSsmpcn9Okwxf#gh)emr0o&cCv1|c=zW*^)<^ZL7sa4u{gE$T@F&xRhJ(!v{1 zRo+ZYea;F0ukWGa(NGzg?%( zZeIh+S>*tR@ zn#`Ge&AW80cotL64w5LM!px9J0hvvoA-dx`+;|xZV~-S>UBah{^LhiONJbYMLd_Z5 zAr=??Fl9!zi?fq=OlMS7^;p?MlNh-Q!phXvLf~S;szo}$BoSTKGv$`K)oU@<@17kl zepiI7PYGVtosFXr0_^;dsbpxn3VXcy5SZODVBfjaa~>cQ_U}%Co#8ERBv zB?DBL$`C=eY?=hKcMIq1`&kPmet}5cH^Q_UHEi`fPuvQcq6zo?_?Q zo+ov5Eh~KVA8&r123wP+TX^Z=b6osOl)hYSh)cqj(3dx3$Zdh$RL~#_V#7DnV}+mK zTDKJq`7xP^iEt<$5+1vv*=Y&ypH=|W&pAoh9vw0$yWN8SOVIJV#Wwu4?L+61sTqJc6 zF4erp+O|j#>l0$fL$1Q8f+YL4f@7ZElVAr7vtYXQKb&12 zB{o}#Fb_6W;8Ybk=E|viXf-OwpiKgb&JkoTPCAayo|nUbt~&l);|j*=%V?v73Xe(l zBwK@B@Od`@QO>#BDsu^1MP{+i3iNootn$h!@JiW%Ee|hoBH|VYmPfTyK{nbFtNaJ6F`6DcB%dn+z8`c~C+R!tb^R`jP&O%5|Uc1QRhdU(w6W=E2K zuL~MvzK{ShRru~_0hUoy@an-6uq*U6Zuh?o6=S;WKi5pCxx9`&yDkr|CLLux6mEiT zr4Kv7BoMMx&$DiGjbQ$BPuBY86*9TYfgP+dqKgC!*jhBkb*7`3e(56azLtVo!VfU^ zf(TwS>cOVA65jl;LM&6K3{4J_tnu2T;Cp2v+riDrl|?78>W-0+_-hzH40%E#*In~p zFcq3MA(q>1BG=zVps3y+`m%93x;-h=<^l2ZnTD%59ve7snfY!*VRpSaL(4 z7&AEb(*_H~CBntzZ*v9)UGO0F9tmjnYi(hNj6cpkd5=bYUXD4MfWFU!(M#bxcD$cS zAJ@m?q``G$=izIZ(=7}k7Ad$Y&>EssBhburJM^q`M_!*dL>B#`_eU;5;@0In?V(sm z?$LrpBo$Uc8oYUx3xZkwa8eFojkz3i(xVWBPiivWzL_8zJB4K;;~m?9W{^`UoMl|gznpSql#3PB4_ z(f`^BlrK%-RmyIJl_?@HY!?VitbJgBp9mpOAA^MREkLU=$e+b=1-b5+$kj9$)HP(5 zo85pf`NmB3u|#;bNQa5{hyd3{Nycw90RFQmhZ*}_!Qr?S9DlD2OWTEL!_Q^JW@-TT z#-5>rXNFPt_G0vNHe~0Rr64$7UMNfle-Z?xbTKQEIlZMItO0C(fwLHncG4fk6ji{1W7ST zLas1trvOvceiFvQYT%LVVHmYM3m1OcLw2zbc{W27qT2*<$9XNH-FAhWsrk`K|9!zZ z4*Ixi`eat~jSsgcoz5C?D`HhYGdAT*H&$nvu)_}o*m9mGD@rG@&acE+!Dmuzu?5$U zSs=llRrE#^>tU4gEubeh*P&6CDp@0tf;n&GpipNSu8`-lqBS?EoyJb+2ukDiXxPIY z$ue^1u{4}BnG6o|RY`M_4k&C*rb~1c;O{d%oNe=-=vD5<9Mo`T<>PeAGdSFJY9cs`%N=l+polVNc2g^t#fc( z{3y8ZOar}^E@&5d3>x}I%=zwDP*Ui^99-TE!lC|5`}9Vz@Qq{?jGuu{QXE4#&Fm7- zXr{O32IPMZV2rJjVB;EBM&w2ebPgIZGu`}Qul5_L{ktA~%4b5|h#7p|*-u@=rh-Lv z4Z4P4W0dA}0E?Zdb=h$>-x-hejIggt>DgWHKbH zXtT9C6XE%p=UDSojB~_mW7}C#ICnaZ1iTZ5Wx5w&OUrk1f}0!dSn`@=hj9DrHKAl! zPlUOaV$16^9fvcO2k6QVEpW2%7md5bea~uVqm1n!$qaQso=YXIZ*aj~8h6p;{wefm zkYh)qBGBmUVs?ISBCbnyXE&84qQk_KY~P0qIP}?9)7C;zJLmkeyK85Kq*JUqwyaa~>RQ&OUKRn61W~)D5L)Y$h>V^g79lXP?1BIszJ^??U&1R+yWx5H3EJVs;3w zA_Gm+n5sE()UlcKBtAAoxnVt~uXQDE&{pHvrGO=KMVTYFML5s*OPEa;&=bRvu(V%` z3~5Y&-mksH^zc;vw@vmii<^0aXd=uk^216l^S|vuAr>Tm1=H8%>#7JQa6ZhsiS)zxWanQWj1fF4U9ecK$ZI?IF?5iU37UC@$`X?#=|#GdJ(4JfEt>OL>j|p(;fW4=X!;D4I6I2L=JW7=!!O7)ptt=#=RUYVgb z6<9C&8?GeQ<5R6%(Ea!drJn=XK^a~RYbeawnT{ck3Gxs5;8?~DywISAS36&$`mcqw zS+fUoPnnUD8x6QNs*9wDXQ08DAxJHDz?(TMV3Dl_%^utU7juPSq-7oKcoYLibxeS0 zy@B|dFNow8X~sQXf|vAR8bjw5(?9QKFsD+C(ce^``SfrXE)ki+JdF3mdndkw;-_VJ zY+@das7j&1>5Wk3u1#-ljVF2IS)^Y$oa)wXhfHfb+~`Un_Sj_%_a6rHk^(H$S7DB2 zP&9F$$wcX-Vos|$L*MVle`B+lm}@2UZJi2pa^g0kmGKXlKn5zcAHb7FF0cM%GhAI) z4#D23+X3t@UjM+{zc%t8CO6?jE@K3T7ijS8LmF#M1~Seu<-3Y zTH0TT!T;^SxliMNmgoHnJL{a#oAm~Wb_{iumibb zj0wj*{oC9CYPZW!^-2f`D8yiLcRsOIUW#*1HPFf#&*=<<7(5X**IeO47Yg-q`M!(t z?1l&)oG>?HjnD3fgB_-9ur*{_KLleHhl$gczld(87R-0egXl0Y zjVV;(;g03p=OCz@WMza_)oI=&e;ZfEg;sS$YV_0nJRUrC4X zG_Lz{p0IOXf$B*SvUr6yv$cH^@6<1QW+D~j`_10VY_R^%>@oiklQtQ7@=td$l0F+r z#ttln0PCDm8qY~}>EU~2+* zZ_s0l3WA`|+MM&jZH5kI&JQ<34Q9R7Wu;WY$bhCKyRXoVZ+Ey3pDnATV{PYAsl))g zmd8@1TYK@>pGLA}Nh0oj8wiul@=*7889XoL<3@o_XtcSDeXG0R(U%y^$*q8;Im=K% zHjLX{U#34d3W0Z>3(>t*%fD~Mz`GxFG1od0Lf@rgj4~G|GH61R_Bs&ckKk>O*YHSA zgte3?g|6+xi21S5_3$NTrJF+#*IAMnnn;ADWiTUeh}#R6kq|q~<8XA=yM;c1SuD{H~{F-k(8JZzZZfp1_>d3dZRpGR)(e zB-D8*&Kzh>N2P&xV7cuYhIU_rok2hvzT1HdUkcH-orWmu<$#Bl4O7y43lq(9 z=r{X1jJy&-x7xL%qhvgF4}6OnS-D*1qZ%g-P#SnH6>G2M(7*N@uuU$3{H5RTSxkGRG6KY zM5qDp7cO5VNi(-qqXXH>zvCK<$7Y`4(eE?y+iyKGuV)IC6AB~`1Ix&yv~p#F+WC|MPTGA};h{OSwbUPys0o9m0mw-~T9Ht$E-<)-Xw%_XRnZOGQE z>7x7%RW^64I0hR1!^`>a=%mwk@ek+JbL-W?^2der;1dNRF`Q1dYFr?F{vBFn{RBcf zJL$Vr5vF>QEP}f_6Ej;6Z8JExeDh+oyEBd1Td*D1E|XzYZlA^zl-p-%_~WohG03YN z!>)`|P@Qdu5A!4-{qi3=+A2lX)!9(XAU~RaZh)7yeF_%6X(0*Ti%{Ld7~Vg3#KU`c z!?N`YP;6xo>>cLZX;&klaQYqEZXW~d>Z|zke{(=_;ZEN4i&1bv%8~>=^8>F0V=}+P z4L1D9vN#>N6fPbzrY`#C5c@5k$|o3dtd~A|UU4d{eLD%We@a2=;Td?RLSix-&bj_tvUQ|dBitZu?VX4yLet)wrk1lB(mK{ z4_^D;C%?D7B}dQQBfAHz$%o-Q(&8pl_&j$Vv7Mnt=L)>B;2WNzAIF5~gHy@0spcv* z|C&kH%^jr|ALmfzn&}85aa1ST5j&SjP?e}K#GsKTtDK7@G@F}?dMhLKf zcHyZxSrC&Pj|;TQL1sZN?kTN!_$}A$kB}_(8-{l z40Oa}?w1rY){~6BQO3NeyhuFN8AD5(x8SwI)3Nf^2z|WX7mqa6@$W9pMg@^XQnjiP z Thyrvc9#0LdVHP?Hu-^V|%ndF(x8SB1 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�H3- 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitclap.wav b/osu.Game.Rulesets.Taiko/Resources/Samples/Gameplay/soft-hitclap.wav new file mode 100755 index 0000000000000000000000000000000000000000..b4cfa2626511db11bca7ea67149f93702a8961f0 GIT binary patch literal 573290 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

  • +*9>W5IUw5urKo-zh`hF zTEE`Nd(}H)yOKBC?J*1W9|SVXs(C2OwXwRzhC&v?oJ_B&O z>Q0cugK>Dhq>&;^?XdQ%Xl07WUVL<4Eq;f6&rAmfWh{AaU>)oBB$cg?}AQd*qBM%x*00 zDTyP6APpMfkwpRZSDBXBYTEVo8mpc^i`v!ln8GbZGXFEcBHZV(%*m?sussyMYm~6h zCT93_?k&M(dmd9;M$*=vXE-Z;Dy=qniMv+Lpbxoq*cPQq-;UN}?>-IM*mMl5c21%I z1zRkX38EG0$)NuGDA~50<9X{t6s?uR0{+I))hUwn-@8-_|Gk1#vQz18L?(@w3#Ii_ zvuV89ESkUi3_TqwPLuo3(CAV-7FBzg8oP&9NY_}>@BO==KHHbI)hz~nuQJ%MQw?Nv ze6i_y4onrz#bg@!%>4+fz<9XC|XfLg9sUp3ld+0;;BeGT%n1Um< zq^SIp$tp#YgjAvMWExNH+axNEg??aSJ#kh}GfI7NgwIk zB_1vnWYX&;GPrn!KI!M{W7Vs<+|L^u(Q?TsTzdBy28%2g82&_jc{>t|_w7X*QHc^F zyYZ-H8)lzek9+U&XuH%7tJWu?k&-L^wTegi35apI^5~>F2=B#;`TfN**z{!B7YbyfRzpvh_ZKd{R37a5{<| zE2onG_f&j#;35kcb_yFW%9;&xy@k)_XTf!&mnhiMu%zQ5ZgD=039}fch85w!#=}@T zxeRrL&vy08Q|KJ90&nE&;N(T#7&A=-x4g8)KJi=NeIp1(<|tM~e>sk^rxdA$KaGXW z7W5@J7xypqp=iOwH1bg@d4F!lg(VNkI^rr;PU|3*$YRtT-a_h)!v071E*YitqDE>3 z{kz|d_sSCKm*zEWO$ni86>T{ArZ=8^@ZzT*vOinQXn#uW)nbU8Xff$Sv=dBIlAUtUfk@ z)KrDOhGGlqlRk)HtJahHgA|t;6>R(Bjz>?`>2q)aS)eVPR~W#ftc_ZZDNi(*EfkGEV{l!@TYCVmPxD0@Ze%BSMwyV-+DMneSqnP zO~uo@4>R8l2cc+o7hhti2gasz;cssbyca3u6e51Yh7%`wn{lcb9c;xE+J*CF#3}yF z)M(WE)XEzPyTsBG9igMC6~`y~Q~B4Q`0aZpeadRYxx%cPEO1`jg$~lWcoVblv{L%T z0(_D~bbo0iY72LLwQ@6Xb7`KC2UNm;N+GmI;tjN(HYe#T3!#4Z5V9LC4O;*9a)AlfawI!C;egMUeE6^^muUR5WT*+)%JXIV6Bh;*M z$Y2H-?~6xkse2WktO6GdZ(}Lj8Zh&zJ^AVg`?YDVWMcRL4~ja{<4uB_#@w48j691Q z`cKoq`8@pZns6psv=w!%PSTTw*FfjY9XKa5FKN~|pu}r@J;{p{{Wi7Jyv&tMzskptD+lhg)ngpl8)e&)EK8v6)#TPD@Ux5F!@jnF? zR$ki?x<0SL>I3)6-}UdpAW;?8JuVTqN}gdy%+BG#{7=k%?n6uv{mru93c>hMa+G(r z5bq9?q~X39ICPpc=|_d3$~B;XH9JsFPM&NER$|WQY^GRlj3r^MymYSy)}cAKe&SH< zd^!?DerWmfFU)mVIO zkidd^gN1DQ0rq45CKOp_&X#SqN9(PZ*okyu=HA)M3ev_SSFX?A?ra9x22WnP=rDNO zpXE1BssNFRA9;CEeQaB$1vVR9FxUJSto^5eK9_Gmt<(ziEc?lM%CE;uO6p)?;EOX~ zxq{KbwWx3B2~pQWF(b$pYQi^Rd%-(1pX_je&kC>3G^8jY*7Z1@WCHnfr@Ih`5}=bRP6T;7U=_4-&;U6M7kSUWM5HZr1O33oKT= zVph$6A#lGfn_2%0G=lTYM);1v?TVUkH(doIzchfl%pkP-zJa@nG8p)@0G?UZ!;g%U zpl|03TFMte=lCe-+&u*6xTwJ$JO}+p_Ckx?2hQIy1|FAb3x1t8PHixP)%EC^r4Mam zPF`AItz5~1KQ+R&wr(a8&;wtmO((@Y58?Du4f5*v40CV&W%<{}V#Q~5iWJj9>={k# zuW@)i|2u1P0=)d-5NpfPM9re-{IS17ForYc?izdpU8zmb@U{dDUhD?6w1%-~O2K*1 zof9`b4&F};`HzCjELusMAM1D$yp^T7q9;w9ciPeNf!+1Ih}$cEjY=?Eq&k;<^3GvH zHNWxp;!32O|Jp2ij=-6A1j4*!LKbwyL5QCpNF&!;!1?;p=7 z+!JzYR`V(LrI6ZS3!SlfU?`CVeF~yn`fq}?4o%j0N$6IbqR2_V@WBaX8z7+B9i5h5 zBy0u!5sRSbaCb##)gJH-_2z%v-3EHw4zb76 zy13@)l4RZWpnTGXg=Bp^fPa5x5p{O#W)~(-rH-B9OwUb%cKN$ApEK|Hti(C2`pg!- z?(jqAe(E5X9nizV;uTCdaRFoQFA8uX&Tqv3NQ1AsaM#0LK4DQ@N%R40o78u8k|1s^C@esqbeF zCE_G*??8vQEu=TkL&-J!0NFeXBjfT|nzPA;rdeoEU*#wYh4I4mZwIT?v?o8Km%Lno zIfX9UWVXEPEvq`8z%?}AW!q>4q-QEqwD>o037A07l_uecp&wYp*X8)*_cPYEWee_f zt!9_SWl+RzA?qI-2QHCOEU?sm#uh$O=cH|V5A2&Gr0)9;)mWL>#~#t(C* zn;(rxLu`=U*mRv$-95$<4xZ=t{_1C+PP@U?6QZd+CoB=VFQe%nrZS5#<5#cDcxe>&BahEcSOFU{L_ zgp{vD(4UqR+P6KH`VK{trDqgL-IzmHWrAts@bTo5Y)*S`8qtf|8_dpk5$RSJvyi_F z1TM~iEqXDBbYe$9=t(hwFN%Y(jlJx?)j}ArI>^+j9&-ObkEGf@gkKH|XnD^IcqQ-} zxr5d4%yKg=rV>c$IY>Q6HgXl`Pm)TUA2YakLAVgq;o=(q(xjw{)!H@kFyfGI9l0U3mqZ1 z=f)(KzF?C#%;oYbQB*A}i$*c3pk3FuLD|RSlxutvdTTG!^pg=VVtp-HoU1dv_WlK(oimv!sq|2%)CAVv(?;V= zrm#arf+O~<6)UU}_`Fe7?9TK|vYDC09Al$MBm8QGyXJZl|5wND-eOH2lS4U6>n^sS zS_$&@Ze{Unt3cW65qo^^J(wQ-$u3M6!N9{xlp+@kI!UHf>y*d&51mOR=@Y>N7ErZE zF{ip@Ed?I>z^6K<=LRSz%F-ZzUV#p4leEYP5W`Z{_bCr&w|3n**J zAZv&`PF5loY~;%f3hOh5jTd&&@RB1i(NB>?vcJKhwnmnqs)k!5Z!vc@8!Ve3!F*KQ z{@-~A`WZ&}s^tiDO}PQG3sSh;@7q9g=K?l0^)sh*a4!>?M%=t2!FgIUgtc0|DGl$p_W2O%O~uP{rDnj*_}}Cd-|lOP6A=Gvx^d6danv!WSN={-|+G{%i_`ww&RL ztTvN&L>x%26S{-lhT_5Rm)X+paVR^{lCPYvjM4KEtUFIa#o%$sO$dj__CFva;Q`#S z{0MT=K`_bb0ECvAn7F7mo1IvGjLGt46@oI3Ics~fXE7()rVpQ)_L?=!p<_I)yRw(J zxwMknm612Td6F6nOwC@*s-{A<=iK^tMYK#J7Z!@_Cijifn4Y8BI*VBzN_m%qnR`SuDK1iH+sorA@eBN>cL|;`!JF>iuVr+XMDc;toq(qiaix;_3fBI1{yz`fnR!@Lx*%^F@Rw5U=Na!fsvw`Ufxr1&G z8Pc}UCk@Xz^k#|y{eCOB(UfEN3J*-e>Tkvr9ljFp94QfUVi725`iXzA;|QLgei)K&9TR5EY3Q*!0Ar%P z@uS@|Y>tk^-2$Ub@`ustP$Ts0JC0X8RN&izWK23=%2yvT$0#UZn=*%j>ws`Re0PW$ zioIoCXLYEpH=2d)%cPtWQC+F}@W=?TR- zYoSeTDV3b_#+wqsBwrAOCW#U>-Y5o>inKW;KW|)|_yBg@bVD7Bx!BXPNT{0Hj|M8H zIMy;1HyCMP=$90%8ZrQ?iNUy9@Ho1rnFxI^+K~D78i*W>Gc#rnc|M?li2~!DLjMVUCNXVsKXAY~1y#6ca5Z(XaFx`p>)s&QtR- z?a^W=md(VREM>E|sUaA+E#J&oQ4!^bHS^#s4Z)J;%<24SX4h`c%@O&)MyqFnnvNg2 z8hL?hb~KHuUjeD!ROIz2XM8a9E9KRcrS;1xC|-3!}ah*w;E zz84P;>F2z&L-6SK$I!6Z6|-NAL-LxAV%Ao8dBP+#*tr#%<9lfC*pF{DkAvl>2+Xn5 z=KdJ@qE_BkR&;y>dR58O-|PVBdo`K%jVa}ILp&+wObtsu=ugtMnxs5ipRRrOpsF2e zR5se1c9s5NDZ=aQh-!X_;ti&fxfr58e&m;#*2DhuH5{s|Vc5|d@bn`mc$g;Rp2-W* zLwqAHiSoxiuj6rEcsPb@??(Cf5Df90g&*|waCF>!w3b{hbb#sL!>B!M&8#Hw9Xgae zJSF)SQEBRGzr~`aTGLk{w|HZnC5;v4psN2CQO$|BY|WxobWgsP$p#mC%uJ zPBN8CFdEH50~4WXS0^`4`XiLM|A3TkJ?wFsgXRYo;g3vDTztk4Wmm?de*8Wxn^%BO zM~7hsmxlkfZ9geCl$NKx5Mg(rmRt^R__JPt3x{ zk5|y+_jUNTUXS(^zsDg@gx$oHVdeu*^mrW;QS+~(c7crjQ1f+3^>DaixVd-hXHfS3 zh{n$1Sne(4|AhRAm~|@3>{7+dH=EGMUKC9Qm*&j|!9#L)JN%t{o%231#w=8;quh4) z6+Y!#7vFyJyIChUmjzyQpA}2MYVD0CeSS4l+hQPP638;DQ2_(c@ zV$hk#ur*l~H>$+JvXRA*G9nYCdwy{i<~2}#FR8-$@@Ne0sjA2oX$HwkJ>Dob3b=F9 z%>8QuSD0SO^9J*I>DlhwyGJH`;7&J)@O{nC9cTgX=RJI{n=RsnGkp4B8j4(-YZgA? zA?m7y!gJ53=o6g^-9Oq;GQS#beSL=acHIZwq#kEkjK!Pl&f`zHVffTJ0sDrD;k7H9 z@Vn5V8CtE4l2vMmg$dvqC@b*(d1gNUeTJO1Dtu&38@Stz2Hl4jz^1kteAi8YF@lG( z=<{6I{murvYnMZ$z-|Vvw*!;e`%rbvQLw8jMONhnoaI9--dhMi_xI!TpyzOW)=&KN zQQ!e3zv1s4TDWY(BMkU#ho!yO1h?B-eEB;MOOvK-EN5bqtsR!n6vZlI z11!AN2wQ`dQQjmLRDAwI-a%&wY25-Z^`fEg`a-ViO#_s?*5UlL$6)miKeLZB&GDp| zkbe!2MA_>1{94I8Ow5@B7yp%^-1&Tv4`8V0L!hg19nZ>$pz*z{!X8x@eLb$Cte7); zZ9R_Kjw^+%k~2E~I)Kp^XQ2J7gZL>(=tCRrgLzXdu;sW8CTtytIgfF*NAURMYX zvqylp{D=w-H~@z!o{d;^4t6XYMGviu;TPvbrfchA&adS(%vBWaUA-w-SyRY^3f#~T z3rv5zn~q=IjQb}~BvYvftVxh!?~S5SBz=x)=cGWi*P|F=OZiLj^s_|XI!qn^$!D?0OCN#lsdr4%Z7$r{afju78Oggo?_~RSMzZqC z18k&01-rFd5e^(NBB`eWCm|J1`@ieqqTEz!-W`T|fmu|tJsed{!pUNO1jZE%qZ?5N(_< zeW7oV{0!`(!Ks3XFeyBKN>2h}}eVBx?ib16O{vsw?`H*r?6TWyjmzs)SV7-Kp zm(uOWC)b-<&h=+_bX6rQE53j>(FfUyiq)9qo5vPiONRy}3Hlb7!Z*B?px8MV*t4nH zq;4%w={|at=q#{fj>BlkkkwT6OPRVq#gKB{a>|L?O>^@jNZoBd)z3akSD(s~%CkiJ zuUwg(I2}vN6wKk6(-GS6^gc9miKKW_2`xq*pm!zisBU3K?V4eDRkMv5jC8|3fxSE{ z+;L7Z9YM#E?a<0DhrLi&L^WYA(zrQ~%l})*2iz8VoVQl6F9qUsb*~J`<<6zvpEIfL zKqzeyp0j_3#?Yt0Rb*U{L1}^BwC?i}dbwaF?eO14SuHW-DQZQNnhuk`%LpnCvJ<+g z&NG)+GGyeU&GH*XDQRz1#mxh4OlJiL>r8(04H~aG? zKCxo^gLZC@sx#}mT2k><@(}Aiq0A=g&1dVDSFs1n%9(MW8i^krL8TKzsOX>+$pl^` z=Z)R$7++1}CiXHH^?JG;I)dWrZ{{#+r@HSZ^k0xJtyV@mvq*P-YI&1+$?0iYCy&Snl!3cij1PO}tvu zNZ>*M89VV4U8E2`JqW`R?qnf2Nc71bG!_?$s!GkN!@;gWB zQ5r|}yY~?1F_ds}C>gtH(U$vh^z4`~ZFD|N>whIvk?H{oEzP3X>*3V(B848Pg;P$T zkWJ9tPxEJPBdxnYzO}o^qNI;?tFI#O$YIQ~PK&%%@0wO#xyD+bE@AH`XRvOChb#xv z*_<7}*x6YNSy01o7Ha9r8!j~OSBlQ(8zu8&X6(3~JW?52VeJzVSw3t5G zN>bd?y)^Jenl!Uw$nBvEiHhzbostv^KkP_)5&5*}#&p_s?I8K&07b71r$Y z6Be-@dhJa4#D9YSZVa7TJDI%PW(xD@Osbh=Mk3udq%=-}9x)S=JWD^2`mo@JyoJD3+#rb96;J$^Lql)40w*3@2coC#* zBdF=eHSl;IFYF!!Ur%m4HCv2AuJC zE2gp3jyG4IOS|O#VAPpt>TN#{T8Fc!r~N5({Wwi>G2$q-Jsb=jgmA9($c`c0z442D-_c-4JGl4cdzEVskXgNr|zwLPv79*A+IlGY(gN z{Ke{5?m($L36e23#hyV`+7M)d`uuuwzc3mdlKtu86fcPC^CQKBIxO2w$Ww1h;B}b} zX*>`$i}>@E{kB=e7yEu^E$hFV$*gT*a(|_vU+gwp79a%$;Sx+){VI4%{4#yKeKO{J zSA=-8NQ|r70_OF(I4x`vxVIj|xNXxQa?Eb*wUmHa5o^$H-ZlQK#!?J6NnjzZW~h6r zjOF%<;ZvV#cBbVSY*;>=vOnJfo5OR2|AI3x-^`!B#jb<}7uL{n^E58yga@^ce^4H3 zvy2+$&Q%UqY&t|T1^eSrTEa$u~#tU6=78Oa+ zhp2SZGcI``mcGA^hFGU4a`LZ(e{KnM|D-s6s69$<{t{SyJ&vB#SmFARg>>_=z`sTI zu(ItFa8F1w`(&bm2DiTPH+5cvyj3jMz1k6cE-L`3z2(EcXTp!9N4)R8%P?Y}p5QEr zg#7YHta;dIXtnsxelsUVLo->A&Ru49rGjs+lcGW=Ul92_i{gHK2Ca!+bhgwG4NmT% z_D(PK`WZ^L9Z`5TUf5~e&Ji*&9MyXlVZP}gs~^0GO?pe1_O(2Wnev}$hsXgO@=gv~ z4|oag^lFf8{0*DByP&bv07mWm2n`=w_~KofczE{;7CCnoN*nEFS}i(g{XCe-DX0s( zz%-WitQfW*J-}*LUgUSpSjCJ3f3w=E{d|_z0@}r?L(9q|)M)w>9*P!HU%)h!TY8eR zCkr`A(W5k3Z8;_lJw$&FMdK{Cjt+m0!%O!SXqk-QO3MAk&R^Stdjy{FpvY`Ad@Kh( zfd=TX@&hEk*2XZ~30N*!22B-e*i&D~EuYTe>d*=7wvfT}=Zl%!f}e27@CXZzoCro5 z=1jJ+rF{KHO(9b|l6f^H@b8N*vY77M6>9?Y>CUw`T=f<&+Lu`m&VK^PW4t!@Cr6N1 z-5kunc!#o*#Y0!ge%%ie47GQ%fxZ|Axe}{ z>jEEREGX;LQ7D{hOPc$?fNjzkO7R(mzg^>5m6Q%%$u6wex@0bW%WkQhRA!{%Qk?cfN)yg$20st`4mBGewyf zVXXAj3m6|DM(^9=AZf=8S`e!X-G!R;BsiD%Q}1Jk-LCTgb-riIjYHY_$h)ki;Uder zFpDLRI>tmq9&rZ>&$6+HE1@pQiWPtQ1%W!f6^)u|m_F$)*Za*1)pp(lqizS3NF5_| z!5X2Y9w+cj)9_xAKOXF#h^>yHxVcCdzl8^2rule`0XJM!b^&zD7UEhU?o^>NI*SMK zGA7wDe4`J`jXMcHe)q8EC8^Mos7{)4G0;AJENu#AwoYE$HsShlA!wIZr?Kx_@Pe)ccbA$4^sA42~_ugfq)po zDx+YC?@{Vah=)X%SPEEt8@j%3rIE#>g#4pD)#f{4mWCo(u82g@qp#UwqZ4@L;Xht| zpa?CZm+@OAD=^2T!ZdCE1zhnYg=D8-cs+*4%_GHc5D^1fo!^jTDNNpKJD6r)Hk8Z7TCvc>OO zz&d?37jhl(xMMaLUJbsf;K0Z^a!;0If58G2nt7dbCVN<)H$H=lC7GRz%_0V{UN2Hyo3bj9*C zOMWef(KIhX=p)U*cPGyaPKy|9ma3usPh3#?0g=Na9o+igDU#pc09&7JqLMA4AkwH# zLuQA8rc@fU6A^s(t#>(v#FoKAnb9N> z@CLH$_OQa#CTLH0HY;xV4_2ihTsD+N_mw3Kc54A_EKS9{#8fWiQ8K36FJ+xhiKutAm2G!SzyfPaI@lMB zcZFW!z8N8Co9aiGPtL=Zok7&-qJ*Z)B86v`J~n)I5uEVDaNwc>xl5e~$0#qRxcwhz z*Kvl^_4vcp&R4>a6^&f5(;6%tJq;9xZonGl@vz^{8zmQS2icB5EQtFE8&d^8>tjW9 zQm_|t2P&w3VkB<9Zh%%RGeE{^IzI04;<9c`#fWub%=3gT8pRH$qTm_m`IDnSr_s2F zTS%e%KEVa@qe-WlA-*k)Y&30Q$lkqzb73KGGtGcx+8=X6R6nzscT?f*f;{$n;wtEI zb!NpgRYByw)a7H-UvZ8@o#4IVPcCyG4>{UeoRiTY$c8y_618stwMW4Hj8gbKLjtnT zMZtPi6S&Yi59HHQ;o1dhI8=WZ1d^6B_Z1vh^H(v^oJ#l@BuZWBN#NaJLdIEhA^D>f zHQn@ts~?=mB3To}XL``Y?dQ3O171|J<1MFfTaTWfvIE6ZG16Nr1@))v*f6I|F5mhW zKX39{uHvW>4A|vXRPHSUyL(F9`N|Pk) zKaBVMAr+HFlEGcChx;x1!_4=xJD6%LV2$~sK;7UYD=U?P*oot*OVba^*5M+cXw zV@@zA_zv$u9E5o>;gHzD({toUgHwMF#qqx@dSHUk%m6r?-0k>_7 znb@{IPA%d(%UX4xN0VW+ZgehdcqUJgPZTKNjs%_gCu9~>6sac1f*z>+WBPJ)DgNg> z_AP7?ooXl66=Fpqbt_m`i4uk0QDU!s^O>iyHj{gFhcB_e$M-F)=R|6zm*;-UgS!Jt z&^>7gdfsv69_Ee3_DDms0by=>-#ozC&Kib$_UXZXVV3iraJfP%aSrSYUc|oj9Oa*# zKEe(; z+`57>*tvc`Z*wXal>QmAze}dTh`C|R7-zuCtO_>PT@KXdRCT4h`%y> zGHF$DEW1>dTE1qp!HVHjyRwSi-}sYN-TT4%e+u1&i{CPJDG_?CXUg;pkFpT6a z%b>M>Jf=M8xLVk@Lc`p$Mz{31r%ltC(zqe|zc<>tE>Y&BSyS_7v=6vQcVLpxO7(+Wf57D(}%cxo50{tBwLhJ0# zQ)&5n`jL5tUVReIM){}7-%pFOi?gWi zyL+pl)97Fb{(p`T6)?lf8Jpft!0Uy}(RZ{y#y_5mhksAT7JU)aZ+Z!bJWD}CGR~|= zL>CIZQ<&eL<9t=SK3NakVj>RVWE?k^mTkX4N7+;gy!n7M_v%w*`6CJ)rAjV08c1=; z1gaIgP9iVH&>e;I6h%K+>;2Yp{&QWkY?)NX1(utvVHWHHEy^-+uujBfZWR@m|M8} zbFNc{t|JVYUP+tJRKO#ZlQemSBwD@LPZ6)C;BFM0m%INW})W! z@n-W^%V7UQ!NHVQ4wvSofX8=DNGLlFkH!1BEgJ5yK*kjMR+)20bgbd#(3iZpmn?|B zC}N?GYNnC%HR#1^VeS+1Muzt)D%@@g{X6G|fjyk2`|?}C^X?f6?A{8YEqOH7Gy-mK zOdqW)vM}J8}l0%gTYNEzN}1$h-Vj6AP|#`W*Hl_!wLE<2JKe`kIyg zlp#*|zxW+)OUo8dr>6m7w6uK|)np%|QXOTg8g-OZ?&&gnjT6*odIZ{Lw;yCV`&vy;dWh5YT{W!Ieh7UMwo!>CF#jP|Tk7iQ8piYuK> zn3qX2pL$ZF{c)OgG?2n|573MuiFD|q4M_}7r>p6rbfo4G88@C}%ae|fe72uiW${7s zQxf3cqD|yzse&&)deX-Yi;;Zi(&u-3P~nz2z4;f7Zh=}f_+LB@`5{f;BLmQY-C+BF z2>GEIxvX)R9(*-D%dWo|#?rP{v7{^aS+P|woBB?h@>Pe?tV=FbK2(Bg;&u^Nu0`LQ zqshf^8P%7^(4V?Rbhg}y0;T8E&_i!ni>N1McDb>&<5rT$+!{_%)_@Xk+=AwxV=45l z6Z#JsLZX(5SXh?CvK21jr>rPe<64P2c^>RFT}H8=qgY;U0S@gx&MS^j$Gxs&n40ot zyj&H=3?8+?@S%Ck^QRAY`hyd@{3V-JO0H$I<{MB(Y9Wg}yPhbZiN$*+ki)t@7BcfV zRi=wjQBW4iw+^RP%Z=onHj;v(Rq2a@2JH=VVLscY(LZemIQ`Lfc^S8LMzOdT*Rkc)W_D#sH74g+u!3i2P|VMqJ=h)7yvY;Hqm*Qp@GBSWR2#sNNy$ zSCpu+G#ypTgzw$iTx{CCmx=Zy3jF~y**JwgxW?cZJM~*|kqR^UGH)qV8h(`N-H-%v ze^Zus?iA}B{LLr!PohNzGnx3LFk$By$!z*glc@0$Htk&%Rj-a_NzZDiwd)GIB65j3 zQIVd6CexH(^C>yVm0nc%)0UvWEPKA-6O@0)-;LHMW0x#gvPF*8ebB;zz2$7#zqz<_ z+*0;^`!?*VG-oZQ$v8(woNeF^VAbh|{G5&zXfX3RKc`9?j|^GBKZ`AfIz25jGZ+dY zX;sGhR8;OYXFlJsx0czoz2Vd6Posxy605lBM?ohhvmx(7XmGbSYg@UITomu|lA%kf zbxtu~SD{7e@saHJ$m7g*tWepr#Em<*xZ3Cj>v_8c zy~UO=Z@Cy;S@VV8{vrWW&q}e)DWSOC-jcO?S>lWs9d=;$Fw}kdm*0DS3nbR&@h3Xe znCyNBp5&64)DU|Xy!kB?-?@(sovK6b){-nKz*g`}58+lXH6;^yMc(@OaFT0KV`XMB z%p;|jzo{k$4*R4a=tnUO{Td3&f0qkvmlz@fFGF^G7&V43YH$XKu%t$x))W&eJx z+HnG;mqp-`rVB725`z1)oFi__T=?@M;RlF$|U8@3?u2L-b zy9R9EbCgX~OW^!}zhc&zGNyaajU~Bv#r%u8!fdd-ke_|Eh26LP!UvijVh*o4CVlg7 zMdSMxKIAQN#{J5mc1a$T$J__srb8gH`V0K0dkY?p8j4G8`$6@zHL&-lRiv*3=&VZK%ODwwiz zKD%%RZcy67e;eF~Xd-kbNN%B`olS-vok_MWjG7pup zLX(h6G9}!zk1~{0nut_VNdrZZN}8YF^TNjqZ*YJ2p0n3p>$}!lLBd%jb}MfK3pQFv zCM}wRg~6_n&^8n+>#l%=jR9V1)uE+vsn}C6o011vShB%~zET*6U(^rLo5zsF6vj}) zneh-t5 z*5zL_8;IoS5xm@R1`JrK$K797fr5uH&j{YQ`6+{Wn$d20=gt!}9~2>=_##jg;ZHl{ zw9)pUkd+w`P5N6+sr3#q?3*~48fpo9tHxV(|Hlqhl6!>8d<`)F=6xC=ID zPv=v{sM2LsUR+4n(8Z=p_}(l2^wwN!KInEBb$&OPSGvbhe)boZdB#zd+9urLcz~)O zHAB-xZ<;$|EKFSCLEp|Qfj`^yXx)e};ClNqh@Z&ON7?Vlr9y$n*F05Vs|}=jyH8=; zQ4&KczZ77KV>o;r*MKMPD$}%8 zHTXVv3q4R@hY3QTz#LwLrRCXFtwIOyKhCG+&kV`%1*Np&iaqF+S5lU^7=HB>(u%6Z zaBE5wrBfF{dbbnBo%`VTj6t-|Edl)IdH{_VeEZ#V*n)WupdAql0@pOtyNM-WvZ|0qu6_(7jvk;JcRhmDtL?W?+ zY{++6i}8qiDZbcy9?joxV)ggJa83R=STj13g*x_uL-9u2sF4%tRT&W9J+hk4CWF9J zFNE%rE&@ZnXxbvMcFZuCe!r9gH&2Gp%ZjVPPJbsoZ|4D3dneO|Q#x?-v@+GZcSvN? z_DRSD>=n3YMQ}@C(n$Tg2#e(ha#E58`C?hV@^=QoOYs8h zyRa@wjBay(f%O+I_A*zZs%{HG{+S|Op??V+U&_+D5FvXWDM?$ln^NPpZ;+&GOlwzv zggLo7^w-EH7`9EC_V3Ps(m}ltZlDRZ*7u+{(F`K&cfoOX2>RX~6rXIXfppDmOb(N# z0adSXYw-k{d{>gYzgj}ohrPl38`jd0@45I)$bbp#A2e{-M0XAKL!U7lX!r?=uP@J| zO(&bg63$cT#od`OKuO>c3Vz11n?HlZm$CH9+p}>%D97SE>3c4O_GW9-czU9Q)pR{G`p3jRX=7Lm+P;Ex_C zL6wk+8Mh`1)Q0Tj-Au^Jf1b>@WOYJ(q9zxQA4)T|8u9L|UO4ySHS_ChhN5l<=$4VB zgZoc|Ny=+DKkzo7ek4S{98AB4$-%V;!v!DvI`A@3rr+bvL)iRZ(5z7cV-0RVR`(h3 zPD_NzJMzIlRRR9w~*Yc0BSp6|OYp+D>+Lg%1R3kbqZxdV)>(R%* z+94OE=u!Pav_9}I{E_$!6NbgWmdqN^l34(e!*juGt2cO?rh$QBEXkar4(SQ^ZJmFc z3H#O|%g8d&Hphw;1eK*76DG=EVZ_${6S z{x+o$u=Nr&p3j2zyd21Lt0SIXF%T_u@<~Xnhbvd&vB_x!%%3IA^)^l;+EL?pXnGsd zxM{?#obyq)PLZGaFqn^8_7qhlM0PT+B69UiT@5&yR6@XaHlNQ0nnoyT}cEtTU= zeI<|=nT!2r%fNk>2!nq7fX=)~rXnXWk6&&k=}~WB*$X9zkt>6w(nZjn5Cdzx_JW(l zU$R~$0`!)S#WewuF#o^}{Ju&R9NtR_+@#{t)LuP6OU}`xVbjT8jVXx1yKqT+zD$r*LZ7 zNYH7$&fJd@P>!udOL^RAH6FUzpZm<6z#}3K zaifO|_`}Bu{JOw)pH6&u-{x(6W8!3iSpwYDU6nU)@4?58<=E>Rg3Z4vN-&FJT{}rg zeY91`#=e6jpF1#JUx)r3_y`P6j-vm>w*?(~w7{Nf0G)0<+Wh@G?5dTdnLz_!=3Ftf z4^YC6fFq&`T872BpQ ze@%F-WeAUbG=|sr&J%Q`K|D16ALgBk!Loa^af|#@vG(%?K+66dP2zJeRrn6ywmA zX!iZO43`o(iLAz*?+Q}qx7`o$YSZa_-v@z(wsJD3=VJNk!ZCdP$=!T++F;(X%9~G6 zeu*W0gzNTpqqS5g^2on9wb}-Q9t(^a)=YMdGDNkGNT{?wEOJsh1U({4_!*TAp6eEY zxfH^a@W*zC2W)ZxVReC}c|#lrwl>kOY_dBy>USt;enV zt$1{AI+iXxgFQa3DAA#AE43zF9AG&FY$r-Xu#%aubDIyxuWCV`(@}^$G6t5UB!cIY zwZvIA2*{oWW~=W3^DbuKDF>lLt6raPZ5{{)i3|DP#VsOl`K^4zzGZCT;utRd>ok+- zkLO3fdE&o$vAq7oJlw@1gpS}Cb}}iLCx2>WZk>C$DY)Xe1xvW{Ga0lvH;&7GX%O$q z(&SH0o)VWg|3K5#+T_}bMBFj=6-j!khvtt5!@6_BuqkN|+3nPf5ZzVK4PW&4BNG-8eAuFJZ#@Mo`)LkhwC5pd1$~v zn0;K6Cm%|KRsK5M_i8iDay8;h4=B?)@_+CHQ=skVIx$YjHw0w;!`?qZ;IXt1ziYU| z!(q3v%jhd%LjJEKE?yM5rW~7d0$ID$BivY^fWOT?;p^bZnE&%Wj(@QigPM+F-PkOQ zP1}ZNm%YKXsSGdp7vmeH*ElrkJchjagU$0wuu)H%?>bh5Dq2s`PiHrJjej6;80E37 zQGy4U-w>TP7{DKTECT(HgL&zew~)Nni2L;$P#rtMdFEK*4(`B{?`Tr5gDzYz{xKLY zoy4n!%*^q<hjb+;}L8LM*xrrYIWFrGDLQo1 zg!A`m@YjWMnYA)tu-T5^G_ZjU|E&1u$H8FKX~B=~yA7Sc#`96;w?;%p~^PVSea~?r%EHK2>0o|-JaChmohM%mb z$O0USR53Nw1LP}m*{!}skY7;FMj9u;bq^=pIwl{|gM|Zm(-}CTufjbG%Rskk1pk+p z2Ck7xJWS6VRCh^oV*88)9M~_fucRPrt`4bl_E94x0o6El^mHS%eM~*fLnP(cwlG?c*?4BJH^2?T&5eV z*9@Z4cPfS6fNzjLFc|-?ZUTm>?1tY3NC+pTfBeQ^9-t4gwcRbETRO z(ELD(hcTh^)ciU2_x^=$Z5#Y+`VKT!*)Z9ShrrA~k!&0OoAib)hMLFOK6R>+E5&DpnV~m;YsVyf(w`wPHLo`~W-^CQT=!AlO|xhF4zM072@LxUzLP zJls5oGv`X^KQfW4YIng0iz!@6`aK*U;LiUpcnBpUthn>ZCos6G9izUVgg$Ry9Mj%H zo=TRmZWR@9l$*$M^zEUo!H-pXj)HxbQ7pWtmLwQ@iQP(-$RUR_B=|&-*zNmnBGIiV zjvg4!+}3Fmt86FSm|z0x56m&sZZ}LS`NSNLKI~Zpj^M3RIpZniv^`DALLh!KoZ6gvD!X>UD7Mr+h`xqUs1uz>rFt>{2!AX zqz3!lM&j*R17Kmi0`_mp5E-7o$RuWLWj*x+L>5_(n8l|O+lZ|SXxKWHy?G(R>Rlt4 z@y)%Mx;Bh>9ZW>M@e4%$x5uFAL%>qZ6FU~I#DUYEij1R$dG=GMIK!o#1y6fvtE`$P zcDp=PB=xOOR3RD-+ZT;vgWYbzE2(UDK&cnB^n+LsyAB!!uS7l4XF*S{v~-90U5K{P zVUcfgz;AC1@m?7OTSNy)v-Nh6vXEo`TJhlW_zRmb;0Rpy&t$vWgWz4@F($QQ7ig?+ z5kC;LBFA&9Slphw;Gwsj>6Tpu}5{Lwct9Yj2W6I!`J0m zqJoAAV6pCU>Awau*!H2B6~{$DbhZh8HI0H7GiC5lp`fYyRkHbe>WRd-DdM2C5U4F1 zN?yb^fXc69WYYSd@Vnv-*)!oMWHl?0vP5ON#{D5nooY=`cdyABIfW4L4;M zgY(VJ;B&|a2JSiphNXgz5f=>3UBlt@F&A)L)IidT*TcHRiDdsGAE?vou$BHi1;h>g z;@e90$M#H3fQiTNqhvdJiPzB}&fhIt^YE zrm&RFM+N^z1elpntQj^IkEf09 zg0A{#G~FWbo3#`)sKWVc;t2JxVDSi;#@cc)DIbXXVuVVCiP&9sOUR7x!Y8TG@O$u1 z^s0D8et!za!Urcv(@TnXBYeU6z70AEY@ci^dvq974X$bP@bsoZ)LFqF9mDjgl->q( zm@tKU4IYNpvjo19yEb`bvxw?(EjUsq^iw`|g-y5YsN#WH@OH#B+A`e-e(y1*s!dVw zow#rvRez<0QGbu4UbFg!85m#w7gE&_f6Q|sRix`bo zL+ikJXgYp8^bCfn*y>TV=tT}Y zHPo8A)gNW=>z7jOG-E+_AyiuB8##9{l)eZ{1sQ?M_e%LT=$sx$6)R6c$v#!;Jxv>~ z|MvhE84ZN(T1z4QlOr^?{wC3J!u>cuoXidCVtT}s1dW}G4*R!@R!tE&8nZr%GTgso zwqYwd_+Fc@pWp;b_G$4S1E;_eCpms2cqioe4&$CuH(_kK&^K~tF!j0Kf>-pkX+M?2 z9r5~<`hFx21IJKfs}m5YN~x}AGu#WYqd!02gNWm!>EE(9Fnzf;J@5Pu^sEf%_4myn z)AkYu4XuD6l!d`o$>127LW;LPAr97$$?v9qru<<5I7pnvzlW4zyLmZ&tqTC#JD<@u zumo0}9K=s)33{x#a7QnkO1rmR$4QqL2wBqKY;WmunlNpZNYQR9-QxO;dBKjJM&Ln{FKE$&vD4|1(vehC#hS_q|2w}A1_G;gIK6%C2`pEUr7mV$q0g}j z27R@G&o~2|XO|Pt(G4uPMqTtxV4CjwF@mYaYw+~nNn*!AdVErU4l${te5z|86xOfg zM=Bn{Il*(kX6bNxb-OtiEgeszjtjcc+!@q%&@lWve>L^&oCIz~+v$PWFQ9X03$49v zORs9Jr1Cx+Xy!gIYBD{NK5t$~r>pOzXWi^*bLe{7qbp5ghRvjrj-}w8IF=fZo(WC` zZ@|lSE>TI70@Y|+;!?F1^WE1FquRgdOr^*oYa?#Bc{~vdyItWCCCe=K@SLMPWXG9k z{?%+D^u71vZ~EiGS!W8Djj4nL>4Ch%SCUpGE=2x(6dnI@CM=&X^gr8-r(;T8Y1FVt z>K|lDXNyl#cL#mCBqEtc3wO7LEeC1y=?;jr3!`TH%E2Pvh3<;A2jf&Z+7tR&^gH4l zocVKr6}vAWlNzR@)}L%lSB=DdOQ&$t9geuOZokkGR>c&I%Pd<-9wLY+U(NFO^|GNCv2<&LA(b!O zNx@Npj&;wV&qwxwb8#`fp*xKBh%eCN*M`tqiDPtCh|qng5vq>yk`E$(dVz%3=GCZRFl3<5`B#XE@s}lkGnj$+Z?|vn|iJ z@#NZcHZ8=S54)&Bq+UsLd6Ts;pj?bReFBAP<+dr4!$HAhFb0l!NCKlw(D&a3 zQM6x> zcOoRmM?lpEAm4}PL8E>GOKd8GmcVUTTX_^J=YB_p0BZof@!afCnOJ@3LS8X;Io6Eb z$m>nZ&{1YPZ*Q-|ck1hTR_6yyJSg0|+alqE7Tl_>f)%w*<#}IX z$?MvYyi{`~tm>8Ew|Z(J{ro3P7}5{-LhA&by$fW%Y{f|dzhHiL0t>kI29E4kA$c$`TO4x@@UOtvTL&>cC9^0PUf7zfDn1I@7yQMJuAZoNeUWwZYi_*?#i2ba@dpb z#aw028+Pm8H14hBhwJYea+L#j(eOq$dd&Qe4xQl`82<-TJ&T$DZcVPFdXWtJZpHuk zWdJpu%1=I&qoFMp+**#%if5W!I?R?XbNz{9e-fI_p5iQ_XWRDsDZyJHPj}V-W}469 zA@1WZu|p&kv*;r6iDBb#SXQ<;(I5}67gvaP99H8sWy47H9KkEU`~{I+A>w+9Cg;tiI7KeUk?23O~bVha$$DWZ|rbQfXNe#x&03fsOg!)SKTvZ3xxc0 zgcQL^KPb1>U4?g7P2dT?(@@W76es8F@%YPTOxW9wH!eHjtTX-S>7Bw%9>2jiioT@r z+eLJ6yGGWUhoI2@Mw*_DN3&s(WaGbqSZS6eE=sN-6(;KF)_5HD8P3NgO!u4e%YoxBWg0lO4zLjx>FcE^_4(>Vw3oYZmfNOcU>z&E}2n zy?A5jME*(9mbVI=>Tw$;@xj(Zd9I8qcXXBGv2uU$p>8F9o8F9BijnA99f7I&o3MQi zvN1=r&^lEg>ZV^~tJ_LoLF)wkBk+F|8jqt=gcZGPm5(&cg?jAE6|`k{T2xnrSF|nZ z3%M&8@?4fK_d<;SbPp6$PGIfIA&{Gtfc7!+IQx4#I+HdW_aGWAK8g4#(K7T%TFRTw zcw)Y-JJ*Q2jIWFsHCOyQZp9F7UWFCGDk*C&+1998ACMcdT z2j|{72DgTKVbfF<=x`o~63dpb?4E7x!^}~5GRu|RdbSZA{X)sAxfd~E-UilWBF3b2 zb&T!F#dn&E&_-(^`mDW-9_r(mvDpWFmy<=dJe1?+i(TQvG)ca=It_k|{(v{1eu9i9 zd0xF=k~aM`;c-*$f>5)>ce$lOZrw!Q=o1IckA$4&r+qNs(@<_aZ5cGQeMQ|{V_=qZ zH698$M{I3Qpu`Lfv7C>Cz~s@viE|8bQN}_n3cAh`r+cG=zPs4_w$#&7lKN}Z7g@KTnktl+I^?f*JkraI`HHIH{97bzy zh`7Ci3N22tX(zV|D3qtP<2*z z+Dhn{R7JZOSzbhY*&2&{v_N;3mE(-$$aCf%0CCiwo4oFX$H`lS z4p@QrR1(Ltz7)Z^i>JAMN<8=!p5t33mV$X`3SY8c5)KJJ4~obZy^##%J)7!EjrT9- zJvuWO>T7fB`VMxstp`;%tKn0@fK=Q>n5*ak~xT)>g;s&xL7C&F_zhE~Uq;&x%W^mXlj{M->4dI;9@ zjvpW4^{nlD`SXkLVV^e-mR$>3L^JhHwSRb@;l5a<}j8Gdc|%Ik;6mnADOiCIo7Fkku^qMW5zo2M19s%CcAb5#FqOq z)5oXb>X$CoIim{(JUxSD`*mp2sL$B$I-ZUWk>nbhX4Jg>Et)$T(x@+k_#FX&_pm~r z?^yc_9+*&058Z^NrjvNvu)Q#;-j1u?&mnf@mRxyO1shnZ!*A#x#LnI!Jn8gVM4fsZ z^|}n-Ne81uW(oSAxX(gn&O*~M>sVp^Kq9ogiS1s^09(6o@zM{Ou*FGRoO0LRLOqkK>-{IP{nTAEh3Sx6&TspX7ARD{#U# zaT%TzdP@BLE3v*fg@n47;V#X7vg}_dzUh5Owj}GK^%xb%N|-KAE9GRP<6E*T>9aVe zMibJ6nKXIpUWoJR$HAf3z`$3FZ;?v_(-9_I^Wi!WFL2;VrQJlkdLCaMFqQm$j4VV`d3RUkP3p2=k$T4rixLflCtw5P)xyHeP$M$@K`)lZbn!Dui~|5N|zo(f*tQ z;?rb>hU#(<@wxyX>aBp*&7W}Om?N;yXE5JqDfEaRlHw*hry(eD0B_Sc1qI#h_=QEo z?mrh%qIr?PnI4D7*D674_g;2u-6`Vya0Qug;sCk7bQCOJ{Xo>ZCl1E#(qQ`rSHN_& zRm}987-S_i#YR=JAhkJP^rd4fT>4f(>?Gzxx%fWOQ_mE+y&FTy_HIGhTU7LO;~jLo zlTT)csB#ONFXUH-2EV(anHVVdVB5hrWT#Ux7Qa`7;J@qfmf#1l_;Xp@^?55CDOd;l z=7vGt@=7>#A{8_e9)t6@Y~b>}P}LO(Ut1*UwYu*_Tk{$Cd(;w(EBB#tOBMNOQVGR} zvdPZ)!?4YKC#j71PMEz8xsW}Tb;M61v0ukyldC@&Y?^@yoA!%#dDUa^7d^%wea2_6 z&apkCJMeLGCR1#^h@`QReX=#e`|Enys+avDV~5M^_+SIjOCH7ih0Yxp$8^#*y94re zy2C~D5!6yP8U`y_(lq~_FznnY8r3-!?vGZXvyJA!!s#;9CBzX{jD8QDho%Azxdf{Z zj)1^Z>*3SGGekmC5lmA1L_4PKBoYZ|yRdi%bG~5Ax(#gc{NIj&6S3||nW(;MA0~|v_6Hhc@Zm3Q2%2(*xr(=euOw%;v-070;tr;Dt^(3M z$CHbvA3@LWv2gE+6rJQ42WwVq(T;OvFmr)6^%OkynRAWleWO9twnUd+`}7mES`_H@ zl|p~klwKI=z5zySXTSovrzCBgF&r=-Lgs5|5N)g9tp0To@mcSTt7pC;|3>V>JjD)j zC+8?ej~oNnHlM}n2uB#%mWE0h6dqchLDx$=z|(&bu9{H};a-zixcN|;d*iF9L(iJ_ zn9737iD?4oCAzF%h3G6bh>7; zJNt8D0S!NsMZ2a@X1PNSX@S-Zh41 z&#q;UMs-5TXiI#J=b`-7Zmd3a5UQ6Pz@@o9U|k!F_R9#Y+?b1swqt-yJBw|G|ADkZ z8eVig2m$)}SXv@vS~HH|vY%3PdG;!_A26DlH7MaIYENso2Z`tU|3^WxRz$Z6T{PvV zi070!blb&bGW5?9>f$qp@b5F}&Xhw$vC^Ja@(SA{?~Uowm0?U_(;wJ#^EUIoQV-{t z6prZ1fq-s;+#wadc237&M-R}|ScM%yQqa14Bi8J`MCSerL0hfSF!PW#f-OsBdvu)kM_&|8b;u`lyAm?S5n z_S;Kv#^oBi8Xtw@PNy)VU^!&YT94)hF7V>0&?_%L2V`!fyKl= zGiw?(C>L#o=c)Q?1m5_#oo3vah|l}{Y3rye7C&}A%^AOibxoW_cT2{J=af&O65gkZ zcGj!YHm^5q<*M5t{lWnYo<+m;8_{^kLJf}OBT6j%E?(UH0(af}#SAAuK||FxCVjU9 z&sKCYpZ7z!AKqoT$3}1o^PQsXI29qUYD%UOMIjqw3TtSxd5OUG2&SXQ4@U(Rfhlo4R(vdJ4qXznPNepJBJKYbFRD=$y!e;H ziSxSGaARdF={o(0OO{dMYFI6 z?7l?`)?76}jcGDC@Ad(7aJ)i_zMaRl-B~ckm*Hf&e)xH<9A8$N(bR>txOK}Mny}|C z+MioTm-`9qk%gOtJf|cswp~vzFFL`h&U(@}^~&t0kv$#Cj}yheay09P3#h!j2%Qr{ z;M=&fM9st%BG*Zwt4}x>yRF0#snt+5I2X$%--EuXA92@X!E>n4gHn+JFi7VEhW;>z zpKEWU!NNI2XW$VO*CaCsr2RkuC@EnD ziYo`=x+#~4bFPZWLUdldCTBAEYQ?hV_F^!<-pdkn{=m=!Ho{PDFTz zY?j49dViA|n;&r-ZjC=7p6|2??ArQBYVs6f<-ZS(HH~HFh60ld$FkLD7C_yN^=$oz zjbJeB16%#&B)m923tLVdhTC@~@aWql(46v&&6}16K|=)p{Lxr&iIzscLu*0w`-fOH zdoE0nnMSmLFS+l~&dzE0hgUV@tRA>}fTOE{JDZXPz;|U<(X3OtLZU3Br4qTZr}E zX&Bn^AJjb4z;l6N5FKB^9-Dg56oecGbTfnaKGtY+Dqz7ogvfkI8pd+ z0}?ltY@gg825&cCXJ0QklJp&;F(Ip36xX~3O&TRYza$Ks&ToV}&7r7ou?UXn3I3pZ zKWHDCfZ~C3pnSO}R_nHtMQ*03oGv38@}rSSoSIQ8fA2AqI1*i2eZG!K5W5mV0%Py8 zBU!Ot6$=TF#8aEgnZ%(F?1|qK@hi2_?2}?R3x8HEy3i+&g(jZjPjnGZI+88kGVd^+ zbF?9wdn$0hq8C|xq7qyFOd)H|rsK8;7fJ3tFLVl(C&zL;kPY7RjuDkR-MheXcdL^@SMH0-jZ&~tpSml*^C9g~Ue zd^Z@{cv2MdSOY`_DQw;OWlYE#ze-VE8u@&77%9+t9HS|2# zCl1Q&WBqvBHf_{1X4hOu2Bx;LA|a>IHYSrTlhuLToR!R^v4L1Lgs?wpk;LaqKdb&Z ziR>Kchgaeh$jG)VG_^iJt_(YY7V!_sfXB(0^-x5X%ojSa9&RA}y{oYNV~TA-$9W8s zE*1Y7pCrtZMYfee;pkvrW!szPhI&8xMF;0j!Az&^^d_Rcf|~a44bb^ z+E@>!T&Q5l3d3M{$^_Q6LJw*`)rlPpj6kpZJ(JL?A|6%7*yL>@j;uGrj1!Jbcd`n` zG~2P9Fl(H3C!9r{KZq%XvPfT_LX`(gQFHMLG)xS_JF0P5yI?O$e)hr+nTcp}kfQZQ zODwjNMG4`{HSh^b7x#;!tyg27X*zi_t^~bWtzl?cEuKE(3GYhppzripuzERwhvo*t z=BIi*O@EcZXc@~-K3@#?sU<%%NDF&zA#u)`O;tU0HaqUqifI5Q&&uM0Z?FIt1)o4>GpUpans?LW3| zjvjyUcpp<{W4Z1oa+BF&c9}nm2bO%B2 zL{0uPG=O~clI5k(&6q`gId+Bhv9#{3Xb_}@SI)Gu!j4zWB>tG#@AM+JSk(|b!bY%h zJRX$K1~H{m@t|uM!fuMDL&D}%_BG}USrcu=e6E%dw*jk(*TD0(neLHfRW(7cFY824 zX5`^~VGi}l=tqTlokZic6*mt(AnaKu@YFTOp?3t~X+Dwg!Eq^nacVy7(D36L&IF#| zTE19g1UQ7cay7Y^gikQwJzKMg)S@RiA!$AtUosglH`tLRn=BIKYDwy>4ncOoR*}i9 zJTShR!(=Rrp`^hAL*ol!y`X39JM1U0{IXf0%Tp4(W`I~?*?XJT7cI7in+OJ5blbkK zXhl|^Cz9A}z)cb}i9xzOH>(^7j(b<|uR8{Sy=^eRvvo3@P7CLmdV`@=W3Q04tRl50 z8@RUhYm%|hiC_4eOmarsaE+fTO#Ztn*PCmJ3PURKPgMxY$f)9r;2Ly*1o4iXJHlS( zE$KA8ic4m0109EpC|hp|zdO>3bZ8 zzif2ilz9%;O&Bpo`HV3sn zgp$*b{V=^{wx~2+cptl2TQ9nNo^&{MiEg@VgE{wikt-hY(CU7X{F)dDc?s9a#)qj; z=vYqi9TX%5W~F3?gYiAwan{534B?d#wyJH!WnuQL5kfAkh5Q^Ij^W30MC#9rQ0c`fX6N)2 z^K_Hh0N)Ro79Gk~g$fMP13LJ1fD*svw;t_Jbfcaq440p{gmoK^W88ySyc=17zORI{ zYjqYbtDS_GB@=MXupH*Hcsi zZ8x#4o&b(kafFJJNW(P~=n5FbMAO3|YiN#GY!eG6O@l<9MJ^CCb+~XI%E7klM@0MV zw~`K#rD#hQV}%))*>;cZnDod4J$&HFc(tp8*Cl5=2QF)l}R2U}zd#l@l1Abdvwt9v{ZVs0ql^0gHtft+Nk{!9=D z90*``&JN79`3C!~q05vdg2Zp?Ua~8B_sH$FQ!y^Y47~0nVECp!QhhTD3x}G4dW;cf z?OzPZxtXkUUKBXRe-(FZ4};Q%4I;yD`(WE>OCq~)DWoZxLSxc!C=vWkg>o%K!s`g= z9=kxUY|4UKWpmrs$|N|@{)&CW5HK>`j8Cqoz}nnP7+jhSU7re2_EXIVqx!lo{WQ1jGXtHxSXDgUNZ8~I`og&@8=K_to~HA@pC$Ju@qkCh@oix zaXD8GEL6mfn{dj4PT1AKL4);(Fup_$2HJnH#nd7fg|YOVvBD_-_}n zSiAiJMr!~RYqmFp3kH;J4tk=bqILP))9O8slk(X1>&B| zZ%Jg?OtSZg4srWkM5dm-C^D{`PJHE_*#@_7Ev2t5SmnLjBG=uQS^o@sa@tV%TlFQ$ zi>ygF|DiK^Gx-m@wRjR~?H+;;->)PZ)*Y;}kCbM6C5a~;HWNP@G7t*SbMeQL@nAhk zkL?U1ur$)WSn@uf4Vezynf0xyX*ntagYVkmQYp@6ER zVwg#AF3V0I!&ua3apk#XrO`F>Ny2i%e)Xl2AEz0!)$AY^;}aQ4(Sr0_KT4|~dO^p{ zDJ0c506JV7$cd$)u>YPicdBkCDD0A9tOBFB2PVb5I!m}4^r9*1p# zBbArP6B-64->0&TD~`ZQ@`wG+jfSMF<1sbW5O#g_!7A+nlH z-}yx2X$aH16hr1I2D4fjVeYx+DsrA|4i@G@0A=$8Shr*;JUG)r3P&9kwAnkQ9p33s zry+1!FW!KKxfSe9U?a>KG7H};wE%r01dbm*6ST<+G$=X_-5(!d$^9+RI-?%Hf0zWa za>AK<`#Z6pzXo+3;)(IAIjpe7$~LxJfhCl!V`TAEvL?BaNe!6_u4}58URM}M_+2lx zNZ$wjeg-V1YzDY#8nazn!l5HNo_uOs29kpvAt`+**l)^&;@L5zIG_r==~i)9`FVJ* zE{_NPWb!WOiNHiKKWia2G?MPl=F z8FQKQRCHI#RIKNgFE;bZ5XnAEwmoV3oa8PH6E%hk_p1GmMD}~l;ntl9QO~~RQ2b;L zDF_jKU#{24w5xUG-MALw&{-gwr(^(9NfJcMU^O^AP-Zg(Zu!#>su*Q%407Y6F!zHk zxEW=m+ptiuC@aP;HG%b-P>R=+4M9TiCtQE{hxF&)#$N3a@LO~i9hW=8tv3lMF?c-0 zACtrEi}vvN+8A~}&Mo;0^bDF1aE(GV5=RP1X$0o>jG69sgQ0g3QyB8>(E&{nMy$sEvw z*|E7It>ZD#OdoD2qr90sky5;$#O0eqWuiK$!0 zL)Wo$?Bv3u@NKFylhV2jV;}5daud%%xuQJ_JCzQHR6;~*ryHRlt(vS5ID^#>%89|q zIykd2mQ0|H-a%VGpdeRq4`j4|6`MDr($yoaE7hv_hgPCl* z3rSu_*p@9386z#CtMx%meUTr4J2T z7#w%LN!*`j!oGm(qQ#qiA+T(Tc)8qAkZ3ow=}Wmo8p_>>Lf}8roGeGQ{%S$3* zC4HE`XQ|j=N4Hr)8VYAd$U{}pB>#LB*T|EHb z=n0*Ldjy@n{Skb7X@MgeKY;X?@#t{&IZPWd2DP?7hkZi!=0b(gjbU*JKl%Iy&G8xN z{Id-rLNYO>=`BRcWnk{2&k*)L9OwGIgap z3WXDoHOU9Hbug_UgWS@a2`<9jYgzn6*kTkxtku4gwOVJ%F0WeRa3`Jko9lsNkP3;h z4FrpMpKVL;GjO(9!WPzbfwz@9s%Cryr*|Hxp)F)g_AW*3X>D-*b`&bE>;nsNG){b= zK~s;#;;c?X>YNvhD@SPkkD@bitLg2+a8gMsm1apLDJp5&Yn=v3QX!cmL#8D03n@d= ztXT+2Qb{FA1MPPmQ<)+mAt6bTkR&tV+uwiCb*}2XYpv(LA5r~CPdawL2Y%BciNY&a>@V+o!ww9dzD+BItFF0>GShuJ7bN<3ofVwmv_(3+SJ!;K*Lm0DKGM?4RXS3a*9DAWz#{MeZU<)VS zW1h=HSf8{ZbGc&6ngXuy*IwLb=RXZ%{X74oycV916C5%wD#?7qiZqhFu^U$E9;VdV zc3A5fP3~s%@Ze)_>iwC7ePRDt&ICW)aPcX-7P0`>kO7%DtivgF9HnnNjBb-Yv6Aiz zVK;k<#SK4)w=;gTMMDeleZd6UyX*-1KHfxYrPHwP+ivom6M^Hd@26i!)}oYj0$q7v zjcd=E8)7#H2qSWYsmlt9BWTBb&={P&RxLHBK|b{s<&C%pX-M zXOmISCbaMIr@;&6V@sW)A#Tj|ymQ?gZaG3M_e!2?nXFQMTPCT-X{+Sz)KK zNaYw+1zg4Oxa*X9`XZhmeUDBR#o^eP*JP?5idyzBX?=(dzIgGNvJ(!$+s^YOxA;2m zIwh6eJYJQ563ro>!Z)k-RGgp#RsI^j2dy#*A7`uX#mmU!zQ~ zHq?ND%s5`JPKCex=r9DOcChpE-2mESsrABmR4MYMh5$=^cK94sWhi5iK_A_e)7e`+;KCkWN}}?ox3=3MI@xO%)$hs75P; z+O#FXRC+44SL{MXgH7!I{TBSauK)_16-6sfsH4SPL(yJqN8BOY_&c*hg*&o_$Y#z` zblx^t^xZ)UORPH4_>Vg9k_Rz!O^+VG~11>fIdiH=iYRqkN%whlDa+==Kqpy_vwChWm+SCZ2_w9ZSWr_vhiyzq7@Q zLXTm~rDRdijLbUW3KLfQcXe4ixW`ZbP}P0+Vp94DZ_2)930#C|RFN z8`le+UBdp(a{O+*c{h(%NLpfZ?r}0qzRtaQRYJk{ocWOU60#UtR;B*t2Kmm5vh9Vh zw6)xUnafLyoh~F)8L6v^17lx<_iJPE;)Dr!+jNrnjJS=S%)?5%Hk&HSS+Yi5X-g2Ab(j({5xkc zwg@>XjS)-n=om@y8|75&K0Q!8;7SGtYYY_sO5BHK*9VC8#vVht;XQQdzXH_fI>}gr z$J)gm)cU&tvz4Dx^W{cNjk!rTvc+h+{R$0{O~#Ogx5+u#3eT>qr3-t1z=zYdv?2O6 z7#?^}L3`$N4gX1tTR;C{Y69o&IntQk^t`2SAGJuK?-TtL?hi}*2Z`6c5ZoD+QsUWL zhLJM?U&NWbh70+Y`JxYa*r#an$m2#S~L;GhT2r8o`UhoR%D-c z6la^RCKaJae(?NB)ZklyulD?4=U613&1z$3G&(>{xHYm%Px#wft4aLn59_cvMkPng zX+~of6)$t4r^{1m+xbn@YaBrq9l7*y^kyp5O{4o!i^;=w9TnGV(Duy96f5}NGR7^T zaK|>5+^J60KWtcpthB9CLoJ_{^cqZ~61Gdhkez_P*%%VHD26+o|P|{(B&rFp$E|~-#gfQ)0|$cYQXT( zL+J0_TiBP`z$}bw@Y05>?D$pT4L-7i9~GL6cOt9+?u|s{J5A6(Ya&#;{)F@%OLjV3 z6;*79(Y^(f@b8#N%G|UHO{eA2-B1nucI^m>%k)vBBc2jJ|Adrx8)^HveQz2 z!8e5T^N!V^cCy+c+9@&QpIO$S6#@Gem zqT`S8q|6MQCGbt^%9GLMsD>!*n-1P!CZfPA$>4f$gy@@KDp@vTh^RPwB)yJoL(}AV zGQE|D6Q>r?!?zRA{6`M;I_vY@H&4=m4-RyM4v_Y&ll1wv)gCKQLz@sJj zn9N1%?ragbKxdKMwH-J!bGm3hcNoVib0Q!4LwI_;is;nJ2{;vLCGlweb>$5 zeUD0D+}Iz?skGKsb$A;6S>C~lGha~5#0ga0_FHfV0Oh@_qqhg9kSO;U{rNYaMn6oZ z4~oMn@Ov}`&D_l|jnX00Gr~@Cyb%l5D@Eg|$*{?_AJv?7aOvdXqS-H&;Y5M2taeDo zGh@6&#}-B5R9PR6qEOU96dl%)8ulQgw2mlis|3;3f34{33@FAP*W zL3KBpV9()1I(ESawLA2Mto&<~sGHB!*Qtw6y*v(auMI?(7x%zRyK$msnPE6B%~Ze*&*}5%Y4aZ~){92JFQue+MhT~iyD3<3FWk-( zeB7rKA%CltSoZX3IPuk9EITb7idWc*pX|K_0nc^BF})M8>X(%GdR-z)jlM<29FHG{ zMA8(sPCOrdgtcTyizLtbLHC%8!L-0JOccYFiiCEdn8^B93tA4y8v|t{zk_!zUcnu z84lLlj2k<6JejP6uWd4sSrqc^e*;nBr#2;?(m)NfH8kx+3poGYN7Fh#LvzM$+E;lH zp2~I5+6##=%=ZfY9a#@S2}!hiu{rvRX3?&`IMgIJQdi5tWBRjcPjERN3fHB}Wf!qG z;3(7L@8H?@dEDo_&A8j55F*v?pkDSx*gfPR;^!979I+S0ucXk-PPj`H^nvYrH9R%` z5p+JO1Ecqm&}3Z)>{kj`db9@)mKZRl#v)J}Jd-`NybNQzy_s&>Xw;tgnAK05iOEkm zI&vgI$eoQL>#n0XG}D-5L?t*U`ag21yn}(V?bD6YYlQVR+yx{T!}U)fYM9^dvcF-+P&?kZsao`i6dj1am`*R8_*-w;}Ydc`Ej=-%8z^C!>a}I$5oA!rliZ%*S1XTbtwgL=$`T z-~1jHj~#-g!CP>lZ4vZI)nWf&AKp#1A7#^Pna2o4(cMQ#_Nkg8g{C}ee5NCcsJ%zN zZ3j*sI+-BJuFeBr?|&y{+3X@JDK*IK5KA zzb7r~zxR$tc-=zF69dK5Z>idx4x;?lx zd^rmrJqs1%lriR96FBUz!ocLC{Ea3l(bSLKtU}dBBp$YqOnyueT^D8>$z`0#)jpYi z#OaAXjLM^fWpbhwtFMu2*m-mm_Td4h4`J2iQaW|en6z;@ZFkJ4@*jEZi&O_`>L1|? z1m@lIyDp6Fw-+aW9fY1$=HmM6^D(kjNgSiS3Ug)OP*B5q)ZdXw`Q=f#=%Wn1^4^N! z+s?t&epB>ZdJ5HyPD0pbJ<;VON4Y5j=82wcO=cy90iqx;Es{9CQ3ONgkgnwdQGJKt zoL()=lCuR@cI5!ku!dC1SdoVNA048_6IEfNkuPb>O{awuuCjW!yOcgNnBDxXEH=)J zt?D(l5<`y|pcTf-}Q6Ez~ev^s|pzqo&%CZ}UKdgt*=c$-0};cdF9oB%gxyrPhzTFBbnNnP55F|eebszd{@ zJ+6l4jU0*(PckxD`wxCK`4Jl#4kP}!vWH$N{PuzI&_l;qz|wK}IaHDsX|KUklV;I_ zr%9MRY9G}PKY?C~dnvd-2b0VrNc&9=E~%YO;YItLg$g*uA5 zVwvMlur5zZymQJ)tgwDcIkR?R`1dN>tnG}uZ>*zlCIivqWeT%y-2^Y(24I?z17~}D z4<37)%dQ8X!yOt8tljDk=1!8OHiw6})|qE@YNgm(u$Ot9*ovNWWY-9Ueb{GiTJtB_?%37y$qI4SHq z$)qgB$;*8G@rhk&NCmy=5xi!JGBhaa^7T*K_%qH@?9RJb zR*Rvq$3~S|e|E>eX=j-0lr327?M)T7ff%ACWY!*R$2sq&QtO(dLLOG|lMCF4s&hZP ztmuc0k7ejeQaqd-_lC`V_}o@vP#!C6+rVCC?Pf(2v?;uCAlofBm~wn(RUNyvi%s9( zz$p#8Ue)s<2r`%-*MCtKm3n4DmoMN;TMg`*tBz;S+2H;u4DQXh!KMdtpfKG4CHj=D z!+vXGqunuPZ2uKD@5yKCHLVb4d6XSj`39pEcqTQ>6P%u@(cYi=yxtJOi*5Chxv!i; zR~}oEtqjs+vq-{8msyL&4k{|#%T0gvg5`XF4}*e;AN58PB|JV_$tsOPefMqfMb{kl zyeq+?${qvO%A$VvG*mHNfPrhLpym4@jCRz+&9}y5pK=Z)Ogab>XXn}Wpe%T+tz}NP z##Uu#ce5{BKl2tT>SWV-k6FDT)>JW#PDSl!dq#<<`(7nWK4nB@Zxv{mlosved)TBH z6Tx(Ho+TV;XPZVRF}Gj`CL#Hg?;h_Bovmj%7YkW*_o)H5oLN}ES_U;92z#Gm3Bik7 zif4ZP2164uJ{|oE4yH7q+xvqcnb3*yGeaOECj!bI_nu62VwzTEmWP zj2Cis34EN`A0u8w+3s1PiWgd6bA}mrpl*)fl?Y7)-vMv9O?(z;3dL*{@BYBGu}9g< zBwft>s7GwnVK1uhjN-!~W?HXNsegFW$J{1*BX=Y-Pl^=P7=E;jZn(WNSL zT=IP&b?#n>uzwDFJb4v*4RPawhEB$a3K3@>VTNAc19`9CD!3|X2}`*02fFs%W)f@U zF?q5HUH&^1%k^SNfNMZDE{s;Zaf3|TVDb*n<9pomgxOt>Pxrq{tKyTvH?oeVuojr! zQbm(T?}vEpN{Y!^4{v;`sK+V@D)S5JtXl~Sl0=pN~pAj)R`3kd-nF2G{x7xJ>;d_hnom!f(^6-K&qIg!e`6?5SW> zzgx$#2V(@6i3JNDaRR)TUSVE^&-rZw8=0QuOsdWo94TKb$?=sJ%R5y^@r_ot^7g05 zbr(WkPBGQbdI7VaF)I2!5MxFPjBMdm(0>t4+$s$ikvWYv-%@50*4eBvG=in3B|+Hw z5EhUikKRX|S>XsspUhFiDacZ+M}K8_=9zE6{Y*6zbI%as>@GWZnN9G(xq7 zzJaM#bKX5*cPA*&OzY)L@pCeL*B&BBOwN+F`2nc@_lP>{H1V!xKSe3|qnXMN(z>x5 zzdU|SEm8%T)g^cY#F^OGx0!ktC!varC;89y#K(_J>FASxP}x<@Nh>GX|9tIW`QbNux%;^`(B`;VMp-&@_STx_XgGt7G}@ES8$I5dB~1dQcB zne)!__Y#Wn+E=JryD|w&X6u2JsS*0Vdk!m_OhM!51iWQ&n~gkfit2%yv}}PIO7*!> zY``E~yE&K^6DISJhFv63t*Ei1!-m=aoHUxmKEvS?gx7Mj@2 zqNhnK@UlW3li#j~s$p0aTk{jguEpq9zrGyu6+Iof(` z96!ugfh>-D@gI~msVpIjFS695Rd-MEu3BH2|8O5xHhnJ})zQyN7aFlKRnipYJ%)|? zJdoNv^QuhEhtSO;cj%crmNwa*ff6lqs!Mtcmf^0{Hb4o#e2UF7vSVG7>up%v%tCInxabx-9)NClz8f0d`b2{>pWvM8W)lU^FadRa8<6ttm{U2TT`NC4{ zH`ARj#mso#0t&jB$;{q3(UuQJ?EDc8(%x^)%lqzPU7IYyLQ8=gez65mSRHh%JAy{v6j5c%Iqdma51S^OLC;|h5IBD?R)t=nvSpd%Jm zDWrq^@>DK;*(>mWmC82>+)45)3(iyeGjtD?XZtSS11;ZPmgo=zPJ$Ok_Q!Jgp1p}~ zN-hSYTpx<)x@r@>TKHde>lB~oZ$om)ci6rGYe`;q2YD`7LtjJBQdEx-y=uBmd9NQa zC4(E(WRc5qPTZy&d3DU(rGwPg@ysx%i85_U`H)=|l=f*?mG0L4#H zv)Bc-6%ewyoUI%30p^}eV{S&nu=naw?o~o0>}<(^pdGt-*f|?EJ{`;|&R9Z=)&lOz z!(E_~>jZ8m{&1GEwlG|>lf9hn3OQ^A1ly8<)~)NB9f~ zADm8N=`XN;+F|l`l0|=~5~>+A5~Bx|lKRj^*nM#~*@X*x#H=OMkaz&g`=-&z@f)#W zffU&dH$kRwfc>@8#b(V-EUnBE(-*B}X39eE_M|l|X6PlbpXbDWc)jLpzQ!=SXDT#7 z{yj_elclX@ngY{yift9L;D2;t*;EH}s`wPhTzZYES@3;UKR2O%aXaiw9zz~ULZ&rx z8fn@apwo^$Bzb=(=0C`$)~0M6F!dm5cobm&pGZ>KlZL;ajiiG?t8pMTu(9=svigVE zi(D8s~ceVwaAlu+wtj>F+{aQfz%=X zE2; z=U>>~t;L)V41)CRuYBKje-_lZo(q|xKqsFsgjE}KNy)nptUhZ~frKoo7XD_c#xBsf zG=@Q*hbfQ@!M?5aiCH$bKQFiTlyN9qH-c?jT%l@d=P_Q zYYKc=4frQ&3U{|7aDTlIxx__-!|`k~)(PRZnii5*$6@|bZ6cMe;Q8OrgUHu$7N5Is zF$JZ+=0+$^C(9EbVb)ejs*9a~y1qA9N!1dxzwO94)hKLPYYLYJ=HTpOwP2)FiH2|F zFl56G^c(XPhHScxXYToel~SJ9O0*OIokH*6yBKRPI~W3Q1`yzp=%LtWb=+w zQ{HNvJg0`G`{Xmp8p`5pDcE`s|8+nS<^A2s9FFaxsmJ5lx7=}5 zcI+c>8X3+cBAm*nFN_DJpC`FdI^(fSO%*!C%kkV^N!0QP#VmddRyW6Dx9S8OUa}eu zSFOUG84eh*@c>HCI|s$4rt)*`A#=cS#HycjeRCWl?DS>>ibl zT!J`HR$Lq;&Va`x#wsq!n2nrDVMaHJ67M4U0iWcIHGxfAvYc*ypd`+|TN1(i4C;7C0 zfo_L(GF)5;hn4S=MDGpm@1Sz39=?S?xFeAoE=96!4dY4O{V#K=@?Z}(>Ci;J83e5i z{dSv#`C*f2ZbuT%*Rmq@+B96`Fp!c4`{P#C*ZhQELPqde7&OG1Vd*z%+<5Umuzil` zJ(J_Ncy7TzKOZp~l7eMsuGE=-5c>?XsYEgtEz$%|&H6BYe$!4~BRM|Lc?i(I$J)w^>2wSD%99?YpV^&S|)&yPXW0 zq=Y*wP@nS@y!Jqq>Yh8Ge&$Q|dG1ZPwnB%k8hwMiIhb+XNyU7te>n^|9m;gB+hMf8 z)|`_{z=44pKW|TH-6i#$Epb4vGaaEV_ zzg%-asDuk|z^O)@jDZ=yHFy*IJnuL6Kv~%PIzNKtiT_cuhZ-8VB~XqQ;I-T&TChtC zPa3Dw)pf!iG<*{kPKg26*72m`n##v-c+D)b{xI3wrTlv>6EYPQz@)7TbVW1*C-n^# z*!!tCCVVW#WXIsD?{1W59)qbvN70*mJF)m^Dx11vGiDZEwpH-(z~2EoA*Ndj&&X?_ z%Sk8bo8^Z~udZX^D_3BOr3LLVoPlOm+i6AbLi}*Zmx8XZ#E$vC)R=FGoy+&o#P}@m zixd3TgHH1;3%1jXjU}wCHjti0zh$F(lE_kU4q6Mh=X;@kG@@lDoeqwmg2h89=7$YM zUnyV~GF>cfMqO3%oDpos?P8eToWd1pe}t?rk&t)#FSKe8#V1(?cyECnT6~*=y2k-C zgdK+VEIl+2Yl1OXhvG&q4#wI&g`gVgDqYK$Q0EZGQnx6e(%W{XB2q=a{-IQ?EQ9v1 z1?NciYZy~pNP%B(g4Vq%Dm|4C!*WiN`n0`JKQ^7*et5&r+Ej`-t6*F9DT-nWLRh!% zV&XT|GaKPEo^>*liA|F@N&Dk`v2cf9*xSwBZk~Xdy(gh~s1N$3561XSQTTnpb8sE8 z9P$lib;Wm4^@Jrg^vcq;6--i`~JGEYQWd*N1Y`f7}Lx zz-rrS#m1_(?tPrcxreN)Xa}qrv6_U91H|tvARWKKXsUUgJlTEUJH9M4JWn@#q3w%A1*tuYSg}7Q=nGGr15XZlvI?w1pUV zA`07BHg+{eVCy7d$LlR*|3?UaSM>|=*P->OJ+c8_489M_0gt#fucg`g4s+hO@;U2I zxy#A@@*s`R>7e9(gbKdx2JE{{7mVD%s^A?-05>o6lfUv6Q&i^EuQPc2iDf zC-~pIL`4GsefR2qfl=|oKe6U?sWJ!;toLT~^W!jk!T{dF{{Tviv9v+oD4dph6F!>% zhZ#{W=w7%Um3VJdZ(WDZLB_cMiyvl;O9d4PPaz}S&Q}(X7FZM|lC`@FACtn!>9;fd zI#^1+`#)A)Yj{H5+J(G@qQG?ymbC49`GZRGf`AYGNHC5E81sobol@cZ@DA#ie-3H8 zuaZv3V3cS~AfGyS{4Y(PR*u_*LHCaG<4rP9Jh>S>hF79YvJ;*+%)orlIvjS# z1)HWm#`d4uIQPjNRQ-4jEM8v_yw_u3eMt#=Hzl(tK1Z;Bq#>E7ZpZM-cv`SzAm;kk z(oG$0*lO~Qid2d?>Bc^aa9(XYVb}}OmJl-y*9yuX@|E?TK0sSfII+jZt4Vg}AV^v^ zglvbuhxrd&1vbhC10NiKk+!MmsWloy{LZ8CN(WrG?G36=c1OuBNzvw?Q}IWZyy$ek z1WuZyEb?yt&W+q7BRV*_f&b$67Sj}iSX6W=y7dkwoyR^w7n^Cp+G?u4UMrk~3^vjWNAUY*Hn3I4)Ed%311QgkJz8%j(z zGP{9`F?;VaI3k^ZdN>H@mJ}h(x5qK6g3mh31AlCOh^Z;sc%--qn=A9-Lh224a{9wH z1)WAs?L5A9NFHu`-o>)C1?SVs)dY|#_^=BIwynUY&noEre=>MotB}N;AKdItp>u&k z4pL?hW&2rk%_sI!-Fye`y?7f{$1JJp+G{4TU2XiX3mr^CMUz)nWX#Ry6F0PTHd6`7 z0WW(W{_%M!!FMZTYip^362q+6hF2O`F@qR}a;Q7~0-LdCBHHo!?9fC#JbUdaJDSlA zMgJ+2dg^Id`_zTrncRk$BdY|@*9REAV;n>MkAtMwB zhACOhGyM-}?w-j+TZLI@RDG3BnF%&5N#dds%(3;*ai}Y|L;o)yAfw$9?>K(|V=EB` z{Cf)OXAp}go8y-*O+0yH9!9>D$CuNcu^}rLevY4yL4`ZH)$c`UYPXXO`f?H$y%yfz z`S*C^*T>me6OLtVh-B%4gSYyAk?nY8q(wK!K}TyiNo1A5@Nq||^ocCS#mCe3Ukd2d zxSF01H^ZYQPGr5u4K0OC@TxQ)^!=^O{~NsyH!nN_4?O3fWd2z6{34Cqy+DjRcK|fH z60lF{C%5`j398gc1vp{Dx7K|6w%xX}FP@qTs8(;!g?fnb4-Ni%zc` z!oJ0ZQ9{@pGT1$pEVZr>ckBs!D1JffpC08MeT6sK`@?4qTOX0)T?;V0^Nd=)KLi)o z5~@fN;jF1{l%)`WrEZ?=>9y5Zt8){6mz!db=5n-|bs3({JcxUK$be078D^X~&Nmv> zpj_A%*1nnH4bq|H|4v}kvL*CT^8_ZyM^dlm2K+TKfd(a}gX+I%`Y7>&8I%eO)gg0* zzNy*5U3UXHCuq}M_XH}=Z)C;s<@EP@1mE!C3OPPK086xr=(Y7UG#jPINkR8QPl8r3u#;pubBZb*IT8E6XP5cx8D0Cxv!=Jisci z1(NkyO=^*Jpy=V_$$rEq7SlI{;@LVrrhW;9?OFqM2QBC`@=(xpmz_?MK$9nW?A?1C z^ti#ea9?*^sJ92M#o1!axKCgq>x|pL1pTeXV9B?s7#NcWKX*mqCW91C>fdo}G!Z&o z*Ph4aYwt0wF{L>E8j{Z2Jy@LRM_(oc;)cKgsy$>b_>eY`^`Jkncv%|FR$dK$GY(Vo zCk^&8(1*-dHnOyeuS~{6m+Erwu|Bu)d()r7Hg>encCbh(N@3s^^YN|7MdM9&lCN)BG z#Z9g>Qx8oo4?$wPH`-i~#>+3(V(7DR_$D7v-oPBi4{t%o96gNL(Z;0-J!3`k$S=-) z4fA(uvAbEXz_0l+I}h*S?+%V~3<{uIcssLq|G4pk;%V#WNvu^TjdC39ndX=z3e0Ka zk5&pU)QBHe=ZojjLkWBK(MN~wDrd5$z+6^y-k%BYOip3Ah;>bP1$oB=r;fKaIz2Gt zUDWmPVU0S}ZFfMC^?BH~#vN;Z%i`B_=D5|=3hQ*=!TAb5yp_rz%*+>)y@$d6;1MW6 zoB3sl55ZG9ndyud+!hW0n8M8nIF+tKH(LhqhgDUnXvbJ4F@6NO%bsD9cU7s;NQbtk z-e*o)E>tz$n_aB;B;!B+?Da!i`f8ZWM&>_b>f5KW3p$ZZ{NoX~gqLMvKWWT)f12ON z34W3hTWp(OjliKdj{qz*#2Y1}QDK9SlQ`>+Ub3&D<+7RJ_PhsSW6e-beJ*4bXrYsw zK4&WN42Inq!Zy~$Ly^)$=J-|yOe06qqzD=I=Dxnbe|4~eS3lXjC@E49eY_OL)GtRR{5{frMZC~@G)~3-QD{JdJB7n?iCPjV%OP&8W+re5zY8! zS(NzFZB=k^7X+r}!#&Gv81-TlmORP;Sm}tq<0`m$3Da#%T^-IpeUn5dtMyoQr8jjy*JEiie^~hRbhh-HIV($j!R9v3 z;O<`>K;0UvA*Fa6%?@q>V<&HleIkW@>)q(pnb)ug)F^T2MIlrDj2+CK2VNcrSVwv} z*PN2UdnY9Dy{;!<6EE~bU$Vph#=T&H-$T%{(~7p=Sb@?)?)uR29mvZcqwXDhP)@3X z=A4Vix|(xz{e?Q}oyeoM)sa<+r$T5--*5JOh%H68YLM^r5p=aypMHF5VHtuG@$gm; z7O-ZTkjcGXwfveT86Pd=dUSJG|Ds5^QsvHjTGYXfl|!IHrV2XxAHl4N(Xe#-Gz>nK z$o~yZ!n3!(vA;j}q=icW+=*oOI|yR33}k_?Qhy%x98m z$t>{TcJ{FT86OtCjV;bHgH-t#rsF7$&rLFzv%pqOm#<=P?AxGvTsRv$?;s>vH}Ucb zL%?T@C1jit@$&7l@ToYG%^7zHBzNjlP0AtQ_OGVg--(b=nM4VxN>K6a6zw}w#Vs9O zN2SC1I5y=X{V-SLE-K`c(b4e&OO{P1ji>V#y@G2@Qi+e6_a8O=8p;mqPo#(I?z8YB zM=~u_q#gT#_MCsq>L+|;qP3B1`tWhAYx+|@$j5~9U0YuDIaUv3w-TSMH6E_U)iF6w zYX~@{KvL=lxiPZ_P)XSa=5X=>Tlz%kJ*qgu9-doG5q2hQ(vl<8wdyZ#m`fzJM}wt4 ze@ybkmt&!A!b}39MUqlkRirmKC zT})=OH4D1c$IA>Sru0<;#BTL0qSGIWzj(2Rzq_HdLy9T&9fQ{AscdZidAK_2Cet{3 z6=JMkvY!hVfu5hh$X@@$54q?`bECenM_sciV%Qu?UF=SZf`elJeLYI!atIf+GO3yp zD*MRTBN3xSI>ih|T%e0r^I2Z{IkMk1gne}=qL-!d-20dD^i=mem~R+N@+qd6HBz7L zUA78Crb&XD+$J>ISuA{iti&-(2jk7!m1r@1FdDr!!2;)}kY|++%av-u|D_E-*V`A) zG^VjjkyDtlt|ECqXkj*W&UEsGJdJwhOY0&W$? zCtjqx;VcFHG9~9FLjR$ZnDN3rsI2!_m5KQpYR&3~!mCbXuwW^EbkL;r1?iac=sf$= zxff-|?`BLX1`pV;XOk2|vB`Z2TlQDrcI_lN1^0)Lmbe9uEl&YS%P8Ppn6RKNJK&>? zh^`%L;JhA2kZ+bm(uv7R%G<$m2u2R)v#{-en>t=fnTigr?Yr3;y5O`+6tE~LL! ziGtTU(y*OrY{s3*6yIRUy;|%{Npb-#iERP1y2Vtvc`QC|oI!sl3$Dk@l1OXpR| zH1!$$lAKBz`pxhtZ4OO&+zUh2#nEUXgEQ9c7&*Nw;?Kt)Afx49y&hI)cwz=Eft~!;EQz zb}Xc}PbT%G>+s3aTyO+c!O>?^sr0iuv=^_ZI|>|(s$5NSX2W6g5>sl)zRqRGE?~X0 z?U?`h!C;oOj~y;(0^5OJEF@|Pwgq+Y>bLh}MDlpef5cR-u_8~)~mXs+MqA~G4&)bSo7GO-Fi0>&q`3BCcOlAe+Ps0_dscim|cU;5;r>cEnio*OF$vuzx#;T8M+1_6| zlA7IRLAOJbK&lNc9vw}NYiw}QWpk3cYK|R}N;G$vF21;x%_iCn!Td+pc(p%Y!CPko zcR!>abZb-L0JjRhpe$OC9t|r_IpE?eqir1@PQ`DhHCb7M8(!YOlx1X2#u~X}?Dthi zlz8!qT{|fBM{et5jUlsPZPOq+7i+{yuFBJ#PnpbHeF$}w*D+;{B-U%HN;y3eoZevv zdax`FT%DItyImR>__YHO@i$#reRj-MCQ!_c>?fLoD-L3YU9Pc)J!H;!Z5HB`KBfT=h>I@>^pH1HOBZ zro1zxJ9|?9uAAJERv@RP#=QG!Ig(ho%qA6Yv-;W@F#Po-ruQffRG<67{rQ3?a*48# z>pubdV2r;8^uqnywrHiMiE~q@;*OQ-*sUCdckcDVMz@XFm)`&)!6U1k-U|{gis&%! z9ULpD1kZ=H;BwIzew@jMV;uw7H^XC4omRsNo(;gTr5)^|*)WXRu1v~nlRzn+GjUxhAY z!R7vbTMQV>PsN!x-QaPvA|~&=$C*Cd2FAt4V9{w@l{Ah)_0k+wu8hFm{BG8+w;pS3)hS@-b`0w=rqHimX!bvf&cvOn?+fFmkYpwyAxe@|+_SbM zl}ai}lCL63N`q7qDQPm5c}Pe?k|e}EYfF+OX_6$NQlVK=iBkRc&mV9f&wb84d#`uB z@8``MO(zx2AWixQ@s6byQ5RL@WOwP2z693W^?nMu!s&zPnGwWdZUDYxm?#=TdRBgfF&#&U z%Gq=f+qsdzH)*(7JdISC6><%ViX>`7IG@%!4Au3UamSH9kn2mvhgCP3_aFkZS4;s1 zbvMRR?h_`Ynxn%h0UvlT(p+Wevw2vM8hpOs%IR6S!1=nfT#<|w%y009s^kE$_pgK0 zF|AP6_zs4~Ym(@@a%9&;b)ws9PD`LsQ; z^qz$sLF37o+bwvt|0XIZ(8qKtDo1+Vu?)b##+0TXQD|3XGEb2Jft_V&hdeS`67n(q)Famasp31qmjwEX{GWh?tjv^!FS&6ayA2|N^D7%+G zgPZ>qfmCD^MAz>Ek-n%hhp1zqR=5WZdLKb~a|yOz`2@Zef6%aBg4m8Qq@kVvz=7we z;UpQd+0~xTTQHyOf3%6-_+?LIS1qN1R~D0c$=THO%sk>;V?YO<8<5h5R($nTocLeO z<)cP+L*Otwvprux(ye^hGWHVue0&oY{ECDD*GFKx!3-LM$2FyrBJ3}OzPq{T^djF zoxkwSlOIFeip#>Tm=4hTlg^1Ke22t|hoN9g8w~$)hevr~(0@K1s{Nceqafz1?os8N z{2ze-1PfeoO@b60tHEUovg8=^V10Pl30iN=Xr^W{w8v@D*O{YWwCE@rsvs)-^+=pr z)yabT*%#RT62*Y7z1TJ z_fcXX6P}&@i8v4q!?Q{-Ypsw=)!K|AcISA{*!8&I;WU5W+zq9kC}Z5MrJRQ|LEU@h zpsN;*hn;nZtCj&yOz|M~d&J>*MkLXGkp>Fl=|nNc8%EE~WGu>6uw>{IS^kyzd;f-$ zGYcz0WBww7|Fy%exHcGhyB-p=oS?`&8%_`0<|m8t(BOCn?Yr`z^Cr`HCZ~d>gdrWU zj{wgMEn50R8r(9psoZ%{=n^PWf2B{HzF`W>L@(nClmxur^0@Mhy$hhXXEU!}^%Y)+ zl< z^>Ks`+%}FBTc2lKk`l0*I)F!6x5JwWGigNbXufXNE;`&X9vush(uAOTe6V;ojXF1o zgR^JTnIUrYM7j#?FCI(t)?GvIUM2eMf*tR8LWb&&e+Lf@W$DR}E6KzUg%}dOgE;v$ z@Cpa_GcJXz;BUlXqE6FqTaJC`pbp9n%$9mrrXXjM>NT zJ_b%)W6^6cX?w(XbofB=!!sBvqQi}JQ=pBP4&n8dl~hrQv6dGerZ3LRP|25pG+SDo z28IPtr4eGZhTBHd_x-};m=)B^cr5MOqfh6GkEf1N!>HZTiKR}A@H06A+b-MT+8dpG zntTW^BC2L~^7blFJ2Mfs{AdAP%LK;$?gqQdL6E&_5VSLT0a6z5;6Z~z*VNA=H#@=KtI`}aG=U7go5vonBlbf-kCm_lm zOrintA9(9^=V)M!9;dprkV^a$gY;X4tSfRg#H>F~r>$BIrYD!sS6Szw@Sr3$sjr3L z*G}kLd>u5#E`(s)cyLba0OzdTAP2HUf88`F9y6Ng815Ecm--EUS#fy$WIKG1?Zm$L zbWYLg4tlnvpw!i9Oi0#XIr18;FfgIQ;C@W^x2M9JwYbMRl=g*9Lu0R#6vtfSE&Lg4 zY3x>hW``H;A2l894R+9q%u+a&x`#UY+=GnJxwJ5?0yNcHQH$x#AIr~U;JYZ85Oo>D zZr|gU=B8lC{8B!%QUY=kgHd;m6xl4-iY1RUNnp`vT7U32XzkLYzm6jmyG*4C%XDGt z8Ua;kUx4~fN_5_h20Z4Thz2H&nDu&qzj);>>MY3NMZarNk#A~3&&LO;*3rFS6Lppz zx2*-q(p;Ky@-p;iAD|ER)kDXiCCy|V)K=#-Xy+rgx40xq<5rCzrYBx9P9$Sg|4hZ8 zkxdZv*cSJtN5kfUBEDz2JoJ5x6BwU1<8}J{IH_D8#G6{2duat8_MeSQLPyh9-5wNZ zX;c5_hO{zb3fXHf!CYaj4YZ3dvU@Ga+g zj^~$Xq=V(oO#IY*02ZwLhOPnIc-t`=^x_F!JUa0|8r7c77k&<)QwrFuoU?@{2TM{v zi8-_=Ybk9@m7o$hm!3ELjIx3S)W$Ijr&zhr;buqv&Ik``D$)kJJzg}|aRL!H+(FMB zoJ2R$CPfYkbi&~PTTDrN!T*Rso1ffWF;@5>qB>tALC|H6L!|!b(>9R2pmXNu@zmk zc_Oi6&(NtGtRwP+ByHMM4<-tqvCC&3C+${%((-q3jjS4eJfuaZ_L!k*xfZqFcpM#8 zDpRLVC$LU`I#s_?fj!5T(@8@r)VkJ^-Y#85cLjaHWX-Kq?NLj|NcobGl zI7K7pW}{zeGF_+e0#(MGpnu}paXDkuI9ZjVOcC4JL_NTQ`{CT15lZynlS0VftVrKR zE0R^dOiQ(NC4s>})sLi+Q)bJk+@cDyrNoP__NXGw>g%bucMiD}<3NWpj}VxoPisa^ zBvpSW(9@mHl%6q^iHbOHG(?rs-TNm^V%n`W7Nc4gesqwq6cM_sr`ScylkN^ecD$H z#-j}A&i-}8s6m}JFDoX|ng;aD^83W=|JfY92D0L-9u?zxQZ`wV_MSgMEM9y>moz;R z{Zy6)>{$j+Mt{Z3SW_s-bjS*1Uhl=demJsi?OIQ(d2~>cBbFw&#pcW#%`im*kZ_X z^G+zgF^E`au?%BY46#yX{*8#!^qLNDz-)Gcqn4_kBbM4%gOojMEGykb1LFG^_9f1l2{w**%Pvi-S% zI_CJ^qM^^t_<4Tu^jm8)mnUsQAB}bg#m{BvXcGw5F7@VjHJc%K+Znj|`zs7v%pwbv zUjpBMk|>RP3Gy#9$f3?FU>U=hrn{$s=Pr-CrPq_U`!8XP%~;Yp?FJef%mw={ zf3)6ci8Br?#e_6fI{01-C&`7-)aeR*<4l&9t3JX7w3O13UJj6HT0|cN9fK={DU^51 zf{Zs|RQq&0j51qIy}peiwzDMZrVEou>WlwSuTY+dq%ObWvhxXCz*x}SBuX|gj!Sx$ z7BLcRBvDDD$?V8C?qEH8 z=J-PDFvgr)k6TYXMKh^ko?op>tFMpcd*!{T!?eQ!gO)_9)0xD1&5NM&)&g+Wol9Me zPD6dN47Gk+2@{ug;`obEpphSndFfUVr@Iwno^1k0i6A`iC=XgLNMn8P|zcz`#> zf}wUSPgnx7YLlq-=V8#yTR>eURmRMzsBcDgt-BoHthnz zRoC!#R1S%oDJeYYm`Ku;=EJw{mE_90c93g)1COV2r2hIiIPhT&*>Ele#hjgpZ0-zt zRcRr~3*W@LZ4HS>=jAGF3(OnQMtb&L7sBZ9#PUEU06_bW&>K!nF4Z z^7@gm zkH3T=fk(LpefCUw*YWm=n$+?_B=5LjBJCUBDX`2}WnB^p!g<1{SeakKm+w7{rbiD6 zz4kQo)=M>ob(W4Wd^ZSJJsrbzpCEMY-%hqYiQz0%gNR@3O)f3Xo%A`+;7n$2AcY|c z5b=8*QP8b~|8NSa9*`ssWz8^sqAZ#1xD#Fvh?24!nm`})K=CC>PHeaX_M6F|s!TnM zb4|51B9X?nPgYrip(82T*$r43r7M=1^3Crgo= zqiZ4g44P02KRU$-K&oAhA4;G?*U(6{T#FtzehO2Fp?DSSjyX0IFs|Q#o)%8kwj(!WxLKJAlTIbE;~1KA?IHL_PpU$KUYH9 zt2pc*PJ@&m*Rf=T8@zAK!JgfRp>6&`Tt2T6@F(ylQkkIcm(Nv>R0r#mE+E&E$#smD zAtc`##3n5xM%5=l_HGz)czy-`E=VCJDpepS$L9G7xv)1ln|M@4!_>r6WWCaAcy{y% zS(-4H^I&pR=ikRdl|`bYr$!75UcCde@+()B`XjL>A-Ez6GP+!GLx!SumPujH{24&KyT*e92fSF`i)hCz04KO@|kw!%4Yq5hyWkV!PBk zND$dV!Zh_r)a~`8ICcW@IKvT%KnYU0;TK5cet_rp$6;e;H_Pu;bD`1Kpz~`s=d(W+ zaLX{)eQPG`$ZqAFlH;K>^)%OK@EQ!?EdjSjnQ$xr2B>5+FingGshpn1RXsH#9<$rZ zi&f0X_1+-Vo?t;XJb#R8vQ{K~NgaBv(IJ!5v$4i+1Q~LU#A1mFq-wc77Oa>|LVJ#z zn=-zK+!Sr*hhTbii#rtlc@H`}jzihR&ycb361;1<183XoU~tABcyP4_0?$o=F7FFa zt7ZW+bhkn0x)R7`^JdfAC(tN94=&qOz`&f5(01oCVC-(bMC?3he+Fe#7D=gfjdEgsoDezeMAp zacK*l;7dVt(_H+}*9scpDO_>tadeLskq+f{h2?AO@+`v`_e6|p|? za$NPz2H)OBv`m}L+gCJV%0E4B!_-Q&nJNO~oerS))C~}{W*kbC9|66`A9>|xNs#pK z4i}O96spB8!h@VHSbD4p0_L_uk=A*LWxM6+HV)8!6}i(gh2X0s z((EEnE!2KP-Jlg6`7IY-n5?8n%Do|2Y(4dvQ^I}SzmA4Z9w=KKr%or%TFiOr#bAP0 z65nU8#h~`nd5fDo2Q%>}W1ADTX{SisMe+2qfu| z%CN&`Ia!*x7uMgHOnh$afb*iyz_NK3I0Tvsm2X?Ho|RrCqYB_~i6(7NW19YPHR^e} z66jq5XqvFF`r%>5cpN5Pf`PCmkUpV6Ydmpu4MpYEXV#vl9(pM{ue zmdm?NZsqI!oQ41T+d1{-KH-x`mtb>gGr!mN5y+Nb$yz?C zFb7Y-`5~64d>8_s_BnB7-wwj7Gzk#9KNl*-sX=4W3QoFj1NSt!hOakrrA;9b`nruI2~kr7sB6LBp3%1Bk1`*9KWekl3o0quo&)NR1@IosuHY`g_H)IMYU#wwg(*(#++Wkh;!E_^0x&=ihPv{ozm|_BXe+ClqJw z6$NLvbjI|n;chieMGzZ_sg5&v6`KSMT^Me@UHlSuMimJL{J*1)ZI$p=f<6r`N;ID` zZ3gWO5aIGubZKY$B|&WDM>O3KEie*~z`hF!g1wU6eEv9bq3mWwWEWTN$ZE=m9=K#~ z`sOQ#vU+H%Ou%U9CeF8X1O0ij^!e#cVA*3zCExFXJwK<=&1n(P^+AmODBlQ?4_>j( zxdpH%{3J?#d(ADjG{^qOVZ4XtU7=6wDQxYZ1A|k)vPE+pJoXf!6YKh6-A^eB%;PZO zm?HI>JC=yKNm89;b#i9WZ`|MC54UzUqFUMsI0(@gs@lm-+#!lCE}ERnrw@YAqC)<6 z^B7Jbg80w7O&Hv)M$v=_Hk*y1evTWtsuB$v+V@w$R(CYvk0CanSw@W-J8)QNM$bRh zqk1CpRO*ijog+Vpof|Z%r)n{(n2)0Q|DEOUED@zn!Z=vqUU!GL@rdS6>g>S89~b%XK5<)#*Y|5zW08kX{9{hQ#*2Tcss66J3X+GBz&#o&uG zaKGtd+Wd}re47%evsoEFyO>AcZIPl?9P?^!pHH_JGoEL|cOP9v zEdtD_?4gBpD6$6+E!Cj4*A?-6;RQ^v4uNLN3p{^Chk)BJF2ZUh(P?*u6E}j1%zSYc4NKK<3K+hhQlj+!9_b78Vf%Gu8)CL4@VQlu}?wb*+gQk z)B$7CenZFUEEv4G6EZ9Mxvr&&T=m@$vpFv*KU=trkM9Xb{@)z@V>pDi&(7c|DHkg9 z>Jff@UNaGfR>U9Mw%amfZ|!WwxO46_wd2uEr!r? zX+QtqkO6@HLSbW5me8q)3Wf&~(66~f_`~}PN^?rML5J}?(^q0c?;<*&dkpOktfzK5 z`_MAkms(ry!p`Opx^%=GtZI&=Q@+f>6w@erT6P)k`|D4)oO8hWrdD*!`un`Bvp99R z^PGSFHx`ql%rWUN5!?dCws;axa*OCL7g z48uS@E8hByA3AL+#1a<^)KZnCF3VRwB+;ZI8z?w_m>Pbn;e1bX)a(5PenfZy7F5ha5358$$ASQKYd;KP zsk3m&>SoyAHNgK_^Na0m9|`$YpINV;tl-;!tQSVJPLQB}3QmlzWRpHm4`Z_{j$NZ3I0evN|_de z;bIY9zvYG(hAr^ZSv2n$Sn<9#*Y#0OQVI_;&YsNPae+_D_n2`n;Lc zZ&M%F(PBsY>O}b&b+*(fauk-E8Pkbfnm8q5G~Ht~i*MfAiJ>>Hnor-Ifz4}mIk%e` zJTQie+A&>zz>1<_-)3Q*>;uf}7|9JvPr=((jJsy+&zJ0CEQ^;{g|i0s!n*p~0^|3m zA!D65ANu_S#Jk&}!ukLZiI2x&a*sQxa}BFcY!}EJ>O()?7nkNe!zp>9bW|$E`hx;G za`rWxxYnNfSKdbF9kZ#{jaO*;m+`t^U&PRGIeO#XUta2}3^g2CBIudW%0}KvFeCRA znk|V05x4PzS*f<5vF#1a+aAtIo|;Lz9!%#wZ)p(Ir$RnURg7$~9?LHr^Bd~rYJ|Q| zJK>OdB%e8QDg`cTiQS4<=HpTJMKCbCnsW2-D-UCY$SfJ>E(2kYX#1B4KSv3 zBiLLPBM-ly0gXxtvi{8-K({(L+a*T+ob-b(GM3~u*mIGrKhNK0JT9y(0B_MuR5^Q@ z8^7ZtuAQTcp*M}Gx9uGqez22nwb!PlZKr6y{$i^8@*HjQJVsysI!pBuSp_O8J5A8EgVZ-g2M1E6rn@jA7O2j2CCk-gKCYd=4-0EVP#w` zr}K9jY4gZ|=8aZlIBg^`Tc<}twY5op?LGLVGKCD?m4#TMNBC|DY`ZZ4MXSZ>E@=nw zwcJ40o>0X4HK(ZSquV%sQW@?1Ce6Bbt7(RmI_CN^;`@J_o$5c-%PEjVf&VjW5f9rUfZe-@jVa`THcgVzLt5!u$!>&q&gfl26dY z`!4=E8iqSgCi5|eG%(_`B$&qJ3VgGVGvBW}WDDcj9Cjaq%5Ff?R?HuI zhZE!_=w6LV)(NCc*O@w@_P;Sy>5u}x4{XHy?sojo!Z6gR&F5;>^w96@Ojxq<86WpH z0vf}X2`7u6g}m;`;Fi}0R~2KR?!q;5y#l zcmY)G8ZZXGfak(y3|rX@%g#37gNb(_f4C3>E;d54yE`7)*A1y2>-f1Z-#|&C2k0Jr z21#EZ!?XuQuyM8&2^Kv7QRPacB*YX}{!k)im3f@Puo9`XJItvb(j)bg-*W-)j7X!M zCLEU6CTeAGIDJ$k9@nQs(`dGG*F zo0?5{MXC~9g(lc4s!H0XMB(ZZT@pR_5{9AynPeS}xAx8@&W;jTe`ggDQ5q#^`o+39 zM%aS}^L)8w)x(XVab)d(sw88aB3V&1hfIo)BKNhIvR>aRxL)rpk_hH0GJ|*`clQ=9WWA*0rmn^E*T;!Y zlbUefoDJj}%kc~ZEFi}kyCGq=0kL{8h16OOg6J_Pvc_{N^mJ|_ZEhP-Fnc{wbP;7; zGp;0ZqBwmKY)_J>ccNm&1Tyd4V>G;Y7dmF=Ve6_ysJoHH3{JF^aVN(KPw;BktOqXAI5JpWXa%<+xRH(5Bxn@j*D@Sby~%v z<$*4kZn+5EMSjA|ys21Nqf8_m1eoAGj(GjI1}9I^C!x3g3Z0n$&P3`Y^Q9_~VD_08 z(C09ZNn% z?<4mw*${6&oY<{hPtN)tA-bVR%4~2l4ka&jGx)k|OGxbK`+VII zO_F6EZ@zoWL-37k;as{Gg8gU@0sg1MmC3&m2AconEyu3qe1cLjLiZGxC|iXhYlZ}l zQim|~M|FADmqo(Rw>^U3tc4)Av70L?35Q0vy&w!Ngn`)W5PRhZTz>rl#=X%dxcW8h zR5v5dVfWz{%lUi%z7JU!))9x=YH+`El&pPU19g`VkiQrAf@_aCG42&|c_~dGk-QLg zFPaTK9zuBQTFZU^!nhJeA~Ur`mjMyqi;C&DxSqE6crD45OU(F-j5xWF> z>TxJ?R<6uNx0l!aHJh)K8sKhTKg$`>N~lgg3C4Y6h%L*?Zo4*@y;BrPQIRW|zib4l z4GAC_*O}jQ_Fj^_{2izjyOAGeFQF%RCW$GeuzkB4F?)OuP8Lg(iSysWozG3sGOrrW z)K6qw(ge^1DLisA2qZ_8qRT%wkW7=I#WqLa)`rP6x$h!O*)2y0FV{lh!$Le-S^!4f z)6vq^5CWxac#)KpvUO`cL2Qf&ud-8$SnA4gJ}s8ySLG>g&QUKSypX}Q{I{9dC|~Bn zzB)4>xCOVseLkty-yn$MCK3_WZ(6lcnP_#FbDlbVFfV5%>|3`0h6}Sn`uRux;H-x* z_tb901DD~U;vod4N&WG>h&oOF0@X#I(YnV~xZ=Jz&HD97XuP`$2kmQltD-%)Ht_*} z!u=|*9~j5mUb5o+3)A`BOmhg)u)~JJ8c0g=L$eSQl5Y`!VwuaxiFHosS>r(Tml@-< z<8ug(+{p*6nnt$$lZUL&V;S>*GpHXdfxiak@LVpKD-}vW)c$@x_4{v5es?mu*G*?^ zg`c=&j6QhFPNuaT4V*QvN3$N>6GWVlVp#)WS%=OL4w??|gPzPYKjIV`>@UYnm)dbf zCx=lDJ*aIG$WPsP9|QWOVMfn6EY_}rqK)S&vNVYQo@%}^5F=r`$qBEg;>`&}j=?)nm zmFTST%CLH!4mGVb7mmF+hprY`iBV>37im+7PNS7*#h7}upH+jtZHx_lU?awE_=Uco zr7%dO9y6aZEl~O-Km5XjX<;XzK`|fn`6l?XmE{XYRYQjEDB^sz3rg>rkb{H$aNK+j zDKohS369#Nk7=|KELT&estqN&N5IRhgj0E&&4tchX5Q#*j4#69@J~m*#b@5JC@eFl z8>iG_ME*)TzV8j*6J?B^g8LXfW+wIG@^I*%0zDpPjQ@_^!|x}C_%-Sdc<$*0>?_&J zOOKz1R-1;n=~puNwnZmF5Uj_UuQ(4c&H>0hD}v%vdtu|AGhp(^2MWu=A#u!B2rirh zJ}(Ju6qn~Nt;)JhL}<$lF>3j_02#O)pWO<^g&_yA`g<_;eXQXV&KRSLeFf){s3c51 zFaoq+wsOK9Cg8H{HkTvf0M({X1rNR$vnO+#AU@)*D6 zYtT@DDw!tH=a!EwN;;i*^kz@&y}Yv*o^s~#&efTweg;o6<6&&x_pnH8k}$*$3+wz1(6CruC(w7 z#Ceo(*AK3S)Nyw?pPL+5Kh+QnPOjn#rb(c_nKUN^acKx{hlod5vos4@=DbTdOUtrGQRrZ324pt=G`Z1KG(0@eiITQqzKTF2sScLjNp= zh4pi2N6BUQ*GOpf&et$@ogQ5=)C&u){ldEjPar?P5|5d&j*1ZrF)(oz9Cg3U>(wN1 zjZq7DrIh*DIzyb7_G3Ly_b%MQOsJmL_yAl!GSb|43n7@ds>Wsm!A% zV7Ekp`mU&F-f}Jaxw@9+dJJfezYuN(vv)*5FpOT*fR(`$A%1QO^KIT2c)m=*F0&VW ze?|gIuvyJd%N18lsKIlu0c&!;q16>TEZnC;{VplszY8ifm}!r0Wm2@J(iI zWM{34xD~pYwV>0U4S3q@Bev`b#oF(ZG)*B5ceg3hStoB{bJ=LR+IuA3CiVxTe3;I; z^#|H-0;+0SgSN9~&}s39(aTgo$Ngh7)oxR|FuF)^piz~+Zy(9Jk?OHlpa}a@@AIc^ zdpZAE-rV0um$++^rJUZzqg-#-8LsxR0rzeM75da^bM>zpg`tL*%CqDY`LH*2{OM9j zbX?70XRAGK4_Sh*8S~m^+AMq){{aJsXQE(_8tqsUj!$n-q>b5#zxp(&{M1@p6!9Bl z%R=z8S~D6e`|wvk=AeHNFANTHL-kc1LRS-0bT}L)=s5g>FEEVcS_`fSOJ0qKxnnnQ zi_Lb!z)e*E8&mj~I-bp8=|a=sFz&+!b^eORQ@%-eI#;pY3qMQ?6qMm3r?%WW6}33;4G4e^A1GA)#Bw?)4dv2bSvQJ%U1Aoc08ZA)&#sC`*Yf|HV{Cb zakjtDaB|;2b2T?cph%qWjB5uXkZwN1pRS6Xw3Svy4e) z!FHAnm`u(_O~oCO(j*do)70dO9Nm`;3H;{>Ko5u;VL2T-4i(et+tq3!2xJn`rd zwq<*wez+s%vPe#R;8eijmjH@9;XaHHe_^mayjGY%)9cAb0J~a`HjX zi?i8gPqH@b5TtFJMDou{bFagngSmSt_bK5AcYR+4XL0Q?Uh``gG<*}M1ESZ2iZw=5 zy-gk4(1C8c#qM-h1L?>M<5^G7Vd@mgddJLIC+n{bXe#pf20SC_WK5jT$bRmDO^@M7W; zyBR(`noSr`2+ z>k*|P1(U(j@FOmZf6hFP7m#+#6RY=sc_(QN(ieYLpxCTTc50?`Bklfy>Hc9ZfALvp zdO8vG%-Xs4pJKr(dO)yT;uCBOs^*()6^R=Sz?~M)p#|CBK|fHM{1Feivwmz11zKXS z&4;{Fqw`mV;XBE%sCq%1Zl4>E5{xBabVUY*50+7vlUl+Tch=Ag%9=%lxf$MVlQ7c?w#7PT?D|9GNI{X;MKiG*T0b<1B?KAYy z{R)>^Mm#R}2l#X=v%91^dHYP2-d&N?3g7Pc)FEJfGFD-{c-<7<-VkuX*139_D zk(`%b5d51gf)T>k5aFALy#*gYFY_HP+$loL=Zv6lZx69zlTAER`mYwIoRKnqyx&o z;n3=lw9;3LNIo7#`CemUT`EJ*Z&4*-c3-gUWDA>_BhdeOI2b-!!GH8!3S*A7a!E(F zaRC#yKt{AEzH2=T3(Ask3)7kMzLeunhr6)9@&bnEzW~Dy)-R>?9`Z+OLafMVc%@ek z84{Oavg=i7o;$#1uwhs=zn=d-Xi3JMI)Ogx7L%o)o}z^lO{NHH-rDnD9+$H>oE^M!`b)Mf>3EZOuH8cEmzin>l=UQ-0cZB3TA?7nlD6b z=@XQCg@K9HbewYSJoG%-gHvDh!`a{fRE=N^q?e)WE-{XH?~THHU*$-o^h(TpDMCcP z$eN|fyn@Q<9$W~UTl&c}^G%~Bf@ESf=UUElo|mH`kExi-Yd^qRR`oG^+&6f&B>}eC zRYJwSXt?sR5NfC=99t0wP9D1;tz;#X{@M#iHASG$+XnoumJ8xOnE{HI@ahwmz|;@+ zsPWbtR!us@xIV`rOZN!Y9Zdnn#mTruhs~co$vErk5JQz z%eVksf|OW?U_KPS98JEjYlPSAyP2?7oap9d!nsFG+juPnYkx|U#tkw8rzR=VS$(Pe z`sxPo|K-958J&Sw%f>V9zYuOO4MmBRhwxJ*8f{D|`1OWj)PxB5+BpYPd(EL|)?!{G zSrLMr)ImW?6ynpyT_@LZDFUlLPa1J$8_Q7>SaXbM-$N0$&_Q1Rs9Gy$yq)H&Twc+vkH4`|fuZDS?XpB(k|_7H{!ak)&7eM4G_% zZ;s60^+JT?hRaaC;w^Y@)u&S`Ps6MwjFXX~$vHJV!0$_@V=>cJo9_hSt}k;jZDTY( z{P0qskh2=QY#ToGS*~$Ad-)n&LD8cDQNpd=?ic2iiChrqsVR_j^lGDlj zPHK9@ary}2E%yub4l0vRcMrl02YqrhZ!SMzXG(4;B;mIdD^fkV3mbK`J?~vUv6fh z)r5PT?UV=jab_-zxyj@Hff2;#!)p9>#gr_EH^QDd_Qd}ESjao*K)hE5L;omKVpe$v z)_&}Pv>|zND}#e&cH>A+#!J4d)sRHcXjC}}WbETsj3Dz#HR#ksdW1#@g6ei#@?+d81V-nxjauwI@+yQ=>Dd=AE z6w**1(^kk5anoD8lavlw>TAkx5}8T-w{>!7FE1ulTa&@rYYx!}`3wh-Dv+0fqQt4^ z9Q;@$O)~clao&4J6QjmAyx|6>zichS6DI%QwUIde;Qa*5Scc~IvJ&{POoJLn9fdZ= z52*R61usJ-Y4-M$T~xgT-g-0<_^w1{uL`)bEfNb^#dK;g zVsHHvE-EVvZ98KGI@M!P=8f~Uxg1jyTB;qD>P|E!H|s@ z5gKlVA7%ewq@gW*VmuG)@ebgFjLj??0E=F$k=H-Af{PN{31&@(Ne6Dh-d(0p^)L~_ z^*6x`c*B{zu>~KeW?pHe7D!K9j~y>mV1GpfJ{jo@{r_X=OdNXXqA*;kv~MaYrHzzO zskvt=DH27tLKG6Rg@hy|Eec6{A*r-c64mdXNs=TAVd99%5p|e~At3j&y(qPcK+6R16o^g+bc5 zA0Vr@8zy~FWv`r?4zD{VvF5wR!hZw$Y>;*ebX~BP*r6>7 z4U9LN`)vgkT4u*ozI{`&`_*^Bxy(*7ak3^IK3)RfBI2m;1Y!1-<`?Sr<2%?4|Du!p z%HdYNG`5-Fg7pi&Q7PLB=q}kti@KvgLi3TJ>9QBAFMNU17kH*$^jKC#ONslQK7lQ}X~0ccGL7wY{4To&B#E9#RjZ%4`%-g^=U7>C!E7Qll+WUx23!Jp zd2KHFs3%BY_<{D3+Qge@=!P9sLFJiuXiDMM74r{kgR+KrN@Y}UdAkTn|_1ci>DB=19w31E1W;OE{7bO7vOk(3Q2M5g9KKJ zz7hKauf!&!S^YmyH$RI%lYfJCW&>{4d;yCm$Z$-1DEw{L=W2u8pitPDlbhlIc^cEW zn-w=mkIW?QwB;}f{O>V zpwgoPd%QhCt=bzmI>ZA6j%8xa(qYNqQOIu&2d(%Ps2wOF*#`fCqv}g~RI46VzE8wV zo};jNTNid(RzaqOC})|I2a%0@|8}+=yR2LvT#%Rmt_T2BPI;%+!K(hJ2)dg&6$ zGBh>*L1Wwok&gXDzq<|NwqgN&;o6ULhiA}M{co6%;Umah*vHRu4H@0+H+)VlMldr} zfKT@)(vM;jFzx77`epPqNk5Y$P@c63MwCNH>g#N%FG?W)*58Ez(WOk+O#y^TjmIUm z=^(Z@0o~eH!zrGDXdiuos16>)ZC2};=i}GogSJ!5oj3kC_3ac|80U=I3v5s%^#i@{ zeh>X(_!-St5l%1t1fGbV#Pz5qV5!6`?pLKd{&&uZyQw=3yIdr=>)%bV=!pP#9N3Pv z{n4nfe%G>EQA^_{d$DJh}4(ZKKp+_r!8!jP^nAo={wB>kdXf->Fag z5=a+cD>yAT8*1Hq8D`Z_BB6xe2@yWl2GwLV5l#vQ;lb*aqJOV<$`=h9Dw z_fala9XrgLF@D`DRH|ykxBr4MUC3Ka#ZpIjAZ%7tUXh!552HLe`QvD$%)v z3_QEfh@8%+?|ieTrFo#tQO32(WO=G?L$$jCsvS-Wg26^vIS{ zbF-=B)cuLrTkQn33W0c)SpnAm!T8{p5~x`vqRGQ2OpDGC3V&RSE9#ZF(1EXrEniWj z#*}-!?h@{q?#%t!rH1~;H*#G(-JSLI;VQ{|rdE6>7o$Fh>D#rQD|kJbC>t!`+-^h? zUrvSF?ed2#``3VG*)u`W!x|U&908#;rZ{k=AAFAZM0&0Z!;7cKAXxe~Gj~-!^tS#j zZTCxrnNRtd{+9cs>z^g2-_H;ZL9fpsmUB=3$2u$yLiPAe#(JAT&rfki| zp9A7t_@7fa_p%%}IAa}}tkU5`nspG?P2;8ys^f1JMK0^Y9Q@+{0q^p&RnJ2gFw(;n z_Y}yXaosrdPTxSoZhoWQTg+&E!8aNy-pMTgE1)|fv>~J0j%tHDr1+Q9!bnXxVz3qO z^!5>*@ElCBvLXpb+c0%Q4Gml+&B5wpc=f#km$UmSn%sJa&-PuxfrbqzR`DA5ta(Ep z{gU83cTX$z4prd>?2Q@S7b={srG~|iJG`&?Pi;x-4++lKxK>b5FU55|k)$D#eb~E2 zh+dD}i@$>|QvKJtRHse_2Nu?r3W7{9(zk;I>R8~1^D`l%!vJsXl?TZK2559*9oaTp z8z)w2(Z&aBP;R|8o>%6b@e||lkbMUB{uSVpnddN*-#s3Z;j@&oqbUB;8~rycbGOGN zQ~zoFS%1q)bH5KtTz*0+(Qp*v1~P}p@}$4Wi*+G2?IQx`4xL?B5Igz*;=y@n|9g;J z=u$#ZzfTHmYpBpGf%)%=C@`D)k;b?Nl`bjYirOYVG(#~Sg{t%D>#htu^GgQLRzJWq ziqU8zH-Ia?)ZmD-IF~mn%-OoVL8Av^oM>u3j_eWURCX`txvnp9tr(@!QFl>SIGxrA z-rQhBB+wIYD{|om9+o6=MG|qlHh<+R%j9J>H4-c4Oe?##Y+*mj&C$ z0Twbs4CI__BBy(#q4~8koMtbR$lt%ngu)V%$mi~RqL(m|Z_bg7gykr;@+9qhR*qr; zlGwHM2A)f|;4`aB@Rq4FjxJUcR+^-F-~HQ5*i=s z;5jKy)W=+aLD$9-9w3J$Z@rkCq5QKv_9I#2%|biWo;SAxt`w+0nBFVs4KC ze?vuxo2~^P_K$(EYDp06drF?ZA0-Nh#ONPeYluysjUp>_z$Nqw_VeD3u^l2@n!#rJ zFwcO~cix2dzWUs_3+WhgO@&+Qa|&04enQuK{N3+dEcW_b!4$qT^>w5I_q|$78%Hjq z$9XNNJLQk+$0>wViSqM#J_{2uRJvkuA7nb|5htq;u+~RFByNbYs=rm?_=W$#(*F^; z)$0s`l{v)ew;BmhdrsP)o}e+x(;#-T6`HP{2MSLf@Xpg7@>)}tTWqOHD~(LK(V>27 z+HT3&ZBoRbs2SX<01*t8QsR{GHg(wZ5-V@?3PcYFV9ex1fx{t|4xG6qFieag)@M_x z!z?qXUR^?SJ<8lye(LFHXHE;M`wUsf1%fqp#a=aD^kx#TOX4w=hc zGj4=(XHzaHvG=FQD6}`foD8?Asw^&PVIAwM#&pXX(v0w+7SYpCw%$T_+Nlgcz{|kIeln=YIzSjrI@lInl=Fcf2^YH}) z*2{qUd};U*z6Rt?zEOdBJS3Wx;xgxAK7%06J@G37!BRsm>>JOHVW)G>?qA^LbZzb* zGlt!5qQVvJYKO(Mgt%i*PeA#o0DtmKzvPuF7@br?3aXOGq7#KgL-aNr_<5d~yc^Hv ztvFtKB%ZMT3bU!LkuB?%m?E$|V9Yj$=@LIDH9qrvm&gZ8vaf@h$&#COP@d6AW~wZK zRhQL4Z0$4V@dX{2m3fBJS^J=9=QNb8I0ZER02Xv!1nHU_Y!ojC{iRQ_(61NT4!^}~ zg3s{IF(03FH^ayOt#oxtkMDf5SG4|I!9ek}J%(j?`@+FyO`1QaH8{;p*L1K??hfl$_UH!CHcP|)^ z9ZweinFIIZRG@VEM`GUN37Zwo$-C`o&|0;MRE@t6SIQ*7a-b6~<_f_EjTTVQNFs@E z>pq%7 zgYQIl4U;lW7Z7TCPI|OIlY@UILHf=J#?mMjJU_0dwv#g;@^T|Rc_fnWX}zU?QoVU! z!7_R_av=}HOklS1PSeG@$C-t19idIFl2KkW4@?#s!ZaHeJg?mYw_)D@p2+8s87JcM zPnun2v?eeg{6&03nn2=|49_yChKJLilJvfFaIRY%s>TI@-3$Vjv)047TYDkS z{SPTBF@lA2jxdYIz9l81$)zV!v|)J37TWx2GML}~k1mp)4kmG`w5!Jkgm)DY-MJpH zUvfD-b+H4@=m_X(umzi*%W!kV0?bGw6sz};(S5S4jJy+x9An15mh~d3=j_z=!W+1Vz;Ie%T!`HQh|G zdCLbkoghN+5RWg2rbWWBSkaRysOZ+gKga#a zN|&>=UrY>SJj%%A{jxA{ls```oCjKR|G{&+M7U|A!9q2chs zv;plINBYtCDLs8y1_DoBB;$&Xz|Dg@;D#li5t6P0n;C;JcCj*>J9`X!_&*y~JV%uG ze!8-DmZEI)z;2#R^d8Ji_pu5Gi$ErS4V!mS7oPHrf?kX3^qG4VaQEh-ZZJT}8EbqS zqe@Q7df@Csu{3`81YQ;;SSn+O59XXkuUc!GF(AM@LBYgW+|LPt0dtQpS+Jp2XvThv*58+~?(+fTS2?acc2UW9-{ z8`uZCO`&eqGWMysKU4nCgbiKyh%PXeXM2ruX~C{P5Z$7PH(Q>=x2z0QWm7;Zq6xiv zG@xbt73`|WW`cv(;`sFilt??{u=@^FwbH>HyIf2+{lXMjomtjS~j%4;QQ`oQl+I6$22AQ~dl;XTpP-g z1sAc5`ZyCV;I1_jC}zoR+et}dsUfGoZY<b4!&51)7Ni>T-zo1 zz~C;brA&|Xj1pd>d*fV4Fpw3|k!mf*xcF!Rg zk*cME21@*Uc`1hL$+1mbCtA|sP{oLQX33A0B%k43 zvJc9&8mZcgc&Oe{N~G*uKr8JOG&US3MwP=5-DFNhO=qxej|^~)g*_|N#m`3`^WMJ6 zIXE+7JllG?2_yFnL;0p*RQ9bX1*?j8Rb#%@!VMn(2 z;Q3brplJUQ@!@uGD*1%g;Z~)F$|79D+ab!P_F>k-E$E-{6umkV@ap+WR7}2w<$T_v zHmwu=oK9hi%>X*h49BbDk8pa=8T2*`K-FMh^sG8f`8f_{=A@9Ix$DT%0yUVMWCq(3 z!k}8*2s)(-A-!Cc8EonSwMpNoPPQ`Z;9!d47P{Yn}@}x(tIu^~KCU@oHa-8X*!Y!IxPQB~Ka;^KNNYBeRm>Kt$#Cu&vE=mtdN)7Rj zuo<{5ILi!cPKNrqf5~0YgB@cNz$N1w(SG&<_8(e8mg&8LV12Z(zjO)Gu69vxxxb`W zCZU4*o_$KYyW7ai>TiOE1V>2L zZ!s^p%saWCg)?_@PlB?W9hvgr0Bp*SC&ALQz*cpFg<>^FJfm(2(j$H{PvCR5 z#^W;6P$7a6iQCC~z2&G@YEAa@Q6`bvd>W}J!L9hV6sM0<;Kqo%VA~2|PI;3SCLDT= zr{&D}9!N2c^jyR}zfYp9Q#aaacw)7n8NrnINNwWpuv&36r!^llcb+38`3yE!t%A)N zI=JjaGQZa`qmOR$=hl``i>p`4;Nu<#a*f15V~!r27vz&6E&)Vv%Cfu9~=Gd&L{xk~)Lh38$pN|gXvQDu*c~MmPgm(z!3v3 z`9&tacL$ESX@{zVx?KIWvvlInZ%ippWMVHg;EwQNGV-Mi#XT`ItFV*1s%u#Z5@-@C++9p_4zYS+#Ih8c{D~K)B#YHNH zAb1mp>O7D5>9sG2yyskGrV7vL>w|5=YMgJCEc@F^liQc9#>(4F;10g}33CeHAXw#q zqD?9$nj8R~r+PRw+YF4Z*ptc?iKWr4vG7A?9hTmE$8-FzU>)z&N&QiU*Qfl0Pd!bz z|M~;C?fwQYzvOxP1MO%tKLdvM7okRcGz`v2#B66-_^aZD^QwdB`9B|NUC(hGmz8e8 zETCAMB?Y=(6vvr{@L8$HX#VaYtX=RQ8f!FwL%|dDHfjdh(`oqa$X7Taq=O+D;_T3l z^GxRE$58xdCj`9N3bz}}V9t|R;&iqK{)9cD`>R@EM{EENl=s8_mOFTL$zLe(8%0&y z=g?Cw!5te4hZQIOpy_K7!1gD2^`kAHJ2{61_mAP=TL%4)bm61+PlD=y5}dUBWpeYW zD)->RR#-D2$B9^$L+W`E&PU-V)Lm-jXQHZXOJgD`&6~v1;CYzfEyq@_XrLZh-+DES4PghsUS7a8|`k zICM^$^SRSY;$&4g`#Xl@otivnb@&PO{UFS3r-0XK8O91GlxukFq3W1 zJx_jo;e9x6Z-}Lq05*;|!4*RXa2yDQ;0(o*fWc!tBY7>JKOX_9uX?aQDFCw5mADGg zrSQU2g*nJlNG7$bo(qH` z3`$nSnS<)lOuBmR9dOWUprw3oGtRM?4vbM|`+5dw+Nud`q8k5h=RI?2Q`gYwy<^z3 zbFVRxS9$lA`zEr7pQ%-FF~oL_KRM{mkl#yx)8QYN38_g&^fiF@!jCX+-3ka_`Wdfk zZwD8lA=H`g3d(iw@z;#Ca8&ILzCYpyQy1OB69q?LdAC0{8+n5qEuk%46X9i9IdQ^C zWYE|ZWY^}>BTI6?sahP-p&M)iWO2Hu1gpGK4JW;oWn)BUW8ZQiHq~_=8k{JAsMB7! z^YeHhzZonyO0sAvuczh#WATV>onWEj9-OLumP~QW#$UcBpvopn7Qo4wQ*e39qsY_7y z5^T12q#uIgV9%D{biDR)m==cIj?uUZXFx+)r1JW+UV7vG( zaKy%-&_EnX`XIjc zHXXY3h8+7d9XEw;B!3S1p_;xKk&e5FO7clecTX`^IzAFu{wu$RTMW=~R9CGm>S_J4SkIN$=26G_xBeb*Xu{ zI(rQK(<#EW$*SNxCl0l@EamUk8kq0Iv+1O>DbE7~+aG)BVRQt`?lbg|NGmDivv(G1 zVT9vnjtlNuknzfV{^;gXVj_GN*6WTk7eADN_IpXDLGwAt|7B_7s(avhX%!uP7z#ES zkpj1s2H?0|o4EeDMb;nAB&{361h1TLk=E}GG|*EL{$`HSmXU*C)742Gv@e0xsV!7V z;sVSta;Lw~><8mT@sv44;O|f|m8HET@(!h~m-i6OF>W++PBEjje+3ggEK9Y8=9aD* z2%#|+*DPG`l+Z<{kIDVg*VJ;`Zivf&N^ST%*oWW6^w{qW@MFmis(N5OcxH%O_~@*M zANo!t;n*e+eQ}OBxEnxM@Geq$OAhi5t|ISNYe3Ak8{}!DBHXr?h4S>V@bA0`WL23%eGs(>YupZjA1%p} zN!AcBr;5}?i~)7=H^kxPPm=tthzM6U5h>UGq&@W!X*;~1tX~~R=5LK4xfy$yf{-+F z)kTq3E@>yf=mu&uWCALy!)R#VN{BuCib@Ok*?H<88Z&YP`~t2~9qV8y(%Q=GZ;b~z zvYXTe6u^IZ@24mB9 zfxXLLaw}^i$bM)h|ELeF;_sRzpWPt+$A0KglY-N8g28`f3Q1RvfXj-qL~Y+`a64>6 z26C?fN}gd3Pow_npg6~Qn|(*pxGCPCjVZ``ew z0X`B^__Qk#g!G3jvPOL2=|_I9n_&yC58dF`Ep3P#I0>6U3N+?s!_JCf65~+{f-)<} zzIX)!_&imTAQz@@IRz8R5!fNJ3l?|{l7dagq5Qoj{Zf(){x?)GP9Yt{B@A(1P!der z%)5#|N5Izw8W`!F1kH1op!dT9a9h0;^?BamlvzXc&hKsTZt4MMRkjSY%1S}PtX$ zft(6X!8(f+e(xM0a#-+m+)p6vpooTGT`mmfS`_KQBY z_lD}p>zG3g>tM%!tI6b>fe`GyktpjP1-T!5N4C%vymHsUlH^(7aJrOtwsn#u_hwKd z_n5q(3OF+JB$YaF8vK1tF_7<3snv$#;LjQ+(INs@IW$qd^J1u~#WVdrPM{&vyir}F zRN#3coWCSAv>X z5r%)Y1gEAP^mh@4RuYW`KWa#Kq)7Y-m)DWCg)*-UNRUx$Vcy}L^v0C1uMR1LfY%YSo0?juv`u;pJzefy+W!loC79W zI|PB@2n`cC64##$CVh5LS1=y%b-sbae>pF1q zo>UUqT!DX7_rf`r-(`&42E)vSI2bkx9~b?i%`OtG_O*o4&oLh%XxRqx$@n^$C43|O zGgF}8kTtAaa}e6M9{|C)KJu;P04!TtLZ76C0=a$^MXbCbFQN?d4TT_B=`9Z2brDEN zNpT*nJ+$zR4rfzjgT0I%$JFuON)b`+M;hM&+k6wZUActozsyB;u>dP~d(-KcAK;98 zHKf`;5si#5!BD0sp13W<=J`ttq6~Nk*nV@ecg7gDd2axbD1HZ4GseJ)&n3`TJrS%E z!=UAmA*78=gDKneAad>!a^;0Q9PH?zUmlDBhsr=)J8e98WtL&m@CZo~>c&WsQl?Iu z=M_B8rs8}i$J%cK4pqx>E;jyHUM|c@?74{+E1Gf0z7nP3I4UO;qe+@NV||#Pl@8B< zUz;NEYn2;#+_J*z{>|_={UL4G9|OLB-D%OQ6j*jiQD9)72CsWg5+B1;pi$=lp8We~ z;5mPX!EY7;8g-H2HMn^3|&2bDbeJKw}qWIDRA@Y^k1BK-;NO>d(De8ocNXbcfFV(SuRlu(Vp zV8diVmRApbdNz^?wryte3~rTPJzx)&!9pdcCl&M0yfftE&3B-~GxF5~__@>pEz-QH z61t2EN;!W2Hf2^64S1Lj0_BCc)iVx`@tLaid!|8&7Kam}VhCrRkG{#iboujZ=*92* zL^FFZC@cvBcm726WBGW$y9v+t-NtIa0@NJ;1UCnjpjTxkzP*-?t1fNDTc5me)L020 zc1=L7@wtMP&S})YcLEeu2MYq9p96ujFp*nV2l6*~d7FJBs0m+$&m!lC#&~(6?l~dvP^hOP!4)Z-VgZlPH=oCk6HP)d*J5DEtupnK`t} z7On0)C#we}aP?wSh?dQ#WoqUSFlIG9^kg<%k*X0i5Au8eC^hCV*aPWBLa8cy1L2&mSfXqmP>{>zR9HEp)!X zm*&ZZ3UVh9wDtH{>M;_Am7O{?p(z_f!tc=)F|oMhz99zk&iK4b-nhd(9ZiZoQDrb0 zU#*M8ZNfp=zvwnbku7LKn=!?~5cTSAWA}Xr8n}`Ff1RYH<5L(KJ)8^Dd$*&q+l1bggCas^c|?OKhZ5X2-(W$U&-qLm%c_kHMjBmCS3?@krF}(2!hN zoRKVpt`lC;lXVK{F-@Fi-W{Q~*FsCVJt}BDR+)-d$)m*AO8!i(jBRn}=PilnoFVz6LwX}ZosT=C=?NldB7 zy*-LhStP)N%y^iue+i%Y>w@<-KHKNE2Nr9mVzOH-oJfr0&oD9I^Tz}2*DV3pJ71_` z!b$QvV=hgvcu{H{X+j1ZPca*E6d-u0$)bt)fzO~i9XEUkwBLr(drB&h>M=lVLyj?p z3#VajOevL?>)N)gu@4c0l0gb40;^Ipn<;0o~uV{Mo3HY^g{jUV~$a=KW_xh|i@aU2!2r z>}G-82-1tvCKf*|SK#LbzRYM`G)9izF8%Ix5k+^V(*(0T%xjv8b9e?~ZT(DqT5u9& zc+u2i5{L?`e+q_eqS5{gVayG~(SOD%M(MmRMr3?oqFxx$x%p?wK=}fqAW=@t`_GYv z!@G#+y>!wcp-omF6oQofTN$;D!tnd+Ie~Aj2BUCezF^L?WNO>MnU5>~OgA*;kbEC0 zJTE*I(pL^q%lt`De*YD9lb-+;ZP)3lqAue9D}mzN7ACJMP|)KaPPfJ16?lYxqoJDi z)K+2&PE&2Bn(^vrylX1%FR!8%)~2{!S%TWhYoq6tc0o&<4%X(6q2lQiF-Jp%Sbu1w zv2G8@441F8=xiNnJ~JJ+9a4tJZzkfY`NyHFX&rqsKNO_07m(Rf4zO!@6WQ|91bnJ5 zkTVn2V6{aSIbZ#l)Xyv;Zhd2z)DBb9IqMXywE1iCYpe|KrF10kyKJ%K{$29Cc>}*E zNhcvg!8k@yK`^K446-H>w0nFwx*8|Y>9T9Ea_v3FeAE?lhMI_&>THRJIIRb)=NWFFi(<-q6FW zC}-jo8iXP4;dIZtcpUUl#H0Ba(MkC)P15Bvu9k_kr=$#}Xc9d#sRY}m<l>AO>nH zvPePL8Q4=Z4U*Qag)e3?U{HI9NV%m#(CW2xVyqvOZ#BZ78|H%d)Oh?OX%7Q8pWDp|@~YIfX54l*iue9vt3 zc0Nbe*!i*%S`%Y|;6xDIE{mV#?>D5!nc5S*?WAms(>{O5B~AQrR>4|$)Vg3N39bK^-` ztMwV3KCYp?DQa9xoCKY}oX>BV$1tt$l(@xm-OTszqv*YE7SXon&lEJ2+}=C^XK??B ze_I0c^``^a&Kv_7rdwgTPZZ=`2!LgaUqH2DFm&pF2W_!H_;|P(Tu�#h+5R6IBA` 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

    public abstract bool CursorInPlacementArea { get; } - /// - /// Creates a for a specific . - /// - /// The to create the overlay for. - public virtual SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) => null; - - /// - /// Creates a which outlines s and handles movement of selections. - /// - public virtual SelectionHandler CreateSelectionHandler() => new SelectionHandler(); - /// /// Creates the applicable for a selection. /// diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index cafaddc39e..39ec42ba96 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -22,7 +22,11 @@ using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components { - public class BlueprintContainer : CompositeDrawable, IKeyBindingHandler + /// + /// A container which provides a "blueprint" display of hitobjects. + /// Includes selection and manipulation support via a . + /// + public abstract class BlueprintContainer : CompositeDrawable, IKeyBindingHandler { public event Action> SelectionChanged; @@ -42,15 +46,26 @@ namespace osu.Game.Screens.Edit.Compose.Components [Resolved] private EditorBeatmap beatmap { get; set; } - public BlueprintContainer() + protected BlueprintContainer() { RelativeSizeAxes = Axes.Both; } + /// + /// Creates a which outlines s and handles movement of selections. + /// + public virtual SelectionHandler CreateSelectionHandler() => new SelectionHandler(); + + /// + /// Creates a for a specific . + /// + /// The to create the overlay for. + public virtual SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) => null; + [BackgroundDependencyLoader] private void load() { - selectionHandler = composer.CreateSelectionHandler(); + selectionHandler = CreateSelectionHandler(); selectionHandler.DeselectAll = deselectAll; InternalChildren = new[] @@ -259,7 +274,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { refreshTool(); - var blueprint = composer.CreateBlueprintFor(hitObject); + var blueprint = CreateBlueprintFor(hitObject); if (blueprint == null) return; diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs new file mode 100644 index 0000000000..9267006e4c --- /dev/null +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Screens.Edit.Compose.Components +{ + /// + /// A blueprint container generally displayed as an overlay to a ruleset's playfield. + /// + public class ComposeBlueprintContainer : BlueprintContainer + { + } +} From d8d12cbbddfe864f96467e22a8b672f8ef4d22c6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 2 Jan 2020 19:09:37 +0900 Subject: [PATCH 4868/5608] wip: Move more functionality into ComposeBlueprintContainer --- .../Timelines/Summary/Parts/TimelinePart.cs | 4 ++-- .../Edit/Compose/Components/BlueprintContainer.cs | 5 +---- .../Components/Timeline/TimelineHitObjectDisplay.cs | 12 ++++++++---- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs index 7706e33179..119635ccd5 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// /// Represents a part of the summary timeline.. /// - public abstract class TimelinePart : Container + public class TimelinePart : Container { protected readonly IBindable Beatmap = new Bindable(); @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts protected override Container Content => timeline; - protected TimelinePart() + public TimelinePart() { AddInternal(timeline = new Container { RelativeSizeAxes = Axes.Both }); diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 39ec42ba96..a8fb87c1b0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -40,9 +40,6 @@ namespace osu.Game.Screens.Edit.Compose.Components [Resolved] private IAdjustableClock adjustableClock { get; set; } - [Resolved] - private HitObjectComposer composer { get; set; } - [Resolved] private EditorBeatmap beatmap { get; set; } @@ -77,7 +74,7 @@ namespace osu.Game.Screens.Edit.Compose.Components dragBox.CreateProxy() }; - foreach (var obj in composer.HitObjects) + foreach (var obj in beatmap.HitObjects) addBlueprintFor(obj); } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs index b20f2fa11d..12909f257d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectDisplay.cs @@ -14,15 +14,19 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - internal class TimelineHitObjectDisplay : TimelinePart + internal class TimelineHitObjectDisplay : BlueprintContainer { private EditorBeatmap beatmap { get; } + private readonly TimelinePart content; + public TimelineHitObjectDisplay(EditorBeatmap beatmap) { RelativeSizeAxes = Axes.Both; this.beatmap = beatmap; + + AddInternal(content = new TimelinePart()); } [BackgroundDependencyLoader] @@ -42,15 +46,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void remove(HitObject h) { - foreach (var d in Children.OfType().Where(c => c.HitObject == h)) + foreach (var d in content.OfType().Where(c => c.HitObject == h)) d.Expire(); } private void add(HitObject h) { - var yOffset = Children.Count(d => d.X == h.StartTime); + var yOffset = content.Count(d => d.X == h.StartTime); - Add(new TimelineHitObjectRepresentation(h) { Y = -yOffset * TimelineHitObjectRepresentation.THICKNESS }); + content.Add(new TimelineHitObjectRepresentation(h) { Y = -yOffset * TimelineHitObjectRepresentation.THICKNESS }); } private class TimelineHitObjectRepresentation : CompositeDrawable From 904b068a15c5bb55629d70c8bb5ca035a1d65649 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 2 Jan 2020 13:18:18 +0300 Subject: [PATCH 4869/5608] Simplify colour setting for additional elements in OverlayRulesetTabItem --- osu.Game/Overlays/OverlayRulesetTabItem.cs | 23 +++++++++++-------- .../Components/ProfileRulesetTabItem.cs | 13 +---------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/osu.Game/Overlays/OverlayRulesetTabItem.cs b/osu.Game/Overlays/OverlayRulesetTabItem.cs index 9d6d28a81f..e1cc1de8de 100644 --- a/osu.Game/Overlays/OverlayRulesetTabItem.cs +++ b/osu.Game/Overlays/OverlayRulesetTabItem.cs @@ -11,6 +11,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK.Graphics; using osuTK; +using System; namespace osu.Game.Overlays { @@ -33,10 +34,12 @@ namespace osu.Game.Overlays accentColour = value; - UpdateState(); + updateState(); } } + protected Action OnStateUpdated; + protected override Container Content => content; public OverlayRulesetTabItem(RulesetInfo value) @@ -67,32 +70,32 @@ namespace osu.Game.Overlays protected override void LoadComplete() { base.LoadComplete(); - Enabled.BindValueChanged(_ => UpdateState(), true); + Enabled.BindValueChanged(_ => updateState(), true); } protected override bool OnHover(HoverEvent e) { base.OnHover(e); - UpdateState(); + updateState(); return true; } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - UpdateState(); + updateState(); } - protected override void OnActivated() => UpdateState(); + protected override void OnActivated() => updateState(); - protected override void OnDeactivated() => UpdateState(); + protected override void OnDeactivated() => updateState(); - protected virtual void UpdateState() + private void updateState() { + var updatedColour = IsHovered || Active.Value ? Color4.White : Enabled.Value ? AccentColour : Color4.DimGray; Text.Font = Text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Medium); - Text.FadeColour(GetColour(), 120, Easing.OutQuint); + Text.FadeColour(updatedColour, 120, Easing.OutQuint); + OnStateUpdated?.Invoke(updatedColour); } - - protected Color4 GetColour() => IsHovered || Active.Value ? Color4.White : Enabled.Value ? AccentColour : Color4.DimGray; } } diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs index adf324b259..d416e98b31 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets; using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { @@ -13,12 +12,6 @@ namespace osu.Game.Overlays.Profile.Header.Components { private readonly SpriteIcon icon; - public new Color4 AccentColour - { - get => base.AccentColour; - set => base.AccentColour = icon.Colour = value; - } - private bool isDefault; public bool IsDefault @@ -47,12 +40,8 @@ namespace osu.Game.Overlays.Profile.Header.Components Icon = FontAwesome.Solid.Star, Size = new Vector2(12), }); - } - protected override void UpdateState() - { - base.UpdateState(); - icon.FadeColour(GetColour(), 120, Easing.OutQuint); + OnStateUpdated += colour => icon.FadeColour(colour, 120, Easing.OutQuint); } } } From 132b420aaa565fefa69b73b132f97968ed61309a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 2 Jan 2020 19:19:00 +0900 Subject: [PATCH 4870/5608] Fix changelog overlay hard crashing on no internet connection --- osu.Game/Overlays/ChangelogOverlay.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index fbc9dfcbd9..e7986e701c 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -158,7 +158,8 @@ namespace osu.Game.Overlays private Task initialFetchTask; - private void performAfterFetch(Action action) => fetchListing()?.ContinueWith(_ => Schedule(action)); + private void performAfterFetch(Action action) => fetchListing()?.ContinueWith(_ => + Schedule(action), TaskContinuationOptions.OnlyOnRanToCompletion); private Task fetchListing() { From 7b71e568177f1d827316dd3930ac64fd2921f5c0 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Thu, 2 Jan 2020 17:07:28 +0100 Subject: [PATCH 4871/5608] Initial commit --- .../API/Requests/MarkChannelAsReadRequest.cs | 21 +++++++++++++++++++ osu.Game/Online/Chat/Channel.cs | 8 +++++++ osu.Game/Online/Chat/ChannelManager.cs | 8 +++++++ 3 files changed, 37 insertions(+) create mode 100644 osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs diff --git a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs new file mode 100644 index 0000000000..3f28037816 --- /dev/null +++ b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Online.Chat; + +namespace osu.Game.Online.API.Requests +{ + public class MarkChannelAsReadRequest : APIRequest + { + private readonly Channel channel; + private readonly Message message; + + public MarkChannelAsReadRequest(Channel channel, Message message) + { + this.channel = channel; + this.message = message; + } + + protected override string Target => @"/chat/channels/{channel}/mark-as-read/{message}"; + } +} diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 451174a73c..6f67a95f53 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -36,6 +36,11 @@ namespace osu.Game.Online.Chat /// public readonly SortedList Messages = new SortedList(Comparer.Default); + /// + /// Contains all the messages that weren't read by the user. + /// + public IEnumerable UnreadMessages => Messages.Where(m => LastReadId < m.Id); + /// /// Contains all the messages that are still pending for submission to the server. /// @@ -75,6 +80,9 @@ namespace osu.Game.Online.Chat [JsonProperty(@"last_message_id")] public long? LastMessageId; + [JsonProperty(@"last_read_id")] + public long? LastReadId; + /// /// Signalles if the current user joined this channel or not. Defaults to false. /// diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 1d8c5609d9..e92a4853ff 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -445,6 +445,14 @@ namespace osu.Game.Online.Chat return tcs.Task; } + public void MarkChannelAsRead(Message message) + { + var channel = JoinedChannels.First(c => c.Id == message.ChannelId); + var req = new MarkChannelAsReadRequest(channel, message); + req.Success += () => channel.LastReadId = message.Id; + api.Queue(req); + } + [BackgroundDependencyLoader] private void load(IAPIProvider api) { From 51556a809d578f159387664cf23ce26a856643b1 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Thu, 2 Jan 2020 17:20:33 +0100 Subject: [PATCH 4872/5608] Fix variables not being used inside target string --- osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs index 3f28037816..76c925588b 100644 --- a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs +++ b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs @@ -16,6 +16,6 @@ namespace osu.Game.Online.API.Requests this.message = message; } - protected override string Target => @"/chat/channels/{channel}/mark-as-read/{message}"; + protected override string Target => $"/chat/channels/{channel}/mark-as-read/{message}"; } } From b54491cc82d50fe3c1c8f892527c5d911c7af795 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Jan 2020 14:16:33 +0900 Subject: [PATCH 4873/5608] Make sure an exception is thrown --- osu.Game/Overlays/ChangelogOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index e7986e701c..15b0079277 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -186,10 +186,10 @@ namespace osu.Game.Overlays tcs.SetResult(true); }); - req.Failure += _ => + req.Failure += e => { initialFetchTask = null; - tcs.SetResult(false); + tcs.SetException(e); }; await API.PerformAsync(req); From e8567414c6d253f94fb36e2b06fb2f8b80ab9c75 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 3 Jan 2020 15:01:42 +0900 Subject: [PATCH 4874/5608] Refactor into some kind of sanity --- .../Online/TestSceneUserProfileHeader.cs | 2 +- .../BreadcrumbControlOverlayHeader.cs | 29 ++++++++++- .../Overlays/Changelog/ChangelogHeader.cs | 14 +++--- osu.Game/Overlays/News/NewsHeader.cs | 14 +++--- osu.Game/Overlays/OverlayHeader.cs | 4 +- .../OverlayHeaderBreadcrumbControl.cs | 32 ------------- osu.Game/Overlays/OverlayHeaderTabControl.cs | 48 ------------------- osu.Game/Overlays/TabControlOverlayHeader.cs | 43 ++++++++++++++++- 8 files changed, 86 insertions(+), 100 deletions(-) delete mode 100644 osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs delete mode 100644 osu.Game/Overlays/OverlayHeaderTabControl.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index 63b8acb234..63b46c991f 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Online typeof(ProfileHeader), typeof(RankGraph), typeof(LineGraph), - typeof(OverlayHeaderTabControl), + typeof(TabControlOverlayHeader.OverlayHeaderTabControl), typeof(CentreHeaderContainer), typeof(BottomHeaderContainer), typeof(DetailHeaderContainer), diff --git a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs index 6f9445bd47..8a82b1f0c0 100644 --- a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs +++ b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs @@ -1,14 +1,39 @@ // 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.UserInterface; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays { public abstract class BreadcrumbControlOverlayHeader : OverlayHeader { - protected OverlayHeaderBreadcrumbControl TabControl; + protected OverlayHeaderBreadcrumbControl BreadcrumbControl; - protected override TabControl CreateControl() => TabControl = new OverlayHeaderBreadcrumbControl(); + protected override TabControl CreateTabControl() => BreadcrumbControl = new OverlayHeaderBreadcrumbControl(); + + public class OverlayHeaderBreadcrumbControl : BreadcrumbControl + { + public OverlayHeaderBreadcrumbControl() + { + RelativeSizeAxes = Axes.X; + } + + protected override TabItem CreateTabItem(string value) => new ControlTabItem(value); + + private class ControlTabItem : BreadcrumbTabItem + { + protected override float ChevronSize => 8; + + public ControlTabItem(string value) + : base(value) + { + Text.Font = Text.Font.With(size: 14); + Chevron.Y = 3; + Bar.Height = 0; + } + } + } } } diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index ddf07e4b50..7e47a3e29f 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -27,8 +27,8 @@ namespace osu.Game.Overlays.Changelog public ChangelogHeader() { - TabControl.AddItem(listing_string); - TabControl.Current.ValueChanged += e => + BreadcrumbControl.AddItem(listing_string); + BreadcrumbControl.Current.ValueChanged += e => { if (e.NewValue == listing_string) ListingSelected?.Invoke(); @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Changelog [BackgroundDependencyLoader] private void load(OsuColour colours) { - TabControl.AccentColour = colours.Violet; + BreadcrumbControl.AccentColour = colours.Violet; TitleBackgroundColour = colours.GreyVioletDarker; ControlBackgroundColour = colours.GreyVioletDark; } @@ -56,12 +56,12 @@ namespace osu.Game.Overlays.Changelog private void showBuild(ValueChangedEvent e) { if (e.OldValue != null) - TabControl.RemoveItem(e.OldValue.ToString()); + BreadcrumbControl.RemoveItem(e.OldValue.ToString()); if (e.NewValue != null) { - TabControl.AddItem(e.NewValue.ToString()); - TabControl.Current.Value = e.NewValue.ToString(); + BreadcrumbControl.AddItem(e.NewValue.ToString()); + BreadcrumbControl.Current.Value = e.NewValue.ToString(); Streams.Current.Value = Streams.Items.FirstOrDefault(s => s.Name == e.NewValue.UpdateStream.Name); @@ -69,7 +69,7 @@ namespace osu.Game.Overlays.Changelog } else { - TabControl.Current.Value = listing_string; + BreadcrumbControl.Current.Value = listing_string; Streams.Current.Value = null; title.Version = null; } diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 2cbe2fa04e..fc88c86df2 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -24,9 +24,9 @@ namespace osu.Game.Overlays.News public NewsHeader() { - TabControl.AddItem(front_page_string); + BreadcrumbControl.AddItem(front_page_string); - TabControl.Current.ValueChanged += e => + BreadcrumbControl.Current.ValueChanged += e => { if (e.NewValue == front_page_string) ShowFrontPage?.Invoke(); @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.News [BackgroundDependencyLoader] private void load(OsuColour colours) { - TabControl.AccentColour = colours.Violet; + BreadcrumbControl.AccentColour = colours.Violet; TitleBackgroundColour = colours.GreyVioletDarker; ControlBackgroundColour = colours.GreyVioletDark; } @@ -46,18 +46,18 @@ namespace osu.Game.Overlays.News private void showPost(ValueChangedEvent e) { if (e.OldValue != null) - TabControl.RemoveItem(e.OldValue); + BreadcrumbControl.RemoveItem(e.OldValue); if (e.NewValue != null) { - TabControl.AddItem(e.NewValue); - TabControl.Current.Value = e.NewValue; + BreadcrumbControl.AddItem(e.NewValue); + BreadcrumbControl.Current.Value = e.NewValue; title.IsReadingPost = true; } else { - TabControl.Current.Value = front_page_string; + BreadcrumbControl.Current.Value = front_page_string; title.IsReadingPost = false; } } diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index 7575801aac..53da2da634 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -84,7 +84,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Colour = Color4.Gray, }, - CreateControl().With(control => control.Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }) + CreateTabControl().With(control => control.Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }) } }, CreateContent() @@ -99,6 +99,6 @@ namespace osu.Game.Overlays protected abstract ScreenTitle CreateTitle(); - protected abstract TabControl CreateControl(); + protected abstract TabControl CreateTabControl(); } } diff --git a/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs b/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs deleted file mode 100644 index 047ca5eba2..0000000000 --- a/osu.Game/Overlays/OverlayHeaderBreadcrumbControl.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Graphics.UserInterface; -using osu.Framework.Graphics; -using osu.Framework.Graphics.UserInterface; - -namespace osu.Game.Overlays -{ - public class OverlayHeaderBreadcrumbControl : BreadcrumbControl - { - public OverlayHeaderBreadcrumbControl() - { - RelativeSizeAxes = Axes.X; - } - - protected override TabItem CreateTabItem(string value) => new ControlTabItem(value); - - private class ControlTabItem : BreadcrumbTabItem - { - protected override float ChevronSize => 8; - - public ControlTabItem(string value) - : base(value) - { - Text.Font = Text.Font.With(size: 14); - Chevron.Y = 3; - Bar.Height = 0; - } - } - } -} diff --git a/osu.Game/Overlays/OverlayHeaderTabControl.cs b/osu.Game/Overlays/OverlayHeaderTabControl.cs deleted file mode 100644 index 7e11e066c7..0000000000 --- a/osu.Game/Overlays/OverlayHeaderTabControl.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osuTK; -using osu.Game.Graphics; - -namespace osu.Game.Overlays -{ - public class OverlayHeaderTabControl : OverlayTabControl - { - public OverlayHeaderTabControl() - { - BarHeight = 1; - RelativeSizeAxes = Axes.None; - AutoSizeAxes = Axes.X; - Anchor = Anchor.BottomLeft; - Origin = Anchor.BottomLeft; - Height = 35; - } - - protected override TabItem CreateTabItem(string value) => new OverlayHeaderTabItem(value) - { - AccentColour = AccentColour, - }; - - protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer - { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5, 0), - }; - - private class OverlayHeaderTabItem : OverlayTabItem - { - public OverlayHeaderTabItem(string value) - : base(value) - { - Text.Text = value; - Text.Font = OsuFont.GetFont(size: 14); - Bar.ExpandedSize = 5; - } - } - } -} diff --git a/osu.Game/Overlays/TabControlOverlayHeader.cs b/osu.Game/Overlays/TabControlOverlayHeader.cs index f8683b3e7d..f3521b66c8 100644 --- a/osu.Game/Overlays/TabControlOverlayHeader.cs +++ b/osu.Game/Overlays/TabControlOverlayHeader.cs @@ -1,7 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using osuTK; namespace osu.Game.Overlays { @@ -9,6 +13,43 @@ namespace osu.Game.Overlays { protected OverlayHeaderTabControl TabControl; - protected override TabControl CreateControl() => TabControl = new OverlayHeaderTabControl(); + protected override TabControl CreateTabControl() => TabControl = new OverlayHeaderTabControl(); + + public class OverlayHeaderTabControl : OverlayTabControl + { + public OverlayHeaderTabControl() + { + BarHeight = 1; + RelativeSizeAxes = Axes.None; + AutoSizeAxes = Axes.X; + Anchor = Anchor.BottomLeft; + Origin = Anchor.BottomLeft; + Height = 35; + } + + protected override TabItem CreateTabItem(string value) => new OverlayHeaderTabItem(value) + { + AccentColour = AccentColour, + }; + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + }; + + private class OverlayHeaderTabItem : OverlayTabItem + { + public OverlayHeaderTabItem(string value) + : base(value) + { + Text.Text = value; + Text.Font = OsuFont.GetFont(size: 14); + Bar.ExpandedSize = 5; + } + } + } } } From fe581bf27ef852055e16894d45bcaed55b0f2ffb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 3 Jan 2020 15:35:18 +0900 Subject: [PATCH 4875/5608] Remove unnecessarily exposed value --- osu.Game/Graphics/UserInterface/OsuTabControl.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index a6ee666e1d..ed8904db7e 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -30,8 +30,6 @@ namespace osu.Game.Graphics.UserInterface protected virtual float StripWidth => TabContainer.Children.Sum(c => c.IsPresent ? c.DrawWidth + TabContainer.Spacing.X : 0) - TabContainer.Spacing.X; - protected virtual float StripHeight => 1; - /// /// Whether entries should be automatically populated if is an type. /// @@ -47,7 +45,7 @@ namespace osu.Game.Graphics.UserInterface { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Height = StripHeight, + Height = 1, Colour = Color4.White.Opacity(0), }); From 97b4c655541a87b592afd348ebc58625debb15d6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Jan 2020 16:24:29 +0900 Subject: [PATCH 4876/5608] Fix taiko replay frames being mis-ordered --- .../Replays/TaikoAutoGenerator.cs | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 4b234b56d4..7654cad6b4 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -121,9 +121,7 @@ namespace osu.Game.Rulesets.Taiko.Replays var nextHitObject = GetNextObject(i); // Get the next object that requires pressing the same button bool canDelayKeyUp = nextHitObject == null || nextHitObject.StartTime > endTime + KEY_UP_DELAY; - double calculatedDelay = canDelayKeyUp ? KEY_UP_DELAY : (nextHitObject.StartTime - endTime) * 0.9; - Frames.Add(new TaikoReplayFrame(endTime + calculatedDelay)); if (i < Beatmap.HitObjects.Count - 1) @@ -138,24 +136,5 @@ namespace osu.Game.Rulesets.Taiko.Replays return Replay; } - - protected override HitObject GetNextObject(int currentIndex) - { - Type desiredType = Beatmap.HitObjects[currentIndex].GetType(); - - for (int i = currentIndex + 1; i < Beatmap.HitObjects.Count; i++) - { - var currentObj = Beatmap.HitObjects[i]; - - if (currentObj.GetType() == desiredType || - // Un-press all keys before a DrumRoll or Swell - currentObj is DrumRoll || currentObj is Swell) - { - return Beatmap.HitObjects[i]; - } - } - - return null; - } } } From 9c49da8942d52b5e78e296f2a9be61d15d352329 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Jan 2020 16:24:39 +0900 Subject: [PATCH 4877/5608] Remove unnecessary extra "wait" frame --- osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 7654cad6b4..48eb33976e 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -124,13 +124,6 @@ namespace osu.Game.Rulesets.Taiko.Replays double calculatedDelay = canDelayKeyUp ? KEY_UP_DELAY : (nextHitObject.StartTime - endTime) * 0.9; Frames.Add(new TaikoReplayFrame(endTime + calculatedDelay)); - if (i < Beatmap.HitObjects.Count - 1) - { - double waitTime = Beatmap.HitObjects[i + 1].StartTime - 1000; - if (waitTime > endTime) - Frames.Add(new TaikoReplayFrame(waitTime)); - } - hitButton = !hitButton; } From e9b57de76f245adc7a0dfc4d11384c07e9c65a6d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 3 Jan 2020 17:23:17 +0900 Subject: [PATCH 4878/5608] 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 0b41d5cda4..e1e6f2e478 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 565608b40f..b497133e62 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 60355b8592..edd35b0774 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 77fb632d443d2665ac1be4d2b7827d990f34cefe Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 3 Jan 2020 17:57:01 +0900 Subject: [PATCH 4879/5608] Remove now unnecessary using --- osu.Game.Tests/Resources/TestResources.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index 7588e27b3e..8b892fbb2f 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -4,7 +4,6 @@ using System.IO; using NUnit.Framework; using osu.Framework.IO.Stores; -using osu.Game.Resources; namespace osu.Game.Tests.Resources { From 3a903339d6e41aa5c37bed8928ce16be03e609b0 Mon Sep 17 00:00:00 2001 From: Albie Spriddell Date: Fri, 3 Jan 2020 11:39:15 +0000 Subject: [PATCH 4880/5608] add playingverb and database migrations --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 + osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 + osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 + osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 + .../20200103111200_AddPlayingVerb.Designer.cs | 508 ++++++++++++++++++ .../20200103111200_AddPlayingVerb.cs | 22 + .../Migrations/OsuDbContextModelSnapshot.cs | 2 + osu.Game/Rulesets/Ruleset.cs | 9 +- osu.Game/Rulesets/RulesetInfo.cs | 2 + osu.Game/Rulesets/RulesetStore.cs | 1 + osu.Game/Users/UserActivity.cs | 2 +- 11 files changed, 552 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Migrations/20200103111200_AddPlayingVerb.Designer.cs create mode 100644 osu.Game/Migrations/20200103111200_AddPlayingVerb.cs diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index dc8df28e6a..e5c3647f99 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -135,6 +135,8 @@ namespace osu.Game.Rulesets.Catch public override string ShortName => SHORT_NAME; + public override string PlayingVerb => "Catching fruit"; + public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetCatch }; public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(this, beatmap); diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index c50f4314a3..02c2158383 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -179,6 +179,8 @@ namespace osu.Game.Rulesets.Mania public override string ShortName => SHORT_NAME; + public override string PlayingVerb => "Smashing keys"; + public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetMania }; public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new ManiaDifficultyCalculator(this, beatmap); diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 36346eb78a..148869f5e8 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -175,6 +175,8 @@ namespace osu.Game.Rulesets.Osu public override string ShortName => SHORT_NAME; + public override string PlayingVerb => "Clicking circles"; + public override RulesetSettingsSubsection CreateSettings() => new OsuSettingsSubsection(this); public override ISkin CreateLegacySkinProvider(ISkinSource source) => new OsuLegacySkinTransformer(source); diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 536cbdc562..fc79e59864 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -139,6 +139,8 @@ namespace osu.Game.Rulesets.Taiko public override string ShortName => SHORT_NAME; + public override string PlayingVerb => "Bashing drums"; + public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetTaiko }; public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new TaikoDifficultyCalculator(this, beatmap); diff --git a/osu.Game/Migrations/20200103111200_AddPlayingVerb.Designer.cs b/osu.Game/Migrations/20200103111200_AddPlayingVerb.Designer.cs new file mode 100644 index 0000000000..eb1b004dea --- /dev/null +++ b/osu.Game/Migrations/20200103111200_AddPlayingVerb.Designer.cs @@ -0,0 +1,508 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using osu.Game.Database; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20200103111200_AddPlayingVerb")] + partial class AddPlayingVerb + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("ApproachRate"); + + b.Property("CircleSize"); + + b.Property("DrainRate"); + + b.Property("OverallDifficulty"); + + b.Property("SliderMultiplier"); + + b.Property("SliderTickRate"); + + b.HasKey("ID"); + + b.ToTable("BeatmapDifficulty"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("AudioLeadIn"); + + b.Property("BPM"); + + b.Property("BaseDifficultyID"); + + b.Property("BeatDivisor"); + + b.Property("BeatmapSetInfoID"); + + b.Property("Countdown"); + + b.Property("DistanceSpacing"); + + b.Property("GridSize"); + + b.Property("Hash"); + + b.Property("Hidden"); + + b.Property("Length"); + + b.Property("LetterboxInBreaks"); + + b.Property("MD5Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapID"); + + b.Property("Path"); + + b.Property("RulesetID"); + + b.Property("SpecialStyle"); + + b.Property("StackLeniency"); + + b.Property("StarDifficulty"); + + b.Property("Status"); + + b.Property("StoredBookmarks"); + + b.Property("TimelineZoom"); + + b.Property("Version"); + + b.Property("WidescreenStoryboard"); + + b.HasKey("ID"); + + b.HasIndex("BaseDifficultyID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("Hash"); + + b.HasIndex("MD5Hash"); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("BeatmapInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Artist"); + + b.Property("ArtistUnicode"); + + b.Property("AudioFile"); + + b.Property("AuthorString") + .HasColumnName("Author"); + + b.Property("BackgroundFile"); + + b.Property("PreviewTime"); + + b.Property("Source"); + + b.Property("Tags"); + + b.Property("Title"); + + b.Property("TitleUnicode"); + + b.Property("VideoFile"); + + b.HasKey("ID"); + + b.ToTable("BeatmapMetadata"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("BeatmapSetInfoID"); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.HasKey("ID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("FileInfoID"); + + b.ToTable("BeatmapSetFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("DateAdded"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapSetID"); + + b.Property("Protected"); + + b.Property("Status"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapSetID") + .IsUnique(); + + b.ToTable("BeatmapSetInfo"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Key") + .HasColumnName("Key"); + + b.Property("RulesetID"); + + b.Property("SkinInfoID"); + + b.Property("StringValue") + .HasColumnName("Value"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("SkinInfoID"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("osu.Game.IO.FileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Hash"); + + b.Property("ReferenceCount"); + + b.HasKey("ID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("ReferenceCount"); + + b.ToTable("FileInfo"); + }); + + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntAction") + .HasColumnName("Action"); + + b.Property("KeysString") + .HasColumnName("Keys"); + + b.Property("RulesetID"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("IntAction"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("KeyBinding"); + }); + + modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Available"); + + b.Property("InstantiationInfo"); + + b.Property("Name"); + + b.Property("ShortName"); + + b.Property("PlayingVerb"); + + b.HasKey("ID"); + + b.HasIndex("Available"); + + b.HasIndex("ShortName") + .IsUnique(); + + b.ToTable("RulesetInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("ScoreInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("ScoreInfoID"); + + b.ToTable("ScoreFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Accuracy") + .HasColumnType("DECIMAL(1,4)"); + + b.Property("BeatmapInfoID"); + + b.Property("Combo"); + + b.Property("Date"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MaxCombo"); + + b.Property("ModsJson") + .HasColumnName("Mods"); + + b.Property("OnlineScoreID"); + + b.Property("PP"); + + b.Property("Rank"); + + b.Property("RulesetID"); + + b.Property("StatisticsJson") + .HasColumnName("Statistics"); + + b.Property("TotalScore"); + + b.Property("UserID") + .HasColumnName("UserID"); + + b.Property("UserString") + .HasColumnName("User"); + + b.HasKey("ID"); + + b.HasIndex("BeatmapInfoID"); + + b.HasIndex("OnlineScoreID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("ScoreInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("SkinInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("SkinInfoID"); + + b.ToTable("SkinFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Creator"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("Name"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.ToTable("SkinInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") + .WithMany() + .HasForeignKey("BaseDifficultyID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") + .WithMany("Beatmaps") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("Beatmaps") + .HasForeignKey("MetadataID"); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") + .WithMany("Files") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("BeatmapSets") + .HasForeignKey("MetadataID"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Settings") + .HasForeignKey("SkinInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Scoring.ScoreInfo") + .WithMany("Files") + .HasForeignKey("ScoreInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap") + .WithMany("Scores") + .HasForeignKey("BeatmapInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Files") + .HasForeignKey("SkinInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/osu.Game/Migrations/20200103111200_AddPlayingVerb.cs b/osu.Game/Migrations/20200103111200_AddPlayingVerb.cs new file mode 100644 index 0000000000..1f1d89f55e --- /dev/null +++ b/osu.Game/Migrations/20200103111200_AddPlayingVerb.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace osu.Game.Migrations +{ + public partial class AddPlayingVerb : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "PlayingVerb", + table: "RulesetInfo", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "PlayingVerb", + table: "RulesetInfo"); + } + } +} diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index a6d9d1f3cb..5d64d2ac5d 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -283,6 +283,8 @@ namespace osu.Game.Migrations b.Property("ShortName"); + b.Property("PlayingVerb"); + b.HasKey("ID"); b.HasIndex("Available"); diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 693d85c574..c930b42157 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -21,6 +21,7 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Skinning; +using osu.Game.Users; namespace osu.Game.Rulesets { @@ -57,7 +58,8 @@ namespace osu.Game.Rulesets ShortName = ShortName, ID = (this as ILegacyRuleset)?.LegacyID, InstantiationInfo = GetType().AssemblyQualifiedName, - Available = true + Available = true, + PlayingVerb = PlayingVerb, }; } @@ -121,6 +123,11 @@ namespace osu.Game.Rulesets /// public abstract string ShortName { get; } + /// + /// String used for and + /// + public virtual string PlayingVerb => "Playing solo"; + /// /// A list of available variant ids. /// diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index ececc18c96..237469aff2 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -17,6 +17,8 @@ namespace osu.Game.Rulesets public string InstantiationInfo { get; set; } + public string PlayingVerb { get; set; } + [JsonIgnore] public bool Available { get; set; } diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index a389d4ff75..2b502c8edd 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -92,6 +92,7 @@ namespace osu.Game.Rulesets r.Name = instanceInfo.Name; r.ShortName = instanceInfo.ShortName; r.InstantiationInfo = instanceInfo.InstantiationInfo; + r.PlayingVerb = instanceInfo.PlayingVerb; r.Available = true; } diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 8030fc55a2..85c1b1f706 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -52,7 +52,7 @@ namespace osu.Game.Users Ruleset = ruleset; } - public override string Status => @"Playing alone"; + public override string Status => Ruleset.PlayingVerb; } public class Spectating : UserActivity From 59408515198260fd1913a86f13b1130bd413fe41 Mon Sep 17 00:00:00 2001 From: Albie Spriddell Date: Fri, 3 Jan 2020 12:17:01 +0000 Subject: [PATCH 4881/5608] remove database dependency --- .../20200103111200_AddPlayingVerb.Designer.cs | 508 ------------------ .../20200103111200_AddPlayingVerb.cs | 22 - .../Migrations/OsuDbContextModelSnapshot.cs | 2 - osu.Game/Rulesets/RulesetInfo.cs | 2 + 4 files changed, 2 insertions(+), 532 deletions(-) delete mode 100644 osu.Game/Migrations/20200103111200_AddPlayingVerb.Designer.cs delete mode 100644 osu.Game/Migrations/20200103111200_AddPlayingVerb.cs diff --git a/osu.Game/Migrations/20200103111200_AddPlayingVerb.Designer.cs b/osu.Game/Migrations/20200103111200_AddPlayingVerb.Designer.cs deleted file mode 100644 index eb1b004dea..0000000000 --- a/osu.Game/Migrations/20200103111200_AddPlayingVerb.Designer.cs +++ /dev/null @@ -1,508 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using osu.Game.Database; - -namespace osu.Game.Migrations -{ - [DbContext(typeof(OsuDbContext))] - [Migration("20200103111200_AddPlayingVerb")] - partial class AddPlayingVerb - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("ApproachRate"); - - b.Property("CircleSize"); - - b.Property("DrainRate"); - - b.Property("OverallDifficulty"); - - b.Property("SliderMultiplier"); - - b.Property("SliderTickRate"); - - b.HasKey("ID"); - - b.ToTable("BeatmapDifficulty"); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("AudioLeadIn"); - - b.Property("BPM"); - - b.Property("BaseDifficultyID"); - - b.Property("BeatDivisor"); - - b.Property("BeatmapSetInfoID"); - - b.Property("Countdown"); - - b.Property("DistanceSpacing"); - - b.Property("GridSize"); - - b.Property("Hash"); - - b.Property("Hidden"); - - b.Property("Length"); - - b.Property("LetterboxInBreaks"); - - b.Property("MD5Hash"); - - b.Property("MetadataID"); - - b.Property("OnlineBeatmapID"); - - b.Property("Path"); - - b.Property("RulesetID"); - - b.Property("SpecialStyle"); - - b.Property("StackLeniency"); - - b.Property("StarDifficulty"); - - b.Property("Status"); - - b.Property("StoredBookmarks"); - - b.Property("TimelineZoom"); - - b.Property("Version"); - - b.Property("WidescreenStoryboard"); - - b.HasKey("ID"); - - b.HasIndex("BaseDifficultyID"); - - b.HasIndex("BeatmapSetInfoID"); - - b.HasIndex("Hash"); - - b.HasIndex("MD5Hash"); - - b.HasIndex("MetadataID"); - - b.HasIndex("OnlineBeatmapID") - .IsUnique(); - - b.HasIndex("RulesetID"); - - b.ToTable("BeatmapInfo"); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("Artist"); - - b.Property("ArtistUnicode"); - - b.Property("AudioFile"); - - b.Property("AuthorString") - .HasColumnName("Author"); - - b.Property("BackgroundFile"); - - b.Property("PreviewTime"); - - b.Property("Source"); - - b.Property("Tags"); - - b.Property("Title"); - - b.Property("TitleUnicode"); - - b.Property("VideoFile"); - - b.HasKey("ID"); - - b.ToTable("BeatmapMetadata"); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("BeatmapSetInfoID"); - - b.Property("FileInfoID"); - - b.Property("Filename") - .IsRequired(); - - b.HasKey("ID"); - - b.HasIndex("BeatmapSetInfoID"); - - b.HasIndex("FileInfoID"); - - b.ToTable("BeatmapSetFileInfo"); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("DeletePending"); - - b.Property("Hash"); - - b.Property("MetadataID"); - - b.Property("OnlineBeatmapSetID"); - - b.Property("Protected"); - - b.Property("Status"); - - b.HasKey("ID"); - - b.HasIndex("DeletePending"); - - b.HasIndex("Hash") - .IsUnique(); - - b.HasIndex("MetadataID"); - - b.HasIndex("OnlineBeatmapSetID") - .IsUnique(); - - b.ToTable("BeatmapSetInfo"); - }); - - modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("Key") - .HasColumnName("Key"); - - b.Property("RulesetID"); - - b.Property("SkinInfoID"); - - b.Property("StringValue") - .HasColumnName("Value"); - - b.Property("Variant"); - - b.HasKey("ID"); - - b.HasIndex("SkinInfoID"); - - b.HasIndex("RulesetID", "Variant"); - - b.ToTable("Settings"); - }); - - modelBuilder.Entity("osu.Game.IO.FileInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("Hash"); - - b.Property("ReferenceCount"); - - b.HasKey("ID"); - - b.HasIndex("Hash") - .IsUnique(); - - b.HasIndex("ReferenceCount"); - - b.ToTable("FileInfo"); - }); - - modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("IntAction") - .HasColumnName("Action"); - - b.Property("KeysString") - .HasColumnName("Keys"); - - b.Property("RulesetID"); - - b.Property("Variant"); - - b.HasKey("ID"); - - b.HasIndex("IntAction"); - - b.HasIndex("RulesetID", "Variant"); - - b.ToTable("KeyBinding"); - }); - - modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("Available"); - - b.Property("InstantiationInfo"); - - b.Property("Name"); - - b.Property("ShortName"); - - b.Property("PlayingVerb"); - - b.HasKey("ID"); - - b.HasIndex("Available"); - - b.HasIndex("ShortName") - .IsUnique(); - - b.ToTable("RulesetInfo"); - }); - - modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("FileInfoID"); - - b.Property("Filename") - .IsRequired(); - - b.Property("ScoreInfoID"); - - b.HasKey("ID"); - - b.HasIndex("FileInfoID"); - - b.HasIndex("ScoreInfoID"); - - b.ToTable("ScoreFileInfo"); - }); - - modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("Accuracy") - .HasColumnType("DECIMAL(1,4)"); - - b.Property("BeatmapInfoID"); - - b.Property("Combo"); - - b.Property("Date"); - - b.Property("DeletePending"); - - b.Property("Hash"); - - b.Property("MaxCombo"); - - b.Property("ModsJson") - .HasColumnName("Mods"); - - b.Property("OnlineScoreID"); - - b.Property("PP"); - - b.Property("Rank"); - - b.Property("RulesetID"); - - b.Property("StatisticsJson") - .HasColumnName("Statistics"); - - b.Property("TotalScore"); - - b.Property("UserID") - .HasColumnName("UserID"); - - b.Property("UserString") - .HasColumnName("User"); - - b.HasKey("ID"); - - b.HasIndex("BeatmapInfoID"); - - b.HasIndex("OnlineScoreID") - .IsUnique(); - - b.HasIndex("RulesetID"); - - b.ToTable("ScoreInfo"); - }); - - modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("FileInfoID"); - - b.Property("Filename") - .IsRequired(); - - b.Property("SkinInfoID"); - - b.HasKey("ID"); - - b.HasIndex("FileInfoID"); - - b.HasIndex("SkinInfoID"); - - b.ToTable("SkinFileInfo"); - }); - - modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("Creator"); - - b.Property("DeletePending"); - - b.Property("Hash"); - - b.Property("Name"); - - b.HasKey("ID"); - - b.HasIndex("DeletePending"); - - b.HasIndex("Hash") - .IsUnique(); - - b.ToTable("SkinInfo"); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => - { - b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") - .WithMany() - .HasForeignKey("BaseDifficultyID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") - .WithMany("Beatmaps") - .HasForeignKey("BeatmapSetInfoID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") - .WithMany("Beatmaps") - .HasForeignKey("MetadataID"); - - b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") - .WithMany() - .HasForeignKey("RulesetID") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => - { - b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") - .WithMany("Files") - .HasForeignKey("BeatmapSetInfoID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("osu.Game.IO.FileInfo", "FileInfo") - .WithMany() - .HasForeignKey("FileInfoID") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => - { - b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") - .WithMany("BeatmapSets") - .HasForeignKey("MetadataID"); - }); - - modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => - { - b.HasOne("osu.Game.Skinning.SkinInfo") - .WithMany("Settings") - .HasForeignKey("SkinInfoID"); - }); - - modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => - { - b.HasOne("osu.Game.IO.FileInfo", "FileInfo") - .WithMany() - .HasForeignKey("FileInfoID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("osu.Game.Scoring.ScoreInfo") - .WithMany("Files") - .HasForeignKey("ScoreInfoID"); - }); - - modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => - { - b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap") - .WithMany("Scores") - .HasForeignKey("BeatmapInfoID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") - .WithMany() - .HasForeignKey("RulesetID") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => - { - b.HasOne("osu.Game.IO.FileInfo", "FileInfo") - .WithMany() - .HasForeignKey("FileInfoID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("osu.Game.Skinning.SkinInfo") - .WithMany("Files") - .HasForeignKey("SkinInfoID") - .OnDelete(DeleteBehavior.Cascade); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/osu.Game/Migrations/20200103111200_AddPlayingVerb.cs b/osu.Game/Migrations/20200103111200_AddPlayingVerb.cs deleted file mode 100644 index 1f1d89f55e..0000000000 --- a/osu.Game/Migrations/20200103111200_AddPlayingVerb.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -namespace osu.Game.Migrations -{ - public partial class AddPlayingVerb : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "PlayingVerb", - table: "RulesetInfo", - nullable: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "PlayingVerb", - table: "RulesetInfo"); - } - } -} diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 5d64d2ac5d..a6d9d1f3cb 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -283,8 +283,6 @@ namespace osu.Game.Migrations b.Property("ShortName"); - b.Property("PlayingVerb"); - b.HasKey("ID"); b.HasIndex("Available"); diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 237469aff2..11f35204a6 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.ComponentModel.DataAnnotations.Schema; using System.Diagnostics.CodeAnalysis; using Newtonsoft.Json; @@ -17,6 +18,7 @@ namespace osu.Game.Rulesets public string InstantiationInfo { get; set; } + [NotMapped] public string PlayingVerb { get; set; } [JsonIgnore] From b500ee44fbba7956f7b5bc5f4e233ca923f9b1b8 Mon Sep 17 00:00:00 2001 From: Albie Date: Fri, 3 Jan 2020 13:00:57 +0000 Subject: [PATCH 4882/5608] Update osu.Game/Rulesets/Ruleset.cs Co-Authored-By: Salman Ahmed --- osu.Game/Rulesets/Ruleset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index c930b42157..8563abf1e4 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -124,7 +124,7 @@ namespace osu.Game.Rulesets public abstract string ShortName { get; } /// - /// String used for and + /// The playing verb to be shown in the . /// public virtual string PlayingVerb => "Playing solo"; From 71a3db7cd6d4d0e9d0ae1b49dd4def7884aace7f Mon Sep 17 00:00:00 2001 From: Albie Spriddell Date: Fri, 3 Jan 2020 13:08:01 +0000 Subject: [PATCH 4883/5608] remove from rulesetinfo --- osu.Game/Rulesets/Ruleset.cs | 1 - osu.Game/Rulesets/RulesetInfo.cs | 4 ---- osu.Game/Rulesets/RulesetStore.cs | 1 - osu.Game/Users/UserActivity.cs | 2 +- 4 files changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index c930b42157..4d36bbe98f 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -59,7 +59,6 @@ namespace osu.Game.Rulesets ID = (this as ILegacyRuleset)?.LegacyID, InstantiationInfo = GetType().AssemblyQualifiedName, Available = true, - PlayingVerb = PlayingVerb, }; } diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 11f35204a6..ececc18c96 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.ComponentModel.DataAnnotations.Schema; using System.Diagnostics.CodeAnalysis; using Newtonsoft.Json; @@ -18,9 +17,6 @@ namespace osu.Game.Rulesets public string InstantiationInfo { get; set; } - [NotMapped] - public string PlayingVerb { get; set; } - [JsonIgnore] public bool Available { get; set; } diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 2b502c8edd..a389d4ff75 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -92,7 +92,6 @@ namespace osu.Game.Rulesets r.Name = instanceInfo.Name; r.ShortName = instanceInfo.ShortName; r.InstantiationInfo = instanceInfo.InstantiationInfo; - r.PlayingVerb = instanceInfo.PlayingVerb; r.Available = true; } diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 85c1b1f706..5c8617e88c 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -52,7 +52,7 @@ namespace osu.Game.Users Ruleset = ruleset; } - public override string Status => Ruleset.PlayingVerb; + public override string Status => Beatmap.Ruleset.CreateInstance().PlayingVerb; } public class Spectating : UserActivity From 960bbae87f84e588f3300ea9e872ee4cd99a2b23 Mon Sep 17 00:00:00 2001 From: Albie Date: Fri, 3 Jan 2020 15:07:47 +0000 Subject: [PATCH 4884/5608] Update osu.Game/Users/UserActivity.cs Co-Authored-By: Salman Ahmed --- osu.Game/Users/UserActivity.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 5c8617e88c..a775310256 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -52,7 +52,7 @@ namespace osu.Game.Users Ruleset = ruleset; } - public override string Status => Beatmap.Ruleset.CreateInstance().PlayingVerb; + public override string Status => Ruleset.CreateInstance().PlayingVerb; } public class Spectating : UserActivity From d4888c39de6ce88c4f73aa414a5ffa9db6616c36 Mon Sep 17 00:00:00 2001 From: Albie Spriddell Date: Fri, 3 Jan 2020 15:22:33 +0000 Subject: [PATCH 4885/5608] cleanup --- osu.Game/Users/UserActivity.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 5c8617e88c..3c9f201805 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -3,6 +3,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Rulesets; using osuTK.Graphics; namespace osu.Game.Users @@ -44,15 +45,15 @@ namespace osu.Game.Users { public BeatmapInfo Beatmap { get; } - public Rulesets.RulesetInfo Ruleset { get; } + public RulesetInfo Ruleset { get; } - public SoloGame(BeatmapInfo info, Rulesets.RulesetInfo ruleset) + public SoloGame(BeatmapInfo info, RulesetInfo ruleset) { Beatmap = info; Ruleset = ruleset; } - public override string Status => Beatmap.Ruleset.CreateInstance().PlayingVerb; + public override string Status => Ruleset.CreateInstance().PlayingVerb; } public class Spectating : UserActivity From 79a6655e1f6d64cb4246fc197560e607cccbbe87 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 3 Jan 2020 21:02:56 +0300 Subject: [PATCH 4886/5608] Use bindables for colour updates --- osu.Game/Overlays/OverlayRulesetTabItem.cs | 31 +++++++++---------- .../Components/ProfileRulesetTabItem.cs | 12 +++++-- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/OverlayRulesetTabItem.cs b/osu.Game/Overlays/OverlayRulesetTabItem.cs index e1cc1de8de..bf24895306 100644 --- a/osu.Game/Overlays/OverlayRulesetTabItem.cs +++ b/osu.Game/Overlays/OverlayRulesetTabItem.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osuTK.Graphics; using osuTK; -using System; +using osu.Framework.Bindables; namespace osu.Game.Overlays { @@ -22,24 +22,15 @@ namespace osu.Game.Overlays public override bool PropagatePositionalInputSubTree => Enabled.Value && !Active.Value && base.PropagatePositionalInputSubTree; - private Color4 accentColour; + private readonly Bindable accentColour = new Bindable(); + private readonly Bindable currentColour = new Bindable(); public Color4 AccentColour { - get => accentColour; - set - { - if (accentColour == value) - return; - - accentColour = value; - - updateState(); - } + get => accentColour.Value; + set => accentColour.Value = value; } - protected Action OnStateUpdated; - protected override Container Content => content; public OverlayRulesetTabItem(RulesetInfo value) @@ -70,6 +61,9 @@ namespace osu.Game.Overlays protected override void LoadComplete() { base.LoadComplete(); + + currentColour.BindValueChanged(OnCurrentColourChanged); + accentColour.BindValueChanged(_ => updateState()); Enabled.BindValueChanged(_ => updateState(), true); } @@ -92,10 +86,13 @@ namespace osu.Game.Overlays private void updateState() { - var updatedColour = IsHovered || Active.Value ? Color4.White : Enabled.Value ? AccentColour : Color4.DimGray; Text.Font = Text.Font.With(weight: Active.Value ? FontWeight.Bold : FontWeight.Medium); - Text.FadeColour(updatedColour, 120, Easing.OutQuint); - OnStateUpdated?.Invoke(updatedColour); + + currentColour.Value = IsHovered || Active.Value + ? Color4.White + : Enabled.Value ? AccentColour : Color4.DimGray; } + + protected virtual void OnCurrentColourChanged(ValueChangedEvent colour) => Text.FadeColour(colour.NewValue, 120, Easing.OutQuint); } } diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs index d416e98b31..038509d371 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs @@ -1,17 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets; using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { public class ProfileRulesetTabItem : OverlayRulesetTabItem { - private readonly SpriteIcon icon; - private bool isDefault; public bool IsDefault @@ -28,6 +28,8 @@ namespace osu.Game.Overlays.Profile.Header.Components } } + private readonly SpriteIcon icon; + public ProfileRulesetTabItem(RulesetInfo value) : base(value) { @@ -40,8 +42,12 @@ namespace osu.Game.Overlays.Profile.Header.Components Icon = FontAwesome.Solid.Star, Size = new Vector2(12), }); + } - OnStateUpdated += colour => icon.FadeColour(colour, 120, Easing.OutQuint); + protected override void OnCurrentColourChanged(ValueChangedEvent colour) + { + base.OnCurrentColourChanged(colour); + icon.FadeColour(colour.NewValue, 120, Easing.OutQuint); } } } From bd5140c3fa72b79d8f03b6e1eda6ccbd919e12f8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 3 Jan 2020 21:20:31 +0300 Subject: [PATCH 4887/5608] Add missing line breaks --- osu.Game/Overlays/OverlayRulesetTabItem.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/OverlayRulesetTabItem.cs b/osu.Game/Overlays/OverlayRulesetTabItem.cs index bf24895306..91cf2d6b96 100644 --- a/osu.Game/Overlays/OverlayRulesetTabItem.cs +++ b/osu.Game/Overlays/OverlayRulesetTabItem.cs @@ -90,7 +90,9 @@ namespace osu.Game.Overlays currentColour.Value = IsHovered || Active.Value ? Color4.White - : Enabled.Value ? AccentColour : Color4.DimGray; + : Enabled.Value + ? AccentColour + : Color4.DimGray; } protected virtual void OnCurrentColourChanged(ValueChangedEvent colour) => Text.FadeColour(colour.NewValue, 120, Easing.OutQuint); From e23c71be803ddc3f30d1070d3c1fe2bdd04ee6c9 Mon Sep 17 00:00:00 2001 From: Willy Tu Date: Fri, 3 Jan 2020 11:34:26 -0800 Subject: [PATCH 4888/5608] Update Resolved and Cached attribute issues --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 13 +++--------- .../TestSceneUserTopScoreContainer.cs | 14 +++---------- .../TestSceneDeleteLocalScore.cs | 21 +++++-------------- .../Online/Leaderboards/LeaderboardScore.cs | 6 +++--- .../Select/BeatmapClearScoresDialog.cs | 9 ++------ .../Screens/Select/LocalScoreDeleteDialog.cs | 9 ++------ 6 files changed, 18 insertions(+), 54 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 386fadc0d3..6ae0a80123 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -30,6 +30,7 @@ namespace osu.Game.Tests.Visual.SongSelect private readonly FailableLeaderboard leaderboard; + [Cached] private readonly DialogOverlay dialogOverlay; public TestSceneBeatmapLeaderboard() @@ -39,13 +40,13 @@ namespace osu.Game.Tests.Visual.SongSelect Depth = -1 }); - leaderboard = new FailableLeaderboard + Add(leaderboard = new FailableLeaderboard { Origin = Anchor.Centre, Anchor = Anchor.Centre, Size = new Vector2(550f, 450f), Scope = BeatmapLeaderboardScope.Global, - }; + }); AddStep(@"New Scores", newScores); AddStep(@"Show personal best", showPersonalBest); @@ -290,13 +291,5 @@ namespace osu.Game.Tests.Visual.SongSelect PlaceholderState = state; } } - - [BackgroundDependencyLoader] - private void load() - { - Dependencies.Cache(dialogOverlay); - - Add(leaderboard); - } } } diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs index c69626321d..0598324110 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs @@ -17,8 +17,8 @@ namespace osu.Game.Tests.Visual.SongSelect { public class TestSceneUserTopScoreContainer : OsuTestScene { + [Cached] private readonly DialogOverlay dialogOverlay; - private readonly Container container; public TestSceneUserTopScoreContainer() { @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual.SongSelect Depth = -1 }); - container = new Container + Add(new Container { Origin = Anchor.BottomCentre, Anchor = Anchor.Centre, @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.SongSelect Anchor = Anchor.BottomCentre, } } - }; + }); var scores = new[] { @@ -124,13 +124,5 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"Add score(rank 22333)", () => topScoreContainer.Score.Value = scores[2]); AddStep(@"Add null score", () => topScoreContainer.Score.Value = null); } - - [BackgroundDependencyLoader] - private void load() - { - Dependencies.Cache(dialogOverlay); - - Add(container); - } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index 2369b22ec2..de10eaccca 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -34,6 +34,7 @@ namespace osu.Game.Tests.Visual.UserInterface private readonly FailableLeaderboard leaderboard; + [Cached] private readonly DialogOverlay dialogOverlay; public TestSceneDeleteLocalScore() @@ -43,7 +44,7 @@ namespace osu.Game.Tests.Visual.UserInterface Depth = -1 }); - leaderboard = new FailableLeaderboard + Add(leaderboard = new FailableLeaderboard { Origin = Anchor.Centre, Anchor = Anchor.Centre, @@ -64,7 +65,7 @@ namespace osu.Game.Tests.Visual.UserInterface }, Version = "Insane" }, - }; + }); AddStep("Insert Local Scores", reset); } @@ -75,13 +76,6 @@ namespace osu.Game.Tests.Visual.UserInterface leaderboard.RefreshScores(); } - [BackgroundDependencyLoader] - private void load() - { - Dependencies.Cache(dialogOverlay); - Add(leaderboard); - } - private class FailableLeaderboard : BeatmapLeaderboard { private List scoreList; @@ -145,7 +139,8 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestLeaderboardScore : LeaderboardScore { - private DialogOverlay dialogOverlay; + [Resolved] + private DialogOverlay dialogOverlay { get; set; } private readonly FailableLeaderboard leaderboard; @@ -159,12 +154,6 @@ namespace osu.Game.Tests.Visual.UserInterface { dialogOverlay?.Push(new TestLocalScoreDeleteDialog(score, leaderboard)); } - - [BackgroundDependencyLoader] - private void load(DialogOverlay dialogOverlay) - { - this.dialogOverlay = dialogOverlay; - } } private class TestLocalScoreDeleteDialog : PopupDialog diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index b49a8bf483..7e24dc990b 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -55,7 +55,8 @@ namespace osu.Game.Online.Leaderboards private List statisticsLabels; - private DialogOverlay dialogOverlay; + [Resolved] + private DialogOverlay dialogOverlay { get; set; } public LeaderboardScore(ScoreInfo score, int rank, bool allowHighlight = true) { @@ -68,10 +69,9 @@ namespace osu.Game.Online.Leaderboards } [BackgroundDependencyLoader] - private void load(IAPIProvider api, OsuColour colour, DialogOverlay overlay) + private void load(IAPIProvider api, OsuColour colour) { var user = score.User; - dialogOverlay = overlay; statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s)).ToList(); diff --git a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs index c9b6ca7bb3..b32416b361 100644 --- a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs +++ b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs @@ -14,7 +14,8 @@ namespace osu.Game.Screens.Select { public class BeatmapClearScoresDialog : PopupDialog { - private ScoreManager scoreManager; + [Resolved] + private ScoreManager scoreManager { get; set; } public BeatmapClearScoresDialog(BeatmapInfo beatmap, Action onCompletion) { @@ -38,11 +39,5 @@ namespace osu.Game.Screens.Select }, }; } - - [BackgroundDependencyLoader] - private void load(ScoreManager scoreManager) - { - this.scoreManager = scoreManager; - } } } diff --git a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs index 514c5adf95..c1d680fd45 100644 --- a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs +++ b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs @@ -11,7 +11,8 @@ namespace osu.Game.Screens.Select { public class LocalScoreDeleteDialog : PopupDialog { - private ScoreManager scoreManager; + [Resolved] + private ScoreManager scoreManager { get; set; } public LocalScoreDeleteDialog(ScoreInfo score) { @@ -35,11 +36,5 @@ namespace osu.Game.Screens.Select }, }; } - - [BackgroundDependencyLoader] - private void load(ScoreManager scoreManager) - { - this.scoreManager = scoreManager; - } } } From 264523bc8babe7c9a5cdfd338b7c86ced3accd5f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 3 Jan 2020 23:22:19 +0300 Subject: [PATCH 4889/5608] Split ControllableOverlayHeader from base class --- .../BreadcrumbControlOverlayHeader.cs | 2 +- .../Overlays/ControllableOverlayHeader.cs | 41 +++++++++++ osu.Game/Overlays/OverlayHeader.cs | 71 ++++++++----------- osu.Game/Overlays/TabControlOverlayHeader.cs | 2 +- 4 files changed, 72 insertions(+), 44 deletions(-) create mode 100644 osu.Game/Overlays/ControllableOverlayHeader.cs diff --git a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs index 8a82b1f0c0..d7fa346c15 100644 --- a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs +++ b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs @@ -7,7 +7,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays { - public abstract class BreadcrumbControlOverlayHeader : OverlayHeader + public abstract class BreadcrumbControlOverlayHeader : ControllableOverlayHeader { protected OverlayHeaderBreadcrumbControl BreadcrumbControl; diff --git a/osu.Game/Overlays/ControllableOverlayHeader.cs b/osu.Game/Overlays/ControllableOverlayHeader.cs new file mode 100644 index 0000000000..30509995dd --- /dev/null +++ b/osu.Game/Overlays/ControllableOverlayHeader.cs @@ -0,0 +1,41 @@ +// 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.Shapes; +using osu.Framework.Graphics.UserInterface; +using osuTK.Graphics; + +namespace osu.Game.Overlays +{ + public abstract class ControllableOverlayHeader : OverlayHeader + { + protected Color4 ControlBackgroundColour + { + set => controlBackground.Colour = value; + } + + private readonly Box controlBackground; + + protected ControllableOverlayHeader() + { + HeaderInfo.Add(new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + controlBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray, + }, + CreateTabControl().With(control => control.Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }) + } + }); + } + + protected abstract TabControl CreateTabControl(); + } +} diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index 53da2da634..8c36e8cc9b 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -5,7 +5,6 @@ using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osuTK.Graphics; @@ -14,19 +13,14 @@ namespace osu.Game.Overlays public abstract class OverlayHeader : Container { private readonly Box titleBackground; - private readonly Box controlBackground; private readonly Container background; + protected readonly FillFlowContainer HeaderInfo; protected Color4 TitleBackgroundColour { set => titleBackground.Colour = value; } - protected Color4 ControlBackgroundColour - { - set => controlBackground.Colour = value; - } - protected float BackgroundHeight { set => background.Height = value; @@ -44,47 +38,42 @@ namespace osu.Game.Overlays Direction = FillDirection.Vertical, Children = new[] { - background = new Container - { - RelativeSizeAxes = Axes.X, - Height = 80, - Masking = true, - Child = CreateBackground() - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - titleBackground = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Gray, - }, - CreateTitle().With(title => - { - title.Margin = new MarginPadding - { - Vertical = 10, - Left = UserProfileOverlay.CONTENT_X_MARGIN - }; - }) - } - }, - new Container + HeaderInfo = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, Depth = -float.MaxValue, Children = new Drawable[] { - controlBackground = new Box + background = new Container { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Gray, + RelativeSizeAxes = Axes.X, + Height = 80, + Masking = true, + Child = CreateBackground() + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + titleBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray, + }, + CreateTitle().With(title => + { + title.Margin = new MarginPadding + { + Vertical = 10, + Left = UserProfileOverlay.CONTENT_X_MARGIN + }; + }) + } }, - CreateTabControl().With(control => control.Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }) } }, CreateContent() @@ -98,7 +87,5 @@ namespace osu.Game.Overlays protected virtual Drawable CreateContent() => new Container(); protected abstract ScreenTitle CreateTitle(); - - protected abstract TabControl CreateTabControl(); } } diff --git a/osu.Game/Overlays/TabControlOverlayHeader.cs b/osu.Game/Overlays/TabControlOverlayHeader.cs index f3521b66c8..1e6be9422d 100644 --- a/osu.Game/Overlays/TabControlOverlayHeader.cs +++ b/osu.Game/Overlays/TabControlOverlayHeader.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Overlays { - public abstract class TabControlOverlayHeader : OverlayHeader + public abstract class TabControlOverlayHeader : ControllableOverlayHeader { protected OverlayHeaderTabControl TabControl; From 53c8592cb9932d96fd1b4ab2894159c8df34052b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 3 Jan 2020 23:54:56 +0300 Subject: [PATCH 4890/5608] Add test scene --- .../UserInterface/TestSceneOverlayHeaders.cs | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaders.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaders.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaders.cs new file mode 100644 index 0000000000..60cf0f6885 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaders.cs @@ -0,0 +1,168 @@ +// 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.Containers; +using osu.Game.Overlays; +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics; +using osu.Framework.Graphics.Shapes; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneOverlayHeaders : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OverlayHeader), + typeof(ControllableOverlayHeader), + typeof(TabControlOverlayHeader), + typeof(BreadcrumbControlOverlayHeader), + typeof(TestNoControlHeader), + typeof(TestTabControlHeader), + typeof(TestBreadcrumbControlHeader), + }; + + private readonly FillFlowContainer flow; + + public TestSceneOverlayHeaders() + { + AddRange(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + new BasicScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = flow = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical + } + } + }); + + addHeader("OverlayHeader", new TestNoControlHeader()); + addHeader("TabControlOverlayHeader", new TestTabControlHeader()); + addHeader("BreadcrumbControlOverlayHeader", new TestBreadcrumbControlHeader()); + } + + private void addHeader(string name, OverlayHeader header) + { + flow.Add(new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new OsuSpriteText + { + Margin = new MarginPadding(20), + Text = name, + }, + header + } + }); + } + + private class TestNoControlHeader : OverlayHeader + { + protected override Drawable CreateBackground() => new TestBackground(); + + protected override ScreenTitle CreateTitle() => new TestTitle(); + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + TitleBackgroundColour = colours.GreyVioletDarker; + } + } + + private class TestTabControlHeader : TabControlOverlayHeader + { + protected override Drawable CreateBackground() => new TestBackground(); + + protected override ScreenTitle CreateTitle() => new TestTitle(); + + public TestTabControlHeader() + { + TabControl.AddItem("tab1"); + TabControl.AddItem("tab2"); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + TitleBackgroundColour = colours.GreyVioletDarker; + ControlBackgroundColour = colours.GreyVioletDark; + TabControl.AccentColour = colours.Violet; + } + } + + private class TestBreadcrumbControlHeader : BreadcrumbControlOverlayHeader + { + protected override Drawable CreateBackground() => new TestBackground(); + + protected override ScreenTitle CreateTitle() => new TestTitle(); + + public TestBreadcrumbControlHeader() + { + BreadcrumbControl.AddItem("tab1"); + BreadcrumbControl.AddItem("tab2"); + BreadcrumbControl.Current.Value = "tab2"; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + TitleBackgroundColour = colours.GreyVioletDarker; + ControlBackgroundColour = colours.GreyVioletDark; + BreadcrumbControl.AccentColour = colours.Violet; + } + } + + private class TestBackground : Sprite + { + public TestBackground() + { + RelativeSizeAxes = Axes.Both; + FillMode = FillMode.Fill; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Texture = textures.Get(@"Headers/changelog"); + } + } + + private class TestTitle : ScreenTitle + { + public TestTitle() + { + Title = "title"; + Section = "section"; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AccentColour = colours.Violet; + } + + protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/changelog"); + } + } +} From 9b95ce1045e0d1eba172e41cf96367e656bedffd Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sat, 4 Jan 2020 00:45:02 +0100 Subject: [PATCH 4891/5608] Change wrong values used to form target URL Dumb mistake by me, C# used ToString() on these objects. --- osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs index 76c925588b..689fd7e485 100644 --- a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs +++ b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs @@ -16,6 +16,6 @@ namespace osu.Game.Online.API.Requests this.message = message; } - protected override string Target => $"/chat/channels/{channel}/mark-as-read/{message}"; + protected override string Target => $"chat/channels/{channel.Id}/mark-as-read/{message.Id}"; } } From 8dbddfab559830ffe19f3c675af4ca0367a296d3 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sat, 4 Jan 2020 00:45:51 +0100 Subject: [PATCH 4892/5608] Add HTTP method --- osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs index 689fd7e485..95a5d0acbd 100644 --- a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs +++ b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Net.Http; +using osu.Framework.IO.Network; using osu.Game.Online.Chat; namespace osu.Game.Online.API.Requests @@ -17,5 +19,12 @@ namespace osu.Game.Online.API.Requests } protected override string Target => $"chat/channels/{channel.Id}/mark-as-read/{message.Id}"; + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Put; + return req; + } } } From 4f36bc0fd399a69194d10535ea9c61c8c51f395d Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sat, 4 Jan 2020 00:49:35 +0100 Subject: [PATCH 4893/5608] Add error log message for debugging --- osu.Game/Online/Chat/ChannelManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index e92a4853ff..6eb1674f37 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -450,6 +450,7 @@ namespace osu.Game.Online.Chat var channel = JoinedChannels.First(c => c.Id == message.ChannelId); var req = new MarkChannelAsReadRequest(channel, message); req.Success += () => channel.LastReadId = message.Id; + req.Failure += (e) => Logger.Error(e, "Failed to mark channel as read"); api.Queue(req); } From 7cc388b5abc56b5d49d9fabe9596db1701b22641 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sat, 4 Jan 2020 00:50:12 +0100 Subject: [PATCH 4894/5608] Mark channel up to last message as read when switching channels --- osu.Game/Overlays/ChatOverlay.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index e80c51d82a..b64d3a1893 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -279,6 +279,10 @@ namespace osu.Game.Overlays currentChannelContainer.Clear(false); currentChannelContainer.Add(loaded); } + + // mark channel as read when channel switched + if (e.NewValue.Messages.Any()) + channelManager.MarkChannelAsRead(e.NewValue.Messages.Last()); } private float startDragChatHeight; From cd91cc860d52f029fc77b32034eb966cf4a08bba Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sat, 4 Jan 2020 01:06:38 +0100 Subject: [PATCH 4895/5608] Resolve "Redundant lambda signature parentheses" --- osu.Game/Online/Chat/ChannelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 6eb1674f37..19c3be0d7b 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -450,7 +450,7 @@ namespace osu.Game.Online.Chat var channel = JoinedChannels.First(c => c.Id == message.ChannelId); var req = new MarkChannelAsReadRequest(channel, message); req.Success += () => channel.LastReadId = message.Id; - req.Failure += (e) => Logger.Error(e, "Failed to mark channel as read"); + req.Failure += e => Logger.Error(e, "Failed to mark channel as read"); api.Queue(req); } From a756d5d95d79e4c5997473c28c1877e88d9e18cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 4 Jan 2020 14:52:07 +0900 Subject: [PATCH 4896/5608] Fix new account registration attempting to login with email --- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 6de14c51ee..e530ff5489 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -196,7 +196,7 @@ namespace osu.Game.Overlays.AccountCreation return; } - api.Login(emailTextBox.Text, passwordTextBox.Text); + api.Login(usernameTextBox.Text, passwordTextBox.Text); }); }); } From 9da7eec0d91f4779c98ec094c321eba952440884 Mon Sep 17 00:00:00 2001 From: Sebastian Krajewski Date: Sat, 4 Jan 2020 08:21:48 +0100 Subject: [PATCH 4897/5608] Add pulse to slider reverse arrows --- .../Objects/Drawables/DrawableRepeatPoint.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index b81d94a673..db8ad98f8a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -65,12 +65,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateInitialTransforms() { - animDuration = Math.Min(150, repeatPoint.SpanDuration / 2); + animDuration = Math.Min(300, repeatPoint.SpanDuration); - this.Animate( - d => d.FadeIn(animDuration), - d => d.ScaleTo(0.5f).ScaleTo(1f, animDuration * 4, Easing.OutElasticHalf) - ); + this.FadeIn(animDuration); + + double fadeInStart = repeatPoint.StartTime - 2 * repeatPoint.SpanDuration; + + // We want first repeat arrow to start pulsing during snake in + if (repeatPoint.RepeatIndex == 0) + fadeInStart -= repeatPoint.TimePreempt; + + for (double pulseStartTime = fadeInStart; pulseStartTime < repeatPoint.StartTime; pulseStartTime += 300) + this.Delay(pulseStartTime - LifetimeStart).ScaleTo(1.3f).ScaleTo(1f, Math.Min(300, repeatPoint.StartTime - pulseStartTime)); } protected override void UpdateStateTransforms(ArmedState state) @@ -88,7 +94,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables break; case ArmedState.Hit: - this.FadeOut(animDuration, Easing.OutQuint) + this.FadeOut(animDuration, Easing.Out) .ScaleTo(Scale * 1.5f, animDuration, Easing.Out); break; } From fc0b622a69dc20e0104536d58b15f5a5f67cf45d Mon Sep 17 00:00:00 2001 From: Sebastian Krajewski Date: Sat, 4 Jan 2020 10:35:10 +0100 Subject: [PATCH 4898/5608] Change reverse arrow pulse easing to OutQuad --- .../Objects/Drawables/DrawableRepeatPoint.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index db8ad98f8a..e1cacfaaff 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.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; @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables fadeInStart -= repeatPoint.TimePreempt; for (double pulseStartTime = fadeInStart; pulseStartTime < repeatPoint.StartTime; pulseStartTime += 300) - this.Delay(pulseStartTime - LifetimeStart).ScaleTo(1.3f).ScaleTo(1f, Math.Min(300, repeatPoint.StartTime - pulseStartTime)); + this.Delay(pulseStartTime - LifetimeStart).ScaleTo(1.3f).ScaleTo(1f, Math.Min(300, repeatPoint.StartTime - pulseStartTime), Easing.Out); } protected override void UpdateStateTransforms(ArmedState state) From a897f497a2c20d074d0e108ede5e09934736be89 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sat, 4 Jan 2020 18:35:37 +0800 Subject: [PATCH 4899/5608] remove LaneGlowPiece and GlowPiece --- .../Objects/Drawables/Pieces/GlowPiece.cs | 68 --------------- .../Objects/Drawables/Pieces/LaneGlowPiece.cs | 85 ------------------- 2 files changed, 153 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs delete mode 100644 osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs deleted file mode 100644 index 1d25a0c966..0000000000 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; -using osuTK.Graphics; - -namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces -{ - public class GlowPiece : CompositeDrawable, IHasAccentColour - { - private const float glow_alpha = 0.7f; - private const float glow_radius = 5; - - public GlowPiece() - { - RelativeSizeAxes = Axes.Both; - Masking = true; - - InternalChild = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - updateGlow(); - } - - private Color4 accentColour; - - public Color4 AccentColour - { - get => accentColour; - set - { - if (accentColour == value) - return; - - accentColour = value; - - updateGlow(); - } - } - - private void updateGlow() - { - if (!IsLoaded) - return; - - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Colour = AccentColour.Opacity(glow_alpha), - Radius = glow_radius, - Hollow = true - }; - } - } -} diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs deleted file mode 100644 index 48c7ea7b7f..0000000000 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs +++ /dev/null @@ -1,85 +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 osuTK.Graphics; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; - -namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces -{ - public class LaneGlowPiece : CompositeDrawable, IHasAccentColour - { - private const float total_height = 100; - private const float glow_height = 50; - private const float glow_alpha = 0.4f; - private const float edge_alpha = 0.3f; - - public LaneGlowPiece() - { - BypassAutoSizeAxes = Axes.Both; - RelativeSizeAxes = Axes.X; - Height = total_height; - - InternalChildren = new[] - { - new Container - { - Name = "Left edge", - RelativeSizeAxes = Axes.Y, - Width = 1, - Children = createGradient(edge_alpha) - }, - new Container - { - Name = "Right edge", - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.Y, - Width = 1, - Children = createGradient(edge_alpha) - }, - new Container - { - Name = "Glow", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, - Height = glow_height, - Children = createGradient(glow_alpha) - } - }; - } - - private Drawable[] createGradient(float alpha) => new Drawable[] - { - new Box - { - Name = "Top", - RelativeSizeAxes = Axes.Both, - Height = 0.5f, - Blending = BlendingParameters.Additive, - Colour = ColourInfo.GradientVertical(Color4.Transparent, Color4.White.Opacity(alpha)) - }, - new Box - { - Name = "Bottom", - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.Both, - Height = 0.5f, - Blending = BlendingParameters.Additive, - Colour = ColourInfo.GradientVertical(Color4.White.Opacity(alpha), Color4.Transparent) - } - }; - - public Color4 AccentColour - { - get => Colour; - set => Colour = value; - } - } -} From 46271ccbc89e2a55059cda1070d1599321427bca Mon Sep 17 00:00:00 2001 From: Sebastian Krajewski Date: Sat, 4 Jan 2020 13:01:42 +0100 Subject: [PATCH 4900/5608] Add slider reverse arrow pulse settings --- .../Configuration/OsuRulesetConfigManager.cs | 5 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 43 +++++++------- .../Drawables/Pieces/ReverseArrowPiece.cs | 58 +++++++++++++++++++ .../UI/OsuSettingsSubsection.cs | 5 ++ .../UI/ReverseArrowPulseMode.cs | 18 ++++++ 5 files changed, 108 insertions(+), 21 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs create mode 100644 osu.Game.Rulesets.Osu/UI/ReverseArrowPulseMode.cs diff --git a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs index f76635a932..77b0c728b0 100644 --- a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs @@ -3,6 +3,7 @@ using osu.Game.Configuration; using osu.Game.Rulesets.Configuration; +using osu.Game.Rulesets.Osu.UI; namespace osu.Game.Rulesets.Osu.Configuration { @@ -19,6 +20,7 @@ namespace osu.Game.Rulesets.Osu.Configuration Set(OsuRulesetSetting.SnakingInSliders, true); Set(OsuRulesetSetting.SnakingOutSliders, true); Set(OsuRulesetSetting.ShowCursorTrail, true); + Set(OsuRulesetSetting.ReverseArrowPulse, ReverseArrowPulseMode.Synced); } } @@ -26,6 +28,7 @@ namespace osu.Game.Rulesets.Osu.Configuration { SnakingInSliders, SnakingOutSliders, - ShowCursorTrail + ShowCursorTrail, + ReverseArrowPulse, } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index e1cacfaaff..1f3c5d54bc 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.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; @@ -6,13 +6,13 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Scoring; using osuTK; -using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -21,9 +21,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly RepeatPoint repeatPoint; private readonly DrawableSlider drawableSlider; + public readonly Bindable PulseMode = new Bindable(ReverseArrowPulseMode.Synced); + private double animDuration; - private readonly SkinnableDrawable scaleContainer; + private readonly Drawable scaleContainer; + + [Resolved(CanBeNull = true)] + private OsuRulesetConfigManager config { get; set; } public DrawableRepeatPoint(RepeatPoint repeatPoint, DrawableSlider drawableSlider) : base(repeatPoint) @@ -36,16 +41,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Blending = BlendingParameters.Additive; Origin = Anchor.Centre; - InternalChild = scaleContainer = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.ReverseArrow), _ => new SpriteIcon - { - RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.Solid.ChevronRight, - Size = new Vector2(0.35f) - }, confineMode: ConfineMode.NoScaling) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }; + InternalChild = scaleContainer = new ReverseArrowPiece(); } private readonly IBindable scaleBindable = new Bindable(); @@ -55,6 +51,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { scaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); scaleBindable.BindTo(HitObject.ScaleBindable); + + config?.BindWith(OsuRulesetSetting.ReverseArrowPulse, PulseMode); } protected override void CheckForResult(bool userTriggered, double timeOffset) @@ -69,14 +67,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables this.FadeIn(animDuration); - double fadeInStart = repeatPoint.StartTime - 2 * repeatPoint.SpanDuration; + if (PulseMode.Value == ReverseArrowPulseMode.Stable) + { + double fadeInStart = repeatPoint.StartTime - 2 * repeatPoint.SpanDuration; - // We want first repeat arrow to start pulsing during snake in - if (repeatPoint.RepeatIndex == 0) - fadeInStart -= repeatPoint.TimePreempt; + // We want first repeat arrow to start pulsing during snake in + if (repeatPoint.RepeatIndex == 0) + fadeInStart -= repeatPoint.TimePreempt; - for (double pulseStartTime = fadeInStart; pulseStartTime < repeatPoint.StartTime; pulseStartTime += 300) - this.Delay(pulseStartTime - LifetimeStart).ScaleTo(1.3f).ScaleTo(1f, Math.Min(300, repeatPoint.StartTime - pulseStartTime), Easing.Out); + for (double pulseStartTime = fadeInStart; pulseStartTime < repeatPoint.StartTime; pulseStartTime += 300) + this.Delay(pulseStartTime - LifetimeStart).ScaleTo(1.3f).ScaleTo(1f, Math.Min(300, repeatPoint.StartTime - pulseStartTime), Easing.Out); + } + else if (PulseMode.Value == ReverseArrowPulseMode.Off) + this.ScaleTo(0.5f).ScaleTo(1f, animDuration * 2, Easing.OutElasticHalf); } protected override void UpdateStateTransforms(ArmedState state) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs new file mode 100644 index 0000000000..1ec175274e --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs @@ -0,0 +1,58 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Audio.Track; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osuTK; +using osu.Framework.Graphics.Sprites; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Containers; +using osu.Game.Rulesets.Osu.Configuration; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +{ + public class ReverseArrowPiece : BeatSyncedContainer + { + public readonly Bindable PulseMode = new Bindable(ReverseArrowPulseMode.Synced); + + [Resolved(CanBeNull = true)] + private OsuRulesetConfigManager config { get; set; } + + public ReverseArrowPiece() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + Blending = BlendingParameters.Additive; + + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); + + InternalChild = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.ReverseArrow), _ => new SpriteIcon + { + RelativeSizeAxes = Axes.Both, + Icon = FontAwesome.Solid.ChevronRight, + Size = new Vector2(0.35f) + }, confineMode: ConfineMode.NoScaling) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + } + + protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) + { + if (PulseMode.Value == ReverseArrowPulseMode.Synced) + InternalChild.ScaleTo(1.3f).ScaleTo(1f, timingPoint.BeatLength, Easing.Out); + } + + [BackgroundDependencyLoader] + private void load() + { + config?.BindWith(OsuRulesetSetting.ReverseArrowPulse, PulseMode); + } + } +} diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs index 88adf72551..afde693316 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs @@ -39,6 +39,11 @@ namespace osu.Game.Rulesets.Osu.UI LabelText = "Cursor trail", Bindable = config.GetBindable(OsuRulesetSetting.ShowCursorTrail) }, + new SettingsEnumDropdown + { + LabelText = "Slider reverse arrow pulse", + Bindable = config.GetBindable(OsuRulesetSetting.ReverseArrowPulse) + }, }; } } diff --git a/osu.Game.Rulesets.Osu/UI/ReverseArrowPulseMode.cs b/osu.Game.Rulesets.Osu/UI/ReverseArrowPulseMode.cs new file mode 100644 index 0000000000..d3261e71db --- /dev/null +++ b/osu.Game.Rulesets.Osu/UI/ReverseArrowPulseMode.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 System.ComponentModel; + +namespace osu.Game.Rulesets.Osu.UI +{ + public enum ReverseArrowPulseMode + { + Off, + + [Description("Match osu!stable")] + Stable, + + [Description("Sync to beatmap")] + Synced + } +} From 319465899824dfde4a6ef3150c86651c3afc98f9 Mon Sep 17 00:00:00 2001 From: Sebastian Krajewski Date: Sat, 4 Jan 2020 13:12:37 +0100 Subject: [PATCH 4901/5608] Fix repeat point pulsing when it is in fade out state --- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- .../Objects/Drawables/Pieces/ReverseArrowPiece.cs | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 1f3c5d54bc..6bf2f95f41 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Blending = BlendingParameters.Additive; Origin = Anchor.Centre; - InternalChild = scaleContainer = new ReverseArrowPiece(); + InternalChild = scaleContainer = new ReverseArrowPiece(repeatPoint); } private readonly IBindable scaleBindable = new Bindable(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs index 1ec175274e..114cf9d27e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Bindables; @@ -22,8 +23,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces [Resolved(CanBeNull = true)] private OsuRulesetConfigManager config { get; set; } - public ReverseArrowPiece() + private readonly RepeatPoint repeatPoint; + + public ReverseArrowPiece(RepeatPoint repeatPoint) { + this.repeatPoint = repeatPoint; + Anchor = Anchor.Centre; Origin = Anchor.Centre; @@ -45,8 +50,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) { - if (PulseMode.Value == ReverseArrowPulseMode.Synced) - InternalChild.ScaleTo(1.3f).ScaleTo(1f, timingPoint.BeatLength, Easing.Out); + if (PulseMode.Value == ReverseArrowPulseMode.Synced && Clock.CurrentTime < repeatPoint.StartTime) + InternalChild.ScaleTo(1.3f).ScaleTo(1f, Math.Min(timingPoint.BeatLength, repeatPoint.StartTime - Clock.CurrentTime), Easing.Out); } [BackgroundDependencyLoader] From 9fb29cc7a7ffc7a7db1a42e59d871f3799c9b2e9 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 4 Jan 2020 18:45:34 +0300 Subject: [PATCH 4902/5608] Move medal loading to LoadComplete --- osu.Game/Overlays/MedalOverlay.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 5da573e81a..f7070bbaec 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -154,19 +154,22 @@ namespace osu.Game.Overlays Colour = colours.Blue.Opacity(0.5f), Radius = 50, }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); LoadComponentAsync(drawableMedal = new DrawableMedal(medal) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Both, - }, disc.Add); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - Show(); + }, loaded => + { + disc.Add(loaded); + Show(); + }); } protected override void Update() From 3bd3ebad49466e55ade2c3a682a71d27c9e77dda Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 4 Jan 2020 18:26:31 +0100 Subject: [PATCH 4903/5608] Move placeholders to a dedicated namespace --- osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs | 1 + osu.Game/Online/Leaderboards/Leaderboard.cs | 1 + osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs | 1 + .../Online/{Leaderboards => Placeholders}/MessagePlaceholder.cs | 2 +- osu.Game/Online/{Leaderboards => Placeholders}/Placeholder.cs | 2 +- 5 files changed, 5 insertions(+), 2 deletions(-) rename osu.Game/Online/{Leaderboards => Placeholders}/MessagePlaceholder.cs (95%) rename osu.Game/Online/{Leaderboards => Placeholders}/Placeholder.cs (95%) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 57e297bcd5..2b52deb605 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; +using osu.Game.Online.Placeholders; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; using osu.Game.Screens.Select.Leaderboards; diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 9c48ebd09b..60c79f6d8f 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -14,6 +14,7 @@ using osu.Framework.Threading; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; +using osu.Game.Online.Placeholders; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs b/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs index 801f3f8ff0..15d7dabe65 100644 --- a/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs +++ b/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; +using osu.Game.Online.Placeholders; using osuTK; namespace osu.Game.Online.Leaderboards diff --git a/osu.Game/Online/Leaderboards/MessagePlaceholder.cs b/osu.Game/Online/Placeholders/MessagePlaceholder.cs similarity index 95% rename from osu.Game/Online/Leaderboards/MessagePlaceholder.cs rename to osu.Game/Online/Placeholders/MessagePlaceholder.cs index ef425dacd8..7342765ca4 100644 --- a/osu.Game/Online/Leaderboards/MessagePlaceholder.cs +++ b/osu.Game/Online/Placeholders/MessagePlaceholder.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -namespace osu.Game.Online.Leaderboards +namespace osu.Game.Online.Placeholders { public class MessagePlaceholder : Placeholder { diff --git a/osu.Game/Online/Leaderboards/Placeholder.cs b/osu.Game/Online/Placeholders/Placeholder.cs similarity index 95% rename from osu.Game/Online/Leaderboards/Placeholder.cs rename to osu.Game/Online/Placeholders/Placeholder.cs index d38110a9d0..f58282bbd9 100644 --- a/osu.Game/Online/Leaderboards/Placeholder.cs +++ b/osu.Game/Online/Placeholders/Placeholder.cs @@ -5,7 +5,7 @@ using System; using osu.Framework.Graphics; using osu.Game.Graphics.Containers; -namespace osu.Game.Online.Leaderboards +namespace osu.Game.Online.Placeholders { public abstract class Placeholder : OsuTextFlowContainer, IEquatable { From 474b8fc8fd441a6cf3f77cf35b8630bcb0b420bb Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 4 Jan 2020 19:25:49 +0100 Subject: [PATCH 4904/5608] Add LoginPlaceholder --- .../Online/Placeholders/LoginPlaceholder.cs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 osu.Game/Online/Placeholders/LoginPlaceholder.cs diff --git a/osu.Game/Online/Placeholders/LoginPlaceholder.cs b/osu.Game/Online/Placeholders/LoginPlaceholder.cs new file mode 100644 index 0000000000..f7450b8209 --- /dev/null +++ b/osu.Game/Online/Placeholders/LoginPlaceholder.cs @@ -0,0 +1,44 @@ +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Game.Overlays; + +namespace osu.Game.Online.Placeholders +{ + public sealed class LoginPlaceholder : Placeholder + { + [Resolved] + private LoginOverlay login { get; set; } + + public LoginPlaceholder(string action) + { + AddIcon(FontAwesome.Solid.UserLock, cp => + { + cp.Font = cp.Font.With(size: TEXT_SIZE); + cp.Padding = new MarginPadding { Right = 10 }; + }); + + AddText(@"Please sign in to " + action); + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + this.ScaleTo(0.8f, 4000, Easing.OutQuint); + return base.OnMouseDown(e); + } + + protected override bool OnMouseUp(MouseUpEvent e) + { + this.ScaleTo(1, 1000, Easing.OutElastic); + return base.OnMouseUp(e); + } + + protected override bool OnClick(ClickEvent e) + { + login?.Show(); + return base.OnClick(e); + } + + } +} From 5fd5665467e4b7503d4dd52e7fed4e821689f2a8 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 4 Jan 2020 19:59:25 +0100 Subject: [PATCH 4905/5608] Use implementation on song select leaderboards. --- osu.Game/Online/Leaderboards/Leaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 60c79f6d8f..06a36af618 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -151,7 +151,7 @@ namespace osu.Game.Online.Leaderboards break; case PlaceholderState.NotLoggedIn: - replacePlaceholder(new MessagePlaceholder(@"Please sign in to view online leaderboards!")); + replacePlaceholder(new LoginPlaceholder(@"view online leaderboards!")); break; case PlaceholderState.NotSupporter: From 3d747835dc7ef94c825ad8154c99ffacdc10b234 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 4 Jan 2020 21:09:40 +0100 Subject: [PATCH 4906/5608] Fix CI issues --- osu.Game/Online/Placeholders/LoginPlaceholder.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Placeholders/LoginPlaceholder.cs b/osu.Game/Online/Placeholders/LoginPlaceholder.cs index f7450b8209..dc753c6ab7 100644 --- a/osu.Game/Online/Placeholders/LoginPlaceholder.cs +++ b/osu.Game/Online/Placeholders/LoginPlaceholder.cs @@ -1,4 +1,7 @@ -using osu.Framework.Allocation; +// 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.Sprites; using osu.Framework.Input.Events; @@ -39,6 +42,5 @@ namespace osu.Game.Online.Placeholders login?.Show(); return base.OnClick(e); } - } } From 21e6351c5354467ad641f5fee2971438b50b2ad6 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 5 Jan 2020 14:33:44 +0100 Subject: [PATCH 4907/5608] Allow DI for LoginOverlay to resolve to null in non-graphical environments (fix tests) --- osu.Game/Online/Placeholders/LoginPlaceholder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Placeholders/LoginPlaceholder.cs b/osu.Game/Online/Placeholders/LoginPlaceholder.cs index dc753c6ab7..f6e4131930 100644 --- a/osu.Game/Online/Placeholders/LoginPlaceholder.cs +++ b/osu.Game/Online/Placeholders/LoginPlaceholder.cs @@ -11,7 +11,7 @@ namespace osu.Game.Online.Placeholders { public sealed class LoginPlaceholder : Placeholder { - [Resolved] + [Resolved(CanBeNull = true)] private LoginOverlay login { get; set; } public LoginPlaceholder(string action) From f70f25098b2b64999708d1771dce0189e4a4f029 Mon Sep 17 00:00:00 2001 From: Sebastian Krajewski Date: Mon, 6 Jan 2020 00:32:13 +0100 Subject: [PATCH 4908/5608] Change visible triangles colour when dark or light colour is changed --- osu.Game/Graphics/Backgrounds/Triangles.cs | 46 ++++++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 6d88808150..cbb50f7ddb 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -29,8 +29,29 @@ namespace osu.Game.Graphics.Backgrounds /// private const float edge_smoothness = 1; - public Color4 ColourLight = Color4.White; - public Color4 ColourDark = Color4.Black; + private Color4 colourLight = Color4.White; + + public Color4 ColourLight + { + get => colourLight; + set + { + colourLight = value; + updateColours(); + } + } + + private Color4 colourDark = Color4.Black; + + public Color4 ColourDark + { + get => colourDark; + set + { + colourDark = value; + updateColours(); + } + } /// /// Whether we want to expire triangles as they exit our draw area completely. @@ -151,7 +172,8 @@ namespace osu.Game.Graphics.Backgrounds TriangleParticle particle = CreateTriangle(); particle.Position = new Vector2(RNG.NextSingle(), randomY ? RNG.NextSingle() : 1); - particle.Colour = CreateTriangleShade(); + particle.ColourShade = RNG.NextSingle(); + particle.Colour = CreateTriangleShade(particle.ColourShade); return particle; } @@ -177,7 +199,17 @@ namespace osu.Game.Graphics.Backgrounds /// Creates a shade of colour for the triangles. /// /// The colour. - protected virtual Color4 CreateTriangleShade() => Interpolation.ValueAt(RNG.NextSingle(), ColourDark, ColourLight, 0, 1); + protected virtual Color4 CreateTriangleShade(float shade) => Interpolation.ValueAt(shade, colourDark, colourLight, 0, 1); + + private void updateColours() + { + for (int i = 0; i < parts.Count; i++) + { + TriangleParticle newParticle = parts[i]; + newParticle.Colour = CreateTriangleShade(newParticle.ColourShade); + parts[i] = newParticle; + } + } protected override DrawNode CreateDrawNode() => new TrianglesDrawNode(this); @@ -264,6 +296,12 @@ namespace osu.Game.Graphics.Backgrounds /// public Vector2 Position; + /// + /// The colour shade of the triangle. + /// This is needed for colour recalculation of visible triangles when or is changed. + /// + public float ColourShade; + /// /// The colour of the triangle. /// From d1f3cb3dbdc928317d21242374d1a6d0ec2f1152 Mon Sep 17 00:00:00 2001 From: Sebastian Krajewski Date: Mon, 6 Jan 2020 01:53:29 +0100 Subject: [PATCH 4909/5608] Premature checks to avoid unnecessary updates --- osu.Game/Graphics/Backgrounds/Triangles.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index cbb50f7ddb..af492bacc9 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -36,6 +36,8 @@ namespace osu.Game.Graphics.Backgrounds get => colourLight; set { + if (colourLight == value) return; + colourLight = value; updateColours(); } @@ -48,6 +50,8 @@ namespace osu.Game.Graphics.Backgrounds get => colourDark; set { + if (colourDark == value) return; + colourDark = value; updateColours(); } From d188d33f182a55d907fd6bcb79d8ad6f532b235a Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 5 Jan 2020 18:59:06 -0800 Subject: [PATCH 4910/5608] Fix osu!direct global action not being bound to a key --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index bf758e21d9..e37567c72c 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -32,6 +32,7 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings), new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar), new KeyBinding(new[] { InputKey.Control, InputKey.O }, GlobalAction.ToggleSettings), + new KeyBinding(new[] { InputKey.Control, InputKey.D }, GlobalAction.ToggleDirect), new KeyBinding(InputKey.Escape, GlobalAction.Back), new KeyBinding(InputKey.ExtraMouseButton1, GlobalAction.Back), From 49c252ec784eb21d7d8ba000153eba603a864ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 6 Jan 2020 07:33:59 +0100 Subject: [PATCH 4911/5608] Mark storyboard sample retrieval test headless --- osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs index 5deb136c85..84506739ab 100644 --- a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.IO.Stores; +using osu.Framework.Testing; using osu.Game.Audio; using osu.Game.Skinning; using osu.Game.Tests.Resources; @@ -15,6 +16,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Gameplay { + [HeadlessTest] public class TestSceneStoryboardSamples : OsuTestScene { [Test] From f91637e7b63e3157ed46df3d6ba4b8a91fbc56b9 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2020 07:41:37 +0000 Subject: [PATCH 4912/5608] Bump NUnit3TestAdapter from 3.15.1 to 3.16.0 Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 3.15.1 to 3.16.0. - [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases) - [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V3.15.1...V3.16) Signed-off-by: dependabot-preview[bot] --- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 9559d13328..0b2862e5bb 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index dea6e6c0fb..9d362e5819 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 9d4e016eae..1d8c4708c1 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index d728d65bfd..da89b37fbf 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 6c799e5e90..3f8a548fd5 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 7ecfd6ef70..75b88be1ab 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -7,7 +7,7 @@ - + WinExe From ee15967c4a7faeae023fc2a0fe553f2bc64e641f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Jan 2020 17:15:59 +0900 Subject: [PATCH 4913/5608] Rewrite test scene to be automated --- .../TestSceneDeleteLocalScore.cs | 255 +++++++++--------- 1 file changed, 120 insertions(+), 135 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index de10eaccca..e896b0fab6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -3,20 +3,26 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; +using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Allocation; -using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Cursor; +using osu.Framework.MathUtils; +using osu.Framework.Platform; +using osu.Framework.Testing; using osu.Game.Beatmaps; -using osu.Game.Online.API; +using osu.Game.Graphics.Cursor; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.Leaderboards; using osu.Game.Overlays; -using osu.Game.Overlays.Dialog; +using osu.Game.Rulesets; using osu.Game.Scoring; using osu.Game.Screens.Select.Leaderboards; +using osu.Game.Tests.Resources; using osu.Game.Users; using osuTK; +using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { @@ -32,154 +38,133 @@ namespace osu.Game.Tests.Visual.UserInterface typeof(LeaderboardScore), }; - private readonly FailableLeaderboard leaderboard; + private readonly ContextMenuContainer contextMenuContainer; + private readonly BeatmapLeaderboard leaderboard; + + private RulesetStore rulesetStore; + private BeatmapManager beatmapManager; + private ScoreManager scoreManager; + + private readonly List scores = new List(); + private BeatmapInfo beatmap; [Cached] private readonly DialogOverlay dialogOverlay; public TestSceneDeleteLocalScore() { - Add(dialogOverlay = new DialogOverlay + Children = new Drawable[] { - Depth = -1 - }); - - Add(leaderboard = new FailableLeaderboard - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Size = new Vector2(550f, 450f), - Scope = BeatmapLeaderboardScope.Local, - Beatmap = new BeatmapInfo + contextMenuContainer = new OsuContextMenuContainer { - ID = 1, - Metadata = new BeatmapMetadata + RelativeSizeAxes = Axes.Both, + Child = leaderboard = new BeatmapLeaderboard { - ID = 1, - Title = "TestSong", - Artist = "TestArtist", - Author = new User + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(550f, 450f), + Scope = BeatmapLeaderboardScope.Local, + Beatmap = new BeatmapInfo { - Username = "TestAuthor" + ID = 1, + Metadata = new BeatmapMetadata + { + ID = 1, + Title = "TestSong", + Artist = "TestArtist", + Author = new User + { + Username = "TestAuthor" + }, + }, + Version = "Insane" }, - }, - Version = "Insane" + } }, + dialogOverlay = new DialogOverlay() + }; + } + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + + dependencies.Cache(rulesetStore = new RulesetStore(ContextFactory)); + dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, ContextFactory, rulesetStore, null, Audio, dependencies.Get(), Beatmap.Default)); + dependencies.Cache(scoreManager = new ScoreManager(rulesetStore, () => beatmapManager, LocalStorage, null, ContextFactory)); + + beatmap = beatmapManager.Import(TestResources.GetTestBeatmapForImport()).Result.Beatmaps[0]; + + for (int i = 0; i < 50; i++) + { + var score = new ScoreInfo + { + OnlineScoreID = i, + Beatmap = beatmap, + BeatmapInfoID = beatmap.ID, + Accuracy = RNG.NextDouble(), + TotalScore = RNG.Next(1, 1000000), + MaxCombo = RNG.Next(1, 1000), + Rank = ScoreRank.XH, + User = new User { Username = "TestUser" }, + }; + + scores.Add(scoreManager.Import(score).Result); + } + + scores.Sort(Comparer.Create((s1, s2) => s2.TotalScore.CompareTo(s1.TotalScore))); + + return dependencies; + } + + [SetUp] + public void Setup() => Schedule(() => + { + // Due to soft deletions, we can re-use deleted scores between test runs + scoreManager.Undelete(scoreManager.QueryScores(s => s.DeletePending).ToList()); + + leaderboard.Beatmap = beatmap; + leaderboard.RefreshScores(); + }); + + [Test] + public void TestDeleteViaRightClick() + { + // Ensure the leaderboard items have finished showing up + AddStep("finish transforms", () => leaderboard.FinishTransforms(true)); + + AddStep("open menu for top score", () => + { + InputManager.MoveMouseTo(leaderboard.ChildrenOfType().First()); + InputManager.Click(MouseButton.Right); }); - AddStep("Insert Local Scores", reset); + // Ensure the context menu has finished showing + AddStep("finish transforms", () => contextMenuContainer.FinishTransforms(true)); + + AddStep("click delete option", () => + { + InputManager.MoveMouseTo(contextMenuContainer.ChildrenOfType().First(i => i.Item.Text.Value.ToLowerInvariant() == "delete")); + InputManager.Click(MouseButton.Left); + }); + + // Ensure the dialog has finished showing + AddStep("finish transforms", () => dialogOverlay.FinishTransforms(true)); + + AddStep("click delete button", () => + { + InputManager.MoveMouseTo(dialogOverlay.ChildrenOfType().First()); + InputManager.Click(MouseButton.Left); + }); + + AddUntilStep("score removed from leaderboard", () => leaderboard.Scores.All(s => s.OnlineScoreID != scores[0].OnlineScoreID)); } - private void reset() + [Test] + public void TestDeleteViaDatabase() { - leaderboard.InitialLoad = true; - leaderboard.RefreshScores(); - } - - private class FailableLeaderboard : BeatmapLeaderboard - { - private List scoreList; - - private Random rnd; - - public bool InitialLoad; - - public void DeleteScore(ScoreInfo score) - { - scoreList.Remove(score); - RefreshScores(); - } - - public FailableLeaderboard() - { - InitialLoad = true; - } - - public void SetRetrievalState(PlaceholderState state) - { - PlaceholderState = state; - } - - protected override APIRequest FetchScores(Action> scoresCallback) - { - if (InitialLoad) - { - rnd = new Random(); - - scoreList = Enumerable.Range(1, 50).Select(createScore).ToList(); - Scores = scoreList.OrderByDescending(s => s.TotalScore).ToArray(); - - InitialLoad = false; - } - else - { - Scores = scoreList.OrderByDescending(s => s.TotalScore).ToArray(); - } - - return null; - } - - private ScoreInfo createScore(int id) => new ScoreInfo - { - ID = id, - Accuracy = rnd.NextDouble(), - PP = rnd.Next(1, 1000000), - TotalScore = rnd.Next(1, 1000000), - MaxCombo = rnd.Next(1, 1000), - Rank = ScoreRank.XH, - User = new User { Username = "TestUser" }, - }; - - protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) - { - model.Beatmap = Beatmap; - return new TestLeaderboardScore(model, index, this, IsOnlineScope); - } - } - - private class TestLeaderboardScore : LeaderboardScore - { - [Resolved] - private DialogOverlay dialogOverlay { get; set; } - - private readonly FailableLeaderboard leaderboard; - - public TestLeaderboardScore(ScoreInfo score, int rank, FailableLeaderboard leaderboard, bool allowHighlight = true) - : base(score, rank, allowHighlight) - { - this.leaderboard = leaderboard; - } - - protected override void DeleteLocalScore(ScoreInfo score) - { - dialogOverlay?.Push(new TestLocalScoreDeleteDialog(score, leaderboard)); - } - } - - private class TestLocalScoreDeleteDialog : PopupDialog - { - public TestLocalScoreDeleteDialog(ScoreInfo score, FailableLeaderboard leaderboard) - { - Debug.Assert(score != null); - - string accuracy = string.Format(score.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", score.Accuracy); - - BodyText = $@"{score.User}'s {accuracy} {score.Rank} Rank on {score.Beatmap}"; - Icon = FontAwesome.Solid.Eraser; - HeaderText = @"Deleting this local score. Are you sure?"; - Buttons = new PopupDialogButton[] - { - new PopupDialogOkButton - { - Text = @"Yes. Please.", - Action = () => leaderboard.DeleteScore(score) - }, - new PopupDialogCancelButton - { - Text = @"No, I'm still attached.", - }, - }; - } + AddStep("delete top score", () => scoreManager.Delete(scores[0])); + AddUntilStep("score removed from leaderboard", () => leaderboard.Scores.All(s => s.OnlineScoreID != scores[0].OnlineScoreID)); } } } From 4a7f5f98dff7ac42191e664fd98e8f9f67467a6a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Jan 2020 17:20:09 +0900 Subject: [PATCH 4914/5608] Cleanup methods/events --- .../Online/Leaderboards/LeaderboardScore.cs | 7 +------ .../Select/Leaderboards/BeatmapLeaderboard.cs | 19 +++++++------------ 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 7e24dc990b..9c7324d913 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -367,11 +367,6 @@ namespace osu.Game.Online.Leaderboards } } - protected virtual void DeleteLocalScore(ScoreInfo score) - { - dialogOverlay?.Push(new LocalScoreDeleteDialog(score)); - } - public MenuItem[] ContextMenuItems { get @@ -379,7 +374,7 @@ namespace osu.Game.Online.Leaderboards List items = new List(); if (score.ID != 0) - items.Add(new OsuMenuItem("Delete", MenuItemType.Destructive, () => DeleteLocalScore(score))); + items.Add(new OsuMenuItem("Delete", MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(score)))); return items.ToArray(); } diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 8442e91712..9cf328e900 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -104,7 +104,7 @@ namespace osu.Game.Screens.Select.Leaderboards ScoreSelected = s => ScoreSelected?.Invoke(s) }); - scoreManager.ItemRemoved += deleteLocalScore; + scoreManager.ItemRemoved += onScoreRemoved; } protected override void Reset() @@ -113,15 +113,7 @@ namespace osu.Game.Screens.Select.Leaderboards TopScore = null; } - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (scoreManager != null) - { - scoreManager.ItemRemoved -= deleteLocalScore; - } - } + private void onScoreRemoved(ScoreInfo score) => Schedule(RefreshScores); protected override bool IsOnlineScope => Scope != BeatmapLeaderboardScope.Local; @@ -204,9 +196,12 @@ namespace osu.Game.Screens.Select.Leaderboards }; } - private void deleteLocalScore(ScoreInfo score) + protected override void Dispose(bool isDisposing) { - Schedule(RefreshScores); + base.Dispose(isDisposing); + + if (scoreManager != null) + scoreManager.ItemRemoved -= onScoreRemoved; } } } From 61c269b17b78e5e1b08c58b22a096e9043b4f1d8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Jan 2020 17:32:24 +0900 Subject: [PATCH 4915/5608] Leaderboard should not change the model --- .../Select/Leaderboards/BeatmapLeaderboard.cs | 11 +++-------- .../Screens/Select/LocalScoreDeleteDialog.cs | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 9cf328e900..e36493c82f 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -186,15 +186,10 @@ namespace osu.Game.Screens.Select.Leaderboards return req; } - protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) + protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) => new LeaderboardScore(model, index, IsOnlineScope) { - model.Beatmap = beatmap; - - return new LeaderboardScore(model, index, IsOnlineScope) - { - Action = () => ScoreSelected?.Invoke(model) - }; - } + Action = () => ScoreSelected?.Invoke(model) + }; protected override void Dispose(bool isDisposing) { diff --git a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs index c1d680fd45..d607706fc3 100644 --- a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs +++ b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs @@ -6,21 +6,35 @@ using osu.Game.Overlays.Dialog; using osu.Game.Scoring; using System.Diagnostics; using osu.Framework.Graphics.Sprites; +using osu.Game.Beatmaps; namespace osu.Game.Screens.Select { public class LocalScoreDeleteDialog : PopupDialog { + private readonly ScoreInfo score; + [Resolved] private ScoreManager scoreManager { get; set; } + [Resolved] + private BeatmapManager beatmapManager { get; set; } + public LocalScoreDeleteDialog(ScoreInfo score) { + this.score = score; Debug.Assert(score != null); + } + + [BackgroundDependencyLoader] + private void load() + { + BeatmapInfo beatmap = beatmapManager.QueryBeatmap(b => b.ID == score.BeatmapInfoID); + Debug.Assert(beatmap != null); string accuracy = string.Format(score.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", score.Accuracy); - BodyText = $@"{score.User}'s {accuracy} {score.Rank} Rank on {score.Beatmap}"; + BodyText = $@"{score.User}'s {accuracy} {score.Rank} Rank on {beatmap}"; Icon = FontAwesome.Solid.Eraser; HeaderText = @"Deleting this local score. Are you sure?"; Buttons = new PopupDialogButton[] @@ -28,7 +42,7 @@ namespace osu.Game.Screens.Select new PopupDialogOkButton { Text = @"Yes. Please.", - Action = () => scoreManager.Delete(score) + Action = () => scoreManager?.Delete(score) }, new PopupDialogCancelButton { From 28510674acee6420d4eb28add332b4981939c41f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Jan 2020 17:46:38 +0900 Subject: [PATCH 4916/5608] Shorten body text --- osu.Game/Screens/Select/LocalScoreDeleteDialog.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs index d607706fc3..97df40fa6d 100644 --- a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs +++ b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs @@ -32,21 +32,21 @@ namespace osu.Game.Screens.Select BeatmapInfo beatmap = beatmapManager.QueryBeatmap(b => b.ID == score.BeatmapInfoID); Debug.Assert(beatmap != null); - string accuracy = string.Format(score.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", score.Accuracy); + string accuracy = string.Format(score.Accuracy == 1 ? "{0:P0}" : "{0:P2}", score.Accuracy); + BodyText = $"{score.User} ({accuracy}, {score.Rank})"; - BodyText = $@"{score.User}'s {accuracy} {score.Rank} Rank on {beatmap}"; - Icon = FontAwesome.Solid.Eraser; - HeaderText = @"Deleting this local score. Are you sure?"; + Icon = FontAwesome.Regular.TrashAlt; + HeaderText = "Confirm deletion of local score"; Buttons = new PopupDialogButton[] { new PopupDialogOkButton { - Text = @"Yes. Please.", + Text = "Yes. Please.", Action = () => scoreManager?.Delete(score) }, new PopupDialogCancelButton { - Text = @"No, I'm still attached.", + Text = "No, I'm still attached.", }, }; } From e433e8b78f3d28494d88b9d9ab47ad2b53ca254c Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Mon, 6 Jan 2020 17:12:10 +0700 Subject: [PATCH 4917/5608] Remove unused variable --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 7bd40af512..a3128e36c4 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -48,11 +48,9 @@ namespace osu.Game.Beatmaps.Drawables InternalChild = iconContainer = new Container { Size = new Vector2(20f) }; } - public string TooltipText { get; set; } - public ITooltip GetCustomTooltip() => new DifficultyIconTooltip(); - public object TooltipContent { get; set; } + public object TooltipContent { get; } [BackgroundDependencyLoader] private void load(OsuColour colours) From de4c62788c88bb9ced4e976c9a32ccafba3f4266 Mon Sep 17 00:00:00 2001 From: Sebastian Krajewski Date: Mon, 6 Jan 2020 12:51:38 +0100 Subject: [PATCH 4918/5608] Move colour generation to TriangleParticle --- osu.Game/Graphics/Backgrounds/Triangles.cs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index af492bacc9..0eb5e90d3e 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -176,8 +176,7 @@ namespace osu.Game.Graphics.Backgrounds TriangleParticle particle = CreateTriangle(); particle.Position = new Vector2(RNG.NextSingle(), randomY ? RNG.NextSingle() : 1); - particle.ColourShade = RNG.NextSingle(); - particle.Colour = CreateTriangleShade(particle.ColourShade); + particle.UpdateColour(colourDark, colourLight); return particle; } @@ -199,18 +198,12 @@ namespace osu.Game.Graphics.Backgrounds return new TriangleParticle { Scale = scale }; } - /// - /// Creates a shade of colour for the triangles. - /// - /// The colour. - protected virtual Color4 CreateTriangleShade(float shade) => Interpolation.ValueAt(shade, colourDark, colourLight, 0, 1); - private void updateColours() { for (int i = 0; i < parts.Count; i++) { TriangleParticle newParticle = parts[i]; - newParticle.Colour = CreateTriangleShade(newParticle.ColourShade); + newParticle.UpdateColour(colourDark, colourLight); parts[i] = newParticle; } } @@ -293,7 +286,7 @@ namespace osu.Game.Graphics.Backgrounds } } - protected struct TriangleParticle : IComparable + protected class TriangleParticle : IComparable { /// /// The position of the top vertex of the triangle. @@ -304,7 +297,7 @@ namespace osu.Game.Graphics.Backgrounds /// The colour shade of the triangle. /// This is needed for colour recalculation of visible triangles when or is changed. /// - public float ColourShade; + private readonly float colourShade = RNG.NextSingle(); /// /// The colour of the triangle. @@ -316,6 +309,11 @@ namespace osu.Game.Graphics.Backgrounds /// public float Scale; + public void UpdateColour(Color4 colourDark, Color4 colourLight) + { + Colour = Interpolation.ValueAt(colourShade, colourDark, colourLight, 0, 1); + } + /// /// Compares two s. This is a reverse comparer because when the /// triangles are added to the particles list, they should be drawn from largest to smallest From 031bed15da7f1624d7e1b37e0e1119b1c90d877e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 6 Jan 2020 20:56:32 +0300 Subject: [PATCH 4919/5608] Fix comments async loading wasn't really async --- osu.Game/Overlays/Comments/DrawableComment.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 7ae6efda6a..bdae9da226 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -16,6 +16,7 @@ using osu.Framework.Graphics.Shapes; using System.Linq; using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; +using osu.Framework.Allocation; namespace osu.Game.Overlays.Comments { @@ -28,10 +29,16 @@ namespace osu.Game.Overlays.Comments private readonly BindableBool childrenExpanded = new BindableBool(true); - private readonly FillFlowContainer childCommentsVisibilityContainer; + private FillFlowContainer childCommentsVisibilityContainer; private readonly Comment comment; public DrawableComment(Comment comment) + { + this.comment = comment; + } + + [BackgroundDependencyLoader] + private void load() { LinkFlowContainer username; FillFlowContainer childCommentsContainer; @@ -41,8 +48,6 @@ namespace osu.Game.Overlays.Comments GridContainer content; VotePill votePill; - this.comment = comment; - RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; InternalChild = new FillFlowContainer From 7716a96b2848d32d1e49c932d8a25d19a877aa02 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 6 Jan 2020 23:07:58 +0300 Subject: [PATCH 4920/5608] Allow scrolling through DimmedLoadingLayer --- .../Graphics/UserInterface/DimmedLoadingLayer.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs index f2f6dd429b..aca3768540 100644 --- a/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs +++ b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.Color4Extensions; using osuTK; +using osu.Framework.Input.Events; namespace osu.Game.Graphics.UserInterface { @@ -41,5 +42,16 @@ namespace osu.Game.Graphics.UserInterface this.FadeOut(transition_duration, Easing.OutQuint); loading.Hide(); } + + protected override bool Handle(UIEvent e) + { + switch (e) + { + case ScrollEvent _: + return false; + } + + return base.Handle(e); + } } } From e0f66928e6e76dfeef068327a4296d1482baff97 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 7 Jan 2020 01:07:50 +0300 Subject: [PATCH 4921/5608] Allow CommentsContainer refetch comments using a method --- .../Online/TestSceneCommentsContainer.cs | 28 +++++++---------- .../Overlays/Comments/CommentsContainer.cs | 30 ++++++++++++------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index 86bd0ddd11..8134c10750 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -30,29 +30,23 @@ namespace osu.Game.Tests.Visual.Online public TestSceneCommentsContainer() { - BasicScrollContainer scrollFlow; + BasicScrollContainer scroll; + CommentsContainer comments; - Add(scrollFlow = new BasicScrollContainer + Add(scroll = new BasicScrollContainer { RelativeSizeAxes = Axes.Both, + Child = comments = new CommentsContainer() }); - AddStep("Big Black comments", () => + AddStep("Big Black comments", () => comments.ShowComments(CommentableType.Beatmapset, 41823)); + AddStep("Airman comments", () => comments.ShowComments(CommentableType.Beatmapset, 24313)); + AddStep("Lazer build comments", () => comments.ShowComments(CommentableType.Build, 4772)); + AddStep("News comments", () => comments.ShowComments(CommentableType.NewsPost, 715)); + AddStep("Idle state", () => { - scrollFlow.Clear(); - scrollFlow.Add(new CommentsContainer(CommentableType.Beatmapset, 41823)); - }); - - AddStep("Airman comments", () => - { - scrollFlow.Clear(); - scrollFlow.Add(new CommentsContainer(CommentableType.Beatmapset, 24313)); - }); - - AddStep("lazer build comments", () => - { - scrollFlow.Clear(); - scrollFlow.Add(new CommentsContainer(CommentableType.Build, 4772)); + scroll.Clear(); + scroll.Add(comments = new CommentsContainer()); }); } } diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 560123eb55..584f658673 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -18,8 +18,8 @@ namespace osu.Game.Overlays.Comments { public class CommentsContainer : CompositeDrawable { - private readonly CommentableType type; - private readonly long id; + private CommentableType type; + private long id; public readonly Bindable Sort = new Bindable(); public readonly BindableBool ShowDeleted = new BindableBool(); @@ -39,11 +39,8 @@ namespace osu.Game.Overlays.Comments private readonly DeletedChildrenPlaceholder deletedChildrenPlaceholder; private readonly CommentsShowMoreButton moreButton; - public CommentsContainer(CommentableType type, long id) + public CommentsContainer() { - this.type = type; - this.id = id; - RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; AddRangeInternal(new Drawable[] @@ -101,7 +98,8 @@ namespace osu.Game.Overlays.Comments Anchor = Anchor.Centre, Origin = Anchor.Centre, Margin = new MarginPadding(5), - Action = getComments + Action = getComments, + IsLoading = true, } } } @@ -121,12 +119,24 @@ namespace osu.Game.Overlays.Comments protected override void LoadComplete() { - Sort.BindValueChanged(onSortChanged, true); + Sort.BindValueChanged(_ => resetComments()); base.LoadComplete(); } - private void onSortChanged(ValueChangedEvent sort) + /// The type of resource to get comments for. + /// The id of the resource to get comments for. + public void ShowComments(CommentableType type, long id) { + this.type = type; + this.id = id; + Sort.TriggerChange(); + } + + private void resetComments() + { + if (id == default) + return; + clearComments(); getComments(); } @@ -152,7 +162,7 @@ namespace osu.Game.Overlays.Comments { loadCancellation = new CancellationTokenSource(); - FillFlowContainer page = new FillFlowContainer + var page = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, From 0b9cc8ed1b4e2f15ceb11228a51a7f27afce5e67 Mon Sep 17 00:00:00 2001 From: Sebastian Krajewski Date: Mon, 6 Jan 2020 12:51:38 +0100 Subject: [PATCH 4922/5608] Revert "Move colour generation to TriangleParticle" This reverts commit de4c62788c88bb9ced4e976c9a32ccafba3f4266. --- osu.Game/Graphics/Backgrounds/Triangles.cs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 0eb5e90d3e..af492bacc9 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -176,7 +176,8 @@ namespace osu.Game.Graphics.Backgrounds TriangleParticle particle = CreateTriangle(); particle.Position = new Vector2(RNG.NextSingle(), randomY ? RNG.NextSingle() : 1); - particle.UpdateColour(colourDark, colourLight); + particle.ColourShade = RNG.NextSingle(); + particle.Colour = CreateTriangleShade(particle.ColourShade); return particle; } @@ -198,12 +199,18 @@ namespace osu.Game.Graphics.Backgrounds return new TriangleParticle { Scale = scale }; } + /// + /// Creates a shade of colour for the triangles. + /// + /// The colour. + protected virtual Color4 CreateTriangleShade(float shade) => Interpolation.ValueAt(shade, colourDark, colourLight, 0, 1); + private void updateColours() { for (int i = 0; i < parts.Count; i++) { TriangleParticle newParticle = parts[i]; - newParticle.UpdateColour(colourDark, colourLight); + newParticle.Colour = CreateTriangleShade(newParticle.ColourShade); parts[i] = newParticle; } } @@ -286,7 +293,7 @@ namespace osu.Game.Graphics.Backgrounds } } - protected class TriangleParticle : IComparable + protected struct TriangleParticle : IComparable { /// /// The position of the top vertex of the triangle. @@ -297,7 +304,7 @@ namespace osu.Game.Graphics.Backgrounds /// The colour shade of the triangle. /// This is needed for colour recalculation of visible triangles when or is changed. /// - private readonly float colourShade = RNG.NextSingle(); + public float ColourShade; /// /// The colour of the triangle. @@ -309,11 +316,6 @@ namespace osu.Game.Graphics.Backgrounds /// public float Scale; - public void UpdateColour(Color4 colourDark, Color4 colourLight) - { - Colour = Interpolation.ValueAt(colourShade, colourDark, colourLight, 0, 1); - } - /// /// Compares two s. This is a reverse comparer because when the /// triangles are added to the particles list, they should be drawn from largest to smallest From 3ca4d1a28c7cb1fdbefa15f46a469712fe74e0a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Jan 2020 11:47:00 +0900 Subject: [PATCH 4923/5608] Split out tests --- .../Online/TestSceneBeatmapManager.cs | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Online/TestSceneBeatmapManager.cs b/osu.Game.Tests/Online/TestSceneBeatmapManager.cs index 7887002e1f..0ae0186770 100644 --- a/osu.Game.Tests/Online/TestSceneBeatmapManager.cs +++ b/osu.Game.Tests/Online/TestSceneBeatmapManager.cs @@ -26,16 +26,23 @@ namespace osu.Game.Tests.Online beatmaps.PostNotification = n => recentNotification = n as ProgressNotification; } - [TestCase(true)] - [TestCase(false)] - public void TestCancelDownloadRequest(bool closeFromRequest) + [Test] + public void TestCancelDownloadFromRequest() { AddStep("download beatmap", () => beatmaps.Download(test_model)); - if (closeFromRequest) - AddStep("cancel download from request", () => beatmaps.GetExistingDownload(test_model).Cancel()); - else - AddStep("cancel download from notification", () => recentNotification.Close()); + AddStep("cancel download from request", () => beatmaps.GetExistingDownload(test_model).Cancel()); + + AddUntilStep("is removed from download list", () => beatmaps.GetExistingDownload(test_model) == null); + AddAssert("is notification cancelled", () => recentNotification.State == ProgressNotificationState.Cancelled); + } + + [Test] + public void TestCancelDownloadFromNotification() + { + AddStep("download beatmap", () => beatmaps.Download(test_model)); + + AddStep("cancel download from notification", () => recentNotification.Close()); AddUntilStep("is removed from download list", () => beatmaps.GetExistingDownload(test_model) == null); AddAssert("is notification cancelled", () => recentNotification.State == ProgressNotificationState.Cancelled); From 21468eb07011c8774f9de838a5a19d602fe01fc6 Mon Sep 17 00:00:00 2001 From: Sebastian Krajewski Date: Tue, 7 Jan 2020 04:55:05 +0100 Subject: [PATCH 4924/5608] Remove settings related to reverse arrow --- .../Configuration/OsuRulesetConfigManager.cs | 5 +--- .../Objects/Drawables/DrawableRepeatPoint.cs | 28 +++---------------- .../Drawables/Pieces/ReverseArrowPiece.cs | 17 +---------- .../UI/OsuSettingsSubsection.cs | 5 ---- .../UI/ReverseArrowPulseMode.cs | 18 ------------ 5 files changed, 6 insertions(+), 67 deletions(-) delete mode 100644 osu.Game.Rulesets.Osu/UI/ReverseArrowPulseMode.cs diff --git a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs index 77b0c728b0..f76635a932 100644 --- a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs @@ -3,7 +3,6 @@ using osu.Game.Configuration; using osu.Game.Rulesets.Configuration; -using osu.Game.Rulesets.Osu.UI; namespace osu.Game.Rulesets.Osu.Configuration { @@ -20,7 +19,6 @@ namespace osu.Game.Rulesets.Osu.Configuration Set(OsuRulesetSetting.SnakingInSliders, true); Set(OsuRulesetSetting.SnakingOutSliders, true); Set(OsuRulesetSetting.ShowCursorTrail, true); - Set(OsuRulesetSetting.ReverseArrowPulse, ReverseArrowPulseMode.Synced); } } @@ -28,7 +26,6 @@ namespace osu.Game.Rulesets.Osu.Configuration { SnakingInSliders, SnakingOutSliders, - ShowCursorTrail, - ReverseArrowPulse, + ShowCursorTrail } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 6bf2f95f41..4873160af0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -8,9 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; -using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Scoring; using osuTK; @@ -21,15 +19,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly RepeatPoint repeatPoint; private readonly DrawableSlider drawableSlider; - public readonly Bindable PulseMode = new Bindable(ReverseArrowPulseMode.Synced); - private double animDuration; private readonly Drawable scaleContainer; - [Resolved(CanBeNull = true)] - private OsuRulesetConfigManager config { get; set; } - public DrawableRepeatPoint(RepeatPoint repeatPoint, DrawableSlider drawableSlider) : base(repeatPoint) { @@ -51,8 +44,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { scaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); scaleBindable.BindTo(HitObject.ScaleBindable); - - config?.BindWith(OsuRulesetSetting.ReverseArrowPulse, PulseMode); } protected override void CheckForResult(bool userTriggered, double timeOffset) @@ -65,21 +56,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { animDuration = Math.Min(300, repeatPoint.SpanDuration); - this.FadeIn(animDuration); - - if (PulseMode.Value == ReverseArrowPulseMode.Stable) - { - double fadeInStart = repeatPoint.StartTime - 2 * repeatPoint.SpanDuration; - - // We want first repeat arrow to start pulsing during snake in - if (repeatPoint.RepeatIndex == 0) - fadeInStart -= repeatPoint.TimePreempt; - - for (double pulseStartTime = fadeInStart; pulseStartTime < repeatPoint.StartTime; pulseStartTime += 300) - this.Delay(pulseStartTime - LifetimeStart).ScaleTo(1.3f).ScaleTo(1f, Math.Min(300, repeatPoint.StartTime - pulseStartTime), Easing.Out); - } - else if (PulseMode.Value == ReverseArrowPulseMode.Off) - this.ScaleTo(0.5f).ScaleTo(1f, animDuration * 2, Easing.OutElasticHalf); + this.Animate( + d => d.FadeIn(animDuration), + d => d.ScaleTo(0.5f).ScaleTo(1f, animDuration * 2, Easing.OutElasticHalf) + ); } protected override void UpdateStateTransforms(ArmedState state) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs index 114cf9d27e..2b9a3aa197 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs @@ -2,27 +2,18 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Allocation; using osu.Framework.Audio.Track; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osuTK; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Containers; -using osu.Game.Rulesets.Osu.Configuration; -using osu.Game.Rulesets.Osu.UI; using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class ReverseArrowPiece : BeatSyncedContainer { - public readonly Bindable PulseMode = new Bindable(ReverseArrowPulseMode.Synced); - - [Resolved(CanBeNull = true)] - private OsuRulesetConfigManager config { get; set; } - private readonly RepeatPoint repeatPoint; public ReverseArrowPiece(RepeatPoint repeatPoint) @@ -50,14 +41,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) { - if (PulseMode.Value == ReverseArrowPulseMode.Synced && Clock.CurrentTime < repeatPoint.StartTime) + if (Clock.CurrentTime < repeatPoint.StartTime) InternalChild.ScaleTo(1.3f).ScaleTo(1f, Math.Min(timingPoint.BeatLength, repeatPoint.StartTime - Clock.CurrentTime), Easing.Out); } - - [BackgroundDependencyLoader] - private void load() - { - config?.BindWith(OsuRulesetSetting.ReverseArrowPulse, PulseMode); - } } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs index afde693316..88adf72551 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs @@ -39,11 +39,6 @@ namespace osu.Game.Rulesets.Osu.UI LabelText = "Cursor trail", Bindable = config.GetBindable(OsuRulesetSetting.ShowCursorTrail) }, - new SettingsEnumDropdown - { - LabelText = "Slider reverse arrow pulse", - Bindable = config.GetBindable(OsuRulesetSetting.ReverseArrowPulse) - }, }; } } diff --git a/osu.Game.Rulesets.Osu/UI/ReverseArrowPulseMode.cs b/osu.Game.Rulesets.Osu/UI/ReverseArrowPulseMode.cs deleted file mode 100644 index d3261e71db..0000000000 --- a/osu.Game.Rulesets.Osu/UI/ReverseArrowPulseMode.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.ComponentModel; - -namespace osu.Game.Rulesets.Osu.UI -{ - public enum ReverseArrowPulseMode - { - Off, - - [Description("Match osu!stable")] - Stable, - - [Description("Sync to beatmap")] - Synced - } -} From 4a68c791375248441fcb307a0a903aa502c23c2e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 7 Jan 2020 13:06:30 +0900 Subject: [PATCH 4925/5608] Make tests safer against async loads / transforms --- .../UserInterface/TestSceneDeleteLocalScore.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index e896b0fab6..289c01fbf3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -123,16 +123,26 @@ namespace osu.Game.Tests.Visual.UserInterface // Due to soft deletions, we can re-use deleted scores between test runs scoreManager.Undelete(scoreManager.QueryScores(s => s.DeletePending).ToList()); + leaderboard.Scores = null; + leaderboard.FinishTransforms(true); // After setting scores, we may be waiting for transforms to expire drawables + leaderboard.Beatmap = beatmap; - leaderboard.RefreshScores(); + leaderboard.RefreshScores(); // Required in the case that the beatmap hasn't changed }); + [SetUpSteps] + public void SetupSteps() + { + // Ensure the leaderboard has finished async-loading drawables + AddUntilStep("wait for drawables", () => leaderboard.ChildrenOfType().Any()); + + // Ensure the leaderboard items have finished showing up + AddStep("finish transforms", () => leaderboard.FinishTransforms(true)); + } + [Test] public void TestDeleteViaRightClick() { - // Ensure the leaderboard items have finished showing up - AddStep("finish transforms", () => leaderboard.FinishTransforms(true)); - AddStep("open menu for top score", () => { InputManager.MoveMouseTo(leaderboard.ChildrenOfType().First()); From fd925526e2b320f4b055506312113b9f9a62d569 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Jan 2020 13:39:30 +0900 Subject: [PATCH 4926/5608] Fix medal overlay display --- osu.Game/Overlays/MedalOverlay.cs | 174 ++++++++++++++++-------------- 1 file changed, 91 insertions(+), 83 deletions(-) diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index f7070bbaec..15aec1f17c 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -41,105 +41,114 @@ namespace osu.Game.Overlays private SampleChannel getSample; + private readonly Container content; + public MedalOverlay(Medal medal) { this.medal = medal; RelativeSizeAxes = Axes.Both; - Children = new Drawable[] + Child = content = new Container { - background = new Box + Alpha = 0, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(60), - }, - outerSpin = new Sprite - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(DISC_SIZE + 500), - Alpha = 0f, - }, - backgroundStrip = new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, - Height = border_width, - Alpha = 0f, - Children = new[] + background = new Box { - new Container + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(60), + }, + outerSpin = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(DISC_SIZE + 500), + Alpha = 0f, + }, + backgroundStrip = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Height = border_width, + Alpha = 0f, + Children = new[] { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.CentreRight, - Width = 0.5f, - Padding = new MarginPadding { Right = DISC_SIZE / 2 }, - Children = new[] + new Container { - leftStrip = new BackgroundStrip(0f, 1f) + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.CentreRight, + Width = 0.5f, + Padding = new MarginPadding { Right = DISC_SIZE / 2 }, + Children = new[] { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, + leftStrip = new BackgroundStrip(0f, 1f) + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }, + }, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.CentreLeft, + Width = 0.5f, + Padding = new MarginPadding { Left = DISC_SIZE / 2 }, + Children = new[] + { + rightStrip = new BackgroundStrip(1f, 0f), }, }, }, - new Container + }, + particleContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Alpha = 0f, + }, + disc = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Alpha = 0f, + Masking = true, + AlwaysPresent = true, + BorderColour = Color4.White, + BorderThickness = border_width, + Size = new Vector2(DISC_SIZE), + Scale = new Vector2(0.8f), + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.CentreLeft, - Width = 0.5f, - Padding = new MarginPadding { Left = DISC_SIZE / 2 }, - Children = new[] + new Box { - rightStrip = new BackgroundStrip(1f, 0f), + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"05262f"), + }, + new Triangles + { + RelativeSizeAxes = Axes.Both, + TriangleScale = 2, + ColourDark = OsuColour.FromHex(@"04222b"), + ColourLight = OsuColour.FromHex(@"052933"), + }, + innerSpin = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(1.05f), + Alpha = 0.25f, }, }, }, - }, - particleContainer = new Container - { - RelativeSizeAxes = Axes.Both, - Alpha = 0f, - }, - disc = new CircularContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Alpha = 0f, - Masking = true, - AlwaysPresent = true, - BorderColour = Color4.White, - BorderThickness = border_width, - Size = new Vector2(DISC_SIZE), - Scale = new Vector2(0.8f), - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"05262f"), - }, - new Triangles - { - RelativeSizeAxes = Axes.Both, - TriangleScale = 2, - ColourDark = OsuColour.FromHex(@"04222b"), - ColourLight = OsuColour.FromHex(@"052933"), - }, - innerSpin = new Sprite - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(1.05f), - Alpha = 0.25f, - }, - }, - }, + } }; + + Show(); } [BackgroundDependencyLoader] @@ -168,7 +177,7 @@ namespace osu.Game.Overlays }, loaded => { disc.Add(loaded); - Show(); + startAnimation(); }); } @@ -193,11 +202,10 @@ namespace osu.Game.Overlays private const double initial_duration = 400; private const double step_duration = 900; - protected override void PopIn() + private void startAnimation() { - base.PopIn(); + content.Show(); - this.FadeIn(200); background.FlashColour(Color4.White.Opacity(0.25f), 400); getSample.Play(); From 97b5d71ee4dd86619f116f9e86bd33b7c7de72db Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 7 Jan 2020 15:09:30 +0900 Subject: [PATCH 4927/5608] Adjust catch HP increase values --- .../Judgements/CatchBananaJudgement.cs | 2 +- .../Judgements/CatchDropletJudgement.cs | 12 ------------ osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs | 12 ------------ .../Judgements/CatchTinyDropletJudgement.cs | 2 +- 4 files changed, 2 insertions(+), 26 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs index 374dd50c11..fc030877f1 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Judgements return 0; case HitResult.Perfect: - return 0.008; + return 0.01; } } diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs index f1399bb5c0..e87ecba749 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs @@ -18,17 +18,5 @@ namespace osu.Game.Rulesets.Catch.Judgements return 30; } } - - protected override double HealthIncreaseFor(HitResult result) - { - switch (result) - { - default: - return base.HealthIncreaseFor(result); - - case HitResult.Perfect: - return 0.007; - } - } } } diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs index 8fd9ac92ba..2149ed9712 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs @@ -23,18 +23,6 @@ namespace osu.Game.Rulesets.Catch.Judgements } } - protected override double HealthIncreaseFor(HitResult result) - { - switch (result) - { - default: - return -0.02; - - case HitResult.Perfect: - return 0.01; - } - } - /// /// Whether fruit on the platter should explode or drop. /// Note that this is only checked if the owning object is also diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs index 3829b5e94f..d607b49ea4 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.Judgements return 0; case HitResult.Perfect: - return 0.004; + return 0.02; } } } From dfa6575f75d375d7f4cb09c9206308263fe19d13 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 7 Jan 2020 15:24:33 +0900 Subject: [PATCH 4928/5608] Adjust mania HP increase values --- .../Judgements/HoldNoteTickJudgement.cs | 6 ++--- .../Judgements/ManiaJudgement.cs | 27 ------------------- 2 files changed, 3 insertions(+), 30 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs index b9c6e3a7f7..00b839f8ec 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs @@ -15,11 +15,11 @@ namespace osu.Game.Rulesets.Mania.Judgements { switch (result) { - case HitResult.Miss: + default: return 0; - default: - return 0.040; + case HitResult.Perfect: + return 0.01; } } } diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs index 0e4c811945..c2f8fb8678 100644 --- a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs @@ -29,32 +29,5 @@ namespace osu.Game.Rulesets.Mania.Judgements return 300; } } - - protected override double HealthIncreaseFor(HitResult result) - { - switch (result) - { - case HitResult.Miss: - return -0.125; - - case HitResult.Meh: - return 0.005; - - case HitResult.Ok: - return 0.010; - - case HitResult.Good: - return 0.035; - - case HitResult.Great: - return 0.055; - - case HitResult.Perfect: - return 0.065; - - default: - return 0; - } - } } } From e33de0c2e423e2ae7a44c19797c40096f7ec6c7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Jan 2020 15:14:09 +0800 Subject: [PATCH 4929/5608] Fix ScrollContainer crashes --- osu.Game/Graphics/Containers/OsuScrollContainer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuScrollContainer.cs b/osu.Game/Graphics/Containers/OsuScrollContainer.cs index ab72276ad0..cfd459da5e 100644 --- a/osu.Game/Graphics/Containers/OsuScrollContainer.cs +++ b/osu.Game/Graphics/Containers/OsuScrollContainer.cs @@ -123,8 +123,6 @@ namespace osu.Game.Graphics.Containers Masking = true; Child = box = new Box { RelativeSizeAxes = Axes.Both }; - - ResizeTo(1); } [BackgroundDependencyLoader] From 6adf5ba3813482e40cf3e0c391d136e7e9c596e9 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 7 Jan 2020 12:29:21 +0300 Subject: [PATCH 4930/5608] Use nullable long type for id value --- osu.Game/Overlays/Comments/CommentsContainer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 584f658673..97bd0a75e9 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Comments public class CommentsContainer : CompositeDrawable { private CommentableType type; - private long id; + private long? id; public readonly Bindable Sort = new Bindable(); public readonly BindableBool ShowDeleted = new BindableBool(); @@ -134,18 +134,18 @@ namespace osu.Game.Overlays.Comments private void resetComments() { - if (id == default) - return; - clearComments(); getComments(); } private void getComments() { + if (!id.HasValue) + return; + request?.Cancel(); loadCancellation?.Cancel(); - request = new GetCommentsRequest(type, id, Sort.Value, currentPage++); + request = new GetCommentsRequest(type, id.Value, Sort.Value, currentPage++); request.Success += onSuccess; api.Queue(request); } From 7dc03a1335f860ea0e190901bdc27827352e7286 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 7 Jan 2020 12:30:06 +0300 Subject: [PATCH 4931/5608] resetComments -> refetchComments --- osu.Game/Overlays/Comments/CommentsContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 97bd0a75e9..99f79cd940 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -119,7 +119,7 @@ namespace osu.Game.Overlays.Comments protected override void LoadComplete() { - Sort.BindValueChanged(_ => resetComments()); + Sort.BindValueChanged(_ => refetchComments()); base.LoadComplete(); } @@ -132,7 +132,7 @@ namespace osu.Game.Overlays.Comments Sort.TriggerChange(); } - private void resetComments() + private void refetchComments() { clearComments(); getComments(); From 7f92cefe1023fbfd2ff98045a70186d70e10e760 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Tue, 7 Jan 2020 19:06:47 +0100 Subject: [PATCH 4932/5608] Apply review suggestions --- osu.Game/Online/Leaderboards/Leaderboard.cs | 2 +- osu.Game/Online/Placeholders/LoginPlaceholder.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 06a36af618..095e552ddd 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -151,7 +151,7 @@ namespace osu.Game.Online.Leaderboards break; case PlaceholderState.NotLoggedIn: - replacePlaceholder(new LoginPlaceholder(@"view online leaderboards!")); + replacePlaceholder(new LoginPlaceholder(@"Please sign in to view online leaderboards!")); break; case PlaceholderState.NotSupporter: diff --git a/osu.Game/Online/Placeholders/LoginPlaceholder.cs b/osu.Game/Online/Placeholders/LoginPlaceholder.cs index f6e4131930..a613d7344a 100644 --- a/osu.Game/Online/Placeholders/LoginPlaceholder.cs +++ b/osu.Game/Online/Placeholders/LoginPlaceholder.cs @@ -22,7 +22,7 @@ namespace osu.Game.Online.Placeholders cp.Padding = new MarginPadding { Right = 10 }; }); - AddText(@"Please sign in to " + action); + AddText(action); } protected override bool OnMouseDown(MouseDownEvent e) From eb828154eeb6a38c45b52d7a48c582122df3fef3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 8 Jan 2020 00:41:52 +0300 Subject: [PATCH 4933/5608] Allow any type to be used to create TabControl --- .../Online/TestSceneUserProfileHeader.cs | 2 +- .../UserInterface/TestSceneOverlayHeaders.cs | 44 ++++++++++++++++--- .../BreadcrumbControlOverlayHeader.cs | 2 +- .../Overlays/ControllableOverlayHeader.cs | 5 ++- osu.Game/Overlays/Profile/ProfileHeader.cs | 2 +- osu.Game/Overlays/TabControlOverlayHeader.cs | 19 +++++--- 6 files changed, 56 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index 63b46c991f..b4408343c4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Online typeof(ProfileHeader), typeof(RankGraph), typeof(LineGraph), - typeof(TabControlOverlayHeader.OverlayHeaderTabControl), + typeof(TabControlOverlayHeader<>.OverlayHeaderTabControl), typeof(CentreHeaderContainer), typeof(BottomHeaderContainer), typeof(DetailHeaderContainer), diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaders.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaders.cs index 60cf0f6885..3ed5e53260 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaders.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaders.cs @@ -22,11 +22,12 @@ namespace osu.Game.Tests.Visual.UserInterface public override IReadOnlyList RequiredTypes => new[] { typeof(OverlayHeader), - typeof(ControllableOverlayHeader), - typeof(TabControlOverlayHeader), + typeof(ControllableOverlayHeader<>), + typeof(TabControlOverlayHeader<>), typeof(BreadcrumbControlOverlayHeader), typeof(TestNoControlHeader), - typeof(TestTabControlHeader), + typeof(TestStringTabControlHeader), + typeof(TestEnumTabControlHeader), typeof(TestBreadcrumbControlHeader), }; @@ -54,7 +55,8 @@ namespace osu.Game.Tests.Visual.UserInterface }); addHeader("OverlayHeader", new TestNoControlHeader()); - addHeader("TabControlOverlayHeader", new TestTabControlHeader()); + addHeader("TabControlOverlayHeader (string)", new TestStringTabControlHeader()); + addHeader("TabControlOverlayHeader (enum)", new TestEnumTabControlHeader()); addHeader("BreadcrumbControlOverlayHeader", new TestBreadcrumbControlHeader()); } @@ -69,10 +71,16 @@ namespace osu.Game.Tests.Visual.UserInterface { new OsuSpriteText { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Margin = new MarginPadding(20), Text = name, }, - header + header.With(header => + { + header.Anchor = Anchor.TopCentre; + header.Origin = Anchor.TopCentre; + }) } }); } @@ -90,13 +98,13 @@ namespace osu.Game.Tests.Visual.UserInterface } } - private class TestTabControlHeader : TabControlOverlayHeader + private class TestStringTabControlHeader : TabControlOverlayHeader { protected override Drawable CreateBackground() => new TestBackground(); protected override ScreenTitle CreateTitle() => new TestTitle(); - public TestTabControlHeader() + public TestStringTabControlHeader() { TabControl.AddItem("tab1"); TabControl.AddItem("tab2"); @@ -111,6 +119,28 @@ namespace osu.Game.Tests.Visual.UserInterface } } + private class TestEnumTabControlHeader : TabControlOverlayHeader + { + protected override Drawable CreateBackground() => new TestBackground(); + + protected override ScreenTitle CreateTitle() => new TestTitle(); + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + TitleBackgroundColour = colours.GreyVioletDarker; + ControlBackgroundColour = colours.GreyVioletDark; + TabControl.AccentColour = colours.Violet; + } + } + + private enum TestEnum + { + Some, + Cool, + Tabs + } + private class TestBreadcrumbControlHeader : BreadcrumbControlOverlayHeader { protected override Drawable CreateBackground() => new TestBackground(); diff --git a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs index d7fa346c15..a82ff44505 100644 --- a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs +++ b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs @@ -7,7 +7,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays { - public abstract class BreadcrumbControlOverlayHeader : ControllableOverlayHeader + public abstract class BreadcrumbControlOverlayHeader : ControllableOverlayHeader { protected OverlayHeaderBreadcrumbControl BreadcrumbControl; diff --git a/osu.Game/Overlays/ControllableOverlayHeader.cs b/osu.Game/Overlays/ControllableOverlayHeader.cs index 30509995dd..9b2bf526ca 100644 --- a/osu.Game/Overlays/ControllableOverlayHeader.cs +++ b/osu.Game/Overlays/ControllableOverlayHeader.cs @@ -9,7 +9,8 @@ using osuTK.Graphics; namespace osu.Game.Overlays { - public abstract class ControllableOverlayHeader : OverlayHeader + /// The type of item to be represented by tabs in . + public abstract class ControllableOverlayHeader : OverlayHeader { protected Color4 ControlBackgroundColour { @@ -36,6 +37,6 @@ namespace osu.Game.Overlays }); } - protected abstract TabControl CreateTabControl(); + protected abstract TabControl CreateTabControl(); } } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 59e64dfc26..768344dfee 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -15,7 +15,7 @@ using osu.Game.Users; namespace osu.Game.Overlays.Profile { - public class ProfileHeader : TabControlOverlayHeader + public class ProfileHeader : TabControlOverlayHeader { private UserCoverBackground coverContainer; diff --git a/osu.Game/Overlays/TabControlOverlayHeader.cs b/osu.Game/Overlays/TabControlOverlayHeader.cs index 1e6be9422d..d108af4348 100644 --- a/osu.Game/Overlays/TabControlOverlayHeader.cs +++ b/osu.Game/Overlays/TabControlOverlayHeader.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; @@ -9,13 +10,13 @@ using osuTK; namespace osu.Game.Overlays { - public abstract class TabControlOverlayHeader : ControllableOverlayHeader + public abstract class TabControlOverlayHeader : ControllableOverlayHeader { protected OverlayHeaderTabControl TabControl; - protected override TabControl CreateTabControl() => TabControl = new OverlayHeaderTabControl(); + protected override TabControl CreateTabControl() => TabControl = new OverlayHeaderTabControl(); - public class OverlayHeaderTabControl : OverlayTabControl + public class OverlayHeaderTabControl : OverlayTabControl { public OverlayHeaderTabControl() { @@ -25,9 +26,15 @@ namespace osu.Game.Overlays Anchor = Anchor.BottomLeft; Origin = Anchor.BottomLeft; Height = 35; + + if (typeof(T).IsEnum) + { + foreach (var val in (T[])Enum.GetValues(typeof(T))) + AddItem(val); + } } - protected override TabItem CreateTabItem(string value) => new OverlayHeaderTabItem(value) + protected override TabItem CreateTabItem(T value) => new OverlayHeaderTabItem(value) { AccentColour = AccentColour, }; @@ -42,10 +49,10 @@ namespace osu.Game.Overlays private class OverlayHeaderTabItem : OverlayTabItem { - public OverlayHeaderTabItem(string value) + public OverlayHeaderTabItem(T value) : base(value) { - Text.Text = value; + Text.Text = value.ToString().ToLowerInvariant(); Text.Font = OsuFont.GetFont(size: 14); Bar.ExpandedSize = 5; } From 351aaf41d93765cb7e85a7299e18deffc10df473 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 8 Jan 2020 00:54:02 +0300 Subject: [PATCH 4934/5608] Fix parameter naming --- .../Visual/UserInterface/TestSceneOverlayHeaders.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaders.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaders.cs index 3ed5e53260..bede4e38b8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaders.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaders.cs @@ -76,10 +76,10 @@ namespace osu.Game.Tests.Visual.UserInterface Margin = new MarginPadding(20), Text = name, }, - header.With(header => + header.With(h => { - header.Anchor = Anchor.TopCentre; - header.Origin = Anchor.TopCentre; + h.Anchor = Anchor.TopCentre; + h.Origin = Anchor.TopCentre; }) } }); From 2688a855a0ab397e411aa225438ea5cbd9fcac1a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 8 Jan 2020 14:14:46 +0900 Subject: [PATCH 4935/5608] Downgrade NUnit to fix discovery issues --- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 0b2862e5bb..9559d13328 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index 9d362e5819..dea6e6c0fb 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index da89b37fbf..d728d65bfd 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 3f8a548fd5..6c799e5e90 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 75b88be1ab..7ecfd6ef70 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -7,7 +7,7 @@ - + WinExe From 6dd45e52ef45028104978e785ad79a05995f7654 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Jan 2020 17:22:51 +0900 Subject: [PATCH 4936/5608] Move text definition inside class --- osu.Game/Online/Leaderboards/Leaderboard.cs | 2 +- osu.Game/Online/Placeholders/LoginPlaceholder.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 095e552ddd..55233bef6e 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -151,7 +151,7 @@ namespace osu.Game.Online.Leaderboards break; case PlaceholderState.NotLoggedIn: - replacePlaceholder(new LoginPlaceholder(@"Please sign in to view online leaderboards!")); + replacePlaceholder(new LoginPlaceholder()); break; case PlaceholderState.NotSupporter: diff --git a/osu.Game/Online/Placeholders/LoginPlaceholder.cs b/osu.Game/Online/Placeholders/LoginPlaceholder.cs index a613d7344a..ffc6623229 100644 --- a/osu.Game/Online/Placeholders/LoginPlaceholder.cs +++ b/osu.Game/Online/Placeholders/LoginPlaceholder.cs @@ -14,7 +14,7 @@ namespace osu.Game.Online.Placeholders [Resolved(CanBeNull = true)] private LoginOverlay login { get; set; } - public LoginPlaceholder(string action) + public LoginPlaceholder() { AddIcon(FontAwesome.Solid.UserLock, cp => { @@ -22,7 +22,7 @@ namespace osu.Game.Online.Placeholders cp.Padding = new MarginPadding { Right = 10 }; }); - AddText(action); + AddText(@"Please sign in to view online leaderboards!"); } protected override bool OnMouseDown(MouseDownEvent e) From c2fc7d5cbdb721887020dabc326bcf4443855da4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 6 Jan 2020 19:48:28 +0800 Subject: [PATCH 4937/5608] Add empty benchmark project. --- osu.Desktop.slnf | 1 + osu.Game.Benchmarks/Program.cs | 13 +++++++++++++ osu.Game.Benchmarks/osu.Game.Benchmarks.csproj | 9 +++++++++ osu.sln | 14 ++++++++++++++ 4 files changed, 37 insertions(+) create mode 100644 osu.Game.Benchmarks/Program.cs create mode 100644 osu.Game.Benchmarks/osu.Game.Benchmarks.csproj diff --git a/osu.Desktop.slnf b/osu.Desktop.slnf index e6b6446f72..d2c14d321a 100644 --- a/osu.Desktop.slnf +++ b/osu.Desktop.slnf @@ -3,6 +3,7 @@ "path": "osu.sln", "projects": [ "osu.Desktop\\osu.Desktop.csproj", + "osu.Game.Benchmarks\\osu.Game.Benchmarks.csproj", "osu.Game.Rulesets.Catch.Tests\\osu.Game.Rulesets.Catch.Tests.csproj", "osu.Game.Rulesets.Catch\\osu.Game.Rulesets.Catch.csproj", "osu.Game.Rulesets.Mania.Tests\\osu.Game.Rulesets.Mania.Tests.csproj", diff --git a/osu.Game.Benchmarks/Program.cs b/osu.Game.Benchmarks/Program.cs new file mode 100644 index 0000000000..ebd30c0a7a --- /dev/null +++ b/osu.Game.Benchmarks/Program.cs @@ -0,0 +1,13 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Benchmarks +{ + public static class Program + { + public static void Main(string[] args) + { + + } + } +} diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj new file mode 100644 index 0000000000..65bfa2be14 --- /dev/null +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -0,0 +1,9 @@ + + + + netcoreapp3.1 + Exe + false + + + diff --git a/osu.sln b/osu.sln index 79823848f0..1d64f6ff10 100644 --- a/osu.sln +++ b/osu.sln @@ -65,6 +65,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution osu.TestProject.props = osu.TestProject.props EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Benchmarks", "osu.Game.Benchmarks\osu.Game.Benchmarks.csproj", "{93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -399,6 +401,18 @@ Global {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU + {93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}.Debug|iPhone.Build.0 = Debug|Any CPU + {93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}.Release|Any CPU.Build.0 = Release|Any CPU + {93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}.Release|iPhone.ActiveCfg = Release|Any CPU + {93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}.Release|iPhone.Build.0 = Release|Any CPU + {93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}.Release|iPhoneSimulator.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 1b9f8d27372f247ee3213ec7422536a691a470af Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 8 Jan 2020 20:36:00 +0800 Subject: [PATCH 4938/5608] Add benchmark runner. --- osu.Game.Benchmarks/BenchmarkTest.cs | 23 +++++++++++++++++++ osu.Game.Benchmarks/Program.cs | 6 ++++- .../osu.Game.Benchmarks.csproj | 10 ++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Benchmarks/BenchmarkTest.cs diff --git a/osu.Game.Benchmarks/BenchmarkTest.cs b/osu.Game.Benchmarks/BenchmarkTest.cs new file mode 100644 index 0000000000..34f5edd084 --- /dev/null +++ b/osu.Game.Benchmarks/BenchmarkTest.cs @@ -0,0 +1,23 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Running; +using NUnit.Framework; + +namespace osu.Game.Benchmarks +{ + [TestFixture] + [MemoryDiagnoser] + public abstract class BenchmarkTest + { + [GlobalSetup] + [OneTimeSetUp] + public virtual void SetUp() + { + } + + [Test] + public void RunBenchmark() => BenchmarkRunner.Run(GetType()); + } +} diff --git a/osu.Game.Benchmarks/Program.cs b/osu.Game.Benchmarks/Program.cs index ebd30c0a7a..c55075fea6 100644 --- a/osu.Game.Benchmarks/Program.cs +++ b/osu.Game.Benchmarks/Program.cs @@ -1,13 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using BenchmarkDotNet.Running; + namespace osu.Game.Benchmarks { public static class Program { public static void Main(string[] args) { - + BenchmarkSwitcher + .FromAssembly(typeof(Program).Assembly) + .Run(args); } } } diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index 65bfa2be14..3281fcc855 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -6,4 +6,14 @@ false + + + + + + + + + + From bd22d5b0f44522bf8293cfb9e8f9e69232534a6c Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 8 Jan 2020 21:31:58 +0800 Subject: [PATCH 4939/5608] Add benchmark launch profiles. --- .../.idea/runConfigurations/Benchmarks.xml | 20 +++++++++++++++++ .vscode/launch.json | 19 ++++++++++++++-- .vscode/tasks.json | 22 +++++++++++++++++-- .../Properties/launchSettings.json | 8 +++++++ 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 .idea/.idea.osu.Desktop/.idea/runConfigurations/Benchmarks.xml create mode 100644 osu.Game.Benchmarks/Properties/launchSettings.json diff --git a/.idea/.idea.osu.Desktop/.idea/runConfigurations/Benchmarks.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/Benchmarks.xml new file mode 100644 index 0000000000..1815c271b4 --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/runConfigurations/Benchmarks.xml @@ -0,0 +1,20 @@ + + + + \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index e7b691909e..6480612b2e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,6 +1,7 @@ { "version": "0.2.0", - "configurations": [{ + "configurations": [ + { "name": "osu! (Debug)", "type": "coreclr", "request": "launch", @@ -50,7 +51,8 @@ } }, "console": "internalConsole" - }, { + }, + { "name": "osu! (Tests, Release)", "type": "coreclr", "request": "launch", @@ -139,6 +141,19 @@ }, "console": "internalConsole" }, + { + "name": "Benchmark", + "type": "coreclr", + "request": "launch", + "program": "${workspaceRoot}/osu.Game.Benchmarks/bin/Release/netcoreapp3.1/osu.Game.Benchmarks.dll", + "args": [ + "--filter", + "*" + ], + "cwd": "${workspaceRoot}", + "preLaunchTask": "Build benchmarks", + "console": "internalConsole" + }, { "name": "Cake: Debug Script", "type": "coreclr", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index c087800d2a..e638dec767 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,7 +2,8 @@ // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format "version": "2.0.0", - "tasks": [{ + "tasks": [ + { "label": "Build osu! (Debug)", "type": "shell", "command": "dotnet", @@ -78,7 +79,8 @@ ], "group": "build", "problemMatcher": "$msCompile" - }, { + }, + { "label": "Build tournament tests (Release)", "type": "shell", "command": "dotnet", @@ -94,6 +96,22 @@ "group": "build", "problemMatcher": "$msCompile" }, + { + "label": "Build benchmarks", + "type": "shell", + "command": "dotnet", + "args": [ + "build", + "--no-restore", + "osu.Game.Benchmarks", + "/p:Configuration=Release", + "/p:GenerateFullPaths=true", + "/m", + "/verbosity:m" + ], + "group": "build", + "problemMatcher": "$msCompile" + }, { "label": "Restore (netcoreapp3.1)", "type": "shell", diff --git a/osu.Game.Benchmarks/Properties/launchSettings.json b/osu.Game.Benchmarks/Properties/launchSettings.json new file mode 100644 index 0000000000..c1868088f9 --- /dev/null +++ b/osu.Game.Benchmarks/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "All Benchmarks": { + "commandName": "Project", + "commandLineArgs": "--filter *" + } + } +} \ No newline at end of file From 7f393c61f8679e4a57847a97a07d6988b1b3a2f4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 8 Jan 2020 21:55:39 +0800 Subject: [PATCH 4940/5608] Add BDN artifacts to gitignore. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index e6b5db5904..732b171f69 100644 --- a/.gitignore +++ b/.gitignore @@ -331,3 +331,6 @@ fastlane/report.xml # inspectcode inspectcodereport.xml inspectcode + +# BenchmarkDotNet +/BenchmarkDotNet.Artifacts From 14289523777302fbcb3aa3c524964f9d43a365af Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 8 Jan 2020 18:59:13 +0300 Subject: [PATCH 4941/5608] Implement CountryFilter component for RankingsOverlay --- .../Online/TestSceneRankingsCountryFilter.cs | 45 ++++ osu.Game/Overlays/Rankings/CountryFilter.cs | 231 ++++++++++++++++++ 2 files changed, 276 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs create mode 100644 osu.Game/Overlays/Rankings/CountryFilter.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs new file mode 100644 index 0000000000..968be62a7c --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.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 System; +using System.Collections.Generic; +using osu.Framework.Bindables; +using osu.Game.Overlays.Rankings; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsCountryFilter : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(CountryFilter), + }; + + public TestSceneRankingsCountryFilter() + { + var countryBindable = new Bindable(); + CountryFilter filter; + + Add(filter = new CountryFilter + { + Country = { BindTarget = countryBindable } + }); + + var country = new Country + { + FlagName = "BY", + FullName = "Belarus" + }; + var unknownCountry = new Country + { + FlagName = "CK", + FullName = "Cook Islands" + }; + + AddStep("Set country", () => countryBindable.Value = country); + AddStep("Set null country", () => countryBindable.Value = null); + AddStep("Set country with no flag", () => countryBindable.Value = unknownCountry); + } + } +} diff --git a/osu.Game/Overlays/Rankings/CountryFilter.cs b/osu.Game/Overlays/Rankings/CountryFilter.cs new file mode 100644 index 0000000000..4a24a440cc --- /dev/null +++ b/osu.Game/Overlays/Rankings/CountryFilter.cs @@ -0,0 +1,231 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Users; +using osu.Game.Users.Drawables; +using osuTK; + +namespace osu.Game.Overlays.Rankings +{ + public class CountryFilter : Container + { + private const int duration = 200; + private const int height = 50; + + public readonly Bindable Country = new Bindable(); + + private readonly Box background; + private readonly CountryPill countryPill; + private readonly Container content; + + public CountryFilter() + { + RelativeSizeAxes = Axes.X; + Child = content = new Container + { + RelativeSizeAxes = Axes.X, + Height = height, + Alpha = 0, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = @"filtered by country:", + Font = OsuFont.GetFont(size: 14) + }, + countryPill = new CountryPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Alpha = 0, + Country = { BindTarget = Country } + } + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.GreySeafoam; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Country.BindValueChanged(onCountryChanged, true); + } + + private void onCountryChanged(ValueChangedEvent country) + { + countryPill.ClearTransforms(); + + if (country.NewValue == null) + { + countryPill.Collapse(); + this.ResizeHeightTo(0, duration, Easing.OutQuint); + content.FadeOut(duration, Easing.OutQuint); + return; + } + + this.ResizeHeightTo(height, duration, Easing.OutQuint); + content.FadeIn(duration, Easing.OutQuint).Finally(_ => countryPill.Expand()); + } + + private class CountryPill : CircularContainer + { + private readonly Box background; + private readonly UpdateableFlag flag; + private readonly OsuSpriteText countryName; + + public readonly Bindable Country = new Bindable(); + + public CountryPill() + { + AutoSizeDuration = duration; + AutoSizeEasing = Easing.OutQuint; + Height = 25; + Masking = true; + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Margin = new MarginPadding { Horizontal = 10 }, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(8, 0), + Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(3, 0), + Children = new Drawable[] + { + flag = new UpdateableFlag + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(22, 15) + }, + countryName = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 14) + } + } + }, + new CloseButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + ClickAction = () => Country.Value = null + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.GreySeafoamDarker; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Country.BindValueChanged(onCountryChanged, true); + } + + public void Expand() + { + AutoSizeAxes = Axes.X; + this.FadeIn(duration, Easing.OutQuint); + } + + public void Collapse() + { + AutoSizeAxes = Axes.None; + this.ResizeWidthTo(0, duration, Easing.OutQuint); + this.FadeOut(duration, Easing.OutQuint); + } + + private void onCountryChanged(ValueChangedEvent country) + { + if (country.NewValue == null) + return; + + flag.Country = country.NewValue; + countryName.Text = country.NewValue.FullName; + } + + private class CloseButton : Container + { + public Action ClickAction; + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AutoSizeAxes = Axes.Both; + Children = new Drawable[] + { + new SpriteIcon + { + Size = new Vector2(8), + Icon = FontAwesome.Solid.Times, + Colour = colours.GreySeafoamLighter, + }, + new HoverClickSounds(), + }; + } + + protected override bool OnClick(ClickEvent e) + { + ClickAction?.Invoke(); + return base.OnClick(e); + } + } + } + } +} From dc64ba8ed81d21aef0c4368f53c5fcfda795161a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 8 Jan 2020 19:22:07 +0300 Subject: [PATCH 4942/5608] Remove unused variable --- osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs index 968be62a7c..9a8ddf9cad 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs @@ -19,9 +19,8 @@ namespace osu.Game.Tests.Visual.Online public TestSceneRankingsCountryFilter() { var countryBindable = new Bindable(); - CountryFilter filter; - Add(filter = new CountryFilter + Add(new CountryFilter { Country = { BindTarget = countryBindable } }); From 1dbae21f981852f878154d73af241d7e44e0073a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 8 Jan 2020 19:40:28 +0300 Subject: [PATCH 4943/5608] Fix crashing test --- osu.Game/Overlays/Rankings/CountryFilter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Rankings/CountryFilter.cs b/osu.Game/Overlays/Rankings/CountryFilter.cs index 4a24a440cc..008214a9a4 100644 --- a/osu.Game/Overlays/Rankings/CountryFilter.cs +++ b/osu.Game/Overlays/Rankings/CountryFilter.cs @@ -86,6 +86,7 @@ namespace osu.Game.Overlays.Rankings private void onCountryChanged(ValueChangedEvent country) { + content.ClearTransforms(); countryPill.ClearTransforms(); if (country.NewValue == null) From a3f7d3c4454ba53e61ef521a23d069c4ec74ebb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 8 Jan 2020 19:55:35 +0100 Subject: [PATCH 4944/5608] Add failing test Add test case demonstrating the lack of update of the metadata display's mods upon setting the Mods property in PlayerLoader. --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 14 +++++++++++++ osu.Game/Screens/Play/PlayerLoader.cs | 20 ++++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index f68f4b8b83..fd3037341b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -146,6 +146,18 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("player mods applied", () => playerMod2.Applied); } + [Test] + public void TestModDisplayChanges() + { + var testMod = new TestMod(); + + AddStep("load player", () => ResetPlayer(true)); + + AddUntilStep("wait for loader to become current", () => loader.IsCurrentScreen()); + AddStep("set test mod in loader", () => loader.Mods.Value = new[] { testMod }); + AddAssert("test mod is displayed", () => (TestMod)loader.DisplayedMods.Single() == testMod); + } + [Test] public void TestMutedNotificationMasterVolume() => addVolumeSteps("master volume", () => audioManager.Volume.Value = 0, null, () => audioManager.Volume.IsDefault); @@ -221,6 +233,8 @@ namespace osu.Game.Tests.Visual.Gameplay public new Task DisposalTask => base.DisposalTask; + public IReadOnlyList DisplayedMods => MetadataInfo.Mods; + public TestPlayerLoader(Func createPlayer) : base(createPlayer) { diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 64fcc48004..f200c8e0ae 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Play private LogoTrackingContainer content; - private BeatmapMetadataDisplay info; + protected BeatmapMetadataDisplay MetadataInfo; private bool hideOverlays; public override bool HideOverlaysOnEnter => hideOverlays; @@ -96,7 +96,7 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, }).WithChildren(new Drawable[] { - info = new BeatmapMetadataDisplay(Beatmap.Value, Mods.Value, content.LogoFacade) + MetadataInfo = new BeatmapMetadataDisplay(Beatmap.Value, Mods.Value, content.LogoFacade) { Alpha = 0, Anchor = Anchor.Centre, @@ -138,7 +138,7 @@ namespace osu.Game.Screens.Play contentIn(); - info.Delay(750).FadeIn(500); + MetadataInfo.Delay(750).FadeIn(500); this.Delay(1800).Schedule(pushWhenLoaded); if (!muteWarningShownOnce.Value) @@ -158,7 +158,7 @@ namespace osu.Game.Screens.Play contentIn(); - info.Loading = true; + MetadataInfo.Loading = true; //we will only be resumed if the player has requested a re-run (see ValidForResume setting above) loadNewPlayer(); @@ -174,7 +174,7 @@ namespace osu.Game.Screens.Play player.RestartCount = restartCount; player.RestartRequested = restartRequested; - LoadTask = LoadComponentAsync(player, _ => info.Loading = false); + LoadTask = LoadComponentAsync(player, _ => MetadataInfo.Loading = false); } private void contentIn() @@ -350,7 +350,7 @@ namespace osu.Game.Screens.Play } } - private class BeatmapMetadataDisplay : Container + protected class BeatmapMetadataDisplay : Container { private class MetadataLine : Container { @@ -379,11 +379,12 @@ namespace osu.Game.Screens.Play } private readonly WorkingBeatmap beatmap; - private readonly IReadOnlyList mods; private readonly Drawable facade; private LoadingAnimation loading; private Sprite backgroundSprite; + public IReadOnlyList Mods { get; } + public bool Loading { set @@ -404,8 +405,9 @@ namespace osu.Game.Screens.Play public BeatmapMetadataDisplay(WorkingBeatmap beatmap, IReadOnlyList mods, Drawable facade) { this.beatmap = beatmap; - this.mods = mods; this.facade = facade; + + Mods = mods; } [BackgroundDependencyLoader] @@ -492,7 +494,7 @@ namespace osu.Game.Screens.Play Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Top = 20 }, - Current = { Value = mods } + Current = { Value = Mods } } }, } From f0fe3bc804738cb518c5234566cfbf511df1b8a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 8 Jan 2020 20:10:43 +0100 Subject: [PATCH 4945/5608] Pass bindable to BeatmapMetadataDisplay It was reported that mods selected in song select would show up during loading of replays which were recorded under a different set of mods. This was caused by BeatmapMetadataDisplay accepting a plain read-only value of the Mods bindable in PlayerLoader.load(), therefore making the mod value assignment in ReplayPlayerLoader.OnEntering() have no effect on that component. To resolve this issue, make BeatmapMetadataDisplay accept the higher-level bindable, bind to it locally and pass it down the hierarchy to ModDisplay. --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 2 +- osu.Game/Screens/Play/PlayerLoader.cs | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index fd3037341b..587281ef11 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -233,7 +233,7 @@ namespace osu.Game.Tests.Visual.Gameplay public new Task DisposalTask => base.DisposalTask; - public IReadOnlyList DisplayedMods => MetadataInfo.Mods; + public IReadOnlyList DisplayedMods => MetadataInfo.Mods.Value; public TestPlayerLoader(Func createPlayer) : base(createPlayer) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index f200c8e0ae..f37faac988 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -96,7 +96,7 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, }).WithChildren(new Drawable[] { - MetadataInfo = new BeatmapMetadataDisplay(Beatmap.Value, Mods.Value, content.LogoFacade) + MetadataInfo = new BeatmapMetadataDisplay(Beatmap.Value, Mods, content.LogoFacade) { Alpha = 0, Anchor = Anchor.Centre, @@ -379,11 +379,12 @@ namespace osu.Game.Screens.Play } private readonly WorkingBeatmap beatmap; + private readonly Bindable> mods; private readonly Drawable facade; private LoadingAnimation loading; private Sprite backgroundSprite; - public IReadOnlyList Mods { get; } + public IBindable> Mods => mods; public bool Loading { @@ -402,12 +403,13 @@ namespace osu.Game.Screens.Play } } - public BeatmapMetadataDisplay(WorkingBeatmap beatmap, IReadOnlyList mods, Drawable facade) + public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Bindable> mods, Drawable facade) { this.beatmap = beatmap; this.facade = facade; - Mods = mods; + this.mods = new Bindable>(); + this.mods.BindTo(mods); } [BackgroundDependencyLoader] @@ -494,7 +496,7 @@ namespace osu.Game.Screens.Play Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Top = 20 }, - Current = { Value = Mods } + Current = mods } }, } From 34d8740ec430215a5bcf7caff3ace0669de7b265 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Wed, 8 Jan 2020 20:21:13 +0100 Subject: [PATCH 4946/5608] Remove remaining usage of osuTK.MathHelper --- .../Objects/Drawables/DrawableRepeatPoint.cs | 3 ++- .../Objects/Drawables/Pieces/SnakingSliderBody.cs | 6 +++++- .../Objects/Drawables/Pieces/SpinnerDisc.cs | 3 ++- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 3 ++- osu.Game/Graphics/Cursor/MenuCursor.cs | 3 ++- osu.Game/Screens/Menu/LogoVisualisation.cs | 5 +++-- 6 files changed, 16 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index b81d94a673..94fa0272f8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -13,6 +13,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osu.Game.Rulesets.Scoring; using osuTK; using osu.Game.Skinning; +using osu.Framework.Utils; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -121,7 +122,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables break; } - float aimRotation = MathHelper.RadiansToDegrees(MathF.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X)); + float aimRotation = MathUtils.RadiansToDegrees(MathF.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X)); while (Math.Abs(aimRotation - Rotation) > 180) aimRotation += aimRotation < Rotation ? 360 : -360; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index 8a8668d6af..765b3ef456 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -125,7 +125,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private void setRange(double p0, double p1) { if (p0 > p1) - MathHelper.Swap(ref p0, ref p1); + { + double temp = p0; + p0 = p1; + p1 = temp; + } if (SnakedStart == p0 && SnakedEnd == p1) return; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index c45e98cc76..e3dd2b1b4f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -8,6 +8,7 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osuTK; using osuTK.Graphics; +using osu.Framework.Utils; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { @@ -93,7 +94,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { base.Update(); - var thisAngle = -(float)MathHelper.RadiansToDegrees(Math.Atan2(mousePosition.X - DrawSize.X / 2, mousePosition.Y - DrawSize.Y / 2)); + var thisAngle = -MathUtils.RadiansToDegrees(MathF.Atan2(mousePosition.X - DrawSize.X / 2, mousePosition.Y - DrawSize.Y / 2)); bool validAndTracking = tracking && spinner.StartTime <= Time.Current && spinner.EndTime > Time.Current; diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index b1b27278fe..c46634e72f 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics; using osu.Game.IO; using osu.Game.Storyboards; using osu.Game.Beatmaps.Legacy; +using osu.Framework.Utils; namespace osu.Game.Beatmaps.Formats { @@ -190,7 +191,7 @@ namespace osu.Game.Beatmaps.Formats { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; - timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue)); + timelineGroup?.Rotation.Add(easing, startTime, endTime, MathUtils.RadiansToDegrees(startValue), MathUtils.RadiansToDegrees(endValue)); break; } diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 5a83d8e4ce..170ea63059 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -14,6 +14,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Events; using osuTK.Input; +using osu.Framework.Utils; namespace osu.Game.Graphics.Cursor { @@ -55,7 +56,7 @@ namespace osu.Game.Graphics.Cursor if (dragRotationState == DragRotationState.Rotating && distance > 0) { Vector2 offset = e.MousePosition - positionMouseDown; - float degrees = (float)MathHelper.RadiansToDegrees(Math.Atan2(-offset.X, offset.Y)) + 24.3f; + float degrees = MathUtils.RadiansToDegrees(MathF.Atan2(-offset.X, offset.Y)) + 24.3f; // Always rotate in the direction of least distance float diff = (degrees - activeCursor.Rotation) % 360; diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 1a625f8d83..8fc07f5989 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -19,6 +19,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Utils; namespace osu.Game.Screens.Menu { @@ -205,13 +206,13 @@ namespace osu.Game.Screens.Menu if (audioData[i] < amplitude_dead_zone) continue; - float rotation = MathHelper.DegreesToRadians(i / (float)bars_per_visualiser * 360 + j * 360 / visualiser_rounds); + float rotation = MathUtils.DegreesToRadians(i / (float)bars_per_visualiser * 360 + j * 360 / visualiser_rounds); float rotationCos = MathF.Cos(rotation); float rotationSin = MathF.Sin(rotation); //taking the cos and sin to the 0..1 range var barPosition = new Vector2(rotationCos / 2 + 0.5f, rotationSin / 2 + 0.5f) * size; - var barSize = new Vector2(size * (float)Math.Sqrt(2 * (1 - Math.Cos(MathHelper.DegreesToRadians(360f / bars_per_visualiser)))) / 2f, bar_length * audioData[i]); + var barSize = new Vector2(size * MathF.Sqrt(2 * (1 - MathF.Cos(MathUtils.DegreesToRadians(360f / bars_per_visualiser)))) / 2f, bar_length * audioData[i]); //The distance between the position and the sides of the bar. var bottomOffset = new Vector2(-rotationSin * barSize.X / 2, rotationCos * barSize.X / 2); //The distance between the bottom side of the bar and the top side. From ed2bf5154ddf87ac94702d5fa1284495701d2af4 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Wed, 8 Jan 2020 20:46:17 +0100 Subject: [PATCH 4947/5608] Use tuple deconstruction to swap values --- .../Objects/Drawables/Pieces/SnakingSliderBody.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index 765b3ef456..e24fa865ad 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -125,11 +125,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private void setRange(double p0, double p1) { if (p0 > p1) - { - double temp = p0; - p0 = p1; - p1 = temp; - } + (p0, p1) = (p1, p0); if (SnakedStart == p0 && SnakedEnd == p1) return; From 6cb763a019b3ecc34d47d683390a5b476ee94334 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 9 Jan 2020 00:06:28 +0300 Subject: [PATCH 4948/5608] Improve animations --- osu.Game/Overlays/Rankings/CountryFilter.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Rankings/CountryFilter.cs b/osu.Game/Overlays/Rankings/CountryFilter.cs index 008214a9a4..5452bc9327 100644 --- a/osu.Game/Overlays/Rankings/CountryFilter.cs +++ b/osu.Game/Overlays/Rankings/CountryFilter.cs @@ -86,9 +86,6 @@ namespace osu.Game.Overlays.Rankings private void onCountryChanged(ValueChangedEvent country) { - content.ClearTransforms(); - countryPill.ClearTransforms(); - if (country.NewValue == null) { countryPill.Collapse(); @@ -98,7 +95,8 @@ namespace osu.Game.Overlays.Rankings } this.ResizeHeightTo(height, duration, Easing.OutQuint); - content.FadeIn(duration, Easing.OutQuint).Finally(_ => countryPill.Expand()); + content.FadeIn(duration, Easing.OutQuint); + countryPill.Expand(); } private class CountryPill : CircularContainer @@ -181,12 +179,14 @@ namespace osu.Game.Overlays.Rankings public void Expand() { + ClearTransforms(); AutoSizeAxes = Axes.X; this.FadeIn(duration, Easing.OutQuint); } public void Collapse() { + ClearTransforms(); AutoSizeAxes = Axes.None; this.ResizeWidthTo(0, duration, Easing.OutQuint); this.FadeOut(duration, Easing.OutQuint); From 29c4ae68d91e8bb06f6197eb7da2ee24dc2725bb Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 9 Jan 2020 00:14:29 +0300 Subject: [PATCH 4949/5608] Add some content to test scene for better visual representation --- .../Online/TestSceneRankingsCountryFilter.cs | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs index 9a8ddf9cad..360bb81715 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs @@ -4,8 +4,13 @@ using System; using System.Collections.Generic; using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Rankings; using osu.Game.Users; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osuTK.Graphics; +using osu.Game.Graphics.Sprites; namespace osu.Game.Tests.Visual.Online { @@ -20,9 +25,35 @@ namespace osu.Game.Tests.Visual.Online { var countryBindable = new Bindable(); - Add(new CountryFilter + AddRange(new Drawable[] { - Country = { BindTarget = countryBindable } + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new CountryFilter + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Country = { BindTarget = countryBindable } + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Some content", + Margin = new MarginPadding { Vertical = 20 } + } + } + } }); var country = new Country From 0d9fb065da462b36074c9b292cc50c001b39236a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 9 Jan 2020 00:27:22 +0300 Subject: [PATCH 4950/5608] Move CountryPill to it's own class --- .../Online/TestSceneRankingsCountryFilter.cs | 1 + osu.Game/Overlays/Rankings/CountryFilter.cs | 135 ---------------- osu.Game/Overlays/Rankings/CountryPill.cs | 149 ++++++++++++++++++ 3 files changed, 150 insertions(+), 135 deletions(-) create mode 100644 osu.Game/Overlays/Rankings/CountryPill.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs index 360bb81715..3d38710b59 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs @@ -19,6 +19,7 @@ namespace osu.Game.Tests.Visual.Online public override IReadOnlyList RequiredTypes => new[] { typeof(CountryFilter), + typeof(CountryPill) }; public TestSceneRankingsCountryFilter() diff --git a/osu.Game/Overlays/Rankings/CountryFilter.cs b/osu.Game/Overlays/Rankings/CountryFilter.cs index 5452bc9327..7cd56100db 100644 --- a/osu.Game/Overlays/Rankings/CountryFilter.cs +++ b/osu.Game/Overlays/Rankings/CountryFilter.cs @@ -1,19 +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 osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Users; -using osu.Game.Users.Drawables; using osuTK; namespace osu.Game.Overlays.Rankings @@ -98,135 +93,5 @@ namespace osu.Game.Overlays.Rankings content.FadeIn(duration, Easing.OutQuint); countryPill.Expand(); } - - private class CountryPill : CircularContainer - { - private readonly Box background; - private readonly UpdateableFlag flag; - private readonly OsuSpriteText countryName; - - public readonly Bindable Country = new Bindable(); - - public CountryPill() - { - AutoSizeDuration = duration; - AutoSizeEasing = Easing.OutQuint; - Height = 25; - Masking = true; - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both - }, - new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Margin = new MarginPadding { Horizontal = 10 }, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(8, 0), - Children = new Drawable[] - { - new FillFlowContainer - { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(3, 0), - Children = new Drawable[] - { - flag = new UpdateableFlag - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(22, 15) - }, - countryName = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14) - } - } - }, - new CloseButton - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - ClickAction = () => Country.Value = null - } - } - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = colours.GreySeafoamDarker; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - Country.BindValueChanged(onCountryChanged, true); - } - - public void Expand() - { - ClearTransforms(); - AutoSizeAxes = Axes.X; - this.FadeIn(duration, Easing.OutQuint); - } - - public void Collapse() - { - ClearTransforms(); - AutoSizeAxes = Axes.None; - this.ResizeWidthTo(0, duration, Easing.OutQuint); - this.FadeOut(duration, Easing.OutQuint); - } - - private void onCountryChanged(ValueChangedEvent country) - { - if (country.NewValue == null) - return; - - flag.Country = country.NewValue; - countryName.Text = country.NewValue.FullName; - } - - private class CloseButton : Container - { - public Action ClickAction; - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - AutoSizeAxes = Axes.Both; - Children = new Drawable[] - { - new SpriteIcon - { - Size = new Vector2(8), - Icon = FontAwesome.Solid.Times, - Colour = colours.GreySeafoamLighter, - }, - new HoverClickSounds(), - }; - } - - protected override bool OnClick(ClickEvent e) - { - ClickAction?.Invoke(); - return base.OnClick(e); - } - } - } } } diff --git a/osu.Game/Overlays/Rankings/CountryPill.cs b/osu.Game/Overlays/Rankings/CountryPill.cs new file mode 100644 index 0000000000..65fce3b909 --- /dev/null +++ b/osu.Game/Overlays/Rankings/CountryPill.cs @@ -0,0 +1,149 @@ +// 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.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Users; +using osu.Game.Users.Drawables; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Rankings +{ + public class CountryPill : CircularContainer + { + private const int duration = 200; + + private readonly Box background; + private readonly UpdateableFlag flag; + private readonly OsuSpriteText countryName; + + public readonly Bindable Country = new Bindable(); + + public CountryPill() + { + AutoSizeDuration = duration; + AutoSizeEasing = Easing.OutQuint; + Height = 25; + Masking = true; + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Margin = new MarginPadding { Horizontal = 10 }, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(8, 0), + Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(3, 0), + Children = new Drawable[] + { + flag = new UpdateableFlag + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(22, 15) + }, + countryName = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 14) + } + } + }, + new CloseButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Action = () => Country.Value = null + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.GreySeafoamDarker; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Country.BindValueChanged(onCountryChanged, true); + } + + public void Expand() + { + ClearTransforms(); + AutoSizeAxes = Axes.X; + this.FadeIn(duration, Easing.OutQuint); + } + + public void Collapse() + { + ClearTransforms(); + AutoSizeAxes = Axes.None; + this.ResizeWidthTo(0, duration, Easing.OutQuint); + this.FadeOut(duration, Easing.OutQuint); + } + + private void onCountryChanged(ValueChangedEvent country) + { + if (country.NewValue == null) + return; + + flag.Country = country.NewValue; + countryName.Text = country.NewValue.FullName; + } + + private class CloseButton : OsuHoverContainer + { + private readonly SpriteIcon icon; + + protected override IEnumerable EffectTargets => new[] { icon }; + + public CloseButton() + { + AutoSizeAxes = Axes.Both; + Add(icon = new SpriteIcon + { + Size = new Vector2(8), + Icon = FontAwesome.Solid.Times + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + IdleColour = colours.GreySeafoamLighter; + HoverColour = Color4.White; + } + } + } +} From 91735ff367f42a114b04776a728c010d190288ea Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 9 Jan 2020 13:43:44 +0900 Subject: [PATCH 4951/5608] Update MathUtils namespace usages --- osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs | 2 +- osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs | 2 +- .../Replays/CatchFramedReplayInputHandler.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs | 2 +- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs | 2 +- .../Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs | 2 +- osu.Game.Rulesets.Mania/UI/HitExplosion.cs | 2 +- osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs | 2 +- .../TestSceneSliderSelectionBlueprint.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs | 2 +- .../Objects/Drawables/Pieces/SpinnerSpmCounter.cs | 2 +- osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs | 2 +- osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs | 2 +- osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs | 2 +- osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs | 2 +- osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs | 2 +- osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs | 2 +- .../Visual/Editor/TestSceneZoomableScrollContainer.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs | 2 +- .../Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs | 2 +- osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs | 2 +- .../Visual/Online/TestSceneBeatmapSetOverlayDetails.cs | 2 +- .../Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs | 2 +- osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs | 2 +- osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs | 2 +- osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs | 2 +- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 2 +- osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs | 2 +- .../Visual/UserInterface/TestSceneLogoTrackingContainer.cs | 2 +- .../Visual/UserInterface/TestSceneNotificationOverlay.cs | 2 +- .../Visual/UserInterface/TestSceneNowPlayingOverlay.cs | 2 +- .../Visual/UserInterface/TestSceneToolbarRulesetSelector.cs | 2 +- .../Components/TestSceneMatchScoreDisplay.cs | 2 +- .../Screens/Drawings/Components/VisualiserContainer.cs | 2 +- osu.Game/Graphics/Backgrounds/Triangles.cs | 2 +- osu.Game/Graphics/Containers/LogoTrackingContainer.cs | 2 +- osu.Game/Graphics/Containers/ParallaxContainer.cs | 2 +- osu.Game/Graphics/UserInterface/OsuTabControl.cs | 2 +- osu.Game/Graphics/UserInterface/StarCounter.cs | 2 +- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 2 +- osu.Game/Overlays/MedalOverlay.cs | 2 +- osu.Game/Overlays/MusicController.cs | 2 +- osu.Game/Overlays/Volume/VolumeMeter.cs | 2 +- osu.Game/Rulesets/Objects/BarLineGenerator.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 2 +- osu.Game/Rulesets/Objects/SliderPath.cs | 2 +- osu.Game/Rulesets/Scoring/HealthProcessor.cs | 2 +- osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs | 2 +- .../Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs | 2 +- osu.Game/Screens/Edit/EditorClock.cs | 2 +- osu.Game/Screens/Loader.cs | 2 +- osu.Game/Screens/Menu/IntroScreen.cs | 2 +- osu.Game/Screens/Menu/IntroTriangles.cs | 2 +- osu.Game/Screens/Menu/OsuLogo.cs | 2 +- osu.Game/Screens/Play/FailAnimation.cs | 2 +- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 2 +- osu.Game/Screens/Play/SkipOverlay.cs | 2 +- osu.Game/Screens/Play/SongProgressBar.cs | 2 +- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs | 2 +- osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs | 2 +- osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs | 2 +- 77 files changed, 77 insertions(+), 77 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index 493ac7ae39..f4749be370 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; using NUnit.Framework; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Rulesets.Catch.Mods; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 958cd19d50..53a018c9f4 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 6c8515eb90..4649dcae90 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -3,7 +3,7 @@ using System; using System.Linq; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Replays; using osu.Game.Rulesets.Catch.Beatmaps; diff --git a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs index 22532bc9ec..f122588a2b 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using osu.Framework.Input.StateChanges; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Replays; using osu.Game.Rulesets.Replays; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 2d6ce02e45..0c8c483048 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -7,7 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index 12865385b6..d0ff1fab43 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using NUnit.Framework; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 1a77a4944b..d904474815 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -5,7 +5,7 @@ using osu.Game.Rulesets.Mania.Objects; using System; using System.Linq; using System.Collections.Generic; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 9565ac8994..315ef96e49 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.MathUtils; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs index 9275371a61..b12d3a7a70 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs @@ -4,7 +4,7 @@ using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Sprites; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Beatmaps; diff --git a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs index ccbff226a9..35de47e208 100644 --- a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs @@ -5,7 +5,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index 450f7de6d2..cd3daf18a9 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using NUnit.Framework; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Tests.Beatmaps; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index c9b3d08a22..4af4d5f966 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Beatmaps; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs index 863d0eda09..d692be89b2 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Diagnostics; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs index 013920684c..5dd2bd18a8 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSelectionBlueprint.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using NUnit.Framework; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index bd9d948782..5cf571d961 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -4,7 +4,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 778c2f7d43..ac20407ed2 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -8,7 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Events; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index b81d94a673..2571ef3a70 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -7,7 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs index 97a7b98c5b..80ab03c45c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index 2686ba4fd2..4cb2cd6539 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osuTK; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Osu.Objects; using System; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs index c6ac1dd346..b42e9ac187 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using osu.Framework.Input.StateChanges; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Replays; using osu.Game.Rulesets.Replays; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs index d41135ca69..21df49d80b 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBody.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index 28f5d4d301..f23fd6d3f9 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using NUnit.Framework; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Tests.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index b2c8c7feda..c01eef5252 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -7,7 +7,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 338fd9e20f..5806c90115 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -4,7 +4,7 @@ using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osuTK.Graphics; diff --git a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs index eec52669ff..244e37f017 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs @@ -4,7 +4,7 @@ using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Beatmaps; diff --git a/osu.Game.Tests/Visual/Editor/TestSceneZoomableScrollContainer.cs b/osu.Game.Tests/Visual/Editor/TestSceneZoomableScrollContainer.cs index da8702209c..fd248abbc9 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneZoomableScrollContainer.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneZoomableScrollContainer.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Shapes; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Testing; using osu.Game.Graphics; using osu.Game.Graphics.Cursor; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs index e3688c276f..72fc6d8bd2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs @@ -6,7 +6,7 @@ using osu.Game.Rulesets.Objects; using System; using System.Collections.Generic; using osu.Game.Rulesets.Judgements; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index 36235a4418..46f62b9541 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -10,7 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index 5336c720a1..78c3b22fb9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -7,7 +7,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index ad747e88e1..e7b3e007fc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Screens.Play; using osuTK.Input; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs index 0150c6ea74..563d6be0da 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs @@ -5,7 +5,7 @@ using System.Diagnostics; using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Osu; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index f68f4b8b83..a1eb416043 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -12,7 +12,7 @@ using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Screens; using osu.Game.Configuration; using osu.Game.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs index 080a287b48..ffd6f55b53 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs @@ -4,7 +4,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play.HUD; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index af21007efe..9a217ae416 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Timing; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Play; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs index 68ad0b42b4..1e3e06ce7a 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs @@ -7,7 +7,7 @@ using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Match.Components; using osu.Framework.Graphics; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Audio; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs index 96c0c59695..990e0a166b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Overlays.BeatmapSet; using osu.Game.Screens.Select.Details; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs index 80fad44593..2b572c1f6c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs @@ -8,7 +8,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Overlays.BeatmapSet; using osu.Game.Screens.Select.Details; diff --git a/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs b/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs index 16e47c5df9..c98b65ded7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; using osu.Game.Overlays.Chat.Tabs; diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index b19f2dbf31..1b136d9e41 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Rulesets.Osu.Mods; diff --git a/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs index 4702d24125..f14c75084f 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Game.Overlays.Comments; -using osu.Framework.MathUtils; +using osu.Framework.Utils; namespace osu.Game.Tests.Visual.Online { diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 00fa95bedc..eb812f5d5a 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -11,7 +11,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Extensions; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Beatmaps; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs index e95f4c09c6..d1dde4664a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Sprites; using osuTK; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs index 54876dbbda..4e394b5ed8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Testing; using osu.Game.Graphics.Containers; using osu.Game.Screens.Menu; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs index 35e5f9719c..f8ace73168 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs @@ -8,7 +8,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index 330ccecd54..2ea9aec50a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -4,7 +4,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Overlays; using osu.Game.Rulesets.Osu; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs index 0da256855a..e6589fa823 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Rulesets; namespace osu.Game.Tests.Visual.UserInterface diff --git a/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs index 72d9eb0e07..77119f7a60 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs @@ -3,7 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Screens.Gameplay.Components; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs index 1cd942b987..f21f5c9460 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.MathUtils; +using osu.Framework.Utils; namespace osu.Game.Tournament.Screens.Drawings.Components { diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index af492bacc9..b9c7b26e3e 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osuTK; using osuTK.Graphics; using System; diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index 23015e8bf5..dadd7d5240 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -4,7 +4,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Screens.Menu; using osuTK; diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index bf743b90ed..4cd3934cde 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -9,7 +9,7 @@ using osuTK; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Configuration; -using osu.Framework.MathUtils; +using osu.Framework.Utils; namespace osu.Game.Graphics.Containers { diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index ed8904db7e..6a7998d5fb 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -15,7 +15,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Graphics/UserInterface/StarCounter.cs b/osu.Game/Graphics/UserInterface/StarCounter.cs index 3ee572602b..586cd2ce84 100644 --- a/osu.Game/Graphics/UserInterface/StarCounter.cs +++ b/osu.Game/Graphics/UserInterface/StarCounter.cs @@ -4,7 +4,7 @@ using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using System; using System.Linq; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index e530ff5489..7067e02cd2 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -9,7 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 15aec1f17c..aa28b0659d 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -21,7 +21,7 @@ using osu.Framework.Graphics.Shapes; using System; using osu.Framework.Graphics.Effects; using osu.Framework.Input.Events; -using osu.Framework.MathUtils; +using osu.Framework.Utils; namespace osu.Game.Overlays { diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 270e90dca5..3c0f6468bc 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -8,7 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Input.Bindings; diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index da696e0fdd..7effd290e6 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK; diff --git a/osu.Game/Rulesets/Objects/BarLineGenerator.cs b/osu.Game/Rulesets/Objects/BarLineGenerator.cs index 99672240e2..5588e9c0b7 100644 --- a/osu.Game/Rulesets/Objects/BarLineGenerator.cs +++ b/osu.Game/Rulesets/Objects/BarLineGenerator.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 3eab4555d1..1fc51d2ce8 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -10,7 +10,7 @@ using osu.Game.Beatmaps.Formats; using osu.Game.Audio; using System.Linq; using JetBrains.Annotations; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps.Legacy; namespace osu.Game.Rulesets.Objects.Legacy diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 293138097f..62a5b6f0b5 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -7,7 +7,7 @@ using System.Linq; using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Framework.Caching; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index 0c6b3f67b4..45edc0f4a3 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Bindables; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Rulesets.Judgements; namespace osu.Game.Rulesets.Scoring diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 095985e9d1..980a127cf4 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -4,7 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Configuration; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index 54922fec5e..9aa527667b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Transforms; using osu.Framework.Input.Events; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Graphics.Containers; using osuTK; diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 93a5f19121..e5e47507f3 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -3,7 +3,7 @@ using System; using System.Linq; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index 41ee01be20..289413c65a 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -6,7 +6,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shaders; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Screens.Menu; using osuTK; using osu.Framework.Screens; diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index df83e98494..26455b1dbd 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -7,7 +7,7 @@ using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Configuration; diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index c86f1393a4..50cfe23481 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -13,7 +13,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Video; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Timing; using osu.Game.Graphics; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 534400e720..33b6ee8025 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Events; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; diff --git a/osu.Game/Screens/Play/FailAnimation.cs b/osu.Game/Screens/Play/FailAnimation.cs index a3caffb620..54c644c999 100644 --- a/osu.Game/Screens/Play/FailAnimation.cs +++ b/osu.Game/Screens/Play/FailAnimation.cs @@ -10,7 +10,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; using osu.Framework.Graphics; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Drawables; using osuTK; diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 640224c057..7946e6d322 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 1a5ed20953..772d326c7f 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -19,7 +19,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Containers; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Input.Bindings; namespace osu.Game.Screens.Play diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index cdf495e257..9df36c9c2b 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Framework.Threading; namespace osu.Game.Screens.Play diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 4acc619753..bf2382c4ae 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -9,7 +9,7 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Configuration; using osuTK.Input; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index d54c13c7db..451708c1cf 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -13,7 +13,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index 6118191302..121491d6ca 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -10,7 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Graphics; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index a076bb54df..ced3b9c1b6 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -8,7 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Textures; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; namespace osu.Game.Storyboards.Drawables diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index ac795b3349..c0da0e9c0e 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -8,7 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.MathUtils; +using osu.Framework.Utils; using osu.Game.Beatmaps; namespace osu.Game.Storyboards.Drawables From dde843268466c82ee02dcb369e7c4afaaf787f90 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 9 Jan 2020 13:43:57 +0900 Subject: [PATCH 4952/5608] Fix exception through due to multiple binds --- osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 1ab3a5b533..3ced9ee753 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -49,9 +49,12 @@ namespace osu.Game.Screens.Backgrounds Beatmap = beatmap; InternalChild = dimmable = CreateFadeContainer(); + dimmable.EnableUserDim.BindTo(EnableUserDim); dimmable.IsBreakTime.BindTo(IsBreakTime); dimmable.BlurAmount.BindTo(BlurAmount); + + StoryboardReplacesBackground.BindTo(dimmable.StoryboardReplacesBackground); } [BackgroundDependencyLoader] @@ -99,7 +102,6 @@ namespace osu.Game.Screens.Backgrounds b.Depth = newDepth; dimmable.Background = Background = b; - StoryboardReplacesBackground.BindTo(dimmable.StoryboardReplacesBackground); } public override bool Equals(BackgroundScreen other) From b2db2ee259f1661c2a6576a4aa247bff27b642fe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 9 Jan 2020 15:35:54 +0900 Subject: [PATCH 4953/5608] Update package version --- 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 e1e6f2e478..a78148f36e 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 b497133e62..77d41566ca 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 edd35b0774..b551a1442f 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 26c80e35fbdeb7af8ecdb144628b863e3b1d25ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Jan 2020 17:17:08 +0800 Subject: [PATCH 4954/5608] Fix missing namespace --- osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index 289c01fbf3..d2ac1bf079 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -15,6 +15,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Leaderboards; +using osu.Game.Online.Placeholders; using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Scoring; From ffa0cf2d44174c870c5c0dc2173b73e9ba496a89 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Jan 2020 17:28:48 +0800 Subject: [PATCH 4955/5608] Add comment detailing why this is requried --- osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs index aca3768540..bdc3cd4c49 100644 --- a/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs +++ b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs @@ -47,6 +47,7 @@ namespace osu.Game.Graphics.UserInterface { switch (e) { + // blocking scroll can cause weird behaviour when this layer is used within a ScrollContainer. case ScrollEvent _: return false; } From 6a2bcbcef81a986f3f9823ae29957206c0b306b3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 9 Jan 2020 18:47:00 +0900 Subject: [PATCH 4956/5608] Bump version --- 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 a78148f36e..fde58ec489 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 77d41566ca..04d0b580da 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 b551a1442f..50aabd636a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 87645f6a41c443f5c78a9fb16a338130be52df3d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Jan 2020 01:13:42 +0800 Subject: [PATCH 4957/5608] Remove excess namespace specification --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 662fd15183..96b18f2d80 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -13,7 +13,6 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osu.Game.Rulesets.Scoring; using osuTK; using osu.Game.Skinning; -using osu.Framework.Utils; namespace osu.Game.Rulesets.Osu.Objects.Drawables { From 14829837c467c07c2eae8445e9e1c7dfce262006 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Jan 2020 01:38:03 +0800 Subject: [PATCH 4958/5608] Update namespace specifications --- .../Visual/UserInterface/TestSceneDeleteLocalScore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index d2ac1bf079..1e5e26e4c5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -8,9 +8,9 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics.Cursor; -using osu.Framework.MathUtils; using osu.Framework.Platform; using osu.Framework.Testing; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; From 20f426cda0348a8ad4f45cd7b75b0d3ce8a91951 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 8 Jan 2020 22:06:18 +0800 Subject: [PATCH 4959/5608] Add beatmap parsing as sample benchmark. --- .../BenchmarkBeatmapParsing.cs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs diff --git a/osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs b/osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs new file mode 100644 index 0000000000..394fd75488 --- /dev/null +++ b/osu.Game.Benchmarks/BenchmarkBeatmapParsing.cs @@ -0,0 +1,37 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.IO; +using BenchmarkDotNet.Attributes; +using osu.Framework.IO.Stores; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Formats; +using osu.Game.IO; +using osu.Game.IO.Archives; +using osu.Game.Resources; + +namespace osu.Game.Benchmarks +{ + public class BenchmarkBeatmapParsing : BenchmarkTest + { + private readonly MemoryStream beatmapStream = new MemoryStream(); + + public override void SetUp() + { + using (var resources = new DllResourceStore(OsuResources.ResourceAssembly)) + using (var archive = resources.GetStream("Beatmaps/241526 Soleily - Renatus.osz")) + using (var reader = new ZipArchiveReader(archive)) + reader.GetStream("Soleily - Renatus (Gamu) [Insane].osu").CopyTo(beatmapStream); + } + + [Benchmark] + public Beatmap BenchmarkBundledBeatmap() + { + beatmapStream.Seek(0, SeekOrigin.Begin); + var reader = new LineBufferedReader(beatmapStream); // no disposal + + var decoder = Decoder.GetDecoder(reader); + return decoder.Decode(reader); + } + } +} From c4131e01da7341984450a11d8e5349f02e2c0d58 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 10 Jan 2020 20:20:44 +0800 Subject: [PATCH 4960/5608] Downgrade NUnit for now. --- osu.Game.Benchmarks/osu.Game.Benchmarks.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index 3281fcc855..f2e1c0ec3b 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -9,7 +9,7 @@ - + From f65f030e79ff6756fe11156311e1bceaf95720f0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 10 Jan 2020 15:48:54 +0300 Subject: [PATCH 4961/5608] Implement GetSpotlightsRequest --- .../API/Requests/GetSpotlightsRequest.cs | 13 +++++++ .../API/Requests/Responses/APISpotlight.cs | 34 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 osu.Game/Online/API/Requests/GetSpotlightsRequest.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APISpotlight.cs diff --git a/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs b/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs new file mode 100644 index 0000000000..7a6a988c09 --- /dev/null +++ b/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs @@ -0,0 +1,13 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Online.API.Requests +{ + public class GetSpotlightsRequest : APIRequest> + { + protected override string Target => "spotlights"; + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APISpotlight.cs b/osu.Game/Online/API/Requests/Responses/APISpotlight.cs new file mode 100644 index 0000000000..210ef04dac --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APISpotlight.cs @@ -0,0 +1,34 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using Newtonsoft.Json; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APISpotlight + { + [JsonProperty("id")] + public int Id; + + [JsonProperty("name")] + public string Name; + + [JsonProperty("type")] + public string Type; + + [JsonProperty("mode_specific")] + public bool ModeSpecific; + + [JsonProperty(@"start_date")] + public DateTimeOffset StartDate; + + [JsonProperty(@"end_date")] + public DateTimeOffset EndDate; + + [JsonProperty(@"participant_count")] + public int? ParticipiantCount; + + public override string ToString() => Name; + } +} From 08fb68ddfeddb891b2ddc9972544a0bf6f2bff68 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 10 Jan 2020 16:28:52 +0300 Subject: [PATCH 4962/5608] Fix incorrect return type for spotlight request --- osu.Game/Online/API/Requests/GetSpotlightsRequest.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs b/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs index 7a6a988c09..d5b03e52e2 100644 --- a/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs +++ b/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs @@ -2,12 +2,19 @@ // 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 GetSpotlightsRequest : APIRequest> + public class GetSpotlightsRequest : APIRequest { protected override string Target => "spotlights"; } + + public class SpotlightsArray + { + [JsonProperty("spotlights")] + public List Spotlights; + } } From d48b161662ec0058d8f1aed526bb5fa1d9d1af50 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 10 Jan 2020 16:33:00 +0300 Subject: [PATCH 4963/5608] Implement basic SpotlightSelector component --- .../TestSceneRankingsSpotlightSelector.cs | 28 ++++++++ .../Overlays/Rankings/SpotlightSelector.cs | 67 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs create mode 100644 osu.Game/Overlays/Rankings/SpotlightSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs new file mode 100644 index 0000000000..9320213844 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs @@ -0,0 +1,28 @@ +// 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.Game.Overlays.Rankings; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsSpotlightSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(SpotlightSelector), + }; + + protected override bool UseOnlineAPI => true; + + public TestSceneRankingsSpotlightSelector() + { + SpotlightSelector selector; + + Add(selector = new SpotlightSelector()); + + AddStep("Fetch spotlights", selector.FetchSpotlights); + } + } +} diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs new file mode 100644 index 0000000000..95bcc10631 --- /dev/null +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -0,0 +1,67 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Overlays.Rankings +{ + public class SpotlightSelector : Container + { + private readonly Box background; + private readonly OsuDropdown dropdown; + private readonly DimmedLoadingLayer loading; + + [Resolved] + private IAPIProvider api { get; set; } + + public SpotlightSelector() + { + RelativeSizeAxes = Axes.X; + Height = 200; + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + dropdown = new OsuDropdown + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Width = 0.8f, + Margin = new MarginPadding { Top = 10 } + }, + loading = new DimmedLoadingLayer(), + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.GreySeafoam; + dropdown.AccentColour = colours.GreySeafoamDarker; + } + + public void FetchSpotlights() + { + loading.Show(); + + var request = new GetSpotlightsRequest(); + request.Success += response => + { + dropdown.Items = response.Spotlights; + loading.Hide(); + }; + api.Queue(request); + } + } +} From 474d7e92d92ef7a20dc07ee4a75cb2e62b5bd2e2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 10 Jan 2020 16:41:17 +0300 Subject: [PATCH 4964/5608] Fix incorrect dropdown menu height --- osu.Game/Overlays/Rankings/SpotlightSelector.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs index 95bcc10631..482db10796 100644 --- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Rankings public class SpotlightSelector : Container { private readonly Box background; - private readonly OsuDropdown dropdown; + private readonly SpotlightsDropdown dropdown; private readonly DimmedLoadingLayer loading; [Resolved] @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Rankings { RelativeSizeAxes = Axes.Both, }, - dropdown = new OsuDropdown + dropdown = new SpotlightsDropdown { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -63,5 +63,10 @@ namespace osu.Game.Overlays.Rankings }; api.Queue(request); } + + private class SpotlightsDropdown : OsuDropdown + { + protected override DropdownMenu CreateMenu() => base.CreateMenu().With(menu => menu.MaxHeight = 400); + } } } From 2e627f4b7c4f52d827941399cf67fce87087ebc3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 10 Jan 2020 17:30:51 +0300 Subject: [PATCH 4965/5608] Implement InfoColumn component --- .../Overlays/Rankings/SpotlightSelector.cs | 111 ++++++++++++++++-- 1 file changed, 102 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs index 482db10796..66c5f37917 100644 --- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -2,14 +2,18 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; +using osuTK; +using System; namespace osu.Game.Overlays.Rankings { @@ -22,23 +26,49 @@ namespace osu.Game.Overlays.Rankings [Resolved] private IAPIProvider api { get; set; } + public readonly Bindable SelectedSpotlight = new Bindable(); + + private readonly InfoCoulmn startDateColumn; + private readonly InfoCoulmn endDateColumn; + public SpotlightSelector() { RelativeSizeAxes = Axes.X; - Height = 200; + Height = 100; Children = new Drawable[] { background = new Box { RelativeSizeAxes = Axes.Both, }, - dropdown = new SpotlightsDropdown + new Container { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, - Width = 0.8f, - Margin = new MarginPadding { Top = 10 } + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, + Children = new Drawable[] + { + dropdown = new SpotlightsDropdown + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Current = SelectedSpotlight, + Depth = -float.MaxValue + }, + new FillFlowContainer + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(15, 0), + Children = new Drawable[] + { + startDateColumn = new InfoCoulmn(@"Start Date"), + endDateColumn = new InfoCoulmn(@"End Date"), + } + } + } }, loading = new DimmedLoadingLayer(), }; @@ -48,7 +78,12 @@ namespace osu.Game.Overlays.Rankings private void load(OsuColour colours) { background.Colour = colours.GreySeafoam; - dropdown.AccentColour = colours.GreySeafoamDarker; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + SelectedSpotlight.BindValueChanged(onSelectionChanged); } public void FetchSpotlights() @@ -64,9 +99,67 @@ namespace osu.Game.Overlays.Rankings api.Queue(request); } + private void onSelectionChanged(ValueChangedEvent spotlight) + { + startDateColumn.Value = dateToString(spotlight.NewValue.StartDate); + endDateColumn.Value = dateToString(spotlight.NewValue.EndDate); + } + + private string dateToString(DateTimeOffset date) => $"{date.Year}-{date.Month:D2}-{date.Day:D2}"; + + private class InfoCoulmn : FillFlowContainer + { + public string Value + { + set => valueText.Text = value; + } + + private readonly OsuSpriteText valueText; + + public InfoCoulmn(string name) + { + AutoSizeAxes = Axes.Both; + Direction = FillDirection.Vertical; + Children = new Drawable[] + { + new OsuSpriteText + { + Text = name, + Font = OsuFont.GetFont(size: 10), + }, + new Container + { + AutoSizeAxes = Axes.X, + Height = 20, + Child = valueText = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Light), + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + valueText.Colour = colours.GreySeafoamLighter; + } + } + private class SpotlightsDropdown : OsuDropdown { - protected override DropdownMenu CreateMenu() => base.CreateMenu().With(menu => menu.MaxHeight = 400); + private DropdownMenu menu; + + protected override DropdownMenu CreateMenu() => menu = base.CreateMenu().With(m => m.MaxHeight = 400); + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + menu.BackgroundColour = colours.Gray1; + AccentColour = colours.GreySeafoamDarker; + } } } } From 9260ea91955fdcf56e4edbbb3770e39ac0eb21a0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 10 Jan 2020 20:46:35 +0300 Subject: [PATCH 4966/5608] Apply suggestions --- .../Online/API/Requests/GetSpotlightsRequest.cs | 4 ++-- .../Online/API/Requests/Responses/APISpotlight.cs | 2 +- osu.Game/Overlays/Rankings/SpotlightSelector.cs | 14 +++++++------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs b/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs index d5b03e52e2..6fafb3933c 100644 --- a/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs +++ b/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs @@ -7,12 +7,12 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { - public class GetSpotlightsRequest : APIRequest + public class GetSpotlightsRequest : APIRequest { protected override string Target => "spotlights"; } - public class SpotlightsArray + public class SpotlightsCollection { [JsonProperty("spotlights")] public List Spotlights; diff --git a/osu.Game/Online/API/Requests/Responses/APISpotlight.cs b/osu.Game/Online/API/Requests/Responses/APISpotlight.cs index 210ef04dac..63c47e7812 100644 --- a/osu.Game/Online/API/Requests/Responses/APISpotlight.cs +++ b/osu.Game/Online/API/Requests/Responses/APISpotlight.cs @@ -27,7 +27,7 @@ namespace osu.Game.Online.API.Requests.Responses public DateTimeOffset EndDate; [JsonProperty(@"participant_count")] - public int? ParticipiantCount; + public int? ParticipantCount; public override string ToString() => Name; } diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs index 66c5f37917..fb61555c20 100644 --- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -28,8 +28,8 @@ namespace osu.Game.Overlays.Rankings public readonly Bindable SelectedSpotlight = new Bindable(); - private readonly InfoCoulmn startDateColumn; - private readonly InfoCoulmn endDateColumn; + private readonly InfoColumn startDateColumn; + private readonly InfoColumn endDateColumn; public SpotlightSelector() { @@ -64,8 +64,8 @@ namespace osu.Game.Overlays.Rankings Spacing = new Vector2(15, 0), Children = new Drawable[] { - startDateColumn = new InfoCoulmn(@"Start Date"), - endDateColumn = new InfoCoulmn(@"End Date"), + startDateColumn = new InfoColumn(@"Start Date"), + endDateColumn = new InfoColumn(@"End Date"), } } } @@ -105,9 +105,9 @@ namespace osu.Game.Overlays.Rankings endDateColumn.Value = dateToString(spotlight.NewValue.EndDate); } - private string dateToString(DateTimeOffset date) => $"{date.Year}-{date.Month:D2}-{date.Day:D2}"; + private string dateToString(DateTimeOffset date) => date.ToString("yyyy-MM-dd"); - private class InfoCoulmn : FillFlowContainer + private class InfoColumn : FillFlowContainer { public string Value { @@ -116,7 +116,7 @@ namespace osu.Game.Overlays.Rankings private readonly OsuSpriteText valueText; - public InfoCoulmn(string name) + public InfoColumn(string name) { AutoSizeAxes = Axes.Both; Direction = FillDirection.Vertical; From bd175118e9a5075c396a4dfb578729f6d1a7ff89 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 11 Jan 2020 04:16:07 +0800 Subject: [PATCH 4967/5608] 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 fde58ec489..f3838644d1 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 04d0b580da..4fc9e47119 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 50aabd636a..760600e6d4 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 19033e0ef85fba4086d303825718de15affc268c Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 10 Jan 2020 19:25:33 -0800 Subject: [PATCH 4968/5608] Fix user status dropdown having no padding around items --- osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 27796c1e32..e485aa5ea9 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -323,8 +323,6 @@ namespace osu.Game.Overlays.Settings.Sections.General Colour = Color4.Black.Opacity(0.25f), Radius = 4, }; - - ItemsContainer.Padding = new MarginPadding(); } [BackgroundDependencyLoader] From 6500cc967fff845a8e65cd3fc1a7a666be43669e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 11 Jan 2020 06:58:35 +0300 Subject: [PATCH 4969/5608] Implement SongTicker component --- osu.Game/Screens/Menu/MainMenu.cs | 7 +++ osu.Game/Screens/Menu/SongTicker.cs | 66 +++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 osu.Game/Screens/Menu/SongTicker.cs diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index b28d572b5c..47c86fc1ae 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -75,6 +75,13 @@ namespace osu.Game.Screens.Menu holdDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); loginDisplayed = statics.GetBindable(Static.LoginOverlayDisplayed); + AddInternal(new SongTicker + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Margin = new MarginPadding { Right = 15 } + }); + if (host.CanExit) { AddInternal(exitConfirmOverlay = new ExitConfirmOverlay diff --git a/osu.Game/Screens/Menu/SongTicker.cs b/osu.Game/Screens/Menu/SongTicker.cs new file mode 100644 index 0000000000..504b016019 --- /dev/null +++ b/osu.Game/Screens/Menu/SongTicker.cs @@ -0,0 +1,66 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osuTK; +using osu.Game.Graphics; +using osu.Framework.Bindables; +using osu.Game.Beatmaps; + +namespace osu.Game.Screens.Menu +{ + public class SongTicker : Container + { + private const int duration = 500; + + [Resolved] + private Bindable beatmap { get; set; } + + private readonly Bindable workingBeatmap = new Bindable(); + private readonly OsuSpriteText title, artist; + + public SongTicker() + { + AutoSizeAxes = Axes.Both; + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 3), + Children = new Drawable[] + { + title = new OsuSpriteText + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light, italics: true) + }, + artist = new OsuSpriteText + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Font = OsuFont.GetFont(size: 16) + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + workingBeatmap.BindTo(beatmap); + workingBeatmap.BindValueChanged(onBeatmapChanged); + } + + private void onBeatmapChanged(ValueChangedEvent working) + { + title.Text = working.NewValue?.Metadata?.Title; + artist.Text = working.NewValue?.Metadata?.Artist; + + this.FadeIn(duration, Easing.OutQuint).Delay(4000).Then().FadeOut(duration, Easing.OutQuint); + } + } +} From 7716a555ecb71fd5d3ad290bc22d89daf4a281c1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 11 Jan 2020 07:08:00 +0300 Subject: [PATCH 4970/5608] Move only ButtonSystem on screen changes rather than everything --- osu.Game/Screens/Menu/MainMenu.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 47c86fc1ae..c4465dce17 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -69,6 +69,8 @@ namespace osu.Game.Screens.Menu private ExitConfirmOverlay exitConfirmOverlay; + private ParallaxContainer buttonsContainer; + [BackgroundDependencyLoader(true)] private void load(DirectOverlay direct, SettingsOverlay settings, OsuConfigManager config, SessionStatics statics) { @@ -79,7 +81,7 @@ namespace osu.Game.Screens.Menu { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - Margin = new MarginPadding { Right = 15 } + Margin = new MarginPadding { Right = 15, Top = 5 } }); if (host.CanExit) @@ -98,7 +100,7 @@ namespace osu.Game.Screens.Menu AddRangeInternal(new Drawable[] { - new ParallaxContainer + buttonsContainer = new ParallaxContainer { ParallaxAmount = 0.01f, Children = new Drawable[] @@ -197,7 +199,7 @@ namespace osu.Game.Screens.Menu buttons.State = ButtonSystemState.TopLevel; this.FadeIn(FADE_IN_DURATION, Easing.OutQuint); - this.MoveTo(new Vector2(0, 0), FADE_IN_DURATION, Easing.OutQuint); + buttonsContainer.MoveTo(new Vector2(0, 0), FADE_IN_DURATION, Easing.OutQuint); sideFlashes.Delay(FADE_IN_DURATION).FadeIn(64, Easing.InQuint); } @@ -234,7 +236,7 @@ namespace osu.Game.Screens.Menu buttons.State = ButtonSystemState.EnteringMode; this.FadeOut(FADE_OUT_DURATION, Easing.InSine); - this.MoveTo(new Vector2(-800, 0), FADE_OUT_DURATION, Easing.InSine); + buttonsContainer.MoveTo(new Vector2(-800, 0), FADE_OUT_DURATION, Easing.InSine); sideFlashes.FadeOut(64, Easing.OutQuint); } From 820f9f2273f98995c2da7c40427e43b3d0ca0ae8 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 10 Jan 2020 20:16:46 -0800 Subject: [PATCH 4971/5608] Fix default button absorbing drag scroll on settings --- osu.Game/Overlays/Settings/SettingsItem.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 35f28ab1b2..55e1937d83 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -163,10 +163,6 @@ namespace osu.Game.Overlays.Settings public string TooltipText => "Revert to default"; - protected override bool OnMouseDown(MouseDownEvent e) => true; - - protected override bool OnMouseUp(MouseUpEvent e) => true; - protected override bool OnClick(ClickEvent e) { if (bindable != null && !bindable.Disabled) From d59cae33d3f0ff67fc5f6a38a7a2c02449bcb110 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 11 Jan 2020 07:17:13 +0300 Subject: [PATCH 4972/5608] Some animation adjustments --- osu.Game/Screens/Menu/MainMenu.cs | 6 +++++- osu.Game/Screens/Menu/SongTicker.cs | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index c4465dce17..0b267731d8 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -70,6 +70,7 @@ namespace osu.Game.Screens.Menu private ExitConfirmOverlay exitConfirmOverlay; private ParallaxContainer buttonsContainer; + private SongTicker songTicker; [BackgroundDependencyLoader(true)] private void load(DirectOverlay direct, SettingsOverlay settings, OsuConfigManager config, SessionStatics statics) @@ -77,7 +78,7 @@ namespace osu.Game.Screens.Menu holdDelay = config.GetBindable(OsuSetting.UIHoldActivationDelay); loginDisplayed = statics.GetBindable(Static.LoginOverlayDisplayed); - AddInternal(new SongTicker + AddInternal(songTicker = new SongTicker { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -235,6 +236,7 @@ namespace osu.Game.Screens.Menu buttons.State = ButtonSystemState.EnteringMode; + songTicker.Hide(); this.FadeOut(FADE_OUT_DURATION, Easing.InSine); buttonsContainer.MoveTo(new Vector2(-800, 0), FADE_OUT_DURATION, Easing.InSine); @@ -244,6 +246,7 @@ namespace osu.Game.Screens.Menu public override void OnResuming(IScreen last) { base.OnResuming(last); + songTicker.Hide(); (Background as BackgroundScreenDefault)?.Next(); @@ -272,6 +275,7 @@ namespace osu.Game.Screens.Menu buttons.State = ButtonSystemState.Exit; this.FadeOut(3000); + songTicker.Hide(); return base.OnExiting(next); } diff --git a/osu.Game/Screens/Menu/SongTicker.cs b/osu.Game/Screens/Menu/SongTicker.cs index 504b016019..eb7012a150 100644 --- a/osu.Game/Screens/Menu/SongTicker.cs +++ b/osu.Game/Screens/Menu/SongTicker.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Menu { public class SongTicker : Container { - private const int duration = 500; + private const int fade_duration = 800; [Resolved] private Bindable beatmap { get; set; } @@ -60,7 +60,7 @@ namespace osu.Game.Screens.Menu title.Text = working.NewValue?.Metadata?.Title; artist.Text = working.NewValue?.Metadata?.Artist; - this.FadeIn(duration, Easing.OutQuint).Delay(4000).Then().FadeOut(duration, Easing.OutQuint); + this.FadeIn(fade_duration, Easing.OutQuint).Delay(4000).Then().FadeOut(fade_duration, Easing.OutQuint); } } } From e6210f10b7de81a12ef03148202ae14933a77fb7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 11 Jan 2020 07:32:40 +0300 Subject: [PATCH 4973/5608] Add unicode metadata support --- osu.Game/Screens/Menu/SongTicker.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/SongTicker.cs b/osu.Game/Screens/Menu/SongTicker.cs index eb7012a150..d9b66d06e9 100644 --- a/osu.Game/Screens/Menu/SongTicker.cs +++ b/osu.Game/Screens/Menu/SongTicker.cs @@ -9,6 +9,7 @@ using osuTK; using osu.Game.Graphics; using osu.Framework.Bindables; using osu.Game.Beatmaps; +using osu.Framework.Localisation; namespace osu.Game.Screens.Menu { @@ -57,8 +58,13 @@ namespace osu.Game.Screens.Menu private void onBeatmapChanged(ValueChangedEvent working) { - title.Text = working.NewValue?.Metadata?.Title; - artist.Text = working.NewValue?.Metadata?.Artist; + if (working.NewValue?.Beatmap == null) + return; + + var metadata = working.NewValue?.Metadata; + + title.Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)); + artist.Text = new LocalisedString((metadata.ArtistUnicode, metadata.Artist)); this.FadeIn(fade_duration, Easing.OutQuint).Delay(4000).Then().FadeOut(fade_duration, Easing.OutQuint); } From 76c70a76229a956c186d304c9232a604015148e8 Mon Sep 17 00:00:00 2001 From: mcendu Date: Sat, 11 Jan 2020 21:19:46 +0800 Subject: [PATCH 4974/5608] Move hit target bar height def to defaulthittarget --- osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index ee2cec1bbd..90e78c3899 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -18,8 +18,6 @@ namespace osu.Game.Rulesets.Mania.UI.Components { public class ColumnHitObjectArea : CompositeDrawable, IHasAccentColour { - private const float hit_target_bar_height = 2; - private readonly IBindable direction = new Bindable(); private readonly Drawable hitTarget; @@ -67,6 +65,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components private class DefaultHitTarget : CompositeDrawable, IHasAccentColour { + private const float hit_target_bar_height = 2; + private readonly IBindable direction = new Bindable(); private readonly Container hitTargetLine; From d25ef1966d32bda80e258da550a6c87768ca0eeb Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 11 Jan 2020 17:48:09 +0300 Subject: [PATCH 4975/5608] Remove unnecessary local bindable --- osu.Game/Screens/Menu/SongTicker.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/SongTicker.cs b/osu.Game/Screens/Menu/SongTicker.cs index d9b66d06e9..f2c861a296 100644 --- a/osu.Game/Screens/Menu/SongTicker.cs +++ b/osu.Game/Screens/Menu/SongTicker.cs @@ -20,7 +20,6 @@ namespace osu.Game.Screens.Menu [Resolved] private Bindable beatmap { get; set; } - private readonly Bindable workingBeatmap = new Bindable(); private readonly OsuSpriteText title, artist; public SongTicker() @@ -52,8 +51,7 @@ namespace osu.Game.Screens.Menu protected override void LoadComplete() { base.LoadComplete(); - workingBeatmap.BindTo(beatmap); - workingBeatmap.BindValueChanged(onBeatmapChanged); + beatmap.BindValueChanged(onBeatmapChanged); } private void onBeatmapChanged(ValueChangedEvent working) From 81948744d056acd6ca24d0f6875236fcef3f034a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 11 Jan 2020 17:50:13 +0300 Subject: [PATCH 4976/5608] remove unnecessary null checks --- osu.Game/Screens/Menu/SongTicker.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Screens/Menu/SongTicker.cs b/osu.Game/Screens/Menu/SongTicker.cs index f2c861a296..8eae94ae1d 100644 --- a/osu.Game/Screens/Menu/SongTicker.cs +++ b/osu.Game/Screens/Menu/SongTicker.cs @@ -56,10 +56,7 @@ namespace osu.Game.Screens.Menu private void onBeatmapChanged(ValueChangedEvent working) { - if (working.NewValue?.Beatmap == null) - return; - - var metadata = working.NewValue?.Metadata; + var metadata = working.NewValue.Metadata; title.Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)); artist.Text = new LocalisedString((metadata.ArtistUnicode, metadata.Artist)); From ec95cbd0affc9e9c91817459740f46f4ba964a4d Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 11 Jan 2020 16:03:00 +0100 Subject: [PATCH 4977/5608] Don't update rich presence if the rpc client isn't initialized. --- osu.Desktop/DiscordRichPresence.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 80bb82c769..08cc0e7f5f 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -75,6 +75,9 @@ namespace osu.Desktop private void updateStatus() { + if (!client.IsInitialized) + return; + if (status.Value is UserStatusOffline) { client.ClearPresence(); From bd33687f533a969d7bd855054b50f840614ef754 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 11 Jan 2020 18:27:22 +0300 Subject: [PATCH 4978/5608] Add AllowUpdates flag to SongTicker --- osu.Game/Screens/Menu/MainMenu.cs | 5 ++++- osu.Game/Screens/Menu/SongTicker.cs | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 0b267731d8..72b61eb05c 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -237,6 +237,8 @@ namespace osu.Game.Screens.Menu buttons.State = ButtonSystemState.EnteringMode; songTicker.Hide(); + songTicker.AllowUpdates = false; + this.FadeOut(FADE_OUT_DURATION, Easing.InSine); buttonsContainer.MoveTo(new Vector2(-800, 0), FADE_OUT_DURATION, Easing.InSine); @@ -246,7 +248,8 @@ namespace osu.Game.Screens.Menu public override void OnResuming(IScreen last) { base.OnResuming(last); - songTicker.Hide(); + + songTicker.AllowUpdates = true; (Background as BackgroundScreenDefault)?.Next(); diff --git a/osu.Game/Screens/Menu/SongTicker.cs b/osu.Game/Screens/Menu/SongTicker.cs index 8eae94ae1d..f858d162d2 100644 --- a/osu.Game/Screens/Menu/SongTicker.cs +++ b/osu.Game/Screens/Menu/SongTicker.cs @@ -17,6 +17,8 @@ namespace osu.Game.Screens.Menu { private const int fade_duration = 800; + public bool AllowUpdates { get; set; } = true; + [Resolved] private Bindable beatmap { get; set; } @@ -56,6 +58,9 @@ namespace osu.Game.Screens.Menu private void onBeatmapChanged(ValueChangedEvent working) { + if (!AllowUpdates) + return; + var metadata = working.NewValue.Metadata; title.Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)); From cd679707eddc4aa2a4ff911e4da1221526bc3a2a Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sat, 11 Jan 2020 17:16:11 +0100 Subject: [PATCH 4979/5608] Prevent channel duplicates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bartłomiej Dach --- osu.Game/Online/Chat/ChannelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 19c3be0d7b..33b0c0e9e1 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -447,7 +447,7 @@ namespace osu.Game.Online.Chat public void MarkChannelAsRead(Message message) { - var channel = JoinedChannels.First(c => c.Id == message.ChannelId); + var channel = JoinedChannels.Single(c => c.Id == message.ChannelId); var req = new MarkChannelAsReadRequest(channel, message); req.Success += () => channel.LastReadId = message.Id; req.Failure += e => Logger.Error(e, "Failed to mark channel as read"); From 50e357a79930b0980fb67fddafc21c65712a0c49 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sat, 11 Jan 2020 17:42:02 +0100 Subject: [PATCH 4980/5608] Change method parameters, add detailed error message and method docs --- osu.Game/Online/Chat/ChannelManager.cs | 16 +++++++++++++--- osu.Game/Overlays/ChatOverlay.cs | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 33b0c0e9e1..9f263477d0 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -445,12 +445,22 @@ namespace osu.Game.Online.Chat return tcs.Task; } - public void MarkChannelAsRead(Message message) + /// + /// Marks the as read + /// (see for more information) + /// + /// The channel that will be marked as read + /// The message where it will be read up to. If was provided, the latest message of the will be read. + public void MarkChannelAsRead(Channel channel, Message message = null) { - var channel = JoinedChannels.Single(c => c.Id == message.ChannelId); + if (message == null) + message = channel.Messages.Last(); + var req = new MarkChannelAsReadRequest(channel, message); + req.Success += () => channel.LastReadId = message.Id; - req.Failure += e => Logger.Error(e, "Failed to mark channel as read"); + req.Failure += e => Logger.Error(e, $"Failed to mark channel {channel.ToString()} up to '{message.ToString()}' as read"); + api.Queue(req); } diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index b64d3a1893..45d311df28 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -282,7 +282,7 @@ namespace osu.Game.Overlays // mark channel as read when channel switched if (e.NewValue.Messages.Any()) - channelManager.MarkChannelAsRead(e.NewValue.Messages.Last()); + channelManager.MarkChannelAsRead(e.NewValue); } private float startDragChatHeight; From d9c57baa89cab9430f3a9577666d0a8708096444 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sat, 11 Jan 2020 17:48:03 +0100 Subject: [PATCH 4981/5608] Add test case for mismatch of channels --- osu.Game/Online/Chat/ChannelManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 9f263477d0..b30d1ffa60 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; @@ -455,6 +456,8 @@ namespace osu.Game.Online.Chat { if (message == null) message = channel.Messages.Last(); + else + Debug.Assert(channel.Id == message.Id, "Provided channel and message owner channel aren't equal."); var req = new MarkChannelAsReadRequest(channel, message); From f8a11e50b677c4f3172efbbeae05eee81e713608 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sat, 11 Jan 2020 18:00:34 +0100 Subject: [PATCH 4982/5608] Remove redundant ToString() calls as string interpolation does this automatically.. --- osu.Game/Online/Chat/ChannelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index b30d1ffa60..5aab43dbd9 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -462,7 +462,7 @@ namespace osu.Game.Online.Chat var req = new MarkChannelAsReadRequest(channel, message); req.Success += () => channel.LastReadId = message.Id; - req.Failure += e => Logger.Error(e, $"Failed to mark channel {channel.ToString()} up to '{message.ToString()}' as read"); + req.Failure += e => Logger.Error(e, $"Failed to mark channel {channel} up to '{message}' as read"); api.Queue(req); } From 2ea1367a881cab6e5e9eed787971a6f5ca22f989 Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sat, 11 Jan 2020 19:47:35 +0100 Subject: [PATCH 4983/5608] Remove message parameter and make it mark the entire channel as read --- osu.Game/Online/Chat/ChannelManager.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 5aab43dbd9..4071be0aaf 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -448,17 +448,11 @@ namespace osu.Game.Online.Chat /// /// Marks the as read - /// (see for more information) /// /// The channel that will be marked as read - /// The message where it will be read up to. If was provided, the latest message of the will be read. - public void MarkChannelAsRead(Channel channel, Message message = null) + public void MarkChannelAsRead(Channel channel) { - if (message == null) - message = channel.Messages.Last(); - else - Debug.Assert(channel.Id == message.Id, "Provided channel and message owner channel aren't equal."); - + var message = channel.Messages.Last(); var req = new MarkChannelAsReadRequest(channel, message); req.Success += () => channel.LastReadId = message.Id; From ccaf4e48a169644bafbfeafe006e9c71d57a5beb Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sat, 11 Jan 2020 20:04:58 +0100 Subject: [PATCH 4984/5608] Remove using directive --- osu.Game/Online/Chat/ChannelManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 4071be0aaf..35a48b7ec8 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; From 730cc92bf36ddf5c7a2eb53d5c7042b422708de5 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 11 Jan 2020 22:43:07 +0300 Subject: [PATCH 4985/5608] Fade out instead of insta hiding on menu suspending --- osu.Game/Screens/Menu/MainMenu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 72b61eb05c..2de31cf399 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -236,7 +236,7 @@ namespace osu.Game.Screens.Menu buttons.State = ButtonSystemState.EnteringMode; - songTicker.Hide(); + songTicker.FadeOut(100, Easing.OutQuint); songTicker.AllowUpdates = false; this.FadeOut(FADE_OUT_DURATION, Easing.InSine); From f43602518a6b013bdcb0e8cd9bc3309463f4d53c Mon Sep 17 00:00:00 2001 From: Joehu Date: Sat, 11 Jan 2020 11:43:51 -0800 Subject: [PATCH 4986/5608] Add global action for toggling now playing overlay --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 4 ++++ osu.Game/OsuGame.cs | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index e37567c72c..7763577a14 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -24,6 +24,7 @@ namespace osu.Game.Input.Bindings public IEnumerable GlobalKeyBindings => new[] { + new KeyBinding(InputKey.F6, GlobalAction.ToggleNowPlaying), new KeyBinding(InputKey.F8, GlobalAction.ToggleChat), new KeyBinding(InputKey.F9, GlobalAction.ToggleSocial), new KeyBinding(InputKey.F10, GlobalAction.ToggleGameplayMouseButtons), @@ -137,5 +138,8 @@ namespace osu.Game.Input.Bindings [Description("Play / pause")] MusicPlay, + + [Description("Toggle now playing overlay")] + ToggleNowPlaying, } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 84aba4af52..9df854d178 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -61,6 +61,8 @@ namespace osu.Game private NotificationOverlay notifications; + private NowPlayingOverlay nowPlaying; + private DirectOverlay direct; private SocialOverlay social; @@ -624,7 +626,7 @@ namespace osu.Game Origin = Anchor.TopRight, }, rightFloatingOverlayContent.Add, true); - loadComponentSingleFile(new NowPlayingOverlay + loadComponentSingleFile(nowPlaying = new NowPlayingOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, @@ -822,6 +824,10 @@ namespace osu.Game switch (action) { + case GlobalAction.ToggleNowPlaying: + nowPlaying.ToggleVisibility(); + return true; + case GlobalAction.ToggleChat: chatOverlay.ToggleVisibility(); return true; From f1b4fbb844082a910481373c74114b59519ad62c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 12 Jan 2020 17:38:15 +0300 Subject: [PATCH 4987/5608] Make gradient in NewsArticleCover be effected by hover --- osu.Game/Overlays/News/NewsArticleCover.cs | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/News/NewsArticleCover.cs b/osu.Game/Overlays/News/NewsArticleCover.cs index e484309a18..f61b30b381 100644 --- a/osu.Game/Overlays/News/NewsArticleCover.cs +++ b/osu.Game/Overlays/News/NewsArticleCover.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK.Graphics; @@ -19,6 +20,10 @@ namespace osu.Game.Overlays.News { public class NewsArticleCover : Container { + private const int hover_duration = 300; + + private readonly Box gradient; + public NewsArticleCover(ArticleInfo info) { RelativeSizeAxes = Axes.X; @@ -47,11 +52,11 @@ namespace osu.Game.Overlays.News Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, }, - new Box + gradient = new Box { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.1f), Color4.Black.Opacity(0.6f)), - Alpha = 1f, + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.1f), Color4.Black.Opacity(0.7f)), + Alpha = 0 }, new DateContainer(info.Time) { @@ -90,6 +95,18 @@ namespace osu.Game.Overlays.News bg.OnLoadComplete += d => d.FadeIn(250, Easing.In); } + protected override bool OnHover(HoverEvent e) + { + gradient.FadeIn(hover_duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + gradient.FadeOut(hover_duration, Easing.OutQuint); + } + [LongRunningLoad] private class NewsBackground : Sprite { From 8cc2d70df0fb725e09891caf912adb335841e31d Mon Sep 17 00:00:00 2001 From: Craftplacer Date: Sun, 12 Jan 2020 16:24:14 +0100 Subject: [PATCH 4988/5608] Reduce API calls by checking what message was last marked as read --- osu.Game/Online/Chat/ChannelManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 35a48b7ec8..b741bd9433 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -451,6 +451,9 @@ namespace osu.Game.Online.Chat /// The channel that will be marked as read public void MarkChannelAsRead(Channel channel) { + if (channel.LastMessageId == channel.LastReadId) + return; + var message = channel.Messages.Last(); var req = new MarkChannelAsReadRequest(channel, message); From aa2645502cf182cc8241814f89ad0a39f6b4cbf3 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Sun, 12 Jan 2020 20:43:48 +0100 Subject: [PATCH 4989/5608] Fix adjusted value always being 0 --- osu.Game/Screens/Select/Details/AdvancedStats.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index a147527f6c..52a5b101d4 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -118,17 +118,9 @@ namespace osu.Game.Screens.Select.Details mod.ApplyToDifficulty(adjustedDifficulty); } - //mania specific - if ((Beatmap?.Ruleset?.ID ?? 0) == 3) - { - firstValue.Title = "Key Amount"; - firstValue.Value = ((int)MathF.Round(baseDifficulty?.CircleSize ?? 0), (int)MathF.Round(adjustedDifficulty?.CircleSize ?? 0)); - } - else - { - firstValue.Title = "Circle Size"; - firstValue.Value = (baseDifficulty?.CircleSize ?? 0, adjustedDifficulty?.CircleSize); - } + // Account for mania differences + firstValue.Title = (Beatmap?.Ruleset?.ID ?? 0) == 3 ? "Key Amount" : "Circle Size"; + firstValue.Value = (baseDifficulty?.CircleSize ?? 0, adjustedDifficulty?.CircleSize); starDifficulty.Value = ((float)(Beatmap?.StarDifficulty ?? 0), null); From b5ac707c6cf9be7671adbaa95677ad43ce7d9379 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Sun, 12 Jan 2020 21:09:48 +0100 Subject: [PATCH 4990/5608] Remove unnecessary directive --- osu.Game/Screens/Select/Details/AdvancedStats.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 52a5b101d4..b7f60a8370 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using System; using osu.Game.Beatmaps; using osu.Framework.Bindables; using System.Collections.Generic; From c190c68659236e0e5b2d57945b7a52ee7d936a7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Jan 2020 12:22:44 +0900 Subject: [PATCH 4991/5608] Add safety for channel with no messages --- osu.Game/Online/Chat/ChannelManager.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index b741bd9433..4b5ec1cad0 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -454,7 +454,11 @@ namespace osu.Game.Online.Chat if (channel.LastMessageId == channel.LastReadId) return; - var message = channel.Messages.Last(); + var message = channel.Messages.LastOrDefault(); + + if (message == null) + return; + var req = new MarkChannelAsReadRequest(channel, message); req.Success += () => channel.LastReadId = message.Id; From af167eb719964794663983e32f2fbac80ba4f693 Mon Sep 17 00:00:00 2001 From: recapitalverb <41869184+recapitalverb@users.noreply.github.com> Date: Mon, 13 Jan 2020 23:28:26 +0700 Subject: [PATCH 4992/5608] Remove duplicate condition in TournamentFont --- osu.Game.Tournament/TournamentFont.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/TournamentFont.cs b/osu.Game.Tournament/TournamentFont.cs index f9e60ff2bc..32f0264562 100644 --- a/osu.Game.Tournament/TournamentFont.cs +++ b/osu.Game.Tournament/TournamentFont.cs @@ -61,7 +61,7 @@ namespace osu.Game.Tournament string weightString = weight.ToString(); // Only exo has an explicit "regular" weight, other fonts do not - if (weight == FontWeight.Regular && family != GetFamilyString(TournamentTypeface.Aquatico) && family != GetFamilyString(TournamentTypeface.Aquatico)) + if (weight == FontWeight.Regular && family != GetFamilyString(TournamentTypeface.Aquatico)) weightString = string.Empty; return weightString; From 619fe29871b7e2797b9e0c15003842bb70e4059f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Jan 2020 01:39:45 +0900 Subject: [PATCH 4993/5608] Make reverse arrow animate faster via divisor specification Adds MinimumBeatLength to BeatSyncedContainer to make sure things don't get out of hand. --- .../Objects/Drawables/Pieces/ReverseArrowPiece.cs | 3 +++ osu.Game/Graphics/Containers/BeatSyncedContainer.cs | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs index 2b9a3aa197..2c6e5b7c18 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs @@ -20,6 +20,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { this.repeatPoint = repeatPoint; + Divisor = 2; + MinimumBeatLength = 200; + Anchor = Anchor.Centre; Origin = Anchor.Centre; diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index b9ef279f5c..be9aefa359 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -38,6 +38,11 @@ namespace osu.Game.Graphics.Containers /// public int Divisor { get; set; } = 1; + /// + /// An optional minimum beat length. Any beat length below this will be multiplied by two until valid. + /// + public double MinimumBeatLength { get; set; } + /// /// Default length of a beat in milliseconds. Used whenever there is no beatmap or track playing. /// @@ -89,6 +94,9 @@ namespace osu.Game.Graphics.Containers double beatLength = timingPoint.BeatLength / Divisor; + while (beatLength < MinimumBeatLength) + beatLength *= 2; + int beatIndex = (int)((currentTrackTime - timingPoint.Time) / beatLength) - (effectPoint.OmitFirstBarLine ? 1 : 0); // The beats before the start of the first control point are off by 1, this should do the trick From c5085aea24ae4b08890baac8e894ce208d71af7e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Jan 2020 01:45:10 +0900 Subject: [PATCH 4994/5608] Use Child, not InternalChild --- .../Objects/Drawables/Pieces/ReverseArrowPiece.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs index 2c6e5b7c18..ee7cdefa13 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); - InternalChild = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.ReverseArrow), _ => new SpriteIcon + Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.ReverseArrow), _ => new SpriteIcon { RelativeSizeAxes = Axes.Both, Icon = FontAwesome.Solid.ChevronRight, @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) { if (Clock.CurrentTime < repeatPoint.StartTime) - InternalChild.ScaleTo(1.3f).ScaleTo(1f, Math.Min(timingPoint.BeatLength, repeatPoint.StartTime - Clock.CurrentTime), Easing.Out); + Child.ScaleTo(1.3f).ScaleTo(1f, Math.Min(timingPoint.BeatLength, repeatPoint.StartTime - Clock.CurrentTime), Easing.Out); } } } From 210d06b75ed27209d6d8721a8d3b131004a57bb5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Jan 2020 01:45:32 +0900 Subject: [PATCH 4995/5608] Remove default value --- .../Objects/Drawables/Pieces/ReverseArrowPiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs index ee7cdefa13..37bbfbe806 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces RelativeSizeAxes = Axes.Both, Icon = FontAwesome.Solid.ChevronRight, Size = new Vector2(0.35f) - }, confineMode: ConfineMode.NoScaling) + }) { Anchor = Anchor.Centre, Origin = Anchor.Centre, From ab4f31639d9e2ccfd8ac4cc61091c024aa0c6827 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Jan 2020 01:47:44 +0900 Subject: [PATCH 4996/5608] Remove weird time clause --- .../Objects/Drawables/Pieces/ReverseArrowPiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs index 37bbfbe806..0403fe8196 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) { if (Clock.CurrentTime < repeatPoint.StartTime) - Child.ScaleTo(1.3f).ScaleTo(1f, Math.Min(timingPoint.BeatLength, repeatPoint.StartTime - Clock.CurrentTime), Easing.Out); + Child.ScaleTo(1.3f).ScaleTo(1f, timingPoint.BeatLength, Easing.Out); } } } From fe09e34f1bf8a9ed9d7479c0792ac871ae3b5020 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Jan 2020 01:48:20 +0900 Subject: [PATCH 4997/5608] Remove limiting clause --- .../Objects/Drawables/Pieces/ReverseArrowPiece.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs index 0403fe8196..08dd97b0d8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ReverseArrowPiece.cs @@ -42,10 +42,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces }; } - protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) - { - if (Clock.CurrentTime < repeatPoint.StartTime) - Child.ScaleTo(1.3f).ScaleTo(1f, timingPoint.BeatLength, Easing.Out); - } + protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) => + Child.ScaleTo(1.3f).ScaleTo(1f, timingPoint.BeatLength, Easing.Out); } } From 90e4def4bd0d782f24b4d987639f33a1388fe621 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 14 Jan 2020 07:07:21 +0300 Subject: [PATCH 4998/5608] Remove online stuff out of the selector --- .../TestSceneRankingsSpotlightSelector.cs | 18 ++++++-- .../Overlays/Rankings/SpotlightSelector.cs | 45 +++++++------------ 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs index 9320213844..0862b3251a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Rankings; namespace osu.Game.Tests.Visual.Online @@ -14,15 +15,26 @@ namespace osu.Game.Tests.Visual.Online typeof(SpotlightSelector), }; - protected override bool UseOnlineAPI => true; - public TestSceneRankingsSpotlightSelector() { SpotlightSelector selector; Add(selector = new SpotlightSelector()); - AddStep("Fetch spotlights", selector.FetchSpotlights); + var spotlights = new APISpotlight[] + { + new APISpotlight { Name = "Spotlight 1" }, + new APISpotlight { Name = "Spotlight 2" }, + new APISpotlight { Name = "Spotlight 3" }, + }; + + AddStep("Load spotlights", () => selector.Spotlights = spotlights); + AddStep("Load info", () => selector.UpdateInfo(new APISpotlight + { + StartDate = DateTimeOffset.Now, + EndDate = DateTimeOffset.Now, + ParticipantCount = 15155151, + }, 18)); } } } diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs index fb61555c20..a275f4ed50 100644 --- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -9,11 +9,10 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osuTK; using System; +using System.Collections.Generic; namespace osu.Game.Overlays.Rankings { @@ -21,15 +20,19 @@ namespace osu.Game.Overlays.Rankings { private readonly Box background; private readonly SpotlightsDropdown dropdown; - private readonly DimmedLoadingLayer loading; - - [Resolved] - private IAPIProvider api { get; set; } public readonly Bindable SelectedSpotlight = new Bindable(); + public IEnumerable Spotlights + { + get => dropdown.Items; + set => dropdown.Items = value; + } + private readonly InfoColumn startDateColumn; private readonly InfoColumn endDateColumn; + private readonly InfoColumn mapCountColumn; + private readonly InfoColumn participants; public SpotlightSelector() { @@ -66,11 +69,12 @@ namespace osu.Game.Overlays.Rankings { startDateColumn = new InfoColumn(@"Start Date"), endDateColumn = new InfoColumn(@"End Date"), + mapCountColumn = new InfoColumn(@"Map Count"), + participants = new InfoColumn(@"Participants"), } } } }, - loading = new DimmedLoadingLayer(), }; } @@ -80,29 +84,12 @@ namespace osu.Game.Overlays.Rankings background.Colour = colours.GreySeafoam; } - protected override void LoadComplete() + public void UpdateInfo(APISpotlight spotlight, int mapCount) { - base.LoadComplete(); - SelectedSpotlight.BindValueChanged(onSelectionChanged); - } - - public void FetchSpotlights() - { - loading.Show(); - - var request = new GetSpotlightsRequest(); - request.Success += response => - { - dropdown.Items = response.Spotlights; - loading.Hide(); - }; - api.Queue(request); - } - - private void onSelectionChanged(ValueChangedEvent spotlight) - { - startDateColumn.Value = dateToString(spotlight.NewValue.StartDate); - endDateColumn.Value = dateToString(spotlight.NewValue.EndDate); + startDateColumn.Value = dateToString(spotlight.StartDate); + endDateColumn.Value = dateToString(spotlight.EndDate); + mapCountColumn.Value = mapCount.ToString(); + participants.Value = spotlight.ParticipantCount?.ToString("N0"); } private string dateToString(DateTimeOffset date) => date.ToString("yyyy-MM-dd"); From 18ebd309788124c12ae3d5bf8388f97e4822939c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 14 Jan 2020 07:20:03 +0300 Subject: [PATCH 4999/5608] CI fix --- .../Visual/Online/TestSceneRankingsSpotlightSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs index 0862b3251a..1a62cb6dad 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.Online Add(selector = new SpotlightSelector()); - var spotlights = new APISpotlight[] + var spotlights = new[] { new APISpotlight { Name = "Spotlight 1" }, new APISpotlight { Name = "Spotlight 2" }, From c196e83e75f495f533f82e867d7d8cd3e9165738 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 13 Jan 2020 20:48:39 -0800 Subject: [PATCH 5000/5608] Allow changing volume in song select with arrow keys when pressing alt --- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index bf2382c4ae..da01ac5f95 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -436,7 +436,7 @@ namespace osu.Game.Screens.Select break; } - if (direction == 0) + if (direction == 0 || e.AltPressed) return base.OnKeyDown(e); SelectNext(direction, skipDifficulties); From 7349c023d1b9696559d5190469024544d064204a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Jan 2020 14:01:51 +0900 Subject: [PATCH 5001/5608] Cleanup spotlight selection --- .../TestSceneRankingsSpotlightSelector.cs | 4 +-- .../API/Requests/Responses/APISpotlight.cs | 2 +- .../Overlays/Rankings/SpotlightSelector.cs | 30 ++++++++++++++----- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs index 1a62cb6dad..d714d5fb7d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs @@ -29,12 +29,12 @@ namespace osu.Game.Tests.Visual.Online }; AddStep("Load spotlights", () => selector.Spotlights = spotlights); - AddStep("Load info", () => selector.UpdateInfo(new APISpotlight + AddStep("Load info", () => selector.Current.Value = new APISpotlight { StartDate = DateTimeOffset.Now, EndDate = DateTimeOffset.Now, ParticipantCount = 15155151, - }, 18)); + }); } } } diff --git a/osu.Game/Online/API/Requests/Responses/APISpotlight.cs b/osu.Game/Online/API/Requests/Responses/APISpotlight.cs index 63c47e7812..2191ed4743 100644 --- a/osu.Game/Online/API/Requests/Responses/APISpotlight.cs +++ b/osu.Game/Online/API/Requests/Responses/APISpotlight.cs @@ -27,7 +27,7 @@ namespace osu.Game.Online.API.Requests.Responses public DateTimeOffset EndDate; [JsonProperty(@"participant_count")] - public int? ParticipantCount; + public int ParticipantCount; public override string ToString() => Name; } diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs index a275f4ed50..def7469b16 100644 --- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -13,15 +13,22 @@ using osu.Game.Online.API.Requests.Responses; using osuTK; using System; using System.Collections.Generic; +using osu.Framework.Graphics.UserInterface; namespace osu.Game.Overlays.Rankings { - public class SpotlightSelector : Container + public class SpotlightSelector : Container, IHasCurrentValue { private readonly Box background; private readonly SpotlightsDropdown dropdown; - public readonly Bindable SelectedSpotlight = new Bindable(); + private readonly BindableWithCurrent current = new BindableWithCurrent(); + + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } public IEnumerable Spotlights { @@ -55,7 +62,7 @@ namespace osu.Game.Overlays.Rankings Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, - Current = SelectedSpotlight, + Current = Current, Depth = -float.MaxValue }, new FillFlowContainer @@ -84,12 +91,19 @@ namespace osu.Game.Overlays.Rankings background.Colour = colours.GreySeafoam; } - public void UpdateInfo(APISpotlight spotlight, int mapCount) + protected override void LoadComplete() { - startDateColumn.Value = dateToString(spotlight.StartDate); - endDateColumn.Value = dateToString(spotlight.EndDate); - mapCountColumn.Value = mapCount.ToString(); - participants.Value = spotlight.ParticipantCount?.ToString("N0"); + base.LoadComplete(); + + Current.BindValueChanged(onCurrentChanged); + } + + private void onCurrentChanged(ValueChangedEvent spotlight) + { + startDateColumn.Value = dateToString(spotlight.NewValue.StartDate); + endDateColumn.Value = dateToString(spotlight.NewValue.EndDate); + // mapCountColumn.Value = spotlight.NewValue.ParticipantCount.ToString(); + participants.Value = spotlight.NewValue.ParticipantCount.ToString(); } private string dateToString(DateTimeOffset date) => date.ToString("yyyy-MM-dd"); From 20466d79df37e8671badf7bd12f7dc66b0bcea10 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Jan 2020 14:18:28 +0900 Subject: [PATCH 5002/5608] Update netcore version --- .idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml index 1fd10e0e1a..d85a0ae44c 100644 --- a/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml +++ b/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml @@ -1,6 +1,6 @@ -
    /// Creates the conversion value for a . A conversion value stores information about the converted . @@ -176,6 +184,32 @@ namespace osu.Game.Tests.Beatmaps [JsonProperty] public List Mappings = new List(); } + + private class ConversionWorkingBeatmap : WorkingBeatmap + { + public Action, IBeatmapConverter> ConversionGenerated; + + private readonly IBeatmap beatmap; + + public ConversionWorkingBeatmap(IBeatmap beatmap) + : base(beatmap.BeatmapInfo, null) + { + this.beatmap = beatmap; + } + + protected override IBeatmap GetBeatmap() => beatmap; + + protected override Texture GetBackground() => throw new NotImplementedException(); + + protected override Track GetTrack() => throw new NotImplementedException(); + + protected override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) + { + var converter = base.CreateBeatmapConverter(beatmap, ruleset); + converter.ObjectConverted += (orig, converted) => ConversionGenerated?.Invoke(orig, converted, converter); + return converter; + } + } } public abstract class BeatmapConversionTest : BeatmapConversionTest, TConvertValue> From ed4dda19363a1a112b4d55b6719c4d456073a459 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 31 Jul 2019 19:49:25 +0900 Subject: [PATCH 2138/5608] Support beatmap conversion tests with mods --- .../CatchBeatmapConversionTest.cs | 2 +- .../ManiaBeatmapConversionTest.cs | 2 +- osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs | 2 +- .../TaikoBeatmapConversionTest.cs | 2 +- osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index e45ed8c6f4..3a695ca179 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.Tests [TestCase("spinner")] [TestCase("spinner-and-circles")] [TestCase("slider")] - public new void Test(string name) + public void Test(string name) { base.Test(name); } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index 51c7ba029a..3ca9dcc42c 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Mania.Tests protected override string ResourceAssembly => "osu.Game.Rulesets.Mania"; [TestCase("basic")] - public new void Test(string name) + public void Test(string name) { base.Test(name); } diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index f98d63e6c7..6a6d0abe24 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Tests [TestCase("basic")] [TestCase("colinear-perfect-curve")] [TestCase("slider-ticks")] - public new void Test(string name) + public void Test(string name) { base.Test(name); } diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index 68ae7544c2..bafa814582 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Taiko.Tests [NonParallelizable] [TestCase("basic")] [TestCase("slider-generating-drumroll")] - public new void Test(string name) + public void Test(string name) { base.Test(name); } diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 1f2d457624..a555a52e42 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -28,9 +28,9 @@ namespace osu.Game.Tests.Beatmaps protected abstract string ResourceAssembly { get; } - protected void Test(string name) + protected void Test(string name, params Type[] mods) { - var ourResult = convert(name); + var ourResult = convert(name, mods.Select(m => (Mod)Activator.CreateInstance(m)).ToArray()); var expectedResult = read(name); Assert.Multiple(() => @@ -92,7 +92,7 @@ namespace osu.Game.Tests.Beatmaps }); } - private ConvertResult convert(string name) + private ConvertResult convert(string name, Mod[] mods) { var beatmap = getBeatmap(name); @@ -110,7 +110,7 @@ namespace osu.Game.Tests.Beatmaps } }; - working.GetPlayableBeatmap(rulesetInstance.RulesetInfo, Array.Empty()); + working.GetPlayableBeatmap(rulesetInstance.RulesetInfo, mods); return new ConvertResult { From fdc6a3958d3655e799420469c1fe17f4cecd11a9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 31 Jul 2019 18:44:01 +0900 Subject: [PATCH 2139/5608] Make catch HR properly utilise the RNG --- .../Beatmaps/CatchBeatmapProcessor.cs | 119 +++++++++++++++++- .../MathUtils/FastRandom.cs | 8 ++ .../Mods/CatchModHardRock.cs | 112 +---------------- 3 files changed, 127 insertions(+), 112 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 645cb5701a..343f48f15c 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -10,6 +10,8 @@ using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects.Types; using osuTK; using osu.Game.Rulesets.Catch.MathUtils; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Catch.Beatmaps { @@ -26,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { base.PostProcess(); - applyPositionOffsets(); + ApplyPositionOffsets(Beatmap); initialiseHyperDash((List)Beatmap.HitObjects); @@ -40,15 +42,23 @@ namespace osu.Game.Rulesets.Catch.Beatmaps } } - private void applyPositionOffsets() + public static void ApplyPositionOffsets(IBeatmap beatmap, params Mod[] mods) { var rng = new FastRandom(RNG_SEED); - // todo: HardRock displacement should be applied here - foreach (var obj in Beatmap.HitObjects) + bool shouldApplyHardRockOffset = mods.Any(m => m is ModHardRock); + float? lastPosition = null; + double lastStartTime = 0; + + foreach (var obj in beatmap.HitObjects) { switch (obj) { + case Fruit fruit: + if (shouldApplyHardRockOffset) + applyHardRockOffset(fruit, ref lastPosition, ref lastStartTime, rng); + break; + case BananaShower bananaShower: foreach (var banana in bananaShower.NestedHitObjects.OfType()) { @@ -76,6 +86,107 @@ namespace osu.Game.Rulesets.Catch.Beatmaps } } + private static void applyHardRockOffset(HitObject hitObject, ref float? lastPosition, ref double lastStartTime, FastRandom rng) + { + if (hitObject is JuiceStream stream) + { + lastPosition = stream.EndX; + lastStartTime = stream.EndTime; + return; + } + + if (!(hitObject is Fruit)) + return; + + var catchObject = (CatchHitObject)hitObject; + + float position = catchObject.X; + double startTime = hitObject.StartTime; + + if (lastPosition == null) + { + lastPosition = position; + lastStartTime = startTime; + + return; + } + + float positionDiff = position - lastPosition.Value; + double timeDiff = startTime - lastStartTime; + + if (timeDiff > 1000) + { + lastPosition = position; + lastStartTime = startTime; + return; + } + + if (positionDiff == 0) + { + applyRandomOffset(ref position, timeDiff / 4d, rng); + catchObject.X = position; + return; + } + + if (Math.Abs(positionDiff * CatchPlayfield.BASE_WIDTH) < timeDiff / 3d) + applyOffset(ref position, positionDiff); + + catchObject.X = position; + + lastPosition = position; + lastStartTime = startTime; + } + + /// + /// Applies a random offset in a random direction to a position, ensuring that the final position remains within the boundary of the playfield. + /// + /// The position which the offset should be applied to. + /// The maximum offset, cannot exceed 20px. + /// The random number generator. + private static void applyRandomOffset(ref float position, double maxOffset, FastRandom rng) + { + bool right = rng.NextBool(); + float rand = Math.Min(20, (float)rng.Next(0, Math.Max(0, maxOffset))) / CatchPlayfield.BASE_WIDTH; + + if (right) + { + // Clamp to the right bound + if (position + rand <= 1) + position += rand; + else + position -= rand; + } + else + { + // Clamp to the left bound + if (position - rand >= 0) + position -= rand; + else + position += rand; + } + } + + /// + /// Applies an offset to a position, ensuring that the final position remains within the boundary of the playfield. + /// + /// The position which the offset should be applied to. + /// The amount to offset by. + private static void applyOffset(ref float position, float amount) + { + if (amount > 0) + { + // Clamp to the right bound + if (position + amount < 1) + position += amount; + } + else + { + // Clamp to the left bound + if (position + amount > 0) + position += amount; + } + } + private void initialiseHyperDash(List objects) { List objectWithDroplets = new List(); diff --git a/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs b/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs index b3605b013b..c721ff862a 100644 --- a/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs +++ b/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs @@ -61,6 +61,14 @@ namespace osu.Game.Rulesets.Catch.MathUtils /// The random value. public int Next(int lowerBound, int upperBound) => (int)(lowerBound + NextDouble() * (upperBound - lowerBound)); + /// + /// Generates a random integer value within the range [, ). + /// + /// The lower bound of the range. + /// The upper bound of the range. + /// The random value. + public int Next(double lowerBound, double upperBound) => (int)(lowerBound + NextDouble() * (upperBound - lowerBound)); + /// /// Generates a random double value within the range [0, 1). /// diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs index 060e51e31d..ced1900ba9 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs @@ -1,121 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.MathUtils; -using osu.Game.Rulesets.Catch.Objects; -using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Mods; -using System; -using osu.Game.Rulesets.Objects; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Beatmaps; namespace osu.Game.Rulesets.Catch.Mods { - public class CatchModHardRock : ModHardRock, IApplicableToHitObject + public class CatchModHardRock : ModHardRock, IApplicableToBeatmap { public override double ScoreMultiplier => 1.12; public override bool Ranked => true; - private float? lastPosition; - private double lastStartTime; - - public void ApplyToHitObject(HitObject hitObject) - { - if (hitObject is JuiceStream stream) - { - lastPosition = stream.EndX; - lastStartTime = stream.EndTime; - return; - } - - if (!(hitObject is Fruit)) - return; - - var catchObject = (CatchHitObject)hitObject; - - float position = catchObject.X; - double startTime = hitObject.StartTime; - - if (lastPosition == null) - { - lastPosition = position; - lastStartTime = startTime; - - return; - } - - float positionDiff = position - lastPosition.Value; - double timeDiff = startTime - lastStartTime; - - if (timeDiff > 1000) - { - lastPosition = position; - lastStartTime = startTime; - return; - } - - if (positionDiff == 0) - { - applyRandomOffset(ref position, timeDiff / 4d); - catchObject.X = position; - return; - } - - if (Math.Abs(positionDiff * CatchPlayfield.BASE_WIDTH) < timeDiff / 3d) - applyOffset(ref position, positionDiff); - - catchObject.X = position; - - lastPosition = position; - lastStartTime = startTime; - } - - /// - /// Applies a random offset in a random direction to a position, ensuring that the final position remains within the boundary of the playfield. - /// - /// The position which the offset should be applied to. - /// The maximum offset, cannot exceed 20px. - private void applyRandomOffset(ref float position, double maxOffset) - { - bool right = RNG.NextBool(); - float rand = Math.Min(20, (float)RNG.NextDouble(0, Math.Max(0, maxOffset))) / CatchPlayfield.BASE_WIDTH; - - if (right) - { - // Clamp to the right bound - if (position + rand <= 1) - position += rand; - else - position -= rand; - } - else - { - // Clamp to the left bound - if (position - rand >= 0) - position -= rand; - else - position += rand; - } - } - - /// - /// Applies an offset to a position, ensuring that the final position remains within the boundary of the playfield. - /// - /// The position which the offset should be applied to. - /// The amount to offset by. - private void applyOffset(ref float position, float amount) - { - if (amount > 0) - { - // Clamp to the right bound - if (position + amount < 1) - position += amount; - } - else - { - // Clamp to the left bound - if (position + amount > 0) - position += amount; - } - } + public void ApplyToBeatmap(IBeatmap beatmap) => CatchBeatmapProcessor.ApplyPositionOffsets(beatmap, this); } } From 38a2b9d92b5af230ee315f6e223f4a6da3f46373 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Aug 2019 13:33:00 +0900 Subject: [PATCH 2140/5608] Fix multiple invocations by using a separate variable --- .../Beatmaps/CatchBeatmapProcessor.cs | 32 +++++++++---------- .../Objects/CatchHitObject.cs | 14 +++++++- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 343f48f15c..ffff9b854d 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -11,7 +11,6 @@ using osu.Game.Rulesets.Objects.Types; using osuTK; using osu.Game.Rulesets.Catch.MathUtils; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Catch.Beatmaps { @@ -50,8 +49,10 @@ namespace osu.Game.Rulesets.Catch.Beatmaps float? lastPosition = null; double lastStartTime = 0; - foreach (var obj in beatmap.HitObjects) + foreach (var obj in beatmap.HitObjects.OfType()) { + obj.XOffset = 0; + switch (obj) { case Fruit fruit: @@ -62,7 +63,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps case BananaShower bananaShower: foreach (var banana in bananaShower.NestedHitObjects.OfType()) { - banana.X = (float)rng.NextDouble(); + banana.XOffset = (float)rng.NextDouble(); rng.Next(); // osu!stable retrieved a random banana type rng.Next(); // osu!stable retrieved a random banana rotation rng.Next(); // osu!stable retrieved a random banana colour @@ -75,10 +76,9 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { var hitObject = (CatchHitObject)nested; if (hitObject is TinyDroplet) - hitObject.X += rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH; + hitObject.XOffset = MathHelper.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -hitObject.X, 1 - hitObject.X); else if (hitObject is Droplet) rng.Next(); // osu!stable retrieved a random droplet rotation - hitObject.X = MathHelper.Clamp(hitObject.X, 0, 1); } break; @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps } } - private static void applyHardRockOffset(HitObject hitObject, ref float? lastPosition, ref double lastStartTime, FastRandom rng) + private static void applyHardRockOffset(CatchHitObject hitObject, ref float? lastPosition, ref double lastStartTime, FastRandom rng) { if (hitObject is JuiceStream stream) { @@ -98,42 +98,40 @@ namespace osu.Game.Rulesets.Catch.Beatmaps if (!(hitObject is Fruit)) return; - var catchObject = (CatchHitObject)hitObject; - - float position = catchObject.X; + float offsetPosition = hitObject.X; double startTime = hitObject.StartTime; if (lastPosition == null) { - lastPosition = position; + lastPosition = offsetPosition; lastStartTime = startTime; return; } - float positionDiff = position - lastPosition.Value; + float positionDiff = offsetPosition - lastPosition.Value; double timeDiff = startTime - lastStartTime; if (timeDiff > 1000) { - lastPosition = position; + lastPosition = offsetPosition; lastStartTime = startTime; return; } if (positionDiff == 0) { - applyRandomOffset(ref position, timeDiff / 4d, rng); - catchObject.X = position; + applyRandomOffset(ref offsetPosition, timeDiff / 4d, rng); + hitObject.XOffset = hitObject.X - offsetPosition; return; } if (Math.Abs(positionDiff * CatchPlayfield.BASE_WIDTH) < timeDiff / 3d) - applyOffset(ref position, positionDiff); + applyOffset(ref offsetPosition, positionDiff); - catchObject.X = position; + hitObject.XOffset = hitObject.X - offsetPosition; - lastPosition = position; + lastPosition = offsetPosition; lastStartTime = startTime; } diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index be76edc01b..19a1b59752 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -3,6 +3,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -12,7 +13,18 @@ namespace osu.Game.Rulesets.Catch.Objects { public const double OBJECT_RADIUS = 44; - public float X { get; set; } + private float x; + + public float X + { + get => x + XOffset; + set => x = value; + } + + /// + /// A random offset applied to , set by the . + /// + internal float XOffset { get; set; } public double TimePreempt = 1000; From e2420af10c844d9459fd906b3035086c949e3266 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Aug 2019 13:37:40 +0900 Subject: [PATCH 2141/5608] Fix applying mods to the wrong beatmap --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index baf921ddfc..c6105f6566 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -142,7 +142,7 @@ namespace osu.Game.Beatmaps processor?.PostProcess(); foreach (var mod in mods.OfType()) - mod.ApplyToBeatmap(Beatmap); + mod.ApplyToBeatmap(converted); return converted; } From d05b9b1734bf9734ce9434721ef5ee990ef6dd38 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 1 Aug 2019 14:19:45 +0900 Subject: [PATCH 2142/5608] Use dummyAPI and move load check into MusicController --- .../Visual/Menus/TestSceneScreenNavigation.cs | 26 +++++++++++++------ osu.Game/OsuGame.cs | 2 +- osu.Game/Overlays/MusicController.cs | 4 +++ osu.Game/Screens/Multi/Multiplayer.cs | 2 +- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index f71e8dc2ce..88dac8d0ff 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -8,11 +8,11 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Screens; @@ -111,6 +111,7 @@ namespace osu.Game.Tests.Visual.Menus [Test] public void TestOpenOptionsAndExitWithEscape() { + AddUntilStep("Wait for options to load", () => osuGame.Settings.IsLoaded); AddStep("Enter menu", () => pressAndRelease(Key.Enter)); AddStep("Move mouse to options overlay", () => InputManager.MoveMouseTo(optionsButtonPosition)); AddStep("Click options overlay", () => InputManager.Click(MouseButton.Left)); @@ -122,13 +123,7 @@ namespace osu.Game.Tests.Visual.Menus private void pushAndConfirm(Func newScreen, string screenName) { Screen screen = null; - AddStep($"Push new {screenName}", () => - { - if (screenName == "song select") - Logger.Log("fuck"); - - osuGame.ScreenStack.Push(screen = newScreen()); - }); + AddStep($"Push new {screenName}", () => osuGame.ScreenStack.Push(screen = newScreen())); AddUntilStep($"Wait for new {screenName}", () => osuGame.ScreenStack.CurrentScreen == screen && screen.IsLoaded); } @@ -160,6 +155,21 @@ namespace osu.Game.Tests.Visual.Menus public new SettingsPanel Settings => base.Settings; protected override Loader CreateLoader() => new TestLoader(); + + private DependencyContainer dependencies; + + private DummyAPIAccess dummyAPI; + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => + dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + + protected override void LoadComplete() + { + base.LoadComplete(); + dependencies.CacheAs(dummyAPI = new DummyAPIAccess()); + + dummyAPI.Login("Rhythm Champion", "osu!"); + } } private class TestSongSelect : PlaySongSelect diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e7c0d01f31..63ec349d3d 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -318,7 +318,7 @@ namespace osu.Game private void currentTrackCompleted() { - if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled && musicController.IsLoaded) + if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled) musicController.NextTrack(); } diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index abbcec5094..91ae92320a 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -316,6 +316,10 @@ namespace osu.Game.Overlays private void next(bool instant = false) { + // beatmapSets doesn't get populated until loading has completed. + if (!IsLoaded) + return; + if (!instant) queuedDirection = TransformDirection.Next; diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 3d9997e236..9550d883fd 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -168,7 +168,7 @@ namespace osu.Game.Screens.Multi public void APIStateChanged(IAPIProvider api, APIState state) { - if (RequireOnline && state != APIState.Online) + if (state != APIState.Online) forcefullyExit(); } From 423857f403581907eef4c44cc97199e5d84546f3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Aug 2019 14:57:07 +0900 Subject: [PATCH 2143/5608] Fix inverted offset --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index ffff9b854d..3ee2928573 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -122,14 +122,14 @@ namespace osu.Game.Rulesets.Catch.Beatmaps if (positionDiff == 0) { applyRandomOffset(ref offsetPosition, timeDiff / 4d, rng); - hitObject.XOffset = hitObject.X - offsetPosition; + hitObject.XOffset = offsetPosition - hitObject.X; return; } if (Math.Abs(positionDiff * CatchPlayfield.BASE_WIDTH) < timeDiff / 3d) applyOffset(ref offsetPosition, positionDiff); - hitObject.XOffset = hitObject.X - offsetPosition; + hitObject.XOffset = offsetPosition - hitObject.X; lastPosition = offsetPosition; lastStartTime = startTime; From 8a1d690011665ab19aceb2bd6ada65185517e7d2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Aug 2019 14:57:17 +0900 Subject: [PATCH 2144/5608] Reset tick offsets --- .../Beatmaps/CatchBeatmapProcessor.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 3ee2928573..5ab47c1611 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -74,10 +74,12 @@ namespace osu.Game.Rulesets.Catch.Beatmaps case JuiceStream juiceStream: foreach (var nested in juiceStream.NestedHitObjects) { - var hitObject = (CatchHitObject)nested; - if (hitObject is TinyDroplet) - hitObject.XOffset = MathHelper.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -hitObject.X, 1 - hitObject.X); - else if (hitObject is Droplet) + var catchObject = (CatchHitObject)nested; + catchObject.XOffset = 0; + + if (catchObject is TinyDroplet) + catchObject.XOffset = MathHelper.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); + else if (catchObject is Droplet) rng.Next(); // osu!stable retrieved a random droplet rotation } From b978727422b8a163aaa7402ba91951a6dc303e80 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Aug 2019 14:58:17 +0900 Subject: [PATCH 2145/5608] Add stream + repeat slider tests --- .../CatchBeatmapConversionTest.cs | 7 +- ...ock-repeat-slider-expected-conversion.json | 150 +++++++++++ .../Beatmaps/hardrock-repeat-slider.osu | 18 ++ .../hardrock-stream-expected-conversion.json | 234 ++++++++++++++++++ .../Testing/Beatmaps/hardrock-stream.osu | 107 ++++++++ 5 files changed, 514 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-repeat-slider-expected-conversion.json create mode 100644 osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-repeat-slider.osu create mode 100644 osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-stream-expected-conversion.json create mode 100644 osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-stream.osu diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index 3a695ca179..80ac64c5f9 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Newtonsoft.Json; using NUnit.Framework; using osu.Framework.MathUtils; +using osu.Game.Rulesets.Catch.Mods; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects; @@ -22,9 +23,11 @@ namespace osu.Game.Rulesets.Catch.Tests [TestCase("spinner")] [TestCase("spinner-and-circles")] [TestCase("slider")] - public void Test(string name) + [TestCase("hardrock-stream", new[] { typeof(CatchModHardRock) })] + [TestCase("hardrock-repeat-slider", new[] { typeof(CatchModHardRock) })] + public new void Test(string name, params Type[] mods) { - base.Test(name); + base.Test(name, mods); } protected override IEnumerable CreateConvertValue(HitObject hitObject) diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-repeat-slider-expected-conversion.json b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-repeat-slider-expected-conversion.json new file mode 100644 index 0000000000..83f9e30800 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-repeat-slider-expected-conversion.json @@ -0,0 +1,150 @@ +{ + "Mappings": [{ + "StartTime": 369, + "Objects": [{ + "StartTime": 369, + "Position": 177 + }, + { + "StartTime": 450, + "Position": 216.539276 + }, + { + "StartTime": 532, + "Position": 256.5667 + }, + { + "StartTime": 614, + "Position": 296.594116 + }, + { + "StartTime": 696, + "Position": 336.621521 + }, + { + "StartTime": 778, + "Position": 376.99762 + }, + { + "StartTime": 860, + "Position": 337.318878 + }, + { + "StartTime": 942, + "Position": 297.291443 + }, + { + "StartTime": 1024, + "Position": 257.264038 + }, + { + "StartTime": 1106, + "Position": 217.2366 + }, + { + "StartTime": 1188, + "Position": 177 + }, + { + "StartTime": 1270, + "Position": 216.818192 + }, + { + "StartTime": 1352, + "Position": 256.8456 + }, + { + "StartTime": 1434, + "Position": 296.873047 + }, + { + "StartTime": 1516, + "Position": 336.900452 + }, + { + "StartTime": 1598, + "Position": 376.99762 + }, + { + "StartTime": 1680, + "Position": 337.039948 + }, + { + "StartTime": 1762, + "Position": 297.0125 + }, + { + "StartTime": 1844, + "Position": 256.9851 + }, + { + "StartTime": 1926, + "Position": 216.957672 + }, + { + "StartTime": 2008, + "Position": 177 + }, + { + "StartTime": 2090, + "Position": 217.097137 + }, + { + "StartTime": 2172, + "Position": 257.124573 + }, + { + "StartTime": 2254, + "Position": 297.152 + }, + { + "StartTime": 2336, + "Position": 337.179443 + }, + { + "StartTime": 2418, + "Position": 376.99762 + }, + { + "StartTime": 2500, + "Position": 336.760956 + }, + { + "StartTime": 2582, + "Position": 296.733643 + }, + { + "StartTime": 2664, + "Position": 256.7062 + }, + { + "StartTime": 2746, + "Position": 216.678772 + }, + { + "StartTime": 2828, + "Position": 177 + }, + { + "StartTime": 2909, + "Position": 216.887909 + }, + { + "StartTime": 2991, + "Position": 256.915344 + }, + { + "StartTime": 3073, + "Position": 296.942749 + }, + { + "StartTime": 3155, + "Position": 336.970184 + }, + { + "StartTime": 3237, + "Position": 376.99762 + } + ] + }] +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-repeat-slider.osu b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-repeat-slider.osu new file mode 100644 index 0000000000..c1971edf2c --- /dev/null +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-repeat-slider.osu @@ -0,0 +1,18 @@ +osu file format v14 + +[General] +StackLeniency: 0.4 +Mode: 0 + +[Difficulty] +CircleSize:4 +OverallDifficulty:7 +ApproachRate:8 +SliderMultiplier:1.6 +SliderTickRate:4 + +[TimingPoints] +369,327.868852459016,4,2,2,32,1,0 + +[HitObjects] +177,191,369,6,0,L|382:192,7,200 diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-stream-expected-conversion.json b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-stream-expected-conversion.json new file mode 100644 index 0000000000..bbc16ab912 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-stream-expected-conversion.json @@ -0,0 +1,234 @@ +{ + "Mappings": [{ + "StartTime": 369, + "Objects": [{ + "StartTime": 369, + "Position": 258 + }] + }, + { + "StartTime": 450, + "Objects": [{ + "StartTime": 450, + "Position": 254 + }] + }, + { + "StartTime": 532, + "Objects": [{ + "StartTime": 532, + "Position": 241 + }] + }, + { + "StartTime": 614, + "Objects": [{ + "StartTime": 614, + "Position": 238 + }] + }, + { + "StartTime": 696, + "Objects": [{ + "StartTime": 696, + "Position": 238 + }] + }, + { + "StartTime": 778, + "Objects": [{ + "StartTime": 778, + "Position": 278 + }] + }, + { + "StartTime": 860, + "Objects": [{ + "StartTime": 860, + "Position": 238 + }] + }, + { + "StartTime": 942, + "Objects": [{ + "StartTime": 942, + "Position": 278 + }] + }, + { + "StartTime": 1024, + "Objects": [{ + "StartTime": 1024, + "Position": 238 + }] + }, + { + "StartTime": 1106, + "Objects": [{ + "StartTime": 1106, + "Position": 278 + }] + }, + { + "StartTime": 1188, + "Objects": [{ + "StartTime": 1188, + "Position": 278 + }] + }, + { + "StartTime": 1270, + "Objects": [{ + "StartTime": 1270, + "Position": 278 + }] + }, + { + "StartTime": 1352, + "Objects": [{ + "StartTime": 1352, + "Position": 238 + }] + }, + { + "StartTime": 1434, + "Objects": [{ + "StartTime": 1434, + "Position": 258 + }] + }, + { + "StartTime": 1516, + "Objects": [{ + "StartTime": 1516, + "Position": 253 + }] + }, + { + "StartTime": 1598, + "Objects": [{ + "StartTime": 1598, + "Position": 238 + }] + }, + { + "StartTime": 1680, + "Objects": [{ + "StartTime": 1680, + "Position": 260 + }] + }, + { + "StartTime": 1762, + "Objects": [{ + "StartTime": 1762, + "Position": 238 + }] + }, + { + "StartTime": 1844, + "Objects": [{ + "StartTime": 1844, + "Position": 278 + }] + }, + { + "StartTime": 1926, + "Objects": [{ + "StartTime": 1926, + "Position": 278 + }] + }, + { + "StartTime": 2008, + "Objects": [{ + "StartTime": 2008, + "Position": 238 + }] + }, + { + "StartTime": 2090, + "Objects": [{ + "StartTime": 2090, + "Position": 238 + }] + }, + { + "StartTime": 2172, + "Objects": [{ + "StartTime": 2172, + "Position": 243 + }] + }, + { + "StartTime": 2254, + "Objects": [{ + "StartTime": 2254, + "Position": 278 + }] + }, + { + "StartTime": 2336, + "Objects": [{ + "StartTime": 2336, + "Position": 278 + }] + }, + { + "StartTime": 2418, + "Objects": [{ + "StartTime": 2418, + "Position": 238 + }] + }, + { + "StartTime": 2500, + "Objects": [{ + "StartTime": 2500, + "Position": 258 + }] + }, + { + "StartTime": 2582, + "Objects": [{ + "StartTime": 2582, + "Position": 256 + }] + }, + { + "StartTime": 2664, + "Objects": [{ + "StartTime": 2664, + "Position": 242 + }] + }, + { + "StartTime": 2746, + "Objects": [{ + "StartTime": 2746, + "Position": 238 + }] + }, + { + "StartTime": 2828, + "Objects": [{ + "StartTime": 2828, + "Position": 238 + }] + }, + { + "StartTime": 2909, + "Objects": [{ + "StartTime": 2909, + "Position": 271 + }] + }, + { + "StartTime": 2991, + "Objects": [{ + "StartTime": 2991, + "Position": 254 + }] + } + ] +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-stream.osu b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-stream.osu new file mode 100644 index 0000000000..62835135df --- /dev/null +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-stream.osu @@ -0,0 +1,107 @@ +osu file format v14 + +[General] +AudioFilename: audio.mp3 +AudioLeadIn: 0 +PreviewTime: 53483 +Countdown: 0 +SampleSet: Soft +StackLeniency: 0.4 +Mode: 0 +LetterboxInBreaks: 0 +WidescreenStoryboard: 0 + +[Editor] +Bookmarks: 369,1680,12172,22664,33155,43647,54139,64631,75123,85614,96106,103975,114467,124959,135287 +DistanceSpacing: 1 +BeatDivisor: 4 +GridSize: 8 +TimelineZoom: 2.899999 + +[Metadata] +Title:Silhouette +TitleUnicode:シルエット +Artist:KANA-BOON +ArtistUnicode:KANA-BOON +Creator:Nevo +Version:lit120's Hard +Source:NARUTO-ナルト-疾風伝 +Tags:shippuuden shipuuden shippuden nine tails opening 16 kage cut ver version naotoshi nao tomori shunao shogunmoon sotarks pika [[pika]] frostwich lit120 shiratoi armin a_r_m_i_n +BeatmapID:1653115 +BeatmapSetID:780952 + +[Difficulty] +HPDrainRate:6 +CircleSize:4 +OverallDifficulty:7 +ApproachRate:8 +SliderMultiplier:1.6 +SliderTickRate:1 + +[Events] +//Background and Video events +0,0,"OSpGdEP.png",0,0 +//Break Periods +//Storyboard Layer 0 (Background) +//Storyboard Layer 1 (Fail) +//Storyboard Layer 2 (Pass) +//Storyboard Layer 3 (Foreground) +//Storyboard Sound Samples + +[TimingPoints] +369,327.868852459016,4,2,2,32,1,0 +1680,-100,4,2,2,42,0,0 +6926,-100,4,2,2,52,0,0 +11844,-100,4,2,2,5,0,0 +12172,-100,4,2,2,62,0,0 +22664,-100,4,2,2,52,0,0 +43647,-100,4,2,2,52,0,0 +53483,-100,4,2,2,32,0,0 +54139,-100,4,2,2,72,0,1 +96106,-100,4,2,2,52,0,0 +103975,-100,4,2,2,82,0,1 +124959,-100,4,2,2,62,0,0 +130205,-100,4,2,2,72,0,0 +132991,-100,4,2,2,82,0,0 + + +[Colours] +Combo1 : 154,53,255 +Combo2 : 253,211,47 +Combo3 : 86,168,250 +Combo4 : 192,192,192 + +[HitObjects] +258,189,369,1,0,0:0:0:0: +258,189,450,1,0,0:0:0:0: +258,189,532,1,0,0:0:0:0: +258,189,614,1,0,0:0:0:0: +258,189,696,1,0,0:0:0:0: +258,189,778,1,0,0:0:0:0: +258,189,860,1,0,0:0:0:0: +258,189,942,1,0,0:0:0:0: +258,189,1024,1,0,0:0:0:0: +258,189,1106,1,0,0:0:0:0: +258,189,1188,1,0,0:0:0:0: +258,189,1270,1,0,0:0:0:0: +258,189,1352,1,0,0:0:0:0: +258,189,1434,1,0,0:0:0:0: +258,189,1516,1,0,0:0:0:0: +258,189,1598,1,0,0:0:0:0: +258,189,1680,1,0,0:0:0:0: +258,189,1762,1,0,0:0:0:0: +258,189,1844,1,0,0:0:0:0: +258,189,1926,1,0,0:0:0:0: +258,189,2008,1,0,0:0:0:0: +258,189,2090,1,0,0:0:0:0: +258,189,2172,1,0,0:0:0:0: +258,189,2254,1,0,0:0:0:0: +258,189,2336,1,0,0:0:0:0: +258,189,2418,1,0,0:0:0:0: +258,189,2500,1,0,0:0:0:0: +258,189,2582,1,0,0:0:0:0: +258,189,2664,1,0,0:0:0:0: +258,189,2746,1,0,0:0:0:0: +258,189,2828,1,0,0:0:0:0: +258,189,2909,1,0,0:0:0:0: +258,189,2991,1,0,0:0:0:0: From d772bbaf8c77bae4a280a8facca67832b208d007 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 1 Aug 2019 10:04:04 +0300 Subject: [PATCH 2146/5608] Simplify disposing --- osu.Game/OsuGame.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 431e6c91f9..b9e2b79b05 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -307,11 +307,10 @@ namespace osu.Game if (nextBeatmap?.Track != null) nextBeatmap.Track.Completed += currentTrackCompleted; - var oldBeatmap = beatmap.OldValue; - if (oldBeatmap?.Track != null) - oldBeatmap.Track.Completed -= currentTrackCompleted; + using (var oldBeatmap = beatmap.OldValue) + if (oldBeatmap?.Track != null) + oldBeatmap.Track.Completed -= currentTrackCompleted; - oldBeatmap?.Dispose(); nextBeatmap?.LoadBeatmapAsync(); } From 0f36088ef894f0f94869d0c5df3d7bddfbb00151 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 1 Aug 2019 11:06:29 +0300 Subject: [PATCH 2147/5608] Add loved section --- osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs | 1 + osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs index f3384163b8..fb1385793f 100644 --- a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs @@ -27,6 +27,7 @@ namespace osu.Game.Online.API.Requests { Favourite, RankedAndApproved, + Loved, Unranked, Graveyard } diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs index ae91837d29..37f017277f 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs @@ -18,6 +18,7 @@ namespace osu.Game.Overlays.Profile.Sections { new PaginatedBeatmapContainer(BeatmapSetType.Favourite, User, "Favourite Beatmaps"), new PaginatedBeatmapContainer(BeatmapSetType.RankedAndApproved, User, "Ranked & Approved Beatmaps"), + new PaginatedBeatmapContainer(BeatmapSetType.Loved, User, "Loved Beatmaps"), new PaginatedBeatmapContainer(BeatmapSetType.Unranked, User, "Pending Beatmaps"), new PaginatedBeatmapContainer(BeatmapSetType.Graveyard, User, "Graveyarded Beatmaps"), }; From a2468e599b292d1c4d4da4cc5d49b87d38c01d98 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Aug 2019 17:31:26 +0900 Subject: [PATCH 2148/5608] Fix ticks in repeat spans being returned in reverse order --- .../Rulesets/Objects/SliderEventGenerator.cs | 60 ++++++++++++++----- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs index 7cda7485f9..9047d338aa 100644 --- a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -3,13 +3,15 @@ using System; using System.Collections.Generic; +using System.Linq; using osuTK; namespace osu.Game.Rulesets.Objects { public static class SliderEventGenerator { - public static IEnumerable Generate(double startTime, double spanDuration, double velocity, double tickDistance, double totalDistance, int spanCount, double? legacyLastTickOffset) + public static IEnumerable Generate(double startTime, double spanDuration, double velocity, double tickDistance, double totalDistance, int spanCount, + double? legacyLastTickOffset) { // A very lenient maximum length of a slider for ticks to be generated. // This exists for edge cases such as /b/1573664 where the beatmap has been edited by the user, and should never be reached in normal usage. @@ -36,24 +38,17 @@ namespace osu.Game.Rulesets.Objects var spanStartTime = startTime + span * spanDuration; var reversed = span % 2 == 1; - for (var d = tickDistance; d <= length; d += tickDistance) + var ticks = generateTicks(span, spanStartTime, spanDuration, reversed, length, tickDistance, minDistanceFromEnd); + + if (reversed) { - if (d >= length - minDistanceFromEnd) - break; - - var pathProgress = d / length; - var timeProgress = reversed ? 1 - pathProgress : pathProgress; - - yield return new SliderEventDescriptor - { - Type = SliderEventType.Tick, - SpanIndex = span, - SpanStartTime = spanStartTime, - Time = spanStartTime + timeProgress * spanDuration, - PathProgress = pathProgress, - }; + // For repeat spans, ticks are returned in reverse-StartTime order, which is undesirable for some rulesets + ticks = ticks.Reverse(); } + foreach (var e in ticks) + yield return e; + if (span < spanCount - 1) { yield return new SliderEventDescriptor @@ -103,6 +98,39 @@ namespace osu.Game.Rulesets.Objects PathProgress = spanCount % 2, }; } + + /// + /// Generates the ticks for a span of the slider. + /// + /// The span index. + /// The start time of the span. + /// The duration of the span. + /// Whether the span is reversed. + /// The length of the path. + /// The distance between each tick. + /// The distance from the end of the path at which ticks are not allowed to be added. + /// A for each tick. If is true, the ticks will be returned in reverse-StartTime order. + private static IEnumerable generateTicks(int spanIndex, double spanStartTime, double spanDuration, bool reversed, double length, double tickDistance, + double minDistanceFromEnd) + { + for (var d = tickDistance; d <= length; d += tickDistance) + { + if (d >= length - minDistanceFromEnd) + break; + + var pathProgress = d / length; + var timeProgress = reversed ? 1 - pathProgress : pathProgress; + + yield return new SliderEventDescriptor + { + Type = SliderEventType.Tick, + SpanIndex = spanIndex, + SpanStartTime = spanStartTime, + Time = spanStartTime + timeProgress * spanDuration, + PathProgress = pathProgress, + }; + } + } } /// From f2b940f930a89ebd14370eff3d231f402579197e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Aug 2019 17:31:08 +0900 Subject: [PATCH 2149/5608] Add tests --- .../OsuBeatmapConversionTest.cs | 2 + .../repeat-slider-expected-conversion.json | 222 +++++++++++ .../Testing/Beatmaps/repeat-slider.osu | 18 + ...ven-repeat-slider-expected-conversion.json | 348 ++++++++++++++++++ .../Testing/Beatmaps/uneven-repeat-slider.osu | 19 + .../Beatmaps/SliderEventGenerationTest.cs | 116 ++++++ 6 files changed, 725 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/repeat-slider-expected-conversion.json create mode 100644 osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/repeat-slider.osu create mode 100644 osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/uneven-repeat-slider-expected-conversion.json create mode 100644 osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/uneven-repeat-slider.osu create mode 100644 osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index f98d63e6c7..451ecf97ea 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Osu.Tests [TestCase("basic")] [TestCase("colinear-perfect-curve")] [TestCase("slider-ticks")] + [TestCase("repeat-slider")] + [TestCase("uneven-repeat-slider")] public new void Test(string name) { base.Test(name); diff --git a/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/repeat-slider-expected-conversion.json b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/repeat-slider-expected-conversion.json new file mode 100644 index 0000000000..fb4050963f --- /dev/null +++ b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/repeat-slider-expected-conversion.json @@ -0,0 +1,222 @@ +{ + "Mappings": [{ + "StartTime": 369, + "Objects": [{ + "StartTime": 369, + "EndTime": 369, + "X": 177, + "Y": 191 + }, + { + "StartTime": 450, + "EndTime": 450, + "X": 216.539276, + "Y": 191.192871 + }, + { + "StartTime": 532, + "EndTime": 532, + "X": 256.5667, + "Y": 191.388138 + }, + { + "StartTime": 614, + "EndTime": 614, + "X": 296.594116, + "Y": 191.583389 + }, + { + "StartTime": 696, + "EndTime": 696, + "X": 336.621521, + "Y": 191.778641 + }, + { + "StartTime": 778, + "EndTime": 778, + "X": 376.648926, + "Y": 191.9739 + }, + { + "StartTime": 860, + "EndTime": 860, + "X": 337.318878, + "Y": 191.782043 + }, + { + "StartTime": 942, + "EndTime": 942, + "X": 297.291443, + "Y": 191.586792 + }, + { + "StartTime": 1024, + "EndTime": 1024, + "X": 257.264038, + "Y": 191.391541 + }, + { + "StartTime": 1106, + "EndTime": 1106, + "X": 217.2366, + "Y": 191.196274 + }, + { + "StartTime": 1188, + "EndTime": 1188, + "X": 177.209213, + "Y": 191.001022 + }, + { + "StartTime": 1270, + "EndTime": 1270, + "X": 216.818192, + "Y": 191.194229 + }, + { + "StartTime": 1352, + "EndTime": 1352, + "X": 256.8456, + "Y": 191.3895 + }, + { + "StartTime": 1434, + "EndTime": 1434, + "X": 296.873047, + "Y": 191.584747 + }, + { + "StartTime": 1516, + "EndTime": 1516, + "X": 336.900452, + "Y": 191.78 + }, + { + "StartTime": 1598, + "EndTime": 1598, + "X": 376.927917, + "Y": 191.975266 + }, + { + "StartTime": 1680, + "EndTime": 1680, + "X": 337.039948, + "Y": 191.780685 + }, + { + "StartTime": 1762, + "EndTime": 1762, + "X": 297.0125, + "Y": 191.585434 + }, + { + "StartTime": 1844, + "EndTime": 1844, + "X": 256.9851, + "Y": 191.390167 + }, + { + "StartTime": 1926, + "EndTime": 1926, + "X": 216.957672, + "Y": 191.194916 + }, + { + "StartTime": 2008, + "EndTime": 2008, + "X": 177.069717, + "Y": 191.000336 + }, + { + "StartTime": 2090, + "EndTime": 2090, + "X": 217.097137, + "Y": 191.1956 + }, + { + "StartTime": 2172, + "EndTime": 2172, + "X": 257.124573, + "Y": 191.390854 + }, + { + "StartTime": 2254, + "EndTime": 2254, + "X": 297.152, + "Y": 191.5861 + }, + { + "StartTime": 2336, + "EndTime": 2336, + "X": 337.179443, + "Y": 191.781372 + }, + { + "StartTime": 2418, + "EndTime": 2418, + "X": 376.7884, + "Y": 191.974579 + }, + { + "StartTime": 2500, + "EndTime": 2500, + "X": 336.760956, + "Y": 191.779327 + }, + { + "StartTime": 2582, + "EndTime": 2582, + "X": 296.733643, + "Y": 191.584076 + }, + { + "StartTime": 2664, + "EndTime": 2664, + "X": 256.7062, + "Y": 191.388809 + }, + { + "StartTime": 2746, + "EndTime": 2746, + "X": 216.678772, + "Y": 191.193558 + }, + { + "StartTime": 2828, + "EndTime": 2828, + "X": 177.348663, + "Y": 191.0017 + }, + { + "StartTime": 2909, + "EndTime": 2909, + "X": 216.887909, + "Y": 191.19458 + }, + { + "StartTime": 2991, + "EndTime": 2991, + "X": 256.915344, + "Y": 191.389832 + }, + { + "StartTime": 3073, + "EndTime": 3073, + "X": 296.942749, + "Y": 191.585083 + }, + { + "StartTime": 3155, + "EndTime": 3155, + "X": 336.970184, + "Y": 191.78035 + }, + { + "StartTime": 3201, + "EndTime": 3201, + "X": 376.99762, + "Y": 191.9756 + } + ] + }] +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/repeat-slider.osu b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/repeat-slider.osu new file mode 100644 index 0000000000..624d905384 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/repeat-slider.osu @@ -0,0 +1,18 @@ +osu file format v14 + +[General] +StackLeniency: 0.4 +Mode: 0 + +[Difficulty] +CircleSize:4 +OverallDifficulty:7 +ApproachRate:8 +SliderMultiplier:1.6 +SliderTickRate:4 + +[TimingPoints] +369,327.868852459016,4,2,2,32,1,0 + +[HitObjects] +177,191,369,6,0,L|382:192,7,200 \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/uneven-repeat-slider-expected-conversion.json b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/uneven-repeat-slider-expected-conversion.json new file mode 100644 index 0000000000..12d1645c04 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/uneven-repeat-slider-expected-conversion.json @@ -0,0 +1,348 @@ +{ + "Mappings": [{ + "StartTime": 369, + "Objects": [{ + "StartTime": 369, + "EndTime": 369, + "X": 127, + "Y": 194 + }, + { + "StartTime": 450, + "EndTime": 450, + "X": 166.53389, + "Y": 193.8691 + }, + { + "StartTime": 532, + "EndTime": 532, + "X": 206.555847, + "Y": 193.736572 + }, + { + "StartTime": 614, + "EndTime": 614, + "X": 246.57782, + "Y": 193.60405 + }, + { + "StartTime": 696, + "EndTime": 696, + "X": 286.5998, + "Y": 193.471527 + }, + { + "StartTime": 778, + "EndTime": 778, + "X": 326.621765, + "Y": 193.339 + }, + { + "StartTime": 860, + "EndTime": 860, + "X": 366.6437, + "Y": 193.206482 + }, + { + "StartTime": 942, + "EndTime": 942, + "X": 406.66568, + "Y": 193.073959 + }, + { + "StartTime": 970, + "EndTime": 970, + "X": 420.331726, + "Y": 193.0287 + }, + { + "StartTime": 997, + "EndTime": 997, + "X": 407.153748, + "Y": 193.072342 + }, + { + "StartTime": 1079, + "EndTime": 1079, + "X": 367.131775, + "Y": 193.204865 + }, + { + "StartTime": 1161, + "EndTime": 1161, + "X": 327.1098, + "Y": 193.337387 + }, + { + "StartTime": 1243, + "EndTime": 1243, + "X": 287.08783, + "Y": 193.46991 + }, + { + "StartTime": 1325, + "EndTime": 1325, + "X": 247.0659, + "Y": 193.602432 + }, + { + "StartTime": 1407, + "EndTime": 1407, + "X": 207.043915, + "Y": 193.734955 + }, + { + "StartTime": 1489, + "EndTime": 1489, + "X": 167.021988, + "Y": 193.867477 + }, + { + "StartTime": 1571, + "EndTime": 1571, + "X": 127, + "Y": 194 + }, + { + "StartTime": 1653, + "EndTime": 1653, + "X": 167.021988, + "Y": 193.867477 + }, + { + "StartTime": 1735, + "EndTime": 1735, + "X": 207.043976, + "Y": 193.734955 + }, + { + "StartTime": 1817, + "EndTime": 1817, + "X": 247.065887, + "Y": 193.602432 + }, + { + "StartTime": 1899, + "EndTime": 1899, + "X": 287.08783, + "Y": 193.46991 + }, + { + "StartTime": 1981, + "EndTime": 1981, + "X": 327.1098, + "Y": 193.337387 + }, + { + "StartTime": 2062, + "EndTime": 2062, + "X": 366.643738, + "Y": 193.206482 + }, + { + "StartTime": 2144, + "EndTime": 2144, + "X": 406.665649, + "Y": 193.073959 + }, + { + "StartTime": 2172, + "EndTime": 2172, + "X": 420.331726, + "Y": 193.0287 + }, + { + "StartTime": 2199, + "EndTime": 2199, + "X": 407.153748, + "Y": 193.072342 + }, + { + "StartTime": 2281, + "EndTime": 2281, + "X": 367.1318, + "Y": 193.204865 + }, + { + "StartTime": 2363, + "EndTime": 2363, + "X": 327.1098, + "Y": 193.337387 + }, + { + "StartTime": 2445, + "EndTime": 2445, + "X": 287.08783, + "Y": 193.46991 + }, + { + "StartTime": 2527, + "EndTime": 2527, + "X": 247.065887, + "Y": 193.602432 + }, + { + "StartTime": 2609, + "EndTime": 2609, + "X": 207.043976, + "Y": 193.734955 + }, + { + "StartTime": 2691, + "EndTime": 2691, + "X": 167.021988, + "Y": 193.867477 + }, + { + "StartTime": 2773, + "EndTime": 2773, + "X": 127, + "Y": 194 + }, + { + "StartTime": 2855, + "EndTime": 2855, + "X": 167.021988, + "Y": 193.867477 + }, + { + "StartTime": 2937, + "EndTime": 2937, + "X": 207.043976, + "Y": 193.734955 + }, + { + "StartTime": 3019, + "EndTime": 3019, + "X": 247.065948, + "Y": 193.602432 + }, + { + "StartTime": 3101, + "EndTime": 3101, + "X": 287.087952, + "Y": 193.46991 + }, + { + "StartTime": 3183, + "EndTime": 3183, + "X": 327.109772, + "Y": 193.337387 + }, + { + "StartTime": 3265, + "EndTime": 3265, + "X": 367.131775, + "Y": 193.204865 + }, + { + "StartTime": 3347, + "EndTime": 3347, + "X": 407.153748, + "Y": 193.072342 + }, + { + "StartTime": 3374, + "EndTime": 3374, + "X": 420.331726, + "Y": 193.0287 + }, + { + "StartTime": 3401, + "EndTime": 3401, + "X": 407.153748, + "Y": 193.072342 + }, + { + "StartTime": 3483, + "EndTime": 3483, + "X": 367.131775, + "Y": 193.204865 + }, + { + "StartTime": 3565, + "EndTime": 3565, + "X": 327.109772, + "Y": 193.337387 + }, + { + "StartTime": 3647, + "EndTime": 3647, + "X": 287.087952, + "Y": 193.46991 + }, + { + "StartTime": 3729, + "EndTime": 3729, + "X": 247.065948, + "Y": 193.602432 + }, + { + "StartTime": 3811, + "EndTime": 3811, + "X": 207.043976, + "Y": 193.734955 + }, + { + "StartTime": 3893, + "EndTime": 3893, + "X": 167.021988, + "Y": 193.867477 + }, + { + "StartTime": 3975, + "EndTime": 3975, + "X": 127, + "Y": 194 + }, + { + "StartTime": 4057, + "EndTime": 4057, + "X": 167.021988, + "Y": 193.867477 + }, + { + "StartTime": 4139, + "EndTime": 4139, + "X": 207.043976, + "Y": 193.734955 + }, + { + "StartTime": 4221, + "EndTime": 4221, + "X": 247.065948, + "Y": 193.602432 + }, + { + "StartTime": 4303, + "EndTime": 4303, + "X": 287.087952, + "Y": 193.46991 + }, + { + "StartTime": 4385, + "EndTime": 4385, + "X": 327.109772, + "Y": 193.337387 + }, + { + "StartTime": 4467, + "EndTime": 4467, + "X": 367.131775, + "Y": 193.204865 + }, + { + "StartTime": 4540, + "EndTime": 4540, + "X": 420.331726, + "Y": 193.0287 + }, + { + "StartTime": 4549, + "EndTime": 4549, + "X": 407.153748, + "Y": 193.072342 + } + ] + }] +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/uneven-repeat-slider.osu b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/uneven-repeat-slider.osu new file mode 100644 index 0000000000..64aeeb0c07 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/uneven-repeat-slider.osu @@ -0,0 +1,19 @@ +osu file format v14 + +[General] +StackLeniency: 0.4 +Mode: 0 + +[Difficulty] +CircleSize:4 +OverallDifficulty:7 +ApproachRate:8 +SliderMultiplier:1.6 +SliderTickRate:4 + +[TimingPoints] +369,327.868852459016,4,2,2,32,1,0 + +[HitObjects] +// A slider with an un-even amount of ticks +127,194,369,6,0,L|429:193,7,293.333333333333 diff --git a/osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs b/osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs new file mode 100644 index 0000000000..9fba0f1668 --- /dev/null +++ b/osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs @@ -0,0 +1,116 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Tests.Beatmaps +{ + [TestFixture] + public class SliderEventGenerationTest + { + private const double start_time = 0; + private const double span_duration = 1000; + + [Test] + public void TestSingleSpan() + { + var events = SliderEventGenerator.Generate(start_time, span_duration, 1, span_duration / 2, span_duration, 1, null).ToArray(); + + Assert.That(events[0].Type, Is.EqualTo(SliderEventType.Head)); + Assert.That(events[0].Time, Is.EqualTo(start_time)); + + Assert.That(events[1].Type, Is.EqualTo(SliderEventType.Tick)); + Assert.That(events[1].Time, Is.EqualTo(span_duration / 2)); + + Assert.That(events[3].Type, Is.EqualTo(SliderEventType.Tail)); + Assert.That(events[3].Time, Is.EqualTo(span_duration)); + } + + [Test] + public void TestRepeat() + { + var events = SliderEventGenerator.Generate(start_time, span_duration, 1, span_duration / 2, span_duration, 2, null).ToArray(); + + Assert.That(events[0].Type, Is.EqualTo(SliderEventType.Head)); + Assert.That(events[0].Time, Is.EqualTo(start_time)); + + Assert.That(events[1].Type, Is.EqualTo(SliderEventType.Tick)); + Assert.That(events[1].Time, Is.EqualTo(span_duration / 2)); + + Assert.That(events[2].Type, Is.EqualTo(SliderEventType.Repeat)); + Assert.That(events[2].Time, Is.EqualTo(span_duration)); + + Assert.That(events[3].Type, Is.EqualTo(SliderEventType.Tick)); + Assert.That(events[3].Time, Is.EqualTo(span_duration + span_duration / 2)); + + Assert.That(events[5].Type, Is.EqualTo(SliderEventType.Tail)); + Assert.That(events[5].Time, Is.EqualTo(2 * span_duration)); + } + + [Test] + public void TestNonEvenTicks() + { + var events = SliderEventGenerator.Generate(start_time, span_duration, 1, 300, span_duration, 2, null).ToArray(); + + Assert.That(events[0].Type, Is.EqualTo(SliderEventType.Head)); + Assert.That(events[0].Time, Is.EqualTo(start_time)); + + Assert.That(events[1].Type, Is.EqualTo(SliderEventType.Tick)); + Assert.That(events[1].Time, Is.EqualTo(300)); + + Assert.That(events[2].Type, Is.EqualTo(SliderEventType.Tick)); + Assert.That(events[2].Time, Is.EqualTo(600)); + + Assert.That(events[3].Type, Is.EqualTo(SliderEventType.Tick)); + Assert.That(events[3].Time, Is.EqualTo(900)); + + Assert.That(events[4].Type, Is.EqualTo(SliderEventType.Repeat)); + Assert.That(events[4].Time, Is.EqualTo(span_duration)); + + Assert.That(events[5].Type, Is.EqualTo(SliderEventType.Tick)); + Assert.That(events[5].Time, Is.EqualTo(1100)); + + Assert.That(events[6].Type, Is.EqualTo(SliderEventType.Tick)); + Assert.That(events[6].Time, Is.EqualTo(1400)); + + Assert.That(events[7].Type, Is.EqualTo(SliderEventType.Tick)); + Assert.That(events[7].Time, Is.EqualTo(1700)); + + Assert.That(events[9].Type, Is.EqualTo(SliderEventType.Tail)); + Assert.That(events[9].Time, Is.EqualTo(2 * span_duration)); + } + + [Test] + public void TestLegacyLastTickOffset() + { + var events = SliderEventGenerator.Generate(start_time, span_duration, 1, span_duration / 2, span_duration, 1, 100).ToArray(); + + Assert.That(events[2].Type, Is.EqualTo(SliderEventType.LegacyLastTick)); + Assert.That(events[2].Time, Is.EqualTo(900)); + } + + [Test] + public void TestMinimumTickDistance() + { + const double velocity = 5; + const double min_distance = velocity * 10; + + var events = SliderEventGenerator.Generate(start_time, span_duration, velocity, velocity, span_duration, 2, 0).ToArray(); + + Assert.Multiple(() => + { + int tickIndex = -1; + + while (++tickIndex < events.Length) + { + if (events[tickIndex].Type != SliderEventType.Tick) + continue; + + Assert.That(events[tickIndex].Time, Is.LessThan(span_duration - min_distance).Or.GreaterThan(span_duration + min_distance)); + } + }); + } + } +} From 0ff1c6184b31768e3aff483b2c603213ae91e6c7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Aug 2019 17:36:20 +0900 Subject: [PATCH 2150/5608] Add generation comment --- osu.Game/Rulesets/Objects/SliderEventGenerator.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs index 9047d338aa..0d8796b4cb 100644 --- a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -118,6 +118,7 @@ namespace osu.Game.Rulesets.Objects if (d >= length - minDistanceFromEnd) break; + // Always generate ticks from the start of the path rather than the span to ensure that ticks in repeat spans are positioned identically to those in non-repeat spans var pathProgress = d / length; var timeProgress = reversed ? 1 - pathProgress : pathProgress; From 2ae8cba24d8c951bb7d6331b6c7151d1c02e40b4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Aug 2019 17:58:20 +0900 Subject: [PATCH 2151/5608] Add hardrock spinner test --- .../CatchBeatmapConversionTest.cs | 1 + .../hardrock-spinner-expected-conversion.json | 74 +++++++++++++++++++ .../Testing/Beatmaps/hardrock-spinner.osu | 18 +++++ 3 files changed, 93 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-spinner-expected-conversion.json create mode 100644 osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-spinner.osu diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index 80ac64c5f9..dd272599ab 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -25,6 +25,7 @@ namespace osu.Game.Rulesets.Catch.Tests [TestCase("slider")] [TestCase("hardrock-stream", new[] { typeof(CatchModHardRock) })] [TestCase("hardrock-repeat-slider", new[] { typeof(CatchModHardRock) })] + [TestCase("hardrock-spinner", new[] { typeof(CatchModHardRock) })] public new void Test(string name, params Type[] mods) { base.Test(name, mods); diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-spinner-expected-conversion.json b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-spinner-expected-conversion.json new file mode 100644 index 0000000000..7333b600fb --- /dev/null +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-spinner-expected-conversion.json @@ -0,0 +1,74 @@ +{ + "Mappings": [{ + "StartTime": 369, + "Objects": [{ + "StartTime": 369, + "Position": 65 + }, + { + "StartTime": 450, + "Position": 482 + }, + { + "StartTime": 532, + "Position": 164 + }, + { + "StartTime": 614, + "Position": 315 + }, + { + "StartTime": 696, + "Position": 145 + }, + { + "StartTime": 778, + "Position": 159 + }, + { + "StartTime": 860, + "Position": 310 + }, + { + "StartTime": 942, + "Position": 441 + }, + { + "StartTime": 1024, + "Position": 428 + }, + { + "StartTime": 1106, + "Position": 243 + }, + { + "StartTime": 1188, + "Position": 422 + }, + { + "StartTime": 1270, + "Position": 481 + }, + { + "StartTime": 1352, + "Position": 104 + }, + { + "StartTime": 1434, + "Position": 473 + }, + { + "StartTime": 1516, + "Position": 135 + }, + { + "StartTime": 1598, + "Position": 360 + }, + { + "StartTime": 1680, + "Position": 123 + } + ] + }] +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-spinner.osu b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-spinner.osu new file mode 100644 index 0000000000..208d21a344 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-spinner.osu @@ -0,0 +1,18 @@ +osu file format v14 + +[General] +StackLeniency: 0.4 +Mode: 0 + +[Difficulty] +CircleSize:4 +OverallDifficulty:7 +ApproachRate:8 +SliderMultiplier:1.6 +SliderTickRate:4 + +[TimingPoints] +369,327.868852459016,4,2,2,32,1,0 + +[HitObjects] +256,192,369,12,0,1680,0:0:0:0: From e9eea7157d9cf0fa333513a98171ff6b3203e23c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Aug 2019 18:04:57 +0900 Subject: [PATCH 2152/5608] Trim unnecessary file contents --- .../Testing/Beatmaps/hardrock-stream.osu | 59 +------------------ 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-stream.osu b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-stream.osu index 62835135df..321af4604b 100644 --- a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-stream.osu +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/hardrock-stream.osu @@ -1,75 +1,18 @@ osu file format v14 [General] -AudioFilename: audio.mp3 -AudioLeadIn: 0 -PreviewTime: 53483 -Countdown: 0 -SampleSet: Soft StackLeniency: 0.4 Mode: 0 -LetterboxInBreaks: 0 -WidescreenStoryboard: 0 - -[Editor] -Bookmarks: 369,1680,12172,22664,33155,43647,54139,64631,75123,85614,96106,103975,114467,124959,135287 -DistanceSpacing: 1 -BeatDivisor: 4 -GridSize: 8 -TimelineZoom: 2.899999 - -[Metadata] -Title:Silhouette -TitleUnicode:シルエット -Artist:KANA-BOON -ArtistUnicode:KANA-BOON -Creator:Nevo -Version:lit120's Hard -Source:NARUTO-ナルト-疾風伝 -Tags:shippuuden shipuuden shippuden nine tails opening 16 kage cut ver version naotoshi nao tomori shunao shogunmoon sotarks pika [[pika]] frostwich lit120 shiratoi armin a_r_m_i_n -BeatmapID:1653115 -BeatmapSetID:780952 [Difficulty] -HPDrainRate:6 CircleSize:4 OverallDifficulty:7 ApproachRate:8 SliderMultiplier:1.6 SliderTickRate:1 -[Events] -//Background and Video events -0,0,"OSpGdEP.png",0,0 -//Break Periods -//Storyboard Layer 0 (Background) -//Storyboard Layer 1 (Fail) -//Storyboard Layer 2 (Pass) -//Storyboard Layer 3 (Foreground) -//Storyboard Sound Samples - [TimingPoints] 369,327.868852459016,4,2,2,32,1,0 -1680,-100,4,2,2,42,0,0 -6926,-100,4,2,2,52,0,0 -11844,-100,4,2,2,5,0,0 -12172,-100,4,2,2,62,0,0 -22664,-100,4,2,2,52,0,0 -43647,-100,4,2,2,52,0,0 -53483,-100,4,2,2,32,0,0 -54139,-100,4,2,2,72,0,1 -96106,-100,4,2,2,52,0,0 -103975,-100,4,2,2,82,0,1 -124959,-100,4,2,2,62,0,0 -130205,-100,4,2,2,72,0,0 -132991,-100,4,2,2,82,0,0 - - -[Colours] -Combo1 : 154,53,255 -Combo2 : 253,211,47 -Combo3 : 86,168,250 -Combo4 : 192,192,192 [HitObjects] 258,189,369,1,0,0:0:0:0: @@ -104,4 +47,4 @@ Combo4 : 192,192,192 258,189,2746,1,0,0:0:0:0: 258,189,2828,1,0,0:0:0:0: 258,189,2909,1,0,0:0:0:0: -258,189,2991,1,0,0:0:0:0: +258,189,2991,1,0,0:0:0:0: \ No newline at end of file From f0941a11b513b2f9a506d140124037f05d3235af Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 1 Aug 2019 21:22:08 +0900 Subject: [PATCH 2153/5608] Remove no longer needed property --- osu.Game/Screens/Multi/Multiplayer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 9550d883fd..90806bab6e 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -34,8 +34,6 @@ namespace osu.Game.Screens.Multi public override bool DisallowExternalBeatmapRulesetChanges => true; - protected virtual bool RequireOnline => true; - private readonly MultiplayerWaveContainer waves; private readonly OsuButton createButton; From 6ab9f645a2f436944d5a583b1faeefdf1e0d121a Mon Sep 17 00:00:00 2001 From: David Zhao Date: Thu, 1 Aug 2019 21:26:52 +0900 Subject: [PATCH 2154/5608] Remove usage of no longer needed property --- osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index 88dac8d0ff..08afe90de8 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -97,14 +97,14 @@ namespace osu.Game.Tests.Visual.Menus [Test] public void TestExitMultiWithEscape() { - pushAndConfirm(() => new TestMultiplayer(), "multiplayer"); + pushAndConfirm(() => new Screens.Multi.Multiplayer(), "multiplayer"); exitViaEscapeAndConfirm(); } [Test] public void TestExitMultiWithBackButton() { - pushAndConfirm(() => new TestMultiplayer(), "multiplayer"); + pushAndConfirm(() => new Screens.Multi.Multiplayer(), "multiplayer"); exitViaBackButtonAndConfirm(); } @@ -177,11 +177,6 @@ namespace osu.Game.Tests.Visual.Menus public ModSelectOverlay ModSelectOverlay => ModSelect; } - private class TestMultiplayer : Screens.Multi.Multiplayer - { - protected override bool RequireOnline => false; - } - private class TestLoader : Loader { protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler(); From d55875800067ec90f60f55e492a26c2a30dc0ca3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 1 Aug 2019 19:14:07 +0300 Subject: [PATCH 2155/5608] Add PreviousUsernames field to the User --- osu.Game/Users/User.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 34bd4bbaae..22c0a4fcd0 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -20,6 +20,9 @@ namespace osu.Game.Users [JsonProperty(@"username")] public string Username; + [JsonProperty(@"previous_usernames")] + public string[] PreviousUsernames; + [JsonProperty(@"country")] public Country Country; From 90c59ab39d3058189e530ed25e3597284ea27b5b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 1 Aug 2019 21:26:59 +0300 Subject: [PATCH 2156/5608] implement PreviousUsernamesContainer --- .../TestScenePreviousUsernamesContainer.cs | 52 +++++ .../Header/PreviousUsernamesContainer.cs | 179 ++++++++++++++++++ 2 files changed, 231 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs create mode 100644 osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs diff --git a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs new file mode 100644 index 0000000000..0469c230d0 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs @@ -0,0 +1,52 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Overlays.Profile.Header; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + [TestFixture] + public class TestScenePreviousUsernamesContainer : OsuTestScene + { + public TestScenePreviousUsernamesContainer() + { + Bindable user = new Bindable(); + + Child = new PreviousUsernamesContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + User = { BindTarget = user }, + }; + + AddStep("single username", () => user.Value = new User + { + PreviousUsernames = new[] { "username1" }, + }); + + AddStep("two usernames", () => user.Value = new User + { + PreviousUsernames = new[] { "longusername", "longerusername" }, + }); + + AddStep("three usernames", () => user.Value = new User + { + PreviousUsernames = new[] { "test", "angelsim", "verylongusername" }, + }); + + AddStep("four usernames", () => user.Value = new User + { + PreviousUsernames = new[] { "ihavenoidea", "howcani", "makethistext" , "anylonger" }, + }); + + AddStep("no username", () => user.Value = new User + { + PreviousUsernames = new string[0], + }); + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs new file mode 100644 index 0000000000..39bd2388a4 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs @@ -0,0 +1,179 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Users; +using osuTK; +using System; +using System.Linq; + +namespace osu.Game.Overlays.Profile.Header +{ + public class PreviousUsernamesContainer : Container + { + private const int duration = 200; + private const int margin = 10; + private const int width = 350; + private const int move_offset = 30; + + public readonly Bindable User = new Bindable(); + + private readonly HoverIconContainer hoverIcon; + private readonly ContentContainer contentContainer; + + public PreviousUsernamesContainer() + { + AutoSizeAxes = Axes.Y; + Width = width; + Children = new Drawable[] + { + contentContainer = new ContentContainer(), + hoverIcon = new HoverIconContainer(), + }; + + hoverIcon.ActivateHover += () => + { + contentContainer.Show(); + this.MoveToY(-move_offset, duration, Easing.OutQuint); + }; + + User.BindValueChanged(onUserChanged); + } + + private void onUserChanged(ValueChangedEvent user) + { + contentContainer.Clear(); + + var usernames = user.NewValue.PreviousUsernames; + + if (usernames.Any()) + { + var amount = usernames.Count(); + + for (int i = 0; i < amount; i++) + { + string text = (i + 1 == amount) ? usernames[i] : $@"{usernames[i]},"; + + contentContainer.Usernames.AddText(new SpriteText + { + Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true), + Text = text, + }); + } + + Show(); + return; + } + + Hide(); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + contentContainer.Hide(); + this.MoveToY(0, duration, Easing.OutQuint); + } + + private class ContentContainer : VisibilityContainer + { + private const int header_height = 25; + private const int content_padding = 60; + + public readonly TextFlowContainer Usernames; + + private readonly Box background; + + public ContentContainer() + { + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + Masking = true; + AlwaysPresent = true; + CornerRadius = 5; + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + Height = header_height, + Children = new Drawable[] + { + new SpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Padding = new MarginPadding { Left = content_padding }, + Text = @"formerly known as", + Font = OsuFont.GetFont(size: 14, italics: true) + } + } + }, + Usernames = new TextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Full, + Spacing = new Vector2(5, 5), + Padding = new MarginPadding { Left = content_padding, Bottom = margin }, + }, + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.GreySeafoamDarker; + } + + public override void Clear(bool disposeChildren) => Usernames.Clear(disposeChildren); + + protected override void PopIn() => this.FadeIn(duration, Easing.OutQuint); + + protected override void PopOut() => this.FadeOut(duration, Easing.OutQuint); + } + + private class HoverIconContainer : Container + { + public Action ActivateHover; + + public HoverIconContainer() + { + AutoSizeAxes = Axes.Both; + Child = new SpriteIcon + { + Margin = new MarginPadding(margin) { Top = 7 }, + Size = new Vector2(20), + Icon = FontAwesome.Solid.IdCard, + }; + } + + protected override bool OnHover(HoverEvent e) + { + ActivateHover?.Invoke(); + return base.OnHover(e); + } + } + } +} From 13fe1732d8cf8b76aa689a585ad6c3fe63128119 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 1 Aug 2019 21:32:04 +0300 Subject: [PATCH 2157/5608] adjust height values to avoid random jumps --- .../Overlays/Profile/Header/PreviousUsernamesContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs index 39bd2388a4..67b9bcb651 100644 --- a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs +++ b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Profile.Header private const int duration = 200; private const int margin = 10; private const int width = 350; - private const int move_offset = 30; + private const int move_offset = 20; public readonly Bindable User = new Bindable(); @@ -163,7 +163,7 @@ namespace osu.Game.Overlays.Profile.Header AutoSizeAxes = Axes.Both; Child = new SpriteIcon { - Margin = new MarginPadding(margin) { Top = 7 }, + Margin = new MarginPadding(margin) { Top = 6 }, Size = new Vector2(20), Icon = FontAwesome.Solid.IdCard, }; From e66a3494b9fbd43c9f49d718af1683106d86dc93 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 1 Aug 2019 22:50:01 +0300 Subject: [PATCH 2158/5608] make the container hidden by default --- osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs index 67b9bcb651..5165f0d0df 100644 --- a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs +++ b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs @@ -45,6 +45,7 @@ namespace osu.Game.Overlays.Profile.Header }; User.BindValueChanged(onUserChanged); + Hide(); } private void onUserChanged(ValueChangedEvent user) From 55475927685aee49e5686899d6898ff8093fc7d4 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 1 Aug 2019 23:04:18 +0300 Subject: [PATCH 2159/5608] CI fixes --- .../Visual/Online/TestScenePreviousUsernamesContainer.cs | 2 +- .../Overlays/Profile/Header/PreviousUsernamesContainer.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs index 0469c230d0..a33de887d7 100644 --- a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs @@ -40,7 +40,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("four usernames", () => user.Value = new User { - PreviousUsernames = new[] { "ihavenoidea", "howcani", "makethistext" , "anylonger" }, + PreviousUsernames = new[] { "ihavenoidea", "howcani", "makethistext", "anylonger" }, }); AddStep("no username", () => user.Value = new User diff --git a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs index 5165f0d0df..1c98cff616 100644 --- a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs +++ b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs @@ -25,11 +25,12 @@ namespace osu.Game.Overlays.Profile.Header public readonly Bindable User = new Bindable(); - private readonly HoverIconContainer hoverIcon; private readonly ContentContainer contentContainer; public PreviousUsernamesContainer() { + HoverIconContainer hoverIcon; + AutoSizeAxes = Axes.Y; Width = width; Children = new Drawable[] @@ -56,7 +57,7 @@ namespace osu.Game.Overlays.Profile.Header if (usernames.Any()) { - var amount = usernames.Count(); + var amount = usernames.Length; for (int i = 0; i < amount; i++) { From de96e5dfc605f559269a2e045652ab2453267d2d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 2 Aug 2019 07:41:11 +0300 Subject: [PATCH 2160/5608] Apply suggested changes --- .../TestScenePreviousUsernamesContainer.cs | 5 ++ .../Header/PreviousUsernamesContainer.cs | 58 +++++++++---------- 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs index a33de887d7..4f3a2e47c6 100644 --- a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs @@ -43,6 +43,11 @@ namespace osu.Game.Tests.Visual.Online PreviousUsernames = new[] { "ihavenoidea", "howcani", "makethistext", "anylonger" }, }); + AddStep("many usernames", () => user.Value = new User + { + PreviousUsernames = new[] { "ihavenoidea", "howcani", "makethistext", "anylonger", "but", "ican", "try", "tomake", "this" }, + }); + AddStep("no username", () => user.Value = new User { PreviousUsernames = new string[0], diff --git a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs index 1c98cff616..e8443dff1b 100644 --- a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs +++ b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs @@ -16,12 +16,12 @@ using System.Linq; namespace osu.Game.Overlays.Profile.Header { - public class PreviousUsernamesContainer : Container + public class PreviousUsernamesContainer : CompositeDrawable { private const int duration = 200; private const int margin = 10; - private const int width = 350; - private const int move_offset = 20; + private const int width = 310; + private const int move_offset = 15; public readonly Bindable User = new Bindable(); @@ -33,43 +33,35 @@ namespace osu.Game.Overlays.Profile.Header AutoSizeAxes = Axes.Y; Width = width; - Children = new Drawable[] + + AddRangeInternal(new Drawable[] { contentContainer = new ContentContainer(), hoverIcon = new HoverIconContainer(), - }; + }); hoverIcon.ActivateHover += () => { contentContainer.Show(); this.MoveToY(-move_offset, duration, Easing.OutQuint); }; + } - User.BindValueChanged(onUserChanged); - Hide(); + protected override void LoadComplete() + { + base.LoadComplete(); + User.BindValueChanged(onUserChanged, true); } private void onUserChanged(ValueChangedEvent user) { - contentContainer.Clear(); + contentContainer.Text = string.Empty; - var usernames = user.NewValue.PreviousUsernames; + var usernames = user.NewValue?.PreviousUsernames; - if (usernames.Any()) + if (usernames?.Any() ?? false) { - var amount = usernames.Length; - - for (int i = 0; i < amount; i++) - { - string text = (i + 1 == amount) ? usernames[i] : $@"{usernames[i]},"; - - contentContainer.Usernames.AddText(new SpriteText - { - Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true), - Text = text, - }); - } - + contentContainer.Text = string.Join(", ", usernames); Show(); return; } @@ -86,11 +78,15 @@ namespace osu.Game.Overlays.Profile.Header private class ContentContainer : VisibilityContainer { - private const int header_height = 25; - private const int content_padding = 60; + private const int header_height = 20; + private const int content_padding = 40; - public readonly TextFlowContainer Usernames; + public string Text + { + set => usernames.Text = value; + } + private readonly TextFlowContainer usernames; private readonly Box background; public ContentContainer() @@ -126,16 +122,16 @@ namespace osu.Game.Overlays.Profile.Header Origin = Anchor.BottomLeft, Padding = new MarginPadding { Left = content_padding }, Text = @"formerly known as", - Font = OsuFont.GetFont(size: 14, italics: true) + Font = OsuFont.GetFont(size: 10, italics: true) } } }, - Usernames = new TextFlowContainer + usernames = new TextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold, italics: true)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Full, - Spacing = new Vector2(5, 5), + Spacing = new Vector2(0, 5), Padding = new MarginPadding { Left = content_padding, Bottom = margin }, }, } @@ -149,8 +145,6 @@ namespace osu.Game.Overlays.Profile.Header background.Colour = colours.GreySeafoamDarker; } - public override void Clear(bool disposeChildren) => Usernames.Clear(disposeChildren); - protected override void PopIn() => this.FadeIn(duration, Easing.OutQuint); protected override void PopOut() => this.FadeOut(duration, Easing.OutQuint); @@ -166,7 +160,7 @@ namespace osu.Game.Overlays.Profile.Header Child = new SpriteIcon { Margin = new MarginPadding(margin) { Top = 6 }, - Size = new Vector2(20), + Size = new Vector2(15), Icon = FontAwesome.Solid.IdCard, }; } From 4c0a9aeab701381ad602cde155b636327ba979f7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 2 Aug 2019 07:44:09 +0300 Subject: [PATCH 2161/5608] Add null user step --- .../Visual/Online/TestScenePreviousUsernamesContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs index 4f3a2e47c6..4a3b3403b2 100644 --- a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs @@ -52,6 +52,8 @@ namespace osu.Game.Tests.Visual.Online { PreviousUsernames = new string[0], }); + + AddStep("null user", () => user.Value = null); } } } From ba3f8a643a899f268d75882af1c44ba045f13180 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 2 Aug 2019 14:16:57 +0900 Subject: [PATCH 2162/5608] Update cake --- build/cakebuild.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/cakebuild.csproj b/build/cakebuild.csproj index 8ccce35e26..d5a6d44740 100644 --- a/build/cakebuild.csproj +++ b/build/cakebuild.csproj @@ -5,7 +5,7 @@ netcoreapp2.0 - - + + \ No newline at end of file From 1b5a9aecffdef0b307c3712d0d85992928b0d894 Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Fri, 2 Aug 2019 23:34:25 +0800 Subject: [PATCH 2163/5608] Add iOS URL Scheme support --- .../Graphics/Containers/LinkFlowContainer.cs | 47 +--------------- osu.Game/Online/Chat/MessageFormatter.cs | 54 ++++++++++++++++++- osu.Game/OsuGame.cs | 22 ++++++++ osu.iOS/AppDelegate.cs | 7 ++- osu.iOS/Info.plist | 14 +++++ 5 files changed, 93 insertions(+), 51 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 15068d81c0..51a842fc84 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -86,52 +86,7 @@ namespace osu.Game.Graphics.Containers { RelativeSizeAxes = Axes.Both, TooltipText = tooltipText ?? (url != text ? url : string.Empty), - Action = action ?? (() => - { - switch (linkType) - { - case LinkAction.OpenBeatmap: - // TODO: proper query params handling - if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) - game?.ShowBeatmap(beatmapId); - break; - - case LinkAction.OpenBeatmapSet: - if (int.TryParse(linkArgument, out int setId)) - game?.ShowBeatmapSet(setId); - break; - - case LinkAction.OpenChannel: - try - { - channelManager?.OpenChannel(linkArgument); - } - catch (ChannelNotFoundException) - { - Logger.Log($"The requested channel \"{linkArgument}\" does not exist"); - } - - break; - - case LinkAction.OpenEditorTimestamp: - case LinkAction.JoinMultiplayerMatch: - case LinkAction.Spectate: - showNotImplementedError?.Invoke(); - break; - - case LinkAction.External: - game?.OpenUrlExternally(url); - break; - - case LinkAction.OpenUserProfile: - if (long.TryParse(linkArgument, out long userId)) - game?.ShowUser(userId); - break; - - default: - throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); - } - }), + Action = action ?? (() => LinkUtils.HandleLink(url, linkType, linkArgument, game, channelManager, showNotImplementedError)), }); return drawables; diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 4aaffdd161..ee8f45803b 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text.RegularExpressions; +using osu.Framework.Logging; namespace osu.Game.Online.Chat { @@ -98,7 +100,7 @@ namespace osu.Game.Online.Chat } } - private static LinkDetails getLinkDetails(string url) + public static LinkDetails getLinkDetails(string url) { var args = url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); args[0] = args[0].TrimEnd(':'); @@ -288,4 +290,54 @@ namespace osu.Game.Online.Chat public int CompareTo(Link otherLink) => Index > otherLink.Index ? 1 : -1; } + + public static class LinkUtils + { + public static void HandleLink(string url, LinkAction linkType, string linkArgument, OsuGame game, ChannelManager channelManager = null, Action showNotImplementedError = null) + { + switch (linkType) + { + case LinkAction.OpenBeatmap: + // TODO: proper query params handling + if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) + game?.ShowBeatmap(beatmapId); + break; + + case LinkAction.OpenBeatmapSet: + if (int.TryParse(linkArgument, out int setId)) + game?.ShowBeatmapSet(setId); + break; + + case LinkAction.OpenChannel: + try + { + channelManager?.OpenChannel(linkArgument); + } + catch (ChannelNotFoundException) + { + Logger.Log($"The requested channel \"{linkArgument}\" does not exist"); + } + + break; + + case LinkAction.OpenEditorTimestamp: + case LinkAction.JoinMultiplayerMatch: + case LinkAction.Spectate: + showNotImplementedError?.Invoke(); + break; + + case LinkAction.External: + game?.OpenUrlExternally(url); + break; + + case LinkAction.OpenUserProfile: + if (long.TryParse(linkArgument, out long userId)) + game?.ShowUser(userId); + break; + + default: + throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); + } + } + } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e71dd67bf2..5dea67253d 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -43,6 +43,7 @@ using osu.Game.Scoring; using osu.Game.Screens.Select; using osu.Game.Utils; using LogLevel = osu.Framework.Logging.LogLevel; +using static osu.Game.Online.Chat.MessageFormatter; namespace osu.Game { @@ -90,6 +91,8 @@ namespace osu.Game private IntroScreen introScreen; + private bool loaded = false; + private Bindable configRuleset; private Bindable configSkin; @@ -190,10 +193,29 @@ namespace osu.Game Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade); Beatmap.BindValueChanged(beatmapChanged, true); + + loaded = true; } private ExternalLinkOpener externalLinkOpener; + public void HandleUrl(string url) + { + Logger.Log($"Request to handle url: {url}"); + if (loaded) + { + Action showNotImplementedError = () => notifications?.Post(new SimpleNotification + { + Text = @"This link type is not yet supported!", + Icon = FontAwesome.Solid.LifeRing, + }); + LinkDetails linkDetails = getLinkDetails(url); + Schedule(() => LinkUtils.HandleLink(url, linkDetails.Action, linkDetails.Argument, this, channelManager, showNotImplementedError)); + } + else + Scheduler.AddDelayed(() => HandleUrl(url), 1000); + } + public void OpenUrlExternally(string url) { if (url.StartsWith("/")) diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs index 9ef21e014c..e727305997 100644 --- a/osu.iOS/AppDelegate.cs +++ b/osu.iOS/AppDelegate.cs @@ -1,10 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Threading.Tasks; using Foundation; using osu.Framework.iOS; -using osu.Game; +using osu.Framework.Threading; using UIKit; namespace osu.iOS @@ -16,9 +15,9 @@ namespace osu.iOS protected override Framework.Game CreateGame() => game = new OsuGameIOS(); - public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation) + public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options) { - Task.Run(() => game.Import(url.Path)); + game.HandleUrl(url.AbsoluteString); return true; } } diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index 4fbc67e27b..5fe8cd6d5b 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -107,5 +107,19 @@ + UIFileSharingEnabled + + CFBundleURLTypes + + + CFBundleURLSchemes + + osu + osump + + CFBundleTypeRole + Editor + + From 471103fd101180e78f2d54fc34d96cb5198dcada Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Sat, 3 Aug 2019 00:00:22 +0800 Subject: [PATCH 2164/5608] Fix code format --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 1 - osu.Game/Online/Chat/MessageFormatter.cs | 2 +- osu.Game/OsuGame.cs | 8 +++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 51a842fc84..ab4629cfff 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -8,7 +8,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using System.Collections.Generic; using osu.Framework.Graphics; -using osu.Framework.Logging; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using osu.Game.Users; diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index ee8f45803b..347139975e 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -100,7 +100,7 @@ namespace osu.Game.Online.Chat } } - public static LinkDetails getLinkDetails(string url) + public static LinkDetails GetLinkDetails(string url) { var args = url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); args[0] = args[0].TrimEnd(':'); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 5dea67253d..fa68142fea 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -91,7 +91,7 @@ namespace osu.Game private IntroScreen introScreen; - private bool loaded = false; + private bool loaded; private Bindable configRuleset; @@ -193,8 +193,6 @@ namespace osu.Game Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade); Beatmap.BindValueChanged(beatmapChanged, true); - - loaded = true; } private ExternalLinkOpener externalLinkOpener; @@ -202,6 +200,7 @@ namespace osu.Game public void HandleUrl(string url) { Logger.Log($"Request to handle url: {url}"); + if (loaded) { Action showNotImplementedError = () => notifications?.Post(new SimpleNotification @@ -402,6 +401,8 @@ namespace osu.Game protected override void LoadComplete() { + loaded = false; + base.LoadComplete(); // The next time this is updated is in UpdateAfterChildren, which occurs too late and results @@ -597,6 +598,7 @@ namespace osu.Game settings.State.ValueChanged += _ => updateScreenOffset(); notifications.State.ValueChanged += _ => updateScreenOffset(); + loaded = true; } public class GameIdleTracker : IdleTracker From e84c79d14051ecb220429c38cdb321e53f9a0b24 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 2 Aug 2019 13:16:33 -0700 Subject: [PATCH 2165/5608] Update osu!direct categories sorting with web changes --- .../API/Requests/SearchBeatmapSetsRequest.cs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs index d9d05ff285..c8c36789c4 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs @@ -27,24 +27,25 @@ namespace osu.Game.Online.API.Requests } // ReSharper disable once ImpureMethodCallOnReadonlyValueField - protected override string Target => $@"beatmapsets/search?q={query}&m={ruleset.ID ?? 0}&s={(int)searchCategory}&sort={sortCriteria.ToString().ToLowerInvariant()}_{directionString}"; + protected override string Target => $@"beatmapsets/search?q={query}&m={ruleset.ID ?? 0}&s={searchCategory.ToString().ToLowerInvariant()}&sort={sortCriteria.ToString().ToLowerInvariant()}_{directionString}"; } public enum BeatmapSearchCategory { - Any = 7, + Any, - [Description("Ranked & Approved")] - RankedApproved = 0, - Qualified = 3, - Loved = 8, - Favourites = 2, + [Description("Has Leaderboard")] + Leaderboard, + Ranked, + Qualified, + Loved, + Favourites, [Description("Pending & WIP")] - PendingWIP = 4, - Graveyard = 5, + Pending, + Graveyard, [Description("My Maps")] - MyMaps = 6, + Mine, } } From 0082695cd827a574e91a0c8be4d0bd8da1288e8e Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 2 Aug 2019 13:22:58 -0700 Subject: [PATCH 2166/5608] Choose default category sorting instead of being always first --- osu.Game/Overlays/Direct/FilterControl.cs | 1 + .../Overlays/SearchableList/SearchableListFilterControl.cs | 4 ++++ osu.Game/Overlays/Social/FilterControl.cs | 1 + osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs | 1 + 4 files changed, 7 insertions(+) diff --git a/osu.Game/Overlays/Direct/FilterControl.cs b/osu.Game/Overlays/Direct/FilterControl.cs index 4b43542b43..8b04bf0387 100644 --- a/osu.Game/Overlays/Direct/FilterControl.cs +++ b/osu.Game/Overlays/Direct/FilterControl.cs @@ -18,6 +18,7 @@ namespace osu.Game.Overlays.Direct protected override Color4 BackgroundColour => OsuColour.FromHex(@"384552"); protected override DirectSortCriteria DefaultTab => DirectSortCriteria.Ranked; + protected override BeatmapSearchCategory DefaultCategory => BeatmapSearchCategory.Leaderboard; protected override Drawable CreateSupplementaryControls() => rulesetSelector = new DirectRulesetSelector(); diff --git a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs index b0a8a0e77d..a0c4e9a080 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs @@ -26,6 +26,7 @@ namespace osu.Game.Overlays.SearchableList protected abstract Color4 BackgroundColour { get; } protected abstract T DefaultTab { get; } + protected abstract U DefaultCategory { get; } protected virtual Drawable CreateSupplementaryControls() => null; /// @@ -109,6 +110,9 @@ namespace osu.Game.Overlays.SearchableList Tabs.Current.Value = DefaultTab; Tabs.Current.TriggerChange(); + + DisplayStyleControl.Dropdown.Current.Value = DefaultCategory; + DisplayStyleControl.Dropdown.Current.TriggerChange(); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Social/FilterControl.cs b/osu.Game/Overlays/Social/FilterControl.cs index 6abf6ec98d..1c2cb95dfe 100644 --- a/osu.Game/Overlays/Social/FilterControl.cs +++ b/osu.Game/Overlays/Social/FilterControl.cs @@ -12,6 +12,7 @@ namespace osu.Game.Overlays.Social { protected override Color4 BackgroundColour => OsuColour.FromHex(@"47253a"); protected override SocialSortCriteria DefaultTab => SocialSortCriteria.Rank; + protected override SortDirection DefaultCategory => SortDirection.Ascending; public FilterControl() { diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index 8e14f76e4b..d0d983bbff 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -14,6 +14,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components { protected override Color4 BackgroundColour => OsuColour.FromHex(@"362e42"); protected override PrimaryFilter DefaultTab => PrimaryFilter.Open; + protected override SecondaryFilter DefaultCategory => SecondaryFilter.Public; protected override float ContentHorizontalPadding => base.ContentHorizontalPadding + OsuScreen.HORIZONTAL_OVERFLOW_PADDING; From f81238b8b18b38546615c2992df68ca35a19baa8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 3 Aug 2019 04:45:41 +0300 Subject: [PATCH 2167/5608] Add online test --- .../TestScenePreviousUsernamesContainer.cs | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs index 4a3b3403b2..dafc1870e4 100644 --- a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs @@ -2,8 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; @@ -12,10 +15,13 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestScenePreviousUsernamesContainer : OsuTestScene { + [Resolved] + private IAPIProvider api { get; set; } + + private readonly Bindable user = new Bindable(); + public TestScenePreviousUsernamesContainer() { - Bindable user = new Bindable(); - Child = new PreviousUsernamesContainer { Anchor = Anchor.Centre, @@ -55,5 +61,17 @@ namespace osu.Game.Tests.Visual.Online AddStep("null user", () => user.Value = null); } + + protected override void LoadComplete() + { + base.LoadComplete(); + + AddStep("online user (Angelsim)", () => + { + var request = new GetUserRequest(1777162); + request.Success += user => this.user.Value = user; + api.Queue(request); + }); + } } } From 37be4fbf1622d0f80271b5400a497b0bfdfb9984 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 3 Aug 2019 05:34:14 +0300 Subject: [PATCH 2168/5608] Use GridContainer for layout --- .../TestScenePreviousUsernamesContainer.cs | 43 ++--- .../Header/PreviousUsernamesContainer.cs | 159 +++++++++--------- 2 files changed, 90 insertions(+), 112 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs index dafc1870e4..5636f8756d 100644 --- a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs @@ -29,37 +29,22 @@ namespace osu.Game.Tests.Visual.Online User = { BindTarget = user }, }; - AddStep("single username", () => user.Value = new User + User[] users = new[] { - PreviousUsernames = new[] { "username1" }, - }); + new User { PreviousUsernames = new[] { "username1" } }, + new User { PreviousUsernames = new[] { "longusername", "longerusername" } }, + new User { PreviousUsernames = new[] { "test", "angelsim", "verylongusername" } }, + new User { PreviousUsernames = new[] { "ihavenoidea", "howcani", "makethistext", "anylonger" } }, + new User { PreviousUsernames = new string[0] }, + null + }; - AddStep("two usernames", () => user.Value = new User - { - PreviousUsernames = new[] { "longusername", "longerusername" }, - }); - - AddStep("three usernames", () => user.Value = new User - { - PreviousUsernames = new[] { "test", "angelsim", "verylongusername" }, - }); - - AddStep("four usernames", () => user.Value = new User - { - PreviousUsernames = new[] { "ihavenoidea", "howcani", "makethistext", "anylonger" }, - }); - - AddStep("many usernames", () => user.Value = new User - { - PreviousUsernames = new[] { "ihavenoidea", "howcani", "makethistext", "anylonger", "but", "ican", "try", "tomake", "this" }, - }); - - AddStep("no username", () => user.Value = new User - { - PreviousUsernames = new string[0], - }); - - AddStep("null user", () => user.Value = null); + AddStep("single username", () => user.Value = users[0]); + AddStep("two usernames", () => user.Value = users[1]); + AddStep("three usernames", () => user.Value = users[2]); + AddStep("four usernames", () => user.Value = users[3]); + AddStep("no username", () => user.Value = users[4]); + AddStep("null user", () => user.Value = users[5]); } protected override void LoadComplete() diff --git a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs index e8443dff1b..36034fe8db 100644 --- a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs +++ b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs @@ -25,7 +25,9 @@ namespace osu.Game.Overlays.Profile.Header public readonly Bindable User = new Bindable(); - private readonly ContentContainer contentContainer; + private readonly TextFlowContainer text; + private readonly Box background; + private readonly SpriteText header; public PreviousUsernamesContainer() { @@ -33,18 +35,68 @@ namespace osu.Game.Overlays.Profile.Header AutoSizeAxes = Axes.Y; Width = width; + Masking = true; + CornerRadius = 5; AddRangeInternal(new Drawable[] { - contentContainer = new ContentContainer(), - hoverIcon = new HoverIconContainer(), + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new GridContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize) + }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Distributed) + }, + Content = new[] + { + new Drawable[] + { + hoverIcon = new HoverIconContainer(), + header = new SpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Text = @"formerly known as", + Font = OsuFont.GetFont(size: 10, italics: true) + } + }, + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + }, + text = new TextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold, italics: true)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Full, + Margin = new MarginPadding { Bottom = margin, Top = margin / 2 } + } + } + } + } }); - hoverIcon.ActivateHover += () => - { - contentContainer.Show(); - this.MoveToY(-move_offset, duration, Easing.OutQuint); - }; + hoverIcon.ActivateHover += showContent; + hideContent(); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.GreySeafoamDarker; } protected override void LoadComplete() @@ -55,13 +107,13 @@ namespace osu.Game.Overlays.Profile.Header private void onUserChanged(ValueChangedEvent user) { - contentContainer.Text = string.Empty; + text.Text = string.Empty; var usernames = user.NewValue?.PreviousUsernames; if (usernames?.Any() ?? false) { - contentContainer.Text = string.Join(", ", usernames); + text.Text = string.Join(", ", usernames); Show(); return; } @@ -72,82 +124,23 @@ namespace osu.Game.Overlays.Profile.Header protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - contentContainer.Hide(); - this.MoveToY(0, duration, Easing.OutQuint); + hideContent(); } - private class ContentContainer : VisibilityContainer + private void showContent() { - private const int header_height = 20; - private const int content_padding = 40; + text.FadeIn(duration, Easing.OutQuint); + header.FadeIn(duration, Easing.OutQuint); + background.FadeIn(duration, Easing.OutQuint); + this.MoveToY(-move_offset, duration, Easing.OutQuint); + } - public string Text - { - set => usernames.Text = value; - } - - private readonly TextFlowContainer usernames; - private readonly Box background; - - public ContentContainer() - { - AutoSizeAxes = Axes.Y; - RelativeSizeAxes = Axes.X; - Masking = true; - AlwaysPresent = true; - CornerRadius = 5; - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), - Children = new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.X, - Height = header_height, - Children = new Drawable[] - { - new SpriteText - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Padding = new MarginPadding { Left = content_padding }, - Text = @"formerly known as", - Font = OsuFont.GetFont(size: 10, italics: true) - } - } - }, - usernames = new TextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold, italics: true)) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Full, - Spacing = new Vector2(0, 5), - Padding = new MarginPadding { Left = content_padding, Bottom = margin }, - }, - } - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = colours.GreySeafoamDarker; - } - - protected override void PopIn() => this.FadeIn(duration, Easing.OutQuint); - - protected override void PopOut() => this.FadeOut(duration, Easing.OutQuint); + private void hideContent() + { + text.FadeOut(duration, Easing.OutQuint); + header.FadeOut(duration, Easing.OutQuint); + background.FadeOut(duration, Easing.OutQuint); + this.MoveToY(0, duration, Easing.OutQuint); } private class HoverIconContainer : Container @@ -159,7 +152,7 @@ namespace osu.Game.Overlays.Profile.Header AutoSizeAxes = Axes.Both; Child = new SpriteIcon { - Margin = new MarginPadding(margin) { Top = 6 }, + Margin = new MarginPadding { Top = 6, Left = margin, Right = margin * 2 }, Size = new Vector2(15), Icon = FontAwesome.Solid.IdCard, }; From 416f9d89dba59a8cc85e020e643506f4f02b1b44 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 3 Aug 2019 05:49:01 +0300 Subject: [PATCH 2169/5608] CI fixes --- .../Visual/Online/TestScenePreviousUsernamesContainer.cs | 2 +- osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs index 5636f8756d..b891fda0f4 100644 --- a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual.Online User = { BindTarget = user }, }; - User[] users = new[] + User[] users = { new User { PreviousUsernames = new[] { "username1" } }, new User { PreviousUsernames = new[] { "longusername", "longerusername" } }, diff --git a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs index 36034fe8db..b53ac8eb80 100644 --- a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs +++ b/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs @@ -82,7 +82,7 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Full, - Margin = new MarginPadding { Bottom = margin, Top = margin / 2 } + Margin = new MarginPadding { Bottom = margin, Top = margin / 2f } } } } From b244b2fe3d378f7050ba3f8dc9f88a098a98b776 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 2 Aug 2019 21:13:29 -0700 Subject: [PATCH 2170/5608] Add hover click sounds to leaderboard mod filter --- osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index d158186899..544acc7eb2 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -81,7 +81,8 @@ namespace osu.Game.Graphics.UserInterface Colour = Color4.White, Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, - } + }, + new HoverClickSounds() }; Current.ValueChanged += selected => From c9e14c8f063afae562789111864fc094601a9202 Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Sat, 3 Aug 2019 19:46:57 +0800 Subject: [PATCH 2171/5608] Fix typo --- osu.Game/Online/Chat/MessageFormatter.cs | 4 ++-- osu.Game/OsuGame.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 347139975e..73396ce4d2 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -78,7 +78,7 @@ namespace osu.Game.Online.Chat //since we just changed the line display text, offset any already processed links. result.Links.ForEach(l => l.Index -= l.Index > index ? m.Length - displayText.Length : 0); - var details = getLinkDetails(linkText); + var details = GetLinkDetails(linkText); result.Links.Add(new Link(linkText, index, displayText.Length, linkActionOverride ?? details.Action, details.Argument)); //adjust the offset for processing the current matches group. @@ -95,7 +95,7 @@ namespace osu.Game.Online.Chat var link = m.Groups["link"].Value; var indexLength = link.Length; - var details = getLinkDetails(link); + var details = GetLinkDetails(link); result.Links.Add(new Link(link, index, indexLength, details.Action, details.Argument)); } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index fa68142fea..c478ad0a57 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -208,7 +208,7 @@ namespace osu.Game Text = @"This link type is not yet supported!", Icon = FontAwesome.Solid.LifeRing, }); - LinkDetails linkDetails = getLinkDetails(url); + LinkDetails linkDetails = GetLinkDetails(url); Schedule(() => LinkUtils.HandleLink(url, linkDetails.Action, linkDetails.Argument, this, channelManager, showNotImplementedError)); } else From c8dd29067b2f44354a624bf67567b6f382bd1bd5 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sun, 4 Aug 2019 00:34:51 +0300 Subject: [PATCH 2172/5608] Update Entity Framework Core --- osu.Desktop/osu.Desktop.csproj | 4 ++-- osu.Game/osu.Game.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 8c9e1f279f..538aaf2d7a 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -28,8 +28,8 @@ - - + + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 1f91ce1cd8..cf325b77be 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -11,8 +11,8 @@ - - + + From 115cf47ed5e8a697c25b24395094f076b0a47955 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sat, 3 Aug 2019 15:20:44 -0700 Subject: [PATCH 2173/5608] Fix settings sidebar showing scrollbar at max ui scale --- osu.Game/Overlays/Settings/Sidebar.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Settings/Sidebar.cs b/osu.Game/Overlays/Settings/Sidebar.cs index a80b7c1108..358f94b659 100644 --- a/osu.Game/Overlays/Settings/Sidebar.cs +++ b/osu.Game/Overlays/Settings/Sidebar.cs @@ -84,6 +84,7 @@ namespace osu.Game.Overlays.Settings Content.Anchor = Anchor.CentreLeft; Content.Origin = Anchor.CentreLeft; RelativeSizeAxes = Axes.Both; + ScrollbarVisible = false; } } From f6f96658c7b7a51f327702d9a612806af0484da2 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sat, 3 Aug 2019 15:22:06 -0700 Subject: [PATCH 2174/5608] Fix settings sidebar being behind toolbar --- osu.Game/Overlays/SettingsPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 474f529bb1..9dd0def453 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -186,7 +186,7 @@ namespace osu.Game.Overlays base.UpdateAfterChildren(); ContentContainer.Margin = new MarginPadding { Left = Sidebar?.DrawWidth ?? 0 }; - ContentContainer.Padding = new MarginPadding { Top = GetToolbarHeight?.Invoke() ?? 0 }; + Padding = new MarginPadding { Top = GetToolbarHeight?.Invoke() ?? 0 }; } protected class SettingsSectionsContainer : SectionsContainer From c8acbdb1d9600db601c9967f0d2e18b15584be80 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 4 Aug 2019 06:15:15 +0300 Subject: [PATCH 2175/5608] Update the colour --- osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index c5e61f68f4..fa60a37ddb 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -80,7 +80,6 @@ namespace osu.Game.Overlays.Profile.Header.Components private void load(OsuColour colours) { background.Colour = colours.Pink; - iconContainer.Colour = colours.GreySeafoam; } } } From a30d7912b1b34cb0d06b013683143994549b7f57 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 4 Aug 2019 11:09:12 +0300 Subject: [PATCH 2176/5608] Move DimmedLoadingAnimation to it's own file --- .../UserInterface/DimmedLoadingAnimation.cs | 44 +++++++++++++++++++ osu.Game/Screens/Select/BeatmapDetails.cs | 35 +-------------- 2 files changed, 45 insertions(+), 34 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/DimmedLoadingAnimation.cs diff --git a/osu.Game/Graphics/UserInterface/DimmedLoadingAnimation.cs b/osu.Game/Graphics/UserInterface/DimmedLoadingAnimation.cs new file mode 100644 index 0000000000..30c8c5f143 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/DimmedLoadingAnimation.cs @@ -0,0 +1,44 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osuTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Extensions.Color4Extensions; + +namespace osu.Game.Graphics.UserInterface +{ + public class DimmedLoadingAnimation : VisibilityContainer + { + private const float transition_duration = 250; + + private readonly LoadingAnimation loading; + + public DimmedLoadingAnimation() + { + RelativeSizeAxes = Axes.Both; + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0.5f), + }, + loading = new LoadingAnimation(), + }; + } + + protected override void PopIn() + { + this.FadeIn(transition_duration, Easing.OutQuint); + loading.Show(); + } + + protected override void PopOut() + { + this.FadeOut(transition_duration, Easing.OutQuint); + loading.Hide(); + } + } +} diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 23dd87d8ea..9d2e6f1719 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -156,10 +156,7 @@ namespace osu.Game.Screens.Select }, }, }, - loading = new DimmedLoadingAnimation - { - RelativeSizeAxes = Axes.Both, - }, + loading = new DimmedLoadingAnimation(), }; } @@ -365,35 +362,5 @@ namespace osu.Game.Screens.Select }); } } - - private class DimmedLoadingAnimation : VisibilityContainer - { - private readonly LoadingAnimation loading; - - public DimmedLoadingAnimation() - { - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(0.5f), - }, - loading = new LoadingAnimation(), - }; - } - - protected override void PopIn() - { - this.FadeIn(transition_duration, Easing.OutQuint); - loading.Show(); - } - - protected override void PopOut() - { - this.FadeOut(transition_duration, Easing.OutQuint); - loading.Hide(); - } - } } } From fd44ca3233a90207122b0ae16d9606bf09fa9755 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 4 Aug 2019 13:54:23 +0300 Subject: [PATCH 2177/5608] Rename Animation to Layer --- .../{DimmedLoadingAnimation.cs => DimmedLoadingLayer.cs} | 4 ++-- osu.Game/Screens/Select/BeatmapDetails.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game/Graphics/UserInterface/{DimmedLoadingAnimation.cs => DimmedLoadingLayer.cs} (91%) diff --git a/osu.Game/Graphics/UserInterface/DimmedLoadingAnimation.cs b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs similarity index 91% rename from osu.Game/Graphics/UserInterface/DimmedLoadingAnimation.cs rename to osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs index 30c8c5f143..b7d2222f33 100644 --- a/osu.Game/Graphics/UserInterface/DimmedLoadingAnimation.cs +++ b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs @@ -9,13 +9,13 @@ using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Graphics.UserInterface { - public class DimmedLoadingAnimation : VisibilityContainer + public class DimmedLoadingLayer : VisibilityContainer { private const float transition_duration = 250; private readonly LoadingAnimation loading; - public DimmedLoadingAnimation() + public DimmedLoadingLayer() { RelativeSizeAxes = Axes.Both; Children = new Drawable[] diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 9d2e6f1719..577d999388 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Select private readonly MetadataSection description, source, tags; private readonly Container failRetryContainer; private readonly FailRetryGraph failRetryGraph; - private readonly DimmedLoadingAnimation loading; + private readonly DimmedLoadingLayer loading; private IAPIProvider api; @@ -156,7 +156,7 @@ namespace osu.Game.Screens.Select }, }, }, - loading = new DimmedLoadingAnimation(), + loading = new DimmedLoadingLayer(), }; } From 3ae5428dad6e81dc0f7d5e3043247063774ee2d2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 4 Aug 2019 14:15:16 +0300 Subject: [PATCH 2178/5608] ProfileRulesetSelector improvements --- .../Online/TestSceneProfileRulesetSelector.cs | 8 +++++- .../Components/ProfileRulesetSelector.cs | 28 ++++++++++--------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs index c344cb9598..d439e6a7c3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Taiko; +using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { @@ -34,7 +35,12 @@ namespace osu.Game.Tests.Visual.Online AddStep("set mania as default", () => selector.SetDefaultRuleset(new ManiaRuleset().RulesetInfo)); AddStep("set taiko as default", () => selector.SetDefaultRuleset(new TaikoRuleset().RulesetInfo)); AddStep("set catch as default", () => selector.SetDefaultRuleset(new CatchRuleset().RulesetInfo)); - AddStep("select default ruleset", selector.SelectDefaultRuleset); + + AddStep("User with osu as default", () => selector.User.Value = new User { PlayMode = "osu" }); + AddStep("User with mania as default", () => selector.User.Value = new User { PlayMode = "mania" }); + AddStep("User with taiko as default", () => selector.User.Value = new User { PlayMode = "taiko" }); + AddStep("User with catch as default", () => selector.User.Value = new User { PlayMode = "fruits" }); + AddStep("null user", () => selector.User.Value = null); } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs index b6112a6501..09bc2f2cdc 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs @@ -2,11 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Rulesets; +using osu.Game.Users; using osuTK; using osuTK.Graphics; @@ -16,6 +18,8 @@ namespace osu.Game.Overlays.Profile.Header.Components { private Color4 accentColour = Color4.White; + public readonly Bindable User = new Bindable(); + public ProfileRulesetSelector() { TabContainer.Masking = false; @@ -32,24 +36,22 @@ namespace osu.Game.Overlays.Profile.Header.Components ((ProfileRulesetTabItem)tabItem).AccentColour = accentColour; } - public void SetDefaultRuleset(RulesetInfo ruleset) + protected override void LoadComplete() { - // Todo: This method shouldn't exist, but bindables don't provide the concept of observing a change to the default value - foreach (TabItem tabItem in TabContainer) - ((ProfileRulesetTabItem)tabItem).IsDefault = ((ProfileRulesetTabItem)tabItem).Value.ID == ruleset.ID; + base.LoadComplete(); + + User.BindValueChanged(onUserChanged, true); } - public void SelectDefaultRuleset() + private void onUserChanged(ValueChangedEvent user) + { + SetDefaultRuleset(Rulesets.GetRuleset(user.NewValue?.PlayMode ?? "osu")); + } + + public void SetDefaultRuleset(RulesetInfo ruleset) { - // Todo: This method shouldn't exist, but bindables don't provide the concept of observing a change to the default value foreach (TabItem tabItem in TabContainer) - { - if (((ProfileRulesetTabItem)tabItem).IsDefault) - { - Current.Value = ((ProfileRulesetTabItem)tabItem).Value; - return; - } - } + ((ProfileRulesetTabItem)tabItem).IsDefault = ((ProfileRulesetTabItem)tabItem).Value.ID == ruleset.ID; } protected override TabItem CreateTabItem(RulesetInfo value) => new ProfileRulesetTabItem(value) From d693a54c84eb088a31fc9ebefcc9d7d811db60d1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 4 Aug 2019 14:35:26 +0300 Subject: [PATCH 2179/5608] Move RankHistoryData to User Statistics --- .../Visual/Online/TestSceneRankGraph.cs | 47 +++++++------------ .../Online/TestSceneUserProfileOverlay.cs | 12 ++--- .../Profile/Header/Components/RankGraph.cs | 19 +++++--- .../Profile/Header/DetailHeaderContainer.cs | 2 +- osu.Game/Users/User.cs | 5 +- osu.Game/Users/UserStatistics.cs | 3 ++ 6 files changed, 42 insertions(+), 46 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs index 709e75ab13..c70cc4ae4e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs @@ -69,28 +69,22 @@ namespace osu.Game.Tests.Visual.Online } }); - AddStep("null user", () => graph.User.Value = null); + AddStep("null user", () => graph.Statistics.Value = null); AddStep("rank only", () => { - graph.User.Value = new User + graph.Statistics.Value = new UserStatistics { - Statistics = new UserStatistics - { - Ranks = new UserStatistics.UserRanks { Global = 123456 }, - PP = 12345, - } + Ranks = new UserStatistics.UserRanks { Global = 123456 }, + PP = 12345, }; }); AddStep("with rank history", () => { - graph.User.Value = new User + graph.Statistics.Value = new UserStatistics { - Statistics = new UserStatistics - { - Ranks = new UserStatistics.UserRanks { Global = 89000 }, - PP = 12345, - }, + Ranks = new UserStatistics.UserRanks { Global = 89000 }, + PP = 12345, RankHistory = new User.RankHistoryData { Data = data, @@ -100,13 +94,10 @@ namespace osu.Game.Tests.Visual.Online AddStep("with zero values", () => { - graph.User.Value = new User + graph.Statistics.Value = new UserStatistics { - Statistics = new UserStatistics - { - Ranks = new UserStatistics.UserRanks { Global = 89000 }, - PP = 12345, - }, + Ranks = new UserStatistics.UserRanks { Global = 89000 }, + PP = 12345, RankHistory = new User.RankHistoryData { Data = dataWithZeros, @@ -116,13 +107,10 @@ namespace osu.Game.Tests.Visual.Online AddStep("small amount of data", () => { - graph.User.Value = new User + graph.Statistics.Value = new UserStatistics { - Statistics = new UserStatistics - { - Ranks = new UserStatistics.UserRanks { Global = 12000 }, - PP = 12345, - }, + Ranks = new UserStatistics.UserRanks { Global = 12000 }, + PP = 12345, RankHistory = new User.RankHistoryData { Data = smallData, @@ -132,13 +120,10 @@ namespace osu.Game.Tests.Visual.Online AddStep("graph with edges", () => { - graph.User.Value = new User + graph.Statistics.Value = new UserStatistics { - Statistics = new UserStatistics - { - Ranks = new UserStatistics.UserRanks { Global = 12000 }, - PP = 12345, - }, + Ranks = new UserStatistics.UserRanks { Global = 12000 }, + PP = 12345, RankHistory = new User.RankHistoryData { Data = edgyData, diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index c2376aa153..84c99d8c3a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -50,12 +50,12 @@ namespace osu.Game.Tests.Visual.Online { Current = 727, Progress = 69, - } - }, - RankHistory = new User.RankHistoryData - { - Mode = @"osu", - Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray() + }, + RankHistory = new User.RankHistoryData + { + Mode = @"osu", + Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray() + }, }, Badges = new[] { diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 5f79386b76..4818cd8df6 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Profile.Header.Components private KeyValuePair[] ranks; private int dayIndex; - public Bindable User = new Bindable(); + public readonly Bindable Statistics = new Bindable(); public RankGraph() { @@ -56,8 +56,6 @@ namespace osu.Game.Overlays.Profile.Header.Components }; graph.OnBallMove += i => dayIndex = i; - - User.ValueChanged += userChanged; } [BackgroundDependencyLoader] @@ -66,18 +64,25 @@ namespace osu.Game.Overlays.Profile.Header.Components graph.LineColour = colours.Yellow; } - private void userChanged(ValueChangedEvent e) + protected override void LoadComplete() + { + base.LoadComplete(); + + Statistics.BindValueChanged(statistics => updateStatistics(statistics.NewValue)); + } + + private void updateStatistics(UserStatistics statistics) { placeholder.FadeIn(fade_duration, Easing.Out); - if (e.NewValue?.Statistics?.Ranks.Global == null) + if (statistics?.Ranks.Global == null) { graph.FadeOut(fade_duration, Easing.Out); ranks = null; return; } - int[] userRanks = e.NewValue.RankHistory?.Data ?? new[] { e.NewValue.Statistics.Ranks.Global.Value }; + int[] userRanks = statistics.RankHistory?.Data ?? new[] { statistics.Ranks.Global.Value }; ranks = userRanks.Select((x, index) => new KeyValuePair(index, x)).Where(x => x.Value != 0).ToArray(); if (ranks.Length > 1) @@ -191,7 +196,7 @@ namespace osu.Game.Overlays.Profile.Header.Components } } - public string TooltipText => User.Value?.Statistics?.Ranks.Global == null ? "" : $"#{ranks[dayIndex].Value:#,##0}|{ranked_days - ranks[dayIndex].Key + 1}"; + public string TooltipText => Statistics.Value?.Ranks.Global == null ? "" : $"#{ranks[dayIndex].Value:#,##0}|{ranked_days - ranks[dayIndex].Key + 1}"; public ITooltip GetCustomTooltip() => new RankGraphTooltip(); diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index 0db1cb32d7..6ee0d9ee8f 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -179,7 +179,7 @@ namespace osu.Game.Overlays.Profile.Header detailGlobalRank.Content = user?.Statistics?.Ranks.Global?.ToString("\\##,##0") ?? "-"; detailCountryRank.Content = user?.Statistics?.Ranks.Country?.ToString("\\##,##0") ?? "-"; - rankGraph.User.Value = user; + rankGraph.Statistics.Value = user?.Statistics; } private class ScoreRankInfo : CompositeDrawable diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 34bd4bbaae..b738eff4a6 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -159,7 +159,10 @@ namespace osu.Game.Users } [JsonProperty(@"rankHistory")] - public RankHistoryData RankHistory; + private RankHistoryData rankHistory + { + set => Statistics.RankHistory = value; + } [JsonProperty("badges")] public Badge[] Badges; diff --git a/osu.Game/Users/UserStatistics.cs b/osu.Game/Users/UserStatistics.cs index 7afbef01c5..032ec2e05f 100644 --- a/osu.Game/Users/UserStatistics.cs +++ b/osu.Game/Users/UserStatistics.cs @@ -4,6 +4,7 @@ using System; using Newtonsoft.Json; using osu.Game.Scoring; +using static osu.Game.Users.User; namespace osu.Game.Users { @@ -113,5 +114,7 @@ namespace osu.Game.Users [JsonProperty(@"country")] public int? Country; } + + public RankHistoryData RankHistory; } } From cd7b6d2d27de45747cf439a4676e0b3c0ba5cc43 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 4 Aug 2019 15:00:02 +0300 Subject: [PATCH 2180/5608] TestCase improvement --- .../Online/TestSceneProfileRulesetSelector.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs index d439e6a7c3..1f5ba67e03 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs @@ -10,6 +10,7 @@ using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Taiko; using osu.Game.Users; +using osu.Framework.Bindables; namespace osu.Game.Tests.Visual.Online { @@ -24,11 +25,13 @@ namespace osu.Game.Tests.Visual.Online public TestSceneProfileRulesetSelector() { ProfileRulesetSelector selector; + Bindable user = new Bindable(); Child = selector = new ProfileRulesetSelector { Anchor = Anchor.Centre, Origin = Anchor.Centre, + User = { BindTarget = user } }; AddStep("set osu! as default", () => selector.SetDefaultRuleset(new OsuRuleset().RulesetInfo)); @@ -36,11 +39,11 @@ namespace osu.Game.Tests.Visual.Online AddStep("set taiko as default", () => selector.SetDefaultRuleset(new TaikoRuleset().RulesetInfo)); AddStep("set catch as default", () => selector.SetDefaultRuleset(new CatchRuleset().RulesetInfo)); - AddStep("User with osu as default", () => selector.User.Value = new User { PlayMode = "osu" }); - AddStep("User with mania as default", () => selector.User.Value = new User { PlayMode = "mania" }); - AddStep("User with taiko as default", () => selector.User.Value = new User { PlayMode = "taiko" }); - AddStep("User with catch as default", () => selector.User.Value = new User { PlayMode = "fruits" }); - AddStep("null user", () => selector.User.Value = null); + AddStep("User with osu as default", () => user.Value = new User { PlayMode = "osu" }); + AddStep("User with mania as default", () => user.Value = new User { PlayMode = "mania" }); + AddStep("User with taiko as default", () => user.Value = new User { PlayMode = "taiko" }); + AddStep("User with catch as default", () => user.Value = new User { PlayMode = "fruits" }); + AddStep("null user", () => user.Value = null); } } } From 2f5d23b35419f78763924593e5dc03876b0baeb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20H=C3=BCbner?= Date: Mon, 5 Aug 2019 01:02:42 +0200 Subject: [PATCH 2181/5608] add join command --- osu.Game/Online/Chat/ChannelManager.cs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 3af11ff20f..30135d5b8b 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -213,8 +213,27 @@ namespace osu.Game.Online.Chat PostMessage(content, true); break; + case "j": + case "join": + if (string.IsNullOrWhiteSpace(content)) + { + target.AddNewMessages(new ErrorMessage("Usage: /join [channel]")); + break; + } + + var channel = availableChannels.Where(c => c.Name == content || c.Name == $"#{content}").FirstOrDefault(); + if (channel == null) + { + target.AddNewMessages(new ErrorMessage($"Channel '{content}' not found.")); + break; + } + + JoinChannel(channel); + CurrentChannel.Value = channel; + break; + case "help": - target.AddNewMessages(new InfoMessage("Supported commands: /help, /me [action]")); + target.AddNewMessages(new InfoMessage("Supported commands: /help, /me [action], /join [channel]")); break; default: From d83971713118afe7dff0ea2f31d47e540b9d3f27 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 5 Aug 2019 13:18:29 +0900 Subject: [PATCH 2182/5608] Remove unnecessary intermediate method --- .../Profile/Header/Components/ProfileRulesetSelector.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs index 09bc2f2cdc..2c9a3dd5f9 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs @@ -40,12 +40,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { base.LoadComplete(); - User.BindValueChanged(onUserChanged, true); - } - - private void onUserChanged(ValueChangedEvent user) - { - SetDefaultRuleset(Rulesets.GetRuleset(user.NewValue?.PlayMode ?? "osu")); + User.BindValueChanged(u => SetDefaultRuleset(Rulesets.GetRuleset(u.NewValue?.PlayMode ?? "osu")), true); } public void SetDefaultRuleset(RulesetInfo ruleset) From 379c9e8b7caf3f8382418d818741632ce5dd0303 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 5 Aug 2019 10:02:28 +0200 Subject: [PATCH 2183/5608] Use expression body --- osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs | 5 +---- osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs | 5 +---- osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs | 5 +---- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index 3a695ca179..b9699a88e4 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -22,10 +22,7 @@ namespace osu.Game.Rulesets.Catch.Tests [TestCase("spinner")] [TestCase("spinner-and-circles")] [TestCase("slider")] - public void Test(string name) - { - base.Test(name); - } + public void Test(string name) => base.Test(name); protected override IEnumerable CreateConvertValue(HitObject hitObject) { diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index 3ca9dcc42c..6f10540973 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -20,10 +20,7 @@ namespace osu.Game.Rulesets.Mania.Tests protected override string ResourceAssembly => "osu.Game.Rulesets.Mania"; [TestCase("basic")] - public void Test(string name) - { - base.Test(name); - } + public void Test(string name) => base.Test(name); protected override IEnumerable CreateConvertValue(HitObject hitObject) { diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index bafa814582..6c1882b4e2 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -20,10 +20,7 @@ namespace osu.Game.Rulesets.Taiko.Tests [NonParallelizable] [TestCase("basic")] [TestCase("slider-generating-drumroll")] - public void Test(string name) - { - base.Test(name); - } + public void Test(string name) => base.Test(name); protected override IEnumerable CreateConvertValue(HitObject hitObject) { From ee9e8f6261d92ca24f364b7147c54dca4e542d39 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 5 Aug 2019 17:58:16 +0900 Subject: [PATCH 2184/5608] Fix memory leaks from download buttons --- osu.Game/Online/DownloadTrackingComposite.cs | 30 +++++++++++--------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/osu.Game/Online/DownloadTrackingComposite.cs b/osu.Game/Online/DownloadTrackingComposite.cs index 62d6efcb6f..7bfdc7ff69 100644 --- a/osu.Game/Online/DownloadTrackingComposite.cs +++ b/osu.Game/Online/DownloadTrackingComposite.cs @@ -48,22 +48,24 @@ namespace osu.Game.Online attachDownload(manager.GetExistingDownload(modelInfo.NewValue)); }, true); - manager.DownloadBegan += download => - { - if (download.Model.Equals(Model.Value)) - attachDownload(download); - }; - - manager.DownloadFailed += download => - { - if (download.Model.Equals(Model.Value)) - attachDownload(null); - }; - + manager.DownloadBegan += downloadBegan; + manager.DownloadFailed += downloadFailed; manager.ItemAdded += itemAdded; manager.ItemRemoved += itemRemoved; } + private void downloadBegan(ArchiveDownloadRequest request) + { + if (request.Model.Equals(Model.Value)) + attachDownload(request); + } + + private void downloadFailed(ArchiveDownloadRequest request) + { + if (request.Model.Equals(Model.Value)) + attachDownload(null); + } + private ArchiveDownloadRequest attachedRequest; private void attachDownload(ArchiveDownloadRequest request) @@ -126,8 +128,10 @@ namespace osu.Game.Online if (manager != null) { - manager.DownloadBegan -= attachDownload; + manager.DownloadBegan -= downloadBegan; + manager.DownloadFailed -= downloadFailed; manager.ItemAdded -= itemAdded; + manager.ItemRemoved -= itemRemoved; } State.UnbindAll(); From 749a00cc2f324490096fadd5bc3eeee12f13ce81 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 5 Aug 2019 12:49:54 +0300 Subject: [PATCH 2185/5608] Force bindable change --- osu.Game/Overlays/Profile/Header/Components/RankGraph.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 4818cd8df6..9cb9d48de7 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -68,7 +68,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { base.LoadComplete(); - Statistics.BindValueChanged(statistics => updateStatistics(statistics.NewValue)); + Statistics.BindValueChanged(statistics => updateStatistics(statistics.NewValue), true); } private void updateStatistics(UserStatistics statistics) From 11916782ba9dd82b51ede9cf57e4e36252f05e34 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 5 Aug 2019 19:23:13 +0900 Subject: [PATCH 2186/5608] Fix drawable channels remaining in memory after being closed --- osu.Game/Overlays/ChatOverlay.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index e223856b27..53a05656b1 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -256,6 +256,9 @@ namespace osu.Game.Overlays loadedChannels.Add(loaded); LoadComponentAsync(loaded, l => { + if (currentChannel.Value != e.NewValue) + return; + loading.Hide(); currentChannelContainer.Clear(false); @@ -381,7 +384,18 @@ namespace osu.Game.Overlays foreach (Channel channel in channels) { ChannelTabControl.RemoveChannel(channel); - loadedChannels.Remove(loadedChannels.Find(c => c.Channel == channel)); + + var loaded = loadedChannels.Find(c => c.Channel == channel); + + if (loaded != null) + { + loadedChannels.Remove(loaded); + + // Because the container is only cleared in the async load callback of a new channel, it is forcefully cleared + // to ensure that the previous channel doesn't get updated after it's disposed + currentChannelContainer.Remove(loaded); + loaded.Dispose(); + } } } From 0fe6585975a7efdf6b00a73f7be41593c7ea6e20 Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Mon, 5 Aug 2019 22:30:35 +0800 Subject: [PATCH 2187/5608] Fix iOS importing --- osu.Game/Database/ArchiveModelManager.cs | 2 +- osu.Game/OsuGame.cs | 24 ++++++++---------------- osu.iOS/AppDelegate.cs | 6 +++++- osu.iOS/Info.plist | 2 ++ osu.iOS/OsuGameIOS.cs | 2 ++ 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index efb76deff8..37ea7b2ca9 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -54,7 +54,7 @@ namespace osu.Game.Database public virtual string[] HandledExtensions => new[] { ".zip" }; - public virtual bool SupportsImportFromStable => RuntimeInfo.IsDesktop; + public virtual bool SupportsImportFromStable => (RuntimeInfo.IsDesktop || RuntimeInfo.OS == RuntimeInfo.Platform.iOS); protected readonly FileStore Files; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b64f04de2a..846677a0a9 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -91,8 +91,6 @@ namespace osu.Game private IntroScreen introScreen; - private bool loaded; - private Bindable configRuleset; private Bindable configSkin; @@ -201,18 +199,15 @@ namespace osu.Game { Logger.Log($"Request to handle url: {url}"); - if (loaded) + Action showNotImplementedError = () => notifications?.Post(new SimpleNotification { - Action showNotImplementedError = () => notifications?.Post(new SimpleNotification - { - Text = @"This link type is not yet supported!", - Icon = FontAwesome.Solid.LifeRing, - }); - LinkDetails linkDetails = GetLinkDetails(url); - Schedule(() => LinkUtils.HandleLink(url, linkDetails.Action, linkDetails.Argument, this, channelManager, showNotImplementedError)); - } - else - Scheduler.AddDelayed(() => HandleUrl(url), 1000); + Text = @"This link type is not yet supported!", + Icon = FontAwesome.Solid.LifeRing, + }); + + LinkDetails linkDetails = GetLinkDetails(url); + + Schedule(() => LinkUtils.HandleLink(url, linkDetails.Action, linkDetails.Argument, this, channelManager, showNotImplementedError)); } public void OpenUrlExternally(string url) @@ -403,8 +398,6 @@ namespace osu.Game protected override void LoadComplete() { - loaded = false; - base.LoadComplete(); // The next time this is updated is in UpdateAfterChildren, which occurs too late and results @@ -600,7 +593,6 @@ namespace osu.Game settings.State.ValueChanged += _ => updateScreenOffset(); notifications.State.ValueChanged += _ => updateScreenOffset(); - loaded = true; } public class GameIdleTracker : IdleTracker diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs index e727305997..07e0245195 100644 --- a/osu.iOS/AppDelegate.cs +++ b/osu.iOS/AppDelegate.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 Foundation; using osu.Framework.iOS; using osu.Framework.Threading; @@ -17,7 +18,10 @@ namespace osu.iOS public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options) { - game.HandleUrl(url.AbsoluteString); + if (url.IsFileUrl) + Task.Run(() => game.Import(url.Path)); + else + Task.Run(() => game.HandleUrl(url.AbsoluteString)); return true; } } diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index f3067bdcec..5fe8cd6d5b 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -14,6 +14,8 @@ 0.1.0 LSRequiresIPhoneOS + LSSupportsOpeningDocumentsInPlace + MinimumOSVersion 10.0 UIDeviceFamily diff --git a/osu.iOS/OsuGameIOS.cs b/osu.iOS/OsuGameIOS.cs index 6cf18df9a6..ac66357fc9 100644 --- a/osu.iOS/OsuGameIOS.cs +++ b/osu.iOS/OsuGameIOS.cs @@ -3,12 +3,14 @@ using System; using Foundation; +using osu.Framework.Platform; using osu.Game; namespace osu.iOS { public class OsuGameIOS : OsuGame { + public override Storage GetStorageForStableInstall() => Storage; public override Version AssemblyVersion => new Version(NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString()); } } From a7ac411c2562e1f774b77111c10abc8ea6667fe8 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 5 Aug 2019 17:57:04 -0700 Subject: [PATCH 2188/5608] Fix footer button hover sounds playing in unclickable area --- osu.Game/Screens/Select/Footer.cs | 2 +- osu.Game/Screens/Select/FooterButton.cs | 12 ++++++------ osu.Game/Screens/Select/FooterButtonMods.cs | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index 0680711f1c..1dc7081c1c 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -94,7 +94,7 @@ namespace osu.Game.Screens.Select buttons = new FillFlowContainer { Direction = FillDirection.Horizontal, - Spacing = new Vector2(0.2f, 0), + Spacing = new Vector2(-FooterButton.SHEAR_WIDTH, 0), AutoSizeAxes = Axes.Both, } } diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index e18a086a10..90bc902ad8 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -17,7 +17,9 @@ namespace osu.Game.Screens.Select { public class FooterButton : OsuClickableContainer { - private static readonly Vector2 shearing = new Vector2(0.15f, 0); + public static readonly float SHEAR_WIDTH = 7.5f; + + protected static readonly Vector2 SHEARING = new Vector2(SHEAR_WIDTH / Footer.HEIGHT, 0); public string Text { @@ -59,16 +61,16 @@ namespace osu.Game.Screens.Select private readonly Box box; private readonly Box light; - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => box.ReceivePositionalInputAt(screenSpacePos); - public FooterButton() { AutoSizeAxes = Axes.Both; + Shear = SHEARING; Children = new Drawable[] { TextContainer = new Container { - Size = new Vector2(100, 50), + Size = new Vector2(100 - SHEAR_WIDTH, 50), + Shear = -SHEARING, Child = SpriteText = new OsuSpriteText { Anchor = Anchor.Centre, @@ -78,14 +80,12 @@ namespace osu.Game.Screens.Select box = new Box { RelativeSizeAxes = Axes.Both, - Shear = shearing, EdgeSmoothness = new Vector2(2, 0), Colour = Color4.White, Alpha = 0, }, light = new Box { - Shear = shearing, Height = 4, EdgeSmoothness = new Vector2(2, 0), RelativeSizeAxes = Axes.X, diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index fce4d1b2e2..58d92dbca6 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -32,6 +32,7 @@ namespace osu.Game.Screens.Select { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, + Shear = -SHEARING, Child = modDisplay = new FooterModDisplay { DisplayUnrankedText = false, From cd6fe918821aec9d150311bcc6ac0ec653b672dc Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 5 Aug 2019 19:56:35 +0900 Subject: [PATCH 2189/5608] Log error for invalid events --- .../Formats/LegacyBeatmapDecoderTest.cs | 17 + osu.Game.Tests/Resources/invalid-events.osu | 1004 +++++++++++++++++ .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 6 +- .../Formats/LegacyStoryboardDecoder.cs | 3 +- 4 files changed, 1028 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Resources/invalid-events.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index d087251e7e..98464b8d91 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -482,5 +482,22 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(hitObjects[0].Samples[0].Bank, hitObjects[0].Samples[1].Bank); } } + + [Test] + public void TestDecodeInvalidEvents() + { + using (var normalResStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) + using (var normalStream = new StreamReader(normalResStream)) + using (var resStream = TestResources.OpenResource("invalid-events.osu")) + using (var stream = new StreamReader(resStream)) + { + var decoder = Decoder.GetDecoder(stream); + var goodBeatmap = decoder.Decode(normalStream); + Beatmap badBeatmap = null; + + Assert.DoesNotThrow(() => badBeatmap = decoder.Decode(stream)); + Assert.AreEqual(goodBeatmap.HitObjects.Count, badBeatmap.HitObjects.Count); + } + } } } diff --git a/osu.Game.Tests/Resources/invalid-events.osu b/osu.Game.Tests/Resources/invalid-events.osu new file mode 100644 index 0000000000..a8e767585c --- /dev/null +++ b/osu.Game.Tests/Resources/invalid-events.osu @@ -0,0 +1,1004 @@ +osu file format v14 + +[General] +AudioFilename: 03. Renatus - Soleily 192kbps.mp3 +AudioLeadIn: 0 +PreviewTime: 164471 +Countdown: 0 +SampleSet: Soft +StackLeniency: 0.7 +Mode: 0 +LetterboxInBreaks: 0 +WidescreenStoryboard: 0 + +[Editor] +Bookmarks: 11505,22054,32604,43153,53703,64252,74802,85351,95901,106450,116999,119637,130186,140735,151285,161834,164471,175020,185570,196119,206669,209306 +DistanceSpacing: 1.8 +BeatDivisor: 4 +GridSize: 4 +TimelineZoom: 2 + +[Metadata] +Title:Renatus +TitleUnicode:Renatus +Artist:Soleily +ArtistUnicode:Soleily +Creator:Gamu +Version:Insane +Source: +Tags:MBC7 Unisphere 地球ヤバイEP Chikyu Yabai +BeatmapID:557821 +BeatmapSetID:241526 + +[Difficulty] +HPDrainRate:6.5 +CircleSize:4 +OverallDifficulty:8 +ApproachRate:9 +SliderMultiplier:1.8 +SliderTickRate:2 + +[Events] +bad,event,this,should,fail +//Background and Video events +0,0,"machinetop_background.jpg",0,0 +//Break Periods +2,122474,140135 +//Storyboard Layer 0 (Background) +//Storyboard Layer 1 (Fail) +//Storyboard Layer 2 (Pass) +//Storyboard Layer 3 (Foreground) +//Storyboard Sound Samples + +[TimingPoints] +956,329.67032967033,4,2,0,60,1,0 +20736,-100,4,2,0,65,0,0 +22054,-100,4,2,0,70,0,0 +43153,-100,4,2,0,60,0,0 +48428,-100,4,2,0,50,0,0 +52879,-100,4,2,0,50,0,0 +53373,-100,4,2,0,60,0,0 +53703,-100,4,2,0,70,0,1 +74719,-100,4,2,0,70,0,0 +74802,-100,4,2,0,70,0,1 +95901,-100,4,2,0,70,0,0 +116999,-133.333333333333,4,2,0,50,0,0 +117164,-133.333333333333,4,2,0,30,0,0 +117329,-79.9999999999999,4,2,0,50,0,0 +117659,-100,4,2,0,50,0,0 +118977,-100,4,2,0,60,0,0 +119307,-100,4,2,0,70,0,0 +119637,659.340659340659,4,2,0,80,1,0 +119966,-100,4,2,0,70,0,0 +120296,-100,4,2,0,60,0,0 +120626,-100,4,2,0,50,0,0 +120955,-100,4,2,0,40,0,0 +121285,-100,4,2,0,30,0,0 +121615,-100,4,2,0,20,0,0 +121944,-100,4,2,0,10,0,0 +122274,-100,4,2,0,5,0,0 +140735,-100,4,2,0,50,0,0 +151285,-80,4,2,0,60,0,0 +161834,329.67032967033,4,2,0,65,1,0 +164141,-100,4,2,0,70,0,0 +164471,-100,4,2,0,70,0,1 +185487,-100,4,2,0,70,0,0 +185570,-100,4,2,0,70,0,1 +206669,659.340659340659,4,2,0,80,1,0 +206998,-100,4,2,0,70,0,0 +207328,-100,4,2,0,60,0,0 +207658,-100,4,2,0,50,0,0 +207987,-100,4,2,0,40,0,0 +208317,-100,4,2,0,30,0,0 +208647,-100,4,2,0,20,0,0 +208976,-100,4,2,0,10,0,0 +209306,-100,4,2,0,5,0,0 + + +[Colours] +Combo1 : 142,199,255 +Combo2 : 255,128,128 +Combo3 : 128,255,255 +Combo4 : 128,255,128 +Combo5 : 255,187,255 +Combo6 : 255,177,140 +Combo7 : 100,100,100,100 + +[HitObjects] +192,168,956,6,0,P|184:128|200:80,1,90,4|0,1:2|0:0,0:0:0:0: +304,56,1285,1,8,0:0:0:0: +244,236,1450,2,0,P|204:252|156:244,1,90,2|0,0:0|0:0,0:0:0:0: +276,156,1780,2,0,P|310:181|329:226,1,90,2|8,1:2|0:0,0:0:0:0: +300,328,2109,1,2,0:0:0:0: +192,332,2274,6,0,L|144:340,2,45,0|0|0,1:0|0:0|0:0,0:0:0:0: +388,300,2604,1,8,0:0:0:0: +244,236,2769,1,0,1:0:0:0: +232,208,2851,1,0,0:0:0:0: +224,176,2934,1,0,0:0:0:0: +228,144,3016,1,0,0:0:0:0: +244,116,3098,1,0,1:0:0:0: +332,52,3263,2,0,P|376:48|424:56,1,90,8|0,0:0|0:0,0:0:0:0: +488,228,3593,5,0,1:0:0:0: +460,240,3675,1,0,0:0:0:0: +428,236,3758,1,0,0:0:0:0: +292,160,3923,2,0,P|288:204|300:252,1,90,8|0,0:0|0:0,0:0:0:0: +316,276,4170,1,0,0:0:0:0: +344,292,4252,2,0,L|388:300,1,45,0|0,0:0|0:0,0:0:0:0: +288,356,4417,2,0,L|244:364,1,45,0|0,1:0|0:0,0:0:0:0: +168,328,4582,2,0,P|124:324|72:332,1,90,8|0,0:0|0:0,0:0:0:0: +24,188,4912,5,0,1:0:0:0: +56,192,4994,1,0,0:0:0:0: +88,196,5076,1,0,0:0:0:0: +148,108,5241,1,8,0:0:0:0: +188,240,5406,1,0,1:0:0:0: +188,240,5488,1,0,0:0:0:0: +188,240,5571,2,0,L|168:328,1,90,0|0,0:0|1:0,0:0:0:0: +260,216,5901,2,0,P|236:180|188:164,1,90,8|0,0:0|0:0,0:0:0:0: +248,296,6230,6,0,L|348:292,1,90,0|0,1:0|0:0,0:0:0:0: +504,232,6560,1,8,0:0:0:0: +400,204,6725,1,0,0:0:0:0: +392,176,6807,1,0,0:0:0:0: +384,144,6890,1,0,0:0:0:0: +376,116,6972,1,0,0:0:0:0: +368,88,7054,1,0,1:0:0:0: +188,48,7219,2,0,L|208:140,1,90,8|0,0:0|0:0,0:0:0:0: +248,296,7549,5,0,1:0:0:0: +207,135,7714,1,0,0:0:0:0: +156,232,7879,1,8,0:0:0:0: +316,191,8043,1,0,1:0:0:0: +316,191,8126,1,0,0:0:0:0: +316,191,8208,2,0,L|372:200,1,45,0|0,0:0|0:0,0:0:0:0: +492,200,8373,2,0,L|447:207,1,45,0|0,1:0|0:0,0:0:0:0: +408,136,8538,2,0,P|396:92|400:48,1,90,8|0,0:0|0:0,0:0:0:0: +260,32,8868,5,0,1:0:0:0: +252,64,8950,1,0,0:0:0:0: +236,92,9032,2,0,P|204:116|148:128,1,90,0|8,0:0|0:0,0:0:0:0: +28,188,9362,1,0,0:0:0:0: +60,196,9445,1,0,0:0:0:0: +88,212,9527,2,0,P|112:244|124:300,1,90,0|0,0:0|1:0,0:0:0:0: +112,128,9857,2,0,P|152:156|184:196,1,90,8|0,0:0|0:0,0:0:0:0: +216,288,10186,5,0,1:0:0:0: +216,288,10269,1,0,0:0:0:0: +216,288,10351,1,0,0:0:0:0: +268,192,10516,1,8,0:0:0:0: +356,128,10681,1,0,1:0:0:0: +388,120,10763,1,0,0:0:0:0: +420,128,10846,2,0,P|440:168|436:220,1,90,0|0,0:0|1:0,0:0:0:0: +332,328,11175,2,0,L|280:332,1,45,8|8,0:0|0:0,0:0:0:0: +216,288,11340,2,0,L|164:292,1,45,0|0,1:0|0:0,1:0:0:0: +100,248,11505,5,4,1:2:0:0: +148,116,11670,1,2,0:0:0:0: +268,192,11835,1,10,0:0:0:0: +136,328,11999,2,0,L|44:336,1,90,2|0,0:0|0:0,0:0:0:0: +216,288,12329,1,2,1:2:0:0: +148,116,12494,1,10,0:0:0:0: +100,248,12659,1,2,0:0:0:0: +268,192,12824,5,0,1:0:0:0: +268,192,12906,1,0,0:0:0:0: +268,192,12988,1,0,0:0:0:0: +340,272,13153,2,0,P|384:276|432:264,1,90,8|0,0:0|1:0,0:0:0:0: +452,244,13401,1,0,0:0:0:0: +468,216,13483,2,0,L|476:124,1,90,0|0,0:0|1:0,0:0:0:0: +368,32,13813,2,0,L|360:121,1,90,8|0,0:0|0:0,0:0:0:0: +340,272,14142,6,0,L|316:316,2,45,0|0|0,1:0|0:0|0:0,0:0:0:0: +452,244,14472,1,8,0:0:0:0: +268,192,14637,1,0,0:0:0:0: +236,188,14719,1,0,0:0:0:0: +204,192,14802,2,0,P|172:228|160:272,1,90,0|0,0:0|1:0,0:0:0:0: +128,140,15131,2,0,P|160:104|172:60,1,90,8|0,0:0|0:0,0:0:0:0: +64,52,15461,6,0,L|20:68,2,45,0|0|0,1:0|0:0|0:0,0:0:0:0: +171,64,15791,1,8,0:0:0:0: +264,8,15956,2,0,L|356:12,1,90,0|0,1:0|0:0,0:0:0:0: +452,56,16285,1,0,1:0:0:0: +296,140,16450,2,0,L|206:136,1,90,8|0,0:0|0:0,0:0:0:0: +108,184,16780,6,0,P|92:224|96:272,1,90,0|0,1:0|0:0,0:0:0:0: +200,244,17109,1,8,0:0:0:0: +108,108,17274,2,0,L|12:116,1,90,0|0,0:0|0:0,0:0:0:0: +200,244,17604,1,0,1:0:0:0: +296,140,17769,2,0,L|385:132,1,90,8|0,0:0|0:0,0:0:0:0: +480,184,18098,5,0,1:0:0:0: +488,216,18181,1,0,0:0:0:0: +496,248,18263,2,0,L|492:340,1,90,0|8,0:0|0:0,0:0:0:0: +404,224,18593,2,0,L|396:176,2,45,0|0|0,1:0|0:0|0:0,0:0:0:0: +304,264,18923,1,0,1:0:0:0: +200,244,19087,2,0,P|156:240|108:248,1,90,8|0,0:0|0:0,0:0:0:0: +296,140,19417,6,0,P|340:144|388:136,1,90,0|0,1:0|0:0,0:0:0:0: +440,44,19747,1,8,0:0:0:0: +404,224,19912,1,0,0:0:0:0: +404,224,19994,1,0,0:0:0:0: +404,224,20076,2,0,L|412:320,1,90,0|0,0:0|1:0,0:0:0:0: +200,244,20406,2,0,L|192:154,1,90,8|0,0:0|0:0,0:0:0:0: +184,44,20736,5,4,1:2:0:0: +152,40,20818,1,0,0:0:0:0: +120,48,20901,1,0,0:0:0:0: +96,68,20983,1,0,0:0:0:0: +76,92,21065,1,2,0:3:0:0: +64,120,21148,1,0,0:0:0:0: +60,152,21230,1,0,1:0:0:0: +64,184,21313,1,0,0:0:0:0: +76,212,21395,2,0,L|96:252,3,45,0|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: +144,316,21725,2,0,L|188:324,3,45,0|0|2|0,0:0|0:0|0:3|0:0,0:0:0:0: +268,340,22054,6,0,L|364:336,1,90,4|0,1:2|0:0,0:0:0:0: +452,280,22384,1,8,0:0:0:0: +512,188,22549,2,0,P|516:144|504:96,1,90,2|0,0:0|0:0,0:0:0:0: +340,24,22879,2,0,P|336:68|348:116,1,90,2|8,1:2|0:0,0:0:0:0: +420,192,23208,1,2,0:0:0:0: +328,252,23373,6,0,L|232:240,1,90,0|0,1:0|0:0,0:0:0:0: +64,256,23703,1,8,0:0:0:0: +144,184,23868,2,0,P|148:140|136:88,1,90,0|0,1:0|0:0,0:0:0:0: +40,52,24197,1,2,1:2:0:0: +139,95,24362,1,8,0:0:0:0: +216,20,24527,1,0,0:0:0:0: +315,63,24692,6,0,P|360:72|408:68,1,90,2|0,1:2|0:0,0:0:0:0: +492,132,25021,1,8,0:0:0:0: +412,204,25186,2,0,P|403:249|407:297,1,90,2|0,0:0|0:0,0:0:0:0: +268,328,25516,2,0,P|277:283|273:235,1,90,2|8,1:2|0:0,0:0:0:0: +232,140,25846,2,0,P|187:131|139:135,1,90,2|0,0:0|1:0,0:0:0:0: +64,208,26175,5,2,0:0:0:0: +44,316,26340,1,8,0:0:0:0: +148,280,26505,1,2,1:2:0:0: +456,208,26835,1,2,1:2:0:0: +476,316,26999,1,10,0:0:0:0: +372,280,27164,1,2,0:0:0:0: +356,172,27329,6,0,L|380:80,1,90,0|0,1:0|0:0,0:0:0:0: +456,208,27659,1,8,0:0:0:0: +300,236,27824,1,2,0:0:0:0: +300,236,27906,1,0,0:0:0:0: +300,236,27988,2,0,L|208:228,1,90,0|2,0:0|1:2,0:0:0:0: +140,312,28318,1,8,0:0:0:0: +372,280,28483,2,0,L|464:272,1,90,2|0,0:0|1:0,0:0:0:0: +500,136,28813,5,2,0:0:0:0: +432,56,28977,1,8,0:0:0:0: +328,24,29142,2,0,P|284:24|236:28,1,90,2|0,1:2|0:0,0:0:0:0: +80,144,29472,1,2,1:2:0:0: +116,44,29637,1,10,0:0:0:0: +184,128,29802,1,2,0:0:0:0: +20,88,29966,6,0,P|1:164|73:227,1,180,2|10,1:2|0:0,0:0:0:0: +184,128,30461,2,0,P|227:120|276:124,1,90,2|0,0:0|0:0,0:0:0:0: +392,188,30791,1,2,1:2:0:0: +272,260,30956,1,8,0:0:0:0: +396,328,31120,1,0,0:0:0:0: +256,348,31285,5,2,1:2:0:0: +224,344,31368,1,0,1:0:0:0: +192,340,31450,2,0,L|172:248,1,90,2|0,1:2|1:0,0:0:0:0: +8,136,31780,2,0,L|27:223,1,90,2|0,1:2|0:0,0:0:0:0: +56,328,32109,1,2,1:2:0:0: +108,192,32274,1,2,1:2:0:0: +100,160,32357,1,0,1:0:0:0: +92,132,32439,1,2,1:2:0:0: +84,104,32521,1,0,1:0:0:0: +76,72,32604,6,0,P|100:112|148:136,1,90,4|0,1:2|0:0,0:0:0:0: +240,168,32934,1,8,0:0:0:0: +336,124,33098,2,0,L|344:80,2,45,2|0|0,0:0|0:0|0:0,0:0:0:0: +264,248,33428,2,0,P|220:248|176:220,1,90,2|8,1:2|0:0,0:0:0:0: +260,84,33758,1,2,0:0:0:0: +344,212,33923,5,0,1:0:0:0: +344,212,34005,1,0,0:0:0:0: +344,212,34087,1,0,0:0:0:0: +440,160,34252,1,8,0:0:0:0: +312,320,34417,2,0,P|272:336|220:324,1,90,0|0,1:0|0:0,0:0:0:0: +156,176,34747,2,0,P|196:160|248:172,2,90,2|8|0,1:2|0:0|0:0,0:0:0:0: +132,280,35241,5,2,1:2:0:0: +132,280,35324,1,0,0:0:0:0: +132,280,35406,2,0,L|120:376,1,90,0|8,0:0|0:0,0:0:0:0: +312,320,35736,2,0,L|300:230,1,90,2|0,0:0|0:0,0:0:0:0: +316,124,36065,1,2,1:2:0:0: +400,192,36230,1,8,0:0:0:0: +300,230,36395,2,0,P|255:231|211:224,1,90,2|0,0:0|1:0,0:0:0:0: +24,132,36725,5,0,0:0:0:0: +132,152,36890,1,8,0:0:0:0: +60,232,37054,1,2,1:2:0:0: +60,232,37137,1,0,0:0:0:0: +60,232,37219,1,0,0:0:0:0: +92,56,37384,2,0,L|184:44,1,90,2|10,1:2|0:0,0:0:0:0: +316,124,37714,2,0,L|226:135,1,90,2|0,0:0|1:0,0:0:0:0: +60,232,38043,6,0,P|52:276|64:328,1,90,0|8,0:0|0:0,0:0:0:0: +220,152,38373,2,0,P|176:144|124:156,1,90,2|0,0:0|0:0,0:0:0:0: +176,252,38703,1,2,1:2:0:0: +323,213,38868,2,0,L|316:124,1,90,8|2,0:0|0:0,0:0:0:0: +332,320,39197,5,0,1:0:0:0: +424,260,39362,1,2,0:0:0:0: +260,272,39527,2,0,P|246:313|256:360,1,90,8|2,0:0|1:2,0:0:0:0: +408,336,39857,1,0,0:0:0:0: +176,252,40021,2,0,L|80:260,2,90,2|10|2,1:2|0:0|0:0,0:0:0:0: +324,212,40516,5,2,1:2:0:0: +324,212,40598,1,0,1:0:0:0: +324,212,40681,1,0,1:0:0:0: +200,336,40846,1,2,1:2:0:0: +236,188,41010,1,2,1:2:0:0: +236,188,41093,1,0,1:0:0:0: +236,188,41175,1,0,1:0:0:0: +281,357,41340,1,2,1:2:0:0: +176,252,41505,1,2,1:2:0:0: +176,252,41587,1,0,1:0:0:0: +176,252,41670,1,0,1:0:0:0: +344,297,41835,5,2,1:2:0:0: +432,232,41999,1,2,1:2:0:0: +444,204,42082,1,0,1:0:0:0: +448,172,42164,1,0,1:0:0:0: +444,140,42247,1,0,1:0:0:0: +432,112,42329,2,0,L|440:64,2,45,2|0|0,1:2|1:0|1:0,0:0:0:0: +236,188,42659,1,0,0:0:0:0: +340,172,42824,1,2,0:3:0:0: +272,88,42988,1,0,0:0:0:0: +132,160,43153,6,0,P|148:248|220:296,1,180,4|8,1:2|0:0,0:0:0:0: +324,320,43648,2,0,L|336:364,2,45,0|0|0,0:0|0:0|0:0,0:0:0:0: +292,216,43977,1,0,1:0:0:0: +396,240,44142,2,0,P|440:244|488:232,1,90,8|0,0:0|0:0,0:0:0:0: +328,124,44472,6,0,P|284:120|236:132,1,90,0|0,1:0|0:0,0:0:0:0: +168,212,44802,1,8,0:0:0:0: +192,316,44966,1,0,1:0:0:0: +140,220,45131,1,0,0:0:0:0: +83,310,45296,1,0,1:0:0:0: +114,205,45461,1,8,0:0:0:0: +10,229,45626,1,0,0:0:0:0: +106,176,45791,6,0,P|113:133|108:85,1,90,0|0,1:0|0:0,0:0:0:0: +204,136,46120,1,8,0:0:0:0: +256,40,46285,1,0,0:0:0:0: +256,40,46368,1,0,0:0:0:0: +256,40,46450,2,0,L|356:44,1,90,0|0,0:0|1:0,0:0:0:0: +501,124,46780,2,0,L|412:128,1,90,8|0,0:0|0:0,0:0:0:0: +324,192,47109,5,0,1:0:0:0: +356,296,47274,1,0,0:0:0:0: +284,216,47439,1,8,0:0:0:0: +269,323,47604,1,0,1:0:0:0: +237,220,47769,1,0,0:0:0:0: +178,311,47934,1,0,1:0:0:0: +191,203,48098,1,8,0:0:0:0: +99,261,48263,1,0,0:0:0:0: +156,168,48428,6,0,B|176:112|136:64|136:64|200:96,1,180,4|8,1:2|0:0,0:0:0:0: +300,124,48923,2,0,L|392:120,1,90,0|0,0:0|0:0,0:0:0:0: +468,48,49252,1,0,1:0:0:0: +390,120,49417,2,0,P|390:164|406:208,1,90,8|0,0:0|0:0,0:0:0:0: +352,344,49747,6,0,P|352:300|336:256,1,90,4|0,1:2|0:0,0:0:0:0: +240,208,50076,1,8,0:0:0:0: +163,320,50241,2,0,P|207:324|252:316,1,90,0|0,1:0|0:0,0:0:0:0: +240,208,50571,1,0,1:0:0:0: +76,296,50736,2,0,P|76:340|92:384,1,90,8|0,0:0|0:0,0:0:0:0: +312,164,51065,6,0,P|236:124|160:184,1,180,4|8,1:2|0:0,0:0:0:0: +247,297,51560,2,0,L|240:208,1,90,0|0,0:0|0:0,0:0:0:0: +224,48,51890,1,0,1:0:0:0: +332,56,52054,2,0,L|366:58,5,30,8|0|0|0|0|0,0:0|0:0|0:0|0:0|0:0|0:0,0:0:0:0: +408,64,52384,6,0,P|420:108|416:156,1,90,0|0,1:0|0:0,0:0:0:0: +360,260,52714,1,8,0:0:0:0: +247,297,52879,2,0,B|203:281|159:297|159:297|115:313|71:297,1,180,0|0,1:0|1:0,0:0:0:0: +116,196,53373,1,8,0:0:0:0: +120,164,53456,1,0,0:0:0:0: +124,132,53538,1,0,0:0:0:0: +128,100,53620,1,0,0:0:0:0: +132,68,53703,5,4,1:2:0:0: +40,136,53868,1,0,0:0:0:0: +204,160,54032,2,0,L|304:152,1,90,8|0,0:0|0:0,0:0:0:0: +408,64,54362,1,0,0:0:0:0: +408,64,54445,1,0,0:0:0:0: +408,64,54527,2,0,P|404:112|416:160,1,90,0|8,1:0|0:0,0:0:0:0: +484,236,54857,1,0,0:0:0:0: +428,328,55021,5,0,1:0:0:0: +328,296,55186,1,0,0:0:0:0: +328,296,55269,1,0,0:0:0:0: +328,296,55351,1,8,0:0:0:0: +416,300,55516,1,0,1:0:0:0: +472,208,55681,1,0,0:0:0:0: +316,268,55846,1,0,1:0:0:0: +460,180,56010,1,8,0:0:0:0: +304,240,56175,1,0,0:0:0:0: +404,272,56340,5,0,1:0:0:0: +448,152,56505,1,0,0:0:0:0: +448,152,56587,1,0,0:0:0:0: +448,152,56670,2,0,P|456:112|448:60,1,90,8|0,0:0|0:0,0:0:0:0: +268,28,56999,2,0,P|260:68|268:120,1,90,0|0,0:0|1:0,0:0:0:0: +404,272,57329,2,0,P|444:280|496:272,2,90,8|0|0,0:0|0:0|1:0,0:0:0:0: +304,240,57824,5,0,0:0:0:0: +252,336,57988,1,8,0:0:0:0: +196,244,58153,1,0,1:0:0:0: +24,256,58318,1,0,0:0:0:0: +116,200,58483,1,0,1:0:0:0: +136,60,58648,1,8,0:0:0:0: +192,152,58813,1,0,0:0:0:0: +304,240,58977,6,0,P|348:252|396:248,1,90,0|0,1:0|0:0,0:0:0:0: +456,116,59307,2,0,P|412:104|364:108,1,90,8|0,0:0|0:0,0:0:0:0: +273,161,59637,1,0,0:0:0:0: +136,60,59802,1,0,1:0:0:0: +192,152,59966,1,8,0:0:0:0: +23,177,60131,1,0,0:0:0:0: +129,203,60296,5,0,1:0:0:0: +88,304,60461,2,0,P|132:311|176:303,1,90,0|8,0:0|0:0,0:0:0:0: +304,240,60791,1,0,1:0:0:0: +304,240,60873,1,0,0:0:0:0: +304,240,60956,2,0,L|312:288,3,45,0|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: +384,256,61285,2,0,L|392:304,3,45,8|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: +464,272,61615,5,2,1:2:0:0: +488,168,61780,1,2,0:0:0:0: +428,80,61945,1,10,0:0:0:0: +332,32,62109,2,0,P|288:28|240:36,1,90,2|0,0:0|0:0,0:0:0:0: +28,216,62439,1,2,1:2:0:0: +88,304,62604,1,10,0:0:0:0: +184,352,62769,2,0,P|228:356|276:348,1,90,2|0,0:0|1:0,0:0:0:0: +384,256,63098,6,0,P|409:219|426:174,1,90,2|8,0:0|0:0,0:0:0:0: +428,80,63428,2,0,L|420:36,2,45,2|0|0,1:2|0:0|0:0,0:0:0:0: +456,288,63758,1,2,1:2:0:0: +324,200,63923,1,10,1:2:0:0: +292,204,64005,1,0,1:0:0:0: +260,208,64087,1,2,1:2:0:0: +228,212,64170,1,0,1:0:0:0: +196,216,64252,5,4,1:2:0:0: +104,160,64417,1,0,0:0:0:0: +228,296,64582,2,0,L|320:284,1,90,8|0,0:0|0:0,0:0:0:0: +344,112,64912,1,0,0:0:0:0: +344,112,64994,1,0,0:0:0:0: +344,112,65076,2,0,L|254:123,1,90,0|8,1:0|0:0,0:0:0:0: +144,284,65406,2,0,P|148:328|176:364,1,90,0|0,0:0|1:0,0:0:0:0: +196,216,65736,5,0,0:0:0:0: +196,216,65818,1,0,0:0:0:0: +196,216,65901,2,0,P|155:198|110:205,1,90,8|0,0:0|1:0,0:0:0:0: +36,284,66230,1,0,0:0:0:0: +4,180,66395,1,0,1:0:0:0: +132,24,66560,1,8,0:0:0:0: +100,128,66725,1,0,0:0:0:0: +24,48,66890,5,0,1:0:0:0: +212,108,67054,1,0,0:0:0:0: +212,108,67137,1,0,0:0:0:0: +212,108,67219,2,0,L|300:92,1,90,8|0,0:0|0:0,0:0:0:0: +472,144,67549,2,0,L|384:160,1,90,0|0,0:0|1:0,0:0:0:0: +196,216,67879,2,0,P|240:216|288:240,1,90,8|0,0:0|0:0,0:0:0:0: +324,336,68208,5,0,1:0:0:0: +144,288,68373,1,0,0:0:0:0: +58,170,68538,1,8,0:0:0:0: +196,215,68703,1,0,1:0:0:0: +58,260,68868,1,0,0:0:0:0: +144,142,69032,2,0,L|138:108,2,30,0|0|0,1:0|0:0|0:0,0:0:0:0: +144,142,69197,2,0,P|184:124|232:132,1,90,8|0,0:0|0:0,0:0:0:0: +312,248,69527,6,0,L|324:338,1,90,0|0,1:0|0:0,0:0:0:0: +436,248,69857,1,8,0:0:0:0: +432,216,69939,1,0,0:0:0:0: +428,184,70021,1,0,0:0:0:0: +328,120,70186,1,0,0:0:0:0: +324,152,70269,1,0,0:0:0:0: +320,184,70351,1,0,1:0:0:0: +316,216,70434,1,0,0:0:0:0: +312,248,70516,2,0,L|320:300,1,45,8|0,0:0|0:0,0:0:0:0: +244,340,70681,2,0,L|237:295,1,45,0|0,0:0|0:0,0:0:0:0: +216,224,70846,6,0,P|168:216|124:224,1,90,0|0,1:0|0:0,0:0:0:0: +40,288,71175,1,8,0:0:0:0: +2,95,71340,2,0,P|-4:139|4:184,1,90,0|0,1:0|0:0,0:0:0:0: +164,304,71670,1,0,1:0:0:0: +312,248,71835,1,8,0:0:0:0: +244,340,71999,1,0,0:0:0:0: +216,224,72164,6,0,L|228:132,1,90,0|0,1:0|0:0,0:0:0:0: +332,148,72494,2,0,L|344:56,1,90,8|0,0:0|0:0,0:0:0:0: +312,248,72824,1,0,0:0:0:0: +164,304,72988,1,0,1:0:0:0: +332,336,73153,1,8,0:0:0:0: +360,324,73236,1,0,0:0:0:0: +384,304,73318,1,0,0:0:0:0: +399,276,73401,1,0,0:0:0:0: +403,244,73483,6,0,L|396:200,3,45,4|0|2|0,1:2|0:0|0:0|1:0,0:0:0:0: +420,112,73813,2,0,L|427:68,3,45,2|0|2|0,1:2|0:0|1:2|0:0,0:0:0:0: +352,16,74142,2,0,L|345:60,3,45,0|0|2|0,0:0|1:0|1:2|0:0,0:0:0:0: +332,148,74472,1,2,1:2:0:0: +332,148,74554,1,0,1:0:0:0: +332,148,74637,1,2,1:2:0:0: +332,148,74719,1,0,1:0:0:0: +332,148,74802,6,0,P|360:216|320:312,1,180,4|2,1:2|0:3,0:0:0:0: +190,310,75296,2,0,P|151:231|180:148,1,180,4|0,1:2|0:0,0:0:0:0: +256,56,75791,1,0,0:0:0:0: +332,148,75956,1,2,0:3:0:0: +179,148,76120,5,4,1:2:0:0: +336,64,76285,1,4,1:2:0:0: +256,224,76450,1,2,0:3:0:0: +176,64,76615,1,4,1:2:0:0: +256,140,76780,2,0,L|256:324,1,180,2|0,0:0|0:0,0:0:0:0: +364,300,77274,1,2,0:3:0:0: +148,300,77439,6,0,P|104:316|76:356,1,90,4|0,1:2|0:0,0:0:0:0: +24,252,77769,2,0,L|16:208,3,45,8|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: +96,212,78098,2,0,L|104:168,3,45,0|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: +32,128,78428,2,0,L|24:84,3,45,8|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: +104,88,78758,5,2,1:2:0:0: +204,132,78923,1,0,0:0:0:0: +236,124,79005,1,0,0:0:0:0: +268,116,79087,2,0,L|280:68,3,45,8|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: +348,100,79417,2,0,L|360:52,3,45,0|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: +428,84,79747,1,8,1:2:0:0: +460,76,79829,1,0,1:0:0:0: +492,68,79912,1,0,1:0:0:0: +492,260,80076,6,0,P|400:248|328:296,1,180,4|2,1:2|0:3,0:0:0:0: +144,236,80571,2,0,P|236:248|308:200,1,180,4|0,1:2|0:0,0:0:0:0: +348,100,81065,2,0,P|348:56|336:8,1,90,0|2,0:0|0:3,0:0:0:0: +140,48,81395,5,4,1:2:0:0: +244,68,81560,1,4,1:2:0:0: +144,236,81725,1,2,0:3:0:0: +176,133,81890,1,4,1:2:0:0: +184,304,82054,2,0,P|100:300|68:220,1,180,2|0,0:0|0:0,0:0:0:0: +100,116,82549,1,2,0:3:0:0: +264,244,82714,6,0,L|272:340,1,90,4|0,1:2|0:0,0:0:0:0: +380,316,83043,1,8,0:0:0:0: +396,288,83126,1,0,0:0:0:0: +400,256,83208,1,0,0:0:0:0: +396,224,83291,1,0,0:0:0:0: +380,196,83373,2,0,L|336:176,3,45,0|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: +272,148,83703,1,8,0:0:0:0: +256,120,83785,1,0,0:0:0:0: +252,88,83868,1,0,0:0:0:0: +256,56,83950,1,0,0:0:0:0: +272,28,84032,6,0,L|316:8,3,45,2|0|0|0,1:2|0:0|0:0|0:0,0:0:0:0: +360,72,84362,2,0,L|408:72,3,45,8|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: +421,149,84692,2,0,L|464:169,3,45,2|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: +443,244,85021,2,0,L|473:281,3,45,8|0|0|0,1:2|1:0|0:0|0:0,0:0:0:0: +422,339,85351,6,0,L|240:348,1,180,4|2,1:2|0:3,0:0:0:0: +76,172,85846,2,0,L|255:163,1,180,4|0,1:2|0:0,0:0:0:0: +421,149,86340,2,0,P|435:107|428:56,1,90,0|2,0:0|0:3,0:0:0:0: +228,56,86670,5,4,1:2:0:0: +280,192,86835,1,4,1:2:0:0: +328,96,86999,1,2,0:3:0:0: +180,152,87164,1,4,1:2:0:0: +28,100,87330,2,0,P|16:56|20:8,1,90,2|0,0:0|0:0,0:0:0:0: +0,180,87659,1,0,0:0:0:0: +28,284,87824,1,2,0:3:0:0: +108,352,87988,6,0,P|152:360|196:356,1,90,4|0,1:2|0:0,0:0:0:0: +276,284,88318,1,8,0:0:0:0: +304,272,88401,1,0,0:0:0:0: +336,268,88483,1,0,0:0:0:0: +368,272,88565,1,0,0:0:0:0: +396,284,88648,2,0,L|432:312,1,45,0|0,0:0|0:0,0:0:0:0: +488,252,88813,2,0,L|452:224,1,45,0|0,1:0|0:0,0:0:0:0: +400,164,88977,2,0,L|396:116,3,45,8|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: +316,64,89307,6,0,L|320:160,1,90,2|0,1:2|0:0,0:0:0:0: +276,284,89637,1,8,0:0:0:0: +248,296,89719,1,0,0:0:0:0: +216,300,89802,1,0,1:0:0:0: +184,296,89884,1,0,0:0:0:0: +156,284,89966,2,0,L|120:256,1,45,0|0,0:0|0:0,0:0:0:0: +176,200,90131,2,0,L|140:172,1,45,0|0,1:0|0:0,0:0:0:0: +196,116,90296,2,0,L|160:88,3,45,8|0|0|0,1:2|1:0|1:0|0:0,0:0:0:0: +92,44,90626,6,0,P|48:44|24:160,1,180,4|2,1:2|0:3,0:0:0:0: +156,284,91120,2,0,B|200:300|244:284|244:284|288:268|332:284,1,180,4|0,1:2|0:0,0:0:0:0: +176,200,91615,2,0,P|176:156|196:116,1,90,0|2,0:0|0:3,0:0:0:0: +264,28,91945,6,0,L|353:39,1,90,4|0,1:2|1:0,0:0:0:0: +453,159,92274,2,0,L|364:148,1,90,2|4,0:3|1:2,0:0:0:0: +268,196,92604,2,0,P|260:268|328:348,1,180,2|0,0:0|0:0,0:0:0:0: +364,248,93098,1,2,0:3:0:0: +176,200,93263,5,4,1:2:0:0: +72,228,93428,1,0,1:0:0:0: +152,92,93593,1,0,1:0:0:0: +256,64,93758,1,0,1:0:0:0: +336,200,93923,5,0,1:0:0:0: +440,228,94087,1,0,1:0:0:0: +360,92,94252,1,0,1:0:0:0: +256,64,94417,1,0,1:0:0:0: +176,200,94582,5,2,1:2:0:0: +168,228,94664,1,0,1:0:0:0: +168,260,94747,1,0,1:0:0:0: +172,292,94829,1,0,1:0:0:0: +192,316,94912,1,0,1:0:0:0: +220,328,94994,1,0,1:0:0:0: +252,332,95076,1,0,1:0:0:0: +280,320,95159,1,0,1:0:0:0: +300,296,95241,2,0,L|308:248,3,45,2|0|0|0,1:2|1:0|1:0|1:0,0:0:0:0: +312,172,95571,2,0,L|304:127,3,45,0|0|0|0,1:0|1:0|1:0|1:0,0:0:0:0: +256,64,95901,6,0,P|208:56|164:60,1,90,4|0,1:2|0:0,0:0:0:0: +76,116,96230,1,8,0:0:0:0: +60,224,96395,1,0,0:0:0:0: +60,224,96477,1,0,0:0:0:0: +160,184,96642,1,0,0:0:0:0: +160,184,96725,1,0,1:0:0:0: +63,26,96890,2,0,L|76:116,1,90,8|0,0:0|0:0,0:0:0:0: +136,272,97219,5,0,1:0:0:0: +168,268,97302,1,0,0:0:0:0: +200,264,97384,1,0,0:0:0:0: +232,260,97466,1,0,0:0:0:0: +264,256,97549,1,8,0:0:0:0: +384,136,97714,1,0,1:0:0:0: +376,168,97796,1,0,0:0:0:0: +380,200,97879,1,0,0:0:0:0: +392,228,97961,1,0,0:0:0:0: +416,248,98043,2,0,P|464:260|512:260,2,90,0|8|0,1:0|0:0|0:0,0:0:0:0: +231,105,98538,6,0,L|188:116,2,45,0|0|0,1:0|0:0|0:0,0:0:0:0: +376,56,98868,2,0,L|420:64,1,45,8|0,0:0|0:0,0:0:0:0: +384,136,99032,1,0,0:0:0:0: +384,136,99115,2,0,P|340:128|304:92,1,90,0|0,0:0|0:0,0:0:0:0: +303,18,99362,2,0,L|207:26,2,90,0|8|0,1:0|0:0|0:0,0:0:0:0: +452,88,99857,5,0,1:0:0:0: +465,116,99939,1,0,0:0:0:0: +466,147,100021,1,0,0:0:0:0: +456,177,100104,1,0,0:0:0:0: +436,201,100186,2,0,P|416:213|389:216,3,45,8|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: +320,188,100516,2,0,P|300:176|273:173,3,45,0|0|0|0,0:0|1:0|1:0|0:0,0:0:0:0: +204,200,100846,2,0,P|192:220|189:247,3,45,8|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: +188,320,101175,6,0,P|143:322|100:310,1,90,0|0,1:0|0:0,0:0:0:0: +76,292,101423,1,0,0:0:0:0: +76,292,101505,1,8,0:0:0:0: +76,292,101587,2,0,L|72:248,1,45 +12,68,101835,2,0,L|6:24,2,45,0|0|0,0:0|0:0|1:0,0:0:0:0: +104,140,102164,2,0,L|171:132,3,45,8|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: +224,124,102494,6,0,P|236:164|232:216,1,90,0|0,1:0|0:0,0:0:0:0: +288,296,102824,1,8,0:0:0:0: +288,296,102906,1,0,0:0:0:0: +288,296,102988,2,0,P|328:284|380:288,1,90,0|0,1:0|0:0,0:0:0:0: +404,304,103236,1,0,0:0:0:0: +424,328,103318,1,0,1:0:0:0: +448,188,103483,2,0,L|440:140,3,45,8|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: +424,72,103813,5,0,1:0:0:0: +324,112,103977,1,0,0:0:0:0: +324,112,104060,1,0,0:0:0:0: +324,112,104142,2,0,P|280:116|232:104,1,90,8|0,0:0|0:0,0:0:0:0: +160,28,104472,1,0,0:0:0:0: +216,208,104637,1,0,1:0:0:0: +216,208,104719,1,0,0:0:0:0: +216,208,104802,1,8,0:0:0:0: +352,240,104966,1,0,0:0:0:0: +384,244,105049,1,0,0:0:0:0: +416,248,105131,6,0,L|460:240,4,45,0|0|0|0|8,1:0|0:0|0:0|0:0|0:0,0:0:0:0: +272,288,105626,1,0,1:0:0:0: +264,320,105708,1,0,0:0:0:0: +256,352,105791,2,0,L|204:356,5,30,0|0|0|0|0|0,0:0|0:0|0:0|1:0|0:0|0:0,0:0:0:0: +156,332,106120,2,0,L|104:336,5,30,8|0|0|0|0|0,0:0|0:0|0:0|1:0|0:0|0:0,0:0:0:0: +56,312,106450,5,4,1:2:0:0: +4,188,106615,1,0,0:0:0:0: +168,220,106780,2,0,P|127:232|79:228,1,90,8|0,0:0|0:0,0:0:0:0: +112,124,107109,1,0,0:0:0:0: +272,216,107274,2,0,L|264:316,1,90,0|8,1:0|0:0,0:0:0:0: +400,268,107604,1,0,0:0:0:0: +428,132,107769,5,0,1:0:0:0: +428,132,107851,1,0,0:0:0:0: +428,132,107934,1,0,0:0:0:0: +428,132,108016,1,0,0:0:0:0: +428,132,108098,1,8,0:0:0:0: +332,84,108263,2,0,P|288:80|232:88,1,90,0|0,1:0|0:0,0:0:0:0: +112,124,108593,1,0,1:0:0:0: +148,264,108758,1,8,0:0:0:0: +16,236,108923,1,0,0:0:0:0: +264,126,109087,6,0,L|272:216,1,90,0|0,1:0|0:0,0:0:0:0: +452,224,109417,2,0,L|460:320,1,90,8|0,0:0|0:0,0:0:0:0: +360,232,109747,1,0,0:0:0:0: +348,56,109912,1,0,1:0:0:0: +416,140,110076,1,8,0:0:0:0: +256,112,110241,2,0,P|212:120|160:112,1,90,0|0,0:0|1:0,0:0:0:0: +348,56,110571,6,0,L|331:150,1,90,0|8,0:0|0:0,0:0:0:0: +208,328,110901,2,0,L|191:239,1,90,0|0,1:0|0:0,0:0:0:0: +184,216,111148,1,0,1:0:0:0: +178,194,111230,1,0,1:0:0:0: +68,272,111395,1,8,0:0:0:0: +56,136,111560,1,0,1:0:0:0: +178,194,111725,6,0,P|219:203|267:199,1,90,4|0,1:2|0:0,0:0:0:0: +364,148,112054,1,8,0:0:0:0: +384,256,112219,2,0,P|406:291|443:322,1,90,0|0,0:0|0:0,0:0:0:0: +488,224,112549,1,0,1:0:0:0: +304,232,112714,2,0,L|208:224,2,90,8|0|0,0:0|0:0|1:0,0:0:0:0: +208,328,113208,6,0,L|112:320,1,90,0|8,0:0|0:0,0:0:0:0: +26,184,113538,2,0,L|116:192,1,90,0|0,1:0|0:0,0:0:0:0: +304,232,113868,1,0,1:0:0:0: +116,192,114032,1,8,0:0:0:0: +224,132,114197,1,0,0:0:0:0: +208,328,114362,6,0,B|272:360|320:312|320:312|340:368,1,180,4|8,1:2|0:0,0:0:0:0: +304,232,114857,2,0,P|300:184|308:140,1,90,0|0,0:0|0:0,0:0:0:0: +384,64,115186,1,0,1:0:0:0: +307,143,115351,1,8,0:0:0:0: +256,48,115516,1,0,0:0:0:0: +456,24,115681,6,0,B|482:101|420:136|420:136|440:184,1,180,4|8,1:2|0:0,0:0:0:0: +384,64,116175,2,0,P|340:56|296:64,1,90,0|0,1:0|0:0,0:0:0:0: +211,171,116505,1,0,1:0:0:0: +439,181,116670,2,0,L|448:84,1,90,8|0,0:0|0:0,0:0:0:0: +372,296,116999,6,2,L|304:292,1,67.5000025749208,2|0,0:1|0:0,0:0:0:0: +136,252,117329,6,2,P|196:260|212:172,1,168.75,0|0,0:0|0:0,0:0:0:0: +192,148,117659,1,2,0:3:0:0: +164,132,117741,1,2,0:3:0:0: +132,124,117824,1,2,1:3:0:0: +100,132,117906,1,2,0:3:0:0: +72,148,117988,2,0,L|52:56,1,90,2|8,0:3|0:0,0:0:0:0: +36,244,118318,5,0,1:0:0:0: +76,344,118483,1,0,1:0:0:0: +184,352,118648,1,0,1:0:0:0: +244,264,118813,1,0,1:0:0:0: +244,264,118895,1,0,1:0:0:0: +244,264,118977,2,0,L|288:260,3,45,2|0|2|0,1:2|0:0|0:0|0:0,0:0:0:0: +332,328,119307,2,0,L|376:324,3,45,2|0|2|0,1:2|0:0|0:0|0:0,0:0:0:0: +412,252,119637,5,4,1:2:0:0: +256,192,119719,12,0,122274,0:0:0:0: +256,192,140735,6,0,L|228:156,1,45,4|0,1:2|0:0,0:0:0:0: +152,132,141065,2,0,P|129:129|104:136,1,45 +48,192,141395,2,0,P|40:236|52:280,1,90,8|8,0:0|0:0,0:0:0:0: +196,352,142054,6,0,L|308:340,1,90,8|8,0:0|1:2,0:0:0:0: +336,280,142549,1,0,0:0:0:0: +404,324,142713,1,8,0:0:0:0: +404,324,142878,1,8,0:0:0:0: +292,120,143373,5,0,1:0:0:0: +212,104,143538,1,0,0:0:0:0: +140,140,143702,1,0,0:0:0:0: +120,220,143867,1,0,0:0:0:0: +144,296,144032,2,0,P|184:320|228:316,1,90,10|8,0:0|0:0,0:0:0:0: +372,212,144691,6,0,P|327:209|290:232,1,90,10|8,0:0|1:2,0:0:0:0: +348,288,145186,1,0,0:0:0:0: +452,220,145351,1,10,0:0:0:0: +452,220,145516,1,8,0:0:0:0: +328,36,146010,5,2,1:2:0:0: +264,88,146175,1,0,0:0:0:0: +184,108,146340,1,0,0:0:0:0: +104,88,146505,1,0,0:0:0:0: +44,36,146669,1,8,0:0:0:0: +44,36,146999,1,8,0:0:0:0: +44,36,147329,6,0,L|24:84,1,45,8|0,0:0|0:0,0:0:0:0: +52,156,147658,2,0,L|71:204,1,45,8|0,1:2|0:0,0:0:0:0: +144,236,147988,1,8,0:0:0:0: +144,236,148153,1,8,0:0:0:0: +316,64,148647,5,0,1:0:0:0: +380,116,148812,1,0,0:0:0:0: +408,192,148977,1,0,0:0:0:0: +380,268,149142,1,0,0:0:0:0: +316,320,149307,2,0,L|224:316,1,90,10|8,0:0|0:0,0:0:0:0: +64,248,149966,5,10,0:0:0:0: +144,236,150131,1,0,0:0:0:0: +188,168,150296,1,8,1:2:0:0: +192,88,150461,1,0,0:0:0:0: +140,24,150626,2,0,P|120:16|96:20,1,45,10|0,0:0|0:0,0:0:0:0: +260,132,150955,2,0,P|280:140|304:136,1,45,2|0,0:0|0:0,0:0:0:0: +476,48,151285,6,0,L|484:160,1,112.5,4|0,1:2|0:0,0:0:0:0: +464,236,151779,1,0,0:0:0:0: +436,308,151944,2,0,P|380:320|324:308,1,112.5,8|8,0:0|0:0,0:0:0:0: +76,308,152604,6,0,P|132:320|188:308,1,112.5,8|8,0:0|1:2,0:0:0:0: +256,88,153263,1,8,0:0:0:0: +256,168,153428,1,8,0:0:0:0: +256,168,153922,5,4,1:2:0:0: +256,248,154087,1,0,0:0:0:0: +324,128,154252,1,0,0:0:0:0: +188,128,154417,1,0,0:0:0:0: +332,212,154582,2,0,L|388:204,1,56.25,10|0,0:0|0:0,0:0:0:0: +492,152,154911,2,0,L|436:144,1,56.25,8|0,0:0|0:0,0:0:0:0: +324,128,155241,5,10,0:0:0:0: +180,212,155406,1,0,0:0:0:0: +332,212,155571,1,8,1:2:0:0: +188,128,155735,1,0,0:0:0:0: +256,248,155900,1,10,0:0:0:0: +256,248,156065,2,0,L|256:304,2,56.25,0|0|0,0:0|0:0|0:0,0:0:0:0: +180,212,156560,6,0,L|124:204,1,56.25,4|0,1:2|0:0,0:0:0:0: +20,152,156889,2,0,L|76:144,1,56.25,0|0,0:0|0:0,0:0:0:0: +188,128,157219,2,0,P|212:72|192:16,1,112.5,8|8,0:0|0:0,0:0:0:0: +132,72,157713,1,0,0:0:0:0: +180,212,157878,6,0,L|236:208,1,56.25,8|0,0:0|0:0,0:0:0:0: +360,252,158208,2,8,L|304:248,1,56.25,8|0,1:2|0:0,0:0:0:0: +168,292,158538,2,0,L|160:356,2,56.25,8|8|0,0:0|0:0|0:0,0:0:0:0: +180,212,159032,1,0,0:0:0:0: +144,140,159197,6,0,P|104:128|36:148,1,112.5,2|0,1:2|0:0,0:0:0:0: +12,220,159691,1,0,0:0:0:0: +36,296,159856,2,0,P|60:316|92:324,1,56.25,8|0,0:0|0:0,0:0:0:0: +215,264,160186,2,0,P|189:273|168:292,1,56.25,8|0,0:0|0:0,0:0:0:0: +228,344,160516,6,0,L|284:340,1,56.25,10|0,0:0|0:0,0:0:0:0: +328,276,160845,2,0,L|384:272,1,56.25,8|0,1:2|0:0,0:0:0:0: +428,208,161175,1,8,0:0:0:0: +440,128,161340,1,8,0:0:0:0: +400,60,161505,1,2,0:0:0:0: +328,28,161669,1,0,0:0:0:0: +212,76,161834,6,0,P|200:120|208:164,1,90,2|0,1:2|1:0,0:0:0:0: +300,308,162163,2,0,P|312:264|304:220,1,90,2|0,1:2|1:0,0:0:0:0: +140,236,162493,2,0,P|184:248|228:240,1,90,2|0,1:2|1:0,0:0:0:0: +372,148,162823,2,0,P|328:136|284:144,1,90,2|0,1:2|1:0,0:0:0:0: +104,316,163152,5,2,1:2:0:0: +78,297,163235,1,0,1:0:0:0: +60,270,163317,1,0,1:0:0:0: +54,239,163399,1,0,1:0:0:0: +58,207,163482,1,2,1:2:0:0: +74,180,163564,1,0,1:0:0:0: +98,159,163647,1,0,1:0:0:0: +127,149,163729,1,0,1:0:0:0: +158,150,163812,2,0,L|208:160,1,45,2|0,1:2|1:0,0:0:0:0: +344,184,163976,2,0,L|294:194,1,45,0|0,1:0|1:0,0:0:0:0: +140,236,164141,1,4,1:2:0:0: +140,236,164471,6,0,L|232:252,1,90,4|0,1:2|0:0,0:0:0:0: +344,184,164801,1,8,0:0:0:0: +380,284,164965,1,0,0:0:0:0: +368,104,165130,2,0,P|324:104|284:128,1,90,0|0,0:0|1:0,0:0:0:0: +356,360,165460,2,0,P|400:360|440:336,1,90,8|0,0:0|0:0,0:0:0:0: +432,208,165790,5,0,1:0:0:0: +292,260,165954,1,0,0:0:0:0: +344,184,166119,1,8,0:0:0:0: +204,236,166284,1,0,1:0:0:0: +204,236,166366,1,0,0:0:0:0: +204,236,166449,2,0,L|216:328,1,90,0|0,0:0|1:0,0:0:0:0: +120,208,166779,2,0,L|131:118,1,90,8|0,0:0|0:0,0:0:0:0: +204,236,167108,5,0,1:0:0:0: +32,216,167273,1,0,0:0:0:0: +130,118,167438,1,8,0:0:0:0: +110,298,167603,1,0,0:0:0:0: +110,298,167685,1,0,0:0:0:0: +110,298,167768,2,0,L|121:208,1,90,0|0,0:0|1:0,0:0:0:0: +304,40,168097,2,0,L|315:130,1,90,8|0,0:0|0:0,0:0:0:0: +328,236,168427,5,0,1:0:0:0: +184,148,168592,1,0,0:0:0:0: +314,129,168757,1,8,0:0:0:0: +197,254,168921,1,0,1:0:0:0: +197,254,169004,1,0,0:0:0:0: +197,254,169086,2,0,P|220:292|260:312,1,90,0|0,0:0|1:0,0:0:0:0: +409,210,169416,2,0,P|365:211|328:236,1,90,8|0,0:0|0:0,0:0:0:0: +488,232,169746,6,0,P|487:192|464:149,1,90,0|0,1:0|0:0,0:0:0:0: +314,129,170075,1,8,0:0:0:0: +409,210,170240,1,0,0:0:0:0: +332,40,170405,2,0,L|240:36,1,90,0|0,0:0|1:0,0:0:0:0: +68,144,170735,2,0,L|157:140,1,90,8|0,0:0|0:0,0:0:0:0: +314,129,171064,5,0,1:0:0:0: +332,40,171229,1,0,0:0:0:0: +324,216,171394,1,8,0:0:0:0: +306,305,171559,1,0,1:0:0:0: +257,178,171724,1,0,0:0:0:0: +168,160,171888,1,0,1:0:0:0: +384,164,172053,1,8,0:0:0:0: +473,182,172218,1,0,0:0:0:0: +306,305,172383,6,0,L|216:312,1,90,0|0,1:0|0:0,0:0:0:0: +60,172,172713,1,8,0:0:0:0: +120,260,172877,1,0,0:0:0:0: +168,160,173042,2,0,L|172:68,1,90,0|0,0:0|1:0,0:0:0:0: +309,216,173372,2,0,L|306:306,1,90,8|0,0:0|0:0,0:0:0:0: +120,260,173702,5,0,1:0:0:0: +152,256,173784,1,0,1:0:0:0: +184,252,173866,1,0,1:0:0:0: +309,216,174031,1,8,0:0:0:0: +103,168,174196,1,0,1:0:0:0: +135,164,174279,1,0,1:0:0:0: +167,160,174361,1,0,1:0:0:0: +292,124,174526,1,0,1:0:0:0: +87,76,174691,1,8,1:2:0:0: +119,72,174773,1,0,1:0:0:0: +151,68,174855,1,0,1:0:0:0: +276,32,175020,6,0,L|368:40,1,90,0|0,1:0|0:0,0:0:0:0: +448,108,175350,1,8,0:0:0:0: +292,124,175515,1,0,0:0:0:0: +292,124,175597,1,0,0:0:0:0: +292,124,175680,2,0,L|308:216,1,90,0|0,0:0|1:0,0:0:0:0: +328,320,176009,1,8,0:0:0:0: +408,248,176174,1,0,0:0:0:0: +220,300,176339,6,0,P|176:304|128:292,1,90,0|0,1:0|0:0,0:0:0:0: +16,120,176669,1,8,0:0:0:0: +120,152,176834,1,0,1:0:0:0: +120,152,176916,1,0,0:0:0:0: +120,152,176998,2,0,L|124:200,1,45 +212,176,177163,2,0,L|239:215,1,45,0|0,1:0|0:0,0:0:0:0: +292,124,177328,2,0,P|302:79|283:30,1,90,8|0,0:0|0:0,0:0:0:0: +344,192,177658,6,0,P|372:156|376:104,1,90,0|0,1:0|0:0,0:0:0:0: +212,88,177987,1,8,0:0:0:0: +272,228,178152,1,0,0:0:0:0: +272,228,178235,1,0,0:0:0:0: +272,228,178317,1,0,0:0:0:0: +292,124,178482,1,0,1:0:0:0: +180,180,178647,1,8,0:0:0:0: +200,284,178812,1,0,0:0:0:0: +292,124,178976,5,0,1:0:0:0: +288,92,179059,1,0,0:0:0:0: +280,60,179141,2,0,P|248:24|208:14,1,90,0|8,0:0|0:0,0:0:0:0: +22,65,179471,2,0,P|67:71|112:68,1,90,0|0,1:0|0:0,0:0:0:0: +212,88,179801,1,0,1:0:0:0: +22,65,179965,1,8,0:0:0:0: +180,180,180130,5,0,0:0:0:0: +180,180,180213,1,0,0:0:0:0: +180,180,180295,2,0,P|184:224|172:272,1,90,0|0,1:0|0:0,0:0:0:0: +76,216,180625,2,0,P|72:172|84:124,1,90,8|0,0:0|0:0,0:0:0:0: +380,240,180954,2,0,P|384:284|372:332,1,90,0|0,0:0|1:0,0:0:0:0: +276,276,181284,2,0,P|272:232|284:184,1,90,8|0,0:0|0:0,0:0:0:0: +374,129,181614,5,0,1:0:0:0: +300,352,181779,2,0,L|204:348,2,90,0|8|0,0:0|0:0|1:0,0:0:0:0: +448,180,182273,1,2,0:0:0:0: +448,180,182438,1,2,1:2:0:0: +276,276,182603,1,10,0:0:0:0: +276,276,182768,1,2,0:0:0:0: +96,200,182932,6,0,L|88:108,1,90,0|0,1:0|0:0,0:0:0:0: +96,200,183262,1,8,0:0:0:0: +12,68,183427,2,0,P|72:24|164:68,1,180,0|0,0:0|1:0,0:0:0:0: +140,272,183921,2,0,P|92:284|52:271,1,90,8|0,0:0|0:0,0:0:0:0: +176,156,184251,5,0,1:0:0:0: +208,152,184334,1,0,1:0:0:0: +240,148,184416,1,0,1:0:0:0: +308,64,184581,1,8,0:0:0:0: +296,240,184746,1,0,1:0:0:0: +312,268,184828,1,0,1:0:0:0: +336,284,184910,1,0,1:0:0:0: +368,292,184993,1,0,1:0:0:0: +400,288,185075,1,0,1:0:0:0: +464,184,185240,1,8,0:0:0:0: +468,152,185323,1,0,0:0:0:0: +472,120,185405,2,0,L|464:76,1,45,0|0,1:0|1:0,0:0:0:0: +388,96,185570,6,0,P|360:132|316:148,1,90,4|0,1:2|0:0,0:0:0:0: +224,46,185899,2,0,P|268:43|308:63,1,90,8|0,0:0|0:0,0:0:0:0: +296,240,186229,1,0,0:0:0:0: +308,64,186394,1,0,1:0:0:0: +296,240,186559,2,0,L|312:332,1,90,8|0,0:0|0:0,0:0:0:0: +464,184,186888,6,0,P|420:180|372:188,1,90,0|0,1:0|0:0,0:0:0:0: +296,240,187218,1,8,0:0:0:0: +136,292,187383,2,0,P|94:277|54:249,1,90,0|0,1:0|0:0,0:0:0:0: +21,159,187713,1,0,1:0:0:0: +104,8,187877,2,0,L|124:96,1,90,10|0,0:0|0:0,0:0:0:0: +124,96,188207,6,0,P|152:132|196:148,1,90,0|0,1:0|0:0,0:0:0:0: +287,46,188537,2,0,P|243:43|204:63,1,90,8|0,0:0|0:0,0:0:0:0: +216,240,188866,1,2,0:0:0:0: +204,64,189031,1,0,1:0:0:0: +216,240,189196,2,0,L|200:332,1,90,8|0,0:0|0:0,0:0:0:0: +40,240,189526,5,2,1:2:0:0: +128,192,189691,1,0,0:0:0:0: +216,240,189855,1,8,0:0:0:0: +304,192,190020,1,0,1:0:0:0: +392,240,190185,2,0,L|400:332,1,90,2|0,0:0|1:0,0:0:0:0: +464,168,190515,2,0,L|456:76,1,90,8|0,0:0|0:0,0:0:0:0: +392,240,190844,6,0,P|364:272|312:292,1,90,2|0,1:2|0:0,0:0:0:0: +220,140,191174,2,0,P|248:108|296:92,1,90,8|0,0:0|0:0,0:0:0:0: +324,96,191421,1,0,0:0:0:0: +356,104,191504,2,0,L|340:16,1,90,0|0,0:0|1:0,0:0:0:0: +256,276,191834,2,0,L|272:364,1,90,8|0,0:0|0:0,0:0:0:0: +392,240,192163,5,0,1:0:0:0: +356,104,192328,1,0,0:0:0:0: +220,140,192493,1,8,0:0:0:0: +256,276,192658,1,0,1:0:0:0: +305,191,192823,1,0,0:0:0:0: +212,56,192987,1,0,1:0:0:0: +200,220,193152,1,10,0:0:0:0: +200,220,193482,6,0,P|156:228|108:220,1,90,0|0,1:0|0:0,0:0:0:0: +88,116,193812,1,8,0:0:0:0: +16,192,193976,1,0,0:0:0:0: +16,192,194059,1,0,0:0:0:0: +16,192,194141,2,0,L|28:288,1,90,2|0,0:0|1:0,0:0:0:0: +188,309,194471,2,0,L|200:220,1,90,8|0,0:0|0:0,0:0:0:0: +216,112,194801,5,2,1:2:0:0: +216,112,194883,1,0,1:0:0:0: +216,112,194965,1,0,1:0:0:0: +361,25,195130,1,8,0:0:0:0: +294,180,195295,1,0,1:0:0:0: +294,180,195377,1,0,1:0:0:0: +294,180,195460,1,2,0:0:0:0: +256,16,195625,1,0,1:0:0:0: +384,127,195790,1,10,1:2:0:0: +416,132,195872,1,0,1:0:0:0: +448,140,195954,2,0,L|452:84,1,45,0|0,1:0|1:0,0:0:0:0: +416,216,196119,6,0,P|412:264|432:312,1,90,4|0,1:2|0:0,0:0:0:0: +304,268,196449,2,0,P|308:220|288:172,1,90,8|0,0:0|0:0,0:0:0:0: +216,112,196779,2,0,L|120:104,1,90,0|0,0:0|1:0,0:0:0:0: +52,248,197108,2,0,L|141:255,1,90,8|0,0:0|0:0,0:0:0:0: +304,268,197438,5,0,1:0:0:0: +416,216,197603,1,0,0:0:0:0: +408,340,197768,1,8,0:0:0:0: +332,180,197932,1,0,1:0:0:0: +332,180,198015,1,0,0:0:0:0: +332,180,198097,2,0,P|360:140|400:120,1,90,0|0,0:0|1:0,0:0:0:0: +484,284,198427,1,10,0:0:0:0: +304,268,198592,1,2,0:0:0:0: +416,216,198757,6,0,P|428:172|420:124,1,90,2|0,1:2|0:0,0:0:0:0: +344,52,199086,1,8,0:0:0:0: +332,180,199251,1,0,0:0:0:0: +164,236,199416,2,0,P|152:192|160:144,1,90,0|0,0:0|1:0,0:0:0:0: +236,72,199746,1,8,0:0:0:0: +248,200,199910,1,0,0:0:0:0: +156,328,200075,6,0,L|56:320,1,90,2|0,1:2|0:0,0:0:0:0: +164,236,200405,1,8,0:0:0:0: +256,292,200570,2,0,P|300:296|344:284,1,90,0|0,1:0|0:0,0:0:0:0: +432,220,200899,2,0,L|460:308,2,90,0|8|0,1:0|0:0|0:0,0:0:0:0: +392,120,201394,5,4,1:2:0:0: +396,32,201559,1,0,1:0:0:0: +316,72,201724,1,0,1:0:0:0: +256,6,201888,1,0,1:0:0:0: +228,91,202053,1,0,1:0:0:0: +139,87,202218,1,0,1:0:0:0: +179,166,202383,1,0,1:0:0:0: +113,226,202548,1,0,1:0:0:0: +197,253,202713,5,4,1:2:0:0: +193,342,202877,1,0,1:0:0:0: +272,302,203042,1,0,1:0:0:0: +332,367,203207,1,0,1:0:0:0: +359,283,203372,1,2,1:2:0:0: +448,287,203537,1,2,1:2:0:0: +407,208,203702,1,2,1:2:0:0: +472,147,203866,1,2,1:2:0:0: +387,121,204031,5,4,1:2:0:0: +360,100,204114,1,0,1:0:0:0: +344,72,204196,1,0,1:0:0:0: +336,40,204279,1,0,1:0:0:0: +340,8,204361,1,0,1:0:0:0: +316,28,204443,1,0,1:0:0:0: +284,32,204526,1,0,1:0:0:0: +252,28,204608,1,0,1:0:0:0: +228,8,204691,2,0,L|184:20,7,45,4|0|0|0|0|0|0|0,1:2|1:0|1:0|1:0|1:0|1:0|1:0|1:0,0:0:0:0: +112,56,205350,5,4,1:2:0:0: +100,84,205432,1,0,1:0:0:0: +96,116,205515,1,0,1:0:0:0: +100,148,205597,1,0,1:0:0:0: +112,176,205680,1,0,1:0:0:0: +124,204,205762,1,0,1:0:0:0: +128,236,205844,1,0,1:0:0:0: +124,268,205927,1,0,1:0:0:0: +112,296,206009,2,0,L|71:313,3,45,2|0|2|0,1:2|0:0|0:0|0:0,0:0:0:0: +192,312,206339,2,0,L|175:353,3,45,2|0|2|0,1:2|0:0|0:0|0:0,0:0:0:0: +256,264,206669,5,4,1:2:0:0: +256,192,206751,12,0,209306,0:0:0:0: diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 3cd425ea44..24843f8c32 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -290,8 +290,12 @@ namespace osu.Game.Beatmaps.Formats string[] split = line.Split(','); EventType type; + if (!Enum.TryParse(split[0], out type)) - throw new InvalidDataException($@"Unknown event type {split[0]}"); + { + Logger.Log($"A beatmap event could not be parsed and will be ignored: {split[0]}", LoggingTarget.Runtime, LogLevel.Important); + return; + } switch (type) { diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index f6e2bf6966..1dcafb4669 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -10,6 +10,7 @@ using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.IO.File; +using osu.Framework.Logging; using osu.Game.Storyboards; namespace osu.Game.Beatmaps.Formats @@ -83,7 +84,7 @@ namespace osu.Game.Beatmaps.Formats EventType type; if (!Enum.TryParse(split[0], out type)) - throw new InvalidDataException($@"Unknown event type {split[0]}"); + Logger.Log($"A storyboard event could not be parsed and will be ignored: {split[0]}", LoggingTarget.Runtime, LogLevel.Important); switch (type) { From a5c17ae26d81b778c2b8e87f2c1c074d7bf72267 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 6 Aug 2019 10:14:36 +0900 Subject: [PATCH 2190/5608] Don't use GetDecoder --- osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 98464b8d91..7e0374023e 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -486,12 +486,13 @@ namespace osu.Game.Tests.Beatmaps.Formats [Test] public void TestDecodeInvalidEvents() { + var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + using (var normalResStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var normalStream = new StreamReader(normalResStream)) using (var resStream = TestResources.OpenResource("invalid-events.osu")) using (var stream = new StreamReader(resStream)) { - var decoder = Decoder.GetDecoder(stream); var goodBeatmap = decoder.Decode(normalStream); Beatmap badBeatmap = null; From 1fc7ddf621611e9d773fb5b0df218d8a18992681 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 5 Aug 2019 18:14:41 -0700 Subject: [PATCH 2191/5608] Fix text depth regression --- osu.Game/Screens/Select/FooterButton.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index 90bc902ad8..15088f0eb3 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -67,16 +67,6 @@ namespace osu.Game.Screens.Select Shear = SHEARING; Children = new Drawable[] { - TextContainer = new Container - { - Size = new Vector2(100 - SHEAR_WIDTH, 50), - Shear = -SHEARING, - Child = SpriteText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } - }, box = new Box { RelativeSizeAxes = Axes.Both, @@ -90,6 +80,16 @@ namespace osu.Game.Screens.Select EdgeSmoothness = new Vector2(2, 0), RelativeSizeAxes = Axes.X, }, + TextContainer = new Container + { + Size = new Vector2(100 - SHEAR_WIDTH, 50), + Shear = -SHEARING, + Child = SpriteText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }, }; } From b8c38d4dfd5ba9a8cd3acc70ab0f0fcda7495cb7 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 6 Aug 2019 10:36:26 +0900 Subject: [PATCH 2192/5608] remove unnecessary assert --- osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 7e0374023e..bbc3b05d89 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -494,9 +494,8 @@ namespace osu.Game.Tests.Beatmaps.Formats using (var stream = new StreamReader(resStream)) { var goodBeatmap = decoder.Decode(normalStream); - Beatmap badBeatmap = null; + var badBeatmap = decoder.Decode(stream); - Assert.DoesNotThrow(() => badBeatmap = decoder.Decode(stream)); Assert.AreEqual(goodBeatmap.HitObjects.Count, badBeatmap.HitObjects.Count); } } From 2c32d886d7cf77e7615ebe93a7afadb00b1d81ef Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 6 Aug 2019 10:39:54 +0900 Subject: [PATCH 2193/5608] Add better asserts --- osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index bbc3b05d89..e88c3c8ecc 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -496,6 +496,8 @@ namespace osu.Game.Tests.Beatmaps.Formats var goodBeatmap = decoder.Decode(normalStream); var badBeatmap = decoder.Decode(stream); + Assert.AreEqual(goodBeatmap.Breaks[0].Duration, badBeatmap.Breaks[0].Duration); + Assert.AreEqual(goodBeatmap.Metadata.BackgroundFile, badBeatmap.Metadata.BackgroundFile); Assert.AreEqual(goodBeatmap.HitObjects.Count, badBeatmap.HitObjects.Count); } } From 66b02c02831a2004c53b755d0159fea08c9bf2ad Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 6 Aug 2019 12:27:10 +0900 Subject: [PATCH 2194/5608] log type as well --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 24843f8c32..c92c0ba22d 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -293,7 +293,7 @@ namespace osu.Game.Beatmaps.Formats if (!Enum.TryParse(split[0], out type)) { - Logger.Log($"A beatmap event could not be parsed and will be ignored: {split[0]}", LoggingTarget.Runtime, LogLevel.Important); + Logger.Log($"A beatmap {type} event could not be parsed and will be ignored: {split[0]}", LoggingTarget.Runtime, LogLevel.Important); return; } diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 1dcafb4669..512eea0822 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -84,7 +84,7 @@ namespace osu.Game.Beatmaps.Formats EventType type; if (!Enum.TryParse(split[0], out type)) - Logger.Log($"A storyboard event could not be parsed and will be ignored: {split[0]}", LoggingTarget.Runtime, LogLevel.Important); + Logger.Log($"A storyboard {type} event could not be parsed and will be ignored: {split[0]}", LoggingTarget.Runtime, LogLevel.Important); switch (type) { From 497d2cb67784287c5217fe0c5279bfab7748bab7 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 6 Aug 2019 12:35:18 +0900 Subject: [PATCH 2195/5608] shorten tests and rename --- .../Formats/LegacyBeatmapDecoderTest.cs | 13 +- osu.Game.Tests/Resources/invalid-events.osu | 992 +----------------- osu.Game.Tests/Resources/valid-events.osu | 12 + 3 files changed, 19 insertions(+), 998 deletions(-) create mode 100644 osu.Game.Tests/Resources/valid-events.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index e88c3c8ecc..49a6f646ba 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -488,17 +488,16 @@ namespace osu.Game.Tests.Beatmaps.Formats { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; - using (var normalResStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) - using (var normalStream = new StreamReader(normalResStream)) - using (var resStream = TestResources.OpenResource("invalid-events.osu")) - using (var stream = new StreamReader(resStream)) + using (var goodResStream = TestResources.OpenResource("valid-events.osu")) + using (var goodStream = new StreamReader(goodResStream)) + using (var badResStream = TestResources.OpenResource("invalid-events.osu")) + using (var badStream = new StreamReader(badResStream)) { - var goodBeatmap = decoder.Decode(normalStream); - var badBeatmap = decoder.Decode(stream); + var goodBeatmap = decoder.Decode(goodStream); + var badBeatmap = decoder.Decode(badStream); Assert.AreEqual(goodBeatmap.Breaks[0].Duration, badBeatmap.Breaks[0].Duration); Assert.AreEqual(goodBeatmap.Metadata.BackgroundFile, badBeatmap.Metadata.BackgroundFile); - Assert.AreEqual(goodBeatmap.HitObjects.Count, badBeatmap.HitObjects.Count); } } } diff --git a/osu.Game.Tests/Resources/invalid-events.osu b/osu.Game.Tests/Resources/invalid-events.osu index a8e767585c..df86b26dba 100644 --- a/osu.Game.Tests/Resources/invalid-events.osu +++ b/osu.Game.Tests/Resources/invalid-events.osu @@ -1,43 +1,5 @@ osu file format v14 -[General] -AudioFilename: 03. Renatus - Soleily 192kbps.mp3 -AudioLeadIn: 0 -PreviewTime: 164471 -Countdown: 0 -SampleSet: Soft -StackLeniency: 0.7 -Mode: 0 -LetterboxInBreaks: 0 -WidescreenStoryboard: 0 - -[Editor] -Bookmarks: 11505,22054,32604,43153,53703,64252,74802,85351,95901,106450,116999,119637,130186,140735,151285,161834,164471,175020,185570,196119,206669,209306 -DistanceSpacing: 1.8 -BeatDivisor: 4 -GridSize: 4 -TimelineZoom: 2 - -[Metadata] -Title:Renatus -TitleUnicode:Renatus -Artist:Soleily -ArtistUnicode:Soleily -Creator:Gamu -Version:Insane -Source: -Tags:MBC7 Unisphere 地球ヤバイEP Chikyu Yabai -BeatmapID:557821 -BeatmapSetID:241526 - -[Difficulty] -HPDrainRate:6.5 -CircleSize:4 -OverallDifficulty:8 -ApproachRate:9 -SliderMultiplier:1.8 -SliderTickRate:2 - [Events] bad,event,this,should,fail //Background and Video events @@ -45,960 +7,8 @@ bad,event,this,should,fail //Break Periods 2,122474,140135 //Storyboard Layer 0 (Background) +this,is,also,bad //Storyboard Layer 1 (Fail) //Storyboard Layer 2 (Pass) //Storyboard Layer 3 (Foreground) //Storyboard Sound Samples - -[TimingPoints] -956,329.67032967033,4,2,0,60,1,0 -20736,-100,4,2,0,65,0,0 -22054,-100,4,2,0,70,0,0 -43153,-100,4,2,0,60,0,0 -48428,-100,4,2,0,50,0,0 -52879,-100,4,2,0,50,0,0 -53373,-100,4,2,0,60,0,0 -53703,-100,4,2,0,70,0,1 -74719,-100,4,2,0,70,0,0 -74802,-100,4,2,0,70,0,1 -95901,-100,4,2,0,70,0,0 -116999,-133.333333333333,4,2,0,50,0,0 -117164,-133.333333333333,4,2,0,30,0,0 -117329,-79.9999999999999,4,2,0,50,0,0 -117659,-100,4,2,0,50,0,0 -118977,-100,4,2,0,60,0,0 -119307,-100,4,2,0,70,0,0 -119637,659.340659340659,4,2,0,80,1,0 -119966,-100,4,2,0,70,0,0 -120296,-100,4,2,0,60,0,0 -120626,-100,4,2,0,50,0,0 -120955,-100,4,2,0,40,0,0 -121285,-100,4,2,0,30,0,0 -121615,-100,4,2,0,20,0,0 -121944,-100,4,2,0,10,0,0 -122274,-100,4,2,0,5,0,0 -140735,-100,4,2,0,50,0,0 -151285,-80,4,2,0,60,0,0 -161834,329.67032967033,4,2,0,65,1,0 -164141,-100,4,2,0,70,0,0 -164471,-100,4,2,0,70,0,1 -185487,-100,4,2,0,70,0,0 -185570,-100,4,2,0,70,0,1 -206669,659.340659340659,4,2,0,80,1,0 -206998,-100,4,2,0,70,0,0 -207328,-100,4,2,0,60,0,0 -207658,-100,4,2,0,50,0,0 -207987,-100,4,2,0,40,0,0 -208317,-100,4,2,0,30,0,0 -208647,-100,4,2,0,20,0,0 -208976,-100,4,2,0,10,0,0 -209306,-100,4,2,0,5,0,0 - - -[Colours] -Combo1 : 142,199,255 -Combo2 : 255,128,128 -Combo3 : 128,255,255 -Combo4 : 128,255,128 -Combo5 : 255,187,255 -Combo6 : 255,177,140 -Combo7 : 100,100,100,100 - -[HitObjects] -192,168,956,6,0,P|184:128|200:80,1,90,4|0,1:2|0:0,0:0:0:0: -304,56,1285,1,8,0:0:0:0: -244,236,1450,2,0,P|204:252|156:244,1,90,2|0,0:0|0:0,0:0:0:0: -276,156,1780,2,0,P|310:181|329:226,1,90,2|8,1:2|0:0,0:0:0:0: -300,328,2109,1,2,0:0:0:0: -192,332,2274,6,0,L|144:340,2,45,0|0|0,1:0|0:0|0:0,0:0:0:0: -388,300,2604,1,8,0:0:0:0: -244,236,2769,1,0,1:0:0:0: -232,208,2851,1,0,0:0:0:0: -224,176,2934,1,0,0:0:0:0: -228,144,3016,1,0,0:0:0:0: -244,116,3098,1,0,1:0:0:0: -332,52,3263,2,0,P|376:48|424:56,1,90,8|0,0:0|0:0,0:0:0:0: -488,228,3593,5,0,1:0:0:0: -460,240,3675,1,0,0:0:0:0: -428,236,3758,1,0,0:0:0:0: -292,160,3923,2,0,P|288:204|300:252,1,90,8|0,0:0|0:0,0:0:0:0: -316,276,4170,1,0,0:0:0:0: -344,292,4252,2,0,L|388:300,1,45,0|0,0:0|0:0,0:0:0:0: -288,356,4417,2,0,L|244:364,1,45,0|0,1:0|0:0,0:0:0:0: -168,328,4582,2,0,P|124:324|72:332,1,90,8|0,0:0|0:0,0:0:0:0: -24,188,4912,5,0,1:0:0:0: -56,192,4994,1,0,0:0:0:0: -88,196,5076,1,0,0:0:0:0: -148,108,5241,1,8,0:0:0:0: -188,240,5406,1,0,1:0:0:0: -188,240,5488,1,0,0:0:0:0: -188,240,5571,2,0,L|168:328,1,90,0|0,0:0|1:0,0:0:0:0: -260,216,5901,2,0,P|236:180|188:164,1,90,8|0,0:0|0:0,0:0:0:0: -248,296,6230,6,0,L|348:292,1,90,0|0,1:0|0:0,0:0:0:0: -504,232,6560,1,8,0:0:0:0: -400,204,6725,1,0,0:0:0:0: -392,176,6807,1,0,0:0:0:0: -384,144,6890,1,0,0:0:0:0: -376,116,6972,1,0,0:0:0:0: -368,88,7054,1,0,1:0:0:0: -188,48,7219,2,0,L|208:140,1,90,8|0,0:0|0:0,0:0:0:0: -248,296,7549,5,0,1:0:0:0: -207,135,7714,1,0,0:0:0:0: -156,232,7879,1,8,0:0:0:0: -316,191,8043,1,0,1:0:0:0: -316,191,8126,1,0,0:0:0:0: -316,191,8208,2,0,L|372:200,1,45,0|0,0:0|0:0,0:0:0:0: -492,200,8373,2,0,L|447:207,1,45,0|0,1:0|0:0,0:0:0:0: -408,136,8538,2,0,P|396:92|400:48,1,90,8|0,0:0|0:0,0:0:0:0: -260,32,8868,5,0,1:0:0:0: -252,64,8950,1,0,0:0:0:0: -236,92,9032,2,0,P|204:116|148:128,1,90,0|8,0:0|0:0,0:0:0:0: -28,188,9362,1,0,0:0:0:0: -60,196,9445,1,0,0:0:0:0: -88,212,9527,2,0,P|112:244|124:300,1,90,0|0,0:0|1:0,0:0:0:0: -112,128,9857,2,0,P|152:156|184:196,1,90,8|0,0:0|0:0,0:0:0:0: -216,288,10186,5,0,1:0:0:0: -216,288,10269,1,0,0:0:0:0: -216,288,10351,1,0,0:0:0:0: -268,192,10516,1,8,0:0:0:0: -356,128,10681,1,0,1:0:0:0: -388,120,10763,1,0,0:0:0:0: -420,128,10846,2,0,P|440:168|436:220,1,90,0|0,0:0|1:0,0:0:0:0: -332,328,11175,2,0,L|280:332,1,45,8|8,0:0|0:0,0:0:0:0: -216,288,11340,2,0,L|164:292,1,45,0|0,1:0|0:0,1:0:0:0: -100,248,11505,5,4,1:2:0:0: -148,116,11670,1,2,0:0:0:0: -268,192,11835,1,10,0:0:0:0: -136,328,11999,2,0,L|44:336,1,90,2|0,0:0|0:0,0:0:0:0: -216,288,12329,1,2,1:2:0:0: -148,116,12494,1,10,0:0:0:0: -100,248,12659,1,2,0:0:0:0: -268,192,12824,5,0,1:0:0:0: -268,192,12906,1,0,0:0:0:0: -268,192,12988,1,0,0:0:0:0: -340,272,13153,2,0,P|384:276|432:264,1,90,8|0,0:0|1:0,0:0:0:0: -452,244,13401,1,0,0:0:0:0: -468,216,13483,2,0,L|476:124,1,90,0|0,0:0|1:0,0:0:0:0: -368,32,13813,2,0,L|360:121,1,90,8|0,0:0|0:0,0:0:0:0: -340,272,14142,6,0,L|316:316,2,45,0|0|0,1:0|0:0|0:0,0:0:0:0: -452,244,14472,1,8,0:0:0:0: -268,192,14637,1,0,0:0:0:0: -236,188,14719,1,0,0:0:0:0: -204,192,14802,2,0,P|172:228|160:272,1,90,0|0,0:0|1:0,0:0:0:0: -128,140,15131,2,0,P|160:104|172:60,1,90,8|0,0:0|0:0,0:0:0:0: -64,52,15461,6,0,L|20:68,2,45,0|0|0,1:0|0:0|0:0,0:0:0:0: -171,64,15791,1,8,0:0:0:0: -264,8,15956,2,0,L|356:12,1,90,0|0,1:0|0:0,0:0:0:0: -452,56,16285,1,0,1:0:0:0: -296,140,16450,2,0,L|206:136,1,90,8|0,0:0|0:0,0:0:0:0: -108,184,16780,6,0,P|92:224|96:272,1,90,0|0,1:0|0:0,0:0:0:0: -200,244,17109,1,8,0:0:0:0: -108,108,17274,2,0,L|12:116,1,90,0|0,0:0|0:0,0:0:0:0: -200,244,17604,1,0,1:0:0:0: -296,140,17769,2,0,L|385:132,1,90,8|0,0:0|0:0,0:0:0:0: -480,184,18098,5,0,1:0:0:0: -488,216,18181,1,0,0:0:0:0: -496,248,18263,2,0,L|492:340,1,90,0|8,0:0|0:0,0:0:0:0: -404,224,18593,2,0,L|396:176,2,45,0|0|0,1:0|0:0|0:0,0:0:0:0: -304,264,18923,1,0,1:0:0:0: -200,244,19087,2,0,P|156:240|108:248,1,90,8|0,0:0|0:0,0:0:0:0: -296,140,19417,6,0,P|340:144|388:136,1,90,0|0,1:0|0:0,0:0:0:0: -440,44,19747,1,8,0:0:0:0: -404,224,19912,1,0,0:0:0:0: -404,224,19994,1,0,0:0:0:0: -404,224,20076,2,0,L|412:320,1,90,0|0,0:0|1:0,0:0:0:0: -200,244,20406,2,0,L|192:154,1,90,8|0,0:0|0:0,0:0:0:0: -184,44,20736,5,4,1:2:0:0: -152,40,20818,1,0,0:0:0:0: -120,48,20901,1,0,0:0:0:0: -96,68,20983,1,0,0:0:0:0: -76,92,21065,1,2,0:3:0:0: -64,120,21148,1,0,0:0:0:0: -60,152,21230,1,0,1:0:0:0: -64,184,21313,1,0,0:0:0:0: -76,212,21395,2,0,L|96:252,3,45,0|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: -144,316,21725,2,0,L|188:324,3,45,0|0|2|0,0:0|0:0|0:3|0:0,0:0:0:0: -268,340,22054,6,0,L|364:336,1,90,4|0,1:2|0:0,0:0:0:0: -452,280,22384,1,8,0:0:0:0: -512,188,22549,2,0,P|516:144|504:96,1,90,2|0,0:0|0:0,0:0:0:0: -340,24,22879,2,0,P|336:68|348:116,1,90,2|8,1:2|0:0,0:0:0:0: -420,192,23208,1,2,0:0:0:0: -328,252,23373,6,0,L|232:240,1,90,0|0,1:0|0:0,0:0:0:0: -64,256,23703,1,8,0:0:0:0: -144,184,23868,2,0,P|148:140|136:88,1,90,0|0,1:0|0:0,0:0:0:0: -40,52,24197,1,2,1:2:0:0: -139,95,24362,1,8,0:0:0:0: -216,20,24527,1,0,0:0:0:0: -315,63,24692,6,0,P|360:72|408:68,1,90,2|0,1:2|0:0,0:0:0:0: -492,132,25021,1,8,0:0:0:0: -412,204,25186,2,0,P|403:249|407:297,1,90,2|0,0:0|0:0,0:0:0:0: -268,328,25516,2,0,P|277:283|273:235,1,90,2|8,1:2|0:0,0:0:0:0: -232,140,25846,2,0,P|187:131|139:135,1,90,2|0,0:0|1:0,0:0:0:0: -64,208,26175,5,2,0:0:0:0: -44,316,26340,1,8,0:0:0:0: -148,280,26505,1,2,1:2:0:0: -456,208,26835,1,2,1:2:0:0: -476,316,26999,1,10,0:0:0:0: -372,280,27164,1,2,0:0:0:0: -356,172,27329,6,0,L|380:80,1,90,0|0,1:0|0:0,0:0:0:0: -456,208,27659,1,8,0:0:0:0: -300,236,27824,1,2,0:0:0:0: -300,236,27906,1,0,0:0:0:0: -300,236,27988,2,0,L|208:228,1,90,0|2,0:0|1:2,0:0:0:0: -140,312,28318,1,8,0:0:0:0: -372,280,28483,2,0,L|464:272,1,90,2|0,0:0|1:0,0:0:0:0: -500,136,28813,5,2,0:0:0:0: -432,56,28977,1,8,0:0:0:0: -328,24,29142,2,0,P|284:24|236:28,1,90,2|0,1:2|0:0,0:0:0:0: -80,144,29472,1,2,1:2:0:0: -116,44,29637,1,10,0:0:0:0: -184,128,29802,1,2,0:0:0:0: -20,88,29966,6,0,P|1:164|73:227,1,180,2|10,1:2|0:0,0:0:0:0: -184,128,30461,2,0,P|227:120|276:124,1,90,2|0,0:0|0:0,0:0:0:0: -392,188,30791,1,2,1:2:0:0: -272,260,30956,1,8,0:0:0:0: -396,328,31120,1,0,0:0:0:0: -256,348,31285,5,2,1:2:0:0: -224,344,31368,1,0,1:0:0:0: -192,340,31450,2,0,L|172:248,1,90,2|0,1:2|1:0,0:0:0:0: -8,136,31780,2,0,L|27:223,1,90,2|0,1:2|0:0,0:0:0:0: -56,328,32109,1,2,1:2:0:0: -108,192,32274,1,2,1:2:0:0: -100,160,32357,1,0,1:0:0:0: -92,132,32439,1,2,1:2:0:0: -84,104,32521,1,0,1:0:0:0: -76,72,32604,6,0,P|100:112|148:136,1,90,4|0,1:2|0:0,0:0:0:0: -240,168,32934,1,8,0:0:0:0: -336,124,33098,2,0,L|344:80,2,45,2|0|0,0:0|0:0|0:0,0:0:0:0: -264,248,33428,2,0,P|220:248|176:220,1,90,2|8,1:2|0:0,0:0:0:0: -260,84,33758,1,2,0:0:0:0: -344,212,33923,5,0,1:0:0:0: -344,212,34005,1,0,0:0:0:0: -344,212,34087,1,0,0:0:0:0: -440,160,34252,1,8,0:0:0:0: -312,320,34417,2,0,P|272:336|220:324,1,90,0|0,1:0|0:0,0:0:0:0: -156,176,34747,2,0,P|196:160|248:172,2,90,2|8|0,1:2|0:0|0:0,0:0:0:0: -132,280,35241,5,2,1:2:0:0: -132,280,35324,1,0,0:0:0:0: -132,280,35406,2,0,L|120:376,1,90,0|8,0:0|0:0,0:0:0:0: -312,320,35736,2,0,L|300:230,1,90,2|0,0:0|0:0,0:0:0:0: -316,124,36065,1,2,1:2:0:0: -400,192,36230,1,8,0:0:0:0: -300,230,36395,2,0,P|255:231|211:224,1,90,2|0,0:0|1:0,0:0:0:0: -24,132,36725,5,0,0:0:0:0: -132,152,36890,1,8,0:0:0:0: -60,232,37054,1,2,1:2:0:0: -60,232,37137,1,0,0:0:0:0: -60,232,37219,1,0,0:0:0:0: -92,56,37384,2,0,L|184:44,1,90,2|10,1:2|0:0,0:0:0:0: -316,124,37714,2,0,L|226:135,1,90,2|0,0:0|1:0,0:0:0:0: -60,232,38043,6,0,P|52:276|64:328,1,90,0|8,0:0|0:0,0:0:0:0: -220,152,38373,2,0,P|176:144|124:156,1,90,2|0,0:0|0:0,0:0:0:0: -176,252,38703,1,2,1:2:0:0: -323,213,38868,2,0,L|316:124,1,90,8|2,0:0|0:0,0:0:0:0: -332,320,39197,5,0,1:0:0:0: -424,260,39362,1,2,0:0:0:0: -260,272,39527,2,0,P|246:313|256:360,1,90,8|2,0:0|1:2,0:0:0:0: -408,336,39857,1,0,0:0:0:0: -176,252,40021,2,0,L|80:260,2,90,2|10|2,1:2|0:0|0:0,0:0:0:0: -324,212,40516,5,2,1:2:0:0: -324,212,40598,1,0,1:0:0:0: -324,212,40681,1,0,1:0:0:0: -200,336,40846,1,2,1:2:0:0: -236,188,41010,1,2,1:2:0:0: -236,188,41093,1,0,1:0:0:0: -236,188,41175,1,0,1:0:0:0: -281,357,41340,1,2,1:2:0:0: -176,252,41505,1,2,1:2:0:0: -176,252,41587,1,0,1:0:0:0: -176,252,41670,1,0,1:0:0:0: -344,297,41835,5,2,1:2:0:0: -432,232,41999,1,2,1:2:0:0: -444,204,42082,1,0,1:0:0:0: -448,172,42164,1,0,1:0:0:0: -444,140,42247,1,0,1:0:0:0: -432,112,42329,2,0,L|440:64,2,45,2|0|0,1:2|1:0|1:0,0:0:0:0: -236,188,42659,1,0,0:0:0:0: -340,172,42824,1,2,0:3:0:0: -272,88,42988,1,0,0:0:0:0: -132,160,43153,6,0,P|148:248|220:296,1,180,4|8,1:2|0:0,0:0:0:0: -324,320,43648,2,0,L|336:364,2,45,0|0|0,0:0|0:0|0:0,0:0:0:0: -292,216,43977,1,0,1:0:0:0: -396,240,44142,2,0,P|440:244|488:232,1,90,8|0,0:0|0:0,0:0:0:0: -328,124,44472,6,0,P|284:120|236:132,1,90,0|0,1:0|0:0,0:0:0:0: -168,212,44802,1,8,0:0:0:0: -192,316,44966,1,0,1:0:0:0: -140,220,45131,1,0,0:0:0:0: -83,310,45296,1,0,1:0:0:0: -114,205,45461,1,8,0:0:0:0: -10,229,45626,1,0,0:0:0:0: -106,176,45791,6,0,P|113:133|108:85,1,90,0|0,1:0|0:0,0:0:0:0: -204,136,46120,1,8,0:0:0:0: -256,40,46285,1,0,0:0:0:0: -256,40,46368,1,0,0:0:0:0: -256,40,46450,2,0,L|356:44,1,90,0|0,0:0|1:0,0:0:0:0: -501,124,46780,2,0,L|412:128,1,90,8|0,0:0|0:0,0:0:0:0: -324,192,47109,5,0,1:0:0:0: -356,296,47274,1,0,0:0:0:0: -284,216,47439,1,8,0:0:0:0: -269,323,47604,1,0,1:0:0:0: -237,220,47769,1,0,0:0:0:0: -178,311,47934,1,0,1:0:0:0: -191,203,48098,1,8,0:0:0:0: -99,261,48263,1,0,0:0:0:0: -156,168,48428,6,0,B|176:112|136:64|136:64|200:96,1,180,4|8,1:2|0:0,0:0:0:0: -300,124,48923,2,0,L|392:120,1,90,0|0,0:0|0:0,0:0:0:0: -468,48,49252,1,0,1:0:0:0: -390,120,49417,2,0,P|390:164|406:208,1,90,8|0,0:0|0:0,0:0:0:0: -352,344,49747,6,0,P|352:300|336:256,1,90,4|0,1:2|0:0,0:0:0:0: -240,208,50076,1,8,0:0:0:0: -163,320,50241,2,0,P|207:324|252:316,1,90,0|0,1:0|0:0,0:0:0:0: -240,208,50571,1,0,1:0:0:0: -76,296,50736,2,0,P|76:340|92:384,1,90,8|0,0:0|0:0,0:0:0:0: -312,164,51065,6,0,P|236:124|160:184,1,180,4|8,1:2|0:0,0:0:0:0: -247,297,51560,2,0,L|240:208,1,90,0|0,0:0|0:0,0:0:0:0: -224,48,51890,1,0,1:0:0:0: -332,56,52054,2,0,L|366:58,5,30,8|0|0|0|0|0,0:0|0:0|0:0|0:0|0:0|0:0,0:0:0:0: -408,64,52384,6,0,P|420:108|416:156,1,90,0|0,1:0|0:0,0:0:0:0: -360,260,52714,1,8,0:0:0:0: -247,297,52879,2,0,B|203:281|159:297|159:297|115:313|71:297,1,180,0|0,1:0|1:0,0:0:0:0: -116,196,53373,1,8,0:0:0:0: -120,164,53456,1,0,0:0:0:0: -124,132,53538,1,0,0:0:0:0: -128,100,53620,1,0,0:0:0:0: -132,68,53703,5,4,1:2:0:0: -40,136,53868,1,0,0:0:0:0: -204,160,54032,2,0,L|304:152,1,90,8|0,0:0|0:0,0:0:0:0: -408,64,54362,1,0,0:0:0:0: -408,64,54445,1,0,0:0:0:0: -408,64,54527,2,0,P|404:112|416:160,1,90,0|8,1:0|0:0,0:0:0:0: -484,236,54857,1,0,0:0:0:0: -428,328,55021,5,0,1:0:0:0: -328,296,55186,1,0,0:0:0:0: -328,296,55269,1,0,0:0:0:0: -328,296,55351,1,8,0:0:0:0: -416,300,55516,1,0,1:0:0:0: -472,208,55681,1,0,0:0:0:0: -316,268,55846,1,0,1:0:0:0: -460,180,56010,1,8,0:0:0:0: -304,240,56175,1,0,0:0:0:0: -404,272,56340,5,0,1:0:0:0: -448,152,56505,1,0,0:0:0:0: -448,152,56587,1,0,0:0:0:0: -448,152,56670,2,0,P|456:112|448:60,1,90,8|0,0:0|0:0,0:0:0:0: -268,28,56999,2,0,P|260:68|268:120,1,90,0|0,0:0|1:0,0:0:0:0: -404,272,57329,2,0,P|444:280|496:272,2,90,8|0|0,0:0|0:0|1:0,0:0:0:0: -304,240,57824,5,0,0:0:0:0: -252,336,57988,1,8,0:0:0:0: -196,244,58153,1,0,1:0:0:0: -24,256,58318,1,0,0:0:0:0: -116,200,58483,1,0,1:0:0:0: -136,60,58648,1,8,0:0:0:0: -192,152,58813,1,0,0:0:0:0: -304,240,58977,6,0,P|348:252|396:248,1,90,0|0,1:0|0:0,0:0:0:0: -456,116,59307,2,0,P|412:104|364:108,1,90,8|0,0:0|0:0,0:0:0:0: -273,161,59637,1,0,0:0:0:0: -136,60,59802,1,0,1:0:0:0: -192,152,59966,1,8,0:0:0:0: -23,177,60131,1,0,0:0:0:0: -129,203,60296,5,0,1:0:0:0: -88,304,60461,2,0,P|132:311|176:303,1,90,0|8,0:0|0:0,0:0:0:0: -304,240,60791,1,0,1:0:0:0: -304,240,60873,1,0,0:0:0:0: -304,240,60956,2,0,L|312:288,3,45,0|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: -384,256,61285,2,0,L|392:304,3,45,8|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: -464,272,61615,5,2,1:2:0:0: -488,168,61780,1,2,0:0:0:0: -428,80,61945,1,10,0:0:0:0: -332,32,62109,2,0,P|288:28|240:36,1,90,2|0,0:0|0:0,0:0:0:0: -28,216,62439,1,2,1:2:0:0: -88,304,62604,1,10,0:0:0:0: -184,352,62769,2,0,P|228:356|276:348,1,90,2|0,0:0|1:0,0:0:0:0: -384,256,63098,6,0,P|409:219|426:174,1,90,2|8,0:0|0:0,0:0:0:0: -428,80,63428,2,0,L|420:36,2,45,2|0|0,1:2|0:0|0:0,0:0:0:0: -456,288,63758,1,2,1:2:0:0: -324,200,63923,1,10,1:2:0:0: -292,204,64005,1,0,1:0:0:0: -260,208,64087,1,2,1:2:0:0: -228,212,64170,1,0,1:0:0:0: -196,216,64252,5,4,1:2:0:0: -104,160,64417,1,0,0:0:0:0: -228,296,64582,2,0,L|320:284,1,90,8|0,0:0|0:0,0:0:0:0: -344,112,64912,1,0,0:0:0:0: -344,112,64994,1,0,0:0:0:0: -344,112,65076,2,0,L|254:123,1,90,0|8,1:0|0:0,0:0:0:0: -144,284,65406,2,0,P|148:328|176:364,1,90,0|0,0:0|1:0,0:0:0:0: -196,216,65736,5,0,0:0:0:0: -196,216,65818,1,0,0:0:0:0: -196,216,65901,2,0,P|155:198|110:205,1,90,8|0,0:0|1:0,0:0:0:0: -36,284,66230,1,0,0:0:0:0: -4,180,66395,1,0,1:0:0:0: -132,24,66560,1,8,0:0:0:0: -100,128,66725,1,0,0:0:0:0: -24,48,66890,5,0,1:0:0:0: -212,108,67054,1,0,0:0:0:0: -212,108,67137,1,0,0:0:0:0: -212,108,67219,2,0,L|300:92,1,90,8|0,0:0|0:0,0:0:0:0: -472,144,67549,2,0,L|384:160,1,90,0|0,0:0|1:0,0:0:0:0: -196,216,67879,2,0,P|240:216|288:240,1,90,8|0,0:0|0:0,0:0:0:0: -324,336,68208,5,0,1:0:0:0: -144,288,68373,1,0,0:0:0:0: -58,170,68538,1,8,0:0:0:0: -196,215,68703,1,0,1:0:0:0: -58,260,68868,1,0,0:0:0:0: -144,142,69032,2,0,L|138:108,2,30,0|0|0,1:0|0:0|0:0,0:0:0:0: -144,142,69197,2,0,P|184:124|232:132,1,90,8|0,0:0|0:0,0:0:0:0: -312,248,69527,6,0,L|324:338,1,90,0|0,1:0|0:0,0:0:0:0: -436,248,69857,1,8,0:0:0:0: -432,216,69939,1,0,0:0:0:0: -428,184,70021,1,0,0:0:0:0: -328,120,70186,1,0,0:0:0:0: -324,152,70269,1,0,0:0:0:0: -320,184,70351,1,0,1:0:0:0: -316,216,70434,1,0,0:0:0:0: -312,248,70516,2,0,L|320:300,1,45,8|0,0:0|0:0,0:0:0:0: -244,340,70681,2,0,L|237:295,1,45,0|0,0:0|0:0,0:0:0:0: -216,224,70846,6,0,P|168:216|124:224,1,90,0|0,1:0|0:0,0:0:0:0: -40,288,71175,1,8,0:0:0:0: -2,95,71340,2,0,P|-4:139|4:184,1,90,0|0,1:0|0:0,0:0:0:0: -164,304,71670,1,0,1:0:0:0: -312,248,71835,1,8,0:0:0:0: -244,340,71999,1,0,0:0:0:0: -216,224,72164,6,0,L|228:132,1,90,0|0,1:0|0:0,0:0:0:0: -332,148,72494,2,0,L|344:56,1,90,8|0,0:0|0:0,0:0:0:0: -312,248,72824,1,0,0:0:0:0: -164,304,72988,1,0,1:0:0:0: -332,336,73153,1,8,0:0:0:0: -360,324,73236,1,0,0:0:0:0: -384,304,73318,1,0,0:0:0:0: -399,276,73401,1,0,0:0:0:0: -403,244,73483,6,0,L|396:200,3,45,4|0|2|0,1:2|0:0|0:0|1:0,0:0:0:0: -420,112,73813,2,0,L|427:68,3,45,2|0|2|0,1:2|0:0|1:2|0:0,0:0:0:0: -352,16,74142,2,0,L|345:60,3,45,0|0|2|0,0:0|1:0|1:2|0:0,0:0:0:0: -332,148,74472,1,2,1:2:0:0: -332,148,74554,1,0,1:0:0:0: -332,148,74637,1,2,1:2:0:0: -332,148,74719,1,0,1:0:0:0: -332,148,74802,6,0,P|360:216|320:312,1,180,4|2,1:2|0:3,0:0:0:0: -190,310,75296,2,0,P|151:231|180:148,1,180,4|0,1:2|0:0,0:0:0:0: -256,56,75791,1,0,0:0:0:0: -332,148,75956,1,2,0:3:0:0: -179,148,76120,5,4,1:2:0:0: -336,64,76285,1,4,1:2:0:0: -256,224,76450,1,2,0:3:0:0: -176,64,76615,1,4,1:2:0:0: -256,140,76780,2,0,L|256:324,1,180,2|0,0:0|0:0,0:0:0:0: -364,300,77274,1,2,0:3:0:0: -148,300,77439,6,0,P|104:316|76:356,1,90,4|0,1:2|0:0,0:0:0:0: -24,252,77769,2,0,L|16:208,3,45,8|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: -96,212,78098,2,0,L|104:168,3,45,0|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: -32,128,78428,2,0,L|24:84,3,45,8|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: -104,88,78758,5,2,1:2:0:0: -204,132,78923,1,0,0:0:0:0: -236,124,79005,1,0,0:0:0:0: -268,116,79087,2,0,L|280:68,3,45,8|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: -348,100,79417,2,0,L|360:52,3,45,0|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: -428,84,79747,1,8,1:2:0:0: -460,76,79829,1,0,1:0:0:0: -492,68,79912,1,0,1:0:0:0: -492,260,80076,6,0,P|400:248|328:296,1,180,4|2,1:2|0:3,0:0:0:0: -144,236,80571,2,0,P|236:248|308:200,1,180,4|0,1:2|0:0,0:0:0:0: -348,100,81065,2,0,P|348:56|336:8,1,90,0|2,0:0|0:3,0:0:0:0: -140,48,81395,5,4,1:2:0:0: -244,68,81560,1,4,1:2:0:0: -144,236,81725,1,2,0:3:0:0: -176,133,81890,1,4,1:2:0:0: -184,304,82054,2,0,P|100:300|68:220,1,180,2|0,0:0|0:0,0:0:0:0: -100,116,82549,1,2,0:3:0:0: -264,244,82714,6,0,L|272:340,1,90,4|0,1:2|0:0,0:0:0:0: -380,316,83043,1,8,0:0:0:0: -396,288,83126,1,0,0:0:0:0: -400,256,83208,1,0,0:0:0:0: -396,224,83291,1,0,0:0:0:0: -380,196,83373,2,0,L|336:176,3,45,0|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: -272,148,83703,1,8,0:0:0:0: -256,120,83785,1,0,0:0:0:0: -252,88,83868,1,0,0:0:0:0: -256,56,83950,1,0,0:0:0:0: -272,28,84032,6,0,L|316:8,3,45,2|0|0|0,1:2|0:0|0:0|0:0,0:0:0:0: -360,72,84362,2,0,L|408:72,3,45,8|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: -421,149,84692,2,0,L|464:169,3,45,2|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: -443,244,85021,2,0,L|473:281,3,45,8|0|0|0,1:2|1:0|0:0|0:0,0:0:0:0: -422,339,85351,6,0,L|240:348,1,180,4|2,1:2|0:3,0:0:0:0: -76,172,85846,2,0,L|255:163,1,180,4|0,1:2|0:0,0:0:0:0: -421,149,86340,2,0,P|435:107|428:56,1,90,0|2,0:0|0:3,0:0:0:0: -228,56,86670,5,4,1:2:0:0: -280,192,86835,1,4,1:2:0:0: -328,96,86999,1,2,0:3:0:0: -180,152,87164,1,4,1:2:0:0: -28,100,87330,2,0,P|16:56|20:8,1,90,2|0,0:0|0:0,0:0:0:0: -0,180,87659,1,0,0:0:0:0: -28,284,87824,1,2,0:3:0:0: -108,352,87988,6,0,P|152:360|196:356,1,90,4|0,1:2|0:0,0:0:0:0: -276,284,88318,1,8,0:0:0:0: -304,272,88401,1,0,0:0:0:0: -336,268,88483,1,0,0:0:0:0: -368,272,88565,1,0,0:0:0:0: -396,284,88648,2,0,L|432:312,1,45,0|0,0:0|0:0,0:0:0:0: -488,252,88813,2,0,L|452:224,1,45,0|0,1:0|0:0,0:0:0:0: -400,164,88977,2,0,L|396:116,3,45,8|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: -316,64,89307,6,0,L|320:160,1,90,2|0,1:2|0:0,0:0:0:0: -276,284,89637,1,8,0:0:0:0: -248,296,89719,1,0,0:0:0:0: -216,300,89802,1,0,1:0:0:0: -184,296,89884,1,0,0:0:0:0: -156,284,89966,2,0,L|120:256,1,45,0|0,0:0|0:0,0:0:0:0: -176,200,90131,2,0,L|140:172,1,45,0|0,1:0|0:0,0:0:0:0: -196,116,90296,2,0,L|160:88,3,45,8|0|0|0,1:2|1:0|1:0|0:0,0:0:0:0: -92,44,90626,6,0,P|48:44|24:160,1,180,4|2,1:2|0:3,0:0:0:0: -156,284,91120,2,0,B|200:300|244:284|244:284|288:268|332:284,1,180,4|0,1:2|0:0,0:0:0:0: -176,200,91615,2,0,P|176:156|196:116,1,90,0|2,0:0|0:3,0:0:0:0: -264,28,91945,6,0,L|353:39,1,90,4|0,1:2|1:0,0:0:0:0: -453,159,92274,2,0,L|364:148,1,90,2|4,0:3|1:2,0:0:0:0: -268,196,92604,2,0,P|260:268|328:348,1,180,2|0,0:0|0:0,0:0:0:0: -364,248,93098,1,2,0:3:0:0: -176,200,93263,5,4,1:2:0:0: -72,228,93428,1,0,1:0:0:0: -152,92,93593,1,0,1:0:0:0: -256,64,93758,1,0,1:0:0:0: -336,200,93923,5,0,1:0:0:0: -440,228,94087,1,0,1:0:0:0: -360,92,94252,1,0,1:0:0:0: -256,64,94417,1,0,1:0:0:0: -176,200,94582,5,2,1:2:0:0: -168,228,94664,1,0,1:0:0:0: -168,260,94747,1,0,1:0:0:0: -172,292,94829,1,0,1:0:0:0: -192,316,94912,1,0,1:0:0:0: -220,328,94994,1,0,1:0:0:0: -252,332,95076,1,0,1:0:0:0: -280,320,95159,1,0,1:0:0:0: -300,296,95241,2,0,L|308:248,3,45,2|0|0|0,1:2|1:0|1:0|1:0,0:0:0:0: -312,172,95571,2,0,L|304:127,3,45,0|0|0|0,1:0|1:0|1:0|1:0,0:0:0:0: -256,64,95901,6,0,P|208:56|164:60,1,90,4|0,1:2|0:0,0:0:0:0: -76,116,96230,1,8,0:0:0:0: -60,224,96395,1,0,0:0:0:0: -60,224,96477,1,0,0:0:0:0: -160,184,96642,1,0,0:0:0:0: -160,184,96725,1,0,1:0:0:0: -63,26,96890,2,0,L|76:116,1,90,8|0,0:0|0:0,0:0:0:0: -136,272,97219,5,0,1:0:0:0: -168,268,97302,1,0,0:0:0:0: -200,264,97384,1,0,0:0:0:0: -232,260,97466,1,0,0:0:0:0: -264,256,97549,1,8,0:0:0:0: -384,136,97714,1,0,1:0:0:0: -376,168,97796,1,0,0:0:0:0: -380,200,97879,1,0,0:0:0:0: -392,228,97961,1,0,0:0:0:0: -416,248,98043,2,0,P|464:260|512:260,2,90,0|8|0,1:0|0:0|0:0,0:0:0:0: -231,105,98538,6,0,L|188:116,2,45,0|0|0,1:0|0:0|0:0,0:0:0:0: -376,56,98868,2,0,L|420:64,1,45,8|0,0:0|0:0,0:0:0:0: -384,136,99032,1,0,0:0:0:0: -384,136,99115,2,0,P|340:128|304:92,1,90,0|0,0:0|0:0,0:0:0:0: -303,18,99362,2,0,L|207:26,2,90,0|8|0,1:0|0:0|0:0,0:0:0:0: -452,88,99857,5,0,1:0:0:0: -465,116,99939,1,0,0:0:0:0: -466,147,100021,1,0,0:0:0:0: -456,177,100104,1,0,0:0:0:0: -436,201,100186,2,0,P|416:213|389:216,3,45,8|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: -320,188,100516,2,0,P|300:176|273:173,3,45,0|0|0|0,0:0|1:0|1:0|0:0,0:0:0:0: -204,200,100846,2,0,P|192:220|189:247,3,45,8|0|0|0,0:0|0:0|1:0|0:0,0:0:0:0: -188,320,101175,6,0,P|143:322|100:310,1,90,0|0,1:0|0:0,0:0:0:0: -76,292,101423,1,0,0:0:0:0: -76,292,101505,1,8,0:0:0:0: -76,292,101587,2,0,L|72:248,1,45 -12,68,101835,2,0,L|6:24,2,45,0|0|0,0:0|0:0|1:0,0:0:0:0: -104,140,102164,2,0,L|171:132,3,45,8|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: -224,124,102494,6,0,P|236:164|232:216,1,90,0|0,1:0|0:0,0:0:0:0: -288,296,102824,1,8,0:0:0:0: -288,296,102906,1,0,0:0:0:0: -288,296,102988,2,0,P|328:284|380:288,1,90,0|0,1:0|0:0,0:0:0:0: -404,304,103236,1,0,0:0:0:0: -424,328,103318,1,0,1:0:0:0: -448,188,103483,2,0,L|440:140,3,45,8|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0: -424,72,103813,5,0,1:0:0:0: -324,112,103977,1,0,0:0:0:0: -324,112,104060,1,0,0:0:0:0: -324,112,104142,2,0,P|280:116|232:104,1,90,8|0,0:0|0:0,0:0:0:0: -160,28,104472,1,0,0:0:0:0: -216,208,104637,1,0,1:0:0:0: -216,208,104719,1,0,0:0:0:0: -216,208,104802,1,8,0:0:0:0: -352,240,104966,1,0,0:0:0:0: -384,244,105049,1,0,0:0:0:0: -416,248,105131,6,0,L|460:240,4,45,0|0|0|0|8,1:0|0:0|0:0|0:0|0:0,0:0:0:0: -272,288,105626,1,0,1:0:0:0: -264,320,105708,1,0,0:0:0:0: -256,352,105791,2,0,L|204:356,5,30,0|0|0|0|0|0,0:0|0:0|0:0|1:0|0:0|0:0,0:0:0:0: -156,332,106120,2,0,L|104:336,5,30,8|0|0|0|0|0,0:0|0:0|0:0|1:0|0:0|0:0,0:0:0:0: -56,312,106450,5,4,1:2:0:0: -4,188,106615,1,0,0:0:0:0: -168,220,106780,2,0,P|127:232|79:228,1,90,8|0,0:0|0:0,0:0:0:0: -112,124,107109,1,0,0:0:0:0: -272,216,107274,2,0,L|264:316,1,90,0|8,1:0|0:0,0:0:0:0: -400,268,107604,1,0,0:0:0:0: -428,132,107769,5,0,1:0:0:0: -428,132,107851,1,0,0:0:0:0: -428,132,107934,1,0,0:0:0:0: -428,132,108016,1,0,0:0:0:0: -428,132,108098,1,8,0:0:0:0: -332,84,108263,2,0,P|288:80|232:88,1,90,0|0,1:0|0:0,0:0:0:0: -112,124,108593,1,0,1:0:0:0: -148,264,108758,1,8,0:0:0:0: -16,236,108923,1,0,0:0:0:0: -264,126,109087,6,0,L|272:216,1,90,0|0,1:0|0:0,0:0:0:0: -452,224,109417,2,0,L|460:320,1,90,8|0,0:0|0:0,0:0:0:0: -360,232,109747,1,0,0:0:0:0: -348,56,109912,1,0,1:0:0:0: -416,140,110076,1,8,0:0:0:0: -256,112,110241,2,0,P|212:120|160:112,1,90,0|0,0:0|1:0,0:0:0:0: -348,56,110571,6,0,L|331:150,1,90,0|8,0:0|0:0,0:0:0:0: -208,328,110901,2,0,L|191:239,1,90,0|0,1:0|0:0,0:0:0:0: -184,216,111148,1,0,1:0:0:0: -178,194,111230,1,0,1:0:0:0: -68,272,111395,1,8,0:0:0:0: -56,136,111560,1,0,1:0:0:0: -178,194,111725,6,0,P|219:203|267:199,1,90,4|0,1:2|0:0,0:0:0:0: -364,148,112054,1,8,0:0:0:0: -384,256,112219,2,0,P|406:291|443:322,1,90,0|0,0:0|0:0,0:0:0:0: -488,224,112549,1,0,1:0:0:0: -304,232,112714,2,0,L|208:224,2,90,8|0|0,0:0|0:0|1:0,0:0:0:0: -208,328,113208,6,0,L|112:320,1,90,0|8,0:0|0:0,0:0:0:0: -26,184,113538,2,0,L|116:192,1,90,0|0,1:0|0:0,0:0:0:0: -304,232,113868,1,0,1:0:0:0: -116,192,114032,1,8,0:0:0:0: -224,132,114197,1,0,0:0:0:0: -208,328,114362,6,0,B|272:360|320:312|320:312|340:368,1,180,4|8,1:2|0:0,0:0:0:0: -304,232,114857,2,0,P|300:184|308:140,1,90,0|0,0:0|0:0,0:0:0:0: -384,64,115186,1,0,1:0:0:0: -307,143,115351,1,8,0:0:0:0: -256,48,115516,1,0,0:0:0:0: -456,24,115681,6,0,B|482:101|420:136|420:136|440:184,1,180,4|8,1:2|0:0,0:0:0:0: -384,64,116175,2,0,P|340:56|296:64,1,90,0|0,1:0|0:0,0:0:0:0: -211,171,116505,1,0,1:0:0:0: -439,181,116670,2,0,L|448:84,1,90,8|0,0:0|0:0,0:0:0:0: -372,296,116999,6,2,L|304:292,1,67.5000025749208,2|0,0:1|0:0,0:0:0:0: -136,252,117329,6,2,P|196:260|212:172,1,168.75,0|0,0:0|0:0,0:0:0:0: -192,148,117659,1,2,0:3:0:0: -164,132,117741,1,2,0:3:0:0: -132,124,117824,1,2,1:3:0:0: -100,132,117906,1,2,0:3:0:0: -72,148,117988,2,0,L|52:56,1,90,2|8,0:3|0:0,0:0:0:0: -36,244,118318,5,0,1:0:0:0: -76,344,118483,1,0,1:0:0:0: -184,352,118648,1,0,1:0:0:0: -244,264,118813,1,0,1:0:0:0: -244,264,118895,1,0,1:0:0:0: -244,264,118977,2,0,L|288:260,3,45,2|0|2|0,1:2|0:0|0:0|0:0,0:0:0:0: -332,328,119307,2,0,L|376:324,3,45,2|0|2|0,1:2|0:0|0:0|0:0,0:0:0:0: -412,252,119637,5,4,1:2:0:0: -256,192,119719,12,0,122274,0:0:0:0: -256,192,140735,6,0,L|228:156,1,45,4|0,1:2|0:0,0:0:0:0: -152,132,141065,2,0,P|129:129|104:136,1,45 -48,192,141395,2,0,P|40:236|52:280,1,90,8|8,0:0|0:0,0:0:0:0: -196,352,142054,6,0,L|308:340,1,90,8|8,0:0|1:2,0:0:0:0: -336,280,142549,1,0,0:0:0:0: -404,324,142713,1,8,0:0:0:0: -404,324,142878,1,8,0:0:0:0: -292,120,143373,5,0,1:0:0:0: -212,104,143538,1,0,0:0:0:0: -140,140,143702,1,0,0:0:0:0: -120,220,143867,1,0,0:0:0:0: -144,296,144032,2,0,P|184:320|228:316,1,90,10|8,0:0|0:0,0:0:0:0: -372,212,144691,6,0,P|327:209|290:232,1,90,10|8,0:0|1:2,0:0:0:0: -348,288,145186,1,0,0:0:0:0: -452,220,145351,1,10,0:0:0:0: -452,220,145516,1,8,0:0:0:0: -328,36,146010,5,2,1:2:0:0: -264,88,146175,1,0,0:0:0:0: -184,108,146340,1,0,0:0:0:0: -104,88,146505,1,0,0:0:0:0: -44,36,146669,1,8,0:0:0:0: -44,36,146999,1,8,0:0:0:0: -44,36,147329,6,0,L|24:84,1,45,8|0,0:0|0:0,0:0:0:0: -52,156,147658,2,0,L|71:204,1,45,8|0,1:2|0:0,0:0:0:0: -144,236,147988,1,8,0:0:0:0: -144,236,148153,1,8,0:0:0:0: -316,64,148647,5,0,1:0:0:0: -380,116,148812,1,0,0:0:0:0: -408,192,148977,1,0,0:0:0:0: -380,268,149142,1,0,0:0:0:0: -316,320,149307,2,0,L|224:316,1,90,10|8,0:0|0:0,0:0:0:0: -64,248,149966,5,10,0:0:0:0: -144,236,150131,1,0,0:0:0:0: -188,168,150296,1,8,1:2:0:0: -192,88,150461,1,0,0:0:0:0: -140,24,150626,2,0,P|120:16|96:20,1,45,10|0,0:0|0:0,0:0:0:0: -260,132,150955,2,0,P|280:140|304:136,1,45,2|0,0:0|0:0,0:0:0:0: -476,48,151285,6,0,L|484:160,1,112.5,4|0,1:2|0:0,0:0:0:0: -464,236,151779,1,0,0:0:0:0: -436,308,151944,2,0,P|380:320|324:308,1,112.5,8|8,0:0|0:0,0:0:0:0: -76,308,152604,6,0,P|132:320|188:308,1,112.5,8|8,0:0|1:2,0:0:0:0: -256,88,153263,1,8,0:0:0:0: -256,168,153428,1,8,0:0:0:0: -256,168,153922,5,4,1:2:0:0: -256,248,154087,1,0,0:0:0:0: -324,128,154252,1,0,0:0:0:0: -188,128,154417,1,0,0:0:0:0: -332,212,154582,2,0,L|388:204,1,56.25,10|0,0:0|0:0,0:0:0:0: -492,152,154911,2,0,L|436:144,1,56.25,8|0,0:0|0:0,0:0:0:0: -324,128,155241,5,10,0:0:0:0: -180,212,155406,1,0,0:0:0:0: -332,212,155571,1,8,1:2:0:0: -188,128,155735,1,0,0:0:0:0: -256,248,155900,1,10,0:0:0:0: -256,248,156065,2,0,L|256:304,2,56.25,0|0|0,0:0|0:0|0:0,0:0:0:0: -180,212,156560,6,0,L|124:204,1,56.25,4|0,1:2|0:0,0:0:0:0: -20,152,156889,2,0,L|76:144,1,56.25,0|0,0:0|0:0,0:0:0:0: -188,128,157219,2,0,P|212:72|192:16,1,112.5,8|8,0:0|0:0,0:0:0:0: -132,72,157713,1,0,0:0:0:0: -180,212,157878,6,0,L|236:208,1,56.25,8|0,0:0|0:0,0:0:0:0: -360,252,158208,2,8,L|304:248,1,56.25,8|0,1:2|0:0,0:0:0:0: -168,292,158538,2,0,L|160:356,2,56.25,8|8|0,0:0|0:0|0:0,0:0:0:0: -180,212,159032,1,0,0:0:0:0: -144,140,159197,6,0,P|104:128|36:148,1,112.5,2|0,1:2|0:0,0:0:0:0: -12,220,159691,1,0,0:0:0:0: -36,296,159856,2,0,P|60:316|92:324,1,56.25,8|0,0:0|0:0,0:0:0:0: -215,264,160186,2,0,P|189:273|168:292,1,56.25,8|0,0:0|0:0,0:0:0:0: -228,344,160516,6,0,L|284:340,1,56.25,10|0,0:0|0:0,0:0:0:0: -328,276,160845,2,0,L|384:272,1,56.25,8|0,1:2|0:0,0:0:0:0: -428,208,161175,1,8,0:0:0:0: -440,128,161340,1,8,0:0:0:0: -400,60,161505,1,2,0:0:0:0: -328,28,161669,1,0,0:0:0:0: -212,76,161834,6,0,P|200:120|208:164,1,90,2|0,1:2|1:0,0:0:0:0: -300,308,162163,2,0,P|312:264|304:220,1,90,2|0,1:2|1:0,0:0:0:0: -140,236,162493,2,0,P|184:248|228:240,1,90,2|0,1:2|1:0,0:0:0:0: -372,148,162823,2,0,P|328:136|284:144,1,90,2|0,1:2|1:0,0:0:0:0: -104,316,163152,5,2,1:2:0:0: -78,297,163235,1,0,1:0:0:0: -60,270,163317,1,0,1:0:0:0: -54,239,163399,1,0,1:0:0:0: -58,207,163482,1,2,1:2:0:0: -74,180,163564,1,0,1:0:0:0: -98,159,163647,1,0,1:0:0:0: -127,149,163729,1,0,1:0:0:0: -158,150,163812,2,0,L|208:160,1,45,2|0,1:2|1:0,0:0:0:0: -344,184,163976,2,0,L|294:194,1,45,0|0,1:0|1:0,0:0:0:0: -140,236,164141,1,4,1:2:0:0: -140,236,164471,6,0,L|232:252,1,90,4|0,1:2|0:0,0:0:0:0: -344,184,164801,1,8,0:0:0:0: -380,284,164965,1,0,0:0:0:0: -368,104,165130,2,0,P|324:104|284:128,1,90,0|0,0:0|1:0,0:0:0:0: -356,360,165460,2,0,P|400:360|440:336,1,90,8|0,0:0|0:0,0:0:0:0: -432,208,165790,5,0,1:0:0:0: -292,260,165954,1,0,0:0:0:0: -344,184,166119,1,8,0:0:0:0: -204,236,166284,1,0,1:0:0:0: -204,236,166366,1,0,0:0:0:0: -204,236,166449,2,0,L|216:328,1,90,0|0,0:0|1:0,0:0:0:0: -120,208,166779,2,0,L|131:118,1,90,8|0,0:0|0:0,0:0:0:0: -204,236,167108,5,0,1:0:0:0: -32,216,167273,1,0,0:0:0:0: -130,118,167438,1,8,0:0:0:0: -110,298,167603,1,0,0:0:0:0: -110,298,167685,1,0,0:0:0:0: -110,298,167768,2,0,L|121:208,1,90,0|0,0:0|1:0,0:0:0:0: -304,40,168097,2,0,L|315:130,1,90,8|0,0:0|0:0,0:0:0:0: -328,236,168427,5,0,1:0:0:0: -184,148,168592,1,0,0:0:0:0: -314,129,168757,1,8,0:0:0:0: -197,254,168921,1,0,1:0:0:0: -197,254,169004,1,0,0:0:0:0: -197,254,169086,2,0,P|220:292|260:312,1,90,0|0,0:0|1:0,0:0:0:0: -409,210,169416,2,0,P|365:211|328:236,1,90,8|0,0:0|0:0,0:0:0:0: -488,232,169746,6,0,P|487:192|464:149,1,90,0|0,1:0|0:0,0:0:0:0: -314,129,170075,1,8,0:0:0:0: -409,210,170240,1,0,0:0:0:0: -332,40,170405,2,0,L|240:36,1,90,0|0,0:0|1:0,0:0:0:0: -68,144,170735,2,0,L|157:140,1,90,8|0,0:0|0:0,0:0:0:0: -314,129,171064,5,0,1:0:0:0: -332,40,171229,1,0,0:0:0:0: -324,216,171394,1,8,0:0:0:0: -306,305,171559,1,0,1:0:0:0: -257,178,171724,1,0,0:0:0:0: -168,160,171888,1,0,1:0:0:0: -384,164,172053,1,8,0:0:0:0: -473,182,172218,1,0,0:0:0:0: -306,305,172383,6,0,L|216:312,1,90,0|0,1:0|0:0,0:0:0:0: -60,172,172713,1,8,0:0:0:0: -120,260,172877,1,0,0:0:0:0: -168,160,173042,2,0,L|172:68,1,90,0|0,0:0|1:0,0:0:0:0: -309,216,173372,2,0,L|306:306,1,90,8|0,0:0|0:0,0:0:0:0: -120,260,173702,5,0,1:0:0:0: -152,256,173784,1,0,1:0:0:0: -184,252,173866,1,0,1:0:0:0: -309,216,174031,1,8,0:0:0:0: -103,168,174196,1,0,1:0:0:0: -135,164,174279,1,0,1:0:0:0: -167,160,174361,1,0,1:0:0:0: -292,124,174526,1,0,1:0:0:0: -87,76,174691,1,8,1:2:0:0: -119,72,174773,1,0,1:0:0:0: -151,68,174855,1,0,1:0:0:0: -276,32,175020,6,0,L|368:40,1,90,0|0,1:0|0:0,0:0:0:0: -448,108,175350,1,8,0:0:0:0: -292,124,175515,1,0,0:0:0:0: -292,124,175597,1,0,0:0:0:0: -292,124,175680,2,0,L|308:216,1,90,0|0,0:0|1:0,0:0:0:0: -328,320,176009,1,8,0:0:0:0: -408,248,176174,1,0,0:0:0:0: -220,300,176339,6,0,P|176:304|128:292,1,90,0|0,1:0|0:0,0:0:0:0: -16,120,176669,1,8,0:0:0:0: -120,152,176834,1,0,1:0:0:0: -120,152,176916,1,0,0:0:0:0: -120,152,176998,2,0,L|124:200,1,45 -212,176,177163,2,0,L|239:215,1,45,0|0,1:0|0:0,0:0:0:0: -292,124,177328,2,0,P|302:79|283:30,1,90,8|0,0:0|0:0,0:0:0:0: -344,192,177658,6,0,P|372:156|376:104,1,90,0|0,1:0|0:0,0:0:0:0: -212,88,177987,1,8,0:0:0:0: -272,228,178152,1,0,0:0:0:0: -272,228,178235,1,0,0:0:0:0: -272,228,178317,1,0,0:0:0:0: -292,124,178482,1,0,1:0:0:0: -180,180,178647,1,8,0:0:0:0: -200,284,178812,1,0,0:0:0:0: -292,124,178976,5,0,1:0:0:0: -288,92,179059,1,0,0:0:0:0: -280,60,179141,2,0,P|248:24|208:14,1,90,0|8,0:0|0:0,0:0:0:0: -22,65,179471,2,0,P|67:71|112:68,1,90,0|0,1:0|0:0,0:0:0:0: -212,88,179801,1,0,1:0:0:0: -22,65,179965,1,8,0:0:0:0: -180,180,180130,5,0,0:0:0:0: -180,180,180213,1,0,0:0:0:0: -180,180,180295,2,0,P|184:224|172:272,1,90,0|0,1:0|0:0,0:0:0:0: -76,216,180625,2,0,P|72:172|84:124,1,90,8|0,0:0|0:0,0:0:0:0: -380,240,180954,2,0,P|384:284|372:332,1,90,0|0,0:0|1:0,0:0:0:0: -276,276,181284,2,0,P|272:232|284:184,1,90,8|0,0:0|0:0,0:0:0:0: -374,129,181614,5,0,1:0:0:0: -300,352,181779,2,0,L|204:348,2,90,0|8|0,0:0|0:0|1:0,0:0:0:0: -448,180,182273,1,2,0:0:0:0: -448,180,182438,1,2,1:2:0:0: -276,276,182603,1,10,0:0:0:0: -276,276,182768,1,2,0:0:0:0: -96,200,182932,6,0,L|88:108,1,90,0|0,1:0|0:0,0:0:0:0: -96,200,183262,1,8,0:0:0:0: -12,68,183427,2,0,P|72:24|164:68,1,180,0|0,0:0|1:0,0:0:0:0: -140,272,183921,2,0,P|92:284|52:271,1,90,8|0,0:0|0:0,0:0:0:0: -176,156,184251,5,0,1:0:0:0: -208,152,184334,1,0,1:0:0:0: -240,148,184416,1,0,1:0:0:0: -308,64,184581,1,8,0:0:0:0: -296,240,184746,1,0,1:0:0:0: -312,268,184828,1,0,1:0:0:0: -336,284,184910,1,0,1:0:0:0: -368,292,184993,1,0,1:0:0:0: -400,288,185075,1,0,1:0:0:0: -464,184,185240,1,8,0:0:0:0: -468,152,185323,1,0,0:0:0:0: -472,120,185405,2,0,L|464:76,1,45,0|0,1:0|1:0,0:0:0:0: -388,96,185570,6,0,P|360:132|316:148,1,90,4|0,1:2|0:0,0:0:0:0: -224,46,185899,2,0,P|268:43|308:63,1,90,8|0,0:0|0:0,0:0:0:0: -296,240,186229,1,0,0:0:0:0: -308,64,186394,1,0,1:0:0:0: -296,240,186559,2,0,L|312:332,1,90,8|0,0:0|0:0,0:0:0:0: -464,184,186888,6,0,P|420:180|372:188,1,90,0|0,1:0|0:0,0:0:0:0: -296,240,187218,1,8,0:0:0:0: -136,292,187383,2,0,P|94:277|54:249,1,90,0|0,1:0|0:0,0:0:0:0: -21,159,187713,1,0,1:0:0:0: -104,8,187877,2,0,L|124:96,1,90,10|0,0:0|0:0,0:0:0:0: -124,96,188207,6,0,P|152:132|196:148,1,90,0|0,1:0|0:0,0:0:0:0: -287,46,188537,2,0,P|243:43|204:63,1,90,8|0,0:0|0:0,0:0:0:0: -216,240,188866,1,2,0:0:0:0: -204,64,189031,1,0,1:0:0:0: -216,240,189196,2,0,L|200:332,1,90,8|0,0:0|0:0,0:0:0:0: -40,240,189526,5,2,1:2:0:0: -128,192,189691,1,0,0:0:0:0: -216,240,189855,1,8,0:0:0:0: -304,192,190020,1,0,1:0:0:0: -392,240,190185,2,0,L|400:332,1,90,2|0,0:0|1:0,0:0:0:0: -464,168,190515,2,0,L|456:76,1,90,8|0,0:0|0:0,0:0:0:0: -392,240,190844,6,0,P|364:272|312:292,1,90,2|0,1:2|0:0,0:0:0:0: -220,140,191174,2,0,P|248:108|296:92,1,90,8|0,0:0|0:0,0:0:0:0: -324,96,191421,1,0,0:0:0:0: -356,104,191504,2,0,L|340:16,1,90,0|0,0:0|1:0,0:0:0:0: -256,276,191834,2,0,L|272:364,1,90,8|0,0:0|0:0,0:0:0:0: -392,240,192163,5,0,1:0:0:0: -356,104,192328,1,0,0:0:0:0: -220,140,192493,1,8,0:0:0:0: -256,276,192658,1,0,1:0:0:0: -305,191,192823,1,0,0:0:0:0: -212,56,192987,1,0,1:0:0:0: -200,220,193152,1,10,0:0:0:0: -200,220,193482,6,0,P|156:228|108:220,1,90,0|0,1:0|0:0,0:0:0:0: -88,116,193812,1,8,0:0:0:0: -16,192,193976,1,0,0:0:0:0: -16,192,194059,1,0,0:0:0:0: -16,192,194141,2,0,L|28:288,1,90,2|0,0:0|1:0,0:0:0:0: -188,309,194471,2,0,L|200:220,1,90,8|0,0:0|0:0,0:0:0:0: -216,112,194801,5,2,1:2:0:0: -216,112,194883,1,0,1:0:0:0: -216,112,194965,1,0,1:0:0:0: -361,25,195130,1,8,0:0:0:0: -294,180,195295,1,0,1:0:0:0: -294,180,195377,1,0,1:0:0:0: -294,180,195460,1,2,0:0:0:0: -256,16,195625,1,0,1:0:0:0: -384,127,195790,1,10,1:2:0:0: -416,132,195872,1,0,1:0:0:0: -448,140,195954,2,0,L|452:84,1,45,0|0,1:0|1:0,0:0:0:0: -416,216,196119,6,0,P|412:264|432:312,1,90,4|0,1:2|0:0,0:0:0:0: -304,268,196449,2,0,P|308:220|288:172,1,90,8|0,0:0|0:0,0:0:0:0: -216,112,196779,2,0,L|120:104,1,90,0|0,0:0|1:0,0:0:0:0: -52,248,197108,2,0,L|141:255,1,90,8|0,0:0|0:0,0:0:0:0: -304,268,197438,5,0,1:0:0:0: -416,216,197603,1,0,0:0:0:0: -408,340,197768,1,8,0:0:0:0: -332,180,197932,1,0,1:0:0:0: -332,180,198015,1,0,0:0:0:0: -332,180,198097,2,0,P|360:140|400:120,1,90,0|0,0:0|1:0,0:0:0:0: -484,284,198427,1,10,0:0:0:0: -304,268,198592,1,2,0:0:0:0: -416,216,198757,6,0,P|428:172|420:124,1,90,2|0,1:2|0:0,0:0:0:0: -344,52,199086,1,8,0:0:0:0: -332,180,199251,1,0,0:0:0:0: -164,236,199416,2,0,P|152:192|160:144,1,90,0|0,0:0|1:0,0:0:0:0: -236,72,199746,1,8,0:0:0:0: -248,200,199910,1,0,0:0:0:0: -156,328,200075,6,0,L|56:320,1,90,2|0,1:2|0:0,0:0:0:0: -164,236,200405,1,8,0:0:0:0: -256,292,200570,2,0,P|300:296|344:284,1,90,0|0,1:0|0:0,0:0:0:0: -432,220,200899,2,0,L|460:308,2,90,0|8|0,1:0|0:0|0:0,0:0:0:0: -392,120,201394,5,4,1:2:0:0: -396,32,201559,1,0,1:0:0:0: -316,72,201724,1,0,1:0:0:0: -256,6,201888,1,0,1:0:0:0: -228,91,202053,1,0,1:0:0:0: -139,87,202218,1,0,1:0:0:0: -179,166,202383,1,0,1:0:0:0: -113,226,202548,1,0,1:0:0:0: -197,253,202713,5,4,1:2:0:0: -193,342,202877,1,0,1:0:0:0: -272,302,203042,1,0,1:0:0:0: -332,367,203207,1,0,1:0:0:0: -359,283,203372,1,2,1:2:0:0: -448,287,203537,1,2,1:2:0:0: -407,208,203702,1,2,1:2:0:0: -472,147,203866,1,2,1:2:0:0: -387,121,204031,5,4,1:2:0:0: -360,100,204114,1,0,1:0:0:0: -344,72,204196,1,0,1:0:0:0: -336,40,204279,1,0,1:0:0:0: -340,8,204361,1,0,1:0:0:0: -316,28,204443,1,0,1:0:0:0: -284,32,204526,1,0,1:0:0:0: -252,28,204608,1,0,1:0:0:0: -228,8,204691,2,0,L|184:20,7,45,4|0|0|0|0|0|0|0,1:2|1:0|1:0|1:0|1:0|1:0|1:0|1:0,0:0:0:0: -112,56,205350,5,4,1:2:0:0: -100,84,205432,1,0,1:0:0:0: -96,116,205515,1,0,1:0:0:0: -100,148,205597,1,0,1:0:0:0: -112,176,205680,1,0,1:0:0:0: -124,204,205762,1,0,1:0:0:0: -128,236,205844,1,0,1:0:0:0: -124,268,205927,1,0,1:0:0:0: -112,296,206009,2,0,L|71:313,3,45,2|0|2|0,1:2|0:0|0:0|0:0,0:0:0:0: -192,312,206339,2,0,L|175:353,3,45,2|0|2|0,1:2|0:0|0:0|0:0,0:0:0:0: -256,264,206669,5,4,1:2:0:0: -256,192,206751,12,0,209306,0:0:0:0: diff --git a/osu.Game.Tests/Resources/valid-events.osu b/osu.Game.Tests/Resources/valid-events.osu new file mode 100644 index 0000000000..ed3614b4ed --- /dev/null +++ b/osu.Game.Tests/Resources/valid-events.osu @@ -0,0 +1,12 @@ +osu file format v14 + +[Events] +//Background and Video events +0,0,"machinetop_background.jpg",0,0 +//Break Periods +2,122474,140135 +//Storyboard Layer 0 (Background) +//Storyboard Layer 1 (Fail) +//Storyboard Layer 2 (Pass) +//Storyboard Layer 3 (Foreground) +//Storyboard Sound Samples From ee6a90c48da5c6a1a9612358f68a0011e3095a4d Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 5 Aug 2019 20:43:30 -0700 Subject: [PATCH 2196/5608] Fix back button hover sounds playing in unclickable area --- osu.Game/Graphics/UserInterface/BackButton.cs | 4 ++-- osu.Game/Graphics/UserInterface/TwoLayerButton.cs | 13 ++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 48bf0848ae..c4735b4a16 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -22,8 +22,8 @@ namespace osu.Game.Graphics.UserInterface Child = button = new TwoLayerButton { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, Text = @"back", Icon = OsuIcon.LeftCircle, Action = () => Action?.Invoke() diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs index c74d00cd1e..75d3847417 100644 --- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs +++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs @@ -15,6 +15,7 @@ using System; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; +using osu.Game.Screens.Select; namespace osu.Game.Graphics.UserInterface { @@ -28,7 +29,9 @@ namespace osu.Game.Graphics.UserInterface private const int transform_time = 600; private const int pulse_length = 250; - private const float shear = 0.1f; + private const float SHEAR_WIDTH = 5f; + + private static readonly Vector2 shearing = new Vector2(SHEAR_WIDTH / Footer.HEIGHT, 0); public static readonly Vector2 SIZE_EXTENDED = new Vector2(140, 50); public static readonly Vector2 SIZE_RETRACTED = new Vector2(100, 50); @@ -56,7 +59,7 @@ namespace osu.Game.Graphics.UserInterface c1.Origin = c1.Anchor = value.HasFlag(Anchor.x2) ? Anchor.TopLeft : Anchor.TopRight; c2.Origin = c2.Anchor = value.HasFlag(Anchor.x2) ? Anchor.TopRight : Anchor.TopLeft; - X = value.HasFlag(Anchor.x2) ? SIZE_RETRACTED.X * shear * 0.5f : 0; + X = value.HasFlag(Anchor.x2) ? SIZE_RETRACTED.X * shearing.X * 0.5f : 0; Remove(c1); Remove(c2); @@ -70,6 +73,7 @@ namespace osu.Game.Graphics.UserInterface public TwoLayerButton() { Size = SIZE_RETRACTED; + Shear = shearing; Children = new Drawable[] { @@ -82,7 +86,6 @@ namespace osu.Game.Graphics.UserInterface new Container { RelativeSizeAxes = Axes.Both, - Shear = new Vector2(shear, 0), Masking = true, MaskingSmoothness = 2, EdgeEffect = new EdgeEffectParameters @@ -105,6 +108,7 @@ namespace osu.Game.Graphics.UserInterface { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Shear = -shearing, }, } }, @@ -119,7 +123,6 @@ namespace osu.Game.Graphics.UserInterface new Container { RelativeSizeAxes = Axes.Both, - Shear = new Vector2(shear, 0), Masking = true, MaskingSmoothness = 2, EdgeEffect = new EdgeEffectParameters @@ -144,6 +147,7 @@ namespace osu.Game.Graphics.UserInterface { Origin = Anchor.Centre, Anchor = Anchor.Centre, + Shear = -shearing, } } }, @@ -188,7 +192,6 @@ namespace osu.Game.Graphics.UserInterface var flash = new Box { RelativeSizeAxes = Axes.Both, - Shear = new Vector2(shear, 0), Colour = Color4.White.Opacity(0.5f), }; Add(flash); From 11aa3544c49ca6c6d4adc86216eae8ac693c038b Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 5 Aug 2019 20:57:17 -0700 Subject: [PATCH 2197/5608] Fix shear width naming --- osu.Game/Graphics/UserInterface/TwoLayerButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs index 75d3847417..b56dd201c2 100644 --- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs +++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs @@ -29,9 +29,9 @@ namespace osu.Game.Graphics.UserInterface private const int transform_time = 600; private const int pulse_length = 250; - private const float SHEAR_WIDTH = 5f; + private const float shear_width = 5f; - private static readonly Vector2 shearing = new Vector2(SHEAR_WIDTH / Footer.HEIGHT, 0); + private static readonly Vector2 shearing = new Vector2(shear_width / Footer.HEIGHT, 0); public static readonly Vector2 SIZE_EXTENDED = new Vector2(140, 50); public static readonly Vector2 SIZE_RETRACTED = new Vector2(100, 50); From ac0abe0692cd81496b6fd5b8839ede050202752d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 6 Aug 2019 14:21:34 +0900 Subject: [PATCH 2198/5608] Use newly exposed UpdateState --- .../Containers/OsuFocusedOverlayContainer.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index c33e980a9a..eff853abcf 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -55,15 +55,6 @@ namespace osu.Game.Graphics.Containers samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out"); } - protected override void LoadComplete() - { - base.LoadComplete(); - - // This must be added after the base LoadComplete, since onStateChanged contains logic that - // must be run after other state change logic has been completed. - State.ValueChanged += onStateChanged; - } - /// /// Whether mouse input should be blocked screen-wide while this overlay is visible. /// Performing mouse actions outside of the valid extents will hide the overlay. @@ -101,8 +92,10 @@ namespace osu.Game.Graphics.Containers public bool OnReleased(GlobalAction action) => false; - private void onStateChanged(ValueChangedEvent state) + protected override void UpdateState(ValueChangedEvent state) { + base.UpdateState(state); + switch (state.NewValue) { case Visibility.Visible: From dd701eaa6292586c181b35a9cc79bc1e0e677732 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 6 Aug 2019 14:10:03 +0300 Subject: [PATCH 2199/5608] Safely cancel the completion task on restart or immediate exit --- osu.Game/Screens/Play/Player.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 8dc16af575..2f7f793bbf 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -255,7 +255,7 @@ namespace osu.Game.Screens.Play private void performImmediateExit() { // if a restart has been requested, cancel any pending completion (user has shown intent to restart). - onCompletionEvent = null; + onCompletionEvent?.Cancel(); ValidForResume = false; @@ -275,12 +275,8 @@ namespace osu.Game.Screens.Play sampleRestart?.Play(); - // if a restart has been requested, cancel any pending completion (user has shown intent to restart). - onCompletionEvent = null; - - ValidForResume = false; RestartRequested?.Invoke(); - this.Exit(); + performImmediateExit(); } private ScheduledDelegate onCompletionEvent; @@ -306,8 +302,6 @@ namespace osu.Game.Screens.Play scoreManager.Import(score).Wait(); this.Push(CreateResults(score)); - - onCompletionEvent = null; }); } } @@ -471,9 +465,9 @@ namespace osu.Game.Screens.Play public override bool OnExiting(IScreen next) { - if (onCompletionEvent != null) + if (onCompletionEvent != null && !onCompletionEvent.Cancelled && !onCompletionEvent.Completed) + // proceed to result screen if beatmap already finished playing { - // Proceed to result screen if beatmap already finished playing onCompletionEvent.RunTask(); return true; } From 2a68bb2749bf36bc632a1881f124dbbdcc592c96 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 6 Aug 2019 14:11:43 +0300 Subject: [PATCH 2200/5608] onCompletionEvent -> pushResults --- osu.Game/Screens/Play/Player.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 2f7f793bbf..d0ef3bc104 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -255,7 +255,7 @@ namespace osu.Game.Screens.Play private void performImmediateExit() { // if a restart has been requested, cancel any pending completion (user has shown intent to restart). - onCompletionEvent?.Cancel(); + pushResults?.Cancel(); ValidForResume = false; @@ -279,12 +279,12 @@ namespace osu.Game.Screens.Play performImmediateExit(); } - private ScheduledDelegate onCompletionEvent; + private ScheduledDelegate pushResults; private void onCompletion() { // Only show the completion screen if the player hasn't failed - if (ScoreProcessor.HasFailed || onCompletionEvent != null) + if (ScoreProcessor.HasFailed || pushResults != null) return; ValidForResume = false; @@ -293,7 +293,7 @@ namespace osu.Game.Screens.Play using (BeginDelayedSequence(1000)) { - onCompletionEvent = Schedule(delegate + pushResults = Schedule(delegate { if (!this.IsCurrentScreen()) return; @@ -465,10 +465,10 @@ namespace osu.Game.Screens.Play public override bool OnExiting(IScreen next) { - if (onCompletionEvent != null && !onCompletionEvent.Cancelled && !onCompletionEvent.Completed) + if (pushResults != null && !pushResults.Cancelled && !pushResults.Completed) // proceed to result screen if beatmap already finished playing { - onCompletionEvent.RunTask(); + pushResults.RunTask(); return true; } From dda078277a80aa9a465c9edf7ea7b12df3e04f4d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Aug 2019 23:05:12 +0900 Subject: [PATCH 2201/5608] Minor variable name changes --- osu.Game/Screens/Play/Player.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d0ef3bc104..96b8073d11 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -255,7 +255,7 @@ namespace osu.Game.Screens.Play private void performImmediateExit() { // if a restart has been requested, cancel any pending completion (user has shown intent to restart). - pushResults?.Cancel(); + completionProgressDelegate?.Cancel(); ValidForResume = false; @@ -279,12 +279,12 @@ namespace osu.Game.Screens.Play performImmediateExit(); } - private ScheduledDelegate pushResults; + private ScheduledDelegate completionProgressDelegate; private void onCompletion() { // Only show the completion screen if the player hasn't failed - if (ScoreProcessor.HasFailed || pushResults != null) + if (ScoreProcessor.HasFailed || completionProgressDelegate != null) return; ValidForResume = false; @@ -293,7 +293,7 @@ namespace osu.Game.Screens.Play using (BeginDelayedSequence(1000)) { - pushResults = Schedule(delegate + completionProgressDelegate = Schedule(delegate { if (!this.IsCurrentScreen()) return; @@ -465,10 +465,10 @@ namespace osu.Game.Screens.Play public override bool OnExiting(IScreen next) { - if (pushResults != null && !pushResults.Cancelled && !pushResults.Completed) - // proceed to result screen if beatmap already finished playing + if (completionProgressDelegate != null && !completionProgressDelegate.Cancelled && !completionProgressDelegate.Completed) { - pushResults.RunTask(); + // proceed to result screen if beatmap already finished playing + completionProgressDelegate.RunTask(); return true; } From ffb6794b4ebea7651ed29418f5339964e4208ca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20H=C3=BCbner?= Date: Tue, 6 Aug 2019 16:11:13 +0200 Subject: [PATCH 2202/5608] formatting inspection --- osu.Game/Online/Chat/ChannelManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 30135d5b8b..b5d8879e50 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -222,6 +222,7 @@ namespace osu.Game.Online.Chat } var channel = availableChannels.Where(c => c.Name == content || c.Name == $"#{content}").FirstOrDefault(); + if (channel == null) { target.AddNewMessages(new ErrorMessage($"Channel '{content}' not found.")); From 3cfbbac5dc9ae96335a476b829b46de88b4f2299 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 6 Aug 2019 17:47:31 +0300 Subject: [PATCH 2203/5608] Expand requests --- osu.Game/Online/API/Requests/GetUserRequest.cs | 7 +++++-- .../Online/API/Requests/GetUserScoresRequest.cs | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetUserRequest.cs b/osu.Game/Online/API/Requests/GetUserRequest.cs index 37ed0574f1..18fb4bb7db 100644 --- a/osu.Game/Online/API/Requests/GetUserRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRequest.cs @@ -2,18 +2,21 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Users; +using osu.Game.Rulesets; namespace osu.Game.Online.API.Requests { public class GetUserRequest : APIRequest { private readonly long? userId; + private readonly RulesetInfo ruleset; - public GetUserRequest(long? userId = null) + public GetUserRequest(long? userId = null, RulesetInfo ruleset = null) { this.userId = userId; + this.ruleset = ruleset; } - protected override string Target => userId.HasValue ? $@"users/{userId}" : @"me"; + protected override string Target => userId.HasValue ? (ruleset != null ? $@"users/{userId}/{ruleset.ShortName}" : $@"users/{userId}") : @"me"; } } diff --git a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs index d41966fe1b..7b4d66e7b2 100644 --- a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs @@ -2,7 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using osu.Framework.IO.Network; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; namespace osu.Game.Online.API.Requests { @@ -10,12 +12,24 @@ namespace osu.Game.Online.API.Requests { private readonly long userId; private readonly ScoreType type; + private readonly RulesetInfo ruleset; - public GetUserScoresRequest(long userId, ScoreType type, int page = 0, int itemsPerPage = 5) + public GetUserScoresRequest(long userId, ScoreType type, int page = 0, int itemsPerPage = 5, RulesetInfo ruleset = null) : base(page, itemsPerPage) { this.userId = userId; this.type = type; + this.ruleset = ruleset; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + if (ruleset != null) + req.AddParameter("mode", ruleset.ShortName); + + return req; } protected override string Target => $@"users/{userId}/scores/{type.ToString().ToLowerInvariant()}"; From 91b9a496f5c1e3a60fee8136473ee64098c94d20 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 6 Aug 2019 18:29:07 -0700 Subject: [PATCH 2204/5608] Remove now unnecessary .gitmodules and .travis.yml --- .gitmodules | 0 .travis.yml | 2 -- 2 files changed, 2 deletions(-) delete mode 100644 .gitmodules delete mode 100644 .travis.yml diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ce353d9b27..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: csharp -solution: osu.sln \ No newline at end of file From 616de1830a4c4200fba87a0ef8758e9cea0a6907 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Aug 2019 12:20:49 +0900 Subject: [PATCH 2205/5608] Less sheep --- osu.Game/Screens/Select/FooterButton.cs | 6 +++--- osu.Game/Screens/Select/FooterButtonMods.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index 15088f0eb3..c1478aa4ce 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Select { public static readonly float SHEAR_WIDTH = 7.5f; - protected static readonly Vector2 SHEARING = new Vector2(SHEAR_WIDTH / Footer.HEIGHT, 0); + protected static readonly Vector2 SHEAR = new Vector2(SHEAR_WIDTH / Footer.HEIGHT, 0); public string Text { @@ -64,7 +64,7 @@ namespace osu.Game.Screens.Select public FooterButton() { AutoSizeAxes = Axes.Both; - Shear = SHEARING; + Shear = SHEAR; Children = new Drawable[] { box = new Box @@ -83,7 +83,7 @@ namespace osu.Game.Screens.Select TextContainer = new Container { Size = new Vector2(100 - SHEAR_WIDTH, 50), - Shear = -SHEARING, + Shear = -SHEAR, Child = SpriteText = new OsuSpriteText { Anchor = Anchor.Centre, diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 58d92dbca6..29b1364944 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Select { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Shear = -SHEARING, + Shear = -SHEAR, Child = modDisplay = new FooterModDisplay { DisplayUnrankedText = false, From c16e84e5e64dda14c07afe74ba14adb940b8438c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 7 Aug 2019 06:35:57 +0300 Subject: [PATCH 2206/5608] Fix unability to get local user with specific ruleset --- osu.Game/Online/API/Requests/GetUserRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/GetUserRequest.cs b/osu.Game/Online/API/Requests/GetUserRequest.cs index 18fb4bb7db..acf9aefa19 100644 --- a/osu.Game/Online/API/Requests/GetUserRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRequest.cs @@ -17,6 +17,6 @@ namespace osu.Game.Online.API.Requests this.ruleset = ruleset; } - protected override string Target => userId.HasValue ? (ruleset != null ? $@"users/{userId}/{ruleset.ShortName}" : $@"users/{userId}") : @"me"; + protected override string Target => userId.HasValue ? (ruleset != null ? $@"users/{userId}/{ruleset.ShortName}" : $@"users/{userId}") : ruleset != null ? $@"me/{ruleset.ShortName}" : $@"me"; } } From 6ed9c983ff1b8f37e981764370d2f9b255a024ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Aug 2019 12:36:00 +0900 Subject: [PATCH 2207/5608] Rename shear variable --- osu.Game/Graphics/UserInterface/TwoLayerButton.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs index b56dd201c2..aa96796cf1 100644 --- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs +++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs @@ -31,7 +31,7 @@ namespace osu.Game.Graphics.UserInterface private const float shear_width = 5f; - private static readonly Vector2 shearing = new Vector2(shear_width / Footer.HEIGHT, 0); + private static readonly Vector2 shear = new Vector2(shear_width / Footer.HEIGHT, 0); public static readonly Vector2 SIZE_EXTENDED = new Vector2(140, 50); public static readonly Vector2 SIZE_RETRACTED = new Vector2(100, 50); @@ -59,7 +59,7 @@ namespace osu.Game.Graphics.UserInterface c1.Origin = c1.Anchor = value.HasFlag(Anchor.x2) ? Anchor.TopLeft : Anchor.TopRight; c2.Origin = c2.Anchor = value.HasFlag(Anchor.x2) ? Anchor.TopRight : Anchor.TopLeft; - X = value.HasFlag(Anchor.x2) ? SIZE_RETRACTED.X * shearing.X * 0.5f : 0; + X = value.HasFlag(Anchor.x2) ? SIZE_RETRACTED.X * shear.X * 0.5f : 0; Remove(c1); Remove(c2); @@ -73,7 +73,7 @@ namespace osu.Game.Graphics.UserInterface public TwoLayerButton() { Size = SIZE_RETRACTED; - Shear = shearing; + Shear = shear; Children = new Drawable[] { @@ -108,7 +108,7 @@ namespace osu.Game.Graphics.UserInterface { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Shear = -shearing, + Shear = -shear, }, } }, @@ -147,7 +147,7 @@ namespace osu.Game.Graphics.UserInterface { Origin = Anchor.Centre, Anchor = Anchor.Centre, - Shear = -shearing, + Shear = -shear, } } }, From 24f9872315e094d1526aca7226878f42911a1e59 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 7 Aug 2019 06:45:39 +0300 Subject: [PATCH 2208/5608] Fix unnecessary scores loading --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index a6cc2b0500..ec2697447a 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -132,7 +132,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Scores = null; - if (beatmap?.OnlineBeatmapID.HasValue != true) + if (beatmap?.OnlineBeatmapID.HasValue != true || beatmap?.Status <= BeatmapSetOnlineStatus.Pending) return; loadingAnimation.Show(); From b1c78c43f382a6aae24e2ddcb8ac102013243999 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 7 Aug 2019 06:57:46 +0300 Subject: [PATCH 2209/5608] Simplify target string --- osu.Game/Online/API/Requests/GetUserRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/GetUserRequest.cs b/osu.Game/Online/API/Requests/GetUserRequest.cs index acf9aefa19..31b7e95b39 100644 --- a/osu.Game/Online/API/Requests/GetUserRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRequest.cs @@ -17,6 +17,6 @@ namespace osu.Game.Online.API.Requests this.ruleset = ruleset; } - protected override string Target => userId.HasValue ? (ruleset != null ? $@"users/{userId}/{ruleset.ShortName}" : $@"users/{userId}") : ruleset != null ? $@"me/{ruleset.ShortName}" : $@"me"; + protected override string Target => userId.HasValue ? $@"users/{userId}/{ruleset?.ShortName}" : $@"me/{ruleset?.ShortName}"; } } From b9384d7a53cb5e59074ff2b538b90084664c3d6b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 7 Aug 2019 07:00:50 +0300 Subject: [PATCH 2210/5608] Remove unnecessary null check --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index ec2697447a..4bbcd8d631 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -132,7 +132,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Scores = null; - if (beatmap?.OnlineBeatmapID.HasValue != true || beatmap?.Status <= BeatmapSetOnlineStatus.Pending) + if (beatmap?.OnlineBeatmapID.HasValue != true || beatmap.Status <= BeatmapSetOnlineStatus.Pending) return; loadingAnimation.Show(); From b064df91a7065b1b28091208f3638418b1b4df40 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 7 Aug 2019 08:33:55 +0300 Subject: [PATCH 2211/5608] Initial implementation --- .../TestSceneLeaderboardScopeSelector.cs | 37 +++++ .../BeatmapSet/LeaderboardScopeSelector.cs | 157 ++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs create mode 100644 osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs new file mode 100644 index 0000000000..f4c0d32946 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs @@ -0,0 +1,37 @@ +// 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.Overlays.BeatmapSet; +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Bindables; +using osu.Game.Screens.Select.Leaderboards; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneLeaderboardScopeSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(LeaderboardScopeSelector), + }; + + public TestSceneLeaderboardScopeSelector() + { + LeaderboardScopeSelector selector; + Bindable scope = new Bindable(); + + Add(selector = new LeaderboardScopeSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = scope } + }); + + AddStep(@"Select global", () => scope.Value = BeatmapLeaderboardScope.Global); + AddStep(@"Select country", () => scope.Value = BeatmapLeaderboardScope.Country); + AddStep(@"Select friend", () => scope.Value = BeatmapLeaderboardScope.Friend); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs new file mode 100644 index 0000000000..c74c7cbc2b --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -0,0 +1,157 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.UserInterface; +using osu.Game.Screens.Select.Leaderboards; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osuTK; +using osu.Game.Graphics.UserInterface; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Sprites; +using osu.Framework.Extensions; +using osu.Game.Graphics; +using osu.Framework.Allocation; +using osuTK.Graphics; +using osu.Framework.Input.Events; +using osu.Framework.Graphics.Colour; + +namespace osu.Game.Overlays.BeatmapSet +{ + public class LeaderboardScopeSelector : TabControl + { + protected override Dropdown CreateDropdown() => null; + + protected override TabItem CreateTabItem(BeatmapLeaderboardScope value) => new ScopeSelectorTabItem(value); + + public LeaderboardScopeSelector() + { + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + + AddItem(BeatmapLeaderboardScope.Global); + AddItem(BeatmapLeaderboardScope.Country); + AddItem(BeatmapLeaderboardScope.Friend); + + AddInternal(new Line + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + }); + } + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20, 0), + }; + + private class ScopeSelectorTabItem : TabItem + { + private const float transition_duration = 100; + + private readonly Box box; + + protected readonly OsuSpriteText Text; + + public ScopeSelectorTabItem(BeatmapLeaderboardScope value) + : base(value) + { + AutoSizeAxes = Axes.Both; + + Children = new Drawable[] + { + Text = new OsuSpriteText + { + Margin = new MarginPadding { Bottom = 8 }, + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + Text = value.GetDescription() + " Ranking", + Font = OsuFont.GetFont(weight: FontWeight.Regular), + }, + box = new Box + { + RelativeSizeAxes = Axes.X, + Height = 5, + Scale = new Vector2(1f, 0f), + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + }, + new HoverClickSounds() + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + box.Colour = colours.Blue; + } + + protected override bool OnHover(HoverEvent e) + { + Text.FadeColour(Color4.LightSkyBlue); + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + Text.FadeColour(Color4.White); + } + + protected override void OnActivated() + { + box.ScaleTo(new Vector2(1f), transition_duration); + Text.Font = Text.Font.With(weight: FontWeight.Black); + } + + protected override void OnDeactivated() + { + box.ScaleTo(new Vector2(1f, 0f), transition_duration); + Text.Font = Text.Font.With(weight: FontWeight.Regular); + } + } + + private class Line : GridContainer + { + public Line() + { + Height = 1; + RelativeSizeAxes = Axes.X; + Width = 0.8f; + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(mode: GridSizeMode.Relative, size: 0.4f), + new Dimension(), + }; + Content = new[] + { + new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(Color4.Transparent, Color4.Gray), + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Gray, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(Color4.Gray, Color4.Transparent), + }, + } + }; + } + } + } +} From 87974850ddcfdbd55cb332b72016c21f880c91a6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 7 Aug 2019 08:42:43 +0300 Subject: [PATCH 2212/5608] Initial implementation --- .../Online/TestSceneLeaderboardModSelector.cs | 63 ++++++++ .../BeatmapSet/LeaderboardModSelector.cs | 136 ++++++++++++++++++ osu.Game/Overlays/Mods/ModButton.cs | 2 +- osu.Game/Rulesets/Mods/ModType.cs | 3 +- osu.Game/Rulesets/UI/ModIcon.cs | 27 ++-- 5 files changed, 213 insertions(+), 18 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs create mode 100644 osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs new file mode 100644 index 0000000000..eb7fe5591d --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -0,0 +1,63 @@ +// 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.Overlays.BeatmapSet; +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Taiko; +using osu.Game.Rulesets.Catch; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Bindables; +using osu.Game.Rulesets; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneLeaderboardModSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(LeaderboardModSelector), + }; + + public TestSceneLeaderboardModSelector() + { + LeaderboardModSelector modSelector; + FillFlowContainer selectedMods; + Bindable ruleset = new Bindable(); + + Add(selectedMods = new FillFlowContainer + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }); + + Add(modSelector = new LeaderboardModSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Ruleset = { BindTarget = ruleset } + }); + + modSelector.SelectedMods.BindValueChanged(mods => + { + selectedMods.Clear(); + + foreach (var mod in mods.NewValue) + selectedMods.Add(new SpriteText + { + Text = mod.Acronym, + }); + }); + + AddStep("osu mods", () => ruleset.Value = new OsuRuleset().RulesetInfo); + AddStep("mania mods", () => ruleset.Value = new ManiaRuleset().RulesetInfo); + AddStep("taiko mods", () => ruleset.Value = new TaikoRuleset().RulesetInfo); + AddStep("catch mods", () => ruleset.Value = new CatchRuleset().RulesetInfo); + AddStep("Deselect all", () => modSelector.DeselectAll()); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs new file mode 100644 index 0000000000..99c51813c5 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -0,0 +1,136 @@ +// 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.Containers; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Framework.Bindables; +using System.Collections.Generic; +using osu.Game.Rulesets; +using osuTK; +using osu.Game.Rulesets.UI; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; +using osuTK.Graphics; +using System; +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Overlays.BeatmapSet +{ + public class LeaderboardModSelector : Container + { + public readonly Bindable> SelectedMods = new Bindable>(); + public readonly Bindable Ruleset = new Bindable(); + + private readonly FillFlowContainer modsContainer; + + public LeaderboardModSelector() + { + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + Child = modsContainer = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Full, + Spacing = new Vector2(4), + }; + + Ruleset.BindValueChanged(onRulesetChanged); + } + + private void onRulesetChanged(ValueChangedEvent ruleset) + { + SelectedMods.Value = new List(); + + modsContainer.Clear(); + + if (ruleset.NewValue == null) + return; + + modsContainer.Add(new ModButton(new NoMod())); + + foreach (var mod in ruleset.NewValue.CreateInstance().GetAllMods()) + if (mod.Ranked) + modsContainer.Add(new ModButton(mod)); + + foreach (var mod in modsContainer) + mod.OnSelectionChanged += selectionChanged; + } + + private void selectionChanged(Mod mod, bool selected) + { + var mods = SelectedMods.Value.ToList(); + + if (selected) + mods.Add(mod); + else + mods.Remove(mod); + + SelectedMods.Value = mods; + } + + public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); + + private class ModButton : ModIcon + { + private const float mod_scale = 0.4f; + private const int duration = 200; + + public readonly BindableBool Selected = new BindableBool(); + public Action OnSelectionChanged; + + public ModButton(Mod mod) + : base(mod) + { + Scale = new Vector2(mod_scale); + Add(new HoverClickSounds()); + + Selected.BindValueChanged(selected => + { + updateState(); + OnSelectionChanged?.Invoke(mod, selected.NewValue); + }, true); + } + + protected override bool OnClick(ClickEvent e) + { + Selected.Value = !Selected.Value; + return base.OnClick(e); + } + + protected override bool OnHover(HoverEvent e) + { + updateState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + updateState(); + } + + private void updateState() + { + this.FadeColour(IsHovered || Selected.Value ? Color4.White : Color4.Gray, duration, Easing.OutQuint); + } + } + + private class NoMod : Mod + { + public override string Name => "NoMod"; + + public override string Acronym => "NM"; + + public override double ScoreMultiplier => 1; + + public override IconUsage Icon => FontAwesome.Solid.Ban; + + public override ModType Type => ModType.Custom; + } + } +} diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index fa1ee500a8..7b8745cf42 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -96,7 +96,7 @@ namespace osu.Game.Overlays.Mods } } - foregroundIcon.Highlighted = Selected; + foregroundIcon.Highlighted.Value = Selected; SelectionChanged?.Invoke(SelectedMod); return true; diff --git a/osu.Game/Rulesets/Mods/ModType.cs b/osu.Game/Rulesets/Mods/ModType.cs index e3c82e42f5..1cdc4415ac 100644 --- a/osu.Game/Rulesets/Mods/ModType.cs +++ b/osu.Game/Rulesets/Mods/ModType.cs @@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Mods Conversion, Automation, Fun, - System + System, + Custom } } diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 86feea09a8..962263adba 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -11,11 +11,14 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osuTK; +using osu.Framework.Bindables; namespace osu.Game.Rulesets.UI { public class ModIcon : Container, IHasTooltip { + public readonly BindableBool Highlighted = new BindableBool(); + private readonly SpriteIcon modIcon; private readonly SpriteIcon background; @@ -96,27 +99,19 @@ namespace osu.Game.Rulesets.UI backgroundColour = colours.Pink; highlightedColour = colours.PinkLight; break; - } - applyStyle(); - } - - private bool highlighted; - - public bool Highlighted - { - get => highlighted; - - set - { - highlighted = value; - applyStyle(); + case ModType.Custom: + backgroundColour = colours.Gray6; + highlightedColour = colours.Gray7; + modIcon.Colour = colours.Yellow; + break; } } - private void applyStyle() + protected override void LoadComplete() { - background.Colour = highlighted ? highlightedColour : backgroundColour; + base.LoadComplete(); + Highlighted.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); } } } From 1d42f0959af01834fbd4f86bd08c84b2f6b14932 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 7 Aug 2019 08:46:27 +0300 Subject: [PATCH 2213/5608] ModIcon improvements --- osu.Game/Overlays/Mods/ModButton.cs | 2 +- osu.Game/Rulesets/UI/ModIcon.cs | 23 ++++++----------------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index fa1ee500a8..7b8745cf42 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -96,7 +96,7 @@ namespace osu.Game.Overlays.Mods } } - foregroundIcon.Highlighted = Selected; + foregroundIcon.Highlighted.Value = Selected; SelectionChanged?.Invoke(SelectedMod); return true; diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 86feea09a8..5bb1de7a38 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -11,11 +11,14 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osuTK; +using osu.Framework.Bindables; namespace osu.Game.Rulesets.UI { public class ModIcon : Container, IHasTooltip { + public readonly BindableBool Highlighted = new BindableBool(); + private readonly SpriteIcon modIcon; private readonly SpriteIcon background; @@ -97,26 +100,12 @@ namespace osu.Game.Rulesets.UI highlightedColour = colours.PinkLight; break; } - - applyStyle(); } - private bool highlighted; - - public bool Highlighted + protected override void LoadComplete() { - get => highlighted; - - set - { - highlighted = value; - applyStyle(); - } - } - - private void applyStyle() - { - background.Colour = highlighted ? highlightedColour : backgroundColour; + base.LoadComplete(); + Highlighted.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); } } } From a99d6536c22011b34879899017d789b296ad6fba Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 7 Aug 2019 08:49:04 +0300 Subject: [PATCH 2214/5608] CI fix --- .../Visual/Online/TestSceneLeaderboardScopeSelector.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs index f4c0d32946..cc3b2ac68b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs @@ -19,10 +19,9 @@ namespace osu.Game.Tests.Visual.Online public TestSceneLeaderboardScopeSelector() { - LeaderboardScopeSelector selector; Bindable scope = new Bindable(); - Add(selector = new LeaderboardScopeSelector + Add(new LeaderboardScopeSelector { Anchor = Anchor.Centre, Origin = Anchor.Centre, From cf9a5baafae910e287196d8fe702b44e2c1f2b86 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 7 Aug 2019 14:51:24 +0900 Subject: [PATCH 2215/5608] Explicity dispose osuGame instances --- osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs | 3 +++ osu.Game/Overlays/MusicController.cs | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index 08afe90de8..663447d0b4 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -51,7 +51,10 @@ namespace osu.Game.Tests.Visual.Menus AddStep("Create new game instance", () => { if (osuGame != null) + { Remove(osuGame); + osuGame.Dispose(); + } osuGame = new TestOsuGame(); osuGame.SetHost(gameHost); diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 91ae92320a..abbcec5094 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -316,10 +316,6 @@ namespace osu.Game.Overlays private void next(bool instant = false) { - // beatmapSets doesn't get populated until loading has completed. - if (!IsLoaded) - return; - if (!instant) queuedDirection = TransformDirection.Next; From 487979b0164091f9c2928204e660d218ca9faada Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 7 Aug 2019 09:31:07 +0300 Subject: [PATCH 2216/5608] Add Testing --- .../Visual/Online/TestSceneUserRequest.cs | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs b/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs new file mode 100644 index 0000000000..18d6028cb8 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs @@ -0,0 +1,109 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mania; +using osu.Game.Users; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Rulesets.Taiko; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tests.Visual.Online +{ + [TestFixture] + public class TestSceneUserRequest : OsuTestScene + { + [Resolved] + private IAPIProvider api { get; set; } + + private readonly Bindable user = new Bindable(); + private GetUserRequest request; + private readonly DimmedLoadingLayer loading; + + public TestSceneUserRequest() + { + Add(new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new UserTestContainer + { + User = { BindTarget = user } + }, + loading = new DimmedLoadingLayer + { + Alpha = 0 + } + } + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + AddStep(@"local user", () => getUser()); + AddStep(@"local user with taiko ruleset", () => getUser(ruleset: new TaikoRuleset().RulesetInfo)); + AddStep(@"cookiezi", () => getUser(124493)); + AddStep(@"cookiezi with mania ruleset", () => getUser(124493, new ManiaRuleset().RulesetInfo)); + } + + private void getUser(long? userId = null, RulesetInfo ruleset = null) + { + loading.Show(); + + request?.Cancel(); + request = new GetUserRequest(userId, ruleset); + request.Success += user => + { + this.user.Value = user; + loading.Hide(); + }; + api.Queue(request); + } + + private class UserTestContainer : FillFlowContainer + { + public readonly Bindable User = new Bindable(); + + public UserTestContainer() + { + AutoSizeAxes = Axes.Both; + Direction = FillDirection.Vertical; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + User.BindValueChanged(onUserUpdate, true); + } + + private void onUserUpdate(ValueChangedEvent user) + { + Clear(); + + AddRange(new Drawable[] + { + new SpriteText + { + Text = $@"Username: {user.NewValue?.Username}" + }, + new SpriteText + { + Text = $@"RankedScore: {user.NewValue?.Statistics.RankedScore}" + }, + }); + } + } + } +} From 606e977e2d27427229ba09ef62b064b9c4fd826c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Aug 2019 16:07:41 +0900 Subject: [PATCH 2217/5608] Fix twitter link shortener being used --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 52fc29cb98..c4d676f4be 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ If you are not interested in developing the game, you can still consume our [bin | ------------- | ------------- | - **Linux** users are recommended to self-compile until we have official deployment in place. -- **iOS** users can join the [TestFlight beta program](https://t.co/PasE1zrHhw) (note that due to high demand this is regularly full). +- **iOS** users can join the [TestFlight beta program](https://testflight.apple.com/join/2tLcjWlF) (note that due to high demand this is regularly full). - **Android** users can self-compile, and expect a public beta soon. If your platform is not listed above, there is still a chance you can manually build it by following the instructions below. From 669c2462eca3cae95a5944e2581585eeb7d5312c Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 7 Aug 2019 16:25:38 +0900 Subject: [PATCH 2218/5608] Don't consider the type --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index c92c0ba22d..24843f8c32 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -293,7 +293,7 @@ namespace osu.Game.Beatmaps.Formats if (!Enum.TryParse(split[0], out type)) { - Logger.Log($"A beatmap {type} event could not be parsed and will be ignored: {split[0]}", LoggingTarget.Runtime, LogLevel.Important); + Logger.Log($"A beatmap event could not be parsed and will be ignored: {split[0]}", LoggingTarget.Runtime, LogLevel.Important); return; } From c0d3d47c2995dc581f716b4a17ecad8f2d742064 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 7 Aug 2019 16:49:53 +0900 Subject: [PATCH 2219/5608] Don't consider type for storyboards either --- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 512eea0822..1dcafb4669 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -84,7 +84,7 @@ namespace osu.Game.Beatmaps.Formats EventType type; if (!Enum.TryParse(split[0], out type)) - Logger.Log($"A storyboard {type} event could not be parsed and will be ignored: {split[0]}", LoggingTarget.Runtime, LogLevel.Important); + Logger.Log($"A storyboard event could not be parsed and will be ignored: {split[0]}", LoggingTarget.Runtime, LogLevel.Important); switch (type) { From c6d481238d91e63051c920ea6f1d670f28e673cf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Aug 2019 16:56:22 +0900 Subject: [PATCH 2220/5608] Move QuadBatch to a local variable to stop resharper complaining --- osu.Game/Rulesets/Mods/ModFlashlight.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index cb0c2fafe5..7247bafd23 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -155,12 +155,13 @@ namespace osu.Game.Rulesets.Mods private Vector2 flashlightSize; private float flashlightDim; - private readonly VertexBatch quadBatch = new QuadBatch(1, 1); private readonly Action addAction; public FlashlightDrawNode(Flashlight source) : base(source) { + var quadBatch = new QuadBatch(1, 1); + addAction = v => quadBatch.Add(new PositionAndColourVertex { Position = v.Position, From 7bcec31ea370d87a1a58958c0a405f3ff780de0c Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 7 Aug 2019 17:08:41 +0900 Subject: [PATCH 2221/5608] mention that the event was the type --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 24843f8c32..b1261855f2 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -293,7 +293,7 @@ namespace osu.Game.Beatmaps.Formats if (!Enum.TryParse(split[0], out type)) { - Logger.Log($"A beatmap event could not be parsed and will be ignored: {split[0]}", LoggingTarget.Runtime, LogLevel.Important); + Logger.Log($"Unknown beatmap event of type {split[0]} could not be parsed and will be ignored.", LoggingTarget.Runtime, LogLevel.Important); return; } diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 512eea0822..584388333d 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -84,7 +84,7 @@ namespace osu.Game.Beatmaps.Formats EventType type; if (!Enum.TryParse(split[0], out type)) - Logger.Log($"A storyboard {type} event could not be parsed and will be ignored: {split[0]}", LoggingTarget.Runtime, LogLevel.Important); + Logger.Log($"Unknown storyboard event of type {split[0]} could not be parsed and will be ignored.", LoggingTarget.Runtime, LogLevel.Important); switch (type) { From b0e06597159d5259965c6b716f0a35c092645827 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Aug 2019 17:33:30 +0900 Subject: [PATCH 2222/5608] Dispose instead --- osu.Game/Rulesets/Mods/ModFlashlight.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 7247bafd23..4f939362bb 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -155,13 +155,12 @@ namespace osu.Game.Rulesets.Mods private Vector2 flashlightSize; private float flashlightDim; + private readonly VertexBatch quadBatch = new QuadBatch(1, 1); private readonly Action addAction; public FlashlightDrawNode(Flashlight source) : base(source) { - var quadBatch = new QuadBatch(1, 1); - addAction = v => quadBatch.Add(new PositionAndColourVertex { Position = v.Position, @@ -194,6 +193,12 @@ namespace osu.Game.Rulesets.Mods shader.Unbind(); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + quadBatch?.Dispose(); + } } } } From 38df49995ce77e2176b491375144a80227579f58 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Aug 2019 18:29:50 +0900 Subject: [PATCH 2223/5608] Fix cursor scale not matching osu-stable --- .../UI/OsuPlayfieldAdjustmentContainer.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs index f7888f8022..9c8be868b0 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs @@ -13,13 +13,15 @@ namespace osu.Game.Rulesets.Osu.UI protected override Container Content => content; private readonly Container content; + private const float playfield_size_adjust = 0.8f; + public OsuPlayfieldAdjustmentContainer() { Anchor = Anchor.Centre; Origin = Anchor.Centre; // Calculated from osu!stable as 512 (default gamefield size) / 640 (default window size) - Size = new Vector2(0.8f); + Size = new Vector2(playfield_size_adjust); InternalChild = new Container { @@ -41,7 +43,19 @@ namespace osu.Game.Rulesets.Osu.UI { base.Update(); + // The following calculation results in a constant of 1.6 when OsuPlayfieldAdjustmentContainer + // is consuming the full game_size. This matches the osu-stable "magic ratio". + // + // game_size = DrawSizePreservingFillContainer.TargetSize = new Vector2(1024, 768) + // + // Parent is a 4:3 aspect enforced, using height as the constricting dimension + // Parent.ChildSize.X = min(game_size.X, game_size.Y * (4 / 3)) * playfield_size_adjust + // Parent.ChildSize.X = 819.2 + // + // Scale = 819.2 / 512 + // Scale = 1.6 Scale = new Vector2(Parent.ChildSize.X / OsuPlayfield.BASE_SIZE.X); + // Size = 0.625 Size = Vector2.Divide(Vector2.One, Scale); } } From da15e19912783b3848d9315ed365013c712dfa2c Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 7 Aug 2019 18:40:58 +0900 Subject: [PATCH 2224/5608] return on storyboard side --- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 584388333d..f950437e75 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -83,8 +83,12 @@ namespace osu.Game.Beatmaps.Formats storyboardSprite = null; EventType type; + if (!Enum.TryParse(split[0], out type)) + { Logger.Log($"Unknown storyboard event of type {split[0]} could not be parsed and will be ignored.", LoggingTarget.Runtime, LogLevel.Important); + return; + } switch (type) { From ec13143ab3ffffebc718b97e3cd1964d4b88905a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Aug 2019 18:45:56 +0900 Subject: [PATCH 2225/5608] Add further xmldoc --- osu.Game/Skinning/LegacySkin.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 19f04c9b7a..3eda76e40f 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -20,6 +20,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.UI; using osuTK; using osuTK.Graphics; @@ -360,6 +361,10 @@ namespace osu.Game.Skinning } } + /// + /// A sprite which is displayed within the playfield, but historically was not considered part of the playfield. + /// Performs scale adjustment to undo the scale applied by (osu! ruleset specifically). + /// private class NonPlayfieldSprite : Sprite { public override Texture Texture @@ -368,7 +373,8 @@ namespace osu.Game.Skinning set { if (value != null) - value.ScaleAdjust *= 2f; + // stable "magic ratio". see OsuPlayfieldAdjustmentContainer for full explanation. + value.ScaleAdjust *= 1.6f; base.Texture = value; } } From 15a592e25eec64efd0d7e53ae9d52356a4dbf6ec Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 7 Aug 2019 19:25:40 +0900 Subject: [PATCH 2226/5608] Just assert doesn't throw and don't catch at LegacyDecoder --- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 10 ++-------- osu.Game.Tests/Resources/valid-events.osu | 12 ------------ osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 9 +-------- 3 files changed, 3 insertions(+), 28 deletions(-) delete mode 100644 osu.Game.Tests/Resources/valid-events.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 49a6f646ba..535320530d 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -484,20 +484,14 @@ namespace osu.Game.Tests.Beatmaps.Formats } [Test] - public void TestDecodeInvalidEvents() + public void TestInvalidEventStillPasses() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; - using (var goodResStream = TestResources.OpenResource("valid-events.osu")) - using (var goodStream = new StreamReader(goodResStream)) using (var badResStream = TestResources.OpenResource("invalid-events.osu")) using (var badStream = new StreamReader(badResStream)) { - var goodBeatmap = decoder.Decode(goodStream); - var badBeatmap = decoder.Decode(badStream); - - Assert.AreEqual(goodBeatmap.Breaks[0].Duration, badBeatmap.Breaks[0].Duration); - Assert.AreEqual(goodBeatmap.Metadata.BackgroundFile, badBeatmap.Metadata.BackgroundFile); + Assert.DoesNotThrow(() => decoder.Decode(badStream)); } } } diff --git a/osu.Game.Tests/Resources/valid-events.osu b/osu.Game.Tests/Resources/valid-events.osu deleted file mode 100644 index ed3614b4ed..0000000000 --- a/osu.Game.Tests/Resources/valid-events.osu +++ /dev/null @@ -1,12 +0,0 @@ -osu file format v14 - -[Events] -//Background and Video events -0,0,"machinetop_background.jpg",0,0 -//Break Periods -2,122474,140135 -//Storyboard Layer 0 (Background) -//Storyboard Layer 1 (Fail) -//Storyboard Layer 2 (Pass) -//Storyboard Layer 3 (Foreground) -//Storyboard Sound Samples diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 7999c82761..17e278c48e 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -43,14 +43,7 @@ namespace osu.Game.Beatmaps.Formats continue; } - try - { - ParseLine(output, section, line); - } - catch (Exception e) - { - Logger.Error(e, $"Failed to process line \"{line}\" into {output}"); - } + ParseLine(output, section, line); } } From 994c1f21ec5d9391787d73a79b4e5846e2627c08 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 7 Aug 2019 19:33:16 +0900 Subject: [PATCH 2227/5608] Output stacked positions for conversion values --- .../OsuBeatmapConversionTest.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index 392170f0a8..8f975b14a2 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -8,7 +8,6 @@ using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.UI; using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Osu.Tests @@ -31,22 +30,22 @@ namespace osu.Game.Rulesets.Osu.Tests { case Slider slider: foreach (var nested in slider.NestedHitObjects) - yield return createConvertValue(nested); + yield return createConvertValue((OsuHitObject)nested); break; default: - yield return createConvertValue(hitObject); + yield return createConvertValue((OsuHitObject)hitObject); break; } - ConvertValue createConvertValue(HitObject obj) => new ConvertValue + ConvertValue createConvertValue(OsuHitObject obj) => new ConvertValue { StartTime = obj.StartTime, EndTime = (obj as IHasEndTime)?.EndTime ?? obj.StartTime, - X = (obj as IHasPosition)?.X ?? OsuPlayfield.BASE_SIZE.X / 2, - Y = (obj as IHasPosition)?.Y ?? OsuPlayfield.BASE_SIZE.Y / 2, + X = obj.StackedPosition.X, + Y = obj.StackedPosition.Y }; } From 42de5934f6f93c95049f254d748256ca9eb7d8b0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 7 Aug 2019 19:33:35 +0900 Subject: [PATCH 2228/5608] Fix incorrect hitobject indices --- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index 7bb1f42802..a9f8b87fb4 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -211,14 +211,14 @@ namespace osu.Game.Rulesets.Osu.Beatmaps if (Vector2Extensions.Distance(beatmap.HitObjects[j].Position, currHitObject.Position) < stack_distance) { currHitObject.StackHeight++; - startTime = (beatmap.HitObjects[j] as IHasEndTime)?.EndTime ?? beatmap.HitObjects[i].StartTime; + startTime = (beatmap.HitObjects[j] as IHasEndTime)?.EndTime ?? beatmap.HitObjects[j].StartTime; } else if (Vector2Extensions.Distance(beatmap.HitObjects[j].Position, currHitObject.EndPosition) < stack_distance) { //Case for sliders - bump notes down and right, rather than up and left. sliderStack++; beatmap.HitObjects[j].StackHeight -= sliderStack; - startTime = (beatmap.HitObjects[j] as IHasEndTime)?.EndTime ?? beatmap.HitObjects[i].StartTime; + startTime = (beatmap.HitObjects[j] as IHasEndTime)?.EndTime ?? beatmap.HitObjects[j].StartTime; } } } From b8ccba02f2017dea054b3fce5413e90dff08670c Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 7 Aug 2019 19:33:54 +0900 Subject: [PATCH 2229/5608] Log to runtime instead --- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 17e278c48e..8365fb17d3 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -43,7 +43,14 @@ namespace osu.Game.Beatmaps.Formats continue; } - ParseLine(output, section, line); + try + { + ParseLine(output, section, line); + } + catch (Exception e) + { + Logger.Log($"Failed to process line \"{line}\" into {output}", LoggingTarget.Runtime, LogLevel.Important); + } } } From bc3a340286afb799b3af13197fd10f950b0e19f2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 7 Aug 2019 19:35:39 +0900 Subject: [PATCH 2230/5608] Fix incorrect path position being used for old stacking algorithm --- .../OsuBeatmapConversionTest.cs | 1 + .../Beatmaps/OsuBeatmapProcessor.cs | 8 +- .../old-stacking-expected-conversion.json | 278 ++++++++++++++++++ .../Testing/Beatmaps/old-stacking.osu | 40 +++ 4 files changed, 326 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/old-stacking-expected-conversion.json create mode 100644 osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/old-stacking.osu diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index 8f975b14a2..e9fdf924c3 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Osu.Tests [TestCase("slider-ticks")] [TestCase("repeat-slider")] [TestCase("uneven-repeat-slider")] + [TestCase("old-stacking")] public void Test(string name) => base.Test(name); protected override IEnumerable CreateConvertValue(HitObject hitObject) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index a9f8b87fb4..bb19b783aa 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; +using osuTK; namespace osu.Game.Rulesets.Osu.Beatmaps { @@ -208,12 +209,17 @@ namespace osu.Game.Rulesets.Osu.Beatmaps if (beatmap.HitObjects[j].StartTime - stackThreshold > startTime) break; + // The start position of the hitobject, or the position at the end of the path if the hitobject is a slider + Vector2 position2 = currHitObject is Slider currSlider + ? currSlider.Position + currSlider.Path.PositionAt(1) + : currHitObject.Position; + if (Vector2Extensions.Distance(beatmap.HitObjects[j].Position, currHitObject.Position) < stack_distance) { currHitObject.StackHeight++; startTime = (beatmap.HitObjects[j] as IHasEndTime)?.EndTime ?? beatmap.HitObjects[j].StartTime; } - else if (Vector2Extensions.Distance(beatmap.HitObjects[j].Position, currHitObject.EndPosition) < stack_distance) + else if (Vector2Extensions.Distance(beatmap.HitObjects[j].Position, position2) < stack_distance) { //Case for sliders - bump notes down and right, rather than up and left. sliderStack++; diff --git a/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/old-stacking-expected-conversion.json b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/old-stacking-expected-conversion.json new file mode 100644 index 0000000000..b994cbd85a --- /dev/null +++ b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/old-stacking-expected-conversion.json @@ -0,0 +1,278 @@ +{ + "Mappings": [{ + "StartTime": 32165, + "Objects": [{ + "StartTime": 32165, + "EndTime": 32165, + "X": 32, + "Y": 320 + }] + }, + { + "StartTime": 32517, + "Objects": [{ + "StartTime": 32517, + "EndTime": 32517, + "X": 246.396057, + "Y": 182.396057 + }] + }, + { + "StartTime": 32605, + "Objects": [{ + "StartTime": 32605, + "EndTime": 32605, + "X": 249.597382, + "Y": 185.597382 + }] + }, + { + "StartTime": 32693, + "Objects": [{ + "StartTime": 32693, + "EndTime": 32693, + "X": 252.798691, + "Y": 188.798691 + }] + }, + { + "StartTime": 32781, + "Objects": [{ + "StartTime": 32781, + "EndTime": 32781, + "X": 256, + "Y": 192 + }] + }, + { + "StartTime": 33248, + "Objects": [{ + "StartTime": 33248, + "EndTime": 33248, + "X": 39.3960648, + "Y": 76.3960648 + }] + }, + { + "StartTime": 33307, + "Objects": [{ + "StartTime": 33307, + "EndTime": 33307, + "X": 42.5973778, + "Y": 79.597374 + }] + }, + { + "StartTime": 33383, + "Objects": [{ + "StartTime": 33383, + "EndTime": 33383, + "X": 45.798687, + "Y": 82.79869 + }] + }, + { + "StartTime": 33459, + "Objects": [{ + "StartTime": 33459, + "EndTime": 33459, + "X": 49, + "Y": 86 + }, + { + "StartTime": 33635, + "EndTime": 33635, + "X": 123.847847, + "Y": 85.7988 + }, + { + "StartTime": 33811, + "EndTime": 33811, + "X": 198.6957, + "Y": 85.5975952 + }, + { + "StartTime": 33988, + "EndTime": 33988, + "X": 273.9688, + "Y": 85.39525 + }, + { + "StartTime": 34164, + "EndTime": 34164, + "X": 348.816681, + "Y": 85.19404 + }, + { + "StartTime": 34246, + "EndTime": 34246, + "X": 398.998718, + "Y": 85.05914 + } + ] + }, + { + "StartTime": 34341, + "Objects": [{ + "StartTime": 34341, + "EndTime": 34341, + "X": 401.201324, + "Y": 88.20131 + }] + }, + { + "StartTime": 34400, + "Objects": [{ + "StartTime": 34400, + "EndTime": 34400, + "X": 404.402618, + "Y": 91.402626 + }] + }, + { + "StartTime": 34459, + "Objects": [{ + "StartTime": 34459, + "EndTime": 34459, + "X": 407.603943, + "Y": 94.6039352 + }] + }, + { + "StartTime": 34989, + "Objects": [{ + "StartTime": 34989, + "EndTime": 34989, + "X": 163, + "Y": 138 + }, + { + "StartTime": 35018, + "EndTime": 35018, + "X": 188, + "Y": 138 + } + ] + }, + { + "StartTime": 35106, + "Objects": [{ + "StartTime": 35106, + "EndTime": 35106, + "X": 163, + "Y": 138 + }, + { + "StartTime": 35135, + "EndTime": 35135, + "X": 188, + "Y": 138 + } + ] + }, + { + "StartTime": 35224, + "Objects": [{ + "StartTime": 35224, + "EndTime": 35224, + "X": 163, + "Y": 138 + }, + { + "StartTime": 35253, + "EndTime": 35253, + "X": 188, + "Y": 138 + } + ] + }, + { + "StartTime": 35695, + "Objects": [{ + "StartTime": 35695, + "EndTime": 35695, + "X": 166, + "Y": 76 + }, + { + "StartTime": 35871, + "EndTime": 35871, + "X": 240.99855, + "Y": 75.53417 + }, + { + "StartTime": 36011, + "EndTime": 36011, + "X": 315.9971, + "Y": 75.0683441 + } + ] + }, + { + "StartTime": 36106, + "Objects": [{ + "StartTime": 36106, + "EndTime": 36106, + "X": 315, + "Y": 75 + }, + { + "StartTime": 36282, + "EndTime": 36282, + "X": 240.001526, + "Y": 75.47769 + }, + { + "StartTime": 36422, + "EndTime": 36422, + "X": 165.003052, + "Y": 75.95539 + } + ] + }, + { + "StartTime": 36518, + "Objects": [{ + "StartTime": 36518, + "EndTime": 36518, + "X": 166, + "Y": 76 + }, + { + "StartTime": 36694, + "EndTime": 36694, + "X": 240.99855, + "Y": 75.53417 + }, + { + "StartTime": 36834, + "EndTime": 36834, + "X": 315.9971, + "Y": 75.0683441 + } + ] + }, + { + "StartTime": 36929, + "Objects": [{ + "StartTime": 36929, + "EndTime": 36929, + "X": 315, + "Y": 75 + }, + { + "StartTime": 37105, + "EndTime": 37105, + "X": 240.001526, + "Y": 75.47769 + }, + { + "StartTime": 37245, + "EndTime": 37245, + "X": 165.003052, + "Y": 75.95539 + } + ] + } + ] +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/old-stacking.osu b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/old-stacking.osu new file mode 100644 index 0000000000..4bc9226d67 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/old-stacking.osu @@ -0,0 +1,40 @@ +osu file format v3 + +[Difficulty] +HPDrainRate:3 +CircleSize:5 +OverallDifficulty:8 +ApproachRate:8 +SliderMultiplier:1.5 +SliderTickRate:2 + +[TimingPoints] +48,352.941176470588,4,1,1,100,1,0 + +[HitObjects] +// Hit circles +32,320,32165,5,2,0:0:0:0: +256,192,32517,5,0,0:0:0:0: +256,192,32605,1,0,0:0:0:0: +256,192,32693,1,0,0:0:0:0: +256,192,32781,1,0,0:0:0:0: + +// Hit circles on slider endpoints +49,86,33248,1,0,0:0:0:0: +49,86,33307,1,0,0:0:0:0: +49,86,33383,1,0,0:0:0:0: +49,86,33459,2,0,L|421:85,1,350 +398,85,34341,1,0,0:0:0:0: +398,85,34400,1,0,0:0:0:0: +398,85,34459,1,0,0:0:0:0: + +// Sliders +163,138,34989,2,0,L|196:138,1,25 +163,138,35106,2,0,L|196:138,1,25 +163,138,35224,2,0,L|196:138,1,25 + +// Reversed sliders +166,76,35695,2,0,L|327:75,1,150 +315,75,36106,2,0,L|158:76,1,150 +166,76,36518,2,0,L|327:75,1,150 +315,75,36929,2,0,L|158:76,1,150 From bde89adcb72b85fb76476065e017b8533ea79338 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 7 Aug 2019 19:45:29 +0900 Subject: [PATCH 2231/5608] show exception message --- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 8365fb17d3..d6d6804d16 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -49,7 +49,7 @@ namespace osu.Game.Beatmaps.Formats } catch (Exception e) { - Logger.Log($"Failed to process line \"{line}\" into {output}", LoggingTarget.Runtime, LogLevel.Important); + Logger.Log($"Failed to process line \"{line}\" into {output}: {e.Message}", LoggingTarget.Runtime, LogLevel.Important); } } } From 2ab288902759280a2258a07fdd2dbb501d2f398b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Aug 2019 19:56:17 +0900 Subject: [PATCH 2232/5608] 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 e64102c401..c4cdffa8a5 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index cf325b77be..02bf053468 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 66f398a927..5b43a6f46f 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 411916d4a31b39725b58cbc549fd0a9001e691f5 Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Wed, 7 Aug 2019 19:32:48 +0800 Subject: [PATCH 2233/5608] Move static method to Game class --- .../Graphics/Containers/LinkFlowContainer.cs | 2 +- osu.Game/Online/Chat/MessageFormatter.cs | 52 ------------------ osu.Game/OsuGame.cs | 55 +++++++++++++++++-- 3 files changed, 52 insertions(+), 57 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index ab4629cfff..ca9ffd06c6 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -85,7 +85,7 @@ namespace osu.Game.Graphics.Containers { RelativeSizeAxes = Axes.Both, TooltipText = tooltipText ?? (url != text ? url : string.Empty), - Action = action ?? (() => LinkUtils.HandleLink(url, linkType, linkArgument, game, channelManager, showNotImplementedError)), + Action = action ?? (() => game.HandleLink(url, linkType, linkArgument)), }); return drawables; diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 73396ce4d2..c875150091 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -3,9 +3,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text.RegularExpressions; -using osu.Framework.Logging; namespace osu.Game.Online.Chat { @@ -290,54 +288,4 @@ namespace osu.Game.Online.Chat public int CompareTo(Link otherLink) => Index > otherLink.Index ? 1 : -1; } - - public static class LinkUtils - { - public static void HandleLink(string url, LinkAction linkType, string linkArgument, OsuGame game, ChannelManager channelManager = null, Action showNotImplementedError = null) - { - switch (linkType) - { - case LinkAction.OpenBeatmap: - // TODO: proper query params handling - if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) - game?.ShowBeatmap(beatmapId); - break; - - case LinkAction.OpenBeatmapSet: - if (int.TryParse(linkArgument, out int setId)) - game?.ShowBeatmapSet(setId); - break; - - case LinkAction.OpenChannel: - try - { - channelManager?.OpenChannel(linkArgument); - } - catch (ChannelNotFoundException) - { - Logger.Log($"The requested channel \"{linkArgument}\" does not exist"); - } - - break; - - case LinkAction.OpenEditorTimestamp: - case LinkAction.JoinMultiplayerMatch: - case LinkAction.Spectate: - showNotImplementedError?.Invoke(); - break; - - case LinkAction.External: - game?.OpenUrlExternally(url); - break; - - case LinkAction.OpenUserProfile: - if (long.TryParse(linkArgument, out long userId)) - game?.ShowUser(userId); - break; - - default: - throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); - } - } - } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 846677a0a9..43f3f1f5b5 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -195,19 +195,66 @@ namespace osu.Game private ExternalLinkOpener externalLinkOpener; - public void HandleUrl(string url) + public void HandleLink(string url, LinkAction linkType, string linkArgument) { - Logger.Log($"Request to handle url: {url}"); - Action showNotImplementedError = () => notifications?.Post(new SimpleNotification { Text = @"This link type is not yet supported!", Icon = FontAwesome.Solid.LifeRing, }); + switch (linkType) + { + case LinkAction.OpenBeatmap: + // TODO: proper query params handling + if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) + ShowBeatmap(beatmapId); + break; + + case LinkAction.OpenBeatmapSet: + if (int.TryParse(linkArgument, out int setId)) + ShowBeatmapSet(setId); + break; + + case LinkAction.OpenChannel: + try + { + channelManager.OpenChannel(linkArgument); + } + catch (ChannelNotFoundException) + { + Logger.Log($"The requested channel \"{linkArgument}\" does not exist"); + } + + break; + + case LinkAction.OpenEditorTimestamp: + case LinkAction.JoinMultiplayerMatch: + case LinkAction.Spectate: + showNotImplementedError?.Invoke(); + break; + + case LinkAction.External: + OpenUrlExternally(url); + break; + + case LinkAction.OpenUserProfile: + if (long.TryParse(linkArgument, out long userId)) + ShowUser(userId); + break; + + default: + throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); + } + } + + public void HandleUrl(string url) + { + Logger.Log($"Request to handle url: {url}"); + LinkDetails linkDetails = GetLinkDetails(url); - Schedule(() => LinkUtils.HandleLink(url, linkDetails.Action, linkDetails.Argument, this, channelManager, showNotImplementedError)); + Schedule(() => HandleLink(url, linkDetails.Action, linkDetails.Argument)); } public void OpenUrlExternally(string url) From 37e430177384e047ce2ce932b280a22583c7d223 Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Wed, 7 Aug 2019 20:16:22 +0800 Subject: [PATCH 2234/5608] Fix code format --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 11 +---------- osu.Game/OsuGame.cs | 2 +- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index ca9ffd06c6..b03bc4e3aa 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -22,21 +22,12 @@ namespace osu.Game.Graphics.Containers } private OsuGame game; - private ChannelManager channelManager; - private Action showNotImplementedError; [BackgroundDependencyLoader(true)] - private void load(OsuGame game, NotificationOverlay notifications, ChannelManager channelManager) + private void load(OsuGame game) { // will be null in tests this.game = game; - this.channelManager = channelManager; - - showNotImplementedError = () => notifications?.Post(new SimpleNotification - { - Text = @"This link type is not yet supported!", - Icon = FontAwesome.Solid.LifeRing, - }); } public void AddLinks(string text, List links) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 43f3f1f5b5..82bf8abf94 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -231,7 +231,7 @@ namespace osu.Game case LinkAction.OpenEditorTimestamp: case LinkAction.JoinMultiplayerMatch: case LinkAction.Spectate: - showNotImplementedError?.Invoke(); + showNotImplementedError.Invoke(); break; case LinkAction.External: From 9f72e92e0e35dc4c71ba7d6d184334fbd5b732ca Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Wed, 7 Aug 2019 20:27:39 +0800 Subject: [PATCH 2235/5608] Fix code format --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index b03bc4e3aa..66911d9615 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -8,8 +8,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using System.Collections.Generic; using osu.Framework.Graphics; -using osu.Game.Overlays; -using osu.Game.Overlays.Notifications; using osu.Game.Users; namespace osu.Game.Graphics.Containers From c2b3c28c798e2994402ba2fbacd72d9093a99e94 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 7 Aug 2019 16:15:53 +0300 Subject: [PATCH 2236/5608] Use IsBreakTime for checking if currently in a break Rather than iterating over all breaks to find which is in current time --- osu.Game/Screens/Play/Player.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 96b8073d11..e7398be176 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -66,6 +66,8 @@ namespace osu.Game.Screens.Play private SampleChannel sampleRestart; + private BreakOverlay breakOverlay; + protected ScoreProcessor ScoreProcessor { get; private set; } protected DrawableRuleset DrawableRuleset { get; private set; } @@ -134,7 +136,7 @@ namespace osu.Game.Screens.Play } } }, - new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) + breakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -411,8 +413,7 @@ namespace osu.Game.Screens.Play PauseOverlay.Hide(); // breaks and time-based conditions may allow instant resume. - double time = GameplayClockContainer.GameplayClock.CurrentTime; - if (Beatmap.Value.Beatmap.Breaks.Any(b => b.Contains(time)) || time < Beatmap.Value.Beatmap.HitObjects.First().StartTime) + if (breakOverlay.IsBreakTime.Value || GameplayClockContainer.GameplayClock.CurrentTime < Beatmap.Value.Beatmap.HitObjects.First().StartTime) completeResume(); else DrawableRuleset.RequestResume(completeResume); From d3657d82cd042e13c1ea848c003b7e094483575b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 7 Aug 2019 16:28:16 +0300 Subject: [PATCH 2237/5608] Simplify final check for break time --- osu.Game/Screens/Play/BreakOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 93267e5f2a..ea9bba9c95 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -153,7 +153,7 @@ namespace osu.Game.Screens.Play // If the current break doesn't have effects, IsBreakTime should be false. // We also assume that the overlay's fade out transform is "not break time". var currentBreak = breaks[CurrentBreakIndex]; - isBreakTime.Value = currentBreak.HasEffect && time >= currentBreak.StartTime && time <= currentBreak.EndTime - fade_duration; + isBreakTime.Value = currentBreak.HasEffect && currentBreak.Contains(time); } private void initializeBreaks() From ba269a49eef92af0c1ab44dcc73950ed7a8156b4 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 7 Aug 2019 16:59:35 +0300 Subject: [PATCH 2238/5608] Expose break fade duration and add it in the calculation --- osu.Game/Beatmaps/Timing/BreakPeriod.cs | 4 +++- osu.Game/Screens/Play/BreakOverlay.cs | 22 +++++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/osu.Game/Beatmaps/Timing/BreakPeriod.cs b/osu.Game/Beatmaps/Timing/BreakPeriod.cs index 856a5fefd4..5d79c7a86b 100644 --- a/osu.Game/Beatmaps/Timing/BreakPeriod.cs +++ b/osu.Game/Beatmaps/Timing/BreakPeriod.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Screens.Play; + namespace osu.Game.Beatmaps.Timing { public class BreakPeriod @@ -35,6 +37,6 @@ namespace osu.Game.Beatmaps.Timing /// /// The time to check in milliseconds. /// Whether the time falls within this . - public bool Contains(double time) => time >= StartTime && time <= EndTime; + public bool Contains(double time) => time >= StartTime && time <= EndTime - BreakOverlay.BREAK_FADE_DURATION; } } diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index ea9bba9c95..444b1bd210 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -17,7 +17,11 @@ namespace osu.Game.Screens.Play { public class BreakOverlay : Container { - private const double fade_duration = BreakPeriod.MIN_BREAK_DURATION / 2; + /// + /// The duration of the break overlay fading. + /// + public const double BREAK_FADE_DURATION = BreakPeriod.MIN_BREAK_DURATION / 2; + private const float remaining_time_container_max_size = 0.3f; private const int vertical_margin = 25; @@ -172,25 +176,25 @@ namespace osu.Game.Screens.Play using (BeginAbsoluteSequence(b.StartTime, true)) { - fadeContainer.FadeIn(fade_duration); - breakArrows.Show(fade_duration); + fadeContainer.FadeIn(BREAK_FADE_DURATION); + breakArrows.Show(BREAK_FADE_DURATION); remainingTimeAdjustmentBox - .ResizeWidthTo(remaining_time_container_max_size, fade_duration, Easing.OutQuint) - .Delay(b.Duration - fade_duration) + .ResizeWidthTo(remaining_time_container_max_size, BREAK_FADE_DURATION, Easing.OutQuint) + .Delay(b.Duration - BREAK_FADE_DURATION) .ResizeWidthTo(0); remainingTimeBox - .ResizeWidthTo(0, b.Duration - fade_duration) + .ResizeWidthTo(0, b.Duration - BREAK_FADE_DURATION) .Then() .ResizeWidthTo(1); remainingTimeCounter.CountTo(b.Duration).CountTo(0, b.Duration); - using (BeginDelayedSequence(b.Duration - fade_duration, true)) + using (BeginDelayedSequence(b.Duration - BREAK_FADE_DURATION, true)) { - fadeContainer.FadeOut(fade_duration); - breakArrows.Hide(fade_duration); + fadeContainer.FadeOut(BREAK_FADE_DURATION); + breakArrows.Hide(BREAK_FADE_DURATION); } } } From 167a81f40a3561b34f3bfb2e5c6acadb93f891c1 Mon Sep 17 00:00:00 2001 From: jorolf Date: Wed, 7 Aug 2019 18:12:11 +0200 Subject: [PATCH 2239/5608] add special skin hit "animations" --- .../Resources/special-skin/hit0-0@2x.png | Bin 0 -> 4020 bytes .../Resources/special-skin/hit100-0@2x.png | Bin 0 -> 5653 bytes .../Resources/special-skin/hit300-0@2x.png | Bin 0 -> 5004 bytes .../Resources/special-skin/hit50-0@2x.png | Bin 0 -> 3861 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit0-0@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit100-0@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit300-0@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit50-0@2x.png diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit0-0@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit0-0@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9d2ed3a7fa3d5bc0aa43098e9247fa3f6a7c6f80 GIT binary patch literal 4020 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit100-0@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit100-0@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..777af3bd415263824913549c5c4c708c4d6e450a GIT binary patch literal 5653 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 Wr=9MwmK5XvL>cIqJgU`pj`<%3F8Egf literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit300-0@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit300-0@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7ee45a7057ca5f1e11d9bea30375c92e139cf01e GIT binary patch literal 5004 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 F_J2M}_?iF! literal 0 HcmV?d00001 From c77e6074f647574b09403131874ba9566ea1e807 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 7 Aug 2019 19:58:26 +0300 Subject: [PATCH 2240/5608] Disallow adding to score after the player has failed --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 2e863f7edb..fd851f2cbb 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -316,6 +316,9 @@ namespace osu.Game.Rulesets.Scoring /// The to apply. protected virtual void ApplyResult(JudgementResult result) { + if (HasFailed) + return; + result.ComboAtJudgement = Combo.Value; result.HighestComboAtJudgement = HighestCombo.Value; result.HealthAtJudgement = Health.Value; From d5b26b86dafbe9b870b50dd23b74f68ad101471d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 7 Aug 2019 22:18:10 +0300 Subject: [PATCH 2241/5608] Fix storyboard not showing on disabled user dim --- osu.Game/Graphics/Containers/UserDimContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 03de5f651f..dd5134168f 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -76,9 +76,9 @@ namespace osu.Game.Graphics.Containers /// protected virtual void UpdateVisuals() { - ContentDisplayed = ShowDimContent; + ContentDisplayed = !EnableUserDim.Value || ShowDimContent; - dimContent.FadeTo((ContentDisplayed) ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint); + dimContent.FadeTo(ContentDisplayed ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint); dimContent.FadeColour(EnableUserDim.Value ? OsuColour.Gray(1 - (float)UserDimLevel.Value) : Color4.White, BACKGROUND_FADE_DURATION, Easing.OutQuint); } } From 40a33b338201d543c27e97f7769e1731d5461352 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Aug 2019 10:41:23 +0900 Subject: [PATCH 2242/5608] Move IsLoaded check to more correct place --- osu.Game/Screens/Play/BreakOverlay.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 444b1bd210..78690f156f 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -40,7 +40,8 @@ namespace osu.Game.Screens.Play isBreakTime.Value = false; CurrentBreakIndex = 0; - initializeBreaks(); + if (IsLoaded) + initializeBreaks(); } } @@ -162,8 +163,6 @@ namespace osu.Game.Screens.Play private void initializeBreaks() { - if (!IsLoaded) return; // we need a clock. - FinishTransforms(true); Scheduler.CancelDelayedTasks(); From 99f5ca07ce8562e87fa4dae3de9a24c77805cacf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Aug 2019 10:42:54 +0900 Subject: [PATCH 2243/5608] Remove redundant comment --- osu.Game/Screens/Play/BreakOverlay.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 78690f156f..2d014db210 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -154,9 +154,6 @@ namespace osu.Game.Screens.Play CurrentBreakIndex--; } - // This ensures that IsBreakTime is generally consistent with the overlay's transforms during a break. - // If the current break doesn't have effects, IsBreakTime should be false. - // We also assume that the overlay's fade out transform is "not break time". var currentBreak = breaks[CurrentBreakIndex]; isBreakTime.Value = currentBreak.HasEffect && currentBreak.Contains(time); } From 7d42561da93c7f816de3f71e6de32f1d46848250 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Aug 2019 12:58:20 +0900 Subject: [PATCH 2244/5608] Remove linq usage in BreakOverlay update --- osu.Game/Screens/Play/BreakOverlay.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 2d014db210..6fdee85f45 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -138,7 +137,7 @@ namespace osu.Game.Screens.Play private void updateBreakTimeBindable() { - if (breaks?.Any() != true) + if (breaks == null || breaks.Count == 0) return; var time = Clock.CurrentTime; From ffed642929e7ec23ba8e3c60c252a9d0522c9327 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 8 Aug 2019 07:08:51 +0300 Subject: [PATCH 2245/5608] Implement MatchBeatmapPanel --- .../Screens/Multi/Match/Components/Header.cs | 16 ++++++ .../Match/Components/MatchBeatmapPanel.cs | 49 +++++++++++++++++++ .../Screens/Multi/Match/MatchSubScreen.cs | 2 + 3 files changed, 67 insertions(+) create mode 100644 osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index 73994fa369..629a19e5e8 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -29,6 +29,10 @@ namespace osu.Game.Screens.Multi.Match.Components public Action RequestBeatmapSelection; + public BindableBool ShowBeatmapPanel = new BindableBool(); + + private MatchBeatmapPanel beatmapPanel; + public Header() { RelativeSizeAxes = Axes.X; @@ -55,6 +59,12 @@ namespace osu.Game.Screens.Multi.Match.Components RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.4f), Color4.Black.Opacity(0.6f)), }, + beatmapPanel = new MatchBeatmapPanel + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Margin = new MarginPadding { Right = 100 }, + } } }, new Box @@ -114,6 +124,12 @@ namespace osu.Game.Screens.Multi.Match.Components beatmapButton.Action = () => RequestBeatmapSelection?.Invoke(); } + protected override void LoadComplete() + { + base.LoadComplete(); + ShowBeatmapPanel.BindValueChanged(value => beatmapPanel.FadeTo(value.NewValue ? 1 : 0, 200, Easing.OutQuint), true); + } + private class BeatmapSelectButton : HeaderButton { [Resolved(typeof(Room), nameof(Room.RoomID))] diff --git a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs new file mode 100644 index 0000000000..916115f11b --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs @@ -0,0 +1,49 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Overlays.Direct; +using osu.Game.Rulesets; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class MatchBeatmapPanel : MultiplayerComposite + { + [Resolved] + private IAPIProvider api { get; set; } + + [Resolved] + private RulesetStore rulesets { get; set; } + + private GetBeatmapSetRequest request; + + public MatchBeatmapPanel() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load() + { + CurrentItem.BindValueChanged(item => + { + var id = item.NewValue?.Beatmap.OnlineBeatmapID ?? 0; + + if (id != 0) + { + request?.Cancel(); + request = new GetBeatmapSetRequest(id, BeatmapSetLookupType.BeatmapId); + request.Success += beatmap => + { + ClearInternal(); + AddInternal(new DirectGridPanel(beatmap.ToBeatmapSet(rulesets))); + }; + api.Queue(request); + } + }, true); + } + } +} diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 5469d4c8c8..16c6b412fa 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -148,12 +148,14 @@ namespace osu.Game.Screens.Multi.Match if (tab.NewValue is SettingsMatchPage) { + header.ShowBeatmapPanel.Value = false; settings.Show(); info.FadeOut(fade_duration, Easing.OutQuint); bottomRow.FadeOut(fade_duration, Easing.OutQuint); } else { + header.ShowBeatmapPanel.Value = true; settings.Hide(); info.FadeIn(fade_duration, Easing.OutQuint); bottomRow.FadeIn(fade_duration, Easing.OutQuint); From a4459972b6f00d3e533a769468cecf4a7e5462ad Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 8 Aug 2019 07:15:30 +0300 Subject: [PATCH 2246/5608] Remove ViewBeatmapButton --- .../Visual/Multiplayer/TestSceneMatchInfo.cs | 2 +- .../Screens/Multi/Match/Components/Info.cs | 8 +--- .../Match/Components/ViewBeatmapButton.cs | 46 ------------------- 3 files changed, 2 insertions(+), 54 deletions(-) delete mode 100644 osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchInfo.cs index 3f0c0b07b7..a6c036a876 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchInfo.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchInfo.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.Multiplayer typeof(Info), typeof(HeaderButton), typeof(ReadyButton), - typeof(ViewBeatmapButton) + typeof(MatchBeatmapPanel) }; [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index a185c4db50..74f000c21f 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -28,7 +28,6 @@ namespace osu.Game.Screens.Multi.Match.Components private void load() { ReadyButton readyButton; - ViewBeatmapButton viewBeatmapButton; HostInfo hostInfo; InternalChildren = new Drawable[] @@ -80,7 +79,6 @@ namespace osu.Game.Screens.Multi.Match.Components Direction = FillDirection.Horizontal, Children = new Drawable[] { - viewBeatmapButton = new ViewBeatmapButton(), readyButton = new ReadyButton { Action = () => OnStart?.Invoke() @@ -91,11 +89,7 @@ namespace osu.Game.Screens.Multi.Match.Components }, }; - CurrentItem.BindValueChanged(item => - { - viewBeatmapButton.Beatmap.Value = item.NewValue?.Beatmap; - readyButton.Beatmap.Value = item.NewValue?.Beatmap; - }, true); + CurrentItem.BindValueChanged(item => readyButton.Beatmap.Value = item.NewValue?.Beatmap, true); hostInfo.Host.BindTo(Host); } diff --git a/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs b/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs deleted file mode 100644 index 8d1ff21124..0000000000 --- a/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Game.Beatmaps; -using osuTK; - -namespace osu.Game.Screens.Multi.Match.Components -{ - public class ViewBeatmapButton : HeaderButton - { - public readonly Bindable Beatmap = new Bindable(); - - [Resolved(CanBeNull = true)] - private OsuGame osuGame { get; set; } - - public ViewBeatmapButton() - { - RelativeSizeAxes = Axes.Y; - Size = new Vector2(200, 1); - - Text = "View beatmap"; - } - - [BackgroundDependencyLoader] - private void load() - { - if (osuGame != null) - Beatmap.BindValueChanged(beatmap => updateAction(beatmap.NewValue), true); - } - - private void updateAction(BeatmapInfo beatmap) - { - if (beatmap == null) - { - Enabled.Value = false; - return; - } - - Action = () => osuGame.ShowBeatmap(beatmap.OnlineBeatmapID ?? 0); - Enabled.Value = true; - } - } -} From 77df6a0cb7ef7736808811d4c2033d5882d8aa6a Mon Sep 17 00:00:00 2001 From: Joehu Date: Wed, 7 Aug 2019 21:16:36 -0700 Subject: [PATCH 2247/5608] Remove unused direct placeholder screen --- osu.Game/Screens/Direct/OnlineListing.cs | 9 --------- osu.Game/Screens/Menu/MainMenu.cs | 2 -- 2 files changed, 11 deletions(-) delete mode 100644 osu.Game/Screens/Direct/OnlineListing.cs diff --git a/osu.Game/Screens/Direct/OnlineListing.cs b/osu.Game/Screens/Direct/OnlineListing.cs deleted file mode 100644 index 8376383674..0000000000 --- a/osu.Game/Screens/Direct/OnlineListing.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Screens.Direct -{ - public class OnlineListing : ScreenWhiteBox - { - } -} diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index fc8ddd8bd4..499b5089f6 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -14,7 +14,6 @@ using osu.Game.Graphics.Containers; using osu.Game.Overlays; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Charts; -using osu.Game.Screens.Direct; using osu.Game.Screens.Edit; using osu.Game.Screens.Multi; using osu.Game.Screens.Select; @@ -65,7 +64,6 @@ namespace osu.Game.Screens.Menu buttons = new ButtonSystem { OnChart = delegate { this.Push(new ChartListing()); }, - OnDirect = delegate { this.Push(new OnlineListing()); }, OnEdit = delegate { this.Push(new Editor()); }, OnSolo = onSolo, OnMulti = delegate { this.Push(new Multiplayer()); }, From a345955f45c51d4ecaeb9cc728db1f30ce40d1f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Aug 2019 13:57:04 +0900 Subject: [PATCH 2248/5608] Add mentions linking ScoreProcessor apply/revert methods together --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 2e863f7edb..ba2375bec1 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -313,6 +313,9 @@ namespace osu.Game.Rulesets.Scoring /// /// Applies the score change of a to this . /// + /// + /// Any changes applied via this method can be reverted via . + /// /// The to apply. protected virtual void ApplyResult(JudgementResult result) { @@ -357,7 +360,7 @@ namespace osu.Game.Rulesets.Scoring } /// - /// Reverts the score change of a that was applied to this . + /// Reverts the score change of a that was applied to this via . /// /// The judgement scoring result. protected virtual void RevertResult(JudgementResult result) From ac2060f1cf4d1befc59d2b56531d58736f0dd021 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 8 Aug 2019 14:44:04 +0900 Subject: [PATCH 2249/5608] Throw exceptions and let LegacyDecoder handle them --- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 153 ++++----- .../Formats/LegacyStoryboardDecoder.cs | 6 +- .../Objects/Legacy/ConvertHitObjectParser.cs | 323 +++++++++--------- 3 files changed, 223 insertions(+), 259 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index b1261855f2..02d969b571 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -5,7 +5,6 @@ using System; using System.IO; using System.Linq; using osu.Framework.IO.File; -using osu.Framework.Logging; using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Beatmaps.ControlPoints; @@ -292,10 +291,7 @@ namespace osu.Game.Beatmaps.Formats EventType type; if (!Enum.TryParse(split[0], out type)) - { - Logger.Log($"Unknown beatmap event of type {split[0]} could not be parsed and will be ignored.", LoggingTarget.Runtime, LogLevel.Important); - return; - } + throw new InvalidDataException($@"Unknown event type: {split[0]}"); switch (type) { @@ -323,90 +319,79 @@ namespace osu.Game.Beatmaps.Formats private void handleTimingPoint(string line) { - try + string[] split = line.Split(','); + + double time = getOffsetTime(Parsing.ParseDouble(split[0].Trim())); + double beatLength = Parsing.ParseDouble(split[1].Trim()); + double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1; + + TimeSignatures timeSignature = TimeSignatures.SimpleQuadruple; + if (split.Length >= 3) + timeSignature = split[2][0] == '0' ? TimeSignatures.SimpleQuadruple : (TimeSignatures)Parsing.ParseInt(split[2]); + + LegacySampleBank sampleSet = defaultSampleBank; + if (split.Length >= 4) + sampleSet = (LegacySampleBank)Parsing.ParseInt(split[3]); + + int customSampleBank = 0; + if (split.Length >= 5) + customSampleBank = Parsing.ParseInt(split[4]); + + int sampleVolume = defaultSampleVolume; + if (split.Length >= 6) + sampleVolume = Parsing.ParseInt(split[5]); + + bool timingChange = true; + if (split.Length >= 7) + timingChange = split[6][0] == '1'; + + bool kiaiMode = false; + bool omitFirstBarSignature = false; + + if (split.Length >= 8) { - string[] split = line.Split(','); - - double time = getOffsetTime(Parsing.ParseDouble(split[0].Trim())); - double beatLength = Parsing.ParseDouble(split[1].Trim()); - double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1; - - TimeSignatures timeSignature = TimeSignatures.SimpleQuadruple; - if (split.Length >= 3) - timeSignature = split[2][0] == '0' ? TimeSignatures.SimpleQuadruple : (TimeSignatures)Parsing.ParseInt(split[2]); - - LegacySampleBank sampleSet = defaultSampleBank; - if (split.Length >= 4) - sampleSet = (LegacySampleBank)Parsing.ParseInt(split[3]); - - int customSampleBank = 0; - if (split.Length >= 5) - customSampleBank = Parsing.ParseInt(split[4]); - - int sampleVolume = defaultSampleVolume; - if (split.Length >= 6) - sampleVolume = Parsing.ParseInt(split[5]); - - bool timingChange = true; - if (split.Length >= 7) - timingChange = split[6][0] == '1'; - - bool kiaiMode = false; - bool omitFirstBarSignature = false; - - if (split.Length >= 8) - { - EffectFlags effectFlags = (EffectFlags)Parsing.ParseInt(split[7]); - kiaiMode = effectFlags.HasFlag(EffectFlags.Kiai); - omitFirstBarSignature = effectFlags.HasFlag(EffectFlags.OmitFirstBarLine); - } - - string stringSampleSet = sampleSet.ToString().ToLowerInvariant(); - if (stringSampleSet == @"none") - stringSampleSet = @"normal"; - - if (timingChange) - { - var controlPoint = CreateTimingControlPoint(); - controlPoint.Time = time; - controlPoint.BeatLength = beatLength; - controlPoint.TimeSignature = timeSignature; - - handleTimingControlPoint(controlPoint); - } - - handleDifficultyControlPoint(new DifficultyControlPoint - { - Time = time, - SpeedMultiplier = speedMultiplier, - AutoGenerated = timingChange - }); - - handleEffectControlPoint(new EffectControlPoint - { - Time = time, - KiaiMode = kiaiMode, - OmitFirstBarLine = omitFirstBarSignature, - AutoGenerated = timingChange - }); - - handleSampleControlPoint(new LegacySampleControlPoint - { - Time = time, - SampleBank = stringSampleSet, - SampleVolume = sampleVolume, - CustomSampleBank = customSampleBank, - AutoGenerated = timingChange - }); + EffectFlags effectFlags = (EffectFlags)Parsing.ParseInt(split[7]); + kiaiMode = effectFlags.HasFlag(EffectFlags.Kiai); + omitFirstBarSignature = effectFlags.HasFlag(EffectFlags.OmitFirstBarLine); } - catch (FormatException) + + string stringSampleSet = sampleSet.ToString().ToLowerInvariant(); + if (stringSampleSet == @"none") + stringSampleSet = @"normal"; + + if (timingChange) { - Logger.Log("A timing point could not be parsed correctly and will be ignored", LoggingTarget.Runtime, LogLevel.Important); + var controlPoint = CreateTimingControlPoint(); + controlPoint.Time = time; + controlPoint.BeatLength = beatLength; + controlPoint.TimeSignature = timeSignature; + + handleTimingControlPoint(controlPoint); } - catch (OverflowException) + + handleDifficultyControlPoint(new DifficultyControlPoint { - Logger.Log("A timing point could not be parsed correctly and will be ignored", LoggingTarget.Runtime, LogLevel.Important); - } + Time = time, + SpeedMultiplier = speedMultiplier, + AutoGenerated = timingChange + }); + + handleEffectControlPoint(new EffectControlPoint + { + Time = time, + KiaiMode = kiaiMode, + OmitFirstBarLine = omitFirstBarSignature, + AutoGenerated = timingChange + }); + + handleSampleControlPoint(new LegacySampleControlPoint + { + Time = time, + SampleBank = stringSampleSet, + SampleVolume = sampleVolume, + CustomSampleBank = customSampleBank, + AutoGenerated = timingChange + }); } private void handleTimingControlPoint(TimingControlPoint newPoint) diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index f950437e75..3ae1c3ef12 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -10,7 +10,6 @@ using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.IO.File; -using osu.Framework.Logging; using osu.Game.Storyboards; namespace osu.Game.Beatmaps.Formats @@ -85,10 +84,7 @@ namespace osu.Game.Beatmaps.Formats EventType type; if (!Enum.TryParse(split[0], out type)) - { - Logger.Log($"Unknown storyboard event of type {split[0]} could not be parsed and will be ignored.", LoggingTarget.Runtime, LogLevel.Important); - return; - } + throw new InvalidDataException($@"Unknown event type: {split[0]}"); switch (type) { diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index d70c1bf7d3..442e37edf5 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -10,7 +10,6 @@ using osu.Game.Beatmaps.Formats; using osu.Game.Audio; using System.Linq; using JetBrains.Annotations; -using osu.Framework.Logging; using osu.Framework.MathUtils; namespace osu.Game.Rulesets.Objects.Legacy @@ -41,208 +40,192 @@ namespace osu.Game.Rulesets.Objects.Legacy [CanBeNull] public override HitObject Parse(string text) { - try + string[] split = text.Split(','); + + Vector2 pos = new Vector2((int)Parsing.ParseFloat(split[0], Parsing.MAX_COORDINATE_VALUE), (int)Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE)); + + double startTime = Parsing.ParseDouble(split[2]) + Offset; + + ConvertHitObjectType type = (ConvertHitObjectType)Parsing.ParseInt(split[3]); + + int comboOffset = (int)(type & ConvertHitObjectType.ComboOffset) >> 4; + type &= ~ConvertHitObjectType.ComboOffset; + + bool combo = type.HasFlag(ConvertHitObjectType.NewCombo); + type &= ~ConvertHitObjectType.NewCombo; + + var soundType = (LegacySoundType)Parsing.ParseInt(split[4]); + var bankInfo = new SampleBankInfo(); + + HitObject result = null; + + if (type.HasFlag(ConvertHitObjectType.Circle)) { - string[] split = text.Split(','); + result = CreateHit(pos, combo, comboOffset); - Vector2 pos = new Vector2((int)Parsing.ParseFloat(split[0], Parsing.MAX_COORDINATE_VALUE), (int)Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE)); + if (split.Length > 5) + readCustomSampleBanks(split[5], bankInfo); + } + else if (type.HasFlag(ConvertHitObjectType.Slider)) + { + PathType pathType = PathType.Catmull; + double? length = null; - double startTime = Parsing.ParseDouble(split[2]) + Offset; + string[] pointSplit = split[5].Split('|'); - ConvertHitObjectType type = (ConvertHitObjectType)Parsing.ParseInt(split[3]); + int pointCount = 1; + foreach (var t in pointSplit) + if (t.Length > 1) + pointCount++; - int comboOffset = (int)(type & ConvertHitObjectType.ComboOffset) >> 4; - type &= ~ConvertHitObjectType.ComboOffset; + var points = new Vector2[pointCount]; - bool combo = type.HasFlag(ConvertHitObjectType.NewCombo); - type &= ~ConvertHitObjectType.NewCombo; + int pointIndex = 1; - var soundType = (LegacySoundType)Parsing.ParseInt(split[4]); - var bankInfo = new SampleBankInfo(); - - HitObject result = null; - - if (type.HasFlag(ConvertHitObjectType.Circle)) + foreach (string t in pointSplit) { - result = CreateHit(pos, combo, comboOffset); - - if (split.Length > 5) - readCustomSampleBanks(split[5], bankInfo); - } - else if (type.HasFlag(ConvertHitObjectType.Slider)) - { - PathType pathType = PathType.Catmull; - double? length = null; - - string[] pointSplit = split[5].Split('|'); - - int pointCount = 1; - foreach (var t in pointSplit) - if (t.Length > 1) - pointCount++; - - var points = new Vector2[pointCount]; - - int pointIndex = 1; - - foreach (string t in pointSplit) + if (t.Length == 1) { - if (t.Length == 1) + switch (t) { - switch (t) - { - case @"C": - pathType = PathType.Catmull; - break; - - case @"B": - pathType = PathType.Bezier; - break; - - case @"L": - pathType = PathType.Linear; - break; - - case @"P": - pathType = PathType.PerfectCurve; - break; - } - - continue; - } - - string[] temp = t.Split(':'); - points[pointIndex++] = new Vector2((int)Parsing.ParseDouble(temp[0], Parsing.MAX_COORDINATE_VALUE), (int)Parsing.ParseDouble(temp[1], Parsing.MAX_COORDINATE_VALUE)) - pos; - } - - // osu-stable special-cased colinear perfect curves to a CurveType.Linear - bool isLinear(Vector2[] p) => Precision.AlmostEquals(0, (p[1].Y - p[0].Y) * (p[2].X - p[0].X) - (p[1].X - p[0].X) * (p[2].Y - p[0].Y)); - - if (points.Length == 3 && pathType == PathType.PerfectCurve && isLinear(points)) - pathType = PathType.Linear; - - int repeatCount = Parsing.ParseInt(split[6]); - - if (repeatCount > 9000) - throw new ArgumentOutOfRangeException(nameof(repeatCount), @"Repeat count is way too high"); - - // osu-stable treated the first span of the slider as a repeat, but no repeats are happening - repeatCount = Math.Max(0, repeatCount - 1); - - if (split.Length > 7) - { - length = Math.Max(0, Parsing.ParseDouble(split[7])); - if (length == 0) - length = null; - } - - if (split.Length > 10) - readCustomSampleBanks(split[10], bankInfo); - - // One node for each repeat + the start and end nodes - int nodes = repeatCount + 2; - - // Populate node sample bank infos with the default hit object sample bank - var nodeBankInfos = new List(); - for (int i = 0; i < nodes; i++) - nodeBankInfos.Add(bankInfo.Clone()); - - // Read any per-node sample banks - if (split.Length > 9 && split[9].Length > 0) - { - string[] sets = split[9].Split('|'); - - for (int i = 0; i < nodes; i++) - { - if (i >= sets.Length) + case @"C": + pathType = PathType.Catmull; break; - SampleBankInfo info = nodeBankInfos[i]; - readCustomSampleBanks(sets[i], info); - } - } - - // Populate node sound types with the default hit object sound type - var nodeSoundTypes = new List(); - for (int i = 0; i < nodes; i++) - nodeSoundTypes.Add(soundType); - - // Read any per-node sound types - if (split.Length > 8 && split[8].Length > 0) - { - string[] adds = split[8].Split('|'); - - for (int i = 0; i < nodes; i++) - { - if (i >= adds.Length) + case @"B": + pathType = PathType.Bezier; break; - int sound; - int.TryParse(adds[i], out sound); - nodeSoundTypes[i] = (LegacySoundType)sound; + case @"L": + pathType = PathType.Linear; + break; + + case @"P": + pathType = PathType.PerfectCurve; + break; } + + continue; } - // Generate the final per-node samples - var nodeSamples = new List>(nodes); + string[] temp = t.Split(':'); + points[pointIndex++] = new Vector2((int)Parsing.ParseDouble(temp[0], Parsing.MAX_COORDINATE_VALUE), (int)Parsing.ParseDouble(temp[1], Parsing.MAX_COORDINATE_VALUE)) - pos; + } + + // osu-stable special-cased colinear perfect curves to a CurveType.Linear + bool isLinear(Vector2[] p) => Precision.AlmostEquals(0, (p[1].Y - p[0].Y) * (p[2].X - p[0].X) - (p[1].X - p[0].X) * (p[2].Y - p[0].Y)); + + if (points.Length == 3 && pathType == PathType.PerfectCurve && isLinear(points)) + pathType = PathType.Linear; + + int repeatCount = Parsing.ParseInt(split[6]); + + if (repeatCount > 9000) + throw new ArgumentOutOfRangeException(nameof(repeatCount), @"Repeat count is way too high"); + + // osu-stable treated the first span of the slider as a repeat, but no repeats are happening + repeatCount = Math.Max(0, repeatCount - 1); + + if (split.Length > 7) + { + length = Math.Max(0, Parsing.ParseDouble(split[7])); + if (length == 0) + length = null; + } + + if (split.Length > 10) + readCustomSampleBanks(split[10], bankInfo); + + // One node for each repeat + the start and end nodes + int nodes = repeatCount + 2; + + // Populate node sample bank infos with the default hit object sample bank + var nodeBankInfos = new List(); + for (int i = 0; i < nodes; i++) + nodeBankInfos.Add(bankInfo.Clone()); + + // Read any per-node sample banks + if (split.Length > 9 && split[9].Length > 0) + { + string[] sets = split[9].Split('|'); + for (int i = 0; i < nodes; i++) - nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i])); - - result = CreateSlider(pos, combo, comboOffset, points, length, pathType, repeatCount, nodeSamples); - - // The samples are played when the slider ends, which is the last node - result.Samples = nodeSamples[nodeSamples.Count - 1]; - } - else if (type.HasFlag(ConvertHitObjectType.Spinner)) - { - double endTime = Math.Max(startTime, Parsing.ParseDouble(split[5]) + Offset); - - result = CreateSpinner(new Vector2(512, 384) / 2, combo, comboOffset, endTime); - - if (split.Length > 6) - readCustomSampleBanks(split[6], bankInfo); - } - else if (type.HasFlag(ConvertHitObjectType.Hold)) - { - // Note: Hold is generated by BMS converts - - double endTime = Math.Max(startTime, Parsing.ParseDouble(split[2])); - - if (split.Length > 5 && !string.IsNullOrEmpty(split[5])) { - string[] ss = split[5].Split(':'); - endTime = Math.Max(startTime, Parsing.ParseDouble(ss[0])); - readCustomSampleBanks(string.Join(":", ss.Skip(1)), bankInfo); + if (i >= sets.Length) + break; + + SampleBankInfo info = nodeBankInfos[i]; + readCustomSampleBanks(sets[i], info); } - - result = CreateHold(pos, combo, comboOffset, endTime + Offset); } - if (result == null) + // Populate node sound types with the default hit object sound type + var nodeSoundTypes = new List(); + for (int i = 0; i < nodes; i++) + nodeSoundTypes.Add(soundType); + + // Read any per-node sound types + if (split.Length > 8 && split[8].Length > 0) { - Logger.Log($"Unknown hit object type: {type}. Skipped.", level: LogLevel.Error); - return null; + string[] adds = split[8].Split('|'); + + for (int i = 0; i < nodes; i++) + { + if (i >= adds.Length) + break; + + int sound; + int.TryParse(adds[i], out sound); + nodeSoundTypes[i] = (LegacySoundType)sound; + } } - result.StartTime = startTime; + // Generate the final per-node samples + var nodeSamples = new List>(nodes); + for (int i = 0; i < nodes; i++) + nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i])); - if (result.Samples.Count == 0) - result.Samples = convertSoundType(soundType, bankInfo); + result = CreateSlider(pos, combo, comboOffset, points, length, pathType, repeatCount, nodeSamples); - FirstObject = false; - - return result; + // The samples are played when the slider ends, which is the last node + result.Samples = nodeSamples[nodeSamples.Count - 1]; } - catch (FormatException) + else if (type.HasFlag(ConvertHitObjectType.Spinner)) { - Logger.Log("A hitobject could not be parsed correctly and will be ignored", LoggingTarget.Runtime, LogLevel.Important); + double endTime = Math.Max(startTime, Parsing.ParseDouble(split[5]) + Offset); + + result = CreateSpinner(new Vector2(512, 384) / 2, combo, comboOffset, endTime); + + if (split.Length > 6) + readCustomSampleBanks(split[6], bankInfo); } - catch (OverflowException) + else if (type.HasFlag(ConvertHitObjectType.Hold)) { - Logger.Log("A hitobject could not be parsed correctly and will be ignored", LoggingTarget.Runtime, LogLevel.Important); + // Note: Hold is generated by BMS converts + + double endTime = Math.Max(startTime, Parsing.ParseDouble(split[2])); + + if (split.Length > 5 && !string.IsNullOrEmpty(split[5])) + { + string[] ss = split[5].Split(':'); + endTime = Math.Max(startTime, Parsing.ParseDouble(ss[0])); + readCustomSampleBanks(string.Join(":", ss.Skip(1)), bankInfo); + } + + result = CreateHold(pos, combo, comboOffset, endTime + Offset); } - return null; + if (result == null) + throw new InvalidDataException($"Unknown hit object type: {type}"); + + result.StartTime = startTime; + + if (result.Samples.Count == 0) + result.Samples = convertSoundType(soundType, bankInfo); + + FirstObject = false; + + return result; } private void readCustomSampleBanks(string str, SampleBankInfo bankInfo) From de4ad1f62586fb3c55cd8067ac9672f284c8cfbf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 8 Aug 2019 14:44:49 +0900 Subject: [PATCH 2250/5608] Fix bad log message --- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 442e37edf5..e990938291 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -216,7 +216,7 @@ namespace osu.Game.Rulesets.Objects.Legacy } if (result == null) - throw new InvalidDataException($"Unknown hit object type: {type}"); + throw new InvalidDataException($"Unknown hit object type: {split[3]}"); result.StartTime = startTime; From cbcdc2890088bb151ae6c444d4ae95e005a63f6b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 8 Aug 2019 09:04:24 +0300 Subject: [PATCH 2251/5608] Fix hard crash when clicking on a preview button --- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 16c6b412fa..13a21a4516 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -7,6 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; +using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.GameTypes; @@ -18,7 +19,7 @@ using PlaylistItem = osu.Game.Online.Multiplayer.PlaylistItem; namespace osu.Game.Screens.Multi.Match { - public class MatchSubScreen : MultiplayerSubScreen + public class MatchSubScreen : MultiplayerSubScreen, IPreviewTrackOwner { public override bool DisallowExternalBeatmapRulesetChanges => true; @@ -44,6 +45,9 @@ namespace osu.Game.Screens.Multi.Match [Resolved] private BeatmapManager beatmapManager { get; set; } + [Resolved] + private PreviewTrackManager trackManager { get; set; } + [Resolved(CanBeNull = true)] private OsuGame game { get; set; } @@ -184,6 +188,8 @@ namespace osu.Game.Screens.Multi.Match Mods.Value = Array.Empty(); + trackManager.StopAnyPlaying(this); + return base.OnExiting(next); } @@ -237,6 +243,13 @@ namespace osu.Game.Screens.Multi.Match } } + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.CacheAs(this); + return dependencies; + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From 8668bce25d23d69d23c1bc3c0e15a741b9862b1a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 8 Aug 2019 09:52:42 +0300 Subject: [PATCH 2252/5608] Fix preview can be played on start --- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 13a21a4516..3136326cdd 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -231,6 +231,8 @@ namespace osu.Game.Screens.Multi.Match private void onStart() { + trackManager.StopAnyPlaying(this); + switch (type.Value) { default: From bcd443a3aa8178cc68481b96d3055d18a94014e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20H=C3=BCbner?= Date: Thu, 8 Aug 2019 08:56:52 +0200 Subject: [PATCH 2253/5608] remove /j --- osu.Game/Online/Chat/ChannelManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index b5d8879e50..9acf6bd39f 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -213,7 +213,6 @@ namespace osu.Game.Online.Chat PostMessage(content, true); break; - case "j": case "join": if (string.IsNullOrWhiteSpace(content)) { From 0bed3bfece7397236bc891a34e5fe8ab7c343f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20H=C3=BCbner?= Date: Thu, 8 Aug 2019 09:02:09 +0200 Subject: [PATCH 2254/5608] formatting inspection 2 --- osu.Game/Online/Chat/ChannelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 9acf6bd39f..4f6066cab1 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -221,7 +221,7 @@ namespace osu.Game.Online.Chat } var channel = availableChannels.Where(c => c.Name == content || c.Name == $"#{content}").FirstOrDefault(); - + if (channel == null) { target.AddNewMessages(new ErrorMessage($"Channel '{content}' not found.")); From 6d5a7041fdf7873c36eff28d8e624e68fc0088ca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Aug 2019 17:10:06 +0900 Subject: [PATCH 2255/5608] Move system user colour assignment to ensure consistency --- osu.Game/Online/Chat/ErrorMessage.cs | 2 +- osu.Game/Users/User.cs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/ErrorMessage.cs b/osu.Game/Online/Chat/ErrorMessage.cs index a8ff0e9a98..87a65fb3f1 100644 --- a/osu.Game/Online/Chat/ErrorMessage.cs +++ b/osu.Game/Online/Chat/ErrorMessage.cs @@ -8,7 +8,7 @@ namespace osu.Game.Online.Chat public ErrorMessage(string message) : base(message) { - Sender.Colour = @"ff0000"; + // todo: this should likely be styled differently in the future. } } } diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index b738eff4a6..a5f3578711 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -187,6 +187,7 @@ namespace osu.Game.Users public static readonly User SYSTEM_USER = new User { Username = "system", + Colour = @"9c0101", Id = 0 }; From a3dbaef4cabb1fdd37c96cdd9dd5ad88ef1b62df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Aug 2019 17:29:50 +0900 Subject: [PATCH 2256/5608] Adjust background gradient --- osu.Game/Screens/Multi/Match/Components/Header.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index 629a19e5e8..7f2b1278b7 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -57,7 +57,7 @@ namespace osu.Game.Screens.Multi.Match.Components new Box { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.4f), Color4.Black.Opacity(0.6f)), + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.7f), Color4.Black.Opacity(0.8f)), }, beatmapPanel = new MatchBeatmapPanel { From 1b559c15852901bd2c7819b166479cbb76f69475 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 8 Aug 2019 12:01:33 +0300 Subject: [PATCH 2257/5608] Use async loading --- osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs index 916115f11b..dc889eeb94 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs @@ -39,7 +39,8 @@ namespace osu.Game.Screens.Multi.Match.Components request.Success += beatmap => { ClearInternal(); - AddInternal(new DirectGridPanel(beatmap.ToBeatmapSet(rulesets))); + var panel = new DirectGridPanel(beatmap.ToBeatmapSet(rulesets)); + LoadComponentAsync(panel, p => { AddInternal(panel); }); }; api.Queue(request); } From 08a92c38d728e030b64bc0135607ce25ce01f5cd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 8 Aug 2019 12:04:44 +0300 Subject: [PATCH 2258/5608] adjust naming --- .../Screens/Multi/Match/Components/MatchBeatmapPanel.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs index dc889eeb94..b927e38edb 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs @@ -30,12 +30,12 @@ namespace osu.Game.Screens.Multi.Match.Components { CurrentItem.BindValueChanged(item => { - var id = item.NewValue?.Beatmap.OnlineBeatmapID ?? 0; + var onlineId = item.NewValue?.Beatmap.OnlineBeatmapID ?? 0; - if (id != 0) + if (onlineId != 0) { request?.Cancel(); - request = new GetBeatmapSetRequest(id, BeatmapSetLookupType.BeatmapId); + request = new GetBeatmapSetRequest(onlineId, BeatmapSetLookupType.BeatmapId); request.Success += beatmap => { ClearInternal(); From e9b5c91690a424be0f26b8474fc27e03d326add8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 8 Aug 2019 12:08:51 +0300 Subject: [PATCH 2259/5608] Fade out existing panel on beatmap change --- .../Multi/Match/Components/MatchBeatmapPanel.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs index b927e38edb..f73059d069 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs @@ -19,6 +19,7 @@ namespace osu.Game.Screens.Multi.Match.Components private RulesetStore rulesets { get; set; } private GetBeatmapSetRequest request; + private DirectGridPanel panel; public MatchBeatmapPanel() { @@ -30,16 +31,23 @@ namespace osu.Game.Screens.Multi.Match.Components { CurrentItem.BindValueChanged(item => { + request?.Cancel(); + + if (panel != null) + { + panel.FadeOut(200); + panel.Expire(); + panel = null; + } + var onlineId = item.NewValue?.Beatmap.OnlineBeatmapID ?? 0; if (onlineId != 0) { - request?.Cancel(); request = new GetBeatmapSetRequest(onlineId, BeatmapSetLookupType.BeatmapId); request.Success += beatmap => { - ClearInternal(); - var panel = new DirectGridPanel(beatmap.ToBeatmapSet(rulesets)); + panel = new DirectGridPanel(beatmap.ToBeatmapSet(rulesets)); LoadComponentAsync(panel, p => { AddInternal(panel); }); }; api.Queue(request); From 460cf141de6ce895cfa69f3dd00cdc62a0d50205 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 8 Aug 2019 12:18:26 +0300 Subject: [PATCH 2260/5608] Add testing --- .../Multiplayer/TestSceneMatchBeatmapPanel.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs new file mode 100644 index 0000000000..46fd43508b --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.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 System; +using System.Collections.Generic; +using osu.Game.Beatmaps; +using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Match.Components; +using osu.Framework.Graphics; +using osu.Framework.MathUtils; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneMatchBeatmapPanel : MultiplayerTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(MatchBeatmapPanel) + }; + + public TestSceneMatchBeatmapPanel() + { + Add(new MatchBeatmapPanel + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + + var playlist = Room.Playlist; + + playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 1763072 } }); + playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 2101557 } }); + playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 1973466 } }); + playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 2109801 } }); + playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 1922035 } }); + + AddStep("Select random beatmap", () => Room.CurrentItem.Value = playlist[RNG.Next(playlist.Count)]); + } + } +} From 9ab132520cdb6af2063ca8de0d87a56785d44dd6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 8 Aug 2019 12:25:46 +0300 Subject: [PATCH 2261/5608] Testcase improvements --- .../Multiplayer/TestSceneMatchBeatmapPanel.cs | 35 ++++++++++++++----- .../Screens/Multi/Match/MatchSubScreen.cs | 2 ++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs index 46fd43508b..db2b61cdd9 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs @@ -8,16 +8,21 @@ using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Match.Components; using osu.Framework.Graphics; using osu.Framework.MathUtils; +using osu.Game.Audio; +using osu.Framework.Allocation; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMatchBeatmapPanel : MultiplayerTestScene + public class TestSceneMatchBeatmapPanel : MultiplayerTestScene, IPreviewTrackOwner { public override IReadOnlyList RequiredTypes => new[] { typeof(MatchBeatmapPanel) }; + [Resolved] + private PreviewTrackManager trackManager { get; set; } + public TestSceneMatchBeatmapPanel() { Add(new MatchBeatmapPanel @@ -26,15 +31,29 @@ namespace osu.Game.Tests.Visual.Multiplayer Origin = Anchor.Centre, }); - var playlist = Room.Playlist; + Room.Playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 1763072 } }); + Room.Playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 2101557 } }); + Room.Playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 1973466 } }); + Room.Playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 2109801 } }); + Room.Playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 1922035 } }); + } - playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 1763072 } }); - playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 2101557 } }); - playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 1973466 } }); - playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 2109801 } }); - playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 1922035 } }); + protected override void LoadComplete() + { + base.LoadComplete(); - AddStep("Select random beatmap", () => Room.CurrentItem.Value = playlist[RNG.Next(playlist.Count)]); + AddStep("Select random beatmap", () => + { + Room.CurrentItem.Value = Room.Playlist[RNG.Next(Room.Playlist.Count)]; + trackManager.StopAnyPlaying(this); + }); + } + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.CacheAs(this); + return dependencies; } } } diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 3136326cdd..c89c32759d 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -206,6 +206,8 @@ namespace osu.Game.Screens.Multi.Match if (e.NewValue?.Ruleset != null) Ruleset.Value = e.NewValue.Ruleset; + + trackManager.StopAnyPlaying(this); } /// From 3ebfa0505c21bec9ef00fe643b05dbd52336444b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 8 Aug 2019 18:26:03 +0900 Subject: [PATCH 2262/5608] Don't share single scheduler across all model managers --- osu.Game/Database/ArchiveModelManager.cs | 29 +++++++++++------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index efb76deff8..52d3f013ce 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -31,10 +31,21 @@ namespace osu.Game.Database /// /// The model type. /// The associated file join type. - public abstract class ArchiveModelManager : ArchiveModelManager, ICanAcceptFiles, IModelManager + public abstract class ArchiveModelManager : ICanAcceptFiles, IModelManager where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() { + private const int import_queue_request_concurrency = 1; + + /// + /// A singleton scheduler shared by all . + /// + /// + /// This scheduler generally performs IO and CPU intensive work so concurrency is limited harshly. + /// It is mainly being used as a queue mechanism for large imports. + /// + private static readonly ThreadedTaskScheduler import_scheduler = new ThreadedTaskScheduler(import_queue_request_concurrency, nameof(ArchiveModelManager)); + /// /// Set an endpoint for notifications to be posted to. /// @@ -336,7 +347,7 @@ namespace osu.Game.Database flushEvents(true); return item; - }, cancellationToken, TaskCreationOptions.HideScheduler, IMPORT_SCHEDULER).Unwrap(); + }, cancellationToken, TaskCreationOptions.HideScheduler, import_scheduler).Unwrap(); /// /// Perform an update of the specified item. @@ -646,18 +657,4 @@ namespace osu.Game.Database #endregion } - - public abstract class ArchiveModelManager - { - private const int import_queue_request_concurrency = 1; - - /// - /// A singleton scheduler shared by all . - /// - /// - /// This scheduler generally performs IO and CPU intensive work so concurrency is limited harshly. - /// It is mainly being used as a queue mechanism for large imports. - /// - protected static readonly ThreadedTaskScheduler IMPORT_SCHEDULER = new ThreadedTaskScheduler(import_queue_request_concurrency, nameof(ArchiveModelManager)); - } } From 566d874641922a3b680b648542aecc7702a0236b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 8 Aug 2019 15:25:07 +0300 Subject: [PATCH 2263/5608] Prevent failing when reverting to a hasFailedAtJudgement --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index fd851f2cbb..5ca33ff0bc 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -95,7 +95,7 @@ namespace osu.Game.Rulesets.Scoring /// /// Whether this ScoreProcessor has already triggered the failed state. /// - public virtual bool HasFailed { get; private set; } + public virtual bool HasFailed { get; protected set; } /// /// The default conditions for failing. @@ -309,6 +309,7 @@ namespace osu.Game.Rulesets.Scoring } private readonly Dictionary scoreResultCounts = new Dictionary(); + private Judgement hasFailedAtJudgement; /// /// Applies the score change of a to this . @@ -317,7 +318,12 @@ namespace osu.Game.Rulesets.Scoring protected virtual void ApplyResult(JudgementResult result) { if (HasFailed) + { + if (hasFailedAtJudgement == null) + hasFailedAtJudgement = result.Judgement; + return; + } result.ComboAtJudgement = Combo.Value; result.HighestComboAtJudgement = HighestCombo.Value; @@ -365,6 +371,17 @@ namespace osu.Game.Rulesets.Scoring /// The judgement scoring result. protected virtual void RevertResult(JudgementResult result) { + if (HasFailed) + { + if (hasFailedAtJudgement == result.Judgement) + { + hasFailedAtJudgement = null; + HasFailed = false; + } + + return; + } + Combo.Value = result.ComboAtJudgement; HighestCombo.Value = result.HighestComboAtJudgement; Health.Value = result.HealthAtJudgement; From 537973fc458f50a260e1e8d31f217a146b02cd88 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 8 Aug 2019 15:59:29 +0300 Subject: [PATCH 2264/5608] Add test for disabling user dim on storyboard --- .../Background/TestSceneUserDimContainer.cs | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index f114559114..bffee7f1f7 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -149,10 +149,10 @@ namespace osu.Game.Tests.Visual.Background } /// - /// Check if the is properly accepting user-defined visual changes at all. + /// Check if the is properly accepting user-defined visual changes in background at all. /// [Test] - public void DisableUserDimTest() + public void DisableUserDimBackgroundTest() { performFullSetup(); waitForDim(); @@ -165,6 +165,28 @@ namespace osu.Game.Tests.Visual.Background AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied()); } + /// + /// Check if the is properly accepting user-defined visual changes in storyboard at all. + /// + [Test] + public void DisableUserDimStoryboardTest() + { + performFullSetup(); + createFakeStoryboard(); + AddStep("Storyboard Enabled", () => + { + player.ReplacesBackground.Value = true; + player.StoryboardEnabled.Value = true; + }); + AddStep("EnableUserDim enabled", () => player.DimmableStoryboard.EnableUserDim.Value = true); + AddStep("Set dim level to 1", () => songSelect.DimLevel.Value = 1f); + waitForDim(); + AddAssert("Storyboard is invisible", () => !player.IsStoryboardVisible); + AddStep("EnableUserDim disabled", () => player.DimmableStoryboard.EnableUserDim.Value = false); + waitForDim(); + AddAssert("Storyboard is visible", () => player.IsStoryboardVisible); + } + /// /// Check if the visual settings container retains dim and blur when pausing /// From 88b9942b2ac601d33c40a41f8d3625b7788eabf5 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 8 Aug 2019 17:07:06 +0300 Subject: [PATCH 2265/5608] Move EnableUserDim check to defualt value of ShowDimContent --- osu.Game/Graphics/Containers/UserDimContainer.cs | 2 +- osu.Game/Screens/Play/DimmableStoryboard.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index dd5134168f..b7da5592a8 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -69,7 +69,7 @@ namespace osu.Game.Graphics.Containers /// /// Whether the content of this container should currently be visible. /// - protected virtual bool ShowDimContent => true; + protected virtual bool ShowDimContent => !EnableUserDim.Value; /// /// Should be invoked when any dependent dim level or user setting is changed and bring the visual state up-to-date. diff --git a/osu.Game/Screens/Play/DimmableStoryboard.cs b/osu.Game/Screens/Play/DimmableStoryboard.cs index 45dff039b6..10ddaeb354 100644 --- a/osu.Game/Screens/Play/DimmableStoryboard.cs +++ b/osu.Game/Screens/Play/DimmableStoryboard.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Play base.LoadComplete(); } - protected override bool ShowDimContent => ShowStoryboard.Value && UserDimLevel.Value < 1; + protected override bool ShowDimContent => base.ShowDimContent || ShowStoryboard.Value && UserDimLevel.Value < 1; private void initializeStoryboard(bool async) { From bedb744a2e067a53d6aa5fdcbc1c6ede16245b9e Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 8 Aug 2019 17:11:26 +0300 Subject: [PATCH 2266/5608] Add parentheses --- osu.Game/Screens/Play/DimmableStoryboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/DimmableStoryboard.cs b/osu.Game/Screens/Play/DimmableStoryboard.cs index 10ddaeb354..8d1f703791 100644 --- a/osu.Game/Screens/Play/DimmableStoryboard.cs +++ b/osu.Game/Screens/Play/DimmableStoryboard.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Play base.LoadComplete(); } - protected override bool ShowDimContent => base.ShowDimContent || ShowStoryboard.Value && UserDimLevel.Value < 1; + protected override bool ShowDimContent => base.ShowDimContent || (ShowStoryboard.Value && UserDimLevel.Value < 1); private void initializeStoryboard(bool async) { From a3d90da7d4663ee1e0653bdcb9d70143bc89ae9b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 8 Aug 2019 17:29:52 +0300 Subject: [PATCH 2267/5608] Remove unnecessary check --- osu.Game/Graphics/Containers/UserDimContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index b7da5592a8..6696a5bfe0 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -76,7 +76,7 @@ namespace osu.Game.Graphics.Containers /// protected virtual void UpdateVisuals() { - ContentDisplayed = !EnableUserDim.Value || ShowDimContent; + ContentDisplayed = ShowDimContent; dimContent.FadeTo(ContentDisplayed ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint); dimContent.FadeColour(EnableUserDim.Value ? OsuColour.Gray(1 - (float)UserDimLevel.Value) : Color4.White, BACKGROUND_FADE_DURATION, Easing.OutQuint); From 0fcc6c1676089fd2dd963f937bf317b68252336e Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 8 Aug 2019 22:13:48 +0300 Subject: [PATCH 2268/5608] Add DimLevel property --- osu.Game/Graphics/Containers/UserDimContainer.cs | 6 ++++-- osu.Game/Screens/Play/DimmableStoryboard.cs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 6696a5bfe0..023964d701 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -36,6 +36,8 @@ namespace osu.Game.Graphics.Containers protected Bindable ShowStoryboard { get; private set; } + protected double DimLevel => EnableUserDim.Value ? UserDimLevel.Value : 0; + protected override Container Content => dimContent; private Container dimContent { get; } @@ -69,7 +71,7 @@ namespace osu.Game.Graphics.Containers /// /// Whether the content of this container should currently be visible. /// - protected virtual bool ShowDimContent => !EnableUserDim.Value; + protected virtual bool ShowDimContent => true; /// /// Should be invoked when any dependent dim level or user setting is changed and bring the visual state up-to-date. @@ -79,7 +81,7 @@ namespace osu.Game.Graphics.Containers ContentDisplayed = ShowDimContent; dimContent.FadeTo(ContentDisplayed ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint); - dimContent.FadeColour(EnableUserDim.Value ? OsuColour.Gray(1 - (float)UserDimLevel.Value) : Color4.White, BACKGROUND_FADE_DURATION, Easing.OutQuint); + dimContent.FadeColour(OsuColour.Gray(1 - (float)DimLevel), BACKGROUND_FADE_DURATION, Easing.OutQuint); } } } diff --git a/osu.Game/Screens/Play/DimmableStoryboard.cs b/osu.Game/Screens/Play/DimmableStoryboard.cs index 8d1f703791..2154526e54 100644 --- a/osu.Game/Screens/Play/DimmableStoryboard.cs +++ b/osu.Game/Screens/Play/DimmableStoryboard.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Play base.LoadComplete(); } - protected override bool ShowDimContent => base.ShowDimContent || (ShowStoryboard.Value && UserDimLevel.Value < 1); + protected override bool ShowDimContent => ShowStoryboard.Value && DimLevel < 1; private void initializeStoryboard(bool async) { From 565034e658ace24fd3d2ab493bc0df5496a9cdfb Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 8 Aug 2019 22:14:51 +0300 Subject: [PATCH 2269/5608] Remove unnecessary using directive --- osu.Game/Graphics/Containers/UserDimContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 023964d701..2b7635cc88 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -6,7 +6,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; -using osuTK.Graphics; namespace osu.Game.Graphics.Containers { From 7e9c100c9b25dd450e290da9d74ac068010f0044 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Aug 2019 12:29:33 +0900 Subject: [PATCH 2270/5608] Apply new resharper refactors --- osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs | 2 +- osu.Game/Beatmaps/Legacy/LegacyMods.cs | 2 +- osu.Game/Graphics/UserInterface/Bar.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs index a3cd455886..e4a28167ec 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// /// Keep the same as last row. /// - ForceStack = 1 << 0, + ForceStack = 1, /// /// Keep different from last row. diff --git a/osu.Game/Beatmaps/Legacy/LegacyMods.cs b/osu.Game/Beatmaps/Legacy/LegacyMods.cs index 8e53c24e7b..583e950e49 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyMods.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyMods.cs @@ -9,7 +9,7 @@ namespace osu.Game.Beatmaps.Legacy public enum LegacyMods { None = 0, - NoFail = 1 << 0, + NoFail = 1, Easy = 1 << 1, TouchDevice = 1 << 2, Hidden = 1 << 3, diff --git a/osu.Game/Graphics/UserInterface/Bar.cs b/osu.Game/Graphics/UserInterface/Bar.cs index 2a858ccbcf..f8d5955503 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.cs @@ -110,7 +110,7 @@ namespace osu.Game.Graphics.UserInterface [Flags] public enum BarDirection { - LeftToRight = 1 << 0, + LeftToRight = 1, RightToLeft = 1 << 1, TopToBottom = 1 << 2, BottomToTop = 1 << 3, diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs index c9f7224643..eab37b682c 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy [Flags] internal enum ConvertHitObjectType { - Circle = 1 << 0, + Circle = 1, Slider = 1 << 1, NewCombo = 1 << 2, Spinner = 1 << 3, From ca33efead43eafe29d0fbc0861e4918cae261f68 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2019 03:58:06 +0000 Subject: [PATCH 2271/5608] Bump ppy.osu.Game.Resources from 2019.702.0 to 2019.731.1 Bumps [ppy.osu.Game.Resources](https://github.com/ppy/osu-resources) from 2019.702.0 to 2019.731.1. - [Release notes](https://github.com/ppy/osu-resources/releases) - [Commits](https://github.com/ppy/osu-resources/compare/2019.702.0...2019.731.1) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index c4cdffa8a5..40c15a1162 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,7 +62,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 02bf053468..8ee325c2ac 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 5b43a6f46f..b46438f766 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -104,7 +104,7 @@ - + From 58e98e53d276c96eb362f75b84cb9579bb3d4cb0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2019 03:58:06 +0000 Subject: [PATCH 2272/5608] Bump NUnit3TestAdapter from 3.13.0 to 3.14.0 Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 3.13.0 to 3.14.0. - [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases) - [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V3.13...V3.14) Signed-off-by: dependabot-preview[bot] --- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 9acf47a67c..4100404da6 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index df5131dd8b..013d2a71d4 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index bb3e5a66f3..92c5c77aac 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 5510c3a9d9..82055ecaee 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 659f5415c3..50530088c2 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index dad2fe0877..257db89a20 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -7,7 +7,7 @@ - + WinExe From 88fa06efbadc23501209021ad4df1436bd4acb7f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 9 Aug 2019 12:29:58 +0900 Subject: [PATCH 2273/5608] Refactor as proposed --- .../Rulesets/Judgements/JudgementResult.cs | 5 ++++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 29 ++++++------------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs index 195fe316ac..0b3c3943c3 100644 --- a/osu.Game/Rulesets/Judgements/JudgementResult.cs +++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs @@ -42,6 +42,11 @@ namespace osu.Game.Rulesets.Judgements /// public double HealthAtJudgement { get; internal set; } + /// + /// Whether the user was in a failed state prior to this occurring. + /// + public bool FailedAtJudgement { get; internal set; } + /// /// Whether a miss or hit occurred. /// diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 5ca33ff0bc..dd8aae27d8 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -309,7 +309,6 @@ namespace osu.Game.Rulesets.Scoring } private readonly Dictionary scoreResultCounts = new Dictionary(); - private Judgement hasFailedAtJudgement; /// /// Applies the score change of a to this . @@ -317,17 +316,13 @@ namespace osu.Game.Rulesets.Scoring /// The to apply. protected virtual void ApplyResult(JudgementResult result) { - if (HasFailed) - { - if (hasFailedAtJudgement == null) - hasFailedAtJudgement = result.Judgement; - - return; - } - result.ComboAtJudgement = Combo.Value; result.HighestComboAtJudgement = HighestCombo.Value; result.HealthAtJudgement = Health.Value; + result.FailedAtJudgement = HasFailed; + + if (HasFailed) + return; JudgedHits++; @@ -371,21 +366,15 @@ namespace osu.Game.Rulesets.Scoring /// The judgement scoring result. protected virtual void RevertResult(JudgementResult result) { - if (HasFailed) - { - if (hasFailedAtJudgement == result.Judgement) - { - hasFailedAtJudgement = null; - HasFailed = false; - } - - return; - } - Combo.Value = result.ComboAtJudgement; HighestCombo.Value = result.HighestComboAtJudgement; Health.Value = result.HealthAtJudgement; + // Todo: Revert HasFailed state with proper player support + + if (result.FailedAtJudgement) + return; + JudgedHits--; if (result.Type != HitResult.None) From 33f4b628a5fb5316f0be69d52f9856e8d3ccef4e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 9 Aug 2019 13:42:02 +0900 Subject: [PATCH 2274/5608] Make HasFailed private set --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index dd8aae27d8..a39b432e20 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -95,7 +95,7 @@ namespace osu.Game.Rulesets.Scoring /// /// Whether this ScoreProcessor has already triggered the failed state. /// - public virtual bool HasFailed { get; protected set; } + public virtual bool HasFailed { get; private set; } /// /// The default conditions for failing. From d47a8c0826c06af5595d01e8a946df9141065169 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 9 Aug 2019 14:04:51 +0900 Subject: [PATCH 2275/5608] Remove unused combo result count statistic --- .../Scoring/OsuScoreProcessor.cs | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index cf0565c6da..dc4e59294b 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using osu.Framework.Extensions; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; @@ -22,8 +20,6 @@ namespace osu.Game.Rulesets.Osu.Scoring private float hpDrainRate; - private readonly Dictionary comboResultCounts = new Dictionary(); - protected override void ApplyBeatmap(Beatmap beatmap) { base.ApplyBeatmap(beatmap); @@ -31,22 +27,6 @@ namespace osu.Game.Rulesets.Osu.Scoring hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate; } - protected override void Reset(bool storeResults) - { - base.Reset(storeResults); - comboResultCounts.Clear(); - } - - protected override void ApplyResult(JudgementResult result) - { - base.ApplyResult(result); - - var osuResult = (OsuJudgementResult)result; - - if (result.Type != HitResult.None) - comboResultCounts[osuResult.ComboType] = comboResultCounts.GetOrDefault(osuResult.ComboType) + 1; - } - protected override double HealthAdjustmentFactorFor(JudgementResult result) { switch (result.Type) From a9c4b5ac4e9c9c25527c4e71fb550809f7962d81 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 9 Aug 2019 14:04:56 +0900 Subject: [PATCH 2276/5608] Add tests --- .../Visual/Gameplay/TestSceneFailJudgement.cs | 60 +++++++++++++++++++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 4 +- 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs new file mode 100644 index 0000000000..bb0901524f --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -0,0 +1,60 @@ +// 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.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Scoring; +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestSceneFailJudgement : AllPlayersTestScene + { + protected override Player CreatePlayer(Ruleset ruleset) + { + Mods.Value = Array.Empty(); + + var beatmap = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Array.Empty()); + return new FailPlayer(ruleset.GetAutoplayMod().CreateReplayScore(beatmap)); + } + + protected override void AddCheckSteps() + { + AddUntilStep("wait for fail", () => Player.HasFailed); + AddUntilStep("wait for multiple judged objects", () => ((FailPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.Count(h => h.AllJudged) > 1); + AddAssert("total judgements == 1", () => + { + int count = 0; + + foreach (var stat in (HitResult[])Enum.GetValues(typeof(HitResult))) + count += ((FailPlayer)Player).ScoreProcessor.GetStatistic(stat); + + return count == 1; + }); + } + + private class FailPlayer : ReplayPlayer + { + public new DrawableRuleset DrawableRuleset => base.DrawableRuleset; + + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + + protected override bool PauseOnFocusLost => false; + + public FailPlayer(Score score) + : base(score, false, false) + { + } + + protected override void LoadComplete() + { + base.LoadComplete(); + ScoreProcessor.FailConditions += (_, __) => true; + } + } + } +} diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index a39b432e20..1e7cd3810d 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -193,7 +193,7 @@ namespace osu.Game.Rulesets.Scoring score.Statistics[result] = GetStatistic(result); } - protected abstract int GetStatistic(HitResult result); + public abstract int GetStatistic(HitResult result); public abstract double GetStandardisedScore(); } @@ -421,7 +421,7 @@ namespace osu.Game.Rulesets.Scoring } } - protected override int GetStatistic(HitResult result) => scoreResultCounts.GetOrDefault(result); + public override int GetStatistic(HitResult result) => scoreResultCounts.GetOrDefault(result); public override double GetStandardisedScore() => getScore(ScoringMode.Standardised); From 5486c7736277d3d16b9ab1a45dc4051f24a5e7ce Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 9 Aug 2019 15:25:42 +0900 Subject: [PATCH 2277/5608] Remove explicit autosize --- osu.Game/Skinning/LegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 3426ddaf16..5357a75e00 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -140,7 +140,7 @@ namespace osu.Game.Skinning if (texture != null && animatable) { - var animation = new TextureAnimation { DefaultFrameLength = frametime, AutoSizeAxes = Axes.None }; + var animation = new TextureAnimation { DefaultFrameLength = frametime }; for (int i = 1; texture != null; i++) { From 5073bce2dcbf8a5bce4f33b06036822524494082 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 9 Aug 2019 10:47:52 +0300 Subject: [PATCH 2278/5608] Basic request implementation --- .../Requests/GetUserKudosuHistoryRequest.cs | 21 +++++++++++++++++++ .../Requests/Responses/APIKudosuHistory.cs | 20 ++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs diff --git a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs new file mode 100644 index 0000000000..e90e297672 --- /dev/null +++ b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Online.API.Requests +{ + public class GetUserKudosuHistoryRequest : PaginatedAPIRequest> + { + private readonly long userId; + + public GetUserKudosuHistoryRequest(long userId, int page = 0, int itemsPerPage = 5) + : base(page, itemsPerPage) + { + this.userId = userId; + } + + protected override string Target => $"users/{userId}/kudosu"; + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs new file mode 100644 index 0000000000..949ce200d2 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs @@ -0,0 +1,20 @@ +// 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 Newtonsoft.Json; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIKudosuHistory + { + [JsonProperty("id")] + public int ID; + + [JsonProperty("createdAt")] + public DateTimeOffset CreatedAt; + + [JsonProperty("amount")] + public int Amount; + } +} From cf2a9db8e048abc2e788c8ee210a2d7b958c9010 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 9 Aug 2019 11:14:38 +0300 Subject: [PATCH 2279/5608] Implement basic layout for kudosu history --- .../Kudosu/DrawableKudosuHistoryItem.cs | 56 +++++++++++++++++++ .../Kudosu/PaginatedKudosuHistoryContainer.cs | 51 +++++++++++++++++ .../Profile/Sections/KudosuSection.cs | 4 +- 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs create mode 100644 osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs new file mode 100644 index 0000000000..1671073242 --- /dev/null +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.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.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Chat; + +namespace osu.Game.Overlays.Profile.Sections.Kudosu +{ + public class DrawableKudosuHistoryItem : DrawableProfileRow + { + private readonly APIKudosuHistory historyItem; + private LinkFlowContainer content; + + public DrawableKudosuHistoryItem(APIKudosuHistory historyItem) + { + this.historyItem = historyItem; + } + + [BackgroundDependencyLoader] + private void load() + { + LeftFlowContainer.Padding = new MarginPadding { Left = 10 }; + + LeftFlowContainer.Add(content = new LinkFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + }); + + RightFlowContainer.Add(new DrawableDate(historyItem.CreatedAt) + { + Font = OsuFont.GetFont(size: 13), + Colour = OsuColour.Gray(0xAA), + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }); + + var formatted = createMessage(); + + content.AddLinks(formatted.Text, formatted.Links); + } + + protected override Drawable CreateLeftVisual() => new Container + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + }; + + private MessageFormatter.MessageFormatterResult createMessage() => MessageFormatter.FormatText($@"{historyItem.Amount}"); + } +} diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs new file mode 100644 index 0000000000..29b1d3c5aa --- /dev/null +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs @@ -0,0 +1,51 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Game.Online.API.Requests; +using osu.Game.Users; +using System.Linq; +using osu.Framework.Bindables; + +namespace osu.Game.Overlays.Profile.Sections.Kudosu +{ + public class PaginatedKudosuHistoryContainer : PaginatedContainer + { + private GetUserKudosuHistoryRequest request; + + public PaginatedKudosuHistoryContainer(Bindable user, string header, string missing) + : base(user, header, missing) + { + ItemsPerPage = 5; + } + + protected override void ShowMore() + { + request = new GetUserKudosuHistoryRequest(User.Value.Id, VisiblePages++, ItemsPerPage); + request.Success += items => Schedule(() => + { + MoreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0); + MoreButton.IsLoading = false; + + if (!items.Any() && VisiblePages == 1) + { + MissingText.Show(); + return; + } + + MissingText.Hide(); + + foreach (var item in items) + ItemsContainer.Add(new DrawableKudosuHistoryItem(item)); + }); + + Api.Queue(request); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + request?.Cancel(); + } + } +} diff --git a/osu.Game/Overlays/Profile/Sections/KudosuSection.cs b/osu.Game/Overlays/Profile/Sections/KudosuSection.cs index a17b68933c..9ccce7d837 100644 --- a/osu.Game/Overlays/Profile/Sections/KudosuSection.cs +++ b/osu.Game/Overlays/Profile/Sections/KudosuSection.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; using osu.Game.Overlays.Profile.Sections.Kudosu; namespace osu.Game.Overlays.Profile.Sections @@ -13,9 +14,10 @@ namespace osu.Game.Overlays.Profile.Sections public KudosuSection() { - Children = new[] + Children = new Drawable[] { new KudosuInfo(User), + new PaginatedKudosuHistoryContainer(User, null, @"This user hasn't received any kudosu!"), }; } } From 093359c13bc05d590e227a9db7615f4dc287be57 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 9 Aug 2019 11:19:14 +0300 Subject: [PATCH 2280/5608] fix incorrect json property --- osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs index 949ce200d2..271dcc320e 100644 --- a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs +++ b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs @@ -11,7 +11,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("id")] public int ID; - [JsonProperty("createdAt")] + [JsonProperty("created_at")] public DateTimeOffset CreatedAt; [JsonProperty("amount")] From b0eb2c6e28cec2831e02f3f63125532041232365 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 9 Aug 2019 19:21:08 +0930 Subject: [PATCH 2281/5608] Remove iOS BASS libraries and properly reference --- .../osu.Game.Rulesets.Catch.Tests.iOS.csproj | 8 -------- .../osu.Game.Rulesets.Mania.Tests.iOS.csproj | 8 -------- .../osu.Game.Rulesets.Osu.Tests.iOS.csproj | 8 -------- .../osu.Game.Rulesets.Taiko.Tests.iOS.csproj | 8 -------- osu.iOS.props | 18 +++++++++++++----- osu.iOS/libbass.a | Bin 1717480 -> 0 bytes osu.iOS/libbass_fx.a | Bin 621624 -> 0 bytes osu.iOS/osu.iOS.csproj | 6 ------ 8 files changed, 13 insertions(+), 43 deletions(-) delete mode 100644 osu.iOS/libbass.a delete mode 100644 osu.iOS/libbass_fx.a diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj index 37e7c45a4e..7990c35e09 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj @@ -13,14 +13,6 @@ - - libbass.a - PreserveNewest - - - libbass_fx.a - PreserveNewest - Linker.xml diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj index 24abccb19d..58c2e2aa5a 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj @@ -13,14 +13,6 @@ - - libbass.a - PreserveNewest - - - libbass_fx.a - PreserveNewest - Linker.xml diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj index 9930a166e3..c7787bd162 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj @@ -13,14 +13,6 @@ - - libbass.a - PreserveNewest - - - libbass_fx.a - PreserveNewest - Linker.xml diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj index d2817b743c..3e46bb89af 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj @@ -13,14 +13,6 @@ - - libbass.a - PreserveNewest - - - libbass_fx.a - PreserveNewest - Linker.xml diff --git a/osu.iOS.props b/osu.iOS.props index b46438f766..82c60d0aed 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -3,7 +3,8 @@ {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Resources PackageReference - --nolinkaway -gcc_flags "-lstdc++ -framework AudioToolbox -framework SystemConfiguration -framework CFNetwork -framework Accelerate + --nolinkaway + -lstdc++ -lbz2 -framework AudioToolbox -framework AVFoundation -framework CoreMedia -framework VideoToolbox -framework SystemConfiguration -framework CFNetwork -framework Accelerate true @@ -24,7 +25,7 @@ false Default - $(DefaultMtouchExtraArgs) -force_load $(OutputPath)\libbass.a -force_load $(OutputPath)\libbass_fx.a" + $(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)" false cjk,mideast,other,rare,west @@ -44,7 +45,7 @@ NSUrlSessionHandler Default - $(DefaultMtouchExtraArgs) -force_load $(OutputPath)\libbass.a -force_load $(OutputPath)\libbass_fx.a" + $(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)" false cjk,mideast,other,rare,west @@ -62,7 +63,7 @@ NSUrlSessionHandler Default - $(DefaultMtouchExtraArgs) -force_load $(OutputPath)\libbass.a -force_load $(OutputPath)\libbass_fx.a" + $(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)" false cjk,mideast,other,rare,west @@ -86,10 +87,17 @@ NSUrlSessionHandler Default - $(DefaultMtouchExtraArgs) -force_load $(OutputPath)\libbass.a -force_load $(OutputPath)\libbass_fx.a" + $(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)" false cjk,mideast,other,rare,west + + + Static + False + True + + diff --git a/osu.iOS/libbass.a b/osu.iOS/libbass.a deleted file mode 100644 index c34e6a0a0cfb30a240d70443fa0276f6e2774f90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717480 zcmbTe3w%>mwm-i2$w`_feWbiBwdzSrxuHC6K=2~NXqu*nmk#BjBIuCt&;$yUhyKxd zr3IPta3&z~Yf)zkJ_cVyJBkA$)9L`jh|Wy~y-4KVI5T$!nx=UO&7m#L|GQ37UONBZ z=kw3!bF$CbkG1w*d+oK>UVEMMao_uYV2tT-W#P)i(`ACIyo)ORWOtZ7`x;z~- zKILTMYyI^yP^Mv~JJvJtxr0=XGnUF5^p2HjYx?sD2TDdxWa1AjRL?xwwPvyV9z*fi ze;;R+uKmVN82cZ0-#PBC@pnqn1nXE7q>9H{t#^$dkEe-N{L{~ASh#S^oQLmsRLIht znX~6sI0%JFL;s9TG%}WxPDiBE$?5drbh<8`{vw^ekxpCE=@;oVlul`I1UEmOTGQ#Y zbo#?|x-Ok=O{XuV)24L#Q9AuHokr4W1}IPP??|VU(&Mt)An@Qmrjjh3eTAZBhI-S<0 z)B1G!b~YRj$Wx%9^rt-JOoIb?er67CnJ>H`Z4RD_5=c ztn;i|`K_X>t^RdM#rkiRIb7>p-_Bh6q-XKcZ)Hzg`Piy&W!|@R<>Twz-;w>~(yH&y z{f=Jz%R$Zk7KNs*EnB?K^W;svo3?gNm1l`(<>NP^yl>UwMNyH`5(u-x?z2eaGY@`{rRI>)T^S=D+OWcTfUTw)9_heBG+*8;SEk^%B>*{;8{2 zvu4#AtcUVdOZv0qd3dgLt#Pebx^C&3{-q<&o4s`H(sgN2@;vI{x9d>u8qcaVo^}14 zAg@{44_IAxvTO0WRac>Y*Gi<`R6dYKL=UT0KIZA?$E(kk>(*SWas#PRCG~vWGDF^t zPY+^b*A_pDA6!-S#ESl&PFv~eAL;#1to1CuZV>A8eXCqc(%7$G2bEP%JnmU}UFB59 zjmT4Z*Fl&Kk+x>Zb*)kvSBH^CbW`qi!?{}W-Fekd^pEAbipcx{Cin)}*Nr+=6SH{( zWv}K=TX{3kIqO_&`q9jBt*EYATE1rKH8x9ST{p&52F93{?&*%)oZZiTSM#qEvsd%3 z8+I!1I^w1>Xdu_*^VPg>HJo#8v7pJFjvJX(&AMq>BJT$Ny!w2NKaq6<74dunv)w?t z>pHLw1YB_=6|c*ZJyrd)H|M782i7j_UmMpKJuv&eek!XCuAdDx1G7O;ZyupqR{6vY z6ztEV`qxo5Em{~OdwF8Y09OD1ulDkt<6t_c?By!YqD8K?Ysa`oyVk6D@;^qeaIJ+L z8nX)KE&EG%xUYXB0CSYVq+&tXbxdN6p51i+9lut+$O=*U$Blw&_`}ptHxyKL;lg!G z*OQT*{w-WMw_@Jh{-;#>*>XW`PxxMZMPMHdz>UbfsnUKJi&wd-7Oo^vH^VrM_S7W0 zN>Dd0Z%xvu{k;*!;pn6lkn_>I|Fh0j1g=!eg*Zr=4TDTDA(b{W+xf#X>D+D%i zG-GF0r}}Xnn5(x77gl*da97pXyVSg!VXzkjW<^QiuLYI<{S9d!)BjtzaAnoPwNI^B zw5n=hHA(7)jTlt~6|0sk^gt9ZeC!EQ{x`u`4;VBb zJJT@UP1BS%iT%G642)*Qcf%lBs2)*sPmUA-<3B3IXiYJ3Vi7wyuTexu1 z+O^je+zi7D7&bSpq}1B#ubRq9J<)v8#`=?T4Z8>Ht#_G*ZM%apY&lqEstWrzRHADU zo;M>skk0?EOWvE=CU=dkhw`Ol;)A3pTUM9>`S%e?K6r$+ zG#vm`v*Z@`vyx=utq8Lewn*+|;x~~JXA{bM4=^_yo+WEWY4_*1@ZrhC?g)Q_n|U$c zr3IYlBFkiptidzenM`bp^r8)ohnY3|wK7Bf+K4tbiZOFC@skLbI+w6f`7Ii0-;(H& zewwU~h_O*xCN(ax0OB(AESY#b!h^}gl1Q+MS-RUO|A)vwa=yuyOg!Ae()36s=0x^X zl|@C?xCAg*UR1~x{K>>rwRMHs!iN?%^hvXS^o6K4TNdR5pw&pf8+}YB?u#uu?ydl-M|yq0avTvN_M+fACDA#)sY+wj(Su1?dVE3$X(S$i~ouzYrp=9}AZ z(S=T}y|0T6&v*Q>YxiA(54DRlJ9a8lnJLP1ML&&01Bz<>GowkX*mUGP(?*X3tGG3| zq_K)cwVaO_+=hPZvtxRLO*X4N6WWrA^PNI)Hd_C^Qzx%H)L%F3XTy1k31bvnBz4T1 zAS+>G^ewyuP$veL5XO%?8>@hy&5SapZz0Sd`q}7~HoBWkb)`f9B>KG_%NP0nVbNUi zRav|o*|IS#zDXQ5QJL1Yq_U~gwiSHD);oM*W{}*!4iDaaILTha{C6@-zTc1>nw{uu zHB9W3wi3Vm61ll;EIL$qxATNC)@kY%&kmAUv{+%5PQOJGf`Y_?OsbNH0oP98ntaEr zvhT>M0UIWH53EAJS9T^7Rh`qirp_+w7-s}-;c3TbVP-7qY&3e0cn@%SMpurrHLhW+ zasuQd89l2`^x2mg1Q$*{?j8?b$<*veXu1?Jzf?O8e z3pr4Z$Q2+`gkpqo(m2tS^ifhjR53i_@u%Z@o{%JfIDjYK&>$bSr}c|JuN<@ zny5W3&Q?>e*E^na2yUaBYUa6bbC;sse}|`a`K?rIy`$VMj2!Hr7C-J}BU9}b5s zJJT(wE%RGSb)H%{&^!jqidgy z=nN{m>zb#7kyaoqixY>&9wL<=@!>u{|xQe zC>A|e^S)b>4d};{YTLEpQ(tpQtAqXLG}~kUq&oWmqSF0jZiy%mAL9==1xPj9RgA7-6vt8Rq`<0^^nH zn!j7cd{>zG;Lb3$vSQ3l6Tk~`jg}St#Nok6hXc|h&C|L*$*WX(p$MFmOx&ur%?}%2 zcoSu<1E`H4F!R$W%f<}-Ax~6mSE4piNTb$g;e1GhEdR8weQ9XZy51W=EuV5w%VC<#6LPLZf02kY4&x8&8$PtxeigDAg_DJDo+CazUa`(-+$*-d&y_S zyHYhP(kk3YRQYp<7koWJW<|-wA5m*s{I@ou1vjsE*yWKoQR8oNZwnfRaDVZeVy2hFg(gGsZH z-qS%Vuo8E7cl577pEtDvf2FJg&%9+VqPYX#U*p^24w@CILsQQ!quZv%9qJ047T+{B z)u-A!k!q&JH{SIWajkB><42C4I%oyvyYF;Admi?l#EY^1L$vB+#1_0>>TaFEKCjUk}~Gg=}Bp+zRlgO(VoSmZ3yXxY&te>kuLTGb+JVZUq*S!4lt zevVO*+}nWXWWpQzL)z9TxlPzlIsZ?Hw8lF1e|3oAD8iD~?#m9FFpkF$vldDhBdu|l zMLDl=a;bVso8mX|yUUh*xQdOqT`jSpqY2aTF3Rq4$_5i8D)W$Cf{ zH$(o1yr6SRpU&-_)nS6>OxbwC z{?p0{XdQh^(-FZUv@q!?o?+pYAgy$|^P8nAtpD~`A3v@58MhwAKiPl%bj^{y@)_mF zrrmON-C&uG$Zr`O)$^P-jb(U?&&)%utPzrDTepaEZV_Q+NJ}h1!J;{pOuXJb*gP$G z2IW6S`HZ*>Nv~mYmu2jF$I-5pF6Ie7HZ%Iu%HZQi6|ZUL#dlZldEABjjV!qIs8R=` zNn*CBjWs%}>w?Z|w+&-HoNUx>3}+gmn_Kmg>!>oQ@xbO|p$b!_LyDMqGBKrHT8z>9 zu?F(=4yW@BjcTHENk)*?&BS)tlijdloopCcm1LJOSd~}Dn>{)#Y#klWS|Ds64BqZ@ z|Cgd~gl_CPsyG^%`FC!zkD_i`R~f!!!qh%3?o(y#=ZfCD-Vt`6R*pJhIlU=j*2P^K z-%;ggQ!>$e!KSVXF0yL9PlwTF`dE-pu*jz9^W8d`jZysX z!ER;I1KuW2qdnGUT}GBwW&;~h*g~s8@2_!-yA9<7qTbxXma-_V3w^^=&8NcyjJv|D z;P>E=nq`NRe2BM`8^9~2x@h4Q>oWdy9&}Sq8+v21Rq?y)?0Wwf%8THYmbP6=J#1Mq z_kGIolB^Ni%Hn@#R_Lr<7s}!$lNI_Pnebg0yNpWb$R|8HA4UYr(<*1|Wz#X`l>?pbA!~YvL!je z_W|8VHte|L)UxQfvQs*awq{i_tX`>$4HI-P@Uc9q;j14LLOibq)L*?4cLP4c+E5uVLJ$D}3 z>R}@_fubk}4uNPSO<%GB{oWwo5zHt}JuEZa1_MANazBrNjsC zcD9z1jh+F$eN;JPYV~NNn|i4}?f?ABJ`)?E^Ba1!u`Mj4K^yg7IVEdAtryQ9R(U{Z z(7SC>6VpS>NZr+)Q;q)<9z61NxNwFOvT1$il942%5}jKvBuvJ$>pK5BV`unw z1J%IJVcC+-*G5+3p8CV2jVRd|F5GHpI?^G$iEC?0x4=@y?_nG5e}$2voZsR*LMu4q z3bWkaf>p+B7p>J;UCh^S|7ZQ5ra!o8)egDXIy2ipBYqY(j0QX6sh*FP^V0hQTRg0E zhCfI8L$IQ2h%@(f()n!odIu!4fqBaCKM>YRGEs7#?69Kq%wlcJ*)=mN8YQmv%FQ9|;O51t+>GAY*6?J-dOL*@@4OYPJqS2iuiV0{PWd) ziAxdbkmT-5#IQ#k@7G9A2KCaq;5HXGvnq4@gJUHp;T*Ev)-|3pRgcY6arPz7M06Lu zwjn*Mp*k2pG0i&S6K?{AYdKj8~iP-??*@nk_HrgdP(a$zu9ErZCPd^C?U-> zYqxW=@J7aVUhHwFG>*;qX;?6N>N2-m%m&}S&5%!^j}h3}4gsUloBI;KjOd$n(%|6K zuF`6vr^mhC;dM_f$L@L-cGkSHhjU&1=FF+(jn2Nr`ee|_q+3YOWkuC_yI&EX-2~n3 zbl1HzwX4-c`kUZj9YUVc%uK^2krltWFEK9?J+#LydBm5rzcLg&Z#RDVwOj8PEB7U4 zME1ZkEb>UM%>^q8avWb{@02RJCn9V5r(tM-kmm)^eg>lN5XM>DWr|da-F;+ZC)$@d*2#v^ zUUc6^uhf_LL*EA2Xnl$II|UikzMuBLson1gO zgz{f^(%$Z88+EZlttiP|Re8qPWX&<5?<3UQ(y5D`5t(Fl>0(VR z>TC!S_MZVe*`>^z6@8%F7XMY=NkwFT>>9S3UG$oGy8&EmYv%^cODv1moY!XAx?bj3 zJ>1sydNJA7O!Fhhh9*`5>+^XQn{4D*NuMhEroP0iPE8ZDRQmO?e68-%rgb05Ru8i{ z+Gw}OilB}31EQBN)2@oFsR2==!Y6Xe_`o1VZ%U5PwTU4;pSGSyyLfbj2q;|dt%wGO z1wY4*(G=3NvKZsXaKE8xN_?%2nUBYpnAmpiV?|aM^`OaPi+_WCJN5O-KLv;@ONO7Q#HA)@ib}TxQz_+A?c=zn#Mg~opiIuyUD~)t zcd2&m@pzT1FL5^PYi4L?!7Qwsbxi4CR8Bh@%s^Q&X5i0Zg5U^#jxvo^ifY)~A*Mg3 z?%N3_)hAfxsQXS>lu*xfOxeb2nsl+Z81u>TD)eff=6Jl?X-AzsVGjCg{7gEg_!tLV z9~)&>$JE2UEN0@gKK)_+46=4ymw#F6z%%UGQtIbX%9o5Wlb-rICBCFApiEZ#{HOS$ zvDAmv@Q9e8ai+FRv!BG>l&*X8{uE!w>+IjS#g@;Nuhv@X)@7hn@m&7>1m&-6=Qgd9aCOmM2mxr_3DpF%4s`0L4Ii zR&R{u8!!eh&164!Vm@7SF!Cad;wbobZP`hs5Nm8n9@QkN5>WCPtyA0^>+D1Pw0^2- z{dBExg3eg4>ztx_Hej$0-ehW~dYYhn1&hAhvq9FyrV6c*N+y7lY2u>VxlUo(3X@h*H3UzZ&t-Mbr3oX+>Po4$5M?+Ja zn>?vHx2sat85?^94et@gwszJTiAw$WR|mQDF=Q6u2q;d|#->MQZLHEroJaV`yRbn1 zR1v+n=-T9=eK%>Mr*I^4v#lzW%Okv;r$3+gH(T- z+kwLh9MZ<7XU}WIeCW-0JcLKHgD~|a8Uc6eVS;IWhhRN&r7@({OP~-*m36Mv_$`>n z#hAy%X^p^^W?=mnFzyK$b^%M9@KveX%;}(#ov4S z5>vZz&fwGp$@4YtGWiUC6O$k*ukBOblpFrpfBx|HCGVrPP4K}!2c2Vk4i=gu4~>4* ztCO?kXWETy6RaJ5Ig4)hp23KjrOIEg=r9%&ILzyPumW^pxOg2T`lA*2H>02E7p%Dv zclgg-xQ*Ae8@adLz)0F3^S&1{h*W=R$jD5is6Mj{LR&rN-UffcLAO4(gco7`esF;m zrQlms*!VBfx8M|{bVl3zA)Npyn&lxaCtdlwOWuWmRm?^JmU$?AKK%9kmYEm5v-6_M zdYEOQ|E~Os7}H+s??e?Q{!{%O@p+pBtvi|RJ9H*JS0+DB(j~=gQ`m)W-*sq3! z47wTUnW>J)xJe_s}~pspo5DZoWV7qBpOw zt7>So9<%u6`QY-t#24qKm3@g*=cQ$R3IBQWV)<-+iIWHWeOP_jyRkEvD-V(9 zDx-2)F=$}SmKV7<*=bhiDpDaU&2L#C3*diVRAA3<(czq|FY(5C@`?(+xyrCCjZfUA zectJr*sOb9cmwhud*Qp=m^mkS7S@2HYik)aEEnE*%AtGn+4G{FblsNoT-Mc}RkEbY za-Hw=1y($}U86Pl2Nx`ku}r&d<9SIaC>PpnQD(CQX%&|Eo9xA(d7$y{9R~>_Y`14% zO*7M;>(_Z+Y@P>PMQC>g`+qxTXbZG(Ej*C@x$P0u&dLoAf@QUwPf^Ba{U$bEh%N_A z=$AFFD~T^7^{9Vbnd&{R+}BuLbtU1CFe$poy107zLzq`vK0zq($K2RO>mhM3mdNj7 zHCt%)KER|hxm3Oro{do7umbMiXOH;VOQUb)FD{8Okq7yU?4{_cD~Z=4yPzX2&0m1B zwp;g<9lv1YG~(<_HIMQ%jjz!+BbJrf>uEUe)L_TnDvr_hX!~HT|JzrPfS$|0%ox%( zv%O9`WT-vTm<@aH@y9Oza*7zr(OoRCCEvY&V#|1$-|dLJcE9cNGgCrslY_#Tf}2|W zzQ!P@p{gLt0dy>OsYA;7#QCt4A?T%n;#AG8}e~R4eyo&EP|G1oO`^V*9+6cmu z$ZK^M3sO*el9o-j}__1b&I(RfgBZS(7Ry=l?&bNK&Fm1Spx8AXS?439wCz#3Ee!#@8<29Tpv0mXn=vB z>s4M?@$!tZAK$`5vsbgw*Nn!7zHsvH)4kVCehAWHn*D6d?KnqgW_at@uwhql{tw== zRXgebN}{gQN_WmC7yc`+B)pwg+%eq!sI%I2T&bMJgP_cK3DGSSi$Jn&U9;rAl33m; zd9Ebfolg8O?Ud3Ot|S(AQq&7;X*?jfLI3?9DML)G$amh1Gs^CV;WNp+?AY)KANPiR zLwnxh%+LnSDdp(h8``<~n?Nh-HlppsX0o?&^2o`@M>aRZi4w+jfLT__kM#xtZ#?FoC z6MRrX2_7k;DaTxHxBo?r#Heu+#*|Fy%@*a;7lb!U+)mFMA){U!GU`l+55{iI9Tu>< z<@n4s$KsEV^V!SWjIn~uU&w=%OcRgY3Kkm_a5eAs=wi2KF>|59t$b{OW3LP4)&_f5 zV72UY@$Gv&dWWropJS3ONS2~8Hbnmb>_lPL=?hw}cW8XVzGPxv5_!E3~TcJ zl#RgooP-o78Ec_VA%cK=^J^W^yzdBD6kWE5CvE8Iy}5~IR@^*GZxC;4Z{ zDGmocjj*eNE@>I1(jq1~7oAor^QfnF6=I8s6Bt|cKfT)Br!VMuo`a9Avm3wK-;>RrsdAnoIl0wme>tSnD1j&C zmz_tILf;2Cv(Wo9V;ns&d$5`ol_?`6X_2OZM+GBC6p-k{sR}Ff2R+=95iomr$jd4f zF{|m4cU4}SP(Kq^_N`WJLtRD2Sra^7ECX4y7#(Y&lk~q z-C38D*5a!jl5?-h$tK4v=!`3g7dsl^L2Yzu>%A5Co|QcB$)}Y;IPXbL`Umz4$;ra* z%+PT@K^8)K4bho!1%7H%N~|9$tnoudY%FXkzvz7uInI@Z|8ONoX0&Nv(2u2lOpxm< z{u;;#Y8&Y3EqVB&x{Ch_;0REDQjLqs@H;)M!KO?wvCuKb8_Jww{rYB(bIhrn#=fWJ z>evg*F0$48T5O6~SY3Ejnaj!Bn?6r4lMJYF>B-NKUjML1k%#_|t8sql{LsZ0l`U#j z=9*g-M_#Kk71w=v?9yA+{VhlqXUP=(_SYo&fhxG&& z_07Urt7M8O>_2hlU&T6|>TYrGrHVCI67}jXnoe%|&z$@1q&-brVIz5A(@>nBBzwX4 zHKBIIHZmARR1faw(FC)p33a|(rV=F$Q=65!I4GM~U5k5;q>^ub}>LX=sKLa$v( z{9A|(za>aKJP0xrI|I`PxM%*d<_8r?`Yx{!mX~>KY>tQ;7rF)!$l_okrG|(=5PRF>BR}vlVR}$^&nSOe&YS0Ad zSDbFa*e3E(hCq2C_I4$_=;3lc;Z-~95#pBvu-MGJXnsZeR}WX5KL-oq@HM%~a9&{8 zN|Aoo;{1FvMfzpQTt49@KRAo;^y)p?;O1mst?c$7Mzv2TTinian!A^~N64b@gnN2N z{+n{g(B&LE%Aa|&WW6jrEQquJZ12mypp*GBx@gT;xtf|vc%EyY< zW_w$J#y3mOiSeAQn3(mKil%`6EwR2o7W1k%<78S&rfo85*_FiJ3yshPzrH{+l6>$f zDM%iEX_4ia)@Gzh5aS+1Bxm4N}~1x*>XR-K(KzChEk|PsQ?Uu zbB$kHvkA)v*%&KiTM#`=xNvfi#yJB|XB82?Eq&!d&^{yZfV%$J2zU?fvQ;DkI8%aW zN$(_26-9gLLdU_wWfxdz6KA30f-yEov*COO;xNmw-%BQ5x$<^slh!N0t@`u+!~ZU0 zVWO3{!`{g!U{QhD(S7Vy7@{b&1(UnC0gv$%H#ey5O6jE&k7eH)8qU z^VegsVFi43zEVy_hUfO-qy*6;pofW%xE1)pdGMy`rP+{Ayfh~;7alfvsIBFSnbEzf zi=C(M#~vF+(?t(vFhk!3zpJ z$SP-(r}g{i0?;}t?ko;(poI;+oF)0}@3){-8Vdi3|91gpnA7&VCVSCWRF|HpPE)}h zmZ9*U4q{m`t_>)Xtr9+1Uw7j-I1%j@;@nzL?of&!tPg1xEAB6saJqtZ-_5&rb-xy?1T~rt1BN)W{gbhXM3rq7 z`m^YV$x%2 zzPh)tWh&12Pj)4%fk!$NYP&bTWlC3awZ5G2*@4dx;|A=@vuZ02V4i*hX$;Sy8ac;W z5XY#->oREz`DG;drzX;#B&AQi*&F0xQg0%Nxczx@KH}J?2ETt@l9pGqLx&H$^|hnXbMd-@?8*~T@+%o;lJXu274;0Cjx|^mraYywX zid;xNdd-FSQ6=c2v5)f~j3ENQ4W2E|dbnbQ4~ysO+9bE6#!3pkUOBa{;DrFC1yGu5 zNQ(>s?4lYgFjEw3K17)gNx;9KXd@YJ^s{;vs!Lh!z@llRD3{7BsrWQKqAdIO$&GGq z(Fd?Ij%I>Ndt3H+z_-kIgrvyT7#PU3Er{0}CRO6!;>?3j>n-fHasp={rKmoQ#CYzE zQfR8U{VaR{Qy@Awrd8kk&$!la{xV@(0ZE;{#Mb18xzsM}D`AWw z!0$=rdegc5D?aApS9ynBw+bV2foG6})qGhSa%pBO#cXQD&X(KcS3)k)bt@n7%~!z8 z${vCwV$F8rIje*GeGL8x9`XwxqdyqU1UTEH!-DigZy@AtL^~K!+7oxvNiSO8>86M6-gS!2%Ijl#t|M^1X0qz zGNc#D$TJn~ftl@FVUHHc3*Zr@_Spg0l?(XypqCBM(%R>tpLv93@9p4*SQ{UEpJP_V zKe4t|uZH#d72aeoyVXZ-V zDOt~u8GVV8K4y6|kl{yUG@fq9(}MxIy;aAg8A_>B2d#B5^kA;uF|++ao+Ed)i4I;* zx}w!xTX819N96=~JsZw0ZCjthd<7>W69Q9};f&w)n*Cyc)z^4jjr4$m@F(dl5f>Pp(vvu+)DO;Wy9i{J0Jl8AARyW(( z>M3!44xTxxh)tr;uM`@CPLGH8=;OG!*;T0sUaTt2+S9$-SU%VIoG$I9ZPgssgBk;C z5VmW5vy@Uc?;Wy3vSer+9cijXz2}syR%Sk@Q1tnz%==JhE-vv!UbMw#vK#zA#J-VF zIIR?ZPw2@U_lQzTHjl)|HrvAiZT%+u3B;lb4O$=3_H4x`0osF2?HIQedobPMWD)Jd z46w3G`}bkJ2}?(BVt5Cg6tfq#_36FX{EcCqq0uQmzYo2-rGv{P-vyt$T(kXaS8pPR z-h?n~h$jp=vUa--dshoqd2fQ_9Sn-L?@jcESkK_c9Oymu<)ezufVM%X7hi&v?s(lE z#Eka)DeA%Z4HSji`T^umK6EkQ<~*#7v9VFNx6DRrSBh=?PO|7PR>a%B*F3Z9Z^Qnx zE4l8+4z`ot6J%2TRsR{i6ZL{@bZc=sAx*X{D|9b#zY}ui?rSMG<=;wsw-eqe%H&a7 zWP^vK`I)#uNd?Lw#-66c2IwtTeGn}AG+If8nc(wvXTS8!Q-({V!5&hE6*3FiR~~To4=cV7JfzrwWhT<` zu(f8KWhDe zti@)kLA`Q}0=&tY?mxKm91nq7vz1aw2-R@(cU04qRBwy@DK0ySUQB(9PoO?g&NKE8 zT2lRb7bU~8xD{tZDqU(Tl3m{YgbkD%3u+bC*ppq4?Y~}&u$KQn{P3ee{ro_C`WyLS z3(lvHxM2;j7i7&2gWFxM-|-prZa-Jl7tnmwc@3T|vc7@%LAO0~XK&(#cAeZfG{p(e zx7RS7!$p6j(2k#t)}31bnZia0ZQQ!gt^{Vw`|QGwrG6hcViBY^d?XyvrDGn3-vzT_ z+-JkTUi7_s$mAI$Ya5b@U-T5Ib3VhbZ=m^}a<)yKi;M5;=f(Be}Uk z5p&(pOvezR+n4C*HZ`w`ZekC>lCzp9+VgK}tV;6Uq2S9xepDIeodrrEg3!&jH@fN& z<3O6q-|cjz?oM{6tX%GI^k{>tqCaQ<4zGvP6?9=A&Jo*(cU4BI=O+Or%d}_Fd~lGo zsM=kFhz-2cmt-Z9Q(BgKT9q`rQ&xJl`x$5+R!_6k>NdbifQA@AHtcAO<;eMzeM`E2 z^aYkB$|WlvZASFvo0X6^i!NC3zwpANYGl(lZC_VC+`P9+s>*ZpCgxs{mYlvY0OuKq zV@HafE|HdEe(-8iKMh&-vrQi@*UB3_kYbQ*JC>8R2yNkm#C!2!rC1UcIU(&FquvgA zHIRCfUxMXGclV|4jOWy6A@o@_hnJ5Hx0`rew9)#_yfmen zZW&I-4c!h%tF*L{Mx~_IsKVLHac7#Zn60FPEpma!HwDrN(yR=%aT+f%^9Ct66L(-NHpn7K>*0`aqsS9$w$7=@Y+Hb|LK$w= zxaZ)`jyrxAAG_Gy0L==?1{peeGIX{Hr9Mc>$)}WwtrcDO%)!_-KXN>xm{Bsq_oZU; z!7g1fQa&+-H=+NdNFthGsm(FpyUN zp<;G2^ADBcO0vK4PKzP0(=>_RWZ|XQkBr>cawzG|ARBoT%E+!X260!wMxMD^@=Uq} zD|~`@SB?G40KHjq@+QEi?oEL%8S{Z2)$84x?uu8s!@5hSwI8IDq7F`?Bmb~CS2_=#lY=Wj8U&yc) zAhXyktc7!z2_v82#A^9d;70kMk_Y6^&4EAHlJ@7~EbVfnc4Jt7Qk3_Zgy(fWEn=U< zonF?HI3Dq^ijMpR{i~MJhT>3q(0brkc*qZN>#1R;=cSQTBACtmAg0zCNQt?znYES;tUgDt~3< z_njw=hTWMj2op%^ig%LzWo&>?d87{KO~3E_3w)o!odV~AhX>rMqUySZ8W zlJ9o1Z9a+>ah&QG?dab7%}JZouF>&(DwJ_fZRjH%AGg-I*B%QTPU?q<^))yj$a;%T z1-xO=0H18_PR!_U`XkIj{rZO9Ps<B{w9($m7Zyu>VWGem)=jd5>&qj2^x_DA zR){p-UleJ4bWwzj_J(!S0d+p!K$`9gYnS=L8r)|*El0%c$0Fj}QzF{?ACG8P=p%33 zKMb)MEb_{2!y|h~3z65pZ;8C|DE!E1FU)?gfl z0)N;zKMKEnw6lDAQ|Ho2=7@H*E#k;->U62TVkx4@Mt?vl4d9CgUpQ+z#)bRrNlP%^ z#StMJIPM3oempBMe&C_8>i|CkcoS?5U=z=feBo)>*JvVy z#p%dT!`4ifCSgXVV`guH&H$Oyj2GDMypb;4AgTPc&)#y;wm*6YqL`aB&vT1$J7SrG zt?|qnV?8&UChB~d+wT~`qCMWs-CWYqDWSn7s|m5|faiv9 z!4?h3$8|I86b}@l@BKVbcpdC4wcjZo$O3FwO}K9Ew_rd%E?#gTpJwTYj%)mz;)BBL z_@MAQx@29)2U(!YTQMo?yKxZw6pruagGTVdr2Sc{_p4Cmj@)|M6<%Y|z*9u{HLe zUF`X->RHjBLj=${WmFT3*>t}SYqsFpjq43vkhT19L)E>5BY(VyzuaCTjwf@R&I;?+|&~rn=2J|5VeaNJ7{{(t%g)VFW&P?DGrw_r{ zcZIdUX(XJ$lfwCUL9lF>V*$Z9VKkgj#A^YiF9fIM(a4z~`nhw1U{C3d39BV2yMvQNC zKka3_5tOF+vqbY$ABg5A;LcTT5q#IChragl`yPEv(tGb}1pi$5Ew4Wg+iH*esI0>d zTJQbPy~d;uZPFPL7c$kIr}Rj^#x3RqZg zL+XF(NbW>Wp1R`HT1BHX}9xCt+2<#`o1;U)YI z;3M3Gm++@>3&1S`x2C`}K?D9YeUJ3wOZMc&pY7K+OqKN^Z|0jZJ?#pyvo&HDfcTP- zH)k%QKF9*e3TcI$kdEgdq6<3GV7iC;g>PBtp(P6>I+-Z7B?pc!OAb(V9;|WFrJy34 zL^V+RYB_iz`%tnmgS`Jcpcf&tP)Cb8!qqxt2XM4cl?&-|&DHXL7#meQI>6APPKIi0 z+}IBdU{JZ3F4uks48o&Foeb2;1PtBPI;nn$up}%zRYzA!^*{?ob#2K3qigJC$$`Y- z>Zmq?x`>YuRcrC0Yrj~(K-TWYc?hDHwzKVcr{VVeNAu_Ao4yBGWH61xKIRrJ?ly)Q zR*qmuJqvi|c-Ew!HF&0#B^qwePt_0!i}rvW_zDQusZ(OTX7^P1t-MTcEpty-Ot*3O zj*5>F8Guu(!jEy1huGsnyr;=NhR-H^#`M;;xR2}4qAB)*$7}+P~>#nzjX6z^fn?Lqv1DpJJCD87SarU;ptO8X-@)aa3=6erieudPKq z5X)UbasOWOoC$cZqtJ;jh7CWfOl+b!tnaDO0zHZO=PAyhC-ETC@yz>`4@;&wM=IX)$fXDGcoY^YgHK%u&Z}z*p#KtcLWM4e98W z>B#Hf$Km7v=UZErv(myAqnnK!=nqizq?L`-w^UDA;9g*wvFM}|aoMh^i}j07EUH^H z!{uLWT0#`>_X}pr8{`fT8zuRP+Qu|iV;XCJ%#1^#n3?WGYf^_dFef?@6I0oUh}{f7 zpO}jFkeCqU(r57TSr=mu%glJ+{Le`jy`_vdH;*PI)Ye|DUBEbef?8&EHX`yWD+zrc(u^yK;1&7~O<_i( zN3awI#7lo)iW43K$s&{+A3)SfCE|8tS8#{elRu+2=xeCJlRhS>r?q=Lb@uZC>Pw@{ zUPA0oqubrex)W0(^nN*ZR=6)qVi#c2JKb)zYH6It=0ZO$oeP^5IbQ`zYh9WQi4iA3H zQ`)~~wl|q}un~9q1$WL4_=lSi<>^J-Y2#-e?GAs1aPEEhwuiOB(~5Jm5!+I?+=2IWw&9(f&FxGqDc83xmZ!>( z$k~|rTK3-8GnUsa2fPW7;0;hq<;TjX%Ku$lvSgq$Tds7L;!P(O&8pGXGqbQ0?+$E+ z_p^b(5dqF}w~G@EJ~4EA*Dy-D3klNVDP6SXA&|JJ5^;bBCauwrI@Lf&c5^Xn0XUBg7^@&ZT3 z3k8lH;M$h3#Z7Tv=o#c3de@MRKGpEd-RKL-_lHgOmP0x99gqAr+S zzgs@z%y)4_1m|uSUYv`s8N7~n&{(^`n*nby-df{JWBmbyZvn zydDx5&O+4qZozYR^B>*#B2s2U#ZkO#Sj(!X;C%&`s>##uH1+%RQZX0!){eV7u?JEA z-HBfz4nT4`osCYP8jGZAd6^-x)4LS`!wYF z@cHN&-Z^Z!lJIqZ4n3rP6Bl~ux$aTp(Ob_ZoPJP#cVZB}n%JGl>mXXt_uYsNQ*lAl zUyV^>*;|{2AnpfeePdYkU~R_RU*P194bz(u)v+^U=cnOJV{an&%G*l5ZG)`cseKDE zCq;O(F#39TS$uGrq`r|)-yH2ud=;Yey$x*FUk}H$xsUq~$27UN=&)Lf-oaXpZm!MP zCn4hJJfbq#sMdH*t)X5&aig7m^W$1)VRzz#o{YCSVo}K^v;f2UZVO`HdJ}%UW7!&C zRtuXEB)v0`9mA-HQA8b;euy`h*_hV&{91iOMt#Ou!|s!}m ziHJUBq?dVjqAtXT(!1;P5M|4v72QF~?~nlgUuzt3_izI&OYn}4 zsPR+BpFj<2JE>Q4qQ7x}4aJi`EDMN*@=ZAkUZfc~R^urY$DhSYel>Pn$d+sEe@nx^ zU4=hLh5x%6^nU@a$1>igC<=m`(>nutQUK(afxR2wtm?NUMx=4bC?_1x)o@@K#5UT$ zPQ#A&5N)zl*c)pMSVM+Ozj#ue#dNR#r$>f$OQT*_W9zE3btm5I77+moIy2}roUr}{ z?{ss#gC!!`Qbd1__i(G&pm$RIV{f7br8DtW37UyRJ&0Jx8$BCEerdZ?@XfrqeKoz| zjW0nRVrDUT)wV>$DB_2DxGdD;dpWQP@jZp_sIgtG(WfctkZZ%{`tmT#}IhtPt>#WIGIQHoCz zwllP(kx%YPr4s>xsSq@3oPsz0M{lZRWDmbuG7Yw=H~t>=qk$o|g8}wgz;>uJ!J_-U zd;;E+#!5(bjoP2$SED+UdUYm$?ZuhBnDJXyVv@QO|9zR-S=HH4x@o7QcUo1>iK$Oh z(@*W{QyreD$A43wPB^ENW%kXJ-py_{;;R;5HPzWyp2fEZ0@MdR`tV6$9^QB1xsSCq z!RB9#{TIoUg>5O>o#{_Wmc!ljEglP`&@*ffEJ81<3}(EgH%pl5w^4=@1Ms#ed&SbNkdpCGSkNEaiS};3E2M0#D zZ6o%z)Y(merb}#L_E#whQr(Sr-`cP{2#WRHiD?)9U(VhIys0YPA6|Rs(louLrG-)o zB)ys5FhyVxaY)m2g9uU-XR3oUDIk-yAT2r$aCA%oodPmb5d9ZKsn@~FXbU(8R3_!- z>42U|1U*Rc7@TvY7t-#QBzva?`u*OW7Mb&$|MPv%=OfL&t-aS?Ywh>`{$6IJv7#8o zqu17mn_1jH#cZU4HYOk=N#_xdMn|b)kg#*P*^*BL-%7O%O1B+}{$}G>{73`jja0Sj z!$f!o2c_{{X7IzY$Yn5qL$fKTK+iiJ=^k?x#T<(Gwsc2;k_dfaP*R~ia6Fa0HE283 z2`L6BoScaetC?r?y1v7-Z2(r~pwxBC_CK&4<)boU!I^P8Mh~%-h&$UUyo{OP3%BC$ zYdE56T+yNLL8d*ZEdRm%e!i(R6DxO}8gKT#ZT{H@{Ujr+-At^LRY>gSFQD&@KK3|TMpGx?pd>)!2A^QGO)cnr~iGcR&LgKG&jui5Y6@jJL^zlYW_;!4FCh^40A zsj{_u9yk67ZQJGgOxA=*J$PDJEJY`b>nND8qdfKEJvN|h@v#{!+q=}iguA0XebBeS ze&8~-N=6)Wiw_w$GgXamTp&#tXyHwiZK=6AZ`_9Yj9+^rE2X$0F_M%SsQOS-r0Jk+d0G!l+P3qhs5ZW87>R zd1SN>qw`LE+$kV>3cchM^p}x7Ryg5z2hQVgw2#O88Gma(sh90N4&H26sgnlXGT-x$ z=?&uxWPV%0ffsG)vo@3R6l&ew|NR?o_W7IrCk*u;$3^|Wj!WjqxcqO=q>)+Ftu)diH5sEYlPHOs8=czr3Q!-?$hu`RZS zn3BKg7MIza_4V5hFw?_j8y(z6T65w@<>Bfl)sWXzTGfZYvm?S7wv&jIKb#Bc8VC(X zBhrw9rx&VXVxla%_S@80!(vrL8b?U>4i4AcibLy8V2u$ec6g&e`anG7WtUtY=7F%N z0(zD=zzWO5at-$4YI~Q(4cR;7lZd|)dmZ=ceC6TORX77{gfGDECG^ej0<#NO^uAs= zg3GC(^y`7k>5qFk5Q|L2`LPUC^ zcccxZPUL&+hD@53D6Sr)b1Qq>FVm4ku|IO+azwf^TpkW0?~5fx-=6xT_Qr+sY9o?- z15wRNt`bwmX*8k?W2yWX#Sf)8h4OIw5_g}$jeDq{vKy<_{zf2=GAHZP{gIhvUqrh9 z2F=7S_*`}HOHh6*dHqSBS!#($6X5Ho-*LD2{I|3;;R_{;96XiCzG0B_-*eZ3i^h6o z=OW|+aWfHJcs3&C+((a|pDzc$ zmMdDAnNXQ(tEPGBE=+vdjr&-6=oss;1$iY`wSyZ{4=~f&aS^EjUOBS4sSApHWYLM6 z_&Rdc$Q#T}Cx7r5`?EGHd>UlcLF^8!&1xlfCvaA6nyvJHP9)YZqDIDT*Xdnm;?17B zKAFBEU@ygva0R{~*|#loQMWyo<=zqD7aWWrvfiF$zh7sP(-0Akn8UNYDHYZ)cWj)H zx$fb0c4SXy*|&7x&(D95n~payK5H9e?>|d#s7M+^Y+$mbv<&ZRTnmIU3yVlufs)m_ zCXoMspUnMx?H5YR459 zJ@3D+DU=9fs2&+ZdL})KiCGb~u%Pvvd=B5}Snoz>zF>3__cF}2;A}oJCW^r0wc<)p z>T>U9X9Thp%hfnmxR(3N52}ibfnR(QZI^hx@-7~DoWAC#3Dar;zN!7!uyV67d%1Lt zS8n1tGqT;XPK;xPSjD-mJ^p8O9>VNp#qqGZoEmp0P>tK!{#LKN_a2s;<>!jcxPLn{ zAB;%#xEtr7y_3%W9+!jnT6axjnt&E<%mAxMUb!CICzb8JS*Ahk7$#z}n_=XBlrtw$K6Aq?%Dzcn* zVdcYbU`=iP-gUsH^3tjccjV%khgfARhuSn8$E|1tk^o^}XL_!IcDx3pWrb4W9^-&g z8j-{vBczYvl2q{(toMl2*@HVHo;la>noZ}efE2+rG#3%6;}bf=OvsBf(3NM=k`vcO zN(bzQ+{&Yv?aJ%l1u_wH7e$+kNXL6j)qIvYgDAzMEQ1}CwgWh*b@R$1(xDzg^Uh5- z<4zv{sXrpUha(0|W)_ZXEfsM>~PgKSF1%e+1lEd3dE( zbCU;ZL&u*WYW_?Q5Wn%haUEaNm}M=Nvm9evue#o|slD9PjTkfJu0TTN#FPkK|7$$y zRvCzJfL~UqtQLskI{1ggHOy@HHW(w);vqFg?{^h%uV{vi-vJ0=u5{laCGwEHZfmluCm~Zc>vORgKT^h9Lh^i$n>iFr>WHavpIGD zOr9dg5&6tR^MprG4J@Wu@rA)Le(Gy-56k%p*3$H$H05h9@f%$%Xf0_CS?8cqPta;H zR&hqhqw4;pEP{OB@_~7*6i|?bLh(IAl0D?@dT7Irr2?W#++&g1S?paZ{PG|yI2OvHB~(bA=K<6c>MB`^Rn2i( zsO+NiBnsNyrS_J&WECe#ky$z64WZeV@FhlvRUEm1?>}Cc*%~i?hODi0k6mQQfJI#_ zAS|z`&k?QVU&xs)j{x285zsv1?iWDM(!s|;)5U3W{EHXl{jixb@d>xK$!h175zO?! zFJ)Hw=#9cY!CyXb%}VnYzk8jXf7QKen{d9BwE1lU|Ek)Y=G8T}^{W`7QDL_Lz3w8} z2s*K8Fn)LZ4&AQz!KI?l(88vkY50ZE4V3GtLi1dDVxLd9 zmq$L89_MtHMcps+{BDa7FRlk_e?ICD96^8F7%zT9Pkv7&g-X?edJ zRx)=)THnR|Y9P3gEO*7HX^Kd-UHgS;Li{WH?Fp~4B2|aJiR@foxZ__ugz-&yNp~@^ zNxcX60fR6_4Lf zmDXAyz2vkY=1gvKw8?v0RM@J;u_q2-9aZRd(TZlpGw{akWV^~CER}g0mcx?{pQBSU z0BH@h6NZUyzq9rTc?t=ivDT_98|RB}+7Cb1=n9Pkb_CXn660S1x)d|=9k5+A?+M}p znZ~&T<4nCaUZgdd@M?6W&Oru8n)Zyg zI%R2V-+skc$X_%Iv0}|NS$bzgw{1BpOK%Kos5go~3bMk$ER7;vX;i@7*C?`rEV=pu ztC*j@1eLdQRf{bG+Rbul1eYrH5IrAh@!VnQJ4m7iugz5>u+@++bD5YTzXJatT{*W; zMxM9ELH2AJ?-6~fx`q1f1$Ikp4;OzzW^GoNHKWm{`LfcHoN+?dHGbnzL6dyg(d0Of zUPf{E=vnV58n3~dKhY@Ivt(&ppLsPC4KnHul=&U9^pjiOvE-I_Jci0FlYyKE{|2*) z>F~H2aM!55K=*wb?~v!MalO7<*awS<~#;GGv2k>I^Me2%2lcR zbGUPXghI-~Vvs^85~nSYSZJy)T_#ImMQ`PdjTmL|hQ`F>y{|yuq|t7?8E3Plg`R3t z-e#Ov)4w#X5~J198jDL2Z}+r96s1|CrLyYO_@+q7SrbEaI9r4zU_=eYfn zJ-k_w7}lW@A5}(?r9bqVS95}X163-~03YXh$78KiU0G!oFY@m42Y~CG-dMeQKIjFs zd=vAVAyqcQv$W06imc*wcY%u!)@C1s%rwEvvJQsWoJAx<%sAmXXah!^?@Rf4gI9ju zdXIC3^LZQh5y;Be5y&ps5y+X<7)Yt+ z)-(pjJlq&aozJ0aR8F62VQwG)NM0YeS{NRiP(GYiY#&aI<_sWS@et?>Q6Akz{peFI z_c(vy+-Bpy%;`(zqR;)(m+n6pa?i1f``qONOnY+R#FJ$;=xc}4S1bBzSmC_K`Px7A zwb6M5GKLXfZKDHk?{UgAp)Okhcu{99|y-@WI z{22Z5e4IeDAJa&3udY$V`dTY%`pvPsJ16m?^F>5OZbwWR@XnPucpz8HT7MU=LQWNU zW~Z~I3K740(fP@+TkD3cn(`aCE=3dF9DKdR(*93hA%eL3nLZ%+CLV$T~Hl z9W<6*NxqA$J)~*auA~&Qe02w(&wb08IKS!F&^QbBdo~9q7jT95Kn|r5p?zcYO)38@ z_i*UYGcgyB;O}`)dpUpcWY@$kgcYmrXzBmmuW+YajbA5jkT(ZRO3Z3AC|tBZBojcM zP`E=2FqH@o(+~Xy(ha^{%HYz8ThT62Pj7%~r=V*$ziEv<94t_*j>tP7wChK{$Iq@@ zkSh!iftw`=F08^#PnVN;T0U@VS$+^Tf@I+TGh?bhU*Tz|aW&`Ybk;kgHI;yhhZRg$ zy#_D04F5kz=nU{{(|knv7fbkazx5`zSYRWv(T+E^Xn;A~Sq;vhaKi2(u4qArJzP;B zTuCQeC9)#*p@dp(qbxmf1)M(VyTDFhX0;cnjrj5q(Y;%#O|-1HnKG@;v=h$NX;o3X zN0kF9%)kcKGNk?d9B<5v^k${y<9sh7Uh+`y=Zd_*UvT%v>pB1PSi6uE3f^%Bv6|_7 zW>?R<33u5n;EnVBK3Hjdp!Rv^{4p<*kImZMZj_~hD=d$s&(GZMPAkWXpL3Ax+Rn@l zUC;ToTsAU~PLtmj@YIW0g*|1&O)O+YP$>hAfq9t&pN;*YZ1NwE&9&^VG4aN+yxBE zQbE0k#szUOCe2>1hcmGrM92Uw3vp45;*boM_>%oSI@kr&cXCsK+;~^Sr+QW8pO?Ac zp}}Zsn`G&co|sqOUuJl}cUev(un{q=$NxD;lGf!HpVNO=<}l?y$IW~>>{>5vI7G*r z=U%!nXXVP3b3}Y+st;EJ`|bnVUb4dA{P<<8Ox9Hf`3_>6|Z26RVV(p$KhhR%~jd1@10dn zu22R1KA?YyjME_+=NayA2U0l5Yu)HYHdhFHA05^3L#qB`sAAT2z?~sW9o-^mq6VxF>-GZkkdo_YMA}L>pP!HC?<4E-)U%YO1P66fUh0He{8c6P= zRgYS4;?~I0FFuaiJBWU(h0=l9X|lAqyXqm>*S%HabwC~7T4Ah&H7watp$=_bB1_(( z?*i&uyIb#JRACecvkL&|GfA*ta zM;qdyFUV3_w^(g$z2st9CmJR2P}qU5)dr5L;q)mCd{i-4Ga5;i-kXNdZSz|gzM zWJ!YenDF$Lj6_D;M}DV`{N^aXR3p1|;9@NQVTBxP;qK@-V8t)%QH`m$d*#g)UfFFu z(e;yZuiS3g)cOtV{AcBy+=Ft_gUEI@ly~!`ZSsHN*#7Zta;Kr?D6XK^20Dr(kitjx zAq~dTV9@k1T_QAdS^87gS6xQVJ-$?_ePrZ{s;9MfK33(j*kx&VSLe#+s#|BJ@yO_X zXif|UHSR-q*$mXb*B;}_61?YRcLg(_lQ%oYpn@r+2yv2JoUyW>Y2&cgZVY~hD5z1J zCFJ!ktm-_v!*XQ*myBSs-zo=;@E;A)wXet`YF2w+RIEbkB+ko>b$&B&6py*mJtjx@ zV_R*rJ!P)HWv~se_aOEj5~>5*&WS;)kje7LbT}V_^$}TNe6kPy2qH6Bp{n1;)+E|} znW!nqZ?yHn-oo-q{O#4X2j6wo;+ii}my_yEP(CocX9ZMmVzkx-=waaw$j zkKo8`B}y3I@fB7bt+++qopn}a%>_Dv0Kp|@9I!v%nqNK7RZ%|6^LCG(ADdnwWI1g zIcH=&$r+U4Z4&-N-Gq@I35yuts_I`^F;XY)#t14Ty>MG?>xXop)S62(SFnfsMa zqwe*ZJ*b0`?m?zr#`mjO!8l(NB5-#Fw6h|^{IB^w)!kZT)<8m;1=P@4v_9VSsQPm5 zraijP82`)I!u9hfpm+A+F~~K`d&EARwmL4rJ*?`>yL;QnmB`nfb;)VN6)Rn(S7uHi z40=aj-s*Y7e_4%DxDA$)=Tabbuk72u`t2SbaTHXyGRw8Y{ths-$fBm{*`m6L>W2pZ zT02Ik05P9DvP@^KRcc%=@8h>qk1l$$T^aTVu&$$Lk@d(6!-rSf@GQy&E*nnS&h?p* zg1}9o8owlsJ&T;CyRo_#iBB!= ztjb^JT=vegW|!K0$NBF%f%=p^HE%LoB+jw!UsmAf`}hQI3gHS+t1PrS6L!~jR+*I+ z8POJF#%sqhW;8EL@l!kVvPAqoRY6F0bF9pC3e_Jp$`SK2&d-dUutLNub=Vxp%F|(+ z;$0EHdG?A>Hi~p_L`JUvw*eVKbxP2nqNtXZjWbcgk`9t zf@&%SrTCSk7e?+uu~EPlaB&~KGbVau<4vv;52^5cYgo_lSyvRL8IFXRc7#c>g+df6f?`&<8HHAUEG z55`{A4ywat-C9+YCX}HLO?`K~3N~3}zj3qp;<782yY>Xs1w%?tRLE@`Q;Zxw-~^;D zv<~k~p!`iE^4zHh>OSK{iv1JE57AjIq4US6}|?vyJ>>#d*$+I+Io&d`52WWxOuRHZ3EEAv;(Y=HYXoxrWwAfSM+)KS6!DpIkVtE|O%TZ>W1r$g9 z-k*T7qEvY5fgO1S7a6!5`h9^XPvgCw108yAUtm?w#$Fws8r3~nADbxk9)lfwYh1fW z?7dIX$s~yd=qm;%+(+NA75Oat0*~t3`qGmqdyow`Cgh`KD`;FR=n>_)APca7Y%A{n z4|n$|NOj)@?uEYWk0X2(%0(od_}13Yg>Uw2nbI#>50Z31Y0c$PThq|`{ zx`Et7yzlG`vK3i}lZ&ahpA0wuJ{@+FXhfVb4pDJ@TbXtcG~TYoH);byiWNE~t!uLL z*GKhm1?60l{^bf#^tQSMWPP;^^s3{w3i|@N$~ok@WN=tvq_YzmdbD@TuY4C67e_iO zC@gSTn&alfpFnhyt|Qw&^&2=Fdb8_MP$K_wcxe^cS&~*OUj9^2qaW!}edZsm_a9@{ z=&wlnVB5jsGx%+{z4z|BKmFqK1wXyCVHf@0O|+_rZ>u2+wMNiYMJbd`xhv^B&;_fl z7VbktaP*XNTNzQOxGR!Wf_RHj`%ILFH6p@7Rirs9N!iz;a@jb)c1SHwGjXV`B1wqf z9@tlT7IUPPE z3Hrabe;S7>s+7|k3*Rc${cGm#2)Q1Bw~=KR*@+$ zT*UkMVg_^)k{%Qaphyo{Zb%QH5465%c1d~|JxkIK}AO+k% z6t$VR9Nibl%Rsf5SRe}}vMl2L!(z&MQ6EY)EA)qCVD3pbToEi3=w8>%Rv^XgHJdNS(lsIr$%dN8xCOI1$x z{a6>b+^E#3kfd1D%%j*q(nX{E6c)5w_^FX+|6`4cH}&$ykGx%)>}kp>^?`?~6droG zTY|r7l!p?A4`O4L_#bQdVjZXG0?o^bBMwWmhA28|RKKHGAx+P-%xr2L;j=pjt>L|O zq#g5IUe$X0qg5y6bgbCl-Q=L7x*Dxl@W@h&Q)jF3)}n%qS@)5PfrI8#9=e{mXiayi zpz(j?N-bGjuJe=%H&?6i*43J|&OM9h46RnoM+RS94|xx(rJz2*;UCSCY8GYn6ZQgD zWdXA7t0`xDM?gJa7*1XYoPrJY$PF)t2a>4T+~L$>D|nm{ysjRUQ(2$?KUVK+Bdd4x zor!<_-+0%LQtjk#jV{uftXGobhKB3&5ElncBf8F$FM#^Ki*Mjvl3MlOf-7v@*f;6+ zBg49%;2K2}NyfSjN22RC%EO`@EHlc%h5212 zIgBK2>e?45(G#WD;d^-Kilv4)p|N-CHe9LDd5drlp0=ioj#mh%8nLYufBi2v^v1p` zLI0OwS)?b=8y>%!=>Na<8E)72WdUvAZQvZdJ~69r>)p85{5IGy!E5HjXHl>TJO}rv z0i~G_PFf8Z0@*b)QtyE6$Eu!6 zHANsX>WAzgy-N7)qR$#`DlsZw_j(|4Z$fky6PF-D_om$e zGMcuAWaCERg4}?(jOQK5-RP&Ud9z{*a0!U-jNKP#MP|1;o}Uu$JFMvZQzzhh10nFT z{BhpH(D*a_>M1d#cSGWBFt}Qq@HMCUn?_{iTd(JRroLp87Uwucj-CoRIxCN5-vj(? zGmrpw;u2+97p3Y#$~Jsq_GK-Eb~qn*o0Sb~ z0LERh27Kb%6G(pe73@LIp1&L@F!tf8#Ts0_HIO`iPr&f-1$nli98~9mJWWB7xb_wWj!v6Q17p7O}nz}ScP1k$R>t0SOS7vy(ep?XgsW5We`g<w?|XZqx^I8+cFgs5%reb4%cnc?9$Pdr zcp{y{YBJDKb-vmMON(M1N`lMjBf^?Pj|sRs#QL%V%t#pwO6B73|hk__68sxlWpSd4~|~Z z)_{g0+HTJDNpnb^yhT6RMv>oGNBU7YWg>JBZY%b-5>*^~abMtmlI0<9j7T7)jojSR zLOQwkrgRefZCFYku|xbAzp^i2&mbB~GDszm6h~<%QR=Yd>)jW)Td##Bv_c>%3+fFj z`~di4SURED555anYV230)$9vQn@<#*<$;PO8T;JOR@y+j{g9@~4)T2=s>@)zZT<>S zTJi)rdfy(Q_x?iC>$YL8UWWe??}LaQrsY6$HutivaXnf!^#*(g^oVJ7IR0ZV+)6J} zXRMn-PbVDhAC$Oo(oy328yP5;*!4^J@;OK=E6D zSekHygKW1Hwp@znS7Y|O11f)N?n1v#Jd2nT|MIYO2`Ky&i)iy&!!1U{pX%v(Z!ce` z)K9kv^D$bNsvG8Ba?}e)oZ6Q)d+13g5zTV4OPh@fMCtQTtK=l&($r1PgXlK`V(&pk zdOrIL*mk$W%SjRBVd>96_$SPWaj1Y5mfnUAOnpr_Lsr&I5BV!-UgG^cVsUu!^J`)0 z)9V^U;`CbLAOCuc254>T8Rjx)Zq)LS#A$6T-!Eq2X7RgDcyn0()%{5MV`wqtE;jP z++THKU`Am4R-z%=V`96C$OGG_b?BV7yZocLU&Zh($uS(YDI zPBmd|f?j+Z(HTtq*LrPeDR-SJLzs*5C_2tQ^ zHlN&pjJ>%7%S)o~GwY%dUb*=Az!R`MTE&&PhuMg#&U4tn-|JJ1!DT504IYD_viw-d zh#5_SaU+e|`Wv_!IignaNWIZ%5;h*FC}3i%J6Qc7P-{?~^6@=5*Xk}=e&;1&V8zJO zt>PW^asIgjD@J-Cc*_SKC^>12# zX$!_ejrYD2&u0v+r{et#xPxtnZLE)d%uG59P#|ng@FYK8!wOMFB1;duy;Xd)zO^QY zY7DC$U(VTEmj}>~-&TDVuEp$G#mjCc9{2<^QCcZv;{LHWTB_AftFw0bH<-UN%=$uQ zw$8eP%l?d9&$qDlwqXuZaP8IWDVT%l^@u`t|3&_#n&V5m4aOMDqOe@2v-&Zvx2_bU zU=_E!wV~&#sAdnn%h~IMydi|w*8bbTZ>{yVpJHAfwVoKb!&q-Cy@**I*)|Fby+8Ap zEDu)y(QiQx$uq&nKaBWUJjH=1`MaX*KD{Mo>X*8TGM06q$FK-F?C!OwWEqdIYpRT_ zeva19Lz`*tQj9727$sz^P6G}3VhAz2$-(M|WmSG5{P;*u5ZUkJv!~<8%A0+d8jG>J4>1v#pZj+Jd1UUu6Knr%V9nGWwm9$V?|;0{ zBGCvRx7EaDAFKb1T$!U59$%J>QA{zFx?hs35Z5uoaJ+vKAN#S-TI#qaEx2Y98sJN1 zs5Pg@C{A6z)-^#qHe6Rt?|7^#2q}nGzTHrej_NIJ9%kL0UWN=vL%&XQe?NI2VPQ9J zCkzg%qi!N9fg?ickpsY8niDMlfJS&uu=E4wKTz{EzDic`8|U5L4&a(76{X|P07u}A zoY_`agOMx2O6Bd|vLm*E=RrqQ{094%aYEby^HRG@eLLD-E|Sm3>*hH7$6F}}Pd z<>NPo_AguaUvHncI?lUgb=~rNjv)JEZM~s2wBea{&ql-A<;-8Z{5OtA zP_+bpS*+LPH?*M-mY9V_!N#>F(1ORWX+!Q`;+wBSMcR`8l-o27wql=hEc|30YEqkC zl`m+F_BQ0Zn|yUHvoKa{jhvPZoEP~!pC)_dlcv*%nDxp}rLcn2@)B&h`2_=i;wYXT zaYt;u{j^*OG_Ic}w|jhseV6VFrz?~)EG-`_LVkGZ3XPy9y$$^f!ZXSAv7+II5jZf0 z+smBK3B-3Md&QbeWKPw)fOyo%j9qzKD|%v8eptRxbD+C(?H*Lwf@^+EeTF9uB#^opt@oN_%3tCxnxTJvR&SrfJJl#mh2c*;~p7 zN@49#Hyi0`I@2Wa5)7afR(Sk_Vn z)Gdd`FFI4jagj=;)&RX*%W}?QsnVlAEQ?yjihHiZkF@P|*aD}yqjB@Jy2YwOC5B$( zO@{cypJuxG_JWy2-aYN588_D=}=;rBfQ z>Lu1Bi)*jN0cGeBA@K~*^b4AMR1}eBVMWdT>bPXoykbdN-jlkmjlAl8w$EA2haV`IfV*II$-qQg8fqtRw@ zrh9Y($>wbXe|Ik&a4d#5o2RvOD0{sf@iNJ0dg4;Jo{b#W^DMVmp1q*8+J_vGl=QM5 z|KnoKF>Kel5TzzI4$*f-5(P6Ozm^;0j)w${mKAHT{_hsnlc%^H!zWlTZt zW4V_zmgBoD((Uvckcpt?ELe9|Ct9&@@pnnZSww2z8$OEoNDi4M6)o#%b)&k{q2(2j zn-0ifN$xy{`pIO~Ad5yAu>uq)KpsEHf1R44xPb@Z&qAg&dUkePSn_uss5y+Wric{k z@$oJlo?4ICNp}rrxi|di{dg97S;02Yv(PK1eEAyG9-=S$5b#b?DQkl>w$e8=M%+F) z0rV!mbQiJ(qes{c$jFcy_p?Ml$z2n~-GgD&gCqIWgKObsQd+({Sm%nKUmgL9fR|P6 z|8>hq3-{o=3Kg3m#tcy=u8t#0W*ex4MN!FE#(E?yKak=vzyn=; z2=s0!5(k{T7Vsav*V{FjYgt~mJl0P*H7;kHeBN*;tVk`8;cAz^huVc{5iV)6nZMX} zfMS0Zgx^|h#q1f=qV?0fu_A}jaCtE{ zEx=t7Gls*GUIsFXo9YG{qt?8UoCdLm6ZOLj!tRpj^XM+0_aTy__`hIVHHru~Umh!d zgY2V=z9M01x%!)20ewxdnx%^i!kLT7ro(|Rgrrub6~&sGYYDlAvw(K9`j!EV(ZQP9 z8U|c{!h7Iaa2CiUK$`&7HW()QLJ}|=*+O1bH`GNKixw1y<)tzspI zT`&4k|6{=tR6@#GS{nXT$;2xcerG3n0DcyCNLq|{GGqI3H_^{1C!x9?gh8Uh8jW&| zTp**U5nesIU+z^ZXqZb;=fN0HGVVB3mB@)t0KT7|V+}^s5z2{Yz?-@5a|+yK+%a=I zR=N?^x7+-5E+0P8BGehmS-K!>Mk|^fvk;Ol^-{f$Tx3W!(LFM48K^l@WSBT2w`*~B z)knbM!2I`89U-jDCDa$v+v2?SsJLM)Duiapc9;Y&DsWI1*mxg(L-610UZDP>4enfo z?;S{yYJW)jJ2KQc2g|bvx5ijnFb|1ClqpT$fe5|)R=o|j?)SDK7hZ!o`vUrH%nnwZ z?Oha6d0fy#rX4Kwi99e@6Dd zru{Y~IeInd)3eBC`0A2QoQoQyv)O{M8W>5@6Q@zTKL&>@ZEbF!P%=<=x#`w(yMFyk+-t$a}}|T{H}E1 zihjyz_lBfNy_#2uTYd@|AS~@3)bAg1Qno(Dr^W0E0b`S@e1#-^FGY1f=|;Q7l)v{o zH`OfC_(;0CUuc_4#}|YjP9FVgCx~aULfMqZydf#|M!9QIxLX+^F9C|~L~S)U&CZ*b^MoyzX~l59JR#Yy2lj6W_5VtNL!iag`vO{} z4qyScccZpmNO~zS+IID2JQG)M4^-m#)<8&Vfn5O4kK-=soA_60Ell_GugXq?lDSL! z9azJ|99)=o3-B%^?UhRNZNLtH+9e)V9YES`RI&K5Puap zBe!#Bmf1A2CM;Ea5pTQu-) z1?~d;*XI{U$G9Yr<>Vm!hNPl^x@l3+T^B3fJJcbs;OqnUOg%pE5YIVxK!<$BJx$50 zrIE#YGfjnjUY$wTai#|+*~Z_$PG4XEO6@8WH(fRBMIehY$mUN1|0#M;6C!7S@U8a0 zizvSi`5c#TSCxdMfh%XQ&3g1Ww!&1Kx$_ZD<_c*$WhrNwTp*n{$=tRN@SJldde&<_ zyuNh&mUWZ!kDgCJG<$Dm{Uh{DJ+`?SJ15kSKZCuqGkxq-z1%ccy+<2tOEw_m zDdIFZD9bn5Yeh!&8QH;A3K?SQaIBx^%`+5|KD>t2Rl+H&pi%(-(iQ%_AMKgs$Hae1 zzBt+1+!{jAAY>Te`zpCflf2FmDxU^<3ut)2Ifx=+q|1bHU8wL+VanXpw*6|2sMq+ec3HQD@&!cVdc(OpU_g6+7~e#eT* zf(L#C`W2EUD>!nuc~^o$!2+jP!mNm5nCY$q@*pq7K|A2H1Fe5`(p;<2(&)%2(|P6x z-5FfB)}#-%r6iY~lpV=@@pM7$DHW|8=ST!q%eY1o7RyQWvnH~YG4oL;S;#WP$8V&K zSj#fR7ohF@b8JkTk~`R-j9HsvWwZh(Lf4Xk{33@_?bRqe(&&r#lN@tSKF=H&r++BE zWZG+U<>TocLqzAZ{pSKHan=Erc1~X5ZW}Oa$WDtmHu5D^=LX$lsK$?txa@m`*Q601 zY^CSuJSXMz6(Q-ca@S55^7Q_xRwVL6LR%l%*wU!*a3?6BV!`_$6W`jCJ+d-5MnN_d337a3H$P%Q zjMgEiTtrm4_13$_xB9@L8f@{fMh;2o!{GlTUi8MJ;3q?r9~Y9ADsN9YHWb@FBsC)& zj}Up>N4;HBv!PXTq;XIz8m%G9b*xwLUGgEJMYE5OJ6VC&YjK%?0Z6hJgf2)8?abf$ zX2@Nl%Fq4=qpI+!=WP$4J&wrT*KEb#EDBcES!>io9GegHm%oSimX=rA(VtZGYra3R zDA5~Rl;ZnZ$yJ`?^~x6)PxpV<$%%Ykexb&BJ0dzhMa1(|@3YnUe!j@4Tv>V0E1z3z z0;&u{eQ1t*-j;Qiucqfs`euR2tvszX%u4?rK3G>?nSeaz&c%BFv#WIea;Fw|Jj5zm z33YN3W|tMK!HvF9q6kPDXdhIhfm}jlB0Mu1EB%jSC4UazO?0FXV46SS;=If_bEXns zs9pNY3HZ;kY{G;U6_BVWd3LyTc4R?fd#ZQSx-mcqiS_MpS)FwBwUE13V@~|W;4~hD zf9E2X4RjpUZrem(h5XbUR+tWa>b=Ibx2@-1F?h&p58G`xPwOBW(=#mnH!8idDQP#?0*^?Jl##XI27-$YXd@&C-iP@)g!$6>%oxio z97Z6BH|BqIs0DU$jJ=CQ}4qHfiu#1_B z{Ec$ZK)fj1%T)t&KweVfl`FV(J2;w&nNNC-jZ+Kb{hOV~oMdfI^(86K%JkHuH?g1; zuGTi!imZyVkW}0SUyX@uZVDbuiIK9LbC_xH@+rJ$YKBf&-lNfg1`Ot8Jlf;0>%Ghr z?3nJGadZWzwr@` zX$*eTFpo+8xc*dq1+Mu4`1S@?+scX`1OiM*`p?dgq>dCvXL#BuHz12ku@{ybKISxs z8VzIYn{4^tJ_Mf57zf?%1hUqFiVkTElD59|Ahv+sN1TC|4?j)9<&%7H&*;%h}tFL&6<#+b`M8L z4}>aoN^UZ!@jW1hBughI3|oXC^ndsjZ~D~8PfcRhsGLP~D^*#a4X_8LgRc-(%0xbV zwB|w_u)kPEnrH>4e;U5SWN#4qV6jQ-4@&o*!2uf@F&O>ra zAD@hKtNI8jlzezb_*)5S^gQCvVfRKBQaiS?kSmOphz#UnInPh`$O5)>yn$9@P+HiB zZ9so2_vnhvP8ko6fC}xhNn-^f402x4T1=7&_14nL37gSllVHtg$9@p;|FkZ5ULK|K z=aI=8FPIgr#VT%eTSXnRKoNT%Zm;UBS`8fm)%Zk?c%)sF8TwuWa z!!lO1%(v2y?Pr#FJB7EP@mgVHYFQhU+Q(EhcAm7?pnGt#i%3jLv$?yZCMIlBLxvOm75T)q~cfxmM61pE!guL1_xNoH(JGk@~g`fMt zd#o9wcn4}o4Sj>r6^AbkI&n~XS-}$^35?`4`(RMoIpT?r#vGy^EOLxz{&SA;X~g^X zG{Vvl#Yr2ItguAFUbA`7nSynz@)GI-6Zg9l8`Y-6sI*Wfkfx3*;6O=J0X6N0l%PmC zOni7VA?h&kB{zKQKb!4>JyF4BngC3Lpp?@KtsOSBsY2rJa@yX|`V+8U>H!j~Hf6llp1MJ6IU&N_5o)`dqMs@(N zU?$BQI93w7^KapTs`wW#F3(tz(4^l*mZAb*LQ}c(GpE}1SS#uhvpK~TcK%{eIv;?f zy$<#3e#-ha>V990>8HhqJt|XDlQqL+f5^@zEVd^{xI);-3kEx^;qzs9FH~ebAv;n| z;61G2_KHlr-=XXGg+Cul@eQCrT6HM>iQm~b0-f_`@^phyXqek{gqyA@mcF6y{XyXo z`u?w{nKaPd8T|i2`2Q8%Mf}SrTI5wcD3pRPlMR;@&HeU8xd<3Qr17U9hHQy7E^E|Q z>)`Jl_vnJ0E2B8tJ96Po(u+x>oIbYux>V(j&|`=1=y zR$aH?J7QII{5pJ7l}{3eaV9W~f9TNnpVuxC7X7=fOt*{BaV%vdPnmqNN}n^Y7Z_Rh zf7RM21*KmCWxyK#*urwDUkN}^YQyOK=l7hEnKnZ|QulYV(jZ%_D>2G^p*vs3TQtHl zL-uAjD795QR&PYzinf8H_2*E1W0AN3R)G!~2;W$H@7Gh68j}99F4}A_p~}n~^=wGr zVpXh+zjr4h60cOva!r_p;cId5Q_NfL%H;Cd)%9*_N!K#O*(M0|tR7emI^gHGh7+fv z2a5M`MOGue{MLT&e5H508YKA@U^g7>OOMD}1gWRsxO z1e*n&1D-wZIL)fHybKKfWXN+`pSq_Uf|#}>C_Q@xx~BI?-BYUKO1^A( z$9BPewZjPh76kr3^$mAtkTYUCfH_rf+w6hgm2r?Y(v2}MZM9{2&})N9w7}kDgj6zb zJ& zlX|#coh166@KdYgBe;)|?2oBNdgmRs6dyA$@Sz`g8?8#!Q_A3*;#gLRoMJKJA2(H9 zAp0JK?asz1YE%y^t=8}|%{XS}9<)p~=+UYrqK4;sp67nsk`%t^?vCeecU{m- zpqWrx7L-ukVg~SgV-MMazGAP-ZU1xj8IXA!&x6%!+9)9kKljAnv8jszAG={`BGX< z)wL+v9oN4gj+PH9Dhb$lG`Cy zPQPy;WyD_1_iVz^S{&6GH9ebDxQ8R%KGn_@w0m|zq6tc!-7m{i*dqeXTOLpZ5U~aP z=x4{Pk?VYovw%ZaYTS@m&UK%X)%;ho%+oa)v1zy-gv3vUhJKx2>3k-Q26m|IU z70b4NMKmLgn-$ny#vc|7iNoV>#`guK#%>xd8Y9HN>R&|P4WcnA)sr|pF(Gj{L%EW? zn?dPclq;Q(y@S1VR9%%}`HsPigmA2aJweDRUBRi%h(0&^n;| zr{h6s{UE30I@7v|Z$ivSB(5na3EiyN<&E8wj@dsYKa~sH60{ke$Pr!^YSeh^AoXk1 zX1=G2Baas3>G6~)cuH;_uiwr47QwQK+E~!GnbA7%?KFnSYzE9=wu^gVZ}y3SoX1t& zI+dy{vFV1?pjZNK_kJd~SInrgRL^X^Zy<+kilD-=t|8bdPszJnX6MW!_YN#(QE5LY zg}Tg+sm4-x^*3w4VW*yw8#KgO7ea5Lo{jgFg;gV0pOR0;8WkS)afAVXi)y$j7#OD! zaoKaLkESfF;fO17Tv_-h|Y%YE)aqpGyejJ z(>hJXCy>XUCCd2#_VM+Fo?FX|V^CL3>wC}1S@@7@Z4=>(`rmUl0d17DDFcwDI30~b z`OsH#P8#W{Iy>)8+#S2L{*%Prh$&kFS;SO9-`nP|WOMmf^0Y@UC?g~cJ#Cz7a+W

    3S0yH5=kSNov|u{^zsQ>(YUSl6hsD$~S)#eM1gd4+fZ7{tVj;i)#ZO5p=oO zIOL$7lJ~|YVy%ju)R&hBX$2>|O54+~iLO$38-}MMI0KSajAEe)y12_atnkC|Y4eIK zGAg$Or7*N;%J_d8zEjFEFs`yFzuP;T@po&dAAf(}X?!e*_f9vv06)eunGb>nLLe7Jb=dMau`?zUIMc~@F zl|F6;u0#ErUR*Z~ns6qh$%JpCBXw1}2n}}{R#N3}=(T}>BGr>bx3ROl#1u6cj^kHB6^pC(Fdg0X$ zs;^3a>iZGjk;4bW~?^2Y4&M(-Kh)mQ!h3O#L0C&_>k7b zd$hrAvlj%}s_5Aw#Lu`9g_j;|E4|x`D<05z?+ah9BMn+_P4JHmx)-Uur32}lzD(;M zJ(FxL6?KShDKg?~D7hdTE65J)HgUx|XbLlt8*aFRn^q<-nDD-B5c2=?D%5v0;qJeR z_bh$Hjo88~95>xw!G%N8P94i}mM6s`z4GjGh`-x=(UzFolvoKt3$FF*w9e2B3=gGqLWdr|_ z_Y@t~W(M6;b+C@Cx2qwY{ti((MHXZy07n)zI^$2vhhlHw*kRYx`1@%WM(9_k<+g_= z!tyspd_&$Nuh$sF^dzd6rejnSQ%q(#3F-81_2YNQhq!b^&2U+9;%~2W)3hPglkej# zkKRPamWp6Wml%&HAJ~HSyPdZJ`HFTIf8At5m_2L z2obN?27FHB)({3n#&|pBl()m);Lhhe^sUdBfV-c67)TEH$k~Qt{lgr0#{yYB-d*VP zL1u(Tpi44hYkgWWwv9N=g}HZf~zzu+fQSAng%+i1^59PM3N&e zYNn>yc@Es_{Nk4DX+Oe(y1PK_jh6ZpItVS8d;Sh>8!2%Qtj*|LWmaO_e7ZciFi+gFeD$VDS#6e$1$?ssYi|gg2C)c2d5Uif>wDJ_y-3 zt^dfS>SXi>$mBB-si?{Ha#@_%z#%&zSC^jz3$-zg0TU6_AdM?QOd~visW^fPbl6Kx zi?-_W<9dZlj`!_Sq&qb{#ApjHY=9=oN)mjBz@6O(fE0N?21xA;qn49aZ{xn@jqN}~ z&(W}K4x^caayoJQYtng?pX)hjX{haABqEtyR@a57^>5{MCkF{WBUL zy-88pZqQ23KU^UBcH3euG;gPK8Q$hq)}_Pdu|5-`6m50u-eNEf)P zx=`%{`ufQI&&j(0&-$iAdvH;B_%|(1y*b@yan&Dq2S|MwOVl7VU>tMOK0=(g%FE)n z9%!`1&?sxH-JFg5v2o(ZLo=Lgir@FzDvU+0an%;32gt407=>i<_G|RyINZgev0@Zy z?2FQLWjs9U^oBpubdndKQ>4*|FVSp;8hBND`^rhV;z5#JUc z(8EHi+U+*EBf1_8@CCy+n7eZP*WfOdt*FhHvc*N*r84bnaG2;lpSlv|GCfM2r6?~M zPDm77$cx+rs=EX}MJ7HA#AVc`bMsAU;#0p$_mqoIJ*er{s`r;!yVbf%SnvLdh?$iK zQ^ndfnVwhVILHb~h(;yPfVPLhLUC1^d&PomBu>0trakKw^2w6-aZ#8-d-xkOz&AG* zUbb^Mn(5&Y6FwQ9yHa>@-9m<jE{Htns85wLX@AMA;9zO|v4CXFBWLrnw4n`hDeKa9Nzd{brGKKz`MlaMA|Qr1$olWw+!Vv694j3a59 z9!dczE;G2zq@XitL8-Yt>LhM2QW*myQradt z2{b2dDfwUbNs2l%@Av!kSCX9NInR04d%5oGPFVB@_TH87`S&Un@Qgf;UHp^Els)-l zE-J@h(`T~F#d3BnxS$045ObRQBpCIX{5;SByP6xFuEpR9!~2du<#UqnVZ4W#`;^C{ zK5#x3_!{q<+I&IzqA$-}g{S`=p6I)LjlfdV9fMENy9@9aTJfeEI@iJ%LAJ~cSpF|4 zt2-|s?|QDe4EOEnOEQ=E>YU_}8|h`a%2q$rV}GmD zzgK*UaZZ22 z*1gfq?)nqB{l_5AHkl2VR!AnuTF_6??`d_2wOWz_`Cv4n={b2=j6v=tzA)&MPm}le z#*$$&!-_Y*LkAz#^rwf(v9xr=3Fc`M5+^ySL> zTj^@BrzbeetXO@%7;!;a+d)3$7pUal4#KnDY(B-{pk~}WZ~e35dRK&2+g!4L`Le}FYHqu8Fji{b z6N6Rt`{i>xGHh5cAGCGoY?-!Mp3>?KHdpw>a<-V(-qqNDT(Wohbb11S}_A%9OBE$?slvmEmfZkJb7G8~)89 z>5YNC|JCItU?(;uQLArS9={5{7w8X^cUTYq7n9w~1@~Eiwl(?F(ZWYj%rD?=TRZrh zgPv%^V2TOh3RWN@0-hoqL-}uYo<>B%XdsEmcfe&g(DOAYIh#1QKN+!2_482l z2rFdrZVgsxi_A0g8u0y&o|H7Q6fqANP5Ov;wU6FU@LW)SfOnb6(tFhZ z1!(>ERG(@-W^ge^-|q8m2}Jr4AkxWJb3u9SJUq}MnB-RrxZ;)bZ+9}IwgDr?;^^e~ z+azI42C_4WSa+7dMm+pI)E9QDd(if+YS~OaU*869zGAef4bcY|l*i#=r!uMYtd1#Tdj#Zt9Owh>#+CG)Lr<8|I$*H1%7$gMDplGq zD3#~uOS8inRTq@odIYru-kmBZUDCRR2F+>@Jqf+iQ!i`)FEz3Ox3bEpel#TS3Gx~A z8{}XYGH5@}gK0x%lt;oOYu3v zY4h=E6Elqs8Re;$&Gr?&T-3m$PiXmb-@b@>RB;HXdtWO!+l3KCOl4n!bmC z<3IlvR{&W+do^P)5@0cT$dTeO%t^>_Bsu0o;<=Oqxe?du@h508mt{y* z_?`nfz{RXKL>MGd`P3u7tD|)tdGUH3r)hN>hjEGCclw-SmDyPW%aRD3p+0ShM}+TH zL9 zdQsTKt>IVS2J|5KT2`6lq~7^p{JfxC-A)!vio|dPRv?>NJR0MIk`1N=WYcKiHV{{% zh-_K3?q#%RXD-4VpjD=1&nG`yW9WLJ!>I0COrBatYbLG}g*88x5LT4nsi>(nUdpB@ z@-Sj8a(KUmO@QU!>5Yl45yrH(Uwb#UXS4FseTd)vT_-O%OIdE6IuEcenBPX$Bz)%T zTT&#=CSbM@6-sLjGFXf1>cKVOs`V5rDeAE@tvCqnnQaF@!rY6ld78Civ$eVj*eH|% z%r*8D>qM-TquCCuG^y~dHmJEXv|d8G-V9sxqkRJAw#lN~F$rsFsdT$k_tqU5HbmVu z*?6z8;f+z>dNrFWrI8rVf9`(*IHRpJ!`)xP-uGd2t7*RZ%jn`Mm{rBde^el>&+p|U z;QLLUe_fNU_k?O?%nB+8ud+ONuQH!5L52&@j2gzU6V@q2j)gY62{mP*xjPzyw6yr zveDn9gfdb&F}2%u$Id!t<{>pH<8 zJL6icBrdciV>F)mhQoMQ>>rR(dX?OM^hU0BBXVX`8qKs`5X(2^oT)_qtf`lCpsV9b z`NbaI7gjQnrGTyxks*MtiLW$a<%a-ll*ZcASWT^W?hzVTVoa&~BrEdLI{tf_`68|0 zEIX`x8dxSd5J}F=sq&++UpV740dY8#E#=>zus1LrrPGK>_mm)0vq^q0s*w!Ri$4e( zX{4Lv2xfmNP_Emtf3Em}_N}LXh~L5Ff4Ds7HzDV|oAxOlV<_tt+M%#Ir(<6br1*0X4#FUKqzHxnm7H~#T=o{xHjZ_vp-J*3GX_pZ!n z&G2iCLPIOO_CiCdJgP@%fQ146oab-_?H0%Jhi~Wexa0T}8p6uB04MV9HvFROoBv;L z@wAI}w&k{Y-?YIBcUd{mFSwJDt91l?F>}=2HmpSb)~*cW%P1+Vg#DZSWd>sYA?^n9 zLm{SycquZCSYZ|vAWCeMSz3d2@ynJq(Y+!@NB=1E4Qgwl#eN~UvwcE?SqdvV z!Bv-Gq%jpH{6FrddWwM+tHR1A_4ly^aw@FA_po{y){M8QZ#JgNnUKr{53)TYc6rgR zyT9ifDx2x7c7tZ4PW~@sDWm;5tSt41l~?))srn5=28t9&w%`KzH;g!ON0NO9Ec#|H zO9RGdme;TNFNrk`z{QaTq6t!79AU=G-}LBx&`e-;64H3!`$+ewbKDp?2}?Oo_$uUz z3@c~)b+V;D4FA8*K^!(WM&6mCqrEJVgX9GAm4%h7{6+T;eoG@tnfaKje(i2^pn_ik)y3NrFJBI6OMBQIxdD~R$(s+-6eUIl( zJFHctN^X{J;>3i_+5&6MutR)>9-8RQOr`eHS zQ{~{yrybsEbCq}Tma4_jXh;|0#b5hK>KFp)pHHW<`Sj@+DIcktC>E$gUjdcsY;Ik| zx?L9DV#U?2Gy_Q(zfJcb&O#c3l8&-{D9M6z`m{_Bccq?O`bhPd`u4xt=74prn4ZDX zQ*hUNY(?{7WI?&!qZ1J!dgU$+e5O1H3)A$BmeUTsuiZ&HPm#AAmRQ(Tna}YR##cEs znA26r9SvmRC$Jyutva-uHY76U%s@`O>-#OGjSd-*8r6Hi`gv0ovsIOk#eIy+HTcqH*KY+Jcg-uQ;&S2X%%u_r zSO)pU^&Ol>BWG!DxAJ$BZm0*Ui+7q}1J`TFnv3&EnvNt*eTRnU9a<0JX@wRWq+-qi z+%!1l1n_q&F=z8~SP?#94b50jR17}p+1XL*JwkmUCvKmp%9__*UfS$(E?*p0+_;WS z;2Z+>UuL1J4z;_jOwQaFR_bAyh}%WTU&Bc^h6z7O^BZ_Z5!q3EgW>ff|ISKVkC(7# zbj{a^YxtUfzhc0KngSataw7KWq~D-E{lK2ay*<|e7n#gx-2K9{7kOz0dD+Bk;U~f9 z%AW)q$5hoXyGBKnjr6nwuQT=(p~}X2ezT`(@pc=r80bQG3bd~Dbyy%B-50goTYz5; zF;Uuk_wO;sM)Zv^r{Qx5-p+{6v_8FgkZe zT7$6vcOX*&K0oT9bynZWbQV10NQZjO9(tZ5M&A$D+~52a_CDg-BCmU04dGe`Fs;aE zc$wBVLJHEVMhL?AXPlc}9|8_ZUG0tm&k|PF#LG|AVO63If9eP$A3RoV2PeLEF0A~e zH`Tlu^NBRKl(rkg60C6Qnp|UP{-~5IrqM;CtOqQ`)Mu)#3%LyInvmlI@q|nstwvs$ zfOw@{>en4omkC^QlfbUtYOD`5Vt0Bt{ybkxfUTN`J&aQ`fDwm2<*CwQG&aGer}LCJ z>z(sT%?{=)FKs$RdAbhtipYi*Q=*q@F#@?7vxBduJVt`|2qM6_Nvo}9hgH2gtk{6x z=YRr5HY@B))sg^TVNCfHmP^q?4AATq%BnHI`92WaeQTFxR#?eVYe-o}!%F1*BuH%n zkpE#tJ}&}M&T-L0B)#CTIEu0D+sm!tve+7Kr;yF>hBYes+yK`*IM?)dj77VoNcDIx zJ0dG7u38H{5jhkRmcRqf;rm&kRbIbLf+i)v?(uy6cIhtQLp7d1OZ!O^BhX)#Wez2G(q8$pt;Tk+=q)vdWLS4mh`V zvsxp5yPj&5udmzMZLK{I{t1_SYuyg#0iaJOpAIXFfvg|-&#>ae=j+H#$T|2k12*5X zMTqc%&3C9IY}igQ=JJ7M!pm7wGO~^ZPYW+67iD>Y9mVmN>e$55E%6u*CaoasMs^|= zUWZaLUP9gRMw!dN6`A=EX2$+L^b3wmSjJR#wq)cy(ygrXk6lTnh^W(n=y1H-uTGQo zi>?&vsO07Kv`^7~^z`i0(hEK|-YP4ucssVLttP{A1zbn?p(=Xjz80al7Im`9-{UGE z6@j1nQ>C!ZGT-Fzt99MxqSDva&+M|iG@DRJgV;ojy-X%QQm+eT@YhHWpP@UCy5c>B zSYY%Xlizbueg1;_+>@5|xv;J^Dz+XyLuYoYXL9Q6oK#oTLcYJgL^eTYd>bXj-{xiY zn(=t5>7@aFx2sNumFZDp+idgg07`e%=L{CPVBI@vJO0%L-gyIIr9K2xTa@ZOFf!`Sgq2azA?9~{>;3te^n|YwF(3xHanvHu_^(oX3egSq15ZXqt@<0o z!1et^o_#EO*O?p(?m&%op<1vvq=tsFf!_}?9e!tA`Mnepk;!2{lYixo$C=>_>5NgO z2i7I{5y2fsxYcp+J@aN^-6iE|8*ok^TvpzRa%#UGuG^$t-AMcRSJ$+KKQ44WLI5#jn&L`xS7?myv!PYzb>Ra0QS5T z-;%+a>!CZ$Vf3H%w^ph_BhD^VYb3lJQhpOdRO=@G73Lg*Ij*mx^^?gPT!tcO>(Jp^ zRs858Sft#{gmz$sup4UUcC_l5ywbJT#=;%0Z6T9(m^=up*!M1Q1_Co|;%q>ehm=9! zbFj+a;3#9oBj-i+&%x3$nqS?oyp^ylLsu60mj>|r@FuEu-BuUv-A2{Z5>mbow845* zUb+@p4Plpjk@fMDT1UW2;D!|iJSCerqSCB}wCdjxD)> z)auINfM!D>GI&16LdwB_RSGHl0_CUMqDNh1%S-aGLdyESiKl$ZA?5SSsphAEI{ngw zcZMHW4@;zwmh5?c(KSHiLWkbK)?`WBXHe{$RnD!e@u9rSL(KR1Xa{5y@AmAq-RY%z zlfCOCH0Ccxgp{WO%b`Wupers%%~qIBI~pA%wGc~VNU065(-HQ9>2!n#NIQ2qgALgY_Gm#<;j!<=)t#b={O{4p_mx0k#9r2qfR|1tTQ(Z>D1qj!do;@O_(u!@qxV&|AV5p&O`g0gjGRkMgLm8(jF10j`|Q z^gWZ<6^8jfh)(@ruqp`V$BJkCM8 zZAJ^tL%}0#gjE3fXSZAmDbM2kz*#QOA|2||-vMk3*f@{Dn}UALMkcKgBJ8ra^zrMs zKF!S^jW`yqg}s$8J{En5`WCZbcKo!!<*)IT z-qnnpVkI5UdPGC*bUt7;*amqh(`q-Yyzpws3y}@>O-D$Xav2QK#(@~Qkg~a}y^4C~ zgQ(c_v|rfxv|p=A0F@pW>}rIb!`s^4PSkcE?0`JbO`OOkpY|kadjuGEP({~9B=|5Nc_=Icsld{@U|U%(roy^(Sy=?#;2(Ix`+cMLq(|TAn z)`%o(CC3cpP}5aLb?(`~6BE}p%l$U`t?S#Uuc@RgA7$Q7|H6+lMY?yt5Q^z8zBRk- zyccUmA4eEm3-ZcACo6$X=a@rkMn-ygYTDWRBdlN)&;QSNXW{W9VGv*U`p;@yT2v)~ZNG%j~jL59L2xIJ%0MKBaWERTkRb> z`v)C5D}xOn1pa@LqNpBJ3wo=ca&J>^l>964al!iKe*N*rCdw+UgRhmr#)I;DX>E84 zJ;~(7eQ~Qss%krU74ef!lfHC{YU5yeWaUWq=H}e0_IfQOKQ{3fo+jt3(w&x&vI&^_ z6qO5Z9IkgmjxTN-4bD~aGz|9?-#^_YvRim{a+vW9!@@>*%Z%5qnIeZ(4VTd&s7}c=uJ%wzr%s%DGiS46=w4-D){G z8SXtkEqsE5@^ii!inH`w!j68AXk^aUwidJT+i=eV6U=fJ2p}w;}6hpl!q}!yDj}fKMN`KZ>hmoKJQp zTM)V1)Xt23;QHuX&eHJC$It8Bq}yzFHL{FN=0v+>tk$EByf0&Q$Z0BuKPF3*Ypp`T z)Rw~`4KMcc7qx5Rvfzn?+(v#`l9K*>J}2{$J+gC(bhvuVY6)@hq#GP-c_fofnCXE9 zqi{BIPbRZ58|Z%EA7DLT&XKRb3ZBI*tX)y1yjQnr4n8Q_&3f*i4G4`nJXEOtrHKvpgfgP0Z46@OWTB zukd)B%kcz3N*zU4-E_)Soh8+cESK(3N8n`dc8q|@K9=_@l4}$Ab8n3n{7R-#r~aYl2;7Cj4p8MSC1Ir*UmaiM2Zxn0zBvTkPr8 z!`D1u_h7lXNYF&eCR7ml+=SdkGGFJb5EYq8Wp#N)Mz6lHnCeH^U4Ll8Q z>|!D1%XZx+9==%-x*3?!dTi30R_4=fYLwQ(>R4Mhw__EqohOZ0BdiZ8huXDLM#GRz zw@JozU~Q94N!X#yM=!Jvu9rCtxJ!C97nod%I7MUls5IzZ_j9y#TJ3f{(t(s-P2%97Lch#?9hj|ZQ+267WWx5LFUT3!SynJYSm)q1EK zyoNIF)1<92yf}Du@_MqGtYEbJCb^F>y<32nbU6OCBCfV_H0+Tp2e~=%ZYkYeAK*43 z3J-EtJg?YDt7#Kw`7~PYPIn8FjW1_3q;B{$y3{ppHFMT8J$gE%NbM;N%5pZWHrm$g7Qsk>jQ>DTWmB*4}^{WSPYtgBq^7gy0~fFHOLoObO*}U z5B1tpv0hZ!A>&NL+cRzwvU{cMwDI6Phn`%B`#4`)me1xy*(g^nN6e;rPDAtx%9&5~ zMD7wWFm%?jTkKp2%MI=l$PPD+j}0jjChf3MS-!R*8`2t9*bFBJHPqQoz}lMDpa%~| zJu@`O!2jc&;742LoD=>K-jle^9BcFHu{&htO&}8PY#rWUI(Q20%EV!tN~EM$7Dz*1 zo;8xR7S19Rlg43%m$K1T5=%#hpI1{TXBFuOlkA;s$RUW#IAc?Gp@oO}s1)P^WWzQw z^U#-VlKzz;POccaCa&LNyZJUAj1?M(#eT6ZIiyccZ%779*qyEAWkc5uTN{g*b{l;H z?F24{7Ar5s%JN8laq2jdf|S!tvr@Fn zN-59;iBX)}H^sX8SyJ;Mqdr>qoV^lDjg^@33vUoqAb&Thrg zte^#QRMr)lOHpRNhmi=2&jYSMtC5Quc&Te=eAk{N^P?u+LcF8z2S@9K>y~A3(}qO3 z>;D{bX$DaC$n1jrGR&|gB&dDZ<-O4tzas;8@KY^4h~u30e_b8){+EyMv}x#$4Ey^* z6YkMWy~)-T<=osP&CO+(L;MoXDzepbIA zJSYj-jB>H9D)Ji^xuvm?E|y8gbSA^W$1bDNyoiRZnMch8q@!koLT z+;~aj9xn4t>rVCv>-pR?pRCkh&M@=%d@{it@WJU@!Q={C{d(waxpO<7=0(VCjQbV+ zYmgONfY#H|Ee)t0Su!AH)M*=_)47_kD&QL8xfQ7d;@#j3l^q5;lB;<|2m1v2KTr>R z?mVpLF~#0TyWe%E_*dSC#49U9194dj*^ujm1}fbG4?kpEWl(@tHzv~RHc!IJnZ~P` z7%kr79)3LKE05TNl&0zi@BN-f5v|*|GamM zFCC0?@r+9Ue`|FXwOW};mI(%SHhLOofu}2$jx2VE3%7J}g%`i5LrsQwnK%zz5km1T zQPGkG^u>#i;_ZmYrt1gZG2mU~qdD^p_=x98#-$ux?ZCWI5v(U#-p9A~|KYy#-s92@ zh%GMX$YaIC4A|l-5KHX{%H};%xnqUnm;(&X9QqY|5$kN{%5C$cs-8I&oaLtA_j#4U zi#o;I9XpdfSJvw*gJE4o&s@X%!3-VMqq&EPyjpKoNYT>&spegHKeQP~Z$qmj%^@H# z)Hy_JwEP8oN!yUo%mJMxIvoyf1C0}X+5(RjD2a>~KDQzQquO}#hAy?6JcvFsvCvTd zMOg1uPA$w9>N`ycmRq#;AfFqSAr2PZ)vy!M5$r2FnLIa&r`4gp$f%-Q`MiISs-2Gm z%O{^U`b1Np!ocL}=-)67p|oH2C6Hf{V2CvtN}-K>JcWw>%{AJ zP>wjxLaUDYmTI29tytxQU(l#r-6bpUCUj+B)qjrSU@i;R=BdOP1{;up%Qv^pj+CqZ z{YULH7w>PT$fU!;p;uFFsO2c)SP8Ti5(bs>0Ln_$68`#x=x!QvaS%Wb1D95Y%#^X++Ttg4+1eDF{r}hF_xw=b9+O3RFyJ zC;lWdD*g#N1z1EO7Z`}e&~<3j-Z^2z1B<2iBY(D;B|ck&3~GzOwL98#G&n*hj$t{x zne1o6RPH*;Zh}mR#HCmGRyUgq2J(x{X6q0jd31d%D z<7lPBqvCbWczD#8kN)F|-cQ_&D-dhj#AvM+JXn>Dw0fud^k&#wxi>mF<0)w!$~%d; z79kBtM+xx{cX0W?Y-5Nj-UU2w4vT<;RVO{Uhsw~YalV;|FEGj*F6F|~Il1qe_!^_aqSS$_IdG19i)-K=U;}UPA+F>mQ%#rKj4wEOkpz1k9cpBVD~rj(%_mGou!bnUv%L2cvcwkg0oAAUmxnY z1=p~A#rty`6YaanV8xlCA`6Ckz%&JpXp(FwhCo)n>OhNNPvg^4J@ot24q3SXKf4LL zV-R|CGCn(dbIp3#uHhkp%~e(o;+oUI=acea51zfNG>z0U(}g*u+$iSY0X|aP~Oa znwumJ*xjZXvuz!**78WLRJYoyd1h5L%dVJ>uJYi7L6z}$Ph&;GI zvx7tAjBC}n-j$&`TiyxJIYZG^-g#g)jyHj3@f7{Nicn(%qr-r)waKS>YqhC z*NJ6|ZPmBkiR>6B>FT#SGv_vY7~+L8Z4|vwZ`%opXfSLwkDim2)ZQWHhgB{ra3E>H z@heh$rlOy|0lsW@Sg4Gzbu4rX)B#!f>^v;6r4+5Klb@2b$hh`w`%HmGOI}6~JmMDk z-G;h$R-Lbsm3`-d5NG)g3$UGAD`lnWyweE_2-s5NV~+9?5ufB%2AsLmvZutk#n$Vs zb5itY#4|fwPgXH_D|lU<<4L=&n|~OXIOX~CGMEpbZ8%@W&R*vr>t+;uXK?(Umz8aa zJb8GA(g=Tid<4d2OBeWG$zl~##;7dc!)OJ7=4ysqUJ5R0*2v_cSn=p>ERgEwqr4}3 zz>D4prc;cbrHS(5jIRlKRqK*6#EmGI+H5)^4`zow2`l?Rn@v7X?X@5KvQ^sVIO{ly zd`MMQq)WfsN0=jO5z-xiuiiauPfYm?IWjL|)!pu3zH6P^nrofg(Jn0aVaNSo9F@UT zxMIe`Ra8sTJ+!Fh_#Q1RuJWOQV}0$iV!rbBKk6mRn#QUvz~n+;D9s+JD}B-bAeUBI z*Wf#PoaxAP25wguU>xRl5FrbYOn}w2s7|n}S|C5o0;E%?F*=RrfmC zi=`5`W|G8%R}0dAR92d!h&@9*)WFl-d&!R|EJ=1?UqclB;U(z~Hh#a85EL#k(^1@v zQji0+bcxYXhjZ6g(|+eZZnDSJty_ro!o>l)~BX@7J<3q$SvLgCD%y{_T9gYv^_XPT#VRYTs=s1es zvNBs`Dy06S)l%M@jB(ItGkJQIC;GM0J=l4Bm8IDA2YGhfSASo6X_7})CPnkq7Mz%9 zLHSSt_CTN!uzH(4U!5P%K|(ATbc$tFA{*?VZHUO7v=VWYf|{E#sB{EBzbAo%~{K7;r? zAg<=t6k3JImlfZa^d9|0<-LPoc!!YKir}q=^OI+2LDMYr{HNuECuJ z4_9)_n@%AwUkoY_#%6>UrwhQ}a)>2Kc0Fpx9Blesl~KN>#~SYBvT%lRGb1u)E{8lZ zK=HcsA@gJXqs;B9rM4Y=g`HLmJ-4n6R`_D9^_9_lizqdyoV<1~aVxdKV(%&ov~e#F z$(iVz71{T|hn*klPzFCUvYsOQHILc~soQ4Kv6$Z$b17 zd5h`!H{U?`pF`=cdRa@$AXOeG7&cJa2#|vYS;4mBFyA`*A&gpRvkYPDw z0}pwE;3pOw6Qr(l1NXHD&L;YFsPtE-#n}XHnQv*rdMY1!xSH}j2bHf8AHX=iD4lXS zi^y?nAgz)#O2V5!?^NYY9+?fZTw{@U+2EyXAjzxJJIyItJ<@$yOX+xA`-|UwC5tGs zHV;zsGQZ`l*~1lIgIK!)@BKCO9J&V?=)DXY16K&iHuD)AdC*B^CZA085d!Kh)cWUV z_){Bf!b#4zfiSX=KbxzI9n9S9;HFNnv;2l{+cYt3`TfZ16qrdAPEJP%0P8>yR!m$%G_X|qa!l{q7*$8gx@MYvZIIUakd@1 zT-0is0sBo>O!+(PiTn0eV@{)Nc`Ejowat!d$DVk}Wf}P>Cp%D8?Q;@Oh5&~6pfU>O z?t|PEQC0#i!zQq`Lm{nfN8BUzU9Ngh60Tvg9T~fWiY5?L3KEQl`%s_kM1A(D`wGn` zma@@0Qs6%+Av(-vEr$KZsWwJ=?ZdQF(`@Aea;c2L>V zpR4Zd(L-jZsTq6x%N)=E+f5{C!b%byDC-aYpz^Zn*XKmSI=ZNi?jlSZ8JX7o9 zh|+!uI>N+m$S^@=ta{JQ(V$Y2s5i;aL1i#(GI6tmW zPA-t3iR*!j7`VQr=@4BjAif|1e%-)1x|RnA(A4Ija=1%e9EAU${yo?wgaC{(H)aKu zymv*11eg8kOBe3J_MB=UERw6#2WXni@G$lrl)wc-8a?-m8<%--P7=y-LC;h zE_r=|%6H(sbuOUQt;rfxo_lXV_Ikbvd8p+<$XMgXZlQ(#$YZ{2+7G?2N6mBz9B;o8 zg*>IhT0B)mi&2CIa`ItL0e>|sl2eFd24p%<^y6>3e2Xk#G72iUbp@5DE~T26kj9+o z(YatN_!9ElCoTuZE@IwY(3*2K@|eru|C*ZudCIhCM)(1XVdsaDKfo7fHR{cu`VGdQ zGO0_7JX|Y979x|`!=}H5tIZUHI+RgwNs%S#e+$=Q)azDjcMMvmUzfBlsEkA#T6M*! z$FQ)J7#_@mTi9uFB4!uJU2e5C{Kfr2h3m37gUaPj_kL^mMT_42cd*9t zJD1vdw`MKN78l2_9bpc_|4*`nChu0vq|{3z)S2XftR^e}4XLoogB@{!djA9BVv2YS zDqnQMjI4M%GoTfx!M{IOezNj-#C88s;H-`UU+Me(QDipLI!t*cbzPnVDH$5V;8|!dKm72qkN=3-iqU81m7u?4Z)nNqA`< zcLe)b-VKn0V#gcQKoE6DPcqh1}tf0gTt3$1&hB-y(7Kc@>q7TdsZxe^PIj&{&d8P2MDcHlcPoRcD z1^G_prI(~IR}9M^?MdQL?F^ z*&wAOo}tfc0v75+dKT3_nKVcA|3O+)DX(m@rpn3fPC0HXJ(e+;3o6N-@nb2+D@$8D z+2EHlSAa7osIX3wU+I6cSHZ%h+M`B#W`%F4jgNfm;>KpOPLb6s2><_g$VyJ=mIXkz zz%r%g2P0(VfaPoB2Kw)#>98?ny8WDi{4s7nUr62=TWl~f_oOi7t8NawUxDXUs1`qX zDe3}3jVmA+>H|U{JVrGx-0Q-9gt@2xV|xirFlcuUyxp%6ZmB*+B1C~8ZE>0}`f3{; zXYM1p=)U{-ysRZWydWD~YyE>aa)oRCLw2t94_#^Wtn+6fKX7*DI)6@KL6E&%806l_ z5Ax5?1ZQAHEVHOQmZ8>9Kpo*f0)w4sm=GMD4)oB+RL?=DAVs88j0vyi7g^z33-lU! z?C>U;bVbUkb$+oBzY6IW5dE>icw2D{e1-=&A8dXtIH#61)8kmus-KY0!vF2sAA5EL zw|#$X#i0GMl~*C_G%`=~(5E!2BotF_i>>t!Gaxtgw6*@>naHJGL7BeS`bQMnVP^%J z>h`i9TlNa4VNgl$SnD5a0Cy5lvF{)r!8#tjHXfOjN4*O>BHl`^^VO%;LZ30lOowJ- z-FmW8H!(gdkFumMh`Hw&X6PrFsUCcO$p*o8o&_tyla+}xEdG53YjhIh9?+A7N=l#@ zlF?W4p|$=oh0%bGo=(_-@yIu=J~{mq*?sZ!X$z29+YwwgM-1{QeC+Kpbpd7|yQ?u~ zIaClFnJzBL4W^Blub%-sj zK>qS_^kR9;^t?UzYLPX#ErkzmPuU-993f0>mFrwI9wo?WG(Kq_K5BObO%@^4%7kJ> zW`bWz34Bth1dbRe3-tr|qnfAtxe8d*Z!bal*4VHV8qIuAoHHWq3DOJ4CNUA>-^?S34O56Kdun{aqnjTa6@@;>l{~r zH&FZ8gWHObt^1c;Y|@xzf#gEeE0YhhBH+zaT(FYUb^Bv%5Vg;8%wT$xr<7xF&Xrx( zBR^dC@=dQw-_=dOAWWIQ@tfC6A!~)7%+o?U<8_+dByFXrtM{sQm1&2pM$HUp=pD8m z*p0aB>KwF!((3t`%FTC4=~Z(i7(G73OC_HQD(j=PV}S7ryB=ATgUa*K5vol2Y!p^t z)z%odV{|L!uz0Wuhz`U4PggEg@1iHTt(TNRSZfDjeqzeUm-2z0d%wTE8Fp)E8&!_O z&Ml53i@3tA$igFVTO6~(`v&7Zz^XjBW-ySEl%0pi3=3Y-|C{g(3ALeGG^sW+@;L~| zL7;*66Ou+znTI@3LP+FF5F14}aQZZ>5uqhfOIkT1Jj2`G`Eb8*K0 z`$rF*m@0L*A@|_@>->XPm6wu#gRnw`rKjB>pqy6G^|ctG?_qS359GbTF)*#B7_546 z0mW|m7C7${7Y3Az32mKx6r{1oZ8u~;r22L%yHuTJ0rs5_^>|}_)UNM70ogYI{=XB* z9_do8cWV~EiZVw^iO-5&7YfpN`8T7?%NMdXTLC z+if2rj%O{r1-X?NJHR0Zlu1E~=OtTrw=%ky<>WWVl#JehawBwdvSPt120KzW?6EZF zDm~?q3I|p)NUJXBqLisA2tRd2b=yCLm*9$ZQ-i2 zRZqZ=?I{Na+A*fQ0)%i}3mA&*BwK73yyQcXVbf_4c{xSHjqmW<R~6>)`AglBVw zn3FPGVbG|!)6rvFB}BQKcAN8eM_e{*vJ%Kuyz96F!Y zf!)^-Qx^B(>2*Ns!rLbNu?ZuY`haYY^iDH-Tzkl3S>UmE4W3ojm3{}=MM=U>haEz- zMig#uabX=~YRnRS7c=8X8~SbrpY&09s9cZ=kCN9A@A>O1trr0Pf0#PcX$H}ADauZV z=ce=^BM+Vn+XL{YC0(XbWb+`a1niim0tcHw-2@4nJV#)SwY#+q*rKZxc zEe-0o$_}1ofH}2MOBqD+!DKoWY`eR_3w0B|PwFEM$&)CJWHvU%CRPKmYL_Qqw1gP3&K)KrQL!>xEei>dq zdzsd_JbwT&1M%GmBQW7Z4Jfw$<dT@Pl*aO{(F+~=qQnEPhk13B{(TEWVh+{fmMI`U1rB2B6R78gUSmQ@5sNdIJ z^c3VC!*@>?=07xIAbUi_a?7t?=EQ*V0XXo^Is(xD1IoEe%kk}d)zeHh`VQJ(i$04+Ep77_H8^p8Si*NEqTEI?>-bzno%~bFK=A>`Mw=P z%oVK#TQ0E)Iu(mPuw#$jPgllw^PleBU9h3WU`uXqE=la&b+mUo$%_!*yDK7>5_|XO zi2nX@?+z&UB@hWssF5?FOUM1-PhYW3kQIAq4DT=Awukm_=2Fd<$z}ItSW%V&eJNkAn?F z<@Ssz|G1pd98k=ONR0vf0&>)<$A|sf@ekGGN$PQG9kOwe&G0gE|G8C!H_MGFd*JD3 z^5ZURSUcDn<`DhKcn*AnkJ*vGV#xFDIk1Rl0k1zrU1fgnafy^CFre&(?4rNOtk63u zCpfk*z!>k$mU z|K{3u1G7l4f+4!<68Wa!ebi5qtk@Z+Ae#P$W?%J184M^-sOW>U z$P+#&!H`JL$-;ALuP^{oj#`uSuNXGnDlPK*bUEJyGl76ORDDxxHRqD2WJa(Q^%ybr>i>Bc^N7*TivA)`e@KpED#*?+_9t(`;j>75gqWXGFOPkpBj z9#{+0xS7wnAfUW}a;eN+)l_Ov$3WKEfO4TD&t9C#3f^l064|V22q-)Ixct(#d?#J` zeTTDp2X_B&ypf|@TeetcIibGi;S>}9KK&}*~`Cq*G|U=C~s z8lR+yhQxXp_bVBIDx@6i<2)?)AdoVy@RP2Cp`tW)p#h)7B>1MQBCNZckc3$I!Nz}& zlgVu^%9S+?xz%6oD}=4_9*5UQahC>K;oL{zKU!7BF5Kgy64`}1lyp6^&A*S5TIVOE z;E-MTu6>l;!TQ(%{6CEQ755tVTh`ApUISHm2tSHH0ID=PcMU%cpL6(1{+H|?^~f^y zUphzsujDu4_sjTe#NRIb?c-bd_wo4+{^{x$`Y-GJ4-xe(dTyCFqb*peYH1U_T>72^1nT;&K%s6o^~zn*=kSR zgBH$p7Q$8=Z{Kh)wQsJ&j4S^u&5SD_vnH;@E3EI?&q+x< zht+fP>R9O9b5l4((yXYYJI8w}!qZeO@=3(1%Z%+o_8xfhc*wQP{dKg90r8`H^X7w* zEDIhzLe1q$dgvCo41T@ar7t8`+4(jN@~5)=3*KDFtGxH4)2KluCw_doJiOikU}p7oIB*Ka`iag5>v*1y|g*TMx;AtszOke4aze$beoi;I66l zT5;+by8arEEu4P;3R_N#Eo`dg+?)O94CUd`xup_eKdG)E_Pt-t1HPFMq@g!Mp@$_f#w77Ko4tVL^@Dh&#g6f2-6XhT) z%;**qG_zFC=h0)9JNB;u3K8{Fah~y-J=L$?HTgN)_ifZRFSfId<>ASw-Ht1@(`L^3 zKWpbh?Jk3{N^PJ2P&*+}yWjtZ+O27(x{Yq3x-kff@!APLsh#CtYG+q#x1MeGzkj86 zLS_kUQrxbCvBp8L0jkfd`avIR5PpMy%Y{4euSuOt(=Yz&O+G(%@#Z&2U=-aVp!G2y zX8lkeE@$zcV4=}MDSl7A@;gKL1%BsnKOJ!*##8Z|_vGia+>P-z9_RIm>xD5nKg@_k z?*Hl4dR(3PW_%s^5-bRhVPvJFPMd^OT>J6QuDu@D3UAWb{F{rIF_sgu5ZCvdoe^n# zBvGn5rYGad;2TznVN|=ZL->_^6)TfndMk0< z1c$Y{D1zuvNr&21zh78`dK#^*&lb}x zB-;+>zV0mKaQC%%?pEQNv$H1`uP;}O4t`*0$oVeKGSMmbe9hOC$#j?<^ zlwStc%(Wd@GrwX3KLU+l{S|CgTqb8JE@=rY^Cc28T#eU(fvVT*hyNdp<1;HFuTQ|= zM2w`QBaxjGK92012+NS9@d=#<9{IBjc4=~y|HV_|wI>Ww?iY>lb$5Hqe42|(%l3B9 zpKJ8)i}Kc_j%C@1{nIbGusJ8YRMYLchWQ$$)?8!WO6+xex{-0?3u})5E$y{s9d~Q* zHf8tf!h|%Xv;Mb!)t4ORJ3oH_@gw}UPMe^+;o4C*vFu(xysa;FRw44)Xb}Z4x8o&& z?$g~+bz$>hIx;+@OY8RTJO|w$GdA(A+L@91@_O30VM9C-wO}mgQpOU*>XJM;x@CuR zURj2h<-u2dEyWLC107|+x4pyZiJlM<2@P-cMWv$0e~wC^`-XbC$;nfe+rDk1Us{aG zRlpTcYr{sBb1Z7H`jvX*?c+p~kDH3$jE#aHnxl+Y^^8XPEWcm5KcTfJEQ1)wGb3M4 z;s_T28*lm|t{|!HrbR=?u&jm7Wws>XuaYMd0?V)5l6ac?kYBk`Erp3@U_atEz@qap z#P?gT#M=7nb=%<~JK|SN{+EH6f7w5%5NnG_9-#Q@188CXuQeI@Mt6_Lxxy3SVN7$h|p;zBq3h2xw3+Rh1xd|UT*Ub}H(`VH~; zw++)t{AR4y`ufhD(^StLez|UK#qYxF2Yw?Dll4~hzwYVr&#$J(?@zM+$$qXPLpnsj4430m?+u&Pq1YR&6g54S3Lc=-ltVnAM+t%)8rITZMmo;{wPt;26_GQJh=vVHC~goRti`LEwN&i{+! zwYjf_oQ!0O#It_#oKm$c?w5|hb71vdslEwCE}Zq+Bfm4lQwTkRAB~YY;X6m+(>Tumht4PLeRd|+ONJ278A2QnMvPuA zq+LUiizZ2fInG^YLoCICkR}btu=U$pc7~9&3f!R@WTAqedDQeg;t!nw$#t^P9$9Ll z@p~|q6Ip6MftdM~h&_4h6nxDGwgEjd;Gv+AK~{Ue;#O;WAe5R$b%l=;p2f66V9W}& zh^#b$)ilMh0(~e<=5C-BtPO9H1&jgek9nVp-IR42#MbB~Q_{C{!Yg0{pff)n)i!9m zT@M?(U4Kl^U*)xj-?TC8${b%F_C1IzRpcHdf`?gNfyxNB57=#B9yyB00h*6PRE{ng z-ZqN7tMi+HDjmm-LmcvSPT#UE9J_Y9YA4pW?2kS7H}02UK+`d_&k66$a6|1l|EI^P zHY}I0S&uEXigu~pN^LN=qtQTC8P-{$+ZSl<{6ZodH2H35w6$Jo9Zqc>{)U4g&iFC7 zQ>l#ze=N@a8X-bd3YIy|4i-fOy{wBeg4KREINLrUA`axZs3Pm=-ov||4PFujDDkkd4Lt`~71hnJ ze68{Y@KeSW5g#v&DOy*)!I=F4G7!qvaW7+CHWx}moP6<-sN0fLum<`LqL~KO`*RIE zA~Z=847PC=ZMXYjA-~;={ijdY-SkkC#N~p|?)Z;27#LeGC7wE@XkaAMQ#*jLy(nz< zpE%Ct{`)<3iF*e9%RRKm%?W?0E04VO@T~CvPJTaf*F(o6#lL$$Qv2{+`SD79$Y~%f zM`1A2TOK)hTS>$|uOxD(tt9fqHOHcNTUWMMF@5Bi?s&xh;Aa29&f}4sNAda6@yPC~ z_al!#z;eOuRG3eKO$O~;}xF!OV11zx9VZsgKU)Z*yN2Y{=%WnZ9m)!UWMKx$$J z<)3#3lCHElu2wUBQyc4$p>lF%ya$G5}i(;^&n#t_qEh@NQgZi zD=EktOtGrO0(T^O^g6#6Tmt{S*+2VrNcct(IfPd+uGbjhCPEJ1a&;TA>opPw;ChyG zD^{z7lo4EkohHr_QdpjV7{djDudW@UA%|k+dczHTr?Z8 zQXdTI(~fwB?jyB+*l&gI6Zl+-&j3E3!6%Q;dVG$;=acwM!RKT6%)`FsSDuKLMx1Cj zve)<(*3QY6p3=x&B_e6d`nu2Riu+aB<f7Gc^e&}A8TIO6$$1T$U1VMp##9ti@k%&gHoD`hR@Fi!=h z2P-jg_uMuXzW|=;QWge(jOC#E)FbPA+#h>EDZ^V$hSyoR$OfmEjz?7CG1z)vuo=A+ z?oEe@Ecl@gOkwPh3`t&?|wivkF*9gmzb5C>B`2ny(UCJD^ zMOU@p>r%>NaZkA@@d>SOK*y~^eJFCNPmMif6Vp8VfHP-qiyFCfN!g!>60q32l>UIj ziM9~AL>c?w%OPG`MQQCrQ~}~HzXY;6$;+zu9jb=mqp91R|qQ1bXKG<`>Im@}nrtyF+rl7}b@U3$0fhG^X-5P2$CP(^J`_UqmFY56J}E{al0=72Seu@f8Pq9En$r)j&T4hb2+6REeQXCb(M5?v*-l7`8djc z$_j2rz9#|pt!wI7?)=jmqgFNcatLw<2^?h^O-0TZy_!#yWxL>+0SY*a;;M$A-pE*q zG6h7c5W4x~c|IH0mZgtc*s0}N?h3j(7tDcRX&nRmHQ2r-ZsdG;@4J*UewIrSt&|l8 z_i!fU4lfBY?qhtvJ*vMNrCQWHIeb2HFs!0nMPRZThEnt`AETuuA8HCtd_HX$kjf?z zXl2t);Py`SWLLAi&oiq!|9QWgo}Y*3qqbv#ctS*`PXH+|R+UKy zP@{N$S0*2D8GuaS+|-8>I4bXi{-S4wkf_(V4aoHhjxe{OduQ#Zhzg=HtaF2*uz|)^ zmon_K4%vt*i+Se>yl1BU)lP<0n@gL}b}~A<4(^(D)P6Rwg`rOa>-wqU^D^V~^}oiu~jqyVK6UysguyqcVlHciByyMpn|UTlSj7^V_EHS>|DRaUd0eUDzXB6<0u!DX+MW&?dWIVG}bhr#B2{r`7x`} zs(;C8B(%gw6_@s$=PKWq=QY`%WjdT+WpYLPT2ky~U@0q;4rdffdod#>ft3R5b=O{- z_M0lFu~Wx(j_Oj5cZtRvA;%_LXWnnbVM)r`gpG%UVyJ=}9 z;yg`FC6cy#;~$y)$NrC_m0XF0c&zNfBTG@EXKcsueFglaLPL`}Gj8o_wAcPn3F*d$ zF}a{0+-`aXR@BP$dwyt?7XHw**K=N1#_vuVSyMvs37C2B$yft4yK|lQH0NW4>cJUC z6w!J1a#r{K3@-yo6PL&=sE<_j%LdjU~%(OnDuMuitzAxg@*U z0XEk!5fj-kLkfTU$p2&PUErIj(*E%?lQbl4N|Uxg2?dgrmQrrvrho|3G@TZNrFg~L zZmOawDwLvbT`wdpU|IFIDHk^_s6}00@Y;g+}qe`M95>rs-AnD<+VYk~| zlj<3QK8!=#+4%bq2j#Uww`vRI+=&&Ra5`1*JZKGfiS7dA9x~--4cO9QN7oe^s`AkX za;H)kzSG3gkHT+O${zxM!5czCdx~A#_7EhGi2XkWv~+*CLCuc@-y3+|jS1$qUwRVR zWM70#1C1H<$vwfn3)}M?Sg*s@6%3h4&vl0`k$)jcg6Fz#4)1*2j<_1&ymVa5_gXMF z4pU7hLR{K^!B60--VAna!gZwF5nM6lpW=cXQ0eQ@H*`0BXBm$Nwc{T>%8gIN=h)DJ z*3mk`d*Eg>$h{H72m2t>H*oz(KdqtLr30-A|DhDdWVYtQAWf<4)o{@MwuI(M{P?sG zOW7UXh~9lOyiw!sc{!S!*4A1W*VR|WXZ9=_)CsGqh9{pVLY(-`vj?L8P-~pV2EB4i zXegfjpIV4#S1xWIo)S}tW7c*BC?9Pau362SKr%(fZvA)z-Y_wgr)Y2DW{>zZ6Q4?G zxCBm?O>e7bDW6XG)abs&jU05`g^&?#2j=JJ4u#*!&0gGW027vBgQ7&0l3 z213{8EIq0z8UDLkM1$!~dKcBL#yqJjwjCY>glF+C5FFV!W9VP`w<~9iB;SzNrU5aj zL?_dm4XP#Lb|ro94e)jW|AY)QB}8*nANO-`g7gMvWVtiF0U1apb0K$uPO=xc3wT$# zllviYVsv9BumzYrUD;EE=OMG9KJH&ZvqaD0W(+({+yAu7XIoCwGb-?mGsJg*(sAe_ z&HHOJ2R=BejCT(HrtsQS>COB3A?U23(}J8A(ZAQlQkF3rvTW)RBLR*S{Vi4tTgt7? z8a6EGUQSt%)BTH^!%vzl4~7kVDRFBJdNpl}DogDOhtapwRJo*7B+jGmyc0=Vg+0CCLty zgNypqgM01{dR^7o?LSa|(%PIHzK#9c~vrTfpx7e z)(Fhi%AtK=sj1s*oIAp^yA@cnQFdHeSOa}V-mx7nixY=0vfBYW%+lZEne}?3h zXU^QwtYc9j&|E6e#_%jIH4pL3Q!!$xN*xg2windrpD5rS$oKf%bjJf{n7mX$d<1GG zf7XLJdB}(G57;b8x}<2yCN&NK`F*UgHo-@g`g&l0rW40lX}@@`d#;k({(Ul9WBl5E z$rY9F%5S0^?BhoVE#eQ@=_DSF4IMtK-2f@rwj(=$(cex-o4yt{#c@%=1P>d37V%(C zcdWF;lj){&OFVk`cYdo(U>fzvyYt+UT}W>GL(rkqo7cmCOZ7~BoU19!;cWHG7~<>B zb-#u<2rYIao7H^;2X9{g=O>m|JzAD?;4H81kFcM6Zly@OI$ktkj)HgL$OY?%anfOw z>2IxFAnDycpN=Vd>^7D*8&oQ`2+6eqkSM7|_hZPqhi za}1}?T7vOs>9>NCdGsW+Uai@7FQNF_5zmUa;d!C;Km)i*I*VDz(wJ4n;Z6Bwn2N-k zwolE4I!gTAzU;0e5AH!`6v#oEN5ee-jBD%i3Yw?H%`oc|QKLoNuV!yqbs4pxCVG>_ z%_mmV)9zI{AHJnT>P!$5_I{<9yhJBt&)kfi2z;ZXD9#la6>VM??jF~A1hS{M=E&JQ zQuYAf_tCJ1SF_FDsp(IXv9a6Q+s-qAinwN-I$L-cqSn--Ky=}vC4ObGtm1{ z?NsyM;f+l-Upk*IhP$`-)t(->qUpcVdY)N7h71zfqrUm58F>pGe(pmH=$&YssDoOS zuC~gX1c{jA!1MLo0qi~_`&ZhB6Sa87CTke+m=vLCf*xaXZ%)_u`G|xxfFe2UWO=QES3)vukm;cU3O^1Mc(->)EM zAzj2ej5gr;sc8q(J z_^5y#J406RoURF~P4RhGHR?%1PVqdvi~Bqf;_=MGSA_Pv?7BAnb@8YvIG=Yu2^65Q zg%M{^?UC~%u}0zUb6@0iHNhv5<{`J7G#OFBZ;pyAi`XEuMpY3O=@le}dHwG@cUfjys>zRdffQ1WA-I zJ4n`F@4auYr=adp0mz60&(U6c4zw^pt^)S5HYm0iA@cY!mLz3&opVI`rT#HOx{3)R z23a7j*x%b%I)I4OUSR#Y{c)2zzu5kSN&C*%?GKu?=z(uqvb%OnM;#ao z=`qCI0L3aAvB{cuH1Jj~hPU$L4l4Ia3tb&VSA%sI1jeJDM;$!sc~YS3Z?|j#4hc~& zEaX=19rA^KlzrX4TD|+PEk6Psh)YjsB)jYDEz#JOSao9iL)NdmR+^TJSf}A_HV{V= z?q1UpRZX-)a&-hpMY}Jzy=oatLrdXt5$;~ml8)%^aQE^S?uMz8IvaDk>>~OTz8#L` zQP7)B^jxl??0DoykPa_Vp||riH(_`vr|TkmOkHD8?&TUjjY@IpT6n&k>-Jsz3Ygu5 zaDM?_CpwiLPh8Hq>i-XXacH|JcRfZPs53nHf-LBNgLzq6P5K6+zoyGHBi>YxLtApX zo}bCcQb}=C?GFi@KiuuRtZzpgfQ{k%Gnd22W$}7T&Wi(kkZ^bJx$G{)@P9yWEwqof zfR3V{b6s?mijO_YpdH=AxCwz;qgdq}c1)!$xkypZ!rNgFqRcyv4goSZQTo)&d?1Yd zzj_tgQ@T3nFkzbAiWqIoe|V#x4W>Uz76U=w*8P(jLq%^A24+ndIis$%s`?zzEgqdA z-YJ&4-VJM`KZQh-M=~GA#d(E(?Gh)6*`7G}!a;P3ej=?;P z-pNZ}?bf#)h~cbv43r?=!{9X&Bl;dn8FR_h91twQj zn6t2ncQg_fB_HC;pDaj3L^om4jJ1$u{>cKqJQLP=*mFo*ADx@E!}(e5J7I7x;I~y3 zzz4D@^D*f3$1lmEs4KFG*7av-4tL+GTG!D&3txeI_<=Y{s`>SnhY=a?=+}}&YDa64 z13Sq4*?XYn%!Ah5=q1fmR453!fWDFTl`r3qz0iJSJqmZ*!taDx6gTnSMn0fJ&wC|0k%7xGDQo+aW3&J4_{si;wD z{=hl7fu$y54Zyyp3R=xqt?=5X@)nAtOf^bRjX<_=^Z}KZnmI_x;6Ke&ny5sx)4G=n zf5imPdZ)2ri86x$m)Zlo!dm3_;2o~eu3J(5K(lpuZ}-kVq6OmQlwF038x%URfslLNdqCwYKH+3-m6(Q`^?J>z$T~o}fPjhrkRo{q zD^gvJA>|SV$grSI)x3}}B zjQupC4;qk{-)~F0>i5<9XT<-!d$76$XlRv+Jt`JsZ`@8ej2h(3qFw!T%y~UBM+FRN zFY}pM00XRVOEcaeq? zy-(H$lH#56Hrzv{o$_5JmCDmY%(4zSS`iP3{85*lYB>8$3T1@fG90nI)!ei@l!XhC zg|jwW(SFvToLe%(m96MM({*Z|deM1K_0Ss?%-xH;;jBT;v8`!nK$dQnJ_&8Or1j#; zdj`_AphX7aS(NXRu5b?8r+tHO^kkNby1B(24No;F@|63M9ImR)hE>QtCf{+9u5dH{ z=45COJy&kz<*)X@nk5Yu6J?H@qG~EQ`R*5lc0`TKb8Cx6JtfZBa`UD{jD|UMOwqFW z;=GN7BF=Bf6Jw-@#Q43LKtH-W5Tc^mVvM_MFmW!vSQqF1f)5ak}3lo*^B zm@ghvJnlotAz-z#=G#pRMM38IJd}PIIhJtVeY;Zj7fv#?m1%F@I_Fg};E}|@L2=d= zsxuiG6L0b_Ri2HT>CY4AZkfHAmz#U$RUngv9lMkmePQ7!tDE+}T6u1d7|0a4Hlr3A zGH*Tj3VPK|xYVW))qGQhLqdydsI?k9wKuhAr#M4=3-j#czL}L#gu<+1fPs$=-3RVR z89lp!OF-JsaKHWkriyg&=B;E2pYv)zFC7nm0M##!bi>CL#Xq#eyOP5@A2so{vnys* zM!Q8nRveEvTVHzs87B@Y?}2M2`;gOZ-@y7k?+xk2&c)^AkNElG4$UeWIZZETIHa(e z`Qip;WXerjgdH;R&Yr?Pgk_=>2EnSeJIkP~;!pdcYlYMVeG zsmQw~cda+HkBoP2G<154gpFb)8}~-rm?%NsP)d6Q&WduNYJ7v#y{7b-@)$d$Jb^jS z*GMbq)!!%sz~gTARZZDjV@_%pOUp`Ej39?r4B_|vmg9E~?` znzix2C6W~A{7sn6v+*|%7B8lsMMtCK#MHo*Nz*GBvnl!g`zp}HbYuWux?0z(vCrIUamOHo`vhw|^ng0#6@q5pM_ho(3^^`7u z@H{H@P5K=W!sd(VTV!yLx9S#&8hPDi+{bnz$GaY0x5pG_+E6p8GQODn?v23-l@qtd zdq#K&@wrB6H^1oIU(3y!SZQ`2$NgW6>90aVw#F8k9AF-KFYacrodg)PP?T{v1GDC! z_@oG5jq33MI_BYtzgL`r4-kL$R$V>r$KJCTGl}U7IrPVr0Nzy3K?nDyG_#W4_;u+$ zF&@v*gr@P1*QU7#Nsg@}#ql0ZM@>*E1CZfl=xJAJmw^HwqD8{`yYAr?+ z8u9P z4leLs^*z$k=E01~`MwI}BeMve{h68GU5j`2FfqAr(wIiPtsOBCwS}YT3B=oos(`8O zn;jsYa;NW@vWH9TU@PgmATRP!AMo}`;P5n?+<5;P@QM&lJUvO%h+Zlb)lYBtogzuewdhrj!}>B`)Lw0CG}@Yi z)*eR*>ZgDdp@c2!md8Q?N-qgcb84=1fwbD*q8{lvpw6)wfXg6H)KRs>1#t5%--JaMVPo4#@oD z1oS5D?6SF^dq5?>6#KR&q z&i{tSSD*~hH_ROtt12K(RffB-PMtq4H57$O+Jl&8j#AUnt6MrU@~XN(M{LipV!Z zaV8M;%9tM7j$@E!4k^EK%sxOPrqICq#Hjt5EdEaPL$0d0?8FEr`)WW3$CN}aLS@QT zDjO($5b~`?b}IF1>8a%PlaVPqO3^}L0pu?|G^WRZ)^bR>kKL*~Ho6=-aVCG_{T+0| zg>gQoSFZNL%QPkxE9PrODL8&z6piD7A|sCbi%dA~ElS7n)1uKE4ehJr$Ktpu9;S_+KRQaAYIJaGJ_;p`^}rCZ~hKa z+D#irZFvy^pG^Jdz8DN#OWe(DGBN+%N$&yhwZ)v~aF>r}&YWD(*Z*^hl#`HG}3< zewwSU#Pd4lzH<=mT&ieChicw#)@2gG~Dc^#wQxp~tqkl}@P-g%qi`9q>}O~;+@kdBW01!+$4_JwH6+r8vV2ptW$ zYDpQ*;>Y&Eh$c6FO7j%>@m9>a<|Ay9=#}k|-6K4EJ>G?QcBFsk?H@Rm zyJ2ApT4rQ-04&G9_%QSRwSRU*@)950wcG zM|uF`C_^SYs!T95kI$JD;wR~X+@v^+XeRn^ zD8auTe|kwv?>KO;{JTAo--66hU9!06mgIk+x1%AkadM8g)ERa7MfFU%!g(np8`FnI zO&-U!PeJdRWe3Y*_aWS4Eqj~&H~R{Z#*_8a@#n;!8-I^*uXF#!?dAT(4do~B0)HES z5C0Hf%)iWU;wS6h;6LZ<`EU52`1AZ=jYV^#X0c|OX1(S$%^}Ut8d=k!QF$;VCMGXh zPkwBI>{v&uq#zGjA6tPOMP4QgU(CWjPVa6|BAip7g?-oyqM8R!kge+?T-b|y{^x~w z>Mhyw`TxG-(A7Ik*WK~O3km8S(fxNsXiST`wwKOTpTOkzO5gq^QeWh%2{|vWZ_Bn9 zlH@oxs@BUUU`&!^na!=hFa5+yQz6md;49dR$Q!V}{QFz1c_B@lyDbm;PhKv)Y=Dh# zR>j@rL7$9Y zREFzd517zfx4bYspn5PAJBszSCD2=O2AanySNdyOr3+4lZ0+E!$R+EAR5b!SznNR( zi${2Pc*HN3b+B^|vYRsNlOU(LdHKG+$oxvbIJ_b`06Sx`xmfQq6*74US~oCGYD*cd z+=6U)frs|k%jum=Zd$*m?Je|iXgy}uOeP=s;@Uk-?pTif+9y}(=NzMz24Y^Y}KDrE2*Y0P}9LL#s!GB(nKSC zZ<&`$-neaUg%wi5+qE-^4y>~)=a!q$`@Fob$EnVw$leM1mLaM}WftZzydJgCzA*WJ zO06C)y{`S6(kjSIRyVuweW?eu;Kd&z#rIwRRvXsqt{X!^_N|8pN;qk>AeWTP4Cpb6 zyl08Ud-B>ng1i!M3>gLc9YS&P0!!mz%o5r+l&zigDy+F<#z7NV*Iv4ov;e;0)b2m@ zkp707o{qeY7tqoPEDd^#BIuO{Mg@3C>oe4zm{fuJuEn1&5!s>{@L8Bwk2i|NedoAX zc*atVH}qf^(W!ZYyFm{fXj|i?a%y=xTK+`ow5u&I`h}h#WYd`I(K~`{S|6bi?Ul%k zeq&u~MLIG!FnP=8*IFaUm)6YP!K>iT<7U=U@uPevoGwa5yt-dyT zL??60Icb1iMqgp_k91EW+K_6_66BpFsTBs#=HK+{fptl0Jz~Z6Z;gzw%>0`Xs$Mtb zKa>+(diXz>q=^-an;{Q^;DNJeiH|Xymi8*S@;fozYc0okBY#}F zc^CST$@6`2=r7Sny+S?r;@YhzsTR&oDC2W6N_|tQPeP#LWq3c@#}co6T-8Bf9+iv> zJWBcrl~x3~z(>4vP%!f3Yfp`g!)GN^16*<4N#a_DAho!X_z70l>v@>U!LTAm-sZjD zfim!~HW5FwT{kv@Y*{x&oq0^2`k8g$eYtB-ruVH;X=X9KWg?4$S5)(#C2-BRBfZ78dYJZFlp+W7|7S3w!wxC zy{>&zueR^$(&yFwO|Bh_K8(zCqL3t0I)2+#&C?i+!i)e1-$G3WE9OMj{#ofi&%{G_ zzeDqh=4*}Ebx$TNV1%WD%uHAd6Pf((bv#9o|A4ly0arNdi^B}!(Wg}<#{O|Qyl-LG zcfz+_-wHc=8Fx_65X-a!7D}S8v)&YNJFn}M^q;5630cO7&(1C9 zWgTYv#eFja=$&}ZV|LB-bMEM0BDDH{e3RADedz@KHUx=gq4%*)MK4lsj>PAH6eq~* zN(MusqqZIfXWk)lGp+7~reRojX`O|@VkH?bvbH{RDYCLM`KK#WahKJd4LPjz}cs-o_*H$@JZ^+S4(lt#LXNG#G1ci{7mu$wndZ9#xNT`N3#)Z zI2(#@k^gZlI;>-H6@Ki__3r0?859t`&-~KY{lTZA?B)Bq-}uK5)n(dT_`)P~u=)G{?j9Y2itJiqARtaCC8U#-O7V+swBQN~v#W8jG_nv;Z>W z`QVseNaCQrPp+K`IfHasGzyc%saQ!3#bwTkjdNecEYS}O80_OnH|eESr1UcFm7vx3 zR^iuYy{Q$`p_!Wb>R_xX=EGBpuNADbE7IL01I@*5tNXIm!{4yp+44gg z5Kge(I;`#);t7?blP0M_-Nmca2l_wnn;D=t(YsEc$V|4m$-1U#+&o=8 zfLP%OubDIAfW#$mb7qFS=*?Q=T ze*t!krcl?*I#eqP)=W;`b~&|o;O0N*@{zotfTa zM4ut9DgEvSXEMFJ-ED%E?uL@7C;7zET`c|Hrj-}|Idzk>PM%QW(59;td|u_9)R&mu z*kMuRO{;fGe?Oj)h}OdWWte=<>rk&$0g=VzZjmNo4-$uVDO4hHJa&4-+k3ob&vE65 zS8p-7dnJ0qJ#8c7h~@-n*Vu)4AHC-=j8=p?6KCq(aVIn(=yr<)dRNR`cA>%N!F(ra zN++Ss?T3A!E5UOiL9n{NJ7I=g$>ifcMT)H$4}J5bR|Ol_>}P^w(iSf~-~>du%#4bR zfT`hskI^@XAtb40V2q}38};hPCpfhJ_db)_vy)FuuBeZ!EviHj4O#kcSX=dR!@wCG zQBI3FV@5;V6ul+8{Z1g)-LWJOc6=@zT7^h-POxzB;^WbKA9>%G;Mcsy9E<_qEvzw+ ztcmwuHwcf!=Lp;Tsn=mT08ipCP?FL@@OSfWaKe#=x%Kj z@)m5GwsELihcTMF$(R0Ct=DRDPus}G3`nhl$80bjEK+ozYjfQu5E z1z70KSsDpvR@rc6EG#lhvPM_VH=Et*6$b2OW`L)CAkp_S=kOo0+q>MibiE8~0nh5X z?&sml=3~OQMa?@;GOntB{9>0N#4 z2W$IO2`Ne9tX6knGUjbM*MQhdiFQ|vx4@;R?` z>{4wgnBg(1eYb)vq&HPU$3JhPYAuNh(VLr_$ZD4;!73eR3nI$UgE%FOKN}a@DR=3A-rN>{@U%*7>$DDKQEEETsvr-kuS_XIrE8`Mcv zHD}QKq_O%68mk}iw-grgagdpAxVQzsNSlw`YgX8nxC!tpc{I2K-R*#^^rFMeEa~&s)&{`w3rVvW0`Xh5Iwytvza+bABX*6AGDcj z{Y@dFyaAogAY^+ALPM{u1{Em2YAkUw=gEm6z^hDHicJ#@RysWAAC0S>?%g!JQFKRGW z*y%%rt^=mC-D}Pa_@%@rWrd~H_3%)kQKs=lE6sYB=!7?vU5(?weD`5z;s0u?6xDfg zRaB=^C86$ku zMz)=`y*y9n7B}tm#;WQGRLcnheZW)%JY<>2)p7z6dE~<*3j=O=~*t z{V-D3ed|)`c^pwX2VFRme}CmiMQb-()^z{w!#+n}iYC0>SQX|CPn`Zy`4y3&2hcN5 z4A~Dnoh*K14`kL1%7u+p2KfrN&-_YJd_Q9R1WTrPru(H<GZO-`sKE`>EpFxMK!1nB;K>%dkS8TA=T7Q5RVo%P4aZwQn}a-G!H*8gV*w zxjXao8v?oSWy3=QIamI?8QxzUc8AxaH1zw48Od{gGiWog`^ed6-@UgvnkCn6QO8af zHx6_8zGdIEF?hi#`BTte9p?`ym$-l64E<`sFUH&87g`6eKWO`r4W^C*Zl_!cPtQ8e z+JA$lfWHKm}CF)9>uJ|9m(Ky zu#T|sEzAnshxg&53A_xJqs%leZhjG;)A4x=KIa%?!i|MUx2FikA1Nv+EmgWpnUKs` z?^4q5BY9+YkIA%Dv08!EG$j}Dp`2rBc1Pn~$`~X0l90sz7jL?U+42;db*W-=SX{aI z#!b09yR*?J>B1t@hwBWmRq-UZ`n`tEi$yu`BZ5_FYP<&+vf32L#%sOgtuZ)wRJk27 z_O~i2LY|V6m+BI5bSfz(ZrZ)s7aET#ip|i;t;$i-lMS6bJ|`rz3?97v_H}xRQ1h^2 zs#3~1-+uHbS~-Di9|^_Go`88f4iS=e;mw4RyFL!Tg?J5L^RKHjlz5;z-jm(dckXbW>FMrcgP^2PV|u7 zF&uAhH&I=k=pVGKzYnqEdGAsj_vyngg1aq^B7A5;d;|0D>z2Ee=@SS=4e?B%t}j}c zjl01*X-&t2A0AcaU`Ll+8&KCiQ=Bshuj$+V-fD`|ckXcO+g(dG!IzBs%Z>bw81p&s zEkm9umVsRKvxUC+MZJBRG{hfI)FR`|zCQlO5}XHpETed1ev&x^q#=|uUtezIzCI4+ zxY_!tREkO3soYIJh2Te>fjC(Uo$IHt3EWIPd&p7cKmmV|b>5}8CJ4a)uFg4%H^h}? zt`Rz5H@*SP@iX1Gwh%JhJ9x`8-3wd(!<>x$OSJ~x);}n>|7{bfdGN-VO+?WNSjUkk zfH%QoW@HfP3XEh;O}Gv#5784O6??s+x0i^U`g!k2%wIiEy9e`el1QV0dQ}3n;~!M1 zHjJwi%%D`p%^aQn>(T!?&1~Dr_a3rObl9t-tes2_1HV&{fAv8l1d5e>QJu|&gZw`# z=W1eKAxr^%=sU$xMH~^_cl&W=rgx6?Bj!Gx&8-Eeh=JZ6)J5O0qSfp}Yhs!pBiL{T z6!7czAC)sx-a(|)Qs-dY`RjIiSDZ5s3g~O2I!_fcPZeUpbCd5Df6(kguIjgHbD>H3 zJ0cO2EN8mkJvX?b%vlCMW!A>&e^iuAW&?l6I?z#Hl})RG6?xhZmLCLnWfMqt)jJL0 z1soqoKoE{;|EHJe{pC z|4vD-OT^kXKg2R<7XPF?o4OZ$@ssk|p*P?q2wZG0xJNnXN6xwORq#VGdbP*}F6I2F zY~y|qjs9I|(_7pp%9jLEL zt>bpAS#NO-bU*Ie!5ITo2ky`RUSb)`gVY)({}nC!Y(9+*e7&nziJYIaeh2LMTO%#H zTAL2z`Ib6j)UK-h>)S&uF$DA#v6azVsg{8{{!@DfTBEz#8tS=q=*cs-NdJ6v=>8yj zW)oL_ugLogMNRnq@g1C@?rdaV08 z%x28!=rtWFAH?-%9`GY(j{6X+v@J#|>F`d)%8jgJXUycmQ{Txl58ykrNb?dP<5}Y- zQ{;vD2;{2@C%f=h@0ZZa9DpB%UzzBj96=)xua6jo{u084^;p4Z4Sp1#R*cy{kX7*d z@?VAUtSM}KeUO_)=RZGsrW6gv1jmJLrFvU1&A*vbs7v@d!uJjsvldM)6J0-H0Hx1@9?1qF8h8yoCC=dyF zALmvRvggSUhK`vGt~XjS6BTn@bopWuu^&#bkr$>19?M$@z*>d91v?yo~G5^d-A zg|rJ0kdI^tO4e~Srulodoz1I=r|WCAou^jOQw^R4qv*+y7=h7IhklGia)y+$@-^7) z(5O=c@@>h`>GAc7cM1z{&}h02PUE`{#{01*VzswmWsfHNoF$lvjBqcsnkFN6AF{)h zP?kW8(CR}JjU!fQEuq|Z$jJA`#1do=q|9=3ewc*S9^Xt8ac5j+BtzarDm9RQ?(co3 z$vBT1-at8j?CUK+B0(;@NFibFf{|+}3N@wzzo$_B2ha zzYJ%k>m9#Gji<4= z^0I^kNCSM5SeR4y@mkFFCRHb3MJ5BUA81t$nn5waCM9sTNy+=lcyaKh;bEg;ar3$7 zv%-TlY~uoCp}S8h>yKZfINd1VhMieX8rUeHFJL5#%AJFQymaERyZ4^(SPS$PPy}p! zh@=H}4{U-xkwcrTxIcC4mS2YL##wD5YsXSqFG6dBh5-o&{m2s$LhN28wV5jTTFY;m>bUogcreNBN zs!p$ai@Mk4z}uekIxNmniXOCa;r(##vCxxUFB?Q?rM949%;4GHZtFa^OuCBoUx|$|I z8|z*Sy(=`ah34kmIH5TgHa+MW5tX}A?qf-i6XB_ftT?WAujxN)UC%G?*SZ!SQ54f= zrQM1+Z%1y{a92&3pM0>^%wxx9Vu>y(5;glsM8}EQFc7D4y1TiRba)lkWwKehV9Io@RoYB^(6)kejg_dU%@`-K>sQs{OOo%?u9)LX6f0W~ z>+Ry^dM>j$Z`ELo0_Td6wnID5d*orlAffpuu5i!~!%laXwsNBFVK$Cy;%v5uLBDvC z4LE9g_|F2*bj0h(UP*e)*IUvoZg2;NxWa3F@lY#ee*O2pATBW;8f$1LZRGu0mOctm zz_W$A_M>d1RNraJ19qkj80)sGUM^m2w{Q`A^=-fc&eBwcHCB29Bc$_NZ7g1&871Yk z`#}*6>~!~d^oPU||CB#REX${i?Z_sKZLEo@|9Cv482wnI**#hG9?%n&%+^x|e zW%`tRvcM&bOv;O?$GjWJIaC*$h^#i&;xh4pf=bK*10t?HA;Rm3!L9=YRY({L+R>!* zGHi&}PR(ah+DL9A@KB1k15t*D$HYlslW0Q$Wg%8$E^cmUss~yi&HWp`+_lp=sgZV{ zw3l0`$__fzt%Wa`wZI4cNvb5l`!BV@pUnJAq3^H*k($XL^lVl4^)}R9Rgk{7QUTt+ zhnwkh9%$U|$xW_uA2}NZY(aN^yp(|2I@Q|R8!HtcH9{A~GsJLRSKs;`uF{kkLEd1s zA?0>ItvRzAceZ&o*4YEx)~opvzk|wzy4$is%0o6o_`w7XG)=T7(u$be%%j~Qd%8RJd{w>$GQ_)69mDpFT6=P(dVXeaaBk-0? z-sRnmz25kc+cSdnDs5cUGWQVZzN6SW=%+`hREBXi`QQuMg!~bNmxIyHTjq`quVZy( zRc@k@f@Gg_3^b7Iu-j%EnDzkP(=*ELE|KQTf`O&d^Vs-h?l;|L+|8My+oFNsw>%j* zVhs)@)%_YGNr#ACjYGr-+)P^LrnZdeZ^baGm*4K8_x=CZB2O|s15qEL`S6pq7OL$+ ztK9jsrD%-aR3+7mvGZaKF?N~R@#@&|;dPqrz!~~|nNarf85ZvyL1Q<$l&i6wU6=s>Rw+RLAoV z-fPg0=Za$l`l1dZo@n zJ@WRssnUbU_Bpy%2kB_Uh7sBa^T`_v^=aPBzs7H{pE%3E+mJo3A!9eimurICfel&i zv^BuL*c6d!B0lEuFE-^D?A)7)d=QTS37`xz|6ues_Uscu`CfX`pBd4WJD-;_)iE8w z38?;<_%8n;NxnA(%T?`va%~xGIg^8#?Qa1Af@2{i(N^p#SCXfA?@My|lw??Vyp&7K zj_Z6lfdsMZZ=%GU- z4~iwhh`x=BTL>%45!gOSZZ<1F19@#NzHyR1%LYlU$&?QL_i-yH3(65iGDW2{FVD?_7f8M)9I^=) zIT=<&C)EX1Lq`3K(vXyXwwkFP^z{*(CoH!J22Fg;0cDSMkOVmqdT4zd3sQ+aR-9OI&?KE!a@LzwmWz4&C`E$Si3XX?){F1jCy88fo310Fv ztLfJ^woSrb(M?!FO?Zk7l+?BOHt;)+3C%iF5tQ@@ly!|5v%kQ0}21c8~4?wN$n90qn}D?>zl?5f;w@B{6>#P+Dx* z7u;}V$8ho&JD@zvEyVbc71b1%6N z>r-_M1KJGfAwP1k>QyW=?eR?P_zH6b%wF=Ip?z*pQKlnDWmFPq9lupt*91-G1&^Ct z8Y%a2P%Q7Y~F%;b@a4cuP&aa=@XN*mxsktSU!6 z{%99`z@d@j42$JB<7eTN(S(MfXoGtp5Axsjr3WylHY*|EK`aFwdMps{471eplPT+o*)yRUm@-vEUWr{I7EL0C{&(~X4d`T{Va zfZl>tuRv^660OijARg48L)LXy*IzQf@1m@L7I-swfJlA`-vxQFPcxCV2N1myCG&y5 zy#sAX-0LlWjm}l~JlBwtdZgcVl`W}nH`?Ie(=@+*{FLvz=Awr2O|C9~f6an?+N(uv ztJK;wf313d7c$(v7>z%RfcrP}-!I5Nc=?H`L2jZW^m@y4(PZDrg@%TQ&SoI~V~mwb;Lb7jt1A>Bj)V-O|(e)C@*+4{DY)#L7i(wD8H;`aBAnw$%r4}&J> z&M(yN=8bd0k;B}Mvb;dOn*sn2{+dc8%&6J3@&@hubIGA$Fa%a4+^u`_08E_?z{ zaz*RWngJZD1t>SK|4gKgOq`j6J7-_l>PQa4>9{fjSEgCU;@dQQn{r(ljoJdcw7)em zPLICmJiV{44EY2j_YRe)x2TUISq61#=@`^A2K9`&uAa!7S9yq%OjbW;H?VplxVgsa z&w+0Ho1WT_r|7Rf<(Jc6_CNjQ{;ZA-r_VpTW*%W|U0QQfHe+>8#*9u@S1dB1Lounx z#n?f7cHvqft`+WQOw3~J>-`b=M!|k*y_o9R3`|hSc`@LrW>^a(TTQ;_Wk|e;u8;Yd zP$>}QvjkjPTa_$F#X%ojMV4A-BjlR{%423G`@CR zAOEb(%+vRBx4r2m%`KDX`tJ4&g=Bf+5kjHV*6~|3n}Ec%LA3=)OumCqcKpZD4t^`` z2alsn1dI46TNGSqh2Gb!?_~}rq)tSg_=ZA9i`Wt$v;FA=wU5c)dzX21%|3bq5Q5y|yH@tR?~aq(-L!I@V;qi*qbHH~1Nw)fe!@CbQnlib>Fh#w z39Jd!N2`PlWmxTRE?H34{Y4m;7SesF(ajs#z5^c z^sBy_gN@)&+aI~@4?~Lb%aBw4Xcs)vBZVUE%d6aDC9l3W=7GfKP%^K z&|qqQR^)tmlvr7(w-`~Y&^%;E)6){9rSN{EZ`he) zory%g=Hi?VvJ9Q?kA4LTgh`_KS8nd^koA;4{qd`ufCm*OF_N!H7DYdUx;gaONDg?^ z$a!Fe{ZK}{G?Qodd;}g7C$Wh}cZ3Y)79bj+719`4fUiZV}`oGaVD^c zKGP7&_spt6G&1o@EA>vDCk{E68T55nC(uVbYTe5k)p*@9_;Glx5sIc+M^ueCQ7^UP zDYOBDIB^tqYt%}e+Dc~q1XA>`i2dzwOK#3u^~eTwc3k6CQT^@hy?&!szaxn$@i z58_!Le7-UZzh5rlvKI|T_AwPxojO+VEtjBEqjJM{~+MU zZGM&jKDD^nYf6HId}yWMs0!ypGKQ@Ws5Ydt)dr1I3CkHMMSCdQld~&rIAwc+w%Twj zc;}&&J+3U1CgN+ac?0=%4l_P%i|4SfHNcX0SkcZnjEKU+mL*x5u+5wa+ce4g^2d~S z6^Nf7N)LU!n?@OUV$C$1=AL#o+mCr{DPBE4!ff!td;_;bhfq1858NE zd8~S*BcL5W&6$s|m-By&H@0WDub+=Mw$mF!MsM$NaUb4>H$MDCP8UnihFyGJ*MHr% z9c#kk4x#9cu+O}I<=u+SjoOjKbAVnZ!g?QNn=>}18u(eoW zM=8t!S72VOwREO1$Jt&|_@AvmD}fCsM*D(8HIf#@xpfl1n{DfvlxZ^}mHqfB`5AOrY& znQuDZLME9Mk((CUP>VCO7f;cWiUq+ec z%3A=A(ZXBGTeyrYNa0Rcd+peJz~c+oSTroo8Duri>WioIBfTvgm4zjmo1NJg4=Zs( zfBA@%+|^w+pojanJgk(3bw_oj7$a`;l&Z+&BY*%$^RN*%g1a9h%f|5Fv6ULk%G8ZD zHA(j263IZM#Ux}zEqEAtt!HANmQ+A7Ey+I0=055~>PClj%%ivS;||vTnPL8OBcU^5 zx>Maln}3A%d%Wm#4mrHklPorPen1X`V+DJ`-&7Pv9odKWhxzyo7QL%&*QxHyXH(EV zdX6T@BVwjh%SkR-tKH@nfuC@L6OUXsjN zhi>!>X?|GGJ~ag@M8LIVCHVuuvv4-XZ#_FKLmX3X+j3C+N3RC!^7C1TlPJqj{9q@r zC(|mT!b_r&PheF_xj_;vNx+}U%yNhqyZ?%e>sSksb2=HC9nwHFLF<_a%}r9psqVFB zpQ?dRpK18s_=_y`I@Cakpn)54kDFA-00A#z*JtGTP3YE=DzRQ?*k{ zoE<-4r&3Gfj?8x!8h4r>)sOi2?1)Y zQ4@X%SX0Gye#apHkN}?!nq`{Cq{rxOIO{M!OSg)nh`YmYfr}fC)i8kbX_bjUr0a9& z+WZ=CYn~TYH8!O3h1NAyueYRsv$ikc)Zf@f=4~|vlQ+W8qb~^&iLRItuj~?Ub&6u@ zro1eJpPoF@zqt7&7VT%&!Tu=Bsl71CLb^dYXdmSo<< z+RB#L=!vZ(AuXB^*vqABLSMEf>uj%RB|hC8vc2+UYZ4+}9I-}e*ncmX0{@R&D4#jL z&xrn?H*do4X|`8vz%u;?GG;umCA7w*+O;BK)o>wZ%adZ@4d}9ll%R>5^=Bt1<^*F9 z&px`vl;ML6ptXk3_g@yE=SL9#LC+6^H;UyYAi=&QhLTKM?P7F*A8!ba5^H)G_9MB_ z+4qf~CR&b-?+{MlQ2`!8ELt^pgi{GFX&qBIe5UOk$Y$5x2>ein`w4pLOu(Fk#_>!2}8n*~} zIe_qp5shYjQzx>%={G|Il{vhEA7>81=UGQ`jIN2!5rtHr&sq>A*<0iLe+dhyKXiC% zX$xC0JP+kKqXZA2dxj^CX^mR6_B^*B5wSw>$z8CZSr@IH#!Vew@n`3^Ka7*q7FE*I zqXR#QFJTW&t=QON%%D0M_&DlKfiG}ILVvyFFFZ8K-l~DO5SI~;OgEHeazV2unwz4X znwc&AKzrd>P{hYTsw4_&$J{Lj#vt|G;1HATU$l!4;GE$9TD?M%7leyLV~jClcF6691ZCcc> z1K!vi>7;0ZN2%a17j3V^Zj6$K1Ww}H*owhn?_hg?g*l@wFtnmBp-dQEffz;&vwB*W za%mMtcoJH~Q$11X5A?jhKs)PH&$@K{nu*VufbW|qw4RJ@4W+(D`I&^)?Xf!8gLRR- z#un7gk%34JEgcx*_v{q9Mw%4oyor`q2X)9xcNtKSFV=L0+HNZ*Y zO(QDC`sWvvImgrrma(w>bA~k?&wp5PQpR}Asd`0>-8g!yrIMGD17j;oTQ?oji{ZJ-2V*Jo`H-? zc!I01UG3%0&{)a#3XN%ch~C`~IV8W8!8;8(w$KlgCA7|#R!MD?dSb1pVYzm;)bp|x zza02m8{ob z9f8Qj;yN0$vHk@GevFnEqcs{>cHH1K9aBCuR>Z+GSnxAMP{;Y>QTnkeCg1j%xu4QM z_1Ob)m6omPF0)?`J)Pi>EvK|+J<+a6)}|bAo^T8jc@&byuAr{6IYfte5+KF zwb_=<5+Mvo@)Fs`L|#}zLL$p@L0Ezz%SRH@EdwDkOE3xPAzLFG!a#tGYzQrzr432< z5E2?YOaD!lwjqQeNi!pbG)-fe2too_2+78_WDNL!Pst{vXQpSq@Bf~k=fRS0Ro%Mx z-2I&QyoVb>-UYAYt`lN=sV!{Iqn=vaS1^NxGj8?kEVn6BE z)njN(NpJs>8Bq{!%&kaWJ zqZsKwO7U;!hdVJd4+c&nK0kn8WWuV>7o`3cm)xlD;&M?1-Kvb5$e^KhrmdMf`=ye^ zOy+tHks77(w~fXh@2G@y1f!G2;63Mh))?{2iqHRK404$3Fk|xlvnQh&ljb`Wdbu=n z=2QPDzBO~k=RNbSd9Ov14fKvFkkDEhg&2|j ztBb(_WUmdQk-Kd){^`fjh*bu*$-h}+Aicjo8taT0A4?iIX`L}Gk2OI# z)UeYOSygPR!HTo608Ey5*3!7FMz2aW+*zB3)rrRCs?HUVA&pEER?UH#Y-P)pvvJuO z|1;USA-jgZBfB~)B3jD$PDx5BF_kl&<}Wqk$uEW^4M@?Eq)1NdhbzRm{E8&`Wr#u{ zW-;{-#LjIX8GbOs9)1hR=-2;){JuO+vkA>;|Mgh>|3`+E|3QWio~3@c$Ug+TC9LY; znYDSQl%!)NFw|wBADX?H_0sAU=C6kt@U<^)Maj?(JaGgra69KBrDO%loMgfsdxVE&V_oE zzTSYH|6rzeq!=cE3qQ^4cF;Vu%O4T%tXT}E4qEvQ^-EE|pVkg_%QAZnV36n4{WXM@ zd!Syl9;0psZXD{C^SVfDGHNEH^-Hk+0`*EsM7<11#~N-Nfwfxlb360*>m_;GQN7~p zU<%cX(tffd`)R#&sFzOUZ`EwK|IXTon2t4lU>q#Lu2kBQ!M-!lcJY?`Y3&R#nQkcU zKveF#(H?54eucF2PYN=Q+D?#mn6BMCioRp+5SU&f5iq@C%3 z`1x~<+qffXC!IBi`BLE-aIsRq?QpN${fKD6+=6>`U=S*YSH6)L*NFp^R<7@(#!DB= zvnYmbmgQZmn9&oeh9B@xqqJwmH90q<1}Tnc+@9J8J(aOPZUmy3R6wz+doXd<7<54I;}Yc)pMRaFO>iM1p3+TVZkKrE|FqCu)U<5IvKt zPQ;j-Vr1EHYWdpzeRS@%fp|XOM~_}qcupWf9Aa6XQX<|(5u%V&6xvT=6*zH8c;|BT z&c2U=j4eiFHAcDt$#Xm&xA+gRD=9HX$TEAtov_^~ejjbPNV&aN(N$5nXwPIy`PIeZ zj_O=0f3Kq^V2rFP{h~x(!{;UVmm|7D!YNpa)j459lOnJ+B>#xR$#M8_IxDv0>I|P^ zTfw5a&|2vlwg8*FH6(ll`_U@3-*MSGZEHv&A;M`qYr@7)hXfp#b(ESzc=+g*Lpigs zzklemHTV1I!xy7hzLN0agp7^IpP#;zfSU!`xCrtL;O2v|BGn>BQ$UvX-rHh zZEEQ5-7X+-ncT9#H*iU>#XV=vj1@)*Sxyoj;w)lMe=~pH2Y19zG&KlGYPFyTY$Ns zaoF3(iHLiH6B0NV!2@FNE1Dtny*Gm5J|O;sq%~61DIK!9DvJ6E??BQXW&0v7LS}+d z%YPDmh|;?KBLmDBDOY%9b!zLt-69Z%HUpwFgZ)Zv{Ao_b9cwgk$uW2oANU>BaZ|Vz z{a4u}+p#Mk+ri@;&93fnE9wU4Z?fBfeSvfV)8zw7c$V6r<;;!=Kt0TbHSopdA3!t0 z*RaT|Zqf-=gS0dVEx3n~Mp1Tp*DHi9bpqq{7TXK`+}*%@o@W$==6rN^*z+;coyc9I zcw?-qQNmHB;ofhcNl9z2UIZ_0-*WiVcqUsVE0PvbEZ!;u-)!0WXkl0xkRrV>{ImU& zjj}!w1+F}YvkM~tw;3iOvCSAJ>x@U}Q7Bt zpZ@s%xhVbR==kfDyRL~dwMFx9SR_2>`RId)*GKVxF@6|qA3T?n?Kdy7H*LmfOOJ4} z%}&Ah&=T&RhZeBxl+(8EPaZKwW-zp@oDiL_IEZ!W#me*1oGY-A0WA}i`k3G_qWng@ z_k4836%NsPS@!8>dXk=kK19L>lfCT?tc0@tq{Sl5m7?{H5TAozaSiXO^U=KU1cqg=Hi^lu# zgrrwg_=`K18Gjv0H++ZjaJF0Z(lL(+7Oiu{VnQ^bEw{ zrT7!;nyL_EN{5kHg+7u9f07LMtBCdo_P~o%HPEHIQNLZKpg2>ieGFhfQ^1nSzq)|eX~U?P|SN+ab)aTc-s+k zuEpS!iTMcBH}s+r##V%Ob4Q#^riAqai>g zV#eH>Qjy9u7giURVHqZ_FG_T%&+CL4|ZHyGo|BR zU1GbCWOa=4OzF_;u#a+E9VXB84!v`%KB?<$87vkJto!sJ)-C7;dno4U5d5{VG5DLt z@;t^7qdk@gvyJp9+CN~!v6sUB*O=*nCF9ptPhxvf(p{d>;!w}9Hy#lOZBFW%@X#Ib zae_xpVd~~A&#~CyhC6EzGoI{!jC!Ks4fI7LB7ISh#7vbb?$I0H&_kDh2KQP;J_6nv z3m5svHOxp_?#2a4z7v9HnO?W#ak<# zjZ1m#N$#wooyq7bndO9kYwTgzDmiG&t)kMzM`rY?-W9s+vy{%p#l>m#K1W|#z$&V6 z?fyQrrBW$fm75wDlidfrjku?vZ}bk9VMT;aJ~FzmG`3O06*VqiWAFOwn0nMoowto; zY!eH>jdv{OYe4LSeH)E(51~N|s7kQNM8`3Ss6+Q68|k=#vMde-`eeH@$gtN=(pj zlcN4car{nMCVWf5f5dEjWa~{KXw!+()vNxoI})I+^))1#MDg=WYHr;2fz}ax@jCqS zre%Ko+Y2{c{ohvH+%sR(zELyY%N1?3j`xtf_M5z12_#3B-EbU^7D7-h8%VPmn23 z#O8V`((b4&6qh^68l*=g7+$Fp6TZvt=jTiGH!T*7!vc|KIOMga%DPNx;=pOr_;ll9 z_t~b!)@Po3W?HvdTOYLSJhN5yASF{Ekt}J6pTIJKY(^(eF zDBJfwF+k9JPTlBvyBIysfM^(ecB+paE&rsq*w`5o6m0G8=n%8 z(m8N@!PlN~i2=I%!}#4lrlN#YJ}_<+RW4g&Z#iD+%7+c5s$=$QYHw<3V$wExS!NOD zrt_M{#Wd@VeS>9yd#Ym&R*3V_Z!YaYT)_ljrhdi<@1SpX8Z|+;hH8TTy9KpDkFWHN z-+nT-Qn%60AIDwXR6pz`&c+_rK=#Oyr^nUx>|vR(QW;rr4cLQb;Z(uCWEfu|*XO1ppjc4~WSO~uzV+pX$+e!r$&(7bSA><(IiY2B6i?%w0X z7;n8+Bo@_YExr3~qbN&noXm{{_kP~0&T0GiVof%hs%%Y98%@*`-xDG07|VJXbB+;= zvV3Io^;~gzn)i|2;_hWz?cAv(V9oe(a~{Usa%N;1V(G=!kx%YyDnr~$>On7EFX{e6 z{u30FQewpC0G~Ww0v7`@mv9dVp!12QB(i z<6^XFjoZXBf9wIrFXGJt{-=UZsp!!suK;hc5?*Qiad@|KYX9;y8&)trGX6U3`uVfP zCY#d1S>vZjCY>Uw6*ly@0yp+#Yz3Z9{`w^0kFnB|48OjxEHaWKZ&`h_(WD7hX}-AN z?U$+GL&++QkgD~XLmUUG;`eg$(`cMLzAj7T^0nE&1|!hn29jr%m-_Xc;7|UGJ7-6( zxAK6gPV9K**~n7x?}KAd?4FZ)1ix$Sxv)>i&okkVMl%lf{}+!SmF~6H+hY0X%LmzA^>*i!w2^g3un$^izw+F>^_UK<%fVr8EOza(1=jeFUe7Jjds>+~(m-x@IOK<=SOwkxVaF42QX;*NA z#Fq91{;|3BbAjbC9f>vQ_5_M53PtSjl&8dv_EBe+T^(heXTU1`$VhPya3-bV8^G8M z5l!{^4z6qC^5de;kt2Q=-5#!V?J1RG94>cOR#+UB<){3G;wd0WjOpzarbq(cQQic6 zI@iqQ8_iAS9q{@q9@GTBhd04UHM8w&erRoVGgxWM8@k+OM}VKo*+D&mJlb--)I+*{ zz>cgw*OL(#4&BWH^LNpC;RTSWlJ*H>T@}j_62&zyi?V3l3rBMnzyzP?#09>Iwv{fZMIgzG7+f!`SjxJUx+G6y1(kYi{YDd=6R=10 zEW7$^BaIB8B=WH{PbCYPdk*`^Ixh`cT9$^$PfB>e!YfwCCi@e+CeP9#juqGQPkRX| z#%C*l7}M)!q_NCmu{dVEt6*8m8^m)k!#B2`%bDswq%2mBMwCYLnkn6P&!e}0*8LrS z4EC?vfZrAl zaI}D~b}XGN)GUjcl_MxGdUK(NN9-G}D9vkWLR1rz--alm_L2S>9Y3?Ff@`6JV{Clw zN(XoX-IZzMJf@Wv@ihk@DevRPO~YPQ1Yh7duN&t?o2bBk(dQXouRwjXz?Q*)g2i)A zpwDu?@{g^jc1Nq1&FtL1e2<9MWXxoXW$C_v#bAZITKRI$WU0OlT}LaazEp2be|=@C zRmxqxGD+H0XCC-us`sIw2RLu4X=Ep?%%L8%58TZ%-$rt8vZfn10*6(tSrG2pH$4~y~#m0|uI-Yxq z>ik&i2yfvV?!_}YCd|4eKVZ?p73~2pWN?Er#XD96%RTBWfU${>IRCCp#&2^-ZFf>^ ze6O*IxO~*$YT_fMH>gY{=<~mvRg7{PokCHij`|`qH3b(YE5wV?1Jim*<)d2AZjZ|8 zI7QMKBdw*%cAfI~r&*xzjlvzAMeE0^#1a3=!S+!+7s1LDoUOyE#N`DjryOWF6q2tS z-O~`9rK5Z3`UvcZR+k!1ejF@Iwsri=>Y3d(L>VRChLsKvv|H5bYQKPe+iD(B0!-gU zp9=00N1Yub9=fng90ZgS5bsqZyzirYwCZq+eX*j(!kR?Lo1++wu07C#>wZbmD0aJ9 z`@LLBjjiK;)3Q$8OM2@DyBYpJ92m`a1!WqH!UpQcQtUr1dbjFNrT1fWa?k_j_&#Y* zPfkBQb_eD|m8xsPEX;?$koPK5rgcB6Kzk_)y}xwK!OALMILQJo0 z8-J&Wzi-6|ue?`C0bh|Y7(F?I-XVZ8qbCEVn)HbKyW<7J_E6!_06>feCxB2#>r&ULU=ziy|q6STVqpU{@9)f&UptOb4I>xPle1yWC zFGD_xUb*AZw1>c5J8s7#v8=L(V`k&?r3T0NZCVi;!H#8Zav6EC9BqDH++Ir7{G-kD z#Zx8I(x@h+8;_TLGs->)mTf{>a7FJ*WhZ+$k2sm}vOi`h0EU3jXaDrj2j-^r8KvU_uAjTm%t7xaL%YG9R^-Ex&nIfNB!U~N8x zb@~wY2!ipu^SjzRZ|y1Ks|=Sqn^qXE5!S(T{8?dv=7nA*iYt`)=0gs#=Gg*oM>V5lt zt=!!y?b_rnoU!f>Odlz<;u=NLv;Y__4#wO_YvbcFBWtv~JN{Qy15OCz2X+UuC?>cc z43c{fjNg{nu1jJ-3ng_;o?R20kit9E;EH*|H4XcXI`M5FA#|bv=LYvBXuP2B8fy8v zb7d(2Pe;*_)^kJd8jGv4pl|1*nl3D8&LG z?xa;7jM3kuuxz8h(2JN?4*w;6dYu990=z-sn(S$(b_1En6=H_4egX~2Nnpt94OG{< z*o1u4wQQb4=@^E34ZdXd3RbhH2(^Qj#`33DM9zYilJJ>hJ>$IeInGn#{~$0P7<}8+ ze{c`fmKlrS(R{k4$cvKV*}qrkk^}J?_fUh)IXo@PPRTJA%gH)3C+ z4NmW`^9a;A1vtzRKdE!d$7XLze~k<4a3%wrzMW~IZU5h?b=}1R%EemX5%N=N5-ne$ z)`FGlD_F-t7BWkXUl=_R*2zI$(m>e`I7bTYV-dbu5W7yZ_OSvBj4c9tGW0ss)5@?5 zg|^3@c7}GK<6(c8Fe}ADeXRZf^*bHL=j4Z|pUE7L$9UsZ^sX9_`Wt!}7#Y8dmR-b7 z0R78o`HP<$Grg5|M&Mb%e*f&O{^w`cN{D@BYxa&j7mY!q@63Bk-%H3#YhC$1*R32x zdM3i@%?SpS*$`)C zT@PJjS*JwJ_A{}D#yDGjp~$vyku5#gCwD9L@-E#|8;gEc8fk@>wiEZ8)b(XzDs(Su z&!Zxu`eecn+2*inJZWA5s~_oMc(E)k&GQ=KLvU{=cAwYD;00L-UzWoS;JvD=EN?6~ z0tuk^+6_wRInG6Qhi^tr%{e=U)f=~Mwx{|H^^2N#ah-j%xUN|ZHl#$+;2ln z8%GXqVnH+B#Cw>+OTEveLJ&4M&j1 z1?UR9#&tp)-UUrW=`f7aA^u$WWay4tU9X8(qQAe{(5r^;CD*GqWz_57SwsF+=b{}~ zI7p3y9yPaaS1&u5Gptbj=8hw=Eldx&mBqZj-bm*O0d~xcd59myW$qN4g69x>GZX%9 zEN^i0@jK>;4j0QRi*20y3G^)GL78kjJ;UK{Qw=?nwH?u0lHhY9^R--J>5m+c!6!Mv zPv2L-5_&WGT+iW4CXQvo3XU`AZ-Qz$jT;NBgk=vCHed^^nz!Qv;%!L1#&}`8H)qGO z*t-p+RiinRbSvDXEN{JdXI;t#(m^HBsUd$^gqQ2);Hr*&l{za*8lC|H>djtWF6-rHwca7?XbN_5c;g($E2bF7m8b8N+KaM9y!x4&n1Na5K4i!_a%?IC%c?Xq5D#rLft(jq5# zXNllH*@W?r-#X1Y_$QLL+PUc3klZ7yc{ZTEkKSCgxDgoc<%<^wm6`_Xn=<^DTbjA_ z4W;;-scar04g(&3dQhoN8@HQy^YYI76|mH5S)psU_^fN4n6Oy^-aM3cGuzQvK};ck zj;%=r1G}fnuJa|-S-`i)B9Hc1@b~A^-`XCz*9`ww)_~I$IODfol(Emz_Q1e#2|L}x zYl_cB3qpdZ@IHnb<)H?84b8KT%Z6#^qM0FOpJ4>m3Jl2owHhwfDhYEJ%CC_m3+WOr zk7Wt?%i}-ik;C51fZ_W(ChtmEVFXv#;_LFR2(%a%qU=Ts*q!BFcT^$=H6bYEU4ts) zpUM578tK!4YoEuK?EXA9r&^9R0Ic`k{9!h*5mF7$#p3O_+5KnKh-E11-Fk(m7+jQc zkG#uVNj&Q;0;YoZAtlZiOVZ)fTw@;&W+#Qt7gHNkY{VlQ1nxlr`KWCQZ*?ik#L$0? z@;YhOk!BDjuwyLyFW~B0$=`_ntnbg4_;mMh@FO&0pTs9@Ee~qA#vreR4f_}N4qYX% z6Uv3{Ou@z=DirBjvJ$*{=#0gnMk@KMF)G>XF;`Q(WVe?l4Qy9GEsgiK(%?IKHYcVW znA4_UNBxht2~6jcdF5S)mQ%D<(Zzsh`u-;6-w^vKs8lZqDmY%6)0m0h$!-60>}B+G zcYzEe$q-b?%8PgR%HXNXm4AH)JfKsQ#J=-RKLZbNPy^VMS?25b?FTrx)(O6!rmCMt$&Ow=ehYHkZNU znFIGBGhc{qzRoP)BgX;GN1BHTxxwu}9}OWYVnXGG=)YVOx+3`e4xerKeEX)*bqc(j z9viOxabO;GCkm3L4_Le1$UzQNnlu6|z|^csJx}<~u2a%z+=k~5{esfJ*_DsKCwCo= zo!)gm`WfWyXvI5T6uQ2A$%0azk0$mpOHV7=J0FL>g*9A=CiS6ztFi8#8UvggN&BCH zN27bAH<`uUYB^wp$Nn%p7xoViusR!_yb!&5GtLXEhIZy7>=VBC%Ou@Nw@(H1r<*56 z31(6G*4b4)&XRD3-cbgrDA6Cm?vV-!JYNjG(1mF18ucCla|z8KLjOD>bj9Zpp({R* zkmTq(aW5?4569-rrvBhwrf<@kn7KO|?jf}9u?quzoz@_Q_#?)~gMLqeV`p~0W-prG zIS(`Y2JD|~A1pW*-P}gDxNLCJ65AV>fgnW-8s}Bcqdlb6)fJs|b8SerfyPrDeHQC^s(H(A|2; zqr1~RXJSC!K3y>;aAgVk$qHHW_J^@9&h8OLp)H58NLP%mBeox~OASpfm(gKy_`o7s zv6y`{#b)bf#bEYZu9Wtp0<_S}e681GlCN_UWlU zJa2cmsX65FY>GYEua2~E%-jMC72{Z>MFwe_T5|E%T-(Nh^VHE%2%Y@{tTAY~OOH{a zfE3=s81&ffTwL&A$JcnCbOt_2 z+r}r)@{`8yLEptCob}=YTj{%}rUaICvXs|K9e*v{wflUuX01#m@!YMHRoUP zEat`l@s=~p$8z<}T=o#j4hQ~l>;kBkvYZLn2Wadnzx9e|xGY=l)8UhtXOgo=V1_c9 zT;+SpFO~lpt&cM#ECMd)B^P4owOWAfA?zqw;vU@Za# zQec6s4>dhr@x(I>ZG)7j3{4*fXJfv7L|KIstkAXbr2>(V3O_jKV5XN{I?~1L8mvNZ zpg-gQrPCGt>e^W_O6+zj9RVjehK!u4!I=`klgrD1-|LEgd@X>vnfJl^?8Gh-yH;Ci zxpNP#eYfVu$cGM>Y(F=e_uIPz6-fcvXvjrE;t9Tz4tF;21}a&gxZ5@iZLZ>7A7p;! z;wr?72Re$TLr15DpE$ej!0Dfd9<$|eP#D69)fs%&4|H59#2vCS#P52Ee7JCjDgq6W z4*S20RtGm)+3db;&w4X)wa9=bw#YSz9YuZ$ObwPUra=@bu0|KY86~GAw&X4jEqPx+ zCvus(7`J%gRfjysp?+HLEDE&7rs#lBexwy_RIRbg%@{+*Egry^e+meIk$uHnh;inzO6u>XxsVzRIUsym-zvFXLErC zIMAMwoQA)A@(5@E@|>ij*ZX#fitTdfwZS6<8KgNswErt=Smd19IfwMA3y)r)(_N-B z)0GKMTHlxy-{X!$wxk5qa~qXm6kXtlh2Bn$W?EM;h6Dhm)HUVXEsLtDnOS9LzJ zUy`G9{;l?LfT!OLOcGiiJcEe9rlNcq^p#xD#^~)60!o$Ka{p=cQ$J^1SHjhOMRD86 zl1Z_K`*UJbgmaBNufmV~7&}uxq z4=i%}ZIKVdU4!L~2S{?QXr*-raK9Y-HXXGY7==)-B+Rgi{Yv1f6#Ica1NV>_UL-i= zz%~B?)J+N39!_0d+SjfB9p&7Lx5sk_pQYqcKx;m6O8*&gQ)K(00mj@m&c((kv8!!# z$>8@ur!upsEa4IBG(-L&`U=HIrF~UTwDiWs3&eIav#m;n)h?*w$sZ1;S!mie*rBP* zc$^EXAEVthXz5>K$^fFdiK?1^2TGL~MSd33A^P{rI-K7u${M3j zRj1wKG2=uTkZ(R4&AcKr8{j#%g4sIqOet3E$4&!*P!99~hltvdDxlqbFVNaPN(G-! zxE{U?>w*&JemQ)`R{-TD6B49&Tlz*~o*{pymZe;Ql60~P?Hhdff zJj8wj#M5I<+C78CDP~#|cEjJ2na)OchRh;Ypxr}Kl!IG9*8r{;FUGo0U5ovrO68r= zy^!pA3e-c(+8xR%)?Yd>Pl9c4l)M-goE5{+S~<{{P87y&36-h0gytB)3zY|6s6_BT zN!rp~(2@>Zv*TI`uJO1=o}B|0pHqHi`xNBgRnGwlmhS>;DN6_*h9(f-%vrt%yEp3dsl3WFv5bZom@iqQvWv|x zL+_5oUwL|w;?ol<~O zA|j`tdE4F!dARxSRa*&uE+sIKvy+`X%v zW3I_=A{tVgkfcS*gKdKLTfZ(~cRgX?9k}1L+G)N9{{l0ij}a}ijnhhdY^_tI*kD@h zj=BAP(NFq-IM$JtgFCZc#{qxL5V_}fJX#&z2Yiq-0VTjlzvuaIU%O4<_Gd(r;R7YW z!xO%mhxRmjLdj~&yB@@<@`O@ySeTns9Og04=q7qXNsoI%iBn6#SOI?FdxWrj1bXU| z<>8cBZm{=wz>4DuX!N9AaPPxkFm`D61BELh2Vch0Gd7IN{S{AwG9; zICGLar2fbgQttJH66&Xh6*E*}H7pRiCU;1QXXIacLW)z`aAL?EQnYzO0?Ht}Rua}O zO%BWGKE%=#a366rP|D+o;JL|- zTB7Vr?cwA+7ksIOu=z=MC~*-V{w?m)yf!1O%A3($tD?Om`g8cL9g6VoS4xpfMR?3U zcSu$LK$u4^2`{=s@*HL<G$(83IawER;0uSV*BM1^3A2(C{x8ghw9}!)w9D z^5!eYLW4Dn!yj|tEf{eo#B!bC-H>|Lw1n{6OP%4y^7-MnCr#_~yiyl(s%_zYpPoU> zOzz7cK`k^B2-&*O&()hkX^W@z)qJ`sWYpA!ex{y@*4`8viSJLU<>7a5uL0lZs-FtK zgL|}^;_#g_>OxPzgW71=6jI{aV`?G17Vj9b2(zf?SZL@pRhQd&Cd8v0rhQL`O(T@y zj7jRgv}5UE`K0QQ>dVa`!fiTR>dnWwWrZbT5;_%u}?cv`peJcFV=-JhqG~qXoO%4Ax zWDl>+Q-(J@xd_*6eSZv{LI05VjeOD=ejD%8f_d!|47k{6w*@acNTD zupO@O2Ha!Zz=z#=^YFhqq(S-h^?Z2D(s|)AA-V_e+&2%Sr#hs-HATH#s=q?2|N2l1 z(lnIzWDP!5$RBlmT-DWrI*v3bP`~Ps*04ErNB?&@zRL|seKlagk;B)XAF)2vfHbY) z!M>VM4L&)v_2jS+nvC}&FI*dCP<8px=I`b`gZAX5JVD758fu7t7w}y$OqZS)r03U% z+(=8LG_+MB(neF?K|TSL%cxdM3=2uHk`C$rF2i@38tghtYw(G-0Na5RX-SlZvL+$T z3|WoLB_5^4;WzWBO;ueHiLXioCw=@K4DT?5A&poebjWLv^nD?&p9y6x zUKrkkcW_AO`rpCzzauSoL3no_#{V=&-|uIvN4+=W`5Gx&p(hb64vBWeKb#kStG_Nv zyeGZ?Jt??1wg00Az@2KC1v~!Kyo8tRcnkW1* z)}rcS&!9aQd?9^rcnXL;q$yor#N7C7S?G@`@flcz>jxp<#fVhaf@=r;F&#eHA;iX^ z--ob*=6~!>4)V{TJv3?R z6x?GEbDKzl4)h!wMm$E6dP?6LSlf1QLXS#Z7=CM?BmCPLV&8;K4$RzB!+VHnWhsZ= ziD#Cg+==U?mQbK2wA2!L#9l#67MNX;28~aD+G|pp3Teqw+9LECx|jSVi0h*!1p2oA zdoik!hAn$Yb1Mz?KyP3ZwFR}~f7K5EJ8eL+179IVqa1QlV3ZV4dr&_@T3q(LG+JroLnhL9nqlI+FavUq zx075=zrDCdGfccac{MzZZpk>_b~5$0c$zc*LaoOS%@VLcN|^=l`yxHUEjE6-ZO|OILZDq*aon z={!9k>3FNeC0&bFBT2_wj|b-?e@oKwxmt!a8Kp^*uEu&m=LMS2$i96LydR^Q`9<8_ z2g}V;6sXF{RTbndz~xt!FT46{69Xo4{hU!|)koaCL*+-4D<{J)WjY$CH@!45?8uTX?ZFb?RhUJ>xQCNr=o#bLP{TC~)8@Q@cfo^~GT zSm-RitQ(G}ax1|#@+myzVdpmJn+NB|y*p<0va4rw^5F63z;iuT1{~a$*b9&B3a;j^ zrE~d15Z|2iS4W>?IlvmU<8H)82;d~=tJFKxK6}UJVrT`}7ab3naE(dl@ydKL5Iq+< z9CN~IKyiRJ%HgY=41W+62egSQVng`{{PJ@>D(+M6@4y&hRxs&8K3cIB7cJ+DJ`$HzDgw7j2&F2tV!C;AKY zjPBMm$v=6<9OHv@e^|01kuC5q@T&MrOz-|nEX^~iVoqC0ue%tZwqJK~T>GyRHIz1@Sg=cK>`-NV` zBe?U4Augde>0!F_ia&lj9nj+^v}=>-{W~w(98?A>0lhy1@258+FQ6WpZw2L= zG{jl>wrIXX(<^kMeE0mqArGD}N<{veM`pIQ-E)XaCcRH1y|2}8M#yM&KC*96OKkhBmRJMw+X!CowC3LpM@l(gH`w*BgMexVX2KB@7TZ)6j=5-#fGI+bFL zv(Jj>{c&sp#+p2#T}gf2v-6^H*3a6siVWY0{ysj`#)6{a_dUGxxA2Y_N_~8s!J+O| zbkk^i${_@QC`v*fS1$w?*2IV-$@w7tS}@(owJW(+zX|2Li1K}Z--$tgMh)ZnQMo8j zDl_s`D8Sq=pmbW)EyOG#?1P z@&%~pw1_|HmV~qz|04tO>q)&@j3i-N2c$62$4Cy+n1>v6WuLl85_donDE$PKyy2-^ zxno?QzUL>bkm^gn9+b)&pKZ?H8ya+C5WQ`vGyXP0vQw=Ty;?DTr!?E#suRt37aDyr zqg(Cq#RfMd8IN9dXX!gD9c!VhBMT=BPG!(aa_ek?=(V=h5(^RO`&eX+TZ2fY#LZRh zp5BpDslKMThJ80^*H!`nYe9al*}j<5?u#u*l?PR_g~K+$GgBk#JKaBTiMa|8$KmtH-8j-_7PVW^w_XBrZuzm;gvOa|QLOKLieonNt#6Y9$(4^t z!hz_Pw!!#54LC;a8%HlO;7g4t4PpIYb?Fhrdz<8SM#2U}KI|pT$dT)6ctGhJJuwq3 zBsSQcepRLQ2BMX1wP&Fx)cn&~d97VUv`EDCc>(fBbFvJQ2FoI=HA!MYDx^^@N092* zAP2Pw8JJmQ>kS4QMYcoVgP60!R^@PKR+)uBYP&l*9=}}^6uCjXJZRK?<<|Ewwno2d zH0}X=(%^x61S8LnQ&y?Hwu-g(Ket-W>O0xbS){{l6(2y%WIgnqh&1B7TeOaxAYIqkBHMnSpaPd+b;C1UN&6i zagIbu+LQyjc!{vIhN#SO)1*~tX>z$N)}14^LC6kiMYmGD;{e}%6L0#3iI zP6_{Rwd9qhUPPXr%4Wu^>bUIP&FgIJJ!LU^fJt-B-3z-pU}H-7-C1J%aDB5v{N&8 z9Y@BJ#7M@kIGVek+FuaBXqq_-%nk!BZSegNwe?I1{1E+zo>EvPsf>es7(YN}thjD~ zEcA`^{E$|p@iw5l0@0*PNx1)?d-A}jgIJ^2<#miVfpd~8qCU08-r1`5%6BqEK<5$p zTa5?`4^)hcrCMcOtRxGcT)}Jh?p9*S()!~4$W}3~2iLDvwd1-DJ6>F$BR+kbJ&kk( z#4)Jv=O0oa5{HFY2471Q*Mx+30@2UFu|^z28Y#|o8tlP95b>YG7Dzk|HpT)xQeNiK z1JQF4fpp%D=!e&-=l&6BEJQr5qVEp_*TN!et0*V>w2Gb4#+b5%Mch?!Y*lIl-S-xl zxz=z%RIP+HkoTd~HTID{Ao`5J7h3r?nZ)Oo)_nNV?)2ICrSlQKs~AW(^NZ)AD$Ef# zqKB`a0xDT&n2%ZIOUx-&m$8ZL4HUQSalH9*G$khaZK)f(*!@5Rnh7Z~8z_ThKVn}N zmbWw1W*BmsCDp)Ig}$z)UO$9zfEuz|{uBYJq7v#*LiP>H)dZ$bCw#=HEcZ$|jOedp z5?IaFq^`4{@lEZpGkGT?-%;Rc+)GFj36K=Y@J4iqB)^Hmn8e4+ziahjz7?N+IJL(Otb(;M?+n zS-BD2*2}V3CY5M+Z?%NyPr&mM>aJgEpZO@)A0+f*Z}gsP^7=OsGga$($Z;rmh*#`< z6RTT`0j4)JdFHhWgUVd~SVe?l=SC)8vU~mM+Ce%ak-P7B8 ztKZP|^%v+j@pT=+uWv5>I{opI-Mwtw0M--efVw2Hz_r}#Dr!|{ zE-}gRbD9QPHAm{5h0@=Jy|Mt(BR}h58Aeh0E)epsZNYfE9U)I6Z3}<+()M@0xwIW) zBJFvqNjhqBnBy!XTDOFjsSn{a7spc*ha)W5`-0KkH@}Tuyb?dzDHUp*;|9>j-$qYg z`5bitp2f&aw`#N+HOeRSDjSBY>wkai43-yCKH(OV#FH`jU|TZKCsxk30G)w&VG=qn z*>@7Go(_XWyc#XMZggNg{ak*EepO4p6Ct+^@`zlU8F3dAx(}nL82^QD0w*v1nkz2R ziQh&yUs)5rW9@1Yh)*Wp$9a@phbl4u;WJVxcw_;r7Vr&8>k+`_@O^Z94+nOGZEhex zQ>(?*SX)ksZ;8t65vLW|DXsEtGe*8PvIv;=Ob`49o!rEdSf-PkB;O{>>pq<&eumy6 z%jSIYYUi4z+lZl-9WC@4Z zD>|^Osc=e{du3Z6XDpqsWm%c9re_(+Cz6NXDYPGI(!a^u1-YcTXa$-sxL$au^it~r z(HfB6!2kFLb^jX{hW#tp`b22jx zyAa3y-iS`SW)#mxU&c;lJO6ETZ^#IgnaB2R^f$Nm*4KgUeXv_^+<+FZCoWlOtzd5S z2K5bKaR)pZX#Ax1I_J}BvES`<$w%3+<0%DJsV$fQU+oceHVLc_MHkvxu)5<#0IpJbHQ-La~>)EQcAzvt5iN)$7)23r@7ns z6y3++iVgid>_M@yMp421F&27XImFCQpw=_thNzxdiR%h=;cM}#A;U9D(n ze_SowgPk)kSovDcBX(?i3OU1j%(}9|GRRN-0N+MgsPX{smF;D?{>yS)=eTW(b`>o8 z-$pww%PcYD|L+y&R7zwa}Oid*}GxE~9}Q~x&Fe0iW%Kl)@^_faG5s%cNXz>Ix$Y7OFiF=OTA zscE#I#txge&8?hF=QZMGoYuX?qL7dhiDJxg63?8Bx%lE?HTJ|agltEY`HXL)uU{Ux zGQ`00z>E|C8aPkWdNSrr%@H|=6>@kP_qceA<0$^#LcmM0mFYb`oTq&l+){^!9(#)l8-jSzdmTwDuS=-el}9&Q6TOp=i%YIUaIDUr8?Gb zRLtRIo|$bA0Jy02HUdXD6w#;Fux-FnXMn;N`{r6Tu9&cT!bhkF`@wXTYif5Am=QU? z7-z*79YEfwm`T-c;~&;XF6%b9^P9TZvTxvzV(W{6?e|)qqwo3*dpH2gKKXDU zloU=5-FM}g0S4fy!qsG{KFRgPW6YoLJ!lG@_+7`25cqBT0)&;GPEs4e{QwkUibvh)8B z+k#=t^tZ$l;_E+Yi4*^$+{VCiqL-q+JS63YcJ;c)u6DQ`T5zM+|A#gZ z#tBjzRJH!t0`7qph)0@+W{Y>3BdhGM*%8AP^FY-I>@dt5<`P4REV4>g($=Dj`qkF> zoIpCKmd0rvE0$cOSwX98x2gE{mj%AvmUJDQLrFn74~vpo6_hJdVK?Pq%U8gLN~^0D z*9Id^7+V{ro1zTX z5Rn3w*{!f-YzZY8z)_z=ImPp_AZ-+`#oxR(WX110@LNw2efsa2AhFJU`I2PkktsaTnj7tWZRfrM)3xxHUeo%;_HJ(5EQD zAOxg*@KuiQS~pJE-JI_8vFDIF)8S9#nuw7@aK$+jJev7#M7U%@^z75?N?c}gh| z=x?Ed{^supDe-PCuvzjM)u8~stEZw&PgaK-P`;%8bSKhP{pm)e>rieP?up?0;KyY^ z5Xr+le)}d?hZ>QVO0AzK1BR_S-iY*3{pmhKRVbpi(e5U`HwVrSBUc4J z%>4~91)VjDhQT+%^J&S-?e<}(FvDv<0ao?((u6axR$XPe8ej}r`nxfum5qkSS zPhx!FlbFK#oa0^m{r3xaM)n!<`YY^SrQPktDH4|&bG_hLhTY4Ei`e%{yG*4>Jk|rY zrhQ$OR|GM!YtKsMmT4V}444zuEb|&X{bqLVS^g#TmVMF3dX?=dY*}P5$48#KZgev9 zr?KsvbKa-1om>O{Zs8i7pT@S9FD(Bw=1Cz`H0d><=Y?mCp@ep}XPvaGe!Ci8&6#~U z-ew!H>$|Hzjn$f7gCC+9&v{eMmhXtwrw|`AG(D!X^Gp_Vb6^o+@B{Od?Pa9hTmJ9S zf9Y#jaMs0TYg?a91C~0_u;lZ(AKJ~$M;@M6j`YF}_O4bNPOpDr^S!5_alIE20W8g^ z2mfj8wWg1|s#htFKTO=2h>cEVdaOE7fz?35sRE;F@nc7+srg^6)Apf#pn1_L!O>*u zi~a?7i@s^z5thlvO%uTRg;S>8_i1c$P27XxK>NyM_W!c?HegL%+5Yg}Cm)0)NWhPx zqMih>0nrBhsN>i%#BfAwD=KZRwKD;Any3{-oxzz-4OSg$J2PlME`GJxcBa&}3bvir zIvvnfYwgTjQk@nEwy`s}B8Vm_kOQcBe=EW2_@8_4d*A!~pZER0&qY_x*FO8~@4fcg zYyDO*d(+*)RQ3wZEbM?(W@lr;kAf#%W&@|1%|uVqUl*At&VKA=tnE@HKIKhV1i6wm z9rIQ9=9=x7p%4A{HOuI2PAT1BUoRcSd&U*B?ZzT=z2N^#A8D%lT$^&=@~V9JI%np$ z8$XhhtLO9_07@}uI>_GfJ)y#;K0T*rPvl;i9h`BZ2vntOusnmzvE1jPwd@Dw%U8w) zESl<-aowALrmob$OQ;IJ4oG@{aG|Do6x@uccs{l=(HC1er)SO@N}KJ#2D@g@AxZIq zc9#d=((SH78BXNOhI$+dVA%*!O{(hh|d@(i)R)|S``yovg{P*_7?)p(? zOluM_a1m=lg^hn^utR&cCtRZH*v$E)vdp~lPLFaYH+>*qW5?k!ngOhP z3Jwwrd*d^#blx3?bzwZLm_u~T*elCy3;coag-`h{ayyRS;&>6qE*v{?gn^s63afF| z&Mh)btq?cGg?Mko-#wb*Lfj(;;vO~-cQ3R0-H2y_uvhNJu>i*&9Ph_5gyRD^LWC5F ze~Y{jSADqKfMY+7M{&G@<1rks;`kwsSc{p3dZ&|CflkL>S^eF$5V_|3xcm{dd}F1? zY97>#GOL@@vvmM}N7wNbN4vzxf0XGexsRTbpLW3$^IU9Im5+-t&j~xo=Xpgv>?YE9 zr5dO(L$q^x>;o|f(r2=B(`T}y=rgnfO~8!VLZgiOxK#!c*)g;`Y6Xk>=Ey_z_sbf` zDcBtqI!^(UxY`LV@K|`ltQ3DfN7m>aKWBcJL8FA`$Oiqhy#^fhdLN!Cfvo+~&lCM3 zkO*2}{eUq6@#tBJ0kN?}*Z{@SeT&sF+b|Q7@_Fqp#kMw`A`k*4o_F=kV6?(gClWJoAM@2J*iYbV&dM%vn7xbahtPBDyPOAX2VyI)_Yzh2qV+r*{T8c< z)dy%Kn%BOYSSlQ({mIZT6OF*(b~2|c4LbDgZWUT%+X70Lybc%<`w-ytSEv_mJ8#lLQ|v;{@(Il zy}G-jgq59)%nD7L%FU_uZt%Y%0ghU@RQudtUw`q1>izE=$)m z9u4^U%$}2MsPtv%?TZ;wb&dfB?>8F?J;;I`?%Cdn~zP^h7?n@O>fOSZ@?^+J_ip+jICE@O}E6 z&F`f>LEiC(aYi}|x;M>he*+SvCzh;ty$&l*`i9Wj?c8ruweX2+3psc{znA--vV~4t z#r4t&%tRHUzle!PZ(|+X*BIf~J!b^>SdB`bBE8r@1ADAiV|Eg^Yyt{L9riZcy%xy& zxc~34!e;)wO~51en_z`Kr{|Obsb*A;W%dZ}N+t7uZ&S7NDX9i)LN{~sFGJ}Ue}4%$ zkd@lt7X}T+ZtO)>rb(MFCmnpT^UG~7c7F9KWZh!Sb^*_hlAXE!OGx}wJ8`B3A_QXL z9ZdHnR%vPc}iAV*;v?FS@V2fVphXFVPR7Kl09Y2Z(!E;A%>@9 z&Z=+~uYO8aI9ki-jrmI!l@)%g6JZnTc}ivtW*17uVf;ADpA_$7ArGh z%L{J^sBa5+7cr*N;S}J*d!mt2#qN}40JrYDjIQhmH9qyzPB+BGO$7BSdWlt zIvrc3*=b!;hTJ}Vn59ne`A0Y4%gQEt19qjAclw3_``P44$jm;?#*X%t05LfpUZvGL zw?=A%r4MP;`UZ_n@I|ljy?7nG`G9w894QO>z@ZA8BJzDD6MPh_fLQ&9;>}8r68MrR zbEfj?fo7xhZ;V_K$57+cbyxqKEZhI&xm+ApW8t25_($UAm+ITVi!s(#q^e@ieHrR*XCirDI*D@np`^v`D$~}i zR0b@n&t+#(Zg3@bY?+P)QkDJo-$K4V%*g%sh3#^xezL6AbFJgsc;meG9L;;M@|qe! z+OW%przu8w=m73Urf)KG8x5ze!j7)rj@cl+LaQzOHr_O!*@E$X=#C*XF4Tosv zvCE=?~i-w6aWvXS@$GHwJG%W!ATr zCmYb7xF=HzosVs|Lh2jOthS6YK2GCN0VjGzSt6dpXLam~61@)`p#xHB<1R3-)XhhxsO%aEUxJaA1rrsukixk9BG>>rqUDwQ*L4IL8 zej%1KBUE3q8b`2OO^&Ze%s4SH7G{Ghi6 z+_8anUo{|V%j$e7&3G;3iG&Ne^TFYAV7^Ld)es4z?oXhu&H@QoVRqZGUc)^D_U$v^ zc|)IkR-S+_O0p(1#4VpgKuTn!8udwx;sG zAKL79E8UYMS)7ZU;Wz|OCRqu!dUQSUJn9SaZ0?jc*Aux1yl#>EbFS1Zqx^gr*$I2u z9T%9Y$s{>@S9PgX5}y4sGz?lBIg-^R_!ssTuF^QFU4nVO7ib3C=LDBo24l z(qF=Q;u!eEqON2$EWVfJo~&Oc%?Vl~;Ua4b+Xx`^jKD6eCKkG*T+_i-Mc=A`RK_Pd zOK`vTaK~<>m3W>c(}F&C&^k^d!=n%OeW-o5p|1csT5^|}*Zj#N?4gtqf1^U$6uWX{ z6H5RVf3>UJcEEd9*0@>fJik>7RBr5^P0wG0h1s=G%$5Be5<{E0LihP3AY(IChostU zyX56n$D~^L)+65bKJ@La13L(6N!^`P8gokM&?(>}QxnxrI)QbJ21rD(^w%5Bn$Jj1 z+~fJ4kBL7V*qykpQ~OXq^FvmHzP`vVSiTIcY=hUN)KhX>;lt39GRN1{o6{^P=M3;9 z54X`=oV~=D!B6KTD|`&Hf6TpM^MeYgj*WiTRvBK`#@mDOwIvb0z7rL zvxHCOR6|Z9h2+wFcue{f+{%1lbtud#owUKz0VV<#g)7^XY(AD%8>tlh| zmlK)WAvI>I{rDCyNXjp`7Ao#_luVMezS%w118a0HVGW5^NvRr&Ry(qBY{X-y&J#@` zrLO?-TGK1)tzvZvy}Rrm-sO>ZCrLwr`S4=nj`NBaRBvME+4QnAo%lwKx?lGR@T_d8 zu6FV)Dp|GNfzdkLv*;j?*q75PHRWO9`tGjN-ZOi_M?LuqfLZ-d_=7hCh8sTVwvmK# zcF$ktl)Z`4)heYvj7|+klIYRsr0X?6Ye^pVYLKakY|Q00d?AXNm545>(B zVqwu*R(HP(zPF;sFc?}RzH0aZA@VYe*e|-LG zC>XA}@5A#)rI;!z6Y5(^%inVMddm)2#f`>h`0%I>SQXFMbS>FQJ7lXR7Fw)>*G^or zY+Q_IlRVd;^JOow`Q1Wxf!ep5g~vts$ccDj;TE^~OV3_8L6~S(G)$wW}5Q4_N2MJlQ!pvd@!;^)6&wk#+sWCrAft3fA>N zhkatNtQYo4q(900j`C(8o-_kX2kWhpPa@~Qk;AHWVL9n;Vi)`zl_$!12TMa6L(Mzj zVRGRet2{%JSTG|+2}x&^ml;9*B%AxIWQ)TM6xd0MqY_#TW5%K+H847aEGmg{cdr@!tq$NR-c#K5@?@)D~`0kJ-R-6 zM>%kZY8H1mtxgdJ8e~`2h`-nhiK+v?9lZLnt&pnv@Y~6O+*=mT&^4+%+zM_PZhl$5 zWSmpR0|I|p_8a})t&p>R;M;`iRbhVoC}#Re z3TAvxp2kkdixkhv-^X!@f^xrt@~({LJ>`GN`%>iH`55KBW?MAx&-D(&yH>?>y|)=o z$o9dn;c4FB3;3No_%)PE{@@FbKZy_pgLldk;J=9Qk(y`m(+X^B1jr zD{y>X{zP!r!4Eey9Jr-UZZv@dN!*7coYIylP{6jI?WhuAScfE6<{A*UfckN%SC}a0~kQz4xJ#LIs#EI$D zJDcUH`5Xuy7AM{?ZNj{{ViODGE6{oqpFztTOe0D*dV(pD^oTv^0V2?(*6R8dCYGYf zHpwX#KCx_EpU0jw!l(=kVUSw*$A!&~XXSa2hfinE%J<@U7moKBw#Yv)yjE9zxJsS? zeJCCeeL>j*t^+l~>mudPx*m5}V>M=>DJ(|cnv1t*Fvnx&Wxkb8M|GsF$2J;Qx(W+d zzE-$z<%L4yD%Y~YRj(~O_t*t|^$tUNVFE@Vl30YZfNbA&tyE|)=V8pGVIclN&r!~+ zOfNbvr&d0T)n7P6Nj|@_!lv{hy^plCMi9oIF};WxDbL_epgW#kL_LZ)70%Pa9rO63 zk`h+}u4sgyQ0_uHH(>13N*b*G4MGO4t&z7Zk#i9;aqA%)_RP|Ys2#M{+q$eJ<|3+_ z$k;e#?&J?4ZJ2s6sV2HI1SV}IYO9E9>mKQBNZGD=4J$ZsfeiBj?Vd!BhR6|eeg-c{ z+th?ouSklls%6YJ%OFb@VrSf=5#$J*@Oy4YgfSOE|wzRYg1A>YeailQgLDYN++f zlEWJKxCvuNv>0Pl(taIemn!Ul=NI%G8iw-MA=D>V?2%AO`yaIDVSi~0Prz{)>VTfU zf78>7fu|KE#~_Q1d3G4;HldODE1>DANVmML1Uko8%xmyfmh{Fu;NV4jHGX4u<-)hc zFw~`{aoS<}M$+p_==VIhLAa*T~#OCS;aA$%98s(6-~JWX`nbCB6GuRI8x6xkbW z-ATRt?$OWK;yy#aPW(U~20q|ys98Ra`2bgmS3~2kI9+IQi5V-vsby=4i%B#@{PZ+@ zw`&Xj!Gty>Jd+%q(P)ftFK$3O@~+@(LMCQS4FKk7Hl256Uf0fi=Knsl*O`Au7;~e* zx=M1Wzr)ix_H%fAIeJBNII)+X8^a27G_>k_IT^B3aS#*a!~lqIDADKRO!Pp^sY8l6c(XxI#1C*W!Q+1{a;na= zl(vR;Tz>yj$=%Qch3-XnA@gVS>#JQ>=PY&k zSI(a~8~x|ceQR8nRdjZ;kEQ7%Eo1PgXgfu|vfYcA|L1*c;7yvm!ZQETaz44%wZ(S9 zi?OVl_Nht)KMH>q#o4J-3p4Dq(Xy#=qXYp3h36W5D$t*JT2B zU0>1!r)5P;QVVQy+HL(Ebk{Lk^Lbr<U=xWeq+Ur{kB)sUCzjw(nl26(#o4}PUTEA6p0=i&|VyoPYV=9g$v)bja`o(w5(w8MRFATIC-gxoiBDi_msw-B>{(Qta^K1 zPt8hd@h^66f4$%StCgw__y_chy?Jt;{(4ys?>!))rq+-Bvnr5|)d2AwR99+vLsC`d z$@V>sa%O`wDcN5Esad)|CYJ71_A2x9Wb2aL4SDkPCAGb3TuoiF#hE8hTB3aJIF6Pj zDp#JIxuh00lzFoGjV-^>$oeJ6@vB>+dR!xGm*nC%cFC5<^JLAEMtLM+P~tcy|6cUS zMmYu7B4WOs<;lr%R(0Z{)y2e80nl(NBbX>V04es)_kE6X%Ilf(5S2KE>$fZR zX2D`3xywC9#Qd1id$O+9=|;Qnl~2fB%0wT^eeEP^(5ItEJ&!yMqdXOjmHxCSXEgP; zt_Xtn!@XBSaga*2d9*beajx;M2OtG2lh0~KMgT_>EUBB+6b+o7dvCHD~HkTB{MK1mnBkJ>ff+P|IG4*_GvD_ zjz#gzT{AF#G5389R{uMBJ^4UiKu*<<+oLk$%}Lv^s!o7!0g?u`h92!y;k-5E>LeK< z`Kcu-pjog3xR!w_!X_#Eh@*@H211w88e$3_dz~r9R&F% zG^jt4t(9l6nthVRcFYyNUiz|=cg*F`*E3;f@75cB_4PZUAy&?AVA={OVd@NPweWf966ApKB5hI%o2J0bh>4>R2kibw*D1{SjRI zpnetKw{(Q}+zJ-Z3N$t?+5l;Y0zB??Wj}Ue#vPTXeyD0JGY*x~V8_hA*YDwzgziP9 z>vAD$7i&LYpeX)&Yv|lXl{Bi3{M=m)O$K&8o(|}qxnY+vCfxxv$4lv`Sy)Q&*pGsX zX7<{fW#^%0a1YIpT|AT9RKFO~5vS>XStstY0Zo)7U#6lI4YXFsCZX~^*4_6rvRj~W z?-zFH%KM4qS9nSmWdi43*~qh#C&y+4y%}KZAvL)W&#Pv!T}tWLg^jr^tqC)awX4EF zGZ5KqvOtBp92zRjaMVfM{pfn`-^h8^Fid%Jm6vud&-_19s@2O|-Z=Wg;gZD~tvU@`N09wFx z{Xn;r*K@xCX}!tfLNjfa;l zqJi^i9xma@%=t1Oho=j7*%XZ$X@2gv&FMbnsDj+FpXCN~9{Q-KKqoqXTd^ot>v1Nx zh8p_!jmm)k&(_e9j+3&|5%04HClr3vvv58zO+D2cq7n(JMG?A!REy@}n-N>UWRUr!K6Ic8mj70O8!ip$DgVg`>4cV+hxEE_^S?UyE2vkpaB#nHR;L*qvejS z7s_nd(H2SuqdcQm%E%STRp^-zxgvQPUBUXhgtQQ~8#a~9*>J36TbZ!tRGDp!8!;2I z2{QpJ8#`Q^266HYmi-4grt$zZMfdcoEe9awn_0HY*6DRe{6&nv&=9v<8iv&ttIZ28 zUXPkrZG)Cj#3zAJtn{?}S*7%rGy;2NImw?K64K*N|5a`>ge`ND zkIPM>fLzjb^h$%hKtX@ioY)vPXEt7gW(A(H913aRMou9IuCC!~r0>S{KRylPsh*w= z#LI8_$}aTXaJr+>nyzTli^Rt*_T?R-Rq&wJhID4~RL zrN=hq_UwU{0a<0O0vO=sme}>vvU@|*;NGa|+zYD9=TkHh)D_BKVzo}NW>o?<$A%bipx=hAZp!oS62I?iN`JQdTYoQ_9`DZMjp z330pWj$7^wGmX9F&Un+PNGuw}FckP8)beiRbb@KnEqCrPMN2ALCz-djE9TerY6B`Q z?N@K?nsVSJNsYZ3XphuxvhzL6|ASuI>w<=gt_gCV5eK5EFwt?oA#Ri8lr+XGp`{Vs zhTpmKf{yQ_@9Svo=-f20a(p&94Hh#QE;)FtdgJb)?Cm*`K>#i&V7dLa@`CZV&)SxA|hCYJz zKb>d83i0sLdY7c~bpxthTuYV>!dD3w#+ZbfZb;Od;VY`JKF=-T)k~0ZyV3 zds=agGz&J$XDp3)_d|HZGi$bLKMkR-t)xlfyiy3HKv2 z7KNp`gs$gcf2m2-l*IYytsJ_F%uzS4XclsoIbp?oc+)&f)k$ZRD6mF<#Lge1Wo5GDT4W@h! z6n^cbgoN+g5)u+-C*&tQkdW}hlWD}+Iys#9|j9% z?y~*3G0_)qUfQHE5Av*_8W^Y{nmuk@G2?t+IOM!GFH(omQo7BQbJJClY1&O!!%Y)! zx*B21yy+_0ly=kAVAJTEt|ppp^Bw6(7_+hK=z$xlA8q>Zn;TaXFm~U#x&vi&dvcJ~zCCRYJQiTPYsLFZNR=J!2b;@ifPE z72&u?BYw|kgYI66KVCc*yj!TW#dvV-z&Sl{REp^cUtmk|mpDEQF2-}g^WnD&N3t(3 z;^F7-*4mE2V+0R8ny^H8`n|$t1}y^dS|9by6q2l!w!x8Sc*jICf7l^|D}n5~=U&$s z6H@NFJ6BU5Z_+wSX6=+e=X|R55HqKEV*}%{{sc0=DXEOK<_Ck{Y&bj-dYn9a^u+j# zx$R6J@RC2>xW-s$f-~r6&lnfe#IrYM^q!4}*9rJDAere+>o68q1#NN2<8|94NO#AQ zuQD6Pl~Y&eK!fjLJD*bR+zQ>S=o%tAPs(vmNkS#@#+wjwF!raJ|3mi?Su$XqjeYq) zx@YyILemaoky^1GdQ?Wfopg~P6IcLUB-<9q49pQ7B*%l{(D}&wFT2x+*U2%gPF5L? z$kW6_-Q^qAO>tTdO}TOzda`NUr-Emn_aZy(Ph*e8$`rdu%7Fb7_uSz$M{1ynM&;=Z zrC(*^m6b{LG_KDE0s~4-=XTEO*#W$lsJ10Algv}S`)pHMXvL}R*ZlrUs6eKD6sU< zT|cR1(9~ZoxuwgY2jo{_onn>rrb{8$wFhLg-X2^~i2ecoWOTi~XFrDwi)QYPdF=3i9)Kxe#e zKcqN!%9E0LIpjGUmPs*Icyv8~HSZj9P5COSL|$y=;AjlTgA0MgVg0tkZST38uB>!* z*e&&x=AY;(!4>K|8bS#dZJ8-EfpE2IYh zWjBoige=Ae>EXW-zEy$u#`x@97Ch%pvO~%iXA7!enKFnGQpG}PgZ+eTZa5*Q`n;jt z9TQi44*U*YyJm&P4#_9ST7D4h+n|S9yCUDtfr?>ZKo8XC<^JpG_b^UgFOjU)S;3|G z$AZhLbo_6)DbGse`BgU%BE-)Qdqa;7AO|u3UV55og{M8#|J4?7KuQztBojiat-S#; ztT=sAc2rmRq@J|{rD_F&UJkCWm+~l#>h^)!P}VoeOHi&>e~J4>$;L!VmYbJ*C@tLL z4P`>Aa8h1kxc{bjZ$o=pYWO%6-FHeq&QDn{1;$qZ+-?o(#^sC?A|ZzDa2> zz&8^IQdzEfJ{{Jd!G}a|=u97_x4>YmqnO_Q=A^u=n!etI)q6$~aQVP3aOO^$3A`pl zK%=q+VBA=j8{C@zAlg5zn%yh5(B2rUsOKW-%?^R}1|%!#R{tN+%2M?YO8@M6LfsqZ zEGu3+Z^d}O7zcP2JG5e*!Yxy95oyB~bs|j5`H-#rw6cS`TuD%xE8V}xb726+(g*t@6p3pRN!?7}3 z@IzSaGHweVQBoajus;TGX-V})w7?o**&(*%>J-8GGLXj--#=xw1$RfnQ!1)1*n1`v z&|8OGj{y;8RRl588+!UeoeLPZ$xK{RsD<2x>J+tt(pi@iEgeN`ZD9P2J3X1`VXM}B z94y9sF}zg@t{-?lx?T!CIzJkAM5EN>%K13BmgX0jE_&cyMya2D*`Ua|ECh#*n_#)4>r|AdI8SF2Z4la zzz*j3J#{M>tapC}8#*qoU9me7PE#*P^V=1q`4>g@%t&iw<`Jk##+b3L2>leTY^+H9 z%gz0(YM_5Xi#*c5^o`WgulJw*5iNpk2RIO>zCc|eF0`x{%Iz4>Vd?UtCRtzmPT)6u zCHnE@&?xN8%!LN<-(lnX8xxI@FZHPd)1f(BfR-`~_Ne0+cIvGaw(ohgfq3RNzFp)E z{YlR0`MfYTV$psQmM_kG@}kx3|gYIGko4`dApK>X5xOXv3qeXjlz$}PUErp^~ zT3G8Sbyb2#+2sa0((AySQd){Eu0SChSyDtX{rU2Itn9TNTv)pzKe-ALr6+(S%Hoxt z&+$!a^A4XMRsf|%4>aohYPQB9m^09F*BP+e)R8b_Ze(AmNiJb}NW05oy#9kV#-D>dOPXDRm3a`@e_Cek4sW_?SZW1EA*kjB9}cDpa=G#~jK+Al`nOE1D( z8!zi%pK=#QB|Z}Nl(1c9#wGTa(AvwCwt4p7r1@b?7ltc_h|2Zx}xYgeE&czL^yJ5h7V^(SRR{z-WVbnuhl$tk+>pts?Z zStOnu2vjU~L`!H&q};!PzR1A31eUyU(z9(aA(LKm`a)O2LY1YCzc4#k4heG=+iHtF z-4dD^#`@U7fch8Vlp&*;8+>jJ`GNHTC8EMM8K{Rz;Ao~}*1PTOQ0UbVcGqLL8Uh5) zlH$?z8jK7gPiR+htN+)8z&l3QSm=T-O@hwX5*i%V82@sk5z05wOoVNH5&qMWoCc1Q)yOs94=UMmndOJ89B#{??W4$pMGm}b90{9ZHh11WVl&Wgp!+RCNB4H}`<@6)e2v{DVOREB zE39_ti{4Oczlf1>M%U7Vg-&=wYeh*EVlN0IL0jmDefhB4Zjpz;zi58H!=>uNPWnto zAuPv3PhZP0&N|P<>L1&C8m&3OJemn<_Fma+QB z8oZ0@8VQvTcH+QD-GY7~UOIv26w)fESziNRlb3u#u4EK*;w2d#W{VS_nD*yC{b_pC z$G{o+Px*0gO^~qH8Bf|t7K~el@N;q*qn$QwBklXu6p?jEOX#s{sz4@=)2@-{%xKu( z!-IKC=-)aA`O;P_uQRV~34PVs2Ca>x`i_td9;RDDUvx52EIK3qff?$UKVQDhcSdf& zd4EXRn}G9=BIko-9nMeU{F~4VS5-JaV@RkIU9+7Pv(CtGqu!J1zX_cOYHMTuJ#{MR zgSG(w&+Kdoz1m4%d8PA={08n-<5-jbaGlGQP}k;+#oK0S0zy68Iay*8zQul@2CKwN zp;L(I6~szD9hG>#8CZfWvll4cQ7k&&ik8sNI;-*f(*cyhmQZQrnUd^T4thh)y~@BF zn1xzGtyh(SE0MD=u3CdxiORrZv>t&k!k^hwkhc4grn#JT*RF{o+qH!5`EFm_7q<#C zjS-_^XJ|X2!1SNmWMSnf8;qWJtQZ^!)vC&Iy?v5 z0U?P}NsQ@)Kg~!#fkvF+w^$FtiAB;hc2qHTR%LM=^9n%Uu7TW!PFQ-*q>7v;lU zr1wUeuybg<6#BJ%{d@Z&-}^MO8(_p;@PDX}$K`*-;g_*Tp+%{3V3TOD^RGo&YXfeb zqEg$vA9$VGfXIYO8n0iyDD0Zo<-Si@MWgEw=R#;4&n-_K(IV#?mjZKQ*vQ{^yJyU6 z|9m1sNmJ`peTtr%4mIpD1~;>mw~1#;floxtK1ucCBsOl2N4Xn#k0{X{BTpfY4-u<7 ziLPxDOKAxeUj!nyD&KwpZ=y}1R>>FgrO;2W0`qx7iWlGI%AFQF-sK*Y3ft*U0uLr^ zZ!-v3-Efw&8TcvO^dw{)JVgVIBsLBjBD;>^I|poPprWBaT@ifwh;!x@UUf=dQiwKo zh4PwpQ2`lGIIAUe5qy}+y9?4G>Zdches&PZf7dN;BJ%|4pj1dI%+f8Pp%>K>WZ^_0gKY|W3`XQ z!#{P{dqhV|=wt_79q&N@_W04;8ak9_WhZtauYUj7}%7OoeVR5LP^GPa4heQVT!TZBJUwcYDmhk6(0!Y>9IlYo2sfG+>-r z)nS0Po%b zOAXt|H~mmx3Jo%dqL_;Lx`Q;j6o?UNlE}^kaa)}zzZ0D*_Ttw5B&UDl$zT@)JuwVqb@U*gVaC(r;{c>qz>LZ(l4arsm6v?=`^-b+W*LK9%C% zXn#6iIqh5Uhd`}P9pXc8)2;E*70-N&Vo?8g?w-houRuBqnrX-2$l5<{;M)?))r@f2 z`1*y=?fvuGx9Z?!Ju@DoZFR?P4jVgxtf{l%O_yh-$-?)0J@eYFI%O)wv)Q(}J|8(q zXbigSqZ%ONFl*%pEg|*$ z)W>(%x)2L%kFPT999irBKnE>xgERv7dJb29&v# z7>zk`kicF&Owz%l#j$lwMz!ylv)WjhBEVC(qT?89yES4FS>qJZ3u_!x&@%Fw*#W6v zKFN=WFE3!p=uPj#FT+Q&#{F-O32j$#D&?3Q1Wxuj@$%_Xj0o47neCq6fSz^C5(6&|#)h zYrCsUSek(O%3Z>-i=eM%&s!x0-d)|tEfU^_bv~}3cMQ%1v4MAg+&%g*uL5Vs)IP|R z@pMri-x<*-HWz!9J2Cj!Rp`jGa5Fz24;SEAk2fUiYg9|ze*i9 zQf!2%vDJ1SxSGGUou!mSW>27#GWLQ>dJA(Fb3{`kB5kK&pA^mIa7gXA$R^x*w!(@$ z37B`g=OZ^L4U#M9pcj><*Z~A-tmEPBo~i6_*b-Z;&3a&;8F8IZ^;Ygzc*=LhV#dSx--dX#F+K(yTzspPi3XrQMzETTs3r#3*4l}km?28Impl{SC}@`Z}PG;HVqfu4l>h_e$fW zKrWtB9V*|0yk|SYGE~46I98+>`JyGIo@2Wt_x~e?@IDX9Ii}CF@j`7PN?n?=*#P}?ZG4VvxT$oq8NG_Sy}bO%t9p})vDM#CMMCiuMQ7YxdsXG5>a zDUfB5?jQ3XaBF~mli?M1^1IZun+A{PTbeZz{DJ;-|_o?Xbz zW_h6`$>xaX2!-dDK4cMBq=%!aa-&2A=q2-A8h9Y#*-6e#wwHl#!Q7Z@R0{KIFH2Q) zFD%hiYC1OS)O!_Z`-LPS{RyZs)15LI_xzg^DZ($5e zk`8rP_`b5AUJ@=~Uc&U6@Qc`x>53Hrbx_s;e;aim|us*=?(ZpN9nHNY!-J8}4&r&@pEkHEy zDVl@xK^XrbQQ*2hdqH$uGU%WQ`xVe4AHbgHoS7=JVnZF;6$S7QQ{ACaYj%)#h-TRT z$L!K#9gR9u2ptsyd8%Xm>Hy&ZlRsaUPM!wy>StpVP4$_;+vL?3*+_D*HaE59C9F2M zF{l0Sj}dlsh2j8q>h=L44?Pw*-zq!#hdgAfsb6lVZ&2LZM^dbW(@Sx@2Mu%OL_Ynz zN3+*2sdp(}5cbd*`Bv^OuL7kvhQ_KvtZHlS@D{13EW0|g@5P0foj-$(_pdoHq$$N( zK9zhUQp~_?1yZ4sQ|ti`7qtWBAM0dT8#AYM#CJH!apX_BGU3+C(YMU*%gOJ4i{uh!>*4~W(gcV`Pd*F^51zwKfOkLQUN4q6}I^;ft8p8Sf&ZsPO)y6 zCOqO-s0T=(K5=>E~YmV|YkbSQaJ4V!p6oWEq2fInwriNM;r-N=(Fxvo*9N zOflcym;#xnl8v@+1$v$PvVjeU2c;%R@8`9b$Fel+xQ-nnLCQ9QECv`*iC?+MNA!4& zmlJrLeU5z#%36ywfq&gb?IbcIV!xKt%Hk%pr|7&(K76d-;Wb2k&p++l;);3ZZkKv{ zft(iEL;Hi9ycNIL`L82T2H&W5G^|uUquxCT7V-?XRlB7I7i@{$Az-`_cOp~*4Q|{C zco-QJw(K>ac0af{8{V~F>}=SkmbOVOTou8CBh0ww&_USUXT$2}(5EkU9(;WcIrT z;=J&fIF+QoCB^q&v|qG5M5(59QEKDEqv9xSlrBos>VZ{qbI2M&6&Uc@skP?T)YpJZ zyIanH^n+^;<^BP9fqVjLS0p)rV(;A;dDT^_UCP}+bY>?UEQ3MjudW&*4Rx2-=g`W)x=cys)ByVi5E=n%_33c^UL~_v_`bi{(G03?OtI%x> zWjaC)3>K;p25;r)IU|&o*-q*`59VHOR98JEZOZ-SfHe;J-09o|>!V{g%lRX63hTs) z8CJ%axTS+zlg8T%`i-%4ZB5?r!HnNrIr_az7hcG|?cMoPe{&^g+HLQ8rZ$HxN64;6 zIG9k^99qyH=PQs?;|rbEcCKm;&FP0WP$Om=#~H|yYClNB8Cr>jS_)P>CS5wbmj#jp zgG73wF@$X+oN_RirtrGnD6QX~t{n>gT`3KQE}){Z8DmeH(dj!wsB9*1y5JgV2mUo1 zeoeH;$TIG4^c6RU{?>j*wgL%&#Ty#Gc9J&{meL$*!n#@~C16E00{z<4&dk$2Jk932 z9s==cnz8=ZY>#;z{2O-u|16u`f0k20neHN2MjgfSPWy4>D9$%ToE2Qj)s^b~zLhbr zp9q#>+<&#b>hNFjl&7g)S3UR5O4I6Jwdt4=SOXSGu|v6^8Jk1TwQCNms-_;MbpECt z@%6VdFA9<*r%5wYC$%W$-w1dn2Ulue0sg8%}6g ziLV-0ATKN1-@{t1rjFYEi=BGxJygS&ZDkxhQ%7cVj3<3m7hK$fIq9*!!A8N?94hOh zT4A_Ha`@<&D#!i7365E;lFW`Bz%uo%Jhuwz*O^w|FXzo*&pagY?aU}VN4aSZ-O*lo z*tnXoZIwHLr)z-csg!i*0@9pNQ0bq*brSZLSnYT6K*o&?@<{`OZE6zu^+E5K%$jz` z9qh;JN|gR&D{iZ|(BZ@i~tyU%ieMZCJN_?Okch#5)m;bnM{i=2B{$kfs z#8a?-^}>7dZ7i)!jQnSI*CQ@laq-%9%S%~~J%8psEVpdk^3}_hFB9)6UbcSK@@XPV zn=lC}pOCSZ6}Z+RH94j0Tx-{{2TEO$w^kLcf0Q8`%UMBj@hUd6_|Zox!?TvJF2$|V z!lf(mm9q}g#A7OLx>e96=XW36&Yw1DS+PhfV`a9Cr&CBIzWR}M&VhPD)uk*iTleV1_3WXNRfQW?A!`pa zZ5(6ki`N$}Eq0Y+4EgR)%{F{@{?AUnRZgx4&A5r^`ue?yJT?69{9VKSo9Qa9iLMM# zKaNCwpxyzJaSVZaK;58kK|zoobQ#nM>HxKYz5)FWbPjYD)B^efbQ<)ppie<3Ku1A; z0KE&U1HBIVE$Bs16=*x?DbN$3$3W{rkAi*-`Vr^>P(Elj$Of7YngX(b#(~CyOrSBK zQJ~}jqH__H0!jx__^F_opn0H&L90RKpyxqvf<6XOo&;1zDku+B4B81g4(bApg<$3( z(00(Lpcn+s1#JO+4ALnW%Ln}n=qr#}$=Dju`yd5W&F6xi1+{?2s2M8)y#)FSG&}~q z53~`qALIeSSb@c2n`I;@4Rkw51jU28@vIS44O$Kw4f+)EtOA7*|5gwKt;DxaAuS_7 z4yhhILAvPGk~@OQj}LR|QDI6MN4{)hOrnDBs6WwofoN6%ZV2b}&|h z#?e&G*tJ&~8+s6R_2JbN2CQ&fXR|n{DE3YYGtNQ#td4MyGMM zYv=I#54$y>nm@i$a@QZ1{N~sPFI>L;gVC=#|M1q&OOL$1fBy{ZDbM)cum3h9ZT5~C zPgYdS&=@z*Flsi4Im$g;Tgs%X-1Ud$41EG5`?A)_$ z18GYB57IOO;VHjV_GprkygG5DIHAAr|0qrW-E#W((zF%nxw)KfE?)zl4FTO+hm&xR z@rfavc(OB2<7 zHfTC153~qGakxQyKz{^%0~&&~%mGmw|Bup?jId)t6sHwLZFL#waZm$@{{FKx-Q3m} zApDO(^ggBM7|0JYBOR+i4WO~Yf1IY#2v7N(2D%sI1Z@Mo4Qc?$rsh?GXT0v8ghN+-wpy{9=fUcL52H~mBuE$UHMP=;(JqD@mavN7vWSuU`*5r@;7&Jdd76eie~FoDRINP+UKcygzcZMn4)gVPGnz zz`v_uCF=zv5(ul=xo`|S8rHD#a4h3tE#ud8j9-B_4>^u;{~*SF@r*YZ7Jx3ht8KOvGst5yyC)=$iieBa+Dk@Qw6F0J6srWRnm|g-uL^>I@`9csBvZ zXozqBoe+E=3}b%_pATOM2O!yu#xoIXhZHs#+z2F0;KjpX1v5pij93*zQuq(?pNFLL z+wama5#h5DCI#uHx1+H{Q%3Po+6;I?>7(=?3D-lC*bGVHWu&t=l8^hajtYl!*<}1K z1Xd8ew}7Rw`N(@XJQR2H*-ZSZK$Fbi(k`7AGg2-7KR#rDsG!tt;N~a3xu??h%(laD-*NQZS z!&IuFfjm-bAZJA>nQ){Mg|rZ*n-B>ft+}I+3x9!<=|ssyYlcc@Awp8gHp&FZQ!H2%JuD?X-dtR_vCoYDjUKC!i$&vpkSL8ih zJ8AE@IntQ@YwwHjB)3QU%ln1e6t;!7M9A^K+smKm`AW}s*f(D2`8|8;zxMqDiJqzF zJw5LveKLB#+xcju5eU6cZuuFEfcERRL>2IElKP+Q<0lviwds+>D5*Evz8dW?R$;Fj zmWV0k`jsDJBw9V!me=RxtO(m(>qBU*`p#Y7m-ocb?@(&k4+kXjYXu22TEYx z#Femr_wG^f^bi(%$?&b9K9F2b9R$YtUo3QWUUf6?p{+o0v`f~I~*LyX3bHaZ<`U!V_LT|T3 zzmN7OtiR%Bb;rwdxjI@H{TKQ9TNFJ_(Qf|#m*}<8A6PH66>mfTM>HpqZz^|8dwNcC zFHW8jd_Kp$Se}t_S1sA@e$fk9J{?PZI)lWIMaaS|bEtnr|i0)5VzZQLw9J83aA$mPOW1(ox z;x8mxP>BD3uHtWXYrY!2IuX5&Gs~WyRop|_E3F;6Rm=6)zs z^Iz-V_(aa39El%F90%0GhIM=Q+q<9c{(JYknD@^n*8k+O zuP5rJzCSb9dwMRDe#>kRE%|x$C-fQSeNWGSk}gHZ?fFgAiT*A#U3DB}&TBpR`^$TL zYSzo2obi8f?yb?^i2q!4I+6Ps<~q-xNf()yI^rphX1;hKT8rne(XSKgBdiiVJu9N4 z-tK#t{fc@zI>nP(eR^-CdH*2u{_ch)4@I7#}@xl79v&8U(8zlZcCW`3wYHT!#d9*FLFc{M!|wKDU0`Wk&EQTA*2{G-I|F6L=X z^0={vJN`VKjrJvCG{>Jx%-`o(AHoQHCt8NJjMSGWYnuB#J%^e9KjFMA*~bsD3h;bB zdNR?+99EOwv;SFU|JxFtPxD+r^FFx(ya_csiu3=wNUvZm2z}Bl*Q)SDBG=MLb3NJO z)Qs2GNX_+3W_!r3xy~B^{Hmt*`}_I)DV`1X^n8&g3qPgR$-Q^I&)nXK@71KQGN(fc zn%Al0`WJXI6;_1cUCGl!-UQ%YdeHBTD$yC7@2N$p^POaib*2}N`trX&x-$`{BmW~V zL90Mm0~9fga~e@|{(bC=e@d+B;T%UZKOFfLp_wo0eDCcpYm|@s_YtQ#{}5*aVM}V( zD_Y0>dlR2tl{ouOo|pAL>r-4f^U<;YzV07(Kh^UhYg%%PcSnDw?0<5+S7aAQe%=q^ zRXB}!nBU1`_*bGEZrR^BN^7=$oHK;vQR=VJN0@z@dk?a0!twFHxgOIMRajXs;ni7! z)|0KII*#FCwK>C+A=Umz))4V$oGD!NvE>*sr=w>Q_LrFRduW+rwnV?;xcwr>^KY?k z%W{>K<1a+NHu`yDzNrU)K>sv4kjNcYkzaGh5VrOYSTA~dzRVLT-U#7*Ah|c~=jRc6 zdggfk_w?xKuJWrBX9FkkE#xhV)RoLPnE9ITVK#40jNJFppJ9%Ub6u&mKqaNtfbS*F zM3XhwzI^;wl#cPO&adORX7rInOCIN_|9oP66!*Qvu{#{8pJaw6&p>|n^2+sq&mUfs zXq%4Tn!mqr*;+Grzb3Id9OhGg^r6IAP8g+}#46Gdy*p9!PM+tz&0FBxJag2M|4q#M za89JTucNzKwUOV$?dhrE*<{!{Ix85H@O&%!cb-svlWS$oh~%;LgUtGHw4cu}>%Pmm zHgGkzgmVII%k7l6jq?DN{x!}4!aDG;$NtAyAHJH1);e%2Pudhci8BJ;G-CGu@#XsF zafHuHczMZ;umg|KfP z;OS{k&sv`sJpJ-{K~Ho?&nGy;(Q!9flFkyswLsX0nvtzsB?P7Gfi3ud&)g4NX%1>X zYfMkiXE_H@e|7v9JEC)}1j%wwa+T22GmaHOKCK0sf4_4JbN>%#{l9y;U8ysF<=45t zj{YZ{U+4Vc$S?0}cpI&!=U`5$xD z_a|>R9q)C{-{8^E`N6Y^l3u~{;7YJK+5UW8?k5&SCH?SUrIsY8@vyvmPvjE;B zV|`G}W1Ri#$p32B{l7o*uYCFJL+AEAJ(~O4SF`!7^Yoq`-RB6$t52YGY=3K_e4YE> z{qk1V6+-F^Al%{5^?qo*uJptCe&}sD{)f9jKjY}DJCtG6boWO`|8V60*SkQ;dtDEC zkNnrUA7*~?$}h}*-R~Gc(lx)vBz4E@zk1#0dL?sG=V;;XOuxjlFGcs^y#-x!=vj)+ zEi@W2-f zWFBe7B-^9U^7n2}vOmg`d`BZ$zUoi*m5+(?lYN!uUmC;4TNS)c5#xJq{ON(%O*ir3 zrkm1Z>6p_q`VTHDspOr(MIT-GXf6M%eQ5fO+D}z1uKnnO(%QKn{dDc(kAJ-Ok%fzE z^`3ae-(9e!lKN!lWd`Qm;djAXdUY48t z+>(*`idXi3Ro0-vZz`(9qg|_a>J|L||KoGKXZeYOv}ijiPI~CxwCES4J4W(OCh4Q3 zr%1mc-Em)9^vu_I|8obgJbovN79J#F`y#1{_dw&PqUhUv{^VOJYfltC3IDJ=iv9q< zcR%GS{e^c`$AsSA%g(j^W3lMhB>npX{5z@1?@<2FUj4l+#Lf6-ELuRyCgqcgNLxzJ z|M|l!c(0gr&*!7)Uec{!h@!WU{%`-*O}YKgA0+07q(r_i(!MA7MR8L8*T((%ukbxp z!S|LYqv(UY2=!^w`Uj5w`Dyt7wZ8vbTb}$=-vQ52=08bl%U{04ySiVFqTiF|$GV=l zc`fZC$@hz|^1d_M;?pGQ-#nWZ{iz`>dgb@hqMb`)(ag`rqO8w_@k-WtYGu&p&5SSn ztADuld~>HcYE_6kY)<=P&{J0jPI)45a#dimzDd<#ZJoF-#?+4@@g_6f)Vd?P))O() z#-fjr7QQ(aJw^KY0_>!A(tnZuK)Ou&Z_+ zkh%9iY!C6G-v6{ciR~|s#G_pw7#x$?amhC2F3*Z45kTDGE>eQAjp**N_7RF30={|$t< z+!QU;{uP6I=kR7Y%z7+*iQQl#B>$sKL%up6EnH>24Bm;ZfUkxN_!`0%*0Q{hMe%ZM z^P;F$no-^^Jq!QfZL#RkH=}qldOCh-`K9YfS(H-)vtb7u15cVQkncP!jM13e;SF>S z)H|nl!6Minj)HH5Bj9VH-UGc24uY?N%WbcK1JHU$RDQirEB|~Nq81Y7eL9MxqdiQqWPhc1k(9sSrl_fsxJktEx0R#3 zo1$82+}ouY^XMey4c01=_DT;W zsoq?u{MqmaFoS$^iJMNoe%R8 zY2}k%LQ=cS%xO^V9S=vtF>oX-fd4_z(r zYa>otani>~Dz_P`+=Ik#z<-SRBiI^=msY%VJxSxRlQ_-i`X8|0VcSMra(+v1A*tMr z<~nl?)Oar@zs7g}zen+9*cOpLIo{IqNY4{j43EGW@EJIce5+{BsLkw;*v61gTJ4h_ zfxn1yGdD)@k?1`9((+3W#XlC^7k@r_Fn($IrL#zCcYhd%-RWUnxso0=%^Qh%W>teod3LHeiYaD?M`!Ckyd``R>!pvcNu#Q zamTS8CQe#$()%5^m$-}AM-bPDZ4YtMij%G({fPS4Le1w@@U3t$`OXtJpM1-(m6K0e z`J}rzW^hbgcpd6I;4&Nn&%@WjJWkkjUN8u%p9A4u*bnMBKf)Xhb-eF{-^PE^Tm`qI zXK-S67M4SeTMgWdUdM^IbT!mEzXnvCM7y766d+9SIZI>!@5%D?Xtzr4#cdDcL#7pyUyYyVgO)&?-9poQi&7Z|i zQQeVL^CPMMAHOX$7uNw|gl2e^*OniIu$VB1K3Y3-NNEAVSwIUSGU zE78mFC)XM2HMI3Nlv4?H9yZUM0>6cQ)a~4MX1*SJGK!DImVY}BlRbZ>FO#&toriBD z{~4(E9)fG&ez+4hK<%eBl&AXlem9Em#1AJ##1DSm0~@6t0#U!}Yv_*2-Qcr&B&pnP_F?e?{4wPoggSog z)4mP2!XLpZsO?_~6<+~${48UByp#RqmmlOh7~5RthqSh*^ltj9_~~YWc`PT`S3#`{ zk#!c^TJiIs_Sa%_ra292J57ewa13mQGq|Uyd=tz<^8)@a<3E+le#P;0&6Fs923uP$ z`<0Kc(nmr^M#)uq^G zzdp52N$+&rd3ZPF9EE*g+fXjE;RdMo4}3%5kzrxG?1hStnb+}4?}N%;W3DvY?hg5n z<+0Dx&bl{-_GZFci0{O%am*XeT);mR_Ct?<6Td}(9t(dC+pw!W`^??u4)b7sD7VqP zV4i`>mwr$1ciVo$Y#tH(Q_Trb<2e$(LG2n5HDwpjHjbAgunidz)k^bkyL2{5Q~7og$}nGNP{bDO!!oNtad^UZ9t znKrAuo#tk9EmS+^TNj%X&9UZmx9^mB*sL_y+!xAU1hu^ejtY9MxeRK1pRhgz71v;n z;vT2QeW|&~oNtzx)6K@wA$~kmzj#SG!K?VCFPJUn0khuRX>KvA&Gf?1uFkgxo`o8p z<7PeN9@WAQ~kS zA>UQ(YHx?R)7)Y%G3T0-%^Bp^{2vFk{R+(?MWMXDP}}|NgHcod7VbM0NAZpaIWK-N zs+HDpLHaVU8;nAa`!MIhr1pp`Ye>c945B!+e3Q~nWv%pGw7+d!A zRJqa@9uDP>#eeBxelzCbRJqbEB=vheR6mxPi)+}bLz0EufWp6N-e;|xQ-2|>T zur2;TY8<4e;MaJb#6KN90e^CQrALx9zFFpy4~O#0pzOugBg|ZLfZ50FEDrfDo9E1C zbBQ_MoNZ1qi_Br>`45Hij+sZyHD;MP$h1~dyHkX*Q%_4J<**PnedkJb? z*>AnY++eOU7nl=ZI`Ly?MNJ>#eDjWhQG7hM(X*mjX{|HTBORY>Zt?c3gSsBu2X+2+ z$!vw%502V@-Rv`mdrQRSLd6e<%0JqA&__Z)I?x)gQ)a8V#$4sNWoCmpq$K3aHv5_B zW|!k;Ssyd=J{t1nngh*Z^GMQP8shq!ecc}H2_mtm_YO_e8I zj9=I9H}KCz&%&R)o|m4Ae-{22?VgUFj9>aD+9N%Yl*aZLWA1W0*3l1@(?UNsV5_1Z z$#SKeNowbDsP>$|*qs3X}!&Q1JwPWrBL@lxKEnMS8UFN%0JP} zhbm{7{oJ=r_%p4K(ti05J{HDnGuN+&u{A!H8ZYS)9}D?-&YP&O+vQ%FAM(wc#d!&~ zi}O?Yq^FjJd<9Vb8wQWj?i{Fk`=|Gq;!<%?fj9QZEegIZ)%5302R<1)-g1q4a5}_G~fNL0u=WggUR7y&&|b zYep0=!8UV2sz1{CB;~*HcwqD6QB&iu(xMBG^IQ(wp~s_IX=1iZ&vRU^xx?etzyuFZKVk7U z2G!17bAavrta&Lu(XMNY1KSpd`{G5sirAs@_G*LcJF!avg-NY+0&a>3NQu303Y{v(0QZTg-`{3H1zv ziqC}_$8769W*70QzY4AGv()z4Q0GH+upN89<)MF<(Q5w*sC-906WYE09Z~!!wu7HZ zwOhKKe2PB`HC}a4`9^;>*z=+4&4FrXfAgB-hO7wnuebd$T5&s8L`|o7ATcZ_iq~P= zydtWVjeaz?|%^)hyqJM0UAQ_M+F*WGp2o4>$&1k{sz zC(nPdt^We=5x8FIa>t#8s;}Y+*8_FGq!0W(_D!pKzYRSb>N>pZi-B99+R@^C7tQlf z?HE_(c2-4A_0+p;0MFsE4X%o6rPY7w9LM!B=R>t;%$ksY*OP$@tk;>e9YmSB* zk6ftnx?UYcZ-Vtu+o=RyO)4UGV?qh3%zu7#rmi?3ZH@$-QEwJrh%l_&1NLQ2Y zCf{)4%CQ&r{93Sgtq<*8V$L>)L**-T+*Y$1s=fXH zJ@{kh)eS+nnXP6${2le}fSKf*x*=-H;Ju9c%qTts+r$k~t+d)JJ%;p3;zmN%p9l5+ zOqTU^x8uy$!f|Fa{XUQF^w(0y8R-GrL;g(j`nK?#>&mw9eE#xL-q*l(aa(vkPhH!k zPm)ycA#*c)3-xaxUn9?_a(>2p71-92Pg?n;mpFbd)bq4CuBY;++{ec@t5-eJGaO%N zjxvXtxlqq#vMA>n>iIJD=3whjInt_EI@576;=YajDdIA)b$v6cl~$be^>2pqE`Kv> zdK&w;iMxjF0&&uclRix1^P{`X&E`t->Aem%L%a&xa`GkL^N?QZxLL&M_#F-5eMxLH zh)W*NrHdRl(#$p^=bJ^obZlK)Q~9JXZw>A0Fi)5*=00<;xy@W_E;mcIMoq0B;{C=S za@@sMOg+--zw}s=jvIMU>w90=1~Z_><=WFcr~F_nI>7r)T~G6yolo7EGl_{da%tVPC8K!daUERwuJa?=4!Ll9Bby9SH2PAkDJrX(Pq{+qNW!5v-40C z&&4+28&R#a>Xp8{Ipp7O?lzZi4%?Uav*MN57H>{%U+LkFo?b$Bh0#u!9Us@YA*FUGZkw6Y1t9t>dc+yT&VNhF;Mex z10|%=gjQM(l`cr8OSXySImOHg6C8I`G;kz75;P?WulAS2}K~S!NcQmv@G8 zE}G}e^=9=>-Zx>MU25h&Dz>Vfyl>)pC%uHE=Wy9j>v{~PF^+ZL4y=Lu*$+3vAHucY zj+!QXBNpxcYZTvzZOyl%T50lZmtINIx;Y=JoKoVyOnt9!;XN*FbBLE#y!2GZO(IV1 zDj;qOw(-Oz+bKQTaU;!PQ159Df_m@qQcbAu0@QiiIkVL~3KQ2MW&_l9=Q{i6!TZp& zpxQqPY95Y;>c@zhu%BN12j>sihS!AsRQ-@1>bODXK;oCspV>d*{Yh;7h?iEp^o4JQ zcAkYQ|G0U`_H9u0ueH70EQZ>@W_~N|U+I)T8{716rS>oB$&Mdyj)m%1U-I498jH@- zkAc`S$S19KNyi*N|2v^wbIcj$Bs0$(w=2YrG_%cv_HX-67`G)iqWDg1o4%78H|ceb zYj?h*=0iA<8*icPKMus^aYoD zELq=oL%CT{*9n={G4oPgu(v_&?>nI8^%AIgJ^^ZfD}u^j0Cjya#P&hv0JAUDb;u>! zqI`4fL%umsy3ow658Ju(&s+y%8&sd#&eHuHcgF2JY3?>RL+$UYtSijvFme53y(1p# zU1OF)^>eEAP^k81+n!;bb^XoeL35v3Z64Vh%HL~_F#AH)llN@!4>hyQK4!_m;Gc0Y ztm~{X@!8m>9Zaq3(o-Ba&KzToFo&2qQ0rOe4+Bp^J)doX8vl*v2&ndDLv8Pt1Hs>D z?lyOt>&!Lg(gU1l^2M0Zg;9J3w#5fH&qPzlcIk5btI+BAm!r$@OUo}kiKO<7A#MWp z7;)pUjV4Z7ani#bHvlHqBjO+BxcG2=6z`8MgLrAhOLzSslzZ(5VgDN15yfv{yYhq7 z{w3Y+xFf{z*ZiV(#=QmGLE@zOw_UoNr2W3k@w3gTQqxB|V6w z`dYph>f=4(__6QtKGpY9anf7t-;aL>dSfrY^g5EtS!K>NC!6EUK~T^A22kF1_OmCx z&wIz%`ca;=_B-ix*EfUfybN@AL#jQ}Z4IHmRAR58P+QwuyYwDpz`g z<0^^M_BloQtFSHaRlf8TlFmo=dtGUOS_gMM8}ik^lJ7ZS+wp9wUD9hEUu-U5-`Dz4 z3SU9~8Bq7Lr$CL@1aqu894da0+1Ko2>Mz74)+4V=*UZc21@oNQZk{w-&7El1aqjFW!`YV&zmRBd51$g z#+Y5tMNJo2?@o^7dt2D9KNr`PvDo9U;4Pp|7%)Qj6VZ?ROO@Pmu|*iPJJt>|04Ar#4jzs zbRCJ$kDhuyoL5ye2R*|~|8cO_qjlcJ`FbLLs5#iYMx4qy3$@;!wmuHEA0M=?Hze3UwSCVVwtczH+%W#2q&KLEQ&A_Vd7fP~)%_Y8*B~^}E8H3-6$u*+1v|l5fMa zfaizUX8fG*OG>j}OHXrrj=Ar6C}+1h#hhT~npq}4`Io4-`DbB!RzS65o>^>rfpt36 zIGs8c;toOeYcEXn2dY1n_SgM1#9j1$(*_m4$ak?lSo+(~0B$M9$-~UgW&v#Z>>K zOG(N%6>9$|vTiYJ%q`|BGp9Z5Fa4qRuXLz#&e%WRy7KqIKE@nv4l=XM1sx%7f;p@s zoPS>C{^JO2LpoCDpVIsOE5z?MYoO-$I;eRt-1Z#XyUzuCJ5)P&nblC+Yc*8df6x^{%yEX|Aw+5!7>}sj!>zI(Rf32nLbbR2 zd>F5e(@}gWwgu-?<0W0<_#uuP{bCd!hAp>OoOB<@4ZRTB*G2s*|ME+r{Q1A;xdFBd zFQv+tUO~LJ|59^-IoB*UXPQN3w|UJxXPz*d&4Xr*Ip$)hFCV_h_%!?>=$U^BoC0;6 zod|V)wCze1Jpk8V3H@kp<-RGlwO3O8kX}hreEFXPS6&X~mqPV#2GsF$9Mtw30yRGd zn%#d2_dTvb#h-U#B=ZshW81#NP7W?i$ zhJJB8iPvG<`Nvehq$^2k&vK}7seo$NXxoo4j@r%*9@i>!xw(XKlz+a*_o&$j)$SeU znd_mR(@^!Sw4P%Qz8>b~joK(a6x*Qdsd*_q=UN!Q2~hbj|92SwHuDHnKN_LNV=2`3 znr8bXbCj87c3utnPMKr=7Uoy~zlCv|#PflH*!uo0HEz;d9XH=`SGdo+09#3~IO#z* zLiy+TtoDtzE-=f@d1i?@)$ITGkgvnK%{*i_nmf%+=2~;LIjA#i*Nc>=?X}tE^8JHE zyXKlZiBmgwIDU)u8gsSnORN`}^UPBFr$f~<#`ZJjY5R{`w?M`1w=U=k_2-%E{tSJ-~(KZ@eBuubbqZ9nPBB=xiJKLhz$>4fgWuJX=7 zmDlESRvwAsr?DODRgQEWN#ztf|1@(7R5?Y~!^}E!15`V!{u$cY`g|0x#<;zxfhzYpcGY_oN*}Qe-C zyLGGewzRaSqAjs#Bfkr=6Wf-wv|4G(+Ah5bzwZAu{$~`gL9fFv9m6j@!~S%hr_Mr8 z>*bdokALjbv54og@k!`$_@!08^cei3Xfw-bd?I=jerf(~mo6ZwUxSI;RKf41eS-T9 z*ai_Nt#YKZ92dDgGiXl+wyr4EUg^u^P%AIm}6aT0aX4W>0vvJ;<5_gdIbdX*!6o}}$r=6uu54wrY*`nY-2 zJZ#pPyP?{>wNGgG{{7s)#kRRms@>8X9lsvxxVjqZ`}vhn-_KtLdA(@iwT#fN%Vvjp z);wt*gSszpC?l=u$}?#Z&x_;D*cvm^YNa&~q#GQ+%d9c0Aan82V#u^wI1}=^5Wnxl zyuOY1cewvQ9ot08lkVYrb<*QV8n*&-DEv10`jT(gD|r8n=Mn?3^&y|M@<~Ue9mI9s z65`w7m(WL{en(*w8D?Z2y*1Rk1IoV{>N!reb(QtEp5J$ru>QT0a{96#`FXzd=~tvh zXV^YFU}D^E3*&UYUuf5^+~UA+){IH|4{!Jc$R+jhx)$6N&6?=9{dx`u~7447}WiSEZfhz zoMTY?=T@lgvc7+456@rY8?mkJpK6cvDw6uYiE@;01ysKB+e5zd{C>s~Y-P8n@=4c| zly8q&W0njE_B=BOs@yC1Rc?pNT}-(bu$}Eyu5`Q0IZmA3H=DdRil4xClsIYX+%A2{ zaYtOwK3KzethZicE-~|8721_+cH4dfQtZNZ>)rNmH76(I&8y~N^T5DRZoRq9tTLCI zIp+8~Li}j6-S$~`gz@H&48)7^&A1~q-qH<@uZJ4X-PT)SVmmv3^MA0Nv90ZuUwVz> zE6pzRn%VCB%gKKh+o@jprCS`gHY>D$mAS%P2Gy<#sC9dR?ImWh{nMb@J0UCdcOdmm z!d8@(>aX-j`-kBljULgsCfhT!L%r$d5HrUdV~#Qx zygJ0sH>aCZ%?VJ)`HC6I?9OtFuV8N@?YNd5Nmd+<>JO`TTW@KJ>edo=i*^ItRj-4)u=$6P)nlvipN zL$z~;^;GML=18+IR6Q-P3*$9q1@BS5j`4b3YP_Vk*}oKj4SGv2zw|o$tMG3?SNHNu zSJ=N3{}S|~UViCf`w!qRLC@;tmmXz*2mV5IelNfDAp5)V=c2QE`K9}iG#=Lm2c9qw z4-WmF`8m!5vF#t6>bLYx$89y&L5Yg6r(K5Ks={tk3|FTZrF{gd#wp^x?Q zOCPa+2L2ZGp60Xt+YD9iI;e6NJKq-aRbpGvE1&d4`%mDXj2_p^FI`Adx%p7#4uC56 z>T5!Ka#r%ET(DhuO{zW8`(G2{Y8wI)f4bSh< zgYYNMPo?{i)UGo*A#NFQ=W-a2oK&3j5t8B>99KhJBep%g;-t4auF`R*h+BniX|Fix z*^Zk?TqOsDk?gONv5hBAn!2`2Z@MeA>k!vdTUe7e+?8sV^jxn~(;e4mXB3}_ZE~+T z=^b8|Hk(Jx1Lj%tl-ct7(BA`QJ=FcJ%~1D!R@uJXoc;RH&hDq9_#AB0U!Q8H^mvli z@lo)<;Bc5vIl1Ip%5}%IcX3^WEt`DO>c8{=lE(cy)Vg2xhM?y`-A|fiJ=)ARyN8Cj zlS4zhR&L>bAGX$^sdh=%JHEzT^@b4N#(kbDY%AW7ikBW-5Xv1?kd}Cl?(JilZ`cMF zq`mweopgW4WfJ#s`txDp`e92aPFnqw=EhK>e_d}5*LBz5oYpiC|9s**v0Z(0TCKF= zr7x2-9vx=8*=8OykC+F{YN+ogEj1(Rsp1591^1!)V7oCQtyWs~NS_*!)>QEGo1$sk z_b}sQ2rx-4l4i++%j;hxlf* zJU^6wp5JX;f~_n+Rlf8z#}z=8KahB}k9Vr$+1UCKpKPymDl-v#BYkua=ul9o{3*t+d+Cd{{D;j-Qo$%JM$LRhlA1%LhdtO@N{mS}0?r&DaqNU8!Mr?cXxW9>3J<>Dr ztK8yW&`$Jp{KQJTQ~irKMF;r3&@0%^ z-knw}t#(Q8z@IVrrfAj;-pfO8#V@V)NN>hJkoL`+%=G|zJ$`BVrI(OY-*B^^d1@H- z{^_RZcr*76hOyrdqh7S?m2Snq?RPgthq#Z^j&8v(Ex+_OlJ=d>W6eYDUJFzvyNze zU1wIY?x?)hbv%c_wu*HpS-$jglFDCf?lec=8`jnSQ0x3bm$Qj-ju5lIS2@xLh*LRx z%^l`+Gd40D|F2u0HAi7rz8rIkS!I@+t>zB%vU$#&bzdlFh*@oxyfxUTL*0KGVSRmc z(B)9q7xS!Vnw@V6`F23%TWh@(>iS{2bqwnG(=jT<9fRsmq4g@)chGDwx0oyM57#A2 zpz;W+Bvh0yw}I2#!b5F!Qem6 z`RZEota>ozm#%bq{fk0<*Bn2W_#61H^op0x9Ut0}2{j(+*1I1H?J0$_7d;flyKN5l zJ+Ku%lp1g8)#KeRuCvxs#)|R1+J#=`^2^OusQKOk@1@^|pvJ8c>OJN@Zx8i$qE&x~ z%U?|S7qFe_Rlf9M$Imm1q4uw7Z)ZJx2kSfg*Gz1a-p+c6*7dve1jmnsIzP)NUh7Og z^%P*sBR;wANDsuX`+4d7j!!naAAV^{+%8>D(tV`eQ0-oCE_b=@pXE9P+tOa;N_S5P z_v??F_2xRWd_t&q*N3o_94{vBZ)n?J*SJ@T!6M`|3U z*N`+mOUyZr?PG4PVv zGBJ$j6n=-N72A=CsqvIBEjc2({id zTJL~b?>0h}Q)PR(Imhj}LAi6W&Fa-2=^2jeo*c&Int2(jo)b{zZ?b)vxftGpeFD_D zjD&y-295dH! zTo~eZndRo(1>yX1!{fm}*=#8bdQMsB$8~-mX&$zjWvPBhU;J2zJ7YGOd1ktKaef%j zJgD}rnin|FJpO3VHReXMU~aGvGwUA-y2w0U8qQz&ov8SUQr551)cLFQjE{!+(?Ox&Pto6zS;U5Vv+(VCB@b=%37+=}_Byu$f`Dz9-msm?O<}Giyp%5Bosnzr>so z$5sRmfqL(8pgH%GVZP6TI&Z989CSI9-sXG_pAPwVE(!VjK$Y9REO6NJ!1NW4`+SI7 z@%eB)HK>I5>9H;QeCm2idK5|5Y1b>$62HfNs4`rib+BKyU^`Hmx;~TMNK*Urpz^hS zF3hvahqzw*9Bbw0Qu9oD9e!PxZF(>F*U{DZlhd~>=v-fUkP%B?o1uL}Cy7efEGelf7$6Tx1;I_Q!oxF5j%!V|8lVJF%N$|=#A!BvyZuS zWAI=5_rPW5kPYE_EOSHHUX$I}8-^|GsnmWaeFDGE zb64KYeMa1zDiulPOd_&RhI{^Wipy?k@1zrvhuPBO=t=b(9)bZGarE#bYelTiK3H)Bx8@mBJSoA!p|?P{pw`ZB2FZ5dR)DNyH8Mb;zC zn0YxK{O6$J55~iIY`%@(X~ecao*ED7eIy;JvKkRn4D|$pPzw{uI%J2Se=+6zP@-La^pxSZ3+++LZ?}mC0Qtno48^4>X zS9%pmi=q}?=wWUcbomc7vkocbId*F))T>>4fQ>i$a?iJ!v0+j z)vvkMMb>9q!@OvO+MlOD#TA%!KM(ES{TF_J@aJjK?w^PD6SG~qn52A1j|aB>EU@cX z;Phi5e;RXj)U=%2+g-_ns~v<-YRKv|4Fh z&q%lYB=~3YKGpG`a9#D2lwW!zN#$e{r}d?X`=2@31`sE${zzA}g#M2;vs==dW^qAR z_yY0R2DYTtN~>P!<3A4ZhkqRItB#w+eSK^Pf1J9nD&63?rRD<1^SjUSa%}T^#Y@j| zT%MUuyy~5DlJ~l>MZ_oDA$_Vj_?O~uZ{~WeIpvq0OwxJBShM{{q1~H*#Qo<@{O;W^ znXlM3{)qd}X!TEeg5z?{^+!Vdur{u*k8oT(l8TpJMAH5<%W-pvn}cmyuQ=%)&!;t= zeTwZ#dv`w1J&5PiYNb`L^sd8UdsUeW4s#!UF~2Jn=RO3sd55`=j#j*M>vN&r-DV-w zdVl0l;0&mCrJE)H8SeX>Js9jO%$ZR8NpvvWmv4L%JKWDa@4dxniiaF5i+Rybo+ketIp8I0Ev7hUC?}ySS@NZkn z-=X^<_f7V5zJ^~~<0IXOzX)B4{{XrHzqI_)b4hA%v6*gmHU;|?^N_jItTfBa+2&Mp zteI~PHe*ek7rb~=R5OJA8Cz!~=LKk5v|ajoW2pCxdBWUaR+)>;x#o1UpLy;3p`0P` zMYc=-?}z&@8GqnC25f!5AMU?s9Hh(kh5e-vYCIZ#8JO7?c*DBYEdN!omzn*|Ota-= z@Gmi^nHgsH3&DTQY=*y}oqM6aC%wbmWG;qk*CKPid4={V-&v@9t>zK45$d?G2`c|I z>%OPLaVrL8zd*Y+Z;nG9*Ya&&WiBZeO$0_EPJa=2UZ{InLaC zI^>^WW}2P$UpCL1ZRTOK&fI8Lo7Y{=NvL@_`!}JU)$QTy)qc_Xt}1Vci+tv*vpB^4FsHK5Vqvg5V_x&!U%9U=o9Q^!FK)jLm@41}vOBY@X*MFP;JKP_*{LfJCdGjn(yIQRG znf2z{e}?j#pXYdpZOuPZ-|NSg(I-|bt$8iobu+(hNZh5HV@+Sd{te=;V7qX0tX5ia(#<4oj~a75@j18h zdo4FH53sEzURv?e)A4V*g};NO=V9on_@(8S9*bY=U&%t&D|8|L3&@>Pn#`f z6>ZmetT5NnPo3Ad@V>zYY}NELd7dwwPTkty&+=LO_hH9xAif3LfnM>_!!u%u_euKI zvj1oB`_vh+#QP+S!FK5!lE$O))(}_u9sX_%{cpH66(_xmq_|U=p?!<@@mw)87M;jU zwNLu+ZM2bgHQp9$dX{njOEG`{72Dq1Vzts5H|dRcgz_rx2<3I~{`XRB3+_mjCtc#W zqJbfP;J^?+;TfJMV(ULJ6)%0_Rl&a+|H)UyqT{bh`K7A{gmNm)`B39H+j@*S((F4R zlsB30F$}<#F(6f*bj$6byaTs~xGlsT!q#|uDo%Qr{dM^3&^5jM(p4mlZ@J?-h+B%S ztXG`$Nc)G@^ZqV6zn5Qn07>P<%#Qw{U5kmo(4XI>?4N3vbQ?+WYs^fun{6cfCAOpX zzcQ|0u422uc1-S%(skZG*>{EQo_SY@pR$wRo0ILXRJ`={LBU^&zjIJ5x;iN3m!3#c zy`zbHhW+L7>AdHFZ6tBh+JB@6kTh>DzBt$Z%(s4*W4NEIm&*&9^2|W zQ}sw!l2p%PvpFloujBg!$Flf4>shII={l0)H$a^S6%9v<@Teq-Qrv)tUA7wm`b z4xD99F^9o_(vO;9!N0_u^M;^nynk&rtA>XD9pA#d!?tp0s(;c4M}={zhuSW?&5hS^(2iJgY*T_^p z>9hBS_2Gnh#B4NI-y8Cu_zKs5*jC<~$}hcwr2dteW6Z&3mf6R=UJ&9hn5SUkJlh;& z`$#jxY-j(}_TK;I(4H+{<#>p#;mxV`NDqHYEb-pb5UB6BX1pcDPpjtdoM4N+B^56{ zm!$TeF(-}=dJI&3S#J%xW^^p^y8!DR z(&tF}-R)!M)cZreJoCr{LGLt6&B12(*x)~I4mWen%Wn(*b7t||Vomzu_m(-lcZhA) z+hVoS8ZYUCV?umiv+MrQ{@G9PciFMsxIZ;M(z6~6@srKb<_I%pc8&}Etby8o)lmD_ zVyJN{Hg7x->MQvIzspY_uRV~ePx_+!UH)K*JO6o}+fql_gQ+;_c_h`d)p7fY+ktIU zuQ=&gQ8k3V1i=PALlY_a%NBwuwcl`lXk=J@l*8JTN}! zWe){THFvt4y_LMjOuntX%8}kc()e7O5V&+=sP_!-A+4Agiz+6j>XlwZQaekb@{Mx* zP~Lwk#8%KNUV5P8I^PlE&zjBe2=%Nd-%)Ib-;t_Edbi_dnj;-Ql=sdGvE}!Qm(FtB zx`)H~<-<2Kj#*~+v{>T4QwvnP8=%Iy6zYA)5w>STZP#<}4RO`xQggOB2`X-kb&lE3 z?40WUn#au}<{qedxe4m}X3f-C(}IQk9n)OSFR`tf8mpDoypgUXCH7-;vYBIEeNQa$ zUgR*&Z?C_H^RV~C67NMSzjVix(9gChv8KM8xdwg@*ZbI7r^ITd6(@a+bPw%mChlX@ z{|(+NIg0Htang#D-s8Bf#65!j2gKE2+f1Ca;-ojaoagcHK(Fsrj`SRo`ZW=%-f_f# zg#35Dj_Y4+V~CeldD6p4+HQlPw%dt!hx`rZns;;kyp{doeH@>$t$sJx&uHbBE^^!; z;?(ccQ#pUbHjudFI7nwYu6=SSfBobzzN_EQbv?G~$*J*`p5eIRQ1hdob?3W6{AwR{JjWlMdXuKf22n_Zm5}Uc1;iE?VcX;m$BdO#kOO5D!=r4$4xgUnIp_$=9!0M ziSH9{;Qn0)Ys2Y>V~Ot*clYpjs?p6PwZGoHHY04$4k&w@^#QZNtTT7PyBMdBRV>$B@+C0&|$Tm>Aj1%sJ)^bD(+I@#oBgQ2XC%>!oJR2SRz9q23eNV7wO;z+hqk*{&J{%)2$=(+U#Jj zfI43(ff~2T@HeUlDu2HH*-+&~P;p(Z_mp|e<(@XLz~2$y1uww<#oV(a-%!|tK3p8; z^M<+H@56SmI5nT8_mMRJcRQ|*xH@b*d&Nmtk<`u-bNQUm|A|ocOtb65LD!qr<|4Di z9BO8m-7YuxBeCcWw1417Voe>7FkjQ7_#kZkJ`$^y*8VJA@A~pfLOTk~!ygUzlMA8R zbs4+3#awBYnX}BgM`DTRI!hntdWw2>J`#KRxsG&aX(;z_X^1Q3{lcTz_LrvOq^swK z_LM=@JJB3#jx>jwS!SjgL2dVa)-~oKsCDGB*fD=PvVHSiya2Dly` zhZXSGa5g*&r&y1MS_k?;m0SFH;0$w;ISi`2tx)CnWyg35Y6l@-dXfvQ=bLlQ60_Kx zWzI0CnN!S3<^;3I9BUSuqs#&`-^??InuE<8Gus?!_BYip^(Vtr$9ng##=6?9GFO?) z&86mIvmV|`xqHk5W~14V)KsSW8q9igkGadNF}IkT%njx`v)ZgOCz%t>B6F-+XpS=T z%{+6cIoQlGv(5fyUo*o@H`O`*OYfq;;wiJuY&DOWE#{G=cK##gA@hLQ2H9rmt>!Va zgQZONcC*c7El${vmL&a-X0|!d>~He7DiU%0Etdqj)=Drk zyIk%Kb1`=QOD{JUnDfoKW{FvB&N641)66O6By)mUWb&K5iTbz}OptS%1bOzDAir^t zV4hhCH9kwt4dyzt+N?5nnKkA%bBnpjJYY7O4Q9Q$$80r^nJwlK^N@ML>@d%o?dB=7 z&D74Resx*jFt3?c%uA-$J3f*tihdT0`f7cY*19O2XFb@u(7M2Sl68^wEbD33^Q}v) zms*!wS6NqDXD1rNdldY(U(H z+v(WXeJ1EhpADS1lHX5`xW8mxf!WIc1b?p+PFlm?{Dk#i=5JWTmam3-i@wI+%0>78 zPAF&MZrQod2K8>hwEy6@yx~C>`b@aAKEz#O!B;txo(~-LLa<+K=QoTQ>C7|yE;20t zU8r{*zhAEYwZ0Veq(6uF5`OPl{Xd@|_43=z>i4uv-j#rd`q4I6a(mFNg93Nn#dkR< zf7R=Pt{M_pG>mse6hFecfbUSCciqoBY%t>;{6+@MerNFae|ONQrt;1z_L_$k$Mc~N zrbVxWQ$Ivm)N{C0@w|UOm-oowwnZV|jL!y^eNN;&*KGKFsBiC+Y0+)iNAvv!vG3Xt zHydhu?T5F(K3@rX5tN?K0k4quta>WMPx~fqMsJIUaxXN5dMkg!yD+l&68rPsZU>mu4+#(h6+$Jyh#rvcA$9i13wu45AW8|TLA$9&GmwBO9<{7B_A zb7IjiErY!|ihkQikK^cW16Pvpjndmbm+5yuX@rIruit4}tSJ?*$ifrr!p=gERfU=zPwl;Cnb{ zq~SfXoVS5poX>!lavnd5vE`g?;404FT+7%h&Y|n@-Vn})>lyn6=W_5y&TDR9>@m)J z!B25MCNlPH+&&ZU3*p=X{tf3N;Fma`0Kdk0QWoAz#@PmL;`}oBUCw*K`#2v2w{SiJ zKEydA8}B*dTnPR@oHv4xa^431l5->YADm_Izd5Il$NL31YjYUuCyb5cJRUrTvjKb!=jq_wPn_$)f9Cu?_z35z4`JRJcLV;Ea{&Bz z&P6}RI}123eweYZIs3uia-Ot~u^?vyIK)}Ifw8lkE#UK<7l9+3-v?{bWA)AO2-feM zcmEQ0oR5M>b3Ox3=RBtl?>FFVc?|Ch;=E`R-si)44R{jgZD1qk7Vs3#7r;N{9D1BF z8|Qx`}A{K*@PJ<7Qq{5a>vop?_rXZzwI*roZRh0)B_{kru}Ga`qm;`?@(V{xiexqQ>$v{vaN4;=Bm_ z3FmEx8EfTi`3UbBgxwHrGljrOOU(MMM&fv_#jAe3O1fIaTP-g5#>jy z^LCu4USQ11x%?tyw{rFlFm^lV3t$IldUwLiIIHoz9p^FF*jd2&A@Cy3VuHZ#=Ntep z;p|8h*aMuaz~!8ENdjBR*$-aLS&Mbe&p0mvdpYj_KN5F80_Wp7yRq(hn)AV{@cWFM zw~ZCp^PK7TZeQf=1^<53$d5j6`InIUP&pA86$2r%7|H=6T_#4h+%mO>fxg6ZZc_a8V=a<1U=h|EF+yUo0 zuxebaj}Jjn zfi0X{z|%Na-HzWS#c@Fq7&RT4uKE-(q*2B+oE(O z=fFxl55w76EwI-(*RH~IBXKutaU+p)(a-QacHGTF0^7%V5!TKvoIe2{;+*<0o^R*e zvJTIka6SV*%DH1bp3~x7wE@42#M!w~VE>N0c?8eXaJKzYV4a*>z`dLs>jW0&Y`|Lm z0_QDY;o4Xo+x9q~N#ZO%A+QwA)4@85xcyuB{TI%SZwu@`&ZX~Q zZ-es*a2e+g>@6(goVrI~m7FucwVdm~YdIeUKg@a3X9C;6c_+Aza|`%M&f-x#_r!Vc z-v#z-&gsYS+g6+n;O(5ZfnVjk8~i5c6W~V9mM;aihqD{}N6s%F7g#fAT^pWv=G=gN zlMgu;{R7Xna6StDjI-w7cwU&Z1N;@|HQ;}7{shm6eaATj?%-VhoxplH)AM3|oax!H ze$MQ)K$~yTeH9Bhf%8UiGH1sb>>I`H!DBenyWFqgOz$JUo-@50IGZ!QM_A99-Z^{| z=ObY}=goPcEU;TRYtG?)Gn^NL^Ee*^OL6xD0-MdbT!sBX&Rei?e;4Py;2(3YO;oXB z&Um(jm2%z<_HfP^hI1mE=~Ht;LV(O zT!nK+ocDrX;5-R8AsRRrf?tWdzX9jVI3ES?;#`EA7rQyT!S8V{zZv_Zoa@1V=FF@( z$H&VQrl{E8ITwLXaK<@M_BH21@VA`LfP_Nd%XTJmIfjDalaPE$C zqoiU+&f9QSW(wza>^J_9GrLR0Y@9Q|1)SaBS)Az%%3RI|@4-1L&N}Q@-phFs_$QpF zf=f6b0lPWBe=lzC#_e&|p_;QF{8P?!7UCh!XTa+?YZv3380RtI$2m_0`#5)if5o{0 zXA8D+rt<~Aru$JNQ4GW$>vuFH^B@&gIw(K0~akV@JW~h;fI7-kUSP znSL8seSOTHeh*j6nSRT6IA{9(sZpHi-DFpDrsvo)IMXw{nVjkO3np-;XYp_3+yJKi zO-jS7U@Pale~$A?oX7q`#ct;QKkh3SPq5 zvQfnz;Cui~d#se6qDNG0CFeUI#d%!LbAG8}KjS>B4(B#G7vje2Bb+5{aBt%5*rH-j zbGFyx%mQaG_<7FsI}|T+rr(D69cMaMy@NBIU3`nP6Z|&kD)1jT*MZ;XyaoIL=SJ{h z&IiFCb3O+46DMFF^aVV}%2@;-Cr)CFerx`poI~JmI8WN9VkbFUz+If_oqDG^)BEpa z&h#4&7dg}Kd8lrPh3|e5&v|gB_ui*+UIR|!96j&JS%&?!oVCAIF_CjRIEV8ja4u&X z_-4)v!4}Tt;AzCz*Qaxew-Kizzu4 z>z86*9aA7mgCA@B49@TO;yw%KZSA;k!np-|GD|pnKSUZh2fkwrx6PvA>^_fut^(i9`4ey{=VM6cD$YkoVc&yuJ1T>ZGkXVnvz#s9M$YeJ zKjeMRN5%{6ubdys5!lz9JCL5iMZ zDD$~-MmQy$bqMFDoDU+LI?gs|_X6isXt#^=1(bO+=iMluPvdT&%fC2RL5p6_YjpU1 zEzS)n^Q2)so!BGI;5>dQ?p1M4e~qy_IUBZPpP#c6ZFUvsBX43)o^#+W?6-6FHezp+ z^EWQs`vap%M*se$U{t|N_8AH`D|n%TD;2z6!M|4U+X_CQ;NuDoDL5HpT0CtN6ioMw zL2jjX?!8QfYQ?OgX4=ear3Vuz&bl*CjmroSj zq2NS}dvQ0p3YHY?R`4bTZ&mP41ve}BO9l5U_!^9{@pugio~vM&f@>7KMZs?=c&~y# zQt*Ei98vJ-;e%g5OZ^+Y0`pf)6P8V+DVv;QuJNL&3cY?pLsS z)LlOS<1#eaGOA6krV49N$@!x^}PW*S_zZ?H_zPJbfz4$+k|1UnyAgy=x9vt?T=i zWve|UW#6-&S+TV8dzN#`DjukHU%`5HS^1T1uaJuWnyH1~E1{V+c_p=;)t9AiX3c_f zPpPNkfuT{(sVrGO)TYR_s^&7kMdhxwLmka8TT!{X%(0;8O4ib%E7{KRR9qHQERY3j zD@umC=T*TJtr(YI`u|aX0acAF7Zfi27xk4_E-!an`(75w?h4|=`toeU>icXlj|rKadE?w!6=RxI_z z>*J;GMYYv~PKFdUoW#B>ni=ede!Ckv8*Kcze0OE}sul5+&aCjnb9%?B8c&HL6VdN; zDqW>Kc4a##Dqr=0r$XU4W-&DKn4Kbo`RLNBOBKFi7MHTYBf891k)2Cdu54GeDxMdG zLs;Gkfro^x$aTym)ErW>muzQNTps9xT32;Engy;ERpn**)n$X#EM}$1W6T11Z34D)TE>R8>}#RUpuc(mTu6pn43opIK2;>#8Uz zb9id1Drqpe^5r|retPLr#p<$ZbV`@|;MPb@ImKFDw#L3{=~5~M9wc{w92QkqRv`>@ zPeU(VAr{`@4Rr_gE(?OnAisPt1N0pc%_y&2;wq0-v1kz7{tCVo$-2z_+^VvQdpx!7 zd{=q-5?9G`w1-P!%`bD67QwEp_L6O7^$J(5A~f!L?y6d}*SpZE@wyfbLupH6MAULY zSq=4z-w%UdpgzLmD)&4Xmy6q@SmM(OWjNn2ElNdRX=%I^=6Gsq%PKA@MOP{A_{hRj z6}KL$9oc>_J!Cn*tfF*Ckd%xo1bOAuAq0dG&t$$t^&4rTX-2eBU$TkM*kIwoRI0MV zRlPReUh}2Gg$s-BKxw)jC_{epR@J)E6g(xa*qn3d^(x3*%I7gduH;u%tzA%79ZO6p z4~`WNbrbDq=a;QqRaS#GHsl&|Scqy;RxNqT%1iHdm9K(s`O=+bwLh(_ULFm7Ed*Er zIo2Se+FH!~P@CXl)ruu$)q}Z-eMd1|3WKU2?_Oe+KVMQDC_DLBQIXlkX(YAPQ^ zqAzzrwO(3S6z#N>{*eS!;@VZwR1SJ7bk#)5FK@NWQ|?+qeWTJBwWFan8kQFih2I3iaC|kD3pN=sV;P(yv#-27BJ=-K^3Q@eV4hyg+3fl}l+ED`ut5g0eD9@Q2zcLY%uGueNf9 zrvz=rY+}X5C@>7LG*CeIXqlEHQ}fHvyO&|?AQz>c)ukRYr1<=66j$zEBBnpq*a%Bgk^S}d%l){pPh^oDjwRQFeu*w$i`yB z_pOXkD_-p}GQ?Rb5gR8{w|#3C;eXf7hok_hPgK_y$f9xrPNbhas;pFUp=LmIM?K3mf~4T14bF<$keOA*}}C| zm@dT!o7rV+X<}fHO$@$wIoee#9F&(vYf^b77E|~zLRZufYK<#gCGKL^k{YamYRihL zHgP+`CFtaeJ<%KA(<;sImxU-<%3BJ{wPG{g9XguDpxILZ575T zxPkyE#uYB|x2l4FT~!gaz}yTOt*XR~ud3FKYE)WG`#r@=sfP=dl815qG-+609lyUdCe9Lvt3himQj^|H!2J2eWil?0Y#?Bz&(xttpE;s#;Qwx(C}! z-oa6e+R9a^9npT6Yf@EN?kQPY9IeKyYRb#X5bkR1^Kc=HmoBZvHHs~2i?78Gda78t z!C<5h6MdNJ!$Kcc`j|o=x6sE_`k00fG(vok4{67<`ZqBl$3r4-@$? zkq;C3Fp&=v`7n_W6ZtTa4-@$?kqs9~Sa~XCd)HJ}l(JLOv|y!%9A^KIVjikAeG&hpwM$+6!nj1-T zBWZ3V&5fkFku*1w=0?)oNSYf-b0cYPB+ZSaxsfzClIBLz+(?=mNpmAKIVjikAeG&hpwM$+6!nj1-TBWZ3V&5fkFku*1w=0?)oNSYf- zb0cYPB+ZSaxsfzClIBLz+(?=mNpmAKIVjikAe zG&hpwM$+6!nj1-TBWZ3V&5fkFku*1w=0?)oNSYf-b0cYPB+ZSaxsfzClIBLz+(?=m zNpmAKCTO{BSrG&hmvCeqwQnwv;-6KQTD%}u1a zi8MEn<|fkIM4FpOa}#N9BF#;txrsD4k>)1S+(eq2NOKcuZX(T1q`8SSH<9Kh(%eLv zn@DpLX>KCTO{BSrG&hmvCeqwQnwv;-6KQTD%}u1ai8MEn<|fkIM4FpOa}#N9BF#;t zxrsD4k>)1S+(eq2NOKcuZX(T1q`8SSH<9Kh(%eLvn@DpLX>KCTO{BSrG&hmvCeqwQ znwv;-6KQTD%}u1ai8MEn<|fkIM4FpOa}#N9BF#;txrsD4k>)1S+(eq2NOKcuZX(T1 zq`8SSH<9LM(%ej%n@MvsX>KOX&7`@RG&hsxX42eDnwv>;Gih!n&CR5_nKU<(=4R5| zOq!cXb2DjfCe6*HxtTOKljdg9+)SFANpmx4ZYIsmq`8?iHKOX z&7`@RG&hsxX42eDnwv>;Gih!n&CR5_nKU<(=4R5|Oq!cXb2DjfCe6*HxtTOKljdg9 z+)SFANpmx4ZYIsmq`8?iHKOX&7`@RG&hsxX42eDnwv>;Gih!n z&CR5_nKU<(=4R5|Oq!cXb2DjfCe6*HxtTOKljdg9+)SFANpmx4ZYIsmq`8?iHK9SEu^`HG`EoE7Sh~8np;S73u$g4%`K$4g*3O2<`&Z2LYiAha|>y1 zAhkmeTB+(MdLNOKEmZXwMrq`8GOw~*!*(%eFtTS#*YX>K9SEu^`HG`EoE z7Sh~8np;S73u$g4%`K$4g*3O2<`&Z2LYiAha|>y1AhkmeTB+(MdLNOKEm zZXwMrq`8GOw~*!*(%eFtTS#*YX>K9SEu^`HG`EoE7Sh~8np;S73u$g4%`K$4g*3O2 z<`&Z2LYiAha|>y1AhkmeTB+(MdLNOKEmZXwMrq`8GOw~*!*(%eFtTS#*Y zX>K9SEu^`HG`EoER?^%`np;V8D`{>e&8?)ll{B}K=2p_&N}5|qb1P|XCC#m*xs^1x zlIB*@+)A2TNpmY{ZY9mFq`8$ex02>o(%ed#TS;>(X>KLWt)#h?G`EuGR?^%`np;V8 zD`{>e&8?)ll{B}K=2p_&N}5|qb1P|XCC#m*xs^1xlIB*@+)A2TNpmYS$6w}j7pBO! zC1)FNHW|dhKMeP`OhZRxF^eJ!2^V6QF$>$zFa&9}JO%*{`^`EPEX=jJG!y`}IcaPwAf&gNz@H*2`Lk(&o;^uj7Cg7Yc#h1>_o4GlQn@(=70X$a0Fztw*F~-!21u(y3V(hz{_zHhT znEYkHaq92z>?f|%KZQeo#l^VcK$C6$S6sZXV9~<(x0tyU&nT0Bif__ucvn2mW#fxC zb~PSGNu{g27+d=EeP|eN_$MzLF-gX>mpw5p`u^U_!YILRJRLoa{aqf$g9zhu%*CIh ziMHZT`K_347u5`A=JGI#s_;&On;0v{^U+Fwir|p;au3Sgg&oMK_2pss@GPwXS9Wfv z-}xN;qxDSuuei9PycjocmsFPHh6rvk6g%=3=Ebk#`9_3Mh_5FQhB6(PT3-4qF2-GA z+<5cU7B5{zhhHxXLyPBfDgN;<#lqOa%M_12UHXfKf!wUPau}&R3_TBH8xI4IEnWKi zewhx2d9QtV|iJ8yEOeKb_&b z^mlm}jR<2gu6}|rl)7B<04OeAQd6U_xI7FU+K0`JN`^mW7%`ieN75@D|L@z?3|VE3 z9yMEdL##~}#hkDoz!Ci~!S}~tHgfwb8E*KewsH9%t&4T|??74j5yt=RuW^rRmqv<& z`@0jQoF=`*GPCgQOt)TY+#lMLDkVyyq}~+?2l;iQMAyH;_0axEIMD3dBfviksb!6m ziN5`N_sr@o%2DrX=~X5C+@W95*b})usa5Lx!047>C#-cu!iTz9y}m3G{-9eUO@A+4 zjD+8hXe9lLOoaT0Zc*C1pEWn`L8zIcTeXYjM8Z3}@dGQ(qB|0Ptvkori0c>jFn6ki zS7=O1*p=QaOo)WHb_;I^nZk2Ib^^kAwtJa`+-y;23fYnH6Wtf!hw{TR)w>elFA`qg zozOE0n--Dq&$|V&s}w(}*Q^$Il!o@l%VcFY6E!`P5*kYN2yq!w770JlEd(Or((XVx z)1Pl8`=7vme|w`X627;Y@$!g-7j$ng&kJc-T1Yjrp%kGol|K?LjQTE!`tZSr4QW#E zy6I#nVYsA`_Moh8^t+M9NZ8!%==-c_?wJQ`KImP-Ug>ATZ`u>sQ%OJ0PwXGPz|m`) z(9%0Hkp(yF)cuKB_P*^k2YdJC&+k{CzW(aO;Ab^+`q+d&_ide`?jM_#?oj#E&uozk znJy%Z)c7eMYLsY#e{LvZ&@}FEX9=PGfpWnRC~YWbp#(vgcvUOXtR3E?O}0sy(UhrL zBjNTgRbW1Rf76vHRlFB>+v#T$gd81ms%aLH=Y~>sfaS2s+GZgKp-v5yQj8yUHIyTM zHaCP{t81p1Kk&1gnp=sclUwn<@2LFV>PgoKyT*q`YF?2v=ejp-?9{wTHEgOpvoBQD z*kybCx1H%*QJ2^nhp&?*i|&09_A2!6V)}G{a^#xf;jWhCsa@jZR9~Kk?Z{RZx<=mJ zbtI*yOLty#e2j?KlFCfq<=2aOeu(0^`PU^PL`6@)sW)d@7*Ivb9!H7Exl@1DXnp^vv*cS!eb&VQ_$~i z7BaPx7ww2NX2YLo93e@4=QF7tjFC1-YaJdzaUv-_r2Q8}ZO-E~bf`^H7x zu5l#5%?t2Nsha4f{%K3p$L7vO;4cQy-fyynde_bD>wr#_&cU#M0e|?R_s~Dr{n0H- z$wR4``Qmt`-@N+k8!py#dc@H|?4UWD6HbQ!{&b`)= zE2-TK{n^6K_2_*f;iAq&=?nC#k??H9vju6Mg&v2(G9icA62fu+^&}IDqHTU!H0CLt zR1eIZ*o#+aykJaEk;O-^NON%Aq({=623O-H@!3Eg*S1n$WDHc z&ddjKZ8#LVGfxwBT?E%uLh7h{)|rkTAr*>E<)O{&lkDVkt%H1qIxe`UH&N*aJ5*8; zdV)y!+YY^(>F+~t_H~CXGZ8jlb!a53RQrxWx)tU3MMr}4qjz4h=X^?aSFB2qg%l>T ztVsC74lnBUM2Yy%a5b~{Ht31>#$>K>*ijZY;(xF--tMp=>|GsH4m&%_GW2WG-{N%$=6NXBPD2PtgtVB$QO zw{=hpECNmIh_}FJys;M8AlEj{?49n+BJGCM+w2ZfMeI=53;LT|XZEH?Tj0#zQLb2; zMn%&!v-fWc@Lj#uu?D4+{y)Vh}B__a8+R2emxrjUBJ69|D#x-B}gd=d0w&JYQI8r<8%Mwvd-iXQfN!PLN*Xw7^vsLFw=Ihp`Q66+$26xYalDV0XG;i3J1+Oq;9t6oaL z9Okj0UQ!{RN02M(`_|!mB>ZsjPkg?i+Ld!1*{llE$Wa~rtPC>TmeBJN-n~zUe3b2D z&1AY@u5;&w1Yw<15UXai%6^?NEwA*0N;dKO=oK5TRL$W1f5MZENQtQOVN^{T-jk{o z%e9%REXGy1H7ND2Fo>Cl`>JdSz9cabHBReG*?d&~L`Sm-ZEJFU+8H)i@T>L0r-EKM zrV^8VUZ&4U@@X@LtYJQuJvSsIi{*cXy27s_;k2NyNi!k2UZu}!{j02RAXiDxvFu^b z4Z4Y(V*1WjZI4dS^ekdub*7}a&OM!L!@s7dkhwVv;=#^wDKt(F=d%Uxp1g9*PO2*< zf9I%_dHH!Ax@+aGmKzUXRGimgNP+&R@?cis`}IyN!A`Kpjs7}2WMPiXdK3c(iEfd2T2^BP$HBe|7xM&`&J8_W6nNmE?A6UZvwP+C2VCHdEKqh(uEV5B zWVVovH8`v40?sP84f)*{X-M4InUoxQtVJuj4$5O1_B?hdSfDFHZ#wgoSig5YOubLF`6|@szsuT& z0o2jo_aBrU4J?ypMQ^*QC57C>e3*Znn%O%c+P8i#YrUQBHIAe5K__NQZ)$pU?4W$G zQS+P{?${|?v?W|PNm{WS3W3U5?Ar8ZtgI8yuqv%D5xGqAv4CLJOS;fi{fQErEc@TZ ze3gavcpE(p_MTS5GMZ5(JLU0om@@g(|?E6g|z(y*<}Cras| zxsmzOddaYCott9P`=2Qo{plC7Ph`2HDF$&AVi?zIkVc1UBL*oklVyz#WuGJWBLkGG zywVYYKO*!Ln!B0~lh3Tf@)q$h{ANabgOwGDJ>yl0F9=2b&@-F))1g1yb3MHRpOyV<={%4ja|b4SA2 zV{52qz2W5K6>RdIewNedURS=|F102-e{WNd`=d&G(tOk3Hu19`~>t)oocJ0dc6PjKo=`8<6e|(iAtF+|)`b{iyw@e2k^PQ&y4Ze%+qj zO7+0knURcC+_<~zKr+qEhhe-vC?C_ccoIUn7s)-X`~30_9h;cwPwr3X*~ErDpAf1Y z_)Joxv>Mv?MeBg-d9B+P(lISYmhtER**O;dPT`G5J2Pf4LI1O+tMtZj7n^;i>zf-X zmX@xUQc{j@>AXIidMxaes&EP5eI|8&6{E z>3eNHtWSkqsvDDAsqK!q$n@7Yqm41!8ABD?7xN9a-PB(<{>e?PcI=s!xx@Xld#m%H zAy&eLo&(E;+&OKVJS=y%e}wp_fYkdo8~Hko!)(GDhx6Ri$tn*M^I(pCCK8_5PV=t` z?M!cI9r4`UkS1k#&s3~`Y`veYb;~tHA8lP57@U=gt(+jPsnW}&YGbuA+vyiEJW7uXP+vARnGPabzcB)c5bxE7` znaRE#kD-6UoF>IbxltiE+ROp0|Funt;#Gl}y$5tuo*wjpUUy+WR@L*cq81wZ1tGEi zv82NM2IoNdp-8~V#H(p+OASTWYj?<+Cm+Rl?R3|_Q`oo2Mq@U5T`z?dQ)VVqiI(nT z1L4KpY~Oab=+XQp;l<=}zp|%%`L$c?FiHdAx!v0_Bh2!MuE)l$7&pT4HP%eAEB5Y8 zPlJ1+qp3gCtLoS3L>Chi8}FAjk5j)N*)zLW%Aq;CI$_wZpF4J-k4^HEIup9-Gdubz zc8?0M3EE8cbE-G+GiuKb)ibRdBXre3czE~kT>>W*N&I=i=PltAIC1o1&fp|etY z#(N$>vIy$91+7S&a|bFJes&pLZXGlQ%D{OQu1COR&?b@sO_ zuzn5=!;1YXX%j}|3d|H|`wRLi^YqbG$8fAb2f`nAvGKG9eQu*y90(s6*noN2K=@Bx zDhZ{12d#T!tKNyQeWy!6>C?*WXB$&`Y=S5q##lNKehn*O5!Zj$MQgeh8#Q8LPe#Ha z`ItuPD^E-5nXYb=ZR~LG(zL|hGxh^;`BWFmwda_|;7aUiWFhDC0g8PCVyC$%^QMMA zJa6lLG3{d+Yu+QXl{eUV?=lb&!uN<8~$t--_ej#gUbu`G;6+EJmJ z^R$|x8PurI23eRY=q+tyWUVeTF|kz>)Cx1#2%$b9G*N?41g*Cq)HXiwIaZ3gpqAzJ zFyRn*L*tCz8XL}X2qTF1{&{z=hv?QPWrzL3*V z6o1=yKnl63{Fr{2Ux=1cqcc`YR|m+XawE4P=V5%_Cr=+aqqo+Wcy?p;;ofpr;@R~z z16cq2nwZ$=)QeJI?Yu*B2bF#vxuMleHWc`4Cxww8_#D^N1`)52dn?Gahob9sWqA2; z`-e`A2zRe2p; zE7YqUI{5>k%A-5u{e{M#gcLVmK`}CL3}I;X!&+B*w6NRFXce*2l@Lgcy3j@K{L&Yw z^W!l0SNny`Lvo{z^4h2?%oj3Sw1+S%9+G#mL-NavN@6dgn!g6SM78tuS9KuV88g?a&98ij%IKRa5QKF4?`^}3C0{NY|#TAiKdTiBBoo7~!b zTj&LZFdgB2gmvz8G-Q+Ku5Zak>MKc$)}+1%=EZ8#dmW+osE!QThqg?KmYShbE zDLW8n$;xaAKE%VlEAj@y&v%frH3BL7mp+dWtAh?G>qR}?)bY9e4bt&w$6~a5Cqv#@ zqJBbaLEn7jx)yCa-m~irG~()vH2xBa<%LZW`ZBmuAMPzNidh5Ul8&T+vs~&EW43)I zE6H|I$LF0nDTig9x3E|DGlZBzdf9rvE1_1{@1T{?&m8L;X*D!oda_-o{hgE+ns-sf z`?`en7-_Y<9bpe3JsCQ>;Xl>y~CywtC>$?3Geno?&U z>!;RJMYXyHt*38=Q-gk@);S+xByFJ7FYS-Fd2<9JxdWXt@{y$jI`yb02oC z^h*Z9JFpY+CS1K7BtP4OR5y<`X)_N8y%<0q4Z zA>4DeeGzmC?=)9|+G1 z(*ChcI^KD6%1RG*j~^ch+hAu%5yZ#kskkGAosps=U1G||@+5W~s(vh6*nZR))Rs*R zfi{d!+RQg7#X6dwv(PWS6!xrsuS9Ex$$m=zjNWRrChDI{=Oy-t$j6AFcHh=c;qg6P zEsxXecbuP6;6^;OP9F#loGR?lJx-+~ciB=J`c>+duDTSVUllE-c>K7PK)+Kjntj z8u7gFavN7yaHLttB7HEY${v@W-dugdV zJ8-H4w3B5!M|%OU^@!*P2iG8PO3#0HJeq!;4|x!g9|LN3YD2$TQ1vGrQ1z?Rp8R%j z@8GSo-uu@#V(<0YXR%kpY@0BHx+bK$m?#aG9yyi59>rWoo6kZ|d5k51SVAndQ={SGGgBK) z<=XFGuPG0vW_U53oitl@#!>U8;Jo}w*Po7)Ym3GFPmeG8`&2lyV$`H$=du~{v zx-lQ8x&HX%&=1ZPof1^(NK;n6rg_j!Y@I8X>(DArwkHJw%cnNE%CBkCLcOos1Iy9> zw~G}6;kI^h*+BSMJMCQgYy;uX_QvbqK*Cn62o_3XrG@gOkf7| zB5)jY07u_VD^+h`q!kk1e6n4GU3ePdwzLaUVm;c3Sd^dWJ9?63&p)M3Nbz4aZv82y zD(PWK_RGYCTLLa015P3}ty>fx>F51v5 zq=jajS4k;Snluh82$r1|y6=4AR&P4Z%0I%mVn>LHzF~ZyG_n5NceGbY>q!k#HUsN$ zmX3RS+B|%-wM!WWnA6*7RWngCNi+ksq7(V-TfGar7@DBd^p8?^&7PB%e3rQ!j^&X)$JS5s%OZP7QfbGU^8UH`!nS6Pt1_@_!pmGJz8z8XIs-E z#FYhq7sHWmJJi{Pv3EUo9OJfUy5Tx?WMB;DQ_F=JvL*F!Z?)^S9*Zip9O0@jhX37N z5BG=VLhoUDPD54s#qe?5Ee|a*lvFLhM;0?|=@h~^e~%k0XRXlB&g4kD(T4TZYVX3H zhLkIrv76C3Fn*li-(m0ev)|lwt*{O6EYk=9VH^8RsPbaCvHLlUjQXZ8P_DLXx91%` znIce*hod9}UejasjLLUdPiiXG=)P_3MQIm3iT#>^FVWj+CYPOi`UmCbo*p)~b?&LU zgt6DyyBmgMZuh{_b5GCE1V<#E88@}rA_>!Mk==JVx?jD+cJ7fG!PeUXs>vDLM;~^N z$j7(mZZ9O?N?-nN%dGy$c!_*V-7iOd|EKkaKufpIM)Ccn`*!E0IA8nr+;H2s=bpC3 zLMZKiwJsKSe?i{XhlUqEIK%+XRZ>Z0Jx zbFOo?oK$63&7i$>RkWVr9*?)cebBuuT@^f{ekXWvr0Pp*@uLG?cV=#ptTkkxPdGR1 zGi#I0ai~XB+1x(c%u_5$5bJEhRCX$fQJjtY{b)DWI8?z_l@J=HMqiCshQ@Kgy*ynV zJfhhhJP?b+I5yyywJn)9E|#@o7GlwU_M;|kFja+k66U+#Ks>4>Axm{$=nKNDuFC*opbcGBuETQCJb~^SSwx&>p|c0Hr&rq~ zx-W)nx#a8;KRpDVgV9>c}(1K3TVy}gD#DmTi1*8zE~j%E4UGuf=(tx4D`Njm4) zuvjp?Vc&2ntt2V9LH(J0aN34bLgwkV7PxJIU#7pIndaIw$4)iSC&S$%&(PGX-#tj@|ri!Fz#z-Qh>r|Sz1Sy>)-Bc(!X{talPb9ywqnj?x7Pms$H== zfe%J-U*-h%*RW4>wp9>C7qyqh{esxIA3F!oEM8X0Zuokp6*>5;Tenu@D_X1eeTq?; z;WL>D_#EN=R37F0+Uo5 zJ1@4-|M4C@nJ6S|O>+pwI(y2A?XJfd)#Q{;(M2WlA;L=Nbh?hp3qM#|a0B8$DvQ3& z1*yk>=YCfzlrlYOvgi~HKKt*2iE6oRwe&mZK{>$VW8yB(u zZ*c1!4bFsmZ^7-yMbEofi$rccDv!avp2+lXJ*urq!NY=8QU$eYD(AL`DK?v&WB5R3 z4IjvwhK%O?Gv3v(aaLqRZv56YtTo{Ut&!4UmFf%r)ix}U@H~CnDNR^XSMc{X-13uF zN6$eG^P^@yZvl=tn;m-3#GcZRLp(QK178C4kv<%I(6 z@bdcznbZTUb7>XrAH5jvC!s&bl@FXBxP&EnOIqZGnJuy-twk=x|C}^-c4t+*$DqDA zRie{w|BBEKP*GkZ&aP>esdm|yZLyE~$}j5zKasP1*PQWI4)@Q?$Xnt+d3Uy8%I{(5 z&F{vnf$BKb@8a{1T}V2^YM}DSk*%;#9T8lw5lp4-F=yB>7N6gEfo9vR=9{-8lY0DY z;y8cO8E@^!&L^B|w_i>T)HqU{etD76FE8Hw0cy+RE{A8KY%02gNbiWkET(e*Rkv5DVbj?b00H$IMek{9zDI@c#kUex=?f~Rnvk#=D>X0e=$xc|Se zM;PgDgU(58(#sN^N)wV;<{~*qER=*?Yuk_IEZYsaQ@%319Fq1?a^q1xObV!>lq)f_xrHd^viDDNJocZ_P&TX zc6NthAKmpM4tIT!Olxo41(6v=mxPIVZK?gjY4uh%;mec5 z-o)MVTvc#Gf{^`U|LHT~t^>>HZtj-YeHeR6aJ}jo+@J1`2-16z@mHgCW-aM@d3F{4 zSL6Q=UEeHk?2=|_n;X0AvnW37Z^@HH^)~F8EYZOC`cAe?2t0z%{Cr_bW0xaWV|~hg zq%E~aNS!08o*&U8jCiWx^|sOg!wEANP9qezI^8Otpuew;@}%CX$W>~zc4o)&)!;6Y zal%(`!$|U~Bx)?q@xeC-pYgpZcyQxGsTZCI;7OC|8ubE&ors(IPk5HrB5h zqY7@+Y`l~g%7L2)u!30uBQ`}ui^A2_9~)hZ}{4A z*~RcDCmYa@e|Qr2chI+qOXw5=^K4flb(*d=n({t}(cN(>%GZCrkm1s@ey@USYSXN)>_ z&MXh>wMh8z#kYcwCU~W{qPuXn_;)il`Bt>mJgFcWvc~wR{amZ9_l|737sk{^>1Pg2 z*2S>>WFUjz3qgqqlkr9+!yvC0P%9{IxX$xdc z%1k+jgj!<8II)I(#(L-YyIV2VvdX&VIMN;e(_ss*iyTMov%0nkiycY4J zu3?uDe{sQbnKr zkIlF$UW1(v|J!Zyc&F{{Mtjx?a!cRHP2;#5^w(h5a|}bvN@$ZsTM>3nedilaV;AVW zs#h?K%Xi3GMdX(JG>uC}Us-1lMO)&*f+MXI-+1TYo*P&t?!O4<*#NaR{3qi-m1W1T zi?}BuA`e2}bLU^}DMD#9?n9iKxu-rc;?$^QE6^TCI&_YVd9qlfI?M9**n7XMFGxn- z#uVKpXX}JhBZQ~ys?P*-eL>%e2J{5jC&;5v-wU3&eMeBO%4jac-NldlA}ikuetLU) z^NhYoby_~+>$S;QI;^QvlY4~Z^#yyNld_euW}G>Uo~>o#CfZREv9mOl))TS**NgTr zUc4AimNgg+({cXox^s?RJ5EpDjXPSlP^Wj1q=W6KbF>4Wo|%I)6shMDrKQf;`JS)5 zd(J=7^X~aaLm%Kitae8+sH12zwTx}A+y0rHSn}7=&h}bqy&W2DHmk0&<9>& za#qvf&_MDCZ$QU;~yRTs{8$pIJT-Q?ff zgVXY@*qOp>Y6Uq3J5a*N#8%NQM$a^kzu=W(?Fu^xDCtQkX>uVhNp8amsG$H#(Yf%c z@+|ZO!jHnO)S6QKteyqyVzX|Mir_r(VPtKd+8HZ4>s3$BRYy)H~C#C-pb1lSZ^1LoY?{DJLmk9g{P31=k5f_0XVuzR&ai+AzO=fQ(|@y8p8luliE-5H420i`d@z#yrJhhtPHq!!i`l-!ZG{uU z@<>F8^j z?%Dnx`K@4G^5^K&g^{D%s9sQcS4SxAlhEfd^ou&NFkgjL&a7xHDk$h^gIY-}D_bhS zER%euwP7B({M{~=g8yrUA3clb6%vE%6Y2b$(9MSbu0u%fY!ys%9GmR_M!SygMi`W> zJ3gP)NcB>K`&lR===E)Ef+*dK^yEgg-Y;y2XmW=t%G3=$PgO8|L4#h24 zDR!LxOMcRh6pT~%Xw(#Y17h!L8|#p0eZ%ACtCMKoL3?T=qzug05~Pw})&vpO5{hcskd^Jw^~V9O*Q*$?j+R&-CdWzWy`)KPkvPj`pd2&rN5Y z|2jY=nG@Y%J$|VqS=L>$-asj(QAT5EC{SUQuMR${rgXDzVfY4I!zs=w6w)S)K0hh= z0%?z>nriR4@9=C;cnhtAFn>7Fd1swW+%pVbIq{y-w`2nnD&25>*4 zZI~aYmhnx(x4YYzI4$ZefJf*Q#*{^)xoLxYrjPYZE4o zXcOw$1a|g`HF}B8LggR?Yg?f_feBMywV!EY_3J!Bz0Ff+&ppm2js6NdE)!H|pQyom zOnWn`7swNep0rAh)ahn7rTfX(={8jWy&Fg=~#qy2fQ90v> zDOfe(u9@j>IhW=+qF{X8-qEJ1UnxCeKhlg7<1cD_RJv~$eAFg&7?u}ym>$QfDREyU z3oECVWULQzY4t=arwieGIxd9o>WH4E{f(xcub%$+NM~a54(Hrck0V`D2YQKQjg;J< z66$bW!1;gV0=>p;>3+$9+5NBj`_4Ywf3`>HzsgJ_zhJT#oN1%Ec9G-Df>Tg0fv@fA zvHpLaPKLI;kG|$=jI{`9#J%!l+xVvW__SjlFPLeyai-vO>kpge_9a;UPhX_=AqU%n z7ww>5tdIBgcsA(;DaDO5`O7d%o1Wpm&;3r&IdVsHzApV*0k!ro-Wl@rNp;d&!N-%6 zJ+#9=%KeyohHRVU>+iwLZfXYICD1v9slNW+(4*{giH)b8f`wL}n}zwGU|C$y*Oo8U zqvo{qHhA^d;hsb)6LF^^^&a>n+b6vD;9K+#qZV^9gldSo7!MbdQbX^t3F)2;=^k01 zf#-cLWJ}b8u+W3>C1xa{HrF2i((_|^f=FZ2J@WVrJLYM0H&dAMlY+0??vZVXWiCuh zs<&YFah7wBJT-NOT=;~xpM_9z+8MGV^~achlHYq|!z7yLQP|XTU^h#6%#&un-hXd& ztVD`nk9lAdxu8@zCLz4(N$x+n(;WAptmb3(stT?Xklsm+Gh(UDj-KW^R`4-WQTT*l zr8H4b_lW)d=2*IR>x`vonl!XM zr!A20zfMwMynesWpESui`@Pp*d+oK?`mdu#_gGQA7yh2Z1mnz5DT zZ+4&$Gq>0eVE=)YuyW$PaTg_sNhJ@hF-MZrXJnhFdCj^B_4aWWNJ`WDw5BUkS=Yri zC60@$p~3ayW@W4CL5uj?)mNk+c6s2PdK`HkT3t86xmp|4D7P^ryN$>zg1B7_)M}u4 zo8>Wyf047AS)^9(fKMVb<>J&SjN;5L>^YynN*4B_!^YM}up;k)WM(zet~5!p7>UiD z;5#noc=Wwl+!BlwtoU4PXLD5}Y!PS|(hobU;@{N6ajBK_HM`Y;MCyv=ebHtA#WnY} zzP!e?Ce3k0dhU{G^_fefakl_la(tqtt4$ALe&7-`GKMT=N6WEVwYbR*u9cPU+Et64 zzzfb-be}vGJZaAJ{3<87o1^HhphpGnHs=L!KKiyW{>^Yf`OOEvsIwcns9>Y@s_UOu z$3g!_Jk1Mj1Nhe*@RuUubT5cvRLsOZwSLI49P}6GF{Yw8uPVw~T8nSS6|&h%`>RFF zbbIH42W2r!DN^HZ+(dk20lqV{1zMmy>?Gz(PK5&hLOcyMSyrBwH}5`*)s)_$>fc$# zvi&lAHm2e4YN4c}{C@eC_WP03)|Jetqy_RVEQGvsNXMlA7kS}I7R{o@PpGMJv|O z4hKFD9R?^O8Cqi69g1#)u95beqO33E>FqR&LN<6iS_d~CI zxA+xwIVa{Zi^fl*O4{fvxc}D$TCl55&tg~y;8$!3*1_KgF~8U&axW zi$nT1-s-g^^sBhj8VomV4rxyb;z1+ZBY4%YPx3H+_Z3Os>1O5K8TaEff0=aYANNk- zaw97K>yX>PJBR{uoqVqV3#Jo=RZh1S-dqc~;BUE?ohmP^G_o1?vVimBUK8{5y!-~| z6-qokubi@X8w-sH!oEK&eGxA0o@|JJ|14bIZM?roOcm8$O6lx* z#<0BGdOuk}4ND&)tO<3D@;RG73^ zXoALn!O>X#cteQO3)8k^J`KHELqjWNKo`Fq&=wU%VN40lx z*Wa{|Q82!mNseygf{|9QfHs_L6o;jsDQ$^=U#GOe-IH9%%@C%SmpglYg%?yc0Zp$ckEE_iKY;-pAhJ*rdh|lzf zG_&oX>Q!O3qb$r7^Wo-2+2Q5~s&P*8gftcC{Q{J{0-yK8mM;2j>+r47Hn$P?mMctWZQPl%iC z2_+SHLh4M?FU9q{&@SuI?tL`ERg*xK6|kLH zv`>wlV}Hi z3yCt-dTRG>$n3jAsVFB2WsaK7hZ#nfrJyYj#QT$4u{kstAp&H zVp1XI?6NRpZo6w(TJ(n->y^+AZrp_swt*KGvoAr54xNG(S_sqPu4?_%h)Syu{zkL7 zYnxiXtI3!g)atn4meg@rKZWAS3{6lg#M`JU&;`{DW2QIVZk#z9Z8hF8I;5^BjTuvD zG;@0F)SE(6*p$LTszlFtJ<_0Os!ZgVZAaR&SQ^dN#B7WV0&*tOF{D$W_gukf(9idm z$=#HeLzx`PR9!EV$|E{T4ystjtVVnD7wUb>ME(9(dbQwlo7G8PT8%2)n!MbrRjn7P zSI?phqH)reC^VjE8}*|s-mlwvl#6>7rS5n-N>BN)CSpeF3(}@3V}S3sQ#%^4W~ux! z_{2IY7^AEq{(IBM%a4x((&>>W(|9}O!pfU%LQkj`sv%yoN)O9v{=gTo(si~>(RxWv z?)7lN<4nK58E@20KtEMDk7*XQVONMpNg8SoG&4z=yD(-%VOYy4M70eez5?$S;2lA^J#My8 zuNw7n->Hu!>Qg7`;}Z4hP@ncY^$Cgkbf{1JJ@v&`5Jn30L;WN=`{(-j>-|$H_3@xD z>hBoP?ilc_f9~JNJg8Bh@ICd#>6&=sXoWY%Y4GOpNDe_W!z_;{LTV`eKrLEot{ zPFX}Lq$N$C_{*cbNlmHGvS2k!@dh$L|D0g*!dA?ay11)dySR%@WZ1PE zpv+D7rtW`6OldN_pdVI2W1xaRjXJnR(7&k0sv$ah9^F|lE1&+I8}|*J5uKjnra43rN5J`X!Ei} z&M~T~0q6g#Z|nAIo4AsC`%`^izO7QUhX+EMZTPnj|6XUkHq8ZCBwdh;S~LOHHa7h6 zoj=*MW-jeN&xKO;ulCy5xDY@4IqX*BLR-$d}@X?Op4LH7(i_O0KZQ_JZd$LBdYa3y>x9 z!p)O3SgY|e<74?;NRRR~D9?cM)Kp&a&E;(g=_^(xcIPc2gIBxiSpuf{2ch_I7l4NVcm=i>8_7Y zc9?_2!C`zf7@wp>9{p_e>2?ju!zVo11>{XeUN!O>3aY~l5(n{d4iX2KV#gTS(S|Lc z6|`efe2mn39&(l`{3`mEoG90jD33>ZsVGl{@>2d+d0Rl|c8rk|W4r}4dSi@I6Xm2N z%3&zSh;lfTGm6SdLAxL;lAOp*LOakF8W*NV`_RU{Xd?$5`>WW|UcuZM^%~Fw?gEDi ztwcAh?KNpVGn+w=U%t&XeF_QoC1@;33!(LVt9Fb~@~MI~=h+Z`otJ(TY9A4(x36V=X&s!mq9^3v+Kd!Y>!+ zg%74w#99_>X*eYrR%{PG<*wH2s9)lZ{bRfy9!x;}FmOP<5{P|d0p#+m63svUI- zRA*dHB?&>Pdk5!*5CP=BIsUa!K+cp9t1 zI75ZGGT#1zz5cX%?|ku%UTv~A=%HI=XtHp6&NblVvY?6l7nj4m+<=3poW8Q zj*8l2yb}l$TWkzTFt?Y+Mvq7^g~TOrzENhE@*~}B%7Ogfn;uk>ax~VQ zL^mcxsk=a_;GD>#Mjrlq^Tg|jbAWhyK9OGaz3E5lfb5>ALxVch$diORgzwE0uOrS8 zc46fqT_U~ud(+>jW29YL@geQTDuc|Ad@p_6v03BD>LrNFy3yQ2Cc$)A<=VC zBi0$Ok3WmIlqeH?Gx03m+YXE9i^oP?e&bk_Lh2xi$o>jqdh*}v!?FUb1$YvWoef#f&!ME#2!WH{?9LVzQh-j>$VG&uSq%w%ZkpjUnk+m~1_Uq(9(uI`bUX^v`!tb z|8toiY3mYcsl*{^TbOQ&U9Bvq688~9!2g3Ukdd2CPoKf9*pT#Oc)2(vJrPz$4~Tu# zPko}l`h>+&1)hzZ%Q><-wQj3r1zBwd7b_g&>wuqH%*qP2ZFTeRcinGXubD>C`wHcLf{%@WmYNYqT0OZ3}e8j>tA4SZK; zIboMn*$j(kcx}&$Tilo!AK*-1Krd^phE9T+;in(ERz=?3@OkaLWk&NM#g)mXf=k@s~@%%0)M2M)2w%=R?9=a&sh|F{NwV4%cgjlU|1!05Y5>jh>d9ED4NSEI1 z*7p|a>+PK#)RtzEy#V{GW|ylSv-D06`Q_srjPI{q!|BSXb-G-Oj5~_y-@Vc%HiN&C{C5 z<5KdF^~*Q7Z;5NSNAApbwitJ@{1TtWwW&7sxntN-jm^;Ndq(YATFzg1ANLVc{m_jE zKwHx`iRx$D<&40u+@DtQt9aOhS^ssJOWh@?4kO)Y--6n)uq|@H!>O_M8TdSH?P5Z1 znbuzo+wSvXDrUWbeROd_ZDXzad6YNfy!aVxus)NED*s-cyLyZ>Mf_N-bQZW+0gGhR zpT}r0_?&j&h61M>(jK?dd52k&+ZK1ZIs9Xzyv8PWIJJqe|6XZ3hY{l}86CJcDkm9% zO(m|$-G;vtN$wS9kTv2adnx23KGp)Q3!e1~LJ+nSYm!l(@Hw=okBhK2*ewpse)12X zO!BIL1{{czqz50wy|+tcv8i9!FRFla8K*K6(_ycN=L?tY&1n0L2s?VF+bPU4c!l7Z zIxgr`+l*RoGtOMU4OXjF-sMJN&*H9U)cQU5h$K5Fc~AAi*3YYky+{WBWnm0-dx|2EK%bUsxRAM^;Cz}v7ho_thjO2(d_E+)UY9R5j${flrj!Ht^S zLA{4Gl*!H786s_=pur6RM;eRYzzPE+GTROv0<;>Wy-UF^qF46{>i_X;_TL8!AU2hm z9~XDq(|lT3wAVA(c5<1Hr2UzWU7%od$l^i^u`5`>^DONtdq<&7^_+em+Jg6KA!C!} zXlfI!F`LU%zO&%o;#PMy76hO{|pXgzc`>E}m;exnq1N z3pWorMrgmSe@0o)t^4bERq(k-_ZwBgm$*~o(}Jnoic<6y{F?pgmi%G$GTtC0)7%#FWS$7rnGIj;-aHlGn0H@!Nv*RL~Wy9T$hR7 z8Oh%%CxEibg)X(Sx+eMXtQ@zRQ(vMIroK)kn6zyfqUR`bo3sqb6fBVkdBh!i!t`X)>imCm4h3$tAo#| z47lMacikhKE7idUHEa|rxss~#{*KpzJj0!qVl&UXf7D93@6K3IejNUr4Xkb+d_by{ z-96zac0*^o5I#;r5(h7eA?aF>nM_Wnv)SoQ*oV9WVvvcpz-m|!GnsZ3HgnK|r zli*vh55w+I$%<=z2XULL?@;#w?K^K7ZkC3m(?LAL?I;{W6}pP<_@mNVq|3s$kEwZw(nFymJ2<484KnE4F&x;v5n8gbrx|6l2mDv|ym z{CUP+K-!Jq?|HBdzzk%xU6no^{1ST-&4vm4(w_zoy1AJ})3@LTi=Gcjj{zBQNLm-9 zk$_~*=3@+K9I*3Ww;N+A+grxL9t-!ix3I{OhQHwcHR&y~deEA+yOVZ*9?}`ENI$*u zmYiWDq#N~a^_!Y(cxy&p8!C;umzWf61Hx<_lI8^Ij&>7!?r$ITsz?3Q_d%~}lr56e z01G;_m_@cWBpo#2p2&8EFmc+W^$q$a?X1mqcKPQG&a5FRYdGmG4s~P$2SICOkqtu@ z*dtz%Ebv-wkJdCmhQyHG){)YSUgwZC8@-)yg>c;3qbnM;dy|^<`;tmdVNKn=&Y0O8 zyvVko^hFJ11+57RTH3FNq|PqF0N^GphvhSiln>EcW(I!|xEUtYO#Jd``+s#L9pq5{ zrC|(BJZ+c&p!@Yq#5|69#(41 zo%P$^PkCW_ir4^qy?9HWNR*$B@(cO%Dw(0H5Vi@^4Uk#Z6K|exeSM zc3IT%Eb2&yrOamg#YEZj6J>)NMK{;$v4-^hzj}fx?T)wlhr=SIUF!8?^|paV+mJMF zNPtx?#+hN4!!3Cp#)N}Un*a+~0sWjj%vpuKS|{10UXjM*?PB0_&`hKa3wt?uNNpCl z{+;lf+_{eTlD|9Eu=21n;m}X&S?ds$QYvRNVXw~Bh;qO2aC?;=lyE!i?Lp*V zQK6LKcAG;!ekVgt>iO=W_@@^oFr@^QVr}Aye(Z_A*)#-iuf&_XV29#~{*KzQm*M7{ zq3m-g+o8+^@Kij6&Oqms*g(-caVn`Eic>i(VxtGh=0bpt?Au1ukaXuD<+CcYQ8`2> zAFb1>P~=_8ulb2zcI8(ieo>2WSALyvR*~2Vj9#$DhdQ%JZ+$)kA z?*!O#5YLDWoyWhdNc{6@d`8|=BdxkOT}XxJ z{gCu;ofhnc8#?LafF1spPr%JPof&PGDzXU$2#8d31W1!OI}Aw=B0um?@#_&_xeZAV zbV7Eq07t=0Xy2@DB;69E112S~K8K_QH+?Tx>L=eQ8MgV%v;!jtD@3+SX6{Q48RxQ;?Cayk4vgwcC3#)1xkzMY3ndOs}PM|2Q@lq{go zvAo3*t-cc{bj|=28MXr+JvQ9%gZIdVz<|Ixw|A*suzUn7h=wjFn}ylq=4fz32L}R~ zuU*_#ssD%n!_HL2ewDl|K`lk<4niLwdSDUH5tc{wKaZA(8v6Dh*T3yTn<9RCwnKTw z&5_}gM|2pMov4kwfE=eqD><@a)h60l>4NP9e2QW>w~^XM?W8uI2s(L-LnVwF^2mJf ze`YjJD3JN>qPF1B9-#BVXQa;4_4miQIp?moo#^bwm8eLwU6>$|1|*8Kl- zkBUdnZ(odYs5$gwE%p8>(?9neW2+Mi$g5MO`+_yg%zLc9)CuRp2s`r8R(oSo$)B`K z%IvP~hwAH@c|}=+lWQP4i@YaBPih3nXDW^AonJa4kRsK-L22i;Tu9PDx%hBUs#b6a z`>R+aRgSn10vQg^s|KZ~t^pOm$sr9{ZH&yfCxv+jrFGXDL_$$YW`mMHCPsh4Py^7X zRvHLZUS;rwSmCgvLq2Y->se)B`H>#y0mlX0lfy8pA!jf#q$d8;$@s(<&mYz+2MubBC#BeygHuaCw27#NfquI8He1!e<#kxyeeC*aF<#8oDy z*_Mi>ecH4gooNhG%+7q2C&_UwDT_Sqsf7I(_D1+#F%!)KybyuENgm7Aqj(qjKZAqP zJy$vN+5r8UGc?ET5mS1N2J!@6P98R`jYNGDHU8+KXY8&UxM35zToqL$mS z=N~~h2kY8Wm)&hcIcJ9cB3D9-L+Dp^RWp5528%r9K`AyK=ZlT_hI2$NH!MU6%j@*` zL8+@-wU6{~LcuM5((Js<43lp5FQL2grxpK_F%BEuGC{ioTP$dv1ul46FwaqXFn3TF zh#SvQ}G7BX}&xk2V4cm0A>*2c;LT&>HSr^WL`%Hcs3-gVOFR4p(|>pcbde z^W_7FY;npJYFHr0#fmh(KrMV9ItC@r6^By*E&Tk7*35D^NIW;r%aN3Q;9hC06A~?IrV(Xeq)zuZheA*Dm*Mb`46CuCQFSbG5rVP<~idTnrrO<5=&@d_H+M4_s4!^DhV+ zY#~;b79$1RQ76l#G(NeB|9CuSfe&IfD+DFywgv-FY1;__ z#q)Qu-0T2XY(e=anC0-Gba9x*oqip6{e656`gL|#ZJvl6?aT;`NM5-f-;XQbpD!2i z{r7A>o@>jOb*Y))8kyNvkad@rl(DonO zSP4$`WbiEEiNbH`th^i4k9!1Ldh6fZhwQ-L1l0|6TkQoh17V0~ zwOs-K;I5pBb54{o9%!$FQf1Ht2_#mM9{CaIeNdW@8g|1bJ=gdWP|YhLNia3d#h`Ti z2lR%S;j3t*l(!)#7jX`jMjgi7@ zI)A6r)o5CkZX(1s!qsP8IEPeS+G>JtfvwL|rwVB4TZF^YDMQ;M`C@aG6)Wa$)Y=&{ zJ%}C4M>S;mgx={Yp?3}<9?as|v$)+-al2r_&htA3+!g8~WkX{E)Yf%fEa!)yr9Frf zK&!bVU~;oQTS;rbZ7w1m_1UbZD$eA@{n$!2D4o1kKG38AMQMKN!00?q<67CJ>0QP_ zXDu!0vPGCJuo`C{oVYLh!2{_&M$}?Q8TKdRhO7@!rUqgEPjf(0=gsm1Q*f4l-O_;Z zU|RjIq@6hRMd})8mMejwGbl~$()TtpH9VC(EET_B8ZIAzb`Ws^h*wdr4Tw#2td5Yf z;m-uk_A3mY<_6PIX8K&VdJNv>(0ZRSmf##uzd^OL3_EoJ-3CH6#`|4F=OST)%%U{~ z^d&EyCujS$SbL;F*85YN2r;TsK}JKAiO74`uvdxGaJRC~eF(V4RYA3C6Oa$N99EbP z{pnP(<7h*dmUr9I%EtKjVeJ@!RiEZdZ7LC|Bs$AfiYbwQAEef%>}|w4JoYVT-Xt1! z60ZCo{O6FzgtO{Ne4Yaxk{;wGXi<`#E1}i5dd9)aw%E5){K;WxZ>;3cyb|7tS%?O3 zHzG0RLKnkv*}xXnwxx>jC~>sRqn?n&$ZWq6IkDNE@&!hPRUSQub)PKGYE6zb0}U{v z%@JYnMn*g_AXL}X=R|DfpUb9}2Y`_H0C*iv2hahWU>VrM!OJ5iIc3i|`5<(q>wHN~ zHpJsPh_TCR!|fDeUKGR2Zouydlt=G%(rl&d+u-0|^sISSJkg3%yzyD`LCYWG`>0oi zI}Lt_4KD|!WM87a{Vtzwe+ewaT81x2VNo1;U?^o@$}ZjRH?c3p%h&k2T=!G2jcnI6 zv3VZV76u-V?)fctJ??3>*2P`>c`I-!k|WEm5g+L9)HLP6hjmbjbfVRaI*NSf>R1M5!u@6LnbbTQ?HgAP`t>M%5sUh6YY%AR*= zT+gRAsrR8Q?iitYLBjK5*3MwofO)lnP#JBJ-+8`EMZ17gxm~3E8RySoCtwx>=ACw= zWPJW!$*loSPEHG~@8l+DyZn5M3g7DR?6E_joJ!qpqF`1$6TLk_nyMT^qM5H|IXs=( zb99PD70vt!LV(d8bk!ZDd%`+f9Mf{VKc(qlYrI`VlLjDmfI<|nj7o5!qy*)&-89=N zky~XN;|{;>d200(wAu^YDzw0Ir%&J8uAcfi+HFG5t(G!vnXxRREURrFBr%F?0i4O= zQ3<4QHdP(@;A&1l+my1m-mV4Bc^p*ERG>gx)p?@rD74B@P0-&9!|MLmR_pL)zM8&K zEEV$JQAge$VkVPwIyA#xmeQ1go2tg6&;WX=wDgE)vEHW#ic%8joYv3WzTUSu++A3e z+xy$Gr~Z5p=&=R+LRqu-!FGYXABSVSrYvSnA%v6dQ%FO0-qpc9qy-+kDR;+Tr%(d=0_?c?COva|;``wNYwt<01xUR=|Po!0DvUs1k< z5s{@WuxpqSAiS{Twi8Il!Ba|>{tYqt;H!8wcdeyXmL3atBAQ7?n=W#9jNYyZ6OWfA z7gEX6gJEEyCUE-WXWA=}?Yv?fi|HSV%w6E4vqGwJr@naL+PX&jq_eDe;sxw?EfawS zuJ#GpNdZ~)!xhV+(9!iK4Q|#@`um~y*C_z7pSpPIde!$W9bPwc?3g> zdyQm7)>42yE+*XzpIYeli+g;sG$#hhaLpyiujD^P_#lwLa#@kKO`R)C#WA&$P?0#u zi!In^C=EDSWTNbCRU--XiKE`B!8qjiTB)38P7t3^6seM!9=} zY!KZyR+$C03b6{*ifkZD{+`ep7NE7D@^!9hu@CxT2a-!8c)W-70d4PTP;X578j`2c zXLr}qS!gZV85u3VfSW){`A&~4eR)ldS_O=j?^?W8p@rJ*lLfCX$R&R)vv!-?mg%*t zzevkm?)+HRdcSh2aFSf%Y;vAOE91C@RM%_DiPz}MpJWmp*|PLhk7X^37-ht3C<{1c z=|JNAPJP^)sEz8Ph&EGzJc#=YW{YItcFl-Vz4Im4N5F&Q-Ail}Y)fpc*TQpELT?UtCX}K?TY_CqL3=3GV6G`$B}+d^w7`oN zEJq7?^n2MgW$sPh>vlF*P&Oh%Zaj-+Vk4l2GLdX zI*{M%?V2wvIo6A^RH*c=yNaNIIa1GO{!fvaIDq{YHxLqW1gcXPghWPIG6M zS$#Se%Z~yPJHuPEwgMajr+hODSRh5t2anznU`4h_%v0dz`|741hKw}P$FdLiv$;!1 zYMA-4`>-7td;TxvXN*4i8QWd1)vjmk+!vF9^1-lHdi?hW4#IxKefs{uYis^JX1tYU z?+j(@cZQ~B?hNJ3_J&5+;1m!3F=mA~lwQF-!Xe65PFS@l7akdTVYXI`jY}zyjfDka zy5iv>z)lj8Wh#jOXwU0MYPR0xy5F_k&VKcd>b__hH?BEzpMedWO#UYaW>Y#g+ zrMp7xmUX^}>!U{oTUD>o-6Bwe=#I5FnNRYPq-zkh-Uw){PJXji-D}b9?M&tOghuHj zE)IJb^X`C!8MFqnCU6O%bx^{hAC~(YZ)3{rU#Fs#TBg-Thr?bK&oEGj)%q?bdi!FRy?KcOFTd5YJTW= zD8ta~vO(%=b`suQ9P{))U{gmWmUXAyZtosl_}_A}m(CWX=@B~keC`7Dy8-i0!NCgd zg3NiaZF6W!0r>`Q4w*7p0kBANkMzI$RMPpQ_7D_OX26{j&T%#8Z-`>~3aC z59BNR*h!@3oSm+ES3Ld{17_eeMoKlRoA$5dZVom_H{V^q)oZ)%hZJgn*Wj^dTGYU3 z?yT8{9@EbEmtpe1T->4A;~4n;EKreF?4D3dr{$D7c=1Vp3u4co@;+{=NorE*zYhHx zJN};v1oOK+AHgntkDeRS_tV-tE1xjYC_yGDg#X<36F^S0ZDR#fedEM+hy^v?4|`ob z;#*yS@G!mGB5({Sq*@RJS_`obI^tP71MTh}Kh zS^AG4Xc{u-#~x3o6-Zp0owUoJfTf!{_~oNq9_;$JtuWTRxMK2Ld^K3j!=4fv(i7(n zgsMM4D+POZS|QiVarnLeNKZS^=RSu;jNJ2)q2Bp9VtNcQ{2o4LVj@NOdiNN(oW zp&u@|v&Rs8+x|#TcA>N973h7pDzy>9KS@&uf%1|JTj!5DDxnwLNg6q;rzcrIqMPgY zUqDMCnHjk0Nlj>H;UXBU?dpqMedpi+b2f0M!yZJ zvyIl|k|nb6BW@ayE^i<7^UtdS^RqOtq-_C0r!0NmrFr2K+0xv-Dj625p$1s39{Y~P zYTM_Z(SO}@74eQaulqaVx9#G_cj4b9w`y2-xpnw* z?|o$-Rc&%V3uN{BDy;KW9Cm2npJNSDjOwJweb?ag_nmbZ$BAM2Nj~gR)@J3luf?W~ zw6+1|Gq<^_3dlNt1F9^_gH`7vk*By7Wq&#}nvge}iWSC$!6* z#+DC}f^r+_DV{*eru%Br;1y-4fLWZ1mS4z*57CK5}QYnVnq^Z?n&7D|7!TlWlxC2s8jlpiZ1-ZXcp(p)7w)hwEWz z6X5~Jr}@#2K6sK757k}J)uuZ9S%|gBH`v2|5&J<&;6zQ`;n&@DNJDWtz6gz`y$5{m zSb-B~O^Va86aG#3TtH_}@INK`-)ivb1ZvMVLhwrN_!3k{6t}pmbKU9j)Yk_)fy%+9 zW*%}p)0$s1-(6WgyY1DWo*$P{DQ3HNP0V&uWXHd@-Q`Ymn4#H=>v>1+KbbleXGNf_ z+@d~>^Pi0PlDV8SH!wdsrSg+#(D({sy>liO#7V}i8P-SOHv&2=luHL*UxLv#K|DJ~`$ko`lN1ekRNPEn< z_?$f5s~cjyhlhK6VU?odpM}M{io@UKD)y{uCrP-;{zHSz2qcQ`nG-*V<&E0`zpg31 zLxVh<8aUc3AXX>gr7{aWALD~(X+de2U%MluF3`kUCg}rd8<^!KIK$qYU%;7wA%39| zQ3fhEcxKtUXVN{m@&t9{-CV*8oqQ?02NX>YWYvlAIm|pKFU0S${ug0YyDy}fJs9JE z%7;~VXyC2$ZcqE{U%|4LXycVORXFDk`jr-F!e6AV$UqAnu`z42!+8%lVq@28L);2g zIPZ=|yhr)Bll2aC9kXGLWwmwBGT4ze19-5OEzWS>+WE2HtwjreFuKRM0-BI54}}k| zT{)37J!F4ltSoXoIGGhG-<>mHPq0}-r)by!7jVI+3Hfby{GAo=Jghp*@1Q!#n+I5j zOpF~_Yey}3hL|#3L0N3H@}3J@ilG-Npy%Xsxew_vckH2X!&=@_7Mr=259bvp`9Fy9 z)G|H0Jc=1T$pOK_`{5^DkQBJ_CW(2h#yZl75_)TDuaHXAKsZ=h#A+alKufqyoe|QDnDQB`N9V4f+Og!f^4}^YNa5Tn^$J0!jyHR+mEWQ1e=~EzI zDo>IwNYWn@C*!z2hEk||=V%Xv?#-l=%hPBHp23$N=O*QM+)oLuP<~VT1EGbP@XFD5 z)=+K4E65@n=csYyLk*;_ACQ-q$$e=}qg~^7uVr~JL;isFBoDXfc_^WfSqQ73!1r}% zI{3&jMfWul2S~wHmKOFX(%LN)4Vh#z!UMa*PZ(xDU(#8Xzsj}hwN=e-!E)Q#uRB>p zHFa9v6zJ^d+77NN2=HNeTi!xg&6Fz}xlRpu>N=||N{-BUjxiH7<8hj_tQsAle3n(I z`22Y#;R(*QG4m&gpP^QsSXOZXX6md$>^j)pC&RimnIr2~C;rh{RFWnq^bhwydvpVL zg0T~J#Bj3f|9k43M@Da&jaUV}^LdV#rsqYNf;68uWQd&VouUzjG<~)%fgx5fbO|1y_cVcCsa?;8 zxY^YACivPl;k^EAh_4{u!C|z?7Tbk(q${4HCZGgRy+YVDX;X;H+=TqZD;TvR!7EY{ zy(3fw;ua(C;@l#>=GVUiOFT$@ulb%}j>+tn-*#{olPLRN`WB~4<<2T`uBH2`Q}`GB z-*^`(BJ>mmf;h6SCxS!l!s#!*%G1w769Ik^|CQ3Q2P%Y>^Nz#cc>1LM4 zArPNcyx|LHiAT!{LUVj7-Y(#i=nsT8o;(n$djtF^h~8~!z$x?Hp3f96#lmb7aQyVn zo^3eWMS6a$oW>-nPC@d+etCda?EpAQdpKj14ZbUwT_Br0q_<;+fnt)zp5Dfx<1sEl9k3`ZC*w#@BNW1~C36Y#a-cbC zJDpu6#Q&oRc!U-9btoM?S*@qjaRqJ^NFt-NK1pKK7vQ4kEpEi^QFv0IT9QsHH~ac; zM{scJvwme;`Vq6mKO=NLY(HFl3ZEzJZ@m8cou7ZU@Xm`Hchlz`p7)N`7J);Ja3_70 zB)y@OH^QGvYiw5HP+YK-+s24HJsOmxy~A$gi zQ>6IJPu#Ts@x=_tG1qy;3iaht>aiqOpw@rl6nK-Q_RJVtN1WpSoFC!4E$@-Wfq!R2 z9+-yJ?!X$3%L9eycitoqnMA7laW!0@A}@#*P6aVuXkTR!P9=~yQH2vU7=V% z_EVLzpJsMRl5J>YKP9^**pVu>Kc&%WX`FIyXs)ImGA3Du$uen#uE|bF9ekQu%-+PF z+XuUoK8{Y(JeLRReX!~{=#NEyetk!!^0AMWVm}T1RfY!CUgP_#oNi0)wIu%)JKbU2 zT?xU>s^s7%UA3q|nhch%?5Wiv@8BVoVn?-sdhsnzz3Ce~a}v=hG}zZNc?)(a+EELz zW8ohI5{qi~i;&e{4DmJ30#9L8Se5c(NVO3&RY>OmF_yMy6THdGaW_f6-NfbQ#nOvy z*!_TQg`HUSzjnRr67v6J&wKeiX=`t+Rod6Se@}xSBkgGlpEh4Gx#_fJ>rOKa$LjN7 z3x`uloaV=z0~dZBDPJeLPQHL$VjK0KAw2okqcQCdkxn_eq=AN)55{R2(X|mmC z5_&W2Z1ELF9GqEx0oik&!a<3nLRYE8(8OXA%7137+2;9PY)lw^>k zqjFpZ{Z~k`@qJ^0?f(0W4>k=yKNtGOIiC0IHCgd>mISFaX`535KK#vcYpL6k*ca*( z`@&BN$y?@-_J zcmFHd?Q*k`^skWDJ0X!}lfRyT*v%Ac2s)AimFoyjDBQGktENCTq`6Edx`^L4AeWky zRsAH8()SF~sI7;U?seUSVrTSp3rWdDzlcVhdLY!MKPxxd&O$HA4GDdRhx@K@Z)8kj zUOqpr8NgdB=x8DA>cEl> z@uw&ukL_n>ZLn0M4RVBXc01xaHK&*C#wp*D|Bb6<&5X4|@FXIyKCRmiy7+O|Ne1Mg z6(&a+)_Qr&xCnXf2foT8pn_C9UOP~W-E0M+CgEIKQ-=FN5ov&Na)$$-tDKxg` ztXzpQ<{L${mY!1?Jkp>H+OO|#3QgSjLP&+Qe9eR5B=l%naZ)&YE#CcGV`yScQz&!e zS$Q?eSZSOW8%JgQ8|fyB_QsHDV^e6# zwzKjElu>7#9~)mx`LQ;T0wrw3+_3Z#-zA~EHtRQ}8<@HwzpU!AAE%&=Wf&Qph_*Sx znzf~|@rwxm#vU8LLj=wY;ofM%2a9)vxJ=w;7Jwe0$Kl)Taf{(e^qeS7fGr>7i_8?9 zM7Z&MzOvi;Rf<+a6;NG{pGqhSSj_`lr&?@UA8CKyp>o}&I zr!j+0VH>#mHsb2z&L0T<3lL}ciV=w=r2{&G>%TORW-6~sGr9`{QguR)aii`7p}R6k zmR{aH?G2JwDv5(9cPwFh+?G?2J$`V>SPC>4qS-grMo(Kvw5-df&0y_V&D9V)3k z5Sm#*e4SEdLjvrLe+O6nhMraQLO)9SPx2l>xp_u>wuiWa{kZ!iUCnTe zX*le&n|s(cLr|lp*5Guer+(Pw}9^)HYQwBq?7uba={Q$lz z`(@0k_`z=v@p{rwkk9Ra^kqVqP)B@xOBMd_oJ%^0pZ(z}@bQIrfS2FFJhy-1dCz;3 z)HEO+y-5cVzvnpvt_d#5ST0HV1Hk{MI70BQu1qi4kU#7nz`aJC|HtnWNOyfLMI&x- zZxiou<4)NF8!e{ZB>-a}H{vOu+^Tt&w3f*M&9kZdKF|Gz z{+7A{X#unttVr*BqV=e232esFfW0grJ=OJU^#%uNZ>(Yk{$8wUoOjV#FCKMi_N(_D zhb0WvcKniNs^DwPm>*Pe$6?tfG`S9=-7uh~yUn{qMC6>hqtnKb#rc5L-%b7rvAN?B zfowqP>86$nZxBXE%Bidykt+i{YvP=7sw*jv3_)b#(_ z$;_qE`J*+_q6*AccWz(%*pu>V8`&UgqH9VQN0Rx;@Q1*Ou+L*umn{dv$!9iQ#CPqS zYy-B(B4G30#+xEfmF|Qm>W>?Q2+!r0t*dfGmsWioomtvwH~Sm|;=1DlOP4g-(_v#c zAGu1?jz`53XaMm}`Cip%w?&r1FWJG^`zP^tRKPK?lu{{g%JByIqW^*?_o5tIWKM%7 zI^FiTGdWjl{S@O2wDVQ*h)Z?A;9=R;>O<8Om)9=pBdcNA!6N@zza0JDR;A6>Mb=%@ zT5OTGVcSZ57-=03jk86m-vU3P>a=svYJD1gEUghVAL$|DYZq8)|*^rvEfi< z0gJSH`fBb0>J6fUKDrO@T0JGzKe{MJSEt2mw?%HNHw5NIS0`E^`pTnsmmH7&7^AxY zBZ@X>ud5}!cvf2)B&cOw9D|p;M-Akfb=8>J(iV(`fPVL1B_DI-o`${|QG$J^eVm`Y z4++7_vT;X^o9RbuSs`MAWa|+*+!lGTzO^{t0 zXg#ogF&Cv-DF2hIEj5D6=Blgy3iDTnSzn~g)@e`Qs<+@B`ddWW(e!Vx8jZB?Tpf)$ zm{AYQWzX;Ap9maZ+GR8?9+1~1S+zEzi$Fb53C(G5$Z5o}AQG%E2bnuX| z!?5^G>#J#8RTU5i9!<0ao&bJ+>I^)2=z1F_x1mLLP!L93?ZcbIcb#9A&3kVA9_6>0 z$6@S#yq=qi`B}OXXeINakFEb>^pR;h5ocq~-)@w%IAY?oZ8kGE^`rXV$;)#D@zGUj z7{$@%QqOa8Rn9qirtw(sWM22a-&X2G+@mXIu@QH*@6L++LS9!xeeA3G zsETL_YtUGbF&{I|V2kC+DC=dsu~(~J+Do^a(A1lDQ0#TC5wt>F0#C%!qlbXoG`Fw( zZ5rXZeWh=+z@gf|(7G&m+;xYq0|+QeOz-4VIJusZv)b3yV&qCdsl3BicGN!bCXd^D zAWnTDH=9_&LO&}k@SSu2O56)7Eb!e{OL5h1G40<4fYNwQh3K#E*O%0)EPvVxyoWT{QrDOEd8{oLZPDLXQNQUl|D%X6mW(6nZW%%ad7e+hM$PWKW2dtQ2$-f+EUU#OQX!9Fiy!hjR z3={Fn0qKpwBKVV+u7+;SEYN8$yAL;?Ky#1$`Kk$sF~(cVTw6ricc%CvwOR1As)r^m z%gaoE!QJQ~Sc$F<>QuPHT_1o3jWg{-q%_( zI|H&V-TwBjdQ2=0>ac^t;YCa~Pp?jo{8WY|d`o$>6dDqt`B?NW?n~JOK1&GVWPv>{ z^82e#U94M0K8lgrPf;4}yCthKtSzh5uyBhwVMAL5)Gntw5OJkP{zG1_#FuEP=B(5| zYn2}DVcC>R7g>H4cTwA4hAwfsCvJ65)E%iRR4nk-z6?mFVRY~C;?`x>)z;hhoE{xe&00eS$07a4!G)vZNzE5a@^*{!aOHvF1JxDx;6Srpw;g}ZXBNsfDW z>XQyw<)obo8b))$1`hYGh;T7yVQY;aUL~V5%7TGMBefslyINf59v3lOp;bll1mTb* zb7Oq`8h+|8%vEKeR?~XdvC9n6wCp@6)&!3)(`a~0mistUIaXznc2~d%PX>Xrg6eEQ z>s!b!;P0}^)363xFi>2H7O{6Bqk+0xK;7{2uY}a}h&&*bcAi1>YSO@vCI&LFVu3(6 zh6B=Vo$6sj^d4Bbc)-=;vQB>Iq1q!DYqEEt79YE$MXmL)y7bg?)&&Fqu?lsem6dEG zYFmz0u_ZJYYDAKv^}G&fFzMv+!I@e~G8+@&hbDsCB$w`nZ(;n&CLp>s*NjhyqS|b-vH)Uv@JN`Zos2seHRUQ0kOCm?<@aqZ>n;7|YnEZIP9Pu%G zbfYzH@8knT5)z=l-T(bBZU!B{8`@%@IPVref?=KQpmJ46yifC(!%_5y&IADi; z5VewW4Z)+G6~hz9WFgxC##zC+S$#_##wc2QxR!ZABat7B3hG+MGhrIq#ff84NNX#&dHHrN(ik!C9X6)f@|ys-tvbCyNk@Emb9v~cEZ@pFYY zFM$^YQpkJ@C*B7YJE95^m!B49QRsh;(slCX9l8XkUQ9zm$0{znXIOai~RlM0^(~5Z* z7$VPVS_u)H%WponK}Y_^cKFY$#iX6-@K8yH@6}Y_;y$^KtdRPpPp)nf7Y{InGvai- zeuKjRze`~konkG(w`3-=rXgztU|nKgI$wWE4!oqf&@UYfsnMp-;c@@vMJ-}io`SAz z;eZ7r8>eAtpMbZk_>%#{LoI6d^h;SW{XzY6$sM{QE6p(!PF43!e;{gQX#|5P!mhd`rk9@RuHnRHcSYz|2d<_IdPt;lMA=BkOiz zQNQ$Uw+1L6X5b6-OBcH-|6jXD@~-_Bbt3hb z-OKU(i|&3&zM^)begk(=-^9O2lrSS8yZ9H4il;CA9uNN!6D+5bJ?LY%rxmh>S)UDl z-R;p>G*c5JsY80N zW*_*w<j3_5ee? zvAQfy<_huKJbEQ(ol+p3HOt)gx0QO3tHeHG*M^r6TX#yqhi6kDrS;&=8gu;vdRWMF zGj~m_pKyBoDLgrKscLG!Way@v@gX`Zl8)7PG6gvZpN%jhJ(;545N9@wX3Cy>E1Be9q+ zK=bx*!~HM>0(F&e3Kc9Df!EZ{zi~sy3C$|~cim3ZqbAf1LX{a#_%==Uxe{D{EF>2s-?Qi{qi{@HDPLngUOxsq`=gHLfwU6eDxh{=)hFA)G%;T~% zO=v5P*f`FaiWXN5la$4BQUk1sv}GSc_8=WuCU9EDVwB_GD`QHJ6kH0ukfiRj|7Gl5;G-(9_2GB#*)y5Ucz66C7Ixu9&}!?kcNXU4gpXgE}qq zCln<}u|>(gFSJPK8^FDBZq-8nm))Gq=M~J=yT9lELW_Mam7c6E@bg8YcIE1Wl6q>D z)sN?Ca>KKZtk3vbdfx0ao^>m%^t7^3R`!?CgBvSX$HS|ndzH!mWS!Ap={BImcUV}x zTRaH6&p9p|TspcPj#<7c_3<0n+%#}&XP_nECz+RDSTxV_VEvMW0@FENflU$$gbw?L z`XzdNGJNX%iTLKhxAqawy{6A@-GI`oS{yfYByAwCKeA~diW6}nRVc-ae-i##*5fz* ztHUw+hwl>o!}m^{pYofaxQ>g++RNspUKtBKJU^17V}aNYrq~fypnu-MXfgV(LR;32 z>8*uYd$as(iCTOKnAg6&I#pst^KnNf>ux{l-gpp^580l&RmfV0wY`MoV`1@$8Nels zm1T2KUd33hHjeFMGqHkT#nm_(rsE06*dmN%?0*?YaXmBMR2HL+9B6=~OB(MFGX02> zGsbYA9q9A7emnfzu>~yjh=<0UK6cuSjO>z|tA9-SkuCDq?{kO+t&u*e@zgA(lGO>@c2_aetqGDx`ma$YnGm5thAD*ct~Jqb4yFLJ9D)9i{Nl(`%8GB1==a?25oMKH9O>N!Q#$~gH&+5$!^fO_CVg7P zX2(_M@4zn37zb@3xtn%zBjg(a|Kh}LS_aal?s(Q|0d5R@gsx=UhLuauI_D$TJz+uM zRJYL8h^xy>@-r)4L(*UpI5K_!)>mW2D(A5BH8}g@n5}{s)%DOZKS5pXIDR@HYSBV$ z-jwx+_|b5!eOL);(c^nA(sjoI!%Ac+@_OKNjibOWulGb^Nh%SIyiZ$$i38z#JXvm8Ez{cx5qzxH%H#g7P@yg#Y@ z*X6dunjYp`87j4qlz|vwungMay#qU;d;*%!D(tMW^8N|BFA;Cn0&bHVIbww%wxQ!{ zi$%crhmT2?QSJg$$FL#>U_ZQKJ0m+aiBnVZ6!{jWAXX?0{wk~)*h6Rq%0%3JBsYT@ zykHDAOFOv#Q!($7q+w-FxY%m&4=Xdnw4w|vGqgB=8s}Ghsf+#(MkJFb)mB8>VXw`< zTS^`F%qc}~V?meYG=K7^jI@e3fv*-qRv1?PJou(Ve+D`-+nBy)=CJbd;AyawLU&|V zL@LQ4e!^lQ9#OK`iLkB`59w+6t1~UK=>)!I`SCn0R(YP9=ckggzwiOo(<2mY_aec7a+f-?ruvbY;D{=|uEYv-I>P;aZ#o^b-dhn2k=9`N5$9hTbc zG$LW+ocV6jQta|(k6kvhm7^!B^Ic5*3z*-!t5=SmcHvun&FcKsjZ0Wjy)Pg9+}$fI zXa`_nMfdrB?8o;fZkM{9uZ^^Av;$LWduUi$I*66GDrAM-{9Lv!#`zZEIGJzH=X*^br32$NtrQs}CR#IP?yl>|4*^J-Dm}vL@s` zgNTIb*olOW*GBd|MEokoU#1}j(B{bRr?lVcEtTqITn7HCaWnCEIIa#X zVaHg0dy@RyFusW&_UwX3eT+8VesyVe+tl6wb^v!W-ZWl1;WpQ#L1WN&C1aEtC6<2z zyYti9KJLS=V~^&EB$;eNIS;*uM&AjHLcMQT>A9pQc^6U_$!4YF!-_v@eUJDilE1}U z!A1WXr+gB=!F|sHU5Ie0O(^rm2(NK$8Fwe6zjP8YH8A;C9x(r7%n%13>E__K0h5{z z%xagFX_|Dyze5gZb-3RN0wc?HnHgi=)(ik@vh3s} zc0zR}pTIlVM^97@BlpJ5qmy~Yku)%1bB2$=l9c1w1a6R@SNuR-Xc3)_OTZ4ZP+zQ^ zp*jBptN_z5rCRmS(!ozXIjkgVehORvVL&`anY#+tlg8mVzf&z@EQe-Hyst}j@ykd5 z!kM#Z4}Y{G&o-=l(ogFg2Mb>&j3=|ePP_nK7;L2U;k`jWqCK*lsq)yRy}^g0--j;Q zFlSgb9Up+*6n8B&jI4h6Nyj%`rr>GA%0EY#b8O|Q(mh(vnK?cayeF94Jy|HS-mmK` zW)FiiO>o`gG!eg#3BAQ1`ic{obt|+UQ?Q%e17=3{kg-Hm`MI6~)z=2(&o2KG_Hhw) z>My`eD8jE*&a7Ul-N5C|4*ca;BEH7qrdyw6$`;7MO6n5K% zO^*DIj{%pgcBaTTj((r zXhp6Ge%jNbnq(9D%5;Bi34{Dw}13eeNa04Eny+CUEr5$aBS&-rIc~b zE@W)j>d5LqO)Xa023$sjRIxOA#Zv8x3fRcCD;Sv6fE|d))b%tgTSx8uXAiw2e6(m#}_A_7VkN%!GuKX4B1$JHIgcjYr#N+7kVR_+5cB+`0LU@qY5>iUn>#NA$R2 zsZCc=qE5467G+xz`^GKeucn^-!Z(8ZGU;7xEm%eAzEtpBt@d$!b{)M5%QMVxPH&!& zhlL5t?HpKc2O6{0=~dj-!n}}gqxK};NB7S_Z>FG4m$DW|l8+VMh@%yvp#&vC*Klww zt3*wp z!t6nYxF7!pRwmb3tO;#S%P@N)R=Rogx+vcCM|d+Dj3-q&DQ4FREA5iI2hNz%I@Vgr z|Fvl%7&@u`q!J$XT4v;v>fO2IM@E?Eu(Ge0{K!n9wN)#Jb^m3YFpp@`8T`{)lY|@r z+8pd&dRqmtof#`AN9M5dJS@=tnm@#^J-CCcc(BZ`UU+k8e-t<7`!@6XzRkLmYJF}R z?lp?I-&I<{6`ts5f~+yD)b;LE=V?8YEkP&91uAOzLY?GnXoJ;yddgkBAFBfYg{pG( z?P5NE=3`YYi}jO^X+mU(q<)PW7%`jGvb2Toj@X|#?=yvdQnhy9Wk#(wc+M{ksSH&XPABLnH=#0V%uo`@e&a;nIHFGpiw8p_RT#2&Z51w1d2+ zwGg!mc??HtEh1(uA)FD<`4hskv}+@+$!XV8zY$l&@ZhJ~K1TkFhrrOW+;k}DNfZV= zT7I76K6~g;J=yO}JHS?qJ;kD}wk6~CQ0u=OhdwdJK{EpC?4sR;WW|Taj4i{6|0fB! zPBQGg3=8Swxzo}2Kzc---yn0uf5ljzwDF|s(IYCLubPWkm|D^)-tVN^n$G)H0%b&= zE9k#Ww1rjuqZ%4k0#CaWtvS_V?V|RZ zL%&@W*^^>xCY0dilWNnAbzygc;Js8l|z{IrL%T#UI(MeKp4C)F+blWL=$_LlFD zpVexY?kgX?DSG`$^;oQ^wZ$7_3~1vOj*FA<*YEqT)ueoMWfJWx99KTtkc?0M(Tc~Q zSDC=gcC0|#yT%6e*ZauQ@#G=INZyLym~$gfJ;cOm$cz>PpD&}0v+*OkhgyJ#b7UXJYAe8_ zfJ?L>7MwF`?F;XuoK&(|8!LFpv?KQJjqjUwz_aT%dgrt1?YP0)5u%ENSL`3 zj6z_LjE&u8MjYu$byutjqx9i!s!6lf6Qz@W%IH=)=4SE(kbb;cbimg&=8JUALDkek zQpJ<7Q|{c6{sDYZkG!$J5ODz%6Cl>vF{;J2x$YxCsX1#{`3vImtJJk~2ra|9q`KY1 z$_?H58-|tZy1O47Ru*@=@%`%VIRBp7r1sWzjZ0$uE_Z(W1?-8L9eZ$fez&V`Sjp{f z#ow%MKmN|?7I9~0w+nyMyIb*hdbb~cr*(_#hZRe=3xDIg{p*GmQ+F%A$8`JgSLhZu zxY{9q<=O8Tg8qN1CzIo@j$8P=WAw8jWhBs~4r8_B5~oW-@J+045352D+pw|#pOg4p zk53O9Qv88a>I(F8+eXnjq?`de9M2g~|Wvfp0vXz6U&i6_n90 zmvRISDLe2x4SXqd^f_eo8&bSDvVge{p2ki^Std@ai>g>&e9rBVxrUU60Jk8qNcG*W zt}qWNkKtO#9LO;P9u|g_ zh2T9TT`SU-^E#&Vt|=R9f^(D8Fx@F>Z(PUSKk{IW z>F2nG6;<4bZX;$qas$cG6pe`~zO-Rhl_a5lRdltnqX^$nQ*D*KUp*UrAFMRuO{1l* z%wf-bte5Pj(fn#{{R};N4?YvhLzV0BX)X^Pt$3v3(F%MQpk+AAL)TVvkS6h4?-=$_ zjlPE*nsLUCEc|-B;%60?;UQCGAv`tLIf3u*#G+;HJ*ghLBF zQ+-r#k<$`WX^n&C&hS=pQhXY{TSNLb^&Kt^zA9XnS^n`QZh>J$_wbu|%OlZv=-mSg zO@9c38*}79&F+Eu8Eo{~OqMOFjj1fFyub9?QpCb6m^p!{7f0BOxa}NgMR?myh+IR& z#5=`^h9NeGjPwf1rFH_^zNdiiGPOTp1wL1B2#gFjs@ayK!7#_oU!e-=p1D4s7w<(V zY8JjdnwlhwiL<2L1Jg|`)U=9aeL0Y5hEJ3ZQpZfL6w!4V;lhb9hX^$*1HI*A&mUmbxQ4Dbxd7) zzwT|=u75V&C^m9-2bGP>C0%mCJFo?&nm$Yi%e}?Z1^w9roi22vUe;Xc2 zi}bDTQ)qc(1!TXCSm(h3#H>TgD+7LH4|{Rr6Y!A>FHUg1mQFHdv%13ejH?+DR%Pnx zyZ^MdNj+^d-@o;Kz4SyeY;Nl5T}Raw-d`aP8I8?X9A9-|vxQBAE3kA)Y6{r+Sls5i z7gXlw=Ks0!_Z@s)sXAM1s^At6`-oM6#ksUxFH^RFM&dZPB1$s#m^zt)d9BYscuF;< z1`l7TO+tOZAifA5g8EE}%i`ol*#3;U#)3qk#9}G~k0DlsRIUWRgs{A&;0W@>;a5s( zeiJS}iBF!NHy9#S>sH z&(X7N4y~Dk<0+}z+WD-;1AJdn86An#I%T2R`Bg3a`T52|SWmK07qGgEsjChne`ji= z<4$DfEYe$oToU>u^;YTW1Nhy13{S<=j-#C8|8VbcSk69B^IBc)-3J`zE`P0MxZw%C zkKUvxbqCf<&L1vRd^;R5XIr16a~V==o&D}`{&b%eeu6BKu7f8xdVi^Yha*-i%YAp7 zL+F|+L+RS#SaX)kz7c-2JbY?V_l3YfbNAMXbsO)7w!^km?t?WlCl|HEKdj!OCQqPL zVXoim(Mp z^?=tAL#?cbgbDBN5~o?-H$gnqe&3!tv_-C1_q0|6#KY@FXOcVwBp04HD8;6?qZO&` zi&Bl{ycBuEZ`XB_7fz|GQ>n#o({E)ou1gVjQFS}XD|;~R`#FsL5;mgNr&o~N0#>jQ zUHx+owJS0nEQu+|ZTLVsX(g-MkwGu{=^EN!R;PY}Jtk6OY=2~*=|e`O$X*hTPjJ@2 zdb}CZ%q{T8qKp*etMZ74Z%LIOzc;O;Qhxk)eXl{-R}KaW<7%L1JiJsMIG7^WZ^-O; zSv5mWNQ4h4q4b76hWMW$Dr&1D*p+mf;O}t<>o@f^Bj_DIS~a|8DuOX(g7y2PLfhbdsL23rF4| zY`1P@?`g-Hq0h=V`A)UI1}niFz0cEYBjiOm>A*Q0x{ek<(k$P=ZKha%Rcs`!KXvxb%1fUmIHGvDPwwgPW{j z={}ZAR)gH?2G@|XU_y@?E%dvz7U6wVgK1!tV{(bgE#mTxr>U&5UX(|z06wZYSTnpD z(q%j+5`In|$mQ^bgI(PSTRJq5TqX}*qWjMG8iCM5{=@y@aZOS{3IEDLMYy^EM)59q zM^(0ejuqY0?y2R#)tJ_y%b5+neTG<%6YX5h>xVnt9?09AFwMVjy$#oTfh&<1UGQ(=Oy4L`E(e+QJ%HhN$=tS?p!gq9C z_2Gy`(gO~33%qsF(ni<|Z)bUh{#@C3J6#RV^C%CQ9X`P&sB=~?*>9hxlJAYdv%PFJ z#?TGp#jtfG9@(i*M>`<`UGDV6K-;3ZwglE#8aZ}ceS)n%*mHm{@W^c*@~B45xK+MQ zPtO@|3~qCHprZ#Wtd;-a=ruSp9LuHhnjJtLzu3a+ zXx-h0y~iW}Wy=lpG_?5j(zBS;rD!jRS@7S*TbT)8o!$Tp^8@O`hkW#A8}Mc#vIel6 zBxi;byOg}+vZoSPvwW=7&jSPHa*SkW0@Hr$77Kh9cEwVw@7xl(3f2$k4=@qJ8=Q_m zzeVu=)8BnSmwy9V_!x@07M8E3-KI7pII84UXC~e zj3(o#Z=0XqPmqR`pTItkOlluc{}-V3KhW%(`Iy1flh^ljMg71(gdaFzGegS!9@u}8 zX;yIRw+$&pJ@51}v%Uo*#^&nd_&c0wPGNh3+zXD!4ZwL*K0tkqEbo4_eWzA7lP_-S z0^eQ@@WVz|uV{kr4(6GUk+(-?qhJ4`t)m7NE0@OxULP(wGb@;+TNkj8lD} z-?^2(bLa^xS_cfYu!wD@RjI0CNcnsBYUhejTJ?}}Q5CfNd2fRJ*@WJUeD>QUdJ=j? z*(B@$mo&2Vb~4Ih4{5w;@GJBiWMR*CM1=6M6KK&1ZWAoiS)DT=-{s+%W+n>WsVBV- z9HIqiseZd1aYV@ZU;$2HDLAZIS6WarQSYVMkS+b+BdY$A&Z%!PIgzKtM@WM11s<)p zVO)SO{d9cpXXt79p+$`(cef%u;ahA>3bMt8*f5tJ^ z#bXT&D|d`juUQV$_aS)C_Z)x}pyvvXsco@o9aNHCwltK%SDF0B#8k{l$Z#Yz=0n<< z%z@0PhpdQyf*x~OhD3$$IjLQ+c-tND>jzTbr1i+!23ps{$}8jdT%gry4#wp>OmO?% zVzt#>2K0!u2$6UoWg{bo1;Q?>+j;MhVpE-?GaO(t2r-^-$#yky7GC%Mw+z#Sj6tV8zfvfihvNP6U4$vx7cJR}GS!3vWq1UYKTgYbEKx-zh6NT;H zE#b)kcx*c(rR-9XFA;0ey}n3h?7Mtnv2&C$z2gVIo!!}NY55_<%s$Y^3+{53+n~(@ ztP9q6kl6^IxyFuor*0Q~r4WfpYt41!&th$*w80|@B{+p`*ir2BV9%ue<8`bw3Gh!O4`{uQd`oY2T4cwBfSGNv8D6Ih9t{V| zop(C#N^>C2tF;y`Qy4#@b$*6UfkvwKP?c3m=%KmzlbO8xC}(6`2r-)qTH zI{gV`*aZt$W&A8_X?dyjj`FHTmYGD%4g|^^0#JcQE9!@t5-}6?Y{O9nud*$<2#&BdUhuq~^{!hA|ddc8hjm-5zVq=FOBCgAf z_e3samW7=N@gIruP*`YboiLZ)@C`}Fdg#evo6gI`BIv~5{?7ALkMJ!9IXot`kPd@< zIka93=*;*Hi@DH}AY;F10lL6G!9V)u#Wyc~>&fFj!9SrTq`W=AiM+Q9zbHfI|JPeQ z37espZE>tR(**?Xvhw>&f;Z0jk~#yHmz%VmHl#ET*!wfgFQcU01J11>#QziDqbZy= zix_3V3a9Zzn6bKGMVh&$U^`aCQytsYcSVfGhmyd0AR6r8y&?V*tJ4K$ETQH7aL!YN z->~q3w?fJfQ6hM40;b~K1K$JJ+5wFnj#&0W;Q!CYxLbc|ruF+;YoW!i6};Jgp@mk# zYrv6^W~MO}QWj`@2~>AJo>=x2HMA>IYUk(pIAuwU4QX|Q#nK2?r(F3V7`LM zp6(;>a6+4=GSm~YWP|=Zro4qLifqt)}w>()(Lh9-m|Z!OX?%JN#zOUdtIHtFFfBvl>0Et+v_4!X|5z- z&*QlZE_+BwdJr03SlJm~daz23nHS2s*Nj0Cm#OGsQmDJds(l}u-CQ9 zZFMEpR=YUs1(&bJTJ5XbQ(XsbhV&p_{Gp#Dj%kqm`6McvPr3mk<&MdSe~f(Ob9jQf z+Y!q);<52IJFfO5nn=31H%UTVgL4{6I>rv6Bpc2d6Eh_4NL_u@Ap z#yMH`gdCxF+FFgXFE2Bp)FG*&Kdqw?$2PzZoxB40z6$=&>UE-{CQE+&mhxU+S6=;R z)eb})rNz;cfb!*jfY0f^B*>vgsa$5aR5M5Q(%D=t?quLXmOb|hIPO`+<(5^$mWku` zs&6>~`MOQ8U+Uy6-JN!RE$M|ucvSIjOEw|7ogt$R=VNufvG~;Syh|^UAFI&efJDr> z;H#|pzmF+bsqXeIKoCAwC3{lT7Ijab^9E|8ej&g8GuZHqTY9x?4$|{Nm+AY_+Kug>WA7uT*aphSqWPCj`Ie3; zC6{SkBR@S_)5w1>@)_ZpHwGhI^ET%RHLWTH{r|glm>I3ZjNXuPeKf-1wTmI;|BNSC zchh`=Y!Kgdb7-_a(r2vJ*8azGu7pMxjj}QD3R9nHI2ZEkHnbu02x2aooT)`SSm1d| zyVS)VXTN0~#Vo5}R^K$(irq;cd7i%mEJ&-chjAK%5^>^FUMW2o)BV8n3{shUlY3RU z)y3RP%iE4nw!^Q+MdUCGBTlRyBao}Ly7(H(J0$o%M9ei;y3KBN*|n=fh~JE?hRDo> zeW}JNz)l!e{)C-RlxP=+_sCsr7x6B`esLw58XgmOg_L(R|8`=i4=GReWI<}v!!H*5 zKe7irfM{y<2uUyaSE6EU``_iZb6G+*+s^Ih-v$z;J{!eLiT}xX*KD*)JZx~t6Lxts zq$NaHLq`lN%~2HaJ@@p(tk5oR-Ry)GB>?ki*tE|HUWIu&=~qtvMO~B5&%YQSOfl<_ zF-}!hA%^Yx^_u=1bZ7n<2TJE9m)RNa11*oC;2dP9Eo8KBtC4MRqDGe!45VFxb!p8M4i zR&T~{&l8>Uf`*=&S4ZsijX-{uH@xnC51yYz7edM;eA?sx5mHoqzJW}FoNM&L6y968 z4iQzrdsCdkj(rr>Ew^qKUe0pHAxqdlE(kBj6^p(@7?F1QzZ=-R%#KLh1d|&Z5KFL~ z_HvRL88C(08c5dKJ#gN{wFu25n-LQ)*vU)}hb(cQhC0&r%wBbyKl zZ9@rZFF|f=X0l;3cpNi+f*JAU1o{K-HhnWIh(m57!`6m@*;^A(k6YB~c%NG?5Yk0g zum&pe=bLC}q8;eT6&IY(`q^B&JmiVATc_4a{XnTaEHPA7jVB?tPbjHHUF@0JT7fYOA0vwXLI$Y1O@?3^Ki|3TE4s7O6X_X5 zjH9=he8@xf*@61ppP2Pmp}A8PI}dzCXWr1x%-+=Crn=Jm-oL3#wm?SwB}$6C%?|CF zY&_NS(iDqk?%AO7H!bVk-~6v5UON4+4Cq^5!*8|rd(X3b;9k?mU^sL3+tz)q)~DLh z`xMb*2iGUnnnuFLuY$_E;c3=){4WmVXHe;1z)N3f76X_X`A>ln)-Jm?O+67=t~T8q z`l}dSBaxFlq)b;=ewAaR`H|LP2-braAt9K85+c8U!VLJGcIEdYkbEqztG~*>a>wJ0 z|B7@&RauDGLD&hw$3=dJb6{WQtwQsp@;78pBMvuY-oxzw{v}#nZHUGBavpI7hVo3i z)jC_r3b78Tlb2bntWanMHmG0O+iAq;12rcL^?LROE&5bB2CLQAp0lJS1}&TeUfeW05ifaI3pMPv(?ff-S+k}D70+N7 z5Td2!P2C0t?C}MlBc+`)fChMhKU!A~hu6R>$a2Bm3V*dmOAovjw*V{ff_d{OaHVJ2 zh9M+xgZ{7EQ3xN5XIW7B;h^0aRBju*=0cZx%tKO4ti%fKkQa9G40(-%%KFO*)+d0_ zoU&jH!Om+0+9)K(NzbjD55HLp6Lv5lWc!v-T$x>-(NOD0d6%bI@AuPA$L6h--gVsV zqk0pjbrzcOXETDz%)u?t79G$Dw*Yf!v|Mntx=1=fEiFMMZZL$ni58yA7taNiV)W7X z{cPT1nVdYV%~9eLnjbw#SpkrpkUy<%+0L?4-8aF{YQST4bMrGxpMihS zY=388Cl{ARGXM;vuxP&vmNd~dRio308lW2eb>JB4NTuyXemlH>a!@%j@Eg3%0OI#K z7t4De-!H=Be;!uXccF{ar|uqjFoR|=`9n_mJreWp^L~$;W#6|4&y+3fV4r0UBH&6W zVsRI{hmJx@7D|X|nmDQdQ#&p+TU-zMh34g>zt?>Jo(JFfqZQzdM!doU5-}>$sy3z! zj^7J*Vxu^1*3!~sH?7r?$e)IPiToK;){O0O(mT)Ypp}uVjN!SSu z9~oeePX?9wT4Y7!ESG0<9_csU74cCy0jmi5E?YOj2N9{3y=Q`N<|cHv{&B_$wH~-B zUvfhINizBnBYkx81dU_y1Tw+@@uD{Ondb(q10|jB!VdB_vT0|Bl^R$ju=9zHkfl1` zg>Dqfy-nE*!^+(gQ^(kqW4CC>BKB1o@gA0FyobiE3)bU2`H5w^{i~cWK}!fLpFrL# zk}CVt?wT%po+ywg3xdga)9CCd)?lxrXFnx-9-ayIPn~IskyAK3wZ_Mun>uDXKXpux zo#vOwC4f;W{@Q=j=%?`P=k>UMCuK9`kry+l)b0<0F63HfPcVf~FOs9d;2jLfbmViQ!B_jgxQuN+5~=qCq+olg$vx85RofQ%7d zjCXXr6Xgy)1T2py)+LdHH#%j?qc>eDU8%JX-*%R?lAkWTc%H$IZo|kT?$Moe%tYt6 z7HH?A=kPRPC%Bh2HfO@tgNm+ydB5fTDLJ0(PQ*1zJkG@398`w-2$QG1W*Tg}L8Y%x zFW)r@DWyIz_J6%xi7_`8)$j#meG6>;t|#ob zacacliGS}+>4Gt63=-K1*!qLY3lqp^4Vyh77QCMjH1;n!fC-gCo?z&r*SDuY$4`(xS3ST; zwulKpi7qR@fQPGAptF;!4 zL5*&m(!Li!OIavFI*^Y5>vqZRV>Jr&yU6@uu}`jVJ`5za>Su`h&3c-A)f*{3EO#6I zg&nmB7EZ7T!aqY&Paz*UAv0np$z>*K=HcQ;h-W}Au^OxmvE+Z~T7tZ0`YKiLz1hk7 z44G)_oO9|q&pFlKR#ushlJBIyTFGk%+6JN$Ro^qF~_wb|1gu)E~?xw$jxocMRO^^R$A z>&iJWpxj&;FL75Rdp$RLpr#zPvLHI1we}eq;t6G4#fQB*JA)PCLa zV1YE2&&T&T#4{0AVfN+bRN>mo%5#?}W_gjc&waNos4VMcMe!1?0kd(n7qa>Hx-tf%0aE!I5(WuGJTui zYGpy?cRdyTmgQjX!5v=?NR&&nmF3}H)9(-`0nA}8#neJpj?jF%%VME4mv-rs}!EG4k2WQlUUT_{-8aWtso#c_Vbu$`_%v{6(l zqwIv#230-988cey4|cj!n~v7Z+E#%`a+3W|bga!_#ZE+uE|+Gs(7owz%-Vq*704-X z1`hD11N=~!t65l6o*hr$QRU3o8B_{-X70$ z{rsC5Ego&Of7YGrJb3|QX93GS`AuYuLH_FwDucj^NuNIT&8*i~J5!rfWdJeX|9KHe ztclB+@$$iM&bTRhxX797%&$OHJ|cvZ*y=S?W$f*KePy9=&F z6uZ_$`Yv)8@1LsIFS-r8D%y_)b-F5N^TbeS74H3L>^1uVNV)&fu(G$&tZy!JzB@57 zlGbv{X=qB_1!gnZ5}VkJ9oc$ps56-rZ<0BkeOx!hB>s;Ojw1M_-kjh^TvDYGh@7*INb>(aqF~g z=B8xtra^9JJVkt5$$OCW3TOM1TGja{c)ccjg{u>Gq_zA>eWZ2HHs;>MjObxm84JX> z%ni&;DsbX2tY$W6f&}J6=RwRSuGCR!MV2JBi(9<90(rpC#X^EkYiS$2apsI2JaH*N zR#}?S?3jPH>3zx_)Q&QN#doG|XIV)vqNaJ922F*Ia3;wMHV&)BnTn0bT*Iz0^=)EY>3#>YYQ^(l2!~!@=Kd8XcyyF)a;_ z)4)kBEk-a$Y(mm5S*Z`CwQ#V2ZFb)j`XGu55T?$y&3;{0ssl4x&ZA9j@1IAjGI5o2 z`YUUku`kE%!jsJA^hmB}BC3>{ zEnFx4N{chp!TwyowXpV=*WAX?5@bI65oLK z+Y=PHLEkb&Fw)g&27ZyS*fxep%WM9(D}%m;e!kD4i(G9n+~P>95EknewW*w!E7d*H z8q|UFRhM1f8(aRr-QVj=jXud@5bz|lIQi6@xogndq`Ur0y#ks&Br2n6IRuIaOzWn@ zn=sDlaXS0c)+x%(6R!3Kc&EZk&BDpC99K}}WAH4~d%0P0e!bTYiDK=T?cho`M457!*pk4#eob08GZ#>w3*l9PH^7>3pS_S_2Wq%eo;IVyz!E*88$|f#V;#` zm(#2~KJzX|aPG6SV0rX0#8q$(k|Bd?sS%p@z>(?-gtp8to9}47k3%0?RXY9VG8=NyXX4M zeRiJgFU$(OIB_|cEmyg=xm*F+>Vpi#aVvZMSfRN-KfLd%9MxktE#qvr1isFz3Je<* z-$?kYY@=8e2pN`-tu)d2W7a#J2N0!un+mH&DVw{r<1PnzYE-CJ8`V2f#{u6Xexa}! z??!c{cftyl!IcQ5t17Wt#M4oF!+(9VZeJcvePY_D8;h+2OeVS z)T4?k-HW+-5dC|)<70e#`QP5S*LM@xh7qgFpHJhLNF zvyk$yY41JzER{Q^Wr_ObzhDKja=woc2a>}Hf1pgt58;{gT;wwR#XiC?o`Gy&BHllG z?yh%l3Yi|NbAB}XD~Hv|XX}uuY$F(NXG_NdGYsM^WD2!vV`DKPX2K#n_IzX@Br8PW zff2T{5x!x}!3rF`LPhU6SvelT8T=$|iq2g}$Og`26SQer`5k=m(J$oH3!V|yK{iP} z$!iVBKk`tRW%DJC>jD`7=K*Qr;LX=|M2~+FyZR+%hpNlh`DEn( zOR(zv`G;lYsfjcV4IrDkqO4Qx8Y5bJJMgbH##uq-?nx6oJ1;3uT}FI@m8>!h8amKF3$Tisb0SzBF_=6Caz#G}5v`u8h( zKXDp1f}y015#lVskAzV+WmAIRXa%0iz17E=&pVq@-dV(@2$)r8oy%0=E-wH2E|&AT z`X+pGbCAC<4z}K(AEYu2T4ZhpVg$@`!(=WHRe0XYv5bRt{R>Tdo!Mo>yyvnelvxum zMt2189IC>)gsH2shZ%h(wLt&b)Ej(^E2*B`f-Q~@yUv0~9BV-i#anmbpQpxRla+US z??No4uz=-{`tEQ7*EjRdo zS>|=kLm)*0a}zXel42+hKvo)h(IVK%_{0QcI+2w}du7=F6Rfm5z6AX_4xj%61i=Vw z8Ws@Xt+MiCT=N`!>Q@f1)6crMklc?r@OIB?!`i#2TfElv&|xNS>l|K+6! zLt`8e6}~uLI)aE?PO~XgL3=I3`viO5Lqw0ek28{2BC&4rS~LvdLWmbSbP7IGU~Da( zCh3YZu@}(_3Y5tjiMYaE30?JS$$wG66Jm-N`u1H!^uWf9UJlVOo@eHaZw)p$@=i+^ zO~qIFR)G;X{LqG>L@o)LNiwm*Gh?C5meEz)9KV+~J&ky*)0^uYHFw;NtP*GG>H~cl zE88W8n4b&>MIdZ)?1vomd*sY}^rEc1H#W`s(&*jGI24!%9x+IZ3oNTdmQ7w1~)}&!+@G%ysU`&LPVZd+~Wan zYAR&OuyU2gA)HDp0KDRerx(b3YdN&s6s&mkCN@a$0?I2K>%VnEpiM!z>{U$NL#t6ke)Y{#+71eD)}4chn#CNx@O?kEI+Q}H*O&>UkoU@;U&ndgqUkEiBSHqM=LPz+8(Gj z%Z{-dN584cqBG1My2v3ug9Fc?m+}vP-@hWH&cvEyo&ZC3H};1LS|yBJa~H7p60Gl4 zYQ9Z$wrCu-6+XI#xM4h%gI(Oq({kqF{x_39?)%t)GWZ)ux0d56y2mR1t73bd4%rny z2j?6syw4rivEMCZwSWtm71|K>LKa}=%|{#qIQYShNi#XWBA|RY7*M)3?!C3{SpT$~ zspG%J@pG3UwP7Yib|`KKoipN|eS<8A@}mVYW=`UoB4_`_srz;g{u6ylGA(Ai_Y9OgDM_lwvn{V5JOitKLXb;%s`7iJ zTfuwWHk0l>1DOk)%sz%(d|UyvQ{tHHJp|+0`!P9Ly)0H z6$!Cbtm#$S84$%tJ({cC(S|FST#lUC0cHO{K#`*SfQL|}#!{k$7A|Greo2ON+_#&SeePOG`EQr9)j{USWy6d&2) z^vKo>)W-E^m03JTj>0x|{Mft^$T0!sgm%xZYC!3W zYQ7{x2b2%`BYOo!8pz7X*z(bve=t>pNV#wHkJcIdZFQ{)*a|y#ZXndr*33 z&8X6^1}?T~*Ye=;S=1g-*7b{Z0mZHTy}w@w!uiSCniWv)?bjj3d->=qn#TZn3k)KT zA)wrf><1UZt%sXckB-*(cu7BUbA3SZP3lLk!RMbQb#nG)J=Vs6@-(<)-D_yIYqJNG zt3Q~Mzn*JD-e)-m`Ch!(J@n8aGciwg9fs~Vre%qQPwpk~atls_fB9&p9W6%D7RYDE z5G(8PEFU#4!!g+9OwoQc_WRe_z(y2+{Xd`-OeR=2_`mJZvA$#KDadf2dR!R04B6|T zIp^x+#h25DJuBlOQ(4w62|Z*p?f-c6Kbg@AUt9B^229xV&-FP+e_HPxy>H{kp`Tj* z5UR0KBxwqx-g1s^Ncuyl9;4o{P5*jKv#~k0IiP&hCj{+=64d1PeJuYfMC#JjaXzp# zSOu@JpUbwn;eVUOZL^0y+Za&Z=(D-8{`Ywg+e2T9M(ba|zRK^%+h+4##M9M9uAN~G zC@-SC7)h6RJ7&_Mi5c2VazSR3m1|X&UoF`~3)g7(KP1*sKJ?{{Xag2yrIVsgMlbaCL*U-%Qz?c?*p$G+ZpZOSw0i`m&5Zv zozTfQUoxSWnU&=Qlw%XiLPHKyFiwx%n9s)(aXdSqIQq!9Bj`KXvTHCrO1FQsq!=%ghw9=JzX zL75N8L%pq*xkcy~M>Wl20t^iAF#6pP{p}20!YJnSKZCRoP(r;r`Nc_RsHcn&U6M6A zRiW+C3M0;ajdP8YBu~{>m$~TbuHH>f3tI7S{|4)SFRin*zXNU3 zFsXED`DkABE$ww}?SxQ~cS}HN>iu#cmZG$@%vyvseu3$NKerUe*S_kjZ;IO#{h0 zxx%J_Y5SW7Qns3<=7B6z^FVe+^FU5vL4dtn7~tN@5Ae_32*$r<;f&&?;WVv&0_xa~ zJnu~dqN#0g#Y}h-ouqokoCoqYlj25rEkB1>L;srKwMLdayiEpO6^{(`Vj+GN(l2=F zhm-Nf;w)Gb-{bti06TC_D{rOb+R$k%%4ebf@f;369mDNA9B!O(IK1^LWNkJ<1X<$Yn<*ug8+Z8}zE5B{!E8K(u@fmwy>phJr*z!;i~ zoX%RyO*@Y#Uo(mt`~e8@8f35*1AM$Iu=yrF{Eik;NZ717Y&#-uCzc>S(WED59Al(b7u2EVaAQ&X%8;L$ctR_J=2Y_VdD2qk>55GjmD+nq+%zs zn=cJp9wbj^A+R_8aJY4bFt1bog@?wiGt_FOF-&vz(F&lw$Q9hlgc3w#f>%lz{IpOR z{Ln<%pQAYKT$H~Y`2L+q1KcuuI2Crvlwx`o9}sVv8uh|?b2#OuErW5(IDgw<`LfMv zLaDI?-kHlRg@5-M=B@pV@SwxUwau)A8dHnYh>EZ`or?Ct2}{*^;+fh#uquP*t1|e> zGV(r~LXAh!B5U!xGhh*EzS=QDwhWYN`KOx(Y$g|KgdF0DTkxG)rD>qVB%+m3OVbv7 zrzd^@cF1Fhhnwkd7>v_$OH=>g3a!_S8iJ4e-$T!!>=F}L_8@^re%Yv$_aY@{X#LVO zkcRP_j#-#@&C+l(^#%Ius%1A~{5B8d7A`{#aSZ)82eZ|RK1_aa_rT0TYQJUSX~mlm zS!xfwihfJE2^q7mccRbeH@?r>JQ!DqI%ez*alh0;+JpvrSr>%8-|31H|#v~MmglR&~(TMv=8XsCdn;clS2}_HTE4p zP^fkW@9EbOo7Ldv7B{$PHJ0sz%4H3woKyz2yai^-zYe~469P+<9 zLz7SARiMh)qi8)QYy|l%w5&KrX;2Akx-XUOwNEOS!AlWF^jHLUr&yq{^6F$hyzzc_ zsk8S{|w@#d{#PYI1EdJS{0l4v(2Rs7O)Gy6woI zaxxs*+uI`YKkOI+@+4d}0sTXyOc7+uvpOpfNmZuW5|_doTGZmH$Sa!Ss@(3S2iKeM!)>?ZI#GL!E;?Jk4L{hBxa2ZJZD ztF(e=HNNlzj8x6WVieaX)4LN#HnGfE;Dxj-`25ztWCE9?m;S0f~RsErR3JE8CFaQa7P{|DJ9>{(M z(!S|iN!X#qZK)Dv49}6;YFZs3?D&Lt+Y<-C>9CYzvYr8tw{ZFY^g%YrkMjkTCso&= z(fqNxr8V-dfx(X<0eyaPDymnyD8fpdcG-y7h(YAZ8B`3>cLdTY(tAcE6h{Bq|JzRE z^5@gPJ1#%OxExeI8YC;iKF7z1?`eYdA-4)61%8c#%5MjOcxv{R5yd{va`M~5N@#3Q z`788&LdU#Xe~*AKo>1{BY3b-!(D^8zf(IT>lp`sioSIl3iknVzfo4LaMYj&x9z?8d zv^|YJYR74i%x8CS)!CY5;oJ87$>3Bwf*%8Rpom71qG8W$UXIssb9;Rb zc_|NTjo9cGWu*9XUATzxq+uIVIN0R7dgwMI%HQCH3briBMF!~|X!o&aFrHw!=lz39 zHT?21uX2!089s2x17&4(43YO-({sQE29f_y@0 zouQdS&!VV11D>^T%n#I+6{G^Y$m}TVx6FJB?L&wLa8XNvi#%K<$nHq_fpsQgVWslg z|F80B9!6{edX#DcHqDA|lKdOUkB)H8&w*#|b05PvJvNYKCM5I=9BIRmT{x0!rudZz zCrg&Jvpa?v%Pr-zq?YKnG;pW3>Q@2jaDdPBpX0=&S^$*ID1SMA7Ud9|BuOel@DNIy zXAUbzuvZ?_I4fxP8dUCx)?L8ZxHVe$=FApv>p+( zm~|{0eYFbnOw&7Q{*Y`;eKQ+9K>cdh`Zaiw#wU}J zho*Gwk->*;sGkcprpQ+Mekbbcfkq9#Ad&lj_<9rgrpl~;{JA$to2G##r9deKZn{l3 zAY~H}B~8;ySsV&(bsJMrCIy62mtWn6q#%Mg{=%Za6kLj;gWw1ia9DI&6dgu%-UPuH zDU1OZ+NLSDp-pZn(Es<`w7|@~?;k$BN$!2_v!3Ui^PDx4m)^R@3GI=&ZD#Qodpqp^ z+u_%_3g4D0FJ#>lQ_C}f&853wVTGwNY zHl^mmzL|0Z)^A1Kgi~(8sBfm#y^-JH-S$Y{6`CX38~wC;$N?((pY-}0NZ)!RyPyjw z?4#E%qSp@6NJQ!NtZ-c)y*>_4@SEwi+;?^*dL8OJi$`_oFJ6~zkW@UW7vmQy_6X%f zwK;*Pw%@K5I0Oo)GIJk%6>^yQ9ql;(leH0ScpJ_J`FNtb$OfY0+>ktgwV_grFt*oF zif>>Z7GuYJf6~{7X`>)VQDS`dLcW|_-yZn@ng3{R`fVY4BVOhHoBwhDh;o0ua-U|1 zx*w|flV`GnN1fzc(tWyZrJSxQd zOTz82MM?&o5O=@Uu{$si)^a7{-H61WMF||h)_Ejv_~|`4F7^m-LZYq5~-b8Xh*&t4Ulrg8pLSa2H@R38@QNt z8Zq0^=J*Ja3e@mZ)$VSr;N0yI>y>N=Nu(z6qfU81J=`|^0Y_HJzREiQ?`RjE^2jDd;rRS#&=TAs8d=G=+sd= z>t=`A_F(avh6k~(-+G%JJgoBDBlB8U0{h>GHNOgtJt5Ru@z&Y~o;*mdG5BY)4ihngyDHyjBje$?LAcTH-%#g-GH+|G;mNe55@x zO|d1ggtfqn>g({0@myvO=VzXMZ2cmv9%1A-nPt#kNQb3AaT1 zqYzv45G-$;p+7heb&O76mpu5S=zm9&<3M$w|4a1|!S)=AK;e z{Eyjve)7`P0oxscMrvI#=Vq54b5f1$k_$CWL*DlV;{@%jh z4*Y$>|CK+C&;Q0B{r?efM!%isTXC<0@8)SlOgdI`So=J(;C)(y^FZb2=PgpDlb(>z za7pNENc2cr_J}`Tz_{4TV!JO1v;RVO8d;;Msbry-^JI#G{Z9X(jxh;&zFDEl$NFXq zZx(usIbY$QiW5Oi7Gwsp7cQC`5j$Funqx0K(ndUds zZbHdh5=rY!rCFB2Rq@B7<1^q`azj-D$CjVX-wk?EI$-<- z7fM2UKpjC8NBnz-871!9r3IJ3HV{|vUNeW9nKYqBjkhM%XoN}Usr-1aHDp}=cCbZP zB(AY$G+0B1O3qyp+COn5&c&RDZ0K_%d?ckqu)H_Ye9sj?*`zLzm z$@-srr`81{L7YYZy>}bxsc)&sa&^?qz%WL8r@pCo)_>_;F!J?9>fM-|dUsgqojRou zGAr)GL%nseBu8BEtG2_Vw&Pl&eh62CvX7>BmVLx$_jca>(NI8;l!WnNFWm8KN$6)o zbQM@fs=64zPh9_npDwk%eCy{-v}QrBgqO z;(!x~l<+LzX%PDKhT4F#3;(6;G?b0`h~V;XPKuVXimVh-zUP;c(6k{p!}A1`?D(?< zFvt|nHyD|Ak@Hk8pm%?Cc1FHLo;28GNqOBrDC0kTM(5(KE^8w8?W4 z2-D8&&K1Ac(HFMJBDqn;#}5p~PfhC7Zan@4nL+jN~Y>75X#vmV`F5 z{+YC>>rhL!`c3rR$=y7EHuQbtpBc0-%Pt|#Vi!XULyWVObH9YLW!GycQLjJ^yVcL* zuJ!ueZ1t14Tc=+B%h130CNoQ_SQ5&({&ceXF_cca{yRhc&@Z-7p{X&Hz^$>Wzq5rb z0=_eFh2fu}U7_9{>X?u~o;lD2!P5hFN$R3s3PWoPX!ns^hjZWh3;1#OWVE|YJ@J=0 z6UO7)hidaLv`4eWVB`YrrY%;JkmNgGHCLAobVZk=31~wn5eqOpmW`cQv z&i`08_Z>lwc|m8S17~?!r+dL62P5~lv(1`cFwe@bJKL?|HJFW^lIJiE(l>4r%kF`! zCKwUhfeG!;{K6Xg=fJaX5%>*I;|$owBZiFH8;m?a77!kf5|@T(vU{ISRGEnPH(w!& z9mM&+Umim5^LW2ElGgWZ8om7nQFG!`>72L*@qE-GX$@n~3JzPyYWy;ECuS+tr}C2q zcL8`(TUbh4N|;jN^hTM|(c6o`Wx)Rh_|_VXQQqef4>}n6DL4VV4lD%tO~b&`4{*F^&Gm9-eSsVHI$D1aaz@^ifzQ^fc_zURSzW-Q(c}6e zmyCM<60BTckuxp$t%*@A^Oo3ykq?90?dHXt*}Nba`Nvh*tvR>DZY>x&dUc?}!E3ME zYDM{SHoz$^!#SZ)L>8;O7(}JI>YV!x`hx_Dn#+1z;Fewnw#wXRG@zDw=0OK)eS z7pc0Ogd-KcDw{3Ai1sRAP%!wp z$yXh5vlca#i3!AShIPa)r(8UDwtw}bj)=$Q_m0m$L& zF5BRBx{hVM3?0C%@XMKa2Cgk1o^`K%pVb^c#&~=3Xxm*qrrPPmelu2S*|}rKRO%o7 za^BsD-?`KJeU{3fhoY(l6l@~{l z&)ZIxA>007vxK;blwpnRoLFz|*#Q^z*Y$0|NKatE#rOf#BD6BO)CR=@Ft@*ql?W=a z06uH~HeQR~pzSGx%2B;*tEi_aFmT+qk4aC5`W3WbOEF#+q)xJ(+wp0Pb|(@0=R#jH%hk^3)&xsu)db6OTYV1)ABdkFy6YZmC;?nL$${@j&a`=Lsqt1= zq6H%>m3~ZX*B;|;BRv!K;UZaQ9a|=iR=?P5_^%st^~O#8|9!Oo6ZUq!zk=R-AMdsJ zW`wH-j|x5&SdI4xM(zl;<>52_1zV4e2{j^@uIu1AT?fZhm$?qrWftPx&`uBMro@Qk zD|xU(m9V{GM+X-}*QK!LKaX|f)!-1GB1=J*^}H=di5<2d*5PEkiBafaJ&19!7(MiH z8eqdZiW>!=()UBXlbAG}n~v`XdSCe)cN^lQ#W2j|X~3NKn7ZrPYL;mcY+|#8#y_{U zPDc_N7MKEFDzk%((I@{rK}@*(hR z%Dun056t5yJ}~;2((Ci_tAiyvl7C|ad8>o1xvPVTxiKB;m=Do+FER}N5SS~C!g(Ot z`zepc!vpFDr1bZ_rzIXyddOm8CwggZGvvi129TxA82@s6S`&?h?(J_se2DtIzrArw zbX-5S?CcoH)3fM!UyUzoGw-Yb7AtHU7JoM)b1iNksKgX8AUbt0@;CVF4_BgF1tW)B zC6pk3ZCrm!J;546P~4rFglp7MQILu9}6}S*#AmEV9XFy}eWo-;oua z&+eKP`p^=qtnAFt>BX3%_-fj*T^Wy_61R`KF-wFEX%!tUv}*lPQ?OF&ZtS)Dm7ehv zM~#lQ8^tM2KJG2>IEdpt$U)eRFUZLGTy~o`;G_fZsMwldrjCb~=fx(@9Mk1~TAkhO zdpr2^G0>eJZP)H6xlC%Ye_o=!$n0xr(CB{1CG6FT_f8$tc66%$r+4D}-iiIUcZkZp z9sDLRJM`bkJo(L*lJKGX3d6Q}h2aOSh2a;*-w`?yQxg98sV~A0Jvmo;zEs=c(2-3D zG74LAFQ)j8g)^Qx7T#6TAL(}s`6kWLcugUmo?ba%6(JuZ)^5=uTorD&fL zWr{&w%Dtt*$lJ~IlJ*uIS*6{F(%_A$%7tvvx5 z)i|AY(!mZPVMXVoyDXtgmLG$U#n0_@F8?AtvGOQ%T(d%*IKM{s_KM2CwEtH;H)U)) z;<)Azjjn?idFPoKp^;My!+)VDSnyG73>_}KY>SD}rai&fnEef|R#C-G9VteD^_)Cs zrbuz0%SWaJ0Z(&wB4Powge+b#X#?vRcR4=HjRF6?b#xO&-D4SdQx4MCuhYtlYd}+? zafa-m?zD<+k#7}!xgC7hjeB22Bic=P-%9K7BKithwdS-BF%NWtDIQq)P=_|*h!3Z< z%3vh*3iRUmOvYzBK9lgtW$ok-xuc@umApSH(CA!YY^w;^MCatBmOPQpM5ety3XF|7pGjlW*zfY zL-h0ehNee<_wXovdmlg7J)QJ4S0iOO$@loKMV!j#%usa()(Ub9yQ3{)y(qwf+HGlz z+=lw8yjpCFJlw0c_v@#kIdf(zr(T}%@N?ylvyL{c%CE{9e~NYdtVPa2Gnbb@J`0qY z4tZ=T`=ADAE<}Kyq&BOkzJ>EE^RujIP9U|3o^znLZ4v$=?3|fJ&azPELJm6=`92Y! znBxE3Hxj=L+=#Zw#r7M1A=IB5__9Rxu$LmsF{%mPLWjDOB^rzJ;FWk3(%o0B@jmhx zp>;*nGVw4$OtX_0_Q-XJfKSiA2;_;GqD&%@eT7j`OjK{hw7pa(^{)TsG7f!YY`tk&>lg;PWsL0{ESdELXpVnp0fH!O)QP{Fy)tqs-ee!&4eC( za)tU39S6m-Rqu-W+e9LVQ7dV#w;{HAqW7RL{Bd|{+zew; z9rC5f0JNVBy9TEL)&d#OpbPbg!@_0kpliCe0jWO@QkoYZXsb43| zi(c3ejcQ0-!XxUx4pFJ2v4zRrQwxjFOOaE69JROZ_l?lkl5J7cmZ)E+R)ZOYzQD3h ze6(IbCS2zz%6`gn9zf0~HDp>7TrBf}bDL$0;=7rI{6T7tvWzAm?~4{WMS-vQ+CrA@ zghqx-CtvVE=sEIMqE@xy3*vO1ZsF5Wy4W~;K|sS(lq{6Z#JCZ&b%bJLu?A6b%AmV% zi##4=nWUXzk_j0_w44EvrV2Y4_cgxXFKfr5R}GU-#N4weZb`~(fVIXA7Pu0uei%Lj2@f#*!7%B@4rSB+cO zwWE??ImV5ch8|k)wn*L87~~`>E#MueFwPX)I{^l~%_ZbFotEdgV4M9K&EL0eYH?5T z(S|+Z_JCTmvsm?m#?uyAbakf)i3?M|aX;jsyO#?nxxWoMG3SG}_XF`U{F~}cRO>@F zLm-|N1_H~E;+G1Vqz4f#^Z_N3mI1k>0nJJtS+B8>t(jaK$CO;?41&Xi=rx9Vb)%k;0AM-!Q;-IJp?n&WfSC z%N6%wSByiSf7iCps`;VZ5g&+QJBGJK?rAes)ZG+`NGLyt*tI<37?6Fb0BwK2mh^7O z$L>b-0rWNQq--uYDNi_jQl4yFDLHH~jU09J7X zHztxp&J+iB?XILfZWHSQdc@meTp2VpZIJlGd|_BySYveW)ZI}Q1D46vUd zDWILCg{45&eVhbwqq1y$!{xAYT6M;5|CZ@Ii5hNqeyhx*Xw= z6Yzl*9CKS+pF7$Tvy-rw&U?;L582{*dz_CnH&HmyAtI|5);UA{ph^K9DDsrRc}IB# z6V_XWau2e(Y_-1(3hB3>g8$elImsOLM_6Mf?jb#3x7+J89fL7{3Fte^dk|jVPJzxE zo*DOm;!})I#TpNi!jDCJ1u_sBN{ae*=+KcY3hzg8R`9*=~-Jk*1Dw?*|~u~VRr*dy9{KNO?{+7@}}3fU7z`M|%oe(-o2d~y&Ort@;SGX=ZiIMsB{$7THq_5s)BWYA+% zTu90x!BtZhD$dIxIz94KU}tNw=AbCKw5IAj7JAajrLZtpGA0vj;P?*=xg z?A?FVapOBKRwjgd>-fU%J7T+_O;zz^_jIG}FnU4lQ#=dwq2H$vwI`@dkS(|PlF^U< zt+(jM=DDrI(&H;}E!rw`X2^`VW+jFY@fm4*w0UtDagq-iM{eb&4nJ6kPZ@Orw-s|! z5jBXVAIv|fx6igCHywA$7msno`OGrEg_}CJH4agYhNV+Kx_rAKO~oFSfg4~QRa5~j zL2kG6#>P___2qqo%Ft6%I}h!^#o63xfutaSAv~STH+Lq z#C$pXz$93{v_=iNov?X21 zBfE;Wh`Sq>o5HaAze8>f2^RRiD9_S3fHIGnka<%JUkl(T-PfQUru6x(DmKJxU&ONJ zwg#R;1}(QCWkDd0XXz^ydjFcjS$!M`U{=Q~JjzOu@RSx9!;-QRG;<~L2B5z9BtJ`s zy~GN%ifmB7I_zi*)E)fBLt+Znfh24n3~P%FZL!1BIYUc*AZlH=w0h6Er4@(#3lZhy z0}kGxHLw$W!uzJIwh!6En}lVBtue;7NKf-54)17%-wSe#llg^Z#6?hcE}BaR-nq}~ zwCyeqeMj?1R64m{4el0Ezh!u`fJ&Zo3=v1Q2>0M zx0~!l$u}U^;;&DDD@Z>FtdiQWcKEr4#C@on{ydyAc2Dng?($b;*K=YGqMyzaEh+x; zQdp+zff4)p^||5g3)F}`@u8h$0{E-^sZ1!lvz2LLy(e1Y)~;;Ts+_HHEV(GzJ2!la zN>!$p%?*2%Z<%G}znOw)-5NzV7URA90KusR7>i|6qyX%y%m{KiL#$m-W(eCdYwd{Zugz6#wXq zQshYhdkBd2JIL$u418;P&B*y9K-(ll=eqx_79(Z|bao6xj`YHUVj6m*|H^*FrYS!o z=bLTi$Zp|H5x>K!C+XAx-|-gpTJXcB?Zg44Z&mmpZ3A?QIU4UEL_uhQUzycDz(3DX zXs3Jg99p~D|Bal_RLYgNm)fHzl9CYX8~I__Zz&e4k8|~vGdR=X#~A$d+9DbIqrPaH zlrsh8A33+EZtwO-Hab{~D?CIjo@ z6VcS*C!Dj;m+80zToTL9@_taw1S2xMKIm(4l=!p6dt@PDxx?A2Wv;IPJ>S@JdbbltwwZ#DTr-~xz1w3*F%-4zUfL-->gGQUeuA|?T5tB zldAp5lmc!@wK%}@&)K#ts--=uqS3P4B-EH9eyn73dFm=^6Ij|Y)I}{lKqFD%TY9v< zLE@kTU&;n2!3XIvH{mP->u3%6$s*oGhm!>&d)iNc_gqtdqUG-N{fH90IH2N{?2GW% zVk!^u_{dU@sO92fWY(TgN3rGJU7R9%VUGl#c0t{>eYvZdi=)v|{Z#i?u*jymUxbH2 z06BpEdZGV`s_#j4I}`R^h@Mm5U2Mcz75NX{DS&f=?EyaOQ?}A4XEOL_{UgyF z#yAUu9+Omp-}N9Yr2~;M?S-jIf7?yC8;E4JtNipk4L%ClBGFj)zLHR?TG6ROwuIfB z9gi9Cm#ZNQ3q(G-rUpMiQh`9^uD??K(!OHgJM!@+=@_?|aHj<)_Dt`L@b^!nkIp#Fa;D<<~5syVDS}7uqy%--;z@I`01%Ovak4Oo7OxYj~$T>QxkoJoi`W zvl-zvl~IhtEg~s~#``sLeRrd8$WXkWY|O!RptlJ zqV1?}v;zqYqFy0#v)U_$s^GD_geCin!=BRUoE%<4QL^H_@Ljf$MC@;&WoATE3RMVS zg&sGk{P<@1D*RZf+Kqi-Q1AFEw7{Uo9Fzr%!*|_Tjh8Hp-=Q|~sB5tq{?k~e3BlJ8&xBwW8gYT!L3YrK8NK}k-p&l3 zL}Vc@+t@@pRx$Lbun3W6V|8DJm!XBI&ee^GbT|S=5`voD1S7;xM`N+550!-K9%EVP zrG~>?Uu(;TM|dD|xs97NZcJCxjBvmGpLvl6^0Lv6tH`2v6tmh5yTe2&x-k!28T{P`8$6NoHmQ=UR5{tQ!KRk$SW1V z`JZLCc(WIip1`8*h+Ml$GHDt~0QM4r$cd{rdS!uRBzy5h@g8xdZD&BOD-|i`;eKGZ z0Ai)k_mAQ6Qyjhw9Tlh9-|#MS1HE8VAqQG2)?=%WGBIS}Y`CA5)JJ}SPfJfBhw4$}7%au=RbBaVkGA7TJSW_T zUta`Z*{sB23q(E(P*(S7bUA_^6P?SYEZK~5y8?m8t$>>h^L=FD0(=F%24dUwVjpY` zFhvd(K#V;m{Cj&-udvZaF+<>*uG`A=g5JK2%(NcEV3B+ZkD%SGMXSN9yN&C9#msiR6JWAnr6dxgZ6MTw2rKlakh-lr2 z>!?sT!X^f9GCbK{15X#c9-oc)5#-vdSOcnc-kY`Pdt{eHOx8R1 zHK|_X!AEWopQ=dmQ%uSY;wI!ida8o-?u9o_sJhak?bc5lwg-T@kRzwA0yd9Tg-b}D zKd*>9t)Pj_`y84aI?)FrenlfqrRSr*)D-fEB(DsrH7X&g&{6GC35h_u0P3~z1blqpka)8Hnw$)Eo^9kNN}Q02esQERNMy{poq~WCn?K8sZ-|AYTY?w)sAuk2gwMg+)DxtHm}Gln{PT zZs118`pzxokz;+LBH5iPpZyh4UXV9#MduG6`IqvwmK5SX{@Gw!G_yi$b6eGCs701N zz4PxM6^0B3ij@k;h^9-zRZh;~<6-%_FE^iVQ+bo&sG z_%n)O*Uv@lKG07O{@js#-OlUc%kcWyd35(mL{-}&r)dTtV=@mZVwrM!pM-s{MGgf| zT-IeK6}scY9>XMefB~cg>TtB+W}#zuGLm+sHvt2yI-hpl1m4(9A5gahUBUP5i@JkFkg!Re*0sR zO=7M|??9ZpRXU7!sI*mjzGjR3%wVGwgFLNGEzhOT?Y#1I6C@^-5guN>fX=N|I42waokLilUBcE2_YYfw4~vauA*hdZ+;3XMA1S-6vDj= z4UddGi`jY<(Ng$?Z{<$^?Hdg~ha*RvzJa2X^J~k*c>f$R@jxM>P|fo>E07t7o9myx zp$sQbwe+_ukP+o0lbONbo$kpIKU}(fp&+ob;-=B*FHf&!!k{#5rG4Z)k@TQc z<0U!U5!0bpOLokuGa0+n;G6D_);q0s3}P?|Td8-dG_`bA{zTl0J$3TXboUg`>%geQ ziyZ>qgFalzh66h~B^pT}a))ABFwGOKiR=?d4^EgA`hUd&j-i)p1&Qzx#BD^pJ8;XN9O|dz)8Fy0>zccs><>Sqm7CkC zTCVEhG&$fOzJ$L1MR~;5;@9TMr3ppr0S8HRif!!Rc%$u@EGOL~uNo`9F3K7C7`c52 zG9AZyDORQW44@>F<#JN`OPbJ#L_qHbSbSAkHi(Btypk)B+M5`#%j!9g~QD|qik zE1Q=(e$Qad{@6;?^{}>qW{%dXa?~2@)Z?12(^Z;|Cu0gW-GbU`VEMuH<_)TyNlcl}h zo4~!6Ay#biGzMI z*K<@XuKiZt)=1Gk^E`Ad6IIe|+3GnAkF#x!ICWNI4>4^eC*0~T@L+se&S7?Z;Gevi z#`&H<5%sHl>Ad-kbbFlNyyYzs5@EBdvl4P+bvpL986_UpcqwZT-!O4=qGOP4BJd>_ zH^{!)Uz9rD&R3IsewA~bRdswNe%q>X0?SAib8}1149&g&j3Jj@`kj-T8lTHTOPxP9 z^O81p$&w{;_`hUH%sm&1F5GgV2=!71Xh3TQU~D2}sl3{|MIMd0rkIJhY`FvZ^74hV z^3U$!)u=&D{l>cTw$?bc7IFv0f**3j>6-zUX)J&G292+H^JL6zsw2fdbrYBNfjDKu zXn$UA9`GcsA)k=tRZ9|Inw#dchJH;1*9|M>adMI{ZNo5sa_&$comT3^L4G5o57CkX zly}p)rjH2*G+xpkBqBezw!t}m+Qv23-p;3Yp>}(8_ZPo8q|>$HN#FjCYY9ieJ2Gt) zR{rXo4pN=kkd5dkj8y+a0?PY=_)5xdHpB)BsAC132pRb7{A4T-XOu zo30Ub?8O=b*KWCe<8N_)8}fa0`d@2SF_$$RG%=sSCxX*j)T#O(_KHEAlT;+gPI3mr>yM2pQjQo)(sVr{*M zxUIlTOo)z=pp4!Dj;fpIFKb2oM=4bEn!ML&Q}Q~`0!I4OsBYN4)Rx+tFEnA~X|M-q zu#eonkYI|i9pzTJ)kE0C=0c8kZb&Cvwtb;Rn&zUh^Jz~b>x)WCx%LTcAqvhtldo#R z%v4&WDK#j$f=Mf#4$LHSFTzSWd&68 zMp{>vefyTBP18IJ#pd6e9I2vXsTF#EqL*W_4tp^d(bAoMt+HBW{^_vLJ^c($_!u8D zt>##yV=j!kj(Rdwfg@_K)BmXWThx+qnR*mm{UWUXqN~(uy|_)heanmT**aPs@TN7j zpqL}kR;r8MB}~7}MNqcJ3heK~9%X!54!ANc#+2NUmbUO*_6vlcZa^-76Xf24R&GEp zwUMvDD)8LH6o(vHs(c?n!f%o8cimch`^K3E`e9%WU?BPGR?M-%Ppu8`6?v#-Nkrya zj981d3H!yM%vTu0mvZt}+67cr?E?=0$=B4{3OnWRVN#vTTFVsJh^sC{l)W`f3uy-O zqj6u#KXWXtA0CXp=x7Eg^OrA<6rX}LpOQD!zLYkrJiZpkR|Ef=KRp!m)Y#cA#b+(bs?tD@u;JUYJ6s~Vnjl^|xRROMltxCYPrYaU!e^m^w+p5%{v}Rs~tDfg^ox^ju zUst8Ub$?YluA8cc;Ci}hAf9gH2jg1C=iqvj&&K`NtB7v<_*8s%R}IB?FX*9kVkm&Y!6EtkCp56U-~s0yS-G_kD382L%TiIwI2R7Gs4%Fb9R>Y z)33mM9Jt>D6_9c+_t9EK;rF+IfCD}CN-ev8C4W!Anh~&O{8qlAU=~rKvG9J~v0W^a z)uRs7H_4NQZOD;x`$jIXRz;X%+J-r453D^aOO43j`T0%<;fjsc+qcXTr+41I|3$AT3Cg>m^*OLQXrf3q%}hV9S~{v}0m>X&fB<3~b=AL8lM_ z=C=oFZ|c2*fRe4>Gs1CBDGl7XO1is;FmZJEEcz9_WOLG=7H6&HdsHmXQETNF@sfdG z(HXPj6EWq01^V62EPRel|?9eB0p-k70%{u9pTW*QPza?v4 ze&yBInWlCJGV^G0!Wg2gN$a_T9SO)?NZty`z8DY5)P+tb@(yy6=76=2FB;iEIS8z^ z+RA7NOJ9l3{Ul>6lq4r{hfMkmyH(4GcLon_!kMTXF6Y@EteY2t*k_c!jAgN;dbdC5ig$l*_cn{Tr3~;a-qI&pRt=$YO$5o)wTlO10dcVrU<4@~X-~6`p z$NkaY7Kx+Uq!;(kPEEJ#z>9J416^rVA76*x>t)W#fg5I8-^j5!T&N2Cmr*jaBK81# z0-js%vOTPkMOdZQ$W>|u{1xNx4(?g5hI@@W!iBj6J_A1Y7Je50JN{|@dA?Hn3jYEB zXZ|nz7km?cg^yR|s4S{`RR2fys_Kx+t2(dxRi$8Ea6X{StI00SB29RaFuO&Xv3fwQ zPtkWi{nsftm1%MMiegM{5zZaXXsOH>quAGp)f(nZq?wXNefFQ_QHr6>!;_`e)NrVS0{t-%7GsB0soD*)PTW!gHf5Q zS6)P`TxvtgW@9B<xX}-3-XY`io|2e8f#-{E2J-K$VV*F8#NPOKY>{Y|MkW!FzMpzn48wXB3)QbD}^{L zqb$;&YNmR$SO?xQFXg@SH{P;HCst#2Y4%o7EF~wRSR4a%6Yu`dRcGbBbu5Erot7Cq z`x`^2Rw)vdVI+T8)s4Fh7TR5^Cs#w9M76-5R{HAG8?`g(z17*u*a`cNuEmwSDbz{G z{>%_7g*mkjE_(ppZQ}-rE~VbG?i`V1HF$#jDjiLu*B=aIV+5X+6RwZo^`EE>OEImy zR+*9It7-md#s^;8t8nNRsr$ugwP(;r=_7*`n=j$%ep$NvSDq_ zOAbieX8+5a7O&1x`o9ph-&j4eQ&lMxFbY2z*O)Yx-b+G%GL1zR>Fb(lI1%srmzf^5 zI$5df#^}Xbt)niWWyXJ5xA@hA|A%rGn-&%cQvfMUy8Kx_WXRy{Dw)*z8Nt@b2Kr6A zx_=&$u0+fJ^x2sH72t1-;A70`)XjhhWQfZ)GHISG0dVzO7tJfpj79qIRr}6UU0hmp zq$HUrQfBzS0Mq+1pLE(JEa*~X1s18f<~N=dBuP-9$s)brA}kr}jkbTI?Ig*HrfBje@2tnA}27T`>{P$c+*ELD2$ z(~zOQcT+XQ7rqb<(9-n)jCuPL*f+K>rMuS8}VMever z$ii<<5NglLtK3?9x`(T#QxOMSKu%OauEDSRu{jYk_IA}3m0m4|=afShP7zO#j|ucH z2_rv5JqOee)&lB3TD8Ap1u)1JR|4=F4=DP%Mz3H>CMAD5C;YADoA5W5?LCY;s%7v$ z+7A69!5VX=p}f;}RoPSj3330p!lV_Sn(GsC)R0urdL5`={Zn)Y-|Nb$?}rIQuEN;^ zVYqYpC=hg3ypJHea;4FsO8|to-IcB_=V`uAuf#J0H+djp&zxBKW3xdjV8>OX z0m>QpOk*QiDjSM#(fCp}y_riI;z-1kHTvwf%8+!^iHHbqHn|?UN zR4LXD-z@Nt?cU%0M4Sk%!$L8&VH`LRmW{QjOKqTa8COg6EUtQuHK%E)2Ruebju@Aw z#;WsD$yJ(n#JsTZQeDrqTC+nBs{$VM$#C3ModDk!d$lDyyTKw%#W?z@IVXj#njL`) zRIg3s%y^#-S11=rikg%&yaJ!VJp#s|wGBUCn0i7iu#>J#)dXpDAlqQJPkf#0gD;zF zjKXJH&n5Q3q_~;j+F+N?54!n|&0xQ9ega@LTY=FD?ql-g!MyZ2G$LBI%IXXaa^Zwf zsqSH6qP;|U!Ixj9r`!ahzNPNW}emS9DQ21CYI zQ*tgoP{LFuvz)B24;aP*pVe?W9^*@_(br-R1AYdbAERJ|v+{{Lf`vp##b}0*LnQnD z)7DfPyMg8!R_jY@et(`%TKO@{e(21yOFxd=Xl;}psnMz*I^PffPb%=7+6PPO24Di5 zz{ta9gsZ^A!`4k}8*+|de%N(*OL2`=p41`QiorhoTmt&{8+r=7VUe<3M#noi&wk^i zdCfZ)g~t6IBN7NAEs(0QOGPdkujnGkOqy&tr}9B=TV;_3)^L+)mD#0)8p0|Iakflg zv3~SB6jK8_Vp%9UE)B9MWzH`Yjo?`s<|gypxavC5yoJXe5pp4Qg&Z(tGs~I!mU-h` zDMpo8J;{OmW9g+u$%U?AkSW@E=}fmmou$Sr!#zjD@tZT=VAaNIt<6x`dTv1NSjei0 zd$X9n#g%JyGmF^?OE!xLNYF%~z;OCMVW9TPzrsKP`67~!Ag#AXsgU?_$08bs4Z{VK2J-_(Ll4&lr_r zAe$ZjBM;tyHHIJJVUM?TUJ+NoEnIf#VN<4OYnO95t1c-TQEM?04@+-z<}()<&Y#Fs z3kfG@(gCJp{2cb*D^5cnrXUPy2{F*N#!#VhqI{%f zeBg8bxO@fPS)#WD(KZNP-wwX2iw_*;>pEOY>I+Gcac>&keH<^6iryhCKnpT;9v{YhcGulKUjFu$5U! zI>@9=z0^h;d7~-ypYc(z2oepL(^zDp@^Umv#Eyrq;RF|@#NA-jHfaF`{n2L zv*bEG-Cf*^TAt-@I}e(3g}e!MQND_-Ml`q=wHlEk8?O;Ju7@maf@WM=llaTt~`wBEGN=%rC>6Rk;p==#V%WJ)}u zzxZVLm*f1JuFF-LF8PTHzcZy58U5E>`-yshSe(w2vfs#1}@Q_BqzDHy3`}udV3(Jy!UY->k^R8o|qqOMCdji^1pDfoEEl3Mh)! zvZC`LlzK2TgWBN;$~j2o8FF5ol+|g*logTryL!`m&8omwJ!}HwsxO?BkHFvb=R%rI zRlug&*bU2|Jjzjie-Taqfp^AzDa)plunPKn%6dek{ZhVSJSle;G^V&=kB7a;Ym3OP zL*B|wB3N9}nT;NlXbRu5!}f^mjG{J1*@M?uRZZxNsVh>^9rdHWt@FM=+qPib;HAon zu}*^vUk|73woZm$DUXc7QR}E==v8@+@Yy#O=kQ|iUZol~#^y2GZ0_4SZ~1ek_&(m4 z2w&VnNYa_~JGluqU$A@1(OhO7EO(8KxRXtB$g6qv>ERcA$e#7tBu~kQHrRL|#>2~- zU_(Z69yrLY-h)>Vc_KvPFpv$uUfcwIwQJ7_S#q6_JB`r!@|5}hnao7kZDqh_@xjca z@Q9sh-PjYlbOdunvvfqhQUL3m#1nF(v9Qx=M0|In34QaxVziMHI-LgG;V3(agv^bd z_>(#EQHka>AivdhyPb$7Jwvvo9+h|B2kWdS3E!N;?wKJA`7>nmD+7~H0m`|D%IojN z9YL|!vY?HH-KXT;aTLb^*NG%q+-GfR^2lR={S4SYzc^1}N8p`QV6h$*&PTJEfVdHV zMvmXPt?Sqfd4hg!>uh{Z)+7D~KBwv915K4k@h4mKC&`m3E7O0koS(`Gh|!palM^oNnO8KTv$B=?APqTo<=|hMb)m*Tv&AKb7V3z|(iVsP$8%Jy1r4Luqq;j`>6{ z^GVM#sG6nGp3H$aWt!#PK_foi7uYsE8F5j5ej-;+L?p=ji#wWrXj#Gi(E-R9aIZXh z8qwhS@cQC*--}tgSGJ_8vP;Fp?|4|Otmu4v7dM5xKO??4KkCE`rJ09e2?Hd0_`X|8Ex!30U80$Wy7)hHRzUuI=TN*9tMVa%t`;%MGk@Z?zzc z4a!XI=~ZRHe|fa};ya@c_42nMujN$0$YcB%BSk_(IU~w(Hg*R-R+n07y0NdXHdv5U4Y<3-AV5*$7_fff(7^#|Iig zPY9C0iKHEtwQ0mvM6qf-D6E#JQ$x~OU7(Ta;0s(M>emnU>)nGu!8&o)XhxZQBOnz{ zSEI7eojP%WnYNM*KR6s6&MbOGSHq;ei27-f{_J97n6$&C>1wUix=+e&hepVv#J9Yb#lWRQ5CQtDoEUhSl{p9 zFTx+BC_>a-Rez@cdww*Cc=X_pPuWgyzi2OtVF{ zo^vCc9dasvE9;$VWE%I+I4QruMZF?oF++7+46fV2-@E}x-;U2Z(BbDn13sO}Ugy?x zlXbQH`Z(CG;eFJFQ+V#fUY5sjLZ#M}n%2)2IX5RCw1Q%IQQJ%%iUH<$m?hqek>-eH_?>HcRIz91WhIJ96K1liM6 zFWOGL#YeV7Dr(!b-l{r{Y-jkqx9Nne_EVnKTfr$zcF#%wtE_9(_oz0$Yu^ZZNiB1} z`zszfl;)@^9^;*30@vWz_i*diRvdv12=NS)<+?+u=#RLZ=tV)UpW4$? zdmL=~(2my>mtwTJtUafxmnnGT8$21(#DrDgpDDUdv~28ul$|5!dyw}PEuH{Ra>IX7 zFTU%z4_<*L@BI}gWWnVwPCfmdEVyI9+cd66ZW?1Po+dZM6bysr6M6K&=X_(*dl9X` zRDMY_j7r_N1o_{LTb4jNBb57V(T3O9L@gEIyg%KD{e<4SXax^1GD3=(+%QZsa5}H2 zcw2+=%&7L?KN9r$i6bq~q;HZ(7`Zg^#DmrHMFaBXJRgtI!LA+oIZcprB!007at?lw zH6Amw%CsVvZ^9alSNmutGi7?e5t&8QUH_=0++UWX9Ia;g0d-gFa-uBS1~srP zwHoJ`HIiDkz*2;GHcp80X+C+)`V}}`&?=B8@tvuVwDE^!X90sf4j(?6=my873LhO$ zRCpukBI)r`yoJc_hTMFk5j$_JaIuE61EyFmx^T~oY;ZM{({6wjbhrlD;wW<*-5>4; z1*W$s=UhDAOenl4DAd|^aocFh5l1D%$Vd0LUc*>CLrw3Xyj#g5_jWKL1@DiJdJLt- z!Y+L%`QI3kiK(&6X{kv$EPG6@;G>AQ`B;iieg&tdXP?Y{bKo$2vN3V*aRGn)0JHBy# zyoY&Nsbaa`$?k~*y@zG>xMk8GcxRqheiHs{D=o4N0=?#wksqXSAFNz z0MswxGPkwu55ofbxT3&7727ZiakZY5*C>7`8bkwY zUZmPZvQZ7{X9dH=a3_Z>Lr5Gu4OfC}gX;UjCOoWY-UH!q^nw|Ju&miKiF z$Vr;So8T$-VL3G1Pf)4PyDN*-uzqu5cOJnRQgE=){B(ME3-J9eRBT;n1Ppgb2MJDm{M9Qdh`r1^;Z((WO*Xpy~CebJ-C6GiT-YXyujna0N zfO@T$D~sqf@gYZL%u1OdD1#oP(erVac`<<`smlzI7~~u35Gy!qDeV`^du~n<79tiw zTC|U+aTaM~l!a`QED0@(HpwuIlT<43Czvl)-q0UriL?E}((nDVL>1zztabiY{IOXj z@k^hrE)K0Wkff3#z^;V{98+7Z)qdsafZ=JyAqOm`DXudgSPMxY%b0J?^7qR~qw>+2 z3D(w`ILFS#HQB#R>g9)li-Toqn$d3yl@>r2szMzcWTC2OY`Ud5jgHfiEHtfU(L3-w zI3ddnUfcFfa>#5gGTRc9b_Y~rk2WOpI7>0BpQLAR2Y-(^J%W7EH&8j{4~o(eE%3N8P1B~ zPx`dNBujPnaE7_9jm*+IuM#;sP(HyghTRJe55{4+xC<&B}!9La}{$bL@x3_dCc8QWe=v9gan4*HnsllAWVi~1=w z$x>pxzLq)Z7F}5pu!ElYE%Ao|{r&la8V4jHGmTKaM%*kuQUT9Vcv3rj6n6uj?@|NH z5{1fpU@xhIj45udPCc%i`LjlF8<=0H-inAYWW9GDF-Furk30v|m`k|bH_o98)Tka> z`^Co}SjRNciIC1$a}?eo26d}p5hhf)AkE11`(Xu`dD@*?C^DQ1(hyM^*2CRfl(V)8 zb=Os7AJ{A-ZoY$??6Mwd+Uh7tt+StK(Lmc^FHiIjLTz12ZK0;kP;_vJ$Hqghe{+4+ z-P~qFQZ#}FYw*c;xrydXY5JhUsS>94V_B!lE9W1AkvFD?3fC=1NDJ0Xwr z4?7I}AD#QCY=ry)E#P`M%(YPYsGnf2+(+=21Nh?;vb|p{K`atYUXj(uNmsdzBTSXV z5sjC}xCbK2^%1Q1csZ-_2y)baQ=IvOD)6cXQJ_^H2I6A&$-Mu8HSYqi4_9yO3151* zd^mWB35c|yS*s1isTP#e*fnSObU72$kTE+|@GVJSQ2wri8~?6dhwtx}^MO}Ydt@#2 z3j>Q5lpjINN$QosccO(`tHn7A@(NYcn%d%6-<{R9R`qFsW!|4925@FvS_-S7W%X_BUG(iSLbDM@-EyLnv3By$cqQcM%0TSs3V= zEZpN{{<%&n#Te=Rsq|#|mg<89c`h)9vA%N4%P$H{^*J4}&Cu)Zl`vHv7rbznk*&CE4+!zb17 znHOohOA%Y7>P_Vy&t$paFLK}OtjANh+yXx`462vgS+-gpJHBh&!m6(}OcPBypYwrV z;nS(=e{)^EeRNfd4=XcZq`0I6uVQ7Mfczy~dw=T!xleKZ*HyFCsyyz@x=ei)VfI+g z0~@&8U$u`q+ceIZQ7mS=i$$aJcLBBbV_<&o?BW8OmE^~Ky3SVTN@sHS&=28a|3c*B z9N!_6bdFlSu!@<+q6O-!Bt0U%S>^>_O!>R^yt5Pck0rVB)>o%2Z?c=t0z0gubtj}z zLXHDFtXsJJt%Ie=*YLrQ%vguDd?LnyyNVSZfjrZDU>Sn!R95kj85Ps5y(zbCA3&2b zejlx9r+VupD|$vp9sD8_y`_Dv632y4OhwL=dNHHewIt0^BWA!`;!4W&GBduLd{@?& z`@}S^Af2;%U|HY=NGCLiPdtXP1LLl!x31}t$&C1vgI8>n?z1u@{=dm@#1tv zQBO}nJAZ+r6lZ;tD<--9nE0Vl3Hv``I8>zT@EhfUZHe$@DlcKz%;ObUg}QV)_+k`( zdWwtj!1dS+*hhhb#|0bEJ%dPcgVijtHAW-1NxTmV#K8j}A292*U~VMj(`6U#Q~vME z;3Q2NJ@(>7Q~urmW96?eUVIUp(hPp+Hg*iL=db$dSBvzkg|+yx|8o-G&pEs&3@+2n z_;&Mm64pIRUF^u;%54kpcWt|Aa3P0nj9~uCAz-S52@S5uh*ggnXU<=pb8kNG*ezU!RuaWLu={hEU>|A~8y7m9* zx|O)@5ijc(!;`62g##{Ex^U zb9e=}kJhl$z1X!w&P~rF&H}5ixLZ4|nEpEN+$tW%zK3?~U_!_n?=?Y_jgGcrU(>1Q zSD3EPTL;7rA|;JUr9Coa{D_wQ+raRXVED43ZKWO4_>LOMZgA5=;a}!Po>Y~@GbZmY z#Ts?(EE`5I#SGA%)hmiqkV8_D2G10JOY$!B>hyC~=^QeD#VSZF?=n<8N~?T%H{niX zz@5q#^$APTz z#91NAy$5N{s>gm+lrQMX%J>-3C<@<(gFf_%dI&R|pJLJ0&O$Uy7{}l*ak0ZVw{{lY z5j#ia-GujgaHbV{0`Fv%SkwLV>YL+ztLOt)!<@{-eEk_IdRB#h8F{)C`d2iKf$J}e zdYF)WFB$UuG_oi7je`1i9KDSYeq68KF%Cz73tB{10vohwHd{EvOGqOf&d^ci$R{B= z2!S+PCmT63n{mK|ltgbz25KKj6D9{JjfM%Dyd#Nl}FPEuNjQY$UxNtkYCT`7vMK;6Q_eOeO`H0Ngb6%>Cya2M{*JLed1k37{D{@f+Uld7dB$zHB+*^PX7&tpII zykQ3Je`(}?TlkQRFUsux*ct=2;aBq*GuZ^MmSUGV+VlOvkUO zxMT89$|u(p;;0ozCmKxnR)lW_KRGYcWcZJSQj=7uY2?yJ(K=-BlWUUw)DBepSUx|c zMvZ$-xYzWPdwK93E{8PeAPvk2KI9lvt+wrx*Ms`MYlGu>vPydLx0jBNylo43cE7&F zI<7sp@owTS`C;Ro<&1UOfl0Bm&J6+sBNOuvIvD#Dp946z7U$L;VN57v?9WGH>v|FV zi7&#!^Ra#_vAo3RRJT^cKJGWQS5Jstn@n1`92sIlQLet7yGs21_;$9%HCNoi7 z*D>*N;Qwn}dshDv5$(^ru!AJj-IHyi#^otr@BLaVshnq04RJqv!$}rZ7M@)5Ky{1} zL*B`6JO2xCsWyWD>ZP@0oA)DvVyGK?BXHXIdEjv5owQer@&2A+^S$$ou*d3EL(FPl zUJqR4Gc^`22n*|L7?>Jp zrm%%mYe!?%r$#w5SQ2m_JFs`B*~u0js=-*rJY>|@;5|3+9@pKraG*wssMtEppBHQX zcI~${^DgXm((H4UarmEc^d>pBhG-w~8PQv9wXLgvX<^^bs3l(-+Gw5ar8>;mQ)}Df2X68dwEE*_Z&}}U9=0VV*{5JzQafX!tvxWX@)sqqgOjbX2I%ic?Zhz9isA!V7x5@a9`NTXcR$} zn#xTv|8pEUzF+2NQ7rr2EPPk(JhY&yEiB-DouBpolH2{5N%$pf-pky!YX2|R3I@zw zty2~WQ?qlIGH>4GV=@?cfUkKsvs;j>cV0mO| zh`(xe(s-bryxK;+nQ@+aav674yce|uGg^&v6+KgmNuC@Ody-3&ESv#;1vY}-C zE^(q{WdUOsW8w0euSKg)Lpw13eeA$&;gTBL!0;0q8+dd28#k5!^KsjGY1|ao164rQ zQwEPK)}Y1Y9U*Hzc7)t!e7eQEn794rwRao$v~yV~x3ylJVcjf-@z=*-e=}|tzc<#4 zGx7a8quKz#g0>@xJuA+TW#A3)thtYgHg4nf*56}Pt-bqt%kR&Mi)FMg0>TXVYqS{J zV9DPdsl$;9w94JrU-&&(kEPgA*bil2BYyPjSp2Aw^}9A8h7>l}Qs|LF4soQq8tn5H zi!xSOJ{^0U3fW#DemJnG%D~;oTZ(*(MNwN(uJBs?t*aM{p2Avt7IC%9c%0{u^Iqj)<&JxNyuKzU^T;hfHvCO z;e3>MjpTl?Q~=c*lWH1uB-yrbtBXnjKXo`FvZ74vuc(wtsgzXii-^I!?)-z`cXGzo zU(`t>8e)2BKHqggw98aZ!F%|jJmO~iJ71sjn7MOWyYuCVY$8= z`=wN#Auq!9C)Z-7|1{ROyP|ZL7I!V;V|OXBbF-rE5tPr$G`Md(?z7T;@E%xk-!S;V zsQw9H<^Pob1L|esOkl@`-vDo>`zkmC?1P{38u%3cAaH*ABrgMLYOqZYFsv5wzwO_^ zO>BZia;;RB#nC@t2mUc{tRnoJ99G=uT51#jGAeDX9f);tI5HEtLYSJyy9y)VD*hPv zcgP=%E&{B2;3kWE|-GzE5`-|M!Chk4Qw zq%AluG^m26R6S88i1X4;D0W902Zs7A-?{|n$u${gzqAg1IK#7 zchfsg#$gSA#-=N~kje7*c9h=W!*1;R5ogB9@-`#)!P;5>`!W~iwJBL;eV5nbjgoh! zR`Slkp9asCYh$*TB7!kbY|$aE81ZZHWf*(x=r!mC=EB@cN7l}=4}7ls$NGE?(CEOT z;~KJ_XLRt`Q5<=n{3Ez?9Z8*s4n=nWPX{z-0W_eEi)pzr zF|NmOmdFX`v0IKtJ{Qx#Z3`I=j}<-bhev#Ou^r`M*mh&=qI6y@%A_lQjO6}6y>Nhw z*`COLSX+(Qj3*Ppj(ruGV!XgCVBb~yrTA`fgLt5n6>5-C``ywv>~A7ROP0Xh&iBin z==CxGDB)4;!w*RKf;?pZ862YAb9mMh-$hpT#2CEEE=;-G>Vu%52=c&IartFfQ`_Nb zg_pL#jC})T-Xf1JUrxilej4>;c_f}e z;hx=S#LHklXh^^-J;CYSx{8yq@m(!p! z^Ld|kyiAsAZa%G(mET3az4BLhGTstu?4wS7g$yb4P?`)KP<#yDx&n#uP-WHZiB_V0HCwcMD&Fak43> z)}XwonbC@DQUwE)Rl)LS>@Udoozc-0G)wu$sXbBJ*4Kjv3{;D+#KKDQd?&e6-K;3r zZAaU}`yHqBekEF1O$KMIv!&MOx|2Nchri5*G~qGsuV~)0{8QIgV+=xeqkc!BkX5hV z{^^j+1b=nesWfC`;gS>WJzQ>XbE#me|7?u8UKv=VO7PnZW560y2yB08*<#^F4E=wueVcb=fkQE&IJR^|dJ4*9{AIdN{AKYIsRd05!@ zo3Fc`=P2Djlsk|M@pcBbW|4NOJE3&P%=hesFy9NuCZqcYNbq zAlY7IhHb{}ZmZIr;^8fjR3__6gO354-ZXoCbY4&Nf@;i-Y=HYyg8ckohzgRw&mq`8gD>hL>KhTQJoam`x{th z!e%%ug4y4M(3y&eOQa#%2(nPmc4^n^qxewEu2w+C_|a#AM?K!76XSdm-2+;`&4|Ntoiph?&K{p zT#*L{qh2>5B*}; z6w1g|3J0Uym;=|27<#YiZX|W3`o9xeg!m0_^tzOPfW)8afL~Jih;SYGtdxS{+*k*9 z$0^|PSt9d)j?z)j&hfPb6X!5nv};20gj8feafFiQBkS!n)N&k)PAMAe zfeop2J-D8Di{1xpu##%3JV!@CB;3(<%|1urH-+>gzie|@p~9Ee#EhGQY|i4!1V7L? z52kstLyGxh(>7m|&B0q%0KGbAUXM~c*7LN$O_ERkoltB4?6k#y&sA%HnanhjwP>5s z4MA-_p->p~IG(x#S$(0|y_HFRLeg4=v|Z+qtZ1~O_8OO;jCMpu)_kQfuScfkish5u zvVVP=@S#aQz2^h)LT2xv79$Dih8%T6t`glku)^H`NBVwJEWxOP6k(+vyMowjpednG zAElvT>a7JfVgWR8m_e|K47;q)#cv72KK&H+1bf(nV z#y7!NCS%52FvTISwz4|3m@^394aQrR4!$=>e*1TWuUPP_1fM0K%PX>lE+m9};3ESf zuy(91v^znLRpH2N3QSXL0vBRZreM5_*>+pk4yI@H%sTn z;u%a1-yG!zA_=Bv&`h0(<0F`;^U@(@j7xr0VMI*&Q~+1UFa!N;Y19c3;v3w2OPYkiC=lXQEAN9626VnC8gv zrta!Vc^{FiD2<{X?q;Sp+)JG`Mu`9smAxi?#**Y}{GvQd2u zjW+~ji!Iuckn787Y8&KP_O{~>kJ{xj*so40upvH-vO^C=&4lbuaA4-U&p!&xaPo=c zN8Xja4e!WD9wWTR5$%&&yWf|OtEf-2wh{Zd&?RNm}u z{=ozzp0h%JhktO35x=bXv@Q)DuNaCh6NKpX`L@u-gn*BFFHxXA)BAIpY#WX*`M;Oc z7J4mV9L6g%8(O9ciD?CC)N|lgHE@$Kb~StK)MpsY8g+olV)>n7Jx^z;-|5_i($ zPKDHKIcs>|_!i?X^jouKbWV6GzvwMHw)GBCAv{iz8#y1Hbl1@EV7Bf0q zgsg@ag&G0OGcJXs7rMok&cA5}E!yd)n&E(uyGso$I?2{p;liLQyNbraT^9x`vM&tQ z;qTMz|2QTBJ{m>;KN{lb|F4GF5z`Pdsr|A@Lo||xNE?k6P}!K~>_%8M|DlF>T9P!9 zu2}2sypRH2)6%I9xX?0L^{Gv_S|^d2a+*2h^F!O1a(7S*@s71SvISA0{4(iLw>I+V^G{x7x=cJ2QU9lGBC zQwjUeIy9qcf_wJzTROCfyM5#JUyig8W+zF$v=>OONWyI4CRdK7=o@RLJpAR^s%=G)MOKEO)##25*i(vwNH;OPZB#j=mPO1dY7n!Ld$r6aLo;SEsBb z9YbRh<1>AC`R;&{14b^Lw5kH*@HJddW06Mch?XsK0Jm$ynB+#rl188Q zAIvRp|SEOqf+6}jm$g=o*dyN zLDQVQoknIYRuH7YR-MoBeW#%%rmxZ)Nn@osvfR2`IxDN` zW?NA^=|#0uC#rSSI3e z{z;1|QF7&fr^PT=|M&Em!eN$L>{qws?4~CB!v8ygzN3~Rxk?fh>Dj~fo z%gwTKJcj1@(sa{-n(V=%>umNGPR!7=`?F;Q47?|z)i+4&BQdhwb4$q6ly{^bE#&r+8D>7HirK#)rRH>&N9ZA{P#72 z?E|rSxEnQs)KHD|l6GPvt1qexR#p(1o3)`iTH$zCstt`}strlEVdn%-Vl(!WOzY7( zv~In}4UWqhZ>{yGKuaVxCt&to@2@P2&C%3*>CKzdP)qdPcT1?(P_tMMPNu$d-SwJ4 z{r8{yj{1%IFV=U~|J--YoW+2eRtW~MJZ(ar?OOi7+IwRlztmQl%`(S?MymNJ$0j>> zD!q~SryJ56Cp6N$y9@KKnN~1T?Q1S&d$7+&y;JlGL5p9oUq8)^mVcPzoUARc2S-uv`Sem)vp#~ggkl8<`z3<~f+gu2lMsLDZOdsO z>qT0}Q9*-uVxQYWRtl|WIPybB4j9;3{7tLQa3mEOJ!!v6c|Bu3*C=dS#=qrps6}>> zwXX-iedYDwcg@&kw*o)tF6~?Nb67FshoJpVh)Y;JGQG#Szm2?onfI`wE_h^t7EkA; z{W_Z{BVERn*uzxRv{ip8G8fQ2un(SgeH$5n<7TFvZzHcd|H#J~I~ zM}7hFj(&MX{to3Hej<7Z-l>(yamLJq$l%PeEW#hc8x_mG2KFXbT#HfoHnQw8J?s7D z{mUn>*gK1k{QPohU-R5pxf}gPtTaC>Q`Gaw?XeE|4dTwio2p zJsl<2^y2ISuX4wv74ZMIE-`GiPdE!1`v_jAjoX9rLmHpss&(%6pi)A#)3}ch89y22 zcU;v=N5yN0<0I(jpIx;UEX3;n+sNq4k!vR;TsL95(W4)MXP|8{%Ba4aj@XYpLE-6( zY#H7ITl!+*Vq`e9P{?Svu7Ef8`v#ZXQ`&dx&R9J-*j;|@qEaf5L1_2~YB7Z`&huiB zf9GQ4LMX#;T)|1mInJc-(Im;eu4?4GVhYPL@6D_JEo2lFrhGw+)JBOfmG>z;*CR82 zi1S>G91aoBMn=cF>Qd)AV1%?CC*UU{uG5Q={UJe;yN%aV_dVz*JXC4l9XHDrE&}4n z>@%(StbHqXDabsNPjlE-*iVO|9Cl5UifF7N3yr{{O$mJTz&O`6PJ`?Wl2j|3R1R5F z4dvcMBp*q4o;O@g2u!eG`OZLw=-7ZS6TYKxmC_??(pYa^EdWhuGay?s7^^hKzkgC` zpQm6%auKEb;qR%A3qpv?XR3DD&e#2XlWZrv(ckZIDVtJ@x7clc+o^R`%*gwJN>{D{x2Awb#A^o%cvyHK59Q%<&0wWLXx)&ptu9fz^pB}3vqW58oqvuiPBxY&xQnr|k z4$A$z-TQ6ipTwKv?_%V{HPdQbZ?qZQ_PWzXAQHlnS>mQkTnXh)()G$Cqw{i%J#Xe9dl%L9?Dp;edAChI>y-IKj_2fvM2fAaK}YlQ~B5S%dCa{qz;XEuUu z6xYThx1$NIF+Up1&Uts_%lD{HUbseYvb4*qFGekh7XcEaG37>Z8B4v-4W(YU9DJl8qgEAE|ekWhUC0(3EvD&I~l4ZqwyBASt}8 zZa*^>!E13b;<(ldK6K!Japhl7XSvtEobZ;&cXf!`20lPh-rLE?9S1(eie9VK0ZW=z zW+`Ldwom@{ej`eMHL~dkdb+NiGxbCof3!%*&5M!bKi({}hrwUMbNP8b^9p-=BSuv+KZ8EL3q}HsEJ7OC3hH6 z{)<8S|9p@`W?Ytcu7mERyI?7iaPySEkg`n4_K~%V<{)JkMrS^LNi&k-?8QjWkEtfk zi4pb*#_$}RnM2pn6?;2gfK~2=ASc~f=G_*Q-LVZbv%h*Mx=9IJw1h4)PJo?l#dI(3 zknE32;J303rG0CRM+Y_;ElwPdy&1u3tG;V;Nt2RB zy%<>&EQMx)7LC{VQ7WLBXhmm4G#}lF*hPlc38fh-`2guEd@y+48G(Q!$r{2n%E@FN&Lg()Jkw-lDc4GYDOK{H?FlKN@ z%9#E)tT->_tfWj3b?r5X>(F5&)<8xQ5DSv+dI6c&#mKcAA7XBN6h08Sl<|`Dv*m}! zpmbR-LsKa|E7tF^+H32D z1aOGi(tY3+UM};IHe}b;0J&4XM9JF19eo15L>TgE^45Jsss?jIXv0d}y_|-!m|AQfD7Sq}-|H zwdfNabiU14Sw>zV$G~Y|6PI#`uj1;|gvH1cCcC-3!+lpaSM<%$CG^S@Pl`_WVh2`C zE~C4mFHHx(MeAY*d=sx{x##tzIpYINk=TE}k`0_oPUxMIXxcWaA+f(?Q37)IumQO) zvETmSXtxG=LA8^{;M2w?;{Oa*g#YEN&}|7b+jw_;?*WzpuSPcha@|(k(G#%J$KI%o+Sm!K%G>&N8}A<2urF3d zE^6=lxD@fXz zs=$%%;W^0s$W4(I4xsi__AiE)AU|d6QmWJE!~Uh4gNj$~LhX6ev~7I&Ps0ykl$0aB z^zQ4EP!@XXN5dy1uO}GN+ISzIb6QY<1CBmJU27q+b_s+O19>r zUuDRcNqnBo!(fuoaWe&6@x5dtc|E;}a;Kc7Id(zqqqzo;;*aRzDYb9FX`$3mLpVNn*SiTpT43}qoDK2qO z7S=fp4LZq3mWFICyh``Y1hBzU`I5oJRHBm`jnER0L$JY&2n^&}rZRDXPW0pkNMQ+k z@jP7x{wVxfW}Q3m@)NOf%m>Pn4e(g;sp!UJu6LR^o#9yfCN zJmh+<4u18(VW2>UpWu6J?4G_kKv~k&sf+O@psWwTvJdN~{JxClPM z@VOrc-ztSHrop4g=Z*3n5gryeWVJke&?=q(3(g~6N|i@>);N;Rqd(#szaLqYq%+)M z{K6ln_3y_WRNMDs_uM+;y;Y8m)1(!E6ob#Drtjyqlcj#=hyyu$s+)B4?e9@PvD|4} z!R*wB_-xa~$g5Xcb<^E(Kwmw~MoVMNX;cJU3aZNzp=5g{+J#wGc_FK=-D~Q~`P0b$ z##Q*>UukO_WX_K;CuN?S-ZZ!u8bJg5h>->AR7T(xJVADx50CzFv4eIX3UK{ukj?#2 zf9FQpfoQQ(A)Cz=-`&8?7o%p}kJFn6-(p!@fHy7ZS;=#OI<9SKXaM_ljdCcRxeWB2 z%W1C3`$wKZUS4{JRp{|$_^Avd@8=eRCfn0)yQ&8#Al*+Zn>_NFr0auDgUbqT!i_Ad zA4fifK3~bMH)5?g?M1utl+;ET^2=SB5AABNL_W$Lxc=!M$_5TC{5iNPV+`5I zQVCfHHi@$>wm1>ZFh!08h~IXd1`{yJ;7?`Xff|wl8TxLoD{t3wKP164-F*fuT2xN- z@UtcLE)&VZVo4TWyo@r)@s|t+qbc`4^mY3g)MJaCKRpV4uJNtQun7$)Q{fLl1Qah4 z+HEQaXN~PI*+^WuHQ^Ps_Zf_7Zt50$(y22Tg~$Wxi|>`ke{pF|IFrM(pvjFUu-wI; zxa1jWU%40MS!+ZKkGtUzrZ?l)I%;DMZCujyhQJkT^ICm*yG%PLdvf4=<-(u2s9psg zW7dX)SxrLUYB19+Ay$5{1quU;lmCn(_4a%pGff7kD9f7zE#}toLP3KpP^zo7JMjBe z-~*ySAuK>l8fl%25&7j4I7(Mqn{8sT@iy4}4l}#6B4d2h39OOo?3UA9c;AP@z++Fu z-ZXpZpYgrkey@)+mDFP`18t@=`mQL;-%KkHTzD$0`7pl65n~c}?-G^7oHQzp&`C;^ zP3z}M3ZzxU1%JLr2kWX5na;RF$SpoK6>^vAoml-^JD%EF2dy27_@igVG~J{_d_P;H zGjRQ`(mH#o!20&MJS=M{^3nT}*!r*rqU~*k%{s!^?%g}x* zS~E`uhdG zKf91efvyD?6_@18^^_c(-~o$IxL_Fmbb)tdH%#^v)Yo9N0a4viP@jgK|HjDWwOj7qDao*sy^*FZm5;iSO#d-s26-%bmUBIWT}> z-d&h{0>{7+X2Zz+EEtes16K;;lesGA`l0UpZ)XM;ie)ubOEboD`3_*L?rFF&>)Dwiq>Ah;AvR(?=zT|Uc~&_8P-H~7zQuUpRNDLWuB$U%wHYPAhOh?(`&y};p}*39LX`i`hdRfWhsFluwf!0k&jx6}KN4t&Fp7IqIQvs#Cg{2Am9=w!Q5 z2H;dpBRmc%dUdl340+&hC}Swu&yI>2`lF)JbX3gdWX6zR+wjEl`2%->nS;rmb$~UD z@%hu;6Mb#S<75l(ab<32*=Gd(HkRAw=hbQX>(3xxL22y$$XZaEDB#^Gdxn(BP3oJ^ zuUB#K@Ei{4=uP_0?`zPHGKM$ew}oTI1OCkIs&RvVYXEbS>C zmC0vAzD|3NZ+_o%PIaJ8gYvQIEgKwD8^F8AO59jKvPtfo4YX3B9GG*kPA&0}t!<*i zRo>S%$x{M5;HQw>ZuE`|bDq*azi*n8p0mM$XSjd~%0J?p)=YiA;CjnC^mrxkFpQaO zqD6N`_*Z|eDs%gD`4v))Tl+sxPN(**q}JVpJ@;Z^s+(BC zCPAOTSC-@HSkcyT=t1LQv4v4D94)`%n*<&A1$5H9 zPQ?&=Yss4@D)}go#0#yv3JK2WP_4*@ z9J3du*T1y7bp@gwWpaP(is|)Og>ZAL&BD~iMab_q_8>`PbjohOeg(@_Ii?e?iMguv zZa+px14nI^(m*@9PEL+eCb{LkM(mQKQ*`cKcFw2s$ozWGi*}WdGJMP*SSsBSyB^Gi zlGS;&_kDpY>g@a0HEHXIgUnV^PwU|?hG~al=s1QJR|RY;6?QJ%OghgBuXUvYH_!VX z7A7@kfOTEvEAc47@=dGFQ^W72v)&}Gd|;1xF;-U`uN0nfED}wK-hO*Hxv8$Fb1gR$ z2tYBPmB8aiqo6I2J$~vAxi1wv_>|`Rg&e<8zaJSg@LZJTQ{?(wW#GfV9Zo_tY)L(` z%??zU?x$x%Ucmigqw+q7XK%){1u%G~G;=c#3sZN{9-*X3SIuMn8HIlzIG-X&u<;Mr zA3u1OD_Y!@=}BpDt(@OC2YfLkeYEfLigIqMI}!TvMa@)Cn=olB*5fv%Fa>k_?4PuX zGGJ5k)3}*`klG{!?5ww~^?d0phQN>?-6MW+j==VGQ+7QDY=Nq3$n{M$+7YCuk<+r+OA= zJ>vit&Ya>|DCX)E)r-Vj>vYdpXpa~963?RQ8k+)qD|(^O|8Z|N_>=hT=^iky085T} zP0o)?I_5SFY&odIQhnrl|rosutnN@+fRK5BNvg?YUUHNv)>!iZg%)NXC9cDy<5w zvt9)&8~9Gla|iBCMeE3??pmDloI^RJz^KbIPTzS?#=T;ejhlR*m{neA=;0xKO7352fFZ(vKE+sr1|wLh`(8r?LZ!YT$e2d|%f( z!_(#D9WE9QNMnGc7yEtPI;>c+V)0LFqFoVJJPm8GjRSAIlaE<;Mt;hf-LUo19MSnb zr^no|=m=)1n{)CJ%+E)#5|A5vF7EEVerx3rn^U;tMKq^yWw+)Oh4IUaWJ5V4kQGH! zdq!Lf9uRm2Yvu1oO>)d1kjp2&i5$K{yCh=hUGIGBya%=-(#a(CCH13xT1Z@WBF$4^ zkb@p*VGH`EK{IgN=w{4Jun1vhGP1s7E5Y;AmjQbk$3{1AaAFFp5f_qW12 zQ7q_uB~7CnxZYQJ@QI2hFk+X<_SI4J!363io%#w$CM<<=`Dm%>ipn18;&=FQ*u07MSS!gyii6zBUK)lU++S z<_`aNYW(o!VtR&EUR;d&Cf8GqslIaSG}K9EY4FJl?|^4=6yztH*$z50<-Jom_|o(G z&#~UAa^{~prNl!rCbyQ5lwsW|*S6ZzZ%Nof2gz6S!4j-OZ^_rsNWNsyDjMS)NLM{c z7Z?=3f&ZW0eyG=&bjHU`oYO_CA#f>RU4MQd-A}UFAfftIT@!W|Rnr*E^mf0$>ixJP zLs#{FZa|en)+A_D!-Bp)PsO-WJnz^RH09gi^>T)|A{K3cPrZTcN*W+;4JrQkz)?cP zX>jkTMtJ0J>QmCP^c?(_(5l=d?k*18%YOv#TFl}U=cDqm+=PMb9F*|q@qYZ)*!t`y z4SrFslDfgz*?1sLoUJzD0fBAJN48`x{4aytwDGCo%O}lSUfMKGmD|a>OhZYv%I?^&Ucjln5`Hff_~I3ga>!1(@PfbVilw|wxZ6*& zgB@1o#a0e2bQl)HR;G8ffe8}v34MB_txul?I{=>Yrm@+cB7E9GM@|_|;5Uc6-!!rt z+;v#I`(be?AB(X$%2&|D=cT}I%h=1pwMgG^>yUTz9nK$nLfq>5>lj$nwWx8 zn59B_b*1>~;~&G8QWcQNm}w_@J5BX;efCb|IMKo{DD!q+VOjSdl=<1jI3Imq56|at z&OnCBz@6Pdl&eSPxO~&kKYWu`{<@Iv!l|39*CEq6-Rs-Mk#t^TN4RH&*#*hV~ z4Kb^Ts@-R-9*9_OK;$2BOFn#xwUzB-1qvzZ8$6;z%sAf9OznaD#;bvJcvV-erWJan zsLFuGDuky};v!u-G%7qEvEqvGcm?8dfyLS~#LfKOvO!=ST7eSSizwNfcrcbgJTXN< z%}ND)!+#Y$yjCdL|JN(8gOR&sDceT*IgG;TF{Kz)ZwDs}uLwUARr|gawJ!LN??xYOYb)n<`TZsKd^-Im$;44mW7m1PCX0}Y zmVImx{*CY&>Hj^0N{?9pCu=MAOkiN&ep$x2mOr8AfpFsxaawvIq6#X7IL`y9jSQtv zi?2j2g{y{@dvN5&RjQ9FY9MankvfI1Qk@XxPwg2`?FyuwQ4wojjU1mc{PAuDe8(Ix zdb>nLf85hn;Zo$^e^B&?VVSrTc^vF@o#0;nllVBV=pVBdo_0b@^ruKn%!>Y`k1K)W z3lh!=`h$ym6zpGpaXatD=NK>ZDEp7Bb6-XTKhR6>4AVRIiYB2wpyD14#H-c*iL`=M z%XacDu(x9b-~9EZ_#FSG=$a(MD4RQWHhBH^49S$RZdIKcgNSLpig?bR$@GxmLF*jaMW zy4=!^@*&&9-9wHrbI{#?3>a^sQL;!*HdV1+m8=YM0IkUPN4^Gjlr)jN|HxCs{BSYy z1}w#vbIcNfM%ln4kLbY#*Ik0vU$LA%XRl^?VDGu^dMvG-cGh(rg5;^Y7W_O?)qnhHRd0q|)gOL_{C^iCw*iaBio`Ci zNQbOA#facd1wtZ>J&?;>iM0&}enV!y6zTneS-!;+|CX1AbhI4f41N5AygzR3rAW?@ zyg!W3QhfH{Qy-Q0p9Pnu+jc2ZbPIFqN{~xC7~t&o;C=-VY0|i`08z6!`C{ZjJngJB zQaRjzwzet85P~J{Scq@ ztxx7B#-IVO8mLbfPb?J7qW0F=)n3jL*G=!JM60MEkKhAIMhiSu3ijkk{a4`;S0-{DvE&QnhGUjtVyJW08V-g_}$E*g}NM?a2b;eL_M zBYN3ut!{0vt~NR>4lme2m#<`pDr~j^Rto06bta z9Qy znHzezq-kD9-(*{7-)zmzUYf-#uI5Uvr)5UoLli zHF8hb{!y#Li_ z^M!8-iH6J{7a}Jv|EZtZ<6!|M8`dOvdHW-AL+7hi<~>f8!|wzmk&!dCI`w|sxvo+m z9UZyhhi2xz@FqJ62ggjd@+#+Eng?&`#kLPhtNDF|%d-#omnRY~uY=z}J~25szg&4h z6aZUTI$#@%K3B`C59DxpN02>8*J)cmyRUM!3>IqG=@Q8fH0+QMDZV`%;8JJz8CKKL zVTU5HS)Pat1{6W}GqKRRNSsj!uE)Oj!Sb$iAlochSYvHAoUjR4%M+qS5#PVp8QJw~ZY>sd3_K+3G?<&+_Hk#iPc$wPjYi`1M*gaTRBxAp$?MtdZ-l zdy?ya5vAR{j>@NKRMywxNnpYS`vuAlA24Seg?lFv2ZUKyMt)(i7iCaHf0{D`+4y3t ztjL&G0}p}uMkE+bJ8!RM`JZ+y%q(>>j6bySDCA{z8vQXQt2EeCt)rrT;1fsv;8()Z zdBer>(&;({;sTr$+h7ZaU5KOdvpO5{h`_3#APF%lP_|KY9ans~huIXky30@5)%mW{ z%wlJ;mKcsT%1>=?3(R$yktj?hWi!zeU(?O(i2~k!V-6mI0v3{{n9_Vz!u)%deWb0 zndObQRHBEeEWmnr(mLY%w3RGx*xo)h8}ykU}`<=uTf zZy)tiA+C`tDn3G+vd-^urvtsFFrn87jb~BNZ;OJE5UGl`gVb_e=%u=YxLyH!F0c?r z1=xpBu0&{9sVm~6Z4z#btgbz$WBgeo`0W0aRsRll z{92(=P}hGgMULrx4~x2_v#`HoM`uyh8^IT%-Rm}E=jm58o{t2AGPA*d7T7CWUy(^~ z#d_=Anc6z5jK z9$m{iSE-t~NwCK%wR_j}C{^(d@arV1$rcLBLM^B4m1#a(g=2`VELCXgEyCNdR#n1F zqU4?s81~MK!BQ)~Q&#+z-7aeH6uaQ@M*JJ6hR55O2)p9DLyRN)4E4!DAWh^wrEIYS zEfRkQaZK^ed+i#}$5anzH_C>(u=~JHCe`H$K5&Hn7HFmi+O>OAg$gqZyukJZYT!3G zA6XVOgDph6ms(NnmU$G2-9z-6Meu461IMY=p7{fHkD(q~%sR?nD9FMO)r3cTkp<)3vW_UhEUU(?VHPB#twCv*DJ%!gOhV75E9R2Dc2o4C#R zLK+9umppKc17Zn0JJ5%T2l9P()Clj`9o?#WMc_~DePm`kDQ3IXEwC-A7N?WUz}^5mlMOWc#G6dg6W>53 zx@X|J31x(?=w#$Aw&@hGS)xuj!s!+w2M>G1CbZ6qZ>DxZ`81j)ZYp8)D!|Cn1y4&_ zn-R>^3J)+j@p6w6+$3=x4!MtY!ePWIQp+4?)ZdR^WyS}DNsHyy3QMWzDj4)}Gw3;J z1!XVLIw`Aej%|KJ&GOjl!)OHVp+j$k&tLkcHrm2+Fr(2Pb8|Jf?^Sy~q5>IkJseQ} zFBxF9@jDJ8J4RwBzVXYqm*<^TWp8$Ztq!>`Ud5`(EHsK~#cvww?VFuhH{`?W8~pcg zz{i=`BTLlc`#oTrIqTE;?bVMMct-;m`!_kwH?YDn69O4IDSJ4rv;x;U1+wuGpEr<} z`=XIQM1eQfkzIuAeo4mxeayfE_j~wvIbf3c0B3?{pT+KZuh%B$_GO2YkgHKX7_22; zvUl6u!6Z%LyY8UQ;125ZSqR?s5D)#MyTct!e9#?Cn6o9Qyt5q47V?l{CZu+iE0}o4 zBcYUq?w}U;#J>#o;5#1+jXqxr{vQ=Q4aj9xWA$~p>*ybz?rPh-!og2z~9`%?H2IqKl=zVThNL2*(wmGh# zeg!gSZgHW;sK-P0P*PE~6q}v!pgd$=hW0!! zNKa8WFAq(8&lQY&W_F0jlN89HDO=GL9RGGxF!Oj*aO~Nppy9@xsC9l*FheshIw_$k zm~JSKHb1l=I_hLoaPfmDgQ;`pM>9V;88pP(LT}EWA03lW8ZBAX6nwB}UTAYscBpXv z$)JwTAp-x7`O8BGcb|lv^<+?6K<5yNKkj5OA1#_Zw>zksD};6zbqD#Cs!;Y!d#H8h zEU=cG3}zQ}2bBel!Sv%~Y4=(jsh21m!2M<>r*75aorh^EYZH1y6x&d{E2XQ-`4 z9eU^a`BC@tw$Q%rZuHicpz+xSKrhda)^|4rjRpbycUP^WPZvQXUf zTY{PK)C)~PrzS3x_1-T+Su?4(W5@nUqlspm+!D+k`TekFOVB*>{ULnM82P>g-_u6E z|D1ZaK6d{Dn%bcHcw^9T9NOBAXT7IJcC1=R4$i;R7*st|kMFYRzdWx&S#m?I?{x=t zD}lIv2Irqu_q&~qLG?3b(SMmqzw7ZGWqf{iXyQz|M%~})d?ZvmGci<)_R|IypluZ3 zh*}oPI$0Rn^!&+S;)xX@1q&+!1`bYeB z6;b`1$WP0MeqU4@j323I+M%WR9jmKyq&~`KZFFofRv#tmlZd)@j+~39b0h5#FSP^e z+N|#HL?31vcnK+?HQ-)&CC7~XR*d{sU{0;4=YpG20d}Z~U^ZwSIj5y_MX_^QoHLIr z!x+P}rSs~3ud@u=sxdg;-~ii2cQ9k_ywIND<2aTWtp_?IVdOcZ4YA+yk>7H9E|nMW zl;gRDc&BURT*6P@nIOG$1vCo1Q{C@(+M@^XKBJ~Pm^~Mo68*L(L5b+_+F+uzR%k>t zf9$txbblDdQDf|oGn=vX7}yU8k1kMG38P#t^(^%&qTm_#6(i}HTgP7v!kf1LOI{QiKQwb$C~etFh&`977fj11?^-Bvai zDLV#bTO;wY$ZI_iK_t(Gs2{=uA5UU+5YVon@(IS#q$W~3b&+oqr0`Qncd>o!3iu|D zyk{7l6v!0SlQ3S0OG9~vNSsbxjIp`cZkRh%rcV77_EGFxE2MHUjzi@t9oR3Ux3?!p z%8rZV6EB64mqdew+Zsj}8!Q*^B)o`lTpa2Y$La(GGlSHw@i;*tVLUNw+@Ga0d656Y z_9~A^8dY87x0qkWpG&`Mm#eyzPUs5aedAM@2P-fprJswgMh_%JNOK&X)bMoSsbk?2 z@bkmMCvY03;UvW=sLjJ!jT4n2e902CuW^$e44$8blS*s9CVORjyLx60PT+p~-uC-T zQR~OEu8{}#wvSrkxMqG2GYwuU-^A`#`*aSh?1h1yPh&-6cl*oJ`2*Y8>bZ9-&U_hm zN8r88WMS-1GZDvTIpU%bmww-dTXA%zFtGi-a9kAP((c2~75R>5aZiWi)QC&L$wZ%q zo|Y7k-D~;Y_C%z4_36Fs50vh0zc0@^usu3=VEZd}%u4Gu^Ml*lH8=?lyi$DaFYjTt zVm7_`pfE7w6+2F)ylV%)whqipVfT@{(>+kv-`e+yMkE6rHs$=WR;wXkn+ za$q!Luu7|+rq@!U@oqG;3JJ%l5Eskhq}f+`?cgL9zxh@?n6p`@YxG5vy+s926c^5`JyM5e-#$66HH2E*aZD@{gh~s`SZbRpp z3~{ns`#75;gZIDVz;hYbz?IT_ju)CFFJ5J{D@q_cil-SBg{!W=ZY0okeQEJHlj;*% zbfWM~Y}stc98D)nfDc}}*?IuniQ`4nF0;R};$+cMQk}ObVfI7?u&X1e)JRu3yy2ednG5 z?)fwsc;h?7wGZ$2t*5=o!{H^KaVO6_Lo*)BCTU0uKN()!$=zjoyV`9FZqEY0hkPEK zV?-R0I4xz>@X>WrbU-4+d^o)kyS6LA(lgBZJNq(t+@vbV7XF+iDj%QM=9~7J9o}(k@#amNsGNJ*lK@YZzWciq zE+%N5%j}k(;RWmqd7r|LFXj$&%KKvMEMiF0*UklM!{Sll%TPbza-g(|*TfA0LM6*Ea10t6v@7e85Wm-eW@j+U`fX z85iJPRI3=wmHB#Sr9^V)`99fotyAv%=M-6=GE#S0UraV~xp#`-jnqC|cYicE_gjxT zzXOE=?cOXm^R~W~?z)(;ht=_3x42`gTdcm6(KFmZeK~TzPZe;BH5Kr-T;LXK_jB9d z8!hkCbSZrQHC@pc6Q_nh`d1Pf#l7=Yek5+bLz#I`iN;R0b9;auAIIvYv3~$hpIpnl?ty3JUTEHr z<1di$K)inz`DVc%r1nj;D>kAZG3kmJ&2N`&BU^jWGJW-@kTvbykG2`Ptz_3X3EKzT zb}31q+XmaF?u!Yct;fS{tEoWy;%;x9)rd3REf17X>>u!XL_yomrY2|&?!@+l_Qayt8{q#h;x=+!~)~C|cd_nou-?%N)7gsu*`6rXHoWTjxqeTK)I;alUgAx} zt}x8X%H{jC|3V+m4Wbur>Cwp}dlC9US8&Y9dP0w$z?Uxe<%rsjgm7P=?VDoI-hWMh zR%$N`KP1&PybJwnR(rzvgc#@T<;kClaXjQixle^tO1ltt>%l$fa-CZ=xYX5daae7P z;mmbcioUbVz6rco;>%;QHzWAYw94uYow>3e`Xc%|h9O7%8(f-zf@3Ibm9G5YBW3Dd zMKA6lM7@j2=A8>Xq8WKQY;LhQUJlQ{PmS6FTRmufcDkNy6rGvG|Bg$(O>>ZGV$`is z?Z}bx&KJC)9al_(b|*9_S7UztF^tzfqYm1X8PVG;keFNHlX7^cYhH?5y-x$~{@18K zw2qYDi0QRzA4j~QXRf5J$Tvb4YQ9{^D^=}cIO*Py^9r-@&w$5gZ>Z?XF#Mhi-Bs5qW5U4=|8H{D*pYVOG6-mx1Yl`0M+aj?n3THS~t{b=9yeV4g&Xe`kfZ#v8i- z%GOKZ18e?tNxsb{zyl}{zt*BZavfwm>kX0;?hV!p=#5HwK*w!HKd1%tfeHF#H=vb7 zQ|XN>bJW2ckmqnNZUje{EKyABSKZhRbx%bjw8_W7xYj{DvhmD{G zUlVB1j1d}3PeRYr0RI_J++-S`Oc#b}eHw(mP)DCDM{yB&9Nc2N!a|JRP(v&0o3tCT zm*P8JccGVD3?;5H__Iq1okJjOww)j(pi(IeGT6uUyD2H--gZ1!-5Rj+6GAS!8@;k%}}*tEb0*;&>B?Q z`RZIdSH0{YEJgfDHx%izrl?(2z>u5hRqlEja&R7@sP8%a=g($(9Uj>(rEQ`|z3Xkr zqtvBLP5?X)PPL1s9%!htk|WA2jK5LS>*~|^6a>C58y*wPA~#y!pb+SNUwB4((aWXG z_T_leGAPpi)Ss2KA9|$~Nm}8Z%hYo6$id6}E^DHsYii+z{g>GovAVNfW$nlhc1AS% z8@iu5oax0{nl~TFEQ8~m=>9qMo|xvQDP^)?javxKndl27S5kR~S^e^HU3%`j-P{aEU!;;iTaHbUS z(qb-yBx3W1cK)4c;m6SS0bXEOaT@nSG~j&y_>c z$hlGHt+uglXmlE&VQS&pWD;gyQp3qB2a*>cq;oS(zAS<7GX3GFkf(>`@gIH7&_>rK zF2j!U1@;q*(@@WlX_Q!di&3&K^zZ;NVFs(~y2t}H&|_elK?|T&66=94(e zPLE41xW9s>Wix&_q_RZAq}0FEfmN{@>QF;+9`&mCacYN8reSpvq#Q;^+86`$x()GF zwu|n(;2I+DBpFPOS8jK$WIZ8APq99{5gI4;-`moErkj{l=7K*B8LVKFAiHDvekA4l zwd*`Iy|a=|iZ$`aA+0+v?&V%0KZcHWoWw80#Ve{&qKV!k-^$`~W74qxg+&JXGroZ3 z)YZ%0K*A_1Ny0m#>G`+KRW>y+N{P-RDu@S~y^wctM=){@Pt}mt-I4Bh#5quk5w6Bc}JIIQ6o z*AI^9^j;SGfb@S&ugr`0{-Pc--XJJ}BYSQ04y?A@?IPGJ+rgc@viF_ySN38(Bt6Gk zl8ly|q|`hH7=WwPCvdw9>(m3EGX+`-@A*QlH+~F#BI(z|+owW}JKdlT`j4SQ?WiSX zmNLY6t3~V4q70^`OhzI0rH>?iO-2tgea($^mC(^_7GYy=9uJ?41%)RPI+ z)RdhL8_Xu)%gJ6<;oi>IEFmPB+eRj&KyzY(fuYxM@V~|^P8l~#5#SZU7T)&~Pp4$( z_*#kui)a#lxjE*6@yX)?=MFH95)vSqJw)dhr@ND9A?al{@LQwo4?E{An3IRE-V zJmDqs>#_1=aYO-~{wLd&7Mdxu+j9QZ@;mgD1%0(olK+hd9!>C!ljT6l*(T2$58oI12hY(tv`mIk^G)BeVKmfazE6qH*CSF z;$#@O(s@B#m=o$7Az#m+RSR1w`d-H}Hizn6R$;lbH&ifSa`N~6)7df7I%;*+S=>|3 zib;))*irtuTIW-dELa+!fF*eC)81v?-^!RiF0_vs+SEyLMs4BKMZXogUtWmaRt60i z%8)lIfcj+8!5Uezz5avUSZrF(C~0DpG0bA)Xqvvd?OR;+-{{mSeo;GLe?<|$*dpp~9WfM*Jw+c{Z{!6~2te$%_k zJnbCb!;=-f!YFD3OVqN1pq)A1!fm6~Lhv8Ukuxj?E#)QV1YpypqTjyql^x}3WN#D1 zzg?&Zs0h+fx@WEZN9g~{fZjx>Ka%rb=agPq4Qy`V-ICFea{Pajp#BfY*uIXMsN8I4 zS_Nc9rL-5th-AE+{W5~?&g>2S{iZ=s+|siO+cm*b31`a|SQ&&zcGIVGyZr`6Su?u2 z*o2!#{8spaBZjisc}a|>29?cOmzK?DbOy6`nA`m~vqI8_i55hA6TWE@om|$at+wck z%$gw$`rto?miPu^h9{Cqz`XL(@pO^~Hi?e-G=bVJ=!aaSadKw+8T`Lx_0Yg<3s^bu zT@Fr&w)&+U^;!27l9M)?rm0$FX{rl&dXmedz02SqO)U(=UO3j9?1X2HDp?xeaG*T9 zjmtKTk@c#&);l~P!ka!$B?lKVxfdL-dm68BFKOE-xf8Q5fnQ|U{}__x5@?r+Iib}iyARToT8u^ zdq5Q?tDJe=GvhHb&^clLU7>BIB1Tof$}Q6Suj;nAGS0(7slJP>vJQywxYs+$KG6T5 z?HUXv2X4X(gBQ|cZ+pzO*!KH7emjWvoX1~}~K*YdSTpjE^~uz zp!m3+gNP8V=P=43m3-X zlr$C_Z;gfZ7h|ERc^~Lzu-(}i1rG)rNO&Cdf)>7k(_kk{{F_BK7LNeuBQN+a&<$@N z4K@~@@K{Xop!eSYU-jK@A#Kr1ax=mHV`LN_7yc9(g>U~qjRMOFHpl90`w!@U*R=Ka zO1oA<#{chq&rj#k_ZwS=dfqkI^S4d|&dIzvZMMO~FV=s>7*H9eElU{&jm*DJmfhB< z3whL*@LmA=Lf%+6H+W!WE87jU%79hH1)k@*fHj6p=(n?zFUBY581k{oCs)Kn8;U~T zf^n@C?O}N}J888@1Kcyj^0Taywzc=B6(SY0s%B?!i$|jJW0bxa=50Wu^l|)7NW`^R z$H*Dd|BcJ}%tO#_G(cx5oco4|WE*y>kWxh@;@p+;WF@nFH?*52X~@p@anK$ds?`Sg zcV}hnY#)jDdgkv*s>cTShW|UL3QmPnE{2$%6`m86K3=9ot5|wy9>6ORhq8X9R(HKr z%4hOZ`TKOY>cd7ToNheQBqu`3^^5u-ZsL0AV1>)R3%2IwTRpWNZ3w@gi1+EYzGdxL z4}GvtJTd5R#tA!uoP{?D-HT4lh(Hz(pYJ*N>792bS8IA z26>>2jR|UC%wwJ{knUK9ZLlc`2m4mO;xc zoY#a~d9hwx-=1PUS2*_UxQi)uU5vya6MW1tUUaUM(^GB?Vvt`3H3;p z>cR47Y1g-Nx22P*-M94z%ZEvdSs5~v!Db55t2_Q%8eVNc8pW+N;ZfNRSt;5)W<6rU zc|}Phv>xw&@UYSekXKmDzIMHu`e@v~_9T{qX-PrzOFwg8dm_tW5;U~Z_O*}A=vn+we^^}hBoh?76@3f|-0}!u_vuTnHdXtsy z)oFM?v9i4keK>;YB|_7ROsZ@zNW}ZmmF*VvXB?XekYI;*71{3NA~dbpe`6H;pS%w{ zMn$_9y&IjzU*qnpXg5fu?Sl+CToUu3=SZt)uT>*g4Ms(c(F3M~PAX+zJE$0xP!ZW7 zFiMg5a4q(=Cq&}QBHxdW#8*eY9~p_Si^PwM#JdwK+Wl%Pqtd`buKo}^jEan>higSe zb$0n)+o)!oOWMCdzVN4c+qPhX&U$6M9%v+QDJ$;{x1H@ zFy0$vpCJc2byRwbr}~)d!<_ENv*H+)ObO7}*V=ywz0?8PU80he0+ag<@~_|PGQYqJ z(On12l{@AJ-D(2lUaGbVz4m#X2UmXqPV_*ir&k$>Bdh$wDCd8?-{2soW8z-wC^{y- zMr-kZ2d#A+6L%IqRY)cu6RYDui<@9&!~9GqCuTFsoR}{;i2tohSm{p~NULeE!sg;Y z7~fv9+TQBfh@PuXJYYO&%b{uNnP(+sZhEO@UlH=rHdF>!PK zr(Kon6z3Mb1!PzMP28%8|FKGMNnZB_30r3^qypfJnl)P=ZNbQ>=e{@3uT#P&vvDBw zd)$u&_uQH>=Go_rGdO<$VVnDyID2c@^5poOyJH%>tM9|>=qTK5di#geA>fJTyV^-76mkQ8Z>TLs|AA2mq2qWju z?lWU-E@bSU*14yXuk^_lWOIWc&}I>Fu_f+JF)Bk9oNL z4i_T;r;2^sLSfy>9s6misnPI<-7Kx1!y1 zOuR{GGQay2{G!W)F$NBpd4=#jAnzJjZN-xd=m_&iAnyv5F`ooQ_+#()i6YquulM`J zAf9b_UdQt)o}GBM;|Y^Ra}93(^4%N7D^%V!wrnWx#5?jHaYx>OXM^m0qquqbh2Bl)3Hxf z+zNA2n9@_?NjCG1)k>>5=6m#6eO`A5Y)Hd5Kqn+5Tfk#H4mEJoy>M7jlW%0JhwcVHj&Qpb)vB7PeT(f!uyPwZori3PRMkfW zOFJWyK?e?sOFYzN37$!v`sSP|Zj z#%GSezP8@Rv>@_Vh%G=dn83J^oL|*XCz!E!n_mdurW!vift@_(|N3SXcKD$^K76<0 z-of+BN$oLP^153m5N16h=Y<#SOcq1}Ntny}GJY%PKXj85=5;3ltv9!!zy^8v>RJbF z`)TzzqVvEvq9gMgjP!gv4bI9^ZI}7fituP#nA9nLl|O+FN6m73*o{i*P{2wvw`iXK z1%mxlR#kMSL|LQ=eq{N$LDA(aBjsltY!5zHSz#XE;4++X04+Bys%5A6?+Gua>Y6HW zHW&-F-ksuiaTPY@_vNVy_wj(AWOtvT^?iPSZIPnuw`C-a<#x5qWvmm13qOQReTRe; zp|1Gv;3TD9$m{Noo7a7FE$dMpwlHZj;HOQ%zQyj^s(9!At`W~CRgIlOrxkv}r5YQI zTvppKqpB^7z6(!quiE@L2?jE#?_J{qsU-M9<-E3c!2?^r^tqCEV0+BU;4XAI-?qt{ z>6B**DJXA$3-xZXh0a+G&k3h-4pkZaMZ|D?B=K!sZS>1%RwDISjl5Tuy2}3m5J9cR zOg*(!0#l|Q(%H5ai!c@VPG7@{ocMDpfsgIi05>47dnzo5sML?;b}Co}3cp{|D{Gxw zgoCh>0Tw6yA+)pY_4a>muDqr{OpLF$|MVrO8{Y&$Uaby(rz0uK$Zj6BmBX*&3>iWD zgCN@}-^ETlpqn5U>LZ#Tz~%V?qp2KIZBt$(Ot(d(qz0i_#THTKxKPg0&tJN@yzsil083`i7HILBy-cI24xC-}j(h={ zO$vq~Gw6{9`+pnrIP;OPUl63)srUXnbg;-kVl+$R=y+LE*72u7y(~4gAWyPImNZTrNm$%Uq1B{wDL@ zVW>`r^*MZaV5}{mS`1Ou4lidO<@sV?wR^F!`vaPMNw zDi4=#I;W~p?y@c|M@wHmO2$w2`o}h+RKAIQp~M$=dq)6?+~kQ%&pby`#(K+u#tFt^$plM?3*hf!Xv27aeNwYf)&oHlTz$|jS_hi4Ek%auc}{v)ww-oyK2 z(GNV4d$mAg;{EHS&_O4o6*OJ7e`Ge9!?0rk%N?BLsKd^c*5vDg?6osE$6#X!JO$3b z^u|GFNeSJnuyaUPg`Mguym(RbfreI4VT7~-lSp3kL#X%)F&w|%8AQo4-Y-C2(=M_z5HPZ(umsM?6aI0g9)s|LH;mKZ}ruCEp7a$hiV&YY$Wm+%izsc! z#eXlg$OD}GCy(cH6ENVI)#iqrlPwgKHc1AjjL8yw`1=xnx1r;poz9%#gSN)tgCIN% z{&iXK%3xzF>vr4QAL{agWm$5GzGY{d!^Y@GoB3da4XDWA3Xfsu2lc1kG~?uW!FcM5 z3K(HKpfhsNVc0?~2MfI~0;R%Hi~r6-K42oYr7QF_gY$9m18G&5O9PpP)b--ahM=c* zU2CDa$Z9x+9aw2-EjkD(7(4;?CH~nO%0=*6>cJy(p&X z1W}trQZI^=@kW^*O@s!WNtVpQ&{RoYfHeH9gyenV6ssWW^Y@9F*75XTM>hCf zylbi;8uHO9Jcl7>s+HmR%G`|3QCx{7ttA@pVDqQ1&pFiMGEo1d{)5G=J%=Sp^Bb<{ zzzk(NP6}e=cFgOnU2`$C2_6Zv1gnYjKhRUSQt7BI;mq?}s8O~xFL>5~R;$?DC&|)0 zKY)A73EW$XI+GNz%q-4fxU6}>x`_M$cM4k~Fs2eA=~t?t3rmZx%Ym+^^ihEKJInCC z?x=51?AQiI>*!4jdR;;5M5Ra#_=>Rk*@~5-CMkle+`RfL54V@qjL|g#v2dkqca~@( zaYAhgbcbz+faj`ok@55VR(PIJI-0~;1*>r(yBT_??`@wzFlYMNdpflVx)*YvAcxnM z7Fu&csDuAUM$^bMjbnPfi|w4{VyLA6PN@vO}H5P zx`UlEnM;jn^juaF?&^?P7)+UqFq>`HTVm|*1k4(RNauofRx=We-&OM@=g9)T&!r+pw!cR1<6F=q6p}Ea#3_^s?ycrq>@ASWZC?+a zCp{=JC+98M@9^klKsL9kKLO=X2As6w__;U(z#}+koxswJ^&W7-rvlw<1NKYCeuvI) zzzjy7@mvPtnw z5@oud^vrk1JpUA`hlbk}%IHS5_maLse7RbIeLa@Dq-Xmf!Uj6UF!4JNqagp%b5YdR zvR%#yjTP$uN#X;Hj_?6qfKJMcy1xd#g6=p`$^#a{RkQwKy;JWa;~M>n3PKBvtbJ_F z1$wxeB_kkWHe+}UD3@*$d&Qrk!8CAA?&q%RBd$;)aq%7cjP-w1<*Aa7;o28?` zq)*oZe}c>xXK7_-wpTK|(fQ&Gyw&4570)CxQmn&M3u>3)O6mwpWx(6_w8YPI#Lv-f zN?Ti&5pQ)P#Y5?Q8fF!AbL8H;#RchHnhbM{L&*jSQCXU0K+`Y~@2wHh1oAbmoGmS6 z0+X}@EAilf(bYPhw?doBu;5}SaFz7{F|TrSCe{x&X_h$8p@%fAA2eRIZ!_WFnjmQP zH$#hhyk$2-^Lq@d)6qW<_As0?IXvP}&8Gn?kd^bjK!ik3VTA3lw@=(ET6M!QvefTa zCc7C$GTL)9l+kni2>Tn>B9CYuw>{!Wq0B6F! zEa45@$v0v*{i&DkW;3SNS%{k}o56DXW>ADH4^s)#fZaNipP+-%W~aS-&VrNO1q*0u6%~3F!LIOPLd#CUj4Jkv?2i-(;C_P zUA6N#54^}^{^95`QE58TC0`eP?wF{?FR~82gzhTYZX56Ue|E}j9lE!)+)BfA>g&%WNkYWlrsa3F0X_?DT?*lRL@KA=@l z=t#W=|HPkeXa=8U7j`p^;AB0P$u!KcT4iibX4qxW0)zBf7JllWHBm{}Z<;K}f5q0% z!9nJL>hl;lBE^|oleX9vo#RoCqi8qyHHq*A;50qE1p5A~NO0qZxG^LhZ{lt4GeT6g z!F&7&!zLfwfO>K8yn+95;HmsF%-<1KM#7ww{zm9H?y(%uBYI%-fzw(?0uOMYL=^Sd zYgYrAM~T(y0u6iciGN(a5qf*z;KQF?J}yMnus&gHiMRYSXCJt`>x|`x;D6gt8?ef@ z+ceFY`fZ}sqJm~^!ZTBr7Eg@wREqgJjW=_t&F|te7b(1Z$iPI2KAeIW3$?h+KX~?u zaoiNMtZC|u&*2$Z@0~IuUtlPpgEm7KL)XH$QAh~(3$M2y`-O+_m)fVPbD@y{o|SY{ zzq%fp82;&KArLs%?-RA$et~Iq62GJ3dm!(84@@WAqRKv(enV#p_t1qEOrw;TvM;gz zJOd6})Hcj9HYV_Jy6~=*Kpjp?9;Oe|Cp`RVBpQ)2lLAN6;&9;xe_EUhtY6F z>tGX}O!HxEL--9JdBex@UHz-2x0KyGk&YT(*aQx#1OI)r_W4cVl6vvKof3n(d;n4k zh0i6UmQm(6#13O#ISp|14bgA(w`>C6^q7|fCnax;v<$QMR?8-$WzH9^W_go~44A7L z1`Mag88Y*W$3exi*1jsvB&Ws2c;1WWQW^-T6Fg`@zlOw!hjl z0^eF?ul9`8ofhp0Zy`1};R^oeC%lDzDM+~T;!8-eC}Ed48D6Dmtls^-Xwj+Jj=&wk zjv)6~yKg?Du|BTcHc{Qg-tZpU`C{Q5l`?fnlMA_8W%90?)rzjpGB!s#2jpGHS1W=G z48-3tuoJvpN4+Ar1eBpgG#U(<2K=WPcn`GJt`|!lB~=$iOCi^rF>$q$F5H_@_}IlE5JW-!0gx|&I5mY7TF;_gy(&DKB(I$ z-miPBzV>L1I2rm`G&UAmQ5Mh>7!g`8^*`x+(P337&0N!fA^cT7zJ7o>o;MeJS2!KD z(p*=$jVnqD3s<~VxPQf!LgUJk;=+}06<>P(3QE08ms%Ky9fdtBfV;t*mx1WV;AWWROT`_zIGw|X7N=*+Yt_LYT8L!1FTZW|>K7(ao%~O%YWN`A+6L zins9F*zRRsX%OQbQPuA{VMXL;oJ2+S#n3~oirt{AQ2LzKWbEW*GQStpy9+mD*qtcr z6xGm+?tdS6p}?_(70LrtIsyC-$jjeKwKFP-;vUR-lm~?;c<+r+ZNEam?}z0zOaiXh z1+Pi^8263Pj{c=bmGG}L014+R>`(f)HQ+|dArUWF)O}5(C_d(0_(o`He{0!|&}04P)vQ$gyB~_! zhVA?DKWcZj@USofW2tn{Jc?T}(Z8i!%F1FjniKr3Wdz1D%weh&Fs6fPfVQ}iTFY6@ zMqupkjBz2R3NbEVq(*X;zNkZ)k4Yup2*rUvv95C|_J6)KA++|IY>!EJ3z&QS6lcj6JCjuOAKE9zfRbWX z5Swz1zxtddjE54{V0t~$Em3V&>=fb=k?F)+*LsQ_x7{UwgH@t z9O*2}V(UE#e%IH*zp!#u9&R|tOBwBTyoi>PRGWL_3VKgIN+~X)ecZywOJB3iIEP;g zSXuF<%+_YCo8cKh*YEgLEpY;VSsUg1xZk5M4T8@Dv|htON#FZ+UGMy4AQJb<3Qk;i zLAph`IJ>o^%8HX8oEOv#dC%^rhM%Boi@SOEgKO9geoBNh7RJ~HZ_HR1Xj}!pbFvIN ziNCm;-?Hr(wCZ@dZccFOXcxPwYm_N{c6cB>08f9=^5qM5i!!US8i=^*RSnvd3!xny z9PA>%m9P8~bc8%z4aw=3V)25Bf@()P=r^Tx70{=nb{e5cKl3JTDk%h5O$#bjHFEe2 zBm^}w{23ktC^+V`D@n?i-~bW-@?M56N&JO)wo1McoSCc!sEJ9|b#8T73WT)r=k@2s zSaJq*&ZXzifHpt76qKFe1Cd(JKt{*VUs>%ED}PFQNHF!p{#5~+u7g7LK;mW&d(a1> zreIo8(I3|o9r)vsBA3Zu1R08s4~zi4aawef9X-QwGM@(qTRyoE8r#7Kb^iT~B!y5f50niBtt z`Pp;GjnKy4)g_jd?3b&TOwdR(BVkNix4w``(aH)~51SjX|Mlc{mqsM>wo!99{`~K3d=?bp42&JYAq1tvupp6*Nn zg|@XX0U9Hd;<1vM3HVTPkSceSwQ!Qcj38+?&-1Mxfst3JeT5qCY}yFr{GykKLwqJJ2IZr@mz`bGw>|K z^Bz2(rK38k)r!|PU}t*zu%(p18_sb^W^%{NcD>&I>Xz5rcfO;vXFzI2QWRTryR9qO ztnahGvO@0TmBer8$rW?8gMB%w=a7JrdM@Q_c_0K?uzSF|q8SqtCeOY3?R2+df!(U~hwUCO_D3Qx;Yc?o=wFRg=J zXRc^|cjF66QM>dM{%e-XUsQ_fr8)SoTDtMYTv55yEsjPGJf7nU9>SV*!^2gsXh6=t zBDrFcR^3@^t;4RR^wcC(qmDWOHRR6xIu~*XRSj<*(_{_OIHsFiWg7`C(K-iC@W#R0 zh@+!QLNUPjUuE*Ki->b{Y?kC;N`~GtDW*kUlM8Nil;?}A;S8u%mcj>J_u|8GUXrp5e~a)Z+czJ4g!IPT?yu%b*oP=XS=(oq?TZnT zI$h%oI3Ir!&j6>>g?Zm2o)$a#crW_>nW;j|mt)85M4LviHWj4^UoFlW%T`;bgd+b$ z&yCP2U^BOR)CZNu8=-SzQ@v&{G?`!*XYZaj|5UI5{%vK@l_&o9dX!%5mT@P$?a=Jt zq<0U(MuGTef?xH6ho)e+;Vy)duSP-EhTZLe8Q7)8@vJYk?^=Za$ts7*!LNi4+>~v< z?*Z&z#Px8a)&F5`ck6W7VazLVP{O?64f@TvS;xWm1!ivig;2mJ$L|ZFb|2&YF)zqr z?$@B*G1FP+g<5A($$p?-04uhS3+yk%e}fe=pbG3w?mkB`u=?Hm!S`c2vUsa{iJTOz zunMXbLPw{+X6tE56^DE2G?U$G zU!D_apgBriLZpjyO$^h#Gj&0je$IbeW2hl}rl-I~}u=Fh5MXdjAl%rGW0fpHciW zPub#h_*&rIG&5{p%>rI3bF0j{qSfRl4;vOzv^LbQ*jaxWfqhq#?KaWE@&S!Fj*3 zD_IYkC=>ijCaGdv^}%*GM$_ut?i~pv&;+R`m64P`+UEuR%5!KV&QtX{%+Pb9;|SN4 zTNa*U1X!LLczcE3MOXE6%)3X8__0rSm&`*g%m$|RVLII~O*c88J z5R*M$q!SUlaJNn7RtocTu798E<;N__NjaMn%zFG}_acqK`RA&|IckqH=|affyMIiY zpupOCpzVyvJ7T@|;N-%S-3#XfSJzX!Hq4P=qiBHc9~(vUs13;N!Z~V)SPd9@FN@H1 z(V6(e7eYyGyx>pQc>LpKDNhRo-dA-v0pr@NZTxt8e>bQ@5p$H`ebU1p;O3;hP;8^+ z1PJqnRKAJM0>&}v_P}~KUGJu&=&U%ACK*#h=k}wn{XKa7#tWeauE--q; zH_Y+w0dua_?NK*h}E*#NWS!rQg&nQ4x~Qmwx-IO zv<61UJ?70l!fwIQ7aCJFP4l{m19VOq+joy288Dy0ZCz<-yX;JjX<}tIWZ0zITTGl( zr*MdtP4}*er1(FP6d8Aa)08xCCFjT_(q=+C$cI%5%9BW0YTy0M4%H=M`3S8Airm_ zMQEL9n!xoLeJH%k51mPsf>Tf$`$MB8orS-+a)TmpAQ&Cp0*%ec&CQl2xFFT10(}iM zR6M~xu+^1eudtEeE3VyQx{miL<)ns59EW>^;4}085iAF_mU_Y7ZKJ2U1{yu0{DlwN^Lb*UCV81hA75S0R6>Dy&1RJO&H0#?S5V7lZV57y~-a&214z9%p;FB`dBNJoI?43bA6~Wt`c&ysih_K zpB=fu7vpS6=yytz*V>PZZp(4pua09UJ&ya;anWmG`}F)a!YLcdX6FVMjFMT9TE%Fl zCd-nf&yiAJhTrf@$bQqZA-aRebA#iDv)vr{AAu%iO=}i)jb^gMT6h+YbAwM@JJvwj z^2i401bh;>78}*XG?Z2+nb7O7F*gr)>kK5_+O~*Tuu3n$OPQCj{qhuk>l;qtwoNVA z%SqT;0e+t)o-<1syzKfgH~1z2W>|!ha6_gQjk8Hz<`&Oe-1zo0_+zDZJ$lDwZ3)f! zJKkd!JG- zFa~Rd`6C#5lXJ;jPTnsxk8N_8W18?@I+SZh-zwLoHbSqk0J>%rnyAN*Xbl6QaRbkJSNY|j`{UwOX(YJHh1!uH zTRFdWgduI}{W)`%$d&Z?5gF2|2B_&tuMV1kkAs6fSg&EGd!={t**lCitLre6O?o%` zwsgZyzmneFcU!vQrpeN~DYvB?XJQhz!Q2fdt(TRrG#tFlN*;S#%F%c9k50-f`nLQ> zqqkMJ^))Rcrq=S*wV1UsSWLQV13Fp4#Q3HkTV;Or)VR2NZEo-~HxUK(l2x-FzP&Acr%$~5J+P@*aQwosC3!fl}h)7aZWQ%obhpZem)t?N8~ zXsGsMO`rWd6q=0Pdnj}l`e-Ob%LYP|Zpx?8S?fCA$IeV5yTkIolLnj98k~g|H~ROx z;IFV6T63Aa;S~Nuo-%d2Edl#!jt#wH+ir`$VC#OU=tTFTqV2YaVTYb={VX_Lx84@* zQ5YV?p7&5D`%Z?vONe}7b4P)iX6a@i9rY*;_jqm4$xHUf8cqb~a@Dpd55f-oX7O&` zkc#w+Y{~vI$7jJMi03??U6(nMyt$I6sef7Pd4Y4M*qipsr@moq~SdS2Ma*HZ3iAk;D zZCzi^wBQp!Z#EvC0_{wiId)2HT7DZ;4_g?4{1dvM^StD-JlvE<)FZOgscYiK!P|7D}0weqkEllq8Sx$q8+xLc$ zEzrIEYtEIKkSc6|KJh?kDo{Yaf!5yJIBoKLv%8;7vD;B+1>NzYo%P}39CHJBDn}Si zBik+Yd8TX|(=sVI9OiNiqVEmbs(oHZjKuU?!39sc^9TM4YZI%WHFbmvZ#*iRwf5kG zLaYzaCu1Az-3#JQ28F^ZTOv+#VKsE)aI#zd-4&0Dh9rA;Ry<-ex7rklm3|j(MeJq7 zj@Ob;X5+th!e0Zkc-GrzFIk1Z0*O|MlG1N5J@V()OXVS7U_;<8ykPzbaQDHnYIsyk zPg3Fg^rS~cOA@;+3&9c_i`{CwD}pFt^*>u-1^+~i{P-ITUBZAcKSBjz);OU?jIzm78=UzgqS-Xm= z(H2_;C>q_V;6fmTSg%*P?A>!&$jU-TT|)Pog45k)2$Ab<#N`jh`BTsb=~}tD5t?G~ zD2;NLdBW}IQQvp_(Jn2teLx=xt67i6Na<_gx0==Ukv1v-l?f|{tJnt3(+qI$lWIFc z)%_kJH^=IqSYatW8c@Z`gfqyy5qL9f7hq^-Bt{FLqVW9-3_3#R zFGJ>w0ndWag;;Cm# zbSu0)V*LA?AqC-0c$37iTy1TQ$f5My8F<^S@(SJ0M0(WLRgru#>54MuJX=F?*2lP`T? z?FO|4t^FFvWLrYpq;D7NW_Vd{H%YUDPuczvT#NO` z>b??Gs@4B$h5QqinqWpxLTciF8LQ=Y#RQtogfA-uzY`Wae+}5xWq3Ysx8Oh93H*g@ z7O;K5+{gBT)u@$S+Ar){C1y`aMSba-(ztBm{}OY?nuKrEi^Mc&#L3-kAN?dSEVldN zCz6j(749jASb1nSfm|8BoU|jn(a7Z;7ahm!gx-U<>iWW0gj(Rsuod3XE0tzEQlhgH z*gojS)S*6q4J@KM)ab`v9cuIn$}P|e!Q!~n!Dr*x`rLpwi?p&&>PluqFE?&tqyLYt z)g_FlsDQ4)qtM!|54hIF39B%hRvJdx1CGqXme88k0KC{*N-+Md#9ZiJU2;ZT2}2EA z@O{eG;gOQH_Lk6-tCAuPyi}vmD{q+MkElK7E4`Gcdh1#>+WtlaXUm z{3mY!6YUGDEqJ$-p4B3$)!zLDP8Px+DR~|UH7l`$a5y=2t@S0q;Y}ij)rD$sUf6hI zRM0!mW`%o4cA+jX>4CdF=~!VaSN|ip3g^YB3qtU@Nc`9aA^7zCaN0z-&|Q-CkKi-x ze8KFuC(RjEUxZmrS3~zh=zco#y)F`$A;kp>hjN$)DLV^V6!`4_&3bN-93uHENBET z0)p^F?Ao&_B=y!R+YFC75KCOf4~m+B4VBgX+d`FOp?(GyE$V;*UaXo!)33SiL%tgQ zr^pd)P@9@V>DPFa%m-rCANtgEg|BT*M$ww0j?jexS3QsYy*V^`fbEp|x>5C3oIV|) z$9ksWTo_+RydM-X`-cy3MzY#=gib&|&w|?e<*c>H9jR?S@T!_+#u+?^_Jy9i0g3n| zgIgX@lQ)DqUs&Fz|#Vi*9o%0_ixj4d^SL^_9#X%v!S$_;;tebGZ3d@XWbW!5mwGRhez| zpL4yCuB&&I)&I3?v2$LxxcWGxx=O6>Q;6lYANq)Th0pse8vzqankQ)?{yWN< zMLr1_+Lf`3AJ6yaUKg7;EC+?J|LaW^L{W zy)Q1gLaD)C8!&T*8J0qWu%@uiv8JRN^vP})kec2B{uOU2vXlf0$>_2omeazH`MA|T zQ>yk+t{|xf+@$qDHYKqag?r;vUGC zWI|dXO_dQ2s9(*YG}Nt(tQU}m1e_KJD`oP{3@3cWLwYn97D5HktFFKanCsZ=V5yk4 z!L#I7-k{U`>9^2)F~Vp3Vtgg<(7@*8KI}+zG|)z2hfIu1G4p!bS>5LO?^4$SyObDR z;GQ&xI@)V(;<-BKno=DsJ?b2_mj_$G-oUFE(7e`lmLDF5(XJ~+Z&0VTqD=#=!lZ^X zqORbKI1GCAdUy*9-#XaW@Cj~U^f=J4h$^u;^tX1_?>|CUByuMKcRpI!(F(IL;egW{ zN*v&7EcNuYIl&4?W3Yy7vZ>BB!-qHS#ts5BLWxQSnnZqZ>wM;m*y~(tud+=85~Ci} z%q*OEBQFjI2an;1J&({Zpn{gI8rz`6u3(^XZE|Y$zswMU$7$S!CD5aZ(|DUhyKX3r z|8coF^y-b_#xE`xmdK%ZAD3NNDEU_PSPjh~#|>y)lVPA#zU--W@@ARGQ3A_s=$O;+ zZ=CjyLWT!4&;Me<@J=%B(*dH`0H0ot-zeND@2*AeX86gTVB8H`GafVVAyDIrCBjw9 z3WmyoJxl$1`&@Oe{q^>|wB7Iu(g%A{_>y?AZ=eF$iQ9mzH-2PXhYl!v7NGq6O3jdd zp!;orUFomlf!nXNmk5x^Ubn&$rzKR}Yru~9K_H`0uAE>lD8Q+80yS;1V$1f^4ZrS~^%9<~7&FDv*j z7#+5Rgr2ORPRD*_^$6XYB0BmCV53@*@*h_fIISuA?!;BApIE(xmw$QWX~&Iw8aPU`JOXec@_{*CDBiT@#S zr1!koh~IsoMllY*PvUoP=*)lyzt7*de`Z4PB#H9MO_cU@(rq+dNRzKeHeJP#H;QD0ILSKsPX;cK%n8L5)4P7}!F z>yYy)aXah?eTAIfB<6Y^aWTL&BE=KHv?V>h2aOF& z`nu+$F4qG{Bg|-!_sY5t`V_FlNcf&4f551uWO&}hnWJx*D3FPH9)8cZ(JrY+zd#~iTr zb#Yr;bsX+9;O=h#0tz*~1fB*>Rze4fOoUFz?h`2IkWJx{)ij67`Z#X^^33g{HD8EJ z3$dR1SWExbCIeSzAfq|-dr)5Tmj9Q%w*jxJy4JSm-U%UufB_LBA_fGEh!_zmQiKpg zM2d)r9Ey|%1Pllvjgcbd*hncwM2v_O5iwAt1gR24N)RC;Qi_xYODTV1q?Ga}AVm`S z+wcACIW{}(={e^;-?`rF``+(5(ZREyF~-@fv!uQ6pKC_Ei0&mM?j-?fP&i`w*GT%0BZ&elRl={!sU1~LEwQ4dk zetqHdFK?)ueKIAy8;SmZEbgnc*tC&xl^O>J9?LwJlD)U8|1mLEhf|YxoTjJsJ{FrA zyI;TVLwB^owR$M)u8|p8(sZR1^6q@hwcDba=iL_WHobQ?bXTg*nVi?iiT=`GWZ#b7 zNm^a29=T~djkh}F6=h9ft{h-qy?oTKn5pJW`xSQ+b8-SjE!hRkyHR!=d9HaX-$ia4 zyWz-l>8ZVTr1JLqA79YZz?l^#&*e<}t<#$%lGvA*l=3Uq4RWxLyU-zJZ`J8<;<8@n ztzo<+{Kq`sTU?O6^f{fu(uOY0(OV26-({)d%>YiS4;q2+XRdbF;RxLg(d%hIn# z_hn|dw`%Iqw48+Fv4OXa#|FQw`uIX1D{WNZcx>JGFP#1=a3N_`hsVa0o*CVwY;V;M zjt05x$FFWuR>JYRe3zN_dQ?~CH&(>lma;=%8`hVG-{LF7J>!>YhvKn9-iwy*24(fl zjOo<3I_B=PqizTW*ok@5=^yuap>J&GvpY_YifzUBUbvPXS$TR?;I?`@v|8+VBA90| z*}swi2GV}g@b#I#%xiCDd<$L9<2%u}?D$(w{B6mMG_kkx_6%Bo z>G6G6)#p9!`-1(mb}~8!?uhU3Qik3fp|9BK8_<9I!-K~jts8smt$4i_>`M>%vTE?< z(>di|#kgC~y9+l~o@NG+Zokw%%{;nx~VRUtD z)+W|+|C0T2^^A1A89;q&cXe;>oMxR_knZmSI-A`*d_?8RIy0ra)~K_yc~jI_jWxW} zpMG~?M`CucGI0d0p8RS=T2bTtP(Er}mY!XBj*;Z{>dB0Cwb)^kL0{CHg97dH_VJ#o zx{MDUTq~{$v32<7JM6}tlEKPc_L>ds%f9QqjIZ{&wvX;h__{bR;j8kxLC!9P{3?vo zJB)tE^{bnco)tsb#@__eg3YrCuRZWrkqU8TJMM!&Q`oF5FqfH_i>pj$X0gA@eG_;! zyze)4+`iaXpBptT?$JSMB zdY{GAjKA_;&NnkYQ%)AR@Hvln%(_}x?{cPb+38t9(%VuUNQ>opuk;w@?L+o@1yWqQ zZ+$i`ostAOSAP9ao?4jBqs*RL@>ZZ(yos7??tVNIRV#COM#H`7S@j9~i|Pc{Q(#V z871P$ySqvGeyIAUY`xd0Uv=y3cQdPaYmT&azY6j!daYkQM0<-J(Ss*=sf9aMun&@N zXWy%1drI`g*=O}B4Z)z0}mcs7}!`H+kiKDe;v$o&13m$ zIjhRe(|L1r;Eqzhr7$Rq?;y+~On`6RG#FIfJc)OIkje_a)v%k|4)C~HJ?>_*hFz<6 zod?5LG=(X_$^q=W)SKlJYX#b*6Z^fy9w>_a`q^w(6!#6HfzG9~Z=c>f#xO)QDy`JyXV2NwG;eN)Ouh0fszogw5DQW3VH}uNl z?d5m%=&^sFo6A=%s+*?==Elqi(|9`zZ$$WbACJ)3++a`Dy!Csk=C1eW$56f4tm#>m zPqexrz;i%c#a1W1=W@zNRa7^vTZ`ue_Eo(W(jE2F+-r)h^(=cZKC5cMH4N{%sueRk z&}qf_!qerfT*z~3h%-9+*jN5uKQWY@t!Kqt>Z6|pS(geH)#Yi^^qe@b&{b3yCRJ3I z_pSXBE&qJ2>TAjZvs}yi>@9SGTCWCXwQa#wSyJq)`>Q(AUbH8VcLNscT{EfsV&*Po zrIdP!55CHNuDH0lvBweuZM)ay3+LM3RZ*QzOHSNZ>(yv1SBJ8yQ^Q}Gh}kivk^;fl zAkQK_v?ozv2TI>balUe=&8Zg zEz%BD$HyM1PJB#l>leoZ@iDJGT%D5sY8LOQcYFb<1CkbVeR5XM4Ffauws&`{yAXf+ zP1b84$l}fK@kJNDI<2=+tl5yB!4prJu{$!)x^$j`aBVA9n}O?7vKI19^LX~bq+b=g zSI;ul+VKOP<6oE&_t_oS$5rMvbBr}OvKo)`Ff@-sS0JoTV{TPM&u zwtZk$*12Il81vbYGNih7(qNuy)Kk=--}!PzKW5+$-&<>*)^lplYuY6KZ^9mvr70*mEI9N`@;E)`X;l!Rmf2cCSFM3J(xW=JeuL!_S`TuqgRiXdp~Is zXx{zUp=ScG^8QTj`Id0cY$5xEv~qATIXjc@PA2s0v2;ToPe~QV>fOOBk0-<`R(*kT z&4xx<8j%BcAKno^cMH!(C6~v{XB@8#bX<~Ayf22j;|o}NJLjv<^|*d-*10Kn@?LS) zoC7hn=jmPag{(|H7gTD2yZQHe<(u!yHi_gr_*HE1)Q&((9XkSbavayJE+@UomG>#v zqere7m{N~%bM1-PtW?f2`>K9-iFtiiQuEf?`>K9(X>#~CBVqBrs`5*Pu(;+r5AUlg zyHuI&L#(=#GL)GhVc)sby=kD`(4k8==qokX?$a}yOE<6zywA1vz6&nJazEImP8%A( zZ(ntC65r<8n>|YR#ZOY^6ms&^37wVwYSoJOQc{BNB%&RCk=^h)JVTk2njN1qX6PQS ziIb0?jqc4zT;1T>~fDYrY+qJ?i~Xi^kCr zs_oY zH{5l8*M9TDQ%TOXdhpn@b-4T4x>1%|M4+Qu9Z&A_CgH^=0!_~DYksOhpk8LL%%5hQ z*q1=Qn4L}!pY^zR%DWW)@r_E>XZ5Y0^egXA_;NDOgl(+-@(jMMms}M0(sxGnuf8RG zSL>rf-t(NWl_%9dZBqV3ty$E^;h2|Q4qq#;7xx-(t}os=YHpUURyZGL_p81oMPJ4| zN9}Fqt0ci$^+Rc|bNr9L@#RO;@8_%OKVcQph31Ceye7{*RgWK6U3ceLyz%Axtj(?b zEnRecus=JS8R=06)e7R&TBd7cI$?eSXT>Kkf{$g+6>Ndr{K3RS&P#HHj zE~n>-wC67ns!k~F(p91BYveAO@6X>@uU1y#Kjb>`c;<<;N3ROqP)|8m{*+JUFOr*F zyQ1AwbuRqGzkT;JVMPYxN3&j>O>{2V-D5r9Vbc3BcXN)`75is=4WJhzaopTm^I~3e z$DecMn$fj!tjou-bN}V6>qZr2Rq)jkeQ{d$;PEL5wO)Fp`j)=sIlLEq`kIsFZ^ad9 ztkQAuwY(~v2aQ8{)ReAb-Z~LTII-{ZF9*W5O#jKL8#mXQ`|PQtQ*V6v$osUs&;Q5{ zigL=OUc!|a?`|z_M(rhNR=>F^JtmI&TSiQ;sm`tTYSi41!YKyZM$&7r?`+5=wmsFf zK_I1j){ZaTt--YTJBl;-n)GdfQ2QIc<{gE>%0P-dirE2FYi>Hnf5pk6o$n1@{QzZc zlgn3^v-!Gq_fY$>>3pp{E3~>^y~^&iM7)}$pQ?wY!2@GYxv?3c6>R=nbz6|{6sr!t zqP$x;9(gCXa;%;YuQcqbY7@?3?YZH%0dlug{i_!5HPMKxJFAYb+tZtx#HQV!^W7e& zD&poopEbG1&+KU#eXqxVX}soIe0W_U{mwhvq%)66`RVaMdh%_V{Vz1HBc9&$=?}WS zc=5x#Paa*+{@PzZ)ak{G-8*0V>m8l;R2?c?!E-mkcN&!Lsfs&aud;u2%d3Xwq#p~^ z+QWL9yDgSAl|c4RR(@7|(28HQlr*&#u5wz`y@hX{eU%(c%F;g0+T8yN1h;0pQSn0~ z`#QD8Gh@Xy%-dtLu4b=ZOvRq6KYY`wc~0d{y$!9!iYs@>OERXh;-q_kuFZgo%5i(D zetvXkbvjS#yQ`8a4(90VBkra>RWrDfubb6?E2$=o|Gh?8G4CYa(t3xxHFd|cqwYKNWX9$*!}&rqqE#g z+`DZMc&q#gQYX$Ek1pjJZEmT~6L0Xf^9!M3zKL7Jy#SZ6r>fI8Iu3!9`JAKLe{*&7 zVC9~wcGM(yP0;yu^6+|6y>&VDxVB2oo|QG1H-}a}LC))bF{VZCfa;#z+{=$<1=#r& zd_^VMQ}vf4MPZ zbEC-{_Ec?JlXqX|+i!Ox3-Vk}K|$V=ox{-C-PfbPd*sOx`L}g{d_-=68}@X;h$ru9 zHT*W$Z)oo0Bi#LuJ$>5)BMOFQ4lNk!?r=T(_wU;`f82zp{jYKP1>qk(a)%BZGs2C^ z8#ny6F{6g%56yqNvupKaN~DeM~oc$)R+P{VBDz3h^PNkxeq_kH^a4>kP`miWsZ7$RK~b*PZo^Gcil7l z-ur;-F`-~Y?(h-AQyv&M{HZY`I;Xf+?K+V2c5R+?{YMp$o9_7qqn<2q|B^o{9BRz4 zr^Y&pF~ap9H*So(cih;qD)4g6G_>=Bl;(UBu{?qQh{Bcj^jmmx8^(N?JPrB~I$B%ka zhE`AB<61p+d#k7T*Y*Bxzx(ffxP4lh8#C^)p^B=r8$~UTrIttK7Ib!xjmxEI1-FeE zk^6W-jvXfs-AyAV6pX#|DfejJn4wRPp=jT83H6+NYTQ#p9~(C+pYh|$ANRGd{QhS@ z{uX=J2BcdJ5s&D?YoDQi=kGH5nsNy)xoC0$l$=MtF{uWtkaNh_$ls7N$Z6yh@+EQ{ zIf5KU{)~Kqe1_~r{)GGi`91OpvKjdhS%>@@DMj8w-bCI&<{~d4&m%uUCLvEDW08@_ z_mO`=`Xcuu8AunTBa(*PinK;rAU7g6AWcp5I|aE3xdoAbC*)q_LF9W#F7hlg2l*B9 z8$@LaaxhvVJ&|$9tH{U5S)_Hqxkr(gkWY}>IQKw)iu?wt8{=GGC|xjm$>&A~(i4Hw;;Xe2!dKo8E`~7+HqwKzNYA)!|mi^++q^W+Vl<3i%pa1yYQR zK$;<+5YHGSMEp|`hde>rTggik&YP^gRsF`EW4oCeW` z#&DR1@G1=<^K2+|l!oxLuR@{bG=^WF4262r7(PE93O#u&6smJH6#B(qsaqPw(L;ox z5+6Po3N@i|occTz`s0C6=y#vdM)uPN_i-GM7ilm7WY!+yN3KH}B6lE9Bgc?w*dNCC z0m4ln{7&K-UKt9d5_b#I=|_5HG{%AC<970tPX3-FuXV}$X3Dab@*Sqky{M~0iO#*( zfaB2Exii;0H@LZTRjr-d(AK$C?Va1%i8}7)+|PPA*SI&wyC28+yUvZzb}s*MzQ~?S zJwHYLPNHsq!kZ9yJ;o1aIk%L?vAfv0%fEE)ns+#ctDTGcz_~piIrqX=j>!(^rvHih z|IE41{_NcPqt1;w<=lQ6)79slO9-Kh32k!Gy|Zr-ccZTRTxcx37N#d-IvAN=CR4;Gxd`GaP^ z%vtyDkMiGtYuU1H-23fz_sl4n|m zQ}~v5QeijNMY_3IB!~nGyKyDb?N7~W-FU~1xi`Lb5F6|1;`9!DY6AQiO>XHUt|VSf$*fbOGos_&=RiCn(?QgYlG-m^g@Os zQ;@fjazuasl|1F+KMh%gY($PAbPvZJb}o{Ao|^s#d1`{c%B#AkNruas11e7T82mrV z(|@;~{=Ga+B|kOmsb>8qVQYl^<1y@jPUTWv4?=Pg#iRP#gyV*sUisOGoJLZ~#~7p>X&wBJ^VAG~m9sO_2gyOE zBdd^dM1SfNI#w-_G^A#IjDb%?>SsmBexxIL=!A4ex*%PVNIk{luVWU8 zU&l*zosCRFijhUgVq^(YjyN7A=Z_x&{fS3@N4VML%wO2zF{KrRVdDV5vuJz48^-=Lv>srl;8rF>$H*8=K`ne zyFletE>NE20)_uy312&0ic93R4rTh^D@V=z|4(?eg8%#KFNX7(a{kYbpN{YU*#FPg zPmtagseje?|7ji>Z*;u>D}6mOX8m`=*KAM!EdBqnN88&!tDl-hf$%^fR4glzzNkH7sp9s%=l?$4pWhK`25VrA3Eb0^mhH@T~sjj+PRTs#ztaV^5E zIakH36#iZOe`TffZ&&hgC;sj6xrux$w2#H-Oz|miNm!IW<^TQA238XHu#$L+e0~!y z$0J-vg+e{tUHtnnZ}L&Ner#ubh_Z)5*P!j|?&aTFNC$VP)kp?c4&Bi-;*1!HDc$m- zGDPyCvNR9J^l!_uffd+~S(W`FT&75UJmPwgqr1ZSP=5M_f3@PuDw?Bvxdv1|YmuJ} z%aQWaD6CBXjEy6~TSw`4-opLe*tQEcxzc zj*?F^i#06X026ABsC+ug+5EnXy8eMXg;ywaE&MSz%<}GAgKrCwnjgv)d5CK#wT@a& zb@unAPsb8D9M{FuT zE3jx){+P>kF1Nb;#N~JSl+T@^$3rjB3qG-4prh*JJLP`wK6eLPh)|c^rEt0@-9^}! z?t=A#4ZL%V)qUhV+f_rM?YxI9QlIa*{q8ur_3oQ+*f&_&3WfH$59k5DZmQjjXtp88 z+|h8Y9N~AB`>XqLnEeX2m$#d##Ot^hbB?ovKlU?u(^)9A$Gsl5eV?_QP-v@r-*R=< zJs8$6XDzH7mcJpp-3#uxrF+KR9=0ELzh&jemv+AU3-3}>N`GRp`p}iWJj0E3etMQZaN_iOhl`rF)&aQr{w_s4E~Qe?MaFOC@gW-V5WSyj1c-_eaj1 z8p*huh7UVe_%{*x4l7B%u133`yLZui8=2qu6a**R@ zySu~Mm)%bZF_6CNy=U=?38kZ6{F87FI${6EQT$t$o0r^mVecYlmZ8uT*3eXoeiR$- zvfN~}sqR_#Cq|0M=>8=A{|D$bfd>&8^BV(UZ^JhN&y87Rl-N+W1VKumX z@8#Doe{=bM`u)4%@jr6z3%SdrcZ$9q3Y|ngr?>l@{N8;DKR~|^g*G53+;+2k=FY?4 zp{Fa2_4Ij-2j5(2@zGu{d!)x7wa^P(75+bVd&8lBMPKLsGjfc6sWYC!sOJlhxS3eK zc6-9?`-~Ey&@*nU9rxw*etEs_c5|mzzaDhz_uc6CpL2%uts~c+L3cZHm@TgIQg050 ze#=U*FR4a>XrI}cfN7Jq0-v^NA>G?kWXzve&?s2zW8BITR74&@WzPcZUieP4M*9D6nU_V% z_$Z?Q_vhVn;W9R5G^yG9-=+6|J8XHH`vU6skrCil*dSNRztU3Qnbu^-VJ%QftL#wZ|1Aup4s@>ns?;mn+FckVJcNRV&*OAsc%Vuu3V7m@^ zi9YRPP`{3z*MGvDDL*23>tya8vJ-%{bkFZ|h46Uhd&*ICz7xr@W_tdtFZ(0z+OVI_ z{Et}-8U_3qAdl9}X@u(Y57QRE43Fu4j-#IM&;0UG&lhUGcdy0O!Or`4;-@~}otc0? zlIr#H)_MPq@UN@Gv+u~ftmdpwetzbobN`)}Ke+sAXdh!*eoWoyq)t0j=&eH0w3T#xCB%8#rkuxgf| z@niw=Hs^3Z+8p4{kWxR+7$W=~GlgSzZrO&X90^WC2~Z|~!L{tL!! zY0fZme1-Ro?)TyTrV<>5f8y4KL;F!=4>JaTwBKjE2!&qYjubmWm=8o+(^_6%5DE>k z{vQhI?5_A{gl7Z0u#IIGMf6JMHG01KyYJ2O!Zr76_>btLT`jHXSfH4qW59dinP?>C zk}KzbdFdQqVc~TiSC8Hl&dC#;^*;*NkNn;XpS%5;`Z;=NWCrrZm67Wnn?KwT&YRBP z>c2ZIZjBl2uL+M18~N4NJsO_n_*!Zj9z|BU?}Src!u`B&+Yxw^dyYEu-%7vtb0YP9 zo!ynIIlQel6k5!^Nq=-SE9e}y{KCD$9jZ6DR#uOQoLj$3ulHyB9Nv3-zlEC3)!2CE z1Ui-riLaP>fMS1{Ie;Gr{{GzmIOD@hVQ-BCb-2?e@1D#E*l9%XKYk^>k(}XE!&Ww# zah{i7vYn|583A;)r&Pa1$N}NmzIwkeOBPoGdCUYNbHQuz(HNjO{_P0h`@6;fAERdc zy7uT#04GU~CHEL=M$ zZ8mYj+MdP(^?Tp{_q*T0j&ZdR8J%>^pzDOA;m`}1EwE#Yxq@$->$rOw3eB{6!RuG% z1tE7$=m*Sjbl#1`q*;Q$7VyVVJ+gwU1kZFmFdzG0===UC4S}s?j0uJQl{tXQtMk9` zkUPjo5Q%peR|%m|S4ITcG#04;ePKCl_V3L4zqpdG=*(Z?HTT!q|5FREIln*i%X$O5 z(L$lWKkL7WMl*ZaHMbYmqtAY1F?3<92!$rrnD2)|I?MlttG+MoxaoYaIsYoF4b2bU z4aZcM`^gK#NAo*)sP`-WpL3ldOrW>bp}zF{+l(ke%?WO`v?DVDT^WpGB+y*U*Y{#( z1QXC|KA=$1xqv^iO&ASAA&msG&SpIDef~q%vm!OGSpfUU7$4;GIJ1A9`LDCI|M{7J z@|D?#=JuhG`o7v~GQTxX4~4YO;m=n;fa%=+t#JIB``>)!sOt(LIs@=49J=23x!09` zD5UwmFRefS`&FRdarV^;rLQ%u{^;!Q&-{PC3KUuE>TWIa@B6;*`H?F>-}|-R(Gbx! zzv?8q;`Qem>seA;}k9H!k04n6xL5$#*J2C0KIM6O4)M?&_i5bbGbZe0HIsp;PgUejOU zblxO^h{(Qnyn<|k4fg^BFZh{Uh- zBW2}hIQ~dk#rX?RZS1OGJ4G-M6Xdf1!I&6+#Kgn~V^PP(C#9rk7qVwCcj(v=CHzy; zy`D9WcbjhOA5w~D|u{eL5cQ>=Rc7bLri^d(RAZiXlBWI(Ga8yfQr)M%g6i@AV>O(TD8tBWz>hkSH$sq@df< z{de1Dbn|f(cGrD^$e-6m7+5Q=c6>tJdP!F|Zjy3qdLbG$tC|A+@Bfvt;rF|D1l)7T ztH>?w1Fj6Ygxql_doqz{k&lr}$PKSJcmHDNzFg|uBO8zo0XG(TbvOG-_pm3F-$OeE z+;wlWCmeiaIs1IU*EPCO26$(+nk1V_n4sj0iwTW!IzLXZU5vymhPpo-tW-D zpu31HMb;q|$oyf4PmTStb6+4mCX+|x?kVgWM*gF}qTUToJ%`UxMByHq>fB$ZQT@-c zfAHn5r&@vkipVyU4N$K<&pumZ);(KK?E(L*>HSA}dG5=^hL?!*?ioJ4TV8PP(oE-W zc#-{A!HYk;2dq8@O&OZveV?PeMWzPoxF1ay3^?ah? ze8Y&-dgB)jJ5TlgTMP&M%=1Hr2d8;n`JBfC(>+Gw+dtEft9xe!>Gtdi2i4|p*KyIG_yV}d{u+V77&lh! z>r#**O?r51<6Xdm=(9k=kDyz+8?iHNg!x3UAv_;!1dibmgbs{lR!K=V?W}gEd zqF&CS=jVvSh6li3qu&Cq0g-TdPru{4S~ zi8$tk;*`bxk@!-;3t)dx;d&D8^hYsnLAfjKgD#VB;{04F{wWPie&rzPja_XxAJlQ4 z4z>ZugTKT+8dN(N4wARA13`uB3zGM-nc%x%$9U3xJ?K`x;z~QCYadU#aOGD#6;Zk^ zK!tA#z7Hl6?ks)>2-gr@JmJI@PCST|;CHaLD=SC89lw*b{R6dKiMag4_hNSog0A5l zS9%P-3%j`N;-6x_h`;QI;oGr`%PzhZdo2FR*pI+BV;7fQe4T`RtOk|urTCv9d>8ze zqg#Z(xctTEBP#E7P~i%}Rp10r{U_h_V+=4<{d4^Id5ZbVjz*kq!9q+*er#^nLNGM7I+^ zarudFLlp03Q1PzEza{p;_-{hD27ht+i?2Xb4@>Y7eSnfbgo{UUOaPM0B}?kJPvLNaQ2@27{Zx{@|~`Ou{uHKby#3Z*-jrC$9X7x5r*V zyfcZnE4(dsaoNRFv2TOV#hwOF!7eVlcwPk1Fj#NuxlI}fPEyq zKlaGDCf*af&JWoOsCRfK_Q?4{JRMQK+Tgc|c#4Q84P9&e#FdVC3+%h$OR%?tH^VM2 zyLb~s^%xJTyq7swyayfuZ>K+1a$b3k`N$ii89&kO<-8)U@ZuHbw*|k+=vUyk9oi%$a&!bgLb!1{H4JKMF!l{Q9~P&eAn#A6YKJ8$tFGOVcY_3J?8 zXO;1}hB>BBGhW|tJrjSGXJtK~ZpYQGbTzuS>qXNQUw|mynTD-F<)f+L878peJ3+;_ z#c+n{+Z)D$nvYzh9P-;wc{N{Y&A5IT-EPVonZJndL^RJ_2P*zd7EOe)Ji948l;qp} z#+NvsbG2WY6m9q7yAU0hLc@{xHzMp}h7aEG@3Qe1=Wn6-VDrl~YzWe=#wHl&<2K>& z%m+))k(XmvMZ=39MwDKK;R^71_%e{ozOl0j-#3r>Pqr(ahi)d}#nmpw$79#HlD~>^ z7oLwjGR}xkP+qBzA%>YC)i*Y+fh#MbpAMYCJP=*W2ChV0@roZq)Xolq9SOe|R6f^% zT!xNa4K4v!fNGz`#HVz#R=Uz9(h*-IAL5BDY`uzKwfUVab)}clpQ+&|-X1^2*P@}1 zZxep0=$bZ+#wR|Xg)kk@BEuPmg@!4HjX<@VIOCN~cz&ArH-ZYk68t&52>d-b-t>b^ z&&?#a1AXOnK3qAdaFf74pw9u-K8Kq=8C3lHlf%z*k6jC@9#e z$_BF@bU4nH=A#>att$~%I~E^|y^win($8q;@PXLHl^^lm$Vyqfd#4LoyShj}-;16Ol?hO4~dd$I4QO`PFlN{8XQ zu#3wsJ{eKHjW_HED&9^OZ*hVv?Sig-jd;b|S-gwlU1>*nn;P+o2NA`4jy5c;1b;)k zt3jPN-Uhj*8#@R57%T*J{3n3&9}VifIgI|XkM=TdFz0`CgXtgQI$q-QDXaW54O_7|{kZpQT! z`D**1E3H6R-i+%f%cuAXM8|n9;Z*)vU^zGiRQs6(ZUl3|55f5<{=D)GsC0XRMd&+% zY7dRTUEpQ>w}ackKY`1d+j$GrdFfmWAO8u%{f65?oj=;$)`e`MEg>vdCfd=j5ye!IXH#J3g1H2(T`KP*Al?PH`23!Ss~pEb)njrS)>6SnU>)>tgGzs{;S9qmhNIj1c!nF! zHk=MB+zR8%3>O>bxAXS%w|P7bs{RguDWtpeHs+JJGY)Y++>37eZOkX({4EsUged+A z=AUc+y@Rf_09{TEfAMtlZw;!Pm3R2?>kJoz($6+N#xUD(fMIXLG{Z)QC)0d<8Y&@$Lhv zz3nDlrMJ|uz_1#-^ryeYItpcvy}JD{@q-Oc#!rlKAJ56o8bMJ@8x#oy16U; z!|dW~@A2{E-s9uR8p`<`-ROIw@rXC+&ih_SuRi!0`I(dM`D9RhxbcC;kC3+NW5B&W zzr75Hfhtey-d>+#nB3Rv>w`LeNe_9RV93j!!{Lq?Ztd&Kb>;!C-_ULD8!eak0_>`X zhJBbn!slU+)Qfl_qI^s+%zN0U+xuZ3Z{BxYXI0O1zVTecA%^`7vkW^Mwli#D7-zWpdp_Q!hVu+(7#13iG;D2{ zXc%j_b+F~naFAgq!vw?2k9xn;hLwgDhU*RI8|FXi>yh?fIv!o_qtSX4&o;kw!+68$ zLB4)h6E2AE^q^?{idPQu`PgQ-+Hjs>q2VCI&W3G4jVtHvc<(pdX}HO7x#1Kr#POQ+ zT~~IBdDf_FT4sel8yfO;f^dE> zTlh-DGH+Q(tzmBx31TAx`1YMo*!sQR35I0sbtsfJ@f z#WT|EgH7Mdc!Jq4=lJ?M#^$>qIzA(Ir5%Xpl265(11i0)pyEv%?Zd5RU7#bnHlw5A z#AiO?!{vbrHxk@Nz6XN}-}eb0e(pe5+8^QD86WnkAINiL93@A^>mD~@2yc! z;=8OqHiOD<`ycrHw*}SCS{iQ#D*ug)CmN3fRqoSPf1iSiXLFt}SBrp2{d~hB!z{xg<9$4XK;^TaVV3DL zjCU}eYM3q;A;OB^3vpB87EYPcNdp7MC`DPQh5=FNxE9e65QZt=C|x6*L7 z;b>6#8Um{S^|N^95YGT~eQLxbo>}12O9EBju?0TeL#*q>qvKKEE8~OsIje_CP~%dC z@ok{OuQR^L%9Hj(AOA4JL!kQG0Z{o|V>laB_^Chi>1X$Lr8CeK{xF)p_^^pS+{&l@ z_09srnV_zVwomZ=v=gZK_}*2xzpmptAq`#23DNk(lM%I_W5g>Q@FRa6*2%CjD1Eu% zYQvSF^1s}0I;ixX`H@d=bWi4I=qCOsnx6Q0^BV~&-qVJM3@Z(H8xEM{)9DDxza6Oh zOEuouFcDPxb3q-KX{H|yYTmOR+>O53zxwiBhAaOEL515n$>+P_eXQT0+de6pZ}G!~ z3m-2~{#nm>-UU>8Z9(NP#V{6>U;7{XbQhWaQ@H$A{@9g`d7Zs>H@MRE=$8H1m52u! z7sZ#D-!q1plYP09rugu~f8vk#di08Kfaxb0P5^aXzSsEHDXwfF@lQ!+y%OEVDXv6Z z>4_Jc-;!xQzR_SE!gmBKDc`!Eu}1(iwp(e-_feE^oecyIITXgJ|{AJ6XT9+w#3X1E1Z{AZ0Hd)}3$5?}iU>@z@j=y_Kn zuJVcRH@~(se0OSoGs-^*RQtwwk9MfUT+l@IZ9qy^!I;TKE( zit4d14BcS-#N{VG5K+3l3>VGzd^o6l?t0ndYQw3Z{P&t){Z~A{2vESwdUHYTN11ATq+vhe z(S7>?ly?BSUc?i*k1t-h$mef@;c!s*kA^Jr_q!WybEU)34P4~!cT?7d;+f{(&M+Qi z@7UNN;d*o5Cu6%SjYD^Fp(_zrIPpUZeR`jQN@v?bpUx7}sX(_Gf8AG?zxYOk-y@b7 zE;5{LI0MxEjw!^`opjzM-RbC_As+Dn@rX|_zdZczM!x~S@#se5CoVtn;pR6OzdO)> zg5NN71Mm}ilNLwoTl_GhaGUYd{IA7L%#+Y<#4mCk zCH}Vg6&p@9%(ZY6373yVY*>Q!0EzTxwA%y9b~t}Jgz(9L1L z&n|RZ-*6@3Mqh*z`d;nu0%YX4tyD+_(mHh8J>IH>pwMIZaC90+pw!)`F!uc#Bl0-SC&J0 z_I^lvK{t86D-l<^;zP`@jbRhR6R-K>%f7VI)34EdscoRhBO2kj)*q`D`lhDQC7b%zcX&VoY z816M(VK`)|k7tl!Kf|Em#b2@?f_|2?g~vV7RsWLx5Z3R+5C4+z~z&pwBbWr;U2b+E%sCigF!*s*WpsqjK8MXv3 z;is3a%753J{=V-PP~-j@Q2lTTsB$cL)3?)vORjVgx_NK_Z$-CpakPDjuQmUb zhRZ>fYZBq6ao*#V5v5bmO(2}O@+F>c{=2RHY&YCwxW;g<;ffMpKZ^~g8@4k{D)IF; zhxrI@y)8YE5zqc*1a(VI%WP zUGDvx88$L3GJAW&E~bxt+xu_(mB&qnQw<9YyBemwM>bhV4gIdMpQ3zU9XAjAt8mGJP|{#)kC`4_W%HSNZrF8P2qH z#(;`{hUupnPBa{C*m;8w-_|hIu&H5V!z57s{KR^X>p+!vhG7d(=_P_XURyu#_O*s@ z8!j`PWjMod;s?yXs{*d@Zq~ukjsJl8H=HyUisxgm;NgZo*q?!q!7eVlcrQfx>4IMo z`ri1Zqw9p9xctPKcZB^Kf*MB>@&AVN*p46_KQ^JOvnih85VAYA19Dc;rm z+L_-P{5qg(Q^QaE{QLfTayzK&k}Oc?hn8Rr{PJ4LLH}HKko8$~=hspW>#yRKYkhf_ zgP#*_jQkhzT)`2pi_qoBAFlcl@3_Vv?}ng`|A}Aw^eR9dk0pkK4EL}0`U=BEhI0(3 z8;%5ZKWfNoS9aI9p!+@hREMD(xZ0J7D}C{H=HJFJ#qj)lt}LGO!Np^&God^4o+}Yo zIPsJ3`F!lhPxYKwpMCM@cH&~U%uF2f4Lt%jQn*Bh=eTxqx* ztWAE3j88Y5V)%^V1W@@MZ8*g8JIAp2L!a+ihLa6P8V)fWVA#hn%do3qs$sn0d8>#0 zhFcBS8ut3g=c}3FfsH)x!1&R*1O0U)>)IQ6-oeHb@$J~xz{|0pg>S|#9-w`QZ^YjF zn}Eyg$htaluE#DeyZBn{1=RsJ;V#w{@L!ExTz2u5*sF_!F7*J24Fb}@ZB!}^8^X1{FtI%K%jaHHXRQ1QJD zD&1M8pKdtGaEM_)!%V{thOwXccrIG{XF$a_-FU9y=|B2%oB);XLF1bYSAjaeF9vlT zJKJ!YVIHXCG#dOAdmnHocyXu46NbA%`7Hp|uO}KGV%W~`&>y_tY{Myr`JnRG$9M*) z`=Cjtum04BJ7ajnaI0ZI!}^BtpvLQp9X{M*!!s5B`hA7rJW%DI466JSL6u{GVNWoL zc)C__z1}6@8jo?MS?D@daJ>%aZ=rYx^XH`};qdc*?{TJKnqjJ8(D3|r?{~;>8K~np zz<4jibkjF7e&lz)e%67??_w~#E&+zi1FAg3%|2_J_uEdpk^dS{{{4*S?eh9DhB<~q zcKP$i^e;I-p&PWzpFe_>TRg-3+88bcbsT4cDo3G(A4z!DI^4t>;l(HH_UR5b%ru<$ zC$CR8+={RAox0a!Gs8r~pyByF-hR^Xkl`-Fu6uoXmK}Aa8HDM)H(DO?VP>C-eI$HH z4ZHY(eLntA4Yz|T?`Fd_hSSYH+;AYM`sihtVVGj}`i60amq|yYW!8@Bk& z$J_R>$HRZ|c+haO;YPz$LuYvSke`RGXWi`NA;yqH(RrBoGl=RV-*615{yh-XIC19B z-hK#_elsZjV$e2u+qo7z;Nm3p3gMw^|`O70UxohjV|l+Xg!Ii zm|qi6z*s#ChEIWRa4SN}OG3;l@b&O%5;h-Zvz5#~)K&9K!cpJmk zrf&>t-cI{;-%wv8LA9p=V1Rn>W0(pmzsY~~^|fukD@{Sy=&#ZG5|20kt%to|v(MN^ zN!~Uej{1qeZTa11`B)4p{y9f{xW4;b>3noWN21}xTOalLN-=C?m}nSlco|>i|A^rd z)6X}YZaC2}*Knj^Z^Qk^tUe7B&-iwF_A9SH2I~BJ2-N(jGuR1i`;{-px=*=Ji!Sx6 zXgS22nt#G+A1-*x$9M9ijbEVhzry%r<9UW-Oh3S|qv_ikuK&{KbD3c=sQ3nh8aEO^ zU8k)-;qQOV1jPq}-y;7#Px$;7|B35EbQve2`4?}BD86J+<*yH_o$WgA^*Nx9=OE*0 zhAj-+Q;)K@1QpLz!vd?{A%>HxynOXVV zaQUFp840SKZ9p9_Ug8+mSO3l9LBlPE%MGU)?j>FImlajMemZf#XcfBURnhtpl( ziPhe3KkL~^=whp*e&QREaQO`n81jAcus-=4kM#}X4bPcNBO`ew!(8`d{WF#CB+=b*(q&FoXm zKEZfCsQe5wzWbt2zrwJSVG~g8db9a0GR(Z>^VtDZJn^9RkzBm!kIRY8tnZ_%z8F0& z;%6-0Rs2>xEHzvVs@&5-#W(4ak7qRTOh#95DH@OX07T(qFMF&ueil?bM~rVb9AJK3 zK;<*-vX6hw$E?4gYkN5wzj$jz?Rh1rblwIP?*ilVjE^xM8}fdajaL}f*2t;4S^_bK`EbLl2@tML<;pZH4in{WB)y^(cubaQLuM|`^ZyexJtr z`fbE}3wER19viJ+@%4mL{j9a{D~!)FoNky4DnEUVPl@yCjt3P!-*AlSvyJxw6)w|w zSHn)A%A0DuB`Ck-IG^7N=F?5lHH?eqSNw?iZ#UcsDxTHGmw<|Ap2gFLcov|WQzIVn zS?1rUw$J}%<3(`AH`(+P4aXbi8V)iX04lv+wSB%9tkZi~0xqj|G~ePG=HC_6`LsPa zo$;tGsOPR*gW>0{>-hZ4Gb}QkVK~`v0;uczF?9lEId2EtnZ@icKsUTjphR5#Lp;TdSN5q4#lYS7S+l;M_50rJfigf|*mpgQ4;sYh(dj3lM7~dt<@!oG(0qQyO zHH0g!%XKEt^{q#@l5pY*C%zn6gx?bLF9e^5j|cT!d?v`SF}4M$_!B@Khx62n_&HGg z1gQG1wEB*xz7L_>U!%Uox0$^u_6qox8g}t=MDeaNTy8i%!Kc#)lsya7{fJJ+I~Y$* z2$bExdiT-c%v;f=Bm_#t3A0eVsre_He-i%JV84WaBXo)Qi_2epKgY3>aq(gq>)q7z zZjPh4#!2y=h|0YMKaHO$YgxZUw+X+xO9D3WVjR5^~y%lmtSk*-;8cO=|{qe z@2?jqo01oF#luLy9_iH!l!z;T;&T#t_Z#u_1JR9eNxq&AT;=msag~q1G4Czdg>LIr z(fGyNnJ1Lr;_;~ZnGaTH&r{5mb z`#9o3?X%x*_Vk9{-o>y3sQ%Fm)OB8c)9A_qlS>4Qm(;C%zO>xW$I^4F_KB^(lspK*f6myW-t%@g@>) zCA!@;;uYU%@odIV_l*v|$a*)rjrc|GBZ;puzcrT5GH@~VG2QrN!(7AEMm}Fn49}SU z1XxVC3gh$4KGQJE@R;EN!C)2{X9U9+5dF}k+bM$0SS%wA8gn&*_Wf3 z>(}1sGLxg_5N~aMDTbAXpMtMZPs;UR~oZ2K%mdEd|%valiDNO<;;yNFTH$@artl?RU|Fq#@!(E1Juk-!$z{7p!AzTU0*H+6>hfKcUt%phH*`O`j?I8-Q?pNVAvN_J@qu6VZ5_p zYeNSropmjIJstWn_xD>czi$z(C-K>4Z&b+pxZp)K?BY|*-V*yXcwr5@_(-#7U>^-1 zR>Lmd*X#qa_lNhcVHZy|dm;9=@RS;M@%m<;hrJ;@p@v=jd~;tPM+`R`u5RwjeTHyr z(Y@U~T5j=q<~Pf53aI)TW8u0y%l-j$!)t^S&oKK)>{;;6HSFSz%{~iz6L|d^cJWxV zFUB4ZcQx$dM^b#g%dwwG3AoCXXuidFntdns-SCPUcJWPSKZJb?yu5~8e2v*pV_yef zRl_bm-t6rrvu_2STf;7%gQ$HE1l0~(fU39p7H%%#8lj7;5l(#fjlNvluvgwlzHf|{ zOMEM$c-Ml8cM7O@^DJD)pRmsvT~3W~;$6)?8hZx3V-34_8lrexf{Hf|RJ=!;`TVRQ z+}URI@n+Hdh_6KCH{bjcr*PeiZgven@rh<{hy59Nehs^LW9*twe)=Zu0p1XMWPT}r z`39e_T{n2YhD&(f1l{%x`c`b+u5usHxA_z+bx3*^Esynnv>_KG?>qUgoy|zdqt%)EVo>W@GeNEMOfY?(VV{;hpYz_}xj1xLEu;Aq?}%s|PX)Oa z8`})LnRpr!E|Kev)4h0qCAvhyiL3nLafsT@F;L_Fkk+0L5)!_P@ivBuhG$xNzpbr& zzMAp=!R_cawTk9Te6jh@HJs4e`{%K4GYMUO>!`nY{2e~t;2nYRKCn~wupb!R#k9bc zePH6%Y2NQlTA(b3^3>_d{X=vo@Do@0#E+QYAyC(I2k<}7ezHdRA4Inoe{uPX?=t^w zhMNr68Ll#1Zn)TRJlKl(hZ&x@Jy4eXi=b=9y3@Ja1Mbl6ffDg>zTlg%m+y#iXBRS# z!OO9W>$*>T0(SMIyxG(fJP&)MUy0`+pK-hfgGx6Z{2YF;oyYZt^9>K*=KWV1_B3n@ zDtzK?KE1tjI1izVzb%@ccr141kNv)-N$|^UqxltoyRDCZ9;o;x8qYP})p(rYkz0Ly z6^t7vZsj`k)@Xd<%Mg`s4ygD>8t-MijfI~{|8IvbrAB!1b8US1VQqZ5^nT4ebVJ%i z%OySt`_6Y`-0c5xjC@qXABb3NQKi}OFcH+FFyNAWc5eJ{qiWbR{ifVaUe zuJGcG75}0bw{n6jZ3a(L{BYUD_us-fkaEtyB~Z4dfcEko-kXAM_AP-Dait?Z2)p7v zK|0y+0oWtyi1)*;c=Mljr9-7&Kw0_$-gEFC?^Q#$KQ&My zu6&8l!#~ z**>3ohbLf<^dIpcLS9E4Vm#7&CtFS;Ka4+>j7Q=shxkt9BITIOn4|G^f?*!xlj55& zi}zWf8*@iAe(~Xm;vZ}{)38~4^yI%9PIZo5V)3LC&vJB&YQ!VHSpLK_&v3e7XTxKl z&i@CDZ!v6orwED!|8^*47VDlckuBf7#0}z?&S4dL9IJAF@Eq{p7%9O zH$2qQ`_BO7Kf(AgP}dDzjGwp*KkVB<`K=bG{4I>i*F1>T~xQVwxbUl}XpY}_247$?R=#ue^?4J@3B8q?Y-TpXE2bJ#@ zcl&wQ7J(x?|m<^(H&qsBJ_df$FUvog^r=RK5GJJg(WV_N% z=u$JH^(~%zug}*+=70IbIr83UzQl(is_%h@Ye4n$6<}M^SqiG&ib3r=J^{+V(r}x_ z-<0?(&~2^}zxaSm@88p~E2#F>J~L2Ol*M&A?W+^IHkpAEab2&Aw>JM~pyp)_@z;2> zi|gFR=<4Gi8PCKok`JxlEg!=AJ^UQ`h^*&{&qiJ+o|&NXKi)9g;+;mk!_f_{5wG}x z9)5j(rQvMD0>l12e7gO==Sl~n>)Rumu6S?rOESN?_%%Y8Si?_ztL38^`Pfdnn``7l zd?PZS{IA0A1pZ7TO4p%#8$WT?oA_evJE^Bs;#mqW#xAb&hj@OLugCHK%JmlYotqV{ zNAb~!>SusqSMy(ne+IhFHT=cX5aJ%u*!(`luL-(_HT=Zm5%q5e>Np&}&)SjUcEhFj z`T9K1`&w3_TYO)%KE>yn-y~4$E_ues7-k#x1=Y?vf(^hl(AlGiT`h zHFVCYvjS&6lq)jV%$&343Lk3tu)bzyVm|!d@B8}PoEx<7zJI`Yd3?V=*YkC~uc!OE z?{lAPDANU$mp0px_Br^o|7?B&@8g4g8vbT~qWvX4%>OWu?R8M_UBT_r9s|%GJK?s? z(jK%obLBg*S?29rmy{>|eRIL}@ldvTWZuZoGUbK%$xV?hgfxM2|hv3A} zB#`;k1DXC(aW4@p0NUYx50LFL5NNEc;(uwBwod|$_6BlZ*eUi9An$J!j@14x!QpAz zUIk?S%fy}qWI3|abo=5x99t&CZ9-b0eQ6&r(edjArwAUMuHCm6+l=QHqk$~f#UhOj zf*S;L1(o2rLLIJF@U>}rzqqeJyU!B5FjdOqH37@0)rD=t@-hi7wC$KN2 zecGqP6$(ZOmS=1CRKYO8{aM<*OmN?m+FmI*PtYs)*^jmV96`Tes^EwxwEu_+8oLSx z3(k97yC(|v7o7W;b{{2pa-6nz3oa0h5)2c3_fZ{gmEc6d9husFs9>~Us9^nA?H@fB z=NEWh|7jhWn^+TU;I(PqfqF&+94wBRJQFod$pN`iizo{GW$^BJ2Scf7<8f z>-y~#Tqjr|I7{$J!8E}X!8pNiLA&6J=XAQMf?+?^_S&CmyznzTkAMZX8t+TI0=IKN z!}AERq2(Id(J$z5<$}?RwB1QCZn3r_1&>#1J6o_o+(#|Z?n4CaE3|#&ml_ucrU`C; zS-U3+?)ZhaM=aMmtiBuPip!z@@_-JsFTSM1om-~ET^NY(H!XvX%L3tOFR9Yu3RdWF zGw;Oy24%`!5eP?nqLlNb;32`6f2I4^lfTma>+m?N2XGtrt3dyv-F2l-|HF7(SFglA zbY&oY+6NGy{iJb_+Hwft_ana9Z)opE7>=tq1YZ_hEVw|h?<)v}@e~PU_@#oE)@Xa@ zuXTCTf%IRtO5-FT*HM>Xr$6d-@7h+quAT>S-8&9syuCn<_gb-E6PzPBS^Ou6ow!xk ze`{yFe-Li2t%3T}9)J(m*>E7&@k3ki8;`J;0GZ#DK>DX|(dn!R$M}L<+Lk~%v^QVD3wTAYAzv_5i!7(3dyX-F- z_wCp5qrSuS>V8~j?GMDKy;=Md;r|BgjTV2}bMRrgCVpV6+p!Su8NhQzxgXfn_z!IB zY4iGl_RxLWzXZ=Kjo63lrhNf_+8f{3=`4F+muK8%JWl|(#qS5oL;HNauK#wym+NhH zjd);f)Zfuh;I^#Zww^ZgrJX6^QW1{lm8rOnN`qSp!kOonv=b%VrT29DXW!G|*CPCR zxPAFvAUy4(5^kN~JcMVylaAoL18#E=-Yf_0H1S^s{|wlv7Ju6H?;>C7D>#9O{?Pqh zTU{m|T=4u2&q2a1;$7Q%+N>Y#`akP%s|36LS%*(NjPVS&@IME_(>}ddhyQS|4mTI! z4#Dl+y@7DF2f)7!7uZ8lUKi|s@TbjuX%Boy>lH3|;cc8(&%}MTKdLR4-?pi*-o|+~ zY=);@fe-65S#ZZ5-LKOGKijSSmkVClrO#Pr0*!VMJhxNlyJV+6|K5Hd-g^zVik*S; zZ`up-VZ2Pi2*JX)wEJ+ulRI>J%Yh7EBA6}c73?bb>7R7C*8~^+$yRri{qH26_k!E= zf3mHo&3e%)35(j<2=Da!AXJ>1XBeQ1$zsI3gSV2qn?G5?ie7~ zlYRfx?iY{h_2B%Mm{*Qs{y!R64`}bjhwYRp*juo>;7&<*Cr_KIHI~e|auUR_$!(d=O9XHu^v8LijKJADrEV;Jz>HDe$LF zf7%)Nu>J!Dqa?o-7*BoR*42_9?d&gfdscjgb@~ge(_aMIlePyRwtwG~NEH~}sP7|g z!n)lX<%(?7_YvW{hITMM%>T(#I^E|##dX3d%yXv#>C$$b)BcA(#=hzt;++fl(?0#J zzD`fai5$~Q6-)uLJpIJ(E*LI&;kr)u!aKMQx{m9+>w$D>@4&}MPjL4&9lj5~A5?!0 z{?`KGX)nZw;pYLFZ-Lko1d{~&3+}$E!>_)o(@lL>ZCMAm6;}i4(k{n``*Xj9pCp(m zm;^NTd4gSmJkL9HMVDjg6`lUL_pmR5Tg8v)TRz1ePJj}uH693_}&w;SilCDpiYg4+PQ z-8fHXzos1_;SSn#x*G&51Q!Sn7aS-UCD=(YRPeC$m#uAedansC5`40ab{{9$RWMZW zinLGHc6de_?HVQ+3}pLWlXUhww7o;H92k%GnB}n7^~ZB48zy6%!>!n1Ur(F$rJak< zod}nSaJR$#J%k$%w{(P~&2Y2_;KTgF1TVL<*DY+1-%=04xjo8qv7LQAZHA}49sVj5 z`#9WJ+6ns&_|v98?RD_ye24d#<9CU1P6B^({-Zq+ALf@PI8?B|;5n3o?eV4HC6u4{ zq0V8xxB|BeC_inav4(a*2=YcfQ-Q{~4$Cs+@56c%Dro(N-^H_bt>?$fO5RP^yd>AgNgU%1{HQF+&1K#h_A&?*K)8TgG zd-Dz9_PPhr?oUj_a{zGrG~B+PHrtK%&h9$BmECoEX}`nsa&TMTJ&+#l3JK@$ro#{E zro(T<^U_|pC3Opgr+vAr_Wuh0*SbQ_t^t4An{UWMH|1j+R7Ju5C@nQR}kZ@@TR}Hsi zmT?_!{i>}v!&A5Jo zTc<98deJ^C`rH$(b?+ao!*9oPNG`bbjShsT-Cg|ooKh6*2#Y^$|82TF6K}KEC8NLm z6X&7XaLc^SzMeMw4{Z-V#yle7m-fUvkTH%9MB=+az|E1m93J%hTDWbD43vZRYxuC8 zRtlc&p~K@nhFdQ7u&a|j0^w;N!iV9<3q}ZDlm6R?=VpT8cFEFzX>aJQ(;d1-ZQ0Zt z^F{AKy0j+2#Q+p(`;l%V5wU9Qitu6Bf*{q{h)XisqIchO5GiRVKN8w9Y@8DK4Fi;NKLnU02V3^=nckB4|f|~^w3QhsCy|RJqZ)XQ+ zd)Zw&-rD{e%LM&`%kI?fwf!`v3l0~I26FtZir4;yg5%<}y-M_7CRl!luHR%lPxd_A z=G+meAMG~=>2|3BQm3_oO9V>wAf4a-#dwbh+`u(QZ8N z`F4WNZ<}CEf{y21g7qD4>k1*p?XsoaXivn4cJ0d43VDe_)S;zq#+B-RB!0^ju$Jq-K*_Yg5w3d3SPKh z`|lNu6^sx(IaK=}5zH8BuUn4uLi}#rmT_M4iM}scsW`7p9iv@tAJOb-$Ee!SAqCv3ZC=o{4OoP_aRWnv)({{ zw2w=@{V6)!yl3&fOyo5wB@mAGllU;7mnB>V!mWhcQcF16m+`rdaC;?OAB3xi+ipuZ z+9kvEyfFpX8|5B8Oy|E2&y%IXZRoH-{Yhv#SBhTHbkKt8nBO1LqC{UrQ$gm=NMk0m_qjuLKRrf$DjAm7^^DtLY@ z@`t^Hh;r8e+0NsDoHu%ldl-T5rU`F^>y`5>^r|o$38GU za9vIN=)=06`yaN~RbxEvOT+up;a2~!eLZdFLwhei{5|uX2zRx}t_Hn{m>opX}^b!&NnmXx$E*M%(KiN4Mj+dF0g&m>0`5mTg+QJ|Pa3Dk?ejP{m<+ck#|6eM?Fsl8{)L4tNA}!-tu6mWdAD> zJ6CYY1fAYOAp6@qvC9Mt1Y-pqz#~X!CGuhaI|`e>AF~h0`F%T(^FY`WdOp1Zo8|2a zn^*y4KIOnV_G93iz+B)PzzIM;myrqNa{y^Th93(22>t_rOlRgqjZuPK1uu$!=95~7 zXduI1`LV`Lf&+luk3<5mBHe2e{~VC+2Y_@hkoa>1mjaK%eHHKoa5JzM!tVuMhCL}u zkH>|%_}!K)jK{3Nc%(fJACBKq5^goZje*+;OE}tb_^{kcFv_Rv^JTVn-ypb3FkP^} zU`IhExL4At5nL^}6Y0jH{M&r!kCQP^2jhFoaNFcVe}v8cNIM-LmZyG_F2{bscXPCR zxnPoDte`{iBEmDiYqH&V4r$?3^n0Y=Z?fHZ4hep1XphU&{*wySmI-}odgfUo#`wW zteL8>|JnloiF}q%(bx%i4ED)fFo!E;7D+Ct`&J~;`SSGj`7=m;+3hofB72Iap$c*`I6WlDgQLsjE zo!~0L6@tqJmkKTxtPo5U94_b;93q$`=n?EM7$?|AFjg>1u)AO-iN9BHx8M#z+^%P53_c*ZU+^TRF1ll`Ht>+(e!;zhI|R20 zZWLT6xJnRX!ANJZ;6lNKH(*#omhYNZIhX^JK;|(Ji#4Z=RyHOZC&xUu~IZ%_DWQ`Mtv5RrLug?JAt{5PW@9^k@Cyq_P~xCHNp2FAXm^WD50 z?+k`rUZd05`a8PgJ~1ZtFyIbgTVUT!N`(RsY|-J)zNImBmoE3fy*k~9!`gk{Kk>d( zwD^~wDb*2}bX?~@1TWTPJ!ds)y8-W4W<8?tUSYOFwShSI#JhUwuG-_74q)vqcs2z% zK3v=NJvFYzggpo8&+4u1xwmUfx&vVmKJ{*G$2rmVu$SJ0?*IZDAHcIAz)KHm|KK!j z?|vB1KEk~sgW+&4G{L4i038$YObhbK&SCfUiDfY3x@{w5wFXvIRQ7 z6g=mD3*6s*QRAv5I^35)>X!0zn`#Gq9!UG7*gLTBC80d^ztZ7Xy^80vU}xh&9+toR zR-JzK>)Jl|PiPDGPRDgRxzXtCu>0JF>oZ{EAY7jTpC5{QUnu`1OxV;l1Lt`Wzyr9> zV|&-&I)fOCeJ$&wF!8e=UBSMI=`4wWt~LjHw^A<&j{;vId?`ZxMbL{0-p|=mLKdo({fScscl=g)c?%_6d&)QtGe5z2Jw0=YoGCyaC1jOt=G^ zm=nSWf;S3J0{^#gFZg-kY2e=p&jr6?h7ZO3bgOQYV(_-Y%fZ_VuLbWUobRfw z87X`sc#QCf&iEZ^;VZ!7g`Wc-AUrA@zZ)n#2|P*o(Vj}(C%oY{y!TpoY_w7j3ZDp` zCOkJrsYisb10N@RZ>&;J2(Rg-RJQQV;CaGp!KVn{4_+iZsyE)dEPNpNY~jnn=LxR? ze@^%|@CxCz;4cafyB)uSBRmQGm%_`yR|#JXzD9U8_-n!&!G9m-;C6y70Ik z;r-;oXWgOHF5!#8_X^(u{=V=7;2#QK9*5sEFx|nA2yckT``d+2?1y)qo4mhL{}R3s z{H$>NUc35Q_x!iPMf)X#*^0$(hA?pUR&gfDyyzh5Z49{d&IC&8Gtffd9ed zk1M=iQR`Lzq*8Ul8^L!9KL`Gf@JrzJ!uw}opCUX7{Gjkm@V^Vs20tpi0Q{KnS>Rs^ zpPQ}J8Q~kj&k5fT{;lvnKK%Zh@M7@m!W+PYyXo=|nS|>-;RWCwg&zg)BK#6~cj4JN zO5G+Lr#z~+a0mDu!egJpUPkyizfw-&aZ~Vna>8eU-z&U&s#0Fzwb&OuAbfZUe)muK z4)BMC$CWCTDSXyUr5+c)8~jP(=}#+_V}=3u3qJ=wP53tKxk`jLfIlr<{Y0s`!mofo zD?EFyQqK#o0k0IkAAG6s)Mu3Xg&78XrSNm$uL{qer_?&(1@rOKqQV=%HwhoU0KdN} zJQciFcoO!1Zwb!@e_MD3_;X}Z? z33n{T-c@)U_Orc&?_ZAh?+b4Pzf*YBFYvqE!k50RRD$r-b@+WF;b&` z@J_!|YNYU_jY^FXo(Voycz5iP#|tmttkjQ%hy4-1mn7V?O{u4ZXYRtbO8EHQN=+BO z7<{Jib>Ke{zHyII<-)VyQR=6{hwoKtk?^oTEA?~XUhw6@7ruw{E#cii!0$H;k2 zZ-mbRuMxiDh*G~7UJJfe_|i|5dQ*7Pr}!;c;S<642ygrcepkkHKdRIR!sGs_)B)l3 zrhF{~CHxBbSHjO-QtBJwyYZVDmxMQ5!S62!kGO{4 z6zQS+SfA_oeM8}^z{7;|9siw$HwNK(cHw(*(9=_R|2EhU3*Qg^BjJnN;(JTN&w<}9 zJgOa@a~HlN#HI!dpBswj`Gs!=A12&^Yn@c#z~JjZ|;ik{Rpq< zW>Y@leE;fX;d~eDRN)c0Rw@>L00&<)gxB`PHI(r2xK5fcyaIfo@D<=M2#<4N|1Z22 z{3YR6z*h(#=*Ig-gr|b96%O^WcPBW&tH;R=VRX~O%1KO(#le4KCxu8W@#J{~+< zcr|#Q@J^-pzKHM&@FL+WX5#%z!dK0)soBEA=HmST!UsNMQ_l&H!Zmb-@TK4{3O@k8 zOn5o2r++DYGx#duHP6}98sYsH;=L=vqkd{rzZ1Urd7Os`KlC%3dR=&Wg-vZ2?tQ_g zb_w4NzE^l3T))3By#Hc+2VD4O@Q;P>2R|ab6Rz|BDZCu~xEUV&U&7OI?SEGI1zhKU zEj(@ozJD)#Bl!1bc$@*Kp1P0Kg0~SqekI;BCwxEnEy6vo;4DM2=5O5 zsPI|f6NL9aVpCbd7lY>tUk9EqywfN6zLM}b@KWLF;Io9+fIlPrDEI>5-Tz@zKNDUK zzF2st&upqn_-^o*g%AH6@ADR3b^_;9!nc9{KjCM=HwaJvmreb_3=h6d_!aOv;r!m! zPT~BH)jPt|zr{I^@P*)i5q=2#pc(!mzP~4&zkAK=e4fMbH?ofj=kMEoDV)D$dqy~a zm-d|Sv?iPSR(Su*c;B-b9{jp+|Mxgkiqh%t1`iQF1^=V) z9rxN*t?3T_mhep6jCosl1NeKw4|#E~-VBq1=MRKefFBlK3;qw`Lx$n|8p7v-e<8eV z1isHAy#7JE`XAv}z%K}|8EIEd!k6M^(KX>maNZbno9<(0AH$iWaL0JN>L5H5JX|=R zA?YT3;{<&FM))Q0Ucw`AcG*{WEcl(mH-irpzG9+XB?$N9*@kP zr0^Q>F~YZjj}?9de7x|*S$6ef;a)sjFiAL{FL+8gpD`#9egJ&B@UyviPE0tTQTU1Q zS>WZuW1q6Cp9<%_{YAo4!GA8i41BrpYTVENm2lpBUoAWd{5Qgj!E1z;p%Xs!t_~Dg!u3UJ;D|Y1*&i6J<7S4AmOcl=OqKk#| z*~1yaFM!Vx9{g*&nlC&Ge4+3-@E3#+2VWw5Jorn(3&2;9x4}6X_^*X;2471ag7fdy zcJ*7~<=`8I?*QK-d@uML!ViG|NjQIJZMSf~`{2*Q`TmQ2!ui|ke-+N(Q9mTy0se__ zKA-uS@Cxt~!dHMd3aTs|A&%P!$;M|iUbao4$i$=gROGfx?8@`)v za^!nm_z~2F_l~K{a?}OiH8FSv(i|!L5ZdYq;YTmy{)_O&p4j&aA0CWrbKz;=uL*BJ zeRl{?#hC{0-!rdH5aJ)gYa;NT72&nF;(OxgC=9bX7btw;?YM3gz8Bmj+}jD)p2Gd$ zioHK;icd@CT3SZt1_iKgc;@qrS_zLjN!nff(WQXt_Kf<0_cyV9shlMww zJm-b`(YJ#zKe7C0ac0s(c=ztOjuu`9{-E&K9yntWeh%(4gkM5B&kNs-bXEy>Ap92L zN#O4Y_fE%|s_+Kze+l1=GwN%?C;kMtciQT*%`H)?pYTTTp~5@m;e1g;XmMV6ac8`HU-$~Nc}P25&K>J9 zPKD=U{JMo#;2d>~@ana=k0bm5&Qxaz_xv9BT!at*1Ma5?Ke7d9*TN%maBmkJL(=#= zZsCxy**(g_-4>o{;YAj{z`}oN;ae^IZ43X@!p~WFDAqKyY<(?!h=pfb_!JADZ{aH} ze6xkWXW{+NY7W#La-_+krRY2lkJ{9OzGr-grQ;cdDE$`)neE(?Fi!t*S= z+`^Yw_-`zHgN1Ll@Hz|MW#RiR{38qhyM-UK@Y5E4-oh_ixIH3J$50Cox9~^{zr(@@ zTKHfKPqy$;7XGk>PqOeS7G7@QUtll&B|iVcrxBl1_;9a%2A{L|{2QOI@cAEn&f)Vl zKIifI1|L3O{4G8g@!?-qO7hsTS;@u41+(45#Tw@K6&B_dq|7eMD|L;{%PA_vuYT)* z;x(ec_f#vV2lL9@!;{O(O7bVoK)jaW4bSwV()_agqQV=znq&R2&jYh=@Eh(c^WEr} zH#0v6U&1kJC51)iBMT=N-Qbv(SNK$!|0d2e^9pY6dXrN8V5Kr|XrYm%$vI{DGh3Bz zWa-#~{M`J)r&?y2R+KZfrAxYRMro_K=>@*oEdyobO)Hw2H+*dR&74P!znN=VeqpPe zbRuJC7v{7KFI~Z9bd1(s|BL!#*)?w7Q1JQz^{qaw+Z}#4RFQ5s5g*R2s|}|c>kP*q zEa6RB0+QwZP{GTJid#0$qs6(tGE=$-N=k}K&?Scz<(f_-#=}ncmH4LRmF1O~LubVJ zjJ(pkGD&L0c$V&aYY3)rkN!jS(tCu^r0E0`8k$K7TH6)`}u9oUF``p~Ec!pUQOF%e| zfxs=&w$xgOgqkf{w%K)LVe3T4mibD|Y{vSg6&K_UE6EFVGwo!lqjo?YWmc4ew01Uo zU$eVqnr(KoR9m}Q8dp28B7yn2+3kjiV*`T)QQX5@c2>iwRcD1;i~iYc2l^+RTC^hU z7M-m{(^(2oh6bG0vK1{(Bk~JO^~SbxezY{t92-`zM>EpQRyHD7)i4~O22*WaL&Gn9 zMvE3S-5B1|vgXv1JR>*1Xjsv-;-bR5LL^$4J0@=yx<^a*k%gsYzQUZm;rXS-MO;j7 z?mZ^&>1MCOnRz9clv>9SXOyOZxfbNjN|`ZvGFw5ClmMt&;2e?f zE6AT?$|de-7IQmcP3OkeVkweybIn#r%P%ddW#Tr&7}U)!=8g>x`PfPo75YkMo8xuZh}6u?^oP)z zzNhj~-{cu(ehh{D9G~8Ew)8KC%(=3UY2h=hsCf3+yb@iQTuDx4wG3lSv>AERXXKS) zjJ5DX4O7ug@=8YJ=N06R^A*g1Zo@{5$t!!hsAQ^<`fLa=4RXvvMrCE#`Jp!<#EfZ^ z@=5}=(Kec)ISqC{nO=0~A2!0`gmRk_GdYWoQQ8qjC2Su{p<9PwuOE?_ZcJL%_$UH8 zaoG%`lz~X8zEY$8l4ttz3w)C}H(FzH9JO>|)Rrz|bNqR^GYayUbH&r8j;8Yg*iof=RRx%nvLS7`$|h8v{6xU;^LrJejUn?gC&&i_rR>O<{74WnzcG2 z-+;1K54N!(m(@`>v(;s6ULH31EnO@rK0G$LtY}((4#tezrLwZnU|3+eP(XL1O$$(| zj6BTld00CbA~%0#ZoZpra{jE`$+`JLO9OO9VX4IfR(U_&Is`xM0iCgTipnEhwEmO=acHLWjbCsMh3yq9UwL zla0;sWYiA&KgHoUEw5;DE-#~|4jYkDRD>Q@IKo%JUKVi3Ea51I%^}osVqqVimY3qg zp0zoIY;~Pk18;P48cx!Ev2;!=Dtri60;mg;M|)!jVv3EyI3lks$B$L9Xhum+o?fYL z8Vn0yW{Iz`6dFA|d2%VQ8g3TOm~?LLWoE*zee)3L$L!s>fMtPi5{8ZQLpkWV2fL2K z(mXvs-XwvsW77gN;tk~=i!0(h?4fxHo$4#h<&4uD2vIRl=I3GqTsjQ9jr_@+`17#W zH5w7h9Ke)L1)G;~g4F*+ZR7w!fzM z&+xiQo`ySwEkkz3>Xk^PUz{s+vRq3r^8B-n-MHF;*B;z=dwdvI-z4sJM< z70p2JFy>*=q`0UcKWBE9(T!)67Ubn2-I+MA5h1fCPcDNWb2D6FX3fbjRs{nGI{BZA z|GD{}hyNw;zeN5wi2o(=zrpwqgAo5QhLbUzjNxPqCu3m1;6KK2GKP~eT#Vsj3>Ra# z7{kRFF2-;%hKn&=jNxJoH)FUN11lr`V+=QAxEaIE7;eUJGlrWnJdELC3=d;?7{kLD z9>(x6hKDgcjNxI71ja~Uj0DC=V2lLDNMMWv#zk{Bb2F$OcnV8$5C7=syOFk=j6jKPdCm@x)3#$d#74nzzmHFr{TCpC9cb0;-- zQgbIYcT#gFHFr{TCpC9cb0;--QgbIYcT#gFHFr{TCpC9cb0;--QgbIYcT#gFHFr{T zCpC9cb0;--QgbIYcT#gFHFr{TCpC9cb0;--QgbIYcT#gFHFr{TCpC9cb0;--QgbIY zcT#gFHFr{TCpC9cb0;--QgbIYcT#gFHFr{TCpC9cb0;--QgbIYcT#gFHFr{TCpC9c zb0;--QgbIYcT#gFHFr{TCpC9cb0;--QgbIYcT#gFHFr{TCpC9cb0;--QgbIYcT#gF zHFr{TCpC9cb0;--QgbIYcT#gFHFr{TCpC9ba~CytQF9kHcTsZ}HFr^S7d3ZLa~Cyt zQF9kHcTsZ}HFr^S7d3ZLa~CytQF9kHcTsZ}HFr^S7d3ZLa~CytQF9kHcTsZ}HFr^S z7d3ZLa~CytQF9kHcTsZ}HFr^S7d3ZLa~CytQF9kHcTsZ}HFr^S7d3ZLa~CytQF9kH zcTsZ}HFr^S7d3ZLa~CytQF9kHcTsZ}HFr^S7d3ZLa~CytQF9kHcTsZ}HFr^S7d3ZL za~CytQF9kHcTsZ}HFr^S7d3ZLa~CytQF9kHcTsZ}HFr^S7d3ZLa~CytQF9kHcTsZ} zHFr^S7d3ZLa~CytQF9kHcT;mWHFr~UH#K)tb2l}2Q*$>pcT;mWHFr~UH#K)tb2l}2 zQ*$>pcT;mWHFr~UH#K)tb2l}2Q*$>pcT;mWHFr~UH#K)tb2l}2Q*$>pcT;mWHFr~U zH#K)tb2l}2Q*$>pcT;mWHFr~UH#K)tb2l}2Q*$>pcT;mWHFr~UH#K)tb2l}2Q*$>p zcT;mWHFr~UH#K)tb2l}2Q*$>pcT;mWHFr~UH#K)tb2l}2Q*$>pcT;mWHFr~UH#K)t zb2l}2Q*$>pcT;mWHFr~UH#K)tb2l}2Q*$>pcT;mWHFr~UH#K)tb2l}2Q*$>pcT;mW zHFr~UH#PTAa}PE5P;(D8_fT^WHTO_+4>k8ta}PE5P;(D8_fT^WHTO_+4>k8ta}PE5 zP;(D8_fT^WHTO_+4>k8ta}PE5P;(D8_fT^WHTO_+4>k8ta}PE5P;(D8_fT^WHTO_+ z4>k8ta}PE5P;(D8_fT^WHTO_+4>k8ta}PE5P;(D8_fT^WHTO_+4>k8ta}PE5P;(D8 z_fT^WHTO_+4>k8ta}PE5P;(D8_fT^WHTO_+4>k8ta}PE5P;(D8_fT^WHTO_+4>k8t za}PE5P;(D8_fT^WHTO_+4>k8ta}PE5P;(D8_fT^WHTO_+4>k8ta}PE5P;(D8PoU-r z)I5QjCs6YQYMwyN6R3FtHBX@C3Di7+nkP{61Zti@%@e430yR&d<_Xk1ftn{!^8{+1 zK+O}Vc>*<0pymnGJb{`gQ1b+8oOJ}8XEK5xwQ z@bxbP+v52G+EIcY!8Ad9mBaAIR~8J!Bku;*3I0ux&o(d}yxPaWE`o7_$%5kqO9U4R z@)=>q|DE6-!M_TAA=o4sjOS_@zMJ5kf=Pm@f=>ue6`U{lqTp&lyr0uZuTJoN!A}Ig z5WFZDif3n;e^0^wf+>Q0c9;Ief6~YQgP-9}0dch@N4jk7^l+ zM>q|{V`>KCu^9vLwPpkH^#%iP7mO3Ug!BrMIB_L$;!5JgmBfiFi4#{6C$1z;TuGd` zk}z@o_raOg580&U{rABc9^&2PaS{Ct)qfwHDd4kCdCBHeVls&2i3H2D0ODfa-8P=) z`tO4?d{PfLgIYYxFw!`&H5%x@56%Q0{rm5OGdDbOH}<~|&fNIm3|4=94-WhEBxB#L z|ND>o^g)BMWoOvz(1QF)xXn{Kz;~CgWLl!8?3TYr-pn3W~zCEYx|#%sEs=^9jRP!KO4n*XFZ zo9*WGaK*{L*5&isbnJAA(W$NeZmF1fA8gCNtgIZ|9pNLr`mc3*OC`O(Nqw`Cp7l?P z-Ry+)cthS|x762<`tdK57l-&uaAM(u_o}8H+@ZUX9 zr-!eF8GlO?bb1YMOq+27_3W}?7t;NqJQ+XR?rp*wsSh%KHop2z zn|wZAA@W1M!xuh1jB9`A9n(Y5SFf6E$SiX)=!=N`rmvQr52Z z*Pnw%Xit{&)wars@2o@j@`DX%Gp5zp9(g=dp5b^Vq~|GHbw)^PMM*_(@E~tf=rbW> zD^>Nusl_jxAN5T8S4Llb>f`udkE%S?UNwy@{cT2w_g5wUH6cA4Z&6MDx044~;B}v7 zy|ekca#bGgMp;>RM;q1IkG5ri~*L@hyKa( zVZ=rp59(%UYK#?|O3>}1<7Z#Hp2>E(6=`C~M-UyeZwtr6CUwx*#rV6R=Y?*sMoKvz zVL8llGOZY!Dmm5V)d_fQNBFMuYWf+(o7$#wLYB>YzF+6c$QWR(ZBgW|chpChvi8)p z9+%d!cIx(B)672Mh^iigsd}jcucQjGdEd&G{_n->L}EYb^(6gla956A(Q0?^Xh(c@ zv>7HF^<@23tUr1Y+M?X9$Dz7@-NP}-x;6yG;H^aL3*{N7Zr@X2_66&_W2B*SR-5Ip zJ?g!x9KPt*^Aq~}2CQ#O<5AYw;GgFCin z#=P+z{NA)1uX`}!A8+T~YQ~F2JDTYpZ#Tc$J-dCteXY^gbw0ZXsDwzg6*^YLFVLP( z^A+*%KPLSv8}m|wa6hz4y-RJ&?ybiObxvwMX!p$+cZ*m3DXu{Z9nu7IF z*CEg!|F`%TF$bFdW_)wb|5ny{mW6$u?#Dz!^`N(@p zJGOz=oOStSklJ?L-t|mMkjnfVuO-6!o^fSRevtJw(`EYx+;m+Tw{`pCet;{`zGj=W zY}dcHRaK34?_hlQ(xc`A@&{$sND z(DR7ihxjr6YeEC_2s+2M>{fG0b6KU#+neV#uk=B0Q|mIG2=Z>FuB;=+(~W7G`$!Y@ zo|R+$+qO3!>xN$&YNY#^9;cdT8uPVIt1&2RtK(T!sjgODB- zSv4K++R0o4t<53hclm(%a6f6b^Xv9*mAlY~>j!v~zF|LkMoo{y`i}K`u$ea3 zcg!&n)SZ1v=O5#ewLjdbo5rfF(xy8Z9_ zOSPd4>xLPY+OV7^Vt;A0mAPKSFG7_Y>r68`I$_U**Y7wwaj&9WT+`!JGWSuBIL50w z$5L-y1@>4vT%-}sy6&6n^L6Z5sD}f4hQ@Z-M<#lkPTsDnzUabz^lh%=sArJOkB%k3 z�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

    n1vJMuGM~kIoXjExl$^E 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 PzG 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

    h`#jTBZQRdTM3sKKP!c16W2fH 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 ydCELbndd3bprQ_nijA<#w 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

      mToN2G;_Q9zfoOf#Lji2km|0>|0bK?8Z)3&9s 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

      +8|`Fe}5he^`<0O^nL5??QI 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 - - PreserveNewest - - - PreserveNewest - From 1351bfdd1fb2aeac020f6f032125db47bda0e3c0 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 9 Aug 2019 19:21:21 +0930 Subject: [PATCH 2282/5608] Add iOS FFmpeg references --- osu.iOS.props | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.iOS.props b/osu.iOS.props index 82c60d0aed..58c2a55b74 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -97,6 +97,11 @@ False True + + Static + False + True + From f68e41f7b9fef17f238cf322d655f9c7b8164074 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 9 Aug 2019 19:30:31 +0930 Subject: [PATCH 2283/5608] Remove BASS references from osu.Game.Tests.iOS --- osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj | 8 -------- 1 file changed, 8 deletions(-) diff --git a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj index ea5ab699f3..5c0713b895 100644 --- a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj +++ b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj @@ -13,14 +13,6 @@ - - libbass.a - PreserveNewest - - - libbass_fx.a - PreserveNewest - Linker.xml From 90b1fe81f3ffa99167bfa20af7b87ba3c60c8ca9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Aug 2019 19:12:29 +0900 Subject: [PATCH 2284/5608] Update cached usage in line with framework changes --- osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- osu.Game.Tournament/Screens/Ladder/LadderScreen.cs | 2 +- osu.Game/Graphics/Backgrounds/Triangles.cs | 4 ++-- osu.Game/Graphics/UserInterface/LineGraph.cs | 2 +- osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs | 2 +- osu.Game/Screens/Play/SquareGraph.cs | 2 +- osu.Game/Screens/Select/BeatmapCarousel.cs | 4 ++-- osu.Game/Storyboards/CommandTimeline.cs | 4 ++-- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index 8102718edf..a92e56d3c3 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs @@ -100,7 +100,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces } } - private Cached subtractionCache = new Cached(); + private readonly Cached subtractionCache = new Cached(); public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) { diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index a4638c31f2..d3279652c7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Objects public double EndTime => StartTime + this.SpanCount() * Path.Distance / Velocity; public double Duration => EndTime - StartTime; - private Cached endPositionCache; + private readonly Cached endPositionCache = new Cached(); public override Vector2 EndPosition => endPositionCache.IsValid ? endPositionCache.Value : endPositionCache.Value = Position + this.CurvePositionAt(1); diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 67531ce5d3..83a41a662f 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -88,7 +88,7 @@ namespace osu.Game.Tournament.Screens.Ladder }; } - private Cached layout = new Cached(); + private readonly Cached layout = new Cached(); protected override void Update() { diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 2b68e8530d..dffa0c4fd5 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -191,7 +191,7 @@ namespace osu.Game.Graphics.Backgrounds private readonly List parts = new List(); private Vector2 size; - private TriangleBatch vertexBatch; + private QuadBatch vertexBatch; public TrianglesDrawNode(Triangles source) : base(source) @@ -217,7 +217,7 @@ namespace osu.Game.Graphics.Backgrounds if (Source.AimCount > 0 && (vertexBatch == null || vertexBatch.Size != Source.AimCount)) { vertexBatch?.Dispose(); - vertexBatch = new TriangleBatch(Source.AimCount, 1); + vertexBatch = new QuadBatch(Source.AimCount, 1); } shader.Bind(); diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs index 714e953816..6d65b77cbf 100644 --- a/osu.Game/Graphics/UserInterface/LineGraph.cs +++ b/osu.Game/Graphics/UserInterface/LineGraph.cs @@ -93,7 +93,7 @@ namespace osu.Game.Graphics.UserInterface return base.Invalidate(invalidation, source, shallPropagate); } - private Cached pathCached = new Cached(); + private readonly Cached pathCached = new Cached(); protected override void Update() { diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 069e2d1a0b..19247d8a37 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.UI.Scrolling [Resolved] private IScrollingInfo scrollingInfo { get; set; } - private Cached initialStateCache = new Cached(); + private readonly Cached initialStateCache = new Cached(); public ScrollingHitObjectContainer() { diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 5b7a9574b6..9c56725c4e 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Play return base.Invalidate(invalidation, source, shallPropagate); } - private Cached layout = new Cached(); + private readonly Cached layout = new Cached(); private ScheduledDelegate scheduledCreate; protected override void Update() diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index cf88b697d9..7366fa8c17 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -93,8 +93,8 @@ namespace osu.Game.Screens.Select } private readonly List yPositions = new List(); - private Cached itemsCache = new Cached(); - private Cached scrollPositionCache = new Cached(); + private readonly Cached itemsCache = new Cached(); + private readonly Cached scrollPositionCache = new Cached(); private readonly Container scrollableContent; diff --git a/osu.Game/Storyboards/CommandTimeline.cs b/osu.Game/Storyboards/CommandTimeline.cs index aa1f137cf3..bcf642b4ea 100644 --- a/osu.Game/Storyboards/CommandTimeline.cs +++ b/osu.Game/Storyboards/CommandTimeline.cs @@ -15,10 +15,10 @@ namespace osu.Game.Storyboards public IEnumerable Commands => commands.OrderBy(c => c.StartTime); public bool HasCommands => commands.Count > 0; - private Cached startTimeBacking; + private readonly Cached startTimeBacking = new Cached(); public double StartTime => startTimeBacking.IsValid ? startTimeBacking : startTimeBacking.Value = HasCommands ? commands.Min(c => c.StartTime) : double.MinValue; - private Cached endTimeBacking; + private readonly Cached endTimeBacking = new Cached(); public double EndTime => endTimeBacking.IsValid ? endTimeBacking : endTimeBacking.Value = HasCommands ? commands.Max(c => c.EndTime) : double.MaxValue; public T StartValue => HasCommands ? commands.OrderBy(c => c.StartTime).First().StartValue : default; From cb0cd7ed589ef56f1b9a3cedae662a709397a022 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Aug 2019 20:05:28 +0900 Subject: [PATCH 2285/5608] Add triangles intro --- .../Visual/Menus/TestSceneIntroTriangles.cs | 15 + osu.Game/Configuration/IntroSequence.cs | 11 + osu.Game/Configuration/OsuConfigManager.cs | 5 +- .../Sections/Audio/MainMenuSettings.cs | 11 +- osu.Game/Screens/BackgroundScreen.cs | 16 +- .../Backgrounds/BackgroundScreenDefault.cs | 5 + osu.Game/Screens/Loader.cs | 19 +- osu.Game/Screens/Menu/IntroTriangles.cs | 413 ++++++++++++++++++ 8 files changed, 486 insertions(+), 9 deletions(-) create mode 100644 osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs create mode 100644 osu.Game/Configuration/IntroSequence.cs create mode 100644 osu.Game/Screens/Menu/IntroTriangles.cs diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs new file mode 100644 index 0000000000..df79584167 --- /dev/null +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.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 NUnit.Framework; +using osu.Framework.Screens; +using osu.Game.Screens.Menu; + +namespace osu.Game.Tests.Visual.Menus +{ + [TestFixture] + public class TestSceneIntroTriangles : IntroTestScene + { + protected override IScreen CreateScreen() => new IntroTriangles(); + } +} diff --git a/osu.Game/Configuration/IntroSequence.cs b/osu.Game/Configuration/IntroSequence.cs new file mode 100644 index 0000000000..1eb953be36 --- /dev/null +++ b/osu.Game/Configuration/IntroSequence.cs @@ -0,0 +1,11 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Configuration +{ + public enum IntroSequence + { + Circles, + Triangles + } +} diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 1da7c7ec1d..19f46c1d6a 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -105,6 +105,8 @@ namespace osu.Game.Configuration Set(OsuSetting.ScalingPositionY, 0.5f, 0f, 1f); Set(OsuSetting.UIScale, 1f, 0.8f, 1.6f, 0.01f); + + Set(OsuSetting.IntroSequence, IntroSequence.Triangles); } public OsuConfigManager(Storage storage) @@ -167,6 +169,7 @@ namespace osu.Game.Configuration ScalingPositionY, ScalingSizeX, ScalingSizeY, - UIScale + UIScale, + IntroSequence } } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs index 4e43caff23..5ccdc952ba 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs @@ -1,7 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Game.Configuration; namespace osu.Game.Overlays.Settings.Sections.Audio @@ -13,7 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - Children = new[] + Children = new Drawable[] { new SettingsCheckbox { @@ -25,6 +28,12 @@ namespace osu.Game.Overlays.Settings.Sections.Audio LabelText = "osu! music theme", Bindable = config.GetBindable(OsuSetting.MenuMusic) }, + new SettingsDropdown + { + LabelText = "Intro sequence", + Bindable = config.GetBindable(OsuSetting.IntroSequence), + Items = Enum.GetValues(typeof(IntroSequence)).Cast() + }, }; } } diff --git a/osu.Game/Screens/BackgroundScreen.cs b/osu.Game/Screens/BackgroundScreen.cs index bbe162cf7c..5dfaceccf5 100644 --- a/osu.Game/Screens/BackgroundScreen.cs +++ b/osu.Game/Screens/BackgroundScreen.cs @@ -11,8 +11,11 @@ namespace osu.Game.Screens { public abstract class BackgroundScreen : Screen, IEquatable { - protected BackgroundScreen() + private readonly bool animateOnEnter; + + protected BackgroundScreen(bool animateOnEnter = true) { + this.animateOnEnter = animateOnEnter; Anchor = Anchor.Centre; Origin = Anchor.Centre; } @@ -39,11 +42,14 @@ namespace osu.Game.Screens public override void OnEntering(IScreen last) { - this.FadeOut(); - this.MoveToX(x_movement_amount); + if (animateOnEnter) + { + this.FadeOut(); + this.MoveToX(x_movement_amount); - this.FadeIn(transition_length, Easing.InOutQuart); - this.MoveToX(0, transition_length, Easing.InOutQuart); + this.FadeIn(transition_length, Easing.InOutQuart); + this.MoveToX(0, transition_length, Easing.InOutQuart); + } base.OnEntering(last); } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 55338ea01a..2d7fe6a6a3 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -25,6 +25,11 @@ namespace osu.Game.Screens.Backgrounds private Bindable user; private Bindable skin; + public BackgroundScreenDefault(bool animateOnEnter = true) + : base(animateOnEnter) + { + } + [BackgroundDependencyLoader] private void load(IAPIProvider api, SkinManager skinManager) { diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index de00ba2e9f..850349272e 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -9,6 +9,8 @@ using osu.Framework.Graphics.Shaders; using osu.Game.Screens.Menu; using osuTK; using osu.Framework.Screens; +using osu.Game.Configuration; +using IntroSequence = osu.Game.Configuration.IntroSequence; namespace osu.Game.Screens { @@ -45,6 +47,8 @@ namespace osu.Game.Screens private OsuScreen loadableScreen; private ShaderPrecompiler precompiler; + private IntroSequence introSequence; + protected virtual OsuScreen CreateLoadableScreen() { if (showDisclaimer) @@ -53,7 +57,17 @@ namespace osu.Game.Screens return getIntroSequence(); } - private IntroScreen getIntroSequence() => new IntroCircles(); + private IntroScreen getIntroSequence() + { + switch (introSequence) + { + case IntroSequence.Circles: + return new IntroCircles(); + + default: + return new IntroTriangles(); + } + } protected virtual ShaderPrecompiler CreateShaderPrecompiler() => new ShaderPrecompiler(); @@ -79,9 +93,10 @@ namespace osu.Game.Screens } [BackgroundDependencyLoader] - private void load(OsuGameBase game) + private void load(OsuGameBase game, OsuConfigManager config) { showDisclaimer = game.IsDeployedBuild; + introSequence = config.Get(OsuSetting.IntroSequence); } ///

      public int MaxCatchUpFrames { get; set; } = 5; + /// + /// Whether to enable frame-stable playback. + /// + internal bool FrameStablePlayback = true; + [Cached] public GameplayClock GameplayClock { get; } @@ -113,6 +118,9 @@ namespace osu.Game.Rulesets.UI try { + if (!FrameStablePlayback) + manualClock.CurrentTime = newProposedTime; + if (firstConsumption) { // On the first update, frame-stability seeking would result in unexpected/unwanted behaviour. From 0f4bada21e05264e6376f2227aa17524e145c474 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Aug 2019 18:27:45 +0900 Subject: [PATCH 2389/5608] Fix right click absolute scrolling interfering with context menus --- osu.Game/Screens/Select/BeatmapCarousel.cs | 33 +++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 6fda81e47d..7df27de55f 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -115,7 +115,7 @@ namespace osu.Game.Screens.Select InternalChild = new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - Child = scroll = new OsuScrollContainer + Child = scroll = new CarouselScrollContainer { Masking = false, RelativeSizeAxes = Axes.Both, @@ -694,5 +694,36 @@ namespace osu.Game.Screens.Select base.PerformSelection(); } } + + private class CarouselScrollContainer : OsuScrollContainer + { + private bool rightMouseScrollBlocked; + + protected override bool OnMouseDown(MouseDownEvent e) + { + if (e.Button == MouseButton.Right) + { + // we need to block right click absolute scrolling when hovering a carousel item so context menus can display. + // this can be reconsidered when we have an alternative to right click scrolling. + if (GetContainingInputManager().HoveredDrawables.OfType().Any()) + { + rightMouseScrollBlocked = true; + return false; + } + + rightMouseScrollBlocked = false; + } + + return base.OnMouseDown(e); + } + + protected override bool OnDragStart(DragStartEvent e) + { + if (rightMouseScrollBlocked) + return false; + + return base.OnDragStart(e); + } + } } } From b57298406ff7f6a40b1dc661ac2769a363d49d3f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Aug 2019 19:25:33 +0900 Subject: [PATCH 2390/5608] Fix right click blocking not resetting correctly --- osu.Game/Screens/Select/BeatmapCarousel.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 7df27de55f..23c581c6f9 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -710,10 +710,9 @@ namespace osu.Game.Screens.Select rightMouseScrollBlocked = true; return false; } - - rightMouseScrollBlocked = false; } + rightMouseScrollBlocked = false; return base.OnMouseDown(e); } From 386d78881394f344ab87054b926bbe3eb6963a81 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Thu, 15 Aug 2019 18:32:45 +0200 Subject: [PATCH 2391/5608] Change if-else to ternary if --- osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index a46ecab6f0..6326c3a044 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -113,11 +113,7 @@ namespace osu.Game.Rulesets.Taiko.Replays else throw new InvalidOperationException("Unknown hit object type."); - TaikoHitObject nextHitObject; - if (i < Beatmap.HitObjects.Count - 1) - nextHitObject = Beatmap.HitObjects[i + 1]; - else - nextHitObject = null; + TaikoHitObject nextHitObject = i < Beatmap.HitObjects.Count - 1 ? Beatmap.HitObjects[i + 1] : null; bool canDelayKeyUp = nextHitObject != null && nextHitObject.StartTime > endTime + KEY_UP_DELAY; From aa3651f65eb98777c6254ae29e2512f2db098ba4 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Thu, 15 Aug 2019 19:45:10 +0200 Subject: [PATCH 2392/5608] Change the logic so the last button gets unpressed instead of staying pressed forever --- osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 6326c3a044..1d35393de0 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -115,7 +115,7 @@ namespace osu.Game.Rulesets.Taiko.Replays TaikoHitObject nextHitObject = i < Beatmap.HitObjects.Count - 1 ? Beatmap.HitObjects[i + 1] : null; - bool canDelayKeyUp = nextHitObject != null && nextHitObject.StartTime > endTime + KEY_UP_DELAY; + bool canDelayKeyUp = nextHitObject == null || nextHitObject.StartTime > endTime + KEY_UP_DELAY; if (canDelayKeyUp) Frames.Add(new TaikoReplayFrame(endTime + KEY_UP_DELAY)); From ff601eefe6afaf6683af631f71361e05d644278a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Aug 2019 13:21:28 +0900 Subject: [PATCH 2393/5608] Fix failing test --- osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs index d42b61ea55..0c5ead10cf 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs @@ -17,6 +17,8 @@ namespace osu.Game.Tests.Visual.Gameplay { private bool exitAction; + protected override double TimePerAction => 100; // required for the early exit test, since hold-to-confirm delay is 200ms + [BackgroundDependencyLoader] private void load() { From d732d276b1186ce2108c2a5c88a6c2ec45907284 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Aug 2019 13:21:41 +0900 Subject: [PATCH 2394/5608] Make activation delay customisable --- .../Graphics/Containers/HoldToConfirmContainer.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs index 18a4241a79..773265d19b 100644 --- a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs +++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs @@ -12,9 +12,11 @@ namespace osu.Game.Graphics.Containers { public Action Action; - private const int activate_delay = 200; + private const int default_activation_delay = 200; private const int fadeout_delay = 200; + private readonly double activationDelay; + private bool fired; private bool confirming; @@ -25,13 +27,22 @@ namespace osu.Game.Graphics.Containers public Bindable Progress = new BindableDouble(); + /// + /// Create a new instance. + /// + /// The time requried before an action is confirmed. + protected HoldToConfirmContainer(double activationDelay = default_activation_delay) + { + this.activationDelay = activationDelay; + } + protected void BeginConfirm() { if (confirming || (!AllowMultipleFires && fired)) return; confirming = true; - this.TransformBindableTo(Progress, 1, activate_delay * (1 - Progress.Value), Easing.Out).OnComplete(_ => Confirm()); + this.TransformBindableTo(Progress, 1, activationDelay * (1 - Progress.Value), Easing.Out).OnComplete(_ => Confirm()); } protected virtual void Confirm() From 3949d46383b6adece23f0e43445ee92b3ff31585 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Aug 2019 13:46:08 +0900 Subject: [PATCH 2395/5608] Add test fix to other test --- .../Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs index a017418e3a..f787754aa4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs @@ -13,6 +13,8 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneHoldToConfirmOverlay : OsuTestScene { + protected override double TimePerAction => 100; // required for the early exit test, since hold-to-confirm delay is 200ms + public override IReadOnlyList RequiredTypes => new[] { typeof(ExitConfirmOverlay), From b2e05252d78c32b0e2711354bd9aac50797a2c95 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Aug 2019 14:16:00 +0900 Subject: [PATCH 2396/5608] Update fastlane and dependencies --- Gemfile.lock | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 17c0db12e7..56e640599f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,7 +6,7 @@ GEM public_suffix (>= 2.0.2, < 4.0) atomos (0.1.3) babosa (1.0.2) - claide (1.0.2) + claide (1.0.3) colored (1.2) colored2 (3.1.2) commander-fastlane (4.4.6) @@ -14,11 +14,11 @@ GEM declarative (0.0.10) declarative-option (0.1.0) digest-crc (0.4.1) - domain_name (0.5.20180417) + domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) - dotenv (2.7.1) + dotenv (2.7.5) emoji_regex (1.0.1) - excon (0.62.0) + excon (0.66.0) faraday (0.15.4) multipart-post (>= 1.2, < 3) faraday-cookie_jar (0.0.6) @@ -27,7 +27,7 @@ GEM faraday_middleware (0.13.1) faraday (>= 0.7.4, < 1.0) fastimage (2.1.5) - fastlane (2.117.0) + fastlane (2.129.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.3, < 3.0.0) babosa (>= 1.0.2, < 2.0.0) @@ -46,8 +46,8 @@ GEM google-cloud-storage (>= 1.15.0, < 2.0.0) highline (>= 1.7.2, < 2.0.0) json (< 3.0.0) - mini_magick (~> 4.5.1) - multi_json + jwt (~> 2.1.0) + mini_magick (>= 4.9.4, < 5.0.0) multi_xml (~> 0.5) multipart-post (~> 2.0.0) plist (>= 3.1.0, < 4.0.0) @@ -56,12 +56,12 @@ GEM security (= 0.1.3) simctl (~> 1.6.3) slack-notifier (>= 2.0.0, < 3.0.0) - terminal-notifier (>= 1.6.2, < 2.0.0) + terminal-notifier (>= 2.0.0, < 3.0.0) terminal-table (>= 1.4.5, < 2.0.0) tty-screen (>= 0.6.3, < 1.0.0) tty-spinner (>= 0.8.0, < 1.0.0) word_wrap (~> 1.0.0) - xcodeproj (>= 1.6.0, < 2.0.0) + xcodeproj (>= 1.8.1, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) fastlane-plugin-clean_testflight_testers (0.2.0) @@ -79,7 +79,7 @@ GEM signet (~> 0.9) google-cloud-core (1.3.0) google-cloud-env (~> 1.0) - google-cloud-env (1.0.5) + google-cloud-env (1.2.0) faraday (~> 0.11) google-cloud-storage (1.16.0) digest-crc (~> 0.4) @@ -102,8 +102,8 @@ GEM memoist (0.16.0) mime-types (3.2.2) mime-types-data (~> 3.2015) - mime-types-data (3.2018.0812) - mini_magick (4.5.1) + mime-types-data (3.2019.0331) + mini_magick (4.9.5) mini_portile2 (2.4.0) multi_json (1.13.1) multi_xml (0.6.0) @@ -112,7 +112,7 @@ GEM naturally (2.2.0) nokogiri (1.10.1) mini_portile2 (~> 2.4.0) - os (1.0.0) + os (1.0.1) plist (3.5.0) public_suffix (2.0.5) representable (3.0.4) @@ -121,7 +121,7 @@ GEM uber (< 0.2.0) retriable (3.1.2) rouge (2.0.7) - rubyzip (1.2.2) + rubyzip (1.2.3) security (0.1.3) signet (0.11.0) addressable (~> 2.3) @@ -136,20 +136,20 @@ GEM fastlane (>= 2.29.0) highline (~> 1.7) nokogiri (~> 1.7) - terminal-notifier (1.8.0) + terminal-notifier (2.0.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) - tty-cursor (0.6.1) - tty-screen (0.6.5) - tty-spinner (0.9.0) - tty-cursor (~> 0.6.0) + tty-cursor (0.7.0) + tty-screen (0.7.0) + tty-spinner (0.9.1) + tty-cursor (~> 0.7) uber (0.1.0) unf (0.1.4) unf_ext - unf_ext (0.0.7.5) - unicode-display_width (1.4.1) + unf_ext (0.0.7.6) + unicode-display_width (1.6.0) word_wrap (1.0.0) - xcodeproj (1.8.1) + xcodeproj (1.12.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) From 7843b9c532bea4e80934a4da675e37f18d68ab68 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Aug 2019 15:44:17 +0900 Subject: [PATCH 2397/5608] Update fastlane plugins --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 56e640599f..f7c19064b4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -64,7 +64,7 @@ GEM xcodeproj (>= 1.8.1, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) - fastlane-plugin-clean_testflight_testers (0.2.0) + fastlane-plugin-clean_testflight_testers (0.3.0) fastlane-plugin-souyuz (0.8.1) souyuz (>= 0.8.1) fastlane-plugin-xamarin (0.6.3) @@ -110,7 +110,7 @@ GEM multipart-post (2.0.0) nanaimo (0.2.6) naturally (2.2.0) - nokogiri (1.10.1) + nokogiri (1.10.4) mini_portile2 (~> 2.4.0) os (1.0.1) plist (3.5.0) From 3c208b709bfdfd9432ab67a695da5503deee83a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Aug 2019 15:44:38 +0900 Subject: [PATCH 2398/5608] Reorder functions in Fastfile for readability --- fastlane/Fastfile | 29 +++++++++++++---------------- fastlane/README.md | 30 +++++++++++++++--------------- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 48c16caf0f..0b60e28b0f 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -1,22 +1,6 @@ update_fastlane -default_platform(:ios) - platform :ios do - lane :testflight_prune_dry do - clean_testflight_testers(days_of_inactivity:45, dry_run: true) - end - - # Specify a custom number for what's "inactive" - lane :testflight_prune do - clean_testflight_testers(days_of_inactivity: 45) # 120 days, so about 4 months - end - - lane :update_version do |options| - options[:plist_path] = '../osu.iOS/Info.plist' - app_version(options) - end - desc 'Deploy to testflight' lane :beta do |options| update_version(options) @@ -62,4 +46,17 @@ platform :ios do match(options) end + + lane :update_version do |options| + options[:plist_path] = '../osu.iOS/Info.plist' + app_version(options) + end + + lane :testflight_prune_dry do + clean_testflight_testers(days_of_inactivity:45, dry_run: true) + end + + lane :testflight_prune do + clean_testflight_testers(days_of_inactivity: 45) + end end diff --git a/fastlane/README.md b/fastlane/README.md index 53bbc62cae..fbccf1c8c0 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -16,21 +16,6 @@ or alternatively using `brew cask install fastlane` # Available Actions ## iOS -### ios testflight_prune_dry -``` -fastlane ios testflight_prune_dry -``` - -### ios testflight_prune -``` -fastlane ios testflight_prune -``` - -### ios update_version -``` -fastlane ios update_version -``` - ### ios beta ``` fastlane ios beta @@ -46,6 +31,21 @@ Compile the project fastlane ios provision ``` Install provisioning profiles using match +### ios update_version +``` +fastlane ios update_version +``` + +### ios testflight_prune_dry +``` +fastlane ios testflight_prune_dry +``` + +### ios testflight_prune +``` +fastlane ios testflight_prune +``` + ---- From a41356cf0efbae9a44e8c32a2544468d379ed7b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Aug 2019 16:30:46 +0900 Subject: [PATCH 2399/5608] Add android build automation via fastlane --- fastlane/Fastfile | 34 ++++++++++++++++++++++++++++++++++ fastlane/README.md | 19 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 0b60e28b0f..9cc5e4aa74 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -1,5 +1,39 @@ update_fastlane +platform :android do +desc 'Deploy to play store' + lane :beta do |options| + # update csproj version + update_version(options) + + build( + build_configuration: 'Release', + ) + + client = HTTPClient.new + changelog = client.get_content 'https://gist.githubusercontent.com/peppy/ab89c29dcc0dce95f39eb218e8fad197/raw' + changelog.gsub!('$BUILD_ID', options[:build]) + end + + desc 'Compile the project' + lane :build do + nuget_restore( + project_path: 'osu.Android.sln' + ) + + souyuz( + solution_path: 'osu.Android.sln', + platform: "android", + ) + end + + lane :update_version do |options| + options[:plist_path] = '../osu.iOS/Info.plist' + app_version(options) + end + +end + platform :ios do desc 'Deploy to testflight' lane :beta do |options| diff --git a/fastlane/README.md b/fastlane/README.md index fbccf1c8c0..6145620870 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -15,6 +15,25 @@ Install _fastlane_ using or alternatively using `brew cask install fastlane` # Available Actions +## Android +### android beta +``` +fastlane android beta +``` +Deploy to play store +### android build +``` +fastlane android build +``` +Compile the project +### android update_version +``` +fastlane android update_version +``` + + +---- + ## iOS ### ios beta ``` From 536e7d875736de01a5b574259fcdd8085c37aa60 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Aug 2019 19:32:17 +0900 Subject: [PATCH 2400/5608] 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 7bc60ef884..bb283dc0c5 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -61,6 +61,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f5e4d4b1fb..758c4dda4c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 63fa354418..d6ad35b663 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From 24d2b504dd4ce36f2e128a28075444f69860de73 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Fri, 16 Aug 2019 12:39:54 +0200 Subject: [PATCH 2401/5608] Stop autoplay from missing on very dense notes when playing mania --- .../Replays/ManiaAutoGenerator.cs | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index e5669816fa..49bb47cc2b 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Replays; using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; @@ -77,10 +78,35 @@ namespace osu.Game.Rulesets.Mania.Replays private IEnumerable generateActionPoints() { - foreach (var obj in Beatmap.HitObjects) + for (int i = 0; i < Beatmap.HitObjects.Count; i++) { - yield return new HitPoint { Time = obj.StartTime, Column = obj.Column }; - yield return new ReleasePoint { Time = ((obj as IHasEndTime)?.EndTime ?? obj.StartTime) + RELEASE_DELAY, Column = obj.Column }; + var currentObject = Beatmap.HitObjects[i]; + + double endTime = (currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime; + + var nextObjectInTheSameColumn = getNextObjectInTheSameColumn(i); + + bool canDelayKeyUp = nextObjectInTheSameColumn == null || + nextObjectInTheSameColumn.StartTime > endTime + KEY_UP_DELAY; + + double releaseDelay = canDelayKeyUp ? RELEASE_DELAY : nextObjectInTheSameColumn.StartTime - endTime - 1; + + yield return new HitPoint { Time = currentObject.StartTime, Column = currentObject.Column }; + + yield return new ReleasePoint { Time = endTime + releaseDelay, Column = currentObject.Column }; + } + + ManiaHitObject getNextObjectInTheSameColumn(int currentIndex) + { + int desiredColumn = Beatmap.HitObjects[currentIndex++].Column; + + for (; currentIndex < Beatmap.HitObjects.Count; currentIndex++) + { + if (Beatmap.HitObjects[currentIndex].Column == desiredColumn) + return Beatmap.HitObjects[currentIndex]; + } + + return null; } } From 132d51a2cc7ff16b0f35227fa03cb97efee60088 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Aug 2019 19:47:35 +0900 Subject: [PATCH 2402/5608] Update tooltip implementation --- .../Profile/Header/Components/RankGraph.cs | 47 +++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 9cb9d48de7..de760eedfd 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -196,17 +196,30 @@ namespace osu.Game.Overlays.Profile.Header.Components } } - public string TooltipText => Statistics.Value?.Ranks.Global == null ? "" : $"#{ranks[dayIndex].Value:#,##0}|{ranked_days - ranks[dayIndex].Key + 1}"; + public object TooltipContent + { + get + { + if (Statistics.Value?.Ranks.Global == null) + return null; + + var days = ranked_days - ranks[dayIndex].Key + 1; + + return new TooltipDisplayContent + { + Rank = $"#{ranks[dayIndex].Value:#,##0}", + Time = days == 0 ? "now" : $"{days} days ago" + }; + } + } public ITooltip GetCustomTooltip() => new RankGraphTooltip(); - public class RankGraphTooltip : VisibilityContainer, ITooltip + private class RankGraphTooltip : VisibilityContainer, ITooltip { private readonly OsuSpriteText globalRankingText, timeText; private readonly Box background; - public string TooltipText { get; set; } - public RankGraphTooltip() { AutoSizeAxes = Axes.Both; @@ -260,11 +273,14 @@ namespace osu.Game.Overlays.Profile.Header.Components background.Colour = colours.GreySeafoamDark; } - public void Refresh() + public bool SetContent(object content) { - var info = TooltipText.Split('|'); - globalRankingText.Text = info[0]; - timeText.Text = info[1] == "0" ? "now" : $"{info[1]} days ago"; + if (!(content is TooltipDisplayContent info)) + return false; + + globalRankingText.Text = info.Rank; + timeText.Text = info.Time; + return true; } private bool instantMove = true; @@ -280,9 +296,24 @@ namespace osu.Game.Overlays.Profile.Header.Components this.MoveTo(pos, 200, Easing.OutQuint); } + public void Refresh() + { + } + + public string TooltipText + { + set => throw new InvalidOperationException(); + } + protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); protected override void PopOut() => this.FadeOut(200, Easing.OutQuint); } + + private class TooltipDisplayContent + { + public string Rank; + public string Time; + } } } From 7de1757aae1bae0baf006a010cd3be4eb172da62 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Fri, 16 Aug 2019 12:50:48 +0200 Subject: [PATCH 2403/5608] Small improvements --- osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 49bb47cc2b..4fea834748 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -81,19 +81,18 @@ namespace osu.Game.Rulesets.Mania.Replays for (int i = 0; i < Beatmap.HitObjects.Count; i++) { var currentObject = Beatmap.HitObjects[i]; + var nextObjectInTheSameColumn = getNextObjectInTheSameColumn(i); double endTime = (currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime; - var nextObjectInTheSameColumn = getNextObjectInTheSameColumn(i); - bool canDelayKeyUp = nextObjectInTheSameColumn == null || nextObjectInTheSameColumn.StartTime > endTime + KEY_UP_DELAY; - double releaseDelay = canDelayKeyUp ? RELEASE_DELAY : nextObjectInTheSameColumn.StartTime - endTime - 1; + double calculatedDelay = canDelayKeyUp ? RELEASE_DELAY : (nextObjectInTheSameColumn.StartTime - endTime) * 0.9; yield return new HitPoint { Time = currentObject.StartTime, Column = currentObject.Column }; - yield return new ReleasePoint { Time = endTime + releaseDelay, Column = currentObject.Column }; + yield return new ReleasePoint { Time = endTime + calculatedDelay, Column = currentObject.Column }; } ManiaHitObject getNextObjectInTheSameColumn(int currentIndex) From 58d2268b9e6da29b4208ab7d4bf8e0e9c96ab0a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Aug 2019 19:52:35 +0900 Subject: [PATCH 2404/5608] Combine conditionals that provide the same behaviour --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 7c143aa158..66ba6f7e64 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -118,9 +118,6 @@ namespace osu.Game.Rulesets.UI try { - if (!FrameStablePlayback) - manualClock.CurrentTime = newProposedTime; - if (firstConsumption) { // On the first update, frame-stability seeking would result in unexpected/unwanted behaviour. @@ -141,7 +138,7 @@ namespace osu.Game.Rulesets.UI : Math.Max(newProposedTime, manualClock.CurrentTime - sixty_frame_time); } - if (!isAttached) + if (!isAttached || !FrameStablePlayback) { manualClock.CurrentTime = newProposedTime; } From d11b896148508b3e1555982c64ee44ed20b4ff29 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Aug 2019 20:21:00 +0900 Subject: [PATCH 2405/5608] Move FrameStablePlayback handling to early return --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 66ba6f7e64..25fe5cdd96 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -118,7 +118,14 @@ namespace osu.Game.Rulesets.UI try { - if (firstConsumption) + if (!FrameStablePlayback) + { + manualClock.CurrentTime = newProposedTime; + requireMoreUpdateLoops = false; + return; + } + + else if (firstConsumption) { // On the first update, frame-stability seeking would result in unexpected/unwanted behaviour. // Instead we perform an initial seek to the proposed time. @@ -138,7 +145,7 @@ namespace osu.Game.Rulesets.UI : Math.Max(newProposedTime, manualClock.CurrentTime - sixty_frame_time); } - if (!isAttached || !FrameStablePlayback) + if (!isAttached) { manualClock.CurrentTime = newProposedTime; } From 152df9f3d570ee36d05a088c2bbe6d88c3e4a033 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Aug 2019 20:23:09 +0900 Subject: [PATCH 2406/5608] Remove accidental blank line --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 25fe5cdd96..05d3c02381 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -124,7 +124,6 @@ namespace osu.Game.Rulesets.UI requireMoreUpdateLoops = false; return; } - else if (firstConsumption) { // On the first update, frame-stability seeking would result in unexpected/unwanted behaviour. From 0f9706e7985428f1273fd23a9b0e3925dbf1f357 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Sat, 17 Aug 2019 00:18:25 +0200 Subject: [PATCH 2407/5608] Fix using invalid constant --- osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 4fea834748..43150958d0 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Mania.Replays double endTime = (currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime; bool canDelayKeyUp = nextObjectInTheSameColumn == null || - nextObjectInTheSameColumn.StartTime > endTime + KEY_UP_DELAY; + nextObjectInTheSameColumn.StartTime > endTime + RELEASE_DELAY; double calculatedDelay = canDelayKeyUp ? RELEASE_DELAY : (nextObjectInTheSameColumn.StartTime - endTime) * 0.9; From 4fa9abeecec9540da8b24faee553fd482006379d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Aug 2019 15:16:24 +0900 Subject: [PATCH 2408/5608] Replace DifficultyColouredContainer with a more scalable solution --- osu.Game/Beatmaps/BeatmapInfo.cs | 16 ++++ osu.Game/Beatmaps/DifficultyRating.cs | 15 ++++ .../Drawables/DifficultyColouredContainer.cs | 85 ------------------- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 11 ++- osu.Game/Graphics/OsuColour.cs | 26 ++++++ osu.Game/Screens/Select/BeatmapInfoWedge.cs | 14 +-- 6 files changed, 73 insertions(+), 94 deletions(-) create mode 100644 osu.Game/Beatmaps/DifficultyRating.cs delete mode 100644 osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 8042f6b4b9..700f981088 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -129,6 +129,22 @@ namespace osu.Game.Beatmaps ///
      diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs new file mode 100644 index 0000000000..87d6012205 --- /dev/null +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -0,0 +1,413 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.IO; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Audio.Track; +using osu.Framework.Bindables; +using osu.Framework.Screens; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; +using osu.Framework.MathUtils; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.IO.Archives; +using osu.Game.Rulesets; +using osu.Game.Screens.Backgrounds; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Menu +{ + public class IntroTriangles : IntroScreen + { + private const string menu_music_beatmap_hash = "a1556d0801b3a6b175dda32ef546f0ec812b400499f575c44fccbe9c67f9b1e5"; + + private SampleChannel welcome; + + protected override BackgroundScreen CreateBackground() => background = new BackgroundScreenDefault(false) + { + Alpha = 0, + }; + + [Resolved] + private AudioManager audio { get; set; } + + private Bindable menuMusic; + private Track track; + private WorkingBeatmap introBeatmap; + + private BackgroundScreenDefault background; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game) + { + menuMusic = config.GetBindable(OsuSetting.MenuMusic); + + BeatmapSetInfo setInfo = null; + + if (!menuMusic.Value) + { + var sets = beatmaps.GetAllUsableBeatmapSets(); + if (sets.Count > 0) + setInfo = beatmaps.QueryBeatmapSet(s => s.ID == sets[RNG.Next(0, sets.Count - 1)].ID); + } + + if (setInfo == null) + { + setInfo = beatmaps.QueryBeatmapSet(b => b.Hash == menu_music_beatmap_hash); + + if (setInfo == null) + { + // we need to import the default menu background beatmap + setInfo = beatmaps.Import(new ZipArchiveReader(game.Resources.GetStream(@"Tracks/triangles.osz"), "triangles.osz")).Result; + + setInfo.Protected = true; + beatmaps.Update(setInfo); + } + } + + introBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); + + track = introBeatmap.Track; + track.Reset(); + + if (config.Get(OsuSetting.MenuVoice) && !menuMusic.Value) + // triangles has welcome sound included in the track. only play this if the user doesn't want menu music. + welcome = audio.Samples.Get(@"welcome"); + } + + protected override void LogoArriving(OsuLogo logo, bool resuming) + { + base.LogoArriving(logo, resuming); + + logo.Triangles = true; + + if (!resuming) + { + Beatmap.Value = introBeatmap; + introBeatmap = null; + + PrepareMenuLoad(); + + LoadComponentAsync(new TrianglesIntroSequence(logo, background) + { + RelativeSizeAxes = Axes.Both, + Clock = new FramedClock(track), + LoadMenu = LoadMenu + }, t => + { + AddInternal(t); + welcome?.Play(); + + // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu. + if (menuMusic.Value) + track.Start(); + }); + } + } + + public override void OnResuming(IScreen last) + { + base.OnResuming(last); + background.FadeOut(100); + } + + public override void OnSuspending(IScreen next) + { + track = null; + base.OnSuspending(next); + } + + private class TrianglesIntroSequence : CompositeDrawable + { + private readonly OsuLogo logo; + private readonly BackgroundScreenDefault background; + private OsuSpriteText welcomeText; + + private RulesetFlow rulesets; + private Container rulesetsScale; + private Drawable logoContainerSecondary; + private Drawable logoContainer; + + private GlitchingTriangles triangles; + + public Action LoadMenu; + + public TrianglesIntroSequence(OsuLogo logo, BackgroundScreenDefault background) + { + this.logo = logo; + this.background = background; + } + + private OsuGameBase game; + + [BackgroundDependencyLoader] + private void load(TextureStore textures, OsuGameBase game) + { + this.game = game; + + InternalChildren = new[] + { + triangles = new GlitchingTriangles + { + Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(0.4f, 0.16f) + }, + welcomeText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Padding = new MarginPadding { Bottom = 10 }, + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 42), + Alpha = 1, + Spacing = new Vector2(5), + }, + rulesetsScale = new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + rulesets = new RulesetFlow() + } + }, + logoContainerSecondary = new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Child = logoContainer = new LazerLogo(textures.GetStream("Menu/logo-triangles.mp4")) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }, + }; + } + + private const double text_1 = 200; + private const double text_2 = 400; + private const double text_3 = 700; + private const double text_4 = 900; + private const double text_glitch = 1060; + + private const double rulesets_1 = 1450; + private const double rulesets_2 = 1650; + private const double rulesets_3 = 1850; + + private const double logo_scale_duration = 920; + private const double logo_1 = 2080; + private const double logo_2 = logo_1 + logo_scale_duration; + + protected override void LoadComplete() + { + base.LoadComplete(); + + const float scale_start = 1.2f; + const float scale_adjust = 0.8f; + + rulesets.Hide(); + logoContainer.Hide(); + background.Hide(); + + using (BeginAbsoluteSequence(0, true)) + { + using (BeginDelayedSequence(text_1, true)) + welcomeText.FadeIn().OnComplete(t => t.Text = "wel"); + + using (BeginDelayedSequence(text_2, true)) + welcomeText.FadeIn().OnComplete(t => t.Text = "welcome"); + + using (BeginDelayedSequence(text_3, true)) + welcomeText.FadeIn().OnComplete(t => t.Text = "welcome to"); + + using (BeginDelayedSequence(text_4, true)) + { + welcomeText.FadeIn().OnComplete(t => t.Text = "welcome to osu!"); + welcomeText.TransformTo(nameof(welcomeText.Spacing), new Vector2(50, 0), 5000); + } + + using (BeginDelayedSequence(text_glitch, true)) + triangles.FadeIn(); + + using (BeginDelayedSequence(rulesets_1, true)) + { + rulesetsScale.ScaleTo(0.8f, 1000); + rulesets.FadeIn().ScaleTo(1).TransformSpacingTo(new Vector2(200, 0)); + welcomeText.FadeOut(); + triangles.FadeOut(); + } + + using (BeginDelayedSequence(rulesets_2, true)) + { + rulesets.ScaleTo(2).TransformSpacingTo(new Vector2(30, 0)); + } + + using (BeginDelayedSequence(rulesets_3, true)) + { + rulesets.ScaleTo(4).TransformSpacingTo(new Vector2(10, 0)); + rulesetsScale.ScaleTo(1.3f, 1000); + } + + using (BeginDelayedSequence(logo_1, true)) + { + rulesets.FadeOut(); + + // matching flyte curve y = 0.25x^2 + (max(0, x - 0.7) / 0.3) ^ 5 + logoContainer.FadeIn().ScaleTo(scale_start).Then().Delay(logo_scale_duration * 0.7f).ScaleTo(scale_start - scale_adjust, logo_scale_duration * 0.3f, Easing.InQuint); + logoContainerSecondary.ScaleTo(scale_start).Then().ScaleTo(scale_start - scale_adjust * 0.25f, logo_scale_duration, Easing.InQuad); + } + + using (BeginDelayedSequence(logo_2, true)) + { + logoContainer.FadeOut().OnComplete(_ => + { + logo.FadeIn(); + background.FadeIn(); + + game.Add(new GameWideFlash()); + + LoadMenu(); + }); + } + } + } + + private class GameWideFlash : Box + { + private const double flash_length = 1000; + + public GameWideFlash() + { + Colour = Color4.White; + RelativeSizeAxes = Axes.Both; + Blending = BlendingMode.Additive; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + this.FadeOutFromOne(flash_length, Easing.Out); + } + } + + private class LazerLogo : CompositeDrawable + { + public LazerLogo(Stream videoStream) + { + Size = new Vector2(960); + + InternalChild = new VideoSprite(videoStream) + { + RelativeSizeAxes = Axes.Both, + Clock = new FramedOffsetClock(Clock) { Offset = -logo_1 } + }; + } + } + + private class RulesetFlow : FillFlowContainer + { + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) + { + var modes = new List(); + + foreach (var ruleset in rulesets.AvailableRulesets) + { + var icon = new ConstrainedIconContainer + { + Icon = ruleset.CreateInstance().CreateIcon(), + Size = new Vector2(30), + }; + + modes.Add(icon); + } + + AutoSizeAxes = Axes.Both; + Children = modes; + + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + } + } + + private class GlitchingTriangles : CompositeDrawable + { + public GlitchingTriangles() + { + RelativeSizeAxes = Axes.Both; + } + + private double? lastGenTime; + + private const double time_between_triangles = 22; + + protected override void Update() + { + base.Update(); + + if (lastGenTime == null || Time.Current - lastGenTime > time_between_triangles) + { + lastGenTime = (lastGenTime ?? Time.Current) + time_between_triangles; + + Drawable triangle = new OutlineTriangle(RNG.NextBool(), (RNG.NextSingle() + 0.2f) * 80) + { + RelativePositionAxes = Axes.Both, + Position = new Vector2(RNG.NextSingle(), RNG.NextSingle()), + }; + + AddInternal(triangle); + + triangle.FadeOutFromOne(120); + } + } + + /// + /// Represents a sprite that is drawn in a triangle shape, instead of a rectangle shape. + /// + public class OutlineTriangle : BufferedContainer + { + public OutlineTriangle(bool outlineOnly, float size) + { + Size = new Vector2(size); + + InternalChildren = new Drawable[] + { + new Triangle { RelativeSizeAxes = Axes.Both }, + }; + + if (outlineOnly) + { + AddInternal(new Triangle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = Color4.Black, + Size = new Vector2(size - 5), + Blending = BlendingMode.None, + }); + } + + Blending = BlendingMode.Additive; + CacheDrawnFrameBuffer = true; + } + } + } + } + } +} From 8e6a3162ab3bfead6842379973fd671f927e39c7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Aug 2019 20:05:36 +0900 Subject: [PATCH 2286/5608] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 40c15a1162..4ec67ab30d 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,7 +62,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8ee325c2ac..fb9269e5f0 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index b46438f766..1532e2d71b 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -104,7 +104,7 @@ - + From 6264a6a1c95b9b3c924e2ace2b4f8ff0594862f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Aug 2019 20:18:02 +0900 Subject: [PATCH 2287/5608] Adjust slider snaking and hitcircle fading to match stable --- .../Objects/Drawables/Pieces/SnakingSliderBody.cs | 2 +- osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index 0590ca1d96..70a1bad4a3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces var spanProgress = slider.ProgressAt(completionProgress); double start = 0; - double end = SnakingIn.Value ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / slider.TimeFadeIn, 0, 1) : 1; + double end = SnakingIn.Value ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; if (span >= slider.SpanCount() - 1) { diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index d1221fd2d3..b52bfcd181 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Objects base.ApplyDefaultsToSelf(controlPointInfo, difficulty); TimePreempt = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450); - TimeFadeIn = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1200, 800, 300); + TimeFadeIn = 400; // as per osu-stable Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2; } From 7dd62ae6f350211cb09bd7b58afc4adf2f83e80b Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 9 Aug 2019 20:48:08 +0930 Subject: [PATCH 2288/5608] Remove Android BASS libraries --- osu.Android.props | 4 +--- osu.Android/lib/arm64-v8a/libbass.so | Bin 308904 -> 0 bytes osu.Android/lib/arm64-v8a/libbass_fx.so | Bin 154408 -> 0 bytes osu.Android/lib/armeabi-v7a/libbass.so | Bin 222620 -> 0 bytes osu.Android/lib/armeabi-v7a/libbass_fx.so | Bin 92176 -> 0 bytes osu.Android/lib/x86/libbass.so | Bin 316716 -> 0 bytes osu.Android/lib/x86/libbass_fx.so | Bin 153532 -> 0 bytes 7 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 osu.Android/lib/arm64-v8a/libbass.so delete mode 100644 osu.Android/lib/arm64-v8a/libbass_fx.so delete mode 100644 osu.Android/lib/armeabi-v7a/libbass.so delete mode 100644 osu.Android/lib/armeabi-v7a/libbass_fx.so delete mode 100644 osu.Android/lib/x86/libbass.so delete mode 100644 osu.Android/lib/x86/libbass_fx.so diff --git a/osu.Android.props b/osu.Android.props index 40c15a1162..82d8696ca5 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -49,9 +49,7 @@ osu.licenseheader - - Always - + diff --git a/osu.Android/lib/arm64-v8a/libbass.so b/osu.Android/lib/arm64-v8a/libbass.so deleted file mode 100644 index d5c24b3e4b2918a33153cf6a0561366996be16f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 308904 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

      ^m>m@_QI`Gyr3D`HGSXQzB#7TNkp#fsh! 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%0A0ic&Bx^ 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 T?MJo0F6IAiepbA(NM`E) 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 z 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 EAM_!vo&W#< diff --git a/osu.Android/lib/armeabi-v7a/libbass_fx.so b/osu.Android/lib/armeabi-v7a/libbass_fx.so deleted file mode 100644 index 006e2feb30bb005eec727f829cc3965fb136f16c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92176 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 V>7s+MhuN$Sd><=0>Ypgz{{j9{WcmOA diff --git a/osu.Android/lib/x86/libbass.so b/osu.Android/lib/x86/libbass.so deleted file mode 100644 index b0f758a42b7397b3289557f51de6b55df7b3b4ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 316716 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 z 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 kkiFcJ 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 E0opfv^#A|> From caf13ae52ddbf06fbf11fe3c711e1fb304f8915f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Aug 2019 23:29:32 +0900 Subject: [PATCH 2289/5608] 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 40c15a1162..3b2e6574ac 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8ee325c2ac..1dd19ac7ed 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index b46438f766..1c3faeed39 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From fc4c0cc2e72d9108881cba86f1854110ee17549e Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 10:52:37 +0200 Subject: [PATCH 2290/5608] Fix visual discrepancies with master --- osu.Game/Overlays/OSD/Toast.cs | 1 + osu.Game/Overlays/OSD/TrackedSettingToast.cs | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/OSD/Toast.cs b/osu.Game/Overlays/OSD/Toast.cs index 67c9b46c77..db5e6e4a6a 100644 --- a/osu.Game/Overlays/OSD/Toast.cs +++ b/osu.Game/Overlays/OSD/Toast.cs @@ -65,6 +65,7 @@ namespace osu.Game.Overlays.OSD Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, Name = "Shortcut", + Alpha = 0.3f, Margin = new MarginPadding { Bottom = 15 }, Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), Text = string.IsNullOrEmpty(keybinding) ? "NO KEY BOUND" : keybinding.ToUpperInvariant() diff --git a/osu.Game/Overlays/OSD/TrackedSettingToast.cs b/osu.Game/Overlays/OSD/TrackedSettingToast.cs index 9812dcd797..0f4bd34779 100644 --- a/osu.Game/Overlays/OSD/TrackedSettingToast.cs +++ b/osu.Game/Overlays/OSD/TrackedSettingToast.cs @@ -17,6 +17,8 @@ namespace osu.Game.Overlays.OSD { public class TrackedSettingToast : Toast { + private const int lights_bottom_margin = 40; + public TrackedSettingToast(SettingDescription description) : base(description.Name, description.Value, description.Shortcut) { @@ -24,17 +26,16 @@ namespace osu.Game.Overlays.OSD Children = new Drawable[] { - new FillFlowContainer + new Container { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Direction = FillDirection.Vertical, - Margin = new MarginPadding { Top = 70 }, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Margin = new MarginPadding { Bottom = lights_bottom_margin }, Children = new Drawable[] { optionLights = new FillFlowContainer { - Padding = new MarginPadding { Bottom = 5 }, + Margin = new MarginPadding { Bottom = 5 }, Spacing = new Vector2(5, 0), Direction = FillDirection.Horizontal, Anchor = Anchor.TopCentre, From b0a71779877c55e6b181e8e50207de80ff79e96a Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 13:26:19 +0200 Subject: [PATCH 2291/5608] Add ScreenTitleIcon class, used for displaying custom specific icons on overlays. --- .../Graphics/UserInterface/ScreenTitle.cs | 2 +- .../Graphics/UserInterface/ScreenTitleIcon.cs | 61 +++++++++++++++++++ .../Overlays/Changelog/ChangelogHeader.cs | 45 +------------- 3 files changed, 63 insertions(+), 45 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index 7b39238e5e..10fc312d8b 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -15,7 +15,7 @@ namespace osu.Game.Graphics.UserInterface { public const float ICON_WIDTH = ICON_SIZE + icon_spacing; - protected const float ICON_SIZE = 25; + public const float ICON_SIZE = 25; private SpriteIcon iconSprite; private readonly OsuSpriteText titleText, pageText; diff --git a/osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs b/osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs new file mode 100644 index 0000000000..12e0617e35 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs @@ -0,0 +1,61 @@ +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osuTK; + +namespace osu.Game.Graphics.UserInterface +{ + ///

      + /// A custom icon class for use with + /// + public class ScreenTitleIcon : CompositeDrawable + { + private const float circle_allowance = 0.8f; + + private string icon; + + public ScreenTitleIcon(string icon) + { + this.icon = icon; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures, OsuColour colours) + { + Size = new Vector2(ScreenTitle.ICON_SIZE / circle_allowance); + + InternalChildren = new Drawable[] + { + new CircularContainer + { + Masking = true, + BorderColour = colours.Violet, + BorderThickness = 3, + MaskingSmoothness = 1, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Sprite + { + RelativeSizeAxes = Axes.Both, + Texture = textures.Get(icon), + Size = new Vector2(circle_allowance), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Violet, + Alpha = 0, + AlwaysPresent = true, + }, + } + }, + }; + } + } +} diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index fca62fbb44..8b78216136 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -7,13 +7,11 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; -using osuTK; namespace osu.Game.Overlays.Changelog { @@ -123,48 +121,7 @@ namespace osu.Game.Overlays.Changelog AccentColour = colours.Violet; } - protected override Drawable CreateIcon() => new ChangelogIcon(); - - internal class ChangelogIcon : CompositeDrawable - { - private const float circle_allowance = 0.8f; - - [BackgroundDependencyLoader] - private void load(TextureStore textures, OsuColour colours) - { - Size = new Vector2(ICON_SIZE / circle_allowance); - - InternalChildren = new Drawable[] - { - new CircularContainer - { - Masking = true, - BorderColour = colours.Violet, - BorderThickness = 3, - MaskingSmoothness = 1, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Sprite - { - RelativeSizeAxes = Axes.Both, - Texture = textures.Get(@"Icons/changelog"), - Size = new Vector2(circle_allowance), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Violet, - Alpha = 0, - AlwaysPresent = true, - }, - } - }, - }; - } - } + protected override Drawable CreateIcon() => new ScreenTitleIcon(@"Icons/changelog"); } } } From 8eb3409a648bb03ff702d2f66807e6c0e0c02c86 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 14:03:44 +0200 Subject: [PATCH 2292/5608] Add missing licence header --- osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs b/osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs index 12e0617e35..8a42645b37 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs @@ -1,4 +1,7 @@ -using osu.Framework.Allocation; +// 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; From d55f9404dab5cd639d8f3524df9e97c31bf909f3 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 14:23:37 +0200 Subject: [PATCH 2293/5608] Fix CI issues --- osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs b/osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs index 8a42645b37..4ce554009a 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs @@ -18,7 +18,7 @@ namespace osu.Game.Graphics.UserInterface { private const float circle_allowance = 0.8f; - private string icon; + private readonly string icon; public ScreenTitleIcon(string icon) { From e3d52d8d7171076a28ddb67feaf130cf62a7ea3a Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 12:22:45 +0200 Subject: [PATCH 2294/5608] Add NewsOverlay class --- osu.Game/Overlays/NewsOverlay.cs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 osu.Game/Overlays/NewsOverlay.cs diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs new file mode 100644 index 0000000000..76040a6086 --- /dev/null +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -0,0 +1,23 @@ +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; + +namespace osu.Game.Overlays +{ + public class NewsOverlay : FullscreenOverlay + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.PurpleLightAlternative + } + }; + } + } +} From 4b0ac381b7372a0ba2f6238e2890509c158debb2 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 12:26:54 +0200 Subject: [PATCH 2295/5608] Add visual tests. --- .../Visual/Online/TestSceneNewsOverlay.cs | 17 +++++++++++++++++ osu.Game/Overlays/NewsOverlay.cs | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs new file mode 100644 index 0000000000..3362d4700f --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -0,0 +1,17 @@ +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneNewsOverlay : OsuTestScene + { + private NewsOverlay news; + + protected override void LoadComplete() + { + base.LoadComplete(); + Add(news = new NewsOverlay()); + AddStep(@"Show", news.Show); + AddStep(@"Hide", news.Hide); + } + } +} diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index 76040a6086..76b917b65d 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -15,7 +15,7 @@ namespace osu.Game.Overlays new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.PurpleLightAlternative + Colour = colours.PurpleDarkAlternative } }; } From b19c378fc8a7e5b571ed0e288b79c6e2ac628941 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 12:53:34 +0200 Subject: [PATCH 2296/5608] Add NewsHeader class --- osu.Game/Overlays/News/NewsHeader.cs | 71 ++++++++++++++++++++++++++++ osu.Game/Overlays/NewsOverlay.cs | 21 +++++++- 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Overlays/News/NewsHeader.cs diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs new file mode 100644 index 0000000000..43a514cdc6 --- /dev/null +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -0,0 +1,71 @@ +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Overlays.News +{ + public class NewsHeader : OverlayHeader + { + private const string front_page_string = "Front Page"; + + private NewsHeaderTitle title; + + public NewsHeader() + { + TabControl.AddItem(front_page_string); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colour) + { + TabControl.AccentColour = colour.Violet; + } + + protected override Drawable CreateBackground() => new NewsHeaderBackground(); + + protected override Drawable CreateContent() => new Container(); + + protected override ScreenTitle CreateTitle() => title = new NewsHeaderTitle(); + + private class NewsHeaderBackground : Sprite + { + public NewsHeaderBackground() + { + RelativeSizeAxes = Axes.Both; + FillMode = FillMode.Fill; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Texture = textures.Get(@"Headers/changelog"); //using changelog bg until corresponding osu-resources pr is merged. + } + } + + private class NewsHeaderTitle : ScreenTitle + { + private const string article_string = "Article"; + + public bool IsReadingArticle + { + set => Section = value ? article_string : front_page_string; + } + + public NewsHeaderTitle() + { + Title = "News"; + IsReadingArticle = false; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AccentColour = colours.Violet; + } + } + } +} diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index 76b917b65d..80088a25bc 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -1,12 +1,17 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Overlays.News; namespace osu.Game.Overlays { public class NewsOverlay : FullscreenOverlay { + private NewsHeader header; + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -16,7 +21,21 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.Both, Colour = colours.PurpleDarkAlternative - } + }, + new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + header = new NewsHeader() + }, + }, + }, }; } } From 0e5561c783344856d751338f32e876cb373cb4a0 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 16:12:42 +0200 Subject: [PATCH 2297/5608] Use News overlay resources --- osu.Game/Overlays/News/NewsHeader.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 43a514cdc6..fb02f7f105 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.News [BackgroundDependencyLoader] private void load(TextureStore textures) { - Texture = textures.Get(@"Headers/changelog"); //using changelog bg until corresponding osu-resources pr is merged. + Texture = textures.Get(@"Headers/news"); } } @@ -61,6 +61,8 @@ namespace osu.Game.Overlays.News IsReadingArticle = false; } + protected override Drawable CreateIcon() => new ScreenTitleIcon(@"Icons/news"); + [BackgroundDependencyLoader] private void load(OsuColour colours) { From 7825923cb63f157e7e9fcd7307ae05b9d3d0b51d Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 16:33:16 +0200 Subject: [PATCH 2298/5608] Use media keys as default bindings for jukebox. --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 6 +++--- osu.Game/Overlays/MusicController.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 8c927c2bc6..809ec9a09e 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -45,9 +45,9 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.Enter, GlobalAction.Select), new KeyBinding(InputKey.KeypadEnter, GlobalAction.Select), - new KeyBinding(InputKey.F1, GlobalAction.MusicPrev), - new KeyBinding(InputKey.F5, GlobalAction.MusicNext), - new KeyBinding(InputKey.F3, GlobalAction.MusicPlay), + new KeyBinding(InputKey.TrackPrevious, GlobalAction.MusicPrev), + new KeyBinding(InputKey.TrackNext, GlobalAction.MusicNext), + new KeyBinding(InputKey.PlayPause, GlobalAction.MusicPlay), }; public IEnumerable InGameKeyBindings => new[] diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 724be21957..ed51a80924 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -565,7 +565,7 @@ namespace osu.Game.Overlays { if (beatmap.Disabled) return false; - play(); + togglePause(); return true; } From b92e331730f2971c5fbe7b5afe0031e781c2c494 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 17:06:52 +0200 Subject: [PATCH 2299/5608] Add tabcontrol logic to news overlay --- .../Visual/Online/TestSceneNewsOverlay.cs | 3 ++ osu.Game/Overlays/News/NewsHeader.cs | 35 ++++++++++++++++++- osu.Game/Overlays/NewsOverlay.cs | 13 +++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index 3362d4700f..d5273801d8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -12,6 +12,9 @@ namespace osu.Game.Tests.Visual.Online Add(news = new NewsOverlay()); AddStep(@"Show", news.Show); AddStep(@"Hide", news.Hide); + + AddStep(@"Show front page", () => news.ShowFrontPage()); + AddStep(@"Custom article", () => news.Current.Value = "Test Article 101"); } } } diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index fb02f7f105..e887d48456 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -1,10 +1,12 @@ using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; +using System; namespace osu.Game.Overlays.News { @@ -14,9 +16,21 @@ namespace osu.Game.Overlays.News private NewsHeaderTitle title; + public readonly Bindable Current = new Bindable(null); + + public Action ShowFrontPage; + public NewsHeader() { TabControl.AddItem(front_page_string); + + TabControl.Current.ValueChanged += e => + { + if (e.NewValue == front_page_string) + ShowFrontPage?.Invoke(); + }; + + Current.ValueChanged += showArticle; } [BackgroundDependencyLoader] @@ -25,6 +39,25 @@ namespace osu.Game.Overlays.News TabControl.AccentColour = colour.Violet; } + private void showArticle(ValueChangedEvent e) + { + if (e.OldValue != null) + TabControl.RemoveItem(e.OldValue); + + if (e.NewValue != null) + { + TabControl.AddItem(e.NewValue); + TabControl.Current.Value = e.NewValue; + + title.IsReadingArticle = true; + } + else + { + TabControl.Current.Value = front_page_string; + title.IsReadingArticle = false; + } + } + protected override Drawable CreateBackground() => new NewsHeaderBackground(); protected override Drawable CreateContent() => new Container(); @@ -52,7 +85,7 @@ namespace osu.Game.Overlays.News public bool IsReadingArticle { - set => Section = value ? article_string : front_page_string; + set => Section = value ? article_string : front_page_string; } public NewsHeaderTitle() diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index 80088a25bc..1506cbb288 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -1,4 +1,5 @@ using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -12,6 +13,8 @@ namespace osu.Game.Overlays { private NewsHeader header; + public readonly Bindable Current = new Bindable(null); + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -37,6 +40,16 @@ namespace osu.Game.Overlays }, }, }; + + header.Current.BindTo(Current); + header.ShowFrontPage = ShowFrontPage; + Current.TriggerChange(); + } + + public void ShowFrontPage() + { + Current.Value = null; + Show(); } } } From 684c37bf05e8bc3367d5c48d4997a7e1bab75157 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Aug 2019 16:15:44 +0900 Subject: [PATCH 2300/5608] Rename class to better match usage --- ...{ScreenTitleIcon.cs => ScreenTitleTextureIcon.cs} | 12 ++++++------ osu.Game/Overlays/Changelog/ChangelogHeader.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) rename osu.Game/Graphics/UserInterface/{ScreenTitleIcon.cs => ScreenTitleTextureIcon.cs} (85%) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs b/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs similarity index 85% rename from osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs rename to osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs index 4ce554009a..f590e7e357 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitleIcon.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitleTextureIcon.cs @@ -12,17 +12,17 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { /// - /// A custom icon class for use with + /// A custom icon class for use with based off a texture resource. /// - public class ScreenTitleIcon : CompositeDrawable + public class ScreenTitleTextureIcon : CompositeDrawable { private const float circle_allowance = 0.8f; - private readonly string icon; + private readonly string textureName; - public ScreenTitleIcon(string icon) + public ScreenTitleTextureIcon(string textureName) { - this.icon = icon; + this.textureName = textureName; } [BackgroundDependencyLoader] @@ -44,7 +44,7 @@ namespace osu.Game.Graphics.UserInterface new Sprite { RelativeSizeAxes = Axes.Both, - Texture = textures.Get(icon), + Texture = textures.Get(textureName), Size = new Vector2(circle_allowance), Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 8b78216136..b2e9be24b3 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -121,7 +121,7 @@ namespace osu.Game.Overlays.Changelog AccentColour = colours.Violet; } - protected override Drawable CreateIcon() => new ScreenTitleIcon(@"Icons/changelog"); + protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/changelog"); } } } From fd334e0319729576afb81d600b71128f1fff2970 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 11 Aug 2019 14:57:21 +0300 Subject: [PATCH 2301/5608] Implement basic layout for AccuracyBar --- osu.Game/Screens/Play/HUD/AccuracyBar.cs | 19 +++++++++++++++++++ osu.Game/Screens/Play/HUDOverlay.cs | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 osu.Game/Screens/Play/HUD/AccuracyBar.cs diff --git a/osu.Game/Screens/Play/HUD/AccuracyBar.cs b/osu.Game/Screens/Play/HUD/AccuracyBar.cs new file mode 100644 index 0000000000..8b85014b2f --- /dev/null +++ b/osu.Game/Screens/Play/HUD/AccuracyBar.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Judgements; + +namespace osu.Game.Screens.Play.HUD +{ + public class AccuracyBar : Container + { + public AccuracyBar(bool mirrored) + { + } + + public void OnNewJudgement(JudgementResult judgement) + { + } + } +} diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 43b9491750..88ad57c175 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -35,6 +35,8 @@ namespace osu.Game.Screens.Play public readonly ModDisplay ModDisplay; public readonly HoldForMenuButton HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; + public readonly AccuracyBar LeftAccuracyBar; + public readonly AccuracyBar RightAccuracyBar; public Bindable ShowHealthbar = new Bindable(true); @@ -84,6 +86,8 @@ namespace osu.Game.Screens.Play HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), ModDisplay = CreateModsContainer(), + LeftAccuracyBar = CreateAccuracyBar(false), + RightAccuracyBar = CreateAccuracyBar(), } }, PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), @@ -256,6 +260,15 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20, Right = 10 }, }; + protected virtual AccuracyBar CreateAccuracyBar(bool mirrored = true) => new AccuracyBar(mirrored) + { + Anchor = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, + AutoSizeAxes = Axes.X, + Height = 300, + Margin = new MarginPadding { Horizontal = 20 } + }; + protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); protected virtual void BindProcessor(ScoreProcessor processor) @@ -265,6 +278,12 @@ namespace osu.Game.Screens.Play ComboCounter?.Current.BindTo(processor.Combo); HealthDisplay?.Current.BindTo(processor.Health); + if (LeftAccuracyBar != null) + processor.NewJudgement += LeftAccuracyBar.OnNewJudgement; + + if (RightAccuracyBar != null) + processor.NewJudgement += RightAccuracyBar.OnNewJudgement; + if (HealthDisplay is StandardHealthDisplay shd) processor.NewJudgement += shd.Flash; } From ed409d113b2e02bc49c252c4074468393bc6a8ae Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 11 Aug 2019 15:53:15 +0300 Subject: [PATCH 2302/5608] Add judgement lines generator --- osu.Game/Screens/Play/HUD/AccuracyBar.cs | 42 +++++++++++++++++++++++- osu.Game/Screens/Play/HUDOverlay.cs | 4 +-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/AccuracyBar.cs b/osu.Game/Screens/Play/HUD/AccuracyBar.cs index 8b85014b2f..8b14bc47eb 100644 --- a/osu.Game/Screens/Play/HUD/AccuracyBar.cs +++ b/osu.Game/Screens/Play/HUD/AccuracyBar.cs @@ -1,19 +1,59 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Judgements; +using osuTK.Graphics; +using osuTK; namespace osu.Game.Screens.Play.HUD { public class AccuracyBar : Container { - public AccuracyBar(bool mirrored) + private const int bar_width = 5; + private const int bar_height = 250; + private const int spacing = 3; + + private readonly bool mirrored; + + public AccuracyBar(bool mirrored = false) { + this.mirrored = mirrored; + + Size = new Vector2(bar_width, bar_height); + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }; } public void OnNewJudgement(JudgementResult judgement) { + Container judgementLine; + + Add(judgementLine = CreateJudgementLine(judgement.TimeOffset)); + + judgementLine.FadeOut(5000, Easing.OutQuint); + judgementLine.Expire(); } + + protected virtual Container CreateJudgementLine(double offset) => new CircularContainer + { + Anchor = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = mirrored ? Anchor.CentreLeft : Anchor.CentreRight, + Masking = true, + Size = new Vector2(10, 2), + RelativePositionAxes = Axes.Y, + Y = (float)offset / bar_height, + X = mirrored ? spacing : -spacing, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + } + }; } } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 88ad57c175..3fafc21ea8 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -264,9 +264,7 @@ namespace osu.Game.Screens.Play { Anchor = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, Origin = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, - AutoSizeAxes = Axes.X, - Height = 300, - Margin = new MarginPadding { Horizontal = 20 } + Margin = new MarginPadding { Horizontal = 30 } }; protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); From 0a255fe4d1750440e02fc429f40021f7df9b55c8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 11 Aug 2019 16:38:03 +0300 Subject: [PATCH 2303/5608] Add moving arrow --- osu.Game/Screens/Play/HUD/AccuracyBar.cs | 46 ++++++++++++++++++++---- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/AccuracyBar.cs b/osu.Game/Screens/Play/HUD/AccuracyBar.cs index 8b14bc47eb..3c13111b22 100644 --- a/osu.Game/Screens/Play/HUD/AccuracyBar.cs +++ b/osu.Game/Screens/Play/HUD/AccuracyBar.cs @@ -7,6 +7,8 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Judgements; using osuTK.Graphics; using osuTK; +using osu.Framework.Graphics.Sprites; +using System.Collections.Generic; namespace osu.Game.Screens.Play.HUD { @@ -17,16 +19,31 @@ namespace osu.Game.Screens.Play.HUD private const int spacing = 3; private readonly bool mirrored; + private readonly SpriteIcon arrow; + private readonly List judgementOffsets = new List(); public AccuracyBar(bool mirrored = false) { this.mirrored = mirrored; Size = new Vector2(bar_width, bar_height); - Child = new Box + + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = Color4.White, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }, + arrow = new SpriteIcon + { + Anchor = mirrored ? Anchor.CentreLeft : Anchor.CentreRight, + Origin = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, + X = mirrored ? -spacing : spacing, + RelativePositionAxes = Axes.Y, + Icon = mirrored ? FontAwesome.Solid.ChevronRight : FontAwesome.Solid.ChevronLeft, + Size = new Vector2(10), + } }; } @@ -34,20 +51,22 @@ namespace osu.Game.Screens.Play.HUD { Container judgementLine; - Add(judgementLine = CreateJudgementLine(judgement.TimeOffset)); + Add(judgementLine = CreateJudgementLine(judgement)); judgementLine.FadeOut(5000, Easing.OutQuint); judgementLine.Expire(); + + arrow.MoveToY(calculateArrowPosition(judgement) / bar_height, 500, Easing.OutQuint); } - protected virtual Container CreateJudgementLine(double offset) => new CircularContainer + protected virtual Container CreateJudgementLine(JudgementResult judgement) => new CircularContainer { Anchor = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, Origin = mirrored ? Anchor.CentreLeft : Anchor.CentreRight, Masking = true, Size = new Vector2(10, 2), RelativePositionAxes = Axes.Y, - Y = (float)offset / bar_height, + Y = (float)judgement.TimeOffset / bar_height, X = mirrored ? spacing : -spacing, Child = new Box { @@ -55,5 +74,20 @@ namespace osu.Game.Screens.Play.HUD Colour = Color4.White, } }; + + private float calculateArrowPosition(JudgementResult judgement) + { + if (judgementOffsets.Count > 5) + judgementOffsets.RemoveAt(0); + + judgementOffsets.Add(judgement.TimeOffset); + + double offsets = 0; + + foreach (var offset in judgementOffsets) + offsets += offset; + + return (float)offsets / judgementOffsets.Count; + } } } From cc4ee2df0591301b420675255a28e0612862654f Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 11 Aug 2019 16:41:56 +0200 Subject: [PATCH 2304/5608] add ToString() override to Beatmap class --- osu.Game/Beatmaps/Beatmap.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 4ebeee40bf..6079a112e6 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -60,5 +60,7 @@ namespace osu.Game.Beatmaps public class Beatmap : Beatmap { public new Beatmap Clone() => (Beatmap)base.Clone(); + + public override string ToString() => BeatmapInfo?.ToString(); } } From 2a35c3c3e24708ef174f5482250d4de773ccb6d9 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 11 Aug 2019 18:04:54 +0300 Subject: [PATCH 2305/5608] Calculate real position for judgement lines --- osu.Game/Screens/Play/HUD/AccuracyBar.cs | 25 ++++++++++++++++++++---- osu.Game/Screens/Play/HUDOverlay.cs | 6 ++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/AccuracyBar.cs b/osu.Game/Screens/Play/HUD/AccuracyBar.cs index 3c13111b22..590e9ca4d9 100644 --- a/osu.Game/Screens/Play/HUD/AccuracyBar.cs +++ b/osu.Game/Screens/Play/HUD/AccuracyBar.cs @@ -9,6 +9,10 @@ using osuTK.Graphics; using osuTK; using osu.Framework.Graphics.Sprites; using System.Collections.Generic; +using osu.Game.Rulesets.Objects; +using osu.Game.Beatmaps; +using osu.Framework.Bindables; +using osu.Framework.Allocation; namespace osu.Game.Screens.Play.HUD { @@ -18,6 +22,11 @@ namespace osu.Game.Screens.Play.HUD private const int bar_height = 250; private const int spacing = 3; + public HitWindows HitWindows { get; set; } + + [Resolved] + private Bindable beatmap { get; set; } + private readonly bool mirrored; private readonly SpriteIcon arrow; private readonly List judgementOffsets = new List(); @@ -47,6 +56,12 @@ namespace osu.Game.Screens.Play.HUD }; } + protected override void LoadComplete() + { + base.LoadComplete(); + HitWindows.SetDifficulty(beatmap.Value.BeatmapInfo.BaseDifficulty.OverallDifficulty); + } + public void OnNewJudgement(JudgementResult judgement) { Container judgementLine; @@ -56,7 +71,7 @@ namespace osu.Game.Screens.Play.HUD judgementLine.FadeOut(5000, Easing.OutQuint); judgementLine.Expire(); - arrow.MoveToY(calculateArrowPosition(judgement) / bar_height, 500, Easing.OutQuint); + arrow.MoveToY(getRelativeJudgementPosition(calculateArrowPosition(judgement)), 500, Easing.OutQuint); } protected virtual Container CreateJudgementLine(JudgementResult judgement) => new CircularContainer @@ -66,7 +81,7 @@ namespace osu.Game.Screens.Play.HUD Masking = true, Size = new Vector2(10, 2), RelativePositionAxes = Axes.Y, - Y = (float)judgement.TimeOffset / bar_height, + Y = getRelativeJudgementPosition(judgement.TimeOffset), X = mirrored ? spacing : -spacing, Child = new Box { @@ -75,7 +90,9 @@ namespace osu.Game.Screens.Play.HUD } }; - private float calculateArrowPosition(JudgementResult judgement) + private float getRelativeJudgementPosition(double value) => (float)(value / HitWindows.Miss); + + private double calculateArrowPosition(JudgementResult judgement) { if (judgementOffsets.Count > 5) judgementOffsets.RemoveAt(0); @@ -87,7 +104,7 @@ namespace osu.Game.Screens.Play.HUD foreach (var offset in judgementOffsets) offsets += offset; - return (float)offsets / judgementOffsets.Count; + return offsets / judgementOffsets.Count; } } } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 3fafc21ea8..d30a32343a 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -277,10 +277,16 @@ namespace osu.Game.Screens.Play HealthDisplay?.Current.BindTo(processor.Health); if (LeftAccuracyBar != null) + { processor.NewJudgement += LeftAccuracyBar.OnNewJudgement; + LeftAccuracyBar.HitWindows = processor.CreateHitWindows(); + } if (RightAccuracyBar != null) + { processor.NewJudgement += RightAccuracyBar.OnNewJudgement; + RightAccuracyBar.HitWindows = processor.CreateHitWindows(); + } if (HealthDisplay is StandardHealthDisplay shd) processor.NewJudgement += shd.Flash; From 177a317a48b34d73643b946a90db01fe245e24c9 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 11 Aug 2019 18:11:49 +0300 Subject: [PATCH 2306/5608] rename AccuracyBar to HitErrorDisplay --- .../{AccuracyBar.cs => HitErrorDisplay.cs} | 4 ++-- osu.Game/Screens/Play/HUDOverlay.cs | 22 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) rename osu.Game/Screens/Play/HUD/{AccuracyBar.cs => HitErrorDisplay.cs} (97%) diff --git a/osu.Game/Screens/Play/HUD/AccuracyBar.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs similarity index 97% rename from osu.Game/Screens/Play/HUD/AccuracyBar.cs rename to osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 590e9ca4d9..2d33cb08a0 100644 --- a/osu.Game/Screens/Play/HUD/AccuracyBar.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -16,7 +16,7 @@ using osu.Framework.Allocation; namespace osu.Game.Screens.Play.HUD { - public class AccuracyBar : Container + public class HitErrorDisplay : Container { private const int bar_width = 5; private const int bar_height = 250; @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Play.HUD private readonly SpriteIcon arrow; private readonly List judgementOffsets = new List(); - public AccuracyBar(bool mirrored = false) + public HitErrorDisplay(bool mirrored = false) { this.mirrored = mirrored; diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index d30a32343a..a9a469486e 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -35,8 +35,8 @@ namespace osu.Game.Screens.Play public readonly ModDisplay ModDisplay; public readonly HoldForMenuButton HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; - public readonly AccuracyBar LeftAccuracyBar; - public readonly AccuracyBar RightAccuracyBar; + public readonly HitErrorDisplay LeftHitErrorDisplay; + public readonly HitErrorDisplay RightHitErrorDisplay; public Bindable ShowHealthbar = new Bindable(true); @@ -86,8 +86,8 @@ namespace osu.Game.Screens.Play HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), ModDisplay = CreateModsContainer(), - LeftAccuracyBar = CreateAccuracyBar(false), - RightAccuracyBar = CreateAccuracyBar(), + LeftHitErrorDisplay = CreateAccuracyBar(false), + RightHitErrorDisplay = CreateAccuracyBar(), } }, PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), @@ -260,7 +260,7 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20, Right = 10 }, }; - protected virtual AccuracyBar CreateAccuracyBar(bool mirrored = true) => new AccuracyBar(mirrored) + protected virtual HitErrorDisplay CreateAccuracyBar(bool mirrored = true) => new HitErrorDisplay(mirrored) { Anchor = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, Origin = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, @@ -276,16 +276,16 @@ namespace osu.Game.Screens.Play ComboCounter?.Current.BindTo(processor.Combo); HealthDisplay?.Current.BindTo(processor.Health); - if (LeftAccuracyBar != null) + if (LeftHitErrorDisplay != null) { - processor.NewJudgement += LeftAccuracyBar.OnNewJudgement; - LeftAccuracyBar.HitWindows = processor.CreateHitWindows(); + processor.NewJudgement += LeftHitErrorDisplay.OnNewJudgement; + LeftHitErrorDisplay.HitWindows = processor.CreateHitWindows(); } - if (RightAccuracyBar != null) + if (RightHitErrorDisplay != null) { - processor.NewJudgement += RightAccuracyBar.OnNewJudgement; - RightAccuracyBar.HitWindows = processor.CreateHitWindows(); + processor.NewJudgement += RightHitErrorDisplay.OnNewJudgement; + RightHitErrorDisplay.HitWindows = processor.CreateHitWindows(); } if (HealthDisplay is StandardHealthDisplay shd) From 5e0ac28ca88cecd41586c162d5d3b6862b11cfdd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 11 Aug 2019 18:30:03 +0300 Subject: [PATCH 2307/5608] Add basic colours --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 41 ++++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 2d33cb08a0..dba32d4ef8 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -13,12 +13,14 @@ using osu.Game.Rulesets.Objects; using osu.Game.Beatmaps; using osu.Framework.Bindables; using osu.Framework.Allocation; +using osu.Framework.Graphics.Colour; +using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Screens.Play.HUD { public class HitErrorDisplay : Container { - private const int bar_width = 5; + private const int bar_width = 4; private const int bar_height = 250; private const int spacing = 3; @@ -39,10 +41,43 @@ namespace osu.Game.Screens.Play.HUD Children = new Drawable[] { - new Box + new FillFlowContainer { RelativeSizeAxes = Axes.Both, - Colour = Color4.White, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0), Color4.Orange), + Height = 0.3f + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Green, + Height = 0.15f + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Blue, + Height = 0.1f + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Green, + Height = 0.15f + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.Orange, Color4.Black.Opacity(0)), + Height = 0.3f + } + } }, arrow = new SpriteIcon { From 3136d46c7f366c169413f6d3f64f135dbdb98ff2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 11 Aug 2019 19:04:56 +0300 Subject: [PATCH 2308/5608] Do not generate new judgement line on miss --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index dba32d4ef8..874a2cc088 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -99,6 +99,9 @@ namespace osu.Game.Screens.Play.HUD public void OnNewJudgement(JudgementResult judgement) { + if (!judgement.IsHit) + return; + Container judgementLine; Add(judgementLine = CreateJudgementLine(judgement)); From e7964c165f3c2c206dc404d23c7f3e6bcb4f5acd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 11 Aug 2019 19:09:50 +0300 Subject: [PATCH 2309/5608] Make judgement lines alive for a bit longer --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 874a2cc088..4cac73c975 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -106,7 +106,7 @@ namespace osu.Game.Screens.Play.HUD Add(judgementLine = CreateJudgementLine(judgement)); - judgementLine.FadeOut(5000, Easing.OutQuint); + judgementLine.FadeOut(10000, Easing.OutQuint); judgementLine.Expire(); arrow.MoveToY(getRelativeJudgementPosition(calculateArrowPosition(judgement)), 500, Easing.OutQuint); From ce62f6b56e76e13f7ca17891d37453514e3eb3e0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Aug 2019 01:40:11 +0900 Subject: [PATCH 2310/5608] ToString should never return null --- osu.Game/Beatmaps/Beatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 6079a112e6..a09a1bb9cb 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -61,6 +61,6 @@ namespace osu.Game.Beatmaps { public new Beatmap Clone() => (Beatmap)base.Clone(); - public override string ToString() => BeatmapInfo?.ToString(); + public override string ToString() => BeatmapInfo?.ToString() ?? base.ToString(); } } From ff4b271f64c508227f8d70c4301046afad16f2e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Aug 2019 01:42:05 +0900 Subject: [PATCH 2311/5608] Add extra quotations around output --- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index d6d6804d16..9a8197ad82 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -36,7 +36,7 @@ namespace osu.Game.Beatmaps.Formats { if (!Enum.TryParse(line.Substring(1, line.Length - 2), out section)) { - Logger.Log($"Unknown section \"{line}\" in {output}"); + Logger.Log($"Unknown section \"{line}\" in \"{output}\""); section = Section.None; } @@ -49,7 +49,7 @@ namespace osu.Game.Beatmaps.Formats } catch (Exception e) { - Logger.Log($"Failed to process line \"{line}\" into {output}: {e.Message}", LoggingTarget.Runtime, LogLevel.Important); + Logger.Log($"Failed to process line \"{line}\" into \"{output}\": {e.Message}", LoggingTarget.Runtime, LogLevel.Important); } } } From 359261d4a47353221ac5ca15f86b71f7253a8087 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Aug 2019 02:04:06 +0900 Subject: [PATCH 2312/5608] Fix game not starting if intro music is disabled --- osu.Game/Screens/Menu/IntroTriangles.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index 87d6012205..ba0d624959 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.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; @@ -104,14 +104,14 @@ namespace osu.Game.Screens.Menu LoadComponentAsync(new TrianglesIntroSequence(logo, background) { RelativeSizeAxes = Axes.Both, - Clock = new FramedClock(track), + Clock = new FramedClock(menuMusic.Value ? track : null), LoadMenu = LoadMenu }, t => { AddInternal(t); welcome?.Play(); - // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu. + // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Menu. if (menuMusic.Value) track.Start(); }); From e4eed83d85bec2274d40c14d4965cde6f3743def Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 11 Aug 2019 19:14:49 +0200 Subject: [PATCH 2313/5608] Add dual bindings for Jukebox hotkeys --- .../Input/Bindings/GlobalActionContainer.cs | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 809ec9a09e..b2cbb77087 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -46,8 +46,11 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.KeypadEnter, GlobalAction.Select), new KeyBinding(InputKey.TrackPrevious, GlobalAction.MusicPrev), + new KeyBinding(InputKey.F1, GlobalAction.MusicPrev), new KeyBinding(InputKey.TrackNext, GlobalAction.MusicNext), + new KeyBinding(InputKey.F5, GlobalAction.MusicNext), new KeyBinding(InputKey.PlayPause, GlobalAction.MusicPlay), + new KeyBinding(InputKey.F3, GlobalAction.MusicPlay) }; public IEnumerable InGameKeyBindings => new[] @@ -92,16 +95,6 @@ namespace osu.Game.Input.Bindings [Description("Toggle mute")] ToggleMute, - // Game-wide beatmap jukebox keybindings - [Description("Jukebox next track")] - MusicNext, - - [Description("Jukebox previous track")] - MusicPrev, - - [Description("Jukebox play / pause current track")] - MusicPlay, - // In-Game Keybindings [Description("Skip cutscene")] SkipCutscene, @@ -129,5 +122,15 @@ namespace osu.Game.Input.Bindings [Description("Quick exit (Hold)")] QuickExit, + + // Game-wide beatmap jukebox keybindings + [Description("Jukebox next track")] + MusicNext, + + [Description("Jukebox previous track")] + MusicPrev, + + [Description("Jukebox play / pause current track")] + MusicPlay, } } From bc32726f3caee2c95c3111095f4b089e0326fc64 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 11 Aug 2019 23:08:14 +0300 Subject: [PATCH 2314/5608] Apply renaming suggestions Co-Authored-By: Dean Herbert --- osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index bffee7f1f7..813ca904ca 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -149,7 +149,7 @@ namespace osu.Game.Tests.Visual.Background } /// - /// Check if the is properly accepting user-defined visual changes in background at all. + /// Ensure is properly accepting user-defined visual changes for a background. /// [Test] public void DisableUserDimBackgroundTest() @@ -166,7 +166,7 @@ namespace osu.Game.Tests.Visual.Background } /// - /// Check if the is properly accepting user-defined visual changes in storyboard at all. + /// Ensure is properly accepting user-defined visual changes for a storyboard. /// [Test] public void DisableUserDimStoryboardTest() From fe20e1924352fcfea0918e14f55b0c43b6038ffd Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 11 Aug 2019 23:19:22 +0300 Subject: [PATCH 2315/5608] Rename toggling steps --- .../Visual/Background/TestSceneUserDimContainer.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index 813ca904ca..3061a3a542 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -119,14 +119,14 @@ namespace osu.Game.Tests.Visual.Background { performFullSetup(); createFakeStoryboard(); - AddStep("Storyboard Enabled", () => + AddStep("Enable Storyboard", () => { player.ReplacesBackground.Value = true; player.StoryboardEnabled.Value = true; }); waitForDim(); AddAssert("Background is invisible, storyboard is visible", () => songSelect.IsBackgroundInvisible() && player.IsStoryboardVisible); - AddStep("Storyboard Disabled", () => + AddStep("Disable Storyboard", () => { player.ReplacesBackground.Value = false; player.StoryboardEnabled.Value = false; @@ -157,10 +157,10 @@ namespace osu.Game.Tests.Visual.Background performFullSetup(); waitForDim(); AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied()); - AddStep("EnableUserDim disabled", () => songSelect.DimEnabled.Value = false); + AddStep("Enable user dim", () => songSelect.DimEnabled.Value = false); waitForDim(); AddAssert("Screen is undimmed and user blur removed", () => songSelect.IsBackgroundUndimmed() && songSelect.IsUserBlurDisabled()); - AddStep("EnableUserDim enabled", () => songSelect.DimEnabled.Value = true); + AddStep("Disable user dim", () => songSelect.DimEnabled.Value = true); waitForDim(); AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied()); } @@ -173,16 +173,16 @@ namespace osu.Game.Tests.Visual.Background { performFullSetup(); createFakeStoryboard(); - AddStep("Storyboard Enabled", () => + AddStep("Enable Storyboard", () => { player.ReplacesBackground.Value = true; player.StoryboardEnabled.Value = true; }); - AddStep("EnableUserDim enabled", () => player.DimmableStoryboard.EnableUserDim.Value = true); + AddStep("Enable user dim", () => player.DimmableStoryboard.EnableUserDim.Value = true); AddStep("Set dim level to 1", () => songSelect.DimLevel.Value = 1f); waitForDim(); AddAssert("Storyboard is invisible", () => !player.IsStoryboardVisible); - AddStep("EnableUserDim disabled", () => player.DimmableStoryboard.EnableUserDim.Value = false); + AddStep("Disable user dim", () => player.DimmableStoryboard.EnableUserDim.Value = false); waitForDim(); AddAssert("Storyboard is visible", () => player.IsStoryboardVisible); } From 45b4fc9201849483d0d08ec770c6c5b89d413d6a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Aug 2019 15:00:32 +0900 Subject: [PATCH 2316/5608] Add xmldoc --- osu.Game.Rulesets.Osu/OsuInputManager.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index 58e275ba26..cdea7276f3 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -18,6 +18,10 @@ namespace osu.Game.Rulesets.Osu set => ((OsuKeyBindingContainer)KeyBindingContainer).AllowUserPresses = value; } + /// + /// Whether the user's cursor movement events should be accepted. + /// Can be used to block only movement while still accepting button input. + /// public bool AllowUserCursorMovement { get; set; } = true; protected override RulesetKeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) From 707911acac196e5c97ce6d6f5b95a0dbeb3dcdbc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Aug 2019 15:05:27 +0900 Subject: [PATCH 2317/5608] Tidy up code formatting / variable naming --- osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs index 1853b0228f..ca72f18e9c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs @@ -29,19 +29,21 @@ namespace osu.Game.Rulesets.Osu.Mods private OsuInputManager inputManager; private List replayFrames; - private int frameIndex; + + private int currentFrame; public void Update(Playfield playfield) { - // If we are on the last replay frame, no need to do anything - if (frameIndex == replayFrames.Count - 1) return; + if (currentFrame == replayFrames.Count - 1) return; - // Check if we are closer to the next replay frame then the current one - if (Math.Abs(replayFrames[frameIndex].Time - playfield.Time.Current) >= Math.Abs(replayFrames[frameIndex + 1].Time - playfield.Time.Current)) + double time = playfield.Time.Current; + + // Very naive implementation of autopilot based on proximity to replay frames. + // TODO: this needs to be based on user interactions to better match stable (pausing until judgement is registered). + if (Math.Abs(replayFrames[currentFrame + 1].Time - time) <= Math.Abs(replayFrames[currentFrame].Time - time)) { - // If we are, move to the next frame, and update the mouse position - frameIndex++; - new MousePositionAbsoluteInput { Position = playfield.ToScreenSpace(replayFrames[frameIndex].Position) }.Apply(inputManager.CurrentState, inputManager); + currentFrame++; + new MousePositionAbsoluteInput { Position = playfield.ToScreenSpace(replayFrames[currentFrame].Position) }.Apply(inputManager.CurrentState, inputManager); } // TODO: Implement the functionality to automatically spin spinners From 520924b440c0a642597d25d58d24efbcd705ff3a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 09:45:21 +0300 Subject: [PATCH 2318/5608] Don't create a new request if onlineId is null --- .../Screens/Multi/Match/Components/MatchBeatmapPanel.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs index f73059d069..397f158f2b 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs @@ -40,15 +40,15 @@ namespace osu.Game.Screens.Multi.Match.Components panel = null; } - var onlineId = item.NewValue?.Beatmap.OnlineBeatmapID ?? 0; + var onlineId = item.NewValue?.Beatmap.OnlineBeatmapID; - if (onlineId != 0) + if (onlineId.HasValue) { - request = new GetBeatmapSetRequest(onlineId, BeatmapSetLookupType.BeatmapId); + request = new GetBeatmapSetRequest(onlineId.Value, BeatmapSetLookupType.BeatmapId); request.Success += beatmap => { panel = new DirectGridPanel(beatmap.ToBeatmapSet(rulesets)); - LoadComponentAsync(panel, p => { AddInternal(panel); }); + LoadComponentAsync(panel, p => { AddInternal(p); }); }; api.Queue(request); } From 5b68a2f34a2acc1abe91bbb65197e8dcde93ff0d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 09:50:49 +0300 Subject: [PATCH 2319/5608] Rename trackManager to previewTrackManager --- .../Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs | 4 ++-- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs index db2b61cdd9..f148170847 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.Multiplayer }; [Resolved] - private PreviewTrackManager trackManager { get; set; } + private PreviewTrackManager previewTrackManager { get; set; } public TestSceneMatchBeatmapPanel() { @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("Select random beatmap", () => { Room.CurrentItem.Value = Room.Playlist[RNG.Next(Room.Playlist.Count)]; - trackManager.StopAnyPlaying(this); + previewTrackManager.StopAnyPlaying(this); }); } diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index c89c32759d..8d79b21b16 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Multi.Match private BeatmapManager beatmapManager { get; set; } [Resolved] - private PreviewTrackManager trackManager { get; set; } + private PreviewTrackManager previewTrackManager { get; set; } [Resolved(CanBeNull = true)] private OsuGame game { get; set; } @@ -188,7 +188,7 @@ namespace osu.Game.Screens.Multi.Match Mods.Value = Array.Empty(); - trackManager.StopAnyPlaying(this); + previewTrackManager.StopAnyPlaying(this); return base.OnExiting(next); } @@ -207,7 +207,7 @@ namespace osu.Game.Screens.Multi.Match if (e.NewValue?.Ruleset != null) Ruleset.Value = e.NewValue.Ruleset; - trackManager.StopAnyPlaying(this); + previewTrackManager.StopAnyPlaying(this); } /// @@ -233,7 +233,7 @@ namespace osu.Game.Screens.Multi.Match private void onStart() { - trackManager.StopAnyPlaying(this); + previewTrackManager.StopAnyPlaying(this); switch (type.Value) { From cb910a651881819595c639c542af9c1f8686c6c2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 10:02:45 +0300 Subject: [PATCH 2320/5608] Replace if/else statement --- .../Screens/Multi/Match/MatchSubScreen.cs | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 8d79b21b16..dafea70092 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -150,20 +150,12 @@ namespace osu.Game.Screens.Multi.Match { const float fade_duration = 500; - if (tab.NewValue is SettingsMatchPage) - { - header.ShowBeatmapPanel.Value = false; - settings.Show(); - info.FadeOut(fade_duration, Easing.OutQuint); - bottomRow.FadeOut(fade_duration, Easing.OutQuint); - } - else - { - header.ShowBeatmapPanel.Value = true; - settings.Hide(); - info.FadeIn(fade_duration, Easing.OutQuint); - bottomRow.FadeIn(fade_duration, Easing.OutQuint); - } + var settingsDisplayed = tab.NewValue is SettingsMatchPage; + + header.ShowBeatmapPanel.Value = !settingsDisplayed; + settings.State.Value = settingsDisplayed ? Visibility.Visible : Visibility.Hidden; + info.FadeTo(settingsDisplayed ? 0 : 1, fade_duration, Easing.OutQuint); + bottomRow.FadeTo(settingsDisplayed ? 0 : 1, fade_duration, Easing.OutQuint); }, true); chat.Exit += () => From 75cb0d093b59cf74b50a328f7331158be5f6feca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Aug 2019 16:10:25 +0900 Subject: [PATCH 2321/5608] Use description correctly Required for localisation --- osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs | 2 +- .../Select/Leaderboards/BeatmapLeaderboardScope.cs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index c74c7cbc2b..7eb9b1829c 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -69,7 +69,7 @@ namespace osu.Game.Overlays.BeatmapSet Margin = new MarginPadding { Bottom = 8 }, Origin = Anchor.BottomCentre, Anchor = Anchor.BottomCentre, - Text = value.GetDescription() + " Ranking", + Text = value.GetDescription(), Font = OsuFont.GetFont(weight: FontWeight.Regular), }, box = new Box diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs index 9e480b61c6..dc4c2ba4e2 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs @@ -1,13 +1,22 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.ComponentModel; + namespace osu.Game.Screens.Select.Leaderboards { public enum BeatmapLeaderboardScope { + [Description("Local Ranking")] Local, + + [Description("Country Ranking")] Country, + + [Description("Global Ranking")] Global, + + [Description("Friend Ranking")] Friend, } } From 982066dfdfe2bf2356ff1d7acfc5c0827d0894cd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 10:38:34 +0300 Subject: [PATCH 2322/5608] Convert to method group --- osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs index 397f158f2b..7939b18e97 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs @@ -48,7 +48,7 @@ namespace osu.Game.Screens.Multi.Match.Components request.Success += beatmap => { panel = new DirectGridPanel(beatmap.ToBeatmapSet(rulesets)); - LoadComponentAsync(panel, p => { AddInternal(p); }); + LoadComponentAsync(panel, AddInternal); }; api.Queue(request); } From 1bbd0ca54e0bcb4ab90b40cbaa0b533223bf043f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2019 08:30:26 +0000 Subject: [PATCH 2323/5608] Bump ppy.osu.Game.Resources from 2019.731.1 to 2019.809.0 Bumps [ppy.osu.Game.Resources](https://github.com/ppy/osu-resources) from 2019.731.1 to 2019.809.0. - [Release notes](https://github.com/ppy/osu-resources/releases) - [Commits](https://github.com/ppy/osu-resources/compare/2019.731.1...2019.809.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 3b2e6574ac..721d341c08 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,7 +62,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 1dd19ac7ed..b5266fd75d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 1c3faeed39..103d89cadc 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -104,7 +104,7 @@ - + From 9c15024014d9e196e97a9dee1e817c30993080af Mon Sep 17 00:00:00 2001 From: Lucas A Date: Mon, 12 Aug 2019 10:53:06 +0200 Subject: [PATCH 2324/5608] Reword and add missing xmldoc to OnScreenDisplay --- osu.Game/Overlays/OnScreenDisplay.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index a30ce5c56f..a92320945e 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -16,6 +16,10 @@ using osu.Game.Overlays.OSD; namespace osu.Game.Overlays { + /// + /// An on-screen display which automatically tracks and displays toast notifications for . + /// Can also display custom content via + /// public class OnScreenDisplay : Container { private readonly Container box; @@ -97,7 +101,7 @@ namespace osu.Game.Overlays } /// - /// Displays the given as parameter on the OSD + /// Displays the provided temporarily. /// /// public void Display(Toast toast) From 144d41f143fb429a848591ecb77bce3d548b64c9 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 12:33:01 +0300 Subject: [PATCH 2325/5608] Add ability to not add all the items if enum --- osu.Game/Graphics/UserInterface/OsuTabControl.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 11f41b1a48..1bb37560b2 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -31,6 +31,8 @@ namespace osu.Game.Graphics.UserInterface protected virtual float StripWidth() => TabContainer.Children.Sum(c => c.IsPresent ? c.DrawWidth + TabContainer.Spacing.X : 0) - TabContainer.Spacing.X; protected virtual float StripHeight() => 1; + protected virtual bool AddAllItemsIfEnum => true; + private static bool isEnumType => typeof(T).IsEnum; public OsuTabControl() @@ -45,7 +47,7 @@ namespace osu.Game.Graphics.UserInterface Colour = Color4.White.Opacity(0), }); - if (isEnumType) + if (isEnumType && AddAllItemsIfEnum) foreach (var val in (T[])Enum.GetValues(typeof(T))) AddItem(val); } From fc521ac93b3727bc69c3dbebdb94ee53085be1eb Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 13:08:15 +0300 Subject: [PATCH 2326/5608] Expose BoxColour property --- osu.Game/Graphics/UserInterface/PageTabControl.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/PageTabControl.cs b/osu.Game/Graphics/UserInterface/PageTabControl.cs index 156a556b5e..f8d1c7502a 100644 --- a/osu.Game/Graphics/UserInterface/PageTabControl.cs +++ b/osu.Game/Graphics/UserInterface/PageTabControl.cs @@ -32,6 +32,12 @@ namespace osu.Game.Graphics.UserInterface protected readonly SpriteText Text; + protected Color4 BoxColour + { + get => box.Colour; + set => box.Colour = value; + } + public PageTabItem(T value) : base(value) { @@ -66,7 +72,7 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(OsuColour colours) { - box.Colour = colours.Yellow; + BoxColour = colours.Yellow; } protected override bool OnHover(HoverEvent e) From 6533f114d42762d30e98a06770033fdfae247b8b Mon Sep 17 00:00:00 2001 From: Lucas A Date: Mon, 12 Aug 2019 12:09:09 +0200 Subject: [PATCH 2327/5608] Apply review suggestions --- .../UserInterface/TestSceneOnScreenDisplay.cs | 14 ++++++++++++++ osu.Game/Overlays/OSD/Toast.cs | 14 +++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs index 4decfc7dd6..558c027e1d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs @@ -24,6 +24,11 @@ namespace osu.Game.Tests.Visual.UserInterface Add(osd); AddStep("Display empty osd toast", () => osd.Display(new EmptyToast())); + AddAssert("Toast width is 240", () => osd.Child.Width == 240); + + AddStep("Display toast with lengthy text", () => osd.Display(new LengthyToast())); + AddAssert("Toast width is greater than 240", () => osd.Child.Width > 240); + AddRepeatStep("Change toggle (no bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingNoKeybind), 2); AddRepeatStep("Change toggle (with bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingWithKeybind), 2); AddRepeatStep("Change enum (no bind)", () => config.IncrementEnumSetting(TestConfigSetting.EnumSettingNoKeybind), 3); @@ -96,6 +101,15 @@ namespace osu.Game.Tests.Visual.UserInterface } } + private class LengthyToast : Toast + { + public LengthyToast() + : base("Toast with a very very very long text", "A very very very very very very long text also", "A very very very very very long shortcut") + { + + } + } + private class TestOnScreenDisplay : OnScreenDisplay { protected override void DisplayTemporarily(Drawable toDisplay) => toDisplay.FadeIn().ResizeHeightTo(110); diff --git a/osu.Game/Overlays/OSD/Toast.cs b/osu.Game/Overlays/OSD/Toast.cs index db5e6e4a6a..46c53ec409 100644 --- a/osu.Game/Overlays/OSD/Toast.cs +++ b/osu.Game/Overlays/OSD/Toast.cs @@ -13,22 +13,30 @@ namespace osu.Game.Overlays.OSD { public abstract class Toast : Container { + private const int toast_minimum_width = 240; + private readonly Container content; protected override Container Content => content; protected readonly OsuSpriteText ValueText; - protected Toast(string description, string value, string keybinding) + protected Toast(string description, string value, string shortcut) { Anchor = Anchor.Centre; Origin = Anchor.Centre; - Width = 240; // A toast's height is decided (and transformed) by the containing OnScreenDisplay. RelativeSizeAxes = Axes.Y; + AutoSizeAxes = Axes.X; InternalChildren = new Drawable[] { + new Container //this container exists just to set a minimum width for the toast + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = toast_minimum_width + }, new Box { RelativeSizeAxes = Axes.Both, @@ -68,7 +76,7 @@ namespace osu.Game.Overlays.OSD Alpha = 0.3f, Margin = new MarginPadding { Bottom = 15 }, Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), - Text = string.IsNullOrEmpty(keybinding) ? "NO KEY BOUND" : keybinding.ToUpperInvariant() + Text = string.IsNullOrEmpty(shortcut) ? "NO KEY BOUND" : shortcut.ToUpperInvariant() }, }; } From 5e49d0fb28e704a5c53f34ce1358a20173269cdb Mon Sep 17 00:00:00 2001 From: Lucas A Date: Mon, 12 Aug 2019 12:11:01 +0200 Subject: [PATCH 2328/5608] Fix CI issues --- osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs index 558c027e1d..45720548c8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs @@ -106,7 +106,6 @@ namespace osu.Game.Tests.Visual.UserInterface public LengthyToast() : base("Toast with a very very very long text", "A very very very very very very long text also", "A very very very very very long shortcut") { - } } From ba49a4c2da7d0791c53ac49955a41114acfa3a88 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 13:16:57 +0300 Subject: [PATCH 2329/5608] Use existing PageTabControl for layout --- .../BeatmapSet/LeaderboardScopeSelector.cs | 63 ++++--------------- 1 file changed, 12 insertions(+), 51 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index 7eb9b1829c..f54509ff77 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -8,25 +8,24 @@ using osu.Framework.Graphics.Containers; using osuTK; using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics.Sprites; -using osu.Framework.Extensions; using osu.Game.Graphics; using osu.Framework.Allocation; using osuTK.Graphics; -using osu.Framework.Input.Events; using osu.Framework.Graphics.Colour; +using osu.Framework.Input.Events; namespace osu.Game.Overlays.BeatmapSet { - public class LeaderboardScopeSelector : TabControl + public class LeaderboardScopeSelector : PageTabControl { + protected override bool AddAllItemsIfEnum => false; + protected override Dropdown CreateDropdown() => null; protected override TabItem CreateTabItem(BeatmapLeaderboardScope value) => new ScopeSelectorTabItem(value); public LeaderboardScopeSelector() { - AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; AddItem(BeatmapLeaderboardScope.Global); @@ -42,57 +41,31 @@ namespace osu.Game.Overlays.BeatmapSet protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - AutoSizeAxes = Axes.Both, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, Direction = FillDirection.Horizontal, Spacing = new Vector2(20, 0), }; - private class ScopeSelectorTabItem : TabItem + private class ScopeSelectorTabItem : PageTabItem { - private const float transition_duration = 100; - - private readonly Box box; - - protected readonly OsuSpriteText Text; - public ScopeSelectorTabItem(BeatmapLeaderboardScope value) : base(value) { - AutoSizeAxes = Axes.Both; - - Children = new Drawable[] - { - Text = new OsuSpriteText - { - Margin = new MarginPadding { Bottom = 8 }, - Origin = Anchor.BottomCentre, - Anchor = Anchor.BottomCentre, - Text = value.GetDescription(), - Font = OsuFont.GetFont(weight: FontWeight.Regular), - }, - box = new Box - { - RelativeSizeAxes = Axes.X, - Height = 5, - Scale = new Vector2(1f, 0f), - Origin = Anchor.BottomCentre, - Anchor = Anchor.BottomCentre, - }, - new HoverClickSounds() - }; + Text.Font = OsuFont.GetFont(size: 16); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - box.Colour = colours.Blue; + BoxColour = colours.Blue; } protected override bool OnHover(HoverEvent e) { - Text.FadeColour(Color4.LightSkyBlue); + Text.FadeColour(BoxColour); return base.OnHover(e); } @@ -103,18 +76,6 @@ namespace osu.Game.Overlays.BeatmapSet Text.FadeColour(Color4.White); } - - protected override void OnActivated() - { - box.ScaleTo(new Vector2(1f), transition_duration); - Text.Font = Text.Font.With(weight: FontWeight.Black); - } - - protected override void OnDeactivated() - { - box.ScaleTo(new Vector2(1f, 0f), transition_duration); - Text.Font = Text.Font.With(weight: FontWeight.Regular); - } } private class Line : GridContainer From 9c36cb4af4f60a8675640471a99adf65968ea7dd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 14:33:30 +0300 Subject: [PATCH 2330/5608] Use existing AccentColour logic instead of weird BoxColour --- .../Graphics/UserInterface/PageTabControl.cs | 26 ++++++++++++------- .../BeatmapSet/LeaderboardScopeSelector.cs | 14 +++++----- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PageTabControl.cs b/osu.Game/Graphics/UserInterface/PageTabControl.cs index f8d1c7502a..a0d3745180 100644 --- a/osu.Game/Graphics/UserInterface/PageTabControl.cs +++ b/osu.Game/Graphics/UserInterface/PageTabControl.cs @@ -24,7 +24,13 @@ namespace osu.Game.Graphics.UserInterface Height = 30; } - public class PageTabItem : TabItem + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AccentColour = colours.Yellow; + } + + public class PageTabItem : TabItem, IHasAccentColour { private const float transition_duration = 100; @@ -32,10 +38,16 @@ namespace osu.Game.Graphics.UserInterface protected readonly SpriteText Text; - protected Color4 BoxColour + private Color4 accentColour; + + public Color4 AccentColour { - get => box.Colour; - set => box.Colour = value; + get => accentColour; + set + { + accentColour = value; + box.Colour = accentColour; + } } public PageTabItem(T value) @@ -69,12 +81,6 @@ namespace osu.Game.Graphics.UserInterface Active.BindValueChanged(active => Text.Font = Text.Font.With(Typeface.Exo, weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium), true); } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - BoxColour = colours.Yellow; - } - protected override bool OnHover(HoverEvent e) { if (!Active.Value) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index f54509ff77..c867cc3780 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -39,6 +39,12 @@ namespace osu.Game.Overlays.BeatmapSet }); } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AccentColour = colours.Blue; + } + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer { Anchor = Anchor.BottomCentre, @@ -57,15 +63,9 @@ namespace osu.Game.Overlays.BeatmapSet Text.Font = OsuFont.GetFont(size: 16); } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - BoxColour = colours.Blue; - } - protected override bool OnHover(HoverEvent e) { - Text.FadeColour(BoxColour); + Text.FadeColour(AccentColour); return base.OnHover(e); } From 0070f6b26072b391e3989eb880261bc632ce41fb Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 14:49:08 +0300 Subject: [PATCH 2331/5608] Use CompositeDrawable as a parent class --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 99c51813c5..399cd4a49a 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -19,7 +19,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet { - public class LeaderboardModSelector : Container + public class LeaderboardModSelector : CompositeDrawable { public readonly Bindable> SelectedMods = new Bindable>(); public readonly Bindable Ruleset = new Bindable(); @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.BeatmapSet { AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; - Child = modsContainer = new FillFlowContainer + InternalChild = modsContainer = new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 21af39032749fdb8da92fd773a5063f03ab955c6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 14:57:16 +0300 Subject: [PATCH 2332/5608] Move binding to LoadComplete --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 399cd4a49a..99c1b54467 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -38,8 +38,12 @@ namespace osu.Game.Overlays.BeatmapSet Direction = FillDirection.Full, Spacing = new Vector2(4), }; + } - Ruleset.BindValueChanged(onRulesetChanged); + protected override void LoadComplete() + { + base.LoadComplete(); + Ruleset.BindValueChanged(onRulesetChanged, true); } private void onRulesetChanged(ValueChangedEvent ruleset) From 62a91e4aaab46c458152233ef4208278dc635e4b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 15:20:21 +0300 Subject: [PATCH 2333/5608] Add the ability to override Highlighted action to the ModIcon --- .../Overlays/BeatmapSet/LeaderboardModSelector.cs | 14 ++++++++++++-- osu.Game/Rulesets/UI/ModIcon.cs | 13 +++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 99c1b54467..03d2e6ce4b 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -92,11 +92,16 @@ namespace osu.Game.Overlays.BeatmapSet { Scale = new Vector2(mod_scale); Add(new HoverClickSounds()); + } + + protected override void LoadComplete() + { + base.LoadComplete(); Selected.BindValueChanged(selected => { updateState(); - OnSelectionChanged?.Invoke(mod, selected.NewValue); + OnSelectionChanged?.Invoke(Mod, selected.NewValue); }, true); } @@ -120,7 +125,12 @@ namespace osu.Game.Overlays.BeatmapSet private void updateState() { - this.FadeColour(IsHovered || Selected.Value ? Color4.White : Color4.Gray, duration, Easing.OutQuint); + Highlighted.Value = (IsHovered || Selected.Value) ? true : false; + } + + protected override void OnHighlightedChange(ValueChangedEvent highlighted) + { + this.FadeColour(highlighted.NewValue ? Color4.White : Color4.Gray, duration, Easing.OutQuint); } } diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 962263adba..e713216f35 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -34,9 +34,11 @@ namespace osu.Game.Rulesets.UI public virtual string TooltipText { get; } + protected Mod Mod { get; private set; } + public ModIcon(Mod mod) { - if (mod == null) throw new ArgumentNullException(nameof(mod)); + Mod = mod ?? throw new ArgumentNullException(nameof(mod)); type = mod.Type; @@ -106,12 +108,19 @@ namespace osu.Game.Rulesets.UI modIcon.Colour = colours.Yellow; break; } + + background.Colour = backgroundColour; } protected override void LoadComplete() { base.LoadComplete(); - Highlighted.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); + Highlighted.BindValueChanged(OnHighlightedChange, true); + } + + protected virtual void OnHighlightedChange(ValueChangedEvent highlighted) + { + background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour; } } } From b71c776e65c291df39a45a175bc8301d6e3661d7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 16:20:36 +0300 Subject: [PATCH 2334/5608] Add web-like hover behavior --- .../BeatmapSet/LeaderboardModSelector.cs | 39 +++++++++++++++++-- osu.Game/Rulesets/UI/ModIcon.cs | 2 +- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 03d2e6ce4b..1e10c41478 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -57,12 +57,13 @@ namespace osu.Game.Overlays.BeatmapSet modsContainer.Add(new ModButton(new NoMod())); - foreach (var mod in ruleset.NewValue.CreateInstance().GetAllMods()) + ruleset.NewValue.CreateInstance().GetAllMods().ForEach(mod => + { if (mod.Ranked) modsContainer.Add(new ModButton(mod)); + }); - foreach (var mod in modsContainer) - mod.OnSelectionChanged += selectionChanged; + modsContainer.ForEach(button => button.OnSelectionChanged += selectionChanged); } private void selectionChanged(Mod mod, bool selected) @@ -74,11 +75,39 @@ namespace osu.Game.Overlays.BeatmapSet else mods.Remove(mod); + if (!mods.Any() && !IsHovered) + modsContainer.ForEach(button => button.Highlighted.Value = true); + SelectedMods.Value = mods; } + protected override bool OnHover(HoverEvent e) + { + if (!SelectedMods.Value.Any()) + dehighlightAll(); + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + if (!SelectedMods.Value.Any()) + modsContainer.ForEach(mod => mod.Highlighted.Value = true); + } + public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); + private void dehighlightAll() + { + modsContainer.ForEach(button => + { + if (!button.IsHovered) + button.Highlighted.Value = false; + }); + } + private class ModButton : ModIcon { private const float mod_scale = 0.4f; @@ -98,11 +127,13 @@ namespace osu.Game.Overlays.BeatmapSet { base.LoadComplete(); + Highlighted.Value = true; + Selected.BindValueChanged(selected => { updateState(); OnSelectionChanged?.Invoke(Mod, selected.NewValue); - }, true); + }); } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index e713216f35..1bcd2dc780 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -115,7 +115,7 @@ namespace osu.Game.Rulesets.UI protected override void LoadComplete() { base.LoadComplete(); - Highlighted.BindValueChanged(OnHighlightedChange, true); + Highlighted.BindValueChanged(OnHighlightedChange); } protected virtual void OnHighlightedChange(ValueChangedEvent highlighted) From 86c9d5251faea12d24347dc68ae1c94ea3c738db Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 16:28:53 +0300 Subject: [PATCH 2335/5608] Remove unused function --- .../Overlays/BeatmapSet/LeaderboardModSelector.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 1e10c41478..fffbc400b1 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -84,7 +84,11 @@ namespace osu.Game.Overlays.BeatmapSet protected override bool OnHover(HoverEvent e) { if (!SelectedMods.Value.Any()) - dehighlightAll(); + modsContainer.ForEach(button => + { + if (!button.IsHovered) + button.Highlighted.Value = false; + }); return base.OnHover(e); } @@ -99,15 +103,6 @@ namespace osu.Game.Overlays.BeatmapSet public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); - private void dehighlightAll() - { - modsContainer.ForEach(button => - { - if (!button.IsHovered) - button.Highlighted.Value = false; - }); - } - private class ModButton : ModIcon { private const float mod_scale = 0.4f; From cf92d6b1b01174666b484580242ad99891a839e0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 16:32:04 +0300 Subject: [PATCH 2336/5608] Add highlightAll function to avoid duplication --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index fffbc400b1..1489907589 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -76,7 +76,7 @@ namespace osu.Game.Overlays.BeatmapSet mods.Remove(mod); if (!mods.Any() && !IsHovered) - modsContainer.ForEach(button => button.Highlighted.Value = true); + highlightAll(); SelectedMods.Value = mods; } @@ -98,11 +98,13 @@ namespace osu.Game.Overlays.BeatmapSet base.OnHoverLost(e); if (!SelectedMods.Value.Any()) - modsContainer.ForEach(mod => mod.Highlighted.Value = true); + highlightAll(); } public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); + private void highlightAll() => modsContainer.ForEach(mod => mod.Highlighted.Value = true); + private class ModButton : ModIcon { private const float mod_scale = 0.4f; From 883102ee5d912b503db9ea9a9e7e162657023b40 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 12 Aug 2019 16:40:52 +0300 Subject: [PATCH 2337/5608] Move score multiplier logic inside score calculation --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ba2375bec1..c8858233aa 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -398,7 +398,7 @@ namespace osu.Game.Rulesets.Scoring if (rollingMaxBaseScore != 0) Accuracy.Value = baseScore / rollingMaxBaseScore; - TotalScore.Value = getScore(Mode.Value) * scoreMultiplier; + TotalScore.Value = getScore(Mode.Value); } private double getScore(ScoringMode mode) @@ -407,11 +407,11 @@ namespace osu.Game.Rulesets.Scoring { default: case ScoringMode.Standardised: - return max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo.Value / maxHighestCombo) + bonusScore; + return (max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo.Value / maxHighestCombo) + bonusScore) * scoreMultiplier; case ScoringMode.Classic: // should emulate osu-stable's scoring as closely as we can (https://osu.ppy.sh/help/wiki/Score/ScoreV1) - return bonusScore + baseScore * (1 + Math.Max(0, HighestCombo.Value - 1) / 25); + return bonusScore + baseScore * ((1 + Math.Max(0, HighestCombo.Value - 1) * scoreMultiplier) / 25); } } From 1bfb87fcdd01536874269a16ffcf13d6e7ffcc7c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 16:41:35 +0300 Subject: [PATCH 2338/5608] Remove redundant conditional ternary expression --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 1489907589..66d78f927a 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -28,8 +28,7 @@ namespace osu.Game.Overlays.BeatmapSet public LeaderboardModSelector() { - AutoSizeAxes = Axes.Y; - RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Both; InternalChild = modsContainer = new FillFlowContainer { Anchor = Anchor.Centre, @@ -151,10 +150,7 @@ namespace osu.Game.Overlays.BeatmapSet updateState(); } - private void updateState() - { - Highlighted.Value = (IsHovered || Selected.Value) ? true : false; - } + private void updateState() => Highlighted.Value = IsHovered || Selected.Value; protected override void OnHighlightedChange(ValueChangedEvent highlighted) { From c0f0fbbaa93927fb5c520182e0ece74eaaff5e09 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 00:14:37 +0900 Subject: [PATCH 2339/5608] Rename variable and add xmldoc --- osu.Game/Graphics/UserInterface/OsuTabControl.cs | 7 +++++-- osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 1bb37560b2..c55d14456b 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -31,7 +31,10 @@ namespace osu.Game.Graphics.UserInterface protected virtual float StripWidth() => TabContainer.Children.Sum(c => c.IsPresent ? c.DrawWidth + TabContainer.Spacing.X : 0) - TabContainer.Spacing.X; protected virtual float StripHeight() => 1; - protected virtual bool AddAllItemsIfEnum => true; + /// + /// Whether entries should be automatically populated if is an type. + /// + protected virtual bool AddEnumEntriesAutomatically => true; private static bool isEnumType => typeof(T).IsEnum; @@ -47,7 +50,7 @@ namespace osu.Game.Graphics.UserInterface Colour = Color4.White.Opacity(0), }); - if (isEnumType && AddAllItemsIfEnum) + if (isEnumType && AddEnumEntriesAutomatically) foreach (var val in (T[])Enum.GetValues(typeof(T))) AddItem(val); } diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index c867cc3780..04713fd88c 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.BeatmapSet { public class LeaderboardScopeSelector : PageTabControl { - protected override bool AddAllItemsIfEnum => false; + protected override bool AddEnumEntriesAutomatically => false; protected override Dropdown CreateDropdown() => null; From 433b701df3478eb7038ed4002d7f0ba9d9489f86 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 00:21:47 +0900 Subject: [PATCH 2340/5608] Make line slightly thicker (to display better at low resolutions) Also tidies up code. --- .../Overlays/BeatmapSet/LeaderboardScopeSelector.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index 04713fd88c..dcd58db427 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.BeatmapSet AddItem(BeatmapLeaderboardScope.Country); AddItem(BeatmapLeaderboardScope.Friend); - AddInternal(new Line + AddInternal(new GradientLine { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, @@ -78,19 +78,20 @@ namespace osu.Game.Overlays.BeatmapSet } } - private class Line : GridContainer + private class GradientLine : GridContainer { - public Line() + public GradientLine() { - Height = 1; RelativeSizeAxes = Axes.X; - Width = 0.8f; + Size = new Vector2(0.8f, 1.5f); + ColumnDimensions = new[] { new Dimension(), new Dimension(mode: GridSizeMode.Relative, size: 0.4f), new Dimension(), }; + Content = new[] { new Drawable[] From 87811afade5abfdbf6dc3a2503242f2be4be076b Mon Sep 17 00:00:00 2001 From: Lucas A Date: Mon, 12 Aug 2019 20:16:41 +0200 Subject: [PATCH 2341/5608] Add missing licence headers to added files. --- osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs | 5 ++++- osu.Game/Overlays/News/NewsHeader.cs | 5 ++++- osu.Game/Overlays/NewsOverlay.cs | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index d5273801d8..546f6ac182 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -1,4 +1,7 @@ -using osu.Game.Overlays; +// 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.Overlays; namespace osu.Game.Tests.Visual.Online { diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index e887d48456..6a14828473 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -1,4 +1,7 @@ -using osu.Framework.Allocation; +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index 1506cbb288..b509204c58 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -1,4 +1,7 @@ -using osu.Framework.Allocation; +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; From 5447e7cf222ea170409d18e0a8261185b090119a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 11:34:45 +0900 Subject: [PATCH 2342/5608] Fix file ordering --- osu.Game/Overlays/OSD/TrackedSettingToast.cs | 35 +++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/OSD/TrackedSettingToast.cs b/osu.Game/Overlays/OSD/TrackedSettingToast.cs index 0f4bd34779..8e8a99a0a7 100644 --- a/osu.Game/Overlays/OSD/TrackedSettingToast.cs +++ b/osu.Game/Overlays/OSD/TrackedSettingToast.cs @@ -66,12 +66,7 @@ namespace osu.Game.Overlays.OSD ValueText.Origin = optionCount > 0 ? Anchor.BottomCentre : Anchor.Centre; for (int i = 0; i < optionCount; i++) - { - optionLights.Add(new OptionLight - { - Glowing = i == selectedOption - }); - } + optionLights.Add(new OptionLight { Glowing = i == selectedOption }); } private class OptionLight : Container @@ -109,20 +104,6 @@ namespace osu.Game.Overlays.OSD } } - private void updateGlow() - { - if (glowing) - { - fill.FadeColour(glowingColour, transition_speed, Easing.OutQuint); - FadeEdgeEffectTo(glow_strength, transition_speed, Easing.OutQuint); - } - else - { - FadeEdgeEffectTo(0, transition_speed, Easing.OutQuint); - fill.FadeColour(idleColour, transition_speed, Easing.OutQuint); - } - } - [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -147,6 +128,20 @@ namespace osu.Game.Overlays.OSD updateGlow(); FinishTransforms(true); } + + private void updateGlow() + { + if (glowing) + { + fill.FadeColour(glowingColour, transition_speed, Easing.OutQuint); + FadeEdgeEffectTo(glow_strength, transition_speed, Easing.OutQuint); + } + else + { + FadeEdgeEffectTo(0, transition_speed, Easing.OutQuint); + fill.FadeColour(idleColour, transition_speed, Easing.OutQuint); + } + } } } } From f3380c9372c14a2c87db03b832c27001845a1e55 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 12:06:57 +0900 Subject: [PATCH 2343/5608] Remove "jukebox" terminology --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 6 +++--- osu.Game/OsuGame.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index b2cbb77087..c54e3f596e 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -124,13 +124,13 @@ namespace osu.Game.Input.Bindings QuickExit, // Game-wide beatmap jukebox keybindings - [Description("Jukebox next track")] + [Description("Next track")] MusicNext, - [Description("Jukebox previous track")] + [Description("Previous track")] MusicPrev, - [Description("Jukebox play / pause current track")] + [Description("Play / pause")] MusicPlay, } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index af77c8816a..1541d1fa29 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -301,7 +301,7 @@ namespace osu.Game }, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true); } - #region Beatmap jukebox progression + #region Beatmap progression private void beatmapChanged(ValueChangedEvent beatmap) { From aa6f8757eb955cc6179b928dc87038fcc3ff87cd Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 13 Aug 2019 12:26:06 +0900 Subject: [PATCH 2344/5608] remove string param, move menu check to method, add const padding --- .../Visual/Menus/TestSceneScreenNavigation.cs | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index 663447d0b4..efb4f3e83a 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -26,12 +26,14 @@ namespace osu.Game.Tests.Visual.Menus { public class TestSceneScreenNavigation : ManualInputManagerTestScene { + private const float click_padding = 25; + private GameHost gameHost; private TestOsuGame osuGame; - private Vector2 backButtonPosition => osuGame.ToScreenSpace(new Vector2(25, osuGame.LayoutRectangle.Bottom - 25)); + private Vector2 backButtonPosition => osuGame.ToScreenSpace(new Vector2(click_padding, osuGame.LayoutRectangle.Bottom - click_padding)); - private Vector2 optionsButtonPosition => osuGame.ToScreenSpace(new Vector2(25, 25)); + private Vector2 optionsButtonPosition => osuGame.ToScreenSpace(new Vector2(click_padding, click_padding)); [BackgroundDependencyLoader] private void load(GameHost gameHost) @@ -63,7 +65,7 @@ namespace osu.Game.Tests.Visual.Menus }); AddUntilStep("Wait for load", () => osuGame.IsLoaded); AddUntilStep("Wait for intro", () => osuGame.ScreenStack.CurrentScreen is IntroScreen); - AddUntilStep("Wait for main menu", () => osuGame.ScreenStack.CurrentScreen is MainMenu menu && menu.IsLoaded); + confirmAtMainMenu(); } [Test] @@ -71,7 +73,7 @@ namespace osu.Game.Tests.Visual.Menus { TestSongSelect songSelect = null; - pushAndConfirm(() => songSelect = new TestSongSelect(), "song select"); + pushAndConfirm(() => songSelect = new TestSongSelect()); AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show()); AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); AddStep("Press escape", () => pressAndRelease(Key.Escape)); @@ -84,7 +86,7 @@ namespace osu.Game.Tests.Visual.Menus { TestSongSelect songSelect = null; - pushAndConfirm(() => songSelect = new TestSongSelect(), "song select"); + pushAndConfirm(() => songSelect = new TestSongSelect()); AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show()); AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(backButtonPosition)); @@ -100,14 +102,14 @@ namespace osu.Game.Tests.Visual.Menus [Test] public void TestExitMultiWithEscape() { - pushAndConfirm(() => new Screens.Multi.Multiplayer(), "multiplayer"); + pushAndConfirm(() => new Screens.Multi.Multiplayer()); exitViaEscapeAndConfirm(); } [Test] public void TestExitMultiWithBackButton() { - pushAndConfirm(() => new Screens.Multi.Multiplayer(), "multiplayer"); + pushAndConfirm(() => new Screens.Multi.Multiplayer()); exitViaBackButtonAndConfirm(); } @@ -123,26 +125,28 @@ namespace osu.Game.Tests.Visual.Menus AddAssert("Options overlay was closed", () => osuGame.Settings.State.Value == Visibility.Hidden); } - private void pushAndConfirm(Func newScreen, string screenName) + private void pushAndConfirm(Func newScreen) { Screen screen = null; - AddStep($"Push new {screenName}", () => osuGame.ScreenStack.Push(screen = newScreen())); - AddUntilStep($"Wait for new {screenName}", () => osuGame.ScreenStack.CurrentScreen == screen && screen.IsLoaded); + AddStep("Push new screen", () => osuGame.ScreenStack.Push(screen = newScreen())); + AddUntilStep("Wait for new screen", () => osuGame.ScreenStack.CurrentScreen == screen && screen.IsLoaded); } private void exitViaEscapeAndConfirm() { AddStep("Press escape", () => pressAndRelease(Key.Escape)); - AddUntilStep("Wait for main menu", () => osuGame.ScreenStack.CurrentScreen is MainMenu); + confirmAtMainMenu(); } private void exitViaBackButtonAndConfirm() { AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(backButtonPosition)); AddStep("Click back button", () => InputManager.Click(MouseButton.Left)); - AddUntilStep("Wait for main menu", () => osuGame.ScreenStack.CurrentScreen is MainMenu); + confirmAtMainMenu(); } + private void confirmAtMainMenu() => AddUntilStep("Wait for main menu", () => osuGame.ScreenStack.CurrentScreen is MainMenu); + private void pressAndRelease(Key key) { InputManager.PressKey(key); From 0c0c4052168e9cba36bcd096c359c9c89c1e4a1a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 12:27:49 +0900 Subject: [PATCH 2345/5608] Add note to README about ffmpeg requirement on linux --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c4d676f4be..5dc4da12a4 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,9 @@ Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh ## Requirements - A desktop platform with the [.NET Core SDK 2.2](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, there are **[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 working with the codebase, we recommend using an IDE with intellisense and syntax highlighting, such as [Visual Studio 2017+](https://visualstudio.microsoft.com/vs/), [Jetbrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). -- Note that there are **[additional requirements for Windows 7 and Windows 8.1](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore2x)** which you may need to manually install if your operating system is not up-to-date. ## Running osu! From 33a119b7263501823c8f2c1f71a0d881bfd602fd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 12:35:06 +0900 Subject: [PATCH 2346/5608] Fix double grammar Co-Authored-By: Dan Balasescu --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5dc4da12a4..56491a4be4 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh - A desktop platform with the [.NET Core SDK 2.2](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, there are **[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/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 working with the codebase, we recommend using an IDE with intellisense and syntax highlighting, such as [Visual Studio 2017+](https://visualstudio.microsoft.com/vs/), [Jetbrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). ## Running osu! From 5dbde38a6b00586a7d7b9223e775ea7b4fddbf61 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 12:40:20 +0900 Subject: [PATCH 2347/5608] Group key bindings together --- .../Input/Bindings/GlobalActionContainer.cs | 30 +++++++++++-------- .../KeyBinding/GlobalKeyBindingsSection.cs | 12 ++++++++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index c54e3f596e..8073200c47 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -20,7 +20,7 @@ namespace osu.Game.Input.Bindings handler = game; } - public override IEnumerable DefaultKeyBindings => GlobalKeyBindings.Concat(InGameKeyBindings); + public override IEnumerable DefaultKeyBindings => GlobalKeyBindings.Concat(InGameKeyBindings).Concat(AudioControlKeyBindings); public IEnumerable GlobalKeyBindings => new[] { @@ -32,11 +32,6 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings), new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar), new KeyBinding(new[] { InputKey.Control, InputKey.O }, GlobalAction.ToggleSettings), - new KeyBinding(InputKey.Up, GlobalAction.IncreaseVolume), - new KeyBinding(InputKey.MouseWheelUp, GlobalAction.IncreaseVolume), - new KeyBinding(InputKey.Down, GlobalAction.DecreaseVolume), - new KeyBinding(InputKey.MouseWheelDown, GlobalAction.DecreaseVolume), - new KeyBinding(InputKey.F4, GlobalAction.ToggleMute), new KeyBinding(InputKey.Escape, GlobalAction.Back), new KeyBinding(InputKey.ExtraMouseButton1, GlobalAction.Back), @@ -44,13 +39,6 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.Space, GlobalAction.Select), new KeyBinding(InputKey.Enter, GlobalAction.Select), new KeyBinding(InputKey.KeypadEnter, GlobalAction.Select), - - new KeyBinding(InputKey.TrackPrevious, GlobalAction.MusicPrev), - new KeyBinding(InputKey.F1, GlobalAction.MusicPrev), - new KeyBinding(InputKey.TrackNext, GlobalAction.MusicNext), - new KeyBinding(InputKey.F5, GlobalAction.MusicNext), - new KeyBinding(InputKey.PlayPause, GlobalAction.MusicPlay), - new KeyBinding(InputKey.F3, GlobalAction.MusicPlay) }; public IEnumerable InGameKeyBindings => new[] @@ -62,6 +50,22 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { InputKey.Control, InputKey.Minus }, GlobalAction.DecreaseScrollSpeed), }; + public IEnumerable AudioControlKeyBindings => new[] + { + new KeyBinding(InputKey.Up, GlobalAction.IncreaseVolume), + new KeyBinding(InputKey.MouseWheelUp, GlobalAction.IncreaseVolume), + new KeyBinding(InputKey.Down, GlobalAction.DecreaseVolume), + new KeyBinding(InputKey.MouseWheelDown, GlobalAction.DecreaseVolume), + new KeyBinding(InputKey.F4, GlobalAction.ToggleMute), + + new KeyBinding(InputKey.TrackPrevious, GlobalAction.MusicPrev), + new KeyBinding(InputKey.F1, GlobalAction.MusicPrev), + new KeyBinding(InputKey.TrackNext, GlobalAction.MusicNext), + new KeyBinding(InputKey.F5, GlobalAction.MusicNext), + new KeyBinding(InputKey.PlayPause, GlobalAction.MusicPlay), + new KeyBinding(InputKey.F3, GlobalAction.MusicPlay) + }; + protected override IEnumerable KeyBindingInputQueue => handler == null ? base.KeyBindingInputQueue : base.KeyBindingInputQueue.Prepend(handler); } diff --git a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs index 7e33d7ba27..56e93b6a1e 100644 --- a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs @@ -15,6 +15,7 @@ namespace osu.Game.Overlays.KeyBinding public GlobalKeyBindingsSection(GlobalActionContainer manager) { Add(new DefaultBindingsSubsection(manager)); + Add(new AudioControlKeyBindingsSubsection(manager)); Add(new InGameKeyBindingsSubsection(manager)); } @@ -39,5 +40,16 @@ namespace osu.Game.Overlays.KeyBinding Defaults = manager.InGameKeyBindings; } } + + private class AudioControlKeyBindingsSubsection : KeyBindingsSubsection + { + protected override string Header => "Audio"; + + public AudioControlKeyBindingsSubsection(GlobalActionContainer manager) + : base(null) + { + Defaults = manager.AudioControlKeyBindings; + } + } } } From 5681d1097c107c4cbbe060c36997c08cc19ebe74 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 13 Aug 2019 14:07:40 +0900 Subject: [PATCH 2348/5608] Move into components namespace --- .../Visual/Online/TestScenePreviousUsernamesContainer.cs | 2 +- .../Header/{ => Components}/PreviousUsernamesContainer.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game/Overlays/Profile/Header/{ => Components}/PreviousUsernamesContainer.cs (99%) diff --git a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs index b891fda0f4..43373f872a 100644 --- a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs @@ -7,7 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Online.API; using osu.Game.Online.API.Requests; -using osu.Game.Overlays.Profile.Header; +using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual.Online diff --git a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernamesContainer.cs similarity index 99% rename from osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs rename to osu.Game/Overlays/Profile/Header/Components/PreviousUsernamesContainer.cs index b53ac8eb80..ef9c01e12b 100644 --- a/osu.Game/Overlays/Profile/Header/PreviousUsernamesContainer.cs +++ b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernamesContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -11,10 +13,8 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Users; using osuTK; -using System; -using System.Linq; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays.Profile.Header.Components { public class PreviousUsernamesContainer : CompositeDrawable { From 8d3f2f76459d062cd2ee54afa747d96981794e9a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 13 Aug 2019 14:09:10 +0900 Subject: [PATCH 2349/5608] Drop container from name --- ....cs => TestSceneUserProfilePreviousUsernames.cs} | 13 ++++++++++--- ...usUsernamesContainer.cs => PreviousUsernames.cs} | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) rename osu.Game.Tests/Visual/Online/{TestScenePreviousUsernamesContainer.cs => TestSceneUserProfilePreviousUsernames.cs} (85%) rename osu.Game/Overlays/Profile/Header/Components/{PreviousUsernamesContainer.cs => PreviousUsernames.cs} (98%) diff --git a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs similarity index 85% rename from osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs rename to osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs index 43373f872a..d09a50b12c 100644 --- a/osu.Game.Tests/Visual/Online/TestScenePreviousUsernamesContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -13,16 +15,21 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestScenePreviousUsernamesContainer : OsuTestScene + public class TestSceneUserProfilePreviousUsernames : OsuTestScene { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(PreviousUsernames) + }; + [Resolved] private IAPIProvider api { get; set; } private readonly Bindable user = new Bindable(); - public TestScenePreviousUsernamesContainer() + public TestSceneUserProfilePreviousUsernames() { - Child = new PreviousUsernamesContainer + Child = new PreviousUsernames { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Profile/Header/Components/PreviousUsernamesContainer.cs b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs similarity index 98% rename from osu.Game/Overlays/Profile/Header/Components/PreviousUsernamesContainer.cs rename to osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs index ef9c01e12b..f18f319e27 100644 --- a/osu.Game/Overlays/Profile/Header/Components/PreviousUsernamesContainer.cs +++ b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { - public class PreviousUsernamesContainer : CompositeDrawable + public class PreviousUsernames : CompositeDrawable { private const int duration = 200; private const int margin = 10; @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Profile.Header.Components private readonly Box background; private readonly SpriteText header; - public PreviousUsernamesContainer() + public PreviousUsernames() { HoverIconContainer hoverIcon; From ad24265730b98ac86b5b8c739afdf2da172782ad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 14:29:58 +0900 Subject: [PATCH 2350/5608] Split visual component out of MusicController --- .../Visual/Gameplay/TestSceneStoryboard.cs | 40 +- .../TestSceneBeatSyncedContainer.cs | 29 +- ...oller.cs => TestSceneNowPlayingOverlay.cs} | 18 +- osu.Game/OsuGame.cs | 4 +- osu.Game/Overlays/MusicController.cs | 475 +++--------------- osu.Game/Overlays/NowPlayingOverlay.cs | 403 +++++++++++++++ .../Overlays/Toolbar/ToolbarMusicButton.cs | 2 +- 7 files changed, 532 insertions(+), 439 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{TestSceneMusicController.cs => TestSceneNowPlayingOverlay.cs} (58%) create mode 100644 osu.Game/Overlays/NowPlayingOverlay.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs index ead7a4b7fc..ff8437311e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs @@ -21,32 +21,38 @@ namespace osu.Game.Tests.Visual.Gameplay private readonly Container storyboardContainer; private DrawableStoryboard storyboard; + [Cached] + private MusicController musicController = new MusicController(); + public TestSceneStoryboard() { Clock = new FramedClock(); - Add(new Container + AddRange(new Drawable[] { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + musicController, + new Container { - new Box + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - storyboardContainer = new Container - { - RelativeSizeAxes = Axes.Both, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + storyboardContainer = new Container + { + RelativeSizeAxes = Axes.Both, + }, }, }, - }); - - Add(new MusicController - { - Origin = Anchor.TopRight, - Anchor = Anchor.TopRight, - State = { Value = Visibility.Visible }, + new NowPlayingOverlay + { + Origin = Anchor.TopRight, + Anchor = Anchor.TopRight, + State = { Value = Visibility.Visible }, + } }); AddStep("Restart", restart); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index 28f0cc027e..94228e22f0 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -3,6 +3,7 @@ using System; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -22,30 +23,36 @@ namespace osu.Game.Tests.Visual.UserInterface [TestFixture] public class TestSceneBeatSyncedContainer : OsuTestScene { - private readonly MusicController mc; + private readonly NowPlayingOverlay np; + + [Cached] + private MusicController musicController = new MusicController(); public TestSceneBeatSyncedContainer() { Clock = new FramedClock(); Clock.ProcessFrame(); - Add(new BeatContainer + AddRange(new Drawable[] { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - }); - - Add(mc = new MusicController - { - Origin = Anchor.TopRight, - Anchor = Anchor.TopRight, + musicController, + new BeatContainer + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + }, + np = new NowPlayingOverlay + { + Origin = Anchor.TopRight, + Anchor = Anchor.TopRight, + } }); } protected override void LoadComplete() { base.LoadComplete(); - mc.ToggleVisibility(); + np.ToggleVisibility(); } private class BeatContainer : BeatSyncedContainer diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs similarity index 58% rename from osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index ab2ca47100..e3daa9c279 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneMusicController.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Timing; using osu.Game.Overlays; @@ -9,22 +10,27 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneMusicController : OsuTestScene + public class TestSceneNowPlayingOverlay : OsuTestScene { - public TestSceneMusicController() + [Cached] + private MusicController musicController = new MusicController(); + + public TestSceneNowPlayingOverlay() { Clock = new FramedClock(); - var mc = new MusicController + var np = new NowPlayingOverlay { Origin = Anchor.Centre, Anchor = Anchor.Centre }; - Add(mc); - AddStep(@"show", () => mc.Show()); + Add(musicController); + Add(np); + + AddStep(@"show", () => np.Show()); AddToggleStep(@"toggle beatmap lock", state => Beatmap.Disabled = state); - AddStep(@"show", () => mc.Hide()); + AddStep(@"show", () => np.Hide()); } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b9e2b79b05..edf3424e0e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -469,6 +469,8 @@ namespace osu.Game loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add); loadComponentSingleFile(new OnScreenDisplay(), Add, true); + loadComponentSingleFile(musicController = new MusicController(), Add, true); + loadComponentSingleFile(notifications = new NotificationOverlay { GetToolbarHeight = () => ToolbarOffset, @@ -495,7 +497,7 @@ namespace osu.Game Origin = Anchor.TopRight, }, rightFloatingOverlayContent.Add, true); - loadComponentSingleFile(musicController = new MusicController + loadComponentSingleFile(new NowPlayingOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index abbcec5094..d1086d589d 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -4,281 +4,87 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; -using osu.Framework.Input.Events; -using osu.Framework.Localisation; using osu.Framework.Threading; using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Overlays.Music; using osu.Game.Rulesets.Mods; -using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays { - public class MusicController : OsuFocusedOverlayContainer + /// + /// Handles playback of the global music track. + /// + public class MusicController : Component { - private const float player_height = 130; - private const float transition_length = 800; - private const float progress_height = 10; - private const float bottom_black_area_height = 55; - - private Drawable background; - private ProgressBar progressBar; - - private IconButton prevButton; - private IconButton playButton; - private IconButton nextButton; - private IconButton playlistButton; - - private SpriteText title, artist; - - private PlaylistOverlay playlist; - - private BeatmapManager beatmaps; + [Resolved] + private BeatmapManager beatmaps { get; set; } private List beatmapSets; - private Container dragContainer; - private Container playerContainer; - public bool IsUserPaused { get; private set; } + /// + /// Fired when the global has changed. + /// Includes direction information for display purposes. + /// + public event Action TrackChanged; + [Resolved] - private Bindable beatmap { get; set; } + private IBindable beatmap { get; set; } [Resolved] private IBindable> mods { get; set; } - /// - /// Provide a source for the toolbar height. - /// - public Func GetToolbarHeight; - - public MusicController() - { - Width = 400; - Margin = new MarginPadding(10); - } - [BackgroundDependencyLoader] - private void load(Bindable beatmap, BeatmapManager beatmaps, OsuColour colours) + private void load() { - this.beatmaps = beatmaps; - - Children = new Drawable[] - { - dragContainer = new DragContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - playlist = new PlaylistOverlay - { - RelativeSizeAxes = Axes.X, - Y = player_height + 10, - OrderChanged = playlistOrderChanged - }, - playerContainer = new Container - { - RelativeSizeAxes = Axes.X, - Height = player_height, - Masking = true, - CornerRadius = 5, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(40), - Radius = 5, - }, - Children = new[] - { - background = new Background(), - title = new OsuSpriteText - { - Origin = Anchor.BottomCentre, - Anchor = Anchor.TopCentre, - Position = new Vector2(0, 40), - Font = OsuFont.GetFont(size: 25, italics: true), - Colour = Color4.White, - Text = @"Nothing to play", - }, - artist = new OsuSpriteText - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Position = new Vector2(0, 45), - Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold, italics: true), - Colour = Color4.White, - Text = @"Nothing to play", - }, - new Container - { - Padding = new MarginPadding { Bottom = progress_height }, - Height = bottom_black_area_height, - RelativeSizeAxes = Axes.X, - Origin = Anchor.BottomCentre, - Anchor = Anchor.BottomCentre, - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5), - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Children = new[] - { - prevButton = new MusicIconButton - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Action = prev, - Icon = FontAwesome.Solid.StepBackward, - }, - playButton = new MusicIconButton - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(1.4f), - IconScale = new Vector2(1.4f), - Action = togglePause, - Icon = FontAwesome.Regular.PlayCircle, - }, - nextButton = new MusicIconButton - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Action = () => next(), - Icon = FontAwesome.Solid.StepForward, - }, - } - }, - playlistButton = new MusicIconButton - { - Origin = Anchor.Centre, - Anchor = Anchor.CentreRight, - Position = new Vector2(-bottom_black_area_height / 2, 0), - Icon = FontAwesome.Solid.Bars, - Action = () => playlist.ToggleVisibility(), - }, - } - }, - progressBar = new ProgressBar - { - Origin = Anchor.BottomCentre, - Anchor = Anchor.BottomCentre, - Height = progress_height, - FillColour = colours.Yellow, - OnSeek = attemptSeek - } - }, - }, - } - } - }; - beatmapSets = beatmaps.GetAllUsableBeatmapSets(); beatmaps.ItemAdded += handleBeatmapAdded; beatmaps.ItemRemoved += handleBeatmapRemoved; - - playlist.State.ValueChanged += s => playlistButton.FadeColour(s.NewValue == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint); } - private ScheduledDelegate seekDelegate; - - private void attemptSeek(double progress) + protected override void LoadComplete() { - seekDelegate?.Cancel(); - seekDelegate = Schedule(() => - { - if (!beatmap.Disabled) - current?.Track.Seek(progress); - }); + beatmap.BindValueChanged(beatmapChanged, true); + mods.BindValueChanged(_ => updateAudioAdjustments(), true); + base.LoadComplete(); } - private void playlistOrderChanged(BeatmapSetInfo beatmapSetInfo, int index) + /// + /// Change the position of a in the current playlist. + /// + /// The beatmap to move. + /// The new position. + public void ChangeBeatmapSetPosition(BeatmapSetInfo beatmapSetInfo, int index) { beatmapSets.Remove(beatmapSetInfo); beatmapSets.Insert(index, beatmapSetInfo); } - private void handleBeatmapAdded(BeatmapSetInfo set) => Schedule(() => beatmapSets.Add(set)); + private void handleBeatmapAdded(BeatmapSetInfo set) => + Schedule(() => beatmapSets.Add(set)); - private void handleBeatmapRemoved(BeatmapSetInfo set) => Schedule(() => beatmapSets.RemoveAll(s => s.ID == set.ID)); + private void handleBeatmapRemoved(BeatmapSetInfo set) => + Schedule(() => beatmapSets.RemoveAll(s => s.ID == set.ID)); - protected override void LoadComplete() + private ScheduledDelegate seekDelegate; + + public void SeekTo(double position) { - beatmap.BindValueChanged(beatmapChanged, true); - beatmap.BindDisabledChanged(beatmapDisabledChanged, true); - mods.BindValueChanged(_ => updateAudioAdjustments(), true); - base.LoadComplete(); - } - - private void beatmapDisabledChanged(bool disabled) - { - if (disabled) - playlist.Hide(); - - playButton.Enabled.Value = !disabled; - prevButton.Enabled.Value = !disabled; - nextButton.Enabled.Value = !disabled; - playlistButton.Enabled.Value = !disabled; - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - Height = dragContainer.Height; - - dragContainer.Padding = new MarginPadding { Top = GetToolbarHeight?.Invoke() ?? 0 }; - } - - protected override void Update() - { - base.Update(); - - if (pendingBeatmapSwitch != null) + seekDelegate?.Cancel(); + seekDelegate = Schedule(() => { - pendingBeatmapSwitch(); - pendingBeatmapSwitch = null; - } - - var track = current?.TrackLoaded ?? false ? current.Track : null; - - if (track?.IsDummyDevice == false) - { - progressBar.EndTime = track.Length; - progressBar.CurrentTime = track.CurrentTime; - - playButton.Icon = track.IsRunning ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle; - } - else - { - progressBar.CurrentTime = 0; - progressBar.EndTime = 1; - playButton.Icon = FontAwesome.Regular.PlayCircle; - } + if (!beatmap.Disabled) + current?.Track.Seek(position); + }); } - private void togglePause() + /// + /// Toggle pause / play. + /// + public void TogglePause() { var track = current?.Track; @@ -301,46 +107,57 @@ namespace osu.Game.Overlays } } - private void prev() + /// + /// Play the previous track. + /// + public void PrevTrack() { - queuedDirection = TransformDirection.Prev; + queuedDirection = TrackChangeDirection.Prev; var playable = beatmapSets.TakeWhile(i => i.ID != current.BeatmapSetInfo.ID).LastOrDefault() ?? beatmapSets.LastOrDefault(); if (playable != null) { - beatmap.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); + if (beatmap is Bindable working) + working.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); beatmap.Value.Track.Restart(); } } + /// + /// Play the next random or playlist track. + /// + public void NextTrack() => next(); + private void next(bool instant = false) { if (!instant) - queuedDirection = TransformDirection.Next; + queuedDirection = TrackChangeDirection.Next; var playable = beatmapSets.SkipWhile(i => i.ID != current.BeatmapSetInfo.ID).Skip(1).FirstOrDefault() ?? beatmapSets.FirstOrDefault(); if (playable != null) { - beatmap.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); + if (beatmap is Bindable working) + working.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); beatmap.Value.Track.Restart(); } } private WorkingBeatmap current; - private TransformDirection? queuedDirection; + + private TrackChangeDirection? queuedDirection; private void beatmapChanged(ValueChangedEvent beatmap) { - TransformDirection direction = TransformDirection.None; + TrackChangeDirection direction = TrackChangeDirection.None; if (current != null) { bool audioEquals = beatmap.NewValue?.BeatmapInfo?.AudioEquals(current.BeatmapInfo) ?? false; if (audioEquals) - direction = TransformDirection.None; + direction = TrackChangeDirection.None; else if (queuedDirection.HasValue) { direction = queuedDirection.Value; @@ -352,13 +169,13 @@ namespace osu.Game.Overlays var last = beatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); var next = beatmap.NewValue == null ? -1 : beatmapSets.TakeWhile(b => b.ID != beatmap.NewValue.BeatmapSetInfo?.ID).Count(); - direction = last > next ? TransformDirection.Prev : TransformDirection.Next; + direction = last > next ? TrackChangeDirection.Prev : TrackChangeDirection.Next; } } - progressBar.CurrentTime = 0; + current = beatmap.NewValue; + TrackChanged?.Invoke(current, direction); - updateDisplay(current = beatmap.NewValue, direction); updateAudioAdjustments(); queuedDirection = null; @@ -376,167 +193,19 @@ namespace osu.Game.Overlays mod.ApplyToClock(track); } - private Action pendingBeatmapSwitch; - - private void updateDisplay(WorkingBeatmap beatmap, TransformDirection direction) + protected override void Dispose(bool isDisposing) { - // avoid using scheduler as our scheduler may not be run for a long time, holding references to beatmaps. - pendingBeatmapSwitch = delegate - { - // todo: this can likely be replaced with WorkingBeatmap.GetBeatmapAsync() - Task.Run(() => - { - if (beatmap?.Beatmap == null) //this is not needed if a placeholder exists - { - title.Text = @"Nothing to play"; - artist.Text = @"Nothing to play"; - } - else - { - BeatmapMetadata metadata = beatmap.Metadata; - title.Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)); - artist.Text = new LocalisedString((metadata.ArtistUnicode, metadata.Artist)); - } - }); + base.Dispose(isDisposing); - LoadComponentAsync(new Background(beatmap) { Depth = float.MaxValue }, newBackground => - { - switch (direction) - { - case TransformDirection.Next: - newBackground.Position = new Vector2(400, 0); - newBackground.MoveToX(0, 500, Easing.OutCubic); - background.MoveToX(-400, 500, Easing.OutCubic); - break; - - case TransformDirection.Prev: - newBackground.Position = new Vector2(-400, 0); - newBackground.MoveToX(0, 500, Easing.OutCubic); - background.MoveToX(400, 500, Easing.OutCubic); - break; - } - - background.Expire(); - background = newBackground; - - playerContainer.Add(newBackground); - }); - }; + beatmaps.ItemAdded -= handleBeatmapAdded; + beatmaps.ItemRemoved -= handleBeatmapRemoved; } + } - protected override void PopIn() - { - base.PopIn(); - - this.FadeIn(transition_length, Easing.OutQuint); - dragContainer.ScaleTo(1, transition_length, Easing.OutElastic); - } - - protected override void PopOut() - { - base.PopOut(); - - this.FadeOut(transition_length, Easing.OutQuint); - dragContainer.ScaleTo(0.9f, transition_length, Easing.OutQuint); - } - - private enum TransformDirection - { - None, - Next, - Prev - } - - private class MusicIconButton : IconButton - { - public MusicIconButton() - { - AutoSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - HoverColour = colours.YellowDark.Opacity(0.6f); - FlashColour = colours.Yellow; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - // works with AutoSizeAxes above to make buttons autosize with the scale animation. - Content.AutoSizeAxes = Axes.None; - Content.Size = new Vector2(DEFAULT_BUTTON_SIZE); - } - } - - private class Background : BufferedContainer - { - private readonly Sprite sprite; - private readonly WorkingBeatmap beatmap; - - public Background(WorkingBeatmap beatmap = null) - { - this.beatmap = beatmap; - CacheDrawnFrameBuffer = true; - Depth = float.MaxValue; - RelativeSizeAxes = Axes.Both; - - Children = new Drawable[] - { - sprite = new Sprite - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.Gray(150), - FillMode = FillMode.Fill, - }, - new Box - { - RelativeSizeAxes = Axes.X, - Height = bottom_black_area_height, - Origin = Anchor.BottomCentre, - Anchor = Anchor.BottomCentre, - Colour = Color4.Black.Opacity(0.5f) - } - }; - } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg4"); - } - } - - private class DragContainer : Container - { - protected override bool OnDragStart(DragStartEvent e) - { - return true; - } - - protected override bool OnDrag(DragEvent e) - { - Vector2 change = e.MousePosition - e.MouseDownPosition; - - // Diminish the drag distance as we go further to simulate "rubber band" feeling. - change *= change.Length <= 0 ? 0 : (float)Math.Pow(change.Length, 0.7f) / change.Length; - - this.MoveTo(change); - return true; - } - - protected override bool OnDragEnd(DragEndEvent e) - { - this.MoveTo(Vector2.Zero, 800, Easing.OutElastic); - return base.OnDragEnd(e); - } - } - - /// - /// Play the next random or playlist track. - /// - public void NextTrack() => next(); + public enum TrackChangeDirection + { + None, + Next, + Prev } } diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs new file mode 100644 index 0000000000..98bad5323d --- /dev/null +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -0,0 +1,403 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Threading.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Input.Events; +using osu.Framework.Localisation; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Music; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays +{ + public class NowPlayingOverlay : OsuFocusedOverlayContainer + { + private const float player_height = 130; + private const float transition_length = 800; + private const float progress_height = 10; + private const float bottom_black_area_height = 55; + + private Drawable background; + private ProgressBar progressBar; + + private IconButton prevButton; + private IconButton playButton; + private IconButton nextButton; + private IconButton playlistButton; + + private SpriteText title, artist; + + private PlaylistOverlay playlist; + + private Container dragContainer; + private Container playerContainer; + + /// + /// Provide a source for the toolbar height. + /// + public Func GetToolbarHeight; + + [Resolved] + private MusicController musicController { get; set; } + + [Resolved] + private Bindable beatmap { get; set; } + + public NowPlayingOverlay() + { + Width = 400; + Margin = new MarginPadding(10); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Children = new Drawable[] + { + dragContainer = new DragContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + playlist = new PlaylistOverlay + { + RelativeSizeAxes = Axes.X, + Y = player_height + 10, + OrderChanged = musicController.ChangeBeatmapSetPosition + }, + playerContainer = new Container + { + RelativeSizeAxes = Axes.X, + Height = player_height, + Masking = true, + CornerRadius = 5, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(40), + Radius = 5, + }, + Children = new[] + { + background = new Background(), + title = new OsuSpriteText + { + Origin = Anchor.BottomCentre, + Anchor = Anchor.TopCentre, + Position = new Vector2(0, 40), + Font = OsuFont.GetFont(size: 25, italics: true), + Colour = Color4.White, + Text = @"Nothing to play", + }, + artist = new OsuSpriteText + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Position = new Vector2(0, 45), + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold, italics: true), + Colour = Color4.White, + Text = @"Nothing to play", + }, + new Container + { + Padding = new MarginPadding { Bottom = progress_height }, + Height = bottom_black_area_height, + RelativeSizeAxes = Axes.X, + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Children = new[] + { + prevButton = new MusicIconButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Action = musicController.PrevTrack, + Icon = FontAwesome.Solid.StepBackward, + }, + playButton = new MusicIconButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(1.4f), + IconScale = new Vector2(1.4f), + Action = musicController.TogglePause, + Icon = FontAwesome.Regular.PlayCircle, + }, + nextButton = new MusicIconButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Action = musicController.NextTrack, + Icon = FontAwesome.Solid.StepForward, + }, + } + }, + playlistButton = new MusicIconButton + { + Origin = Anchor.Centre, + Anchor = Anchor.CentreRight, + Position = new Vector2(-bottom_black_area_height / 2, 0), + Icon = FontAwesome.Solid.Bars, + Action = () => playlist.ToggleVisibility(), + }, + } + }, + progressBar = new ProgressBar + { + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + Height = progress_height, + FillColour = colours.Yellow, + OnSeek = musicController.SeekTo + } + }, + }, + } + } + }; + + playlist.State.ValueChanged += s => playlistButton.FadeColour(s.NewValue == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + beatmap.BindDisabledChanged(beatmapDisabledChanged, true); + + musicController.TrackChanged += trackChanged; + trackChanged(beatmap.Value); + } + + protected override void PopIn() + { + base.PopIn(); + + this.FadeIn(transition_length, Easing.OutQuint); + dragContainer.ScaleTo(1, transition_length, Easing.OutElastic); + } + + protected override void PopOut() + { + base.PopOut(); + + this.FadeOut(transition_length, Easing.OutQuint); + dragContainer.ScaleTo(0.9f, transition_length, Easing.OutQuint); + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + Height = dragContainer.Height; + dragContainer.Padding = new MarginPadding { Top = GetToolbarHeight?.Invoke() ?? 0 }; + } + + protected override void Update() + { + base.Update(); + + if (pendingBeatmapSwitch != null) + { + pendingBeatmapSwitch(); + pendingBeatmapSwitch = null; + } + + var track = beatmap.Value?.TrackLoaded ?? false ? beatmap.Value.Track : null; + + if (track?.IsDummyDevice == false) + { + progressBar.EndTime = track.Length; + progressBar.CurrentTime = track.CurrentTime; + + playButton.Icon = track.IsRunning ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle; + } + else + { + progressBar.CurrentTime = 0; + progressBar.EndTime = 1; + playButton.Icon = FontAwesome.Regular.PlayCircle; + } + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + musicController.TrackChanged -= trackChanged; + } + + private Action pendingBeatmapSwitch; + + private void trackChanged(WorkingBeatmap beatmap, TrackChangeDirection direction = TrackChangeDirection.None) + { + // avoid using scheduler as our scheduler may not be run for a long time, holding references to beatmaps. + pendingBeatmapSwitch = delegate + { + // todo: this can likely be replaced with WorkingBeatmap.GetBeatmapAsync() + Task.Run(() => + { + if (beatmap?.Beatmap == null) //this is not needed if a placeholder exists + { + title.Text = @"Nothing to play"; + artist.Text = @"Nothing to play"; + } + else + { + BeatmapMetadata metadata = beatmap.Metadata; + title.Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)); + artist.Text = new LocalisedString((metadata.ArtistUnicode, metadata.Artist)); + } + }); + + LoadComponentAsync(new Background(beatmap) { Depth = float.MaxValue }, newBackground => + { + switch (direction) + { + case TrackChangeDirection.Next: + newBackground.Position = new Vector2(400, 0); + newBackground.MoveToX(0, 500, Easing.OutCubic); + background.MoveToX(-400, 500, Easing.OutCubic); + break; + + case TrackChangeDirection.Prev: + newBackground.Position = new Vector2(-400, 0); + newBackground.MoveToX(0, 500, Easing.OutCubic); + background.MoveToX(400, 500, Easing.OutCubic); + break; + } + + background.Expire(); + background = newBackground; + + playerContainer.Add(newBackground); + }); + }; + } + + private void beatmapDisabledChanged(bool disabled) + { + if (disabled) + playlist.Hide(); + + playButton.Enabled.Value = !disabled; + prevButton.Enabled.Value = !disabled; + nextButton.Enabled.Value = !disabled; + playlistButton.Enabled.Value = !disabled; + } + + private class MusicIconButton : IconButton + { + public MusicIconButton() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + HoverColour = colours.YellowDark.Opacity(0.6f); + FlashColour = colours.Yellow; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + // works with AutoSizeAxes above to make buttons autosize with the scale animation. + Content.AutoSizeAxes = Axes.None; + Content.Size = new Vector2(DEFAULT_BUTTON_SIZE); + } + } + + private class Background : BufferedContainer + { + private readonly Sprite sprite; + private readonly WorkingBeatmap beatmap; + + public Background(WorkingBeatmap beatmap = null) + { + this.beatmap = beatmap; + CacheDrawnFrameBuffer = true; + Depth = float.MaxValue; + RelativeSizeAxes = Axes.Both; + + Children = new Drawable[] + { + sprite = new Sprite + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(150), + FillMode = FillMode.Fill, + }, + new Box + { + RelativeSizeAxes = Axes.X, + Height = bottom_black_area_height, + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + Colour = Color4.Black.Opacity(0.5f) + } + }; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg4"); + } + } + + private class DragContainer : Container + { + protected override bool OnDragStart(DragStartEvent e) + { + return true; + } + + protected override bool OnDrag(DragEvent e) + { + Vector2 change = e.MousePosition - e.MouseDownPosition; + + // Diminish the drag distance as we go further to simulate "rubber band" feeling. + change *= change.Length <= 0 ? 0 : (float)Math.Pow(change.Length, 0.7f) / change.Length; + + this.MoveTo(change); + return true; + } + + protected override bool OnDragEnd(DragEndEvent e) + { + this.MoveTo(Vector2.Zero, 800, Easing.OutElastic); + return base.OnDragEnd(e); + } + } + } +} diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index f03df2ed93..b29aec5842 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -14,7 +14,7 @@ namespace osu.Game.Overlays.Toolbar } [BackgroundDependencyLoader(true)] - private void load(MusicController music) + private void load(NowPlayingOverlay music) { StateContainer = music; } From 9aac5efa4e5bf8ff6374731b815ec5e26a8a75d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 14:38:49 +0900 Subject: [PATCH 2351/5608] Move logic out of OsuGame --- osu.Game/OsuGame.cs | 25 +------ osu.Game/Overlays/MusicController.cs | 74 +++++++++++++++++-- osu.Game/Overlays/NowPlayingOverlay.cs | 6 +- osu.Game/Overlays/OSD/MusicControllerToast.cs | 13 ---- 4 files changed, 70 insertions(+), 48 deletions(-) delete mode 100644 osu.Game/Overlays/OSD/MusicControllerToast.cs diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ab7e5b19d1..0e804ecbaf 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -68,8 +68,6 @@ namespace osu.Game private BeatmapSetOverlay beatmapSetOverlay; - private OnScreenDisplay osd; - [Cached] private readonly ScreenshotManager screenshotManager = new ScreenshotManager(); @@ -469,7 +467,7 @@ namespace osu.Game }); loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add); - loadComponentSingleFile(osd = new OnScreenDisplay(), Add, true); + loadComponentSingleFile(new OnScreenDisplay(), Add, true); loadComponentSingleFile(musicController = new MusicController(), Add, true); @@ -734,27 +732,6 @@ namespace osu.Game case GlobalAction.ToggleGameplayMouseButtons: LocalConfig.Set(OsuSetting.MouseDisableButtons, !LocalConfig.Get(OsuSetting.MouseDisableButtons)); return true; - - case GlobalAction.MusicPlay: - if (!musicController.IsLoaded) return true; - - if (musicController.PlayTrack()) - osd.Display(new Overlays.OSD.MusicControllerToast(musicController.IsPlaying ? "Play track" : "Pause track")); - return true; - - case GlobalAction.MusicNext: - if (!musicController.IsLoaded) return true; - - if (musicController.NextTrack()) - osd.Display(new Overlays.OSD.MusicControllerToast("Next track")); - return true; - - case GlobalAction.MusicPrev: - if (!musicController.IsLoaded) return true; - - if (musicController.PreviousTrack()) - osd.Display(new Overlays.OSD.MusicControllerToast("Previous track")); - return true; } return false; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index d1086d589d..14f7b574da 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -7,8 +7,11 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Input.Bindings; using osu.Framework.Threading; using osu.Game.Beatmaps; +using osu.Game.Input.Bindings; +using osu.Game.Overlays.OSD; using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays @@ -16,7 +19,7 @@ namespace osu.Game.Overlays /// /// Handles playback of the global music track. /// - public class MusicController : Component + public class MusicController : Component, IKeyBindingHandler { [Resolved] private BeatmapManager beatmaps { get; set; } @@ -37,6 +40,9 @@ namespace osu.Game.Overlays [Resolved] private IBindable> mods { get; set; } + [Resolved(canBeNull: true)] + private OnScreenDisplay onScreenDisplay { get; set; } + [BackgroundDependencyLoader] private void load() { @@ -58,11 +64,17 @@ namespace osu.Game.Overlays /// The beatmap to move. /// The new position. public void ChangeBeatmapSetPosition(BeatmapSetInfo beatmapSetInfo, int index) + { beatmapSets.Remove(beatmapSetInfo); beatmapSets.Insert(index, beatmapSetInfo); } + /// + /// Returns whether the current beatmap track is playing. + /// + public bool IsPlaying => beatmap.Value.Track.IsRunning; + private void handleBeatmapAdded(BeatmapSetInfo set) => Schedule(() => beatmapSets.Add(set)); @@ -84,15 +96,17 @@ namespace osu.Game.Overlays /// /// Toggle pause / play. /// - public void TogglePause() + public bool TogglePause() { var track = current?.Track; if (track == null) { - if (!beatmap.Disabled) - next(true); - return; + if (beatmap.Disabled) + return false; + + next(true); + return true; } if (track.IsRunning) @@ -105,12 +119,14 @@ namespace osu.Game.Overlays track.Start(); IsUserPaused = false; } + + return true; } /// /// Play the previous track. /// - public void PrevTrack() + public bool PrevTrack() { queuedDirection = TrackChangeDirection.Prev; @@ -121,15 +137,19 @@ namespace osu.Game.Overlays if (beatmap is Bindable working) working.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); beatmap.Value.Track.Restart(); + + return true; } + + return false; } /// /// Play the next random or playlist track. /// - public void NextTrack() => next(); + public bool NextTrack() => next(); - private void next(bool instant = false) + private bool next(bool instant = false) { if (!instant) queuedDirection = TrackChangeDirection.Next; @@ -141,7 +161,10 @@ namespace osu.Game.Overlays if (beatmap is Bindable working) working.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); beatmap.Value.Track.Restart(); + return true; } + + return false; } private WorkingBeatmap current; @@ -200,6 +223,41 @@ namespace osu.Game.Overlays beatmaps.ItemAdded -= handleBeatmapAdded; beatmaps.ItemRemoved -= handleBeatmapRemoved; } + + public bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.MusicPlay: + if (TogglePause()) + onScreenDisplay?.Display(new MusicControllerToast(IsPlaying ? "Play track" : "Pause track")); + return true; + + case GlobalAction.MusicNext: + if (NextTrack()) + onScreenDisplay?.Display(new MusicControllerToast("Next track")); + + return true; + + case GlobalAction.MusicPrev: + if (PrevTrack()) + onScreenDisplay?.Display(new MusicControllerToast("Previous track")); + + return true; + } + + return false; + } + + public bool OnReleased(GlobalAction action) => false; + + public class MusicControllerToast : Toast + { + public MusicControllerToast(string action) + : base("Music Playback", action, string.Empty) + { + } + } } public enum TrackChangeDirection diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 98bad5323d..f14adcb53d 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -138,7 +138,7 @@ namespace osu.Game.Overlays { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Action = musicController.PrevTrack, + Action = () => musicController.PrevTrack(), Icon = FontAwesome.Solid.StepBackward, }, playButton = new MusicIconButton @@ -147,14 +147,14 @@ namespace osu.Game.Overlays Origin = Anchor.Centre, Scale = new Vector2(1.4f), IconScale = new Vector2(1.4f), - Action = musicController.TogglePause, + Action = () => musicController.TogglePause(), Icon = FontAwesome.Regular.PlayCircle, }, nextButton = new MusicIconButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Action = musicController.NextTrack, + Action = () => musicController.NextTrack(), Icon = FontAwesome.Solid.StepForward, }, } diff --git a/osu.Game/Overlays/OSD/MusicControllerToast.cs b/osu.Game/Overlays/OSD/MusicControllerToast.cs deleted file mode 100644 index d9e0ad2c07..0000000000 --- a/osu.Game/Overlays/OSD/MusicControllerToast.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Overlays.OSD -{ - public class MusicControllerToast : Toast - { - public MusicControllerToast(string value) - : base("Music Playback", value, "") - { - } - } -} From de1ab56a2c28e408879d273fde84c509d91c31cf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 14:45:27 +0900 Subject: [PATCH 2352/5608] Fix potential nullref on disposal --- osu.Game/Overlays/MusicController.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index d1086d589d..681e318c92 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -197,8 +197,11 @@ namespace osu.Game.Overlays { base.Dispose(isDisposing); - beatmaps.ItemAdded -= handleBeatmapAdded; - beatmaps.ItemRemoved -= handleBeatmapRemoved; + if (beatmaps != null) + { + beatmaps.ItemAdded -= handleBeatmapAdded; + beatmaps.ItemRemoved -= handleBeatmapRemoved; + } } } From 2cbdf8c01c3044a028a876e6fd9753996b4b34fe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 14:46:57 +0900 Subject: [PATCH 2353/5608] Update public methods in line with future usage --- osu.Game/Overlays/MusicController.cs | 35 ++++++++++++++++++++------ osu.Game/Overlays/NowPlayingOverlay.cs | 6 ++--- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 681e318c92..da9c34238e 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.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; @@ -63,6 +63,11 @@ namespace osu.Game.Overlays beatmapSets.Insert(index, beatmapSetInfo); } + /// + /// Returns whether the current beatmap track is playing. + /// + public bool IsPlaying => beatmap.Value.Track.IsRunning; + private void handleBeatmapAdded(BeatmapSetInfo set) => Schedule(() => beatmapSets.Add(set)); @@ -84,15 +89,18 @@ namespace osu.Game.Overlays /// /// Toggle pause / play. /// - public void TogglePause() + /// Whether the operation was successful. + public bool TogglePause() { var track = current?.Track; if (track == null) { - if (!beatmap.Disabled) - next(true); - return; + if (beatmap.Disabled) + return false; + + next(true); + return true; } if (track.IsRunning) @@ -105,12 +113,15 @@ namespace osu.Game.Overlays track.Start(); IsUserPaused = false; } + + return true; } /// /// Play the previous track. /// - public void PrevTrack() + /// Whether the operation was successful. + public bool PrevTrack() { queuedDirection = TrackChangeDirection.Prev; @@ -121,15 +132,20 @@ namespace osu.Game.Overlays if (beatmap is Bindable working) working.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); beatmap.Value.Track.Restart(); + + return true; } + + return false; } /// /// Play the next random or playlist track. /// - public void NextTrack() => next(); + /// Whether the operation was successful. + public bool NextTrack() => next(); - private void next(bool instant = false) + private bool next(bool instant = false) { if (!instant) queuedDirection = TrackChangeDirection.Next; @@ -141,7 +157,10 @@ namespace osu.Game.Overlays if (beatmap is Bindable working) working.Value = beatmaps.GetWorkingBeatmap(playable.Beatmaps.First(), beatmap.Value); beatmap.Value.Track.Restart(); + return true; } + + return false; } private WorkingBeatmap current; diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 98bad5323d..f14adcb53d 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -138,7 +138,7 @@ namespace osu.Game.Overlays { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Action = musicController.PrevTrack, + Action = () => musicController.PrevTrack(), Icon = FontAwesome.Solid.StepBackward, }, playButton = new MusicIconButton @@ -147,14 +147,14 @@ namespace osu.Game.Overlays Origin = Anchor.Centre, Scale = new Vector2(1.4f), IconScale = new Vector2(1.4f), - Action = musicController.TogglePause, + Action = () => musicController.TogglePause(), Icon = FontAwesome.Regular.PlayCircle, }, nextButton = new MusicIconButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Action = musicController.NextTrack, + Action = () => musicController.NextTrack(), Icon = FontAwesome.Solid.StepForward, }, } From 81f8b5f325702b5d1ae227006b9c26b7d2dd2834 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 14:52:51 +0900 Subject: [PATCH 2354/5608] Fix merge issue --- osu.Game/Overlays/MusicController.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index b055c7ef1b..91220907a0 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -64,7 +64,6 @@ namespace osu.Game.Overlays /// The beatmap to move. /// The new position. public void ChangeBeatmapSetPosition(BeatmapSetInfo beatmapSetInfo, int index) - { beatmapSets.Remove(beatmapSetInfo); beatmapSets.Insert(index, beatmapSetInfo); From b942192e004c95891e02048d007077836c51f9b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 15:04:04 +0900 Subject: [PATCH 2355/5608] Fix remaining nullref --- osu.Game/Overlays/NowPlayingOverlay.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index f14adcb53d..a3243a655e 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -247,13 +247,6 @@ namespace osu.Game.Overlays } } - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - musicController.TrackChanged -= trackChanged; - } - private Action pendingBeatmapSwitch; private void trackChanged(WorkingBeatmap beatmap, TrackChangeDirection direction = TrackChangeDirection.None) @@ -313,6 +306,14 @@ namespace osu.Game.Overlays playlistButton.Enabled.Value = !disabled; } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (musicController != null) + musicController.TrackChanged -= trackChanged; + } + private class MusicIconButton : IconButton { public MusicIconButton() From 8ef4b2a0f6a1467c0e8fd9dec63e35d63d1df942 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 13 Aug 2019 11:29:48 +0300 Subject: [PATCH 2356/5608] Hide NotificationOverlay --- osu.Desktop/Overlays/VersionManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 1f1d2cea5f..51e801c185 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -113,13 +113,14 @@ namespace osu.Desktop.Overlays } [BackgroundDependencyLoader] - private void load(OsuColour colours, ChangelogOverlay changelog) + private void load(OsuColour colours, ChangelogOverlay changelog, NotificationOverlay notificationOverlay) { Icon = FontAwesome.Solid.CheckSquare; IconBackgound.Colour = colours.BlueDark; Activated = delegate { + notificationOverlay.Hide(); changelog.ShowBuild(OsuGameBase.CLIENT_STREAM_NAME, version); return true; }; From 6b57c9801d8e9a97d5d520f4e0705530190bd216 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 13 Aug 2019 17:32:43 +0900 Subject: [PATCH 2357/5608] Cull some unnecessary whitespace --- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index dafea70092..ea7a713e0e 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -177,9 +177,7 @@ namespace osu.Game.Screens.Multi.Match public override bool OnExiting(IScreen next) { RoomManager?.PartRoom(); - Mods.Value = Array.Empty(); - previewTrackManager.StopAnyPlaying(this); return base.OnExiting(next); From 92c2dafa1281048437cf7651caf61643b5b302d7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 13 Aug 2019 17:34:16 +0900 Subject: [PATCH 2358/5608] Tighten accessibility --- osu.Game/Screens/Multi/Match/Components/Header.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index 7f2b1278b7..a52d43acf4 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -25,12 +25,12 @@ namespace osu.Game.Screens.Multi.Match.Components { public const float HEIGHT = 200; - public MatchTabControl Tabs; + public readonly BindableBool ShowBeatmapPanel = new BindableBool(); + + public MatchTabControl Tabs { get; private set; } public Action RequestBeatmapSelection; - public BindableBool ShowBeatmapPanel = new BindableBool(); - private MatchBeatmapPanel beatmapPanel; public Header() From 7c9c9f1ce1f062f667ec38e6d2c300332cbfe857 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 13 Aug 2019 17:38:21 +0900 Subject: [PATCH 2359/5608] Simplify caching --- .../Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs | 8 +------- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs index f148170847..68ad0b42b4 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs @@ -13,6 +13,7 @@ using osu.Framework.Allocation; namespace osu.Game.Tests.Visual.Multiplayer { + [Cached(typeof(IPreviewTrackOwner))] public class TestSceneMatchBeatmapPanel : MultiplayerTestScene, IPreviewTrackOwner { public override IReadOnlyList RequiredTypes => new[] @@ -48,12 +49,5 @@ namespace osu.Game.Tests.Visual.Multiplayer previewTrackManager.StopAnyPlaying(this); }); } - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(this); - return dependencies; - } } } diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index ea7a713e0e..f3e10db444 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -19,6 +19,7 @@ using PlaylistItem = osu.Game.Online.Multiplayer.PlaylistItem; namespace osu.Game.Screens.Multi.Match { + [Cached(typeof(IPreviewTrackOwner))] public class MatchSubScreen : MultiplayerSubScreen, IPreviewTrackOwner { public override bool DisallowExternalBeatmapRulesetChanges => true; @@ -237,13 +238,6 @@ namespace osu.Game.Screens.Multi.Match } } - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(this); - return dependencies; - } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From f2e596de1640c4939ada0d6c18d2b71e89295679 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2019 08:54:17 +0000 Subject: [PATCH 2360/5608] Bump ppy.osu.Framework from 2019.809.0 to 2019.813.0 Bumps [ppy.osu.Framework](https://github.com/ppy/osu-framework) from 2019.809.0 to 2019.813.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.809.0...2019.813.0) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b5266fd75d..e149c4338d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 103d89cadc..2bb95d0772 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,7 +105,7 @@ - + From e356cc8d9ef288056745f4b0b1899c0503284ee5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 13 Aug 2019 17:57:16 +0900 Subject: [PATCH 2361/5608] Refactor MatchBeatmapPanel for thread safety --- .../Match/Components/MatchBeatmapPanel.cs | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs index 7939b18e97..7c1fe91393 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs @@ -1,8 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Threading; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Direct; @@ -18,6 +20,7 @@ namespace osu.Game.Screens.Multi.Match.Components [Resolved] private RulesetStore rulesets { get; set; } + private CancellationTokenSource loadCancellation; private GetBeatmapSetRequest request; private DirectGridPanel panel; @@ -29,30 +32,31 @@ namespace osu.Game.Screens.Multi.Match.Components [BackgroundDependencyLoader] private void load() { - CurrentItem.BindValueChanged(item => + CurrentItem.BindValueChanged(item => loadNewPanel(item.NewValue?.Beatmap), true); + } + + private void loadNewPanel(BeatmapInfo beatmap) + { + loadCancellation?.Cancel(); + request?.Cancel(); + + panel?.FadeOut(200); + panel?.Expire(); + panel = null; + + if (beatmap?.OnlineBeatmapID == null) + return; + + loadCancellation = new CancellationTokenSource(); + + request = new GetBeatmapSetRequest(beatmap.OnlineBeatmapID.Value, BeatmapSetLookupType.BeatmapId); + request.Success += res => Schedule(() => { - request?.Cancel(); + panel = new DirectGridPanel(res.ToBeatmapSet(rulesets)); + LoadComponentAsync(panel, AddInternal, loadCancellation.Token); + }); - if (panel != null) - { - panel.FadeOut(200); - panel.Expire(); - panel = null; - } - - var onlineId = item.NewValue?.Beatmap.OnlineBeatmapID; - - if (onlineId.HasValue) - { - request = new GetBeatmapSetRequest(onlineId.Value, BeatmapSetLookupType.BeatmapId); - request.Success += beatmap => - { - panel = new DirectGridPanel(beatmap.ToBeatmapSet(rulesets)); - LoadComponentAsync(panel, AddInternal); - }; - api.Queue(request); - } - }, true); + api.Queue(request); } } } From fe7bc824df6b2eda0b52e48517b37535363f4537 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2019 09:00:20 +0000 Subject: [PATCH 2362/5608] Bump ppy.osu.Framework.NativeLibs from 2019.307.0 to 2019.813.0 Bumps [ppy.osu.Framework.NativeLibs](https://github.com/ppy/osu-framework) from 2019.307.0 to 2019.813.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.307.0...2019.813.0) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 103d89cadc..09b9da142c 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -111,6 +111,6 @@ - + From 6b3eeb88fc9dac58b70f60991aceb147aab67895 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2019 09:00:43 +0000 Subject: [PATCH 2363/5608] Bump ppy.osu.Framework.iOS from 2019.809.0 to 2019.813.0 Bumps [ppy.osu.Framework.iOS](https://github.com/ppy/osu-framework) from 2019.809.0 to 2019.813.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.809.0...2019.813.0) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 103d89cadc..d444a5893f 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -106,7 +106,7 @@ - + From 91068dc5709585c1c4175acd45fca05f581ff583 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2019 09:01:00 +0000 Subject: [PATCH 2364/5608] Bump ppy.osu.Framework.Android from 2019.809.0 to 2019.813.0 Bumps [ppy.osu.Framework.Android](https://github.com/ppy/osu-framework) from 2019.809.0 to 2019.813.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.809.0...2019.813.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index 721d341c08..85741fcf84 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + From 5963f7d9147e7ead009611f4b90b27e67506433b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 19:52:40 +0900 Subject: [PATCH 2365/5608] Update comment --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 8073200c47..b70072a222 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -127,7 +127,7 @@ namespace osu.Game.Input.Bindings [Description("Quick exit (Hold)")] QuickExit, - // Game-wide beatmap jukebox keybindings + // Game-wide beatmap msi ccotolle keybindings [Description("Next track")] MusicNext, From 2cd0015735fa28996b2c374a3d632e76a019c503 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Aug 2019 23:27:27 +0900 Subject: [PATCH 2366/5608] Attempt to appease apple with some plist keys --- osu.iOS/Info.plist | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index 0775d1522d..a118b329aa 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -31,6 +31,10 @@ UIStatusBarHidden + NSCameraUsageDescription + We don't really use the camera. + NSMicrophoneUsageDescription + We don't really use the microphone. UISupportedInterfaceOrientations UIInterfaceOrientationPortrait From b6bc84af2c886f964c5aafada6cd82c2065a3bee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 14 Aug 2019 10:52:26 +0900 Subject: [PATCH 2367/5608] Fix chat context menus displaying out-of-bounds --- osu.Game/Overlays/Chat/DrawableChannel.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 8d56e250fc..928201581a 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -32,16 +32,16 @@ namespace osu.Game.Overlays.Chat { Children = new Drawable[] { - scroll = new OsuScrollContainer + new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - // Some chat lines have effects that slightly protrude to the bottom, - // which we do not want to mask away, hence the padding. - Padding = new MarginPadding { Bottom = 5 }, - Child = new OsuContextMenuContainer + Masking = true, + Child = scroll = new OsuScrollContainer { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.Both, + // Some chat lines have effects that slightly protrude to the bottom, + // which we do not want to mask away, hence the padding. + Padding = new MarginPadding { Bottom = 5 }, Child = ChatLineFlow = new ChatLineContainer { Padding = new MarginPadding { Left = 20, Right = 20 }, From 52f42ddadeed12febc7e23897bd243b42448d982 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 14 Aug 2019 10:53:47 +0900 Subject: [PATCH 2368/5608] Use child instead of children --- osu.Game/Overlays/Chat/DrawableChannel.cs | 31 ++++++++++------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 928201581a..f831266b1b 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -30,27 +30,24 @@ namespace osu.Game.Overlays.Chat [BackgroundDependencyLoader] private void load() { - Children = new Drawable[] + Child = new OsuContextMenuContainer { - new OsuContextMenuContainer + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = scroll = new OsuScrollContainer { RelativeSizeAxes = Axes.Both, - Masking = true, - Child = scroll = new OsuScrollContainer + // Some chat lines have effects that slightly protrude to the bottom, + // which we do not want to mask away, hence the padding. + Padding = new MarginPadding { Bottom = 5 }, + Child = ChatLineFlow = new ChatLineContainer { - RelativeSizeAxes = Axes.Both, - // Some chat lines have effects that slightly protrude to the bottom, - // which we do not want to mask away, hence the padding. - Padding = new MarginPadding { Bottom = 5 }, - Child = ChatLineFlow = new ChatLineContainer - { - Padding = new MarginPadding { Left = 20, Right = 20 }, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - } - }, - } + Padding = new MarginPadding { Left = 20, Right = 20 }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + } + }, }; newMessagesArrived(Channel.Messages); From 480e489c44d28130edd5be8dca5d02763455cecb Mon Sep 17 00:00:00 2001 From: David Zhao Date: Wed, 14 Aug 2019 12:51:43 +0900 Subject: [PATCH 2369/5608] add back missing loaded check --- osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs index efb4f3e83a..515f4cdce6 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneScreenNavigation.cs @@ -145,7 +145,7 @@ namespace osu.Game.Tests.Visual.Menus confirmAtMainMenu(); } - private void confirmAtMainMenu() => AddUntilStep("Wait for main menu", () => osuGame.ScreenStack.CurrentScreen is MainMenu); + private void confirmAtMainMenu() => AddUntilStep("Wait for main menu", () => osuGame.ScreenStack.CurrentScreen is MainMenu menu && menu.IsLoaded); private void pressAndRelease(Key key) { From 3a79a4149a430e9f5dec5ab7a47bf425a9cd7cb0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 14 Aug 2019 15:19:21 +0900 Subject: [PATCH 2370/5608] Disable music controls when beatmap is disabled --- osu.Game/Overlays/MusicController.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 91220907a0..f6208c46cb 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -231,6 +231,9 @@ namespace osu.Game.Overlays public bool OnPressed(GlobalAction action) { + if (beatmap.Disabled) + return false; + switch (action) { case GlobalAction.MusicPlay: From 840a142e98a592ef93d0d8ad1dfbf3796005a039 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2019 12:16:32 +0000 Subject: [PATCH 2371/5608] Bump ppy.osu.Framework.iOS from 2019.813.0 to 2019.814.0 Bumps [ppy.osu.Framework.iOS](https://github.com/ppy/osu-framework) from 2019.813.0 to 2019.814.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.813.0...2019.814.0) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 9ea5081658..d50f23c2c2 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -119,7 +119,7 @@ - + From e36e2a899ae1602dc303246eaae217abfd700421 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2019 12:16:53 +0000 Subject: [PATCH 2372/5608] Bump ppy.osu.Framework.Android from 2019.813.0 to 2019.814.0 Bumps [ppy.osu.Framework.Android](https://github.com/ppy/osu-framework) from 2019.813.0 to 2019.814.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.813.0...2019.814.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index 065c66ebba..7bc60ef884 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -61,6 +61,6 @@ - + From 3379672a43a9f1f0536e85db3887b51653b12a22 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2019 12:17:17 +0000 Subject: [PATCH 2373/5608] Bump ppy.osu.Framework from 2019.813.0 to 2019.814.0 Bumps [ppy.osu.Framework](https://github.com/ppy/osu-framework) from 2019.813.0 to 2019.814.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.813.0...2019.814.0) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e149c4338d..f5e4d4b1fb 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 9ea5081658..e831fdc7cb 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,7 +118,7 @@ - + From f849b4ce54e4b8e75a8286192b4dfbae24f80e25 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Wed, 14 Aug 2019 19:49:32 +0200 Subject: [PATCH 2374/5608] Make autoplay unpress sooner, if needed --- .../Replays/TaikoAutoGenerator.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 422ba748e3..60fd88882e 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -113,14 +113,21 @@ namespace osu.Game.Rulesets.Taiko.Replays else throw new InvalidOperationException("Unknown hit object type."); - Frames.Add(new TaikoReplayFrame(endTime + KEY_UP_DELAY)); - if (i < Beatmap.HitObjects.Count - 1) { - double waitTime = Beatmap.HitObjects[i + 1].StartTime - 1000; + var nextHitObject = Beatmap.HitObjects[i + 1]; + + if (!(nextHitObject.StartTime < endTime + KEY_UP_DELAY)) + Frames.Add(new TaikoReplayFrame(endTime + KEY_UP_DELAY)); + + double waitTime = nextHitObject.StartTime - 1000; if (waitTime > endTime) Frames.Add(new TaikoReplayFrame(waitTime)); } + else + { + Frames.Add(new TaikoReplayFrame(endTime + KEY_UP_DELAY)); + } hitButton = !hitButton; } From e567e81981d6f940a9de97d68a3bab496e6d29cc Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Wed, 14 Aug 2019 20:10:52 +0200 Subject: [PATCH 2375/5608] Refactoring --- osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 60fd88882e..014511d090 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -117,7 +117,7 @@ namespace osu.Game.Rulesets.Taiko.Replays { var nextHitObject = Beatmap.HitObjects[i + 1]; - if (!(nextHitObject.StartTime < endTime + KEY_UP_DELAY)) + if (nextHitObject.StartTime > endTime + KEY_UP_DELAY) Frames.Add(new TaikoReplayFrame(endTime + KEY_UP_DELAY)); double waitTime = nextHitObject.StartTime - 1000; From ba539abac77484c3dd5103333e84231a46d81cf2 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Wed, 14 Aug 2019 21:05:24 +0200 Subject: [PATCH 2376/5608] Refactoring --- .../Replays/TaikoAutoGenerator.cs | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 014511d090..a46ecab6f0 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -113,21 +113,23 @@ namespace osu.Game.Rulesets.Taiko.Replays else throw new InvalidOperationException("Unknown hit object type."); + TaikoHitObject nextHitObject; if (i < Beatmap.HitObjects.Count - 1) + nextHitObject = Beatmap.HitObjects[i + 1]; + else + nextHitObject = null; + + bool canDelayKeyUp = nextHitObject != null && nextHitObject.StartTime > endTime + KEY_UP_DELAY; + + if (canDelayKeyUp) + Frames.Add(new TaikoReplayFrame(endTime + KEY_UP_DELAY)); + + if (nextHitObject != null) { - var nextHitObject = Beatmap.HitObjects[i + 1]; - - if (nextHitObject.StartTime > endTime + KEY_UP_DELAY) - Frames.Add(new TaikoReplayFrame(endTime + KEY_UP_DELAY)); - double waitTime = nextHitObject.StartTime - 1000; if (waitTime > endTime) Frames.Add(new TaikoReplayFrame(waitTime)); } - else - { - Frames.Add(new TaikoReplayFrame(endTime + KEY_UP_DELAY)); - } hitButton = !hitButton; } From 840d4741daf285b0c2541997f39b6fda309a492b Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 14 Aug 2019 20:24:36 +0200 Subject: [PATCH 2377/5608] Add NewsContent class and fix broken reference. --- osu.Game/Overlays/News/NewsContent.cs | 16 ++++++++++++++++ osu.Game/Overlays/News/NewsHeader.cs | 2 +- osu.Game/Overlays/NewsOverlay.cs | 10 +++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Overlays/News/NewsContent.cs diff --git a/osu.Game/Overlays/News/NewsContent.cs b/osu.Game/Overlays/News/NewsContent.cs new file mode 100644 index 0000000000..f0763285eb --- /dev/null +++ b/osu.Game/Overlays/News/NewsContent.cs @@ -0,0 +1,16 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Overlays.News +{ + public abstract class NewsContent : FillFlowContainer + { + public NewsContent() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Direction = FillDirection.Vertical; + Padding = new MarginPadding { Bottom = 100 }; + } + } +} diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 6a14828473..27620ab523 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -97,7 +97,7 @@ namespace osu.Game.Overlays.News IsReadingArticle = false; } - protected override Drawable CreateIcon() => new ScreenTitleIcon(@"Icons/news"); + protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/news"); [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index b509204c58..b341321a46 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -15,6 +15,7 @@ namespace osu.Game.Overlays public class NewsOverlay : FullscreenOverlay { private NewsHeader header; + private Container content; public readonly Bindable Current = new Bindable(null); @@ -39,13 +40,20 @@ namespace osu.Game.Overlays Children = new Drawable[] { header = new NewsHeader() + { + ShowFrontPage = ShowFrontPage + }, + content = new Container() + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } }, }, }, }; header.Current.BindTo(Current); - header.ShowFrontPage = ShowFrontPage; Current.TriggerChange(); } From 46e71e9ead75227f63080ed4751e3f61228d1f40 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 14 Aug 2019 21:34:29 +0200 Subject: [PATCH 2378/5608] Add missing licence header --- osu.Game/Overlays/News/NewsContent.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/News/NewsContent.cs b/osu.Game/Overlays/News/NewsContent.cs index f0763285eb..26f92b3825 100644 --- a/osu.Game/Overlays/News/NewsContent.cs +++ b/osu.Game/Overlays/News/NewsContent.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.Framework.Graphics.Containers; namespace osu.Game.Overlays.News From 4d1b1a4022d530d5c7fff5ceec3d04ffca641543 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 14 Aug 2019 21:52:36 +0200 Subject: [PATCH 2379/5608] Fix CI inspections --- osu.Game/Overlays/News/NewsContent.cs | 2 +- osu.Game/Overlays/NewsOverlay.cs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/News/NewsContent.cs b/osu.Game/Overlays/News/NewsContent.cs index 26f92b3825..16a8ed84b8 100644 --- a/osu.Game/Overlays/News/NewsContent.cs +++ b/osu.Game/Overlays/News/NewsContent.cs @@ -8,7 +8,7 @@ namespace osu.Game.Overlays.News { public abstract class NewsContent : FillFlowContainer { - public NewsContent() + protected NewsContent() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index b341321a46..aadca8883e 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -15,6 +15,8 @@ namespace osu.Game.Overlays public class NewsOverlay : FullscreenOverlay { private NewsHeader header; + + //ReSharper disable NotAccessedField.Local private Container content; public readonly Bindable Current = new Bindable(null); @@ -39,11 +41,11 @@ namespace osu.Game.Overlays Direction = FillDirection.Vertical, Children = new Drawable[] { - header = new NewsHeader() + header = new NewsHeader { ShowFrontPage = ShowFrontPage }, - content = new Container() + content = new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, From 07e7e1187c980f9e2962c013203869d3b4c774bc Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 15 Aug 2019 05:30:35 +0300 Subject: [PATCH 2380/5608] Add adjustment function in SkinnableSound --- osu.Game/Skinning/SkinnableSound.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 8e2b5cec98..205f25bf9d 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -37,6 +37,8 @@ namespace osu.Game.Skinning public void Play() => channels?.ForEach(c => c.Play()); + public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => channels?.ForEach(c => c.AddAdjustment(type, adjustBindable)); + public override bool IsPresent => false; // We don't need to receive updates. protected override void SkinChanged(ISkinSource skin, bool allowFallback) From cfa569b226ab742f9527615852a64373a5fd7cb6 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 15 Aug 2019 05:35:47 +0300 Subject: [PATCH 2381/5608] Add looping field and fix build --- osu.Game/Skinning/SkinnableSound.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 205f25bf9d..f9dd39d04d 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Audio; @@ -35,6 +36,8 @@ namespace osu.Game.Skinning this.audio = audio; } + public bool Looping; + public void Play() => channels?.ForEach(c => c.Play()); public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => channels?.ForEach(c => c.AddAdjustment(type, adjustBindable)); @@ -60,6 +63,7 @@ namespace osu.Game.Skinning if (ch == null) continue; + ch.Looping = Looping; ch.Volume.Value = info.Volume / 100.0; return ch; } From f355cff8bcc9c048f793d2032ebb719be89a6358 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Aug 2019 12:11:54 +0900 Subject: [PATCH 2382/5608] Apply reviews --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 167 +++++++++--------- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 2 +- osu.Game/Overlays/Direct/DirectPanel.cs | 2 +- .../Screens/Multi/Components/ModeTypeInfo.cs | 2 +- .../Carousel/DrawableCarouselBeatmap.cs | 2 +- .../Carousel/DrawableCarouselBeatmapSet.cs | 2 +- 6 files changed, 88 insertions(+), 89 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index f5c8d0d029..b29303ad1e 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -23,7 +23,7 @@ namespace osu.Game.Beatmaps.Drawables { private readonly RulesetInfo ruleset; - public DifficultyIcon(BeatmapInfo beatmap, RulesetInfo ruleset = null, Boolean shouldShowTooltip = false) + public DifficultyIcon(BeatmapInfo beatmap, RulesetInfo ruleset = null, bool shouldShowTooltip = true) : base(beatmap) { if (beatmap == null) @@ -39,89 +39,6 @@ namespace osu.Game.Beatmaps.Drawables public ITooltip GetCustomTooltip() => new DifficultyIconTooltip(AccentColour); - public class DifficultyIconTooltip : VisibilityContainer, ITooltip - { - private readonly OsuSpriteText difficultyName, starRating; - private readonly Box background; - - public string TooltipText { get; set; } - - public DifficultyIconTooltip(Color4 accentColour) - { - AutoSizeAxes = Axes.Both; - Masking = true; - CornerRadius = 5; - - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Padding = new MarginPadding(10), - Children = new Drawable[] - { - difficultyName = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 16, weight: FontWeight.Bold), - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Direction = FillDirection.Horizontal, - Children = new Drawable[] - { - starRating = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 16, weight: FontWeight.Regular), - Colour = accentColour - }, - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Margin = new MarginPadding { Left = 4 }, - Icon = FontAwesome.Solid.Star, - Size = new Vector2(12), - Colour = accentColour, - }, - } - } - } - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = colours.GreyCarmineDark; - } - - public void Refresh() - { - var info = TooltipText.Split('$'); - difficultyName.Text = info[0]; - starRating.Text = info[1]; - } - - public void Move(Vector2 pos) => Position = pos; - - protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); - - protected override void PopOut() => this.FadeOut(200, Easing.OutQuint); - } - [BackgroundDependencyLoader] private void load() { @@ -156,5 +73,87 @@ namespace osu.Game.Beatmaps.Drawables } }; } + + private class DifficultyIconTooltip : VisibilityContainer, ITooltip + { + private readonly OsuSpriteText difficultyName, starRating; + private readonly Box background; + + public string TooltipText { get; set; } + + public DifficultyIconTooltip(Color4 difficultyColour) + { + AutoSizeAxes = Axes.Both; + Masking = true; + CornerRadius = 5; + + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Padding = new MarginPadding(10), + Children = new Drawable[] + { + difficultyName = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 16, weight: FontWeight.Bold), + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Direction = FillDirection.Horizontal, + Colour = difficultyColour, + Children = new Drawable[] + { + starRating = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 16, weight: FontWeight.Regular), + }, + new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Left = 4 }, + Icon = FontAwesome.Solid.Star, + Size = new Vector2(12), + }, + } + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.GreyCarmineDark; + } + + public void Refresh() + { + var info = TooltipText.Split('$'); + difficultyName.Text = info[0]; + starRating.Text = info[1]; + } + + public void Move(Vector2 pos) => Position = pos; + + protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); + + protected override void PopOut() => this.FadeOut(200, Easing.OutQuint); + } } } diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index baf702eebc..104315f1c2 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -234,7 +234,7 @@ namespace osu.Game.Overlays.BeatmapSet Colour = Color4.Black.Opacity(0.5f), }, }, - icon = new DifficultyIcon(beatmap) + icon = new DifficultyIcon(beatmap, shouldShowTooltip: false) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 41c565090f..8199d80528 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -143,7 +143,7 @@ namespace osu.Game.Overlays.Direct var icons = new List(); foreach (var b in SetInfo.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty)) - icons.Add(new DifficultyIcon(b, null, true)); + icons.Add(new DifficultyIcon(b)); return icons; } diff --git a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs index 434c5c443b..6080458aec 100644 --- a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Multi.Components if (item?.Beatmap != null) { drawableRuleset.FadeIn(transition_duration); - drawableRuleset.Child = new DifficultyIcon(item.Beatmap, item.Ruleset, true) { Size = new Vector2(height) }; + drawableRuleset.Child = new DifficultyIcon(item.Beatmap, item.Ruleset) { Size = new Vector2(height) }; } else drawableRuleset.FadeOut(transition_duration); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 0a20f2aa6d..fba7a328c1 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -82,7 +82,7 @@ namespace osu.Game.Screens.Select.Carousel Origin = Anchor.CentreLeft, Children = new Drawable[] { - new DifficultyIcon(beatmap) + new DifficultyIcon(beatmap, shouldShowTooltip: false) { Scale = new Vector2(1.8f), }, diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 86ae6a2e58..4ceb82d4cc 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -197,7 +197,7 @@ namespace osu.Game.Screens.Select.Carousel private readonly BindableBool filtered = new BindableBool(); public FilterableDifficultyIcon(CarouselBeatmap item) - : base(item.Beatmap, shouldShowTooltip: true) + : base(item.Beatmap) { filtered.BindTo(item.Filtered); filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100)); From e73a9c2748ad4e0c8b7c5ef263f7ccad14f4268e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Aug 2019 14:00:12 +0900 Subject: [PATCH 2383/5608] Fix song select context menus displaying off-screen --- osu.Game/Screens/Select/BeatmapCarousel.cs | 26 +++++++++++++--------- osu.Game/Screens/Select/SongSelect.cs | 1 - 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 7366fa8c17..6fda81e47d 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -24,7 +24,7 @@ using osu.Game.Screens.Select.Carousel; namespace osu.Game.Screens.Select { - public class BeatmapCarousel : OsuScrollContainer + public class BeatmapCarousel : CompositeDrawable { private const float bleed_top = FilterControl.HEIGHT; private const float bleed_bottom = Footer.HEIGHT; @@ -61,6 +61,8 @@ namespace osu.Game.Screens.Select /// public bool BeatmapSetsLoaded { get; private set; } + private readonly OsuScrollContainer scroll; + private IEnumerable beatmapSets => root.Children.OfType(); public IEnumerable BeatmapSets @@ -110,13 +112,17 @@ namespace osu.Game.Screens.Select public BeatmapCarousel() { root = new CarouselRoot(this); - Child = new OsuContextMenuContainer + InternalChild = new OsuContextMenuContainer { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = scrollableContent = new Container + RelativeSizeAxes = Axes.Both, + Child = scroll = new OsuScrollContainer { - RelativeSizeAxes = Axes.X, + Masking = false, + RelativeSizeAxes = Axes.Both, + Child = scrollableContent = new Container + { + RelativeSizeAxes = Axes.X, + } } }; } @@ -127,7 +133,7 @@ namespace osu.Game.Screens.Select config.BindWith(OsuSetting.RandomSelectAlgorithm, RandomAlgorithm); config.BindWith(OsuSetting.SongSelectRightMouseScroll, RightClickScrollingEnabled); - RightClickScrollingEnabled.ValueChanged += enabled => RightMouseScrollbar = enabled.NewValue; + RightClickScrollingEnabled.ValueChanged += enabled => scroll.RightMouseScrollbar = enabled.NewValue; RightClickScrollingEnabled.TriggerChange(); loadBeatmapSets(beatmaps.GetAllUsableBeatmapSetsEnumerable()); @@ -351,12 +357,12 @@ namespace osu.Game.Screens.Select /// /// The position of the lower visible bound with respect to the current scroll position. /// - private float visibleBottomBound => Current + DrawHeight + bleed_bottom; + private float visibleBottomBound => scroll.Current + DrawHeight + bleed_bottom; /// /// The position of the upper visible bound with respect to the current scroll position. /// - private float visibleUpperBound => Current - bleed_top; + private float visibleUpperBound => scroll.Current - bleed_top; public void FlushPendingFilterOperations() { @@ -628,7 +634,7 @@ namespace osu.Game.Screens.Select private void updateScrollPosition() { - if (scrollTarget != null) ScrollTo(scrollTarget.Value); + if (scrollTarget != null) scroll.ScrollTo(scrollTarget.Value); scrollPositionCache.Validate(); } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 7dd934f91a..8340814db9 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -157,7 +157,6 @@ namespace osu.Game.Screens.Select }, Child = Carousel = new BeatmapCarousel { - Masking = false, RelativeSizeAxes = Axes.Both, Size = new Vector2(1 - wedged_container_size.X, 1), Anchor = Anchor.CentreRight, From f7a92487ef548c060b8af695efe9d49fe76a9b6b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Aug 2019 14:09:30 +0900 Subject: [PATCH 2384/5608] Fix checkbox sounds playing too often --- .../Graphics/UserInterface/OsuCheckbox.cs | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 47324ee646..6593531099 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -72,17 +72,11 @@ namespace osu.Game.Graphics.UserInterface Current.DisabledChanged += disabled => labelText.Alpha = Nub.Alpha = disabled ? 0.3f : 1; } - protected override void LoadComplete() + [BackgroundDependencyLoader] + private void load(AudioManager audio) { - base.LoadComplete(); - - Current.ValueChanged += enabled => - { - if (enabled.NewValue) - sampleChecked?.Play(); - else - sampleUnchecked?.Play(); - }; + sampleChecked = audio.Samples.Get(@"UI/check-on"); + sampleUnchecked = audio.Samples.Get(@"UI/check-off"); } protected override bool OnHover(HoverEvent e) @@ -99,11 +93,13 @@ namespace osu.Game.Graphics.UserInterface base.OnHoverLost(e); } - [BackgroundDependencyLoader] - private void load(AudioManager audio) + protected override void OnUserChange(bool value) { - sampleChecked = audio.Samples.Get(@"UI/check-on"); - sampleUnchecked = audio.Samples.Get(@"UI/check-off"); + base.OnUserChange(value); + if (value) + sampleChecked?.Play(); + else + sampleUnchecked?.Play(); } } } From 9e13a6aeae1a2a0259f926cf3c0d4db284d04315 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Aug 2019 14:32:31 +0900 Subject: [PATCH 2385/5608] Fix newlines being considered in user profile content --- osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index e7f7c2f490..691e18e6bf 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -138,6 +138,9 @@ namespace osu.Game.Overlays.Profile.Header private void tryAddInfo(IconUsage icon, string content, string link = null) { + // newlines could be contained in API returned user content. + content = content?.Replace("\n", " "); + if (string.IsNullOrEmpty(content)) return; bottomLinkContainer.AddIcon(icon, text => From 8f638879728bff8c8812253ba24476d7721e176d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Aug 2019 14:38:49 +0900 Subject: [PATCH 2386/5608] Make use of existing null check --- osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 691e18e6bf..158641d816 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -138,11 +138,11 @@ namespace osu.Game.Overlays.Profile.Header private void tryAddInfo(IconUsage icon, string content, string link = null) { - // newlines could be contained in API returned user content. - content = content?.Replace("\n", " "); - if (string.IsNullOrEmpty(content)) return; + // newlines could be contained in API returned user content. + content = content.Replace("\n", " "); + bottomLinkContainer.AddIcon(icon, text => { text.Font = text.Font.With(size: 10); From ef5ed915e5b51781117bcb514ffe8a2751a3ac86 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Aug 2019 17:14:00 +0900 Subject: [PATCH 2387/5608] Reduce delay for hold-to-confirm controls --- .../Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs | 7 ++++++- osu.Game/Graphics/Containers/HoldToConfirmContainer.cs | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs index 7e6cf1285e..a017418e3a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Screens.Menu; @@ -12,7 +13,11 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneHoldToConfirmOverlay : OsuTestScene { - public override IReadOnlyList RequiredTypes => new[] { typeof(ExitConfirmOverlay) }; + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ExitConfirmOverlay), + typeof(HoldToConfirmContainer), + }; public TestSceneHoldToConfirmOverlay() { diff --git a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs index cda5e150de..18a4241a79 100644 --- a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs +++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs @@ -12,7 +12,7 @@ namespace osu.Game.Graphics.Containers { public Action Action; - private const int activate_delay = 400; + private const int activate_delay = 200; private const int fadeout_delay = 200; private bool fired; From 8c67f58e2d1179f5403e94933dea70df65d90e75 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 15 Aug 2019 18:25:31 +0900 Subject: [PATCH 2388/5608] Disable frame-stable playback in the editor --- osu.Game/Rulesets/Edit/DrawableEditRuleset.cs | 6 ++++++ osu.Game/Rulesets/UI/DrawableRuleset.cs | 9 +++++++++ osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs index 2200caeb20..e85ebb5f3a 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -57,7 +58,12 @@ namespace osu.Game.Rulesets.Edit this.drawableRuleset = drawableRuleset; InternalChild = drawableRuleset; + } + [BackgroundDependencyLoader] + private void load() + { + drawableRuleset.FrameStablePlayback = false; Playfield.DisplayJudgements.Value = false; } diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index ac81fdc719..eb14bd1f24 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -62,6 +62,15 @@ namespace osu.Game.Rulesets.UI public override GameplayClock FrameStableClock => frameStabilityContainer.GameplayClock; + /// + /// Whether to enable frame-stable playback. + /// + internal bool FrameStablePlayback + { + get => frameStabilityContainer.FrameStablePlayback; + set => frameStabilityContainer.FrameStablePlayback = value; + } + /// /// Invoked when a has been applied by a . /// diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 1cc56fff8b..7c143aa158 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -24,6 +24,11 @@ namespace osu.Game.Rulesets.UI ///

    public List Scores { get; set; } + public DifficultyRating DifficultyRating + { + get + { + var rating = StarDifficulty; + + if (rating < 2.0) return DifficultyRating.Easy; + if (rating < 2.7) return DifficultyRating.Normal; + if (rating < 4.0) return DifficultyRating.Hard; + if (rating < 5.3) return DifficultyRating.Insane; + if (rating < 6.5) return DifficultyRating.Expert; + + return DifficultyRating.ExpertPlus; + } + } + public override string ToString() => $"{Metadata} [{Version}]".Trim(); public bool Equals(BeatmapInfo other) diff --git a/osu.Game/Beatmaps/DifficultyRating.cs b/osu.Game/Beatmaps/DifficultyRating.cs new file mode 100644 index 0000000000..f0ee0ad705 --- /dev/null +++ b/osu.Game/Beatmaps/DifficultyRating.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. + +namespace osu.Game.Beatmaps +{ + public enum DifficultyRating + { + Easy, + Normal, + Hard, + Insane, + Expert, + ExpertPlus + } +} diff --git a/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs b/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs deleted file mode 100644 index 26ffcca1ec..0000000000 --- a/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osu.Framework.Allocation; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osuTK.Graphics; - -namespace osu.Game.Beatmaps.Drawables -{ - public abstract class DifficultyColouredContainer : Container, IHasAccentColour - { - public Color4 AccentColour { get; set; } - - private readonly BeatmapInfo beatmap; - private OsuColour palette; - - protected DifficultyColouredContainer(BeatmapInfo beatmap) - { - this.beatmap = beatmap; - } - - [BackgroundDependencyLoader] - private void load(OsuColour palette) - { - if (palette == null) - throw new ArgumentNullException(nameof(palette)); - - this.palette = palette; - AccentColour = getColour(beatmap); - } - - private enum DifficultyRating - { - Easy, - Normal, - Hard, - Insane, - Expert, - ExpertPlus - } - - private DifficultyRating getDifficultyRating(BeatmapInfo beatmap) - { - if (beatmap == null) - throw new ArgumentNullException(nameof(beatmap)); - - var rating = beatmap.StarDifficulty; - - if (rating < 2.0) return DifficultyRating.Easy; - if (rating < 2.7) return DifficultyRating.Normal; - if (rating < 4.0) return DifficultyRating.Hard; - if (rating < 5.3) return DifficultyRating.Insane; - if (rating < 6.5) return DifficultyRating.Expert; - - return DifficultyRating.ExpertPlus; - } - - private Color4 getColour(BeatmapInfo beatmap) - { - switch (getDifficultyRating(beatmap)) - { - case DifficultyRating.Easy: - return palette.Green; - - default: - case DifficultyRating.Normal: - return palette.Blue; - - case DifficultyRating.Hard: - return palette.Yellow; - - case DifficultyRating.Insane: - return palette.Pink; - - case DifficultyRating.Expert: - return palette.Purple; - - case DifficultyRating.ExpertPlus: - return palette.Gray0; - } - } - } -} diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 0a0ad28fdf..2b0a0a5ac1 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Rulesets; using osuTK; @@ -16,23 +17,25 @@ using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables { - public class DifficultyIcon : DifficultyColouredContainer + public class DifficultyIcon : Container { + private readonly BeatmapInfo beatmap; private readonly RulesetInfo ruleset; public DifficultyIcon(BeatmapInfo beatmap, RulesetInfo ruleset = null) - : base(beatmap) { if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); + this.beatmap = beatmap; + this.ruleset = ruleset ?? beatmap.Ruleset; Size = new Vector2(20); } [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { Children = new Drawable[] { @@ -52,7 +55,7 @@ namespace osu.Game.Beatmaps.Drawables Child = new Box { RelativeSizeAxes = Axes.Both, - Colour = AccentColour, + Colour = colours.ForDifficultyRating(beatmap.DifficultyRating), }, }, new ConstrainedIconContainer diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 63ec24f84f..af66f57f14 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Game.Beatmaps; using osuTK.Graphics; namespace osu.Game.Graphics @@ -37,6 +38,31 @@ namespace osu.Game.Graphics } } + public Color4 ForDifficultyRating(DifficultyRating difficulty) + { + switch (difficulty) + { + case DifficultyRating.Easy: + return Green; + + default: + case DifficultyRating.Normal: + return Blue; + + case DifficultyRating.Hard: + return Yellow; + + case DifficultyRating.Insane: + return Pink; + + case DifficultyRating.Expert: + return Purple; + + case DifficultyRating.ExpertPlus: + return Gray0; + } + } + // See https://github.com/ppy/osu-web/blob/master/resources/assets/less/colors.less public readonly Color4 PurpleLighter = FromHex(@"eeeeff"); public readonly Color4 PurpleLight = FromHex(@"aa88ff"); diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index a9e4eaa9b3..5f6307e3b4 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -402,31 +402,35 @@ namespace osu.Game.Screens.Select } } - private class DifficultyColourBar : DifficultyColouredContainer + private class DifficultyColourBar : Container { + private readonly BeatmapInfo beatmap; + public DifficultyColourBar(BeatmapInfo beatmap) - : base(beatmap) { + this.beatmap = beatmap; } [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { const float full_opacity_ratio = 0.7f; + var difficultyColour = colours.ForDifficultyRating(beatmap.DifficultyRating); + Children = new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, - Colour = AccentColour, + Colour = difficultyColour, Width = full_opacity_ratio, }, new Box { RelativeSizeAxes = Axes.Both, RelativePositionAxes = Axes.Both, - Colour = AccentColour, + Colour = difficultyColour, Alpha = 0.5f, X = full_opacity_ratio, Width = 1 - full_opacity_ratio, From 50046d5f69bd206f0480271758b0488b3c97f61a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Aug 2019 15:20:27 +0900 Subject: [PATCH 2409/5608] Use new tooltip style --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 9b265de45b..37fbc617cc 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -32,14 +32,17 @@ namespace osu.Game.Beatmaps.Drawables this.beatmap = beatmap; this.ruleset = ruleset ?? beatmap.Ruleset; - TooltipText = shouldShowTooltip ? $"{beatmap.Version}${beatmap.StarDifficulty:0.##}" : String.Empty; + if (shouldShowTooltip) + TooltipContent = beatmap; Size = new Vector2(20); } public string TooltipText { get; set; } - public ITooltip GetCustomTooltip() => new DifficultyIconTooltip(AccentColour); + public ITooltip GetCustomTooltip() => new DifficultyIconTooltip(); + + public object TooltipContent { get; set; } [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -81,9 +84,14 @@ namespace osu.Game.Beatmaps.Drawables private readonly OsuSpriteText difficultyName, starRating; private readonly Box background; - public string TooltipText { get; set; } + private readonly FillFlowContainer difficultyFlow; - public DifficultyIconTooltip(Color4 difficultyColour) + public string TooltipText + { + set { } + } + + public DifficultyIconTooltip() { AutoSizeAxes = Axes.Both; Masking = true; @@ -108,13 +116,12 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 16, weight: FontWeight.Bold), }, - new FillFlowContainer + difficultyFlow = new FillFlowContainer { AutoSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, Direction = FillDirection.Horizontal, - Colour = difficultyColour, Children = new Drawable[] { starRating = new OsuSpriteText @@ -138,17 +145,29 @@ namespace osu.Game.Beatmaps.Drawables }; } + private OsuColour colours; + [BackgroundDependencyLoader] private void load(OsuColour colours) { + this.colours = colours; background.Colour = colours.GreyCarmineDark; } + public bool SetContent(object content) + { + if (!(content is BeatmapInfo beatmap)) + return false; + + difficultyName.Text = beatmap.Version; + starRating.Text = $"{beatmap.StarDifficulty:0.##}"; + difficultyFlow.Colour = colours.ForDifficultyRating(beatmap.DifficultyRating); + + return true; + } + public void Refresh() { - var info = TooltipText.Split('$'); - difficultyName.Text = info[0]; - starRating.Text = info[1]; } public void Move(Vector2 pos) => Position = pos; From 097763bb1ca9d7215b9ad7ba9bbe14554f9f24df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Aug 2019 15:29:39 +0900 Subject: [PATCH 2410/5608] Add auto size duration --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 37fbc617cc..962cb33a83 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -106,6 +106,8 @@ namespace osu.Game.Beatmaps.Drawables new FillFlowContainer { AutoSizeAxes = Axes.Both, + AutoSizeDuration = 200, + AutoSizeEasing = Easing.OutQuint, Direction = FillDirection.Vertical, Padding = new MarginPadding(10), Children = new Drawable[] From 87dc6499faabccc71e3062a2365446d31945a281 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Aug 2019 15:34:02 +0900 Subject: [PATCH 2411/5608] Fix json decoding being a bit too eager to consume --- osu.Game/Beatmaps/BeatmapInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 700f981088..198046df4f 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -129,6 +129,7 @@ namespace osu.Game.Beatmaps ///
    public List Scores { get; set; } + [JsonIgnore] public DifficultyRating DifficultyRating { get From f7024b513efeabd0a19b97716725770ab86138bd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 01:43:43 +0300 Subject: [PATCH 2412/5608] Visual improvements --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 83 +++++++++++--------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 4cac73c975..ad72063313 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -14,14 +14,15 @@ using osu.Game.Beatmaps; using osu.Framework.Bindables; using osu.Framework.Allocation; using osu.Framework.Graphics.Colour; +using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Screens.Play.HUD { public class HitErrorDisplay : Container { - private const int bar_width = 4; - private const int bar_height = 250; + private const int bar_width = 3; + private const int bar_height = 200; private const int spacing = 3; public HitWindows HitWindows { get; set; } @@ -31,6 +32,7 @@ namespace osu.Game.Screens.Play.HUD private readonly bool mirrored; private readonly SpriteIcon arrow; + private readonly FillFlowContainer bar; private readonly List judgementOffsets = new List(); public HitErrorDisplay(bool mirrored = false) @@ -41,43 +43,10 @@ namespace osu.Game.Screens.Play.HUD Children = new Drawable[] { - new FillFlowContainer + bar = new FillFlowContainer { RelativeSizeAxes = Axes.Both, Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0), Color4.Orange), - Height = 0.3f - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Green, - Height = 0.15f - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Blue, - Height = 0.1f - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Green, - Height = 0.15f - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Orange, Color4.Black.Opacity(0)), - Height = 0.3f - } - } }, arrow = new SpriteIcon { @@ -86,11 +55,49 @@ namespace osu.Game.Screens.Play.HUD X = mirrored ? -spacing : spacing, RelativePositionAxes = Axes.Y, Icon = mirrored ? FontAwesome.Solid.ChevronRight : FontAwesome.Solid.ChevronLeft, - Size = new Vector2(10), + Size = new Vector2(8), } }; } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + bar.AddRange(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(colours.Yellow.Opacity(0), colours.Yellow), + Height = 0.3f + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Green, + Height = 0.15f + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.BlueLight, + Height = 0.1f + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Green, + Height = 0.15f + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(colours.Yellow, colours.Yellow.Opacity(0)), + Height = 0.3f + } + }); + } + protected override void LoadComplete() { base.LoadComplete(); @@ -117,7 +124,7 @@ namespace osu.Game.Screens.Play.HUD Anchor = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, Origin = mirrored ? Anchor.CentreLeft : Anchor.CentreRight, Masking = true, - Size = new Vector2(10, 2), + Size = new Vector2(8, 2), RelativePositionAxes = Axes.Y, Y = getRelativeJudgementPosition(judgement.TimeOffset), X = mirrored ? spacing : -spacing, From 906984ad952f5df2b3c6becf66c30339af2cef36 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 02:49:07 +0300 Subject: [PATCH 2413/5608] Fix the math --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 35 +++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index ad72063313..6ef102e575 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -16,6 +16,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Colour; using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions; +using System.Linq; namespace osu.Game.Screens.Play.HUD { @@ -30,6 +31,9 @@ namespace osu.Game.Screens.Play.HUD [Resolved] private Bindable beatmap { get; set; } + [Resolved] + private OsuColour colours { get; set; } + private readonly bool mirrored; private readonly SpriteIcon arrow; private readonly FillFlowContainer bar; @@ -60,50 +64,46 @@ namespace osu.Game.Screens.Play.HUD }; } - [BackgroundDependencyLoader] - private void load(OsuColour colours) + protected override void LoadComplete() { + base.LoadComplete(); + HitWindows.SetDifficulty(beatmap.Value.BeatmapInfo.BaseDifficulty.OverallDifficulty); + bar.AddRange(new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical(colours.Yellow.Opacity(0), colours.Yellow), - Height = 0.3f + Height = (float)((HitWindows.Meh - HitWindows.Good) / (HitWindows.Meh * 2)) }, new Box { RelativeSizeAxes = Axes.Both, Colour = colours.Green, - Height = 0.15f + Height = (float)((HitWindows.Good - HitWindows.Great) / (HitWindows.Meh * 2)) }, new Box { RelativeSizeAxes = Axes.Both, Colour = colours.BlueLight, - Height = 0.1f + Height = (float)(HitWindows.Great / HitWindows.Meh) }, new Box { RelativeSizeAxes = Axes.Both, Colour = colours.Green, - Height = 0.15f + Height = (float)((HitWindows.Good - HitWindows.Great) / (HitWindows.Meh * 2)) }, new Box { RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical(colours.Yellow, colours.Yellow.Opacity(0)), - Height = 0.3f + Height = (float)((HitWindows.Meh - HitWindows.Good) / (HitWindows.Meh * 2)) } }); } - protected override void LoadComplete() - { - base.LoadComplete(); - HitWindows.SetDifficulty(beatmap.Value.BeatmapInfo.BaseDifficulty.OverallDifficulty); - } - public void OnNewJudgement(JudgementResult judgement) { if (!judgement.IsHit) @@ -135,7 +135,7 @@ namespace osu.Game.Screens.Play.HUD } }; - private float getRelativeJudgementPosition(double value) => (float)(value / HitWindows.Miss); + private float getRelativeJudgementPosition(double value) => (float)(value / HitWindows.Meh); private double calculateArrowPosition(JudgementResult judgement) { @@ -144,12 +144,7 @@ namespace osu.Game.Screens.Play.HUD judgementOffsets.Add(judgement.TimeOffset); - double offsets = 0; - - foreach (var offset in judgementOffsets) - offsets += offset; - - return offsets / judgementOffsets.Count; + return judgementOffsets.Average(); } } } From 50133ba8636159d4b3d79eda20ced928a4fdbf68 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 02:57:12 +0300 Subject: [PATCH 2414/5608] naming adjustments --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 6ef102e575..1dd77469ca 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -22,6 +22,7 @@ namespace osu.Game.Screens.Play.HUD { public class HitErrorDisplay : Container { + private const int stored_judgements_amount = 5; private const int bar_width = 3; private const int bar_height = 200; private const int spacing = 3; @@ -104,19 +105,19 @@ namespace osu.Game.Screens.Play.HUD }); } - public void OnNewJudgement(JudgementResult judgement) + public void OnNewJudgement(JudgementResult newJudgement) { - if (!judgement.IsHit) + if (!newJudgement.IsHit) return; Container judgementLine; - Add(judgementLine = CreateJudgementLine(judgement)); + Add(judgementLine = CreateJudgementLine(newJudgement)); judgementLine.FadeOut(10000, Easing.OutQuint); judgementLine.Expire(); - arrow.MoveToY(getRelativeJudgementPosition(calculateArrowPosition(judgement)), 500, Easing.OutQuint); + arrow.MoveToY(getRelativeJudgementPosition(calculateArrowPosition(newJudgement)), 500, Easing.OutQuint); } protected virtual Container CreateJudgementLine(JudgementResult judgement) => new CircularContainer @@ -137,12 +138,12 @@ namespace osu.Game.Screens.Play.HUD private float getRelativeJudgementPosition(double value) => (float)(value / HitWindows.Meh); - private double calculateArrowPosition(JudgementResult judgement) + private double calculateArrowPosition(JudgementResult newJudgement) { - if (judgementOffsets.Count > 5) + if (judgementOffsets.Count > stored_judgements_amount) judgementOffsets.RemoveAt(0); - judgementOffsets.Add(judgement.TimeOffset); + judgementOffsets.Add(newJudgement.TimeOffset); return judgementOffsets.Average(); } From ee5568e5968489b8dbce42023f4db425f28fff2c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 14:43:34 +0300 Subject: [PATCH 2415/5608] Use Queue instead of List for stored Judgements --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 1dd77469ca..7bb1d30f22 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -38,7 +38,7 @@ namespace osu.Game.Screens.Play.HUD private readonly bool mirrored; private readonly SpriteIcon arrow; private readonly FillFlowContainer bar; - private readonly List judgementOffsets = new List(); + private readonly Queue judgementOffsets = new Queue(); public HitErrorDisplay(bool mirrored = false) { @@ -117,7 +117,7 @@ namespace osu.Game.Screens.Play.HUD judgementLine.FadeOut(10000, Easing.OutQuint); judgementLine.Expire(); - arrow.MoveToY(getRelativeJudgementPosition(calculateArrowPosition(newJudgement)), 500, Easing.OutQuint); + arrow.MoveToY(calculateArrowPosition(newJudgement), 500, Easing.OutQuint); } protected virtual Container CreateJudgementLine(JudgementResult judgement) => new CircularContainer @@ -138,14 +138,14 @@ namespace osu.Game.Screens.Play.HUD private float getRelativeJudgementPosition(double value) => (float)(value / HitWindows.Meh); - private double calculateArrowPosition(JudgementResult newJudgement) + private float calculateArrowPosition(JudgementResult newJudgement) { if (judgementOffsets.Count > stored_judgements_amount) - judgementOffsets.RemoveAt(0); + judgementOffsets.Dequeue(); - judgementOffsets.Add(newJudgement.TimeOffset); + judgementOffsets.Enqueue(newJudgement.TimeOffset); - return judgementOffsets.Average(); + return getRelativeJudgementPosition(judgementOffsets.Average()); } } } From a59a14c9e6f518ab3c99871c5ddae5617dfefc75 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 15:01:04 +0300 Subject: [PATCH 2416/5608] Add setting to enable/disable hit error visibility --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ osu.Game/Configuration/ScoreMeterType.cs | 8 +++++-- .../Sections/Gameplay/GeneralSettings.cs | 5 ++++ osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 24 +++++++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 19f46c1d6a..bffbce2a52 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -79,6 +79,7 @@ namespace osu.Game.Configuration Set(OsuSetting.ShowInterface, true); Set(OsuSetting.ShowHealthDisplayWhenCantFail, true); Set(OsuSetting.KeyOverlay, false); + Set(OsuSetting.ScoreMeter, ScoreMeterType.HitError); Set(OsuSetting.FloatingComments, false); @@ -132,6 +133,7 @@ namespace osu.Game.Configuration BlurLevel, ShowStoryboard, KeyOverlay, + ScoreMeter, FloatingComments, ShowInterface, ShowHealthDisplayWhenCantFail, diff --git a/osu.Game/Configuration/ScoreMeterType.cs b/osu.Game/Configuration/ScoreMeterType.cs index 21a63fb3ed..e78220c9c9 100644 --- a/osu.Game/Configuration/ScoreMeterType.cs +++ b/osu.Game/Configuration/ScoreMeterType.cs @@ -1,12 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.ComponentModel; + namespace osu.Game.Configuration { public enum ScoreMeterType { + [Description("None")] None, - Colour, - Error + + [Description("Hit Error")] + HitError } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 9142492610..520a8852b3 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -44,6 +44,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay LabelText = "Always show key overlay", Bindable = config.GetBindable(OsuSetting.KeyOverlay) }, + new SettingsEnumDropdown + { + LabelText = "Score meter type", + Bindable = config.GetBindable(OsuSetting.ScoreMeter) + }, new SettingsEnumDropdown { LabelText = "Score display mode", diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 7bb1d30f22..9a5198b7cc 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -17,6 +17,7 @@ using osu.Framework.Graphics.Colour; using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions; using System.Linq; +using osu.Game.Configuration; namespace osu.Game.Screens.Play.HUD { @@ -40,6 +41,8 @@ namespace osu.Game.Screens.Play.HUD private readonly FillFlowContainer bar; private readonly Queue judgementOffsets = new Queue(); + private readonly Bindable type = new Bindable(); + public HitErrorDisplay(bool mirrored = false) { this.mirrored = mirrored; @@ -65,6 +68,12 @@ namespace osu.Game.Screens.Play.HUD }; } + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + config.BindWith(OsuSetting.ScoreMeter, type); + } + protected override void LoadComplete() { base.LoadComplete(); @@ -103,6 +112,21 @@ namespace osu.Game.Screens.Play.HUD Height = (float)((HitWindows.Meh - HitWindows.Good) / (HitWindows.Meh * 2)) } }); + + type.BindValueChanged(onTypeChanged, true); + } + + private void onTypeChanged(ValueChangedEvent type) + { + switch (type.NewValue) + { + case ScoreMeterType.None: + this.FadeOut(200, Easing.OutQuint); + break; + case ScoreMeterType.HitError: + this.FadeIn(200, Easing.OutQuint); + break; + } } public void OnNewJudgement(JudgementResult newJudgement) From 8740ebd13f2fcac9a46151cf0991031e3edbdf32 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 15:45:18 +0300 Subject: [PATCH 2417/5608] Simplify layout --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 72 +++++++++++++------- osu.Game/Screens/Play/HUDOverlay.cs | 12 ++-- 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 9a5198b7cc..1a4d2a45c5 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -21,10 +21,11 @@ using osu.Game.Configuration; namespace osu.Game.Screens.Play.HUD { - public class HitErrorDisplay : Container + public class HitErrorDisplay : CompositeDrawable { private const int stored_judgements_amount = 5; private const int bar_width = 3; + private const int judgement_line_width = 8; private const int bar_height = 200; private const int spacing = 3; @@ -36,36 +37,57 @@ namespace osu.Game.Screens.Play.HUD [Resolved] private OsuColour colours { get; set; } - private readonly bool mirrored; private readonly SpriteIcon arrow; private readonly FillFlowContainer bar; + private readonly Container judgementsContainer; private readonly Queue judgementOffsets = new Queue(); private readonly Bindable type = new Bindable(); - public HitErrorDisplay(bool mirrored = false) + public HitErrorDisplay(bool reversed = false) { - this.mirrored = mirrored; + AutoSizeAxes = Axes.Both; - Size = new Vector2(bar_width, bar_height); - - Children = new Drawable[] + AddInternal(new FillFlowContainer { - bar = new FillFlowContainer + AutoSizeAxes = Axes.X, + Height = bar_height, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(spacing, 0), + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - }, - arrow = new SpriteIcon - { - Anchor = mirrored ? Anchor.CentreLeft : Anchor.CentreRight, - Origin = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, - X = mirrored ? -spacing : spacing, - RelativePositionAxes = Axes.Y, - Icon = mirrored ? FontAwesome.Solid.ChevronRight : FontAwesome.Solid.ChevronLeft, - Size = new Vector2(8), + judgementsContainer = new Container + { + Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Width = judgement_line_width, + RelativeSizeAxes = Axes.Y, + }, + bar = new FillFlowContainer + { + Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Width = bar_width, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + }, + new Container + { + Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Child = arrow = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.Y, + Icon = reversed ? FontAwesome.Solid.ChevronRight : FontAwesome.Solid.ChevronLeft, + Size = new Vector2(8), + } + }, } - }; + }); } [BackgroundDependencyLoader] @@ -136,7 +158,7 @@ namespace osu.Game.Screens.Play.HUD Container judgementLine; - Add(judgementLine = CreateJudgementLine(newJudgement)); + judgementsContainer.Add(judgementLine = CreateJudgementLine(newJudgement)); judgementLine.FadeOut(10000, Easing.OutQuint); judgementLine.Expire(); @@ -146,13 +168,13 @@ namespace osu.Game.Screens.Play.HUD protected virtual Container CreateJudgementLine(JudgementResult judgement) => new CircularContainer { - Anchor = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = mirrored ? Anchor.CentreLeft : Anchor.CentreRight, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Masking = true, - Size = new Vector2(8, 2), + RelativeSizeAxes = Axes.X, + Height = 2, RelativePositionAxes = Axes.Y, Y = getRelativeJudgementPosition(judgement.TimeOffset), - X = mirrored ? spacing : -spacing, Child = new Box { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index a9a469486e..50480c001c 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -86,8 +86,8 @@ namespace osu.Game.Screens.Play HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), ModDisplay = CreateModsContainer(), - LeftHitErrorDisplay = CreateAccuracyBar(false), - RightHitErrorDisplay = CreateAccuracyBar(), + LeftHitErrorDisplay = CreateHitErrorDisplay(false), + RightHitErrorDisplay = CreateHitErrorDisplay(), } }, PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), @@ -260,11 +260,11 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20, Right = 10 }, }; - protected virtual HitErrorDisplay CreateAccuracyBar(bool mirrored = true) => new HitErrorDisplay(mirrored) + protected virtual HitErrorDisplay CreateHitErrorDisplay(bool reversed = true) => new HitErrorDisplay(reversed) { - Anchor = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = mirrored ? Anchor.CentreRight : Anchor.CentreLeft, - Margin = new MarginPadding { Horizontal = 30 } + Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Margin = new MarginPadding { Horizontal = 20 } }; protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); From af2ffac03a5fe99a4d62e0508e3e0f1e215d2be3 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 18 Aug 2019 14:52:26 +0200 Subject: [PATCH 2418/5608] Add global Top and Horizontal padding to NewsContent --- osu.Game/Overlays/News/NewsContent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/News/NewsContent.cs b/osu.Game/Overlays/News/NewsContent.cs index 16a8ed84b8..5ff210f9f5 100644 --- a/osu.Game/Overlays/News/NewsContent.cs +++ b/osu.Game/Overlays/News/NewsContent.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.News RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; - Padding = new MarginPadding { Bottom = 100 }; + Padding = new MarginPadding { Bottom = 100, Top = 20, Horizontal = 50 }; } } } From 55cd1cecdfb57c6ba8794ce66946b24be2d8fe4d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 15:53:42 +0300 Subject: [PATCH 2419/5608] Add missing blank line --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 1a4d2a45c5..2959a9aca7 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -145,6 +145,7 @@ namespace osu.Game.Screens.Play.HUD case ScoreMeterType.None: this.FadeOut(200, Easing.OutQuint); break; + case ScoreMeterType.HitError: this.FadeIn(200, Easing.OutQuint); break; From 6c60db550ff9c3e76abdc89add98d6f26e415b28 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 16:24:13 +0300 Subject: [PATCH 2420/5608] Fix crash if ruleset has no Meh hit windows --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 21 ++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 2959a9aca7..2ed06209de 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -107,37 +107,46 @@ namespace osu.Game.Screens.Play.HUD { RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical(colours.Yellow.Opacity(0), colours.Yellow), - Height = (float)((HitWindows.Meh - HitWindows.Good) / (HitWindows.Meh * 2)) + Height = (float)((getMehHitWindows() - HitWindows.Good) / (getMehHitWindows() * 2)) }, new Box { RelativeSizeAxes = Axes.Both, Colour = colours.Green, - Height = (float)((HitWindows.Good - HitWindows.Great) / (HitWindows.Meh * 2)) + Height = (float)((HitWindows.Good - HitWindows.Great) / (getMehHitWindows() * 2)) }, new Box { RelativeSizeAxes = Axes.Both, Colour = colours.BlueLight, - Height = (float)(HitWindows.Great / HitWindows.Meh) + Height = (float)(HitWindows.Great / getMehHitWindows()) }, new Box { RelativeSizeAxes = Axes.Both, Colour = colours.Green, - Height = (float)((HitWindows.Good - HitWindows.Great) / (HitWindows.Meh * 2)) + Height = (float)((HitWindows.Good - HitWindows.Great) / (getMehHitWindows() * 2)) }, new Box { RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical(colours.Yellow, colours.Yellow.Opacity(0)), - Height = (float)((HitWindows.Meh - HitWindows.Good) / (HitWindows.Meh * 2)) + Height = (float)((getMehHitWindows() - HitWindows.Good) / (getMehHitWindows() * 2)) } }); type.BindValueChanged(onTypeChanged, true); } + private double getMehHitWindows() + { + // In case if ruleset has no Meh hit windows (like Taiko) + if (HitWindows.Meh == 0) + return HitWindows.Good + 40; + + return HitWindows.Meh; + } + private void onTypeChanged(ValueChangedEvent type) { switch (type.NewValue) @@ -183,7 +192,7 @@ namespace osu.Game.Screens.Play.HUD } }; - private float getRelativeJudgementPosition(double value) => (float)(value / HitWindows.Meh); + private float getRelativeJudgementPosition(double value) => (float)(value / getMehHitWindows()); private float calculateArrowPosition(JudgementResult newJudgement) { From dd6351b8caa83e917152a74220ed1a04fe56f3f3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 16:51:16 +0300 Subject: [PATCH 2421/5608] Apply suggested changes --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 16 +++++++++------- osu.Game/Screens/Play/HUDOverlay.cs | 18 +++++++++--------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 2ed06209de..1a3682351b 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -27,6 +27,9 @@ namespace osu.Game.Screens.Play.HUD private const int bar_width = 3; private const int judgement_line_width = 8; private const int bar_height = 200; + private const int fade_duration = 200; + private const int arrow_move_duration = 500; + private const int judgement_life_time = 10000; private const int spacing = 3; public HitWindows HitWindows { get; set; } @@ -152,11 +155,11 @@ namespace osu.Game.Screens.Play.HUD switch (type.NewValue) { case ScoreMeterType.None: - this.FadeOut(200, Easing.OutQuint); + this.FadeOut(fade_duration, Easing.OutQuint); break; case ScoreMeterType.HitError: - this.FadeIn(200, Easing.OutQuint); + this.FadeIn(fade_duration, Easing.OutQuint); break; } } @@ -166,14 +169,13 @@ namespace osu.Game.Screens.Play.HUD if (!newJudgement.IsHit) return; - Container judgementLine; + var judgementLine = CreateJudgementLine(newJudgement); - judgementsContainer.Add(judgementLine = CreateJudgementLine(newJudgement)); + judgementsContainer.Add(judgementLine); - judgementLine.FadeOut(10000, Easing.OutQuint); - judgementLine.Expire(); + judgementLine.FadeOut(judgement_life_time, Easing.OutQuint).Expire(); - arrow.MoveToY(calculateArrowPosition(newJudgement), 500, Easing.OutQuint); + arrow.MoveToY(calculateArrowPosition(newJudgement), arrow_move_duration, Easing.OutQuint); } protected virtual Container CreateJudgementLine(JudgementResult judgement) => new CircularContainer diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 50480c001c..114dc86757 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -276,17 +277,16 @@ namespace osu.Game.Screens.Play ComboCounter?.Current.BindTo(processor.Combo); HealthDisplay?.Current.BindTo(processor.Health); - if (LeftHitErrorDisplay != null) - { - processor.NewJudgement += LeftHitErrorDisplay.OnNewJudgement; - LeftHitErrorDisplay.HitWindows = processor.CreateHitWindows(); - } + var hitWindows = processor.CreateHitWindows(); - if (RightHitErrorDisplay != null) + visibilityContainer.ForEach(drawable => { - processor.NewJudgement += RightHitErrorDisplay.OnNewJudgement; - RightHitErrorDisplay.HitWindows = processor.CreateHitWindows(); - } + if (drawable is HitErrorDisplay) + { + processor.NewJudgement += (drawable as HitErrorDisplay).OnNewJudgement; + (drawable as HitErrorDisplay).HitWindows = hitWindows; + } + }); if (HealthDisplay is StandardHealthDisplay shd) processor.NewJudgement += shd.Flash; From 4c817b18b7f217ef9c95c01c867d8e4442c7ad18 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 17:03:11 +0300 Subject: [PATCH 2422/5608] Use direct cast --- osu.Game/Screens/Play/HUDOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 114dc86757..be291003b5 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -283,8 +283,8 @@ namespace osu.Game.Screens.Play { if (drawable is HitErrorDisplay) { - processor.NewJudgement += (drawable as HitErrorDisplay).OnNewJudgement; - (drawable as HitErrorDisplay).HitWindows = hitWindows; + processor.NewJudgement += ((HitErrorDisplay)drawable).OnNewJudgement; + ((HitErrorDisplay)drawable).HitWindows = hitWindows; } }); From 3fcd786198a60b61cd6179f56294b0b12d209808 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 18 Aug 2019 19:32:56 +0200 Subject: [PATCH 2423/5608] Take lease on WorkingBeatmap during intro screens to prevent weird interactions with Playback control. --- osu.Game/Screens/Menu/IntroScreen.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 27f3c9a45b..a621e29cf8 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -28,11 +28,18 @@ namespace osu.Game.Screens.Menu private Bindable menuVoice; + private LeasedBindable beatmap; + + public new Bindable Beatmap { get => beatmap; } + protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack(); [BackgroundDependencyLoader] private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game) { + //we take a lease on the beatmap bindable to prevent music playback from changing / pausing music during intros, as it is causing weird interactions with certains intros + beatmap = base.Beatmap.BeginLease(false); + menuVoice = config.GetBindable(OsuSetting.MenuVoice); seeya = audio.Samples.Get(@"seeya"); } @@ -108,6 +115,8 @@ namespace osu.Game.Screens.Menu protected void LoadMenu() { DidLoadMenu = true; + beatmap.Return(); //we return the lease to the beatmap bindable as we're pushing the main menu. + this.Push(mainMenu); } } From 2393bbc69b15e1f3421f3d4b140393bbaa8462ac Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 21:27:53 +0300 Subject: [PATCH 2424/5608] Expand APIKudosuHistory --- .../Requests/GetUserKudosuHistoryRequest.cs | 10 ++++ .../Requests/Responses/APIKudosuHistory.cs | 46 +++++++++++++++++-- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs index e90e297672..af37bd4b51 100644 --- a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs @@ -18,4 +18,14 @@ namespace osu.Game.Online.API.Requests protected override string Target => $"users/{userId}/kudosu"; } + + public enum KudosuAction + { + Give, + VoteGive, + Reset, + VoteReset, + DenyKudosuReset, + Revoke, + } } diff --git a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs index 271dcc320e..d02f71c339 100644 --- a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs +++ b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs @@ -2,19 +2,59 @@ // See the LICENCE file in the repository root for full licence text. using System; +using Humanizer; using Newtonsoft.Json; namespace osu.Game.Online.API.Requests.Responses { public class APIKudosuHistory { - [JsonProperty("id")] - public int ID; - [JsonProperty("created_at")] public DateTimeOffset CreatedAt; [JsonProperty("amount")] + private int amount + { + set => Amount = Math.Abs(value); + } + public int Amount; + + [JsonProperty("post")] + public ModdingPost Post; + + public class ModdingPost + { + [JsonProperty("url")] + public string Url; + + [JsonProperty("title")] + public string Title; + } + + [JsonProperty("giver")] + public KudosuGiver Giver; + + public class KudosuGiver + { + [JsonProperty("url")] + public string Url; + + [JsonProperty("username")] + public string Username; + } + + [JsonProperty("action")] + private string action + { + set + { + string parsed = value.Contains(".") ? value.Split('.')[0].Pascalize() + value.Split('.')[1].Pascalize() : value.Pascalize(); + + Action = (KudosuAction)Enum.Parse(typeof(KudosuAction), parsed); + } + } + + public KudosuAction Action; } } From be97804180f00c93818ea91b9afd58037e27c7dd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 21:28:07 +0300 Subject: [PATCH 2425/5608] Implement text formatting --- .../Kudosu/DrawableKudosuHistoryItem.cs | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index 1671073242..9b68131515 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.API.Requests; using osu.Game.Online.Chat; namespace osu.Game.Overlays.Profile.Sections.Kudosu @@ -51,6 +52,45 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu AutoSizeAxes = Axes.X, }; - private MessageFormatter.MessageFormatterResult createMessage() => MessageFormatter.FormatText($@"{historyItem.Amount}"); + private MessageFormatter.MessageFormatterResult createMessage() + { + string postLinkTemplate() => $"[{historyItem.Post.Url} {historyItem.Post.Title}]"; + string userLinkTemplate() => $"[{historyItem.Giver?.Url} {historyItem.Giver?.Username}]"; + + string message; + + switch (historyItem.Action) + { + case KudosuAction.Give: + message = $"Received {historyItem.Amount} kudosu from {userLinkTemplate()} for a post at {postLinkTemplate()}"; + break; + + case KudosuAction.VoteGive: + message = $"Received {historyItem.Amount} kudosu from obtaining votes in modding post of {postLinkTemplate()}"; + break; + + case KudosuAction.Reset: + message = $"Kudosu reset by {userLinkTemplate()} for the post {postLinkTemplate()}"; + break; + + case KudosuAction.VoteReset: + message = $"Lost {historyItem.Amount} kudosu from losing votes in modding post of {postLinkTemplate()}"; + break; + + case KudosuAction.DenyKudosuReset: + message = $"Denied {historyItem.Amount} kudosu from modding post {postLinkTemplate()}"; + break; + + case KudosuAction.Revoke: + message = $"Denied kudosu by {userLinkTemplate()} for the post {postLinkTemplate()}"; + break; + + default: + message = string.Empty; + break; + } + + return MessageFormatter.FormatText(message); + } } } From 4c9b621f43d9a702be1bd3149758a9e030f781bf Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 22:01:36 +0300 Subject: [PATCH 2426/5608] Fix some user links can't be opened inside the game --- osu.Game/Online/Chat/MessageFormatter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 4aaffdd161..db26945ef3 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -122,6 +122,7 @@ namespace osu.Game.Online.Chat return new LinkDetails(LinkAction.OpenBeatmapSet, args[3]); case "u": + case "users": return new LinkDetails(LinkAction.OpenUserProfile, args[3]); } } From 015406f4d2b7256ee0f7c0c9d2e0bb5445ab86ea Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 18 Aug 2019 22:02:59 +0300 Subject: [PATCH 2427/5608] Fix link parser --- osu.Game/Online/Chat/MessageFormatter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 4aaffdd161..db26945ef3 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -122,6 +122,7 @@ namespace osu.Game.Online.Chat return new LinkDetails(LinkAction.OpenBeatmapSet, args[3]); case "u": + case "users": return new LinkDetails(LinkAction.OpenUserProfile, args[3]); } } From a51fbfa31b52aefb18a8ec9d78f93f475b724de5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Aug 2019 10:46:28 +0900 Subject: [PATCH 2428/5608] Fix osu! default tooltips not displaying --- .../Graphics/Cursor/OsuTooltipContainer.cs | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs index cfcda892fd..57f39bb8c7 100644 --- a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs @@ -30,22 +30,24 @@ namespace osu.Game.Graphics.Cursor private readonly OsuSpriteText text; private bool instantMovement = true; - public override string TooltipText + public override bool SetContent(object content) { - set + if (!(content is string contentString)) + return false; + + if (contentString == text.Text) return true; + + text.Text = contentString; + + if (IsPresent) { - if (value == text.Text) return; - - text.Text = value; - - if (IsPresent) - { - AutoSizeDuration = 250; - background.FlashColour(OsuColour.Gray(0.4f), 1000, Easing.OutQuint); - } - else - AutoSizeDuration = 0; + AutoSizeDuration = 250; + background.FlashColour(OsuColour.Gray(0.4f), 1000, Easing.OutQuint); } + else + AutoSizeDuration = 0; + + return true; } public OsuTooltip() From 1f00793891e1488151e7817edd99cbd9a362dfd7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Aug 2019 11:30:04 +0900 Subject: [PATCH 2429/5608] Unpause music when changing selection at song select --- osu.Game/Overlays/MusicController.cs | 9 +++++++++ osu.Game/Screens/Select/SongSelect.cs | 13 +++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index f6208c46cb..6ad147735b 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -92,6 +92,15 @@ namespace osu.Game.Overlays }); } + /// + /// Start playing the current track (if not already playing). + /// + public void Play() + { + if (!IsPlaying) + TogglePause(); + } + /// /// Toggle pause / play. /// diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 8340814db9..edb0e6deb8 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -359,6 +359,7 @@ namespace osu.Game.Screens.Select return; beatmapNoDebounce = beatmap; + performUpdateSelected(); } @@ -586,10 +587,18 @@ namespace osu.Game.Screens.Select { Track track = Beatmap.Value.Track; - if ((!track.IsRunning || restart) && music?.IsUserPaused != true) + if (!track.IsRunning || restart) { track.RestartPoint = Beatmap.Value.Metadata.PreviewTime; - track.Restart(); + + if (music != null) + { + // use the global music controller (when available) to cancel a potential local user paused state. + music.SeekTo(track.RestartPoint); + music.Play(); + } + else + track.Restart(); } } From 7143497441a95db5f98d81797ed2966058671cf4 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Mon, 19 Aug 2019 10:32:01 +0700 Subject: [PATCH 2430/5608] Match up tooltip background color with OsuTooltipContainer --- 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 962cb33a83..3c3a7c056e 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -153,7 +153,7 @@ namespace osu.Game.Beatmaps.Drawables private void load(OsuColour colours) { this.colours = colours; - background.Colour = colours.GreyCarmineDark; + background.Colour = colours.Gray3; } public bool SetContent(object content) From be51fde2925a674d0fd31b6b24bb9e8aeca015ca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Aug 2019 13:22:32 +0900 Subject: [PATCH 2431/5608] Centre beatmap panels in profile overlay --- .../Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 1b6c1c99a6..8a6b52b7ee 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -46,8 +46,11 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps if (!s.OnlineBeatmapSetID.HasValue) continue; - var panel = new DirectGridPanel(s.ToBeatmapSet(Rulesets)); - ItemsContainer.Add(panel); + ItemsContainer.Add(new DirectGridPanel(s.ToBeatmapSet(Rulesets)) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }); } }); From 4356f2ef9fdf072fbacdc7e196edff4659bd9582 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Aug 2019 17:45:54 +0900 Subject: [PATCH 2432/5608] Add sample usage of looping skinnable --- osu.Game/Skinning/LegacySkin.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index b560fd4f84..a41812bad0 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.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; @@ -102,6 +102,10 @@ namespace osu.Game.Skinning return null; + case "Play/osu/sliderfollowcircle": + animatable = true; + break; + case "Play/Miss": componentName = "hit0"; animatable = true; @@ -149,8 +153,6 @@ namespace osu.Game.Skinning texture = GetTexture($"{componentName}-{i}"); } - // This comment can be removed once we have components which are looping - // ReSharper disable once ConditionIsAlwaysTrueOrFalse animation.Repeat = looping; return animation; From d224405bc611aa7f1c4be3df83b7b51136a74716 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Aug 2019 17:46:05 +0900 Subject: [PATCH 2433/5608] Rename const and make more available --- osu.Game/Skinning/LegacySkin.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index a41812bad0..2b9ed2aa8b 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.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; @@ -76,11 +76,12 @@ namespace osu.Game.Skinning Samples?.Dispose(); } + private const double default_frame_time = 1000 / 60d; + public override Drawable GetDrawableComponent(string componentName) { bool animatable = false; bool looping = true; - const double frametime = 1000 / 60d; switch (componentName) { @@ -145,7 +146,7 @@ namespace osu.Game.Skinning if (texture != null && animatable) { - var animation = new TextureAnimation { DefaultFrameLength = frametime }; + var animation = new TextureAnimation { DefaultFrameLength = default_frame_time }; for (int i = 1; texture != null; i++) { From d02b8d14f7e18ebc7292cf30e2243e4268d498e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Aug 2019 17:47:59 +0900 Subject: [PATCH 2434/5608] Avoid unnecessary texture retrieval for non-animated sprites --- osu.Game/Skinning/LegacySkin.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 2b9ed2aa8b..d47e100d0e 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -142,9 +142,9 @@ namespace osu.Game.Skinning }; } - var texture = GetTexture($"{componentName}-0"); + Texture texture; - if (texture != null && animatable) + if (animatable && (texture = GetTexture($"{componentName}-0")) != null) { var animation = new TextureAnimation { DefaultFrameLength = default_frame_time }; From 539a27a557738923c4805b5dadfc89bc2be4853f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Aug 2019 19:23:54 +0900 Subject: [PATCH 2435/5608] Refactor texture lookup code --- osu.Game/Skinning/LegacySkin.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index d47e100d0e..94421b1251 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.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; @@ -142,28 +142,31 @@ namespace osu.Game.Skinning }; } + return getAnimation(componentName, animatable, looping); + } + + private Drawable getAnimation(string componentName, bool animatable, bool looping, string animationSeparator = "-") + { Texture texture; - if (animatable && (texture = GetTexture($"{componentName}-0")) != null) + Texture getFrameTexture(int frame) => GetTexture($"{componentName}{animationSeparator}{frame}"); + + if (animatable && (texture = getFrameTexture(0)) != null) { var animation = new TextureAnimation { DefaultFrameLength = default_frame_time }; for (int i = 1; texture != null; i++) { animation.AddFrame(texture); - texture = GetTexture($"{componentName}-{i}"); + texture = getFrameTexture(i); } animation.Repeat = looping; return animation; } - else - { - texture = GetTexture(componentName); - return texture == null ? null : new Sprite { Texture = texture }; - } + return (texture = GetTexture(componentName)) == null ? null : new Sprite { Texture = texture }; } public class LegacySliderBall : Sprite From d0766fa1cdaa15c1a35a096e1364de4455dcefb5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Aug 2019 19:52:53 +0900 Subject: [PATCH 2436/5608] Add slider ball animation support --- .../Objects/Drawables/Pieces/SliderBall.cs | 12 +++++- osu.Game/Skinning/LegacySkin.cs | 42 +++++++++++++------ 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 8b72b23ca3..332e25750f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -55,7 +55,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Child = new Container { RelativeSizeAxes = Axes.Both, - // TODO: support skin filename animation (sliderb0, sliderb1...) Child = new SkinnableDrawable("Play/osu/sliderball", _ => new DefaultSliderBall()), } } @@ -168,9 +167,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces return action == OsuAction.LeftButton || action == OsuAction.RightButton; } + private Vector2? lastPosition; + public void UpdateProgress(double completionProgress) { - Position = slider.CurvePositionAt(completionProgress); + var newPos = slider.CurvePositionAt(completionProgress); + + var diff = lastPosition.HasValue ? lastPosition.Value - newPos : newPos - slider.CurvePositionAt(completionProgress + 0.01f); + + Position = newPos; + Rotation = 90 + (float)(-Math.Atan2(diff.X, diff.Y) * 180 / Math.PI); + + lastPosition = newPos; } private class FollowCircleContainer : Container diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 94421b1251..883e0ce3fc 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.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; @@ -92,8 +92,20 @@ namespace osu.Game.Skinning return null; case "Play/osu/sliderball": - if (GetTexture("sliderb") != null) - return new LegacySliderBall(); + var sliderBallContent = getAnimation("sliderb", true, true, ""); + + if (sliderBallContent != null) + { + var size = sliderBallContent.Size; + + sliderBallContent.RelativeSizeAxes = Axes.Both; + sliderBallContent.Size = Vector2.One; + + return new LegacySliderBall(sliderBallContent) + { + Size = size + }; + } return null; @@ -169,16 +181,6 @@ namespace osu.Game.Skinning return (texture = GetTexture(componentName)) == null ? null : new Sprite { Texture = texture }; } - public class LegacySliderBall : Sprite - { - [BackgroundDependencyLoader] - private void load(ISkinSource skin) - { - Texture = skin.GetTexture("sliderb"); - Colour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Color4.White; - } - } - public override Texture GetTexture(string componentName) { float ratio = 2; @@ -333,6 +335,20 @@ namespace osu.Game.Skinning } } + public class LegacySliderBall : CompositeDrawable + { + public LegacySliderBall(Drawable content) + { + InternalChild = content; + } + + [BackgroundDependencyLoader] + private void load(ISkinSource skin) + { + Colour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Color4.White; + } + } + public class LegacyMainCirclePiece : CompositeDrawable { public LegacyMainCirclePiece() From b3556403aac6af43614e429054a4b6672583b700 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Mon, 19 Aug 2019 16:18:25 +0200 Subject: [PATCH 2437/5608] Make GetNextObject() a virtual method --- .../Replays/ManiaAutoGenerator.cs | 24 ++++++++--------- .../Replays/TaikoAutoGenerator.cs | 26 +++++++++++++++---- osu.Game/Rulesets/Replays/AutoGenerator.cs | 9 +++++++ 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 43150958d0..b9dd32208e 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Replays; using osu.Game.Rulesets.Mania.Beatmaps; -using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Mania.Replays for (int i = 0; i < Beatmap.HitObjects.Count; i++) { var currentObject = Beatmap.HitObjects[i]; - var nextObjectInTheSameColumn = getNextObjectInTheSameColumn(i); + var nextObjectInTheSameColumn = GetNextObject(i); double endTime = (currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime; @@ -94,19 +94,19 @@ namespace osu.Game.Rulesets.Mania.Replays yield return new ReleasePoint { Time = endTime + calculatedDelay, Column = currentObject.Column }; } + } - ManiaHitObject getNextObjectInTheSameColumn(int currentIndex) + protected override HitObject GetNextObject(int currentIndex) + { + int desiredColumn = Beatmap.HitObjects[currentIndex++].Column; + + for (; currentIndex < Beatmap.HitObjects.Count; currentIndex++) { - int desiredColumn = Beatmap.HitObjects[currentIndex++].Column; - - for (; currentIndex < Beatmap.HitObjects.Count; currentIndex++) - { - if (Beatmap.HitObjects[currentIndex].Column == desiredColumn) - return Beatmap.HitObjects[currentIndex]; - } - - return null; + if (Beatmap.HitObjects[currentIndex].Column == desiredColumn) + return Beatmap.HitObjects[currentIndex]; } + + return null; } private interface IActionPoint diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 1d35393de0..67f93a0259 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -10,6 +10,7 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Taiko.Beatmaps; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Taiko.Replays { @@ -113,16 +114,17 @@ namespace osu.Game.Rulesets.Taiko.Replays else throw new InvalidOperationException("Unknown hit object type."); - TaikoHitObject nextHitObject = i < Beatmap.HitObjects.Count - 1 ? Beatmap.HitObjects[i + 1] : null; + var nextHitObject = GetNextObject(i); bool canDelayKeyUp = nextHitObject == null || nextHitObject.StartTime > endTime + KEY_UP_DELAY; - if (canDelayKeyUp) - Frames.Add(new TaikoReplayFrame(endTime + KEY_UP_DELAY)); + double calculatedDelay = canDelayKeyUp ? KEY_UP_DELAY : nextHitObject.StartTime - endTime; - if (nextHitObject != null) + Frames.Add(new TaikoReplayFrame(endTime + calculatedDelay)); + + if (i < Beatmap.HitObjects.Count - 1) { - double waitTime = nextHitObject.StartTime - 1000; + double waitTime = Beatmap.HitObjects[i + 1].StartTime - 1000; if (waitTime > endTime) Frames.Add(new TaikoReplayFrame(waitTime)); } @@ -132,5 +134,19 @@ namespace osu.Game.Rulesets.Taiko.Replays return Replay; } + + protected override HitObject GetNextObject(int currentIndex) + { + Type desiredType = Beatmap.HitObjects[currentIndex++].GetType(); + + for (; currentIndex < Beatmap.HitObjects.Count; currentIndex++) + { + var currentObj = Beatmap.HitObjects[currentIndex]; + if (currentObj.GetType().Equals(desiredType) || currentObj is DrumRoll) + return Beatmap.HitObjects[currentIndex]; + } + + return null; + } } } diff --git a/osu.Game/Rulesets/Replays/AutoGenerator.cs b/osu.Game/Rulesets/Replays/AutoGenerator.cs index 1d4cdbf04c..3319f30a6f 100644 --- a/osu.Game/Rulesets/Replays/AutoGenerator.cs +++ b/osu.Game/Rulesets/Replays/AutoGenerator.cs @@ -3,6 +3,7 @@ using osu.Game.Beatmaps; using osu.Game.Replays; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Replays { @@ -34,5 +35,13 @@ namespace osu.Game.Rulesets.Replays protected const double KEY_UP_DELAY = 50; #endregion + + protected virtual HitObject GetNextObject(int currentIndex) + { + if (currentIndex >= Beatmap.HitObjects.Count - 1) + return null; + + return Beatmap.HitObjects[currentIndex + 1]; + } } } From daeefc449c30785ba9db860ddaaf7f7fc7c92c18 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 19 Aug 2019 17:49:53 +0300 Subject: [PATCH 2438/5608] Use another link format to avoid representation issues --- .../Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index 9b68131515..ac5801f989 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu private MessageFormatter.MessageFormatterResult createMessage() { - string postLinkTemplate() => $"[{historyItem.Post.Url} {historyItem.Post.Title}]"; + string postLinkTemplate() => $"({historyItem.Post.Title})[{historyItem.Post.Url}]"; string userLinkTemplate() => $"[{historyItem.Giver?.Url} {historyItem.Giver?.Username}]"; string message; From 6b8fbf0eb1ead2c25e04b8a62ca70aaaf8e42b2c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 19 Aug 2019 17:59:55 +0300 Subject: [PATCH 2439/5608] Change link format back Due to unavaliability to handle round brackets --- .../Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index ac5801f989..9b68131515 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu private MessageFormatter.MessageFormatterResult createMessage() { - string postLinkTemplate() => $"({historyItem.Post.Title})[{historyItem.Post.Url}]"; + string postLinkTemplate() => $"[{historyItem.Post.Url} {historyItem.Post.Title}]"; string userLinkTemplate() => $"[{historyItem.Giver?.Url} {historyItem.Giver?.Username}]"; string message; From eb83e36e0f85dc3b0ca6f4f6ce1c138b6ecc938c Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Mon, 19 Aug 2019 17:05:25 +0200 Subject: [PATCH 2440/5608] Make TaikoAutoGenerator unpress sooner --- osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 67f93a0259..463bb84d07 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -118,7 +118,7 @@ namespace osu.Game.Rulesets.Taiko.Replays bool canDelayKeyUp = nextHitObject == null || nextHitObject.StartTime > endTime + KEY_UP_DELAY; - double calculatedDelay = canDelayKeyUp ? KEY_UP_DELAY : nextHitObject.StartTime - endTime; + double calculatedDelay = canDelayKeyUp ? KEY_UP_DELAY : (nextHitObject.StartTime - endTime) * 0.9; Frames.Add(new TaikoReplayFrame(endTime + calculatedDelay)); From 9732f5d6226f739c51e6cae81b706581d5c0291d Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Mon, 19 Aug 2019 17:28:32 +0200 Subject: [PATCH 2441/5608] Add Swell to GetNextObject() check --- osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 463bb84d07..fbc7b75854 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -142,7 +142,8 @@ namespace osu.Game.Rulesets.Taiko.Replays for (; currentIndex < Beatmap.HitObjects.Count; currentIndex++) { var currentObj = Beatmap.HitObjects[currentIndex]; - if (currentObj.GetType().Equals(desiredType) || currentObj is DrumRoll) + if (currentObj.GetType().Equals(desiredType) || + currentObj is DrumRoll || currentObj is Swell) // It's best to unpress any remaining keys before DrumRoll or Swell return Beatmap.HitObjects[currentIndex]; } From 70084b5553102e93fb5d592fb7d24d4672c070b4 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 19 Aug 2019 20:28:03 +0300 Subject: [PATCH 2442/5608] Move HitErrorDisplay outside of the HUD --- osu.Game/Screens/Play/HUDOverlay.cs | 22 ------ .../HitErrorDisplay.cs | 66 +++++------------- .../HitErrorDisplay/HitErrorDisplayOverlay.cs | 69 +++++++++++++++++++ osu.Game/Screens/Play/Player.cs | 4 ++ 4 files changed, 90 insertions(+), 71 deletions(-) rename osu.Game/Screens/Play/{HUD => HitErrorDisplay}/HitErrorDisplay.cs (77%) create mode 100644 osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index be291003b5..1124c8f5f0 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -36,8 +36,6 @@ namespace osu.Game.Screens.Play public readonly ModDisplay ModDisplay; public readonly HoldForMenuButton HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; - public readonly HitErrorDisplay LeftHitErrorDisplay; - public readonly HitErrorDisplay RightHitErrorDisplay; public Bindable ShowHealthbar = new Bindable(true); @@ -87,8 +85,6 @@ namespace osu.Game.Screens.Play HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), ModDisplay = CreateModsContainer(), - LeftHitErrorDisplay = CreateHitErrorDisplay(false), - RightHitErrorDisplay = CreateHitErrorDisplay(), } }, PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), @@ -261,13 +257,6 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20, Right = 10 }, }; - protected virtual HitErrorDisplay CreateHitErrorDisplay(bool reversed = true) => new HitErrorDisplay(reversed) - { - Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - Margin = new MarginPadding { Horizontal = 20 } - }; - protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); protected virtual void BindProcessor(ScoreProcessor processor) @@ -277,17 +266,6 @@ namespace osu.Game.Screens.Play ComboCounter?.Current.BindTo(processor.Combo); HealthDisplay?.Current.BindTo(processor.Health); - var hitWindows = processor.CreateHitWindows(); - - visibilityContainer.ForEach(drawable => - { - if (drawable is HitErrorDisplay) - { - processor.NewJudgement += ((HitErrorDisplay)drawable).OnNewJudgement; - ((HitErrorDisplay)drawable).HitWindows = hitWindows; - } - }); - if (HealthDisplay is StandardHealthDisplay shd) processor.NewJudgement += shd.Flash; } diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs similarity index 77% rename from osu.Game/Screens/Play/HUD/HitErrorDisplay.cs rename to osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs index 1a3682351b..1a776bc78d 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs @@ -10,16 +10,13 @@ using osuTK; using osu.Framework.Graphics.Sprites; using System.Collections.Generic; using osu.Game.Rulesets.Objects; -using osu.Game.Beatmaps; -using osu.Framework.Bindables; using osu.Framework.Allocation; using osu.Framework.Graphics.Colour; using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions; using System.Linq; -using osu.Game.Configuration; -namespace osu.Game.Screens.Play.HUD +namespace osu.Game.Screens.Play.HitErrorDisplay { public class HitErrorDisplay : CompositeDrawable { @@ -27,29 +24,24 @@ namespace osu.Game.Screens.Play.HUD private const int bar_width = 3; private const int judgement_line_width = 8; private const int bar_height = 200; - private const int fade_duration = 200; private const int arrow_move_duration = 500; private const int judgement_life_time = 10000; private const int spacing = 3; - public HitWindows HitWindows { get; set; } - - [Resolved] - private Bindable beatmap { get; set; } - - [Resolved] - private OsuColour colours { get; set; } - + private readonly HitWindows hitWindows; private readonly SpriteIcon arrow; private readonly FillFlowContainer bar; private readonly Container judgementsContainer; private readonly Queue judgementOffsets = new Queue(); - private readonly Bindable type = new Bindable(); - - public HitErrorDisplay(bool reversed = false) + public HitErrorDisplay(float overallDifficulty, HitWindows hitWindows, bool reversed = false) { + this.hitWindows = hitWindows; + hitWindows.SetDifficulty(overallDifficulty); + AutoSizeAxes = Axes.Both; + Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft; + Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft; AddInternal(new FillFlowContainer { @@ -94,74 +86,50 @@ namespace osu.Game.Screens.Play.HUD } [BackgroundDependencyLoader] - private void load(OsuConfigManager config) + private void load(OsuColour colours) { - config.BindWith(OsuSetting.ScoreMeter, type); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - HitWindows.SetDifficulty(beatmap.Value.BeatmapInfo.BaseDifficulty.OverallDifficulty); - bar.AddRange(new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical(colours.Yellow.Opacity(0), colours.Yellow), - Height = (float)((getMehHitWindows() - HitWindows.Good) / (getMehHitWindows() * 2)) + Height = (float)((getMehHitWindows() - hitWindows.Good) / (getMehHitWindows() * 2)) }, new Box { RelativeSizeAxes = Axes.Both, Colour = colours.Green, - Height = (float)((HitWindows.Good - HitWindows.Great) / (getMehHitWindows() * 2)) + Height = (float)((hitWindows.Good - hitWindows.Great) / (getMehHitWindows() * 2)) }, new Box { RelativeSizeAxes = Axes.Both, Colour = colours.BlueLight, - Height = (float)(HitWindows.Great / getMehHitWindows()) + Height = (float)(hitWindows.Great / getMehHitWindows()) }, new Box { RelativeSizeAxes = Axes.Both, Colour = colours.Green, - Height = (float)((HitWindows.Good - HitWindows.Great) / (getMehHitWindows() * 2)) + Height = (float)((hitWindows.Good - hitWindows.Great) / (getMehHitWindows() * 2)) }, new Box { RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical(colours.Yellow, colours.Yellow.Opacity(0)), - Height = (float)((getMehHitWindows() - HitWindows.Good) / (getMehHitWindows() * 2)) + Height = (float)((getMehHitWindows() - hitWindows.Good) / (getMehHitWindows() * 2)) } }); - - type.BindValueChanged(onTypeChanged, true); } private double getMehHitWindows() { // In case if ruleset has no Meh hit windows (like Taiko) - if (HitWindows.Meh == 0) - return HitWindows.Good + 40; + if (hitWindows.Meh == 0) + return hitWindows.Good + 40; - return HitWindows.Meh; - } - - private void onTypeChanged(ValueChangedEvent type) - { - switch (type.NewValue) - { - case ScoreMeterType.None: - this.FadeOut(fade_duration, Easing.OutQuint); - break; - - case ScoreMeterType.HitError: - this.FadeIn(fade_duration, Easing.OutQuint); - break; - } + return hitWindows.Meh; } public void OnNewJudgement(JudgementResult newJudgement) diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs new file mode 100644 index 0000000000..09ecbdfc66 --- /dev/null +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs @@ -0,0 +1,69 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Scoring; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Framework.Extensions.IEnumerableExtensions; +using System.Linq; + +namespace osu.Game.Screens.Play.HitErrorDisplay +{ + public class HitErrorDisplayOverlay : Container + { + private const int fade_duration = 200; + private const int margin = 10; + + private readonly Bindable type = new Bindable(); + + public HitErrorDisplayOverlay(ScoreProcessor processor, WorkingBeatmap workingBeatmap) + { + float overallDifficulty = workingBeatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty; + + RelativeSizeAxes = Axes.Both; + Children = new[] + { + new HitErrorDisplay(overallDifficulty, processor.CreateHitWindows()) + { + Margin = new MarginPadding { Left = margin } + }, + new HitErrorDisplay(overallDifficulty, processor.CreateHitWindows(), true) + { + Margin = new MarginPadding { Right = margin } + }, + }; + + Children.ForEach(t => processor.NewJudgement += t.OnNewJudgement); + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + config.BindWith(OsuSetting.ScoreMeter, type); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + type.BindValueChanged(onTypeChanged, true); + } + + private void onTypeChanged(ValueChangedEvent type) + { + switch (type.NewValue) + { + case ScoreMeterType.None: + InternalChildren.ForEach(t => t.FadeOut(fade_duration, Easing.OutQuint)); + break; + + default: + InternalChildren.ForEach(t => t.FadeIn(fade_duration, Easing.OutQuint)); + break; + } + } + } +} diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index e7398be176..9ef8cc4509 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -24,6 +24,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; +using osu.Game.Screens.Play.HitErrorDisplay; using osu.Game.Screens.Ranking; using osu.Game.Skinning; using osu.Game.Users; @@ -73,6 +74,8 @@ namespace osu.Game.Screens.Play protected HUDOverlay HUDOverlay { get; private set; } + protected HitErrorDisplayOverlay HitErrorDisplayOverlay { get; private set; } + public bool LoadedBeatmapSuccessfully => DrawableRuleset?.Objects.Any() == true; protected GameplayClockContainer GameplayClockContainer { get; private set; } @@ -157,6 +160,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre }, + HitErrorDisplayOverlay = new HitErrorDisplayOverlay(ScoreProcessor, working), new SkipOverlay(DrawableRuleset.GameplayStartTime) { RequestSeek = GameplayClockContainer.Seek From 6d3aa0520b6cc6bc999809b123b600414314260f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 19 Aug 2019 20:44:06 +0300 Subject: [PATCH 2443/5608] Make HitErrorDisplay an abstract class --- .../HitErrorDisplay/DefaultHitErrorDisplay.cs | 174 ++++++++++++++++++ .../Play/HitErrorDisplay/HitErrorDisplay.cs | 167 +---------------- .../HitErrorDisplay/HitErrorDisplayOverlay.cs | 4 +- 3 files changed, 182 insertions(+), 163 deletions(-) create mode 100644 osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs diff --git a/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs new file mode 100644 index 0000000000..6cf80b209a --- /dev/null +++ b/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs @@ -0,0 +1,174 @@ +// 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.Shapes; +using osu.Game.Rulesets.Judgements; +using osuTK.Graphics; +using osuTK; +using osu.Framework.Graphics.Sprites; +using System.Collections.Generic; +using osu.Game.Rulesets.Objects; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Colour; +using osu.Game.Graphics; +using osu.Framework.Extensions.Color4Extensions; +using System.Linq; + +namespace osu.Game.Screens.Play.HitErrorDisplay +{ + public class DefaultHitErrorDisplay : HitErrorDisplay + { + private const int stored_judgements_amount = 5; + private const int bar_width = 3; + private const int judgement_line_width = 8; + private const int bar_height = 200; + private const int arrow_move_duration = 500; + private const int judgement_life_time = 10000; + private const int spacing = 3; + + private readonly SpriteIcon arrow; + private readonly FillFlowContainer bar; + private readonly Container judgementsContainer; + private readonly Queue judgementOffsets = new Queue(); + + public DefaultHitErrorDisplay(float overallDifficulty, HitWindows hitWindows, bool reversed = false) + : base(overallDifficulty, hitWindows) + { + AutoSizeAxes = Axes.Both; + Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft; + Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft; + + AddInternal(new FillFlowContainer + { + AutoSizeAxes = Axes.X, + Height = bar_height, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(spacing, 0), + Children = new Drawable[] + { + judgementsContainer = new Container + { + Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Width = judgement_line_width, + RelativeSizeAxes = Axes.Y, + }, + bar = new FillFlowContainer + { + Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Width = bar_width, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + }, + new Container + { + Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Child = arrow = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.Y, + Icon = reversed ? FontAwesome.Solid.ChevronRight : FontAwesome.Solid.ChevronLeft, + Size = new Vector2(8), + } + }, + } + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + bar.AddRange(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(colours.Yellow.Opacity(0), colours.Yellow), + Height = (float)((getMehHitWindows() - HitWindows.Good) / (getMehHitWindows() * 2)) + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Green, + Height = (float)((HitWindows.Good - HitWindows.Great) / (getMehHitWindows() * 2)) + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.BlueLight, + Height = (float)(HitWindows.Great / getMehHitWindows()) + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Green, + Height = (float)((HitWindows.Good - HitWindows.Great) / (getMehHitWindows() * 2)) + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(colours.Yellow, colours.Yellow.Opacity(0)), + Height = (float)((getMehHitWindows() - HitWindows.Good) / (getMehHitWindows() * 2)) + } + }); + } + + private double getMehHitWindows() + { + // In case if ruleset has no Meh hit windows (like Taiko) + if (HitWindows.Meh == 0) + return HitWindows.Good + 40; + + return HitWindows.Meh; + } + + public override void OnNewJudgement(JudgementResult newJudgement) + { + if (!newJudgement.IsHit) + return; + + var judgementLine = CreateJudgementLine(newJudgement); + + judgementsContainer.Add(judgementLine); + + judgementLine.FadeOut(judgement_life_time, Easing.OutQuint).Expire(); + + arrow.MoveToY(calculateArrowPosition(newJudgement), arrow_move_duration, Easing.OutQuint); + } + + protected virtual Container CreateJudgementLine(JudgementResult judgement) => new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + RelativeSizeAxes = Axes.X, + Height = 2, + RelativePositionAxes = Axes.Y, + Y = getRelativeJudgementPosition(judgement.TimeOffset), + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + } + }; + + private float getRelativeJudgementPosition(double value) => (float)(value / getMehHitWindows()); + + private float calculateArrowPosition(JudgementResult newJudgement) + { + if (judgementOffsets.Count > stored_judgements_amount) + judgementOffsets.Dequeue(); + + judgementOffsets.Enqueue(newJudgement.TimeOffset); + + return getRelativeJudgementPosition(judgementOffsets.Average()); + } + } +} diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs index 1a776bc78d..fb22b35736 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs @@ -1,177 +1,22 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Judgements; -using osuTK.Graphics; -using osuTK; -using osu.Framework.Graphics.Sprites; -using System.Collections.Generic; using osu.Game.Rulesets.Objects; -using osu.Framework.Allocation; -using osu.Framework.Graphics.Colour; -using osu.Game.Graphics; -using osu.Framework.Extensions.Color4Extensions; -using System.Linq; namespace osu.Game.Screens.Play.HitErrorDisplay { - public class HitErrorDisplay : CompositeDrawable + public abstract class HitErrorDisplay : CompositeDrawable { - private const int stored_judgements_amount = 5; - private const int bar_width = 3; - private const int judgement_line_width = 8; - private const int bar_height = 200; - private const int arrow_move_duration = 500; - private const int judgement_life_time = 10000; - private const int spacing = 3; + protected readonly HitWindows HitWindows; - private readonly HitWindows hitWindows; - private readonly SpriteIcon arrow; - private readonly FillFlowContainer bar; - private readonly Container judgementsContainer; - private readonly Queue judgementOffsets = new Queue(); - - public HitErrorDisplay(float overallDifficulty, HitWindows hitWindows, bool reversed = false) + public HitErrorDisplay(float overallDifficulty, HitWindows hitWindows) { - this.hitWindows = hitWindows; - hitWindows.SetDifficulty(overallDifficulty); - - AutoSizeAxes = Axes.Both; - Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft; - Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft; - - AddInternal(new FillFlowContainer - { - AutoSizeAxes = Axes.X, - Height = bar_height, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(spacing, 0), - Children = new Drawable[] - { - judgementsContainer = new Container - { - Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - Width = judgement_line_width, - RelativeSizeAxes = Axes.Y, - }, - bar = new FillFlowContainer - { - Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - Width = bar_width, - RelativeSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - }, - new Container - { - Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Child = arrow = new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativePositionAxes = Axes.Y, - Icon = reversed ? FontAwesome.Solid.ChevronRight : FontAwesome.Solid.ChevronLeft, - Size = new Vector2(8), - } - }, - } - }); + HitWindows = hitWindows; + HitWindows.SetDifficulty(overallDifficulty); } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - bar.AddRange(new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(colours.Yellow.Opacity(0), colours.Yellow), - Height = (float)((getMehHitWindows() - hitWindows.Good) / (getMehHitWindows() * 2)) - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Green, - Height = (float)((hitWindows.Good - hitWindows.Great) / (getMehHitWindows() * 2)) - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.BlueLight, - Height = (float)(hitWindows.Great / getMehHitWindows()) - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Green, - Height = (float)((hitWindows.Good - hitWindows.Great) / (getMehHitWindows() * 2)) - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(colours.Yellow, colours.Yellow.Opacity(0)), - Height = (float)((getMehHitWindows() - hitWindows.Good) / (getMehHitWindows() * 2)) - } - }); - } - - private double getMehHitWindows() - { - // In case if ruleset has no Meh hit windows (like Taiko) - if (hitWindows.Meh == 0) - return hitWindows.Good + 40; - - return hitWindows.Meh; - } - - public void OnNewJudgement(JudgementResult newJudgement) - { - if (!newJudgement.IsHit) - return; - - var judgementLine = CreateJudgementLine(newJudgement); - - judgementsContainer.Add(judgementLine); - - judgementLine.FadeOut(judgement_life_time, Easing.OutQuint).Expire(); - - arrow.MoveToY(calculateArrowPosition(newJudgement), arrow_move_duration, Easing.OutQuint); - } - - protected virtual Container CreateJudgementLine(JudgementResult judgement) => new CircularContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Masking = true, - RelativeSizeAxes = Axes.X, - Height = 2, - RelativePositionAxes = Axes.Y, - Y = getRelativeJudgementPosition(judgement.TimeOffset), - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.White, - } - }; - - private float getRelativeJudgementPosition(double value) => (float)(value / getMehHitWindows()); - - private float calculateArrowPosition(JudgementResult newJudgement) - { - if (judgementOffsets.Count > stored_judgements_amount) - judgementOffsets.Dequeue(); - - judgementOffsets.Enqueue(newJudgement.TimeOffset); - - return getRelativeJudgementPosition(judgementOffsets.Average()); - } + public abstract void OnNewJudgement(JudgementResult newJudgement); } } diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs index 09ecbdfc66..35b883ff27 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs @@ -27,11 +27,11 @@ namespace osu.Game.Screens.Play.HitErrorDisplay RelativeSizeAxes = Axes.Both; Children = new[] { - new HitErrorDisplay(overallDifficulty, processor.CreateHitWindows()) + new DefaultHitErrorDisplay(overallDifficulty, processor.CreateHitWindows()) { Margin = new MarginPadding { Left = margin } }, - new HitErrorDisplay(overallDifficulty, processor.CreateHitWindows(), true) + new DefaultHitErrorDisplay(overallDifficulty, processor.CreateHitWindows(), true) { Margin = new MarginPadding { Right = margin } }, From 9bd844bf4d41c6dd9b82aa7cbc27079b738b35d2 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Mon, 19 Aug 2019 19:54:22 +0200 Subject: [PATCH 2444/5608] Make comment more informative --- osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index fbc7b75854..4d6730c0e6 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Taiko.Replays { var currentObj = Beatmap.HitObjects[currentIndex]; if (currentObj.GetType().Equals(desiredType) || - currentObj is DrumRoll || currentObj is Swell) // It's best to unpress any remaining keys before DrumRoll or Swell + currentObj is DrumRoll || currentObj is Swell) // Unpress all keys before DrumRoll or Swell return Beatmap.HitObjects[currentIndex]; } From 6d84523bc0d87ba814ddddf1edcdff53812a48be Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 19 Aug 2019 21:10:12 +0300 Subject: [PATCH 2445/5608] Add testing --- .../Gameplay/TestSceneHitErrorDisplay.cs | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs new file mode 100644 index 0000000000..c5e5e96ad9 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs @@ -0,0 +1,110 @@ +// 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.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Screens.Play.HitErrorDisplay; +using System; +using System.Collections.Generic; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Scoring; +using osu.Framework.MathUtils; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestSceneHitErrorDisplay : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HitErrorDisplay), + }; + + private HitErrorDisplay display; + + public TestSceneHitErrorDisplay() + { + recreateDisplay(new OsuHitWindows(), 5); + AddStep("New random judgement", () => newJudgement()); + AddStep("New fixed judgement (50ms)", () => newJudgement(50)); + } + + [Test] + public void TestOsu() + { + AddStep("OD 1", () => recreateDisplay(new OsuHitWindows(), 1)); + AddStep("OD 2", () => recreateDisplay(new OsuHitWindows(), 2)); + AddStep("OD 3", () => recreateDisplay(new OsuHitWindows(), 3)); + AddStep("OD 4", () => recreateDisplay(new OsuHitWindows(), 4)); + AddStep("OD 5", () => recreateDisplay(new OsuHitWindows(), 5)); + AddStep("OD 6", () => recreateDisplay(new OsuHitWindows(), 6)); + AddStep("OD 7", () => recreateDisplay(new OsuHitWindows(), 7)); + AddStep("OD 8", () => recreateDisplay(new OsuHitWindows(), 8)); + AddStep("OD 9", () => recreateDisplay(new OsuHitWindows(), 9)); + AddStep("OD 10", () => recreateDisplay(new OsuHitWindows(), 10)); + } + + [Test] + public void TestTaiko() + { + AddStep("OD 1", () => recreateDisplay(new TaikoHitWindows(), 1)); + AddStep("OD 2", () => recreateDisplay(new TaikoHitWindows(), 2)); + AddStep("OD 3", () => recreateDisplay(new TaikoHitWindows(), 3)); + AddStep("OD 4", () => recreateDisplay(new TaikoHitWindows(), 4)); + AddStep("OD 5", () => recreateDisplay(new TaikoHitWindows(), 5)); + AddStep("OD 6", () => recreateDisplay(new TaikoHitWindows(), 6)); + AddStep("OD 7", () => recreateDisplay(new TaikoHitWindows(), 7)); + AddStep("OD 8", () => recreateDisplay(new TaikoHitWindows(), 8)); + AddStep("OD 9", () => recreateDisplay(new TaikoHitWindows(), 9)); + AddStep("OD 10", () => recreateDisplay(new TaikoHitWindows(), 10)); + } + + [Test] + public void TestMania() + { + AddStep("OD 1", () => recreateDisplay(new ManiaHitWindows(), 1)); + AddStep("OD 2", () => recreateDisplay(new ManiaHitWindows(), 2)); + AddStep("OD 3", () => recreateDisplay(new ManiaHitWindows(), 3)); + AddStep("OD 4", () => recreateDisplay(new ManiaHitWindows(), 4)); + AddStep("OD 5", () => recreateDisplay(new ManiaHitWindows(), 5)); + AddStep("OD 6", () => recreateDisplay(new ManiaHitWindows(), 6)); + AddStep("OD 7", () => recreateDisplay(new ManiaHitWindows(), 7)); + AddStep("OD 8", () => recreateDisplay(new ManiaHitWindows(), 8)); + AddStep("OD 9", () => recreateDisplay(new ManiaHitWindows(), 9)); + AddStep("OD 10", () => recreateDisplay(new ManiaHitWindows(), 10)); + } + + [Test] + public void TestCatch() + { + AddStep("OD 1", () => recreateDisplay(new CatchHitWindows(), 1)); + AddStep("OD 2", () => recreateDisplay(new CatchHitWindows(), 2)); + AddStep("OD 3", () => recreateDisplay(new CatchHitWindows(), 3)); + AddStep("OD 4", () => recreateDisplay(new CatchHitWindows(), 4)); + AddStep("OD 5", () => recreateDisplay(new CatchHitWindows(), 5)); + AddStep("OD 6", () => recreateDisplay(new CatchHitWindows(), 6)); + AddStep("OD 7", () => recreateDisplay(new CatchHitWindows(), 7)); + AddStep("OD 8", () => recreateDisplay(new CatchHitWindows(), 8)); + AddStep("OD 9", () => recreateDisplay(new CatchHitWindows(), 9)); + AddStep("OD 10", () => recreateDisplay(new CatchHitWindows(), 10)); + } + + private void recreateDisplay(HitWindows hitWindows, float overallDifficulty) + { + Clear(); + Add(display = new DefaultHitErrorDisplay(overallDifficulty, hitWindows)); + } + + private void newJudgement(float offset = 0) + { + display?.OnNewJudgement(new JudgementResult(new Judgement()) + { + TimeOffset = offset == 0 ? RNG.Next(-70, 70) : offset, + Type = HitResult.Perfect, + }); + } + } +} From 1bff103d3244aff12c6faf83454cb43bbfd2d852 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 19 Aug 2019 21:25:14 +0300 Subject: [PATCH 2446/5608] CI fixes --- .../Visual/Gameplay/TestSceneHitErrorDisplay.cs | 7 ++++++- osu.Game/Screens/Play/HUDOverlay.cs | 1 - .../Play/HitErrorDisplay/DefaultHitErrorDisplay.cs | 2 -- osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs | 2 +- .../Play/HitErrorDisplay/HitErrorDisplayOverlay.cs | 9 ++++++--- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs index c5e5e96ad9..e86606e4fc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs @@ -13,6 +13,7 @@ using System.Collections.Generic; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Framework.MathUtils; +using osu.Framework.Graphics; namespace osu.Game.Tests.Visual.Gameplay { @@ -95,7 +96,11 @@ namespace osu.Game.Tests.Visual.Gameplay private void recreateDisplay(HitWindows hitWindows, float overallDifficulty) { Clear(); - Add(display = new DefaultHitErrorDisplay(overallDifficulty, hitWindows)); + Add(display = new DefaultHitErrorDisplay(overallDifficulty, hitWindows) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); } private void newJudgement(float offset = 0) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 1124c8f5f0..43b9491750 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; diff --git a/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs index 6cf80b209a..a0b9787c5f 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs @@ -37,8 +37,6 @@ namespace osu.Game.Screens.Play.HitErrorDisplay : base(overallDifficulty, hitWindows) { AutoSizeAxes = Axes.Both; - Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft; - Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft; AddInternal(new FillFlowContainer { diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs index fb22b35736..10b5e5b1cb 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs @@ -11,7 +11,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay { protected readonly HitWindows HitWindows; - public HitErrorDisplay(float overallDifficulty, HitWindows hitWindows) + protected HitErrorDisplay(float overallDifficulty, HitWindows hitWindows) { HitWindows = hitWindows; HitWindows.SetDifficulty(overallDifficulty); diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs index 35b883ff27..fd118a26e5 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs @@ -9,7 +9,6 @@ using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; -using System.Linq; namespace osu.Game.Screens.Play.HitErrorDisplay { @@ -29,11 +28,15 @@ namespace osu.Game.Screens.Play.HitErrorDisplay { new DefaultHitErrorDisplay(overallDifficulty, processor.CreateHitWindows()) { - Margin = new MarginPadding { Left = margin } + Margin = new MarginPadding { Left = margin }, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, }, new DefaultHitErrorDisplay(overallDifficulty, processor.CreateHitWindows(), true) { - Margin = new MarginPadding { Right = margin } + Margin = new MarginPadding { Right = margin }, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, }, }; From 77e9e89fecdcac72fd34e607fe4f909b2b83cbf0 Mon Sep 17 00:00:00 2001 From: Desconocidosmh Date: Mon, 19 Aug 2019 20:45:23 +0200 Subject: [PATCH 2447/5608] Refactoring --- osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs | 8 ++++---- osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index b9dd32208e..fd0a876775 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -81,14 +81,14 @@ namespace osu.Game.Rulesets.Mania.Replays for (int i = 0; i < Beatmap.HitObjects.Count; i++) { var currentObject = Beatmap.HitObjects[i]; - var nextObjectInTheSameColumn = GetNextObject(i); + var nextObjectInColumn = GetNextObject(i); // Get the next object that requires pressing the same button double endTime = (currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime; - bool canDelayKeyUp = nextObjectInTheSameColumn == null || - nextObjectInTheSameColumn.StartTime > endTime + RELEASE_DELAY; + bool canDelayKeyUp = nextObjectInColumn == null || + nextObjectInColumn.StartTime > endTime + RELEASE_DELAY; - double calculatedDelay = canDelayKeyUp ? RELEASE_DELAY : (nextObjectInTheSameColumn.StartTime - endTime) * 0.9; + double calculatedDelay = canDelayKeyUp ? RELEASE_DELAY : (nextObjectInColumn.StartTime - endTime) * 0.9; yield return new HitPoint { Time = currentObject.StartTime, Column = currentObject.Column }; diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 4d6730c0e6..6720d8b8bf 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Taiko.Replays else throw new InvalidOperationException("Unknown hit object type."); - var nextHitObject = GetNextObject(i); + var nextHitObject = GetNextObject(i); // Get the next object that requires pressing the same button bool canDelayKeyUp = nextHitObject == null || nextHitObject.StartTime > endTime + KEY_UP_DELAY; @@ -142,7 +142,7 @@ namespace osu.Game.Rulesets.Taiko.Replays for (; currentIndex < Beatmap.HitObjects.Count; currentIndex++) { var currentObj = Beatmap.HitObjects[currentIndex]; - if (currentObj.GetType().Equals(desiredType) || + if (currentObj.GetType() == desiredType || currentObj is DrumRoll || currentObj is Swell) // Unpress all keys before DrumRoll or Swell return Beatmap.HitObjects[currentIndex]; } From f1c3a60660d035128c8f3e938f88b216d4ab8669 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 19 Aug 2019 22:04:27 +0300 Subject: [PATCH 2448/5608] Add ability to select side --- osu.Game/Configuration/OsuConfigManager.cs | 2 +- osu.Game/Configuration/ScoreMeterType.cs | 10 ++- .../HitErrorDisplay/HitErrorDisplayOverlay.cs | 66 +++++++++++++------ 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index bffbce2a52..fbb17fa7f9 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -79,7 +79,7 @@ namespace osu.Game.Configuration Set(OsuSetting.ShowInterface, true); Set(OsuSetting.ShowHealthDisplayWhenCantFail, true); Set(OsuSetting.KeyOverlay, false); - Set(OsuSetting.ScoreMeter, ScoreMeterType.HitError); + Set(OsuSetting.ScoreMeter, ScoreMeterType.HitErrorBoth); Set(OsuSetting.FloatingComments, false); diff --git a/osu.Game/Configuration/ScoreMeterType.cs b/osu.Game/Configuration/ScoreMeterType.cs index e78220c9c9..b85ef9309d 100644 --- a/osu.Game/Configuration/ScoreMeterType.cs +++ b/osu.Game/Configuration/ScoreMeterType.cs @@ -10,7 +10,13 @@ namespace osu.Game.Configuration [Description("None")] None, - [Description("Hit Error")] - HitError + [Description("Hit Error (left)")] + HitErrorLeft, + + [Description("Hit Error (right)")] + HitErrorRight, + + [Description("Hit Error (both)")] + HitErrorBoth, } } diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs index fd118a26e5..bbed2b1618 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs @@ -9,6 +9,7 @@ using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Play.HitErrorDisplay { @@ -18,29 +19,18 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private const int margin = 10; private readonly Bindable type = new Bindable(); + private readonly HitWindows hitWindows; + private readonly ScoreProcessor processor; + private readonly float overallDifficulty; public HitErrorDisplayOverlay(ScoreProcessor processor, WorkingBeatmap workingBeatmap) { - float overallDifficulty = workingBeatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty; + this.processor = processor; + + overallDifficulty = workingBeatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty; + hitWindows = processor.CreateHitWindows(); RelativeSizeAxes = Axes.Both; - Children = new[] - { - new DefaultHitErrorDisplay(overallDifficulty, processor.CreateHitWindows()) - { - Margin = new MarginPadding { Left = margin }, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - }, - new DefaultHitErrorDisplay(overallDifficulty, processor.CreateHitWindows(), true) - { - Margin = new MarginPadding { Right = margin }, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - }, - }; - - Children.ForEach(t => processor.NewJudgement += t.OnNewJudgement); } [BackgroundDependencyLoader] @@ -57,16 +47,50 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private void onTypeChanged(ValueChangedEvent type) { + clear(); + switch (type.NewValue) { case ScoreMeterType.None: - InternalChildren.ForEach(t => t.FadeOut(fade_duration, Easing.OutQuint)); break; - default: - InternalChildren.ForEach(t => t.FadeIn(fade_duration, Easing.OutQuint)); + case ScoreMeterType.HitErrorBoth: + createNew(); + createNew(true); + break; + + case ScoreMeterType.HitErrorLeft: + createNew(); + break; + + case ScoreMeterType.HitErrorRight: + createNew(true); break; } } + + private void clear() + { + Children.ForEach(t => + { + processor.NewJudgement -= t.OnNewJudgement; + t.FadeOut(fade_duration, Easing.OutQuint).Expire(); + }); + } + + private void createNew(bool reversed = false) + { + var display = new DefaultHitErrorDisplay(overallDifficulty, hitWindows, reversed) + { + Margin = new MarginPadding(margin), + Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Alpha = 0, + }; + + processor.NewJudgement += display.OnNewJudgement; + Add(display); + display.FadeInFromZero(fade_duration, Easing.OutQuint); + } } } From 50c47568e434f5a68002d40610d1618f221fbd39 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 19 Aug 2019 22:45:27 +0300 Subject: [PATCH 2449/5608] Don't present Meh hit windows if it has no value --- .../Gameplay/TestSceneHitErrorDisplay.cs | 19 +++++++ .../HitErrorDisplay/DefaultHitErrorDisplay.cs | 54 ++++++++++--------- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs index e86606e4fc..006773a091 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs @@ -14,6 +14,8 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Framework.MathUtils; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; namespace osu.Game.Tests.Visual.Gameplay { @@ -95,7 +97,24 @@ namespace osu.Game.Tests.Visual.Gameplay private void recreateDisplay(HitWindows hitWindows, float overallDifficulty) { + hitWindows.SetDifficulty(overallDifficulty); + Clear(); + + Add(new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Both, + Children = new[] + { + new SpriteText { Text = $@"Great: {hitWindows.Great}" }, + new SpriteText { Text = $@"Good: {hitWindows.Good}" }, + new SpriteText { Text = $@"Meh: {hitWindows.Meh}" }, + } + }); + Add(display = new DefaultHitErrorDisplay(overallDifficulty, hitWindows) { Anchor = Anchor.Centre, diff --git a/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs index a0b9787c5f..11de0696d3 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs @@ -32,12 +32,14 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private readonly FillFlowContainer bar; private readonly Container judgementsContainer; private readonly Queue judgementOffsets = new Queue(); + private readonly double maxHitWindows; public DefaultHitErrorDisplay(float overallDifficulty, HitWindows hitWindows, bool reversed = false) : base(overallDifficulty, hitWindows) { - AutoSizeAxes = Axes.Both; + maxHitWindows = HitWindows.Meh == 0 ? HitWindows.Good : HitWindows.Meh; + AutoSizeAxes = Axes.Both; AddInternal(new FillFlowContainer { AutoSizeAxes = Axes.X, @@ -83,48 +85,52 @@ namespace osu.Game.Screens.Play.HitErrorDisplay [BackgroundDependencyLoader] private void load(OsuColour colours) { - bar.AddRange(new Drawable[] - { - new Box + Box topGreenBox; + Box bottomGreenBox; + + if (HitWindows.Meh != 0) + bar.Add(new Box { RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical(colours.Yellow.Opacity(0), colours.Yellow), - Height = (float)((getMehHitWindows() - HitWindows.Good) / (getMehHitWindows() * 2)) - }, - new Box + Height = (float)((maxHitWindows - HitWindows.Good) / (maxHitWindows * 2)) + }); + + bar.AddRange(new Drawable[] + { + topGreenBox = new Box { RelativeSizeAxes = Axes.Both, Colour = colours.Green, - Height = (float)((HitWindows.Good - HitWindows.Great) / (getMehHitWindows() * 2)) + Height = (float)((HitWindows.Good - HitWindows.Great) / (maxHitWindows * 2)) }, new Box { RelativeSizeAxes = Axes.Both, Colour = colours.BlueLight, - Height = (float)(HitWindows.Great / getMehHitWindows()) + Height = (float)(HitWindows.Great / maxHitWindows) }, - new Box + bottomGreenBox = new Box { RelativeSizeAxes = Axes.Both, Colour = colours.Green, - Height = (float)((HitWindows.Good - HitWindows.Great) / (getMehHitWindows() * 2)) - }, - new Box + Height = (float)((HitWindows.Good - HitWindows.Great) / (maxHitWindows * 2)) + } + });; + + if (HitWindows.Meh != 0) + bar.Add(new Box { RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical(colours.Yellow, colours.Yellow.Opacity(0)), - Height = (float)((getMehHitWindows() - HitWindows.Good) / (getMehHitWindows() * 2)) - } - }); - } + Height = (float)((maxHitWindows - HitWindows.Good) / (maxHitWindows * 2)) + }); - private double getMehHitWindows() - { - // In case if ruleset has no Meh hit windows (like Taiko) if (HitWindows.Meh == 0) - return HitWindows.Good + 40; - - return HitWindows.Meh; + { + topGreenBox.Colour = ColourInfo.GradientVertical(colours.Green.Opacity(0), colours.Green); + bottomGreenBox.Colour = ColourInfo.GradientVertical(colours.Green, colours.Green.Opacity(0)); + } } public override void OnNewJudgement(JudgementResult newJudgement) @@ -157,7 +163,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay } }; - private float getRelativeJudgementPosition(double value) => (float)(value / getMehHitWindows()); + private float getRelativeJudgementPosition(double value) => (float)(value / maxHitWindows); private float calculateArrowPosition(JudgementResult newJudgement) { From 415f1802614dbcd96541746a02a8a61500ba07bb Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 19 Aug 2019 22:53:28 +0300 Subject: [PATCH 2450/5608] Delete extra semicolon --- osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs index 11de0696d3..2d05dc8aba 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs @@ -116,7 +116,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay Colour = colours.Green, Height = (float)((HitWindows.Good - HitWindows.Great) / (maxHitWindows * 2)) } - });; + }); if (HitWindows.Meh != 0) bar.Add(new Box From 62a24bf16d38ffbf9460a8025748c012b20d1939 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Aug 2019 13:18:34 +0900 Subject: [PATCH 2451/5608] Fix a couple of rotation-related issues --- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 332e25750f..02505c3ec0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -174,9 +174,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces var newPos = slider.CurvePositionAt(completionProgress); var diff = lastPosition.HasValue ? lastPosition.Value - newPos : newPos - slider.CurvePositionAt(completionProgress + 0.01f); + if (diff == Vector2.Zero) + return; Position = newPos; - Rotation = 90 + (float)(-Math.Atan2(diff.X, diff.Y) * 180 / Math.PI); + Rotation = -90 + (float)(-Math.Atan2(diff.X, diff.Y) * 180 / Math.PI); lastPosition = newPos; } From 550311698b74769f95f35f130f72ae84e17c775d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Aug 2019 13:18:59 +0900 Subject: [PATCH 2452/5608] Update slider test scene --- .../TestSceneSlider.cs | 160 ++++++++++-------- 1 file changed, 86 insertions(+), 74 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index c5a27205d6..29c71a8903 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -10,7 +10,6 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Tests.Visual; using osuTK; using osuTK.Graphics; using osu.Game.Rulesets.Mods; @@ -27,83 +26,96 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; namespace osu.Game.Rulesets.Osu.Tests { [TestFixture] - public class TestSceneSlider : OsuTestScene + public class TestSceneSlider : SkinnableTestScene { public override IReadOnlyList RequiredTypes => new[] { + typeof(Slider), + typeof(SliderTick), + typeof(SliderTailCircle), typeof(SliderBall), typeof(SliderBody), - typeof(SliderTick), + typeof(SnakingSliderBody), typeof(DrawableSlider), typeof(DrawableSliderTick), + typeof(DrawableSliderTail), + typeof(DrawableSliderHead), typeof(DrawableRepeatPoint), typeof(DrawableOsuHitObject) }; - private readonly Container content; - protected override Container Content => content; + private Container content; + + protected override Container Content + { + get + { + if (content == null) + base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 })); + + return content; + } + } private int depthIndex; public TestSceneSlider() { - base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 })); + AddStep("Big Single", () => SetContents(() => testSimpleBig())); + AddStep("Medium Single", () => SetContents(() => testSimpleMedium())); + AddStep("Small Single", () => SetContents(() => testSimpleSmall())); + AddStep("Big 1 Repeat", () => SetContents(() => testSimpleBig(1))); + AddStep("Medium 1 Repeat", () => SetContents(() => testSimpleMedium(1))); + AddStep("Small 1 Repeat", () => SetContents(() => testSimpleSmall(1))); + AddStep("Big 2 Repeats", () => SetContents(() => testSimpleBig(2))); + AddStep("Medium 2 Repeats", () => SetContents(() => testSimpleMedium(2))); + AddStep("Small 2 Repeats", () => SetContents(() => testSimpleSmall(2))); - AddStep("Big Single", () => testSimpleBig()); - AddStep("Medium Single", () => testSimpleMedium()); - AddStep("Small Single", () => testSimpleSmall()); - AddStep("Big 1 Repeat", () => testSimpleBig(1)); - AddStep("Medium 1 Repeat", () => testSimpleMedium(1)); - AddStep("Small 1 Repeat", () => testSimpleSmall(1)); - AddStep("Big 2 Repeats", () => testSimpleBig(2)); - AddStep("Medium 2 Repeats", () => testSimpleMedium(2)); - AddStep("Small 2 Repeats", () => testSimpleSmall(2)); + AddStep("Slow Slider", () => SetContents(testSlowSpeed)); // slow long sliders take ages already so no repeat steps + AddStep("Slow Short Slider", () => SetContents(() => testShortSlowSpeed())); + AddStep("Slow Short Slider 1 Repeats", () => SetContents(() => testShortSlowSpeed(1))); + AddStep("Slow Short Slider 2 Repeats", () => SetContents(() => testShortSlowSpeed(2))); - AddStep("Slow Slider", testSlowSpeed); // slow long sliders take ages already so no repeat steps - AddStep("Slow Short Slider", () => testShortSlowSpeed()); - AddStep("Slow Short Slider 1 Repeats", () => testShortSlowSpeed(1)); - AddStep("Slow Short Slider 2 Repeats", () => testShortSlowSpeed(2)); + AddStep("Fast Slider", () => SetContents(() => testHighSpeed())); + AddStep("Fast Slider 1 Repeat", () => SetContents(() => testHighSpeed(1))); + AddStep("Fast Slider 2 Repeats", () => SetContents(() => testHighSpeed(2))); + AddStep("Fast Short Slider", () => SetContents(() => testShortHighSpeed())); + AddStep("Fast Short Slider 1 Repeat", () => SetContents(() => testShortHighSpeed(1))); + AddStep("Fast Short Slider 2 Repeats", () => SetContents(() => testShortHighSpeed(2))); + AddStep("Fast Short Slider 6 Repeats", () => SetContents(() => testShortHighSpeed(6))); - AddStep("Fast Slider", () => testHighSpeed()); - AddStep("Fast Slider 1 Repeat", () => testHighSpeed(1)); - AddStep("Fast Slider 2 Repeats", () => testHighSpeed(2)); - AddStep("Fast Short Slider", () => testShortHighSpeed()); - AddStep("Fast Short Slider 1 Repeat", () => testShortHighSpeed(1)); - AddStep("Fast Short Slider 2 Repeats", () => testShortHighSpeed(2)); - AddStep("Fast Short Slider 6 Repeats", () => testShortHighSpeed(6)); + AddStep("Perfect Curve", () => SetContents(() => testPerfect())); + AddStep("Perfect Curve 1 Repeat", () => SetContents(() => testPerfect(1))); + AddStep("Perfect Curve 2 Repeats", () => SetContents(() => testPerfect(2))); - AddStep("Perfect Curve", () => testPerfect()); - AddStep("Perfect Curve 1 Repeat", () => testPerfect(1)); - AddStep("Perfect Curve 2 Repeats", () => testPerfect(2)); + AddStep("Linear Slider", () => SetContents(() => testLinear())); + AddStep("Linear Slider 1 Repeat", () => SetContents(() => testLinear(1))); + AddStep("Linear Slider 2 Repeats", () => SetContents(() => testLinear(2))); - AddStep("Linear Slider", () => testLinear()); - AddStep("Linear Slider 1 Repeat", () => testLinear(1)); - AddStep("Linear Slider 2 Repeats", () => testLinear(2)); + AddStep("Bezier Slider", () => SetContents(() => testBezier())); + AddStep("Bezier Slider 1 Repeat", () => SetContents(() => testBezier(1))); + AddStep("Bezier Slider 2 Repeats", () => SetContents(() => testBezier(2))); - AddStep("Bezier Slider", () => testBezier()); - AddStep("Bezier Slider 1 Repeat", () => testBezier(1)); - AddStep("Bezier Slider 2 Repeats", () => testBezier(2)); + AddStep("Linear Overlapping", () => SetContents(() => testLinearOverlapping())); + AddStep("Linear Overlapping 1 Repeat", () => SetContents(() => testLinearOverlapping(1))); + AddStep("Linear Overlapping 2 Repeats", () => SetContents(() => testLinearOverlapping(2))); - AddStep("Linear Overlapping", () => testLinearOverlapping()); - AddStep("Linear Overlapping 1 Repeat", () => testLinearOverlapping(1)); - AddStep("Linear Overlapping 2 Repeats", () => testLinearOverlapping(2)); + AddStep("Catmull Slider", () => SetContents(() => testCatmull())); + AddStep("Catmull Slider 1 Repeat", () => SetContents(() => testCatmull(1))); + AddStep("Catmull Slider 2 Repeats", () => SetContents(() => testCatmull(2))); - AddStep("Catmull Slider", () => testCatmull()); - AddStep("Catmull Slider 1 Repeat", () => testCatmull(1)); - AddStep("Catmull Slider 2 Repeats", () => testCatmull(2)); + AddStep("Big Single, Large StackOffset", () => SetContents(() => testSimpleBigLargeStackOffset())); + AddStep("Big 1 Repeat, Large StackOffset", () => SetContents(() => testSimpleBigLargeStackOffset(1))); - AddStep("Big Single, Large StackOffset", () => testSimpleBigLargeStackOffset()); - AddStep("Big 1 Repeat, Large StackOffset", () => testSimpleBigLargeStackOffset(1)); - - AddStep("Distance Overflow", () => testDistanceOverflow()); - AddStep("Distance Overflow 1 Repeat", () => testDistanceOverflow(1)); + AddStep("Distance Overflow", () => SetContents(() => testDistanceOverflow())); + AddStep("Distance Overflow 1 Repeat", () => SetContents(() => testDistanceOverflow(1))); } - private void testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats); + private Drawable testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats); - private void testSimpleBigLargeStackOffset(int repeats = 0) => createSlider(2, repeats: repeats, stackHeight: 10); + private Drawable testSimpleBigLargeStackOffset(int repeats = 0) => createSlider(2, repeats: repeats, stackHeight: 10); - private void testDistanceOverflow(int repeats = 0) + private Drawable testDistanceOverflow(int repeats = 0) { var slider = new Slider { @@ -120,22 +132,22 @@ namespace osu.Game.Rulesets.Osu.Tests StackHeight = 10 }; - addSlider(slider, 2, 2); + return createDrawable(slider, 2, 2); } - private void testSimpleMedium(int repeats = 0) => createSlider(5, repeats: repeats); + private Drawable testSimpleMedium(int repeats = 0) => createSlider(5, repeats: repeats); - private void testSimpleSmall(int repeats = 0) => createSlider(7, repeats: repeats); + private Drawable testSimpleSmall(int repeats = 0) => createSlider(7, repeats: repeats); - private void testSlowSpeed() => createSlider(speedMultiplier: 0.5); + private Drawable testSlowSpeed() => createSlider(speedMultiplier: 0.5); - private void testShortSlowSpeed(int repeats = 0) => createSlider(distance: 100, repeats: repeats, speedMultiplier: 0.5); + private Drawable testShortSlowSpeed(int repeats = 0) => createSlider(distance: 100, repeats: repeats, speedMultiplier: 0.5); - private void testHighSpeed(int repeats = 0) => createSlider(repeats: repeats, speedMultiplier: 15); + private Drawable testHighSpeed(int repeats = 0) => createSlider(repeats: repeats, speedMultiplier: 15); - private void testShortHighSpeed(int repeats = 0) => createSlider(distance: 100, repeats: repeats, speedMultiplier: 15); + private Drawable testShortHighSpeed(int repeats = 0) => createSlider(distance: 100, repeats: repeats, speedMultiplier: 15); - private void createSlider(float circleSize = 2, float distance = 400, int repeats = 0, double speedMultiplier = 2, int stackHeight = 0) + private Drawable createSlider(float circleSize = 2, float distance = 400, int repeats = 0, double speedMultiplier = 2, int stackHeight = 0) { var slider = new Slider { @@ -151,10 +163,10 @@ namespace osu.Game.Rulesets.Osu.Tests StackHeight = stackHeight }; - addSlider(slider, circleSize, speedMultiplier); + return createDrawable(slider, circleSize, speedMultiplier); } - private void testPerfect(int repeats = 0) + private Drawable testPerfect(int repeats = 0) { var slider = new Slider { @@ -170,12 +182,12 @@ namespace osu.Game.Rulesets.Osu.Tests NodeSamples = createEmptySamples(repeats) }; - addSlider(slider, 2, 3); + return createDrawable(slider, 2, 3); } - private void testLinear(int repeats = 0) => createLinear(repeats); + private Drawable testLinear(int repeats = 0) => createLinear(repeats); - private void createLinear(int repeats) + private Drawable createLinear(int repeats) { var slider = new Slider { @@ -194,12 +206,12 @@ namespace osu.Game.Rulesets.Osu.Tests NodeSamples = createEmptySamples(repeats) }; - addSlider(slider, 2, 3); + return createDrawable(slider, 2, 3); } - private void testBezier(int repeats = 0) => createBezier(repeats); + private Drawable testBezier(int repeats = 0) => createBezier(repeats); - private void createBezier(int repeats) + private Drawable createBezier(int repeats) { var slider = new Slider { @@ -217,12 +229,12 @@ namespace osu.Game.Rulesets.Osu.Tests NodeSamples = createEmptySamples(repeats) }; - addSlider(slider, 2, 3); + return createDrawable(slider, 2, 3); } - private void testLinearOverlapping(int repeats = 0) => createOverlapping(repeats); + private Drawable testLinearOverlapping(int repeats = 0) => createOverlapping(repeats); - private void createOverlapping(int repeats) + private Drawable createOverlapping(int repeats) { var slider = new Slider { @@ -241,12 +253,12 @@ namespace osu.Game.Rulesets.Osu.Tests NodeSamples = createEmptySamples(repeats) }; - addSlider(slider, 2, 3); + return createDrawable(slider, 2, 3); } - private void testCatmull(int repeats = 0) => createCatmull(repeats); + private Drawable testCatmull(int repeats = 0) => createCatmull(repeats); - private void createCatmull(int repeats = 0) + private Drawable createCatmull(int repeats = 0) { var repeatSamples = new List>(); for (int i = 0; i < repeats; i++) @@ -267,7 +279,7 @@ namespace osu.Game.Rulesets.Osu.Tests NodeSamples = repeatSamples }; - addSlider(slider, 3, 1); + return createDrawable(slider, 3, 1); } private List> createEmptySamples(int repeats) @@ -278,7 +290,7 @@ namespace osu.Game.Rulesets.Osu.Tests return repeatSamples; } - private void addSlider(Slider slider, float circleSize, double speedMultiplier) + private Drawable createDrawable(Slider slider, float circleSize, double speedMultiplier) { var cpi = new ControlPointInfo(); cpi.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = speedMultiplier }); @@ -296,7 +308,7 @@ namespace osu.Game.Rulesets.Osu.Tests drawable.OnNewResult += onNewResult; - Add(drawable); + return drawable; } private float judgementOffsetDirection = 1; From b5cb59faf2a3f17602e7c2d81dc1c8970c705cb8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Aug 2019 13:19:23 +0900 Subject: [PATCH 2453/5608] Add default skin sprites and specular/diffuse layer support --- .../Resources/default-skin/sliderb-nd@2x.png | Bin 0 -> 14258 bytes .../default-skin/sliderb-spec@2x.png | Bin 0 -> 13141 bytes .../Resources/default-skin/sliderb0@2x.png | Bin 0 -> 17053 bytes .../Resources/default-skin/sliderb1@2x.png | Bin 0 -> 17792 bytes .../Resources/default-skin/sliderb2@2x.png | Bin 0 -> 18268 bytes .../Resources/default-skin/sliderb3@2x.png | Bin 0 -> 18182 bytes .../Resources/default-skin/sliderb4@2x.png | Bin 0 -> 18062 bytes .../Resources/default-skin/sliderb5@2x.png | Bin 0 -> 16895 bytes .../Resources/default-skin/sliderb6@2x.png | Bin 0 -> 16702 bytes .../Resources/default-skin/sliderb7@2x.png | Bin 0 -> 17139 bytes .../Resources/default-skin/sliderb8@2x.png | Bin 0 -> 17084 bytes .../Resources/default-skin/sliderb9@2x.png | Bin 0 -> 17067 bytes osu.Game/Skinning/LegacySkin.cs | 23 +++++++++++++++--- 13 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb-nd@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb-spec@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb0@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb1@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb2@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb3@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb4@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb5@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb6@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb7@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb8@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb9@2x.png diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb-nd@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb-nd@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..626fd91e386796be54e3ff952006082d90361319 GIT binary patch literal 14258 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb-spec@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb-spec@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..76fd9ab16807c2ef61dd2aa0db47c78262db03b2 GIT binary patch literal 13141 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 O@*I3?M71L9&Hn(Rv4%VV literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb1@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb1@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e99f076947aa7ca1614fe825839dd3d7b8dcc303 GIT binary patch literal 17792 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb2@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb2@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cd36a0ae169e1d876012402b2b7aa34a13a179d6 GIT binary patch literal 18268 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 SqgKcO0000l1{&5@md}*`-!Dp9 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 Y0Z!VEjc(%0RR91007*qoM6N<$f_m)to&W#< literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb4@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb4@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a5b19887d64f0040da387029545dea15d85669c9 GIT binary patch literal 18062 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 Hu0mjf{m45K literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb5@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4bb01f0e88229c6433c6363d7f7c725776372683 GIT binary patch literal 16895 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

    {E0 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 E0O3MVi~s-t literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb6@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb6@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..859e0aa4c1f0d548eda3fe4c6c02f7fc4af1831f GIT binary patch literal 16702 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb8@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb8@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fcdf4ed4a4a76808dbfe41e54a45d4433dc1320b GIT binary patch literal 17084 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb9@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/sliderb9@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c990cf0fe6784265e2419070a27459fa6f7b2fa0 GIT binary patch literal 17067 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 => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Color4.White; + + InternalChildren = new[] + { + new Sprite + { + Texture = skin.GetTexture("sliderb-nd"), + Colour = new Color4(5, 5, 5, 255), + }, + animationContent, + new Sprite + { + Texture = skin.GetTexture("sliderb-spec"), + Blending = BlendingMode.Additive, + }, + }; } } From 3b7cee2d45ef027b93d71950ff4ccc24843323b3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Aug 2019 13:50:16 +0900 Subject: [PATCH 2454/5608] Fix LegacySkin not checking for @2x hitcircle when deciding sizing --- osu.Game/Skinning/LegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 3eda76e40f..7c621ee87f 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -59,7 +59,7 @@ namespace osu.Game.Skinning Samples = audioManager.GetSampleStore(storage); Textures = new TextureStore(new TextureLoaderStore(storage)); - using (var testStream = storage.GetStream("hitcircle")) + using (var testStream = storage.GetStream("hitcircle@2x") ?? storage.GetStream("hitcircle")) hasHitCircle |= testStream != null; if (hasHitCircle) From c4251d512e069cfee758bafe8f85dd7113d360e3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Aug 2019 08:00:09 +0300 Subject: [PATCH 2455/5608] Simplify bar building --- .../HitErrorDisplay/DefaultHitErrorDisplay.cs | 69 ++++++++----------- 1 file changed, 27 insertions(+), 42 deletions(-) diff --git a/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs index 2d05dc8aba..a9dd7ffcca 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private const int spacing = 3; private readonly SpriteIcon arrow; - private readonly FillFlowContainer bar; + private readonly FillFlowContainer bar; private readonly Container judgementsContainer; private readonly Queue judgementOffsets = new Queue(); private readonly double maxHitWindows; @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay Width = judgement_line_width, RelativeSizeAxes = Axes.Y, }, - bar = new FillFlowContainer + bar = new FillFlowContainer { Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, @@ -85,54 +85,39 @@ namespace osu.Game.Screens.Play.HitErrorDisplay [BackgroundDependencyLoader] private void load(OsuColour colours) { - Box topGreenBox; - Box bottomGreenBox; - if (HitWindows.Meh != 0) - bar.Add(new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(colours.Yellow.Opacity(0), colours.Yellow), - Height = (float)((maxHitWindows - HitWindows.Good) / (maxHitWindows * 2)) - }); - - bar.AddRange(new Drawable[] { - topGreenBox = new Box + bar.AddRange(new[] { - RelativeSizeAxes = Axes.Both, - Colour = colours.Green, - Height = (float)((HitWindows.Good - HitWindows.Great) / (maxHitWindows * 2)) - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.BlueLight, - Height = (float)(HitWindows.Great / maxHitWindows) - }, - bottomGreenBox = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Green, - Height = (float)((HitWindows.Good - HitWindows.Great) / (maxHitWindows * 2)) - } - }); - - if (HitWindows.Meh != 0) - bar.Add(new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(colours.Yellow, colours.Yellow.Opacity(0)), - Height = (float)((maxHitWindows - HitWindows.Good) / (maxHitWindows * 2)) + createColoredPiece(ColourInfo.GradientVertical(colours.Yellow.Opacity(0), colours.Yellow), + (maxHitWindows - HitWindows.Good) / (maxHitWindows * 2)), + createColoredPiece(colours.Green, (HitWindows.Good - HitWindows.Great) / (maxHitWindows * 2)), + createColoredPiece(colours.BlueLight, HitWindows.Great / maxHitWindows), + createColoredPiece(colours.Green, (HitWindows.Good - HitWindows.Great) / (maxHitWindows * 2)), + createColoredPiece(ColourInfo.GradientVertical(colours.Yellow, colours.Yellow.Opacity(0)), + (maxHitWindows - HitWindows.Good) / (maxHitWindows * 2)) }); - - if (HitWindows.Meh == 0) + } + else { - topGreenBox.Colour = ColourInfo.GradientVertical(colours.Green.Opacity(0), colours.Green); - bottomGreenBox.Colour = ColourInfo.GradientVertical(colours.Green, colours.Green.Opacity(0)); + bar.AddRange(new[] + { + createColoredPiece(ColourInfo.GradientVertical(colours.Green.Opacity(0), colours.Green), + (HitWindows.Good - HitWindows.Great) / (maxHitWindows * 2)), + createColoredPiece(colours.BlueLight, HitWindows.Great / maxHitWindows), + createColoredPiece(ColourInfo.GradientVertical(colours.Green, colours.Green.Opacity(0)), + (HitWindows.Good - HitWindows.Great) / (maxHitWindows * 2)), + }); } } + private Box createColoredPiece(ColourInfo colour, double height) => new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colour, + Height = (float)height + }; + public override void OnNewJudgement(JudgementResult newJudgement) { if (!newJudgement.IsHit) From d337f9b482a9144d85d8d12682b0a0461a8f3bff Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Aug 2019 08:03:17 +0300 Subject: [PATCH 2456/5608] DefaultHitErrorDisplay -> BarHitErrorDisplay --- osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs | 2 +- .../{DefaultHitErrorDisplay.cs => BarHitErrorDisplay.cs} | 4 ++-- .../Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game/Screens/Play/HitErrorDisplay/{DefaultHitErrorDisplay.cs => BarHitErrorDisplay.cs} (97%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs index 006773a091..02773e0561 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs @@ -115,7 +115,7 @@ namespace osu.Game.Tests.Visual.Gameplay } }); - Add(display = new DefaultHitErrorDisplay(overallDifficulty, hitWindows) + Add(display = new BarHitErrorDisplay(overallDifficulty, hitWindows) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs similarity index 97% rename from osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs rename to osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs index a9dd7ffcca..26f9e3a5e0 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/DefaultHitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs @@ -18,7 +18,7 @@ using System.Linq; namespace osu.Game.Screens.Play.HitErrorDisplay { - public class DefaultHitErrorDisplay : HitErrorDisplay + public class BarHitErrorDisplay : HitErrorDisplay { private const int stored_judgements_amount = 5; private const int bar_width = 3; @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private readonly Queue judgementOffsets = new Queue(); private readonly double maxHitWindows; - public DefaultHitErrorDisplay(float overallDifficulty, HitWindows hitWindows, bool reversed = false) + public BarHitErrorDisplay(float overallDifficulty, HitWindows hitWindows, bool reversed = false) : base(overallDifficulty, hitWindows) { maxHitWindows = HitWindows.Meh == 0 ? HitWindows.Good : HitWindows.Meh; diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs index bbed2b1618..e4a630245d 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs @@ -80,7 +80,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private void createNew(bool reversed = false) { - var display = new DefaultHitErrorDisplay(overallDifficulty, hitWindows, reversed) + var display = new BarHitErrorDisplay(overallDifficulty, hitWindows, reversed) { Margin = new MarginPadding(margin), Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, From 9f64e0962534b6a4aa149ad24d2d0d18c1815ee3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Aug 2019 08:45:51 +0300 Subject: [PATCH 2457/5608] Move HitErrorDisplayOverlay back to the HUD --- .../Visual/Gameplay/TestSceneHitErrorDisplay.cs | 2 +- osu.Game/Screens/Play/HUDOverlay.cs | 8 ++++++++ .../Play/HitErrorDisplay/BarHitErrorDisplay.cs | 4 ++-- .../Screens/Play/HitErrorDisplay/HitErrorDisplay.cs | 3 +-- .../Play/HitErrorDisplay/HitErrorDisplayOverlay.cs | 12 ++++-------- osu.Game/Screens/Play/Player.cs | 4 ---- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs index 02773e0561..a148bdad67 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs @@ -115,7 +115,7 @@ namespace osu.Game.Tests.Visual.Gameplay } }); - Add(display = new BarHitErrorDisplay(overallDifficulty, hitWindows) + Add(display = new BarHitErrorDisplay(hitWindows) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 43b9491750..02432cf64e 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -15,6 +15,7 @@ using osu.Game.Overlays.Notifications; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Play.HitErrorDisplay; using osu.Game.Screens.Play.HUD; using osuTK; using osuTK.Input; @@ -33,6 +34,7 @@ namespace osu.Game.Screens.Play public readonly HealthDisplay HealthDisplay; public readonly SongProgress Progress; public readonly ModDisplay ModDisplay; + public readonly HitErrorDisplayOverlay HitErrorDisplayOverlay; public readonly HoldForMenuButton HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; @@ -84,6 +86,7 @@ namespace osu.Game.Screens.Play HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), ModDisplay = CreateModsContainer(), + HitErrorDisplayOverlay = CreateHitErrorDisplayOverlay(), } }, PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), @@ -256,6 +259,11 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20, Right = 10 }, }; + protected virtual HitErrorDisplayOverlay CreateHitErrorDisplayOverlay() => new HitErrorDisplayOverlay(scoreProcessor) + { + RelativeSizeAxes = Axes.Both, + }; + protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); protected virtual void BindProcessor(ScoreProcessor processor) diff --git a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs index 26f9e3a5e0..6539ce38a8 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs @@ -34,8 +34,8 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private readonly Queue judgementOffsets = new Queue(); private readonly double maxHitWindows; - public BarHitErrorDisplay(float overallDifficulty, HitWindows hitWindows, bool reversed = false) - : base(overallDifficulty, hitWindows) + public BarHitErrorDisplay(HitWindows hitWindows, bool reversed = false) + : base(hitWindows) { maxHitWindows = HitWindows.Meh == 0 ? HitWindows.Good : HitWindows.Meh; diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs index 10b5e5b1cb..422e151d8a 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs @@ -11,10 +11,9 @@ namespace osu.Game.Screens.Play.HitErrorDisplay { protected readonly HitWindows HitWindows; - protected HitErrorDisplay(float overallDifficulty, HitWindows hitWindows) + protected HitErrorDisplay(HitWindows hitWindows) { HitWindows = hitWindows; - HitWindows.SetDifficulty(overallDifficulty); } public abstract void OnNewJudgement(JudgementResult newJudgement); diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs index e4a630245d..1c61904461 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs @@ -21,22 +21,18 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private readonly Bindable type = new Bindable(); private readonly HitWindows hitWindows; private readonly ScoreProcessor processor; - private readonly float overallDifficulty; - public HitErrorDisplayOverlay(ScoreProcessor processor, WorkingBeatmap workingBeatmap) + public HitErrorDisplayOverlay(ScoreProcessor processor) { this.processor = processor; - - overallDifficulty = workingBeatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty; hitWindows = processor.CreateHitWindows(); - - RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] - private void load(OsuConfigManager config) + private void load(OsuConfigManager config, Bindable workingBeatmap) { config.BindWith(OsuSetting.ScoreMeter, type); + hitWindows.SetDifficulty(workingBeatmap.Value.BeatmapInfo.BaseDifficulty.OverallDifficulty); } protected override void LoadComplete() @@ -80,7 +76,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private void createNew(bool reversed = false) { - var display = new BarHitErrorDisplay(overallDifficulty, hitWindows, reversed) + var display = new BarHitErrorDisplay(hitWindows, reversed) { Margin = new MarginPadding(margin), Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 9ef8cc4509..e7398be176 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -24,7 +24,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; -using osu.Game.Screens.Play.HitErrorDisplay; using osu.Game.Screens.Ranking; using osu.Game.Skinning; using osu.Game.Users; @@ -74,8 +73,6 @@ namespace osu.Game.Screens.Play protected HUDOverlay HUDOverlay { get; private set; } - protected HitErrorDisplayOverlay HitErrorDisplayOverlay { get; private set; } - public bool LoadedBeatmapSuccessfully => DrawableRuleset?.Objects.Any() == true; protected GameplayClockContainer GameplayClockContainer { get; private set; } @@ -160,7 +157,6 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre }, - HitErrorDisplayOverlay = new HitErrorDisplayOverlay(ScoreProcessor, working), new SkipOverlay(DrawableRuleset.GameplayStartTime) { RequestSeek = GameplayClockContainer.Seek From 596ee150c6e2db6fc3963ca237afba868432543a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Aug 2019 08:51:41 +0300 Subject: [PATCH 2458/5608] Add xmldoc for not obvious const --- .../Play/HitErrorDisplay/BarHitErrorDisplay.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs index 6539ce38a8..f68e17c908 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs @@ -20,12 +20,15 @@ namespace osu.Game.Screens.Play.HitErrorDisplay { public class BarHitErrorDisplay : HitErrorDisplay { + ///

    + /// The amount of which will be stored to calculate arrow position. + /// private const int stored_judgements_amount = 5; - private const int bar_width = 3; + private const int judgement_fade_duration = 10000; + private const int arrow_move_duration = 500; private const int judgement_line_width = 8; private const int bar_height = 200; - private const int arrow_move_duration = 500; - private const int judgement_life_time = 10000; + private const int bar_width = 3; private const int spacing = 3; private readonly SpriteIcon arrow; @@ -127,7 +130,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay judgementsContainer.Add(judgementLine); - judgementLine.FadeOut(judgement_life_time, Easing.OutQuint).Expire(); + judgementLine.FadeOut(judgement_fade_duration, Easing.OutQuint).Expire(); arrow.MoveToY(calculateArrowPosition(newJudgement), arrow_move_duration, Easing.OutQuint); } From 84530b7839dce1db5481ce52ca86a9803529444f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Aug 2019 15:02:07 +0900 Subject: [PATCH 2459/5608] Colour the correct layer --- osu.Game/Skinning/LegacySkin.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index d6446625a5..26ee434bb4 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -43,6 +43,7 @@ namespace osu.Game.Skinning public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini") { + if (!Configuration.CustomColours.ContainsKey("SliderBall")) Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); } private readonly bool hasHitCircle; @@ -347,7 +348,7 @@ namespace osu.Game.Skinning [BackgroundDependencyLoader] private void load(ISkinSource skin, DrawableHitObject drawableObject) { - Colour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Color4.White; + animationContent.Colour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Color4.White; InternalChildren = new[] { From f72edb8bf8840139adf03a8a125a09373167a20f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Aug 2019 09:03:31 +0300 Subject: [PATCH 2460/5608] Add missing blank line --- osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs index f68e17c908..d8ae3dd9b0 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs @@ -24,6 +24,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay /// The amount of which will be stored to calculate arrow position. ///
    private const int stored_judgements_amount = 5; + private const int judgement_fade_duration = 10000; private const int arrow_move_duration = 500; private const int judgement_line_width = 8; From 9fbc8440fc069ce732f6a7961366269062fdcd53 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Aug 2019 17:39:16 +0900 Subject: [PATCH 2461/5608] Add actual testing of animations --- .../Resources/special-skin/hit0-0@2x.png | Bin 4020 -> 3009 bytes .../Resources/special-skin/hit0-1@2x.png | Bin 0 -> 8378 bytes .../Resources/special-skin/hit100-0@2x.png | Bin 5653 -> 3461 bytes .../Resources/special-skin/hit100-1@2x.png | Bin 0 -> 9934 bytes .../Resources/special-skin/hit300-0@2x.png | Bin 5004 -> 3928 bytes .../Resources/special-skin/hit300-1@2x.png | Bin 0 -> 13096 bytes .../Resources/special-skin/hit50-0@2x.png | Bin 3861 -> 2966 bytes .../Resources/special-skin/hit50-1@2x.png | Bin 0 -> 9138 bytes .../SkinnableTestScene.cs | 45 +++++++++++------- 9 files changed, 27 insertions(+), 18 deletions(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit0-1@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit100-1@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit300-1@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit50-1@2x.png diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit0-0@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit0-0@2x.png index 9d2ed3a7fa3d5bc0aa43098e9247fa3f6a7c6f80..37e7e9143f63e30bcfd3de38c46dac951451f43d 100644 GIT binary patch literal 3009 zcmb_eX;c$g7OpI^4Ja}_dKeWlp;b6-_5~7_u*o9BP9vy|#H4^INhKkW00Pl=T5a*r z9vwhI!*nA|;|Qp@MoHm5fMA2qd|^`~yVy7#;He&2od z>R?1zppDfZtpEV92@dj)0ss_Zq5umsyFeLk2be4ndE&>^ z8az(G_rz~zgpxzWeqf3qC`$@PXNAS^vUc%Ud_2bs=b>OD076j4#VLfTqBOR`6aNmE zjo7AT5+3)?MYhWm|GucW&1*a7LmfF(OIkwI4YUqMk2eBC^Q0v z$)=OpR4VSng-5bU`AO_3|9}sH)Gj; zQjjZyq%jbbx-bP1DUb|GOM%2VKR=V|ESz&FmnRUJ7F|q2z3feV(1Aw_M*xx5c(fLbHL1b6ZDwsR8&Sqv4Zmrwe zV!JYIHP#umNonV68E6@SJ|-sm3?42jJ!;=Fms~E_d(cjiblcE}&gDM+s!7^I4_&fB z>o|(G1-wlk11#{Vj8BKOSkZrjR4PwY9LzjZbzz-N-tDe3!?~*Z0*_O#R_G?H2HWc= z?#n$+m)OHK=09h_9NiW3bJzoC+kHxtoYcnns|H);la{P`^+okk)B%V9SipNR52s2R ze+Qszd*hV=4hXUK&V2!!;n1}Y?cw8UYm{?fJEn8W5#=l}dnj>=0Bn^vQ?bgmGkwID z8tdXLOl@`5{+)Rknvzn4THi?mP|hiqiE{-2_PlU*I+oyy?)s+hj-O37pv~^=A+np% z4uMq@w8xPN-=`@5_MBuV^A>{W+Xdsjc0e{nNq}ec6Z|F~J!-uUYuhDnrPceST z*E+y;P0C9lN=k+C8Romnhc#;o!*j}$pJXivGQ)tQR?BLyyy1to!h!RZJm4V5Bbpm z+ALAu@LA1E8~A#~=v-MCXYj%3;8`7{HX76A>Q&@pXYB5}0FzpfH<}9DB?h<759%TF z$QztPqe;{Epf5GH39DIa-A#FuvLI|m_te2TEAMvmN#0w|xhCVt0G9GCwWVXrb3O2= z?s|vueAnvcl2ck^_1}&kt*#uXue;LfI1w*P4yq0r!E`XjwB(qA8zbYhA_ zfX>d{b?eEG+6#!D7wQM(p4ItU>#{oFjiPn~A0xj1L>o*QdO&S^HZ{9%*K=ot&Z|RL zmtWau1E1^DPYN%X4>m(*j7!h&UtSm#c~@X*yL&~gSE=QOL^E-f;_OpZj{I`oiMPW0 zvr~}>J3pz0CP;b9S1B`ZP10VIpDwE#oN_Q!o5vkPXt!^bl~lbY&Ht!03|!zqiAR^! zcKP0O0UFw`ebq8$rAcabWK-`@2d*{!LH<1=$iOU47kf)*A2)1`yIT6vka43g%!D%z zdKX<3SngRZ6}^dADI~%6AVO6*FTDK_8|AEFdbKsQ&FwpB>SZDs2tVE9Guz8nC7wOG zwCc&iVgyGQMCuBVXQ@?(yq+epoEJby?{05P>4nz3g&?2?3juZ-SpbvbvN+qq9- zd%{XP0vsxV4Lq~)Sa^>LJ=5KksGnL6CjatJV zr#)3Kd)bh>(hfn07^Nm|9p0*(Y}Fs%{3KX6xV49J)8tOMUOF=tm=9kbo>F%UoJMx( ziUaH`0SoWj7Ul6R+tr-;_z|5u=dmoiMDtXow^%uqPi={RD=Mit$QqZqn6J}!sb4)( z6`W)n6t>OxTC;|Jq203|QCO`4V7rf=NsFh#r!zhs(&AbAKSL_DhRsS8aNZ)>X>IhT R0@F`*@WwFzYTv}Y{{lUSa}NLj literal 4020 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 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit0-1@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit0-1@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b75c71927c6671c72bc8ad92d25235067d5a2743 GIT binary patch literal 8378 zcmd6McTkhvw)c}56$A@Sx?mJRAq43VdhcC82p}ayN)mbrEh8N)1v%uQ#6azUTYqn=|*1Z|=;wnc1^T*7~irSK0IIy&??s)X$$|I|l&3c})!! zBLDzVh9H3I45dSQ& zAn|gMh5l11b6o>&Wt<0!TTD*m&Whjct z;C{Al@Y{kya17?pzWzb&>1BlaKWhA2YEKh?Hx%3m<%#q5u&4OL@!H?a6x;pxg8mRv zw2{{LaH2TH)>Q>(?~OrWy);#1p_G3F9h@Ab#YKh0B*h%WVJJ}v5tyi$h$zg~Rzwo! zAS5IvA|dP`B_byAH_pG~S5sCI7giJ&S5guYyM0?#N=ZUZR8?F`SVTlfRY_Dy{BK@O ztf!YP)*kh@Y$uBBzj(#|TV82p50tGJ&cg(UbNxFC4DRE+aGv*ZZrsYsf4nZm&8KT? z?}Yucc=L~={<&`zl!ucK%0bNohvEK*rKO$zjTRz8q9V8LMQ_7|B_!-<8kDNjiv$ z!W>2H>?K8n#e}3p9iV^lJN*Az5Kd7F{wG}iukiVMi4v24hW|Mg?r4PB;)!+Zr3o@`w@NgjhydhYAV?{xR>a))03@^wzVfhBr* zYT2r*vvV_T=l6*394SQt=Qt_gD>L=XOO`k}B7vT)CfCfT2dw%(#@FZpgof;JV*r3q z4gkuLqCn{`QQCiK%1seXMQLCFAW%APO8XB@6)2+rGK7$1LiMKt1C2u)a&_#+foXrr zAyVI8_Z6)FRKQYUr_t9PS8tLu()LQ;&{bfi?LmZj`$J^Fm`wpPokm`!u`0hh6nXQ)untg4bWd?F zeD}(`^LiNk7W^mKd~?h zT_*s$q{Er}O+_)e^QKgBcKQx`@r?Chaab$NCsNt;7wSDH9E4#E@< zT;hGZ3kiJpg!r~2Vl05+#lfBWy_Zpse6kr>7Ms0U|t(% zWD%)*uk~o+&XVVal=0ToMaELs^Wg3jzIru)rf~}CrdXN_edaT8XCpX=6~vd~UVWM1 z&I|B{h4@b^$d!%b-wzAhrH1I#tlr;^WXHL#4j=AQv1%>8)~d5^nHFLK5Wh@KnX$Ej zYmYWa(GXCvF;@5tS{=zg+GHmxmtKAcDjGM%VrVB6*Hq%&nW7cg1guvyYx3)INWeke#$n-<+_Y8$@Q1Rg2Z%Jc zhcXE3$HRE*I;?A~hJ)^|8E?k;`&IRKI}YMX?*MHnj;hq@!%F}ysG12}0~WFwgalV( zIpr-cm-@b?1#N;kf;-yQR);>UCISn2DphU8W2=*bch6h`;AwTS+~7U(>x-?#Ptc?3UOKqR8W#5E;e&S2bqt|3qfaj${XW+nWub|MEv zA&G0bLv8Ew)BX;8@;foACAC0l@6zBB2Jke09MyQW|4mhzKpz%RF#>qA9)hDMY(MPZ z0)26>iUDp>gAH&qI;vVlt+8*96^)J_J7NZV&aJ3kvmT=cEie~V$1U*N{6Ndpo#aPC z98|L=AF`hZ;o||<%b;)g(EFHr?;+K~pj)@%is=YGw=4ryha9@asCt*U`sr1^5Ar4( z$G%N`G!P%v?1$!sWM-Iu(n^Qj>6FV76mmbFdN+9kSdlcbNeEn@Y#9m5wCZkfmpHRB z6$1=EyjFJMQF>f|YmaaTOfBxGd8JT9QP8~<*tbSmj4r|~a<*>P$0#ELfMohZ*UA&f z&#tQg+5xG64vqG&nOWUaJCK#!OxU~o=ov7NxiE4XQ(s-qe*eZeQC(RS|sqM-rtwx=ZWTJH7 z5i7dXC%BW&bz-!TDx0T5>m9Fvp}lIRQT&=j-nV?2q4u=5)8Q}$k4VJD!12DDqgrWS zQxp#piHn7qvTE)R=tlx>7m)fZsAQL4ON7PvIiqdD>!+#eJ-eEp&8Me`(S7c;qGkHU zVYIy*zV@l*%Git%UL=^L1H`q3M8(@os9u=<8XEc%S&S$4L5D6^bp;xA2g~0_`>fTr zBN>hb?(3gf0VQeimJODidx!os*2L^*hc=pg63G0ZfsVjz9nNJ*tzZvz6IBFE(Rx4` zxwf@aU$p#C(kAeQ*TUh?kRV8#~-ND4jo4{@2`ckVloJV>t zd9bJZ+B20do1i-?+d)OLbft(#WodJRH)6YOAPP@-XVXWV!koi_YTMPxh4rQPd2eUG zM%4ep(n=NLH7^rpo2JrVzV`Ir9{JkR*%U%Y051+iAg5=^8C}8IA406&oo{zW%ILaR zlw93;$z1glii_U=QZT$$QFXYX5DY$IWp`OMc7tTU$z1-xTe&KiWr?M>i;F=^HK4iz zlG&D-+WK=6`1y^IEX}+K3^|xjD47TpJ^{Hy-QGq3D!?Sukq>HlXMg<}J69F^!Noik z2dS`C>p1&LNabe1_?s)7rSiNteSO9-DjA0k!BeLYbL#S1n-4Btng~Ypd>Sfp&qzeW zj#K86lt1KCsWt{@kovuu4xnI`@8^W*lX7^#a4JNct;FR7t-3f@i3M*1a*C2s{CSl=tSl!Hv0{587PYWctc0X+P(QO z7$Gxx+@JF^hn!c!k{@FtxbaOd$n4$KrFboE3R+cDNV%(K$erqjc?}VWImVv58m{5@=igBxeE|%uuS!sL%g2tY-Gfd6!3O zn;Y#a@6FJN8~S}}+8?{T49y0R1Rl@ zg9e|^R#Az~Zw<|+KFSzYdXGQN-80iX@^oY24WqQKS8%Wt@08MJfoCbhVtPO?Gi;H` z?_g&+ug{Zj^td1lCO6uu{j5%Xn703H6QLvJMd|ok=CHjMQ5i>8&*PuG8?Iq3^H*<{ z_?hgc%sy@R3H9Sk6zzZhwyKU+d3(8t{bJ5i@V;?Y(7_CuQOZ$d_eS1{*1EGo1Tv5q zzs!Fq(kym)gKzvCXn~Hw7B}hqNKd8B64RZWXozqL~ln0HG@ zGp|L|pJ%^LH>?RR?p2?Ed-P?XnYo>~^&7vRxc?pX3u!sN>W@e9tG3^NDUsT@ESQ9y_0}VPD}UP8k!{4IOZSY zfgA?cQ@vodh0v;Ko(6J#yh^GAGLZ`GNqyjcGP?af~4LehJCs%dyYV+c`aZ@7DX zO#`r)e-R@Pxb9I=JWv`Gu)Qc|9qKvh-=HDOk{`0-LVvWNl^3U5D9LND?mr@>XQZ0W zCN?-0e|tarBl#pehySS9Q}4Bbk}U8c&mbqFzKIva*ZBcQ3w`=lRe-(PaIP=oDH}ZZ z#|kl3VOGFjX0;QF&+;gXTz()?)jgK944w5ddjISMo1^Zty%KZh>|XF%mG0+s9f1ql z7n&fMzxRHrU4^sIxp0lhwd;LlM>n3^R}477WLe^3EWECn`iKhFy0NyHG8QVvGQIGz z*PR&Ncj+RPwi6It?_im;uRLx$|}u#y_(ywAzrtqwlp^}dk>hL4{q%TB#k9X(dG`TVVGp_(=($tf8UVirH;R7*In6*|p?TGqt&-_;m0%hKB zczx1!W16+q_-a1igw&s+1d(*;PiuLXyQ{|Nsv{7km;zjYPxXTbz<@i_(n(m8D*fF{md8JfJ!QdtJZ>}a2KGI ziX+?aHO-X!Lc|)`jk7w9{JG_A$xJ6o5BSPg^w7i`ToSy@n?_-LLoP(-0gJ039j1;d!|x&M#YQ{&$~niy&Y_o86B2aBP6gco&KsIDdC+`VGB_<(LRG) zYUSyjE{So{Y1pl0E_Ym^WosEkWkwL?!(pFTTDDtR_$;jDNqg-4~r$~XLl6B=$1PW|TY66mKBnVo3n{tV5f$uyZYbU0$dRq-! zIx(Ag)jtPi6z7b)1kZ7}equkR{;A)qtG!vIVji<|9L{h0eVfSmp^V+Ij8T^8c~fkP zpKv{s*M2g;?NoJ=HdIItz?#jT+!C7{990ML-3)utJ61_sS$j1yeH1EYlI)d{f{WjJ zlR3dr8j^iqdu4DfF*SAew$!thG1e%!jbPW)tj_|Ui+Zc;l@VdDBPCzJ0>XX$_SOQTa7S0^v4X_iKhGd zg{<9L|Jlw4KZ#$jGRv(L)j4`vSE|lwWjmTUpjLu%R&?4+?omxg02)7@JfvZ`7}|C; zXqh$-O2@aU0e#LoD*+Ip0(t_;92t4wH}5KQcFOLo$>&Q?lvmUThLIiuMr|%(h%Wxd zjWOgCMAYyVN$##&j8p8HzpqTqllc7|=CdP34e7oagJS(xA66AxUp$@Jr!xH|^g3bJ ze9UCmW+#w}8&#&3%7RqxnechlEKhu#`jJ z<%rr@Yylg1WHI{jq%G&A#rOO9-h+X?sR&$Bz!8ebKoYhM3~>87EqE%jUAeV}gqC3j zA^^Q)?_+i>x5cMh_&Z69!g{F_UJO&hX{-HYPu~k(obo|ws;>hEUz=821$^?iwe;7p!$jZmDt1_4QlX@arC|FE1#H$VL-*(Fagx7&yP8GbFuJ5P_^S9^z_I3V@suF9)fF6F9jNM%^_f}(uFDK-CbSrBCle8gY`C4vd$h0=&)ODpO1)j6K1G3&?Vc)Vw{HJMlKr`8VFGea4 ze*4a`&u>`EoaJgr3D}l=fT9~-4V``<n^_0tq}LcLCuv|yU5B9(t#RV zrcj`_>SN!;HBME46C_GJ{ri=?jRd)(>kpxWb<8r0;x78kZGJJw`;nL-|Ufr#`6c6X0y_G{R_*8|LR8g~^tF8nV8$0q{ z=ouFSV)W*ocWpfa+~P5rA1$KlI@lljXr`$Dg8#<#GxJc6vd%Uz`Gw-a8}X-mu?%lu zZHB*;n5s^0-G5Q$#Lrt_tK0Kibfnh8tZc*ov)p~I-_xWG|K0p$O_Zd`ofa;idHi#F zD=cy=iN-7amz-I-PKD6EI(GNdGd7VU@z0OM)q@c{ty84O#m=@r^Q^r zV%$R@og|H^YjTRWvM(47Nr(3Dr1A0y?>~$KGkCmU4!~93^wbFg_21Fw>4_Q_RbnoT zeYGwYpO9i;yPB=V_nhv_668g<$j%6j)mzL&%DTY5h<;!XI5Jhaar z@ifS;*f}Q7+eWfUz!$HWs??`51YtJ=k_OO%e4yTp53kmwa&(M*+9dl+-E)>=ezr;B|{c$|@4@^4d3hVBh@=GT3XtjPV6m)|crAeqNu`|Z2N0!=pM@l|ar zTUm5xdkpo;59lSK1|MH|4f7h!+8Bqg=^up7tOs%XM%oF1XOmvJlbn^FDN)yG z5u*O38hAo9#K9yOZb=kB>ErR!xD=+czAp5svhC6O;%aRTf5{Hu*c8MSeA FzW}dVh$;X8 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit100-0@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit100-0@2x.png index 777af3bd415263824913549c5c4c708c4d6e450a..79326674086568e677792fe57141e52e9944c33b 100644 GIT binary patch literal 3461 zcmb_fc|6qVAOFterbxXgM+RHAtugnBMg}>SY&X*b(Jj?!Ji z5`~tfQ;yP5iAI+~W|T6f5j)!2-@abEzy0I4`~34f&*%I3yg%>fb9}$gHz&Y<&0GTu z0{{T#dV9GC0sus_gaCRvnkk%jI$AR=7I=gTf;iCv5se1|s~Maq5a!LI#ejhzjggda z3v>p6IbvpTs36quTQZ%)a-_}bIEq^%-)IM8GF>|*x`m#kUOiV=3O zPbz{q7rWm`h57}+s2m;$!#U#NbQBf`Baj?Xcnp?AS_wlVQA7lih(KZBC_EX9B%{%= z&%;jRjmL;42fBNH_NCdm*u@G2TrvV75{Vo|7)K5-27w}xNC+evfkwkM8gPCRTR;=T z*?jvi2<{-C&SP=~Ob#11i%5&&2n8;78m7M;fyMRn`yH6g{~Rby$Pi*07lCp_B3P{1 zbA8h03j)Fa()delesB^OL3g7a7QShNSx zo#2LZbHkEQC=Zew!4vC&C!sMIq=y^U4gbZ~o6Q%{*mUrVZ>GlgXIt#w+LEa}kS5^p zf;pV{FI5l_%Moz+u^cXpN}bI*3HG%gjm~7x3YX6&>bG;dgFI#;$nfNGSg=o#CNuwn z1qO-5py*f>98Dn5;hI9C!HEnU79Nd>q7yM_9Fl}(*nPHV{J#-IXhv&6p)s{sK0Qg8Rw!Q$T6{oB^r6Bg;*S-M~6i0LKM)TOSv z+f4VGmS}}T9U-UYgu8_|U*5sjX9(>(iADqOed@hNl+n(Yzv50k=&J3yus-F@hY!8L z%OPV9L=SKU04QJrWB`B`0Q>Z6_{XAu3Fc3f{s+N~tsgh~*qWQ0Kb*eM7*U|!E}1JS z5>D25sC%zbIMbJ7d-8Ru;uNr1t#>K}>wOq4GXTZ!gA-~?J5-VLNQk%xtI3j?$2-J zJdOpgLg$#`wB7FS*3(62!-nOkQNv%x+1KyR)C*e>xJuHR)Lu{`e_ex9hxDl;@)PhR{nCPiRw86iuyS?43v7Yvg5>@;&yRz>3yd@TSofLF zy0Z!p>5Yoc5_Ua4#1vTGGQ$E3B|XPCkKTMSoo6d#32&4(9-UdN<;pr&?NisSN@x~Z zey~~B6*!Q0T<#3@3T?XE-4b)|fk8vJ>YF2*DTz5{HFeKoJ%C^=lxTit4?0{jJv~@6 z_(BiYyyz(FHZt8#RkqDsm~!#0Ho9nSNN3e~TEcq`6+ z>JRK2|5{Beb$+qz(B#E5ixs07MM?eJYqM<=*Q2$)CYu(pS()C}-JK`^+BrxCq!vKJ!x#QQlh`K(c@uxsKHHL7 zcb;rWd3Nk}g!m~2dRl@_diZVZVGb)O1NOpm*O^tvQhKUvCGSlx_0&1#)UGkiXbUVa zJJ1j`a_Hct=*4m8E9I!IWny%`)|+x>T#X7y*zh2TJe}q|J|i{aOIFLcP9UMkW{z|{y+7@g zBZXYOzu@HI>&;b9p|E?{NJ^@){kGytdZ$bULp+-?yq7h$@9NQF*uC0yTZH;mSF`W%UqTPtk>c1@Vx{;{ue>f~$@{=LEbw8)&idtelbUdWHaPqXO z0@3tdSEBIUU-RU2_V&a@+B-;nU*W?iBX{1r?`u`oCfglVlwW;g3&J5()Oz_ilBZIR zS$XQ^O}-mGw;XrfZVm8bF0{_syrfz-@~Cn_46diYXR0qx84uWJEbxTvf0$Z1aJT)Z z+Z)GyMz#>7i-F3!E?8k%`xe1NZGz4weNjmPEYHU@v~bW6lm7K@w>-Yqbe1Wo zBEHB^VhPu>3>8&I8JAi|E)1Ab?d$h$@+f|r0?&6o=%nrySd~e)DEDm=E3}%3wkE5t zWpvG@h3H3WSf&MO4k<$JcvnV?vdz>xn@hss;HF z6U)a6n$o}#S8VuK7QbfC}}ocX1LoO*M{$v6CIPT_W$ zgW$Z%!8&Ghmm+}LUwIvAAy(iAxLrvHop$>S@jbKwdKfXWw`NN-4`|sUO j{)ql>-g}6H6o?KWI_G)Bc-VCS&C9aPtiuX literal 5653 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 Wr=9MwmK5XvL>cIqJgU`pj`<%3F8Egf diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit100-1@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit100-1@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0b0ae85972b22118b1d3116dfc4f2e0915076d73 GIT binary patch literal 9934 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�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 S;=}F{0ZMY}vT$jO@c#lO1J)@3 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit300-0@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit300-0@2x.png index 7ee45a7057ca5f1e11d9bea30375c92e139cf01e..441c3ec21f8a88762c00ea80eda09a7a32faa334 100644 GIT binary patch literal 3928 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 AIRF3v literal 5004 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 QCoF)HoVsi+&@%l00vK~Sa{vGU literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit50-0@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit50-0@2x.png index 7be5374a4679af322dd3d4c4b331afc8951a1bda..6f92db28d3c20066a8a74ec8c6d8d143945a450a 100644 GIT binary patch literal 2966 zcmdT`X;@Qd7XAX1%^=hk3o7Iqw73wm6A}y{n=FC|h@fB+k{gJS+?WItlqHIVQdFD~ z!O;jhwWxJm!y{0OpaaE%3swbW)u1A>DX1*6%tgh{52w#O^YqW$Ki~PzJ@0$Ycb5Cz ztl*$kW~TE@0RU!xzFr{!U{DbQj1AExN_J9+F4hX~2t_C&R492e7_1Z^F)-vO=EcGx zFi()Q6h#BD!c8UR@#A3y6a&YKBy9Y^>4Bs`sV5vK^4%tbL$?Km@wdhEnF73X4mBwT`Kok<$nMiUblBoo;6N^S- zQ7F)d2akG_352W=FP{&-&>b5er%*^)M50oubW~Cu5m_ve%w#f&Bnpv2A)pond6GoI zQxPO`yBP*ASk9M;qzVxtfuME)UBXv&Bxo|H&-BoW2p z>2tlamMcQw-^2K%wLC0I3KK(MIg%*jqxBHl&4AI|{jsBILo^!J8kqNz&igSmgOmfc?v`p zh9C(uT@W0HC=huZB85CXr>o9{mIU(nBFVIJ>2#sqpW6$TiMGN59~mNs-esC4`a~2| z5{*jc)5ru0gTW`Djl?533+Ob0kQ&2xrc&r6CQX30sCBx zb0HVYgLAx0LQIMbLOqu3X#IM*`7e28E!+FrQaZ3%><0ay-n7fhZHIe5CI{bo1yDv#cEY!S> zU#GU$9`ghl$YNkzxl2EIb=OyVYH;u~W1t6tin(cWuD%84;4>_@d*4FPxi-=L@T48! zAHsyS8h;54xPk`MI>K=LuV(HB+~alXyf?GlflsjkX<`*Hd>l5|Id?HbuP#IPu>NkQ za`si_CgGDpEzWTG%CW_j9d#rZBN4!?ioRW~cWBI_g}rfRMpiM`HgXSmr7u-C?X zvTJtElVw4tzOre(l$jArt1De(0Rq&UF}_WpSJ2$?^5K-kzin{XxMoZ~i=(8ziByBA zth+DyN5BnA3)rpHov<~JZ<4DLm_VG;W`sF!9!v*iV&HmfEG=SCcyxaJFj_aHU}1Y{ zXsi}v)i_b6skSvzaU%94Swp~WJJhHyc`~`hS$divMZOq_6H97 zwFNeF3CTIR+O$&JQ}ZJ(zYrdNbaU0Y;U(Aj6WMi{x*Vl8a&XeSMXT;xSA2K}{V-`Ua8IPy~-&Yr|xQARRCEV6HEVa4)o?WA?0F!X8&^O&0n9XjU?F7>Aak5AIc7S?aartQ_@Skvv zciW6PT5j!bzs4skhvS>o@Z&eJ-8^${)3xGqE2|TRMc1QUW6soWJi;+O*AO~psrasQ za6#5B@?>Q-Lznz>>8@eZ@#p=EfTsq7g~z7GdQ0!c5n>EnIhhc4+^~H^ zYk)jb4;$2`RpQS1XbbPRJTSjImU+56IocjW(znt$r<@z=spOkCCNb&;PF=*cq`J@y zpqfZ`&U_A&eR1H~Uo!Ma)j%`WJi1q_j@sH*((f^?c*QoG+IRIrOHzUwV56VA_rHE} zva|R5+ghZf1BZ!AfPP5e+E7dTd3|j){o9>44T#50DkF|-ZfYaaYlg>rD0&N%)52BN zn+&*$I(2A}dCH#8pT*cuS{PMiPMB7nT(Dts#1U`N(3y5g)pl)Gb}MtJ>$V-n-b!t? z<9u$JOWN4LozzEuo{5}U5cbWHjv@29@nqMWp^TedsXtj(+m9GLDg%e-<0kvoW`tV3 z`rgK#U(Qprf4^)j!2kE{^WWT>N3W!PW(AgCFFNzMzVQJ1qYV7KgS^gqaCiO-X=E-p literal 3861 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 F_J2M}_?iF! diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit50-1@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/hit50-1@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b28503e9f2eb683cac80a4b5853c6fa884d75964 GIT binary patch literal 9138 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, "Resources/metrics_skin"), audio, true); + defaultSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore(dllStore, "Resources/default_skin"), audio, false); + specialSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore(dllStore, "Resources/special_skin"), audio, true); } public void SetContents(Func creationFunction) @@ -43,23 +43,32 @@ namespace osu.Game.Rulesets.Osu.Tests Cell(3).Child = new LocalSkinOverrideContainer(specialSkin) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); } - private static Skin getSkinFromResources(SkinManager skins, string name) + private class TestLegacySkin : LegacySkin { - using (var storage = new DllResourceStore("osu.Game.Rulesets.Osu.Tests.dll")) + private readonly bool extrapolateAnimations; + + public TestLegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager, bool extrapolateAnimations) + : base(skin, storage, audioManager, "skin.ini") { - var tempName = Path.GetTempFileName(); + this.extrapolateAnimations = extrapolateAnimations; + } - File.Delete(tempName); - Directory.CreateDirectory(tempName); + public override Texture GetTexture(string componentName) + { + // extrapolate frames to test longer animations + if (extrapolateAnimations) + { + var match = Regex.Match(componentName, "-([0-9]*)"); - var files = storage.GetAvailableResources().Where(f => f.StartsWith($"Resources/{name}")); + if (match.Length > 0) + { + var number = int.Parse(match.Groups[1].Value); + if (number < 60) + return base.GetTexture(componentName.Replace($"-{number}", $"-{number % 2}")); + } + } - foreach (var file in files) - using (var stream = storage.GetStream(file)) - using (var newFile = File.Create(Path.Combine(tempName, Path.GetFileName(file)))) - stream.CopyTo(newFile); - - return skins.GetSkin(skins.Import(tempName).Result); + return base.GetTexture(componentName); } } } From 6dd638b32793acb6dd0d2db08f92ec00cae3db39 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Aug 2019 17:39:24 +0900 Subject: [PATCH 2462/5608] Further improve legibility of texture lookup --- osu.Game/Skinning/LegacySkin.cs | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 94421b1251..6e983fe771 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -151,22 +151,33 @@ namespace osu.Game.Skinning Texture getFrameTexture(int frame) => GetTexture($"{componentName}{animationSeparator}{frame}"); - if (animatable && (texture = getFrameTexture(0)) != null) + TextureAnimation animation = null; + + if (animatable) { - var animation = new TextureAnimation { DefaultFrameLength = default_frame_time }; - - for (int i = 1; texture != null; i++) + for (int i = 0;; i++) { + if ((texture = getFrameTexture(i)) == null) + break; + + if (animation == null) + animation = new TextureAnimation + { + DefaultFrameLength = default_frame_time, + Repeat = looping + }; + animation.AddFrame(texture); - texture = getFrameTexture(i); } - - animation.Repeat = looping; - - return animation; } - return (texture = GetTexture(componentName)) == null ? null : new Sprite { Texture = texture }; + if (animation != null) + return animation; + + if ((texture = GetTexture(componentName)) != null) + return new Sprite { Texture = texture }; + + return null; } public class LegacySliderBall : Sprite From 9f0a0b2fcb0055ca5b4cc47334aef18fa0260402 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Aug 2019 17:42:33 +0900 Subject: [PATCH 2463/5608] Fix file extension case #1 --- .../Resources/metrics-skin/hit0@2x.PNG | Bin 9492 -> 0 bytes .../Resources/metrics-skin/hit100@2x.PNG | Bin 8371 -> 0 bytes .../Resources/metrics-skin/hit300@2x.PNG | Bin 9589 -> 0 bytes .../Resources/metrics-skin/hit50@2x.PNG | Bin 9299 -> 0 bytes 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit0@2x.PNG delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit100@2x.PNG delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit300@2x.PNG delete mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit50@2x.PNG diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit0@2x.PNG b/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit0@2x.PNG deleted file mode 100644 index a91072eb5b84a8204add39df625c54b703e0d873..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9492 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 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit50@2x.PNG b/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit50@2x.PNG deleted file mode 100644 index f64feded0cc2fc38672c081da38fe214d2546df3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9299 zcmZ`&pup=OL6CLN(;pu4%fq-7AfxT&H=@>SaCSq9g2H#cP;Mjy!`&(-LenQSKe=rYnE6#xL{{Rjgxfh+X(=`{QlpD zfeIH{005K#8IY)&`_hU2hhKQJNkW{XpBaLXIkKw)KHmetc<>VNYGJ>|+2|w_pp)iY zEzCF++6vTSuEyQ~xTdD`GU86Nm0%YI*zk+1law-;Ug%~)8{P!yybCbw^r-%{-qKiP zg;-e9T2zwtHttrOc6xYP;xy)W%6rEsh6OMB|1Qu$cP_FlNyCCHg`bec{{KS^$EK+597m6ieVe3=py3L`$qiNbIRH-sxbN@O@J*zu&l&r;7FM=cz ztmGWa$)`o@$o|TQP}0+k(7jCg$C-7)=A=)s6MMlP`IaxE5>KWq&`=v`0IOhb9}u=O zxQ4>{s2uBq_DYPv8E}4!;$EuCPXVs4D~ZF$Zp3_b=-9s3?{x82&uJ&MEc0Sri9E zft2kT0V-a|DmlsZ;2xb)2XB&I*iC-B>J0mK$~$y=>=2qT=!`M4LBMp4S}^-P)|e&c zaH%`yn215wvR}Usx9XEKAW7CUmd-c(Z)%;}NTPaslOIgbHe@{=x9)XOBWx z%iD09WAuZdw#by?azil|m12M8QP%yOzLdADdHpVNrcm{7=aS(E9%8_BFq>=-$ zT8EDxVuEQ%qBuZ&bM9@yGm<5Gnq>oiKOMYb54usgKH->(dg`V@mT+2^lkX+*mem__ z1OgoyD~_}SY7UCCR^z%F=4!%iCfHSLYPDssfo3Z%4YanB+S8%eXPs4M3pj%K^J-uf z*2|J9c5n@t-El;INO@?gA}>FTy7I($`+Hr7n1w6R1zp>kx%BuF3k@&dST=a1LLz!p zr=i-3K`QqbTEj=qnJ7MMn=f-O3>}?T+va6tt|i-bEM%!ID#5+z?j6hpAiQCor%tS* z9!j^S?%AaN&tA%60VA!D6z_(#b7`oeSjrO zr0qvI3!C`sON|m3ZZ&-Vh%qyF63kYPTR5j_!OmXbDb@NXD(18qgng*CTiou->ibw3*w*<8A9Z@VNUOQa|v(Uy^{ zyT{%L_Zvg0Uin|9tYf*M#4?)wQkVVHg7By!ldy)+DH6n*35n-|29Q#o$*@Gn?_~yP%U;ohV|cX0K=-k>vB+ES)#Jcp&ypR5EHIh z(wqt2iVVAev@WS3ESux}j|~^uR{fi#ru>QW7R)yc3|C5$#g^a3B@$6LZ8$D|>a~mc zsd0gd6MqZ}FU|g|C5JA-oda!Pyv4z5o#JbLbjQs0hNw{S{ld|+u^!@@?%)SA^~w0ohF#S$Ta(BXV|6WP zIOm^|*;^lBT7y0bUEWEA-4>>vSEoG)VFyOt%s2d7SRm00Ei=cP_NGp}{9~m>54pnm z&I`jCd5>Uhb+&m%l_3pyxf2<8T~<5XvNDHsKOXVZDgF|KmIp6ipV+# zc)1Th)1A+uFW2kvN#^&E@FdG{@nv;!A~KkeUtZp+oY>_PFrFZ1pd-Veh|PfpD2BIy zva+L-_B@g(eb4DvtNohl^9-t1lhq_ix84Qi+B^B;-X=VQzvZ+#q6MN=VTXO;n`WKa4cYa#h5et z$E~m~(jmiAh#p^{ci77_2xYM%iJWBzjbwKvfCXVeMybVq@C{b#-HUn8Y{mB;zYUh| zhDJB}oNEE_JmsH75bb8J#WrG>mo}vx6BdnVz%t?>+5X6XUht+SkAp2@Xo8Wt84ic5tT? zejMtCXeIlO;m9Z9K#a~)*iU5~iW|d@ehX_ApRhiqgRuBe3HJ_B&-BOY-^8x6?^I9V zCnHEO32j+eG}*Y*6p+!8K(Z(uIjj!f5`o=-G%M zW6VR6(=!|FNc>5S1!~1FIHc13kOWU9oq?p`BVl0;b( zkztl}4aJu&q@-QRk zG<1N?!?%A{iTawn&Arhv#t@@rWK)ESLha@+p0#lf-A(K%&%M>q-z;{`rgiWoot450 zI6rhBW$a^ZwZdLE-$G2Nd``Bc38QSrH#FHr)-x}bbWn|${9wcmiF!IC$=qT z8%A-l#Hh7mqA`2M25sP58zniwnjzh^!*Ids6c^-sM1#9)$qVJq{kQb6B>+REAh#Dm6s7uv66!GJTtHvBVcv|tQ(tvp)sVv6uN4#0 zSrFFuOIFup3oBh!TJ9Nv8Rr)pqiqV&oxJWSySWT2p<-ke{}Q>;@)tIeH)QJTubmot zR-^6Ro;0;x->=n5Ae5I~t^3Fcj&=;@Gf^Z&w%u=Tgs-?D1Lie1g+Bf=e@6el^DIi# zG(@csIk>5GV)keHFxUbZEB;-1M@(^I5Kg-NV~%t_8x25gAP^_ct$^b7j1dJ~D(VuH zbkgI%9ep-Zei>kjVpFhf0m!}U)yN=6c;)o>({+6Kt=POScIoYO$ue}7SElU7`{L|48W!odUp&N&q?5U9zokAMoAu-_9)^- zLNr{gqXPhX;T3RS(*L02ufF6xc)+#742d@z>)|^;H_kXk!aVBi**%8q&A_7g`Gz5- zt$6ulD(fhlD#2maWx0l$_`H->8G`G+`uh|8q&d4HT$;VRLQ%>^#@xnWJ;_AmL!)6K zu{XMx)}p|$JTE3vlG`on0X?EDD7kAWvS8Ds48NzV#KFTEkbJ>4hr`r4uaFV~S7k;u z-UzCHBK>%&G@C1cZpM+(pAZ*7gt5dc0nomKr9A62!!hG2!qJvQxHobqihXmMxP1%z zeR%@G++gqxIa&ujUU92^$=a;{bN_VZ?n6D+kruE@7Em+zM>ABLd*oAEECC)8?%@ua zJx5?2C3XoMRyexE27t|`yekIGYtWk-w8BC)kaErOH^Fj|u_R@{E(Q`KayjG}`MlNw zS|Z-GbjmpU8nNW~VHmTw6niPK$NXdcm)(Lo+HqI^%m&)Ez(U2Dl|+0he*ZzjRWDN4CgIY!%VwZ~hI<jM`xQla~^#D=iCyYhqQIfczF9km+nFDmL_;lf$TD_aVSe&cEi}6BO?w1;)fa( z@mgeM^AhX8W093jBU)twH4+2wsuq_suMbUP zN(b<1Obash*D>+B z+r3*=rjRO=*`ZgaKY>SHByr09Jx3v>fj8mb$<7OCR^N?ijs9n}^op_m?q7&#$~ zvRk`wqf7-hSNFlIBY8N1)&0Z&*=Plg#{gsM-* zON8sg^$%PaXim1JdODq4*(zQW(hoU`3-V2kx(DH}WtOotf)(!bj{$82!*)v8`2Dtb z(2!7`)r4Luc3Qd7W@Q@&OLldAWDLq5mVVz)&Pbvj#sDm97|v>(m#VnpZsSB zSY2Kc?s(hx856dC`0a#faK2=RIKv?F+!Y?QGIUX^F>-U@ zBuCH+Uh7(%9)l%o93FvDN+i;n!RRc6J3o(BSo#)!lj=+T6R%U2lVt+NeQ}TFAhf5N zoby-0+cL*LEv$#{<{M|!V+>7TZ61@Gm-V0u!(MtrCygVNPp~}014gJv0NQ)}=n-TE zn;Vz0QL zd&3RdNTsIRC{`!0FPUiW=6<$LBj^d2K`n?vqZw4 zNCB#3M7pcZZht(l3Y8TH!fN!-nGfc>HPsTN|9G+P*up5+LUh+c?1cj7J=4R!2k)OW zwwPjv|9!9PBWdw{RjW+J7Y9nnt1wV<^w!C6*cSJEZO*y|@!V!~O*j_-r!zokfiXzm zaTvaY-wwudZJ>-|Nb1j+DI|l{GD=8}eG#4-mR;ClJbAiIcTAF61kAog`O4Bm{s3Rmu1}o*W!j>Cjy8PrJl7^q(k_v0>nbMfEi_M1 zB-wC_BaefaIo5wu3qcWv-QlacHJmxpq&1DdwI>WA%sphahrMZ6FxHV&?CPNTZ?Pt* zp>ViXns^3BI~9$Q99Wy7pTQAM^o&Mti1DpMsT+iZr3@b%1^11_U-+4{Q!4wJ$12U) zT?%+)_|FbnK8{n*l_h-o*PN4V^>l-bW(P@zLar>g_}@AV)+?jG&gAZVu36oQfHbd6 z^8}TxvM{%V>oz}IfARVjb&p9y?Xznkm5JAW{QH&P6j|(SuuWsEmjJnvUxr(c^Y$@h z1`o<}UnCDO2$ub;{3tWT6I{|+FrT@LhWNaa<-6?eZIB&MhK;hWX?Jny@gQ)}TsUMV zh4FrvuhTFlGGog-stH99{uj3_0T#$mN4REQHY@I|rSKdX`DXn;To^46CjjJumRepM z&JnPf572J>jN{?>)zj?v+jVo9LCa$unAQhv0K>=Xe8$moEt;+yIh)L6RW&6FZm=aF zV9@HR=ghlO=FzsgzIMX~aFq$2S^k7s1jk?kFM^~T*`z*mt4#5z$Jx2()8Rp$BL%3L zz2g?DwKYQB*#0k_RXzmtw}8ha2m$*6LVmZ+f4!Jas%zwWojR3m_S2ozo-o{Ae=XT! zGTQ2RiP-~O=YFDNc?@u6k*-a{{0fj!_|3a3NHsoC89)Az&qo0sJwc`CG{x0*+liM|p)L!=EmLYXX^5f)ymog%`mt4KTWq?;_}kYiDT2ua5YZKnxc3*lZ?|$>7#Q>06Wz_Ydt1RM|lqSgKtlD z4Y}rt4R>ahDa-H11Q$qc1h~pEcnMsbtNQQvL+N)-dbW z9&fXekcp+s$Z>pJ*bX1TZu>x`;B)Hoa>0Ba3!6zjbRpQ->(e~!1~^iA`wqqq!y2<- zj)<{8y00)0y9e{fc_P0}n1|A^y|C7B_vCFjpD=Al@>k(8@joMF6pmQ25I1Y{(Mfw! z{{!lpP~{Dzkd2OuX0h^lKNp6MRhd7PIKnZ^u2hm9Uw?*47I4IPEk*r1w#Cyssr)E& zlYAERm0hVE-C}f7nbg02>UmHZ^*LMTiVVM$Kzm2I z0-JT#mYe5=-H;9b<6mc7H-O)|x$`?a&O@hr;(rYTtwt&ZZz`-XbWY7_<|XnPneeh* zbQD^97Uzj|qbcNRjoAFke6*KJM`G_jIqhog(fg;}*b1I!{M*pD&k`-U_z?xo1plvlm}B38v zKFU(g5-op{A(?Uu%_IDvP<->&K@~rl;adP5DJ$;!n!&pqrOVD1BsY7$(Wj_r$SPN^ zJH`LZuovPiYGcnw^zSE;_dE=UH!t?7GFRfEn6JXwiFMyQ2pIPy<_ehHJm<07%CkB* zK1Mgs`no69q9k`)%20}(l10c~Tzzq){niBJ)>X~84g2<6;@^F3M%ulXw(qsL84Tu# zMG{2YswF;CV5{Z$xD%exXk#{BM?%Q31~QNLBflX`DK0>ADE{tqGw8{W{e zfvXIIIlJZSLx8Z{sUjtT_j-%M?o=TAmNDkJ0|Z*35`GP!sFi)Fv4!izgr*&+p9tXO z6~kg`Dj4UTSgyon4PFUB9qyjo9mcWKrF{S+}e z_btMCqjO-r!#E@ir0B|ij0=)(jkClDqair_M!C^eQS5YGq6sueJJQ$MUW}c8sY@$s zGUqX89r`!jY>V+2@i2*^CW6@8EPm^sF)!VF(C`#8bQaVphx|CO)yg)eshPU?+Z#J0 zO^0xY{NO&iD=X)(MoqP?!XkcLh$I?P0`JhLMi|nuPB{9r{lK<70F?_O*|DAmfe+mRh~3sK_qEWRQFTWumIJF?vnx~f22u26Pq-`(z1tzS z8uCK^(^Y!xpXhRB<{UX+ifsvcWyKJI|U9+TAUs3r}K$bJ`ebk_Tn z&s>7ciqb>^t)6P+BiLt)vu3zOB4TcF$;n|IOceDbjCi+($>!2i{o!>jqy~47e}hG% zQ=;wkl$zFYcf*tiD!E(K*;TpoFo3(>hrYlNql^y^#zJ}rV!jzUQgz25ZUY)N+aeAr z!`dz@QCFUnoj%v&X|35&Hz=-)yyF+al$S&8`^cm13ro@7N>Wy*eT9shM`|ddJGiVF zx_Z)VUsv*B&M48Up?HCVa`$!tPG@QRURpVJCN$H4KnCgij+{JvJBSLP{Sj)@0w|Y* z691={wY7x1SOy@C=e8ubobp$YheM`j1K<4^ZQf0Y*a^k4l9y(WW}*)J{P2-~dLCXbH|f^Pan828o6w-6_wRnA1#7>+B^AydQuzL_BXNl~TS0Lx|% z|1B3#Pmrp!QTJjAaX+>nN?H$A9H4{dZVfXoM%>bNi0!E=0Ag=g?R#}UsL$p&2Yf*t8FM( zAabzgfR!Sn?V^6r^QlPDg^tll--!^VXV*k}F<&4uEJjKv z^ksS4o5k$L3RZzAsD;)+Fi~oZq9*E3rlBfagyVTp$h8;jTPV4Hk+P*9>eQb`r8sv1a61l>`U1{DC~weJEj@g$-$XVh3E{Y z2EtF;nieNN>HO$_R$?kb`nhk>9gW+RQSuIUhQ4Yx70yTvA8#6MN5S0#Fy}MhF;I;p z6Sq-x`a9twJ;4>RZTQooVU%2aZt~A7T3TZU72M=iL+;JhYW$)+lNUVVuXKHJj(5(Q z1zeoHJ+3*A;i#A|t@+%GQHI(mm}NSAS=@>npV9!}&H6X}(C2Y=c}ybmx~@p)h*Dpr zG#GH|PE7O^slDVdm)b%PJsr__BQ~a?oD(Gz%XOuKT^UJ70}evANhpMk>bTw$dO2E+y` z3qfJ*G;f^!4R00JnK-=8OrMEiBMwhu@@N>ba|Mq1_*9nbYEJfv62pqBa1!)u5f>Sx z6Fp6q4I6Lyr@iS_sb67Lx8Y7XV0A}}dq615j&3$RiXpBP1U*A~_L-Db!h~Jz*~BP} z__@8-O&r#D62?7B)st*qFmv5rf4;-te{QD-8-b5$=puZA#8;gN@|Vo7eWvaBf^ev0 zdu)w46#8y{*L;`F7w@(f`XcDa^d$+0Dq`6HcN*=XG3Z&GAxLo-1GUnmaB0E+xq-6-Hbd>A#2pUU!& zV?9|~z3+aDJTQfDpf4dW!*p!fpi2UjV@}0y#P7yo&(nI}g{@v;>rj4$iq4*NJHUee zSS#IJH9Ft;3}}i;53cYg-HjHD0&T$5qGtc8v!pd_>6&77H zk!&x#8o9t)e%ySK1S2)oU`;xtJ8E3=Zlq0(X!}TS{r9|$ z#j6T>U5+i77!mkJe)??a*!((y1r_dS%DHtU8}!7CxF?lR$4oI-72c99SX2LwE)i)o3ooE%?D)J>DG|DuLk@$tzJSNx!6*C9m~ak0pCd4NAkMW;~6#|5TP+J-R^W_g?&*yHlNcR!=|0MOdI} z^JJ%bg@)m*jXQ!>V9o3eenrLif-B}?D={J|JHj3@&GM?5t_Pt_Jl2P>WmAN0^$zcj+qfRU1j zaa2F1g5DneNu9^<_O`J4`zkNl>BQ@f zUJ!y%upiia^S+0<^_;sl>7;5Fx1*jLV9GMsd)!UbsI%K16j)60RmBtrhlvsW&?Nka z{<#tE9vVLAUp|iChGAV^SWKh=A4}>%hz|{?N(UPf-EKm0qB)?s`8qr5rqaTyBZI6Q zKyjd4YjixdY!#Q4kc<+qO%gTqGUq_OsSIb}E6X&!eHH}aWJW3Hu! Date: Tue, 20 Aug 2019 17:42:57 +0900 Subject: [PATCH 2464/5608] Fix file extension case #2 --- .../Resources/metrics-skin/hit0@2x.png | Bin 0 -> 9492 bytes .../Resources/metrics-skin/hit100@2x.png | Bin 0 -> 8371 bytes .../Resources/metrics-skin/hit300@2x.png | Bin 0 -> 9589 bytes .../Resources/metrics-skin/hit50@2x.png | Bin 0 -> 9299 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit0@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit100@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit300@2x.png create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit50@2x.png diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit0@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit0@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a91072eb5b84a8204add39df625c54b703e0d873 GIT binary patch literal 9492 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit50@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/hit50@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f64feded0cc2fc38672c081da38fe214d2546df3 GIT binary patch literal 9299 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 Date: Tue, 20 Aug 2019 17:47:24 +0900 Subject: [PATCH 2465/5608] Don't show judgement type "none" --- .../TestSceneDrawableJudgement.cs | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index 6f6520dafa..82a8d0e5e6 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; @@ -21,19 +22,13 @@ namespace osu.Game.Rulesets.Osu.Tests public TestSceneDrawableJudgement() { - foreach (HitResult result in Enum.GetValues(typeof(HitResult))) - { - JudgementResult judgement = new JudgementResult(null) - { - Type = result, - }; - - AddStep("Show " + result.GetDescription(), () => SetContents(() => new DrawableOsuJudgement(judgement, null) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - })); - } + foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType().Skip(1)) + AddStep("Show " + result.GetDescription(), () => SetContents(() => + new DrawableOsuJudgement(new JudgementResult(null) { Type = result }, null) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + })); } } } From 7d668c81fcbbeb1cd2ccd7dba538864c764d81a0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Aug 2019 18:13:00 +0900 Subject: [PATCH 2466/5608] Avoid test failures This is a bit of a workaround (I'm pretty sure these tests are not running correctly on appveyor) but I think it will do for now. Cannot repro failures locally at all. --- osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs b/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs index 8b37ef5876..02716dc1d5 100644 --- a/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs +++ b/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs @@ -60,12 +60,8 @@ namespace osu.Game.Rulesets.Osu.Tests { var match = Regex.Match(componentName, "-([0-9]*)"); - if (match.Length > 0) - { - var number = int.Parse(match.Groups[1].Value); - if (number < 60) - return base.GetTexture(componentName.Replace($"-{number}", $"-{number % 2}")); - } + if (match.Length > 0 && int.TryParse(match.Groups[1].Value, out var number) && number < 60) + return base.GetTexture(componentName.Replace($"-{number}", $"-{number % 2}")); } return base.GetTexture(componentName); From 33946f045812e67b22681cdedf408008807ac739 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Tue, 20 Aug 2019 11:18:41 +0200 Subject: [PATCH 2467/5608] Fix CI issues and update comments. --- osu.Game/Screens/Menu/IntroScreen.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index a621e29cf8..6a98c78d5f 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -30,14 +30,14 @@ namespace osu.Game.Screens.Menu private LeasedBindable beatmap; - public new Bindable Beatmap { get => beatmap; } + public new Bindable Beatmap => beatmap; protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack(); [BackgroundDependencyLoader] private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game) { - //we take a lease on the beatmap bindable to prevent music playback from changing / pausing music during intros, as it is causing weird interactions with certains intros + // we take a lease on the beatmap bindable to prevent music playback from changing / pausing during intros, as it is causing weird interactions with certains intros. beatmap = base.Beatmap.BeginLease(false); menuVoice = config.GetBindable(OsuSetting.MenuVoice); @@ -115,7 +115,7 @@ namespace osu.Game.Screens.Menu protected void LoadMenu() { DidLoadMenu = true; - beatmap.Return(); //we return the lease to the beatmap bindable as we're pushing the main menu. + beatmap.Return(); this.Push(mainMenu); } From 0de219dda48cb8d7a370e0424ebba7a5e9025c0a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 21 Jun 2019 20:47:43 +0900 Subject: [PATCH 2468/5608] Update with spritetext text builder changes --- osu.Game/Skinning/LegacySkin.cs | 50 +++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 3eda76e40f..ee88d3254e 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -15,6 +15,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; +using osu.Framework.Text; using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -234,37 +235,50 @@ namespace osu.Game.Skinning private class LegacySpriteText : OsuSpriteText { - private readonly TextureStore textures; - private readonly string font; + private readonly LegacyGlyphStore glyphStore; public LegacySpriteText(TextureStore textures, string font) { - this.textures = textures; - this.font = font; - Shadow = false; UseFullGlyphHeight = false; + + Font = new FontUsage(font, 16); + glyphStore = new LegacyGlyphStore(textures); } - protected override Texture GetTextureForCharacter(char c) + protected override TextBuilder CreateTextBuilder(ITexturedGlyphLookupStore store) => base.CreateTextBuilder(glyphStore); + + private class LegacyGlyphStore : ITexturedGlyphLookupStore { - string textureName = $"{font}-{c}"; + private readonly TextureStore textures; - // Approximate value that brings character sizing roughly in-line with stable - float ratio = 36; - - var texture = textures.Get($"{textureName}@2x"); - - if (texture == null) + public LegacyGlyphStore(TextureStore textures) { - ratio = 18; - texture = textures.Get(textureName); + this.textures = textures; } - if (texture != null) - texture.ScaleAdjust = ratio; + public ITexturedCharacterGlyph Get(string fontName, char character) + { + string textureName = $"{fontName}-{character}"; - return texture; + // Approximate value that brings character sizing roughly in-line with stable + float ratio = 36; + + var texture = textures.Get($"{textureName}@2x"); + + if (texture == null) + { + ratio = 18; + texture = textures.Get(textureName); + } + + if (texture != null) + texture.ScaleAdjust = ratio; + + return new TexturedCharacterGlyph(new CharacterGlyph(character, 0, 0, texture?.Width ?? 0, null), texture, 1f / ratio); + } + + public Task GetAsync(string fontName, char character) => Task.Run(() => Get(fontName, character)); } } From f1d02d8169a6b38b6f8019c83a3fbaea8bae2d81 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Aug 2019 15:00:14 +0300 Subject: [PATCH 2469/5608] Update design in line with web --- .../Kudosu/DrawableKudosuHistoryItem.cs | 105 +++++++++++++----- 1 file changed, 78 insertions(+), 27 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index 9b68131515..7c120e60f3 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -12,49 +12,100 @@ using osu.Game.Online.Chat; namespace osu.Game.Overlays.Profile.Sections.Kudosu { - public class DrawableKudosuHistoryItem : DrawableProfileRow + public class DrawableKudosuHistoryItem : CompositeDrawable { + private const int height = 25; + + [Resolved] + private OsuColour colours { get; set; } + private readonly APIKudosuHistory historyItem; - private LinkFlowContainer content; + private readonly LinkFlowContainer linkFlowContainer; + private readonly DrawableDate date; public DrawableKudosuHistoryItem(APIKudosuHistory historyItem) { this.historyItem = historyItem; + + Height = height; + RelativeSizeAxes = Axes.X; + AddRangeInternal(new Drawable[] + { + linkFlowContainer = new LinkFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + }, + date = new DrawableDate(historyItem.CreatedAt) + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + } + }); } [BackgroundDependencyLoader] private void load() { - LeftFlowContainer.Padding = new MarginPadding { Left = 10 }; + date.Colour = colours.GreySeafoamLighter; - LeftFlowContainer.Add(content = new LinkFlowContainer + switch (historyItem.Action) { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - }); + case KudosuAction.VoteGive: + case KudosuAction.Give: + linkFlowContainer.AddText($@"Received "); + addKudosuPart(); + addMainPart(); + addPostPart(); + break; - RightFlowContainer.Add(new DrawableDate(historyItem.CreatedAt) - { - Font = OsuFont.GetFont(size: 13), - Colour = OsuColour.Gray(0xAA), - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - }); + case KudosuAction.Reset: + addMainPart(); + addPostPart(); + break; - var formatted = createMessage(); + case KudosuAction.VoteReset: + linkFlowContainer.AddText($@"Lost "); + addKudosuPart(); + addMainPart(); + addPostPart(); + break; - content.AddLinks(formatted.Text, formatted.Links); + case KudosuAction.DenyKudosuReset: + linkFlowContainer.AddText($@"Denied "); + addKudosuPart(); + addMainPart(); + addPostPart(); + break; + + case KudosuAction.Revoke: + addMainPart(); + addPostPart(); + break; + } } - protected override Drawable CreateLeftVisual() => new Container + private void addKudosuPart() { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - }; + linkFlowContainer.AddText($@"{historyItem.Amount} kudosu", t => + { + t.Font = t.Font.With(italics: true); + t.Colour = colours.Blue; + }); + } + + private void addMainPart() + { + var text = createMessage(); + + linkFlowContainer.AddLinks(text.Text, text.Links); + } + + private void addPostPart() => linkFlowContainer.AddLink(historyItem.Post.Title, historyItem.Post.Url); private MessageFormatter.MessageFormatterResult createMessage() { - string postLinkTemplate() => $"[{historyItem.Post.Url} {historyItem.Post.Title}]"; string userLinkTemplate() => $"[{historyItem.Giver?.Url} {historyItem.Giver?.Username}]"; string message; @@ -62,27 +113,27 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu switch (historyItem.Action) { case KudosuAction.Give: - message = $"Received {historyItem.Amount} kudosu from {userLinkTemplate()} for a post at {postLinkTemplate()}"; + message = $" from {userLinkTemplate()} for a post at "; break; case KudosuAction.VoteGive: - message = $"Received {historyItem.Amount} kudosu from obtaining votes in modding post of {postLinkTemplate()}"; + message = $" from obtaining votes in modding post of "; break; case KudosuAction.Reset: - message = $"Kudosu reset by {userLinkTemplate()} for the post {postLinkTemplate()}"; + message = $"Kudosu reset by {userLinkTemplate()} for the post "; break; case KudosuAction.VoteReset: - message = $"Lost {historyItem.Amount} kudosu from losing votes in modding post of {postLinkTemplate()}"; + message = $" from losing votes in modding post of "; break; case KudosuAction.DenyKudosuReset: - message = $"Denied {historyItem.Amount} kudosu from modding post {postLinkTemplate()}"; + message = $" from modding post "; break; case KudosuAction.Revoke: - message = $"Denied kudosu by {userLinkTemplate()} for the post {postLinkTemplate()}"; + message = $"Denied kudosu by {userLinkTemplate()} for the post "; break; default: From 832b365bd08ac76da29707aea9d2d466d745497c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Aug 2019 15:17:31 +0300 Subject: [PATCH 2470/5608] Add testing --- .../Visual/Online/TestSceneKudosuHistory.cs | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs new file mode 100644 index 0000000000..6424db89fa --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs @@ -0,0 +1,156 @@ +// 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.Overlays.Profile.Sections.Kudosu; +using System.Collections.Generic; +using System; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.API.Requests; +using osu.Framework.Extensions.IEnumerableExtensions; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneKudosuHistory : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(DrawableKudosuHistoryItem), + }; + + private readonly Box background; + + public TestSceneKudosuHistory() + { + FillFlowContainer content; + + AddRange(new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + content = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Width = 0.7f, + AutoSizeAxes = Axes.Y, + } + }); + + items.ForEach(t => content.Add(new DrawableKudosuHistoryItem(t))); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.GreySeafoam; + } + + private IEnumerable items = new[] + { + new APIKudosuHistory + { + Amount = 10, + CreatedAt = new DateTimeOffset(new DateTime(2011, 11, 11)), + Action = KudosuAction.DenyKudosuReset, + Post = new APIKudosuHistory.ModdingPost + { + Title = @"Random post 1", + Url = @"https://osu.ppy.sh/b/1234", + }, + Giver = new APIKudosuHistory.KudosuGiver + { + Username = @"Username1", + Url = @"https://osu.ppy.sh/u/1234" + } + }, + new APIKudosuHistory + { + Amount = 5, + CreatedAt = new DateTimeOffset(new DateTime(2012, 10, 11)), + Action = KudosuAction.Give, + Post = new APIKudosuHistory.ModdingPost + { + Title = @"Random post 2", + Url = @"https://osu.ppy.sh/b/1234", + }, + Giver = new APIKudosuHistory.KudosuGiver + { + Username = @"Username2", + Url = @"https://osu.ppy.sh/u/1234" + } + }, + new APIKudosuHistory + { + Amount = 8, + CreatedAt = new DateTimeOffset(new DateTime(2013, 9, 11)), + Action = KudosuAction.Reset, + Post = new APIKudosuHistory.ModdingPost + { + Title = @"Random post 3", + Url = @"https://osu.ppy.sh/b/1234", + }, + Giver = new APIKudosuHistory.KudosuGiver + { + Username = @"Username3", + Url = @"https://osu.ppy.sh/u/1234" + } + }, + new APIKudosuHistory + { + Amount = 7, + CreatedAt = new DateTimeOffset(new DateTime(2014, 8, 11)), + Action = KudosuAction.Revoke, + Post = new APIKudosuHistory.ModdingPost + { + Title = @"Random post 4", + Url = @"https://osu.ppy.sh/b/1234", + }, + Giver = new APIKudosuHistory.KudosuGiver + { + Username = @"Username4", + Url = @"https://osu.ppy.sh/u/1234" + } + }, + new APIKudosuHistory + { + Amount = 100, + CreatedAt = new DateTimeOffset(new DateTime(2015, 7, 11)), + Action = KudosuAction.VoteGive, + Post = new APIKudosuHistory.ModdingPost + { + Title = @"Random post 5", + Url = @"https://osu.ppy.sh/b/1234", + }, + Giver = new APIKudosuHistory.KudosuGiver + { + Username = @"Username5", + Url = @"https://osu.ppy.sh/u/1234" + } + }, + new APIKudosuHistory + { + Amount = 20, + CreatedAt = new DateTimeOffset(new DateTime(2016, 6, 11)), + Action = KudosuAction.VoteReset, + Post = new APIKudosuHistory.ModdingPost + { + Title = @"Random post 6", + Url = @"https://osu.ppy.sh/b/1234", + }, + Giver = new APIKudosuHistory.KudosuGiver + { + Username = @"Username6", + Url = @"https://osu.ppy.sh/u/1234" + } + } + }; + } +} From c4344f3f7cc985b5f40ad4e1603c59ab910b3e2b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Aug 2019 15:29:32 +0300 Subject: [PATCH 2471/5608] CI fixes --- .../Visual/Online/TestSceneKudosuHistory.cs | 2 +- .../Kudosu/DrawableKudosuHistoryItem.cs | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs index 6424db89fa..dcf2bec239 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs @@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.Online background.Colour = colours.GreySeafoam; } - private IEnumerable items = new[] + private readonly IEnumerable items = new[] { new APIKudosuHistory { diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index 7c120e60f3..d6dfdc84ec 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu { case KudosuAction.VoteGive: case KudosuAction.Give: - linkFlowContainer.AddText($@"Received "); + linkFlowContainer.AddText(@"Received "); addKudosuPart(); addMainPart(); addPostPart(); @@ -66,14 +66,14 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu break; case KudosuAction.VoteReset: - linkFlowContainer.AddText($@"Lost "); + linkFlowContainer.AddText(@"Lost "); addKudosuPart(); addMainPart(); addPostPart(); break; case KudosuAction.DenyKudosuReset: - linkFlowContainer.AddText($@"Denied "); + linkFlowContainer.AddText(@"Denied "); addKudosuPart(); addMainPart(); addPostPart(); @@ -113,27 +113,27 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu switch (historyItem.Action) { case KudosuAction.Give: - message = $" from {userLinkTemplate()} for a post at "; + message = $@" from {userLinkTemplate()} for a post at "; break; case KudosuAction.VoteGive: - message = $" from obtaining votes in modding post of "; + message = @" from obtaining votes in modding post of "; break; case KudosuAction.Reset: - message = $"Kudosu reset by {userLinkTemplate()} for the post "; + message = $@"Kudosu reset by {userLinkTemplate()} for the post "; break; case KudosuAction.VoteReset: - message = $" from losing votes in modding post of "; + message = @" from losing votes in modding post of "; break; case KudosuAction.DenyKudosuReset: - message = $" from modding post "; + message = @" from modding post "; break; case KudosuAction.Revoke: - message = $"Denied kudosu by {userLinkTemplate()} for the post "; + message = $@"Denied kudosu by {userLinkTemplate()} for the post "; break; default: From 5c7cb4dc21ecb4a3b5961a4bed7c7f4b1562aa1a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Aug 2019 16:11:59 +0300 Subject: [PATCH 2472/5608] Simplify text creation --- .../Kudosu/DrawableKudosuHistoryItem.cs | 64 +++++-------------- 1 file changed, 16 insertions(+), 48 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index d6dfdc84ec..1b0a501db2 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -50,37 +50,45 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu { date.Colour = colours.GreySeafoamLighter; + string userLinkTemplate() => $"[{historyItem.Giver?.Url} {historyItem.Giver?.Username}]"; + switch (historyItem.Action) { case KudosuAction.VoteGive: + linkFlowContainer.AddText(@"Received "); + addKudosuPart(); + addMainPart($@" from {userLinkTemplate()} for a post at "); + addPostPart(); + break; + case KudosuAction.Give: linkFlowContainer.AddText(@"Received "); addKudosuPart(); - addMainPart(); + addMainPart(@" from obtaining votes in modding post of "); addPostPart(); break; case KudosuAction.Reset: - addMainPart(); + addMainPart($@"Kudosu reset by {userLinkTemplate()} for the post "); addPostPart(); break; case KudosuAction.VoteReset: linkFlowContainer.AddText(@"Lost "); addKudosuPart(); - addMainPart(); + addMainPart(@" from losing votes in modding post of "); addPostPart(); break; case KudosuAction.DenyKudosuReset: linkFlowContainer.AddText(@"Denied "); addKudosuPart(); - addMainPart(); + addMainPart(@" from modding post "); addPostPart(); break; case KudosuAction.Revoke: - addMainPart(); + addMainPart($@"Denied kudosu by {userLinkTemplate()} for the post "); addPostPart(); break; } @@ -95,53 +103,13 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu }); } - private void addMainPart() + private void addMainPart(string text) { - var text = createMessage(); + var formatted = MessageFormatter.FormatText(text); - linkFlowContainer.AddLinks(text.Text, text.Links); + linkFlowContainer.AddLinks(formatted.Text, formatted.Links); } private void addPostPart() => linkFlowContainer.AddLink(historyItem.Post.Title, historyItem.Post.Url); - - private MessageFormatter.MessageFormatterResult createMessage() - { - string userLinkTemplate() => $"[{historyItem.Giver?.Url} {historyItem.Giver?.Username}]"; - - string message; - - switch (historyItem.Action) - { - case KudosuAction.Give: - message = $@" from {userLinkTemplate()} for a post at "; - break; - - case KudosuAction.VoteGive: - message = @" from obtaining votes in modding post of "; - break; - - case KudosuAction.Reset: - message = $@"Kudosu reset by {userLinkTemplate()} for the post "; - break; - - case KudosuAction.VoteReset: - message = @" from losing votes in modding post of "; - break; - - case KudosuAction.DenyKudosuReset: - message = @" from modding post "; - break; - - case KudosuAction.Revoke: - message = $@"Denied kudosu by {userLinkTemplate()} for the post "; - break; - - default: - message = string.Empty; - break; - } - - return MessageFormatter.FormatText(message); - } } } From 426c7a48989302453ca7e05b8c91738e06d6ad7e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Aug 2019 16:19:21 +0300 Subject: [PATCH 2473/5608] Fix incorrect templates --- .../Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index 1b0a501db2..e5f5b720c2 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -57,14 +57,14 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu case KudosuAction.VoteGive: linkFlowContainer.AddText(@"Received "); addKudosuPart(); - addMainPart($@" from {userLinkTemplate()} for a post at "); + addMainPart(@" from obtaining votes in modding post of "); addPostPart(); break; case KudosuAction.Give: linkFlowContainer.AddText(@"Received "); addKudosuPart(); - addMainPart(@" from obtaining votes in modding post of "); + addMainPart($@" from {userLinkTemplate()} for a post at "); addPostPart(); break; From 439d825dd1beecf4a9c447974bcacdee82df3c6b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 20 Aug 2019 18:39:29 +0300 Subject: [PATCH 2474/5608] Disallow adding bonus judgements' result to statistics --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index c8858233aa..e47df6b473 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -325,9 +325,6 @@ namespace osu.Game.Rulesets.Scoring JudgedHits++; - if (result.Type != HitResult.None) - scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) + 1; - if (result.Judgement.AffectsCombo) { switch (result.Type) @@ -352,6 +349,9 @@ namespace osu.Game.Rulesets.Scoring } else { + if (result.HasResult) + scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) + 1; + baseScore += result.Judgement.NumericResultFor(result); rollingMaxBaseScore += result.Judgement.MaxNumericResult; } @@ -371,9 +371,6 @@ namespace osu.Game.Rulesets.Scoring JudgedHits--; - if (result.Type != HitResult.None) - scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) - 1; - if (result.Judgement.IsBonus) { if (result.IsHit) @@ -381,6 +378,9 @@ namespace osu.Game.Rulesets.Scoring } else { + if (result.HasResult) + scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) - 1; + baseScore -= result.Judgement.NumericResultFor(result); rollingMaxBaseScore -= result.Judgement.MaxNumericResult; } From 48716f8f2b6c57639cf2a2223bb78610ecccf403 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Aug 2019 13:29:50 +0900 Subject: [PATCH 2475/5608] Update framework --- osu.Android.props | 2 +- .../Objects/Drawable/DrawableFruit.cs | 2 +- .../Objects/Drawable/Pieces/Pulp.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- .../Objects/Drawables/Pieces/BodyPiece.cs | 4 ++-- .../Objects/Drawables/Pieces/LaneGlowPiece.cs | 4 ++-- .../UI/Components/ColumnBackground.cs | 2 +- .../Objects/Drawables/Connections/FollowPoint.cs | 2 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- .../Objects/Drawables/Pieces/CirclePiece.cs | 2 +- .../Objects/Drawables/Pieces/ExplodePiece.cs | 4 ++-- .../Objects/Drawables/Pieces/FlashPiece.cs | 2 +- .../Objects/Drawables/Pieces/GlowPiece.cs | 2 +- .../Objects/Drawables/Pieces/SliderBall.cs | 4 ++-- .../Objects/Drawables/DrawableSwell.cs | 4 ++-- .../Objects/Drawables/Pieces/CirclePiece.cs | 2 +- osu.Game.Rulesets.Taiko/UI/InputDrum.cs | 4 ++-- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 6 +++--- .../Visual/UserInterface/TestSceneCursors.cs | 2 +- .../Components/TournamentBeatmapPanel.cs | 2 +- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 9 --------- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 2 +- osu.Game/Graphics/Containers/OsuScrollContainer.cs | 2 +- osu.Game/Graphics/Cursor/MenuCursor.cs | 2 +- osu.Game/Graphics/Sprites/GlowingSpriteText.cs | 2 +- osu.Game/Graphics/UserInterface/DialogButton.cs | 2 +- osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs | 2 +- osu.Game/Graphics/UserInterface/OsuButton.cs | 2 +- .../Overlays/Profile/Header/Components/RankGraph.cs | 9 --------- osu.Game/Overlays/Toolbar/ToolbarButton.cs | 2 +- .../Overlays/Toolbar/ToolbarOverlayToggleButton.cs | 2 +- .../Components/RadioButtons/DrawableRadioButton.cs | 2 +- .../Edit/Compose/Components/BeatDivisorControl.cs | 2 +- osu.Game/Screens/Menu/Button.cs | 2 +- osu.Game/Screens/Menu/IntroTriangles.cs | 6 +++--- osu.Game/Screens/Menu/LogoVisualisation.cs | 2 +- osu.Game/Screens/Menu/MenuSideFlashes.cs | 4 ++-- osu.Game/Screens/Menu/OsuLogo.cs | 4 ++-- .../Screens/Multi/Match/Components/HeaderButton.cs | 2 +- osu.Game/Screens/ScreenWhiteBox.cs | 2 +- .../Screens/Select/Carousel/DrawableCarouselItem.cs | 2 +- .../Screens/Select/Options/BeatmapOptionsButton.cs | 2 +- osu.Game/Storyboards/CommandTimelineGroup.cs | 4 ++-- osu.Game/Storyboards/Drawables/DrawablesExtensions.cs | 10 +++++----- osu.Game/Storyboards/StoryboardSprite.cs | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 47 files changed, 63 insertions(+), 81 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index bb283dc0c5..fe6420ead8 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -61,6 +61,6 @@ - + diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index ce2daebbf1..1af77b75fc 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Anchor = Anchor.Centre, Origin = Anchor.Centre, AccentColour = Color4.Red, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Alpha = 0.5f, Scale = new Vector2(1.333f) }); diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs index b9b6d5b924..1e9daf18db 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces Anchor = Anchor.Centre; Origin = Anchor.Centre; - Blending = BlendingMode.Additive; + Blending = BlendingParameters.Additive; Colour = Color4.White.Opacity(0.9f); } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 0b06e958e6..62abe53559 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -201,7 +201,7 @@ namespace osu.Game.Rulesets.Catch.UI additive.Scale = Scale; additive.Colour = HyperDashing ? Color4.Red : Color4.White; additive.RelativePositionAxes = RelativePositionAxes; - additive.Blending = BlendingMode.Additive; + additive.Blending = BlendingParameters.Additive; AdditiveTarget.Add(additive); diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index a92e56d3c3..31a4857805 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs @@ -26,14 +26,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces public BodyPiece() { - Blending = BlendingMode.Additive; + Blending = BlendingParameters.Additive; Children = new[] { Background = new Box { RelativeSizeAxes = Axes.Both }, Foreground = new BufferedContainer { - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, RelativeSizeAxes = Axes.Both, CacheDrawnFrameBuffer = true, Children = new Drawable[] diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs index 9e0307c5c2..48c7ea7b7f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces Name = "Top", RelativeSizeAxes = Axes.Both, Height = 0.5f, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Colour = ColourInfo.GradientVertical(Color4.Transparent, Color4.White.Opacity(alpha)) }, new Box @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, Height = 0.5f, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Colour = ColourInfo.GradientVertical(Color4.White.Opacity(alpha), Color4.Transparent) } }; diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index b4e29ae9f9..5ee78aa496 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components Name = "Background Gradient Overlay", RelativeSizeAxes = Axes.Both, Height = 0.5f, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Alpha = 0 } }; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index a2a23e9ff7..523e911434 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections Child = new Box { Size = new Vector2(width), - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Origin = Anchor.Centre, Anchor = Anchor.Centre, Alpha = 0.5f, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index f75b62eecf..1db1eec33e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); - Blending = BlendingMode.Additive; + Blending = BlendingParameters.Additive; Origin = Anchor.Centre; InternalChild = scaleContainer = new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index c92937ef09..a59cfc1123 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces new TrianglesPiece { RelativeSizeAxes = Axes.Both, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Alpha = 0.5f, } }; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs index 8ff16f8b84..1d21347cba 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs @@ -17,12 +17,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Anchor = Anchor.Centre; Origin = Anchor.Centre; - Blending = BlendingMode.Additive; + Blending = BlendingParameters.Additive; Alpha = 0; Child = new SkinnableDrawable("Play/osu/hitcircle-explode", _ => new TrianglesPiece { - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, RelativeSizeAxes = Axes.Both, Alpha = 0.2f, }, s => s.GetTexture("Play/osu/hitcircle") == null); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs index c22073f56c..1e3af567fe 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Anchor = Anchor.Centre; Origin = Anchor.Centre; - Blending = BlendingMode.Additive; + Blending = BlendingParameters.Additive; Alpha = 0; Child = new SkinnableDrawable("Play/osu/hitcircle-flash", name => new CircularContainer diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs index 917695c790..a36d9e96c8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Anchor = Anchor.Centre, Origin = Anchor.Centre, Texture = textures.Get(name), - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Alpha = 0.5f }, s => s.GetTexture("Play/osu/hitcircle") == null); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 8b72b23ca3..dbab83d24a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces this.drawableSlider = drawableSlider; this.slider = slider; - Blending = BlendingMode.Additive; + Blending = BlendingParameters.Additive; Origin = Anchor.Centre; Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); @@ -190,7 +190,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Masking = true, BorderThickness = 5, BorderColour = Color4.Orange, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Child = new Box { Colour = Color4.Orange, diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 5ec9dc61e2..82448ec7d5 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Origin = Anchor.Centre, Alpha = 0, RelativeSizeAxes = Axes.Both, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Masking = true, Children = new[] { @@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables RelativeSizeAxes = Axes.Both, Masking = true, BorderThickness = target_ring_thick_border, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Children = new Drawable[] { new Box diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs index b7db819717..d9c0664ecd 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, Colour = Color4.White, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Alpha = 0, AlwaysPresent = true } diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index aa37ff7008..d6866c7d25 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -108,7 +108,7 @@ namespace osu.Game.Rulesets.Taiko.UI Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, Alpha = 0, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, }, centre = new Sprite { @@ -124,7 +124,7 @@ namespace osu.Game.Rulesets.Taiko.UI RelativeSizeAxes = Axes.Both, Size = new Vector2(0.7f), Alpha = 0, - Blending = BlendingMode.Additive + Blending = BlendingParameters.Additive } }; } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 7427a3235d..e62dc45cab 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Taiko.UI { RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, }, HitTarget = new HitTarget { @@ -127,14 +127,14 @@ namespace osu.Game.Rulesets.Taiko.UI RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, Margin = new MarginPadding { Left = HIT_TARGET_OFFSET }, - Blending = BlendingMode.Additive + Blending = BlendingParameters.Additive }, judgementContainer = new JudgementContainer { Name = "Judgements", RelativeSizeAxes = Axes.Y, Margin = new MarginPadding { Left = HIT_TARGET_OFFSET }, - Blending = BlendingMode.Additive + Blending = BlendingParameters.Additive }, } }, diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs index 23d9112b25..e95f4c09c6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs @@ -249,7 +249,7 @@ namespace osu.Game.Tests.Visual.UserInterface Size = new Vector2(50); Masking = true; - Blending = BlendingMode.Additive; + Blending = BlendingParameters.Additive; Alpha = 0.5f; Child = new Box { RelativeSizeAxes = Axes.Both }; diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index d5e28c1e3e..f6c1be0e36 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -125,7 +125,7 @@ namespace osu.Game.Tournament.Components { RelativeSizeAxes = Axes.Both, Colour = Color4.Gray, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Alpha = 0, }, }); diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 3c3a7c056e..5cce29d609 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -86,11 +86,6 @@ namespace osu.Game.Beatmaps.Drawables private readonly FillFlowContainer difficultyFlow; - public string TooltipText - { - set { } - } - public DifficultyIconTooltip() { AutoSizeAxes = Axes.Both; @@ -168,10 +163,6 @@ namespace osu.Game.Beatmaps.Drawables return true; } - public void Refresh() - { - } - public void Move(Vector2 pos) => Position = pos; protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 3ae1c3ef12..17df9ccc7e 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -246,7 +246,7 @@ namespace osu.Game.Beatmaps.Formats switch (type) { case "A": - timelineGroup?.BlendingMode.Add(easing, startTime, endTime, BlendingMode.Additive, startTime == endTime ? BlendingMode.Additive : BlendingMode.Inherit); + timelineGroup?.BlendingParameters.Add(easing, startTime, endTime, BlendingParameters.Additive, startTime == endTime ? BlendingParameters.Additive : BlendingParameters.Inherit); break; case "H": diff --git a/osu.Game/Graphics/Containers/OsuScrollContainer.cs b/osu.Game/Graphics/Containers/OsuScrollContainer.cs index 8fc8dec9fd..2721ce55dc 100644 --- a/osu.Game/Graphics/Containers/OsuScrollContainer.cs +++ b/osu.Game/Graphics/Containers/OsuScrollContainer.cs @@ -98,7 +98,7 @@ namespace osu.Game.Graphics.Containers public OsuScrollbar(Direction scrollDir) : base(scrollDir) { - Blending = BlendingMode.Additive; + Blending = BlendingParameters.Additive; CornerRadius = 5; diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 092a23e787..e103798355 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -150,7 +150,7 @@ namespace osu.Game.Graphics.Cursor }, AdditiveLayer = new Sprite { - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Colour = colour.Pink, Alpha = 0, Texture = textures.Get(@"Cursor/menu-cursor-additive"), diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs index 74e387d60e..24816deeb5 100644 --- a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs @@ -56,7 +56,7 @@ namespace osu.Game.Graphics.Sprites BlurSigma = new Vector2(4), CacheDrawnFrameBuffer = true, RelativeSizeAxes = Axes.Both, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Size = new Vector2(3f), Children = new[] { diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index b50bf14bab..927ad13829 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -254,7 +254,7 @@ namespace osu.Game.Graphics.UserInterface colourContainer.Add(flash); flash.Colour = ButtonColour; - flash.Blending = BlendingMode.Additive; + flash.Blending = BlendingParameters.Additive; flash.Alpha = 0.3f; flash.FadeOutFromOne(click_duration); flash.Expire(); diff --git a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs index 1a8fea4ff9..660bd7979f 100644 --- a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs @@ -64,7 +64,7 @@ namespace osu.Game.Graphics.UserInterface { RelativeSizeAxes = Axes.Both, Colour = HoverColour, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Alpha = 0, }, } diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 7a27f825f6..c1810800a0 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -39,7 +39,7 @@ namespace osu.Game.Graphics.UserInterface hover = new Box { RelativeSizeAxes = Axes.Both, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Colour = Color4.White.Opacity(0.1f), Alpha = 0, Depth = -1 diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index de760eedfd..24ed0cc022 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -296,15 +296,6 @@ namespace osu.Game.Overlays.Profile.Header.Components this.MoveTo(pos, 200, Easing.OutQuint); } - public void Refresh() - { - } - - public string TooltipText - { - set => throw new InvalidOperationException(); - } - protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); protected override void PopOut() => this.FadeOut(200, Easing.OutQuint); diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index 2b2b19b73a..d6b810366d 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -79,7 +79,7 @@ namespace osu.Game.Overlays.Toolbar { RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(80).Opacity(180), - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Alpha = 0, }, Flow = new FillFlowContainer diff --git a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs index b286cbfb1d..36387bb00d 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs @@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Toolbar { RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(150).Opacity(180), - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Depth = 2, Alpha = 0, }); diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs index 70c0cf623e..5854d66aa8 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons Scale = new Vector2(0.5f), X = 10, Masking = true, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Child = new Box { RelativeSizeAxes = Axes.Both } }; } diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index c615656d60..0d16d8474b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -360,7 +360,7 @@ namespace osu.Game.Screens.Edit.Compose.Components Origin = Anchor.BottomCentre, Anchor = Anchor.BottomCentre, Colour = ColourInfo.GradientVertical(Color4.White.Opacity(0.2f), Color4.White), - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, }, new EquilateralTriangle { diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index badd1e0549..1bf25a2504 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -92,7 +92,7 @@ namespace osu.Game.Screens.Menu { EdgeSmoothness = new Vector2(1.5f, 0), RelativeSizeAxes = Axes.Both, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Colour = Color4.White, Alpha = 0, }, diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index ba0d624959..f5a72c2c1d 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -296,7 +296,7 @@ namespace osu.Game.Screens.Menu { Colour = Color4.White; RelativeSizeAxes = Axes.Both; - Blending = BlendingMode.Additive; + Blending = BlendingParameters.Additive; } protected override void LoadComplete() @@ -399,11 +399,11 @@ namespace osu.Game.Screens.Menu Origin = Anchor.Centre, Colour = Color4.Black, Size = new Vector2(size - 5), - Blending = BlendingMode.None, + Blending = BlendingParameters.None, }); } - Blending = BlendingMode.Additive; + Blending = BlendingParameters.Additive; CacheDrawnFrameBuffer = true; } } diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 39bda799b5..9d0a5cd05b 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -76,7 +76,7 @@ namespace osu.Game.Screens.Menu public LogoVisualisation() { texture = Texture.WhitePixel; - Blending = BlendingMode.Additive; + Blending = BlendingParameters.Additive; } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Menu/MenuSideFlashes.cs b/osu.Game/Screens/Menu/MenuSideFlashes.cs index 95d0bf04b4..393964561c 100644 --- a/osu.Game/Screens/Menu/MenuSideFlashes.cs +++ b/osu.Game/Screens/Menu/MenuSideFlashes.cs @@ -70,7 +70,7 @@ namespace osu.Game.Screens.Menu // align off-screen to make sure our edges don't become visible during parallax. X = -box_width, Alpha = 0, - Blending = BlendingMode.Additive + Blending = BlendingParameters.Additive }, rightBox = new Box { @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Menu Height = 1.5f, X = box_width, Alpha = 0, - Blending = BlendingMode.Additive + Blending = BlendingParameters.Additive } }; diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 479b3d80b6..0c5bf12bdb 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -124,7 +124,7 @@ namespace osu.Game.Screens.Menu { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Alpha = 0 } } @@ -185,7 +185,7 @@ namespace osu.Game.Screens.Menu flashLayer = new Box { RelativeSizeAxes = Axes.Both, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Colour = Color4.White, Alpha = 0, }, diff --git a/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs b/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs index f3412d0be7..de6ece6a05 100644 --- a/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Multi.Match.Components { RelativeSizeAxes = Axes.Both, Alpha = 0.15f, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, }, }); } diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index 5648dd997b..6c5854d17e 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -95,7 +95,7 @@ namespace osu.Game.Screens Colour = getColourFor(GetType()), Alpha = 0.2f, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, }, textContainer = new FillFlowContainer { diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index b906bd935c..6118191302 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -64,7 +64,7 @@ namespace osu.Game.Screens.Select.Carousel { RelativeSizeAxes = Axes.Both, Alpha = 0, - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, }, } }; diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs index a8b5bbbd00..ff9beafb23 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs @@ -121,7 +121,7 @@ namespace osu.Game.Screens.Select.Options { RelativeSizeAxes = Axes.Both, EdgeSmoothness = new Vector2(1.5f, 0), - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, Colour = Color4.White, Alpha = 0, }, diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index b1cc0436de..461ee762e9 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -20,7 +20,7 @@ namespace osu.Game.Storyboards public CommandTimeline Rotation = new CommandTimeline(); public CommandTimeline Colour = new CommandTimeline(); public CommandTimeline Alpha = new CommandTimeline(); - public CommandTimeline BlendingMode = new CommandTimeline(); + public CommandTimeline BlendingParameters = new CommandTimeline(); public CommandTimeline FlipH = new CommandTimeline(); public CommandTimeline FlipV = new CommandTimeline(); @@ -35,7 +35,7 @@ namespace osu.Game.Storyboards yield return Rotation; yield return Colour; yield return Alpha; - yield return BlendingMode; + yield return BlendingParameters; yield return FlipH; yield return FlipV; } diff --git a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs index 7e31e1135e..bbc55a336d 100644 --- a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs +++ b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs @@ -12,19 +12,19 @@ namespace osu.Game.Storyboards.Drawables /// Adjusts after a delay. ///

    /// A to which further transforms can be added. - public static TransformSequence TransformBlendingMode(this T drawable, BlendingMode newValue, double delay = 0) + public static TransformSequence TransformBlendingMode(this T drawable, BlendingParameters newValue, double delay = 0) where T : Drawable - => drawable.TransformTo(drawable.PopulateTransform(new TransformBlendingMode(), newValue, delay)); + => drawable.TransformTo(drawable.PopulateTransform(new TransformBlendingParameters(), newValue, delay)); } - public class TransformBlendingMode : Transform + public class TransformBlendingParameters : Transform { - private BlendingMode valueAt(double time) + private BlendingParameters valueAt(double time) => time < EndTime ? StartValue : EndValue; public override string TargetMember => nameof(Drawable.Blending); protected override void Apply(Drawable d, double time) => d.Blending = valueAt(time); - protected override void ReadIntoStartValue(Drawable d) => StartValue = d.Blending.Mode; + protected override void ReadIntoStartValue(Drawable d) => StartValue = d.Blending; } } diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 8f8ec22aae..37c3ff495f 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -69,7 +69,7 @@ namespace osu.Game.Storyboards applyCommands(drawable, getCommands(g => g.Rotation, triggeredGroups), (d, value) => d.Rotation = value, (d, value, duration, easing) => d.RotateTo(value, duration, easing)); applyCommands(drawable, getCommands(g => g.Colour, triggeredGroups), (d, value) => d.Colour = value, (d, value, duration, easing) => d.FadeColour(value, duration, easing)); applyCommands(drawable, getCommands(g => g.Alpha, triggeredGroups), (d, value) => d.Alpha = value, (d, value, duration, easing) => d.FadeTo(value, duration, easing)); - applyCommands(drawable, getCommands(g => g.BlendingMode, triggeredGroups), (d, value) => d.Blending = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), false); + applyCommands(drawable, getCommands(g => g.BlendingParameters, triggeredGroups), (d, value) => d.Blending = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), false); if (drawable is IFlippable flippable) { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 758c4dda4c..8176b61fca 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index d6ad35b663..332d891416 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From cca64771dd73030f81a6f9b1019223aacb746294 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Aug 2019 13:56:49 +0900 Subject: [PATCH 2476/5608] Add comment about placement of default loading --- osu.Game/Skinning/LegacySkin.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 5a05420e75..2be31c5ee0 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -43,6 +43,7 @@ namespace osu.Game.Skinning public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini") { + // defaults should only be applied for non-beatmap skins (which are parsed via this constructor). if (!Configuration.CustomColours.ContainsKey("SliderBall")) Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); } From 724365c6d12e4b1f24824dfc7a20448839066f32 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Aug 2019 14:01:07 +0900 Subject: [PATCH 2477/5608] Minor tidying --- osu.Game/Screens/Menu/IntroScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 6a98c78d5f..4d0f7ff87a 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -37,7 +37,7 @@ namespace osu.Game.Screens.Menu [BackgroundDependencyLoader] private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game) { - // we take a lease on the beatmap bindable to prevent music playback from changing / pausing during intros, as it is causing weird interactions with certains intros. + // prevent user from changing beatmap while the intro is still runnning. beatmap = base.Beatmap.BeginLease(false); menuVoice = config.GetBindable(OsuSetting.MenuVoice); @@ -114,9 +114,9 @@ namespace osu.Game.Screens.Menu protected void LoadMenu() { - DidLoadMenu = true; beatmap.Return(); + DidLoadMenu = true; this.Push(mainMenu); } } From ae7bedacc1a05d9ea4d70eae3c4faee003f6e497 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 21 Aug 2019 05:20:49 +0000 Subject: [PATCH 2478/5608] Bump ppy.osu.Framework.iOS from 2019.816.0 to 2019.821.0 Bumps [ppy.osu.Framework.iOS](https://github.com/ppy/osu-framework) from 2019.816.0 to 2019.821.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.816.0...2019.821.0) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index d6ad35b663..6e459bdd23 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -119,7 +119,7 @@ - + From 9ce783fbf284d8b6e84798a96e336b454bbc367c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 21 Aug 2019 05:21:25 +0000 Subject: [PATCH 2479/5608] Bump ppy.osu.Framework.Android from 2019.816.0 to 2019.821.0 Bumps [ppy.osu.Framework.Android](https://github.com/ppy/osu-framework) from 2019.816.0 to 2019.821.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.816.0...2019.821.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index bb283dc0c5..fe6420ead8 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -61,6 +61,6 @@ - + From 444f2b9387bf6c850dd95e49ddd7ce3ed09cfbd6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Aug 2019 14:31:19 +0900 Subject: [PATCH 2480/5608] Specify font size in a saner way --- osu.Game/Skinning/LegacySkin.cs | 35 +++++++++++++-------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 21e8995981..de6346c9dc 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -135,7 +135,7 @@ namespace osu.Game.Skinning case "Play/osu/number-text": return !hasFont(Configuration.HitCircleFont) ? null - : new LegacySpriteText(Textures, Configuration.HitCircleFont) + : new LegacySpriteText(this, Configuration.HitCircleFont) { Scale = new Vector2(0.96f), // Spacing value was reverse-engineered from the ratio of the rendered sprite size in the visual inspector vs the actual texture size @@ -282,45 +282,38 @@ namespace osu.Game.Skinning { private readonly LegacyGlyphStore glyphStore; - public LegacySpriteText(TextureStore textures, string font) + public LegacySpriteText(ISkin skin, string font) { Shadow = false; UseFullGlyphHeight = false; - Font = new FontUsage(font, 16); - glyphStore = new LegacyGlyphStore(textures); + Font = new FontUsage(font, OsuFont.DEFAULT_FONT_SIZE); + glyphStore = new LegacyGlyphStore(skin); } protected override TextBuilder CreateTextBuilder(ITexturedGlyphLookupStore store) => base.CreateTextBuilder(glyphStore); private class LegacyGlyphStore : ITexturedGlyphLookupStore { - private readonly TextureStore textures; + private readonly ISkin skin; - public LegacyGlyphStore(TextureStore textures) + public LegacyGlyphStore(ISkin skin) { - this.textures = textures; + this.skin = skin; } public ITexturedCharacterGlyph Get(string fontName, char character) { - string textureName = $"{fontName}-{character}"; - - // Approximate value that brings character sizing roughly in-line with stable - float ratio = 36; - - var texture = textures.Get($"{textureName}@2x"); - - if (texture == null) - { - ratio = 18; - texture = textures.Get(textureName); - } + var texture = skin.GetTexture($"{fontName}-{character}"); if (texture != null) - texture.ScaleAdjust = ratio; + // Approximate value that brings character sizing roughly in-line with stable + texture.ScaleAdjust *= 18; - return new TexturedCharacterGlyph(new CharacterGlyph(character, 0, 0, texture?.Width ?? 0, null), texture, 1f / ratio); + if (texture == null) + return null; + + return new TexturedCharacterGlyph(new CharacterGlyph(character, 0, 0, texture?.Width ?? 0, null), texture, 1f / texture.ScaleAdjust); } public Task GetAsync(string fontName, char character) => Task.Run(() => Get(fontName, character)); From 4186d2566a4a85d09507804fa90b0a9a67228cea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Aug 2019 15:11:33 +0900 Subject: [PATCH 2481/5608] Remove unnecessary null checks --- osu.Game/Skinning/LegacySkin.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index e2ef3183da..a81e8c2b67 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.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; @@ -317,7 +317,7 @@ namespace osu.Game.Skinning if (texture == null) return null; - return new TexturedCharacterGlyph(new CharacterGlyph(character, 0, 0, texture?.Width ?? 0, null), texture, 1f / texture.ScaleAdjust); + return new TexturedCharacterGlyph(new CharacterGlyph(character, 0, 0, texture.Width, null), texture, 1f / texture.ScaleAdjust); } public Task GetAsync(string fontName, char character) => Task.Run(() => Get(fontName, character)); From 28dfe072a50f5998b5d31ea9b5bba01c0f9846a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Aug 2019 15:11:46 +0900 Subject: [PATCH 2482/5608] Update one more blending mode change post-master merge --- osu.Game/Skinning/LegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index a81e8c2b67..48310cf027 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -380,7 +380,7 @@ namespace osu.Game.Skinning new Sprite { Texture = skin.GetTexture("sliderb-spec"), - Blending = BlendingMode.Additive, + Blending = BlendingParameters.Additive, }, }; } From 71cbc3525d98e3177c60c60f0677dece66ad9105 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 21 Aug 2019 09:16:09 +0300 Subject: [PATCH 2483/5608] Add/remove displays only if necessary --- .../HitErrorDisplay/HitErrorDisplayOverlay.cs | 62 ++++++++++++++----- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs index 1c61904461..fae1b68e4a 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs @@ -8,7 +8,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Configuration; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Play.HitErrorDisplay @@ -22,6 +21,9 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private readonly HitWindows hitWindows; private readonly ScoreProcessor processor; + private BarHitErrorDisplay leftDisplay; + private BarHitErrorDisplay rightDisplay; + public HitErrorDisplayOverlay(ScoreProcessor processor) { this.processor = processor; @@ -43,38 +45,69 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private void onTypeChanged(ValueChangedEvent type) { - clear(); - switch (type.NewValue) { case ScoreMeterType.None: + removeLeftDisplay(); + removeRightDisplay(); break; case ScoreMeterType.HitErrorBoth: - createNew(); - createNew(true); + addLeftDisplay(); + addRightDisplay(); break; case ScoreMeterType.HitErrorLeft: - createNew(); + addLeftDisplay(); + removeRightDisplay(); break; case ScoreMeterType.HitErrorRight: - createNew(true); + addRightDisplay(); + removeLeftDisplay(); break; } } - private void clear() + private void addLeftDisplay() { - Children.ForEach(t => - { - processor.NewJudgement -= t.OnNewJudgement; - t.FadeOut(fade_duration, Easing.OutQuint).Expire(); - }); + if (leftDisplay != null) + return; + + leftDisplay = createNew(); } - private void createNew(bool reversed = false) + private void addRightDisplay() + { + if (rightDisplay != null) + return; + + rightDisplay = createNew(true); + } + + private void removeRightDisplay() + { + if (rightDisplay == null) + return; + + processor.NewJudgement -= rightDisplay.OnNewJudgement; + + rightDisplay.FadeOut(fade_duration, Easing.OutQuint).Expire(); + rightDisplay = null; + } + + private void removeLeftDisplay() + { + if (leftDisplay == null) + return; + + processor.NewJudgement -= leftDisplay.OnNewJudgement; + + leftDisplay.FadeOut(fade_duration, Easing.OutQuint).Expire(); + leftDisplay = null; + } + + private BarHitErrorDisplay createNew(bool reversed = false) { var display = new BarHitErrorDisplay(hitWindows, reversed) { @@ -87,6 +120,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay processor.NewJudgement += display.OnNewJudgement; Add(display); display.FadeInFromZero(fade_duration, Easing.OutQuint); + return display; } } } From a994ad9c84047e583471443c0d68f4ecc0e94dc4 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 21 Aug 2019 09:40:15 +0300 Subject: [PATCH 2484/5608] Use moving average to calculate arrow position --- .../HitErrorDisplay/BarHitErrorDisplay.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs index d8ae3dd9b0..d24982635b 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private readonly SpriteIcon arrow; private readonly FillFlowContainer bar; private readonly Container judgementsContainer; - private readonly Queue judgementOffsets = new Queue(); + private readonly List judgementOffsets = new List(); private readonly double maxHitWindows; public BarHitErrorDisplay(HitWindows hitWindows, bool reversed = false) @@ -154,14 +154,23 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private float getRelativeJudgementPosition(double value) => (float)(value / maxHitWindows); + private double sum = 0; + private float calculateArrowPosition(JudgementResult newJudgement) { + var offset = newJudgement.TimeOffset; + + sum += offset; + + judgementOffsets.Add(offset); + if (judgementOffsets.Count > stored_judgements_amount) - judgementOffsets.Dequeue(); + { + sum -= judgementOffsets[0]; + judgementOffsets.RemoveAt(0); + } - judgementOffsets.Enqueue(newJudgement.TimeOffset); - - return getRelativeJudgementPosition(judgementOffsets.Average()); + return getRelativeJudgementPosition(sum / stored_judgements_amount); } } } From a5acc913eab464a2f0e313df630a1a1a6736e87b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 21 Aug 2019 09:58:47 +0300 Subject: [PATCH 2485/5608] CI fixes --- osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs index d24982635b..d2bef75fd7 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs @@ -14,7 +14,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Colour; using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions; -using System.Linq; namespace osu.Game.Screens.Play.HitErrorDisplay { @@ -154,7 +153,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private float getRelativeJudgementPosition(double value) => (float)(value / maxHitWindows); - private double sum = 0; + private double sum; private float calculateArrowPosition(JudgementResult newJudgement) { From 0ccfaeb8d9896ae901e09a8eb284477514cd5fde Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 21 Aug 2019 10:13:59 +0300 Subject: [PATCH 2486/5608] Simplify moving average --- .../Play/HitErrorDisplay/BarHitErrorDisplay.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs index d2bef75fd7..85d017073a 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs @@ -14,6 +14,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Colour; using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions; +using System.Linq; namespace osu.Game.Screens.Play.HitErrorDisplay { @@ -153,21 +154,17 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private float getRelativeJudgementPosition(double value) => (float)(value / maxHitWindows); - private double sum; - private float calculateArrowPosition(JudgementResult newJudgement) { - var offset = newJudgement.TimeOffset; + judgementOffsets.Add(newJudgement.TimeOffset); - sum += offset; + if (judgementOffsets.Count < stored_judgements_amount) + return getRelativeJudgementPosition(judgementOffsets.Average()); - judgementOffsets.Add(offset); + double sum = 0; - if (judgementOffsets.Count > stored_judgements_amount) - { - sum -= judgementOffsets[0]; - judgementOffsets.RemoveAt(0); - } + for (int i = judgementOffsets.Count - stored_judgements_amount; i < judgementOffsets.Count; i++) + sum += judgementOffsets[i]; return getRelativeJudgementPosition(sum / stored_judgements_amount); } From 43c51366637984cf8132fb81c38d21bc8a0ad28e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Aug 2019 17:22:20 +0900 Subject: [PATCH 2487/5608] Remove plist reference --- fastlane/Fastfile | 1 - 1 file changed, 1 deletion(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 9cc5e4aa74..f6eb95ca3d 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -28,7 +28,6 @@ desc 'Deploy to play store' end lane :update_version do |options| - options[:plist_path] = '../osu.iOS/Info.plist' app_version(options) end From fb8d8f9438d8b4b704a3201ccc371c07211b80be Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 21 Aug 2019 08:27:56 +0000 Subject: [PATCH 2488/5608] Bump SharpCompress from 0.23.0 to 0.24.0 Bumps [SharpCompress](https://github.com/adamhathcock/sharpcompress) from 0.23.0 to 0.24.0. - [Release notes](https://github.com/adamhathcock/sharpcompress/releases) - [Commits](https://github.com/adamhathcock/sharpcompress/compare/0.23...0.24) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 758c4dda4c..9318468c78 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index d6ad35b663..aebef4dc3a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -120,7 +120,7 @@ - + From 727a6abaf775ff392b4ac135c1f2a188ab1d4d14 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 21 Aug 2019 12:16:30 +0300 Subject: [PATCH 2489/5608] Simplify caching --- .../Graphics/Containers/OsuFocusedOverlayContainer.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 5606328575..0f7b26835b 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -15,6 +15,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.Containers { + [Cached(typeof(IPreviewTrackOwner))] public abstract class OsuFocusedOverlayContainer : FocusedOverlayContainer, IPreviewTrackOwner, IKeyBindingHandler { private SampleChannel samplePopIn; @@ -38,13 +39,6 @@ namespace osu.Game.Graphics.Containers protected readonly Bindable OverlayActivationMode = new Bindable(OverlayActivation.All); - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(this); - return dependencies; - } - [BackgroundDependencyLoader(true)] private void load(AudioManager audio) { From 87f3184fccee86fe7d3dc94c5ce38d98108ae8a6 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 21 Aug 2019 15:14:33 +0300 Subject: [PATCH 2490/5608] Try retrieving samples without bank names Fallback for spinner bonus samples --- osu.Game/Skinning/SkinnableSound.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 8e2b5cec98..b50cc19482 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -55,8 +55,16 @@ namespace osu.Game.Skinning foreach (var lookup in info.LookupNames) { var ch = getSampleFunction($"Gameplay/{lookup}"); + if (ch == null) - continue; + { + // Try fallback to non-bank samples. + var bank = lookup.Split('/').Last().Split('-')[0] + '-'; + ch = getSampleFunction($"Gameplay/{lookup.Replace(bank, "")}"); + + if (ch == null) + continue; + } ch.Volume.Value = info.Volume / 100.0; return ch; From 7bf430afd5be08dec4dd0aefb4734a42cd1ebc52 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Aug 2019 21:16:06 +0900 Subject: [PATCH 2491/5608] Add padding back to difficulty icons on carousel --- osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 4ceb82d4cc..0259f3cd81 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -98,6 +98,7 @@ namespace osu.Game.Screens.Select.Carousel new FillFlowContainer { AutoSizeAxes = Axes.Both, + Spacing = new Vector2(3), Children = ((CarouselBeatmapSet)Item).Beatmaps.Select(b => new FilterableDifficultyIcon(b)).ToList() }, } From acc07c1d6548cd2a26882b73a8fb4ad3db8599c2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Aug 2019 22:18:29 +0900 Subject: [PATCH 2492/5608] Remove mod icon offset --- osu.Game/Rulesets/UI/ModIcon.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 5bb1de7a38..88a2338b94 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -52,7 +52,6 @@ namespace osu.Game.Rulesets.UI Anchor = Anchor.Centre, Size = new Vector2(size), Icon = OsuIcon.ModBg, - Y = -6.5f, Shadow = true, }, modIcon = new SpriteIcon From 4f98361da3b3bcf7b5764522f683eb4b116bebdf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Aug 2019 22:22:03 +0900 Subject: [PATCH 2493/5608] One more offset removed --- osu.Game/Overlays/SettingsSubPanel.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/SettingsSubPanel.cs b/osu.Game/Overlays/SettingsSubPanel.cs index 7f794e2927..5000156e97 100644 --- a/osu.Game/Overlays/SettingsSubPanel.cs +++ b/osu.Game/Overlays/SettingsSubPanel.cs @@ -57,7 +57,6 @@ namespace osu.Game.Overlays { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Y = -15, Size = new Vector2(15), Shadow = true, Icon = FontAwesome.Solid.ChevronLeft From db1ff6d211e1d482cea28b922c8a04ac79efab4a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Aug 2019 13:48:27 +0900 Subject: [PATCH 2494/5608] Fix video decoding loop running permanently in the background --- osu.Game/Screens/Menu/IntroTriangles.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index f5a72c2c1d..bb3a8f0013 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -139,7 +139,7 @@ namespace osu.Game.Screens.Menu private RulesetFlow rulesets; private Container rulesetsScale; private Drawable logoContainerSecondary; - private Drawable logoContainer; + private Drawable lazerLogo; private GlitchingTriangles triangles; @@ -191,7 +191,7 @@ namespace osu.Game.Screens.Menu RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Child = logoContainer = new LazerLogo(textures.GetStream("Menu/logo-triangles.mp4")) + Child = lazerLogo = new LazerLogo(textures.GetStream("Menu/logo-triangles.mp4")) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -222,7 +222,7 @@ namespace osu.Game.Screens.Menu const float scale_adjust = 0.8f; rulesets.Hide(); - logoContainer.Hide(); + lazerLogo.Hide(); background.Hide(); using (BeginAbsoluteSequence(0, true)) @@ -269,14 +269,17 @@ namespace osu.Game.Screens.Menu rulesets.FadeOut(); // matching flyte curve y = 0.25x^2 + (max(0, x - 0.7) / 0.3) ^ 5 - logoContainer.FadeIn().ScaleTo(scale_start).Then().Delay(logo_scale_duration * 0.7f).ScaleTo(scale_start - scale_adjust, logo_scale_duration * 0.3f, Easing.InQuint); + lazerLogo.FadeIn().ScaleTo(scale_start).Then().Delay(logo_scale_duration * 0.7f).ScaleTo(scale_start - scale_adjust, logo_scale_duration * 0.3f, Easing.InQuint); logoContainerSecondary.ScaleTo(scale_start).Then().ScaleTo(scale_start - scale_adjust * 0.25f, logo_scale_duration, Easing.InQuad); } using (BeginDelayedSequence(logo_2, true)) { - logoContainer.FadeOut().OnComplete(_ => + lazerLogo.FadeOut().OnComplete(_ => { + lazerLogo.Expire(); + lazerLogo.Dispose(); // explicit disposal as we are pushing a new screen and the expire may not get run. + logo.FadeIn(); background.FadeIn(); From 66d84401678a10e3692c95da2042f7c6a71bda94 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 22 Aug 2019 12:50:47 +0300 Subject: [PATCH 2495/5608] Move non-bank samples logic to LegacySkin --- osu.Game/Skinning/LegacySkin.cs | 14 +++++++++++++- osu.Game/Skinning/SkinnableSound.cs | 10 +--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 48310cf027..73957a203e 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -212,7 +212,19 @@ namespace osu.Game.Skinning return texture; } - public override SampleChannel GetSample(string sampleName) => Samples.Get(sampleName); + public override SampleChannel GetSample(string sampleName) + { + var sample = Samples.Get(sampleName); + + if (sample == null) + { + // Try fallback to non-bank samples. + var bank = sampleName.Split('/').Last().Split('-')[0] + '-'; + sample = Samples.Get($"Gameplay/{sampleName.Replace(bank, "")}"); + } + + return sample; + } private bool hasFont(string fontName) => GetTexture($"{fontName}-0") != null; diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index b50cc19482..8e2b5cec98 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -55,16 +55,8 @@ namespace osu.Game.Skinning foreach (var lookup in info.LookupNames) { var ch = getSampleFunction($"Gameplay/{lookup}"); - if (ch == null) - { - // Try fallback to non-bank samples. - var bank = lookup.Split('/').Last().Split('-')[0] + '-'; - ch = getSampleFunction($"Gameplay/{lookup.Replace(bank, "")}"); - - if (ch == null) - continue; - } + continue; ch.Volume.Value = info.Volume / 100.0; return ch; From f4d2bb036b3bcd9ed7819ad1380e1310bf8a2984 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 22 Aug 2019 16:50:54 +0300 Subject: [PATCH 2496/5608] Expand KudosuAction list --- .../Visual/Online/TestSceneKudosuHistory.cs | 80 +++++++++++++++++++ .../Requests/GetUserKudosuHistoryRequest.cs | 5 ++ .../Kudosu/DrawableKudosuHistoryItem.cs | 35 ++++++++ 3 files changed, 120 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs index dcf2bec239..8badfeaa23 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs @@ -150,6 +150,86 @@ namespace osu.Game.Tests.Visual.Online Username = @"Username6", Url = @"https://osu.ppy.sh/u/1234" } + }, + new APIKudosuHistory + { + Amount = 11, + CreatedAt = new DateTimeOffset(new DateTime(2016, 6, 11)), + Action = KudosuAction.AllowKudosuGive, + Post = new APIKudosuHistory.ModdingPost + { + Title = @"Random post 7", + Url = @"https://osu.ppy.sh/b/1234", + }, + Giver = new APIKudosuHistory.KudosuGiver + { + Username = @"Username7", + Url = @"https://osu.ppy.sh/u/1234" + } + }, + new APIKudosuHistory + { + Amount = 24, + CreatedAt = new DateTimeOffset(new DateTime(2014, 6, 11)), + Action = KudosuAction.DeleteReset, + Post = new APIKudosuHistory.ModdingPost + { + Title = @"Random post 8", + Url = @"https://osu.ppy.sh/b/1234", + }, + Giver = new APIKudosuHistory.KudosuGiver + { + Username = @"Username8", + Url = @"https://osu.ppy.sh/u/1234" + } + }, + new APIKudosuHistory + { + Amount = 12, + CreatedAt = new DateTimeOffset(new DateTime(2016, 6, 11)), + Action = KudosuAction.RestoreGive, + Post = new APIKudosuHistory.ModdingPost + { + Title = @"Random post 9", + Url = @"https://osu.ppy.sh/b/1234", + }, + Giver = new APIKudosuHistory.KudosuGiver + { + Username = @"Username9", + Url = @"https://osu.ppy.sh/u/1234" + } + }, + new APIKudosuHistory + { + Amount = 2, + CreatedAt = new DateTimeOffset(new DateTime(2012, 6, 11)), + Action = KudosuAction.RecalculateGive, + Post = new APIKudosuHistory.ModdingPost + { + Title = @"Random post 10", + Url = @"https://osu.ppy.sh/b/1234", + }, + Giver = new APIKudosuHistory.KudosuGiver + { + Username = @"Username10", + Url = @"https://osu.ppy.sh/u/1234" + } + }, + new APIKudosuHistory + { + Amount = 32, + CreatedAt = new DateTimeOffset(new DateTime(2019, 8, 11)), + Action = KudosuAction.RecalculateReset, + Post = new APIKudosuHistory.ModdingPost + { + Title = @"Random post 11", + Url = @"https://osu.ppy.sh/b/1234", + }, + Giver = new APIKudosuHistory.KudosuGiver + { + Username = @"Username11", + Url = @"https://osu.ppy.sh/u/1234" + } } }; } diff --git a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs index af37bd4b51..dd6f2ccf22 100644 --- a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs @@ -27,5 +27,10 @@ namespace osu.Game.Online.API.Requests VoteReset, DenyKudosuReset, Revoke, + AllowKudosuGive, + DeleteReset, + RestoreGive, + RecalculateGive, + RecalculateReset } } diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index e5f5b720c2..3cc39f0e73 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -91,6 +91,41 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu addMainPart($@"Denied kudosu by {userLinkTemplate()} for the post "); addPostPart(); break; + + case KudosuAction.AllowKudosuGive: + linkFlowContainer.AddText(@"Received "); + addKudosuPart(); + addMainPart(@" from kudosu deny repeal of modding post "); + addPostPart(); + break; + + case KudosuAction.DeleteReset: + linkFlowContainer.AddText(@"Lost "); + addKudosuPart(); + addMainPart(@" from modding post deletion of "); + addPostPart(); + break; + + case KudosuAction.RestoreGive: + linkFlowContainer.AddText(@"Received "); + addKudosuPart(); + addMainPart(@" from modding post restoration of "); + addPostPart(); + break; + + case KudosuAction.RecalculateGive: + linkFlowContainer.AddText(@"Received "); + addKudosuPart(); + addMainPart(@" from votes recalculation in modding post of "); + addPostPart(); + break; + + case KudosuAction.RecalculateReset: + linkFlowContainer.AddText(@"Lost "); + addKudosuPart(); + addMainPart(@" from votes recalculation in modding post of "); + addPostPart(); + break; } } From a30567394ed1973230716b6d6b55090a1097d407 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 23 Aug 2019 12:39:24 +0900 Subject: [PATCH 2497/5608] Remove bottom margin from show more button --- osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs index 5ed546c62b..cf4e1c0dde 100644 --- a/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs +++ b/osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs @@ -124,14 +124,12 @@ namespace osu.Game.Overlays.Profile.Sections private class ChevronIcon : SpriteIcon { - private const int bottom_margin = 2; private const int icon_size = 8; public ChevronIcon() { Anchor = Anchor.Centre; Origin = Anchor.Centre; - Margin = new MarginPadding { Bottom = bottom_margin }; Size = new Vector2(icon_size); Icon = FontAwesome.Solid.ChevronDown; } From 900df5d72f576a0f31d0840b3d1672314eb5e02a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Aug 2019 13:02:50 +0900 Subject: [PATCH 2498/5608] Fix crash on closing game --- osu.Game/Screens/Menu/IntroTriangles.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index bb3a8f0013..db970dd76e 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -138,7 +138,7 @@ namespace osu.Game.Screens.Menu private RulesetFlow rulesets; private Container rulesetsScale; - private Drawable logoContainerSecondary; + private Container logoContainerSecondary; private Drawable lazerLogo; private GlitchingTriangles triangles; @@ -158,7 +158,7 @@ namespace osu.Game.Screens.Menu { this.game = game; - InternalChildren = new[] + InternalChildren = new Drawable[] { triangles = new GlitchingTriangles { @@ -277,7 +277,7 @@ namespace osu.Game.Screens.Menu { lazerLogo.FadeOut().OnComplete(_ => { - lazerLogo.Expire(); + logoContainerSecondary.Remove(lazerLogo); lazerLogo.Dispose(); // explicit disposal as we are pushing a new screen and the expire may not get run. logo.FadeIn(); From c41b1e9eb4c900906c3d092c09c29142eb3bd314 Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 22 Aug 2019 21:36:21 -0700 Subject: [PATCH 2499/5608] Fix alignment and size of mute button --- osu.Game/Overlays/Volume/MuteButton.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index a4884dc2c1..0f69f11985 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.cs @@ -65,13 +65,14 @@ namespace osu.Game.Overlays.Volume { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(20), } }); Current.ValueChanged += muted => { icon.Icon = muted.NewValue ? FontAwesome.Solid.VolumeMute : FontAwesome.Solid.VolumeUp; + icon.Size = new Vector2(muted.NewValue ? 18 : 20); + icon.Margin = new MarginPadding { Right = muted.NewValue ? 2 : 0 }; }; Current.TriggerChange(); From c55d237db6e2db0fc3e468d98ae74bc9a7f6adf3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Aug 2019 17:42:40 +0900 Subject: [PATCH 2500/5608] Use BindValueChanged --- osu.Game/Overlays/Volume/MuteButton.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index 0f69f11985..6d876a77b1 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.cs @@ -68,14 +68,12 @@ namespace osu.Game.Overlays.Volume } }); - Current.ValueChanged += muted => + Current.BindValueChanged(muted => { icon.Icon = muted.NewValue ? FontAwesome.Solid.VolumeMute : FontAwesome.Solid.VolumeUp; icon.Size = new Vector2(muted.NewValue ? 18 : 20); icon.Margin = new MarginPadding { Right = muted.NewValue ? 2 : 0 }; - }; - - Current.TriggerChange(); + }, true); } protected override bool OnHover(HoverEvent e) From cb54fbee875d7806c3bbc0867242cc2c9e7e1211 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2019 09:29:35 +0000 Subject: [PATCH 2501/5608] Bump ppy.osu.Framework.Android from 2019.821.0 to 2019.823.0 Bumps [ppy.osu.Framework.Android](https://github.com/ppy/osu-framework) from 2019.821.0 to 2019.823.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.821.0...2019.823.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index fe6420ead8..9c4a308271 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -61,6 +61,6 @@ - + From 4bc05818716e94dc4bc63b8122c127ac29c520f5 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2019 09:33:38 +0000 Subject: [PATCH 2502/5608] Bump ppy.osu.Framework.iOS from 2019.821.0 to 2019.823.0 Bumps [ppy.osu.Framework.iOS](https://github.com/ppy/osu-framework) from 2019.821.0 to 2019.823.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.821.0...2019.823.0) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 05910f846a..39066cb440 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -119,7 +119,7 @@ - + From 11a61b953b15e669a1124c52b2a1e12140b0d327 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2019 09:43:34 +0000 Subject: [PATCH 2503/5608] Bump ppy.osu.Framework from 2019.821.0 to 2019.823.0 Bumps [ppy.osu.Framework](https://github.com/ppy/osu-framework) from 2019.821.0 to 2019.823.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.821.0...2019.823.0) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 905fa57f22..8c692132ad 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 05910f846a..3007a9cb86 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,7 +118,7 @@ - + From c836ef57217d086c22df6aa0d72738e2cc076706 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2019 10:04:00 +0000 Subject: [PATCH 2504/5608] Bump ppy.osu.Game.Resources from 2019.809.0 to 2019.823.0 Bumps [ppy.osu.Game.Resources](https://github.com/ppy/osu-resources) from 2019.809.0 to 2019.823.0. - [Release notes](https://github.com/ppy/osu-resources/releases) - [Commits](https://github.com/ppy/osu-resources/compare/2019.809.0...2019.823.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index fe6420ead8..232d89b375 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -60,7 +60,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 905fa57f22..22af0a5f6d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 05910f846a..3fe4d1d613 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -117,7 +117,7 @@ - + From 050130e1591e6ec6991b9027fa51c0d085498307 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 23 Aug 2019 14:11:21 +0300 Subject: [PATCH 2505/5608] Refactor PaginatedContainer to centralise repetitive logic --- .../Beatmaps/PaginatedBeatmapContainer.cs | 48 +++---------- .../PaginatedMostPlayedBeatmapContainer.cs | 41 +++-------- .../Kudosu/PaginatedKudosuHistoryContainer.cs | 38 ++-------- .../Profile/Sections/PaginatedContainer.cs | 72 +++++++++++++++---- .../Sections/Ranks/PaginatedScoreContainer.cs | 65 ++++++----------- .../PaginatedRecentActivityContainer.cs | 39 ++-------- 6 files changed, 110 insertions(+), 193 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 8a6b52b7ee..3fbd1dacd9 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -1,21 +1,22 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; +using System.Collections.Generic; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Direct; using osu.Game.Users; using osuTK; namespace osu.Game.Overlays.Profile.Sections.Beatmaps { - public class PaginatedBeatmapContainer : PaginatedContainer + public class PaginatedBeatmapContainer : PaginatedContainer { private const float panel_padding = 10f; private readonly BeatmapSetType type; - private GetUserBeatmapsRequest request; public PaginatedBeatmapContainer(BeatmapSetType type, Bindable user, string header, string missing = "None... yet.") : base(user, header, missing) @@ -27,40 +28,13 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps ItemsContainer.Spacing = new Vector2(panel_padding); } - protected override void ShowMore() + protected override APIRequest> CreateRequest() + => new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); + + protected override Drawable CreateDrawableItem(APIBeatmapSet item) => new DirectGridPanel(item.ToBeatmapSet(Rulesets)) { - request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); - request.Success += sets => Schedule(() => - { - MoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0); - MoreButton.IsLoading = false; - - if (!sets.Any() && VisiblePages == 1) - { - MissingText.Show(); - return; - } - - foreach (var s in sets) - { - if (!s.OnlineBeatmapSetID.HasValue) - continue; - - ItemsContainer.Add(new DirectGridPanel(s.ToBeatmapSet(Rulesets)) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - }); - } - }); - - Api.Queue(request); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - request?.Cancel(); - } + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }; } } diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index 23072f8d90..e444363e52 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -1,19 +1,19 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; +using System.Collections.Generic; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Users; namespace osu.Game.Overlays.Profile.Sections.Historical { - public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer + public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer { - private GetUserMostPlayedBeatmapsRequest request; - public PaginatedMostPlayedBeatmapContainer(Bindable user) : base(user, "Most Played Beatmaps", "No records. :(") { @@ -22,35 +22,10 @@ namespace osu.Game.Overlays.Profile.Sections.Historical ItemsContainer.Direction = FillDirection.Vertical; } - protected override void ShowMore() - { - request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++, ItemsPerPage); - request.Success += beatmaps => Schedule(() => - { - MoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0); - MoreButton.IsLoading = false; + protected override APIRequest> CreateRequest() + => new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++, ItemsPerPage); - if (!beatmaps.Any() && VisiblePages == 1) - { - MissingText.Show(); - return; - } - - MissingText.Hide(); - - foreach (var beatmap in beatmaps) - { - ItemsContainer.Add(new DrawableMostPlayedBeatmap(beatmap.GetBeatmapInfo(Rulesets), beatmap.PlayCount)); - } - }); - - Api.Queue(request); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - request?.Cancel(); - } + protected override Drawable CreateDrawableItem(APIUserMostPlayedBeatmap item) + => new DrawableMostPlayedBeatmap(item.GetBeatmapInfo(Rulesets), item.PlayCount); } } diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs index 29b1d3c5aa..0e7cfc37c0 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs @@ -4,48 +4,24 @@ using osu.Framework.Graphics; using osu.Game.Online.API.Requests; using osu.Game.Users; -using System.Linq; using osu.Framework.Bindables; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.API; +using System.Collections.Generic; namespace osu.Game.Overlays.Profile.Sections.Kudosu { - public class PaginatedKudosuHistoryContainer : PaginatedContainer + public class PaginatedKudosuHistoryContainer : PaginatedContainer { - private GetUserKudosuHistoryRequest request; - public PaginatedKudosuHistoryContainer(Bindable user, string header, string missing) : base(user, header, missing) { ItemsPerPage = 5; } - protected override void ShowMore() - { - request = new GetUserKudosuHistoryRequest(User.Value.Id, VisiblePages++, ItemsPerPage); - request.Success += items => Schedule(() => - { - MoreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0); - MoreButton.IsLoading = false; + protected override APIRequest> CreateRequest() + => new GetUserKudosuHistoryRequest(User.Value.Id, VisiblePages++, ItemsPerPage); - if (!items.Any() && VisiblePages == 1) - { - MissingText.Show(); - return; - } - - MissingText.Hide(); - - foreach (var item in items) - ItemsContainer.Add(new DrawableKudosuHistoryItem(item)); - }); - - Api.Queue(request); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - request?.Cancel(); - } + protected override Drawable CreateDrawableItem(APIKudosuHistory item) => new DrawableKudosuHistoryItem(item); } } diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index b459afcb49..e329fce67b 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -11,22 +11,25 @@ using osu.Game.Graphics.Sprites; using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Users; +using System.Collections.Generic; +using System.Linq; namespace osu.Game.Overlays.Profile.Sections { - public abstract class PaginatedContainer : FillFlowContainer + public abstract class PaginatedContainer : FillFlowContainer { - protected readonly FillFlowContainer ItemsContainer; - protected readonly ShowMoreButton MoreButton; - protected readonly OsuSpriteText MissingText; + private readonly ShowMoreButton moreButton; + private readonly OsuSpriteText missingText; + private APIRequest> retrievalRequest; + + [Resolved] + private IAPIProvider api { get; set; } protected int VisiblePages; protected int ItemsPerPage; protected readonly Bindable User = new Bindable(); - - protected IAPIProvider Api; - protected APIRequest RetrievalRequest; + protected readonly FillFlowContainer ItemsContainer; protected RulesetStore Rulesets; protected PaginatedContainer(Bindable user, string header, string missing) @@ -51,15 +54,15 @@ namespace osu.Game.Overlays.Profile.Sections RelativeSizeAxes = Axes.X, Spacing = new Vector2(0, 2), }, - MoreButton = new ShowMoreButton + moreButton = new ShowMoreButton { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Alpha = 0, Margin = new MarginPadding { Top = 10 }, - Action = ShowMore, + Action = showMore, }, - MissingText = new OsuSpriteText + missingText = new OsuSpriteText { Font = OsuFont.GetFont(size: 15), Text = missing, @@ -69,9 +72,8 @@ namespace osu.Game.Overlays.Profile.Sections } [BackgroundDependencyLoader] - private void load(IAPIProvider api, RulesetStore rulesets) + private void load(RulesetStore rulesets) { - Api = api; Rulesets = rulesets; User.ValueChanged += onUserChanged; @@ -84,9 +86,51 @@ namespace osu.Game.Overlays.Profile.Sections ItemsContainer.Clear(); if (e.NewValue != null) - ShowMore(); + showMore(); } - protected abstract void ShowMore(); + private void showMore() + { + retrievalRequest = CreateRequest(); + retrievalRequest.Success += items => UpdateItems(items); + + api.Queue(retrievalRequest); + } + + protected virtual void UpdateItems(List items) + { + Schedule(() => + { + moreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0); + moreButton.IsLoading = false; + + if (!items.Any() && VisiblePages == 1) + { + moreButton.Hide(); + moreButton.IsLoading = false; + missingText.Show(); + return; + } + + LoadComponentsAsync(items.Select(item => CreateDrawableItem(item)), i => + { + missingText.Hide(); + moreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0); + moreButton.IsLoading = false; + + ItemsContainer.AddRange(i); + }); + }); + } + + protected abstract APIRequest> CreateRequest(); + + protected abstract Drawable CreateDrawableItem(T item); + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + retrievalRequest?.Cancel(); + } } } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 4a9ac6e5c7..dfe300b069 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -5,18 +5,18 @@ using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests; using osu.Game.Users; using System; -using System.Collections.Generic; -using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Online.API.Requests.Responses; +using System.Collections.Generic; +using osu.Game.Online.API; namespace osu.Game.Overlays.Profile.Sections.Ranks { - public class PaginatedScoreContainer : PaginatedContainer + public class PaginatedScoreContainer : PaginatedContainer { private readonly bool includeWeight; private readonly ScoreType type; - private GetUserScoresRequest request; public PaginatedScoreContainer(ScoreType type, Bindable user, string header, string missing, bool includeWeight = false) : base(user, header, missing) @@ -29,52 +29,27 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks ItemsContainer.Direction = FillDirection.Vertical; } - protected override void ShowMore() + protected override void UpdateItems(List items) { - request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); - request.Success += scores => Schedule(() => - { - foreach (var s in scores) - s.Ruleset = Rulesets.GetRuleset(s.RulesetID); + foreach (var item in items) + item.Ruleset = Rulesets.GetRuleset(item.RulesetID); - if (!scores.Any() && VisiblePages == 1) - { - MoreButton.Hide(); - MoreButton.IsLoading = false; - MissingText.Show(); - return; - } - - IEnumerable drawableScores; - - switch (type) - { - default: - drawableScores = scores.Select(score => new DrawablePerformanceScore(score, includeWeight ? Math.Pow(0.95, ItemsContainer.Count) : (double?)null)); - break; - - case ScoreType.Recent: - drawableScores = scores.Select(score => new DrawableTotalScore(score)); - break; - } - - LoadComponentsAsync(drawableScores, s => - { - MissingText.Hide(); - MoreButton.FadeTo(scores.Count == ItemsPerPage ? 1 : 0); - MoreButton.IsLoading = false; - - ItemsContainer.AddRange(s); - }); - }); - - Api.Queue(request); + base.UpdateItems(items); } - protected override void Dispose(bool isDisposing) + protected override APIRequest> CreateRequest() + => new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); + + protected override Drawable CreateDrawableItem(APILegacyScoreInfo item) { - base.Dispose(isDisposing); - request?.Cancel(); + switch (type) + { + default: + return new DrawablePerformanceScore(item, includeWeight ? Math.Pow(0.95, ItemsContainer.Count) : (double?)null); + + case ScoreType.Recent: + return new DrawableTotalScore(item); + } } } } diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index f2a778a874..0251dd0740 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -4,51 +4,24 @@ using osu.Framework.Graphics; using osu.Game.Online.API.Requests; using osu.Game.Users; -using System.Linq; using osu.Framework.Bindables; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.API; +using System.Collections.Generic; namespace osu.Game.Overlays.Profile.Sections.Recent { - public class PaginatedRecentActivityContainer : PaginatedContainer + public class PaginatedRecentActivityContainer : PaginatedContainer { - private GetUserRecentActivitiesRequest request; - public PaginatedRecentActivityContainer(Bindable user, string header, string missing) : base(user, header, missing) { ItemsPerPage = 5; } - protected override void ShowMore() - { - request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++, ItemsPerPage); - request.Success += activities => Schedule(() => - { - MoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0); - MoreButton.IsLoading = false; + protected override APIRequest> CreateRequest() + => new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++, ItemsPerPage); - if (!activities.Any() && VisiblePages == 1) - { - MissingText.Show(); - return; - } - - MissingText.Hide(); - - foreach (APIRecentActivity activity in activities) - { - ItemsContainer.Add(new DrawableRecentActivity(activity)); - } - }); - - Api.Queue(request); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - request?.Cancel(); - } + protected override Drawable CreateDrawableItem(APIRecentActivity item) => new DrawableRecentActivity(item); } } From 45c0826314fb89ec07026037aa93c7e50979cb80 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 23 Aug 2019 14:14:39 +0300 Subject: [PATCH 2506/5608] Remove repetitive code --- osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index e329fce67b..6c444b2e26 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -101,9 +101,6 @@ namespace osu.Game.Overlays.Profile.Sections { Schedule(() => { - moreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0); - moreButton.IsLoading = false; - if (!items.Any() && VisiblePages == 1) { moreButton.Hide(); From 6bf31e8f91111d762d657dd1f93dddfeb0577b2a Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 23 Aug 2019 13:15:38 +0200 Subject: [PATCH 2507/5608] Make song select grouping & sorting filters persistent --- osu.Game/Configuration/OsuConfigManager.cs | 6 +++ osu.Game/Screens/Select/FilterControl.cs | 54 +++++++--------------- 2 files changed, 23 insertions(+), 37 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 19f46c1d6a..6ebacc642d 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -8,6 +8,7 @@ using osu.Framework.Platform; using osu.Game.Overlays; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Select; +using osu.Game.Screens.Select.Filter; namespace osu.Game.Configuration { @@ -25,6 +26,9 @@ namespace osu.Game.Configuration Set(OsuSetting.DisplayStarsMinimum, 0.0, 0, 10, 0.1); Set(OsuSetting.DisplayStarsMaximum, 10.0, 0, 10, 0.1); + Set(OsuSetting.SelectGroupingMode, GroupMode.All); + Set(OsuSetting.SelectSortingMode, SortMode.Title); + Set(OsuSetting.RandomSelectAlgorithm, RandomSelectAlgorithm.RandomPermutation); Set(OsuSetting.ChatDisplayHeight, ChatOverlay.DEFAULT_HEIGHT, 0.2, 1); @@ -150,6 +154,8 @@ namespace osu.Game.Configuration SaveUsername, DisplayStarsMinimum, DisplayStarsMaximum, + SelectGroupingMode, + SelectSortingMode, RandomSelectAlgorithm, ShowFpsDisplay, ChatDisplayHeight, diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 84e8e90f54..b97d64f013 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -29,40 +29,14 @@ namespace osu.Game.Screens.Select private readonly TabControl groupTabs; - private SortMode sort = SortMode.Title; + public readonly Bindable SortMode = new Bindable(Filter.SortMode.Title); - public SortMode Sort - { - get => sort; - set - { - if (sort != value) - { - sort = value; - FilterChanged?.Invoke(CreateCriteria()); - } - } - } - - private GroupMode group = GroupMode.All; - - public GroupMode Group - { - get => group; - set - { - if (group != value) - { - group = value; - FilterChanged?.Invoke(CreateCriteria()); - } - } - } + public readonly Bindable GroupMode = new Bindable(Filter.GroupMode.All); public FilterCriteria CreateCriteria() => new FilterCriteria { - Group = group, - Sort = sort, + Group = GroupMode.Value, + Sort = SortMode.Value, SearchText = searchTextBox.Text, AllowConvertedBeatmaps = showConverted.Value, Ruleset = ruleset.Value @@ -122,7 +96,7 @@ namespace osu.Game.Screens.Select Height = 24, Width = 0.5f, AutoSort = true, - Current = { Value = GroupMode.Title } + Current = GroupMode }, //spriteText = new OsuSpriteText //{ @@ -141,7 +115,7 @@ namespace osu.Game.Screens.Select Width = 0.5f, Height = 24, AutoSort = true, - Current = { Value = SortMode.Title } + Current = SortMode } } }, @@ -151,10 +125,8 @@ namespace osu.Game.Screens.Select searchTextBox.Current.ValueChanged += _ => FilterChanged?.Invoke(CreateCriteria()); - groupTabs.PinItem(GroupMode.All); - groupTabs.PinItem(GroupMode.RecentlyPlayed); - groupTabs.Current.ValueChanged += group => Group = group.NewValue; - sortTabs.Current.ValueChanged += sort => Sort = sort.NewValue; + groupTabs.PinItem(Filter.GroupMode.All); + groupTabs.PinItem(Filter.GroupMode.RecentlyPlayed); } public void Deactivate() @@ -184,7 +156,15 @@ namespace osu.Game.Screens.Select showConverted.ValueChanged += _ => updateCriteria(); ruleset.BindTo(parentRuleset); - ruleset.BindValueChanged(_ => updateCriteria(), true); + ruleset.BindValueChanged(_ => updateCriteria()); + + config.BindWith(OsuSetting.SelectGroupingMode, GroupMode); + config.BindWith(OsuSetting.SelectSortingMode, SortMode); + + GroupMode.BindValueChanged(_ => updateCriteria()); + SortMode.BindValueChanged(_ => updateCriteria()); + + updateCriteria(); } private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria()); From 6ea10ada3451d0096c9e4da34f3e5ac51e50aaae Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 23 Aug 2019 13:31:45 +0200 Subject: [PATCH 2508/5608] Fix visual tests. --- .../Visual/SongSelect/TestScenePlaySongSelect.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 680250a226..2dbe53709b 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -111,13 +111,13 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap); - AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; }); - AddStep(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; }); - AddStep(@"Sort by Author", delegate { songSelect.FilterControl.Sort = SortMode.Author; }); - AddStep(@"Sort by DateAdded", delegate { songSelect.FilterControl.Sort = SortMode.DateAdded; }); - AddStep(@"Sort by BPM", delegate { songSelect.FilterControl.Sort = SortMode.BPM; }); - AddStep(@"Sort by Length", delegate { songSelect.FilterControl.Sort = SortMode.Length; }); - AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; }); + AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.SortMode.Value = SortMode.Artist; }); + AddStep(@"Sort by Title", delegate { songSelect.FilterControl.SortMode.Value = SortMode.Title; }); + AddStep(@"Sort by Author", delegate { songSelect.FilterControl.SortMode.Value = SortMode.Author; }); + AddStep(@"Sort by DateAdded", delegate { songSelect.FilterControl.SortMode.Value = SortMode.DateAdded; }); + AddStep(@"Sort by BPM", delegate { songSelect.FilterControl.SortMode.Value = SortMode.BPM; }); + AddStep(@"Sort by Length", delegate { songSelect.FilterControl.SortMode.Value = SortMode.Length; }); + AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.SortMode.Value = SortMode.Difficulty; }); } [Test] From d8535574d10b26413c18639ccedc93ff15e00a4c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 23 Aug 2019 14:32:43 +0300 Subject: [PATCH 2509/5608] Pass sample info to Skin.GetSample --- .../TestSceneCatcher.cs | 2 +- .../Gameplay/TestSceneSkinnableDrawable.cs | 7 ++++--- osu.Game/Skinning/DefaultSkin.cs | 3 ++- osu.Game/Skinning/ISkin.cs | 3 ++- osu.Game/Skinning/LegacySkin.cs | 20 +++++++++++-------- .../Skinning/LocalSkinOverrideContainer.cs | 7 ++++--- osu.Game/Skinning/Skin.cs | 3 ++- osu.Game/Skinning/SkinManager.cs | 3 ++- 8 files changed, 29 insertions(+), 19 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 33f93cdb4a..72646e656e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Catch.Tests return null; } - public SampleChannel GetSample(string sampleName) => + public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException(); public Texture GetTexture(string componentName) => diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs index 0b5978e3eb..6c003e62ec 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; +using osu.Game.Audio; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Skinning; @@ -253,7 +254,7 @@ namespace osu.Game.Tests.Visual.Gameplay public Texture GetTexture(string componentName) => throw new NotImplementedException(); - public SampleChannel GetSample(string sampleName) => throw new NotImplementedException(); + public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException(); public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); } @@ -264,7 +265,7 @@ namespace osu.Game.Tests.Visual.Gameplay public Texture GetTexture(string componentName) => throw new NotImplementedException(); - public SampleChannel GetSample(string sampleName) => throw new NotImplementedException(); + public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException(); public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); } @@ -275,7 +276,7 @@ namespace osu.Game.Tests.Visual.Gameplay public Texture GetTexture(string componentName) => throw new NotImplementedException(); - public SampleChannel GetSample(string sampleName) => throw new NotImplementedException(); + public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException(); public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); } diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs index c7556dddd5..6072bb64ed 100644 --- a/osu.Game/Skinning/DefaultSkin.cs +++ b/osu.Game/Skinning/DefaultSkin.cs @@ -4,6 +4,7 @@ using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; +using osu.Game.Audio; namespace osu.Game.Skinning { @@ -19,6 +20,6 @@ namespace osu.Game.Skinning public override Texture GetTexture(string componentName) => null; - public override SampleChannel GetSample(string sampleName) => null; + public override SampleChannel GetSample(ISampleInfo sampleInfo) => null; } } diff --git a/osu.Game/Skinning/ISkin.cs b/osu.Game/Skinning/ISkin.cs index 0e67a1897c..4867aba0a9 100644 --- a/osu.Game/Skinning/ISkin.cs +++ b/osu.Game/Skinning/ISkin.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; +using osu.Game.Audio; namespace osu.Game.Skinning { @@ -17,7 +18,7 @@ namespace osu.Game.Skinning Texture GetTexture(string componentName); - SampleChannel GetSample(string sampleName); + SampleChannel GetSample(ISampleInfo sampleInfo); TValue GetValue(Func query) where TConfiguration : SkinConfiguration; } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 73957a203e..bf2f382527 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -17,6 +17,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Framework.Text; +using osu.Game.Audio; using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -212,18 +213,21 @@ namespace osu.Game.Skinning return texture; } - public override SampleChannel GetSample(string sampleName) + public override SampleChannel GetSample(ISampleInfo sampleInfo) { - var sample = Samples.Get(sampleName); - - if (sample == null) + foreach (var lookup in sampleInfo.LookupNames) { - // Try fallback to non-bank samples. - var bank = sampleName.Split('/').Last().Split('-')[0] + '-'; - sample = Samples.Get($"Gameplay/{sampleName.Replace(bank, "")}"); + var sample = Samples.Get(lookup); + + if (sample != null) + return sample; } - return sample; + if (sampleInfo is HitSampleInfo hsi) + // Try fallback to non-bank samples. + return Samples.Get($"{hsi.Name}"); + + return null; } private bool hasFont(string fontName) => GetTexture($"{fontName}-0") != null; diff --git a/osu.Game/Skinning/LocalSkinOverrideContainer.cs b/osu.Game/Skinning/LocalSkinOverrideContainer.cs index 7882e0f31b..fc36d1c8da 100644 --- a/osu.Game/Skinning/LocalSkinOverrideContainer.cs +++ b/osu.Game/Skinning/LocalSkinOverrideContainer.cs @@ -8,6 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; +using osu.Game.Audio; using osu.Game.Configuration; namespace osu.Game.Skinning @@ -49,13 +50,13 @@ namespace osu.Game.Skinning return fallbackSource.GetTexture(componentName); } - public SampleChannel GetSample(string sampleName) + public SampleChannel GetSample(ISampleInfo sampleInfo) { SampleChannel sourceChannel; - if (beatmapHitsounds.Value && (sourceChannel = skin?.GetSample(sampleName)) != null) + if (beatmapHitsounds.Value && (sourceChannel = skin?.GetSample(sampleInfo)) != null) return sourceChannel; - return fallbackSource?.GetSample(sampleName); + return fallbackSource?.GetSample(sampleInfo); } public TValue GetValue(Func query) where TConfiguration : SkinConfiguration diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 09c0d3d0bc..027d9df8b8 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; +using osu.Game.Audio; namespace osu.Game.Skinning { @@ -16,7 +17,7 @@ namespace osu.Game.Skinning public abstract Drawable GetDrawableComponent(string componentName); - public abstract SampleChannel GetSample(string sampleName); + public abstract SampleChannel GetSample(ISampleInfo sampleInfo); public abstract Texture GetTexture(string componentName); diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 19997e8844..e747a8b1ce 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -15,6 +15,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Framework.Platform; +using osu.Game.Audio; using osu.Game.Database; using osu.Game.IO.Archives; @@ -120,7 +121,7 @@ namespace osu.Game.Skinning public Texture GetTexture(string componentName) => CurrentSkin.Value.GetTexture(componentName); - public SampleChannel GetSample(string sampleName) => CurrentSkin.Value.GetSample(sampleName); + public SampleChannel GetSample(ISampleInfo sampleInfo) => CurrentSkin.Value.GetSample(sampleInfo); public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => CurrentSkin.Value.GetValue(query); } From 7e34afeab874911ef0fd3edb1ad94388fc681d9d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 23 Aug 2019 14:38:18 +0300 Subject: [PATCH 2510/5608] Conver to method group --- osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 6c444b2e26..0e2b4c986a 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -82,6 +82,8 @@ namespace osu.Game.Overlays.Profile.Sections private void onUserChanged(ValueChangedEvent e) { + retrievalRequest?.Cancel(); + VisiblePages = 0; ItemsContainer.Clear(); @@ -92,7 +94,7 @@ namespace osu.Game.Overlays.Profile.Sections private void showMore() { retrievalRequest = CreateRequest(); - retrievalRequest.Success += items => UpdateItems(items); + retrievalRequest.Success += UpdateItems; api.Queue(retrievalRequest); } @@ -109,13 +111,13 @@ namespace osu.Game.Overlays.Profile.Sections return; } - LoadComponentsAsync(items.Select(item => CreateDrawableItem(item)), i => + LoadComponentsAsync(items.Select(CreateDrawableItem), drawables => { missingText.Hide(); moreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0); moreButton.IsLoading = false; - ItemsContainer.AddRange(i); + ItemsContainer.AddRange(drawables); }); }); } From 0cde0982e595da7dc28240b78ed534e83f171507 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 23 Aug 2019 14:52:26 +0300 Subject: [PATCH 2511/5608] Use cansellation token --- osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 0e2b4c986a..75601041e8 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -13,6 +13,7 @@ using osu.Game.Rulesets; using osu.Game.Users; using System.Collections.Generic; using System.Linq; +using System.Threading; namespace osu.Game.Overlays.Profile.Sections { @@ -21,6 +22,7 @@ namespace osu.Game.Overlays.Profile.Sections private readonly ShowMoreButton moreButton; private readonly OsuSpriteText missingText; private APIRequest> retrievalRequest; + private CancellationTokenSource loadCancellation; [Resolved] private IAPIProvider api { get; set; } @@ -82,6 +84,7 @@ namespace osu.Game.Overlays.Profile.Sections private void onUserChanged(ValueChangedEvent e) { + loadCancellation?.Cancel(); retrievalRequest?.Cancel(); VisiblePages = 0; @@ -93,6 +96,8 @@ namespace osu.Game.Overlays.Profile.Sections private void showMore() { + loadCancellation = new CancellationTokenSource(); + retrievalRequest = CreateRequest(); retrievalRequest.Success += UpdateItems; @@ -118,7 +123,7 @@ namespace osu.Game.Overlays.Profile.Sections moreButton.IsLoading = false; ItemsContainer.AddRange(drawables); - }); + }, loadCancellation.Token); }); } From 7b04fb1690fa32ccdd2f75d6bb4b4b33f5b6806f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 23 Aug 2019 14:54:39 +0300 Subject: [PATCH 2512/5608] StoryboardSample -> StoryboardSampleInfo --- .../Formats/LegacyStoryboardDecoder.cs | 2 +- .../Drawables/DrawableStoryboardSample.cs | 24 +++++++++---------- osu.Game/Storyboards/StoryboardSample.cs | 10 ++++---- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 17df9ccc7e..14c6ea5c8e 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -121,7 +121,7 @@ namespace osu.Game.Beatmaps.Formats var layer = parseLayer(split[2]); var path = cleanFilename(split[3]); var volume = split.Length > 4 ? float.Parse(split[4], CultureInfo.InvariantCulture) : 100; - storyboard.GetLayer(layer).Add(new StoryboardSample(path, time, volume)); + storyboard.GetLayer(layer).Add(new StoryboardSampleInfo(path, time, (int)volume)); break; } } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs index ffd238d4e1..b04f1d4518 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.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.IO; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; @@ -17,25 +16,24 @@ namespace osu.Game.Storyboards.Drawables ///
    private const double allowable_late_start = 100; - private readonly StoryboardSample sample; + private readonly StoryboardSampleInfo sampleInfo; private SampleChannel channel; public override bool RemoveWhenNotAlive => false; - public DrawableStoryboardSample(StoryboardSample sample) + public DrawableStoryboardSample(StoryboardSampleInfo sampleInfo) { - this.sample = sample; - LifetimeStart = sample.StartTime; + this.sampleInfo = sampleInfo; + LifetimeStart = sampleInfo.StartTime; } [BackgroundDependencyLoader] private void load(IBindable beatmap) { - // Try first with the full name, then attempt with no path - channel = beatmap.Value.Skin.GetSample(sample.Path) ?? beatmap.Value.Skin.GetSample(Path.ChangeExtension(sample.Path, null)); + channel = beatmap.Value.Skin.GetSample(sampleInfo); if (channel != null) - channel.Volume.Value = sample.Volume / 100; + channel.Volume.Value = sampleInfo.Volume / 100.0; } protected override void Update() @@ -43,27 +41,27 @@ namespace osu.Game.Storyboards.Drawables base.Update(); // TODO: this logic will need to be consolidated with other game samples like hit sounds. - if (Time.Current < sample.StartTime) + if (Time.Current < sampleInfo.StartTime) { // We've rewound before the start time of the sample channel?.Stop(); // In the case that the user fast-forwards to a point far beyond the start time of the sample, // we want to be able to fall into the if-conditional below (therefore we must not have a life time end) - LifetimeStart = sample.StartTime; + LifetimeStart = sampleInfo.StartTime; LifetimeEnd = double.MaxValue; } - else if (Time.Current - Time.Elapsed < sample.StartTime) + else if (Time.Current - Time.Elapsed < sampleInfo.StartTime) { // We've passed the start time of the sample. We only play the sample if we're within an allowable range // from the sample's start, to reduce layering if we've been fast-forwarded far into the future - if (Time.Current - sample.StartTime < allowable_late_start) + if (Time.Current - sampleInfo.StartTime < allowable_late_start) channel?.Play(); // In the case that the user rewinds to a point far behind the start time of the sample, // we want to be able to fall into the if-conditional above (therefore we must not have a life time start) LifetimeStart = double.MinValue; - LifetimeEnd = sample.StartTime; + LifetimeEnd = sampleInfo.StartTime; } } } diff --git a/osu.Game/Storyboards/StoryboardSample.cs b/osu.Game/Storyboards/StoryboardSample.cs index 24231cdca6..4635109d51 100644 --- a/osu.Game/Storyboards/StoryboardSample.cs +++ b/osu.Game/Storyboards/StoryboardSample.cs @@ -1,21 +1,23 @@ // 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.Game.Audio; using osu.Game.Storyboards.Drawables; namespace osu.Game.Storyboards { - public class StoryboardSample : IStoryboardElement + public class StoryboardSampleInfo : IStoryboardElement, ISampleInfo { - public string Path { get; set; } + public string Path { get; } public bool IsDrawable => true; public double StartTime { get; } - public float Volume; + public int Volume { get; } - public StoryboardSample(string path, double time, float volume) + public StoryboardSampleInfo(string path, double time, int volume) { Path = path; StartTime = time; From b6b050d5e9662155924c3dfa5c41a22a7fbeb1cd Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 23 Aug 2019 14:55:06 +0300 Subject: [PATCH 2513/5608] Add sample path to the lookup names --- osu.Game/Storyboards/StoryboardSample.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Storyboards/StoryboardSample.cs b/osu.Game/Storyboards/StoryboardSample.cs index 4635109d51..5d6ce215f5 100644 --- a/osu.Game/Storyboards/StoryboardSample.cs +++ b/osu.Game/Storyboards/StoryboardSample.cs @@ -17,6 +17,13 @@ namespace osu.Game.Storyboards public int Volume { get; } + public IEnumerable LookupNames => new[] + { + // Try first with the full name, then attempt with no path + Path, + System.IO.Path.ChangeExtension(Path, null), + }; + public StoryboardSampleInfo(string path, double time, int volume) { Path = path; From da72806693cc9688f189f61daa17f2f45ead6145 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 23 Aug 2019 14:55:38 +0300 Subject: [PATCH 2514/5608] Remove lookup logic from SkinnableSound --- osu.Game/Skinning/SkinnableSound.cs | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 8e2b5cec98..23093d9bd9 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.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.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -43,28 +42,21 @@ namespace osu.Game.Skinning { channels = hitSamples.Select(s => { - var ch = loadChannel(s, skin.GetSample); + var ch = skin.GetSample(s); + if (ch == null && allowFallback) - ch = loadChannel(s, audio.Samples.Get); + if (s is HitSampleInfo hsi) + ch = audio.Samples.Get(string.IsNullOrEmpty(hsi.Namespace) + ? $"Gameplay/{hsi.Namespace}/{hsi.Bank}-{hsi.Name}" + : $"Gameplay/{hsi.Bank}-{hsi.Name}"); + + if (ch != null) + ch.Volume.Value = s.Volume / 100.0; + return ch; }).Where(c => c != null).ToArray(); } - private SampleChannel loadChannel(ISampleInfo info, Func getSampleFunction) - { - foreach (var lookup in info.LookupNames) - { - var ch = getSampleFunction($"Gameplay/{lookup}"); - if (ch == null) - continue; - - ch.Volume.Value = info.Volume / 100.0; - return ch; - } - - return null; - } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From ce5ee095b96111f95bb191dda6e3ea04342c8393 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 23 Aug 2019 14:03:56 +0200 Subject: [PATCH 2515/5608] Fetch config bindables in BDL. --- osu.Game/Screens/Select/FilterControl.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index b97d64f013..44bc3235ac 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -29,9 +29,9 @@ namespace osu.Game.Screens.Select private readonly TabControl groupTabs; - public readonly Bindable SortMode = new Bindable(Filter.SortMode.Title); + public Bindable SortMode; - public readonly Bindable GroupMode = new Bindable(Filter.GroupMode.All); + public Bindable GroupMode; public FilterCriteria CreateCriteria() => new FilterCriteria { @@ -96,7 +96,6 @@ namespace osu.Game.Screens.Select Height = 24, Width = 0.5f, AutoSort = true, - Current = GroupMode }, //spriteText = new OsuSpriteText //{ @@ -115,7 +114,6 @@ namespace osu.Game.Screens.Select Width = 0.5f, Height = 24, AutoSort = true, - Current = SortMode } } }, @@ -158,8 +156,11 @@ namespace osu.Game.Screens.Select ruleset.BindTo(parentRuleset); ruleset.BindValueChanged(_ => updateCriteria()); - config.BindWith(OsuSetting.SelectGroupingMode, GroupMode); - config.BindWith(OsuSetting.SelectSortingMode, SortMode); + SortMode = config.GetBindable(OsuSetting.SelectSortingMode); + GroupMode = config.GetBindable(OsuSetting.SelectGroupingMode); + + sortTabs.Current.BindTo(SortMode); + groupTabs.Current.BindTo(GroupMode); GroupMode.BindValueChanged(_ => updateCriteria()); SortMode.BindValueChanged(_ => updateCriteria()); From 94b5caf7404e072353884b2b278ddea8adce6baf Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 23 Aug 2019 15:18:56 +0300 Subject: [PATCH 2516/5608] Fix build issues --- osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs | 1 + osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 72646e656e..406c0af28d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -15,6 +15,7 @@ using osu.Framework.Graphics.Sprites; using osuTK.Graphics; using osu.Framework.Audio.Sample; using osu.Framework.Graphics.Textures; +using osu.Game.Audio; namespace osu.Game.Rulesets.Catch.Tests { diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index 971518909d..953763c95d 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Beatmaps.Formats int spriteCount = background.Elements.Count(x => x.GetType() == typeof(StoryboardSprite)); int animationCount = background.Elements.Count(x => x.GetType() == typeof(StoryboardAnimation)); - int sampleCount = background.Elements.Count(x => x.GetType() == typeof(StoryboardSample)); + int sampleCount = background.Elements.Count(x => x.GetType() == typeof(StoryboardSampleInfo)); Assert.AreEqual(15, spriteCount); Assert.AreEqual(1, animationCount); From 72a644996c830cd5e1479024a02b81d58fe1e6f0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2019 13:41:27 +0000 Subject: [PATCH 2517/5608] Bump NUnit3TestAdapter from 3.14.0 to 3.15.0 Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 3.14.0 to 3.15.0. - [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases) - [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V3.14...V3.15) Signed-off-by: dependabot-preview[bot] --- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 4100404da6..7c282f449b 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index 013d2a71d4..4dcfc1b81f 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 92c5c77aac..197309c7c4 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 82055ecaee..a5db1625d9 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 50530088c2..4a9d88f3a6 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 257db89a20..2a8bd393da 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -7,7 +7,7 @@ - + WinExe From 1295ec490f7c1e5aedba2d349cfc181ef4710114 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 23 Aug 2019 17:57:31 +0300 Subject: [PATCH 2518/5608] Fix difficulty icon not wrapping correctly in beatmap set overlay --- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 104315f1c2..28947b6f22 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -91,7 +91,8 @@ namespace osu.Game.Overlays.BeatmapSet { difficulties = new DifficultiesContainer { - AutoSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Margin = new MarginPadding { Left = -(tile_icon_padding + tile_spacing / 2) }, OnLostHover = () => { From 67acf20805e083264d039d5c063f8bdd94026979 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 23 Aug 2019 18:31:53 +0300 Subject: [PATCH 2519/5608] Add test beatmap set with many difficulties --- .../Online/TestSceneBeatmapSetOverlay.cs | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index daee419b52..8f19df65a9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -135,6 +135,9 @@ namespace osu.Game.Tests.Visual.Online }); downloadAssert(true); + + AddStep("show many difficulties", () => overlay.ShowBeatmapSet(createManyDifficultiesBeatmapSet())); + downloadAssert(true); } [Test] @@ -222,6 +225,56 @@ namespace osu.Game.Tests.Visual.Online AddStep(@"show without reload", overlay.Show); } + private BeatmapSetInfo createManyDifficultiesBeatmapSet() + { + var beatmaps = new List(); + + for (int i = 1; i < 41; i++) + { + beatmaps.Add(new BeatmapInfo + { + OnlineBeatmapID = i * 10, + Version = $"Test #{i}", + Ruleset = Ruleset.Value, + StarDifficulty = 2 + i * 0.1, + BaseDifficulty = new BeatmapDifficulty + { + OverallDifficulty = 3.5f, + }, + OnlineInfo = new BeatmapOnlineInfo(), + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(j => j % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(j => j % 12 - 6).ToArray(), + }, + }); + } + + return new BeatmapSetInfo + { + OnlineBeatmapSetID = 123, + Metadata = new BeatmapMetadata + { + Title = @"many difficulties beatmap", + Artist = @"none", + Author = new User + { + Username = @"BanchoBot", + Id = 3, + }, + }, + OnlineInfo = new BeatmapSetOnlineInfo + { + Preview = @"https://b.ppy.sh/preview/123.mp3", + HasVideo = true, + HasStoryboard = true, + Covers = new BeatmapSetOnlineCovers(), + }, + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, + Beatmaps = beatmaps, + }; + } + private void downloadAssert(bool shown) { AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.DownloadButtonsVisible == shown); From f639df849fa3094a27a35fa08763e6eb501a0def Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 23 Aug 2019 23:11:36 +0300 Subject: [PATCH 2520/5608] Allow for difficulty icon to contain content --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 5cce29d609..81f517dd86 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -19,23 +19,33 @@ using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables { - public class DifficultyIcon : Container, IHasCustomTooltip + public class DifficultyIcon : CompositeDrawable, IHasCustomTooltip { private readonly BeatmapInfo beatmap; private readonly RulesetInfo ruleset; + private readonly Container iconContainer; + + /// + /// Size of this difficulty icon. + /// + public new Vector2 Size + { + get => iconContainer.Size; + set => iconContainer.Size = value; + } + public DifficultyIcon(BeatmapInfo beatmap, RulesetInfo ruleset = null, bool shouldShowTooltip = true) { - if (beatmap == null) - throw new ArgumentNullException(nameof(beatmap)); - - this.beatmap = beatmap; + this.beatmap = beatmap ?? throw new ArgumentNullException(nameof(beatmap)); this.ruleset = ruleset ?? beatmap.Ruleset; if (shouldShowTooltip) TooltipContent = beatmap; - Size = new Vector2(20); + AutoSizeAxes = Axes.Both; + + InternalChild = iconContainer = new Container { Size = new Vector2(20f) }; } public string TooltipText { get; set; } @@ -47,7 +57,7 @@ namespace osu.Game.Beatmaps.Drawables [BackgroundDependencyLoader] private void load(OsuColour colours) { - Children = new Drawable[] + iconContainer.Children = new Drawable[] { new CircularContainer { From d4236c574f99853de259925ebdd44e9dc004200b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 23 Aug 2019 23:30:54 +0300 Subject: [PATCH 2521/5608] Allow difficulty icon to be updateable --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 93 ++++++++++++------- 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 81f517dd86..6d9d0afc78 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -1,7 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -21,10 +22,22 @@ namespace osu.Game.Beatmaps.Drawables { public class DifficultyIcon : CompositeDrawable, IHasCustomTooltip { - private readonly BeatmapInfo beatmap; - private readonly RulesetInfo ruleset; + private BeatmapInfo beatmap; private readonly Container iconContainer; + private readonly Box iconBg; + + protected BeatmapInfo Beatmap + { + get => beatmap; + set + { + beatmap = value; + + if (IsLoaded) + updateIconColour(); + } + } /// /// Size of this difficulty icon. @@ -37,15 +50,46 @@ namespace osu.Game.Beatmaps.Drawables public DifficultyIcon(BeatmapInfo beatmap, RulesetInfo ruleset = null, bool shouldShowTooltip = true) { - this.beatmap = beatmap ?? throw new ArgumentNullException(nameof(beatmap)); + this.beatmap = beatmap; - this.ruleset = ruleset ?? beatmap.Ruleset; if (shouldShowTooltip) TooltipContent = beatmap; AutoSizeAxes = Axes.Both; - InternalChild = iconContainer = new Container { Size = new Vector2(20f) }; + InternalChild = iconContainer = new Container + { + Size = new Vector2(20f), + Children = new Drawable[] + { + new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.84f), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0.08f), + Type = EdgeEffectType.Shadow, + Radius = 5, + }, + Child = iconBg = new Box + { + RelativeSizeAxes = Axes.Both, + }, + }, + new ConstrainedIconContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + // the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment) + Icon = (ruleset ?? beatmap?.Ruleset)?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle } + } + } + }; } public string TooltipText { get; set; } @@ -54,41 +98,18 @@ namespace osu.Game.Beatmaps.Drawables public object TooltipContent { get; set; } + private OsuColour colours; + [BackgroundDependencyLoader] private void load(OsuColour colours) { - iconContainer.Children = new Drawable[] - { - new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.84f), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Masking = true, - EdgeEffect = new EdgeEffectParameters - { - Colour = Color4.Black.Opacity(0.08f), - Type = EdgeEffectType.Shadow, - Radius = 5, - }, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.ForDifficultyRating(beatmap.DifficultyRating), - }, - }, - new ConstrainedIconContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - // the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment) - Icon = ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle } - } - }; + this.colours = colours; + + updateIconColour(); } + private void updateIconColour() => iconBg.Colour = colours.ForDifficultyRating(beatmap.DifficultyRating); + private class DifficultyIconTooltip : VisibilityContainer, ITooltip { private readonly OsuSpriteText difficultyName, starRating; From 83b6e0f30c674b19607cac50b79d899e036721a5 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 23 Aug 2019 23:36:23 +0300 Subject: [PATCH 2522/5608] Implement grouped difficulty icon --- .../Drawables/GroupedDifficultyIcon.cs | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs diff --git a/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs new file mode 100644 index 0000000000..17f2bf719d --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.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 System.Collections.Generic; +using System.Linq; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets; +using osuTK.Graphics; + +namespace osu.Game.Beatmaps.Drawables +{ + public class GroupedDifficultyIcon : DifficultyIcon + { + private readonly OsuSpriteText counter; + + private List beatmaps; + + protected List Beatmaps + { + get => beatmaps; + set + { + beatmaps = value; + + updateDisplay(); + } + } + + public GroupedDifficultyIcon(List beatmaps, RulesetInfo ruleset, Color4 counterColour) + : base(null, ruleset, false) + { + this.beatmaps = beatmaps; + + AddInternal(counter = new OsuSpriteText + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Padding = new MarginPadding { Left = Size.X }, + Margin = new MarginPadding { Left = 2, Right = 5 }, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold), + Colour = counterColour, + }); + + updateDisplay(); + } + + private void updateDisplay() + { + if (beatmaps == null || beatmaps.Count == 0) + return; + + Beatmap = beatmaps.OrderBy(b => b.StarDifficulty).Last(); + counter.Text = beatmaps.Count.ToString(); + } + } +} From 63e6aca61b6f4a246bc05d17d1fbc1cf6e9c2b57 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 23 Aug 2019 23:40:41 +0300 Subject: [PATCH 2523/5608] Add logic to create grouped difficulty icons in direct panel --- osu.Game/Overlays/Direct/DirectPanel.cs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 8199d80528..b2f3c6befb 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -18,6 +18,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; @@ -28,10 +29,12 @@ namespace osu.Game.Overlays.Direct public readonly BeatmapSetInfo SetInfo; private const double hover_transition_time = 400; + private const int maximum_difficulty_icons = 15; private Container content; private BeatmapSetOverlay beatmapSetOverlay; + private RulesetStore rulesets; public PreviewTrack Preview => PlayButton.Preview; public Bindable PreviewPlaying => PlayButton.Playing; @@ -67,9 +70,10 @@ namespace osu.Game.Overlays.Direct }; [BackgroundDependencyLoader(permitNulls: true)] - private void load(BeatmapManager beatmaps, OsuColour colours, BeatmapSetOverlay beatmapSetOverlay) + private void load(BeatmapManager beatmaps, OsuColour colours, BeatmapSetOverlay beatmapSetOverlay, RulesetStore rulesets) { this.beatmapSetOverlay = beatmapSetOverlay; + this.rulesets = rulesets; AddInternal(content = new Container { @@ -142,8 +146,18 @@ namespace osu.Game.Overlays.Direct { var icons = new List(); - foreach (var b in SetInfo.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty)) - icons.Add(new DifficultyIcon(b)); + if (SetInfo.Beatmaps.Count > maximum_difficulty_icons) + { + foreach (var ruleset in rulesets.AvailableRulesets) + { + List list; + if ((list = SetInfo.Beatmaps.FindAll(b => b.Ruleset.Equals(ruleset))).Count > 0) + icons.Add(new GroupedDifficultyIcon(list, ruleset, this is DirectListPanel ? Color4.White : Color4.Black)); + } + } + else + foreach (var b in SetInfo.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty)) + icons.Add(new DifficultyIcon(b)); return icons; } From 87340061e16d6d41c59802c5c9f9e3b1f0e90e01 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 24 Aug 2019 00:06:28 +0300 Subject: [PATCH 2524/5608] Add logic to create grouped difficulty icons in carousel beatmap set --- .../Carousel/DrawableCarouselBeatmapSet.cs | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 0259f3cd81..c6bd726632 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -19,6 +19,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; +using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; @@ -39,7 +40,7 @@ namespace osu.Game.Screens.Select.Carousel } [BackgroundDependencyLoader(true)] - private void load(BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay) + private void load(BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay, RulesetStore rulesets) { restoreHiddenRequested = s => s.Beatmaps.ForEach(manager.Restore); dialogOverlay = overlay; @@ -95,11 +96,11 @@ namespace osu.Game.Screens.Select.Carousel TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 }, Status = beatmapSet.Status }, - new FillFlowContainer + new FillFlowContainer { AutoSizeAxes = Axes.Both, Spacing = new Vector2(3), - Children = ((CarouselBeatmapSet)Item).Beatmaps.Select(b => new FilterableDifficultyIcon(b)).ToList() + Children = getDifficultyIcons(rulesets), }, } } @@ -108,6 +109,27 @@ namespace osu.Game.Screens.Select.Carousel }; } + private const int maximum_difficulty_icons = 18; + + private List getDifficultyIcons(RulesetStore rulesets) + { + var beatmaps = ((CarouselBeatmapSet)Item).Beatmaps.ToList(); + var icons = new List(); + + if (beatmaps.Count > maximum_difficulty_icons) + { + foreach (var ruleset in rulesets.AvailableRulesets.OrderBy(r => r.ID)) + { + List list; + if ((list = beatmaps.FindAll(b => b.Beatmap.Ruleset.Equals(ruleset))).Count > 0) + icons.Add(new FilterableGroupedDifficultyIcon(list, ruleset)); + } + } + else beatmaps.ForEach(b => icons.Add(new FilterableDifficultyIcon(b))); + + return icons; + } + public MenuItem[] ContextMenuItems { get @@ -205,5 +227,21 @@ namespace osu.Game.Screens.Select.Carousel filtered.TriggerChange(); } } + + public class FilterableGroupedDifficultyIcon : GroupedDifficultyIcon + { + public FilterableGroupedDifficultyIcon(List items, RulesetInfo ruleset) + : base(items.Select(i => i.Beatmap).ToList(), ruleset, Color4.White) + { + items.ForEach(item => item.Filtered.ValueChanged += _ => + { + var hiddenItems = items.FindAll(i => !i.Filtered.Value); + var hasHidden = hiddenItems.Count > 0; + + this.FadeTo(hasHidden ? 1 : 0.1f, 100); + Beatmaps = (hasHidden ? hiddenItems : items).Select(i => i.Beatmap).ToList(); + }); + } + } } } From 8584d3ba231e6b8c67d7ea3f85bf3c5075c996c1 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 24 Aug 2019 00:31:36 +0300 Subject: [PATCH 2525/5608] Add many difficulties beatmap direct panel to the tests --- .../Visual/Online/TestSceneDirectPanel.cs | 62 +++++++++++++++---- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs index 53dbaeddda..731cb62518 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Overlays.Direct; using osu.Game.Rulesets; -using osu.Game.Rulesets.Osu; using osu.Game.Users; using osuTK; @@ -24,7 +23,7 @@ namespace osu.Game.Tests.Visual.Online typeof(IconPill) }; - private BeatmapSetInfo getUndownloadableBeatmapSet(RulesetInfo ruleset) => new BeatmapSetInfo + private BeatmapSetInfo getUndownloadableBeatmapSet() => new BeatmapSetInfo { OnlineBeatmapSetID = 123, Metadata = new BeatmapMetadata @@ -56,23 +55,62 @@ namespace osu.Game.Tests.Visual.Online { new BeatmapInfo { - Ruleset = ruleset, + Ruleset = Ruleset.Value, Version = "Test", StarDifficulty = 6.42, } } }; - [BackgroundDependencyLoader] - private void load() + private BeatmapSetInfo getManyDifficultiesBeatmapSet(RulesetStore rulesets) { - var ruleset = new OsuRuleset().RulesetInfo; + var beatmaps = new List(); - var normal = CreateWorkingBeatmap(ruleset).BeatmapSetInfo; + for (int i = 0; i < 100; i++) + { + beatmaps.Add(new BeatmapInfo + { + Ruleset = rulesets.GetRuleset(i % 4), + StarDifficulty = 2 + i % 4 * 2, + BaseDifficulty = new BeatmapDifficulty + { + OverallDifficulty = 3.5f, + } + }); + } + + return new BeatmapSetInfo + { + OnlineBeatmapSetID = 1, + Metadata = new BeatmapMetadata + { + Title = "many difficulties beatmap", + Artist = "test", + Author = new User + { + Username = "BanchoBot", + Id = 3, + } + }, + OnlineInfo = new BeatmapSetOnlineInfo + { + HasVideo = true, + HasStoryboard = true, + Covers = new BeatmapSetOnlineCovers(), + }, + Beatmaps = beatmaps, + }; + } + + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) + { + var normal = CreateWorkingBeatmap(Ruleset.Value).BeatmapSetInfo; normal.OnlineInfo.HasVideo = true; normal.OnlineInfo.HasStoryboard = true; - var undownloadable = getUndownloadableBeatmapSet(ruleset); + var undownloadable = getUndownloadableBeatmapSet(); + var manyDifficulties = getManyDifficultiesBeatmapSet(rulesets); Child = new BasicScrollContainer { @@ -81,15 +119,17 @@ namespace osu.Game.Tests.Visual.Online { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, + Direction = FillDirection.Full, Padding = new MarginPadding(20), - Spacing = new Vector2(0, 20), + Spacing = new Vector2(5, 20), Children = new Drawable[] { new DirectGridPanel(normal), - new DirectListPanel(normal), new DirectGridPanel(undownloadable), + new DirectGridPanel(manyDifficulties), + new DirectListPanel(normal), new DirectListPanel(undownloadable), + new DirectListPanel(manyDifficulties), }, }, }; From f6feef6b5661cb3b40276311ac2745ee5f3b1053 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 24 Aug 2019 00:33:14 +0300 Subject: [PATCH 2526/5608] Remove redundant using directive --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 6d9d0afc78..7732aa96f8 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; From 8ccbe84f67b87ba97b45576c495a53e509fa878f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 24 Aug 2019 01:30:33 +0300 Subject: [PATCH 2527/5608] Loop on distinct rulesets of beatmap instead of all --- osu.Game/Overlays/Direct/DirectPanel.cs | 12 +++--------- .../Select/Carousel/DrawableCarouselBeatmapSet.cs | 14 +++++--------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index b2f3c6befb..d6258061e1 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -34,7 +34,6 @@ namespace osu.Game.Overlays.Direct private Container content; private BeatmapSetOverlay beatmapSetOverlay; - private RulesetStore rulesets; public PreviewTrack Preview => PlayButton.Preview; public Bindable PreviewPlaying => PlayButton.Playing; @@ -70,10 +69,9 @@ namespace osu.Game.Overlays.Direct }; [BackgroundDependencyLoader(permitNulls: true)] - private void load(BeatmapManager beatmaps, OsuColour colours, BeatmapSetOverlay beatmapSetOverlay, RulesetStore rulesets) + private void load(BeatmapManager beatmaps, OsuColour colours, BeatmapSetOverlay beatmapSetOverlay) { this.beatmapSetOverlay = beatmapSetOverlay; - this.rulesets = rulesets; AddInternal(content = new Container { @@ -148,12 +146,8 @@ namespace osu.Game.Overlays.Direct if (SetInfo.Beatmaps.Count > maximum_difficulty_icons) { - foreach (var ruleset in rulesets.AvailableRulesets) - { - List list; - if ((list = SetInfo.Beatmaps.FindAll(b => b.Ruleset.Equals(ruleset))).Count > 0) - icons.Add(new GroupedDifficultyIcon(list, ruleset, this is DirectListPanel ? Color4.White : Color4.Black)); - } + foreach (var ruleset in SetInfo.Beatmaps.Select(b => b.Ruleset).Distinct()) + icons.Add(new GroupedDifficultyIcon(SetInfo.Beatmaps.FindAll(b => b.Ruleset.Equals(ruleset)), ruleset, this is DirectListPanel ? Color4.White : Color4.Black)); } else foreach (var b in SetInfo.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty)) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index c6bd726632..69b9aa399a 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -40,7 +40,7 @@ namespace osu.Game.Screens.Select.Carousel } [BackgroundDependencyLoader(true)] - private void load(BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay, RulesetStore rulesets) + private void load(BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay) { restoreHiddenRequested = s => s.Beatmaps.ForEach(manager.Restore); dialogOverlay = overlay; @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Select.Carousel { AutoSizeAxes = Axes.Both, Spacing = new Vector2(3), - Children = getDifficultyIcons(rulesets), + Children = getDifficultyIcons(), }, } } @@ -111,19 +111,15 @@ namespace osu.Game.Screens.Select.Carousel private const int maximum_difficulty_icons = 18; - private List getDifficultyIcons(RulesetStore rulesets) + private List getDifficultyIcons() { var beatmaps = ((CarouselBeatmapSet)Item).Beatmaps.ToList(); var icons = new List(); if (beatmaps.Count > maximum_difficulty_icons) { - foreach (var ruleset in rulesets.AvailableRulesets.OrderBy(r => r.ID)) - { - List list; - if ((list = beatmaps.FindAll(b => b.Beatmap.Ruleset.Equals(ruleset))).Count > 0) - icons.Add(new FilterableGroupedDifficultyIcon(list, ruleset)); - } + foreach (var ruleset in beatmaps.Select(b => b.Beatmap.Ruleset).Distinct()) + icons.Add(new FilterableGroupedDifficultyIcon(beatmaps.FindAll(b => b.Beatmap.Ruleset.Equals(ruleset)), ruleset)); } else beatmaps.ForEach(b => icons.Add(new FilterableDifficultyIcon(b))); From 830ddd6ed9a99c42bac7ba4dfa9714751b46076b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 24 Aug 2019 01:31:53 +0300 Subject: [PATCH 2528/5608] Use all rulesets for many difficulties test --- osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 7c9b7c7815..6669ec7da3 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -516,6 +516,7 @@ namespace osu.Game.Tests.Visual.SongSelect OnlineBeatmapID = b * 10, Path = $"extra{b}.osu", Version = $"Extra {b}", + Ruleset = rulesets.GetRuleset((b - 1) % 4), StarDifficulty = 2, BaseDifficulty = new BeatmapDifficulty { From 008e39b7381c0b0b7ffcee28df42019ab967ba49 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 24 Aug 2019 01:40:40 +0300 Subject: [PATCH 2529/5608] Remove redundant using directive --- osu.Game/Overlays/Direct/DirectPanel.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index d6258061e1..7e16daee75 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -18,7 +18,6 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; From 0bcd323d17b12d1c48a13bbc7de2d674a156d513 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 24 Aug 2019 09:30:43 +0300 Subject: [PATCH 2530/5608] Remove unnecessary string literal --- osu.Game/Skinning/LegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index bf2f382527..d699b1f3c6 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -225,7 +225,7 @@ namespace osu.Game.Skinning if (sampleInfo is HitSampleInfo hsi) // Try fallback to non-bank samples. - return Samples.Get($"{hsi.Name}"); + return Samples.Get(hsi.Name); return null; } From af4adb6339e807ee71be35766c1366fb67fcbf38 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sat, 24 Aug 2019 09:43:55 +0300 Subject: [PATCH 2531/5608] Add xmldoc --- osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs index 17f2bf719d..b48b966918 100644 --- a/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs @@ -11,6 +11,12 @@ using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables { + /// + /// A difficulty icon that contains a counter on the right-side of it. + /// + /// + /// Used in cases when there are too many difficulty icons to show. + /// public class GroupedDifficultyIcon : DifficultyIcon { private readonly OsuSpriteText counter; From b204e4419a9dab314f49a4dc52682b95fe8e66e2 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 24 Aug 2019 10:34:54 +0200 Subject: [PATCH 2532/5608] Rename SelectSortingMode & SelectGroupingMode -> SongSelectSortingMode & SongSelectGroupingMode --- osu.Game/Configuration/OsuConfigManager.cs | 8 ++++---- osu.Game/Screens/Select/FilterControl.cs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 6ebacc642d..b13e115387 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -26,8 +26,8 @@ namespace osu.Game.Configuration Set(OsuSetting.DisplayStarsMinimum, 0.0, 0, 10, 0.1); Set(OsuSetting.DisplayStarsMaximum, 10.0, 0, 10, 0.1); - Set(OsuSetting.SelectGroupingMode, GroupMode.All); - Set(OsuSetting.SelectSortingMode, SortMode.Title); + Set(OsuSetting.SongSelectGroupingMode, GroupMode.All); + Set(OsuSetting.SongSelectSortingMode, SortMode.Title); Set(OsuSetting.RandomSelectAlgorithm, RandomSelectAlgorithm.RandomPermutation); @@ -154,8 +154,8 @@ namespace osu.Game.Configuration SaveUsername, DisplayStarsMinimum, DisplayStarsMaximum, - SelectGroupingMode, - SelectSortingMode, + SongSelectGroupingMode, + SongSelectSortingMode, RandomSelectAlgorithm, ShowFpsDisplay, ChatDisplayHeight, diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 44bc3235ac..06b6cccf96 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -156,8 +156,8 @@ namespace osu.Game.Screens.Select ruleset.BindTo(parentRuleset); ruleset.BindValueChanged(_ => updateCriteria()); - SortMode = config.GetBindable(OsuSetting.SelectSortingMode); - GroupMode = config.GetBindable(OsuSetting.SelectGroupingMode); + SortMode = config.GetBindable(OsuSetting.SongSelectSortingMode); + GroupMode = config.GetBindable(OsuSetting.SongSelectGroupingMode); sortTabs.Current.BindTo(SortMode); groupTabs.Current.BindTo(GroupMode); From a19a9b90ede7f812335433b8f171a56fab578a29 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 25 Aug 2019 11:38:26 +0900 Subject: [PATCH 2533/5608] Simplify group filter display --- .../Drawables/GroupedDifficultyIcon.cs | 33 ++----------------- .../Carousel/DrawableCarouselBeatmapSet.cs | 7 ++-- 2 files changed, 5 insertions(+), 35 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs index b48b966918..fbad113caa 100644 --- a/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs @@ -19,46 +19,19 @@ namespace osu.Game.Beatmaps.Drawables /// public class GroupedDifficultyIcon : DifficultyIcon { - private readonly OsuSpriteText counter; - - private List beatmaps; - - protected List Beatmaps - { - get => beatmaps; - set - { - beatmaps = value; - - updateDisplay(); - } - } - public GroupedDifficultyIcon(List beatmaps, RulesetInfo ruleset, Color4 counterColour) - : base(null, ruleset, false) + : base(beatmaps.OrderBy(b => b.StarDifficulty).Last(), ruleset, false) { - this.beatmaps = beatmaps; - - AddInternal(counter = new OsuSpriteText + AddInternal(new OsuSpriteText { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Padding = new MarginPadding { Left = Size.X }, Margin = new MarginPadding { Left = 2, Right = 5 }, Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold), + Text = beatmaps.Count.ToString(), Colour = counterColour, }); - - updateDisplay(); - } - - private void updateDisplay() - { - if (beatmaps == null || beatmaps.Count == 0) - return; - - Beatmap = beatmaps.OrderBy(b => b.StarDifficulty).Last(); - counter.Text = beatmaps.Count.ToString(); } } } diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 69b9aa399a..79e5debdd2 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -231,11 +231,8 @@ namespace osu.Game.Screens.Select.Carousel { items.ForEach(item => item.Filtered.ValueChanged += _ => { - var hiddenItems = items.FindAll(i => !i.Filtered.Value); - var hasHidden = hiddenItems.Count > 0; - - this.FadeTo(hasHidden ? 1 : 0.1f, 100); - Beatmaps = (hasHidden ? hiddenItems : items).Select(i => i.Beatmap).ToList(); + // for now, fade the whole group based on the ratio of hidden items. + this.FadeTo(1 - 0.9f * ((float)items.Count(i => i.Filtered.Value) / items.Count), 100); }); } } From 2e21fbcf6a2ce843172a1f58be10dbf01ffa758f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 25 Aug 2019 11:44:56 +0900 Subject: [PATCH 2534/5608] Fix incorrect colour usage --- osu.Game/Overlays/Direct/DirectGridPanel.cs | 2 +- osu.Game/Overlays/Direct/DirectListPanel.cs | 2 +- osu.Game/Overlays/Direct/DirectPanel.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index 243e79eb9b..7bf94c1483 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -151,7 +151,7 @@ namespace osu.Game.Overlays.Direct AutoSizeAxes = Axes.X, Height = 20, Margin = new MarginPadding { Top = vertical_padding, Bottom = vertical_padding }, - Children = GetDifficultyIcons(), + Children = GetDifficultyIcons(colours), }, }, }, diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index 5757e1445b..158ff648dd 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -129,7 +129,7 @@ namespace osu.Game.Overlays.Direct AutoSizeAxes = Axes.X, Height = 20, Margin = new MarginPadding { Top = vertical_padding, Bottom = vertical_padding }, - Children = GetDifficultyIcons(), + Children = GetDifficultyIcons(colours), }, }, }, diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 7e16daee75..641423f21f 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -139,14 +139,14 @@ namespace osu.Game.Overlays.Direct }; } - protected List GetDifficultyIcons() + protected List GetDifficultyIcons(OsuColour colours) { var icons = new List(); if (SetInfo.Beatmaps.Count > maximum_difficulty_icons) { foreach (var ruleset in SetInfo.Beatmaps.Select(b => b.Ruleset).Distinct()) - icons.Add(new GroupedDifficultyIcon(SetInfo.Beatmaps.FindAll(b => b.Ruleset.Equals(ruleset)), ruleset, this is DirectListPanel ? Color4.White : Color4.Black)); + icons.Add(new GroupedDifficultyIcon(SetInfo.Beatmaps.FindAll(b => b.Ruleset.Equals(ruleset)), ruleset, this is DirectListPanel ? Color4.White : colours.Gray5)); } else foreach (var b in SetInfo.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty)) From 1d34124667666f291957df354b362873c534fce1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 25 Aug 2019 11:56:07 +0900 Subject: [PATCH 2535/5608] Revert all DifficultyIcon changes --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 91 ++++++++----------- 1 file changed, 36 insertions(+), 55 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 7732aa96f8..81f517dd86 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -20,22 +21,10 @@ namespace osu.Game.Beatmaps.Drawables { public class DifficultyIcon : CompositeDrawable, IHasCustomTooltip { - private BeatmapInfo beatmap; + private readonly BeatmapInfo beatmap; + private readonly RulesetInfo ruleset; private readonly Container iconContainer; - private readonly Box iconBg; - - protected BeatmapInfo Beatmap - { - get => beatmap; - set - { - beatmap = value; - - if (IsLoaded) - updateIconColour(); - } - } /// /// Size of this difficulty icon. @@ -48,46 +37,15 @@ namespace osu.Game.Beatmaps.Drawables public DifficultyIcon(BeatmapInfo beatmap, RulesetInfo ruleset = null, bool shouldShowTooltip = true) { - this.beatmap = beatmap; + this.beatmap = beatmap ?? throw new ArgumentNullException(nameof(beatmap)); + this.ruleset = ruleset ?? beatmap.Ruleset; if (shouldShowTooltip) TooltipContent = beatmap; AutoSizeAxes = Axes.Both; - InternalChild = iconContainer = new Container - { - Size = new Vector2(20f), - Children = new Drawable[] - { - new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.84f), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Masking = true, - EdgeEffect = new EdgeEffectParameters - { - Colour = Color4.Black.Opacity(0.08f), - Type = EdgeEffectType.Shadow, - Radius = 5, - }, - Child = iconBg = new Box - { - RelativeSizeAxes = Axes.Both, - }, - }, - new ConstrainedIconContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - // the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment) - Icon = (ruleset ?? beatmap?.Ruleset)?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle } - } - } - }; + InternalChild = iconContainer = new Container { Size = new Vector2(20f) }; } public string TooltipText { get; set; } @@ -96,18 +54,41 @@ namespace osu.Game.Beatmaps.Drawables public object TooltipContent { get; set; } - private OsuColour colours; - [BackgroundDependencyLoader] private void load(OsuColour colours) { - this.colours = colours; - - updateIconColour(); + iconContainer.Children = new Drawable[] + { + new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.84f), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0.08f), + Type = EdgeEffectType.Shadow, + Radius = 5, + }, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.ForDifficultyRating(beatmap.DifficultyRating), + }, + }, + new ConstrainedIconContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + // the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment) + Icon = ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle } + } + }; } - private void updateIconColour() => iconBg.Colour = colours.ForDifficultyRating(beatmap.DifficultyRating); - private class DifficultyIconTooltip : VisibilityContainer, ITooltip { private readonly OsuSpriteText difficultyName, starRating; From ef397434f68b3e6ccd4fca8dc8ddead3f31928f7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 25 Aug 2019 12:00:06 +0900 Subject: [PATCH 2536/5608] use GroupBy instead of Distinct+FindAll --- .../Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 79e5debdd2..c9419107a2 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -118,8 +118,8 @@ namespace osu.Game.Screens.Select.Carousel if (beatmaps.Count > maximum_difficulty_icons) { - foreach (var ruleset in beatmaps.Select(b => b.Beatmap.Ruleset).Distinct()) - icons.Add(new FilterableGroupedDifficultyIcon(beatmaps.FindAll(b => b.Beatmap.Ruleset.Equals(ruleset)), ruleset)); + foreach (var group in beatmaps.GroupBy(b => b.Beatmap.Ruleset)) + icons.Add(new FilterableGroupedDifficultyIcon(group.ToList(), group.Key)); } else beatmaps.ForEach(b => icons.Add(new FilterableDifficultyIcon(b))); From 9881d3677df5896d28bb6e95d5ba7b4e65b0744d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 25 Aug 2019 12:05:46 +0900 Subject: [PATCH 2537/5608] Simplify icon creation --- .../Carousel/DrawableCarouselBeatmapSet.cs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index c9419107a2..0a8c61e3d2 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Select.Carousel { AutoSizeAxes = Axes.Both, Spacing = new Vector2(3), - Children = getDifficultyIcons(), + ChildrenEnumerable = getDifficultyIcons(), }, } } @@ -111,19 +111,13 @@ namespace osu.Game.Screens.Select.Carousel private const int maximum_difficulty_icons = 18; - private List getDifficultyIcons() + private IEnumerable getDifficultyIcons() { var beatmaps = ((CarouselBeatmapSet)Item).Beatmaps.ToList(); - var icons = new List(); - if (beatmaps.Count > maximum_difficulty_icons) - { - foreach (var group in beatmaps.GroupBy(b => b.Beatmap.Ruleset)) - icons.Add(new FilterableGroupedDifficultyIcon(group.ToList(), group.Key)); - } - else beatmaps.ForEach(b => icons.Add(new FilterableDifficultyIcon(b))); - - return icons; + return beatmaps.Count > maximum_difficulty_icons + ? (IEnumerable)beatmaps.GroupBy(b => b.Beatmap.Ruleset).Select(group => new FilterableGroupedDifficultyIcon(group.ToList(), group.Key)) + : beatmaps.Select(b => new FilterableDifficultyIcon(b)); } public MenuItem[] ContextMenuItems From de2c6aa23d30e0480755f1d592f18c864f8b4316 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Aug 2019 12:21:11 +0900 Subject: [PATCH 2538/5608] Rename and expand usability of SkinProvidingContainer --- .../Skinning/BeatmapSkinProvidingContainer.cs | 38 ++++++++++++++++ ...Container.cs => SkinProvidingContainer.cs} | 44 ++++++++----------- 2 files changed, 57 insertions(+), 25 deletions(-) create mode 100644 osu.Game/Skinning/BeatmapSkinProvidingContainer.cs rename osu.Game/Skinning/{LocalSkinOverrideContainer.cs => SkinProvidingContainer.cs} (60%) diff --git a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs new file mode 100644 index 0000000000..dc25a33f1e --- /dev/null +++ b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs @@ -0,0 +1,38 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Game.Configuration; + +namespace osu.Game.Skinning +{ + /// + /// A container which overrides existing skin options with beatmap-local values. + /// + public class BeatmapSkinProvidingContainer : SkinProvidingContainer + { + private readonly Bindable beatmapSkins = new Bindable(); + private readonly Bindable beatmapHitsounds = new Bindable(); + + protected override bool AllowConfigurationLookup => beatmapSkins.Value; + protected override bool AllowDrawableLookup(string componentName) => beatmapSkins.Value; + protected override bool AllowTextureLookup(string componentName) => beatmapSkins.Value; + protected override bool AllowSampleLookup(string componentName) => beatmapHitsounds.Value; + + public BeatmapSkinProvidingContainer(ISkin skin) + : base(skin) + { + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + config.BindWith(OsuSetting.BeatmapSkins, beatmapSkins); + config.BindWith(OsuSetting.BeatmapHitsounds, beatmapHitsounds); + + beatmapSkins.BindValueChanged(_ => TriggerSourceChanged()); + beatmapHitsounds.BindValueChanged(_ => TriggerSourceChanged()); + } + } +} diff --git a/osu.Game/Skinning/LocalSkinOverrideContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs similarity index 60% rename from osu.Game/Skinning/LocalSkinOverrideContainer.cs rename to osu.Game/Skinning/SkinProvidingContainer.cs index 7882e0f31b..a92a0ae0d1 100644 --- a/osu.Game/Skinning/LocalSkinOverrideContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -4,29 +4,32 @@ using System; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; -using osu.Game.Configuration; namespace osu.Game.Skinning { /// - /// A container which overrides existing skin options with beatmap-local values. + /// A container which adds a local to the hierarchy. /// - public class LocalSkinOverrideContainer : Container, ISkinSource + public class SkinProvidingContainer : Container, ISkinSource { public event Action SourceChanged; - private readonly Bindable beatmapSkins = new Bindable(); - private readonly Bindable beatmapHitsounds = new Bindable(); - private readonly ISkin skin; private ISkinSource fallbackSource; - public LocalSkinOverrideContainer(ISkin skin) + protected virtual bool AllowDrawableLookup(string componentName) => true; + + protected virtual bool AllowTextureLookup(string componentName) => true; + + protected virtual bool AllowSampleLookup(string componentName) => true; + + protected virtual bool AllowConfigurationLookup => true; + + public SkinProvidingContainer(ISkin skin) { this.skin = skin; } @@ -34,7 +37,7 @@ namespace osu.Game.Skinning public Drawable GetDrawableComponent(string componentName) { Drawable sourceDrawable; - if (beatmapSkins.Value && (sourceDrawable = skin?.GetDrawableComponent(componentName)) != null) + if (AllowDrawableLookup(componentName) && (sourceDrawable = skin?.GetDrawableComponent(componentName)) != null) return sourceDrawable; return fallbackSource?.GetDrawableComponent(componentName); @@ -43,7 +46,7 @@ namespace osu.Game.Skinning public Texture GetTexture(string componentName) { Texture sourceTexture; - if (beatmapSkins.Value && (sourceTexture = skin?.GetTexture(componentName)) != null) + if (AllowTextureLookup(componentName) && (sourceTexture = skin?.GetTexture(componentName)) != null) return sourceTexture; return fallbackSource.GetTexture(componentName); @@ -52,7 +55,7 @@ namespace osu.Game.Skinning public SampleChannel GetSample(string sampleName) { SampleChannel sourceChannel; - if (beatmapHitsounds.Value && (sourceChannel = skin?.GetSample(sampleName)) != null) + if (AllowSampleLookup(sampleName) && (sourceChannel = skin?.GetSample(sampleName)) != null) return sourceChannel; return fallbackSource?.GetSample(sampleName); @@ -61,14 +64,13 @@ namespace osu.Game.Skinning public TValue GetValue(Func query) where TConfiguration : SkinConfiguration { TValue val; - if ((skin as Skin)?.Configuration is TConfiguration conf) - if (beatmapSkins.Value && (val = query.Invoke(conf)) != null) - return val; + if (AllowConfigurationLookup && skin != null && (val = skin.GetValue(query)) != null) + return val; return fallbackSource == null ? default : fallbackSource.GetValue(query); } - private void onSourceChanged() => SourceChanged?.Invoke(); + protected virtual void TriggerSourceChanged() => SourceChanged?.Invoke(); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { @@ -76,18 +78,10 @@ namespace osu.Game.Skinning fallbackSource = dependencies.Get(); if (fallbackSource != null) - fallbackSource.SourceChanged += onSourceChanged; + fallbackSource.SourceChanged += TriggerSourceChanged; dependencies.CacheAs(this); - var config = dependencies.Get(); - - config.BindWith(OsuSetting.BeatmapSkins, beatmapSkins); - config.BindWith(OsuSetting.BeatmapHitsounds, beatmapHitsounds); - - beatmapSkins.BindValueChanged(_ => onSourceChanged()); - beatmapHitsounds.BindValueChanged(_ => onSourceChanged()); - return dependencies; } @@ -99,7 +93,7 @@ namespace osu.Game.Skinning base.Dispose(isDisposing); if (fallbackSource != null) - fallbackSource.SourceChanged -= onSourceChanged; + fallbackSource.SourceChanged -= TriggerSourceChanged; } } } From 5e362d10b1c26443bb6c95c3f61c0b5984e81b7d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Aug 2019 12:21:49 +0900 Subject: [PATCH 2539/5608] Add ruleset-specific legacy skin providers This moves implementation of osu! skinnables to OsuLegacySkin. --- osu.Game.Rulesets.Osu/OsuLegacySkin.cs | 228 +++++++++++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 3 + osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 2 +- osu.Game/Rulesets/Ruleset.cs | 3 + osu.Game/Screens/Play/Player.cs | 41 ++-- osu.Game/Skinning/LegacySkin.cs | 137 -------------- 6 files changed, 261 insertions(+), 153 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/OsuLegacySkin.cs diff --git a/osu.Game.Rulesets.Osu/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/OsuLegacySkin.cs new file mode 100644 index 0000000000..0085d64353 --- /dev/null +++ b/osu.Game.Rulesets.Osu/OsuLegacySkin.cs @@ -0,0 +1,228 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Animations; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu +{ + public class OsuLegacySkin : ISkin + { + private readonly ISkin source; + + private Lazy configuration; + + private Lazy hasHitCircle; + + /// + /// On osu-stable, hitcircles have 5 pixels of transparent padding on each side to allow for shadows etc. + /// Their hittable area is 128px, but the actual circle portion is 118px. + /// We must account for some gameplay elements such as slider bodies, where this padding is not present. + /// + private const float legacy_circle_radius = 64 - 5; + + public OsuLegacySkin(ISkinSource source) + { + this.source = source; + + source.SourceChanged += sourceChanged; + sourceChanged(); + } + + private void sourceChanged() + { + configuration = new Lazy(() => + { + var config = new SkinConfiguration(); + if (hasHitCircle.Value) + config.SliderPathRadius = legacy_circle_radius; + return config; + }); + + hasHitCircle = new Lazy(() => source.GetTexture("hitcircle") != null); + } + + private const double default_frame_time = 1000 / 60d; + + public Drawable GetDrawableComponent(string componentName) + { + switch (componentName) + { + case "Play/osu/sliderball": + var sliderBallContent = getAnimation("sliderb", true, true, ""); + + if (sliderBallContent != null) + { + var size = sliderBallContent.Size; + + sliderBallContent.RelativeSizeAxes = Axes.Both; + sliderBallContent.Size = Vector2.One; + + return new LegacySliderBall(sliderBallContent) + { + Size = size + }; + } + + return null; + + case "Play/osu/hitcircle": + if (hasHitCircle.Value) + return new LegacyMainCirclePiece(); + + return null; + } + + return null; + } + + private Drawable getAnimation(string componentName, bool animatable, bool looping, string animationSeparator = "-") + { + Texture texture; + + Texture getFrameTexture(int frame) => source.GetTexture($"{componentName}{animationSeparator}{frame}"); + + TextureAnimation animation = null; + + if (animatable) + { + for (int i = 0;; i++) + { + if ((texture = getFrameTexture(i)) == null) + break; + + if (animation == null) + animation = new TextureAnimation + { + DefaultFrameLength = default_frame_time, + Repeat = looping + }; + + animation.AddFrame(texture); + } + } + + if (animation != null) + return animation; + + if ((texture = source.GetTexture(componentName)) != null) + return new Sprite { Texture = texture }; + + return null; + } + + public Texture GetTexture(string componentName) => null; + + public SampleChannel GetSample(string sampleName) => null; + + public TValue GetValue(Func query) where TConfiguration : SkinConfiguration + => configuration.Value is TConfiguration conf ? query.Invoke(conf) : default; + + public class LegacySliderBall : CompositeDrawable + { + private readonly Drawable animationContent; + + public LegacySliderBall(Drawable animationContent) + { + this.animationContent = animationContent; + } + + [BackgroundDependencyLoader] + private void load(ISkinSource skin, DrawableHitObject drawableObject) + { + animationContent.Colour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Color4.White; + + InternalChildren = new[] + { + new Sprite + { + Texture = skin.GetTexture("sliderb-nd"), + Colour = new Color4(5, 5, 5, 255), + }, + animationContent, + new Sprite + { + Texture = skin.GetTexture("sliderb-spec"), + Blending = BlendingParameters.Additive, + }, + }; + } + } + + public class LegacyMainCirclePiece : CompositeDrawable + { + public LegacyMainCirclePiece() + { + Size = new Vector2(128); + } + + private readonly IBindable state = new Bindable(); + + private readonly Bindable accentColour = new Bindable(); + + [BackgroundDependencyLoader] + private void load(DrawableHitObject drawableObject, ISkinSource skin) + { + Sprite hitCircleSprite; + + InternalChildren = new Drawable[] + { + hitCircleSprite = new Sprite + { + Texture = skin.GetTexture("hitcircle"), + Colour = drawableObject.AccentColour.Value, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new SkinnableSpriteText("Play/osu/number-text", _ => new OsuSpriteText + { + Font = OsuFont.Numeric.With(size: 40), + UseFullGlyphHeight = false, + }, confineMode: ConfineMode.NoScaling) + { + Text = (((IHasComboInformation)drawableObject.HitObject).IndexInCurrentCombo + 1).ToString() + }, + new Sprite + { + Texture = skin.GetTexture("hitcircleoverlay"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + + state.BindTo(drawableObject.State); + state.BindValueChanged(updateState, true); + + accentColour.BindTo(drawableObject.AccentColour); + accentColour.BindValueChanged(colour => hitCircleSprite.Colour = colour.NewValue, true); + } + + private void updateState(ValueChangedEvent state) + { + const double legacy_fade_duration = 240; + + switch (state.NewValue) + { + case ArmedState.Hit: + this.FadeOut(legacy_fade_duration, Easing.Out); + this.ScaleTo(1.4f, legacy_fade_duration, Easing.Out); + break; + } + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index d50d4f401c..4211ae253c 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -24,6 +24,7 @@ using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Difficulty; using osu.Game.Scoring; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu { @@ -163,6 +164,8 @@ namespace osu.Game.Rulesets.Osu public override RulesetSettingsSubsection CreateSettings() => new OsuSettingsSubsection(this); + public override ISkin CreateLegacySkinProvider(ISkinSource source) => new OsuLegacySkin(source); + public override int? LegacyID => 0; public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new OsuReplayFrame(); diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 9037faf606..178183bd22 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.UI }, // Todo: This should not exist, but currently helps to reduce LOH allocations due to unbinding skin source events on judgement disposal // Todo: Remove when hitobjects are properly pooled - new LocalSkinOverrideContainer(null) + new SkinProvidingContainer(null) { RelativeSizeAxes = Axes.Both, Child = HitObjectContainer, diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 42b1322cae..2fbbd74d7a 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -18,6 +18,7 @@ using osu.Game.Configuration; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; using osu.Game.Scoring; +using osu.Game.Skinning; namespace osu.Game.Rulesets { @@ -44,6 +45,8 @@ namespace osu.Game.Rulesets public ModAutoplay GetAutoplayMod() => GetAllMods().OfType().First(); + public virtual ISkin CreateLegacySkinProvider(ISkinSource source) => null; + protected Ruleset(RulesetInfo rulesetInfo = null) { RulesetInfo = rulesetInfo ?? createRulesetInfo(); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index e7398be176..deed17a049 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -60,7 +60,9 @@ namespace osu.Game.Screens.Play [Resolved] private ScoreManager scoreManager { get; set; } - private RulesetInfo ruleset; + private RulesetInfo rulesetInfo; + + private Ruleset ruleset; private IAPIProvider api; @@ -121,20 +123,29 @@ namespace osu.Game.Screens.Play InternalChild = GameplayClockContainer = new GameplayClockContainer(working, Mods.Value, DrawableRuleset.GameplayStartTime); + SkinProvidingContainer skinProvidingContainer = new BeatmapSkinProvidingContainer(working.Skin) + { + RelativeSizeAxes = Axes.Both, + }; + GameplayClockContainer.Children = new[] { DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both }, new ScalingContainer(ScalingMode.Gameplay) { - Child = new LocalSkinOverrideContainer(working.Skin) - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + Child = skinProvidingContainer.WithChild( + // the skinProvidingContainer is used as the fallback source here to allow the ruleset-specific skin implementation + // full access to all skin sources. + new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(skinProvidingContainer)) { - DrawableRuleset, - new ComboEffects(ScoreProcessor) + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + DrawableRuleset, + new ComboEffects(ScoreProcessor) + } } - } + ) }, breakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { @@ -222,20 +233,20 @@ namespace osu.Game.Screens.Play if (beatmap == null) throw new InvalidOperationException("Beatmap was not loaded"); - ruleset = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset; - var rulesetInstance = ruleset.CreateInstance(); + rulesetInfo = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset; + ruleset = rulesetInfo.CreateInstance(); try { - DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(working, Mods.Value); + DrawableRuleset = ruleset.CreateDrawableRulesetWith(working, Mods.Value); } catch (BeatmapInvalidForRulesetException) { // we may fail to create a DrawableRuleset if the beatmap cannot be loaded with the user's preferred ruleset // let's try again forcing the beatmap's ruleset. - ruleset = beatmap.BeatmapInfo.Ruleset; - rulesetInstance = ruleset.CreateInstance(); - DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(Beatmap.Value, Mods.Value); + rulesetInfo = beatmap.BeatmapInfo.Ruleset; + ruleset = rulesetInfo.CreateInstance(); + DrawableRuleset = ruleset.CreateDrawableRulesetWith(Beatmap.Value, Mods.Value); } if (!DrawableRuleset.Objects.Any()) @@ -313,7 +324,7 @@ namespace osu.Game.Screens.Play var score = DrawableRuleset.ReplayScore?.ScoreInfo ?? new ScoreInfo { Beatmap = Beatmap.Value.BeatmapInfo, - Ruleset = ruleset, + Ruleset = rulesetInfo, Mods = Mods.Value.ToArray(), User = api.LocalUser.Value, }; diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 48310cf027..785daba878 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -9,7 +9,6 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Containers; @@ -20,8 +19,6 @@ using osu.Framework.Text; using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; using osuTK; using osuTK.Graphics; @@ -34,13 +31,6 @@ namespace osu.Game.Skinning protected IResourceStore Samples; - /// - /// On osu-stable, hitcircles have 5 pixels of transparent padding on each side to allow for shadows etc. - /// Their hittable area is 128px, but the actual circle portion is 118px. - /// We must account for some gameplay elements such as slider bodies, where this padding is not present. - /// - private const float legacy_circle_radius = 64 - 5; - public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini") { @@ -48,8 +38,6 @@ namespace osu.Game.Skinning if (!Configuration.CustomColours.ContainsKey("SliderBall")) Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); } - private readonly bool hasHitCircle; - protected LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager, string filename) : base(skin) { @@ -62,14 +50,6 @@ namespace osu.Game.Skinning Samples = audioManager.GetSampleStore(storage); Textures = new TextureStore(new TextureLoaderStore(storage)); - - using (var testStream = storage.GetStream("hitcircle@2x") ?? storage.GetStream("hitcircle")) - hasHitCircle |= testStream != null; - - if (hasHitCircle) - { - Configuration.SliderPathRadius = legacy_circle_radius; - } } protected override void Dispose(bool isDisposing) @@ -94,30 +74,6 @@ namespace osu.Game.Skinning return null; - case "Play/osu/sliderball": - var sliderBallContent = getAnimation("sliderb", true, true, ""); - - if (sliderBallContent != null) - { - var size = sliderBallContent.Size; - - sliderBallContent.RelativeSizeAxes = Axes.Both; - sliderBallContent.Size = Vector2.One; - - return new LegacySliderBall(sliderBallContent) - { - Size = size - }; - } - - return null; - - case "Play/osu/hitcircle": - if (hasHitCircle) - return new LegacyMainCirclePiece(); - - return null; - case "Play/osu/sliderfollowcircle": animatable = true; break; @@ -355,99 +311,6 @@ namespace osu.Game.Skinning } } - public class LegacySliderBall : CompositeDrawable - { - private readonly Drawable animationContent; - - public LegacySliderBall(Drawable animationContent) - { - this.animationContent = animationContent; - } - - [BackgroundDependencyLoader] - private void load(ISkinSource skin, DrawableHitObject drawableObject) - { - animationContent.Colour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Color4.White; - - InternalChildren = new[] - { - new Sprite - { - Texture = skin.GetTexture("sliderb-nd"), - Colour = new Color4(5, 5, 5, 255), - }, - animationContent, - new Sprite - { - Texture = skin.GetTexture("sliderb-spec"), - Blending = BlendingParameters.Additive, - }, - }; - } - } - - public class LegacyMainCirclePiece : CompositeDrawable - { - public LegacyMainCirclePiece() - { - Size = new Vector2(128); - } - - private readonly IBindable state = new Bindable(); - - private readonly Bindable accentColour = new Bindable(); - - [BackgroundDependencyLoader] - private void load(DrawableHitObject drawableObject, ISkinSource skin) - { - Sprite hitCircleSprite; - - InternalChildren = new Drawable[] - { - hitCircleSprite = new Sprite - { - Texture = skin.GetTexture("hitcircle"), - Colour = drawableObject.AccentColour.Value, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - new SkinnableSpriteText("Play/osu/number-text", _ => new OsuSpriteText - { - Font = OsuFont.Numeric.With(size: 40), - UseFullGlyphHeight = false, - }, confineMode: ConfineMode.NoScaling) - { - Text = (((IHasComboInformation)drawableObject.HitObject).IndexInCurrentCombo + 1).ToString() - }, - new Sprite - { - Texture = skin.GetTexture("hitcircleoverlay"), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } - }; - - state.BindTo(drawableObject.State); - state.BindValueChanged(updateState, true); - - accentColour.BindTo(drawableObject.AccentColour); - accentColour.BindValueChanged(colour => hitCircleSprite.Colour = colour.NewValue, true); - } - - private void updateState(ValueChangedEvent state) - { - const double legacy_fade_duration = 240; - - switch (state.NewValue) - { - case ArmedState.Hit: - this.FadeOut(legacy_fade_duration, Easing.Out); - this.ScaleTo(1.4f, legacy_fade_duration, Easing.Out); - break; - } - } - } - /// /// A sprite which is displayed within the playfield, but historically was not considered part of the playfield. /// Performs scale adjustment to undo the scale applied by (osu! ruleset specifically). From 6e3a63dae8a9dbc59d47993d884b97b2414de7df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Aug 2019 12:31:51 +0900 Subject: [PATCH 2540/5608] Update tests --- .../SkinnableTestScene.cs | 20 +++++++++++++++---- .../Gameplay/TestSceneSkinnableDrawable.cs | 8 ++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs b/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs index 02716dc1d5..c3a64f8b54 100644 --- a/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs +++ b/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs @@ -37,10 +37,22 @@ namespace osu.Game.Rulesets.Osu.Tests public void SetContents(Func creationFunction) { - Cell(0).Child = new LocalSkinOverrideContainer(null) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); - Cell(1).Child = new LocalSkinOverrideContainer(metricsSkin) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); - Cell(2).Child = new LocalSkinOverrideContainer(defaultSkin) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); - Cell(3).Child = new LocalSkinOverrideContainer(specialSkin) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); + Cell(0).Child = createProvider(null, creationFunction); + Cell(1).Child = createProvider(metricsSkin, creationFunction); + Cell(2).Child = createProvider(defaultSkin, creationFunction); + Cell(3).Child = createProvider(specialSkin, creationFunction); + } + + private Drawable createProvider(Skin skin, Func creationFunction) + { + var mainProvider = new SkinProvidingContainer(skin) { RelativeSizeAxes = Axes.Both }; + + return mainProvider + .WithChild(new SkinProvidingContainer(Ruleset.Value.CreateInstance().CreateLegacySkinProvider(mainProvider)) + { + RelativeSizeAxes = Axes.Both, + Child = creationFunction() + }); } private class TestLegacySkin : LegacySkin diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs index 0b5978e3eb..b18eca0600 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("setup layout larger source", () => { - Child = new LocalSkinOverrideContainer(new SizedSource(50)) + Child = new SkinProvidingContainer(new SizedSource(50)) { RelativeSizeAxes = Axes.Both, Child = fill = new FillFlowContainer @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("setup layout larger source", () => { - Child = new LocalSkinOverrideContainer(new SizedSource(30)) + Child = new SkinProvidingContainer(new SizedSource(30)) { RelativeSizeAxes = Axes.Both, Child = fill = new FillFlowContainer @@ -95,7 +95,7 @@ namespace osu.Game.Tests.Visual.Gameplay Child = new SkinSourceContainer { RelativeSizeAxes = Axes.Both, - Child = new LocalSkinOverrideContainer(secondarySource) + Child = new SkinProvidingContainer(secondarySource) { RelativeSizeAxes = Axes.Both, Child = consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation"), source => true) @@ -120,7 +120,7 @@ namespace osu.Game.Tests.Visual.Gameplay Child = new SkinSourceContainer { RelativeSizeAxes = Axes.Both, - Child = target = new LocalSkinOverrideContainer(secondarySource) + Child = target = new SkinProvidingContainer(secondarySource) { RelativeSizeAxes = Axes.Both, } From d99c60adc7cf97d11de29631ec46c1c652a1b62e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Aug 2019 12:51:13 +0900 Subject: [PATCH 2541/5608] Provide a way to scale beat lengths relative to each other --- .../Rulesets/Timing/MultiplierControlPoint.cs | 8 +++- .../UI/Scrolling/DrawableScrollingRuleset.cs | 38 +++++++++++++++---- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs index 9bab065d1e..ffa35c24cd 100644 --- a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs +++ b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs @@ -20,7 +20,13 @@ namespace osu.Game.Rulesets.Timing /// /// The aggregate multiplier which this provides. /// - public double Multiplier => Velocity * DifficultyPoint.SpeedMultiplier * 1000 / TimingPoint.BeatLength; + public double Multiplier => Velocity * DifficultyPoint.SpeedMultiplier * BaseBeatLength / TimingPoint.BeatLength; + + /// + /// The base beat length to scale the provided multiplier relative to. + /// + /// For a of 1000, a with a beat length of 500 will increase the multiplier by 2. + public double BaseBeatLength = 1000; /// /// The velocity multiplier. diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 42ec0b79b9..385f824ef5 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -69,6 +69,11 @@ namespace osu.Game.Rulesets.UI.Scrolling /// protected virtual bool UserScrollSpeedAdjustment => true; + /// + /// Whether beat lengths should scale relative to the most common beat length in the . + /// + protected virtual bool RelativeScaleBeatLengths => false; + /// /// Provides the default s that adjust the scrolling rate of s /// inside this . @@ -107,16 +112,35 @@ namespace osu.Game.Rulesets.UI.Scrolling [BackgroundDependencyLoader] private void load() { - // Calculate default multiplier control points + double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; + double baseBeatLength = 1000; + + if (RelativeScaleBeatLengths) + { + IReadOnlyList timingPoints = Beatmap.ControlPointInfo.TimingPoints; + double maxDuration = 0; + + for (int i = 0; i < timingPoints.Count; i++) + { + double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time : lastObjectTime; + double duration = endTime - timingPoints[i].Time; + + if (duration > maxDuration) + { + maxDuration = duration; + baseBeatLength = timingPoints[i].BeatLength; + } + } + } + + // Merge sequences of timing and difficulty control points to create the aggregate "multiplier" control point var lastTimingPoint = new TimingControlPoint(); var lastDifficultyPoint = new DifficultyControlPoint(); - - // Merge timing + difficulty points var allPoints = new SortedList(Comparer.Default); allPoints.AddRange(Beatmap.ControlPointInfo.TimingPoints); allPoints.AddRange(Beatmap.ControlPointInfo.DifficultyPoints); - // Generate the timing points, making non-timing changes use the previous timing change + // Generate the timing points, making non-timing changes use the previous timing change and vice-versa var timingChanges = allPoints.Select(c => { var timingPoint = c as TimingControlPoint; @@ -131,14 +155,13 @@ namespace osu.Game.Rulesets.UI.Scrolling return new MultiplierControlPoint(c.Time) { Velocity = Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier, + BaseBeatLength = baseBeatLength, TimingPoint = lastTimingPoint, DifficultyPoint = lastDifficultyPoint }; }); - double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; - - // Perform some post processing of the timing changes + // Trim unwanted sequences of timing changes timingChanges = timingChanges // Collapse sections after the last hit object .Where(s => s.StartTime <= lastObjectTime) @@ -147,7 +170,6 @@ namespace osu.Game.Rulesets.UI.Scrolling controlPoints.AddRange(timingChanges); - // If we have no control points, add a default one if (controlPoints.Count == 0) controlPoints.Add(new MultiplierControlPoint { Velocity = Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier }); } From e30ae57ea66325491eb1f94c7314d6270da5d3c8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Aug 2019 12:51:23 +0900 Subject: [PATCH 2542/5608] Scale mania beat lengths relative to each other --- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index c8aeda8fe4..0718de2c7d 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -36,6 +36,8 @@ namespace osu.Game.Rulesets.Mania.UI public IEnumerable BarLines; + protected override bool RelativeScaleBeatLengths => true; + protected new ManiaRulesetConfigManager Config => (ManiaRulesetConfigManager)base.Config; private readonly Bindable configDirection = new Bindable(); From 7b82121b8503f81de85013e9c82435d4b584d34c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Aug 2019 13:03:00 +0900 Subject: [PATCH 2543/5608] Add comment about lazy usage --- osu.Game.Rulesets.Osu/OsuLegacySkin.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/OsuLegacySkin.cs index 0085d64353..988eb6a439 100644 --- a/osu.Game.Rulesets.Osu/OsuLegacySkin.cs +++ b/osu.Game.Rulesets.Osu/OsuLegacySkin.cs @@ -45,6 +45,7 @@ namespace osu.Game.Rulesets.Osu private void sourceChanged() { + // these need to be lazy in order to ensure they aren't called before the dependencies have been loaded into our source. configuration = new Lazy(() => { var config = new SkinConfiguration(); From 289bd8e6b0c9367ae4cb9bbb15a4f3be7c424213 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Aug 2019 14:25:35 +0900 Subject: [PATCH 2544/5608] Don't return DefaultSkin on beatmap skin parsing failure --- osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 5657b8fb8a..2d8a0b1249 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -138,19 +138,15 @@ namespace osu.Game.Beatmaps protected override Skin GetSkin() { - Skin skin; - try { - skin = new LegacyBeatmapSkin(BeatmapInfo, store, AudioManager); + return new LegacyBeatmapSkin(BeatmapInfo, store, AudioManager); } catch (Exception e) { Logger.Error(e, "Skin failed to load"); - skin = new DefaultSkin(); + return null; } - - return skin; } } } From db987c6077153102848ffe9f16c79de8480c39e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Aug 2019 14:24:48 +0900 Subject: [PATCH 2545/5608] Move SliderBall colour logic to OsuLegacySkinProvider --- osu.Game.Rulesets.Osu/OsuLegacySkin.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Rulesets.Osu/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/OsuLegacySkin.cs index 988eb6a439..1957156918 100644 --- a/osu.Game.Rulesets.Osu/OsuLegacySkin.cs +++ b/osu.Game.Rulesets.Osu/OsuLegacySkin.cs @@ -51,6 +51,12 @@ namespace osu.Game.Rulesets.Osu var config = new SkinConfiguration(); if (hasHitCircle.Value) config.SliderPathRadius = legacy_circle_radius; + + // defaults should only be applied for non-beatmap skins (which are parsed via this constructor). + config.CustomColours["SliderBall"] = + source.GetValue(s => s.CustomColours.TryGetValue("SliderBall", out var val) ? val : (Color4?)null) + ?? new Color4(2, 170, 255, 255); + return config; }); From 1cfe2b7de8388ade173269519e7947400ef18778 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Aug 2019 16:25:23 +0900 Subject: [PATCH 2546/5608] Fix timing points beyond the end time potentially becoming dominant --- osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 385f824ef5..65a22b10b7 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -122,6 +122,9 @@ namespace osu.Game.Rulesets.UI.Scrolling for (int i = 0; i < timingPoints.Count; i++) { + if (timingPoints[i].Time > lastObjectTime) + break; + double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time : lastObjectTime; double duration = endTime - timingPoints[i].Time; From fb8b5ee1060dfd0ec8467ed15ddcc4c84806603f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Aug 2019 16:31:46 +0900 Subject: [PATCH 2547/5608] Add test --- .../TestSceneDrawableScrollingRuleset.cs | 305 ++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs new file mode 100644 index 0000000000..ee11fc0d06 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -0,0 +1,305 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Framework.MathUtils; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Configuration; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.UI.Scrolling; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestSceneDrawableScrollingRuleset : OsuTestScene + { + /// + /// The amount of time visible by the "view window" of the playfield. + /// All hitobjects added through are spaced apart by this value, such that for a beat length of 1000, + /// there will be at most 2 hitobjects visible in the "view window". + /// + private const double time_range = 1000; + + private readonly ManualClock testClock = new ManualClock(); + private TestDrawableScrollingRuleset drawableRuleset; + + [SetUp] + public void Setup() => Schedule(() => testClock.CurrentTime = 0); + + [Test] + public void TestRelativeBeatLengthScaleSingleTimingPoint() + { + var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range / 2 }); + + createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); + + assertPosition(0, 0f); + + // The single timing point is 1x speed relative to itself, such that the hitobject occurring time_range milliseconds later should appear + // at the bottom of the view window regardless of the timing point's beat length + assertPosition(1, 1f); + } + + [Test] + public void TestRelativeBeatLengthScaleTimingPointBeyondEndDoesNotBecomeDominant() + { + var beatmap = createBeatmap( + new TimingControlPoint { BeatLength = time_range / 2 }, + new TimingControlPoint { Time = 12000, BeatLength = time_range }, + new TimingControlPoint { Time = 100000, BeatLength = time_range }); + + createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); + + assertPosition(0, 0f); + assertPosition(1, 1f); + } + + [Test] + public void TestRelativeBeatLengthScaleFromSecondTimingPoint() + { + var beatmap = createBeatmap( + new TimingControlPoint { BeatLength = time_range }, + new TimingControlPoint { Time = 3 * time_range, BeatLength = time_range / 2 }); + + createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); + + // The first timing point should have a relative velocity of 2 + assertPosition(0, 0f); + assertPosition(1, 0.5f); + assertPosition(2, 1f); + + // Move to the second timing point + setTime(3 * time_range); + assertPosition(3, 0f); + + // As above, this is the timing point that is 1x speed relative to itself, so the hitobject occurring time_range milliseconds later should be at the bottom of the view window + assertPosition(4, 1f); + } + + [Test] + public void TestNonRelativeScale() + { + var beatmap = createBeatmap( + new TimingControlPoint { BeatLength = time_range }, + new TimingControlPoint { Time = 3 * time_range, BeatLength = time_range / 2 }); + + createTest(beatmap); + + assertPosition(0, 0f); + assertPosition(1, 1); + + // Move to the second timing point + setTime(3 * time_range); + assertPosition(3, 0f); + + // For a beat length of 500, the view window of this timing point is elongated 2x (1000 / 500), such that the second hitobject is two TimeRanges away (offscreen) + // To bring it on-screen, half TimeRange is added to the current time, bringing the second half of the view window into view, and the hitobject should appear at the bottom + setTime(3 * time_range + time_range / 2); + assertPosition(4, 1f); + } + + private void assertPosition(int index, float relativeY) => AddAssert($"hitobject {index} at {relativeY}", + () => Precision.AlmostEquals(drawableRuleset.Playfield.AllHitObjects.ElementAt(index).DrawPosition.Y, drawableRuleset.Playfield.HitObjectContainer.DrawHeight * relativeY)); + + private void setTime(double time) + { + AddStep($"set time = {time}", () => testClock.CurrentTime = time); + } + + /// + /// Creates an , containing 10 hitobjects and user-provided timing points. + /// The hitobjects are spaced milliseconds apart. + /// + /// The timing points to add to the beatmap. + /// The . + private IBeatmap createBeatmap(params TimingControlPoint[] timingControlPoints) + { + var beatmap = new Beatmap { BeatmapInfo = { Ruleset = new OsuRuleset().RulesetInfo } }; + + beatmap.ControlPointInfo.TimingPoints.AddRange(timingControlPoints); + + for (int i = 0; i < 10; i++) + beatmap.HitObjects.Add(new HitObject { StartTime = i * time_range }); + + return beatmap; + } + + private void createTest(IBeatmap beatmap, Action overrideAction = null) => AddStep("create test", () => + { + var ruleset = new TestScrollingRuleset(); + + drawableRuleset = (TestDrawableScrollingRuleset)ruleset.CreateDrawableRulesetWith(CreateWorkingBeatmap(beatmap), Array.Empty()); + drawableRuleset.FrameStablePlayback = false; + + overrideAction?.Invoke(drawableRuleset); + + Child = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Height = 0.75f, + Width = 400, + Masking = true, + Clock = new FramedClock(testClock), + Child = drawableRuleset + }; + }); + + #region Ruleset + + private class TestScrollingRuleset : Ruleset + { + public TestScrollingRuleset(RulesetInfo rulesetInfo = null) + : base(rulesetInfo) + { + } + + public override IEnumerable GetModsFor(ModType type) => throw new NotImplementedException(); + + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods) => new TestDrawableScrollingRuleset(this, beatmap, mods); + + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap); + + public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new NotImplementedException(); + + public override string Description { get; } = string.Empty; + + public override string ShortName { get; } = string.Empty; + } + + private class TestDrawableScrollingRuleset : DrawableScrollingRuleset + { + public bool RelativeScaleBeatLengthsOverride { get; set; } + + protected override bool RelativeScaleBeatLengths => RelativeScaleBeatLengthsOverride; + + protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping; + + public TestDrawableScrollingRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) + : base(ruleset, beatmap, mods) + { + TimeRange.Value = time_range; + } + + public override DrawableHitObject CreateDrawableRepresentation(TestHitObject h) => new DrawableTestHitObject(h); + + protected override PassThroughInputManager CreateInputManager() => new PassThroughInputManager(); + + protected override Playfield CreatePlayfield() => new TestPlayfield(); + } + + private class TestPlayfield : ScrollingPlayfield + { + public TestPlayfield() + { + AddInternal(new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.2f, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 150 }, + Children = new Drawable[] + { + new Box + { + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Height = 2, + Colour = Color4.Green + }, + HitObjectContainer + } + } + } + }); + } + } + + private class TestBeatmapConverter : BeatmapConverter + { + public TestBeatmapConverter(IBeatmap beatmap) + : base(beatmap) + { + } + + protected override IEnumerable ValidConversionTypes => new[] { typeof(HitObject) }; + + protected override IEnumerable ConvertHitObject(HitObject original, IBeatmap beatmap) + { + yield return new TestHitObject + { + StartTime = original.StartTime, + EndTime = (original as IHasEndTime)?.EndTime ?? (original.StartTime + 100) + }; + } + } + + #endregion + + #region HitObject + + private class TestHitObject : HitObject, IHasEndTime + { + public double EndTime { get; set; } + + public double Duration => EndTime - StartTime; + } + + private class DrawableTestHitObject : DrawableHitObject + { + public DrawableTestHitObject(TestHitObject hitObject) + : base(hitObject) + { + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; + + Size = new Vector2(100, 25); + + AddRangeInternal(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.LightPink + }, + new Box + { + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, + Height = 2, + Colour = Color4.Red + } + }); + } + } + + #endregion + } +} From 6596d7fc463d3a73cbf5605d1074135db9c230f8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Aug 2019 16:33:24 +0900 Subject: [PATCH 2548/5608] Add nullref safety to FrameStablePlayback boolean --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index eb14bd1f24..ccfd89adca 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -62,13 +62,20 @@ namespace osu.Game.Rulesets.UI public override GameplayClock FrameStableClock => frameStabilityContainer.GameplayClock; + private bool frameStablePlayback = true; + /// /// Whether to enable frame-stable playback. /// internal bool FrameStablePlayback { - get => frameStabilityContainer.FrameStablePlayback; - set => frameStabilityContainer.FrameStablePlayback = value; + get => frameStablePlayback; + set + { + frameStablePlayback = false; + if (frameStabilityContainer != null) + frameStabilityContainer.FrameStablePlayback = value; + } } /// @@ -156,6 +163,7 @@ namespace osu.Game.Rulesets.UI { frameStabilityContainer = new FrameStabilityContainer(GameplayStartTime) { + FrameStablePlayback = FrameStablePlayback, Child = KeyBindingInputManager .WithChild(CreatePlayfieldAdjustmentContainer() .WithChild(Playfield) From 6dfe95db74b6d12d1ed5b9567a0652eb6303d589 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Aug 2019 16:34:12 +0900 Subject: [PATCH 2549/5608] Allow RulesetConfigCache to return null configs --- osu.Game/Rulesets/RulesetConfigCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index 9a5a4d4acd..8c9e3c94e2 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets public IRulesetConfigManager GetConfigFor(Ruleset ruleset) { if (ruleset.RulesetInfo.ID == null) - throw new InvalidOperationException("The provided ruleset doesn't have a valid id."); + return null; return configCache.GetOrAdd(ruleset.RulesetInfo.ID.Value, _ => ruleset.CreateConfig(settingsStore)); } From fb1cd9e5e7a9050a8b2af1882ecf342f4928baf8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Aug 2019 16:47:23 +0900 Subject: [PATCH 2550/5608] Add a sane default lifetime end for scrolling hitobjects --- .../UI/Scrolling/ScrollingHitObjectContainer.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 19247d8a37..14a4869a98 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -12,8 +12,13 @@ namespace osu.Game.Rulesets.UI.Scrolling { public class ScrollingHitObjectContainer : HitObjectContainer { - private readonly IBindable timeRange = new BindableDouble(); + /// + /// A multiplier applied to the length of the scrolling area to determine a safe default lifetime end for hitobjects. + /// This is only used to limit the lifetime end within reason, as proper lifetime management should be implemented on hitobjects themselves. + /// + private const float safe_lifetime_end_multiplier = 2; + private readonly IBindable timeRange = new BindableDouble(); private readonly IBindable direction = new Bindable(); [Resolved] @@ -92,6 +97,8 @@ namespace osu.Game.Rulesets.UI.Scrolling if (hitObject.HitObject is IHasEndTime endTime) { + hitObject.LifetimeEnd = scrollingInfo.Algorithm.TimeAt(scrollLength * safe_lifetime_end_multiplier, endTime.EndTime, timeRange.Value, scrollLength); + switch (direction.Value) { case ScrollingDirection.Up: @@ -105,6 +112,8 @@ namespace osu.Game.Rulesets.UI.Scrolling break; } } + else + hitObject.LifetimeEnd = scrollingInfo.Algorithm.TimeAt(scrollLength * safe_lifetime_end_multiplier, hitObject.HitObject.StartTime, timeRange.Value, scrollLength); foreach (var obj in hitObject.NestedHitObjects) { From d4a296f9116fc9ce35695e9f2c89bfebd3cd8041 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Aug 2019 17:45:12 +0900 Subject: [PATCH 2551/5608] Slight refactoring --- .../Replays/ManiaAutoGenerator.cs | 8 ++++---- .../Replays/TaikoAutoGenerator.cs | 14 +++++++++----- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index fd0a876775..7b8bbc2095 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -98,12 +98,12 @@ namespace osu.Game.Rulesets.Mania.Replays protected override HitObject GetNextObject(int currentIndex) { - int desiredColumn = Beatmap.HitObjects[currentIndex++].Column; + int desiredColumn = Beatmap.HitObjects[currentIndex].Column; - for (; currentIndex < Beatmap.HitObjects.Count; currentIndex++) + for (int i = currentIndex + 1; i < Beatmap.HitObjects.Count; i++) { - if (Beatmap.HitObjects[currentIndex].Column == desiredColumn) - return Beatmap.HitObjects[currentIndex]; + if (Beatmap.HitObjects[i].Column == desiredColumn) + return Beatmap.HitObjects[i]; } return null; diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 6720d8b8bf..299679b2c1 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -137,14 +137,18 @@ namespace osu.Game.Rulesets.Taiko.Replays protected override HitObject GetNextObject(int currentIndex) { - Type desiredType = Beatmap.HitObjects[currentIndex++].GetType(); + Type desiredType = Beatmap.HitObjects[currentIndex].GetType(); - for (; currentIndex < Beatmap.HitObjects.Count; currentIndex++) + for (int i = currentIndex + 1; i < Beatmap.HitObjects.Count; i++) { - var currentObj = Beatmap.HitObjects[currentIndex]; + var currentObj = Beatmap.HitObjects[i]; + if (currentObj.GetType() == desiredType || - currentObj is DrumRoll || currentObj is Swell) // Unpress all keys before DrumRoll or Swell - return Beatmap.HitObjects[currentIndex]; + // Un-press all keys before a DrumRoll or Swell + currentObj is DrumRoll || currentObj is Swell) + { + return Beatmap.HitObjects[i]; + } } return null; From 62641c149d96d33ec56542764b3d2a8ddd7258cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Aug 2019 18:18:14 +0900 Subject: [PATCH 2552/5608] Fx component lookups being incorrect for non-databased legacy skins --- .../metrics-skin/approachcircle@2x.png | Bin 0 -> 13816 bytes osu.Game/Skinning/LegacySkin.cs | 10 ++++++---- 2 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/approachcircle@2x.png diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/approachcircle@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/metrics-skin/approachcircle@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..72ef665478b758c364197aa79f238230e229b3c4 GIT binary patch literal 13816 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 X;|*6ltxe$d|7PiG>1$T1+eQB$HM;D+ literal 0 HcmV?d00001 diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 48310cf027..7bffe5d321 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -155,6 +155,11 @@ namespace osu.Game.Skinning // Spacing value was reverse-engineered from the ratio of the rendered sprite size in the visual inspector vs the actual texture size Spacing = new Vector2(-Configuration.HitCircleOverlap * 0.89f, 0) }; + + default: + string lastPiece = componentName.Split('/').Last(); + componentName = componentName.StartsWith("Gameplay/taiko/") ? "taiko-" + lastPiece : lastPiece; + break; } return getAnimation(componentName, animatable, looping); @@ -226,11 +231,8 @@ namespace osu.Game.Skinning { bool hasExtension = filename.Contains('.'); - string lastPiece = filename.Split('/').Last(); - var legacyName = filename.StartsWith("Gameplay/taiko/") ? "taiko-" + lastPiece : lastPiece; - var file = source.Files.Find(f => - string.Equals(hasExtension ? f.Filename : Path.ChangeExtension(f.Filename, null), legacyName, StringComparison.InvariantCultureIgnoreCase)); + string.Equals(hasExtension ? f.Filename : Path.ChangeExtension(f.Filename, null), filename, StringComparison.InvariantCultureIgnoreCase)); return file?.FileInfo.StoragePath; } From 0422c19c2fc524d03f1d159f780f01ae6457365a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Aug 2019 19:06:23 +0900 Subject: [PATCH 2553/5608] Group lifetime setters together --- .../UI/Scrolling/ScrollingHitObjectContainer.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 14a4869a98..1df8c8218f 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -93,27 +93,28 @@ namespace osu.Game.Rulesets.UI.Scrolling private void computeInitialStateRecursive(DrawableHitObject hitObject) { - hitObject.LifetimeStart = scrollingInfo.Algorithm.GetDisplayStartTime(hitObject.HitObject.StartTime, timeRange.Value); + double endTime = hitObject.HitObject.StartTime; - if (hitObject.HitObject is IHasEndTime endTime) + if (hitObject.HitObject is IHasEndTime e) { - hitObject.LifetimeEnd = scrollingInfo.Algorithm.TimeAt(scrollLength * safe_lifetime_end_multiplier, endTime.EndTime, timeRange.Value, scrollLength); + endTime = e.EndTime; switch (direction.Value) { case ScrollingDirection.Up: case ScrollingDirection.Down: - hitObject.Height = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, endTime.EndTime, timeRange.Value, scrollLength); + hitObject.Height = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, endTime, timeRange.Value, scrollLength); break; case ScrollingDirection.Left: case ScrollingDirection.Right: - hitObject.Width = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, endTime.EndTime, timeRange.Value, scrollLength); + hitObject.Width = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, endTime, timeRange.Value, scrollLength); break; } } - else - hitObject.LifetimeEnd = scrollingInfo.Algorithm.TimeAt(scrollLength * safe_lifetime_end_multiplier, hitObject.HitObject.StartTime, timeRange.Value, scrollLength); + + hitObject.LifetimeStart = scrollingInfo.Algorithm.GetDisplayStartTime(hitObject.HitObject.StartTime, timeRange.Value); + hitObject.LifetimeEnd = scrollingInfo.Algorithm.TimeAt(scrollLength * safe_lifetime_end_multiplier, endTime, timeRange.Value, scrollLength); foreach (var obj in hitObject.NestedHitObjects) { From fd0f42eee4ffd88e1b65e69e8187d906b596b25e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 26 Aug 2019 14:11:24 +0300 Subject: [PATCH 2554/5608] Fix filtered grouped difficulty items in DrawableCarouselBeatmapSet aren't hidden on first load --- .../Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 0a8c61e3d2..137fce7acf 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -223,11 +223,9 @@ namespace osu.Game.Screens.Select.Carousel public FilterableGroupedDifficultyIcon(List items, RulesetInfo ruleset) : base(items.Select(i => i.Beatmap).ToList(), ruleset, Color4.White) { - items.ForEach(item => item.Filtered.ValueChanged += _ => - { - // for now, fade the whole group based on the ratio of hidden items. - this.FadeTo(1 - 0.9f * ((float)items.Count(i => i.Filtered.Value) / items.Count), 100); - }); + // for now, fade the whole group based on the ratio of hidden items. + items.ForEach(item => item.Filtered.BindValueChanged(_ + => this.FadeTo(1 - 0.9f * ((float)items.Count(i => i.Filtered.Value) / items.Count), 100), true)); } } } From 9321f208841a9b66a8f7a1441f9812a5f7d4c157 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 26 Aug 2019 14:32:27 +0300 Subject: [PATCH 2555/5608] Move arrow to the first line --- .../Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 137fce7acf..5ef20bd0f2 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -224,8 +224,8 @@ namespace osu.Game.Screens.Select.Carousel : base(items.Select(i => i.Beatmap).ToList(), ruleset, Color4.White) { // for now, fade the whole group based on the ratio of hidden items. - items.ForEach(item => item.Filtered.BindValueChanged(_ - => this.FadeTo(1 - 0.9f * ((float)items.Count(i => i.Filtered.Value) / items.Count), 100), true)); + items.ForEach(item => item.Filtered.BindValueChanged(_ => + this.FadeTo(1 - 0.9f * ((float)items.Count(i => i.Filtered.Value) / items.Count), 100), true)); } } } From fb69755869775abfbbb7ae79c4ca8087696c6aa8 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 26 Aug 2019 15:15:23 +0300 Subject: [PATCH 2556/5608] Use transform management for catch hit objects --- .../Objects/Drawable/DrawableCatchHitObject.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index a1279e8443..f4218061d4 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -58,14 +58,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable ApplyResult(r => r.Type = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss); } - protected override bool UseTransformStateManagement => false; + protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; - protected override void UpdateState(ArmedState state) + protected override void UpdateInitialTransforms() => this.FadeIn(200); + + protected override void UpdateStateTransforms(ArmedState state) { - // TODO: update to use new state management. - using (BeginAbsoluteSequence(HitObject.StartTime - HitObject.TimePreempt)) - this.FadeIn(200); - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; using (BeginAbsoluteSequence(endTime, true)) From 3f93780306769c6a6bee07c57065052178f41bef Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 26 Aug 2019 15:15:48 +0300 Subject: [PATCH 2557/5608] Override transform update functions in bar line --- .../Objects/Drawables/DrawableBarLine.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index 9c3197504f..dee7bddcb3 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -69,7 +69,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Alpha = 0.2f; } - protected override void UpdateState(ArmedState state) + protected override void UpdateInitialTransforms() + { + } + + protected override void UpdateStateTransforms(ArmedState state) { } } From 62edfe7327672f2b56de7bfaf797555a3676927f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 26 Aug 2019 15:16:01 +0300 Subject: [PATCH 2558/5608] Correct comment --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 62abe53559..ceda643335 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.UI if (lastPlateableFruit == null) return; - // this is required to make this run after the last caught fruit runs UpdateState at least once. + // this is required to make this run after the last caught fruit runs updateState() at least once. // TODO: find a better alternative if (lastPlateableFruit.IsLoaded) action(); From 24e7146a976297fabe3d56093cda75d16e412a4c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 26 Aug 2019 15:26:19 +0300 Subject: [PATCH 2559/5608] Revert unintended change --- .../Objects/Drawables/DrawableBarLine.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index dee7bddcb3..9c3197504f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -69,11 +69,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Alpha = 0.2f; } - protected override void UpdateInitialTransforms() - { - } - - protected override void UpdateStateTransforms(ArmedState state) + protected override void UpdateState(ArmedState state) { } } From c11f5084004520256a56663d7fdb5d7c3e80869b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 26 Aug 2019 22:06:30 +0300 Subject: [PATCH 2560/5608] Use transform management for mania hit objects --- .../Objects/Drawables/DrawableBarLine.cs | 2 +- .../Drawables/DrawableManiaHitObject.cs | 29 +++++++++---------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index 9c3197504f..e9c352c97e 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Alpha = 0.2f; } - protected override void UpdateState(ArmedState state) + protected override void UpdateStateTransforms(ArmedState state) { } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index db6b53e76d..e5b114ca81 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -45,24 +45,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { Anchor = Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; } - } - public abstract class DrawableManiaHitObject : DrawableManiaHitObject - where TObject : ManiaHitObject - { - public new readonly TObject HitObject; - - protected DrawableManiaHitObject(TObject hitObject) - : base(hitObject) + protected override void UpdateStateTransforms(ArmedState state) { - HitObject = hitObject; - } - - protected override bool UseTransformStateManagement => false; - - protected override void UpdateState(ArmedState state) - { - // TODO: update to use new state management. switch (state) { case ArmedState.Miss: @@ -75,4 +60,16 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } } } + + public abstract class DrawableManiaHitObject : DrawableManiaHitObject + where TObject : ManiaHitObject + { + public new readonly TObject HitObject; + + protected DrawableManiaHitObject(TObject hitObject) + : base(hitObject) + { + HitObject = hitObject; + } + } } From 8d30c35104378baee846b75c338313291543c724 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 27 Aug 2019 03:10:58 +0300 Subject: [PATCH 2561/5608] Implement sorting --- osu.Game/Overlays/SocialOverlay.cs | 65 +++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 4def249200..dc63b0ab9a 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -16,6 +16,7 @@ using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.Social; using osu.Game.Users; using osu.Framework.Threading; +using System; namespace osu.Game.Overlays { @@ -71,7 +72,7 @@ namespace osu.Game.Overlays Filter.Tabs.Current.ValueChanged += _ => queueUpdate(); Filter.DisplayStyleControl.DisplayStyle.ValueChanged += style => recreatePanels(style.NewValue); - Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => queueUpdate(); + Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => onDropdownChanged(); currentQuery.BindTo(Filter.Search.Current); currentQuery.ValueChanged += query => @@ -175,11 +176,71 @@ namespace osu.Game.Overlays private void updateUsers(IEnumerable newUsers) { - Users = newUsers; + var sortDirection = Filter.DisplayStyleControl.Dropdown.Current.Value; + + IEnumerable sortedUsers = newUsers; + + switch (Filter.Tabs.Current.Value) + { + case SocialSortCriteria.Location: + switch (sortDirection) + { + case SortDirection.Ascending: + sortedUsers = newUsers.OrderBy(u => u.Country.FullName); + break; + + case SortDirection.Descending: + sortedUsers = newUsers.OrderByDescending(u => u.Country.FullName); + break; + } + break; + + case SocialSortCriteria.Name: + switch (sortDirection) + { + case SortDirection.Ascending: + sortedUsers = newUsers.OrderBy(u => u.Username); + break; + + case SortDirection.Descending: + sortedUsers = newUsers.OrderByDescending(u => u.Username); + break; + } + break; + + case SocialSortCriteria.Rank: + if (newUsers.FirstOrDefault().Statistics != null) + { + switch (sortDirection) + { + case SortDirection.Ascending: + sortedUsers = newUsers.OrderBy(u => u.Statistics?.Ranks.Global); + break; + + case SortDirection.Descending: + sortedUsers = newUsers.OrderByDescending(u => u.Statistics?.Ranks.Global); + break; + } + } + break; + } + + Users = sortedUsers; loading.Hide(); recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); } + private void onDropdownChanged() + { + if (Users == null) + { + queueUpdate(); + return; + } + + updateUsers(Users); + } + private void clearPanels() { if (panels != null) From cb81d1dd2fea0a174777044e7fdd8fa451f977f6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 27 Aug 2019 03:53:16 +0300 Subject: [PATCH 2562/5608] Better use of loading animation --- osu.Game/Overlays/SocialOverlay.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index dc63b0ab9a..2202c473f6 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -103,7 +103,6 @@ namespace osu.Game.Overlays Users = null; clearPanels(); - loading.Hide(); getUsersRequest?.Cancel(); if (API?.IsLoggedIn != true) @@ -131,8 +130,13 @@ namespace osu.Game.Overlays { clearPanels(); + loading.Show(); + if (Users == null) + { + loading.Hide(); return; + } var newPanels = new FillFlowContainer { @@ -167,15 +171,15 @@ namespace osu.Game.Overlays LoadComponentAsync(newPanels, f => { - if (panels != null) - ScrollFlow.Remove(panels); - + loading.Hide(); ScrollFlow.Add(panels = newPanels); }); } private void updateUsers(IEnumerable newUsers) { + loading.Show(); + var sortDirection = Filter.DisplayStyleControl.Dropdown.Current.Value; IEnumerable sortedUsers = newUsers; @@ -226,7 +230,6 @@ namespace osu.Game.Overlays } Users = sortedUsers; - loading.Hide(); recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); } From 7cc6494482c7ba413012c5aa527da25b1c66eb41 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 27 Aug 2019 03:54:49 +0300 Subject: [PATCH 2563/5608] Remove sorting by rank Since it isn't working for any case currently --- osu.Game/Overlays/SocialOverlay.cs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 2202c473f6..8353e2d683 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -211,22 +211,6 @@ namespace osu.Game.Overlays break; } break; - - case SocialSortCriteria.Rank: - if (newUsers.FirstOrDefault().Statistics != null) - { - switch (sortDirection) - { - case SortDirection.Ascending: - sortedUsers = newUsers.OrderBy(u => u.Statistics?.Ranks.Global); - break; - - case SortDirection.Descending: - sortedUsers = newUsers.OrderByDescending(u => u.Statistics?.Ranks.Global); - break; - } - } - break; } Users = sortedUsers; From 66b27875e06dedb156b76caacdedc213d6affb87 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 27 Aug 2019 04:00:22 +0300 Subject: [PATCH 2564/5608] Fix possible null exception --- osu.Game/Overlays/SocialOverlay.cs | 49 ++++++++++++++++-------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 8353e2d683..22d1471229 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -184,33 +184,36 @@ namespace osu.Game.Overlays IEnumerable sortedUsers = newUsers; - switch (Filter.Tabs.Current.Value) + if (sortedUsers.Any()) { - case SocialSortCriteria.Location: - switch (sortDirection) - { - case SortDirection.Ascending: - sortedUsers = newUsers.OrderBy(u => u.Country.FullName); - break; + switch (Filter.Tabs.Current.Value) + { + case SocialSortCriteria.Location: + switch (sortDirection) + { + case SortDirection.Ascending: + sortedUsers = sortedUsers.OrderBy(u => u.Country.FullName); + break; - case SortDirection.Descending: - sortedUsers = newUsers.OrderByDescending(u => u.Country.FullName); - break; - } - break; + case SortDirection.Descending: + sortedUsers = sortedUsers.OrderByDescending(u => u.Country.FullName); + break; + } + break; - case SocialSortCriteria.Name: - switch (sortDirection) - { - case SortDirection.Ascending: - sortedUsers = newUsers.OrderBy(u => u.Username); - break; + case SocialSortCriteria.Name: + switch (sortDirection) + { + case SortDirection.Ascending: + sortedUsers = sortedUsers.OrderBy(u => u.Username); + break; - case SortDirection.Descending: - sortedUsers = newUsers.OrderByDescending(u => u.Username); - break; - } - break; + case SortDirection.Descending: + sortedUsers = sortedUsers.OrderByDescending(u => u.Username); + break; + } + break; + } } Users = sortedUsers; From 385bc6f52988c3f8c9858b8525aeceb11e6b33fa Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 27 Aug 2019 04:11:22 +0300 Subject: [PATCH 2565/5608] Remove using and add blank lines --- osu.Game/Overlays/SocialOverlay.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 22d1471229..23185ed989 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -16,7 +16,6 @@ using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.Social; using osu.Game.Users; using osu.Framework.Threading; -using System; namespace osu.Game.Overlays { @@ -199,6 +198,7 @@ namespace osu.Game.Overlays sortedUsers = sortedUsers.OrderByDescending(u => u.Country.FullName); break; } + break; case SocialSortCriteria.Name: @@ -212,6 +212,7 @@ namespace osu.Game.Overlays sortedUsers = sortedUsers.OrderByDescending(u => u.Username); break; } + break; } } From 9223a1ba8a4ff25c82e719374e37a3f3f3a90f81 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 27 Aug 2019 05:03:47 +0300 Subject: [PATCH 2566/5608] Simplify sorting logic --- osu.Game/Overlays/SocialOverlay.cs | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 23185ed989..e2179361b1 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -16,6 +16,7 @@ using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.Social; using osu.Game.Users; using osu.Framework.Threading; +using System; namespace osu.Game.Overlays { @@ -188,31 +189,11 @@ namespace osu.Game.Overlays switch (Filter.Tabs.Current.Value) { case SocialSortCriteria.Location: - switch (sortDirection) - { - case SortDirection.Ascending: - sortedUsers = sortedUsers.OrderBy(u => u.Country.FullName); - break; - - case SortDirection.Descending: - sortedUsers = sortedUsers.OrderByDescending(u => u.Country.FullName); - break; - } - + sortedUsers = sortBy(sortedUsers, u => u.Country.FullName, sortDirection); break; case SocialSortCriteria.Name: - switch (sortDirection) - { - case SortDirection.Ascending: - sortedUsers = sortedUsers.OrderBy(u => u.Username); - break; - - case SortDirection.Descending: - sortedUsers = sortedUsers.OrderByDescending(u => u.Username); - break; - } - + sortedUsers = sortBy(sortedUsers, u => u.Username, sortDirection); break; } } @@ -221,6 +202,9 @@ namespace osu.Game.Overlays recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); } + private IEnumerable sortBy(IEnumerable users, Func condition, SortDirection sortDirection) => + sortDirection == SortDirection.Ascending ? users.OrderBy(condition) : users.OrderByDescending(condition); + private void onDropdownChanged() { if (Users == null) From 843da26dbafc7c1605981bcf15f9c3006d5b5361 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 27 Aug 2019 05:03:56 +0300 Subject: [PATCH 2567/5608] Use transform management for taiko hit objects --- .../Objects/Drawables/DrawableDrumRoll.cs | 4 +- .../Objects/Drawables/DrawableDrumRollTick.cs | 2 +- .../Objects/Drawables/DrawableHit.cs | 64 ++++++++----------- .../Objects/Drawables/DrawableSwell.cs | 21 +++--- .../Drawables/DrawableTaikoHitObject.cs | 2 - 5 files changed, 41 insertions(+), 52 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 9b4df74a61..f4407a7b54 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -88,13 +88,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables ApplyResult(r => r.Type = HitResult.Miss); } - protected override void UpdateState(ArmedState state) + protected override void UpdateStateTransforms(ArmedState state) { switch (state) { case ArmedState.Hit: case ArmedState.Miss: - this.FadeOut(100).Expire(); + this.Delay(HitObject.Duration).FadeOut(100).Expire(); break; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 9259c693d9..cef9a53deb 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables ApplyResult(r => r.Type = HitResult.Great); } - protected override void UpdateState(ArmedState state) + protected override void UpdateStateTransforms(ArmedState state) { switch (state) { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 34ae7db984..fa45067210 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -92,56 +92,42 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Size = BaseSize * Parent.RelativeChildSize; } - protected override void UpdateState(ArmedState state) + protected override void UpdateStateTransforms(ArmedState state) { - // TODO: update to use new state management. - var circlePiece = MainPiece as CirclePiece; - circlePiece?.FlashBox.FinishTransforms(); - - var offset = !AllJudged ? 0 : Time.Current - HitObject.StartTime; - - using (BeginDelayedSequence(HitObject.StartTime - Time.Current + offset, true)) + switch (state) { - switch (State.Value) - { - case ArmedState.Idle: - validActionPressed = false; + case ArmedState.Idle: + validActionPressed = false; - UnproxyContent(); - this.Delay(HitObject.HitWindows.HalfWindowFor(HitResult.Miss)).Expire(); - break; + UnproxyContent(); + this.Delay(HitObject.HitWindows.HalfWindowFor(HitResult.Miss)).Expire(); + break; - case ArmedState.Miss: - this.FadeOut(100) - .Expire(); - break; + case ArmedState.Miss: + this.FadeOut(100) + .Expire(); + break; - case ArmedState.Hit: - // If we're far enough away from the left stage, we should bring outselves in front of it - ProxyContent(); + case ArmedState.Hit: + // If we're far enough away from the left stage, we should bring outselves in front of it + ProxyContent(); - var flash = circlePiece?.FlashBox; + var flash = (MainPiece as CirclePiece)?.FlashBox; + flash?.FadeTo(0.9f).FadeOut(300); - if (flash != null) - { - flash.FadeTo(0.9f); - flash.FadeOut(300); - } + const float gravity_time = 300; + const float gravity_travel_height = 200; - const float gravity_time = 300; - const float gravity_travel_height = 200; + this.ScaleTo(0.8f, gravity_time * 2, Easing.OutQuad); - this.ScaleTo(0.8f, gravity_time * 2, Easing.OutQuad); + this.MoveToY(-gravity_travel_height, gravity_time, Easing.Out) + .Then() + .MoveToY(gravity_travel_height * 2, gravity_time * 2, Easing.In); - this.MoveToY(-gravity_travel_height, gravity_time, Easing.Out) - .Then() - .MoveToY(gravity_travel_height * 2, gravity_time * 2, Easing.In); + this.FadeOut(800) + .Expire(); - this.FadeOut(800) - .Expire(); - - break; - } + break; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 82448ec7d5..88769bfff6 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -179,26 +179,31 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override void UpdateState(ArmedState state) + protected override double InitialLifetimeOffset => 100; + + protected override void UpdateInitialTransforms() => targetRing.ScaleTo(target_ring_scale, InitialLifetimeOffset * 4, Easing.OutQuint); + + protected override void UpdateStateTransforms(ArmedState state) { - const float preempt = 100; - const float out_transition_time = 300; + const double transition_duration = 300; switch (state) { case ArmedState.Idle: UnproxyContent(); expandingRing.FadeTo(0); - using (BeginAbsoluteSequence(HitObject.StartTime - preempt, true)) - targetRing.ScaleTo(target_ring_scale, preempt * 4, Easing.OutQuint); break; case ArmedState.Miss: case ArmedState.Hit: - this.FadeOut(out_transition_time, Easing.Out); - bodyContainer.ScaleTo(1.4f, out_transition_time); + using (BeginAbsoluteSequence(Time.Current, true)) + { + this.FadeOut(transition_duration, Easing.Out); + bodyContainer.ScaleTo(1.4f, transition_duration); + + Expire(); + } - Expire(); break; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index b46738c69a..bd45b52d7b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -121,8 +121,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override bool UseTransformStateManagement => false; - // Normal and clap samples are handled by the drum protected override IEnumerable GetSamples() => HitObject.Samples.Where(s => s.Name != HitSampleInfo.HIT_NORMAL && s.Name != HitSampleInfo.HIT_CLAP); From cd68d030bd186fe3e9ef98489d876f258b76a4e1 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 27 Aug 2019 05:04:34 +0300 Subject: [PATCH 2568/5608] Remove unnecessary UpdateState overrides --- osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs | 4 ---- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs | 4 ---- .../Objects/Drawables/DrawableStrongNestedHit.cs | 4 ---- .../Objects/Drawables/DrawableSwellTick.cs | 4 ---- 4 files changed, 16 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index 6f9856df83..3c84d900a6 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -247,10 +247,6 @@ namespace osu.Game.Rulesets.Taiko.Tests : base(hitObject) { } - - protected override void UpdateState(ArmedState state) - { - } } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index f8909fb98c..bf89f7e15b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -53,9 +53,5 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Alpha = 0.75f }); } - - protected override void UpdateState(ArmedState state) - { - } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs index 98a2e8a721..108e42eea5 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs @@ -18,9 +18,5 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { MainObject = mainObject; } - - protected override void UpdateState(ArmedState state) - { - } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index 41a8fd9a75..fb80a9a5b4 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -21,10 +21,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { } - protected override void UpdateState(ArmedState state) - { - } - public override bool OnPressed(TaikoAction action) => false; } } From 0eef398ca74ebf8d860ae81b86eab3ee0f0d9636 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 27 Aug 2019 05:19:21 +0300 Subject: [PATCH 2569/5608] Remove redundant using directive --- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index fb80a9a5b4..8b27d78101 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Objects.Drawables From 6368189d4660c188ae2360c856268d029ea5de91 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 27 Aug 2019 11:59:25 +0900 Subject: [PATCH 2570/5608] Refactor --- .../Select/Carousel/DrawableCarouselBeatmapSet.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 5ef20bd0f2..97b6a78804 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -220,12 +220,23 @@ namespace osu.Game.Screens.Select.Carousel public class FilterableGroupedDifficultyIcon : GroupedDifficultyIcon { + private readonly List items; + public FilterableGroupedDifficultyIcon(List items, RulesetInfo ruleset) : base(items.Select(i => i.Beatmap).ToList(), ruleset, Color4.White) + { + this.items = items; + + foreach (var item in items) + item.Filtered.BindValueChanged(_ => Scheduler.AddOnce(updateFilteredDisplay)); + + updateFilteredDisplay(); + } + + private void updateFilteredDisplay() { // for now, fade the whole group based on the ratio of hidden items. - items.ForEach(item => item.Filtered.BindValueChanged(_ => - this.FadeTo(1 - 0.9f * ((float)items.Count(i => i.Filtered.Value) / items.Count), 100), true)); + this.FadeTo(1 - 0.9f * ((float)items.Count(i => i.Filtered.Value) / items.Count), 100); } } } From 6014a6680411e2d553a8b09ef2beb86d2f0ee928 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 27 Aug 2019 12:22:31 +0900 Subject: [PATCH 2571/5608] Add initial fade transform to fix rewind --- .../Objects/Drawables/DrawableManiaHitObject.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index e5b114ca81..ce1484d460 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -46,6 +46,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Anchor = Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; } + protected override void UpdateInitialTransforms() => this.FadeIn(); + protected override void UpdateStateTransforms(ArmedState state) { switch (state) From fff2da728926758c7ce6502ab0558b888289f979 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 27 Aug 2019 12:59:57 +0900 Subject: [PATCH 2572/5608] Fix hold notes disappearing instantaneously --- .../Objects/Drawables/DrawableHoldNote.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 952c6e128e..fc3b6885d7 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; @@ -104,6 +105,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables bodyPiece.Height = DrawHeight - Head.Height / 2 + Tail.Height / 2; } + protected override void UpdateStateTransforms(ArmedState state) + { + using (BeginDelayedSequence(HitObject.Duration, true)) + base.UpdateStateTransforms(state); + } + protected void BeginHold() { holdStartTime = Time.Current; From 7885c79467aa732110d1cc6be57daf5a7521336a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 27 Aug 2019 14:31:34 +0900 Subject: [PATCH 2573/5608] Make bindables private --- .../SongSelect/TestScenePlaySongSelect.cs | 21 ++++++++++------ osu.Game/Screens/Select/FilterControl.cs | 24 +++++++++---------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 2dbe53709b..263eada07c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -15,6 +15,7 @@ using osu.Framework.MathUtils; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; @@ -79,8 +80,12 @@ namespace osu.Game.Tests.Visual.SongSelect Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, defaultBeatmap = Beatmap.Default)); Beatmap.SetDefault(); + + Dependencies.Cache(config = new OsuConfigManager(LocalStorage)); } + private OsuConfigManager config; + [SetUp] public virtual void SetUp() => Schedule(() => { @@ -111,13 +116,15 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap); - AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.SortMode.Value = SortMode.Artist; }); - AddStep(@"Sort by Title", delegate { songSelect.FilterControl.SortMode.Value = SortMode.Title; }); - AddStep(@"Sort by Author", delegate { songSelect.FilterControl.SortMode.Value = SortMode.Author; }); - AddStep(@"Sort by DateAdded", delegate { songSelect.FilterControl.SortMode.Value = SortMode.DateAdded; }); - AddStep(@"Sort by BPM", delegate { songSelect.FilterControl.SortMode.Value = SortMode.BPM; }); - AddStep(@"Sort by Length", delegate { songSelect.FilterControl.SortMode.Value = SortMode.Length; }); - AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.SortMode.Value = SortMode.Difficulty; }); + var sortMode = config.GetBindable(OsuSetting.SongSelectSortingMode); + + AddStep(@"Sort by Artist", delegate { sortMode.Value = SortMode.Artist; }); + AddStep(@"Sort by Title", delegate { sortMode.Value = SortMode.Title; }); + AddStep(@"Sort by Author", delegate { sortMode.Value = SortMode.Author; }); + AddStep(@"Sort by DateAdded", delegate { sortMode.Value = SortMode.DateAdded; }); + AddStep(@"Sort by BPM", delegate { sortMode.Value = SortMode.BPM; }); + AddStep(@"Sort by Length", delegate { sortMode.Value = SortMode.Length; }); + AddStep(@"Sort by Difficulty", delegate { sortMode.Value = SortMode.Difficulty; }); } [Test] diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 06b6cccf96..ed74b01fc9 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -29,14 +29,14 @@ namespace osu.Game.Screens.Select private readonly TabControl groupTabs; - public Bindable SortMode; + private Bindable sortMode; - public Bindable GroupMode; + private Bindable groupMode; public FilterCriteria CreateCriteria() => new FilterCriteria { - Group = GroupMode.Value, - Sort = SortMode.Value, + Group = groupMode.Value, + Sort = sortMode.Value, SearchText = searchTextBox.Text, AllowConvertedBeatmaps = showConverted.Value, Ruleset = ruleset.Value @@ -123,8 +123,8 @@ namespace osu.Game.Screens.Select searchTextBox.Current.ValueChanged += _ => FilterChanged?.Invoke(CreateCriteria()); - groupTabs.PinItem(Filter.GroupMode.All); - groupTabs.PinItem(Filter.GroupMode.RecentlyPlayed); + groupTabs.PinItem(GroupMode.All); + groupTabs.PinItem(GroupMode.RecentlyPlayed); } public void Deactivate() @@ -156,14 +156,14 @@ namespace osu.Game.Screens.Select ruleset.BindTo(parentRuleset); ruleset.BindValueChanged(_ => updateCriteria()); - SortMode = config.GetBindable(OsuSetting.SongSelectSortingMode); - GroupMode = config.GetBindable(OsuSetting.SongSelectGroupingMode); + sortMode = config.GetBindable(OsuSetting.SongSelectSortingMode); + groupMode = config.GetBindable(OsuSetting.SongSelectGroupingMode); - sortTabs.Current.BindTo(SortMode); - groupTabs.Current.BindTo(GroupMode); + sortTabs.Current.BindTo(sortMode); + groupTabs.Current.BindTo(groupMode); - GroupMode.BindValueChanged(_ => updateCriteria()); - SortMode.BindValueChanged(_ => updateCriteria()); + groupMode.BindValueChanged(_ => updateCriteria()); + sortMode.BindValueChanged(_ => updateCriteria()); updateCriteria(); } From b85e62a6e2da4f861788a67da8ae64495f30038b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 27 Aug 2019 14:19:55 +0900 Subject: [PATCH 2574/5608] Fix taiko proxies being removed on rewind --- .../Drawables/DrawableTaikoHitObject.cs | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index b46738c69a..ea3ea4a9ad 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -78,10 +78,29 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public abstract bool OnPressed(TaikoAction action); public virtual bool OnReleased(TaikoAction action) => false; + public override double LifetimeStart + { + get => base.LifetimeStart; + set + { + base.LifetimeStart = value; + proxiedContent.LifetimeStart = value; + } + } + + public override double LifetimeEnd + { + get => base.LifetimeEnd; + set + { + base.LifetimeEnd = value; + proxiedContent.LifetimeEnd = value; + } + } + private class ProxiedContentContainer : Container { - public override double LifetimeStart => Parent?.LifetimeStart ?? base.LifetimeStart; - public override double LifetimeEnd => Parent?.LifetimeEnd ?? base.LifetimeEnd; + public override bool RemoveWhenNotAlive => false; } } From dba367981759de0db52b7b54bfc2046bfc15a154 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 27 Aug 2019 15:19:16 +0900 Subject: [PATCH 2575/5608] Fix DrawableSwell not proxying its content in time/correctly --- .../Objects/Drawables/DrawableSwell.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 88769bfff6..7d5b928b4f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -179,9 +179,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override double InitialLifetimeOffset => 100; + protected override void UpdateInitialTransforms() + { + base.UpdateInitialTransforms(); - protected override void UpdateInitialTransforms() => targetRing.ScaleTo(target_ring_scale, InitialLifetimeOffset * 4, Easing.OutQuint); + using (BeginAbsoluteSequence(HitObject.StartTime - 100, true)) + targetRing.ScaleTo(target_ring_scale, 400, Easing.OutQuint); + } protected override void UpdateStateTransforms(ArmedState state) { @@ -190,7 +194,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (state) { case ArmedState.Idle: - UnproxyContent(); expandingRing.FadeTo(0); break; @@ -217,9 +220,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables // Make the swell stop at the hit target X = Math.Max(0, X); - double t = Math.Min(HitObject.StartTime, Time.Current); - if (t == HitObject.StartTime) + if (Time.Current >= HitObject.StartTime - 100) ProxyContent(); + else + UnproxyContent(); } private bool? lastWasCentre; From bc7a81e733c21adb600120065e78eff7f65ac5da Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 27 Aug 2019 15:19:29 +0900 Subject: [PATCH 2576/5608] Add initial fade transform --- .../Objects/Drawables/DrawableTaikoHitObject.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index bd45b52d7b..a0a71a4c42 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -78,6 +78,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public abstract bool OnPressed(TaikoAction action); public virtual bool OnReleased(TaikoAction action) => false; + protected override void UpdateInitialTransforms() => this.FadeIn(); + private class ProxiedContentContainer : Container { public override double LifetimeStart => Parent?.LifetimeStart ?? base.LifetimeStart; From 2b22fd799dd4f16393f746aa9ea39819025ac9c0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 27 Aug 2019 15:21:54 +0900 Subject: [PATCH 2577/5608] Use constant value for offset --- .../Objects/Drawables/DrawableSwell.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 7d5b928b4f..094ad1230f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -25,6 +25,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private const float target_ring_scale = 5f; private const float inner_ring_alpha = 0.65f; + /// + /// Offset away from the start time of the swell at which the ring starts appearing. + /// + private const double ring_appear_offset = 100; + private readonly List ticks = new List(); private readonly Container bodyContainer; @@ -183,7 +188,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { base.UpdateInitialTransforms(); - using (BeginAbsoluteSequence(HitObject.StartTime - 100, true)) + using (BeginAbsoluteSequence(HitObject.StartTime - ring_appear_offset, true)) targetRing.ScaleTo(target_ring_scale, 400, Easing.OutQuint); } @@ -220,7 +225,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables // Make the swell stop at the hit target X = Math.Max(0, X); - if (Time.Current >= HitObject.StartTime - 100) + if (Time.Current >= HitObject.StartTime - ring_appear_offset) ProxyContent(); else UnproxyContent(); From 9e926d44c0b68c86dadc031940a440ae86ccbabd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 27 Aug 2019 16:09:47 +0900 Subject: [PATCH 2578/5608] Obsolete legacy UpdateState() method --- .../Visual/Gameplay/TestSceneScrollingHitObjects.cs | 8 -------- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 6 ++++++ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs index 0a9cdc6a8e..aa80819694 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs @@ -200,10 +200,6 @@ namespace osu.Game.Tests.Visual.Gameplay break; } } - - protected override void UpdateState(ArmedState state) - { - } } private class TestDrawableHitObject : DrawableHitObject @@ -216,10 +212,6 @@ namespace osu.Game.Tests.Visual.Gameplay AddInternal(new Box { Size = new Vector2(75) }); } - - protected override void UpdateState(ArmedState state) - { - } } } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index b72a55b9ed..80e70589bd 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -132,6 +132,8 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public event Action ApplyCustomUpdateState; +#pragma warning disable 618 // (legacy state management) - can be removed 20200227 + /// /// Enables automatic transform management of this hitobject. Implementation of transforms should be done in and only. Rewinding and removing previous states is done automatically. /// @@ -139,6 +141,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Going forward, this is the preferred way of implementing s. Previous functionality /// is offered as a compatibility layer until all rulesets have been migrated across. /// + [Obsolete("Use UpdateInitialTransforms()/UpdateStateTransforms() instead")] // can be removed 20200227 protected virtual bool UseTransformStateManagement => true; protected override void ClearInternal(bool disposeChildren = true) => throw new InvalidOperationException($"Should never clear a {nameof(DrawableHitObject)}"); @@ -219,10 +222,13 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Should generally not be used when is true; use instead. /// /// The new armed state. + [Obsolete("Use UpdateInitialTransforms()/UpdateStateTransforms() instead")] // can be removed 20200227 protected virtual void UpdateState(ArmedState state) { } +#pragma warning restore 618 + #endregion protected override void SkinChanged(ISkinSource skin, bool allowFallback) From 0ea10a49223ab178cd4fb520ffd7fc2ad87c1464 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 27 Aug 2019 17:18:32 +0900 Subject: [PATCH 2579/5608] Fix skin sample reading failing --- osu.Game/Skinning/LegacySkin.cs | 55 +++++++++++++++++---------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 7bffe5d321..37a3059160 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -155,16 +155,40 @@ namespace osu.Game.Skinning // Spacing value was reverse-engineered from the ratio of the rendered sprite size in the visual inspector vs the actual texture size Spacing = new Vector2(-Configuration.HitCircleOverlap * 0.89f, 0) }; - - default: - string lastPiece = componentName.Split('/').Last(); - componentName = componentName.StartsWith("Gameplay/taiko/") ? "taiko-" + lastPiece : lastPiece; - break; } return getAnimation(componentName, animatable, looping); } + public override Texture GetTexture(string componentName) + { + componentName = getFallbackName(componentName); + + float ratio = 2; + var texture = Textures.Get($"{componentName}@2x"); + + if (texture == null) + { + ratio = 1; + texture = Textures.Get(componentName); + } + + if (texture != null) + texture.ScaleAdjust = ratio; + + return texture; + } + + public override SampleChannel GetSample(string sampleName) => Samples.Get(getFallbackName(sampleName)); + + private bool hasFont(string fontName) => GetTexture($"{fontName}-0") != null; + + private string getFallbackName(string componentName) + { + string lastPiece = componentName.Split('/').Last(); + return componentName.StartsWith("Gameplay/taiko/") ? "taiko-" + lastPiece : lastPiece; + } + private Drawable getAnimation(string componentName, bool animatable, bool looping, string animationSeparator = "-") { Texture texture; @@ -200,27 +224,6 @@ namespace osu.Game.Skinning return null; } - public override Texture GetTexture(string componentName) - { - float ratio = 2; - var texture = Textures.Get($"{componentName}@2x"); - - if (texture == null) - { - ratio = 1; - texture = Textures.Get(componentName); - } - - if (texture != null) - texture.ScaleAdjust = ratio; - - return texture; - } - - public override SampleChannel GetSample(string sampleName) => Samples.Get(sampleName); - - private bool hasFont(string fontName) => GetTexture($"{fontName}-0") != null; - protected class LegacySkinResourceStore : IResourceStore where T : INamedFileInfo { From 7aeeb65ae7fe6df164155f31414997c8c64629ab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 27 Aug 2019 18:27:21 +0900 Subject: [PATCH 2580/5608] Tidy up Player's container loading logic Fixes drawable ruleset being loaded before skin sources are finished, by loading them as a separate operation (to avoid children being loaded first). --- .../SkinnableTestScene.cs | 3 +- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 1 - osu.Game/Screens/Play/Player.cs | 81 +++++++++++-------- osu.Game/Skinning/SkinProvidingContainer.cs | 2 + 4 files changed, 49 insertions(+), 38 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs b/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs index c3a64f8b54..29e5146ff1 100644 --- a/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs +++ b/osu.Game.Rulesets.Osu.Tests/SkinnableTestScene.cs @@ -45,12 +45,11 @@ namespace osu.Game.Rulesets.Osu.Tests private Drawable createProvider(Skin skin, Func creationFunction) { - var mainProvider = new SkinProvidingContainer(skin) { RelativeSizeAxes = Axes.Both }; + var mainProvider = new SkinProvidingContainer(skin); return mainProvider .WithChild(new SkinProvidingContainer(Ruleset.Value.CreateInstance().CreateLegacySkinProvider(mainProvider)) { - RelativeSizeAxes = Axes.Both, Child = creationFunction() }); } diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 178183bd22..ea7eee8bb8 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -44,7 +44,6 @@ namespace osu.Game.Rulesets.Osu.UI // Todo: Remove when hitobjects are properly pooled new SkinProvidingContainer(null) { - RelativeSizeAxes = Axes.Both, Child = HitObjectContainer, }, approachCircles = new ApproachCircleProxyContainer diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index deed17a049..b487f3e61b 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -123,30 +123,53 @@ namespace osu.Game.Screens.Play InternalChild = GameplayClockContainer = new GameplayClockContainer(working, Mods.Value, DrawableRuleset.GameplayStartTime); - SkinProvidingContainer skinProvidingContainer = new BeatmapSkinProvidingContainer(working.Skin) - { - RelativeSizeAxes = Axes.Both, - }; + addUnderlayComponents(GameplayClockContainer); + addGameplayComponents(GameplayClockContainer, working); + addOverlayComponents(GameplayClockContainer, working); - GameplayClockContainer.Children = new[] + DrawableRuleset.HasReplayLoaded.BindValueChanged(e => HUDOverlay.HoldToQuit.PauseOnFocusLost = !e.NewValue && PauseOnFocusLost, true); + + // bind clock into components that require it + DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); + + // Bind ScoreProcessor to ourselves + ScoreProcessor.AllJudged += onCompletion; + ScoreProcessor.Failed += onFail; + + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToScoreProcessor(ScoreProcessor); + } + + private void addUnderlayComponents(Container target) + { + target.Add(DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both }); + } + + private void addGameplayComponents(Container target, WorkingBeatmap working) + { + var beatmapSkinProvider = new BeatmapSkinProvidingContainer(working.Skin); + + // the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation + // full access to all skin sources. + var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider)); + + // load the skinning hierarchy first. + // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. + target.Add(new ScalingContainer(ScalingMode.Gameplay) + .WithChild(beatmapSkinProvider + .WithChild(target = rulesetSkinProvider))); + + target.AddRange(new Drawable[] + { + DrawableRuleset, + new ComboEffects(ScoreProcessor) + }); + } + + private void addOverlayComponents(Container target, WorkingBeatmap working) + { + target.AddRange(new[] { - DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both }, - new ScalingContainer(ScalingMode.Gameplay) - { - Child = skinProvidingContainer.WithChild( - // the skinProvidingContainer is used as the fallback source here to allow the ruleset-specific skin implementation - // full access to all skin sources. - new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(skinProvidingContainer)) - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - DrawableRuleset, - new ComboEffects(ScoreProcessor) - } - } - ) - }, breakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { Anchor = Anchor.Centre, @@ -205,19 +228,7 @@ namespace osu.Game.Screens.Play }, }, failAnimation = new FailAnimation(DrawableRuleset) { OnComplete = onFailComplete, } - }; - - DrawableRuleset.HasReplayLoaded.BindValueChanged(e => HUDOverlay.HoldToQuit.PauseOnFocusLost = !e.NewValue && PauseOnFocusLost, true); - - // bind clock into components that require it - DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); - - // Bind ScoreProcessor to ourselves - ScoreProcessor.AllJudged += onCompletion; - ScoreProcessor.Failed += onFail; - - foreach (var mod in Mods.Value.OfType()) - mod.ApplyToScoreProcessor(ScoreProcessor); + }); } private WorkingBeatmap loadBeatmap() diff --git a/osu.Game/Skinning/SkinProvidingContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs index a92a0ae0d1..9d6fbfdc74 100644 --- a/osu.Game/Skinning/SkinProvidingContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -32,6 +32,8 @@ namespace osu.Game.Skinning public SkinProvidingContainer(ISkin skin) { this.skin = skin; + + RelativeSizeAxes = Axes.Both; } public Drawable GetDrawableComponent(string componentName) From b59973c712a6213b103ad2cb4ecda79b267d610e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 27 Aug 2019 18:42:49 +0900 Subject: [PATCH 2581/5608] Update in line with framework changes --- osu.Game/Graphics/ScreenshotManager.cs | 2 +- osu.Game/Input/Bindings/GlobalActionContainer.cs | 2 +- osu.Game/Input/IdleTracker.cs | 2 +- osu.Game/Overlays/Volume/VolumeControlReceptor.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 524a4742c0..f532302de2 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -22,7 +22,7 @@ using SixLabors.ImageSharp; namespace osu.Game.Graphics { - public class ScreenshotManager : Container, IKeyBindingHandler, IHandleGlobalInput + public class ScreenshotManager : Container, IKeyBindingHandler, IHandleGlobalKeyboardInput { private readonly BindableBool cursorVisibility = new BindableBool(true); diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index b70072a222..bf758e21d9 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -10,7 +10,7 @@ using osu.Framework.Input.Bindings; namespace osu.Game.Input.Bindings { - public class GlobalActionContainer : DatabasedKeyBindingContainer, IHandleGlobalInput + public class GlobalActionContainer : DatabasedKeyBindingContainer, IHandleGlobalKeyboardInput { private readonly Drawable handler; diff --git a/osu.Game/Input/IdleTracker.cs b/osu.Game/Input/IdleTracker.cs index cbc446a126..39ccf9fe1c 100644 --- a/osu.Game/Input/IdleTracker.cs +++ b/osu.Game/Input/IdleTracker.cs @@ -12,7 +12,7 @@ namespace osu.Game.Input /// /// Track whether the end-user is in an idle state, based on their last interaction with the game. /// - public class IdleTracker : Component, IKeyBindingHandler, IHandleGlobalInput + public class IdleTracker : Component, IKeyBindingHandler, IHandleGlobalKeyboardInput { private readonly double timeToIdle; diff --git a/osu.Game/Overlays/Volume/VolumeControlReceptor.cs b/osu.Game/Overlays/Volume/VolumeControlReceptor.cs index 26235fa280..9cd3aac2cb 100644 --- a/osu.Game/Overlays/Volume/VolumeControlReceptor.cs +++ b/osu.Game/Overlays/Volume/VolumeControlReceptor.cs @@ -9,7 +9,7 @@ using osu.Game.Input.Bindings; namespace osu.Game.Overlays.Volume { - public class VolumeControlReceptor : Container, IScrollBindingHandler, IHandleGlobalInput + public class VolumeControlReceptor : Container, IScrollBindingHandler, IHandleGlobalKeyboardInput { public Func ActionRequested; public Func ScrollActionRequested; From f49b58c102e641ada62971df2413b8e83e1aefb6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 27 Aug 2019 15:30:41 +0300 Subject: [PATCH 2582/5608] Simplify text building --- .../Kudosu/DrawableKudosuHistoryItem.cs | 46 ++++++------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index 3cc39f0e73..4dba07713f 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -55,83 +55,67 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu switch (historyItem.Action) { case KudosuAction.VoteGive: - linkFlowContainer.AddText(@"Received "); - addKudosuPart(); + addKudosuPart(@"Received"); addMainPart(@" from obtaining votes in modding post of "); - addPostPart(); break; case KudosuAction.Give: - linkFlowContainer.AddText(@"Received "); - addKudosuPart(); + addKudosuPart(@"Received"); addMainPart($@" from {userLinkTemplate()} for a post at "); - addPostPart(); break; case KudosuAction.Reset: addMainPart($@"Kudosu reset by {userLinkTemplate()} for the post "); - addPostPart(); break; case KudosuAction.VoteReset: - linkFlowContainer.AddText(@"Lost "); - addKudosuPart(); + addKudosuPart(@"Lost"); addMainPart(@" from losing votes in modding post of "); - addPostPart(); break; case KudosuAction.DenyKudosuReset: - linkFlowContainer.AddText(@"Denied "); - addKudosuPart(); + addKudosuPart(@"Denied"); addMainPart(@" from modding post "); - addPostPart(); break; case KudosuAction.Revoke: addMainPart($@"Denied kudosu by {userLinkTemplate()} for the post "); - addPostPart(); break; case KudosuAction.AllowKudosuGive: - linkFlowContainer.AddText(@"Received "); - addKudosuPart(); + addKudosuPart(@"Received"); addMainPart(@" from kudosu deny repeal of modding post "); - addPostPart(); break; case KudosuAction.DeleteReset: - linkFlowContainer.AddText(@"Lost "); - addKudosuPart(); + addKudosuPart(@"Lost"); addMainPart(@" from modding post deletion of "); - addPostPart(); break; case KudosuAction.RestoreGive: - linkFlowContainer.AddText(@"Received "); - addKudosuPart(); + addKudosuPart(@"Received"); addMainPart(@" from modding post restoration of "); - addPostPart(); break; case KudosuAction.RecalculateGive: - linkFlowContainer.AddText(@"Received "); - addKudosuPart(); + addKudosuPart(@"Received"); addMainPart(@" from votes recalculation in modding post of "); - addPostPart(); break; case KudosuAction.RecalculateReset: - linkFlowContainer.AddText(@"Lost "); - addKudosuPart(); + addKudosuPart(@"Lost"); addMainPart(@" from votes recalculation in modding post of "); - addPostPart(); break; } + + addPostPart(); } - private void addKudosuPart() + private void addKudosuPart(string prefix) { - linkFlowContainer.AddText($@"{historyItem.Amount} kudosu", t => + linkFlowContainer.AddText(prefix); + + linkFlowContainer.AddText($@" {historyItem.Amount} kudosu", t => { t.Font = t.Font.With(italics: true); t.Colour = colours.Blue; From ed827d514f42d2d774f9b592dfee85c962036b94 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 27 Aug 2019 15:36:08 +0300 Subject: [PATCH 2583/5608] Add comments --- osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs index d02f71c339..19ce11aa13 100644 --- a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs +++ b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs @@ -15,6 +15,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("amount")] private int amount { + //We can receive negative values. However "action" is enough to build needed items set => Amount = Math.Abs(value); } @@ -49,6 +50,7 @@ namespace osu.Game.Online.API.Requests.Responses { set { + //We will receive something like "foo.bar" or just "foo" string parsed = value.Contains(".") ? value.Split('.')[0].Pascalize() + value.Split('.')[1].Pascalize() : value.Pascalize(); Action = (KudosuAction)Enum.Parse(typeof(KudosuAction), parsed); From 22ee7db805c1be3876c6d625d6107e98d4425cbf Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 27 Aug 2019 15:47:37 +0300 Subject: [PATCH 2584/5608] Refactor PaginatedContainer to avoid code duplication --- .../Beatmaps/PaginatedBeatmapContainer.cs | 48 +++--------- .../PaginatedMostPlayedBeatmapContainer.cs | 41 ++-------- .../Profile/Sections/PaginatedContainer.cs | 76 +++++++++++++++---- .../Sections/Ranks/PaginatedScoreContainer.cs | 65 +++++----------- .../PaginatedRecentActivityContainer.cs | 39 ++-------- 5 files changed, 107 insertions(+), 162 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 8a6b52b7ee..d0ba3e6ba5 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -1,21 +1,22 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; +using System.Collections.Generic; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Direct; using osu.Game.Users; using osuTK; namespace osu.Game.Overlays.Profile.Sections.Beatmaps { - public class PaginatedBeatmapContainer : PaginatedContainer + public class PaginatedBeatmapContainer : PaginatedContainer { private const float panel_padding = 10f; private readonly BeatmapSetType type; - private GetUserBeatmapsRequest request; public PaginatedBeatmapContainer(BeatmapSetType type, Bindable user, string header, string missing = "None... yet.") : base(user, header, missing) @@ -27,40 +28,13 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps ItemsContainer.Spacing = new Vector2(panel_padding); } - protected override void ShowMore() + protected override APIRequest> CreateRequest() => + new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); + + protected override Drawable CreateDrawableItem(APIBeatmapSet item) => new DirectGridPanel(item.ToBeatmapSet(Rulesets)) { - request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); - request.Success += sets => Schedule(() => - { - MoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0); - MoreButton.IsLoading = false; - - if (!sets.Any() && VisiblePages == 1) - { - MissingText.Show(); - return; - } - - foreach (var s in sets) - { - if (!s.OnlineBeatmapSetID.HasValue) - continue; - - ItemsContainer.Add(new DirectGridPanel(s.ToBeatmapSet(Rulesets)) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - }); - } - }); - - Api.Queue(request); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - request?.Cancel(); - } + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }; } } diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index 23072f8d90..10aa31225f 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -1,19 +1,19 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; +using System.Collections.Generic; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Users; namespace osu.Game.Overlays.Profile.Sections.Historical { - public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer + public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer { - private GetUserMostPlayedBeatmapsRequest request; - public PaginatedMostPlayedBeatmapContainer(Bindable user) : base(user, "Most Played Beatmaps", "No records. :(") { @@ -22,35 +22,10 @@ namespace osu.Game.Overlays.Profile.Sections.Historical ItemsContainer.Direction = FillDirection.Vertical; } - protected override void ShowMore() - { - request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++, ItemsPerPage); - request.Success += beatmaps => Schedule(() => - { - MoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0); - MoreButton.IsLoading = false; + protected override APIRequest> CreateRequest() => + new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++, ItemsPerPage); - if (!beatmaps.Any() && VisiblePages == 1) - { - MissingText.Show(); - return; - } - - MissingText.Hide(); - - foreach (var beatmap in beatmaps) - { - ItemsContainer.Add(new DrawableMostPlayedBeatmap(beatmap.GetBeatmapInfo(Rulesets), beatmap.PlayCount)); - } - }); - - Api.Queue(request); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - request?.Cancel(); - } + protected override Drawable CreateDrawableItem(APIUserMostPlayedBeatmap item) => + new DrawableMostPlayedBeatmap(item.GetBeatmapInfo(Rulesets), item.PlayCount); } } diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index b459afcb49..75601041e8 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -11,22 +11,27 @@ using osu.Game.Graphics.Sprites; using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Users; +using System.Collections.Generic; +using System.Linq; +using System.Threading; namespace osu.Game.Overlays.Profile.Sections { - public abstract class PaginatedContainer : FillFlowContainer + public abstract class PaginatedContainer : FillFlowContainer { - protected readonly FillFlowContainer ItemsContainer; - protected readonly ShowMoreButton MoreButton; - protected readonly OsuSpriteText MissingText; + private readonly ShowMoreButton moreButton; + private readonly OsuSpriteText missingText; + private APIRequest> retrievalRequest; + private CancellationTokenSource loadCancellation; + + [Resolved] + private IAPIProvider api { get; set; } protected int VisiblePages; protected int ItemsPerPage; protected readonly Bindable User = new Bindable(); - - protected IAPIProvider Api; - protected APIRequest RetrievalRequest; + protected readonly FillFlowContainer ItemsContainer; protected RulesetStore Rulesets; protected PaginatedContainer(Bindable user, string header, string missing) @@ -51,15 +56,15 @@ namespace osu.Game.Overlays.Profile.Sections RelativeSizeAxes = Axes.X, Spacing = new Vector2(0, 2), }, - MoreButton = new ShowMoreButton + moreButton = new ShowMoreButton { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Alpha = 0, Margin = new MarginPadding { Top = 10 }, - Action = ShowMore, + Action = showMore, }, - MissingText = new OsuSpriteText + missingText = new OsuSpriteText { Font = OsuFont.GetFont(size: 15), Text = missing, @@ -69,9 +74,8 @@ namespace osu.Game.Overlays.Profile.Sections } [BackgroundDependencyLoader] - private void load(IAPIProvider api, RulesetStore rulesets) + private void load(RulesetStore rulesets) { - Api = api; Rulesets = rulesets; User.ValueChanged += onUserChanged; @@ -80,13 +84,57 @@ namespace osu.Game.Overlays.Profile.Sections private void onUserChanged(ValueChangedEvent e) { + loadCancellation?.Cancel(); + retrievalRequest?.Cancel(); + VisiblePages = 0; ItemsContainer.Clear(); if (e.NewValue != null) - ShowMore(); + showMore(); } - protected abstract void ShowMore(); + private void showMore() + { + loadCancellation = new CancellationTokenSource(); + + retrievalRequest = CreateRequest(); + retrievalRequest.Success += UpdateItems; + + api.Queue(retrievalRequest); + } + + protected virtual void UpdateItems(List items) + { + Schedule(() => + { + if (!items.Any() && VisiblePages == 1) + { + moreButton.Hide(); + moreButton.IsLoading = false; + missingText.Show(); + return; + } + + LoadComponentsAsync(items.Select(CreateDrawableItem), drawables => + { + missingText.Hide(); + moreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0); + moreButton.IsLoading = false; + + ItemsContainer.AddRange(drawables); + }, loadCancellation.Token); + }); + } + + protected abstract APIRequest> CreateRequest(); + + protected abstract Drawable CreateDrawableItem(T item); + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + retrievalRequest?.Cancel(); + } } } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 4a9ac6e5c7..96291f5a32 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -5,18 +5,18 @@ using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests; using osu.Game.Users; using System; -using System.Collections.Generic; -using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Online.API.Requests.Responses; +using System.Collections.Generic; +using osu.Game.Online.API; namespace osu.Game.Overlays.Profile.Sections.Ranks { - public class PaginatedScoreContainer : PaginatedContainer + public class PaginatedScoreContainer : PaginatedContainer { private readonly bool includeWeight; private readonly ScoreType type; - private GetUserScoresRequest request; public PaginatedScoreContainer(ScoreType type, Bindable user, string header, string missing, bool includeWeight = false) : base(user, header, missing) @@ -29,52 +29,27 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks ItemsContainer.Direction = FillDirection.Vertical; } - protected override void ShowMore() + protected override void UpdateItems(List items) { - request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); - request.Success += scores => Schedule(() => - { - foreach (var s in scores) - s.Ruleset = Rulesets.GetRuleset(s.RulesetID); + foreach (var item in items) + item.Ruleset = Rulesets.GetRuleset(item.RulesetID); - if (!scores.Any() && VisiblePages == 1) - { - MoreButton.Hide(); - MoreButton.IsLoading = false; - MissingText.Show(); - return; - } - - IEnumerable drawableScores; - - switch (type) - { - default: - drawableScores = scores.Select(score => new DrawablePerformanceScore(score, includeWeight ? Math.Pow(0.95, ItemsContainer.Count) : (double?)null)); - break; - - case ScoreType.Recent: - drawableScores = scores.Select(score => new DrawableTotalScore(score)); - break; - } - - LoadComponentsAsync(drawableScores, s => - { - MissingText.Hide(); - MoreButton.FadeTo(scores.Count == ItemsPerPage ? 1 : 0); - MoreButton.IsLoading = false; - - ItemsContainer.AddRange(s); - }); - }); - - Api.Queue(request); + base.UpdateItems(items); } - protected override void Dispose(bool isDisposing) + protected override APIRequest> CreateRequest() => + new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); + + protected override Drawable CreateDrawableItem(APILegacyScoreInfo item) { - base.Dispose(isDisposing); - request?.Cancel(); + switch (type) + { + default: + return new DrawablePerformanceScore(item, includeWeight ? Math.Pow(0.95, ItemsContainer.Count) : (double?)null); + + case ScoreType.Recent: + return new DrawableTotalScore(item); + } } } } diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index f2a778a874..8cc762e3a7 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -4,51 +4,24 @@ using osu.Framework.Graphics; using osu.Game.Online.API.Requests; using osu.Game.Users; -using System.Linq; using osu.Framework.Bindables; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.API; +using System.Collections.Generic; namespace osu.Game.Overlays.Profile.Sections.Recent { - public class PaginatedRecentActivityContainer : PaginatedContainer + public class PaginatedRecentActivityContainer : PaginatedContainer { - private GetUserRecentActivitiesRequest request; - public PaginatedRecentActivityContainer(Bindable user, string header, string missing) : base(user, header, missing) { ItemsPerPage = 5; } - protected override void ShowMore() - { - request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++, ItemsPerPage); - request.Success += activities => Schedule(() => - { - MoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0); - MoreButton.IsLoading = false; + protected override APIRequest> CreateRequest() => + new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++, ItemsPerPage); - if (!activities.Any() && VisiblePages == 1) - { - MissingText.Show(); - return; - } - - MissingText.Hide(); - - foreach (APIRecentActivity activity in activities) - { - ItemsContainer.Add(new DrawableRecentActivity(activity)); - } - }); - - Api.Queue(request); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - request?.Cancel(); - } + protected override Drawable CreateDrawableItem(APIRecentActivity item) => new DrawableRecentActivity(item); } } From 9a383eee1a802f85819504e31da54852816df45d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 27 Aug 2019 15:58:57 +0300 Subject: [PATCH 2585/5608] Add AllowCreate function --- .../Sections/Beatmaps/PaginatedBeatmapContainer.cs | 2 ++ osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index d0ba3e6ba5..0b424057ae 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -31,6 +31,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps protected override APIRequest> CreateRequest() => new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); + protected override bool AllowCreate(APIBeatmapSet item) => item.OnlineBeatmapSetID.HasValue; + protected override Drawable CreateDrawableItem(APIBeatmapSet item) => new DirectGridPanel(item.ToBeatmapSet(Rulesets)) { Anchor = Anchor.TopCentre, diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 75601041e8..adc1107b32 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -116,7 +116,7 @@ namespace osu.Game.Overlays.Profile.Sections return; } - LoadComponentsAsync(items.Select(CreateDrawableItem), drawables => + LoadComponentsAsync(items.Where(item => AllowCreate(item)).Select(CreateDrawableItem), drawables => { missingText.Hide(); moreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0); @@ -127,6 +127,13 @@ namespace osu.Game.Overlays.Profile.Sections }); } + /// + /// Used to check whether the item is suitable for drawable creation. + /// + /// An item to check + /// + protected virtual bool AllowCreate(T item) => true; + protected abstract APIRequest> CreateRequest(); protected abstract Drawable CreateDrawableItem(T item); From 5fd43d42f441c54787ba132012297f8e6de9e956 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 27 Aug 2019 16:09:37 +0300 Subject: [PATCH 2586/5608] CI fixes --- osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs | 2 +- .../Profile/Sections/Ranks/PaginatedScoreContainer.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index adc1107b32..a3a22d6248 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -116,7 +116,7 @@ namespace osu.Game.Overlays.Profile.Sections return; } - LoadComponentsAsync(items.Where(item => AllowCreate(item)).Select(CreateDrawableItem), drawables => + LoadComponentsAsync(items.Where(AllowCreate).Select(CreateDrawableItem), drawables => { missingText.Hide(); moreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0); diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 96291f5a32..5f023cfa4b 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -45,10 +45,10 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks switch (type) { default: - return new DrawablePerformanceScore(item, includeWeight ? Math.Pow(0.95, ItemsContainer.Count) : (double?)null); + return new DrawablePerformanceScore(item, includeWeight ? Math.Pow(0.95, ItemsContainer.Count) : (double?)null); case ScoreType.Recent: - return new DrawableTotalScore(item); + return new DrawableTotalScore(item); } } } From 4ef991b97309868a507a63097caa9de1611da9be Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 27 Aug 2019 19:42:17 +0300 Subject: [PATCH 2587/5608] Loop over lookup names on default-samples retrieval --- osu.Game/Skinning/SkinnableSound.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 23093d9bd9..0c20241c4c 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -45,10 +45,9 @@ namespace osu.Game.Skinning var ch = skin.GetSample(s); if (ch == null && allowFallback) - if (s is HitSampleInfo hsi) - ch = audio.Samples.Get(string.IsNullOrEmpty(hsi.Namespace) - ? $"Gameplay/{hsi.Namespace}/{hsi.Bank}-{hsi.Name}" - : $"Gameplay/{hsi.Bank}-{hsi.Name}"); + foreach (var lookup in s.LookupNames) + if ((ch = audio.Samples.Get($"Gameplay/{lookup}")) != null) + break; if (ch != null) ch.Volume.Value = s.Volume / 100.0; From 4add1727b7458b9e36584fafdb753793c41ee447 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 03:25:57 +0900 Subject: [PATCH 2588/5608] Fix hitsounds not updating immediately after switching skins --- osu.Game/Skinning/SkinnableSound.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 8e2b5cec98..aa1c596a51 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -37,7 +37,7 @@ namespace osu.Game.Skinning public void Play() => channels?.ForEach(c => c.Play()); - public override bool IsPresent => false; // We don't need to receive updates. + public override bool IsPresent => Scheduler.HasPendingTasks; protected override void SkinChanged(ISkinSource skin, bool allowFallback) { From 11df8c5576478f920f3c09e3b8c884623a0cb836 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 28 Aug 2019 01:02:26 +0300 Subject: [PATCH 2589/5608] Remove a lot of loading animation calls --- osu.Game/Overlays/SocialOverlay.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index e2179361b1..a467ae6dfa 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -122,16 +122,12 @@ namespace osu.Game.Overlays API.Queue(getUsersRequest = userRequest); break; } - - loading.Show(); } private void recreatePanels(PanelDisplayStyle displayStyle) { clearPanels(); - loading.Show(); - if (Users == null) { loading.Hide(); @@ -178,8 +174,6 @@ namespace osu.Game.Overlays private void updateUsers(IEnumerable newUsers) { - loading.Show(); - var sortDirection = Filter.DisplayStyleControl.Dropdown.Current.Value; IEnumerable sortedUsers = newUsers; @@ -218,6 +212,8 @@ namespace osu.Game.Overlays private void clearPanels() { + loading.Show(); + if (panels != null) { panels.Expire(); From 9b1e8cf48b701aad40f4a3b34a4d14205bc5bb77 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 28 Aug 2019 01:03:51 +0300 Subject: [PATCH 2590/5608] Use CancelDelayedTasks instead of private ScheduledDelegate --- osu.Game/Overlays/SocialOverlay.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index a467ae6dfa..5ed6a9a703 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -77,12 +77,12 @@ namespace osu.Game.Overlays currentQuery.BindTo(Filter.Search.Current); currentQuery.ValueChanged += query => { - queryChangedDebounce?.Cancel(); + Scheduler.CancelDelayedTasks(); if (string.IsNullOrEmpty(query.NewValue)) queueUpdate(); else - queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); + Scheduler.AddDelayed(updateSearch, 500); }; } @@ -90,13 +90,11 @@ namespace osu.Game.Overlays private readonly Bindable currentQuery = new Bindable(); - private ScheduledDelegate queryChangedDebounce; - private void queueUpdate() => Scheduler.AddOnce(updateSearch); private void updateSearch() { - queryChangedDebounce?.Cancel(); + Scheduler.CancelDelayedTasks(); if (!IsLoaded) return; From 2d7024ffd92656a9d3646abc0e87111709e6bfe4 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 28 Aug 2019 01:14:35 +0300 Subject: [PATCH 2591/5608] Use CancellationTokenSource to avoid unwanted panels creation --- osu.Game/Overlays/SocialOverlay.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 5ed6a9a703..ee3adf65b9 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -17,6 +17,7 @@ using osu.Game.Overlays.Social; using osu.Game.Users; using osu.Framework.Threading; using System; +using System.Threading; namespace osu.Game.Overlays { @@ -92,6 +93,8 @@ namespace osu.Game.Overlays private void queueUpdate() => Scheduler.AddOnce(updateSearch); + private CancellationTokenSource loadCancellation; + private void updateSearch() { Scheduler.CancelDelayedTasks(); @@ -132,6 +135,8 @@ namespace osu.Game.Overlays return; } + loadCancellation = new CancellationTokenSource(); + var newPanels = new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -167,7 +172,7 @@ namespace osu.Game.Overlays { loading.Hide(); ScrollFlow.Add(panels = newPanels); - }); + }, loadCancellation.Token); } private void updateUsers(IEnumerable newUsers) @@ -212,6 +217,8 @@ namespace osu.Game.Overlays { loading.Show(); + loadCancellation?.Cancel(); + if (panels != null) { panels.Expire(); From 6aef05f5d877dfd29b2035cdcadb5f36aa706e3a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 28 Aug 2019 01:16:55 +0300 Subject: [PATCH 2592/5608] Remove useless function --- osu.Game/Overlays/SocialOverlay.cs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index ee3adf65b9..97e1c2b5a4 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -73,7 +73,7 @@ namespace osu.Game.Overlays Filter.Tabs.Current.ValueChanged += _ => queueUpdate(); Filter.DisplayStyleControl.DisplayStyle.ValueChanged += style => recreatePanels(style.NewValue); - Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => onDropdownChanged(); + Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => updateUsers(Users); currentQuery.BindTo(Filter.Search.Current); currentQuery.ValueChanged += query => @@ -202,17 +202,6 @@ namespace osu.Game.Overlays private IEnumerable sortBy(IEnumerable users, Func condition, SortDirection sortDirection) => sortDirection == SortDirection.Ascending ? users.OrderBy(condition) : users.OrderByDescending(condition); - private void onDropdownChanged() - { - if (Users == null) - { - queueUpdate(); - return; - } - - updateUsers(Users); - } - private void clearPanels() { loading.Show(); From b6b4173a8481987f3afc73f90d3cc712e099f000 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 28 Aug 2019 01:27:16 +0300 Subject: [PATCH 2593/5608] Remove unused using --- osu.Game/Overlays/SocialOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 97e1c2b5a4..bf306f9569 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -15,7 +15,6 @@ using osu.Game.Online.API.Requests; using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.Social; using osu.Game.Users; -using osu.Framework.Threading; using System; using System.Threading; From 7cc92e2fad4cdfbeefd12d718d73e3cf0ad27af8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Aug 2019 13:20:28 +0900 Subject: [PATCH 2594/5608] Make taiko proxy containers use LifetimeManagementContainer --- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index e62dc45cab..a10f70a344 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -44,9 +44,8 @@ namespace osu.Game.Rulesets.Taiko.UI private readonly JudgementContainer judgementContainer; internal readonly HitTarget HitTarget; - private readonly Container topLevelHitContainer; - - private readonly Container barlineContainer; + private readonly ProxyContainer topLevelHitContainer; + private readonly ProxyContainer barlineContainer; private readonly Container overlayBackgroundContainer; private readonly Container backgroundContainer; @@ -108,7 +107,7 @@ namespace osu.Game.Rulesets.Taiko.UI } } }, - barlineContainer = new Container + barlineContainer = new ProxyContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Left = HIT_TARGET_OFFSET } @@ -183,7 +182,7 @@ namespace osu.Game.Rulesets.Taiko.UI } } }, - topLevelHitContainer = new Container + topLevelHitContainer = new ProxyContainer { Name = "Top level hit objects", RelativeSizeAxes = Axes.Both, @@ -256,5 +255,15 @@ namespace osu.Game.Rulesets.Taiko.UI break; } } + + private class ProxyContainer : LifetimeManagementContainer + { + public new MarginPadding Padding + { + set => base.Padding = value; + } + + public void Add(Drawable proxy) => AddInternal(proxy); + } } } From f18b5a3c02ff44dd78db54fc9eae2f2c4979fac0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 13:27:44 +0900 Subject: [PATCH 2595/5608] Remove "AllowCreate" function by instead handling nulls --- .../Sections/Beatmaps/PaginatedBeatmapContainer.cs | 14 +++++++------- .../Profile/Sections/PaginatedContainer.cs | 9 +-------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 0b424057ae..fe6822440f 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -31,12 +31,12 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps protected override APIRequest> CreateRequest() => new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); - protected override bool AllowCreate(APIBeatmapSet item) => item.OnlineBeatmapSetID.HasValue; - - protected override Drawable CreateDrawableItem(APIBeatmapSet item) => new DirectGridPanel(item.ToBeatmapSet(Rulesets)) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - }; + protected override Drawable CreateDrawableItem(APIBeatmapSet item) => !item.OnlineBeatmapSetID.HasValue + ? null + : new DirectGridPanel(item.ToBeatmapSet(Rulesets)) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }; } } diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index a3a22d6248..4a10946ec2 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -116,7 +116,7 @@ namespace osu.Game.Overlays.Profile.Sections return; } - LoadComponentsAsync(items.Where(AllowCreate).Select(CreateDrawableItem), drawables => + LoadComponentsAsync(items.Select(CreateDrawableItem).Where(d => d != null), drawables => { missingText.Hide(); moreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0); @@ -127,13 +127,6 @@ namespace osu.Game.Overlays.Profile.Sections }); } - /// - /// Used to check whether the item is suitable for drawable creation. - /// - /// An item to check - /// - protected virtual bool AllowCreate(T item) => true; - protected abstract APIRequest> CreateRequest(); protected abstract Drawable CreateDrawableItem(T item); From 27633c8dbd28b50a9f7796617d426c563d4dd5e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 13:28:21 +0900 Subject: [PATCH 2596/5608] T -> TModel --- .../Overlays/Profile/Sections/PaginatedContainer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 4a10946ec2..b91f22d1e7 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -17,11 +17,11 @@ using System.Threading; namespace osu.Game.Overlays.Profile.Sections { - public abstract class PaginatedContainer : FillFlowContainer + public abstract class PaginatedContainer : FillFlowContainer { private readonly ShowMoreButton moreButton; private readonly OsuSpriteText missingText; - private APIRequest> retrievalRequest; + private APIRequest> retrievalRequest; private CancellationTokenSource loadCancellation; [Resolved] @@ -104,7 +104,7 @@ namespace osu.Game.Overlays.Profile.Sections api.Queue(retrievalRequest); } - protected virtual void UpdateItems(List items) + protected virtual void UpdateItems(List items) { Schedule(() => { @@ -127,9 +127,9 @@ namespace osu.Game.Overlays.Profile.Sections }); } - protected abstract APIRequest> CreateRequest(); + protected abstract APIRequest> CreateRequest(); - protected abstract Drawable CreateDrawableItem(T item); + protected abstract Drawable CreateDrawableItem(TModel item); protected override void Dispose(bool isDisposing) { From 3942c83c187034750131d527e5b839106e973160 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 13:28:57 +0900 Subject: [PATCH 2597/5608] Simplify schedule layout --- .../Profile/Sections/PaginatedContainer.cs | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index b91f22d1e7..e26f7f3601 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -104,28 +104,25 @@ namespace osu.Game.Overlays.Profile.Sections api.Queue(retrievalRequest); } - protected virtual void UpdateItems(List items) + protected virtual void UpdateItems(List items) => Schedule(() => { - Schedule(() => + if (!items.Any() && VisiblePages == 1) { - if (!items.Any() && VisiblePages == 1) - { - moreButton.Hide(); - moreButton.IsLoading = false; - missingText.Show(); - return; - } + moreButton.Hide(); + moreButton.IsLoading = false; + missingText.Show(); + return; + } - LoadComponentsAsync(items.Select(CreateDrawableItem).Where(d => d != null), drawables => - { - missingText.Hide(); - moreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0); - moreButton.IsLoading = false; + LoadComponentsAsync(items.Select(CreateDrawableItem).Where(d => d != null), drawables => + { + missingText.Hide(); + moreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0); + moreButton.IsLoading = false; - ItemsContainer.AddRange(drawables); - }, loadCancellation.Token); - }); - } + ItemsContainer.AddRange(drawables); + }, loadCancellation.Token); + }); protected abstract APIRequest> CreateRequest(); From bef44b8e58581a6e5d51871c8ef5acd13aca2502 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 13:31:12 +0900 Subject: [PATCH 2598/5608] item -> model --- .../Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs | 4 ++-- .../Historical/PaginatedMostPlayedBeatmapContainer.cs | 4 ++-- osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs | 2 +- .../Profile/Sections/Ranks/PaginatedScoreContainer.cs | 6 +++--- .../Sections/Recent/PaginatedRecentActivityContainer.cs | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index fe6822440f..919f8a2fa0 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -31,9 +31,9 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps protected override APIRequest> CreateRequest() => new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); - protected override Drawable CreateDrawableItem(APIBeatmapSet item) => !item.OnlineBeatmapSetID.HasValue + protected override Drawable CreateDrawableItem(APIBeatmapSet model) => !model.OnlineBeatmapSetID.HasValue ? null - : new DirectGridPanel(item.ToBeatmapSet(Rulesets)) + : new DirectGridPanel(model.ToBeatmapSet(Rulesets)) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index 10aa31225f..6e6d6272c7 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical protected override APIRequest> CreateRequest() => new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++, ItemsPerPage); - protected override Drawable CreateDrawableItem(APIUserMostPlayedBeatmap item) => - new DrawableMostPlayedBeatmap(item.GetBeatmapInfo(Rulesets), item.PlayCount); + protected override Drawable CreateDrawableItem(APIUserMostPlayedBeatmap model) => + new DrawableMostPlayedBeatmap(model.GetBeatmapInfo(Rulesets), model.PlayCount); } } diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index e26f7f3601..bb221bd43a 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -126,7 +126,7 @@ namespace osu.Game.Overlays.Profile.Sections protected abstract APIRequest> CreateRequest(); - protected abstract Drawable CreateDrawableItem(TModel item); + protected abstract Drawable CreateDrawableItem(TModel model); protected override void Dispose(bool isDisposing) { diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 5f023cfa4b..853b9db0a7 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -40,15 +40,15 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks protected override APIRequest> CreateRequest() => new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); - protected override Drawable CreateDrawableItem(APILegacyScoreInfo item) + protected override Drawable CreateDrawableItem(APILegacyScoreInfo model) { switch (type) { default: - return new DrawablePerformanceScore(item, includeWeight ? Math.Pow(0.95, ItemsContainer.Count) : (double?)null); + return new DrawablePerformanceScore(model, includeWeight ? Math.Pow(0.95, ItemsContainer.Count) : (double?)null); case ScoreType.Recent: - return new DrawableTotalScore(item); + return new DrawableTotalScore(model); } } } diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index 8cc762e3a7..3f9d4dc93e 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -22,6 +22,6 @@ namespace osu.Game.Overlays.Profile.Sections.Recent protected override APIRequest> CreateRequest() => new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++, ItemsPerPage); - protected override Drawable CreateDrawableItem(APIRecentActivity item) => new DrawableRecentActivity(item); + protected override Drawable CreateDrawableItem(APIRecentActivity model) => new DrawableRecentActivity(model); } } From 70da25cfca5664965951c27bbd41600cb13898eb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 17:03:54 +0900 Subject: [PATCH 2599/5608] 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 215a9a8090..0f6e32d664 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -61,6 +61,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 4fe9119cef..d791909372 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 82301549d7..9fc472bf40 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From bb22c2d6e48b8039b967bd7c7320f84e382af794 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 17:29:18 +0900 Subject: [PATCH 2600/5608] Tidy up text construction --- .../Kudosu/DrawableKudosuHistoryItem.cs | 116 ++++++++++-------- 1 file changed, 66 insertions(+), 50 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index 4dba07713f..fb7d597012 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -50,85 +50,101 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu { date.Colour = colours.GreySeafoamLighter; - string userLinkTemplate() => $"[{historyItem.Giver?.Url} {historyItem.Giver?.Username}]"; + string prefix = getPrefix(historyItem); + var formattedSource = MessageFormatter.FormatText(getSource(historyItem)); + + if (!string.IsNullOrEmpty(prefix)) + { + linkFlowContainer.AddText(prefix); + linkFlowContainer.AddText($@" {historyItem.Amount} kudosu", t => + { + t.Font = t.Font.With(italics: true); + t.Colour = colours.Blue; + }); + } + + linkFlowContainer.AddLinks(formattedSource.Text + " ", formattedSource.Links); + linkFlowContainer.AddLink(historyItem.Post.Title, historyItem.Post.Url); + } + + private string getSource(APIKudosuHistory historyItem) + { + string userLink() => $"[{historyItem.Giver?.Url} {historyItem.Giver?.Username}]"; switch (historyItem.Action) { case KudosuAction.VoteGive: - addKudosuPart(@"Received"); - addMainPart(@" from obtaining votes in modding post of "); - break; + return @" from obtaining votes in modding post of"; case KudosuAction.Give: - addKudosuPart(@"Received"); - addMainPart($@" from {userLinkTemplate()} for a post at "); - break; + return $@" from {userLink()} for a post at"; case KudosuAction.Reset: - addMainPart($@"Kudosu reset by {userLinkTemplate()} for the post "); - break; + return $@"Kudosu reset by {userLink()} for the post"; case KudosuAction.VoteReset: - addKudosuPart(@"Lost"); - addMainPart(@" from losing votes in modding post of "); - break; + return @" from losing votes in modding post of"; case KudosuAction.DenyKudosuReset: - addKudosuPart(@"Denied"); - addMainPart(@" from modding post "); - break; + return @" from modding post"; case KudosuAction.Revoke: - addMainPart($@"Denied kudosu by {userLinkTemplate()} for the post "); - break; + return $@"Denied kudosu by {userLink()} for the post"; case KudosuAction.AllowKudosuGive: - addKudosuPart(@"Received"); - addMainPart(@" from kudosu deny repeal of modding post "); - break; + return @" from kudosu deny repeal of modding post"; case KudosuAction.DeleteReset: - addKudosuPart(@"Lost"); - addMainPart(@" from modding post deletion of "); - break; + return @" from modding post deletion of"; case KudosuAction.RestoreGive: - addKudosuPart(@"Received"); - addMainPart(@" from modding post restoration of "); - break; + return @" from modding post restoration of"; case KudosuAction.RecalculateGive: - addKudosuPart(@"Received"); - addMainPart(@" from votes recalculation in modding post of "); - break; + return @" from votes recalculation in modding post of"; case KudosuAction.RecalculateReset: - addKudosuPart(@"Lost"); - addMainPart(@" from votes recalculation in modding post of "); - break; + return @" from votes recalculation in modding post of"; + + default: + return @" from unknown event "; } - - addPostPart(); } - private void addKudosuPart(string prefix) + private string getPrefix(APIKudosuHistory historyItem) { - linkFlowContainer.AddText(prefix); - - linkFlowContainer.AddText($@" {historyItem.Amount} kudosu", t => + switch (historyItem.Action) { - t.Font = t.Font.With(italics: true); - t.Colour = colours.Blue; - }); + case KudosuAction.VoteGive: + return @"Received"; + + case KudosuAction.Give: + return @"Received"; + + case KudosuAction.VoteReset: + return @"Lost"; + + case KudosuAction.DenyKudosuReset: + return @"Denied"; + + case KudosuAction.AllowKudosuGive: + return @"Received"; + + case KudosuAction.DeleteReset: + return @"Lost"; + + case KudosuAction.RestoreGive: + return @"Received"; + + case KudosuAction.RecalculateGive: + return @"Received"; + + case KudosuAction.RecalculateReset: + return @"Lost"; + + default: + return null; + } } - - private void addMainPart(string text) - { - var formatted = MessageFormatter.FormatText(text); - - linkFlowContainer.AddLinks(formatted.Text, formatted.Links); - } - - private void addPostPart() => linkFlowContainer.AddLink(historyItem.Post.Title, historyItem.Post.Url); } } From 9752dbf9505ba614d6609c42fa874aeb73aad026 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 18:10:58 +0900 Subject: [PATCH 2601/5608] Fix osu! approach circles fading in too late --- .../Objects/Drawables/DrawableHitCircle.cs | 6 +++++- .../Objects/Drawables/DrawableOsuHitObject.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 7 +++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index ca124e9214..0af278f6a4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -29,6 +29,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly HitArea hitArea; + private readonly SkinnableDrawable mainContent; + public DrawableHitCircle(HitCircle h) : base(h) { @@ -56,7 +58,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return true; }, }, - new SkinnableDrawable("Play/osu/hitcircle", _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)), + mainContent = new SkinnableDrawable("Play/osu/hitcircle", _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)), ApproachCircle = new ApproachCircle { Alpha = 0, @@ -108,6 +110,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.UpdateInitialTransforms(); + mainContent.FadeInFromZero(HitObject.TimeFadeIn); + ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadeIn * 2, HitObject.TimePreempt)); ApproachCircle.ScaleTo(1f, HitObject.TimePreempt); ApproachCircle.Expire(true); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index a89fb8b682..17efefa959 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; - protected override void UpdateInitialTransforms() => this.FadeIn(HitObject.TimeFadeIn); + protected override void UpdateInitialTransforms() => this.FadeInFromZero(); private OsuInputManager osuActionInputManager; internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index a0626707af..1749ea1f60 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -93,6 +93,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } + protected override void UpdateInitialTransforms() + { + base.UpdateInitialTransforms(); + + Body.FadeInFromZero(HitObject.TimeFadeIn); + } + [BackgroundDependencyLoader] private void load() { From 9a98f39f06623a181bf4298e8ffb1c8f80e238a0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 18:12:47 +0900 Subject: [PATCH 2602/5608] Share logic with other rulesets (and make default) --- .../Objects/Drawable/DrawableCatchHitObject.cs | 2 +- .../Objects/Drawables/DrawableManiaHitObject.cs | 2 -- .../Objects/Drawables/DrawableOsuHitObject.cs | 2 -- .../Objects/Drawables/DrawableTaikoHitObject.cs | 2 -- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 4 ++++ 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index f4218061d4..00734810b3 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; - protected override void UpdateInitialTransforms() => this.FadeIn(200); + protected override void UpdateInitialTransforms() => this.FadeInFromZero(200); protected override void UpdateStateTransforms(ArmedState state) { diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index ce1484d460..e5b114ca81 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -46,8 +46,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Anchor = Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; } - protected override void UpdateInitialTransforms() => this.FadeIn(); - protected override void UpdateStateTransforms(ArmedState state) { switch (state) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 17efefa959..b4f5642f45 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -36,8 +36,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; - protected override void UpdateInitialTransforms() => this.FadeInFromZero(); - private OsuInputManager osuActionInputManager; internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 5f3bab5b28..5424ccb4de 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -78,8 +78,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public abstract bool OnPressed(TaikoAction action); public virtual bool OnReleased(TaikoAction action) => false; - protected override void UpdateInitialTransforms() => this.FadeIn(); - public override double LifetimeStart { get => base.LifetimeStart; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 80e70589bd..4a6f261905 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; +using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Game.Audio; using osu.Game.Rulesets.Judgements; @@ -186,6 +187,8 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Apply (generally fade-in) transforms leading into the start time. /// The local drawable hierarchy is recursively delayed to for convenience. + /// + /// By default this will fade in the object from zero with no duration. /// /// /// This is called once before every . This is to ensure a good state in the case @@ -193,6 +196,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// protected virtual void UpdateInitialTransforms() { + this.FadeInFromZero(); } /// From cb8fe89b8bf9d82008db4853cbd6ba680a194de7 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 28 Aug 2019 13:09:53 +0300 Subject: [PATCH 2603/5608] Allow setting looping to existing channels --- osu.Game/Skinning/SkinnableSound.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index ac2cb16a6a..1491f2a989 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -35,7 +35,18 @@ namespace osu.Game.Skinning this.audio = audio; } - public bool Looping; + private bool looping; + + public bool Looping + { + get => looping; + set + { + looping = value; + + channels.ForEach(c => c.Looping = looping); + } + } public void Play() => channels?.ForEach(c => c.Play()); From 2f3fb8cf88823e906df851d9da5d5ca9c1eb3f9a Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 28 Aug 2019 13:10:11 +0300 Subject: [PATCH 2604/5608] Add Stop + RemoveAdjustment functions --- osu.Game/Skinning/SkinnableSound.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 1491f2a989..74804d5a06 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -49,8 +49,10 @@ namespace osu.Game.Skinning } public void Play() => channels?.ForEach(c => c.Play()); + public void Stop() => channels?.ForEach(c => c.Stop()); public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => channels?.ForEach(c => c.AddAdjustment(type, adjustBindable)); + public void RemoveAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => channels?.ForEach(c => c.RemoveAdjustment(type, adjustBindable)); public override bool IsPresent => Scheduler.HasPendingTasks; From 01aede3e299f53f0fd2c86f00a5c5087559ace88 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 19:57:17 +0900 Subject: [PATCH 2605/5608] Add comprehensive skin fallback integration testing --- .../TestSceneOsuPlayer.cs | 140 ++++++++++++++++++ .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 8 +- osu.Game/Skinning/SkinnableDrawable.cs | 2 +- osu.Game/Tests/Visual/PlayerTestScene.cs | 7 +- osu.Game/Tests/Visual/TestPlayer.cs | 3 + 6 files changed, 153 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs index 0a33b09ba8..7c84ae80c8 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs @@ -1,7 +1,23 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Timing; +using osu.Game.Audio; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Graphics; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Screens.Play; +using osu.Game.Skinning; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests @@ -9,9 +25,133 @@ namespace osu.Game.Rulesets.Osu.Tests [TestFixture] public class TestSceneOsuPlayer : PlayerTestScene { + private readonly TestSource testUserSkin; + private readonly TestSource testBeatmapSkin; + public TestSceneOsuPlayer() : base(new OsuRuleset()) { + testUserSkin = new TestSource("user"); + testBeatmapSkin = new TestSource("beatmap"); + } + + [Test] + public void TestBeatmapSkinDefault() + { + AddStep("enable user provider", () => testUserSkin.Enabled = true); + + AddStep("enable beatmap skin", () => LocalConfig.Set(OsuSetting.BeatmapSkins, true)); + checkNextHitObject("beatmap"); + + AddStep("disable beatmap skin", () => LocalConfig.Set(OsuSetting.BeatmapSkins, false)); + checkNextHitObject("user"); + + AddStep("disable user provider", () => testUserSkin.Enabled = false); + checkNextHitObject(null); + } + + private void checkNextHitObject(string skin) => + AddUntilStep($"check skin from {skin}", () => + { + var firstObject = ((TestPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.OfType().FirstOrDefault(); + + if (firstObject == null) + return false; + + var skinnable = firstObject?.ApproachCircle.Child as SkinnableDrawable; + + if (skin == null && skinnable?.Drawable is Sprite) + // check for default skin provider + return true; + + var text = skinnable?.Drawable as SpriteText; + + return text?.Text == skin; + }); + + [Resolved] + private AudioManager audio { get; set; } + + protected override Player CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin); + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) => new CustomSkinWorkingBeatmap(beatmap, Clock, audio, testBeatmapSkin); + + public class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap + { + private readonly ISkinSource skin; + + public CustomSkinWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock frameBasedClock, AudioManager audio, ISkinSource skin) + : base(beatmap, frameBasedClock, audio) + { + this.skin = skin; + } + + protected override ISkin GetSkin() => skin; + } + + public class SkinProvidingPlayer : TestPlayer + { + private readonly TestSource userSkin; + + public SkinProvidingPlayer(TestSource userSkin) + { + this.userSkin = userSkin; + } + + private DependencyContainer dependencies; + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + + dependencies.CacheAs(userSkin); + + return dependencies; + } + } + + public class TestSource : ISkinSource + { + private readonly string identifier; + + public TestSource(string identifier) + { + this.identifier = identifier; + } + + public Drawable GetDrawableComponent(string componentName) + { + if (!enabled) return null; + + return new SpriteText + { + Text = identifier, + Font = OsuFont.Default.With(size: 30), + }; + } + + public Texture GetTexture(string componentName) => null; + + public SampleChannel GetSample(ISampleInfo sampleInfo) => null; + + public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => default; + + public event Action SourceChanged; + + private bool enabled = true; + + public bool Enabled + { + get => enabled; + set + { + if (value == enabled) + return; + + enabled = value; + SourceChanged?.Invoke(); + } + } } } } diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 2d8a0b1249..5bbffc2f77 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -136,7 +136,7 @@ namespace osu.Game.Beatmaps return storyboard; } - protected override Skin GetSkin() + protected override ISkin GetSkin() { try { diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 8605caa5fe..9addcfbdd7 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -46,7 +46,7 @@ namespace osu.Game.Beatmaps background = new RecyclableLazy(GetBackground, BackgroundStillValid); waveform = new RecyclableLazy(GetWaveform); storyboard = new RecyclableLazy(GetStoryboard); - skin = new RecyclableLazy(GetSkin); + skin = new RecyclableLazy(GetSkin); total_count.Value++; } @@ -214,10 +214,10 @@ namespace osu.Game.Beatmaps private readonly RecyclableLazy storyboard; public bool SkinLoaded => skin.IsResultAvailable; - public Skin Skin => skin.Value; + public ISkin Skin => skin.Value; - protected virtual Skin GetSkin() => new DefaultSkin(); - private readonly RecyclableLazy skin; + protected virtual ISkin GetSkin() => new DefaultSkin(); + private readonly RecyclableLazy skin; /// /// Transfer pieces of a beatmap to a new one, where possible, to save on loading. diff --git a/osu.Game/Skinning/SkinnableDrawable.cs b/osu.Game/Skinning/SkinnableDrawable.cs index 0c635a3d2f..07f802944b 100644 --- a/osu.Game/Skinning/SkinnableDrawable.cs +++ b/osu.Game/Skinning/SkinnableDrawable.cs @@ -16,7 +16,7 @@ namespace osu.Game.Skinning /// /// The displayed component. /// - protected Drawable Drawable { get; private set; } + public Drawable Drawable { get; private set; } private readonly string componentName; diff --git a/osu.Game/Tests/Visual/PlayerTestScene.cs b/osu.Game/Tests/Visual/PlayerTestScene.cs index 03e17a819c..1ab20ecd48 100644 --- a/osu.Game/Tests/Visual/PlayerTestScene.cs +++ b/osu.Game/Tests/Visual/PlayerTestScene.cs @@ -22,12 +22,13 @@ namespace osu.Game.Tests.Visual this.ruleset = ruleset; } + protected OsuConfigManager LocalConfig; + [BackgroundDependencyLoader] private void load() { - OsuConfigManager manager; - Dependencies.Cache(manager = new OsuConfigManager(LocalStorage)); - manager.GetBindable(OsuSetting.DimLevel).Value = 1.0; + Dependencies.Cache(LocalConfig = new OsuConfigManager(LocalStorage)); + LocalConfig.GetBindable(OsuSetting.DimLevel).Value = 1.0; } [SetUpSteps] diff --git a/osu.Game/Tests/Visual/TestPlayer.cs b/osu.Game/Tests/Visual/TestPlayer.cs index b93a1466e0..31f6edadec 100644 --- a/osu.Game/Tests/Visual/TestPlayer.cs +++ b/osu.Game/Tests/Visual/TestPlayer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual @@ -9,6 +10,8 @@ namespace osu.Game.Tests.Visual { protected override bool PauseOnFocusLost => false; + public new DrawableRuleset DrawableRuleset => base.DrawableRuleset; + public TestPlayer(bool allowPause = true, bool showResults = true) : base(allowPause, showResults) { From c7e20b34bae62458749b973acb1e0cd54f1e8c7b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 20:15:28 +0900 Subject: [PATCH 2606/5608] Cleanup --- osu.Game/Utils/HumanizerUtils.cs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/osu.Game/Utils/HumanizerUtils.cs b/osu.Game/Utils/HumanizerUtils.cs index 398c76a09f..5b7c3630d9 100644 --- a/osu.Game/Utils/HumanizerUtils.cs +++ b/osu.Game/Utils/HumanizerUtils.cs @@ -10,27 +10,21 @@ namespace osu.Game.Utils public static class HumanizerUtils { /// - /// Humanizes a string using the system culture, then falls back if one cannot be found. - /// - /// A localization lookup failure will throw an exception of type - /// + /// Turns the current or provided date into a human readable sentence /// - /// The time to humanize. - /// A humanized string of the given time. - public static string Humanize(DateTimeOffset dateTimeOffset) + /// The date to be humanized + /// distance of time in words + public static string Humanize(DateTimeOffset input) { - string offset; - + // this works around https://github.com/xamarin/xamarin-android/issues/2012 and https://github.com/Humanizr/Humanizer/issues/690#issuecomment-368536282 try { - offset = dateTimeOffset.Humanize(); + return input.Humanize(); } catch (ArgumentException) { - offset = dateTimeOffset.Humanize(culture: new CultureInfo("en-US")); + return input.Humanize(culture: new CultureInfo("en-US")); } - - return offset; } } } From 8b42890644d503b32e663e028bd711434b1969c6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 20:19:19 +0900 Subject: [PATCH 2607/5608] Fix unnecessary null check --- osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs index 7c84ae80c8..d61378f4f8 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Osu.Tests if (firstObject == null) return false; - var skinnable = firstObject?.ApproachCircle.Child as SkinnableDrawable; + var skinnable = firstObject.ApproachCircle.Child as SkinnableDrawable; if (skin == null && skinnable?.Drawable is Sprite) // check for default skin provider From 348d88846da7d530b992a651512843d123f07bb7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Aug 2019 20:19:22 +0900 Subject: [PATCH 2608/5608] Add IBeatmap interface for typed hitobject retrieval --- osu.Game/Beatmaps/Beatmap.cs | 12 ++++-------- osu.Game/Beatmaps/IBeatmap.cs | 9 +++++++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index a09a1bb9cb..5435e86dfd 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -14,7 +14,7 @@ namespace osu.Game.Beatmaps /// /// A Beatmap containing converted HitObjects. /// - public class Beatmap : IBeatmap + public class Beatmap : IBeatmap where T : HitObject { public BeatmapInfo BeatmapInfo { get; set; } = new BeatmapInfo @@ -36,17 +36,13 @@ namespace osu.Game.Beatmaps public List Breaks { get; set; } = new List(); - /// - /// Total amount of break time in the beatmap. - /// [JsonIgnore] public double TotalBreakTime => Breaks.Sum(b => b.Duration); - /// - /// The HitObjects this Beatmap contains. - /// [JsonConverter(typeof(TypedListConverter))] - public List HitObjects = new List(); + public List HitObjects { get; set; } = new List(); + + IReadOnlyList IBeatmap.HitObjects => HitObjects; IReadOnlyList IBeatmap.HitObjects => HitObjects; diff --git a/osu.Game/Beatmaps/IBeatmap.cs b/osu.Game/Beatmaps/IBeatmap.cs index 512fe25809..8f27e0b0e9 100644 --- a/osu.Game/Beatmaps/IBeatmap.cs +++ b/osu.Game/Beatmaps/IBeatmap.cs @@ -53,4 +53,13 @@ namespace osu.Game.Beatmaps /// The shallow-cloned beatmap. IBeatmap Clone(); } + + public interface IBeatmap : IBeatmap + where T : HitObject + { + /// + /// The hitobjects contained by this beatmap. + /// + new IReadOnlyList HitObjects { get; } + } } From f6ad95018adda03061931a74039c8a375ae887df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 20:22:16 +0900 Subject: [PATCH 2609/5608] Centralise default beat length specification --- osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs | 4 +++- .../Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs | 2 +- osu.Game/Rulesets/Timing/MultiplierControlPoint.cs | 2 +- osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index e5815a3f3b..ccb8a92b3a 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -14,6 +14,8 @@ namespace osu.Game.Beatmaps.ControlPoints /// public TimeSignatures TimeSignature = TimeSignatures.SimpleQuadruple; + public const double DEFAULT_BEAT_LENGTH = 1000; + /// /// The beat length at this control point. /// @@ -23,7 +25,7 @@ namespace osu.Game.Beatmaps.ControlPoints set => beatLength = MathHelper.Clamp(value, 6, 60000); } - private double beatLength = 1000; + private double beatLength = DEFAULT_BEAT_LENGTH; public bool Equals(TimingControlPoint other) => base.Equals(other) diff --git a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs index 540f616ea9..8775c15f17 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs @@ -31,7 +31,7 @@ namespace osu.Game.Beatmaps.Formats private class LegacyDifficultyCalculatorControlPoint : TimingControlPoint { - public override double BeatLength { get; set; } = 1000; + public override double BeatLength { get; set; } = TimingControlPoint.DEFAULT_BEAT_LENGTH; } } } diff --git a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs index ffa35c24cd..4b3c3f90f0 100644 --- a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs +++ b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Timing /// The base beat length to scale the provided multiplier relative to. /// /// For a of 1000, a with a beat length of 500 will increase the multiplier by 2. - public double BaseBeatLength = 1000; + public double BaseBeatLength = TimingControlPoint.DEFAULT_BEAT_LENGTH; /// /// The velocity multiplier. diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 65a22b10b7..c1a4c9520e 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -113,7 +113,7 @@ namespace osu.Game.Rulesets.UI.Scrolling private void load() { double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; - double baseBeatLength = 1000; + double baseBeatLength = TimingControlPoint.DEFAULT_BEAT_LENGTH; if (RelativeScaleBeatLengths) { From 3d6200338263bdaca6e39410bd52df1a0dab7e79 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 28 Aug 2019 15:39:45 +0300 Subject: [PATCH 2610/5608] Add null check --- osu.Game/Skinning/SkinnableSound.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 74804d5a06..cb511fc775 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -44,7 +44,7 @@ namespace osu.Game.Skinning { looping = value; - channels.ForEach(c => c.Looping = looping); + channels?.ForEach(c => c.Looping = looping); } } From c6e757fdae6c89b70927a26a83db61ed2cb8e572 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Aug 2019 22:11:23 +0900 Subject: [PATCH 2611/5608] Remove redundant qualifier --- .../Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs index 8775c15f17..2c493254e0 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs @@ -31,7 +31,7 @@ namespace osu.Game.Beatmaps.Formats private class LegacyDifficultyCalculatorControlPoint : TimingControlPoint { - public override double BeatLength { get; set; } = TimingControlPoint.DEFAULT_BEAT_LENGTH; + public override double BeatLength { get; set; } = DEFAULT_BEAT_LENGTH; } } } From 73fd3cf03ca93a0a73b9ae4d55e726d3e3c8089f Mon Sep 17 00:00:00 2001 From: Joehu Date: Wed, 28 Aug 2019 19:00:01 -0700 Subject: [PATCH 2612/5608] Fix gameplay menu button initial hover animation --- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index c7e762714c..f93d5d8b02 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -304,8 +304,6 @@ namespace osu.Game.Screens.Play private class Button : DialogButton { - protected override bool OnHover(HoverEvent e) => true; - protected override bool OnMouseMove(MouseMoveEvent e) { Selected.Value = true; From 03a4acaf4ca0071c9885e5176e67296bb7b68073 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Aug 2019 12:07:58 +0900 Subject: [PATCH 2613/5608] Fix drags outside of overlay container bounds not hiding overlay --- .../Containers/OsuFocusedOverlayContainer.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 0f7b26835b..9c948d6f90 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -62,15 +62,23 @@ namespace osu.Game.Graphics.Containers protected override bool OnClick(ClickEvent e) { - if (!base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)) - { - Hide(); - return true; - } + closeIfOutside(e); return base.OnClick(e); } + protected override bool OnDragEnd(DragEndEvent e) + { + closeIfOutside(e); + return base.OnDragEnd(e); + } + + private void closeIfOutside(MouseEvent e) + { + if (!base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)) + Hide(); + } + public virtual bool OnPressed(GlobalAction action) { switch (action) From 6949c96aaa51952258a335de43b73fc0ba7a793f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 12:43:43 +0900 Subject: [PATCH 2614/5608] Add initial EditorBeatmap structure --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 14 ++++ osu.Game/Screens/Edit/EditorBeatmap.cs | 79 +++++++++++++++++++++ osu.Game/Screens/Edit/IEditorBeatmap.cs | 17 +++++ 3 files changed, 110 insertions(+) create mode 100644 osu.Game/Screens/Edit/EditorBeatmap.cs create mode 100644 osu.Game/Screens/Edit/IEditorBeatmap.cs diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 38ec09535d..6d98f45187 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Components.RadioButtons; using osu.Game.Screens.Edit.Compose.Components; @@ -185,6 +186,19 @@ namespace osu.Game.Rulesets.Edit { } + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var workingBeatmap = parent.Get>(); + var playableBeatmap = (Beatmap)workingBeatmap.Value.GetPlayableBeatmap(Ruleset.RulesetInfo, Array.Empty()); + var editorBeatmap = new EditorBeatmap(playableBeatmap); + + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.CacheAs(editorBeatmap); + dependencies.CacheAs(editorBeatmap); + + return dependencies; + } + internal override DrawableEditRuleset CreateDrawableRuleset() => new DrawableEditRuleset(CreateDrawableRuleset(Ruleset, Beatmap.Value, Array.Empty())); diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs new file mode 100644 index 0000000000..99dd441578 --- /dev/null +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -0,0 +1,79 @@ +// 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.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Beatmaps.Timing; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Screens.Edit +{ + public class EditorBeatmap : IBeatmap, IEditorBeatmap + where T : HitObject + { + public event Action HitObjectRemoved; + public event Action HitObjectAdded; + + event Action IEditorBeatmap.HitObjectAdded + { + add => HitObjectAdded += value; + remove => HitObjectAdded -= value; + } + + event Action IEditorBeatmap.HitObjectRemoved + { + add => HitObjectRemoved += value; + remove => HitObjectRemoved -= value; + } + + private readonly Beatmap beatmap; + + public EditorBeatmap(Beatmap beatmap) + { + this.beatmap = beatmap; + } + + public BeatmapInfo BeatmapInfo + { + get => beatmap.BeatmapInfo; + set => beatmap.BeatmapInfo = value; + } + + public BeatmapMetadata Metadata => beatmap.Metadata; + + public ControlPointInfo ControlPointInfo => beatmap.ControlPointInfo; + + public List Breaks => beatmap.Breaks; + + public double TotalBreakTime => beatmap.TotalBreakTime; + + IReadOnlyList IBeatmap.HitObjects => beatmap.HitObjects; + + IReadOnlyList IBeatmap.HitObjects => beatmap.HitObjects; + + public IEnumerable GetStatistics() => beatmap.GetStatistics(); + + public IBeatmap Clone() => (EditorBeatmap)MemberwiseClone(); + + public void Add(T hitObject) + { + // Preserve existing sorting order in the beatmap + var insertionIndex = beatmap.HitObjects.FindLastIndex(h => h.StartTime <= hitObject.StartTime); + beatmap.HitObjects.Insert(insertionIndex + 1, hitObject); + + HitObjectAdded?.Invoke(hitObject); + } + + public void Remove(T hitObject) + { + if (beatmap.HitObjects.Remove(hitObject)) + HitObjectRemoved?.Invoke(hitObject); + } + + public void Add(HitObject hitObject) => Add((T)hitObject); + + public void Remove(HitObject hitObject) => Remove((T)hitObject); + } +} diff --git a/osu.Game/Screens/Edit/IEditorBeatmap.cs b/osu.Game/Screens/Edit/IEditorBeatmap.cs new file mode 100644 index 0000000000..602a096d65 --- /dev/null +++ b/osu.Game/Screens/Edit/IEditorBeatmap.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Screens.Edit +{ + public interface IEditorBeatmap + { + event Action HitObjectAdded; + event Action HitObjectRemoved; + + void Add(HitObject hitObject); + void Remove(HitObject hitObject); + } +} From 840f2246199d7818dc29771de2dd81628f689294 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 16:05:44 +0900 Subject: [PATCH 2615/5608] Remove typed events to reduce complexity --- osu.Game/Screens/Edit/EditorBeatmap.cs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index 99dd441578..d9f17abfa5 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -13,20 +13,8 @@ namespace osu.Game.Screens.Edit public class EditorBeatmap : IBeatmap, IEditorBeatmap where T : HitObject { - public event Action HitObjectRemoved; - public event Action HitObjectAdded; - - event Action IEditorBeatmap.HitObjectAdded - { - add => HitObjectAdded += value; - remove => HitObjectAdded -= value; - } - - event Action IEditorBeatmap.HitObjectRemoved - { - add => HitObjectRemoved += value; - remove => HitObjectRemoved -= value; - } + public event Action HitObjectAdded; + public event Action HitObjectRemoved; private readonly Beatmap beatmap; From 7927b684d3c0ace143ae033f20b944c37c9f1f41 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 16:06:40 +0900 Subject: [PATCH 2616/5608] Hook up + use editor beatmap --- .../Editor/TestSceneHitObjectComposer.cs | 16 +--- osu.Game/Rulesets/Edit/DrawableEditRuleset.cs | 63 ++++----------- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 66 ++++++++++++---- .../Compose/Components/BlueprintContainer.cs | 76 +++++++++++++------ .../Screens/Edit/Compose/ComposeScreen.cs | 12 +-- 5 files changed, 118 insertions(+), 115 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs b/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs index 7accbe2fa8..0ea73fb3de 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneHitObjectComposer.cs @@ -16,15 +16,13 @@ using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Compose.Components; using osuTK; namespace osu.Game.Tests.Visual.Editor { [TestFixture] - [Cached(Type = typeof(IPlacementHandler))] - public class TestSceneHitObjectComposer : OsuTestScene, IPlacementHandler + public class TestSceneHitObjectComposer : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -39,8 +37,6 @@ namespace osu.Game.Tests.Visual.Editor typeof(HitCirclePlacementBlueprint), }; - private HitObjectComposer composer; - [BackgroundDependencyLoader] private void load() { @@ -67,15 +63,7 @@ namespace osu.Game.Tests.Visual.Editor Dependencies.CacheAs(clock); Dependencies.CacheAs(clock); - Child = composer = new OsuHitObjectComposer(new OsuRuleset()); + Child = new OsuHitObjectComposer(new OsuRuleset()); } - - public void BeginPlacement(HitObject hitObject) - { - } - - public void EndPlacement(HitObject hitObject) => composer.Add(hitObject); - - public void Delete(HitObject hitObject) => composer.Remove(hitObject); } } diff --git a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs index e85ebb5f3a..c9d7b2cd81 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs @@ -5,10 +5,9 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Edit; namespace osu.Game.Rulesets.Edit { @@ -25,20 +24,6 @@ namespace osu.Game.Rulesets.Edit { RelativeSizeAxes = Axes.Both; } - - /// - /// Adds a to the and displays a visual representation of it. - /// - /// The to add. - /// The visual representation of . - internal abstract DrawableHitObject Add(HitObject hitObject); - - /// - /// Removes a from the and the display. - /// - /// The to remove. - /// The visual representation of the removed . - internal abstract DrawableHitObject Remove(HitObject hitObject); } public class DrawableEditRuleset : DrawableEditRuleset @@ -48,11 +33,11 @@ namespace osu.Game.Rulesets.Edit public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => drawableRuleset.CreatePlayfieldAdjustmentContainer(); - private Ruleset ruleset => drawableRuleset.Ruleset; - private Beatmap beatmap => drawableRuleset.Beatmap; - private readonly DrawableRuleset drawableRuleset; + [Resolved] + private EditorBeatmap beatmap { get; set; } + public DrawableEditRuleset(DrawableRuleset drawableRuleset) { this.drawableRuleset = drawableRuleset; @@ -67,50 +52,28 @@ namespace osu.Game.Rulesets.Edit Playfield.DisplayJudgements.Value = false; } - internal override DrawableHitObject Add(HitObject hitObject) + protected override void LoadComplete() { - var tObject = (TObject)hitObject; + base.LoadComplete(); - // Add to beatmap, preserving sorting order - var insertionIndex = beatmap.HitObjects.FindLastIndex(h => h.StartTime <= hitObject.StartTime); - beatmap.HitObjects.Insert(insertionIndex + 1, tObject); + beatmap.HitObjectAdded += addHitObject; + beatmap.HitObjectRemoved += removeHitObject; + } - // Process object - var processor = ruleset.CreateBeatmapProcessor(beatmap); - - processor?.PreProcess(); - tObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.BeatmapInfo.BaseDifficulty); - processor?.PostProcess(); - - // Add visual representation - var drawableObject = drawableRuleset.CreateDrawableRepresentation(tObject); + private void addHitObject(HitObject hitObject) + { + var drawableObject = drawableRuleset.CreateDrawableRepresentation((TObject)hitObject); drawableRuleset.Playfield.Add(drawableObject); drawableRuleset.Playfield.PostProcess(); - - return drawableObject; } - internal override DrawableHitObject Remove(HitObject hitObject) + private void removeHitObject(HitObject hitObject) { - var tObject = (TObject)hitObject; - - // Remove from beatmap - beatmap.HitObjects.Remove(tObject); - - // Process the beatmap - var processor = ruleset.CreateBeatmapProcessor(beatmap); - - processor?.PreProcess(); - processor?.PostProcess(); - - // Remove visual representation var drawableObject = Playfield.AllHitObjects.Single(d => d.HitObject == hitObject); drawableRuleset.Playfield.Remove(drawableObject); drawableRuleset.Playfield.PostProcess(); - - return drawableObject; } } } diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 6d98f45187..fe81f6747d 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -20,6 +20,7 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Components.RadioButtons; +using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Edit @@ -154,14 +155,6 @@ namespace osu.Game.Rulesets.Edit /// public virtual bool CursorInPlacementArea => DrawableRuleset.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); - /// - /// Adds a to the and visualises it. - /// - /// The to add. - public void Add(HitObject hitObject) => blueprintContainer.AddBlueprintFor(DrawableRuleset.Add(hitObject)); - - public void Remove(HitObject hitObject) => blueprintContainer.RemoveBlueprintFor(DrawableRuleset.Remove(hitObject)); - internal abstract DrawableEditRuleset CreateDrawableRuleset(); protected abstract IReadOnlyList CompositionTools { get; } @@ -178,9 +171,16 @@ namespace osu.Game.Rulesets.Edit public virtual SelectionHandler CreateSelectionHandler() => new SelectionHandler(); } - public abstract class HitObjectComposer : HitObjectComposer + [Cached(Type = typeof(IPlacementHandler))] + public abstract class HitObjectComposer : HitObjectComposer, IPlacementHandler where TObject : HitObject { + private Beatmap playableBeatmap; + + [Cached] + [Cached(typeof(IEditorBeatmap))] + private EditorBeatmap editorBeatmap; + protected HitObjectComposer(Ruleset ruleset) : base(ruleset) { @@ -189,19 +189,55 @@ namespace osu.Game.Rulesets.Edit protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { var workingBeatmap = parent.Get>(); - var playableBeatmap = (Beatmap)workingBeatmap.Value.GetPlayableBeatmap(Ruleset.RulesetInfo, Array.Empty()); - var editorBeatmap = new EditorBeatmap(playableBeatmap); + playableBeatmap = (Beatmap)workingBeatmap.Value.GetPlayableBeatmap(Ruleset.RulesetInfo, Array.Empty()); - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(editorBeatmap); - dependencies.CacheAs(editorBeatmap); + editorBeatmap = new EditorBeatmap(playableBeatmap); + editorBeatmap.HitObjectAdded += addHitObject; + editorBeatmap.HitObjectRemoved += removeHitObject; - return dependencies; + return base.CreateChildDependencies(parent); + } + + private void addHitObject(HitObject hitObject) + { + // Process object + var processor = Ruleset.CreateBeatmapProcessor(playableBeatmap); + + processor?.PreProcess(); + hitObject.ApplyDefaults(playableBeatmap.ControlPointInfo, playableBeatmap.BeatmapInfo.BaseDifficulty); + processor?.PostProcess(); + } + + private void removeHitObject(HitObject hitObject) + { + var processor = Ruleset.CreateBeatmapProcessor(playableBeatmap); + + processor?.PreProcess(); + processor?.PostProcess(); } internal override DrawableEditRuleset CreateDrawableRuleset() => new DrawableEditRuleset(CreateDrawableRuleset(Ruleset, Beatmap.Value, Array.Empty())); protected abstract DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods); + + public void BeginPlacement(HitObject hitObject) + { + } + + public void EndPlacement(HitObject hitObject) => editorBeatmap.Add(hitObject); + + public void Delete(HitObject hitObject) => editorBeatmap.Remove(hitObject); + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (editorBeatmap != null) + { + editorBeatmap.HitObjectAdded -= addHitObject; + editorBeatmap.HitObjectRemoved -= removeHitObject; + } + } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index a1e62cd38b..7d25fd5283 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -11,6 +11,7 @@ using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Screens.Edit.Compose.Components @@ -29,6 +30,9 @@ namespace osu.Game.Screens.Edit.Compose.Components [Resolved] private HitObjectComposer composer { get; set; } + [Resolved] + private IEditorBeatmap beatmap { get; set; } + public BlueprintContainer() { RelativeSizeAxes = Axes.Both; @@ -53,7 +57,15 @@ namespace osu.Game.Screens.Edit.Compose.Components }; foreach (var obj in composer.HitObjects) - AddBlueprintFor(obj); + addBlueprintFor(obj); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + beatmap.HitObjectAdded += addBlueprintFor; + beatmap.HitObjectRemoved += removeBlueprintFor; } private HitObjectCompositionTool currentTool; @@ -75,11 +87,32 @@ namespace osu.Game.Screens.Edit.Compose.Components } } - /// - /// Adds a blueprint for a which adds movement support. - /// - /// The to create a blueprint for. - public void AddBlueprintFor(DrawableHitObject hitObject) + private void addBlueprintFor(HitObject hitObject) + { + var drawable = composer.HitObjects.FirstOrDefault(d => d.HitObject == hitObject); + if (drawable == null) + return; + + addBlueprintFor(drawable); + } + + private void removeBlueprintFor(HitObject hitObject) + { + var blueprint = selectionBlueprints.Single(m => m.HitObject.HitObject == hitObject); + if (blueprint == null) + return; + + blueprint.Deselect(); + + blueprint.Selected -= onBlueprintSelected; + blueprint.Deselected -= onBlueprintDeselected; + blueprint.SelectionRequested -= onSelectionRequested; + blueprint.DragRequested -= onDragRequested; + + selectionBlueprints.Remove(blueprint); + } + + private void addBlueprintFor(DrawableHitObject hitObject) { refreshTool(); @@ -95,25 +128,7 @@ namespace osu.Game.Screens.Edit.Compose.Components selectionBlueprints.Add(blueprint); } - /// - /// Removes a blueprint for a . - /// - /// The for which to remove the blueprint. - public void RemoveBlueprintFor(DrawableHitObject hitObject) - { - var blueprint = selectionBlueprints.Single(m => m.HitObject == hitObject); - if (blueprint == null) - return; - - blueprint.Deselect(); - - blueprint.Selected -= onBlueprintSelected; - blueprint.Deselected -= onBlueprintDeselected; - blueprint.SelectionRequested -= onSelectionRequested; - blueprint.DragRequested -= onDragRequested; - - selectionBlueprints.Remove(blueprint); - } + private void removeBlueprintFor(DrawableHitObject hitObject) => removeBlueprintFor(hitObject.HitObject); protected override bool OnClick(ClickEvent e) { @@ -183,6 +198,17 @@ namespace osu.Game.Screens.Edit.Compose.Components private void onDragRequested(SelectionBlueprint blueprint, DragEvent dragEvent) => selectionHandler.HandleDrag(blueprint, dragEvent); + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (beatmap != null) + { + beatmap.HitObjectAdded -= addBlueprintFor; + beatmap.HitObjectRemoved -= removeBlueprintFor; + } + } + private class SelectionBlueprintContainer : Container { protected override int Compare(Drawable x, Drawable y) diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 5699ef0a84..ec4dda5c23 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -9,15 +9,13 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Logging; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Screens.Edit.Compose.Components.Timeline; using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose { - [Cached(Type = typeof(IPlacementHandler))] - public class ComposeScreen : EditorScreen, IPlacementHandler + public class ComposeScreen : EditorScreen { private const float vertical_margins = 10; private const float horizontal_margins = 20; @@ -119,13 +117,5 @@ namespace osu.Game.Screens.Edit.Compose composerContainer.Child = composer; } - - public void BeginPlacement(HitObject hitObject) - { - } - - public void EndPlacement(HitObject hitObject) => composer.Add(hitObject); - - public void Delete(HitObject hitObject) => composer.Remove(hitObject); } } From 5db813b7a411b94d61676cb325e883f929861755 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 16:26:39 +0900 Subject: [PATCH 2617/5608] Add secondary interface for further abstraction --- osu.Game/Rulesets/Edit/DrawableEditRuleset.cs | 2 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 9 ++++--- osu.Game/Screens/Edit/EditorBeatmap.cs | 2 +- osu.Game/Screens/Edit/IEditorBeatmap.cs | 27 ++++++++++++++++--- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs index c9d7b2cd81..95a1492a45 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Edit private readonly DrawableRuleset drawableRuleset; [Resolved] - private EditorBeatmap beatmap { get; set; } + private IEditorBeatmap beatmap { get; set; } public DrawableEditRuleset(DrawableRuleset drawableRuleset) { diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index fe81f6747d..fb7021bfa8 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -176,9 +176,6 @@ namespace osu.Game.Rulesets.Edit where TObject : HitObject { private Beatmap playableBeatmap; - - [Cached] - [Cached(typeof(IEditorBeatmap))] private EditorBeatmap editorBeatmap; protected HitObjectComposer(Ruleset ruleset) @@ -195,7 +192,11 @@ namespace osu.Game.Rulesets.Edit editorBeatmap.HitObjectAdded += addHitObject; editorBeatmap.HitObjectRemoved += removeHitObject; - return base.CreateChildDependencies(parent); + var dependencies = new DependencyContainer(parent); + dependencies.CacheAs(editorBeatmap); + dependencies.CacheAs>(editorBeatmap); + + return base.CreateChildDependencies(dependencies); } private void addHitObject(HitObject hitObject) diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index d9f17abfa5..2261f6f45c 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Edit { - public class EditorBeatmap : IBeatmap, IEditorBeatmap + public class EditorBeatmap : IEditorBeatmap where T : HitObject { public event Action HitObjectAdded; diff --git a/osu.Game/Screens/Edit/IEditorBeatmap.cs b/osu.Game/Screens/Edit/IEditorBeatmap.cs index 602a096d65..2f250ba446 100644 --- a/osu.Game/Screens/Edit/IEditorBeatmap.cs +++ b/osu.Game/Screens/Edit/IEditorBeatmap.cs @@ -2,16 +2,35 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Edit { - public interface IEditorBeatmap + /// + /// Interface for the contained by the see . + /// Children of may resolve the beatmap via or . + /// + public interface IEditorBeatmap : IBeatmap { + /// + /// Invoked when a is added to this . + /// event Action HitObjectAdded; - event Action HitObjectRemoved; - void Add(HitObject hitObject); - void Remove(HitObject hitObject); + /// + /// Invoked when a is removed from this . + /// + event Action HitObjectRemoved; + } + + /// + /// Interface for the contained by the see . + /// Children of may resolve the beatmap via or . + /// + public interface IEditorBeatmap : IEditorBeatmap, IBeatmap + where T : HitObject + { } } From dad0fa2dca16f672569e1a59bf4d16c54456346b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 16:31:40 +0900 Subject: [PATCH 2618/5608] Bind disposal --- osu.Game/Rulesets/Edit/DrawableEditRuleset.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs index 95a1492a45..a12e4ba3ab 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs @@ -75,5 +75,16 @@ namespace osu.Game.Rulesets.Edit drawableRuleset.Playfield.Remove(drawableObject); drawableRuleset.Playfield.PostProcess(); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (beatmap != null) + { + beatmap.HitObjectAdded -= addHitObject; + beatmap.HitObjectRemoved -= removeHitObject; + } + } } } From b04a8ae8560e467ca8f3172e0261b9f3f4b05591 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 16:31:43 +0900 Subject: [PATCH 2619/5608] Add xmldocs --- osu.Game/Screens/Edit/EditorBeatmap.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index 2261f6f45c..f0b6c62154 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -45,6 +45,10 @@ namespace osu.Game.Screens.Edit public IBeatmap Clone() => (EditorBeatmap)MemberwiseClone(); + /// + /// Adds a to this . + /// + /// The to add. public void Add(T hitObject) { // Preserve existing sorting order in the beatmap @@ -54,14 +58,26 @@ namespace osu.Game.Screens.Edit HitObjectAdded?.Invoke(hitObject); } + /// + /// Removes a from this . + /// + /// The to add. public void Remove(T hitObject) { if (beatmap.HitObjects.Remove(hitObject)) HitObjectRemoved?.Invoke(hitObject); } + /// + /// Adds a to this . + /// + /// The to add. public void Add(HitObject hitObject) => Add((T)hitObject); + /// + /// Removes a from this . + /// + /// The to add. public void Remove(HitObject hitObject) => Remove((T)hitObject); } } From 40c1c6072ed587b0f9f3c8ec6d720117788fd62b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Aug 2019 16:38:39 +0900 Subject: [PATCH 2620/5608] Add "osu!classic" as a bundled skin choice --- osu.Game/Configuration/OsuConfigManager.cs | 2 +- osu.Game/OsuGame.cs | 21 +++++++++++++++++++- osu.Game/OsuGameBase.cs | 2 +- osu.Game/Skinning/DefaultLegacySkin.cs | 23 ++++++++++++++++++++++ osu.Game/Skinning/LegacySkin.cs | 3 +++ osu.Game/Skinning/SkinInfo.cs | 6 +++++- osu.Game/Skinning/SkinManager.cs | 18 +++++++++++++++-- 7 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 osu.Game/Skinning/DefaultLegacySkin.cs diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index b13e115387..fb472f3f89 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -18,7 +18,7 @@ namespace osu.Game.Configuration { // UI/selection defaults Set(OsuSetting.Ruleset, 0, 0, int.MaxValue); - Set(OsuSetting.Skin, 0, 0, int.MaxValue); + Set(OsuSetting.Skin, 0, -1, int.MaxValue); Set(OsuSetting.BeatmapDetailTab, BeatmapDetailTab.Details); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 0e804ecbaf..8fa8ffaf9b 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -182,7 +182,26 @@ namespace osu.Game // bind config int to database SkinInfo configSkin = LocalConfig.GetBindable(OsuSetting.Skin); SkinManager.CurrentSkinInfo.ValueChanged += skin => configSkin.Value = skin.NewValue.ID; - configSkin.ValueChanged += skinId => SkinManager.CurrentSkinInfo.Value = SkinManager.Query(s => s.ID == skinId.NewValue) ?? SkinInfo.Default; + configSkin.ValueChanged += skinId => + { + var skinInfo = SkinManager.Query(s => s.ID == skinId.NewValue); + + if (skinInfo == null) + { + switch (skinId.NewValue) + { + case -1: + skinInfo = DefaultLegacySkin.Info; + break; + + default: + skinInfo = SkinInfo.Default; + break; + } + } + + SkinManager.CurrentSkinInfo.Value = skinInfo; + }; configSkin.TriggerChange(); IsActive.BindValueChanged(active => updateActiveState(active.NewValue), true); diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 076c9ada78..de8f316b06 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -158,7 +158,7 @@ namespace osu.Game runMigrations(); - dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio)); + dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio, new NamespacedResourceStore(Resources, "Skins/Legacy"))); dependencies.CacheAs(SkinManager); API = new APIAccess(LocalConfig); diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs new file mode 100644 index 0000000000..b35c9c7b97 --- /dev/null +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -0,0 +1,23 @@ +// 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.Audio; +using osu.Framework.IO.Stores; + +namespace osu.Game.Skinning +{ + public class DefaultLegacySkin : LegacySkin + { + public DefaultLegacySkin(IResourceStore storage, AudioManager audioManager) + : base(Info, storage, audioManager, string.Empty) + { + } + + public static SkinInfo Info { get; } = new SkinInfo + { + ID = -1, // this is temporary until database storage is decided upon. + Name = "osu!classic", + Creator = "team osu!" + }; + } +} diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 570ba1ced7..0cc5e9c9b6 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -248,6 +248,9 @@ namespace osu.Game.Skinning private string getPathForFile(string filename) { + if (source.Files == null) + return null; + bool hasExtension = filename.Contains('.'); var file = source.Files.Find(f => diff --git a/osu.Game/Skinning/SkinInfo.cs b/osu.Game/Skinning/SkinInfo.cs index 187ea910a7..6b9627188e 100644 --- a/osu.Game/Skinning/SkinInfo.cs +++ b/osu.Game/Skinning/SkinInfo.cs @@ -26,7 +26,11 @@ namespace osu.Game.Skinning public string FullName => $"\"{Name}\" by {Creator}"; - public static SkinInfo Default { get; } = new SkinInfo { Name = "osu!lazer", Creator = "team osu!" }; + public static SkinInfo Default { get; } = new SkinInfo + { + Name = "osu!lazer", + Creator = "team osu!" + }; public bool Equals(SkinInfo other) => other != null && ID == other.ID; diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index e747a8b1ce..0e40eb5376 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -14,6 +14,7 @@ using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; +using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Game.Audio; using osu.Game.Database; @@ -25,6 +26,8 @@ namespace osu.Game.Skinning { private readonly AudioManager audio; + private readonly IResourceStore legacyDefaultResources; + public readonly Bindable CurrentSkin = new Bindable(new DefaultSkin()); public readonly Bindable CurrentSkinInfo = new Bindable(SkinInfo.Default) { Default = SkinInfo.Default }; @@ -34,10 +37,11 @@ namespace osu.Game.Skinning protected override string ImportFromStablePath => "Skins"; - public SkinManager(Storage storage, DatabaseContextFactory contextFactory, IIpcHost importHost, AudioManager audio) + public SkinManager(Storage storage, DatabaseContextFactory contextFactory, IIpcHost importHost, AudioManager audio, IResourceStore legacyDefaultResources) : base(storage, contextFactory, new SkinStore(contextFactory, storage), importHost) { this.audio = audio; + this.legacyDefaultResources = legacyDefaultResources; ItemRemoved += removedInfo => { @@ -56,6 +60,9 @@ namespace osu.Game.Skinning }; } + private Skin createIfNotExisting(SkinInfo skinInfo) => + GetSkin(Query(s => s.Name == skinInfo.Name) ?? Import(skinInfo).Result); + protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osk"; /// @@ -66,6 +73,7 @@ namespace osu.Game.Skinning { var userSkins = GetAllUserSkins(); userSkins.Insert(0, SkinInfo.Default); + userSkins.Insert(1, DefaultLegacySkin.Info); return userSkins; } @@ -91,7 +99,7 @@ namespace osu.Game.Skinning else { model.Name = model.Name.Replace(".osk", ""); - model.Creator = "Unknown"; + model.Creator = model.Creator ?? "Unknown"; } } @@ -102,9 +110,15 @@ namespace osu.Game.Skinning /// A instance correlating to the provided . public Skin GetSkin(SkinInfo skinInfo) { + if (skinInfo == null) + return null; + if (skinInfo == SkinInfo.Default) return new DefaultSkin(); + if (skinInfo == DefaultLegacySkin.Info) + return new DefaultLegacySkin(legacyDefaultResources, audio); + return new LegacySkin(skinInfo, Files.Store, audio); } From b40143cb73d8d5b8a0eaf8605b81b40ee30c05e7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 17:18:34 +0900 Subject: [PATCH 2621/5608] Remove unnecessary comment --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index fb7021bfa8..d5a0e052a5 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -201,7 +201,6 @@ namespace osu.Game.Rulesets.Edit private void addHitObject(HitObject hitObject) { - // Process object var processor = Ruleset.CreateBeatmapProcessor(playableBeatmap); processor?.PreProcess(); From 0fbdcabb6faa374e20fd43f1a762c839b73d4ced Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 17:21:52 +0900 Subject: [PATCH 2622/5608] Re-use a single beatmap processor --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index d5a0e052a5..ed2ef5d9f8 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -177,6 +177,7 @@ namespace osu.Game.Rulesets.Edit { private Beatmap playableBeatmap; private EditorBeatmap editorBeatmap; + private IBeatmapProcessor beatmapProcessor; protected HitObjectComposer(Ruleset ruleset) : base(ruleset) @@ -188,6 +189,8 @@ namespace osu.Game.Rulesets.Edit var workingBeatmap = parent.Get>(); playableBeatmap = (Beatmap)workingBeatmap.Value.GetPlayableBeatmap(Ruleset.RulesetInfo, Array.Empty()); + beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap); + editorBeatmap = new EditorBeatmap(playableBeatmap); editorBeatmap.HitObjectAdded += addHitObject; editorBeatmap.HitObjectRemoved += removeHitObject; @@ -201,19 +204,15 @@ namespace osu.Game.Rulesets.Edit private void addHitObject(HitObject hitObject) { - var processor = Ruleset.CreateBeatmapProcessor(playableBeatmap); - - processor?.PreProcess(); + beatmapProcessor?.PreProcess(); hitObject.ApplyDefaults(playableBeatmap.ControlPointInfo, playableBeatmap.BeatmapInfo.BaseDifficulty); - processor?.PostProcess(); + beatmapProcessor?.PostProcess(); } private void removeHitObject(HitObject hitObject) { - var processor = Ruleset.CreateBeatmapProcessor(playableBeatmap); - - processor?.PreProcess(); - processor?.PostProcess(); + beatmapProcessor?.PreProcess(); + beatmapProcessor?.PostProcess(); } internal override DrawableEditRuleset CreateDrawableRuleset() From 59296d12f3af1e2d107c0b0c3206e47cd1feab08 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 18:02:50 +0900 Subject: [PATCH 2623/5608] Refactor HitObjectComposer --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 150 +++++++++----------- 1 file changed, 70 insertions(+), 80 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index ed2ef5d9f8..239ec572b2 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -25,40 +25,40 @@ using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Edit { - public abstract class HitObjectComposer : CompositeDrawable + [Cached(Type = typeof(IPlacementHandler))] + public abstract class HitObjectComposer : HitObjectComposer, IPlacementHandler + where TObject : HitObject { - public IEnumerable HitObjects => DrawableRuleset.Playfield.AllHitObjects; + protected IRulesetConfigManager Config { get; private set; } + protected DrawableEditRuleset DrawableRuleset { get; private set; } protected readonly Ruleset Ruleset; - protected readonly IBindable Beatmap = new Bindable(); - - protected IRulesetConfigManager Config { get; private set; } - - private readonly List layerContainers = new List(); - - protected DrawableEditRuleset DrawableRuleset { get; private set; } + private IBindable workingBeatmap; + private Beatmap playableBeatmap; + private EditorBeatmap editorBeatmap; + private IBeatmapProcessor beatmapProcessor; private BlueprintContainer blueprintContainer; + private readonly List layerContainers = new List(); private InputManager inputManager; - internal HitObjectComposer(Ruleset ruleset) + protected HitObjectComposer(Ruleset ruleset) { Ruleset = ruleset; - RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] - private void load(IBindable beatmap, IFrameBasedClock framedClock) + private void load(IFrameBasedClock framedClock) { - Beatmap.BindTo(beatmap); - try { - DrawableRuleset = CreateDrawableRuleset(); - DrawableRuleset.Clock = framedClock; + DrawableRuleset = new DrawableEditRuleset(CreateDrawableRuleset(Ruleset, workingBeatmap.Value, Array.Empty())) + { + Clock = framedClock + }; } catch (Exception e) { @@ -120,6 +120,26 @@ namespace osu.Game.Rulesets.Edit toolboxCollection.Items[0].Select(); } + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + workingBeatmap = parent.Get>().GetBoundCopy(); + playableBeatmap = (Beatmap)workingBeatmap.Value.GetPlayableBeatmap(Ruleset.RulesetInfo, Array.Empty()); + + beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap); + + editorBeatmap = new EditorBeatmap(playableBeatmap); + editorBeatmap.HitObjectAdded += addHitObject; + editorBeatmap.HitObjectRemoved += removeHitObject; + + var dependencies = new DependencyContainer(parent); + dependencies.CacheAs(editorBeatmap); + dependencies.CacheAs>(editorBeatmap); + + Config = dependencies.Get().GetConfigFor(Ruleset); + + return base.CreateChildDependencies(dependencies); + } + protected override void LoadComplete() { base.LoadComplete(); @@ -127,16 +147,6 @@ namespace osu.Game.Rulesets.Edit inputManager = GetContainingInputManager(); } - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - - dependencies.CacheAs(this); - Config = dependencies.Get().GetConfigFor(Ruleset); - - return dependencies; - } - protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); @@ -150,58 +160,6 @@ namespace osu.Game.Rulesets.Edit }); } - /// - /// Whether the user's cursor is currently in an area of the that is valid for placement. - /// - public virtual bool CursorInPlacementArea => DrawableRuleset.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); - - internal abstract DrawableEditRuleset CreateDrawableRuleset(); - - protected abstract IReadOnlyList CompositionTools { get; } - - /// - /// Creates a for a specific . - /// - /// The to create the overlay for. - public virtual SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) => null; - - /// - /// Creates a which outlines s and handles movement of selections. - /// - public virtual SelectionHandler CreateSelectionHandler() => new SelectionHandler(); - } - - [Cached(Type = typeof(IPlacementHandler))] - public abstract class HitObjectComposer : HitObjectComposer, IPlacementHandler - where TObject : HitObject - { - private Beatmap playableBeatmap; - private EditorBeatmap editorBeatmap; - private IBeatmapProcessor beatmapProcessor; - - protected HitObjectComposer(Ruleset ruleset) - : base(ruleset) - { - } - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var workingBeatmap = parent.Get>(); - playableBeatmap = (Beatmap)workingBeatmap.Value.GetPlayableBeatmap(Ruleset.RulesetInfo, Array.Empty()); - - beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap); - - editorBeatmap = new EditorBeatmap(playableBeatmap); - editorBeatmap.HitObjectAdded += addHitObject; - editorBeatmap.HitObjectRemoved += removeHitObject; - - var dependencies = new DependencyContainer(parent); - dependencies.CacheAs(editorBeatmap); - dependencies.CacheAs>(editorBeatmap); - - return base.CreateChildDependencies(dependencies); - } - private void addHitObject(HitObject hitObject) { beatmapProcessor?.PreProcess(); @@ -215,8 +173,10 @@ namespace osu.Game.Rulesets.Edit beatmapProcessor?.PostProcess(); } - internal override DrawableEditRuleset CreateDrawableRuleset() - => new DrawableEditRuleset(CreateDrawableRuleset(Ruleset, Beatmap.Value, Array.Empty())); + public override IEnumerable HitObjects => DrawableRuleset.Playfield.AllHitObjects; + public override bool CursorInPlacementArea => DrawableRuleset.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); + + protected abstract IReadOnlyList CompositionTools { get; } protected abstract DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods); @@ -239,4 +199,34 @@ namespace osu.Game.Rulesets.Edit } } } + + [Cached(typeof(HitObjectComposer))] + public abstract class HitObjectComposer : CompositeDrawable + { + internal HitObjectComposer() + { + RelativeSizeAxes = Axes.Both; + } + + /// + /// All the s. + /// + public abstract IEnumerable HitObjects { get; } + + /// + /// Whether the user's cursor is currently in an area of the that is valid for placement. + /// + public abstract bool CursorInPlacementArea { get; } + + /// + /// Creates a for a specific . + /// + /// The to create the overlay for. + public virtual SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) => null; + + /// + /// Creates a which outlines s and handles movement of selections. + /// + public virtual SelectionHandler CreateSelectionHandler() => new SelectionHandler(); + } } From 87e28ab1f97869de9fef85deac8ec2be1072f0e0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 18:12:29 +0900 Subject: [PATCH 2624/5608] Remove non-generic DrawableEditRuleset --- .../Edit/ManiaHitObjectComposer.cs | 12 ++++----- osu.Game/Rulesets/Edit/DrawableEditRuleset.cs | 25 +++++-------------- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 22 ++++++++-------- 3 files changed, 23 insertions(+), 36 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 2729621ab3..3a28149946 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.Edit [Cached(Type = typeof(IManiaHitObjectComposer))] public class ManiaHitObjectComposer : HitObjectComposer, IManiaHitObjectComposer { - protected new DrawableManiaEditRuleset DrawableRuleset { get; private set; } + private DrawableManiaEditRuleset drawableRuleset; public ManiaHitObjectComposer(Ruleset ruleset) : base(ruleset) @@ -33,23 +33,23 @@ namespace osu.Game.Rulesets.Mania.Edit /// /// The screen-space position. /// The column which intersects with . - public Column ColumnAt(Vector2 screenSpacePosition) => DrawableRuleset.GetColumnByPosition(screenSpacePosition); + public Column ColumnAt(Vector2 screenSpacePosition) => drawableRuleset.GetColumnByPosition(screenSpacePosition); private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - public int TotalColumns => ((ManiaPlayfield)DrawableRuleset.Playfield).TotalColumns; + public int TotalColumns => ((ManiaPlayfield)drawableRuleset.Playfield).TotalColumns; protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) { - DrawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap, mods); + drawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap, mods); // This is the earliest we can cache the scrolling info to ourselves, before masks are added to the hierarchy and inject it - dependencies.CacheAs(DrawableRuleset.ScrollingInfo); + dependencies.CacheAs(drawableRuleset.ScrollingInfo); - return DrawableRuleset; + return drawableRuleset; } protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] diff --git a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs index a12e4ba3ab..a9f0dd4197 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs @@ -11,27 +11,10 @@ using osu.Game.Screens.Edit; namespace osu.Game.Rulesets.Edit { - public abstract class DrawableEditRuleset : CompositeDrawable - { - /// - /// The contained by this . - /// - public abstract Playfield Playfield { get; } - - public abstract PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer(); - - internal DrawableEditRuleset() - { - RelativeSizeAxes = Axes.Both; - } - } - - public class DrawableEditRuleset : DrawableEditRuleset + public class DrawableEditRuleset : CompositeDrawable where TObject : HitObject { - public override Playfield Playfield => drawableRuleset.Playfield; - - public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => drawableRuleset.CreatePlayfieldAdjustmentContainer(); + public Playfield Playfield => drawableRuleset.Playfield; private readonly DrawableRuleset drawableRuleset; @@ -42,6 +25,8 @@ namespace osu.Game.Rulesets.Edit { this.drawableRuleset = drawableRuleset; + RelativeSizeAxes = Axes.Both; + InternalChild = drawableRuleset; } @@ -76,6 +61,8 @@ namespace osu.Game.Rulesets.Edit drawableRuleset.Playfield.PostProcess(); } + public PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => drawableRuleset.CreatePlayfieldAdjustmentContainer(); + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 239ec572b2..35c5a63ef1 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -30,7 +30,6 @@ namespace osu.Game.Rulesets.Edit where TObject : HitObject { protected IRulesetConfigManager Config { get; private set; } - protected DrawableEditRuleset DrawableRuleset { get; private set; } protected readonly Ruleset Ruleset; @@ -39,6 +38,7 @@ namespace osu.Game.Rulesets.Edit private EditorBeatmap editorBeatmap; private IBeatmapProcessor beatmapProcessor; + private DrawableEditRuleset drawableRuleset; private BlueprintContainer blueprintContainer; private readonly List layerContainers = new List(); @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Edit { try { - DrawableRuleset = new DrawableEditRuleset(CreateDrawableRuleset(Ruleset, workingBeatmap.Value, Array.Empty())) + drawableRuleset = new DrawableEditRuleset(CreateDrawableRuleset(Ruleset, workingBeatmap.Value, Array.Empty())) { Clock = framedClock }; @@ -66,10 +66,10 @@ namespace osu.Game.Rulesets.Edit return; } - var layerBelowRuleset = DrawableRuleset.CreatePlayfieldAdjustmentContainer(); + var layerBelowRuleset = drawableRuleset.CreatePlayfieldAdjustmentContainer(); layerBelowRuleset.Child = new EditorPlayfieldBorder { RelativeSizeAxes = Axes.Both }; - var layerAboveRuleset = DrawableRuleset.CreatePlayfieldAdjustmentContainer(); + var layerAboveRuleset = drawableRuleset.CreatePlayfieldAdjustmentContainer(); layerAboveRuleset.Child = blueprintContainer = new BlueprintContainer(); layerContainers.Add(layerBelowRuleset); @@ -100,7 +100,7 @@ namespace osu.Game.Rulesets.Edit Children = new Drawable[] { layerBelowRuleset, - DrawableRuleset, + drawableRuleset, layerAboveRuleset } } @@ -153,10 +153,10 @@ namespace osu.Game.Rulesets.Edit layerContainers.ForEach(l => { - l.Anchor = DrawableRuleset.Playfield.Anchor; - l.Origin = DrawableRuleset.Playfield.Origin; - l.Position = DrawableRuleset.Playfield.Position; - l.Size = DrawableRuleset.Playfield.Size; + l.Anchor = drawableRuleset.Playfield.Anchor; + l.Origin = drawableRuleset.Playfield.Origin; + l.Position = drawableRuleset.Playfield.Position; + l.Size = drawableRuleset.Playfield.Size; }); } @@ -173,8 +173,8 @@ namespace osu.Game.Rulesets.Edit beatmapProcessor?.PostProcess(); } - public override IEnumerable HitObjects => DrawableRuleset.Playfield.AllHitObjects; - public override bool CursorInPlacementArea => DrawableRuleset.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); + public override IEnumerable HitObjects => drawableRuleset.Playfield.AllHitObjects; + public override bool CursorInPlacementArea => drawableRuleset.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); protected abstract IReadOnlyList CompositionTools { get; } From 714ee312da0338bb768ac543ad5ffb4cf43328f0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 18:20:43 +0900 Subject: [PATCH 2625/5608] Rename DrawableEditRuleset -> DrawableEditRulesetWrapper --- ...leset.cs => DrawableEditRulesetWrapper.cs} | 7 ++++-- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 22 +++++++++---------- 2 files changed, 16 insertions(+), 13 deletions(-) rename osu.Game/Rulesets/Edit/{DrawableEditRuleset.cs => DrawableEditRulesetWrapper.cs} (85%) diff --git a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs similarity index 85% rename from osu.Game/Rulesets/Edit/DrawableEditRuleset.cs rename to osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs index a9f0dd4197..af565f8896 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs @@ -11,7 +11,10 @@ using osu.Game.Screens.Edit; namespace osu.Game.Rulesets.Edit { - public class DrawableEditRuleset : CompositeDrawable + /// + /// A wrapper for a . Handles adding visual representations of s to the underlying . + /// + internal class DrawableEditRulesetWrapper : CompositeDrawable where TObject : HitObject { public Playfield Playfield => drawableRuleset.Playfield; @@ -21,7 +24,7 @@ namespace osu.Game.Rulesets.Edit [Resolved] private IEditorBeatmap beatmap { get; set; } - public DrawableEditRuleset(DrawableRuleset drawableRuleset) + public DrawableEditRulesetWrapper(DrawableRuleset drawableRuleset) { this.drawableRuleset = drawableRuleset; diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 35c5a63ef1..d7ee63d4a4 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Edit private EditorBeatmap editorBeatmap; private IBeatmapProcessor beatmapProcessor; - private DrawableEditRuleset drawableRuleset; + private DrawableEditRulesetWrapper drawableRulesetWrapper; private BlueprintContainer blueprintContainer; private readonly List layerContainers = new List(); @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Edit { try { - drawableRuleset = new DrawableEditRuleset(CreateDrawableRuleset(Ruleset, workingBeatmap.Value, Array.Empty())) + drawableRulesetWrapper = new DrawableEditRulesetWrapper(CreateDrawableRuleset(Ruleset, workingBeatmap.Value, Array.Empty())) { Clock = framedClock }; @@ -66,10 +66,10 @@ namespace osu.Game.Rulesets.Edit return; } - var layerBelowRuleset = drawableRuleset.CreatePlayfieldAdjustmentContainer(); + var layerBelowRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer(); layerBelowRuleset.Child = new EditorPlayfieldBorder { RelativeSizeAxes = Axes.Both }; - var layerAboveRuleset = drawableRuleset.CreatePlayfieldAdjustmentContainer(); + var layerAboveRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer(); layerAboveRuleset.Child = blueprintContainer = new BlueprintContainer(); layerContainers.Add(layerBelowRuleset); @@ -100,7 +100,7 @@ namespace osu.Game.Rulesets.Edit Children = new Drawable[] { layerBelowRuleset, - drawableRuleset, + drawableRulesetWrapper, layerAboveRuleset } } @@ -153,10 +153,10 @@ namespace osu.Game.Rulesets.Edit layerContainers.ForEach(l => { - l.Anchor = drawableRuleset.Playfield.Anchor; - l.Origin = drawableRuleset.Playfield.Origin; - l.Position = drawableRuleset.Playfield.Position; - l.Size = drawableRuleset.Playfield.Size; + l.Anchor = drawableRulesetWrapper.Playfield.Anchor; + l.Origin = drawableRulesetWrapper.Playfield.Origin; + l.Position = drawableRulesetWrapper.Playfield.Position; + l.Size = drawableRulesetWrapper.Playfield.Size; }); } @@ -173,8 +173,8 @@ namespace osu.Game.Rulesets.Edit beatmapProcessor?.PostProcess(); } - public override IEnumerable HitObjects => drawableRuleset.Playfield.AllHitObjects; - public override bool CursorInPlacementArea => drawableRuleset.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); + public override IEnumerable HitObjects => drawableRulesetWrapper.Playfield.AllHitObjects; + public override bool CursorInPlacementArea => drawableRulesetWrapper.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); protected abstract IReadOnlyList CompositionTools { get; } From d3030831793dc68f7d8e04fce2d05209e6fab796 Mon Sep 17 00:00:00 2001 From: StanR Date: Thu, 29 Aug 2019 12:29:31 +0300 Subject: [PATCH 2626/5608] Update to match api --- .../Online/TestSceneBeatmapSetOverlay.cs | 4 +- osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs | 51 +++---------------- .../API/Requests/Responses/APIBeatmapSet.cs | 4 +- osu.Game/Overlays/BeatmapSet/Info.cs | 4 +- 4 files changed, 12 insertions(+), 51 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 2d918442eb..ee9e088dcc 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -176,8 +176,8 @@ namespace osu.Game.Tests.Visual.Online HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), - Language = BeatmapSetOnlineLanguage.English, - Genre = BeatmapSetOnlineGenre.Rock, + Language = new BeatmapSetOnlineLanguage { Id = 3, Name = "English" }, + Genre = new BeatmapSetOnlineGenre { Id = 4, Name = "Rock" }, }, Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = new List diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs index decf2d10db..500e42096c 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs @@ -88,55 +88,16 @@ namespace osu.Game.Beatmaps public BeatmapSetOnlineLanguage Language { get; set; } } - public enum BeatmapSetOnlineGenre + public class BeatmapSetOnlineGenre { - [Description("Any")] - Any = 0, - - [Description("Unspecified")] - Unspecified = 1, - - [Description("Video Game")] - VideoGame = 2, - - [Description("Anime")] - Anime = 3, - - [Description("Rock")] - Rock = 4, - - [Description("Pop")] - Pop = 5, - - [Description("Other")] - Other = 6, - - [Description("Novelty")] - Novelty = 7, - - // genre_id 8 doesn't exist - - [Description("Hip-Hop")] - HipHop = 9, - - [Description("Electronic")] - Electronic = 10 + public int Id { get; set; } + public string Name { get; set; } } - public enum BeatmapSetOnlineLanguage + public class BeatmapSetOnlineLanguage { - Any, - Other, - English, - Japanese, - Chinese, - Instrumental, - Korean, - French, - German, - Swedish, - Spanish, - Italian + public int Id { get; set; } + public string Name { get; set; } } public class BeatmapSetOnlineCovers diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 1526cccf31..1ca14256e5 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -69,10 +69,10 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"availability")] private BeatmapSetOnlineAvailability availability { get; set; } - [JsonProperty(@"genre_id")] + [JsonProperty(@"genre")] private BeatmapSetOnlineGenre genre { get; set; } - [JsonProperty(@"language_id")] + [JsonProperty(@"language")] private BeatmapSetOnlineLanguage language { get; set; } [JsonProperty(@"beatmaps")] diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 0e4e9db948..9c5cce89f9 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -133,8 +133,8 @@ namespace osu.Game.Overlays.BeatmapSet { source.Text = b.NewValue?.Metadata.Source ?? string.Empty; tags.Text = b.NewValue?.Metadata.Tags ?? string.Empty; - genre.Text = (b.NewValue?.OnlineInfo.Genre ?? BeatmapSetOnlineGenre.Unspecified).GetDescription(); - language.Text = (b.NewValue?.OnlineInfo.Language ?? BeatmapSetOnlineLanguage.Other).ToString(); + genre.Text = b.NewValue?.OnlineInfo.Genre.Name ?? "Unspecified"; + language.Text = b.NewValue?.OnlineInfo.Language.Name ?? "Other"; }; } From 68ee7346b213b099e6eceed2cd8478181e15b484 Mon Sep 17 00:00:00 2001 From: StanR Date: Thu, 29 Aug 2019 12:49:44 +0300 Subject: [PATCH 2627/5608] Remove usings --- osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs | 1 - osu.Game/Overlays/BeatmapSet/Info.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs index 500e42096c..06dee4d3f5 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.ComponentModel; using Newtonsoft.Json; namespace osu.Game.Beatmaps diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 9c5cce89f9..f17b44c8f7 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -3,7 +3,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; From c1c1c7874bab0786ffeaa6f3a99e63c9b2317853 Mon Sep 17 00:00:00 2001 From: StanR Date: Thu, 29 Aug 2019 13:25:05 +0300 Subject: [PATCH 2628/5608] Nullcheck --- osu.Game/Overlays/BeatmapSet/Info.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index f17b44c8f7..72db03a5a6 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -132,8 +132,8 @@ namespace osu.Game.Overlays.BeatmapSet { source.Text = b.NewValue?.Metadata.Source ?? string.Empty; tags.Text = b.NewValue?.Metadata.Tags ?? string.Empty; - genre.Text = b.NewValue?.OnlineInfo.Genre.Name ?? "Unspecified"; - language.Text = b.NewValue?.OnlineInfo.Language.Name ?? "Other"; + genre.Text = b.NewValue?.OnlineInfo?.Genre?.Name ?? "Unspecified"; + language.Text = b.NewValue?.OnlineInfo?.Language?.Name ?? "Other"; }; } From 6ab2b20c70dcea4dd98ec7c7ebc9f477170ea95d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 19:38:44 +0900 Subject: [PATCH 2629/5608] Add an interface for working beatmaps --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- .../UI/DrawableCatchRuleset.cs | 4 +- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../UI/DrawableManiaRuleset.cs | 2 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../UI/DrawableOsuRuleset.cs | 2 +- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- .../UI/DrawableTaikoRuleset.cs | 2 +- .../TestSceneDrawableScrollingRuleset.cs | 4 +- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/IWorkingBeatmap.cs | 61 +++++++++++++++++++ osu.Game/Beatmaps/WorkingBeatmap.cs | 16 +---- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 12 ++-- osu.Game/Rulesets/Ruleset.cs | 2 +- osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 +- .../UI/Scrolling/DrawableScrollingRuleset.cs | 2 +- 16 files changed, 85 insertions(+), 34 deletions(-) create mode 100644 osu.Game/Beatmaps/IWorkingBeatmap.cs diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 6f1a7873ec..71e05083be 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch { public class CatchRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableCatchRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableCatchRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index f48b84e344..6b7f00c5d0 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -25,11 +25,11 @@ namespace osu.Game.Rulesets.Catch.UI protected override bool UserScrollSpeedAdjustment => false; - public DrawableCatchRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) + public DrawableCatchRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { Direction.Value = ScrollingDirection.Down; - TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450); + TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450); } public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this); diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 8966b5058f..0de86c2149 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Mania { public class ManiaRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableManiaRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableManiaRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score); diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 0718de2c7d..f26526fe70 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly Bindable configDirection = new Bindable(); - public DrawableManiaRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) + public DrawableManiaRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { // Generate the bar lines diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index d50d4f401c..3bbfc25d22 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Osu { public class OsuRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableOsuRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableOsuRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap); diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index d185d7d4c9..aa61fb6922 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.UI { protected new OsuRulesetConfigManager Config => (OsuRulesetConfigManager)base.Config; - public DrawableOsuRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) + public DrawableOsuRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 83356b77c2..6d0a5eb1e1 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko { public class TaikoRuleset : Ruleset { - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableTaikoRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableTaikoRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index ec3a56e9c7..b03bea578e 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Taiko.UI protected override bool UserScrollSpeedAdjustment => false; - public DrawableTaikoRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) + public DrawableTaikoRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { Direction.Value = ScrollingDirection.Left; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index ee11fc0d06..60ace8ea69 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -174,7 +174,7 @@ namespace osu.Game.Tests.Visual.Gameplay public override IEnumerable GetModsFor(ModType type) => throw new NotImplementedException(); - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods) => new TestDrawableScrollingRuleset(this, beatmap, mods); + public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => new TestDrawableScrollingRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap); @@ -193,7 +193,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping; - public TestDrawableScrollingRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) + public TestDrawableScrollingRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { TimeRange.Value = time_range; diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 3a4c677bd1..29ade24328 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -54,7 +54,7 @@ namespace osu.Game.Beatmaps { public override IEnumerable GetModsFor(ModType type) => new Mod[] { }; - public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods) + public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) { throw new NotImplementedException(); } diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs new file mode 100644 index 0000000000..aea3751bb5 --- /dev/null +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -0,0 +1,61 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Audio.Track; +using osu.Framework.Graphics.Textures; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.UI; +using osu.Game.Skinning; +using osu.Game.Storyboards; + +namespace osu.Game.Beatmaps +{ + public interface IWorkingBeatmap + { + /// + /// Retrieves the which this represents. + /// + IBeatmap Beatmap { get; } + + /// + /// Retrieves the background for this . + /// + Texture Background { get; } + + /// + /// Retrieves the audio track for this . + /// + Track Track { get; } + + /// + /// Retrieves the for the of this . + /// + Waveform Waveform { get; } + + /// + /// Retrieves the which this provides. + /// + Storyboard Storyboard { get; } + + /// + /// Retrieves the which this provides. + /// + Skin Skin { get; } + + /// + /// Constructs a playable from using the applicable converters for a specific . + /// + /// The returned is in a playable state - all and s + /// have been applied, and s have been fully constructed. + /// + /// + /// The to create a playable for. + /// The s to apply to the . + /// The converted . + /// If could not be converted to . + IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods); + } +} diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 8605caa5fe..1cce3dc5fe 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -16,14 +16,13 @@ using osu.Framework.Audio; using osu.Framework.Statistics; using osu.Game.IO.Serialization; using osu.Game.Rulesets; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; using osu.Game.Skinning; namespace osu.Game.Beatmaps { - public abstract class WorkingBeatmap : IDisposable + public abstract class WorkingBeatmap : IWorkingBeatmap, IDisposable { public readonly BeatmapInfo BeatmapInfo; @@ -97,18 +96,7 @@ namespace osu.Game.Beatmaps /// The applicable . protected virtual IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) => ruleset.CreateBeatmapConverter(beatmap); - /// - /// Constructs a playable from using the applicable converters for a specific . - /// - /// The returned is in a playable state - all and s - /// have been applied, and s have been fully constructed. - /// - /// - /// The to create a playable for. - /// The s to apply to the . - /// The converted . - /// If could not be converted to . - public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods) + public virtual IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods) { var rulesetInstance = ruleset.CreateInstance(); diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index d7ee63d4a4..fc324d7021 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Edit protected readonly Ruleset Ruleset; - private IBindable workingBeatmap; + private IWorkingBeatmap workingBeatmap; private Beatmap playableBeatmap; private EditorBeatmap editorBeatmap; private IBeatmapProcessor beatmapProcessor; @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Edit { try { - drawableRulesetWrapper = new DrawableEditRulesetWrapper(CreateDrawableRuleset(Ruleset, workingBeatmap.Value, Array.Empty())) + drawableRulesetWrapper = new DrawableEditRulesetWrapper(CreateDrawableRuleset(Ruleset, workingBeatmap, Array.Empty())) { Clock = framedClock }; @@ -122,8 +122,10 @@ namespace osu.Game.Rulesets.Edit protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - workingBeatmap = parent.Get>().GetBoundCopy(); - playableBeatmap = (Beatmap)workingBeatmap.Value.GetPlayableBeatmap(Ruleset.RulesetInfo, Array.Empty()); + var parentWorkingBeatmap = parent.Get>().Value; + + playableBeatmap = (Beatmap)parentWorkingBeatmap.GetPlayableBeatmap(Ruleset.RulesetInfo, Array.Empty()); + workingBeatmap = new EditorWorkingBeatmap(playableBeatmap, parentWorkingBeatmap); beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap); @@ -178,7 +180,7 @@ namespace osu.Game.Rulesets.Edit protected abstract IReadOnlyList CompositionTools { get; } - protected abstract DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods); + protected abstract DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods); public void BeginPlacement(HitObject hitObject) { diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 42b1322cae..b089840f1e 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets /// The s to apply. /// Unable to successfully load the beatmap to be usable with this ruleset. /// - public abstract DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList mods); + public abstract DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods); /// /// Creates a to convert a to one that is applicable for this . diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index ccfd89adca..021bd515b5 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -113,7 +113,7 @@ namespace osu.Game.Rulesets.UI /// The ruleset being represented. /// The beatmap to create the hit renderer for. /// The s to apply. - protected DrawableRuleset(Ruleset ruleset, WorkingBeatmap workingBeatmap, IReadOnlyList mods) + protected DrawableRuleset(Ruleset ruleset, IWorkingBeatmap workingBeatmap, IReadOnlyList mods) : base(ruleset) { if (workingBeatmap == null) diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index c1a4c9520e..64e491858b 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.UI.Scrolling [Cached(Type = typeof(IScrollingInfo))] private readonly LocalScrollingInfo scrollingInfo; - protected DrawableScrollingRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) + protected DrawableScrollingRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { scrollingInfo = new LocalScrollingInfo(); From 6641811125b938aa1511325938504f4be4e876a0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 19:40:56 +0900 Subject: [PATCH 2630/5608] Add EditorWorkingBeatmap for reuse of the playable beatmap --- .../Edit/DrawableManiaEditRuleset.cs | 2 +- .../Edit/ManiaHitObjectComposer.cs | 2 +- .../Edit/DrawableOsuEditRuleset.cs | 2 +- .../Edit/OsuHitObjectComposer.cs | 2 +- osu.Game/Screens/Edit/EditorWorkingBeatmap.cs | 42 +++++++++++++++++++ 5 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Screens/Edit/EditorWorkingBeatmap.cs diff --git a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs index e5f379f608..97d8aaa052 100644 --- a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs +++ b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Edit { public new IScrollingInfo ScrollingInfo => base.ScrollingInfo; - public DrawableManiaEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) + public DrawableManiaEditRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 3a28149946..0bfe6f9517 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.Edit public int TotalColumns => ((ManiaPlayfield)drawableRuleset.Playfield).TotalColumns; - protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) + protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) { drawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap, mods); diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs index bcb6099cfb..cc08d356f9 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Edit { public class DrawableOsuEditRuleset : DrawableOsuRuleset { - public DrawableOsuEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) + public DrawableOsuEditRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index c5452ae0aa..1c040e9dee 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Edit { } - protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList mods) + protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableOsuEditRuleset(ruleset, beatmap, mods); protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] diff --git a/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs b/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs new file mode 100644 index 0000000000..8bec68596c --- /dev/null +++ b/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs @@ -0,0 +1,42 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Audio.Track; +using osu.Framework.Graphics.Textures; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Skinning; +using osu.Game.Storyboards; + +namespace osu.Game.Screens.Edit +{ + public class EditorWorkingBeatmap : IWorkingBeatmap + where TObject : HitObject + { + private readonly Beatmap playableBeatmap; + private readonly WorkingBeatmap workingBeatmap; + + public EditorWorkingBeatmap(Beatmap playableBeatmap, WorkingBeatmap workingBeatmap) + { + this.playableBeatmap = playableBeatmap; + this.workingBeatmap = workingBeatmap; + } + + public IBeatmap Beatmap => workingBeatmap.Beatmap; + + public Texture Background => workingBeatmap.Background; + + public Track Track => workingBeatmap.Track; + + public Waveform Waveform => workingBeatmap.Waveform; + + public Storyboard Storyboard => workingBeatmap.Storyboard; + + public Skin Skin => workingBeatmap.Skin; + + public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods) => playableBeatmap; + } +} From ae0a5504d705fb4ed1dd95751e71d581f40cf636 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Aug 2019 19:43:33 +0900 Subject: [PATCH 2631/5608] Revert unnecessary change --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 1cce3dc5fe..90dde4239c 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -96,7 +96,7 @@ namespace osu.Game.Beatmaps /// The applicable . protected virtual IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) => ruleset.CreateBeatmapConverter(beatmap); - public virtual IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods) + public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods) { var rulesetInstance = ruleset.CreateInstance(); From ec6a40af339a78b2d172b69089ea77b6afca8c5e Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 29 Aug 2019 15:32:21 +0300 Subject: [PATCH 2632/5608] Add adjustments on channel creation if there is --- osu.Game/Skinning/SkinnableSound.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index cb511fc775..e1d9b231dc 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -15,6 +15,9 @@ namespace osu.Game.Skinning public class SkinnableSound : SkinReloadableDrawable { private readonly ISampleInfo[] hitSamples; + + private readonly List<(AdjustableProperty, BindableDouble)> adjustments = new List<(AdjustableProperty, BindableDouble)>(); + private SampleChannel[] channels; private AudioManager audio; @@ -51,8 +54,17 @@ namespace osu.Game.Skinning public void Play() => channels?.ForEach(c => c.Play()); public void Stop() => channels?.ForEach(c => c.Stop()); - public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => channels?.ForEach(c => c.AddAdjustment(type, adjustBindable)); - public void RemoveAdjustment(AdjustableProperty type, BindableDouble adjustBindable) => channels?.ForEach(c => c.RemoveAdjustment(type, adjustBindable)); + public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) + { + adjustments.Add((type, adjustBindable)); + channels?.ForEach(c => c.AddAdjustment(type, adjustBindable)); + } + + public void RemoveAdjustment(AdjustableProperty type, BindableDouble adjustBindable) + { + adjustments.Remove((type, adjustBindable)); + channels?.ForEach(c => c.RemoveAdjustment(type, adjustBindable)); + } public override bool IsPresent => Scheduler.HasPendingTasks; @@ -71,6 +83,9 @@ namespace osu.Game.Skinning { ch.Looping = looping; ch.Volume.Value = s.Volume / 100.0; + + foreach (var adjustment in adjustments) + ch.AddAdjustment(adjust.Item1, adjust.Item2); } return ch; From 06224a7d4ee9921180946040f62811d75689a406 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 29 Aug 2019 15:38:33 +0300 Subject: [PATCH 2633/5608] Fix build issue --- osu.Game/Skinning/SkinnableSound.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index e1d9b231dc..bf647baeec 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -85,7 +85,7 @@ namespace osu.Game.Skinning ch.Volume.Value = s.Volume / 100.0; foreach (var adjustment in adjustments) - ch.AddAdjustment(adjust.Item1, adjust.Item2); + ch.AddAdjustment(adjustment.Item1, adjustment.Item2); } return ch; From 3f500131d483b5ebbdc60fb4c905de2e754965d7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 11:33:50 +0900 Subject: [PATCH 2634/5608] Add basic xmldoc --- osu.Game/Screens/Edit/EditorWorkingBeatmap.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs b/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs index 8bec68596c..45fca493a2 100644 --- a/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs @@ -13,6 +13,10 @@ using osu.Game.Storyboards; namespace osu.Game.Screens.Edit { + /// + /// Encapsulates a while providing an overridden . + /// + /// public class EditorWorkingBeatmap : IWorkingBeatmap where TObject : HitObject { From bfbec067b13ba7546b1ece8f460b4c433200564c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 11:54:36 +0900 Subject: [PATCH 2635/5608] Remove remnants of user skin PR --- osu.Game/Skinning/SkinManager.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 0e40eb5376..a713933c6e 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -60,9 +60,6 @@ namespace osu.Game.Skinning }; } - private Skin createIfNotExisting(SkinInfo skinInfo) => - GetSkin(Query(s => s.Name == skinInfo.Name) ?? Import(skinInfo).Result); - protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osk"; /// @@ -110,9 +107,6 @@ namespace osu.Game.Skinning /// A instance correlating to the provided . public Skin GetSkin(SkinInfo skinInfo) { - if (skinInfo == null) - return null; - if (skinInfo == SkinInfo.Default) return new DefaultSkin(); From 8fe37d0c43aec1182f9b437ba16cce2103a6a526 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 12:35:44 +0900 Subject: [PATCH 2636/5608] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 0f6e32d664..3854cab34f 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -60,7 +60,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index d791909372..5563f9efeb 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 9fc472bf40..a430ff59ab 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -117,7 +117,7 @@ - + From 9c622680e32a5f21777ffb4aee13acbee1a7fe86 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 12:35:53 +0900 Subject: [PATCH 2637/5608] 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 3854cab34f..2c3c8bcaad 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -61,6 +61,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5563f9efeb..8e6ce2d1ba 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index a430ff59ab..47cc6ec97a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From 84e474826817f394594a0973016492d3bda740d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 12:59:58 +0900 Subject: [PATCH 2638/5608] Remove duplicate getAnimation function and improve namespacing --- osu.Game.Rulesets.Osu/OsuLegacySkin.cs | 236 ------------------ osu.Game.Rulesets.Osu/OsuRuleset.cs | 1 + .../Skinning/LegacyMainCirclePiece.cs | 81 ++++++ .../Skinning/LegacySliderBall.cs | 44 ++++ .../Skinning/OsuLegacySkin.cs | 97 +++++++ osu.Game/Beatmaps/IWorkingBeatmap.cs | 2 +- osu.Game/Screens/Edit/EditorWorkingBeatmap.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 40 +-- osu.Game/Skinning/LegacySkinExtensions.cs | 53 ++++ 9 files changed, 279 insertions(+), 277 deletions(-) delete mode 100644 osu.Game.Rulesets.Osu/OsuLegacySkin.cs create mode 100644 osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs create mode 100644 osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs create mode 100644 osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs create mode 100644 osu.Game/Skinning/LegacySkinExtensions.cs diff --git a/osu.Game.Rulesets.Osu/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/OsuLegacySkin.cs deleted file mode 100644 index d4b00ab911..0000000000 --- a/osu.Game.Rulesets.Osu/OsuLegacySkin.cs +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osu.Framework.Allocation; -using osu.Framework.Audio.Sample; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Animations; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; -using osu.Game.Audio; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; -using osu.Game.Skinning; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Rulesets.Osu -{ - public class OsuLegacySkin : ISkin - { - private readonly ISkin source; - - private Lazy configuration; - - private Lazy hasHitCircle; - - /// - /// On osu-stable, hitcircles have 5 pixels of transparent padding on each side to allow for shadows etc. - /// Their hittable area is 128px, but the actual circle portion is 118px. - /// We must account for some gameplay elements such as slider bodies, where this padding is not present. - /// - private const float legacy_circle_radius = 64 - 5; - - public OsuLegacySkin(ISkinSource source) - { - this.source = source; - - source.SourceChanged += sourceChanged; - sourceChanged(); - } - - private void sourceChanged() - { - // these need to be lazy in order to ensure they aren't called before the dependencies have been loaded into our source. - configuration = new Lazy(() => - { - var config = new SkinConfiguration(); - if (hasHitCircle.Value) - config.SliderPathRadius = legacy_circle_radius; - - // defaults should only be applied for non-beatmap skins (which are parsed via this constructor). - config.CustomColours["SliderBall"] = - source.GetValue(s => s.CustomColours.TryGetValue("SliderBall", out var val) ? val : (Color4?)null) - ?? new Color4(2, 170, 255, 255); - - return config; - }); - - hasHitCircle = new Lazy(() => source.GetTexture("hitcircle") != null); - } - - private const double default_frame_time = 1000 / 60d; - - public Drawable GetDrawableComponent(string componentName) - { - switch (componentName) - { - case "Play/osu/sliderball": - var sliderBallContent = getAnimation("sliderb", true, true, ""); - - if (sliderBallContent != null) - { - var size = sliderBallContent.Size; - - sliderBallContent.RelativeSizeAxes = Axes.Both; - sliderBallContent.Size = Vector2.One; - - return new LegacySliderBall(sliderBallContent) - { - Size = size - }; - } - - return null; - - case "Play/osu/hitcircle": - if (hasHitCircle.Value) - return new LegacyMainCirclePiece(); - - return null; - } - - return null; - } - - private Drawable getAnimation(string componentName, bool animatable, bool looping, string animationSeparator = "-") - { - Texture texture; - - Texture getFrameTexture(int frame) => source.GetTexture($"{componentName}{animationSeparator}{frame}"); - - TextureAnimation animation = null; - - if (animatable) - { - for (int i = 0;; i++) - { - if ((texture = getFrameTexture(i)) == null) - break; - - if (animation == null) - animation = new TextureAnimation - { - DefaultFrameLength = default_frame_time, - Repeat = looping - }; - - animation.AddFrame(texture); - } - } - - if (animation != null) - return animation; - - if ((texture = source.GetTexture(componentName)) != null) - return new Sprite { Texture = texture }; - - return null; - } - - public Texture GetTexture(string componentName) => null; - - public SampleChannel GetSample(ISampleInfo sample) => null; - - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration - => configuration.Value is TConfiguration conf ? query.Invoke(conf) : default; - - public class LegacySliderBall : CompositeDrawable - { - private readonly Drawable animationContent; - - public LegacySliderBall(Drawable animationContent) - { - this.animationContent = animationContent; - } - - [BackgroundDependencyLoader] - private void load(ISkinSource skin, DrawableHitObject drawableObject) - { - animationContent.Colour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Color4.White; - - InternalChildren = new[] - { - new Sprite - { - Texture = skin.GetTexture("sliderb-nd"), - Colour = new Color4(5, 5, 5, 255), - }, - animationContent, - new Sprite - { - Texture = skin.GetTexture("sliderb-spec"), - Blending = BlendingParameters.Additive, - }, - }; - } - } - - public class LegacyMainCirclePiece : CompositeDrawable - { - public LegacyMainCirclePiece() - { - Size = new Vector2(128); - } - - private readonly IBindable state = new Bindable(); - - private readonly Bindable accentColour = new Bindable(); - - [BackgroundDependencyLoader] - private void load(DrawableHitObject drawableObject, ISkinSource skin) - { - Sprite hitCircleSprite; - - InternalChildren = new Drawable[] - { - hitCircleSprite = new Sprite - { - Texture = skin.GetTexture("hitcircle"), - Colour = drawableObject.AccentColour.Value, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - new SkinnableSpriteText("Play/osu/number-text", _ => new OsuSpriteText - { - Font = OsuFont.Numeric.With(size: 40), - UseFullGlyphHeight = false, - }, confineMode: ConfineMode.NoScaling) - { - Text = (((IHasComboInformation)drawableObject.HitObject).IndexInCurrentCombo + 1).ToString() - }, - new Sprite - { - Texture = skin.GetTexture("hitcircleoverlay"), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } - }; - - state.BindTo(drawableObject.State); - state.BindValueChanged(updateState, true); - - accentColour.BindTo(drawableObject.AccentColour); - accentColour.BindValueChanged(colour => hitCircleSprite.Colour = colour.NewValue, true); - } - - private void updateState(ValueChangedEvent state) - { - const double legacy_fade_duration = 240; - - switch (state.NewValue) - { - case ArmedState.Hit: - this.FadeOut(legacy_fade_duration, Easing.Out); - this.ScaleTo(1.4f, legacy_fade_duration, Easing.Out); - break; - } - } - } - } -} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index e2c64bbedf..49676933e1 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -23,6 +23,7 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Difficulty; +using osu.Game.Rulesets.Osu.Skinning; using osu.Game.Scoring; using osu.Game.Skinning; diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs new file mode 100644 index 0000000000..a7906ddd24 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs @@ -0,0 +1,81 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Skinning +{ + public class LegacyMainCirclePiece : CompositeDrawable + { + public LegacyMainCirclePiece() + { + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); + } + + private readonly IBindable state = new Bindable(); + + private readonly Bindable accentColour = new Bindable(); + + [BackgroundDependencyLoader] + private void load(DrawableHitObject drawableObject, ISkinSource skin) + { + Sprite hitCircleSprite; + + InternalChildren = new Drawable[] + { + hitCircleSprite = new Sprite + { + Texture = skin.GetTexture("hitcircle"), + Colour = drawableObject.AccentColour.Value, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new SkinnableSpriteText("Play/osu/number-text", _ => new OsuSpriteText + { + Font = OsuFont.Numeric.With(size: 40), + UseFullGlyphHeight = false, + }, confineMode: ConfineMode.NoScaling) + { + Text = (((IHasComboInformation)drawableObject.HitObject).IndexInCurrentCombo + 1).ToString() + }, + new Sprite + { + Texture = skin.GetTexture("hitcircleoverlay"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + + state.BindTo(drawableObject.State); + state.BindValueChanged(updateState, true); + + accentColour.BindTo(drawableObject.AccentColour); + accentColour.BindValueChanged(colour => hitCircleSprite.Colour = colour.NewValue, true); + } + + private void updateState(ValueChangedEvent state) + { + const double legacy_fade_duration = 240; + + switch (state.NewValue) + { + case ArmedState.Hit: + this.FadeOut(legacy_fade_duration, Easing.Out); + this.ScaleTo(1.4f, legacy_fade_duration, Easing.Out); + break; + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs new file mode 100644 index 0000000000..ec838c596d --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs @@ -0,0 +1,44 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Skinning; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Skinning +{ + public class LegacySliderBall : CompositeDrawable + { + private readonly Drawable animationContent; + + public LegacySliderBall(Drawable animationContent) + { + this.animationContent = animationContent; + } + + [BackgroundDependencyLoader] + private void load(ISkinSource skin, DrawableHitObject drawableObject) + { + animationContent.Colour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Color4.White; + + InternalChildren = new[] + { + new Sprite + { + Texture = skin.GetTexture("sliderb-nd"), + Colour = new Color4(5, 5, 5, 255), + }, + animationContent, + new Sprite + { + Texture = skin.GetTexture("sliderb-spec"), + Blending = BlendingParameters.Additive, + }, + }; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs new file mode 100644 index 0000000000..927cbc5d2f --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs @@ -0,0 +1,97 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Audio.Sample; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Textures; +using osu.Game.Audio; +using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Skinning +{ + public class OsuLegacySkin : ISkin + { + private readonly ISkin source; + + private Lazy configuration; + + private Lazy hasHitCircle; + + /// + /// On osu-stable, hitcircles have 5 pixels of transparent padding on each side to allow for shadows etc. + /// Their hittable area is 128px, but the actual circle portion is 118px. + /// We must account for some gameplay elements such as slider bodies, where this padding is not present. + /// + private const float legacy_circle_radius = 64 - 5; + + public OsuLegacySkin(ISkinSource source) + { + this.source = source; + + source.SourceChanged += sourceChanged; + sourceChanged(); + } + + private void sourceChanged() + { + // these need to be lazy in order to ensure they aren't called before the dependencies have been loaded into our source. + configuration = new Lazy(() => + { + var config = new SkinConfiguration(); + if (hasHitCircle.Value) + config.SliderPathRadius = legacy_circle_radius; + + // defaults should only be applied for non-beatmap skins (which are parsed via this constructor). + config.CustomColours["SliderBall"] = + source.GetValue(s => s.CustomColours.TryGetValue("SliderBall", out var val) ? val : (Color4?)null) + ?? new Color4(2, 170, 255, 255); + + return config; + }); + + hasHitCircle = new Lazy(() => source.GetTexture("hitcircle") != null); + } + + public Drawable GetDrawableComponent(string componentName) + { + switch (componentName) + { + case "Play/osu/sliderball": + var sliderBallContent = this.GetAnimation("sliderb", true, true, ""); + + if (sliderBallContent != null) + { + var size = sliderBallContent.Size; + + sliderBallContent.RelativeSizeAxes = Axes.Both; + sliderBallContent.Size = Vector2.One; + + return new LegacySliderBall(sliderBallContent) + { + Size = size + }; + } + + return null; + + case "Play/osu/hitcircle": + if (hasHitCircle.Value) + return new LegacyMainCirclePiece(); + + return null; + } + + return null; + } + + public Texture GetTexture(string componentName) => null; + + public SampleChannel GetSample(ISampleInfo sample) => null; + + public TValue GetValue(Func query) where TConfiguration : SkinConfiguration + => configuration.Value is TConfiguration conf ? query.Invoke(conf) : default; + } +} diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index aea3751bb5..44071d9cc1 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -43,7 +43,7 @@ namespace osu.Game.Beatmaps /// /// Retrieves the which this provides. /// - Skin Skin { get; } + ISkin Skin { get; } /// /// Constructs a playable from using the applicable converters for a specific . diff --git a/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs b/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs index 45fca493a2..299059407c 100644 --- a/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.Edit public Storyboard Storyboard => workingBeatmap.Storyboard; - public Skin Skin => workingBeatmap.Skin; + public ISkin Skin => workingBeatmap.Skin; public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList mods) => playableBeatmap; } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 8dfefcfa1b..d567e48d9a 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -10,7 +10,6 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; -using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; @@ -60,8 +59,6 @@ namespace osu.Game.Skinning Samples?.Dispose(); } - private const double default_frame_time = 1000 / 60d; - public override Drawable GetDrawableComponent(string componentName) { bool animatable = false; @@ -114,7 +111,7 @@ namespace osu.Game.Skinning }; } - return getAnimation(componentName, animatable, looping); + return this.GetAnimation(componentName, animatable, looping); } public override Texture GetTexture(string componentName) @@ -161,41 +158,6 @@ namespace osu.Game.Skinning return componentName.StartsWith("Gameplay/taiko/") ? "taiko-" + lastPiece : lastPiece; } - private Drawable getAnimation(string componentName, bool animatable, bool looping, string animationSeparator = "-") - { - Texture texture; - - Texture getFrameTexture(int frame) => GetTexture($"{componentName}{animationSeparator}{frame}"); - - TextureAnimation animation = null; - - if (animatable) - { - for (int i = 0;; i++) - { - if ((texture = getFrameTexture(i)) == null) - break; - - if (animation == null) - animation = new TextureAnimation - { - DefaultFrameLength = default_frame_time, - Repeat = looping - }; - - animation.AddFrame(texture); - } - } - - if (animation != null) - return animation; - - if ((texture = GetTexture(componentName)) != null) - return new Sprite { Texture = texture }; - - return null; - } - protected class LegacySkinResourceStore : IResourceStore where T : INamedFileInfo { diff --git a/osu.Game/Skinning/LegacySkinExtensions.cs b/osu.Game/Skinning/LegacySkinExtensions.cs new file mode 100644 index 0000000000..c5582af836 --- /dev/null +++ b/osu.Game/Skinning/LegacySkinExtensions.cs @@ -0,0 +1,53 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Animations; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; + +namespace osu.Game.Skinning +{ + public static class LegacySkinExtensions + { + public static Drawable GetAnimation(this ISkin source, string componentName, bool animatable, bool looping, string animationSeparator = "-") + { + const double default_frame_time = 1000 / 60d; + + Texture texture; + + Texture getFrameTexture(int frame) => source.GetTexture($"{componentName}{animationSeparator}{frame}"); + + TextureAnimation animation = null; + + if (animatable) + { + for (int i = 0;; i++) + { + if ((texture = getFrameTexture(i)) == null) + break; + + if (animation == null) + animation = new TextureAnimation + { + DefaultFrameLength = default_frame_time, + Repeat = looping + }; + + animation.AddFrame(texture); + } + } + + if (animation != null) + return animation; + + if ((texture = source.GetTexture(componentName)) != null) + return new Sprite + { + Texture = texture + }; + + return null; + } + } +} From 7bba8ca14bb92bea3f1d6a707ba1c85cc8f8f9a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 13:04:11 +0900 Subject: [PATCH 2639/5608] Split out nested classes --- osu.Game/Skinning/LegacySkin.cs | 112 ------------------- osu.Game/Skinning/LegacySkinResourceStore.cs | 76 +++++++++++++ osu.Game/Skinning/LegacySpriteText.cs | 53 +++++++++ 3 files changed, 129 insertions(+), 112 deletions(-) create mode 100644 osu.Game/Skinning/LegacySkinResourceStore.cs create mode 100644 osu.Game/Skinning/LegacySpriteText.cs diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index d567e48d9a..0151a211d3 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -1,11 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using System.Collections.Generic; using System.IO; using System.Linq; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -14,11 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; -using osu.Framework.Text; using osu.Game.Audio; -using osu.Game.Database; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.UI; using osuTK; using osuTK.Graphics; @@ -158,111 +151,6 @@ namespace osu.Game.Skinning return componentName.StartsWith("Gameplay/taiko/") ? "taiko-" + lastPiece : lastPiece; } - protected class LegacySkinResourceStore : IResourceStore - where T : INamedFileInfo - { - private readonly IHasFiles source; - private readonly IResourceStore underlyingStore; - - private string getPathForFile(string filename) - { - bool hasExtension = filename.Contains('.'); - - var file = source.Files.Find(f => - string.Equals(hasExtension ? f.Filename : Path.ChangeExtension(f.Filename, null), filename, StringComparison.InvariantCultureIgnoreCase)); - return file?.FileInfo.StoragePath; - } - - public LegacySkinResourceStore(IHasFiles source, IResourceStore underlyingStore) - { - this.source = source; - this.underlyingStore = underlyingStore; - } - - public Stream GetStream(string name) - { - string path = getPathForFile(name); - return path == null ? null : underlyingStore.GetStream(path); - } - - public IEnumerable GetAvailableResources() => source.Files.Select(f => f.Filename); - - byte[] IResourceStore.Get(string name) => GetAsync(name).Result; - - public Task GetAsync(string name) - { - string path = getPathForFile(name); - return path == null ? Task.FromResult(null) : underlyingStore.GetAsync(path); - } - - #region IDisposable Support - - private bool isDisposed; - - protected virtual void Dispose(bool disposing) - { - if (!isDisposed) - { - isDisposed = true; - } - } - - ~LegacySkinResourceStore() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - #endregion - } - - private class LegacySpriteText : OsuSpriteText - { - private readonly LegacyGlyphStore glyphStore; - - public LegacySpriteText(ISkin skin, string font) - { - Shadow = false; - UseFullGlyphHeight = false; - - Font = new FontUsage(font, OsuFont.DEFAULT_FONT_SIZE); - glyphStore = new LegacyGlyphStore(skin); - } - - protected override TextBuilder CreateTextBuilder(ITexturedGlyphLookupStore store) => base.CreateTextBuilder(glyphStore); - - private class LegacyGlyphStore : ITexturedGlyphLookupStore - { - private readonly ISkin skin; - - public LegacyGlyphStore(ISkin skin) - { - this.skin = skin; - } - - public ITexturedCharacterGlyph Get(string fontName, char character) - { - var texture = skin.GetTexture($"{fontName}-{character}"); - - if (texture != null) - // Approximate value that brings character sizing roughly in-line with stable - texture.ScaleAdjust *= 18; - - if (texture == null) - return null; - - return new TexturedCharacterGlyph(new CharacterGlyph(character, 0, 0, texture.Width, null), texture, 1f / texture.ScaleAdjust); - } - - public Task GetAsync(string fontName, char character) => Task.Run(() => Get(fontName, character)); - } - } - public class LegacyCursor : CompositeDrawable { public LegacyCursor() diff --git a/osu.Game/Skinning/LegacySkinResourceStore.cs b/osu.Game/Skinning/LegacySkinResourceStore.cs new file mode 100644 index 0000000000..c8912aeb1f --- /dev/null +++ b/osu.Game/Skinning/LegacySkinResourceStore.cs @@ -0,0 +1,76 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using osu.Framework.IO.Stores; +using osu.Game.Database; + +namespace osu.Game.Skinning +{ + public class LegacySkinResourceStore : IResourceStore + where T : INamedFileInfo + { + private readonly IHasFiles source; + private readonly IResourceStore underlyingStore; + + private string getPathForFile(string filename) + { + bool hasExtension = filename.Contains('.'); + + var file = source.Files.Find(f => + string.Equals(hasExtension ? f.Filename : Path.ChangeExtension(f.Filename, null), filename, StringComparison.InvariantCultureIgnoreCase)); + return file?.FileInfo.StoragePath; + } + + public LegacySkinResourceStore(IHasFiles source, IResourceStore underlyingStore) + { + this.source = source; + this.underlyingStore = underlyingStore; + } + + public Stream GetStream(string name) + { + string path = getPathForFile(name); + return path == null ? null : underlyingStore.GetStream(path); + } + + public IEnumerable GetAvailableResources() => source.Files.Select(f => f.Filename); + + byte[] IResourceStore.Get(string name) => GetAsync(name).Result; + + public Task GetAsync(string name) + { + string path = getPathForFile(name); + return path == null ? Task.FromResult(null) : underlyingStore.GetAsync(path); + } + + #region IDisposable Support + + private bool isDisposed; + + protected virtual void Dispose(bool disposing) + { + if (!isDisposed) + { + isDisposed = true; + } + } + + ~LegacySkinResourceStore() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + } +} diff --git a/osu.Game/Skinning/LegacySpriteText.cs b/osu.Game/Skinning/LegacySpriteText.cs new file mode 100644 index 0000000000..dbcec019d6 --- /dev/null +++ b/osu.Game/Skinning/LegacySpriteText.cs @@ -0,0 +1,53 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Threading.Tasks; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Text; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Skinning +{ + public class LegacySpriteText : OsuSpriteText + { + private readonly LegacyGlyphStore glyphStore; + + public LegacySpriteText(ISkin skin, string font) + { + Shadow = false; + UseFullGlyphHeight = false; + + Font = new FontUsage(font, OsuFont.DEFAULT_FONT_SIZE); + glyphStore = new LegacyGlyphStore(skin); + } + + protected override TextBuilder CreateTextBuilder(ITexturedGlyphLookupStore store) => base.CreateTextBuilder(glyphStore); + + private class LegacyGlyphStore : ITexturedGlyphLookupStore + { + private readonly ISkin skin; + + public LegacyGlyphStore(ISkin skin) + { + this.skin = skin; + } + + public ITexturedCharacterGlyph Get(string fontName, char character) + { + var texture = skin.GetTexture($"{fontName}-{character}"); + + if (texture != null) + // Approximate value that brings character sizing roughly in-line with stable + texture.ScaleAdjust *= 18; + + if (texture == null) + return null; + + return new TexturedCharacterGlyph(new CharacterGlyph(character, 0, 0, texture.Width, null), texture, 1f / texture.ScaleAdjust); + } + + public Task GetAsync(string fontName, char character) => Task.Run(() => Get(fontName, character)); + } + } +} From c389a5c798974d33f1b8728b09b99ebdd7e23137 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 13:42:29 +0900 Subject: [PATCH 2640/5608] Move remaining osu-specific implementations to OsuLegacySkin --- .../Skinning/LegacyCursor.cs | 42 +++++++++++ .../Skinning/NonPlayfieldSprite.cs | 28 +++++++ .../Skinning/OsuLegacySkin.cs | 22 ++++++ osu.Game/Skinning/LegacySkin.cs | 73 ------------------- 4 files changed, 92 insertions(+), 73 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs create mode 100644 osu.Game.Rulesets.Osu/Skinning/NonPlayfieldSprite.cs diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs new file mode 100644 index 0000000000..470ba3acae --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursor.cs @@ -0,0 +1,42 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Skinning; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Skinning +{ + public class LegacyCursor : CompositeDrawable + { + public LegacyCursor() + { + Size = new Vector2(50); + + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + } + + [BackgroundDependencyLoader] + private void load(ISkinSource skin) + { + InternalChildren = new Drawable[] + { + new NonPlayfieldSprite + { + Texture = skin.GetTexture("cursormiddle"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new NonPlayfieldSprite + { + Texture = skin.GetTexture("cursor"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/NonPlayfieldSprite.cs b/osu.Game.Rulesets.Osu/Skinning/NonPlayfieldSprite.cs new file mode 100644 index 0000000000..55257106e2 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/NonPlayfieldSprite.cs @@ -0,0 +1,28 @@ +// 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.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Osu.Skinning +{ + /// + /// A sprite which is displayed within the playfield, but historically was not considered part of the playfield. + /// Performs scale adjustment to undo the scale applied by (osu! ruleset specifically). + /// + public class NonPlayfieldSprite : Sprite + { + public override Texture Texture + { + get => base.Texture; + set + { + if (value != null) + // stable "magic ratio". see OsuPlayfieldAdjustmentContainer for full explanation. + value.ScaleAdjust *= 1.6f; + base.Texture = value; + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs index 927cbc5d2f..27bfdc315b 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs @@ -82,6 +82,26 @@ namespace osu.Game.Rulesets.Osu.Skinning return new LegacyMainCirclePiece(); return null; + + case "Play/osu/cursor": + if (GetTexture("cursor") != null) + return new LegacyCursor(); + + return null; + + case "Play/osu/number-text": + + string font = GetValue(config => config.HitCircleFont); + var overlap = GetValue(config => config.HitCircleOverlap); + + return !hasFont(font) + ? null + : new LegacySpriteText(this, font) + { + // Spacing value was reverse-engineered from the ratio of the rendered sprite size in the visual inspector vs the actual texture size + Scale = new Vector2(0.96f), + Spacing = new Vector2(-overlap * 0.89f, 0) + }; } return null; @@ -93,5 +113,7 @@ namespace osu.Game.Rulesets.Osu.Skinning public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => configuration.Value is TConfiguration conf ? query.Invoke(conf) : default; + + private bool hasFont(string fontName) => GetTexture($"{fontName}-0") != null; } } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 0151a211d3..9a47e01f4e 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -3,17 +3,12 @@ using System.IO; using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Game.Audio; -using osu.Game.Rulesets.UI; -using osuTK; using osuTK.Graphics; namespace osu.Game.Skinning @@ -59,12 +54,6 @@ namespace osu.Game.Skinning switch (componentName) { - case "Play/osu/cursor": - if (GetTexture("cursor") != null) - return new LegacyCursor(); - - return null; - case "Play/osu/sliderfollowcircle": animatable = true; break; @@ -92,16 +81,6 @@ namespace osu.Game.Skinning animatable = true; looping = false; break; - - case "Play/osu/number-text": - return !hasFont(Configuration.HitCircleFont) - ? null - : new LegacySpriteText(this, Configuration.HitCircleFont) - { - Scale = new Vector2(0.96f), - // Spacing value was reverse-engineered from the ratio of the rendered sprite size in the visual inspector vs the actual texture size - Spacing = new Vector2(-Configuration.HitCircleOverlap * 0.89f, 0) - }; } return this.GetAnimation(componentName, animatable, looping); @@ -143,62 +122,10 @@ namespace osu.Game.Skinning return null; } - private bool hasFont(string fontName) => GetTexture($"{fontName}-0") != null; - private string getFallbackName(string componentName) { string lastPiece = componentName.Split('/').Last(); return componentName.StartsWith("Gameplay/taiko/") ? "taiko-" + lastPiece : lastPiece; } - - public class LegacyCursor : CompositeDrawable - { - public LegacyCursor() - { - Size = new Vector2(50); - - Anchor = Anchor.Centre; - Origin = Anchor.Centre; - } - - [BackgroundDependencyLoader] - private void load(ISkinSource skin) - { - InternalChildren = new Drawable[] - { - new NonPlayfieldSprite - { - Texture = skin.GetTexture("cursormiddle"), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - new NonPlayfieldSprite - { - Texture = skin.GetTexture("cursor"), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } - }; - } - } - - /// - /// A sprite which is displayed within the playfield, but historically was not considered part of the playfield. - /// Performs scale adjustment to undo the scale applied by (osu! ruleset specifically). - /// - private class NonPlayfieldSprite : Sprite - { - public override Texture Texture - { - get => base.Texture; - set - { - if (value != null) - // stable "magic ratio". see OsuPlayfieldAdjustmentContainer for full explanation. - value.ScaleAdjust *= 1.6f; - base.Texture = value; - } - } - } } } From 22e3ad8b9c388ee6b4ff43c9acb3f186a7070264 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 13:58:17 +0900 Subject: [PATCH 2641/5608] Add skinning support to cursor test --- .../Resources/default-skin/cursor@2x.png | Bin 0 -> 28063 bytes .../default-skin/cursormiddle@2x.png | Bin 0 -> 7676 bytes .../TestSceneGameplayCursor.cs | 18 ++++++------------ .../Skinning/OsuLegacySkin.cs | 2 +- 4 files changed, 7 insertions(+), 13 deletions(-) create mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/cursor@2x.png create mode 100755 osu.Game.Rulesets.Osu.Tests/Resources/default-skin/cursormiddle@2x.png diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/cursor@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/cursor@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..75f9ba5ea6637636912004f8a889f5575d830436 GIT binary patch literal 28063 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/cursormiddle@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/default-skin/cursormiddle@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..ebf59c18ba9f62390f49be4bed696a997a51f05c GIT binary patch literal 7676 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 q!@f`~Q0000 RequiredTypes => new[] { typeof(CursorTrail) }; - public CursorContainer Cursor => cursorContainer; - - public bool ProvidingUserCursor => true; - [BackgroundDependencyLoader] private void load() { - Add(cursorContainer = new OsuCursorContainer { RelativeSizeAxes = Axes.Both }); + SetContents(() => new OsuCursorContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + }); } } } diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs index 27bfdc315b..0295a419ac 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs @@ -84,7 +84,7 @@ namespace osu.Game.Rulesets.Osu.Skinning return null; case "Play/osu/cursor": - if (GetTexture("cursor") != null) + if (source.GetTexture("cursor") != null) return new LegacyCursor(); return null; From 8f9fe9923746dfd62231d30dc198bf2458bfa36d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 14:40:36 +0900 Subject: [PATCH 2642/5608] Move SliderFollowCircle implementation --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs | 3 +++ osu.Game/Skinning/LegacySkin.cs | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs index 0295a419ac..3c508f34e0 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs @@ -59,6 +59,9 @@ namespace osu.Game.Rulesets.Osu.Skinning { switch (componentName) { + case "Play/osu/sliderfollowcircle": + return this.GetAnimation(componentName, true, true); + case "Play/osu/sliderball": var sliderBallContent = this.GetAnimation("sliderb", true, true, ""); diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 9a47e01f4e..1572c588e8 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -54,10 +54,6 @@ namespace osu.Game.Skinning switch (componentName) { - case "Play/osu/sliderfollowcircle": - animatable = true; - break; - case "Play/Miss": componentName = "hit0"; animatable = true; From 493fc5d400d616135e94291f6ec6f498cbd971da Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 14:44:36 +0900 Subject: [PATCH 2643/5608] Bring back OsuPlayer test --- .../TestSceneOsuPlayer.cs | 148 +---------------- .../TestSceneSkinFallbacks.cs | 157 ++++++++++++++++++ 2 files changed, 161 insertions(+), 144 deletions(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs index d61378f4f8..1ba027ea4b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs @@ -1,157 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using System.Linq; using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; -using osu.Framework.Timing; -using osu.Game.Audio; -using osu.Game.Beatmaps; -using osu.Game.Configuration; -using osu.Game.Graphics; -using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Screens.Play; -using osu.Game.Skinning; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { - [TestFixture] - public class TestSceneOsuPlayer : PlayerTestScene - { - private readonly TestSource testUserSkin; - private readonly TestSource testBeatmapSkin; - - public TestSceneOsuPlayer() - : base(new OsuRuleset()) + [TestFixture] + public class TestSceneOsuPlayer : PlayerTestScene { - testUserSkin = new TestSource("user"); - testBeatmapSkin = new TestSource("beatmap"); - } - - [Test] - public void TestBeatmapSkinDefault() - { - AddStep("enable user provider", () => testUserSkin.Enabled = true); - - AddStep("enable beatmap skin", () => LocalConfig.Set(OsuSetting.BeatmapSkins, true)); - checkNextHitObject("beatmap"); - - AddStep("disable beatmap skin", () => LocalConfig.Set(OsuSetting.BeatmapSkins, false)); - checkNextHitObject("user"); - - AddStep("disable user provider", () => testUserSkin.Enabled = false); - checkNextHitObject(null); - } - - private void checkNextHitObject(string skin) => - AddUntilStep($"check skin from {skin}", () => + public TestSceneOsuPlayer() + : base(new OsuRuleset()) { - var firstObject = ((TestPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.OfType().FirstOrDefault(); - - if (firstObject == null) - return false; - - var skinnable = firstObject.ApproachCircle.Child as SkinnableDrawable; - - if (skin == null && skinnable?.Drawable is Sprite) - // check for default skin provider - return true; - - var text = skinnable?.Drawable as SpriteText; - - return text?.Text == skin; - }); - - [Resolved] - private AudioManager audio { get; set; } - - protected override Player CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin); - - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) => new CustomSkinWorkingBeatmap(beatmap, Clock, audio, testBeatmapSkin); - - public class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap - { - private readonly ISkinSource skin; - - public CustomSkinWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock frameBasedClock, AudioManager audio, ISkinSource skin) - : base(beatmap, frameBasedClock, audio) - { - this.skin = skin; - } - - protected override ISkin GetSkin() => skin; - } - - public class SkinProvidingPlayer : TestPlayer - { - private readonly TestSource userSkin; - - public SkinProvidingPlayer(TestSource userSkin) - { - this.userSkin = userSkin; - } - - private DependencyContainer dependencies; - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - - dependencies.CacheAs(userSkin); - - return dependencies; } } - - public class TestSource : ISkinSource - { - private readonly string identifier; - - public TestSource(string identifier) - { - this.identifier = identifier; - } - - public Drawable GetDrawableComponent(string componentName) - { - if (!enabled) return null; - - return new SpriteText - { - Text = identifier, - Font = OsuFont.Default.With(size: 30), - }; - } - - public Texture GetTexture(string componentName) => null; - - public SampleChannel GetSample(ISampleInfo sampleInfo) => null; - - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => default; - - public event Action SourceChanged; - - private bool enabled = true; - - public bool Enabled - { - get => enabled; - set - { - if (value == enabled) - return; - - enabled = value; - SourceChanged?.Invoke(); - } - } - } - } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs new file mode 100644 index 0000000000..24d0b39bed --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -0,0 +1,157 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Timing; +using osu.Game.Audio; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Graphics; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Screens.Play; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Osu.Tests +{ + [TestFixture] + public class TestSceneSkinFallbacks : PlayerTestScene + { + private readonly TestSource testUserSkin; + private readonly TestSource testBeatmapSkin; + + public TestSceneSkinFallbacks() + : base(new OsuRuleset()) + { + testUserSkin = new TestSource("user"); + testBeatmapSkin = new TestSource("beatmap"); + } + + [Test] + public void TestBeatmapSkinDefault() + { + AddStep("enable user provider", () => testUserSkin.Enabled = true); + + AddStep("enable beatmap skin", () => LocalConfig.Set(OsuSetting.BeatmapSkins, true)); + checkNextHitObject("beatmap"); + + AddStep("disable beatmap skin", () => LocalConfig.Set(OsuSetting.BeatmapSkins, false)); + checkNextHitObject("user"); + + AddStep("disable user provider", () => testUserSkin.Enabled = false); + checkNextHitObject(null); + } + + private void checkNextHitObject(string skin) => + AddUntilStep($"check skin from {skin}", () => + { + var firstObject = ((TestPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.OfType().FirstOrDefault(); + + if (firstObject == null) + return false; + + var skinnable = firstObject.ApproachCircle.Child as SkinnableDrawable; + + if (skin == null && skinnable?.Drawable is Sprite) + // check for default skin provider + return true; + + var text = skinnable?.Drawable as SpriteText; + + return text?.Text == skin; + }); + + [Resolved] + private AudioManager audio { get; set; } + + protected override Player CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin); + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) => new CustomSkinWorkingBeatmap(beatmap, Clock, audio, testBeatmapSkin); + + public class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap + { + private readonly ISkinSource skin; + + public CustomSkinWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock frameBasedClock, AudioManager audio, ISkinSource skin) + : base(beatmap, frameBasedClock, audio) + { + this.skin = skin; + } + + protected override ISkin GetSkin() => skin; + } + + public class SkinProvidingPlayer : TestPlayer + { + private readonly TestSource userSkin; + + public SkinProvidingPlayer(TestSource userSkin) + { + this.userSkin = userSkin; + } + + private DependencyContainer dependencies; + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + + dependencies.CacheAs(userSkin); + + return dependencies; + } + } + + public class TestSource : ISkinSource + { + private readonly string identifier; + + public TestSource(string identifier) + { + this.identifier = identifier; + } + + public Drawable GetDrawableComponent(string componentName) + { + if (!enabled) return null; + + return new SpriteText + { + Text = identifier, + Font = OsuFont.Default.With(size: 30), + }; + } + + public Texture GetTexture(string componentName) => null; + + public SampleChannel GetSample(ISampleInfo sampleInfo) => null; + + public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => default; + + public event Action SourceChanged; + + private bool enabled = true; + + public bool Enabled + { + get => enabled; + set + { + if (value == enabled) + return; + + enabled = value; + SourceChanged?.Invoke(); + } + } + } + } +} From c3fb4b9099c9f7dd7e0bd71f6ae14a61d66c6f3d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 14:51:47 +0900 Subject: [PATCH 2644/5608] Fix test failing --- osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index 24d0b39bed..731b0a84e9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Osu.Tests private void checkNextHitObject(string skin) => AddUntilStep($"check skin from {skin}", () => { - var firstObject = ((TestPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.OfType().FirstOrDefault(); + var firstObject = ((TestPlayer)Player).DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.OfType().FirstOrDefault(); if (firstObject == null) return false; From ae05faa6d2e96d49c0de9d2791d0bbb4d12c4e21 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 14:54:46 +0900 Subject: [PATCH 2645/5608] Fix indentation --- osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs index 1ba027ea4b..0a33b09ba8 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs @@ -6,12 +6,12 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests { - [TestFixture] - public class TestSceneOsuPlayer : PlayerTestScene + [TestFixture] + public class TestSceneOsuPlayer : PlayerTestScene + { + public TestSceneOsuPlayer() + : base(new OsuRuleset()) { - public TestSceneOsuPlayer() - : base(new OsuRuleset()) - { - } } + } } From a15828ab25d6b727618fe4159fbadacb90fc9de5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 14:39:02 +0900 Subject: [PATCH 2646/5608] Introduce the concept of SkinComponents Removes reliance on string lookups and better defines elements for introduction into database --- .../TestSceneCatcher.cs | 6 ++-- osu.Game.Rulesets.Catch/CatchRuleset.cs | 4 ++- osu.Game.Rulesets.Catch/CatchSkinComponent.cs | 19 ++++++++++++ .../CatchSkinComponents.cs | 10 +++++++ osu.Game.Rulesets.Catch/UI/CatcherSprite.cs | 2 +- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 4 ++- osu.Game.Rulesets.Mania/ManiaSkinComponent.cs | 19 ++++++++++++ .../ManiaSkinComponents.cs | 9 ++++++ .../TestSceneSkinFallbacks.cs | 2 +- .../Drawables/Connections/FollowPoint.cs | 2 +- .../Objects/Drawables/DrawableHitCircle.cs | 2 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- .../Objects/Drawables/DrawableSliderTick.cs | 2 +- .../Drawables/Pieces/ApproachCircle.cs | 6 ++-- .../Objects/Drawables/Pieces/ExplodePiece.cs | 5 ++-- .../Objects/Drawables/Pieces/FlashPiece.cs | 5 ++-- .../Objects/Drawables/Pieces/GlowPiece.cs | 7 ++--- .../Objects/Drawables/Pieces/NumberPiece.cs | 6 ++-- .../Objects/Drawables/Pieces/RingPiece.cs | 5 ++-- .../Objects/Drawables/Pieces/SliderBall.cs | 4 +-- osu.Game.Rulesets.Osu/OsuRuleset.cs | 4 ++- osu.Game.Rulesets.Osu/OsuSkinComponent.cs | 19 ++++++++++++ osu.Game.Rulesets.Osu/OsuSkinComponents.cs | 18 +++++++++++ .../Skinning/LegacyMainCirclePiece.cs | 2 +- .../Skinning/OsuLegacySkin.cs | 22 +++++++------- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs | 2 +- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 4 ++- osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs | 19 ++++++++++++ .../TaikoSkinComponents.cs | 9 ++++++ .../Gameplay/TestSceneSkinnableDrawable.cs | 30 ++++++++++++++----- .../Rulesets/Judgements/DrawableJudgement.cs | 2 +- .../Skinning/BeatmapSkinProvidingContainer.cs | 2 +- osu.Game/Skinning/DefaultSkin.cs | 4 +-- osu.Game/Skinning/ISkin.cs | 2 +- osu.Game/Skinning/ISkinComponent.cs | 10 +++++++ osu.Game/Skinning/LegacySkin.cs | 29 +++++------------- osu.Game/Skinning/PlaySkinComponent.cs | 23 ++++++++++++++ osu.Game/Skinning/Skin.cs | 4 +-- osu.Game/Skinning/SkinManager.cs | 4 +-- osu.Game/Skinning/SkinProvidingContainer.cs | 8 ++--- osu.Game/Skinning/SkinnableDrawable.cs | 20 ++++++------- osu.Game/Skinning/SkinnableSprite.cs | 6 ++-- osu.Game/Skinning/SkinnableSpriteText.cs | 4 +-- 43 files changed, 264 insertions(+), 104 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/CatchSkinComponent.cs create mode 100644 osu.Game.Rulesets.Catch/CatchSkinComponents.cs create mode 100644 osu.Game.Rulesets.Mania/ManiaSkinComponent.cs create mode 100644 osu.Game.Rulesets.Mania/ManiaSkinComponents.cs create mode 100644 osu.Game.Rulesets.Osu/OsuSkinComponent.cs create mode 100644 osu.Game.Rulesets.Osu/OsuSkinComponents.cs create mode 100644 osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs create mode 100644 osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs create mode 100644 osu.Game/Skinning/ISkinComponent.cs create mode 100644 osu.Game/Skinning/PlaySkinComponent.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 406c0af28d..13286f4524 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.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 NUnit.Framework; @@ -82,9 +82,9 @@ namespace osu.Game.Rulesets.Catch.Tests remove { } } - public Drawable GetDrawableComponent(string componentName) + public Drawable GetDrawableComponent(ISkinComponent component) { - switch (componentName) + switch (component.LookupName) { case "Play/Catch/fruit-catcher-idle": return new CatcherCustomSkin(); diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 71e05083be..cd2f8d56af 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -27,6 +27,8 @@ namespace osu.Game.Rulesets.Catch public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); + public const string SHORT_NAME = "catch"; + public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] { new KeyBinding(InputKey.Z, CatchAction.MoveLeft), @@ -117,7 +119,7 @@ namespace osu.Game.Rulesets.Catch public override string Description => "osu!catch"; - public override string ShortName => "fruits"; + public override string ShortName => SHORT_NAME; public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetCatch }; diff --git a/osu.Game.Rulesets.Catch/CatchSkinComponent.cs b/osu.Game.Rulesets.Catch/CatchSkinComponent.cs new file mode 100644 index 0000000000..620720310f --- /dev/null +++ b/osu.Game.Rulesets.Catch/CatchSkinComponent.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Catch +{ + public class CatchSkinComponent : PlaySkinComponent + { + public CatchSkinComponent(CatchSkinComponents component) + : base(component) + { + } + + protected override string RulesetPrefix => CatchRuleset.SHORT_NAME; + + protected override string ComponentName => Component.ToString().ToLower(); + } +} diff --git a/osu.Game.Rulesets.Catch/CatchSkinComponents.cs b/osu.Game.Rulesets.Catch/CatchSkinComponents.cs new file mode 100644 index 0000000000..c03fe42af7 --- /dev/null +++ b/osu.Game.Rulesets.Catch/CatchSkinComponents.cs @@ -0,0 +1,10 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Catch +{ + public enum CatchSkinComponents + { + Catcher + } +} diff --git a/osu.Game.Rulesets.Catch/UI/CatcherSprite.cs b/osu.Game.Rulesets.Catch/UI/CatcherSprite.cs index c0c1952064..1c2fe3517a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherSprite.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherSprite.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.UI [BackgroundDependencyLoader] private void load() { - InternalChild = new SkinnableSprite(@"Play/Catch/fruit-catcher-idle") + InternalChild = new SkinnableSprite(new CatchSkinComponent(CatchSkinComponents.Catcher)) { RelativeSizeAxes = Axes.Both, Anchor = Anchor.TopCentre, diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 0de86c2149..0c4e7d4858 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -35,6 +35,8 @@ namespace osu.Game.Rulesets.Mania public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score); + public const string SHORT_NAME = "mania"; + public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this); public override IEnumerable ConvertLegacyMods(LegacyMods mods) @@ -163,7 +165,7 @@ namespace osu.Game.Rulesets.Mania public override string Description => "osu!mania"; - public override string ShortName => "mania"; + public override string ShortName => SHORT_NAME; public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetMania }; diff --git a/osu.Game.Rulesets.Mania/ManiaSkinComponent.cs b/osu.Game.Rulesets.Mania/ManiaSkinComponent.cs new file mode 100644 index 0000000000..72a3ce7ad5 --- /dev/null +++ b/osu.Game.Rulesets.Mania/ManiaSkinComponent.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Mania +{ + public class ManiaSkinComponent : PlaySkinComponent + { + public ManiaSkinComponent(ManiaSkinComponents component) + : base(component) + { + } + + protected override string RulesetPrefix => ManiaRuleset.SHORT_NAME; + + protected override string ComponentName => Component.ToString().ToLower(); + } +} diff --git a/osu.Game.Rulesets.Mania/ManiaSkinComponents.cs b/osu.Game.Rulesets.Mania/ManiaSkinComponents.cs new file mode 100644 index 0000000000..6d85816e5a --- /dev/null +++ b/osu.Game.Rulesets.Mania/ManiaSkinComponents.cs @@ -0,0 +1,9 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Mania +{ + public enum ManiaSkinComponents + { + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index 731b0a84e9..fe73e7c861 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -119,7 +119,7 @@ namespace osu.Game.Rulesets.Osu.Tests this.identifier = identifier; } - public Drawable GetDrawableComponent(string componentName) + public Drawable GetDrawableComponent(ISkinComponent component) { if (!enabled) return null; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index 523e911434..89ffddf4cb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { Origin = Anchor.Centre; - Child = new SkinnableDrawable("Play/osu/followpoint", _ => new Container + Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.FollowPoint), _ => new Container { Masking = true, AutoSizeAxes = Axes.Both, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 0af278f6a4..22b12be030 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return true; }, }, - mainContent = new SkinnableDrawable("Play/osu/hitcircle", _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)), + mainContent = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.HitCircle), _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)), ApproachCircle = new ApproachCircle { Alpha = 0, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 1db1eec33e..50187781f6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Blending = BlendingParameters.Additive; Origin = Anchor.Centre; - InternalChild = scaleContainer = new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon + InternalChild = scaleContainer = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.ReverseArrow), _ => new SpriteIcon { RelativeSizeAxes = Axes.Both, Icon = FontAwesome.Solid.ChevronRight, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index 653e73ac3f..c5fa5f0af5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Origin = Anchor.Centre; - InternalChild = scaleContainer = new SkinnableDrawable("Play/osu/sliderscorepoint", _ => new CircularContainer + InternalChild = scaleContainer = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderScorePoint), _ => new CircularContainer { Masking = true, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs index 5813197336..c17c276205 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs @@ -31,13 +31,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private class SkinnableApproachCircle : SkinnableSprite { public SkinnableApproachCircle() - : base("Play/osu/approachcircle") + : base(new OsuSkinComponent(OsuSkinComponents.ApproachCircle)) { } - protected override Drawable CreateDefault(string name) + protected override Drawable CreateDefault(ISkinComponent component) { - var drawable = base.CreateDefault(name); + var drawable = base.CreateDefault(component); // account for the sprite being used for the default approach circle being taken from stable, // when hitcircles have 5px padding on each size. this should be removed if we update the sprite. diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs index 1d21347cba..6381ddca69 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs @@ -3,7 +3,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Skinning; using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces @@ -20,12 +19,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Blending = BlendingParameters.Additive; Alpha = 0; - Child = new SkinnableDrawable("Play/osu/hitcircle-explode", _ => new TrianglesPiece + Child = new TrianglesPiece { Blending = BlendingParameters.Additive, RelativeSizeAxes = Axes.Both, Alpha = 0.2f, - }, s => s.GetTexture("Play/osu/hitcircle") == null); + }; } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs index 1e3af567fe..038a2299e9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK; using osu.Framework.Graphics.Shapes; -using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { @@ -21,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Blending = BlendingParameters.Additive; Alpha = 0; - Child = new SkinnableDrawable("Play/osu/hitcircle-flash", name => new CircularContainer + Child = new CircularContainer { Masking = true, RelativeSizeAxes = Axes.Both, @@ -29,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { RelativeSizeAxes = Axes.Both } - }, s => s.GetTexture("Play/osu/hitcircle") == null); + }; } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs index a36d9e96c8..00188689dd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { @@ -22,14 +21,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces [BackgroundDependencyLoader] private void load(TextureStore textures) { - Child = new SkinnableDrawable("Play/osu/ring-glow", name => new Sprite + Child = new Sprite { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Texture = textures.Get(name), + Texture = textures.Get("ring-glow"), Blending = BlendingParameters.Additive, Alpha = 0.5f - }, s => s.GetTexture("Play/osu/hitcircle") == null); + }; } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs index e8dc63abca..62c4ba5ee3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Children = new Drawable[] { - new SkinnableDrawable("Play/osu/number-glow", name => new CircularContainer + new CircularContainer { Masking = true, Origin = Anchor.Centre, @@ -41,8 +41,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Colour = Color4.White.Opacity(0.5f), }, Child = new Box() - }, s => s.GetTexture("Play/osu/hitcircle") == null), - number = new SkinnableSpriteText("Play/osu/number-text", _ => new OsuSpriteText + }, + number = new SkinnableSpriteText(new OsuSkinComponent(OsuSkinComponents.HitCircleText), _ => new OsuSpriteText { Font = OsuFont.Numeric.With(size: 40), UseFullGlyphHeight = false, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs index 575f2c92c5..c97b74756a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics.Containers; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { @@ -19,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Anchor = Anchor.Centre; Origin = Anchor.Centre; - InternalChild = new SkinnableDrawable("Play/osu/hitcircleoverlay", _ => new Container + InternalChild = new Container { Masking = true, CornerRadius = Size.X / 2, @@ -35,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces RelativeSizeAxes = Axes.Both } } - }); + }; } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 329aed7b81..7c871c6ccd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Anchor = Anchor.Centre, RelativeSizeAxes = Axes.Both, Alpha = 0, - Child = new SkinnableDrawable("Play/osu/sliderfollowcircle", _ => new DefaultFollowCircle()), + Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderFollowCircle), _ => new DefaultFollowCircle()), }, new CircularContainer { @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Child = new Container { RelativeSizeAxes = Axes.Both, - Child = new SkinnableDrawable("Play/osu/sliderball", _ => new DefaultSliderBall()), + Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBall), _ => new DefaultSliderBall()), } } }; diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 49676933e1..27899ab56e 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -35,6 +35,8 @@ namespace osu.Game.Rulesets.Osu public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap); + public const string SHORT_NAME = "osu"; + public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] { new KeyBinding(InputKey.Z, OsuAction.LeftButton), @@ -161,7 +163,7 @@ namespace osu.Game.Rulesets.Osu public override string Description => "osu!"; - public override string ShortName => "osu"; + public override string ShortName => SHORT_NAME; public override RulesetSettingsSubsection CreateSettings() => new OsuSettingsSubsection(this); diff --git a/osu.Game.Rulesets.Osu/OsuSkinComponent.cs b/osu.Game.Rulesets.Osu/OsuSkinComponent.cs new file mode 100644 index 0000000000..ef0df6cbda --- /dev/null +++ b/osu.Game.Rulesets.Osu/OsuSkinComponent.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Osu +{ + public class OsuSkinComponent : PlaySkinComponent + { + public OsuSkinComponent(OsuSkinComponents component) + : base(component) + { + } + + protected override string RulesetPrefix => OsuRuleset.SHORT_NAME; + + protected override string ComponentName => Component.ToString().ToLower(); + } +} diff --git a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs new file mode 100644 index 0000000000..5971f053c2 --- /dev/null +++ b/osu.Game.Rulesets.Osu/OsuSkinComponents.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. + +namespace osu.Game.Rulesets.Osu +{ + public enum OsuSkinComponents + { + HitCircle, + FollowPoint, + Cursor, + SliderScorePoint, + ApproachCircle, + ReverseArrow, + HitCircleText, + SliderFollowCircle, + SliderBall + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs index a7906ddd24..83d507f64b 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyMainCirclePiece.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Skinning Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - new SkinnableSpriteText("Play/osu/number-text", _ => new OsuSpriteText + new SkinnableSpriteText(new OsuSkinComponent(OsuSkinComponents.HitCircleText), _ => new OsuSpriteText { Font = OsuFont.Numeric.With(size: 40), UseFullGlyphHeight = false, diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs index 3c508f34e0..002b3f8cda 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs @@ -55,14 +55,17 @@ namespace osu.Game.Rulesets.Osu.Skinning hasHitCircle = new Lazy(() => source.GetTexture("hitcircle") != null); } - public Drawable GetDrawableComponent(string componentName) + public Drawable GetDrawableComponent(ISkinComponent component) { - switch (componentName) - { - case "Play/osu/sliderfollowcircle": - return this.GetAnimation(componentName, true, true); + if (!(component is OsuSkinComponent osuComponent)) + return null; - case "Play/osu/sliderball": + switch (osuComponent.Component) + { + case OsuSkinComponents.SliderFollowCircle: + return this.GetAnimation("sliderfollowcircle", true, true); + + case OsuSkinComponents.SliderBall: var sliderBallContent = this.GetAnimation("sliderb", true, true, ""); if (sliderBallContent != null) @@ -80,20 +83,19 @@ namespace osu.Game.Rulesets.Osu.Skinning return null; - case "Play/osu/hitcircle": + case OsuSkinComponents.HitCircle: if (hasHitCircle.Value) return new LegacyMainCirclePiece(); return null; - case "Play/osu/cursor": + case OsuSkinComponents.Cursor: if (source.GetTexture("cursor") != null) return new LegacyCursor(); return null; - case "Play/osu/number-text": - + case OsuSkinComponents.HitCircleText: string font = GetValue(config => config.HitCircleFont); var overlap = GetValue(config => config.HitCircleOverlap); diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index eb1977a13d..869c27dcac 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, Anchor = Anchor.Centre, - Child = scaleTarget = new SkinnableDrawable("Play/osu/cursor", _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling) + Child = scaleTarget = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.Cursor), _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling) { Origin = Anchor.Centre, Anchor = Anchor.Centre, diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 6d0a5eb1e1..7fdb823388 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -26,6 +26,8 @@ namespace osu.Game.Rulesets.Taiko public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList mods) => new DrawableTaikoRuleset(this, beatmap, mods); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); + public const string SHORT_NAME = "taiko"; + public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] { new KeyBinding(InputKey.MouseLeft, TaikoAction.LeftCentre), @@ -116,7 +118,7 @@ namespace osu.Game.Rulesets.Taiko public override string Description => "osu!taiko"; - public override string ShortName => "taiko"; + public override string ShortName => SHORT_NAME; public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetTaiko }; diff --git a/osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs b/osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs new file mode 100644 index 0000000000..474154279c --- /dev/null +++ b/osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Taiko +{ + public class TaikoSkinComponent : PlaySkinComponent + { + public TaikoSkinComponent(TaikoSkinComponents component) + : base(component) + { + } + + protected override string RulesetPrefix => TaikoRuleset.SHORT_NAME; + + protected override string ComponentName => Component.ToString().ToLower(); + } +} diff --git a/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs b/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs new file mode 100644 index 0000000000..04aca534c6 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs @@ -0,0 +1,9 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Taiko +{ + public enum TaikoSkinComponents + { + } +} diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs index 96dc864577..ee5552c6e0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs @@ -137,8 +137,8 @@ namespace osu.Game.Tests.Visual.Gameplay { public new Drawable Drawable => base.Drawable; - public ExposedSkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) - : base(name, defaultImplementation, allowFallback, confineMode) + public ExposedSkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + : base(new TestSkinComponent(name), defaultImplementation, allowFallback, confineMode) { } } @@ -206,8 +206,8 @@ namespace osu.Game.Tests.Visual.Gameplay public new Drawable Drawable => base.Drawable; public int SkinChangedCount { get; private set; } - public SkinConsumer(string name, Func defaultImplementation, Func allowFallback = null) - : base(name, defaultImplementation, allowFallback) + public SkinConsumer(string name, Func defaultImplementation, Func allowFallback = null) + : base(new TestSkinComponent(name), defaultImplementation, allowFallback) { } @@ -243,8 +243,8 @@ namespace osu.Game.Tests.Visual.Gameplay this.size = size; } - public Drawable GetDrawableComponent(string componentName) => - componentName == "available" + public Drawable GetDrawableComponent(ISkinComponent componentName) => + componentName.LookupName == "available" ? new DrawWidthBox { Colour = Color4.Yellow, @@ -261,7 +261,7 @@ namespace osu.Game.Tests.Visual.Gameplay private class SecondarySource : ISkin { - public Drawable GetDrawableComponent(string componentName) => new SecondarySourceBox(); + public Drawable GetDrawableComponent(ISkinComponent componentName) => new SecondarySourceBox(); public Texture GetTexture(string componentName) => throw new NotImplementedException(); @@ -272,7 +272,7 @@ namespace osu.Game.Tests.Visual.Gameplay private class SkinSourceContainer : Container, ISkin { - public Drawable GetDrawableComponent(string componentName) => new BaseSourceBox(); + public Drawable GetDrawableComponent(ISkinComponent componentName) => new BaseSourceBox(); public Texture GetTexture(string componentName) => throw new NotImplementedException(); @@ -280,5 +280,19 @@ namespace osu.Game.Tests.Visual.Gameplay public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); } + + private class TestSkinComponent : ISkinComponent + { + private readonly string name; + + public TestSkinComponent(string name) + { + this.name = name; + } + + public string ComponentGroup => string.Empty; + + public string LookupName => name; + } } } diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 61c2644c6f..ecbdc53493 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Judgements Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Child = new SkinnableDrawable($"Play/{Result.Type}", _ => JudgementText = new OsuSpriteText + Child = new SkinnableDrawable(new PlaySkinComponent(Result.Type), _ => JudgementText = new OsuSpriteText { Text = Result.Type.GetDescription().ToUpperInvariant(), Font = OsuFont.Numeric.With(size: 12), diff --git a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs index 345df35b12..40335db697 100644 --- a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs +++ b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs @@ -17,7 +17,7 @@ namespace osu.Game.Skinning private readonly Bindable beatmapHitsounds = new Bindable(); protected override bool AllowConfigurationLookup => beatmapSkins.Value; - protected override bool AllowDrawableLookup(string componentName) => beatmapSkins.Value; + protected override bool AllowDrawableLookup(ISkinComponent component) => beatmapSkins.Value; protected override bool AllowTextureLookup(string componentName) => beatmapSkins.Value; protected override bool AllowSampleLookup(ISampleInfo componentName) => beatmapHitsounds.Value; diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs index 6072bb64ed..f917514877 100644 --- a/osu.Game/Skinning/DefaultSkin.cs +++ b/osu.Game/Skinning/DefaultSkin.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.Audio.Sample; @@ -16,7 +16,7 @@ namespace osu.Game.Skinning Configuration = new SkinConfiguration(); } - public override Drawable GetDrawableComponent(string componentName) => null; + public override Drawable GetDrawableComponent(ISkinComponent component) => null; public override Texture GetTexture(string componentName) => null; diff --git a/osu.Game/Skinning/ISkin.cs b/osu.Game/Skinning/ISkin.cs index 4867aba0a9..bc1ae634c9 100644 --- a/osu.Game/Skinning/ISkin.cs +++ b/osu.Game/Skinning/ISkin.cs @@ -14,7 +14,7 @@ namespace osu.Game.Skinning /// public interface ISkin { - Drawable GetDrawableComponent(string componentName); + Drawable GetDrawableComponent(ISkinComponent component); Texture GetTexture(string componentName); diff --git a/osu.Game/Skinning/ISkinComponent.cs b/osu.Game/Skinning/ISkinComponent.cs new file mode 100644 index 0000000000..4bd9f21b6b --- /dev/null +++ b/osu.Game/Skinning/ISkinComponent.cs @@ -0,0 +1,10 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Skinning +{ + public interface ISkinComponent + { + string LookupName { get; } + } +} diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 1572c588e8..179b93d405 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -47,39 +47,24 @@ namespace osu.Game.Skinning Samples?.Dispose(); } - public override Drawable GetDrawableComponent(string componentName) + public override Drawable GetDrawableComponent(ISkinComponent component) { - bool animatable = false; - bool looping = true; - - switch (componentName) + switch (component.LookupName) { case "Play/Miss": - componentName = "hit0"; - animatable = true; - looping = false; - break; + return this.GetAnimation("hit0", true, false); case "Play/Meh": - componentName = "hit50"; - animatable = true; - looping = false; - break; + return this.GetAnimation("hit50", true, false); case "Play/Good": - componentName = "hit100"; - animatable = true; - looping = false; - break; + return this.GetAnimation("hit100", true, false); case "Play/Great": - componentName = "hit300"; - animatable = true; - looping = false; - break; + return this.GetAnimation("hit300", true, false); } - return this.GetAnimation(componentName, animatable, looping); + return this.GetAnimation(component.LookupName, false, false); } public override Texture GetTexture(string componentName) diff --git a/osu.Game/Skinning/PlaySkinComponent.cs b/osu.Game/Skinning/PlaySkinComponent.cs new file mode 100644 index 0000000000..f228d5cf9c --- /dev/null +++ b/osu.Game/Skinning/PlaySkinComponent.cs @@ -0,0 +1,23 @@ +// 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; + +namespace osu.Game.Skinning +{ + public class PlaySkinComponent : ISkinComponent where T : struct + { + public readonly T Component; + + public PlaySkinComponent(T component) + { + this.Component = component; + } + + protected virtual string RulesetPrefix => string.Empty; + protected virtual string ComponentName => Component.ToString(); + + public string LookupName => + string.Join("/", new[] { "Play", RulesetPrefix, ComponentName }.Where(s => !string.IsNullOrEmpty(s))); + } +} diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 027d9df8b8..299f257e57 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.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; @@ -15,7 +15,7 @@ namespace osu.Game.Skinning public virtual SkinConfiguration Configuration { get; protected set; } - public abstract Drawable GetDrawableComponent(string componentName); + public abstract Drawable GetDrawableComponent(ISkinComponent componentName); public abstract SampleChannel GetSample(ISampleInfo sampleInfo); diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index a713933c6e..a55a128dff 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.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; @@ -125,7 +125,7 @@ namespace osu.Game.Skinning public event Action SourceChanged; - public Drawable GetDrawableComponent(string componentName) => CurrentSkin.Value.GetDrawableComponent(componentName); + public Drawable GetDrawableComponent(ISkinComponent component) => CurrentSkin.Value.GetDrawableComponent(component); public Texture GetTexture(string componentName) => CurrentSkin.Value.GetTexture(componentName); diff --git a/osu.Game/Skinning/SkinProvidingContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs index 45b8baa0bb..85a80655ea 100644 --- a/osu.Game/Skinning/SkinProvidingContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Skinning private ISkinSource fallbackSource; - protected virtual bool AllowDrawableLookup(string componentName) => true; + protected virtual bool AllowDrawableLookup(ISkinComponent component) => true; protected virtual bool AllowTextureLookup(string componentName) => true; @@ -37,13 +37,13 @@ namespace osu.Game.Skinning RelativeSizeAxes = Axes.Both; } - public Drawable GetDrawableComponent(string componentName) + public Drawable GetDrawableComponent(ISkinComponent component) { Drawable sourceDrawable; - if (AllowDrawableLookup(componentName) && (sourceDrawable = skin?.GetDrawableComponent(componentName)) != null) + if (AllowDrawableLookup(component) && (sourceDrawable = skin?.GetDrawableComponent(component)) != null) return sourceDrawable; - return fallbackSource?.GetDrawableComponent(componentName); + return fallbackSource?.GetDrawableComponent(component); } public Texture GetTexture(string componentName) diff --git a/osu.Game/Skinning/SkinnableDrawable.cs b/osu.Game/Skinning/SkinnableDrawable.cs index 07f802944b..9ca5d60cb0 100644 --- a/osu.Game/Skinning/SkinnableDrawable.cs +++ b/osu.Game/Skinning/SkinnableDrawable.cs @@ -18,39 +18,39 @@ namespace osu.Game.Skinning /// public Drawable Drawable { get; private set; } - private readonly string componentName; + private readonly ISkinComponent component; private readonly ConfineMode confineMode; /// /// Create a new skinnable drawable. /// - /// The namespace-complete resource name for this skinnable element. + /// The namespace-complete resource name for this skinnable element. /// A function to create the default skin implementation of this element. /// A conditional to decide whether to allow fallback to the default implementation if a skinned element is not present. /// How (if at all) the should be resize to fit within our own bounds. - public SkinnableDrawable(string name, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) - : this(name, allowFallback, confineMode) + public SkinnableDrawable(ISkinComponent component, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + : this(component, allowFallback, confineMode) { createDefault = defaultImplementation; } - protected SkinnableDrawable(string name, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + protected SkinnableDrawable(ISkinComponent component, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) : base(allowFallback) { - componentName = name; + this.component = component; this.confineMode = confineMode; RelativeSizeAxes = Axes.Both; } - private readonly Func createDefault; + private readonly Func createDefault; private readonly Cached scaling = new Cached(); private bool isDefault; - protected virtual Drawable CreateDefault(string name) => createDefault(name); + protected virtual Drawable CreateDefault(ISkinComponent component) => createDefault(component); /// /// Whether to apply size restrictions (specified via ) to the default implementation. @@ -59,13 +59,13 @@ namespace osu.Game.Skinning protected override void SkinChanged(ISkinSource skin, bool allowFallback) { - Drawable = skin.GetDrawableComponent(componentName); + Drawable = skin.GetDrawableComponent(component); isDefault = false; if (Drawable == null && allowFallback) { - Drawable = CreateDefault(componentName); + Drawable = CreateDefault(component); isDefault = true; } diff --git a/osu.Game/Skinning/SkinnableSprite.cs b/osu.Game/Skinning/SkinnableSprite.cs index 07ba48d6ae..0081aef520 100644 --- a/osu.Game/Skinning/SkinnableSprite.cs +++ b/osu.Game/Skinning/SkinnableSprite.cs @@ -19,11 +19,11 @@ namespace osu.Game.Skinning [Resolved] private TextureStore textures { get; set; } - public SkinnableSprite(string name, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) - : base(name, allowFallback, confineMode) + public SkinnableSprite(ISkinComponent component, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + : base(component, allowFallback, confineMode) { } - protected override Drawable CreateDefault(string name) => new Sprite { Texture = textures.Get(name) }; + protected override Drawable CreateDefault(ISkinComponent component) => new Sprite { Texture = textures.Get(component.LookupName) }; } } diff --git a/osu.Game/Skinning/SkinnableSpriteText.cs b/osu.Game/Skinning/SkinnableSpriteText.cs index 5af6df15e1..e72f9c9811 100644 --- a/osu.Game/Skinning/SkinnableSpriteText.cs +++ b/osu.Game/Skinning/SkinnableSpriteText.cs @@ -8,8 +8,8 @@ namespace osu.Game.Skinning { public class SkinnableSpriteText : SkinnableDrawable, IHasText { - public SkinnableSpriteText(string name, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) - : base(name, defaultImplementation, allowFallback, confineMode) + public SkinnableSpriteText(ISkinComponent component, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit) + : base(component, defaultImplementation, allowFallback, confineMode) { } From a7c94c388307e02980a172ca357bb3da1fd78f63 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 15:12:03 +0900 Subject: [PATCH 2647/5608] Simplify hit result lookups --- osu.Game/Skinning/LegacySkin.cs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 179b93d405..e51bf8245c 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Game.Audio; +using osu.Game.Rulesets.Scoring; using osuTK.Graphics; namespace osu.Game.Skinning @@ -49,19 +50,25 @@ namespace osu.Game.Skinning public override Drawable GetDrawableComponent(ISkinComponent component) { - switch (component.LookupName) + switch (component) { - case "Play/Miss": - return this.GetAnimation("hit0", true, false); + case PlaySkinComponent resultComponent: + switch (resultComponent.Component) + { + case HitResult.Miss: + return this.GetAnimation("hit0", true, false); - case "Play/Meh": - return this.GetAnimation("hit50", true, false); + case HitResult.Meh: + return this.GetAnimation("hit50", true, false); - case "Play/Good": - return this.GetAnimation("hit100", true, false); + case HitResult.Good: + return this.GetAnimation("hit100", true, false); - case "Play/Great": - return this.GetAnimation("hit300", true, false); + case HitResult.Great: + return this.GetAnimation("hit300", true, false); + } + + break; } return this.GetAnimation(component.LookupName, false, false); From 70e417533f47009049075747a8bc87636b633b53 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 15:10:11 +0900 Subject: [PATCH 2648/5608] Update naming --- osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs | 4 ++-- osu.Game.Rulesets.Catch/CatchSkinComponent.cs | 2 +- osu.Game.Rulesets.Mania/ManiaSkinComponent.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 2 +- .../Objects/Drawables/Pieces/CirclePiece.cs | 2 +- osu.Game.Rulesets.Osu/OsuSkinComponent.cs | 2 +- osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs | 2 +- osu.Game.Rulesets.Taiko/UI/InputDrum.cs | 8 ++++---- osu.Game/Rulesets/Judgements/DrawableJudgement.cs | 2 +- .../{PlaySkinComponent.cs => GameplaySkinComponent.cs} | 6 +++--- osu.Game/Skinning/LegacySkin.cs | 2 +- 11 files changed, 17 insertions(+), 17 deletions(-) rename osu.Game/Skinning/{PlaySkinComponent.cs => GameplaySkinComponent.cs} (66%) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 13286f4524..c89cd95f36 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.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 NUnit.Framework; @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Catch.Tests { switch (component.LookupName) { - case "Play/Catch/fruit-catcher-idle": + case "Gameplay/Catch/fruit-catcher-idle": return new CatcherCustomSkin(); } diff --git a/osu.Game.Rulesets.Catch/CatchSkinComponent.cs b/osu.Game.Rulesets.Catch/CatchSkinComponent.cs index 620720310f..0a3e43dcfc 100644 --- a/osu.Game.Rulesets.Catch/CatchSkinComponent.cs +++ b/osu.Game.Rulesets.Catch/CatchSkinComponent.cs @@ -5,7 +5,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch { - public class CatchSkinComponent : PlaySkinComponent + public class CatchSkinComponent : GameplaySkinComponent { public CatchSkinComponent(CatchSkinComponents component) : base(component) diff --git a/osu.Game.Rulesets.Mania/ManiaSkinComponent.cs b/osu.Game.Rulesets.Mania/ManiaSkinComponent.cs index 72a3ce7ad5..69bd4b0ecf 100644 --- a/osu.Game.Rulesets.Mania/ManiaSkinComponent.cs +++ b/osu.Game.Rulesets.Mania/ManiaSkinComponent.cs @@ -5,7 +5,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania { - public class ManiaSkinComponent : PlaySkinComponent + public class ManiaSkinComponent : GameplaySkinComponent { public ManiaSkinComponent(ManiaSkinComponents component) : base(component) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 445f81c6d4..1eb37f8119 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -188,7 +188,7 @@ namespace osu.Game.Rulesets.Osu.Mods [BackgroundDependencyLoader] private void load(TextureStore textures) { - Texture = textures.Get("Play/osu/blinds-panel"); + Texture = textures.Get("Gameplay/osu/blinds-panel"); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index a59cfc1123..210d5ff839 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Texture = textures.Get(@"Play/osu/disc"), + Texture = textures.Get(@"Gameplay/osu/disc"), }, new TrianglesPiece { diff --git a/osu.Game.Rulesets.Osu/OsuSkinComponent.cs b/osu.Game.Rulesets.Osu/OsuSkinComponent.cs index ef0df6cbda..1d223f231b 100644 --- a/osu.Game.Rulesets.Osu/OsuSkinComponent.cs +++ b/osu.Game.Rulesets.Osu/OsuSkinComponent.cs @@ -5,7 +5,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu { - public class OsuSkinComponent : PlaySkinComponent + public class OsuSkinComponent : GameplaySkinComponent { public OsuSkinComponent(OsuSkinComponents component) : base(component) diff --git a/osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs b/osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs index 474154279c..e6e4bc0dd7 100644 --- a/osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs +++ b/osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs @@ -5,7 +5,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko { - public class TaikoSkinComponent : PlaySkinComponent + public class TaikoSkinComponent : GameplaySkinComponent { public TaikoSkinComponent(TaikoSkinComponents component) : base(component) diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index d6866c7d25..9766da9a24 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -132,10 +132,10 @@ namespace osu.Game.Rulesets.Taiko.UI [BackgroundDependencyLoader] private void load(TextureStore textures, OsuColour colours) { - rim.Texture = textures.Get(@"Play/Taiko/taiko-drum-outer"); - rimHit.Texture = textures.Get(@"Play/Taiko/taiko-drum-outer-hit"); - centre.Texture = textures.Get(@"Play/Taiko/taiko-drum-inner"); - centreHit.Texture = textures.Get(@"Play/Taiko/taiko-drum-inner-hit"); + rim.Texture = textures.Get(@"Gameplay/Taiko/taiko-drum-outer"); + rimHit.Texture = textures.Get(@"Gameplay/Taiko/taiko-drum-outer-hit"); + centre.Texture = textures.Get(@"Gameplay/Taiko/taiko-drum-inner"); + centreHit.Texture = textures.Get(@"Gameplay/Taiko/taiko-drum-inner-hit"); rimHit.Colour = colours.Blue; centreHit.Colour = colours.Pink; diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index ecbdc53493..4f8cb7660b 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Judgements Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Child = new SkinnableDrawable(new PlaySkinComponent(Result.Type), _ => JudgementText = new OsuSpriteText + Child = new SkinnableDrawable(new GameplaySkinComponent(Result.Type), _ => JudgementText = new OsuSpriteText { Text = Result.Type.GetDescription().ToUpperInvariant(), Font = OsuFont.Numeric.With(size: 12), diff --git a/osu.Game/Skinning/PlaySkinComponent.cs b/osu.Game/Skinning/GameplaySkinComponent.cs similarity index 66% rename from osu.Game/Skinning/PlaySkinComponent.cs rename to osu.Game/Skinning/GameplaySkinComponent.cs index f228d5cf9c..da65084a1d 100644 --- a/osu.Game/Skinning/PlaySkinComponent.cs +++ b/osu.Game/Skinning/GameplaySkinComponent.cs @@ -5,11 +5,11 @@ using System.Linq; namespace osu.Game.Skinning { - public class PlaySkinComponent : ISkinComponent where T : struct + public class GameplaySkinComponent : ISkinComponent where T : struct { public readonly T Component; - public PlaySkinComponent(T component) + public GameplaySkinComponent(T component) { this.Component = component; } @@ -18,6 +18,6 @@ namespace osu.Game.Skinning protected virtual string ComponentName => Component.ToString(); public string LookupName => - string.Join("/", new[] { "Play", RulesetPrefix, ComponentName }.Where(s => !string.IsNullOrEmpty(s))); + string.Join("/", new[] { "Gameplay", RulesetPrefix, ComponentName }.Where(s => !string.IsNullOrEmpty(s))); } } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index e51bf8245c..753b2ba41b 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -52,7 +52,7 @@ namespace osu.Game.Skinning { switch (component) { - case PlaySkinComponent resultComponent: + case GameplaySkinComponent resultComponent: switch (resultComponent.Component) { case HitResult.Miss: From 835ee0aa2fbd75ed38782a54750135131396e708 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 15:29:13 +0900 Subject: [PATCH 2649/5608] Code quality fixes --- .../Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs index fae1b68e4a..fbd6aedd45 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs @@ -18,10 +18,13 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private const int margin = 10; private readonly Bindable type = new Bindable(); + private readonly HitWindows hitWindows; + private readonly ScoreProcessor processor; private BarHitErrorDisplay leftDisplay; + private BarHitErrorDisplay rightDisplay; public HitErrorDisplayOverlay(ScoreProcessor processor) @@ -40,10 +43,10 @@ namespace osu.Game.Screens.Play.HitErrorDisplay protected override void LoadComplete() { base.LoadComplete(); - type.BindValueChanged(onTypeChanged, true); + type.BindValueChanged(typeChanged, true); } - private void onTypeChanged(ValueChangedEvent type) + private void typeChanged(ValueChangedEvent type) { switch (type.NewValue) { From fe90e194e37b977ebcd2232f0af0b5177efef571 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 15:29:44 +0900 Subject: [PATCH 2650/5608] Remove redundant qualifier --- osu.Game/Skinning/PlaySkinComponent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/PlaySkinComponent.cs b/osu.Game/Skinning/PlaySkinComponent.cs index f228d5cf9c..68b67ee0c5 100644 --- a/osu.Game/Skinning/PlaySkinComponent.cs +++ b/osu.Game/Skinning/PlaySkinComponent.cs @@ -11,7 +11,7 @@ namespace osu.Game.Skinning public PlaySkinComponent(T component) { - this.Component = component; + Component = component; } protected virtual string RulesetPrefix => string.Empty; From bdbfa7bd2f5a4afde5c21478144f76a49dc25b2d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 15:32:47 +0900 Subject: [PATCH 2651/5608] Fix class naming --- ...isplay.cs => TestSceneBarHitErrorMeter.cs} | 12 +- osu.Game/Screens/Play/HUDOverlay.cs | 7 +- ...HitErrorDisplay.cs => BarHitErrorMeter.cs} | 4 +- .../Play/HitErrorDisplay/HitErrorDisplay.cs | 120 +++++++++++++++- .../HitErrorDisplay/HitErrorDisplayOverlay.cs | 129 ------------------ .../Play/HitErrorDisplay/HitErrorMeter.cs | 21 +++ 6 files changed, 146 insertions(+), 147 deletions(-) rename osu.Game.Tests/Visual/Gameplay/{TestSceneHitErrorDisplay.cs => TestSceneBarHitErrorMeter.cs} (94%) rename osu.Game/Screens/Play/HitErrorDisplay/{BarHitErrorDisplay.cs => BarHitErrorMeter.cs} (98%) delete mode 100644 osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs create mode 100644 osu.Game/Screens/Play/HitErrorDisplay/HitErrorMeter.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs similarity index 94% rename from osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs index a148bdad67..aac9e206c3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorDisplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs @@ -19,16 +19,16 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneHitErrorDisplay : OsuTestScene + public class TestSceneBarHitErrorMeter : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { - typeof(HitErrorDisplay), + typeof(HitErrorMeter), }; - private HitErrorDisplay display; + private HitErrorMeter meter; - public TestSceneHitErrorDisplay() + public TestSceneBarHitErrorMeter() { recreateDisplay(new OsuHitWindows(), 5); AddStep("New random judgement", () => newJudgement()); @@ -115,7 +115,7 @@ namespace osu.Game.Tests.Visual.Gameplay } }); - Add(display = new BarHitErrorDisplay(hitWindows) + Add(meter = new BarHitErrorMeter(hitWindows) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -124,7 +124,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void newJudgement(float offset = 0) { - display?.OnNewJudgement(new JudgementResult(new Judgement()) + meter?.OnNewJudgement(new JudgementResult(new Judgement()) { TimeOffset = offset == 0 ? RNG.Next(-70, 70) : offset, Type = HitResult.Perfect, diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 02432cf64e..79392221e4 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -15,7 +15,6 @@ using osu.Game.Overlays.Notifications; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; -using osu.Game.Screens.Play.HitErrorDisplay; using osu.Game.Screens.Play.HUD; using osuTK; using osuTK.Input; @@ -34,7 +33,7 @@ namespace osu.Game.Screens.Play public readonly HealthDisplay HealthDisplay; public readonly SongProgress Progress; public readonly ModDisplay ModDisplay; - public readonly HitErrorDisplayOverlay HitErrorDisplayOverlay; + public readonly HitErrorDisplay.HitErrorDisplay HitErrorDisplay; public readonly HoldForMenuButton HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; @@ -86,7 +85,7 @@ namespace osu.Game.Screens.Play HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), ModDisplay = CreateModsContainer(), - HitErrorDisplayOverlay = CreateHitErrorDisplayOverlay(), + HitErrorDisplay = CreateHitErrorDisplayOverlay(), } }, PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), @@ -259,7 +258,7 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20, Right = 10 }, }; - protected virtual HitErrorDisplayOverlay CreateHitErrorDisplayOverlay() => new HitErrorDisplayOverlay(scoreProcessor) + protected virtual HitErrorDisplay.HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay.HitErrorDisplay(scoreProcessor) { RelativeSizeAxes = Axes.Both, }; diff --git a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs similarity index 98% rename from osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs rename to osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs index 85d017073a..3ec3740816 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs @@ -18,7 +18,7 @@ using System.Linq; namespace osu.Game.Screens.Play.HitErrorDisplay { - public class BarHitErrorDisplay : HitErrorDisplay + public class BarHitErrorMeter : HitErrorMeter { /// /// The amount of which will be stored to calculate arrow position. @@ -38,7 +38,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private readonly List judgementOffsets = new List(); private readonly double maxHitWindows; - public BarHitErrorDisplay(HitWindows hitWindows, bool reversed = false) + public BarHitErrorMeter(HitWindows hitWindows, bool reversed = false) : base(hitWindows) { maxHitWindows = HitWindows.Meh == 0 ? HitWindows.Good : HitWindows.Meh; diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs index 422e151d8a..5c884f3f53 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs @@ -2,20 +2,128 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Judgements; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Scoring; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Play.HitErrorDisplay { - public abstract class HitErrorDisplay : CompositeDrawable + public class HitErrorDisplay : Container { - protected readonly HitWindows HitWindows; + private const int fade_duration = 200; + private const int margin = 10; - protected HitErrorDisplay(HitWindows hitWindows) + private readonly Bindable type = new Bindable(); + + private readonly HitWindows hitWindows; + + private readonly ScoreProcessor processor; + + private BarHitErrorMeter leftMeter; + + private BarHitErrorMeter rightMeter; + + public HitErrorDisplay(ScoreProcessor processor) { - HitWindows = hitWindows; + this.processor = processor; + hitWindows = processor.CreateHitWindows(); } - public abstract void OnNewJudgement(JudgementResult newJudgement); + [BackgroundDependencyLoader] + private void load(OsuConfigManager config, Bindable workingBeatmap) + { + config.BindWith(OsuSetting.ScoreMeter, type); + hitWindows.SetDifficulty(workingBeatmap.Value.BeatmapInfo.BaseDifficulty.OverallDifficulty); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + type.BindValueChanged(typeChanged, true); + } + + private void typeChanged(ValueChangedEvent type) + { + switch (type.NewValue) + { + case ScoreMeterType.None: + removeLeftDisplay(); + removeRightDisplay(); + break; + + case ScoreMeterType.HitErrorBoth: + addLeftDisplay(); + addRightDisplay(); + break; + + case ScoreMeterType.HitErrorLeft: + addLeftDisplay(); + removeRightDisplay(); + break; + + case ScoreMeterType.HitErrorRight: + addRightDisplay(); + removeLeftDisplay(); + break; + } + } + + private void addLeftDisplay() + { + if (leftMeter != null) + return; + + leftMeter = createNew(); + } + + private void addRightDisplay() + { + if (rightMeter != null) + return; + + rightMeter = createNew(true); + } + + private void removeRightDisplay() + { + if (rightMeter == null) + return; + + processor.NewJudgement -= rightMeter.OnNewJudgement; + + rightMeter.FadeOut(fade_duration, Easing.OutQuint).Expire(); + rightMeter = null; + } + + private void removeLeftDisplay() + { + if (leftMeter == null) + return; + + processor.NewJudgement -= leftMeter.OnNewJudgement; + + leftMeter.FadeOut(fade_duration, Easing.OutQuint).Expire(); + leftMeter = null; + } + + private BarHitErrorMeter createNew(bool reversed = false) + { + var display = new BarHitErrorMeter(hitWindows, reversed) + { + Margin = new MarginPadding(margin), + Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Alpha = 0, + }; + + processor.NewJudgement += display.OnNewJudgement; + Add(display); + display.FadeInFromZero(fade_duration, Easing.OutQuint); + return display; + } } } diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs deleted file mode 100644 index fbd6aedd45..0000000000 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplayOverlay.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics; -using osu.Game.Rulesets.Scoring; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Game.Beatmaps; -using osu.Game.Configuration; -using osu.Game.Rulesets.Objects; - -namespace osu.Game.Screens.Play.HitErrorDisplay -{ - public class HitErrorDisplayOverlay : Container - { - private const int fade_duration = 200; - private const int margin = 10; - - private readonly Bindable type = new Bindable(); - - private readonly HitWindows hitWindows; - - private readonly ScoreProcessor processor; - - private BarHitErrorDisplay leftDisplay; - - private BarHitErrorDisplay rightDisplay; - - public HitErrorDisplayOverlay(ScoreProcessor processor) - { - this.processor = processor; - hitWindows = processor.CreateHitWindows(); - } - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config, Bindable workingBeatmap) - { - config.BindWith(OsuSetting.ScoreMeter, type); - hitWindows.SetDifficulty(workingBeatmap.Value.BeatmapInfo.BaseDifficulty.OverallDifficulty); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - type.BindValueChanged(typeChanged, true); - } - - private void typeChanged(ValueChangedEvent type) - { - switch (type.NewValue) - { - case ScoreMeterType.None: - removeLeftDisplay(); - removeRightDisplay(); - break; - - case ScoreMeterType.HitErrorBoth: - addLeftDisplay(); - addRightDisplay(); - break; - - case ScoreMeterType.HitErrorLeft: - addLeftDisplay(); - removeRightDisplay(); - break; - - case ScoreMeterType.HitErrorRight: - addRightDisplay(); - removeLeftDisplay(); - break; - } - } - - private void addLeftDisplay() - { - if (leftDisplay != null) - return; - - leftDisplay = createNew(); - } - - private void addRightDisplay() - { - if (rightDisplay != null) - return; - - rightDisplay = createNew(true); - } - - private void removeRightDisplay() - { - if (rightDisplay == null) - return; - - processor.NewJudgement -= rightDisplay.OnNewJudgement; - - rightDisplay.FadeOut(fade_duration, Easing.OutQuint).Expire(); - rightDisplay = null; - } - - private void removeLeftDisplay() - { - if (leftDisplay == null) - return; - - processor.NewJudgement -= leftDisplay.OnNewJudgement; - - leftDisplay.FadeOut(fade_duration, Easing.OutQuint).Expire(); - leftDisplay = null; - } - - private BarHitErrorDisplay createNew(bool reversed = false) - { - var display = new BarHitErrorDisplay(hitWindows, reversed) - { - Margin = new MarginPadding(margin), - Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - Alpha = 0, - }; - - processor.NewJudgement += display.OnNewJudgement; - Add(display); - display.FadeInFromZero(fade_duration, Easing.OutQuint); - return display; - } - } -} diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorMeter.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorMeter.cs new file mode 100644 index 0000000000..848e892eaa --- /dev/null +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorMeter.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Screens.Play.HitErrorDisplay +{ + public abstract class HitErrorMeter : CompositeDrawable + { + protected readonly HitWindows HitWindows; + + protected HitErrorMeter(HitWindows hitWindows) + { + HitWindows = hitWindows; + } + + public abstract void OnNewJudgement(JudgementResult newJudgement); + } +} From 6640161bc1fde5e88fff7e1084c83468670660ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 15:51:36 +0900 Subject: [PATCH 2652/5608] Simplify event propagation --- .../Play/HitErrorDisplay/BarHitErrorMeter.cs | 16 ++-- .../Play/HitErrorDisplay/HitErrorDisplay.cs | 90 ++++++------------- 2 files changed, 36 insertions(+), 70 deletions(-) diff --git a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs index 3ec3740816..b00f3f6f5f 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs @@ -38,7 +38,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private readonly List judgementOffsets = new List(); private readonly double maxHitWindows; - public BarHitErrorMeter(HitWindows hitWindows, bool reversed = false) + public BarHitErrorMeter(HitWindows hitWindows, bool rightAligned = false) : base(hitWindows) { maxHitWindows = HitWindows.Meh == 0 ? HitWindows.Good : HitWindows.Meh; @@ -54,23 +54,23 @@ namespace osu.Game.Screens.Play.HitErrorDisplay { judgementsContainer = new Container { - Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Anchor = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, Width = judgement_line_width, RelativeSizeAxes = Axes.Y, }, bar = new FillFlowContainer { - Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Anchor = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, Width = bar_width, RelativeSizeAxes = Axes.Y, Direction = FillDirection.Vertical, }, new Container { - Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Anchor = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, AutoSizeAxes = Axes.X, RelativeSizeAxes = Axes.Y, Child = arrow = new SpriteIcon @@ -78,7 +78,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativePositionAxes = Axes.Y, - Icon = reversed ? FontAwesome.Solid.ChevronRight : FontAwesome.Solid.ChevronLeft, + Icon = rightAligned ? FontAwesome.Solid.ChevronRight : FontAwesome.Solid.ChevronLeft, Size = new Vector2(8), } }, diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs index 5c884f3f53..eaaf8e810c 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs @@ -1,13 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Rulesets.Scoring; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Play.HitErrorDisplay @@ -19,25 +22,33 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private readonly Bindable type = new Bindable(); - private readonly HitWindows hitWindows; + private HitWindows hitWindows; private readonly ScoreProcessor processor; - private BarHitErrorMeter leftMeter; - - private BarHitErrorMeter rightMeter; - public HitErrorDisplay(ScoreProcessor processor) { this.processor = processor; - hitWindows = processor.CreateHitWindows(); + processor.NewJudgement += onNewJudgement; + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + processor.NewJudgement -= onNewJudgement; + } + + private void onNewJudgement(JudgementResult result) + { + foreach (var c in Children) + c.OnNewJudgement(result); } [BackgroundDependencyLoader] private void load(OsuConfigManager config, Bindable workingBeatmap) { config.BindWith(OsuSetting.ScoreMeter, type); - hitWindows.SetDifficulty(workingBeatmap.Value.BeatmapInfo.BaseDifficulty.OverallDifficulty); + hitWindows = workingBeatmap.Value.Beatmap.HitObjects.First().HitWindows; } protected override void LoadComplete() @@ -48,82 +59,37 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private void typeChanged(ValueChangedEvent type) { + Children.ForEach(c => c.FadeOut(fade_duration, Easing.OutQuint)); + switch (type.NewValue) { - case ScoreMeterType.None: - removeLeftDisplay(); - removeRightDisplay(); - break; - case ScoreMeterType.HitErrorBoth: - addLeftDisplay(); - addRightDisplay(); + createBar(false); + createBar(true); break; case ScoreMeterType.HitErrorLeft: - addLeftDisplay(); - removeRightDisplay(); + createBar(false); break; case ScoreMeterType.HitErrorRight: - addRightDisplay(); - removeLeftDisplay(); + createBar(true); break; } } - private void addLeftDisplay() + private void createBar(bool rightAligned) { - if (leftMeter != null) - return; - - leftMeter = createNew(); - } - - private void addRightDisplay() - { - if (rightMeter != null) - return; - - rightMeter = createNew(true); - } - - private void removeRightDisplay() - { - if (rightMeter == null) - return; - - processor.NewJudgement -= rightMeter.OnNewJudgement; - - rightMeter.FadeOut(fade_duration, Easing.OutQuint).Expire(); - rightMeter = null; - } - - private void removeLeftDisplay() - { - if (leftMeter == null) - return; - - processor.NewJudgement -= leftMeter.OnNewJudgement; - - leftMeter.FadeOut(fade_duration, Easing.OutQuint).Expire(); - leftMeter = null; - } - - private BarHitErrorMeter createNew(bool reversed = false) - { - var display = new BarHitErrorMeter(hitWindows, reversed) + var display = new BarHitErrorMeter(hitWindows, rightAligned) { Margin = new MarginPadding(margin), - Anchor = reversed ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = reversed ? Anchor.CentreRight : Anchor.CentreLeft, + Anchor = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, + Origin = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, Alpha = 0, }; - processor.NewJudgement += display.OnNewJudgement; Add(display); display.FadeInFromZero(fade_duration, Easing.OutQuint); - return display; } } } From b03b520818eb2e9474fa7f7ea7daf01c287263b5 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 30 Aug 2019 10:13:21 +0300 Subject: [PATCH 2653/5608] Move Absing from the APIKudosuHistory --- osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs | 6 ------ .../Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs | 3 ++- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs index 19ce11aa13..67ff20e6c2 100644 --- a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs +++ b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs @@ -13,12 +13,6 @@ namespace osu.Game.Online.API.Requests.Responses public DateTimeOffset CreatedAt; [JsonProperty("amount")] - private int amount - { - //We can receive negative values. However "action" is enough to build needed items - set => Amount = Math.Abs(value); - } - public int Amount; [JsonProperty("post")] diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index fb7d597012..94733324ba 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -9,6 +9,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests; using osu.Game.Online.Chat; +using System; namespace osu.Game.Overlays.Profile.Sections.Kudosu { @@ -56,7 +57,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu if (!string.IsNullOrEmpty(prefix)) { linkFlowContainer.AddText(prefix); - linkFlowContainer.AddText($@" {historyItem.Amount} kudosu", t => + linkFlowContainer.AddText($@" {Math.Abs(historyItem.Amount)} kudosu", t => { t.Font = t.Font.With(italics: true); t.Colour = colours.Blue; From 71c844facdff1219fc5b0a6e1189b81e6058c8d5 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 30 Aug 2019 10:22:49 +0300 Subject: [PATCH 2654/5608] Remove unwanted spacings --- .../Kudosu/DrawableKudosuHistoryItem.cs | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index 94733324ba..408468fa73 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -10,6 +10,7 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests; using osu.Game.Online.Chat; using System; +using osuTK; namespace osu.Game.Overlays.Profile.Sections.Kudosu { @@ -37,6 +38,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, + Spacing = new Vector2(3), }, date = new DrawableDate(historyItem.CreatedAt) { @@ -57,7 +59,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu if (!string.IsNullOrEmpty(prefix)) { linkFlowContainer.AddText(prefix); - linkFlowContainer.AddText($@" {Math.Abs(historyItem.Amount)} kudosu", t => + linkFlowContainer.AddText($@"{Math.Abs(historyItem.Amount)} kudosu", t => { t.Font = t.Font.With(italics: true); t.Colour = colours.Blue; @@ -75,40 +77,40 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu switch (historyItem.Action) { case KudosuAction.VoteGive: - return @" from obtaining votes in modding post of"; + return @"from obtaining votes in modding post of"; case KudosuAction.Give: - return $@" from {userLink()} for a post at"; + return $@"from {userLink()} for a post at"; case KudosuAction.Reset: return $@"Kudosu reset by {userLink()} for the post"; case KudosuAction.VoteReset: - return @" from losing votes in modding post of"; + return @"from losing votes in modding post of"; case KudosuAction.DenyKudosuReset: - return @" from modding post"; + return @"from modding post"; case KudosuAction.Revoke: return $@"Denied kudosu by {userLink()} for the post"; case KudosuAction.AllowKudosuGive: - return @" from kudosu deny repeal of modding post"; + return @"from kudosu deny repeal of modding post"; case KudosuAction.DeleteReset: - return @" from modding post deletion of"; + return @"from modding post deletion of"; case KudosuAction.RestoreGive: - return @" from modding post restoration of"; + return @"from modding post restoration of"; case KudosuAction.RecalculateGive: - return @" from votes recalculation in modding post of"; + return @"from votes recalculation in modding post of"; case KudosuAction.RecalculateReset: - return @" from votes recalculation in modding post of"; + return @"from votes recalculation in modding post of"; default: - return @" from unknown event "; + return @"from unknown event"; } } From 72dbeaec1632ce6a94c71bc82141d447a1f19d4f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 30 Aug 2019 10:26:11 +0300 Subject: [PATCH 2655/5608] Fix the comment --- osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs index 67ff20e6c2..f2297f7a10 100644 --- a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs +++ b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs @@ -44,7 +44,7 @@ namespace osu.Game.Online.API.Requests.Responses { set { - //We will receive something like "foo.bar" or just "foo" + //We will receive something like "event.action" or just "action" string parsed = value.Contains(".") ? value.Split('.')[0].Pascalize() + value.Split('.')[1].Pascalize() : value.Pascalize(); Action = (KudosuAction)Enum.Parse(typeof(KudosuAction), parsed); From 5f3e638499c1d8fde4362239bdbfef91b9add024 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 16:40:24 +0900 Subject: [PATCH 2656/5608] Make test useful --- .../Visual/Gameplay/TestSceneBarHitErrorMeter.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs index aac9e206c3..28c5f0ae08 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs @@ -30,8 +30,14 @@ namespace osu.Game.Tests.Visual.Gameplay public TestSceneBarHitErrorMeter() { - recreateDisplay(new OsuHitWindows(), 5); - AddStep("New random judgement", () => newJudgement()); + var hitWindows = new OsuHitWindows(); + + recreateDisplay(hitWindows, 5); + + AddRepeatStep("New random judgement", () => newJudgement(), 40); + + AddRepeatStep("New max negative", () => newJudgement(-hitWindows.Meh), 20); + AddRepeatStep("New max positive", () => newJudgement(hitWindows.Meh), 20); AddStep("New fixed judgement (50ms)", () => newJudgement(50)); } @@ -122,11 +128,11 @@ namespace osu.Game.Tests.Visual.Gameplay }); } - private void newJudgement(float offset = 0) + private void newJudgement(double offset = 0) { meter?.OnNewJudgement(new JudgementResult(new Judgement()) { - TimeOffset = offset == 0 ? RNG.Next(-70, 70) : offset, + TimeOffset = offset == 0 ? RNG.Next(-150, 150) : offset, Type = HitResult.Perfect, }); } From a73d672c2f3c0397d80400d8c3e96d4b22b55d2c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 16:40:39 +0900 Subject: [PATCH 2657/5608] Tidy up judgement line logic (and fix it displaying at the wrong place) --- .../Play/HitErrorDisplay/BarHitErrorMeter.cs | 119 +++++++++--------- .../Play/HitErrorDisplay/HitErrorMeter.cs | 2 +- 2 files changed, 63 insertions(+), 58 deletions(-) diff --git a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs index b00f3f6f5f..ffaada6ff4 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -8,42 +9,46 @@ using osu.Game.Rulesets.Judgements; using osuTK.Graphics; using osuTK; using osu.Framework.Graphics.Sprites; -using System.Collections.Generic; using osu.Game.Rulesets.Objects; using osu.Framework.Allocation; using osu.Framework.Graphics.Colour; using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions; -using System.Linq; namespace osu.Game.Screens.Play.HitErrorDisplay { public class BarHitErrorMeter : HitErrorMeter { - /// - /// The amount of which will be stored to calculate arrow position. - /// - private const int stored_judgements_amount = 5; + private readonly bool rightAligned; private const int judgement_fade_duration = 10000; - private const int arrow_move_duration = 500; + + private const int arrow_move_duration = 400; + private const int judgement_line_width = 8; + private const int bar_height = 200; + private const int bar_width = 3; + private const int spacing = 3; private readonly SpriteIcon arrow; + private readonly FillFlowContainer bar; + private readonly Container judgementsContainer; - private readonly List judgementOffsets = new List(); - private readonly double maxHitWindows; + + private readonly double maxHitWindow; public BarHitErrorMeter(HitWindows hitWindows, bool rightAligned = false) : base(hitWindows) { - maxHitWindows = HitWindows.Meh == 0 ? HitWindows.Good : HitWindows.Meh; + this.rightAligned = rightAligned; + maxHitWindow = Math.Max(Math.Max(HitWindows.Meh, HitWindows.Ok), HitWindows.Good); AutoSizeAxes = Axes.Both; + AddInternal(new FillFlowContainer { AutoSizeAxes = Axes.X, @@ -75,9 +80,10 @@ namespace osu.Game.Screens.Play.HitErrorDisplay RelativeSizeAxes = Axes.Y, Child = arrow = new SpriteIcon { - Anchor = Anchor.Centre, + Anchor = Anchor.TopCentre, Origin = Anchor.Centre, RelativePositionAxes = Axes.Y, + Y = 0.5f, Icon = rightAligned ? FontAwesome.Solid.ChevronRight : FontAwesome.Solid.ChevronLeft, Size = new Vector2(8), } @@ -93,24 +99,20 @@ namespace osu.Game.Screens.Play.HitErrorDisplay { bar.AddRange(new[] { - createColoredPiece(ColourInfo.GradientVertical(colours.Yellow.Opacity(0), colours.Yellow), - (maxHitWindows - HitWindows.Good) / (maxHitWindows * 2)), - createColoredPiece(colours.Green, (HitWindows.Good - HitWindows.Great) / (maxHitWindows * 2)), - createColoredPiece(colours.BlueLight, HitWindows.Great / maxHitWindows), - createColoredPiece(colours.Green, (HitWindows.Good - HitWindows.Great) / (maxHitWindows * 2)), - createColoredPiece(ColourInfo.GradientVertical(colours.Yellow, colours.Yellow.Opacity(0)), - (maxHitWindows - HitWindows.Good) / (maxHitWindows * 2)) + createColoredPiece(ColourInfo.GradientVertical(colours.Yellow.Opacity(0), colours.Yellow), (maxHitWindow - HitWindows.Good) / (maxHitWindow * 2)), + createColoredPiece(colours.Green, (HitWindows.Good - HitWindows.Great) / (maxHitWindow * 2)), + createColoredPiece(colours.BlueLight, HitWindows.Great / maxHitWindow), + createColoredPiece(colours.Green, (HitWindows.Good - HitWindows.Great) / (maxHitWindow * 2)), + createColoredPiece(ColourInfo.GradientVertical(colours.Yellow, colours.Yellow.Opacity(0)), (maxHitWindow - HitWindows.Good) / (maxHitWindow * 2)) }); } else { bar.AddRange(new[] { - createColoredPiece(ColourInfo.GradientVertical(colours.Green.Opacity(0), colours.Green), - (HitWindows.Good - HitWindows.Great) / (maxHitWindows * 2)), - createColoredPiece(colours.BlueLight, HitWindows.Great / maxHitWindows), - createColoredPiece(ColourInfo.GradientVertical(colours.Green, colours.Green.Opacity(0)), - (HitWindows.Good - HitWindows.Great) / (maxHitWindows * 2)), + createColoredPiece(ColourInfo.GradientVertical(colours.Green.Opacity(0), colours.Green), (HitWindows.Good - HitWindows.Great) / (maxHitWindow * 2)), + createColoredPiece(colours.BlueLight, HitWindows.Great / maxHitWindow), + createColoredPiece(ColourInfo.GradientVertical(colours.Green, colours.Green.Opacity(0)), (HitWindows.Good - HitWindows.Great) / (maxHitWindow * 2)), }); } } @@ -122,51 +124,54 @@ namespace osu.Game.Screens.Play.HitErrorDisplay Height = (float)height }; - public override void OnNewJudgement(JudgementResult newJudgement) + private double floatingAverage; + + public override void OnNewJudgement(JudgementResult judgement) { - if (!newJudgement.IsHit) + if (!judgement.IsHit) return; - var judgementLine = CreateJudgementLine(newJudgement); + judgementsContainer.Add(new JudgementLine + { + Y = getRelativeJudgementPosition(judgement.TimeOffset), + Anchor = rightAligned ? Anchor.TopLeft : Anchor.TopRight, + Origin = rightAligned ? Anchor.TopLeft : Anchor.TopRight, + }); - judgementsContainer.Add(judgementLine); - - judgementLine.FadeOut(judgement_fade_duration, Easing.OutQuint).Expire(); - - arrow.MoveToY(calculateArrowPosition(newJudgement), arrow_move_duration, Easing.OutQuint); + arrow.MoveToY(getRelativeJudgementPosition(floatingAverage = floatingAverage * 0.9 + judgement.TimeOffset * 0.1) + , arrow_move_duration, Easing.Out); } - protected virtual Container CreateJudgementLine(JudgementResult judgement) => new CircularContainer + private float getRelativeJudgementPosition(double value) => (float)((value / maxHitWindow) + 1) / 2; + + public class JudgementLine : CompositeDrawable { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Masking = true, - RelativeSizeAxes = Axes.X, - Height = 2, - RelativePositionAxes = Axes.Y, - Y = getRelativeJudgementPosition(judgement.TimeOffset), - Child = new Box + public JudgementLine() { - RelativeSizeAxes = Axes.Both, - Colour = Color4.White, + RelativeSizeAxes = Axes.X; + RelativePositionAxes = Axes.Y; + Height = 2; + + InternalChild = new CircularContainer + { + Masking = true, + RelativeSizeAxes = Axes.Both, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + } + }; } - }; - private float getRelativeJudgementPosition(double value) => (float)(value / maxHitWindows); + protected override void LoadComplete() + { + base.LoadComplete(); - private float calculateArrowPosition(JudgementResult newJudgement) - { - judgementOffsets.Add(newJudgement.TimeOffset); - - if (judgementOffsets.Count < stored_judgements_amount) - return getRelativeJudgementPosition(judgementOffsets.Average()); - - double sum = 0; - - for (int i = judgementOffsets.Count - stored_judgements_amount; i < judgementOffsets.Count; i++) - sum += judgementOffsets[i]; - - return getRelativeJudgementPosition(sum / stored_judgements_amount); + Width = 0; + this.ResizeWidthTo(1, 150, Easing.OutElasticHalf); + this.FadeTo(0.8f, 150).Then().FadeOut(judgement_fade_duration, Easing.OutQuint).Expire(); + } } } } diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorMeter.cs b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorMeter.cs index 848e892eaa..e4599eb2fc 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorMeter.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/HitErrorMeter.cs @@ -16,6 +16,6 @@ namespace osu.Game.Screens.Play.HitErrorDisplay HitWindows = hitWindows; } - public abstract void OnNewJudgement(JudgementResult newJudgement); + public abstract void OnNewJudgement(JudgementResult judgement); } } From 54696eef3990a1a93f2f707653d2b1fef5071ddc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 17:06:23 +0900 Subject: [PATCH 2658/5608] Reverse display, add animation and reduce width --- .../Gameplay/TestSceneBarHitErrorMeter.cs | 24 +++++--- .../Play/HitErrorDisplay/BarHitErrorMeter.cs | 59 +++++++++++-------- 2 files changed, 52 insertions(+), 31 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs index 28c5f0ae08..334e0d3b90 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs @@ -27,6 +27,7 @@ namespace osu.Game.Tests.Visual.Gameplay }; private HitErrorMeter meter; + private HitErrorMeter meter2; public TestSceneBarHitErrorMeter() { @@ -109,8 +110,8 @@ namespace osu.Game.Tests.Visual.Gameplay Add(new FillFlowContainer { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Direction = FillDirection.Vertical, AutoSizeAxes = Axes.Both, Children = new[] @@ -121,20 +122,29 @@ namespace osu.Game.Tests.Visual.Gameplay } }); - Add(meter = new BarHitErrorMeter(hitWindows) + Add(meter = new BarHitErrorMeter(hitWindows, true) { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + }); + + Add(meter2 = new BarHitErrorMeter(hitWindows, false) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, }); } private void newJudgement(double offset = 0) { - meter?.OnNewJudgement(new JudgementResult(new Judgement()) + var judgement = new JudgementResult(new Judgement()) { TimeOffset = offset == 0 ? RNG.Next(-150, 150) : offset, Type = HitResult.Perfect, - }); + }; + + meter.OnNewJudgement(judgement); + meter2.OnNewJudgement(judgement); } } } diff --git a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs index ffaada6ff4..7fb7b3cf99 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs @@ -25,19 +25,19 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private const int arrow_move_duration = 400; - private const int judgement_line_width = 8; + private const int judgement_line_width = 6; private const int bar_height = 200; - private const int bar_width = 3; + private const int bar_width = 2; - private const int spacing = 3; + private const int spacing = 2; - private readonly SpriteIcon arrow; + private SpriteIcon arrow; - private readonly FillFlowContainer bar; + private FillFlowContainer colourBarFlow; - private readonly Container judgementsContainer; + private Container judgementsContainer; private readonly double maxHitWindow; @@ -48,34 +48,39 @@ namespace osu.Game.Screens.Play.HitErrorDisplay maxHitWindow = Math.Max(Math.Max(HitWindows.Meh, HitWindows.Ok), HitWindows.Good); AutoSizeAxes = Axes.Both; + } - AddInternal(new FillFlowContainer + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + InternalChild = new FillFlowContainer { AutoSizeAxes = Axes.X, Height = bar_height, Direction = FillDirection.Horizontal, Spacing = new Vector2(spacing, 0), + Margin = new MarginPadding(2), Children = new Drawable[] { judgementsContainer = new Container { - Anchor = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, + Anchor = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, + Origin = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, Width = judgement_line_width, RelativeSizeAxes = Axes.Y, }, - bar = new FillFlowContainer + colourBarFlow = new FillFlowContainer { - Anchor = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, + Anchor = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, + Origin = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, Width = bar_width, RelativeSizeAxes = Axes.Y, Direction = FillDirection.Vertical, }, new Container { - Anchor = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, - Origin = rightAligned ? Anchor.CentreRight : Anchor.CentreLeft, + Anchor = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, + Origin = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, AutoSizeAxes = Axes.X, RelativeSizeAxes = Axes.Y, Child = arrow = new SpriteIcon @@ -84,20 +89,16 @@ namespace osu.Game.Screens.Play.HitErrorDisplay Origin = Anchor.Centre, RelativePositionAxes = Axes.Y, Y = 0.5f, - Icon = rightAligned ? FontAwesome.Solid.ChevronRight : FontAwesome.Solid.ChevronLeft, + Icon = rightAligned ? FontAwesome.Solid.ChevronLeft : FontAwesome.Solid.ChevronRight, Size = new Vector2(8), } }, } - }); - } + }; - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { if (HitWindows.Meh != 0) { - bar.AddRange(new[] + colourBarFlow.AddRange(new[] { createColoredPiece(ColourInfo.GradientVertical(colours.Yellow.Opacity(0), colours.Yellow), (maxHitWindow - HitWindows.Good) / (maxHitWindow * 2)), createColoredPiece(colours.Green, (HitWindows.Good - HitWindows.Great) / (maxHitWindow * 2)), @@ -108,7 +109,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay } else { - bar.AddRange(new[] + colourBarFlow.AddRange(new[] { createColoredPiece(ColourInfo.GradientVertical(colours.Green.Opacity(0), colours.Green), (HitWindows.Good - HitWindows.Great) / (maxHitWindow * 2)), createColoredPiece(colours.BlueLight, HitWindows.Great / maxHitWindow), @@ -117,6 +118,16 @@ namespace osu.Game.Screens.Play.HitErrorDisplay } } + protected override void LoadComplete() + { + base.LoadComplete(); + + colourBarFlow.Height = 0; + colourBarFlow.ResizeHeightTo(1, 400, Easing.OutQuint); + + arrow.FadeInFromZero(400); + } + private Box createColoredPiece(ColourInfo colour, double height) => new Box { RelativeSizeAxes = Axes.Both, @@ -134,8 +145,8 @@ namespace osu.Game.Screens.Play.HitErrorDisplay judgementsContainer.Add(new JudgementLine { Y = getRelativeJudgementPosition(judgement.TimeOffset), - Anchor = rightAligned ? Anchor.TopLeft : Anchor.TopRight, - Origin = rightAligned ? Anchor.TopLeft : Anchor.TopRight, + Anchor = rightAligned ? Anchor.TopRight : Anchor.TopLeft, + Origin = rightAligned ? Anchor.TopRight : Anchor.TopLeft, }); arrow.MoveToY(getRelativeJudgementPosition(floatingAverage = floatingAverage * 0.9 + judgement.TimeOffset * 0.1) From 40729356fa1d19849f15120851653c323c372388 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Aug 2019 17:34:02 +0900 Subject: [PATCH 2659/5608] Move beat divisor colour retrieval to BindableBeatDivisor --- osu.Game/Screens/Edit/BindableBeatDivisor.cs | 39 +++++++++++++++ .../Compose/Components/BeatDivisorControl.cs | 47 +++---------------- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index ea3b68e3bd..055077cc4f 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -4,6 +4,9 @@ using System; using System.Linq; using osu.Framework.Bindables; +using osu.Framework.Graphics.Colour; +using osu.Game.Graphics; +using osuTK.Graphics; namespace osu.Game.Screens.Edit { @@ -35,5 +38,41 @@ namespace osu.Game.Screens.Edit protected override int DefaultMinValue => VALID_DIVISORS.First(); protected override int DefaultMaxValue => VALID_DIVISORS.Last(); protected override int DefaultPrecision => 1; + + /// + /// Retrieves the appropriate colour for a beat divisor. + /// + /// The beat divisor. + /// The set of colours. + /// The applicable colour from for . + public ColourInfo GetColourFor(int beatDivisor, OsuColour colours) + { + switch (beatDivisor) + { + case 2: + return colours.BlueLight; + + case 4: + return colours.Blue; + + case 8: + return colours.BlueDarker; + + case 16: + return colours.PurpleDark; + + case 3: + return colours.YellowLight; + + case 6: + return colours.Yellow; + + case 12: + return colours.YellowDarker; + + default: + return Color4.White; + } + } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 0d16d8474b..ddcdfdaf80 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -188,6 +188,9 @@ namespace osu.Game.Screens.Edit.Compose.Components { private Marker marker; + [Resolved] + private OsuColour colours { get; set; } + private readonly BindableBeatDivisor beatDivisor; private readonly int[] availableDivisors; @@ -204,11 +207,12 @@ namespace osu.Game.Screens.Edit.Compose.Components { foreach (var t in availableDivisors) { - AddInternal(new Tick(t) + AddInternal(new Tick { Anchor = Anchor.TopLeft, Origin = Anchor.TopCentre, RelativePositionAxes = Axes.X, + Colour = beatDivisor.GetColourFor(t, colours), X = getMappedPosition(t) }); } @@ -284,11 +288,8 @@ namespace osu.Game.Screens.Edit.Compose.Components private class Tick : CompositeDrawable { - private readonly int divisor; - - public Tick(int divisor) + public Tick() { - this.divisor = divisor; Size = new Vector2(2.5f, 10); InternalChild = new Box { RelativeSizeAxes = Axes.Both }; @@ -296,42 +297,6 @@ namespace osu.Game.Screens.Edit.Compose.Components CornerRadius = 0.5f; Masking = true; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Colour = getColourForDivisor(divisor, colours); - } - - private ColourInfo getColourForDivisor(int divisor, OsuColour colours) - { - switch (divisor) - { - case 2: - return colours.BlueLight; - - case 4: - return colours.Blue; - - case 8: - return colours.BlueDarker; - - case 16: - return colours.PurpleDark; - - case 3: - return colours.YellowLight; - - case 6: - return colours.Yellow; - - case 12: - return colours.YellowDarker; - - default: - return Color4.White; - } - } } private class Marker : CompositeDrawable From 741bd0a5cffd4a972291054188cc139d62a7358d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 18:35:06 +0900 Subject: [PATCH 2660/5608] Fix incorrect colour sizes and simplify alignment specification --- .../Gameplay/TestSceneBarHitErrorMeter.cs | 4 +- osu.Game/Rulesets/Objects/HitWindows.cs | 13 ++ .../Play/HitErrorDisplay/BarHitErrorMeter.cs | 172 +++++++++++++----- 3 files changed, 140 insertions(+), 49 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs index 334e0d3b90..8852a27f50 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs @@ -37,8 +37,8 @@ namespace osu.Game.Tests.Visual.Gameplay AddRepeatStep("New random judgement", () => newJudgement(), 40); - AddRepeatStep("New max negative", () => newJudgement(-hitWindows.Meh), 20); - AddRepeatStep("New max positive", () => newJudgement(hitWindows.Meh), 20); + AddRepeatStep("New max negative", () => newJudgement(-hitWindows.HalfWindowFor(HitResult.Meh)), 20); + AddRepeatStep("New max positive", () => newJudgement(hitWindows.HalfWindowFor(HitResult.Meh)), 20); AddStep("New fixed judgement (50ms)", () => newJudgement(50)); } diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index fe099aaee7..e88af67c7c 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -65,6 +65,19 @@ namespace osu.Game.Rulesets.Objects return HitResult.None; } + /// + /// Retrieves a mapping of s to their half window timing for all allowed s. + /// + /// + public IEnumerable<(HitResult result, double length)> GetAllAvailableHalfWindows() + { + for (var result = HitResult.Meh; result <= HitResult.Perfect; ++result) + { + if (IsHitResultAllowed(result)) + yield return (result, HalfWindowFor(result)); + } + } + /// /// Check whether it is possible to achieve the provided . /// diff --git a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs index 7fb7b3cf99..5a2d892d7f 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs @@ -1,7 +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.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -11,15 +11,16 @@ using osuTK; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Objects; using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Colour; using osu.Game.Graphics; -using osu.Framework.Extensions.Color4Extensions; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Screens.Play.HitErrorDisplay { public class BarHitErrorMeter : HitErrorMeter { - private readonly bool rightAligned; + private readonly Anchor alignment; private const int judgement_fade_duration = 10000; @@ -35,17 +36,17 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private SpriteIcon arrow; - private FillFlowContainer colourBarFlow; + private Container colourBarsEarly; + private Container colourBarsLate; private Container judgementsContainer; - private readonly double maxHitWindow; + private double maxHitWindow; public BarHitErrorMeter(HitWindows hitWindows, bool rightAligned = false) : base(hitWindows) { - this.rightAligned = rightAligned; - maxHitWindow = Math.Max(Math.Max(HitWindows.Meh, HitWindows.Ok), HitWindows.Good); + alignment = rightAligned ? Anchor.x0 : Anchor.x2; AutoSizeAxes = Axes.Both; } @@ -64,23 +65,40 @@ namespace osu.Game.Screens.Play.HitErrorDisplay { judgementsContainer = new Container { - Anchor = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, - Origin = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, + Anchor = Anchor.y1 | alignment, + Origin = Anchor.y1 | alignment, Width = judgement_line_width, RelativeSizeAxes = Axes.Y, }, - colourBarFlow = new FillFlowContainer + colourBars = new Container { - Anchor = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, - Origin = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, Width = bar_width, RelativeSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, + Anchor = Anchor.y1 | alignment, + Origin = Anchor.y1 | alignment, + Children = new Drawable[] + { + colourBarsEarly = new Container + { + Anchor = Anchor.y1 | alignment, + Origin = alignment, + RelativeSizeAxes = Axes.Both, + Height = 0.5f, + Scale = new Vector2(1, -1), + }, + colourBarsLate = new Container + { + Anchor = Anchor.y1 | alignment, + Origin = alignment, + RelativeSizeAxes = Axes.Both, + Height = 0.5f, + }, + } }, new Container { - Anchor = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, - Origin = rightAligned ? Anchor.CentreLeft : Anchor.CentreRight, + Anchor = Anchor.y1 | alignment, + Origin = Anchor.y1 | alignment, AutoSizeAxes = Axes.X, RelativeSizeAxes = Axes.Y, Child = arrow = new SpriteIcon @@ -89,53 +107,111 @@ namespace osu.Game.Screens.Play.HitErrorDisplay Origin = Anchor.Centre, RelativePositionAxes = Axes.Y, Y = 0.5f, - Icon = rightAligned ? FontAwesome.Solid.ChevronLeft : FontAwesome.Solid.ChevronRight, + Icon = alignment == Anchor.x2 ? FontAwesome.Solid.ChevronRight : FontAwesome.Solid.ChevronLeft, Size = new Vector2(8), } }, } }; - if (HitWindows.Meh != 0) - { - colourBarFlow.AddRange(new[] - { - createColoredPiece(ColourInfo.GradientVertical(colours.Yellow.Opacity(0), colours.Yellow), (maxHitWindow - HitWindows.Good) / (maxHitWindow * 2)), - createColoredPiece(colours.Green, (HitWindows.Good - HitWindows.Great) / (maxHitWindow * 2)), - createColoredPiece(colours.BlueLight, HitWindows.Great / maxHitWindow), - createColoredPiece(colours.Green, (HitWindows.Good - HitWindows.Great) / (maxHitWindow * 2)), - createColoredPiece(ColourInfo.GradientVertical(colours.Yellow, colours.Yellow.Opacity(0)), (maxHitWindow - HitWindows.Good) / (maxHitWindow * 2)) - }); - } - else - { - colourBarFlow.AddRange(new[] - { - createColoredPiece(ColourInfo.GradientVertical(colours.Green.Opacity(0), colours.Green), (HitWindows.Good - HitWindows.Great) / (maxHitWindow * 2)), - createColoredPiece(colours.BlueLight, HitWindows.Great / maxHitWindow), - createColoredPiece(ColourInfo.GradientVertical(colours.Green, colours.Green.Opacity(0)), (HitWindows.Good - HitWindows.Great) / (maxHitWindow * 2)), - }); - } + createColourBars(colours); } protected override void LoadComplete() { base.LoadComplete(); - colourBarFlow.Height = 0; - colourBarFlow.ResizeHeightTo(1, 400, Easing.OutQuint); + colourBars.Height = 0; + colourBars.ResizeHeightTo(1, 800, Easing.OutQuint); - arrow.FadeInFromZero(400); + arrow.Alpha = 0.01f; + arrow.Delay(200).FadeInFromZero(600); } - private Box createColoredPiece(ColourInfo colour, double height) => new Box + private void createColourBars(OsuColour colours) { - RelativeSizeAxes = Axes.Both, - Colour = colour, - Height = (float)height - }; + var windows = HitWindows.GetAllAvailableHalfWindows().ToArray(); + + maxHitWindow = windows.First().length; + + for (var i = 0; i < windows.Length; i++) + { + var (result, length) = windows[i]; + + colourBarsEarly.Add(createColourBar(result, (float)(length / maxHitWindow), i == 0)); + colourBarsLate.Add(createColourBar(result, (float)(length / maxHitWindow), i == 0)); + } + + // a little nub to mark the centre point. + var centre = createColourBar(windows.Last().result, 0.01f); + centre.Anchor = centre.Origin = Anchor.y1 | alignment; + centre.Width = 1.5f; + colourBars.Add(centre); + + Color4 getColour(HitResult result) + { + switch (result) + { + case HitResult.Meh: + return colours.Yellow; + + case HitResult.Ok: + return colours.Green; + + case HitResult.Good: + return colours.GreenLight; + + case HitResult.Great: + return colours.Blue; + + default: + return colours.BlueLight; + } + } + + Drawable createColourBar(HitResult result, float height, bool first = false) + { + var colour = getColour(result); + + if (first) + { + // the first bar needs gradient rendering. + const float gradient_start = 0.8f; + + return new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = getColour(result), + Height = height * gradient_start + }, + new Box + { + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(colour, colour.Opacity(0)), + Y = gradient_start, + Height = height * (1 - gradient_start) + }, + } + }; + } + + return new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colour, + Height = height + }; + } + } private double floatingAverage; + private Container colourBars; public override void OnNewJudgement(JudgementResult judgement) { @@ -145,11 +221,12 @@ namespace osu.Game.Screens.Play.HitErrorDisplay judgementsContainer.Add(new JudgementLine { Y = getRelativeJudgementPosition(judgement.TimeOffset), - Anchor = rightAligned ? Anchor.TopRight : Anchor.TopLeft, - Origin = rightAligned ? Anchor.TopRight : Anchor.TopLeft, + Anchor = alignment == Anchor.x2 ? Anchor.x0 : Anchor.x2, + Origin = alignment == Anchor.x2 ? Anchor.x0 : Anchor.x2, }); - arrow.MoveToY(getRelativeJudgementPosition(floatingAverage = floatingAverage * 0.9 + judgement.TimeOffset * 0.1) + arrow.MoveToY( + getRelativeJudgementPosition(floatingAverage = floatingAverage * 0.9 + judgement.TimeOffset * 0.1) , arrow_move_duration, Easing.Out); } @@ -180,6 +257,7 @@ namespace osu.Game.Screens.Play.HitErrorDisplay base.LoadComplete(); Width = 0; + this.ResizeWidthTo(1, 150, Easing.OutElasticHalf); this.FadeTo(0.8f, 150).Then().FadeOut(judgement_fade_duration, Easing.OutQuint).Expire(); } From 8fc177b743d8a1b3c5300379b597c5487650cb31 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 18:46:42 +0900 Subject: [PATCH 2661/5608] Fix namespacing and hitwindow source --- .../Gameplay/TestSceneBarHitErrorMeter.cs | 2 +- .../HitErrorDisplay.cs | 22 ++++++++++--------- .../HitErrorMeters}/BarHitErrorMeter.cs | 18 +++++++-------- .../HitErrorMeters}/HitErrorMeter.cs | 2 +- osu.Game/Screens/Play/HUDOverlay.cs | 8 +++---- 5 files changed, 26 insertions(+), 26 deletions(-) rename osu.Game/Screens/Play/{HitErrorDisplay => HUD}/HitErrorDisplay.cs (87%) rename osu.Game/Screens/Play/{HitErrorDisplay => HUD/HitErrorMeters}/BarHitErrorMeter.cs (99%) rename osu.Game/Screens/Play/{HitErrorDisplay => HUD/HitErrorMeters}/HitErrorMeter.cs (91%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs index 8852a27f50..98826331e1 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs @@ -7,7 +7,6 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Catch.Objects; -using osu.Game.Screens.Play.HitErrorDisplay; using System; using System.Collections.Generic; using osu.Game.Rulesets.Judgements; @@ -16,6 +15,7 @@ using osu.Framework.MathUtils; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Game.Screens.Play.HUD.HitErrorMeters; namespace osu.Game.Tests.Visual.Gameplay { diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs similarity index 87% rename from osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs rename to osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index eaaf8e810c..0dcb1fee2b 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -1,19 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics; -using osu.Game.Rulesets.Scoring; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Game.Beatmaps; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Configuration; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; +using osu.Game.Screens.Play.HUD.HitErrorMeters; -namespace osu.Game.Screens.Play.HitErrorDisplay +namespace osu.Game.Screens.Play.HUD { public class HitErrorDisplay : Container { @@ -22,13 +21,17 @@ namespace osu.Game.Screens.Play.HitErrorDisplay private readonly Bindable type = new Bindable(); - private HitWindows hitWindows; + private readonly HitWindows hitWindows; private readonly ScoreProcessor processor; - public HitErrorDisplay(ScoreProcessor processor) + public HitErrorDisplay(ScoreProcessor processor, HitWindows hitWindows) { this.processor = processor; + this.hitWindows = hitWindows; + + RelativeSizeAxes = Axes.Both; + processor.NewJudgement += onNewJudgement; } @@ -45,10 +48,9 @@ namespace osu.Game.Screens.Play.HitErrorDisplay } [BackgroundDependencyLoader] - private void load(OsuConfigManager config, Bindable workingBeatmap) + private void load(OsuConfigManager config) { config.BindWith(OsuSetting.ScoreMeter, type); - hitWindows = workingBeatmap.Value.Beatmap.HitObjects.First().HitWindows; } protected override void LoadComplete() diff --git a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs similarity index 99% rename from osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs rename to osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 5a2d892d7f..22cccf30d7 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -2,21 +2,21 @@ // 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.Framework.Graphics.Shapes; -using osu.Game.Rulesets.Judgements; -using osuTK.Graphics; -using osuTK; -using osu.Framework.Graphics.Sprites; -using osu.Game.Rulesets.Objects; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; +using osuTK; +using osuTK.Graphics; -namespace osu.Game.Screens.Play.HitErrorDisplay +namespace osu.Game.Screens.Play.HUD.HitErrorMeters { public class BarHitErrorMeter : HitErrorMeter { diff --git a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs similarity index 91% rename from osu.Game/Screens/Play/HitErrorDisplay/HitErrorMeter.cs rename to osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs index e4599eb2fc..da1d9fff0d 100644 --- a/osu.Game/Screens/Play/HitErrorDisplay/HitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; -namespace osu.Game.Screens.Play.HitErrorDisplay +namespace osu.Game.Screens.Play.HUD.HitErrorMeters { public abstract class HitErrorMeter : CompositeDrawable { diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 79392221e4..21d5ae557f 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -33,7 +34,7 @@ namespace osu.Game.Screens.Play public readonly HealthDisplay HealthDisplay; public readonly SongProgress Progress; public readonly ModDisplay ModDisplay; - public readonly HitErrorDisplay.HitErrorDisplay HitErrorDisplay; + public readonly HitErrorDisplay HitErrorDisplay; public readonly HoldForMenuButton HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; @@ -258,10 +259,7 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20, Right = 10 }, }; - protected virtual HitErrorDisplay.HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay.HitErrorDisplay(scoreProcessor) - { - RelativeSizeAxes = Axes.Both, - }; + protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset.Objects.First().HitWindows); protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); From 171f88da409964efc0b56908fc30a0824ee20da9 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2019 09:47:18 +0000 Subject: [PATCH 2662/5608] Bump ppy.osu.Framework from 2019.830.0 to 2019.830.1 Bumps [ppy.osu.Framework](https://github.com/ppy/osu-framework) from 2019.830.0 to 2019.830.1. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.830.0...2019.830.1) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8e6ce2d1ba..330018d5cb 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 47cc6ec97a..298fbc6704 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,7 +118,7 @@ - + From c3abf0ccb7112f654910ef867a658986e517fa54 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 18:50:38 +0900 Subject: [PATCH 2663/5608] Improve visuals --- .../Play/HUD/HitErrorMeters/BarHitErrorMeter.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 22cccf30d7..4e32be3cda 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -22,8 +22,6 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { private readonly Anchor alignment; - private const int judgement_fade_duration = 10000; - private const int arrow_move_duration = 400; private const int judgement_line_width = 6; @@ -34,6 +32,8 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters private const int spacing = 2; + private const float chevron_size = 8; + private SpriteIcon arrow; private Container colourBarsEarly; @@ -99,7 +99,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { Anchor = Anchor.y1 | alignment, Origin = Anchor.y1 | alignment, - AutoSizeAxes = Axes.X, + Width = chevron_size, RelativeSizeAxes = Axes.Y, Child = arrow = new SpriteIcon { @@ -108,7 +108,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters RelativePositionAxes = Axes.Y, Y = 0.5f, Icon = alignment == Anchor.x2 ? FontAwesome.Solid.ChevronRight : FontAwesome.Solid.ChevronLeft, - Size = new Vector2(8), + Size = new Vector2(chevron_size), } }, } @@ -124,7 +124,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters colourBars.Height = 0; colourBars.ResizeHeightTo(1, 800, Easing.OutQuint); - arrow.Alpha = 0.01f; + arrow.Alpha = 0; arrow.Delay(200).FadeInFromZero(600); } @@ -234,11 +234,13 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters public class JudgementLine : CompositeDrawable { + private const int judgement_fade_duration = 10000; + public JudgementLine() { RelativeSizeAxes = Axes.X; RelativePositionAxes = Axes.Y; - Height = 2; + Height = 3; InternalChild = new CircularContainer { @@ -258,7 +260,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters Width = 0; - this.ResizeWidthTo(1, 150, Easing.OutElasticHalf); + this.ResizeWidthTo(1, 200, Easing.OutElasticHalf); this.FadeTo(0.8f, 150).Then().FadeOut(judgement_fade_duration, Easing.OutQuint).Expire(); } } From b639ce8e5d237c845adec63f26f5993df4140be8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2019 10:01:16 +0000 Subject: [PATCH 2664/5608] Bump ppy.osu.Framework.iOS from 2019.830.0 to 2019.830.1 Bumps [ppy.osu.Framework.iOS](https://github.com/ppy/osu-framework) from 2019.830.0 to 2019.830.1. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.830.0...2019.830.1) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 47cc6ec97a..afb0b9217e 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -119,7 +119,7 @@ - + From 815220de039ef25606591f5a0e0f7f1122952870 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2019 10:01:35 +0000 Subject: [PATCH 2665/5608] Bump ppy.osu.Framework.Android from 2019.830.0 to 2019.830.1 Bumps [ppy.osu.Framework.Android](https://github.com/ppy/osu-framework) from 2019.830.0 to 2019.830.1. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.830.0...2019.830.1) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index 2c3c8bcaad..93a9a073a4 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -61,6 +61,6 @@ - + From 80671cefd7db5e83b1059fdccaa3bc5a475bd603 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 19:14:07 +0900 Subject: [PATCH 2666/5608] Final visual polish --- .../HUD/HitErrorMeters/BarHitErrorMeter.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 4e32be3cda..51f9be4792 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -93,6 +93,22 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters RelativeSizeAxes = Axes.Both, Height = 0.5f, }, + new SpriteIcon + { + Y = -10, + Size = new Vector2(10), + Icon = FontAwesome.Solid.ShippingFast, + Anchor = Anchor.y0 | alignment, + Origin = Anchor.y0 | alignment, + }, + new SpriteIcon + { + Y = 10, + Size = new Vector2(10), + Icon = FontAwesome.Solid.Bicycle, + Anchor = Anchor.y2 | alignment, + Origin = Anchor.y2 | alignment, + } } }, new Container @@ -144,8 +160,8 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters // a little nub to mark the centre point. var centre = createColourBar(windows.Last().result, 0.01f); - centre.Anchor = centre.Origin = Anchor.y1 | alignment; - centre.Width = 1.5f; + centre.Anchor = centre.Origin = Anchor.y1 | (alignment == Anchor.x2 ? Anchor.x0 : Anchor.x2); + centre.Width = 2.5f; colourBars.Add(centre); Color4 getColour(HitResult result) From 665fc95d49c595b751d44ca5cf5bae91ae5bda58 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 19:37:20 +0900 Subject: [PATCH 2667/5608] Handle no hitobjects / no hitwindows (osu!catch) --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 3 +++ osu.Game/Screens/Play/HUDOverlay.cs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 0dcb1fee2b..2e28d17b80 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -63,6 +63,9 @@ namespace osu.Game.Screens.Play.HUD { Children.ForEach(c => c.FadeOut(fade_duration, Easing.OutQuint)); + if (hitWindows == null) + return; + switch (type.NewValue) { case ScoreMeterType.HitErrorBoth: diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 21d5ae557f..285737f7a8 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -259,7 +259,7 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20, Right = 10 }, }; - protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset.Objects.First().HitWindows); + protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset.Objects.FirstOrDefault().HitWindows); protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); From fab12fa9cd00043a9b820d7511ca2fcddb729d8d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Aug 2019 19:34:28 +0900 Subject: [PATCH 2668/5608] Centre align the icons Seems to look better this way. --- .../Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 51f9be4792..7d3b0ae141 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -98,16 +98,16 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters Y = -10, Size = new Vector2(10), Icon = FontAwesome.Solid.ShippingFast, - Anchor = Anchor.y0 | alignment, - Origin = Anchor.y0 | alignment, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, }, new SpriteIcon { Y = 10, Size = new Vector2(10), Icon = FontAwesome.Solid.Bicycle, - Anchor = Anchor.y2 | alignment, - Origin = Anchor.y2 | alignment, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, } } }, From 8b4976ad92399c19acffa4275710eaffe3d9ff02 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Aug 2019 19:37:18 +0900 Subject: [PATCH 2669/5608] Remove unnecessary intermediate OD tests --- .../Gameplay/TestSceneBarHitErrorMeter.cs | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs index 98826331e1..d317c6551f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs @@ -46,14 +46,6 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestOsu() { AddStep("OD 1", () => recreateDisplay(new OsuHitWindows(), 1)); - AddStep("OD 2", () => recreateDisplay(new OsuHitWindows(), 2)); - AddStep("OD 3", () => recreateDisplay(new OsuHitWindows(), 3)); - AddStep("OD 4", () => recreateDisplay(new OsuHitWindows(), 4)); - AddStep("OD 5", () => recreateDisplay(new OsuHitWindows(), 5)); - AddStep("OD 6", () => recreateDisplay(new OsuHitWindows(), 6)); - AddStep("OD 7", () => recreateDisplay(new OsuHitWindows(), 7)); - AddStep("OD 8", () => recreateDisplay(new OsuHitWindows(), 8)); - AddStep("OD 9", () => recreateDisplay(new OsuHitWindows(), 9)); AddStep("OD 10", () => recreateDisplay(new OsuHitWindows(), 10)); } @@ -61,14 +53,6 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestTaiko() { AddStep("OD 1", () => recreateDisplay(new TaikoHitWindows(), 1)); - AddStep("OD 2", () => recreateDisplay(new TaikoHitWindows(), 2)); - AddStep("OD 3", () => recreateDisplay(new TaikoHitWindows(), 3)); - AddStep("OD 4", () => recreateDisplay(new TaikoHitWindows(), 4)); - AddStep("OD 5", () => recreateDisplay(new TaikoHitWindows(), 5)); - AddStep("OD 6", () => recreateDisplay(new TaikoHitWindows(), 6)); - AddStep("OD 7", () => recreateDisplay(new TaikoHitWindows(), 7)); - AddStep("OD 8", () => recreateDisplay(new TaikoHitWindows(), 8)); - AddStep("OD 9", () => recreateDisplay(new TaikoHitWindows(), 9)); AddStep("OD 10", () => recreateDisplay(new TaikoHitWindows(), 10)); } @@ -76,14 +60,6 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestMania() { AddStep("OD 1", () => recreateDisplay(new ManiaHitWindows(), 1)); - AddStep("OD 2", () => recreateDisplay(new ManiaHitWindows(), 2)); - AddStep("OD 3", () => recreateDisplay(new ManiaHitWindows(), 3)); - AddStep("OD 4", () => recreateDisplay(new ManiaHitWindows(), 4)); - AddStep("OD 5", () => recreateDisplay(new ManiaHitWindows(), 5)); - AddStep("OD 6", () => recreateDisplay(new ManiaHitWindows(), 6)); - AddStep("OD 7", () => recreateDisplay(new ManiaHitWindows(), 7)); - AddStep("OD 8", () => recreateDisplay(new ManiaHitWindows(), 8)); - AddStep("OD 9", () => recreateDisplay(new ManiaHitWindows(), 9)); AddStep("OD 10", () => recreateDisplay(new ManiaHitWindows(), 10)); } @@ -91,14 +67,6 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestCatch() { AddStep("OD 1", () => recreateDisplay(new CatchHitWindows(), 1)); - AddStep("OD 2", () => recreateDisplay(new CatchHitWindows(), 2)); - AddStep("OD 3", () => recreateDisplay(new CatchHitWindows(), 3)); - AddStep("OD 4", () => recreateDisplay(new CatchHitWindows(), 4)); - AddStep("OD 5", () => recreateDisplay(new CatchHitWindows(), 5)); - AddStep("OD 6", () => recreateDisplay(new CatchHitWindows(), 6)); - AddStep("OD 7", () => recreateDisplay(new CatchHitWindows(), 7)); - AddStep("OD 8", () => recreateDisplay(new CatchHitWindows(), 8)); - AddStep("OD 9", () => recreateDisplay(new CatchHitWindows(), 9)); AddStep("OD 10", () => recreateDisplay(new CatchHitWindows(), 10)); } From 6fb8a6cdbe894343c98a54e115c97a2451264717 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Aug 2019 19:47:13 +0900 Subject: [PATCH 2670/5608] Fix testcases not working for OD10 --- .../Visual/Gameplay/TestSceneBarHitErrorMeter.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs index d317c6551f..f20440249b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs @@ -28,12 +28,11 @@ namespace osu.Game.Tests.Visual.Gameplay private HitErrorMeter meter; private HitErrorMeter meter2; + private HitWindows hitWindows; public TestSceneBarHitErrorMeter() { - var hitWindows = new OsuHitWindows(); - - recreateDisplay(hitWindows, 5); + recreateDisplay(new OsuHitWindows(), 5); AddRepeatStep("New random judgement", () => newJudgement(), 40); @@ -72,7 +71,9 @@ namespace osu.Game.Tests.Visual.Gameplay private void recreateDisplay(HitWindows hitWindows, float overallDifficulty) { - hitWindows.SetDifficulty(overallDifficulty); + this.hitWindows = hitWindows; + + hitWindows?.SetDifficulty(overallDifficulty); Clear(); @@ -84,9 +85,9 @@ namespace osu.Game.Tests.Visual.Gameplay AutoSizeAxes = Axes.Both, Children = new[] { - new SpriteText { Text = $@"Great: {hitWindows.Great}" }, - new SpriteText { Text = $@"Good: {hitWindows.Good}" }, - new SpriteText { Text = $@"Meh: {hitWindows.Meh}" }, + new SpriteText { Text = $@"Great: {hitWindows?.Great}" }, + new SpriteText { Text = $@"Good: {hitWindows?.Good}" }, + new SpriteText { Text = $@"Meh: {hitWindows?.Meh}" }, } }); From dfccc6036109226ca4be14cd92ca38f6fd3e6d5c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Aug 2019 19:47:21 +0900 Subject: [PATCH 2671/5608] Reorder HitErrorDisplay --- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 2e28d17b80..cdfa0e993b 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -35,18 +35,6 @@ namespace osu.Game.Screens.Play.HUD processor.NewJudgement += onNewJudgement; } - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - processor.NewJudgement -= onNewJudgement; - } - - private void onNewJudgement(JudgementResult result) - { - foreach (var c in Children) - c.OnNewJudgement(result); - } - [BackgroundDependencyLoader] private void load(OsuConfigManager config) { @@ -59,6 +47,12 @@ namespace osu.Game.Screens.Play.HUD type.BindValueChanged(typeChanged, true); } + private void onNewJudgement(JudgementResult result) + { + foreach (var c in Children) + c.OnNewJudgement(result); + } + private void typeChanged(ValueChangedEvent type) { Children.ForEach(c => c.FadeOut(fade_duration, Easing.OutQuint)); @@ -96,5 +90,11 @@ namespace osu.Game.Screens.Play.HUD Add(display); display.FadeInFromZero(fade_duration, Easing.OutQuint); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + processor.NewJudgement -= onNewJudgement; + } } } From fc813347ac522fad92e2b88b022ab2561957b6ee Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Aug 2019 19:54:36 +0900 Subject: [PATCH 2672/5608] Make JudgementLine private --- osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 7d3b0ae141..d5d3cb528e 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -248,7 +248,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters private float getRelativeJudgementPosition(double value) => (float)((value / maxHitWindow) + 1) / 2; - public class JudgementLine : CompositeDrawable + private class JudgementLine : CompositeDrawable { private const int judgement_fade_duration = 10000; From f1db6c7039c1bbc037c36c0449a599f9a6694497 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Aug 2019 20:18:21 +0900 Subject: [PATCH 2673/5608] Fix likely nullref --- osu.Game/Screens/Play/HUDOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 285737f7a8..8e642ea552 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -259,7 +259,7 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20, Right = 10 }, }; - protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset.Objects.FirstOrDefault().HitWindows); + protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset.Objects.FirstOrDefault()?.HitWindows); protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); From 2876588193897bc9128bb62041c0e6adbc13941b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2019 13:36:31 +0000 Subject: [PATCH 2674/5608] Bump NUnit3TestAdapter from 3.15.0 to 3.15.1 Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 3.15.0 to 3.15.1. - [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases) - [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V3.15...V3.15.1) Signed-off-by: dependabot-preview[bot] --- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 7c282f449b..c527a81f51 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index 4dcfc1b81f..af10d5e06e 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 197309c7c4..c331c811d2 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index a5db1625d9..d2a0a8fa6f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 4a9d88f3a6..84f67c9319 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 2a8bd393da..bba3c92245 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -7,7 +7,7 @@ - + WinExe From 6e5cb8a318840fc1b1e156f8583641d4881cfd84 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 30 Aug 2019 23:19:34 +0300 Subject: [PATCH 2675/5608] implement video parsing --- osu.Game/Beatmaps/BeatmapManager.cs | 2 ++ .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 16 ++++++++++++++++ osu.Game/Beatmaps/BeatmapMetadata.cs | 4 +++- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 3 +++ .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 9 +++++++-- osu.Game/Beatmaps/IWorkingBeatmap.cs | 6 ++++++ osu.Game/Beatmaps/WorkingBeatmap.cs | 9 +++++++++ .../20171019041408_InitialCreate.Designer.cs | 2 ++ .../Migrations/20171019041408_InitialCreate.cs | 1 + ...171025071459_AddMissingIndexRules.Designer.cs | 2 ++ ...ddBeatmapOnlineIDUniqueConstraint.Designer.cs | 2 ++ ...209034410_AddRulesetInfoShortName.Designer.cs | 2 ++ .../20180125143340_Settings.Designer.cs | 2 ++ .../20180219060912_AddSkins.Designer.cs | 2 ++ ...55154_RemoveUniqueHashConstraints.Designer.cs | 2 ++ ...044111_UpdateTaikoDefaultBindings.Designer.cs | 2 ++ ...180628011956_RemoveNegativeSetIDs.Designer.cs | 2 ++ .../20180913080842_AddRankStatus.Designer.cs | 2 ++ .../20181007180454_StandardizePaths.Designer.cs | 2 ++ .../20181007180454_StandardizePaths.cs | 1 + .../20181128100659_AddSkinInfoHash.Designer.cs | 2 ++ ...20181130113755_AddScoreInfoTables.Designer.cs | 2 ++ .../20190225062029_AddUserIDColumn.Designer.cs | 2 ++ .../20190525060824_SkinSettings.Designer.cs | 2 ++ ...46_AddDateAddedColumnToBeatmapSet.Designer.cs | 2 ++ ...0708070844_AddBPMAndLengthColumns.Designer.cs | 2 ++ osu.Game/Migrations/OsuDbContextModelSnapshot.cs | 2 ++ osu.Game/Screens/Edit/EditorWorkingBeatmap.cs | 3 +++ osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs | 3 +++ osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 3 +++ 30 files changed, 93 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 166ba5111c..b9ed3664ef 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -13,6 +13,7 @@ using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Extensions; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Framework.Lists; using osu.Framework.Logging; using osu.Framework.Platform; @@ -340,6 +341,7 @@ namespace osu.Game.Beatmaps protected override IBeatmap GetBeatmap() => beatmap; protected override Texture GetBackground() => null; + protected override VideoSprite GetVideo() => null; protected override Track GetTrack() => null; } diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 5bbffc2f77..1d00c94ef2 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Game.Beatmaps.Formats; @@ -64,6 +65,21 @@ namespace osu.Game.Beatmaps } } + protected override VideoSprite GetVideo() + { + if (Metadata?.VideoFile == null) + return null; + + try + { + return new VideoSprite(textureStore.GetStream(getPathForFile(Metadata.VideoFile))); + } + catch + { + return null; + } + } + protected override Track GetTrack() { try diff --git a/osu.Game/Beatmaps/BeatmapMetadata.cs b/osu.Game/Beatmaps/BeatmapMetadata.cs index 001f319307..9267527d79 100644 --- a/osu.Game/Beatmaps/BeatmapMetadata.cs +++ b/osu.Game/Beatmaps/BeatmapMetadata.cs @@ -52,6 +52,7 @@ namespace osu.Game.Beatmaps public int PreviewTime { get; set; } public string AudioFile { get; set; } public string BackgroundFile { get; set; } + public string VideoFile { get; set; } public override string ToString() => $"{Artist} - {Title} ({Author})"; @@ -81,7 +82,8 @@ namespace osu.Game.Beatmaps && Tags == other.Tags && PreviewTime == other.PreviewTime && AudioFile == other.AudioFile - && BackgroundFile == other.BackgroundFile; + && BackgroundFile == other.BackgroundFile + && VideoFile == other.VideoFile; } } } diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 29ade24328..a3ab01c886 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -7,6 +7,7 @@ using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Game.Rulesets; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; @@ -44,6 +45,8 @@ namespace osu.Game.Beatmaps protected override Texture GetBackground() => textures?.Get(@"Backgrounds/bg4"); + protected override VideoSprite GetVideo() => null; + protected override Track GetTrack() => GetVirtualTrack(); private class DummyRulesetInfo : RulesetInfo diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 02d969b571..0532790f0a 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -296,8 +296,13 @@ namespace osu.Game.Beatmaps.Formats switch (type) { case EventType.Background: - string filename = split[2].Trim('"'); - beatmap.BeatmapInfo.Metadata.BackgroundFile = FileSafety.PathStandardise(filename); + string bgFilename = split[2].Trim('"'); + beatmap.BeatmapInfo.Metadata.BackgroundFile = FileSafety.PathStandardise(bgFilename); + break; + + case EventType.Video: + string videoFilename = split[2].Trim('"'); + beatmap.BeatmapInfo.Metadata.VideoFile = FileSafety.PathStandardise(videoFilename); break; case EventType.Break: diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index 44071d9cc1..b932e67bae 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; @@ -25,6 +26,11 @@ namespace osu.Game.Beatmaps /// Texture Background { get; } + /// + /// Retrieves the video file for this . + /// + VideoSprite Video { get; } + /// /// Retrieves the audio track for this . /// diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index d8ab411beb..b489936556 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -19,6 +19,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; using osu.Game.Skinning; +using osu.Framework.Graphics.Video; namespace osu.Game.Beatmaps { @@ -43,6 +44,7 @@ namespace osu.Game.Beatmaps track = new RecyclableLazy(() => GetTrack() ?? GetVirtualTrack()); background = new RecyclableLazy(GetBackground, BackgroundStillValid); + video = new RecyclableLazy(GetVideo); waveform = new RecyclableLazy(GetWaveform); storyboard = new RecyclableLazy(GetStoryboard); skin = new RecyclableLazy(GetSkin); @@ -183,9 +185,16 @@ namespace osu.Game.Beatmaps public bool BackgroundLoaded => background.IsResultAvailable; public Texture Background => background.Value; protected virtual bool BackgroundStillValid(Texture b) => b == null || b.Available; + protected abstract Texture GetBackground(); private readonly RecyclableLazy background; + public bool VideoLoaded => video.IsResultAvailable; + public VideoSprite Video => video.Value; + + protected abstract VideoSprite GetVideo(); + private readonly RecyclableLazy video; + public bool TrackLoaded => track.IsResultAvailable; public Track Track => track.Value; protected abstract Track GetTrack(); diff --git a/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs b/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs index c751530bf4..596d80557b 100644 --- a/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs +++ b/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs @@ -123,6 +123,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20171019041408_InitialCreate.cs b/osu.Game/Migrations/20171019041408_InitialCreate.cs index 9b6881f98c..3349998873 100644 --- a/osu.Game/Migrations/20171019041408_InitialCreate.cs +++ b/osu.Game/Migrations/20171019041408_InitialCreate.cs @@ -35,6 +35,7 @@ namespace osu.Game.Migrations AudioFile = table.Column(type: "TEXT", nullable: true), Author = table.Column(type: "TEXT", nullable: true), BackgroundFile = table.Column(type: "TEXT", nullable: true), + VideoFile = table.Column(type: "TEXT", nullable: true), PreviewTime = table.Column(type: "INTEGER", nullable: false), Source = table.Column(type: "TEXT", nullable: true), Tags = table.Column(type: "TEXT", nullable: true), diff --git a/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs b/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs index 4cd234f2ef..ab85aece9f 100644 --- a/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs +++ b/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs @@ -125,6 +125,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs b/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs index 006acf12cd..d565e1cbf2 100644 --- a/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs +++ b/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs @@ -128,6 +128,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs b/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs index fc2496bc24..3c37c59595 100644 --- a/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs +++ b/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs @@ -128,6 +128,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180125143340_Settings.Designer.cs b/osu.Game/Migrations/20180125143340_Settings.Designer.cs index 4bb599eec1..4c41d223c5 100644 --- a/osu.Game/Migrations/20180125143340_Settings.Designer.cs +++ b/osu.Game/Migrations/20180125143340_Settings.Designer.cs @@ -128,6 +128,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs b/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs index cdc4ef2e66..124c61283f 100644 --- a/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs +++ b/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs @@ -128,6 +128,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs b/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs index f28408bfb3..9cbd75ce2c 100644 --- a/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs +++ b/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs @@ -126,6 +126,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs b/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs index aaa11e88b6..150bc2ecbc 100644 --- a/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs +++ b/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs @@ -125,6 +125,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs b/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs index 7eeacd56d7..0a1db37c7f 100644 --- a/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs +++ b/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs @@ -125,6 +125,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs b/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs index 5ab43da046..b04d36fac1 100644 --- a/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs +++ b/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs b/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs index b387a45ecf..aed946e577 100644 --- a/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs +++ b/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20181007180454_StandardizePaths.cs b/osu.Game/Migrations/20181007180454_StandardizePaths.cs index 274b8030a9..c106b839e2 100644 --- a/osu.Game/Migrations/20181007180454_StandardizePaths.cs +++ b/osu.Game/Migrations/20181007180454_StandardizePaths.cs @@ -15,6 +15,7 @@ namespace osu.Game.Migrations migrationBuilder.Sql($"UPDATE `BeatmapInfo` SET `Path` = REPLACE(`Path`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `BeatmapMetadata` SET `AudioFile` = REPLACE(`AudioFile`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `BeatmapMetadata` SET `BackgroundFile` = REPLACE(`BackgroundFile`, '{windowsStyle}', '{standardized}')"); + migrationBuilder.Sql($"UPDATE `BeatmapMetadata` SET `VideoFile` = REPLACE(`VideoFile`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `BeatmapSetFileInfo` SET `Filename` = REPLACE(`Filename`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `SkinFileInfo` SET `Filename` = REPLACE(`Filename`, '{windowsStyle}', '{standardized}')"); } diff --git a/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs b/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs index 120674671a..fe0594e542 100644 --- a/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs +++ b/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs b/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs index eee53182ce..efa64f014f 100644 --- a/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs +++ b/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs b/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs index 8e1e3a59f3..a950a54e39 100644 --- a/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs +++ b/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs b/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs index 348c42adb9..df2c434b4e 100644 --- a/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs +++ b/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs b/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs index 9477369aa0..ea699edcc9 100644 --- a/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs +++ b/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs b/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs index c5fcc16f84..fb678178a2 100644 --- a/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs +++ b/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs @@ -131,6 +131,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 761dca2801..1725812d33 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -129,6 +129,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs b/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs index 299059407c..4b8720fe1c 100644 --- a/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -33,6 +34,8 @@ namespace osu.Game.Screens.Edit public Texture Background => workingBeatmap.Background; + public VideoSprite Video => workingBeatmap.Video; + public Track Track => workingBeatmap.Track; public Waveform Waveform => workingBeatmap.Waveform; diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index a555a52e42..3fc9662b17 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -10,6 +10,7 @@ using Newtonsoft.Json; using NUnit.Framework; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.Rulesets; @@ -201,6 +202,8 @@ namespace osu.Game.Tests.Beatmaps protected override Texture GetBackground() => throw new NotImplementedException(); + protected override VideoSprite GetVideo() => throw new NotImplementedException(); + protected override Track GetTrack() => throw new NotImplementedException(); protected override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index 0ef35879e3..0d9f4f51be 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -3,6 +3,7 @@ using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Game.Beatmaps; namespace osu.Game.Tests.Beatmaps @@ -25,6 +26,8 @@ namespace osu.Game.Tests.Beatmaps protected override Texture GetBackground() => null; + protected override VideoSprite GetVideo() => null; + protected override Track GetTrack() => null; } } From 58a0b4e19b2f5cfe29e9a98e3d33d314ffd9c277 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 30 Aug 2019 23:19:55 +0300 Subject: [PATCH 2676/5608] Add basic layout for player --- osu.Game/Screens/Play/Player.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index b487f3e61b..9ff52d8444 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -10,6 +10,7 @@ using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Video; using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Framework.Screens; @@ -81,6 +82,8 @@ namespace osu.Game.Screens.Play protected DimmableStoryboard DimmableStoryboard { get; private set; } + protected VideoSprite Video { get; private set; } + [Cached] [Cached(Type = typeof(IBindable>))] protected new readonly Bindable> Mods = new Bindable>(Array.Empty()); @@ -143,6 +146,14 @@ namespace osu.Game.Screens.Play private void addUnderlayComponents(Container target) { target.Add(DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both }); + + var video = Beatmap.Value.Video; + + if (video != null) + { + target.Add(Video = video); + Video.RelativeSizeAxes = Axes.Both; + } } private void addGameplayComponents(Container target, WorkingBeatmap working) From d55be4d59cd645e3dcde3d60c28c266235127115 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 30 Aug 2019 23:48:38 +0300 Subject: [PATCH 2677/5608] Implement DimmableVideo component --- osu.Game/Screens/Play/DimmableVideo.cs | 64 ++++++++++++++++++++++++++ osu.Game/Screens/Play/Player.cs | 10 +--- 2 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Screens/Play/DimmableVideo.cs diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs new file mode 100644 index 0000000000..68ce5fcd40 --- /dev/null +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -0,0 +1,64 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Video; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Screens.Play +{ + public class DimmableVideo : UserDimContainer + { + private readonly VideoSprite video; + private DrawableVideo drawableVideo; + + public DimmableVideo(VideoSprite video) + { + this.video = video; + } + + [BackgroundDependencyLoader] + private void load() + { + initializeVideo(false); + } + + protected override void LoadComplete() + { + ShowStoryboard.BindValueChanged(_ => initializeVideo(true), true); + base.LoadComplete(); + } + + protected override bool ShowDimContent => ShowStoryboard.Value && DimLevel < 1; + + private void initializeVideo(bool async) + { + if (drawableVideo != null) + return; + + if (!ShowStoryboard.Value) + return; + + drawableVideo = new DrawableVideo(video); + + if (async) + LoadComponentAsync(drawableVideo, Add); + else + Add(drawableVideo); + } + + private class DrawableVideo : Container + { + public DrawableVideo(VideoSprite video) + { + RelativeSizeAxes = Axes.Both; + Masking = true; + + AddInternal(video); + video.RelativeSizeAxes = Axes.Both; + } + } + } +} diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 9ff52d8444..968b78ad8e 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -81,6 +81,7 @@ namespace osu.Game.Screens.Play protected GameplayClockContainer GameplayClockContainer { get; private set; } protected DimmableStoryboard DimmableStoryboard { get; private set; } + protected DimmableVideo DimmableVideo { get; private set; } protected VideoSprite Video { get; private set; } @@ -146,14 +147,7 @@ namespace osu.Game.Screens.Play private void addUnderlayComponents(Container target) { target.Add(DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both }); - - var video = Beatmap.Value.Video; - - if (video != null) - { - target.Add(Video = video); - Video.RelativeSizeAxes = Axes.Both; - } + target.Add(DimmableVideo = new DimmableVideo(Beatmap.Value.Video) { RelativeSizeAxes = Axes.Both }); } private void addGameplayComponents(Container target, WorkingBeatmap working) From 5dd688a51b841f534070fe3066905817a9dec8c4 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 00:09:23 +0300 Subject: [PATCH 2678/5608] Fix video doesn't use gameplay clock --- osu.Game/Screens/Play/DimmableVideo.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index 68ce5fcd40..bc4105c3b9 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -59,6 +59,13 @@ namespace osu.Game.Screens.Play AddInternal(video); video.RelativeSizeAxes = Axes.Both; } + + [BackgroundDependencyLoader] + private void load(GameplayClock clock) + { + if (clock != null) + Clock = clock; + } } } } From fa3591e5ec35b80115b3ed3005067ef1ae05231a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 00:42:20 +0300 Subject: [PATCH 2679/5608] Add setting to turn on/off the video --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ osu.Game/Graphics/Containers/UserDimContainer.cs | 4 ++++ .../Overlays/Settings/Sections/Graphics/DetailSettings.cs | 5 +++++ osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs | 2 +- osu.Game/Screens/Play/DimmableVideo.cs | 6 +++--- osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs | 3 +++ 6 files changed, 18 insertions(+), 4 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 0cecbb225f..357883da45 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -69,6 +69,7 @@ namespace osu.Game.Configuration Set(OsuSetting.ShowFpsDisplay, false); Set(OsuSetting.ShowStoryboard, true); + Set(OsuSetting.ShowVideo, true); Set(OsuSetting.BeatmapSkins, true); Set(OsuSetting.BeatmapHitsounds, true); @@ -136,6 +137,7 @@ namespace osu.Game.Configuration DimLevel, BlurLevel, ShowStoryboard, + ShowVideo, KeyOverlay, ScoreMeter, FloatingComments, diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 2b7635cc88..d0e932fac0 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -35,6 +35,8 @@ namespace osu.Game.Graphics.Containers protected Bindable ShowStoryboard { get; private set; } + protected Bindable ShowVideo { get; private set; } + protected double DimLevel => EnableUserDim.Value ? UserDimLevel.Value : 0; protected override Container Content => dimContent; @@ -54,10 +56,12 @@ namespace osu.Game.Graphics.Containers { UserDimLevel = config.GetBindable(OsuSetting.DimLevel); ShowStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); + ShowVideo = config.GetBindable(OsuSetting.ShowVideo); EnableUserDim.ValueChanged += _ => UpdateVisuals(); UserDimLevel.ValueChanged += _ => UpdateVisuals(); ShowStoryboard.ValueChanged += _ => UpdateVisuals(); + ShowVideo.ValueChanged += _ => UpdateVisuals(); StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals(); } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index 01cdc9aa32..6d9870598f 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -22,6 +22,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Bindable = config.GetBindable(OsuSetting.ShowStoryboard) }, new SettingsCheckbox + { + LabelText = "Video", + Bindable = config.GetBindable(OsuSetting.ShowVideo) + }, + new SettingsCheckbox { LabelText = "Rotate cursor when dragging", Bindable = config.GetBindable(OsuSetting.CursorRotation) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 5225740d0b..2730b0b90d 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -178,7 +178,7 @@ namespace osu.Game.Screens.Backgrounds BlurAmount.ValueChanged += _ => UpdateVisuals(); } - protected override bool ShowDimContent => !ShowStoryboard.Value || !StoryboardReplacesBackground.Value; // The background needs to be hidden in the case of it being replaced by the storyboard + protected override bool ShowDimContent => !ShowStoryboard.Value || !StoryboardReplacesBackground.Value || !ShowVideo.Value; // The background needs to be hidden in the case of it being replaced by the storyboard protected override void UpdateVisuals() { diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index bc4105c3b9..0452af8419 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -27,18 +27,18 @@ namespace osu.Game.Screens.Play protected override void LoadComplete() { - ShowStoryboard.BindValueChanged(_ => initializeVideo(true), true); + ShowVideo.BindValueChanged(_ => initializeVideo(true), true); base.LoadComplete(); } - protected override bool ShowDimContent => ShowStoryboard.Value && DimLevel < 1; + protected override bool ShowDimContent => ShowVideo.Value && DimLevel < 1; private void initializeVideo(bool async) { if (drawableVideo != null) return; - if (!ShowStoryboard.Value) + if (!ShowVideo.Value) return; drawableVideo = new DrawableVideo(video); diff --git a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs index 1c8628f704..5e47b730ad 100644 --- a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs @@ -15,6 +15,7 @@ namespace osu.Game.Screens.Play.PlayerSettings private readonly PlayerSliderBar dimSliderBar; private readonly PlayerSliderBar blurSliderBar; private readonly PlayerCheckbox showStoryboardToggle; + private readonly PlayerCheckbox showVideoToggle; private readonly PlayerCheckbox beatmapSkinsToggle; private readonly PlayerCheckbox beatmapHitsoundsToggle; @@ -37,6 +38,7 @@ namespace osu.Game.Screens.Play.PlayerSettings Text = "Toggles:" }, showStoryboardToggle = new PlayerCheckbox { LabelText = "Storyboards" }, + showVideoToggle = new PlayerCheckbox { LabelText = "Video" }, beatmapSkinsToggle = new PlayerCheckbox { LabelText = "Beatmap skins" }, beatmapHitsoundsToggle = new PlayerCheckbox { LabelText = "Beatmap hitsounds" } }; @@ -48,6 +50,7 @@ namespace osu.Game.Screens.Play.PlayerSettings dimSliderBar.Bindable = config.GetBindable(OsuSetting.DimLevel); blurSliderBar.Bindable = config.GetBindable(OsuSetting.BlurLevel); showStoryboardToggle.Current = config.GetBindable(OsuSetting.ShowStoryboard); + showVideoToggle.Current = config.GetBindable(OsuSetting.ShowVideo); beatmapSkinsToggle.Current = config.GetBindable(OsuSetting.BeatmapSkins); beatmapHitsoundsToggle.Current = config.GetBindable(OsuSetting.BeatmapHitsounds); } From 264441d90c0662edfdcf722e7806f9997551c0de Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 02:42:26 +0300 Subject: [PATCH 2680/5608] Fix broken test --- osu.Game.Tests/WaveformTestBeatmap.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index 3e0df8d45e..db9576b5fa 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -6,6 +6,7 @@ using System.Linq; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.IO.Archives; @@ -42,6 +43,8 @@ namespace osu.Game.Tests protected override Texture GetBackground() => null; + protected override VideoSprite GetVideo() => null; + protected override Waveform GetWaveform() => new Waveform(trackStore.GetStream(firstAudioFile)); protected override Track GetTrack() => trackStore.Get(firstAudioFile); From fd958ec1abb31f182b673dc2b13223df9a854560 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 02:56:41 +0300 Subject: [PATCH 2681/5608] Remove unused property accessor --- osu.Game/Screens/Play/Player.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 968b78ad8e..b5a378506a 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -83,8 +83,6 @@ namespace osu.Game.Screens.Play protected DimmableStoryboard DimmableStoryboard { get; private set; } protected DimmableVideo DimmableVideo { get; private set; } - protected VideoSprite Video { get; private set; } - [Cached] [Cached(Type = typeof(IBindable>))] protected new readonly Bindable> Mods = new Bindable>(Array.Empty()); From d4291556eef6a67926b0dffd855c933abfc1ab82 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 02:57:14 +0300 Subject: [PATCH 2682/5608] Remove unused using --- osu.Game/Screens/Play/Player.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index b5a378506a..274107dfa5 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -10,7 +10,6 @@ using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Video; using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Framework.Screens; From 1ddf292ad687878c0acf8ef247a0060ba08a5d5c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Aug 2019 12:20:50 +0900 Subject: [PATCH 2683/5608] Fix vertical alignment of hit error display ticks Wasn't correctly centered before. --- osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index d5d3cb528e..594dd64e52 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -238,7 +238,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { Y = getRelativeJudgementPosition(judgement.TimeOffset), Anchor = alignment == Anchor.x2 ? Anchor.x0 : Anchor.x2, - Origin = alignment == Anchor.x2 ? Anchor.x0 : Anchor.x2, + Origin = Anchor.y1 | (alignment == Anchor.x2 ? Anchor.x0 : Anchor.x2), }); arrow.MoveToY( From f89981e1a330c3105e7fe87481f7a0df6721fa32 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Aug 2019 12:23:15 +0900 Subject: [PATCH 2684/5608] Fix legacy skin text reading from the wrong source Regressed with ruleset legacy skin implementation. --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs index 3c508f34e0..d1bd0f0a88 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Skinning return !hasFont(font) ? null - : new LegacySpriteText(this, font) + : new LegacySpriteText(source, font) { // Spacing value was reverse-engineered from the ratio of the rendered sprite size in the visual inspector vs the actual texture size Scale = new Vector2(0.96f), @@ -117,6 +117,6 @@ namespace osu.Game.Rulesets.Osu.Skinning public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => configuration.Value is TConfiguration conf ? query.Invoke(conf) : default; - private bool hasFont(string fontName) => GetTexture($"{fontName}-0") != null; + private bool hasFont(string fontName) => source.GetTexture($"{fontName}-0") != null; } } From 12eeec36fca2dccda14043caab9802aa9cdc9754 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Aug 2019 12:33:29 +0900 Subject: [PATCH 2685/5608] Fix ruleset skins incorrectly providing configuration defaults --- osu.Game/Skinning/DefaultSkin.cs | 2 +- osu.Game/Skinning/DefaultSkinConfiguration.cs | 28 +++++++++++++++++++ osu.Game/Skinning/LegacySkin.cs | 2 +- osu.Game/Skinning/SkinConfiguration.cs | 15 ++++------ 4 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 osu.Game/Skinning/DefaultSkinConfiguration.cs diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs index 6072bb64ed..ec957566cb 100644 --- a/osu.Game/Skinning/DefaultSkin.cs +++ b/osu.Game/Skinning/DefaultSkin.cs @@ -13,7 +13,7 @@ namespace osu.Game.Skinning public DefaultSkin() : base(SkinInfo.Default) { - Configuration = new SkinConfiguration(); + Configuration = new DefaultSkinConfiguration(); } public override Drawable GetDrawableComponent(string componentName) => null; diff --git a/osu.Game/Skinning/DefaultSkinConfiguration.cs b/osu.Game/Skinning/DefaultSkinConfiguration.cs new file mode 100644 index 0000000000..722b35f102 --- /dev/null +++ b/osu.Game/Skinning/DefaultSkinConfiguration.cs @@ -0,0 +1,28 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osuTK.Graphics; + +namespace osu.Game.Skinning +{ + /// + /// A skin configuration pre-populated with sane defaults. + /// + public class DefaultSkinConfiguration : SkinConfiguration + { + public DefaultSkinConfiguration() + { + HitCircleFont = "default"; + + ComboColours.AddRange(new[] + { + new Color4(17, 136, 170, 255), + new Color4(102, 136, 0, 255), + new Color4(204, 102, 0, 255), + new Color4(121, 9, 13, 255) + }); + + CursorExpand = true; + } + } +} diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 1572c588e8..56b8aa19c2 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -34,7 +34,7 @@ namespace osu.Game.Skinning using (StreamReader reader = new StreamReader(stream)) Configuration = new LegacySkinDecoder().Decode(reader); else - Configuration = new SkinConfiguration(); + Configuration = new DefaultSkinConfiguration(); Samples = audioManager.GetSampleStore(storage); Textures = new TextureStore(new TextureLoaderStore(storage)); diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index 93b599f9f6..d585c58ef1 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -7,21 +7,18 @@ using osuTK.Graphics; namespace osu.Game.Skinning { + /// + /// An empty skin configuration. + /// public class SkinConfiguration : IHasComboColours, IHasCustomColours { public readonly SkinInfo SkinInfo = new SkinInfo(); - public List ComboColours { get; set; } = new List - { - new Color4(17, 136, 170, 255), - new Color4(102, 136, 0, 255), - new Color4(204, 102, 0, 255), - new Color4(121, 9, 13, 255) - }; + public List ComboColours { get; set; } = new List(); public Dictionary CustomColours { get; set; } = new Dictionary(); - public string HitCircleFont { get; set; } = "default"; + public string HitCircleFont { get; set; } public int HitCircleOverlap { get; set; } @@ -29,6 +26,6 @@ namespace osu.Game.Skinning public float? SliderPathRadius { get; set; } - public bool? CursorExpand { get; set; } = true; + public bool? CursorExpand { get; set; } } } From d2a3e0581b750c030d197573e6923815ca2e60f8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Aug 2019 13:27:03 +0900 Subject: [PATCH 2686/5608] Fix legacy decoder using wrong configuration --- osu.Game/Skinning/LegacySkinDecoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index ecb112955c..0160755eed 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -5,14 +5,14 @@ using osu.Game.Beatmaps.Formats; namespace osu.Game.Skinning { - public class LegacySkinDecoder : LegacyDecoder + public class LegacySkinDecoder : LegacyDecoder { public LegacySkinDecoder() : base(1) { } - protected override void ParseLine(SkinConfiguration skin, Section section, string line) + protected override void ParseLine(DefaultSkinConfiguration skin, Section section, string line) { line = StripComments(line); From 2988624f1fd66896c72cb286984a733ebd4bfb02 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Aug 2019 16:52:41 +0900 Subject: [PATCH 2687/5608] Add fallback for safety --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs index 3c508f34e0..97db2d7c8e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs @@ -115,7 +115,7 @@ namespace osu.Game.Rulesets.Osu.Skinning public SampleChannel GetSample(ISampleInfo sample) => null; public TValue GetValue(Func query) where TConfiguration : SkinConfiguration - => configuration.Value is TConfiguration conf ? query.Invoke(conf) : default; + => configuration.Value is TConfiguration conf ? query.Invoke(conf) : source.GetValue(query); private bool hasFont(string fontName) => GetTexture($"{fontName}-0") != null; } From 3da5eb6c8b3642980a8f2e0197d0a644122bae13 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 31 Aug 2019 16:56:32 +0900 Subject: [PATCH 2688/5608] Add source lookups for safety --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs index d1bd0f0a88..f9fbdcd0e9 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs @@ -110,9 +110,9 @@ namespace osu.Game.Rulesets.Osu.Skinning return null; } - public Texture GetTexture(string componentName) => null; + public Texture GetTexture(string componentName) => source.GetTexture(componentName); - public SampleChannel GetSample(ISampleInfo sample) => null; + public SampleChannel GetSample(ISampleInfo sample) => source.GetSample(sample); public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => configuration.Value is TConfiguration conf ? query.Invoke(conf) : default; From cbbc6aad6eefdf4bcac3b1fba363dce0e66879d5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 31 Aug 2019 21:32:02 +0900 Subject: [PATCH 2689/5608] Make method static --- osu.Game/Screens/Edit/BindableBeatDivisor.cs | 2 +- osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index 055077cc4f..2aeb1ef04b 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -45,7 +45,7 @@ namespace osu.Game.Screens.Edit /// The beat divisor. /// The set of colours. /// The applicable colour from for . - public ColourInfo GetColourFor(int beatDivisor, OsuColour colours) + public static ColourInfo GetColourFor(int beatDivisor, OsuColour colours) { switch (beatDivisor) { diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index ddcdfdaf80..4d89e43ee5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -212,7 +212,7 @@ namespace osu.Game.Screens.Edit.Compose.Components Anchor = Anchor.TopLeft, Origin = Anchor.TopCentre, RelativePositionAxes = Axes.X, - Colour = beatDivisor.GetColourFor(t, colours), + Colour = BindableBeatDivisor.GetColourFor(t, colours), X = getMappedPosition(t) }); } From c10d2302dc6d276a3f50601bd59db44a1b4ec443 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 15:49:57 +0300 Subject: [PATCH 2690/5608] Remove video property from migrations --- osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs | 2 -- .../Migrations/20171025071459_AddMissingIndexRules.Designer.cs | 2 -- ...0171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs | 2 -- .../20171209034410_AddRulesetInfoShortName.Designer.cs | 2 -- osu.Game/Migrations/20180125143340_Settings.Designer.cs | 2 -- osu.Game/Migrations/20180219060912_AddSkins.Designer.cs | 2 -- .../20180529055154_RemoveUniqueHashConstraints.Designer.cs | 2 -- .../20180621044111_UpdateTaikoDefaultBindings.Designer.cs | 2 -- .../Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs | 2 -- osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs | 2 -- osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs | 2 -- osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs | 2 -- .../Migrations/20181130113755_AddScoreInfoTables.Designer.cs | 2 -- osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs | 2 -- osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs | 2 -- .../20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs | 2 -- .../20190708070844_AddBPMAndLengthColumns.Designer.cs | 2 -- osu.Game/Migrations/OsuDbContextModelSnapshot.cs | 2 -- 18 files changed, 36 deletions(-) diff --git a/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs b/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs index 596d80557b..c751530bf4 100644 --- a/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs +++ b/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs @@ -123,8 +123,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs b/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs index ab85aece9f..4cd234f2ef 100644 --- a/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs +++ b/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs @@ -125,8 +125,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs b/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs index d565e1cbf2..006acf12cd 100644 --- a/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs +++ b/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs @@ -128,8 +128,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs b/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs index 3c37c59595..fc2496bc24 100644 --- a/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs +++ b/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs @@ -128,8 +128,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180125143340_Settings.Designer.cs b/osu.Game/Migrations/20180125143340_Settings.Designer.cs index 4c41d223c5..4bb599eec1 100644 --- a/osu.Game/Migrations/20180125143340_Settings.Designer.cs +++ b/osu.Game/Migrations/20180125143340_Settings.Designer.cs @@ -128,8 +128,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs b/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs index 124c61283f..cdc4ef2e66 100644 --- a/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs +++ b/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs @@ -128,8 +128,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs b/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs index 9cbd75ce2c..f28408bfb3 100644 --- a/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs +++ b/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs @@ -126,8 +126,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs b/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs index 150bc2ecbc..aaa11e88b6 100644 --- a/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs +++ b/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs @@ -125,8 +125,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs b/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs index 0a1db37c7f..7eeacd56d7 100644 --- a/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs +++ b/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs @@ -125,8 +125,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs b/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs index b04d36fac1..5ab43da046 100644 --- a/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs +++ b/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs b/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs index aed946e577..b387a45ecf 100644 --- a/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs +++ b/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs b/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs index fe0594e542..120674671a 100644 --- a/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs +++ b/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs b/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs index efa64f014f..eee53182ce 100644 --- a/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs +++ b/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs b/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs index a950a54e39..8e1e3a59f3 100644 --- a/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs +++ b/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs b/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs index df2c434b4e..348c42adb9 100644 --- a/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs +++ b/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs b/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs index ea699edcc9..9477369aa0 100644 --- a/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs +++ b/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs b/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs index fb678178a2..c5fcc16f84 100644 --- a/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs +++ b/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs @@ -131,8 +131,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 1725812d33..761dca2801 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -129,8 +129,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); From d2f7a653a8aecc198fb7cadaddbbe75e2888b855 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 16:10:07 +0300 Subject: [PATCH 2691/5608] Fix nullref --- osu.Game/Screens/Play/DimmableVideo.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index 0452af8419..3e6b95d2cc 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -35,6 +35,9 @@ namespace osu.Game.Screens.Play private void initializeVideo(bool async) { + if (video == null) + return; + if (drawableVideo != null) return; From 94512fea8e82504f920a3e56a0a195029b831cdf Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 16:20:33 +0300 Subject: [PATCH 2692/5608] Apply naming suggestions --- osu.Game/Beatmaps/IWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 1 - osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- osu.Game/Graphics/Containers/UserDimContainer.cs | 2 +- .../Overlays/Settings/Sections/Graphics/DetailSettings.cs | 2 +- osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs | 2 +- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index b932e67bae..a087a52ada 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -27,7 +27,7 @@ namespace osu.Game.Beatmaps Texture Background { get; } /// - /// Retrieves the video file for this . + /// Retrieves the video background file for this . /// VideoSprite Video { get; } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index b489936556..bf3fa90d7b 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -185,7 +185,6 @@ namespace osu.Game.Beatmaps public bool BackgroundLoaded => background.IsResultAvailable; public Texture Background => background.Value; protected virtual bool BackgroundStillValid(Texture b) => b == null || b.Available; - protected abstract Texture GetBackground(); private readonly RecyclableLazy background; diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 357883da45..71a74a5558 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -69,7 +69,7 @@ namespace osu.Game.Configuration Set(OsuSetting.ShowFpsDisplay, false); Set(OsuSetting.ShowStoryboard, true); - Set(OsuSetting.ShowVideo, true); + Set(OsuSetting.ShowVideoBackground, true); Set(OsuSetting.BeatmapSkins, true); Set(OsuSetting.BeatmapHitsounds, true); @@ -137,7 +137,7 @@ namespace osu.Game.Configuration DimLevel, BlurLevel, ShowStoryboard, - ShowVideo, + ShowVideoBackground, KeyOverlay, ScoreMeter, FloatingComments, diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index d0e932fac0..7683bbcd63 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -56,7 +56,7 @@ namespace osu.Game.Graphics.Containers { UserDimLevel = config.GetBindable(OsuSetting.DimLevel); ShowStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); - ShowVideo = config.GetBindable(OsuSetting.ShowVideo); + ShowVideo = config.GetBindable(OsuSetting.ShowVideoBackground); EnableUserDim.ValueChanged += _ => UpdateVisuals(); UserDimLevel.ValueChanged += _ => UpdateVisuals(); diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index 6d9870598f..56e56f6ca8 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics new SettingsCheckbox { LabelText = "Video", - Bindable = config.GetBindable(OsuSetting.ShowVideo) + Bindable = config.GetBindable(OsuSetting.ShowVideoBackground) }, new SettingsCheckbox { diff --git a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs index 5e47b730ad..ff64f35a18 100644 --- a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens.Play.PlayerSettings dimSliderBar.Bindable = config.GetBindable(OsuSetting.DimLevel); blurSliderBar.Bindable = config.GetBindable(OsuSetting.BlurLevel); showStoryboardToggle.Current = config.GetBindable(OsuSetting.ShowStoryboard); - showVideoToggle.Current = config.GetBindable(OsuSetting.ShowVideo); + showVideoToggle.Current = config.GetBindable(OsuSetting.ShowVideoBackground); beatmapSkinsToggle.Current = config.GetBindable(OsuSetting.BeatmapSkins); beatmapHitsoundsToggle.Current = config.GetBindable(OsuSetting.BeatmapHitsounds); } From 1b4ae5a4a495917257be26a88a0b48a57cc231e4 Mon Sep 17 00:00:00 2001 From: pi1024e Date: Thu, 22 Aug 2019 22:37:01 -0400 Subject: [PATCH 2693/5608] Spelling fixes --- osu.Game/Online/API/APIAccess.cs | 2 +- osu.Game/Screens/Menu/IntroCircles.cs | 2 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 4 ++-- osu.Game/Screens/Menu/OsuLogo.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index d722c7a98a..0303293c41 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -165,7 +165,7 @@ namespace osu.Game.Online.API } // The Success callback event is fired on the main thread, so we should wait for that to run before proceeding. - // Without this, we will end up circulating this Connecting loop multiple times and queueing up many web requests + // Without this, we will end up circulating this Connecting loop multiple times and queuing up many web requests // before actually going online. while (State > APIState.Offline && State < APIState.Online) Thread.Sleep(500); diff --git a/osu.Game/Screens/Menu/IntroCircles.cs b/osu.Game/Screens/Menu/IntroCircles.cs index 4fa1a81123..c069f82134 100644 --- a/osu.Game/Screens/Menu/IntroCircles.cs +++ b/osu.Game/Screens/Menu/IntroCircles.cs @@ -77,7 +77,7 @@ namespace osu.Game.Screens.Menu Scheduler.AddDelayed(delegate { - // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu. + // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Menu. if (menuMusic.Value) { track.Restart(); diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 9d0a5cd05b..6984959e9c 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Menu private const float visualiser_rounds = 5; /// - /// How much should each bar go down each milisecond (based on a full bar). + /// How much should each bar go down each millisecond (based on a full bar). /// private const float decay_per_milisecond = 0.0024f; @@ -161,7 +161,7 @@ namespace osu.Game.Screens.Menu private IShader shader; private Texture texture; - //Asuming the logo is a circle, we don't need a second dimension. + //Assuming the logo is a circle, we don't need a second dimension. private float size; private Color4 colour; diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 0c5bf12bdb..d37cfe32db 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -229,7 +229,7 @@ namespace osu.Game.Screens.Menu } /// - /// Schedule a new extenral animation. Handled queueing and finishing previous animations in a sane way. + /// Schedule a new external animation. Handled queuing and finishing previous animations in a sane way. /// /// The animation to be performed /// If true, the new animation is delayed until all previous transforms finish. If false, existing transformed are cleared. From 5695bb670e62db544b536942bfd52db23554b461 Mon Sep 17 00:00:00 2001 From: pi1024e Date: Fri, 30 Aug 2019 13:48:45 -0400 Subject: [PATCH 2694/5608] change back to queuing --- osu.Game/Online/API/APIAccess.cs | 2 +- osu.Game/Screens/Menu/OsuLogo.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 0303293c41..d722c7a98a 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -165,7 +165,7 @@ namespace osu.Game.Online.API } // The Success callback event is fired on the main thread, so we should wait for that to run before proceeding. - // Without this, we will end up circulating this Connecting loop multiple times and queuing up many web requests + // Without this, we will end up circulating this Connecting loop multiple times and queueing up many web requests // before actually going online. while (State > APIState.Offline && State < APIState.Online) Thread.Sleep(500); diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index d37cfe32db..534400e720 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -229,7 +229,7 @@ namespace osu.Game.Screens.Menu } /// - /// Schedule a new external animation. Handled queuing and finishing previous animations in a sane way. + /// Schedule a new external animation. Handled queueing and finishing previous animations in a sane way. /// /// The animation to be performed /// If true, the new animation is delayed until all previous transforms finish. If false, existing transformed are cleared. From a1c72db5f62001aa62f994f5f24c463032a8ddce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 31 Aug 2019 17:01:12 +0200 Subject: [PATCH 2695/5608] Fix inconsistent sound effects on mod buttons Because HoverClickSounds.OnClick() does not fire upon right clicking on mod buttons, the sound effects that play on left and right click were inconsistent. Introduce HoverMouseUpSounds drawable that allows to play the click sound effect upon mouse up events for an arbitrary set of mouse buttons and use it on mod buttons. --- .../UserInterface/HoverMouseUpSounds.cs | 42 +++++++++++++++++++ osu.Game/Overlays/Mods/ModButton.cs | 3 +- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Graphics/UserInterface/HoverMouseUpSounds.cs diff --git a/osu.Game/Graphics/UserInterface/HoverMouseUpSounds.cs b/osu.Game/Graphics/UserInterface/HoverMouseUpSounds.cs new file mode 100644 index 0000000000..dcb443d5aa --- /dev/null +++ b/osu.Game/Graphics/UserInterface/HoverMouseUpSounds.cs @@ -0,0 +1,42 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Extensions; +using osu.Framework.Input.Events; +using osuTK.Input; + +namespace osu.Game.Graphics.UserInterface +{ + /// + /// Adds hover sounds to a drawable, as well as click sounds upon MouseUp events for selected mouse buttons. + /// Intended to be used for controls that can respond to clicks of buttons other than the left mouse button in place of . + /// + public class HoverMouseUpSounds : HoverSounds + { + private SampleChannel sampleClick; + private readonly List buttons; + + public HoverMouseUpSounds(List buttons, HoverSampleSet sampleSet = HoverSampleSet.Normal) + : base(sampleSet) + { + this.buttons = buttons; + } + + protected override bool OnMouseUp(MouseUpEvent e) + { + if (Contains(e.ScreenSpaceMousePosition) && buttons.Contains(e.Button)) + sampleClick?.Play(); + return base.OnMouseUp(e); + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleClick = audio.Samples.Get($@"UI/generic-select{SampleSet.GetDescription()}"); + } + } +} diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index 7b8745cf42..ba39360102 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -11,6 +11,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using System; +using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; @@ -283,7 +284,7 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.TopCentre, Font = OsuFont.GetFont(size: 18) }, - new HoverClickSounds() + new HoverMouseUpSounds(new List { MouseButton.Left, MouseButton.Right }) }; Mod = mod; From 658e0edc3e7df2510953bc9acc11aac35b081590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 31 Aug 2019 20:16:16 +0200 Subject: [PATCH 2696/5608] Handle other button clicks in HoverClickSounds As suggested in review, remove previously introduced HoverMouseUpSounds and instead change effect playing logic in HoverClickSounds by moving it out of OnClick() to OnMouseUp(). Users of the class can either use the existing constructor to play the effect only on left click or use the newly introduced constructor with the MouseButton[] parameter to specify which button clicks should trigger the sound. --- .../UserInterface/HoverClickSounds.cs | 32 ++++++++++++-- .../UserInterface/HoverMouseUpSounds.cs | 42 ------------------- osu.Game/Overlays/Mods/ModButton.cs | 3 +- 3 files changed, 29 insertions(+), 48 deletions(-) delete mode 100644 osu.Game/Graphics/UserInterface/HoverMouseUpSounds.cs diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index 70d988f60e..8fe20e3566 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -1,11 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Extensions; using osu.Framework.Input.Events; +using osuTK.Input; namespace osu.Game.Graphics.UserInterface { @@ -16,16 +18,38 @@ namespace osu.Game.Graphics.UserInterface public class HoverClickSounds : HoverSounds { private SampleChannel sampleClick; + private readonly MouseButton[] buttons; + /// + /// Creates an instance that adds sounds on hover and left click only. + /// + /// Set of click samples to play. public HoverClickSounds(HoverSampleSet sampleSet = HoverSampleSet.Normal) - : base(sampleSet) + : this(new[] { MouseButton.Left }, sampleSet) { } - protected override bool OnClick(ClickEvent e) + /// + /// Creates an instance that adds sounds on hover and on click for any of the buttons specified. + /// + /// Array of button codes which should trigger the click sound. + /// Set of click samples to play. + public HoverClickSounds(MouseButton[] buttons, HoverSampleSet sampleSet = HoverSampleSet.Normal) + : base(sampleSet) { - sampleClick?.Play(); - return base.OnClick(e); + this.buttons = buttons; + } + + protected override bool OnMouseUp(MouseUpEvent e) + { + var index = Array.IndexOf(buttons, e.Button); + bool shouldPlayEffect = index > -1 && index < buttons.Length; + + // examine the button pressed first for short-circuiting + // in most usages it is more likely that another button was pressed than that the cursor left the drawable bounds + if (shouldPlayEffect && Contains(e.ScreenSpaceMousePosition)) + sampleClick?.Play(); + return base.OnMouseUp(e); } [BackgroundDependencyLoader] diff --git a/osu.Game/Graphics/UserInterface/HoverMouseUpSounds.cs b/osu.Game/Graphics/UserInterface/HoverMouseUpSounds.cs deleted file mode 100644 index dcb443d5aa..0000000000 --- a/osu.Game/Graphics/UserInterface/HoverMouseUpSounds.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; -using osu.Framework.Extensions; -using osu.Framework.Input.Events; -using osuTK.Input; - -namespace osu.Game.Graphics.UserInterface -{ - /// - /// Adds hover sounds to a drawable, as well as click sounds upon MouseUp events for selected mouse buttons. - /// Intended to be used for controls that can respond to clicks of buttons other than the left mouse button in place of . - /// - public class HoverMouseUpSounds : HoverSounds - { - private SampleChannel sampleClick; - private readonly List buttons; - - public HoverMouseUpSounds(List buttons, HoverSampleSet sampleSet = HoverSampleSet.Normal) - : base(sampleSet) - { - this.buttons = buttons; - } - - protected override bool OnMouseUp(MouseUpEvent e) - { - if (Contains(e.ScreenSpaceMousePosition) && buttons.Contains(e.Button)) - sampleClick?.Play(); - return base.OnMouseUp(e); - } - - [BackgroundDependencyLoader] - private void load(AudioManager audio) - { - sampleClick = audio.Samples.Get($@"UI/generic-select{SampleSet.GetDescription()}"); - } - } -} diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index ba39360102..f46555dc4b 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -11,7 +11,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using System; -using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; @@ -284,7 +283,7 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.TopCentre, Font = OsuFont.GetFont(size: 18) }, - new HoverMouseUpSounds(new List { MouseButton.Left, MouseButton.Right }) + new HoverClickSounds(new[] { MouseButton.Left, MouseButton.Right }) }; Mod = mod; From aff4dab9aa342955a44e53335c6899fed8fbe3b3 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 1 Sep 2019 03:17:55 +0300 Subject: [PATCH 2697/5608] Ensure playing track of beatmap selected only if a track change occurred --- osu.Game/Screens/Select/SongSelect.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index edb0e6deb8..d0cb5986a8 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -414,7 +414,11 @@ namespace osu.Game.Screens.Select { Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\""); - Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value); + WorkingBeatmap previous = Beatmap.Value; + Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap, previous); + + if (this.IsCurrentScreen() && Beatmap.Value?.Track != previous?.Track) + ensurePlayingSelected(); if (beatmap != null) { @@ -425,8 +429,6 @@ namespace osu.Game.Screens.Select } } - if (this.IsCurrentScreen()) - ensurePlayingSelected(); UpdateBeatmap(Beatmap.Value); } } From 7d955839be8fc02b466ab53000598e98c36afb9c Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 1 Sep 2019 04:22:24 +0300 Subject: [PATCH 2698/5608] Instantly move rank graph tooltip --- .../Overlays/Profile/Header/Components/RankGraph.cs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 24ed0cc022..56405483af 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -283,18 +283,7 @@ namespace osu.Game.Overlays.Profile.Header.Components return true; } - private bool instantMove = true; - - public void Move(Vector2 pos) - { - if (instantMove) - { - Position = pos; - instantMove = false; - } - else - this.MoveTo(pos, 200, Easing.OutQuint); - } + public void Move(Vector2 pos) => Position = pos; protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); From a155814bc48b5547b63f50ea60a4ae67bc377bd8 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 1 Sep 2019 06:07:25 +0300 Subject: [PATCH 2699/5608] Implement instant movement properly --- .../Profile/Header/Components/RankGraph.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 56405483af..c6d96c5917 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -283,9 +283,24 @@ namespace osu.Game.Overlays.Profile.Header.Components return true; } - public void Move(Vector2 pos) => Position = pos; + private bool instantMove = true; - protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); + public void Move(Vector2 pos) + { + if (instantMove) + { + Position = pos; + instantMove = false; + } + else + this.MoveTo(pos, 200, Easing.OutQuint); + } + + protected override void PopIn() + { + instantMove |= !IsPresent; + this.FadeIn(200, Easing.OutQuint); + } protected override void PopOut() => this.FadeOut(200, Easing.OutQuint); } From d1eafafa51b6632c5facea6e9b952e29fdef3441 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 1 Sep 2019 19:57:12 +0900 Subject: [PATCH 2700/5608] Allow searching channels by topics Closes #5939 --- osu.Game/Overlays/Chat/Selection/ChannelListItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs b/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs index 4d77e5f93d..cb0639d85d 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs @@ -36,7 +36,7 @@ namespace osu.Game.Overlays.Chat.Selection private Color4 topicColour; private Color4 hoverColour; - public IEnumerable FilterTerms => new[] { channel.Name }; + public IEnumerable FilterTerms => new[] { channel.Name, channel.Topic }; public bool MatchingFilter { From c4dc34eefde8740e12bd2ed974f81841d862c878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 1 Sep 2019 13:10:11 +0200 Subject: [PATCH 2701/5608] Consolidate HoverClickSounds constructors As suggested in review, merge both HoverClickSounds constructors into one accepting optional arguments. Due to existing usages the parameter is added as second and supplied by name in ModButton. --- .../Graphics/UserInterface/HoverClickSounds.cs | 18 ++++++------------ osu.Game/Overlays/Mods/ModButton.cs | 2 +- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index 8fe20e3566..7e6c0a0974 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -20,24 +20,18 @@ namespace osu.Game.Graphics.UserInterface private SampleChannel sampleClick; private readonly MouseButton[] buttons; - /// - /// Creates an instance that adds sounds on hover and left click only. - /// - /// Set of click samples to play. - public HoverClickSounds(HoverSampleSet sampleSet = HoverSampleSet.Normal) - : this(new[] { MouseButton.Left }, sampleSet) - { - } - /// /// Creates an instance that adds sounds on hover and on click for any of the buttons specified. /// - /// Array of button codes which should trigger the click sound. /// Set of click samples to play. - public HoverClickSounds(MouseButton[] buttons, HoverSampleSet sampleSet = HoverSampleSet.Normal) + /// + /// Array of button codes which should trigger the click sound. + /// If this optional parameter is omitted or set to null, the click sound will also be added on left click. + /// + public HoverClickSounds(HoverSampleSet sampleSet = HoverSampleSet.Normal, MouseButton[] buttons = null) : base(sampleSet) { - this.buttons = buttons; + this.buttons = buttons ?? new[] { MouseButton.Left }; } protected override bool OnMouseUp(MouseUpEvent e) diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index f46555dc4b..58892cd0dd 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -283,7 +283,7 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.TopCentre, Font = OsuFont.GetFont(size: 18) }, - new HoverClickSounds(new[] { MouseButton.Left, MouseButton.Right }) + new HoverClickSounds(buttons: new[] { MouseButton.Left, MouseButton.Right }) }; Mod = mod; From fc48b190fedb15f243e6087315567907cc80c166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 1 Sep 2019 13:32:53 +0200 Subject: [PATCH 2702/5608] Fix inaccurate xmldoc --- osu.Game/Graphics/UserInterface/HoverClickSounds.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index 7e6c0a0974..050e5a2835 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -26,7 +26,7 @@ namespace osu.Game.Graphics.UserInterface /// Set of click samples to play. /// /// Array of button codes which should trigger the click sound. - /// If this optional parameter is omitted or set to null, the click sound will also be added on left click. + /// If this optional parameter is omitted or set to null, the click sound will only be added on left click. /// public HoverClickSounds(HoverSampleSet sampleSet = HoverSampleSet.Normal, MouseButton[] buttons = null) : base(sampleSet) From 7ca51d3866657302a2c30f90b5e7a757bdb3fe93 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 11:20:50 +0900 Subject: [PATCH 2703/5608] Fix resume overlay being drawn below cursor Closes #5905. --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 11 +++++++---- osu.Game/Screens/Play/Player.cs | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 021bd515b5..0ee9196fb8 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -215,10 +215,6 @@ namespace osu.Game.Rulesets.UI continueResume(); } - public ResumeOverlay ResumeOverlay { get; private set; } - - protected virtual ResumeOverlay CreateResumeOverlay() => null; - /// /// Creates and adds the visual representation of a to this . /// @@ -389,6 +385,13 @@ namespace osu.Game.Rulesets.UI /// public abstract GameplayCursorContainer Cursor { get; } + /// + /// An optional overlay used when resuming gameplay from a paused state. + /// + public ResumeOverlay ResumeOverlay { get; protected set; } + + protected virtual ResumeOverlay CreateResumeOverlay() => null; + /// /// Sets a replay to be used, overriding local input. /// diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index b487f3e61b..3f1603eabe 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -178,6 +178,7 @@ namespace osu.Game.Screens.Play }, // display the cursor above some HUD elements. DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), + DrawableRuleset.ResumeOverlay?.CreateProxy() ?? new Container(), HUDOverlay = new HUDOverlay(ScoreProcessor, DrawableRuleset, Mods.Value) { HoldToQuit = From 2bd074883a834305efbf5a89610e2c442a08dc64 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 12:36:08 +0900 Subject: [PATCH 2704/5608] Fix OsuLegacySkin fallback logic being incorrect Fixes skin fonts not being applied. This is a temporary fix as configuration retrieval from skins will see a complete rewrite over the coming days. --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs index 904064e2f0..ea7257d258 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkin.cs @@ -115,7 +115,13 @@ namespace osu.Game.Rulesets.Osu.Skinning public SampleChannel GetSample(ISampleInfo sample) => source.GetSample(sample); public TValue GetValue(Func query) where TConfiguration : SkinConfiguration - => configuration.Value is TConfiguration conf ? query.Invoke(conf) : source.GetValue(query); + { + TValue val; + if (configuration.Value is TConfiguration conf && (val = query.Invoke(conf)) != null) + return val; + + return source.GetValue(query); + } private bool hasFont(string fontName) => source.GetTexture($"{fontName}-0") != null; } From cad68bb82fce1bfdaed3ca85b092b39f484cb222 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 12:54:59 +0900 Subject: [PATCH 2705/5608] Add autoplay helper property --- osu.Game/Tests/Visual/PlayerTestScene.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/PlayerTestScene.cs b/osu.Game/Tests/Visual/PlayerTestScene.cs index 1ab20ecd48..599cb060b1 100644 --- a/osu.Game/Tests/Visual/PlayerTestScene.cs +++ b/osu.Game/Tests/Visual/PlayerTestScene.cs @@ -3,6 +3,7 @@ using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Testing; using osu.Game.Configuration; using osu.Game.Rulesets; @@ -40,6 +41,8 @@ namespace osu.Game.Tests.Visual protected virtual bool AllowFail => false; + protected virtual bool Autoplay => false; + private void loadPlayer() { var beatmap = CreateBeatmap(ruleset.RulesetInfo); @@ -53,6 +56,16 @@ namespace osu.Game.Tests.Visual LoadScreen(Player); } - protected virtual Player CreatePlayer(Ruleset ruleset) => new TestPlayer(false, false); + protected virtual Player CreatePlayer(Ruleset ruleset) + { + if (Autoplay) + { + var mod = ruleset.GetAutoplayMod(); + if (mod != null) + Mods.Value = Mods.Value.Concat(mod.Yield()).ToArray(); + } + + return new TestPlayer(false, false); + } } } From 2945fef62d5afbd53ad3022bd9304d34d108fe0d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 13:04:30 +0900 Subject: [PATCH 2706/5608] Expose HasCompleted from ScoreProcessor --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index e47df6b473..3b7e457990 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Scoring /// /// Whether all s have been processed. /// - protected virtual bool HasCompleted => false; + public virtual bool HasCompleted => false; /// /// Whether this ScoreProcessor has already triggered the failed state. @@ -205,7 +205,7 @@ namespace osu.Game.Rulesets.Scoring private const double combo_portion = 0.7; private const double max_score = 1000000; - protected sealed override bool HasCompleted => JudgedHits == MaxHits; + public sealed override bool HasCompleted => JudgedHits == MaxHits; protected int MaxHits { get; private set; } protected int JudgedHits { get; private set; } From fc668d8a74898586c8a774fd1bd50f36032c7746 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 13:24:39 +0900 Subject: [PATCH 2707/5608] Move autoplay mod to a less overridable location --- osu.Game/Tests/Visual/PlayerTestScene.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game/Tests/Visual/PlayerTestScene.cs b/osu.Game/Tests/Visual/PlayerTestScene.cs index 599cb060b1..ccd996098c 100644 --- a/osu.Game/Tests/Visual/PlayerTestScene.cs +++ b/osu.Game/Tests/Visual/PlayerTestScene.cs @@ -52,12 +52,6 @@ namespace osu.Game.Tests.Visual if (!AllowFail) Mods.Value = new[] { ruleset.GetAllMods().First(m => m is ModNoFail) }; - Player = CreatePlayer(ruleset); - LoadScreen(Player); - } - - protected virtual Player CreatePlayer(Ruleset ruleset) - { if (Autoplay) { var mod = ruleset.GetAutoplayMod(); @@ -65,7 +59,10 @@ namespace osu.Game.Tests.Visual Mods.Value = Mods.Value.Concat(mod.Yield()).ToArray(); } - return new TestPlayer(false, false); + Player = CreatePlayer(ruleset); + LoadScreen(Player); } + + protected virtual Player CreatePlayer(Ruleset ruleset) => new TestPlayer(false, false); } } From 5b685c4cd2929f759be82a973f3f187f1642d50f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 13:25:39 +0900 Subject: [PATCH 2708/5608] Fix swell ticks having non-zero time offsets --- .../TestSceneSwellJudgements.cs | 74 +++++++++++++++++++ .../Objects/Drawables/DrawableSwellTick.cs | 6 +- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs new file mode 100644 index 0000000000..f27e329e8e --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs @@ -0,0 +1,74 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Judgements; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Screens.Play; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + public class TestSceneSwellJudgements : PlayerTestScene + { + protected new TestPlayer Player => (TestPlayer)base.Player; + + public TestSceneSwellJudgements() + : base(new TaikoRuleset()) + { + } + + [Test] + public void TestZeroTickTimeOffsets() + { + AddUntilStep("gameplay finished", () => Player.ScoreProcessor.HasCompleted); + AddAssert("all tick offsets are 0", () => Player.Results.Where(r => r.Judgement is TaikoSwellTickJudgement).All(r => r.TimeOffset == 0)); + } + + protected override bool Autoplay => true; + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) + { + var beatmap = new Beatmap + { + BeatmapInfo = { Ruleset = new TaikoRuleset().RulesetInfo }, + HitObjects = + { + new Swell + { + StartTime = 1000, + Duration = 1000, + } + } + }; + + return beatmap; + } + + protected override Player CreatePlayer(Ruleset ruleset) => new TestPlayer(); + + protected class TestPlayer : Player + { + public readonly List Results = new List(); + + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + + public TestPlayer() + : base(false, false) + { + } + + [BackgroundDependencyLoader] + private void load() + { + ScoreProcessor.NewJudgement += r => Results.Add(r); + } + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index 8b27d78101..4833d420f7 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -14,7 +14,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { } - public void TriggerResult(HitResult type) => ApplyResult(r => r.Type = type); + public void TriggerResult(HitResult type) + { + HitObject.StartTime = Time.Current; + ApplyResult(r => r.Type = type); + } protected override void CheckForResult(bool userTriggered, double timeOffset) { From 1df422e59135964b243ac168ba15bf8fd843a722 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 13:30:08 +0900 Subject: [PATCH 2709/5608] Hide taiko swell ticks --- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index 8b27d78101..c2e8c08e7e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -14,6 +15,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { } + protected override void UpdateInitialTransforms() => this.FadeOut(); + public void TriggerResult(HitResult type) => ApplyResult(r => r.Type = type); protected override void CheckForResult(bool userTriggered, double timeOffset) From 6603cbd74d2a5d4d0450af0953ea39452844ec89 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 13:41:14 +0900 Subject: [PATCH 2710/5608] No language doesn't mean "Other" --- osu.Game/Overlays/BeatmapSet/Info.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 72db03a5a6..df077a65a9 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -133,7 +133,7 @@ namespace osu.Game.Overlays.BeatmapSet source.Text = b.NewValue?.Metadata.Source ?? string.Empty; tags.Text = b.NewValue?.Metadata.Tags ?? string.Empty; genre.Text = b.NewValue?.OnlineInfo?.Genre?.Name ?? "Unspecified"; - language.Text = b.NewValue?.OnlineInfo?.Language?.Name ?? "Other"; + language.Text = b.NewValue?.OnlineInfo?.Language?.Name ?? "Unspecified"; }; } From d4c12881f5fd4417d6d108da0719001619fd0893 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 13:45:13 +0900 Subject: [PATCH 2711/5608] Remove unnecessary over-complication and fix transitions --- osu.Game/Overlays/BeatmapSet/Info.cs | 30 ++++++---------------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index df077a65a9..16d6236051 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -83,24 +83,12 @@ namespace osu.Game.Overlays.BeatmapSet { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - LayoutDuration = transition_duration, + Direction = FillDirection.Full, Children = new[] { source = new MetadataSection("Source"), - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Width = 0.5f, - FillMode = FillMode.Fit, - Children = new Drawable[] - { - genre = new MetadataSection("Genre"), - language = new MetadataSection("Language"), - } - }, + genre = new MetadataSection("Genre") { Width = 0.5f }, + language = new MetadataSection("Language") { Width = 0.5f }, tags = new MetadataSection("Tags"), }, }, @@ -132,8 +120,8 @@ namespace osu.Game.Overlays.BeatmapSet { source.Text = b.NewValue?.Metadata.Source ?? string.Empty; tags.Text = b.NewValue?.Metadata.Tags ?? string.Empty; - genre.Text = b.NewValue?.OnlineInfo?.Genre?.Name ?? "Unspecified"; - language.Text = b.NewValue?.OnlineInfo?.Language?.Name ?? "Unspecified"; + genre.Text = b.NewValue?.OnlineInfo?.Genre?.Name ?? string.Empty; + language.Text = b.NewValue?.OnlineInfo?.Language?.Name ?? string.Empty; }; } @@ -154,7 +142,7 @@ namespace osu.Game.Overlays.BeatmapSet { if (string.IsNullOrEmpty(value)) { - this.FadeOut(transition_duration); + Hide(); return; } @@ -164,12 +152,6 @@ namespace osu.Game.Overlays.BeatmapSet } } - public Color4 TextColour - { - get => textFlow.Colour; - set => textFlow.Colour = value; - } - public MetadataSection(string title) { RelativeSizeAxes = Axes.X; From 0f04357f1f0759c0560ed555f6e1071c1d4caef0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 14:41:14 +0900 Subject: [PATCH 2712/5608] Revert short name change for now --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index cd2f8d56af..5428b4eeb8 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Catch public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); - public const string SHORT_NAME = "catch"; + public const string SHORT_NAME = "fruits"; public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] { From 8f8d35bd15f27f5613bfb9506c96266288081dee Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 15:02:16 +0900 Subject: [PATCH 2713/5608] Delay initial hitobject state computation --- .../Objects/Drawables/DrawableHitObject.cs | 9 ++++++ .../Scrolling/ScrollingHitObjectContainer.cs | 29 +++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 4a6f261905..a24476418c 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -9,6 +9,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; +using osu.Framework.Threading; using osu.Game.Audio; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; @@ -278,6 +279,14 @@ namespace osu.Game.Rulesets.Objects.Drawables UpdateResult(false); } + /// + /// Schedules an to this . + /// + /// + /// Only provided temporarily until hitobject pooling is implemented. + /// + protected internal new ScheduledDelegate Schedule(Action action) => base.Schedule(action); + private double? lifetimeStart; public override double LifetimeStart diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 1df8c8218f..107d55ff0d 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.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.Allocation; using osu.Framework.Bindables; using osu.Framework.Caching; @@ -86,13 +87,34 @@ namespace osu.Game.Rulesets.UI.Scrolling scrollingInfo.Algorithm.Reset(); foreach (var obj in Objects) + { + computeLifetimeStartRecursive(obj); computeInitialStateRecursive(obj); + } + initialStateCache.Validate(); } } - private void computeInitialStateRecursive(DrawableHitObject hitObject) + private void computeLifetimeStartRecursive(DrawableHitObject hitObject) { + hitObject.LifetimeStart = scrollingInfo.Algorithm.GetDisplayStartTime(hitObject.HitObject.StartTime, timeRange.Value); + + foreach (var obj in hitObject.NestedHitObjects) + computeLifetimeStartRecursive(obj); + } + + private readonly Dictionary hitObjectInitialStateCache = new Dictionary(); + + // Cant use AddOnce() since the delegate is re-constructed every invocation + private void computeInitialStateRecursive(DrawableHitObject hitObject) => hitObject.Schedule(() => + { + if (!hitObjectInitialStateCache.TryGetValue(hitObject, out var cached)) + cached = hitObjectInitialStateCache[hitObject] = new Cached(); + + if (cached.IsValid) + return; + double endTime = hitObject.HitObject.StartTime; if (hitObject.HitObject is IHasEndTime e) @@ -113,7 +135,6 @@ namespace osu.Game.Rulesets.UI.Scrolling } } - hitObject.LifetimeStart = scrollingInfo.Algorithm.GetDisplayStartTime(hitObject.HitObject.StartTime, timeRange.Value); hitObject.LifetimeEnd = scrollingInfo.Algorithm.TimeAt(scrollLength * safe_lifetime_end_multiplier, endTime, timeRange.Value, scrollLength); foreach (var obj in hitObject.NestedHitObjects) @@ -123,7 +144,9 @@ namespace osu.Game.Rulesets.UI.Scrolling // Nested hitobjects don't need to scroll, but they do need accurate positions updatePosition(obj, hitObject.HitObject.StartTime); } - } + + cached.Validate(); + }); protected override void UpdateAfterChildrenLife() { From d74e1b9b6473613784be40adcf3202ae3f3908f1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 15:06:43 +0900 Subject: [PATCH 2714/5608] Remove from dictionary on Remove() --- .../Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 107d55ff0d..bd1f496dfa 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -51,8 +51,13 @@ namespace osu.Game.Rulesets.UI.Scrolling public override bool Remove(DrawableHitObject hitObject) { var result = base.Remove(hitObject); + if (result) + { initialStateCache.Invalidate(); + hitObjectInitialStateCache.Remove(hitObject); + } + return result; } From c06908adf7c653f98fddda7d08f55e50a290b642 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 15:37:38 +0900 Subject: [PATCH 2715/5608] Fix spacing specifications --- .../Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index 408468fa73..9b81e8c573 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, - Spacing = new Vector2(3), + Spacing = new Vector2(0, 3), }, date = new DrawableDate(historyItem.CreatedAt) { @@ -59,14 +59,15 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu if (!string.IsNullOrEmpty(prefix)) { linkFlowContainer.AddText(prefix); - linkFlowContainer.AddText($@"{Math.Abs(historyItem.Amount)} kudosu", t => + linkFlowContainer.AddText($@" {Math.Abs(historyItem.Amount)} kudosu ", t => { t.Font = t.Font.With(italics: true); t.Colour = colours.Blue; }); } - linkFlowContainer.AddLinks(formattedSource.Text + " ", formattedSource.Links); + linkFlowContainer.AddLinks(formattedSource.Text, formattedSource.Links); + linkFlowContainer.AddText(" "); linkFlowContainer.AddLink(historyItem.Post.Title, historyItem.Post.Url); } From da4507037333adcda31a9512f101b667cddb77ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 15:44:21 +0900 Subject: [PATCH 2716/5608] Group common prefixes together --- .../Kudosu/DrawableKudosuHistoryItem.cs | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index 9b81e8c573..ff64ea5648 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -120,29 +120,17 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu switch (historyItem.Action) { case KudosuAction.VoteGive: - return @"Received"; - case KudosuAction.Give: + case KudosuAction.AllowKudosuGive: + case KudosuAction.RestoreGive: + case KudosuAction.RecalculateGive: return @"Received"; - case KudosuAction.VoteReset: - return @"Lost"; - case KudosuAction.DenyKudosuReset: return @"Denied"; - case KudosuAction.AllowKudosuGive: - return @"Received"; - case KudosuAction.DeleteReset: - return @"Lost"; - - case KudosuAction.RestoreGive: - return @"Received"; - - case KudosuAction.RecalculateGive: - return @"Received"; - + case KudosuAction.VoteReset: case KudosuAction.RecalculateReset: return @"Lost"; From 3d551b08a96a1d9be3130a9b5bf27613fced44bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 15:57:23 +0900 Subject: [PATCH 2717/5608] Rename legacy actions --- .../Visual/Online/TestSceneKudosuHistory.cs | 6 +++--- .../API/Requests/GetUserKudosuHistoryRequest.cs | 16 ++++++++-------- .../Sections/Kudosu/DrawableKudosuHistoryItem.cs | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs index 8badfeaa23..a4f3bf65e6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs @@ -75,7 +75,7 @@ namespace osu.Game.Tests.Visual.Online { Amount = 5, CreatedAt = new DateTimeOffset(new DateTime(2012, 10, 11)), - Action = KudosuAction.Give, + Action = KudosuAction.ForumGive, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 2", @@ -91,7 +91,7 @@ namespace osu.Game.Tests.Visual.Online { Amount = 8, CreatedAt = new DateTimeOffset(new DateTime(2013, 9, 11)), - Action = KudosuAction.Reset, + Action = KudosuAction.ForumReset, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 3", @@ -107,7 +107,7 @@ namespace osu.Game.Tests.Visual.Online { Amount = 7, CreatedAt = new DateTimeOffset(new DateTime(2014, 8, 11)), - Action = KudosuAction.Revoke, + Action = KudosuAction.ForumRevoke, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 4", diff --git a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs index dd6f2ccf22..32aa0c15fa 100644 --- a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs @@ -21,16 +21,16 @@ namespace osu.Game.Online.API.Requests public enum KudosuAction { - Give, - VoteGive, - Reset, - VoteReset, - DenyKudosuReset, - Revoke, AllowKudosuGive, DeleteReset, - RestoreGive, + DenyKudosuReset, + ForumGive, + ForumReset, + ForumRevoke, RecalculateGive, - RecalculateReset + RecalculateReset, + RestoreGive, + VoteGive, + VoteReset, } } diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index ff64ea5648..5229269def 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -80,10 +80,10 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu case KudosuAction.VoteGive: return @"from obtaining votes in modding post of"; - case KudosuAction.Give: + case KudosuAction.ForumGive: return $@"from {userLink()} for a post at"; - case KudosuAction.Reset: + case KudosuAction.ForumReset: return $@"Kudosu reset by {userLink()} for the post"; case KudosuAction.VoteReset: @@ -92,7 +92,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu case KudosuAction.DenyKudosuReset: return @"from modding post"; - case KudosuAction.Revoke: + case KudosuAction.ForumRevoke: return $@"Denied kudosu by {userLink()} for the post"; case KudosuAction.AllowKudosuGive: @@ -120,7 +120,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu switch (historyItem.Action) { case KudosuAction.VoteGive: - case KudosuAction.Give: + case KudosuAction.ForumGive: case KudosuAction.AllowKudosuGive: case KudosuAction.RestoreGive: case KudosuAction.RecalculateGive: From 0985b1679f86de6a4a96d34edb0e84cb30a55dac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 15:57:55 +0900 Subject: [PATCH 2718/5608] Move enum to response class --- .../Visual/Online/TestSceneKudosuHistory.cs | 1 - .../API/Requests/GetUserKudosuHistoryRequest.cs | 15 --------------- .../API/Requests/Responses/APIKudosuHistory.cs | 15 +++++++++++++++ .../Sections/Kudosu/DrawableKudosuHistoryItem.cs | 1 - 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs index a4f3bf65e6..84152e40fa 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs @@ -10,7 +10,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Online.API.Requests; using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Tests.Visual.Online diff --git a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs index 32aa0c15fa..e90e297672 100644 --- a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs @@ -18,19 +18,4 @@ namespace osu.Game.Online.API.Requests protected override string Target => $"users/{userId}/kudosu"; } - - public enum KudosuAction - { - AllowKudosuGive, - DeleteReset, - DenyKudosuReset, - ForumGive, - ForumReset, - ForumRevoke, - RecalculateGive, - RecalculateReset, - RestoreGive, - VoteGive, - VoteReset, - } } diff --git a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs index f2297f7a10..25b11a6cf9 100644 --- a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs +++ b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs @@ -53,4 +53,19 @@ namespace osu.Game.Online.API.Requests.Responses public KudosuAction Action; } + + public enum KudosuAction + { + AllowKudosuGive, + DeleteReset, + DenyKudosuReset, + ForumGive, + ForumReset, + ForumRevoke, + RecalculateGive, + RecalculateReset, + RestoreGive, + VoteGive, + VoteReset, + } } diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index 5229269def..6efe9825ec 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Online.API.Requests; using osu.Game.Online.Chat; using System; using osuTK; From 0a89603e79871ffa10c7858759ce231a6113f2b5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 16:07:16 +0900 Subject: [PATCH 2719/5608] Fix hit error potentially not displaying with null hitwindows --- osu.Game/Screens/Play/HUDOverlay.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 8e642ea552..eac45f9214 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -259,7 +259,9 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20, Right = 10 }, }; - protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset.Objects.FirstOrDefault()?.HitWindows); + protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay( + scoreProcessor, + drawableRuleset.Objects.Concat(drawableRuleset.Objects.SelectMany(h => h.NestedHitObjects)).FirstOrDefault(h => h.HitWindows != null)?.HitWindows); protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); From f3656475de102de8379409868d63aecc321ebe9f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 16:10:30 +0900 Subject: [PATCH 2720/5608] Return null hitwindows for non-time-based objects --- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 3 +++ osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs | 3 +++ osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 ++ osu.Game.Rulesets.Osu/Objects/SliderTick.cs | 3 +++ osu.Game.Rulesets.Osu/Objects/Spinner.cs | 3 +++ osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 3 +++ osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs | 3 +++ osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs | 3 +++ osu.Game.Rulesets.Taiko/Objects/Swell.cs | 3 +++ osu.Game.Rulesets.Taiko/Objects/SwellTick.cs | 3 +++ 10 files changed, 29 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 5e9f46d9c7..d28d04b3c1 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -5,6 +5,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Mania.Objects @@ -99,5 +100,7 @@ namespace osu.Game.Rulesets.Mania.Objects } public override Judgement CreateJudgement() => new HoldNoteJudgement(); + + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs index c133ee73b1..6bb21633b6 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs @@ -3,6 +3,7 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mania.Objects { @@ -12,5 +13,7 @@ namespace osu.Game.Rulesets.Mania.Objects public class HoldNoteTick : ManiaHitObject { public override Judgement CreateJudgement() => new HoldNoteTickJudgement(); + + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index d3279652c7..93231844bb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -229,5 +229,7 @@ namespace osu.Game.Rulesets.Osu.Objects nodeIndex < NodeSamples.Count ? NodeSamples[nodeIndex] : Samples; public override Judgement CreateJudgement() => new OsuJudgement(); + + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs index 85439699dd..60e9084ed3 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs @@ -4,6 +4,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; namespace osu.Game.Rulesets.Osu.Objects @@ -30,5 +31,7 @@ namespace osu.Game.Rulesets.Osu.Objects } public override Judgement CreateJudgement() => new OsuJudgement(); + + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index 8a2fd3b7aa..69c779a182 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -6,6 +6,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; namespace osu.Game.Rulesets.Osu.Objects @@ -31,5 +32,7 @@ namespace osu.Game.Rulesets.Osu.Objects } public override Judgement CreateJudgement() => new OsuJudgement(); + + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 1d25735fe3..3ed52f21f0 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -6,6 +6,7 @@ using System; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects @@ -86,5 +87,7 @@ namespace osu.Game.Rulesets.Taiko.Objects } public override Judgement CreateJudgement() => new TaikoDrumRollJudgement(); + + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index 8448036f76..39e2b45e24 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects @@ -25,5 +26,7 @@ namespace osu.Game.Rulesets.Taiko.Objects public double HitWindow => TickSpacing / 2; public override Judgement CreateJudgement() => new TaikoDrumRollTickJudgement(); + + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs index 2a03c23934..830e640242 100644 --- a/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects @@ -9,5 +10,7 @@ namespace osu.Game.Rulesets.Taiko.Objects public class StrongHitObject : TaikoHitObject { public override Judgement CreateJudgement() => new TaikoStrongJudgement(); + + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index befa728570..e7812841bf 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -4,6 +4,7 @@ using System; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects @@ -33,5 +34,7 @@ namespace osu.Game.Rulesets.Taiko.Objects } public override Judgement CreateJudgement() => new TaikoSwellJudgement(); + + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs index c2ae784b2a..049fa7de5f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects @@ -9,5 +10,7 @@ namespace osu.Game.Rulesets.Taiko.Objects public class SwellTick : TaikoHitObject { public override Judgement CreateJudgement() => new TaikoSwellTickJudgement(); + + protected override HitWindows CreateHitWindows() => null; } } From f2bdf94a1dda65e33a45ce3007b03c4d95f649ed Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 16:28:14 +0900 Subject: [PATCH 2721/5608] Add HitWindows to JudgementResult to indicate timing errors --- .../TestSceneDrawableJudgement.cs | 3 ++- .../Judgements/OsuJudgementResult.cs | 5 +++-- .../Objects/Drawables/DrawableOsuHitObject.cs | 3 ++- osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs | 2 +- .../TestSceneTaikoPlayfield.cs | 8 ++++---- .../Visual/Gameplay/TestSceneBarHitErrorMeter.cs | 2 +- osu.Game/Rulesets/Judgements/JudgementResult.cs | 14 +++++++++++++- .../Objects/Drawables/DrawableHitObject.cs | 6 ++++-- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 +- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 3 +++ 10 files changed, 34 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index 82a8d0e5e6..6d240ee009 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Scoring; @@ -24,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Tests { foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType().Skip(1)) AddStep("Show " + result.GetDescription(), () => SetContents(() => - new DrawableOsuJudgement(new JudgementResult(null) { Type = result }, null) + new DrawableOsuJudgement(new JudgementResult(null, new HitWindows()) { Type = result }, null) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs index c7661bddb1..367c2c8f14 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Osu.Judgements { @@ -9,8 +10,8 @@ namespace osu.Game.Rulesets.Osu.Judgements { public ComboResult ComboType; - public OsuJudgementResult(Judgement judgement) - : base(judgement) + public OsuJudgementResult(Judgement judgement, HitWindows hitWindows) + : base(judgement, hitWindows) { } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index b4f5642f45..02b6a932d3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Graphics.Containers; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -41,6 +42,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength); - protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(judgement); + protected override JudgementResult CreateResult(Judgement judgement, HitWindows hitWindows) => new OsuJudgementResult(judgement, hitWindows); } } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index cf0565c6da..08dc355bcf 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Osu.Scoring } } - protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(judgement); + protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(judgement, null); public override HitWindows CreateHitWindows() => new OsuHitWindows(); } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index 3c84d900a6..2db1e3e70a 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -144,7 +144,7 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement(), new TaikoHitWindows()) { Type = hitResult }); } private void addStrongHitJudgement(bool kiai) @@ -159,13 +159,13 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new TestStrongNestedHit(h), new JudgementResult(new TaikoStrongJudgement()) { Type = HitResult.Great }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement(), new TaikoHitWindows()) { Type = hitResult }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new TestStrongNestedHit(h), new JudgementResult(new TaikoStrongJudgement(), new TaikoHitWindows()) { Type = HitResult.Great }); } private void addMissJudgement() { - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new DrawableTestHit(new Hit()), new JudgementResult(new TaikoJudgement()) { Type = HitResult.Miss }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new DrawableTestHit(new Hit()), new JudgementResult(new TaikoJudgement(), new TaikoHitWindows()) { Type = HitResult.Miss }); } private void addBarLine(bool major, double delay = scroll_time) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs index f20440249b..0376e775bc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs @@ -106,7 +106,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void newJudgement(double offset = 0) { - var judgement = new JudgementResult(new Judgement()) + var judgement = new JudgementResult(new Judgement(), hitWindows) { TimeOffset = offset == 0 ? RNG.Next(-150, 150) : offset, Type = HitResult.Perfect, diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs index 195fe316ac..aea3c9085b 100644 --- a/osu.Game/Rulesets/Judgements/JudgementResult.cs +++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using JetBrains.Annotations; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; @@ -21,6 +23,13 @@ namespace osu.Game.Rulesets.Judgements /// public readonly Judgement Judgement; + /// + /// The which the was judged against. + /// May be null to indicate that the timing error should not be displayed to the user. + /// + [CanBeNull] + public readonly HitWindows HitWindows; + /// /// The offset from a perfect hit at which this occurred. /// Populated when this is applied via . @@ -56,9 +65,12 @@ namespace osu.Game.Rulesets.Judgements /// Creates a new . /// /// The to refer to for scoring information. - public JudgementResult(Judgement judgement) + /// The which the was judged against. + /// May be null to indicate that the timing error should not be displayed to the user. + public JudgementResult([NotNull] Judgement judgement, [CanBeNull] HitWindows hitWindows) { Judgement = judgement; + HitWindows = hitWindows; } public override string ToString() => $"{Type} (Score:{Judgement.NumericResultFor(this)} HP:{Judgement.HealthIncreaseFor(this)} {Judgement})"; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 4a6f261905..4106f8320f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Objects.Drawables if (judgement != null) { - Result = CreateResult(judgement); + Result = CreateResult(judgement, HitObject.HitWindows); if (Result == null) throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); } @@ -401,7 +401,9 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Creates the that represents the scoring result for this . /// /// The that provides the scoring information. - protected virtual JudgementResult CreateResult(Judgement judgement) => new JudgementResult(judgement); + /// The which the was judged against. + /// May be null to indicate that the timing error should not be displayed to the user. + protected virtual JudgementResult CreateResult(Judgement judgement, HitWindows hitWindows) => new JudgementResult(judgement, hitWindows); } public abstract class DrawableHitObject : DrawableHitObject diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 3b7e457990..3230551386 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -442,7 +442,7 @@ namespace osu.Game.Rulesets.Scoring /// Creates the that represents the scoring result for a . /// /// The that provides the scoring information. - protected virtual JudgementResult CreateResult(Judgement judgement) => new JudgementResult(judgement); + protected virtual JudgementResult CreateResult(Judgement judgement) => new JudgementResult(judgement, null); } public enum ScoringMode diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index cdfa0e993b..3e925a5a50 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -49,6 +49,9 @@ namespace osu.Game.Screens.Play.HUD private void onNewJudgement(JudgementResult result) { + if (result.HitWindows == null) + return; + foreach (var c in Children) c.OnNewJudgement(result); } From d21d68b36c4271d611db888c1917e09ee93b95ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 16:34:11 +0900 Subject: [PATCH 2722/5608] Refactor to match web implementation 1:1 --- .../Visual/Online/TestSceneKudosuHistory.cs | 33 +++-- .../Requests/Responses/APIKudosuHistory.cs | 44 ++++-- .../Kudosu/DrawableKudosuHistoryItem.cs | 138 +++++++++--------- 3 files changed, 122 insertions(+), 93 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs index 84152e40fa..325d657f0e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs @@ -58,7 +58,8 @@ namespace osu.Game.Tests.Visual.Online { Amount = 10, CreatedAt = new DateTimeOffset(new DateTime(2011, 11, 11)), - Action = KudosuAction.DenyKudosuReset, + Source = KudosuSource.DenyKudosu, + Action = KudosuAction.Reset, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 1", @@ -74,7 +75,8 @@ namespace osu.Game.Tests.Visual.Online { Amount = 5, CreatedAt = new DateTimeOffset(new DateTime(2012, 10, 11)), - Action = KudosuAction.ForumGive, + Source = KudosuSource.Forum, + Action = KudosuAction.Give, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 2", @@ -90,7 +92,8 @@ namespace osu.Game.Tests.Visual.Online { Amount = 8, CreatedAt = new DateTimeOffset(new DateTime(2013, 9, 11)), - Action = KudosuAction.ForumReset, + Source = KudosuSource.Forum, + Action = KudosuAction.Reset, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 3", @@ -106,7 +109,8 @@ namespace osu.Game.Tests.Visual.Online { Amount = 7, CreatedAt = new DateTimeOffset(new DateTime(2014, 8, 11)), - Action = KudosuAction.ForumRevoke, + Source = KudosuSource.Forum, + Action = KudosuAction.Revoke, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 4", @@ -122,7 +126,8 @@ namespace osu.Game.Tests.Visual.Online { Amount = 100, CreatedAt = new DateTimeOffset(new DateTime(2015, 7, 11)), - Action = KudosuAction.VoteGive, + Source = KudosuSource.Vote, + Action = KudosuAction.Give, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 5", @@ -138,7 +143,8 @@ namespace osu.Game.Tests.Visual.Online { Amount = 20, CreatedAt = new DateTimeOffset(new DateTime(2016, 6, 11)), - Action = KudosuAction.VoteReset, + Source = KudosuSource.Vote, + Action = KudosuAction.Reset, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 6", @@ -154,7 +160,8 @@ namespace osu.Game.Tests.Visual.Online { Amount = 11, CreatedAt = new DateTimeOffset(new DateTime(2016, 6, 11)), - Action = KudosuAction.AllowKudosuGive, + Source = KudosuSource.AllowKudosu, + Action = KudosuAction.Give, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 7", @@ -170,7 +177,8 @@ namespace osu.Game.Tests.Visual.Online { Amount = 24, CreatedAt = new DateTimeOffset(new DateTime(2014, 6, 11)), - Action = KudosuAction.DeleteReset, + Source = KudosuSource.Delete, + Action = KudosuAction.Reset, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 8", @@ -186,7 +194,8 @@ namespace osu.Game.Tests.Visual.Online { Amount = 12, CreatedAt = new DateTimeOffset(new DateTime(2016, 6, 11)), - Action = KudosuAction.RestoreGive, + Source = KudosuSource.Restore, + Action = KudosuAction.Give, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 9", @@ -202,7 +211,8 @@ namespace osu.Game.Tests.Visual.Online { Amount = 2, CreatedAt = new DateTimeOffset(new DateTime(2012, 6, 11)), - Action = KudosuAction.RecalculateGive, + Source = KudosuSource.Recalculate, + Action = KudosuAction.Give, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 10", @@ -218,7 +228,8 @@ namespace osu.Game.Tests.Visual.Online { Amount = 32, CreatedAt = new DateTimeOffset(new DateTime(2019, 8, 11)), - Action = KudosuAction.RecalculateReset, + Source = KudosuSource.Recalculate, + Action = KudosuAction.Reset, Post = new APIKudosuHistory.ModdingPost { Title = @"Random post 11", diff --git a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs index 25b11a6cf9..d596ddc560 100644 --- a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs +++ b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; -using Humanizer; +using System.Linq; using Newtonsoft.Json; namespace osu.Game.Online.API.Requests.Responses @@ -39,33 +39,45 @@ namespace osu.Game.Online.API.Requests.Responses public string Username; } + public KudosuSource Source; + + public KudosuAction Action; + [JsonProperty("action")] private string action { set { - //We will receive something like "event.action" or just "action" - string parsed = value.Contains(".") ? value.Split('.')[0].Pascalize() + value.Split('.')[1].Pascalize() : value.Pascalize(); + // incoming action may contain a prefix. if it doesn't, it's a legacy forum event. - Action = (KudosuAction)Enum.Parse(typeof(KudosuAction), parsed); + string[] split = value.Split('.'); + + if (split.Length > 1) + Enum.TryParse(split.First().Replace("_", ""), true, out Source); + else + Source = KudosuSource.Forum; + + Enum.TryParse(split.Last(), true, out Action); } } + } - public KudosuAction Action; + public enum KudosuSource + { + Unknown, + AllowKudosu, + Delete, + DenyKudosu, + Forum, + Recalculate, + Restore, + Vote } public enum KudosuAction { - AllowKudosuGive, - DeleteReset, - DenyKudosuReset, - ForumGive, - ForumReset, - ForumRevoke, - RecalculateGive, - RecalculateReset, - RestoreGive, - VoteGive, - VoteReset, + Give, + Reset, + Revoke, } } diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index 6efe9825ec..d0cfe9fa54 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -51,91 +51,97 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu private void load() { date.Colour = colours.GreySeafoamLighter; - - string prefix = getPrefix(historyItem); - var formattedSource = MessageFormatter.FormatText(getSource(historyItem)); - - if (!string.IsNullOrEmpty(prefix)) - { - linkFlowContainer.AddText(prefix); - linkFlowContainer.AddText($@" {Math.Abs(historyItem.Amount)} kudosu ", t => - { - t.Font = t.Font.With(italics: true); - t.Colour = colours.Blue; - }); - } - + var formattedSource = MessageFormatter.FormatText(getString(historyItem)); linkFlowContainer.AddLinks(formattedSource.Text, formattedSource.Links); - linkFlowContainer.AddText(" "); - linkFlowContainer.AddLink(historyItem.Post.Title, historyItem.Post.Url); } - private string getSource(APIKudosuHistory historyItem) + private string getString(APIKudosuHistory item) { - string userLink() => $"[{historyItem.Giver?.Url} {historyItem.Giver?.Username}]"; + string amount = $"{Math.Abs(item.Amount)} kudosu"; + string post = $"[{item.Post.Title}]({item.Post.Url})"; - switch (historyItem.Action) + switch (item.Source) { - case KudosuAction.VoteGive: - return @"from obtaining votes in modding post of"; + case KudosuSource.AllowKudosu: + switch (item.Action) + { + case KudosuAction.Give: + return $"Received {amount} from kudosu deny repeal of modding post {post}"; + } - case KudosuAction.ForumGive: - return $@"from {userLink()} for a post at"; + break; - case KudosuAction.ForumReset: - return $@"Kudosu reset by {userLink()} for the post"; + case KudosuSource.DenyKudosu: + switch (item.Action) + { + case KudosuAction.Reset: + return $"Denied {amount} from modding post {post}"; + } - case KudosuAction.VoteReset: - return @"from losing votes in modding post of"; + break; - case KudosuAction.DenyKudosuReset: - return @"from modding post"; + case KudosuSource.Delete: + switch (item.Action) + { + case KudosuAction.Reset: + return $"Lost {amount} from modding post deletion of {post}"; + } - case KudosuAction.ForumRevoke: - return $@"Denied kudosu by {userLink()} for the post"; + break; - case KudosuAction.AllowKudosuGive: - return @"from kudosu deny repeal of modding post"; + case KudosuSource.Restore: + switch (item.Action) + { + case KudosuAction.Give: + return $"Received {amount} from modding post restoration of {post}"; + } - case KudosuAction.DeleteReset: - return @"from modding post deletion of"; + break; - case KudosuAction.RestoreGive: - return @"from modding post restoration of"; + case KudosuSource.Vote: + switch (item.Action) + { + case KudosuAction.Give: + return $"Received {amount} from obtaining votes in modding post of {post}"; - case KudosuAction.RecalculateGive: - return @"from votes recalculation in modding post of"; + case KudosuAction.Reset: + return $"Lost {amount} from losing votes in modding post of {post}"; + } - case KudosuAction.RecalculateReset: - return @"from votes recalculation in modding post of"; + break; - default: - return @"from unknown event"; + case KudosuSource.Recalculate: + switch (item.Action) + { + case KudosuAction.Give: + return $"Received {amount} from votes recalculation in modding post of {post}"; + + case KudosuAction.Reset: + return $"Lost {amount} from votes recalculation in modding post of {post}"; + } + + break; + + case KudosuSource.Forum: + + string giver = $"[{item.Giver?.Username}]({item.Giver?.Url})"; + + switch (historyItem.Action) + { + case KudosuAction.Give: + return $"Received {amount} from {giver} for a post at {post}"; + + case KudosuAction.Reset: + return $"Kudosu reset by {giver} for the post {post}"; + + case KudosuAction.Revoke: + return $"Denied kudosu by {giver} for the post {post}"; + } + + break; } - } - private string getPrefix(APIKudosuHistory historyItem) - { - switch (historyItem.Action) - { - case KudosuAction.VoteGive: - case KudosuAction.ForumGive: - case KudosuAction.AllowKudosuGive: - case KudosuAction.RestoreGive: - case KudosuAction.RecalculateGive: - return @"Received"; - - case KudosuAction.DenyKudosuReset: - return @"Denied"; - - case KudosuAction.DeleteReset: - case KudosuAction.VoteReset: - case KudosuAction.RecalculateReset: - return @"Lost"; - - default: - return null; - } + return $"Unknown event ({amount} change)"; } } } From 841da7d69147ce0c1490eae4c500cbd802d1805b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 17:12:32 +0900 Subject: [PATCH 2723/5608] Fix potential null reference on DirectPanel unbind --- osu.Game/Overlays/Direct/DirectPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 641423f21f..a9b6633864 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.Direct private BeatmapSetOverlay beatmapSetOverlay; public PreviewTrack Preview => PlayButton.Preview; - public Bindable PreviewPlaying => PlayButton.Playing; + public Bindable PreviewPlaying => PlayButton?.Playing; protected abstract PlayButton PlayButton { get; } protected abstract Box PreviewBar { get; } From 0c73c5acf3b104ebfe5b13832946be6752c5de1c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 17:14:40 +0900 Subject: [PATCH 2724/5608] Expose full hitobject rather than hit windows --- .../TestSceneDrawableJudgement.cs | 2 +- .../Judgements/OsuJudgementResult.cs | 4 ++-- .../Objects/Drawables/DrawableOsuHitObject.cs | 3 +-- .../Scoring/OsuScoreProcessor.cs | 2 +- .../TestSceneTaikoPlayfield.cs | 8 ++++---- .../Gameplay/TestSceneBarHitErrorMeter.cs | 2 +- .../Rulesets/Judgements/JudgementResult.cs | 19 +++++++++---------- .../Objects/Drawables/DrawableHitObject.cs | 6 ++---- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 5 +++-- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 2 +- 10 files changed, 25 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index 6d240ee009..433ec6bd25 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Tests { foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType().Skip(1)) AddStep("Show " + result.GetDescription(), () => SetContents(() => - new DrawableOsuJudgement(new JudgementResult(null, new HitWindows()) { Type = result }, null) + new DrawableOsuJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs index 367c2c8f14..15444b847b 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs @@ -10,8 +10,8 @@ namespace osu.Game.Rulesets.Osu.Judgements { public ComboResult ComboType; - public OsuJudgementResult(Judgement judgement, HitWindows hitWindows) - : base(judgement, hitWindows) + public OsuJudgementResult(HitObject hitObject, Judgement judgement) + : base(hitObject, judgement) { } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 02b6a932d3..fcd42314fc 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Graphics.Containers; -using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -42,6 +41,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength); - protected override JudgementResult CreateResult(Judgement judgement, HitWindows hitWindows) => new OsuJudgementResult(judgement, hitWindows); + protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(HitObject, judgement); } } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 08dc355bcf..66ef020d09 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Osu.Scoring } } - protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(judgement, null); + protected override JudgementResult CreateResult(HitObject hitObject, Judgement judgement) => new OsuJudgementResult(hitObject, judgement); public override HitWindows CreateHitWindows() => new OsuHitWindows(); } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index 2db1e3e70a..6fd16c213b 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -144,7 +144,7 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement(), new TaikoHitWindows()) { Type = hitResult }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = hitResult }); } private void addStrongHitJudgement(bool kiai) @@ -159,13 +159,13 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement(), new TaikoHitWindows()) { Type = hitResult }); - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new TestStrongNestedHit(h), new JudgementResult(new TaikoStrongJudgement(), new TaikoHitWindows()) { Type = HitResult.Great }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = hitResult }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new TestStrongNestedHit(h), new JudgementResult(new HitObject(), new TaikoStrongJudgement()) { Type = HitResult.Great }); } private void addMissJudgement() { - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new DrawableTestHit(new Hit()), new JudgementResult(new TaikoJudgement(), new TaikoHitWindows()) { Type = HitResult.Miss }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new DrawableTestHit(new Hit()), new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = HitResult.Miss }); } private void addBarLine(bool major, double delay = scroll_time) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs index 0376e775bc..e9c15dab9b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs @@ -106,7 +106,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void newJudgement(double offset = 0) { - var judgement = new JudgementResult(new Judgement(), hitWindows) + var judgement = new JudgementResult(new HitObject(), new Judgement()) { TimeOffset = offset == 0 ? RNG.Next(-150, 150) : offset, Type = HitResult.Perfect, diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs index aea3c9085b..56dc121b17 100644 --- a/osu.Game/Rulesets/Judgements/JudgementResult.cs +++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs @@ -19,16 +19,16 @@ namespace osu.Game.Rulesets.Judgements public HitResult Type; /// - /// The which this applies for. + /// The which was judged. /// - public readonly Judgement Judgement; + [NotNull] + public readonly HitObject HitObject; /// - /// The which the was judged against. - /// May be null to indicate that the timing error should not be displayed to the user. + /// The which this applies for. /// - [CanBeNull] - public readonly HitWindows HitWindows; + [NotNull] + public readonly Judgement Judgement; /// /// The offset from a perfect hit at which this occurred. @@ -64,13 +64,12 @@ namespace osu.Game.Rulesets.Judgements /// /// Creates a new . /// + /// The which was judged. /// The to refer to for scoring information. - /// The which the was judged against. - /// May be null to indicate that the timing error should not be displayed to the user. - public JudgementResult([NotNull] Judgement judgement, [CanBeNull] HitWindows hitWindows) + public JudgementResult([NotNull] HitObject hitObject, [NotNull] Judgement judgement) { + HitObject = hitObject; Judgement = judgement; - HitWindows = hitWindows; } public override string ToString() => $"{Type} (Score:{Judgement.NumericResultFor(this)} HP:{Judgement.HealthIncreaseFor(this)} {Judgement})"; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 4106f8320f..4073bd53ab 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Objects.Drawables if (judgement != null) { - Result = CreateResult(judgement, HitObject.HitWindows); + Result = CreateResult(judgement); if (Result == null) throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); } @@ -401,9 +401,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Creates the that represents the scoring result for this . /// /// The that provides the scoring information. - /// The which the was judged against. - /// May be null to indicate that the timing error should not be displayed to the user. - protected virtual JudgementResult CreateResult(Judgement judgement, HitWindows hitWindows) => new JudgementResult(judgement, hitWindows); + protected virtual JudgementResult CreateResult(Judgement judgement) => new JudgementResult(HitObject, judgement); } public abstract class DrawableHitObject : DrawableHitObject diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 3230551386..86c2c07f2a 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -275,7 +275,7 @@ namespace osu.Game.Rulesets.Scoring if (judgement == null) return; - var result = CreateResult(judgement); + var result = CreateResult(obj, judgement); if (result == null) throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); @@ -441,8 +441,9 @@ namespace osu.Game.Rulesets.Scoring /// /// Creates the that represents the scoring result for a . /// + /// The which was judged. /// The that provides the scoring information. - protected virtual JudgementResult CreateResult(Judgement judgement) => new JudgementResult(judgement, null); + protected virtual JudgementResult CreateResult(HitObject hitObject, Judgement judgement) => new JudgementResult(hitObject, judgement); } public enum ScoringMode diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 3e925a5a50..adda94d629 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -49,7 +49,7 @@ namespace osu.Game.Screens.Play.HUD private void onNewJudgement(JudgementResult result) { - if (result.HitWindows == null) + if (result.HitObject.HitWindows == null) return; foreach (var c in Children) From f6102b4d920ca15ade9af87434ceac6e856d7f9c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 17:15:36 +0900 Subject: [PATCH 2725/5608] Adjust xmldoc --- osu.Game/Rulesets/Objects/HitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index bf04963b76..f0547550e0 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Objects /// /// Creates the for this . - /// This can be null to indicate that the has no . + /// This can be null to indicate that the has no and timing errors should not be displayed to the user. /// /// This will only be invoked if hasn't been set externally (e.g. from a . /// From 4c150839c0de41487da978017ec4d496e1663417 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 17:38:52 +0900 Subject: [PATCH 2726/5608] Fix potential diffcalc hitwindow nullref --- .../Difficulty/ManiaDifficultyCalculator.cs | 7 ++++++- .../Difficulty/OsuDifficultyCalculator.cs | 6 +++++- .../Difficulty/TaikoDifficultyCalculator.cs | 6 +++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index 4a9c22d339..d945abdb04 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -11,7 +11,9 @@ using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Difficulty.Preprocessing; using osu.Game.Rulesets.Mania.Difficulty.Skills; using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mania.Difficulty { @@ -32,12 +34,15 @@ namespace osu.Game.Rulesets.Mania.Difficulty if (beatmap.HitObjects.Count == 0) return new ManiaDifficultyAttributes { Mods = mods, Skills = skills }; + HitWindows hitWindows = new ManiaHitWindows(); + hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); + return new ManiaDifficultyAttributes { StarRating = difficultyValue(skills) * star_scaling_factor, Mods = mods, // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future - GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate, + GreatHitWindow = (int)(hitWindows.Great / 2) / clockRate, Skills = skills }; } diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index c197933233..61e9f60cdd 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; using osu.Game.Rulesets.Osu.Difficulty.Skills; using osu.Game.Rulesets.Osu.Mods; @@ -34,8 +35,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; double starRating = aimRating + speedRating + Math.Abs(aimRating - speedRating) / 2; + HitWindows hitWindows = new OsuHitWindows(); + hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); + // Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be removed in the future - double hitWindowGreat = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate; + double hitWindowGreat = (int)(hitWindows.Great / 2) / clockRate; double preempt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate; int maxCombo = beatmap.HitObjects.Count; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index c8f3e18911..fc93bccb94 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -8,6 +8,7 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing; using osu.Game.Rulesets.Taiko.Difficulty.Skills; using osu.Game.Rulesets.Taiko.Mods; @@ -29,12 +30,15 @@ namespace osu.Game.Rulesets.Taiko.Difficulty if (beatmap.HitObjects.Count == 0) return new TaikoDifficultyAttributes { Mods = mods, Skills = skills }; + HitWindows hitWindows = new TaikoHitWindows(); + hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); + return new TaikoDifficultyAttributes { StarRating = skills.Single().DifficultyValue() * star_scaling_factor, Mods = mods, // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future - GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate, + GreatHitWindow = (int)(hitWindows.Great / 2) / clockRate, MaxCombo = beatmap.HitObjects.Count(h => h is Hit), Skills = skills }; From f20e07136a842f2b23bd52f9a45039757fbcb084 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 17:48:41 +0900 Subject: [PATCH 2727/5608] Add attribute to catch potential future nullrefs --- osu.Game/Rulesets/Objects/HitObject.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index f0547550e0..5e029139d9 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using JetBrains.Annotations; using Newtonsoft.Json; using osu.Game.Audio; using osu.Game.Beatmaps; @@ -56,6 +57,7 @@ namespace osu.Game.Rulesets.Objects /// /// The hit windows for this . /// + [CanBeNull] public HitWindows HitWindows { get; set; } private readonly List nestedHitObjects = new List(); @@ -116,6 +118,7 @@ namespace osu.Game.Rulesets.Objects /// This will only be invoked if hasn't been set externally (e.g. from a . /// /// + [CanBeNull] protected virtual HitWindows CreateHitWindows() => new HitWindows(); } } From 9c53430a0f7ac80f7d9a4786a7b58c0000f4803a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 18:18:59 +0900 Subject: [PATCH 2728/5608] Only initialise when required --- osu.Game/Skinning/SkinnableSound.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index bf647baeec..c402df1bde 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -16,7 +16,7 @@ namespace osu.Game.Skinning { private readonly ISampleInfo[] hitSamples; - private readonly List<(AdjustableProperty, BindableDouble)> adjustments = new List<(AdjustableProperty, BindableDouble)>(); + private List<(AdjustableProperty, BindableDouble)> adjustments; private SampleChannel[] channels; @@ -56,13 +56,15 @@ namespace osu.Game.Skinning public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) { + if (adjustments == null) adjustments = new List<(AdjustableProperty, BindableDouble)>(); + adjustments.Add((type, adjustBindable)); channels?.ForEach(c => c.AddAdjustment(type, adjustBindable)); } public void RemoveAdjustment(AdjustableProperty type, BindableDouble adjustBindable) { - adjustments.Remove((type, adjustBindable)); + adjustments?.Remove((type, adjustBindable)); channels?.ForEach(c => c.RemoveAdjustment(type, adjustBindable)); } @@ -84,8 +86,9 @@ namespace osu.Game.Skinning ch.Looping = looping; ch.Volume.Value = s.Volume / 100.0; - foreach (var adjustment in adjustments) - ch.AddAdjustment(adjustment.Item1, adjustment.Item2); + if (adjustments != null) + foreach (var adjustment in adjustments) + ch.AddAdjustment(adjustment.Item1, adjustment.Item2); } return ch; From f08b523abf9b9296f241dd32b841da15549eb3bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 18:20:30 +0900 Subject: [PATCH 2729/5608] Name tuple items --- osu.Game/Skinning/SkinnableSound.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index c402df1bde..07ffbb8a51 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -16,7 +16,7 @@ namespace osu.Game.Skinning { private readonly ISampleInfo[] hitSamples; - private List<(AdjustableProperty, BindableDouble)> adjustments; + private List<(AdjustableProperty property, BindableDouble bindable)> adjustments; private SampleChannel[] channels; @@ -88,7 +88,7 @@ namespace osu.Game.Skinning if (adjustments != null) foreach (var adjustment in adjustments) - ch.AddAdjustment(adjustment.Item1, adjustment.Item2); + ch.AddAdjustment(adjustment.property, adjustment.bindable); } return ch; From 8302658186b7ff64f63a9c72190d0fa1603d14ad Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 18:31:33 +0900 Subject: [PATCH 2730/5608] Fix other potential nullref cases that rider missed --- .../Objects/Drawables/DrawableHoldNote.cs | 3 +++ .../Objects/Drawables/DrawableNote.cs | 3 +++ .../TestSceneShaking.cs | 7 +++++-- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 8 +++++++- .../Objects/Drawables/DrawableHitCircle.cs | 5 +++++ .../Replays/OsuAutoGenerator.cs | 18 +++++++++--------- .../Replays/OsuAutoGeneratorBase.cs | 10 ++++++++++ .../Objects/Drawables/DrawableHit.cs | 5 +++++ 8 files changed, 47 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index fc3b6885d7..c5c157608f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.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.Diagnostics; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; @@ -209,6 +210,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void CheckForResult(bool userTriggered, double timeOffset) { + Debug.Assert(HitObject.HitWindows != null); + // Factor in the release lenience timeOffset /= release_window_lenience; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index dccff7f6ac..2cd81104a3 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.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.Diagnostics; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -52,6 +53,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void CheckForResult(bool userTriggered, double timeOffset) { + Debug.Assert(HitObject.HitWindows != null); + if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs index 84a73c7cfc..585fdb9cb4 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.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.Diagnostics; using osu.Framework.MathUtils; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; @@ -13,8 +14,10 @@ namespace osu.Game.Rulesets.Osu.Tests { var drawableHitObject = base.CreateDrawableHitCircle(circle, auto); - Scheduler.AddDelayed(() => drawableHitObject.TriggerJudgement(), - drawableHitObject.HitObject.StartTime - (drawableHitObject.HitObject.HitWindows.HalfWindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current); + Debug.Assert(drawableHitObject.HitObject.HitWindows != null); + + double delay = drawableHitObject.HitObject.StartTime - (drawableHitObject.HitObject.HitWindows.HalfWindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current; + Scheduler.AddDelayed(() => drawableHitObject.TriggerJudgement(), delay); return drawableHitObject; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 5625028707..649b01c132 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Types; @@ -38,7 +39,12 @@ namespace osu.Game.Rulesets.Osu.Mods if ((osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime) || osuHit.IsHit) continue; - requiresHit |= osuHit is DrawableHitCircle && osuHit.IsHovered && osuHit.HitObject.HitWindows.CanBeHit(relativetime); + if (osuHit is DrawableHitCircle && osuHit.IsHovered) + { + Debug.Assert(osuHit.HitObject.HitWindows != null); + requiresHit |= osuHit.HitObject.HitWindows.CanBeHit(relativetime); + } + requiresHold |= (osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered)) || osuHit is DrawableSpinner; } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 0af278f6a4..1c40e37262 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -87,6 +88,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForResult(bool userTriggered, double timeOffset) { + Debug.Assert(HitObject.HitWindows != null); + if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) @@ -119,6 +122,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateStateTransforms(ArmedState state) { + Debug.Assert(HitObject.HitWindows != null); + switch (state) { case ArmedState.Idle: diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index 690263c6a0..e1614984de 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -92,20 +92,20 @@ namespace osu.Game.Rulesets.Osu.Replays double endTime = (prev as IHasEndTime)?.EndTime ?? prev.StartTime; // Make the cursor stay at a hitObject as long as possible (mainly for autopilot). - if (h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Miss) > endTime + h.HitWindows.HalfWindowFor(HitResult.Meh) + 50) + if (h.StartTime - HitWindows.HalfWindowFor(HitResult.Miss) > endTime + HitWindows.HalfWindowFor(HitResult.Meh) + 50) { - if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new OsuReplayFrame(endTime + h.HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); - if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Miss), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); + if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new OsuReplayFrame(endTime + HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); + if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - HitWindows.HalfWindowFor(HitResult.Miss), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); } - else if (h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh) > endTime + h.HitWindows.HalfWindowFor(HitResult.Meh) + 50) + else if (h.StartTime - HitWindows.HalfWindowFor(HitResult.Meh) > endTime + HitWindows.HalfWindowFor(HitResult.Meh) + 50) { - if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new OsuReplayFrame(endTime + h.HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); - if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); + if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new OsuReplayFrame(endTime + HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); + if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); } - else if (h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Good) > endTime + h.HitWindows.HalfWindowFor(HitResult.Good) + 50) + else if (h.StartTime - HitWindows.HalfWindowFor(HitResult.Good) > endTime + HitWindows.HalfWindowFor(HitResult.Good) + 50) { - if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new OsuReplayFrame(endTime + h.HitWindows.HalfWindowFor(HitResult.Good), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); - if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Good), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); + if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new OsuReplayFrame(endTime + HitWindows.HalfWindowFor(HitResult.Good), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); + if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - HitWindows.HalfWindowFor(HitResult.Good), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); } } diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs index 9ab358ee12..7c94027c28 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs @@ -6,6 +6,8 @@ using osu.Game.Beatmaps; using System; using System.Collections.Generic; using osu.Game.Replays; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Replays; @@ -27,6 +29,11 @@ namespace osu.Game.Rulesets.Osu.Replays /// protected readonly double FrameDelay; + /// + /// The hit windows. + /// + protected readonly HitWindows HitWindows; + #endregion #region Construction / Initialisation @@ -41,6 +48,9 @@ namespace osu.Game.Rulesets.Osu.Replays // We are using ApplyModsToRate and not ApplyModsToTime to counteract the speed up / slow down from HalfTime / DoubleTime so that we remain at a constant framerate of 60 fps. FrameDelay = ApplyModsToRate(1000.0 / 60.0); + + HitWindows = new OsuHitWindows(); + HitWindows.SetDifficulty(Beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); } #endregion diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index fa45067210..0942b37f58 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; @@ -34,6 +35,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void CheckForResult(bool userTriggered, double timeOffset) { + Debug.Assert(HitObject.HitWindows != null); + if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) @@ -94,6 +97,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void UpdateStateTransforms(ArmedState state) { + Debug.Assert(HitObject.HitWindows != null); + switch (state) { case ArmedState.Idle: From 90671e061715b3c7458e3d2d1f8d32e2bb033ec5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Sep 2019 18:58:13 +0900 Subject: [PATCH 2731/5608] Attempt to not break per-hitobject hitwindows --- .../Replays/OsuAutoGenerator.cs | 53 +++++++++++++++---- .../Replays/OsuAutoGeneratorBase.cs | 8 --- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index e1614984de..e5fa571d4d 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -6,9 +6,11 @@ using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Osu.Objects; using System; +using System.Diagnostics; using System.Linq; using osu.Framework.Graphics; using osu.Game.Replays; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Scoring; @@ -36,6 +38,8 @@ namespace osu.Game.Rulesets.Osu.Replays /// private readonly double reactionTime; + private readonly HitWindows defaultHitWindows; + /// /// What easing to use when moving between hitobjects /// @@ -50,6 +54,9 @@ namespace osu.Game.Rulesets.Osu.Replays { // Already superhuman, but still somewhat realistic reactionTime = ApplyModsToRate(100); + + defaultHitWindows = new OsuHitWindows(); + defaultHitWindows.SetDifficulty(Beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); } #endregion @@ -91,21 +98,49 @@ namespace osu.Game.Rulesets.Osu.Replays { double endTime = (prev as IHasEndTime)?.EndTime ?? prev.StartTime; + HitWindows hitWindows = null; + + switch (h) + { + case HitCircle hitCircle: + hitWindows = hitCircle.HitWindows; + break; + + case Slider slider: + hitWindows = slider.TailCircle.HitWindows; + break; + + case Spinner _: + hitWindows = defaultHitWindows; + break; + } + + Debug.Assert(hitWindows != null); + // Make the cursor stay at a hitObject as long as possible (mainly for autopilot). - if (h.StartTime - HitWindows.HalfWindowFor(HitResult.Miss) > endTime + HitWindows.HalfWindowFor(HitResult.Meh) + 50) + if (h.StartTime - hitWindows.HalfWindowFor(HitResult.Miss) > endTime + hitWindows.HalfWindowFor(HitResult.Meh) + 50) { - if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new OsuReplayFrame(endTime + HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); - if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - HitWindows.HalfWindowFor(HitResult.Miss), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); + if (!(prev is Spinner) && h.StartTime - endTime < 1000) + AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); + + if (!(h is Spinner)) + AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.HalfWindowFor(HitResult.Miss), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); } - else if (h.StartTime - HitWindows.HalfWindowFor(HitResult.Meh) > endTime + HitWindows.HalfWindowFor(HitResult.Meh) + 50) + else if (h.StartTime - hitWindows.HalfWindowFor(HitResult.Meh) > endTime + hitWindows.HalfWindowFor(HitResult.Meh) + 50) { - if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new OsuReplayFrame(endTime + HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); - if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); + if (!(prev is Spinner) && h.StartTime - endTime < 1000) + AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); + + if (!(h is Spinner)) + AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.HalfWindowFor(HitResult.Meh), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); } - else if (h.StartTime - HitWindows.HalfWindowFor(HitResult.Good) > endTime + HitWindows.HalfWindowFor(HitResult.Good) + 50) + else if (h.StartTime - hitWindows.HalfWindowFor(HitResult.Good) > endTime + hitWindows.HalfWindowFor(HitResult.Good) + 50) { - if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new OsuReplayFrame(endTime + HitWindows.HalfWindowFor(HitResult.Good), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); - if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - HitWindows.HalfWindowFor(HitResult.Good), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); + if (!(prev is Spinner) && h.StartTime - endTime < 1000) + AddFrameToReplay(new OsuReplayFrame(endTime + hitWindows.HalfWindowFor(HitResult.Good), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y))); + + if (!(h is Spinner)) + AddFrameToReplay(new OsuReplayFrame(h.StartTime - hitWindows.HalfWindowFor(HitResult.Good), new Vector2(h.StackedPosition.X, h.StackedPosition.Y))); } } diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs index 7c94027c28..3c889d1f52 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs @@ -29,11 +29,6 @@ namespace osu.Game.Rulesets.Osu.Replays ///
    protected readonly double FrameDelay; - /// - /// The hit windows. - /// - protected readonly HitWindows HitWindows; - #endregion #region Construction / Initialisation @@ -48,9 +43,6 @@ namespace osu.Game.Rulesets.Osu.Replays // We are using ApplyModsToRate and not ApplyModsToTime to counteract the speed up / slow down from HalfTime / DoubleTime so that we remain at a constant framerate of 60 fps. FrameDelay = ApplyModsToRate(1000.0 / 60.0); - - HitWindows = new OsuHitWindows(); - HitWindows.SetDifficulty(Beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); } #endregion From 0bfe4650c3da9796c112de5abbca281817ddbccf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 19:01:17 +0900 Subject: [PATCH 2732/5608] Early return if no change occurred in looping value --- osu.Game/Skinning/SkinnableSound.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 07ffbb8a51..8012500280 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -45,6 +45,8 @@ namespace osu.Game.Skinning get => looping; set { + if (value == looping) return; + looping = value; channels?.ForEach(c => c.Looping = looping); From b460f76fa6ad54a9098babe7bef500caa938923e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 19:01:43 +0900 Subject: [PATCH 2733/5608] Adjust file spacing slightly --- osu.Game/Skinning/SkinnableSound.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 8012500280..3d0219ed93 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -54,6 +54,7 @@ namespace osu.Game.Skinning } public void Play() => channels?.ForEach(c => c.Play()); + public void Stop() => channels?.ForEach(c => c.Stop()); public void AddAdjustment(AdjustableProperty type, BindableDouble adjustBindable) From 0ee0184e01c5fd055d20744b998426e8f4d44ecb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Sep 2019 19:13:06 +0900 Subject: [PATCH 2734/5608] Remove unnecessary usings --- osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs index 3c889d1f52..9ab358ee12 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs @@ -6,8 +6,6 @@ using osu.Game.Beatmaps; using System; using System.Collections.Generic; using osu.Game.Replays; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Replays; From 53c254c6a5ca0b59f1471a670beaf81d083f0450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 2 Sep 2019 19:01:36 +0200 Subject: [PATCH 2735/5608] Replace Array.IndexOf() with Contains() --- osu.Game/Graphics/UserInterface/HoverClickSounds.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index 050e5a2835..e64b9259f1 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -1,7 +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.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -36,9 +36,7 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnMouseUp(MouseUpEvent e) { - var index = Array.IndexOf(buttons, e.Button); - bool shouldPlayEffect = index > -1 && index < buttons.Length; - + bool shouldPlayEffect = buttons.Contains(e.Button); // examine the button pressed first for short-circuiting // in most usages it is more likely that another button was pressed than that the cursor left the drawable bounds if (shouldPlayEffect && Contains(e.ScreenSpaceMousePosition)) From 6ca17bdfd5106815ae2bbdd544302bf821679fed Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 2 Sep 2019 10:42:21 -0700 Subject: [PATCH 2736/5608] Center icon and text using anchor and origin instead of margin --- osu.Game/Overlays/Chat/Selection/ChannelListItem.cs | 3 ++- osu.Game/Overlays/Direct/DirectPanel.cs | 3 ++- osu.Game/Overlays/Music/PlaylistItem.cs | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs b/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs index cb0639d85d..31c48deee0 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs @@ -121,10 +121,11 @@ namespace osu.Game.Overlays.Chat.Selection { new SpriteIcon { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, Icon = FontAwesome.Solid.User, Size = new Vector2(text_size - 2), Shadow = false, - Margin = new MarginPadding { Top = 1 }, }, new OsuSpriteText { diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index a9b6633864..6074aa16a5 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -190,10 +190,11 @@ namespace osu.Game.Overlays.Direct text = new OsuSpriteText { Font = OsuFont.GetFont(weight: FontWeight.SemiBold, italics: true) }, new SpriteIcon { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, Icon = icon, Shadow = true, Size = new Vector2(14), - Margin = new MarginPadding { Top = 1 }, }, }; diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index df37a1b2c7..29b6ae00f3 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -161,12 +161,12 @@ namespace osu.Game.Overlays.Music { public PlaylistItemHandle() { - Anchor = Anchor.TopLeft; - Origin = Anchor.TopLeft; + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; Size = new Vector2(12); Icon = FontAwesome.Solid.Bars; Alpha = 0f; - Margin = new MarginPadding { Left = 5, Top = 2 }; + Margin = new MarginPadding { Left = 5 }; } public override bool HandlePositionalInput => IsPresent; From 5d3f3b7cc2376d925e4269de7f982ba7a58d8897 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 2 Sep 2019 10:59:43 -0700 Subject: [PATCH 2737/5608] Add spacing to diff icons on direct panels --- osu.Game/Overlays/Direct/DirectGridPanel.cs | 1 + osu.Game/Overlays/Direct/DirectListPanel.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index 7bf94c1483..2528ccec41 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -151,6 +151,7 @@ namespace osu.Game.Overlays.Direct AutoSizeAxes = Axes.X, Height = 20, Margin = new MarginPadding { Top = vertical_padding, Bottom = vertical_padding }, + Spacing = new Vector2(3), Children = GetDifficultyIcons(colours), }, }, diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index 158ff648dd..b64142dfe7 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -129,6 +129,7 @@ namespace osu.Game.Overlays.Direct AutoSizeAxes = Axes.X, Height = 20, Margin = new MarginPadding { Top = vertical_padding, Bottom = vertical_padding }, + Spacing = new Vector2(3), Children = GetDifficultyIcons(colours), }, }, From ce446826e8f9c87e63b8c9483c2fc057114ab345 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 2 Sep 2019 11:00:12 -0700 Subject: [PATCH 2738/5608] Match web's max diff icon number --- osu.Game/Overlays/Direct/DirectPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index a9b6633864..c911a521b9 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.Direct public readonly BeatmapSetInfo SetInfo; private const double hover_transition_time = 400; - private const int maximum_difficulty_icons = 15; + private const int maximum_difficulty_icons = 10; private Container content; From 3d1f051437650be239c1af83f253ea942248fbd1 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 2 Sep 2019 11:13:34 -0700 Subject: [PATCH 2739/5608] Move hover tests after key tests --- .../Gameplay/TestSceneGameplayMenuOverlay.cs | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs index 4727140d99..0d8a84fa51 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs @@ -56,17 +56,14 @@ namespace osu.Game.Tests.Visual.Gameplay pauseOverlay.Retries = failOverlay.Retries = retryCount; }); - AddToggleStep("Toggle pause overlay", t => pauseOverlay.ToggleVisibility()); - AddToggleStep("Toggle fail overlay", t => failOverlay.ToggleVisibility()); - - testHideResets(); - testEnterWithoutSelection(); testKeyUpFromInitial(); testKeyDownFromInitial(); testKeyUpWrapping(); testKeyDownWrapping(); + testHideResets(); + testMouseSelectionAfterKeySelection(); testKeySelectionAfterMouseSelection(); @@ -76,19 +73,6 @@ namespace osu.Game.Tests.Visual.Gameplay testEnterKeySelection(); } - /// - /// Test that hiding the overlay after hovering a button will reset the overlay to the initial state with no buttons selected. - /// - private void testHideResets() - { - AddStep("Show overlay", () => failOverlay.Show()); - - AddStep("Hover first button", () => InputManager.MoveMouseTo(failOverlay.Buttons.First())); - AddStep("Hide overlay", () => failOverlay.Hide()); - - AddAssert("Overlay state is reset", () => !failOverlay.Buttons.Any(b => b.Selected.Value)); - } - /// /// Tests that pressing enter after an overlay shows doesn't trigger an event because a selection hasn't occurred. /// @@ -162,6 +146,19 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("Hide overlay", () => failOverlay.Hide()); } + /// + /// Test that hiding the overlay after hovering a button will reset the overlay to the initial state with no buttons selected. + /// + private void testHideResets() + { + AddStep("Show overlay", () => failOverlay.Show()); + + AddStep("Hover first button", () => InputManager.MoveMouseTo(failOverlay.Buttons.First())); + AddStep("Hide overlay", () => failOverlay.Hide()); + + AddAssert("Overlay state is reset", () => !failOverlay.Buttons.Any(b => b.Selected.Value)); + } + /// /// Tests that hovering a button that was previously selected with the keyboard correctly selects the new button and deselects the previous button. /// From cb55159b280d19c9376718093e34491c76852d02 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 3 Sep 2019 01:28:51 +0300 Subject: [PATCH 2740/5608] Use float types for cursor sizes --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs | 8 ++++---- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- osu.Game/Graphics/Cursor/MenuCursor.cs | 7 +++---- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 10 +++++----- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index eb1977a13d..f384b1150e 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private bool cursorExpand; - private Bindable cursorScale; + private Bindable cursorScale; private Bindable autoCursorScale; private readonly IBindable beatmap = new Bindable(); @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor this.beatmap.BindTo(beatmap); this.beatmap.ValueChanged += _ => calculateScale(); - cursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); + cursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); cursorScale.ValueChanged += _ => calculateScale(); autoCursorScale = config.GetBindable(OsuSetting.AutoCursorSize); @@ -70,12 +70,12 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private void calculateScale() { - float scale = (float)cursorScale.Value; + float scale = cursorScale.Value; if (autoCursorScale.Value && beatmap.Value != null) { // if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier. - scale *= (float)(1 - 0.7 * (1 + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY); + scale *= 1f - 0.7f * (1f + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY; } scaleTarget.Scale = new Vector2(scale); diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 0cecbb225f..c901a28a59 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -58,8 +58,8 @@ namespace osu.Game.Configuration Set(OsuSetting.AudioOffset, 0, -500.0, 500.0, 1); // Input - Set(OsuSetting.MenuCursorSize, 1.0, 0.5f, 2, 0.01); - Set(OsuSetting.GameplayCursorSize, 1.0, 0.1f, 2, 0.01); + Set(OsuSetting.MenuCursorSize, 1.0f, 0.5f, 2f, 0.01f); + Set(OsuSetting.GameplayCursorSize, 1.0f, 0.1f, 2f, 0.01f); Set(OsuSetting.AutoCursorSize, false); Set(OsuSetting.MouseDisableButtons, false); diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index e103798355..5a83d8e4ce 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -124,7 +124,7 @@ namespace osu.Game.Graphics.Cursor public class Cursor : Container { private Container cursorContainer; - private Bindable cursorScale; + private Bindable cursorScale; private const float base_scale = 0.15f; public Sprite AdditiveLayer; @@ -159,9 +159,8 @@ namespace osu.Game.Graphics.Cursor } }; - cursorScale = config.GetBindable(OsuSetting.MenuCursorSize); - cursorScale.ValueChanged += scale => cursorContainer.Scale = new Vector2((float)scale.NewValue * base_scale); - cursorScale.TriggerChange(); + cursorScale = config.GetBindable(OsuSetting.MenuCursorSize); + cursorScale.BindValueChanged(scale => cursorContainer.Scale = new Vector2(scale.NewValue * base_scale), true); } } diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 35be930a2e..d3029d8ab9 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -35,16 +35,16 @@ namespace osu.Game.Overlays.Settings.Sections Children = new Drawable[] { skinDropdown = new SkinSettingsDropdown(), - new SettingsSlider + new SettingsSlider { LabelText = "Menu cursor size", - Bindable = config.GetBindable(OsuSetting.MenuCursorSize), + Bindable = config.GetBindable(OsuSetting.MenuCursorSize), KeyboardStep = 0.01f }, - new SettingsSlider + new SettingsSlider { LabelText = "Gameplay cursor size", - Bindable = config.GetBindable(OsuSetting.GameplayCursorSize), + Bindable = config.GetBindable(OsuSetting.GameplayCursorSize), KeyboardStep = 0.01f }, new SettingsCheckbox @@ -95,7 +95,7 @@ namespace osu.Game.Overlays.Settings.Sections } } - private class SizeSlider : OsuSliderBar + private class SizeSlider : OsuSliderBar { public override string TooltipText => Current.Value.ToString(@"0.##x"); } From de6dba9716ba720f8756b38662ecc48aa32d148d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Tue, 3 Sep 2019 01:50:52 +0300 Subject: [PATCH 2741/5608] Use float type for chat overlay height --- osu.Game/Configuration/OsuConfigManager.cs | 2 +- osu.Game/Overlays/ChatOverlay.cs | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 0cecbb225f..9246acb00b 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -31,7 +31,7 @@ namespace osu.Game.Configuration Set(OsuSetting.RandomSelectAlgorithm, RandomSelectAlgorithm.RandomPermutation); - Set(OsuSetting.ChatDisplayHeight, ChatOverlay.DEFAULT_HEIGHT, 0.2, 1); + Set(OsuSetting.ChatDisplayHeight, ChatOverlay.DEFAULT_HEIGHT, 0.2f, 1f); // Online settings Set(OsuSetting.Username, string.Empty); diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 53a05656b1..6f848c7627 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -54,7 +54,7 @@ namespace osu.Game.Overlays private Box chatBackground; private Box tabBackground; - public Bindable ChatHeight { get; set; } + public Bindable ChatHeight { get; set; } private Container channelSelectionContainer; protected ChannelSelectionOverlay ChannelSelectionOverlay; @@ -190,14 +190,13 @@ namespace osu.Game.Overlays ChannelSelectionOverlay.OnRequestJoin = channel => channelManager.JoinChannel(channel); ChannelSelectionOverlay.OnRequestLeave = channelManager.LeaveChannel; - ChatHeight = config.GetBindable(OsuSetting.ChatDisplayHeight); - ChatHeight.ValueChanged += height => + ChatHeight = config.GetBindable(OsuSetting.ChatDisplayHeight); + ChatHeight.BindValueChanged(height => { - chatContainer.Height = (float)height.NewValue; - channelSelectionContainer.Height = 1f - (float)height.NewValue; - tabBackground.FadeTo(height.NewValue == 1 ? 1 : 0.8f, 200); - }; - ChatHeight.TriggerChange(); + chatContainer.Height = height.NewValue; + channelSelectionContainer.Height = 1f - height.NewValue; + tabBackground.FadeTo(height.NewValue == 1f ? 1f : 0.8f, 200); + }, true); chatBackground.Colour = colours.ChatBlue; @@ -273,7 +272,7 @@ namespace osu.Game.Overlays } } - private double startDragChatHeight; + private float startDragChatHeight; private bool isDragging; protected override bool OnDragStart(DragStartEvent e) @@ -291,7 +290,7 @@ namespace osu.Game.Overlays { if (isDragging) { - double targetChatHeight = startDragChatHeight - (e.MousePosition.Y - e.MouseDownPosition.Y) / Parent.DrawSize.Y; + float targetChatHeight = startDragChatHeight - (e.MousePosition.Y - e.MouseDownPosition.Y) / Parent.DrawSize.Y; // If the channel selection screen is shown, mind its minimum height if (ChannelSelectionOverlay.State.Value == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height) From 3b769128a82c8f9cb0e588208a7d5f7eee3938d6 Mon Sep 17 00:00:00 2001 From: jorolf Date: Tue, 3 Sep 2019 00:57:29 +0200 Subject: [PATCH 2742/5608] Add a 60bpm beat when no beatmap is playing --- .../TestSceneBeatSyncedContainer.cs | 10 ++- .../Containers/BeatSyncedContainer.cs | 64 +++++++++++++++---- 2 files changed, 62 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index 94228e22f0..d84ffa0d93 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Track; @@ -25,6 +26,11 @@ namespace osu.Game.Tests.Visual.UserInterface { private readonly NowPlayingOverlay np; + public override IReadOnlyList RequiredTypes => new[] + { + typeof(BeatSyncedContainer) + }; + [Cached] private MusicController musicController = new MusicController(); @@ -154,7 +160,9 @@ namespace osu.Game.Tests.Visual.UserInterface if (timingPoints[timingPoints.Count - 1] == current) return current; - return timingPoints[timingPoints.IndexOf(current) + 1]; + int index = timingPoints.IndexOf(current); // -1 means that this is a "default beat" + + return index == -1 ? current : timingPoints[index + 1]; } private int calculateBeatCount(TimingControlPoint current) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 621eeea2b7..f6d950c414 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -33,23 +33,46 @@ namespace osu.Game.Graphics.Containers ///
    public double TimeSinceLastBeat { get; private set; } + /// + /// Default length of a beat in milliseconds. Used whenever there is no beatmap or track playing. + /// + private const double default_beat_length = 60000.0 / 60.0; + + private TimingControlPoint defaultTiming; + private EffectControlPoint defaultEffect; + private TrackAmplitudes defaultAmplitudes; + protected override void Update() { - if (!Beatmap.Value.TrackLoaded || !Beatmap.Value.BeatmapLoaded) return; + Track track = null; + IBeatmap beatmap = null; - var track = Beatmap.Value.Track; - var beatmap = Beatmap.Value.Beatmap; + double currentTrackTime; + TimingControlPoint timingPoint; + EffectControlPoint effectPoint; - if (track == null || beatmap == null) - return; + if (Beatmap.Value.TrackLoaded && Beatmap.Value.BeatmapLoaded) + { + track = Beatmap.Value.Track; + beatmap = Beatmap.Value.Beatmap; + } - double currentTrackTime = track.Length > 0 ? track.CurrentTime + EarlyActivationMilliseconds : Clock.CurrentTime; + if (track != null && beatmap != null && track.IsRunning) + { + currentTrackTime = track.Length > 0 ? track.CurrentTime + EarlyActivationMilliseconds : Clock.CurrentTime; - TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(currentTrackTime); - EffectControlPoint effectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTrackTime); + timingPoint = beatmap.ControlPointInfo.TimingPointAt(currentTrackTime); + effectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTrackTime); - if (timingPoint.BeatLength == 0) - return; + if (timingPoint.BeatLength == 0) + return; + } + else + { + currentTrackTime = Clock.CurrentTime; + timingPoint = defaultTiming; + effectPoint = defaultEffect; + } int beatIndex = (int)((currentTrackTime - timingPoint.Time) / timingPoint.BeatLength); @@ -67,7 +90,7 @@ namespace osu.Game.Graphics.Containers return; using (BeginDelayedSequence(-TimeSinceLastBeat, true)) - OnNewBeat(beatIndex, timingPoint, effectPoint, track.CurrentAmplitudes); + OnNewBeat(beatIndex, timingPoint, effectPoint, track?.CurrentAmplitudes ?? defaultAmplitudes); lastBeat = beatIndex; lastTimingPoint = timingPoint; @@ -77,6 +100,25 @@ namespace osu.Game.Graphics.Containers private void load(IBindable beatmap) { Beatmap.BindTo(beatmap); + defaultTiming = new TimingControlPoint + { + BeatLength = default_beat_length, + AutoGenerated = true, + Time = 0 + }; + defaultEffect = new EffectControlPoint + { + Time = 0, + AutoGenerated = true, + KiaiMode = false, + OmitFirstBarLine = false + }; + defaultAmplitudes = new TrackAmplitudes + { + FrequencyAmplitudes = new float[256], + LeftChannel = 0, + RightChannel = 0 + }; } protected virtual void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) From eab06995d0378d8e984937acd34e3009c9dc0156 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 3 Sep 2019 11:37:56 +0900 Subject: [PATCH 2743/5608] Add some whitespace --- osu.Game/Graphics/Containers/BeatSyncedContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index f6d950c414..370d044ba4 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -100,12 +100,14 @@ namespace osu.Game.Graphics.Containers private void load(IBindable beatmap) { Beatmap.BindTo(beatmap); + defaultTiming = new TimingControlPoint { BeatLength = default_beat_length, AutoGenerated = true, Time = 0 }; + defaultEffect = new EffectControlPoint { Time = 0, @@ -113,6 +115,7 @@ namespace osu.Game.Graphics.Containers KiaiMode = false, OmitFirstBarLine = false }; + defaultAmplitudes = new TrackAmplitudes { FrequencyAmplitudes = new float[256], From 444419b2e6f99fcab6775245a346dd6f6db0c092 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 12:04:49 +0900 Subject: [PATCH 2744/5608] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 93a9a073a4..743508baf8 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -60,7 +60,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 330018d5cb..03207dfdf7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 9f8d82ad1e..ec76ceaf95 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -117,7 +117,7 @@ - + From 11dfdc33d519673df52de4a6e09434d0c83d9634 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2019 03:05:45 +0000 Subject: [PATCH 2745/5608] Bump ppy.osu.Game.Resources from 2019.830.0 to 2019.903.0 Bumps [ppy.osu.Game.Resources](https://github.com/ppy/osu-resources) from 2019.830.0 to 2019.903.0. - [Release notes](https://github.com/ppy/osu-resources/releases) - [Commits](https://github.com/ppy/osu-resources/compare/2019.830.0...2019.903.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 93a9a073a4..743508baf8 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -60,7 +60,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 330018d5cb..03207dfdf7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 9f8d82ad1e..ec76ceaf95 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -117,7 +117,7 @@ - + From 4f3511e8e9637fded836e3f0080b5ba28958ecd8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 12:32:10 +0900 Subject: [PATCH 2746/5608] Fix ring glow lookup being incorrect --- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs index 00188689dd..30937313fd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Texture = textures.Get("ring-glow"), + Texture = textures.Get("Gameplay/osu/ring-glow"), Blending = BlendingParameters.Additive, Alpha = 0.5f }; From 4cad55cee6a73bb010d0838afeecfa63d38b17a2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Sep 2019 13:05:03 +0900 Subject: [PATCH 2747/5608] Move hit windows lookup to DrawableRuleset --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 23 +++++++++++++++++++++++ osu.Game/Screens/Play/HUDOverlay.cs | 5 +---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 0ee9196fb8..a32407d180 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -13,6 +13,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading; +using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Graphics.Cursor; using osu.Framework.Input; @@ -390,6 +391,28 @@ namespace osu.Game.Rulesets.UI ///